From 63660c12199ef55128b4660ad14f5c2b6ef23460 Mon Sep 17 00:00:00 2001 From: Panos Date: Wed, 15 Jan 2025 22:06:25 +0000 Subject: [PATCH 01/46] Removed manylinux 2010 builds and files. Removed manylinux2010 from build script. --- ci/build-manylinux.sh | 1 - ci/docker/manylinux/Dockerfile | 48 ------------------------- ci/docker/manylinux/cmake-3.31.3.tar.xz | 3 -- ci/docker/manylinux/krb5-1.21.3.tar.xz | 3 -- 4 files changed, 55 deletions(-) delete mode 100644 ci/docker/manylinux/Dockerfile delete mode 100644 ci/docker/manylinux/cmake-3.31.3.tar.xz delete mode 100644 ci/docker/manylinux/krb5-1.21.3.tar.xz diff --git a/ci/build-manylinux.sh b/ci/build-manylinux.sh index 0efcf2c2..2affdbd5 100755 --- a/ci/build-manylinux.sh +++ b/ci/build-manylinux.sh @@ -18,7 +18,6 @@ docker_repo="parallelssh/ssh-manylinux" docker_files=( - "ci/docker/manylinux/Dockerfile" "ci/docker/manylinux/Dockerfile.2014_x86_64" # "ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64" # "ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64" diff --git a/ci/docker/manylinux/Dockerfile b/ci/docker/manylinux/Dockerfile deleted file mode 100644 index 94bf1bc1..00000000 --- a/ci/docker/manylinux/Dockerfile +++ /dev/null @@ -1,48 +0,0 @@ -FROM quay.io/pypa/manylinux2010_x86_64 - -ENV OPENSSL openssl-3.4.0 -ENV LIBSSH 0.11.1 -ENV KRB 1.21.3 -ENV CMAKE 3.31.3 -ENV SYSTEM_LIBSSH 1 -ENV CFLAGS "-g0 -s" - -RUN yum install zlib-devel cmake3 perl-IPC-Cmd -y - -ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz -ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz -ADD krb5-${KRB}.tar.xz krb5-${KRB}.tar.xz -ADD cmake-${CMAKE}.tar.xz cmake-${CMAKE}.tar.xz - -RUN tar -xzf ${OPENSSL}.tar.gz - -# Openssl -RUN cd ${OPENSSL} && \ - ./config --prefix=/usr --openssldir=/usr/openssl threads shared && \ - make -j6 && make install_sw - - -# CMake - Krb dependency -RUN cd cmake-${CMAKE}.tar.xz/cmake-${CMAKE} && \ - ./bootstrap --prefix=/usr && \ - make && \ - make install - - -RUN yum remove cmake3 -y - -# Kerberos -RUN cd krb5-${KRB}.tar.xz/krb5-${KRB}/src && \ - ./configure && \ - make -j6 && \ - make install - -# Libssh -RUN mkdir -p build_libssh && cd build_libssh && \ - cmake ../libssh.tar.xz/libssh-${LIBSSH} -DCMAKE_BUILD_TYPE=Release \ - -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF && \ - make -j6 install/strip - -RUN rm -rf ${OPENSSL}* libssh build_libssh krb5-${KRB}.tar.xz cmake-${CMAKE}.tar.xz - -VOLUME /var/cache diff --git a/ci/docker/manylinux/cmake-3.31.3.tar.xz b/ci/docker/manylinux/cmake-3.31.3.tar.xz deleted file mode 100644 index 0378453d..00000000 --- a/ci/docker/manylinux/cmake-3.31.3.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8c978c8f15640b3858fa207226920a6c931d8318f7de6c7a040bfb163e694099 -size 8056928 diff --git a/ci/docker/manylinux/krb5-1.21.3.tar.xz b/ci/docker/manylinux/krb5-1.21.3.tar.xz deleted file mode 100644 index f64c4030..00000000 --- a/ci/docker/manylinux/krb5-1.21.3.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:79f1c69f5f305033f87a88b3f0b48446f3a9476f8207fac2af739082efc47c6b -size 6688044 From 9874cd721d0c8272d35ed03b61df97f54f1f8fd2 Mon Sep 17 00:00:00 2001 From: Panos Date: Thu, 16 Jan 2025 00:24:45 +0000 Subject: [PATCH 02/46] Updated manylinux build script to use embedded libssh. Removed archive files. Updated embedded build script, CI cfgs. --- .circleci/config.yml | 1 + .gitignore | 1 + _setup_libssh.py | 1 + ci/appveyor/build_krb.bat | 9 --------- ci/appveyor/build_ssh.bat | 1 + ci/build-manylinux.sh | 1 + ci/docker/manylinux/Dockerfile.2014_x86_64 | 12 +++++------- ci/docker/manylinux/Dockerfile.aarch64 | 10 ++++------ ci/docker/manylinux/libssh-0.11.1.tar.xz | 3 --- ci/docker/manylinux/libssh-0.11.1.tar.xz.asc | 16 ---------------- 10 files changed, 14 insertions(+), 41 deletions(-) delete mode 100755 ci/appveyor/build_krb.bat delete mode 100644 ci/docker/manylinux/libssh-0.11.1.tar.xz delete mode 100644 ci/docker/manylinux/libssh-0.11.1.tar.xz.asc diff --git a/.circleci/config.yml b/.circleci/config.yml index c4fca4c3..b4bd5062 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -119,6 +119,7 @@ jobs: - run: name: Build Wheels command: | + export LIBSSH_VERSION=0.11.1 if [[ -z "${CIRCLE_PR_NUMBER}" ]]; then echo "$DOCKER_PASSWORD" | docker login -u="$DOCKER_USERNAME" --password-stdin; fi diff --git a/.gitignore b/.gitignore index bd3d616f..0f6d53d4 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ libssh/compile_commands.json /.idea /ci/integration_tests/unit_test_cert_key-cert.pub /doc/_build +ci/docker/manylinux/*.tar.gz \ No newline at end of file diff --git a/_setup_libssh.py b/_setup_libssh.py index fe9c5411..d63e414c 100644 --- a/_setup_libssh.py +++ b/_setup_libssh.py @@ -45,6 +45,7 @@ def build_ssh(): check_call("""cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../local \ -DWITH_GSSAPI=ON \ -DWITH_EXAMPLES=OFF \ + -DUNIT_TESTING=OFF \ ../libssh""", shell=True, env=os.environ) check_call(['make', '-j%s' % (cpu_count(),), 'all', 'install']) diff --git a/ci/appveyor/build_krb.bat b/ci/appveyor/build_krb.bat deleted file mode 100755 index 1f241e14..00000000 --- a/ci/appveyor/build_krb.bat +++ /dev/null @@ -1,9 +0,0 @@ -refreshenv -set KRB_INSTALL_DIR=%APPVEYOR_HOME_DIR%/src/lib -set CPU=AMD64 -setenv /x64 /release -cd kfw-4.1/src -make -f Makefile.in prep-windows -make -make install -cd ../.. diff --git a/ci/appveyor/build_ssh.bat b/ci/appveyor/build_ssh.bat index 50180d7b..aab30d10 100755 --- a/ci/appveyor/build_ssh.bat +++ b/ci/appveyor/build_ssh.bat @@ -10,6 +10,7 @@ cmake ..\libssh ^ -DZLIB_INCLUDE_DIR=C:/zlib/include ^ -DWITH_GSSAPI=ON ^ -DWITH_EXAMPLES=OFF ^ + -DUNIT_TESTING=OFF ^ -DOPENSSL_ROOT_DIR=%OPENSSL_DIR% diff --git a/ci/build-manylinux.sh b/ci/build-manylinux.sh index 2affdbd5..adbca5a1 100755 --- a/ci/build-manylinux.sh +++ b/ci/build-manylinux.sh @@ -15,6 +15,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +tar -czf ci/docker/manylinux/libssh-${LIBSSH_VERSION}.tar.gz libssh docker_repo="parallelssh/ssh-manylinux" docker_files=( diff --git a/ci/docker/manylinux/Dockerfile.2014_x86_64 b/ci/docker/manylinux/Dockerfile.2014_x86_64 index 023a16ba..87d1865a 100644 --- a/ci/docker/manylinux/Dockerfile.2014_x86_64 +++ b/ci/docker/manylinux/Dockerfile.2014_x86_64 @@ -1,16 +1,14 @@ FROM quay.io/pypa/manylinux2014_x86_64 ENV OPENSSL openssl-3.4.0 -ENV LIBSSH 0.11.1 -ENV KRB 1.21.3 +ENV LIBSSH_VERSION 0.11.1 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" RUN yum install zlib-devel cmake3 perl-IPC-Cmd -y -ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz +ADD libssh-${LIBSSH_VERSION}.tar.xz libssh.tar.xz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz -ADD krb5-${KRB}.tar.xz krb5-${KRB}.tar.xz RUN tar -xzf ${OPENSSL}.tar.gz # Openssl @@ -26,10 +24,10 @@ RUN cd krb5-${KRB}.tar.xz/krb5-${KRB}/src && \ # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ - cmake3 ../libssh.tar.xz/libssh-${LIBSSH} -DCMAKE_BUILD_TYPE=Release \ - -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF && \ + cmake3 ../libssh.tar.gz/libssh -DCMAKE_BUILD_TYPE=Release \ + -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF -DUNIT_TESTING=OFF && \ make -j6 install/strip -RUN rm -rf ${OPENSSL}* libssh build_libssh krb5-${KRB}.tar.xz +RUN rm -rf ${OPENSSL}* libssh build_libssh VOLUME /var/cache diff --git a/ci/docker/manylinux/Dockerfile.aarch64 b/ci/docker/manylinux/Dockerfile.aarch64 index 6f123e60..a8aef124 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64 +++ b/ci/docker/manylinux/Dockerfile.aarch64 @@ -1,16 +1,14 @@ FROM quay.io/pypa/manylinux2014_aarch64 ENV OPENSSL openssl-3.4.0 -ENV LIBSSH 0.11.1 -ENV KRB 1.21.3 +ENV LIBSSH_VERSION 0.11.1 ENV SYSTEM_LIBSSH 1 ENV CFLAGS "-g0 -s" RUN yum install epel-release -y && yum install zlib-devel cmake3 perl-IPC-Cmd -y -ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz +ADD libssh-${LIBSSH_VERSION}.tar.xz libssh.tar.gz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz -ADD krb5-${KRB}.tar.xz krb5-${KRB}.tar.xz RUN tar -xzf ${OPENSSL}.tar.gz # Openssl @@ -26,8 +24,8 @@ RUN cd krb5-${KRB}.tar.xz/krb5-${KRB}/src && \ # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ - cmake3 ../libssh.tar.xz/libssh-${LIBSSH} -DCMAKE_BUILD_TYPE=Release \ - -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF && \ + cmake3 ../libssh.tar.gz/libssh -DCMAKE_BUILD_TYPE=Release \ + -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF -DUNIT_TESTING=OFF && \ make -j6 install/strip RUN rm -rf ${OPENSSL}* libssh build_libssh krb5-${KRB}.tar.xz diff --git a/ci/docker/manylinux/libssh-0.11.1.tar.xz b/ci/docker/manylinux/libssh-0.11.1.tar.xz deleted file mode 100644 index d76ccb87..00000000 --- a/ci/docker/manylinux/libssh-0.11.1.tar.xz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:14b7dcc72e91e08151c58b981a7b570ab2663f630e7d2837645d5a9c612c1b79 -size 621108 diff --git a/ci/docker/manylinux/libssh-0.11.1.tar.xz.asc b/ci/docker/manylinux/libssh-0.11.1.tar.xz.asc deleted file mode 100644 index 3969e708..00000000 --- a/ci/docker/manylinux/libssh-0.11.1.tar.xz.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCAAdFiEEiKIo2JsHwsd9DHgJA9XfjP3T6OcFAmbRl74ACgkQA9XfjP3T -6OdnSw/+IrXAbSSpjVNG5Wjz3WQjqXkWInCT+qNhcS5w+qasGW5i6mktoNJkg2Fd -P4iRCeJEuZbOHZLWXdUaDKjmlOUIda2xA8U01uw2VrleEu05JV/s5tS1MpVOPfDi -8+CTxPesFQ9uX9q+OojTr4QXqBDqv15sldwRVTKegNpLkk3xHUUaMjwikWKKxXG+ -ypD4UCJWKVVhen9HPRSUOtruliZFPxQSLYvj4XKJxpr/QVaORS0EsTpdYP0h1+18 -6epynp4e1/9GRTmrKa8/JcCd/4c2UnHBFpw0DU1YirLK+54/qD76o63MTbo7mKru -cgfypfA/sdeklGTZYLrCyizcrSc2poaTznczUZC6gi3FxivLoldFyDgXeSQWEieB -QTGgnaLkB2Y2XuBl9F9MatqFC35TBuUUwHBoEa31acQhmotui5tF4oq/JxRtZi8v -OyrTYc/xfmDh4SbWuEVqr6B2SZjhxrIvEGEe4adJQ/tVN2wweoNgTHt8XjBb1amB -M9RPeXG5Uon+gIXDVzjgx+DZ85FweCEngv+OdjHPIBWsJUEc722L/gypIFnBfaPV -JgM84wxQz2J8xyk2zEANog9M8ae5jG9TVJORO8to+gbRlKB2ZRDdDne0cgRUSWaj -0IKsnehsxjF2OqChjRqRMBhfVAA0hrYU1ngxwCcdAcdlbfgs5L0= -=P/pw ------END PGP SIGNATURE----- From 2b5fdb3185a52b2659451fe490803494edb7e22f Mon Sep 17 00:00:00 2001 From: Panos Date: Thu, 16 Jan 2025 00:25:02 +0000 Subject: [PATCH 03/46] Cleanup appveyor cfg --- .appveyor.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 9591c725..08aea5a8 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -61,10 +61,6 @@ install: - "%PYTHON_DEF%\\python.exe ci/appveyor/fix_version.py ." - mv -f .git .git.bak - 7z x ci\appveyor\zlib1211.zip - # - appveyor DownloadFile http://web.mit.edu/kerberos/dist/kfw/4.1/kfw-4.1-amd64.msi - # - msiexec /i kfw-4.1-amd64.msi /passive /qn - # - ps: ls "C:\Program Files\MIT\Kerberos\" - # - cp "C:\Program Files\MIT\Kerberos\*.dll" ssh/ - ps: ls ssh/*.dll - ps: ls ssh - ps: ls From ac0aea1283e900f1667418811618e0e5de858a0a Mon Sep 17 00:00:00 2001 From: Panos Date: Thu, 16 Jan 2025 23:46:39 +0000 Subject: [PATCH 04/46] Updated CI cfg --- .circleci/config.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b4bd5062..e2b262b5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -80,7 +80,7 @@ jobs: - run: name: deps command: | - brew install cmake git-lfs krb5 python libssh + brew install cmake python libssh brew link --force openssl brew link --force libssh pip3 install twine @@ -101,13 +101,6 @@ jobs: image: ubuntu-2004:current steps: &manylinux-steps - checkout - - run: - name: Git LFS - command: | - curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash - sudo apt-get install git-lfs - git lfs install - git lfs pull - run: name: Deps command: | From 3c1c412d65964df3bbc7c885f21f4c62fffe17c3 Mon Sep 17 00:00:00 2001 From: Panos Date: Thu, 16 Jan 2025 23:47:07 +0000 Subject: [PATCH 05/46] Updated appveyor cfg --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 08aea5a8..f2b4b076 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -32,7 +32,7 @@ environment: PYTHON_DEF: "C:\\Python38-x64" PYTHON_VERSION: "3.8" # Python versions to build wheels for - PYTHONVERS: C:\Python38-x64 C:\Python39-x64 C:\Python310-x64 C:\Python311-x64 C:\Python312-x64 + PYTHONVERS: C:\Python36-x64 C:\Python37-x64 C:\Python38-x64 C:\Python39-x64 C:\Python310-x64 C:\Python311-x64 C:\Python312-x64 PYTHON_ARCH: "64" install: From 367d6248a4b6dd62b54472be46e7fd8f1577bccd Mon Sep 17 00:00:00 2001 From: Panos Date: Fri, 17 Jan 2025 00:02:29 +0000 Subject: [PATCH 06/46] Updated dockerfiles --- ci/docker/manylinux/Dockerfile.2014_x86_64 | 15 +++++---------- ci/docker/manylinux/Dockerfile.aarch64 | 13 ++++--------- ci/docker/manylinux/Dockerfile.aarch64_2_24 | 5 ----- ci/docker/manylinux/Dockerfile.aarch64_2_28 | 5 ----- .../manylinux/Dockerfile.manylinux_2_24_x86_64 | 5 ----- .../manylinux/Dockerfile.manylinux_2_28_x86_64 | 5 ----- 6 files changed, 9 insertions(+), 39 deletions(-) diff --git a/ci/docker/manylinux/Dockerfile.2014_x86_64 b/ci/docker/manylinux/Dockerfile.2014_x86_64 index 87d1865a..cbedbda1 100644 --- a/ci/docker/manylinux/Dockerfile.2014_x86_64 +++ b/ci/docker/manylinux/Dockerfile.2014_x86_64 @@ -1,13 +1,13 @@ FROM quay.io/pypa/manylinux2014_x86_64 -ENV OPENSSL openssl-3.4.0 -ENV LIBSSH_VERSION 0.11.1 -ENV SYSTEM_LIBSSH 1 -ENV CFLAGS "-g0 -s" +ENV OPENSSL=openssl-3.4.0 +ENV LIBSSH_VERSION=0.11.1 +ENV SYSTEM_LIBSSH=1 +ENV CFLAGS="-g0 -s" RUN yum install zlib-devel cmake3 perl-IPC-Cmd -y -ADD libssh-${LIBSSH_VERSION}.tar.xz libssh.tar.xz +ADD libssh-${LIBSSH_VERSION}.tar.gz libssh.tar.gz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz RUN tar -xzf ${OPENSSL}.tar.gz @@ -16,11 +16,6 @@ RUN cd ${OPENSSL} && \ ./config --prefix=/usr --openssldir=/usr/openssl threads shared && \ make -j6 && make install_sw -# Kerberos -RUN cd krb5-${KRB}.tar.xz/krb5-${KRB}/src && \ - ./configure && \ - make -j6 && \ - make install # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ diff --git a/ci/docker/manylinux/Dockerfile.aarch64 b/ci/docker/manylinux/Dockerfile.aarch64 index a8aef124..ea3b637c 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64 +++ b/ci/docker/manylinux/Dockerfile.aarch64 @@ -1,9 +1,9 @@ FROM quay.io/pypa/manylinux2014_aarch64 -ENV OPENSSL openssl-3.4.0 -ENV LIBSSH_VERSION 0.11.1 -ENV SYSTEM_LIBSSH 1 -ENV CFLAGS "-g0 -s" +ENV OPENSSL=openssl-3.4.0 +ENV LIBSSH_VERSION=0.11.1 +ENV SYSTEM_LIBSSH=1 +ENV CFLAGS="-g0 -s" RUN yum install epel-release -y && yum install zlib-devel cmake3 perl-IPC-Cmd -y @@ -16,11 +16,6 @@ RUN cd ${OPENSSL} && \ ./config --prefix=/usr --openssldir=/usr/openssl threads shared && \ make -j6 && make install_sw -# Kerberos -RUN cd krb5-${KRB}.tar.xz/krb5-${KRB}/src && \ - ./configure && \ - make -j6 && \ - make install # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ diff --git a/ci/docker/manylinux/Dockerfile.aarch64_2_24 b/ci/docker/manylinux/Dockerfile.aarch64_2_24 index 98c48841..68025e38 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64_2_24 +++ b/ci/docker/manylinux/Dockerfile.aarch64_2_24 @@ -19,11 +19,6 @@ RUN cd ${OPENSSL} && \ ./config --prefix=/usr --openssldir=/usr/openssl threads shared && \ make -j6 && make install_sw -# Kerberos -RUN cd krb5-${KRB}.tar.xz/krb5-${KRB}/src && \ - ./configure && \ - make -j6 && \ - make install # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ diff --git a/ci/docker/manylinux/Dockerfile.aarch64_2_28 b/ci/docker/manylinux/Dockerfile.aarch64_2_28 index 84977056..870fbafc 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64_2_28 +++ b/ci/docker/manylinux/Dockerfile.aarch64_2_28 @@ -19,11 +19,6 @@ RUN cd ${OPENSSL} && \ ./config --prefix=/usr --openssldir=/usr/openssl threads shared && \ make -j6 && make install_sw -# Kerberos -RUN cd krb5-${KRB}.tar.xz/krb5-${KRB}/src && \ - ./configure && \ - make -j6 && \ - make install # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 index 1342fbeb..3a9c555f 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 @@ -19,11 +19,6 @@ RUN cd ${OPENSSL} && \ ./config --prefix=/usr --openssldir=/usr/openssl threads shared && \ make -j6 && make install_sw -# Kerberos -RUN cd krb5-${KRB}.tar.xz/krb5-${KRB}/src && \ - ./configure && \ - make -j6 && \ - make install # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 index 83aa2683..533d146b 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 @@ -19,11 +19,6 @@ RUN cd ${OPENSSL} && \ ./config --prefix=/usr --openssldir=/usr/openssl threads shared && \ make -j6 && make install_sw -# Kerberos -RUN cd krb5-${KRB}.tar.xz/krb5-${KRB}/src && \ - ./configure && \ - make -j6 && \ - make install # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ From a0efa66be1a1bc248fe58543139f7ca3e651b9a9 Mon Sep 17 00:00:00 2001 From: Panos Date: Wed, 22 Jan 2025 15:26:50 +0000 Subject: [PATCH 07/46] Updated CI cfg --- .circleci/config.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e2b262b5..14e34f8f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -151,10 +151,10 @@ workflows: - manylinux-x86_64: &manylinux-wf context: Docker filters: - tags: - only: /.*/ - branches: - ignore: /.*/ +# tags: +# only: /.*/ +# branches: +# ignore: /.*/ - manylinux-aarch64: *manylinux-wf - osx: matrix: @@ -164,8 +164,8 @@ workflows: - "15.0.0" - "16.0.0" context: Docker - filters: - tags: - only: /.*/ - branches: - ignore: /.*/ +# filters: +# tags: +# only: /.*/ +# branches: +# ignore: /.*/ From f2b008129a7e156b9a431dcc10c912a77d99cb0b Mon Sep 17 00:00:00 2001 From: Panos Date: Wed, 22 Jan 2025 15:29:03 +0000 Subject: [PATCH 08/46] Updated CI cfg --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 14e34f8f..c515ed82 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -150,7 +150,7 @@ workflows: ignore: /.*/ - manylinux-x86_64: &manylinux-wf context: Docker - filters: +# filters: # tags: # only: /.*/ # branches: From 67d6ba5124975d51a2426d1090e4c22ae6fb01a8 Mon Sep 17 00:00:00 2001 From: Panos Date: Wed, 22 Jan 2025 15:34:03 +0000 Subject: [PATCH 09/46] Removed zlib archive, added source. --- .appveyor.yml | 1 - ci/appveyor/zlib1211.zip | 3 - zlib-1.2.11/CMakeLists.txt | 249 ++ zlib-1.2.11/ChangeLog | 1515 ++++++++++++ zlib-1.2.11/FAQ | 368 +++ zlib-1.2.11/INDEX | 68 + zlib-1.2.11/Makefile | 5 + zlib-1.2.11/Makefile.in | 410 ++++ zlib-1.2.11/README | 115 + zlib-1.2.11/adler32.c | 186 ++ zlib-1.2.11/amiga/Makefile.pup | 69 + zlib-1.2.11/amiga/Makefile.sas | 68 + zlib-1.2.11/compress.c | 86 + zlib-1.2.11/configure | 921 +++++++ zlib-1.2.11/contrib/README.contrib | 78 + zlib-1.2.11/contrib/ada/buffer_demo.adb | 106 + zlib-1.2.11/contrib/ada/mtest.adb | 156 ++ zlib-1.2.11/contrib/ada/read.adb | 156 ++ zlib-1.2.11/contrib/ada/readme.txt | 65 + zlib-1.2.11/contrib/ada/test.adb | 463 ++++ zlib-1.2.11/contrib/ada/zlib-streams.adb | 225 ++ zlib-1.2.11/contrib/ada/zlib-streams.ads | 114 + zlib-1.2.11/contrib/ada/zlib-thin.adb | 141 ++ zlib-1.2.11/contrib/ada/zlib-thin.ads | 450 ++++ zlib-1.2.11/contrib/ada/zlib.adb | 701 ++++++ zlib-1.2.11/contrib/ada/zlib.ads | 328 +++ zlib-1.2.11/contrib/ada/zlib.gpr | 20 + zlib-1.2.11/contrib/amd64/amd64-match.S | 452 ++++ zlib-1.2.11/contrib/asm686/README.686 | 51 + zlib-1.2.11/contrib/asm686/match.S | 357 +++ zlib-1.2.11/contrib/blast/Makefile | 8 + zlib-1.2.11/contrib/blast/README | 4 + zlib-1.2.11/contrib/blast/blast.c | 466 ++++ zlib-1.2.11/contrib/blast/blast.h | 83 + zlib-1.2.11/contrib/blast/test.pk | Bin 0 -> 8 bytes zlib-1.2.11/contrib/blast/test.txt | 1 + zlib-1.2.11/contrib/delphi/ZLib.pas | 557 +++++ zlib-1.2.11/contrib/delphi/ZLibConst.pas | 11 + zlib-1.2.11/contrib/delphi/readme.txt | 76 + zlib-1.2.11/contrib/delphi/zlibd32.mak | 99 + zlib-1.2.11/contrib/dotzlib/DotZLib.build | 33 + zlib-1.2.11/contrib/dotzlib/DotZLib.chm | Bin 0 -> 72726 bytes zlib-1.2.11/contrib/dotzlib/DotZLib.sln | 21 + .../contrib/dotzlib/DotZLib/AssemblyInfo.cs | 58 + .../contrib/dotzlib/DotZLib/ChecksumImpl.cs | 202 ++ .../contrib/dotzlib/DotZLib/CircularBuffer.cs | 83 + .../contrib/dotzlib/DotZLib/CodecBase.cs | 198 ++ .../contrib/dotzlib/DotZLib/Deflater.cs | 106 + .../contrib/dotzlib/DotZLib/DotZLib.cs | 288 +++ .../contrib/dotzlib/DotZLib/DotZLib.csproj | 141 ++ .../contrib/dotzlib/DotZLib/GZipStream.cs | 301 +++ .../contrib/dotzlib/DotZLib/Inflater.cs | 105 + .../contrib/dotzlib/DotZLib/UnitTests.cs | 274 +++ zlib-1.2.11/contrib/dotzlib/LICENSE_1_0.txt | 23 + zlib-1.2.11/contrib/dotzlib/readme.txt | 58 + zlib-1.2.11/contrib/gcc_gvmat64/gvmat64.S | 574 +++++ zlib-1.2.11/contrib/infback9/README | 1 + zlib-1.2.11/contrib/infback9/infback9.c | 615 +++++ zlib-1.2.11/contrib/infback9/infback9.h | 37 + zlib-1.2.11/contrib/infback9/inffix9.h | 107 + zlib-1.2.11/contrib/infback9/inflate9.h | 47 + zlib-1.2.11/contrib/infback9/inftree9.c | 324 +++ zlib-1.2.11/contrib/infback9/inftree9.h | 61 + zlib-1.2.11/contrib/inflate86/inffas86.c | 1157 +++++++++ zlib-1.2.11/contrib/inflate86/inffast.S | 1368 +++++++++++ zlib-1.2.11/contrib/iostream/test.cpp | 24 + zlib-1.2.11/contrib/iostream/zfstream.cpp | 329 +++ zlib-1.2.11/contrib/iostream/zfstream.h | 128 + zlib-1.2.11/contrib/iostream2/zstream.h | 307 +++ .../contrib/iostream2/zstream_test.cpp | 25 + zlib-1.2.11/contrib/iostream3/README | 35 + zlib-1.2.11/contrib/iostream3/TODO | 17 + zlib-1.2.11/contrib/iostream3/test.cc | 50 + zlib-1.2.11/contrib/iostream3/zfstream.cc | 479 ++++ zlib-1.2.11/contrib/iostream3/zfstream.h | 466 ++++ zlib-1.2.11/contrib/masmx64/bld_ml64.bat | 2 + zlib-1.2.11/contrib/masmx64/gvmat64.asm | 553 +++++ zlib-1.2.11/contrib/masmx64/inffas8664.c | 186 ++ zlib-1.2.11/contrib/masmx64/inffasx64.asm | 396 +++ zlib-1.2.11/contrib/masmx64/readme.txt | 31 + zlib-1.2.11/contrib/masmx86/bld_ml32.bat | 2 + zlib-1.2.11/contrib/masmx86/inffas32.asm | 1080 ++++++++ zlib-1.2.11/contrib/masmx86/match686.asm | 479 ++++ zlib-1.2.11/contrib/masmx86/readme.txt | 27 + zlib-1.2.11/contrib/minizip/Makefile | 25 + zlib-1.2.11/contrib/minizip/Makefile.am | 45 + .../contrib/minizip/MiniZip64_Changes.txt | 6 + .../contrib/minizip/MiniZip64_info.txt | 74 + zlib-1.2.11/contrib/minizip/configure.ac | 32 + zlib-1.2.11/contrib/minizip/crypt.h | 131 + zlib-1.2.11/contrib/minizip/ioapi.c | 247 ++ zlib-1.2.11/contrib/minizip/ioapi.h | 208 ++ zlib-1.2.11/contrib/minizip/iowin32.c | 462 ++++ zlib-1.2.11/contrib/minizip/iowin32.h | 28 + zlib-1.2.11/contrib/minizip/make_vms.com | 25 + zlib-1.2.11/contrib/minizip/miniunz.c | 660 +++++ zlib-1.2.11/contrib/minizip/miniunzip.1 | 63 + zlib-1.2.11/contrib/minizip/minizip.1 | 46 + zlib-1.2.11/contrib/minizip/minizip.c | 520 ++++ zlib-1.2.11/contrib/minizip/minizip.pc.in | 12 + zlib-1.2.11/contrib/minizip/mztools.c | 291 +++ zlib-1.2.11/contrib/minizip/mztools.h | 37 + zlib-1.2.11/contrib/minizip/unzip.c | 2125 ++++++++++++++++ zlib-1.2.11/contrib/minizip/unzip.h | 437 ++++ zlib-1.2.11/contrib/minizip/zip.c | 2007 +++++++++++++++ zlib-1.2.11/contrib/minizip/zip.h | 362 +++ zlib-1.2.11/contrib/pascal/example.pas | 599 +++++ zlib-1.2.11/contrib/pascal/readme.txt | 76 + zlib-1.2.11/contrib/pascal/zlibd32.mak | 99 + zlib-1.2.11/contrib/pascal/zlibpas.pas | 276 +++ zlib-1.2.11/contrib/puff/Makefile | 42 + zlib-1.2.11/contrib/puff/README | 63 + zlib-1.2.11/contrib/puff/puff.c | 840 +++++++ zlib-1.2.11/contrib/puff/puff.h | 35 + zlib-1.2.11/contrib/puff/pufftest.c | 165 ++ zlib-1.2.11/contrib/puff/zeros.raw | Bin 0 -> 2517 bytes zlib-1.2.11/contrib/testzlib/testzlib.c | 275 +++ zlib-1.2.11/contrib/testzlib/testzlib.txt | 10 + zlib-1.2.11/contrib/untgz/Makefile | 14 + zlib-1.2.11/contrib/untgz/Makefile.msc | 17 + zlib-1.2.11/contrib/untgz/untgz.c | 674 +++++ zlib-1.2.11/contrib/vstudio/readme.txt | 78 + .../contrib/vstudio/vc10/miniunz.vcxproj | 310 +++ .../vstudio/vc10/miniunz.vcxproj.filters | 22 + .../contrib/vstudio/vc10/minizip.vcxproj | 307 +++ .../vstudio/vc10/minizip.vcxproj.filters | 22 + .../contrib/vstudio/vc10/testzlib.vcxproj | 420 ++++ .../vstudio/vc10/testzlib.vcxproj.filters | 58 + .../contrib/vstudio/vc10/testzlibdll.vcxproj | 310 +++ .../vstudio/vc10/testzlibdll.vcxproj.filters | 22 + zlib-1.2.11/contrib/vstudio/vc10/zlib.rc | 32 + .../contrib/vstudio/vc10/zlibstat.vcxproj | 473 ++++ .../vstudio/vc10/zlibstat.vcxproj.filters | 77 + zlib-1.2.11/contrib/vstudio/vc10/zlibvc.def | 153 ++ zlib-1.2.11/contrib/vstudio/vc10/zlibvc.sln | 135 + .../contrib/vstudio/vc10/zlibvc.vcxproj | 657 +++++ .../vstudio/vc10/zlibvc.vcxproj.filters | 118 + .../contrib/vstudio/vc11/miniunz.vcxproj | 314 +++ .../contrib/vstudio/vc11/minizip.vcxproj | 311 +++ .../contrib/vstudio/vc11/testzlib.vcxproj | 426 ++++ .../contrib/vstudio/vc11/testzlibdll.vcxproj | 314 +++ zlib-1.2.11/contrib/vstudio/vc11/zlib.rc | 32 + .../contrib/vstudio/vc11/zlibstat.vcxproj | 464 ++++ zlib-1.2.11/contrib/vstudio/vc11/zlibvc.def | 153 ++ zlib-1.2.11/contrib/vstudio/vc11/zlibvc.sln | 117 + .../contrib/vstudio/vc11/zlibvc.vcxproj | 688 ++++++ .../contrib/vstudio/vc12/miniunz.vcxproj | 316 +++ .../contrib/vstudio/vc12/minizip.vcxproj | 313 +++ .../contrib/vstudio/vc12/testzlib.vcxproj | 430 ++++ .../contrib/vstudio/vc12/testzlibdll.vcxproj | 316 +++ zlib-1.2.11/contrib/vstudio/vc12/zlib.rc | 32 + .../contrib/vstudio/vc12/zlibstat.vcxproj | 467 ++++ zlib-1.2.11/contrib/vstudio/vc12/zlibvc.def | 153 ++ zlib-1.2.11/contrib/vstudio/vc12/zlibvc.sln | 119 + .../contrib/vstudio/vc12/zlibvc.vcxproj | 692 ++++++ .../contrib/vstudio/vc14/miniunz.vcxproj | 316 +++ .../contrib/vstudio/vc14/minizip.vcxproj | 313 +++ .../contrib/vstudio/vc14/testzlib.vcxproj | 430 ++++ .../contrib/vstudio/vc14/testzlibdll.vcxproj | 316 +++ zlib-1.2.11/contrib/vstudio/vc14/zlib.rc | 32 + .../contrib/vstudio/vc14/zlibstat.vcxproj | 467 ++++ zlib-1.2.11/contrib/vstudio/vc14/zlibvc.def | 153 ++ zlib-1.2.11/contrib/vstudio/vc14/zlibvc.sln | 119 + .../contrib/vstudio/vc14/zlibvc.vcxproj | 692 ++++++ .../contrib/vstudio/vc9/miniunz.vcproj | 565 +++++ .../contrib/vstudio/vc9/minizip.vcproj | 562 +++++ .../contrib/vstudio/vc9/testzlib.vcproj | 852 +++++++ .../contrib/vstudio/vc9/testzlibdll.vcproj | 565 +++++ zlib-1.2.11/contrib/vstudio/vc9/zlib.rc | 32 + .../contrib/vstudio/vc9/zlibstat.vcproj | 835 +++++++ zlib-1.2.11/contrib/vstudio/vc9/zlibvc.def | 153 ++ zlib-1.2.11/contrib/vstudio/vc9/zlibvc.sln | 144 ++ zlib-1.2.11/contrib/vstudio/vc9/zlibvc.vcproj | 1156 +++++++++ zlib-1.2.11/crc32.c | 442 ++++ zlib-1.2.11/crc32.h | 441 ++++ zlib-1.2.11/deflate.c | 2163 +++++++++++++++++ zlib-1.2.11/deflate.h | 349 +++ zlib-1.2.11/doc/algorithm.txt | 209 ++ zlib-1.2.11/doc/rfc1950.txt | 619 +++++ zlib-1.2.11/doc/rfc1951.txt | 955 ++++++++ zlib-1.2.11/doc/rfc1952.txt | 675 +++++ zlib-1.2.11/doc/txtvsbin.txt | 107 + zlib-1.2.11/examples/README.examples | 49 + zlib-1.2.11/examples/enough.c | 572 +++++ zlib-1.2.11/examples/fitblk.c | 233 ++ zlib-1.2.11/examples/gun.c | 702 ++++++ zlib-1.2.11/examples/gzappend.c | 504 ++++ zlib-1.2.11/examples/gzjoin.c | 449 ++++ zlib-1.2.11/examples/gzlog.c | 1059 ++++++++ zlib-1.2.11/examples/gzlog.h | 91 + zlib-1.2.11/examples/zlib_how.html | 545 +++++ zlib-1.2.11/examples/zpipe.c | 205 ++ zlib-1.2.11/examples/zran.c | 409 ++++ zlib-1.2.11/gzclose.c | 25 + zlib-1.2.11/gzguts.h | 218 ++ zlib-1.2.11/gzlib.c | 637 +++++ zlib-1.2.11/gzread.c | 654 +++++ zlib-1.2.11/gzwrite.c | 665 +++++ zlib-1.2.11/infback.c | 640 +++++ zlib-1.2.11/inffast.c | 323 +++ zlib-1.2.11/inffast.h | 11 + zlib-1.2.11/inffixed.h | 94 + zlib-1.2.11/inflate.c | 1561 ++++++++++++ zlib-1.2.11/inflate.h | 125 + zlib-1.2.11/inftrees.c | 304 +++ zlib-1.2.11/inftrees.h | 62 + zlib-1.2.11/make_vms.com | 867 +++++++ zlib-1.2.11/msdos/Makefile.bor | 115 + zlib-1.2.11/msdos/Makefile.dj2 | 104 + zlib-1.2.11/msdos/Makefile.emx | 69 + zlib-1.2.11/msdos/Makefile.msc | 112 + zlib-1.2.11/msdos/Makefile.tc | 100 + zlib-1.2.11/nintendods/Makefile | 126 + zlib-1.2.11/nintendods/README | 5 + zlib-1.2.11/old/Makefile.emx | 69 + zlib-1.2.11/old/Makefile.riscos | 151 ++ zlib-1.2.11/old/README | 3 + zlib-1.2.11/old/descrip.mms | 48 + zlib-1.2.11/old/os2/Makefile.os2 | 136 ++ zlib-1.2.11/old/os2/zlib.def | 51 + zlib-1.2.11/old/visual-basic.txt | 160 ++ zlib-1.2.11/os400/README400 | 48 + zlib-1.2.11/os400/bndsrc | 119 + zlib-1.2.11/os400/make.sh | 366 +++ zlib-1.2.11/os400/zlib.inc | 527 ++++ zlib-1.2.11/qnx/package.qpg | 141 ++ zlib-1.2.11/test/example.c | 602 +++++ zlib-1.2.11/test/infcover.c | 671 +++++ zlib-1.2.11/test/minigzip.c | 651 +++++ zlib-1.2.11/treebuild.xml | 116 + zlib-1.2.11/trees.c | 1203 +++++++++ zlib-1.2.11/trees.h | 128 + zlib-1.2.11/uncompr.c | 93 + zlib-1.2.11/watcom/watcom_f.mak | 43 + zlib-1.2.11/watcom/watcom_l.mak | 43 + zlib-1.2.11/win32/DLL_FAQ.txt | 397 +++ zlib-1.2.11/win32/Makefile.bor | 110 + zlib-1.2.11/win32/Makefile.gcc | 182 ++ zlib-1.2.11/win32/Makefile.msc | 163 ++ zlib-1.2.11/win32/README-WIN32.txt | 103 + zlib-1.2.11/win32/VisualC.txt | 3 + zlib-1.2.11/win32/zlib.def | 94 + zlib-1.2.11/win32/zlib1.rc | 40 + zlib-1.2.11/zconf.h | 534 ++++ zlib-1.2.11/zconf.h.cmakein | 536 ++++ zlib-1.2.11/zconf.h.in | 534 ++++ zlib-1.2.11/zlib.3 | 149 ++ zlib-1.2.11/zlib.3.pdf | Bin 0 -> 19318 bytes zlib-1.2.11/zlib.h | 1912 +++++++++++++++ zlib-1.2.11/zlib.map | 94 + zlib-1.2.11/zlib.pc.cmakein | 13 + zlib-1.2.11/zlib.pc.in | 13 + zlib-1.2.11/zlib2ansi | 152 ++ zlib-1.2.11/zutil.c | 325 +++ zlib-1.2.11/zutil.h | 271 +++ 255 files changed, 76196 insertions(+), 4 deletions(-) delete mode 100644 ci/appveyor/zlib1211.zip create mode 100644 zlib-1.2.11/CMakeLists.txt create mode 100644 zlib-1.2.11/ChangeLog create mode 100644 zlib-1.2.11/FAQ create mode 100644 zlib-1.2.11/INDEX create mode 100644 zlib-1.2.11/Makefile create mode 100644 zlib-1.2.11/Makefile.in create mode 100644 zlib-1.2.11/README create mode 100644 zlib-1.2.11/adler32.c create mode 100644 zlib-1.2.11/amiga/Makefile.pup create mode 100644 zlib-1.2.11/amiga/Makefile.sas create mode 100644 zlib-1.2.11/compress.c create mode 100755 zlib-1.2.11/configure create mode 100644 zlib-1.2.11/contrib/README.contrib create mode 100644 zlib-1.2.11/contrib/ada/buffer_demo.adb create mode 100644 zlib-1.2.11/contrib/ada/mtest.adb create mode 100644 zlib-1.2.11/contrib/ada/read.adb create mode 100644 zlib-1.2.11/contrib/ada/readme.txt create mode 100644 zlib-1.2.11/contrib/ada/test.adb create mode 100644 zlib-1.2.11/contrib/ada/zlib-streams.adb create mode 100644 zlib-1.2.11/contrib/ada/zlib-streams.ads create mode 100644 zlib-1.2.11/contrib/ada/zlib-thin.adb create mode 100644 zlib-1.2.11/contrib/ada/zlib-thin.ads create mode 100644 zlib-1.2.11/contrib/ada/zlib.adb create mode 100644 zlib-1.2.11/contrib/ada/zlib.ads create mode 100644 zlib-1.2.11/contrib/ada/zlib.gpr create mode 100644 zlib-1.2.11/contrib/amd64/amd64-match.S create mode 100644 zlib-1.2.11/contrib/asm686/README.686 create mode 100644 zlib-1.2.11/contrib/asm686/match.S create mode 100644 zlib-1.2.11/contrib/blast/Makefile create mode 100644 zlib-1.2.11/contrib/blast/README create mode 100644 zlib-1.2.11/contrib/blast/blast.c create mode 100644 zlib-1.2.11/contrib/blast/blast.h create mode 100644 zlib-1.2.11/contrib/blast/test.pk create mode 100644 zlib-1.2.11/contrib/blast/test.txt create mode 100644 zlib-1.2.11/contrib/delphi/ZLib.pas create mode 100644 zlib-1.2.11/contrib/delphi/ZLibConst.pas create mode 100644 zlib-1.2.11/contrib/delphi/readme.txt create mode 100644 zlib-1.2.11/contrib/delphi/zlibd32.mak create mode 100644 zlib-1.2.11/contrib/dotzlib/DotZLib.build create mode 100644 zlib-1.2.11/contrib/dotzlib/DotZLib.chm create mode 100644 zlib-1.2.11/contrib/dotzlib/DotZLib.sln create mode 100644 zlib-1.2.11/contrib/dotzlib/DotZLib/AssemblyInfo.cs create mode 100644 zlib-1.2.11/contrib/dotzlib/DotZLib/ChecksumImpl.cs create mode 100644 zlib-1.2.11/contrib/dotzlib/DotZLib/CircularBuffer.cs create mode 100644 zlib-1.2.11/contrib/dotzlib/DotZLib/CodecBase.cs create mode 100644 zlib-1.2.11/contrib/dotzlib/DotZLib/Deflater.cs create mode 100644 zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.cs create mode 100644 zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.csproj create mode 100644 zlib-1.2.11/contrib/dotzlib/DotZLib/GZipStream.cs create mode 100644 zlib-1.2.11/contrib/dotzlib/DotZLib/Inflater.cs create mode 100644 zlib-1.2.11/contrib/dotzlib/DotZLib/UnitTests.cs create mode 100644 zlib-1.2.11/contrib/dotzlib/LICENSE_1_0.txt create mode 100644 zlib-1.2.11/contrib/dotzlib/readme.txt create mode 100644 zlib-1.2.11/contrib/gcc_gvmat64/gvmat64.S create mode 100644 zlib-1.2.11/contrib/infback9/README create mode 100644 zlib-1.2.11/contrib/infback9/infback9.c create mode 100644 zlib-1.2.11/contrib/infback9/infback9.h create mode 100644 zlib-1.2.11/contrib/infback9/inffix9.h create mode 100644 zlib-1.2.11/contrib/infback9/inflate9.h create mode 100644 zlib-1.2.11/contrib/infback9/inftree9.c create mode 100644 zlib-1.2.11/contrib/infback9/inftree9.h create mode 100644 zlib-1.2.11/contrib/inflate86/inffas86.c create mode 100644 zlib-1.2.11/contrib/inflate86/inffast.S create mode 100644 zlib-1.2.11/contrib/iostream/test.cpp create mode 100644 zlib-1.2.11/contrib/iostream/zfstream.cpp create mode 100644 zlib-1.2.11/contrib/iostream/zfstream.h create mode 100644 zlib-1.2.11/contrib/iostream2/zstream.h create mode 100644 zlib-1.2.11/contrib/iostream2/zstream_test.cpp create mode 100644 zlib-1.2.11/contrib/iostream3/README create mode 100644 zlib-1.2.11/contrib/iostream3/TODO create mode 100644 zlib-1.2.11/contrib/iostream3/test.cc create mode 100644 zlib-1.2.11/contrib/iostream3/zfstream.cc create mode 100644 zlib-1.2.11/contrib/iostream3/zfstream.h create mode 100644 zlib-1.2.11/contrib/masmx64/bld_ml64.bat create mode 100644 zlib-1.2.11/contrib/masmx64/gvmat64.asm create mode 100644 zlib-1.2.11/contrib/masmx64/inffas8664.c create mode 100644 zlib-1.2.11/contrib/masmx64/inffasx64.asm create mode 100644 zlib-1.2.11/contrib/masmx64/readme.txt create mode 100644 zlib-1.2.11/contrib/masmx86/bld_ml32.bat create mode 100644 zlib-1.2.11/contrib/masmx86/inffas32.asm create mode 100644 zlib-1.2.11/contrib/masmx86/match686.asm create mode 100644 zlib-1.2.11/contrib/masmx86/readme.txt create mode 100644 zlib-1.2.11/contrib/minizip/Makefile create mode 100644 zlib-1.2.11/contrib/minizip/Makefile.am create mode 100644 zlib-1.2.11/contrib/minizip/MiniZip64_Changes.txt create mode 100644 zlib-1.2.11/contrib/minizip/MiniZip64_info.txt create mode 100644 zlib-1.2.11/contrib/minizip/configure.ac create mode 100644 zlib-1.2.11/contrib/minizip/crypt.h create mode 100644 zlib-1.2.11/contrib/minizip/ioapi.c create mode 100644 zlib-1.2.11/contrib/minizip/ioapi.h create mode 100644 zlib-1.2.11/contrib/minizip/iowin32.c create mode 100644 zlib-1.2.11/contrib/minizip/iowin32.h create mode 100644 zlib-1.2.11/contrib/minizip/make_vms.com create mode 100644 zlib-1.2.11/contrib/minizip/miniunz.c create mode 100644 zlib-1.2.11/contrib/minizip/miniunzip.1 create mode 100644 zlib-1.2.11/contrib/minizip/minizip.1 create mode 100644 zlib-1.2.11/contrib/minizip/minizip.c create mode 100644 zlib-1.2.11/contrib/minizip/minizip.pc.in create mode 100644 zlib-1.2.11/contrib/minizip/mztools.c create mode 100644 zlib-1.2.11/contrib/minizip/mztools.h create mode 100644 zlib-1.2.11/contrib/minizip/unzip.c create mode 100644 zlib-1.2.11/contrib/minizip/unzip.h create mode 100644 zlib-1.2.11/contrib/minizip/zip.c create mode 100644 zlib-1.2.11/contrib/minizip/zip.h create mode 100644 zlib-1.2.11/contrib/pascal/example.pas create mode 100644 zlib-1.2.11/contrib/pascal/readme.txt create mode 100644 zlib-1.2.11/contrib/pascal/zlibd32.mak create mode 100644 zlib-1.2.11/contrib/pascal/zlibpas.pas create mode 100644 zlib-1.2.11/contrib/puff/Makefile create mode 100644 zlib-1.2.11/contrib/puff/README create mode 100644 zlib-1.2.11/contrib/puff/puff.c create mode 100644 zlib-1.2.11/contrib/puff/puff.h create mode 100644 zlib-1.2.11/contrib/puff/pufftest.c create mode 100644 zlib-1.2.11/contrib/puff/zeros.raw create mode 100644 zlib-1.2.11/contrib/testzlib/testzlib.c create mode 100644 zlib-1.2.11/contrib/testzlib/testzlib.txt create mode 100644 zlib-1.2.11/contrib/untgz/Makefile create mode 100644 zlib-1.2.11/contrib/untgz/Makefile.msc create mode 100644 zlib-1.2.11/contrib/untgz/untgz.c create mode 100644 zlib-1.2.11/contrib/vstudio/readme.txt create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj.filters create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj.filters create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj.filters create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj.filters create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/zlib.rc create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj.filters create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/zlibvc.def create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/zlibvc.sln create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj.filters create mode 100644 zlib-1.2.11/contrib/vstudio/vc11/miniunz.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc11/minizip.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc11/testzlib.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc11/testzlibdll.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc11/zlib.rc create mode 100644 zlib-1.2.11/contrib/vstudio/vc11/zlibstat.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc11/zlibvc.def create mode 100644 zlib-1.2.11/contrib/vstudio/vc11/zlibvc.sln create mode 100644 zlib-1.2.11/contrib/vstudio/vc11/zlibvc.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc12/miniunz.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc12/minizip.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc12/testzlib.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc12/testzlibdll.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc12/zlib.rc create mode 100644 zlib-1.2.11/contrib/vstudio/vc12/zlibstat.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc12/zlibvc.def create mode 100644 zlib-1.2.11/contrib/vstudio/vc12/zlibvc.sln create mode 100644 zlib-1.2.11/contrib/vstudio/vc12/zlibvc.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc14/miniunz.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc14/minizip.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc14/testzlib.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc14/testzlibdll.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc14/zlib.rc create mode 100644 zlib-1.2.11/contrib/vstudio/vc14/zlibstat.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc14/zlibvc.def create mode 100644 zlib-1.2.11/contrib/vstudio/vc14/zlibvc.sln create mode 100644 zlib-1.2.11/contrib/vstudio/vc14/zlibvc.vcxproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc9/miniunz.vcproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc9/minizip.vcproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc9/testzlib.vcproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc9/testzlibdll.vcproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc9/zlib.rc create mode 100644 zlib-1.2.11/contrib/vstudio/vc9/zlibstat.vcproj create mode 100644 zlib-1.2.11/contrib/vstudio/vc9/zlibvc.def create mode 100644 zlib-1.2.11/contrib/vstudio/vc9/zlibvc.sln create mode 100644 zlib-1.2.11/contrib/vstudio/vc9/zlibvc.vcproj create mode 100644 zlib-1.2.11/crc32.c create mode 100644 zlib-1.2.11/crc32.h create mode 100644 zlib-1.2.11/deflate.c create mode 100644 zlib-1.2.11/deflate.h create mode 100644 zlib-1.2.11/doc/algorithm.txt create mode 100644 zlib-1.2.11/doc/rfc1950.txt create mode 100644 zlib-1.2.11/doc/rfc1951.txt create mode 100644 zlib-1.2.11/doc/rfc1952.txt create mode 100644 zlib-1.2.11/doc/txtvsbin.txt create mode 100644 zlib-1.2.11/examples/README.examples create mode 100644 zlib-1.2.11/examples/enough.c create mode 100644 zlib-1.2.11/examples/fitblk.c create mode 100644 zlib-1.2.11/examples/gun.c create mode 100644 zlib-1.2.11/examples/gzappend.c create mode 100644 zlib-1.2.11/examples/gzjoin.c create mode 100644 zlib-1.2.11/examples/gzlog.c create mode 100644 zlib-1.2.11/examples/gzlog.h create mode 100644 zlib-1.2.11/examples/zlib_how.html create mode 100644 zlib-1.2.11/examples/zpipe.c create mode 100644 zlib-1.2.11/examples/zran.c create mode 100644 zlib-1.2.11/gzclose.c create mode 100644 zlib-1.2.11/gzguts.h create mode 100644 zlib-1.2.11/gzlib.c create mode 100644 zlib-1.2.11/gzread.c create mode 100644 zlib-1.2.11/gzwrite.c create mode 100644 zlib-1.2.11/infback.c create mode 100644 zlib-1.2.11/inffast.c create mode 100644 zlib-1.2.11/inffast.h create mode 100644 zlib-1.2.11/inffixed.h create mode 100644 zlib-1.2.11/inflate.c create mode 100644 zlib-1.2.11/inflate.h create mode 100644 zlib-1.2.11/inftrees.c create mode 100644 zlib-1.2.11/inftrees.h create mode 100644 zlib-1.2.11/make_vms.com create mode 100644 zlib-1.2.11/msdos/Makefile.bor create mode 100644 zlib-1.2.11/msdos/Makefile.dj2 create mode 100644 zlib-1.2.11/msdos/Makefile.emx create mode 100644 zlib-1.2.11/msdos/Makefile.msc create mode 100644 zlib-1.2.11/msdos/Makefile.tc create mode 100644 zlib-1.2.11/nintendods/Makefile create mode 100644 zlib-1.2.11/nintendods/README create mode 100644 zlib-1.2.11/old/Makefile.emx create mode 100644 zlib-1.2.11/old/Makefile.riscos create mode 100644 zlib-1.2.11/old/README create mode 100644 zlib-1.2.11/old/descrip.mms create mode 100644 zlib-1.2.11/old/os2/Makefile.os2 create mode 100644 zlib-1.2.11/old/os2/zlib.def create mode 100644 zlib-1.2.11/old/visual-basic.txt create mode 100644 zlib-1.2.11/os400/README400 create mode 100644 zlib-1.2.11/os400/bndsrc create mode 100644 zlib-1.2.11/os400/make.sh create mode 100644 zlib-1.2.11/os400/zlib.inc create mode 100644 zlib-1.2.11/qnx/package.qpg create mode 100644 zlib-1.2.11/test/example.c create mode 100644 zlib-1.2.11/test/infcover.c create mode 100644 zlib-1.2.11/test/minigzip.c create mode 100644 zlib-1.2.11/treebuild.xml create mode 100644 zlib-1.2.11/trees.c create mode 100644 zlib-1.2.11/trees.h create mode 100644 zlib-1.2.11/uncompr.c create mode 100644 zlib-1.2.11/watcom/watcom_f.mak create mode 100644 zlib-1.2.11/watcom/watcom_l.mak create mode 100644 zlib-1.2.11/win32/DLL_FAQ.txt create mode 100644 zlib-1.2.11/win32/Makefile.bor create mode 100644 zlib-1.2.11/win32/Makefile.gcc create mode 100644 zlib-1.2.11/win32/Makefile.msc create mode 100644 zlib-1.2.11/win32/README-WIN32.txt create mode 100644 zlib-1.2.11/win32/VisualC.txt create mode 100644 zlib-1.2.11/win32/zlib.def create mode 100644 zlib-1.2.11/win32/zlib1.rc create mode 100644 zlib-1.2.11/zconf.h create mode 100644 zlib-1.2.11/zconf.h.cmakein create mode 100644 zlib-1.2.11/zconf.h.in create mode 100644 zlib-1.2.11/zlib.3 create mode 100644 zlib-1.2.11/zlib.3.pdf create mode 100644 zlib-1.2.11/zlib.h create mode 100644 zlib-1.2.11/zlib.map create mode 100644 zlib-1.2.11/zlib.pc.cmakein create mode 100644 zlib-1.2.11/zlib.pc.in create mode 100755 zlib-1.2.11/zlib2ansi create mode 100644 zlib-1.2.11/zutil.c create mode 100644 zlib-1.2.11/zutil.h diff --git a/.appveyor.yml b/.appveyor.yml index f2b4b076..cbc88c34 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -60,7 +60,6 @@ install: # do not cause a version change. - "%PYTHON_DEF%\\python.exe ci/appveyor/fix_version.py ." - mv -f .git .git.bak - - 7z x ci\appveyor\zlib1211.zip - ps: ls ssh/*.dll - ps: ls ssh - ps: ls diff --git a/ci/appveyor/zlib1211.zip b/ci/appveyor/zlib1211.zip deleted file mode 100644 index db8c6583..00000000 --- a/ci/appveyor/zlib1211.zip +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d7510a8ee1918b7d0cad197a089c0a2cd4d6df05fee22389f67f115e738b178d -size 747422 diff --git a/zlib-1.2.11/CMakeLists.txt b/zlib-1.2.11/CMakeLists.txt new file mode 100644 index 00000000..0fe939df --- /dev/null +++ b/zlib-1.2.11/CMakeLists.txt @@ -0,0 +1,249 @@ +cmake_minimum_required(VERSION 2.4.4) +set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON) + +project(zlib C) + +set(VERSION "1.2.11") + +option(ASM686 "Enable building i686 assembly implementation") +option(AMD64 "Enable building amd64 assembly implementation") + +set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") +set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") +set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") +set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") +set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") + +include(CheckTypeSize) +include(CheckFunctionExists) +include(CheckIncludeFile) +include(CheckCSourceCompiles) +enable_testing() + +check_include_file(sys/types.h HAVE_SYS_TYPES_H) +check_include_file(stdint.h HAVE_STDINT_H) +check_include_file(stddef.h HAVE_STDDEF_H) + +# +# Check to see if we have large file support +# +set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1) +# We add these other definitions here because CheckTypeSize.cmake +# in CMake 2.4.x does not automatically do so and we want +# compatibility with CMake 2.4.x. +if(HAVE_SYS_TYPES_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H) +endif() +if(HAVE_STDINT_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H) +endif() +if(HAVE_STDDEF_H) + list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H) +endif() +check_type_size(off64_t OFF64_T) +if(HAVE_OFF64_T) + add_definitions(-D_LARGEFILE64_SOURCE=1) +endif() +set(CMAKE_REQUIRED_DEFINITIONS) # clear variable + +# +# Check for fseeko +# +check_function_exists(fseeko HAVE_FSEEKO) +if(NOT HAVE_FSEEKO) + add_definitions(-DNO_FSEEKO) +endif() + +# +# Check for unistd.h +# +check_include_file(unistd.h Z_HAVE_UNISTD_H) + +if(MSVC) + set(CMAKE_DEBUG_POSTFIX "d") + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) + add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) + include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR) + # If we're doing an out of source build and the user has a zconf.h + # in their source tree... + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h) + message(STATUS "Renaming") + message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h") + message(STATUS "to 'zconf.h.included' because this file is included with zlib") + message(STATUS "but CMake generates it automatically in the build directory.") + file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.included) + endif() +endif() + +set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/zlib.pc) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein + ${ZLIB_PC} @ONLY) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zconf.h.cmakein + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h @ONLY) +include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}) + + +#============================================================================ +# zlib +#============================================================================ + +set(ZLIB_PUBLIC_HDRS + ${CMAKE_CURRENT_BINARY_DIR}/zconf.h + zlib.h +) +set(ZLIB_PRIVATE_HDRS + crc32.h + deflate.h + gzguts.h + inffast.h + inffixed.h + inflate.h + inftrees.h + trees.h + zutil.h +) +set(ZLIB_SRCS + adler32.c + compress.c + crc32.c + deflate.c + gzclose.c + gzlib.c + gzread.c + gzwrite.c + inflate.c + infback.c + inftrees.c + inffast.c + trees.c + uncompr.c + zutil.c +) + +if(NOT MINGW) + set(ZLIB_DLL_SRCS + win32/zlib1.rc # If present will override custom build rule below. + ) +endif() + +if(CMAKE_COMPILER_IS_GNUCC) + if(ASM686) + set(ZLIB_ASMS contrib/asm686/match.S) + elseif (AMD64) + set(ZLIB_ASMS contrib/amd64/amd64-match.S) + endif () + + if(ZLIB_ASMS) + add_definitions(-DASMV) + set_source_files_properties(${ZLIB_ASMS} PROPERTIES LANGUAGE C COMPILE_FLAGS -DNO_UNDERLINE) + endif() +endif() + +if(MSVC) + if(ASM686) + ENABLE_LANGUAGE(ASM_MASM) + set(ZLIB_ASMS + contrib/masmx86/inffas32.asm + contrib/masmx86/match686.asm + ) + elseif (AMD64) + ENABLE_LANGUAGE(ASM_MASM) + set(ZLIB_ASMS + contrib/masmx64/gvmat64.asm + contrib/masmx64/inffasx64.asm + ) + endif() + + if(ZLIB_ASMS) + add_definitions(-DASMV -DASMINF) + endif() +endif() + +# parse the full version number from zlib.h and include in ZLIB_FULL_VERSION +file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib.h _zlib_h_contents) +string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*" + "\\1" ZLIB_FULL_VERSION ${_zlib_h_contents}) + +if(MINGW) + # This gets us DLL resource information when compiling on MinGW. + if(NOT CMAKE_RC_COMPILER) + set(CMAKE_RC_COMPILER windres.exe) + endif() + + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + COMMAND ${CMAKE_RC_COMPILER} + -D GCC_WINDRES + -I ${CMAKE_CURRENT_SOURCE_DIR} + -I ${CMAKE_CURRENT_BINARY_DIR} + -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) + set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) +endif(MINGW) + +add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) +set_target_properties(zlib PROPERTIES SOVERSION 1) + +if(NOT CYGWIN) + # This property causes shared libraries on Linux to have the full version + # encoded into their final filename. We disable this on Cygwin because + # it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll + # seems to be the default. + # + # This has no effect with MSVC, on that platform the version info for + # the DLL comes from the resource file win32/zlib1.rc + set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION}) +endif() + +if(UNIX) + # On unix-like platforms the library is almost always called libz + set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z) + if(NOT APPLE) + set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") + endif() +elseif(BUILD_SHARED_LIBS AND WIN32) + # Creates zlib1.dll when building shared library version + set_target_properties(zlib PROPERTIES SUFFIX "1.dll") +endif() + +if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) + install(TARGETS zlib zlibstatic + RUNTIME DESTINATION "${INSTALL_BIN_DIR}" + ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" + LIBRARY DESTINATION "${INSTALL_LIB_DIR}" ) +endif() +if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL ) + install(FILES ${ZLIB_PUBLIC_HDRS} DESTINATION "${INSTALL_INC_DIR}") +endif() +if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) + install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3") +endif() +if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) + install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}") +endif() + +#============================================================================ +# Example binaries +#============================================================================ + +add_executable(example test/example.c) +target_link_libraries(example zlib) +add_test(example example) + +add_executable(minigzip test/minigzip.c) +target_link_libraries(minigzip zlib) + +if(HAVE_OFF64_T) + add_executable(example64 test/example.c) + target_link_libraries(example64 zlib) + set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") + add_test(example64 example64) + + add_executable(minigzip64 test/minigzip.c) + target_link_libraries(minigzip64 zlib) + set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") +endif() diff --git a/zlib-1.2.11/ChangeLog b/zlib-1.2.11/ChangeLog new file mode 100644 index 00000000..30199a65 --- /dev/null +++ b/zlib-1.2.11/ChangeLog @@ -0,0 +1,1515 @@ + + ChangeLog file for zlib + +Changes in 1.2.11 (15 Jan 2017) +- Fix deflate stored bug when pulling last block from window +- Permit immediate deflateParams changes before any deflate input + +Changes in 1.2.10 (2 Jan 2017) +- Avoid warnings on snprintf() return value +- Fix bug in deflate_stored() for zero-length input +- Fix bug in gzwrite.c that produced corrupt gzip files +- Remove files to be installed before copying them in Makefile.in +- Add warnings when compiling with assembler code + +Changes in 1.2.9 (31 Dec 2016) +- Fix contrib/minizip to permit unzipping with desktop API [Zouzou] +- Improve contrib/blast to return unused bytes +- Assure that gzoffset() is correct when appending +- Improve compress() and uncompress() to support large lengths +- Fix bug in test/example.c where error code not saved +- Remedy Coverity warning [Randers-Pehrson] +- Improve speed of gzprintf() in transparent mode +- Fix inflateInit2() bug when windowBits is 16 or 32 +- Change DEBUG macro to ZLIB_DEBUG +- Avoid uninitialized access by gzclose_w() +- Allow building zlib outside of the source directory +- Fix bug that accepted invalid zlib header when windowBits is zero +- Fix gzseek() problem on MinGW due to buggy _lseeki64 there +- Loop on write() calls in gzwrite.c in case of non-blocking I/O +- Add --warn (-w) option to ./configure for more compiler warnings +- Reject a window size of 256 bytes if not using the zlib wrapper +- Fix bug when level 0 used with Z_HUFFMAN or Z_RLE +- Add --debug (-d) option to ./configure to define ZLIB_DEBUG +- Fix bugs in creating a very large gzip header +- Add uncompress2() function, which returns the input size used +- Assure that deflateParams() will not switch functions mid-block +- Dramatically speed up deflation for level 0 (storing) +- Add gzfread(), duplicating the interface of fread() +- Add gzfwrite(), duplicating the interface of fwrite() +- Add deflateGetDictionary() function +- Use snprintf() for later versions of Microsoft C +- Fix *Init macros to use z_ prefix when requested +- Replace as400 with os400 for OS/400 support [Monnerat] +- Add crc32_z() and adler32_z() functions with size_t lengths +- Update Visual Studio project files [AraHaan] + +Changes in 1.2.8 (28 Apr 2013) +- Update contrib/minizip/iowin32.c for Windows RT [Vollant] +- Do not force Z_CONST for C++ +- Clean up contrib/vstudio [Roß] +- Correct spelling error in zlib.h +- Fix mixed line endings in contrib/vstudio + +Changes in 1.2.7.3 (13 Apr 2013) +- Fix version numbers and DLL names in contrib/vstudio/*/zlib.rc + +Changes in 1.2.7.2 (13 Apr 2013) +- Change check for a four-byte type back to hexadecimal +- Fix typo in win32/Makefile.msc +- Add casts in gzwrite.c for pointer differences + +Changes in 1.2.7.1 (24 Mar 2013) +- Replace use of unsafe string functions with snprintf if available +- Avoid including stddef.h on Windows for Z_SOLO compile [Niessink] +- Fix gzgetc undefine when Z_PREFIX set [Turk] +- Eliminate use of mktemp in Makefile (not always available) +- Fix bug in 'F' mode for gzopen() +- Add inflateGetDictionary() function +- Correct comment in deflate.h +- Use _snprintf for snprintf in Microsoft C +- On Darwin, only use /usr/bin/libtool if libtool is not Apple +- Delete "--version" file if created by "ar --version" [Richard G.] +- Fix configure check for veracity of compiler error return codes +- Fix CMake compilation of static lib for MSVC2010 x64 +- Remove unused variable in infback9.c +- Fix argument checks in gzlog_compress() and gzlog_write() +- Clean up the usage of z_const and respect const usage within zlib +- Clean up examples/gzlog.[ch] comparisons of different types +- Avoid shift equal to bits in type (caused endless loop) +- Fix uninitialized value bug in gzputc() introduced by const patches +- Fix memory allocation error in examples/zran.c [Nor] +- Fix bug where gzopen(), gzclose() would write an empty file +- Fix bug in gzclose() when gzwrite() runs out of memory +- Check for input buffer malloc failure in examples/gzappend.c +- Add note to contrib/blast to use binary mode in stdio +- Fix comparisons of differently signed integers in contrib/blast +- Check for invalid code length codes in contrib/puff +- Fix serious but very rare decompression bug in inftrees.c +- Update inflateBack() comments, since inflate() can be faster +- Use underscored I/O function names for WINAPI_FAMILY +- Add _tr_flush_bits to the external symbols prefixed by --zprefix +- Add contrib/vstudio/vc10 pre-build step for static only +- Quote --version-script argument in CMakeLists.txt +- Don't specify --version-script on Apple platforms in CMakeLists.txt +- Fix casting error in contrib/testzlib/testzlib.c +- Fix types in contrib/minizip to match result of get_crc_table() +- Simplify contrib/vstudio/vc10 with 'd' suffix +- Add TOP support to win32/Makefile.msc +- Suport i686 and amd64 assembler builds in CMakeLists.txt +- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h +- Add vc11 and vc12 build files to contrib/vstudio +- Add gzvprintf() as an undocumented function in zlib +- Fix configure for Sun shell +- Remove runtime check in configure for four-byte integer type +- Add casts and consts to ease user conversion to C++ +- Add man pages for minizip and miniunzip +- In Makefile uninstall, don't rm if preceding cd fails +- Do not return Z_BUF_ERROR if deflateParam() has nothing to write + +Changes in 1.2.7 (2 May 2012) +- Replace use of memmove() with a simple copy for portability +- Test for existence of strerror +- Restore gzgetc_ for backward compatibility with 1.2.6 +- Fix build with non-GNU make on Solaris +- Require gcc 4.0 or later on Mac OS X to use the hidden attribute +- Include unistd.h for Watcom C +- Use __WATCOMC__ instead of __WATCOM__ +- Do not use the visibility attribute if NO_VIZ defined +- Improve the detection of no hidden visibility attribute +- Avoid using __int64 for gcc or solo compilation +- Cast to char * in gzprintf to avoid warnings [Zinser] +- Fix make_vms.com for VAX [Zinser] +- Don't use library or built-in byte swaps +- Simplify test and use of gcc hidden attribute +- Fix bug in gzclose_w() when gzwrite() fails to allocate memory +- Add "x" (O_EXCL) and "e" (O_CLOEXEC) modes support to gzopen() +- Fix bug in test/minigzip.c for configure --solo +- Fix contrib/vstudio project link errors [Mohanathas] +- Add ability to choose the builder in make_vms.com [Schweda] +- Add DESTDIR support to mingw32 win32/Makefile.gcc +- Fix comments in win32/Makefile.gcc for proper usage +- Allow overriding the default install locations for cmake +- Generate and install the pkg-config file with cmake +- Build both a static and a shared version of zlib with cmake +- Include version symbols for cmake builds +- If using cmake with MSVC, add the source directory to the includes +- Remove unneeded EXTRA_CFLAGS from win32/Makefile.gcc [Truta] +- Move obsolete emx makefile to old [Truta] +- Allow the use of -Wundef when compiling or using zlib +- Avoid the use of the -u option with mktemp +- Improve inflate() documentation on the use of Z_FINISH +- Recognize clang as gcc +- Add gzopen_w() in Windows for wide character path names +- Rename zconf.h in CMakeLists.txt to move it out of the way +- Add source directory in CMakeLists.txt for building examples +- Look in build directory for zlib.pc in CMakeLists.txt +- Remove gzflags from zlibvc.def in vc9 and vc10 +- Fix contrib/minizip compilation in the MinGW environment +- Update ./configure for Solaris, support --64 [Mooney] +- Remove -R. from Solaris shared build (possible security issue) +- Avoid race condition for parallel make (-j) running example +- Fix type mismatch between get_crc_table() and crc_table +- Fix parsing of version with "-" in CMakeLists.txt [Snider, Ziegler] +- Fix the path to zlib.map in CMakeLists.txt +- Force the native libtool in Mac OS X to avoid GNU libtool [Beebe] +- Add instructions to win32/Makefile.gcc for shared install [Torri] + +Changes in 1.2.6.1 (12 Feb 2012) +- Avoid the use of the Objective-C reserved name "id" +- Include io.h in gzguts.h for Microsoft compilers +- Fix problem with ./configure --prefix and gzgetc macro +- Include gz_header definition when compiling zlib solo +- Put gzflags() functionality back in zutil.c +- Avoid library header include in crc32.c for Z_SOLO +- Use name in GCC_CLASSIC as C compiler for coverage testing, if set +- Minor cleanup in contrib/minizip/zip.c [Vollant] +- Update make_vms.com [Zinser] +- Remove unnecessary gzgetc_ function +- Use optimized byte swap operations for Microsoft and GNU [Snyder] +- Fix minor typo in zlib.h comments [Rzesniowiecki] + +Changes in 1.2.6 (29 Jan 2012) +- Update the Pascal interface in contrib/pascal +- Fix function numbers for gzgetc_ in zlibvc.def files +- Fix configure.ac for contrib/minizip [Schiffer] +- Fix large-entry detection in minizip on 64-bit systems [Schiffer] +- Have ./configure use the compiler return code for error indication +- Fix CMakeLists.txt for cross compilation [McClure] +- Fix contrib/minizip/zip.c for 64-bit architectures [Dalsnes] +- Fix compilation of contrib/minizip on FreeBSD [Marquez] +- Correct suggested usages in win32/Makefile.msc [Shachar, Horvath] +- Include io.h for Turbo C / Borland C on all platforms [Truta] +- Make version explicit in contrib/minizip/configure.ac [Bosmans] +- Avoid warning for no encryption in contrib/minizip/zip.c [Vollant] +- Minor cleanup up contrib/minizip/unzip.c [Vollant] +- Fix bug when compiling minizip with C++ [Vollant] +- Protect for long name and extra fields in contrib/minizip [Vollant] +- Avoid some warnings in contrib/minizip [Vollant] +- Add -I../.. -L../.. to CFLAGS for minizip and miniunzip +- Add missing libs to minizip linker command +- Add support for VPATH builds in contrib/minizip +- Add an --enable-demos option to contrib/minizip/configure +- Add the generation of configure.log by ./configure +- Exit when required parameters not provided to win32/Makefile.gcc +- Have gzputc return the character written instead of the argument +- Use the -m option on ldconfig for BSD systems [Tobias] +- Correct in zlib.map when deflateResetKeep was added + +Changes in 1.2.5.3 (15 Jan 2012) +- Restore gzgetc function for binary compatibility +- Do not use _lseeki64 under Borland C++ [Truta] +- Update win32/Makefile.msc to build test/*.c [Truta] +- Remove old/visualc6 given CMakefile and other alternatives +- Update AS400 build files and documentation [Monnerat] +- Update win32/Makefile.gcc to build test/*.c [Truta] +- Permit stronger flushes after Z_BLOCK flushes +- Avoid extraneous empty blocks when doing empty flushes +- Permit Z_NULL arguments to deflatePending +- Allow deflatePrime() to insert bits in the middle of a stream +- Remove second empty static block for Z_PARTIAL_FLUSH +- Write out all of the available bits when using Z_BLOCK +- Insert the first two strings in the hash table after a flush + +Changes in 1.2.5.2 (17 Dec 2011) +- fix ld error: unable to find version dependency 'ZLIB_1.2.5' +- use relative symlinks for shared libs +- Avoid searching past window for Z_RLE strategy +- Assure that high-water mark initialization is always applied in deflate +- Add assertions to fill_window() in deflate.c to match comments +- Update python link in README +- Correct spelling error in gzread.c +- Fix bug in gzgets() for a concatenated empty gzip stream +- Correct error in comment for gz_make() +- Change gzread() and related to ignore junk after gzip streams +- Allow gzread() and related to continue after gzclearerr() +- Allow gzrewind() and gzseek() after a premature end-of-file +- Simplify gzseek() now that raw after gzip is ignored +- Change gzgetc() to a macro for speed (~40% speedup in testing) +- Fix gzclose() to return the actual error last encountered +- Always add large file support for windows +- Include zconf.h for windows large file support +- Include zconf.h.cmakein for windows large file support +- Update zconf.h.cmakein on make distclean +- Merge vestigial vsnprintf determination from zutil.h to gzguts.h +- Clarify how gzopen() appends in zlib.h comments +- Correct documentation of gzdirect() since junk at end now ignored +- Add a transparent write mode to gzopen() when 'T' is in the mode +- Update python link in zlib man page +- Get inffixed.h and MAKEFIXED result to match +- Add a ./config --solo option to make zlib subset with no library use +- Add undocumented inflateResetKeep() function for CAB file decoding +- Add --cover option to ./configure for gcc coverage testing +- Add #define ZLIB_CONST option to use const in the z_stream interface +- Add comment to gzdopen() in zlib.h to use dup() when using fileno() +- Note behavior of uncompress() to provide as much data as it can +- Add files in contrib/minizip to aid in building libminizip +- Split off AR options in Makefile.in and configure +- Change ON macro to Z_ARG to avoid application conflicts +- Facilitate compilation with Borland C++ for pragmas and vsnprintf +- Include io.h for Turbo C / Borland C++ +- Move example.c and minigzip.c to test/ +- Simplify incomplete code table filling in inflate_table() +- Remove code from inflate.c and infback.c that is impossible to execute +- Test the inflate code with full coverage +- Allow deflateSetDictionary, inflateSetDictionary at any time (in raw) +- Add deflateResetKeep and fix inflateResetKeep to retain dictionary +- Fix gzwrite.c to accommodate reduced memory zlib compilation +- Have inflate() with Z_FINISH avoid the allocation of a window +- Do not set strm->adler when doing raw inflate +- Fix gzeof() to behave just like feof() when read is not past end of file +- Fix bug in gzread.c when end-of-file is reached +- Avoid use of Z_BUF_ERROR in gz* functions except for premature EOF +- Document gzread() capability to read concurrently written files +- Remove hard-coding of resource compiler in CMakeLists.txt [Blammo] + +Changes in 1.2.5.1 (10 Sep 2011) +- Update FAQ entry on shared builds (#13) +- Avoid symbolic argument to chmod in Makefile.in +- Fix bug and add consts in contrib/puff [Oberhumer] +- Update contrib/puff/zeros.raw test file to have all block types +- Add full coverage test for puff in contrib/puff/Makefile +- Fix static-only-build install in Makefile.in +- Fix bug in unzGetCurrentFileInfo() in contrib/minizip [Kuno] +- Add libz.a dependency to shared in Makefile.in for parallel builds +- Spell out "number" (instead of "nb") in zlib.h for total_in, total_out +- Replace $(...) with `...` in configure for non-bash sh [Bowler] +- Add darwin* to Darwin* and solaris* to SunOS\ 5* in configure [Groffen] +- Add solaris* to Linux* in configure to allow gcc use [Groffen] +- Add *bsd* to Linux* case in configure [Bar-Lev] +- Add inffast.obj to dependencies in win32/Makefile.msc +- Correct spelling error in deflate.h [Kohler] +- Change libzdll.a again to libz.dll.a (!) in win32/Makefile.gcc +- Add test to configure for GNU C looking for gcc in output of $cc -v +- Add zlib.pc generation to win32/Makefile.gcc [Weigelt] +- Fix bug in zlib.h for _FILE_OFFSET_BITS set and _LARGEFILE64_SOURCE not +- Add comment in zlib.h that adler32_combine with len2 < 0 makes no sense +- Make NO_DIVIDE option in adler32.c much faster (thanks to John Reiser) +- Make stronger test in zconf.h to include unistd.h for LFS +- Apply Darwin patches for 64-bit file offsets to contrib/minizip [Slack] +- Fix zlib.h LFS support when Z_PREFIX used +- Add updated as400 support (removed from old) [Monnerat] +- Avoid deflate sensitivity to volatile input data +- Avoid division in adler32_combine for NO_DIVIDE +- Clarify the use of Z_FINISH with deflateBound() amount of space +- Set binary for output file in puff.c +- Use u4 type for crc_table to avoid conversion warnings +- Apply casts in zlib.h to avoid conversion warnings +- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller] +- Improve inflateSync() documentation to note indeterminancy +- Add deflatePending() function to return the amount of pending output +- Correct the spelling of "specification" in FAQ [Randers-Pehrson] +- Add a check in configure for stdarg.h, use for gzprintf() +- Check that pointers fit in ints when gzprint() compiled old style +- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler] +- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt] +- Add debug records in assmebler code [Londer] +- Update RFC references to use http://tools.ietf.org/html/... [Li] +- Add --archs option, use of libtool to configure for Mac OS X [Borstel] + +Changes in 1.2.5 (19 Apr 2010) +- Disable visibility attribute in win32/Makefile.gcc [Bar-Lev] +- Default to libdir as sharedlibdir in configure [Nieder] +- Update copyright dates on modified source files +- Update trees.c to be able to generate modified trees.h +- Exit configure for MinGW, suggesting win32/Makefile.gcc +- Check for NULL path in gz_open [Homurlu] + +Changes in 1.2.4.5 (18 Apr 2010) +- Set sharedlibdir in configure [Torok] +- Set LDFLAGS in Makefile.in [Bar-Lev] +- Avoid mkdir objs race condition in Makefile.in [Bowler] +- Add ZLIB_INTERNAL in front of internal inter-module functions and arrays +- Define ZLIB_INTERNAL to hide internal functions and arrays for GNU C +- Don't use hidden attribute when it is a warning generator (e.g. Solaris) + +Changes in 1.2.4.4 (18 Apr 2010) +- Fix CROSS_PREFIX executable testing, CHOST extract, mingw* [Torok] +- Undefine _LARGEFILE64_SOURCE in zconf.h if it is zero, but not if empty +- Try to use bash or ksh regardless of functionality of /bin/sh +- Fix configure incompatibility with NetBSD sh +- Remove attempt to run under bash or ksh since have better NetBSD fix +- Fix win32/Makefile.gcc for MinGW [Bar-Lev] +- Add diagnostic messages when using CROSS_PREFIX in configure +- Added --sharedlibdir option to configure [Weigelt] +- Use hidden visibility attribute when available [Frysinger] + +Changes in 1.2.4.3 (10 Apr 2010) +- Only use CROSS_PREFIX in configure for ar and ranlib if they exist +- Use CROSS_PREFIX for nm [Bar-Lev] +- Assume _LARGEFILE64_SOURCE defined is equivalent to true +- Avoid use of undefined symbols in #if with && and || +- Make *64 prototypes in gzguts.h consistent with functions +- Add -shared load option for MinGW in configure [Bowler] +- Move z_off64_t to public interface, use instead of off64_t +- Remove ! from shell test in configure (not portable to Solaris) +- Change +0 macro tests to -0 for possibly increased portability + +Changes in 1.2.4.2 (9 Apr 2010) +- Add consistent carriage returns to readme.txt's in masmx86 and masmx64 +- Really provide prototypes for *64 functions when building without LFS +- Only define unlink() in minigzip.c if unistd.h not included +- Update README to point to contrib/vstudio project files +- Move projects/vc6 to old/ and remove projects/ +- Include stdlib.h in minigzip.c for setmode() definition under WinCE +- Clean up assembler builds in win32/Makefile.msc [Rowe] +- Include sys/types.h for Microsoft for off_t definition +- Fix memory leak on error in gz_open() +- Symbolize nm as $NM in configure [Weigelt] +- Use TEST_LDSHARED instead of LDSHARED to link test programs [Weigelt] +- Add +0 to _FILE_OFFSET_BITS and _LFS64_LARGEFILE in case not defined +- Fix bug in gzeof() to take into account unused input data +- Avoid initialization of structures with variables in puff.c +- Updated win32/README-WIN32.txt [Rowe] + +Changes in 1.2.4.1 (28 Mar 2010) +- Remove the use of [a-z] constructs for sed in configure [gentoo 310225] +- Remove $(SHAREDLIB) from LIBS in Makefile.in [Creech] +- Restore "for debugging" comment on sprintf() in gzlib.c +- Remove fdopen for MVS from gzguts.h +- Put new README-WIN32.txt in win32 [Rowe] +- Add check for shell to configure and invoke another shell if needed +- Fix big fat stinking bug in gzseek() on uncompressed files +- Remove vestigial F_OPEN64 define in zutil.h +- Set and check the value of _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE +- Avoid errors on non-LFS systems when applications define LFS macros +- Set EXE to ".exe" in configure for MINGW [Kahle] +- Match crc32() in crc32.c exactly to the prototype in zlib.h [Sherrill] +- Add prefix for cross-compilation in win32/makefile.gcc [Bar-Lev] +- Add DLL install in win32/makefile.gcc [Bar-Lev] +- Allow Linux* or linux* from uname in configure [Bar-Lev] +- Allow ldconfig to be redefined in configure and Makefile.in [Bar-Lev] +- Add cross-compilation prefixes to configure [Bar-Lev] +- Match type exactly in gz_load() invocation in gzread.c +- Match type exactly of zcalloc() in zutil.c to zlib.h alloc_func +- Provide prototypes for *64 functions when building zlib without LFS +- Don't use -lc when linking shared library on MinGW +- Remove errno.h check in configure and vestigial errno code in zutil.h + +Changes in 1.2.4 (14 Mar 2010) +- Fix VER3 extraction in configure for no fourth subversion +- Update zlib.3, add docs to Makefile.in to make .pdf out of it +- Add zlib.3.pdf to distribution +- Don't set error code in gzerror() if passed pointer is NULL +- Apply destination directory fixes to CMakeLists.txt [Lowman] +- Move #cmakedefine's to a new zconf.in.cmakein +- Restore zconf.h for builds that don't use configure or cmake +- Add distclean to dummy Makefile for convenience +- Update and improve INDEX, README, and FAQ +- Update CMakeLists.txt for the return of zconf.h [Lowman] +- Update contrib/vstudio/vc9 and vc10 [Vollant] +- Change libz.dll.a back to libzdll.a in win32/Makefile.gcc +- Apply license and readme changes to contrib/asm686 [Raiter] +- Check file name lengths and add -c option in minigzip.c [Li] +- Update contrib/amd64 and contrib/masmx86/ [Vollant] +- Avoid use of "eof" parameter in trees.c to not shadow library variable +- Update make_vms.com for removal of zlibdefs.h [Zinser] +- Update assembler code and vstudio projects in contrib [Vollant] +- Remove outdated assembler code contrib/masm686 and contrib/asm586 +- Remove old vc7 and vc8 from contrib/vstudio +- Update win32/Makefile.msc, add ZLIB_VER_SUBREVISION [Rowe] +- Fix memory leaks in gzclose_r() and gzclose_w(), file leak in gz_open() +- Add contrib/gcc_gvmat64 for longest_match and inflate_fast [Vollant] +- Remove *64 functions from win32/zlib.def (they're not 64-bit yet) +- Fix bug in void-returning vsprintf() case in gzwrite.c +- Fix name change from inflate.h in contrib/inflate86/inffas86.c +- Check if temporary file exists before removing in make_vms.com [Zinser] +- Fix make install and uninstall for --static option +- Fix usage of _MSC_VER in gzguts.h and zutil.h [Truta] +- Update readme.txt in contrib/masmx64 and masmx86 to assemble + +Changes in 1.2.3.9 (21 Feb 2010) +- Expunge gzio.c +- Move as400 build information to old +- Fix updates in contrib/minizip and contrib/vstudio +- Add const to vsnprintf test in configure to avoid warnings [Weigelt] +- Delete zconf.h (made by configure) [Weigelt] +- Change zconf.in.h to zconf.h.in per convention [Weigelt] +- Check for NULL buf in gzgets() +- Return empty string for gzgets() with len == 1 (like fgets()) +- Fix description of gzgets() in zlib.h for end-of-file, NULL return +- Update minizip to 1.1 [Vollant] +- Avoid MSVC loss of data warnings in gzread.c, gzwrite.c +- Note in zlib.h that gzerror() should be used to distinguish from EOF +- Remove use of snprintf() from gzlib.c +- Fix bug in gzseek() +- Update contrib/vstudio, adding vc9 and vc10 [Kuno, Vollant] +- Fix zconf.h generation in CMakeLists.txt [Lowman] +- Improve comments in zconf.h where modified by configure + +Changes in 1.2.3.8 (13 Feb 2010) +- Clean up text files (tabs, trailing whitespace, etc.) [Oberhumer] +- Use z_off64_t in gz_zero() and gz_skip() to match state->skip +- Avoid comparison problem when sizeof(int) == sizeof(z_off64_t) +- Revert to Makefile.in from 1.2.3.6 (live with the clutter) +- Fix missing error return in gzflush(), add zlib.h note +- Add *64 functions to zlib.map [Levin] +- Fix signed/unsigned comparison in gz_comp() +- Use SFLAGS when testing shared linking in configure +- Add --64 option to ./configure to use -m64 with gcc +- Fix ./configure --help to correctly name options +- Have make fail if a test fails [Levin] +- Avoid buffer overrun in contrib/masmx64/gvmat64.asm [Simpson] +- Remove assembler object files from contrib + +Changes in 1.2.3.7 (24 Jan 2010) +- Always gzopen() with O_LARGEFILE if available +- Fix gzdirect() to work immediately after gzopen() or gzdopen() +- Make gzdirect() more precise when the state changes while reading +- Improve zlib.h documentation in many places +- Catch memory allocation failure in gz_open() +- Complete close operation if seek forward in gzclose_w() fails +- Return Z_ERRNO from gzclose_r() if close() fails +- Return Z_STREAM_ERROR instead of EOF for gzclose() being passed NULL +- Return zero for gzwrite() errors to match zlib.h description +- Return -1 on gzputs() error to match zlib.h description +- Add zconf.in.h to allow recovery from configure modification [Weigelt] +- Fix static library permissions in Makefile.in [Weigelt] +- Avoid warnings in configure tests that hide functionality [Weigelt] +- Add *BSD and DragonFly to Linux case in configure [gentoo 123571] +- Change libzdll.a to libz.dll.a in win32/Makefile.gcc [gentoo 288212] +- Avoid access of uninitialized data for first inflateReset2 call [Gomes] +- Keep object files in subdirectories to reduce the clutter somewhat +- Remove default Makefile and zlibdefs.h, add dummy Makefile +- Add new external functions to Z_PREFIX, remove duplicates, z_z_ -> z_ +- Remove zlibdefs.h completely -- modify zconf.h instead + +Changes in 1.2.3.6 (17 Jan 2010) +- Avoid void * arithmetic in gzread.c and gzwrite.c +- Make compilers happier with const char * for gz_error message +- Avoid unused parameter warning in inflate.c +- Avoid signed-unsigned comparison warning in inflate.c +- Indent #pragma's for traditional C +- Fix usage of strwinerror() in glib.c, change to gz_strwinerror() +- Correct email address in configure for system options +- Update make_vms.com and add make_vms.com to contrib/minizip [Zinser] +- Update zlib.map [Brown] +- Fix Makefile.in for Solaris 10 make of example64 and minizip64 [Torok] +- Apply various fixes to CMakeLists.txt [Lowman] +- Add checks on len in gzread() and gzwrite() +- Add error message for no more room for gzungetc() +- Remove zlib version check in gzwrite() +- Defer compression of gzprintf() result until need to +- Use snprintf() in gzdopen() if available +- Remove USE_MMAP configuration determination (only used by minigzip) +- Remove examples/pigz.c (available separately) +- Update examples/gun.c to 1.6 + +Changes in 1.2.3.5 (8 Jan 2010) +- Add space after #if in zutil.h for some compilers +- Fix relatively harmless bug in deflate_fast() [Exarevsky] +- Fix same problem in deflate_slow() +- Add $(SHAREDLIBV) to LIBS in Makefile.in [Brown] +- Add deflate_rle() for faster Z_RLE strategy run-length encoding +- Add deflate_huff() for faster Z_HUFFMAN_ONLY encoding +- Change name of "write" variable in inffast.c to avoid library collisions +- Fix premature EOF from gzread() in gzio.c [Brown] +- Use zlib header window size if windowBits is 0 in inflateInit2() +- Remove compressBound() call in deflate.c to avoid linking compress.o +- Replace use of errno in gz* with functions, support WinCE [Alves] +- Provide alternative to perror() in minigzip.c for WinCE [Alves] +- Don't use _vsnprintf on later versions of MSVC [Lowman] +- Add CMake build script and input file [Lowman] +- Update contrib/minizip to 1.1 [Svensson, Vollant] +- Moved nintendods directory from contrib to . +- Replace gzio.c with a new set of routines with the same functionality +- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above +- Update contrib/minizip to 1.1b +- Change gzeof() to return 0 on error instead of -1 to agree with zlib.h + +Changes in 1.2.3.4 (21 Dec 2009) +- Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility +- Update comments in configure and Makefile.in for default --shared +- Fix test -z's in configure [Marquess] +- Build examplesh and minigzipsh when not testing +- Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h +- Import LDFLAGS from the environment in configure +- Fix configure to populate SFLAGS with discovered CFLAGS options +- Adapt make_vms.com to the new Makefile.in [Zinser] +- Add zlib2ansi script for C++ compilation [Marquess] +- Add _FILE_OFFSET_BITS=64 test to make test (when applicable) +- Add AMD64 assembler code for longest match to contrib [Teterin] +- Include options from $SFLAGS when doing $LDSHARED +- Simplify 64-bit file support by introducing z_off64_t type +- Make shared object files in objs directory to work around old Sun cc +- Use only three-part version number for Darwin shared compiles +- Add rc option to ar in Makefile.in for when ./configure not run +- Add -WI,-rpath,. to LDFLAGS for OSF 1 V4* +- Set LD_LIBRARYN32_PATH for SGI IRIX shared compile +- Protect against _FILE_OFFSET_BITS being defined when compiling zlib +- Rename Makefile.in targets allstatic to static and allshared to shared +- Fix static and shared Makefile.in targets to be independent +- Correct error return bug in gz_open() by setting state [Brown] +- Put spaces before ;;'s in configure for better sh compatibility +- Add pigz.c (parallel implementation of gzip) to examples/ +- Correct constant in crc32.c to UL [Leventhal] +- Reject negative lengths in crc32_combine() +- Add inflateReset2() function to work like inflateEnd()/inflateInit2() +- Include sys/types.h for _LARGEFILE64_SOURCE [Brown] +- Correct typo in doc/algorithm.txt [Janik] +- Fix bug in adler32_combine() [Zhu] +- Catch missing-end-of-block-code error in all inflates and in puff + Assures that random input to inflate eventually results in an error +- Added enough.c (calculation of ENOUGH for inftrees.h) to examples/ +- Update ENOUGH and its usage to reflect discovered bounds +- Fix gzerror() error report on empty input file [Brown] +- Add ush casts in trees.c to avoid pedantic runtime errors +- Fix typo in zlib.h uncompress() description [Reiss] +- Correct inflate() comments with regard to automatic header detection +- Remove deprecation comment on Z_PARTIAL_FLUSH (it stays) +- Put new version of gzlog (2.0) in examples with interruption recovery +- Add puff compile option to permit invalid distance-too-far streams +- Add puff TEST command options, ability to read piped input +- Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but + _LARGEFILE64_SOURCE not defined +- Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart +- Fix deflateSetDictionary() to use all 32K for output consistency +- Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h) +- Clear bytes after deflate lookahead to avoid use of uninitialized data +- Change a limit in inftrees.c to be more transparent to Coverity Prevent +- Update win32/zlib.def with exported symbols from zlib.h +- Correct spelling errors in zlib.h [Willem, Sobrado] +- Allow Z_BLOCK for deflate() to force a new block +- Allow negative bits in inflatePrime() to delete existing bit buffer +- Add Z_TREES flush option to inflate() to return at end of trees +- Add inflateMark() to return current state information for random access +- Add Makefile for NintendoDS to contrib [Costa] +- Add -w in configure compile tests to avoid spurious warnings [Beucler] +- Fix typos in zlib.h comments for deflateSetDictionary() +- Fix EOF detection in transparent gzread() [Maier] + +Changes in 1.2.3.3 (2 October 2006) +- Make --shared the default for configure, add a --static option +- Add compile option to permit invalid distance-too-far streams +- Add inflateUndermine() function which is required to enable above +- Remove use of "this" variable name for C++ compatibility [Marquess] +- Add testing of shared library in make test, if shared library built +- Use ftello() and fseeko() if available instead of ftell() and fseek() +- Provide two versions of all functions that use the z_off_t type for + binary compatibility -- a normal version and a 64-bit offset version, + per the Large File Support Extension when _LARGEFILE64_SOURCE is + defined; use the 64-bit versions by default when _FILE_OFFSET_BITS + is defined to be 64 +- Add a --uname= option to configure to perhaps help with cross-compiling + +Changes in 1.2.3.2 (3 September 2006) +- Turn off silly Borland warnings [Hay] +- Use off64_t and define _LARGEFILE64_SOURCE when present +- Fix missing dependency on inffixed.h in Makefile.in +- Rig configure --shared to build both shared and static [Teredesai, Truta] +- Remove zconf.in.h and instead create a new zlibdefs.h file +- Fix contrib/minizip/unzip.c non-encrypted after encrypted [Vollant] +- Add treebuild.xml (see http://treebuild.metux.de/) [Weigelt] + +Changes in 1.2.3.1 (16 August 2006) +- Add watcom directory with OpenWatcom make files [Daniel] +- Remove #undef of FAR in zconf.in.h for MVS [Fedtke] +- Update make_vms.com [Zinser] +- Use -fPIC for shared build in configure [Teredesai, Nicholson] +- Use only major version number for libz.so on IRIX and OSF1 [Reinholdtsen] +- Use fdopen() (not _fdopen()) for Interix in zutil.h [Bäck] +- Add some FAQ entries about the contrib directory +- Update the MVS question in the FAQ +- Avoid extraneous reads after EOF in gzio.c [Brown] +- Correct spelling of "successfully" in gzio.c [Randers-Pehrson] +- Add comments to zlib.h about gzerror() usage [Brown] +- Set extra flags in gzip header in gzopen() like deflate() does +- Make configure options more compatible with double-dash conventions + [Weigelt] +- Clean up compilation under Solaris SunStudio cc [Rowe, Reinholdtsen] +- Fix uninstall target in Makefile.in [Truta] +- Add pkgconfig support [Weigelt] +- Use $(DESTDIR) macro in Makefile.in [Reinholdtsen, Weigelt] +- Replace set_data_type() with a more accurate detect_data_type() in + trees.c, according to the txtvsbin.txt document [Truta] +- Swap the order of #include and #include "zlib.h" in + gzio.c, example.c and minigzip.c [Truta] +- Shut up annoying VS2005 warnings about standard C deprecation [Rowe, + Truta] (where?) +- Fix target "clean" from win32/Makefile.bor [Truta] +- Create .pdb and .manifest files in win32/makefile.msc [Ziegler, Rowe] +- Update zlib www home address in win32/DLL_FAQ.txt [Truta] +- Update contrib/masmx86/inffas32.asm for VS2005 [Vollant, Van Wassenhove] +- Enable browse info in the "Debug" and "ASM Debug" configurations in + the Visual C++ 6 project, and set (non-ASM) "Debug" as default [Truta] +- Add pkgconfig support [Weigelt] +- Add ZLIB_VER_MAJOR, ZLIB_VER_MINOR and ZLIB_VER_REVISION in zlib.h, + for use in win32/zlib1.rc [Polushin, Rowe, Truta] +- Add a document that explains the new text detection scheme to + doc/txtvsbin.txt [Truta] +- Add rfc1950.txt, rfc1951.txt and rfc1952.txt to doc/ [Truta] +- Move algorithm.txt into doc/ [Truta] +- Synchronize FAQ with website +- Fix compressBound(), was low for some pathological cases [Fearnley] +- Take into account wrapper variations in deflateBound() +- Set examples/zpipe.c input and output to binary mode for Windows +- Update examples/zlib_how.html with new zpipe.c (also web site) +- Fix some warnings in examples/gzlog.c and examples/zran.c (it seems + that gcc became pickier in 4.0) +- Add zlib.map for Linux: "All symbols from zlib-1.1.4 remain + un-versioned, the patch adds versioning only for symbols introduced in + zlib-1.2.0 or later. It also declares as local those symbols which are + not designed to be exported." [Levin] +- Update Z_PREFIX list in zconf.in.h, add --zprefix option to configure +- Do not initialize global static by default in trees.c, add a response + NO_INIT_GLOBAL_POINTERS to initialize them if needed [Marquess] +- Don't use strerror() in gzio.c under WinCE [Yakimov] +- Don't use errno.h in zutil.h under WinCE [Yakimov] +- Move arguments for AR to its usage to allow replacing ar [Marot] +- Add HAVE_VISIBILITY_PRAGMA in zconf.in.h for Mozilla [Randers-Pehrson] +- Improve inflateInit() and inflateInit2() documentation +- Fix structure size comment in inflate.h +- Change configure help option from --h* to --help [Santos] + +Changes in 1.2.3 (18 July 2005) +- Apply security vulnerability fixes to contrib/infback9 as well +- Clean up some text files (carriage returns, trailing space) +- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant] + +Changes in 1.2.2.4 (11 July 2005) +- Add inflatePrime() function for starting inflation at bit boundary +- Avoid some Visual C warnings in deflate.c +- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit + compile +- Fix some spelling errors in comments [Betts] +- Correct inflateInit2() error return documentation in zlib.h +- Add zran.c example of compressed data random access to examples + directory, shows use of inflatePrime() +- Fix cast for assignments to strm->state in inflate.c and infback.c +- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer] +- Move declarations of gf2 functions to right place in crc32.c [Oberhumer] +- Add cast in trees.c t avoid a warning [Oberhumer] +- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer] +- Update make_vms.com [Zinser] +- Initialize state->write in inflateReset() since copied in inflate_fast() +- Be more strict on incomplete code sets in inflate_table() and increase + ENOUGH and MAXD -- this repairs a possible security vulnerability for + invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for + discovering the vulnerability and providing test cases. +- Add ia64 support to configure for HP-UX [Smith] +- Add error return to gzread() for format or i/o error [Levin] +- Use malloc.h for OS/2 [Necasek] + +Changes in 1.2.2.3 (27 May 2005) +- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile +- Typecast fread() return values in gzio.c [Vollant] +- Remove trailing space in minigzip.c outmode (VC++ can't deal with it) +- Fix crc check bug in gzread() after gzungetc() [Heiner] +- Add the deflateTune() function to adjust internal compression parameters +- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack) +- Remove an incorrect assertion in examples/zpipe.c +- Add C++ wrapper in infback9.h [Donais] +- Fix bug in inflateCopy() when decoding fixed codes +- Note in zlib.h how much deflateSetDictionary() actually uses +- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used) +- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer] +- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer] +- Add gzdirect() function to indicate transparent reads +- Update contrib/minizip [Vollant] +- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer] +- Add casts in crc32.c to avoid warnings [Oberhumer] +- Add contrib/masmx64 [Vollant] +- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant] + +Changes in 1.2.2.2 (30 December 2004) +- Replace structure assignments in deflate.c and inflate.c with zmemcpy to + avoid implicit memcpy calls (portability for no-library compilation) +- Increase sprintf() buffer size in gzdopen() to allow for large numbers +- Add INFLATE_STRICT to check distances against zlib header +- Improve WinCE errno handling and comments [Chang] +- Remove comment about no gzip header processing in FAQ +- Add Z_FIXED strategy option to deflateInit2() to force fixed trees +- Add updated make_vms.com [Coghlan], update README +- Create a new "examples" directory, move gzappend.c there, add zpipe.c, + fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html. +- Add FAQ entry and comments in deflate.c on uninitialized memory access +- Add Solaris 9 make options in configure [Gilbert] +- Allow strerror() usage in gzio.c for STDC +- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer] +- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant] +- Use z_off_t for adler32_combine() and crc32_combine() lengths +- Make adler32() much faster for small len +- Use OS_CODE in deflate() default gzip header + +Changes in 1.2.2.1 (31 October 2004) +- Allow inflateSetDictionary() call for raw inflate +- Fix inflate header crc check bug for file names and comments +- Add deflateSetHeader() and gz_header structure for custom gzip headers +- Add inflateGetheader() to retrieve gzip headers +- Add crc32_combine() and adler32_combine() functions +- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list +- Use zstreamp consistently in zlib.h (inflate_back functions) +- Remove GUNZIP condition from definition of inflate_mode in inflate.h + and in contrib/inflate86/inffast.S [Truta, Anderson] +- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson] +- Update projects/README.projects and projects/visualc6 [Truta] +- Update win32/DLL_FAQ.txt [Truta] +- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta] +- Deprecate Z_ASCII; use Z_TEXT instead [Truta] +- Use a new algorithm for setting strm->data_type in trees.c [Truta] +- Do not define an exit() prototype in zutil.c unless DEBUG defined +- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] +- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() +- Fix Darwin build version identification [Peterson] + +Changes in 1.2.2 (3 October 2004) +- Update zlib.h comments on gzip in-memory processing +- Set adler to 1 in inflateReset() to support Java test suite [Walles] +- Add contrib/dotzlib [Ravn] +- Update win32/DLL_FAQ.txt [Truta] +- Update contrib/minizip [Vollant] +- Move contrib/visual-basic.txt to old/ [Truta] +- Fix assembler builds in projects/visualc6/ [Truta] + +Changes in 1.2.1.2 (9 September 2004) +- Update INDEX file +- Fix trees.c to update strm->data_type (no one ever noticed!) +- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown] +- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE) +- Add limited multitasking protection to DYNAMIC_CRC_TABLE +- Add NO_vsnprintf for VMS in zutil.h [Mozilla] +- Don't declare strerror() under VMS [Mozilla] +- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize +- Update contrib/ada [Anisimkov] +- Update contrib/minizip [Vollant] +- Fix configure to not hardcode directories for Darwin [Peterson] +- Fix gzio.c to not return error on empty files [Brown] +- Fix indentation; update version in contrib/delphi/ZLib.pas and + contrib/pascal/zlibpas.pas [Truta] +- Update mkasm.bat in contrib/masmx86 [Truta] +- Update contrib/untgz [Truta] +- Add projects/README.projects [Truta] +- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta] +- Update win32/DLL_FAQ.txt [Truta] +- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta] +- Remove an unnecessary assignment to curr in inftrees.c [Truta] +- Add OS/2 to exe builds in configure [Poltorak] +- Remove err dummy parameter in zlib.h [Kientzle] + +Changes in 1.2.1.1 (9 January 2004) +- Update email address in README +- Several FAQ updates +- Fix a big fat bug in inftrees.c that prevented decoding valid + dynamic blocks with only literals and no distance codes -- + Thanks to "Hot Emu" for the bug report and sample file +- Add a note to puff.c on no distance codes case. + +Changes in 1.2.1 (17 November 2003) +- Remove a tab in contrib/gzappend/gzappend.c +- Update some interfaces in contrib for new zlib functions +- Update zlib version number in some contrib entries +- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta] +- Support shared libraries on Hurd and KFreeBSD [Brown] +- Fix error in NO_DIVIDE option of adler32.c + +Changes in 1.2.0.8 (4 November 2003) +- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas +- Add experimental NO_DIVIDE #define in adler32.c + - Possibly faster on some processors (let me know if it is) +- Correct Z_BLOCK to not return on first inflate call if no wrap +- Fix strm->data_type on inflate() return to correctly indicate EOB +- Add deflatePrime() function for appending in the middle of a byte +- Add contrib/gzappend for an example of appending to a stream +- Update win32/DLL_FAQ.txt [Truta] +- Delete Turbo C comment in README [Truta] +- Improve some indentation in zconf.h [Truta] +- Fix infinite loop on bad input in configure script [Church] +- Fix gzeof() for concatenated gzip files [Johnson] +- Add example to contrib/visual-basic.txt [Michael B.] +- Add -p to mkdir's in Makefile.in [vda] +- Fix configure to properly detect presence or lack of printf functions +- Add AS400 support [Monnerat] +- Add a little Cygwin support [Wilson] + +Changes in 1.2.0.7 (21 September 2003) +- Correct some debug formats in contrib/infback9 +- Cast a type in a debug statement in trees.c +- Change search and replace delimiter in configure from % to # [Beebe] +- Update contrib/untgz to 0.2 with various fixes [Truta] +- Add build support for Amiga [Nikl] +- Remove some directories in old that have been updated to 1.2 +- Add dylib building for Mac OS X in configure and Makefile.in +- Remove old distribution stuff from Makefile +- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X +- Update links in README + +Changes in 1.2.0.6 (13 September 2003) +- Minor FAQ updates +- Update contrib/minizip to 1.00 [Vollant] +- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta] +- Update POSTINC comment for 68060 [Nikl] +- Add contrib/infback9 with deflate64 decoding (unsupported) +- For MVS define NO_vsnprintf and undefine FAR [van Burik] +- Add pragma for fdopen on MVS [van Burik] + +Changes in 1.2.0.5 (8 September 2003) +- Add OF to inflateBackEnd() declaration in zlib.h +- Remember start when using gzdopen in the middle of a file +- Use internal off_t counters in gz* functions to properly handle seeks +- Perform more rigorous check for distance-too-far in inffast.c +- Add Z_BLOCK flush option to return from inflate at block boundary +- Set strm->data_type on return from inflate + - Indicate bits unused, if at block boundary, and if in last block +- Replace size_t with ptrdiff_t in crc32.c, and check for correct size +- Add condition so old NO_DEFLATE define still works for compatibility +- FAQ update regarding the Windows DLL [Truta] +- INDEX update: add qnx entry, remove aix entry [Truta] +- Install zlib.3 into mandir [Wilson] +- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta] +- Adapt the zlib interface to the new DLL convention guidelines [Truta] +- Introduce ZLIB_WINAPI macro to allow the export of functions using + the WINAPI calling convention, for Visual Basic [Vollant, Truta] +- Update msdos and win32 scripts and makefiles [Truta] +- Export symbols by name, not by ordinal, in win32/zlib.def [Truta] +- Add contrib/ada [Anisimkov] +- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta] +- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant] +- Add contrib/masm686 [Truta] +- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm + [Truta, Vollant] +- Update contrib/delphi; rename to contrib/pascal; add example [Truta] +- Remove contrib/delphi2; add a new contrib/delphi [Truta] +- Avoid inclusion of the nonstandard in contrib/iostream, + and fix some method prototypes [Truta] +- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip + [Truta] +- Avoid the use of backslash (\) in contrib/minizip [Vollant] +- Fix file time handling in contrib/untgz; update makefiles [Truta] +- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines + [Vollant] +- Remove contrib/vstudio/vc15_16 [Vollant] +- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta] +- Update README.contrib [Truta] +- Invert the assignment order of match_head and s->prev[...] in + INSERT_STRING [Truta] +- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings + [Truta] +- Compare function pointers with 0, not with NULL or Z_NULL [Truta] +- Fix prototype of syncsearch in inflate.c [Truta] +- Introduce ASMINF macro to be enabled when using an ASM implementation + of inflate_fast [Truta] +- Change NO_DEFLATE to NO_GZCOMPRESS [Truta] +- Modify test_gzio in example.c to take a single file name as a + parameter [Truta] +- Exit the example.c program if gzopen fails [Truta] +- Add type casts around strlen in example.c [Truta] +- Remove casting to sizeof in minigzip.c; give a proper type + to the variable compared with SUFFIX_LEN [Truta] +- Update definitions of STDC and STDC99 in zconf.h [Truta] +- Synchronize zconf.h with the new Windows DLL interface [Truta] +- Use SYS16BIT instead of __32BIT__ to distinguish between + 16- and 32-bit platforms [Truta] +- Use far memory allocators in small 16-bit memory models for + Turbo C [Truta] +- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in + zlibCompileFlags [Truta] +- Cygwin has vsnprintf [Wilson] +- In Windows16, OS_CODE is 0, as in MSDOS [Truta] +- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson] + +Changes in 1.2.0.4 (10 August 2003) +- Minor FAQ updates +- Be more strict when checking inflateInit2's windowBits parameter +- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well +- Add gzip wrapper option to deflateInit2 using windowBits +- Add updated QNX rule in configure and qnx directory [Bonnefoy] +- Make inflate distance-too-far checks more rigorous +- Clean up FAR usage in inflate +- Add casting to sizeof() in gzio.c and minigzip.c + +Changes in 1.2.0.3 (19 July 2003) +- Fix silly error in gzungetc() implementation [Vollant] +- Update contrib/minizip and contrib/vstudio [Vollant] +- Fix printf format in example.c +- Correct cdecl support in zconf.in.h [Anisimkov] +- Minor FAQ updates + +Changes in 1.2.0.2 (13 July 2003) +- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons +- Attempt to avoid warnings in crc32.c for pointer-int conversion +- Add AIX to configure, remove aix directory [Bakker] +- Add some casts to minigzip.c +- Improve checking after insecure sprintf() or vsprintf() calls +- Remove #elif's from crc32.c +- Change leave label to inf_leave in inflate.c and infback.c to avoid + library conflicts +- Remove inflate gzip decoding by default--only enable gzip decoding by + special request for stricter backward compatibility +- Add zlibCompileFlags() function to return compilation information +- More typecasting in deflate.c to avoid warnings +- Remove leading underscore from _Capital #defines [Truta] +- Fix configure to link shared library when testing +- Add some Windows CE target adjustments [Mai] +- Remove #define ZLIB_DLL in zconf.h [Vollant] +- Add zlib.3 [Rodgers] +- Update RFC URL in deflate.c and algorithm.txt [Mai] +- Add zlib_dll_FAQ.txt to contrib [Truta] +- Add UL to some constants [Truta] +- Update minizip and vstudio [Vollant] +- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h +- Expand use of NO_DUMMY_DECL to avoid all dummy structures +- Added iostream3 to contrib [Schwardt] +- Replace rewind() with fseek() for WinCE [Truta] +- Improve setting of zlib format compression level flags + - Report 0 for huffman and rle strategies and for level == 0 or 1 + - Report 2 only for level == 6 +- Only deal with 64K limit when necessary at compile time [Truta] +- Allow TOO_FAR check to be turned off at compile time [Truta] +- Add gzclearerr() function [Souza] +- Add gzungetc() function + +Changes in 1.2.0.1 (17 March 2003) +- Add Z_RLE strategy for run-length encoding [Truta] + - When Z_RLE requested, restrict matches to distance one + - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE +- Correct FASTEST compilation to allow level == 0 +- Clean up what gets compiled for FASTEST +- Incorporate changes to zconf.in.h [Vollant] + - Refine detection of Turbo C need for dummy returns + - Refine ZLIB_DLL compilation + - Include additional header file on VMS for off_t typedef +- Try to use _vsnprintf where it supplants vsprintf [Vollant] +- Add some casts in inffast.c +- Enchance comments in zlib.h on what happens if gzprintf() tries to + write more than 4095 bytes before compression +- Remove unused state from inflateBackEnd() +- Remove exit(0) from minigzip.c, example.c +- Get rid of all those darn tabs +- Add "check" target to Makefile.in that does the same thing as "test" +- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in +- Update contrib/inflate86 [Anderson] +- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant] +- Add msdos and win32 directories with makefiles [Truta] +- More additions and improvements to the FAQ + +Changes in 1.2.0 (9 March 2003) +- New and improved inflate code + - About 20% faster + - Does not allocate 32K window unless and until needed + - Automatically detects and decompresses gzip streams + - Raw inflate no longer needs an extra dummy byte at end + - Added inflateBack functions using a callback interface--even faster + than inflate, useful for file utilities (gzip, zip) + - Added inflateCopy() function to record state for random access on + externally generated deflate streams (e.g. in gzip files) + - More readable code (I hope) +- New and improved crc32() + - About 50% faster, thanks to suggestions from Rodney Brown +- Add deflateBound() and compressBound() functions +- Fix memory leak in deflateInit2() +- Permit setting dictionary for raw deflate (for parallel deflate) +- Fix const declaration for gzwrite() +- Check for some malloc() failures in gzio.c +- Fix bug in gzopen() on single-byte file 0x1f +- Fix bug in gzread() on concatenated file with 0x1f at end of buffer + and next buffer doesn't start with 0x8b +- Fix uncompress() to return Z_DATA_ERROR on truncated input +- Free memory at end of example.c +- Remove MAX #define in trees.c (conflicted with some libraries) +- Fix static const's in deflate.c, gzio.c, and zutil.[ch] +- Declare malloc() and free() in gzio.c if STDC not defined +- Use malloc() instead of calloc() in zutil.c if int big enough +- Define STDC for AIX +- Add aix/ with approach for compiling shared library on AIX +- Add HP-UX support for shared libraries in configure +- Add OpenUNIX support for shared libraries in configure +- Use $cc instead of gcc to build shared library +- Make prefix directory if needed when installing +- Correct Macintosh avoidance of typedef Byte in zconf.h +- Correct Turbo C memory allocation when under Linux +- Use libz.a instead of -lz in Makefile (assure use of compiled library) +- Update configure to check for snprintf or vsnprintf functions and their + return value, warn during make if using an insecure function +- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that + is lost when library is used--resolution is to build new zconf.h +- Documentation improvements (in zlib.h): + - Document raw deflate and inflate + - Update RFCs URL + - Point out that zlib and gzip formats are different + - Note that Z_BUF_ERROR is not fatal + - Document string limit for gzprintf() and possible buffer overflow + - Note requirement on avail_out when flushing + - Note permitted values of flush parameter of inflate() +- Add some FAQs (and even answers) to the FAQ +- Add contrib/inflate86/ for x86 faster inflate +- Add contrib/blast/ for PKWare Data Compression Library decompression +- Add contrib/puff/ simple inflate for deflate format description + +Changes in 1.1.4 (11 March 2002) +- ZFREE was repeated on same allocation on some error conditions. + This creates a security problem described in + http://www.zlib.org/advisory-2002-03-11.txt +- Returned incorrect error (Z_MEM_ERROR) on some invalid data +- Avoid accesses before window for invalid distances with inflate window + less than 32K. +- force windowBits > 8 to avoid a bug in the encoder for a window size + of 256 bytes. (A complete fix will be available in 1.1.5). + +Changes in 1.1.3 (9 July 1998) +- fix "an inflate input buffer bug that shows up on rare but persistent + occasions" (Mark) +- fix gzread and gztell for concatenated .gz files (Didier Le Botlan) +- fix gzseek(..., SEEK_SET) in write mode +- fix crc check after a gzeek (Frank Faubert) +- fix miniunzip when the last entry in a zip file is itself a zip file + (J Lillge) +- add contrib/asm586 and contrib/asm686 (Brian Raiter) + See http://www.muppetlabs.com/~breadbox/software/assembly.html +- add support for Delphi 3 in contrib/delphi (Bob Dellaca) +- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti) +- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren) +- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks) +- added a FAQ file + +- Support gzdopen on Mac with Metrowerks (Jason Linhart) +- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart) +- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young) +- avoid some warnings with Borland C (Tom Tanner) +- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant) +- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant) +- allow several arguments to configure (Tim Mooney, Frodo Looijaard) +- use libdir and includedir in Makefile.in (Tim Mooney) +- support shared libraries on OSF1 V4 (Tim Mooney) +- remove so_locations in "make clean" (Tim Mooney) +- fix maketree.c compilation error (Glenn, Mark) +- Python interface to zlib now in Python 1.5 (Jeremy Hylton) +- new Makefile.riscos (Rich Walker) +- initialize static descriptors in trees.c for embedded targets (Nick Smith) +- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith) +- add the OS/2 files in Makefile.in too (Andrew Zabolotny) +- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane) +- fix maketree.c to allow clean compilation of inffixed.h (Mark) +- fix parameter check in deflateCopy (Gunther Nikl) +- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler) +- Many portability patches by Christian Spieler: + . zutil.c, zutil.h: added "const" for zmem* + . Make_vms.com: fixed some typos + . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists + . msdos/Makefile.msc: remove "default rtl link library" info from obj files + . msdos/Makefile.*: use model-dependent name for the built zlib library + . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc: + new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT) +- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane) +- replace __far with _far for better portability (Christian Spieler, Tom Lane) +- fix test for errno.h in configure (Tim Newsham) + +Changes in 1.1.2 (19 March 98) +- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant) + See http://www.winimage.com/zLibDll/unzip.html +- preinitialize the inflate tables for fixed codes, to make the code + completely thread safe (Mark) +- some simplifications and slight speed-up to the inflate code (Mark) +- fix gzeof on non-compressed files (Allan Schrum) +- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs) +- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn) +- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny) +- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori) +- do not wrap extern "C" around system includes (Tom Lane) +- mention zlib binding for TCL in README (Andreas Kupries) +- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert) +- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson) +- allow "configure --prefix $HOME" (Tim Mooney) +- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson) +- move Makefile.sas to amiga/Makefile.sas + +Changes in 1.1.1 (27 Feb 98) +- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson) +- remove block truncation heuristic which had very marginal effect for zlib + (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the + compression ratio on some files. This also allows inlining _tr_tally for + matches in deflate_slow. +- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) + +Changes in 1.1.0 (24 Feb 98) +- do not return STREAM_END prematurely in inflate (John Bowler) +- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler) +- compile with -DFASTEST to get compression code optimized for speed only +- in minigzip, try mmap'ing the input file first (Miguel Albrecht) +- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain + on Sun but significant on HP) + +- add a pointer to experimental unzip library in README (Gilles Vollant) +- initialize variable gcc in configure (Chris Herborth) + +Changes in 1.0.9 (17 Feb 1998) +- added gzputs and gzgets functions +- do not clear eof flag in gzseek (Mark Diekhans) +- fix gzseek for files in transparent mode (Mark Diekhans) +- do not assume that vsprintf returns the number of bytes written (Jens Krinke) +- replace EXPORT with ZEXPORT to avoid conflict with other programs +- added compress2 in zconf.h, zlib.def, zlib.dnt +- new asm code from Gilles Vollant in contrib/asm386 +- simplify the inflate code (Mark): + . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new() + . ZALLOC the length list in inflate_trees_fixed() instead of using stack + . ZALLOC the value area for huft_build() instead of using stack + . Simplify Z_FINISH check in inflate() + +- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 +- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) +- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with + the declaration of FAR (Gilles VOllant) +- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) +- read_buf buf parameter of type Bytef* instead of charf* +- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) +- do not redeclare unlink in minigzip.c for WIN32 (John Bowler) +- fix check for presence of directories in "make install" (Ian Willis) + +Changes in 1.0.8 (27 Jan 1998) +- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant) +- fix gzgetc and gzputc for big endian systems (Markus Oberhumer) +- added compress2() to allow setting the compression level +- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) +- use constant arrays for the static trees in trees.c instead of computing + them at run time (thanks to Ken Raeburn for this suggestion). To create + trees.h, compile with GEN_TREES_H and run "make test". +- check return code of example in "make test" and display result +- pass minigzip command line options to file_compress +- simplifying code of inflateSync to avoid gcc 2.8 bug + +- support CC="gcc -Wall" in configure -s (QingLong) +- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn) +- fix test for shared library support to avoid compiler warnings +- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant) +- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit) +- do not use fdopen for Metrowerks on Mac (Brad Pettit)) +- add checks for gzputc and gzputc in example.c +- avoid warnings in gzio.c and deflate.c (Andreas Kleinert) +- use const for the CRC table (Ken Raeburn) +- fixed "make uninstall" for shared libraries +- use Tracev instead of Trace in infblock.c +- in example.c use correct compressed length for test_sync +- suppress +vnocompatwarnings in configure for HPUX (not always supported) + +Changes in 1.0.7 (20 Jan 1998) +- fix gzseek which was broken in write mode +- return error for gzseek to negative absolute position +- fix configure for Linux (Chun-Chung Chen) +- increase stack space for MSC (Tim Wegner) +- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant) +- define EXPORTVA for gzprintf (Gilles Vollant) +- added man page zlib.3 (Rick Rodgers) +- for contrib/untgz, fix makedir() and improve Makefile + +- check gzseek in write mode in example.c +- allocate extra buffer for seeks only if gzseek is actually called +- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant) +- add inflateSyncPoint in zconf.h +- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def + +Changes in 1.0.6 (19 Jan 1998) +- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and + gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) +- Fix a deflate bug occurring only with compression level 0 (thanks to + Andy Buckler for finding this one). +- In minigzip, pass transparently also the first byte for .Z files. +- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() +- check Z_FINISH in inflate (thanks to Marc Schluper) +- Implement deflateCopy (thanks to Adam Costello) +- make static libraries by default in configure, add --shared option. +- move MSDOS or Windows specific files to directory msdos +- suppress the notion of partial flush to simplify the interface + (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) +- suppress history buffer provided by application to simplify the interface + (this feature was not implemented anyway in 1.0.4) +- next_in and avail_in must be initialized before calling inflateInit or + inflateInit2 +- add EXPORT in all exported functions (for Windows DLL) +- added Makefile.nt (thanks to Stephen Williams) +- added the unsupported "contrib" directory: + contrib/asm386/ by Gilles Vollant + 386 asm code replacing longest_match(). + contrib/iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + contrib/iostream2/ by Tyge Løvset + Another C++ I/O streams interface + contrib/untgz/ by "Pedro A. Aranda Guti\irrez" + A very simple tar.gz file extractor using zlib + contrib/visual-basic.txt by Carlos Rios + How to use compress(), uncompress() and the gz* functions from VB. +- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression + level) in minigzip (thanks to Tom Lane) + +- use const for rommable constants in deflate +- added test for gzseek and gztell in example.c +- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) +- add undocumented function zError to convert error code to string + (for Tim Smithers) +- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. +- Use default memcpy for Symantec MSDOS compiler. +- Add EXPORT keyword for check_func (needed for Windows DLL) +- add current directory to LD_LIBRARY_PATH for "make test" +- create also a link for libz.so.1 +- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura) +- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX) +- added -soname for Linux in configure (Chun-Chung Chen, +- assign numbers to the exported functions in zlib.def (for Windows DLL) +- add advice in zlib.h for best usage of deflateSetDictionary +- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn) +- allow compilation with ANSI keywords only enabled for TurboC in large model +- avoid "versionString"[0] (Borland bug) +- add NEED_DUMMY_RETURN for Borland +- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). +- allow compilation with CC +- defined STDC for OS/2 (David Charlap) +- limit external names to 8 chars for MVS (Thomas Lund) +- in minigzip.c, use static buffers only for 16-bit systems +- fix suffix check for "minigzip -d foo.gz" +- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee) +- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) +- added makelcc.bat for lcc-win32 (Tom St Denis) +- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) +- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. +- check for unistd.h in configure (for off_t) +- remove useless check parameter in inflate_blocks_free +- avoid useless assignment of s->check to itself in inflate_blocks_new +- do not flush twice in gzclose (thanks to Ken Raeburn) +- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h +- use NO_ERRNO_H instead of enumeration of operating systems with errno.h +- work around buggy fclose on pipes for HP/UX +- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson) +- fix configure if CC is already equal to gcc + +Changes in 1.0.5 (3 Jan 98) +- Fix inflate to terminate gracefully when fed corrupted or invalid data +- Use const for rommable constants in inflate +- Eliminate memory leaks on error conditions in inflate +- Removed some vestigial code in inflate +- Update web address in README + +Changes in 1.0.4 (24 Jul 96) +- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF + bit, so the decompressor could decompress all the correct data but went + on to attempt decompressing extra garbage data. This affected minigzip too. +- zlibVersion and gzerror return const char* (needed for DLL) +- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) +- use z_error only for DEBUG (avoid problem with DLLs) + +Changes in 1.0.3 (2 Jul 96) +- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS + small and medium models; this makes the library incompatible with previous + versions for these models. (No effect in large model or on other systems.) +- return OK instead of BUF_ERROR if previous deflate call returned with + avail_out as zero but there is nothing to do +- added memcmp for non STDC compilers +- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly) +- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO) +- better check for 16-bit mode MSC (avoids problem with Symantec) + +Changes in 1.0.2 (23 May 96) +- added Windows DLL support +- added a function zlibVersion (for the DLL support) +- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model) +- Bytef is define's instead of typedef'd only for Borland C +- avoid reading uninitialized memory in example.c +- mention in README that the zlib format is now RFC1950 +- updated Makefile.dj2 +- added algorithm.doc + +Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion] +- fix array overlay in deflate.c which sometimes caused bad compressed data +- fix inflate bug with empty stored block +- fix MSDOS medium model which was broken in 0.99 +- fix deflateParams() which could generate bad compressed data. +- Bytef is define'd instead of typedef'ed (work around Borland bug) +- added an INDEX file +- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), + Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas) +- speed up adler32 for modern machines without auto-increment +- added -ansi for IRIX in configure +- static_init_done in trees.c is an int +- define unlink as delete for VMS +- fix configure for QNX +- add configure branch for SCO and HPUX +- avoid many warnings (unused variables, dead assignments, etc...) +- no fdopen for BeOS +- fix the Watcom fix for 32 bit mode (define FAR as empty) +- removed redefinition of Byte for MKWERKS +- work around an MWKERKS bug (incorrect merge of all .h files) + +Changes in 0.99 (27 Jan 96) +- allow preset dictionary shared between compressor and decompressor +- allow compression level 0 (no compression) +- add deflateParams in zlib.h: allow dynamic change of compression level + and compression strategy. +- test large buffers and deflateParams in example.c +- add optional "configure" to build zlib as a shared library +- suppress Makefile.qnx, use configure instead +- fixed deflate for 64-bit systems (detected on Cray) +- fixed inflate_blocks for 64-bit systems (detected on Alpha) +- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2) +- always return Z_BUF_ERROR when deflate() has nothing to do +- deflateInit and inflateInit are now macros to allow version checking +- prefix all global functions and types with z_ with -DZ_PREFIX +- make falloc completely reentrant (inftrees.c) +- fixed very unlikely race condition in ct_static_init +- free in reverse order of allocation to help memory manager +- use zlib-1.0/* instead of zlib/* inside the tar.gz +- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith + -Wconversion -Wstrict-prototypes -Wmissing-prototypes" +- allow gzread on concatenated .gz files +- deflateEnd now returns Z_DATA_ERROR if it was premature +- deflate is finally (?) fully deterministic (no matches beyond end of input) +- Document Z_SYNC_FLUSH +- add uninstall in Makefile +- Check for __cpluplus in zlib.h +- Better test in ct_align for partial flush +- avoid harmless warnings for Borland C++ +- initialize hash_head in deflate.c +- avoid warning on fdopen (gzio.c) for HP cc -Aa +- include stdlib.h for STDC compilers +- include errno.h for Cray +- ignore error if ranlib doesn't exist +- call ranlib twice for NeXTSTEP +- use exec_prefix instead of prefix for libz.a +- renamed ct_* as _tr_* to avoid conflict with applications +- clear z->msg in inflateInit2 before any error return +- initialize opaque in example.c, gzio.c, deflate.c and inflate.c +- fixed typo in zconf.h (_GNUC__ => __GNUC__) +- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode) +- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) +- in fcalloc, normalize pointer if size > 65520 bytes +- don't use special fcalloc for 32 bit Borland C++ +- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... +- use Z_BINARY instead of BINARY +- document that gzclose after gzdopen will close the file +- allow "a" as mode in gzopen. +- fix error checking in gzread +- allow skipping .gz extra-field on pipes +- added reference to Perl interface in README +- put the crc table in FAR data (I dislike more and more the medium model :) +- added get_crc_table +- added a dimension to all arrays (Borland C can't count). +- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast +- guard against multiple inclusion of *.h (for precompiled header on Mac) +- Watcom C pretends to be Microsoft C small model even in 32 bit mode. +- don't use unsized arrays to avoid silly warnings by Visual C++: + warning C4746: 'inflate_mask' : unsized array treated as '__far' + (what's wrong with far data in far model?). +- define enum out of inflate_blocks_state to allow compilation with C++ + +Changes in 0.95 (16 Aug 95) +- fix MSDOS small and medium model (now easier to adapt to any compiler) +- inlined send_bits +- fix the final (:-) bug for deflate with flush (output was correct but + not completely flushed in rare occasions). +- default window size is same for compression and decompression + (it's now sufficient to set MAX_WBITS in zconf.h). +- voidp -> voidpf and voidnp -> voidp (for consistency with other + typedefs and because voidnp was not near in large model). + +Changes in 0.94 (13 Aug 95) +- support MSDOS medium model +- fix deflate with flush (could sometimes generate bad output) +- fix deflateReset (zlib header was incorrectly suppressed) +- added support for VMS +- allow a compression level in gzopen() +- gzflush now calls fflush +- For deflate with flush, flush even if no more input is provided. +- rename libgz.a as libz.a +- avoid complex expression in infcodes.c triggering Turbo C bug +- work around a problem with gcc on Alpha (in INSERT_STRING) +- don't use inline functions (problem with some gcc versions) +- allow renaming of Byte, uInt, etc... with #define. +- avoid warning about (unused) pointer before start of array in deflate.c +- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c +- avoid reserved word 'new' in trees.c + +Changes in 0.93 (25 June 95) +- temporarily disable inline functions +- make deflate deterministic +- give enough lookahead for PARTIAL_FLUSH +- Set binary mode for stdin/stdout in minigzip.c for OS/2 +- don't even use signed char in inflate (not portable enough) +- fix inflate memory leak for segmented architectures + +Changes in 0.92 (3 May 95) +- don't assume that char is signed (problem on SGI) +- Clear bit buffer when starting a stored block +- no memcpy on Pyramid +- suppressed inftest.c +- optimized fill_window, put longest_match inline for gcc +- optimized inflate on stored blocks. +- untabify all sources to simplify patches + +Changes in 0.91 (2 May 95) +- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h +- Document the memory requirements in zconf.h +- added "make install" +- fix sync search logic in inflateSync +- deflate(Z_FULL_FLUSH) now works even if output buffer too short +- after inflateSync, don't scare people with just "lo world" +- added support for DJGPP + +Changes in 0.9 (1 May 95) +- don't assume that zalloc clears the allocated memory (the TurboC bug + was Mark's bug after all :) +- let again gzread copy uncompressed data unchanged (was working in 0.71) +- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented +- added a test of inflateSync in example.c +- moved MAX_WBITS to zconf.h because users might want to change that. +- document explicitly that zalloc(64K) on MSDOS must return a normalized + pointer (zero offset) +- added Makefiles for Microsoft C, Turbo C, Borland C++ +- faster crc32() + +Changes in 0.8 (29 April 95) +- added fast inflate (inffast.c) +- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this + is incompatible with previous versions of zlib which returned Z_OK. +- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) + (actually that was not a compiler bug, see 0.81 above) +- gzread no longer reads one extra byte in certain cases +- In gzio destroy(), don't reference a freed structure +- avoid many warnings for MSDOS +- avoid the ERROR symbol which is used by MS Windows + +Changes in 0.71 (14 April 95) +- Fixed more MSDOS compilation problems :( There is still a bug with + TurboC large model. + +Changes in 0.7 (14 April 95) +- Added full inflate support. +- Simplified the crc32() interface. The pre- and post-conditioning + (one's complement) is now done inside crc32(). WARNING: this is + incompatible with previous versions; see zlib.h for the new usage. + +Changes in 0.61 (12 April 95) +- workaround for a bug in TurboC. example and minigzip now work on MSDOS. + +Changes in 0.6 (11 April 95) +- added minigzip.c +- added gzdopen to reopen a file descriptor as gzFile +- added transparent reading of non-gziped files in gzread. +- fixed bug in gzread (don't read crc as data) +- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). +- don't allocate big arrays in the stack (for MSDOS) +- fix some MSDOS compilation problems + +Changes in 0.5: +- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but + not yet Z_FULL_FLUSH. +- support decompression but only in a single step (forced Z_FINISH) +- added opaque object for zalloc and zfree. +- added deflateReset and inflateReset +- added a variable zlib_version for consistency checking. +- renamed the 'filter' parameter of deflateInit2 as 'strategy'. + Added Z_FILTERED and Z_HUFFMAN_ONLY constants. + +Changes in 0.4: +- avoid "zip" everywhere, use zlib instead of ziplib. +- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush + if compression method == 8. +- added adler32 and crc32 +- renamed deflateOptions as deflateInit2, call one or the other but not both +- added the method parameter for deflateInit2. +- added inflateInit2 +- simplied considerably deflateInit and inflateInit by not supporting + user-provided history buffer. This is supported only in deflateInit2 + and inflateInit2. + +Changes in 0.3: +- prefix all macro names with Z_ +- use Z_FINISH instead of deflateEnd to finish compression. +- added Z_HUFFMAN_ONLY +- added gzerror() diff --git a/zlib-1.2.11/FAQ b/zlib-1.2.11/FAQ new file mode 100644 index 00000000..99b7cf92 --- /dev/null +++ b/zlib-1.2.11/FAQ @@ -0,0 +1,368 @@ + + Frequently Asked Questions about zlib + + +If your question is not there, please check the zlib home page +http://zlib.net/ which may have more recent information. +The lastest zlib FAQ is at http://zlib.net/zlib_faq.html + + + 1. Is zlib Y2K-compliant? + + Yes. zlib doesn't handle dates. + + 2. Where can I get a Windows DLL version? + + The zlib sources can be compiled without change to produce a DLL. See the + file win32/DLL_FAQ.txt in the zlib distribution. Pointers to the + precompiled DLL are found in the zlib web site at http://zlib.net/ . + + 3. Where can I get a Visual Basic interface to zlib? + + See + * http://marknelson.us/1997/01/01/zlib-engine/ + * win32/DLL_FAQ.txt in the zlib distribution + + 4. compress() returns Z_BUF_ERROR. + + Make sure that before the call of compress(), the length of the compressed + buffer is equal to the available size of the compressed buffer and not + zero. For Visual Basic, check that this parameter is passed by reference + ("as any"), not by value ("as long"). + + 5. deflate() or inflate() returns Z_BUF_ERROR. + + Before making the call, make sure that avail_in and avail_out are not zero. + When setting the parameter flush equal to Z_FINISH, also make sure that + avail_out is big enough to allow processing all pending input. Note that a + Z_BUF_ERROR is not fatal--another call to deflate() or inflate() can be + made with more input or output space. A Z_BUF_ERROR may in fact be + unavoidable depending on how the functions are used, since it is not + possible to tell whether or not there is more output pending when + strm.avail_out returns with zero. See http://zlib.net/zlib_how.html for a + heavily annotated example. + + 6. Where's the zlib documentation (man pages, etc.)? + + It's in zlib.h . Examples of zlib usage are in the files test/example.c + and test/minigzip.c, with more in examples/ . + + 7. Why don't you use GNU autoconf or libtool or ...? + + Because we would like to keep zlib as a very small and simple package. + zlib is rather portable and doesn't need much configuration. + + 8. I found a bug in zlib. + + Most of the time, such problems are due to an incorrect usage of zlib. + Please try to reproduce the problem with a small program and send the + corresponding source to us at zlib@gzip.org . Do not send multi-megabyte + data files without prior agreement. + + 9. Why do I get "undefined reference to gzputc"? + + If "make test" produces something like + + example.o(.text+0x154): undefined reference to `gzputc' + + check that you don't have old files libz.* in /usr/lib, /usr/local/lib or + /usr/X11R6/lib. Remove any old versions, then do "make install". + +10. I need a Delphi interface to zlib. + + See the contrib/delphi directory in the zlib distribution. + +11. Can zlib handle .zip archives? + + Not by itself, no. See the directory contrib/minizip in the zlib + distribution. + +12. Can zlib handle .Z files? + + No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt + the code of uncompress on your own. + +13. How can I make a Unix shared library? + + By default a shared (and a static) library is built for Unix. So: + + make distclean + ./configure + make + +14. How do I install a shared zlib library on Unix? + + After the above, then: + + make install + + However, many flavors of Unix come with a shared zlib already installed. + Before going to the trouble of compiling a shared version of zlib and + trying to install it, you may want to check if it's already there! If you + can #include , it's there. The -lz option will probably link to + it. You can check the version at the top of zlib.h or with the + ZLIB_VERSION symbol defined in zlib.h . + +15. I have a question about OttoPDF. + + We are not the authors of OttoPDF. The real author is on the OttoPDF web + site: Joel Hainley, jhainley@myndkryme.com. + +16. Can zlib decode Flate data in an Adobe PDF file? + + Yes. See http://www.pdflib.com/ . To modify PDF forms, see + http://sourceforge.net/projects/acroformtool/ . + +17. Why am I getting this "register_frame_info not found" error on Solaris? + + After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib + generates an error such as: + + ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so: + symbol __register_frame_info: referenced symbol not found + + The symbol __register_frame_info is not part of zlib, it is generated by + the C compiler (cc or gcc). You must recompile applications using zlib + which have this problem. This problem is specific to Solaris. See + http://www.sunfreeware.com for Solaris versions of zlib and applications + using zlib. + +18. Why does gzip give an error on a file I make with compress/deflate? + + The compress and deflate functions produce data in the zlib format, which + is different and incompatible with the gzip format. The gz* functions in + zlib on the other hand use the gzip format. Both the zlib and gzip formats + use the same compressed data format internally, but have different headers + and trailers around the compressed data. + +19. Ok, so why are there two different formats? + + The gzip format was designed to retain the directory information about a + single file, such as the name and last modification date. The zlib format + on the other hand was designed for in-memory and communication channel + applications, and has a much more compact header and trailer and uses a + faster integrity check than gzip. + +20. Well that's nice, but how do I make a gzip file in memory? + + You can request that deflate write the gzip format instead of the zlib + format using deflateInit2(). You can also request that inflate decode the + gzip format using inflateInit2(). Read zlib.h for more details. + +21. Is zlib thread-safe? + + Yes. However any library routines that zlib uses and any application- + provided memory allocation routines must also be thread-safe. zlib's gz* + functions use stdio library routines, and most of zlib's functions use the + library memory allocation routines by default. zlib's *Init* functions + allow for the application to provide custom memory allocation routines. + + Of course, you should only operate on any given zlib or gzip stream from a + single thread at a time. + +22. Can I use zlib in my commercial application? + + Yes. Please read the license in zlib.h. + +23. Is zlib under the GNU license? + + No. Please read the license in zlib.h. + +24. The license says that altered source versions must be "plainly marked". So + what exactly do I need to do to meet that requirement? + + You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In + particular, the final version number needs to be changed to "f", and an + identification string should be appended to ZLIB_VERSION. Version numbers + x.x.x.f are reserved for modifications to zlib by others than the zlib + maintainers. For example, if the version of the base zlib you are altering + is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and + ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also + update the version strings in deflate.c and inftrees.c. + + For altered source distributions, you should also note the origin and + nature of the changes in zlib.h, as well as in ChangeLog and README, along + with the dates of the alterations. The origin should include at least your + name (or your company's name), and an email address to contact for help or + issues with the library. + + Note that distributing a compiled zlib library along with zlib.h and + zconf.h is also a source distribution, and so you should change + ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes + in zlib.h as you would for a full source distribution. + +25. Will zlib work on a big-endian or little-endian architecture, and can I + exchange compressed data between them? + + Yes and yes. + +26. Will zlib work on a 64-bit machine? + + Yes. It has been tested on 64-bit machines, and has no dependence on any + data types being limited to 32-bits in length. If you have any + difficulties, please provide a complete problem report to zlib@gzip.org + +27. Will zlib decompress data from the PKWare Data Compression Library? + + No. The PKWare DCL uses a completely different compressed data format than + does PKZIP and zlib. However, you can look in zlib's contrib/blast + directory for a possible solution to your problem. + +28. Can I access data randomly in a compressed stream? + + No, not without some preparation. If when compressing you periodically use + Z_FULL_FLUSH, carefully write all the pending data at those points, and + keep an index of those locations, then you can start decompression at those + points. You have to be careful to not use Z_FULL_FLUSH too often, since it + can significantly degrade compression. Alternatively, you can scan a + deflate stream once to generate an index, and then use that index for + random access. See examples/zran.c . + +29. Does zlib work on MVS, OS/390, CICS, etc.? + + It has in the past, but we have not heard of any recent evidence. There + were working ports of zlib 1.1.4 to MVS, but those links no longer work. + If you know of recent, successful applications of zlib on these operating + systems, please let us know. Thanks. + +30. Is there some simpler, easier to read version of inflate I can look at to + understand the deflate format? + + First off, you should read RFC 1951. Second, yes. Look in zlib's + contrib/puff directory. + +31. Does zlib infringe on any patents? + + As far as we know, no. In fact, that was originally the whole point behind + zlib. Look here for some more information: + + http://www.gzip.org/#faq11 + +32. Can zlib work with greater than 4 GB of data? + + Yes. inflate() and deflate() will process any amount of data correctly. + Each call of inflate() or deflate() is limited to input and output chunks + of the maximum value that can be stored in the compiler's "unsigned int" + type, but there is no limit to the number of chunks. Note however that the + strm.total_in and strm_total_out counters may be limited to 4 GB. These + counters are provided as a convenience and are not used internally by + inflate() or deflate(). The application can easily set up its own counters + updated after each call of inflate() or deflate() to count beyond 4 GB. + compress() and uncompress() may be limited to 4 GB, since they operate in a + single call. gzseek() and gztell() may be limited to 4 GB depending on how + zlib is compiled. See the zlibCompileFlags() function in zlib.h. + + The word "may" appears several times above since there is a 4 GB limit only + if the compiler's "long" type is 32 bits. If the compiler's "long" type is + 64 bits, then the limit is 16 exabytes. + +33. Does zlib have any security vulnerabilities? + + The only one that we are aware of is potentially in gzprintf(). If zlib is + compiled to use sprintf() or vsprintf(), then there is no protection + against a buffer overflow of an 8K string space (or other value as set by + gzbuffer()), other than the caller of gzprintf() assuring that the output + will not exceed 8K. On the other hand, if zlib is compiled to use + snprintf() or vsnprintf(), which should normally be the case, then there is + no vulnerability. The ./configure script will display warnings if an + insecure variation of sprintf() will be used by gzprintf(). Also the + zlibCompileFlags() function will return information on what variant of + sprintf() is used by gzprintf(). + + If you don't have snprintf() or vsnprintf() and would like one, you can + find a portable implementation here: + + http://www.ijs.si/software/snprintf/ + + Note that you should be using the most recent version of zlib. Versions + 1.1.3 and before were subject to a double-free vulnerability, and versions + 1.2.1 and 1.2.2 were subject to an access exception when decompressing + invalid compressed data. + +34. Is there a Java version of zlib? + + Probably what you want is to use zlib in Java. zlib is already included + as part of the Java SDK in the java.util.zip package. If you really want + a version of zlib written in the Java language, look on the zlib home + page for links: http://zlib.net/ . + +35. I get this or that compiler or source-code scanner warning when I crank it + up to maximally-pedantic. Can't you guys write proper code? + + Many years ago, we gave up attempting to avoid warnings on every compiler + in the universe. It just got to be a waste of time, and some compilers + were downright silly as well as contradicted each other. So now, we simply + make sure that the code always works. + +36. Valgrind (or some similar memory access checker) says that deflate is + performing a conditional jump that depends on an uninitialized value. + Isn't that a bug? + + No. That is intentional for performance reasons, and the output of deflate + is not affected. This only started showing up recently since zlib 1.2.x + uses malloc() by default for allocations, whereas earlier versions used + calloc(), which zeros out the allocated memory. Even though the code was + correct, versions 1.2.4 and later was changed to not stimulate these + checkers. + +37. Will zlib read the (insert any ancient or arcane format here) compressed + data format? + + Probably not. Look in the comp.compression FAQ for pointers to various + formats and associated software. + +38. How can I encrypt/decrypt zip files with zlib? + + zlib doesn't support encryption. The original PKZIP encryption is very + weak and can be broken with freely available programs. To get strong + encryption, use GnuPG, http://www.gnupg.org/ , which already includes zlib + compression. For PKZIP compatible "encryption", look at + http://www.info-zip.org/ + +39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? + + "gzip" is the gzip format, and "deflate" is the zlib format. They should + probably have called the second one "zlib" instead to avoid confusion with + the raw deflate compressed data format. While the HTTP 1.1 RFC 2616 + correctly points to the zlib specification in RFC 1950 for the "deflate" + transfer encoding, there have been reports of servers and browsers that + incorrectly produce or expect raw deflate data per the deflate + specification in RFC 1951, most notably Microsoft. So even though the + "deflate" transfer encoding using the zlib format would be the more + efficient approach (and in fact exactly what the zlib format was designed + for), using the "gzip" transfer encoding is probably more reliable due to + an unfortunate choice of name on the part of the HTTP 1.1 authors. + + Bottom line: use the gzip format for HTTP 1.1 encoding. + +40. Does zlib support the new "Deflate64" format introduced by PKWare? + + No. PKWare has apparently decided to keep that format proprietary, since + they have not documented it as they have previous compression formats. In + any case, the compression improvements are so modest compared to other more + modern approaches, that it's not worth the effort to implement. + +41. I'm having a problem with the zip functions in zlib, can you help? + + There are no zip functions in zlib. You are probably using minizip by + Giles Vollant, which is found in the contrib directory of zlib. It is not + part of zlib. In fact none of the stuff in contrib is part of zlib. The + files in there are not supported by the zlib authors. You need to contact + the authors of the respective contribution for help. + +42. The match.asm code in contrib is under the GNU General Public License. + Since it's part of zlib, doesn't that mean that all of zlib falls under the + GNU GPL? + + No. The files in contrib are not part of zlib. They were contributed by + other authors and are provided as a convenience to the user within the zlib + distribution. Each item in contrib has its own license. + +43. Is zlib subject to export controls? What is its ECCN? + + zlib is not subject to export controls, and so is classified as EAR99. + +44. Can you please sign these lengthy legal documents and fax them back to us + so that we can use your software in our product? + + No. Go away. Shoo. diff --git a/zlib-1.2.11/INDEX b/zlib-1.2.11/INDEX new file mode 100644 index 00000000..2ba06412 --- /dev/null +++ b/zlib-1.2.11/INDEX @@ -0,0 +1,68 @@ +CMakeLists.txt cmake build file +ChangeLog history of changes +FAQ Frequently Asked Questions about zlib +INDEX this file +Makefile dummy Makefile that tells you to ./configure +Makefile.in template for Unix Makefile +README guess what +configure configure script for Unix +make_vms.com makefile for VMS +test/example.c zlib usages examples for build testing +test/minigzip.c minimal gzip-like functionality for build testing +test/infcover.c inf*.c code coverage for build coverage testing +treebuild.xml XML description of source file dependencies +zconf.h.cmakein zconf.h template for cmake +zconf.h.in zconf.h template for configure +zlib.3 Man page for zlib +zlib.3.pdf Man page in PDF format +zlib.map Linux symbol information +zlib.pc.in Template for pkg-config descriptor +zlib.pc.cmakein zlib.pc template for cmake +zlib2ansi perl script to convert source files for C++ compilation + +amiga/ makefiles for Amiga SAS C +as400/ makefiles for AS/400 +doc/ documentation for formats and algorithms +msdos/ makefiles for MSDOS +nintendods/ makefile for Nintendo DS +old/ makefiles for various architectures and zlib documentation + files that have not yet been updated for zlib 1.2.x +qnx/ makefiles for QNX +watcom/ makefiles for OpenWatcom +win32/ makefiles for Windows + + zlib public header files (required for library use): +zconf.h +zlib.h + + private source files used to build the zlib library: +adler32.c +compress.c +crc32.c +crc32.h +deflate.c +deflate.h +gzclose.c +gzguts.h +gzlib.c +gzread.c +gzwrite.c +infback.c +inffast.c +inffast.h +inffixed.h +inflate.c +inflate.h +inftrees.c +inftrees.h +trees.c +trees.h +uncompr.c +zutil.c +zutil.h + + source files for sample programs +See examples/README.examples + + unsupported contributions by third parties +See contrib/README.contrib diff --git a/zlib-1.2.11/Makefile b/zlib-1.2.11/Makefile new file mode 100644 index 00000000..6bba86c7 --- /dev/null +++ b/zlib-1.2.11/Makefile @@ -0,0 +1,5 @@ +all: + -@echo "Please use ./configure first. Thank you." + +distclean: + make -f Makefile.in distclean diff --git a/zlib-1.2.11/Makefile.in b/zlib-1.2.11/Makefile.in new file mode 100644 index 00000000..5a77949f --- /dev/null +++ b/zlib-1.2.11/Makefile.in @@ -0,0 +1,410 @@ +# Makefile for zlib +# Copyright (C) 1995-2017 Jean-loup Gailly, Mark Adler +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile and test, type: +# ./configure; make test +# Normally configure builds both a static and a shared library. +# If you want to build just a static library, use: ./configure --static + +# To use the asm code, type: +# cp contrib/asm?86/match.S ./match.S +# make LOC=-DASMV OBJA=match.o + +# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type: +# make install +# To install in $HOME instead of /usr/local, use: +# make install prefix=$HOME + +CC=cc + +CFLAGS=-O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-g -DZLIB_DEBUG +#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ +# -Wstrict-prototypes -Wmissing-prototypes + +SFLAGS=-O +LDFLAGS= +TEST_LDFLAGS=-L. libz.a +LDSHARED=$(CC) +CPP=$(CC) -E + +STATICLIB=libz.a +SHAREDLIB=libz.so +SHAREDLIBV=libz.so.1.2.11 +SHAREDLIBM=libz.so.1 +LIBS=$(STATICLIB) $(SHAREDLIBV) + +AR=ar +ARFLAGS=rc +RANLIB=ranlib +LDCONFIG=ldconfig +LDSHAREDLIBC=-lc +TAR=tar +SHELL=/bin/sh +EXE= + +prefix = /usr/local +exec_prefix = ${prefix} +libdir = ${exec_prefix}/lib +sharedlibdir = ${libdir} +includedir = ${prefix}/include +mandir = ${prefix}/share/man +man3dir = ${mandir}/man3 +pkgconfigdir = ${libdir}/pkgconfig +SRCDIR= +ZINC= +ZINCOUT=-I. + +OBJZ = adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o +OBJG = compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o +OBJC = $(OBJZ) $(OBJG) + +PIC_OBJZ = adler32.lo crc32.lo deflate.lo infback.lo inffast.lo inflate.lo inftrees.lo trees.lo zutil.lo +PIC_OBJG = compress.lo uncompr.lo gzclose.lo gzlib.lo gzread.lo gzwrite.lo +PIC_OBJC = $(PIC_OBJZ) $(PIC_OBJG) + +# to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo +OBJA = +PIC_OBJA = + +OBJS = $(OBJC) $(OBJA) + +PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA) + +all: static shared + +static: example$(EXE) minigzip$(EXE) + +shared: examplesh$(EXE) minigzipsh$(EXE) + +all64: example64$(EXE) minigzip64$(EXE) + +check: test + +test: all teststatic testshared + +teststatic: static + @TMPST=tmpst_$$; \ + if echo hello world | ./minigzip | ./minigzip -d && ./example $$TMPST ; then \ + echo ' *** zlib test OK ***'; \ + else \ + echo ' *** zlib test FAILED ***'; false; \ + fi; \ + rm -f $$TMPST + +testshared: shared + @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ + LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \ + DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ + SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ + TMPSH=tmpsh_$$; \ + if echo hello world | ./minigzipsh | ./minigzipsh -d && ./examplesh $$TMPSH; then \ + echo ' *** zlib shared test OK ***'; \ + else \ + echo ' *** zlib shared test FAILED ***'; false; \ + fi; \ + rm -f $$TMPSH + +test64: all64 + @TMP64=tmp64_$$; \ + if echo hello world | ./minigzip64 | ./minigzip64 -d && ./example64 $$TMP64; then \ + echo ' *** zlib 64-bit test OK ***'; \ + else \ + echo ' *** zlib 64-bit test FAILED ***'; false; \ + fi; \ + rm -f $$TMP64 + +infcover.o: $(SRCDIR)test/infcover.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/infcover.c + +infcover: infcover.o libz.a + $(CC) $(CFLAGS) -o $@ infcover.o libz.a + +cover: infcover + rm -f *.gcda + ./infcover + gcov inf*.c + +libz.a: $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 + +match.o: match.S + $(CPP) match.S > _match.s + $(CC) -c _match.s + mv _match.o match.o + rm -f _match.s + +match.lo: match.S + $(CPP) match.S > _match.s + $(CC) -c -fPIC _match.s + mv _match.o match.lo + rm -f _match.s + +example.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/example.c + +minigzip.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/minigzip.c + +example64.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/example.c + +minigzip64.o: $(SRCDIR)test/minigzip.c $(SRCDIR)zlib.h zconf.h + $(CC) $(CFLAGS) $(ZINCOUT) -D_FILE_OFFSET_BITS=64 -c -o $@ $(SRCDIR)test/minigzip.c + + +adler32.o: $(SRCDIR)adler32.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)adler32.c + +crc32.o: $(SRCDIR)crc32.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)crc32.c + +deflate.o: $(SRCDIR)deflate.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)deflate.c + +infback.o: $(SRCDIR)infback.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)infback.c + +inffast.o: $(SRCDIR)inffast.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inffast.c + +inflate.o: $(SRCDIR)inflate.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inflate.c + +inftrees.o: $(SRCDIR)inftrees.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)inftrees.c + +trees.o: $(SRCDIR)trees.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)trees.c + +zutil.o: $(SRCDIR)zutil.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)zutil.c + +compress.o: $(SRCDIR)compress.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)compress.c + +uncompr.o: $(SRCDIR)uncompr.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)uncompr.c + +gzclose.o: $(SRCDIR)gzclose.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzclose.c + +gzlib.o: $(SRCDIR)gzlib.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzlib.c + +gzread.o: $(SRCDIR)gzread.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzread.c + +gzwrite.o: $(SRCDIR)gzwrite.c + $(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)gzwrite.c + + +adler32.lo: $(SRCDIR)adler32.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/adler32.o $(SRCDIR)adler32.c + -@mv objs/adler32.o $@ + +crc32.lo: $(SRCDIR)crc32.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/crc32.o $(SRCDIR)crc32.c + -@mv objs/crc32.o $@ + +deflate.lo: $(SRCDIR)deflate.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/deflate.o $(SRCDIR)deflate.c + -@mv objs/deflate.o $@ + +infback.lo: $(SRCDIR)infback.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/infback.o $(SRCDIR)infback.c + -@mv objs/infback.o $@ + +inffast.lo: $(SRCDIR)inffast.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inffast.o $(SRCDIR)inffast.c + -@mv objs/inffast.o $@ + +inflate.lo: $(SRCDIR)inflate.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inflate.o $(SRCDIR)inflate.c + -@mv objs/inflate.o $@ + +inftrees.lo: $(SRCDIR)inftrees.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/inftrees.o $(SRCDIR)inftrees.c + -@mv objs/inftrees.o $@ + +trees.lo: $(SRCDIR)trees.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/trees.o $(SRCDIR)trees.c + -@mv objs/trees.o $@ + +zutil.lo: $(SRCDIR)zutil.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/zutil.o $(SRCDIR)zutil.c + -@mv objs/zutil.o $@ + +compress.lo: $(SRCDIR)compress.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/compress.o $(SRCDIR)compress.c + -@mv objs/compress.o $@ + +uncompr.lo: $(SRCDIR)uncompr.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/uncompr.o $(SRCDIR)uncompr.c + -@mv objs/uncompr.o $@ + +gzclose.lo: $(SRCDIR)gzclose.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzclose.o $(SRCDIR)gzclose.c + -@mv objs/gzclose.o $@ + +gzlib.lo: $(SRCDIR)gzlib.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzlib.o $(SRCDIR)gzlib.c + -@mv objs/gzlib.o $@ + +gzread.lo: $(SRCDIR)gzread.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzread.o $(SRCDIR)gzread.c + -@mv objs/gzread.o $@ + +gzwrite.lo: $(SRCDIR)gzwrite.c + -@mkdir objs 2>/dev/null || test -d objs + $(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/gzwrite.o $(SRCDIR)gzwrite.c + -@mv objs/gzwrite.o $@ + + +placebo $(SHAREDLIBV): $(PIC_OBJS) libz.a + $(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) $(LDSHAREDLIBC) $(LDFLAGS) + rm -f $(SHAREDLIB) $(SHAREDLIBM) + ln -s $@ $(SHAREDLIB) + ln -s $@ $(SHAREDLIBM) + -@rmdir objs + +example$(EXE): example.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ example.o $(TEST_LDFLAGS) + +minigzip$(EXE): minigzip.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ minigzip.o $(TEST_LDFLAGS) + +examplesh$(EXE): example.o $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV) + +minigzipsh$(EXE): minigzip.o $(SHAREDLIBV) + $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV) + +example64$(EXE): example64.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ example64.o $(TEST_LDFLAGS) + +minigzip64$(EXE): minigzip64.o $(STATICLIB) + $(CC) $(CFLAGS) -o $@ minigzip64.o $(TEST_LDFLAGS) + +install-libs: $(LIBS) + -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi + -@if [ ! -d $(DESTDIR)$(libdir) ]; then mkdir -p $(DESTDIR)$(libdir); fi + -@if [ ! -d $(DESTDIR)$(sharedlibdir) ]; then mkdir -p $(DESTDIR)$(sharedlibdir); fi + -@if [ ! -d $(DESTDIR)$(man3dir) ]; then mkdir -p $(DESTDIR)$(man3dir); fi + -@if [ ! -d $(DESTDIR)$(pkgconfigdir) ]; then mkdir -p $(DESTDIR)$(pkgconfigdir); fi + rm -f $(DESTDIR)$(libdir)/$(STATICLIB) + cp $(STATICLIB) $(DESTDIR)$(libdir) + chmod 644 $(DESTDIR)$(libdir)/$(STATICLIB) + -@($(RANLIB) $(DESTDIR)$(libdir)/libz.a || true) >/dev/null 2>&1 + -@if test -n "$(SHAREDLIBV)"; then \ + rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \ + cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir); \ + echo "cp $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)"; \ + chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV); \ + echo "chmod 755 $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBV)"; \ + rm -f $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ + ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIB); \ + ln -s $(SHAREDLIBV) $(DESTDIR)$(sharedlibdir)/$(SHAREDLIBM); \ + ($(LDCONFIG) || true) >/dev/null 2>&1; \ + fi + rm -f $(DESTDIR)$(man3dir)/zlib.3 + cp $(SRCDIR)zlib.3 $(DESTDIR)$(man3dir) + chmod 644 $(DESTDIR)$(man3dir)/zlib.3 + rm -f $(DESTDIR)$(pkgconfigdir)/zlib.pc + cp zlib.pc $(DESTDIR)$(pkgconfigdir) + chmod 644 $(DESTDIR)$(pkgconfigdir)/zlib.pc +# The ranlib in install is needed on NeXTSTEP which checks file times +# ldconfig is for Linux + +install: install-libs + -@if [ ! -d $(DESTDIR)$(includedir) ]; then mkdir -p $(DESTDIR)$(includedir); fi + rm -f $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h + cp $(SRCDIR)zlib.h zconf.h $(DESTDIR)$(includedir) + chmod 644 $(DESTDIR)$(includedir)/zlib.h $(DESTDIR)$(includedir)/zconf.h + +uninstall: + cd $(DESTDIR)$(includedir) && rm -f zlib.h zconf.h + cd $(DESTDIR)$(libdir) && rm -f libz.a; \ + if test -n "$(SHAREDLIBV)" -a -f $(SHAREDLIBV); then \ + rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \ + fi + cd $(DESTDIR)$(man3dir) && rm -f zlib.3 + cd $(DESTDIR)$(pkgconfigdir) && rm -f zlib.pc + +docs: zlib.3.pdf + +zlib.3.pdf: $(SRCDIR)zlib.3 + groff -mandoc -f H -T ps $(SRCDIR)zlib.3 | ps2pdf - $@ + +zconf.h.cmakein: $(SRCDIR)zconf.h.in + -@ TEMPFILE=zconfh_$$; \ + echo "/#define ZCONF_H/ a\\\\\n#cmakedefine Z_PREFIX\\\\\n#cmakedefine Z_HAVE_UNISTD_H\n" >> $$TEMPFILE &&\ + sed -f $$TEMPFILE $(SRCDIR)zconf.h.in > $@ &&\ + touch -r $(SRCDIR)zconf.h.in $@ &&\ + rm $$TEMPFILE + +zconf: $(SRCDIR)zconf.h.in + cp -p $(SRCDIR)zconf.h.in zconf.h + +mostlyclean: clean +clean: + rm -f *.o *.lo *~ \ + example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ + example64$(EXE) minigzip64$(EXE) \ + infcover \ + libz.* foo.gz so_locations \ + _match.s maketree contrib/infback9/*.o + rm -rf objs + rm -f *.gcda *.gcno *.gcov + rm -f contrib/infback9/*.gcda contrib/infback9/*.gcno contrib/infback9/*.gcov + +maintainer-clean: distclean +distclean: clean zconf zconf.h.cmakein docs + rm -f Makefile zlib.pc configure.log + -@rm -f .DS_Store + @if [ -f Makefile.in ]; then \ + printf 'all:\n\t-@echo "Please use ./configure first. Thank you."\n' > Makefile ; \ + printf '\ndistclean:\n\tmake -f Makefile.in distclean\n' >> Makefile ; \ + touch -r $(SRCDIR)Makefile.in Makefile ; fi + @if [ ! -f zconf.h.in ]; then rm -f zconf.h zconf.h.cmakein ; fi + @if [ ! -f zlib.3 ]; then rm -f zlib.3.pdf ; fi + +tags: + etags $(SRCDIR)*.[ch] + +adler32.o zutil.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +gzclose.o gzlib.o gzread.o gzwrite.o: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h +compress.o example.o minigzip.o uncompr.o: $(SRCDIR)zlib.h zconf.h +crc32.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h +deflate.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +infback.o inflate.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h +inffast.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h +inftrees.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h +trees.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h + +adler32.lo zutil.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +gzclose.lo gzlib.lo gzread.lo gzwrite.lo: $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h +compress.lo example.lo minigzip.lo uncompr.lo: $(SRCDIR)zlib.h zconf.h +crc32.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)crc32.h +deflate.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h +infback.lo inflate.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h $(SRCDIR)inffixed.h +inffast.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h +inftrees.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h +trees.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h diff --git a/zlib-1.2.11/README b/zlib-1.2.11/README new file mode 100644 index 00000000..51106de4 --- /dev/null +++ b/zlib-1.2.11/README @@ -0,0 +1,115 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.11 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and +rfc1952 (gzip format). + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file test/example.c which also tests that +the library is working correctly. Another example is given in the file +test/minigzip.c. The compression library itself is composed of all source +files in the root directory. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile.in. In short "./configure; make test", and if that goes +well, "make install" should work for most flavors of Unix. For Windows, use +one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use +make_vms.com. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://zlib.net/ . Before reporting a problem, please check this site to +verify that you have the latest version of zlib; otherwise get the latest +version and check whether the problem still exists or not. + +PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available at +http://marknelson.us/1997/01/01/zlib-engine/ . + +The changes made in version 1.2.11 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory contrib/ . + +zlib is available in Java using the java.util.zip package, documented at +http://java.sun.com/developer/technicalArticles/Programming/compression/ . + +A Perl interface to zlib written by Paul Marquess is available +at CPAN (Comprehensive Perl Archive Network) sites, including +http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://docs.python.org/library/zlib.html . + +zlib is built into tcl: http://wiki.tcl.tk/4610 . + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS or BEOS. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate and + zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; they + are too numerous to cite here. + +Copyright notice: + + (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. diff --git a/zlib-1.2.11/adler32.c b/zlib-1.2.11/adler32.c new file mode 100644 index 00000000..d0be4380 --- /dev/null +++ b/zlib-1.2.11/adler32.c @@ -0,0 +1,186 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); + +#define BASE 65521U /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ +#ifdef NO_DIVIDE +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ + do { \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ + do { \ + CHOP(a); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD(a) \ + do { \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32_z(adler, buf, len) + uLong adler; + const Bytef *buf; + z_size_t len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD28(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + return adler32_z(adler, buf, len); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + + /* the derivation of this formula is left as an exercise for the reader */ + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/zlib-1.2.11/amiga/Makefile.pup b/zlib-1.2.11/amiga/Makefile.pup new file mode 100644 index 00000000..8940c120 --- /dev/null +++ b/zlib-1.2.11/amiga/Makefile.pup @@ -0,0 +1,69 @@ +# Amiga powerUP (TM) Makefile +# makefile for libpng and SAS C V6.58/7.00 PPC compiler +# Copyright (C) 1998 by Andreas R. Kleinert + +LIBNAME = libzip.a + +CC = scppc +CFLAGS = NOSTKCHK NOSINT OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL \ + OPTLOOP OPTRDEP=8 OPTDEP=8 OPTCOMP=8 NOVER +AR = ppc-amigaos-ar cr +RANLIB = ppc-amigaos-ranlib +LD = ppc-amigaos-ld -r +LDFLAGS = -o +LDLIBS = LIB:scppc.a LIB:end.o +RM = delete quiet + +OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ + uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example minigzip + +check: test +test: all + example + echo hello world | minigzip | minigzip -d + +$(LIBNAME): $(OBJS) + $(AR) $@ $(OBJS) + -$(RANLIB) $@ + +example: example.o $(LIBNAME) + $(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS) + +minigzip: minigzip.o $(LIBNAME) + $(LD) $(LDFLAGS) $@ LIB:c_ppc.o $@.o $(LIBNAME) $(LDLIBS) + +mostlyclean: clean +clean: + $(RM) *.o example minigzip $(LIBNAME) foo.gz + +zip: + zip -ul9 zlib README ChangeLog Makefile Make????.??? Makefile.?? \ + descrip.mms *.[ch] + +tgz: + cd ..; tar cfz zlib/zlib.tgz zlib/README zlib/ChangeLog zlib/Makefile \ + zlib/Make????.??? zlib/Makefile.?? zlib/descrip.mms zlib/*.[ch] + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +adler32.o: zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: crc32.h zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +example.o: zlib.h zconf.h +gzclose.o: zlib.h zconf.h gzguts.h +gzlib.o: zlib.h zconf.h gzguts.h +gzread.o: zlib.h zconf.h gzguts.h +gzwrite.o: zlib.h zconf.h gzguts.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +minigzip.o: zlib.h zconf.h +trees.o: deflate.h zutil.h zlib.h zconf.h trees.h +uncompr.o: zlib.h zconf.h +zutil.o: zutil.h zlib.h zconf.h diff --git a/zlib-1.2.11/amiga/Makefile.sas b/zlib-1.2.11/amiga/Makefile.sas new file mode 100644 index 00000000..749e2915 --- /dev/null +++ b/zlib-1.2.11/amiga/Makefile.sas @@ -0,0 +1,68 @@ +# SMakefile for zlib +# Modified from the standard UNIX Makefile Copyright Jean-loup Gailly +# Osma Ahvenlampi +# Amiga, SAS/C 6.56 & Smake + +CC=sc +CFLAGS=OPT +#CFLAGS=OPT CPU=68030 +#CFLAGS=DEBUG=LINE +LDFLAGS=LIB z.lib + +SCOPTIONS=OPTSCHED OPTINLINE OPTALIAS OPTTIME OPTINLOCAL STRMERGE \ + NOICONS PARMS=BOTH NOSTACKCHECK UTILLIB NOVERSION ERRORREXX \ + DEF=POSTINC + +OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ + uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: SCOPTIONS example minigzip + +check: test +test: all + example + echo hello world | minigzip | minigzip -d + +install: z.lib + copy clone zlib.h zconf.h INCLUDE: + copy clone z.lib LIB: + +z.lib: $(OBJS) + oml z.lib r $(OBJS) + +example: example.o z.lib + $(CC) $(CFLAGS) LINK TO $@ example.o $(LDFLAGS) + +minigzip: minigzip.o z.lib + $(CC) $(CFLAGS) LINK TO $@ minigzip.o $(LDFLAGS) + +mostlyclean: clean +clean: + -delete force quiet example minigzip *.o z.lib foo.gz *.lnk SCOPTIONS + +SCOPTIONS: Makefile.sas + copy to $@ (uLong)max ? max : (uInt)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = sourceLen > (uLong)max ? max : (uInt)sourceLen; + sourceLen -= stream.avail_in; + } + err = deflate(&stream, sourceLen ? Z_NO_FLUSH : Z_FINISH); + } while (err == Z_OK); + + *destLen = stream.total_out; + deflateEnd(&stream); + return err == Z_STREAM_END ? Z_OK : err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} + +/* =========================================================================== + If the default memLevel or windowBits for deflateInit() is changed, then + this function needs to be updated. + */ +uLong ZEXPORT compressBound (sourceLen) + uLong sourceLen; +{ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13; +} diff --git a/zlib-1.2.11/configure b/zlib-1.2.11/configure new file mode 100755 index 00000000..e974d1fd --- /dev/null +++ b/zlib-1.2.11/configure @@ -0,0 +1,921 @@ +#!/bin/sh +# configure script for zlib. +# +# Normally configure builds both a static and a shared library. +# If you want to build just a static library, use: ./configure --static +# +# To impose specific compiler or flags or install directory, use for example: +# prefix=$HOME CC=cc CFLAGS="-O4" ./configure +# or for csh/tcsh users: +# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure) + +# Incorrect settings of CC or CFLAGS may prevent creating a shared library. +# If you have problems, try without defining CC and CFLAGS before reporting +# an error. + +# start off configure.log +echo -------------------- >> configure.log +echo $0 $* >> configure.log +date >> configure.log + +# get source directory +SRCDIR=`dirname $0` +if test $SRCDIR = "."; then + ZINC="" + ZINCOUT="-I." + SRCDIR="" +else + ZINC='-include zconf.h' + ZINCOUT='-I. -I$(SRCDIR)' + SRCDIR="$SRCDIR/" +fi + +# set command prefix for cross-compilation +if [ -n "${CHOST}" ]; then + uname="`echo "${CHOST}" | sed -e 's/^[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)$/\1/' -e 's/^[^-]*-[^-]*-\([^-]*\)-.*$/\1/'`" + CROSS_PREFIX="${CHOST}-" +fi + +# destination name for static library +STATICLIB=libz.a + +# extract zlib version numbers from zlib.h +VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < ${SRCDIR}zlib.h` +VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\).*/\1/p' < ${SRCDIR}zlib.h` +VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h` +VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < ${SRCDIR}zlib.h` + +# establish commands for library building +if "${CROSS_PREFIX}ar" --version >/dev/null 2>/dev/null || test $? -lt 126; then + AR=${AR-"${CROSS_PREFIX}ar"} + test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log +else + AR=${AR-"ar"} + test -n "${CROSS_PREFIX}" && echo Using ${AR} | tee -a configure.log +fi +ARFLAGS=${ARFLAGS-"rc"} +if "${CROSS_PREFIX}ranlib" --version >/dev/null 2>/dev/null || test $? -lt 126; then + RANLIB=${RANLIB-"${CROSS_PREFIX}ranlib"} + test -n "${CROSS_PREFIX}" && echo Using ${RANLIB} | tee -a configure.log +else + RANLIB=${RANLIB-"ranlib"} +fi +if "${CROSS_PREFIX}nm" --version >/dev/null 2>/dev/null || test $? -lt 126; then + NM=${NM-"${CROSS_PREFIX}nm"} + test -n "${CROSS_PREFIX}" && echo Using ${NM} | tee -a configure.log +else + NM=${NM-"nm"} +fi + +# set defaults before processing command line options +LDCONFIG=${LDCONFIG-"ldconfig"} +LDSHAREDLIBC="${LDSHAREDLIBC--lc}" +ARCHS= +prefix=${prefix-/usr/local} +exec_prefix=${exec_prefix-'${prefix}'} +libdir=${libdir-'${exec_prefix}/lib'} +sharedlibdir=${sharedlibdir-'${libdir}'} +includedir=${includedir-'${prefix}/include'} +mandir=${mandir-'${prefix}/share/man'} +shared_ext='.so' +shared=1 +solo=0 +cover=0 +zprefix=0 +zconst=0 +build64=0 +gcc=0 +warn=0 +debug=0 +old_cc="$CC" +old_cflags="$CFLAGS" +OBJC='$(OBJZ) $(OBJG)' +PIC_OBJC='$(PIC_OBJZ) $(PIC_OBJG)' + +# leave this script, optionally in a bad way +leave() +{ + if test "$*" != "0"; then + echo "** $0 aborting." | tee -a configure.log + fi + rm -f $test.[co] $test $test$shared_ext $test.gcno ./--version + echo -------------------- >> configure.log + echo >> configure.log + echo >> configure.log + exit $1 +} + +# process command line options +while test $# -ge 1 +do +case "$1" in + -h* | --help) + echo 'usage:' | tee -a configure.log + echo ' configure [--const] [--zprefix] [--prefix=PREFIX] [--eprefix=EXPREFIX]' | tee -a configure.log + echo ' [--static] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log + echo ' [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log + exit 0 ;; + -p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;; + -e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;; + -l*=* | --libdir=*) libdir=`echo $1 | sed 's/.*=//'`; shift ;; + --sharedlibdir=*) sharedlibdir=`echo $1 | sed 's/.*=//'`; shift ;; + -i*=* | --includedir=*) includedir=`echo $1 | sed 's/.*=//'`;shift ;; + -u*=* | --uname=*) uname=`echo $1 | sed 's/.*=//'`;shift ;; + -p* | --prefix) prefix="$2"; shift; shift ;; + -e* | --eprefix) exec_prefix="$2"; shift; shift ;; + -l* | --libdir) libdir="$2"; shift; shift ;; + -i* | --includedir) includedir="$2"; shift; shift ;; + -s* | --shared | --enable-shared) shared=1; shift ;; + -t | --static) shared=0; shift ;; + --solo) solo=1; shift ;; + --cover) cover=1; shift ;; + -z* | --zprefix) zprefix=1; shift ;; + -6* | --64) build64=1; shift ;; + -a*=* | --archs=*) ARCHS=`echo $1 | sed 's/.*=//'`; shift ;; + --sysconfdir=*) echo "ignored option: --sysconfdir" | tee -a configure.log; shift ;; + --localstatedir=*) echo "ignored option: --localstatedir" | tee -a configure.log; shift ;; + -c* | --const) zconst=1; shift ;; + -w* | --warn) warn=1; shift ;; + -d* | --debug) debug=1; shift ;; + *) + echo "unknown option: $1" | tee -a configure.log + echo "$0 --help for help" | tee -a configure.log + leave 1;; + esac +done + +# temporary file name +test=ztest$$ + +# put arguments in log, also put test file in log if used in arguments +show() +{ + case "$*" in + *$test.c*) + echo === $test.c === >> configure.log + cat $test.c >> configure.log + echo === >> configure.log;; + esac + echo $* >> configure.log +} + +# check for gcc vs. cc and set compile and link flags based on the system identified by uname +cat > $test.c <&1` in + *gcc*) gcc=1 ;; + *clang*) gcc=1 ;; +esac + +show $cc -c $test.c +if test "$gcc" -eq 1 && ($cc -c $test.c) >> configure.log 2>&1; then + echo ... using gcc >> configure.log + CC="$cc" + CFLAGS="${CFLAGS--O3}" + SFLAGS="${CFLAGS--O3} -fPIC" + if test "$ARCHS"; then + CFLAGS="${CFLAGS} ${ARCHS}" + LDFLAGS="${LDFLAGS} ${ARCHS}" + fi + if test $build64 -eq 1; then + CFLAGS="${CFLAGS} -m64" + SFLAGS="${SFLAGS} -m64" + fi + if test "$warn" -eq 1; then + if test "$zconst" -eq 1; then + CFLAGS="${CFLAGS} -Wall -Wextra -Wcast-qual -pedantic -DZLIB_CONST" + else + CFLAGS="${CFLAGS} -Wall -Wextra -pedantic" + fi + fi + if test $debug -eq 1; then + CFLAGS="${CFLAGS} -DZLIB_DEBUG" + SFLAGS="${SFLAGS} -DZLIB_DEBUG" + fi + if test -z "$uname"; then + uname=`(uname -s || echo unknown) 2>/dev/null` + fi + case "$uname" in + Linux* | linux* | GNU | GNU/* | solaris*) + LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} ;; + *BSD | *bsd* | DragonFly) + LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,${SRCDIR}zlib.map"} + LDCONFIG="ldconfig -m" ;; + CYGWIN* | Cygwin* | cygwin* | OS/2*) + EXE='.exe' ;; + MINGW* | mingw*) +# temporary bypass + rm -f $test.[co] $test $test$shared_ext + echo "Please use win32/Makefile.gcc instead." | tee -a configure.log + leave 1 + LDSHARED=${LDSHARED-"$cc -shared"} + LDSHAREDLIBC="" + EXE='.exe' ;; + QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 + # (alain.bonnefoy@icbt.com) + LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;; + HP-UX*) + LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} + case `(uname -m || echo unknown) 2>/dev/null` in + ia64) + shared_ext='.so' + SHAREDLIB='libz.so' ;; + *) + shared_ext='.sl' + SHAREDLIB='libz.sl' ;; + esac ;; + Darwin* | darwin*) + shared_ext='.dylib' + SHAREDLIB=libz$shared_ext + SHAREDLIBV=libz.$VER$shared_ext + SHAREDLIBM=libz.$VER1$shared_ext + LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"} + if libtool -V 2>&1 | grep Apple > /dev/null; then + AR="libtool" + else + AR="/usr/bin/libtool" + fi + ARFLAGS="-o" ;; + *) LDSHARED=${LDSHARED-"$cc -shared"} ;; + esac +else + # find system name and corresponding cc options + CC=${CC-cc} + gcc=0 + echo ... using $CC >> configure.log + if test -z "$uname"; then + uname=`(uname -sr || echo unknown) 2>/dev/null` + fi + case "$uname" in + HP-UX*) SFLAGS=${CFLAGS-"-O +z"} + CFLAGS=${CFLAGS-"-O"} +# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"} + LDSHARED=${LDSHARED-"ld -b"} + case `(uname -m || echo unknown) 2>/dev/null` in + ia64) + shared_ext='.so' + SHAREDLIB='libz.so' ;; + *) + shared_ext='.sl' + SHAREDLIB='libz.sl' ;; + esac ;; + IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."} + CFLAGS=${CFLAGS-"-ansi -O2"} + LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; + OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"} + CFLAGS=${CFLAGS-"-O -std1"} + LDFLAGS="${LDFLAGS} -Wl,-rpath,." + LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"} ;; + OSF1*) SFLAGS=${CFLAGS-"-O -std1"} + CFLAGS=${CFLAGS-"-O -std1"} + LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; + QNX*) SFLAGS=${CFLAGS-"-4 -O"} + CFLAGS=${CFLAGS-"-4 -O"} + LDSHARED=${LDSHARED-"cc"} + RANLIB=${RANLIB-"true"} + AR="cc" + ARFLAGS="-A" ;; + SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "} + CFLAGS=${CFLAGS-"-O3"} + LDSHARED=${LDSHARED-"cc -dy -KPIC -G"} ;; + SunOS\ 5* | solaris*) + LDSHARED=${LDSHARED-"cc -G -h libz$shared_ext.$VER1"} + SFLAGS=${CFLAGS-"-fast -KPIC"} + CFLAGS=${CFLAGS-"-fast"} + if test $build64 -eq 1; then + # old versions of SunPRO/Workshop/Studio don't support -m64, + # but newer ones do. Check for it. + flag64=`$CC -flags | egrep -- '^-m64'` + if test x"$flag64" != x"" ; then + CFLAGS="${CFLAGS} -m64" + SFLAGS="${SFLAGS} -m64" + else + case `(uname -m || echo unknown) 2>/dev/null` in + i86*) + SFLAGS="$SFLAGS -xarch=amd64" + CFLAGS="$CFLAGS -xarch=amd64" ;; + *) + SFLAGS="$SFLAGS -xarch=v9" + CFLAGS="$CFLAGS -xarch=v9" ;; + esac + fi + fi + if test -n "$ZINC"; then + ZINC='-I- -I. -I$(SRCDIR)' + fi + ;; + SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"} + CFLAGS=${CFLAGS-"-O2"} + LDSHARED=${LDSHARED-"ld"} ;; + SunStudio\ 9*) SFLAGS=${CFLAGS-"-fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"} + CFLAGS=${CFLAGS-"-fast -xtarget=ultra3 -xarch=v9b"} + LDSHARED=${LDSHARED-"cc -xarch=v9b"} ;; + UNIX_System_V\ 4.2.0) + SFLAGS=${CFLAGS-"-KPIC -O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -G"} ;; + UNIX_SV\ 4.2MP) + SFLAGS=${CFLAGS-"-Kconform_pic -O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -G"} ;; + OpenUNIX\ 5) + SFLAGS=${CFLAGS-"-KPIC -O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -G"} ;; + AIX*) # Courtesy of dbakker@arrayasolutions.com + SFLAGS=${CFLAGS-"-O -qmaxmem=8192"} + CFLAGS=${CFLAGS-"-O -qmaxmem=8192"} + LDSHARED=${LDSHARED-"xlc -G"} ;; + # send working options for other systems to zlib@gzip.org + *) SFLAGS=${CFLAGS-"-O"} + CFLAGS=${CFLAGS-"-O"} + LDSHARED=${LDSHARED-"cc -shared"} ;; + esac +fi + +# destination names for shared library if not defined above +SHAREDLIB=${SHAREDLIB-"libz$shared_ext"} +SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"} +SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"} + +echo >> configure.log + +# define functions for testing compiler and library characteristics and logging the results + +cat > $test.c </dev/null; then + try() + { + show $* + test "`( $* ) 2>&1 | tee -a configure.log`" = "" + } + echo - using any output from compiler to indicate an error >> configure.log +else + try() + { + show $* + ( $* ) >> configure.log 2>&1 + ret=$? + if test $ret -ne 0; then + echo "(exit code "$ret")" >> configure.log + fi + return $ret + } +fi + +tryboth() +{ + show $* + got=`( $* ) 2>&1` + ret=$? + printf %s "$got" >> configure.log + if test $ret -ne 0; then + return $ret + fi + test "$got" = "" +} + +cat > $test.c << EOF +int foo() { return 0; } +EOF +echo "Checking for obsessive-compulsive compiler options..." >> configure.log +if try $CC -c $CFLAGS $test.c; then + : +else + echo "Compiler error reporting is too harsh for $0 (perhaps remove -Werror)." | tee -a configure.log + leave 1 +fi + +echo >> configure.log + +# see if shared library build supported +cat > $test.c <> configure.log + show "$NM $test.o | grep _hello" + if test "`$NM $test.o | grep _hello | tee -a configure.log`" = ""; then + CPP="$CPP -DNO_UNDERLINE" + echo Checking for underline in external names... No. | tee -a configure.log + else + echo Checking for underline in external names... Yes. | tee -a configure.log + fi ;; +esac + +echo >> configure.log + +# check for size_t +cat > $test.c < +#include +size_t dummy = 0; +EOF +if try $CC -c $CFLAGS $test.c; then + echo "Checking for size_t... Yes." | tee -a configure.log + need_sizet=0 +else + echo "Checking for size_t... No." | tee -a configure.log + need_sizet=1 +fi + +echo >> configure.log + +# find the size_t integer type, if needed +if test $need_sizet -eq 1; then + cat > $test.c < $test.c < +int main(void) { + if (sizeof(void *) <= sizeof(int)) puts("int"); + else if (sizeof(void *) <= sizeof(long)) puts("long"); + else puts("z_longlong"); + return 0; +} +EOF + else + echo "Checking for long long... No." | tee -a configure.log + cat > $test.c < +int main(void) { + if (sizeof(void *) <= sizeof(int)) puts("int"); + else puts("long"); + return 0; +} +EOF + fi + if try $CC $CFLAGS -o $test $test.c; then + sizet=`./$test` + echo "Checking for a pointer-size integer type..." $sizet"." | tee -a configure.log + else + echo "Failed to find a pointer-size integer type." | tee -a configure.log + leave 1 + fi +fi + +if test $need_sizet -eq 1; then + CFLAGS="${CFLAGS} -DNO_SIZE_T=${sizet}" + SFLAGS="${SFLAGS} -DNO_SIZE_T=${sizet}" +fi + +echo >> configure.log + +# check for large file support, and if none, check for fseeko() +cat > $test.c < +off64_t dummy = 0; +EOF +if try $CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c; then + CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1" + SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1" + ALL="${ALL} all64" + TEST="${TEST} test64" + echo "Checking for off64_t... Yes." | tee -a configure.log + echo "Checking for fseeko... Yes." | tee -a configure.log +else + echo "Checking for off64_t... No." | tee -a configure.log + echo >> configure.log + cat > $test.c < +int main(void) { + fseeko(NULL, 0, 0); + return 0; +} +EOF + if try $CC $CFLAGS -o $test $test.c; then + echo "Checking for fseeko... Yes." | tee -a configure.log + else + CFLAGS="${CFLAGS} -DNO_FSEEKO" + SFLAGS="${SFLAGS} -DNO_FSEEKO" + echo "Checking for fseeko... No." | tee -a configure.log + fi +fi + +echo >> configure.log + +# check for strerror() for use by gz* functions +cat > $test.c < +#include +int main() { return strlen(strerror(errno)); } +EOF +if try $CC $CFLAGS -o $test $test.c; then + echo "Checking for strerror... Yes." | tee -a configure.log +else + CFLAGS="${CFLAGS} -DNO_STRERROR" + SFLAGS="${SFLAGS} -DNO_STRERROR" + echo "Checking for strerror... No." | tee -a configure.log +fi + +# copy clean zconf.h for subsequent edits +cp -p ${SRCDIR}zconf.h.in zconf.h + +echo >> configure.log + +# check for unistd.h and save result in zconf.h +cat > $test.c < +int main() { return 0; } +EOF +if try $CC -c $CFLAGS $test.c; then + sed < zconf.h "/^#ifdef HAVE_UNISTD_H.* may be/s/def HAVE_UNISTD_H\(.*\) may be/ 1\1 was/" > zconf.temp.h + mv zconf.temp.h zconf.h + echo "Checking for unistd.h... Yes." | tee -a configure.log +else + echo "Checking for unistd.h... No." | tee -a configure.log +fi + +echo >> configure.log + +# check for stdarg.h and save result in zconf.h +cat > $test.c < +int main() { return 0; } +EOF +if try $CC -c $CFLAGS $test.c; then + sed < zconf.h "/^#ifdef HAVE_STDARG_H.* may be/s/def HAVE_STDARG_H\(.*\) may be/ 1\1 was/" > zconf.temp.h + mv zconf.temp.h zconf.h + echo "Checking for stdarg.h... Yes." | tee -a configure.log +else + echo "Checking for stdarg.h... No." | tee -a configure.log +fi + +# if the z_ prefix was requested, save that in zconf.h +if test $zprefix -eq 1; then + sed < zconf.h "/#ifdef Z_PREFIX.* may be/s/def Z_PREFIX\(.*\) may be/ 1\1 was/" > zconf.temp.h + mv zconf.temp.h zconf.h + echo >> configure.log + echo "Using z_ prefix on all symbols." | tee -a configure.log +fi + +# if --solo compilation was requested, save that in zconf.h and remove gz stuff from object lists +if test $solo -eq 1; then + sed '/#define ZCONF_H/a\ +#define Z_SOLO + +' < zconf.h > zconf.temp.h + mv zconf.temp.h zconf.h +OBJC='$(OBJZ)' +PIC_OBJC='$(PIC_OBJZ)' +fi + +# if code coverage testing was requested, use older gcc if defined, e.g. "gcc-4.2" on Mac OS X +if test $cover -eq 1; then + CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage" + if test -n "$GCC_CLASSIC"; then + CC=$GCC_CLASSIC + fi +fi + +echo >> configure.log + +# conduct a series of tests to resolve eight possible cases of using "vs" or "s" printf functions +# (using stdarg or not), with or without "n" (proving size of buffer), and with or without a +# return value. The most secure result is vsnprintf() with a return value. snprintf() with a +# return value is secure as well, but then gzprintf() will be limited to 20 arguments. +cat > $test.c < +#include +#include "zconf.h" +int main() +{ +#ifndef STDC + choke me +#endif + return 0; +} +EOF +if try $CC -c $CFLAGS $test.c; then + echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()." | tee -a configure.log + + echo >> configure.log + cat > $test.c < +#include +int mytest(const char *fmt, ...) +{ + char buf[20]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + return 0; +} +int main() +{ + return (mytest("Hello%d\n", 1)); +} +EOF + if try $CC $CFLAGS -o $test $test.c; then + echo "Checking for vsnprintf() in stdio.h... Yes." | tee -a configure.log + + echo >> configure.log + cat >$test.c < +#include +int mytest(const char *fmt, ...) +{ + int n; + char buf[20]; + va_list ap; + va_start(ap, fmt); + n = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + return n; +} +int main() +{ + return (mytest("Hello%d\n", 1)); +} +EOF + + if try $CC -c $CFLAGS $test.c; then + echo "Checking for return value of vsnprintf()... Yes." | tee -a configure.log + else + CFLAGS="$CFLAGS -DHAS_vsnprintf_void" + SFLAGS="$SFLAGS -DHAS_vsnprintf_void" + echo "Checking for return value of vsnprintf()... No." | tee -a configure.log + echo " WARNING: apparently vsnprintf() does not return a value. zlib" | tee -a configure.log + echo " can build but will be open to possible string-format security" | tee -a configure.log + echo " vulnerabilities." | tee -a configure.log + fi + else + CFLAGS="$CFLAGS -DNO_vsnprintf" + SFLAGS="$SFLAGS -DNO_vsnprintf" + echo "Checking for vsnprintf() in stdio.h... No." | tee -a configure.log + echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib" | tee -a configure.log + echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log + echo " vulnerabilities." | tee -a configure.log + + echo >> configure.log + cat >$test.c < +#include +int mytest(const char *fmt, ...) +{ + int n; + char buf[20]; + va_list ap; + va_start(ap, fmt); + n = vsprintf(buf, fmt, ap); + va_end(ap); + return n; +} +int main() +{ + return (mytest("Hello%d\n", 1)); +} +EOF + + if try $CC -c $CFLAGS $test.c; then + echo "Checking for return value of vsprintf()... Yes." | tee -a configure.log + else + CFLAGS="$CFLAGS -DHAS_vsprintf_void" + SFLAGS="$SFLAGS -DHAS_vsprintf_void" + echo "Checking for return value of vsprintf()... No." | tee -a configure.log + echo " WARNING: apparently vsprintf() does not return a value. zlib" | tee -a configure.log + echo " can build but will be open to possible string-format security" | tee -a configure.log + echo " vulnerabilities." | tee -a configure.log + fi + fi +else + echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()." | tee -a configure.log + + echo >> configure.log + cat >$test.c < +int mytest() +{ + char buf[20]; + snprintf(buf, sizeof(buf), "%s", "foo"); + return 0; +} +int main() +{ + return (mytest()); +} +EOF + + if try $CC $CFLAGS -o $test $test.c; then + echo "Checking for snprintf() in stdio.h... Yes." | tee -a configure.log + + echo >> configure.log + cat >$test.c < +int mytest() +{ + char buf[20]; + return snprintf(buf, sizeof(buf), "%s", "foo"); +} +int main() +{ + return (mytest()); +} +EOF + + if try $CC -c $CFLAGS $test.c; then + echo "Checking for return value of snprintf()... Yes." | tee -a configure.log + else + CFLAGS="$CFLAGS -DHAS_snprintf_void" + SFLAGS="$SFLAGS -DHAS_snprintf_void" + echo "Checking for return value of snprintf()... No." | tee -a configure.log + echo " WARNING: apparently snprintf() does not return a value. zlib" | tee -a configure.log + echo " can build but will be open to possible string-format security" | tee -a configure.log + echo " vulnerabilities." | tee -a configure.log + fi + else + CFLAGS="$CFLAGS -DNO_snprintf" + SFLAGS="$SFLAGS -DNO_snprintf" + echo "Checking for snprintf() in stdio.h... No." | tee -a configure.log + echo " WARNING: snprintf() not found, falling back to sprintf(). zlib" | tee -a configure.log + echo " can build but will be open to possible buffer-overflow security" | tee -a configure.log + echo " vulnerabilities." | tee -a configure.log + + echo >> configure.log + cat >$test.c < +int mytest() +{ + char buf[20]; + return sprintf(buf, "%s", "foo"); +} +int main() +{ + return (mytest()); +} +EOF + + if try $CC -c $CFLAGS $test.c; then + echo "Checking for return value of sprintf()... Yes." | tee -a configure.log + else + CFLAGS="$CFLAGS -DHAS_sprintf_void" + SFLAGS="$SFLAGS -DHAS_sprintf_void" + echo "Checking for return value of sprintf()... No." | tee -a configure.log + echo " WARNING: apparently sprintf() does not return a value. zlib" | tee -a configure.log + echo " can build but will be open to possible string-format security" | tee -a configure.log + echo " vulnerabilities." | tee -a configure.log + fi + fi +fi + +# see if we can hide zlib internal symbols that are linked between separate source files +if test "$gcc" -eq 1; then + echo >> configure.log + cat > $test.c <> configure.log +echo ALL = $ALL >> configure.log +echo AR = $AR >> configure.log +echo ARFLAGS = $ARFLAGS >> configure.log +echo CC = $CC >> configure.log +echo CFLAGS = $CFLAGS >> configure.log +echo CPP = $CPP >> configure.log +echo EXE = $EXE >> configure.log +echo LDCONFIG = $LDCONFIG >> configure.log +echo LDFLAGS = $LDFLAGS >> configure.log +echo LDSHARED = $LDSHARED >> configure.log +echo LDSHAREDLIBC = $LDSHAREDLIBC >> configure.log +echo OBJC = $OBJC >> configure.log +echo PIC_OBJC = $PIC_OBJC >> configure.log +echo RANLIB = $RANLIB >> configure.log +echo SFLAGS = $SFLAGS >> configure.log +echo SHAREDLIB = $SHAREDLIB >> configure.log +echo SHAREDLIBM = $SHAREDLIBM >> configure.log +echo SHAREDLIBV = $SHAREDLIBV >> configure.log +echo STATICLIB = $STATICLIB >> configure.log +echo TEST = $TEST >> configure.log +echo VER = $VER >> configure.log +echo Z_U4 = $Z_U4 >> configure.log +echo SRCDIR = $SRCDIR >> configure.log +echo exec_prefix = $exec_prefix >> configure.log +echo includedir = $includedir >> configure.log +echo libdir = $libdir >> configure.log +echo mandir = $mandir >> configure.log +echo prefix = $prefix >> configure.log +echo sharedlibdir = $sharedlibdir >> configure.log +echo uname = $uname >> configure.log + +# udpate Makefile with the configure results +sed < ${SRCDIR}Makefile.in " +/^CC *=/s#=.*#=$CC# +/^CFLAGS *=/s#=.*#=$CFLAGS# +/^SFLAGS *=/s#=.*#=$SFLAGS# +/^LDFLAGS *=/s#=.*#=$LDFLAGS# +/^LDSHARED *=/s#=.*#=$LDSHARED# +/^CPP *=/s#=.*#=$CPP# +/^STATICLIB *=/s#=.*#=$STATICLIB# +/^SHAREDLIB *=/s#=.*#=$SHAREDLIB# +/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# +/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# +/^AR *=/s#=.*#=$AR# +/^ARFLAGS *=/s#=.*#=$ARFLAGS# +/^RANLIB *=/s#=.*#=$RANLIB# +/^LDCONFIG *=/s#=.*#=$LDCONFIG# +/^LDSHAREDLIBC *=/s#=.*#=$LDSHAREDLIBC# +/^EXE *=/s#=.*#=$EXE# +/^SRCDIR *=/s#=.*#=$SRCDIR# +/^ZINC *=/s#=.*#=$ZINC# +/^ZINCOUT *=/s#=.*#=$ZINCOUT# +/^prefix *=/s#=.*#=$prefix# +/^exec_prefix *=/s#=.*#=$exec_prefix# +/^libdir *=/s#=.*#=$libdir# +/^sharedlibdir *=/s#=.*#=$sharedlibdir# +/^includedir *=/s#=.*#=$includedir# +/^mandir *=/s#=.*#=$mandir# +/^OBJC *=/s#=.*#= $OBJC# +/^PIC_OBJC *=/s#=.*#= $PIC_OBJC# +/^all: */s#:.*#: $ALL# +/^test: */s#:.*#: $TEST# +" > Makefile + +# create zlib.pc with the configure results +sed < ${SRCDIR}zlib.pc.in " +/^CC *=/s#=.*#=$CC# +/^CFLAGS *=/s#=.*#=$CFLAGS# +/^CPP *=/s#=.*#=$CPP# +/^LDSHARED *=/s#=.*#=$LDSHARED# +/^STATICLIB *=/s#=.*#=$STATICLIB# +/^SHAREDLIB *=/s#=.*#=$SHAREDLIB# +/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# +/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# +/^AR *=/s#=.*#=$AR# +/^ARFLAGS *=/s#=.*#=$ARFLAGS# +/^RANLIB *=/s#=.*#=$RANLIB# +/^EXE *=/s#=.*#=$EXE# +/^prefix *=/s#=.*#=$prefix# +/^exec_prefix *=/s#=.*#=$exec_prefix# +/^libdir *=/s#=.*#=$libdir# +/^sharedlibdir *=/s#=.*#=$sharedlibdir# +/^includedir *=/s#=.*#=$includedir# +/^mandir *=/s#=.*#=$mandir# +/^LDFLAGS *=/s#=.*#=$LDFLAGS# +" | sed -e " +s/\@VERSION\@/$VER/g; +" > zlib.pc + +# done +leave 0 diff --git a/zlib-1.2.11/contrib/README.contrib b/zlib-1.2.11/contrib/README.contrib new file mode 100644 index 00000000..a411d5c3 --- /dev/null +++ b/zlib-1.2.11/contrib/README.contrib @@ -0,0 +1,78 @@ +All files under this contrib directory are UNSUPPORTED. There were +provided by users of zlib and were not tested by the authors of zlib. +Use at your own risk. Please contact the authors of the contributions +for help about these, not the zlib authors. Thanks. + + +ada/ by Dmitriy Anisimkov + Support for Ada + See http://zlib-ada.sourceforge.net/ + +amd64/ by Mikhail Teterin + asm code for AMD64 + See patch at http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/96393 + +asm686/ by Brian Raiter + asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax + See http://www.muppetlabs.com/~breadbox/software/assembly.html + +blast/ by Mark Adler + Decompressor for output of PKWare Data Compression Library (DCL) + +delphi/ by Cosmin Truta + Support for Delphi and C++ Builder + +dotzlib/ by Henrik Ravn + Support for Microsoft .Net and Visual C++ .Net + +gcc_gvmat64/by Gilles Vollant + GCC Version of x86 64-bit (AMD64 and Intel EM64t) code for x64 + assembler to replace longest_match() and inflate_fast() + +infback9/ by Mark Adler + Unsupported diffs to infback to decode the deflate64 format + +inflate86/ by Chris Anderson + Tuned x86 gcc asm code to replace inflate_fast() + +iostream/ by Kevin Ruland + A C++ I/O streams interface to the zlib gz* functions + +iostream2/ by Tyge Løvset + Another C++ I/O streams interface + +iostream3/ by Ludwig Schwardt + and Kevin Ruland + Yet another C++ I/O streams interface + +masmx64/ by Gilles Vollant + x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to + replace longest_match() and inflate_fast(), also masm x86 + 64-bits translation of Chris Anderson inflate_fast() + +masmx86/ by Gilles Vollant + x86 asm code to replace longest_match() and inflate_fast(), + for Visual C++ and MASM (32 bits). + Based on Brian Raiter (asm686) and Chris Anderson (inflate86) + +minizip/ by Gilles Vollant + Mini zip and unzip based on zlib + Includes Zip64 support by Mathias Svensson + See http://www.winimage.com/zLibDll/minizip.html + +pascal/ by Bob Dellaca et al. + Support for Pascal + +puff/ by Mark Adler + Small, low memory usage inflate. Also serves to provide an + unambiguous description of the deflate format. + +testzlib/ by Gilles Vollant + Example of the use of zlib + +untgz/ by Pedro A. Aranda Gutierrez + A very simple tar.gz file extractor using zlib + +vstudio/ by Gilles Vollant + Building a minizip-enhanced zlib with Microsoft Visual Studio + Includes vc11 from kreuzerkrieg and vc12 from davispuh diff --git a/zlib-1.2.11/contrib/ada/buffer_demo.adb b/zlib-1.2.11/contrib/ada/buffer_demo.adb new file mode 100644 index 00000000..46b86381 --- /dev/null +++ b/zlib-1.2.11/contrib/ada/buffer_demo.adb @@ -0,0 +1,106 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2004 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- +-- +-- $Id: buffer_demo.adb,v 1.3 2004/09/06 06:55:35 vagul Exp $ + +-- This demo program provided by Dr Steve Sangwine +-- +-- Demonstration of a problem with Zlib-Ada (already fixed) when a buffer +-- of exactly the correct size is used for decompressed data, and the last +-- few bytes passed in to Zlib are checksum bytes. + +-- This program compresses a string of text, and then decompresses the +-- compressed text into a buffer of the same size as the original text. + +with Ada.Streams; use Ada.Streams; +with Ada.Text_IO; + +with ZLib; use ZLib; + +procedure Buffer_Demo is + EOL : Character renames ASCII.LF; + Text : constant String + := "Four score and seven years ago our fathers brought forth," & EOL & + "upon this continent, a new nation, conceived in liberty," & EOL & + "and dedicated to the proposition that `all men are created equal'."; + + Source : Stream_Element_Array (1 .. Text'Length); + for Source'Address use Text'Address; + +begin + Ada.Text_IO.Put (Text); + Ada.Text_IO.New_Line; + Ada.Text_IO.Put_Line + ("Uncompressed size : " & Positive'Image (Text'Length) & " bytes"); + + declare + Compressed_Data : Stream_Element_Array (1 .. Text'Length); + L : Stream_Element_Offset; + begin + Compress : declare + Compressor : Filter_Type; + I : Stream_Element_Offset; + begin + Deflate_Init (Compressor); + + -- Compress the whole of T at once. + + Translate (Compressor, Source, I, Compressed_Data, L, Finish); + pragma Assert (I = Source'Last); + + Close (Compressor); + + Ada.Text_IO.Put_Line + ("Compressed size : " + & Stream_Element_Offset'Image (L) & " bytes"); + end Compress; + + -- Now we decompress the data, passing short blocks of data to Zlib + -- (because this demonstrates the problem - the last block passed will + -- contain checksum information and there will be no output, only a + -- check inside Zlib that the checksum is correct). + + Decompress : declare + Decompressor : Filter_Type; + + Uncompressed_Data : Stream_Element_Array (1 .. Text'Length); + + Block_Size : constant := 4; + -- This makes sure that the last block contains + -- only Adler checksum data. + + P : Stream_Element_Offset := Compressed_Data'First - 1; + O : Stream_Element_Offset; + begin + Inflate_Init (Decompressor); + + loop + Translate + (Decompressor, + Compressed_Data + (P + 1 .. Stream_Element_Offset'Min (P + Block_Size, L)), + P, + Uncompressed_Data + (Total_Out (Decompressor) + 1 .. Uncompressed_Data'Last), + O, + No_Flush); + + Ada.Text_IO.Put_Line + ("Total in : " & Count'Image (Total_In (Decompressor)) & + ", out : " & Count'Image (Total_Out (Decompressor))); + + exit when P = L; + end loop; + + Ada.Text_IO.New_Line; + Ada.Text_IO.Put_Line + ("Decompressed text matches original text : " + & Boolean'Image (Uncompressed_Data = Source)); + end Decompress; + end; +end Buffer_Demo; diff --git a/zlib-1.2.11/contrib/ada/mtest.adb b/zlib-1.2.11/contrib/ada/mtest.adb new file mode 100644 index 00000000..c4dfd080 --- /dev/null +++ b/zlib-1.2.11/contrib/ada/mtest.adb @@ -0,0 +1,156 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- +-- Continuous test for ZLib multithreading. If the test would fail +-- we should provide thread safe allocation routines for the Z_Stream. +-- +-- $Id: mtest.adb,v 1.4 2004/07/23 07:49:54 vagul Exp $ + +with ZLib; +with Ada.Streams; +with Ada.Numerics.Discrete_Random; +with Ada.Text_IO; +with Ada.Exceptions; +with Ada.Task_Identification; + +procedure MTest is + use Ada.Streams; + use ZLib; + + Stop : Boolean := False; + + pragma Atomic (Stop); + + subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#; + + package Random_Elements is + new Ada.Numerics.Discrete_Random (Visible_Symbols); + + task type Test_Task; + + task body Test_Task is + Buffer : Stream_Element_Array (1 .. 100_000); + Gen : Random_Elements.Generator; + + Buffer_First : Stream_Element_Offset; + Compare_First : Stream_Element_Offset; + + Deflate : Filter_Type; + Inflate : Filter_Type; + + procedure Further (Item : in Stream_Element_Array); + + procedure Read_Buffer + (Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset); + + ------------- + -- Further -- + ------------- + + procedure Further (Item : in Stream_Element_Array) is + + procedure Compare (Item : in Stream_Element_Array); + + ------------- + -- Compare -- + ------------- + + procedure Compare (Item : in Stream_Element_Array) is + Next_First : Stream_Element_Offset := Compare_First + Item'Length; + begin + if Buffer (Compare_First .. Next_First - 1) /= Item then + raise Program_Error; + end if; + + Compare_First := Next_First; + end Compare; + + procedure Compare_Write is new ZLib.Write (Write => Compare); + begin + Compare_Write (Inflate, Item, No_Flush); + end Further; + + ----------------- + -- Read_Buffer -- + ----------------- + + procedure Read_Buffer + (Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset) + is + Buff_Diff : Stream_Element_Offset := Buffer'Last - Buffer_First; + Next_First : Stream_Element_Offset; + begin + if Item'Length <= Buff_Diff then + Last := Item'Last; + + Next_First := Buffer_First + Item'Length; + + Item := Buffer (Buffer_First .. Next_First - 1); + + Buffer_First := Next_First; + else + Last := Item'First + Buff_Diff; + Item (Item'First .. Last) := Buffer (Buffer_First .. Buffer'Last); + Buffer_First := Buffer'Last + 1; + end if; + end Read_Buffer; + + procedure Translate is new Generic_Translate + (Data_In => Read_Buffer, + Data_Out => Further); + + begin + Random_Elements.Reset (Gen); + + Buffer := (others => 20); + + Main : loop + for J in Buffer'Range loop + Buffer (J) := Random_Elements.Random (Gen); + + Deflate_Init (Deflate); + Inflate_Init (Inflate); + + Buffer_First := Buffer'First; + Compare_First := Buffer'First; + + Translate (Deflate); + + if Compare_First /= Buffer'Last + 1 then + raise Program_Error; + end if; + + Ada.Text_IO.Put_Line + (Ada.Task_Identification.Image + (Ada.Task_Identification.Current_Task) + & Stream_Element_Offset'Image (J) + & ZLib.Count'Image (Total_Out (Deflate))); + + Close (Deflate); + Close (Inflate); + + exit Main when Stop; + end loop; + end loop Main; + exception + when E : others => + Ada.Text_IO.Put_Line (Ada.Exceptions.Exception_Information (E)); + Stop := True; + end Test_Task; + + Test : array (1 .. 4) of Test_Task; + + pragma Unreferenced (Test); + + Dummy : Character; + +begin + Ada.Text_IO.Get_Immediate (Dummy); + Stop := True; +end MTest; diff --git a/zlib-1.2.11/contrib/ada/read.adb b/zlib-1.2.11/contrib/ada/read.adb new file mode 100644 index 00000000..1f2efbfe --- /dev/null +++ b/zlib-1.2.11/contrib/ada/read.adb @@ -0,0 +1,156 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: read.adb,v 1.8 2004/05/31 10:53:40 vagul Exp $ + +-- Test/demo program for the generic read interface. + +with Ada.Numerics.Discrete_Random; +with Ada.Streams; +with Ada.Text_IO; + +with ZLib; + +procedure Read is + + use Ada.Streams; + + ------------------------------------ + -- Test configuration parameters -- + ------------------------------------ + + File_Size : Stream_Element_Offset := 100_000; + + Continuous : constant Boolean := False; + -- If this constant is True, the test would be repeated again and again, + -- with increment File_Size for every iteration. + + Header : constant ZLib.Header_Type := ZLib.Default; + -- Do not use Header other than Default in ZLib versions 1.1.4 and older. + + Init_Random : constant := 8; + -- We are using the same random sequence, in case of we catch bug, + -- so we would be able to reproduce it. + + -- End -- + + Pack_Size : Stream_Element_Offset; + Offset : Stream_Element_Offset; + + Filter : ZLib.Filter_Type; + + subtype Visible_Symbols + is Stream_Element range 16#20# .. 16#7E#; + + package Random_Elements is new + Ada.Numerics.Discrete_Random (Visible_Symbols); + + Gen : Random_Elements.Generator; + Period : constant Stream_Element_Offset := 200; + -- Period constant variable for random generator not to be very random. + -- Bigger period, harder random. + + Read_Buffer : Stream_Element_Array (1 .. 2048); + Read_First : Stream_Element_Offset; + Read_Last : Stream_Element_Offset; + + procedure Reset; + + procedure Read + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset); + -- this procedure is for generic instantiation of + -- ZLib.Read + -- reading data from the File_In. + + procedure Read is new ZLib.Read + (Read, + Read_Buffer, + Rest_First => Read_First, + Rest_Last => Read_Last); + + ---------- + -- Read -- + ---------- + + procedure Read + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset) is + begin + Last := Stream_Element_Offset'Min + (Item'Last, + Item'First + File_Size - Offset); + + for J in Item'First .. Last loop + if J < Item'First + Period then + Item (J) := Random_Elements.Random (Gen); + else + Item (J) := Item (J - Period); + end if; + + Offset := Offset + 1; + end loop; + end Read; + + ----------- + -- Reset -- + ----------- + + procedure Reset is + begin + Random_Elements.Reset (Gen, Init_Random); + Pack_Size := 0; + Offset := 1; + Read_First := Read_Buffer'Last + 1; + Read_Last := Read_Buffer'Last; + end Reset; + +begin + Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version); + + loop + for Level in ZLib.Compression_Level'Range loop + + Ada.Text_IO.Put ("Level =" + & ZLib.Compression_Level'Image (Level)); + + -- Deflate using generic instantiation. + + ZLib.Deflate_Init + (Filter, + Level, + Header => Header); + + Reset; + + Ada.Text_IO.Put + (Stream_Element_Offset'Image (File_Size) & " ->"); + + loop + declare + Buffer : Stream_Element_Array (1 .. 1024); + Last : Stream_Element_Offset; + begin + Read (Filter, Buffer, Last); + + Pack_Size := Pack_Size + Last - Buffer'First + 1; + + exit when Last < Buffer'Last; + end; + end loop; + + Ada.Text_IO.Put_Line (Stream_Element_Offset'Image (Pack_Size)); + + ZLib.Close (Filter); + end loop; + + exit when not Continuous; + + File_Size := File_Size + 1; + end loop; +end Read; diff --git a/zlib-1.2.11/contrib/ada/readme.txt b/zlib-1.2.11/contrib/ada/readme.txt new file mode 100644 index 00000000..ce4d2cad --- /dev/null +++ b/zlib-1.2.11/contrib/ada/readme.txt @@ -0,0 +1,65 @@ + ZLib for Ada thick binding (ZLib.Ada) + Release 1.3 + +ZLib.Ada is a thick binding interface to the popular ZLib data +compression library, available at http://www.gzip.org/zlib/. +It provides Ada-style access to the ZLib C library. + + + Here are the main changes since ZLib.Ada 1.2: + +- Attension: ZLib.Read generic routine have a initialization requirement + for Read_Last parameter now. It is a bit incompartible with previous version, + but extends functionality, we could use new parameters Allow_Read_Some and + Flush now. + +- Added Is_Open routines to ZLib and ZLib.Streams packages. + +- Add pragma Assert to check Stream_Element is 8 bit. + +- Fix extraction to buffer with exact known decompressed size. Error reported by + Steve Sangwine. + +- Fix definition of ULong (changed to unsigned_long), fix regression on 64 bits + computers. Patch provided by Pascal Obry. + +- Add Status_Error exception definition. + +- Add pragma Assertion that Ada.Streams.Stream_Element size is 8 bit. + + + How to build ZLib.Ada under GNAT + +You should have the ZLib library already build on your computer, before +building ZLib.Ada. Make the directory of ZLib.Ada sources current and +issue the command: + + gnatmake test -largs -L -lz + +Or use the GNAT project file build for GNAT 3.15 or later: + + gnatmake -Pzlib.gpr -L + + + How to build ZLib.Ada under Aonix ObjectAda for Win32 7.2.2 + +1. Make a project with all *.ads and *.adb files from the distribution. +2. Build the libz.a library from the ZLib C sources. +3. Rename libz.a to z.lib. +4. Add the library z.lib to the project. +5. Add the libc.lib library from the ObjectAda distribution to the project. +6. Build the executable using test.adb as a main procedure. + + + How to use ZLib.Ada + +The source files test.adb and read.adb are small demo programs that show +the main functionality of ZLib.Ada. + +The routines from the package specifications are commented. + + +Homepage: http://zlib-ada.sourceforge.net/ +Author: Dmitriy Anisimkov + +Contributors: Pascal Obry , Steve Sangwine diff --git a/zlib-1.2.11/contrib/ada/test.adb b/zlib-1.2.11/contrib/ada/test.adb new file mode 100644 index 00000000..90773acf --- /dev/null +++ b/zlib-1.2.11/contrib/ada/test.adb @@ -0,0 +1,463 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: test.adb,v 1.17 2003/08/12 12:13:30 vagul Exp $ + +-- The program has a few aims. +-- 1. Test ZLib.Ada95 thick binding functionality. +-- 2. Show the example of use main functionality of the ZLib.Ada95 binding. +-- 3. Build this program automatically compile all ZLib.Ada95 packages under +-- GNAT Ada95 compiler. + +with ZLib.Streams; +with Ada.Streams.Stream_IO; +with Ada.Numerics.Discrete_Random; + +with Ada.Text_IO; + +with Ada.Calendar; + +procedure Test is + + use Ada.Streams; + use Stream_IO; + + ------------------------------------ + -- Test configuration parameters -- + ------------------------------------ + + File_Size : Count := 100_000; + Continuous : constant Boolean := False; + + Header : constant ZLib.Header_Type := ZLib.Default; + -- ZLib.None; + -- ZLib.Auto; + -- ZLib.GZip; + -- Do not use Header other then Default in ZLib versions 1.1.4 + -- and older. + + Strategy : constant ZLib.Strategy_Type := ZLib.Default_Strategy; + Init_Random : constant := 10; + + -- End -- + + In_File_Name : constant String := "testzlib.in"; + -- Name of the input file + + Z_File_Name : constant String := "testzlib.zlb"; + -- Name of the compressed file. + + Out_File_Name : constant String := "testzlib.out"; + -- Name of the decompressed file. + + File_In : File_Type; + File_Out : File_Type; + File_Back : File_Type; + File_Z : ZLib.Streams.Stream_Type; + + Filter : ZLib.Filter_Type; + + Time_Stamp : Ada.Calendar.Time; + + procedure Generate_File; + -- Generate file of spetsified size with some random data. + -- The random data is repeatable, for the good compression. + + procedure Compare_Streams + (Left, Right : in out Root_Stream_Type'Class); + -- The procedure compearing data in 2 streams. + -- It is for compare data before and after compression/decompression. + + procedure Compare_Files (Left, Right : String); + -- Compare files. Based on the Compare_Streams. + + procedure Copy_Streams + (Source, Target : in out Root_Stream_Type'Class; + Buffer_Size : in Stream_Element_Offset := 1024); + -- Copying data from one stream to another. It is for test stream + -- interface of the library. + + procedure Data_In + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset); + -- this procedure is for generic instantiation of + -- ZLib.Generic_Translate. + -- reading data from the File_In. + + procedure Data_Out (Item : in Stream_Element_Array); + -- this procedure is for generic instantiation of + -- ZLib.Generic_Translate. + -- writing data to the File_Out. + + procedure Stamp; + -- Store the timestamp to the local variable. + + procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count); + -- Print the time statistic with the message. + + procedure Translate is new ZLib.Generic_Translate + (Data_In => Data_In, + Data_Out => Data_Out); + -- This procedure is moving data from File_In to File_Out + -- with compression or decompression, depend on initialization of + -- Filter parameter. + + ------------------- + -- Compare_Files -- + ------------------- + + procedure Compare_Files (Left, Right : String) is + Left_File, Right_File : File_Type; + begin + Open (Left_File, In_File, Left); + Open (Right_File, In_File, Right); + Compare_Streams (Stream (Left_File).all, Stream (Right_File).all); + Close (Left_File); + Close (Right_File); + end Compare_Files; + + --------------------- + -- Compare_Streams -- + --------------------- + + procedure Compare_Streams + (Left, Right : in out Ada.Streams.Root_Stream_Type'Class) + is + Left_Buffer, Right_Buffer : Stream_Element_Array (0 .. 16#FFF#); + Left_Last, Right_Last : Stream_Element_Offset; + begin + loop + Read (Left, Left_Buffer, Left_Last); + Read (Right, Right_Buffer, Right_Last); + + if Left_Last /= Right_Last then + Ada.Text_IO.Put_Line ("Compare error :" + & Stream_Element_Offset'Image (Left_Last) + & " /= " + & Stream_Element_Offset'Image (Right_Last)); + + raise Constraint_Error; + + elsif Left_Buffer (0 .. Left_Last) + /= Right_Buffer (0 .. Right_Last) + then + Ada.Text_IO.Put_Line ("ERROR: IN and OUT files is not equal."); + raise Constraint_Error; + + end if; + + exit when Left_Last < Left_Buffer'Last; + end loop; + end Compare_Streams; + + ------------------ + -- Copy_Streams -- + ------------------ + + procedure Copy_Streams + (Source, Target : in out Ada.Streams.Root_Stream_Type'Class; + Buffer_Size : in Stream_Element_Offset := 1024) + is + Buffer : Stream_Element_Array (1 .. Buffer_Size); + Last : Stream_Element_Offset; + begin + loop + Read (Source, Buffer, Last); + Write (Target, Buffer (1 .. Last)); + + exit when Last < Buffer'Last; + end loop; + end Copy_Streams; + + ------------- + -- Data_In -- + ------------- + + procedure Data_In + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset) is + begin + Read (File_In, Item, Last); + end Data_In; + + -------------- + -- Data_Out -- + -------------- + + procedure Data_Out (Item : in Stream_Element_Array) is + begin + Write (File_Out, Item); + end Data_Out; + + ------------------- + -- Generate_File -- + ------------------- + + procedure Generate_File is + subtype Visible_Symbols is Stream_Element range 16#20# .. 16#7E#; + + package Random_Elements is + new Ada.Numerics.Discrete_Random (Visible_Symbols); + + Gen : Random_Elements.Generator; + Buffer : Stream_Element_Array := (1 .. 77 => 16#20#) & 10; + + Buffer_Count : constant Count := File_Size / Buffer'Length; + -- Number of same buffers in the packet. + + Density : constant Count := 30; -- from 0 to Buffer'Length - 2; + + procedure Fill_Buffer (J, D : in Count); + -- Change the part of the buffer. + + ----------------- + -- Fill_Buffer -- + ----------------- + + procedure Fill_Buffer (J, D : in Count) is + begin + for K in 0 .. D loop + Buffer + (Stream_Element_Offset ((J + K) mod (Buffer'Length - 1) + 1)) + := Random_Elements.Random (Gen); + + end loop; + end Fill_Buffer; + + begin + Random_Elements.Reset (Gen, Init_Random); + + Create (File_In, Out_File, In_File_Name); + + Fill_Buffer (1, Buffer'Length - 2); + + for J in 1 .. Buffer_Count loop + Write (File_In, Buffer); + + Fill_Buffer (J, Density); + end loop; + + -- fill remain size. + + Write + (File_In, + Buffer + (1 .. Stream_Element_Offset + (File_Size - Buffer'Length * Buffer_Count))); + + Flush (File_In); + Close (File_In); + end Generate_File; + + --------------------- + -- Print_Statistic -- + --------------------- + + procedure Print_Statistic (Msg : String; Data_Size : ZLib.Count) is + use Ada.Calendar; + use Ada.Text_IO; + + package Count_IO is new Integer_IO (ZLib.Count); + + Curr_Dur : Duration := Clock - Time_Stamp; + begin + Put (Msg); + + Set_Col (20); + Ada.Text_IO.Put ("size ="); + + Count_IO.Put + (Data_Size, + Width => Stream_IO.Count'Image (File_Size)'Length); + + Put_Line (" duration =" & Duration'Image (Curr_Dur)); + end Print_Statistic; + + ----------- + -- Stamp -- + ----------- + + procedure Stamp is + begin + Time_Stamp := Ada.Calendar.Clock; + end Stamp; + +begin + Ada.Text_IO.Put_Line ("ZLib " & ZLib.Version); + + loop + Generate_File; + + for Level in ZLib.Compression_Level'Range loop + + Ada.Text_IO.Put_Line ("Level =" + & ZLib.Compression_Level'Image (Level)); + + -- Test generic interface. + Open (File_In, In_File, In_File_Name); + Create (File_Out, Out_File, Z_File_Name); + + Stamp; + + -- Deflate using generic instantiation. + + ZLib.Deflate_Init + (Filter => Filter, + Level => Level, + Strategy => Strategy, + Header => Header); + + Translate (Filter); + Print_Statistic ("Generic compress", ZLib.Total_Out (Filter)); + ZLib.Close (Filter); + + Close (File_In); + Close (File_Out); + + Open (File_In, In_File, Z_File_Name); + Create (File_Out, Out_File, Out_File_Name); + + Stamp; + + -- Inflate using generic instantiation. + + ZLib.Inflate_Init (Filter, Header => Header); + + Translate (Filter); + Print_Statistic ("Generic decompress", ZLib.Total_Out (Filter)); + + ZLib.Close (Filter); + + Close (File_In); + Close (File_Out); + + Compare_Files (In_File_Name, Out_File_Name); + + -- Test stream interface. + + -- Compress to the back stream. + + Open (File_In, In_File, In_File_Name); + Create (File_Back, Out_File, Z_File_Name); + + Stamp; + + ZLib.Streams.Create + (Stream => File_Z, + Mode => ZLib.Streams.Out_Stream, + Back => ZLib.Streams.Stream_Access + (Stream (File_Back)), + Back_Compressed => True, + Level => Level, + Strategy => Strategy, + Header => Header); + + Copy_Streams + (Source => Stream (File_In).all, + Target => File_Z); + + -- Flushing internal buffers to the back stream. + + ZLib.Streams.Flush (File_Z, ZLib.Finish); + + Print_Statistic ("Write compress", + ZLib.Streams.Write_Total_Out (File_Z)); + + ZLib.Streams.Close (File_Z); + + Close (File_In); + Close (File_Back); + + -- Compare reading from original file and from + -- decompression stream. + + Open (File_In, In_File, In_File_Name); + Open (File_Back, In_File, Z_File_Name); + + ZLib.Streams.Create + (Stream => File_Z, + Mode => ZLib.Streams.In_Stream, + Back => ZLib.Streams.Stream_Access + (Stream (File_Back)), + Back_Compressed => True, + Header => Header); + + Stamp; + Compare_Streams (Stream (File_In).all, File_Z); + + Print_Statistic ("Read decompress", + ZLib.Streams.Read_Total_Out (File_Z)); + + ZLib.Streams.Close (File_Z); + Close (File_In); + Close (File_Back); + + -- Compress by reading from compression stream. + + Open (File_Back, In_File, In_File_Name); + Create (File_Out, Out_File, Z_File_Name); + + ZLib.Streams.Create + (Stream => File_Z, + Mode => ZLib.Streams.In_Stream, + Back => ZLib.Streams.Stream_Access + (Stream (File_Back)), + Back_Compressed => False, + Level => Level, + Strategy => Strategy, + Header => Header); + + Stamp; + Copy_Streams + (Source => File_Z, + Target => Stream (File_Out).all); + + Print_Statistic ("Read compress", + ZLib.Streams.Read_Total_Out (File_Z)); + + ZLib.Streams.Close (File_Z); + + Close (File_Out); + Close (File_Back); + + -- Decompress to decompression stream. + + Open (File_In, In_File, Z_File_Name); + Create (File_Back, Out_File, Out_File_Name); + + ZLib.Streams.Create + (Stream => File_Z, + Mode => ZLib.Streams.Out_Stream, + Back => ZLib.Streams.Stream_Access + (Stream (File_Back)), + Back_Compressed => False, + Header => Header); + + Stamp; + + Copy_Streams + (Source => Stream (File_In).all, + Target => File_Z); + + Print_Statistic ("Write decompress", + ZLib.Streams.Write_Total_Out (File_Z)); + + ZLib.Streams.Close (File_Z); + Close (File_In); + Close (File_Back); + + Compare_Files (In_File_Name, Out_File_Name); + end loop; + + Ada.Text_IO.Put_Line (Count'Image (File_Size) & " Ok."); + + exit when not Continuous; + + File_Size := File_Size + 1; + end loop; +end Test; diff --git a/zlib-1.2.11/contrib/ada/zlib-streams.adb b/zlib-1.2.11/contrib/ada/zlib-streams.adb new file mode 100644 index 00000000..b6497bae --- /dev/null +++ b/zlib-1.2.11/contrib/ada/zlib-streams.adb @@ -0,0 +1,225 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: zlib-streams.adb,v 1.10 2004/05/31 10:53:40 vagul Exp $ + +with Ada.Unchecked_Deallocation; + +package body ZLib.Streams is + + ----------- + -- Close -- + ----------- + + procedure Close (Stream : in out Stream_Type) is + procedure Free is new Ada.Unchecked_Deallocation + (Stream_Element_Array, Buffer_Access); + begin + if Stream.Mode = Out_Stream or Stream.Mode = Duplex then + -- We should flush the data written by the writer. + + Flush (Stream, Finish); + + Close (Stream.Writer); + end if; + + if Stream.Mode = In_Stream or Stream.Mode = Duplex then + Close (Stream.Reader); + Free (Stream.Buffer); + end if; + end Close; + + ------------ + -- Create -- + ------------ + + procedure Create + (Stream : out Stream_Type; + Mode : in Stream_Mode; + Back : in Stream_Access; + Back_Compressed : in Boolean; + Level : in Compression_Level := Default_Compression; + Strategy : in Strategy_Type := Default_Strategy; + Header : in Header_Type := Default; + Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset + := Default_Buffer_Size; + Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset + := Default_Buffer_Size) + is + + subtype Buffer_Subtype is Stream_Element_Array (1 .. Read_Buffer_Size); + + procedure Init_Filter + (Filter : in out Filter_Type; + Compress : in Boolean); + + ----------------- + -- Init_Filter -- + ----------------- + + procedure Init_Filter + (Filter : in out Filter_Type; + Compress : in Boolean) is + begin + if Compress then + Deflate_Init + (Filter, Level, Strategy, Header => Header); + else + Inflate_Init (Filter, Header => Header); + end if; + end Init_Filter; + + begin + Stream.Back := Back; + Stream.Mode := Mode; + + if Mode = Out_Stream or Mode = Duplex then + Init_Filter (Stream.Writer, Back_Compressed); + Stream.Buffer_Size := Write_Buffer_Size; + else + Stream.Buffer_Size := 0; + end if; + + if Mode = In_Stream or Mode = Duplex then + Init_Filter (Stream.Reader, not Back_Compressed); + + Stream.Buffer := new Buffer_Subtype; + Stream.Rest_First := Stream.Buffer'Last + 1; + Stream.Rest_Last := Stream.Buffer'Last; + end if; + end Create; + + ----------- + -- Flush -- + ----------- + + procedure Flush + (Stream : in out Stream_Type; + Mode : in Flush_Mode := Sync_Flush) + is + Buffer : Stream_Element_Array (1 .. Stream.Buffer_Size); + Last : Stream_Element_Offset; + begin + loop + Flush (Stream.Writer, Buffer, Last, Mode); + + Ada.Streams.Write (Stream.Back.all, Buffer (1 .. Last)); + + exit when Last < Buffer'Last; + end loop; + end Flush; + + ------------- + -- Is_Open -- + ------------- + + function Is_Open (Stream : Stream_Type) return Boolean is + begin + return Is_Open (Stream.Reader) or else Is_Open (Stream.Writer); + end Is_Open; + + ---------- + -- Read -- + ---------- + + procedure Read + (Stream : in out Stream_Type; + Item : out Stream_Element_Array; + Last : out Stream_Element_Offset) + is + + procedure Read + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset); + + ---------- + -- Read -- + ---------- + + procedure Read + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset) is + begin + Ada.Streams.Read (Stream.Back.all, Item, Last); + end Read; + + procedure Read is new ZLib.Read + (Read => Read, + Buffer => Stream.Buffer.all, + Rest_First => Stream.Rest_First, + Rest_Last => Stream.Rest_Last); + + begin + Read (Stream.Reader, Item, Last); + end Read; + + ------------------- + -- Read_Total_In -- + ------------------- + + function Read_Total_In (Stream : in Stream_Type) return Count is + begin + return Total_In (Stream.Reader); + end Read_Total_In; + + -------------------- + -- Read_Total_Out -- + -------------------- + + function Read_Total_Out (Stream : in Stream_Type) return Count is + begin + return Total_Out (Stream.Reader); + end Read_Total_Out; + + ----------- + -- Write -- + ----------- + + procedure Write + (Stream : in out Stream_Type; + Item : in Stream_Element_Array) + is + + procedure Write (Item : in Stream_Element_Array); + + ----------- + -- Write -- + ----------- + + procedure Write (Item : in Stream_Element_Array) is + begin + Ada.Streams.Write (Stream.Back.all, Item); + end Write; + + procedure Write is new ZLib.Write + (Write => Write, + Buffer_Size => Stream.Buffer_Size); + + begin + Write (Stream.Writer, Item, No_Flush); + end Write; + + -------------------- + -- Write_Total_In -- + -------------------- + + function Write_Total_In (Stream : in Stream_Type) return Count is + begin + return Total_In (Stream.Writer); + end Write_Total_In; + + --------------------- + -- Write_Total_Out -- + --------------------- + + function Write_Total_Out (Stream : in Stream_Type) return Count is + begin + return Total_Out (Stream.Writer); + end Write_Total_Out; + +end ZLib.Streams; diff --git a/zlib-1.2.11/contrib/ada/zlib-streams.ads b/zlib-1.2.11/contrib/ada/zlib-streams.ads new file mode 100644 index 00000000..8e26cd45 --- /dev/null +++ b/zlib-1.2.11/contrib/ada/zlib-streams.ads @@ -0,0 +1,114 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: zlib-streams.ads,v 1.12 2004/05/31 10:53:40 vagul Exp $ + +package ZLib.Streams is + + type Stream_Mode is (In_Stream, Out_Stream, Duplex); + + type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class; + + type Stream_Type is + new Ada.Streams.Root_Stream_Type with private; + + procedure Read + (Stream : in out Stream_Type; + Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset); + + procedure Write + (Stream : in out Stream_Type; + Item : in Ada.Streams.Stream_Element_Array); + + procedure Flush + (Stream : in out Stream_Type; + Mode : in Flush_Mode := Sync_Flush); + -- Flush the written data to the back stream, + -- all data placed to the compressor is flushing to the Back stream. + -- Should not be used until necessary, because it is decreasing + -- compression. + + function Read_Total_In (Stream : in Stream_Type) return Count; + pragma Inline (Read_Total_In); + -- Return total number of bytes read from back stream so far. + + function Read_Total_Out (Stream : in Stream_Type) return Count; + pragma Inline (Read_Total_Out); + -- Return total number of bytes read so far. + + function Write_Total_In (Stream : in Stream_Type) return Count; + pragma Inline (Write_Total_In); + -- Return total number of bytes written so far. + + function Write_Total_Out (Stream : in Stream_Type) return Count; + pragma Inline (Write_Total_Out); + -- Return total number of bytes written to the back stream. + + procedure Create + (Stream : out Stream_Type; + Mode : in Stream_Mode; + Back : in Stream_Access; + Back_Compressed : in Boolean; + Level : in Compression_Level := Default_Compression; + Strategy : in Strategy_Type := Default_Strategy; + Header : in Header_Type := Default; + Read_Buffer_Size : in Ada.Streams.Stream_Element_Offset + := Default_Buffer_Size; + Write_Buffer_Size : in Ada.Streams.Stream_Element_Offset + := Default_Buffer_Size); + -- Create the Comression/Decompression stream. + -- If mode is In_Stream then Write operation is disabled. + -- If mode is Out_Stream then Read operation is disabled. + + -- If Back_Compressed is true then + -- Data written to the Stream is compressing to the Back stream + -- and data read from the Stream is decompressed data from the Back stream. + + -- If Back_Compressed is false then + -- Data written to the Stream is decompressing to the Back stream + -- and data read from the Stream is compressed data from the Back stream. + + -- !!! When the Need_Header is False ZLib-Ada is using undocumented + -- ZLib 1.1.4 functionality to do not create/wait for ZLib headers. + + function Is_Open (Stream : Stream_Type) return Boolean; + + procedure Close (Stream : in out Stream_Type); + +private + + use Ada.Streams; + + type Buffer_Access is access all Stream_Element_Array; + + type Stream_Type + is new Root_Stream_Type with + record + Mode : Stream_Mode; + + Buffer : Buffer_Access; + Rest_First : Stream_Element_Offset; + Rest_Last : Stream_Element_Offset; + -- Buffer for Read operation. + -- We need to have this buffer in the record + -- because not all read data from back stream + -- could be processed during the read operation. + + Buffer_Size : Stream_Element_Offset; + -- Buffer size for write operation. + -- We do not need to have this buffer + -- in the record because all data could be + -- processed in the write operation. + + Back : Stream_Access; + Reader : Filter_Type; + Writer : Filter_Type; + end record; + +end ZLib.Streams; diff --git a/zlib-1.2.11/contrib/ada/zlib-thin.adb b/zlib-1.2.11/contrib/ada/zlib-thin.adb new file mode 100644 index 00000000..0ca4a712 --- /dev/null +++ b/zlib-1.2.11/contrib/ada/zlib-thin.adb @@ -0,0 +1,141 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: zlib-thin.adb,v 1.8 2003/12/14 18:27:31 vagul Exp $ + +package body ZLib.Thin is + + ZLIB_VERSION : constant Chars_Ptr := zlibVersion; + + Z_Stream_Size : constant Int := Z_Stream'Size / System.Storage_Unit; + + -------------- + -- Avail_In -- + -------------- + + function Avail_In (Strm : in Z_Stream) return UInt is + begin + return Strm.Avail_In; + end Avail_In; + + --------------- + -- Avail_Out -- + --------------- + + function Avail_Out (Strm : in Z_Stream) return UInt is + begin + return Strm.Avail_Out; + end Avail_Out; + + ------------------ + -- Deflate_Init -- + ------------------ + + function Deflate_Init + (strm : Z_Streamp; + level : Int; + method : Int; + windowBits : Int; + memLevel : Int; + strategy : Int) + return Int is + begin + return deflateInit2 + (strm, + level, + method, + windowBits, + memLevel, + strategy, + ZLIB_VERSION, + Z_Stream_Size); + end Deflate_Init; + + ------------------ + -- Inflate_Init -- + ------------------ + + function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int is + begin + return inflateInit2 (strm, windowBits, ZLIB_VERSION, Z_Stream_Size); + end Inflate_Init; + + ------------------------ + -- Last_Error_Message -- + ------------------------ + + function Last_Error_Message (Strm : in Z_Stream) return String is + use Interfaces.C.Strings; + begin + if Strm.msg = Null_Ptr then + return ""; + else + return Value (Strm.msg); + end if; + end Last_Error_Message; + + ------------ + -- Set_In -- + ------------ + + procedure Set_In + (Strm : in out Z_Stream; + Buffer : in Voidp; + Size : in UInt) is + begin + Strm.Next_In := Buffer; + Strm.Avail_In := Size; + end Set_In; + + ------------------ + -- Set_Mem_Func -- + ------------------ + + procedure Set_Mem_Func + (Strm : in out Z_Stream; + Opaque : in Voidp; + Alloc : in alloc_func; + Free : in free_func) is + begin + Strm.opaque := Opaque; + Strm.zalloc := Alloc; + Strm.zfree := Free; + end Set_Mem_Func; + + ------------- + -- Set_Out -- + ------------- + + procedure Set_Out + (Strm : in out Z_Stream; + Buffer : in Voidp; + Size : in UInt) is + begin + Strm.Next_Out := Buffer; + Strm.Avail_Out := Size; + end Set_Out; + + -------------- + -- Total_In -- + -------------- + + function Total_In (Strm : in Z_Stream) return ULong is + begin + return Strm.Total_In; + end Total_In; + + --------------- + -- Total_Out -- + --------------- + + function Total_Out (Strm : in Z_Stream) return ULong is + begin + return Strm.Total_Out; + end Total_Out; + +end ZLib.Thin; diff --git a/zlib-1.2.11/contrib/ada/zlib-thin.ads b/zlib-1.2.11/contrib/ada/zlib-thin.ads new file mode 100644 index 00000000..810173cf --- /dev/null +++ b/zlib-1.2.11/contrib/ada/zlib-thin.ads @@ -0,0 +1,450 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2003 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: zlib-thin.ads,v 1.11 2004/07/23 06:33:11 vagul Exp $ + +with Interfaces.C.Strings; + +with System; + +private package ZLib.Thin is + + -- From zconf.h + + MAX_MEM_LEVEL : constant := 9; -- zconf.h:105 + -- zconf.h:105 + MAX_WBITS : constant := 15; -- zconf.h:115 + -- 32K LZ77 window + -- zconf.h:115 + SEEK_SET : constant := 8#0000#; -- zconf.h:244 + -- Seek from beginning of file. + -- zconf.h:244 + SEEK_CUR : constant := 1; -- zconf.h:245 + -- Seek from current position. + -- zconf.h:245 + SEEK_END : constant := 2; -- zconf.h:246 + -- Set file pointer to EOF plus "offset" + -- zconf.h:246 + + type Byte is new Interfaces.C.unsigned_char; -- 8 bits + -- zconf.h:214 + type UInt is new Interfaces.C.unsigned; -- 16 bits or more + -- zconf.h:216 + type Int is new Interfaces.C.int; + + type ULong is new Interfaces.C.unsigned_long; -- 32 bits or more + -- zconf.h:217 + subtype Chars_Ptr is Interfaces.C.Strings.chars_ptr; + + type ULong_Access is access ULong; + type Int_Access is access Int; + + subtype Voidp is System.Address; -- zconf.h:232 + + subtype Byte_Access is Voidp; + + Nul : constant Voidp := System.Null_Address; + -- end from zconf + + Z_NO_FLUSH : constant := 8#0000#; -- zlib.h:125 + -- zlib.h:125 + Z_PARTIAL_FLUSH : constant := 1; -- zlib.h:126 + -- will be removed, use + -- Z_SYNC_FLUSH instead + -- zlib.h:126 + Z_SYNC_FLUSH : constant := 2; -- zlib.h:127 + -- zlib.h:127 + Z_FULL_FLUSH : constant := 3; -- zlib.h:128 + -- zlib.h:128 + Z_FINISH : constant := 4; -- zlib.h:129 + -- zlib.h:129 + Z_OK : constant := 8#0000#; -- zlib.h:132 + -- zlib.h:132 + Z_STREAM_END : constant := 1; -- zlib.h:133 + -- zlib.h:133 + Z_NEED_DICT : constant := 2; -- zlib.h:134 + -- zlib.h:134 + Z_ERRNO : constant := -1; -- zlib.h:135 + -- zlib.h:135 + Z_STREAM_ERROR : constant := -2; -- zlib.h:136 + -- zlib.h:136 + Z_DATA_ERROR : constant := -3; -- zlib.h:137 + -- zlib.h:137 + Z_MEM_ERROR : constant := -4; -- zlib.h:138 + -- zlib.h:138 + Z_BUF_ERROR : constant := -5; -- zlib.h:139 + -- zlib.h:139 + Z_VERSION_ERROR : constant := -6; -- zlib.h:140 + -- zlib.h:140 + Z_NO_COMPRESSION : constant := 8#0000#; -- zlib.h:145 + -- zlib.h:145 + Z_BEST_SPEED : constant := 1; -- zlib.h:146 + -- zlib.h:146 + Z_BEST_COMPRESSION : constant := 9; -- zlib.h:147 + -- zlib.h:147 + Z_DEFAULT_COMPRESSION : constant := -1; -- zlib.h:148 + -- zlib.h:148 + Z_FILTERED : constant := 1; -- zlib.h:151 + -- zlib.h:151 + Z_HUFFMAN_ONLY : constant := 2; -- zlib.h:152 + -- zlib.h:152 + Z_DEFAULT_STRATEGY : constant := 8#0000#; -- zlib.h:153 + -- zlib.h:153 + Z_BINARY : constant := 8#0000#; -- zlib.h:156 + -- zlib.h:156 + Z_ASCII : constant := 1; -- zlib.h:157 + -- zlib.h:157 + Z_UNKNOWN : constant := 2; -- zlib.h:158 + -- zlib.h:158 + Z_DEFLATED : constant := 8; -- zlib.h:161 + -- zlib.h:161 + Z_NULL : constant := 8#0000#; -- zlib.h:164 + -- for initializing zalloc, zfree, opaque + -- zlib.h:164 + type gzFile is new Voidp; -- zlib.h:646 + + type Z_Stream is private; + + type Z_Streamp is access all Z_Stream; -- zlib.h:89 + + type alloc_func is access function + (Opaque : Voidp; + Items : UInt; + Size : UInt) + return Voidp; -- zlib.h:63 + + type free_func is access procedure (opaque : Voidp; address : Voidp); + + function zlibVersion return Chars_Ptr; + + function Deflate (strm : Z_Streamp; flush : Int) return Int; + + function DeflateEnd (strm : Z_Streamp) return Int; + + function Inflate (strm : Z_Streamp; flush : Int) return Int; + + function InflateEnd (strm : Z_Streamp) return Int; + + function deflateSetDictionary + (strm : Z_Streamp; + dictionary : Byte_Access; + dictLength : UInt) + return Int; + + function deflateCopy (dest : Z_Streamp; source : Z_Streamp) return Int; + -- zlib.h:478 + + function deflateReset (strm : Z_Streamp) return Int; -- zlib.h:495 + + function deflateParams + (strm : Z_Streamp; + level : Int; + strategy : Int) + return Int; -- zlib.h:506 + + function inflateSetDictionary + (strm : Z_Streamp; + dictionary : Byte_Access; + dictLength : UInt) + return Int; -- zlib.h:548 + + function inflateSync (strm : Z_Streamp) return Int; -- zlib.h:565 + + function inflateReset (strm : Z_Streamp) return Int; -- zlib.h:580 + + function compress + (dest : Byte_Access; + destLen : ULong_Access; + source : Byte_Access; + sourceLen : ULong) + return Int; -- zlib.h:601 + + function compress2 + (dest : Byte_Access; + destLen : ULong_Access; + source : Byte_Access; + sourceLen : ULong; + level : Int) + return Int; -- zlib.h:615 + + function uncompress + (dest : Byte_Access; + destLen : ULong_Access; + source : Byte_Access; + sourceLen : ULong) + return Int; + + function gzopen (path : Chars_Ptr; mode : Chars_Ptr) return gzFile; + + function gzdopen (fd : Int; mode : Chars_Ptr) return gzFile; + + function gzsetparams + (file : gzFile; + level : Int; + strategy : Int) + return Int; + + function gzread + (file : gzFile; + buf : Voidp; + len : UInt) + return Int; + + function gzwrite + (file : in gzFile; + buf : in Voidp; + len : in UInt) + return Int; + + function gzprintf (file : in gzFile; format : in Chars_Ptr) return Int; + + function gzputs (file : in gzFile; s : in Chars_Ptr) return Int; + + function gzgets + (file : gzFile; + buf : Chars_Ptr; + len : Int) + return Chars_Ptr; + + function gzputc (file : gzFile; char : Int) return Int; + + function gzgetc (file : gzFile) return Int; + + function gzflush (file : gzFile; flush : Int) return Int; + + function gzseek + (file : gzFile; + offset : Int; + whence : Int) + return Int; + + function gzrewind (file : gzFile) return Int; + + function gztell (file : gzFile) return Int; + + function gzeof (file : gzFile) return Int; + + function gzclose (file : gzFile) return Int; + + function gzerror (file : gzFile; errnum : Int_Access) return Chars_Ptr; + + function adler32 + (adler : ULong; + buf : Byte_Access; + len : UInt) + return ULong; + + function crc32 + (crc : ULong; + buf : Byte_Access; + len : UInt) + return ULong; + + function deflateInit + (strm : Z_Streamp; + level : Int; + version : Chars_Ptr; + stream_size : Int) + return Int; + + function deflateInit2 + (strm : Z_Streamp; + level : Int; + method : Int; + windowBits : Int; + memLevel : Int; + strategy : Int; + version : Chars_Ptr; + stream_size : Int) + return Int; + + function Deflate_Init + (strm : Z_Streamp; + level : Int; + method : Int; + windowBits : Int; + memLevel : Int; + strategy : Int) + return Int; + pragma Inline (Deflate_Init); + + function inflateInit + (strm : Z_Streamp; + version : Chars_Ptr; + stream_size : Int) + return Int; + + function inflateInit2 + (strm : in Z_Streamp; + windowBits : in Int; + version : in Chars_Ptr; + stream_size : in Int) + return Int; + + function inflateBackInit + (strm : in Z_Streamp; + windowBits : in Int; + window : in Byte_Access; + version : in Chars_Ptr; + stream_size : in Int) + return Int; + -- Size of window have to be 2**windowBits. + + function Inflate_Init (strm : Z_Streamp; windowBits : Int) return Int; + pragma Inline (Inflate_Init); + + function zError (err : Int) return Chars_Ptr; + + function inflateSyncPoint (z : Z_Streamp) return Int; + + function get_crc_table return ULong_Access; + + -- Interface to the available fields of the z_stream structure. + -- The application must update next_in and avail_in when avail_in has + -- dropped to zero. It must update next_out and avail_out when avail_out + -- has dropped to zero. The application must initialize zalloc, zfree and + -- opaque before calling the init function. + + procedure Set_In + (Strm : in out Z_Stream; + Buffer : in Voidp; + Size : in UInt); + pragma Inline (Set_In); + + procedure Set_Out + (Strm : in out Z_Stream; + Buffer : in Voidp; + Size : in UInt); + pragma Inline (Set_Out); + + procedure Set_Mem_Func + (Strm : in out Z_Stream; + Opaque : in Voidp; + Alloc : in alloc_func; + Free : in free_func); + pragma Inline (Set_Mem_Func); + + function Last_Error_Message (Strm : in Z_Stream) return String; + pragma Inline (Last_Error_Message); + + function Avail_Out (Strm : in Z_Stream) return UInt; + pragma Inline (Avail_Out); + + function Avail_In (Strm : in Z_Stream) return UInt; + pragma Inline (Avail_In); + + function Total_In (Strm : in Z_Stream) return ULong; + pragma Inline (Total_In); + + function Total_Out (Strm : in Z_Stream) return ULong; + pragma Inline (Total_Out); + + function inflateCopy + (dest : in Z_Streamp; + Source : in Z_Streamp) + return Int; + + function compressBound (Source_Len : in ULong) return ULong; + + function deflateBound + (Strm : in Z_Streamp; + Source_Len : in ULong) + return ULong; + + function gzungetc (C : in Int; File : in gzFile) return Int; + + function zlibCompileFlags return ULong; + +private + + type Z_Stream is record -- zlib.h:68 + Next_In : Voidp := Nul; -- next input byte + Avail_In : UInt := 0; -- number of bytes available at next_in + Total_In : ULong := 0; -- total nb of input bytes read so far + Next_Out : Voidp := Nul; -- next output byte should be put there + Avail_Out : UInt := 0; -- remaining free space at next_out + Total_Out : ULong := 0; -- total nb of bytes output so far + msg : Chars_Ptr; -- last error message, NULL if no error + state : Voidp; -- not visible by applications + zalloc : alloc_func := null; -- used to allocate the internal state + zfree : free_func := null; -- used to free the internal state + opaque : Voidp; -- private data object passed to + -- zalloc and zfree + data_type : Int; -- best guess about the data type: + -- ascii or binary + adler : ULong; -- adler32 value of the uncompressed + -- data + reserved : ULong; -- reserved for future use + end record; + + pragma Convention (C, Z_Stream); + + pragma Import (C, zlibVersion, "zlibVersion"); + pragma Import (C, Deflate, "deflate"); + pragma Import (C, DeflateEnd, "deflateEnd"); + pragma Import (C, Inflate, "inflate"); + pragma Import (C, InflateEnd, "inflateEnd"); + pragma Import (C, deflateSetDictionary, "deflateSetDictionary"); + pragma Import (C, deflateCopy, "deflateCopy"); + pragma Import (C, deflateReset, "deflateReset"); + pragma Import (C, deflateParams, "deflateParams"); + pragma Import (C, inflateSetDictionary, "inflateSetDictionary"); + pragma Import (C, inflateSync, "inflateSync"); + pragma Import (C, inflateReset, "inflateReset"); + pragma Import (C, compress, "compress"); + pragma Import (C, compress2, "compress2"); + pragma Import (C, uncompress, "uncompress"); + pragma Import (C, gzopen, "gzopen"); + pragma Import (C, gzdopen, "gzdopen"); + pragma Import (C, gzsetparams, "gzsetparams"); + pragma Import (C, gzread, "gzread"); + pragma Import (C, gzwrite, "gzwrite"); + pragma Import (C, gzprintf, "gzprintf"); + pragma Import (C, gzputs, "gzputs"); + pragma Import (C, gzgets, "gzgets"); + pragma Import (C, gzputc, "gzputc"); + pragma Import (C, gzgetc, "gzgetc"); + pragma Import (C, gzflush, "gzflush"); + pragma Import (C, gzseek, "gzseek"); + pragma Import (C, gzrewind, "gzrewind"); + pragma Import (C, gztell, "gztell"); + pragma Import (C, gzeof, "gzeof"); + pragma Import (C, gzclose, "gzclose"); + pragma Import (C, gzerror, "gzerror"); + pragma Import (C, adler32, "adler32"); + pragma Import (C, crc32, "crc32"); + pragma Import (C, deflateInit, "deflateInit_"); + pragma Import (C, inflateInit, "inflateInit_"); + pragma Import (C, deflateInit2, "deflateInit2_"); + pragma Import (C, inflateInit2, "inflateInit2_"); + pragma Import (C, zError, "zError"); + pragma Import (C, inflateSyncPoint, "inflateSyncPoint"); + pragma Import (C, get_crc_table, "get_crc_table"); + + -- since zlib 1.2.0: + + pragma Import (C, inflateCopy, "inflateCopy"); + pragma Import (C, compressBound, "compressBound"); + pragma Import (C, deflateBound, "deflateBound"); + pragma Import (C, gzungetc, "gzungetc"); + pragma Import (C, zlibCompileFlags, "zlibCompileFlags"); + + pragma Import (C, inflateBackInit, "inflateBackInit_"); + + -- I stopped binding the inflateBack routines, because realize that + -- it does not support zlib and gzip headers for now, and have no + -- symmetric deflateBack routines. + -- ZLib-Ada is symmetric regarding deflate/inflate data transformation + -- and has a similar generic callback interface for the + -- deflate/inflate transformation based on the regular Deflate/Inflate + -- routines. + + -- pragma Import (C, inflateBack, "inflateBack"); + -- pragma Import (C, inflateBackEnd, "inflateBackEnd"); + +end ZLib.Thin; diff --git a/zlib-1.2.11/contrib/ada/zlib.adb b/zlib-1.2.11/contrib/ada/zlib.adb new file mode 100644 index 00000000..8b6fd686 --- /dev/null +++ b/zlib-1.2.11/contrib/ada/zlib.adb @@ -0,0 +1,701 @@ +---------------------------------------------------------------- +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2004 Dmitriy Anisimkov -- +-- -- +-- Open source license information is in the zlib.ads file. -- +---------------------------------------------------------------- + +-- $Id: zlib.adb,v 1.31 2004/09/06 06:53:19 vagul Exp $ + +with Ada.Exceptions; +with Ada.Unchecked_Conversion; +with Ada.Unchecked_Deallocation; + +with Interfaces.C.Strings; + +with ZLib.Thin; + +package body ZLib is + + use type Thin.Int; + + type Z_Stream is new Thin.Z_Stream; + + type Return_Code_Enum is + (OK, + STREAM_END, + NEED_DICT, + ERRNO, + STREAM_ERROR, + DATA_ERROR, + MEM_ERROR, + BUF_ERROR, + VERSION_ERROR); + + type Flate_Step_Function is access + function (Strm : in Thin.Z_Streamp; Flush : in Thin.Int) return Thin.Int; + pragma Convention (C, Flate_Step_Function); + + type Flate_End_Function is access + function (Ctrm : in Thin.Z_Streamp) return Thin.Int; + pragma Convention (C, Flate_End_Function); + + type Flate_Type is record + Step : Flate_Step_Function; + Done : Flate_End_Function; + end record; + + subtype Footer_Array is Stream_Element_Array (1 .. 8); + + Simple_GZip_Header : constant Stream_Element_Array (1 .. 10) + := (16#1f#, 16#8b#, -- Magic header + 16#08#, -- Z_DEFLATED + 16#00#, -- Flags + 16#00#, 16#00#, 16#00#, 16#00#, -- Time + 16#00#, -- XFlags + 16#03# -- OS code + ); + -- The simplest gzip header is not for informational, but just for + -- gzip format compatibility. + -- Note that some code below is using assumption + -- Simple_GZip_Header'Last > Footer_Array'Last, so do not make + -- Simple_GZip_Header'Last <= Footer_Array'Last. + + Return_Code : constant array (Thin.Int range <>) of Return_Code_Enum + := (0 => OK, + 1 => STREAM_END, + 2 => NEED_DICT, + -1 => ERRNO, + -2 => STREAM_ERROR, + -3 => DATA_ERROR, + -4 => MEM_ERROR, + -5 => BUF_ERROR, + -6 => VERSION_ERROR); + + Flate : constant array (Boolean) of Flate_Type + := (True => (Step => Thin.Deflate'Access, + Done => Thin.DeflateEnd'Access), + False => (Step => Thin.Inflate'Access, + Done => Thin.InflateEnd'Access)); + + Flush_Finish : constant array (Boolean) of Flush_Mode + := (True => Finish, False => No_Flush); + + procedure Raise_Error (Stream : in Z_Stream); + pragma Inline (Raise_Error); + + procedure Raise_Error (Message : in String); + pragma Inline (Raise_Error); + + procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int); + + procedure Free is new Ada.Unchecked_Deallocation + (Z_Stream, Z_Stream_Access); + + function To_Thin_Access is new Ada.Unchecked_Conversion + (Z_Stream_Access, Thin.Z_Streamp); + + procedure Translate_GZip + (Filter : in out Filter_Type; + In_Data : in Ada.Streams.Stream_Element_Array; + In_Last : out Ada.Streams.Stream_Element_Offset; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode); + -- Separate translate routine for make gzip header. + + procedure Translate_Auto + (Filter : in out Filter_Type; + In_Data : in Ada.Streams.Stream_Element_Array; + In_Last : out Ada.Streams.Stream_Element_Offset; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode); + -- translate routine without additional headers. + + ----------------- + -- Check_Error -- + ----------------- + + procedure Check_Error (Stream : in Z_Stream; Code : in Thin.Int) is + use type Thin.Int; + begin + if Code /= Thin.Z_OK then + Raise_Error + (Return_Code_Enum'Image (Return_Code (Code)) + & ": " & Last_Error_Message (Stream)); + end if; + end Check_Error; + + ----------- + -- Close -- + ----------- + + procedure Close + (Filter : in out Filter_Type; + Ignore_Error : in Boolean := False) + is + Code : Thin.Int; + begin + if not Ignore_Error and then not Is_Open (Filter) then + raise Status_Error; + end if; + + Code := Flate (Filter.Compression).Done (To_Thin_Access (Filter.Strm)); + + if Ignore_Error or else Code = Thin.Z_OK then + Free (Filter.Strm); + else + declare + Error_Message : constant String + := Last_Error_Message (Filter.Strm.all); + begin + Free (Filter.Strm); + Ada.Exceptions.Raise_Exception + (ZLib_Error'Identity, + Return_Code_Enum'Image (Return_Code (Code)) + & ": " & Error_Message); + end; + end if; + end Close; + + ----------- + -- CRC32 -- + ----------- + + function CRC32 + (CRC : in Unsigned_32; + Data : in Ada.Streams.Stream_Element_Array) + return Unsigned_32 + is + use Thin; + begin + return Unsigned_32 (crc32 (ULong (CRC), + Data'Address, + Data'Length)); + end CRC32; + + procedure CRC32 + (CRC : in out Unsigned_32; + Data : in Ada.Streams.Stream_Element_Array) is + begin + CRC := CRC32 (CRC, Data); + end CRC32; + + ------------------ + -- Deflate_Init -- + ------------------ + + procedure Deflate_Init + (Filter : in out Filter_Type; + Level : in Compression_Level := Default_Compression; + Strategy : in Strategy_Type := Default_Strategy; + Method : in Compression_Method := Deflated; + Window_Bits : in Window_Bits_Type := Default_Window_Bits; + Memory_Level : in Memory_Level_Type := Default_Memory_Level; + Header : in Header_Type := Default) + is + use type Thin.Int; + Win_Bits : Thin.Int := Thin.Int (Window_Bits); + begin + if Is_Open (Filter) then + raise Status_Error; + end if; + + -- We allow ZLib to make header only in case of default header type. + -- Otherwise we would either do header by ourselfs, or do not do + -- header at all. + + if Header = None or else Header = GZip then + Win_Bits := -Win_Bits; + end if; + + -- For the GZip CRC calculation and make headers. + + if Header = GZip then + Filter.CRC := 0; + Filter.Offset := Simple_GZip_Header'First; + else + Filter.Offset := Simple_GZip_Header'Last + 1; + end if; + + Filter.Strm := new Z_Stream; + Filter.Compression := True; + Filter.Stream_End := False; + Filter.Header := Header; + + if Thin.Deflate_Init + (To_Thin_Access (Filter.Strm), + Level => Thin.Int (Level), + method => Thin.Int (Method), + windowBits => Win_Bits, + memLevel => Thin.Int (Memory_Level), + strategy => Thin.Int (Strategy)) /= Thin.Z_OK + then + Raise_Error (Filter.Strm.all); + end if; + end Deflate_Init; + + ----------- + -- Flush -- + ----------- + + procedure Flush + (Filter : in out Filter_Type; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode) + is + No_Data : Stream_Element_Array := (1 .. 0 => 0); + Last : Stream_Element_Offset; + begin + Translate (Filter, No_Data, Last, Out_Data, Out_Last, Flush); + end Flush; + + ----------------------- + -- Generic_Translate -- + ----------------------- + + procedure Generic_Translate + (Filter : in out ZLib.Filter_Type; + In_Buffer_Size : in Integer := Default_Buffer_Size; + Out_Buffer_Size : in Integer := Default_Buffer_Size) + is + In_Buffer : Stream_Element_Array + (1 .. Stream_Element_Offset (In_Buffer_Size)); + Out_Buffer : Stream_Element_Array + (1 .. Stream_Element_Offset (Out_Buffer_Size)); + Last : Stream_Element_Offset; + In_Last : Stream_Element_Offset; + In_First : Stream_Element_Offset; + Out_Last : Stream_Element_Offset; + begin + Main : loop + Data_In (In_Buffer, Last); + + In_First := In_Buffer'First; + + loop + Translate + (Filter => Filter, + In_Data => In_Buffer (In_First .. Last), + In_Last => In_Last, + Out_Data => Out_Buffer, + Out_Last => Out_Last, + Flush => Flush_Finish (Last < In_Buffer'First)); + + if Out_Buffer'First <= Out_Last then + Data_Out (Out_Buffer (Out_Buffer'First .. Out_Last)); + end if; + + exit Main when Stream_End (Filter); + + -- The end of in buffer. + + exit when In_Last = Last; + + In_First := In_Last + 1; + end loop; + end loop Main; + + end Generic_Translate; + + ------------------ + -- Inflate_Init -- + ------------------ + + procedure Inflate_Init + (Filter : in out Filter_Type; + Window_Bits : in Window_Bits_Type := Default_Window_Bits; + Header : in Header_Type := Default) + is + use type Thin.Int; + Win_Bits : Thin.Int := Thin.Int (Window_Bits); + + procedure Check_Version; + -- Check the latest header types compatibility. + + procedure Check_Version is + begin + if Version <= "1.1.4" then + Raise_Error + ("Inflate header type " & Header_Type'Image (Header) + & " incompatible with ZLib version " & Version); + end if; + end Check_Version; + + begin + if Is_Open (Filter) then + raise Status_Error; + end if; + + case Header is + when None => + Check_Version; + + -- Inflate data without headers determined + -- by negative Win_Bits. + + Win_Bits := -Win_Bits; + when GZip => + Check_Version; + + -- Inflate gzip data defined by flag 16. + + Win_Bits := Win_Bits + 16; + when Auto => + Check_Version; + + -- Inflate with automatic detection + -- of gzip or native header defined by flag 32. + + Win_Bits := Win_Bits + 32; + when Default => null; + end case; + + Filter.Strm := new Z_Stream; + Filter.Compression := False; + Filter.Stream_End := False; + Filter.Header := Header; + + if Thin.Inflate_Init + (To_Thin_Access (Filter.Strm), Win_Bits) /= Thin.Z_OK + then + Raise_Error (Filter.Strm.all); + end if; + end Inflate_Init; + + ------------- + -- Is_Open -- + ------------- + + function Is_Open (Filter : in Filter_Type) return Boolean is + begin + return Filter.Strm /= null; + end Is_Open; + + ----------------- + -- Raise_Error -- + ----------------- + + procedure Raise_Error (Message : in String) is + begin + Ada.Exceptions.Raise_Exception (ZLib_Error'Identity, Message); + end Raise_Error; + + procedure Raise_Error (Stream : in Z_Stream) is + begin + Raise_Error (Last_Error_Message (Stream)); + end Raise_Error; + + ---------- + -- Read -- + ---------- + + procedure Read + (Filter : in out Filter_Type; + Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode := No_Flush) + is + In_Last : Stream_Element_Offset; + Item_First : Ada.Streams.Stream_Element_Offset := Item'First; + V_Flush : Flush_Mode := Flush; + + begin + pragma Assert (Rest_First in Buffer'First .. Buffer'Last + 1); + pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last); + + loop + if Rest_Last = Buffer'First - 1 then + V_Flush := Finish; + + elsif Rest_First > Rest_Last then + Read (Buffer, Rest_Last); + Rest_First := Buffer'First; + + if Rest_Last < Buffer'First then + V_Flush := Finish; + end if; + end if; + + Translate + (Filter => Filter, + In_Data => Buffer (Rest_First .. Rest_Last), + In_Last => In_Last, + Out_Data => Item (Item_First .. Item'Last), + Out_Last => Last, + Flush => V_Flush); + + Rest_First := In_Last + 1; + + exit when Stream_End (Filter) + or else Last = Item'Last + or else (Last >= Item'First and then Allow_Read_Some); + + Item_First := Last + 1; + end loop; + end Read; + + ---------------- + -- Stream_End -- + ---------------- + + function Stream_End (Filter : in Filter_Type) return Boolean is + begin + if Filter.Header = GZip and Filter.Compression then + return Filter.Stream_End + and then Filter.Offset = Footer_Array'Last + 1; + else + return Filter.Stream_End; + end if; + end Stream_End; + + -------------- + -- Total_In -- + -------------- + + function Total_In (Filter : in Filter_Type) return Count is + begin + return Count (Thin.Total_In (To_Thin_Access (Filter.Strm).all)); + end Total_In; + + --------------- + -- Total_Out -- + --------------- + + function Total_Out (Filter : in Filter_Type) return Count is + begin + return Count (Thin.Total_Out (To_Thin_Access (Filter.Strm).all)); + end Total_Out; + + --------------- + -- Translate -- + --------------- + + procedure Translate + (Filter : in out Filter_Type; + In_Data : in Ada.Streams.Stream_Element_Array; + In_Last : out Ada.Streams.Stream_Element_Offset; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode) is + begin + if Filter.Header = GZip and then Filter.Compression then + Translate_GZip + (Filter => Filter, + In_Data => In_Data, + In_Last => In_Last, + Out_Data => Out_Data, + Out_Last => Out_Last, + Flush => Flush); + else + Translate_Auto + (Filter => Filter, + In_Data => In_Data, + In_Last => In_Last, + Out_Data => Out_Data, + Out_Last => Out_Last, + Flush => Flush); + end if; + end Translate; + + -------------------- + -- Translate_Auto -- + -------------------- + + procedure Translate_Auto + (Filter : in out Filter_Type; + In_Data : in Ada.Streams.Stream_Element_Array; + In_Last : out Ada.Streams.Stream_Element_Offset; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode) + is + use type Thin.Int; + Code : Thin.Int; + + begin + if not Is_Open (Filter) then + raise Status_Error; + end if; + + if Out_Data'Length = 0 and then In_Data'Length = 0 then + raise Constraint_Error; + end if; + + Set_Out (Filter.Strm.all, Out_Data'Address, Out_Data'Length); + Set_In (Filter.Strm.all, In_Data'Address, In_Data'Length); + + Code := Flate (Filter.Compression).Step + (To_Thin_Access (Filter.Strm), + Thin.Int (Flush)); + + if Code = Thin.Z_STREAM_END then + Filter.Stream_End := True; + else + Check_Error (Filter.Strm.all, Code); + end if; + + In_Last := In_Data'Last + - Stream_Element_Offset (Avail_In (Filter.Strm.all)); + Out_Last := Out_Data'Last + - Stream_Element_Offset (Avail_Out (Filter.Strm.all)); + end Translate_Auto; + + -------------------- + -- Translate_GZip -- + -------------------- + + procedure Translate_GZip + (Filter : in out Filter_Type; + In_Data : in Ada.Streams.Stream_Element_Array; + In_Last : out Ada.Streams.Stream_Element_Offset; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode) + is + Out_First : Stream_Element_Offset; + + procedure Add_Data (Data : in Stream_Element_Array); + -- Add data to stream from the Filter.Offset till necessary, + -- used for add gzip headr/footer. + + procedure Put_32 + (Item : in out Stream_Element_Array; + Data : in Unsigned_32); + pragma Inline (Put_32); + + -------------- + -- Add_Data -- + -------------- + + procedure Add_Data (Data : in Stream_Element_Array) is + Data_First : Stream_Element_Offset renames Filter.Offset; + Data_Last : Stream_Element_Offset; + Data_Len : Stream_Element_Offset; -- -1 + Out_Len : Stream_Element_Offset; -- -1 + begin + Out_First := Out_Last + 1; + + if Data_First > Data'Last then + return; + end if; + + Data_Len := Data'Last - Data_First; + Out_Len := Out_Data'Last - Out_First; + + if Data_Len <= Out_Len then + Out_Last := Out_First + Data_Len; + Data_Last := Data'Last; + else + Out_Last := Out_Data'Last; + Data_Last := Data_First + Out_Len; + end if; + + Out_Data (Out_First .. Out_Last) := Data (Data_First .. Data_Last); + + Data_First := Data_Last + 1; + Out_First := Out_Last + 1; + end Add_Data; + + ------------ + -- Put_32 -- + ------------ + + procedure Put_32 + (Item : in out Stream_Element_Array; + Data : in Unsigned_32) + is + D : Unsigned_32 := Data; + begin + for J in Item'First .. Item'First + 3 loop + Item (J) := Stream_Element (D and 16#FF#); + D := Shift_Right (D, 8); + end loop; + end Put_32; + + begin + Out_Last := Out_Data'First - 1; + + if not Filter.Stream_End then + Add_Data (Simple_GZip_Header); + + Translate_Auto + (Filter => Filter, + In_Data => In_Data, + In_Last => In_Last, + Out_Data => Out_Data (Out_First .. Out_Data'Last), + Out_Last => Out_Last, + Flush => Flush); + + CRC32 (Filter.CRC, In_Data (In_Data'First .. In_Last)); + end if; + + if Filter.Stream_End and then Out_Last <= Out_Data'Last then + -- This detection method would work only when + -- Simple_GZip_Header'Last > Footer_Array'Last + + if Filter.Offset = Simple_GZip_Header'Last + 1 then + Filter.Offset := Footer_Array'First; + end if; + + declare + Footer : Footer_Array; + begin + Put_32 (Footer, Filter.CRC); + Put_32 (Footer (Footer'First + 4 .. Footer'Last), + Unsigned_32 (Total_In (Filter))); + Add_Data (Footer); + end; + end if; + end Translate_GZip; + + ------------- + -- Version -- + ------------- + + function Version return String is + begin + return Interfaces.C.Strings.Value (Thin.zlibVersion); + end Version; + + ----------- + -- Write -- + ----------- + + procedure Write + (Filter : in out Filter_Type; + Item : in Ada.Streams.Stream_Element_Array; + Flush : in Flush_Mode := No_Flush) + is + Buffer : Stream_Element_Array (1 .. Buffer_Size); + In_Last : Stream_Element_Offset; + Out_Last : Stream_Element_Offset; + In_First : Stream_Element_Offset := Item'First; + begin + if Item'Length = 0 and Flush = No_Flush then + return; + end if; + + loop + Translate + (Filter => Filter, + In_Data => Item (In_First .. Item'Last), + In_Last => In_Last, + Out_Data => Buffer, + Out_Last => Out_Last, + Flush => Flush); + + if Out_Last >= Buffer'First then + Write (Buffer (1 .. Out_Last)); + end if; + + exit when In_Last = Item'Last or Stream_End (Filter); + + In_First := In_Last + 1; + end loop; + end Write; + +end ZLib; diff --git a/zlib-1.2.11/contrib/ada/zlib.ads b/zlib-1.2.11/contrib/ada/zlib.ads new file mode 100644 index 00000000..79ffc409 --- /dev/null +++ b/zlib-1.2.11/contrib/ada/zlib.ads @@ -0,0 +1,328 @@ +------------------------------------------------------------------------------ +-- ZLib for Ada thick binding. -- +-- -- +-- Copyright (C) 2002-2004 Dmitriy Anisimkov -- +-- -- +-- This library 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 2 of the License, or (at -- +-- your option) any later version. -- +-- -- +-- This library 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 library; if not, write to the Free Software Foundation, -- +-- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -- +-- -- +-- As a special exception, if other files instantiate generics from this -- +-- unit, or you link this unit with other files to produce an executable, -- +-- this unit does not by itself cause the resulting executable to be -- +-- covered by the GNU General Public License. This exception does not -- +-- however invalidate any other reasons why the executable file might be -- +-- covered by the GNU Public License. -- +------------------------------------------------------------------------------ + +-- $Id: zlib.ads,v 1.26 2004/09/06 06:53:19 vagul Exp $ + +with Ada.Streams; + +with Interfaces; + +package ZLib is + + ZLib_Error : exception; + Status_Error : exception; + + type Compression_Level is new Integer range -1 .. 9; + + type Flush_Mode is private; + + type Compression_Method is private; + + type Window_Bits_Type is new Integer range 8 .. 15; + + type Memory_Level_Type is new Integer range 1 .. 9; + + type Unsigned_32 is new Interfaces.Unsigned_32; + + type Strategy_Type is private; + + type Header_Type is (None, Auto, Default, GZip); + -- Header type usage have a some limitation for inflate. + -- See comment for Inflate_Init. + + subtype Count is Ada.Streams.Stream_Element_Count; + + Default_Memory_Level : constant Memory_Level_Type := 8; + Default_Window_Bits : constant Window_Bits_Type := 15; + + ---------------------------------- + -- Compression method constants -- + ---------------------------------- + + Deflated : constant Compression_Method; + -- Only one method allowed in this ZLib version + + --------------------------------- + -- Compression level constants -- + --------------------------------- + + No_Compression : constant Compression_Level := 0; + Best_Speed : constant Compression_Level := 1; + Best_Compression : constant Compression_Level := 9; + Default_Compression : constant Compression_Level := -1; + + -------------------------- + -- Flush mode constants -- + -------------------------- + + No_Flush : constant Flush_Mode; + -- Regular way for compression, no flush + + Partial_Flush : constant Flush_Mode; + -- Will be removed, use Z_SYNC_FLUSH instead + + Sync_Flush : constant Flush_Mode; + -- All pending output is flushed to the output buffer and the output + -- is aligned on a byte boundary, so that the decompressor can get all + -- input data available so far. (In particular avail_in is zero after the + -- call if enough output space has been provided before the call.) + -- Flushing may degrade compression for some compression algorithms and so + -- it should be used only when necessary. + + Block_Flush : constant Flush_Mode; + -- Z_BLOCK requests that inflate() stop + -- if and when it get to the next deflate block boundary. When decoding the + -- zlib or gzip format, this will cause inflate() to return immediately + -- after the header and before the first block. When doing a raw inflate, + -- inflate() will go ahead and process the first block, and will return + -- when it gets to the end of that block, or when it runs out of data. + + Full_Flush : constant Flush_Mode; + -- All output is flushed as with SYNC_FLUSH, and the compression state + -- is reset so that decompression can restart from this point if previous + -- compressed data has been damaged or if random access is desired. Using + -- Full_Flush too often can seriously degrade the compression. + + Finish : constant Flush_Mode; + -- Just for tell the compressor that input data is complete. + + ------------------------------------ + -- Compression strategy constants -- + ------------------------------------ + + -- RLE stategy could be used only in version 1.2.0 and later. + + Filtered : constant Strategy_Type; + Huffman_Only : constant Strategy_Type; + RLE : constant Strategy_Type; + Default_Strategy : constant Strategy_Type; + + Default_Buffer_Size : constant := 4096; + + type Filter_Type is tagged limited private; + -- The filter is for compression and for decompression. + -- The usage of the type is depend of its initialization. + + function Version return String; + pragma Inline (Version); + -- Return string representation of the ZLib version. + + procedure Deflate_Init + (Filter : in out Filter_Type; + Level : in Compression_Level := Default_Compression; + Strategy : in Strategy_Type := Default_Strategy; + Method : in Compression_Method := Deflated; + Window_Bits : in Window_Bits_Type := Default_Window_Bits; + Memory_Level : in Memory_Level_Type := Default_Memory_Level; + Header : in Header_Type := Default); + -- Compressor initialization. + -- When Header parameter is Auto or Default, then default zlib header + -- would be provided for compressed data. + -- When Header is GZip, then gzip header would be set instead of + -- default header. + -- When Header is None, no header would be set for compressed data. + + procedure Inflate_Init + (Filter : in out Filter_Type; + Window_Bits : in Window_Bits_Type := Default_Window_Bits; + Header : in Header_Type := Default); + -- Decompressor initialization. + -- Default header type mean that ZLib default header is expecting in the + -- input compressed stream. + -- Header type None mean that no header is expecting in the input stream. + -- GZip header type mean that GZip header is expecting in the + -- input compressed stream. + -- Auto header type mean that header type (GZip or Native) would be + -- detected automatically in the input stream. + -- Note that header types parameter values None, GZip and Auto are + -- supported for inflate routine only in ZLib versions 1.2.0.2 and later. + -- Deflate_Init is supporting all header types. + + function Is_Open (Filter : in Filter_Type) return Boolean; + pragma Inline (Is_Open); + -- Is the filter opened for compression or decompression. + + procedure Close + (Filter : in out Filter_Type; + Ignore_Error : in Boolean := False); + -- Closing the compression or decompressor. + -- If stream is closing before the complete and Ignore_Error is False, + -- The exception would be raised. + + generic + with procedure Data_In + (Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset); + with procedure Data_Out + (Item : in Ada.Streams.Stream_Element_Array); + procedure Generic_Translate + (Filter : in out Filter_Type; + In_Buffer_Size : in Integer := Default_Buffer_Size; + Out_Buffer_Size : in Integer := Default_Buffer_Size); + -- Compress/decompress data fetch from Data_In routine and pass the result + -- to the Data_Out routine. User should provide Data_In and Data_Out + -- for compression/decompression data flow. + -- Compression or decompression depend on Filter initialization. + + function Total_In (Filter : in Filter_Type) return Count; + pragma Inline (Total_In); + -- Returns total number of input bytes read so far + + function Total_Out (Filter : in Filter_Type) return Count; + pragma Inline (Total_Out); + -- Returns total number of bytes output so far + + function CRC32 + (CRC : in Unsigned_32; + Data : in Ada.Streams.Stream_Element_Array) + return Unsigned_32; + pragma Inline (CRC32); + -- Compute CRC32, it could be necessary for make gzip format + + procedure CRC32 + (CRC : in out Unsigned_32; + Data : in Ada.Streams.Stream_Element_Array); + pragma Inline (CRC32); + -- Compute CRC32, it could be necessary for make gzip format + + ------------------------------------------------- + -- Below is more complex low level routines. -- + ------------------------------------------------- + + procedure Translate + (Filter : in out Filter_Type; + In_Data : in Ada.Streams.Stream_Element_Array; + In_Last : out Ada.Streams.Stream_Element_Offset; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode); + -- Compress/decompress the In_Data buffer and place the result into + -- Out_Data. In_Last is the index of last element from In_Data accepted by + -- the Filter. Out_Last is the last element of the received data from + -- Filter. To tell the filter that incoming data are complete put the + -- Flush parameter to Finish. + + function Stream_End (Filter : in Filter_Type) return Boolean; + pragma Inline (Stream_End); + -- Return the true when the stream is complete. + + procedure Flush + (Filter : in out Filter_Type; + Out_Data : out Ada.Streams.Stream_Element_Array; + Out_Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode); + pragma Inline (Flush); + -- Flushing the data from the compressor. + + generic + with procedure Write + (Item : in Ada.Streams.Stream_Element_Array); + -- User should provide this routine for accept + -- compressed/decompressed data. + + Buffer_Size : in Ada.Streams.Stream_Element_Offset + := Default_Buffer_Size; + -- Buffer size for Write user routine. + + procedure Write + (Filter : in out Filter_Type; + Item : in Ada.Streams.Stream_Element_Array; + Flush : in Flush_Mode := No_Flush); + -- Compress/Decompress data from Item to the generic parameter procedure + -- Write. Output buffer size could be set in Buffer_Size generic parameter. + + generic + with procedure Read + (Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset); + -- User should provide data for compression/decompression + -- thru this routine. + + Buffer : in out Ada.Streams.Stream_Element_Array; + -- Buffer for keep remaining data from the previous + -- back read. + + Rest_First, Rest_Last : in out Ada.Streams.Stream_Element_Offset; + -- Rest_First have to be initialized to Buffer'Last + 1 + -- Rest_Last have to be initialized to Buffer'Last + -- before usage. + + Allow_Read_Some : in Boolean := False; + -- Is it allowed to return Last < Item'Last before end of data. + + procedure Read + (Filter : in out Filter_Type; + Item : out Ada.Streams.Stream_Element_Array; + Last : out Ada.Streams.Stream_Element_Offset; + Flush : in Flush_Mode := No_Flush); + -- Compress/Decompress data from generic parameter procedure Read to the + -- Item. User should provide Buffer and initialized Rest_First, Rest_Last + -- indicators. If Allow_Read_Some is True, Read routines could return + -- Last < Item'Last only at end of stream. + +private + + use Ada.Streams; + + pragma Assert (Ada.Streams.Stream_Element'Size = 8); + pragma Assert (Ada.Streams.Stream_Element'Modulus = 2**8); + + type Flush_Mode is new Integer range 0 .. 5; + + type Compression_Method is new Integer range 8 .. 8; + + type Strategy_Type is new Integer range 0 .. 3; + + No_Flush : constant Flush_Mode := 0; + Partial_Flush : constant Flush_Mode := 1; + Sync_Flush : constant Flush_Mode := 2; + Full_Flush : constant Flush_Mode := 3; + Finish : constant Flush_Mode := 4; + Block_Flush : constant Flush_Mode := 5; + + Filtered : constant Strategy_Type := 1; + Huffman_Only : constant Strategy_Type := 2; + RLE : constant Strategy_Type := 3; + Default_Strategy : constant Strategy_Type := 0; + + Deflated : constant Compression_Method := 8; + + type Z_Stream; + + type Z_Stream_Access is access all Z_Stream; + + type Filter_Type is tagged limited record + Strm : Z_Stream_Access; + Compression : Boolean; + Stream_End : Boolean; + Header : Header_Type; + CRC : Unsigned_32; + Offset : Stream_Element_Offset; + -- Offset for gzip header/footer output. + end record; + +end ZLib; diff --git a/zlib-1.2.11/contrib/ada/zlib.gpr b/zlib-1.2.11/contrib/ada/zlib.gpr new file mode 100644 index 00000000..296b22aa --- /dev/null +++ b/zlib-1.2.11/contrib/ada/zlib.gpr @@ -0,0 +1,20 @@ +project Zlib is + + for Languages use ("Ada"); + for Source_Dirs use ("."); + for Object_Dir use "."; + for Main use ("test.adb", "mtest.adb", "read.adb", "buffer_demo"); + + package Compiler is + for Default_Switches ("ada") use ("-gnatwcfilopru", "-gnatVcdfimorst", "-gnatyabcefhiklmnoprst"); + end Compiler; + + package Linker is + for Default_Switches ("ada") use ("-lz"); + end Linker; + + package Builder is + for Default_Switches ("ada") use ("-s", "-gnatQ"); + end Builder; + +end Zlib; diff --git a/zlib-1.2.11/contrib/amd64/amd64-match.S b/zlib-1.2.11/contrib/amd64/amd64-match.S new file mode 100644 index 00000000..81d4a1c9 --- /dev/null +++ b/zlib-1.2.11/contrib/amd64/amd64-match.S @@ -0,0 +1,452 @@ +/* + * match.S -- optimized version of longest_match() + * based on the similar work by Gilles Vollant, and Brian Raiter, written 1998 + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the BSD License. Use by owners of Che Guevarra + * parafernalia is prohibited, where possible, and highly discouraged + * elsewhere. + */ + +#ifndef NO_UNDERLINE +# define match_init _match_init +# define longest_match _longest_match +#endif + +#define scanend ebx +#define scanendw bx +#define chainlenwmask edx /* high word: current chain len low word: s->wmask */ +#define curmatch rsi +#define curmatchd esi +#define windowbestlen r8 +#define scanalign r9 +#define scanalignd r9d +#define window r10 +#define bestlen r11 +#define bestlend r11d +#define scanstart r12d +#define scanstartw r12w +#define scan r13 +#define nicematch r14d +#define limit r15 +#define limitd r15d +#define prev rcx + +/* + * The 258 is a "magic number, not a parameter -- changing it + * breaks the hell loose + */ +#define MAX_MATCH (258) +#define MIN_MATCH (3) +#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) +#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) + +/* stack frame offsets */ +#define LocalVarsSize (112) +#define _chainlenwmask ( 8-LocalVarsSize)(%rsp) +#define _windowbestlen (16-LocalVarsSize)(%rsp) +#define save_r14 (24-LocalVarsSize)(%rsp) +#define save_rsi (32-LocalVarsSize)(%rsp) +#define save_rbx (40-LocalVarsSize)(%rsp) +#define save_r12 (56-LocalVarsSize)(%rsp) +#define save_r13 (64-LocalVarsSize)(%rsp) +#define save_r15 (80-LocalVarsSize)(%rsp) + + +.globl match_init, longest_match + +/* + * On AMD64 the first argument of a function (in our case -- the pointer to + * deflate_state structure) is passed in %rdi, hence our offsets below are + * all off of that. + */ + +/* you can check the structure offset by running + +#include +#include +#include "deflate.h" + +void print_depl() +{ +deflate_state ds; +deflate_state *s=&ds; +printf("size pointer=%u\n",(int)sizeof(void*)); + +printf("#define dsWSize (%3u)(%%rdi)\n",(int)(((char*)&(s->w_size))-((char*)s))); +printf("#define dsWMask (%3u)(%%rdi)\n",(int)(((char*)&(s->w_mask))-((char*)s))); +printf("#define dsWindow (%3u)(%%rdi)\n",(int)(((char*)&(s->window))-((char*)s))); +printf("#define dsPrev (%3u)(%%rdi)\n",(int)(((char*)&(s->prev))-((char*)s))); +printf("#define dsMatchLen (%3u)(%%rdi)\n",(int)(((char*)&(s->match_length))-((char*)s))); +printf("#define dsPrevMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_match))-((char*)s))); +printf("#define dsStrStart (%3u)(%%rdi)\n",(int)(((char*)&(s->strstart))-((char*)s))); +printf("#define dsMatchStart (%3u)(%%rdi)\n",(int)(((char*)&(s->match_start))-((char*)s))); +printf("#define dsLookahead (%3u)(%%rdi)\n",(int)(((char*)&(s->lookahead))-((char*)s))); +printf("#define dsPrevLen (%3u)(%%rdi)\n",(int)(((char*)&(s->prev_length))-((char*)s))); +printf("#define dsMaxChainLen (%3u)(%%rdi)\n",(int)(((char*)&(s->max_chain_length))-((char*)s))); +printf("#define dsGoodMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->good_match))-((char*)s))); +printf("#define dsNiceMatch (%3u)(%%rdi)\n",(int)(((char*)&(s->nice_match))-((char*)s))); +} + +*/ + + +/* + to compile for XCode 3.2 on MacOSX x86_64 + - run "gcc -g -c -DXCODE_MAC_X64_STRUCTURE amd64-match.S" + */ + + +#ifndef CURRENT_LINX_XCODE_MAC_X64_STRUCTURE +#define dsWSize ( 68)(%rdi) +#define dsWMask ( 76)(%rdi) +#define dsWindow ( 80)(%rdi) +#define dsPrev ( 96)(%rdi) +#define dsMatchLen (144)(%rdi) +#define dsPrevMatch (148)(%rdi) +#define dsStrStart (156)(%rdi) +#define dsMatchStart (160)(%rdi) +#define dsLookahead (164)(%rdi) +#define dsPrevLen (168)(%rdi) +#define dsMaxChainLen (172)(%rdi) +#define dsGoodMatch (188)(%rdi) +#define dsNiceMatch (192)(%rdi) + +#else + +#ifndef STRUCT_OFFSET +# define STRUCT_OFFSET (0) +#endif + + +#define dsWSize ( 56 + STRUCT_OFFSET)(%rdi) +#define dsWMask ( 64 + STRUCT_OFFSET)(%rdi) +#define dsWindow ( 72 + STRUCT_OFFSET)(%rdi) +#define dsPrev ( 88 + STRUCT_OFFSET)(%rdi) +#define dsMatchLen (136 + STRUCT_OFFSET)(%rdi) +#define dsPrevMatch (140 + STRUCT_OFFSET)(%rdi) +#define dsStrStart (148 + STRUCT_OFFSET)(%rdi) +#define dsMatchStart (152 + STRUCT_OFFSET)(%rdi) +#define dsLookahead (156 + STRUCT_OFFSET)(%rdi) +#define dsPrevLen (160 + STRUCT_OFFSET)(%rdi) +#define dsMaxChainLen (164 + STRUCT_OFFSET)(%rdi) +#define dsGoodMatch (180 + STRUCT_OFFSET)(%rdi) +#define dsNiceMatch (184 + STRUCT_OFFSET)(%rdi) + +#endif + + + + +.text + +/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ + +longest_match: +/* + * Retrieve the function arguments. %curmatch will hold cur_match + * throughout the entire function (passed via rsi on amd64). + * rdi will hold the pointer to the deflate_state (first arg on amd64) + */ + mov %rsi, save_rsi + mov %rbx, save_rbx + mov %r12, save_r12 + mov %r13, save_r13 + mov %r14, save_r14 + mov %r15, save_r15 + +/* uInt wmask = s->w_mask; */ +/* unsigned chain_length = s->max_chain_length; */ +/* if (s->prev_length >= s->good_match) { */ +/* chain_length >>= 2; */ +/* } */ + + movl dsPrevLen, %eax + movl dsGoodMatch, %ebx + cmpl %ebx, %eax + movl dsWMask, %eax + movl dsMaxChainLen, %chainlenwmask + jl LastMatchGood + shrl $2, %chainlenwmask +LastMatchGood: + +/* chainlen is decremented once beforehand so that the function can */ +/* use the sign flag instead of the zero flag for the exit test. */ +/* It is then shifted into the high word, to make room for the wmask */ +/* value, which it will always accompany. */ + + decl %chainlenwmask + shll $16, %chainlenwmask + orl %eax, %chainlenwmask + +/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ + + movl dsNiceMatch, %eax + movl dsLookahead, %ebx + cmpl %eax, %ebx + jl LookaheadLess + movl %eax, %ebx +LookaheadLess: movl %ebx, %nicematch + +/* register Bytef *scan = s->window + s->strstart; */ + + mov dsWindow, %window + movl dsStrStart, %limitd + lea (%limit, %window), %scan + +/* Determine how many bytes the scan ptr is off from being */ +/* dword-aligned. */ + + mov %scan, %scanalign + negl %scanalignd + andl $3, %scanalignd + +/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ +/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ + + movl dsWSize, %eax + subl $MIN_LOOKAHEAD, %eax + xorl %ecx, %ecx + subl %eax, %limitd + cmovng %ecx, %limitd + +/* int best_len = s->prev_length; */ + + movl dsPrevLen, %bestlend + +/* Store the sum of s->window + best_len in %windowbestlen locally, and in memory. */ + + lea (%window, %bestlen), %windowbestlen + mov %windowbestlen, _windowbestlen + +/* register ush scan_start = *(ushf*)scan; */ +/* register ush scan_end = *(ushf*)(scan+best_len-1); */ +/* Posf *prev = s->prev; */ + + movzwl (%scan), %scanstart + movzwl -1(%scan, %bestlen), %scanend + mov dsPrev, %prev + +/* Jump into the main loop. */ + + movl %chainlenwmask, _chainlenwmask + jmp LoopEntry + +.balign 16 + +/* do { + * match = s->window + cur_match; + * if (*(ushf*)(match+best_len-1) != scan_end || + * *(ushf*)match != scan_start) continue; + * [...] + * } while ((cur_match = prev[cur_match & wmask]) > limit + * && --chain_length != 0); + * + * Here is the inner loop of the function. The function will spend the + * majority of its time in this loop, and majority of that time will + * be spent in the first ten instructions. + */ +LookupLoop: + andl %chainlenwmask, %curmatchd + movzwl (%prev, %curmatch, 2), %curmatchd + cmpl %limitd, %curmatchd + jbe LeaveNow + subl $0x00010000, %chainlenwmask + js LeaveNow +LoopEntry: cmpw -1(%windowbestlen, %curmatch), %scanendw + jne LookupLoop + cmpw %scanstartw, (%window, %curmatch) + jne LookupLoop + +/* Store the current value of chainlen. */ + movl %chainlenwmask, _chainlenwmask + +/* %scan is the string under scrutiny, and %prev to the string we */ +/* are hoping to match it up with. In actuality, %esi and %edi are */ +/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ +/* initialized to -(MAX_MATCH_8 - scanalign). */ + + mov $(-MAX_MATCH_8), %rdx + lea (%curmatch, %window), %windowbestlen + lea MAX_MATCH_8(%windowbestlen, %scanalign), %windowbestlen + lea MAX_MATCH_8(%scan, %scanalign), %prev + +/* the prefetching below makes very little difference... */ + prefetcht1 (%windowbestlen, %rdx) + prefetcht1 (%prev, %rdx) + +/* + * Test the strings for equality, 8 bytes at a time. At the end, + * adjust %rdx so that it is offset to the exact byte that mismatched. + * + * It should be confessed that this loop usually does not represent + * much of the total running time. Replacing it with a more + * straightforward "rep cmpsb" would not drastically degrade + * performance -- unrolling it, for example, makes no difference. + */ + +#undef USE_SSE /* works, but is 6-7% slower, than non-SSE... */ + +LoopCmps: +#ifdef USE_SSE + /* Preload the SSE registers */ + movdqu (%windowbestlen, %rdx), %xmm1 + movdqu (%prev, %rdx), %xmm2 + pcmpeqb %xmm2, %xmm1 + movdqu 16(%windowbestlen, %rdx), %xmm3 + movdqu 16(%prev, %rdx), %xmm4 + pcmpeqb %xmm4, %xmm3 + movdqu 32(%windowbestlen, %rdx), %xmm5 + movdqu 32(%prev, %rdx), %xmm6 + pcmpeqb %xmm6, %xmm5 + movdqu 48(%windowbestlen, %rdx), %xmm7 + movdqu 48(%prev, %rdx), %xmm8 + pcmpeqb %xmm8, %xmm7 + + /* Check the comparisions' results */ + pmovmskb %xmm1, %rax + notw %ax + bsfw %ax, %ax + jnz LeaveLoopCmps + + /* this is the only iteration of the loop with a possibility of having + incremented rdx by 0x108 (each loop iteration add 16*4 = 0x40 + and (0x40*4)+8=0x108 */ + add $8, %rdx + jz LenMaximum + add $8, %rdx + + + pmovmskb %xmm3, %rax + notw %ax + bsfw %ax, %ax + jnz LeaveLoopCmps + + + add $16, %rdx + + + pmovmskb %xmm5, %rax + notw %ax + bsfw %ax, %ax + jnz LeaveLoopCmps + + add $16, %rdx + + + pmovmskb %xmm7, %rax + notw %ax + bsfw %ax, %ax + jnz LeaveLoopCmps + + add $16, %rdx + + jmp LoopCmps +LeaveLoopCmps: add %rax, %rdx +#else + mov (%windowbestlen, %rdx), %rax + xor (%prev, %rdx), %rax + jnz LeaveLoopCmps + + mov 8(%windowbestlen, %rdx), %rax + xor 8(%prev, %rdx), %rax + jnz LeaveLoopCmps8 + + mov 16(%windowbestlen, %rdx), %rax + xor 16(%prev, %rdx), %rax + jnz LeaveLoopCmps16 + + add $24, %rdx + jnz LoopCmps + jmp LenMaximum +# if 0 +/* + * This three-liner is tantalizingly simple, but bsf is a slow instruction, + * and the complicated alternative down below is quite a bit faster. Sad... + */ + +LeaveLoopCmps: bsf %rax, %rax /* find the first non-zero bit */ + shrl $3, %eax /* divide by 8 to get the byte */ + add %rax, %rdx +# else +LeaveLoopCmps16: + add $8, %rdx +LeaveLoopCmps8: + add $8, %rdx +LeaveLoopCmps: testl $0xFFFFFFFF, %eax /* Check the first 4 bytes */ + jnz Check16 + add $4, %rdx + shr $32, %rax +Check16: testw $0xFFFF, %ax + jnz LenLower + add $2, %rdx + shrl $16, %eax +LenLower: subb $1, %al + adc $0, %rdx +# endif +#endif + +/* Calculate the length of the match. If it is longer than MAX_MATCH, */ +/* then automatically accept it as the best possible match and leave. */ + + lea (%prev, %rdx), %rax + sub %scan, %rax + cmpl $MAX_MATCH, %eax + jge LenMaximum + +/* If the length of the match is not longer than the best match we */ +/* have so far, then forget it and return to the lookup loop. */ + + cmpl %bestlend, %eax + jg LongerMatch + mov _windowbestlen, %windowbestlen + mov dsPrev, %prev + movl _chainlenwmask, %edx + jmp LookupLoop + +/* s->match_start = cur_match; */ +/* best_len = len; */ +/* if (len >= nice_match) break; */ +/* scan_end = *(ushf*)(scan+best_len-1); */ + +LongerMatch: + movl %eax, %bestlend + movl %curmatchd, dsMatchStart + cmpl %nicematch, %eax + jge LeaveNow + + lea (%window, %bestlen), %windowbestlen + mov %windowbestlen, _windowbestlen + + movzwl -1(%scan, %rax), %scanend + mov dsPrev, %prev + movl _chainlenwmask, %chainlenwmask + jmp LookupLoop + +/* Accept the current string, with the maximum possible length. */ + +LenMaximum: + movl $MAX_MATCH, %bestlend + movl %curmatchd, dsMatchStart + +/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ +/* return s->lookahead; */ + +LeaveNow: + movl dsLookahead, %eax + cmpl %eax, %bestlend + cmovngl %bestlend, %eax +LookaheadRet: + +/* Restore the registers and return from whence we came. */ + + mov save_rsi, %rsi + mov save_rbx, %rbx + mov save_r12, %r12 + mov save_r13, %r13 + mov save_r14, %r14 + mov save_r15, %r15 + + ret + +match_init: ret diff --git a/zlib-1.2.11/contrib/asm686/README.686 b/zlib-1.2.11/contrib/asm686/README.686 new file mode 100644 index 00000000..a0bf3bea --- /dev/null +++ b/zlib-1.2.11/contrib/asm686/README.686 @@ -0,0 +1,51 @@ +This is a patched version of zlib, modified to use +Pentium-Pro-optimized assembly code in the deflation algorithm. The +files changed/added by this patch are: + +README.686 +match.S + +The speedup that this patch provides varies, depending on whether the +compiler used to build the original version of zlib falls afoul of the +PPro's speed traps. My own tests show a speedup of around 10-20% at +the default compression level, and 20-30% using -9, against a version +compiled using gcc 2.7.2.3. Your mileage may vary. + +Note that this code has been tailored for the PPro/PII in particular, +and will not perform particuarly well on a Pentium. + +If you are using an assembler other than GNU as, you will have to +translate match.S to use your assembler's syntax. (Have fun.) + +Brian Raiter +breadbox@muppetlabs.com +April, 1998 + + +Added for zlib 1.1.3: + +The patches come from +http://www.muppetlabs.com/~breadbox/software/assembly.html + +To compile zlib with this asm file, copy match.S to the zlib directory +then do: + +CFLAGS="-O3 -DASMV" ./configure +make OBJA=match.o + + +Update: + +I've been ignoring these assembly routines for years, believing that +gcc's generated code had caught up with it sometime around gcc 2.95 +and the major rearchitecting of the Pentium 4. However, I recently +learned that, despite what I believed, this code still has some life +in it. On the Pentium 4 and AMD64 chips, it continues to run about 8% +faster than the code produced by gcc 4.1. + +In acknowledgement of its continuing usefulness, I've altered the +license to match that of the rest of zlib. Share and Enjoy! + +Brian Raiter +breadbox@muppetlabs.com +April, 2007 diff --git a/zlib-1.2.11/contrib/asm686/match.S b/zlib-1.2.11/contrib/asm686/match.S new file mode 100644 index 00000000..fa421092 --- /dev/null +++ b/zlib-1.2.11/contrib/asm686/match.S @@ -0,0 +1,357 @@ +/* match.S -- x86 assembly version of the zlib longest_match() function. + * Optimized for the Intel 686 chips (PPro and later). + * + * Copyright (C) 1998, 2007 Brian Raiter + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the author be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + */ + +#ifndef NO_UNDERLINE +#define match_init _match_init +#define longest_match _longest_match +#endif + +#define MAX_MATCH (258) +#define MIN_MATCH (3) +#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) +#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) + +/* stack frame offsets */ + +#define chainlenwmask 0 /* high word: current chain len */ + /* low word: s->wmask */ +#define window 4 /* local copy of s->window */ +#define windowbestlen 8 /* s->window + bestlen */ +#define scanstart 16 /* first two bytes of string */ +#define scanend 12 /* last two bytes of string */ +#define scanalign 20 /* dword-misalignment of string */ +#define nicematch 24 /* a good enough match size */ +#define bestlen 28 /* size of best match so far */ +#define scan 32 /* ptr to string wanting match */ + +#define LocalVarsSize (36) +/* saved ebx 36 */ +/* saved edi 40 */ +/* saved esi 44 */ +/* saved ebp 48 */ +/* return address 52 */ +#define deflatestate 56 /* the function arguments */ +#define curmatch 60 + +/* All the +zlib1222add offsets are due to the addition of fields + * in zlib in the deflate_state structure since the asm code was first written + * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). + * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). + * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). + */ + +#define zlib1222add (8) + +#define dsWSize (36+zlib1222add) +#define dsWMask (44+zlib1222add) +#define dsWindow (48+zlib1222add) +#define dsPrev (56+zlib1222add) +#define dsMatchLen (88+zlib1222add) +#define dsPrevMatch (92+zlib1222add) +#define dsStrStart (100+zlib1222add) +#define dsMatchStart (104+zlib1222add) +#define dsLookahead (108+zlib1222add) +#define dsPrevLen (112+zlib1222add) +#define dsMaxChainLen (116+zlib1222add) +#define dsGoodMatch (132+zlib1222add) +#define dsNiceMatch (136+zlib1222add) + + +.file "match.S" + +.globl match_init, longest_match + +.text + +/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ +.cfi_sections .debug_frame + +longest_match: + +.cfi_startproc +/* Save registers that the compiler may be using, and adjust %esp to */ +/* make room for our stack frame. */ + + pushl %ebp + .cfi_def_cfa_offset 8 + .cfi_offset ebp, -8 + pushl %edi + .cfi_def_cfa_offset 12 + pushl %esi + .cfi_def_cfa_offset 16 + pushl %ebx + .cfi_def_cfa_offset 20 + subl $LocalVarsSize, %esp + .cfi_def_cfa_offset LocalVarsSize+20 + +/* Retrieve the function arguments. %ecx will hold cur_match */ +/* throughout the entire function. %edx will hold the pointer to the */ +/* deflate_state structure during the function's setup (before */ +/* entering the main loop). */ + + movl deflatestate(%esp), %edx + movl curmatch(%esp), %ecx + +/* uInt wmask = s->w_mask; */ +/* unsigned chain_length = s->max_chain_length; */ +/* if (s->prev_length >= s->good_match) { */ +/* chain_length >>= 2; */ +/* } */ + + movl dsPrevLen(%edx), %eax + movl dsGoodMatch(%edx), %ebx + cmpl %ebx, %eax + movl dsWMask(%edx), %eax + movl dsMaxChainLen(%edx), %ebx + jl LastMatchGood + shrl $2, %ebx +LastMatchGood: + +/* chainlen is decremented once beforehand so that the function can */ +/* use the sign flag instead of the zero flag for the exit test. */ +/* It is then shifted into the high word, to make room for the wmask */ +/* value, which it will always accompany. */ + + decl %ebx + shll $16, %ebx + orl %eax, %ebx + movl %ebx, chainlenwmask(%esp) + +/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ + + movl dsNiceMatch(%edx), %eax + movl dsLookahead(%edx), %ebx + cmpl %eax, %ebx + jl LookaheadLess + movl %eax, %ebx +LookaheadLess: movl %ebx, nicematch(%esp) + +/* register Bytef *scan = s->window + s->strstart; */ + + movl dsWindow(%edx), %esi + movl %esi, window(%esp) + movl dsStrStart(%edx), %ebp + lea (%esi,%ebp), %edi + movl %edi, scan(%esp) + +/* Determine how many bytes the scan ptr is off from being */ +/* dword-aligned. */ + + movl %edi, %eax + negl %eax + andl $3, %eax + movl %eax, scanalign(%esp) + +/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ +/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ + + movl dsWSize(%edx), %eax + subl $MIN_LOOKAHEAD, %eax + subl %eax, %ebp + jg LimitPositive + xorl %ebp, %ebp +LimitPositive: + +/* int best_len = s->prev_length; */ + + movl dsPrevLen(%edx), %eax + movl %eax, bestlen(%esp) + +/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ + + addl %eax, %esi + movl %esi, windowbestlen(%esp) + +/* register ush scan_start = *(ushf*)scan; */ +/* register ush scan_end = *(ushf*)(scan+best_len-1); */ +/* Posf *prev = s->prev; */ + + movzwl (%edi), %ebx + movl %ebx, scanstart(%esp) + movzwl -1(%edi,%eax), %ebx + movl %ebx, scanend(%esp) + movl dsPrev(%edx), %edi + +/* Jump into the main loop. */ + + movl chainlenwmask(%esp), %edx + jmp LoopEntry + +.balign 16 + +/* do { + * match = s->window + cur_match; + * if (*(ushf*)(match+best_len-1) != scan_end || + * *(ushf*)match != scan_start) continue; + * [...] + * } while ((cur_match = prev[cur_match & wmask]) > limit + * && --chain_length != 0); + * + * Here is the inner loop of the function. The function will spend the + * majority of its time in this loop, and majority of that time will + * be spent in the first ten instructions. + * + * Within this loop: + * %ebx = scanend + * %ecx = curmatch + * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) + * %esi = windowbestlen - i.e., (window + bestlen) + * %edi = prev + * %ebp = limit + */ +LookupLoop: + andl %edx, %ecx + movzwl (%edi,%ecx,2), %ecx + cmpl %ebp, %ecx + jbe LeaveNow + subl $0x00010000, %edx + js LeaveNow +LoopEntry: movzwl -1(%esi,%ecx), %eax + cmpl %ebx, %eax + jnz LookupLoop + movl window(%esp), %eax + movzwl (%eax,%ecx), %eax + cmpl scanstart(%esp), %eax + jnz LookupLoop + +/* Store the current value of chainlen. */ + + movl %edx, chainlenwmask(%esp) + +/* Point %edi to the string under scrutiny, and %esi to the string we */ +/* are hoping to match it up with. In actuality, %esi and %edi are */ +/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ +/* initialized to -(MAX_MATCH_8 - scanalign). */ + + movl window(%esp), %esi + movl scan(%esp), %edi + addl %ecx, %esi + movl scanalign(%esp), %eax + movl $(-MAX_MATCH_8), %edx + lea MAX_MATCH_8(%edi,%eax), %edi + lea MAX_MATCH_8(%esi,%eax), %esi + +/* Test the strings for equality, 8 bytes at a time. At the end, + * adjust %edx so that it is offset to the exact byte that mismatched. + * + * We already know at this point that the first three bytes of the + * strings match each other, and they can be safely passed over before + * starting the compare loop. So what this code does is skip over 0-3 + * bytes, as much as necessary in order to dword-align the %edi + * pointer. (%esi will still be misaligned three times out of four.) + * + * It should be confessed that this loop usually does not represent + * much of the total running time. Replacing it with a more + * straightforward "rep cmpsb" would not drastically degrade + * performance. + */ +LoopCmps: + movl (%esi,%edx), %eax + xorl (%edi,%edx), %eax + jnz LeaveLoopCmps + movl 4(%esi,%edx), %eax + xorl 4(%edi,%edx), %eax + jnz LeaveLoopCmps4 + addl $8, %edx + jnz LoopCmps + jmp LenMaximum +LeaveLoopCmps4: addl $4, %edx +LeaveLoopCmps: testl $0x0000FFFF, %eax + jnz LenLower + addl $2, %edx + shrl $16, %eax +LenLower: subb $1, %al + adcl $0, %edx + +/* Calculate the length of the match. If it is longer than MAX_MATCH, */ +/* then automatically accept it as the best possible match and leave. */ + + lea (%edi,%edx), %eax + movl scan(%esp), %edi + subl %edi, %eax + cmpl $MAX_MATCH, %eax + jge LenMaximum + +/* If the length of the match is not longer than the best match we */ +/* have so far, then forget it and return to the lookup loop. */ + + movl deflatestate(%esp), %edx + movl bestlen(%esp), %ebx + cmpl %ebx, %eax + jg LongerMatch + movl windowbestlen(%esp), %esi + movl dsPrev(%edx), %edi + movl scanend(%esp), %ebx + movl chainlenwmask(%esp), %edx + jmp LookupLoop + +/* s->match_start = cur_match; */ +/* best_len = len; */ +/* if (len >= nice_match) break; */ +/* scan_end = *(ushf*)(scan+best_len-1); */ + +LongerMatch: movl nicematch(%esp), %ebx + movl %eax, bestlen(%esp) + movl %ecx, dsMatchStart(%edx) + cmpl %ebx, %eax + jge LeaveNow + movl window(%esp), %esi + addl %eax, %esi + movl %esi, windowbestlen(%esp) + movzwl -1(%edi,%eax), %ebx + movl dsPrev(%edx), %edi + movl %ebx, scanend(%esp) + movl chainlenwmask(%esp), %edx + jmp LookupLoop + +/* Accept the current string, with the maximum possible length. */ + +LenMaximum: movl deflatestate(%esp), %edx + movl $MAX_MATCH, bestlen(%esp) + movl %ecx, dsMatchStart(%edx) + +/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ +/* return s->lookahead; */ + +LeaveNow: + movl deflatestate(%esp), %edx + movl bestlen(%esp), %ebx + movl dsLookahead(%edx), %eax + cmpl %eax, %ebx + jg LookaheadRet + movl %ebx, %eax +LookaheadRet: + +/* Restore the stack and return from whence we came. */ + + addl $LocalVarsSize, %esp + .cfi_def_cfa_offset 20 + popl %ebx + .cfi_def_cfa_offset 16 + popl %esi + .cfi_def_cfa_offset 12 + popl %edi + .cfi_def_cfa_offset 8 + popl %ebp + .cfi_def_cfa_offset 4 +.cfi_endproc +match_init: ret diff --git a/zlib-1.2.11/contrib/blast/Makefile b/zlib-1.2.11/contrib/blast/Makefile new file mode 100644 index 00000000..9be80baf --- /dev/null +++ b/zlib-1.2.11/contrib/blast/Makefile @@ -0,0 +1,8 @@ +blast: blast.c blast.h + cc -DTEST -o blast blast.c + +test: blast + blast < test.pk | cmp - test.txt + +clean: + rm -f blast blast.o diff --git a/zlib-1.2.11/contrib/blast/README b/zlib-1.2.11/contrib/blast/README new file mode 100644 index 00000000..e3a60b3f --- /dev/null +++ b/zlib-1.2.11/contrib/blast/README @@ -0,0 +1,4 @@ +Read blast.h for purpose and usage. + +Mark Adler +madler@alumni.caltech.edu diff --git a/zlib-1.2.11/contrib/blast/blast.c b/zlib-1.2.11/contrib/blast/blast.c new file mode 100644 index 00000000..e6e65907 --- /dev/null +++ b/zlib-1.2.11/contrib/blast/blast.c @@ -0,0 +1,466 @@ +/* blast.c + * Copyright (C) 2003, 2012, 2013 Mark Adler + * For conditions of distribution and use, see copyright notice in blast.h + * version 1.3, 24 Aug 2013 + * + * blast.c decompresses data compressed by the PKWare Compression Library. + * This function provides functionality similar to the explode() function of + * the PKWare library, hence the name "blast". + * + * This decompressor is based on the excellent format description provided by + * Ben Rudiak-Gould in comp.compression on August 13, 2001. Interestingly, the + * example Ben provided in the post is incorrect. The distance 110001 should + * instead be 111000. When corrected, the example byte stream becomes: + * + * 00 04 82 24 25 8f 80 7f + * + * which decompresses to "AIAIAIAIAIAIA" (without the quotes). + */ + +/* + * Change history: + * + * 1.0 12 Feb 2003 - First version + * 1.1 16 Feb 2003 - Fixed distance check for > 4 GB uncompressed data + * 1.2 24 Oct 2012 - Add note about using binary mode in stdio + * - Fix comparisons of differently signed integers + * 1.3 24 Aug 2013 - Return unused input from blast() + * - Fix test code to correctly report unused input + * - Enable the provision of initial input to blast() + */ + +#include /* for NULL */ +#include /* for setjmp(), longjmp(), and jmp_buf */ +#include "blast.h" /* prototype for blast() */ + +#define local static /* for local function definitions */ +#define MAXBITS 13 /* maximum code length */ +#define MAXWIN 4096 /* maximum window size */ + +/* input and output state */ +struct state { + /* input state */ + blast_in infun; /* input function provided by user */ + void *inhow; /* opaque information passed to infun() */ + unsigned char *in; /* next input location */ + unsigned left; /* available input at in */ + int bitbuf; /* bit buffer */ + int bitcnt; /* number of bits in bit buffer */ + + /* input limit error return state for bits() and decode() */ + jmp_buf env; + + /* output state */ + blast_out outfun; /* output function provided by user */ + void *outhow; /* opaque information passed to outfun() */ + unsigned next; /* index of next write location in out[] */ + int first; /* true to check distances (for first 4K) */ + unsigned char out[MAXWIN]; /* output buffer and sliding window */ +}; + +/* + * Return need bits from the input stream. This always leaves less than + * eight bits in the buffer. bits() works properly for need == 0. + * + * Format notes: + * + * - Bits are stored in bytes from the least significant bit to the most + * significant bit. Therefore bits are dropped from the bottom of the bit + * buffer, using shift right, and new bytes are appended to the top of the + * bit buffer, using shift left. + */ +local int bits(struct state *s, int need) +{ + int val; /* bit accumulator */ + + /* load at least need bits into val */ + val = s->bitbuf; + while (s->bitcnt < need) { + if (s->left == 0) { + s->left = s->infun(s->inhow, &(s->in)); + if (s->left == 0) longjmp(s->env, 1); /* out of input */ + } + val |= (int)(*(s->in)++) << s->bitcnt; /* load eight bits */ + s->left--; + s->bitcnt += 8; + } + + /* drop need bits and update buffer, always zero to seven bits left */ + s->bitbuf = val >> need; + s->bitcnt -= need; + + /* return need bits, zeroing the bits above that */ + return val & ((1 << need) - 1); +} + +/* + * Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of + * each length, which for a canonical code are stepped through in order. + * symbol[] are the symbol values in canonical order, where the number of + * entries is the sum of the counts in count[]. The decoding process can be + * seen in the function decode() below. + */ +struct huffman { + short *count; /* number of symbols of each length */ + short *symbol; /* canonically ordered symbols */ +}; + +/* + * Decode a code from the stream s using huffman table h. Return the symbol or + * a negative value if there is an error. If all of the lengths are zero, i.e. + * an empty code, or if the code is incomplete and an invalid code is received, + * then -9 is returned after reading MAXBITS bits. + * + * Format notes: + * + * - The codes as stored in the compressed data are bit-reversed relative to + * a simple integer ordering of codes of the same lengths. Hence below the + * bits are pulled from the compressed data one at a time and used to + * build the code value reversed from what is in the stream in order to + * permit simple integer comparisons for decoding. + * + * - The first code for the shortest length is all ones. Subsequent codes of + * the same length are simply integer decrements of the previous code. When + * moving up a length, a one bit is appended to the code. For a complete + * code, the last code of the longest length will be all zeros. To support + * this ordering, the bits pulled during decoding are inverted to apply the + * more "natural" ordering starting with all zeros and incrementing. + */ +local int decode(struct state *s, struct huffman *h) +{ + int len; /* current number of bits in code */ + int code; /* len bits being decoded */ + int first; /* first code of length len */ + int count; /* number of codes of length len */ + int index; /* index of first code of length len in symbol table */ + int bitbuf; /* bits from stream */ + int left; /* bits left in next or left to process */ + short *next; /* next number of codes */ + + bitbuf = s->bitbuf; + left = s->bitcnt; + code = first = index = 0; + len = 1; + next = h->count + 1; + while (1) { + while (left--) { + code |= (bitbuf & 1) ^ 1; /* invert code */ + bitbuf >>= 1; + count = *next++; + if (code < first + count) { /* if length len, return symbol */ + s->bitbuf = bitbuf; + s->bitcnt = (s->bitcnt - len) & 7; + return h->symbol[index + (code - first)]; + } + index += count; /* else update for next length */ + first += count; + first <<= 1; + code <<= 1; + len++; + } + left = (MAXBITS+1) - len; + if (left == 0) break; + if (s->left == 0) { + s->left = s->infun(s->inhow, &(s->in)); + if (s->left == 0) longjmp(s->env, 1); /* out of input */ + } + bitbuf = *(s->in)++; + s->left--; + if (left > 8) left = 8; + } + return -9; /* ran out of codes */ +} + +/* + * Given a list of repeated code lengths rep[0..n-1], where each byte is a + * count (high four bits + 1) and a code length (low four bits), generate the + * list of code lengths. This compaction reduces the size of the object code. + * Then given the list of code lengths length[0..n-1] representing a canonical + * Huffman code for n symbols, construct the tables required to decode those + * codes. Those tables are the number of codes of each length, and the symbols + * sorted by length, retaining their original order within each length. The + * return value is zero for a complete code set, negative for an over- + * subscribed code set, and positive for an incomplete code set. The tables + * can be used if the return value is zero or positive, but they cannot be used + * if the return value is negative. If the return value is zero, it is not + * possible for decode() using that table to return an error--any stream of + * enough bits will resolve to a symbol. If the return value is positive, then + * it is possible for decode() using that table to return an error for received + * codes past the end of the incomplete lengths. + */ +local int construct(struct huffman *h, const unsigned char *rep, int n) +{ + int symbol; /* current symbol when stepping through length[] */ + int len; /* current length when stepping through h->count[] */ + int left; /* number of possible codes left of current length */ + short offs[MAXBITS+1]; /* offsets in symbol table for each length */ + short length[256]; /* code lengths */ + + /* convert compact repeat counts into symbol bit length list */ + symbol = 0; + do { + len = *rep++; + left = (len >> 4) + 1; + len &= 15; + do { + length[symbol++] = len; + } while (--left); + } while (--n); + n = symbol; + + /* count number of codes of each length */ + for (len = 0; len <= MAXBITS; len++) + h->count[len] = 0; + for (symbol = 0; symbol < n; symbol++) + (h->count[length[symbol]])++; /* assumes lengths are within bounds */ + if (h->count[0] == n) /* no codes! */ + return 0; /* complete, but decode() will fail */ + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; /* one possible code of zero length */ + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; /* one more bit, double codes left */ + left -= h->count[len]; /* deduct count from possible codes */ + if (left < 0) return left; /* over-subscribed--return negative */ + } /* left > 0 means incomplete */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + h->count[len]; + + /* + * put symbols in table sorted by length, by symbol order within each + * length + */ + for (symbol = 0; symbol < n; symbol++) + if (length[symbol] != 0) + h->symbol[offs[length[symbol]]++] = symbol; + + /* return zero for complete set, positive for incomplete set */ + return left; +} + +/* + * Decode PKWare Compression Library stream. + * + * Format notes: + * + * - First byte is 0 if literals are uncoded or 1 if they are coded. Second + * byte is 4, 5, or 6 for the number of extra bits in the distance code. + * This is the base-2 logarithm of the dictionary size minus six. + * + * - Compressed data is a combination of literals and length/distance pairs + * terminated by an end code. Literals are either Huffman coded or + * uncoded bytes. A length/distance pair is a coded length followed by a + * coded distance to represent a string that occurs earlier in the + * uncompressed data that occurs again at the current location. + * + * - A bit preceding a literal or length/distance pair indicates which comes + * next, 0 for literals, 1 for length/distance. + * + * - If literals are uncoded, then the next eight bits are the literal, in the + * normal bit order in the stream, i.e. no bit-reversal is needed. Similarly, + * no bit reversal is needed for either the length extra bits or the distance + * extra bits. + * + * - Literal bytes are simply written to the output. A length/distance pair is + * an instruction to copy previously uncompressed bytes to the output. The + * copy is from distance bytes back in the output stream, copying for length + * bytes. + * + * - Distances pointing before the beginning of the output data are not + * permitted. + * + * - Overlapped copies, where the length is greater than the distance, are + * allowed and common. For example, a distance of one and a length of 518 + * simply copies the last byte 518 times. A distance of four and a length of + * twelve copies the last four bytes three times. A simple forward copy + * ignoring whether the length is greater than the distance or not implements + * this correctly. + */ +local int decomp(struct state *s) +{ + int lit; /* true if literals are coded */ + int dict; /* log2(dictionary size) - 6 */ + int symbol; /* decoded symbol, extra bits for distance */ + int len; /* length for copy */ + unsigned dist; /* distance for copy */ + int copy; /* copy counter */ + unsigned char *from, *to; /* copy pointers */ + static int virgin = 1; /* build tables once */ + static short litcnt[MAXBITS+1], litsym[256]; /* litcode memory */ + static short lencnt[MAXBITS+1], lensym[16]; /* lencode memory */ + static short distcnt[MAXBITS+1], distsym[64]; /* distcode memory */ + static struct huffman litcode = {litcnt, litsym}; /* length code */ + static struct huffman lencode = {lencnt, lensym}; /* length code */ + static struct huffman distcode = {distcnt, distsym};/* distance code */ + /* bit lengths of literal codes */ + static const unsigned char litlen[] = { + 11, 124, 8, 7, 28, 7, 188, 13, 76, 4, 10, 8, 12, 10, 12, 10, 8, 23, 8, + 9, 7, 6, 7, 8, 7, 6, 55, 8, 23, 24, 12, 11, 7, 9, 11, 12, 6, 7, 22, 5, + 7, 24, 6, 11, 9, 6, 7, 22, 7, 11, 38, 7, 9, 8, 25, 11, 8, 11, 9, 12, + 8, 12, 5, 38, 5, 38, 5, 11, 7, 5, 6, 21, 6, 10, 53, 8, 7, 24, 10, 27, + 44, 253, 253, 253, 252, 252, 252, 13, 12, 45, 12, 45, 12, 61, 12, 45, + 44, 173}; + /* bit lengths of length codes 0..15 */ + static const unsigned char lenlen[] = {2, 35, 36, 53, 38, 23}; + /* bit lengths of distance codes 0..63 */ + static const unsigned char distlen[] = {2, 20, 53, 230, 247, 151, 248}; + static const short base[16] = { /* base for length codes */ + 3, 2, 4, 5, 6, 7, 8, 9, 10, 12, 16, 24, 40, 72, 136, 264}; + static const char extra[16] = { /* extra bits for length codes */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8}; + + /* set up decoding tables (once--might not be thread-safe) */ + if (virgin) { + construct(&litcode, litlen, sizeof(litlen)); + construct(&lencode, lenlen, sizeof(lenlen)); + construct(&distcode, distlen, sizeof(distlen)); + virgin = 0; + } + + /* read header */ + lit = bits(s, 8); + if (lit > 1) return -1; + dict = bits(s, 8); + if (dict < 4 || dict > 6) return -2; + + /* decode literals and length/distance pairs */ + do { + if (bits(s, 1)) { + /* get length */ + symbol = decode(s, &lencode); + len = base[symbol] + bits(s, extra[symbol]); + if (len == 519) break; /* end code */ + + /* get distance */ + symbol = len == 2 ? 2 : dict; + dist = decode(s, &distcode) << symbol; + dist += bits(s, symbol); + dist++; + if (s->first && dist > s->next) + return -3; /* distance too far back */ + + /* copy length bytes from distance bytes back */ + do { + to = s->out + s->next; + from = to - dist; + copy = MAXWIN; + if (s->next < dist) { + from += copy; + copy = dist; + } + copy -= s->next; + if (copy > len) copy = len; + len -= copy; + s->next += copy; + do { + *to++ = *from++; + } while (--copy); + if (s->next == MAXWIN) { + if (s->outfun(s->outhow, s->out, s->next)) return 1; + s->next = 0; + s->first = 0; + } + } while (len != 0); + } + else { + /* get literal and write it */ + symbol = lit ? decode(s, &litcode) : bits(s, 8); + s->out[s->next++] = symbol; + if (s->next == MAXWIN) { + if (s->outfun(s->outhow, s->out, s->next)) return 1; + s->next = 0; + s->first = 0; + } + } + } while (1); + return 0; +} + +/* See comments in blast.h */ +int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow, + unsigned *left, unsigned char **in) +{ + struct state s; /* input/output state */ + int err; /* return value */ + + /* initialize input state */ + s.infun = infun; + s.inhow = inhow; + if (left != NULL && *left) { + s.left = *left; + s.in = *in; + } + else + s.left = 0; + s.bitbuf = 0; + s.bitcnt = 0; + + /* initialize output state */ + s.outfun = outfun; + s.outhow = outhow; + s.next = 0; + s.first = 1; + + /* return if bits() or decode() tries to read past available input */ + if (setjmp(s.env) != 0) /* if came back here via longjmp(), */ + err = 2; /* then skip decomp(), return error */ + else + err = decomp(&s); /* decompress */ + + /* return unused input */ + if (left != NULL) + *left = s.left; + if (in != NULL) + *in = s.left ? s.in : NULL; + + /* write any leftover output and update the error code if needed */ + if (err != 1 && s.next && s.outfun(s.outhow, s.out, s.next) && err == 0) + err = 1; + return err; +} + +#ifdef TEST +/* Example of how to use blast() */ +#include +#include + +#define CHUNK 16384 + +local unsigned inf(void *how, unsigned char **buf) +{ + static unsigned char hold[CHUNK]; + + *buf = hold; + return fread(hold, 1, CHUNK, (FILE *)how); +} + +local int outf(void *how, unsigned char *buf, unsigned len) +{ + return fwrite(buf, 1, len, (FILE *)how) != len; +} + +/* Decompress a PKWare Compression Library stream from stdin to stdout */ +int main(void) +{ + int ret; + unsigned left; + + /* decompress to stdout */ + left = 0; + ret = blast(inf, stdin, outf, stdout, &left, NULL); + if (ret != 0) + fprintf(stderr, "blast error: %d\n", ret); + + /* count any leftover bytes */ + while (getchar() != EOF) + left++; + if (left) + fprintf(stderr, "blast warning: %u unused bytes of input\n", left); + + /* return blast() error code */ + return ret; +} +#endif diff --git a/zlib-1.2.11/contrib/blast/blast.h b/zlib-1.2.11/contrib/blast/blast.h new file mode 100644 index 00000000..6cf65eda --- /dev/null +++ b/zlib-1.2.11/contrib/blast/blast.h @@ -0,0 +1,83 @@ +/* blast.h -- interface for blast.c + Copyright (C) 2003, 2012, 2013 Mark Adler + version 1.3, 24 Aug 2013 + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Mark Adler madler@alumni.caltech.edu + */ + + +/* + * blast() decompresses the PKWare Data Compression Library (DCL) compressed + * format. It provides the same functionality as the explode() function in + * that library. (Note: PKWare overused the "implode" verb, and the format + * used by their library implode() function is completely different and + * incompatible with the implode compression method supported by PKZIP.) + * + * The binary mode for stdio functions should be used to assure that the + * compressed data is not corrupted when read or written. For example: + * fopen(..., "rb") and fopen(..., "wb"). + */ + + +typedef unsigned (*blast_in)(void *how, unsigned char **buf); +typedef int (*blast_out)(void *how, unsigned char *buf, unsigned len); +/* Definitions for input/output functions passed to blast(). See below for + * what the provided functions need to do. + */ + + +int blast(blast_in infun, void *inhow, blast_out outfun, void *outhow, + unsigned *left, unsigned char **in); +/* Decompress input to output using the provided infun() and outfun() calls. + * On success, the return value of blast() is zero. If there is an error in + * the source data, i.e. it is not in the proper format, then a negative value + * is returned. If there is not enough input available or there is not enough + * output space, then a positive error is returned. + * + * The input function is invoked: len = infun(how, &buf), where buf is set by + * infun() to point to the input buffer, and infun() returns the number of + * available bytes there. If infun() returns zero, then blast() returns with + * an input error. (blast() only asks for input if it needs it.) inhow is for + * use by the application to pass an input descriptor to infun(), if desired. + * + * If left and in are not NULL and *left is not zero when blast() is called, + * then the *left bytes are *in are consumed for input before infun() is used. + * + * The output function is invoked: err = outfun(how, buf, len), where the bytes + * to be written are buf[0..len-1]. If err is not zero, then blast() returns + * with an output error. outfun() is always called with len <= 4096. outhow + * is for use by the application to pass an output descriptor to outfun(), if + * desired. + * + * If there is any unused input, *left is set to the number of bytes that were + * read and *in points to them. Otherwise *left is set to zero and *in is set + * to NULL. If left or in are NULL, then they are not set. + * + * The return codes are: + * + * 2: ran out of input before completing decompression + * 1: output error before completing decompression + * 0: successful decompression + * -1: literal flag not zero or one + * -2: dictionary size not in 4..6 + * -3: distance is too far back + * + * At the bottom of blast.c is an example program that uses blast() that can be + * compiled to produce a command-line decompression filter by defining TEST. + */ diff --git a/zlib-1.2.11/contrib/blast/test.pk b/zlib-1.2.11/contrib/blast/test.pk new file mode 100644 index 0000000000000000000000000000000000000000..be10b2bbb251759ffdf6da49fadd1a3f137a54c1 GIT binary patch literal 8 PcmZQzX;M+`Z>R?V2c!aC literal 0 HcmV?d00001 diff --git a/zlib-1.2.11/contrib/blast/test.txt b/zlib-1.2.11/contrib/blast/test.txt new file mode 100644 index 00000000..bfdf1c5d --- /dev/null +++ b/zlib-1.2.11/contrib/blast/test.txt @@ -0,0 +1 @@ +AIAIAIAIAIAIA \ No newline at end of file diff --git a/zlib-1.2.11/contrib/delphi/ZLib.pas b/zlib-1.2.11/contrib/delphi/ZLib.pas new file mode 100644 index 00000000..060e1991 --- /dev/null +++ b/zlib-1.2.11/contrib/delphi/ZLib.pas @@ -0,0 +1,557 @@ +{*******************************************************} +{ } +{ Borland Delphi Supplemental Components } +{ ZLIB Data Compression Interface Unit } +{ } +{ Copyright (c) 1997,99 Borland Corporation } +{ } +{*******************************************************} + +{ Updated for zlib 1.2.x by Cosmin Truta } + +unit ZLib; + +interface + +uses SysUtils, Classes; + +type + TAlloc = function (AppData: Pointer; Items, Size: Integer): Pointer; cdecl; + TFree = procedure (AppData, Block: Pointer); cdecl; + + // Internal structure. Ignore. + TZStreamRec = packed record + next_in: PChar; // next input byte + avail_in: Integer; // number of bytes available at next_in + total_in: Longint; // total nb of input bytes read so far + + next_out: PChar; // next output byte should be put here + avail_out: Integer; // remaining free space at next_out + total_out: Longint; // total nb of bytes output so far + + msg: PChar; // last error message, NULL if no error + internal: Pointer; // not visible by applications + + zalloc: TAlloc; // used to allocate the internal state + zfree: TFree; // used to free the internal state + AppData: Pointer; // private data object passed to zalloc and zfree + + data_type: Integer; // best guess about the data type: ascii or binary + adler: Longint; // adler32 value of the uncompressed data + reserved: Longint; // reserved for future use + end; + + // Abstract ancestor class + TCustomZlibStream = class(TStream) + private + FStrm: TStream; + FStrmPos: Integer; + FOnProgress: TNotifyEvent; + FZRec: TZStreamRec; + FBuffer: array [Word] of Char; + protected + procedure Progress(Sender: TObject); dynamic; + property OnProgress: TNotifyEvent read FOnProgress write FOnProgress; + constructor Create(Strm: TStream); + end; + +{ TCompressionStream compresses data on the fly as data is written to it, and + stores the compressed data to another stream. + + TCompressionStream is write-only and strictly sequential. Reading from the + stream will raise an exception. Using Seek to move the stream pointer + will raise an exception. + + Output data is cached internally, written to the output stream only when + the internal output buffer is full. All pending output data is flushed + when the stream is destroyed. + + The Position property returns the number of uncompressed bytes of + data that have been written to the stream so far. + + CompressionRate returns the on-the-fly percentage by which the original + data has been compressed: (1 - (CompressedBytes / UncompressedBytes)) * 100 + If raw data size = 100 and compressed data size = 25, the CompressionRate + is 75% + + The OnProgress event is called each time the output buffer is filled and + written to the output stream. This is useful for updating a progress + indicator when you are writing a large chunk of data to the compression + stream in a single call.} + + + TCompressionLevel = (clNone, clFastest, clDefault, clMax); + + TCompressionStream = class(TCustomZlibStream) + private + function GetCompressionRate: Single; + public + constructor Create(CompressionLevel: TCompressionLevel; Dest: TStream); + destructor Destroy; override; + function Read(var Buffer; Count: Longint): Longint; override; + function Write(const Buffer; Count: Longint): Longint; override; + function Seek(Offset: Longint; Origin: Word): Longint; override; + property CompressionRate: Single read GetCompressionRate; + property OnProgress; + end; + +{ TDecompressionStream decompresses data on the fly as data is read from it. + + Compressed data comes from a separate source stream. TDecompressionStream + is read-only and unidirectional; you can seek forward in the stream, but not + backwards. The special case of setting the stream position to zero is + allowed. Seeking forward decompresses data until the requested position in + the uncompressed data has been reached. Seeking backwards, seeking relative + to the end of the stream, requesting the size of the stream, and writing to + the stream will raise an exception. + + The Position property returns the number of bytes of uncompressed data that + have been read from the stream so far. + + The OnProgress event is called each time the internal input buffer of + compressed data is exhausted and the next block is read from the input stream. + This is useful for updating a progress indicator when you are reading a + large chunk of data from the decompression stream in a single call.} + + TDecompressionStream = class(TCustomZlibStream) + public + constructor Create(Source: TStream); + destructor Destroy; override; + function Read(var Buffer; Count: Longint): Longint; override; + function Write(const Buffer; Count: Longint): Longint; override; + function Seek(Offset: Longint; Origin: Word): Longint; override; + property OnProgress; + end; + + + +{ CompressBuf compresses data, buffer to buffer, in one call. + In: InBuf = ptr to compressed data + InBytes = number of bytes in InBuf + Out: OutBuf = ptr to newly allocated buffer containing decompressed data + OutBytes = number of bytes in OutBuf } +procedure CompressBuf(const InBuf: Pointer; InBytes: Integer; + out OutBuf: Pointer; out OutBytes: Integer); + + +{ DecompressBuf decompresses data, buffer to buffer, in one call. + In: InBuf = ptr to compressed data + InBytes = number of bytes in InBuf + OutEstimate = zero, or est. size of the decompressed data + Out: OutBuf = ptr to newly allocated buffer containing decompressed data + OutBytes = number of bytes in OutBuf } +procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; + OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer); + +{ DecompressToUserBuf decompresses data, buffer to buffer, in one call. + In: InBuf = ptr to compressed data + InBytes = number of bytes in InBuf + Out: OutBuf = ptr to user-allocated buffer to contain decompressed data + BufSize = number of bytes in OutBuf } +procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer; + const OutBuf: Pointer; BufSize: Integer); + +const + zlib_version = '1.2.11'; + +type + EZlibError = class(Exception); + ECompressionError = class(EZlibError); + EDecompressionError = class(EZlibError); + +implementation + +uses ZLibConst; + +const + Z_NO_FLUSH = 0; + Z_PARTIAL_FLUSH = 1; + Z_SYNC_FLUSH = 2; + Z_FULL_FLUSH = 3; + Z_FINISH = 4; + + Z_OK = 0; + Z_STREAM_END = 1; + Z_NEED_DICT = 2; + Z_ERRNO = (-1); + Z_STREAM_ERROR = (-2); + Z_DATA_ERROR = (-3); + Z_MEM_ERROR = (-4); + Z_BUF_ERROR = (-5); + Z_VERSION_ERROR = (-6); + + Z_NO_COMPRESSION = 0; + Z_BEST_SPEED = 1; + Z_BEST_COMPRESSION = 9; + Z_DEFAULT_COMPRESSION = (-1); + + Z_FILTERED = 1; + Z_HUFFMAN_ONLY = 2; + Z_RLE = 3; + Z_DEFAULT_STRATEGY = 0; + + Z_BINARY = 0; + Z_ASCII = 1; + Z_UNKNOWN = 2; + + Z_DEFLATED = 8; + + +{$L adler32.obj} +{$L compress.obj} +{$L crc32.obj} +{$L deflate.obj} +{$L infback.obj} +{$L inffast.obj} +{$L inflate.obj} +{$L inftrees.obj} +{$L trees.obj} +{$L uncompr.obj} +{$L zutil.obj} + +procedure adler32; external; +procedure compressBound; external; +procedure crc32; external; +procedure deflateInit2_; external; +procedure deflateParams; external; + +function _malloc(Size: Integer): Pointer; cdecl; +begin + Result := AllocMem(Size); +end; + +procedure _free(Block: Pointer); cdecl; +begin + FreeMem(Block); +end; + +procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl; +begin + FillChar(P^, count, B); +end; + +procedure _memcpy(dest, source: Pointer; count: Integer); cdecl; +begin + Move(source^, dest^, count); +end; + + + +// deflate compresses data +function deflateInit_(var strm: TZStreamRec; level: Integer; version: PChar; + recsize: Integer): Integer; external; +function deflate(var strm: TZStreamRec; flush: Integer): Integer; external; +function deflateEnd(var strm: TZStreamRec): Integer; external; + +// inflate decompresses data +function inflateInit_(var strm: TZStreamRec; version: PChar; + recsize: Integer): Integer; external; +function inflate(var strm: TZStreamRec; flush: Integer): Integer; external; +function inflateEnd(var strm: TZStreamRec): Integer; external; +function inflateReset(var strm: TZStreamRec): Integer; external; + + +function zlibAllocMem(AppData: Pointer; Items, Size: Integer): Pointer; cdecl; +begin +// GetMem(Result, Items*Size); + Result := AllocMem(Items * Size); +end; + +procedure zlibFreeMem(AppData, Block: Pointer); cdecl; +begin + FreeMem(Block); +end; + +{function zlibCheck(code: Integer): Integer; +begin + Result := code; + if code < 0 then + raise EZlibError.Create('error'); //!! +end;} + +function CCheck(code: Integer): Integer; +begin + Result := code; + if code < 0 then + raise ECompressionError.Create('error'); //!! +end; + +function DCheck(code: Integer): Integer; +begin + Result := code; + if code < 0 then + raise EDecompressionError.Create('error'); //!! +end; + +procedure CompressBuf(const InBuf: Pointer; InBytes: Integer; + out OutBuf: Pointer; out OutBytes: Integer); +var + strm: TZStreamRec; + P: Pointer; +begin + FillChar(strm, sizeof(strm), 0); + strm.zalloc := zlibAllocMem; + strm.zfree := zlibFreeMem; + OutBytes := ((InBytes + (InBytes div 10) + 12) + 255) and not 255; + GetMem(OutBuf, OutBytes); + try + strm.next_in := InBuf; + strm.avail_in := InBytes; + strm.next_out := OutBuf; + strm.avail_out := OutBytes; + CCheck(deflateInit_(strm, Z_BEST_COMPRESSION, zlib_version, sizeof(strm))); + try + while CCheck(deflate(strm, Z_FINISH)) <> Z_STREAM_END do + begin + P := OutBuf; + Inc(OutBytes, 256); + ReallocMem(OutBuf, OutBytes); + strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); + strm.avail_out := 256; + end; + finally + CCheck(deflateEnd(strm)); + end; + ReallocMem(OutBuf, strm.total_out); + OutBytes := strm.total_out; + except + FreeMem(OutBuf); + raise + end; +end; + + +procedure DecompressBuf(const InBuf: Pointer; InBytes: Integer; + OutEstimate: Integer; out OutBuf: Pointer; out OutBytes: Integer); +var + strm: TZStreamRec; + P: Pointer; + BufInc: Integer; +begin + FillChar(strm, sizeof(strm), 0); + strm.zalloc := zlibAllocMem; + strm.zfree := zlibFreeMem; + BufInc := (InBytes + 255) and not 255; + if OutEstimate = 0 then + OutBytes := BufInc + else + OutBytes := OutEstimate; + GetMem(OutBuf, OutBytes); + try + strm.next_in := InBuf; + strm.avail_in := InBytes; + strm.next_out := OutBuf; + strm.avail_out := OutBytes; + DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); + try + while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do + begin + P := OutBuf; + Inc(OutBytes, BufInc); + ReallocMem(OutBuf, OutBytes); + strm.next_out := PChar(Integer(OutBuf) + (Integer(strm.next_out) - Integer(P))); + strm.avail_out := BufInc; + end; + finally + DCheck(inflateEnd(strm)); + end; + ReallocMem(OutBuf, strm.total_out); + OutBytes := strm.total_out; + except + FreeMem(OutBuf); + raise + end; +end; + +procedure DecompressToUserBuf(const InBuf: Pointer; InBytes: Integer; + const OutBuf: Pointer; BufSize: Integer); +var + strm: TZStreamRec; +begin + FillChar(strm, sizeof(strm), 0); + strm.zalloc := zlibAllocMem; + strm.zfree := zlibFreeMem; + strm.next_in := InBuf; + strm.avail_in := InBytes; + strm.next_out := OutBuf; + strm.avail_out := BufSize; + DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); + try + if DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END then + raise EZlibError.CreateRes(@sTargetBufferTooSmall); + finally + DCheck(inflateEnd(strm)); + end; +end; + +// TCustomZlibStream + +constructor TCustomZLibStream.Create(Strm: TStream); +begin + inherited Create; + FStrm := Strm; + FStrmPos := Strm.Position; + FZRec.zalloc := zlibAllocMem; + FZRec.zfree := zlibFreeMem; +end; + +procedure TCustomZLibStream.Progress(Sender: TObject); +begin + if Assigned(FOnProgress) then FOnProgress(Sender); +end; + + +// TCompressionStream + +constructor TCompressionStream.Create(CompressionLevel: TCompressionLevel; + Dest: TStream); +const + Levels: array [TCompressionLevel] of ShortInt = + (Z_NO_COMPRESSION, Z_BEST_SPEED, Z_DEFAULT_COMPRESSION, Z_BEST_COMPRESSION); +begin + inherited Create(Dest); + FZRec.next_out := FBuffer; + FZRec.avail_out := sizeof(FBuffer); + CCheck(deflateInit_(FZRec, Levels[CompressionLevel], zlib_version, sizeof(FZRec))); +end; + +destructor TCompressionStream.Destroy; +begin + FZRec.next_in := nil; + FZRec.avail_in := 0; + try + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (CCheck(deflate(FZRec, Z_FINISH)) <> Z_STREAM_END) + and (FZRec.avail_out = 0) do + begin + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); + FZRec.next_out := FBuffer; + FZRec.avail_out := sizeof(FBuffer); + end; + if FZRec.avail_out < sizeof(FBuffer) then + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer) - FZRec.avail_out); + finally + deflateEnd(FZRec); + end; + inherited Destroy; +end; + +function TCompressionStream.Read(var Buffer; Count: Longint): Longint; +begin + raise ECompressionError.CreateRes(@sInvalidStreamOp); +end; + +function TCompressionStream.Write(const Buffer; Count: Longint): Longint; +begin + FZRec.next_in := @Buffer; + FZRec.avail_in := Count; + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (FZRec.avail_in > 0) do + begin + CCheck(deflate(FZRec, 0)); + if FZRec.avail_out = 0 then + begin + FStrm.WriteBuffer(FBuffer, sizeof(FBuffer)); + FZRec.next_out := FBuffer; + FZRec.avail_out := sizeof(FBuffer); + FStrmPos := FStrm.Position; + Progress(Self); + end; + end; + Result := Count; +end; + +function TCompressionStream.Seek(Offset: Longint; Origin: Word): Longint; +begin + if (Offset = 0) and (Origin = soFromCurrent) then + Result := FZRec.total_in + else + raise ECompressionError.CreateRes(@sInvalidStreamOp); +end; + +function TCompressionStream.GetCompressionRate: Single; +begin + if FZRec.total_in = 0 then + Result := 0 + else + Result := (1.0 - (FZRec.total_out / FZRec.total_in)) * 100.0; +end; + + +// TDecompressionStream + +constructor TDecompressionStream.Create(Source: TStream); +begin + inherited Create(Source); + FZRec.next_in := FBuffer; + FZRec.avail_in := 0; + DCheck(inflateInit_(FZRec, zlib_version, sizeof(FZRec))); +end; + +destructor TDecompressionStream.Destroy; +begin + FStrm.Seek(-FZRec.avail_in, 1); + inflateEnd(FZRec); + inherited Destroy; +end; + +function TDecompressionStream.Read(var Buffer; Count: Longint): Longint; +begin + FZRec.next_out := @Buffer; + FZRec.avail_out := Count; + if FStrm.Position <> FStrmPos then FStrm.Position := FStrmPos; + while (FZRec.avail_out > 0) do + begin + if FZRec.avail_in = 0 then + begin + FZRec.avail_in := FStrm.Read(FBuffer, sizeof(FBuffer)); + if FZRec.avail_in = 0 then + begin + Result := Count - FZRec.avail_out; + Exit; + end; + FZRec.next_in := FBuffer; + FStrmPos := FStrm.Position; + Progress(Self); + end; + CCheck(inflate(FZRec, 0)); + end; + Result := Count; +end; + +function TDecompressionStream.Write(const Buffer; Count: Longint): Longint; +begin + raise EDecompressionError.CreateRes(@sInvalidStreamOp); +end; + +function TDecompressionStream.Seek(Offset: Longint; Origin: Word): Longint; +var + I: Integer; + Buf: array [0..4095] of Char; +begin + if (Offset = 0) and (Origin = soFromBeginning) then + begin + DCheck(inflateReset(FZRec)); + FZRec.next_in := FBuffer; + FZRec.avail_in := 0; + FStrm.Position := 0; + FStrmPos := 0; + end + else if ( (Offset >= 0) and (Origin = soFromCurrent)) or + ( ((Offset - FZRec.total_out) > 0) and (Origin = soFromBeginning)) then + begin + if Origin = soFromBeginning then Dec(Offset, FZRec.total_out); + if Offset > 0 then + begin + for I := 1 to Offset div sizeof(Buf) do + ReadBuffer(Buf, sizeof(Buf)); + ReadBuffer(Buf, Offset mod sizeof(Buf)); + end; + end + else + raise EDecompressionError.CreateRes(@sInvalidStreamOp); + Result := FZRec.total_out; +end; + + +end. diff --git a/zlib-1.2.11/contrib/delphi/ZLibConst.pas b/zlib-1.2.11/contrib/delphi/ZLibConst.pas new file mode 100644 index 00000000..cdfe1367 --- /dev/null +++ b/zlib-1.2.11/contrib/delphi/ZLibConst.pas @@ -0,0 +1,11 @@ +unit ZLibConst; + +interface + +resourcestring + sTargetBufferTooSmall = 'ZLib error: target buffer may be too small'; + sInvalidStreamOp = 'Invalid stream operation'; + +implementation + +end. diff --git a/zlib-1.2.11/contrib/delphi/readme.txt b/zlib-1.2.11/contrib/delphi/readme.txt new file mode 100644 index 00000000..2dc9a8bb --- /dev/null +++ b/zlib-1.2.11/contrib/delphi/readme.txt @@ -0,0 +1,76 @@ + +Overview +======== + +This directory contains an update to the ZLib interface unit, +distributed by Borland as a Delphi supplemental component. + +The original ZLib unit is Copyright (c) 1997,99 Borland Corp., +and is based on zlib version 1.0.4. There are a series of bugs +and security problems associated with that old zlib version, and +we recommend the users to update their ZLib unit. + + +Summary of modifications +======================== + +- Improved makefile, adapted to zlib version 1.2.1. + +- Some field types from TZStreamRec are changed from Integer to + Longint, for consistency with the zlib.h header, and for 64-bit + readiness. + +- The zlib_version constant is updated. + +- The new Z_RLE strategy has its corresponding symbolic constant. + +- The allocation and deallocation functions and function types + (TAlloc, TFree, zlibAllocMem and zlibFreeMem) are now cdecl, + and _malloc and _free are added as C RTL stubs. As a result, + the original C sources of zlib can be compiled out of the box, + and linked to the ZLib unit. + + +Suggestions for improvements +============================ + +Currently, the ZLib unit provides only a limited wrapper around +the zlib library, and much of the original zlib functionality is +missing. Handling compressed file formats like ZIP/GZIP or PNG +cannot be implemented without having this functionality. +Applications that handle these formats are either using their own, +duplicated code, or not using the ZLib unit at all. + +Here are a few suggestions: + +- Checksum class wrappers around adler32() and crc32(), similar + to the Java classes that implement the java.util.zip.Checksum + interface. + +- The ability to read and write raw deflate streams, without the + zlib stream header and trailer. Raw deflate streams are used + in the ZIP file format. + +- The ability to read and write gzip streams, used in the GZIP + file format, and normally produced by the gzip program. + +- The ability to select a different compression strategy, useful + to PNG and MNG image compression, and to multimedia compression + in general. Besides the compression level + + TCompressionLevel = (clNone, clFastest, clDefault, clMax); + + which, in fact, could have used the 'z' prefix and avoided + TColor-like symbols + + TCompressionLevel = (zcNone, zcFastest, zcDefault, zcMax); + + there could be a compression strategy + + TCompressionStrategy = (zsDefault, zsFiltered, zsHuffmanOnly, zsRle); + +- ZIP and GZIP stream handling via TStreams. + + +-- +Cosmin Truta diff --git a/zlib-1.2.11/contrib/delphi/zlibd32.mak b/zlib-1.2.11/contrib/delphi/zlibd32.mak new file mode 100644 index 00000000..9bb00b7c --- /dev/null +++ b/zlib-1.2.11/contrib/delphi/zlibd32.mak @@ -0,0 +1,99 @@ +# Makefile for zlib +# For use with Delphi and C++ Builder under Win32 +# Updated for zlib 1.2.x by Cosmin Truta + +# ------------ Borland C++ ------------ + +# This project uses the Delphi (fastcall/register) calling convention: +LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl + +CC = bcc32 +LD = bcc32 +AR = tlib +# do not use "-pr" in CFLAGS +CFLAGS = -a -d -k- -O2 $(LOC) +LDFLAGS = + + +# variables +ZLIB_LIB = zlib.lib + +OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj +OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj +OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj +OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj + + +# targets +all: $(ZLIB_LIB) example.exe minigzip.exe + +.c.obj: + $(CC) -c $(CFLAGS) $*.c + +adler32.obj: adler32.c zlib.h zconf.h + +compress.obj: compress.c zlib.h zconf.h + +crc32.obj: crc32.c zlib.h zconf.h crc32.h + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + +gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h + +gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h + +gzread.obj: gzread.c zlib.h zconf.h gzguts.h + +gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h + +infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h + +inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + +trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h + +uncompr.obj: uncompr.c zlib.h zconf.h + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + +example.obj: test/example.c zlib.h zconf.h + +minigzip.obj: test/minigzip.c zlib.h zconf.h + + +# For the sake of the old Borland make, +# the command line is cut to fit in the MS-DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + -del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) $(OBJP1) + $(AR) $(ZLIB_LIB) $(OBJP2) + + +# testing +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) + + +# cleanup +clean: + -del *.obj + -del *.exe + -del *.lib + -del *.tds + -del zlib.bak + -del foo.gz + diff --git a/zlib-1.2.11/contrib/dotzlib/DotZLib.build b/zlib-1.2.11/contrib/dotzlib/DotZLib.build new file mode 100644 index 00000000..7f90d6bc --- /dev/null +++ b/zlib-1.2.11/contrib/dotzlib/DotZLib.build @@ -0,0 +1,33 @@ + + + A .Net wrapper library around ZLib1.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/dotzlib/DotZLib.chm b/zlib-1.2.11/contrib/dotzlib/DotZLib.chm new file mode 100644 index 0000000000000000000000000000000000000000..f214a444aebb20950fb3e8499b36731e1f12be95 GIT binary patch literal 72726 zcmeGEby!tR_Xmt0Lb^-3ySqWUyF;2oNq0+kgMffYgLESxDJ4jYNJ^JTHv%sx-r#-v zJooqc<9Geu_qyC%`^?@mpEY~UXU(jcS?6pdRg}fR004mg^$Bu)%1mlyL4X4QNEaZU zg&sr5>2QFIcf>23$bY-P!QUL1KN5iJZK}ffiW3R5Bgdsi#SjndZHoZ7pFgTx{Kvz zl?C`=WYS*WsmLox3SSrcy2a>U->NFfT;oBWza%PF`f;lwBm?q1PBTK{x+--^IT3kv zWsrnPVqY0p22wFe6GwAd19NMT#CmhT0wib#Qh6aMNjYT|ki;D7XOGYsNY&K^9UN?o z%ncmPoq;mu)=wO6G{*aFfr7n_EzsW4?OK=|9Qg(!4Rmv{u{Zup4&xu0LMrw^AV|WL zwQsr1_s9JrB4XfZ0FoHNo#>AC4@p@ATad(TRwb-|l-$z;f)Is4#Ky?U3TW+k-2@wJ zdNVU4khpqL-+b49mOKH8pXU?Axt4I$k})@=7c{m6+6$Wjjh;9-S<#z0T3Lel_6kK{ z(ESI5s;#ksBT&!A8E9{5V_>Yu@xs_Wvg1a4XW~9`%&`_aeeJ)((#LPDYM4 z_P1bvf^b5Le+4t$qN5&#DE~W}`4*jo5@tpG`?_U;R)#?PTaA4`Y7~qAN1&sbjq%T> zWj@XEAo#1spY)0Yt%3FicWv5~3zH%HFDNCT1JLn@j{f;lA>2&=1^aiq+%n<6i4ckN zzsTKk;{Vw>0`q^7yX^=5y$_%1{V#H?x9w}T45wlIzqjv}X#aBXD6{`Yp_+lE6Y%yC zvAiK_cU|-!MiDY_0MhFjIoaD^52PO=0n>~j#w7n)tM4M;$Bh3eRfG)Hzaa0~Gw=m` zs1Vz~;Qxb71J`(?*#1}9Te}8M!9+6uud=tc4Qv-omi%93Z|xgc;}Ido`oFdJ*2aN( z^3k;aM(sU22kdBss?h)UNBzUU1eD1|h%o%0g>FYzz#EiM{{OqwtqlS?6~amWr9oom zK+B)rBw)xPoR9jy>-LME3J7$1rTMP{_xx4B8EuxqoyY&}(72s(%z?LN30Ou87rAra z|B(4bBfn$pD4YKZzNd|U3Q8pBf8povn)nAnhqK(dWnmj*pwacbW_&kE-I^B!eDF&e= zzkBj6o3~FM*9s%~T{Et&W?*UVerwo}d9M&^{NJ?pzHvh~C_>#H{s#2jz(Kp%;Y`0X z@Dm{?6BD4l@?Q@N9w7}8yj%Eu9}3^ukhlI#J3|f#Lu`Imul>!!L*B{pj=c-S5S`y4 zuW`RxEi}+F4Eb+k>_&rsc--J>v|t0ge>Pdv`Fi@j?J1$rUSY<+!QA(b!HrIlD!<|P z7ylFVO}b9F@p~coG=qg7vHB_q7h1r3{n#+fe>h8z0>mi+=#_ zX%duU7QywmcK=kGfX+b6A00F_2Rs_*9zsc&h52vBsv-z? zxaaqOLHvF7!SbWlux6I~D}CYrCUa}Xurk*BEB#+Y{?RW&zi8fH>HjD2txFF*a=X9M z|4-;!FBN(vbAP4(3;Gueg|?vFU+Mo1c+XN{VO%*LcisJ$K_+2feY3f`rELr zJe2%;+xxr25HSWJ1O5n30L~7!4rT+I2HFJ51=0yZ?STQf6qqY$0th@v6o4OK0=U`# z(?Z#%dGKq@!3>E)vb-&IgQ7?o;=7W_=qr> zNUgi+?Ow4A(Aw1TcD)h#nk|C;w;CzfIGF#4Gu%WAB0HW$-1E`*YP;h!s!S#M_hj8* zgxr3T71aY9N_}U>dv)CrA2rMt#dbI1e!)22Z$Q*%iwK9`QgzQfQJXr6F2AkqJLpce zXn&Px?7JE8?y>*quMx{0VfuHY_qWJf?-jA59i{Lu&|B9PaYYk}@H?aZG7ch=$@^7* zkGeM!B8TPM>3-Mfzt1s|5nQqE@PBor@4d&jfGZ37&XGx4{})FVlcay&k^L5X>&Rjv zaql~_zo5T3vY33K`;P1{(0xZ1Q|25>e&=)k!hBagI?g&=^sZC?Ec}NJqsO^|#qK)d zPuwqDN2jyg_c?c%drU{qJ}t$&v&S{YhF-$JK?G>%WcvN)yH>F=tRbQ|p}HR-xx0dx zdfYJazlq;0_T)|EO-%lZ4aFwAg(%#)nD630PzpBY);E*PkEdixhA8~fCL8)6FjdK) z0gu>1tPrWYF>|jfRT&#=)7y$FjY8z^hQfD{ssqsBI*NK7EwgmHS#{nb8<|3M?iM=V zk!siBwC_R68|M+*fe<3}t4{y0Ma&+4@T0rs)=ee9*dgYvQ7O;eChVsC@BKLDR3}mW zZY6XR_!M92`IrQfOLS5E*Rk&7G})H(ik4)Z7FlAp$%Y z4&gf2#?j;^r0_j6e%mn^_g0`xVT42e~2LWd0%_zvdF;1&76%6hF32tv=dGj!U z1uoUU;;%KbzUf2&LnwxS1*_N_SUZ^5*jq7tSD%+$?|%^S;1CmL=Hy~!q~j7{VWMMV z61lz-V&Jxr-`6Pf_{Lii%x zdZoL)i++*|5t=&fa-*N3>gCP@d3pHNAOm#Lr_Lg7m#Xz(9Ql|at87Hcm8)v z@Si*TA8W$9;J}}&KMed~;12_T82H1$9|ry~@P~mv4E$l>4+DP~_`|>-2L3c!ufYge={Z>GIXM`auggilzhiMD^ZmVvAHsn0 zKJ~2h7aczvcilR8z|YX(O$-PC20*yZxc3480OC5w_?Mgq0BC@$gR!*)(9#wFdHt+1 zD5GMy>-6Th<_bxLL|OI~aW%-zV}ict{&<7q_VSmvJZ^r~@%Q5f_m_%4h5n>}82H1$ z9|ry~@P~mv4E$l>4+DP~_`|>-2L3Schk-u~{J)9;#M@W^64Fidgau511pq))O(ryd z1lkJ<4U}b!vlFh=$D7i8MMuk2Nz7V{XY;j|=6tiZHcmtQJY)|M{NXWUF#tfqtS<@y zkOZWYRRSyJ)PzW-rIW-?Bok@f2oou!{V6E}wf86Bn|cRo9k!a1=<6%bC$jZADJ=&a z7pWfWw>tNp1R$Ovql(VwWf2_s5U3IgsvhL#TSH^So#=o{Uuy^+Qqys*;DvUL}rA?=4`lbR=jsW0?YvR*h$HnNhp= zC!izu;7A+DiZ@kulAlK{n{*^;+WBXnvVm^`j#IMvXU-V}_qao1<69ICjx z#>je?dOT5Wl|%`3vbEPHG~%aFZzYFws0JrvGib&2P+KG9gm@|Na;`dR;@hXdF0GoZ zA-H|QH*e*41=$Iq5bI%HN<7~G#@%@RB7i{JIIaZ}5Wwy4o<;eoy+hDvrhjIDL?wm@1uB1Q#CKL+EnX#od_o5Ll)IMaO z7NBj&@^Kd;)<%OES%^J;dru5(Byz|)wNe231+*1B;m&Izkxf{~q>@M^K5oRE!sTob zc|{J+dp9AWy9VYkT9+9Xs~h za7ux3s^H@U1XPuqE^Qhl@AX5bvU0-YlbYY7u#DLoD@_$+y~NzrtM0>7+1`o^!%<4#Gz6nx%!45)1j#*6H%w}%lL>bkPU;E?AJ8F+BF#1h*)IhVyMi_Ov zsP^M0U`mpo15%jKwLnIhv>I@EEM%1`z#gA-uZa|{w;0Fa<;p*AlslXpj&U`@7sC2t z^zDl(eNUPt;1!(3LTitPAQ;BOW~318lc{z8PH}Qizn}}TOCKI8urso=eH&5)*=8`` zp2~o#l&9$#hnp<9m0A6^0!0mYp=~A0p6kv&f``RmG&`p&3S1xA1q#Z&mWDQ+e8$QU zdYCmRYx5Uo_^3Kpt2*gWb+llW=!(}qid*e*;K%r3yXT@z9M~6J6s4W)yAYFWe5HLK zLzt|wA*)yYu{qhsS{D>18jm#IH$G*d<0Wc!%;ZV=R!Zbb{^7V)aDh~#YlpjpjKM9N=; z>p{p}tsH%-GWJ_W?06|`VM8Q3<;UnLcV=dbQ(dHnG(Sljt7YptrcYv!i*oOTH}{dKWA=+9*g{ZYWJuh2k-7#a>5t$bF)tT%YE zXknN}yshg~aR3ihYrf2JAi1;`U>8O3G~wXHJT%z47}=uULl5)|GbC{@3l!y+B2*~f z5DjcU3lNj0L9LvJs2$yYo&PnlA$`0mw8lE44re*ay-w$)@TQd*clNAR(%5uPdB1zi z$VV@;e2am|gwU=bi3Ahc2-#RQ@Nj4ZR|M%yV{F)u1EjT!9~IyGxH=6o=bI!9tM4V9 zbj_g>xz2R!1`{swDfWX?J_xn2!x`6(1sn7`%cIC}oA8KLKFZ6G`1-{Mb%Gh{twcVN zq6VA;DyiF|ZA@EJ=2F1GleU)erF@D~9hw9hVXb^lDkhymJIUFHVbQAc(AH!-KEV8w zAjx)Vwy>U^Iw=20(<2uf(23nLxb!{&gdH4nxP_*xYF?fdBUT{!B>#)%AdnKLLoAd% zF)T0&Lw=ZSZHt59{(K>Bkvty(DpM`l82!)rC-3lEYU$}o8c0{qipkSGIh)_p6+1p# zvQ=^Jkc`a9Sh>;&={E<<*3Q65XH(xKGsk_s8o{X6xD&4X*)r4CLE#*tde3<2Ftz&J z-bRK2D)TE^O0lz+q_}32BSXH1giVjkV-(CZqm^v#z3`3d>Q)Jlz#WZ2C|%q+1=V7( zOL<5p{(S34Nr@ks)(@gEk0mIzP1K$3)Az#HKgrY=yXS2rUBJ+Y=+H1-R5Fa~QBCT! z;f*{V=ue75&_o`g?M=eV>fF=Ze+=&v4p)Cx6@aLwjlc>kTCyq1q@mr`ZM7q*a8^Ly z7rz}o$wn8ZUHU<+Y8&|JQlkt+Luh{UZ0GGW=pkwJ@fV_I9S-k7!Cuo$&2Vpl9RZKd zRQCZ-s|f59qfG4gNx(e7C8Y721+6zf4~s=w7U|a_o6;>swO!S`4CNDZwO@EKZpwjQ z@Pb_6ThX|78nr(WG{ROYB;F7^oFX=zE~dK9y4#dXex!BgnaRaZU$J?%%%?&@hbFD_ z%Ej3Yq2$%}j60QKxp?1@dHrs(8ZPvf(sVTU+E_+p@nQTY&2sr@D^;-;ho|sPO(8yoxcfqEqX?w-F68l>x{*l95$+F#fzj1+VJ-K+ktL;m{t$ zn*%I&+651%T{a&pFy@uVK)CaMp}j?{^FkcEfLYv<4xTgo(Wqm$#Om052eiCYmD5DZ z&ijs8rrC14S&PxVisY*Kk%D6meU3**RHOwGs&qZsrpG0M*RMk9!HROcM%3-mu)-(XZb)E($w()#z-L!EMb*e%#1Z&iG(gpF+| zPXJUKk3eY3l_H->hMO+$C1jVgFKG1?m&zkX*b&7{SCJIYlb(0r-{B6Oe9N(5)5M=Uak}sB*b)ZU~ghv z(IG(iUu5B<3fH9T^vKy~ats%hi{$1Kr^pY|L96c7P4Ov5#}w|2zlD{iskUo=IVpM& z5&@Ix^_sV=wO8TrX-WhxY#pk%*a8z;q0z?Y<$dMxBn;Zozj{YZV2o7z&>-DtLB`*fMufc%%(P`up2-<26ztjiYl_%skr?=WwAIm-DJTPl3SZ?3yXxi-;#GI?^qq0Vz>4 z17s=BFD^xg9QS3XB!9=mS(}0@iPiJn9F_P{+q@xoiB?Pdx_epH5dJ=0UgN)10zR@>e3E?b9{{ zu=7O-DJXpk$DfkL>3b_qCwqJZ(UJ*8MzM^gggLS^N`54;Yct-#~H$Opm6;`8YGxoQ}nH}tDm6C{>AWzyOt zc*q%{(5GjR-L*c-SM-qC8rWtpJ}eyPLfs2(;`=O)&pfpP?+S}`2*d-mA)Gz(@Ft?R zt2G~BJg^gwVe2)myY~)kl+hL5HM6v*|CE5I0N*l$uUwYfeSNjeS z`)!3Mh4u&uQ#rhcI;Damwu(b;3wdYGeE#~QH2~Q}43<5R`+2?}n;|>zyo?cv{eTw- zriS0vVZYvMCV^{zOFyle9<$auzW9~f7(b#M^>`otrAN#T%&-+lM;i#CcGV|Kq`IIT zf;N?5q-`97b)<>Z5tBoK^NWxKcbHM5957zsdeFKAo1-weVs;pe$jiL8B7qK@+Se1& zXa+-)2$2@;Eb2y4lmv>Y)31$JA!c467rmo)o3P%2aapVL?BrhZdYJdl$-%C~;;j&o&8+sIuC5Hud||g|)0M~D+^e+JPOja>HqYSdkF2!= zgGe!}hQQ_+Gkdd(J=c=$`tfz|1&_XOo>|5>oW#%Vf*atEtQXbgyN&#ESLSPS$QOmq8~BiXU;z6*+xu=JQSQ+JU~{t_=sVL>ii(V-}H6M-2+xf>cp> zIMCfb4tePxIM{PVzTgVEX~XBfSH@ArgQ?rgVuj+KEw;e1sYH^vCBEZf@jht=o(vh0 zn~>wHx`X_i$*#mR0uKVRmx_9rR7y)Dk54veWKQB*0V(P+L<65F)^;aRpkKp|uzBQ# zo}#0DW&>}U>Y9$o;AA+UuF9WZo{;{aJKq%kvUXhy@=*89D=Ub?a*T7eU=t2h+ju^F zT_5)2dY8%7pe$0{d=*6%?4Gze7XqdRlwH+q2?g_SN?906dm++;hlki%IqQRNO@&Q% z!SKZIOzqvXZ3rpRV5U&ucY9@~&?Y0Necd9wZF3id>w>~;lKJf8M9mK061%TP^D8Kb zef?xC;PJJB%t}etmuBPK6ZAmAKR04Yp&^}d-hxC0@DY`!5%Sq1AU0k}@zaS<{_efl zXBtzKcG?TAhz9f?RcZV09+=C0U0L^`zEC%$(&r{GWIUWFL1Kp=f_aO?8DHW53I-`u z4V*tDLS-;4uBl^929^3*t!}ClMZqHi{2n<)AM5OlG$KK6{1ii(a#N**5Ev=Xup_*I zEX8BvB%cD69?VhC-nAo5&*$&7D^H~kO6|04QqmFHP9^o}rY89F+v6*7?T|%yH4v}_ zE7|Rc_i_q_AM$%n)CxcyESmRZrjxoq=Pt^|TMQqH9t&kO(dBN?7O_MO`NhuVg&e2`KMd?Bt{8q+~=86vNUk!`z}G?0+n9sB%)sDV^{OiS*9!yH7{@mmZ){U%dVb_5R?MpzGt|H7&>z1wlHDwoin!&tU!a z1pS$dTb84Jqm{4~VT0ck=J#;p?w26bGjL)w$3pSqz17UwhJQp&f<52e$)-SwkIoJw zl3+6_my0ke)>r#ck&~DB_0+Q~Vzkg@UHqpJX6b<>II!X;$L}{tsz%|S$N!8RZ3f;J|*8y zv-j+r-|k1;Y=AN`lLUfxzTlPCpSoT%X|6@lc?;IY1ayVOOgT^2PUUS?)o#U^i0_9i zTu0o-kv;+dSXi&KzyNDt1QPnyF)2_WG$5e-t!3@@=)yKWI$x^$+nv9bmT8PRmo~bD zTUb3gZZ0YLI@35=QnR}on^ZU%wOiL+*w_`uz&o<4W#t;GZfYG72->_;5iCFmzHkm8 z0sxSiz_J;Anjg)cZyn8SUCk)h%|rk-s~&!~t{r>w^`p5;&Wi+D79=|DR7aDT0%}$$ znXClJbk}rfKOa!P9H=m6P(q(aKK_8{y+`dCnBfFzgtyO?}e)*?u*m%?G=5O*z`2edwRd!QC4AjE(XI{AQK2_nUv53>yY}6 zXY1or!u*R;p2vY6(a9ttr!Wah^~>vqHMv#|;cYFG!>CPR>D$x7>7(4Vy0WcXIZ`{L zMdOi2Gu)UBX-RrtJW^m~;VGc4ww$%#wNmA?CnLF%QyG~(_IfAiAJDb83#6H<)E#XQ zuNPlD*h$;|@vFy<+50j@lULpkJNe-tbg#!CXGM}dThN0wY zd0vvwsyF$cYcB;lFx7re)zbU6b@2G|M z7#N0IF?1Tz^kwo`N`MlDJc%7H?5U1E970xI&R&U>=N~t!|BzT>?G{ zi2LohH00cJBGqih8UXLB-)vMXOm3E3*_x>%MGb6Y*y6F)mhTS!iL>*b#!5PiqhZVI z$~m()Do1J`!oH-CrLC+9)HTDH#iJkwaWSOy-Fjc6o?NPaY;+0=vs?I+Cm=_x2Z|CR1tz2#D!j>Ky_mvG8YTe#^)P^=aWIVm1W+!q?2PpDdy z!?>rDk1u3$O-du}p_t;`9-r~}ifx7sI7ctJyM|jq=E%Y+ZHXdcB zD^_NV)L~*WNzzaAmMIcvsT0)5a$murA&+jb$#ZTbm|7gO7-y_K@f>_1uX}=w2i-cq z3Pgw{kejSq7cPDurWz?n7QAO!Up7fOsNC)kOZ6%f0n7IE+-wRwcoT0G;tFO) z-D^=T48wu}uwoZAI&#b^nC--lEY|;+K+tdXLkEM^s;5z6fD1eq!>Mln*iy&K(k|_n z41HBF3y`~EyqV0J<~){HJ`eWDtFVWNBZG8ao-{tJXhE7?6wKn9IxDDEEZ>{D>*8Jd%etAphHkuB|@oH-*n(2lBVC9(vdED#>(+ zPWLRJ5*Ngw5`y@2p;3Pe_UJ>x(r>Nf7auUlUg8-s^P41)A=Q=dZCpA!A6hLDt+LA| z#*1MGMjyYYqYw){pTOjse_3HF?t+M)T&}IaG?+S%vc0mabYi&Onw27s-2Ub)D4cg! zv2j0;48?)7!zjwIEmYd9mTo6&9S)IGqO9jjw-v)dq*XUur=Nj_*7SNoq8MageL`!0 zvh=ahxC!Zp)kZZU0?{*yOkC1cD$Ycwrn!BkS6oW_jJcl4!AzQ4A*QX05lbN2!U4Fd z=-qF@_K4l1bn6V*o*T-okqm#pPB+? z{(?uujG%lulY0g%vS13?ZExpbCw;v|ZPVT!z-7_e`l*Z%Q}ihmEkjcw)QY*k5@?3z zgSF{yM+-+$;8+kBO9(v^)9~_Wh64SDZUE=kgiD%|+x$8vZb$D!$mAfnCLfV2pPBka zXsh$GcwRb!mARyeN5ckNa}F3e?TU=1Q5kc0lBQyCI8#`ON-V31H9%9|#x_cZEj~tG zAH2g0*bA=kBxYBc2!ebgIWLGFNJd8Rn9iJ;lFOm{NFZp346wiUsI0G;DPY={^i4cI zI@8<-nmOwDp32#z_uHhSC;IU_M3&tvexDsqgxF3h`}BkkEGDu!mx;D(`bC>Q4ahLH z&4+doE0`V5H80hmcXz>?vI+q*w&HWnTiQ#4-y~r|M7$m)BxS&Go6kv90$D00N-P3< zz4?s;&W$~kK64y%dKg*grOr|DLA{}Ltu%&o_i1DoDsfWT4zh+23WO)N;n2cKWIDmi zUbup8~!V0J%e5xsHP@-#daiW)*n9C+tON1&Rc~%Smt}T>mS- z?vjE;;;Zfhe{&Kz#E3o9Md^CLGSqueKlR4g?6Ad0d{W}dC@;3A&ex~wqAx^0=O+j8 zoSH?vieTcMugR+RL8b$fjsF5|>nv% zxEn^)8#(2^009s{*V&13z&H9 z=*@0}=T0=^)#^QZHrcEYR>9P=P#Zqx%0ZpZzE}04u)l#zd(QQw8PWQoedN2vehh{S zbg_5OM_Va2DOu)11^5`q*9J1I%fVlMa)DlWpWt-{B_+(zU#IJ&lz_?0pGne~AOl^; zDN_$LN%cyYbPfu@dz@t77=x}Gh-#|y`G`(vf%8`+8erGxC=cKT}~!RUv|^lX+J+VF^7FRJIUc*hvsNK$Y+Yr z=`FWwRA)%e9qe-$9`q;_)uzR3ww`gPN>&PI!A9s(sb}Xso%|H9RZ!zfm+0VSyccH+ z!K)XJRQMZjRyZO+;} z6#GxzQqxEQ{VY#pc%R3A9DSYV;(2jMiErqwYZM zTvm6f1&%lib=g>dzUEcF&^HkmAB?!3nf&FV%`$Nk#7C}L zgxtM7h-S1Omi*i>+54-v(JIqg>Qs8ss2T9EUAi#=E!HnONh1p%KTxh! z_o^5o|N2P;7Y{YgQ{>@=pD>_0YAqLy^#qgyCnmqA;4CiV%p5n_9-a<=x&XtMTA>0~ zfhmX`Hq#5mOPMxA{%T|-)*AEyAjfSv=}R4)-(V>*;d=l+7kj~rRf*Fj*fi?8@aC<8 zUFq_9HFaZ`*{g>PxSg7!JS{SkGcbNNwW$PWae-szqRcd*L+Xe$g#Wj~c{cr$J$g#||a$w_zoQDn}38gsA#hiNTz=exy zcJRYD#5Uxrr&WOn$J(nI+2boL5fAJx4Ij&cDxxvtKC3Bddzv=&DpI2-jkw64qgORN zc$m=nL3+khHT^M(vnTp7!3L%JRAUn-odw!^%RaNL=Nyy!yX+9nm_kU44x%7X=c$S& zY%7e`HA56^;uSA2O1_HM2n{Z$Lt+Yk?86qO;A!Kw4Y8k8^q(AT^;FV!psmj0DiAl( z7Wo#b>?Qu9`+@MMN!nFQk}1xx7$rwbLOe)A#V5ua@a4mvHR0|tG(2Mm zdQ!tsw~%b}t<$!DA`IpY>xEnx663d%D%!2xEpv}kPOx>VQ57w18LH3fvxvEZ6NJG| z3M+unT*e<;5YKrZ0!<7G>3LqNpoyl6K&`|$8+L+Lz+oL|6-I439VQiuy$)BndftMp z8m#Ee2SvW!;v+kt@%*FSGpJ1eWHiuc2+ixo^V&hGh6*I&vdI+B-&Henmq^IiscUY2 z!$?vj{IJb5QjZb!HA~n%P54RpWYMrRTCGl~H`_VAj7WulF;G)6Ed=rdCG~z zxs?L3y*5#mq+|(wzmfLQn#I2y)XUS-;RT zxKe2?d;DaKx=Hywz1Q>vfB~a#UP7n(G+YA*+Y?)Ca-f%GG~%2P>nF2>aI@Ly4y5nX zsinVFN8qb6(g_#}_@c3TP&_0ywbf0t%zTBtEJU{5Z(O_?;J&pr1jF_~`6*aT4>zFNJ%Y8>&WmbBO%?!Un`jw`rG}8sB%ohe6 zbBev?3Gr@gmI&03t)mlNf*Ok<|8Nj#;T2^KY=TApTsc$5@sZ*4i-7Q_+>Zk1#+_#} z^HERFrc#S8-!*t!&f1uP#RiT8N-f?lvJ9cGFk5nz)u?FE@Ml(i%1=EYb01v`KS;q&H)QEwZ|;4l-{Y0H_h7?d#(eWX zjsKRi<`y2Dlg#PQy7^3|_o1t7p*E?=Cc*RWK4hlY4mcQQCONBp5_(bE%lJBSB{|lC zx=o==x?WSWRJJS8py0i(0Joe<@fqF`m;6thPkWMwFNh3mJ3J%`%_Bd^usic|O36xC zWUmCdlyVuO`0&xIiQ3T*K;Tc2S@<7#w8ZbfA#b0qf!}1*j}r!M?jqr!RUzcYJEsFD znO#>H6gr2T;V6MJc>HzgQ`r^KVIX}?+>*GU@PMMc()cCHr@~kaX>6+)LQ#_opFBk! z`CMpGYdf3?F8yh-JT3Pli<~sLJ>oBn>WcOgZ=-h%C#9B1!E-b=Uc8nJL-qVDp``D2 zWg6{sNa{X2-Oc|jmZI|=4Y{?}6P%Hel5@@ogSH}rCmnq_V=_&ZxI_`VVr}Un9k^=)>b%#rc`Pr6D!se2|f9-X&6=t5!Sl0V+;$Re8Au!aFETzne2n z1q6BMfq<&}ER4R)ZVCjQ;XDJuYnIQ|XiLM!s=}oK;m&>Q)TOve#(n?B#LBVFS_f zq})=lXaLeyI0b+YnDZGx;5H0m^!!jH6565`;nIu&G8J%MDbwE?WP z!nHFz%Y)7hjmZ=9Z?aCnKspZtE&u@Il~OYRU~`TD6x2KbTL>D`7is52yBL9$RG?P1 zuhZSR?v&1yWA@B?AZ4a;%7$*-eu~eFzPECEcejKhu@W!ubDh;dS9jf;izoCY3qfUr zwI|?#@o%(g2>^&Z(zv?-0dRns$y^2^oX7UprlYNyt*V))9(mfa{dljo+^4>b*OXX| z^-~H@cIZe6LVduVdQ)8@Ed~uO2`vPLiE@xn8Um#uO6CpXV+TU(4FDzDrvVM|0i<|W zF}-qIJPpOx1vX|r=Lan? zWrk@FJ8A{nnrR1hN4_FCgod}IN~(tGYwSL$D&)Ym$2NgSYVIj2!2$o`xy@=GP%-7j zh5SYn%dfUJn+R6>EKZcx#ib#Q}#owtZNV&s)&e&)QlB_KmssY0AFq7Dlh;GkuRPVhCz^b)q3{DRlE8|=TZPo zjln9~$nKn}%npe#$-SGGq< zuA1#U)^I;K$nc~9=wgq=WVCWvmDju>KJc|-e=?i-{q}+ zD1<_NO-EnM4Z4oGmrXaq7nYJB{SdgV+kM*b*87Z9)u;in_|j{tqqK=w&Yf31F3RhW|d`J?28 zOzzY-EKi?fMX2~3`M`a~8tFH7hpGEEckig`$ut6x{4$CjmxTEYLz!c|rS`yQlM!OkS!6 z&%Jn77(OTL^6+ElHr=L9^SGs%!Je4&hbPIXnYpF!3rD7|?A`3b#orbzN1Mn|MoHBK zmy|%Rmwkyt3vhW@Gbf`MDjIzZ!x#Q^IY75krD!(x6H2z!YaMT9+bAa~Hqgp}MFEu}*)km1lIMv5^2`;0Ce`;wbZ+u*0)9?M@DS6da ziCz^2)#-|G#o@8N@|2gg^0fAptaG?I32}D?yUmhaw^b(y@lyqsD~aVHo(BEUZ^i=G z-$0`d=?p#@8+fu-dM4{jdA^t-EY5a<g3?d=X5U1J@mfoh>gdfGr?3Wv7)4k*m^w$YcgyNw*4$~V*)k)dyrF@Af1FvkaL zXdj}n>MO(=qk^{%xe%e~v%yV$em;1(tjBFtFwY{3s3KnlfmoHTB5mh|wA*Cxa3u@IbHZ9TLnZcjP1#j%N|pQpwTVS ziJS|JT;-W#!qsuaXBZUf0%J@tcbEtK7&%X{mp9-T1sFw=srhn=xbWsUgr?rr*G*J+ zJ+ICq8#Le0)HC6H9aLuSiDbt->LD0Lo=r*A!P%Y#yXy~SogvVAYW$KBTp12+n&<4#;QY@G@*kGtLj_WBe`8Z(W&F@~ z{zWu2Ys?PTq5VKFC?c$8dU-#66kE~rTzA2m0!xI;e_r;PzLk1hcqj7X3FC0wl}PS% zm;62UruR`239S1~AbJoCzO1m1OPA_f4W}}{Olw?J74}y?k>3517c&|gXUV|zFumJZ z_}$U7lIDlcdE<*DyF>3zA*>jv@|3dW(e2D&wCs2;>@-q30r$ze_20wn_%TV0-wxZ~pfqPPKfwjl{ zNa?KjDx3l@1`|?gd+eMRS3Wf)2K$k7?Pdw@n~bp#+(Rrk^$V!{N4s7xx3@t z93hkt&y0gNG3f_)eLq0vFN+AdiAHUp@S?DNtd>Z9)s-!H2+b79fdpwkWz|1=$g+s7 z=Lm4FU|y3|0>h2FOz+Y{;n?LJ+khC+03K#5B&lCoP&I#+wAH5MXX);nR!@=v^% zgL;ny(*`YTtm=CGcfM9MuNXY$bUxZRQf3fQ<+0x4Cz_<9aTwD9y&6!RAjGdk%U>e3 z!7|1p1AE9NTMA2Z>X2crMo8O0@BZo2uqmh}+vv6)B6>H=Qq3E@d6`G98%U808lLsRy{2R!zBIcX3N$|2((bsfL1;gNMBtc`9~`L7~ceO(JSh9udrT(pD}Y z4d5R;@;j~vJF8mMu!rSDzf?0+8N?cWcG8=j{HamY-8I`jMPAIY1-+C+NtUi!$=!UPGqz1PuMvpU0TOsKk2{4{h%=R}_0AmL5> z$!9OLQ*@D15|?0T@Dr1tE^=Dc{Nrc;rRLEw6L6XRg%dSq+gh=+OT)B0j9EGelj z2gNN~OnwmRrAzP@t%)y{fCme-oY;YgDIzlWfD!;3CarFr6x3Z`ueYeG>3Xn$`@Hgz z=LI0YH#YiwD{NfI?h7Ujl-E%*L;_-J5uOGg?W~`fRRF>wE*(rJhHKv5v!P|1^F}U} zbYHFp6C7Y26BpSmY0Xg=dqIMJ)hzKUqR=zg1Uw~-#--Jg;$;ap!4G1rsmgMxXAUL~ zQYtEqBcjmH#>%e$RRsS|25bZX4FK>-2Z@3A09?+^#EwR7HG!!B8UTP%M5J+^!bAwC zGw-8$W?vd_SW5If1WFAlwejJZz=Flhu?%2K`7)ly>v21(gEhbh;yOXYz>&;D6vsZ- z%G7jkOolgZdknpW0eA|J<~Aw&Yz@E`iKIu_Yw@KF)_FK4Q^L2%r&?ar7Lec_^wq&v z$jDUhTAOVSkJ7_Vn7I(B^P4gj7k}A0v?*Jk(ovmpuh)EpQ&O>MPP^zvXilA0M054& z@gU8|IC@PLuoXh5XZTA_pNh5Q7oM}~KYNA?lL}e5As@n41U*Ki_CSS$1;LpJgom%s zNiOA+Eb#5(stw%k96dVXX;55i$bOH}ljcmK)`_o0^@omM@LbwqJFJ)srzOPk%$dyQ za2MS_wUI0`7WjE<%nK357caqjyo|tpFhlt4qC82+5h&IFQFrz!X3r-~^XB(^0jw|9}G}I;-J!=Vj zJqEkBF|Y1JFznYMh`O^J@_r5@%R=Iy=t;v?HqDgVn~;wzJ0O3s(;4oAGMh zztEo;!|q*-ja#eL8G$qf1Rbtb7MbNQR|`s#Aq1r<*FhtD!>G}mHO_(bmcOjA*465Tl3ZL1<01_5IS)wR)nuQ<$%i^iDATzYrJ>9OyUM8TW(UB-u z?5`l!>H>h{Sj{LW+zD+N<8KCLYtgdhnF0-2;F?92XbG?8ULNwR!Dkpsp0OHteloGm z=6%2-I%!6oDVZ3g@6As@p+q@@yM=D(;qy_cBB@#QM20e`#}yXwVMgv?!ROMJ$6bR> z9V+oJELlepgL?U!H!~cctUf0&qFhHJZ%P0;Z0qskCvxmtZ^Wx_F0L>Zeoq!ZOB5&NuCD8s&p+ouk*dav|C-G8zq0`>m>E zQ6PG3U#f(jtoA^pB)|^_P)rC5@D#ZIGO87TnZZ>Ka7hLbUOR@Po44E!K#*m~IJ)Y+ zOxP923V}=oJa4H#NL4?7ADDG6X_!)~UiADCYKbTm0p*njZV%Mo&*TP(gwcvY!9*O4{sWSi&A$A`5#I29xqJQ6^D-#(tZRa=p+!n! z{)#4nF|z)AjSV^k2BlILn{5e+R-wDLm=YuL(?{eK4|tb44&b2GN9&PZGd;yiU%soUJpEO=nmJ=7)0-tTH6;_3ja!or z{S#Y9&V8SayCcf%Dx3#^-*!u^s-EpeCT%CGJ*45^HSB}XYy+{e1&s$M^a0pi|EPwl zqmUKQB))yx>{5H&G=(=-Sn}K%kIY5A#%fB3M>W}0Q)LW0Q$&{ZN;^;vg-Fp?(OcyI z0ark%zZSj%6cTVa@Hq|~zySdcoWqCt7@rLPBmI*V8Il5N7_ua>lW55di$@ca3GNh< zZc}9R$v$dRm5szKF2&`C)f|xAT}H8(lV)vDVEZkqoz|L z(ivRGV%%7EcI-?*#IPB&C9#{u%_mL$_(zdS^ZrE>oh;q(vW|m)eeak2h>4ccGUPI| zs`!k#$tt}3%$%8kOxA{DjqXitm^8zP+hPgAYTmiNa?Iq(Q)65kk9WZ5CQW#3sqnhyu-025`t}*CP zyYZVk9kK(FYaX(yRjse6E)$F2vfY2}GAznjX!qRz)DRZlx-GCAQ^qr`8D6@sl?DEI z%BN24x8ice67z*w6}!~$F(Ze7OJd=@U=TGz#iC7d0tCxYX}|@c@;XZ%1VUzD_FMUqWC5Rg4HL(5{lz# z@cOk?8RN&lFP~)a%273(-baQWyS6$Rc1s-RiS_8NTOG=&wwviFt6}1CFvU4Cq|n1# z=4DPEnUj{v()#3a+^mT4 zeZmcLn7d}Yz(vt7LhMrmmxFHS?3hTTfn++U4 zBf*9TF%4=%hto~p#TRQV;d`IO9EK1L3m z{J<0+B}r!*FCKnw051q(4=T&yq084fLbX5#al*=aj15sPO*1M%|Xvor8?;swt$avlw^{#mX1Yq6M2*6@Dt# z=h51|W}clgxU?92u_KeiMArOK;F#?>waDM<9;u#`C|!FH+`f-84_z)*aRi-O>gQ_y zFRYjXEP`*I%?QtmdfKpQpN^{n&N~*|ZDGUp5@0m7cx|6sYB|&N?=*%1X<*4N?b0FX zRCNNw^oI6y^uQouha~he?O)V~8KLB7y9$N?A$JWgP9SC}XoOi;O}U%Y!l_o@29i&Q z6}XwOip+{^hxAu?-`~P}&5-u~GsX<_U4=^eJsOePqX!bUNjFCKUf+;s8;#ICyunE; za9e{d8fwPBf8G0|Lp0D9vFoSP6QDqkJd?ln2J{Ns2>SgfYF6!Sfs4n8kjjQ?-e?&# zJ#1P}N|Pn)nt>q+Pn`gOsO9*T?2!HPAgJqvj2S}|g2?Mosc&m@l{A)o-`Y)lHeoS0 ziZrArO(K^cS?lt$kf*)rYm0ToAq+or=z7axIwvDIY@ja9#I2hT(i^#k<)NgH?!e^J zkgMb8HMi%Io`W8souPy(2hQ7Co5r|FkA!YT+5aUmvzBY*eiK@A5qJYeJ8@acW{&R~ zmp|>%!EOiR9-|?S1_u)uFASLNQ{ig!y5IL2&+1|L%|XwUP(k3hJE-0v5$F44VP!(aAVECl4(O-aMO1M@Q<0kGD&`YjPFN+YRcak zJ*+6+{b6PL&nUI!*Mqjena*M_G32<74x5IN3YdLm za9tIT;Bi#BbCqFTN4=p!Vn<}y3=Gs^?H30>lwvcXNM6@xJEbJKsj0o?EMx>I9ilif z%IFykN<2*nHPk>L+Z}Prmpl22a$=17I%AUkA0BQHlE}t+*f+VekYDNBe#rU+d4lHv zkhhcV?i;v*DHGVxJv(vy0R#)`@v0|PXPN-6MS~!?tgMaT1+gTUu!U_yV}tL#FArw0 z_3aPVw5s|(=x}aIRjC$rD3!#E%^20u0bqV5Y7Nxl&H1xby~HvdI_a@?SebKtifvcP zerl5SjqZrJgFreo#tiJxp153Hr~~3V=FFImkIcXGJFM;xIy~_ayx_>jKJ`~Na|Uw| z2o(dd6ZSC|!oAib1hIi$k8a_5+F-)TcUUk66^=AgIZkQ1H9rSg?aASYGkbP)vNo?L z2L=75+t{2))Zj)Vy(l4cgGk7XVY`#x1^jq~StjN>pVZ~hGK(*B@Bu&b1EC2CtDAo= z-YV4~%_25?IHq-4h`aUpswqeOiG#hXbniaaxjDDjk-;betlThW1v3(E-n?Q3n79=N zfL95tbmERnp?3Rf&CN%D9F#{iauErzym}VC&agD_(1~g!i!#G+F@6PGt8~NWI;$m< zz2PxK$nF<@Rp}hq*1}+@@4uwTk|0D^NJY^TFci^xn!}_(qbZy9priKar5njuBt!rJ zy8+Dz2z|m(NITDC8}Z%a`P7_`yk$b7JYS@2tRP(1PY#pAdqa7{pHL9wT;2Jv9)Z!} z!2Ii@T7rN-!PGiM^u@2x{Z|jh! ziV9DJ{H~$9>cOQHc;AURg_rym0sjTF9UibtXVcUgButGt)K267*GoRtm@!YZm9>Kv z5GqRQGL}vR)(h(=<&2U(5HSTf9ri?sfeydHjs)>w7e7ZNy_CynV3bUv8AJep%>gw2 z2zF2@zj+AS^`J{ipyEFmkAlC25cNU-L&gIa000mN007`S000000002WmZD!~z9bmK zgt%9jm_FZ0XteP+xEQ*`GK9lHI_(U>Z=ith9S4+_sBIWC42Xbxg! zWw|8$sIBFgZlSb}dV?i8XUvdW#buw1Xzr~F8ll>5HuMyjSTnqSZnE!$_Bq%Xd zz2Q`-gCeAL-V}sBm+g(Et)Uc`!($t5=~6h2B;q7_-%^ZCR=CYq`-x70 z*^}|ojXCs*U{B_ap#PS+>_+mxM2mjyccCV!8d85?-to<+wft*G(Z5|}o(ar#2sNgY zyvAT&HQ1x*MPLL<10xRlmT$$Rfl57W0k+4Uk%RdSW$(<8U^2&)!h(f=r=9i%>|G*n z9qqr5m7l${b9AKJLbq|J>oI2fbJgp9y$ zM`A~qC1{Ib{u@mUfd>F1!^4kf1{fV0OwNI7)rI9g__EmF`(SH@Gm3tdte}8N*5S#g z7^{QP=Mlic&z53D@xforIEkI8B8!W@n9UDsO4GVw#IzSl<45%(U5Bt&p5?^Yw}}wA zDRZ{!QF=@X8%zn&=QQis(-Hb@<+E;hnZcueXCo5yN zRq8)V-X@c~R$(^lDmQ*k)P#Mh08zpI44TO6W|Tjc@bL}1s*T~i?bS$oK%BEdxb^}> zKcfsk;4xIduS>~>*3Ff~FszPklu|#CND_)o6*>E&Hfb4=sVcH$WxJicKH*o)1MJoA z(jt9PMJ$(`Hk_(=Nc9jg$Trft>{j-4EJ)_ik97D3kOnI8VI4y4ikSdn7$Ud7Rf>ri ztfJR|N44KTD~3u+3H{zlCKhoNsbZe+--p|Yo(weMFeRP*cUBV%SXrbkLo&Lw*w_V+ zM|6 zpxuWN%iqurQM1Qf-7lR^1gpyG8ffY2b$#A~ub8($t7*WcW}+&|mvA@xLDjKZXt^sl zO?hR!6G>z4*lc3{dQoDXbqpkOUaOtQ47{UI~S3-4QW(eujpBg7*qqdK~=t@fAOht7nA_B697m-833H1 z3IG6L0NQv4DgYNK04UZp000mW0ssI2G$UX&004b(yW91;rQ>zH7N^zHVfxsKy_0eZ9T+YPU47EM+j3*hUeEW{QO|0|Wt~K@eJc z<*_y(Bmlr4YE=-3AQpcNm;eC)8JV!60{~F~rzVZE*(Jp!5=GBQSn){`H0s3KPZL{8 z0e9UTqmWI#_d;%M+wN{w2Hb4-J6$%m)V?_!Ms00+a!T9UDSmli*A}gOe6%XAR=!Tb z9YsMoGP%P6D3D0p9I|PWKsW#ZW(3S=3;^d1`JQg?+wNVvnJu=q5M8&L?q0jw?RVF% zEn5`Ux9@S(Q8JK#Ig&^SVkt2)QGf^t5{*I;0VId{5#a~;AL2of=?8#4 zeSelr1Oq$&B?}V;j}danNe@Vc0rk&7EQR`n6l9JI`ox8fISPg_dP<~#DoSBwVyQWw zh9;{^LWh(WDNSsU|bTF+8NNvq5}^elRTwTX`PMHVTdHk zdz|d+X;g&Fb~GtDRn;miNLgRlmAE*5`urz(`$C&vChH}UjgkvtktxWPkI= zXa4!G@gkR|7iXK!iEfXXm7x%x)nd!-_4jkvnMQo(1m1hPlqyURcBTQbrXb$Rm*E_RSbHve$x8Hc1dK64AxdG z5+~@w#BdUzMuC+buoF7^+v&dqk+@oEGGFS{_ya?KpY(kCH6`#W$HYBGPE@+sDsDO& zB?vM#Kun^1bak(%vxVo39TCzl(=&NPq_7#!)HKG<>e!b$TTf1qOPY)kyIQtkiC3Il zsMHhES@H)uryGnO;OapY<8F0hW2n%GwVu;Xk}Qg28ppLZQj8BOQ(E0d$r zR&*WvCS`{);FiUY-3NtnY8%hTGdc98DXLD(F}*CC^wy#6ElB~#s07RuolH^bICR7SrQk_<$^js*X;hw0m z&3toUHC)Kg+6y+Q>5r@v6LK2Oib}F3nDsfYgNSlhP7ECJRclRMnORl>oAe z)tAnxxuMiycRCV~WHiI7P(Cfj{SmYk7sDeC=eDY{|H;?Bg(N5|?t<+cW6u}Hd1t!00z zZ|oQ=aF)3g#&;za=IJjT{B%vzg4dqN#+TyhtvO=i4VAwy&y}2s8{(yCk`}?ROMW0P z@cH?ZBhfd~)Fc~zrBAA#8(Yl%wXSTq?IWVfU9OQ1ZUHoHGSY73+>#y;pPYj)XnPJD zjrWQ)Kj5|zCh!!hAprcSe>OY;qG`}AI@y{)X%&#I7=jIPCuW3zV6|g>{}cLXgLI;$ z_HR0YHCNNbW*tlPiPll*RBAM41gsyZTPPqq;3P}^08SfWAq*Afoea(wGBem=@P`S^ z&brVMB2*KI_X7)yZ)DH*ogzdk;Ie>*o209q)!y+!@ zl5Z%1LycpA9zRVL9YL)tb|(ZI_Op>J(o6Yg^)3b8_5C}%tKAR&0pdf-VqO)XcO>oX zsetukIqivRnSoJMvKjUV1T3wsW62jI9og_$-zWqeF0;l*YT;JT02sTRer3}#TzSWI zK|#aBrxH3RVgQf8;h(^_L}fRM=VlpN$HihLUf-}XIOp>#?sLw7$vm*Nq~9O&0id1g4gLCHu{J-cz4vZxjxXaxs2Uu`j6TTT#(ypN;VDmG7RAq~vT9 zdk*4?>sakGUR}Y~tmHFDhQ(h*s{$L}j?g=2nk0=PbYUC#1wZlee-q3qYwOBBC~=qs zRhk~N_&7w7u#<$gIwK;twpvAh`|+Qg^0Wu9hTTb&Y>*D8^yml^FcYH1yDc&JzGWF@E?1g_>i?As1M(v}E{BwK)NZu^v&GP}axG4~>mgZ|#qXOY!DLf>o}y%TI*mvj zs;;gRlp(SYGllv|ZTNC_vr!2*Msvoy zomLUsPRh0B*t?HF)3oEs!@}L@a=Hf0($2?Qml?oi&X(y!?c^m2#5@lkjGLKP8vl>+ ziGyA=vs>Ed`{MhqXWR5$(2`k@t(>Zy@`6&1aP4~6kY`DS?Wk`etBTCco!%!+(@L_2 z;dA$~u$y)vvlrgmycfH2n-+p*9Pb$o@oK6-FI^rxt*)(ySZ|Tk3YY3k6Ipw*tzicf z1NJsxDr_~`{_j`13boWQCqf|wum>_|OT&+#=haCj?hX-Jb>n+w;+RSyG$+LqV6lXc zW77o3+rMCNeiFIOvDcK>LTB$~+^I4L8`9>-{O}rpn%L{%XZZ30y8uze6D)jEH;}8) zNWS?ZaR3KU0WG@Xbl4NzAAL{6V~0b6kV84-Lk^hl$Xd(z=N5>CFqc8Lt@;61X20zA z24)yh<=Z!9z_bjuZ&9Txm+IA*`kw*=K2UvtxBWL>*wvAE-^>B$#}Q(}y!;xJ6an>zjQ9w6Kc?kx1%acIvUYc%Hi`g-Aw_Zh@$*oG#Si#nM9Z!5 z)u`(o1`{|D)DL-?02R?htoVb!op^hB`9bWH0F48Rn)0xp6#>LYFx9AlaayNX`2yTr zCd+3^MZo#-<97o14=dA(D%e~TInzfFZz4RAgc{Y$6UU3RO;{|nA_DjiE?LQjP_)34 zI!)gs*N=Q8ak?8his_vWgBuMUD%pU=Rh~^PoSi?}?(%z%3Fw`gNZ0p&sw$o5ojzhF zl-q`;YlvyAtK>hUfs`wXMzm>luSyVC5=nJkQuYy9&w~*IJIz_|D1v!%3NtVAy1Ol=q6ZJGg0@pup$^2y>3pxN!&%HM!S@Av^%pyuXkW)HvvT4vRzFm2T4iPT{07haIG2e)}F`r z^!q&hKXsUw)GLc)LS8|!zRn$o2(yv1n65m3v|O~zemXsWBR3N~Ao=r+3;+*GO!a4) z-n-mx$Zpl~Yhj15K1@d=RlRN(6i5^exSxq@zVdWTr1ZRUVI+BHBQ@73 zwl*MNp~vX3X(g1bTw=0!3@#{X2A;I#tueri0V3m?=$@LJVLykmZ?*<~ z5^!i8Hig}EakkB{3E6;B93F9EA~v5!-*(wkKM+3PLiJ6yJU`c=YvF9;{pP||W~5A} zX4j&d@O;YmJ2&5^UP5(omeC%%fw#_y=G5*K=ZF&B&w1ftdr z-Eg1%j{uvT`4M5;v-XPP2fagdagJ`0PB91Jo*}~;SiAB!#C`z9J24;b%ZJ>2ju(mQ zS$Kyi1@Zcan&B^QWLGIBGJk){k!oxgh>2AWmHR*=P!a3Ss0lFdjy^ljI?ZVB7e>E1 zQCXh#c9V?g2V~H$-W?eKfLbcocnWQL(2g}A^l5_YkaFQUZP4j#=p;*#xxF7qi}Yc3 z3kHet;94zG7Aj^<;v-RK88Ntcw?Bl20*-?qwjnxpypnTU zZw<-<*Rv^%GzkQ%p8MiSN?7x#9mD?7U%QWV>&!*?AQ9J(=@*SLkKG{=2n`tF-ClBK zgBsGXoELbF4$8wUfGgo7SfF0|qsZ}-7d&4Ws~?f%Tub>-qz})}K;x#O(oW6whaU~K^UOE@Q#fs;?xy=WHR2*%j zW?p8kN*7Ai>|(0hd)5wi%N4#UrUPrOmbb2Wtyv%MYc;%41?1CmzHj4%hLFjKW231V zT}Vucl82SYEhetcW319nkYGDyjM;kTrf-=wU-x0mlQUxio-rAWMvRz#9#j2{>hMhQ zV)b`S+cQ^-XM!~jwCHRQ-J}gk#;b7Ce$S-tEMvvnRq3FZ?OwbaFF%t)I^6-MJb#Mu z-Gw`reLcy9pH26Y^-e7WrL%x+>ADH1rFwAZ73c>ltiNmacUCay7>M+ShiD{ikwSqA z*x6FjQWX;O2v=T+_Cf{|8tH~lvu#o_Sp%Ih8-2idj8x0kW2X?>9@1}*lbnks9()m+ zXQ2ft8sAb~luEe9O9*Am_#kT?0{SA63uH!)GWI0{=AsMXPv+Q0XT&}l0B&TOjkE@f z>3teI+f1FTF6mMsCp)fa#9tHP)9KBb(Ef} zg`!k3>U5)+nNmDzo83I>(BJl>fbH^8C6<2pq6R{V4uz9=DXf8|Iz_^Yn7>NhH9Ne~2#g!wX(}&&ShDMNSzj+})qfoNb2E8G`#eHKbXMdjl4;!sh&F!e`Kf{{Jyy-FiT6bTr4qb^Xb zLBZXksuZ;D2D?;~Tu_Q=YzaZpl68=5T1C5=aiGuI6=hM-fn4*FXh$q)poU>w?%u0I zS+R#`reTdEZneqmlUDLMlhEg7?*J#FN;@7R+IgR4)DWR-#~eTSc|=%~ZY@X9cS(*D zj+HrpUGLxsy(_Ffc~8_3*#%W#%ZZX}~lBb`HJ^yn;DC$XOq-8k6Y#<4sXHr1xv=5J)$A~^-?%3iH{Ba+T`4bts z!`#NiYg#h#x$m-Ytoeta{~=G$xBTSm<<#Nxi`?KqPjcKB7Y~#VftkN~FyR!~oSc`! z@WNhP87EWxuHT;FulUV*A@luX|7FV!`S6c732SfcH@x>RWVw8k7{~Q{r~PE>xN>3t zi-xcLgMReh?;QQ(8J9fzCtv#mv;Oh&%YI{|94;}*({DpI_ z!InWtqTkOwinlQ4kKB9bWBlg#r+#qbW_*wXFy`N!dAgzCXFp5Yl>4VY*)aci-0IIf zN*#U|3;jCw_C8-nxC(!i+vvCyKjhl<_!|qqzJmO44@Au8-)lS=STJV1_ES>T6Pf3O za^~;27huAv*8LR|d6jX%XCHxz4E_zQ|MJ4$U$F3t0DgmC{p{aE?=|xfK2Y-S|2XYe z+3$f*>oL4<{%w|L^TVJgFy2mF;}uPw`_G=&0}eX(UJvu1)_wi~^ZF=pMP}I)A6e+h zCGG?>bUE9fa%g{uFPvkT!h9&Zlt4ab#F=5x%PcW+1hI_d#l#A+S%ml*2Rn4Q*C66i<@s`M-~w; zUeb;g6Fztn4`7A>4DbdNK!AQB0HFW?AreHID*)>~d;Ryi>-~P#EZfVLle^YtyRlbF zH?o^G6Ag0>5D~;P_#l2n{4n*=0*D9ukL2N$a0edlqkS3QL#1ts&G??TnpxuPH8dX9 zcrZ8~drDem0s?3sY-qcy7bNzI^bQ=c&hECn%?|NOT6L<4w{>vL-S%hmUAElq1-Fds z6>vryb=&yjX+QYrt7?HkmMm?{!>%`CJ|k9DcAPJ`!tSv6I&MVn0H>@|D4Uv#JY z8*`8KF>z)G&fphm_nKT+2@kkR(=|dX?lqu%M22s$(9Vs1RmhL$pyu@XKp*_Ujicm+ z-nh~uopLuZ@(g~b1RE1J8ybk48hJMSYzRLlx4iNY_%#r0NZ7y55H~gQZ1~s^{YW># z@(}nn5Nu4?2#XnRYvkDQupv8=>ydWMH)Nz8&DBXnDJLVSoF`Cd5vLFojG(`NAt*sj zixP6iIEA2y1cf0e3PDi_z>_SJ@5-4QaaKv#$Q>f~`A32gG)KroPSS{$XpBxFC?dp` ze~eBcQ5^v?qeR0|QGObNnjPJIvmataG3&IP(v6fXE8jy#mPAbw5|PA3fk!J5QJU!_ zWU2FH3XS3vf+7$Ug`h(OO%x&krZeHSye2+Pk9nfm5-~Dcl_e`98M#PS*^@mIKO&6C zITA3U)|oT&60`Z_@e%!PN$xhT9FdjJY!QrXlcAa0Gdyyiwl3Z+JIM8?BAmhVJ~rQx1Ux z;NjKAwUDl4rQkWwJgpRdKXPdhxrsG9uJvM=>b;v#Hj9&{+aBPNi+1)+-!7tTc{xTt zQ~z(W>r@qQL9{ir9^LVbfIEf0#-Y8%E_s3%IpPiug|%)s7xJ%{zCricCl7hZ8O%Sw zJHIiT@yR}T(wVCSHtIdw#9qxD#yqa)v54(1qQ>|IS6s1p(K~8n_-*PWRR@+S*ryOP{mGNy#tyW;l-o$J8stskU@W4Nu->B|dqqi@-JG=2~UAxU+ zX!>(6gI*iog6U=pJGs~Kd-|T0#Icv~{rj^jyMFZ<@BWzDn&O%}>Dk)}wcz3QuWr$& z@{5MF1>br^0`nSvhm6A0qrf4CQ+xS;`45K39+7%7|2EMP4hydxhoK%)NP^QTq4%9n z28;gc*~H#VCoyQ_51-h-am9jwtQ_l@Yyi>eI-liLIbD2shD2xt+OhdwAiLza3UMY0 z*Tilf9y7Mp!I9hS^zq0ScBP3{jnRs?i0-uc>k#C@r5B%f6FHC(!Htn$?@2`JKR}+l zZH>mUjkmRz%6t&LoE$THSupAi-Y=o#8hf}^kqM#k)f(&STMm95ssznhPseCI~sma(`Ob_4qeJD8FLc%?Th)~&F63%Zyr z(j-DI8|8jn>XkkXBUBUcI&O>k(lJOM^njOkUje_+JFPUGerC!JwXF}8O|ISQ#B&mz z$GQyLI`p{^s@HWI{XDNGw4ScaJ5f6*i{3Qq9nf&kp~@1M+k>tghk8(e6qh2bD&~L| z^qsHVqzNxhsV`^*sK{CYQZnqsWdn24IvfUdK^LIHd8c&LgRp3PN9yQ|kPq{@oG#PP zeVJT4gQJI)>N*vC+vb2yV@_Ij8xo6pTJty@xd=T;Bp;OSN`_A}hwVh7q25q$9LQwU zW?G*6C5tcNw9-6ulZj|N7I#P(p-=)`a)RaN(xED#A!&`(jsSOOFht^fC5;5}?Npsj z=PU23F8YLqvml=4Zf z^H2T`oNY6Tm{QLs`9WjnK>MlQ^@hxtlB;*3=LDswuPR_-u_By}*PS~9I|wfaSN?6+ zEPVH~X$$A^1O6#JL}zpOBklhTOX4s?I}_^NF$eqebdu40QJV~$@WG3=RX&U#evmsm zeo#NOF00dESloaf4MjppeWFl{nSt_C;wiJ8>lA}vrcq~h-f9{m;_Y{nq>V>`n67y{ z(;Zf$Cv<7hbtm&3VbjE6-)ZrcIUX!ubb2Hk8ozh28f4S}y;;m2#pstnc2IiK>KscM zrKJ9vOlykS(C6beOPq~shok+G;-zP+X36W;-QA8pN?#$ad|ytE-;9YTc?`%4KOPUD;yn z-GN{R>!JabKV{P2(4(fqgO@W)u&KD_=tGwE@dLN-n-JVb)c_<#l0s~j=pyRg6Er$- zLqxf~Ysq8>wX<|Hxsl@`o*aNcnH?Ha$xdjvoH_?sGS^?aq%B z`W_@$oyav-T|rs`QQ`Jsv(-wNWQ9Sc_J^37oi%?NC?-f0&nrl;Q1?e^^DbNXOp0hdEs9?45`8l-X0%C{5Zs zR~RQI?kvPrxjs@${Im;g>7is{19b*U8^YlN=8Gr_B9GSe$}ePshf`!b zzR2vGtM;~KG2vm4I{<`*pqKD-;oaU}*L;ep1$*~PwhK^E+BvMV*d@-v?pRZVGDu`) zA)W`DVj%Ggh3?!>Wz8r+wYevrY86_zZ&%Y-?`$=2M}}g(%qRBI?ryAZu^+1IUM=S{ zTW-&gdb3o7V+7-dgj}L~?j~9tF#B zoQ7XW5ceX-kdFPEYK&7UK{ZO<G?pQnp}U35=tM>5{AlucddT?fAp$^GACf)h0#wuT6DwPjxU2%4}E| zYFbcfiv46?9cTRvt8L%)&WXfRI@zU=vSrUZ5d}l|B*F-o7$TgIN$rwbY3)gDX>6%( zId6i>hy{snj8+q2VvgeD#XrbodxYE&JxrF^b*C|ASCp++dx-gLBNr}8K`tZAr^DAT z?Dx&1iD`0A>naSa>X>!ewfN@I%C;Wx>@+$n2Z7d7Qia{jDtJf+L4nM3+Yxp?@PljdGrKmg>ebBZ208BGAPsx02-;$J)2 z#Xe(R0Qyl?{VM3`0JX<5SQI>8w1OtNW0?ew*txHC{qjbIG&iu-WLfn##0hT9s*MnZ;0=P}V@8y658@#^ zm$y2kkU}d?^x%`DP#lUX7tkE7_?SVRau~A*Y9H+VfR>?qj>&N3b1N{I?W1j9*oJco z??C3UCw2fU;VQLFrlwkh(9;nR^JUfn8#RDV2CgtG4B*%MtlMIs3}cRhv%otBurZ-j z3m;i{nFB9mxtdUccP!SnT~HX>0m$`TA%N+QEP#et>x~~s#uoW>7Q$E70)+8IO;95> zRjh}*wtQdEiO2YbxJ{rRIu?uZbD+=s1bU~dBwb(qpbm%O#bpy*oU&e7V3xRkMeGHy zm88);b3eFqY(L{MqN=p?>tTbl=8uA7t^=!xigp7LH#s?@H@6L_G!oa(a;MTo@2)pi zB9r_A?cu7&@YgNU_v{|MhN}lk)r$sAVMO_(F|?Ke^-Qox$SU2@#B&6lqI1!`09z8= ze=-9JdqQCC3)?3ym-W(WCpjMcxB)^Iu1^o%5)gjE@Rk)`o>@{yHwyh2D*&62yC!M= zWf39ZS3hgMKLamW=(I&=@jV zseC>1tQlN&#R1i-u@BIjqpFZPIcK?s)&na@N*HI}a)N`nEt6qLl*zE#{duV)28Tre z0Jrgbul52z#l;14q%B!^k5YnBs=P)8fo1ZDpbc{>^&7W~5NC|3g}4C5UULPip&<0j z$lA{lrvXybB6Y8*s#cL z!XKwPEFaV2J@9sr2r(pTJqY8-Euuj}ifJ?;!En&3{$QEWN_*Cn8KF7y0LH6#SQW5z z>Ca|Sg%PxDhJj+AQph>rLyaci-!tw1?7NZ6<^2;NkD7`rQK-oP32wXiNh@y4<_73F zkFf@oJ|GEuMfG}&NKQ=t-%rfUGi`Pc5@!c5LvU?U#Y z8JL>w%Yx}q9(X+QZInZ|uoM)p3Rr-n2B=Xv6>~v{3|L{58O;Z^tz*C4@(IgCg{^_Q zeb_9Q!_(0EHZa)W11+P;Tab@lxnQ;i)mhG%q}QYQ4Cc|42JAkzc7uc-q?0vR_}F7F zr^#C)n{79+?!fMH7x-|1UP&%B-|qFe!k^ZBQ`(aD13|;|t>9rz&WPJEU?H$y95YY5 z^f{lg-35Y2AcCL=QS0l6^Oy70`YD6II{7E75Nbz%Y_@^gHpce;Q8#AC6UWRqS z^Bp=&jkOAfAbz+q&yD|{rQ_NLJ70u2YVr*91C84T;BE)r^Vmy|lP(5$8UAjeUe67D zzOu%H1CJTW4(XZmPP7#WUke6VZ{G4C!DG;NG2CzBKyT{uMwJrP(ETddR7@yyMo$|x z`$_}&mLMi;pHMT(>l{)}{Xo}9sA2_{gZ=tZ6NoTnK1%7w2C_4jn9Yk-@D4I#0B9BD zbqXq~gJq*_z%tuT4CM378#zW0A-86k9!TbnKt8Pz^=1D{B%pv;_8Hlm5qU`sH*x$J z{cQ>P{mM2W(l?THeQI|g04`*`6}%EBaPd*2cl01mB`Q-JsG>Jm8JQNA8|P*q&7WdB z*9eX8(nmcMWN_~ynKpYvnNi|tP=5wgV|tN_lwiT8^%yCbmEoIAWy7-t#|&+?3|?96 z)rG-g11#4uvkoJM=PqMA^$2Ffdp_s}5E%)xrK%r*j~dy%5*yOBG$#b9TP5)IXb^w% zd4Z}t03KExS@uK83W;ZmNj2kEEpUE}3!u{8IjXR4tFZ1qrl=HuPnGF6+%ECsbOh$@ zFS{X_e3`Fc4%}ZdhDcbdJ=)}OXXe~|HK)|Y(LIu@^98Rwjq zEO&ww2X`QqG>k;k&u3J)q`q%4PYLG;8G@dkywL_Egjyn%EWuGjQtGglX3ouX38{u+ z<*FC>=RzLkm44PPJnHo6fxk%lTucuE`TsOyZ^-+B`=9y1pn)gF7v&Vqz@Hh3`=bbE z06`2n~(ndGFHE-`TDsJm&c%*4wdHl%Cv_~m$IrCAxhA) zVkxpADbeLZP?0v9q;+hF3bnaVC?FdmVl5(;EgO__ZZ2XoX<`$qd}fb{8_7$bHMUqNsY+)BDW8TYRLzA_6~+m5HlYeq zW+$3Zuo6T;RMrggd!s>+?-J;D?h9Ch-qKg z;i^(o#GR(D>&Bp3R4B?nt!}BPSE>FlGd5^Fu1#NdsQFu9B+CYK?^G)C_eUB44`nNLh+2AIGkpV?(RF`Yp%u`@UnHu1!N zhLkekBqjbAjw2Yz5}24+DI*Hf?+9-nQDB&98_H6`Z^>=oiL(TrCiHeq=8?OH|1uC~ z^%x`5do3pt1k%{jb~`~yJ5lSo1iiG#+SVrd(jaWRo9jyi!L+}&pH7gc0q}Mcq?+R! zZv=Uo;9F29h_udIzbDAF)!e@)2sGNbp-+%$zqx=-5UM@6^Gy(`Y0MQ}f{~gC-NGj% zwUD}qPl0M6c}a;SYUJ(^O@!dd@I0ZLa73X$ zY4C(&DjcD?&|@C=`=KNtl#MqNF4e#U)WFCW(?UDU?J> zNhFF&qESo|C1O%2iIb8^6qH1wm?TQYq)`$kC6XvSp_{lw!J+x7FXD;b#1m6Q=ab&& z6TgHfCK8Pg4uww%$G?9s{3|~Lru*1^5}OeB-Vn%y1~QUxH2`-9002|tSVLnP5+DWx zP4+|@8uV`1J&>N8e`9wxu-MRy?(!CJ--aDz$GF=~0`8AU+E*(XpV1#mY*w+*Nb$B- zkv=R+@moB3EG%pKY1gmTlFr+2TfdE#uUDh#l`12%swy)XA~?9Bqm`yHsJK>KhN`ND zFs$<%<9-|n2{=X=bZhg?ki!}U1V6YTtQMyU(WDeL6g5&^X=%Z7uBRPPRo`86-%047 zDUycoRo_7DliD=kuBv0G?_OH+&ik93l~WlA&wKCL#c}8J-Fm~!c?tZ)=-HUSpIK*( z009&g0RR9I4Mzb%lw*j(!QL3DjQOf6tGr38*%$8b-$C+G*9DU1&ind7r#V1tuIsFN zBkl7EUH%d?)qHbu*@yc7zed%``ERx7;KMmS21SX(*O1|^U98zy(#r?cNXe5S{srFe z-UILhvR+$=yb=MVJsU_O8?@8BfInXNxYzjwuk+^1mhf)EX4h(HlI5gNUI?S8@8Gw(3WE>eiT8VJ=)DL$|0o zijEGvk*u&AHUf9%j5r0JxNQVh&<`IG5ksd_$dQw~_Q95qSdG&~=W${iKjBxbSg=>3 z^{kKGdj!r)S8@6vy_>E-rfVdwh^L=>dt%gMg^@8@QDBU2tiU&@?on4c)atnf9jPDO z-Ps?buLj#vVL&t$qNdVQ)tmSwU%sCOGuaUT`Y31E6?lpBVl&$5h|@A?7g9xxrBt4 z)P;rS)G(4Pdx75s*5>TFbMjC-EoKzwpIsoQBObRz(w}NS5}#^1QjBVDU6;D1=JT(A z!c#;5RU?uDRr`^hRV7K!s)!_K)ivV;TH22atu09sRE$B1G4OW`9e(XGfGs=Ns(5+y`@u4Ns6kz^;5U)rYS6+-SuaM zCG+cn8I~R2*S+IAi&Z;)txUXF9v+c7$1pYatyiEoYql>|=<*A~Xa6sAoly3lTi=>) z`vvXf?Xl0MiS`P%kNIl=dmn}F zKyhu39+F5=d8lb2|G{nZA?k9r4$VwyaI_mRhbWl2(utSM!=bNQ>Gw?yor0`$=8i}9 zWNDCt80oCCTG_9Ld(ZTs=SdOVyKFz@=P{1Y$vchDg%9w5s#?gzK`|_RSXnw7De5KX zLSyX|Eb5eeRPQ6(N@|uY;sg{=>hZq|b{Cg(*cZz&e<74q(X)psI=C3H4gFj*_72cK zIB7|c0){I8`f?Fn;~#i-g||)1ao&*igeU%|7Y=PHzkf!_mUaY54LANg5w>Yf-*}Jj9W{}U-4y_psf4ipJ{s(}3 zziTSQS0Xy#eoounOqV9W%T!X(^IU`L3lk(oB>O{OE;=T}C^I1&68^(yV?}WSAr&zq zSsB{GM^R7<1PsLFiMb@82mAx$R7+L$A0bPUZZ2eS7{aki8F}iBvgkq`)|X*RlTx`} z?nYKAt;fs3Y#gj+DKJUnm5)r8C0d!Boyh?@+q)Ua;b+NZDPa~6zhcLT+@vwTjs#m0 zuo>3}GB_?@lA#(Wp~MbSdRg0rOwmpn50wn50$R?J=9bhct#@$6GpRbQZ=BK`nbqo) zM4FVh03T$ICLi&^LGKb{B6i}R8CPTy5Fa5{7+$p>^h(72LEkHj^WuCcCI`R#yA zed&d7lLRN|wN(G6cA3&s*C04EFKcb)n=F~cn%Sc^bWzkfin!~phnx8RfEiTP%DOPx z{s#oOt}5rByn8WrfAckvPEu~;1J|PXGoU3g_$}{jw;ky5UI?W5)mT&sVZJ&SDpY$I zWUx~T4-keI_llDDm@l)u*-xqaJJc5GUBRo<1sb-_*F0)3aUY$;4_m+W$bi5oxQ14f z{yuJO6fFnfpBL3e)Z3txy5YAL2SdlNCx23#8@lV=klhQrgCtCK^6iq&yiGFX5gCk? zJi$U8oA&ueV5a4Hibx?Jp{Wc)@yX=My*( zL7_7NhVB~}!;y46N@yX6=YrUu?q0n2-ayE&8Ho^2BXfon%n2sU9aqf$oy;6~8J}>H zA=e6|(V|~0e$zg3m8eUa8xk-7JsYyzuqpOft-`Rs zH^+xTx^N`$Z(RqLP=&Cgt{C(VUdUC!mI((V)P4m!0wiLB9-ShsWtBKhe;Uo=S~*pirGTs*K95*3FV&@Z1ZZvE zs5;LRT(8aVhx$2Rw2m9u0ed~~K_>+K?D zQ->Y$as3~}ncAQf`Px+BhWYurUqwNYCk}Ae9}f!cSZ}aN419)jz}OD?14EuQj7E8X z%#CFCGLl{2KeqR z93I_m2RRq+EpkhL`5qeZZZFA@Dd>i!S9QL#ocuX<;Di515AeJnM5)m&{DwdT6}UGZ z?Uh#$Y6g>e%;_3}a`FG(76i>` zmP&lVdBNoMCUt}+xUcScH_sZfJF@aMJ)L>t4NOU#VH&1h(E9s5WOKHKC=ly-4$9jM zEE55DTxES{$aq3gb#=7Xg1ESn06x3_JrvU+xr;S91oUY&5OtS?NMJf*nj>gnH;|xK!p;vm&%_V^CrBt#gE)ST&-YNyWb6|sl#a@W0#~i; z>m$o(W>{vB=VoSS*c^DP8JSff`(OOoRt{y=K8i6ijAu^8kQOiFVY9A6YRG}3WZtmf zkfh?J<7%3aopW%u8OKyPCuxSr0oa(YMje=_9za>@!5@Kol$Wr2q)=Bq{%R!EunQm% ztoS>ixZ&obHjK|T+tb7Le3)`4dNMDRk&f~7`9jv>k+LQ<4;-g(@S%OL4_-Ptc@aJr zk`wpgV9(o5$pjM9{~2-P@y*dEad{cg54z|u5EJ3W&!*{eT{hXjfJ%vY@F;a0u z<@HFN*82RvNu61V2%s4i!^wbFKSOa-c}QPvs-( zb*|>|LLp>$ExD{S(NZG@#Cpwc;n>Whycyunvc`pAE{1-#>?b?RWqK22XyaN<5izLq zG3}x#N<8`Ivbh*zRrd}i%cXMRd}MQ~*Y|+#F6@H~+cQQ)+==?`zmk5$Th*v>#)!6daf6%pp=)r>m|T!9zXv%$ zALcUT6Mtq3n2oAw!Kk14-vkwTET!yNzq8HH5YQa2_Xi z6ArY?2h91VXJre5ABlpB7?R_uPC+ir!7GnbV#s+GP7EJgiPPA@5S(diaorAAD8cTF zo(+{hTmwJS?xrM^9vJ3Cjb7lKA2tJXefPF*(qK0H+>WP%5ZR?E0W`87l_1-d}X zD5lzwmnGk^*g}kFDKoSYTC`RLhX8ULYgRbqRFhv&BaU?N1mOv`CREcA&Ol-s3LLOM zHC|%Ag~wplRiIqM)G*!|=tLR$*5C{C!vov@H`};}Zp%9qGHhg$A0$Zngj}Sk zteKOn-C%ZcLK1SB+AGzQ|wl z(}r`j%?N8sv?Bl?>1bK7jJJ04HGUE{IkB<^jm!^`)U~VD9>-i1enVWHf=1p#&r( zmW0s>DifF>2x~^{;aMSkj}M&%D=XDMuESWZdpS~JRQpQx2qm6g0dBkhc+@^B0pv|_ zA4B|gY7X?aDh2$T*C?k~Ad>?3ZX{SCg<#yJtuvTSKL;8$`A7cht-N$XeNOMa8Ucv0 zrh&TsHQV*=PJxg2RW#lIXFh{(*HiUu9H!!&8X3A$mS}|ga|I3Kdt?+z(%LX`jzS!~lz3XM#v-%kdpx-a|XEtI#F%U`ccf zvTc)Df*4cU@J({p*ZhEm)`)|q1x@yPo?`3uKr};Qua`i!$&&kVx5UlOip)w^oEaQ> z!%%0aOxpsfQFv71R;G*s9C<0(+17TatOJbmV@@&gRIsiV48}%#=lF8BYliTqKl$J@j~wsTyyg=-C z%jEV3!BoWtTqx4?vMyIR2#~9;wT(D5-~$gCg3A?r^3X?$xE5tbNzGbB=&dmhH)cvO zh%rh4Jjn*eCN_$3n^#0^0dYCLV{dzC~ zLJRO}{N-*0x*=|8i+NN*e3?lRr9eQ#E zJ5{&Y+2F>)$J$A*c^}yUIO;G_z{M3|F6t>&WmF< z>e*q@&`PqvSrhE(m8s@FO5RNiH4=Um+Uu4-0N2@VsZl|!+dFxvD#Ew4c>R?IaO#)j z)M(w-=J7+y-}_yi#H*_ye~s4Cl5M%E&#i4osmC?6bB9`X$Q<7LqlT_72UQ%bNJ?4o zj!yVuk6+V>+#&NXlvuni4lgdZEu3(caof~1^%hy^f;Mjy-qNLuCXsjsANoH%MVb+s zZh5(!ie|UNAxx0j2?AR%M##dN;-J zr&q-Om)4Juy{qW;GA*batgd@?!W!q}OH?yUAY5WRkB^_

%dT8#&n9#M4$?9@Y?VN*Gm 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. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/zlib-1.2.11/contrib/dotzlib/DotZLib/ChecksumImpl.cs b/zlib-1.2.11/contrib/dotzlib/DotZLib/ChecksumImpl.cs new file mode 100644 index 00000000..788b2fce --- /dev/null +++ b/zlib-1.2.11/contrib/dotzlib/DotZLib/ChecksumImpl.cs @@ -0,0 +1,202 @@ +// +// Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.Runtime.InteropServices; +using System.Text; + + +namespace DotZLib +{ + #region ChecksumGeneratorBase + ///

+ /// Implements the common functionality needed for all s + /// + /// + public abstract class ChecksumGeneratorBase : ChecksumGenerator + { + /// + /// The value of the current checksum + /// + protected uint _current; + + /// + /// Initializes a new instance of the checksum generator base - the current checksum is + /// set to zero + /// + public ChecksumGeneratorBase() + { + _current = 0; + } + + /// + /// Initializes a new instance of the checksum generator basewith a specified value + /// + /// The value to set the current checksum to + public ChecksumGeneratorBase(uint initialValue) + { + _current = initialValue; + } + + /// + /// Resets the current checksum to zero + /// + public void Reset() { _current = 0; } + + /// + /// Gets the current checksum value + /// + public uint Value { get { return _current; } } + + /// + /// Updates the current checksum with part of an array of bytes + /// + /// The data to update the checksum with + /// Where in data to start updating + /// The number of bytes from data to use + /// The sum of offset and count is larger than the length of data + /// data is a null reference + /// Offset or count is negative. + /// All the other Update methods are implmeneted in terms of this one. + /// This is therefore the only method a derived class has to implement + public abstract void Update(byte[] data, int offset, int count); + + /// + /// Updates the current checksum with an array of bytes. + /// + /// The data to update the checksum with + public void Update(byte[] data) + { + Update(data, 0, data.Length); + } + + /// + /// Updates the current checksum with the data from a string + /// + /// The string to update the checksum with + /// The characters in the string are converted by the UTF-8 encoding + public void Update(string data) + { + Update(Encoding.UTF8.GetBytes(data)); + } + + /// + /// Updates the current checksum with the data from a string, using a specific encoding + /// + /// The string to update the checksum with + /// The encoding to use + public void Update(string data, Encoding encoding) + { + Update(encoding.GetBytes(data)); + } + + } + #endregion + + #region CRC32 + /// + /// Implements a CRC32 checksum generator + /// + public sealed class CRC32Checksum : ChecksumGeneratorBase + { + #region DLL imports + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern uint crc32(uint crc, int data, uint length); + + #endregion + + /// + /// Initializes a new instance of the CRC32 checksum generator + /// + public CRC32Checksum() : base() {} + + /// + /// Initializes a new instance of the CRC32 checksum generator with a specified value + /// + /// The value to set the current checksum to + public CRC32Checksum(uint initialValue) : base(initialValue) {} + + /// + /// Updates the current checksum with part of an array of bytes + /// + /// The data to update the checksum with + /// Where in data to start updating + /// The number of bytes from data to use + /// The sum of offset and count is larger than the length of data + /// data is a null reference + /// Offset or count is negative. + public override void Update(byte[] data, int offset, int count) + { + if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); + if ((offset+count) > data.Length) throw new ArgumentException(); + GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); + try + { + _current = crc32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); + } + finally + { + hData.Free(); + } + } + + } + #endregion + + #region Adler + /// + /// Implements a checksum generator that computes the Adler checksum on data + /// + public sealed class AdlerChecksum : ChecksumGeneratorBase + { + #region DLL imports + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern uint adler32(uint adler, int data, uint length); + + #endregion + + /// + /// Initializes a new instance of the Adler checksum generator + /// + public AdlerChecksum() : base() {} + + /// + /// Initializes a new instance of the Adler checksum generator with a specified value + /// + /// The value to set the current checksum to + public AdlerChecksum(uint initialValue) : base(initialValue) {} + + /// + /// Updates the current checksum with part of an array of bytes + /// + /// The data to update the checksum with + /// Where in data to start updating + /// The number of bytes from data to use + /// The sum of offset and count is larger than the length of data + /// data is a null reference + /// Offset or count is negative. + public override void Update(byte[] data, int offset, int count) + { + if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); + if ((offset+count) > data.Length) throw new ArgumentException(); + GCHandle hData = GCHandle.Alloc(data, GCHandleType.Pinned); + try + { + _current = adler32(_current, hData.AddrOfPinnedObject().ToInt32()+offset, (uint)count); + } + finally + { + hData.Free(); + } + } + + } + #endregion + +} \ No newline at end of file diff --git a/zlib-1.2.11/contrib/dotzlib/DotZLib/CircularBuffer.cs b/zlib-1.2.11/contrib/dotzlib/DotZLib/CircularBuffer.cs new file mode 100644 index 00000000..c1cab3a0 --- /dev/null +++ b/zlib-1.2.11/contrib/dotzlib/DotZLib/CircularBuffer.cs @@ -0,0 +1,83 @@ +// +// Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.Diagnostics; + +namespace DotZLib +{ + + /// + /// This class implements a circular buffer + /// + internal class CircularBuffer + { + #region Private data + private int _capacity; + private int _head; + private int _tail; + private int _size; + private byte[] _buffer; + #endregion + + public CircularBuffer(int capacity) + { + Debug.Assert( capacity > 0 ); + _buffer = new byte[capacity]; + _capacity = capacity; + _head = 0; + _tail = 0; + _size = 0; + } + + public int Size { get { return _size; } } + + public int Put(byte[] source, int offset, int count) + { + Debug.Assert( count > 0 ); + int trueCount = Math.Min(count, _capacity - Size); + for (int i = 0; i < trueCount; ++i) + _buffer[(_tail+i) % _capacity] = source[offset+i]; + _tail += trueCount; + _tail %= _capacity; + _size += trueCount; + return trueCount; + } + + public bool Put(byte b) + { + if (Size == _capacity) // no room + return false; + _buffer[_tail++] = b; + _tail %= _capacity; + ++_size; + return true; + } + + public int Get(byte[] destination, int offset, int count) + { + int trueCount = Math.Min(count,Size); + for (int i = 0; i < trueCount; ++i) + destination[offset + i] = _buffer[(_head+i) % _capacity]; + _head += trueCount; + _head %= _capacity; + _size -= trueCount; + return trueCount; + } + + public int Get() + { + if (Size == 0) + return -1; + + int result = (int)_buffer[_head++ % _capacity]; + --_size; + return result; + } + + } +} diff --git a/zlib-1.2.11/contrib/dotzlib/DotZLib/CodecBase.cs b/zlib-1.2.11/contrib/dotzlib/DotZLib/CodecBase.cs new file mode 100644 index 00000000..42e6da3a --- /dev/null +++ b/zlib-1.2.11/contrib/dotzlib/DotZLib/CodecBase.cs @@ -0,0 +1,198 @@ +// +// Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.Runtime.InteropServices; + +namespace DotZLib +{ + /// + /// Implements the common functionality needed for all s + /// + public abstract class CodecBase : Codec, IDisposable + { + + #region Data members + + /// + /// Instance of the internal zlib buffer structure that is + /// passed to all functions in the zlib dll + /// + internal ZStream _ztream = new ZStream(); + + /// + /// True if the object instance has been disposed, false otherwise + /// + protected bool _isDisposed = false; + + /// + /// The size of the internal buffers + /// + protected const int kBufferSize = 16384; + + private byte[] _outBuffer = new byte[kBufferSize]; + private byte[] _inBuffer = new byte[kBufferSize]; + + private GCHandle _hInput; + private GCHandle _hOutput; + + private uint _checksum = 0; + + #endregion + + /// + /// Initializes a new instance of the CodeBase class. + /// + public CodecBase() + { + try + { + _hInput = GCHandle.Alloc(_inBuffer, GCHandleType.Pinned); + _hOutput = GCHandle.Alloc(_outBuffer, GCHandleType.Pinned); + } + catch (Exception) + { + CleanUp(false); + throw; + } + } + + + #region Codec Members + + /// + /// Occurs when more processed data are available. + /// + public event DataAvailableHandler DataAvailable; + + /// + /// Fires the event + /// + protected void OnDataAvailable() + { + if (_ztream.total_out > 0) + { + if (DataAvailable != null) + DataAvailable( _outBuffer, 0, (int)_ztream.total_out); + resetOutput(); + } + } + + /// + /// Adds more data to the codec to be processed. + /// + /// Byte array containing the data to be added to the codec + /// Adding data may, or may not, raise the DataAvailable event + public void Add(byte[] data) + { + Add(data,0,data.Length); + } + + /// + /// Adds more data to the codec to be processed. + /// + /// Byte array containing the data to be added to the codec + /// The index of the first byte to add from data + /// The number of bytes to add + /// Adding data may, or may not, raise the DataAvailable event + /// This must be implemented by a derived class + public abstract void Add(byte[] data, int offset, int count); + + /// + /// Finishes up any pending data that needs to be processed and handled. + /// + /// This must be implemented by a derived class + public abstract void Finish(); + + /// + /// Gets the checksum of the data that has been added so far + /// + public uint Checksum { get { return _checksum; } } + + #endregion + + #region Destructor & IDisposable stuff + + /// + /// Destroys this instance + /// + ~CodecBase() + { + CleanUp(false); + } + + /// + /// Releases any unmanaged resources and calls the method of the derived class + /// + public void Dispose() + { + CleanUp(true); + } + + /// + /// Performs any codec specific cleanup + /// + /// This must be implemented by a derived class + protected abstract void CleanUp(); + + // performs the release of the handles and calls the dereived CleanUp() + private void CleanUp(bool isDisposing) + { + if (!_isDisposed) + { + CleanUp(); + if (_hInput.IsAllocated) + _hInput.Free(); + if (_hOutput.IsAllocated) + _hOutput.Free(); + + _isDisposed = true; + } + } + + + #endregion + + #region Helper methods + + /// + /// Copies a number of bytes to the internal codec buffer - ready for proccesing + /// + /// The byte array that contains the data to copy + /// The index of the first byte to copy + /// The number of bytes to copy from data + protected void copyInput(byte[] data, int startIndex, int count) + { + Array.Copy(data, startIndex, _inBuffer,0, count); + _ztream.next_in = _hInput.AddrOfPinnedObject(); + _ztream.total_in = 0; + _ztream.avail_in = (uint)count; + + } + + /// + /// Resets the internal output buffers to a known state - ready for processing + /// + protected void resetOutput() + { + _ztream.total_out = 0; + _ztream.avail_out = kBufferSize; + _ztream.next_out = _hOutput.AddrOfPinnedObject(); + } + + /// + /// Updates the running checksum property + /// + /// The new checksum value + protected void setChecksum(uint newSum) + { + _checksum = newSum; + } + #endregion + + } +} diff --git a/zlib-1.2.11/contrib/dotzlib/DotZLib/Deflater.cs b/zlib-1.2.11/contrib/dotzlib/DotZLib/Deflater.cs new file mode 100644 index 00000000..c2477925 --- /dev/null +++ b/zlib-1.2.11/contrib/dotzlib/DotZLib/Deflater.cs @@ -0,0 +1,106 @@ +// +// Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace DotZLib +{ + + /// + /// Implements a data compressor, using the deflate algorithm in the ZLib dll + /// + public sealed class Deflater : CodecBase + { + #region Dll imports + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] + private static extern int deflateInit_(ref ZStream sz, int level, string vs, int size); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int deflate(ref ZStream sz, int flush); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int deflateReset(ref ZStream sz); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int deflateEnd(ref ZStream sz); + #endregion + + /// + /// Constructs an new instance of the Deflater + /// + /// The compression level to use for this Deflater + public Deflater(CompressLevel level) : base() + { + int retval = deflateInit_(ref _ztream, (int)level, Info.Version, Marshal.SizeOf(_ztream)); + if (retval != 0) + throw new ZLibException(retval, "Could not initialize deflater"); + + resetOutput(); + } + + /// + /// Adds more data to the codec to be processed. + /// + /// Byte array containing the data to be added to the codec + /// The index of the first byte to add from data + /// The number of bytes to add + /// Adding data may, or may not, raise the DataAvailable event + public override void Add(byte[] data, int offset, int count) + { + if (data == null) throw new ArgumentNullException(); + if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); + if ((offset+count) > data.Length) throw new ArgumentException(); + + int total = count; + int inputIndex = offset; + int err = 0; + + while (err >= 0 && inputIndex < total) + { + copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); + while (err >= 0 && _ztream.avail_in > 0) + { + err = deflate(ref _ztream, (int)FlushTypes.None); + if (err == 0) + while (_ztream.avail_out == 0) + { + OnDataAvailable(); + err = deflate(ref _ztream, (int)FlushTypes.None); + } + inputIndex += (int)_ztream.total_in; + } + } + setChecksum( _ztream.adler ); + } + + + /// + /// Finishes up any pending data that needs to be processed and handled. + /// + public override void Finish() + { + int err; + do + { + err = deflate(ref _ztream, (int)FlushTypes.Finish); + OnDataAvailable(); + } + while (err == 0); + setChecksum( _ztream.adler ); + deflateReset(ref _ztream); + resetOutput(); + } + + /// + /// Closes the internal zlib deflate stream + /// + protected override void CleanUp() { deflateEnd(ref _ztream); } + + } +} diff --git a/zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.cs b/zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.cs new file mode 100644 index 00000000..be184b4c --- /dev/null +++ b/zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.cs @@ -0,0 +1,288 @@ +// +// Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; + + +namespace DotZLib +{ + + #region Internal types + + /// + /// Defines constants for the various flush types used with zlib + /// + internal enum FlushTypes + { + None, Partial, Sync, Full, Finish, Block + } + + #region ZStream structure + // internal mapping of the zlib zstream structure for marshalling + [StructLayoutAttribute(LayoutKind.Sequential, Pack=4, Size=0, CharSet=CharSet.Ansi)] + internal struct ZStream + { + public IntPtr next_in; + public uint avail_in; + public uint total_in; + + public IntPtr next_out; + public uint avail_out; + public uint total_out; + + [MarshalAs(UnmanagedType.LPStr)] + string msg; + uint state; + + uint zalloc; + uint zfree; + uint opaque; + + int data_type; + public uint adler; + uint reserved; + } + + #endregion + + #endregion + + #region Public enums + /// + /// Defines constants for the available compression levels in zlib + /// + public enum CompressLevel : int + { + /// + /// The default compression level with a reasonable compromise between compression and speed + /// + Default = -1, + /// + /// No compression at all. The data are passed straight through. + /// + None = 0, + /// + /// The maximum compression rate available. + /// + Best = 9, + /// + /// The fastest available compression level. + /// + Fastest = 1 + } + #endregion + + #region Exception classes + /// + /// The exception that is thrown when an error occurs on the zlib dll + /// + public class ZLibException : ApplicationException + { + /// + /// Initializes a new instance of the class with a specified + /// error message and error code + /// + /// The zlib error code that caused the exception + /// A message that (hopefully) describes the error + public ZLibException(int errorCode, string msg) : base(String.Format("ZLib error {0} {1}", errorCode, msg)) + { + } + + /// + /// Initializes a new instance of the class with a specified + /// error code + /// + /// The zlib error code that caused the exception + public ZLibException(int errorCode) : base(String.Format("ZLib error {0}", errorCode)) + { + } + } + #endregion + + #region Interfaces + + /// + /// Declares methods and properties that enables a running checksum to be calculated + /// + public interface ChecksumGenerator + { + /// + /// Gets the current value of the checksum + /// + uint Value { get; } + + /// + /// Clears the current checksum to 0 + /// + void Reset(); + + /// + /// Updates the current checksum with an array of bytes + /// + /// The data to update the checksum with + void Update(byte[] data); + + /// + /// Updates the current checksum with part of an array of bytes + /// + /// The data to update the checksum with + /// Where in data to start updating + /// The number of bytes from data to use + /// The sum of offset and count is larger than the length of data + /// data is a null reference + /// Offset or count is negative. + void Update(byte[] data, int offset, int count); + + /// + /// Updates the current checksum with the data from a string + /// + /// The string to update the checksum with + /// The characters in the string are converted by the UTF-8 encoding + void Update(string data); + + /// + /// Updates the current checksum with the data from a string, using a specific encoding + /// + /// The string to update the checksum with + /// The encoding to use + void Update(string data, Encoding encoding); + } + + + /// + /// Represents the method that will be called from a codec when new data + /// are available. + /// + /// The byte array containing the processed data + /// The index of the first processed byte in data + /// The number of processed bytes available + /// On return from this method, the data may be overwritten, so grab it while you can. + /// You cannot assume that startIndex will be zero. + /// + public delegate void DataAvailableHandler(byte[] data, int startIndex, int count); + + /// + /// Declares methods and events for implementing compressors/decompressors + /// + public interface Codec + { + /// + /// Occurs when more processed data are available. + /// + event DataAvailableHandler DataAvailable; + + /// + /// Adds more data to the codec to be processed. + /// + /// Byte array containing the data to be added to the codec + /// Adding data may, or may not, raise the DataAvailable event + void Add(byte[] data); + + /// + /// Adds more data to the codec to be processed. + /// + /// Byte array containing the data to be added to the codec + /// The index of the first byte to add from data + /// The number of bytes to add + /// Adding data may, or may not, raise the DataAvailable event + void Add(byte[] data, int offset, int count); + + /// + /// Finishes up any pending data that needs to be processed and handled. + /// + void Finish(); + + /// + /// Gets the checksum of the data that has been added so far + /// + uint Checksum { get; } + + + } + + #endregion + + #region Classes + /// + /// Encapsulates general information about the ZLib library + /// + public class Info + { + #region DLL imports + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern uint zlibCompileFlags(); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern string zlibVersion(); + #endregion + + #region Private stuff + private uint _flags; + + // helper function that unpacks a bitsize mask + private static int bitSize(uint bits) + { + switch (bits) + { + case 0: return 16; + case 1: return 32; + case 2: return 64; + } + return -1; + } + #endregion + + /// + /// Constructs an instance of the Info class. + /// + public Info() + { + _flags = zlibCompileFlags(); + } + + /// + /// True if the library is compiled with debug info + /// + public bool HasDebugInfo { get { return 0 != (_flags & 0x100); } } + + /// + /// True if the library is compiled with assembly optimizations + /// + public bool UsesAssemblyCode { get { return 0 != (_flags & 0x200); } } + + /// + /// Gets the size of the unsigned int that was compiled into Zlib + /// + public int SizeOfUInt { get { return bitSize(_flags & 3); } } + + /// + /// Gets the size of the unsigned long that was compiled into Zlib + /// + public int SizeOfULong { get { return bitSize((_flags >> 2) & 3); } } + + /// + /// Gets the size of the pointers that were compiled into Zlib + /// + public int SizeOfPointer { get { return bitSize((_flags >> 4) & 3); } } + + /// + /// Gets the size of the z_off_t type that was compiled into Zlib + /// + public int SizeOfOffset { get { return bitSize((_flags >> 6) & 3); } } + + /// + /// Gets the version of ZLib as a string, e.g. "1.2.1" + /// + public static string Version { get { return zlibVersion(); } } + } + + #endregion + +} diff --git a/zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.csproj b/zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.csproj new file mode 100644 index 00000000..71eeb859 --- /dev/null +++ b/zlib-1.2.11/contrib/dotzlib/DotZLib/DotZLib.csproj @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zlib-1.2.11/contrib/dotzlib/DotZLib/GZipStream.cs b/zlib-1.2.11/contrib/dotzlib/DotZLib/GZipStream.cs new file mode 100644 index 00000000..b161300b --- /dev/null +++ b/zlib-1.2.11/contrib/dotzlib/DotZLib/GZipStream.cs @@ -0,0 +1,301 @@ +// +// Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace DotZLib +{ + /// + /// Implements a compressed , in GZip (.gz) format. + /// + public class GZipStream : Stream, IDisposable + { + #region Dll Imports + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] + private static extern IntPtr gzopen(string name, string mode); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int gzclose(IntPtr gzFile); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int gzwrite(IntPtr gzFile, int data, int length); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int gzread(IntPtr gzFile, int data, int length); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int gzgetc(IntPtr gzFile); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int gzputc(IntPtr gzFile, int c); + + #endregion + + #region Private data + private IntPtr _gzFile; + private bool _isDisposed = false; + private bool _isWriting; + #endregion + + #region Constructors + /// + /// Creates a new file as a writeable GZipStream + /// + /// The name of the compressed file to create + /// The compression level to use when adding data + /// If an error occurred in the internal zlib function + public GZipStream(string fileName, CompressLevel level) + { + _isWriting = true; + _gzFile = gzopen(fileName, String.Format("wb{0}", (int)level)); + if (_gzFile == IntPtr.Zero) + throw new ZLibException(-1, "Could not open " + fileName); + } + + /// + /// Opens an existing file as a readable GZipStream + /// + /// The name of the file to open + /// If an error occurred in the internal zlib function + public GZipStream(string fileName) + { + _isWriting = false; + _gzFile = gzopen(fileName, "rb"); + if (_gzFile == IntPtr.Zero) + throw new ZLibException(-1, "Could not open " + fileName); + + } + #endregion + + #region Access properties + /// + /// Returns true of this stream can be read from, false otherwise + /// + public override bool CanRead + { + get + { + return !_isWriting; + } + } + + + /// + /// Returns false. + /// + public override bool CanSeek + { + get + { + return false; + } + } + + /// + /// Returns true if this tsream is writeable, false otherwise + /// + public override bool CanWrite + { + get + { + return _isWriting; + } + } + #endregion + + #region Destructor & IDispose stuff + + /// + /// Destroys this instance + /// + ~GZipStream() + { + cleanUp(false); + } + + /// + /// Closes the external file handle + /// + public void Dispose() + { + cleanUp(true); + } + + // Does the actual closing of the file handle. + private void cleanUp(bool isDisposing) + { + if (!_isDisposed) + { + gzclose(_gzFile); + _isDisposed = true; + } + } + #endregion + + #region Basic reading and writing + /// + /// Attempts to read a number of bytes from the stream. + /// + /// The destination data buffer + /// The index of the first destination byte in buffer + /// The number of bytes requested + /// The number of bytes read + /// If buffer is null + /// If count or offset are negative + /// If offset + count is > buffer.Length + /// If this stream is not readable. + /// If this stream has been disposed. + public override int Read(byte[] buffer, int offset, int count) + { + if (!CanRead) throw new NotSupportedException(); + if (buffer == null) throw new ArgumentNullException(); + if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); + if ((offset+count) > buffer.Length) throw new ArgumentException(); + if (_isDisposed) throw new ObjectDisposedException("GZipStream"); + + GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); + int result; + try + { + result = gzread(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); + if (result < 0) + throw new IOException(); + } + finally + { + h.Free(); + } + return result; + } + + /// + /// Attempts to read a single byte from the stream. + /// + /// The byte that was read, or -1 in case of error or End-Of-File + public override int ReadByte() + { + if (!CanRead) throw new NotSupportedException(); + if (_isDisposed) throw new ObjectDisposedException("GZipStream"); + return gzgetc(_gzFile); + } + + /// + /// Writes a number of bytes to the stream + /// + /// + /// + /// + /// If buffer is null + /// If count or offset are negative + /// If offset + count is > buffer.Length + /// If this stream is not writeable. + /// If this stream has been disposed. + public override void Write(byte[] buffer, int offset, int count) + { + if (!CanWrite) throw new NotSupportedException(); + if (buffer == null) throw new ArgumentNullException(); + if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); + if ((offset+count) > buffer.Length) throw new ArgumentException(); + if (_isDisposed) throw new ObjectDisposedException("GZipStream"); + + GCHandle h = GCHandle.Alloc(buffer, GCHandleType.Pinned); + try + { + int result = gzwrite(_gzFile, h.AddrOfPinnedObject().ToInt32() + offset, count); + if (result < 0) + throw new IOException(); + } + finally + { + h.Free(); + } + } + + /// + /// Writes a single byte to the stream + /// + /// The byte to add to the stream. + /// If this stream is not writeable. + /// If this stream has been disposed. + public override void WriteByte(byte value) + { + if (!CanWrite) throw new NotSupportedException(); + if (_isDisposed) throw new ObjectDisposedException("GZipStream"); + + int result = gzputc(_gzFile, (int)value); + if (result < 0) + throw new IOException(); + } + #endregion + + #region Position & length stuff + /// + /// Not supported. + /// + /// + /// Always thrown + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + /// + /// Not suppported. + /// + /// + /// + /// + /// Always thrown + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + /// + /// Flushes the GZipStream. + /// + /// In this implementation, this method does nothing. This is because excessive + /// flushing may degrade the achievable compression rates. + public override void Flush() + { + // left empty on purpose + } + + /// + /// Gets/sets the current position in the GZipStream. Not suppported. + /// + /// In this implementation this property is not supported + /// Always thrown + public override long Position + { + get + { + throw new NotSupportedException(); + } + set + { + throw new NotSupportedException(); + } + } + + /// + /// Gets the size of the stream. Not suppported. + /// + /// In this implementation this property is not supported + /// Always thrown + public override long Length + { + get + { + throw new NotSupportedException(); + } + } + #endregion + } +} diff --git a/zlib-1.2.11/contrib/dotzlib/DotZLib/Inflater.cs b/zlib-1.2.11/contrib/dotzlib/DotZLib/Inflater.cs new file mode 100644 index 00000000..8ed5451d --- /dev/null +++ b/zlib-1.2.11/contrib/dotzlib/DotZLib/Inflater.cs @@ -0,0 +1,105 @@ +// +// Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace DotZLib +{ + + /// + /// Implements a data decompressor, using the inflate algorithm in the ZLib dll + /// + public class Inflater : CodecBase + { + #region Dll imports + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl, CharSet=CharSet.Ansi)] + private static extern int inflateInit_(ref ZStream sz, string vs, int size); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int inflate(ref ZStream sz, int flush); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int inflateReset(ref ZStream sz); + + [DllImport("ZLIB1.dll", CallingConvention=CallingConvention.Cdecl)] + private static extern int inflateEnd(ref ZStream sz); + #endregion + + /// + /// Constructs an new instance of the Inflater + /// + public Inflater() : base() + { + int retval = inflateInit_(ref _ztream, Info.Version, Marshal.SizeOf(_ztream)); + if (retval != 0) + throw new ZLibException(retval, "Could not initialize inflater"); + + resetOutput(); + } + + + /// + /// Adds more data to the codec to be processed. + /// + /// Byte array containing the data to be added to the codec + /// The index of the first byte to add from data + /// The number of bytes to add + /// Adding data may, or may not, raise the DataAvailable event + public override void Add(byte[] data, int offset, int count) + { + if (data == null) throw new ArgumentNullException(); + if (offset < 0 || count < 0) throw new ArgumentOutOfRangeException(); + if ((offset+count) > data.Length) throw new ArgumentException(); + + int total = count; + int inputIndex = offset; + int err = 0; + + while (err >= 0 && inputIndex < total) + { + copyInput(data, inputIndex, Math.Min(total - inputIndex, kBufferSize)); + err = inflate(ref _ztream, (int)FlushTypes.None); + if (err == 0) + while (_ztream.avail_out == 0) + { + OnDataAvailable(); + err = inflate(ref _ztream, (int)FlushTypes.None); + } + + inputIndex += (int)_ztream.total_in; + } + setChecksum( _ztream.adler ); + } + + + /// + /// Finishes up any pending data that needs to be processed and handled. + /// + public override void Finish() + { + int err; + do + { + err = inflate(ref _ztream, (int)FlushTypes.Finish); + OnDataAvailable(); + } + while (err == 0); + setChecksum( _ztream.adler ); + inflateReset(ref _ztream); + resetOutput(); + } + + /// + /// Closes the internal zlib inflate stream + /// + protected override void CleanUp() { inflateEnd(ref _ztream); } + + + } +} diff --git a/zlib-1.2.11/contrib/dotzlib/DotZLib/UnitTests.cs b/zlib-1.2.11/contrib/dotzlib/DotZLib/UnitTests.cs new file mode 100644 index 00000000..44f76332 --- /dev/null +++ b/zlib-1.2.11/contrib/dotzlib/DotZLib/UnitTests.cs @@ -0,0 +1,274 @@ +// +// © Copyright Henrik Ravn 2004 +// +// Use, modification and distribution are subject to the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +using System; +using System.Collections; +using System.IO; + +// uncomment the define below to include unit tests +//#define nunit +#if nunit +using NUnit.Framework; + +// Unit tests for the DotZLib class library +// ---------------------------------------- +// +// Use this with NUnit 2 from http://www.nunit.org +// + +namespace DotZLibTests +{ + using DotZLib; + + // helper methods + internal class Utils + { + public static bool byteArrEqual( byte[] lhs, byte[] rhs ) + { + if (lhs.Length != rhs.Length) + return false; + for (int i = lhs.Length-1; i >= 0; --i) + if (lhs[i] != rhs[i]) + return false; + return true; + } + + } + + + [TestFixture] + public class CircBufferTests + { + #region Circular buffer tests + [Test] + public void SinglePutGet() + { + CircularBuffer buf = new CircularBuffer(10); + Assert.AreEqual( 0, buf.Size ); + Assert.AreEqual( -1, buf.Get() ); + + Assert.IsTrue(buf.Put( 1 )); + Assert.AreEqual( 1, buf.Size ); + Assert.AreEqual( 1, buf.Get() ); + Assert.AreEqual( 0, buf.Size ); + Assert.AreEqual( -1, buf.Get() ); + } + + [Test] + public void BlockPutGet() + { + CircularBuffer buf = new CircularBuffer(10); + byte[] arr = {1,2,3,4,5,6,7,8,9,10}; + Assert.AreEqual( 10, buf.Put(arr,0,10) ); + Assert.AreEqual( 10, buf.Size ); + Assert.IsFalse( buf.Put(11) ); + Assert.AreEqual( 1, buf.Get() ); + Assert.IsTrue( buf.Put(11) ); + + byte[] arr2 = (byte[])arr.Clone(); + Assert.AreEqual( 9, buf.Get(arr2,1,9) ); + Assert.IsTrue( Utils.byteArrEqual(arr,arr2) ); + } + + #endregion + } + + [TestFixture] + public class ChecksumTests + { + #region CRC32 Tests + [Test] + public void CRC32_Null() + { + CRC32Checksum crc32 = new CRC32Checksum(); + Assert.AreEqual( 0, crc32.Value ); + + crc32 = new CRC32Checksum(1); + Assert.AreEqual( 1, crc32.Value ); + + crc32 = new CRC32Checksum(556); + Assert.AreEqual( 556, crc32.Value ); + } + + [Test] + public void CRC32_Data() + { + CRC32Checksum crc32 = new CRC32Checksum(); + byte[] data = { 1,2,3,4,5,6,7 }; + crc32.Update(data); + Assert.AreEqual( 0x70e46888, crc32.Value ); + + crc32 = new CRC32Checksum(); + crc32.Update("penguin"); + Assert.AreEqual( 0x0e5c1a120, crc32.Value ); + + crc32 = new CRC32Checksum(1); + crc32.Update("penguin"); + Assert.AreEqual(0x43b6aa94, crc32.Value); + + } + #endregion + + #region Adler tests + + [Test] + public void Adler_Null() + { + AdlerChecksum adler = new AdlerChecksum(); + Assert.AreEqual(0, adler.Value); + + adler = new AdlerChecksum(1); + Assert.AreEqual( 1, adler.Value ); + + adler = new AdlerChecksum(556); + Assert.AreEqual( 556, adler.Value ); + } + + [Test] + public void Adler_Data() + { + AdlerChecksum adler = new AdlerChecksum(1); + byte[] data = { 1,2,3,4,5,6,7 }; + adler.Update(data); + Assert.AreEqual( 0x5b001d, adler.Value ); + + adler = new AdlerChecksum(); + adler.Update("penguin"); + Assert.AreEqual(0x0bcf02f6, adler.Value ); + + adler = new AdlerChecksum(1); + adler.Update("penguin"); + Assert.AreEqual(0x0bd602f7, adler.Value); + + } + #endregion + } + + [TestFixture] + public class InfoTests + { + #region Info tests + [Test] + public void Info_Version() + { + Info info = new Info(); + Assert.AreEqual("1.2.11", Info.Version); + Assert.AreEqual(32, info.SizeOfUInt); + Assert.AreEqual(32, info.SizeOfULong); + Assert.AreEqual(32, info.SizeOfPointer); + Assert.AreEqual(32, info.SizeOfOffset); + } + #endregion + } + + [TestFixture] + public class DeflateInflateTests + { + #region Deflate tests + [Test] + public void Deflate_Init() + { + using (Deflater def = new Deflater(CompressLevel.Default)) + { + } + } + + private ArrayList compressedData = new ArrayList(); + private uint adler1; + + private ArrayList uncompressedData = new ArrayList(); + private uint adler2; + + public void CDataAvail(byte[] data, int startIndex, int count) + { + for (int i = 0; i < count; ++i) + compressedData.Add(data[i+startIndex]); + } + + [Test] + public void Deflate_Compress() + { + compressedData.Clear(); + + byte[] testData = new byte[35000]; + for (int i = 0; i < testData.Length; ++i) + testData[i] = 5; + + using (Deflater def = new Deflater((CompressLevel)5)) + { + def.DataAvailable += new DataAvailableHandler(CDataAvail); + def.Add(testData); + def.Finish(); + adler1 = def.Checksum; + } + } + #endregion + + #region Inflate tests + [Test] + public void Inflate_Init() + { + using (Inflater inf = new Inflater()) + { + } + } + + private void DDataAvail(byte[] data, int startIndex, int count) + { + for (int i = 0; i < count; ++i) + uncompressedData.Add(data[i+startIndex]); + } + + [Test] + public void Inflate_Expand() + { + uncompressedData.Clear(); + + using (Inflater inf = new Inflater()) + { + inf.DataAvailable += new DataAvailableHandler(DDataAvail); + inf.Add((byte[])compressedData.ToArray(typeof(byte))); + inf.Finish(); + adler2 = inf.Checksum; + } + Assert.AreEqual( adler1, adler2 ); + } + #endregion + } + + [TestFixture] + public class GZipStreamTests + { + #region GZipStream test + [Test] + public void GZipStream_WriteRead() + { + using (GZipStream gzOut = new GZipStream("gzstream.gz", CompressLevel.Best)) + { + BinaryWriter writer = new BinaryWriter(gzOut); + writer.Write("hi there"); + writer.Write(Math.PI); + writer.Write(42); + } + + using (GZipStream gzIn = new GZipStream("gzstream.gz")) + { + BinaryReader reader = new BinaryReader(gzIn); + string s = reader.ReadString(); + Assert.AreEqual("hi there",s); + double d = reader.ReadDouble(); + Assert.AreEqual(Math.PI, d); + int i = reader.ReadInt32(); + Assert.AreEqual(42,i); + } + + } + #endregion + } +} + +#endif diff --git a/zlib-1.2.11/contrib/dotzlib/LICENSE_1_0.txt b/zlib-1.2.11/contrib/dotzlib/LICENSE_1_0.txt new file mode 100644 index 00000000..30aac2cf --- /dev/null +++ b/zlib-1.2.11/contrib/dotzlib/LICENSE_1_0.txt @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/zlib-1.2.11/contrib/dotzlib/readme.txt b/zlib-1.2.11/contrib/dotzlib/readme.txt new file mode 100644 index 00000000..b2395720 --- /dev/null +++ b/zlib-1.2.11/contrib/dotzlib/readme.txt @@ -0,0 +1,58 @@ +This directory contains a .Net wrapper class library for the ZLib1.dll + +The wrapper includes support for inflating/deflating memory buffers, +.Net streaming wrappers for the gz streams part of zlib, and wrappers +for the checksum parts of zlib. See DotZLib/UnitTests.cs for examples. + +Directory structure: +-------------------- + +LICENSE_1_0.txt - License file. +readme.txt - This file. +DotZLib.chm - Class library documentation +DotZLib.build - NAnt build file +DotZLib.sln - Microsoft Visual Studio 2003 solution file + +DotZLib\*.cs - Source files for the class library + +Unit tests: +----------- +The file DotZLib/UnitTests.cs contains unit tests for use with NUnit 2.1 or higher. +To include unit tests in the build, define nunit before building. + + +Build instructions: +------------------- + +1. Using Visual Studio.Net 2003: + Open DotZLib.sln in VS.Net and build from there. Output file (DotZLib.dll) + will be found ./DotZLib/bin/release or ./DotZLib/bin/debug, depending on + you are building the release or debug version of the library. Check + DotZLib/UnitTests.cs for instructions on how to include unit tests in the + build. + +2. Using NAnt: + Open a command prompt with access to the build environment and run nant + in the same directory as the DotZLib.build file. + You can define 2 properties on the nant command-line to control the build: + debug={true|false} to toggle between release/debug builds (default=true). + nunit={true|false} to include or esclude unit tests (default=true). + Also the target clean will remove binaries. + Output file (DotZLib.dll) will be found in either ./DotZLib/bin/release + or ./DotZLib/bin/debug, depending on whether you are building the release + or debug version of the library. + + Examples: + nant -D:debug=false -D:nunit=false + will build a release mode version of the library without unit tests. + nant + will build a debug version of the library with unit tests + nant clean + will remove all previously built files. + + +--------------------------------- +Copyright (c) Henrik Ravn 2004 + +Use, modification and distribution are subject to the Boost Software License, Version 1.0. +(See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/zlib-1.2.11/contrib/gcc_gvmat64/gvmat64.S b/zlib-1.2.11/contrib/gcc_gvmat64/gvmat64.S new file mode 100644 index 00000000..dd858ddb --- /dev/null +++ b/zlib-1.2.11/contrib/gcc_gvmat64/gvmat64.S @@ -0,0 +1,574 @@ +/* +;uInt longest_match_x64( +; deflate_state *s, +; IPos cur_match); // current match + +; gvmat64.S -- Asm portion of the optimized longest_match for 32 bits x86_64 +; (AMD64 on Athlon 64, Opteron, Phenom +; and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7) +; this file is translation from gvmat64.asm to GCC 4.x (for Linux, Mac XCode) +; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant. +; +; File written by Gilles Vollant, by converting to assembly the longest_match +; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. +; and by taking inspiration on asm686 with masm, optimised assembly code +; from Brian Raiter, written 1998 +; +; This software is provided 'as-is', without any express or implied +; warranty. In no event will the authors be held liable for any damages +; arising from the use of this software. +; +; Permission is granted to anyone to use this software for any purpose, +; including commercial applications, and to alter it and redistribute it +; freely, subject to the following restrictions: +; +; 1. The origin of this software must not be misrepresented; you must not +; claim that you wrote the original software. If you use this software +; in a product, an acknowledgment in the product documentation would be +; appreciated but is not required. +; 2. Altered source versions must be plainly marked as such, and must not be +; misrepresented as being the original software +; 3. This notice may not be removed or altered from any source distribution. +; +; http://www.zlib.net +; http://www.winimage.com/zLibDll +; http://www.muppetlabs.com/~breadbox/software/assembly.html +; +; to compile this file for zLib, I use option: +; gcc -c -arch x86_64 gvmat64.S + + +;uInt longest_match(s, cur_match) +; deflate_state *s; +; IPos cur_match; // current match / +; +; with XCode for Mac, I had strange error with some jump on intel syntax +; this is why BEFORE_JMP and AFTER_JMP are used + */ + + +#define BEFORE_JMP .att_syntax +#define AFTER_JMP .intel_syntax noprefix + +#ifndef NO_UNDERLINE +# define match_init _match_init +# define longest_match _longest_match +#endif + +.intel_syntax noprefix + +.globl match_init, longest_match +.text +longest_match: + + + +#define LocalVarsSize 96 +/* +; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12 +; free register : r14,r15 +; register can be saved : rsp +*/ + +#define chainlenwmask (rsp + 8 - LocalVarsSize) +#define nicematch (rsp + 16 - LocalVarsSize) + +#define save_rdi (rsp + 24 - LocalVarsSize) +#define save_rsi (rsp + 32 - LocalVarsSize) +#define save_rbx (rsp + 40 - LocalVarsSize) +#define save_rbp (rsp + 48 - LocalVarsSize) +#define save_r12 (rsp + 56 - LocalVarsSize) +#define save_r13 (rsp + 64 - LocalVarsSize) +#define save_r14 (rsp + 72 - LocalVarsSize) +#define save_r15 (rsp + 80 - LocalVarsSize) + + +/* +; all the +4 offsets are due to the addition of pending_buf_size (in zlib +; in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, remove the +4). +; Note : these value are good with a 8 bytes boundary pack structure +*/ + +#define MAX_MATCH 258 +#define MIN_MATCH 3 +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) + +/* +;;; Offsets for fields in the deflate_state structure. These numbers +;;; are calculated from the definition of deflate_state, with the +;;; assumption that the compiler will dword-align the fields. (Thus, +;;; changing the definition of deflate_state could easily cause this +;;; program to crash horribly, without so much as a warning at +;;; compile time. Sigh.) + +; all the +zlib1222add offsets are due to the addition of fields +; in zlib in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). +; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). +; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). +*/ + + + +/* you can check the structure offset by running + +#include +#include +#include "deflate.h" + +void print_depl() +{ +deflate_state ds; +deflate_state *s=&ds; +printf("size pointer=%u\n",(int)sizeof(void*)); + +printf("#define dsWSize %u\n",(int)(((char*)&(s->w_size))-((char*)s))); +printf("#define dsWMask %u\n",(int)(((char*)&(s->w_mask))-((char*)s))); +printf("#define dsWindow %u\n",(int)(((char*)&(s->window))-((char*)s))); +printf("#define dsPrev %u\n",(int)(((char*)&(s->prev))-((char*)s))); +printf("#define dsMatchLen %u\n",(int)(((char*)&(s->match_length))-((char*)s))); +printf("#define dsPrevMatch %u\n",(int)(((char*)&(s->prev_match))-((char*)s))); +printf("#define dsStrStart %u\n",(int)(((char*)&(s->strstart))-((char*)s))); +printf("#define dsMatchStart %u\n",(int)(((char*)&(s->match_start))-((char*)s))); +printf("#define dsLookahead %u\n",(int)(((char*)&(s->lookahead))-((char*)s))); +printf("#define dsPrevLen %u\n",(int)(((char*)&(s->prev_length))-((char*)s))); +printf("#define dsMaxChainLen %u\n",(int)(((char*)&(s->max_chain_length))-((char*)s))); +printf("#define dsGoodMatch %u\n",(int)(((char*)&(s->good_match))-((char*)s))); +printf("#define dsNiceMatch %u\n",(int)(((char*)&(s->nice_match))-((char*)s))); +} +*/ + +#define dsWSize 68 +#define dsWMask 76 +#define dsWindow 80 +#define dsPrev 96 +#define dsMatchLen 144 +#define dsPrevMatch 148 +#define dsStrStart 156 +#define dsMatchStart 160 +#define dsLookahead 164 +#define dsPrevLen 168 +#define dsMaxChainLen 172 +#define dsGoodMatch 188 +#define dsNiceMatch 192 + +#define window_size [ rcx + dsWSize] +#define WMask [ rcx + dsWMask] +#define window_ad [ rcx + dsWindow] +#define prev_ad [ rcx + dsPrev] +#define strstart [ rcx + dsStrStart] +#define match_start [ rcx + dsMatchStart] +#define Lookahead [ rcx + dsLookahead] //; 0ffffffffh on infozip +#define prev_length [ rcx + dsPrevLen] +#define max_chain_length [ rcx + dsMaxChainLen] +#define good_match [ rcx + dsGoodMatch] +#define nice_match [ rcx + dsNiceMatch] + +/* +; windows: +; parameter 1 in rcx(deflate state s), param 2 in rdx (cur match) + +; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and +; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp +; +; All registers must be preserved across the call, except for +; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch. + +; +; gcc on macosx-linux: +; see http://www.x86-64.org/documentation/abi-0.99.pdf +; param 1 in rdi, param 2 in rsi +; rbx, rsp, rbp, r12 to r15 must be preserved + +;;; Save registers that the compiler may be using, and adjust esp to +;;; make room for our stack frame. + + +;;; Retrieve the function arguments. r8d will hold cur_match +;;; throughout the entire function. edx will hold the pointer to the +;;; deflate_state structure during the function's setup (before +;;; entering the main loop. + +; ms: parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) +; mac: param 1 in rdi, param 2 rsi +; this clear high 32 bits of r8, which can be garbage in both r8 and rdx +*/ + mov [save_rbx],rbx + mov [save_rbp],rbp + + + mov rcx,rdi + + mov r8d,esi + + + mov [save_r12],r12 + mov [save_r13],r13 + mov [save_r14],r14 + mov [save_r15],r15 + + +//;;; uInt wmask = s->w_mask; +//;;; unsigned chain_length = s->max_chain_length; +//;;; if (s->prev_length >= s->good_match) { +//;;; chain_length >>= 2; +//;;; } + + + mov edi, prev_length + mov esi, good_match + mov eax, WMask + mov ebx, max_chain_length + cmp edi, esi + jl LastMatchGood + shr ebx, 2 +LastMatchGood: + +//;;; chainlen is decremented once beforehand so that the function can +//;;; use the sign flag instead of the zero flag for the exit test. +//;;; It is then shifted into the high word, to make room for the wmask +//;;; value, which it will always accompany. + + dec ebx + shl ebx, 16 + or ebx, eax + +//;;; on zlib only +//;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + + + mov eax, nice_match + mov [chainlenwmask], ebx + mov r10d, Lookahead + cmp r10d, eax + cmovnl r10d, eax + mov [nicematch],r10d + + + +//;;; register Bytef *scan = s->window + s->strstart; + mov r10, window_ad + mov ebp, strstart + lea r13, [r10 + rbp] + +//;;; Determine how many bytes the scan ptr is off from being +//;;; dword-aligned. + + mov r9,r13 + neg r13 + and r13,3 + +//;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +//;;; s->strstart - (IPos)MAX_DIST(s) : NIL; + + + mov eax, window_size + sub eax, MIN_LOOKAHEAD + + + xor edi,edi + sub ebp, eax + + mov r11d, prev_length + + cmovng ebp,edi + +//;;; int best_len = s->prev_length; + + +//;;; Store the sum of s->window + best_len in esi locally, and in esi. + + lea rsi,[r10+r11] + +//;;; register ush scan_start = *(ushf*)scan; +//;;; register ush scan_end = *(ushf*)(scan+best_len-1); +//;;; Posf *prev = s->prev; + + movzx r12d,word ptr [r9] + movzx ebx, word ptr [r9 + r11 - 1] + + mov rdi, prev_ad + +//;;; Jump into the main loop. + + mov edx, [chainlenwmask] + + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + + + +LookupLoop1: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + + + + sub edx, 0x00010000 + BEFORE_JMP + js LeaveNow + AFTER_JMP + +LoopEntry1: + cmp bx,word ptr [rsi + r8 - 1] + BEFORE_JMP + jz LookupLoopIsZero + AFTER_JMP + +LookupLoop2: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + BEFORE_JMP + jbe LeaveNow + AFTER_JMP + sub edx, 0x00010000 + BEFORE_JMP + js LeaveNow + AFTER_JMP + +LoopEntry2: + cmp bx,word ptr [rsi + r8 - 1] + BEFORE_JMP + jz LookupLoopIsZero + AFTER_JMP + +LookupLoop4: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + BEFORE_JMP + jbe LeaveNow + AFTER_JMP + sub edx, 0x00010000 + BEFORE_JMP + js LeaveNow + AFTER_JMP + +LoopEntry4: + + cmp bx,word ptr [rsi + r8 - 1] + BEFORE_JMP + jnz LookupLoop1 + jmp LookupLoopIsZero + AFTER_JMP +/* +;;; do { +;;; match = s->window + cur_match; +;;; if (*(ushf*)(match+best_len-1) != scan_end || +;;; *(ushf*)match != scan_start) continue; +;;; [...] +;;; } while ((cur_match = prev[cur_match & wmask]) > limit +;;; && --chain_length != 0); +;;; +;;; Here is the inner loop of the function. The function will spend the +;;; majority of its time in this loop, and majority of that time will +;;; be spent in the first ten instructions. +;;; +;;; Within this loop: +;;; ebx = scanend +;;; r8d = curmatch +;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) +;;; esi = windowbestlen - i.e., (window + bestlen) +;;; edi = prev +;;; ebp = limit +*/ +.balign 16 +LookupLoop: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + BEFORE_JMP + jbe LeaveNow + AFTER_JMP + sub edx, 0x00010000 + BEFORE_JMP + js LeaveNow + AFTER_JMP + +LoopEntry: + + cmp bx,word ptr [rsi + r8 - 1] + BEFORE_JMP + jnz LookupLoop1 + AFTER_JMP +LookupLoopIsZero: + cmp r12w, word ptr [r10 + r8] + BEFORE_JMP + jnz LookupLoop1 + AFTER_JMP + + +//;;; Store the current value of chainlen. + mov [chainlenwmask], edx +/* +;;; Point edi to the string under scrutiny, and esi to the string we +;;; are hoping to match it up with. In actuality, esi and edi are +;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is +;;; initialized to -(MAX_MATCH_8 - scanalign). +*/ + lea rsi,[r8+r10] + mov rdx, 0xfffffffffffffef8 //; -(MAX_MATCH_8) + lea rsi, [rsi + r13 + 0x0108] //;MAX_MATCH_8] + lea rdi, [r9 + r13 + 0x0108] //;MAX_MATCH_8] + + prefetcht1 [rsi+rdx] + prefetcht1 [rdi+rdx] + +/* +;;; Test the strings for equality, 8 bytes at a time. At the end, +;;; adjust rdx so that it is offset to the exact byte that mismatched. +;;; +;;; We already know at this point that the first three bytes of the +;;; strings match each other, and they can be safely passed over before +;;; starting the compare loop. So what this code does is skip over 0-3 +;;; bytes, as much as necessary in order to dword-align the edi +;;; pointer. (rsi will still be misaligned three times out of four.) +;;; +;;; It should be confessed that this loop usually does not represent +;;; much of the total running time. Replacing it with a more +;;; straightforward "rep cmpsb" would not drastically degrade +;;; performance. +*/ + +LoopCmps: + mov rax, [rsi + rdx] + xor rax, [rdi + rdx] + jnz LeaveLoopCmps + + mov rax, [rsi + rdx + 8] + xor rax, [rdi + rdx + 8] + jnz LeaveLoopCmps8 + + + mov rax, [rsi + rdx + 8+8] + xor rax, [rdi + rdx + 8+8] + jnz LeaveLoopCmps16 + + add rdx,8+8+8 + + BEFORE_JMP + jnz LoopCmps + jmp LenMaximum + AFTER_JMP + +LeaveLoopCmps16: add rdx,8 +LeaveLoopCmps8: add rdx,8 +LeaveLoopCmps: + + test eax, 0x0000FFFF + jnz LenLower + + test eax,0xffffffff + + jnz LenLower32 + + add rdx,4 + shr rax,32 + or ax,ax + BEFORE_JMP + jnz LenLower + AFTER_JMP + +LenLower32: + shr eax,16 + add rdx,2 + +LenLower: + sub al, 1 + adc rdx, 0 +//;;; Calculate the length of the match. If it is longer than MAX_MATCH, +//;;; then automatically accept it as the best possible match and leave. + + lea rax, [rdi + rdx] + sub rax, r9 + cmp eax, MAX_MATCH + BEFORE_JMP + jge LenMaximum + AFTER_JMP +/* +;;; If the length of the match is not longer than the best match we +;;; have so far, then forget it and return to the lookup loop. +;/////////////////////////////////// +*/ + cmp eax, r11d + jg LongerMatch + + lea rsi,[r10+r11] + + mov rdi, prev_ad + mov edx, [chainlenwmask] + BEFORE_JMP + jmp LookupLoop + AFTER_JMP +/* +;;; s->match_start = cur_match; +;;; best_len = len; +;;; if (len >= nice_match) break; +;;; scan_end = *(ushf*)(scan+best_len-1); +*/ +LongerMatch: + mov r11d, eax + mov match_start, r8d + cmp eax, [nicematch] + BEFORE_JMP + jge LeaveNow + AFTER_JMP + + lea rsi,[r10+rax] + + movzx ebx, word ptr [r9 + rax - 1] + mov rdi, prev_ad + mov edx, [chainlenwmask] + BEFORE_JMP + jmp LookupLoop + AFTER_JMP + +//;;; Accept the current string, with the maximum possible length. + +LenMaximum: + mov r11d,MAX_MATCH + mov match_start, r8d + +//;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; +//;;; return s->lookahead; + +LeaveNow: + mov eax, Lookahead + cmp r11d, eax + cmovng eax, r11d + + + +//;;; Restore the stack and return from whence we came. + + +// mov rsi,[save_rsi] +// mov rdi,[save_rdi] + mov rbx,[save_rbx] + mov rbp,[save_rbp] + mov r12,[save_r12] + mov r13,[save_r13] + mov r14,[save_r14] + mov r15,[save_r15] + + + ret 0 +//; please don't remove this string ! +//; Your can freely use gvmat64 in any free or commercial app +//; but it is far better don't remove the string in the binary! + // db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0 + + +match_init: + ret 0 + + diff --git a/zlib-1.2.11/contrib/infback9/README b/zlib-1.2.11/contrib/infback9/README new file mode 100644 index 00000000..e75ed132 --- /dev/null +++ b/zlib-1.2.11/contrib/infback9/README @@ -0,0 +1 @@ +See infback9.h for what this is and how to use it. diff --git a/zlib-1.2.11/contrib/infback9/infback9.c b/zlib-1.2.11/contrib/infback9/infback9.c new file mode 100644 index 00000000..05fb3e33 --- /dev/null +++ b/zlib-1.2.11/contrib/infback9/infback9.c @@ -0,0 +1,615 @@ +/* infback9.c -- inflate deflate64 data using a call-back interface + * Copyright (C) 1995-2008 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infback9.h" +#include "inftree9.h" +#include "inflate9.h" + +#define WSIZE 65536UL + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + window is a user-supplied window and output buffer that is 64K bytes. + */ +int ZEXPORT inflateBack9Init_(strm, window, version, stream_size) +z_stream FAR *strm; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == (free_func)0) strm->zfree = zcfree; + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (voidpf)state; + state->window = window; + return Z_OK; +} + +/* + Build and output length and distance decoding tables for fixed code + decoding. + */ +#ifdef MAKEFIXED +#include + +void makefixed9(void) +{ + unsigned sym, bits, low, size; + code *next, *lenfix, *distfix; + struct inflate_state state; + code fixed[544]; + + /* literal/length table */ + sym = 0; + while (sym < 144) state.lens[sym++] = 8; + while (sym < 256) state.lens[sym++] = 9; + while (sym < 280) state.lens[sym++] = 7; + while (sym < 288) state.lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table9(LENS, state.lens, 288, &(next), &(bits), state.work); + + /* distance table */ + sym = 0; + while (sym < 32) state.lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table9(DISTS, state.lens, 32, &(next), &(bits), state.work); + + /* write tables */ + puts(" /* inffix9.h -- table for decoding deflate64 fixed codes"); + puts(" * Generated automatically by makefixed9()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", lenfix[low].op, lenfix[low].bits, + lenfix[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 5) == 0) printf("\n "); + printf("{%u,%u,%d}", distfix[low].op, distfix[low].bits, + distfix[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* Macros for inflateBack(): */ + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n <= 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = window; \ + left = WSIZE; \ + wrap = 1; \ + if (out(out_desc, put, (unsigned)left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack9(strm, in, in_desc, out, out_desc) +z_stream FAR *strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have; /* available input */ + unsigned long left; /* available output */ + inflate_mode mode; /* current inflate mode */ + int lastblock; /* true if processing last block */ + int wrap; /* true if the window has wrapped */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned extra; /* extra bits needed */ + unsigned long length; /* literal or length of data to copy */ + unsigned long offset; /* distance back to copy string from */ + unsigned long copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; +#include "inffix9.h" + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + mode = TYPE; + lastblock = 0; + wrap = 0; + window = state->window; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = window; + left = WSIZE; + lencode = Z_NULL; + distcode = Z_NULL; + + /* Inflate until end of block marked as last */ + for (;;) + switch (mode) { + case TYPE: + /* determine and dispatch block type */ + if (lastblock) { + BYTEBITS(); + mode = DONE; + break; + } + NEEDBITS(3); + lastblock = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + lastblock ? " (last)" : "")); + mode = STORED; + break; + case 1: /* fixed block */ + lencode = lenfix; + lenbits = 9; + distcode = distfix; + distbits = 5; + Tracev((stderr, "inflate: fixed codes block%s\n", + lastblock ? " (last)" : "")); + mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + lastblock ? " (last)" : "")); + mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + mode = BAD; + break; + } + length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %lu\n", + length)); + INITBITS(); + + /* copy stored block from input to output */ + while (length != 0) { + copy = length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); + if (state->nlen > 286) { + strm->msg = (char *)"too many length symbols"; + mode = BAD; + break; + } + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + lencode = (code const FAR *)(state->next); + lenbits = 7; + ret = inflate_table9(CODES, state->lens, 19, &(state->next), + &(lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = lencode[BITS(lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + NEEDBITS(here.bits); + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftree9.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + lencode = (code const FAR *)(state->next); + lenbits = 9; + ret = inflate_table9(LENS, state->lens, state->nlen, + &(state->next), &(lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + mode = BAD; + break; + } + distcode = (code const FAR *)(state->next); + distbits = 6; + ret = inflate_table9(DISTS, state->lens + state->nlen, + state->ndist, &(state->next), &(distbits), + state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + mode = LEN; + + case LEN: + /* get a literal, length, or end-of-block code */ + for (;;) { + here = lencode[BITS(lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + length = (unsigned)here.val; + + /* process literal */ + if (here.op == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + ROOM(); + *put++ = (unsigned char)(length); + left--; + mode = LEN; + break; + } + + /* process end of block */ + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + mode = TYPE; + break; + } + + /* invalid code */ + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + extra = (unsigned)(here.op) & 31; + if (extra != 0) { + NEEDBITS(extra); + length += BITS(extra); + DROPBITS(extra); + } + Tracevv((stderr, "inflate: length %lu\n", length)); + + /* get distance code */ + for (;;) { + here = distcode[BITS(distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + mode = BAD; + break; + } + offset = (unsigned)here.val; + + /* get distance extra bits, if any */ + extra = (unsigned)(here.op) & 15; + if (extra != 0) { + NEEDBITS(extra); + offset += BITS(extra); + DROPBITS(extra); + } + if (offset > WSIZE - (wrap ? 0: left)) { + strm->msg = (char *)"invalid distance too far back"; + mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %lu\n", offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = WSIZE - offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - offset; + copy = left; + } + if (copy > length) copy = length; + length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < WSIZE) { + if (out(out_desc, window, (unsigned)(WSIZE - left))) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBack9End(strm) +z_stream FAR *strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/zlib-1.2.11/contrib/infback9/infback9.h b/zlib-1.2.11/contrib/infback9/infback9.h new file mode 100644 index 00000000..1073c0a3 --- /dev/null +++ b/zlib-1.2.11/contrib/infback9/infback9.h @@ -0,0 +1,37 @@ +/* infback9.h -- header for using inflateBack9 functions + * Copyright (C) 2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * This header file and associated patches provide a decoder for PKWare's + * undocumented deflate64 compression method (method 9). Use with infback9.c, + * inftree9.h, inftree9.c, and inffix9.h. These patches are not supported. + * This should be compiled with zlib, since it uses zutil.h and zutil.o. + * This code has not yet been tested on 16-bit architectures. See the + * comments in zlib.h for inflateBack() usage. These functions are used + * identically, except that there is no windowBits parameter, and a 64K + * window must be provided. Also if int's are 16 bits, then a zero for + * the third parameter of the "out" function actually means 65536UL. + * zlib.h must be included before this header file. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +ZEXTERN int ZEXPORT inflateBack9End OF((z_stream FAR *strm)); +ZEXTERN int ZEXPORT inflateBack9Init_ OF((z_stream FAR *strm, + unsigned char FAR *window, + const char *version, + int stream_size)); +#define inflateBack9Init(strm, window) \ + inflateBack9Init_((strm), (window), \ + ZLIB_VERSION, sizeof(z_stream)) + +#ifdef __cplusplus +} +#endif diff --git a/zlib-1.2.11/contrib/infback9/inffix9.h b/zlib-1.2.11/contrib/infback9/inffix9.h new file mode 100644 index 00000000..ee5671d2 --- /dev/null +++ b/zlib-1.2.11/contrib/infback9/inffix9.h @@ -0,0 +1,107 @@ + /* inffix9.h -- table for decoding deflate64 fixed codes + * Generated automatically by makefixed9(). + */ + + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{132,8,115},{130,7,31},{0,8,112}, + {0,8,48},{0,9,192},{128,7,10},{0,8,96},{0,8,32},{0,9,160}, + {0,8,0},{0,8,128},{0,8,64},{0,9,224},{128,7,6},{0,8,88}, + {0,8,24},{0,9,144},{131,7,59},{0,8,120},{0,8,56},{0,9,208}, + {129,7,17},{0,8,104},{0,8,40},{0,9,176},{0,8,8},{0,8,136}, + {0,8,72},{0,9,240},{128,7,4},{0,8,84},{0,8,20},{133,8,227}, + {131,7,43},{0,8,116},{0,8,52},{0,9,200},{129,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232}, + {128,7,8},{0,8,92},{0,8,28},{0,9,152},{132,7,83},{0,8,124}, + {0,8,60},{0,9,216},{130,7,23},{0,8,108},{0,8,44},{0,9,184}, + {0,8,12},{0,8,140},{0,8,76},{0,9,248},{128,7,3},{0,8,82}, + {0,8,18},{133,8,163},{131,7,35},{0,8,114},{0,8,50},{0,9,196}, + {129,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},{0,8,130}, + {0,8,66},{0,9,228},{128,7,7},{0,8,90},{0,8,26},{0,9,148}, + {132,7,67},{0,8,122},{0,8,58},{0,9,212},{130,7,19},{0,8,106}, + {0,8,42},{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244}, + {128,7,5},{0,8,86},{0,8,22},{65,8,0},{131,7,51},{0,8,118}, + {0,8,54},{0,9,204},{129,7,15},{0,8,102},{0,8,38},{0,9,172}, + {0,8,6},{0,8,134},{0,8,70},{0,9,236},{128,7,9},{0,8,94}, + {0,8,30},{0,9,156},{132,7,99},{0,8,126},{0,8,62},{0,9,220}, + {130,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{133,8,131}, + {130,7,31},{0,8,113},{0,8,49},{0,9,194},{128,7,10},{0,8,97}, + {0,8,33},{0,9,162},{0,8,1},{0,8,129},{0,8,65},{0,9,226}, + {128,7,6},{0,8,89},{0,8,25},{0,9,146},{131,7,59},{0,8,121}, + {0,8,57},{0,9,210},{129,7,17},{0,8,105},{0,8,41},{0,9,178}, + {0,8,9},{0,8,137},{0,8,73},{0,9,242},{128,7,4},{0,8,85}, + {0,8,21},{144,8,3},{131,7,43},{0,8,117},{0,8,53},{0,9,202}, + {129,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133}, + {0,8,69},{0,9,234},{128,7,8},{0,8,93},{0,8,29},{0,9,154}, + {132,7,83},{0,8,125},{0,8,61},{0,9,218},{130,7,23},{0,8,109}, + {0,8,45},{0,9,186},{0,8,13},{0,8,141},{0,8,77},{0,9,250}, + {128,7,3},{0,8,83},{0,8,19},{133,8,195},{131,7,35},{0,8,115}, + {0,8,51},{0,9,198},{129,7,11},{0,8,99},{0,8,35},{0,9,166}, + {0,8,3},{0,8,131},{0,8,67},{0,9,230},{128,7,7},{0,8,91}, + {0,8,27},{0,9,150},{132,7,67},{0,8,123},{0,8,59},{0,9,214}, + {130,7,19},{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139}, + {0,8,75},{0,9,246},{128,7,5},{0,8,87},{0,8,23},{77,8,0}, + {131,7,51},{0,8,119},{0,8,55},{0,9,206},{129,7,15},{0,8,103}, + {0,8,39},{0,9,174},{0,8,7},{0,8,135},{0,8,71},{0,9,238}, + {128,7,9},{0,8,95},{0,8,31},{0,9,158},{132,7,99},{0,8,127}, + {0,8,63},{0,9,222},{130,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80}, + {0,8,16},{132,8,115},{130,7,31},{0,8,112},{0,8,48},{0,9,193}, + {128,7,10},{0,8,96},{0,8,32},{0,9,161},{0,8,0},{0,8,128}, + {0,8,64},{0,9,225},{128,7,6},{0,8,88},{0,8,24},{0,9,145}, + {131,7,59},{0,8,120},{0,8,56},{0,9,209},{129,7,17},{0,8,104}, + {0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},{0,9,241}, + {128,7,4},{0,8,84},{0,8,20},{133,8,227},{131,7,43},{0,8,116}, + {0,8,52},{0,9,201},{129,7,13},{0,8,100},{0,8,36},{0,9,169}, + {0,8,4},{0,8,132},{0,8,68},{0,9,233},{128,7,8},{0,8,92}, + {0,8,28},{0,9,153},{132,7,83},{0,8,124},{0,8,60},{0,9,217}, + {130,7,23},{0,8,108},{0,8,44},{0,9,185},{0,8,12},{0,8,140}, + {0,8,76},{0,9,249},{128,7,3},{0,8,82},{0,8,18},{133,8,163}, + {131,7,35},{0,8,114},{0,8,50},{0,9,197},{129,7,11},{0,8,98}, + {0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {128,7,7},{0,8,90},{0,8,26},{0,9,149},{132,7,67},{0,8,122}, + {0,8,58},{0,9,213},{130,7,19},{0,8,106},{0,8,42},{0,9,181}, + {0,8,10},{0,8,138},{0,8,74},{0,9,245},{128,7,5},{0,8,86}, + {0,8,22},{65,8,0},{131,7,51},{0,8,118},{0,8,54},{0,9,205}, + {129,7,15},{0,8,102},{0,8,38},{0,9,173},{0,8,6},{0,8,134}, + {0,8,70},{0,9,237},{128,7,9},{0,8,94},{0,8,30},{0,9,157}, + {132,7,99},{0,8,126},{0,8,62},{0,9,221},{130,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253}, + {96,7,0},{0,8,81},{0,8,17},{133,8,131},{130,7,31},{0,8,113}, + {0,8,49},{0,9,195},{128,7,10},{0,8,97},{0,8,33},{0,9,163}, + {0,8,1},{0,8,129},{0,8,65},{0,9,227},{128,7,6},{0,8,89}, + {0,8,25},{0,9,147},{131,7,59},{0,8,121},{0,8,57},{0,9,211}, + {129,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},{0,8,137}, + {0,8,73},{0,9,243},{128,7,4},{0,8,85},{0,8,21},{144,8,3}, + {131,7,43},{0,8,117},{0,8,53},{0,9,203},{129,7,13},{0,8,101}, + {0,8,37},{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235}, + {128,7,8},{0,8,93},{0,8,29},{0,9,155},{132,7,83},{0,8,125}, + {0,8,61},{0,9,219},{130,7,23},{0,8,109},{0,8,45},{0,9,187}, + {0,8,13},{0,8,141},{0,8,77},{0,9,251},{128,7,3},{0,8,83}, + {0,8,19},{133,8,195},{131,7,35},{0,8,115},{0,8,51},{0,9,199}, + {129,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{128,7,7},{0,8,91},{0,8,27},{0,9,151}, + {132,7,67},{0,8,123},{0,8,59},{0,9,215},{130,7,19},{0,8,107}, + {0,8,43},{0,9,183},{0,8,11},{0,8,139},{0,8,75},{0,9,247}, + {128,7,5},{0,8,87},{0,8,23},{77,8,0},{131,7,51},{0,8,119}, + {0,8,55},{0,9,207},{129,7,15},{0,8,103},{0,8,39},{0,9,175}, + {0,8,7},{0,8,135},{0,8,71},{0,9,239},{128,7,9},{0,8,95}, + {0,8,31},{0,9,159},{132,7,99},{0,8,127},{0,8,63},{0,9,223}, + {130,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143}, + {0,8,79},{0,9,255} + }; + + static const code distfix[32] = { + {128,5,1},{135,5,257},{131,5,17},{139,5,4097},{129,5,5}, + {137,5,1025},{133,5,65},{141,5,16385},{128,5,3},{136,5,513}, + {132,5,33},{140,5,8193},{130,5,9},{138,5,2049},{134,5,129}, + {142,5,32769},{128,5,2},{135,5,385},{131,5,25},{139,5,6145}, + {129,5,7},{137,5,1537},{133,5,97},{141,5,24577},{128,5,4}, + {136,5,769},{132,5,49},{140,5,12289},{130,5,13},{138,5,3073}, + {134,5,193},{142,5,49153} + }; diff --git a/zlib-1.2.11/contrib/infback9/inflate9.h b/zlib-1.2.11/contrib/infback9/inflate9.h new file mode 100644 index 00000000..ee9a7939 --- /dev/null +++ b/zlib-1.2.11/contrib/infback9/inflate9.h @@ -0,0 +1,47 @@ +/* inflate9.h -- internal inflate state definition + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Possible inflate modes between inflate() calls */ +typedef enum { + TYPE, /* i: waiting for type bits, including last-flag bit */ + STORED, /* i: waiting for stored size (length and complement) */ + TABLE, /* i: waiting for dynamic block table lengths */ + LEN, /* i: waiting for length/lit code */ + DONE, /* finished check, done -- remain here until reset */ + BAD /* got a data error -- remain here until reset */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to the BAD mode -- not shown for clarity) + + Read deflate blocks: + TYPE -> STORED or TABLE or LEN or DONE + STORED -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN + Read deflate codes: + LEN -> LEN or TYPE + */ + +/* state maintained between inflate() calls. Approximately 7K bytes. */ +struct inflate_state { + /* sliding window */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ +}; diff --git a/zlib-1.2.11/contrib/infback9/inftree9.c b/zlib-1.2.11/contrib/infback9/inftree9.c new file mode 100644 index 00000000..5f4a7679 --- /dev/null +++ b/zlib-1.2.11/contrib/infback9/inftree9.c @@ -0,0 +1,324 @@ +/* inftree9.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftree9.h" + +#define MAXBITS 15 + +const char inflate9_copyright[] = + " inflate9 1.2.11 Copyright 1995-2017 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int inflate_table9(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code this; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + int end; /* use base and extra for symbol > end */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, + 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, + 131, 163, 195, 227, 3, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, + 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132, + 133, 133, 133, 133, 144, 77, 202}; + static const unsigned short dbase[32] = { /* Distance codes 0..31 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, + 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, + 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153}; + static const unsigned short dext[32] = { /* Distance codes 0..31 extra */ + 128, 128, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, + 133, 133, 134, 134, 135, 135, 136, 136, 137, 137, 138, 138, + 139, 139, 140, 140, 141, 141, 142, 142}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) return -1; /* no codes! */ + for (min = 1; min <= MAXBITS; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftree9.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + end = 19; + break; + case LENS: + base = lbase; + base -= 257; + extra = lext; + extra -= 257; + end = 256; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + this.bits = (unsigned char)(len - drop); + if ((int)(work[sym]) < end) { + this.op = (unsigned char)0; + this.val = work[sym]; + } + else if ((int)(work[sym]) > end) { + this.op = (unsigned char)(extra[work[sym]]); + this.val = base[work[sym]]; + } + else { + this.op = (unsigned char)(32 + 64); /* end of block */ + this.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + do { + fill -= incr; + next[(huff >> drop) + fill] = this; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += 1U << curr; + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used >= ENOUGH_LENS) || + (type == DISTS && used >= ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* + Fill in rest of table for incomplete codes. This loop is similar to the + loop above in incrementing huff for table indices. It is assumed that + len is equal to curr + drop, so there is no loop needed to increment + through high index bits. When the current sub-table is filled, the loop + drops back to the root table to fill in any remaining entries there. + */ + this.op = (unsigned char)64; /* invalid code marker */ + this.bits = (unsigned char)(len - drop); + this.val = (unsigned short)0; + while (huff != 0) { + /* when done with sub-table, drop back to root table */ + if (drop != 0 && (huff & mask) != low) { + drop = 0; + len = root; + next = *table; + curr = root; + this.bits = (unsigned char)len; + } + + /* put invalid code marker in table */ + next[huff >> drop] = this; + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/zlib-1.2.11/contrib/infback9/inftree9.h b/zlib-1.2.11/contrib/infback9/inftree9.h new file mode 100644 index 00000000..5ab21f0c --- /dev/null +++ b/zlib-1.2.11/contrib/infback9/inftree9.h @@ -0,0 +1,61 @@ +/* inftree9.h -- header to use inftree9.c + * Copyright (C) 1995-2008 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 100eeeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1446, which is the sum of 852 for literal/length codes and 594 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 32 6 15" for distance codes returns 594. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in infback9.c. If the root table size is changed, + then these maximum sizes would be need to be recalculated and updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 594 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table9() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +extern int inflate_table9 OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/zlib-1.2.11/contrib/inflate86/inffas86.c b/zlib-1.2.11/contrib/inflate86/inffas86.c new file mode 100644 index 00000000..7292f67b --- /dev/null +++ b/zlib-1.2.11/contrib/inflate86/inffas86.c @@ -0,0 +1,1157 @@ +/* inffas86.c is a hand tuned assembler version of + * + * inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Copyright (C) 2003 Chris Anderson + * Please use the copyright conditions above. + * + * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also + * slightly quicker on x86 systems because, instead of using rep movsb to copy + * data, it uses rep movsw, which moves data in 2-byte chunks instead of single + * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates + * from http://fedora.linux.duke.edu/fc1_x86_64 + * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with + * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, + * when decompressing mozilla-source-1.3.tar.gz. + * + * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from + * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at + * the moment. I have successfully compiled and tested this code with gcc2.96, + * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S + * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX + * enabled. I will attempt to merge the MMX code into this version. Newer + * versions of this and inffast.S can be found at + * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* Mark Adler's comments from inffast.c: */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + struct inffast_ar { +/* 64 32 x86 x86_64 */ +/* ar offset register */ +/* 0 0 */ void *esp; /* esp save */ +/* 8 4 */ void *ebp; /* ebp save */ +/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ +/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ +/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ +/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ +/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ +/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ +/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ +/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ +/* 80 40 */ unsigned long hold; /* edx rdx local strm->hold */ +/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ +/* 92 48 */ unsigned wsize; /* window size */ +/* 96 52 */ unsigned write; /* window write index */ +/*100 56 */ unsigned lmask; /* r12 mask for lcode */ +/*104 60 */ unsigned dmask; /* r13 mask for dcode */ +/*108 64 */ unsigned len; /* r14 match length */ +/*112 68 */ unsigned dist; /* r15 match distance */ +/*116 72 */ unsigned status; /* set when state chng*/ + } ar; + +#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) +#define PAD_AVAIL_IN 6 +#define PAD_AVAIL_OUT 258 +#else +#define PAD_AVAIL_IN 5 +#define PAD_AVAIL_OUT 257 +#endif + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + ar.in = strm->next_in; + ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); + ar.out = strm->next_out; + ar.beg = ar.out - (start - strm->avail_out); + ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); + ar.wsize = state->wsize; + ar.write = state->wnext; + ar.window = state->window; + ar.hold = state->hold; + ar.bits = state->bits; + ar.lcode = state->lencode; + ar.dcode = state->distcode; + ar.lmask = (1U << state->lenbits) - 1; + ar.dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + /* align in on 1/2 hold size boundary */ + while (((unsigned long)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { + ar.hold += (unsigned long)*ar.in++ << ar.bits; + ar.bits += 8; + } + +#if defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 ) + __asm__ __volatile__ ( +" leaq %0, %%rax\n" +" movq %%rbp, 8(%%rax)\n" /* save regs rbp and rsp */ +" movq %%rsp, (%%rax)\n" +" movq %%rax, %%rsp\n" /* make rsp point to &ar */ +" movq 16(%%rsp), %%rsi\n" /* rsi = in */ +" movq 32(%%rsp), %%rdi\n" /* rdi = out */ +" movq 24(%%rsp), %%r9\n" /* r9 = last */ +" movq 48(%%rsp), %%r10\n" /* r10 = end */ +" movq 64(%%rsp), %%rbp\n" /* rbp = lcode */ +" movq 72(%%rsp), %%r11\n" /* r11 = dcode */ +" movq 80(%%rsp), %%rdx\n" /* rdx = hold */ +" movl 88(%%rsp), %%ebx\n" /* ebx = bits */ +" movl 100(%%rsp), %%r12d\n" /* r12d = lmask */ +" movl 104(%%rsp), %%r13d\n" /* r13d = dmask */ + /* r14d = len */ + /* r15d = dist */ +" cld\n" +" cmpq %%rdi, %%r10\n" +" je .L_one_time\n" /* if only one decode left */ +" cmpq %%rsi, %%r9\n" +" je .L_one_time\n" +" jmp .L_do_loop\n" + +".L_one_time:\n" +" movq %%r12, %%r8\n" /* r8 = lmask */ +" cmpb $32, %%bl\n" +" ja .L_get_length_code_one_time\n" + +" lodsl\n" /* eax = *(uint *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $32, %%bl\n" /* bits += 32 */ +" shlq %%cl, %%rax\n" +" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ +" jmp .L_get_length_code_one_time\n" + +".align 32,0x90\n" +".L_while_test:\n" +" cmpq %%rdi, %%r10\n" +" jbe .L_break_loop\n" +" cmpq %%rsi, %%r9\n" +" jbe .L_break_loop\n" + +".L_do_loop:\n" +" movq %%r12, %%r8\n" /* r8 = lmask */ +" cmpb $32, %%bl\n" +" ja .L_get_length_code\n" /* if (32 < bits) */ + +" lodsl\n" /* eax = *(uint *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $32, %%bl\n" /* bits += 32 */ +" shlq %%cl, %%rax\n" +" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ + +".L_get_length_code:\n" +" andq %%rdx, %%r8\n" /* r8 &= hold */ +" movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ + +" movb %%ah, %%cl\n" /* cl = this.bits */ +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ + +" testb %%al, %%al\n" +" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ + +" movq %%r12, %%r8\n" /* r8 = lmask */ +" shrl $16, %%eax\n" /* output this.val char */ +" stosb\n" + +".L_get_length_code_one_time:\n" +" andq %%rdx, %%r8\n" /* r8 &= hold */ +" movl (%%rbp,%%r8,4), %%eax\n" /* eax = lcode[hold & lmask] */ + +".L_dolen:\n" +" movb %%ah, %%cl\n" /* cl = this.bits */ +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ + +" testb %%al, %%al\n" +" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ + +" shrl $16, %%eax\n" /* output this.val char */ +" stosb\n" +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_test_for_length_base:\n" +" movl %%eax, %%r14d\n" /* len = this */ +" shrl $16, %%r14d\n" /* len = this.val */ +" movb %%al, %%cl\n" + +" testb $16, %%al\n" +" jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ +" andb $15, %%cl\n" /* op &= 15 */ +" jz .L_decode_distance\n" /* if (!op) */ + +".L_add_bits_to_len:\n" +" subb %%cl, %%bl\n" +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" shrq %%cl, %%rdx\n" +" addl %%eax, %%r14d\n" /* len += hold & mask[op] */ + +".L_decode_distance:\n" +" movq %%r13, %%r8\n" /* r8 = dmask */ +" cmpb $32, %%bl\n" +" ja .L_get_distance_code\n" /* if (32 < bits) */ + +" lodsl\n" /* eax = *(uint *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $32, %%bl\n" /* bits += 32 */ +" shlq %%cl, %%rax\n" +" orq %%rax, %%rdx\n" /* hold |= *((uint *)in)++ << bits */ + +".L_get_distance_code:\n" +" andq %%rdx, %%r8\n" /* r8 &= hold */ +" movl (%%r11,%%r8,4), %%eax\n" /* eax = dcode[hold & dmask] */ + +".L_dodist:\n" +" movl %%eax, %%r15d\n" /* dist = this */ +" shrl $16, %%r15d\n" /* dist = this.val */ +" movb %%ah, %%cl\n" +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrq %%cl, %%rdx\n" /* hold >>= this.bits */ +" movb %%al, %%cl\n" /* cl = this.op */ + +" testb $16, %%al\n" /* if ((op & 16) == 0) */ +" jz .L_test_for_second_level_dist\n" +" andb $15, %%cl\n" /* op &= 15 */ +" jz .L_check_dist_one\n" + +".L_add_bits_to_dist:\n" +" subb %%cl, %%bl\n" +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" /* (1 << op) - 1 */ +" andl %%edx, %%eax\n" /* eax &= hold */ +" shrq %%cl, %%rdx\n" +" addl %%eax, %%r15d\n" /* dist += hold & ((1 << op) - 1) */ + +".L_check_window:\n" +" movq %%rsi, %%r8\n" /* save in so from can use it's reg */ +" movq %%rdi, %%rax\n" +" subq 40(%%rsp), %%rax\n" /* nbytes = out - beg */ + +" cmpl %%r15d, %%eax\n" +" jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ + +" movl %%r14d, %%ecx\n" /* ecx = len */ +" movq %%rdi, %%rsi\n" +" subq %%r15, %%rsi\n" /* from = out - dist */ + +" sarl %%ecx\n" +" jnc .L_copy_two\n" /* if len % 2 == 0 */ + +" rep movsw\n" +" movb (%%rsi), %%al\n" +" movb %%al, (%%rdi)\n" +" incq %%rdi\n" + +" movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ +" jmp .L_while_test\n" + +".L_copy_two:\n" +" rep movsw\n" +" movq %%r8, %%rsi\n" /* move in back to %rsi, toss from */ +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_check_dist_one:\n" +" cmpl $1, %%r15d\n" /* if dist 1, is a memset */ +" jne .L_check_window\n" +" cmpq %%rdi, 40(%%rsp)\n" /* if out == beg, outside window */ +" je .L_check_window\n" + +" movl %%r14d, %%ecx\n" /* ecx = len */ +" movb -1(%%rdi), %%al\n" +" movb %%al, %%ah\n" + +" sarl %%ecx\n" +" jnc .L_set_two\n" +" movb %%al, (%%rdi)\n" +" incq %%rdi\n" + +".L_set_two:\n" +" rep stosw\n" +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_test_for_second_level_length:\n" +" testb $64, %%al\n" +" jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ + +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" addl %%r14d, %%eax\n" /* eax += len */ +" movl (%%rbp,%%rax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ +" jmp .L_dolen\n" + +".align 32,0x90\n" +".L_test_for_second_level_dist:\n" +" testb $64, %%al\n" +" jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ + +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" addl %%r15d, %%eax\n" /* eax += dist */ +" movl (%%r11,%%rax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ +" jmp .L_dodist\n" + +".align 32,0x90\n" +".L_clip_window:\n" +" movl %%eax, %%ecx\n" /* ecx = nbytes */ +" movl 92(%%rsp), %%eax\n" /* eax = wsize, prepare for dist cmp */ +" negl %%ecx\n" /* nbytes = -nbytes */ + +" cmpl %%r15d, %%eax\n" +" jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ + +" addl %%r15d, %%ecx\n" /* nbytes = dist - nbytes */ +" cmpl $0, 96(%%rsp)\n" +" jne .L_wrap_around_window\n" /* if (write != 0) */ + +" movq 56(%%rsp), %%rsi\n" /* from = window */ +" subl %%ecx, %%eax\n" /* eax -= nbytes */ +" addq %%rax, %%rsi\n" /* from += wsize - nbytes */ + +" movl %%r14d, %%eax\n" /* eax = len */ +" cmpl %%ecx, %%r14d\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* eax -= nbytes */ +" rep movsb\n" +" movq %%rdi, %%rsi\n" +" subq %%r15, %%rsi\n" /* from = &out[ -dist ] */ +" jmp .L_do_copy\n" + +".align 32,0x90\n" +".L_wrap_around_window:\n" +" movl 96(%%rsp), %%eax\n" /* eax = write */ +" cmpl %%eax, %%ecx\n" +" jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ + +" movl 92(%%rsp), %%esi\n" /* from = wsize */ +" addq 56(%%rsp), %%rsi\n" /* from += window */ +" addq %%rax, %%rsi\n" /* from += write */ +" subq %%rcx, %%rsi\n" /* from -= nbytes */ +" subl %%eax, %%ecx\n" /* nbytes -= write */ + +" movl %%r14d, %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movq 56(%%rsp), %%rsi\n" /* from = window */ +" movl 96(%%rsp), %%ecx\n" /* nbytes = write */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movq %%rdi, %%rsi\n" +" subq %%r15, %%rsi\n" /* from = out - dist */ +" jmp .L_do_copy\n" + +".align 32,0x90\n" +".L_contiguous_in_window:\n" +" movq 56(%%rsp), %%rsi\n" /* rsi = window */ +" addq %%rax, %%rsi\n" +" subq %%rcx, %%rsi\n" /* from += write - nbytes */ + +" movl %%r14d, %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movq %%rdi, %%rsi\n" +" subq %%r15, %%rsi\n" /* from = out - dist */ +" jmp .L_do_copy\n" /* if (nbytes >= len) */ + +".align 32,0x90\n" +".L_do_copy:\n" +" movl %%eax, %%ecx\n" /* ecx = len */ +" rep movsb\n" + +" movq %%r8, %%rsi\n" /* move in back to %esi, toss from */ +" jmp .L_while_test\n" + +".L_test_for_end_of_block:\n" +" testb $32, %%al\n" +" jz .L_invalid_literal_length_code\n" +" movl $1, 116(%%rsp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_literal_length_code:\n" +" movl $2, 116(%%rsp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_distance_code:\n" +" movl $3, 116(%%rsp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_distance_too_far:\n" +" movl $4, 116(%%rsp)\n" +" jmp .L_break_loop_with_status\n" + +".L_break_loop:\n" +" movl $0, 116(%%rsp)\n" + +".L_break_loop_with_status:\n" +/* put in, out, bits, and hold back into ar and pop esp */ +" movq %%rsi, 16(%%rsp)\n" /* in */ +" movq %%rdi, 32(%%rsp)\n" /* out */ +" movl %%ebx, 88(%%rsp)\n" /* bits */ +" movq %%rdx, 80(%%rsp)\n" /* hold */ +" movq (%%rsp), %%rax\n" /* restore rbp and rsp */ +" movq 8(%%rsp), %%rbp\n" +" movq %%rax, %%rsp\n" + : + : "m" (ar) + : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" + ); +#elif ( defined( __GNUC__ ) || defined( __ICC ) ) && defined( __i386 ) + __asm__ __volatile__ ( +" leal %0, %%eax\n" +" movl %%esp, (%%eax)\n" /* save esp, ebp */ +" movl %%ebp, 4(%%eax)\n" +" movl %%eax, %%esp\n" +" movl 8(%%esp), %%esi\n" /* esi = in */ +" movl 16(%%esp), %%edi\n" /* edi = out */ +" movl 40(%%esp), %%edx\n" /* edx = hold */ +" movl 44(%%esp), %%ebx\n" /* ebx = bits */ +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ + +" cld\n" +" jmp .L_do_loop\n" + +".align 32,0x90\n" +".L_while_test:\n" +" cmpl %%edi, 24(%%esp)\n" /* out < end */ +" jbe .L_break_loop\n" +" cmpl %%esi, 12(%%esp)\n" /* in < last */ +" jbe .L_break_loop\n" + +".L_do_loop:\n" +" cmpb $15, %%bl\n" +" ja .L_get_length_code\n" /* if (15 < bits) */ + +" xorl %%eax, %%eax\n" +" lodsw\n" /* al = *(ushort *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $16, %%bl\n" /* bits += 16 */ +" shll %%cl, %%eax\n" +" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ + +".L_get_length_code:\n" +" movl 56(%%esp), %%eax\n" /* eax = lmask */ +" andl %%edx, %%eax\n" /* eax &= hold */ +" movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[hold & lmask] */ + +".L_dolen:\n" +" movb %%ah, %%cl\n" /* cl = this.bits */ +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrl %%cl, %%edx\n" /* hold >>= this.bits */ + +" testb %%al, %%al\n" +" jnz .L_test_for_length_base\n" /* if (op != 0) 45.7% */ + +" shrl $16, %%eax\n" /* output this.val char */ +" stosb\n" +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_test_for_length_base:\n" +" movl %%eax, %%ecx\n" /* len = this */ +" shrl $16, %%ecx\n" /* len = this.val */ +" movl %%ecx, 64(%%esp)\n" /* save len */ +" movb %%al, %%cl\n" + +" testb $16, %%al\n" +" jz .L_test_for_second_level_length\n" /* if ((op & 16) == 0) 8% */ +" andb $15, %%cl\n" /* op &= 15 */ +" jz .L_decode_distance\n" /* if (!op) */ +" cmpb %%cl, %%bl\n" +" jae .L_add_bits_to_len\n" /* if (op <= bits) */ + +" movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ +" xorl %%eax, %%eax\n" +" lodsw\n" /* al = *(ushort *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $16, %%bl\n" /* bits += 16 */ +" shll %%cl, %%eax\n" +" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ +" movb %%ch, %%cl\n" /* move op back to ecx */ + +".L_add_bits_to_len:\n" +" subb %%cl, %%bl\n" +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" shrl %%cl, %%edx\n" +" addl %%eax, 64(%%esp)\n" /* len += hold & mask[op] */ + +".L_decode_distance:\n" +" cmpb $15, %%bl\n" +" ja .L_get_distance_code\n" /* if (15 < bits) */ + +" xorl %%eax, %%eax\n" +" lodsw\n" /* al = *(ushort *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $16, %%bl\n" /* bits += 16 */ +" shll %%cl, %%eax\n" +" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ + +".L_get_distance_code:\n" +" movl 60(%%esp), %%eax\n" /* eax = dmask */ +" movl 36(%%esp), %%ecx\n" /* ecx = dcode */ +" andl %%edx, %%eax\n" /* eax &= hold */ +" movl (%%ecx,%%eax,4), %%eax\n"/* eax = dcode[hold & dmask] */ + +".L_dodist:\n" +" movl %%eax, %%ebp\n" /* dist = this */ +" shrl $16, %%ebp\n" /* dist = this.val */ +" movb %%ah, %%cl\n" +" subb %%ah, %%bl\n" /* bits -= this.bits */ +" shrl %%cl, %%edx\n" /* hold >>= this.bits */ +" movb %%al, %%cl\n" /* cl = this.op */ + +" testb $16, %%al\n" /* if ((op & 16) == 0) */ +" jz .L_test_for_second_level_dist\n" +" andb $15, %%cl\n" /* op &= 15 */ +" jz .L_check_dist_one\n" +" cmpb %%cl, %%bl\n" +" jae .L_add_bits_to_dist\n" /* if (op <= bits) 97.6% */ + +" movb %%cl, %%ch\n" /* stash op in ch, freeing cl */ +" xorl %%eax, %%eax\n" +" lodsw\n" /* al = *(ushort *)in++ */ +" movb %%bl, %%cl\n" /* cl = bits, needs it for shifting */ +" addb $16, %%bl\n" /* bits += 16 */ +" shll %%cl, %%eax\n" +" orl %%eax, %%edx\n" /* hold |= *((ushort *)in)++ << bits */ +" movb %%ch, %%cl\n" /* move op back to ecx */ + +".L_add_bits_to_dist:\n" +" subb %%cl, %%bl\n" +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" /* (1 << op) - 1 */ +" andl %%edx, %%eax\n" /* eax &= hold */ +" shrl %%cl, %%edx\n" +" addl %%eax, %%ebp\n" /* dist += hold & ((1 << op) - 1) */ + +".L_check_window:\n" +" movl %%esi, 8(%%esp)\n" /* save in so from can use it's reg */ +" movl %%edi, %%eax\n" +" subl 20(%%esp), %%eax\n" /* nbytes = out - beg */ + +" cmpl %%ebp, %%eax\n" +" jb .L_clip_window\n" /* if (dist > nbytes) 4.2% */ + +" movl 64(%%esp), %%ecx\n" /* ecx = len */ +" movl %%edi, %%esi\n" +" subl %%ebp, %%esi\n" /* from = out - dist */ + +" sarl %%ecx\n" +" jnc .L_copy_two\n" /* if len % 2 == 0 */ + +" rep movsw\n" +" movb (%%esi), %%al\n" +" movb %%al, (%%edi)\n" +" incl %%edi\n" + +" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ +" jmp .L_while_test\n" + +".L_copy_two:\n" +" rep movsw\n" +" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_check_dist_one:\n" +" cmpl $1, %%ebp\n" /* if dist 1, is a memset */ +" jne .L_check_window\n" +" cmpl %%edi, 20(%%esp)\n" +" je .L_check_window\n" /* out == beg, if outside window */ + +" movl 64(%%esp), %%ecx\n" /* ecx = len */ +" movb -1(%%edi), %%al\n" +" movb %%al, %%ah\n" + +" sarl %%ecx\n" +" jnc .L_set_two\n" +" movb %%al, (%%edi)\n" +" incl %%edi\n" + +".L_set_two:\n" +" rep stosw\n" +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ +" jmp .L_while_test\n" + +".align 32,0x90\n" +".L_test_for_second_level_length:\n" +" testb $64, %%al\n" +" jnz .L_test_for_end_of_block\n" /* if ((op & 64) != 0) */ + +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" addl 64(%%esp), %%eax\n" /* eax += len */ +" movl (%%ebp,%%eax,4), %%eax\n" /* eax = lcode[val+(hold&mask[op])]*/ +" jmp .L_dolen\n" + +".align 32,0x90\n" +".L_test_for_second_level_dist:\n" +" testb $64, %%al\n" +" jnz .L_invalid_distance_code\n" /* if ((op & 64) != 0) */ + +" xorl %%eax, %%eax\n" +" incl %%eax\n" +" shll %%cl, %%eax\n" +" decl %%eax\n" +" andl %%edx, %%eax\n" /* eax &= hold */ +" addl %%ebp, %%eax\n" /* eax += dist */ +" movl 36(%%esp), %%ecx\n" /* ecx = dcode */ +" movl (%%ecx,%%eax,4), %%eax\n" /* eax = dcode[val+(hold&mask[op])]*/ +" jmp .L_dodist\n" + +".align 32,0x90\n" +".L_clip_window:\n" +" movl %%eax, %%ecx\n" +" movl 48(%%esp), %%eax\n" /* eax = wsize */ +" negl %%ecx\n" /* nbytes = -nbytes */ +" movl 28(%%esp), %%esi\n" /* from = window */ + +" cmpl %%ebp, %%eax\n" +" jb .L_invalid_distance_too_far\n" /* if (dist > wsize) */ + +" addl %%ebp, %%ecx\n" /* nbytes = dist - nbytes */ +" cmpl $0, 52(%%esp)\n" +" jne .L_wrap_around_window\n" /* if (write != 0) */ + +" subl %%ecx, %%eax\n" +" addl %%eax, %%esi\n" /* from += wsize - nbytes */ + +" movl 64(%%esp), %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movl %%edi, %%esi\n" +" subl %%ebp, %%esi\n" /* from = out - dist */ +" jmp .L_do_copy\n" + +".align 32,0x90\n" +".L_wrap_around_window:\n" +" movl 52(%%esp), %%eax\n" /* eax = write */ +" cmpl %%eax, %%ecx\n" +" jbe .L_contiguous_in_window\n" /* if (write >= nbytes) */ + +" addl 48(%%esp), %%esi\n" /* from += wsize */ +" addl %%eax, %%esi\n" /* from += write */ +" subl %%ecx, %%esi\n" /* from -= nbytes */ +" subl %%eax, %%ecx\n" /* nbytes -= write */ + +" movl 64(%%esp), %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movl 28(%%esp), %%esi\n" /* from = window */ +" movl 52(%%esp), %%ecx\n" /* nbytes = write */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movl %%edi, %%esi\n" +" subl %%ebp, %%esi\n" /* from = out - dist */ +" jmp .L_do_copy\n" + +".align 32,0x90\n" +".L_contiguous_in_window:\n" +" addl %%eax, %%esi\n" +" subl %%ecx, %%esi\n" /* from += write - nbytes */ + +" movl 64(%%esp), %%eax\n" /* eax = len */ +" cmpl %%ecx, %%eax\n" +" jbe .L_do_copy\n" /* if (nbytes >= len) */ + +" subl %%ecx, %%eax\n" /* len -= nbytes */ +" rep movsb\n" +" movl %%edi, %%esi\n" +" subl %%ebp, %%esi\n" /* from = out - dist */ +" jmp .L_do_copy\n" /* if (nbytes >= len) */ + +".align 32,0x90\n" +".L_do_copy:\n" +" movl %%eax, %%ecx\n" +" rep movsb\n" + +" movl 8(%%esp), %%esi\n" /* move in back to %esi, toss from */ +" movl 32(%%esp), %%ebp\n" /* ebp = lcode */ +" jmp .L_while_test\n" + +".L_test_for_end_of_block:\n" +" testb $32, %%al\n" +" jz .L_invalid_literal_length_code\n" +" movl $1, 72(%%esp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_literal_length_code:\n" +" movl $2, 72(%%esp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_distance_code:\n" +" movl $3, 72(%%esp)\n" +" jmp .L_break_loop_with_status\n" + +".L_invalid_distance_too_far:\n" +" movl 8(%%esp), %%esi\n" +" movl $4, 72(%%esp)\n" +" jmp .L_break_loop_with_status\n" + +".L_break_loop:\n" +" movl $0, 72(%%esp)\n" + +".L_break_loop_with_status:\n" +/* put in, out, bits, and hold back into ar and pop esp */ +" movl %%esi, 8(%%esp)\n" /* save in */ +" movl %%edi, 16(%%esp)\n" /* save out */ +" movl %%ebx, 44(%%esp)\n" /* save bits */ +" movl %%edx, 40(%%esp)\n" /* save hold */ +" movl 4(%%esp), %%ebp\n" /* restore esp, ebp */ +" movl (%%esp), %%esp\n" + : + : "m" (ar) + : "memory", "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi" + ); +#elif defined( _MSC_VER ) && ! defined( _M_AMD64 ) + __asm { + lea eax, ar + mov [eax], esp /* save esp, ebp */ + mov [eax+4], ebp + mov esp, eax + mov esi, [esp+8] /* esi = in */ + mov edi, [esp+16] /* edi = out */ + mov edx, [esp+40] /* edx = hold */ + mov ebx, [esp+44] /* ebx = bits */ + mov ebp, [esp+32] /* ebp = lcode */ + + cld + jmp L_do_loop + +ALIGN 4 +L_while_test: + cmp [esp+24], edi + jbe L_break_loop + cmp [esp+12], esi + jbe L_break_loop + +L_do_loop: + cmp bl, 15 + ja L_get_length_code /* if (15 < bits) */ + + xor eax, eax + lodsw /* al = *(ushort *)in++ */ + mov cl, bl /* cl = bits, needs it for shifting */ + add bl, 16 /* bits += 16 */ + shl eax, cl + or edx, eax /* hold |= *((ushort *)in)++ << bits */ + +L_get_length_code: + mov eax, [esp+56] /* eax = lmask */ + and eax, edx /* eax &= hold */ + mov eax, [ebp+eax*4] /* eax = lcode[hold & lmask] */ + +L_dolen: + mov cl, ah /* cl = this.bits */ + sub bl, ah /* bits -= this.bits */ + shr edx, cl /* hold >>= this.bits */ + + test al, al + jnz L_test_for_length_base /* if (op != 0) 45.7% */ + + shr eax, 16 /* output this.val char */ + stosb + jmp L_while_test + +ALIGN 4 +L_test_for_length_base: + mov ecx, eax /* len = this */ + shr ecx, 16 /* len = this.val */ + mov [esp+64], ecx /* save len */ + mov cl, al + + test al, 16 + jz L_test_for_second_level_length /* if ((op & 16) == 0) 8% */ + and cl, 15 /* op &= 15 */ + jz L_decode_distance /* if (!op) */ + cmp bl, cl + jae L_add_bits_to_len /* if (op <= bits) */ + + mov ch, cl /* stash op in ch, freeing cl */ + xor eax, eax + lodsw /* al = *(ushort *)in++ */ + mov cl, bl /* cl = bits, needs it for shifting */ + add bl, 16 /* bits += 16 */ + shl eax, cl + or edx, eax /* hold |= *((ushort *)in)++ << bits */ + mov cl, ch /* move op back to ecx */ + +L_add_bits_to_len: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx /* eax &= hold */ + shr edx, cl + add [esp+64], eax /* len += hold & mask[op] */ + +L_decode_distance: + cmp bl, 15 + ja L_get_distance_code /* if (15 < bits) */ + + xor eax, eax + lodsw /* al = *(ushort *)in++ */ + mov cl, bl /* cl = bits, needs it for shifting */ + add bl, 16 /* bits += 16 */ + shl eax, cl + or edx, eax /* hold |= *((ushort *)in)++ << bits */ + +L_get_distance_code: + mov eax, [esp+60] /* eax = dmask */ + mov ecx, [esp+36] /* ecx = dcode */ + and eax, edx /* eax &= hold */ + mov eax, [ecx+eax*4]/* eax = dcode[hold & dmask] */ + +L_dodist: + mov ebp, eax /* dist = this */ + shr ebp, 16 /* dist = this.val */ + mov cl, ah + sub bl, ah /* bits -= this.bits */ + shr edx, cl /* hold >>= this.bits */ + mov cl, al /* cl = this.op */ + + test al, 16 /* if ((op & 16) == 0) */ + jz L_test_for_second_level_dist + and cl, 15 /* op &= 15 */ + jz L_check_dist_one + cmp bl, cl + jae L_add_bits_to_dist /* if (op <= bits) 97.6% */ + + mov ch, cl /* stash op in ch, freeing cl */ + xor eax, eax + lodsw /* al = *(ushort *)in++ */ + mov cl, bl /* cl = bits, needs it for shifting */ + add bl, 16 /* bits += 16 */ + shl eax, cl + or edx, eax /* hold |= *((ushort *)in)++ << bits */ + mov cl, ch /* move op back to ecx */ + +L_add_bits_to_dist: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax /* (1 << op) - 1 */ + and eax, edx /* eax &= hold */ + shr edx, cl + add ebp, eax /* dist += hold & ((1 << op) - 1) */ + +L_check_window: + mov [esp+8], esi /* save in so from can use it's reg */ + mov eax, edi + sub eax, [esp+20] /* nbytes = out - beg */ + + cmp eax, ebp + jb L_clip_window /* if (dist > nbytes) 4.2% */ + + mov ecx, [esp+64] /* ecx = len */ + mov esi, edi + sub esi, ebp /* from = out - dist */ + + sar ecx, 1 + jnc L_copy_two + + rep movsw + mov al, [esi] + mov [edi], al + inc edi + + mov esi, [esp+8] /* move in back to %esi, toss from */ + mov ebp, [esp+32] /* ebp = lcode */ + jmp L_while_test + +L_copy_two: + rep movsw + mov esi, [esp+8] /* move in back to %esi, toss from */ + mov ebp, [esp+32] /* ebp = lcode */ + jmp L_while_test + +ALIGN 4 +L_check_dist_one: + cmp ebp, 1 /* if dist 1, is a memset */ + jne L_check_window + cmp [esp+20], edi + je L_check_window /* out == beg, if outside window */ + + mov ecx, [esp+64] /* ecx = len */ + mov al, [edi-1] + mov ah, al + + sar ecx, 1 + jnc L_set_two + mov [edi], al /* memset out with from[-1] */ + inc edi + +L_set_two: + rep stosw + mov ebp, [esp+32] /* ebp = lcode */ + jmp L_while_test + +ALIGN 4 +L_test_for_second_level_length: + test al, 64 + jnz L_test_for_end_of_block /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx /* eax &= hold */ + add eax, [esp+64] /* eax += len */ + mov eax, [ebp+eax*4] /* eax = lcode[val+(hold&mask[op])]*/ + jmp L_dolen + +ALIGN 4 +L_test_for_second_level_dist: + test al, 64 + jnz L_invalid_distance_code /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx /* eax &= hold */ + add eax, ebp /* eax += dist */ + mov ecx, [esp+36] /* ecx = dcode */ + mov eax, [ecx+eax*4] /* eax = dcode[val+(hold&mask[op])]*/ + jmp L_dodist + +ALIGN 4 +L_clip_window: + mov ecx, eax + mov eax, [esp+48] /* eax = wsize */ + neg ecx /* nbytes = -nbytes */ + mov esi, [esp+28] /* from = window */ + + cmp eax, ebp + jb L_invalid_distance_too_far /* if (dist > wsize) */ + + add ecx, ebp /* nbytes = dist - nbytes */ + cmp dword ptr [esp+52], 0 + jne L_wrap_around_window /* if (write != 0) */ + + sub eax, ecx + add esi, eax /* from += wsize - nbytes */ + + mov eax, [esp+64] /* eax = len */ + cmp eax, ecx + jbe L_do_copy /* if (nbytes >= len) */ + + sub eax, ecx /* len -= nbytes */ + rep movsb + mov esi, edi + sub esi, ebp /* from = out - dist */ + jmp L_do_copy + +ALIGN 4 +L_wrap_around_window: + mov eax, [esp+52] /* eax = write */ + cmp ecx, eax + jbe L_contiguous_in_window /* if (write >= nbytes) */ + + add esi, [esp+48] /* from += wsize */ + add esi, eax /* from += write */ + sub esi, ecx /* from -= nbytes */ + sub ecx, eax /* nbytes -= write */ + + mov eax, [esp+64] /* eax = len */ + cmp eax, ecx + jbe L_do_copy /* if (nbytes >= len) */ + + sub eax, ecx /* len -= nbytes */ + rep movsb + mov esi, [esp+28] /* from = window */ + mov ecx, [esp+52] /* nbytes = write */ + cmp eax, ecx + jbe L_do_copy /* if (nbytes >= len) */ + + sub eax, ecx /* len -= nbytes */ + rep movsb + mov esi, edi + sub esi, ebp /* from = out - dist */ + jmp L_do_copy + +ALIGN 4 +L_contiguous_in_window: + add esi, eax + sub esi, ecx /* from += write - nbytes */ + + mov eax, [esp+64] /* eax = len */ + cmp eax, ecx + jbe L_do_copy /* if (nbytes >= len) */ + + sub eax, ecx /* len -= nbytes */ + rep movsb + mov esi, edi + sub esi, ebp /* from = out - dist */ + jmp L_do_copy + +ALIGN 4 +L_do_copy: + mov ecx, eax + rep movsb + + mov esi, [esp+8] /* move in back to %esi, toss from */ + mov ebp, [esp+32] /* ebp = lcode */ + jmp L_while_test + +L_test_for_end_of_block: + test al, 32 + jz L_invalid_literal_length_code + mov dword ptr [esp+72], 1 + jmp L_break_loop_with_status + +L_invalid_literal_length_code: + mov dword ptr [esp+72], 2 + jmp L_break_loop_with_status + +L_invalid_distance_code: + mov dword ptr [esp+72], 3 + jmp L_break_loop_with_status + +L_invalid_distance_too_far: + mov esi, [esp+4] + mov dword ptr [esp+72], 4 + jmp L_break_loop_with_status + +L_break_loop: + mov dword ptr [esp+72], 0 + +L_break_loop_with_status: +/* put in, out, bits, and hold back into ar and pop esp */ + mov [esp+8], esi /* save in */ + mov [esp+16], edi /* save out */ + mov [esp+44], ebx /* save bits */ + mov [esp+40], edx /* save hold */ + mov ebp, [esp+4] /* restore esp, ebp */ + mov esp, [esp] + } +#else +#error "x86 architecture not defined" +#endif + + if (ar.status > 1) { + if (ar.status == 2) + strm->msg = "invalid literal/length code"; + else if (ar.status == 3) + strm->msg = "invalid distance code"; + else + strm->msg = "invalid distance too far back"; + state->mode = BAD; + } + else if ( ar.status == 1 ) { + state->mode = TYPE; + } + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + ar.len = ar.bits >> 3; + ar.in -= ar.len; + ar.bits -= ar.len << 3; + ar.hold &= (1U << ar.bits) - 1; + + /* update state and return */ + strm->next_in = ar.in; + strm->next_out = ar.out; + strm->avail_in = (unsigned)(ar.in < ar.last ? + PAD_AVAIL_IN + (ar.last - ar.in) : + PAD_AVAIL_IN - (ar.in - ar.last)); + strm->avail_out = (unsigned)(ar.out < ar.end ? + PAD_AVAIL_OUT + (ar.end - ar.out) : + PAD_AVAIL_OUT - (ar.out - ar.end)); + state->hold = ar.hold; + state->bits = ar.bits; + return; +} + diff --git a/zlib-1.2.11/contrib/inflate86/inffast.S b/zlib-1.2.11/contrib/inflate86/inffast.S new file mode 100644 index 00000000..2245a290 --- /dev/null +++ b/zlib-1.2.11/contrib/inflate86/inffast.S @@ -0,0 +1,1368 @@ +/* + * inffast.S is a hand tuned assembler version of: + * + * inffast.c -- fast decoding + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Copyright (C) 2003 Chris Anderson + * Please use the copyright conditions above. + * + * This version (Jan-23-2003) of inflate_fast was coded and tested under + * GNU/Linux on a pentium 3, using the gcc-3.2 compiler distribution. On that + * machine, I found that gzip style archives decompressed about 20% faster than + * the gcc-3.2 -O3 -fomit-frame-pointer compiled version. Your results will + * depend on how large of a buffer is used for z_stream.next_in & next_out + * (8K-32K worked best for my 256K cpu cache) and how much overhead there is in + * stream processing I/O and crc32/addler32. In my case, this routine used + * 70% of the cpu time and crc32 used 20%. + * + * I am confident that this version will work in the general case, but I have + * not tested a wide variety of datasets or a wide variety of platforms. + * + * Jan-24-2003 -- Added -DUSE_MMX define for slightly faster inflating. + * It should be a runtime flag instead of compile time flag... + * + * Jan-26-2003 -- Added runtime check for MMX support with cpuid instruction. + * With -DUSE_MMX, only MMX code is compiled. With -DNO_MMX, only non-MMX code + * is compiled. Without either option, runtime detection is enabled. Runtime + * detection should work on all modern cpus and the recomended algorithm (flip + * ID bit on eflags and then use the cpuid instruction) is used in many + * multimedia applications. Tested under win2k with gcc-2.95 and gas-2.12 + * distributed with cygwin3. Compiling with gcc-2.95 -c inffast.S -o + * inffast.obj generates a COFF object which can then be linked with MSVC++ + * compiled code. Tested under FreeBSD 4.7 with gcc-2.95. + * + * Jan-28-2003 -- Tested Athlon XP... MMX mode is slower than no MMX (and + * slower than compiler generated code). Adjusted cpuid check to use the MMX + * code only for Pentiums < P4 until I have more data on the P4. Speed + * improvment is only about 15% on the Athlon when compared with code generated + * with MSVC++. Not sure yet, but I think the P4 will also be slower using the + * MMX mode because many of it's x86 ALU instructions execute in .5 cycles and + * have less latency than MMX ops. Added code to buffer the last 11 bytes of + * the input stream since the MMX code grabs bits in chunks of 32, which + * differs from the inffast.c algorithm. I don't think there would have been + * read overruns where a page boundary was crossed (a segfault), but there + * could have been overruns when next_in ends on unaligned memory (unintialized + * memory read). + * + * Mar-13-2003 -- P4 MMX is slightly slower than P4 NO_MMX. I created a C + * version of the non-MMX code so that it doesn't depend on zstrm and zstate + * structure offsets which are hard coded in this file. This was last tested + * with zlib-1.2.0 which is currently in beta testing, newer versions of this + * and inffas86.c can be found at http://www.eetbeetee.com/zlib/ and + * http://www.charm.net/~christop/zlib/ + */ + + +/* + * if you have underscore linking problems (_inflate_fast undefined), try + * using -DGAS_COFF + */ +#if ! defined( GAS_COFF ) && ! defined( GAS_ELF ) + +#if defined( WIN32 ) || defined( __CYGWIN__ ) +#define GAS_COFF /* windows object format */ +#else +#define GAS_ELF +#endif + +#endif /* ! GAS_COFF && ! GAS_ELF */ + + +#if defined( GAS_COFF ) + +/* coff externals have underscores */ +#define inflate_fast _inflate_fast +#define inflate_fast_use_mmx _inflate_fast_use_mmx + +#endif /* GAS_COFF */ + + +.file "inffast.S" + +.globl inflate_fast + +.text +.align 4,0 +.L_invalid_literal_length_code_msg: +.string "invalid literal/length code" + +.align 4,0 +.L_invalid_distance_code_msg: +.string "invalid distance code" + +.align 4,0 +.L_invalid_distance_too_far_msg: +.string "invalid distance too far back" + +#if ! defined( NO_MMX ) +.align 4,0 +.L_mask: /* mask[N] = ( 1 << N ) - 1 */ +.long 0 +.long 1 +.long 3 +.long 7 +.long 15 +.long 31 +.long 63 +.long 127 +.long 255 +.long 511 +.long 1023 +.long 2047 +.long 4095 +.long 8191 +.long 16383 +.long 32767 +.long 65535 +.long 131071 +.long 262143 +.long 524287 +.long 1048575 +.long 2097151 +.long 4194303 +.long 8388607 +.long 16777215 +.long 33554431 +.long 67108863 +.long 134217727 +.long 268435455 +.long 536870911 +.long 1073741823 +.long 2147483647 +.long 4294967295 +#endif /* NO_MMX */ + +.text + +/* + * struct z_stream offsets, in zlib.h + */ +#define next_in_strm 0 /* strm->next_in */ +#define avail_in_strm 4 /* strm->avail_in */ +#define next_out_strm 12 /* strm->next_out */ +#define avail_out_strm 16 /* strm->avail_out */ +#define msg_strm 24 /* strm->msg */ +#define state_strm 28 /* strm->state */ + +/* + * struct inflate_state offsets, in inflate.h + */ +#define mode_state 0 /* state->mode */ +#define wsize_state 32 /* state->wsize */ +#define write_state 40 /* state->write */ +#define window_state 44 /* state->window */ +#define hold_state 48 /* state->hold */ +#define bits_state 52 /* state->bits */ +#define lencode_state 68 /* state->lencode */ +#define distcode_state 72 /* state->distcode */ +#define lenbits_state 76 /* state->lenbits */ +#define distbits_state 80 /* state->distbits */ + +/* + * inflate_fast's activation record + */ +#define local_var_size 64 /* how much local space for vars */ +#define strm_sp 88 /* first arg: z_stream * (local_var_size + 24) */ +#define start_sp 92 /* second arg: unsigned int (local_var_size + 28) */ + +/* + * offsets for local vars on stack + */ +#define out 60 /* unsigned char* */ +#define window 56 /* unsigned char* */ +#define wsize 52 /* unsigned int */ +#define write 48 /* unsigned int */ +#define in 44 /* unsigned char* */ +#define beg 40 /* unsigned char* */ +#define buf 28 /* char[ 12 ] */ +#define len 24 /* unsigned int */ +#define last 20 /* unsigned char* */ +#define end 16 /* unsigned char* */ +#define dcode 12 /* code* */ +#define lcode 8 /* code* */ +#define dmask 4 /* unsigned int */ +#define lmask 0 /* unsigned int */ + +/* + * typedef enum inflate_mode consts, in inflate.h + */ +#define INFLATE_MODE_TYPE 11 /* state->mode flags enum-ed in inflate.h */ +#define INFLATE_MODE_BAD 26 + + +#if ! defined( USE_MMX ) && ! defined( NO_MMX ) + +#define RUN_TIME_MMX + +#define CHECK_MMX 1 +#define DO_USE_MMX 2 +#define DONT_USE_MMX 3 + +.globl inflate_fast_use_mmx + +.data + +.align 4,0 +inflate_fast_use_mmx: /* integer flag for run time control 1=check,2=mmx,3=no */ +.long CHECK_MMX + +#if defined( GAS_ELF ) +/* elf info */ +.type inflate_fast_use_mmx,@object +.size inflate_fast_use_mmx,4 +#endif + +#endif /* RUN_TIME_MMX */ + +#if defined( GAS_COFF ) +/* coff info: scl 2 = extern, type 32 = function */ +.def inflate_fast; .scl 2; .type 32; .endef +#endif + +.text + +.align 32,0x90 +inflate_fast: + pushl %edi + pushl %esi + pushl %ebp + pushl %ebx + pushf /* save eflags (strm_sp, state_sp assumes this is 32 bits) */ + subl $local_var_size, %esp + cld + +#define strm_r %esi +#define state_r %edi + + movl strm_sp(%esp), strm_r + movl state_strm(strm_r), state_r + + /* in = strm->next_in; + * out = strm->next_out; + * last = in + strm->avail_in - 11; + * beg = out - (start - strm->avail_out); + * end = out + (strm->avail_out - 257); + */ + movl avail_in_strm(strm_r), %edx + movl next_in_strm(strm_r), %eax + + addl %eax, %edx /* avail_in += next_in */ + subl $11, %edx /* avail_in -= 11 */ + + movl %eax, in(%esp) + movl %edx, last(%esp) + + movl start_sp(%esp), %ebp + movl avail_out_strm(strm_r), %ecx + movl next_out_strm(strm_r), %ebx + + subl %ecx, %ebp /* start -= avail_out */ + negl %ebp /* start = -start */ + addl %ebx, %ebp /* start += next_out */ + + subl $257, %ecx /* avail_out -= 257 */ + addl %ebx, %ecx /* avail_out += out */ + + movl %ebx, out(%esp) + movl %ebp, beg(%esp) + movl %ecx, end(%esp) + + /* wsize = state->wsize; + * write = state->write; + * window = state->window; + * hold = state->hold; + * bits = state->bits; + * lcode = state->lencode; + * dcode = state->distcode; + * lmask = ( 1 << state->lenbits ) - 1; + * dmask = ( 1 << state->distbits ) - 1; + */ + + movl lencode_state(state_r), %eax + movl distcode_state(state_r), %ecx + + movl %eax, lcode(%esp) + movl %ecx, dcode(%esp) + + movl $1, %eax + movl lenbits_state(state_r), %ecx + shll %cl, %eax + decl %eax + movl %eax, lmask(%esp) + + movl $1, %eax + movl distbits_state(state_r), %ecx + shll %cl, %eax + decl %eax + movl %eax, dmask(%esp) + + movl wsize_state(state_r), %eax + movl write_state(state_r), %ecx + movl window_state(state_r), %edx + + movl %eax, wsize(%esp) + movl %ecx, write(%esp) + movl %edx, window(%esp) + + movl hold_state(state_r), %ebp + movl bits_state(state_r), %ebx + +#undef strm_r +#undef state_r + +#define in_r %esi +#define from_r %esi +#define out_r %edi + + movl in(%esp), in_r + movl last(%esp), %ecx + cmpl in_r, %ecx + ja .L_align_long /* if in < last */ + + addl $11, %ecx /* ecx = &in[ avail_in ] */ + subl in_r, %ecx /* ecx = avail_in */ + movl $12, %eax + subl %ecx, %eax /* eax = 12 - avail_in */ + leal buf(%esp), %edi + rep movsb /* memcpy( buf, in, avail_in ) */ + movl %eax, %ecx + xorl %eax, %eax + rep stosb /* memset( &buf[ avail_in ], 0, 12 - avail_in ) */ + leal buf(%esp), in_r /* in = buf */ + movl in_r, last(%esp) /* last = in, do just one iteration */ + jmp .L_is_aligned + + /* align in_r on long boundary */ +.L_align_long: + testl $3, in_r + jz .L_is_aligned + xorl %eax, %eax + movb (in_r), %al + incl in_r + movl %ebx, %ecx + addl $8, %ebx + shll %cl, %eax + orl %eax, %ebp + jmp .L_align_long + +.L_is_aligned: + movl out(%esp), out_r + +#if defined( NO_MMX ) + jmp .L_do_loop +#endif + +#if defined( USE_MMX ) + jmp .L_init_mmx +#endif + +/*** Runtime MMX check ***/ + +#if defined( RUN_TIME_MMX ) +.L_check_mmx: + cmpl $DO_USE_MMX, inflate_fast_use_mmx + je .L_init_mmx + ja .L_do_loop /* > 2 */ + + pushl %eax + pushl %ebx + pushl %ecx + pushl %edx + pushf + movl (%esp), %eax /* copy eflags to eax */ + xorl $0x200000, (%esp) /* try toggling ID bit of eflags (bit 21) + * to see if cpu supports cpuid... + * ID bit method not supported by NexGen but + * bios may load a cpuid instruction and + * cpuid may be disabled on Cyrix 5-6x86 */ + popf + pushf + popl %edx /* copy new eflags to edx */ + xorl %eax, %edx /* test if ID bit is flipped */ + jz .L_dont_use_mmx /* not flipped if zero */ + xorl %eax, %eax + cpuid + cmpl $0x756e6547, %ebx /* check for GenuineIntel in ebx,ecx,edx */ + jne .L_dont_use_mmx + cmpl $0x6c65746e, %ecx + jne .L_dont_use_mmx + cmpl $0x49656e69, %edx + jne .L_dont_use_mmx + movl $1, %eax + cpuid /* get cpu features */ + shrl $8, %eax + andl $15, %eax + cmpl $6, %eax /* check for Pentium family, is 0xf for P4 */ + jne .L_dont_use_mmx + testl $0x800000, %edx /* test if MMX feature is set (bit 23) */ + jnz .L_use_mmx + jmp .L_dont_use_mmx +.L_use_mmx: + movl $DO_USE_MMX, inflate_fast_use_mmx + jmp .L_check_mmx_pop +.L_dont_use_mmx: + movl $DONT_USE_MMX, inflate_fast_use_mmx +.L_check_mmx_pop: + popl %edx + popl %ecx + popl %ebx + popl %eax + jmp .L_check_mmx +#endif + + +/*** Non-MMX code ***/ + +#if defined ( NO_MMX ) || defined( RUN_TIME_MMX ) + +#define hold_r %ebp +#define bits_r %bl +#define bitslong_r %ebx + +.align 32,0x90 +.L_while_test: + /* while (in < last && out < end) + */ + cmpl out_r, end(%esp) + jbe .L_break_loop /* if (out >= end) */ + + cmpl in_r, last(%esp) + jbe .L_break_loop + +.L_do_loop: + /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out + * + * do { + * if (bits < 15) { + * hold |= *((unsigned short *)in)++ << bits; + * bits += 16 + * } + * this = lcode[hold & lmask] + */ + cmpb $15, bits_r + ja .L_get_length_code /* if (15 < bits) */ + + xorl %eax, %eax + lodsw /* al = *(ushort *)in++ */ + movb bits_r, %cl /* cl = bits, needs it for shifting */ + addb $16, bits_r /* bits += 16 */ + shll %cl, %eax + orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ + +.L_get_length_code: + movl lmask(%esp), %edx /* edx = lmask */ + movl lcode(%esp), %ecx /* ecx = lcode */ + andl hold_r, %edx /* edx &= hold */ + movl (%ecx,%edx,4), %eax /* eax = lcode[hold & lmask] */ + +.L_dolen: + /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out + * + * dolen: + * bits -= this.bits; + * hold >>= this.bits + */ + movb %ah, %cl /* cl = this.bits */ + subb %ah, bits_r /* bits -= this.bits */ + shrl %cl, hold_r /* hold >>= this.bits */ + + /* check if op is a literal + * if (op == 0) { + * PUP(out) = this.val; + * } + */ + testb %al, %al + jnz .L_test_for_length_base /* if (op != 0) 45.7% */ + + shrl $16, %eax /* output this.val char */ + stosb + jmp .L_while_test + +.L_test_for_length_base: + /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = len + * + * else if (op & 16) { + * len = this.val + * op &= 15 + * if (op) { + * if (op > bits) { + * hold |= *((unsigned short *)in)++ << bits; + * bits += 16 + * } + * len += hold & mask[op]; + * bits -= op; + * hold >>= op; + * } + */ +#define len_r %edx + movl %eax, len_r /* len = this */ + shrl $16, len_r /* len = this.val */ + movb %al, %cl + + testb $16, %al + jz .L_test_for_second_level_length /* if ((op & 16) == 0) 8% */ + andb $15, %cl /* op &= 15 */ + jz .L_save_len /* if (!op) */ + cmpb %cl, bits_r + jae .L_add_bits_to_len /* if (op <= bits) */ + + movb %cl, %ch /* stash op in ch, freeing cl */ + xorl %eax, %eax + lodsw /* al = *(ushort *)in++ */ + movb bits_r, %cl /* cl = bits, needs it for shifting */ + addb $16, bits_r /* bits += 16 */ + shll %cl, %eax + orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ + movb %ch, %cl /* move op back to ecx */ + +.L_add_bits_to_len: + movl $1, %eax + shll %cl, %eax + decl %eax + subb %cl, bits_r + andl hold_r, %eax /* eax &= hold */ + shrl %cl, hold_r + addl %eax, len_r /* len += hold & mask[op] */ + +.L_save_len: + movl len_r, len(%esp) /* save len */ +#undef len_r + +.L_decode_distance: + /* regs: %esi = in, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * + * if (bits < 15) { + * hold |= *((unsigned short *)in)++ << bits; + * bits += 16 + * } + * this = dcode[hold & dmask]; + * dodist: + * bits -= this.bits; + * hold >>= this.bits; + * op = this.op; + */ + + cmpb $15, bits_r + ja .L_get_distance_code /* if (15 < bits) */ + + xorl %eax, %eax + lodsw /* al = *(ushort *)in++ */ + movb bits_r, %cl /* cl = bits, needs it for shifting */ + addb $16, bits_r /* bits += 16 */ + shll %cl, %eax + orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ + +.L_get_distance_code: + movl dmask(%esp), %edx /* edx = dmask */ + movl dcode(%esp), %ecx /* ecx = dcode */ + andl hold_r, %edx /* edx &= hold */ + movl (%ecx,%edx,4), %eax /* eax = dcode[hold & dmask] */ + +#define dist_r %edx +.L_dodist: + movl %eax, dist_r /* dist = this */ + shrl $16, dist_r /* dist = this.val */ + movb %ah, %cl + subb %ah, bits_r /* bits -= this.bits */ + shrl %cl, hold_r /* hold >>= this.bits */ + + /* if (op & 16) { + * dist = this.val + * op &= 15 + * if (op > bits) { + * hold |= *((unsigned short *)in)++ << bits; + * bits += 16 + * } + * dist += hold & mask[op]; + * bits -= op; + * hold >>= op; + */ + movb %al, %cl /* cl = this.op */ + + testb $16, %al /* if ((op & 16) == 0) */ + jz .L_test_for_second_level_dist + andb $15, %cl /* op &= 15 */ + jz .L_check_dist_one + cmpb %cl, bits_r + jae .L_add_bits_to_dist /* if (op <= bits) 97.6% */ + + movb %cl, %ch /* stash op in ch, freeing cl */ + xorl %eax, %eax + lodsw /* al = *(ushort *)in++ */ + movb bits_r, %cl /* cl = bits, needs it for shifting */ + addb $16, bits_r /* bits += 16 */ + shll %cl, %eax + orl %eax, hold_r /* hold |= *((ushort *)in)++ << bits */ + movb %ch, %cl /* move op back to ecx */ + +.L_add_bits_to_dist: + movl $1, %eax + shll %cl, %eax + decl %eax /* (1 << op) - 1 */ + subb %cl, bits_r + andl hold_r, %eax /* eax &= hold */ + shrl %cl, hold_r + addl %eax, dist_r /* dist += hold & ((1 << op) - 1) */ + jmp .L_check_window + +.L_check_window: + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes + * + * nbytes = out - beg; + * if (dist <= nbytes) { + * from = out - dist; + * do { + * PUP(out) = PUP(from); + * } while (--len > 0) { + * } + */ + + movl in_r, in(%esp) /* save in so from can use it's reg */ + movl out_r, %eax + subl beg(%esp), %eax /* nbytes = out - beg */ + + cmpl dist_r, %eax + jb .L_clip_window /* if (dist > nbytes) 4.2% */ + + movl len(%esp), %ecx + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + + subl $3, %ecx + movb (from_r), %al + movb %al, (out_r) + movb 1(from_r), %al + movb 2(from_r), %dl + addl $3, from_r + movb %al, 1(out_r) + movb %dl, 2(out_r) + addl $3, out_r + rep movsb + + movl in(%esp), in_r /* move in back to %esi, toss from */ + jmp .L_while_test + +.align 16,0x90 +.L_check_dist_one: + cmpl $1, dist_r + jne .L_check_window + cmpl out_r, beg(%esp) + je .L_check_window + + decl out_r + movl len(%esp), %ecx + movb (out_r), %al + subl $3, %ecx + + movb %al, 1(out_r) + movb %al, 2(out_r) + movb %al, 3(out_r) + addl $4, out_r + rep stosb + + jmp .L_while_test + +.align 16,0x90 +.L_test_for_second_level_length: + /* else if ((op & 64) == 0) { + * this = lcode[this.val + (hold & mask[op])]; + * } + */ + testb $64, %al + jnz .L_test_for_end_of_block /* if ((op & 64) != 0) */ + + movl $1, %eax + shll %cl, %eax + decl %eax + andl hold_r, %eax /* eax &= hold */ + addl %edx, %eax /* eax += this.val */ + movl lcode(%esp), %edx /* edx = lcode */ + movl (%edx,%eax,4), %eax /* eax = lcode[val + (hold&mask[op])] */ + jmp .L_dolen + +.align 16,0x90 +.L_test_for_second_level_dist: + /* else if ((op & 64) == 0) { + * this = dcode[this.val + (hold & mask[op])]; + * } + */ + testb $64, %al + jnz .L_invalid_distance_code /* if ((op & 64) != 0) */ + + movl $1, %eax + shll %cl, %eax + decl %eax + andl hold_r, %eax /* eax &= hold */ + addl %edx, %eax /* eax += this.val */ + movl dcode(%esp), %edx /* edx = dcode */ + movl (%edx,%eax,4), %eax /* eax = dcode[val + (hold&mask[op])] */ + jmp .L_dodist + +.align 16,0x90 +.L_clip_window: + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes + * + * else { + * if (dist > wsize) { + * invalid distance + * } + * from = window; + * nbytes = dist - nbytes; + * if (write == 0) { + * from += wsize - nbytes; + */ +#define nbytes_r %ecx + movl %eax, nbytes_r + movl wsize(%esp), %eax /* prepare for dist compare */ + negl nbytes_r /* nbytes = -nbytes */ + movl window(%esp), from_r /* from = window */ + + cmpl dist_r, %eax + jb .L_invalid_distance_too_far /* if (dist > wsize) */ + + addl dist_r, nbytes_r /* nbytes = dist - nbytes */ + cmpl $0, write(%esp) + jne .L_wrap_around_window /* if (write != 0) */ + + subl nbytes_r, %eax + addl %eax, from_r /* from += wsize - nbytes */ + + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes, %eax = len + * + * if (nbytes < len) { + * len -= nbytes; + * do { + * PUP(out) = PUP(from); + * } while (--nbytes); + * from = out - dist; + * } + * } + */ +#define len_r %eax + movl len(%esp), len_r + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1 + + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1 + +.L_wrap_around_window: + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes, %eax = write, %eax = len + * + * else if (write < nbytes) { + * from += wsize + write - nbytes; + * nbytes -= write; + * if (nbytes < len) { + * len -= nbytes; + * do { + * PUP(out) = PUP(from); + * } while (--nbytes); + * from = window; + * nbytes = write; + * if (nbytes < len) { + * len -= nbytes; + * do { + * PUP(out) = PUP(from); + * } while(--nbytes); + * from = out - dist; + * } + * } + * } + */ +#define write_r %eax + movl write(%esp), write_r + cmpl write_r, nbytes_r + jbe .L_contiguous_in_window /* if (write >= nbytes) */ + + addl wsize(%esp), from_r + addl write_r, from_r + subl nbytes_r, from_r /* from += wsize + write - nbytes */ + subl write_r, nbytes_r /* nbytes -= write */ +#undef write_r + + movl len(%esp), len_r + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl window(%esp), from_r /* from = window */ + movl write(%esp), nbytes_r /* nbytes = write */ + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1 + +.L_contiguous_in_window: + /* regs: %esi = from, %ebp = hold, %bl = bits, %edi = out, %edx = dist + * %ecx = nbytes, %eax = write, %eax = len + * + * else { + * from += write - nbytes; + * if (nbytes < len) { + * len -= nbytes; + * do { + * PUP(out) = PUP(from); + * } while (--nbytes); + * from = out - dist; + * } + * } + */ +#define write_r %eax + addl write_r, from_r + subl nbytes_r, from_r /* from += write - nbytes */ +#undef write_r + + movl len(%esp), len_r + cmpl nbytes_r, len_r + jbe .L_do_copy1 /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + +.L_do_copy1: + /* regs: %esi = from, %esi = in, %ebp = hold, %bl = bits, %edi = out + * %eax = len + * + * while (len > 0) { + * PUP(out) = PUP(from); + * len--; + * } + * } + * } while (in < last && out < end); + */ +#undef nbytes_r +#define in_r %esi + movl len_r, %ecx + rep movsb + + movl in(%esp), in_r /* move in back to %esi, toss from */ + jmp .L_while_test + +#undef len_r +#undef dist_r + +#endif /* NO_MMX || RUN_TIME_MMX */ + + +/*** MMX code ***/ + +#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) + +.align 32,0x90 +.L_init_mmx: + emms + +#undef bits_r +#undef bitslong_r +#define bitslong_r %ebp +#define hold_mm %mm0 + movd %ebp, hold_mm + movl %ebx, bitslong_r + +#define used_mm %mm1 +#define dmask2_mm %mm2 +#define lmask2_mm %mm3 +#define lmask_mm %mm4 +#define dmask_mm %mm5 +#define tmp_mm %mm6 + + movd lmask(%esp), lmask_mm + movq lmask_mm, lmask2_mm + movd dmask(%esp), dmask_mm + movq dmask_mm, dmask2_mm + pxor used_mm, used_mm + movl lcode(%esp), %ebx /* ebx = lcode */ + jmp .L_do_loop_mmx + +.align 32,0x90 +.L_while_test_mmx: + /* while (in < last && out < end) + */ + cmpl out_r, end(%esp) + jbe .L_break_loop /* if (out >= end) */ + + cmpl in_r, last(%esp) + jbe .L_break_loop + +.L_do_loop_mmx: + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + + cmpl $32, bitslong_r + ja .L_get_length_code_mmx /* if (32 < bits) */ + + movd bitslong_r, tmp_mm + movd (in_r), %mm7 + addl $4, in_r + psllq tmp_mm, %mm7 + addl $32, bitslong_r + por %mm7, hold_mm /* hold_mm |= *((uint *)in)++ << bits */ + +.L_get_length_code_mmx: + pand hold_mm, lmask_mm + movd lmask_mm, %eax + movq lmask2_mm, lmask_mm + movl (%ebx,%eax,4), %eax /* eax = lcode[hold & lmask] */ + +.L_dolen_mmx: + movzbl %ah, %ecx /* ecx = this.bits */ + movd %ecx, used_mm + subl %ecx, bitslong_r /* bits -= this.bits */ + + testb %al, %al + jnz .L_test_for_length_base_mmx /* if (op != 0) 45.7% */ + + shrl $16, %eax /* output this.val char */ + stosb + jmp .L_while_test_mmx + +.L_test_for_length_base_mmx: +#define len_r %edx + movl %eax, len_r /* len = this */ + shrl $16, len_r /* len = this.val */ + + testb $16, %al + jz .L_test_for_second_level_length_mmx /* if ((op & 16) == 0) 8% */ + andl $15, %eax /* op &= 15 */ + jz .L_decode_distance_mmx /* if (!op) */ + + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd %eax, used_mm + movd hold_mm, %ecx + subl %eax, bitslong_r + andl .L_mask(,%eax,4), %ecx + addl %ecx, len_r /* len += hold & mask[op] */ + +.L_decode_distance_mmx: + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + + cmpl $32, bitslong_r + ja .L_get_dist_code_mmx /* if (32 < bits) */ + + movd bitslong_r, tmp_mm + movd (in_r), %mm7 + addl $4, in_r + psllq tmp_mm, %mm7 + addl $32, bitslong_r + por %mm7, hold_mm /* hold_mm |= *((uint *)in)++ << bits */ + +.L_get_dist_code_mmx: + movl dcode(%esp), %ebx /* ebx = dcode */ + pand hold_mm, dmask_mm + movd dmask_mm, %eax + movq dmask2_mm, dmask_mm + movl (%ebx,%eax,4), %eax /* eax = dcode[hold & lmask] */ + +.L_dodist_mmx: +#define dist_r %ebx + movzbl %ah, %ecx /* ecx = this.bits */ + movl %eax, dist_r + shrl $16, dist_r /* dist = this.val */ + subl %ecx, bitslong_r /* bits -= this.bits */ + movd %ecx, used_mm + + testb $16, %al /* if ((op & 16) == 0) */ + jz .L_test_for_second_level_dist_mmx + andl $15, %eax /* op &= 15 */ + jz .L_check_dist_one_mmx + +.L_add_bits_to_dist_mmx: + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd %eax, used_mm /* save bit length of current op */ + movd hold_mm, %ecx /* get the next bits on input stream */ + subl %eax, bitslong_r /* bits -= op bits */ + andl .L_mask(,%eax,4), %ecx /* ecx = hold & mask[op] */ + addl %ecx, dist_r /* dist += hold & mask[op] */ + +.L_check_window_mmx: + movl in_r, in(%esp) /* save in so from can use it's reg */ + movl out_r, %eax + subl beg(%esp), %eax /* nbytes = out - beg */ + + cmpl dist_r, %eax + jb .L_clip_window_mmx /* if (dist > nbytes) 4.2% */ + + movl len_r, %ecx + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + + subl $3, %ecx + movb (from_r), %al + movb %al, (out_r) + movb 1(from_r), %al + movb 2(from_r), %dl + addl $3, from_r + movb %al, 1(out_r) + movb %dl, 2(out_r) + addl $3, out_r + rep movsb + + movl in(%esp), in_r /* move in back to %esi, toss from */ + movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ + jmp .L_while_test_mmx + +.align 16,0x90 +.L_check_dist_one_mmx: + cmpl $1, dist_r + jne .L_check_window_mmx + cmpl out_r, beg(%esp) + je .L_check_window_mmx + + decl out_r + movl len_r, %ecx + movb (out_r), %al + subl $3, %ecx + + movb %al, 1(out_r) + movb %al, 2(out_r) + movb %al, 3(out_r) + addl $4, out_r + rep stosb + + movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ + jmp .L_while_test_mmx + +.align 16,0x90 +.L_test_for_second_level_length_mmx: + testb $64, %al + jnz .L_test_for_end_of_block /* if ((op & 64) != 0) */ + + andl $15, %eax + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd hold_mm, %ecx + andl .L_mask(,%eax,4), %ecx + addl len_r, %ecx + movl (%ebx,%ecx,4), %eax /* eax = lcode[hold & lmask] */ + jmp .L_dolen_mmx + +.align 16,0x90 +.L_test_for_second_level_dist_mmx: + testb $64, %al + jnz .L_invalid_distance_code /* if ((op & 64) != 0) */ + + andl $15, %eax + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd hold_mm, %ecx + andl .L_mask(,%eax,4), %ecx + movl dcode(%esp), %eax /* ecx = dcode */ + addl dist_r, %ecx + movl (%eax,%ecx,4), %eax /* eax = lcode[hold & lmask] */ + jmp .L_dodist_mmx + +.align 16,0x90 +.L_clip_window_mmx: +#define nbytes_r %ecx + movl %eax, nbytes_r + movl wsize(%esp), %eax /* prepare for dist compare */ + negl nbytes_r /* nbytes = -nbytes */ + movl window(%esp), from_r /* from = window */ + + cmpl dist_r, %eax + jb .L_invalid_distance_too_far /* if (dist > wsize) */ + + addl dist_r, nbytes_r /* nbytes = dist - nbytes */ + cmpl $0, write(%esp) + jne .L_wrap_around_window_mmx /* if (write != 0) */ + + subl nbytes_r, %eax + addl %eax, from_r /* from += wsize - nbytes */ + + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1_mmx + + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1_mmx + +.L_wrap_around_window_mmx: +#define write_r %eax + movl write(%esp), write_r + cmpl write_r, nbytes_r + jbe .L_contiguous_in_window_mmx /* if (write >= nbytes) */ + + addl wsize(%esp), from_r + addl write_r, from_r + subl nbytes_r, from_r /* from += wsize + write - nbytes */ + subl write_r, nbytes_r /* nbytes -= write */ +#undef write_r + + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl window(%esp), from_r /* from = window */ + movl write(%esp), nbytes_r /* nbytes = write */ + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + jmp .L_do_copy1_mmx + +.L_contiguous_in_window_mmx: +#define write_r %eax + addl write_r, from_r + subl nbytes_r, from_r /* from += write - nbytes */ +#undef write_r + + cmpl nbytes_r, len_r + jbe .L_do_copy1_mmx /* if (nbytes >= len) */ + + subl nbytes_r, len_r /* len -= nbytes */ + rep movsb + movl out_r, from_r + subl dist_r, from_r /* from = out - dist */ + +.L_do_copy1_mmx: +#undef nbytes_r +#define in_r %esi + movl len_r, %ecx + rep movsb + + movl in(%esp), in_r /* move in back to %esi, toss from */ + movl lcode(%esp), %ebx /* move lcode back to %ebx, toss dist */ + jmp .L_while_test_mmx + +#undef hold_r +#undef bitslong_r + +#endif /* USE_MMX || RUN_TIME_MMX */ + + +/*** USE_MMX, NO_MMX, and RUNTIME_MMX from here on ***/ + +.L_invalid_distance_code: + /* else { + * strm->msg = "invalid distance code"; + * state->mode = BAD; + * } + */ + movl $.L_invalid_distance_code_msg, %ecx + movl $INFLATE_MODE_BAD, %edx + jmp .L_update_stream_state + +.L_test_for_end_of_block: + /* else if (op & 32) { + * state->mode = TYPE; + * break; + * } + */ + testb $32, %al + jz .L_invalid_literal_length_code /* if ((op & 32) == 0) */ + + movl $0, %ecx + movl $INFLATE_MODE_TYPE, %edx + jmp .L_update_stream_state + +.L_invalid_literal_length_code: + /* else { + * strm->msg = "invalid literal/length code"; + * state->mode = BAD; + * } + */ + movl $.L_invalid_literal_length_code_msg, %ecx + movl $INFLATE_MODE_BAD, %edx + jmp .L_update_stream_state + +.L_invalid_distance_too_far: + /* strm->msg = "invalid distance too far back"; + * state->mode = BAD; + */ + movl in(%esp), in_r /* from_r has in's reg, put in back */ + movl $.L_invalid_distance_too_far_msg, %ecx + movl $INFLATE_MODE_BAD, %edx + jmp .L_update_stream_state + +.L_update_stream_state: + /* set strm->msg = %ecx, strm->state->mode = %edx */ + movl strm_sp(%esp), %eax + testl %ecx, %ecx /* if (msg != NULL) */ + jz .L_skip_msg + movl %ecx, msg_strm(%eax) /* strm->msg = msg */ +.L_skip_msg: + movl state_strm(%eax), %eax /* state = strm->state */ + movl %edx, mode_state(%eax) /* state->mode = edx (BAD | TYPE) */ + jmp .L_break_loop + +.align 32,0x90 +.L_break_loop: + +/* + * Regs: + * + * bits = %ebp when mmx, and in %ebx when non-mmx + * hold = %hold_mm when mmx, and in %ebp when non-mmx + * in = %esi + * out = %edi + */ + +#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) + +#if defined( RUN_TIME_MMX ) + + cmpl $DO_USE_MMX, inflate_fast_use_mmx + jne .L_update_next_in + +#endif /* RUN_TIME_MMX */ + + movl %ebp, %ebx + +.L_update_next_in: + +#endif + +#define strm_r %eax +#define state_r %edx + + /* len = bits >> 3; + * in -= len; + * bits -= len << 3; + * hold &= (1U << bits) - 1; + * state->hold = hold; + * state->bits = bits; + * strm->next_in = in; + * strm->next_out = out; + */ + movl strm_sp(%esp), strm_r + movl %ebx, %ecx + movl state_strm(strm_r), state_r + shrl $3, %ecx + subl %ecx, in_r + shll $3, %ecx + subl %ecx, %ebx + movl out_r, next_out_strm(strm_r) + movl %ebx, bits_state(state_r) + movl %ebx, %ecx + + leal buf(%esp), %ebx + cmpl %ebx, last(%esp) + jne .L_buf_not_used /* if buf != last */ + + subl %ebx, in_r /* in -= buf */ + movl next_in_strm(strm_r), %ebx + movl %ebx, last(%esp) /* last = strm->next_in */ + addl %ebx, in_r /* in += strm->next_in */ + movl avail_in_strm(strm_r), %ebx + subl $11, %ebx + addl %ebx, last(%esp) /* last = &strm->next_in[ avail_in - 11 ] */ + +.L_buf_not_used: + movl in_r, next_in_strm(strm_r) + + movl $1, %ebx + shll %cl, %ebx + decl %ebx + +#if defined( USE_MMX ) || defined( RUN_TIME_MMX ) + +#if defined( RUN_TIME_MMX ) + + cmpl $DO_USE_MMX, inflate_fast_use_mmx + jne .L_update_hold + +#endif /* RUN_TIME_MMX */ + + psrlq used_mm, hold_mm /* hold_mm >>= last bit length */ + movd hold_mm, %ebp + + emms + +.L_update_hold: + +#endif /* USE_MMX || RUN_TIME_MMX */ + + andl %ebx, %ebp + movl %ebp, hold_state(state_r) + +#define last_r %ebx + + /* strm->avail_in = in < last ? 11 + (last - in) : 11 - (in - last) */ + movl last(%esp), last_r + cmpl in_r, last_r + jbe .L_last_is_smaller /* if (in >= last) */ + + subl in_r, last_r /* last -= in */ + addl $11, last_r /* last += 11 */ + movl last_r, avail_in_strm(strm_r) + jmp .L_fixup_out +.L_last_is_smaller: + subl last_r, in_r /* in -= last */ + negl in_r /* in = -in */ + addl $11, in_r /* in += 11 */ + movl in_r, avail_in_strm(strm_r) + +#undef last_r +#define end_r %ebx + +.L_fixup_out: + /* strm->avail_out = out < end ? 257 + (end - out) : 257 - (out - end)*/ + movl end(%esp), end_r + cmpl out_r, end_r + jbe .L_end_is_smaller /* if (out >= end) */ + + subl out_r, end_r /* end -= out */ + addl $257, end_r /* end += 257 */ + movl end_r, avail_out_strm(strm_r) + jmp .L_done +.L_end_is_smaller: + subl end_r, out_r /* out -= end */ + negl out_r /* out = -out */ + addl $257, out_r /* out += 257 */ + movl out_r, avail_out_strm(strm_r) + +#undef end_r +#undef strm_r +#undef state_r + +.L_done: + addl $local_var_size, %esp + popf + popl %ebx + popl %ebp + popl %esi + popl %edi + ret + +#if defined( GAS_ELF ) +/* elf info */ +.type inflate_fast,@function +.size inflate_fast,.-inflate_fast +#endif diff --git a/zlib-1.2.11/contrib/iostream/test.cpp b/zlib-1.2.11/contrib/iostream/test.cpp new file mode 100644 index 00000000..7d265b3b --- /dev/null +++ b/zlib-1.2.11/contrib/iostream/test.cpp @@ -0,0 +1,24 @@ + +#include "zfstream.h" + +int main() { + + // Construct a stream object with this filebuffer. Anything sent + // to this stream will go to standard out. + gzofstream os( 1, ios::out ); + + // This text is getting compressed and sent to stdout. + // To prove this, run 'test | zcat'. + os << "Hello, Mommy" << endl; + + os << setcompressionlevel( Z_NO_COMPRESSION ); + os << "hello, hello, hi, ho!" << endl; + + setcompressionlevel( os, Z_DEFAULT_COMPRESSION ) + << "I'm compressing again" << endl; + + os.close(); + + return 0; + +} diff --git a/zlib-1.2.11/contrib/iostream/zfstream.cpp b/zlib-1.2.11/contrib/iostream/zfstream.cpp new file mode 100644 index 00000000..d0cd85fa --- /dev/null +++ b/zlib-1.2.11/contrib/iostream/zfstream.cpp @@ -0,0 +1,329 @@ + +#include "zfstream.h" + +gzfilebuf::gzfilebuf() : + file(NULL), + mode(0), + own_file_descriptor(0) +{ } + +gzfilebuf::~gzfilebuf() { + + sync(); + if ( own_file_descriptor ) + close(); + +} + +gzfilebuf *gzfilebuf::open( const char *name, + int io_mode ) { + + if ( is_open() ) + return NULL; + + char char_mode[10]; + char *p = char_mode; + + if ( io_mode & ios::in ) { + mode = ios::in; + *p++ = 'r'; + } else if ( io_mode & ios::app ) { + mode = ios::app; + *p++ = 'a'; + } else { + mode = ios::out; + *p++ = 'w'; + } + + if ( io_mode & ios::binary ) { + mode |= ios::binary; + *p++ = 'b'; + } + + // Hard code the compression level + if ( io_mode & (ios::out|ios::app )) { + *p++ = '9'; + } + + // Put the end-of-string indicator + *p = '\0'; + + if ( (file = gzopen(name, char_mode)) == NULL ) + return NULL; + + own_file_descriptor = 1; + + return this; + +} + +gzfilebuf *gzfilebuf::attach( int file_descriptor, + int io_mode ) { + + if ( is_open() ) + return NULL; + + char char_mode[10]; + char *p = char_mode; + + if ( io_mode & ios::in ) { + mode = ios::in; + *p++ = 'r'; + } else if ( io_mode & ios::app ) { + mode = ios::app; + *p++ = 'a'; + } else { + mode = ios::out; + *p++ = 'w'; + } + + if ( io_mode & ios::binary ) { + mode |= ios::binary; + *p++ = 'b'; + } + + // Hard code the compression level + if ( io_mode & (ios::out|ios::app )) { + *p++ = '9'; + } + + // Put the end-of-string indicator + *p = '\0'; + + if ( (file = gzdopen(file_descriptor, char_mode)) == NULL ) + return NULL; + + own_file_descriptor = 0; + + return this; + +} + +gzfilebuf *gzfilebuf::close() { + + if ( is_open() ) { + + sync(); + gzclose( file ); + file = NULL; + + } + + return this; + +} + +int gzfilebuf::setcompressionlevel( int comp_level ) { + + return gzsetparams(file, comp_level, -2); + +} + +int gzfilebuf::setcompressionstrategy( int comp_strategy ) { + + return gzsetparams(file, -2, comp_strategy); + +} + + +streampos gzfilebuf::seekoff( streamoff off, ios::seek_dir dir, int which ) { + + return streampos(EOF); + +} + +int gzfilebuf::underflow() { + + // If the file hasn't been opened for reading, error. + if ( !is_open() || !(mode & ios::in) ) + return EOF; + + // if a buffer doesn't exists, allocate one. + if ( !base() ) { + + if ( (allocate()) == EOF ) + return EOF; + setp(0,0); + + } else { + + if ( in_avail() ) + return (unsigned char) *gptr(); + + if ( out_waiting() ) { + if ( flushbuf() == EOF ) + return EOF; + } + + } + + // Attempt to fill the buffer. + + int result = fillbuf(); + if ( result == EOF ) { + // disable get area + setg(0,0,0); + return EOF; + } + + return (unsigned char) *gptr(); + +} + +int gzfilebuf::overflow( int c ) { + + if ( !is_open() || !(mode & ios::out) ) + return EOF; + + if ( !base() ) { + if ( allocate() == EOF ) + return EOF; + setg(0,0,0); + } else { + if (in_avail()) { + return EOF; + } + if (out_waiting()) { + if (flushbuf() == EOF) + return EOF; + } + } + + int bl = blen(); + setp( base(), base() + bl); + + if ( c != EOF ) { + + *pptr() = c; + pbump(1); + + } + + return 0; + +} + +int gzfilebuf::sync() { + + if ( !is_open() ) + return EOF; + + if ( out_waiting() ) + return flushbuf(); + + return 0; + +} + +int gzfilebuf::flushbuf() { + + int n; + char *q; + + q = pbase(); + n = pptr() - q; + + if ( gzwrite( file, q, n) < n ) + return EOF; + + setp(0,0); + + return 0; + +} + +int gzfilebuf::fillbuf() { + + int required; + char *p; + + p = base(); + + required = blen(); + + int t = gzread( file, p, required ); + + if ( t <= 0) return EOF; + + setg( base(), base(), base()+t); + + return t; + +} + +gzfilestream_common::gzfilestream_common() : + ios( gzfilestream_common::rdbuf() ) +{ } + +gzfilestream_common::~gzfilestream_common() +{ } + +void gzfilestream_common::attach( int fd, int io_mode ) { + + if ( !buffer.attach( fd, io_mode) ) + clear( ios::failbit | ios::badbit ); + else + clear(); + +} + +void gzfilestream_common::open( const char *name, int io_mode ) { + + if ( !buffer.open( name, io_mode ) ) + clear( ios::failbit | ios::badbit ); + else + clear(); + +} + +void gzfilestream_common::close() { + + if ( !buffer.close() ) + clear( ios::failbit | ios::badbit ); + +} + +gzfilebuf *gzfilestream_common::rdbuf() +{ + return &buffer; +} + +gzifstream::gzifstream() : + ios( gzfilestream_common::rdbuf() ) +{ + clear( ios::badbit ); +} + +gzifstream::gzifstream( const char *name, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::open( name, io_mode ); +} + +gzifstream::gzifstream( int fd, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::attach( fd, io_mode ); +} + +gzifstream::~gzifstream() { } + +gzofstream::gzofstream() : + ios( gzfilestream_common::rdbuf() ) +{ + clear( ios::badbit ); +} + +gzofstream::gzofstream( const char *name, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::open( name, io_mode ); +} + +gzofstream::gzofstream( int fd, int io_mode ) : + ios( gzfilestream_common::rdbuf() ) +{ + gzfilestream_common::attach( fd, io_mode ); +} + +gzofstream::~gzofstream() { } diff --git a/zlib-1.2.11/contrib/iostream/zfstream.h b/zlib-1.2.11/contrib/iostream/zfstream.h new file mode 100644 index 00000000..ed79098a --- /dev/null +++ b/zlib-1.2.11/contrib/iostream/zfstream.h @@ -0,0 +1,128 @@ + +#ifndef zfstream_h +#define zfstream_h + +#include +#include "zlib.h" + +class gzfilebuf : public streambuf { + +public: + + gzfilebuf( ); + virtual ~gzfilebuf(); + + gzfilebuf *open( const char *name, int io_mode ); + gzfilebuf *attach( int file_descriptor, int io_mode ); + gzfilebuf *close(); + + int setcompressionlevel( int comp_level ); + int setcompressionstrategy( int comp_strategy ); + + inline int is_open() const { return (file !=NULL); } + + virtual streampos seekoff( streamoff, ios::seek_dir, int ); + + virtual int sync(); + +protected: + + virtual int underflow(); + virtual int overflow( int = EOF ); + +private: + + gzFile file; + short mode; + short own_file_descriptor; + + int flushbuf(); + int fillbuf(); + +}; + +class gzfilestream_common : virtual public ios { + + friend class gzifstream; + friend class gzofstream; + friend gzofstream &setcompressionlevel( gzofstream &, int ); + friend gzofstream &setcompressionstrategy( gzofstream &, int ); + +public: + virtual ~gzfilestream_common(); + + void attach( int fd, int io_mode ); + void open( const char *name, int io_mode ); + void close(); + +protected: + gzfilestream_common(); + +private: + gzfilebuf *rdbuf(); + + gzfilebuf buffer; + +}; + +class gzifstream : public gzfilestream_common, public istream { + +public: + + gzifstream(); + gzifstream( const char *name, int io_mode = ios::in ); + gzifstream( int fd, int io_mode = ios::in ); + + virtual ~gzifstream(); + +}; + +class gzofstream : public gzfilestream_common, public ostream { + +public: + + gzofstream(); + gzofstream( const char *name, int io_mode = ios::out ); + gzofstream( int fd, int io_mode = ios::out ); + + virtual ~gzofstream(); + +}; + +template class gzomanip { + friend gzofstream &operator<<(gzofstream &, const gzomanip &); +public: + gzomanip(gzofstream &(*f)(gzofstream &, T), T v) : func(f), val(v) { } +private: + gzofstream &(*func)(gzofstream &, T); + T val; +}; + +template gzofstream &operator<<(gzofstream &s, const gzomanip &m) +{ + return (*m.func)(s, m.val); +} + +inline gzofstream &setcompressionlevel( gzofstream &s, int l ) +{ + (s.rdbuf())->setcompressionlevel(l); + return s; +} + +inline gzofstream &setcompressionstrategy( gzofstream &s, int l ) +{ + (s.rdbuf())->setcompressionstrategy(l); + return s; +} + +inline gzomanip setcompressionlevel(int l) +{ + return gzomanip(&setcompressionlevel,l); +} + +inline gzomanip setcompressionstrategy(int l) +{ + return gzomanip(&setcompressionstrategy,l); +} + +#endif diff --git a/zlib-1.2.11/contrib/iostream2/zstream.h b/zlib-1.2.11/contrib/iostream2/zstream.h new file mode 100644 index 00000000..43d2332b --- /dev/null +++ b/zlib-1.2.11/contrib/iostream2/zstream.h @@ -0,0 +1,307 @@ +/* + * + * Copyright (c) 1997 + * Christian Michelsen Research AS + * Advanced Computing + * Fantoftvegen 38, 5036 BERGEN, Norway + * http://www.cmr.no + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Christian Michelsen Research AS makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef ZSTREAM__H +#define ZSTREAM__H + +/* + * zstream.h - C++ interface to the 'zlib' general purpose compression library + * $Id: zstream.h 1.1 1997-06-25 12:00:56+02 tyge Exp tyge $ + */ + +#include +#include +#include +#include "zlib.h" + +#if defined(_WIN32) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +class zstringlen { +public: + zstringlen(class izstream&); + zstringlen(class ozstream&, const char*); + size_t value() const { return val.word; } +private: + struct Val { unsigned char byte; size_t word; } val; +}; + +// ----------------------------- izstream ----------------------------- + +class izstream +{ + public: + izstream() : m_fp(0) {} + izstream(FILE* fp) : m_fp(0) { open(fp); } + izstream(const char* name) : m_fp(0) { open(name); } + ~izstream() { close(); } + + /* Opens a gzip (.gz) file for reading. + * open() can be used to read a file which is not in gzip format; + * in this case read() will directly read from the file without + * decompression. errno can be checked to distinguish two error + * cases (if errno is zero, the zlib error is Z_MEM_ERROR). + */ + void open(const char* name) { + if (m_fp) close(); + m_fp = ::gzopen(name, "rb"); + } + + void open(FILE* fp) { + SET_BINARY_MODE(fp); + if (m_fp) close(); + m_fp = ::gzdopen(fileno(fp), "rb"); + } + + /* Flushes all pending input if necessary, closes the compressed file + * and deallocates all the (de)compression state. The return value is + * the zlib error number (see function error() below). + */ + int close() { + int r = ::gzclose(m_fp); + m_fp = 0; return r; + } + + /* Binary read the given number of bytes from the compressed file. + */ + int read(void* buf, size_t len) { + return ::gzread(m_fp, buf, len); + } + + /* Returns the error message for the last error which occurred on the + * given compressed file. errnum is set to zlib error number. If an + * error occurred in the file system and not in the compression library, + * errnum is set to Z_ERRNO and the application may consult errno + * to get the exact error code. + */ + const char* error(int* errnum) { + return ::gzerror(m_fp, errnum); + } + + gzFile fp() { return m_fp; } + + private: + gzFile m_fp; +}; + +/* + * Binary read the given (array of) object(s) from the compressed file. + * If the input file was not in gzip format, read() copies the objects number + * of bytes into the buffer. + * returns the number of uncompressed bytes actually read + * (0 for end of file, -1 for error). + */ +template +inline int read(izstream& zs, T* x, Items items) { + return ::gzread(zs.fp(), x, items*sizeof(T)); +} + +/* + * Binary input with the '>' operator. + */ +template +inline izstream& operator>(izstream& zs, T& x) { + ::gzread(zs.fp(), &x, sizeof(T)); + return zs; +} + + +inline zstringlen::zstringlen(izstream& zs) { + zs > val.byte; + if (val.byte == 255) zs > val.word; + else val.word = val.byte; +} + +/* + * Read length of string + the string with the '>' operator. + */ +inline izstream& operator>(izstream& zs, char* x) { + zstringlen len(zs); + ::gzread(zs.fp(), x, len.value()); + x[len.value()] = '\0'; + return zs; +} + +inline char* read_string(izstream& zs) { + zstringlen len(zs); + char* x = new char[len.value()+1]; + ::gzread(zs.fp(), x, len.value()); + x[len.value()] = '\0'; + return x; +} + +// ----------------------------- ozstream ----------------------------- + +class ozstream +{ + public: + ozstream() : m_fp(0), m_os(0) { + } + ozstream(FILE* fp, int level = Z_DEFAULT_COMPRESSION) + : m_fp(0), m_os(0) { + open(fp, level); + } + ozstream(const char* name, int level = Z_DEFAULT_COMPRESSION) + : m_fp(0), m_os(0) { + open(name, level); + } + ~ozstream() { + close(); + } + + /* Opens a gzip (.gz) file for writing. + * The compression level parameter should be in 0..9 + * errno can be checked to distinguish two error cases + * (if errno is zero, the zlib error is Z_MEM_ERROR). + */ + void open(const char* name, int level = Z_DEFAULT_COMPRESSION) { + char mode[4] = "wb\0"; + if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; + if (m_fp) close(); + m_fp = ::gzopen(name, mode); + } + + /* open from a FILE pointer. + */ + void open(FILE* fp, int level = Z_DEFAULT_COMPRESSION) { + SET_BINARY_MODE(fp); + char mode[4] = "wb\0"; + if (level != Z_DEFAULT_COMPRESSION) mode[2] = '0'+level; + if (m_fp) close(); + m_fp = ::gzdopen(fileno(fp), mode); + } + + /* Flushes all pending output if necessary, closes the compressed file + * and deallocates all the (de)compression state. The return value is + * the zlib error number (see function error() below). + */ + int close() { + if (m_os) { + ::gzwrite(m_fp, m_os->str(), m_os->pcount()); + delete[] m_os->str(); delete m_os; m_os = 0; + } + int r = ::gzclose(m_fp); m_fp = 0; return r; + } + + /* Binary write the given number of bytes into the compressed file. + */ + int write(const void* buf, size_t len) { + return ::gzwrite(m_fp, (voidp) buf, len); + } + + /* Flushes all pending output into the compressed file. The parameter + * _flush is as in the deflate() function. The return value is the zlib + * error number (see function gzerror below). flush() returns Z_OK if + * the flush_ parameter is Z_FINISH and all output could be flushed. + * flush() should be called only when strictly necessary because it can + * degrade compression. + */ + int flush(int _flush) { + os_flush(); + return ::gzflush(m_fp, _flush); + } + + /* Returns the error message for the last error which occurred on the + * given compressed file. errnum is set to zlib error number. If an + * error occurred in the file system and not in the compression library, + * errnum is set to Z_ERRNO and the application may consult errno + * to get the exact error code. + */ + const char* error(int* errnum) { + return ::gzerror(m_fp, errnum); + } + + gzFile fp() { return m_fp; } + + ostream& os() { + if (m_os == 0) m_os = new ostrstream; + return *m_os; + } + + void os_flush() { + if (m_os && m_os->pcount()>0) { + ostrstream* oss = new ostrstream; + oss->fill(m_os->fill()); + oss->flags(m_os->flags()); + oss->precision(m_os->precision()); + oss->width(m_os->width()); + ::gzwrite(m_fp, m_os->str(), m_os->pcount()); + delete[] m_os->str(); delete m_os; m_os = oss; + } + } + + private: + gzFile m_fp; + ostrstream* m_os; +}; + +/* + * Binary write the given (array of) object(s) into the compressed file. + * returns the number of uncompressed bytes actually written + * (0 in case of error). + */ +template +inline int write(ozstream& zs, const T* x, Items items) { + return ::gzwrite(zs.fp(), (voidp) x, items*sizeof(T)); +} + +/* + * Binary output with the '<' operator. + */ +template +inline ozstream& operator<(ozstream& zs, const T& x) { + ::gzwrite(zs.fp(), (voidp) &x, sizeof(T)); + return zs; +} + +inline zstringlen::zstringlen(ozstream& zs, const char* x) { + val.byte = 255; val.word = ::strlen(x); + if (val.word < 255) zs < (val.byte = val.word); + else zs < val; +} + +/* + * Write length of string + the string with the '<' operator. + */ +inline ozstream& operator<(ozstream& zs, const char* x) { + zstringlen len(zs, x); + ::gzwrite(zs.fp(), (voidp) x, len.value()); + return zs; +} + +#ifdef _MSC_VER +inline ozstream& operator<(ozstream& zs, char* const& x) { + return zs < (const char*) x; +} +#endif + +/* + * Ascii write with the << operator; + */ +template +inline ostream& operator<<(ozstream& zs, const T& x) { + zs.os_flush(); + return zs.os() << x; +} + +#endif diff --git a/zlib-1.2.11/contrib/iostream2/zstream_test.cpp b/zlib-1.2.11/contrib/iostream2/zstream_test.cpp new file mode 100644 index 00000000..6273f62d --- /dev/null +++ b/zlib-1.2.11/contrib/iostream2/zstream_test.cpp @@ -0,0 +1,25 @@ +#include "zstream.h" +#include +#include +#include + +void main() { + char h[256] = "Hello"; + char* g = "Goodbye"; + ozstream out("temp.gz"); + out < "This works well" < h < g; + out.close(); + + izstream in("temp.gz"); // read it back + char *x = read_string(in), *y = new char[256], z[256]; + in > y > z; + in.close(); + cout << x << endl << y << endl << z << endl; + + out.open("temp.gz"); // try ascii output; zcat temp.gz to see the results + out << setw(50) << setfill('#') << setprecision(20) << x << endl << y << endl << z << endl; + out << z << endl << y << endl << x << endl; + out << 1.1234567890123456789 << endl; + + delete[] x; delete[] y; +} diff --git a/zlib-1.2.11/contrib/iostream3/README b/zlib-1.2.11/contrib/iostream3/README new file mode 100644 index 00000000..f7b319ab --- /dev/null +++ b/zlib-1.2.11/contrib/iostream3/README @@ -0,0 +1,35 @@ +These classes provide a C++ stream interface to the zlib library. It allows you +to do things like: + + gzofstream outf("blah.gz"); + outf << "These go into the gzip file " << 123 << endl; + +It does this by deriving a specialized stream buffer for gzipped files, which is +the way Stroustrup would have done it. :-> + +The gzifstream and gzofstream classes were originally written by Kevin Ruland +and made available in the zlib contrib/iostream directory. The older version still +compiles under gcc 2.xx, but not under gcc 3.xx, which sparked the development of +this version. + +The new classes are as standard-compliant as possible, closely following the +approach of the standard library's fstream classes. It compiles under gcc versions +3.2 and 3.3, but not under gcc 2.xx. This is mainly due to changes in the standard +library naming scheme. The new version of gzifstream/gzofstream/gzfilebuf differs +from the previous one in the following respects: +- added showmanyc +- added setbuf, with support for unbuffered output via setbuf(0,0) +- a few bug fixes of stream behavior +- gzipped output file opened with default compression level instead of maximum level +- setcompressionlevel()/strategy() members replaced by single setcompression() + +The code is provided "as is", with the permission to use, copy, modify, distribute +and sell it for any purpose without fee. + +Ludwig Schwardt + + +DSP Lab +Electrical & Electronic Engineering Department +University of Stellenbosch +South Africa diff --git a/zlib-1.2.11/contrib/iostream3/TODO b/zlib-1.2.11/contrib/iostream3/TODO new file mode 100644 index 00000000..7032f97b --- /dev/null +++ b/zlib-1.2.11/contrib/iostream3/TODO @@ -0,0 +1,17 @@ +Possible upgrades to gzfilebuf: + +- The ability to do putback (e.g. putbackfail) + +- The ability to seek (zlib supports this, but could be slow/tricky) + +- Simultaneous read/write access (does it make sense?) + +- Support for ios_base::ate open mode + +- Locale support? + +- Check public interface to see which calls give problems + (due to dependence on library internals) + +- Override operator<<(ostream&, gzfilebuf*) to allow direct copying + of stream buffer to stream ( i.e. os << is.rdbuf(); ) diff --git a/zlib-1.2.11/contrib/iostream3/test.cc b/zlib-1.2.11/contrib/iostream3/test.cc new file mode 100644 index 00000000..94235334 --- /dev/null +++ b/zlib-1.2.11/contrib/iostream3/test.cc @@ -0,0 +1,50 @@ +/* + * Test program for gzifstream and gzofstream + * + * by Ludwig Schwardt + * original version by Kevin Ruland + */ + +#include "zfstream.h" +#include // for cout + +int main() { + + gzofstream outf; + gzifstream inf; + char buf[80]; + + outf.open("test1.txt.gz"); + outf << "The quick brown fox sidestepped the lazy canine\n" + << 1.3 << "\nPlan " << 9 << std::endl; + outf.close(); + std::cout << "Wrote the following message to 'test1.txt.gz' (check with zcat or zless):\n" + << "The quick brown fox sidestepped the lazy canine\n" + << 1.3 << "\nPlan " << 9 << std::endl; + + std::cout << "\nReading 'test1.txt.gz' (buffered) produces:\n"; + inf.open("test1.txt.gz"); + while (inf.getline(buf,80,'\n')) { + std::cout << buf << "\t(" << inf.rdbuf()->in_avail() << " chars left in buffer)\n"; + } + inf.close(); + + outf.rdbuf()->pubsetbuf(0,0); + outf.open("test2.txt.gz"); + outf << setcompression(Z_NO_COMPRESSION) + << "The quick brown fox sidestepped the lazy canine\n" + << 1.3 << "\nPlan " << 9 << std::endl; + outf.close(); + std::cout << "\nWrote the same message to 'test2.txt.gz' in uncompressed form"; + + std::cout << "\nReading 'test2.txt.gz' (unbuffered) produces:\n"; + inf.rdbuf()->pubsetbuf(0,0); + inf.open("test2.txt.gz"); + while (inf.getline(buf,80,'\n')) { + std::cout << buf << "\t(" << inf.rdbuf()->in_avail() << " chars left in buffer)\n"; + } + inf.close(); + + return 0; + +} diff --git a/zlib-1.2.11/contrib/iostream3/zfstream.cc b/zlib-1.2.11/contrib/iostream3/zfstream.cc new file mode 100644 index 00000000..94eb9334 --- /dev/null +++ b/zlib-1.2.11/contrib/iostream3/zfstream.cc @@ -0,0 +1,479 @@ +/* + * A C++ I/O streams interface to the zlib gz* functions + * + * by Ludwig Schwardt + * original version by Kevin Ruland + * + * This version is standard-compliant and compatible with gcc 3.x. + */ + +#include "zfstream.h" +#include // for strcpy, strcat, strlen (mode strings) +#include // for BUFSIZ + +// Internal buffer sizes (default and "unbuffered" versions) +#define BIGBUFSIZE BUFSIZ +#define SMALLBUFSIZE 1 + +/*****************************************************************************/ + +// Default constructor +gzfilebuf::gzfilebuf() +: file(NULL), io_mode(std::ios_base::openmode(0)), own_fd(false), + buffer(NULL), buffer_size(BIGBUFSIZE), own_buffer(true) +{ + // No buffers to start with + this->disable_buffer(); +} + +// Destructor +gzfilebuf::~gzfilebuf() +{ + // Sync output buffer and close only if responsible for file + // (i.e. attached streams should be left open at this stage) + this->sync(); + if (own_fd) + this->close(); + // Make sure internal buffer is deallocated + this->disable_buffer(); +} + +// Set compression level and strategy +int +gzfilebuf::setcompression(int comp_level, + int comp_strategy) +{ + return gzsetparams(file, comp_level, comp_strategy); +} + +// Open gzipped file +gzfilebuf* +gzfilebuf::open(const char *name, + std::ios_base::openmode mode) +{ + // Fail if file already open + if (this->is_open()) + return NULL; + // Don't support simultaneous read/write access (yet) + if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) + return NULL; + + // Build mode string for gzopen and check it [27.8.1.3.2] + char char_mode[6] = "\0\0\0\0\0"; + if (!this->open_mode(mode, char_mode)) + return NULL; + + // Attempt to open file + if ((file = gzopen(name, char_mode)) == NULL) + return NULL; + + // On success, allocate internal buffer and set flags + this->enable_buffer(); + io_mode = mode; + own_fd = true; + return this; +} + +// Attach to gzipped file +gzfilebuf* +gzfilebuf::attach(int fd, + std::ios_base::openmode mode) +{ + // Fail if file already open + if (this->is_open()) + return NULL; + // Don't support simultaneous read/write access (yet) + if ((mode & std::ios_base::in) && (mode & std::ios_base::out)) + return NULL; + + // Build mode string for gzdopen and check it [27.8.1.3.2] + char char_mode[6] = "\0\0\0\0\0"; + if (!this->open_mode(mode, char_mode)) + return NULL; + + // Attempt to attach to file + if ((file = gzdopen(fd, char_mode)) == NULL) + return NULL; + + // On success, allocate internal buffer and set flags + this->enable_buffer(); + io_mode = mode; + own_fd = false; + return this; +} + +// Close gzipped file +gzfilebuf* +gzfilebuf::close() +{ + // Fail immediately if no file is open + if (!this->is_open()) + return NULL; + // Assume success + gzfilebuf* retval = this; + // Attempt to sync and close gzipped file + if (this->sync() == -1) + retval = NULL; + if (gzclose(file) < 0) + retval = NULL; + // File is now gone anyway (postcondition [27.8.1.3.8]) + file = NULL; + own_fd = false; + // Destroy internal buffer if it exists + this->disable_buffer(); + return retval; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +// Convert int open mode to mode string +bool +gzfilebuf::open_mode(std::ios_base::openmode mode, + char* c_mode) const +{ + bool testb = mode & std::ios_base::binary; + bool testi = mode & std::ios_base::in; + bool testo = mode & std::ios_base::out; + bool testt = mode & std::ios_base::trunc; + bool testa = mode & std::ios_base::app; + + // Check for valid flag combinations - see [27.8.1.3.2] (Table 92) + // Original zfstream hardcoded the compression level to maximum here... + // Double the time for less than 1% size improvement seems + // excessive though - keeping it at the default level + // To change back, just append "9" to the next three mode strings + if (!testi && testo && !testt && !testa) + strcpy(c_mode, "w"); + if (!testi && testo && !testt && testa) + strcpy(c_mode, "a"); + if (!testi && testo && testt && !testa) + strcpy(c_mode, "w"); + if (testi && !testo && !testt && !testa) + strcpy(c_mode, "r"); + // No read/write mode yet +// if (testi && testo && !testt && !testa) +// strcpy(c_mode, "r+"); +// if (testi && testo && testt && !testa) +// strcpy(c_mode, "w+"); + + // Mode string should be empty for invalid combination of flags + if (strlen(c_mode) == 0) + return false; + if (testb) + strcat(c_mode, "b"); + return true; +} + +// Determine number of characters in internal get buffer +std::streamsize +gzfilebuf::showmanyc() +{ + // Calls to underflow will fail if file not opened for reading + if (!this->is_open() || !(io_mode & std::ios_base::in)) + return -1; + // Make sure get area is in use + if (this->gptr() && (this->gptr() < this->egptr())) + return std::streamsize(this->egptr() - this->gptr()); + else + return 0; +} + +// Fill get area from gzipped file +gzfilebuf::int_type +gzfilebuf::underflow() +{ + // If something is left in the get area by chance, return it + // (this shouldn't normally happen, as underflow is only supposed + // to be called when gptr >= egptr, but it serves as error check) + if (this->gptr() && (this->gptr() < this->egptr())) + return traits_type::to_int_type(*(this->gptr())); + + // If the file hasn't been opened for reading, produce error + if (!this->is_open() || !(io_mode & std::ios_base::in)) + return traits_type::eof(); + + // Attempt to fill internal buffer from gzipped file + // (buffer must be guaranteed to exist...) + int bytes_read = gzread(file, buffer, buffer_size); + // Indicates error or EOF + if (bytes_read <= 0) + { + // Reset get area + this->setg(buffer, buffer, buffer); + return traits_type::eof(); + } + // Make all bytes read from file available as get area + this->setg(buffer, buffer, buffer + bytes_read); + + // Return next character in get area + return traits_type::to_int_type(*(this->gptr())); +} + +// Write put area to gzipped file +gzfilebuf::int_type +gzfilebuf::overflow(int_type c) +{ + // Determine whether put area is in use + if (this->pbase()) + { + // Double-check pointer range + if (this->pptr() > this->epptr() || this->pptr() < this->pbase()) + return traits_type::eof(); + // Add extra character to buffer if not EOF + if (!traits_type::eq_int_type(c, traits_type::eof())) + { + *(this->pptr()) = traits_type::to_char_type(c); + this->pbump(1); + } + // Number of characters to write to file + int bytes_to_write = this->pptr() - this->pbase(); + // Overflow doesn't fail if nothing is to be written + if (bytes_to_write > 0) + { + // If the file hasn't been opened for writing, produce error + if (!this->is_open() || !(io_mode & std::ios_base::out)) + return traits_type::eof(); + // If gzipped file won't accept all bytes written to it, fail + if (gzwrite(file, this->pbase(), bytes_to_write) != bytes_to_write) + return traits_type::eof(); + // Reset next pointer to point to pbase on success + this->pbump(-bytes_to_write); + } + } + // Write extra character to file if not EOF + else if (!traits_type::eq_int_type(c, traits_type::eof())) + { + // If the file hasn't been opened for writing, produce error + if (!this->is_open() || !(io_mode & std::ios_base::out)) + return traits_type::eof(); + // Impromptu char buffer (allows "unbuffered" output) + char_type last_char = traits_type::to_char_type(c); + // If gzipped file won't accept this character, fail + if (gzwrite(file, &last_char, 1) != 1) + return traits_type::eof(); + } + + // If you got here, you have succeeded (even if c was EOF) + // The return value should therefore be non-EOF + if (traits_type::eq_int_type(c, traits_type::eof())) + return traits_type::not_eof(c); + else + return c; +} + +// Assign new buffer +std::streambuf* +gzfilebuf::setbuf(char_type* p, + std::streamsize n) +{ + // First make sure stuff is sync'ed, for safety + if (this->sync() == -1) + return NULL; + // If buffering is turned off on purpose via setbuf(0,0), still allocate one... + // "Unbuffered" only really refers to put [27.8.1.4.10], while get needs at + // least a buffer of size 1 (very inefficient though, therefore make it bigger?) + // This follows from [27.5.2.4.3]/12 (gptr needs to point at something, it seems) + if (!p || !n) + { + // Replace existing buffer (if any) with small internal buffer + this->disable_buffer(); + buffer = NULL; + buffer_size = 0; + own_buffer = true; + this->enable_buffer(); + } + else + { + // Replace existing buffer (if any) with external buffer + this->disable_buffer(); + buffer = p; + buffer_size = n; + own_buffer = false; + this->enable_buffer(); + } + return this; +} + +// Write put area to gzipped file (i.e. ensures that put area is empty) +int +gzfilebuf::sync() +{ + return traits_type::eq_int_type(this->overflow(), traits_type::eof()) ? -1 : 0; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +// Allocate internal buffer +void +gzfilebuf::enable_buffer() +{ + // If internal buffer required, allocate one + if (own_buffer && !buffer) + { + // Check for buffered vs. "unbuffered" + if (buffer_size > 0) + { + // Allocate internal buffer + buffer = new char_type[buffer_size]; + // Get area starts empty and will be expanded by underflow as need arises + this->setg(buffer, buffer, buffer); + // Setup entire internal buffer as put area. + // The one-past-end pointer actually points to the last element of the buffer, + // so that overflow(c) can safely add the extra character c to the sequence. + // These pointers remain in place for the duration of the buffer + this->setp(buffer, buffer + buffer_size - 1); + } + else + { + // Even in "unbuffered" case, (small?) get buffer is still required + buffer_size = SMALLBUFSIZE; + buffer = new char_type[buffer_size]; + this->setg(buffer, buffer, buffer); + // "Unbuffered" means no put buffer + this->setp(0, 0); + } + } + else + { + // If buffer already allocated, reset buffer pointers just to make sure no + // stale chars are lying around + this->setg(buffer, buffer, buffer); + this->setp(buffer, buffer + buffer_size - 1); + } +} + +// Destroy internal buffer +void +gzfilebuf::disable_buffer() +{ + // If internal buffer exists, deallocate it + if (own_buffer && buffer) + { + // Preserve unbuffered status by zeroing size + if (!this->pbase()) + buffer_size = 0; + delete[] buffer; + buffer = NULL; + this->setg(0, 0, 0); + this->setp(0, 0); + } + else + { + // Reset buffer pointers to initial state if external buffer exists + this->setg(buffer, buffer, buffer); + if (buffer) + this->setp(buffer, buffer + buffer_size - 1); + else + this->setp(0, 0); + } +} + +/*****************************************************************************/ + +// Default constructor initializes stream buffer +gzifstream::gzifstream() +: std::istream(NULL), sb() +{ this->init(&sb); } + +// Initialize stream buffer and open file +gzifstream::gzifstream(const char* name, + std::ios_base::openmode mode) +: std::istream(NULL), sb() +{ + this->init(&sb); + this->open(name, mode); +} + +// Initialize stream buffer and attach to file +gzifstream::gzifstream(int fd, + std::ios_base::openmode mode) +: std::istream(NULL), sb() +{ + this->init(&sb); + this->attach(fd, mode); +} + +// Open file and go into fail() state if unsuccessful +void +gzifstream::open(const char* name, + std::ios_base::openmode mode) +{ + if (!sb.open(name, mode | std::ios_base::in)) + this->setstate(std::ios_base::failbit); + else + this->clear(); +} + +// Attach to file and go into fail() state if unsuccessful +void +gzifstream::attach(int fd, + std::ios_base::openmode mode) +{ + if (!sb.attach(fd, mode | std::ios_base::in)) + this->setstate(std::ios_base::failbit); + else + this->clear(); +} + +// Close file +void +gzifstream::close() +{ + if (!sb.close()) + this->setstate(std::ios_base::failbit); +} + +/*****************************************************************************/ + +// Default constructor initializes stream buffer +gzofstream::gzofstream() +: std::ostream(NULL), sb() +{ this->init(&sb); } + +// Initialize stream buffer and open file +gzofstream::gzofstream(const char* name, + std::ios_base::openmode mode) +: std::ostream(NULL), sb() +{ + this->init(&sb); + this->open(name, mode); +} + +// Initialize stream buffer and attach to file +gzofstream::gzofstream(int fd, + std::ios_base::openmode mode) +: std::ostream(NULL), sb() +{ + this->init(&sb); + this->attach(fd, mode); +} + +// Open file and go into fail() state if unsuccessful +void +gzofstream::open(const char* name, + std::ios_base::openmode mode) +{ + if (!sb.open(name, mode | std::ios_base::out)) + this->setstate(std::ios_base::failbit); + else + this->clear(); +} + +// Attach to file and go into fail() state if unsuccessful +void +gzofstream::attach(int fd, + std::ios_base::openmode mode) +{ + if (!sb.attach(fd, mode | std::ios_base::out)) + this->setstate(std::ios_base::failbit); + else + this->clear(); +} + +// Close file +void +gzofstream::close() +{ + if (!sb.close()) + this->setstate(std::ios_base::failbit); +} diff --git a/zlib-1.2.11/contrib/iostream3/zfstream.h b/zlib-1.2.11/contrib/iostream3/zfstream.h new file mode 100644 index 00000000..8574479a --- /dev/null +++ b/zlib-1.2.11/contrib/iostream3/zfstream.h @@ -0,0 +1,466 @@ +/* + * A C++ I/O streams interface to the zlib gz* functions + * + * by Ludwig Schwardt + * original version by Kevin Ruland + * + * This version is standard-compliant and compatible with gcc 3.x. + */ + +#ifndef ZFSTREAM_H +#define ZFSTREAM_H + +#include // not iostream, since we don't need cin/cout +#include +#include "zlib.h" + +/*****************************************************************************/ + +/** + * @brief Gzipped file stream buffer class. + * + * This class implements basic_filebuf for gzipped files. It doesn't yet support + * seeking (allowed by zlib but slow/limited), putback and read/write access + * (tricky). Otherwise, it attempts to be a drop-in replacement for the standard + * file streambuf. +*/ +class gzfilebuf : public std::streambuf +{ +public: + // Default constructor. + gzfilebuf(); + + // Destructor. + virtual + ~gzfilebuf(); + + /** + * @brief Set compression level and strategy on the fly. + * @param comp_level Compression level (see zlib.h for allowed values) + * @param comp_strategy Compression strategy (see zlib.h for allowed values) + * @return Z_OK on success, Z_STREAM_ERROR otherwise. + * + * Unfortunately, these parameters cannot be modified separately, as the + * previous zfstream version assumed. Since the strategy is seldom changed, + * it can default and setcompression(level) then becomes like the old + * setcompressionlevel(level). + */ + int + setcompression(int comp_level, + int comp_strategy = Z_DEFAULT_STRATEGY); + + /** + * @brief Check if file is open. + * @return True if file is open. + */ + bool + is_open() const { return (file != NULL); } + + /** + * @brief Open gzipped file. + * @param name File name. + * @param mode Open mode flags. + * @return @c this on success, NULL on failure. + */ + gzfilebuf* + open(const char* name, + std::ios_base::openmode mode); + + /** + * @brief Attach to already open gzipped file. + * @param fd File descriptor. + * @param mode Open mode flags. + * @return @c this on success, NULL on failure. + */ + gzfilebuf* + attach(int fd, + std::ios_base::openmode mode); + + /** + * @brief Close gzipped file. + * @return @c this on success, NULL on failure. + */ + gzfilebuf* + close(); + +protected: + /** + * @brief Convert ios open mode int to mode string used by zlib. + * @return True if valid mode flag combination. + */ + bool + open_mode(std::ios_base::openmode mode, + char* c_mode) const; + + /** + * @brief Number of characters available in stream buffer. + * @return Number of characters. + * + * This indicates number of characters in get area of stream buffer. + * These characters can be read without accessing the gzipped file. + */ + virtual std::streamsize + showmanyc(); + + /** + * @brief Fill get area from gzipped file. + * @return First character in get area on success, EOF on error. + * + * This actually reads characters from gzipped file to stream + * buffer. Always buffered. + */ + virtual int_type + underflow(); + + /** + * @brief Write put area to gzipped file. + * @param c Extra character to add to buffer contents. + * @return Non-EOF on success, EOF on error. + * + * This actually writes characters in stream buffer to + * gzipped file. With unbuffered output this is done one + * character at a time. + */ + virtual int_type + overflow(int_type c = traits_type::eof()); + + /** + * @brief Installs external stream buffer. + * @param p Pointer to char buffer. + * @param n Size of external buffer. + * @return @c this on success, NULL on failure. + * + * Call setbuf(0,0) to enable unbuffered output. + */ + virtual std::streambuf* + setbuf(char_type* p, + std::streamsize n); + + /** + * @brief Flush stream buffer to file. + * @return 0 on success, -1 on error. + * + * This calls underflow(EOF) to do the job. + */ + virtual int + sync(); + +// +// Some future enhancements +// +// virtual int_type uflow(); +// virtual int_type pbackfail(int_type c = traits_type::eof()); +// virtual pos_type +// seekoff(off_type off, +// std::ios_base::seekdir way, +// std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out); +// virtual pos_type +// seekpos(pos_type sp, +// std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out); + +private: + /** + * @brief Allocate internal buffer. + * + * This function is safe to call multiple times. It will ensure + * that a proper internal buffer exists if it is required. If the + * buffer already exists or is external, the buffer pointers will be + * reset to their original state. + */ + void + enable_buffer(); + + /** + * @brief Destroy internal buffer. + * + * This function is safe to call multiple times. It will ensure + * that the internal buffer is deallocated if it exists. In any + * case, it will also reset the buffer pointers. + */ + void + disable_buffer(); + + /** + * Underlying file pointer. + */ + gzFile file; + + /** + * Mode in which file was opened. + */ + std::ios_base::openmode io_mode; + + /** + * @brief True if this object owns file descriptor. + * + * This makes the class responsible for closing the file + * upon destruction. + */ + bool own_fd; + + /** + * @brief Stream buffer. + * + * For simplicity this remains allocated on the free store for the + * entire life span of the gzfilebuf object, unless replaced by setbuf. + */ + char_type* buffer; + + /** + * @brief Stream buffer size. + * + * Defaults to system default buffer size (typically 8192 bytes). + * Modified by setbuf. + */ + std::streamsize buffer_size; + + /** + * @brief True if this object owns stream buffer. + * + * This makes the class responsible for deleting the buffer + * upon destruction. + */ + bool own_buffer; +}; + +/*****************************************************************************/ + +/** + * @brief Gzipped file input stream class. + * + * This class implements ifstream for gzipped files. Seeking and putback + * is not supported yet. +*/ +class gzifstream : public std::istream +{ +public: + // Default constructor + gzifstream(); + + /** + * @brief Construct stream on gzipped file to be opened. + * @param name File name. + * @param mode Open mode flags (forced to contain ios::in). + */ + explicit + gzifstream(const char* name, + std::ios_base::openmode mode = std::ios_base::in); + + /** + * @brief Construct stream on already open gzipped file. + * @param fd File descriptor. + * @param mode Open mode flags (forced to contain ios::in). + */ + explicit + gzifstream(int fd, + std::ios_base::openmode mode = std::ios_base::in); + + /** + * Obtain underlying stream buffer. + */ + gzfilebuf* + rdbuf() const + { return const_cast(&sb); } + + /** + * @brief Check if file is open. + * @return True if file is open. + */ + bool + is_open() { return sb.is_open(); } + + /** + * @brief Open gzipped file. + * @param name File name. + * @param mode Open mode flags (forced to contain ios::in). + * + * Stream will be in state good() if file opens successfully; + * otherwise in state fail(). This differs from the behavior of + * ifstream, which never sets the state to good() and therefore + * won't allow you to reuse the stream for a second file unless + * you manually clear() the state. The choice is a matter of + * convenience. + */ + void + open(const char* name, + std::ios_base::openmode mode = std::ios_base::in); + + /** + * @brief Attach to already open gzipped file. + * @param fd File descriptor. + * @param mode Open mode flags (forced to contain ios::in). + * + * Stream will be in state good() if attach succeeded; otherwise + * in state fail(). + */ + void + attach(int fd, + std::ios_base::openmode mode = std::ios_base::in); + + /** + * @brief Close gzipped file. + * + * Stream will be in state fail() if close failed. + */ + void + close(); + +private: + /** + * Underlying stream buffer. + */ + gzfilebuf sb; +}; + +/*****************************************************************************/ + +/** + * @brief Gzipped file output stream class. + * + * This class implements ofstream for gzipped files. Seeking and putback + * is not supported yet. +*/ +class gzofstream : public std::ostream +{ +public: + // Default constructor + gzofstream(); + + /** + * @brief Construct stream on gzipped file to be opened. + * @param name File name. + * @param mode Open mode flags (forced to contain ios::out). + */ + explicit + gzofstream(const char* name, + std::ios_base::openmode mode = std::ios_base::out); + + /** + * @brief Construct stream on already open gzipped file. + * @param fd File descriptor. + * @param mode Open mode flags (forced to contain ios::out). + */ + explicit + gzofstream(int fd, + std::ios_base::openmode mode = std::ios_base::out); + + /** + * Obtain underlying stream buffer. + */ + gzfilebuf* + rdbuf() const + { return const_cast(&sb); } + + /** + * @brief Check if file is open. + * @return True if file is open. + */ + bool + is_open() { return sb.is_open(); } + + /** + * @brief Open gzipped file. + * @param name File name. + * @param mode Open mode flags (forced to contain ios::out). + * + * Stream will be in state good() if file opens successfully; + * otherwise in state fail(). This differs from the behavior of + * ofstream, which never sets the state to good() and therefore + * won't allow you to reuse the stream for a second file unless + * you manually clear() the state. The choice is a matter of + * convenience. + */ + void + open(const char* name, + std::ios_base::openmode mode = std::ios_base::out); + + /** + * @brief Attach to already open gzipped file. + * @param fd File descriptor. + * @param mode Open mode flags (forced to contain ios::out). + * + * Stream will be in state good() if attach succeeded; otherwise + * in state fail(). + */ + void + attach(int fd, + std::ios_base::openmode mode = std::ios_base::out); + + /** + * @brief Close gzipped file. + * + * Stream will be in state fail() if close failed. + */ + void + close(); + +private: + /** + * Underlying stream buffer. + */ + gzfilebuf sb; +}; + +/*****************************************************************************/ + +/** + * @brief Gzipped file output stream manipulator class. + * + * This class defines a two-argument manipulator for gzofstream. It is used + * as base for the setcompression(int,int) manipulator. +*/ +template + class gzomanip2 + { + public: + // Allows insertor to peek at internals + template + friend gzofstream& + operator<<(gzofstream&, + const gzomanip2&); + + // Constructor + gzomanip2(gzofstream& (*f)(gzofstream&, T1, T2), + T1 v1, + T2 v2); + private: + // Underlying manipulator function + gzofstream& + (*func)(gzofstream&, T1, T2); + + // Arguments for manipulator function + T1 val1; + T2 val2; + }; + +/*****************************************************************************/ + +// Manipulator function thunks through to stream buffer +inline gzofstream& +setcompression(gzofstream &gzs, int l, int s = Z_DEFAULT_STRATEGY) +{ + (gzs.rdbuf())->setcompression(l, s); + return gzs; +} + +// Manipulator constructor stores arguments +template + inline + gzomanip2::gzomanip2(gzofstream &(*f)(gzofstream &, T1, T2), + T1 v1, + T2 v2) + : func(f), val1(v1), val2(v2) + { } + +// Insertor applies underlying manipulator function to stream +template + inline gzofstream& + operator<<(gzofstream& s, const gzomanip2& m) + { return (*m.func)(s, m.val1, m.val2); } + +// Insert this onto stream to simplify setting of compression level +inline gzomanip2 +setcompression(int l, int s = Z_DEFAULT_STRATEGY) +{ return gzomanip2(&setcompression, l, s); } + +#endif // ZFSTREAM_H diff --git a/zlib-1.2.11/contrib/masmx64/bld_ml64.bat b/zlib-1.2.11/contrib/masmx64/bld_ml64.bat new file mode 100644 index 00000000..8f9343d0 --- /dev/null +++ b/zlib-1.2.11/contrib/masmx64/bld_ml64.bat @@ -0,0 +1,2 @@ +ml64.exe /Flinffasx64 /c /Zi inffasx64.asm +ml64.exe /Flgvmat64 /c /Zi gvmat64.asm diff --git a/zlib-1.2.11/contrib/masmx64/gvmat64.asm b/zlib-1.2.11/contrib/masmx64/gvmat64.asm new file mode 100644 index 00000000..9879c28b --- /dev/null +++ b/zlib-1.2.11/contrib/masmx64/gvmat64.asm @@ -0,0 +1,553 @@ +;uInt longest_match_x64( +; deflate_state *s, +; IPos cur_match); /* current match */ + +; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86_64 +; (AMD64 on Athlon 64, Opteron, Phenom +; and Intel EM64T on Pentium 4 with EM64T, Pentium D, Core 2 Duo, Core I5/I7) +; Copyright (C) 1995-2010 Jean-loup Gailly, Brian Raiter and Gilles Vollant. +; +; File written by Gilles Vollant, by converting to assembly the longest_match +; from Jean-loup Gailly in deflate.c of zLib and infoZip zip. +; +; and by taking inspiration on asm686 with masm, optimised assembly code +; from Brian Raiter, written 1998 +; +; This software is provided 'as-is', without any express or implied +; warranty. In no event will the authors be held liable for any damages +; arising from the use of this software. +; +; Permission is granted to anyone to use this software for any purpose, +; including commercial applications, and to alter it and redistribute it +; freely, subject to the following restrictions: +; +; 1. The origin of this software must not be misrepresented; you must not +; claim that you wrote the original software. If you use this software +; in a product, an acknowledgment in the product documentation would be +; appreciated but is not required. +; 2. Altered source versions must be plainly marked as such, and must not be +; misrepresented as being the original software +; 3. This notice may not be removed or altered from any source distribution. +; +; +; +; http://www.zlib.net +; http://www.winimage.com/zLibDll +; http://www.muppetlabs.com/~breadbox/software/assembly.html +; +; to compile this file for infozip Zip, I use option: +; ml64.exe /Flgvmat64 /c /Zi /DINFOZIP gvmat64.asm +; +; to compile this file for zLib, I use option: +; ml64.exe /Flgvmat64 /c /Zi gvmat64.asm +; Be carrefull to adapt zlib1222add below to your version of zLib +; (if you use a version of zLib before 1.0.4 or after 1.2.2.2, change +; value of zlib1222add later) +; +; This file compile with Microsoft Macro Assembler (x64) for AMD64 +; +; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK +; +; (you can get Windows WDK with ml64 for AMD64 from +; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) +; + + +;uInt longest_match(s, cur_match) +; deflate_state *s; +; IPos cur_match; /* current match */ +.code +longest_match PROC + + +;LocalVarsSize equ 88 + LocalVarsSize equ 72 + +; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12 +; free register : r14,r15 +; register can be saved : rsp + + chainlenwmask equ rsp + 8 - LocalVarsSize ; high word: current chain len + ; low word: s->wmask +;window equ rsp + xx - LocalVarsSize ; local copy of s->window ; stored in r10 +;windowbestlen equ rsp + xx - LocalVarsSize ; s->window + bestlen , use r10+r11 +;scanstart equ rsp + xx - LocalVarsSize ; first two bytes of string ; stored in r12w +;scanend equ rsp + xx - LocalVarsSize ; last two bytes of string use ebx +;scanalign equ rsp + xx - LocalVarsSize ; dword-misalignment of string r13 +;bestlen equ rsp + xx - LocalVarsSize ; size of best match so far -> r11d +;scan equ rsp + xx - LocalVarsSize ; ptr to string wanting match -> r9 +IFDEF INFOZIP +ELSE + nicematch equ (rsp + 16 - LocalVarsSize) ; a good enough match size +ENDIF + +save_rdi equ rsp + 24 - LocalVarsSize +save_rsi equ rsp + 32 - LocalVarsSize +save_rbx equ rsp + 40 - LocalVarsSize +save_rbp equ rsp + 48 - LocalVarsSize +save_r12 equ rsp + 56 - LocalVarsSize +save_r13 equ rsp + 64 - LocalVarsSize +;save_r14 equ rsp + 72 - LocalVarsSize +;save_r15 equ rsp + 80 - LocalVarsSize + + +; summary of register usage +; scanend ebx +; scanendw bx +; chainlenwmask edx +; curmatch rsi +; curmatchd esi +; windowbestlen r8 +; scanalign r9 +; scanalignd r9d +; window r10 +; bestlen r11 +; bestlend r11d +; scanstart r12d +; scanstartw r12w +; scan r13 +; nicematch r14d +; limit r15 +; limitd r15d +; prev rcx + +; all the +4 offsets are due to the addition of pending_buf_size (in zlib +; in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, remove the +4). +; Note : these value are good with a 8 bytes boundary pack structure + + + MAX_MATCH equ 258 + MIN_MATCH equ 3 + MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) + + +;;; Offsets for fields in the deflate_state structure. These numbers +;;; are calculated from the definition of deflate_state, with the +;;; assumption that the compiler will dword-align the fields. (Thus, +;;; changing the definition of deflate_state could easily cause this +;;; program to crash horribly, without so much as a warning at +;;; compile time. Sigh.) + +; all the +zlib1222add offsets are due to the addition of fields +; in zlib in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). +; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). +; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). + + +IFDEF INFOZIP + +_DATA SEGMENT +COMM window_size:DWORD +; WMask ; 7fff +COMM window:BYTE:010040H +COMM prev:WORD:08000H +; MatchLen : unused +; PrevMatch : unused +COMM strstart:DWORD +COMM match_start:DWORD +; Lookahead : ignore +COMM prev_length:DWORD ; PrevLen +COMM max_chain_length:DWORD +COMM good_match:DWORD +COMM nice_match:DWORD +prev_ad equ OFFSET prev +window_ad equ OFFSET window +nicematch equ nice_match +_DATA ENDS +WMask equ 07fffh + +ELSE + + IFNDEF zlib1222add + zlib1222add equ 8 + ENDIF +dsWSize equ 56+zlib1222add+(zlib1222add/2) +dsWMask equ 64+zlib1222add+(zlib1222add/2) +dsWindow equ 72+zlib1222add +dsPrev equ 88+zlib1222add +dsMatchLen equ 128+zlib1222add +dsPrevMatch equ 132+zlib1222add +dsStrStart equ 140+zlib1222add +dsMatchStart equ 144+zlib1222add +dsLookahead equ 148+zlib1222add +dsPrevLen equ 152+zlib1222add +dsMaxChainLen equ 156+zlib1222add +dsGoodMatch equ 172+zlib1222add +dsNiceMatch equ 176+zlib1222add + +window_size equ [ rcx + dsWSize] +WMask equ [ rcx + dsWMask] +window_ad equ [ rcx + dsWindow] +prev_ad equ [ rcx + dsPrev] +strstart equ [ rcx + dsStrStart] +match_start equ [ rcx + dsMatchStart] +Lookahead equ [ rcx + dsLookahead] ; 0ffffffffh on infozip +prev_length equ [ rcx + dsPrevLen] +max_chain_length equ [ rcx + dsMaxChainLen] +good_match equ [ rcx + dsGoodMatch] +nice_match equ [ rcx + dsNiceMatch] +ENDIF + +; parameter 1 in r8(deflate state s), param 2 in rdx (cur match) + +; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and +; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp +; +; All registers must be preserved across the call, except for +; rax, rcx, rdx, r8, r9, r10, and r11, which are scratch. + + + +;;; Save registers that the compiler may be using, and adjust esp to +;;; make room for our stack frame. + + +;;; Retrieve the function arguments. r8d will hold cur_match +;;; throughout the entire function. edx will hold the pointer to the +;;; deflate_state structure during the function's setup (before +;;; entering the main loop. + +; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match) + +; this clear high 32 bits of r8, which can be garbage in both r8 and rdx + + mov [save_rdi],rdi + mov [save_rsi],rsi + mov [save_rbx],rbx + mov [save_rbp],rbp +IFDEF INFOZIP + mov r8d,ecx +ELSE + mov r8d,edx +ENDIF + mov [save_r12],r12 + mov [save_r13],r13 +; mov [save_r14],r14 +; mov [save_r15],r15 + + +;;; uInt wmask = s->w_mask; +;;; unsigned chain_length = s->max_chain_length; +;;; if (s->prev_length >= s->good_match) { +;;; chain_length >>= 2; +;;; } + + mov edi, prev_length + mov esi, good_match + mov eax, WMask + mov ebx, max_chain_length + cmp edi, esi + jl LastMatchGood + shr ebx, 2 +LastMatchGood: + +;;; chainlen is decremented once beforehand so that the function can +;;; use the sign flag instead of the zero flag for the exit test. +;;; It is then shifted into the high word, to make room for the wmask +;;; value, which it will always accompany. + + dec ebx + shl ebx, 16 + or ebx, eax + +;;; on zlib only +;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + +IFDEF INFOZIP + mov [chainlenwmask], ebx +; on infozip nice_match = [nice_match] +ELSE + mov eax, nice_match + mov [chainlenwmask], ebx + mov r10d, Lookahead + cmp r10d, eax + cmovnl r10d, eax + mov [nicematch],r10d +ENDIF + +;;; register Bytef *scan = s->window + s->strstart; + mov r10, window_ad + mov ebp, strstart + lea r13, [r10 + rbp] + +;;; Determine how many bytes the scan ptr is off from being +;;; dword-aligned. + + mov r9,r13 + neg r13 + and r13,3 + +;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +;;; s->strstart - (IPos)MAX_DIST(s) : NIL; +IFDEF INFOZIP + mov eax,07efah ; MAX_DIST = (WSIZE-MIN_LOOKAHEAD) (0x8000-(3+8+1)) +ELSE + mov eax, window_size + sub eax, MIN_LOOKAHEAD +ENDIF + xor edi,edi + sub ebp, eax + + mov r11d, prev_length + + cmovng ebp,edi + +;;; int best_len = s->prev_length; + + +;;; Store the sum of s->window + best_len in esi locally, and in esi. + + lea rsi,[r10+r11] + +;;; register ush scan_start = *(ushf*)scan; +;;; register ush scan_end = *(ushf*)(scan+best_len-1); +;;; Posf *prev = s->prev; + + movzx r12d,word ptr [r9] + movzx ebx, word ptr [r9 + r11 - 1] + + mov rdi, prev_ad + +;;; Jump into the main loop. + + mov edx, [chainlenwmask] + + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + +LookupLoop1: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry1: + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + +LookupLoop2: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry2: + cmp bx,word ptr [rsi + r8 - 1] + jz LookupLoopIsZero + +LookupLoop4: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry4: + + cmp bx,word ptr [rsi + r8 - 1] + jnz LookupLoop1 + jmp LookupLoopIsZero + + +;;; do { +;;; match = s->window + cur_match; +;;; if (*(ushf*)(match+best_len-1) != scan_end || +;;; *(ushf*)match != scan_start) continue; +;;; [...] +;;; } while ((cur_match = prev[cur_match & wmask]) > limit +;;; && --chain_length != 0); +;;; +;;; Here is the inner loop of the function. The function will spend the +;;; majority of its time in this loop, and majority of that time will +;;; be spent in the first ten instructions. +;;; +;;; Within this loop: +;;; ebx = scanend +;;; r8d = curmatch +;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) +;;; esi = windowbestlen - i.e., (window + bestlen) +;;; edi = prev +;;; ebp = limit + +LookupLoop: + and r8d, edx + + movzx r8d, word ptr [rdi + r8*2] + cmp r8d, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow + +LoopEntry: + + cmp bx,word ptr [rsi + r8 - 1] + jnz LookupLoop1 +LookupLoopIsZero: + cmp r12w, word ptr [r10 + r8] + jnz LookupLoop1 + + +;;; Store the current value of chainlen. + mov [chainlenwmask], edx + +;;; Point edi to the string under scrutiny, and esi to the string we +;;; are hoping to match it up with. In actuality, esi and edi are +;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is +;;; initialized to -(MAX_MATCH_8 - scanalign). + + lea rsi,[r8+r10] + mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8) + lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8] + lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8] + + prefetcht1 [rsi+rdx] + prefetcht1 [rdi+rdx] + + +;;; Test the strings for equality, 8 bytes at a time. At the end, +;;; adjust rdx so that it is offset to the exact byte that mismatched. +;;; +;;; We already know at this point that the first three bytes of the +;;; strings match each other, and they can be safely passed over before +;;; starting the compare loop. So what this code does is skip over 0-3 +;;; bytes, as much as necessary in order to dword-align the edi +;;; pointer. (rsi will still be misaligned three times out of four.) +;;; +;;; It should be confessed that this loop usually does not represent +;;; much of the total running time. Replacing it with a more +;;; straightforward "rep cmpsb" would not drastically degrade +;;; performance. + + +LoopCmps: + mov rax, [rsi + rdx] + xor rax, [rdi + rdx] + jnz LeaveLoopCmps + + mov rax, [rsi + rdx + 8] + xor rax, [rdi + rdx + 8] + jnz LeaveLoopCmps8 + + + mov rax, [rsi + rdx + 8+8] + xor rax, [rdi + rdx + 8+8] + jnz LeaveLoopCmps16 + + add rdx,8+8+8 + + jnz short LoopCmps + jmp short LenMaximum +LeaveLoopCmps16: add rdx,8 +LeaveLoopCmps8: add rdx,8 +LeaveLoopCmps: + + test eax, 0000FFFFh + jnz LenLower + + test eax,0ffffffffh + + jnz LenLower32 + + add rdx,4 + shr rax,32 + or ax,ax + jnz LenLower + +LenLower32: + shr eax,16 + add rdx,2 +LenLower: sub al, 1 + adc rdx, 0 +;;; Calculate the length of the match. If it is longer than MAX_MATCH, +;;; then automatically accept it as the best possible match and leave. + + lea rax, [rdi + rdx] + sub rax, r9 + cmp eax, MAX_MATCH + jge LenMaximum + +;;; If the length of the match is not longer than the best match we +;;; have so far, then forget it and return to the lookup loop. +;/////////////////////////////////// + + cmp eax, r11d + jg LongerMatch + + lea rsi,[r10+r11] + + mov rdi, prev_ad + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; s->match_start = cur_match; +;;; best_len = len; +;;; if (len >= nice_match) break; +;;; scan_end = *(ushf*)(scan+best_len-1); + +LongerMatch: + mov r11d, eax + mov match_start, r8d + cmp eax, [nicematch] + jge LeaveNow + + lea rsi,[r10+rax] + + movzx ebx, word ptr [r9 + rax - 1] + mov rdi, prev_ad + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; Accept the current string, with the maximum possible length. + +LenMaximum: + mov r11d,MAX_MATCH + mov match_start, r8d + +;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; +;;; return s->lookahead; + +LeaveNow: +IFDEF INFOZIP + mov eax,r11d +ELSE + mov eax, Lookahead + cmp r11d, eax + cmovng eax, r11d +ENDIF + +;;; Restore the stack and return from whence we came. + + + mov rsi,[save_rsi] + mov rdi,[save_rdi] + mov rbx,[save_rbx] + mov rbp,[save_rbp] + mov r12,[save_r12] + mov r13,[save_r13] +; mov r14,[save_r14] +; mov r15,[save_r15] + + + ret 0 +; please don't remove this string ! +; Your can freely use gvmat64 in any free or commercial app +; but it is far better don't remove the string in the binary! + db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0 +longest_match ENDP + +match_init PROC + ret 0 +match_init ENDP + + +END diff --git a/zlib-1.2.11/contrib/masmx64/inffas8664.c b/zlib-1.2.11/contrib/masmx64/inffas8664.c new file mode 100644 index 00000000..e8af06fa --- /dev/null +++ b/zlib-1.2.11/contrib/masmx64/inffas8664.c @@ -0,0 +1,186 @@ +/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding + * version for AMD64 on Windows using Microsoft C compiler + * + * Copyright (C) 1995-2003 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Copyright (C) 2003 Chris Anderson + * Please use the copyright conditions above. + * + * 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant + * + * inffas8664.c call function inffas8664fnc in inffasx64.asm + * inffasx64.asm is automatically convert from AMD64 portion of inffas86.c + * + * Dec-29-2003 -- I added AMD64 inflate asm support. This version is also + * slightly quicker on x86 systems because, instead of using rep movsb to copy + * data, it uses rep movsw, which moves data in 2-byte chunks instead of single + * bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates + * from http://fedora.linux.duke.edu/fc1_x86_64 + * which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with + * 1GB ram. The 64-bit version is about 4% faster than the 32-bit version, + * when decompressing mozilla-source-1.3.tar.gz. + * + * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from + * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at + * the moment. I have successfully compiled and tested this code with gcc2.96, + * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S + * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX + * enabled. I will attempt to merge the MMX code into this version. Newer + * versions of this and inffast.S can be found at + * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ + * + */ + +#include +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* Mark Adler's comments from inffast.c: */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ + + + + typedef struct inffast_ar { +/* 64 32 x86 x86_64 */ +/* ar offset register */ +/* 0 0 */ void *esp; /* esp save */ +/* 8 4 */ void *ebp; /* ebp save */ +/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */ +/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */ +/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */ +/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */ +/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */ +/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */ +/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */ +/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */ +/* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */ +/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */ +/* 92 48 */ unsigned wsize; /* window size */ +/* 96 52 */ unsigned write; /* window write index */ +/*100 56 */ unsigned lmask; /* r12 mask for lcode */ +/*104 60 */ unsigned dmask; /* r13 mask for dcode */ +/*108 64 */ unsigned len; /* r14 match length */ +/*112 68 */ unsigned dist; /* r15 match distance */ +/*116 72 */ unsigned status; /* set when state chng*/ + } type_ar; +#ifdef ASMINF + +void inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + type_ar ar; + void inffas8664fnc(struct inffast_ar * par); + + + +#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64)) +#define PAD_AVAIL_IN 6 +#define PAD_AVAIL_OUT 258 +#else +#define PAD_AVAIL_IN 5 +#define PAD_AVAIL_OUT 257 +#endif + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + + ar.in = strm->next_in; + ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN); + ar.out = strm->next_out; + ar.beg = ar.out - (start - strm->avail_out); + ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT); + ar.wsize = state->wsize; + ar.write = state->wnext; + ar.window = state->window; + ar.hold = state->hold; + ar.bits = state->bits; + ar.lcode = state->lencode; + ar.dcode = state->distcode; + ar.lmask = (1U << state->lenbits) - 1; + ar.dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + /* align in on 1/2 hold size boundary */ + while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) { + ar.hold += (unsigned long)*ar.in++ << ar.bits; + ar.bits += 8; + } + + inffas8664fnc(&ar); + + if (ar.status > 1) { + if (ar.status == 2) + strm->msg = "invalid literal/length code"; + else if (ar.status == 3) + strm->msg = "invalid distance code"; + else + strm->msg = "invalid distance too far back"; + state->mode = BAD; + } + else if ( ar.status == 1 ) { + state->mode = TYPE; + } + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + ar.len = ar.bits >> 3; + ar.in -= ar.len; + ar.bits -= ar.len << 3; + ar.hold &= (1U << ar.bits) - 1; + + /* update state and return */ + strm->next_in = ar.in; + strm->next_out = ar.out; + strm->avail_in = (unsigned)(ar.in < ar.last ? + PAD_AVAIL_IN + (ar.last - ar.in) : + PAD_AVAIL_IN - (ar.in - ar.last)); + strm->avail_out = (unsigned)(ar.out < ar.end ? + PAD_AVAIL_OUT + (ar.end - ar.out) : + PAD_AVAIL_OUT - (ar.out - ar.end)); + state->hold = (unsigned long)ar.hold; + state->bits = ar.bits; + return; +} + +#endif diff --git a/zlib-1.2.11/contrib/masmx64/inffasx64.asm b/zlib-1.2.11/contrib/masmx64/inffasx64.asm new file mode 100644 index 00000000..60a8d89b --- /dev/null +++ b/zlib-1.2.11/contrib/masmx64/inffasx64.asm @@ -0,0 +1,396 @@ +; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding +; version for AMD64 on Windows using Microsoft C compiler +; +; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c +; inffasx64.asm is called by inffas8664.c, which contain more info. + + +; to compile this file, I use option +; ml64.exe /Flinffasx64 /c /Zi inffasx64.asm +; with Microsoft Macro Assembler (x64) for AMD64 +; + +; This file compile with Microsoft Macro Assembler (x64) for AMD64 +; +; ml64.exe is given with Visual Studio 2005/2008/2010 and Windows WDK +; +; (you can get Windows WDK with ml64 for AMD64 from +; http://www.microsoft.com/whdc/Devtools/wdk/default.mspx for low price) +; + + +.code +inffas8664fnc PROC + +; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and +; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp +; +; All registers must be preserved across the call, except for +; rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch. + + + mov [rsp-8],rsi + mov [rsp-16],rdi + mov [rsp-24],r12 + mov [rsp-32],r13 + mov [rsp-40],r14 + mov [rsp-48],r15 + mov [rsp-56],rbx + + mov rax,rcx + + mov [rax+8], rbp ; /* save regs rbp and rsp */ + mov [rax], rsp + + mov rsp, rax ; /* make rsp point to &ar */ + + mov rsi, [rsp+16] ; /* rsi = in */ + mov rdi, [rsp+32] ; /* rdi = out */ + mov r9, [rsp+24] ; /* r9 = last */ + mov r10, [rsp+48] ; /* r10 = end */ + mov rbp, [rsp+64] ; /* rbp = lcode */ + mov r11, [rsp+72] ; /* r11 = dcode */ + mov rdx, [rsp+80] ; /* rdx = hold */ + mov ebx, [rsp+88] ; /* ebx = bits */ + mov r12d, [rsp+100] ; /* r12d = lmask */ + mov r13d, [rsp+104] ; /* r13d = dmask */ + ; /* r14d = len */ + ; /* r15d = dist */ + + + cld + cmp r10, rdi + je L_one_time ; /* if only one decode left */ + cmp r9, rsi + + jne L_do_loop + + +L_one_time: + mov r8, r12 ; /* r8 = lmask */ + cmp bl, 32 + ja L_get_length_code_one_time + + lodsd ; /* eax = *(uint *)in++ */ + mov cl, bl ; /* cl = bits, needs it for shifting */ + add bl, 32 ; /* bits += 32 */ + shl rax, cl + or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ + jmp L_get_length_code_one_time + +ALIGN 4 +L_while_test: + cmp r10, rdi + jbe L_break_loop + cmp r9, rsi + jbe L_break_loop + +L_do_loop: + mov r8, r12 ; /* r8 = lmask */ + cmp bl, 32 + ja L_get_length_code ; /* if (32 < bits) */ + + lodsd ; /* eax = *(uint *)in++ */ + mov cl, bl ; /* cl = bits, needs it for shifting */ + add bl, 32 ; /* bits += 32 */ + shl rax, cl + or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ + +L_get_length_code: + and r8, rdx ; /* r8 &= hold */ + mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ + + mov cl, ah ; /* cl = this.bits */ + sub bl, ah ; /* bits -= this.bits */ + shr rdx, cl ; /* hold >>= this.bits */ + + test al, al + jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ + + mov r8, r12 ; /* r8 = lmask */ + shr eax, 16 ; /* output this.val char */ + stosb + +L_get_length_code_one_time: + and r8, rdx ; /* r8 &= hold */ + mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */ + +L_dolen: + mov cl, ah ; /* cl = this.bits */ + sub bl, ah ; /* bits -= this.bits */ + shr rdx, cl ; /* hold >>= this.bits */ + + test al, al + jnz L_test_for_length_base ; /* if (op != 0) 45.7% */ + + shr eax, 16 ; /* output this.val char */ + stosb + jmp L_while_test + +ALIGN 4 +L_test_for_length_base: + mov r14d, eax ; /* len = this */ + shr r14d, 16 ; /* len = this.val */ + mov cl, al + + test al, 16 + jz L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */ + and cl, 15 ; /* op &= 15 */ + jz L_decode_distance ; /* if (!op) */ + +L_add_bits_to_len: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx ; /* eax &= hold */ + shr rdx, cl + add r14d, eax ; /* len += hold & mask[op] */ + +L_decode_distance: + mov r8, r13 ; /* r8 = dmask */ + cmp bl, 32 + ja L_get_distance_code ; /* if (32 < bits) */ + + lodsd ; /* eax = *(uint *)in++ */ + mov cl, bl ; /* cl = bits, needs it for shifting */ + add bl, 32 ; /* bits += 32 */ + shl rax, cl + or rdx, rax ; /* hold |= *((uint *)in)++ << bits */ + +L_get_distance_code: + and r8, rdx ; /* r8 &= hold */ + mov eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */ + +L_dodist: + mov r15d, eax ; /* dist = this */ + shr r15d, 16 ; /* dist = this.val */ + mov cl, ah + sub bl, ah ; /* bits -= this.bits */ + shr rdx, cl ; /* hold >>= this.bits */ + mov cl, al ; /* cl = this.op */ + + test al, 16 ; /* if ((op & 16) == 0) */ + jz L_test_for_second_level_dist + and cl, 15 ; /* op &= 15 */ + jz L_check_dist_one + +L_add_bits_to_dist: + sub bl, cl + xor eax, eax + inc eax + shl eax, cl + dec eax ; /* (1 << op) - 1 */ + and eax, edx ; /* eax &= hold */ + shr rdx, cl + add r15d, eax ; /* dist += hold & ((1 << op) - 1) */ + +L_check_window: + mov r8, rsi ; /* save in so from can use it's reg */ + mov rax, rdi + sub rax, [rsp+40] ; /* nbytes = out - beg */ + + cmp eax, r15d + jb L_clip_window ; /* if (dist > nbytes) 4.2% */ + + mov ecx, r14d ; /* ecx = len */ + mov rsi, rdi + sub rsi, r15 ; /* from = out - dist */ + + sar ecx, 1 + jnc L_copy_two ; /* if len % 2 == 0 */ + + rep movsw + mov al, [rsi] + mov [rdi], al + inc rdi + + mov rsi, r8 ; /* move in back to %rsi, toss from */ + jmp L_while_test + +L_copy_two: + rep movsw + mov rsi, r8 ; /* move in back to %rsi, toss from */ + jmp L_while_test + +ALIGN 4 +L_check_dist_one: + cmp r15d, 1 ; /* if dist 1, is a memset */ + jne L_check_window + cmp [rsp+40], rdi ; /* if out == beg, outside window */ + je L_check_window + + mov ecx, r14d ; /* ecx = len */ + mov al, [rdi-1] + mov ah, al + + sar ecx, 1 + jnc L_set_two + mov [rdi], al + inc rdi + +L_set_two: + rep stosw + jmp L_while_test + +ALIGN 4 +L_test_for_second_level_length: + test al, 64 + jnz L_test_for_end_of_block ; /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx ; /* eax &= hold */ + add eax, r14d ; /* eax += len */ + mov eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/ + jmp L_dolen + +ALIGN 4 +L_test_for_second_level_dist: + test al, 64 + jnz L_invalid_distance_code ; /* if ((op & 64) != 0) */ + + xor eax, eax + inc eax + shl eax, cl + dec eax + and eax, edx ; /* eax &= hold */ + add eax, r15d ; /* eax += dist */ + mov eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/ + jmp L_dodist + +ALIGN 4 +L_clip_window: + mov ecx, eax ; /* ecx = nbytes */ + mov eax, [rsp+92] ; /* eax = wsize, prepare for dist cmp */ + neg ecx ; /* nbytes = -nbytes */ + + cmp eax, r15d + jb L_invalid_distance_too_far ; /* if (dist > wsize) */ + + add ecx, r15d ; /* nbytes = dist - nbytes */ + cmp dword ptr [rsp+96], 0 + jne L_wrap_around_window ; /* if (write != 0) */ + + mov rsi, [rsp+56] ; /* from = window */ + sub eax, ecx ; /* eax -= nbytes */ + add rsi, rax ; /* from += wsize - nbytes */ + + mov eax, r14d ; /* eax = len */ + cmp r14d, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* eax -= nbytes */ + rep movsb + mov rsi, rdi + sub rsi, r15 ; /* from = &out[ -dist ] */ + jmp L_do_copy + +ALIGN 4 +L_wrap_around_window: + mov eax, [rsp+96] ; /* eax = write */ + cmp ecx, eax + jbe L_contiguous_in_window ; /* if (write >= nbytes) */ + + mov esi, [rsp+92] ; /* from = wsize */ + add rsi, [rsp+56] ; /* from += window */ + add rsi, rax ; /* from += write */ + sub rsi, rcx ; /* from -= nbytes */ + sub ecx, eax ; /* nbytes -= write */ + + mov eax, r14d ; /* eax = len */ + cmp eax, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* len -= nbytes */ + rep movsb + mov rsi, [rsp+56] ; /* from = window */ + mov ecx, [rsp+96] ; /* nbytes = write */ + cmp eax, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* len -= nbytes */ + rep movsb + mov rsi, rdi + sub rsi, r15 ; /* from = out - dist */ + jmp L_do_copy + +ALIGN 4 +L_contiguous_in_window: + mov rsi, [rsp+56] ; /* rsi = window */ + add rsi, rax + sub rsi, rcx ; /* from += write - nbytes */ + + mov eax, r14d ; /* eax = len */ + cmp eax, ecx + jbe L_do_copy ; /* if (nbytes >= len) */ + + sub eax, ecx ; /* len -= nbytes */ + rep movsb + mov rsi, rdi + sub rsi, r15 ; /* from = out - dist */ + jmp L_do_copy ; /* if (nbytes >= len) */ + +ALIGN 4 +L_do_copy: + mov ecx, eax ; /* ecx = len */ + rep movsb + + mov rsi, r8 ; /* move in back to %esi, toss from */ + jmp L_while_test + +L_test_for_end_of_block: + test al, 32 + jz L_invalid_literal_length_code + mov dword ptr [rsp+116], 1 + jmp L_break_loop_with_status + +L_invalid_literal_length_code: + mov dword ptr [rsp+116], 2 + jmp L_break_loop_with_status + +L_invalid_distance_code: + mov dword ptr [rsp+116], 3 + jmp L_break_loop_with_status + +L_invalid_distance_too_far: + mov dword ptr [rsp+116], 4 + jmp L_break_loop_with_status + +L_break_loop: + mov dword ptr [rsp+116], 0 + +L_break_loop_with_status: +; /* put in, out, bits, and hold back into ar and pop esp */ + mov [rsp+16], rsi ; /* in */ + mov [rsp+32], rdi ; /* out */ + mov [rsp+88], ebx ; /* bits */ + mov [rsp+80], rdx ; /* hold */ + + mov rax, [rsp] ; /* restore rbp and rsp */ + mov rbp, [rsp+8] + mov rsp, rax + + + + mov rsi,[rsp-8] + mov rdi,[rsp-16] + mov r12,[rsp-24] + mov r13,[rsp-32] + mov r14,[rsp-40] + mov r15,[rsp-48] + mov rbx,[rsp-56] + + ret 0 +; : +; : "m" (ar) +; : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", +; "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" +; ); + +inffas8664fnc ENDP +;_TEXT ENDS +END diff --git a/zlib-1.2.11/contrib/masmx64/readme.txt b/zlib-1.2.11/contrib/masmx64/readme.txt new file mode 100644 index 00000000..2da67334 --- /dev/null +++ b/zlib-1.2.11/contrib/masmx64/readme.txt @@ -0,0 +1,31 @@ +Summary +------- +This directory contains ASM implementations of the functions +longest_match() and inflate_fast(), for 64 bits x86 (both AMD64 and Intel EM64t), +for use with Microsoft Macro Assembler (x64) for AMD64 and Microsoft C++ 64 bits. + +gvmat64.asm is written by Gilles Vollant (2005), by using Brian Raiter 686/32 bits + assembly optimized version from Jean-loup Gailly original longest_match function + +inffasx64.asm and inffas8664.c were written by Chris Anderson, by optimizing + original function from Mark Adler + +Use instructions +---------------- +Assemble the .asm files using MASM and put the object files into the zlib source +directory. You can also get object files here: + + http://www.winimage.com/zLibDll/zlib124_masm_obj.zip + +define ASMV and ASMINF in your project. Include inffas8664.c in your source tree, +and inffasx64.obj and gvmat64.obj as object to link. + + +Build instructions +------------------ +run bld_64.bat with Microsoft Macro Assembler (x64) for AMD64 (ml64.exe) + +ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK + +You can get Windows 2003 server DDK with ml64 and cl for AMD64 from + http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price) diff --git a/zlib-1.2.11/contrib/masmx86/bld_ml32.bat b/zlib-1.2.11/contrib/masmx86/bld_ml32.bat new file mode 100644 index 00000000..e1b86bf6 --- /dev/null +++ b/zlib-1.2.11/contrib/masmx86/bld_ml32.bat @@ -0,0 +1,2 @@ +ml /coff /Zi /c /Flmatch686.lst match686.asm +ml /coff /Zi /c /Flinffas32.lst inffas32.asm diff --git a/zlib-1.2.11/contrib/masmx86/inffas32.asm b/zlib-1.2.11/contrib/masmx86/inffas32.asm new file mode 100644 index 00000000..03d20f83 --- /dev/null +++ b/zlib-1.2.11/contrib/masmx86/inffas32.asm @@ -0,0 +1,1080 @@ +;/* inffas32.asm is a hand tuned assembler version of inffast.c -- fast decoding +; * +; * inffas32.asm is derivated from inffas86.c, with translation of assembly code +; * +; * Copyright (C) 1995-2003 Mark Adler +; * For conditions of distribution and use, see copyright notice in zlib.h +; * +; * Copyright (C) 2003 Chris Anderson +; * Please use the copyright conditions above. +; * +; * Mar-13-2003 -- Most of this is derived from inffast.S which is derived from +; * the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at +; * the moment. I have successfully compiled and tested this code with gcc2.96, +; * gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S +; * compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX +; * enabled. I will attempt to merge the MMX code into this version. Newer +; * versions of this and inffast.S can be found at +; * http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/ +; * +; * 2005 : modification by Gilles Vollant +; */ +; For Visual C++ 4.x and higher and ML 6.x and higher +; ml.exe is in directory \MASM611C of Win95 DDK +; ml.exe is also distributed in http://www.masm32.com/masmdl.htm +; and in VC++2003 toolkit at http://msdn.microsoft.com/visualc/vctoolkit2003/ +; +; +; compile with command line option +; ml /coff /Zi /c /Flinffas32.lst inffas32.asm + +; if you define NO_GZIP (see inflate.h), compile with +; ml /coff /Zi /c /Flinffas32.lst /DNO_GUNZIP inffas32.asm + + +; zlib122sup is 0 fort zlib 1.2.2.1 and lower +; zlib122sup is 8 fort zlib 1.2.2.2 and more (with addition of dmax and head +; in inflate_state in inflate.h) +zlib1222sup equ 8 + + +IFDEF GUNZIP + INFLATE_MODE_TYPE equ 11 + INFLATE_MODE_BAD equ 26 +ELSE + IFNDEF NO_GUNZIP + INFLATE_MODE_TYPE equ 11 + INFLATE_MODE_BAD equ 26 + ELSE + INFLATE_MODE_TYPE equ 3 + INFLATE_MODE_BAD equ 17 + ENDIF +ENDIF + + +; 75 "inffast.S" +;FILE "inffast.S" + +;;;GLOBAL _inflate_fast + +;;;SECTION .text + + + + .586p + .mmx + + name inflate_fast_x86 + .MODEL FLAT + +_DATA segment +inflate_fast_use_mmx: + dd 1 + + +_TEXT segment + + + +ALIGN 4 + db 'Fast decoding Code from Chris Anderson' + db 0 + +ALIGN 4 +invalid_literal_length_code_msg: + db 'invalid literal/length code' + db 0 + +ALIGN 4 +invalid_distance_code_msg: + db 'invalid distance code' + db 0 + +ALIGN 4 +invalid_distance_too_far_msg: + db 'invalid distance too far back' + db 0 + + +ALIGN 4 +inflate_fast_mask: +dd 0 +dd 1 +dd 3 +dd 7 +dd 15 +dd 31 +dd 63 +dd 127 +dd 255 +dd 511 +dd 1023 +dd 2047 +dd 4095 +dd 8191 +dd 16383 +dd 32767 +dd 65535 +dd 131071 +dd 262143 +dd 524287 +dd 1048575 +dd 2097151 +dd 4194303 +dd 8388607 +dd 16777215 +dd 33554431 +dd 67108863 +dd 134217727 +dd 268435455 +dd 536870911 +dd 1073741823 +dd 2147483647 +dd 4294967295 + + +mode_state equ 0 ;/* state->mode */ +wsize_state equ (32+zlib1222sup) ;/* state->wsize */ +write_state equ (36+4+zlib1222sup) ;/* state->write */ +window_state equ (40+4+zlib1222sup) ;/* state->window */ +hold_state equ (44+4+zlib1222sup) ;/* state->hold */ +bits_state equ (48+4+zlib1222sup) ;/* state->bits */ +lencode_state equ (64+4+zlib1222sup) ;/* state->lencode */ +distcode_state equ (68+4+zlib1222sup) ;/* state->distcode */ +lenbits_state equ (72+4+zlib1222sup) ;/* state->lenbits */ +distbits_state equ (76+4+zlib1222sup) ;/* state->distbits */ + + +;;SECTION .text +; 205 "inffast.S" +;GLOBAL inflate_fast_use_mmx + +;SECTION .data + + +; GLOBAL inflate_fast_use_mmx:object +;.size inflate_fast_use_mmx, 4 +; 226 "inffast.S" +;SECTION .text + +ALIGN 4 +_inflate_fast proc near +.FPO (16, 4, 0, 0, 1, 0) + push edi + push esi + push ebp + push ebx + pushfd + sub esp,64 + cld + + + + + mov esi, [esp+88] + mov edi, [esi+28] + + + + + + + + mov edx, [esi+4] + mov eax, [esi+0] + + add edx,eax + sub edx,11 + + mov [esp+44],eax + mov [esp+20],edx + + mov ebp, [esp+92] + mov ecx, [esi+16] + mov ebx, [esi+12] + + sub ebp,ecx + neg ebp + add ebp,ebx + + sub ecx,257 + add ecx,ebx + + mov [esp+60],ebx + mov [esp+40],ebp + mov [esp+16],ecx +; 285 "inffast.S" + mov eax, [edi+lencode_state] + mov ecx, [edi+distcode_state] + + mov [esp+8],eax + mov [esp+12],ecx + + mov eax,1 + mov ecx, [edi+lenbits_state] + shl eax,cl + dec eax + mov [esp+0],eax + + mov eax,1 + mov ecx, [edi+distbits_state] + shl eax,cl + dec eax + mov [esp+4],eax + + mov eax, [edi+wsize_state] + mov ecx, [edi+write_state] + mov edx, [edi+window_state] + + mov [esp+52],eax + mov [esp+48],ecx + mov [esp+56],edx + + mov ebp, [edi+hold_state] + mov ebx, [edi+bits_state] +; 321 "inffast.S" + mov esi, [esp+44] + mov ecx, [esp+20] + cmp ecx,esi + ja L_align_long + + add ecx,11 + sub ecx,esi + mov eax,12 + sub eax,ecx + lea edi, [esp+28] + rep movsb + mov ecx,eax + xor eax,eax + rep stosb + lea esi, [esp+28] + mov [esp+20],esi + jmp L_is_aligned + + +L_align_long: + test esi,3 + jz L_is_aligned + xor eax,eax + mov al, [esi] + inc esi + mov ecx,ebx + add ebx,8 + shl eax,cl + or ebp,eax + jmp L_align_long + +L_is_aligned: + mov edi, [esp+60] +; 366 "inffast.S" +L_check_mmx: + cmp dword ptr [inflate_fast_use_mmx],2 + je L_init_mmx + ja L_do_loop + + push eax + push ebx + push ecx + push edx + pushfd + mov eax, [esp] + xor dword ptr [esp],0200000h + + + + + popfd + pushfd + pop edx + xor edx,eax + jz L_dont_use_mmx + xor eax,eax + cpuid + cmp ebx,0756e6547h + jne L_dont_use_mmx + cmp ecx,06c65746eh + jne L_dont_use_mmx + cmp edx,049656e69h + jne L_dont_use_mmx + mov eax,1 + cpuid + shr eax,8 + and eax,15 + cmp eax,6 + jne L_dont_use_mmx + test edx,0800000h + jnz L_use_mmx + jmp L_dont_use_mmx +L_use_mmx: + mov dword ptr [inflate_fast_use_mmx],2 + jmp L_check_mmx_pop +L_dont_use_mmx: + mov dword ptr [inflate_fast_use_mmx],3 +L_check_mmx_pop: + pop edx + pop ecx + pop ebx + pop eax + jmp L_check_mmx +; 426 "inffast.S" +ALIGN 4 +L_do_loop: +; 437 "inffast.S" + cmp bl,15 + ja L_get_length_code + + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + +L_get_length_code: + mov edx, [esp+0] + mov ecx, [esp+8] + and edx,ebp + mov eax, [ecx+edx*4] + +L_dolen: + + + + + + + mov cl,ah + sub bl,ah + shr ebp,cl + + + + + + + test al,al + jnz L_test_for_length_base + + shr eax,16 + stosb + +L_while_test: + + + cmp [esp+16],edi + jbe L_break_loop + + cmp [esp+20],esi + ja L_do_loop + jmp L_break_loop + +L_test_for_length_base: +; 502 "inffast.S" + mov edx,eax + shr edx,16 + mov cl,al + + test al,16 + jz L_test_for_second_level_length + and cl,15 + jz L_save_len + cmp bl,cl + jae L_add_bits_to_len + + mov ch,cl + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + mov cl,ch + +L_add_bits_to_len: + mov eax,1 + shl eax,cl + dec eax + sub bl,cl + and eax,ebp + shr ebp,cl + add edx,eax + +L_save_len: + mov [esp+24],edx + + +L_decode_distance: +; 549 "inffast.S" + cmp bl,15 + ja L_get_distance_code + + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + +L_get_distance_code: + mov edx, [esp+4] + mov ecx, [esp+12] + and edx,ebp + mov eax, [ecx+edx*4] + + +L_dodist: + mov edx,eax + shr edx,16 + mov cl,ah + sub bl,ah + shr ebp,cl +; 584 "inffast.S" + mov cl,al + + test al,16 + jz L_test_for_second_level_dist + and cl,15 + jz L_check_dist_one + cmp bl,cl + jae L_add_bits_to_dist + + mov ch,cl + xor eax,eax + lodsw + mov cl,bl + add bl,16 + shl eax,cl + or ebp,eax + mov cl,ch + +L_add_bits_to_dist: + mov eax,1 + shl eax,cl + dec eax + sub bl,cl + and eax,ebp + shr ebp,cl + add edx,eax + jmp L_check_window + +L_check_window: +; 625 "inffast.S" + mov [esp+44],esi + mov eax,edi + sub eax, [esp+40] + + cmp eax,edx + jb L_clip_window + + mov ecx, [esp+24] + mov esi,edi + sub esi,edx + + sub ecx,3 + mov al, [esi] + mov [edi],al + mov al, [esi+1] + mov dl, [esi+2] + add esi,3 + mov [edi+1],al + mov [edi+2],dl + add edi,3 + rep movsb + + mov esi, [esp+44] + jmp L_while_test + +ALIGN 4 +L_check_dist_one: + cmp edx,1 + jne L_check_window + cmp [esp+40],edi + je L_check_window + + dec edi + mov ecx, [esp+24] + mov al, [edi] + sub ecx,3 + + mov [edi+1],al + mov [edi+2],al + mov [edi+3],al + add edi,4 + rep stosb + + jmp L_while_test + +ALIGN 4 +L_test_for_second_level_length: + + + + + test al,64 + jnz L_test_for_end_of_block + + mov eax,1 + shl eax,cl + dec eax + and eax,ebp + add eax,edx + mov edx, [esp+8] + mov eax, [edx+eax*4] + jmp L_dolen + +ALIGN 4 +L_test_for_second_level_dist: + + + + + test al,64 + jnz L_invalid_distance_code + + mov eax,1 + shl eax,cl + dec eax + and eax,ebp + add eax,edx + mov edx, [esp+12] + mov eax, [edx+eax*4] + jmp L_dodist + +ALIGN 4 +L_clip_window: +; 721 "inffast.S" + mov ecx,eax + mov eax, [esp+52] + neg ecx + mov esi, [esp+56] + + cmp eax,edx + jb L_invalid_distance_too_far + + add ecx,edx + cmp dword ptr [esp+48],0 + jne L_wrap_around_window + + sub eax,ecx + add esi,eax +; 749 "inffast.S" + mov eax, [esp+24] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + jmp L_do_copy1 + + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + jmp L_do_copy1 + +L_wrap_around_window: +; 793 "inffast.S" + mov eax, [esp+48] + cmp ecx,eax + jbe L_contiguous_in_window + + add esi, [esp+52] + add esi,eax + sub esi,ecx + sub ecx,eax + + + mov eax, [esp+24] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi, [esp+56] + mov ecx, [esp+48] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + jmp L_do_copy1 + +L_contiguous_in_window: +; 836 "inffast.S" + add esi,eax + sub esi,ecx + + + mov eax, [esp+24] + cmp eax,ecx + jbe L_do_copy1 + + sub eax,ecx + rep movsb + mov esi,edi + sub esi,edx + +L_do_copy1: +; 862 "inffast.S" + mov ecx,eax + rep movsb + + mov esi, [esp+44] + jmp L_while_test +; 878 "inffast.S" +ALIGN 4 +L_init_mmx: + emms + + + + + + movd mm0,ebp + mov ebp,ebx +; 896 "inffast.S" + movd mm4,dword ptr [esp+0] + movq mm3,mm4 + movd mm5,dword ptr [esp+4] + movq mm2,mm5 + pxor mm1,mm1 + mov ebx, [esp+8] + jmp L_do_loop_mmx + +ALIGN 4 +L_do_loop_mmx: + psrlq mm0,mm1 + + cmp ebp,32 + ja L_get_length_code_mmx + + movd mm6,ebp + movd mm7,dword ptr [esi] + add esi,4 + psllq mm7,mm6 + add ebp,32 + por mm0,mm7 + +L_get_length_code_mmx: + pand mm4,mm0 + movd eax,mm4 + movq mm4,mm3 + mov eax, [ebx+eax*4] + +L_dolen_mmx: + movzx ecx,ah + movd mm1,ecx + sub ebp,ecx + + test al,al + jnz L_test_for_length_base_mmx + + shr eax,16 + stosb + +L_while_test_mmx: + + + cmp [esp+16],edi + jbe L_break_loop + + cmp [esp+20],esi + ja L_do_loop_mmx + jmp L_break_loop + +L_test_for_length_base_mmx: + + mov edx,eax + shr edx,16 + + test al,16 + jz L_test_for_second_level_length_mmx + and eax,15 + jz L_decode_distance_mmx + + psrlq mm0,mm1 + movd mm1,eax + movd ecx,mm0 + sub ebp,eax + and ecx, [inflate_fast_mask+eax*4] + add edx,ecx + +L_decode_distance_mmx: + psrlq mm0,mm1 + + cmp ebp,32 + ja L_get_dist_code_mmx + + movd mm6,ebp + movd mm7,dword ptr [esi] + add esi,4 + psllq mm7,mm6 + add ebp,32 + por mm0,mm7 + +L_get_dist_code_mmx: + mov ebx, [esp+12] + pand mm5,mm0 + movd eax,mm5 + movq mm5,mm2 + mov eax, [ebx+eax*4] + +L_dodist_mmx: + + movzx ecx,ah + mov ebx,eax + shr ebx,16 + sub ebp,ecx + movd mm1,ecx + + test al,16 + jz L_test_for_second_level_dist_mmx + and eax,15 + jz L_check_dist_one_mmx + +L_add_bits_to_dist_mmx: + psrlq mm0,mm1 + movd mm1,eax + movd ecx,mm0 + sub ebp,eax + and ecx, [inflate_fast_mask+eax*4] + add ebx,ecx + +L_check_window_mmx: + mov [esp+44],esi + mov eax,edi + sub eax, [esp+40] + + cmp eax,ebx + jb L_clip_window_mmx + + mov ecx,edx + mov esi,edi + sub esi,ebx + + sub ecx,3 + mov al, [esi] + mov [edi],al + mov al, [esi+1] + mov dl, [esi+2] + add esi,3 + mov [edi+1],al + mov [edi+2],dl + add edi,3 + rep movsb + + mov esi, [esp+44] + mov ebx, [esp+8] + jmp L_while_test_mmx + +ALIGN 4 +L_check_dist_one_mmx: + cmp ebx,1 + jne L_check_window_mmx + cmp [esp+40],edi + je L_check_window_mmx + + dec edi + mov ecx,edx + mov al, [edi] + sub ecx,3 + + mov [edi+1],al + mov [edi+2],al + mov [edi+3],al + add edi,4 + rep stosb + + mov ebx, [esp+8] + jmp L_while_test_mmx + +ALIGN 4 +L_test_for_second_level_length_mmx: + test al,64 + jnz L_test_for_end_of_block + + and eax,15 + psrlq mm0,mm1 + movd ecx,mm0 + and ecx, [inflate_fast_mask+eax*4] + add ecx,edx + mov eax, [ebx+ecx*4] + jmp L_dolen_mmx + +ALIGN 4 +L_test_for_second_level_dist_mmx: + test al,64 + jnz L_invalid_distance_code + + and eax,15 + psrlq mm0,mm1 + movd ecx,mm0 + and ecx, [inflate_fast_mask+eax*4] + mov eax, [esp+12] + add ecx,ebx + mov eax, [eax+ecx*4] + jmp L_dodist_mmx + +ALIGN 4 +L_clip_window_mmx: + + mov ecx,eax + mov eax, [esp+52] + neg ecx + mov esi, [esp+56] + + cmp eax,ebx + jb L_invalid_distance_too_far + + add ecx,ebx + cmp dword ptr [esp+48],0 + jne L_wrap_around_window_mmx + + sub eax,ecx + add esi,eax + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + jmp L_do_copy1_mmx + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + jmp L_do_copy1_mmx + +L_wrap_around_window_mmx: + + mov eax, [esp+48] + cmp ecx,eax + jbe L_contiguous_in_window_mmx + + add esi, [esp+52] + add esi,eax + sub esi,ecx + sub ecx,eax + + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi, [esp+56] + mov ecx, [esp+48] + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + jmp L_do_copy1_mmx + +L_contiguous_in_window_mmx: + + add esi,eax + sub esi,ecx + + + cmp edx,ecx + jbe L_do_copy1_mmx + + sub edx,ecx + rep movsb + mov esi,edi + sub esi,ebx + +L_do_copy1_mmx: + + + mov ecx,edx + rep movsb + + mov esi, [esp+44] + mov ebx, [esp+8] + jmp L_while_test_mmx +; 1174 "inffast.S" +L_invalid_distance_code: + + + + + + mov ecx, invalid_distance_code_msg + mov edx,INFLATE_MODE_BAD + jmp L_update_stream_state + +L_test_for_end_of_block: + + + + + + test al,32 + jz L_invalid_literal_length_code + + mov ecx,0 + mov edx,INFLATE_MODE_TYPE + jmp L_update_stream_state + +L_invalid_literal_length_code: + + + + + + mov ecx, invalid_literal_length_code_msg + mov edx,INFLATE_MODE_BAD + jmp L_update_stream_state + +L_invalid_distance_too_far: + + + + mov esi, [esp+44] + mov ecx, invalid_distance_too_far_msg + mov edx,INFLATE_MODE_BAD + jmp L_update_stream_state + +L_update_stream_state: + + mov eax, [esp+88] + test ecx,ecx + jz L_skip_msg + mov [eax+24],ecx +L_skip_msg: + mov eax, [eax+28] + mov [eax+mode_state],edx + jmp L_break_loop + +ALIGN 4 +L_break_loop: +; 1243 "inffast.S" + cmp dword ptr [inflate_fast_use_mmx],2 + jne L_update_next_in + + + + mov ebx,ebp + +L_update_next_in: +; 1266 "inffast.S" + mov eax, [esp+88] + mov ecx,ebx + mov edx, [eax+28] + shr ecx,3 + sub esi,ecx + shl ecx,3 + sub ebx,ecx + mov [eax+12],edi + mov [edx+bits_state],ebx + mov ecx,ebx + + lea ebx, [esp+28] + cmp [esp+20],ebx + jne L_buf_not_used + + sub esi,ebx + mov ebx, [eax+0] + mov [esp+20],ebx + add esi,ebx + mov ebx, [eax+4] + sub ebx,11 + add [esp+20],ebx + +L_buf_not_used: + mov [eax+0],esi + + mov ebx,1 + shl ebx,cl + dec ebx + + + + + + cmp dword ptr [inflate_fast_use_mmx],2 + jne L_update_hold + + + + psrlq mm0,mm1 + movd ebp,mm0 + + emms + +L_update_hold: + + + + and ebp,ebx + mov [edx+hold_state],ebp + + + + + mov ebx, [esp+20] + cmp ebx,esi + jbe L_last_is_smaller + + sub ebx,esi + add ebx,11 + mov [eax+4],ebx + jmp L_fixup_out +L_last_is_smaller: + sub esi,ebx + neg esi + add esi,11 + mov [eax+4],esi + + + + +L_fixup_out: + + mov ebx, [esp+16] + cmp ebx,edi + jbe L_end_is_smaller + + sub ebx,edi + add ebx,257 + mov [eax+16],ebx + jmp L_done +L_end_is_smaller: + sub edi,ebx + neg edi + add edi,257 + mov [eax+16],edi + + + + + +L_done: + add esp,64 + popfd + pop ebx + pop ebp + pop esi + pop edi + ret +_inflate_fast endp + +_TEXT ends +end diff --git a/zlib-1.2.11/contrib/masmx86/match686.asm b/zlib-1.2.11/contrib/masmx86/match686.asm new file mode 100644 index 00000000..3b09212f --- /dev/null +++ b/zlib-1.2.11/contrib/masmx86/match686.asm @@ -0,0 +1,479 @@ +; match686.asm -- Asm portion of the optimized longest_match for 32 bits x86 +; Copyright (C) 1995-1996 Jean-loup Gailly, Brian Raiter and Gilles Vollant. +; File written by Gilles Vollant, by converting match686.S from Brian Raiter +; for MASM. This is as assembly version of longest_match +; from Jean-loup Gailly in deflate.c +; +; http://www.zlib.net +; http://www.winimage.com/zLibDll +; http://www.muppetlabs.com/~breadbox/software/assembly.html +; +; For Visual C++ 4.x and higher and ML 6.x and higher +; ml.exe is distributed in +; http://www.microsoft.com/downloads/details.aspx?FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64 +; +; this file contain two implementation of longest_match +; +; this longest_match was written by Brian raiter (1998), optimized for Pentium Pro +; (and the faster known version of match_init on modern Core 2 Duo and AMD Phenom) +; +; for using an assembly version of longest_match, you need define ASMV in project +; +; compile the asm file running +; ml /coff /Zi /c /Flmatch686.lst match686.asm +; and do not include match686.obj in your project +; +; note: contrib of zLib 1.2.3 and earlier contained both a deprecated version for +; Pentium (prior Pentium Pro) and this version for Pentium Pro and modern processor +; with autoselect (with cpu detection code) +; if you want support the old pentium optimization, you can still use these version +; +; this file is not optimized for old pentium, but it compatible with all x86 32 bits +; processor (starting 80386) +; +; +; see below : zlib1222add must be adjuster if you use a zlib version < 1.2.2.2 + +;uInt longest_match(s, cur_match) +; deflate_state *s; +; IPos cur_match; /* current match */ + + NbStack equ 76 + cur_match equ dword ptr[esp+NbStack-0] + str_s equ dword ptr[esp+NbStack-4] +; 5 dword on top (ret,ebp,esi,edi,ebx) + adrret equ dword ptr[esp+NbStack-8] + pushebp equ dword ptr[esp+NbStack-12] + pushedi equ dword ptr[esp+NbStack-16] + pushesi equ dword ptr[esp+NbStack-20] + pushebx equ dword ptr[esp+NbStack-24] + + chain_length equ dword ptr [esp+NbStack-28] + limit equ dword ptr [esp+NbStack-32] + best_len equ dword ptr [esp+NbStack-36] + window equ dword ptr [esp+NbStack-40] + prev equ dword ptr [esp+NbStack-44] + scan_start equ word ptr [esp+NbStack-48] + wmask equ dword ptr [esp+NbStack-52] + match_start_ptr equ dword ptr [esp+NbStack-56] + nice_match equ dword ptr [esp+NbStack-60] + scan equ dword ptr [esp+NbStack-64] + + windowlen equ dword ptr [esp+NbStack-68] + match_start equ dword ptr [esp+NbStack-72] + strend equ dword ptr [esp+NbStack-76] + NbStackAdd equ (NbStack-24) + + .386p + + name gvmatch + .MODEL FLAT + + + +; all the +zlib1222add offsets are due to the addition of fields +; in zlib in the deflate_state structure since the asm code was first written +; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)"). +; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0"). +; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8"). + + zlib1222add equ 8 + +; Note : these value are good with a 8 bytes boundary pack structure + dep_chain_length equ 74h+zlib1222add + dep_window equ 30h+zlib1222add + dep_strstart equ 64h+zlib1222add + dep_prev_length equ 70h+zlib1222add + dep_nice_match equ 88h+zlib1222add + dep_w_size equ 24h+zlib1222add + dep_prev equ 38h+zlib1222add + dep_w_mask equ 2ch+zlib1222add + dep_good_match equ 84h+zlib1222add + dep_match_start equ 68h+zlib1222add + dep_lookahead equ 6ch+zlib1222add + + +_TEXT segment + +IFDEF NOUNDERLINE + public longest_match + public match_init +ELSE + public _longest_match + public _match_init +ENDIF + + MAX_MATCH equ 258 + MIN_MATCH equ 3 + MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1) + + + +MAX_MATCH equ 258 +MIN_MATCH equ 3 +MIN_LOOKAHEAD equ (MAX_MATCH + MIN_MATCH + 1) +MAX_MATCH_8_ equ ((MAX_MATCH + 7) AND 0FFF0h) + + +;;; stack frame offsets + +chainlenwmask equ esp + 0 ; high word: current chain len + ; low word: s->wmask +window equ esp + 4 ; local copy of s->window +windowbestlen equ esp + 8 ; s->window + bestlen +scanstart equ esp + 16 ; first two bytes of string +scanend equ esp + 12 ; last two bytes of string +scanalign equ esp + 20 ; dword-misalignment of string +nicematch equ esp + 24 ; a good enough match size +bestlen equ esp + 28 ; size of best match so far +scan equ esp + 32 ; ptr to string wanting match + +LocalVarsSize equ 36 +; saved ebx byte esp + 36 +; saved edi byte esp + 40 +; saved esi byte esp + 44 +; saved ebp byte esp + 48 +; return address byte esp + 52 +deflatestate equ esp + 56 ; the function arguments +curmatch equ esp + 60 + +;;; Offsets for fields in the deflate_state structure. These numbers +;;; are calculated from the definition of deflate_state, with the +;;; assumption that the compiler will dword-align the fields. (Thus, +;;; changing the definition of deflate_state could easily cause this +;;; program to crash horribly, without so much as a warning at +;;; compile time. Sigh.) + +dsWSize equ 36+zlib1222add +dsWMask equ 44+zlib1222add +dsWindow equ 48+zlib1222add +dsPrev equ 56+zlib1222add +dsMatchLen equ 88+zlib1222add +dsPrevMatch equ 92+zlib1222add +dsStrStart equ 100+zlib1222add +dsMatchStart equ 104+zlib1222add +dsLookahead equ 108+zlib1222add +dsPrevLen equ 112+zlib1222add +dsMaxChainLen equ 116+zlib1222add +dsGoodMatch equ 132+zlib1222add +dsNiceMatch equ 136+zlib1222add + + +;;; match686.asm -- Pentium-Pro-optimized version of longest_match() +;;; Written for zlib 1.1.2 +;;; Copyright (C) 1998 Brian Raiter +;;; You can look at http://www.muppetlabs.com/~breadbox/software/assembly.html +;;; +;; +;; This software is provided 'as-is', without any express or implied +;; warranty. In no event will the authors be held liable for any damages +;; arising from the use of this software. +;; +;; Permission is granted to anyone to use this software for any purpose, +;; including commercial applications, and to alter it and redistribute it +;; freely, subject to the following restrictions: +;; +;; 1. The origin of this software must not be misrepresented; you must not +;; claim that you wrote the original software. If you use this software +;; in a product, an acknowledgment in the product documentation would be +;; appreciated but is not required. +;; 2. Altered source versions must be plainly marked as such, and must not be +;; misrepresented as being the original software +;; 3. This notice may not be removed or altered from any source distribution. +;; + +;GLOBAL _longest_match, _match_init + + +;SECTION .text + +;;; uInt longest_match(deflate_state *deflatestate, IPos curmatch) + +;_longest_match: + IFDEF NOUNDERLINE + longest_match proc near + ELSE + _longest_match proc near + ENDIF +.FPO (9, 4, 0, 0, 1, 0) + +;;; Save registers that the compiler may be using, and adjust esp to +;;; make room for our stack frame. + + push ebp + push edi + push esi + push ebx + sub esp, LocalVarsSize + +;;; Retrieve the function arguments. ecx will hold cur_match +;;; throughout the entire function. edx will hold the pointer to the +;;; deflate_state structure during the function's setup (before +;;; entering the main loop. + + mov edx, [deflatestate] + mov ecx, [curmatch] + +;;; uInt wmask = s->w_mask; +;;; unsigned chain_length = s->max_chain_length; +;;; if (s->prev_length >= s->good_match) { +;;; chain_length >>= 2; +;;; } + + mov eax, [edx + dsPrevLen] + mov ebx, [edx + dsGoodMatch] + cmp eax, ebx + mov eax, [edx + dsWMask] + mov ebx, [edx + dsMaxChainLen] + jl LastMatchGood + shr ebx, 2 +LastMatchGood: + +;;; chainlen is decremented once beforehand so that the function can +;;; use the sign flag instead of the zero flag for the exit test. +;;; It is then shifted into the high word, to make room for the wmask +;;; value, which it will always accompany. + + dec ebx + shl ebx, 16 + or ebx, eax + mov [chainlenwmask], ebx + +;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + mov eax, [edx + dsNiceMatch] + mov ebx, [edx + dsLookahead] + cmp ebx, eax + jl LookaheadLess + mov ebx, eax +LookaheadLess: mov [nicematch], ebx + +;;; register Bytef *scan = s->window + s->strstart; + + mov esi, [edx + dsWindow] + mov [window], esi + mov ebp, [edx + dsStrStart] + lea edi, [esi + ebp] + mov [scan], edi + +;;; Determine how many bytes the scan ptr is off from being +;;; dword-aligned. + + mov eax, edi + neg eax + and eax, 3 + mov [scanalign], eax + +;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ? +;;; s->strstart - (IPos)MAX_DIST(s) : NIL; + + mov eax, [edx + dsWSize] + sub eax, MIN_LOOKAHEAD + sub ebp, eax + jg LimitPositive + xor ebp, ebp +LimitPositive: + +;;; int best_len = s->prev_length; + + mov eax, [edx + dsPrevLen] + mov [bestlen], eax + +;;; Store the sum of s->window + best_len in esi locally, and in esi. + + add esi, eax + mov [windowbestlen], esi + +;;; register ush scan_start = *(ushf*)scan; +;;; register ush scan_end = *(ushf*)(scan+best_len-1); +;;; Posf *prev = s->prev; + + movzx ebx, word ptr [edi] + mov [scanstart], ebx + movzx ebx, word ptr [edi + eax - 1] + mov [scanend], ebx + mov edi, [edx + dsPrev] + +;;; Jump into the main loop. + + mov edx, [chainlenwmask] + jmp short LoopEntry + +align 4 + +;;; do { +;;; match = s->window + cur_match; +;;; if (*(ushf*)(match+best_len-1) != scan_end || +;;; *(ushf*)match != scan_start) continue; +;;; [...] +;;; } while ((cur_match = prev[cur_match & wmask]) > limit +;;; && --chain_length != 0); +;;; +;;; Here is the inner loop of the function. The function will spend the +;;; majority of its time in this loop, and majority of that time will +;;; be spent in the first ten instructions. +;;; +;;; Within this loop: +;;; ebx = scanend +;;; ecx = curmatch +;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) +;;; esi = windowbestlen - i.e., (window + bestlen) +;;; edi = prev +;;; ebp = limit + +LookupLoop: + and ecx, edx + movzx ecx, word ptr [edi + ecx*2] + cmp ecx, ebp + jbe LeaveNow + sub edx, 00010000h + js LeaveNow +LoopEntry: movzx eax, word ptr [esi + ecx - 1] + cmp eax, ebx + jnz LookupLoop + mov eax, [window] + movzx eax, word ptr [eax + ecx] + cmp eax, [scanstart] + jnz LookupLoop + +;;; Store the current value of chainlen. + + mov [chainlenwmask], edx + +;;; Point edi to the string under scrutiny, and esi to the string we +;;; are hoping to match it up with. In actuality, esi and edi are +;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is +;;; initialized to -(MAX_MATCH_8 - scanalign). + + mov esi, [window] + mov edi, [scan] + add esi, ecx + mov eax, [scanalign] + mov edx, 0fffffef8h; -(MAX_MATCH_8) + lea edi, [edi + eax + 0108h] ;MAX_MATCH_8] + lea esi, [esi + eax + 0108h] ;MAX_MATCH_8] + +;;; Test the strings for equality, 8 bytes at a time. At the end, +;;; adjust edx so that it is offset to the exact byte that mismatched. +;;; +;;; We already know at this point that the first three bytes of the +;;; strings match each other, and they can be safely passed over before +;;; starting the compare loop. So what this code does is skip over 0-3 +;;; bytes, as much as necessary in order to dword-align the edi +;;; pointer. (esi will still be misaligned three times out of four.) +;;; +;;; It should be confessed that this loop usually does not represent +;;; much of the total running time. Replacing it with a more +;;; straightforward "rep cmpsb" would not drastically degrade +;;; performance. + +LoopCmps: + mov eax, [esi + edx] + xor eax, [edi + edx] + jnz LeaveLoopCmps + mov eax, [esi + edx + 4] + xor eax, [edi + edx + 4] + jnz LeaveLoopCmps4 + add edx, 8 + jnz LoopCmps + jmp short LenMaximum +LeaveLoopCmps4: add edx, 4 +LeaveLoopCmps: test eax, 0000FFFFh + jnz LenLower + add edx, 2 + shr eax, 16 +LenLower: sub al, 1 + adc edx, 0 + +;;; Calculate the length of the match. If it is longer than MAX_MATCH, +;;; then automatically accept it as the best possible match and leave. + + lea eax, [edi + edx] + mov edi, [scan] + sub eax, edi + cmp eax, MAX_MATCH + jge LenMaximum + +;;; If the length of the match is not longer than the best match we +;;; have so far, then forget it and return to the lookup loop. + + mov edx, [deflatestate] + mov ebx, [bestlen] + cmp eax, ebx + jg LongerMatch + mov esi, [windowbestlen] + mov edi, [edx + dsPrev] + mov ebx, [scanend] + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; s->match_start = cur_match; +;;; best_len = len; +;;; if (len >= nice_match) break; +;;; scan_end = *(ushf*)(scan+best_len-1); + +LongerMatch: mov ebx, [nicematch] + mov [bestlen], eax + mov [edx + dsMatchStart], ecx + cmp eax, ebx + jge LeaveNow + mov esi, [window] + add esi, eax + mov [windowbestlen], esi + movzx ebx, word ptr [edi + eax - 1] + mov edi, [edx + dsPrev] + mov [scanend], ebx + mov edx, [chainlenwmask] + jmp LookupLoop + +;;; Accept the current string, with the maximum possible length. + +LenMaximum: mov edx, [deflatestate] + mov dword ptr [bestlen], MAX_MATCH + mov [edx + dsMatchStart], ecx + +;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len; +;;; return s->lookahead; + +LeaveNow: + mov edx, [deflatestate] + mov ebx, [bestlen] + mov eax, [edx + dsLookahead] + cmp ebx, eax + jg LookaheadRet + mov eax, ebx +LookaheadRet: + +;;; Restore the stack and return from whence we came. + + add esp, LocalVarsSize + pop ebx + pop esi + pop edi + pop ebp + + ret +; please don't remove this string ! +; Your can freely use match686 in any free or commercial app if you don't remove the string in the binary! + db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998",0dh,0ah + + + IFDEF NOUNDERLINE + longest_match endp + ELSE + _longest_match endp + ENDIF + + IFDEF NOUNDERLINE + match_init proc near + ret + match_init endp + ELSE + _match_init proc near + ret + _match_init endp + ENDIF + + +_TEXT ends +end diff --git a/zlib-1.2.11/contrib/masmx86/readme.txt b/zlib-1.2.11/contrib/masmx86/readme.txt new file mode 100644 index 00000000..3271f720 --- /dev/null +++ b/zlib-1.2.11/contrib/masmx86/readme.txt @@ -0,0 +1,27 @@ + +Summary +------- +This directory contains ASM implementations of the functions +longest_match() and inflate_fast(). + + +Use instructions +---------------- +Assemble using MASM, and copy the object files into the zlib source +directory, then run the appropriate makefile, as suggested below. You can +donwload MASM from here: + + http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=7a1c9da0-0510-44a2-b042-7ef370530c64 + +You can also get objects files here: + + http://www.winimage.com/zLibDll/zlib124_masm_obj.zip + +Build instructions +------------------ +* With Microsoft C and MASM: +nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj" + +* With Borland C and TASM: +make -f win32/Makefile.bor LOCAL_ZLIB="-DASMV -DASMINF" OBJA="match686.obj inffas32.obj" OBJPA="+match686c.obj+match686.obj+inffas32.obj" + diff --git a/zlib-1.2.11/contrib/minizip/Makefile b/zlib-1.2.11/contrib/minizip/Makefile new file mode 100644 index 00000000..84eaad20 --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/Makefile @@ -0,0 +1,25 @@ +CC=cc +CFLAGS=-O -I../.. + +UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a +ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a + +.c.o: + $(CC) -c $(CFLAGS) $*.c + +all: miniunz minizip + +miniunz: $(UNZ_OBJS) + $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS) + +minizip: $(ZIP_OBJS) + $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS) + +test: miniunz minizip + ./minizip test readme.txt + ./miniunz -l test.zip + mv readme.txt readme.old + ./miniunz test.zip + +clean: + /bin/rm -f *.o *~ minizip miniunz diff --git a/zlib-1.2.11/contrib/minizip/Makefile.am b/zlib-1.2.11/contrib/minizip/Makefile.am new file mode 100644 index 00000000..d343011e --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/Makefile.am @@ -0,0 +1,45 @@ +lib_LTLIBRARIES = libminizip.la + +if COND_DEMOS +bin_PROGRAMS = miniunzip minizip +endif + +zlib_top_srcdir = $(top_srcdir)/../.. +zlib_top_builddir = $(top_builddir)/../.. + +AM_CPPFLAGS = -I$(zlib_top_srcdir) +AM_LDFLAGS = -L$(zlib_top_builddir) + +if WIN32 +iowin32_src = iowin32.c +iowin32_h = iowin32.h +endif + +libminizip_la_SOURCES = \ + ioapi.c \ + mztools.c \ + unzip.c \ + zip.c \ + ${iowin32_src} + +libminizip_la_LDFLAGS = $(AM_LDFLAGS) -version-info 1:0:0 -lz + +minizip_includedir = $(includedir)/minizip +minizip_include_HEADERS = \ + crypt.h \ + ioapi.h \ + mztools.h \ + unzip.h \ + zip.h \ + ${iowin32_h} + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = minizip.pc + +EXTRA_PROGRAMS = miniunzip minizip + +miniunzip_SOURCES = miniunz.c +miniunzip_LDADD = libminizip.la + +minizip_SOURCES = minizip.c +minizip_LDADD = libminizip.la -lz diff --git a/zlib-1.2.11/contrib/minizip/MiniZip64_Changes.txt b/zlib-1.2.11/contrib/minizip/MiniZip64_Changes.txt new file mode 100644 index 00000000..13a1bd91 --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/MiniZip64_Changes.txt @@ -0,0 +1,6 @@ + +MiniZip 1.1 was derrived from MiniZip at version 1.01f + +Change in 1.0 (Okt 2009) + - **TODO - Add history** + diff --git a/zlib-1.2.11/contrib/minizip/MiniZip64_info.txt b/zlib-1.2.11/contrib/minizip/MiniZip64_info.txt new file mode 100644 index 00000000..57d71524 --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/MiniZip64_info.txt @@ -0,0 +1,74 @@ +MiniZip - Copyright (c) 1998-2010 - by Gilles Vollant - version 1.1 64 bits from Mathias Svensson + +Introduction +--------------------- +MiniZip 1.1 is built from MiniZip 1.0 by Gilles Vollant ( http://www.winimage.com/zLibDll/minizip.html ) + +When adding ZIP64 support into minizip it would result into risk of breaking compatibility with minizip 1.0. +All possible work was done for compatibility. + + +Background +--------------------- +When adding ZIP64 support Mathias Svensson found that Even Rouault have added ZIP64 +support for unzip.c into minizip for a open source project called gdal ( http://www.gdal.org/ ) + +That was used as a starting point. And after that ZIP64 support was added to zip.c +some refactoring and code cleanup was also done. + + +Changed from MiniZip 1.0 to MiniZip 1.1 +--------------------------------------- +* Added ZIP64 support for unzip ( by Even Rouault ) +* Added ZIP64 support for zip ( by Mathias Svensson ) +* Reverted some changed that Even Rouault did. +* Bunch of patches received from Gulles Vollant that he received for MiniZip from various users. +* Added unzip patch for BZIP Compression method (patch create by Daniel Borca) +* Added BZIP Compress method for zip +* Did some refactoring and code cleanup + + +Credits + + Gilles Vollant - Original MiniZip author + Even Rouault - ZIP64 unzip Support + Daniel Borca - BZip Compression method support in unzip + Mathias Svensson - ZIP64 zip support + Mathias Svensson - BZip Compression method support in zip + + Resources + + ZipLayout http://result42.com/projects/ZipFileLayout + Command line tool for Windows that shows the layout and information of the headers in a zip archive. + Used when debugging and validating the creation of zip files using MiniZip64 + + + ZIP App Note http://www.pkware.com/documents/casestudies/APPNOTE.TXT + Zip File specification + + +Notes. + * To be able to use BZip compression method in zip64.c or unzip64.c the BZIP2 lib is needed and HAVE_BZIP2 need to be defined. + +License +---------------------------------------------------------- + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +---------------------------------------------------------- + diff --git a/zlib-1.2.11/contrib/minizip/configure.ac b/zlib-1.2.11/contrib/minizip/configure.ac new file mode 100644 index 00000000..5b119709 --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/configure.ac @@ -0,0 +1,32 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_INIT([minizip], [1.2.11], [bugzilla.redhat.com]) +AC_CONFIG_SRCDIR([minizip.c]) +AM_INIT_AUTOMAKE([foreign]) +LT_INIT + +AC_MSG_CHECKING([whether to build example programs]) +AC_ARG_ENABLE([demos], AC_HELP_STRING([--enable-demos], [build example programs])) +AM_CONDITIONAL([COND_DEMOS], [test "$enable_demos" = yes]) +if test "$enable_demos" = yes +then + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +case "${host}" in + *-mingw* | mingw*) + WIN32="yes" + ;; + *) + ;; +esac +AM_CONDITIONAL([WIN32], [test "${WIN32}" = "yes"]) + + +AC_SUBST([HAVE_UNISTD_H], [0]) +AC_CHECK_HEADER([unistd.h], [HAVE_UNISTD_H=1], []) +AC_CONFIG_FILES([Makefile minizip.pc]) +AC_OUTPUT diff --git a/zlib-1.2.11/contrib/minizip/crypt.h b/zlib-1.2.11/contrib/minizip/crypt.h new file mode 100644 index 00000000..1e9e8200 --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/crypt.h @@ -0,0 +1,131 @@ +/* crypt.h -- base code for crypt/uncrypt ZIPfile + + + Version 1.01e, February 12th, 2005 + + Copyright (C) 1998-2005 Gilles Vollant + + This code is a modified version of crypting code in Infozip distribution + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + If you don't need crypting in your application, just define symbols + NOCRYPT and NOUNCRYPT. + + This code support the "Traditional PKWARE Encryption". + + The new AES encryption added on Zip format by Winzip (see the page + http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong + Encryption is not supported. +*/ + +#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) + +/*********************************************************************** + * Return the next byte in the pseudo-random sequence + */ +static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) +{ + unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an + * unpredictable manner on 16-bit systems; not a problem + * with any known compiler so far, though */ + + temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; + return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); +} + +/*********************************************************************** + * Update the encryption keys with the next byte of plain text + */ +static int update_keys(unsigned long* pkeys,const z_crc_t* pcrc_32_tab,int c) +{ + (*(pkeys+0)) = CRC32((*(pkeys+0)), c); + (*(pkeys+1)) += (*(pkeys+0)) & 0xff; + (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; + { + register int keyshift = (int)((*(pkeys+1)) >> 24); + (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); + } + return c; +} + + +/*********************************************************************** + * Initialize the encryption keys and the random header according to + * the given password. + */ +static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcrc_32_tab) +{ + *(pkeys+0) = 305419896L; + *(pkeys+1) = 591751049L; + *(pkeys+2) = 878082192L; + while (*passwd != '\0') { + update_keys(pkeys,pcrc_32_tab,(int)*passwd); + passwd++; + } +} + +#define zdecode(pkeys,pcrc_32_tab,c) \ + (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) + +#define zencode(pkeys,pcrc_32_tab,c,t) \ + (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) + +#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED + +#define RAND_HEAD_LEN 12 + /* "last resort" source for second part of crypt seed pattern */ +# ifndef ZCR_SEED2 +# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ +# endif + +static int crypthead(const char* passwd, /* password string */ + unsigned char* buf, /* where to write header */ + int bufSize, + unsigned long* pkeys, + const z_crc_t* pcrc_32_tab, + unsigned long crcForCrypting) +{ + int n; /* index in random header */ + int t; /* temporary */ + int c; /* random byte */ + unsigned char header[RAND_HEAD_LEN-2]; /* random header */ + static unsigned calls = 0; /* ensure different random header each time */ + + if (bufSize> 7) & 0xff; + header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); + } + /* Encrypt random header (last two bytes is high word of crc) */ + init_keys(passwd, pkeys, pcrc_32_tab); + for (n = 0; n < RAND_HEAD_LEN-2; n++) + { + buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); + } + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); + buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); + return n; +} + +#endif diff --git a/zlib-1.2.11/contrib/minizip/ioapi.c b/zlib-1.2.11/contrib/minizip/ioapi.c new file mode 100644 index 00000000..7f5c191b --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/ioapi.c @@ -0,0 +1,247 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + +*/ + +#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS))) + #define _CRT_SECURE_NO_WARNINGS +#endif + +#if defined(__APPLE__) || defined(IOAPI_NO_64) +// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions +#define FOPEN_FUNC(filename, mode) fopen(filename, mode) +#define FTELLO_FUNC(stream) ftello(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) +#else +#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) +#define FTELLO_FUNC(stream) ftello64(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) +#endif + + +#include "ioapi.h" + +voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode) +{ + if (pfilefunc->zfile_func64.zopen64_file != NULL) + return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode); + else + { + return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode); + } +} + +long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin); + else + { + uLong offsetTruncated = (uLong)offset; + if (offsetTruncated != offset) + return -1; + else + return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin); + } +} + +ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream) +{ + if (pfilefunc->zfile_func64.zseek64_file != NULL) + return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream); + else + { + uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream); + if ((tell_uLong) == MAXU32) + return (ZPOS64_T)-1; + else + return tell_uLong; + } +} + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32) +{ + p_filefunc64_32->zfile_func64.zopen64_file = NULL; + p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file; + p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file; + p_filefunc64_32->zfile_func64.ztell64_file = NULL; + p_filefunc64_32->zfile_func64.zseek64_file = NULL; + p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file; + p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file; + p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque; + p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file; + p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file; +} + + + +static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode)); +static uLong ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +static uLong ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size)); +static ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream)); +static long ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +static int ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream)); +static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream)); + +static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = fopen(filename, mode_fopen); + return file; +} + +static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode) +{ + FILE* file = NULL; + const char* mode_fopen = NULL; + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + mode_fopen = "rb"; + else + if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + mode_fopen = "r+b"; + else + if (mode & ZLIB_FILEFUNC_MODE_CREATE) + mode_fopen = "wb"; + + if ((filename!=NULL) && (mode_fopen != NULL)) + file = FOPEN_FUNC((const char*)filename, mode_fopen); + return file; +} + + +static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size) +{ + uLong ret; + ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size) +{ + uLong ret; + ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); + return ret; +} + +static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream) +{ + long ret; + ret = ftell((FILE *)stream); + return ret; +} + + +static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream) +{ + ZPOS64_T ret; + ret = FTELLO_FUNC((FILE *)stream); + return ret; +} + +static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin) +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + if (fseek((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; + return ret; +} + +static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) +{ + int fseek_origin=0; + long ret; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + fseek_origin = SEEK_CUR; + break; + case ZLIB_FILEFUNC_SEEK_END : + fseek_origin = SEEK_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + fseek_origin = SEEK_SET; + break; + default: return -1; + } + ret = 0; + + if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0) + ret = -1; + + return ret; +} + + +static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream) +{ + int ret; + ret = fclose((FILE *)stream); + return ret; +} + +static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream) +{ + int ret; + ret = ferror((FILE *)stream); + return ret; +} + +void fill_fopen_filefunc (pzlib_filefunc_def) + zlib_filefunc_def* pzlib_filefunc_def; +{ + pzlib_filefunc_def->zopen_file = fopen_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell_file = ftell_file_func; + pzlib_filefunc_def->zseek_file = fseek_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = fopen64_file_func; + pzlib_filefunc_def->zread_file = fread_file_func; + pzlib_filefunc_def->zwrite_file = fwrite_file_func; + pzlib_filefunc_def->ztell64_file = ftell64_file_func; + pzlib_filefunc_def->zseek64_file = fseek64_file_func; + pzlib_filefunc_def->zclose_file = fclose_file_func; + pzlib_filefunc_def->zerror_file = ferror_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/zlib-1.2.11/contrib/minizip/ioapi.h b/zlib-1.2.11/contrib/minizip/ioapi.h new file mode 100644 index 00000000..8dcbdb06 --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/ioapi.h @@ -0,0 +1,208 @@ +/* ioapi.h -- IO base function header for compress/uncompress .zip + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + Changes + + Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this) + Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux. + More if/def section may be needed to support other platforms + Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows. + (but you should use iowin32.c for windows instead) + +*/ + +#ifndef _ZLIBIOAPI64_H +#define _ZLIBIOAPI64_H + +#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) + + // Linux needs this to support file operation on files larger then 4+GB + // But might need better if/def to select just the platforms that needs them. + + #ifndef __USE_FILE_OFFSET64 + #define __USE_FILE_OFFSET64 + #endif + #ifndef __USE_LARGEFILE64 + #define __USE_LARGEFILE64 + #endif + #ifndef _LARGEFILE64_SOURCE + #define _LARGEFILE64_SOURCE + #endif + #ifndef _FILE_OFFSET_BIT + #define _FILE_OFFSET_BIT 64 + #endif + +#endif + +#include +#include +#include "zlib.h" + +#if defined(USE_FILE32API) +#define fopen64 fopen +#define ftello64 ftell +#define fseeko64 fseek +#else +#ifdef __FreeBSD__ +#define fopen64 fopen +#define ftello64 ftello +#define fseeko64 fseeko +#endif +#ifdef _MSC_VER + #define fopen64 fopen + #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC))) + #define ftello64 _ftelli64 + #define fseeko64 _fseeki64 + #else // old MSC + #define ftello64 ftell + #define fseeko64 fseek + #endif +#endif +#endif + +/* +#ifndef ZPOS64_T + #ifdef _WIN32 + #define ZPOS64_T fpos_t + #else + #include + #define ZPOS64_T uint64_t + #endif +#endif +*/ + +#ifdef HAVE_MINIZIP64_CONF_H +#include "mz64conf.h" +#endif + +/* a type choosen by DEFINE */ +#ifdef HAVE_64BIT_INT_CUSTOM +typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T; +#else +#ifdef HAS_STDINT_H +#include "stdint.h" +typedef uint64_t ZPOS64_T; +#else + +/* Maximum unsigned 32-bit value used as placeholder for zip64 */ +#define MAXU32 0xffffffff + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef unsigned __int64 ZPOS64_T; +#else +typedef unsigned long long int ZPOS64_T; +#endif +#endif +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define ZLIB_FILEFUNC_SEEK_CUR (1) +#define ZLIB_FILEFUNC_SEEK_END (2) +#define ZLIB_FILEFUNC_SEEK_SET (0) + +#define ZLIB_FILEFUNC_MODE_READ (1) +#define ZLIB_FILEFUNC_MODE_WRITE (2) +#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) + +#define ZLIB_FILEFUNC_MODE_EXISTING (4) +#define ZLIB_FILEFUNC_MODE_CREATE (8) + + +#ifndef ZCALLBACK + #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) + #define ZCALLBACK CALLBACK + #else + #define ZCALLBACK + #endif +#endif + + + + +typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); +typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); +typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); + +typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); + + +/* here is the "old" 32 bits structure structure */ +typedef struct zlib_filefunc_def_s +{ + open_file_func zopen_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell_file_func ztell_file; + seek_file_func zseek_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc_def; + +typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream)); +typedef long (ZCALLBACK *seek64_file_func) OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +typedef voidpf (ZCALLBACK *open64_file_func) OF((voidpf opaque, const void* filename, int mode)); + +typedef struct zlib_filefunc64_def_s +{ + open64_file_func zopen64_file; + read_file_func zread_file; + write_file_func zwrite_file; + tell64_file_func ztell64_file; + seek64_file_func zseek64_file; + close_file_func zclose_file; + testerror_file_func zerror_file; + voidpf opaque; +} zlib_filefunc64_def; + +void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); + +/* now internal definition, only for zip.c and unzip.h */ +typedef struct zlib_filefunc64_32_def_s +{ + zlib_filefunc64_def zfile_func64; + open_file_func zopen32_file; + tell_file_func ztell32_file; + seek_file_func zseek32_file; +} zlib_filefunc64_32_def; + + +#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size)) +//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) +//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) +#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream)) +#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream)) + +voidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)); +long call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)); +ZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)); + +void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32); + +#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode))) +#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream))) +#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode))) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/zlib-1.2.11/contrib/minizip/iowin32.c b/zlib-1.2.11/contrib/minizip/iowin32.c new file mode 100644 index 00000000..274f39eb --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/iowin32.c @@ -0,0 +1,462 @@ +/* iowin32.c -- IO base function header for compress/uncompress .zip + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + +*/ + +#include + +#include "zlib.h" +#include "ioapi.h" +#include "iowin32.h" + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE (0xFFFFFFFF) +#endif + +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + + +// see Include/shared/winapifamily.h in the Windows Kit +#if defined(WINAPI_FAMILY_PARTITION) && (!(defined(IOWIN32_USING_WINRT_API))) +#if WINAPI_FAMILY_ONE_PARTITION(WINAPI_FAMILY, WINAPI_PARTITION_APP) +#define IOWIN32_USING_WINRT_API 1 +#endif +#endif + +voidpf ZCALLBACK win32_open_file_func OF((voidpf opaque, const char* filename, int mode)); +uLong ZCALLBACK win32_read_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size)); +uLong ZCALLBACK win32_write_file_func OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); +ZPOS64_T ZCALLBACK win32_tell64_file_func OF((voidpf opaque, voidpf stream)); +long ZCALLBACK win32_seek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)); +int ZCALLBACK win32_close_file_func OF((voidpf opaque, voidpf stream)); +int ZCALLBACK win32_error_file_func OF((voidpf opaque, voidpf stream)); + +typedef struct +{ + HANDLE hf; + int error; +} WIN32FILE_IOWIN; + + +static void win32_translate_open_mode(int mode, + DWORD* lpdwDesiredAccess, + DWORD* lpdwCreationDisposition, + DWORD* lpdwShareMode, + DWORD* lpdwFlagsAndAttributes) +{ + *lpdwDesiredAccess = *lpdwShareMode = *lpdwFlagsAndAttributes = *lpdwCreationDisposition = 0; + + if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) + { + *lpdwDesiredAccess = GENERIC_READ; + *lpdwCreationDisposition = OPEN_EXISTING; + *lpdwShareMode = FILE_SHARE_READ; + } + else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) + { + *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + *lpdwCreationDisposition = OPEN_EXISTING; + } + else if (mode & ZLIB_FILEFUNC_MODE_CREATE) + { + *lpdwDesiredAccess = GENERIC_WRITE | GENERIC_READ; + *lpdwCreationDisposition = CREATE_ALWAYS; + } +} + +static voidpf win32_build_iowin(HANDLE hFile) +{ + voidpf ret=NULL; + + if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE)) + { + WIN32FILE_IOWIN w32fiow; + w32fiow.hf = hFile; + w32fiow.error = 0; + ret = malloc(sizeof(WIN32FILE_IOWIN)); + + if (ret==NULL) + CloseHandle(hFile); + else + *((WIN32FILE_IOWIN*)ret) = w32fiow; + } + return ret; +} + +voidpf ZCALLBACK win32_open64_file_func (voidpf opaque,const void* filename,int mode) +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API +#ifdef UNICODE + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + { + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); + } +#endif +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +voidpf ZCALLBACK win32_open64_file_funcA (voidpf opaque,const void* filename,int mode) +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API + if ((filename!=NULL) && (dwDesiredAccess != 0)) + { + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); + } +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFileA((LPCSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +voidpf ZCALLBACK win32_open64_file_funcW (voidpf opaque,const void* filename,int mode) +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile2((LPCWSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition,NULL); +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFileW((LPCWSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +voidpf ZCALLBACK win32_open_file_func (voidpf opaque,const char* filename,int mode) +{ + const char* mode_fopen = NULL; + DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; + HANDLE hFile = NULL; + + win32_translate_open_mode(mode,&dwDesiredAccess,&dwCreationDisposition,&dwShareMode,&dwFlagsAndAttributes); + +#ifdef IOWIN32_USING_WINRT_API +#ifdef UNICODE + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile2((LPCTSTR)filename, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + { + WCHAR filenameW[FILENAME_MAX + 0x200 + 1]; + MultiByteToWideChar(CP_ACP,0,(const char*)filename,-1,filenameW,FILENAME_MAX + 0x200); + hFile = CreateFile2(filenameW, dwDesiredAccess, dwShareMode, dwCreationDisposition, NULL); + } +#endif +#else + if ((filename!=NULL) && (dwDesiredAccess != 0)) + hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); +#endif + + return win32_build_iowin(hFile); +} + + +uLong ZCALLBACK win32_read_file_func (voidpf opaque, voidpf stream, void* buf,uLong size) +{ + uLong ret=0; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + + if (hFile != NULL) + { + if (!ReadFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + } + } + + return ret; +} + + +uLong ZCALLBACK win32_write_file_func (voidpf opaque,voidpf stream,const void* buf,uLong size) +{ + uLong ret=0; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + + if (hFile != NULL) + { + if (!WriteFile(hFile, buf, size, &ret, NULL)) + { + DWORD dwErr = GetLastError(); + if (dwErr == ERROR_HANDLE_EOF) + dwErr = 0; + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + } + } + + return ret; +} + +static BOOL MySetFilePointerEx(HANDLE hFile, LARGE_INTEGER pos, LARGE_INTEGER *newPos, DWORD dwMoveMethod) +{ +#ifdef IOWIN32_USING_WINRT_API + return SetFilePointerEx(hFile, pos, newPos, dwMoveMethod); +#else + LONG lHigh = pos.HighPart; + DWORD dwNewPos = SetFilePointer(hFile, pos.LowPart, &lHigh, dwMoveMethod); + BOOL fOk = TRUE; + if (dwNewPos == 0xFFFFFFFF) + if (GetLastError() != NO_ERROR) + fOk = FALSE; + if ((newPos != NULL) && (fOk)) + { + newPos->LowPart = dwNewPos; + newPos->HighPart = lHigh; + } + return fOk; +#endif +} + +long ZCALLBACK win32_tell_file_func (voidpf opaque,voidpf stream) +{ + long ret=-1; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + { + LARGE_INTEGER pos; + pos.QuadPart = 0; + + if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=(long)pos.LowPart; + } + return ret; +} + +ZPOS64_T ZCALLBACK win32_tell64_file_func (voidpf opaque, voidpf stream) +{ + ZPOS64_T ret= (ZPOS64_T)-1; + HANDLE hFile = NULL; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + + if (hFile) + { + LARGE_INTEGER pos; + pos.QuadPart = 0; + + if (!MySetFilePointerEx(hFile, pos, &pos, FILE_CURRENT)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = (ZPOS64_T)-1; + } + else + ret=pos.QuadPart; + } + return ret; +} + + +long ZCALLBACK win32_seek_file_func (voidpf opaque,voidpf stream,uLong offset,int origin) +{ + DWORD dwMoveMethod=0xFFFFFFFF; + HANDLE hFile = NULL; + + long ret=-1; + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + dwMoveMethod = FILE_CURRENT; + break; + case ZLIB_FILEFUNC_SEEK_END : + dwMoveMethod = FILE_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + dwMoveMethod = FILE_BEGIN; + break; + default: return -1; + } + + if (hFile != NULL) + { + LARGE_INTEGER pos; + pos.QuadPart = offset; + if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=0; + } + return ret; +} + +long ZCALLBACK win32_seek64_file_func (voidpf opaque, voidpf stream,ZPOS64_T offset,int origin) +{ + DWORD dwMoveMethod=0xFFFFFFFF; + HANDLE hFile = NULL; + long ret=-1; + + if (stream!=NULL) + hFile = ((WIN32FILE_IOWIN*)stream)->hf; + + switch (origin) + { + case ZLIB_FILEFUNC_SEEK_CUR : + dwMoveMethod = FILE_CURRENT; + break; + case ZLIB_FILEFUNC_SEEK_END : + dwMoveMethod = FILE_END; + break; + case ZLIB_FILEFUNC_SEEK_SET : + dwMoveMethod = FILE_BEGIN; + break; + default: return -1; + } + + if (hFile) + { + LARGE_INTEGER pos; + pos.QuadPart = offset; + if (!MySetFilePointerEx(hFile, pos, NULL, dwMoveMethod)) + { + DWORD dwErr = GetLastError(); + ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; + ret = -1; + } + else + ret=0; + } + return ret; +} + +int ZCALLBACK win32_close_file_func (voidpf opaque, voidpf stream) +{ + int ret=-1; + + if (stream!=NULL) + { + HANDLE hFile; + hFile = ((WIN32FILE_IOWIN*)stream) -> hf; + if (hFile != NULL) + { + CloseHandle(hFile); + ret=0; + } + free(stream); + } + return ret; +} + +int ZCALLBACK win32_error_file_func (voidpf opaque,voidpf stream) +{ + int ret=-1; + if (stream!=NULL) + { + ret = ((WIN32FILE_IOWIN*)stream) -> error; + } + return ret; +} + +void fill_win32_filefunc (zlib_filefunc_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen_file = win32_open_file_func; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell_file = win32_tell_file_func; + pzlib_filefunc_def->zseek_file = win32_seek_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + +void fill_win32_filefunc64(zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_func; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + + +void fill_win32_filefunc64A(zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_funcA; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} + + +void fill_win32_filefunc64W(zlib_filefunc64_def* pzlib_filefunc_def) +{ + pzlib_filefunc_def->zopen64_file = win32_open64_file_funcW; + pzlib_filefunc_def->zread_file = win32_read_file_func; + pzlib_filefunc_def->zwrite_file = win32_write_file_func; + pzlib_filefunc_def->ztell64_file = win32_tell64_file_func; + pzlib_filefunc_def->zseek64_file = win32_seek64_file_func; + pzlib_filefunc_def->zclose_file = win32_close_file_func; + pzlib_filefunc_def->zerror_file = win32_error_file_func; + pzlib_filefunc_def->opaque = NULL; +} diff --git a/zlib-1.2.11/contrib/minizip/iowin32.h b/zlib-1.2.11/contrib/minizip/iowin32.h new file mode 100644 index 00000000..0ca0969a --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/iowin32.h @@ -0,0 +1,28 @@ +/* iowin32.h -- IO base function header for compress/uncompress .zip + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + +*/ + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); +void fill_win32_filefunc64 OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_win32_filefunc64A OF((zlib_filefunc64_def* pzlib_filefunc_def)); +void fill_win32_filefunc64W OF((zlib_filefunc64_def* pzlib_filefunc_def)); + +#ifdef __cplusplus +} +#endif diff --git a/zlib-1.2.11/contrib/minizip/make_vms.com b/zlib-1.2.11/contrib/minizip/make_vms.com new file mode 100644 index 00000000..9ac13a98 --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/make_vms.com @@ -0,0 +1,25 @@ +$ if f$search("ioapi.h_orig") .eqs. "" then copy ioapi.h ioapi.h_orig +$ open/write zdef vmsdefs.h +$ copy sys$input: zdef +$ deck +#define unix +#define fill_zlib_filefunc64_32_def_from_filefunc32 fillzffunc64from +#define Write_Zip64EndOfCentralDirectoryLocator Write_Zip64EoDLocator +#define Write_Zip64EndOfCentralDirectoryRecord Write_Zip64EoDRecord +#define Write_EndOfCentralDirectoryRecord Write_EoDRecord +$ eod +$ close zdef +$ copy vmsdefs.h,ioapi.h_orig ioapi.h +$ cc/include=[--]/prefix=all ioapi.c +$ cc/include=[--]/prefix=all miniunz.c +$ cc/include=[--]/prefix=all unzip.c +$ cc/include=[--]/prefix=all minizip.c +$ cc/include=[--]/prefix=all zip.c +$ link miniunz,unzip,ioapi,[--]libz.olb/lib +$ link minizip,zip,ioapi,[--]libz.olb/lib +$ mcr []minizip test minizip_info.txt +$ mcr []miniunz -l test.zip +$ rename minizip_info.txt; minizip_info.txt_old +$ mcr []miniunz test.zip +$ delete test.zip;* +$exit diff --git a/zlib-1.2.11/contrib/minizip/miniunz.c b/zlib-1.2.11/contrib/minizip/miniunz.c new file mode 100644 index 00000000..3d65401b --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/miniunz.c @@ -0,0 +1,660 @@ +/* + miniunz.c + Version 1.1, February 14h, 2010 + sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) +*/ + +#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) + #ifndef __USE_FILE_OFFSET64 + #define __USE_FILE_OFFSET64 + #endif + #ifndef __USE_LARGEFILE64 + #define __USE_LARGEFILE64 + #endif + #ifndef _LARGEFILE64_SOURCE + #define _LARGEFILE64_SOURCE + #endif + #ifndef _FILE_OFFSET_BIT + #define _FILE_OFFSET_BIT 64 + #endif +#endif + +#ifdef __APPLE__ +// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions +#define FOPEN_FUNC(filename, mode) fopen(filename, mode) +#define FTELLO_FUNC(stream) ftello(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) +#else +#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) +#define FTELLO_FUNC(stream) ftello64(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) +#endif + + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +# include +# include +#else +# include +# include +#endif + + +#include "unzip.h" + +#define CASESENSITIVITY (0) +#define WRITEBUFFERSIZE (8192) +#define MAXFILENAME (256) + +#ifdef _WIN32 +#define USEWIN32IOAPI +#include "iowin32.h" +#endif +/* + mini unzip, demo of unzip package + + usage : + Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir] + + list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT + if it exists +*/ + + +/* change_file_date : change the date/time of a file + filename : the filename of the file where date/time must be modified + dosdate : the new date at the MSDos format (4 bytes) + tmu_date : the SAME new date at the tm_unz format */ +void change_file_date(filename,dosdate,tmu_date) + const char *filename; + uLong dosdate; + tm_unz tmu_date; +{ +#ifdef _WIN32 + HANDLE hFile; + FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; + + hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE, + 0,NULL,OPEN_EXISTING,0,NULL); + GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite); + DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal); + LocalFileTimeToFileTime(&ftLocal,&ftm); + SetFileTime(hFile,&ftm,&ftLastAcc,&ftm); + CloseHandle(hFile); +#else +#ifdef unix || __APPLE__ + struct utimbuf ut; + struct tm newdate; + newdate.tm_sec = tmu_date.tm_sec; + newdate.tm_min=tmu_date.tm_min; + newdate.tm_hour=tmu_date.tm_hour; + newdate.tm_mday=tmu_date.tm_mday; + newdate.tm_mon=tmu_date.tm_mon; + if (tmu_date.tm_year > 1900) + newdate.tm_year=tmu_date.tm_year - 1900; + else + newdate.tm_year=tmu_date.tm_year ; + newdate.tm_isdst=-1; + + ut.actime=ut.modtime=mktime(&newdate); + utime(filename,&ut); +#endif +#endif +} + + +/* mymkdir and change_file_date are not 100 % portable + As I don't know well Unix, I wait feedback for the unix portion */ + +int mymkdir(dirname) + const char* dirname; +{ + int ret=0; +#ifdef _WIN32 + ret = _mkdir(dirname); +#elif unix + ret = mkdir (dirname,0775); +#elif __APPLE__ + ret = mkdir (dirname,0775); +#endif + return ret; +} + +int makedir (newdir) + char *newdir; +{ + char *buffer ; + char *p; + int len = (int)strlen(newdir); + + if (len <= 0) + return 0; + + buffer = (char*)malloc(len+1); + if (buffer==NULL) + { + printf("Error allocating memory\n"); + return UNZ_INTERNALERROR; + } + strcpy(buffer,newdir); + + if (buffer[len-1] == '/') { + buffer[len-1] = '\0'; + } + if (mymkdir(buffer) == 0) + { + free(buffer); + return 1; + } + + p = buffer+1; + while (1) + { + char hold; + + while(*p && *p != '\\' && *p != '/') + p++; + hold = *p; + *p = 0; + if ((mymkdir(buffer) == -1) && (errno == ENOENT)) + { + printf("couldn't create directory %s\n",buffer); + free(buffer); + return 0; + } + if (hold == 0) + break; + *p++ = hold; + } + free(buffer); + return 1; +} + +void do_banner() +{ + printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n"); + printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); +} + +void do_help() +{ + printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \ + " -e Extract without pathname (junk paths)\n" \ + " -x Extract with pathname\n" \ + " -v list files\n" \ + " -l list files\n" \ + " -d directory to extract into\n" \ + " -o overwrite files without prompting\n" \ + " -p extract crypted file using password\n\n"); +} + +void Display64BitsSize(ZPOS64_T n, int size_char) +{ + /* to avoid compatibility problem , we do here the conversion */ + char number[21]; + int offset=19; + int pos_string = 19; + number[20]=0; + for (;;) { + number[offset]=(char)((n%10)+'0'); + if (number[offset] != '0') + pos_string=offset; + n/=10; + if (offset==0) + break; + offset--; + } + { + int size_display_string = 19-pos_string; + while (size_char > size_display_string) + { + size_char--; + printf(" "); + } + } + + printf("%s",&number[pos_string]); +} + +int do_list(uf) + unzFile uf; +{ + uLong i; + unz_global_info64 gi; + int err; + + err = unzGetGlobalInfo64(uf,&gi); + if (err!=UNZ_OK) + printf("error %d with zipfile in unzGetGlobalInfo \n",err); + printf(" Length Method Size Ratio Date Time CRC-32 Name\n"); + printf(" ------ ------ ---- ----- ---- ---- ------ ----\n"); + for (i=0;i0) + ratio = (uLong)((file_info.compressed_size*100)/file_info.uncompressed_size); + + /* display a '*' if the file is crypted */ + if ((file_info.flag & 1) != 0) + charCrypt='*'; + + if (file_info.compression_method==0) + string_method="Stored"; + else + if (file_info.compression_method==Z_DEFLATED) + { + uInt iLevel=(uInt)((file_info.flag & 0x6)/2); + if (iLevel==0) + string_method="Defl:N"; + else if (iLevel==1) + string_method="Defl:X"; + else if ((iLevel==2) || (iLevel==3)) + string_method="Defl:F"; /* 2:fast , 3 : extra fast*/ + } + else + if (file_info.compression_method==Z_BZIP2ED) + { + string_method="BZip2 "; + } + else + string_method="Unkn. "; + + Display64BitsSize(file_info.uncompressed_size,7); + printf(" %6s%c",string_method,charCrypt); + Display64BitsSize(file_info.compressed_size,7); + printf(" %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n", + ratio, + (uLong)file_info.tmu_date.tm_mon + 1, + (uLong)file_info.tmu_date.tm_mday, + (uLong)file_info.tmu_date.tm_year % 100, + (uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min, + (uLong)file_info.crc,filename_inzip); + if ((i+1)='a') && (rep<='z')) + rep -= 0x20; + } + while ((rep!='Y') && (rep!='N') && (rep!='A')); + } + + if (rep == 'N') + skip = 1; + + if (rep == 'A') + *popt_overwrite=1; + } + + if ((skip==0) && (err==UNZ_OK)) + { + fout=FOPEN_FUNC(write_filename,"wb"); + /* some zipfile don't contain directory alone before file */ + if ((fout==NULL) && ((*popt_extract_without_path)==0) && + (filename_withoutpath!=(char*)filename_inzip)) + { + char c=*(filename_withoutpath-1); + *(filename_withoutpath-1)='\0'; + makedir(write_filename); + *(filename_withoutpath-1)=c; + fout=FOPEN_FUNC(write_filename,"wb"); + } + + if (fout==NULL) + { + printf("error opening %s\n",write_filename); + } + } + + if (fout!=NULL) + { + printf(" extracting: %s\n",write_filename); + + do + { + err = unzReadCurrentFile(uf,buf,size_buf); + if (err<0) + { + printf("error %d with zipfile in unzReadCurrentFile\n",err); + break; + } + if (err>0) + if (fwrite(buf,err,1,fout)!=1) + { + printf("error in writing extracted file\n"); + err=UNZ_ERRNO; + break; + } + } + while (err>0); + if (fout) + fclose(fout); + + if (err==0) + change_file_date(write_filename,file_info.dosDate, + file_info.tmu_date); + } + + if (err==UNZ_OK) + { + err = unzCloseCurrentFile (uf); + if (err!=UNZ_OK) + { + printf("error %d with zipfile in unzCloseCurrentFile\n",err); + } + } + else + unzCloseCurrentFile(uf); /* don't lose the error */ + } + + free(buf); + return err; +} + + +int do_extract(uf,opt_extract_without_path,opt_overwrite,password) + unzFile uf; + int opt_extract_without_path; + int opt_overwrite; + const char* password; +{ + uLong i; + unz_global_info64 gi; + int err; + FILE* fout=NULL; + + err = unzGetGlobalInfo64(uf,&gi); + if (err!=UNZ_OK) + printf("error %d with zipfile in unzGetGlobalInfo \n",err); + + for (i=0;i insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +miniunzip - uncompress and examine ZIP archives +.SH SYNOPSIS +.B miniunzip +.RI [ -exvlo ] +zipfile [ files_to_extract ] [-d tempdir] +.SH DESCRIPTION +.B minizip +is a simple tool which allows the extraction of compressed file +archives in the ZIP format used by the MS-DOS utility PKZIP. It was +written as a demonstration of the +.IR zlib (3) +library and therefore lack many of the features of the +.IR unzip (1) +program. +.SH OPTIONS +A number of options are supported. With the exception of +.BI \-d\ tempdir +these must be supplied before any +other arguments and are: +.TP +.BI \-l\ ,\ \-\-v +List the files in the archive without extracting them. +.TP +.B \-o +Overwrite files without prompting for confirmation. +.TP +.B \-x +Extract files (default). +.PP +The +.I zipfile +argument is the name of the archive to process. The next argument can be used +to specify a single file to extract from the archive. + +Lastly, the following option can be specified at the end of the command-line: +.TP +.BI \-d\ tempdir +Extract the archive in the directory +.I tempdir +rather than the current directory. +.SH SEE ALSO +.BR minizip (1), +.BR zlib (3), +.BR unzip (1). +.SH AUTHOR +This program was written by Gilles Vollant. This manual page was +written by Mark Brown . The -d tempdir option +was added by Dirk Eddelbuettel . diff --git a/zlib-1.2.11/contrib/minizip/minizip.1 b/zlib-1.2.11/contrib/minizip/minizip.1 new file mode 100644 index 00000000..1154484c --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/minizip.1 @@ -0,0 +1,46 @@ +.\" Hey, EMACS: -*- nroff -*- +.TH minizip 1 "May 2, 2001" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.SH NAME +minizip - create ZIP archives +.SH SYNOPSIS +.B minizip +.RI [ -o ] +zipfile [ " files" ... ] +.SH DESCRIPTION +.B minizip +is a simple tool which allows the creation of compressed file archives +in the ZIP format used by the MS-DOS utility PKZIP. It was written as +a demonstration of the +.IR zlib (3) +library and therefore lack many of the features of the +.IR zip (1) +program. +.SH OPTIONS +The first argument supplied is the name of the ZIP archive to create or +.RI -o +in which case it is ignored and the second argument treated as the +name of the ZIP file. If the ZIP file already exists it will be +overwritten. +.PP +Subsequent arguments specify a list of files to place in the ZIP +archive. If none are specified then an empty archive will be created. +.SH SEE ALSO +.BR miniunzip (1), +.BR zlib (3), +.BR zip (1). +.SH AUTHOR +This program was written by Gilles Vollant. This manual page was +written by Mark Brown . + diff --git a/zlib-1.2.11/contrib/minizip/minizip.c b/zlib-1.2.11/contrib/minizip/minizip.c new file mode 100644 index 00000000..4288962e --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/minizip.c @@ -0,0 +1,520 @@ +/* + minizip.c + Version 1.1, February 14h, 2010 + sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) +*/ + + +#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__)) + #ifndef __USE_FILE_OFFSET64 + #define __USE_FILE_OFFSET64 + #endif + #ifndef __USE_LARGEFILE64 + #define __USE_LARGEFILE64 + #endif + #ifndef _LARGEFILE64_SOURCE + #define _LARGEFILE64_SOURCE + #endif + #ifndef _FILE_OFFSET_BIT + #define _FILE_OFFSET_BIT 64 + #endif +#endif + +#ifdef __APPLE__ +// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions +#define FOPEN_FUNC(filename, mode) fopen(filename, mode) +#define FTELLO_FUNC(stream) ftello(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin) +#else +#define FOPEN_FUNC(filename, mode) fopen64(filename, mode) +#define FTELLO_FUNC(stream) ftello64(stream) +#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin) +#endif + + + +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +# include +# include +#else +# include +# include +# include +# include +#endif + +#include "zip.h" + +#ifdef _WIN32 + #define USEWIN32IOAPI + #include "iowin32.h" +#endif + + + +#define WRITEBUFFERSIZE (16384) +#define MAXFILENAME (256) + +#ifdef _WIN32 +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + int ret = 0; + { + FILETIME ftLocal; + HANDLE hFind; + WIN32_FIND_DATAA ff32; + + hFind = FindFirstFileA(f,&ff32); + if (hFind != INVALID_HANDLE_VALUE) + { + FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); + FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); + FindClose(hFind); + ret = 1; + } + } + return ret; +} +#else +#ifdef unix || __APPLE__ +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + int ret=0; + struct stat s; /* results of stat() */ + struct tm* filedate; + time_t tm_t=0; + + if (strcmp(f,"-")!=0) + { + char name[MAXFILENAME+1]; + int len = strlen(f); + if (len > MAXFILENAME) + len = MAXFILENAME; + + strncpy(name, f,MAXFILENAME-1); + /* strncpy doesnt append the trailing NULL, of the string is too long. */ + name[ MAXFILENAME ] = '\0'; + + if (name[len - 1] == '/') + name[len - 1] = '\0'; + /* not all systems allow stat'ing a file with / appended */ + if (stat(name,&s)==0) + { + tm_t = s.st_mtime; + ret = 1; + } + } + filedate = localtime(&tm_t); + + tmzip->tm_sec = filedate->tm_sec; + tmzip->tm_min = filedate->tm_min; + tmzip->tm_hour = filedate->tm_hour; + tmzip->tm_mday = filedate->tm_mday; + tmzip->tm_mon = filedate->tm_mon ; + tmzip->tm_year = filedate->tm_year; + + return ret; +} +#else +uLong filetime(f, tmzip, dt) + char *f; /* name of file to get info on */ + tm_zip *tmzip; /* return value: access, modific. and creation times */ + uLong *dt; /* dostime */ +{ + return 0; +} +#endif +#endif + + + + +int check_exist_file(filename) + const char* filename; +{ + FILE* ftestexist; + int ret = 1; + ftestexist = FOPEN_FUNC(filename,"rb"); + if (ftestexist==NULL) + ret = 0; + else + fclose(ftestexist); + return ret; +} + +void do_banner() +{ + printf("MiniZip 1.1, demo of zLib + MiniZip64 package, written by Gilles Vollant\n"); + printf("more info on MiniZip at http://www.winimage.com/zLibDll/minizip.html\n\n"); +} + +void do_help() +{ + printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] [-j] file.zip [files_to_add]\n\n" \ + " -o Overwrite existing file.zip\n" \ + " -a Append to existing file.zip\n" \ + " -0 Store only\n" \ + " -1 Compress faster\n" \ + " -9 Compress better\n\n" \ + " -j exclude path. store only the file name.\n\n"); +} + +/* calculate the CRC32 of a file, + because to encrypt a file, we need known the CRC32 of the file before */ +int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc) +{ + unsigned long calculate_crc=0; + int err=ZIP_OK; + FILE * fin = FOPEN_FUNC(filenameinzip,"rb"); + + unsigned long size_read = 0; + unsigned long total_read = 0; + if (fin==NULL) + { + err = ZIP_ERRNO; + } + + if (err == ZIP_OK) + do + { + err = ZIP_OK; + size_read = (int)fread(buf,1,size_buf,fin); + if (size_read < size_buf) + if (feof(fin)==0) + { + printf("error in reading %s\n",filenameinzip); + err = ZIP_ERRNO; + } + + if (size_read>0) + calculate_crc = crc32(calculate_crc,buf,size_read); + total_read += size_read; + + } while ((err == ZIP_OK) && (size_read>0)); + + if (fin) + fclose(fin); + + *result_crc=calculate_crc; + printf("file %s crc %lx\n", filenameinzip, calculate_crc); + return err; +} + +int isLargeFile(const char* filename) +{ + int largeFile = 0; + ZPOS64_T pos = 0; + FILE* pFile = FOPEN_FUNC(filename, "rb"); + + if(pFile != NULL) + { + int n = FSEEKO_FUNC(pFile, 0, SEEK_END); + pos = FTELLO_FUNC(pFile); + + printf("File : %s is %lld bytes\n", filename, pos); + + if(pos >= 0xffffffff) + largeFile = 1; + + fclose(pFile); + } + + return largeFile; +} + +int main(argc,argv) + int argc; + char *argv[]; +{ + int i; + int opt_overwrite=0; + int opt_compress_level=Z_DEFAULT_COMPRESSION; + int opt_exclude_path=0; + int zipfilenamearg = 0; + char filename_try[MAXFILENAME+16]; + int zipok; + int err=0; + int size_buf=0; + void* buf=NULL; + const char* password=NULL; + + + do_banner(); + if (argc==1) + { + do_help(); + return 0; + } + else + { + for (i=1;i='0') && (c<='9')) + opt_compress_level = c-'0'; + if ((c=='j') || (c=='J')) + opt_exclude_path = 1; + + if (((c=='p') || (c=='P')) && (i+1='a') && (rep<='z')) + rep -= 0x20; + } + while ((rep!='Y') && (rep!='N') && (rep!='A')); + if (rep=='N') + zipok = 0; + if (rep=='A') + opt_overwrite = 2; + } + } + + if (zipok==1) + { + zipFile zf; + int errclose; +# ifdef USEWIN32IOAPI + zlib_filefunc64_def ffunc; + fill_win32_filefunc64A(&ffunc); + zf = zipOpen2_64(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc); +# else + zf = zipOpen64(filename_try,(opt_overwrite==2) ? 2 : 0); +# endif + + if (zf == NULL) + { + printf("error opening %s\n",filename_try); + err= ZIP_ERRNO; + } + else + printf("creating %s\n",filename_try); + + for (i=zipfilenamearg+1;(i='0') || (argv[i][1]<='9'))) && + (strlen(argv[i]) == 2))) + { + FILE * fin; + int size_read; + const char* filenameinzip = argv[i]; + const char *savefilenameinzip; + zip_fileinfo zi; + unsigned long crcFile=0; + int zip64 = 0; + + zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = + zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; + zi.dosDate = 0; + zi.internal_fa = 0; + zi.external_fa = 0; + filetime(filenameinzip,&zi.tmz_date,&zi.dosDate); + +/* + err = zipOpenNewFileInZip(zf,filenameinzip,&zi, + NULL,0,NULL,0,NULL / * comment * /, + (opt_compress_level != 0) ? Z_DEFLATED : 0, + opt_compress_level); +*/ + if ((password != NULL) && (err==ZIP_OK)) + err = getFileCrc(filenameinzip,buf,size_buf,&crcFile); + + zip64 = isLargeFile(filenameinzip); + + /* The path name saved, should not include a leading slash. */ + /*if it did, windows/xp and dynazip couldn't read the zip file. */ + savefilenameinzip = filenameinzip; + while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' ) + { + savefilenameinzip++; + } + + /*should the zip file contain any path at all?*/ + if( opt_exclude_path ) + { + const char *tmpptr; + const char *lastslash = 0; + for( tmpptr = savefilenameinzip; *tmpptr; tmpptr++) + { + if( *tmpptr == '\\' || *tmpptr == '/') + { + lastslash = tmpptr; + } + } + if( lastslash != NULL ) + { + savefilenameinzip = lastslash+1; // base filename follows last slash. + } + } + + /**/ + err = zipOpenNewFileInZip3_64(zf,savefilenameinzip,&zi, + NULL,0,NULL,0,NULL /* comment*/, + (opt_compress_level != 0) ? Z_DEFLATED : 0, + opt_compress_level,0, + /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + password,crcFile, zip64); + + if (err != ZIP_OK) + printf("error in opening %s in zipfile\n",filenameinzip); + else + { + fin = FOPEN_FUNC(filenameinzip,"rb"); + if (fin==NULL) + { + err=ZIP_ERRNO; + printf("error in opening %s for reading\n",filenameinzip); + } + } + + if (err == ZIP_OK) + do + { + err = ZIP_OK; + size_read = (int)fread(buf,1,size_buf,fin); + if (size_read < size_buf) + if (feof(fin)==0) + { + printf("error in reading %s\n",filenameinzip); + err = ZIP_ERRNO; + } + + if (size_read>0) + { + err = zipWriteInFileInZip (zf,buf,size_read); + if (err<0) + { + printf("error in writing %s in the zipfile\n", + filenameinzip); + } + + } + } while ((err == ZIP_OK) && (size_read>0)); + + if (fin) + fclose(fin); + + if (err<0) + err=ZIP_ERRNO; + else + { + err = zipCloseFileInZip(zf); + if (err!=ZIP_OK) + printf("error in closing %s in the zipfile\n", + filenameinzip); + } + } + } + errclose = zipClose(zf,NULL); + if (errclose != ZIP_OK) + printf("error in closing %s\n",filename_try); + } + else + { + do_help(); + } + + free(buf); + return 0; +} diff --git a/zlib-1.2.11/contrib/minizip/minizip.pc.in b/zlib-1.2.11/contrib/minizip/minizip.pc.in new file mode 100644 index 00000000..69b5b7fd --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/minizip.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/minizip + +Name: minizip +Description: Minizip zip file manipulation library +Requires: +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lminizip +Libs.private: -lz +Cflags: -I${includedir} diff --git a/zlib-1.2.11/contrib/minizip/mztools.c b/zlib-1.2.11/contrib/minizip/mztools.c new file mode 100644 index 00000000..96891c2e --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/mztools.c @@ -0,0 +1,291 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +/* Code */ +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#define READ_8(adr) ((unsigned char)*(adr)) +#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) +#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) + +#define WRITE_8(buff, n) do { \ + *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ +} while(0) +#define WRITE_16(buff, n) do { \ + WRITE_8((unsigned char*)(buff), n); \ + WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ +} while(0) +#define WRITE_32(buff, n) do { \ + WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ + WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ +} while(0) + +extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) +const char* file; +const char* fileOut; +const char* fileOutTmp; +uLong* nRecovered; +uLong* bytesRecovered; +{ + int err = Z_OK; + FILE* fpZip = fopen(file, "rb"); + FILE* fpOut = fopen(fileOut, "wb"); + FILE* fpOutCD = fopen(fileOutTmp, "wb"); + if (fpZip != NULL && fpOut != NULL) { + int entries = 0; + uLong totalBytes = 0; + char header[30]; + char filename[1024]; + char extra[1024]; + int offset = 0; + int offsetCD = 0; + while ( fread(header, 1, 30, fpZip) == 30 ) { + int currentOffset = offset; + + /* File entry */ + if (READ_32(header) == 0x04034b50) { + unsigned int version = READ_16(header + 4); + unsigned int gpflag = READ_16(header + 6); + unsigned int method = READ_16(header + 8); + unsigned int filetime = READ_16(header + 10); + unsigned int filedate = READ_16(header + 12); + unsigned int crc = READ_32(header + 14); /* crc */ + unsigned int cpsize = READ_32(header + 18); /* compressed size */ + unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ + unsigned int fnsize = READ_16(header + 26); /* file name length */ + unsigned int extsize = READ_16(header + 28); /* extra field length */ + filename[0] = extra[0] = '\0'; + + /* Header */ + if (fwrite(header, 1, 30, fpOut) == 30) { + offset += 30; + } else { + err = Z_ERRNO; + break; + } + + /* Filename */ + if (fnsize > 0) { + if (fnsize < sizeof(filename)) { + if (fread(filename, 1, fnsize, fpZip) == fnsize) { + if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { + offset += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (extsize < sizeof(extra)) { + if (fread(extra, 1, extsize, fpZip) == extsize) { + if (fwrite(extra, 1, extsize, fpOut) == extsize) { + offset += extsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_ERRNO; + break; + } + } + + /* Data */ + { + int dataSize = cpsize; + if (dataSize == 0) { + dataSize = uncpsize; + } + if (dataSize > 0) { + char* data = malloc(dataSize); + if (data != NULL) { + if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { + if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { + offset += dataSize; + totalBytes += dataSize; + } else { + err = Z_ERRNO; + } + } else { + err = Z_ERRNO; + } + free(data); + if (err != Z_OK) { + break; + } + } else { + err = Z_MEM_ERROR; + break; + } + } + } + + /* Central directory entry */ + { + char header[46]; + char* comment = ""; + int comsize = (int) strlen(comment); + WRITE_32(header, 0x02014b50); + WRITE_16(header + 4, version); + WRITE_16(header + 6, version); + WRITE_16(header + 8, gpflag); + WRITE_16(header + 10, method); + WRITE_16(header + 12, filetime); + WRITE_16(header + 14, filedate); + WRITE_32(header + 16, crc); + WRITE_32(header + 20, cpsize); + WRITE_32(header + 24, uncpsize); + WRITE_16(header + 28, fnsize); + WRITE_16(header + 30, extsize); + WRITE_16(header + 32, comsize); + WRITE_16(header + 34, 0); /* disk # */ + WRITE_16(header + 36, 0); /* int attrb */ + WRITE_32(header + 38, 0); /* ext attrb */ + WRITE_32(header + 42, currentOffset); + /* Header */ + if (fwrite(header, 1, 46, fpOutCD) == 46) { + offsetCD += 46; + + /* Filename */ + if (fnsize > 0) { + if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { + offsetCD += fnsize; + } else { + err = Z_ERRNO; + break; + } + } else { + err = Z_STREAM_ERROR; + break; + } + + /* Extra field */ + if (extsize > 0) { + if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { + offsetCD += extsize; + } else { + err = Z_ERRNO; + break; + } + } + + /* Comment field */ + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { + offsetCD += comsize; + } else { + err = Z_ERRNO; + break; + } + } + + + } else { + err = Z_ERRNO; + break; + } + } + + /* Success */ + entries++; + + } else { + break; + } + } + + /* Final central directory */ + { + int entriesZip = entries; + char header[22]; + char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; + int comsize = (int) strlen(comment); + if (entriesZip > 0xffff) { + entriesZip = 0xffff; + } + WRITE_32(header, 0x06054b50); + WRITE_16(header + 4, 0); /* disk # */ + WRITE_16(header + 6, 0); /* disk # */ + WRITE_16(header + 8, entriesZip); /* hack */ + WRITE_16(header + 10, entriesZip); /* hack */ + WRITE_32(header + 12, offsetCD); /* size of CD */ + WRITE_32(header + 16, offset); /* offset to CD */ + WRITE_16(header + 20, comsize); /* comment */ + + /* Header */ + if (fwrite(header, 1, 22, fpOutCD) == 22) { + + /* Comment field */ + if (comsize > 0) { + if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { + err = Z_ERRNO; + } + } + + } else { + err = Z_ERRNO; + } + } + + /* Final merge (file + central directory) */ + fclose(fpOutCD); + if (err == Z_OK) { + fpOutCD = fopen(fileOutTmp, "rb"); + if (fpOutCD != NULL) { + int nRead; + char buffer[8192]; + while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { + if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { + err = Z_ERRNO; + break; + } + } + fclose(fpOutCD); + } + } + + /* Close */ + fclose(fpZip); + fclose(fpOut); + + /* Wipe temporary file */ + (void)remove(fileOutTmp); + + /* Number of recovered entries */ + if (err == Z_OK) { + if (nRecovered != NULL) { + *nRecovered = entries; + } + if (bytesRecovered != NULL) { + *bytesRecovered = totalBytes; + } + } + } else { + err = Z_STREAM_ERROR; + } + return err; +} diff --git a/zlib-1.2.11/contrib/minizip/mztools.h b/zlib-1.2.11/contrib/minizip/mztools.h new file mode 100644 index 00000000..a49a426e --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/mztools.h @@ -0,0 +1,37 @@ +/* + Additional tools for Minizip + Code: Xavier Roche '2004 + License: Same as ZLIB (www.gzip.org) +*/ + +#ifndef _zip_tools_H +#define _zip_tools_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#include "unzip.h" + +/* Repair a ZIP file (missing central directory) + file: file to recover + fileOut: output file after recovery + fileOutTmp: temporary file name used for recovery +*/ +extern int ZEXPORT unzRepair(const char* file, + const char* fileOut, + const char* fileOutTmp, + uLong* nRecovered, + uLong* bytesRecovered); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/zlib-1.2.11/contrib/minizip/unzip.c b/zlib-1.2.11/contrib/minizip/unzip.c new file mode 100644 index 00000000..bcfb9416 --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/unzip.c @@ -0,0 +1,2125 @@ +/* unzip.c -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + + ------------------------------------------------------------------------------------ + Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of + compatibility with older software. The following is from the original crypt.c. + Code woven in by Terry Thorsen 1/2003. + + Copyright (c) 1990-2000 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2000-Apr-09 or later + (the contents of which are also included in zip.h) for terms of use. + If, for some reason, all these files are missing, the Info-ZIP license + also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html + + crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] + + The encryption/decryption parts of this source code (as opposed to the + non-echoing password parts) were originally written in Europe. The + whole source package can be freely distributed, including from the USA. + (Prior to January 2000, re-export from the US was a violation of US law.) + + This encryption code is a direct transcription of the algorithm from + Roger Schlafly, described by Phil Katz in the file appnote.txt. This + file (appnote.txt) is distributed with the PKZIP program (even in the + version without encryption capabilities). + + ------------------------------------------------------------------------------------ + + Changes in unzip.c + + 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos + 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz* + 2007-2008 - Even Rouault - Remove old C style function prototypes + 2007-2008 - Even Rouault - Add unzip support for ZIP64 + + Copyright (C) 2007-2008 Even Rouault + + + Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again). + Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G + should only read the compressed/uncompressed size from the Zip64 format if + the size from normal header was 0xFFFFFFFF + Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant + Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required) + Patch created by Daniel Borca + + Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer + + Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson + +*/ + + +#include +#include +#include + +#ifndef NOUNCRYPT + #define NOUNCRYPT +#endif + +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + + +#ifndef CASESENSITIVITYDEFAULT_NO +# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) +# define CASESENSITIVITYDEFAULT_NO +# endif +#endif + + +#ifndef UNZ_BUFSIZE +#define UNZ_BUFSIZE (16384) +#endif + +#ifndef UNZ_MAXFILENAMEINZIP +#define UNZ_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) + + +const char unz_copyright[] = + " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + +/* unz_file_info_interntal contain internal info about a file in zipfile*/ +typedef struct unz_file_info64_internal_s +{ + ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */ +} unz_file_info64_internal; + + +/* file_in_zip_read_info_s contain internal information about a file in zipfile, + when reading and decompress it */ +typedef struct +{ + char *read_buffer; /* internal buffer for compressed data */ + z_stream stream; /* zLib stream structure for inflate */ + +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif + + ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ + uLong stream_initialised; /* flag set if stream structure is initialised*/ + + ZPOS64_T offset_local_extrafield;/* offset of the local extra field */ + uInt size_local_extrafield;/* size of the local extra field */ + ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/ + ZPOS64_T total_out_64; + + uLong crc32; /* crc32 of all data uncompressed */ + uLong crc32_wait; /* crc32 we must obtain after decompress all */ + ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */ + ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/ + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + uLong compression_method; /* compression method (0==store) */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + int raw; +} file_in_zip64_read_info_s; + + +/* unz64_s contain internal information about the zipfile +*/ +typedef struct +{ + zlib_filefunc64_32_def z_filefunc; + int is64bitOpenFunction; + voidpf filestream; /* io structore of the zipfile */ + unz_global_info64 gi; /* public global information */ + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + ZPOS64_T num_file; /* number of the current file in the zipfile*/ + ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/ + ZPOS64_T current_file_ok; /* flag about the usability of the current file*/ + ZPOS64_T central_pos; /* position of the beginning of the central dir*/ + + ZPOS64_T size_central_dir; /* size of the central directory */ + ZPOS64_T offset_central_dir; /* offset of start of central directory with + respect to the starting disk number */ + + unz_file_info64 cur_file_info; /* public info about the current file in zip*/ + unz_file_info64_internal cur_file_info_internal; /* private info about it*/ + file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current + file if we are decompressing it */ + int encrypted; + + int isZip64; + +# ifndef NOUNCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const z_crc_t* pcrc_32_tab; +# endif +} unz64_s; + + +#ifndef NOUNCRYPT +#include "crypt.h" +#endif + +/* =========================================================================== + Read a byte from a gz_stream; update next_in and avail_in. Return EOF + for end of file. + IN assertion: the stream s has been successfully opened for reading. +*/ + + +local int unz64local_getByte OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + int *pi)); + +local int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return UNZ_OK; + } + else + { + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return UNZ_ERRNO; + else + return UNZ_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int unz64local_getShort OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX)); + +local int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + uLong *pX) +{ + uLong x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((uLong)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int unz64local_getLong64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX)); + + +local int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream, + ZPOS64_T *pX) +{ + ZPOS64_T x ; + int i = 0; + int err; + + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (ZPOS64_T)i; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<8; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<16; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<24; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<32; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<40; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<48; + + if (err==UNZ_OK) + err = unz64local_getByte(pzlib_filefunc_def,filestream,&i); + x |= ((ZPOS64_T)i)<<56; + + if (err==UNZ_OK) + *pX = x; + else + *pX = 0; + return err; +} + +/* My own strcmpi / strcasecmp */ +local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) +{ + for (;;) + { + char c1=*(fileName1++); + char c2=*(fileName2++); + if ((c1>='a') && (c1<='z')) + c1 -= 0x20; + if ((c2>='a') && (c2<='z')) + c2 -= 0x20; + if (c1=='\0') + return ((c2=='\0') ? 0 : -1); + if (c2=='\0') + return 1; + if (c1c2) + return 1; + } +} + + +#ifdef CASESENSITIVITYDEFAULT_NO +#define CASESENSITIVITYDEFAULTVALUE 2 +#else +#define CASESENSITIVITYDEFAULTVALUE 1 +#endif + +#ifndef STRCMPCASENOSENTIVEFUNCTION +#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal +#endif + +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) + +*/ +extern int ZEXPORT unzStringFileNameCompare (const char* fileName1, + const char* fileName2, + int iCaseSensitivity) + +{ + if (iCaseSensitivity==0) + iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; + + if (iCaseSensitivity==1) + return strcmp(fileName1,fileName2); + + return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif + +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); +local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + + +/* + Locate the Central directory 64 of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T unz64local_SearchCentralDir64 OF(( + const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream)); + +local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, + voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + uLong uL; + ZPOS64_T relativeOffset; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + if (uPosFound == 0) + return 0; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature, already checked */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + /* number of the disk with the start of the zip64 end of central directory */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 0) + return 0; + + /* relative offset of the zip64 end of central directory record */ + if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK) + return 0; + + /* total number of disks */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + if (uL != 1) + return 0; + + /* Goto end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature */ + if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK) + return 0; + + if (uL != 0x06064b50) + return 0; + + return relativeOffset; +} + +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer + "zlib/zlib114.zip". + If the zipfile cannot be opened (file doesn't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. +*/ +local unzFile unzOpenInternal (const void *path, + zlib_filefunc64_32_def* pzlib_filefunc64_32_def, + int is64bitOpenFunction) +{ + unz64_s us; + unz64_s *s; + ZPOS64_T central_pos; + uLong uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + ZPOS64_T number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + + int err=UNZ_OK; + + if (unz_copyright[0]!=' ') + return NULL; + + us.z_filefunc.zseek32_file = NULL; + us.z_filefunc.ztell32_file = NULL; + if (pzlib_filefunc64_32_def==NULL) + fill_fopen64_filefunc(&us.z_filefunc.zfile_func64); + else + us.z_filefunc = *pzlib_filefunc64_32_def; + us.is64bitOpenFunction = is64bitOpenFunction; + + + + us.filestream = ZOPEN64(us.z_filefunc, + path, + ZLIB_FILEFUNC_MODE_READ | + ZLIB_FILEFUNC_MODE_EXISTING); + if (us.filestream==NULL) + return NULL; + + central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream); + if (central_pos) + { + uLong uS; + ZPOS64_T uL64; + + us.isZip64 = 1; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* size of zip64 end of central directory record */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version made by */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* version needed to extract */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory on this disk */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) + err=UNZ_ERRNO; + + us.gi.size_comment = 0; + } + else + { + central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream); + if (central_pos==0) + err=UNZ_ERRNO; + + us.isZip64 = 0; + + if (ZSEEK64(us.z_filefunc, us.filestream, + central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + /* the signature, already checked */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) + err=UNZ_ERRNO; + + /* number of the disk with the start of the central directory */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) + err=UNZ_ERRNO; + + /* total number of entries in the central dir on this disk */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.gi.number_entry = uL; + + /* total number of entries in the central dir */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + number_entry_CD = uL; + + if ((number_entry_CD!=us.gi.number_entry) || + (number_disk_with_CD!=0) || + (number_disk!=0)) + err=UNZ_BADZIPFILE; + + /* size of the central directory */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.size_central_dir = uL; + + /* offset of start of central directory with respect to the + starting disk number */ + if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) + err=UNZ_ERRNO; + us.offset_central_dir = uL; + + /* zipfile comment length */ + if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) + err=UNZ_ERRNO; + } + + if ((central_pospfile_in_zip_read!=NULL) + unzCloseCurrentFile(file); + + ZCLOSE64(s->z_filefunc, s->filestream); + TRYFREE(s); + return UNZ_OK; +} + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ +extern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + *pglobal_info=s->gi; + return UNZ_OK; +} + +extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32) +{ + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + /* to do : check if number_entry is not truncated */ + pglobal_info32->number_entry = (uLong)s->gi.number_entry; + pglobal_info32->size_comment = s->gi.size_comment; + return UNZ_OK; +} +/* + Translate date/time from Dos format to tm_unz (readable more easilty) +*/ +local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm) +{ + ZPOS64_T uDate; + uDate = (ZPOS64_T)(ulDosDate>>16); + ptm->tm_mday = (uInt)(uDate&0x1f) ; + ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; + ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; + + ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); + ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; + ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; +} + +/* + Get Info about the current file in the zipfile, with internal only info +*/ +local int unz64local_GetCurrentFileInfoInternal OF((unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +local int unz64local_GetCurrentFileInfoInternal (unzFile file, + unz_file_info64 *pfile_info, + unz_file_info64_internal + *pfile_info_internal, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize) +{ + unz64_s* s; + unz_file_info64 file_info; + unz_file_info64_internal file_info_internal; + int err=UNZ_OK; + uLong uMagic; + long lSeek=0; + uLong uL; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pos_in_central_dir+s->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + err=UNZ_ERRNO; + + + /* we check the magic */ + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x02014b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) + err=UNZ_ERRNO; + + unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.compressed_size = uL; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info.uncompressed_size = uL; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) + err=UNZ_ERRNO; + + // relative offset of local header + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + file_info_internal.offset_curfile = uL; + + lSeek+=file_info.size_filename; + if ((err==UNZ_OK) && (szFileName!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_filename0) && (fileNameBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek -= uSizeRead; + } + + // Read extrafield + if ((err==UNZ_OK) && (extraField!=NULL)) + { + ZPOS64_T uSizeRead ; + if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + + lSeek += file_info.size_file_extra - (uLong)uSizeRead; + } + else + lSeek += file_info.size_file_extra; + + + if ((err==UNZ_OK) && (file_info.size_file_extra != 0)) + { + uLong acc = 0; + + // since lSeek now points to after the extra field we need to move back + lSeek -= file_info.size_file_extra; + + if (lSeek!=0) + { + if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + while(acc < file_info.size_file_extra) + { + uLong headerId; + uLong dataSize; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK) + err=UNZ_ERRNO; + + /* ZIP64 extra fields */ + if (headerId == 0x0001) + { + uLong uL; + + if(file_info.uncompressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info.compressed_size == MAXU32) + { + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info_internal.offset_curfile == MAXU32) + { + /* Relative Header offset */ + if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK) + err=UNZ_ERRNO; + } + + if(file_info.disk_num_start == MAXU32) + { + /* Disk Start Number */ + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK) + err=UNZ_ERRNO; + } + + } + else + { + if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0) + err=UNZ_ERRNO; + } + + acc += 2 + 2 + dataSize; + } + } + + if ((err==UNZ_OK) && (szComment!=NULL)) + { + uLong uSizeRead ; + if (file_info.size_file_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) + lSeek=0; + else + err=UNZ_ERRNO; + } + + if ((file_info.size_file_comment>0) && (commentBufferSize>0)) + if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) + err=UNZ_ERRNO; + lSeek+=file_info.size_file_comment - uSizeRead; + } + else + lSeek+=file_info.size_file_comment; + + + if ((err==UNZ_OK) && (pfile_info!=NULL)) + *pfile_info=file_info; + + if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) + *pfile_info_internal=file_info_internal; + + return err; +} + + + +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. +*/ +extern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file, + unz_file_info64 * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); +} + +extern int ZEXPORT unzGetCurrentFileInfo (unzFile file, + unz_file_info * pfile_info, + char * szFileName, uLong fileNameBufferSize, + void *extraField, uLong extraFieldBufferSize, + char* szComment, uLong commentBufferSize) +{ + int err; + unz_file_info64 file_info64; + err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL, + szFileName,fileNameBufferSize, + extraField,extraFieldBufferSize, + szComment,commentBufferSize); + if ((err==UNZ_OK) && (pfile_info != NULL)) + { + pfile_info->version = file_info64.version; + pfile_info->version_needed = file_info64.version_needed; + pfile_info->flag = file_info64.flag; + pfile_info->compression_method = file_info64.compression_method; + pfile_info->dosDate = file_info64.dosDate; + pfile_info->crc = file_info64.crc; + + pfile_info->size_filename = file_info64.size_filename; + pfile_info->size_file_extra = file_info64.size_file_extra; + pfile_info->size_file_comment = file_info64.size_file_comment; + + pfile_info->disk_num_start = file_info64.disk_num_start; + pfile_info->internal_fa = file_info64.internal_fa; + pfile_info->external_fa = file_info64.external_fa; + + pfile_info->tmu_date = file_info64.tmu_date, + + + pfile_info->compressed_size = (uLong)file_info64.compressed_size; + pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size; + + } + return err; +} +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ +extern int ZEXPORT unzGoToFirstFile (unzFile file) +{ + int err=UNZ_OK; + unz64_s* s; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + s->pos_in_central_dir=s->offset_central_dir; + s->num_file=0; + err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ +extern int ZEXPORT unzGoToNextFile (unzFile file) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ + if (s->num_file+1==s->gi.number_entry) + return UNZ_END_OF_LIST_OF_FILE; + + s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + + s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; + s->num_file++; + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + + +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ +extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity) +{ + unz64_s* s; + int err; + + /* We remember the 'current' position in the file so that we can jump + * back there if we fail. + */ + unz_file_info64 cur_file_infoSaved; + unz_file_info64_internal cur_file_info_internalSaved; + ZPOS64_T num_fileSaved; + ZPOS64_T pos_in_central_dirSaved; + + + if (file==NULL) + return UNZ_PARAMERROR; + + if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) + return UNZ_PARAMERROR; + + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + /* Save the current state */ + num_fileSaved = s->num_file; + pos_in_central_dirSaved = s->pos_in_central_dir; + cur_file_infoSaved = s->cur_file_info; + cur_file_info_internalSaved = s->cur_file_info_internal; + + err = unzGoToFirstFile(file); + + while (err == UNZ_OK) + { + char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; + err = unzGetCurrentFileInfo64(file,NULL, + szCurrentFileName,sizeof(szCurrentFileName)-1, + NULL,0,NULL,0); + if (err == UNZ_OK) + { + if (unzStringFileNameCompare(szCurrentFileName, + szFileName,iCaseSensitivity)==0) + return UNZ_OK; + err = unzGoToNextFile(file); + } + } + + /* We failed, so restore the state of the 'current file' to where we + * were. + */ + s->num_file = num_fileSaved ; + s->pos_in_central_dir = pos_in_central_dirSaved ; + s->cur_file_info = cur_file_infoSaved; + s->cur_file_info_internal = cur_file_info_internalSaved; + return err; +} + + +/* +/////////////////////////////////////////// +// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) +// I need random access +// +// Further optimization could be realized by adding an ability +// to cache the directory in memory. The goal being a single +// comprehensive file read to put the file I need in a memory. +*/ + +/* +typedef struct unz_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; // offset in file + ZPOS64_T num_of_file; // # of file +} unz_file_pos; +*/ + +extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) +{ + unz64_s* s; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_END_OF_LIST_OF_FILE; + + file_pos->pos_in_zip_directory = s->pos_in_central_dir; + file_pos->num_of_file = s->num_file; + + return UNZ_OK; +} + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + int err = unzGetFilePos64(file,&file_pos64); + if (err==UNZ_OK) + { + file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory; + file_pos->num_of_file = (uLong)file_pos64.num_of_file; + } + return err; +} + +extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) +{ + unz64_s* s; + int err; + + if (file==NULL || file_pos==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + /* jump to the right spot */ + s->pos_in_central_dir = file_pos->pos_in_zip_directory; + s->num_file = file_pos->num_of_file; + + /* set the current file */ + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + /* return results */ + s->current_file_ok = (err == UNZ_OK); + return err; +} + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos) +{ + unz64_file_pos file_pos64; + if (file_pos == NULL) + return UNZ_PARAMERROR; + + file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory; + file_pos64.num_of_file = file_pos->num_of_file; + return unzGoToFilePos64(file,&file_pos64); +} + +/* +// Unzip Helper Functions - should be here? +/////////////////////////////////////////// +*/ + +/* + Read the local header of the current zipfile + Check the coherency of the local header and info in the end of central + directory about this file + store in *piSizeVar the size of extra info in local header + (filename and size of extra field data) +*/ +local int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar, + ZPOS64_T * poffset_local_extrafield, + uInt * psize_local_extrafield) +{ + uLong uMagic,uData,uFlags; + uLong size_filename; + uLong size_extra_field; + int err=UNZ_OK; + + *piSizeVar = 0; + *poffset_local_extrafield = 0; + *psize_local_extrafield = 0; + + if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + + s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + + if (err==UNZ_OK) + { + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) + err=UNZ_ERRNO; + else if (uMagic!=0x04034b50) + err=UNZ_BADZIPFILE; + } + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; +/* + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) + err=UNZ_BADZIPFILE; +*/ + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) + err=UNZ_ERRNO; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) + err=UNZ_BADZIPFILE; + + if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ + err=UNZ_ERRNO; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */ + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */ + err=UNZ_ERRNO; + else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0)) + err=UNZ_BADZIPFILE; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK) + err=UNZ_ERRNO; + else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) + err=UNZ_BADZIPFILE; + + *piSizeVar += (uInt)size_filename; + + if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK) + err=UNZ_ERRNO; + *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + + SIZEZIPLOCALHEADER + size_filename; + *psize_local_extrafield = (uInt)size_extra_field; + + *piSizeVar += (uInt)size_extra_field; + + return err; +} + +/* + Open for reading data the current file in the zipfile. + If there is no error and the file is opened, the return value is UNZ_OK. +*/ +extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method, + int* level, int raw, const char* password) +{ + int err=UNZ_OK; + uInt iSizeVar; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + ZPOS64_T offset_local_extrafield; /* offset of the local extra field */ + uInt size_local_extrafield; /* size of the local extra field */ +# ifndef NOUNCRYPT + char source[12]; +# else + if (password != NULL) + return UNZ_PARAMERROR; +# endif + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return UNZ_PARAMERROR; + + if (s->pfile_in_zip_read != NULL) + unzCloseCurrentFile(file); + + if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) + return UNZ_BADZIPFILE; + + pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s)); + if (pfile_in_zip_read_info==NULL) + return UNZ_INTERNALERROR; + + pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); + pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; + pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; + pfile_in_zip_read_info->pos_local_extrafield=0; + pfile_in_zip_read_info->raw=raw; + + if (pfile_in_zip_read_info->read_buffer==NULL) + { + TRYFREE(pfile_in_zip_read_info); + return UNZ_INTERNALERROR; + } + + pfile_in_zip_read_info->stream_initialised=0; + + if (method!=NULL) + *method = (int)s->cur_file_info.compression_method; + + if (level!=NULL) + { + *level = 6; + switch (s->cur_file_info.flag & 0x06) + { + case 6 : *level = 1; break; + case 4 : *level = 2; break; + case 2 : *level = 9; break; + } + } + + if ((s->cur_file_info.compression_method!=0) && +/* #ifdef HAVE_BZIP2 */ + (s->cur_file_info.compression_method!=Z_BZIP2ED) && +/* #endif */ + (s->cur_file_info.compression_method!=Z_DEFLATED)) + + err=UNZ_BADZIPFILE; + + pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; + pfile_in_zip_read_info->crc32=0; + pfile_in_zip_read_info->total_out_64=0; + pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method; + pfile_in_zip_read_info->filestream=s->filestream; + pfile_in_zip_read_info->z_filefunc=s->z_filefunc; + pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; + + pfile_in_zip_read_info->stream.total_out = 0; + + if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw)) + { +#ifdef HAVE_BZIP2 + pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0; + pfile_in_zip_read_info->bstream.bzfree = (free_func)0; + pfile_in_zip_read_info->bstream.opaque = (voidpf)0; + pfile_in_zip_read_info->bstream.state = (voidpf)0; + + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = (voidpf)0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } +#else + pfile_in_zip_read_info->raw=1; +#endif + } + else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw)) + { + pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; + pfile_in_zip_read_info->stream.zfree = (free_func)0; + pfile_in_zip_read_info->stream.opaque = (voidpf)0; + pfile_in_zip_read_info->stream.next_in = 0; + pfile_in_zip_read_info->stream.avail_in = 0; + + err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); + if (err == Z_OK) + pfile_in_zip_read_info->stream_initialised=Z_DEFLATED; + else + { + TRYFREE(pfile_in_zip_read_info); + return err; + } + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + * In unzip, i don't wait absolutely Z_STREAM_END because I known the + * size of both compressed and uncompressed data + */ + } + pfile_in_zip_read_info->rest_read_compressed = + s->cur_file_info.compressed_size ; + pfile_in_zip_read_info->rest_read_uncompressed = + s->cur_file_info.uncompressed_size ; + + + pfile_in_zip_read_info->pos_in_zipfile = + s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + + iSizeVar; + + pfile_in_zip_read_info->stream.avail_in = (uInt)0; + + s->pfile_in_zip_read = pfile_in_zip_read_info; + s->encrypted = 0; + +# ifndef NOUNCRYPT + if (password != NULL) + { + int i; + s->pcrc_32_tab = get_crc_table(); + init_keys(password,s->keys,s->pcrc_32_tab); + if (ZSEEK64(s->z_filefunc, s->filestream, + s->pfile_in_zip_read->pos_in_zipfile + + s->pfile_in_zip_read->byte_before_the_zipfile, + SEEK_SET)!=0) + return UNZ_INTERNALERROR; + if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12) + return UNZ_INTERNALERROR; + + for (i = 0; i<12; i++) + zdecode(s->keys,s->pcrc_32_tab,source[i]); + + s->pfile_in_zip_read->pos_in_zipfile+=12; + s->encrypted=1; + } +# endif + + + return UNZ_OK; +} + +extern int ZEXPORT unzOpenCurrentFile (unzFile file) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); +} + +extern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char* password) +{ + return unzOpenCurrentFile3(file, NULL, NULL, 0, password); +} + +extern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw) +{ + return unzOpenCurrentFile3(file, method, level, raw, NULL); +} + +/** Addition for GDAL : START */ + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + s=(unz64_s*)file; + if (file==NULL) + return 0; //UNZ_PARAMERROR; + pfile_in_zip_read_info=s->pfile_in_zip_read; + if (pfile_in_zip_read_info==NULL) + return 0; //UNZ_PARAMERROR; + return pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile; +} + +/** Addition for GDAL : END */ + +/* + Read bytes from the current file. + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ +extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len) +{ + int err=UNZ_OK; + uInt iRead = 0; + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if (pfile_in_zip_read_info->read_buffer == NULL) + return UNZ_END_OF_LIST_OF_FILE; + if (len==0) + return 0; + + pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; + + pfile_in_zip_read_info->stream.avail_out = (uInt)len; + + if ((len>pfile_in_zip_read_info->rest_read_uncompressed) && + (!(pfile_in_zip_read_info->raw))) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_uncompressed; + + if ((len>pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in) && + (pfile_in_zip_read_info->raw)) + pfile_in_zip_read_info->stream.avail_out = + (uInt)pfile_in_zip_read_info->rest_read_compressed+ + pfile_in_zip_read_info->stream.avail_in; + + while (pfile_in_zip_read_info->stream.avail_out>0) + { + if ((pfile_in_zip_read_info->stream.avail_in==0) && + (pfile_in_zip_read_info->rest_read_compressed>0)) + { + uInt uReadThis = UNZ_BUFSIZE; + if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; + if (uReadThis == 0) + return UNZ_EOF; + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->pos_in_zipfile + + pfile_in_zip_read_info->byte_before_the_zipfile, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->read_buffer, + uReadThis)!=uReadThis) + return UNZ_ERRNO; + + +# ifndef NOUNCRYPT + if(s->encrypted) + { + uInt i; + for(i=0;iread_buffer[i] = + zdecode(s->keys,s->pcrc_32_tab, + pfile_in_zip_read_info->read_buffer[i]); + } +# endif + + + pfile_in_zip_read_info->pos_in_zipfile += uReadThis; + + pfile_in_zip_read_info->rest_read_compressed-=uReadThis; + + pfile_in_zip_read_info->stream.next_in = + (Bytef*)pfile_in_zip_read_info->read_buffer; + pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; + } + + if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) + { + uInt uDoCopy,i ; + + if ((pfile_in_zip_read_info->stream.avail_in == 0) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + return (iRead==0) ? UNZ_EOF : iRead; + + if (pfile_in_zip_read_info->stream.avail_out < + pfile_in_zip_read_info->stream.avail_in) + uDoCopy = pfile_in_zip_read_info->stream.avail_out ; + else + uDoCopy = pfile_in_zip_read_info->stream.avail_in ; + + for (i=0;istream.next_out+i) = + *(pfile_in_zip_read_info->stream.next_in+i); + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, + pfile_in_zip_read_info->stream.next_out, + uDoCopy); + pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; + pfile_in_zip_read_info->stream.avail_in -= uDoCopy; + pfile_in_zip_read_info->stream.avail_out -= uDoCopy; + pfile_in_zip_read_info->stream.next_out += uDoCopy; + pfile_in_zip_read_info->stream.next_in += uDoCopy; + pfile_in_zip_read_info->stream.total_out += uDoCopy; + iRead += uDoCopy; + } + else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) + { +#ifdef HAVE_BZIP2 + uLong uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + uLong uOutThis; + + pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in; + pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in; + pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in; + pfile_in_zip_read_info->bstream.total_in_hi32 = 0; + pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out; + pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out; + pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out; + pfile_in_zip_read_info->bstream.total_out_hi32 = 0; + + uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32; + bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out; + + err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream); + + uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis)); + pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis; + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in; + pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in; + pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32; + pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out; + pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out; + pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32; + + if (err==BZ_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=BZ_OK) + break; +#endif + } // end Z_BZIP2ED + else + { + ZPOS64_T uTotalOutBefore,uTotalOutAfter; + const Bytef *bufBefore; + ZPOS64_T uOutThis; + int flush=Z_SYNC_FLUSH; + + uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; + bufBefore = pfile_in_zip_read_info->stream.next_out; + + /* + if ((pfile_in_zip_read_info->rest_read_uncompressed == + pfile_in_zip_read_info->stream.avail_out) && + (pfile_in_zip_read_info->rest_read_compressed == 0)) + flush = Z_FINISH; + */ + err=inflate(&pfile_in_zip_read_info->stream,flush); + + if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) + err = Z_DATA_ERROR; + + uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; + uOutThis = uTotalOutAfter-uTotalOutBefore; + + pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis; + + pfile_in_zip_read_info->crc32 = + crc32(pfile_in_zip_read_info->crc32,bufBefore, + (uInt)(uOutThis)); + + pfile_in_zip_read_info->rest_read_uncompressed -= + uOutThis; + + iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); + + if (err==Z_STREAM_END) + return (iRead==0) ? UNZ_EOF : iRead; + if (err!=Z_OK) + break; + } + } + + if (err==Z_OK) + return iRead; + return err; +} + + +/* + Give the current position in uncompressed data +*/ +extern z_off_t ZEXPORT unztell (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + return (z_off_t)pfile_in_zip_read_info->stream.total_out; +} + +extern ZPOS64_T ZEXPORT unztell64 (unzFile file) +{ + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return (ZPOS64_T)-1; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return (ZPOS64_T)-1; + + return pfile_in_zip_read_info->total_out_64; +} + + +/* + return 1 if the end of file was reached, 0 elsewhere +*/ +extern int ZEXPORT unzeof (unzFile file) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + if (pfile_in_zip_read_info->rest_read_uncompressed == 0) + return 1; + else + return 0; +} + + + +/* +Read extra field from the current file (opened by unzOpenCurrentFile) +This is the local-header version of the extra field (sometimes, there is +more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field that can be read + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ +extern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len) +{ + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + uInt read_now; + ZPOS64_T size_to_read; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + size_to_read = (pfile_in_zip_read_info->size_local_extrafield - + pfile_in_zip_read_info->pos_local_extrafield); + + if (buf==NULL) + return (int)size_to_read; + + if (len>size_to_read) + read_now = (uInt)size_to_read; + else + read_now = (uInt)len ; + + if (read_now==0) + return 0; + + if (ZSEEK64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + pfile_in_zip_read_info->offset_local_extrafield + + pfile_in_zip_read_info->pos_local_extrafield, + ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (ZREAD64(pfile_in_zip_read_info->z_filefunc, + pfile_in_zip_read_info->filestream, + buf,read_now)!=read_now) + return UNZ_ERRNO; + + return (int)read_now; +} + +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ +extern int ZEXPORT unzCloseCurrentFile (unzFile file) +{ + int err=UNZ_OK; + + unz64_s* s; + file_in_zip64_read_info_s* pfile_in_zip_read_info; + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + pfile_in_zip_read_info=s->pfile_in_zip_read; + + if (pfile_in_zip_read_info==NULL) + return UNZ_PARAMERROR; + + + if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) && + (!pfile_in_zip_read_info->raw)) + { + if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) + err=UNZ_CRCERROR; + } + + + TRYFREE(pfile_in_zip_read_info->read_buffer); + pfile_in_zip_read_info->read_buffer = NULL; + if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED) + inflateEnd(&pfile_in_zip_read_info->stream); +#ifdef HAVE_BZIP2 + else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED) + BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream); +#endif + + + pfile_in_zip_read_info->stream_initialised = 0; + TRYFREE(pfile_in_zip_read_info); + + s->pfile_in_zip_read=NULL; + + return err; +} + + +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ +extern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf) +{ + unz64_s* s; + uLong uReadThis ; + if (file==NULL) + return (int)UNZ_PARAMERROR; + s=(unz64_s*)file; + + uReadThis = uSizeBuf; + if (uReadThis>s->gi.size_comment) + uReadThis = s->gi.size_comment; + + if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) + return UNZ_ERRNO; + + if (uReadThis>0) + { + *szComment='\0'; + if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) + return UNZ_ERRNO; + } + + if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) + *(szComment+s->gi.size_comment)='\0'; + return (int)uReadThis; +} + +/* Additions by RX '2004 */ +extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) +{ + unz64_s* s; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + s=(unz64_s*)file; + if (!s->current_file_ok) + return 0; + if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) + if (s->num_file==s->gi.number_entry) + return 0; + return s->pos_in_central_dir; +} + +extern uLong ZEXPORT unzGetOffset (unzFile file) +{ + ZPOS64_T offset64; + + if (file==NULL) + return 0; //UNZ_PARAMERROR; + offset64 = unzGetOffset64(file); + return (uLong)offset64; +} + +extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) +{ + unz64_s* s; + int err; + + if (file==NULL) + return UNZ_PARAMERROR; + s=(unz64_s*)file; + + s->pos_in_central_dir = pos; + s->num_file = s->gi.number_entry; /* hack */ + err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info, + &s->cur_file_info_internal, + NULL,0,NULL,0,NULL,0); + s->current_file_ok = (err == UNZ_OK); + return err; +} + +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) +{ + return unzSetOffset64(file,pos); +} diff --git a/zlib-1.2.11/contrib/minizip/unzip.h b/zlib-1.2.11/contrib/minizip/unzip.h new file mode 100644 index 00000000..2104e391 --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/unzip.h @@ -0,0 +1,437 @@ +/* unzip.h -- IO for uncompress .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications of Unzip for Zip64 + Copyright (C) 2007-2008 Even Rouault + + Modifications for Zip64 support on both zip and unzip + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + --------------------------------------------------------------------------------- + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + --------------------------------------------------------------------------------- + + Changes + + See header of unzip64.c + +*/ + +#ifndef _unz64_H +#define _unz64_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#ifdef HAVE_BZIP2 +#include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + +#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagunzFile__ { int unused; } unzFile__; +typedef unzFile__ *unzFile; +#else +typedef voidp unzFile; +#endif + + +#define UNZ_OK (0) +#define UNZ_END_OF_LIST_OF_FILE (-100) +#define UNZ_ERRNO (Z_ERRNO) +#define UNZ_EOF (0) +#define UNZ_PARAMERROR (-102) +#define UNZ_BADZIPFILE (-103) +#define UNZ_INTERNALERROR (-104) +#define UNZ_CRCERROR (-105) + +/* tm_unz contain date/time info */ +typedef struct tm_unz_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_unz; + +/* unz_global_info structure contain global data about the ZIPfile + These data comes from the end of central dir */ +typedef struct unz_global_info64_s +{ + ZPOS64_T number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info64; + +typedef struct unz_global_info_s +{ + uLong number_entry; /* total number of entries in + the central dir on this disk */ + uLong size_comment; /* size of the global comment of the zipfile */ +} unz_global_info; + +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_info64_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + ZPOS64_T compressed_size; /* compressed size 8 bytes */ + ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info64; + +typedef struct unz_file_info_s +{ + uLong version; /* version made by 2 bytes */ + uLong version_needed; /* version needed to extract 2 bytes */ + uLong flag; /* general purpose bit flag 2 bytes */ + uLong compression_method; /* compression method 2 bytes */ + uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ + uLong crc; /* crc-32 4 bytes */ + uLong compressed_size; /* compressed size 4 bytes */ + uLong uncompressed_size; /* uncompressed size 4 bytes */ + uLong size_filename; /* filename length 2 bytes */ + uLong size_file_extra; /* extra field length 2 bytes */ + uLong size_file_comment; /* file comment length 2 bytes */ + + uLong disk_num_start; /* disk number start 2 bytes */ + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ + + tm_unz tmu_date; +} unz_file_info; + +extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, + const char* fileName2, + int iCaseSensitivity)); +/* + Compare two filename (fileName1,fileName2). + If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) + If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi + or strcasecmp) + If iCaseSenisivity = 0, case sensitivity is defaut of your operating system + (like 1 on Unix, 2 on Windows) +*/ + + +extern unzFile ZEXPORT unzOpen OF((const char *path)); +extern unzFile ZEXPORT unzOpen64 OF((const void *path)); +/* + Open a Zip file. path contain the full pathname (by example, + on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer + "zlib/zlib113.zip". + If the zipfile cannot be opened (file don't exist or in not valid), the + return value is NULL. + Else, the return value is a unzFile Handle, usable with other function + of this unzip package. + the "64" function take a const void* pointer, because the path is just the + value passed to the open64_file_func callback. + Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path + is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char* + does not describe the reality +*/ + + +extern unzFile ZEXPORT unzOpen2 OF((const char *path, + zlib_filefunc_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unzOpen, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern unzFile ZEXPORT unzOpen2_64 OF((const void *path, + zlib_filefunc64_def* pzlib_filefunc_def)); +/* + Open a Zip file, like unz64Open, but provide a set of file low level API + for read/write the zip file (see ioapi.h) +*/ + +extern int ZEXPORT unzClose OF((unzFile file)); +/* + Close a ZipFile opened with unzOpen. + If there is files inside the .Zip opened with unzOpenCurrentFile (see later), + these files MUST be closed with unzCloseCurrentFile before call unzClose. + return UNZ_OK if there is no problem. */ + +extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, + unz_global_info *pglobal_info)); + +extern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file, + unz_global_info64 *pglobal_info)); +/* + Write info about the ZipFile in the *pglobal_info structure. + No preparation of the structure is needed + return UNZ_OK if there is no problem. */ + + +extern int ZEXPORT unzGetGlobalComment OF((unzFile file, + char *szComment, + uLong uSizeBuf)); +/* + Get the global comment string of the ZipFile, in the szComment buffer. + uSizeBuf is the size of the szComment buffer. + return the number of byte copied or an error code <0 +*/ + + +/***************************************************************************/ +/* Unzip package allow you browse the directory of the zipfile */ + +extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); +/* + Set the current file of the zipfile to the first file. + return UNZ_OK if there is no problem +*/ + +extern int ZEXPORT unzGoToNextFile OF((unzFile file)); +/* + Set the current file of the zipfile to the next file. + return UNZ_OK if there is no problem + return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. +*/ + +extern int ZEXPORT unzLocateFile OF((unzFile file, + const char *szFileName, + int iCaseSensitivity)); +/* + Try locate the file szFileName in the zipfile. + For the iCaseSensitivity signification, see unzStringFileNameCompare + + return value : + UNZ_OK if the file is found. It becomes the current file. + UNZ_END_OF_LIST_OF_FILE if the file is not found +*/ + + +/* ****************************************** */ +/* Ryan supplied functions */ +/* unz_file_info contain information about a file in the zipfile */ +typedef struct unz_file_pos_s +{ + uLong pos_in_zip_directory; /* offset in zip file directory */ + uLong num_of_file; /* # of file */ +} unz_file_pos; + +extern int ZEXPORT unzGetFilePos( + unzFile file, + unz_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos( + unzFile file, + unz_file_pos* file_pos); + +typedef struct unz64_file_pos_s +{ + ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */ + ZPOS64_T num_of_file; /* # of file */ +} unz64_file_pos; + +extern int ZEXPORT unzGetFilePos64( + unzFile file, + unz64_file_pos* file_pos); + +extern int ZEXPORT unzGoToFilePos64( + unzFile file, + const unz64_file_pos* file_pos); + +/* ****************************************** */ + +extern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file, + unz_file_info64 *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); + +extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, + unz_file_info *pfile_info, + char *szFileName, + uLong fileNameBufferSize, + void *extraField, + uLong extraFieldBufferSize, + char *szComment, + uLong commentBufferSize)); +/* + Get Info about the current file + if pfile_info!=NULL, the *pfile_info structure will contain somes info about + the current file + if szFileName!=NULL, the filemane string will be copied in szFileName + (fileNameBufferSize is the size of the buffer) + if extraField!=NULL, the extra field information will be copied in extraField + (extraFieldBufferSize is the size of the buffer). + This is the Central-header version of the extra field + if szComment!=NULL, the comment string of the file will be copied in szComment + (commentBufferSize is the size of the buffer) +*/ + + +/** Addition for GDAL : START */ + +extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file)); + +/** Addition for GDAL : END */ + + +/***************************************************************************/ +/* for reading the content of the current zipfile, you can open it, read data + from it, and close it (you can close it before reading all the file) + */ + +extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); +/* + Open for reading data the current file in the zipfile. + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, + const char* password)); +/* + Open for reading data the current file in the zipfile. + password is a crypting password + If there is no error, the return value is UNZ_OK. +*/ + +extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, + int* method, + int* level, + int raw)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + +extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, + int* method, + int* level, + int raw, + const char* password)); +/* + Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) + if raw==1 + *method will receive method of compression, *level will receive level of + compression + note : you can set level parameter as NULL (if you did not want known level, + but you CANNOT set method parameter as NULL +*/ + + +extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); +/* + Close the file in zip opened with unzOpenCurrentFile + Return UNZ_CRCERROR if all the file was read but the CRC is not good +*/ + +extern int ZEXPORT unzReadCurrentFile OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read bytes from the current file (opened by unzOpenCurrentFile) + buf contain buffer where data must be copied + len the size of buf. + + return the number of byte copied if somes bytes are copied + return 0 if the end of file was reached + return <0 with error code if there is an error + (UNZ_ERRNO for IO error, or zLib error for uncompress error) +*/ + +extern z_off_t ZEXPORT unztell OF((unzFile file)); + +extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file)); +/* + Give the current position in uncompressed data +*/ + +extern int ZEXPORT unzeof OF((unzFile file)); +/* + return 1 if the end of file was reached, 0 elsewhere +*/ + +extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, + voidp buf, + unsigned len)); +/* + Read extra field from the current file (opened by unzOpenCurrentFile) + This is the local-header version of the extra field (sometimes, there is + more info in the local-header version than in the central-header) + + if buf==NULL, it return the size of the local extra field + + if buf!=NULL, len is the size of the buffer, the extra header is copied in + buf. + the return value is the number of bytes copied in buf, or (if <0) + the error code +*/ + +/***************************************************************************/ + +/* Get the current file offset */ +extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file); +extern uLong ZEXPORT unzGetOffset (unzFile file); + +/* Set the current file offset */ +extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos); +extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); + + + +#ifdef __cplusplus +} +#endif + +#endif /* _unz64_H */ diff --git a/zlib-1.2.11/contrib/minizip/zip.c b/zlib-1.2.11/contrib/minizip/zip.c new file mode 100644 index 00000000..44e88a9c --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/zip.c @@ -0,0 +1,2007 @@ +/* zip.c -- IO on .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + Changes + Oct-2009 - Mathias Svensson - Remove old C style function prototypes + Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives + Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions. + Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data + It is used when recreting zip archive with RAW when deleting items from a zip. + ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed. + Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required) + Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer + +*/ + + +#include +#include +#include +#include +#include "zlib.h" +#include "zip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +#ifndef VERSIONMADEBY +# define VERSIONMADEBY (0x0) /* platform depedent */ +#endif + +#ifndef Z_BUFSIZE +#define Z_BUFSIZE (64*1024) //(16384) +#endif + +#ifndef Z_MAXFILENAMEINZIP +#define Z_MAXFILENAMEINZIP (256) +#endif + +#ifndef ALLOC +# define ALLOC(size) (malloc(size)) +#endif +#ifndef TRYFREE +# define TRYFREE(p) {if (p) free(p);} +#endif + +/* +#define SIZECENTRALDIRITEM (0x2e) +#define SIZEZIPLOCALHEADER (0x1e) +*/ + +/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ + + +// NOT sure that this work on ALL platform +#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32)) + +#ifndef SEEK_CUR +#define SEEK_CUR 1 +#endif + +#ifndef SEEK_END +#define SEEK_END 2 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifndef DEF_MEM_LEVEL +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +#endif +const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; + + +#define SIZEDATA_INDATABLOCK (4096-(4*4)) + +#define LOCALHEADERMAGIC (0x04034b50) +#define CENTRALHEADERMAGIC (0x02014b50) +#define ENDHEADERMAGIC (0x06054b50) +#define ZIP64ENDHEADERMAGIC (0x6064b50) +#define ZIP64ENDLOCHEADERMAGIC (0x7064b50) + +#define FLAG_LOCALHEADER_OFFSET (0x06) +#define CRC_LOCALHEADER_OFFSET (0x0e) + +#define SIZECENTRALHEADER (0x2e) /* 46 */ + +typedef struct linkedlist_datablock_internal_s +{ + struct linkedlist_datablock_internal_s* next_datablock; + uLong avail_in_this_block; + uLong filled_in_this_block; + uLong unused; /* for future use and alignment */ + unsigned char data[SIZEDATA_INDATABLOCK]; +} linkedlist_datablock_internal; + +typedef struct linkedlist_data_s +{ + linkedlist_datablock_internal* first_block; + linkedlist_datablock_internal* last_block; +} linkedlist_data; + + +typedef struct +{ + z_stream stream; /* zLib stream structure for inflate */ +#ifdef HAVE_BZIP2 + bz_stream bstream; /* bzLib stream structure for bziped */ +#endif + + int stream_initialised; /* 1 is stream is initialised */ + uInt pos_in_buffered_data; /* last written byte in buffered_data */ + + ZPOS64_T pos_local_header; /* offset of the local header of the file + currenty writing */ + char* central_header; /* central header data for the current file */ + uLong size_centralExtra; + uLong size_centralheader; /* size of the central header for cur file */ + uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */ + uLong flag; /* flag of the file currently writing */ + + int method; /* compression method of file currenty wr.*/ + int raw; /* 1 for directly writing raw data */ + Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/ + uLong dosDate; + uLong crc32; + int encrypt; + int zip64; /* Add ZIP64 extened information in the extra field */ + ZPOS64_T pos_zip64extrainfo; + ZPOS64_T totalCompressedData; + ZPOS64_T totalUncompressedData; +#ifndef NOCRYPT + unsigned long keys[3]; /* keys defining the pseudo-random sequence */ + const z_crc_t* pcrc_32_tab; + int crypt_header_size; +#endif +} curfile64_info; + +typedef struct +{ + zlib_filefunc64_32_def z_filefunc; + voidpf filestream; /* io structore of the zipfile */ + linkedlist_data central_dir;/* datablock with central dir in construction*/ + int in_opened_file_inzip; /* 1 if a file in the zip is currently writ.*/ + curfile64_info ci; /* info on the file curretly writing */ + + ZPOS64_T begin_pos; /* position of the beginning of the zipfile */ + ZPOS64_T add_position_when_writing_offset; + ZPOS64_T number_entry; + +#ifndef NO_ADDFILEINEXISTINGZIP + char *globalcomment; +#endif + +} zip64_internal; + + +#ifndef NOCRYPT +#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED +#include "crypt.h" +#endif + +local linkedlist_datablock_internal* allocate_new_datablock() +{ + linkedlist_datablock_internal* ldi; + ldi = (linkedlist_datablock_internal*) + ALLOC(sizeof(linkedlist_datablock_internal)); + if (ldi!=NULL) + { + ldi->next_datablock = NULL ; + ldi->filled_in_this_block = 0 ; + ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ; + } + return ldi; +} + +local void free_datablock(linkedlist_datablock_internal* ldi) +{ + while (ldi!=NULL) + { + linkedlist_datablock_internal* ldinext = ldi->next_datablock; + TRYFREE(ldi); + ldi = ldinext; + } +} + +local void init_linkedlist(linkedlist_data* ll) +{ + ll->first_block = ll->last_block = NULL; +} + +local void free_linkedlist(linkedlist_data* ll) +{ + free_datablock(ll->first_block); + ll->first_block = ll->last_block = NULL; +} + + +local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) +{ + linkedlist_datablock_internal* ldi; + const unsigned char* from_copy; + + if (ll==NULL) + return ZIP_INTERNALERROR; + + if (ll->last_block == NULL) + { + ll->first_block = ll->last_block = allocate_new_datablock(); + if (ll->first_block == NULL) + return ZIP_INTERNALERROR; + } + + ldi = ll->last_block; + from_copy = (unsigned char*)buf; + + while (len>0) + { + uInt copy_this; + uInt i; + unsigned char* to_copy; + + if (ldi->avail_in_this_block==0) + { + ldi->next_datablock = allocate_new_datablock(); + if (ldi->next_datablock == NULL) + return ZIP_INTERNALERROR; + ldi = ldi->next_datablock ; + ll->last_block = ldi; + } + + if (ldi->avail_in_this_block < len) + copy_this = (uInt)ldi->avail_in_this_block; + else + copy_this = (uInt)len; + + to_copy = &(ldi->data[ldi->filled_in_this_block]); + + for (i=0;ifilled_in_this_block += copy_this; + ldi->avail_in_this_block -= copy_this; + from_copy += copy_this ; + len -= copy_this; + } + return ZIP_OK; +} + + + +/****************************************************************************/ + +#ifndef NO_ADDFILEINEXISTINGZIP +/* =========================================================================== + Inputs a long in LSB order to the given file + nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T) +*/ + +local int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)); +local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) +{ + unsigned char buf[8]; + int n; + for (n = 0; n < nbByte; n++) + { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + if (x != 0) + { /* data overflow - hack for ZIP64 (X Roche) */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } + + if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte) + return ZIP_ERRNO; + else + return ZIP_OK; +} + +local void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte)); +local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) +{ + unsigned char* buf=(unsigned char*)dest; + int n; + for (n = 0; n < nbByte; n++) { + buf[n] = (unsigned char)(x & 0xff); + x >>= 8; + } + + if (x != 0) + { /* data overflow - hack for ZIP64 */ + for (n = 0; n < nbByte; n++) + { + buf[n] = 0xff; + } + } +} + +/****************************************************************************/ + + +local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) +{ + uLong year = (uLong)ptm->tm_year; + if (year>=1980) + year-=1980; + else if (year>=80) + year-=80; + return + (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) | + ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour)); +} + + +/****************************************************************************/ + +local int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)); + +local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi) +{ + unsigned char c; + int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1); + if (err==1) + { + *pi = (int)c; + return ZIP_OK; + } + else + { + if (ZERROR64(*pzlib_filefunc_def,filestream)) + return ZIP_ERRNO; + else + return ZIP_EOF; + } +} + + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets +*/ +local int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); + +local int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) +{ + uLong x ; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX)); + +local int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) +{ + uLong x ; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (uLong)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<8; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<16; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((uLong)i)<<24; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + return err; +} + +local int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)); + + +local int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) +{ + ZPOS64_T x; + int i = 0; + int err; + + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x = (ZPOS64_T)i; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<8; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<16; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<24; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<32; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<40; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<48; + + if (err==ZIP_OK) + err = zip64local_getByte(pzlib_filefunc_def,filestream,&i); + x += ((ZPOS64_T)i)<<56; + + if (err==ZIP_OK) + *pX = x; + else + *pX = 0; + + return err; +} + +#ifndef BUFREADCOMMENT +#define BUFREADCOMMENT (0x400) +#endif +/* + Locate the Central directory of a zipfile (at the end, just before + the global comment) +*/ +local ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); + +local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && + ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) + { + uPosFound = uReadPos+i; + break; + } + + if (uPosFound!=0) + break; + } + TRYFREE(buf); + return uPosFound; +} + +/* +Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before +the global comment) +*/ +local ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)); + +local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) +{ + unsigned char* buf; + ZPOS64_T uSizeFile; + ZPOS64_T uBackRead; + ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */ + ZPOS64_T uPosFound=0; + uLong uL; + ZPOS64_T relativeOffset; + + if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) + return 0; + + uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream); + + if (uMaxBack>uSizeFile) + uMaxBack = uSizeFile; + + buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); + if (buf==NULL) + return 0; + + uBackRead = 4; + while (uBackReaduMaxBack) + uBackRead = uMaxBack; + else + uBackRead+=BUFREADCOMMENT; + uReadPos = uSizeFile-uBackRead ; + + uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? + (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos); + if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) + break; + + if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) + break; + + for (i=(int)uReadSize-3; (i--)>0;) + { + // Signature "0x07064b50" Zip64 end of central directory locater + if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07)) + { + uPosFound = uReadPos+i; + break; + } + } + + if (uPosFound!=0) + break; + } + + TRYFREE(buf); + if (uPosFound == 0) + return 0; + + /* Zip64 end of central directory locator */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature, already checked */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + + /* number of the disk with the start of the zip64 end of central directory */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + if (uL != 0) + return 0; + + /* relative offset of the zip64 end of central directory record */ + if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK) + return 0; + + /* total number of disks */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + if (uL != 1) + return 0; + + /* Goto Zip64 end of central directory record */ + if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0) + return 0; + + /* the signature */ + if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK) + return 0; + + if (uL != 0x06064b50) // signature of 'Zip64 end of central directory' + return 0; + + return relativeOffset; +} + +int LoadCentralDirectoryRecord(zip64_internal* pziinit) +{ + int err=ZIP_OK; + ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ + + ZPOS64_T size_central_dir; /* size of the central directory */ + ZPOS64_T offset_central_dir; /* offset of start of central directory */ + ZPOS64_T central_pos; + uLong uL; + + uLong number_disk; /* number of the current dist, used for + spaning ZIP, unsupported, always 0*/ + uLong number_disk_with_CD; /* number the the disk with central dir, used + for spaning ZIP, unsupported, always 0*/ + ZPOS64_T number_entry; + ZPOS64_T number_entry_CD; /* total number of entries in + the central dir + (same than number_entry on nospan) */ + uLong VersionMadeBy; + uLong VersionNeeded; + uLong size_comment; + + int hasZIP64Record = 0; + + // check first if we find a ZIP64 record + central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream); + if(central_pos > 0) + { + hasZIP64Record = 1; + } + else if(central_pos == 0) + { + central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream); + } + +/* disable to allow appending to empty ZIP archive + if (central_pos==0) + err=ZIP_ERRNO; +*/ + + if(hasZIP64Record) + { + ZPOS64_T sizeEndOfCentralDirectory; + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* size of zip64 end of central directory record */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK) + err=ZIP_ERRNO; + + /* version made by */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK) + err=ZIP_ERRNO; + + /* version needed to extract */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central directory on this disk */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central directory */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + /* offset of start of central directory with respect to the + starting disk number */ + if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK) + err=ZIP_ERRNO; + + // TODO.. + // read the comment from the standard central header. + size_comment = 0; + } + else + { + // Read End of central Directory info + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) + err=ZIP_ERRNO; + + /* the signature, already checked */ + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of this disk */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK) + err=ZIP_ERRNO; + + /* number of the disk with the start of the central directory */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK) + err=ZIP_ERRNO; + + /* total number of entries in the central dir on this disk */ + number_entry = 0; + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + number_entry = uL; + + /* total number of entries in the central dir */ + number_entry_CD = 0; + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + number_entry_CD = uL; + + if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) + err=ZIP_BADZIPFILE; + + /* size of the central directory */ + size_central_dir = 0; + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + size_central_dir = uL; + + /* offset of start of central directory with respect to the starting disk number */ + offset_central_dir = 0; + if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK) + err=ZIP_ERRNO; + else + offset_central_dir = uL; + + + /* zipfile global comment length */ + if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK) + err=ZIP_ERRNO; + } + + if ((central_posz_filefunc, pziinit->filestream); + return ZIP_ERRNO; + } + + if (size_comment>0) + { + pziinit->globalcomment = (char*)ALLOC(size_comment+1); + if (pziinit->globalcomment) + { + size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment); + pziinit->globalcomment[size_comment]=0; + } + } + + byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); + pziinit->add_position_when_writing_offset = byte_before_the_zipfile; + + { + ZPOS64_T size_central_dir_to_read = size_central_dir; + size_t buf_size = SIZEDATA_INDATABLOCK; + void* buf_read = (void*)ALLOC(buf_size); + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + while ((size_central_dir_to_read>0) && (err==ZIP_OK)) + { + ZPOS64_T read_this = SIZEDATA_INDATABLOCK; + if (read_this > size_central_dir_to_read) + read_this = size_central_dir_to_read; + + if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this) + err=ZIP_ERRNO; + + if (err==ZIP_OK) + err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this); + + size_central_dir_to_read-=read_this; + } + TRYFREE(buf_read); + } + pziinit->begin_pos = byte_before_the_zipfile; + pziinit->number_entry = number_entry_CD; + + if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0) + err=ZIP_ERRNO; + + return err; +} + + +#endif /* !NO_ADDFILEINEXISTINGZIP*/ + + +/************************************************************/ +extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) +{ + zip64_internal ziinit; + zip64_internal* zi; + int err=ZIP_OK; + + ziinit.z_filefunc.zseek32_file = NULL; + ziinit.z_filefunc.ztell32_file = NULL; + if (pzlib_filefunc64_32_def==NULL) + fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64); + else + ziinit.z_filefunc = *pzlib_filefunc64_32_def; + + ziinit.filestream = ZOPEN64(ziinit.z_filefunc, + pathname, + (append == APPEND_STATUS_CREATE) ? + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : + (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); + + if (ziinit.filestream == NULL) + return NULL; + + if (append == APPEND_STATUS_CREATEAFTER) + ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END); + + ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream); + ziinit.in_opened_file_inzip = 0; + ziinit.ci.stream_initialised = 0; + ziinit.number_entry = 0; + ziinit.add_position_when_writing_offset = 0; + init_linkedlist(&(ziinit.central_dir)); + + + + zi = (zip64_internal*)ALLOC(sizeof(zip64_internal)); + if (zi==NULL) + { + ZCLOSE64(ziinit.z_filefunc,ziinit.filestream); + return NULL; + } + + /* now we add file in a zipfile */ +# ifndef NO_ADDFILEINEXISTINGZIP + ziinit.globalcomment = NULL; + if (append == APPEND_STATUS_ADDINZIP) + { + // Read and Cache Central Directory Records + err = LoadCentralDirectoryRecord(&ziinit); + } + + if (globalcomment) + { + *globalcomment = ziinit.globalcomment; + } +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + + if (err != ZIP_OK) + { +# ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(ziinit.globalcomment); +# endif /* !NO_ADDFILEINEXISTINGZIP*/ + TRYFREE(zi); + return NULL; + } + else + { + *zi = ziinit; + return (zipFile)zi; + } +} + +extern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) +{ + if (pzlib_filefunc32_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def); + return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); + } + else + return zipOpen3(pathname, append, globalcomment, NULL); +} + +extern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) +{ + if (pzlib_filefunc_def != NULL) + { + zlib_filefunc64_32_def zlib_filefunc64_32_def_fill; + zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def; + zlib_filefunc64_32_def_fill.ztell32_file = NULL; + zlib_filefunc64_32_def_fill.zseek32_file = NULL; + return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill); + } + else + return zipOpen3(pathname, append, globalcomment, NULL); +} + + + +extern zipFile ZEXPORT zipOpen (const char* pathname, int append) +{ + return zipOpen3((const void*)pathname,append,NULL,NULL); +} + +extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append) +{ + return zipOpen3(pathname,append,NULL,NULL); +} + +int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) +{ + /* write the local header */ + int err; + uInt size_filename = (uInt)strlen(filename); + uInt size_extrafield = size_extrafield_local; + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4); + + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */ + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2); + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2); + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4); + + // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */ + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */ + } + if (err==ZIP_OK) + { + if(zi->ci.zip64) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */ + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */ + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2); + + if(zi->ci.zip64) + { + size_extrafield += 20; + } + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2); + + if ((err==ZIP_OK) && (size_filename > 0)) + { + if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename) + err = ZIP_ERRNO; + } + + if ((err==ZIP_OK) && (size_extrafield_local > 0)) + { + if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local) + err = ZIP_ERRNO; + } + + + if ((err==ZIP_OK) && (zi->ci.zip64)) + { + // write the Zip64 extended info + short HeaderID = 1; + short DataSize = 16; + ZPOS64_T CompressedSize = 0; + ZPOS64_T UncompressedSize = 0; + + // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file) + zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream); + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2); + + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8); + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8); + } + + return err; +} + +/* + NOTE. + When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped + before calling this function it can be done with zipRemoveExtraInfoBlock + + It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize + unnecessary allocations. + */ +extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase, int zip64) +{ + zip64_internal* zi; + uInt size_filename; + uInt size_comment; + uInt i; + int err = ZIP_OK; + +# ifdef NOCRYPT + (crcForCrypting); + if (password != NULL) + return ZIP_PARAMERROR; +# endif + + if (file == NULL) + return ZIP_PARAMERROR; + +#ifdef HAVE_BZIP2 + if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED)) + return ZIP_PARAMERROR; +#else + if ((method!=0) && (method!=Z_DEFLATED)) + return ZIP_PARAMERROR; +#endif + + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + if (err != ZIP_OK) + return err; + } + + if (filename==NULL) + filename="-"; + + if (comment==NULL) + size_comment = 0; + else + size_comment = (uInt)strlen(comment); + + size_filename = (uInt)strlen(filename); + + if (zipfi == NULL) + zi->ci.dosDate = 0; + else + { + if (zipfi->dosDate != 0) + zi->ci.dosDate = zipfi->dosDate; + else + zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date); + } + + zi->ci.flag = flagBase; + if ((level==8) || (level==9)) + zi->ci.flag |= 2; + if (level==2) + zi->ci.flag |= 4; + if (level==1) + zi->ci.flag |= 6; + if (password != NULL) + zi->ci.flag |= 1; + + zi->ci.crc32 = 0; + zi->ci.method = method; + zi->ci.encrypt = 0; + zi->ci.stream_initialised = 0; + zi->ci.pos_in_buffered_data = 0; + zi->ci.raw = raw; + zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream); + + zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment; + zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data + + zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree); + + zi->ci.size_centralExtra = size_extrafield_global; + zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4); + /* version info */ + zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2); + zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2); + zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2); + zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2); + zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4); + zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/ + zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/ + zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/ + zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2); + zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2); + zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2); + zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/ + + if (zipfi==NULL) + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); + else + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); + + if (zipfi==NULL) + zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); + else + zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4); + + if(zi->ci.pos_local_header >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4); + else + zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4); + + for (i=0;ici.central_header+SIZECENTRALHEADER+i) = *(filename+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+i) = + *(((const char*)extrafield_global)+i); + + for (i=0;ici.central_header+SIZECENTRALHEADER+size_filename+ + size_extrafield_global+i) = *(comment+i); + if (zi->ci.central_header == NULL) + return ZIP_INTERNALERROR; + + zi->ci.zip64 = zip64; + zi->ci.totalCompressedData = 0; + zi->ci.totalUncompressedData = 0; + zi->ci.pos_zip64extrainfo = 0; + + err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local); + +#ifdef HAVE_BZIP2 + zi->ci.bstream.avail_in = (uInt)0; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; + zi->ci.bstream.total_in_hi32 = 0; + zi->ci.bstream.total_in_lo32 = 0; + zi->ci.bstream.total_out_hi32 = 0; + zi->ci.bstream.total_out_lo32 = 0; +#endif + + zi->ci.stream.avail_in = (uInt)0; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + zi->ci.stream.total_in = 0; + zi->ci.stream.total_out = 0; + zi->ci.stream.data_type = Z_BINARY; + +#ifdef HAVE_BZIP2 + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) +#else + if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) +#endif + { + if(zi->ci.method == Z_DEFLATED) + { + zi->ci.stream.zalloc = (alloc_func)0; + zi->ci.stream.zfree = (free_func)0; + zi->ci.stream.opaque = (voidpf)0; + + if (windowBits>0) + windowBits = -windowBits; + + err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy); + + if (err==Z_OK) + zi->ci.stream_initialised = Z_DEFLATED; + } + else if(zi->ci.method == Z_BZIP2ED) + { +#ifdef HAVE_BZIP2 + // Init BZip stuff here + zi->ci.bstream.bzalloc = 0; + zi->ci.bstream.bzfree = 0; + zi->ci.bstream.opaque = (voidpf)0; + + err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35); + if(err == BZ_OK) + zi->ci.stream_initialised = Z_BZIP2ED; +#endif + } + + } + +# ifndef NOCRYPT + zi->ci.crypt_header_size = 0; + if ((err==Z_OK) && (password != NULL)) + { + unsigned char bufHead[RAND_HEAD_LEN]; + unsigned int sizeHead; + zi->ci.encrypt = 1; + zi->ci.pcrc_32_tab = get_crc_table(); + /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/ + + sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting); + zi->ci.crypt_header_size = sizeHead; + + if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead) + err = ZIP_ERRNO; + } +# endif + + if (err==Z_OK) + zi->in_opened_file_inzip = 1; + return err; +} + +extern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, + uLong versionMadeBy, uLong flagBase) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, versionMadeBy, flagBase, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, + int windowBits,int memLevel, int strategy, + const char* password, uLong crcForCrypting, int zip64) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + windowBits, memLevel, strategy, + password, crcForCrypting, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); +} + +extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void* extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int raw, int zip64) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, raw, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level, int zip64) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, zip64); +} + +extern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi, + const void* extrafield_local, uInt size_extrafield_local, + const void*extrafield_global, uInt size_extrafield_global, + const char* comment, int method, int level) +{ + return zipOpenNewFileInZip4_64 (file, filename, zipfi, + extrafield_local, size_extrafield_local, + extrafield_global, size_extrafield_global, + comment, method, level, 0, + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + NULL, 0, VERSIONMADEBY, 0, 0); +} + +local int zip64FlushWriteBuffer(zip64_internal* zi) +{ + int err=ZIP_OK; + + if (zi->ci.encrypt != 0) + { +#ifndef NOCRYPT + uInt i; + int t; + for (i=0;ici.pos_in_buffered_data;i++) + zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t); +#endif + } + + if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data) + err = ZIP_ERRNO; + + zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data; + +#ifdef HAVE_BZIP2 + if(zi->ci.method == Z_BZIP2ED) + { + zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32; + zi->ci.bstream.total_in_lo32 = 0; + zi->ci.bstream.total_in_hi32 = 0; + } + else +#endif + { + zi->ci.totalUncompressedData += zi->ci.stream.total_in; + zi->ci.stream.total_in = 0; + } + + + zi->ci.pos_in_buffered_data = 0; + + return err; +} + +extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len) +{ + zip64_internal* zi; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + + zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len); + +#ifdef HAVE_BZIP2 + if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw)) + { + zi->ci.bstream.next_in = (void*)buf; + zi->ci.bstream.avail_in = len; + err = BZ_RUN_OK; + + while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0)) + { + if (zi->ci.bstream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; + } + + + if(err != BZ_RUN_OK) + break; + + if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) + { + uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32; +// uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32; + err=BZ2_bzCompress(&zi->ci.bstream, BZ_RUN); + + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ; + } + } + + if(err == BZ_RUN_OK) + err = ZIP_OK; + } + else +#endif + { + zi->ci.stream.next_in = (Bytef*)buf; + zi->ci.stream.avail_in = len; + + while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0)) + { + if (zi->ci.stream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + + + if(err != ZIP_OK) + break; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + uLong uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_NO_FLUSH); + if(uTotalOutBefore > zi->ci.stream.total_out) + { + int bBreak = 0; + bBreak++; + } + + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + else + { + uInt copy_this,i; + if (zi->ci.stream.avail_in < zi->ci.stream.avail_out) + copy_this = zi->ci.stream.avail_in; + else + copy_this = zi->ci.stream.avail_out; + + for (i = 0; i < copy_this; i++) + *(((char*)zi->ci.stream.next_out)+i) = + *(((const char*)zi->ci.stream.next_in)+i); + { + zi->ci.stream.avail_in -= copy_this; + zi->ci.stream.avail_out-= copy_this; + zi->ci.stream.next_in+= copy_this; + zi->ci.stream.next_out+= copy_this; + zi->ci.stream.total_in+= copy_this; + zi->ci.stream.total_out+= copy_this; + zi->ci.pos_in_buffered_data += copy_this; + } + } + }// while(...) + } + + return err; +} + +extern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32) +{ + return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32); +} + +extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32) +{ + zip64_internal* zi; + ZPOS64_T compressed_size; + uLong invalidValue = 0xffffffff; + short datasize = 0; + int err=ZIP_OK; + + if (file == NULL) + return ZIP_PARAMERROR; + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 0) + return ZIP_PARAMERROR; + zi->ci.stream.avail_in = 0; + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + while (err==ZIP_OK) + { + uLong uTotalOutBefore; + if (zi->ci.stream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.stream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.stream.next_out = zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.stream.total_out; + err=deflate(&zi->ci.stream, Z_FINISH); + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ; + } + } + else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) + { +#ifdef HAVE_BZIP2 + err = BZ_FINISH_OK; + while (err==BZ_FINISH_OK) + { + uLong uTotalOutBefore; + if (zi->ci.bstream.avail_out == 0) + { + if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO) + err = ZIP_ERRNO; + zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE; + zi->ci.bstream.next_out = (char*)zi->ci.buffered_data; + } + uTotalOutBefore = zi->ci.bstream.total_out_lo32; + err=BZ2_bzCompress(&zi->ci.bstream, BZ_FINISH); + if(err == BZ_STREAM_END) + err = Z_STREAM_END; + + zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore); + } + + if(err == BZ_FINISH_OK) + err = ZIP_OK; +#endif + } + + if (err==Z_STREAM_END) + err=ZIP_OK; /* this is normal */ + + if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK)) + { + if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO) + err = ZIP_ERRNO; + } + + if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw)) + { + int tmp_err = deflateEnd(&zi->ci.stream); + if (err == ZIP_OK) + err = tmp_err; + zi->ci.stream_initialised = 0; + } +#ifdef HAVE_BZIP2 + else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw)) + { + int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream); + if (err==ZIP_OK) + err = tmperr; + zi->ci.stream_initialised = 0; + } +#endif + + if (!zi->ci.raw) + { + crc32 = (uLong)zi->ci.crc32; + uncompressed_size = zi->ci.totalUncompressedData; + } + compressed_size = zi->ci.totalCompressedData; + +# ifndef NOCRYPT + compressed_size += zi->ci.crypt_header_size; +# endif + + // update Current Item crc and sizes, + if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff) + { + /*version Made by*/ + zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2); + /*version needed*/ + zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2); + + } + + zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/ + + + if(compressed_size >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/ + else + zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/ + + /// set internal file attributes field + if (zi->ci.stream.data_type == Z_ASCII) + zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2); + + if(uncompressed_size >= 0xffffffff) + zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/ + else + zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/ + + // Add ZIP64 extra info field for uncompressed size + if(uncompressed_size >= 0xffffffff) + datasize += 8; + + // Add ZIP64 extra info field for compressed size + if(compressed_size >= 0xffffffff) + datasize += 8; + + // Add ZIP64 extra info field for relative offset to local file header of current file + if(zi->ci.pos_local_header >= 0xffffffff) + datasize += 8; + + if(datasize > 0) + { + char* p = NULL; + + if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree) + { + // we can not write more data to the buffer that we have room for. + return ZIP_BADZIPFILE; + } + + p = zi->ci.central_header + zi->ci.size_centralheader; + + // Add Extra Information Header for 'ZIP64 information' + zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID + p += 2; + zip64local_putValue_inmemory(p, datasize, 2); // DataSize + p += 2; + + if(uncompressed_size >= 0xffffffff) + { + zip64local_putValue_inmemory(p, uncompressed_size, 8); + p += 8; + } + + if(compressed_size >= 0xffffffff) + { + zip64local_putValue_inmemory(p, compressed_size, 8); + p += 8; + } + + if(zi->ci.pos_local_header >= 0xffffffff) + { + zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8); + p += 8; + } + + // Update how much extra free space we got in the memory buffer + // and increase the centralheader size so the new ZIP64 fields are included + // ( 4 below is the size of HeaderID and DataSize field ) + zi->ci.size_centralExtraFree -= datasize + 4; + zi->ci.size_centralheader += datasize + 4; + + // Update the extra info size field + zi->ci.size_centralExtra += datasize + 4; + zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2); + } + + if (err==ZIP_OK) + err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader); + + free(zi->ci.central_header); + + if (err==ZIP_OK) + { + // Update the LocalFileHeader with the new values. + + ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); + + if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */ + + if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff ) + { + if(zi->ci.pos_zip64extrainfo > 0) + { + // Update the size in the ZIP64 extended field. + if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + + if (err==ZIP_OK) /* compressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8); + } + else + err = ZIP_BADZIPFILE; // Caller passed zip64 = 0, so no room for zip64 info -> fatal + } + else + { + if (err==ZIP_OK) /* compressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4); + + if (err==ZIP_OK) /* uncompressed size, unknown */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4); + } + + if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0) + err = ZIP_ERRNO; + } + + zi->number_entry ++; + zi->in_opened_file_inzip = 0; + + return err; +} + +extern int ZEXPORT zipCloseFileInZip (zipFile file) +{ + return zipCloseFileInZipRaw (file,0,0); +} + +int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) +{ + int err = ZIP_OK; + ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset; + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4); + + /*num disks*/ + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + + /*relative offset*/ + if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8); + + /*total disks*/ /* Do not support spawning of disk so always say 1 here*/ + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4); + + return err; +} + +int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) +{ + int err = ZIP_OK; + + uLong Zip64DataSize = 44; + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ? + + if (err==ZIP_OK) /* version made by */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); + + if (err==ZIP_OK) /* version needed */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2); + + if (err==ZIP_OK) /* number of this disk */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); + + if (err==ZIP_OK) /* total number of entries in the central dir */ + err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8); + + if (err==ZIP_OK) /* size of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ + { + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8); + } + return err; +} +int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) +{ + int err = ZIP_OK; + + /*signature*/ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4); + + if (err==ZIP_OK) /* number of this disk */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* number of the disk with the start of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2); + + if (err==ZIP_OK) /* total number of entries in the central dir on this disk */ + { + { + if(zi->number_entry >= 0xFFFF) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + } + } + + if (err==ZIP_OK) /* total number of entries in the central dir */ + { + if(zi->number_entry >= 0xFFFF) + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2); + } + + if (err==ZIP_OK) /* size of the central directory */ + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4); + + if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */ + { + ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; + if(pos >= 0xffffffff) + { + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4); + } + else + err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4); + } + + return err; +} + +int Write_GlobalComment(zip64_internal* zi, const char* global_comment) +{ + int err = ZIP_OK; + uInt size_global_comment = 0; + + if(global_comment != NULL) + size_global_comment = (uInt)strlen(global_comment); + + err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2); + + if (err == ZIP_OK && size_global_comment > 0) + { + if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment) + err = ZIP_ERRNO; + } + return err; +} + +extern int ZEXPORT zipClose (zipFile file, const char* global_comment) +{ + zip64_internal* zi; + int err = 0; + uLong size_centraldir = 0; + ZPOS64_T centraldir_pos_inzip; + ZPOS64_T pos; + + if (file == NULL) + return ZIP_PARAMERROR; + + zi = (zip64_internal*)file; + + if (zi->in_opened_file_inzip == 1) + { + err = zipCloseFileInZip (file); + } + +#ifndef NO_ADDFILEINEXISTINGZIP + if (global_comment==NULL) + global_comment = zi->globalcomment; +#endif + + centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream); + + if (err==ZIP_OK) + { + linkedlist_datablock_internal* ldi = zi->central_dir.first_block; + while (ldi!=NULL) + { + if ((err==ZIP_OK) && (ldi->filled_in_this_block>0)) + { + if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block) + err = ZIP_ERRNO; + } + + size_centraldir += ldi->filled_in_this_block; + ldi = ldi->next_datablock; + } + } + free_linkedlist(&(zi->central_dir)); + + pos = centraldir_pos_inzip - zi->add_position_when_writing_offset; + if(pos >= 0xffffffff || zi->number_entry > 0xFFFF) + { + ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream); + Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); + + Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos); + } + + if (err==ZIP_OK) + err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip); + + if(err == ZIP_OK) + err = Write_GlobalComment(zi, global_comment); + + if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0) + if (err == ZIP_OK) + err = ZIP_ERRNO; + +#ifndef NO_ADDFILEINEXISTINGZIP + TRYFREE(zi->globalcomment); +#endif + TRYFREE(zi); + + return err; +} + +extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader) +{ + char* p = pData; + int size = 0; + char* pNewHeader; + char* pTmp; + short header; + short dataSize; + + int retVal = ZIP_OK; + + if(pData == NULL || *dataLen < 4) + return ZIP_PARAMERROR; + + pNewHeader = (char*)ALLOC(*dataLen); + pTmp = pNewHeader; + + while(p < (pData + *dataLen)) + { + header = *(short*)p; + dataSize = *(((short*)p)+1); + + if( header == sHeader ) // Header found. + { + p += dataSize + 4; // skip it. do not copy to temp buffer + } + else + { + // Extra Info block should not be removed, So copy it to the temp buffer. + memcpy(pTmp, p, dataSize + 4); + p += dataSize + 4; + size += dataSize + 4; + } + + } + + if(size < *dataLen) + { + // clean old extra info block. + memset(pData,0, *dataLen); + + // copy the new extra info block over the old + if(size > 0) + memcpy(pData, pNewHeader, size); + + // set the new extra info size + *dataLen = size; + + retVal = ZIP_OK; + } + else + retVal = ZIP_ERRNO; + + TRYFREE(pNewHeader); + + return retVal; +} diff --git a/zlib-1.2.11/contrib/minizip/zip.h b/zlib-1.2.11/contrib/minizip/zip.h new file mode 100644 index 00000000..8aaebb62 --- /dev/null +++ b/zlib-1.2.11/contrib/minizip/zip.h @@ -0,0 +1,362 @@ +/* zip.h -- IO on .zip files using zlib + Version 1.1, February 14h, 2010 + part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html ) + + Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html ) + + Modifications for Zip64 support + Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com ) + + For more info read MiniZip_info.txt + + --------------------------------------------------------------------------- + + Condition of use and distribution are the same than zlib : + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + --------------------------------------------------------------------------- + + Changes + + See header of zip.h + +*/ + +#ifndef _zip12_H +#define _zip12_H + +#ifdef __cplusplus +extern "C" { +#endif + +//#define HAVE_BZIP2 + +#ifndef _ZLIB_H +#include "zlib.h" +#endif + +#ifndef _ZLIBIOAPI_H +#include "ioapi.h" +#endif + +#ifdef HAVE_BZIP2 +#include "bzlib.h" +#endif + +#define Z_BZIP2ED 12 + +#if defined(STRICTZIP) || defined(STRICTZIPUNZIP) +/* like the STRICT of WIN32, we define a pointer that cannot be converted + from (void*) without cast */ +typedef struct TagzipFile__ { int unused; } zipFile__; +typedef zipFile__ *zipFile; +#else +typedef voidp zipFile; +#endif + +#define ZIP_OK (0) +#define ZIP_EOF (0) +#define ZIP_ERRNO (Z_ERRNO) +#define ZIP_PARAMERROR (-102) +#define ZIP_BADZIPFILE (-103) +#define ZIP_INTERNALERROR (-104) + +#ifndef DEF_MEM_LEVEL +# if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +# else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +# endif +#endif +/* default memLevel */ + +/* tm_zip contain date/time info */ +typedef struct tm_zip_s +{ + uInt tm_sec; /* seconds after the minute - [0,59] */ + uInt tm_min; /* minutes after the hour - [0,59] */ + uInt tm_hour; /* hours since midnight - [0,23] */ + uInt tm_mday; /* day of the month - [1,31] */ + uInt tm_mon; /* months since January - [0,11] */ + uInt tm_year; /* years - [1980..2044] */ +} tm_zip; + +typedef struct +{ + tm_zip tmz_date; /* date in understandable format */ + uLong dosDate; /* if dos_date == 0, tmu_date is used */ +/* uLong flag; */ /* general purpose bit flag 2 bytes */ + + uLong internal_fa; /* internal file attributes 2 bytes */ + uLong external_fa; /* external file attributes 4 bytes */ +} zip_fileinfo; + +typedef const char* zipcharpc; + + +#define APPEND_STATUS_CREATE (0) +#define APPEND_STATUS_CREATEAFTER (1) +#define APPEND_STATUS_ADDINZIP (2) + +extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append)); +extern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append)); +/* + Create a zipfile. + pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on + an Unix computer "zlib/zlib113.zip". + if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip + will be created at the end of the file. + (useful if the file contain a self extractor code) + if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will + add files in existing zip (be sure you don't add file that doesn't exist) + If the zipfile cannot be opened, the return value is NULL. + Else, the return value is a zipFile Handle, usable with other function + of this zip package. +*/ + +/* Note : there is no delete function into a zipfile. + If you want delete file into a zipfile, you must open a zipfile, and create another + Of couse, you can use RAW reading and writing to copy the file you did not want delte +*/ + +extern zipFile ZEXPORT zipOpen2 OF((const char *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc_def* pzlib_filefunc_def)); + +extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname, + int append, + zipcharpc* globalcomment, + zlib_filefunc64_def* pzlib_filefunc_def)); + +extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level)); + +extern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int zip64)); + +/* + Open a file in the ZIP for writing. + filename : the filename in zip (if NULL, '-' without quote will be used + *zipfi contain supplemental information + if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local + contains the extrafield data the the local header + if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global + contains the extrafield data the the local header + if comment != NULL, comment contain the comment string + method contain the compression method (0 for store, Z_DEFLATED for deflate) + level contain the level of compression (can be Z_DEFAULT_COMPRESSION) + zip64 is set to 1 if a zip64 extended information block should be added to the local file header. + this MUST be '1' if the uncompressed size is >= 0xffffffff. + +*/ + + +extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw)); + + +extern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int zip64)); +/* + Same than zipOpenNewFileInZip, except if raw=1, we write raw file + */ + +extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting)); + +extern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + int zip64 + )); + +/* + Same than zipOpenNewFileInZip2, except + windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 + password : crypting password (NULL for no crypting) + crcForCrypting : crc of file to compress (needed for crypting) + */ + +extern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase + )); + + +extern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file, + const char* filename, + const zip_fileinfo* zipfi, + const void* extrafield_local, + uInt size_extrafield_local, + const void* extrafield_global, + uInt size_extrafield_global, + const char* comment, + int method, + int level, + int raw, + int windowBits, + int memLevel, + int strategy, + const char* password, + uLong crcForCrypting, + uLong versionMadeBy, + uLong flagBase, + int zip64 + )); +/* + Same than zipOpenNewFileInZip4, except + versionMadeBy : value for Version made by field + flag : value for flag field (compression level info will be added) + */ + + +extern int ZEXPORT zipWriteInFileInZip OF((zipFile file, + const void* buf, + unsigned len)); +/* + Write data in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZip OF((zipFile file)); +/* + Close the current file in the zipfile +*/ + +extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file, + uLong uncompressed_size, + uLong crc32)); + +extern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file, + ZPOS64_T uncompressed_size, + uLong crc32)); + +/* + Close the current file in the zipfile, for file opened with + parameter raw=1 in zipOpenNewFileInZip2 + uncompressed_size and crc32 are value for the uncompressed size +*/ + +extern int ZEXPORT zipClose OF((zipFile file, + const char* global_comment)); +/* + Close the zipfile +*/ + + +extern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader)); +/* + zipRemoveExtraInfoBlock - Added by Mathias Svensson + + Remove extra information block from a extra information data for the local file header or central directory header + + It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode. + + 0x0001 is the signature header for the ZIP64 extra information blocks + + usage. + Remove ZIP64 Extra information from a central director extra field data + zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001); + + Remove ZIP64 Extra information from a Local File Header extra field data + zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001); +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _zip64_H */ diff --git a/zlib-1.2.11/contrib/pascal/example.pas b/zlib-1.2.11/contrib/pascal/example.pas new file mode 100644 index 00000000..5518b36a --- /dev/null +++ b/zlib-1.2.11/contrib/pascal/example.pas @@ -0,0 +1,599 @@ +(* example.c -- usage example of the zlib compression library + * Copyright (C) 1995-2003 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Pascal translation + * Copyright (C) 1998 by Jacques Nomssi Nzali. + * For conditions of distribution and use, see copyright notice in readme.txt + * + * Adaptation to the zlibpas interface + * Copyright (C) 2003 by Cosmin Truta. + * For conditions of distribution and use, see copyright notice in readme.txt + *) + +program example; + +{$DEFINE TEST_COMPRESS} +{DO NOT $DEFINE TEST_GZIO} +{$DEFINE TEST_DEFLATE} +{$DEFINE TEST_INFLATE} +{$DEFINE TEST_FLUSH} +{$DEFINE TEST_SYNC} +{$DEFINE TEST_DICT} + +uses SysUtils, zlibpas; + +const TESTFILE = 'foo.gz'; + +(* "hello world" would be more standard, but the repeated "hello" + * stresses the compression code better, sorry... + *) +const hello: PChar = 'hello, hello!'; + +const dictionary: PChar = 'hello'; + +var dictId: LongInt; (* Adler32 value of the dictionary *) + +procedure CHECK_ERR(err: Integer; msg: String); +begin + if err <> Z_OK then + begin + WriteLn(msg, ' error: ', err); + Halt(1); + end; +end; + +procedure EXIT_ERR(const msg: String); +begin + WriteLn('Error: ', msg); + Halt(1); +end; + +(* =========================================================================== + * Test compress and uncompress + *) +{$IFDEF TEST_COMPRESS} +procedure test_compress(compr: Pointer; comprLen: LongInt; + uncompr: Pointer; uncomprLen: LongInt); +var err: Integer; + len: LongInt; +begin + len := StrLen(hello)+1; + + err := compress(compr, comprLen, hello, len); + CHECK_ERR(err, 'compress'); + + StrCopy(PChar(uncompr), 'garbage'); + + err := uncompress(uncompr, uncomprLen, compr, comprLen); + CHECK_ERR(err, 'uncompress'); + + if StrComp(PChar(uncompr), hello) <> 0 then + EXIT_ERR('bad uncompress') + else + WriteLn('uncompress(): ', PChar(uncompr)); +end; +{$ENDIF} + +(* =========================================================================== + * Test read/write of .gz files + *) +{$IFDEF TEST_GZIO} +procedure test_gzio(const fname: PChar; (* compressed file name *) + uncompr: Pointer; + uncomprLen: LongInt); +var err: Integer; + len: Integer; + zfile: gzFile; + pos: LongInt; +begin + len := StrLen(hello)+1; + + zfile := gzopen(fname, 'wb'); + if zfile = NIL then + begin + WriteLn('gzopen error'); + Halt(1); + end; + gzputc(zfile, 'h'); + if gzputs(zfile, 'ello') <> 4 then + begin + WriteLn('gzputs err: ', gzerror(zfile, err)); + Halt(1); + end; + {$IFDEF GZ_FORMAT_STRING} + if gzprintf(zfile, ', %s!', 'hello') <> 8 then + begin + WriteLn('gzprintf err: ', gzerror(zfile, err)); + Halt(1); + end; + {$ELSE} + if gzputs(zfile, ', hello!') <> 8 then + begin + WriteLn('gzputs err: ', gzerror(zfile, err)); + Halt(1); + end; + {$ENDIF} + gzseek(zfile, 1, SEEK_CUR); (* add one zero byte *) + gzclose(zfile); + + zfile := gzopen(fname, 'rb'); + if zfile = NIL then + begin + WriteLn('gzopen error'); + Halt(1); + end; + + StrCopy(PChar(uncompr), 'garbage'); + + if gzread(zfile, uncompr, uncomprLen) <> len then + begin + WriteLn('gzread err: ', gzerror(zfile, err)); + Halt(1); + end; + if StrComp(PChar(uncompr), hello) <> 0 then + begin + WriteLn('bad gzread: ', PChar(uncompr)); + Halt(1); + end + else + WriteLn('gzread(): ', PChar(uncompr)); + + pos := gzseek(zfile, -8, SEEK_CUR); + if (pos <> 6) or (gztell(zfile) <> pos) then + begin + WriteLn('gzseek error, pos=', pos, ', gztell=', gztell(zfile)); + Halt(1); + end; + + if gzgetc(zfile) <> ' ' then + begin + WriteLn('gzgetc error'); + Halt(1); + end; + + if gzungetc(' ', zfile) <> ' ' then + begin + WriteLn('gzungetc error'); + Halt(1); + end; + + gzgets(zfile, PChar(uncompr), uncomprLen); + uncomprLen := StrLen(PChar(uncompr)); + if uncomprLen <> 7 then (* " hello!" *) + begin + WriteLn('gzgets err after gzseek: ', gzerror(zfile, err)); + Halt(1); + end; + if StrComp(PChar(uncompr), hello + 6) <> 0 then + begin + WriteLn('bad gzgets after gzseek'); + Halt(1); + end + else + WriteLn('gzgets() after gzseek: ', PChar(uncompr)); + + gzclose(zfile); +end; +{$ENDIF} + +(* =========================================================================== + * Test deflate with small buffers + *) +{$IFDEF TEST_DEFLATE} +procedure test_deflate(compr: Pointer; comprLen: LongInt); +var c_stream: z_stream; (* compression stream *) + err: Integer; + len: LongInt; +begin + len := StrLen(hello)+1; + + c_stream.zalloc := NIL; + c_stream.zfree := NIL; + c_stream.opaque := NIL; + + err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, 'deflateInit'); + + c_stream.next_in := hello; + c_stream.next_out := compr; + + while (c_stream.total_in <> len) and + (c_stream.total_out < comprLen) do + begin + c_stream.avail_out := 1; { force small buffers } + c_stream.avail_in := 1; + err := deflate(c_stream, Z_NO_FLUSH); + CHECK_ERR(err, 'deflate'); + end; + + (* Finish the stream, still forcing small buffers: *) + while TRUE do + begin + c_stream.avail_out := 1; + err := deflate(c_stream, Z_FINISH); + if err = Z_STREAM_END then + break; + CHECK_ERR(err, 'deflate'); + end; + + err := deflateEnd(c_stream); + CHECK_ERR(err, 'deflateEnd'); +end; +{$ENDIF} + +(* =========================================================================== + * Test inflate with small buffers + *) +{$IFDEF TEST_INFLATE} +procedure test_inflate(compr: Pointer; comprLen : LongInt; + uncompr: Pointer; uncomprLen : LongInt); +var err: Integer; + d_stream: z_stream; (* decompression stream *) +begin + StrCopy(PChar(uncompr), 'garbage'); + + d_stream.zalloc := NIL; + d_stream.zfree := NIL; + d_stream.opaque := NIL; + + d_stream.next_in := compr; + d_stream.avail_in := 0; + d_stream.next_out := uncompr; + + err := inflateInit(d_stream); + CHECK_ERR(err, 'inflateInit'); + + while (d_stream.total_out < uncomprLen) and + (d_stream.total_in < comprLen) do + begin + d_stream.avail_out := 1; (* force small buffers *) + d_stream.avail_in := 1; + err := inflate(d_stream, Z_NO_FLUSH); + if err = Z_STREAM_END then + break; + CHECK_ERR(err, 'inflate'); + end; + + err := inflateEnd(d_stream); + CHECK_ERR(err, 'inflateEnd'); + + if StrComp(PChar(uncompr), hello) <> 0 then + EXIT_ERR('bad inflate') + else + WriteLn('inflate(): ', PChar(uncompr)); +end; +{$ENDIF} + +(* =========================================================================== + * Test deflate with large buffers and dynamic change of compression level + *) +{$IFDEF TEST_DEFLATE} +procedure test_large_deflate(compr: Pointer; comprLen: LongInt; + uncompr: Pointer; uncomprLen: LongInt); +var c_stream: z_stream; (* compression stream *) + err: Integer; +begin + c_stream.zalloc := NIL; + c_stream.zfree := NIL; + c_stream.opaque := NIL; + + err := deflateInit(c_stream, Z_BEST_SPEED); + CHECK_ERR(err, 'deflateInit'); + + c_stream.next_out := compr; + c_stream.avail_out := Integer(comprLen); + + (* At this point, uncompr is still mostly zeroes, so it should compress + * very well: + *) + c_stream.next_in := uncompr; + c_stream.avail_in := Integer(uncomprLen); + err := deflate(c_stream, Z_NO_FLUSH); + CHECK_ERR(err, 'deflate'); + if c_stream.avail_in <> 0 then + EXIT_ERR('deflate not greedy'); + + (* Feed in already compressed data and switch to no compression: *) + deflateParams(c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); + c_stream.next_in := compr; + c_stream.avail_in := Integer(comprLen div 2); + err := deflate(c_stream, Z_NO_FLUSH); + CHECK_ERR(err, 'deflate'); + + (* Switch back to compressing mode: *) + deflateParams(c_stream, Z_BEST_COMPRESSION, Z_FILTERED); + c_stream.next_in := uncompr; + c_stream.avail_in := Integer(uncomprLen); + err := deflate(c_stream, Z_NO_FLUSH); + CHECK_ERR(err, 'deflate'); + + err := deflate(c_stream, Z_FINISH); + if err <> Z_STREAM_END then + EXIT_ERR('deflate should report Z_STREAM_END'); + + err := deflateEnd(c_stream); + CHECK_ERR(err, 'deflateEnd'); +end; +{$ENDIF} + +(* =========================================================================== + * Test inflate with large buffers + *) +{$IFDEF TEST_INFLATE} +procedure test_large_inflate(compr: Pointer; comprLen: LongInt; + uncompr: Pointer; uncomprLen: LongInt); +var err: Integer; + d_stream: z_stream; (* decompression stream *) +begin + StrCopy(PChar(uncompr), 'garbage'); + + d_stream.zalloc := NIL; + d_stream.zfree := NIL; + d_stream.opaque := NIL; + + d_stream.next_in := compr; + d_stream.avail_in := Integer(comprLen); + + err := inflateInit(d_stream); + CHECK_ERR(err, 'inflateInit'); + + while TRUE do + begin + d_stream.next_out := uncompr; (* discard the output *) + d_stream.avail_out := Integer(uncomprLen); + err := inflate(d_stream, Z_NO_FLUSH); + if err = Z_STREAM_END then + break; + CHECK_ERR(err, 'large inflate'); + end; + + err := inflateEnd(d_stream); + CHECK_ERR(err, 'inflateEnd'); + + if d_stream.total_out <> 2 * uncomprLen + comprLen div 2 then + begin + WriteLn('bad large inflate: ', d_stream.total_out); + Halt(1); + end + else + WriteLn('large_inflate(): OK'); +end; +{$ENDIF} + +(* =========================================================================== + * Test deflate with full flush + *) +{$IFDEF TEST_FLUSH} +procedure test_flush(compr: Pointer; var comprLen : LongInt); +var c_stream: z_stream; (* compression stream *) + err: Integer; + len: Integer; +begin + len := StrLen(hello)+1; + + c_stream.zalloc := NIL; + c_stream.zfree := NIL; + c_stream.opaque := NIL; + + err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, 'deflateInit'); + + c_stream.next_in := hello; + c_stream.next_out := compr; + c_stream.avail_in := 3; + c_stream.avail_out := Integer(comprLen); + err := deflate(c_stream, Z_FULL_FLUSH); + CHECK_ERR(err, 'deflate'); + + Inc(PByteArray(compr)^[3]); (* force an error in first compressed block *) + c_stream.avail_in := len - 3; + + err := deflate(c_stream, Z_FINISH); + if err <> Z_STREAM_END then + CHECK_ERR(err, 'deflate'); + + err := deflateEnd(c_stream); + CHECK_ERR(err, 'deflateEnd'); + + comprLen := c_stream.total_out; +end; +{$ENDIF} + +(* =========================================================================== + * Test inflateSync() + *) +{$IFDEF TEST_SYNC} +procedure test_sync(compr: Pointer; comprLen: LongInt; + uncompr: Pointer; uncomprLen : LongInt); +var err: Integer; + d_stream: z_stream; (* decompression stream *) +begin + StrCopy(PChar(uncompr), 'garbage'); + + d_stream.zalloc := NIL; + d_stream.zfree := NIL; + d_stream.opaque := NIL; + + d_stream.next_in := compr; + d_stream.avail_in := 2; (* just read the zlib header *) + + err := inflateInit(d_stream); + CHECK_ERR(err, 'inflateInit'); + + d_stream.next_out := uncompr; + d_stream.avail_out := Integer(uncomprLen); + + inflate(d_stream, Z_NO_FLUSH); + CHECK_ERR(err, 'inflate'); + + d_stream.avail_in := Integer(comprLen-2); (* read all compressed data *) + err := inflateSync(d_stream); (* but skip the damaged part *) + CHECK_ERR(err, 'inflateSync'); + + err := inflate(d_stream, Z_FINISH); + if err <> Z_DATA_ERROR then + EXIT_ERR('inflate should report DATA_ERROR'); + (* Because of incorrect adler32 *) + + err := inflateEnd(d_stream); + CHECK_ERR(err, 'inflateEnd'); + + WriteLn('after inflateSync(): hel', PChar(uncompr)); +end; +{$ENDIF} + +(* =========================================================================== + * Test deflate with preset dictionary + *) +{$IFDEF TEST_DICT} +procedure test_dict_deflate(compr: Pointer; comprLen: LongInt); +var c_stream: z_stream; (* compression stream *) + err: Integer; +begin + c_stream.zalloc := NIL; + c_stream.zfree := NIL; + c_stream.opaque := NIL; + + err := deflateInit(c_stream, Z_BEST_COMPRESSION); + CHECK_ERR(err, 'deflateInit'); + + err := deflateSetDictionary(c_stream, dictionary, StrLen(dictionary)); + CHECK_ERR(err, 'deflateSetDictionary'); + + dictId := c_stream.adler; + c_stream.next_out := compr; + c_stream.avail_out := Integer(comprLen); + + c_stream.next_in := hello; + c_stream.avail_in := StrLen(hello)+1; + + err := deflate(c_stream, Z_FINISH); + if err <> Z_STREAM_END then + EXIT_ERR('deflate should report Z_STREAM_END'); + + err := deflateEnd(c_stream); + CHECK_ERR(err, 'deflateEnd'); +end; +{$ENDIF} + +(* =========================================================================== + * Test inflate with a preset dictionary + *) +{$IFDEF TEST_DICT} +procedure test_dict_inflate(compr: Pointer; comprLen: LongInt; + uncompr: Pointer; uncomprLen: LongInt); +var err: Integer; + d_stream: z_stream; (* decompression stream *) +begin + StrCopy(PChar(uncompr), 'garbage'); + + d_stream.zalloc := NIL; + d_stream.zfree := NIL; + d_stream.opaque := NIL; + + d_stream.next_in := compr; + d_stream.avail_in := Integer(comprLen); + + err := inflateInit(d_stream); + CHECK_ERR(err, 'inflateInit'); + + d_stream.next_out := uncompr; + d_stream.avail_out := Integer(uncomprLen); + + while TRUE do + begin + err := inflate(d_stream, Z_NO_FLUSH); + if err = Z_STREAM_END then + break; + if err = Z_NEED_DICT then + begin + if d_stream.adler <> dictId then + EXIT_ERR('unexpected dictionary'); + err := inflateSetDictionary(d_stream, dictionary, StrLen(dictionary)); + end; + CHECK_ERR(err, 'inflate with dict'); + end; + + err := inflateEnd(d_stream); + CHECK_ERR(err, 'inflateEnd'); + + if StrComp(PChar(uncompr), hello) <> 0 then + EXIT_ERR('bad inflate with dict') + else + WriteLn('inflate with dictionary: ', PChar(uncompr)); +end; +{$ENDIF} + +var compr, uncompr: Pointer; + comprLen, uncomprLen: LongInt; + +begin + if zlibVersion^ <> ZLIB_VERSION[1] then + EXIT_ERR('Incompatible zlib version'); + + WriteLn('zlib version: ', zlibVersion); + WriteLn('zlib compile flags: ', Format('0x%x', [zlibCompileFlags])); + + comprLen := 10000 * SizeOf(Integer); (* don't overflow on MSDOS *) + uncomprLen := comprLen; + GetMem(compr, comprLen); + GetMem(uncompr, uncomprLen); + if (compr = NIL) or (uncompr = NIL) then + EXIT_ERR('Out of memory'); + (* compr and uncompr are cleared to avoid reading uninitialized + * data and to ensure that uncompr compresses well. + *) + FillChar(compr^, comprLen, 0); + FillChar(uncompr^, uncomprLen, 0); + + {$IFDEF TEST_COMPRESS} + WriteLn('** Testing compress'); + test_compress(compr, comprLen, uncompr, uncomprLen); + {$ENDIF} + + {$IFDEF TEST_GZIO} + WriteLn('** Testing gzio'); + if ParamCount >= 1 then + test_gzio(ParamStr(1), uncompr, uncomprLen) + else + test_gzio(TESTFILE, uncompr, uncomprLen); + {$ENDIF} + + {$IFDEF TEST_DEFLATE} + WriteLn('** Testing deflate with small buffers'); + test_deflate(compr, comprLen); + {$ENDIF} + {$IFDEF TEST_INFLATE} + WriteLn('** Testing inflate with small buffers'); + test_inflate(compr, comprLen, uncompr, uncomprLen); + {$ENDIF} + + {$IFDEF TEST_DEFLATE} + WriteLn('** Testing deflate with large buffers'); + test_large_deflate(compr, comprLen, uncompr, uncomprLen); + {$ENDIF} + {$IFDEF TEST_INFLATE} + WriteLn('** Testing inflate with large buffers'); + test_large_inflate(compr, comprLen, uncompr, uncomprLen); + {$ENDIF} + + {$IFDEF TEST_FLUSH} + WriteLn('** Testing deflate with full flush'); + test_flush(compr, comprLen); + {$ENDIF} + {$IFDEF TEST_SYNC} + WriteLn('** Testing inflateSync'); + test_sync(compr, comprLen, uncompr, uncomprLen); + {$ENDIF} + comprLen := uncomprLen; + + {$IFDEF TEST_DICT} + WriteLn('** Testing deflate and inflate with preset dictionary'); + test_dict_deflate(compr, comprLen); + test_dict_inflate(compr, comprLen, uncompr, uncomprLen); + {$ENDIF} + + FreeMem(compr, comprLen); + FreeMem(uncompr, uncomprLen); +end. diff --git a/zlib-1.2.11/contrib/pascal/readme.txt b/zlib-1.2.11/contrib/pascal/readme.txt new file mode 100644 index 00000000..60e87c8a --- /dev/null +++ b/zlib-1.2.11/contrib/pascal/readme.txt @@ -0,0 +1,76 @@ + +This directory contains a Pascal (Delphi, Kylix) interface to the +zlib data compression library. + + +Directory listing +================= + +zlibd32.mak makefile for Borland C++ +example.pas usage example of zlib +zlibpas.pas the Pascal interface to zlib +readme.txt this file + + +Compatibility notes +=================== + +- Although the name "zlib" would have been more normal for the + zlibpas unit, this name is already taken by Borland's ZLib unit. + This is somehow unfortunate, because that unit is not a genuine + interface to the full-fledged zlib functionality, but a suite of + class wrappers around zlib streams. Other essential features, + such as checksums, are missing. + It would have been more appropriate for that unit to have a name + like "ZStreams", or something similar. + +- The C and zlib-supplied types int, uInt, long, uLong, etc. are + translated directly into Pascal types of similar sizes (Integer, + LongInt, etc.), to avoid namespace pollution. In particular, + there is no conversion of unsigned int into a Pascal unsigned + integer. The Word type is non-portable and has the same size + (16 bits) both in a 16-bit and in a 32-bit environment, unlike + Integer. Even if there is a 32-bit Cardinal type, there is no + real need for unsigned int in zlib under a 32-bit environment. + +- Except for the callbacks, the zlib function interfaces are + assuming the calling convention normally used in Pascal + (__pascal for DOS and Windows16, __fastcall for Windows32). + Since the cdecl keyword is used, the old Turbo Pascal does + not work with this interface. + +- The gz* function interfaces are not translated, to avoid + interfacing problems with the C runtime library. Besides, + gzprintf(gzFile file, const char *format, ...) + cannot be translated into Pascal. + + +Legal issues +============ + +The zlibpas interface is: + Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler. + Copyright (C) 1998 by Bob Dellaca. + Copyright (C) 2003 by Cosmin Truta. + +The example program is: + Copyright (C) 1995-2003 by Jean-loup Gailly. + Copyright (C) 1998,1999,2000 by Jacques Nomssi Nzali. + Copyright (C) 2003 by Cosmin Truta. + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + diff --git a/zlib-1.2.11/contrib/pascal/zlibd32.mak b/zlib-1.2.11/contrib/pascal/zlibd32.mak new file mode 100644 index 00000000..9bb00b7c --- /dev/null +++ b/zlib-1.2.11/contrib/pascal/zlibd32.mak @@ -0,0 +1,99 @@ +# Makefile for zlib +# For use with Delphi and C++ Builder under Win32 +# Updated for zlib 1.2.x by Cosmin Truta + +# ------------ Borland C++ ------------ + +# This project uses the Delphi (fastcall/register) calling convention: +LOC = -DZEXPORT=__fastcall -DZEXPORTVA=__cdecl + +CC = bcc32 +LD = bcc32 +AR = tlib +# do not use "-pr" in CFLAGS +CFLAGS = -a -d -k- -O2 $(LOC) +LDFLAGS = + + +# variables +ZLIB_LIB = zlib.lib + +OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj +OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj +OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj +OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj + + +# targets +all: $(ZLIB_LIB) example.exe minigzip.exe + +.c.obj: + $(CC) -c $(CFLAGS) $*.c + +adler32.obj: adler32.c zlib.h zconf.h + +compress.obj: compress.c zlib.h zconf.h + +crc32.obj: crc32.c zlib.h zconf.h crc32.h + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + +gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h + +gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h + +gzread.obj: gzread.c zlib.h zconf.h gzguts.h + +gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h + +infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h + +inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + +trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h + +uncompr.obj: uncompr.c zlib.h zconf.h + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + +example.obj: test/example.c zlib.h zconf.h + +minigzip.obj: test/minigzip.c zlib.h zconf.h + + +# For the sake of the old Borland make, +# the command line is cut to fit in the MS-DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + -del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) $(OBJP1) + $(AR) $(ZLIB_LIB) $(OBJP2) + + +# testing +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) + + +# cleanup +clean: + -del *.obj + -del *.exe + -del *.lib + -del *.tds + -del zlib.bak + -del foo.gz + diff --git a/zlib-1.2.11/contrib/pascal/zlibpas.pas b/zlib-1.2.11/contrib/pascal/zlibpas.pas new file mode 100644 index 00000000..a0dff11b --- /dev/null +++ b/zlib-1.2.11/contrib/pascal/zlibpas.pas @@ -0,0 +1,276 @@ +(* zlibpas -- Pascal interface to the zlib data compression library + * + * Copyright (C) 2003 Cosmin Truta. + * Derived from original sources by Bob Dellaca. + * For conditions of distribution and use, see copyright notice in readme.txt + *) + +unit zlibpas; + +interface + +const + ZLIB_VERSION = '1.2.11'; + ZLIB_VERNUM = $12a0; + +type + alloc_func = function(opaque: Pointer; items, size: Integer): Pointer; + cdecl; + free_func = procedure(opaque, address: Pointer); + cdecl; + + in_func = function(opaque: Pointer; var buf: PByte): Integer; + cdecl; + out_func = function(opaque: Pointer; buf: PByte; size: Integer): Integer; + cdecl; + + z_streamp = ^z_stream; + z_stream = packed record + next_in: PChar; (* next input byte *) + avail_in: Integer; (* number of bytes available at next_in *) + total_in: LongInt; (* total nb of input bytes read so far *) + + next_out: PChar; (* next output byte should be put there *) + avail_out: Integer; (* remaining free space at next_out *) + total_out: LongInt; (* total nb of bytes output so far *) + + msg: PChar; (* last error message, NULL if no error *) + state: Pointer; (* not visible by applications *) + + zalloc: alloc_func; (* used to allocate the internal state *) + zfree: free_func; (* used to free the internal state *) + opaque: Pointer; (* private data object passed to zalloc and zfree *) + + data_type: Integer; (* best guess about the data type: ascii or binary *) + adler: LongInt; (* adler32 value of the uncompressed data *) + reserved: LongInt; (* reserved for future use *) + end; + + gz_headerp = ^gz_header; + gz_header = packed record + text: Integer; (* true if compressed data believed to be text *) + time: LongInt; (* modification time *) + xflags: Integer; (* extra flags (not used when writing a gzip file) *) + os: Integer; (* operating system *) + extra: PChar; (* pointer to extra field or Z_NULL if none *) + extra_len: Integer; (* extra field length (valid if extra != Z_NULL) *) + extra_max: Integer; (* space at extra (only when reading header) *) + name: PChar; (* pointer to zero-terminated file name or Z_NULL *) + name_max: Integer; (* space at name (only when reading header) *) + comment: PChar; (* pointer to zero-terminated comment or Z_NULL *) + comm_max: Integer; (* space at comment (only when reading header) *) + hcrc: Integer; (* true if there was or will be a header crc *) + done: Integer; (* true when done reading gzip header *) + end; + +(* constants *) +const + Z_NO_FLUSH = 0; + Z_PARTIAL_FLUSH = 1; + Z_SYNC_FLUSH = 2; + Z_FULL_FLUSH = 3; + Z_FINISH = 4; + Z_BLOCK = 5; + Z_TREES = 6; + + Z_OK = 0; + Z_STREAM_END = 1; + Z_NEED_DICT = 2; + Z_ERRNO = -1; + Z_STREAM_ERROR = -2; + Z_DATA_ERROR = -3; + Z_MEM_ERROR = -4; + Z_BUF_ERROR = -5; + Z_VERSION_ERROR = -6; + + Z_NO_COMPRESSION = 0; + Z_BEST_SPEED = 1; + Z_BEST_COMPRESSION = 9; + Z_DEFAULT_COMPRESSION = -1; + + Z_FILTERED = 1; + Z_HUFFMAN_ONLY = 2; + Z_RLE = 3; + Z_FIXED = 4; + Z_DEFAULT_STRATEGY = 0; + + Z_BINARY = 0; + Z_TEXT = 1; + Z_ASCII = 1; + Z_UNKNOWN = 2; + + Z_DEFLATED = 8; + +(* basic functions *) +function zlibVersion: PChar; +function deflateInit(var strm: z_stream; level: Integer): Integer; +function deflate(var strm: z_stream; flush: Integer): Integer; +function deflateEnd(var strm: z_stream): Integer; +function inflateInit(var strm: z_stream): Integer; +function inflate(var strm: z_stream; flush: Integer): Integer; +function inflateEnd(var strm: z_stream): Integer; + +(* advanced functions *) +function deflateInit2(var strm: z_stream; level, method, windowBits, + memLevel, strategy: Integer): Integer; +function deflateSetDictionary(var strm: z_stream; const dictionary: PChar; + dictLength: Integer): Integer; +function deflateCopy(var dest, source: z_stream): Integer; +function deflateReset(var strm: z_stream): Integer; +function deflateParams(var strm: z_stream; level, strategy: Integer): Integer; +function deflateTune(var strm: z_stream; good_length, max_lazy, nice_length, max_chain: Integer): Integer; +function deflateBound(var strm: z_stream; sourceLen: LongInt): LongInt; +function deflatePending(var strm: z_stream; var pending: Integer; var bits: Integer): Integer; +function deflatePrime(var strm: z_stream; bits, value: Integer): Integer; +function deflateSetHeader(var strm: z_stream; head: gz_header): Integer; +function inflateInit2(var strm: z_stream; windowBits: Integer): Integer; +function inflateSetDictionary(var strm: z_stream; const dictionary: PChar; + dictLength: Integer): Integer; +function inflateSync(var strm: z_stream): Integer; +function inflateCopy(var dest, source: z_stream): Integer; +function inflateReset(var strm: z_stream): Integer; +function inflateReset2(var strm: z_stream; windowBits: Integer): Integer; +function inflatePrime(var strm: z_stream; bits, value: Integer): Integer; +function inflateMark(var strm: z_stream): LongInt; +function inflateGetHeader(var strm: z_stream; var head: gz_header): Integer; +function inflateBackInit(var strm: z_stream; + windowBits: Integer; window: PChar): Integer; +function inflateBack(var strm: z_stream; in_fn: in_func; in_desc: Pointer; + out_fn: out_func; out_desc: Pointer): Integer; +function inflateBackEnd(var strm: z_stream): Integer; +function zlibCompileFlags: LongInt; + +(* utility functions *) +function compress(dest: PChar; var destLen: LongInt; + const source: PChar; sourceLen: LongInt): Integer; +function compress2(dest: PChar; var destLen: LongInt; + const source: PChar; sourceLen: LongInt; + level: Integer): Integer; +function compressBound(sourceLen: LongInt): LongInt; +function uncompress(dest: PChar; var destLen: LongInt; + const source: PChar; sourceLen: LongInt): Integer; + +(* checksum functions *) +function adler32(adler: LongInt; const buf: PChar; len: Integer): LongInt; +function adler32_combine(adler1, adler2, len2: LongInt): LongInt; +function crc32(crc: LongInt; const buf: PChar; len: Integer): LongInt; +function crc32_combine(crc1, crc2, len2: LongInt): LongInt; + +(* various hacks, don't look :) *) +function deflateInit_(var strm: z_stream; level: Integer; + const version: PChar; stream_size: Integer): Integer; +function inflateInit_(var strm: z_stream; const version: PChar; + stream_size: Integer): Integer; +function deflateInit2_(var strm: z_stream; + level, method, windowBits, memLevel, strategy: Integer; + const version: PChar; stream_size: Integer): Integer; +function inflateInit2_(var strm: z_stream; windowBits: Integer; + const version: PChar; stream_size: Integer): Integer; +function inflateBackInit_(var strm: z_stream; + windowBits: Integer; window: PChar; + const version: PChar; stream_size: Integer): Integer; + + +implementation + +{$L adler32.obj} +{$L compress.obj} +{$L crc32.obj} +{$L deflate.obj} +{$L infback.obj} +{$L inffast.obj} +{$L inflate.obj} +{$L inftrees.obj} +{$L trees.obj} +{$L uncompr.obj} +{$L zutil.obj} + +function adler32; external; +function adler32_combine; external; +function compress; external; +function compress2; external; +function compressBound; external; +function crc32; external; +function crc32_combine; external; +function deflate; external; +function deflateBound; external; +function deflateCopy; external; +function deflateEnd; external; +function deflateInit_; external; +function deflateInit2_; external; +function deflateParams; external; +function deflatePending; external; +function deflatePrime; external; +function deflateReset; external; +function deflateSetDictionary; external; +function deflateSetHeader; external; +function deflateTune; external; +function inflate; external; +function inflateBack; external; +function inflateBackEnd; external; +function inflateBackInit_; external; +function inflateCopy; external; +function inflateEnd; external; +function inflateGetHeader; external; +function inflateInit_; external; +function inflateInit2_; external; +function inflateMark; external; +function inflatePrime; external; +function inflateReset; external; +function inflateReset2; external; +function inflateSetDictionary; external; +function inflateSync; external; +function uncompress; external; +function zlibCompileFlags; external; +function zlibVersion; external; + +function deflateInit(var strm: z_stream; level: Integer): Integer; +begin + Result := deflateInit_(strm, level, ZLIB_VERSION, sizeof(z_stream)); +end; + +function deflateInit2(var strm: z_stream; level, method, windowBits, memLevel, + strategy: Integer): Integer; +begin + Result := deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + ZLIB_VERSION, sizeof(z_stream)); +end; + +function inflateInit(var strm: z_stream): Integer; +begin + Result := inflateInit_(strm, ZLIB_VERSION, sizeof(z_stream)); +end; + +function inflateInit2(var strm: z_stream; windowBits: Integer): Integer; +begin + Result := inflateInit2_(strm, windowBits, ZLIB_VERSION, sizeof(z_stream)); +end; + +function inflateBackInit(var strm: z_stream; + windowBits: Integer; window: PChar): Integer; +begin + Result := inflateBackInit_(strm, windowBits, window, + ZLIB_VERSION, sizeof(z_stream)); +end; + +function _malloc(Size: Integer): Pointer; cdecl; +begin + GetMem(Result, Size); +end; + +procedure _free(Block: Pointer); cdecl; +begin + FreeMem(Block); +end; + +procedure _memset(P: Pointer; B: Byte; count: Integer); cdecl; +begin + FillChar(P^, count, B); +end; + +procedure _memcpy(dest, source: Pointer; count: Integer); cdecl; +begin + Move(source^, dest^, count); +end; + +end. diff --git a/zlib-1.2.11/contrib/puff/Makefile b/zlib-1.2.11/contrib/puff/Makefile new file mode 100644 index 00000000..0e2594c8 --- /dev/null +++ b/zlib-1.2.11/contrib/puff/Makefile @@ -0,0 +1,42 @@ +CFLAGS=-O + +puff: puff.o pufftest.o + +puff.o: puff.h + +pufftest.o: puff.h + +test: puff + puff zeros.raw + +puft: puff.c puff.h pufftest.o + cc -fprofile-arcs -ftest-coverage -o puft puff.c pufftest.o + +# puff full coverage test (should say 100%) +cov: puft + @rm -f *.gcov *.gcda + @puft -w zeros.raw 2>&1 | cat > /dev/null + @echo '04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 + @echo '00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 + @echo '00 00 00 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 254 + @echo '00 01 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 + @echo '01 01 00 fe ff 0a' | xxd -r -p | puft -f 2>&1 | cat > /dev/null + @echo '02 7e ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 + @echo '02' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 + @echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 2 + @echo '04 80 49 92 24 49 92 24 71 ff ff 93 11 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 249 + @echo '04 c0 81 08 00 00 00 00 20 7f eb 0b 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 + @echo '0b 00 00' | xxd -r -p | puft -f 2>&1 | cat > /dev/null + @echo '1a 07' | xxd -r -p | puft 2> /dev/null || test $$? -eq 246 + @echo '0c c0 81 00 00 00 00 00 90 ff 6b 04' | xxd -r -p | puft 2> /dev/null || test $$? -eq 245 + @puft -f zeros.raw 2>&1 | cat > /dev/null + @echo 'fc 00 00' | xxd -r -p | puft 2> /dev/null || test $$? -eq 253 + @echo '04 00 fe ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 252 + @echo '04 00 24 49' | xxd -r -p | puft 2> /dev/null || test $$? -eq 251 + @echo '04 80 49 92 24 49 92 24 0f b4 ff ff c3 84' | xxd -r -p | puft 2> /dev/null || test $$? -eq 248 + @echo '04 00 24 e9 ff ff' | xxd -r -p | puft 2> /dev/null || test $$? -eq 250 + @echo '04 00 24 e9 ff 6d' | xxd -r -p | puft 2> /dev/null || test $$? -eq 247 + @gcov -n puff.c + +clean: + rm -f puff puft *.o *.gc* diff --git a/zlib-1.2.11/contrib/puff/README b/zlib-1.2.11/contrib/puff/README new file mode 100644 index 00000000..bbc4cb59 --- /dev/null +++ b/zlib-1.2.11/contrib/puff/README @@ -0,0 +1,63 @@ +Puff -- A Simple Inflate +3 Mar 2003 +Mark Adler +madler@alumni.caltech.edu + +What this is -- + +puff.c provides the routine puff() to decompress the deflate data format. It +does so more slowly than zlib, but the code is about one-fifth the size of the +inflate code in zlib, and written to be very easy to read. + +Why I wrote this -- + +puff.c was written to document the deflate format unambiguously, by virtue of +being working C code. It is meant to supplement RFC 1951, which formally +describes the deflate format. I have received many questions on details of the +deflate format, and I hope that reading this code will answer those questions. +puff.c is heavily commented with details of the deflate format, especially +those little nooks and cranies of the format that might not be obvious from a +specification. + +puff.c may also be useful in applications where code size or memory usage is a +very limited resource, and speed is not as important. + +How to use it -- + +Well, most likely you should just be reading puff.c and using zlib for actual +applications, but if you must ... + +Include puff.h in your code, which provides this prototype: + +int puff(unsigned char *dest, /* pointer to destination pointer */ + unsigned long *destlen, /* amount of output space */ + unsigned char *source, /* pointer to source data pointer */ + unsigned long *sourcelen); /* amount of input available */ + +Then you can call puff() to decompress a deflate stream that is in memory in +its entirety at source, to a sufficiently sized block of memory for the +decompressed data at dest. puff() is the only external symbol in puff.c The +only C library functions that puff.c needs are setjmp() and longjmp(), which +are used to simplify error checking in the code to improve readabilty. puff.c +does no memory allocation, and uses less than 2K bytes off of the stack. + +If destlen is not enough space for the uncompressed data, then inflate will +return an error without writing more than destlen bytes. Note that this means +that in order to decompress the deflate data successfully, you need to know +the size of the uncompressed data ahead of time. + +If needed, puff() can determine the size of the uncompressed data with no +output space. This is done by passing dest equal to (unsigned char *)0. Then +the initial value of *destlen is ignored and *destlen is set to the length of +the uncompressed data. So if the size of the uncompressed data is not known, +then two passes of puff() can be used--first to determine the size, and second +to do the actual inflation after allocating the appropriate memory. Not +pretty, but it works. (This is one of the reasons you should be using zlib.) + +The deflate format is self-terminating. If the deflate stream does not end +in *sourcelen bytes, puff() will return an error without reading at or past +endsource. + +On return, *sourcelen is updated to the amount of input data consumed, and +*destlen is updated to the size of the uncompressed data. See the comments +in puff.c for the possible return codes for puff(). diff --git a/zlib-1.2.11/contrib/puff/puff.c b/zlib-1.2.11/contrib/puff/puff.c new file mode 100644 index 00000000..c6c90d71 --- /dev/null +++ b/zlib-1.2.11/contrib/puff/puff.c @@ -0,0 +1,840 @@ +/* + * puff.c + * Copyright (C) 2002-2013 Mark Adler + * For conditions of distribution and use, see copyright notice in puff.h + * version 2.3, 21 Jan 2013 + * + * puff.c is a simple inflate written to be an unambiguous way to specify the + * deflate format. It is not written for speed but rather simplicity. As a + * side benefit, this code might actually be useful when small code is more + * important than speed, such as bootstrap applications. For typical deflate + * data, zlib's inflate() is about four times as fast as puff(). zlib's + * inflate compiles to around 20K on my machine, whereas puff.c compiles to + * around 4K on my machine (a PowerPC using GNU cc). If the faster decode() + * function here is used, then puff() is only twice as slow as zlib's + * inflate(). + * + * All dynamically allocated memory comes from the stack. The stack required + * is less than 2K bytes. This code is compatible with 16-bit int's and + * assumes that long's are at least 32 bits. puff.c uses the short data type, + * assumed to be 16 bits, for arrays in order to conserve memory. The code + * works whether integers are stored big endian or little endian. + * + * In the comments below are "Format notes" that describe the inflate process + * and document some of the less obvious aspects of the format. This source + * code is meant to supplement RFC 1951, which formally describes the deflate + * format: + * + * http://www.zlib.org/rfc-deflate.html + */ + +/* + * Change history: + * + * 1.0 10 Feb 2002 - First version + * 1.1 17 Feb 2002 - Clarifications of some comments and notes + * - Update puff() dest and source pointers on negative + * errors to facilitate debugging deflators + * - Remove longest from struct huffman -- not needed + * - Simplify offs[] index in construct() + * - Add input size and checking, using longjmp() to + * maintain easy readability + * - Use short data type for large arrays + * - Use pointers instead of long to specify source and + * destination sizes to avoid arbitrary 4 GB limits + * 1.2 17 Mar 2002 - Add faster version of decode(), doubles speed (!), + * but leave simple version for readabilty + * - Make sure invalid distances detected if pointers + * are 16 bits + * - Fix fixed codes table error + * - Provide a scanning mode for determining size of + * uncompressed data + * 1.3 20 Mar 2002 - Go back to lengths for puff() parameters [Gailly] + * - Add a puff.h file for the interface + * - Add braces in puff() for else do [Gailly] + * - Use indexes instead of pointers for readability + * 1.4 31 Mar 2002 - Simplify construct() code set check + * - Fix some comments + * - Add FIXLCODES #define + * 1.5 6 Apr 2002 - Minor comment fixes + * 1.6 7 Aug 2002 - Minor format changes + * 1.7 3 Mar 2003 - Added test code for distribution + * - Added zlib-like license + * 1.8 9 Jan 2004 - Added some comments on no distance codes case + * 1.9 21 Feb 2008 - Fix bug on 16-bit integer architectures [Pohland] + * - Catch missing end-of-block symbol error + * 2.0 25 Jul 2008 - Add #define to permit distance too far back + * - Add option in TEST code for puff to write the data + * - Add option in TEST code to skip input bytes + * - Allow TEST code to read from piped stdin + * 2.1 4 Apr 2010 - Avoid variable initialization for happier compilers + * - Avoid unsigned comparisons for even happier compilers + * 2.2 25 Apr 2010 - Fix bug in variable initializations [Oberhumer] + * - Add const where appropriate [Oberhumer] + * - Split if's and ?'s for coverage testing + * - Break out test code to separate file + * - Move NIL to puff.h + * - Allow incomplete code only if single code length is 1 + * - Add full code coverage test to Makefile + * 2.3 21 Jan 2013 - Check for invalid code length codes in dynamic blocks + */ + +#include /* for setjmp(), longjmp(), and jmp_buf */ +#include "puff.h" /* prototype for puff() */ + +#define local static /* for local function definitions */ + +/* + * Maximums for allocations and loops. It is not useful to change these -- + * they are fixed by the deflate format. + */ +#define MAXBITS 15 /* maximum bits in a code */ +#define MAXLCODES 286 /* maximum number of literal/length codes */ +#define MAXDCODES 30 /* maximum number of distance codes */ +#define MAXCODES (MAXLCODES+MAXDCODES) /* maximum codes lengths to read */ +#define FIXLCODES 288 /* number of fixed literal/length codes */ + +/* input and output state */ +struct state { + /* output state */ + unsigned char *out; /* output buffer */ + unsigned long outlen; /* available space at out */ + unsigned long outcnt; /* bytes written to out so far */ + + /* input state */ + const unsigned char *in; /* input buffer */ + unsigned long inlen; /* available input at in */ + unsigned long incnt; /* bytes read so far */ + int bitbuf; /* bit buffer */ + int bitcnt; /* number of bits in bit buffer */ + + /* input limit error return state for bits() and decode() */ + jmp_buf env; +}; + +/* + * Return need bits from the input stream. This always leaves less than + * eight bits in the buffer. bits() works properly for need == 0. + * + * Format notes: + * + * - Bits are stored in bytes from the least significant bit to the most + * significant bit. Therefore bits are dropped from the bottom of the bit + * buffer, using shift right, and new bytes are appended to the top of the + * bit buffer, using shift left. + */ +local int bits(struct state *s, int need) +{ + long val; /* bit accumulator (can use up to 20 bits) */ + + /* load at least need bits into val */ + val = s->bitbuf; + while (s->bitcnt < need) { + if (s->incnt == s->inlen) + longjmp(s->env, 1); /* out of input */ + val |= (long)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */ + s->bitcnt += 8; + } + + /* drop need bits and update buffer, always zero to seven bits left */ + s->bitbuf = (int)(val >> need); + s->bitcnt -= need; + + /* return need bits, zeroing the bits above that */ + return (int)(val & ((1L << need) - 1)); +} + +/* + * Process a stored block. + * + * Format notes: + * + * - After the two-bit stored block type (00), the stored block length and + * stored bytes are byte-aligned for fast copying. Therefore any leftover + * bits in the byte that has the last bit of the type, as many as seven, are + * discarded. The value of the discarded bits are not defined and should not + * be checked against any expectation. + * + * - The second inverted copy of the stored block length does not have to be + * checked, but it's probably a good idea to do so anyway. + * + * - A stored block can have zero length. This is sometimes used to byte-align + * subsets of the compressed data for random access or partial recovery. + */ +local int stored(struct state *s) +{ + unsigned len; /* length of stored block */ + + /* discard leftover bits from current byte (assumes s->bitcnt < 8) */ + s->bitbuf = 0; + s->bitcnt = 0; + + /* get length and check against its one's complement */ + if (s->incnt + 4 > s->inlen) + return 2; /* not enough input */ + len = s->in[s->incnt++]; + len |= s->in[s->incnt++] << 8; + if (s->in[s->incnt++] != (~len & 0xff) || + s->in[s->incnt++] != ((~len >> 8) & 0xff)) + return -2; /* didn't match complement! */ + + /* copy len bytes from in to out */ + if (s->incnt + len > s->inlen) + return 2; /* not enough input */ + if (s->out != NIL) { + if (s->outcnt + len > s->outlen) + return 1; /* not enough output space */ + while (len--) + s->out[s->outcnt++] = s->in[s->incnt++]; + } + else { /* just scanning */ + s->outcnt += len; + s->incnt += len; + } + + /* done with a valid stored block */ + return 0; +} + +/* + * Huffman code decoding tables. count[1..MAXBITS] is the number of symbols of + * each length, which for a canonical code are stepped through in order. + * symbol[] are the symbol values in canonical order, where the number of + * entries is the sum of the counts in count[]. The decoding process can be + * seen in the function decode() below. + */ +struct huffman { + short *count; /* number of symbols of each length */ + short *symbol; /* canonically ordered symbols */ +}; + +/* + * Decode a code from the stream s using huffman table h. Return the symbol or + * a negative value if there is an error. If all of the lengths are zero, i.e. + * an empty code, or if the code is incomplete and an invalid code is received, + * then -10 is returned after reading MAXBITS bits. + * + * Format notes: + * + * - The codes as stored in the compressed data are bit-reversed relative to + * a simple integer ordering of codes of the same lengths. Hence below the + * bits are pulled from the compressed data one at a time and used to + * build the code value reversed from what is in the stream in order to + * permit simple integer comparisons for decoding. A table-based decoding + * scheme (as used in zlib) does not need to do this reversal. + * + * - The first code for the shortest length is all zeros. Subsequent codes of + * the same length are simply integer increments of the previous code. When + * moving up a length, a zero bit is appended to the code. For a complete + * code, the last code of the longest length will be all ones. + * + * - Incomplete codes are handled by this decoder, since they are permitted + * in the deflate format. See the format notes for fixed() and dynamic(). + */ +#ifdef SLOW +local int decode(struct state *s, const struct huffman *h) +{ + int len; /* current number of bits in code */ + int code; /* len bits being decoded */ + int first; /* first code of length len */ + int count; /* number of codes of length len */ + int index; /* index of first code of length len in symbol table */ + + code = first = index = 0; + for (len = 1; len <= MAXBITS; len++) { + code |= bits(s, 1); /* get next bit */ + count = h->count[len]; + if (code - count < first) /* if length len, return symbol */ + return h->symbol[index + (code - first)]; + index += count; /* else update for next length */ + first += count; + first <<= 1; + code <<= 1; + } + return -10; /* ran out of codes */ +} + +/* + * A faster version of decode() for real applications of this code. It's not + * as readable, but it makes puff() twice as fast. And it only makes the code + * a few percent larger. + */ +#else /* !SLOW */ +local int decode(struct state *s, const struct huffman *h) +{ + int len; /* current number of bits in code */ + int code; /* len bits being decoded */ + int first; /* first code of length len */ + int count; /* number of codes of length len */ + int index; /* index of first code of length len in symbol table */ + int bitbuf; /* bits from stream */ + int left; /* bits left in next or left to process */ + short *next; /* next number of codes */ + + bitbuf = s->bitbuf; + left = s->bitcnt; + code = first = index = 0; + len = 1; + next = h->count + 1; + while (1) { + while (left--) { + code |= bitbuf & 1; + bitbuf >>= 1; + count = *next++; + if (code - count < first) { /* if length len, return symbol */ + s->bitbuf = bitbuf; + s->bitcnt = (s->bitcnt - len) & 7; + return h->symbol[index + (code - first)]; + } + index += count; /* else update for next length */ + first += count; + first <<= 1; + code <<= 1; + len++; + } + left = (MAXBITS+1) - len; + if (left == 0) + break; + if (s->incnt == s->inlen) + longjmp(s->env, 1); /* out of input */ + bitbuf = s->in[s->incnt++]; + if (left > 8) + left = 8; + } + return -10; /* ran out of codes */ +} +#endif /* SLOW */ + +/* + * Given the list of code lengths length[0..n-1] representing a canonical + * Huffman code for n symbols, construct the tables required to decode those + * codes. Those tables are the number of codes of each length, and the symbols + * sorted by length, retaining their original order within each length. The + * return value is zero for a complete code set, negative for an over- + * subscribed code set, and positive for an incomplete code set. The tables + * can be used if the return value is zero or positive, but they cannot be used + * if the return value is negative. If the return value is zero, it is not + * possible for decode() using that table to return an error--any stream of + * enough bits will resolve to a symbol. If the return value is positive, then + * it is possible for decode() using that table to return an error for received + * codes past the end of the incomplete lengths. + * + * Not used by decode(), but used for error checking, h->count[0] is the number + * of the n symbols not in the code. So n - h->count[0] is the number of + * codes. This is useful for checking for incomplete codes that have more than + * one symbol, which is an error in a dynamic block. + * + * Assumption: for all i in 0..n-1, 0 <= length[i] <= MAXBITS + * This is assured by the construction of the length arrays in dynamic() and + * fixed() and is not verified by construct(). + * + * Format notes: + * + * - Permitted and expected examples of incomplete codes are one of the fixed + * codes and any code with a single symbol which in deflate is coded as one + * bit instead of zero bits. See the format notes for fixed() and dynamic(). + * + * - Within a given code length, the symbols are kept in ascending order for + * the code bits definition. + */ +local int construct(struct huffman *h, const short *length, int n) +{ + int symbol; /* current symbol when stepping through length[] */ + int len; /* current length when stepping through h->count[] */ + int left; /* number of possible codes left of current length */ + short offs[MAXBITS+1]; /* offsets in symbol table for each length */ + + /* count number of codes of each length */ + for (len = 0; len <= MAXBITS; len++) + h->count[len] = 0; + for (symbol = 0; symbol < n; symbol++) + (h->count[length[symbol]])++; /* assumes lengths are within bounds */ + if (h->count[0] == n) /* no codes! */ + return 0; /* complete, but decode() will fail */ + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; /* one possible code of zero length */ + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; /* one more bit, double codes left */ + left -= h->count[len]; /* deduct count from possible codes */ + if (left < 0) + return left; /* over-subscribed--return negative */ + } /* left > 0 means incomplete */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + h->count[len]; + + /* + * put symbols in table sorted by length, by symbol order within each + * length + */ + for (symbol = 0; symbol < n; symbol++) + if (length[symbol] != 0) + h->symbol[offs[length[symbol]]++] = symbol; + + /* return zero for complete set, positive for incomplete set */ + return left; +} + +/* + * Decode literal/length and distance codes until an end-of-block code. + * + * Format notes: + * + * - Compressed data that is after the block type if fixed or after the code + * description if dynamic is a combination of literals and length/distance + * pairs terminated by and end-of-block code. Literals are simply Huffman + * coded bytes. A length/distance pair is a coded length followed by a + * coded distance to represent a string that occurs earlier in the + * uncompressed data that occurs again at the current location. + * + * - Literals, lengths, and the end-of-block code are combined into a single + * code of up to 286 symbols. They are 256 literals (0..255), 29 length + * symbols (257..285), and the end-of-block symbol (256). + * + * - There are 256 possible lengths (3..258), and so 29 symbols are not enough + * to represent all of those. Lengths 3..10 and 258 are in fact represented + * by just a length symbol. Lengths 11..257 are represented as a symbol and + * some number of extra bits that are added as an integer to the base length + * of the length symbol. The number of extra bits is determined by the base + * length symbol. These are in the static arrays below, lens[] for the base + * lengths and lext[] for the corresponding number of extra bits. + * + * - The reason that 258 gets its own symbol is that the longest length is used + * often in highly redundant files. Note that 258 can also be coded as the + * base value 227 plus the maximum extra value of 31. While a good deflate + * should never do this, it is not an error, and should be decoded properly. + * + * - If a length is decoded, including its extra bits if any, then it is + * followed a distance code. There are up to 30 distance symbols. Again + * there are many more possible distances (1..32768), so extra bits are added + * to a base value represented by the symbol. The distances 1..4 get their + * own symbol, but the rest require extra bits. The base distances and + * corresponding number of extra bits are below in the static arrays dist[] + * and dext[]. + * + * - Literal bytes are simply written to the output. A length/distance pair is + * an instruction to copy previously uncompressed bytes to the output. The + * copy is from distance bytes back in the output stream, copying for length + * bytes. + * + * - Distances pointing before the beginning of the output data are not + * permitted. + * + * - Overlapped copies, where the length is greater than the distance, are + * allowed and common. For example, a distance of one and a length of 258 + * simply copies the last byte 258 times. A distance of four and a length of + * twelve copies the last four bytes three times. A simple forward copy + * ignoring whether the length is greater than the distance or not implements + * this correctly. You should not use memcpy() since its behavior is not + * defined for overlapped arrays. You should not use memmove() or bcopy() + * since though their behavior -is- defined for overlapping arrays, it is + * defined to do the wrong thing in this case. + */ +local int codes(struct state *s, + const struct huffman *lencode, + const struct huffman *distcode) +{ + int symbol; /* decoded symbol */ + int len; /* length for copy */ + unsigned dist; /* distance for copy */ + static const short lens[29] = { /* Size base for length codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258}; + static const short lext[29] = { /* Extra bits for length codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; + static const short dists[30] = { /* Offset base for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; + static const short dext[30] = { /* Extra bits for distance codes 0..29 */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + + /* decode literals and length/distance pairs */ + do { + symbol = decode(s, lencode); + if (symbol < 0) + return symbol; /* invalid symbol */ + if (symbol < 256) { /* literal: symbol is the byte */ + /* write out the literal */ + if (s->out != NIL) { + if (s->outcnt == s->outlen) + return 1; + s->out[s->outcnt] = symbol; + } + s->outcnt++; + } + else if (symbol > 256) { /* length */ + /* get and compute length */ + symbol -= 257; + if (symbol >= 29) + return -10; /* invalid fixed code */ + len = lens[symbol] + bits(s, lext[symbol]); + + /* get and check distance */ + symbol = decode(s, distcode); + if (symbol < 0) + return symbol; /* invalid symbol */ + dist = dists[symbol] + bits(s, dext[symbol]); +#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (dist > s->outcnt) + return -11; /* distance too far back */ +#endif + + /* copy length bytes from distance bytes back */ + if (s->out != NIL) { + if (s->outcnt + len > s->outlen) + return 1; + while (len--) { + s->out[s->outcnt] = +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + dist > s->outcnt ? + 0 : +#endif + s->out[s->outcnt - dist]; + s->outcnt++; + } + } + else + s->outcnt += len; + } + } while (symbol != 256); /* end of block symbol */ + + /* done with a valid fixed or dynamic block */ + return 0; +} + +/* + * Process a fixed codes block. + * + * Format notes: + * + * - This block type can be useful for compressing small amounts of data for + * which the size of the code descriptions in a dynamic block exceeds the + * benefit of custom codes for that block. For fixed codes, no bits are + * spent on code descriptions. Instead the code lengths for literal/length + * codes and distance codes are fixed. The specific lengths for each symbol + * can be seen in the "for" loops below. + * + * - The literal/length code is complete, but has two symbols that are invalid + * and should result in an error if received. This cannot be implemented + * simply as an incomplete code since those two symbols are in the "middle" + * of the code. They are eight bits long and the longest literal/length\ + * code is nine bits. Therefore the code must be constructed with those + * symbols, and the invalid symbols must be detected after decoding. + * + * - The fixed distance codes also have two invalid symbols that should result + * in an error if received. Since all of the distance codes are the same + * length, this can be implemented as an incomplete code. Then the invalid + * codes are detected while decoding. + */ +local int fixed(struct state *s) +{ + static int virgin = 1; + static short lencnt[MAXBITS+1], lensym[FIXLCODES]; + static short distcnt[MAXBITS+1], distsym[MAXDCODES]; + static struct huffman lencode, distcode; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + int symbol; + short lengths[FIXLCODES]; + + /* construct lencode and distcode */ + lencode.count = lencnt; + lencode.symbol = lensym; + distcode.count = distcnt; + distcode.symbol = distsym; + + /* literal/length table */ + for (symbol = 0; symbol < 144; symbol++) + lengths[symbol] = 8; + for (; symbol < 256; symbol++) + lengths[symbol] = 9; + for (; symbol < 280; symbol++) + lengths[symbol] = 7; + for (; symbol < FIXLCODES; symbol++) + lengths[symbol] = 8; + construct(&lencode, lengths, FIXLCODES); + + /* distance table */ + for (symbol = 0; symbol < MAXDCODES; symbol++) + lengths[symbol] = 5; + construct(&distcode, lengths, MAXDCODES); + + /* do this just once */ + virgin = 0; + } + + /* decode data until end-of-block code */ + return codes(s, &lencode, &distcode); +} + +/* + * Process a dynamic codes block. + * + * Format notes: + * + * - A dynamic block starts with a description of the literal/length and + * distance codes for that block. New dynamic blocks allow the compressor to + * rapidly adapt to changing data with new codes optimized for that data. + * + * - The codes used by the deflate format are "canonical", which means that + * the actual bits of the codes are generated in an unambiguous way simply + * from the number of bits in each code. Therefore the code descriptions + * are simply a list of code lengths for each symbol. + * + * - The code lengths are stored in order for the symbols, so lengths are + * provided for each of the literal/length symbols, and for each of the + * distance symbols. + * + * - If a symbol is not used in the block, this is represented by a zero as + * as the code length. This does not mean a zero-length code, but rather + * that no code should be created for this symbol. There is no way in the + * deflate format to represent a zero-length code. + * + * - The maximum number of bits in a code is 15, so the possible lengths for + * any code are 1..15. + * + * - The fact that a length of zero is not permitted for a code has an + * interesting consequence. Normally if only one symbol is used for a given + * code, then in fact that code could be represented with zero bits. However + * in deflate, that code has to be at least one bit. So for example, if + * only a single distance base symbol appears in a block, then it will be + * represented by a single code of length one, in particular one 0 bit. This + * is an incomplete code, since if a 1 bit is received, it has no meaning, + * and should result in an error. So incomplete distance codes of one symbol + * should be permitted, and the receipt of invalid codes should be handled. + * + * - It is also possible to have a single literal/length code, but that code + * must be the end-of-block code, since every dynamic block has one. This + * is not the most efficient way to create an empty block (an empty fixed + * block is fewer bits), but it is allowed by the format. So incomplete + * literal/length codes of one symbol should also be permitted. + * + * - If there are only literal codes and no lengths, then there are no distance + * codes. This is represented by one distance code with zero bits. + * + * - The list of up to 286 length/literal lengths and up to 30 distance lengths + * are themselves compressed using Huffman codes and run-length encoding. In + * the list of code lengths, a 0 symbol means no code, a 1..15 symbol means + * that length, and the symbols 16, 17, and 18 are run-length instructions. + * Each of 16, 17, and 18 are follwed by extra bits to define the length of + * the run. 16 copies the last length 3 to 6 times. 17 represents 3 to 10 + * zero lengths, and 18 represents 11 to 138 zero lengths. Unused symbols + * are common, hence the special coding for zero lengths. + * + * - The symbols for 0..18 are Huffman coded, and so that code must be + * described first. This is simply a sequence of up to 19 three-bit values + * representing no code (0) or the code length for that symbol (1..7). + * + * - A dynamic block starts with three fixed-size counts from which is computed + * the number of literal/length code lengths, the number of distance code + * lengths, and the number of code length code lengths (ok, you come up with + * a better name!) in the code descriptions. For the literal/length and + * distance codes, lengths after those provided are considered zero, i.e. no + * code. The code length code lengths are received in a permuted order (see + * the order[] array below) to make a short code length code length list more + * likely. As it turns out, very short and very long codes are less likely + * to be seen in a dynamic code description, hence what may appear initially + * to be a peculiar ordering. + * + * - Given the number of literal/length code lengths (nlen) and distance code + * lengths (ndist), then they are treated as one long list of nlen + ndist + * code lengths. Therefore run-length coding can and often does cross the + * boundary between the two sets of lengths. + * + * - So to summarize, the code description at the start of a dynamic block is + * three counts for the number of code lengths for the literal/length codes, + * the distance codes, and the code length codes. This is followed by the + * code length code lengths, three bits each. This is used to construct the + * code length code which is used to read the remainder of the lengths. Then + * the literal/length code lengths and distance lengths are read as a single + * set of lengths using the code length codes. Codes are constructed from + * the resulting two sets of lengths, and then finally you can start + * decoding actual compressed data in the block. + * + * - For reference, a "typical" size for the code description in a dynamic + * block is around 80 bytes. + */ +local int dynamic(struct state *s) +{ + int nlen, ndist, ncode; /* number of lengths in descriptor */ + int index; /* index of lengths[] */ + int err; /* construct() return value */ + short lengths[MAXCODES]; /* descriptor code lengths */ + short lencnt[MAXBITS+1], lensym[MAXLCODES]; /* lencode memory */ + short distcnt[MAXBITS+1], distsym[MAXDCODES]; /* distcode memory */ + struct huffman lencode, distcode; /* length and distance codes */ + static const short order[19] = /* permutation of code length codes */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* construct lencode and distcode */ + lencode.count = lencnt; + lencode.symbol = lensym; + distcode.count = distcnt; + distcode.symbol = distsym; + + /* get number of lengths in each table, check lengths */ + nlen = bits(s, 5) + 257; + ndist = bits(s, 5) + 1; + ncode = bits(s, 4) + 4; + if (nlen > MAXLCODES || ndist > MAXDCODES) + return -3; /* bad counts */ + + /* read code length code lengths (really), missing lengths are zero */ + for (index = 0; index < ncode; index++) + lengths[order[index]] = bits(s, 3); + for (; index < 19; index++) + lengths[order[index]] = 0; + + /* build huffman table for code lengths codes (use lencode temporarily) */ + err = construct(&lencode, lengths, 19); + if (err != 0) /* require complete code set here */ + return -4; + + /* read length/literal and distance code length tables */ + index = 0; + while (index < nlen + ndist) { + int symbol; /* decoded value */ + int len; /* last length to repeat */ + + symbol = decode(s, &lencode); + if (symbol < 0) + return symbol; /* invalid symbol */ + if (symbol < 16) /* length in 0..15 */ + lengths[index++] = symbol; + else { /* repeat instruction */ + len = 0; /* assume repeating zeros */ + if (symbol == 16) { /* repeat last length 3..6 times */ + if (index == 0) + return -5; /* no last length! */ + len = lengths[index - 1]; /* last length */ + symbol = 3 + bits(s, 2); + } + else if (symbol == 17) /* repeat zero 3..10 times */ + symbol = 3 + bits(s, 3); + else /* == 18, repeat zero 11..138 times */ + symbol = 11 + bits(s, 7); + if (index + symbol > nlen + ndist) + return -6; /* too many lengths! */ + while (symbol--) /* repeat last or zero symbol times */ + lengths[index++] = len; + } + } + + /* check for end-of-block code -- there better be one! */ + if (lengths[256] == 0) + return -9; + + /* build huffman table for literal/length codes */ + err = construct(&lencode, lengths, nlen); + if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1])) + return -7; /* incomplete code ok only for single length 1 code */ + + /* build huffman table for distance codes */ + err = construct(&distcode, lengths + nlen, ndist); + if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1])) + return -8; /* incomplete code ok only for single length 1 code */ + + /* decode data until end-of-block code */ + return codes(s, &lencode, &distcode); +} + +/* + * Inflate source to dest. On return, destlen and sourcelen are updated to the + * size of the uncompressed data and the size of the deflate data respectively. + * On success, the return value of puff() is zero. If there is an error in the + * source data, i.e. it is not in the deflate format, then a negative value is + * returned. If there is not enough input available or there is not enough + * output space, then a positive error is returned. In that case, destlen and + * sourcelen are not updated to facilitate retrying from the beginning with the + * provision of more input data or more output space. In the case of invalid + * inflate data (a negative error), the dest and source pointers are updated to + * facilitate the debugging of deflators. + * + * puff() also has a mode to determine the size of the uncompressed output with + * no output written. For this dest must be (unsigned char *)0. In this case, + * the input value of *destlen is ignored, and on return *destlen is set to the + * size of the uncompressed output. + * + * The return codes are: + * + * 2: available inflate data did not terminate + * 1: output space exhausted before completing inflate + * 0: successful inflate + * -1: invalid block type (type == 3) + * -2: stored block length did not match one's complement + * -3: dynamic block code description: too many length or distance codes + * -4: dynamic block code description: code lengths codes incomplete + * -5: dynamic block code description: repeat lengths with no first length + * -6: dynamic block code description: repeat more than specified lengths + * -7: dynamic block code description: invalid literal/length code lengths + * -8: dynamic block code description: invalid distance code lengths + * -9: dynamic block code description: missing end-of-block code + * -10: invalid literal/length or distance code in fixed or dynamic block + * -11: distance is too far back in fixed or dynamic block + * + * Format notes: + * + * - Three bits are read for each block to determine the kind of block and + * whether or not it is the last block. Then the block is decoded and the + * process repeated if it was not the last block. + * + * - The leftover bits in the last byte of the deflate data after the last + * block (if it was a fixed or dynamic block) are undefined and have no + * expected values to check. + */ +int puff(unsigned char *dest, /* pointer to destination pointer */ + unsigned long *destlen, /* amount of output space */ + const unsigned char *source, /* pointer to source data pointer */ + unsigned long *sourcelen) /* amount of input available */ +{ + struct state s; /* input/output state */ + int last, type; /* block information */ + int err; /* return value */ + + /* initialize output state */ + s.out = dest; + s.outlen = *destlen; /* ignored if dest is NIL */ + s.outcnt = 0; + + /* initialize input state */ + s.in = source; + s.inlen = *sourcelen; + s.incnt = 0; + s.bitbuf = 0; + s.bitcnt = 0; + + /* return if bits() or decode() tries to read past available input */ + if (setjmp(s.env) != 0) /* if came back here via longjmp() */ + err = 2; /* then skip do-loop, return error */ + else { + /* process blocks until last block or error */ + do { + last = bits(&s, 1); /* one if last block */ + type = bits(&s, 2); /* block type 0..3 */ + err = type == 0 ? + stored(&s) : + (type == 1 ? + fixed(&s) : + (type == 2 ? + dynamic(&s) : + -1)); /* type == 3, invalid */ + if (err != 0) + break; /* return with error */ + } while (!last); + } + + /* update the lengths and return */ + if (err <= 0) { + *destlen = s.outcnt; + *sourcelen = s.incnt; + } + return err; +} diff --git a/zlib-1.2.11/contrib/puff/puff.h b/zlib-1.2.11/contrib/puff/puff.h new file mode 100644 index 00000000..e23a2454 --- /dev/null +++ b/zlib-1.2.11/contrib/puff/puff.h @@ -0,0 +1,35 @@ +/* puff.h + Copyright (C) 2002-2013 Mark Adler, all rights reserved + version 2.3, 21 Jan 2013 + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Mark Adler madler@alumni.caltech.edu + */ + + +/* + * See puff.c for purpose and usage. + */ +#ifndef NIL +# define NIL ((unsigned char *)0) /* for no output option */ +#endif + +int puff(unsigned char *dest, /* pointer to destination pointer */ + unsigned long *destlen, /* amount of output space */ + const unsigned char *source, /* pointer to source data pointer */ + unsigned long *sourcelen); /* amount of input available */ diff --git a/zlib-1.2.11/contrib/puff/pufftest.c b/zlib-1.2.11/contrib/puff/pufftest.c new file mode 100644 index 00000000..77648148 --- /dev/null +++ b/zlib-1.2.11/contrib/puff/pufftest.c @@ -0,0 +1,165 @@ +/* + * pufftest.c + * Copyright (C) 2002-2013 Mark Adler + * For conditions of distribution and use, see copyright notice in puff.h + * version 2.3, 21 Jan 2013 + */ + +/* Example of how to use puff(). + + Usage: puff [-w] [-f] [-nnn] file + ... | puff [-w] [-f] [-nnn] + + where file is the input file with deflate data, nnn is the number of bytes + of input to skip before inflating (e.g. to skip a zlib or gzip header), and + -w is used to write the decompressed data to stdout. -f is for coverage + testing, and causes pufftest to fail with not enough output space (-f does + a write like -w, so -w is not required). */ + +#include +#include +#include "puff.h" + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +#define local static + +/* Return size times approximately the cube root of 2, keeping the result as 1, + 3, or 5 times a power of 2 -- the result is always > size, until the result + is the maximum value of an unsigned long, where it remains. This is useful + to keep reallocations less than ~33% over the actual data. */ +local size_t bythirds(size_t size) +{ + int n; + size_t m; + + m = size; + for (n = 0; m; n++) + m >>= 1; + if (n < 3) + return size + 1; + n -= 3; + m = size >> n; + m += m == 6 ? 2 : 1; + m <<= n; + return m > size ? m : (size_t)(-1); +} + +/* Read the input file *name, or stdin if name is NULL, into allocated memory. + Reallocate to larger buffers until the entire file is read in. Return a + pointer to the allocated data, or NULL if there was a memory allocation + failure. *len is the number of bytes of data read from the input file (even + if load() returns NULL). If the input file was empty or could not be opened + or read, *len is zero. */ +local void *load(const char *name, size_t *len) +{ + size_t size; + void *buf, *swap; + FILE *in; + + *len = 0; + buf = malloc(size = 4096); + if (buf == NULL) + return NULL; + in = name == NULL ? stdin : fopen(name, "rb"); + if (in != NULL) { + for (;;) { + *len += fread((char *)buf + *len, 1, size - *len, in); + if (*len < size) break; + size = bythirds(size); + if (size == *len || (swap = realloc(buf, size)) == NULL) { + free(buf); + buf = NULL; + break; + } + buf = swap; + } + fclose(in); + } + return buf; +} + +int main(int argc, char **argv) +{ + int ret, put = 0, fail = 0; + unsigned skip = 0; + char *arg, *name = NULL; + unsigned char *source = NULL, *dest; + size_t len = 0; + unsigned long sourcelen, destlen; + + /* process arguments */ + while (arg = *++argv, --argc) + if (arg[0] == '-') { + if (arg[1] == 'w' && arg[2] == 0) + put = 1; + else if (arg[1] == 'f' && arg[2] == 0) + fail = 1, put = 1; + else if (arg[1] >= '0' && arg[1] <= '9') + skip = (unsigned)atoi(arg + 1); + else { + fprintf(stderr, "invalid option %s\n", arg); + return 3; + } + } + else if (name != NULL) { + fprintf(stderr, "only one file name allowed\n"); + return 3; + } + else + name = arg; + source = load(name, &len); + if (source == NULL) { + fprintf(stderr, "memory allocation failure\n"); + return 4; + } + if (len == 0) { + fprintf(stderr, "could not read %s, or it was empty\n", + name == NULL ? "" : name); + free(source); + return 3; + } + if (skip >= len) { + fprintf(stderr, "skip request of %d leaves no input\n", skip); + free(source); + return 3; + } + + /* test inflate data with offset skip */ + len -= skip; + sourcelen = (unsigned long)len; + ret = puff(NIL, &destlen, source + skip, &sourcelen); + if (ret) + fprintf(stderr, "puff() failed with return code %d\n", ret); + else { + fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen); + if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n", + len - sourcelen); + } + + /* if requested, inflate again and write decompressd data to stdout */ + if (put && ret == 0) { + if (fail) + destlen >>= 1; + dest = malloc(destlen); + if (dest == NULL) { + fprintf(stderr, "memory allocation failure\n"); + free(source); + return 4; + } + puff(dest, &destlen, source + skip, &sourcelen); + SET_BINARY_MODE(stdout); + fwrite(dest, 1, destlen, stdout); + free(dest); + } + + /* clean up */ + free(source); + return ret; +} diff --git a/zlib-1.2.11/contrib/puff/zeros.raw b/zlib-1.2.11/contrib/puff/zeros.raw new file mode 100644 index 0000000000000000000000000000000000000000..0a90e76b300205a44a0ecbf613e64aaaef2e51e7 GIT binary patch literal 2517 zcmYdFkYHV$AkxzmXu#!mP=i#?5{3o^3jqcYc(h*%Opg+yAut*OqaiT#LSPd+y9&tF zP5<`ixi4UXdB8xJfs^6ee;AkH?VUytyFsD;HLIJ(gg5bUnNh}Q2#kinXb22!2pr%5 E0JRq+;s5{u literal 0 HcmV?d00001 diff --git a/zlib-1.2.11/contrib/testzlib/testzlib.c b/zlib-1.2.11/contrib/testzlib/testzlib.c new file mode 100644 index 00000000..5f659dea --- /dev/null +++ b/zlib-1.2.11/contrib/testzlib/testzlib.c @@ -0,0 +1,275 @@ +#include +#include +#include + +#include "zlib.h" + + +void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B) +{ + R->HighPart = A.HighPart - B.HighPart; + if (A.LowPart >= B.LowPart) + R->LowPart = A.LowPart - B.LowPart; + else + { + R->LowPart = A.LowPart - B.LowPart; + R->HighPart --; + } +} + +#ifdef _M_X64 +// see http://msdn2.microsoft.com/library/twchhe95(en-us,vs.80).aspx for __rdtsc +unsigned __int64 __rdtsc(void); +void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) +{ + // printf("rdtsc = %I64x\n",__rdtsc()); + pbeginTime64->QuadPart=__rdtsc(); +} + +LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER LIres; + unsigned _int64 res=__rdtsc()-((unsigned _int64)(beginTime64.QuadPart)); + LIres.QuadPart=res; + // printf("rdtsc = %I64x\n",__rdtsc()); + return LIres; +} +#else +#ifdef _M_IX86 +void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) +{ + DWORD dwEdx,dwEax; + _asm + { + rdtsc + mov dwEax,eax + mov dwEdx,edx + } + pbeginTime64->LowPart=dwEax; + pbeginTime64->HighPart=dwEdx; +} + +void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) +{ + myGetRDTSC32(pbeginTime64); +} + +LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER LIres,endTime64; + myGetRDTSC32(&endTime64); + + LIres.LowPart=LIres.HighPart=0; + MyDoMinus64(&LIres,endTime64,beginTime64); + return LIres; +} +#else +void myGetRDTSC32(LARGE_INTEGER * pbeginTime64) +{ +} + +void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64) +{ +} + +LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER lr; + lr.QuadPart=0; + return lr; +} +#endif +#endif + +void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf) +{ + if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64))) + { + pbeginTime64->LowPart = GetTickCount(); + pbeginTime64->HighPart = 0; + } +} + +DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf) +{ + LARGE_INTEGER endTime64,ticksPerSecond,ticks; + DWORDLONG ticksShifted,tickSecShifted; + DWORD dwLog=16+0; + DWORD dwRet; + if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64))) + dwRet = (GetTickCount() - beginTime64.LowPart)*1; + else + { + MyDoMinus64(&ticks,endTime64,beginTime64); + QueryPerformanceFrequency(&ticksPerSecond); + + + { + ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog); + tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog); + + } + + dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted)); + dwRet *=1; + } + return dwRet; +} + +int ReadFileMemory(const char* filename,long* plFileSize,unsigned char** pFilePtr) +{ + FILE* stream; + unsigned char* ptr; + int retVal=1; + stream=fopen(filename, "rb"); + if (stream==NULL) + return 0; + + fseek(stream,0,SEEK_END); + + *plFileSize=ftell(stream); + fseek(stream,0,SEEK_SET); + ptr=malloc((*plFileSize)+1); + if (ptr==NULL) + retVal=0; + else + { + if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize)) + retVal=0; + } + fclose(stream); + *pFilePtr=ptr; + return retVal; +} + +int main(int argc, char *argv[]) +{ + int BlockSizeCompress=0x8000; + int BlockSizeUncompress=0x8000; + int cprLevel=Z_DEFAULT_COMPRESSION ; + long lFileSize; + unsigned char* FilePtr; + long lBufferSizeCpr; + long lBufferSizeUncpr; + long lCompressedSize=0; + unsigned char* CprPtr; + unsigned char* UncprPtr; + long lSizeCpr,lSizeUncpr; + DWORD dwGetTick,dwMsecQP; + LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc; + + if (argc<=1) + { + printf("run TestZlib [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n"); + return 0; + } + + if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0) + { + printf("error reading %s\n",argv[1]); + return 1; + } + else printf("file %s read, %u bytes\n",argv[1],lFileSize); + + if (argc>=3) + BlockSizeCompress=atol(argv[2]); + + if (argc>=4) + BlockSizeUncompress=atol(argv[3]); + + if (argc>=5) + cprLevel=(int)atol(argv[4]); + + lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200; + lBufferSizeUncpr = lBufferSizeCpr; + + CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress); + + BeginCountPerfCounter(&li_qp,TRUE); + dwGetTick=GetTickCount(); + BeginCountRdtsc(&li_rdtsc); + { + z_stream zcpr; + int ret=Z_OK; + long lOrigToDo = lFileSize; + long lOrigDone = 0; + int step=0; + memset(&zcpr,0,sizeof(z_stream)); + deflateInit(&zcpr,cprLevel); + + zcpr.next_in = FilePtr; + zcpr.next_out = CprPtr; + + + do + { + long all_read_before = zcpr.total_in; + zcpr.avail_in = min(lOrigToDo,BlockSizeCompress); + zcpr.avail_out = BlockSizeCompress; + ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH); + lOrigDone += (zcpr.total_in-all_read_before); + lOrigToDo -= (zcpr.total_in-all_read_before); + step++; + } while (ret==Z_OK); + + lSizeCpr=zcpr.total_out; + deflateEnd(&zcpr); + dwGetTick=GetTickCount()-dwGetTick; + dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); + dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); + printf("total compress size = %u, in %u step\n",lSizeCpr,step); + printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); + printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); + printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); + } + + CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr); + UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress); + + BeginCountPerfCounter(&li_qp,TRUE); + dwGetTick=GetTickCount(); + BeginCountRdtsc(&li_rdtsc); + { + z_stream zcpr; + int ret=Z_OK; + long lOrigToDo = lSizeCpr; + long lOrigDone = 0; + int step=0; + memset(&zcpr,0,sizeof(z_stream)); + inflateInit(&zcpr); + + zcpr.next_in = CprPtr; + zcpr.next_out = UncprPtr; + + + do + { + long all_read_before = zcpr.total_in; + zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress); + zcpr.avail_out = BlockSizeUncompress; + ret=inflate(&zcpr,Z_SYNC_FLUSH); + lOrigDone += (zcpr.total_in-all_read_before); + lOrigToDo -= (zcpr.total_in-all_read_before); + step++; + } while (ret==Z_OK); + + lSizeUncpr=zcpr.total_out; + inflateEnd(&zcpr); + dwGetTick=GetTickCount()-dwGetTick; + dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE); + dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE); + printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step); + printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.); + printf("uncpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.); + printf("uncpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart); + } + + if (lSizeUncpr==lFileSize) + { + if (memcmp(FilePtr,UncprPtr,lFileSize)==0) + printf("compare ok\n"); + + } + + return 0; +} diff --git a/zlib-1.2.11/contrib/testzlib/testzlib.txt b/zlib-1.2.11/contrib/testzlib/testzlib.txt new file mode 100644 index 00000000..62258f14 --- /dev/null +++ b/zlib-1.2.11/contrib/testzlib/testzlib.txt @@ -0,0 +1,10 @@ +To build testzLib with Visual Studio 2005: + +copy to a directory file from : +- root of zLib tree +- contrib/testzlib +- contrib/masmx86 +- contrib/masmx64 +- contrib/vstudio/vc7 + +and open testzlib8.sln \ No newline at end of file diff --git a/zlib-1.2.11/contrib/untgz/Makefile b/zlib-1.2.11/contrib/untgz/Makefile new file mode 100644 index 00000000..b54266fb --- /dev/null +++ b/zlib-1.2.11/contrib/untgz/Makefile @@ -0,0 +1,14 @@ +CC=cc +CFLAGS=-g + +untgz: untgz.o ../../libz.a + $(CC) $(CFLAGS) -o untgz untgz.o -L../.. -lz + +untgz.o: untgz.c ../../zlib.h + $(CC) $(CFLAGS) -c -I../.. untgz.c + +../../libz.a: + cd ../..; ./configure; make + +clean: + rm -f untgz untgz.o *~ diff --git a/zlib-1.2.11/contrib/untgz/Makefile.msc b/zlib-1.2.11/contrib/untgz/Makefile.msc new file mode 100644 index 00000000..77b86022 --- /dev/null +++ b/zlib-1.2.11/contrib/untgz/Makefile.msc @@ -0,0 +1,17 @@ +CC=cl +CFLAGS=-MD + +untgz.exe: untgz.obj ..\..\zlib.lib + $(CC) $(CFLAGS) untgz.obj ..\..\zlib.lib + +untgz.obj: untgz.c ..\..\zlib.h + $(CC) $(CFLAGS) -c -I..\.. untgz.c + +..\..\zlib.lib: + cd ..\.. + $(MAKE) -f win32\makefile.msc + cd contrib\untgz + +clean: + -del untgz.obj + -del untgz.exe diff --git a/zlib-1.2.11/contrib/untgz/untgz.c b/zlib-1.2.11/contrib/untgz/untgz.c new file mode 100644 index 00000000..2c391e59 --- /dev/null +++ b/zlib-1.2.11/contrib/untgz/untgz.c @@ -0,0 +1,674 @@ +/* + * untgz.c -- Display contents and extract files from a gzip'd TAR file + * + * written by Pedro A. Aranda Gutierrez + * adaptation to Unix by Jean-loup Gailly + * various fixes by Cosmin Truta + */ + +#include +#include +#include +#include +#include + +#include "zlib.h" + +#ifdef unix +# include +#else +# include +# include +#endif + +#ifdef WIN32 +#include +# ifndef F_OK +# define F_OK 0 +# endif +# define mkdir(dirname,mode) _mkdir(dirname) +# ifdef _MSC_VER +# define access(path,mode) _access(path,mode) +# define chmod(path,mode) _chmod(path,mode) +# define strdup(str) _strdup(str) +# endif +#else +# include +#endif + + +/* values used in typeflag field */ + +#define REGTYPE '0' /* regular file */ +#define AREGTYPE '\0' /* regular file */ +#define LNKTYPE '1' /* link */ +#define SYMTYPE '2' /* reserved */ +#define CHRTYPE '3' /* character special */ +#define BLKTYPE '4' /* block special */ +#define DIRTYPE '5' /* directory */ +#define FIFOTYPE '6' /* FIFO special */ +#define CONTTYPE '7' /* reserved */ + +/* GNU tar extensions */ + +#define GNUTYPE_DUMPDIR 'D' /* file names from dumped directory */ +#define GNUTYPE_LONGLINK 'K' /* long link name */ +#define GNUTYPE_LONGNAME 'L' /* long file name */ +#define GNUTYPE_MULTIVOL 'M' /* continuation of file from another volume */ +#define GNUTYPE_NAMES 'N' /* file name that does not fit into main hdr */ +#define GNUTYPE_SPARSE 'S' /* sparse file */ +#define GNUTYPE_VOLHDR 'V' /* tape/volume header */ + + +/* tar header */ + +#define BLOCKSIZE 512 +#define SHORTNAMESIZE 100 + +struct tar_header +{ /* byte offset */ + char name[100]; /* 0 */ + char mode[8]; /* 100 */ + char uid[8]; /* 108 */ + char gid[8]; /* 116 */ + char size[12]; /* 124 */ + char mtime[12]; /* 136 */ + char chksum[8]; /* 148 */ + char typeflag; /* 156 */ + char linkname[100]; /* 157 */ + char magic[6]; /* 257 */ + char version[2]; /* 263 */ + char uname[32]; /* 265 */ + char gname[32]; /* 297 */ + char devmajor[8]; /* 329 */ + char devminor[8]; /* 337 */ + char prefix[155]; /* 345 */ + /* 500 */ +}; + +union tar_buffer +{ + char buffer[BLOCKSIZE]; + struct tar_header header; +}; + +struct attr_item +{ + struct attr_item *next; + char *fname; + int mode; + time_t time; +}; + +enum { TGZ_EXTRACT, TGZ_LIST, TGZ_INVALID }; + +char *TGZfname OF((const char *)); +void TGZnotfound OF((const char *)); + +int getoct OF((char *, int)); +char *strtime OF((time_t *)); +int setfiletime OF((char *, time_t)); +void push_attr OF((struct attr_item **, char *, int, time_t)); +void restore_attr OF((struct attr_item **)); + +int ExprMatch OF((char *, char *)); + +int makedir OF((char *)); +int matchname OF((int, int, char **, char *)); + +void error OF((const char *)); +int tar OF((gzFile, int, int, int, char **)); + +void help OF((int)); +int main OF((int, char **)); + +char *prog; + +const char *TGZsuffix[] = { "\0", ".tar", ".tar.gz", ".taz", ".tgz", NULL }; + +/* return the file name of the TGZ archive */ +/* or NULL if it does not exist */ + +char *TGZfname (const char *arcname) +{ + static char buffer[1024]; + int origlen,i; + + strcpy(buffer,arcname); + origlen = strlen(buffer); + + for (i=0; TGZsuffix[i]; i++) + { + strcpy(buffer+origlen,TGZsuffix[i]); + if (access(buffer,F_OK) == 0) + return buffer; + } + return NULL; +} + + +/* error message for the filename */ + +void TGZnotfound (const char *arcname) +{ + int i; + + fprintf(stderr,"%s: Couldn't find ",prog); + for (i=0;TGZsuffix[i];i++) + fprintf(stderr,(TGZsuffix[i+1]) ? "%s%s, " : "or %s%s\n", + arcname, + TGZsuffix[i]); + exit(1); +} + + +/* convert octal digits to int */ +/* on error return -1 */ + +int getoct (char *p,int width) +{ + int result = 0; + char c; + + while (width--) + { + c = *p++; + if (c == 0) + break; + if (c == ' ') + continue; + if (c < '0' || c > '7') + return -1; + result = result * 8 + (c - '0'); + } + return result; +} + + +/* convert time_t to string */ +/* use the "YYYY/MM/DD hh:mm:ss" format */ + +char *strtime (time_t *t) +{ + struct tm *local; + static char result[32]; + + local = localtime(t); + sprintf(result,"%4d/%02d/%02d %02d:%02d:%02d", + local->tm_year+1900, local->tm_mon+1, local->tm_mday, + local->tm_hour, local->tm_min, local->tm_sec); + return result; +} + + +/* set file time */ + +int setfiletime (char *fname,time_t ftime) +{ +#ifdef WIN32 + static int isWinNT = -1; + SYSTEMTIME st; + FILETIME locft, modft; + struct tm *loctm; + HANDLE hFile; + int result; + + loctm = localtime(&ftime); + if (loctm == NULL) + return -1; + + st.wYear = (WORD)loctm->tm_year + 1900; + st.wMonth = (WORD)loctm->tm_mon + 1; + st.wDayOfWeek = (WORD)loctm->tm_wday; + st.wDay = (WORD)loctm->tm_mday; + st.wHour = (WORD)loctm->tm_hour; + st.wMinute = (WORD)loctm->tm_min; + st.wSecond = (WORD)loctm->tm_sec; + st.wMilliseconds = 0; + if (!SystemTimeToFileTime(&st, &locft) || + !LocalFileTimeToFileTime(&locft, &modft)) + return -1; + + if (isWinNT < 0) + isWinNT = (GetVersion() < 0x80000000) ? 1 : 0; + hFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + (isWinNT ? FILE_FLAG_BACKUP_SEMANTICS : 0), + NULL); + if (hFile == INVALID_HANDLE_VALUE) + return -1; + result = SetFileTime(hFile, NULL, NULL, &modft) ? 0 : -1; + CloseHandle(hFile); + return result; +#else + struct utimbuf settime; + + settime.actime = settime.modtime = ftime; + return utime(fname,&settime); +#endif +} + + +/* push file attributes */ + +void push_attr(struct attr_item **list,char *fname,int mode,time_t time) +{ + struct attr_item *item; + + item = (struct attr_item *)malloc(sizeof(struct attr_item)); + if (item == NULL) + error("Out of memory"); + item->fname = strdup(fname); + item->mode = mode; + item->time = time; + item->next = *list; + *list = item; +} + + +/* restore file attributes */ + +void restore_attr(struct attr_item **list) +{ + struct attr_item *item, *prev; + + for (item = *list; item != NULL; ) + { + setfiletime(item->fname,item->time); + chmod(item->fname,item->mode); + prev = item; + item = item->next; + free(prev); + } + *list = NULL; +} + + +/* match regular expression */ + +#define ISSPECIAL(c) (((c) == '*') || ((c) == '/')) + +int ExprMatch (char *string,char *expr) +{ + while (1) + { + if (ISSPECIAL(*expr)) + { + if (*expr == '/') + { + if (*string != '\\' && *string != '/') + return 0; + string ++; expr++; + } + else if (*expr == '*') + { + if (*expr ++ == 0) + return 1; + while (*++string != *expr) + if (*string == 0) + return 0; + } + } + else + { + if (*string != *expr) + return 0; + if (*expr++ == 0) + return 1; + string++; + } + } +} + + +/* recursive mkdir */ +/* abort on ENOENT; ignore other errors like "directory already exists" */ +/* return 1 if OK */ +/* 0 on error */ + +int makedir (char *newdir) +{ + char *buffer = strdup(newdir); + char *p; + int len = strlen(buffer); + + if (len <= 0) { + free(buffer); + return 0; + } + if (buffer[len-1] == '/') { + buffer[len-1] = '\0'; + } + if (mkdir(buffer, 0755) == 0) + { + free(buffer); + return 1; + } + + p = buffer+1; + while (1) + { + char hold; + + while(*p && *p != '\\' && *p != '/') + p++; + hold = *p; + *p = 0; + if ((mkdir(buffer, 0755) == -1) && (errno == ENOENT)) + { + fprintf(stderr,"%s: Couldn't create directory %s\n",prog,buffer); + free(buffer); + return 0; + } + if (hold == 0) + break; + *p++ = hold; + } + free(buffer); + return 1; +} + + +int matchname (int arg,int argc,char **argv,char *fname) +{ + if (arg == argc) /* no arguments given (untgz tgzarchive) */ + return 1; + + while (arg < argc) + if (ExprMatch(fname,argv[arg++])) + return 1; + + return 0; /* ignore this for the moment being */ +} + + +/* tar file list or extract */ + +int tar (gzFile in,int action,int arg,int argc,char **argv) +{ + union tar_buffer buffer; + int len; + int err; + int getheader = 1; + int remaining = 0; + FILE *outfile = NULL; + char fname[BLOCKSIZE]; + int tarmode; + time_t tartime; + struct attr_item *attributes = NULL; + + if (action == TGZ_LIST) + printf(" date time size file\n" + " ---------- -------- --------- -------------------------------------\n"); + while (1) + { + len = gzread(in, &buffer, BLOCKSIZE); + if (len < 0) + error(gzerror(in, &err)); + /* + * Always expect complete blocks to process + * the tar information. + */ + if (len != BLOCKSIZE) + { + action = TGZ_INVALID; /* force error exit */ + remaining = 0; /* force I/O cleanup */ + } + + /* + * If we have to get a tar header + */ + if (getheader >= 1) + { + /* + * if we met the end of the tar + * or the end-of-tar block, + * we are done + */ + if (len == 0 || buffer.header.name[0] == 0) + break; + + tarmode = getoct(buffer.header.mode,8); + tartime = (time_t)getoct(buffer.header.mtime,12); + if (tarmode == -1 || tartime == (time_t)-1) + { + buffer.header.name[0] = 0; + action = TGZ_INVALID; + } + + if (getheader == 1) + { + strncpy(fname,buffer.header.name,SHORTNAMESIZE); + if (fname[SHORTNAMESIZE-1] != 0) + fname[SHORTNAMESIZE] = 0; + } + else + { + /* + * The file name is longer than SHORTNAMESIZE + */ + if (strncmp(fname,buffer.header.name,SHORTNAMESIZE-1) != 0) + error("bad long name"); + getheader = 1; + } + + /* + * Act according to the type flag + */ + switch (buffer.header.typeflag) + { + case DIRTYPE: + if (action == TGZ_LIST) + printf(" %s %s\n",strtime(&tartime),fname); + if (action == TGZ_EXTRACT) + { + makedir(fname); + push_attr(&attributes,fname,tarmode,tartime); + } + break; + case REGTYPE: + case AREGTYPE: + remaining = getoct(buffer.header.size,12); + if (remaining == -1) + { + action = TGZ_INVALID; + break; + } + if (action == TGZ_LIST) + printf(" %s %9d %s\n",strtime(&tartime),remaining,fname); + else if (action == TGZ_EXTRACT) + { + if (matchname(arg,argc,argv,fname)) + { + outfile = fopen(fname,"wb"); + if (outfile == NULL) { + /* try creating directory */ + char *p = strrchr(fname, '/'); + if (p != NULL) { + *p = '\0'; + makedir(fname); + *p = '/'; + outfile = fopen(fname,"wb"); + } + } + if (outfile != NULL) + printf("Extracting %s\n",fname); + else + fprintf(stderr, "%s: Couldn't create %s",prog,fname); + } + else + outfile = NULL; + } + getheader = 0; + break; + case GNUTYPE_LONGLINK: + case GNUTYPE_LONGNAME: + remaining = getoct(buffer.header.size,12); + if (remaining < 0 || remaining >= BLOCKSIZE) + { + action = TGZ_INVALID; + break; + } + len = gzread(in, fname, BLOCKSIZE); + if (len < 0) + error(gzerror(in, &err)); + if (fname[BLOCKSIZE-1] != 0 || (int)strlen(fname) > remaining) + { + action = TGZ_INVALID; + break; + } + getheader = 2; + break; + default: + if (action == TGZ_LIST) + printf(" %s <---> %s\n",strtime(&tartime),fname); + break; + } + } + else + { + unsigned int bytes = (remaining > BLOCKSIZE) ? BLOCKSIZE : remaining; + + if (outfile != NULL) + { + if (fwrite(&buffer,sizeof(char),bytes,outfile) != bytes) + { + fprintf(stderr, + "%s: Error writing %s -- skipping\n",prog,fname); + fclose(outfile); + outfile = NULL; + remove(fname); + } + } + remaining -= bytes; + } + + if (remaining == 0) + { + getheader = 1; + if (outfile != NULL) + { + fclose(outfile); + outfile = NULL; + if (action != TGZ_INVALID) + push_attr(&attributes,fname,tarmode,tartime); + } + } + + /* + * Abandon if errors are found + */ + if (action == TGZ_INVALID) + { + error("broken archive"); + break; + } + } + + /* + * Restore file modes and time stamps + */ + restore_attr(&attributes); + + if (gzclose(in) != Z_OK) + error("failed gzclose"); + + return 0; +} + + +/* ============================================================ */ + +void help(int exitval) +{ + printf("untgz version 0.2.1\n" + " using zlib version %s\n\n", + zlibVersion()); + printf("Usage: untgz file.tgz extract all files\n" + " untgz file.tgz fname ... extract selected files\n" + " untgz -l file.tgz list archive contents\n" + " untgz -h display this help\n"); + exit(exitval); +} + +void error(const char *msg) +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + + +/* ============================================================ */ + +#if defined(WIN32) && defined(__GNUC__) +int _CRT_glob = 0; /* disable argument globbing in MinGW */ +#endif + +int main(int argc,char **argv) +{ + int action = TGZ_EXTRACT; + int arg = 1; + char *TGZfile; + gzFile *f; + + prog = strrchr(argv[0],'\\'); + if (prog == NULL) + { + prog = strrchr(argv[0],'/'); + if (prog == NULL) + { + prog = strrchr(argv[0],':'); + if (prog == NULL) + prog = argv[0]; + else + prog++; + } + else + prog++; + } + else + prog++; + + if (argc == 1) + help(0); + + if (strcmp(argv[arg],"-l") == 0) + { + action = TGZ_LIST; + if (argc == ++arg) + help(0); + } + else if (strcmp(argv[arg],"-h") == 0) + { + help(0); + } + + if ((TGZfile = TGZfname(argv[arg])) == NULL) + TGZnotfound(argv[arg]); + + ++arg; + if ((action == TGZ_LIST) && (arg != argc)) + help(1); + +/* + * Process the TGZ file + */ + switch(action) + { + case TGZ_LIST: + case TGZ_EXTRACT: + f = gzopen(TGZfile,"rb"); + if (f == NULL) + { + fprintf(stderr,"%s: Couldn't gzopen %s\n",prog,TGZfile); + return 1; + } + exit(tar(f, action, arg, argc, argv)); + break; + + default: + error("Unknown option"); + exit(1); + } + + return 0; +} diff --git a/zlib-1.2.11/contrib/vstudio/readme.txt b/zlib-1.2.11/contrib/vstudio/readme.txt new file mode 100644 index 00000000..f67eae86 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/readme.txt @@ -0,0 +1,78 @@ +Building instructions for the DLL versions of Zlib 1.2.11 +======================================================== + +This directory contains projects that build zlib and minizip using +Microsoft Visual C++ 9.0/10.0. + +You don't need to build these projects yourself. You can download the +binaries from: + http://www.winimage.com/zLibDll + +More information can be found at this site. + + + + + +Build instructions for Visual Studio 2008 (32 bits or 64 bits) +-------------------------------------------------------------- +- Decompress current zlib, including all contrib/* files +- Compile assembly code (with Visual Studio Command Prompt) by running: + bld_ml64.bat (in contrib\masmx64) + bld_ml32.bat (in contrib\masmx86) +- Open contrib\vstudio\vc9\zlibvc.sln with Microsoft Visual C++ 2008 +- Or run: vcbuild /rebuild contrib\vstudio\vc9\zlibvc.sln "Release|Win32" + +Build instructions for Visual Studio 2010 (32 bits or 64 bits) +-------------------------------------------------------------- +- Decompress current zlib, including all contrib/* files +- Open contrib\vstudio\vc10\zlibvc.sln with Microsoft Visual C++ 2010 + +Build instructions for Visual Studio 2012 (32 bits or 64 bits) +-------------------------------------------------------------- +- Decompress current zlib, including all contrib/* files +- Open contrib\vstudio\vc11\zlibvc.sln with Microsoft Visual C++ 2012 + +Build instructions for Visual Studio 2013 (32 bits or 64 bits) +-------------------------------------------------------------- +- Decompress current zlib, including all contrib/* files +- Open contrib\vstudio\vc12\zlibvc.sln with Microsoft Visual C++ 2013 + +Build instructions for Visual Studio 2015 (32 bits or 64 bits) +-------------------------------------------------------------- +- Decompress current zlib, including all contrib/* files +- Open contrib\vstudio\vc14\zlibvc.sln with Microsoft Visual C++ 2015 + + +Important +--------- +- To use zlibwapi.dll in your application, you must define the + macro ZLIB_WINAPI when compiling your application's source files. + + +Additional notes +---------------- +- This DLL, named zlibwapi.dll, is compatible to the old zlib.dll built + by Gilles Vollant from the zlib 1.1.x sources, and distributed at + http://www.winimage.com/zLibDll + It uses the WINAPI calling convention for the exported functions, and + includes the minizip functionality. If your application needs that + particular build of zlib.dll, you can rename zlibwapi.dll to zlib.dll. + +- The new DLL was renamed because there exist several incompatible + versions of zlib.dll on the Internet. + +- There is also an official DLL build of zlib, named zlib1.dll. This one + is exporting the functions using the CDECL convention. See the file + win32\DLL_FAQ.txt found in this zlib distribution. + +- There used to be a ZLIB_DLL macro in zlib 1.1.x, but now this symbol + has a slightly different effect. To avoid compatibility problems, do + not define it here. + + +Gilles Vollant +info@winimage.com + +Visual Studio 2013 and 2015 Projects from Sean Hunt +seandhunt_7@yahoo.com diff --git a/zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj b/zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj new file mode 100644 index 00000000..74e15c90 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj @@ -0,0 +1,310 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694382A} + Win32Proj + + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + true + false + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + false + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + true + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + true + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + false + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebug + false + + + $(IntDir) + Level3 + EditAndContinue + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj.filters b/zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj.filters new file mode 100644 index 00000000..0b2a3de2 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/miniunz.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {048af943-022b-4db6-beeb-a54c34774ee2} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {c1d600d2-888f-4aea-b73e-8b0dd9befa0c} + h;hpp;hxx;hm;inl;inc + + + {0844199a-966b-4f19-81db-1e0125e141b9} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj b/zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj new file mode 100644 index 00000000..917e1565 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj @@ -0,0 +1,307 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} + Win32Proj + + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + true + false + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + false + x64\$(Configuration)\ + x64\$(Configuration)\ + true + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + true + false + x64\$(Configuration)\ + x64\$(Configuration)\ + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebug + false + + + $(IntDir) + Level3 + EditAndContinue + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj.filters b/zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj.filters new file mode 100644 index 00000000..dd73cd31 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/minizip.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {c0419b40-bf50-40da-b153-ff74215b79de} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {bb87b070-735b-478e-92ce-7383abb2f36c} + h;hpp;hxx;hm;inl;inc + + + {f46ab6a6-548f-43cb-ae96-681abb5bd5db} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj b/zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj new file mode 100644 index 00000000..9088d176 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj @@ -0,0 +1,420 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} + testzlib + Win32Proj + + + + Application + MultiByte + true + + + Application + MultiByte + true + + + Application + MultiByte + + + Application + MultiByte + true + + + Application + MultiByte + true + + + Application + MultiByte + + + Application + true + + + Application + true + + + Application + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + true + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + true + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebug + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + EditAndContinue + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + %(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj.filters b/zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj.filters new file mode 100644 index 00000000..249daa89 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/testzlib.vcxproj.filters @@ -0,0 +1,58 @@ + + + + + {c1f6a2e3-5da5-4955-8653-310d3efe05a9} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {c2aaffdc-2c95-4d6f-8466-4bec5890af2c} + h;hpp;hxx;hm;inl;inc + + + {c274fe07-05f2-461c-964b-f6341e4e7eb5} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj b/zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj new file mode 100644 index 00000000..bcb08ff9 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj @@ -0,0 +1,310 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694366A} + Win32Proj + + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + true + false + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + false + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + true + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + true + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + false + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebug + false + + + $(IntDir) + Level3 + EditAndContinue + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj.filters b/zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj.filters new file mode 100644 index 00000000..53a8693b --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/testzlibdll.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {fa61a89f-93fc-4c89-b29e-36224b7592f4} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {d4b85da0-2ba2-4934-b57f-e2584e3848ee} + h;hpp;hxx;hm;inl;inc + + + {e573e075-00bd-4a7d-bd67-a8cc9bfc5aca} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc10/zlib.rc b/zlib-1.2.11/contrib/vstudio/vc10/zlib.rc new file mode 100644 index 00000000..fee177a7 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" + VALUE "FileVersion", "1.2.11\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj b/zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj new file mode 100644 index 00000000..b9f2bbe5 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj @@ -0,0 +1,473 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} + + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + MultiThreadedDebug + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + Itanium + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj.filters b/zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj.filters new file mode 100644 index 00000000..c8c7f7ea --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/zlibstat.vcxproj.filters @@ -0,0 +1,77 @@ + + + + + {174213f6-7f66-4ae8-a3a8-a1e0a1e6ffdd} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + + + Source Files + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.def b/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.def new file mode 100644 index 00000000..54e683d9 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.def @@ -0,0 +1,153 @@ +LIBRARY +; zlib data compression and ZIP file I/O library + +VERSION 1.2 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + inflateCopy @42 + inflateBackInit_ @43 + inflateBack @44 + inflateBackEnd @45 + compressBound @46 + deflateBound @47 + gzclearerr @48 + gzungetc @49 + zlibCompileFlags @50 + deflatePrime @51 + deflatePending @52 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unzOpenCurrentFile3 @69 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + unzOpen2 @77 + unzOpenCurrentFile2 @78 + unzOpenCurrentFilePassword @79 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 + zipOpenNewFileInZip2 @86 + zipCloseFileInZipRaw @87 + zipOpen2 @88 + zipOpenNewFileInZip3 @89 + + unzGetFilePos @100 + unzGoToFilePos @101 + + fill_win32_filefunc @110 + +; zlibwapi v1.2.4 added: + fill_win32_filefunc64 @111 + fill_win32_filefunc64A @112 + fill_win32_filefunc64W @113 + + unzOpen64 @120 + unzOpen2_64 @121 + unzGetGlobalInfo64 @122 + unzGetCurrentFileInfo64 @124 + unzGetCurrentFileZStreamPos64 @125 + unztell64 @126 + unzGetFilePos64 @127 + unzGoToFilePos64 @128 + + zipOpen64 @130 + zipOpen2_64 @131 + zipOpenNewFileInZip64 @132 + zipOpenNewFileInZip2_64 @133 + zipOpenNewFileInZip3_64 @134 + zipOpenNewFileInZip4_64 @135 + zipCloseFileInZipRaw64 @136 + +; zlib1 v1.2.4 added: + adler32_combine @140 + crc32_combine @142 + deflateSetHeader @144 + deflateTune @145 + gzbuffer @146 + gzclose_r @147 + gzclose_w @148 + gzdirect @149 + gzoffset @150 + inflateGetHeader @156 + inflateMark @157 + inflatePrime @158 + inflateReset2 @159 + inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.sln b/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.sln new file mode 100644 index 00000000..6f6ffd5e --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.sln @@ -0,0 +1,135 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.Build.0 = Debug|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.Build.0 = Release|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.Build.0 = Debug|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.Build.0 = Release|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.Build.0 = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.Build.0 = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj b/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj new file mode 100644 index 00000000..6ff9ddb0 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj @@ -0,0 +1,657 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {8FD826F8-3739-44E6-8CC8-997122E53B8D} + + + + DynamicLibrary + false + true + + + DynamicLibrary + false + true + + + DynamicLibrary + false + + + DynamicLibrary + false + true + + + DynamicLibrary + false + true + + + DynamicLibrary + false + + + DynamicLibrary + false + true + + + DynamicLibrary + false + true + + + DynamicLibrary + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + true + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + true + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + true + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + zlibwapid + zlibwapi + zlibwapi + zlibwapid + zlibwapi + zlibwapi + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + + + MultiThreadedDebug + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + true + .\zlibvc.def + true + true + Windows + false + + + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + true + false + .\zlibvc.def + true + Windows + false + + + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + true + false + .\zlibvc.def + true + Windows + false + + + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + true + .\zlibvc.def + true + true + Windows + MachineX64 + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + true + false + .\zlibvc.def + true + Windows + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + true + false + .\zlibvc.def + true + Windows + MachineX64 + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj.filters b/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj.filters new file mode 100644 index 00000000..180b71cd --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc10/zlibvc.vcxproj.filters @@ -0,0 +1,118 @@ + + + + + {07934a85-8b61-443d-a0ee-b2eedb74f3cd} + cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90 + + + {1d99675b-433d-4a21-9e50-ed4ab8b19762} + h;hpp;hxx;hm;inl;fi;fd + + + {431c0958-fa71-44d0-9084-2d19d100c0cc} + ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc11/miniunz.vcxproj b/zlib-1.2.11/contrib/vstudio/vc11/miniunz.vcxproj new file mode 100644 index 00000000..8f9f20bd --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc11/miniunz.vcxproj @@ -0,0 +1,314 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694382A} + Win32Proj + + + + Application + MultiByte + v110 + + + Application + Unicode + v110 + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + v110 + + + Application + MultiByte + v110 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + true + false + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + false + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + true + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + true + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + false + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc11/minizip.vcxproj b/zlib-1.2.11/contrib/vstudio/vc11/minizip.vcxproj new file mode 100644 index 00000000..c93d9e6f --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc11/minizip.vcxproj @@ -0,0 +1,311 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} + Win32Proj + + + + Application + MultiByte + v110 + + + Application + Unicode + v110 + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + v110 + + + Application + MultiByte + v110 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + true + false + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + false + x64\$(Configuration)\ + x64\$(Configuration)\ + true + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + true + false + x64\$(Configuration)\ + x64\$(Configuration)\ + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc11/testzlib.vcxproj b/zlib-1.2.11/contrib/vstudio/vc11/testzlib.vcxproj new file mode 100644 index 00000000..6d559540 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc11/testzlib.vcxproj @@ -0,0 +1,426 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} + testzlib + Win32Proj + + + + Application + MultiByte + true + v110 + + + Application + MultiByte + true + v110 + + + Application + Unicode + v110 + + + Application + MultiByte + true + + + Application + MultiByte + true + + + Application + MultiByte + + + Application + true + v110 + + + Application + true + v110 + + + Application + v110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + true + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + true + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + %(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc11/testzlibdll.vcxproj b/zlib-1.2.11/contrib/vstudio/vc11/testzlibdll.vcxproj new file mode 100644 index 00000000..9f20c78f --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc11/testzlibdll.vcxproj @@ -0,0 +1,314 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694366A} + Win32Proj + + + + Application + MultiByte + v110 + + + Application + Unicode + v110 + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + v110 + + + Application + MultiByte + v110 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + true + false + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + false + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + true + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + true + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + false + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc11/zlib.rc b/zlib-1.2.11/contrib/vstudio/vc11/zlib.rc new file mode 100644 index 00000000..fee177a7 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc11/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" + VALUE "FileVersion", "1.2.11\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/zlib-1.2.11/contrib/vstudio/vc11/zlibstat.vcxproj b/zlib-1.2.11/contrib/vstudio/vc11/zlibstat.vcxproj new file mode 100644 index 00000000..806b76a8 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc11/zlibstat.vcxproj @@ -0,0 +1,464 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} + + + + StaticLibrary + false + v110 + + + StaticLibrary + false + v110 + + + StaticLibrary + false + v110 + Unicode + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + v110 + + + StaticLibrary + false + v110 + + + StaticLibrary + false + v110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.def b/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.def new file mode 100644 index 00000000..54e683d9 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.def @@ -0,0 +1,153 @@ +LIBRARY +; zlib data compression and ZIP file I/O library + +VERSION 1.2 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + inflateCopy @42 + inflateBackInit_ @43 + inflateBack @44 + inflateBackEnd @45 + compressBound @46 + deflateBound @47 + gzclearerr @48 + gzungetc @49 + zlibCompileFlags @50 + deflatePrime @51 + deflatePending @52 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unzOpenCurrentFile3 @69 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + unzOpen2 @77 + unzOpenCurrentFile2 @78 + unzOpenCurrentFilePassword @79 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 + zipOpenNewFileInZip2 @86 + zipCloseFileInZipRaw @87 + zipOpen2 @88 + zipOpenNewFileInZip3 @89 + + unzGetFilePos @100 + unzGoToFilePos @101 + + fill_win32_filefunc @110 + +; zlibwapi v1.2.4 added: + fill_win32_filefunc64 @111 + fill_win32_filefunc64A @112 + fill_win32_filefunc64W @113 + + unzOpen64 @120 + unzOpen2_64 @121 + unzGetGlobalInfo64 @122 + unzGetCurrentFileInfo64 @124 + unzGetCurrentFileZStreamPos64 @125 + unztell64 @126 + unzGetFilePos64 @127 + unzGoToFilePos64 @128 + + zipOpen64 @130 + zipOpen2_64 @131 + zipOpenNewFileInZip64 @132 + zipOpenNewFileInZip2_64 @133 + zipOpenNewFileInZip3_64 @134 + zipOpenNewFileInZip4_64 @135 + zipCloseFileInZipRaw64 @136 + +; zlib1 v1.2.4 added: + adler32_combine @140 + crc32_combine @142 + deflateSetHeader @144 + deflateTune @145 + gzbuffer @146 + gzclose_r @147 + gzclose_w @148 + gzdirect @149 + gzoffset @150 + inflateGetHeader @156 + inflateMark @157 + inflatePrime @158 + inflateReset2 @159 + inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.sln b/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.sln new file mode 100644 index 00000000..9fcbafdd --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.sln @@ -0,0 +1,117 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.vcxproj b/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.vcxproj new file mode 100644 index 00000000..c65b95fd --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc11/zlibvc.vcxproj @@ -0,0 +1,688 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {8FD826F8-3739-44E6-8CC8-997122E53B8D} + + + + DynamicLibrary + false + true + v110 + + + DynamicLibrary + false + true + v110 + + + DynamicLibrary + false + v110 + Unicode + + + DynamicLibrary + false + true + + + DynamicLibrary + false + true + + + DynamicLibrary + false + + + DynamicLibrary + false + true + v110 + + + DynamicLibrary + false + true + v110 + + + DynamicLibrary + false + v110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + true + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + true + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + true + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\contrib\masmx64 +bld_ml64.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc12/miniunz.vcxproj b/zlib-1.2.11/contrib/vstudio/vc12/miniunz.vcxproj new file mode 100644 index 00000000..d88ac7fc --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc12/miniunz.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694382A} + Win32Proj + + + + Application + MultiByte + v120 + + + Application + Unicode + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + true + false + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + false + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + true + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + true + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + false + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc12/minizip.vcxproj b/zlib-1.2.11/contrib/vstudio/vc12/minizip.vcxproj new file mode 100644 index 00000000..f1f239c9 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc12/minizip.vcxproj @@ -0,0 +1,313 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} + Win32Proj + + + + Application + MultiByte + v120 + + + Application + Unicode + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + true + false + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + false + x64\$(Configuration)\ + x64\$(Configuration)\ + true + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + true + false + x64\$(Configuration)\ + x64\$(Configuration)\ + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc12/testzlib.vcxproj b/zlib-1.2.11/contrib/vstudio/vc12/testzlib.vcxproj new file mode 100644 index 00000000..64b2cbe3 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc12/testzlib.vcxproj @@ -0,0 +1,430 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} + testzlib + Win32Proj + + + + Application + MultiByte + true + v120 + + + Application + MultiByte + true + v120 + + + Application + Unicode + v120 + + + Application + MultiByte + true + v120 + + + Application + MultiByte + true + v120 + + + Application + MultiByte + v120 + + + Application + true + v120 + + + Application + true + v120 + + + Application + v120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + true + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + true + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + false + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + %(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc12/testzlibdll.vcxproj b/zlib-1.2.11/contrib/vstudio/vc12/testzlibdll.vcxproj new file mode 100644 index 00000000..c66573a8 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc12/testzlibdll.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694366A} + Win32Proj + + + + Application + MultiByte + v120 + + + Application + Unicode + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + true + false + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + false + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + true + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + true + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + false + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc12/zlib.rc b/zlib-1.2.11/contrib/vstudio/vc12/zlib.rc new file mode 100644 index 00000000..c4e4b016 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc12/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" + VALUE "FileVersion", "1.2.11\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/zlib-1.2.11/contrib/vstudio/vc12/zlibstat.vcxproj b/zlib-1.2.11/contrib/vstudio/vc12/zlibstat.vcxproj new file mode 100644 index 00000000..3fdee7c5 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc12/zlibstat.vcxproj @@ -0,0 +1,467 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} + + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + Unicode + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.def b/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.def new file mode 100644 index 00000000..54e683d9 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.def @@ -0,0 +1,153 @@ +LIBRARY +; zlib data compression and ZIP file I/O library + +VERSION 1.2 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + inflateCopy @42 + inflateBackInit_ @43 + inflateBack @44 + inflateBackEnd @45 + compressBound @46 + deflateBound @47 + gzclearerr @48 + gzungetc @49 + zlibCompileFlags @50 + deflatePrime @51 + deflatePending @52 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unzOpenCurrentFile3 @69 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + unzOpen2 @77 + unzOpenCurrentFile2 @78 + unzOpenCurrentFilePassword @79 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 + zipOpenNewFileInZip2 @86 + zipCloseFileInZipRaw @87 + zipOpen2 @88 + zipOpenNewFileInZip3 @89 + + unzGetFilePos @100 + unzGoToFilePos @101 + + fill_win32_filefunc @110 + +; zlibwapi v1.2.4 added: + fill_win32_filefunc64 @111 + fill_win32_filefunc64A @112 + fill_win32_filefunc64W @113 + + unzOpen64 @120 + unzOpen2_64 @121 + unzGetGlobalInfo64 @122 + unzGetCurrentFileInfo64 @124 + unzGetCurrentFileZStreamPos64 @125 + unztell64 @126 + unzGetFilePos64 @127 + unzGoToFilePos64 @128 + + zipOpen64 @130 + zipOpen2_64 @131 + zipOpenNewFileInZip64 @132 + zipOpenNewFileInZip2_64 @133 + zipOpenNewFileInZip3_64 @134 + zipOpenNewFileInZip4_64 @135 + zipCloseFileInZipRaw64 @136 + +; zlib1 v1.2.4 added: + adler32_combine @140 + crc32_combine @142 + deflateSetHeader @144 + deflateTune @145 + gzbuffer @146 + gzclose_r @147 + gzclose_w @148 + gzdirect @149 + gzoffset @150 + inflateGetHeader @156 + inflateMark @157 + inflatePrime @158 + inflateReset2 @159 + inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.sln b/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.sln new file mode 100644 index 00000000..dcda2298 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.sln @@ -0,0 +1,119 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.vcxproj b/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.vcxproj new file mode 100644 index 00000000..ab2b6c36 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc12/zlibvc.vcxproj @@ -0,0 +1,692 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {8FD826F8-3739-44E6-8CC8-997122E53B8D} + + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + v120 + Unicode + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + v120 + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + v120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + true + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + true + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + true + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + false + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\contrib\masmx64 +bld_ml64.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc14/miniunz.vcxproj b/zlib-1.2.11/contrib/vstudio/vc14/miniunz.vcxproj new file mode 100644 index 00000000..9b5c0758 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc14/miniunz.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694382A} + Win32Proj + + + + Application + MultiByte + v140 + + + Application + Unicode + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + true + false + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + false + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + true + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + true + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + false + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc14/minizip.vcxproj b/zlib-1.2.11/contrib/vstudio/vc14/minizip.vcxproj new file mode 100644 index 00000000..968a410a --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc14/minizip.vcxproj @@ -0,0 +1,313 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} + Win32Proj + + + + Application + MultiByte + v140 + + + Application + Unicode + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + true + false + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + false + x64\$(Configuration)\ + x64\$(Configuration)\ + true + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + true + false + x64\$(Configuration)\ + x64\$(Configuration)\ + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc14/testzlib.vcxproj b/zlib-1.2.11/contrib/vstudio/vc14/testzlib.vcxproj new file mode 100644 index 00000000..2c371252 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc14/testzlib.vcxproj @@ -0,0 +1,430 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} + testzlib + Win32Proj + + + + Application + MultiByte + true + v140 + + + Application + MultiByte + true + v140 + + + Application + Unicode + v140 + + + Application + MultiByte + true + v140 + + + Application + MultiByte + true + v140 + + + Application + MultiByte + v140 + + + Application + true + v140 + + + Application + true + v140 + + + Application + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + true + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + true + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + false + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + %(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc14/testzlibdll.vcxproj b/zlib-1.2.11/contrib/vstudio/vc14/testzlibdll.vcxproj new file mode 100644 index 00000000..d87474de --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc14/testzlibdll.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694366A} + Win32Proj + + + + Application + MultiByte + v140 + + + Application + Unicode + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + true + false + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + false + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + true + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + true + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + false + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc14/zlib.rc b/zlib-1.2.11/contrib/vstudio/vc14/zlib.rc new file mode 100644 index 00000000..c4e4b016 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc14/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" + VALUE "FileVersion", "1.2.11\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/zlib-1.2.11/contrib/vstudio/vc14/zlibstat.vcxproj b/zlib-1.2.11/contrib/vstudio/vc14/zlibstat.vcxproj new file mode 100644 index 00000000..3e4b9863 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc14/zlibstat.vcxproj @@ -0,0 +1,467 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} + + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + Unicode + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.def b/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.def new file mode 100644 index 00000000..54e683d9 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.def @@ -0,0 +1,153 @@ +LIBRARY +; zlib data compression and ZIP file I/O library + +VERSION 1.2 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + inflateCopy @42 + inflateBackInit_ @43 + inflateBack @44 + inflateBackEnd @45 + compressBound @46 + deflateBound @47 + gzclearerr @48 + gzungetc @49 + zlibCompileFlags @50 + deflatePrime @51 + deflatePending @52 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unzOpenCurrentFile3 @69 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + unzOpen2 @77 + unzOpenCurrentFile2 @78 + unzOpenCurrentFilePassword @79 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 + zipOpenNewFileInZip2 @86 + zipCloseFileInZipRaw @87 + zipOpen2 @88 + zipOpenNewFileInZip3 @89 + + unzGetFilePos @100 + unzGoToFilePos @101 + + fill_win32_filefunc @110 + +; zlibwapi v1.2.4 added: + fill_win32_filefunc64 @111 + fill_win32_filefunc64A @112 + fill_win32_filefunc64W @113 + + unzOpen64 @120 + unzOpen2_64 @121 + unzGetGlobalInfo64 @122 + unzGetCurrentFileInfo64 @124 + unzGetCurrentFileZStreamPos64 @125 + unztell64 @126 + unzGetFilePos64 @127 + unzGoToFilePos64 @128 + + zipOpen64 @130 + zipOpen2_64 @131 + zipOpenNewFileInZip64 @132 + zipOpenNewFileInZip2_64 @133 + zipOpenNewFileInZip3_64 @134 + zipOpenNewFileInZip4_64 @135 + zipCloseFileInZipRaw64 @136 + +; zlib1 v1.2.4 added: + adler32_combine @140 + crc32_combine @142 + deflateSetHeader @144 + deflateTune @145 + gzbuffer @146 + gzclose_r @147 + gzclose_w @148 + gzdirect @149 + gzoffset @150 + inflateGetHeader @156 + inflateMark @157 + inflatePrime @158 + inflateReset2 @159 + inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.sln b/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.sln new file mode 100644 index 00000000..6f4a1076 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.sln @@ -0,0 +1,119 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.vcxproj b/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.vcxproj new file mode 100644 index 00000000..f8f673cb --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc14/zlibvc.vcxproj @@ -0,0 +1,692 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {8FD826F8-3739-44E6-8CC8-997122E53B8D} + + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + v140 + Unicode + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + true + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + true + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + true + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + false + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\contrib\masmx64 +bld_ml64.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/zlib-1.2.11/contrib/vstudio/vc9/miniunz.vcproj b/zlib-1.2.11/contrib/vstudio/vc9/miniunz.vcproj new file mode 100644 index 00000000..7da32b91 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc9/miniunz.vcproj @@ -0,0 +1,565 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zlib-1.2.11/contrib/vstudio/vc9/minizip.vcproj b/zlib-1.2.11/contrib/vstudio/vc9/minizip.vcproj new file mode 100644 index 00000000..e57e07d9 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc9/minizip.vcproj @@ -0,0 +1,562 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zlib-1.2.11/contrib/vstudio/vc9/testzlib.vcproj b/zlib-1.2.11/contrib/vstudio/vc9/testzlib.vcproj new file mode 100644 index 00000000..9cb0bf87 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc9/testzlib.vcproj @@ -0,0 +1,852 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zlib-1.2.11/contrib/vstudio/vc9/testzlibdll.vcproj b/zlib-1.2.11/contrib/vstudio/vc9/testzlibdll.vcproj new file mode 100644 index 00000000..b1ddde05 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc9/testzlibdll.vcproj @@ -0,0 +1,565 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zlib-1.2.11/contrib/vstudio/vc9/zlib.rc b/zlib-1.2.11/contrib/vstudio/vc9/zlib.rc new file mode 100644 index 00000000..fee177a7 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc9/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" + VALUE "FileVersion", "1.2.11\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/zlib-1.2.11/contrib/vstudio/vc9/zlibstat.vcproj b/zlib-1.2.11/contrib/vstudio/vc9/zlibstat.vcproj new file mode 100644 index 00000000..61c76c7c --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc9/zlibstat.vcproj @@ -0,0 +1,835 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.def b/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.def new file mode 100644 index 00000000..54e683d9 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.def @@ -0,0 +1,153 @@ +LIBRARY +; zlib data compression and ZIP file I/O library + +VERSION 1.2 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + inflateCopy @42 + inflateBackInit_ @43 + inflateBack @44 + inflateBackEnd @45 + compressBound @46 + deflateBound @47 + gzclearerr @48 + gzungetc @49 + zlibCompileFlags @50 + deflatePrime @51 + deflatePending @52 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unzOpenCurrentFile3 @69 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + unzOpen2 @77 + unzOpenCurrentFile2 @78 + unzOpenCurrentFilePassword @79 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 + zipOpenNewFileInZip2 @86 + zipCloseFileInZipRaw @87 + zipOpen2 @88 + zipOpenNewFileInZip3 @89 + + unzGetFilePos @100 + unzGoToFilePos @101 + + fill_win32_filefunc @110 + +; zlibwapi v1.2.4 added: + fill_win32_filefunc64 @111 + fill_win32_filefunc64A @112 + fill_win32_filefunc64W @113 + + unzOpen64 @120 + unzOpen2_64 @121 + unzGetGlobalInfo64 @122 + unzGetCurrentFileInfo64 @124 + unzGetCurrentFileZStreamPos64 @125 + unztell64 @126 + unzGetFilePos64 @127 + unzGoToFilePos64 @128 + + zipOpen64 @130 + zipOpen2_64 @131 + zipOpenNewFileInZip64 @132 + zipOpenNewFileInZip2_64 @133 + zipOpenNewFileInZip3_64 @134 + zipOpenNewFileInZip4_64 @135 + zipCloseFileInZipRaw64 @136 + +; zlib1 v1.2.4 added: + adler32_combine @140 + crc32_combine @142 + deflateSetHeader @144 + deflateTune @145 + gzbuffer @146 + gzclose_r @147 + gzclose_w @148 + gzdirect @149 + gzoffset @150 + inflateGetHeader @156 + inflateMark @157 + inflatePrime @158 + inflateReset2 @159 + inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.sln b/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.sln new file mode 100644 index 00000000..b4829671 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.sln @@ -0,0 +1,144 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestZlibDll", "testzlibdll.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" + ProjectSection(ProjectDependencies) = postProject + {8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" + ProjectSection(ProjectDependencies) = postProject + {8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" + ProjectSection(ProjectDependencies) = postProject + {8FD826F8-3739-44E6-8CC8-997122E53B8D} = {8FD826F8-3739-44E6-8CC8-997122E53B8D} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.Build.0 = Debug|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.Build.0 = Release|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.Build.0 = Debug|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.Build.0 = Release|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = ReleaseWithoutAsm|Itanium + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.Build.0 = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.Build.0 = Debug|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.Build.0 = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.Build.0 = Debug|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.Build.0 = Release|Itanium + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.vcproj b/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.vcproj new file mode 100644 index 00000000..c9a89471 --- /dev/null +++ b/zlib-1.2.11/contrib/vstudio/vc9/zlibvc.vcproj @@ -0,0 +1,1156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zlib-1.2.11/crc32.c b/zlib-1.2.11/crc32.c new file mode 100644 index 00000000..9580440c --- /dev/null +++ b/zlib-1.2.11/crc32.c @@ -0,0 +1,442 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + + DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +/* Definitions for doing the crc four data bytes at a time. */ +#if !defined(NOBYFOUR) && defined(Z_U4) +# define BYFOUR +#endif +#ifdef BYFOUR + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, z_size_t)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, z_size_t)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); + + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local z_crc_t FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const z_crc_t FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + z_crc_t c; + int n, k; + z_crc_t poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0; + for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) + poly |= (z_crc_t)1 << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (z_crc_t)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = ZSWAP32(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = ZSWAP32(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const z_crc_t FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const z_crc_t FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", + (unsigned long)(table[n]), + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const z_crc_t FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const z_crc_t FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32_z(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + z_crc_t endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + return crc32_z(crc, buf, len); +} + +#ifdef BYFOUR + +/* + This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit + integer pointer type. This violates the strict aliasing rule, where a + compiler can assume, for optimization purposes, that two pointers to + fundamentally different types won't ever point to the same memory. This can + manifest as a problem only if one of the pointers is written to. This code + only reads from those pointers. So long as this code remains isolated in + this compilation unit, there won't be a problem. For this reason, this code + should not be copied and pasted into a compilation unit in which other code + writes to the buffer that is passed to these routines. + */ + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + register z_crc_t c; + register const z_crc_t FAR *buf4; + + c = (z_crc_t)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *buf4++; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + register z_crc_t c; + register const z_crc_t FAR *buf4; + + c = ZSWAP32((z_crc_t)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(ZSWAP32(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} diff --git a/zlib-1.2.11/crc32.h b/zlib-1.2.11/crc32.h new file mode 100644 index 00000000..9e0c7781 --- /dev/null +++ b/zlib-1.2.11/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const z_crc_t FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/zlib-1.2.11/deflate.c b/zlib-1.2.11/deflate.c new file mode 100644 index 00000000..1ec76144 --- /dev/null +++ b/zlib-1.2.11/deflate.c @@ -0,0 +1,2163 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in http://tools.ietf.org/html/rfc1951 + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local int deflateStateCheck OF((z_streamp strm)); +local void slide_hash OF((deflate_state *s)); +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +#ifndef FASTEST +local block_state deflate_slow OF((deflate_state *s, int flush)); +#endif +local block_state deflate_rle OF((deflate_state *s, int flush)); +local block_state deflate_huff OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local unsigned read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV +# pragma message("Assembler code may have bugs -- use at your own risk") + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef ZLIB_DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +#ifdef FASTEST +local const config configuration_table[2] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ +#else +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ +#endif + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ +#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to UPDATE_HASH are made with consecutive input + * characters, so that a running hash key can be computed from the previous + * key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to INSERT_STRING are made with consecutive input + * characters and the first MIN_MATCH bytes of str are valid (except for + * the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* =========================================================================== + * Slide the hash table when sliding the window down (could be avoided with 32 + * bit values at the expense of memory usage). We slide even when level == 0 to + * keep the hash table consistent if we switch back to level > 0 later. + */ +local void slide_hash(s) + deflate_state *s; +{ + unsigned n, m; + Posf *p; + uInt wsize = s->w_size; + + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + } while (--n); + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif +} + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int wrap = 1; + static const char my_version[] = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; + } +#ifdef GZIP + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } +#endif + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { + return Z_STREAM_ERROR; + } + if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + s->status = INIT_STATE; /* to pass state test in deflateReset() */ + + s->wrap = wrap; + s->gzhead = Z_NULL; + s->w_bits = (uInt)windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = (uInt)memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->high_water = 0; /* nothing written to s->window yet */ + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + s->status = FINISH_STATE; + strm->msg = ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= + * Check for a valid deflate stream state. Return 0 if ok, 1 if not. + */ +local int deflateStateCheck (strm) + z_streamp strm; +{ + deflate_state *s; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + s = strm->state; + if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && +#ifdef GZIP + s->status != GZIP_STATE && +#endif + s->status != EXTRA_STATE && + s->status != NAME_STATE && + s->status != COMMENT_STATE && + s->status != HCRC_STATE && + s->status != BUSY_STATE && + s->status != FINISH_STATE)) + return 1; + return 0; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt str, n; + int wrap; + unsigned avail; + z_const unsigned char *next; + + if (deflateStateCheck(strm) || dictionary == Z_NULL) + return Z_STREAM_ERROR; + s = strm->state; + wrap = s->wrap; + if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) + return Z_STREAM_ERROR; + + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap == 1) + strm->adler = adler32(strm->adler, dictionary, dictLength); + s->wrap = 0; /* avoid computing Adler-32 in read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s->w_size) { + if (wrap == 0) { /* already empty otherwise */ + CLEAR_HASH(s); + s->strstart = 0; + s->block_start = 0L; + s->insert = 0; + } + dictionary += dictLength - s->w_size; /* use the tail */ + dictLength = s->w_size; + } + + /* insert dictionary into window and hash */ + avail = strm->avail_in; + next = strm->next_in; + strm->avail_in = dictLength; + strm->next_in = (z_const Bytef *)dictionary; + fill_window(s); + while (s->lookahead >= MIN_MATCH) { + str = s->strstart; + n = s->lookahead - (MIN_MATCH-1); + do { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + } while (--n); + s->strstart = str; + s->lookahead = MIN_MATCH-1; + fill_window(s); + } + s->strstart += s->lookahead; + s->block_start = (long)s->strstart; + s->insert = s->lookahead; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + strm->next_in = next; + strm->avail_in = avail; + s->wrap = wrap; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) + z_streamp strm; + Bytef *dictionary; + uInt *dictLength; +{ + deflate_state *s; + uInt len; + + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + s = strm->state; + len = s->strstart + s->lookahead; + if (len > s->w_size) + len = s->w_size; + if (dictionary != Z_NULL && len) + zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); + if (dictLength != Z_NULL) + *dictLength = len; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateResetKeep (strm) + z_streamp strm; +{ + deflate_state *s; + + if (deflateStateCheck(strm)) { + return Z_STREAM_ERROR; + } + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->wrap < 0) { + s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ + } + s->status = +#ifdef GZIP + s->wrap == 2 ? GZIP_STATE : +#endif + s->wrap ? INIT_STATE : BUSY_STATE; + strm->adler = +#ifdef GZIP + s->wrap == 2 ? crc32(0L, Z_NULL, 0) : +#endif + adler32(0L, Z_NULL, 0); + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + int ret; + + ret = deflateResetKeep(strm); + if (ret == Z_OK) + lm_init(strm->state); + return ret; +} + +/* ========================================================================= */ +int ZEXPORT deflateSetHeader (strm, head) + z_streamp strm; + gz_headerp head; +{ + if (deflateStateCheck(strm) || strm->state->wrap != 2) + return Z_STREAM_ERROR; + strm->state->gzhead = head; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePending (strm, pending, bits) + unsigned *pending; + int *bits; + z_streamp strm; +{ + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + if (pending != Z_NULL) + *pending = strm->state->pending; + if (bits != Z_NULL) + *bits = strm->state->bi_valid; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflatePrime (strm, bits, value) + z_streamp strm; + int bits; + int value; +{ + deflate_state *s; + int put; + + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + s = strm->state; + if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) + return Z_BUF_ERROR; + do { + put = Buf_size - s->bi_valid; + if (put > bits) + put = bits; + s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); + s->bi_valid += put; + _tr_flush_bits(s); + value >>= put; + bits -= put; + } while (bits); + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + s = strm->state; + +#ifdef FASTEST + if (level != 0) level = 1; +#else + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#endif + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if ((strategy != s->strategy || func != configuration_table[level].func) && + s->high_water) { + /* Flush the last buffer: */ + int err = deflate(strm, Z_BLOCK); + if (err == Z_STREAM_ERROR) + return err; + if (strm->avail_out == 0) + return Z_BUF_ERROR; + } + if (s->level != level) { + if (s->level == 0 && s->matches != 0) { + if (s->matches == 1) + slide_hash(s); + else + CLEAR_HASH(s); + s->matches = 0; + } + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) + z_streamp strm; + int good_length; + int max_lazy; + int nice_length; + int max_chain; +{ + deflate_state *s; + + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + s = strm->state; + s->good_match = (uInt)good_length; + s->max_lazy_match = (uInt)max_lazy; + s->nice_match = nice_length; + s->max_chain_length = (uInt)max_chain; + return Z_OK; +} + +/* ========================================================================= + * For the default windowBits of 15 and memLevel of 8, this function returns + * a close to exact, as well as small, upper bound on the compressed size. + * They are coded as constants here for a reason--if the #define's are + * changed, then this function needs to be changed as well. The return + * value for 15 and 8 only works for those exact settings. + * + * For any setting other than those defaults for windowBits and memLevel, + * the value returned is a conservative worst case for the maximum expansion + * resulting from using fixed blocks instead of stored blocks, which deflate + * can emit on compressed data for some combinations of the parameters. + * + * This function could be more sophisticated to provide closer upper bounds for + * every combination of windowBits and memLevel. But even the conservative + * upper bound of about 14% expansion does not seem onerous for output buffer + * allocation. + */ +uLong ZEXPORT deflateBound(strm, sourceLen) + z_streamp strm; + uLong sourceLen; +{ + deflate_state *s; + uLong complen, wraplen; + + /* conservative upper bound for compressed data */ + complen = sourceLen + + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; + + /* if can't get parameters, return conservative bound plus zlib wrapper */ + if (deflateStateCheck(strm)) + return complen + 6; + + /* compute wrapper length */ + s = strm->state; + switch (s->wrap) { + case 0: /* raw deflate */ + wraplen = 0; + break; + case 1: /* zlib wrapper */ + wraplen = 6 + (s->strstart ? 4 : 0); + break; +#ifdef GZIP + case 2: /* gzip wrapper */ + wraplen = 18; + if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + Bytef *str; + if (s->gzhead->extra != Z_NULL) + wraplen += 2 + s->gzhead->extra_len; + str = s->gzhead->name; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + str = s->gzhead->comment; + if (str != Z_NULL) + do { + wraplen++; + } while (*str++); + if (s->gzhead->hcrc) + wraplen += 2; + } + break; +#endif + default: /* for compiler happiness */ + wraplen = 6; + } + + /* if not default parameters, return conservative bound */ + if (s->w_bits != 15 || s->hash_bits != 8 + 7) + return complen + wraplen; + + /* default settings: return tight bound for that case */ + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + + (sourceLen >> 25) + 13 - 6 + wraplen; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output, except for + * some deflate_stored() output, goes through this function so some + * applications may wish to modify it to avoid allocating a large + * strm->next_out buffer and copying into it. (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len; + deflate_state *s = strm->state; + + _tr_flush_bits(s); + len = s->pending; + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, s->pending_out, len); + strm->next_out += len; + s->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + s->pending -= len; + if (s->pending == 0) { + s->pending_out = s->pending_buf; + } +} + +/* =========================================================================== + * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. + */ +#define HCRC_UPDATE(beg) \ + do { \ + if (s->gzhead->hcrc && s->pending > (beg)) \ + strm->adler = crc32(strm->adler, s->pending_buf + (beg), \ + s->pending - (beg)); \ + } while (0) + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->avail_in != 0 && strm->next_in == Z_NULL) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + old_flush = s->last_flush; + s->last_flush = flush; + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Write the header */ + if (s->status == INIT_STATE) { + /* zlib header */ + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#ifdef GZIP + if (s->status == GZIP_STATE) { + /* gzip header */ + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex; + while (s->pending + left > s->pending_buf_size) { + uInt copy = s->pending_buf_size - s->pending; + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, copy); + s->pending = s->pending_buf_size; + HCRC_UPDATE(beg); + s->gzindex += copy; + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + left -= copy; + } + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, left); + s->pending += left; + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + int val; + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + int val; + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + } + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) { + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + } + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#endif + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = s->level == 0 ? deflate_stored(s, flush) : + s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + if (s->lookahead == 0) { + s->strstart = 0; + s->block_start = 0L; + s->insert = 0; + } + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + + if (flush != Z_FINISH) return Z_OK; + if (s->wrap <= 0) return Z_STREAM_END; + + /* Write the trailer */ +#ifdef GZIP + if (s->wrap == 2) { + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); + put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); + put_byte(s, (Byte)(strm->total_in & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); + put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); + } + else +#endif + { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; + + status = strm->state->status; + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (deflateStateCheck(source) || dest == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif /* MAXSEG_64K */ +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local unsigned read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + zmemcpy(buf, strm->next_in, len); + if (strm->state->wrap == 1) { + strm->adler = adler32(strm->adler, buf, len); + } +#ifdef GZIP + else if (strm->state->wrap == 2) { + strm->adler = crc32(strm->adler, buf, len); + } +#endif + strm->next_in += len; + strm->total_in += len; + + return len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->insert = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifndef FASTEST +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +#endif +} + +#ifndef FASTEST +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = (int)s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} +#endif /* ASMV */ + +#else /* FASTEST */ + +/* --------------------------------------------------------------------------- + * Optimized version for FASTEST only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; +} + +#endif /* FASTEST */ + +#ifdef ZLIB_DEBUG + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif /* ZLIB_DEBUG */ + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + unsigned n; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (sizeof(int) <= 2) { + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if + * strstart == 0 && lookahead == 1 (input done a byte at time) + */ + more--; + } + } + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + slide_hash(s); + more += wsize; + } + if (s->strm->avail_in == 0) break; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead + s->insert >= MIN_MATCH) { + uInt str = s->strstart - s->insert; + s->ins_h = s->window[str]; + UPDATE_HASH(s, s->ins_h, s->window[str + 1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + while (s->insert) { + UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST + s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif + s->head[s->ins_h] = (Pos)str; + str++; + s->insert--; + if (s->lookahead + s->insert < MIN_MATCH) + break; + } + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); + + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. + */ + if (s->high_water < s->window_size) { + ulg curr = s->strstart + (ulg)(s->lookahead); + ulg init; + + if (s->high_water < curr) { + /* Previous high water mark below current data -- zero WIN_INIT + * bytes or up to end of window, whichever is less. + */ + init = s->window_size - curr; + if (init > WIN_INIT) + init = WIN_INIT; + zmemzero(s->window + curr, (unsigned)init); + s->high_water = curr + init; + } + else if (s->high_water < (ulg)curr + WIN_INIT) { + /* High water mark at or above current data, but below current data + * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up + * to end of window, whichever is less. + */ + init = (ulg)curr + WIN_INIT - s->high_water; + if (init > s->window_size - s->high_water) + init = s->window_size - s->high_water; + zmemzero(s->window + s->high_water, (unsigned)init); + s->high_water += init; + } + } + + Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, + "not enough room for search"); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, last) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (last)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, last) { \ + FLUSH_BLOCK_ONLY(s, last); \ + if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ +} + +/* Maximum stored block length in deflate format (not including header). */ +#define MAX_STORED 65535 + +/* Minimum of a and b. */ +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * + * In case deflateParams() is used to later switch to a non-zero compression + * level, s->matches (otherwise unused when storing) keeps track of the number + * of hash table slides to perform. If s->matches is 1, then one hash table + * slide will be done when switching. If s->matches is 2, the maximum value + * allowed here, then the hash table will be cleared, since two or more slides + * is the same as a clear. + * + * deflate_stored() is written to minimize the number of times an input byte is + * copied. It is most efficient with large input and output buffers, which + * maximizes the opportunites to have a single copy from next_in to next_out. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Smallest worthy block size when not flushing or finishing. By default + * this is 32K. This can be as small as 507 bytes for memLevel == 1. For + * large input and output buffers, the stored block size will be larger. + */ + unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); + + /* Copy as many min_block or larger stored blocks directly to next_out as + * possible. If flushing, copy the remaining available input to next_out as + * stored blocks, if there is enough space. + */ + unsigned len, left, have, last = 0; + unsigned used = s->strm->avail_in; + do { + /* Set len to the maximum size block that we can copy directly with the + * available input data and output space. Set left to how much of that + * would be copied from what's left in the window. + */ + len = MAX_STORED; /* maximum deflate stored block length */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + if (s->strm->avail_out < have) /* need room for header */ + break; + /* maximum stored block length that will fit in avail_out: */ + have = s->strm->avail_out - have; + left = s->strstart - s->block_start; /* bytes left in window */ + if (len > (ulg)left + s->strm->avail_in) + len = left + s->strm->avail_in; /* limit len to the input */ + if (len > have) + len = have; /* limit len to the output */ + + /* If the stored block would be less than min_block in length, or if + * unable to copy all of the available input when flushing, then try + * copying to the window and the pending buffer instead. Also don't + * write an empty block when flushing -- deflate() does that. + */ + if (len < min_block && ((len == 0 && flush != Z_FINISH) || + flush == Z_NO_FLUSH || + len != left + s->strm->avail_in)) + break; + + /* Make a dummy stored block in pending to get the header bytes, + * including any pending bits. This also updates the debugging counts. + */ + last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; + _tr_stored_block(s, (char *)0, 0L, last); + + /* Replace the lengths in the dummy stored block with len. */ + s->pending_buf[s->pending - 4] = len; + s->pending_buf[s->pending - 3] = len >> 8; + s->pending_buf[s->pending - 2] = ~len; + s->pending_buf[s->pending - 1] = ~len >> 8; + + /* Write the stored block header bytes. */ + flush_pending(s->strm); + +#ifdef ZLIB_DEBUG + /* Update debugging counts for the data about to be copied. */ + s->compressed_len += len << 3; + s->bits_sent += len << 3; +#endif + + /* Copy uncompressed bytes from the window to next_out. */ + if (left) { + if (left > len) + left = len; + zmemcpy(s->strm->next_out, s->window + s->block_start, left); + s->strm->next_out += left; + s->strm->avail_out -= left; + s->strm->total_out += left; + s->block_start += left; + len -= left; + } + + /* Copy uncompressed bytes directly from next_in to next_out, updating + * the check value. + */ + if (len) { + read_buf(s->strm, s->strm->next_out, len); + s->strm->next_out += len; + s->strm->avail_out -= len; + s->strm->total_out += len; + } + } while (last == 0); + + /* Update the sliding window with the last s->w_size bytes of the copied + * data, or append all of the copied data to the existing window if less + * than s->w_size bytes were copied. Also update the number of bytes to + * insert in the hash tables, in the event that deflateParams() switches to + * a non-zero compression level. + */ + used -= s->strm->avail_in; /* number of input bytes directly copied */ + if (used) { + /* If any input was used, then no unused input remains in the window, + * therefore s->block_start == s->strstart. + */ + if (used >= s->w_size) { /* supplant the previous history */ + s->matches = 2; /* clear hash */ + zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); + s->strstart = s->w_size; + } + else { + if (s->window_size - s->strstart <= used) { + /* Slide the window down. */ + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + } + zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); + s->strstart += used; + } + s->block_start = s->strstart; + s->insert += MIN(used, s->w_size - s->insert); + } + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* If the last block was written to next_out, then done. */ + if (last) + return finish_done; + + /* If flushing and all input has been consumed, then done. */ + if (flush != Z_NO_FLUSH && flush != Z_FINISH && + s->strm->avail_in == 0 && (long)s->strstart == s->block_start) + return block_done; + + /* Fill the window with any remaining input. */ + have = s->window_size - s->strstart - 1; + if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { + /* Slide the window down. */ + s->block_start -= s->w_size; + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + have += s->w_size; /* more space now */ + } + if (have > s->strm->avail_in) + have = s->strm->avail_in; + if (have) { + read_buf(s->strm, s->window + s->strstart, have); + s->strstart += have; + } + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* There was not enough avail_out to write a complete worthy or flushed + * stored block to next_out. Write a stored block to pending instead, if we + * have enough input for a worthy block, or if flushing and there is enough + * room for the remaining input as a stored block in the pending buffer. + */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + /* maximum stored block length that will fit in pending: */ + have = MIN(s->pending_buf_size - have, MAX_STORED); + min_block = MIN(have, s->w_size); + left = s->strstart - s->block_start; + if (left >= min_block || + ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && + s->strm->avail_in == 0 && left <= have)) { + len = MIN(left, have); + last = flush == Z_FINISH && s->strm->avail_in == 0 && + len == left ? 1 : 0; + _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); + s->block_start += len; + flush_pending(s->strm); + } + + /* We've done all we can with the available input and output. */ + return last ? finish_started : need_more; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; +} + +#ifndef FASTEST +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = NIL; + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s->match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED +#if TOO_FAR <= 32767 + || (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR) +#endif + )) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; +} +#endif /* FASTEST */ + +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) + */ +local block_state deflate_rle(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + uInt prev; /* byte at distance one to match */ + Bytef *scan, *strend; /* scan goes up to strend for length of run */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. + */ + if (s->lookahead <= MAX_MATCH) { + fill_window(s); + if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* See how many times the previous byte repeats */ + s->match_length = 0; + if (s->lookahead >= MIN_MATCH && s->strstart > 0) { + scan = s->window + s->strstart - 1; + prev = *scan; + if (prev == *++scan && prev == *++scan && prev == *++scan) { + strend = s->window + s->strstart + MAX_MATCH; + do { + } while (prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + prev == *++scan && prev == *++scan && + scan < strend); + s->match_length = MAX_MATCH - (uInt)(strend - scan); + if (s->match_length > s->lookahead) + s->match_length = s->lookahead; + } + Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->strstart - 1, s->match_length); + + _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + s->strstart += s->match_length; + s->match_length = 0; + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; +} + +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +local block_state deflate_huff(s, flush) + deflate_state *s; + int flush; +{ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we have a literal to write. */ + if (s->lookahead == 0) { + fill_window(s); + if (s->lookahead == 0) { + if (flush == Z_NO_FLUSH) + return need_more; + break; /* flush the current block */ + } + } + + /* Output a literal byte */ + s->match_length = 0; + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + if (bflush) FLUSH_BLOCK(s, 0); + } + s->insert = 0; + if (flush == Z_FINISH) { + FLUSH_BLOCK(s, 1); + return finish_done; + } + if (s->last_lit) + FLUSH_BLOCK(s, 0); + return block_done; +} diff --git a/zlib-1.2.11/deflate.h b/zlib-1.2.11/deflate.h new file mode 100644 index 00000000..23ecdd31 --- /dev/null +++ b/zlib-1.2.11/deflate.h @@ -0,0 +1,349 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2016 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef DEFLATE_H +#define DEFLATE_H + +#include "zutil.h" + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer creation by deflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip encoding + should be left enabled. */ +#ifndef NO_GZIP +# define GZIP +#endif + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define Buf_size 16 +/* size of bit buffer in bi_buf */ + +#define INIT_STATE 42 /* zlib header -> BUSY_STATE */ +#ifdef GZIP +# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ +#endif +#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ +#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ +#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ +#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ +#define BUSY_STATE 113 /* deflate -> FINISH_STATE */ +#define FINISH_STATE 666 /* stream complete */ +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + const static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + ulg pending; /* nb of bytes in the pending buffer */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + gz_headerp gzhead; /* gzip header information to write */ + ulg gzindex; /* where in extra, name, or comment */ + Byte method; /* can only be DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to suppress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + uInt insert; /* bytes at end of window left to insert */ + +#ifdef ZLIB_DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + ulg high_water; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + +#define WIN_INIT MAX_MATCH +/* Number of bytes after end of data in window to initialize in order to avoid + memory checker errors from longest match routines */ + + /* in trees.c */ +void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); +int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); +void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); +void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, + ulg stored_len, int last)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef ZLIB_DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch ZLIB_INTERNAL _length_code[]; + extern uch ZLIB_INTERNAL _dist_code[]; +#else + extern const uch ZLIB_INTERNAL _length_code[]; + extern const uch ZLIB_INTERNAL _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (uch)(length); \ + ush dist = (ush)(distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif /* DEFLATE_H */ diff --git a/zlib-1.2.11/doc/algorithm.txt b/zlib-1.2.11/doc/algorithm.txt new file mode 100644 index 00000000..c97f4950 --- /dev/null +++ b/zlib-1.2.11/doc/algorithm.txt @@ -0,0 +1,209 @@ +1. Compression algorithm (deflate) + +The deflation algorithm used by gzip (also zip and zlib) is a variation of +LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in +the input data. The second occurrence of a string is replaced by a +pointer to the previous string, in the form of a pair (distance, +length). Distances are limited to 32K bytes, and lengths are limited +to 258 bytes. When a string does not occur anywhere in the previous +32K bytes, it is emitted as a sequence of literal bytes. (In this +description, `string' must be taken as an arbitrary sequence of bytes, +and is not restricted to printable characters.) + +Literals or match lengths are compressed with one Huffman tree, and +match distances are compressed with another tree. The trees are stored +in a compact form at the start of each block. The blocks can have any +size (except that the compressed data for one block must fit in +available memory). A block is terminated when deflate() determines that +it would be useful to start another block with fresh trees. (This is +somewhat similar to the behavior of LZW-based _compress_.) + +Duplicated strings are found using a hash table. All input strings of +length 3 are inserted in the hash table. A hash index is computed for +the next 3 bytes. If the hash chain for this index is not empty, all +strings in the chain are compared with the current input string, and +the longest match is selected. + +The hash chains are searched starting with the most recent strings, to +favor small distances and thus take advantage of the Huffman encoding. +The hash chains are singly linked. There are no deletions from the +hash chains, the algorithm simply discards matches that are too old. + +To avoid a worst-case situation, very long hash chains are arbitrarily +truncated at a certain length, determined by a runtime option (level +parameter of deflateInit). So deflate() does not always find the longest +possible match but generally finds a match which is long enough. + +deflate() also defers the selection of matches with a lazy evaluation +mechanism. After a match of length N has been found, deflate() searches for +a longer match at the next input byte. If a longer match is found, the +previous match is truncated to a length of one (thus producing a single +literal byte) and the process of lazy evaluation begins again. Otherwise, +the original match is kept, and the next match search is attempted only N +steps later. + +The lazy match evaluation is also subject to a runtime parameter. If +the current match is long enough, deflate() reduces the search for a longer +match, thus speeding up the whole process. If compression ratio is more +important than speed, deflate() attempts a complete second search even if +the first match is already long enough. + +The lazy match evaluation is not performed for the fastest compression +modes (level parameter 1 to 3). For these fast modes, new strings +are inserted in the hash table only when no match was found, or +when the match is not too long. This degrades the compression ratio +but saves time since there are both fewer insertions and fewer searches. + + +2. Decompression algorithm (inflate) + +2.1 Introduction + +The key question is how to represent a Huffman code (or any prefix code) so +that you can decode fast. The most important characteristic is that shorter +codes are much more common than longer codes, so pay attention to decoding the +short codes fast, and let the long codes take longer to decode. + +inflate() sets up a first level table that covers some number of bits of +input less than the length of longest code. It gets that many bits from the +stream, and looks it up in the table. The table will tell if the next +code is that many bits or less and how many, and if it is, it will tell +the value, else it will point to the next level table for which inflate() +grabs more bits and tries to decode a longer code. + +How many bits to make the first lookup is a tradeoff between the time it +takes to decode and the time it takes to build the table. If building the +table took no time (and if you had infinite memory), then there would only +be a first level table to cover all the way to the longest code. However, +building the table ends up taking a lot longer for more bits since short +codes are replicated many times in such a table. What inflate() does is +simply to make the number of bits in the first table a variable, and then +to set that variable for the maximum speed. + +For inflate, which has 286 possible codes for the literal/length tree, the size +of the first table is nine bits. Also the distance trees have 30 possible +values, and the size of the first table is six bits. Note that for each of +those cases, the table ended up one bit longer than the ``average'' code +length, i.e. the code length of an approximately flat code which would be a +little more than eight bits for 286 symbols and a little less than five bits +for 30 symbols. + + +2.2 More details on the inflate table lookup + +Ok, you want to know what this cleverly obfuscated inflate tree actually +looks like. You are correct that it's not a Huffman tree. It is simply a +lookup table for the first, let's say, nine bits of a Huffman symbol. The +symbol could be as short as one bit or as long as 15 bits. If a particular +symbol is shorter than nine bits, then that symbol's translation is duplicated +in all those entries that start with that symbol's bits. For example, if the +symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a +symbol is nine bits long, it appears in the table once. + +If the symbol is longer than nine bits, then that entry in the table points +to another similar table for the remaining bits. Again, there are duplicated +entries as needed. The idea is that most of the time the symbol will be short +and there will only be one table look up. (That's whole idea behind data +compression in the first place.) For the less frequent long symbols, there +will be two lookups. If you had a compression method with really long +symbols, you could have as many levels of lookups as is efficient. For +inflate, two is enough. + +So a table entry either points to another table (in which case nine bits in +the above example are gobbled), or it contains the translation for the symbol +and the number of bits to gobble. Then you start again with the next +ungobbled bit. + +You may wonder: why not just have one lookup table for how ever many bits the +longest symbol is? The reason is that if you do that, you end up spending +more time filling in duplicate symbol entries than you do actually decoding. +At least for deflate's output that generates new trees every several 10's of +kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code +would take too long if you're only decoding several thousand symbols. At the +other extreme, you could make a new table for every bit in the code. In fact, +that's essentially a Huffman tree. But then you spend too much time +traversing the tree while decoding, even for short symbols. + +So the number of bits for the first lookup table is a trade of the time to +fill out the table vs. the time spent looking at the second level and above of +the table. + +Here is an example, scaled down: + +The code being decoded, with 10 symbols, from 1 to 6 bits long: + +A: 0 +B: 10 +C: 1100 +D: 11010 +E: 11011 +F: 11100 +G: 11101 +H: 11110 +I: 111110 +J: 111111 + +Let's make the first table three bits long (eight entries): + +000: A,1 +001: A,1 +010: A,1 +011: A,1 +100: B,2 +101: B,2 +110: -> table X (gobble 3 bits) +111: -> table Y (gobble 3 bits) + +Each entry is what the bits decode as and how many bits that is, i.e. how +many bits to gobble. Or the entry points to another table, with the number of +bits to gobble implicit in the size of the table. + +Table X is two bits long since the longest code starting with 110 is five bits +long: + +00: C,1 +01: C,1 +10: D,2 +11: E,2 + +Table Y is three bits long since the longest code starting with 111 is six +bits long: + +000: F,2 +001: F,2 +010: G,2 +011: G,2 +100: H,2 +101: H,2 +110: I,3 +111: J,3 + +So what we have here are three tables with a total of 20 entries that had to +be constructed. That's compared to 64 entries for a single table. Or +compared to 16 entries for a Huffman tree (six two entry tables and one four +entry table). Assuming that the code ideally represents the probability of +the symbols, it takes on the average 1.25 lookups per symbol. That's compared +to one lookup for the single table, or 1.66 lookups per symbol for the +Huffman tree. + +There, I think that gives you a picture of what's going on. For inflate, the +meaning of a particular symbol is often more than just a letter. It can be a +byte (a "literal"), or it can be either a length or a distance which +indicates a base value and a number of bits to fetch after the code that is +added to the base value. Or it might be the special end-of-block code. The +data structures created in inftrees.c try to encode all that information +compactly in the tables. + + +Jean-loup Gailly Mark Adler +jloup@gzip.org madler@alumni.caltech.edu + + +References: + +[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data +Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, +pp. 337-343. + +``DEFLATE Compressed Data Format Specification'' available in +http://tools.ietf.org/html/rfc1951 diff --git a/zlib-1.2.11/doc/rfc1950.txt b/zlib-1.2.11/doc/rfc1950.txt new file mode 100644 index 00000000..ce6428a0 --- /dev/null +++ b/zlib-1.2.11/doc/rfc1950.txt @@ -0,0 +1,619 @@ + + + + + + +Network Working Group P. Deutsch +Request for Comments: 1950 Aladdin Enterprises +Category: Informational J-L. Gailly + Info-ZIP + May 1996 + + + ZLIB Compressed Data Format Specification version 3.3 + +Status of This Memo + + This memo provides information for the Internet community. This memo + does not specify an Internet standard of any kind. Distribution of + this memo is unlimited. + +IESG Note: + + The IESG takes no position on the validity of any Intellectual + Property Rights statements contained in this document. + +Notices + + Copyright (c) 1996 L. Peter Deutsch and Jean-Loup Gailly + + Permission is granted to copy and distribute this document for any + purpose and without charge, including translations into other + languages and incorporation into compilations, provided that the + copyright notice and this notice are preserved, and that any + substantive changes or deletions from the original are clearly + marked. + + A pointer to the latest version of this and related documentation in + HTML format can be found at the URL + . + +Abstract + + This specification defines a lossless compressed data format. The + data can be produced or consumed, even for an arbitrarily long + sequentially presented input data stream, using only an a priori + bounded amount of intermediate storage. The format presently uses + the DEFLATE compression method but can be easily extended to use + other compression methods. It can be implemented readily in a manner + not covered by patents. This specification also defines the ADLER-32 + checksum (an extension and improvement of the Fletcher checksum), + used for detection of data corruption, and provides an algorithm for + computing it. + + + + +Deutsch & Gailly Informational [Page 1] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + +Table of Contents + + 1. Introduction ................................................... 2 + 1.1. Purpose ................................................... 2 + 1.2. Intended audience ......................................... 3 + 1.3. Scope ..................................................... 3 + 1.4. Compliance ................................................ 3 + 1.5. Definitions of terms and conventions used ................ 3 + 1.6. Changes from previous versions ............................ 3 + 2. Detailed specification ......................................... 3 + 2.1. Overall conventions ....................................... 3 + 2.2. Data format ............................................... 4 + 2.3. Compliance ................................................ 7 + 3. References ..................................................... 7 + 4. Source code .................................................... 8 + 5. Security Considerations ........................................ 8 + 6. Acknowledgements ............................................... 8 + 7. Authors' Addresses ............................................. 8 + 8. Appendix: Rationale ............................................ 9 + 9. Appendix: Sample code ..........................................10 + +1. Introduction + + 1.1. Purpose + + The purpose of this specification is to define a lossless + compressed data format that: + + * Is independent of CPU type, operating system, file system, + and character set, and hence can be used for interchange; + + * Can be produced or consumed, even for an arbitrarily long + sequentially presented input data stream, using only an a + priori bounded amount of intermediate storage, and hence can + be used in data communications or similar structures such as + Unix filters; + + * Can use a number of different compression methods; + + * Can be implemented readily in a manner not covered by + patents, and hence can be practiced freely. + + The data format defined by this specification does not attempt to + allow random access to compressed data. + + + + + + + +Deutsch & Gailly Informational [Page 2] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + + 1.2. Intended audience + + This specification is intended for use by implementors of software + to compress data into zlib format and/or decompress data from zlib + format. + + The text of the specification assumes a basic background in + programming at the level of bits and other primitive data + representations. + + 1.3. Scope + + The specification specifies a compressed data format that can be + used for in-memory compression of a sequence of arbitrary bytes. + + 1.4. Compliance + + Unless otherwise indicated below, a compliant decompressor must be + able to accept and decompress any data set that conforms to all + the specifications presented here; a compliant compressor must + produce data sets that conform to all the specifications presented + here. + + 1.5. Definitions of terms and conventions used + + byte: 8 bits stored or transmitted as a unit (same as an octet). + (For this specification, a byte is exactly 8 bits, even on + machines which store a character on a number of bits different + from 8.) See below, for the numbering of bits within a byte. + + 1.6. Changes from previous versions + + Version 3.1 was the first public release of this specification. + In version 3.2, some terminology was changed and the Adler-32 + sample code was rewritten for clarity. In version 3.3, the + support for a preset dictionary was introduced, and the + specification was converted to RFC style. + +2. Detailed specification + + 2.1. Overall conventions + + In the diagrams below, a box like this: + + +---+ + | | <-- the vertical bars might be missing + +---+ + + + + +Deutsch & Gailly Informational [Page 3] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + + represents one byte; a box like this: + + +==============+ + | | + +==============+ + + represents a variable number of bytes. + + Bytes stored within a computer do not have a "bit order", since + they are always treated as a unit. However, a byte considered as + an integer between 0 and 255 does have a most- and least- + significant bit, and since we write numbers with the most- + significant digit on the left, we also write bytes with the most- + significant bit on the left. In the diagrams below, we number the + bits of a byte so that bit 0 is the least-significant bit, i.e., + the bits are numbered: + + +--------+ + |76543210| + +--------+ + + Within a computer, a number may occupy multiple bytes. All + multi-byte numbers in the format described here are stored with + the MOST-significant byte first (at the lower memory address). + For example, the decimal number 520 is stored as: + + 0 1 + +--------+--------+ + |00000010|00001000| + +--------+--------+ + ^ ^ + | | + | + less significant byte = 8 + + more significant byte = 2 x 256 + + 2.2. Data format + + A zlib stream has the following structure: + + 0 1 + +---+---+ + |CMF|FLG| (more-->) + +---+---+ + + + + + + + + +Deutsch & Gailly Informational [Page 4] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + + (if FLG.FDICT set) + + 0 1 2 3 + +---+---+---+---+ + | DICTID | (more-->) + +---+---+---+---+ + + +=====================+---+---+---+---+ + |...compressed data...| ADLER32 | + +=====================+---+---+---+---+ + + Any data which may appear after ADLER32 are not part of the zlib + stream. + + CMF (Compression Method and flags) + This byte is divided into a 4-bit compression method and a 4- + bit information field depending on the compression method. + + bits 0 to 3 CM Compression method + bits 4 to 7 CINFO Compression info + + CM (Compression method) + This identifies the compression method used in the file. CM = 8 + denotes the "deflate" compression method with a window size up + to 32K. This is the method used by gzip and PNG (see + references [1] and [2] in Chapter 3, below, for the reference + documents). CM = 15 is reserved. It might be used in a future + version of this specification to indicate the presence of an + extra field before the compressed data. + + CINFO (Compression info) + For CM = 8, CINFO is the base-2 logarithm of the LZ77 window + size, minus eight (CINFO=7 indicates a 32K window size). Values + of CINFO above 7 are not allowed in this version of the + specification. CINFO is not defined in this specification for + CM not equal to 8. + + FLG (FLaGs) + This flag byte is divided as follows: + + bits 0 to 4 FCHECK (check bits for CMF and FLG) + bit 5 FDICT (preset dictionary) + bits 6 to 7 FLEVEL (compression level) + + The FCHECK value must be such that CMF and FLG, when viewed as + a 16-bit unsigned integer stored in MSB order (CMF*256 + FLG), + is a multiple of 31. + + + + +Deutsch & Gailly Informational [Page 5] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + + FDICT (Preset dictionary) + If FDICT is set, a DICT dictionary identifier is present + immediately after the FLG byte. The dictionary is a sequence of + bytes which are initially fed to the compressor without + producing any compressed output. DICT is the Adler-32 checksum + of this sequence of bytes (see the definition of ADLER32 + below). The decompressor can use this identifier to determine + which dictionary has been used by the compressor. + + FLEVEL (Compression level) + These flags are available for use by specific compression + methods. The "deflate" method (CM = 8) sets these flags as + follows: + + 0 - compressor used fastest algorithm + 1 - compressor used fast algorithm + 2 - compressor used default algorithm + 3 - compressor used maximum compression, slowest algorithm + + The information in FLEVEL is not needed for decompression; it + is there to indicate if recompression might be worthwhile. + + compressed data + For compression method 8, the compressed data is stored in the + deflate compressed data format as described in the document + "DEFLATE Compressed Data Format Specification" by L. Peter + Deutsch. (See reference [3] in Chapter 3, below) + + Other compressed data formats are not specified in this version + of the zlib specification. + + ADLER32 (Adler-32 checksum) + This contains a checksum value of the uncompressed data + (excluding any dictionary data) computed according to Adler-32 + algorithm. This algorithm is a 32-bit extension and improvement + of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 + standard. See references [4] and [5] in Chapter 3, below) + + Adler-32 is composed of two sums accumulated per byte: s1 is + the sum of all bytes, s2 is the sum of all s1 values. Both sums + are done modulo 65521. s1 is initialized to 1, s2 to zero. The + Adler-32 checksum is stored as s2*65536 + s1 in most- + significant-byte first (network) order. + + + + + + + + +Deutsch & Gailly Informational [Page 6] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + + 2.3. Compliance + + A compliant compressor must produce streams with correct CMF, FLG + and ADLER32, but need not support preset dictionaries. When the + zlib data format is used as part of another standard data format, + the compressor may use only preset dictionaries that are specified + by this other data format. If this other format does not use the + preset dictionary feature, the compressor must not set the FDICT + flag. + + A compliant decompressor must check CMF, FLG, and ADLER32, and + provide an error indication if any of these have incorrect values. + A compliant decompressor must give an error indication if CM is + not one of the values defined in this specification (only the + value 8 is permitted in this version), since another value could + indicate the presence of new features that would cause subsequent + data to be interpreted incorrectly. A compliant decompressor must + give an error indication if FDICT is set and DICTID is not the + identifier of a known preset dictionary. A decompressor may + ignore FLEVEL and still be compliant. When the zlib data format + is being used as a part of another standard format, a compliant + decompressor must support all the preset dictionaries specified by + the other format. When the other format does not use the preset + dictionary feature, a compliant decompressor must reject any + stream in which the FDICT flag is set. + +3. References + + [1] Deutsch, L.P.,"GZIP Compressed Data Format Specification", + available in ftp://ftp.uu.net/pub/archiving/zip/doc/ + + [2] Thomas Boutell, "PNG (Portable Network Graphics) specification", + available in ftp://ftp.uu.net/graphics/png/documents/ + + [3] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", + available in ftp://ftp.uu.net/pub/archiving/zip/doc/ + + [4] Fletcher, J. G., "An Arithmetic Checksum for Serial + Transmissions," IEEE Transactions on Communications, Vol. COM-30, + No. 1, January 1982, pp. 247-252. + + [5] ITU-T Recommendation X.224, Annex D, "Checksum Algorithms," + November, 1993, pp. 144, 145. (Available from + gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073. + + + + + + + +Deutsch & Gailly Informational [Page 7] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + +4. Source code + + Source code for a C language implementation of a "zlib" compliant + library is available at ftp://ftp.uu.net/pub/archiving/zip/zlib/. + +5. Security Considerations + + A decoder that fails to check the ADLER32 checksum value may be + subject to undetected data corruption. + +6. Acknowledgements + + Trademarks cited in this document are the property of their + respective owners. + + Jean-Loup Gailly and Mark Adler designed the zlib format and wrote + the related software described in this specification. Glenn + Randers-Pehrson converted this document to RFC and HTML format. + +7. Authors' Addresses + + L. Peter Deutsch + Aladdin Enterprises + 203 Santa Margarita Ave. + Menlo Park, CA 94025 + + Phone: (415) 322-0103 (AM only) + FAX: (415) 322-1734 + EMail: + + + Jean-Loup Gailly + + EMail: + + Questions about the technical content of this specification can be + sent by email to + + Jean-Loup Gailly and + Mark Adler + + Editorial comments on this specification can be sent by email to + + L. Peter Deutsch and + Glenn Randers-Pehrson + + + + + + +Deutsch & Gailly Informational [Page 8] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + +8. Appendix: Rationale + + 8.1. Preset dictionaries + + A preset dictionary is specially useful to compress short input + sequences. The compressor can take advantage of the dictionary + context to encode the input in a more compact manner. The + decompressor can be initialized with the appropriate context by + virtually decompressing a compressed version of the dictionary + without producing any output. However for certain compression + algorithms such as the deflate algorithm this operation can be + achieved without actually performing any decompression. + + The compressor and the decompressor must use exactly the same + dictionary. The dictionary may be fixed or may be chosen among a + certain number of predefined dictionaries, according to the kind + of input data. The decompressor can determine which dictionary has + been chosen by the compressor by checking the dictionary + identifier. This document does not specify the contents of + predefined dictionaries, since the optimal dictionaries are + application specific. Standard data formats using this feature of + the zlib specification must precisely define the allowed + dictionaries. + + 8.2. The Adler-32 algorithm + + The Adler-32 algorithm is much faster than the CRC32 algorithm yet + still provides an extremely low probability of undetected errors. + + The modulo on unsigned long accumulators can be delayed for 5552 + bytes, so the modulo operation time is negligible. If the bytes + are a, b, c, the second sum is 3a + 2b + c + 3, and so is position + and order sensitive, unlike the first sum, which is just a + checksum. That 65521 is prime is important to avoid a possible + large class of two-byte errors that leave the check unchanged. + (The Fletcher checksum uses 255, which is not prime and which also + makes the Fletcher check insensitive to single byte changes 0 <-> + 255.) + + The sum s1 is initialized to 1 instead of zero to make the length + of the sequence part of s2, so that the length does not have to be + checked separately. (Any sequence of zeroes has a Fletcher + checksum of zero.) + + + + + + + + +Deutsch & Gailly Informational [Page 9] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + +9. Appendix: Sample code + + The following C code computes the Adler-32 checksum of a data buffer. + It is written for clarity, not for speed. The sample code is in the + ANSI C programming language. Non C users may find it easier to read + with these hints: + + & Bitwise AND operator. + >> Bitwise right shift operator. When applied to an + unsigned quantity, as here, right shift inserts zero bit(s) + at the left. + << Bitwise left shift operator. Left shift inserts zero + bit(s) at the right. + ++ "n++" increments the variable n. + % modulo operator: a % b is the remainder of a divided by b. + + #define BASE 65521 /* largest prime smaller than 65536 */ + + /* + Update a running Adler-32 checksum with the bytes buf[0..len-1] + and return the updated checksum. The Adler-32 checksum should be + initialized to 1. + + Usage example: + + unsigned long adler = 1L; + + while (read_buffer(buffer, length) != EOF) { + adler = update_adler32(adler, buffer, length); + } + if (adler != original_adler) error(); + */ + unsigned long update_adler32(unsigned long adler, + unsigned char *buf, int len) + { + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int n; + + for (n = 0; n < len; n++) { + s1 = (s1 + buf[n]) % BASE; + s2 = (s2 + s1) % BASE; + } + return (s2 << 16) + s1; + } + + /* Return the adler32 of the bytes buf[0..len-1] */ + + + + +Deutsch & Gailly Informational [Page 10] + +RFC 1950 ZLIB Compressed Data Format Specification May 1996 + + + unsigned long adler32(unsigned char *buf, int len) + { + return update_adler32(1L, buf, len); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Deutsch & Gailly Informational [Page 11] + diff --git a/zlib-1.2.11/doc/rfc1951.txt b/zlib-1.2.11/doc/rfc1951.txt new file mode 100644 index 00000000..403c8c72 --- /dev/null +++ b/zlib-1.2.11/doc/rfc1951.txt @@ -0,0 +1,955 @@ + + + + + + +Network Working Group P. Deutsch +Request for Comments: 1951 Aladdin Enterprises +Category: Informational May 1996 + + + DEFLATE Compressed Data Format Specification version 1.3 + +Status of This Memo + + This memo provides information for the Internet community. This memo + does not specify an Internet standard of any kind. Distribution of + this memo is unlimited. + +IESG Note: + + The IESG takes no position on the validity of any Intellectual + Property Rights statements contained in this document. + +Notices + + Copyright (c) 1996 L. Peter Deutsch + + Permission is granted to copy and distribute this document for any + purpose and without charge, including translations into other + languages and incorporation into compilations, provided that the + copyright notice and this notice are preserved, and that any + substantive changes or deletions from the original are clearly + marked. + + A pointer to the latest version of this and related documentation in + HTML format can be found at the URL + . + +Abstract + + This specification defines a lossless compressed data format that + compresses data using a combination of the LZ77 algorithm and Huffman + coding, with efficiency comparable to the best currently available + general-purpose compression methods. The data can be produced or + consumed, even for an arbitrarily long sequentially presented input + data stream, using only an a priori bounded amount of intermediate + storage. The format can be implemented readily in a manner not + covered by patents. + + + + + + + + +Deutsch Informational [Page 1] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + +Table of Contents + + 1. Introduction ................................................... 2 + 1.1. Purpose ................................................... 2 + 1.2. Intended audience ......................................... 3 + 1.3. Scope ..................................................... 3 + 1.4. Compliance ................................................ 3 + 1.5. Definitions of terms and conventions used ................ 3 + 1.6. Changes from previous versions ............................ 4 + 2. Compressed representation overview ............................. 4 + 3. Detailed specification ......................................... 5 + 3.1. Overall conventions ....................................... 5 + 3.1.1. Packing into bytes .................................. 5 + 3.2. Compressed block format ................................... 6 + 3.2.1. Synopsis of prefix and Huffman coding ............... 6 + 3.2.2. Use of Huffman coding in the "deflate" format ....... 7 + 3.2.3. Details of block format ............................. 9 + 3.2.4. Non-compressed blocks (BTYPE=00) ................... 11 + 3.2.5. Compressed blocks (length and distance codes) ...... 11 + 3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12 + 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13 + 3.3. Compliance ............................................... 14 + 4. Compression algorithm details ................................. 14 + 5. References .................................................... 16 + 6. Security Considerations ....................................... 16 + 7. Source code ................................................... 16 + 8. Acknowledgements .............................................. 16 + 9. Author's Address .............................................. 17 + +1. Introduction + + 1.1. Purpose + + The purpose of this specification is to define a lossless + compressed data format that: + * Is independent of CPU type, operating system, file system, + and character set, and hence can be used for interchange; + * Can be produced or consumed, even for an arbitrarily long + sequentially presented input data stream, using only an a + priori bounded amount of intermediate storage, and hence + can be used in data communications or similar structures + such as Unix filters; + * Compresses data with efficiency comparable to the best + currently available general-purpose compression methods, + and in particular considerably better than the "compress" + program; + * Can be implemented readily in a manner not covered by + patents, and hence can be practiced freely; + + + +Deutsch Informational [Page 2] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + * Is compatible with the file format produced by the current + widely used gzip utility, in that conforming decompressors + will be able to read data produced by the existing gzip + compressor. + + The data format defined by this specification does not attempt to: + + * Allow random access to compressed data; + * Compress specialized data (e.g., raster graphics) as well + as the best currently available specialized algorithms. + + A simple counting argument shows that no lossless compression + algorithm can compress every possible input data set. For the + format defined here, the worst case expansion is 5 bytes per 32K- + byte block, i.e., a size increase of 0.015% for large data sets. + English text usually compresses by a factor of 2.5 to 3; + executable files usually compress somewhat less; graphical data + such as raster images may compress much more. + + 1.2. Intended audience + + This specification is intended for use by implementors of software + to compress data into "deflate" format and/or decompress data from + "deflate" format. + + The text of the specification assumes a basic background in + programming at the level of bits and other primitive data + representations. Familiarity with the technique of Huffman coding + is helpful but not required. + + 1.3. Scope + + The specification specifies a method for representing a sequence + of bytes as a (usually shorter) sequence of bits, and a method for + packing the latter bit sequence into bytes. + + 1.4. Compliance + + Unless otherwise indicated below, a compliant decompressor must be + able to accept and decompress any data set that conforms to all + the specifications presented here; a compliant compressor must + produce data sets that conform to all the specifications presented + here. + + 1.5. Definitions of terms and conventions used + + Byte: 8 bits stored or transmitted as a unit (same as an octet). + For this specification, a byte is exactly 8 bits, even on machines + + + +Deutsch Informational [Page 3] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + which store a character on a number of bits different from eight. + See below, for the numbering of bits within a byte. + + String: a sequence of arbitrary bytes. + + 1.6. Changes from previous versions + + There have been no technical changes to the deflate format since + version 1.1 of this specification. In version 1.2, some + terminology was changed. Version 1.3 is a conversion of the + specification to RFC style. + +2. Compressed representation overview + + A compressed data set consists of a series of blocks, corresponding + to successive blocks of input data. The block sizes are arbitrary, + except that non-compressible blocks are limited to 65,535 bytes. + + Each block is compressed using a combination of the LZ77 algorithm + and Huffman coding. The Huffman trees for each block are independent + of those for previous or subsequent blocks; the LZ77 algorithm may + use a reference to a duplicated string occurring in a previous block, + up to 32K input bytes before. + + Each block consists of two parts: a pair of Huffman code trees that + describe the representation of the compressed data part, and a + compressed data part. (The Huffman trees themselves are compressed + using Huffman encoding.) The compressed data consists of a series of + elements of two types: literal bytes (of strings that have not been + detected as duplicated within the previous 32K input bytes), and + pointers to duplicated strings, where a pointer is represented as a + pair . The representation used in the + "deflate" format limits distances to 32K bytes and lengths to 258 + bytes, but does not limit the size of a block, except for + uncompressible blocks, which are limited as noted above. + + Each type of value (literals, distances, and lengths) in the + compressed data is represented using a Huffman code, using one code + tree for literals and lengths and a separate code tree for distances. + The code trees for each block appear in a compact form just before + the compressed data for that block. + + + + + + + + + + +Deutsch Informational [Page 4] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + +3. Detailed specification + + 3.1. Overall conventions In the diagrams below, a box like this: + + +---+ + | | <-- the vertical bars might be missing + +---+ + + represents one byte; a box like this: + + +==============+ + | | + +==============+ + + represents a variable number of bytes. + + Bytes stored within a computer do not have a "bit order", since + they are always treated as a unit. However, a byte considered as + an integer between 0 and 255 does have a most- and least- + significant bit, and since we write numbers with the most- + significant digit on the left, we also write bytes with the most- + significant bit on the left. In the diagrams below, we number the + bits of a byte so that bit 0 is the least-significant bit, i.e., + the bits are numbered: + + +--------+ + |76543210| + +--------+ + + Within a computer, a number may occupy multiple bytes. All + multi-byte numbers in the format described here are stored with + the least-significant byte first (at the lower memory address). + For example, the decimal number 520 is stored as: + + 0 1 + +--------+--------+ + |00001000|00000010| + +--------+--------+ + ^ ^ + | | + | + more significant byte = 2 x 256 + + less significant byte = 8 + + 3.1.1. Packing into bytes + + This document does not address the issue of the order in which + bits of a byte are transmitted on a bit-sequential medium, + since the final data format described here is byte- rather than + + + +Deutsch Informational [Page 5] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + bit-oriented. However, we describe the compressed block format + in below, as a sequence of data elements of various bit + lengths, not a sequence of bytes. We must therefore specify + how to pack these data elements into bytes to form the final + compressed byte sequence: + + * Data elements are packed into bytes in order of + increasing bit number within the byte, i.e., starting + with the least-significant bit of the byte. + * Data elements other than Huffman codes are packed + starting with the least-significant bit of the data + element. + * Huffman codes are packed starting with the most- + significant bit of the code. + + In other words, if one were to print out the compressed data as + a sequence of bytes, starting with the first byte at the + *right* margin and proceeding to the *left*, with the most- + significant bit of each byte on the left as usual, one would be + able to parse the result from right to left, with fixed-width + elements in the correct MSB-to-LSB order and Huffman codes in + bit-reversed order (i.e., with the first bit of the code in the + relative LSB position). + + 3.2. Compressed block format + + 3.2.1. Synopsis of prefix and Huffman coding + + Prefix coding represents symbols from an a priori known + alphabet by bit sequences (codes), one code for each symbol, in + a manner such that different symbols may be represented by bit + sequences of different lengths, but a parser can always parse + an encoded string unambiguously symbol-by-symbol. + + We define a prefix code in terms of a binary tree in which the + two edges descending from each non-leaf node are labeled 0 and + 1 and in which the leaf nodes correspond one-for-one with (are + labeled with) the symbols of the alphabet; then the code for a + symbol is the sequence of 0's and 1's on the edges leading from + the root to the leaf labeled with that symbol. For example: + + + + + + + + + + + +Deutsch Informational [Page 6] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + /\ Symbol Code + 0 1 ------ ---- + / \ A 00 + /\ B B 1 + 0 1 C 011 + / \ D 010 + A /\ + 0 1 + / \ + D C + + A parser can decode the next symbol from an encoded input + stream by walking down the tree from the root, at each step + choosing the edge corresponding to the next input bit. + + Given an alphabet with known symbol frequencies, the Huffman + algorithm allows the construction of an optimal prefix code + (one which represents strings with those symbol frequencies + using the fewest bits of any possible prefix codes for that + alphabet). Such a code is called a Huffman code. (See + reference [1] in Chapter 5, references for additional + information on Huffman codes.) + + Note that in the "deflate" format, the Huffman codes for the + various alphabets must not exceed certain maximum code lengths. + This constraint complicates the algorithm for computing code + lengths from symbol frequencies. Again, see Chapter 5, + references for details. + + 3.2.2. Use of Huffman coding in the "deflate" format + + The Huffman codes used for each alphabet in the "deflate" + format have two additional rules: + + * All codes of a given bit length have lexicographically + consecutive values, in the same order as the symbols + they represent; + + * Shorter codes lexicographically precede longer codes. + + + + + + + + + + + + +Deutsch Informational [Page 7] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + We could recode the example above to follow this rule as + follows, assuming that the order of the alphabet is ABCD: + + Symbol Code + ------ ---- + A 10 + B 0 + C 110 + D 111 + + I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are + lexicographically consecutive. + + Given this rule, we can define the Huffman code for an alphabet + just by giving the bit lengths of the codes for each symbol of + the alphabet in order; this is sufficient to determine the + actual codes. In our example, the code is completely defined + by the sequence of bit lengths (2, 1, 3, 3). The following + algorithm generates the codes as integers, intended to be read + from most- to least-significant bit. The code lengths are + initially in tree[I].Len; the codes are produced in + tree[I].Code. + + 1) Count the number of codes for each code length. Let + bl_count[N] be the number of codes of length N, N >= 1. + + 2) Find the numerical value of the smallest code for each + code length: + + code = 0; + bl_count[0] = 0; + for (bits = 1; bits <= MAX_BITS; bits++) { + code = (code + bl_count[bits-1]) << 1; + next_code[bits] = code; + } + + 3) Assign numerical values to all codes, using consecutive + values for all codes of the same length with the base + values determined at step 2. Codes that are never used + (which have a bit length of zero) must not be assigned a + value. + + for (n = 0; n <= max_code; n++) { + len = tree[n].Len; + if (len != 0) { + tree[n].Code = next_code[len]; + next_code[len]++; + } + + + +Deutsch Informational [Page 8] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + } + + Example: + + Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3, + 3, 2, 4, 4). After step 1, we have: + + N bl_count[N] + - ----------- + 2 1 + 3 5 + 4 2 + + Step 2 computes the following next_code values: + + N next_code[N] + - ------------ + 1 0 + 2 0 + 3 2 + 4 14 + + Step 3 produces the following code values: + + Symbol Length Code + ------ ------ ---- + A 3 010 + B 3 011 + C 3 100 + D 3 101 + E 3 110 + F 2 00 + G 4 1110 + H 4 1111 + + 3.2.3. Details of block format + + Each block of compressed data begins with 3 header bits + containing the following data: + + first bit BFINAL + next 2 bits BTYPE + + Note that the header bits do not necessarily begin on a byte + boundary, since a block does not necessarily occupy an integral + number of bytes. + + + + + +Deutsch Informational [Page 9] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + BFINAL is set if and only if this is the last block of the data + set. + + BTYPE specifies how the data are compressed, as follows: + + 00 - no compression + 01 - compressed with fixed Huffman codes + 10 - compressed with dynamic Huffman codes + 11 - reserved (error) + + The only difference between the two compressed cases is how the + Huffman codes for the literal/length and distance alphabets are + defined. + + In all cases, the decoding algorithm for the actual data is as + follows: + + do + read block header from input stream. + if stored with no compression + skip any remaining bits in current partially + processed byte + read LEN and NLEN (see next section) + copy LEN bytes of data to output + otherwise + if compressed with dynamic Huffman codes + read representation of code trees (see + subsection below) + loop (until end of block code recognized) + decode literal/length value from input stream + if value < 256 + copy value (literal byte) to output stream + otherwise + if value = end of block (256) + break from loop + otherwise (value = 257..285) + decode distance from input stream + + move backwards distance bytes in the output + stream, and copy length bytes from this + position to the output stream. + end loop + while not last block + + Note that a duplicated string reference may refer to a string + in a previous block; i.e., the backward distance may cross one + or more block boundaries. However a distance cannot refer past + the beginning of the output stream. (An application using a + + + +Deutsch Informational [Page 10] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + preset dictionary might discard part of the output stream; a + distance can refer to that part of the output stream anyway) + Note also that the referenced string may overlap the current + position; for example, if the last 2 bytes decoded have values + X and Y, a string reference with + adds X,Y,X,Y,X to the output stream. + + We now specify each compression method in turn. + + 3.2.4. Non-compressed blocks (BTYPE=00) + + Any bits of input up to the next byte boundary are ignored. + The rest of the block consists of the following information: + + 0 1 2 3 4... + +---+---+---+---+================================+ + | LEN | NLEN |... LEN bytes of literal data...| + +---+---+---+---+================================+ + + LEN is the number of data bytes in the block. NLEN is the + one's complement of LEN. + + 3.2.5. Compressed blocks (length and distance codes) + + As noted above, encoded data blocks in the "deflate" format + consist of sequences of symbols drawn from three conceptually + distinct alphabets: either literal bytes, from the alphabet of + byte values (0..255), or pairs, + where the length is drawn from (3..258) and the distance is + drawn from (1..32,768). In fact, the literal and length + alphabets are merged into a single alphabet (0..285), where + values 0..255 represent literal bytes, the value 256 indicates + end-of-block, and values 257..285 represent length codes + (possibly in conjunction with extra bits following the symbol + code) as follows: + + + + + + + + + + + + + + + + +Deutsch Informational [Page 11] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + Extra Extra Extra + Code Bits Length(s) Code Bits Lengths Code Bits Length(s) + ---- ---- ------ ---- ---- ------- ---- ---- ------- + 257 0 3 267 1 15,16 277 4 67-82 + 258 0 4 268 1 17,18 278 4 83-98 + 259 0 5 269 2 19-22 279 4 99-114 + 260 0 6 270 2 23-26 280 4 115-130 + 261 0 7 271 2 27-30 281 5 131-162 + 262 0 8 272 2 31-34 282 5 163-194 + 263 0 9 273 3 35-42 283 5 195-226 + 264 0 10 274 3 43-50 284 5 227-257 + 265 1 11,12 275 3 51-58 285 0 258 + 266 1 13,14 276 3 59-66 + + The extra bits should be interpreted as a machine integer + stored with the most-significant bit first, e.g., bits 1110 + represent the value 14. + + Extra Extra Extra + Code Bits Dist Code Bits Dist Code Bits Distance + ---- ---- ---- ---- ---- ------ ---- ---- -------- + 0 0 1 10 4 33-48 20 9 1025-1536 + 1 0 2 11 4 49-64 21 9 1537-2048 + 2 0 3 12 5 65-96 22 10 2049-3072 + 3 0 4 13 5 97-128 23 10 3073-4096 + 4 1 5,6 14 6 129-192 24 11 4097-6144 + 5 1 7,8 15 6 193-256 25 11 6145-8192 + 6 2 9-12 16 7 257-384 26 12 8193-12288 + 7 2 13-16 17 7 385-512 27 12 12289-16384 + 8 3 17-24 18 8 513-768 28 13 16385-24576 + 9 3 25-32 19 8 769-1024 29 13 24577-32768 + + 3.2.6. Compression with fixed Huffman codes (BTYPE=01) + + The Huffman codes for the two alphabets are fixed, and are not + represented explicitly in the data. The Huffman code lengths + for the literal/length alphabet are: + + Lit Value Bits Codes + --------- ---- ----- + 0 - 143 8 00110000 through + 10111111 + 144 - 255 9 110010000 through + 111111111 + 256 - 279 7 0000000 through + 0010111 + 280 - 287 8 11000000 through + 11000111 + + + +Deutsch Informational [Page 12] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + The code lengths are sufficient to generate the actual codes, + as described above; we show the codes in the table for added + clarity. Literal/length values 286-287 will never actually + occur in the compressed data, but participate in the code + construction. + + Distance codes 0-31 are represented by (fixed-length) 5-bit + codes, with possible additional bits as shown in the table + shown in Paragraph 3.2.5, above. Note that distance codes 30- + 31 will never actually occur in the compressed data. + + 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) + + The Huffman codes for the two alphabets appear in the block + immediately after the header bits and before the actual + compressed data, first the literal/length code and then the + distance code. Each code is defined by a sequence of code + lengths, as discussed in Paragraph 3.2.2, above. For even + greater compactness, the code length sequences themselves are + compressed using a Huffman code. The alphabet for code lengths + is as follows: + + 0 - 15: Represent code lengths of 0 - 15 + 16: Copy the previous code length 3 - 6 times. + The next 2 bits indicate repeat length + (0 = 3, ... , 3 = 6) + Example: Codes 8, 16 (+2 bits 11), + 16 (+2 bits 10) will expand to + 12 code lengths of 8 (1 + 6 + 5) + 17: Repeat a code length of 0 for 3 - 10 times. + (3 bits of length) + 18: Repeat a code length of 0 for 11 - 138 times + (7 bits of length) + + A code length of 0 indicates that the corresponding symbol in + the literal/length or distance alphabet will not occur in the + block, and should not participate in the Huffman code + construction algorithm given earlier. If only one distance + code is used, it is encoded using one bit, not zero bits; in + this case there is a single code length of one, with one unused + code. One distance code of zero bits means that there are no + distance codes used at all (the data is all literals). + + We can now define the format of the block: + + 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286) + 5 Bits: HDIST, # of Distance codes - 1 (1 - 32) + 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19) + + + +Deutsch Informational [Page 13] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + (HCLEN + 4) x 3 bits: code lengths for the code length + alphabet given just above, in the order: 16, 17, 18, + 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + + These code lengths are interpreted as 3-bit integers + (0-7); as above, a code length of 0 means the + corresponding symbol (literal/length or distance code + length) is not used. + + HLIT + 257 code lengths for the literal/length alphabet, + encoded using the code length Huffman code + + HDIST + 1 code lengths for the distance alphabet, + encoded using the code length Huffman code + + The actual compressed data of the block, + encoded using the literal/length and distance Huffman + codes + + The literal/length symbol 256 (end of data), + encoded using the literal/length Huffman code + + The code length repeat codes can cross from HLIT + 257 to the + HDIST + 1 code lengths. In other words, all code lengths form + a single sequence of HLIT + HDIST + 258 values. + + 3.3. Compliance + + A compressor may limit further the ranges of values specified in + the previous section and still be compliant; for example, it may + limit the range of backward pointers to some value smaller than + 32K. Similarly, a compressor may limit the size of blocks so that + a compressible block fits in memory. + + A compliant decompressor must accept the full range of possible + values defined in the previous section, and must accept blocks of + arbitrary size. + +4. Compression algorithm details + + While it is the intent of this document to define the "deflate" + compressed data format without reference to any particular + compression algorithm, the format is related to the compressed + formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below); + since many variations of LZ77 are patented, it is strongly + recommended that the implementor of a compressor follow the general + algorithm presented here, which is known not to be patented per se. + The material in this section is not part of the definition of the + + + +Deutsch Informational [Page 14] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + specification per se, and a compressor need not follow it in order to + be compliant. + + The compressor terminates a block when it determines that starting a + new block with fresh trees would be useful, or when the block size + fills up the compressor's block buffer. + + The compressor uses a chained hash table to find duplicated strings, + using a hash function that operates on 3-byte sequences. At any + given point during compression, let XYZ be the next 3 input bytes to + be examined (not necessarily all different, of course). First, the + compressor examines the hash chain for XYZ. If the chain is empty, + the compressor simply writes out X as a literal byte and advances one + byte in the input. If the hash chain is not empty, indicating that + the sequence XYZ (or, if we are unlucky, some other 3 bytes with the + same hash function value) has occurred recently, the compressor + compares all strings on the XYZ hash chain with the actual input data + sequence starting at the current point, and selects the longest + match. + + The compressor searches the hash chains starting with the most recent + strings, to favor small distances and thus take advantage of the + Huffman encoding. The hash chains are singly linked. There are no + deletions from the hash chains; the algorithm simply discards matches + that are too old. To avoid a worst-case situation, very long hash + chains are arbitrarily truncated at a certain length, determined by a + run-time parameter. + + To improve overall compression, the compressor optionally defers the + selection of matches ("lazy matching"): after a match of length N has + been found, the compressor searches for a longer match starting at + the next input byte. If it finds a longer match, it truncates the + previous match to a length of one (thus producing a single literal + byte) and then emits the longer match. Otherwise, it emits the + original match, and, as described above, advances N bytes before + continuing. + + Run-time parameters also control this "lazy match" procedure. If + compression ratio is most important, the compressor attempts a + complete second search regardless of the length of the first match. + In the normal case, if the current match is "long enough", the + compressor reduces the search for a longer match, thus speeding up + the process. If speed is most important, the compressor inserts new + strings in the hash table only when no match was found, or when the + match is not "too long". This degrades the compression ratio but + saves time since there are both fewer insertions and fewer searches. + + + + + +Deutsch Informational [Page 15] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + +5. References + + [1] Huffman, D. A., "A Method for the Construction of Minimum + Redundancy Codes", Proceedings of the Institute of Radio + Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101. + + [2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data + Compression", IEEE Transactions on Information Theory, Vol. 23, + No. 3, pp. 337-343. + + [3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources, + available in ftp://ftp.uu.net/pub/archiving/zip/doc/ + + [4] Gailly, J.-L., and Adler, M., GZIP documentation and sources, + available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/ + + [5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix + encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169. + + [6] Hirschberg and Lelewer, "Efficient decoding of prefix codes," + Comm. ACM, 33,4, April 1990, pp. 449-459. + +6. Security Considerations + + Any data compression method involves the reduction of redundancy in + the data. Consequently, any corruption of the data is likely to have + severe effects and be difficult to correct. Uncompressed text, on + the other hand, will probably still be readable despite the presence + of some corrupted bytes. + + It is recommended that systems using this data format provide some + means of validating the integrity of the compressed data. See + reference [3], for example. + +7. Source code + + Source code for a C language implementation of a "deflate" compliant + compressor and decompressor is available within the zlib package at + ftp://ftp.uu.net/pub/archiving/zip/zlib/. + +8. Acknowledgements + + Trademarks cited in this document are the property of their + respective owners. + + Phil Katz designed the deflate format. Jean-Loup Gailly and Mark + Adler wrote the related software described in this specification. + Glenn Randers-Pehrson converted this document to RFC and HTML format. + + + +Deutsch Informational [Page 16] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + +9. Author's Address + + L. Peter Deutsch + Aladdin Enterprises + 203 Santa Margarita Ave. + Menlo Park, CA 94025 + + Phone: (415) 322-0103 (AM only) + FAX: (415) 322-1734 + EMail: + + Questions about the technical content of this specification can be + sent by email to: + + Jean-Loup Gailly and + Mark Adler + + Editorial comments on this specification can be sent by email to: + + L. Peter Deutsch and + Glenn Randers-Pehrson + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Deutsch Informational [Page 17] + diff --git a/zlib-1.2.11/doc/rfc1952.txt b/zlib-1.2.11/doc/rfc1952.txt new file mode 100644 index 00000000..a8e51b45 --- /dev/null +++ b/zlib-1.2.11/doc/rfc1952.txt @@ -0,0 +1,675 @@ + + + + + + +Network Working Group P. Deutsch +Request for Comments: 1952 Aladdin Enterprises +Category: Informational May 1996 + + + GZIP file format specification version 4.3 + +Status of This Memo + + This memo provides information for the Internet community. This memo + does not specify an Internet standard of any kind. Distribution of + this memo is unlimited. + +IESG Note: + + The IESG takes no position on the validity of any Intellectual + Property Rights statements contained in this document. + +Notices + + Copyright (c) 1996 L. Peter Deutsch + + Permission is granted to copy and distribute this document for any + purpose and without charge, including translations into other + languages and incorporation into compilations, provided that the + copyright notice and this notice are preserved, and that any + substantive changes or deletions from the original are clearly + marked. + + A pointer to the latest version of this and related documentation in + HTML format can be found at the URL + . + +Abstract + + This specification defines a lossless compressed data format that is + compatible with the widely used GZIP utility. The format includes a + cyclic redundancy check value for detecting data corruption. The + format presently uses the DEFLATE method of compression but can be + easily extended to use other compression methods. The format can be + implemented readily in a manner not covered by patents. + + + + + + + + + + +Deutsch Informational [Page 1] + +RFC 1952 GZIP File Format Specification May 1996 + + +Table of Contents + + 1. Introduction ................................................... 2 + 1.1. Purpose ................................................... 2 + 1.2. Intended audience ......................................... 3 + 1.3. Scope ..................................................... 3 + 1.4. Compliance ................................................ 3 + 1.5. Definitions of terms and conventions used ................. 3 + 1.6. Changes from previous versions ............................ 3 + 2. Detailed specification ......................................... 4 + 2.1. Overall conventions ....................................... 4 + 2.2. File format ............................................... 5 + 2.3. Member format ............................................. 5 + 2.3.1. Member header and trailer ........................... 6 + 2.3.1.1. Extra field ................................... 8 + 2.3.1.2. Compliance .................................... 9 + 3. References .................................................. 9 + 4. Security Considerations .................................... 10 + 5. Acknowledgements ........................................... 10 + 6. Author's Address ........................................... 10 + 7. Appendix: Jean-Loup Gailly's gzip utility .................. 11 + 8. Appendix: Sample CRC Code .................................. 11 + +1. Introduction + + 1.1. Purpose + + The purpose of this specification is to define a lossless + compressed data format that: + + * Is independent of CPU type, operating system, file system, + and character set, and hence can be used for interchange; + * Can compress or decompress a data stream (as opposed to a + randomly accessible file) to produce another data stream, + using only an a priori bounded amount of intermediate + storage, and hence can be used in data communications or + similar structures such as Unix filters; + * Compresses data with efficiency comparable to the best + currently available general-purpose compression methods, + and in particular considerably better than the "compress" + program; + * Can be implemented readily in a manner not covered by + patents, and hence can be practiced freely; + * Is compatible with the file format produced by the current + widely used gzip utility, in that conforming decompressors + will be able to read data produced by the existing gzip + compressor. + + + + +Deutsch Informational [Page 2] + +RFC 1952 GZIP File Format Specification May 1996 + + + The data format defined by this specification does not attempt to: + + * Provide random access to compressed data; + * Compress specialized data (e.g., raster graphics) as well as + the best currently available specialized algorithms. + + 1.2. Intended audience + + This specification is intended for use by implementors of software + to compress data into gzip format and/or decompress data from gzip + format. + + The text of the specification assumes a basic background in + programming at the level of bits and other primitive data + representations. + + 1.3. Scope + + The specification specifies a compression method and a file format + (the latter assuming only that a file can store a sequence of + arbitrary bytes). It does not specify any particular interface to + a file system or anything about character sets or encodings + (except for file names and comments, which are optional). + + 1.4. Compliance + + Unless otherwise indicated below, a compliant decompressor must be + able to accept and decompress any file that conforms to all the + specifications presented here; a compliant compressor must produce + files that conform to all the specifications presented here. The + material in the appendices is not part of the specification per se + and is not relevant to compliance. + + 1.5. Definitions of terms and conventions used + + byte: 8 bits stored or transmitted as a unit (same as an octet). + (For this specification, a byte is exactly 8 bits, even on + machines which store a character on a number of bits different + from 8.) See below for the numbering of bits within a byte. + + 1.6. Changes from previous versions + + There have been no technical changes to the gzip format since + version 4.1 of this specification. In version 4.2, some + terminology was changed, and the sample CRC code was rewritten for + clarity and to eliminate the requirement for the caller to do pre- + and post-conditioning. Version 4.3 is a conversion of the + specification to RFC style. + + + +Deutsch Informational [Page 3] + +RFC 1952 GZIP File Format Specification May 1996 + + +2. Detailed specification + + 2.1. Overall conventions + + In the diagrams below, a box like this: + + +---+ + | | <-- the vertical bars might be missing + +---+ + + represents one byte; a box like this: + + +==============+ + | | + +==============+ + + represents a variable number of bytes. + + Bytes stored within a computer do not have a "bit order", since + they are always treated as a unit. However, a byte considered as + an integer between 0 and 255 does have a most- and least- + significant bit, and since we write numbers with the most- + significant digit on the left, we also write bytes with the most- + significant bit on the left. In the diagrams below, we number the + bits of a byte so that bit 0 is the least-significant bit, i.e., + the bits are numbered: + + +--------+ + |76543210| + +--------+ + + This document does not address the issue of the order in which + bits of a byte are transmitted on a bit-sequential medium, since + the data format described here is byte- rather than bit-oriented. + + Within a computer, a number may occupy multiple bytes. All + multi-byte numbers in the format described here are stored with + the least-significant byte first (at the lower memory address). + For example, the decimal number 520 is stored as: + + 0 1 + +--------+--------+ + |00001000|00000010| + +--------+--------+ + ^ ^ + | | + | + more significant byte = 2 x 256 + + less significant byte = 8 + + + +Deutsch Informational [Page 4] + +RFC 1952 GZIP File Format Specification May 1996 + + + 2.2. File format + + A gzip file consists of a series of "members" (compressed data + sets). The format of each member is specified in the following + section. The members simply appear one after another in the file, + with no additional information before, between, or after them. + + 2.3. Member format + + Each member has the following structure: + + +---+---+---+---+---+---+---+---+---+---+ + |ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->) + +---+---+---+---+---+---+---+---+---+---+ + + (if FLG.FEXTRA set) + + +---+---+=================================+ + | XLEN |...XLEN bytes of "extra field"...| (more-->) + +---+---+=================================+ + + (if FLG.FNAME set) + + +=========================================+ + |...original file name, zero-terminated...| (more-->) + +=========================================+ + + (if FLG.FCOMMENT set) + + +===================================+ + |...file comment, zero-terminated...| (more-->) + +===================================+ + + (if FLG.FHCRC set) + + +---+---+ + | CRC16 | + +---+---+ + + +=======================+ + |...compressed blocks...| (more-->) + +=======================+ + + 0 1 2 3 4 5 6 7 + +---+---+---+---+---+---+---+---+ + | CRC32 | ISIZE | + +---+---+---+---+---+---+---+---+ + + + + +Deutsch Informational [Page 5] + +RFC 1952 GZIP File Format Specification May 1996 + + + 2.3.1. Member header and trailer + + ID1 (IDentification 1) + ID2 (IDentification 2) + These have the fixed values ID1 = 31 (0x1f, \037), ID2 = 139 + (0x8b, \213), to identify the file as being in gzip format. + + CM (Compression Method) + This identifies the compression method used in the file. CM + = 0-7 are reserved. CM = 8 denotes the "deflate" + compression method, which is the one customarily used by + gzip and which is documented elsewhere. + + FLG (FLaGs) + This flag byte is divided into individual bits as follows: + + bit 0 FTEXT + bit 1 FHCRC + bit 2 FEXTRA + bit 3 FNAME + bit 4 FCOMMENT + bit 5 reserved + bit 6 reserved + bit 7 reserved + + If FTEXT is set, the file is probably ASCII text. This is + an optional indication, which the compressor may set by + checking a small amount of the input data to see whether any + non-ASCII characters are present. In case of doubt, FTEXT + is cleared, indicating binary data. For systems which have + different file formats for ascii text and binary data, the + decompressor can use FTEXT to choose the appropriate format. + We deliberately do not specify the algorithm used to set + this bit, since a compressor always has the option of + leaving it cleared and a decompressor always has the option + of ignoring it and letting some other program handle issues + of data conversion. + + If FHCRC is set, a CRC16 for the gzip header is present, + immediately before the compressed data. The CRC16 consists + of the two least significant bytes of the CRC32 for all + bytes of the gzip header up to and not including the CRC16. + [The FHCRC bit was never set by versions of gzip up to + 1.2.4, even though it was documented with a different + meaning in gzip 1.2.4.] + + If FEXTRA is set, optional extra fields are present, as + described in a following section. + + + +Deutsch Informational [Page 6] + +RFC 1952 GZIP File Format Specification May 1996 + + + If FNAME is set, an original file name is present, + terminated by a zero byte. The name must consist of ISO + 8859-1 (LATIN-1) characters; on operating systems using + EBCDIC or any other character set for file names, the name + must be translated to the ISO LATIN-1 character set. This + is the original name of the file being compressed, with any + directory components removed, and, if the file being + compressed is on a file system with case insensitive names, + forced to lower case. There is no original file name if the + data was compressed from a source other than a named file; + for example, if the source was stdin on a Unix system, there + is no file name. + + If FCOMMENT is set, a zero-terminated file comment is + present. This comment is not interpreted; it is only + intended for human consumption. The comment must consist of + ISO 8859-1 (LATIN-1) characters. Line breaks should be + denoted by a single line feed character (10 decimal). + + Reserved FLG bits must be zero. + + MTIME (Modification TIME) + This gives the most recent modification time of the original + file being compressed. The time is in Unix format, i.e., + seconds since 00:00:00 GMT, Jan. 1, 1970. (Note that this + may cause problems for MS-DOS and other systems that use + local rather than Universal time.) If the compressed data + did not come from a file, MTIME is set to the time at which + compression started. MTIME = 0 means no time stamp is + available. + + XFL (eXtra FLags) + These flags are available for use by specific compression + methods. The "deflate" method (CM = 8) sets these flags as + follows: + + XFL = 2 - compressor used maximum compression, + slowest algorithm + XFL = 4 - compressor used fastest algorithm + + OS (Operating System) + This identifies the type of file system on which compression + took place. This may be useful in determining end-of-line + convention for text files. The currently defined values are + as follows: + + + + + + +Deutsch Informational [Page 7] + +RFC 1952 GZIP File Format Specification May 1996 + + + 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32) + 1 - Amiga + 2 - VMS (or OpenVMS) + 3 - Unix + 4 - VM/CMS + 5 - Atari TOS + 6 - HPFS filesystem (OS/2, NT) + 7 - Macintosh + 8 - Z-System + 9 - CP/M + 10 - TOPS-20 + 11 - NTFS filesystem (NT) + 12 - QDOS + 13 - Acorn RISCOS + 255 - unknown + + XLEN (eXtra LENgth) + If FLG.FEXTRA is set, this gives the length of the optional + extra field. See below for details. + + CRC32 (CRC-32) + This contains a Cyclic Redundancy Check value of the + uncompressed data computed according to CRC-32 algorithm + used in the ISO 3309 standard and in section 8.1.1.6.2 of + ITU-T recommendation V.42. (See http://www.iso.ch for + ordering ISO documents. See gopher://info.itu.ch for an + online version of ITU-T V.42.) + + ISIZE (Input SIZE) + This contains the size of the original (uncompressed) input + data modulo 2^32. + + 2.3.1.1. Extra field + + If the FLG.FEXTRA bit is set, an "extra field" is present in + the header, with total length XLEN bytes. It consists of a + series of subfields, each of the form: + + +---+---+---+---+==================================+ + |SI1|SI2| LEN |... LEN bytes of subfield data ...| + +---+---+---+---+==================================+ + + SI1 and SI2 provide a subfield ID, typically two ASCII letters + with some mnemonic value. Jean-Loup Gailly + is maintaining a registry of subfield + IDs; please send him any subfield ID you wish to use. Subfield + IDs with SI2 = 0 are reserved for future use. The following + IDs are currently defined: + + + +Deutsch Informational [Page 8] + +RFC 1952 GZIP File Format Specification May 1996 + + + SI1 SI2 Data + ---------- ---------- ---- + 0x41 ('A') 0x70 ('P') Apollo file type information + + LEN gives the length of the subfield data, excluding the 4 + initial bytes. + + 2.3.1.2. Compliance + + A compliant compressor must produce files with correct ID1, + ID2, CM, CRC32, and ISIZE, but may set all the other fields in + the fixed-length part of the header to default values (255 for + OS, 0 for all others). The compressor must set all reserved + bits to zero. + + A compliant decompressor must check ID1, ID2, and CM, and + provide an error indication if any of these have incorrect + values. It must examine FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC + at least so it can skip over the optional fields if they are + present. It need not examine any other part of the header or + trailer; in particular, a decompressor may ignore FTEXT and OS + and always produce binary output, and still be compliant. A + compliant decompressor must give an error indication if any + reserved bit is non-zero, since such a bit could indicate the + presence of a new field that would cause subsequent data to be + interpreted incorrectly. + +3. References + + [1] "Information Processing - 8-bit single-byte coded graphic + character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987). + The ISO 8859-1 (Latin-1) character set is a superset of 7-bit + ASCII. Files defining this character set are available as + iso_8859-1.* in ftp://ftp.uu.net/graphics/png/documents/ + + [2] ISO 3309 + + [3] ITU-T recommendation V.42 + + [4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification", + available in ftp://ftp.uu.net/pub/archiving/zip/doc/ + + [5] Gailly, J.-L., GZIP documentation, available as gzip-*.tar in + ftp://prep.ai.mit.edu/pub/gnu/ + + [6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table + Look-Up", Communications of the ACM, 31(8), pp.1008-1013. + + + + +Deutsch Informational [Page 9] + +RFC 1952 GZIP File Format Specification May 1996 + + + [7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal, + pp.118-133. + + [8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt, + describing the CRC concept. + +4. Security Considerations + + Any data compression method involves the reduction of redundancy in + the data. Consequently, any corruption of the data is likely to have + severe effects and be difficult to correct. Uncompressed text, on + the other hand, will probably still be readable despite the presence + of some corrupted bytes. + + It is recommended that systems using this data format provide some + means of validating the integrity of the compressed data, such as by + setting and checking the CRC-32 check value. + +5. Acknowledgements + + Trademarks cited in this document are the property of their + respective owners. + + Jean-Loup Gailly designed the gzip format and wrote, with Mark Adler, + the related software described in this specification. Glenn + Randers-Pehrson converted this document to RFC and HTML format. + +6. Author's Address + + L. Peter Deutsch + Aladdin Enterprises + 203 Santa Margarita Ave. + Menlo Park, CA 94025 + + Phone: (415) 322-0103 (AM only) + FAX: (415) 322-1734 + EMail: + + Questions about the technical content of this specification can be + sent by email to: + + Jean-Loup Gailly and + Mark Adler + + Editorial comments on this specification can be sent by email to: + + L. Peter Deutsch and + Glenn Randers-Pehrson + + + +Deutsch Informational [Page 10] + +RFC 1952 GZIP File Format Specification May 1996 + + +7. Appendix: Jean-Loup Gailly's gzip utility + + The most widely used implementation of gzip compression, and the + original documentation on which this specification is based, were + created by Jean-Loup Gailly . Since this + implementation is a de facto standard, we mention some more of its + features here. Again, the material in this section is not part of + the specification per se, and implementations need not follow it to + be compliant. + + When compressing or decompressing a file, gzip preserves the + protection, ownership, and modification time attributes on the local + file system, since there is no provision for representing protection + attributes in the gzip file format itself. Since the file format + includes a modification time, the gzip decompressor provides a + command line switch that assigns the modification time from the file, + rather than the local modification time of the compressed input, to + the decompressed output. + +8. Appendix: Sample CRC Code + + The following sample code represents a practical implementation of + the CRC (Cyclic Redundancy Check). (See also ISO 3309 and ITU-T V.42 + for a formal specification.) + + The sample code is in the ANSI C programming language. Non C users + may find it easier to read with these hints: + + & Bitwise AND operator. + ^ Bitwise exclusive-OR operator. + >> Bitwise right shift operator. When applied to an + unsigned quantity, as here, right shift inserts zero + bit(s) at the left. + ! Logical NOT operator. + ++ "n++" increments the variable n. + 0xNNN 0x introduces a hexadecimal (base 16) constant. + Suffix L indicates a long value (at least 32 bits). + + /* Table of CRCs of all 8-bit messages. */ + unsigned long crc_table[256]; + + /* Flag: has the table been computed? Initially false. */ + int crc_table_computed = 0; + + /* Make the table for a fast CRC. */ + void make_crc_table(void) + { + unsigned long c; + + + +Deutsch Informational [Page 11] + +RFC 1952 GZIP File Format Specification May 1996 + + + int n, k; + for (n = 0; n < 256; n++) { + c = (unsigned long) n; + for (k = 0; k < 8; k++) { + if (c & 1) { + c = 0xedb88320L ^ (c >> 1); + } else { + c = c >> 1; + } + } + crc_table[n] = c; + } + crc_table_computed = 1; + } + + /* + Update a running crc with the bytes buf[0..len-1] and return + the updated crc. The crc should be initialized to zero. Pre- and + post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the caller. Usage example: + + unsigned long crc = 0L; + + while (read_buffer(buffer, length) != EOF) { + crc = update_crc(crc, buffer, length); + } + if (crc != original_crc) error(); + */ + unsigned long update_crc(unsigned long crc, + unsigned char *buf, int len) + { + unsigned long c = crc ^ 0xffffffffL; + int n; + + if (!crc_table_computed) + make_crc_table(); + for (n = 0; n < len; n++) { + c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); + } + return c ^ 0xffffffffL; + } + + /* Return the CRC of the bytes buf[0..len-1]. */ + unsigned long crc(unsigned char *buf, int len) + { + return update_crc(0L, buf, len); + } + + + + +Deutsch Informational [Page 12] + diff --git a/zlib-1.2.11/doc/txtvsbin.txt b/zlib-1.2.11/doc/txtvsbin.txt new file mode 100644 index 00000000..3d0f0634 --- /dev/null +++ b/zlib-1.2.11/doc/txtvsbin.txt @@ -0,0 +1,107 @@ +A Fast Method for Identifying Plain Text Files +============================================== + + +Introduction +------------ + +Given a file coming from an unknown source, it is sometimes desirable +to find out whether the format of that file is plain text. Although +this may appear like a simple task, a fully accurate detection of the +file type requires heavy-duty semantic analysis on the file contents. +It is, however, possible to obtain satisfactory results by employing +various heuristics. + +Previous versions of PKZip and other zip-compatible compression tools +were using a crude detection scheme: if more than 80% (4/5) of the bytes +found in a certain buffer are within the range [7..127], the file is +labeled as plain text, otherwise it is labeled as binary. A prominent +limitation of this scheme is the restriction to Latin-based alphabets. +Other alphabets, like Greek, Cyrillic or Asian, make extensive use of +the bytes within the range [128..255], and texts using these alphabets +are most often misidentified by this scheme; in other words, the rate +of false negatives is sometimes too high, which means that the recall +is low. Another weakness of this scheme is a reduced precision, due to +the false positives that may occur when binary files containing large +amounts of textual characters are misidentified as plain text. + +In this article we propose a new, simple detection scheme that features +a much increased precision and a near-100% recall. This scheme is +designed to work on ASCII, Unicode and other ASCII-derived alphabets, +and it handles single-byte encodings (ISO-8859, MacRoman, KOI8, etc.) +and variable-sized encodings (ISO-2022, UTF-8, etc.). Wider encodings +(UCS-2/UTF-16 and UCS-4/UTF-32) are not handled, however. + + +The Algorithm +------------- + +The algorithm works by dividing the set of bytecodes [0..255] into three +categories: +- The white list of textual bytecodes: + 9 (TAB), 10 (LF), 13 (CR), 32 (SPACE) to 255. +- The gray list of tolerated bytecodes: + 7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB), 27 (ESC). +- The black list of undesired, non-textual bytecodes: + 0 (NUL) to 6, 14 to 31. + +If a file contains at least one byte that belongs to the white list and +no byte that belongs to the black list, then the file is categorized as +plain text; otherwise, it is categorized as binary. (The boundary case, +when the file is empty, automatically falls into the latter category.) + + +Rationale +--------- + +The idea behind this algorithm relies on two observations. + +The first observation is that, although the full range of 7-bit codes +[0..127] is properly specified by the ASCII standard, most control +characters in the range [0..31] are not used in practice. The only +widely-used, almost universally-portable control codes are 9 (TAB), +10 (LF) and 13 (CR). There are a few more control codes that are +recognized on a reduced range of platforms and text viewers/editors: +7 (BEL), 8 (BS), 11 (VT), 12 (FF), 26 (SUB) and 27 (ESC); but these +codes are rarely (if ever) used alone, without being accompanied by +some printable text. Even the newer, portable text formats such as +XML avoid using control characters outside the list mentioned here. + +The second observation is that most of the binary files tend to contain +control characters, especially 0 (NUL). Even though the older text +detection schemes observe the presence of non-ASCII codes from the range +[128..255], the precision rarely has to suffer if this upper range is +labeled as textual, because the files that are genuinely binary tend to +contain both control characters and codes from the upper range. On the +other hand, the upper range needs to be labeled as textual, because it +is used by virtually all ASCII extensions. In particular, this range is +used for encoding non-Latin scripts. + +Since there is no counting involved, other than simply observing the +presence or the absence of some byte values, the algorithm produces +consistent results, regardless what alphabet encoding is being used. +(If counting were involved, it could be possible to obtain different +results on a text encoded, say, using ISO-8859-16 versus UTF-8.) + +There is an extra category of plain text files that are "polluted" with +one or more black-listed codes, either by mistake or by peculiar design +considerations. In such cases, a scheme that tolerates a small fraction +of black-listed codes would provide an increased recall (i.e. more true +positives). This, however, incurs a reduced precision overall, since +false positives are more likely to appear in binary files that contain +large chunks of textual data. Furthermore, "polluted" plain text should +be regarded as binary by general-purpose text detection schemes, because +general-purpose text processing algorithms might not be applicable. +Under this premise, it is safe to say that our detection method provides +a near-100% recall. + +Experiments have been run on many files coming from various platforms +and applications. We tried plain text files, system logs, source code, +formatted office documents, compiled object code, etc. The results +confirm the optimistic assumptions about the capabilities of this +algorithm. + + +-- +Cosmin Truta +Last updated: 2006-May-28 diff --git a/zlib-1.2.11/examples/README.examples b/zlib-1.2.11/examples/README.examples new file mode 100644 index 00000000..56a31714 --- /dev/null +++ b/zlib-1.2.11/examples/README.examples @@ -0,0 +1,49 @@ +This directory contains examples of the use of zlib and other relevant +programs and documentation. + +enough.c + calculation and justification of ENOUGH parameter in inftrees.h + - calculates the maximum table space used in inflate tree + construction over all possible Huffman codes + +fitblk.c + compress just enough input to nearly fill a requested output size + - zlib isn't designed to do this, but fitblk does it anyway + +gun.c + uncompress a gzip file + - illustrates the use of inflateBack() for high speed file-to-file + decompression using call-back functions + - is approximately twice as fast as gzip -d + - also provides Unix uncompress functionality, again twice as fast + +gzappend.c + append to a gzip file + - illustrates the use of the Z_BLOCK flush parameter for inflate() + - illustrates the use of deflatePrime() to start at any bit + +gzjoin.c + join gzip files without recalculating the crc or recompressing + - illustrates the use of the Z_BLOCK flush parameter for inflate() + - illustrates the use of crc32_combine() + +gzlog.c +gzlog.h + efficiently and robustly maintain a message log file in gzip format + - illustrates use of raw deflate, Z_PARTIAL_FLUSH, deflatePrime(), + and deflateSetDictionary() + - illustrates use of a gzip header extra field + +zlib_how.html + painfully comprehensive description of zpipe.c (see below) + - describes in excruciating detail the use of deflate() and inflate() + +zpipe.c + reads and writes zlib streams from stdin to stdout + - illustrates the proper use of deflate() and inflate() + - deeply commented in zlib_how.html (see above) + +zran.c + index a zlib or gzip stream and randomly access it + - illustrates the use of Z_BLOCK, inflatePrime(), and + inflateSetDictionary() to provide random access diff --git a/zlib-1.2.11/examples/enough.c b/zlib-1.2.11/examples/enough.c new file mode 100644 index 00000000..b9911443 --- /dev/null +++ b/zlib-1.2.11/examples/enough.c @@ -0,0 +1,572 @@ +/* enough.c -- determine the maximum size of inflate's Huffman code tables over + * all possible valid and complete Huffman codes, subject to a length limit. + * Copyright (C) 2007, 2008, 2012 Mark Adler + * Version 1.4 18 August 2012 Mark Adler + */ + +/* Version history: + 1.0 3 Jan 2007 First version (derived from codecount.c version 1.4) + 1.1 4 Jan 2007 Use faster incremental table usage computation + Prune examine() search on previously visited states + 1.2 5 Jan 2007 Comments clean up + As inflate does, decrease root for short codes + Refuse cases where inflate would increase root + 1.3 17 Feb 2008 Add argument for initial root table size + Fix bug for initial root table size == max - 1 + Use a macro to compute the history index + 1.4 18 Aug 2012 Avoid shifts more than bits in type (caused endless loop!) + Clean up comparisons of different types + Clean up code indentation + */ + +/* + Examine all possible Huffman codes for a given number of symbols and a + maximum code length in bits to determine the maximum table size for zilb's + inflate. Only complete Huffman codes are counted. + + Two codes are considered distinct if the vectors of the number of codes per + length are not identical. So permutations of the symbol assignments result + in the same code for the counting, as do permutations of the assignments of + the bit values to the codes (i.e. only canonical codes are counted). + + We build a code from shorter to longer lengths, determining how many symbols + are coded at each length. At each step, we have how many symbols remain to + be coded, what the last code length used was, and how many bit patterns of + that length remain unused. Then we add one to the code length and double the + number of unused patterns to graduate to the next code length. We then + assign all portions of the remaining symbols to that code length that + preserve the properties of a correct and eventually complete code. Those + properties are: we cannot use more bit patterns than are available; and when + all the symbols are used, there are exactly zero possible bit patterns + remaining. + + The inflate Huffman decoding algorithm uses two-level lookup tables for + speed. There is a single first-level table to decode codes up to root bits + in length (root == 9 in the current inflate implementation). The table + has 1 << root entries and is indexed by the next root bits of input. Codes + shorter than root bits have replicated table entries, so that the correct + entry is pointed to regardless of the bits that follow the short code. If + the code is longer than root bits, then the table entry points to a second- + level table. The size of that table is determined by the longest code with + that root-bit prefix. If that longest code has length len, then the table + has size 1 << (len - root), to index the remaining bits in that set of + codes. Each subsequent root-bit prefix then has its own sub-table. The + total number of table entries required by the code is calculated + incrementally as the number of codes at each bit length is populated. When + all of the codes are shorter than root bits, then root is reduced to the + longest code length, resulting in a single, smaller, one-level table. + + The inflate algorithm also provides for small values of root (relative to + the log2 of the number of symbols), where the shortest code has more bits + than root. In that case, root is increased to the length of the shortest + code. This program, by design, does not handle that case, so it is verified + that the number of symbols is less than 2^(root + 1). + + In order to speed up the examination (by about ten orders of magnitude for + the default arguments), the intermediate states in the build-up of a code + are remembered and previously visited branches are pruned. The memory + required for this will increase rapidly with the total number of symbols and + the maximum code length in bits. However this is a very small price to pay + for the vast speedup. + + First, all of the possible Huffman codes are counted, and reachable + intermediate states are noted by a non-zero count in a saved-results array. + Second, the intermediate states that lead to (root + 1) bit or longer codes + are used to look at all sub-codes from those junctures for their inflate + memory usage. (The amount of memory used is not affected by the number of + codes of root bits or less in length.) Third, the visited states in the + construction of those sub-codes and the associated calculation of the table + size is recalled in order to avoid recalculating from the same juncture. + Beginning the code examination at (root + 1) bit codes, which is enabled by + identifying the reachable nodes, accounts for about six of the orders of + magnitude of improvement for the default arguments. About another four + orders of magnitude come from not revisiting previous states. Out of + approximately 2x10^16 possible Huffman codes, only about 2x10^6 sub-codes + need to be examined to cover all of the possible table memory usage cases + for the default arguments of 286 symbols limited to 15-bit codes. + + Note that an unsigned long long type is used for counting. It is quite easy + to exceed the capacity of an eight-byte integer with a large number of + symbols and a large maximum code length, so multiple-precision arithmetic + would need to replace the unsigned long long arithmetic in that case. This + program will abort if an overflow occurs. The big_t type identifies where + the counting takes place. + + An unsigned long long type is also used for calculating the number of + possible codes remaining at the maximum length. This limits the maximum + code length to the number of bits in a long long minus the number of bits + needed to represent the symbols in a flat code. The code_t type identifies + where the bit pattern counting takes place. + */ + +#include +#include +#include +#include + +#define local static + +/* special data types */ +typedef unsigned long long big_t; /* type for code counting */ +typedef unsigned long long code_t; /* type for bit pattern counting */ +struct tab { /* type for been here check */ + size_t len; /* length of bit vector in char's */ + char *vec; /* allocated bit vector */ +}; + +/* The array for saving results, num[], is indexed with this triplet: + + syms: number of symbols remaining to code + left: number of available bit patterns at length len + len: number of bits in the codes currently being assigned + + Those indices are constrained thusly when saving results: + + syms: 3..totsym (totsym == total symbols to code) + left: 2..syms - 1, but only the evens (so syms == 8 -> 2, 4, 6) + len: 1..max - 1 (max == maximum code length in bits) + + syms == 2 is not saved since that immediately leads to a single code. left + must be even, since it represents the number of available bit patterns at + the current length, which is double the number at the previous length. + left ends at syms-1 since left == syms immediately results in a single code. + (left > sym is not allowed since that would result in an incomplete code.) + len is less than max, since the code completes immediately when len == max. + + The offset into the array is calculated for the three indices with the + first one (syms) being outermost, and the last one (len) being innermost. + We build the array with length max-1 lists for the len index, with syms-3 + of those for each symbol. There are totsym-2 of those, with each one + varying in length as a function of sym. See the calculation of index in + count() for the index, and the calculation of size in main() for the size + of the array. + + For the deflate example of 286 symbols limited to 15-bit codes, the array + has 284,284 entries, taking up 2.17 MB for an 8-byte big_t. More than + half of the space allocated for saved results is actually used -- not all + possible triplets are reached in the generation of valid Huffman codes. + */ + +/* The array for tracking visited states, done[], is itself indexed identically + to the num[] array as described above for the (syms, left, len) triplet. + Each element in the array is further indexed by the (mem, rem) doublet, + where mem is the amount of inflate table space used so far, and rem is the + remaining unused entries in the current inflate sub-table. Each indexed + element is simply one bit indicating whether the state has been visited or + not. Since the ranges for mem and rem are not known a priori, each bit + vector is of a variable size, and grows as needed to accommodate the visited + states. mem and rem are used to calculate a single index in a triangular + array. Since the range of mem is expected in the default case to be about + ten times larger than the range of rem, the array is skewed to reduce the + memory usage, with eight times the range for mem than for rem. See the + calculations for offset and bit in beenhere() for the details. + + For the deflate example of 286 symbols limited to 15-bit codes, the bit + vectors grow to total approximately 21 MB, in addition to the 4.3 MB done[] + array itself. + */ + +/* Globals to avoid propagating constants or constant pointers recursively */ +local int max; /* maximum allowed bit length for the codes */ +local int root; /* size of base code table in bits */ +local int large; /* largest code table so far */ +local size_t size; /* number of elements in num and done */ +local int *code; /* number of symbols assigned to each bit length */ +local big_t *num; /* saved results array for code counting */ +local struct tab *done; /* states already evaluated array */ + +/* Index function for num[] and done[] */ +#define INDEX(i,j,k) (((size_t)((i-1)>>1)*((i-2)>>1)+(j>>1)-1)*(max-1)+k-1) + +/* Free allocated space. Uses globals code, num, and done. */ +local void cleanup(void) +{ + size_t n; + + if (done != NULL) { + for (n = 0; n < size; n++) + if (done[n].len) + free(done[n].vec); + free(done); + } + if (num != NULL) + free(num); + if (code != NULL) + free(code); +} + +/* Return the number of possible Huffman codes using bit patterns of lengths + len through max inclusive, coding syms symbols, with left bit patterns of + length len unused -- return -1 if there is an overflow in the counting. + Keep a record of previous results in num to prevent repeating the same + calculation. Uses the globals max and num. */ +local big_t count(int syms, int len, int left) +{ + big_t sum; /* number of possible codes from this juncture */ + big_t got; /* value returned from count() */ + int least; /* least number of syms to use at this juncture */ + int most; /* most number of syms to use at this juncture */ + int use; /* number of bit patterns to use in next call */ + size_t index; /* index of this case in *num */ + + /* see if only one possible code */ + if (syms == left) + return 1; + + /* note and verify the expected state */ + assert(syms > left && left > 0 && len < max); + + /* see if we've done this one already */ + index = INDEX(syms, left, len); + got = num[index]; + if (got) + return got; /* we have -- return the saved result */ + + /* we need to use at least this many bit patterns so that the code won't be + incomplete at the next length (more bit patterns than symbols) */ + least = (left << 1) - syms; + if (least < 0) + least = 0; + + /* we can use at most this many bit patterns, lest there not be enough + available for the remaining symbols at the maximum length (if there were + no limit to the code length, this would become: most = left - 1) */ + most = (((code_t)left << (max - len)) - syms) / + (((code_t)1 << (max - len)) - 1); + + /* count all possible codes from this juncture and add them up */ + sum = 0; + for (use = least; use <= most; use++) { + got = count(syms - use, len + 1, (left - use) << 1); + sum += got; + if (got == (big_t)0 - 1 || sum < got) /* overflow */ + return (big_t)0 - 1; + } + + /* verify that all recursive calls are productive */ + assert(sum != 0); + + /* save the result and return it */ + num[index] = sum; + return sum; +} + +/* Return true if we've been here before, set to true if not. Set a bit in a + bit vector to indicate visiting this state. Each (syms,len,left) state + has a variable size bit vector indexed by (mem,rem). The bit vector is + lengthened if needed to allow setting the (mem,rem) bit. */ +local int beenhere(int syms, int len, int left, int mem, int rem) +{ + size_t index; /* index for this state's bit vector */ + size_t offset; /* offset in this state's bit vector */ + int bit; /* mask for this state's bit */ + size_t length; /* length of the bit vector in bytes */ + char *vector; /* new or enlarged bit vector */ + + /* point to vector for (syms,left,len), bit in vector for (mem,rem) */ + index = INDEX(syms, left, len); + mem -= 1 << root; + offset = (mem >> 3) + rem; + offset = ((offset * (offset + 1)) >> 1) + rem; + bit = 1 << (mem & 7); + + /* see if we've been here */ + length = done[index].len; + if (offset < length && (done[index].vec[offset] & bit) != 0) + return 1; /* done this! */ + + /* we haven't been here before -- set the bit to show we have now */ + + /* see if we need to lengthen the vector in order to set the bit */ + if (length <= offset) { + /* if we have one already, enlarge it, zero out the appended space */ + if (length) { + do { + length <<= 1; + } while (length <= offset); + vector = realloc(done[index].vec, length); + if (vector != NULL) + memset(vector + done[index].len, 0, length - done[index].len); + } + + /* otherwise we need to make a new vector and zero it out */ + else { + length = 1 << (len - root); + while (length <= offset) + length <<= 1; + vector = calloc(length, sizeof(char)); + } + + /* in either case, bail if we can't get the memory */ + if (vector == NULL) { + fputs("abort: unable to allocate enough memory\n", stderr); + cleanup(); + exit(1); + } + + /* install the new vector */ + done[index].len = length; + done[index].vec = vector; + } + + /* set the bit */ + done[index].vec[offset] |= bit; + return 0; +} + +/* Examine all possible codes from the given node (syms, len, left). Compute + the amount of memory required to build inflate's decoding tables, where the + number of code structures used so far is mem, and the number remaining in + the current sub-table is rem. Uses the globals max, code, root, large, and + done. */ +local void examine(int syms, int len, int left, int mem, int rem) +{ + int least; /* least number of syms to use at this juncture */ + int most; /* most number of syms to use at this juncture */ + int use; /* number of bit patterns to use in next call */ + + /* see if we have a complete code */ + if (syms == left) { + /* set the last code entry */ + code[len] = left; + + /* complete computation of memory used by this code */ + while (rem < left) { + left -= rem; + rem = 1 << (len - root); + mem += rem; + } + assert(rem == left); + + /* if this is a new maximum, show the entries used and the sub-code */ + if (mem > large) { + large = mem; + printf("max %d: ", mem); + for (use = root + 1; use <= max; use++) + if (code[use]) + printf("%d[%d] ", code[use], use); + putchar('\n'); + fflush(stdout); + } + + /* remove entries as we drop back down in the recursion */ + code[len] = 0; + return; + } + + /* prune the tree if we can */ + if (beenhere(syms, len, left, mem, rem)) + return; + + /* we need to use at least this many bit patterns so that the code won't be + incomplete at the next length (more bit patterns than symbols) */ + least = (left << 1) - syms; + if (least < 0) + least = 0; + + /* we can use at most this many bit patterns, lest there not be enough + available for the remaining symbols at the maximum length (if there were + no limit to the code length, this would become: most = left - 1) */ + most = (((code_t)left << (max - len)) - syms) / + (((code_t)1 << (max - len)) - 1); + + /* occupy least table spaces, creating new sub-tables as needed */ + use = least; + while (rem < use) { + use -= rem; + rem = 1 << (len - root); + mem += rem; + } + rem -= use; + + /* examine codes from here, updating table space as we go */ + for (use = least; use <= most; use++) { + code[len] = use; + examine(syms - use, len + 1, (left - use) << 1, + mem + (rem ? 1 << (len - root) : 0), rem << 1); + if (rem == 0) { + rem = 1 << (len - root); + mem += rem; + } + rem--; + } + + /* remove entries as we drop back down in the recursion */ + code[len] = 0; +} + +/* Look at all sub-codes starting with root + 1 bits. Look at only the valid + intermediate code states (syms, left, len). For each completed code, + calculate the amount of memory required by inflate to build the decoding + tables. Find the maximum amount of memory required and show the code that + requires that maximum. Uses the globals max, root, and num. */ +local void enough(int syms) +{ + int n; /* number of remaing symbols for this node */ + int left; /* number of unused bit patterns at this length */ + size_t index; /* index of this case in *num */ + + /* clear code */ + for (n = 0; n <= max; n++) + code[n] = 0; + + /* look at all (root + 1) bit and longer codes */ + large = 1 << root; /* base table */ + if (root < max) /* otherwise, there's only a base table */ + for (n = 3; n <= syms; n++) + for (left = 2; left < n; left += 2) + { + /* look at all reachable (root + 1) bit nodes, and the + resulting codes (complete at root + 2 or more) */ + index = INDEX(n, left, root + 1); + if (root + 1 < max && num[index]) /* reachable node */ + examine(n, root + 1, left, 1 << root, 0); + + /* also look at root bit codes with completions at root + 1 + bits (not saved in num, since complete), just in case */ + if (num[index - 1] && n <= left << 1) + examine((n - left) << 1, root + 1, (n - left) << 1, + 1 << root, 0); + } + + /* done */ + printf("done: maximum of %d table entries\n", large); +} + +/* + Examine and show the total number of possible Huffman codes for a given + maximum number of symbols, initial root table size, and maximum code length + in bits -- those are the command arguments in that order. The default + values are 286, 9, and 15 respectively, for the deflate literal/length code. + The possible codes are counted for each number of coded symbols from two to + the maximum. The counts for each of those and the total number of codes are + shown. The maximum number of inflate table entires is then calculated + across all possible codes. Each new maximum number of table entries and the + associated sub-code (starting at root + 1 == 10 bits) is shown. + + To count and examine Huffman codes that are not length-limited, provide a + maximum length equal to the number of symbols minus one. + + For the deflate literal/length code, use "enough". For the deflate distance + code, use "enough 30 6". + + This uses the %llu printf format to print big_t numbers, which assumes that + big_t is an unsigned long long. If the big_t type is changed (for example + to a multiple precision type), the method of printing will also need to be + updated. + */ +int main(int argc, char **argv) +{ + int syms; /* total number of symbols to code */ + int n; /* number of symbols to code for this run */ + big_t got; /* return value of count() */ + big_t sum; /* accumulated number of codes over n */ + code_t word; /* for counting bits in code_t */ + + /* set up globals for cleanup() */ + code = NULL; + num = NULL; + done = NULL; + + /* get arguments -- default to the deflate literal/length code */ + syms = 286; + root = 9; + max = 15; + if (argc > 1) { + syms = atoi(argv[1]); + if (argc > 2) { + root = atoi(argv[2]); + if (argc > 3) + max = atoi(argv[3]); + } + } + if (argc > 4 || syms < 2 || root < 1 || max < 1) { + fputs("invalid arguments, need: [sym >= 2 [root >= 1 [max >= 1]]]\n", + stderr); + return 1; + } + + /* if not restricting the code length, the longest is syms - 1 */ + if (max > syms - 1) + max = syms - 1; + + /* determine the number of bits in a code_t */ + for (n = 0, word = 1; word; n++, word <<= 1) + ; + + /* make sure that the calculation of most will not overflow */ + if (max > n || (code_t)(syms - 2) >= (((code_t)0 - 1) >> (max - 1))) { + fputs("abort: code length too long for internal types\n", stderr); + return 1; + } + + /* reject impossible code requests */ + if ((code_t)(syms - 1) > ((code_t)1 << max) - 1) { + fprintf(stderr, "%d symbols cannot be coded in %d bits\n", + syms, max); + return 1; + } + + /* allocate code vector */ + code = calloc(max + 1, sizeof(int)); + if (code == NULL) { + fputs("abort: unable to allocate enough memory\n", stderr); + return 1; + } + + /* determine size of saved results array, checking for overflows, + allocate and clear the array (set all to zero with calloc()) */ + if (syms == 2) /* iff max == 1 */ + num = NULL; /* won't be saving any results */ + else { + size = syms >> 1; + if (size > ((size_t)0 - 1) / (n = (syms - 1) >> 1) || + (size *= n, size > ((size_t)0 - 1) / (n = max - 1)) || + (size *= n, size > ((size_t)0 - 1) / sizeof(big_t)) || + (num = calloc(size, sizeof(big_t))) == NULL) { + fputs("abort: unable to allocate enough memory\n", stderr); + cleanup(); + return 1; + } + } + + /* count possible codes for all numbers of symbols, add up counts */ + sum = 0; + for (n = 2; n <= syms; n++) { + got = count(n, 1, 2); + sum += got; + if (got == (big_t)0 - 1 || sum < got) { /* overflow */ + fputs("abort: can't count that high!\n", stderr); + cleanup(); + return 1; + } + printf("%llu %d-codes\n", got, n); + } + printf("%llu total codes for 2 to %d symbols", sum, syms); + if (max < syms - 1) + printf(" (%d-bit length limit)\n", max); + else + puts(" (no length limit)"); + + /* allocate and clear done array for beenhere() */ + if (syms == 2) + done = NULL; + else if (size > ((size_t)0 - 1) / sizeof(struct tab) || + (done = calloc(size, sizeof(struct tab))) == NULL) { + fputs("abort: unable to allocate enough memory\n", stderr); + cleanup(); + return 1; + } + + /* find and show maximum inflate table usage */ + if (root > max) /* reduce root to max length */ + root = max; + if ((code_t)syms < ((code_t)1 << (root + 1))) + enough(syms); + else + puts("cannot handle minimum code lengths > root"); + + /* done */ + cleanup(); + return 0; +} diff --git a/zlib-1.2.11/examples/fitblk.c b/zlib-1.2.11/examples/fitblk.c new file mode 100644 index 00000000..c61de5c9 --- /dev/null +++ b/zlib-1.2.11/examples/fitblk.c @@ -0,0 +1,233 @@ +/* fitblk.c: example of fitting compressed output to a specified size + Not copyrighted -- provided to the public domain + Version 1.1 25 November 2004 Mark Adler */ + +/* Version history: + 1.0 24 Nov 2004 First version + 1.1 25 Nov 2004 Change deflateInit2() to deflateInit() + Use fixed-size, stack-allocated raw buffers + Simplify code moving compression to subroutines + Use assert() for internal errors + Add detailed description of approach + */ + +/* Approach to just fitting a requested compressed size: + + fitblk performs three compression passes on a portion of the input + data in order to determine how much of that input will compress to + nearly the requested output block size. The first pass generates + enough deflate blocks to produce output to fill the requested + output size plus a specfied excess amount (see the EXCESS define + below). The last deflate block may go quite a bit past that, but + is discarded. The second pass decompresses and recompresses just + the compressed data that fit in the requested plus excess sized + buffer. The deflate process is terminated after that amount of + input, which is less than the amount consumed on the first pass. + The last deflate block of the result will be of a comparable size + to the final product, so that the header for that deflate block and + the compression ratio for that block will be about the same as in + the final product. The third compression pass decompresses the + result of the second step, but only the compressed data up to the + requested size minus an amount to allow the compressed stream to + complete (see the MARGIN define below). That will result in a + final compressed stream whose length is less than or equal to the + requested size. Assuming sufficient input and a requested size + greater than a few hundred bytes, the shortfall will typically be + less than ten bytes. + + If the input is short enough that the first compression completes + before filling the requested output size, then that compressed + stream is return with no recompression. + + EXCESS is chosen to be just greater than the shortfall seen in a + two pass approach similar to the above. That shortfall is due to + the last deflate block compressing more efficiently with a smaller + header on the second pass. EXCESS is set to be large enough so + that there is enough uncompressed data for the second pass to fill + out the requested size, and small enough so that the final deflate + block of the second pass will be close in size to the final deflate + block of the third and final pass. MARGIN is chosen to be just + large enough to assure that the final compression has enough room + to complete in all cases. + */ + +#include +#include +#include +#include "zlib.h" + +#define local static + +/* print nastygram and leave */ +local void quit(char *why) +{ + fprintf(stderr, "fitblk abort: %s\n", why); + exit(1); +} + +#define RAWLEN 4096 /* intermediate uncompressed buffer size */ + +/* compress from file to def until provided buffer is full or end of + input reached; return last deflate() return value, or Z_ERRNO if + there was read error on the file */ +local int partcompress(FILE *in, z_streamp def) +{ + int ret, flush; + unsigned char raw[RAWLEN]; + + flush = Z_NO_FLUSH; + do { + def->avail_in = fread(raw, 1, RAWLEN, in); + if (ferror(in)) + return Z_ERRNO; + def->next_in = raw; + if (feof(in)) + flush = Z_FINISH; + ret = deflate(def, flush); + assert(ret != Z_STREAM_ERROR); + } while (def->avail_out != 0 && flush == Z_NO_FLUSH); + return ret; +} + +/* recompress from inf's input to def's output; the input for inf and + the output for def are set in those structures before calling; + return last deflate() return value, or Z_MEM_ERROR if inflate() + was not able to allocate enough memory when it needed to */ +local int recompress(z_streamp inf, z_streamp def) +{ + int ret, flush; + unsigned char raw[RAWLEN]; + + flush = Z_NO_FLUSH; + do { + /* decompress */ + inf->avail_out = RAWLEN; + inf->next_out = raw; + ret = inflate(inf, Z_NO_FLUSH); + assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR && + ret != Z_NEED_DICT); + if (ret == Z_MEM_ERROR) + return ret; + + /* compress what was decompresed until done or no room */ + def->avail_in = RAWLEN - inf->avail_out; + def->next_in = raw; + if (inf->avail_out != 0) + flush = Z_FINISH; + ret = deflate(def, flush); + assert(ret != Z_STREAM_ERROR); + } while (ret != Z_STREAM_END && def->avail_out != 0); + return ret; +} + +#define EXCESS 256 /* empirically determined stream overage */ +#define MARGIN 8 /* amount to back off for completion */ + +/* compress from stdin to fixed-size block on stdout */ +int main(int argc, char **argv) +{ + int ret; /* return code */ + unsigned size; /* requested fixed output block size */ + unsigned have; /* bytes written by deflate() call */ + unsigned char *blk; /* intermediate and final stream */ + unsigned char *tmp; /* close to desired size stream */ + z_stream def, inf; /* zlib deflate and inflate states */ + + /* get requested output size */ + if (argc != 2) + quit("need one argument: size of output block"); + ret = strtol(argv[1], argv + 1, 10); + if (argv[1][0] != 0) + quit("argument must be a number"); + if (ret < 8) /* 8 is minimum zlib stream size */ + quit("need positive size of 8 or greater"); + size = (unsigned)ret; + + /* allocate memory for buffers and compression engine */ + blk = malloc(size + EXCESS); + def.zalloc = Z_NULL; + def.zfree = Z_NULL; + def.opaque = Z_NULL; + ret = deflateInit(&def, Z_DEFAULT_COMPRESSION); + if (ret != Z_OK || blk == NULL) + quit("out of memory"); + + /* compress from stdin until output full, or no more input */ + def.avail_out = size + EXCESS; + def.next_out = blk; + ret = partcompress(stdin, &def); + if (ret == Z_ERRNO) + quit("error reading input"); + + /* if it all fit, then size was undersubscribed -- done! */ + if (ret == Z_STREAM_END && def.avail_out >= EXCESS) { + /* write block to stdout */ + have = size + EXCESS - def.avail_out; + if (fwrite(blk, 1, have, stdout) != have || ferror(stdout)) + quit("error writing output"); + + /* clean up and print results to stderr */ + ret = deflateEnd(&def); + assert(ret != Z_STREAM_ERROR); + free(blk); + fprintf(stderr, + "%u bytes unused out of %u requested (all input)\n", + size - have, size); + return 0; + } + + /* it didn't all fit -- set up for recompression */ + inf.zalloc = Z_NULL; + inf.zfree = Z_NULL; + inf.opaque = Z_NULL; + inf.avail_in = 0; + inf.next_in = Z_NULL; + ret = inflateInit(&inf); + tmp = malloc(size + EXCESS); + if (ret != Z_OK || tmp == NULL) + quit("out of memory"); + ret = deflateReset(&def); + assert(ret != Z_STREAM_ERROR); + + /* do first recompression close to the right amount */ + inf.avail_in = size + EXCESS; + inf.next_in = blk; + def.avail_out = size + EXCESS; + def.next_out = tmp; + ret = recompress(&inf, &def); + if (ret == Z_MEM_ERROR) + quit("out of memory"); + + /* set up for next reocmpression */ + ret = inflateReset(&inf); + assert(ret != Z_STREAM_ERROR); + ret = deflateReset(&def); + assert(ret != Z_STREAM_ERROR); + + /* do second and final recompression (third compression) */ + inf.avail_in = size - MARGIN; /* assure stream will complete */ + inf.next_in = tmp; + def.avail_out = size; + def.next_out = blk; + ret = recompress(&inf, &def); + if (ret == Z_MEM_ERROR) + quit("out of memory"); + assert(ret == Z_STREAM_END); /* otherwise MARGIN too small */ + + /* done -- write block to stdout */ + have = size - def.avail_out; + if (fwrite(blk, 1, have, stdout) != have || ferror(stdout)) + quit("error writing output"); + + /* clean up and print results to stderr */ + free(tmp); + ret = inflateEnd(&inf); + assert(ret != Z_STREAM_ERROR); + ret = deflateEnd(&def); + assert(ret != Z_STREAM_ERROR); + free(blk); + fprintf(stderr, + "%u bytes unused out of %u requested (%lu input)\n", + size - have, size, def.total_in); + return 0; +} diff --git a/zlib-1.2.11/examples/gun.c b/zlib-1.2.11/examples/gun.c new file mode 100644 index 00000000..be44fa51 --- /dev/null +++ b/zlib-1.2.11/examples/gun.c @@ -0,0 +1,702 @@ +/* gun.c -- simple gunzip to give an example of the use of inflateBack() + * Copyright (C) 2003, 2005, 2008, 2010, 2012 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + Version 1.7 12 August 2012 Mark Adler */ + +/* Version history: + 1.0 16 Feb 2003 First version for testing of inflateBack() + 1.1 21 Feb 2005 Decompress concatenated gzip streams + Remove use of "this" variable (C++ keyword) + Fix return value for in() + Improve allocation failure checking + Add typecasting for void * structures + Add -h option for command version and usage + Add a bunch of comments + 1.2 20 Mar 2005 Add Unix compress (LZW) decompression + Copy file attributes from input file to output file + 1.3 12 Jun 2005 Add casts for error messages [Oberhumer] + 1.4 8 Dec 2006 LZW decompression speed improvements + 1.5 9 Feb 2008 Avoid warning in latest version of gcc + 1.6 17 Jan 2010 Avoid signed/unsigned comparison warnings + 1.7 12 Aug 2012 Update for z_const usage in zlib 1.2.8 + */ + +/* + gun [ -t ] [ name ... ] + + decompresses the data in the named gzip files. If no arguments are given, + gun will decompress from stdin to stdout. The names must end in .gz, -gz, + .z, -z, _z, or .Z. The uncompressed data will be written to a file name + with the suffix stripped. On success, the original file is deleted. On + failure, the output file is deleted. For most failures, the command will + continue to process the remaining names on the command line. A memory + allocation failure will abort the command. If -t is specified, then the + listed files or stdin will be tested as gzip files for integrity (without + checking for a proper suffix), no output will be written, and no files + will be deleted. + + Like gzip, gun allows concatenated gzip streams and will decompress them, + writing all of the uncompressed data to the output. Unlike gzip, gun allows + an empty file on input, and will produce no error writing an empty output + file. + + gun will also decompress files made by Unix compress, which uses LZW + compression. These files are automatically detected by virtue of their + magic header bytes. Since the end of Unix compress stream is marked by the + end-of-file, they cannot be concantenated. If a Unix compress stream is + encountered in an input file, it is the last stream in that file. + + Like gunzip and uncompress, the file attributes of the original compressed + file are maintained in the final uncompressed file, to the extent that the + user permissions allow it. + + On my Mac OS X PowerPC G4, gun is almost twice as fast as gunzip (version + 1.2.4) is on the same file, when gun is linked with zlib 1.2.2. Also the + LZW decompression provided by gun is about twice as fast as the standard + Unix uncompress command. + */ + +/* external functions and related types and constants */ +#include /* fprintf() */ +#include /* malloc(), free() */ +#include /* strerror(), strcmp(), strlen(), memcpy() */ +#include /* errno */ +#include /* open() */ +#include /* read(), write(), close(), chown(), unlink() */ +#include +#include /* stat(), chmod() */ +#include /* utime() */ +#include "zlib.h" /* inflateBackInit(), inflateBack(), */ + /* inflateBackEnd(), crc32() */ + +/* function declaration */ +#define local static + +/* buffer constants */ +#define SIZE 32768U /* input and output buffer sizes */ +#define PIECE 16384 /* limits i/o chunks for 16-bit int case */ + +/* structure for infback() to pass to input function in() -- it maintains the + input file and a buffer of size SIZE */ +struct ind { + int infile; + unsigned char *inbuf; +}; + +/* Load input buffer, assumed to be empty, and return bytes loaded and a + pointer to them. read() is called until the buffer is full, or until it + returns end-of-file or error. Return 0 on error. */ +local unsigned in(void *in_desc, z_const unsigned char **buf) +{ + int ret; + unsigned len; + unsigned char *next; + struct ind *me = (struct ind *)in_desc; + + next = me->inbuf; + *buf = next; + len = 0; + do { + ret = PIECE; + if ((unsigned)ret > SIZE - len) + ret = (int)(SIZE - len); + ret = (int)read(me->infile, next, ret); + if (ret == -1) { + len = 0; + break; + } + next += ret; + len += ret; + } while (ret != 0 && len < SIZE); + return len; +} + +/* structure for infback() to pass to output function out() -- it maintains the + output file, a running CRC-32 check on the output and the total number of + bytes output, both for checking against the gzip trailer. (The length in + the gzip trailer is stored modulo 2^32, so it's ok if a long is 32 bits and + the output is greater than 4 GB.) */ +struct outd { + int outfile; + int check; /* true if checking crc and total */ + unsigned long crc; + unsigned long total; +}; + +/* Write output buffer and update the CRC-32 and total bytes written. write() + is called until all of the output is written or an error is encountered. + On success out() returns 0. For a write failure, out() returns 1. If the + output file descriptor is -1, then nothing is written. + */ +local int out(void *out_desc, unsigned char *buf, unsigned len) +{ + int ret; + struct outd *me = (struct outd *)out_desc; + + if (me->check) { + me->crc = crc32(me->crc, buf, len); + me->total += len; + } + if (me->outfile != -1) + do { + ret = PIECE; + if ((unsigned)ret > len) + ret = (int)len; + ret = (int)write(me->outfile, buf, ret); + if (ret == -1) + return 1; + buf += ret; + len -= ret; + } while (len != 0); + return 0; +} + +/* next input byte macro for use inside lunpipe() and gunpipe() */ +#define NEXT() (have ? 0 : (have = in(indp, &next)), \ + last = have ? (have--, (int)(*next++)) : -1) + +/* memory for gunpipe() and lunpipe() -- + the first 256 entries of prefix[] and suffix[] are never used, could + have offset the index, but it's faster to waste the memory */ +unsigned char inbuf[SIZE]; /* input buffer */ +unsigned char outbuf[SIZE]; /* output buffer */ +unsigned short prefix[65536]; /* index to LZW prefix string */ +unsigned char suffix[65536]; /* one-character LZW suffix */ +unsigned char match[65280 + 2]; /* buffer for reversed match or gzip + 32K sliding window */ + +/* throw out what's left in the current bits byte buffer (this is a vestigial + aspect of the compressed data format derived from an implementation that + made use of a special VAX machine instruction!) */ +#define FLUSHCODE() \ + do { \ + left = 0; \ + rem = 0; \ + if (chunk > have) { \ + chunk -= have; \ + have = 0; \ + if (NEXT() == -1) \ + break; \ + chunk--; \ + if (chunk > have) { \ + chunk = have = 0; \ + break; \ + } \ + } \ + have -= chunk; \ + next += chunk; \ + chunk = 0; \ + } while (0) + +/* Decompress a compress (LZW) file from indp to outfile. The compress magic + header (two bytes) has already been read and verified. There are have bytes + of buffered input at next. strm is used for passing error information back + to gunpipe(). + + lunpipe() will return Z_OK on success, Z_BUF_ERROR for an unexpected end of + file, read error, or write error (a write error indicated by strm->next_in + not equal to Z_NULL), or Z_DATA_ERROR for invalid input. + */ +local int lunpipe(unsigned have, z_const unsigned char *next, struct ind *indp, + int outfile, z_stream *strm) +{ + int last; /* last byte read by NEXT(), or -1 if EOF */ + unsigned chunk; /* bytes left in current chunk */ + int left; /* bits left in rem */ + unsigned rem; /* unused bits from input */ + int bits; /* current bits per code */ + unsigned code; /* code, table traversal index */ + unsigned mask; /* mask for current bits codes */ + int max; /* maximum bits per code for this stream */ + unsigned flags; /* compress flags, then block compress flag */ + unsigned end; /* last valid entry in prefix/suffix tables */ + unsigned temp; /* current code */ + unsigned prev; /* previous code */ + unsigned final; /* last character written for previous code */ + unsigned stack; /* next position for reversed string */ + unsigned outcnt; /* bytes in output buffer */ + struct outd outd; /* output structure */ + unsigned char *p; + + /* set up output */ + outd.outfile = outfile; + outd.check = 0; + + /* process remainder of compress header -- a flags byte */ + flags = NEXT(); + if (last == -1) + return Z_BUF_ERROR; + if (flags & 0x60) { + strm->msg = (char *)"unknown lzw flags set"; + return Z_DATA_ERROR; + } + max = flags & 0x1f; + if (max < 9 || max > 16) { + strm->msg = (char *)"lzw bits out of range"; + return Z_DATA_ERROR; + } + if (max == 9) /* 9 doesn't really mean 9 */ + max = 10; + flags &= 0x80; /* true if block compress */ + + /* clear table */ + bits = 9; + mask = 0x1ff; + end = flags ? 256 : 255; + + /* set up: get first 9-bit code, which is the first decompressed byte, but + don't create a table entry until the next code */ + if (NEXT() == -1) /* no compressed data is ok */ + return Z_OK; + final = prev = (unsigned)last; /* low 8 bits of code */ + if (NEXT() == -1) /* missing a bit */ + return Z_BUF_ERROR; + if (last & 1) { /* code must be < 256 */ + strm->msg = (char *)"invalid lzw code"; + return Z_DATA_ERROR; + } + rem = (unsigned)last >> 1; /* remaining 7 bits */ + left = 7; + chunk = bits - 2; /* 7 bytes left in this chunk */ + outbuf[0] = (unsigned char)final; /* write first decompressed byte */ + outcnt = 1; + + /* decode codes */ + stack = 0; + for (;;) { + /* if the table will be full after this, increment the code size */ + if (end >= mask && bits < max) { + FLUSHCODE(); + bits++; + mask <<= 1; + mask++; + } + + /* get a code of length bits */ + if (chunk == 0) /* decrement chunk modulo bits */ + chunk = bits; + code = rem; /* low bits of code */ + if (NEXT() == -1) { /* EOF is end of compressed data */ + /* write remaining buffered output */ + if (outcnt && out(&outd, outbuf, outcnt)) { + strm->next_in = outbuf; /* signal write error */ + return Z_BUF_ERROR; + } + return Z_OK; + } + code += (unsigned)last << left; /* middle (or high) bits of code */ + left += 8; + chunk--; + if (bits > left) { /* need more bits */ + if (NEXT() == -1) /* can't end in middle of code */ + return Z_BUF_ERROR; + code += (unsigned)last << left; /* high bits of code */ + left += 8; + chunk--; + } + code &= mask; /* mask to current code length */ + left -= bits; /* number of unused bits */ + rem = (unsigned)last >> (8 - left); /* unused bits from last byte */ + + /* process clear code (256) */ + if (code == 256 && flags) { + FLUSHCODE(); + bits = 9; /* initialize bits and mask */ + mask = 0x1ff; + end = 255; /* empty table */ + continue; /* get next code */ + } + + /* special code to reuse last match */ + temp = code; /* save the current code */ + if (code > end) { + /* Be picky on the allowed code here, and make sure that the code + we drop through (prev) will be a valid index so that random + input does not cause an exception. The code != end + 1 check is + empirically derived, and not checked in the original uncompress + code. If this ever causes a problem, that check could be safely + removed. Leaving this check in greatly improves gun's ability + to detect random or corrupted input after a compress header. + In any case, the prev > end check must be retained. */ + if (code != end + 1 || prev > end) { + strm->msg = (char *)"invalid lzw code"; + return Z_DATA_ERROR; + } + match[stack++] = (unsigned char)final; + code = prev; + } + + /* walk through linked list to generate output in reverse order */ + p = match + stack; + while (code >= 256) { + *p++ = suffix[code]; + code = prefix[code]; + } + stack = p - match; + match[stack++] = (unsigned char)code; + final = code; + + /* link new table entry */ + if (end < mask) { + end++; + prefix[end] = (unsigned short)prev; + suffix[end] = (unsigned char)final; + } + + /* set previous code for next iteration */ + prev = temp; + + /* write output in forward order */ + while (stack > SIZE - outcnt) { + while (outcnt < SIZE) + outbuf[outcnt++] = match[--stack]; + if (out(&outd, outbuf, outcnt)) { + strm->next_in = outbuf; /* signal write error */ + return Z_BUF_ERROR; + } + outcnt = 0; + } + p = match + stack; + do { + outbuf[outcnt++] = *--p; + } while (p > match); + stack = 0; + + /* loop for next code with final and prev as the last match, rem and + left provide the first 0..7 bits of the next code, end is the last + valid table entry */ + } +} + +/* Decompress a gzip file from infile to outfile. strm is assumed to have been + successfully initialized with inflateBackInit(). The input file may consist + of a series of gzip streams, in which case all of them will be decompressed + to the output file. If outfile is -1, then the gzip stream(s) integrity is + checked and nothing is written. + + The return value is a zlib error code: Z_MEM_ERROR if out of memory, + Z_DATA_ERROR if the header or the compressed data is invalid, or if the + trailer CRC-32 check or length doesn't match, Z_BUF_ERROR if the input ends + prematurely or a write error occurs, or Z_ERRNO if junk (not a another gzip + stream) follows a valid gzip stream. + */ +local int gunpipe(z_stream *strm, int infile, int outfile) +{ + int ret, first, last; + unsigned have, flags, len; + z_const unsigned char *next = NULL; + struct ind ind, *indp; + struct outd outd; + + /* setup input buffer */ + ind.infile = infile; + ind.inbuf = inbuf; + indp = &ind; + + /* decompress concatenated gzip streams */ + have = 0; /* no input data read in yet */ + first = 1; /* looking for first gzip header */ + strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */ + for (;;) { + /* look for the two magic header bytes for a gzip stream */ + if (NEXT() == -1) { + ret = Z_OK; + break; /* empty gzip stream is ok */ + } + if (last != 31 || (NEXT() != 139 && last != 157)) { + strm->msg = (char *)"incorrect header check"; + ret = first ? Z_DATA_ERROR : Z_ERRNO; + break; /* not a gzip or compress header */ + } + first = 0; /* next non-header is junk */ + + /* process a compress (LZW) file -- can't be concatenated after this */ + if (last == 157) { + ret = lunpipe(have, next, indp, outfile, strm); + break; + } + + /* process remainder of gzip header */ + ret = Z_BUF_ERROR; + if (NEXT() != 8) { /* only deflate method allowed */ + if (last == -1) break; + strm->msg = (char *)"unknown compression method"; + ret = Z_DATA_ERROR; + break; + } + flags = NEXT(); /* header flags */ + NEXT(); /* discard mod time, xflgs, os */ + NEXT(); + NEXT(); + NEXT(); + NEXT(); + NEXT(); + if (last == -1) break; + if (flags & 0xe0) { + strm->msg = (char *)"unknown header flags set"; + ret = Z_DATA_ERROR; + break; + } + if (flags & 4) { /* extra field */ + len = NEXT(); + len += (unsigned)(NEXT()) << 8; + if (last == -1) break; + while (len > have) { + len -= have; + have = 0; + if (NEXT() == -1) break; + len--; + } + if (last == -1) break; + have -= len; + next += len; + } + if (flags & 8) /* file name */ + while (NEXT() != 0 && last != -1) + ; + if (flags & 16) /* comment */ + while (NEXT() != 0 && last != -1) + ; + if (flags & 2) { /* header crc */ + NEXT(); + NEXT(); + } + if (last == -1) break; + + /* set up output */ + outd.outfile = outfile; + outd.check = 1; + outd.crc = crc32(0L, Z_NULL, 0); + outd.total = 0; + + /* decompress data to output */ + strm->next_in = next; + strm->avail_in = have; + ret = inflateBack(strm, in, indp, out, &outd); + if (ret != Z_STREAM_END) break; + next = strm->next_in; + have = strm->avail_in; + strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */ + + /* check trailer */ + ret = Z_BUF_ERROR; + if (NEXT() != (int)(outd.crc & 0xff) || + NEXT() != (int)((outd.crc >> 8) & 0xff) || + NEXT() != (int)((outd.crc >> 16) & 0xff) || + NEXT() != (int)((outd.crc >> 24) & 0xff)) { + /* crc error */ + if (last != -1) { + strm->msg = (char *)"incorrect data check"; + ret = Z_DATA_ERROR; + } + break; + } + if (NEXT() != (int)(outd.total & 0xff) || + NEXT() != (int)((outd.total >> 8) & 0xff) || + NEXT() != (int)((outd.total >> 16) & 0xff) || + NEXT() != (int)((outd.total >> 24) & 0xff)) { + /* length error */ + if (last != -1) { + strm->msg = (char *)"incorrect length check"; + ret = Z_DATA_ERROR; + } + break; + } + + /* go back and look for another gzip stream */ + } + + /* clean up and return */ + return ret; +} + +/* Copy file attributes, from -> to, as best we can. This is best effort, so + no errors are reported. The mode bits, including suid, sgid, and the sticky + bit are copied (if allowed), the owner's user id and group id are copied + (again if allowed), and the access and modify times are copied. */ +local void copymeta(char *from, char *to) +{ + struct stat was; + struct utimbuf when; + + /* get all of from's Unix meta data, return if not a regular file */ + if (stat(from, &was) != 0 || (was.st_mode & S_IFMT) != S_IFREG) + return; + + /* set to's mode bits, ignore errors */ + (void)chmod(to, was.st_mode & 07777); + + /* copy owner's user and group, ignore errors */ + (void)chown(to, was.st_uid, was.st_gid); + + /* copy access and modify times, ignore errors */ + when.actime = was.st_atime; + when.modtime = was.st_mtime; + (void)utime(to, &when); +} + +/* Decompress the file inname to the file outnname, of if test is true, just + decompress without writing and check the gzip trailer for integrity. If + inname is NULL or an empty string, read from stdin. If outname is NULL or + an empty string, write to stdout. strm is a pre-initialized inflateBack + structure. When appropriate, copy the file attributes from inname to + outname. + + gunzip() returns 1 if there is an out-of-memory error or an unexpected + return code from gunpipe(). Otherwise it returns 0. + */ +local int gunzip(z_stream *strm, char *inname, char *outname, int test) +{ + int ret; + int infile, outfile; + + /* open files */ + if (inname == NULL || *inname == 0) { + inname = "-"; + infile = 0; /* stdin */ + } + else { + infile = open(inname, O_RDONLY, 0); + if (infile == -1) { + fprintf(stderr, "gun cannot open %s\n", inname); + return 0; + } + } + if (test) + outfile = -1; + else if (outname == NULL || *outname == 0) { + outname = "-"; + outfile = 1; /* stdout */ + } + else { + outfile = open(outname, O_CREAT | O_TRUNC | O_WRONLY, 0666); + if (outfile == -1) { + close(infile); + fprintf(stderr, "gun cannot create %s\n", outname); + return 0; + } + } + errno = 0; + + /* decompress */ + ret = gunpipe(strm, infile, outfile); + if (outfile > 2) close(outfile); + if (infile > 2) close(infile); + + /* interpret result */ + switch (ret) { + case Z_OK: + case Z_ERRNO: + if (infile > 2 && outfile > 2) { + copymeta(inname, outname); /* copy attributes */ + unlink(inname); + } + if (ret == Z_ERRNO) + fprintf(stderr, "gun warning: trailing garbage ignored in %s\n", + inname); + break; + case Z_DATA_ERROR: + if (outfile > 2) unlink(outname); + fprintf(stderr, "gun data error on %s: %s\n", inname, strm->msg); + break; + case Z_MEM_ERROR: + if (outfile > 2) unlink(outname); + fprintf(stderr, "gun out of memory error--aborting\n"); + return 1; + case Z_BUF_ERROR: + if (outfile > 2) unlink(outname); + if (strm->next_in != Z_NULL) { + fprintf(stderr, "gun write error on %s: %s\n", + outname, strerror(errno)); + } + else if (errno) { + fprintf(stderr, "gun read error on %s: %s\n", + inname, strerror(errno)); + } + else { + fprintf(stderr, "gun unexpected end of file on %s\n", + inname); + } + break; + default: + if (outfile > 2) unlink(outname); + fprintf(stderr, "gun internal error--aborting\n"); + return 1; + } + return 0; +} + +/* Process the gun command line arguments. See the command syntax near the + beginning of this source file. */ +int main(int argc, char **argv) +{ + int ret, len, test; + char *outname; + unsigned char *window; + z_stream strm; + + /* initialize inflateBack state for repeated use */ + window = match; /* reuse LZW match buffer */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + ret = inflateBackInit(&strm, 15, window); + if (ret != Z_OK) { + fprintf(stderr, "gun out of memory error--aborting\n"); + return 1; + } + + /* decompress each file to the same name with the suffix removed */ + argc--; + argv++; + test = 0; + if (argc && strcmp(*argv, "-h") == 0) { + fprintf(stderr, "gun 1.6 (17 Jan 2010)\n"); + fprintf(stderr, "Copyright (C) 2003-2010 Mark Adler\n"); + fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n"); + return 0; + } + if (argc && strcmp(*argv, "-t") == 0) { + test = 1; + argc--; + argv++; + } + if (argc) + do { + if (test) + outname = NULL; + else { + len = (int)strlen(*argv); + if (strcmp(*argv + len - 3, ".gz") == 0 || + strcmp(*argv + len - 3, "-gz") == 0) + len -= 3; + else if (strcmp(*argv + len - 2, ".z") == 0 || + strcmp(*argv + len - 2, "-z") == 0 || + strcmp(*argv + len - 2, "_z") == 0 || + strcmp(*argv + len - 2, ".Z") == 0) + len -= 2; + else { + fprintf(stderr, "gun error: no gz type on %s--skipping\n", + *argv); + continue; + } + outname = malloc(len + 1); + if (outname == NULL) { + fprintf(stderr, "gun out of memory error--aborting\n"); + ret = 1; + break; + } + memcpy(outname, *argv, len); + outname[len] = 0; + } + ret = gunzip(&strm, *argv, outname, test); + if (outname != NULL) free(outname); + if (ret) break; + } while (argv++, --argc); + else + ret = gunzip(&strm, NULL, NULL, test); + + /* clean up */ + inflateBackEnd(&strm); + return ret; +} diff --git a/zlib-1.2.11/examples/gzappend.c b/zlib-1.2.11/examples/gzappend.c new file mode 100644 index 00000000..662dec37 --- /dev/null +++ b/zlib-1.2.11/examples/gzappend.c @@ -0,0 +1,504 @@ +/* gzappend -- command to append to a gzip file + + Copyright (C) 2003, 2012 Mark Adler, all rights reserved + version 1.2, 11 Oct 2012 + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Mark Adler madler@alumni.caltech.edu + */ + +/* + * Change history: + * + * 1.0 19 Oct 2003 - First version + * 1.1 4 Nov 2003 - Expand and clarify some comments and notes + * - Add version and copyright to help + * - Send help to stdout instead of stderr + * - Add some preemptive typecasts + * - Add L to constants in lseek() calls + * - Remove some debugging information in error messages + * - Use new data_type definition for zlib 1.2.1 + * - Simplfy and unify file operations + * - Finish off gzip file in gztack() + * - Use deflatePrime() instead of adding empty blocks + * - Keep gzip file clean on appended file read errors + * - Use in-place rotate instead of auxiliary buffer + * (Why you ask? Because it was fun to write!) + * 1.2 11 Oct 2012 - Fix for proper z_const usage + * - Check for input buffer malloc failure + */ + +/* + gzappend takes a gzip file and appends to it, compressing files from the + command line or data from stdin. The gzip file is written to directly, to + avoid copying that file, in case it's large. Note that this results in the + unfriendly behavior that if gzappend fails, the gzip file is corrupted. + + This program was written to illustrate the use of the new Z_BLOCK option of + zlib 1.2.x's inflate() function. This option returns from inflate() at each + block boundary to facilitate locating and modifying the last block bit at + the start of the final deflate block. Also whether using Z_BLOCK or not, + another required feature of zlib 1.2.x is that inflate() now provides the + number of unusued bits in the last input byte used. gzappend will not work + with versions of zlib earlier than 1.2.1. + + gzappend first decompresses the gzip file internally, discarding all but + the last 32K of uncompressed data, and noting the location of the last block + bit and the number of unused bits in the last byte of the compressed data. + The gzip trailer containing the CRC-32 and length of the uncompressed data + is verified. This trailer will be later overwritten. + + Then the last block bit is cleared by seeking back in the file and rewriting + the byte that contains it. Seeking forward, the last byte of the compressed + data is saved along with the number of unused bits to initialize deflate. + + A deflate process is initialized, using the last 32K of the uncompressed + data from the gzip file to initialize the dictionary. If the total + uncompressed data was less than 32K, then all of it is used to initialize + the dictionary. The deflate output bit buffer is also initialized with the + last bits from the original deflate stream. From here on, the data to + append is simply compressed using deflate, and written to the gzip file. + When that is complete, the new CRC-32 and uncompressed length are written + as the trailer of the gzip file. + */ + +#include +#include +#include +#include +#include +#include "zlib.h" + +#define local static +#define LGCHUNK 14 +#define CHUNK (1U << LGCHUNK) +#define DSIZE 32768U + +/* print an error message and terminate with extreme prejudice */ +local void bye(char *msg1, char *msg2) +{ + fprintf(stderr, "gzappend error: %s%s\n", msg1, msg2); + exit(1); +} + +/* return the greatest common divisor of a and b using Euclid's algorithm, + modified to be fast when one argument much greater than the other, and + coded to avoid unnecessary swapping */ +local unsigned gcd(unsigned a, unsigned b) +{ + unsigned c; + + while (a && b) + if (a > b) { + c = b; + while (a - c >= c) + c <<= 1; + a -= c; + } + else { + c = a; + while (b - c >= c) + c <<= 1; + b -= c; + } + return a + b; +} + +/* rotate list[0..len-1] left by rot positions, in place */ +local void rotate(unsigned char *list, unsigned len, unsigned rot) +{ + unsigned char tmp; + unsigned cycles; + unsigned char *start, *last, *to, *from; + + /* normalize rot and handle degenerate cases */ + if (len < 2) return; + if (rot >= len) rot %= len; + if (rot == 0) return; + + /* pointer to last entry in list */ + last = list + (len - 1); + + /* do simple left shift by one */ + if (rot == 1) { + tmp = *list; + memcpy(list, list + 1, len - 1); + *last = tmp; + return; + } + + /* do simple right shift by one */ + if (rot == len - 1) { + tmp = *last; + memmove(list + 1, list, len - 1); + *list = tmp; + return; + } + + /* otherwise do rotate as a set of cycles in place */ + cycles = gcd(len, rot); /* number of cycles */ + do { + start = from = list + cycles; /* start index is arbitrary */ + tmp = *from; /* save entry to be overwritten */ + for (;;) { + to = from; /* next step in cycle */ + from += rot; /* go right rot positions */ + if (from > last) from -= len; /* (pointer better not wrap) */ + if (from == start) break; /* all but one shifted */ + *to = *from; /* shift left */ + } + *to = tmp; /* complete the circle */ + } while (--cycles); +} + +/* structure for gzip file read operations */ +typedef struct { + int fd; /* file descriptor */ + int size; /* 1 << size is bytes in buf */ + unsigned left; /* bytes available at next */ + unsigned char *buf; /* buffer */ + z_const unsigned char *next; /* next byte in buffer */ + char *name; /* file name for error messages */ +} file; + +/* reload buffer */ +local int readin(file *in) +{ + int len; + + len = read(in->fd, in->buf, 1 << in->size); + if (len == -1) bye("error reading ", in->name); + in->left = (unsigned)len; + in->next = in->buf; + return len; +} + +/* read from file in, exit if end-of-file */ +local int readmore(file *in) +{ + if (readin(in) == 0) bye("unexpected end of ", in->name); + return 0; +} + +#define read1(in) (in->left == 0 ? readmore(in) : 0, \ + in->left--, *(in->next)++) + +/* skip over n bytes of in */ +local void skip(file *in, unsigned n) +{ + unsigned bypass; + + if (n > in->left) { + n -= in->left; + bypass = n & ~((1U << in->size) - 1); + if (bypass) { + if (lseek(in->fd, (off_t)bypass, SEEK_CUR) == -1) + bye("seeking ", in->name); + n -= bypass; + } + readmore(in); + if (n > in->left) + bye("unexpected end of ", in->name); + } + in->left -= n; + in->next += n; +} + +/* read a four-byte unsigned integer, little-endian, from in */ +unsigned long read4(file *in) +{ + unsigned long val; + + val = read1(in); + val += (unsigned)read1(in) << 8; + val += (unsigned long)read1(in) << 16; + val += (unsigned long)read1(in) << 24; + return val; +} + +/* skip over gzip header */ +local void gzheader(file *in) +{ + int flags; + unsigned n; + + if (read1(in) != 31 || read1(in) != 139) bye(in->name, " not a gzip file"); + if (read1(in) != 8) bye("unknown compression method in", in->name); + flags = read1(in); + if (flags & 0xe0) bye("unknown header flags set in", in->name); + skip(in, 6); + if (flags & 4) { + n = read1(in); + n += (unsigned)(read1(in)) << 8; + skip(in, n); + } + if (flags & 8) while (read1(in) != 0) ; + if (flags & 16) while (read1(in) != 0) ; + if (flags & 2) skip(in, 2); +} + +/* decompress gzip file "name", return strm with a deflate stream ready to + continue compression of the data in the gzip file, and return a file + descriptor pointing to where to write the compressed data -- the deflate + stream is initialized to compress using level "level" */ +local int gzscan(char *name, z_stream *strm, int level) +{ + int ret, lastbit, left, full; + unsigned have; + unsigned long crc, tot; + unsigned char *window; + off_t lastoff, end; + file gz; + + /* open gzip file */ + gz.name = name; + gz.fd = open(name, O_RDWR, 0); + if (gz.fd == -1) bye("cannot open ", name); + gz.buf = malloc(CHUNK); + if (gz.buf == NULL) bye("out of memory", ""); + gz.size = LGCHUNK; + gz.left = 0; + + /* skip gzip header */ + gzheader(&gz); + + /* prepare to decompress */ + window = malloc(DSIZE); + if (window == NULL) bye("out of memory", ""); + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; + strm->opaque = Z_NULL; + ret = inflateInit2(strm, -15); + if (ret != Z_OK) bye("out of memory", " or library mismatch"); + + /* decompress the deflate stream, saving append information */ + lastbit = 0; + lastoff = lseek(gz.fd, 0L, SEEK_CUR) - gz.left; + left = 0; + strm->avail_in = gz.left; + strm->next_in = gz.next; + crc = crc32(0L, Z_NULL, 0); + have = full = 0; + do { + /* if needed, get more input */ + if (strm->avail_in == 0) { + readmore(&gz); + strm->avail_in = gz.left; + strm->next_in = gz.next; + } + + /* set up output to next available section of sliding window */ + strm->avail_out = DSIZE - have; + strm->next_out = window + have; + + /* inflate and check for errors */ + ret = inflate(strm, Z_BLOCK); + if (ret == Z_STREAM_ERROR) bye("internal stream error!", ""); + if (ret == Z_MEM_ERROR) bye("out of memory", ""); + if (ret == Z_DATA_ERROR) + bye("invalid compressed data--format violated in", name); + + /* update crc and sliding window pointer */ + crc = crc32(crc, window + have, DSIZE - have - strm->avail_out); + if (strm->avail_out) + have = DSIZE - strm->avail_out; + else { + have = 0; + full = 1; + } + + /* process end of block */ + if (strm->data_type & 128) { + if (strm->data_type & 64) + left = strm->data_type & 0x1f; + else { + lastbit = strm->data_type & 0x1f; + lastoff = lseek(gz.fd, 0L, SEEK_CUR) - strm->avail_in; + } + } + } while (ret != Z_STREAM_END); + inflateEnd(strm); + gz.left = strm->avail_in; + gz.next = strm->next_in; + + /* save the location of the end of the compressed data */ + end = lseek(gz.fd, 0L, SEEK_CUR) - gz.left; + + /* check gzip trailer and save total for deflate */ + if (crc != read4(&gz)) + bye("invalid compressed data--crc mismatch in ", name); + tot = strm->total_out; + if ((tot & 0xffffffffUL) != read4(&gz)) + bye("invalid compressed data--length mismatch in", name); + + /* if not at end of file, warn */ + if (gz.left || readin(&gz)) + fprintf(stderr, + "gzappend warning: junk at end of gzip file overwritten\n"); + + /* clear last block bit */ + lseek(gz.fd, lastoff - (lastbit != 0), SEEK_SET); + if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name); + *gz.buf = (unsigned char)(*gz.buf ^ (1 << ((8 - lastbit) & 7))); + lseek(gz.fd, -1L, SEEK_CUR); + if (write(gz.fd, gz.buf, 1) != 1) bye("writing after seek to ", name); + + /* if window wrapped, build dictionary from window by rotating */ + if (full) { + rotate(window, DSIZE, have); + have = DSIZE; + } + + /* set up deflate stream with window, crc, total_in, and leftover bits */ + ret = deflateInit2(strm, level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); + if (ret != Z_OK) bye("out of memory", ""); + deflateSetDictionary(strm, window, have); + strm->adler = crc; + strm->total_in = tot; + if (left) { + lseek(gz.fd, --end, SEEK_SET); + if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name); + deflatePrime(strm, 8 - left, *gz.buf); + } + lseek(gz.fd, end, SEEK_SET); + + /* clean up and return */ + free(window); + free(gz.buf); + return gz.fd; +} + +/* append file "name" to gzip file gd using deflate stream strm -- if last + is true, then finish off the deflate stream at the end */ +local void gztack(char *name, int gd, z_stream *strm, int last) +{ + int fd, len, ret; + unsigned left; + unsigned char *in, *out; + + /* open file to compress and append */ + fd = 0; + if (name != NULL) { + fd = open(name, O_RDONLY, 0); + if (fd == -1) + fprintf(stderr, "gzappend warning: %s not found, skipping ...\n", + name); + } + + /* allocate buffers */ + in = malloc(CHUNK); + out = malloc(CHUNK); + if (in == NULL || out == NULL) bye("out of memory", ""); + + /* compress input file and append to gzip file */ + do { + /* get more input */ + len = read(fd, in, CHUNK); + if (len == -1) { + fprintf(stderr, + "gzappend warning: error reading %s, skipping rest ...\n", + name); + len = 0; + } + strm->avail_in = (unsigned)len; + strm->next_in = in; + if (len) strm->adler = crc32(strm->adler, in, (unsigned)len); + + /* compress and write all available output */ + do { + strm->avail_out = CHUNK; + strm->next_out = out; + ret = deflate(strm, last && len == 0 ? Z_FINISH : Z_NO_FLUSH); + left = CHUNK - strm->avail_out; + while (left) { + len = write(gd, out + CHUNK - strm->avail_out - left, left); + if (len == -1) bye("writing gzip file", ""); + left -= (unsigned)len; + } + } while (strm->avail_out == 0 && ret != Z_STREAM_END); + } while (len != 0); + + /* write trailer after last entry */ + if (last) { + deflateEnd(strm); + out[0] = (unsigned char)(strm->adler); + out[1] = (unsigned char)(strm->adler >> 8); + out[2] = (unsigned char)(strm->adler >> 16); + out[3] = (unsigned char)(strm->adler >> 24); + out[4] = (unsigned char)(strm->total_in); + out[5] = (unsigned char)(strm->total_in >> 8); + out[6] = (unsigned char)(strm->total_in >> 16); + out[7] = (unsigned char)(strm->total_in >> 24); + len = 8; + do { + ret = write(gd, out + 8 - len, len); + if (ret == -1) bye("writing gzip file", ""); + len -= ret; + } while (len); + close(gd); + } + + /* clean up and return */ + free(out); + free(in); + if (fd > 0) close(fd); +} + +/* process the compression level option if present, scan the gzip file, and + append the specified files, or append the data from stdin if no other file + names are provided on the command line -- the gzip file must be writable + and seekable */ +int main(int argc, char **argv) +{ + int gd, level; + z_stream strm; + + /* ignore command name */ + argc--; argv++; + + /* provide usage if no arguments */ + if (*argv == NULL) { + printf( + "gzappend 1.2 (11 Oct 2012) Copyright (C) 2003, 2012 Mark Adler\n" + ); + printf( + "usage: gzappend [-level] file.gz [ addthis [ andthis ... ]]\n"); + return 0; + } + + /* set compression level */ + level = Z_DEFAULT_COMPRESSION; + if (argv[0][0] == '-') { + if (argv[0][1] < '0' || argv[0][1] > '9' || argv[0][2] != 0) + bye("invalid compression level", ""); + level = argv[0][1] - '0'; + if (*++argv == NULL) bye("no gzip file name after options", ""); + } + + /* prepare to append to gzip file */ + gd = gzscan(*argv++, &strm, level); + + /* append files on command line, or from stdin if none */ + if (*argv == NULL) + gztack(NULL, gd, &strm, 1); + else + do { + gztack(*argv, gd, &strm, argv[1] == NULL); + } while (*++argv != NULL); + return 0; +} diff --git a/zlib-1.2.11/examples/gzjoin.c b/zlib-1.2.11/examples/gzjoin.c new file mode 100644 index 00000000..89e80984 --- /dev/null +++ b/zlib-1.2.11/examples/gzjoin.c @@ -0,0 +1,449 @@ +/* gzjoin -- command to join gzip files into one gzip file + + Copyright (C) 2004, 2005, 2012 Mark Adler, all rights reserved + version 1.2, 14 Aug 2012 + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Mark Adler madler@alumni.caltech.edu + */ + +/* + * Change history: + * + * 1.0 11 Dec 2004 - First version + * 1.1 12 Jun 2005 - Changed ssize_t to long for portability + * 1.2 14 Aug 2012 - Clean up for z_const usage + */ + +/* + gzjoin takes one or more gzip files on the command line and writes out a + single gzip file that will uncompress to the concatenation of the + uncompressed data from the individual gzip files. gzjoin does this without + having to recompress any of the data and without having to calculate a new + crc32 for the concatenated uncompressed data. gzjoin does however have to + decompress all of the input data in order to find the bits in the compressed + data that need to be modified to concatenate the streams. + + gzjoin does not do an integrity check on the input gzip files other than + checking the gzip header and decompressing the compressed data. They are + otherwise assumed to be complete and correct. + + Each joint between gzip files removes at least 18 bytes of previous trailer + and subsequent header, and inserts an average of about three bytes to the + compressed data in order to connect the streams. The output gzip file + has a minimal ten-byte gzip header with no file name or modification time. + + This program was written to illustrate the use of the Z_BLOCK option of + inflate() and the crc32_combine() function. gzjoin will not compile with + versions of zlib earlier than 1.2.3. + */ + +#include /* fputs(), fprintf(), fwrite(), putc() */ +#include /* exit(), malloc(), free() */ +#include /* open() */ +#include /* close(), read(), lseek() */ +#include "zlib.h" + /* crc32(), crc32_combine(), inflateInit2(), inflate(), inflateEnd() */ + +#define local static + +/* exit with an error (return a value to allow use in an expression) */ +local int bail(char *why1, char *why2) +{ + fprintf(stderr, "gzjoin error: %s%s, output incomplete\n", why1, why2); + exit(1); + return 0; +} + +/* -- simple buffered file input with access to the buffer -- */ + +#define CHUNK 32768 /* must be a power of two and fit in unsigned */ + +/* bin buffered input file type */ +typedef struct { + char *name; /* name of file for error messages */ + int fd; /* file descriptor */ + unsigned left; /* bytes remaining at next */ + unsigned char *next; /* next byte to read */ + unsigned char *buf; /* allocated buffer of length CHUNK */ +} bin; + +/* close a buffered file and free allocated memory */ +local void bclose(bin *in) +{ + if (in != NULL) { + if (in->fd != -1) + close(in->fd); + if (in->buf != NULL) + free(in->buf); + free(in); + } +} + +/* open a buffered file for input, return a pointer to type bin, or NULL on + failure */ +local bin *bopen(char *name) +{ + bin *in; + + in = malloc(sizeof(bin)); + if (in == NULL) + return NULL; + in->buf = malloc(CHUNK); + in->fd = open(name, O_RDONLY, 0); + if (in->buf == NULL || in->fd == -1) { + bclose(in); + return NULL; + } + in->left = 0; + in->next = in->buf; + in->name = name; + return in; +} + +/* load buffer from file, return -1 on read error, 0 or 1 on success, with + 1 indicating that end-of-file was reached */ +local int bload(bin *in) +{ + long len; + + if (in == NULL) + return -1; + if (in->left != 0) + return 0; + in->next = in->buf; + do { + len = (long)read(in->fd, in->buf + in->left, CHUNK - in->left); + if (len < 0) + return -1; + in->left += (unsigned)len; + } while (len != 0 && in->left < CHUNK); + return len == 0 ? 1 : 0; +} + +/* get a byte from the file, bail if end of file */ +#define bget(in) (in->left ? 0 : bload(in), \ + in->left ? (in->left--, *(in->next)++) : \ + bail("unexpected end of file on ", in->name)) + +/* get a four-byte little-endian unsigned integer from file */ +local unsigned long bget4(bin *in) +{ + unsigned long val; + + val = bget(in); + val += (unsigned long)(bget(in)) << 8; + val += (unsigned long)(bget(in)) << 16; + val += (unsigned long)(bget(in)) << 24; + return val; +} + +/* skip bytes in file */ +local void bskip(bin *in, unsigned skip) +{ + /* check pointer */ + if (in == NULL) + return; + + /* easy case -- skip bytes in buffer */ + if (skip <= in->left) { + in->left -= skip; + in->next += skip; + return; + } + + /* skip what's in buffer, discard buffer contents */ + skip -= in->left; + in->left = 0; + + /* seek past multiples of CHUNK bytes */ + if (skip > CHUNK) { + unsigned left; + + left = skip & (CHUNK - 1); + if (left == 0) { + /* exact number of chunks: seek all the way minus one byte to check + for end-of-file with a read */ + lseek(in->fd, skip - 1, SEEK_CUR); + if (read(in->fd, in->buf, 1) != 1) + bail("unexpected end of file on ", in->name); + return; + } + + /* skip the integral chunks, update skip with remainder */ + lseek(in->fd, skip - left, SEEK_CUR); + skip = left; + } + + /* read more input and skip remainder */ + bload(in); + if (skip > in->left) + bail("unexpected end of file on ", in->name); + in->left -= skip; + in->next += skip; +} + +/* -- end of buffered input functions -- */ + +/* skip the gzip header from file in */ +local void gzhead(bin *in) +{ + int flags; + + /* verify gzip magic header and compression method */ + if (bget(in) != 0x1f || bget(in) != 0x8b || bget(in) != 8) + bail(in->name, " is not a valid gzip file"); + + /* get and verify flags */ + flags = bget(in); + if ((flags & 0xe0) != 0) + bail("unknown reserved bits set in ", in->name); + + /* skip modification time, extra flags, and os */ + bskip(in, 6); + + /* skip extra field if present */ + if (flags & 4) { + unsigned len; + + len = bget(in); + len += (unsigned)(bget(in)) << 8; + bskip(in, len); + } + + /* skip file name if present */ + if (flags & 8) + while (bget(in) != 0) + ; + + /* skip comment if present */ + if (flags & 16) + while (bget(in) != 0) + ; + + /* skip header crc if present */ + if (flags & 2) + bskip(in, 2); +} + +/* write a four-byte little-endian unsigned integer to out */ +local void put4(unsigned long val, FILE *out) +{ + putc(val & 0xff, out); + putc((val >> 8) & 0xff, out); + putc((val >> 16) & 0xff, out); + putc((val >> 24) & 0xff, out); +} + +/* Load up zlib stream from buffered input, bail if end of file */ +local void zpull(z_streamp strm, bin *in) +{ + if (in->left == 0) + bload(in); + if (in->left == 0) + bail("unexpected end of file on ", in->name); + strm->avail_in = in->left; + strm->next_in = in->next; +} + +/* Write header for gzip file to out and initialize trailer. */ +local void gzinit(unsigned long *crc, unsigned long *tot, FILE *out) +{ + fwrite("\x1f\x8b\x08\0\0\0\0\0\0\xff", 1, 10, out); + *crc = crc32(0L, Z_NULL, 0); + *tot = 0; +} + +/* Copy the compressed data from name, zeroing the last block bit of the last + block if clr is true, and adding empty blocks as needed to get to a byte + boundary. If clr is false, then the last block becomes the last block of + the output, and the gzip trailer is written. crc and tot maintains the + crc and length (modulo 2^32) of the output for the trailer. The resulting + gzip file is written to out. gzinit() must be called before the first call + of gzcopy() to write the gzip header and to initialize crc and tot. */ +local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot, + FILE *out) +{ + int ret; /* return value from zlib functions */ + int pos; /* where the "last block" bit is in byte */ + int last; /* true if processing the last block */ + bin *in; /* buffered input file */ + unsigned char *start; /* start of compressed data in buffer */ + unsigned char *junk; /* buffer for uncompressed data -- discarded */ + z_off_t len; /* length of uncompressed data (support > 4 GB) */ + z_stream strm; /* zlib inflate stream */ + + /* open gzip file and skip header */ + in = bopen(name); + if (in == NULL) + bail("could not open ", name); + gzhead(in); + + /* allocate buffer for uncompressed data and initialize raw inflate + stream */ + junk = malloc(CHUNK); + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, -15); + if (junk == NULL || ret != Z_OK) + bail("out of memory", ""); + + /* inflate and copy compressed data, clear last-block bit if requested */ + len = 0; + zpull(&strm, in); + start = in->next; + last = start[0] & 1; + if (last && clr) + start[0] &= ~1; + strm.avail_out = 0; + for (;;) { + /* if input used and output done, write used input and get more */ + if (strm.avail_in == 0 && strm.avail_out != 0) { + fwrite(start, 1, strm.next_in - start, out); + start = in->buf; + in->left = 0; + zpull(&strm, in); + } + + /* decompress -- return early when end-of-block reached */ + strm.avail_out = CHUNK; + strm.next_out = junk; + ret = inflate(&strm, Z_BLOCK); + switch (ret) { + case Z_MEM_ERROR: + bail("out of memory", ""); + case Z_DATA_ERROR: + bail("invalid compressed data in ", in->name); + } + + /* update length of uncompressed data */ + len += CHUNK - strm.avail_out; + + /* check for block boundary (only get this when block copied out) */ + if (strm.data_type & 128) { + /* if that was the last block, then done */ + if (last) + break; + + /* number of unused bits in last byte */ + pos = strm.data_type & 7; + + /* find the next last-block bit */ + if (pos != 0) { + /* next last-block bit is in last used byte */ + pos = 0x100 >> pos; + last = strm.next_in[-1] & pos; + if (last && clr) + in->buf[strm.next_in - in->buf - 1] &= ~pos; + } + else { + /* next last-block bit is in next unused byte */ + if (strm.avail_in == 0) { + /* don't have that byte yet -- get it */ + fwrite(start, 1, strm.next_in - start, out); + start = in->buf; + in->left = 0; + zpull(&strm, in); + } + last = strm.next_in[0] & 1; + if (last && clr) + in->buf[strm.next_in - in->buf] &= ~1; + } + } + } + + /* update buffer with unused input */ + in->left = strm.avail_in; + in->next = in->buf + (strm.next_in - in->buf); + + /* copy used input, write empty blocks to get to byte boundary */ + pos = strm.data_type & 7; + fwrite(start, 1, in->next - start - 1, out); + last = in->next[-1]; + if (pos == 0 || !clr) + /* already at byte boundary, or last file: write last byte */ + putc(last, out); + else { + /* append empty blocks to last byte */ + last &= ((0x100 >> pos) - 1); /* assure unused bits are zero */ + if (pos & 1) { + /* odd -- append an empty stored block */ + putc(last, out); + if (pos == 1) + putc(0, out); /* two more bits in block header */ + fwrite("\0\0\xff\xff", 1, 4, out); + } + else { + /* even -- append 1, 2, or 3 empty fixed blocks */ + switch (pos) { + case 6: + putc(last | 8, out); + last = 0; + case 4: + putc(last | 0x20, out); + last = 0; + case 2: + putc(last | 0x80, out); + putc(0, out); + } + } + } + + /* update crc and tot */ + *crc = crc32_combine(*crc, bget4(in), len); + *tot += (unsigned long)len; + + /* clean up */ + inflateEnd(&strm); + free(junk); + bclose(in); + + /* write trailer if this is the last gzip file */ + if (!clr) { + put4(*crc, out); + put4(*tot, out); + } +} + +/* join the gzip files on the command line, write result to stdout */ +int main(int argc, char **argv) +{ + unsigned long crc, tot; /* running crc and total uncompressed length */ + + /* skip command name */ + argc--; + argv++; + + /* show usage if no arguments */ + if (argc == 0) { + fputs("gzjoin usage: gzjoin f1.gz [f2.gz [f3.gz ...]] > fjoin.gz\n", + stderr); + return 0; + } + + /* join gzip files on command line and write to stdout */ + gzinit(&crc, &tot, stdout); + while (argc--) + gzcopy(*argv++, argc, &crc, &tot, stdout); + + /* done */ + return 0; +} diff --git a/zlib-1.2.11/examples/gzlog.c b/zlib-1.2.11/examples/gzlog.c new file mode 100644 index 00000000..b8c29274 --- /dev/null +++ b/zlib-1.2.11/examples/gzlog.c @@ -0,0 +1,1059 @@ +/* + * gzlog.c + * Copyright (C) 2004, 2008, 2012, 2016 Mark Adler, all rights reserved + * For conditions of distribution and use, see copyright notice in gzlog.h + * version 2.2, 14 Aug 2012 + */ + +/* + gzlog provides a mechanism for frequently appending short strings to a gzip + file that is efficient both in execution time and compression ratio. The + strategy is to write the short strings in an uncompressed form to the end of + the gzip file, only compressing when the amount of uncompressed data has + reached a given threshold. + + gzlog also provides protection against interruptions in the process due to + system crashes. The status of the operation is recorded in an extra field + in the gzip file, and is only updated once the gzip file is brought to a + valid state. The last data to be appended or compressed is saved in an + auxiliary file, so that if the operation is interrupted, it can be completed + the next time an append operation is attempted. + + gzlog maintains another auxiliary file with the last 32K of data from the + compressed portion, which is preloaded for the compression of the subsequent + data. This minimizes the impact to the compression ratio of appending. + */ + +/* + Operations Concept: + + Files (log name "foo"): + foo.gz -- gzip file with the complete log + foo.add -- last message to append or last data to compress + foo.dict -- dictionary of the last 32K of data for next compression + foo.temp -- temporary dictionary file for compression after this one + foo.lock -- lock file for reading and writing the other files + foo.repairs -- log file for log file recovery operations (not compressed) + + gzip file structure: + - fixed-length (no file name) header with extra field (see below) + - compressed data ending initially with empty stored block + - uncompressed data filling out originally empty stored block and + subsequent stored blocks as needed (16K max each) + - gzip trailer + - no junk at end (no other gzip streams) + + When appending data, the information in the first three items above plus the + foo.add file are sufficient to recover an interrupted append operation. The + extra field has the necessary information to restore the start of the last + stored block and determine where to append the data in the foo.add file, as + well as the crc and length of the gzip data before the append operation. + + The foo.add file is created before the gzip file is marked for append, and + deleted after the gzip file is marked as complete. So if the append + operation is interrupted, the data to add will still be there. If due to + some external force, the foo.add file gets deleted between when the append + operation was interrupted and when recovery is attempted, the gzip file will + still be restored, but without the appended data. + + When compressing data, the information in the first two items above plus the + foo.add file are sufficient to recover an interrupted compress operation. + The extra field has the necessary information to find the end of the + compressed data, and contains both the crc and length of just the compressed + data and of the complete set of data including the contents of the foo.add + file. + + Again, the foo.add file is maintained during the compress operation in case + of an interruption. If in the unlikely event the foo.add file with the data + to be compressed is missing due to some external force, a gzip file with + just the previous compressed data will be reconstructed. In this case, all + of the data that was to be compressed is lost (approximately one megabyte). + This will not occur if all that happened was an interruption of the compress + operation. + + The third state that is marked is the replacement of the old dictionary with + the new dictionary after a compress operation. Once compression is + complete, the gzip file is marked as being in the replace state. This + completes the gzip file, so an interrupt after being so marked does not + result in recompression. Then the dictionary file is replaced, and the gzip + file is marked as completed. This state prevents the possibility of + restarting compression with the wrong dictionary file. + + All three operations are wrapped by a lock/unlock procedure. In order to + gain exclusive access to the log files, first a foo.lock file must be + exclusively created. When all operations are complete, the lock is + released by deleting the foo.lock file. If when attempting to create the + lock file, it already exists and the modify time of the lock file is more + than five minutes old (set by the PATIENCE define below), then the old + lock file is considered stale and deleted, and the exclusive creation of + the lock file is retried. To assure that there are no false assessments + of the staleness of the lock file, the operations periodically touch the + lock file to update the modified date. + + Following is the definition of the extra field with all of the information + required to enable the above append and compress operations and their + recovery if interrupted. Multi-byte values are stored little endian + (consistent with the gzip format). File pointers are eight bytes long. + The crc's and lengths for the gzip trailer are four bytes long. (Note that + the length at the end of a gzip file is used for error checking only, and + for large files is actually the length modulo 2^32.) The stored block + length is two bytes long. The gzip extra field two-byte identification is + "ap" for append. It is assumed that writing the extra field to the file is + an "atomic" operation. That is, either all of the extra field is written + to the file, or none of it is, if the operation is interrupted right at the + point of updating the extra field. This is a reasonable assumption, since + the extra field is within the first 52 bytes of the file, which is smaller + than any expected block size for a mass storage device (usually 512 bytes or + larger). + + Extra field (35 bytes): + - Pointer to first stored block length -- this points to the two-byte length + of the first stored block, which is followed by the two-byte, one's + complement of that length. The stored block length is preceded by the + three-bit header of the stored block, which is the actual start of the + stored block in the deflate format. See the bit offset field below. + - Pointer to the last stored block length. This is the same as above, but + for the last stored block of the uncompressed data in the gzip file. + Initially this is the same as the first stored block length pointer. + When the stored block gets to 16K (see the MAX_STORE define), then a new + stored block as added, at which point the last stored block length pointer + is different from the first stored block length pointer. When they are + different, the first bit of the last stored block header is eight bits, or + one byte back from the block length. + - Compressed data crc and length. This is the crc and length of the data + that is in the compressed portion of the deflate stream. These are used + only in the event that the foo.add file containing the data to compress is + lost after a compress operation is interrupted. + - Total data crc and length. This is the crc and length of all of the data + stored in the gzip file, compressed and uncompressed. It is used to + reconstruct the gzip trailer when compressing, as well as when recovering + interrupted operations. + - Final stored block length. This is used to quickly find where to append, + and allows the restoration of the original final stored block state when + an append operation is interrupted. + - First stored block start as the number of bits back from the final stored + block first length byte. This value is in the range of 3..10, and is + stored as the low three bits of the final byte of the extra field after + subtracting three (0..7). This allows the last-block bit of the stored + block header to be updated when a new stored block is added, for the case + when the first stored block and the last stored block are the same. (When + they are different, the numbers of bits back is known to be eight.) This + also allows for new compressed data to be appended to the old compressed + data in the compress operation, overwriting the previous first stored + block, or for the compressed data to be terminated and a valid gzip file + reconstructed on the off chance that a compression operation was + interrupted and the data to compress in the foo.add file was deleted. + - The operation in process. This is the next two bits in the last byte (the + bits under the mask 0x18). The are interpreted as 0: nothing in process, + 1: append in process, 2: compress in process, 3: replace in process. + - The top three bits of the last byte in the extra field are reserved and + are currently set to zero. + + Main procedure: + - Exclusively create the foo.lock file using the O_CREAT and O_EXCL modes of + the system open() call. If the modify time of an existing lock file is + more than PATIENCE seconds old, then the lock file is deleted and the + exclusive create is retried. + - Load the extra field from the foo.gz file, and see if an operation was in + progress but not completed. If so, apply the recovery procedure below. + - Perform the append procedure with the provided data. + - If the uncompressed data in the foo.gz file is 1MB or more, apply the + compress procedure. + - Delete the foo.lock file. + + Append procedure: + - Put what to append in the foo.add file so that the operation can be + restarted if this procedure is interrupted. + - Mark the foo.gz extra field with the append operation in progress. + + Restore the original last-block bit and stored block length of the last + stored block from the information in the extra field, in case a previous + append operation was interrupted. + - Append the provided data to the last stored block, creating new stored + blocks as needed and updating the stored blocks last-block bits and + lengths. + - Update the crc and length with the new data, and write the gzip trailer. + - Write over the extra field (with a single write operation) with the new + pointers, lengths, and crc's, and mark the gzip file as not in process. + Though there is still a foo.add file, it will be ignored since nothing + is in process. If a foo.add file is leftover from a previously + completed operation, it is truncated when writing new data to it. + - Delete the foo.add file. + + Compress and replace procedures: + - Read all of the uncompressed data in the stored blocks in foo.gz and write + it to foo.add. Also write foo.temp with the last 32K of that data to + provide a dictionary for the next invocation of this procedure. + - Rewrite the extra field marking foo.gz with a compression in process. + * If there is no data provided to compress (due to a missing foo.add file + when recovering), reconstruct and truncate the foo.gz file to contain + only the previous compressed data and proceed to the step after the next + one. Otherwise ... + - Compress the data with the dictionary in foo.dict, and write to the + foo.gz file starting at the bit immediately following the last previously + compressed block. If there is no foo.dict, proceed anyway with the + compression at slightly reduced efficiency. (For the foo.dict file to be + missing requires some external failure beyond simply the interruption of + a compress operation.) During this process, the foo.lock file is + periodically touched to assure that that file is not considered stale by + another process before we're done. The deflation is terminated with a + non-last empty static block (10 bits long), that is then located and + written over by a last-bit-set empty stored block. + - Append the crc and length of the data in the gzip file (previously + calculated during the append operations). + - Write over the extra field with the updated stored block offsets, bits + back, crc's, and lengths, and mark foo.gz as in process for a replacement + of the dictionary. + @ Delete the foo.add file. + - Replace foo.dict with foo.temp. + - Write over the extra field, marking foo.gz as complete. + + Recovery procedure: + - If not a replace recovery, read in the foo.add file, and provide that data + to the appropriate recovery below. If there is no foo.add file, provide + a zero data length to the recovery. In that case, the append recovery + restores the foo.gz to the previous compressed + uncompressed data state. + For the the compress recovery, a missing foo.add file results in foo.gz + being restored to the previous compressed-only data state. + - Append recovery: + - Pick up append at + step above + - Compress recovery: + - Pick up compress at * step above + - Replace recovery: + - Pick up compress at @ step above + - Log the repair with a date stamp in foo.repairs + */ + +#include +#include /* rename, fopen, fprintf, fclose */ +#include /* malloc, free */ +#include /* strlen, strrchr, strcpy, strncpy, strcmp */ +#include /* open */ +#include /* lseek, read, write, close, unlink, sleep, */ + /* ftruncate, fsync */ +#include /* errno */ +#include /* time, ctime */ +#include /* stat */ +#include /* utimes */ +#include "zlib.h" /* crc32 */ + +#include "gzlog.h" /* header for external access */ + +#define local static +typedef unsigned int uint; +typedef unsigned long ulong; + +/* Macro for debugging to deterministically force recovery operations */ +#ifdef GZLOG_DEBUG + #include /* longjmp */ + jmp_buf gzlog_jump; /* where to go back to */ + int gzlog_bail = 0; /* which point to bail at (1..8) */ + int gzlog_count = -1; /* number of times through to wait */ +# define BAIL(n) do { if (n == gzlog_bail && gzlog_count-- == 0) \ + longjmp(gzlog_jump, gzlog_bail); } while (0) +#else +# define BAIL(n) +#endif + +/* how old the lock file can be in seconds before considering it stale */ +#define PATIENCE 300 + +/* maximum stored block size in Kbytes -- must be in 1..63 */ +#define MAX_STORE 16 + +/* number of stored Kbytes to trigger compression (must be >= 32 to allow + dictionary construction, and <= 204 * MAX_STORE, in order for >> 10 to + discard the stored block headers contribution of five bytes each) */ +#define TRIGGER 1024 + +/* size of a deflate dictionary (this cannot be changed) */ +#define DICT 32768U + +/* values for the operation (2 bits) */ +#define NO_OP 0 +#define APPEND_OP 1 +#define COMPRESS_OP 2 +#define REPLACE_OP 3 + +/* macros to extract little-endian integers from an unsigned byte buffer */ +#define PULL2(p) ((p)[0]+((uint)((p)[1])<<8)) +#define PULL4(p) (PULL2(p)+((ulong)PULL2(p+2)<<16)) +#define PULL8(p) (PULL4(p)+((off_t)PULL4(p+4)<<32)) + +/* macros to store integers into a byte buffer in little-endian order */ +#define PUT2(p,a) do {(p)[0]=a;(p)[1]=(a)>>8;} while(0) +#define PUT4(p,a) do {PUT2(p,a);PUT2(p+2,a>>16);} while(0) +#define PUT8(p,a) do {PUT4(p,a);PUT4(p+4,a>>32);} while(0) + +/* internal structure for log information */ +#define LOGID "\106\035\172" /* should be three non-zero characters */ +struct log { + char id[4]; /* contains LOGID to detect inadvertent overwrites */ + int fd; /* file descriptor for .gz file, opened read/write */ + char *path; /* allocated path, e.g. "/var/log/foo" or "foo" */ + char *end; /* end of path, for appending suffices such as ".gz" */ + off_t first; /* offset of first stored block first length byte */ + int back; /* location of first block id in bits back from first */ + uint stored; /* bytes currently in last stored block */ + off_t last; /* offset of last stored block first length byte */ + ulong ccrc; /* crc of compressed data */ + ulong clen; /* length (modulo 2^32) of compressed data */ + ulong tcrc; /* crc of total data */ + ulong tlen; /* length (modulo 2^32) of total data */ + time_t lock; /* last modify time of our lock file */ +}; + +/* gzip header for gzlog */ +local unsigned char log_gzhead[] = { + 0x1f, 0x8b, /* magic gzip id */ + 8, /* compression method is deflate */ + 4, /* there is an extra field (no file name) */ + 0, 0, 0, 0, /* no modification time provided */ + 0, 0xff, /* no extra flags, no OS specified */ + 39, 0, 'a', 'p', 35, 0 /* extra field with "ap" subfield */ + /* 35 is EXTRA, 39 is EXTRA + 4 */ +}; + +#define HEAD sizeof(log_gzhead) /* should be 16 */ + +/* initial gzip extra field content (52 == HEAD + EXTRA + 1) */ +local unsigned char log_gzext[] = { + 52, 0, 0, 0, 0, 0, 0, 0, /* offset of first stored block length */ + 52, 0, 0, 0, 0, 0, 0, 0, /* offset of last stored block length */ + 0, 0, 0, 0, 0, 0, 0, 0, /* compressed data crc and length */ + 0, 0, 0, 0, 0, 0, 0, 0, /* total data crc and length */ + 0, 0, /* final stored block data length */ + 5 /* op is NO_OP, last bit 8 bits back */ +}; + +#define EXTRA sizeof(log_gzext) /* should be 35 */ + +/* initial gzip data and trailer */ +local unsigned char log_gzbody[] = { + 1, 0, 0, 0xff, 0xff, /* empty stored block (last) */ + 0, 0, 0, 0, /* crc */ + 0, 0, 0, 0 /* uncompressed length */ +}; + +#define BODY sizeof(log_gzbody) + +/* Exclusively create foo.lock in order to negotiate exclusive access to the + foo.* files. If the modify time of an existing lock file is greater than + PATIENCE seconds in the past, then consider the lock file to have been + abandoned, delete it, and try the exclusive create again. Save the lock + file modify time for verification of ownership. Return 0 on success, or -1 + on failure, usually due to an access restriction or invalid path. Note that + if stat() or unlink() fails, it may be due to another process noticing the + abandoned lock file a smidge sooner and deleting it, so those are not + flagged as an error. */ +local int log_lock(struct log *log) +{ + int fd; + struct stat st; + + strcpy(log->end, ".lock"); + while ((fd = open(log->path, O_CREAT | O_EXCL, 0644)) < 0) { + if (errno != EEXIST) + return -1; + if (stat(log->path, &st) == 0 && time(NULL) - st.st_mtime > PATIENCE) { + unlink(log->path); + continue; + } + sleep(2); /* relinquish the CPU for two seconds while waiting */ + } + close(fd); + if (stat(log->path, &st) == 0) + log->lock = st.st_mtime; + return 0; +} + +/* Update the modify time of the lock file to now, in order to prevent another + task from thinking that the lock is stale. Save the lock file modify time + for verification of ownership. */ +local void log_touch(struct log *log) +{ + struct stat st; + + strcpy(log->end, ".lock"); + utimes(log->path, NULL); + if (stat(log->path, &st) == 0) + log->lock = st.st_mtime; +} + +/* Check the log file modify time against what is expected. Return true if + this is not our lock. If it is our lock, touch it to keep it. */ +local int log_check(struct log *log) +{ + struct stat st; + + strcpy(log->end, ".lock"); + if (stat(log->path, &st) || st.st_mtime != log->lock) + return 1; + log_touch(log); + return 0; +} + +/* Unlock a previously acquired lock, but only if it's ours. */ +local void log_unlock(struct log *log) +{ + if (log_check(log)) + return; + strcpy(log->end, ".lock"); + unlink(log->path); + log->lock = 0; +} + +/* Check the gzip header and read in the extra field, filling in the values in + the log structure. Return op on success or -1 if the gzip header was not as + expected. op is the current operation in progress last written to the extra + field. This assumes that the gzip file has already been opened, with the + file descriptor log->fd. */ +local int log_head(struct log *log) +{ + int op; + unsigned char buf[HEAD + EXTRA]; + + if (lseek(log->fd, 0, SEEK_SET) < 0 || + read(log->fd, buf, HEAD + EXTRA) != HEAD + EXTRA || + memcmp(buf, log_gzhead, HEAD)) { + return -1; + } + log->first = PULL8(buf + HEAD); + log->last = PULL8(buf + HEAD + 8); + log->ccrc = PULL4(buf + HEAD + 16); + log->clen = PULL4(buf + HEAD + 20); + log->tcrc = PULL4(buf + HEAD + 24); + log->tlen = PULL4(buf + HEAD + 28); + log->stored = PULL2(buf + HEAD + 32); + log->back = 3 + (buf[HEAD + 34] & 7); + op = (buf[HEAD + 34] >> 3) & 3; + return op; +} + +/* Write over the extra field contents, marking the operation as op. Use fsync + to assure that the device is written to, and in the requested order. This + operation, and only this operation, is assumed to be atomic in order to + assure that the log is recoverable in the event of an interruption at any + point in the process. Return -1 if the write to foo.gz failed. */ +local int log_mark(struct log *log, int op) +{ + int ret; + unsigned char ext[EXTRA]; + + PUT8(ext, log->first); + PUT8(ext + 8, log->last); + PUT4(ext + 16, log->ccrc); + PUT4(ext + 20, log->clen); + PUT4(ext + 24, log->tcrc); + PUT4(ext + 28, log->tlen); + PUT2(ext + 32, log->stored); + ext[34] = log->back - 3 + (op << 3); + fsync(log->fd); + ret = lseek(log->fd, HEAD, SEEK_SET) < 0 || + write(log->fd, ext, EXTRA) != EXTRA ? -1 : 0; + fsync(log->fd); + return ret; +} + +/* Rewrite the last block header bits and subsequent zero bits to get to a byte + boundary, setting the last block bit if last is true, and then write the + remainder of the stored block header (length and one's complement). Leave + the file pointer after the end of the last stored block data. Return -1 if + there is a read or write failure on the foo.gz file */ +local int log_last(struct log *log, int last) +{ + int back, len, mask; + unsigned char buf[6]; + + /* determine the locations of the bytes and bits to modify */ + back = log->last == log->first ? log->back : 8; + len = back > 8 ? 2 : 1; /* bytes back from log->last */ + mask = 0x80 >> ((back - 1) & 7); /* mask for block last-bit */ + + /* get the byte to modify (one or two back) into buf[0] -- don't need to + read the byte if the last-bit is eight bits back, since in that case + the entire byte will be modified */ + buf[0] = 0; + if (back != 8 && (lseek(log->fd, log->last - len, SEEK_SET) < 0 || + read(log->fd, buf, 1) != 1)) + return -1; + + /* change the last-bit of the last stored block as requested -- note + that all bits above the last-bit are set to zero, per the type bits + of a stored block being 00 and per the convention that the bits to + bring the stream to a byte boundary are also zeros */ + buf[1] = 0; + buf[2 - len] = (*buf & (mask - 1)) + (last ? mask : 0); + + /* write the modified stored block header and lengths, move the file + pointer to after the last stored block data */ + PUT2(buf + 2, log->stored); + PUT2(buf + 4, log->stored ^ 0xffff); + return lseek(log->fd, log->last - len, SEEK_SET) < 0 || + write(log->fd, buf + 2 - len, len + 4) != len + 4 || + lseek(log->fd, log->stored, SEEK_CUR) < 0 ? -1 : 0; +} + +/* Append len bytes from data to the locked and open log file. len may be zero + if recovering and no .add file was found. In that case, the previous state + of the foo.gz file is restored. The data is appended uncompressed in + deflate stored blocks. Return -1 if there was an error reading or writing + the foo.gz file. */ +local int log_append(struct log *log, unsigned char *data, size_t len) +{ + uint put; + off_t end; + unsigned char buf[8]; + + /* set the last block last-bit and length, in case recovering an + interrupted append, then position the file pointer to append to the + block */ + if (log_last(log, 1)) + return -1; + + /* append, adding stored blocks and updating the offset of the last stored + block as needed, and update the total crc and length */ + while (len) { + /* append as much as we can to the last block */ + put = (MAX_STORE << 10) - log->stored; + if (put > len) + put = (uint)len; + if (put) { + if (write(log->fd, data, put) != put) + return -1; + BAIL(1); + log->tcrc = crc32(log->tcrc, data, put); + log->tlen += put; + log->stored += put; + data += put; + len -= put; + } + + /* if we need to, add a new empty stored block */ + if (len) { + /* mark current block as not last */ + if (log_last(log, 0)) + return -1; + + /* point to new, empty stored block */ + log->last += 4 + log->stored + 1; + log->stored = 0; + } + + /* mark last block as last, update its length */ + if (log_last(log, 1)) + return -1; + BAIL(2); + } + + /* write the new crc and length trailer, and truncate just in case (could + be recovering from partial append with a missing foo.add file) */ + PUT4(buf, log->tcrc); + PUT4(buf + 4, log->tlen); + if (write(log->fd, buf, 8) != 8 || + (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end)) + return -1; + + /* write the extra field, marking the log file as done, delete .add file */ + if (log_mark(log, NO_OP)) + return -1; + strcpy(log->end, ".add"); + unlink(log->path); /* ignore error, since may not exist */ + return 0; +} + +/* Replace the foo.dict file with the foo.temp file. Also delete the foo.add + file, since the compress operation may have been interrupted before that was + done. Returns 1 if memory could not be allocated, or -1 if reading or + writing foo.gz fails, or if the rename fails for some reason other than + foo.temp not existing. foo.temp not existing is a permitted error, since + the replace operation may have been interrupted after the rename is done, + but before foo.gz is marked as complete. */ +local int log_replace(struct log *log) +{ + int ret; + char *dest; + + /* delete foo.add file */ + strcpy(log->end, ".add"); + unlink(log->path); /* ignore error, since may not exist */ + BAIL(3); + + /* rename foo.name to foo.dict, replacing foo.dict if it exists */ + strcpy(log->end, ".dict"); + dest = malloc(strlen(log->path) + 1); + if (dest == NULL) + return -2; + strcpy(dest, log->path); + strcpy(log->end, ".temp"); + ret = rename(log->path, dest); + free(dest); + if (ret && errno != ENOENT) + return -1; + BAIL(4); + + /* mark the foo.gz file as done */ + return log_mark(log, NO_OP); +} + +/* Compress the len bytes at data and append the compressed data to the + foo.gz deflate data immediately after the previous compressed data. This + overwrites the previous uncompressed data, which was stored in foo.add + and is the data provided in data[0..len-1]. If this operation is + interrupted, it picks up at the start of this routine, with the foo.add + file read in again. If there is no data to compress (len == 0), then we + simply terminate the foo.gz file after the previously compressed data, + appending a final empty stored block and the gzip trailer. Return -1 if + reading or writing the log.gz file failed, or -2 if there was a memory + allocation failure. */ +local int log_compress(struct log *log, unsigned char *data, size_t len) +{ + int fd; + uint got, max; + ssize_t dict; + off_t end; + z_stream strm; + unsigned char buf[DICT]; + + /* compress and append compressed data */ + if (len) { + /* set up for deflate, allocating memory */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8, + Z_DEFAULT_STRATEGY) != Z_OK) + return -2; + + /* read in dictionary (last 32K of data that was compressed) */ + strcpy(log->end, ".dict"); + fd = open(log->path, O_RDONLY, 0); + if (fd >= 0) { + dict = read(fd, buf, DICT); + close(fd); + if (dict < 0) { + deflateEnd(&strm); + return -1; + } + if (dict) + deflateSetDictionary(&strm, buf, (uint)dict); + } + log_touch(log); + + /* prime deflate with last bits of previous block, position write + pointer to write those bits and overwrite what follows */ + if (lseek(log->fd, log->first - (log->back > 8 ? 2 : 1), + SEEK_SET) < 0 || + read(log->fd, buf, 1) != 1 || lseek(log->fd, -1, SEEK_CUR) < 0) { + deflateEnd(&strm); + return -1; + } + deflatePrime(&strm, (8 - log->back) & 7, *buf); + + /* compress, finishing with a partial non-last empty static block */ + strm.next_in = data; + max = (((uint)0 - 1) >> 1) + 1; /* in case int smaller than size_t */ + do { + strm.avail_in = len > max ? max : (uint)len; + len -= strm.avail_in; + do { + strm.avail_out = DICT; + strm.next_out = buf; + deflate(&strm, len ? Z_NO_FLUSH : Z_PARTIAL_FLUSH); + got = DICT - strm.avail_out; + if (got && write(log->fd, buf, got) != got) { + deflateEnd(&strm); + return -1; + } + log_touch(log); + } while (strm.avail_out == 0); + } while (len); + deflateEnd(&strm); + BAIL(5); + + /* find start of empty static block -- scanning backwards the first one + bit is the second bit of the block, if the last byte is zero, then + we know the byte before that has a one in the top bit, since an + empty static block is ten bits long */ + if ((log->first = lseek(log->fd, -1, SEEK_CUR)) < 0 || + read(log->fd, buf, 1) != 1) + return -1; + log->first++; + if (*buf) { + log->back = 1; + while ((*buf & ((uint)1 << (8 - log->back++))) == 0) + ; /* guaranteed to terminate, since *buf != 0 */ + } + else + log->back = 10; + + /* update compressed crc and length */ + log->ccrc = log->tcrc; + log->clen = log->tlen; + } + else { + /* no data to compress -- fix up existing gzip stream */ + log->tcrc = log->ccrc; + log->tlen = log->clen; + } + + /* complete and truncate gzip stream */ + log->last = log->first; + log->stored = 0; + PUT4(buf, log->tcrc); + PUT4(buf + 4, log->tlen); + if (log_last(log, 1) || write(log->fd, buf, 8) != 8 || + (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end)) + return -1; + BAIL(6); + + /* mark as being in the replace operation */ + if (log_mark(log, REPLACE_OP)) + return -1; + + /* execute the replace operation and mark the file as done */ + return log_replace(log); +} + +/* log a repair record to the .repairs file */ +local void log_log(struct log *log, int op, char *record) +{ + time_t now; + FILE *rec; + + now = time(NULL); + strcpy(log->end, ".repairs"); + rec = fopen(log->path, "a"); + if (rec == NULL) + return; + fprintf(rec, "%.24s %s recovery: %s\n", ctime(&now), op == APPEND_OP ? + "append" : (op == COMPRESS_OP ? "compress" : "replace"), record); + fclose(rec); + return; +} + +/* Recover the interrupted operation op. First read foo.add for recovering an + append or compress operation. Return -1 if there was an error reading or + writing foo.gz or reading an existing foo.add, or -2 if there was a memory + allocation failure. */ +local int log_recover(struct log *log, int op) +{ + int fd, ret = 0; + unsigned char *data = NULL; + size_t len = 0; + struct stat st; + + /* log recovery */ + log_log(log, op, "start"); + + /* load foo.add file if expected and present */ + if (op == APPEND_OP || op == COMPRESS_OP) { + strcpy(log->end, ".add"); + if (stat(log->path, &st) == 0 && st.st_size) { + len = (size_t)(st.st_size); + if ((off_t)len != st.st_size || + (data = malloc(st.st_size)) == NULL) { + log_log(log, op, "allocation failure"); + return -2; + } + if ((fd = open(log->path, O_RDONLY, 0)) < 0) { + log_log(log, op, ".add file read failure"); + return -1; + } + ret = (size_t)read(fd, data, len) != len; + close(fd); + if (ret) { + log_log(log, op, ".add file read failure"); + return -1; + } + log_log(log, op, "loaded .add file"); + } + else + log_log(log, op, "missing .add file!"); + } + + /* recover the interrupted operation */ + switch (op) { + case APPEND_OP: + ret = log_append(log, data, len); + break; + case COMPRESS_OP: + ret = log_compress(log, data, len); + break; + case REPLACE_OP: + ret = log_replace(log); + } + + /* log status */ + log_log(log, op, ret ? "failure" : "complete"); + + /* clean up */ + if (data != NULL) + free(data); + return ret; +} + +/* Close the foo.gz file (if open) and release the lock. */ +local void log_close(struct log *log) +{ + if (log->fd >= 0) + close(log->fd); + log->fd = -1; + log_unlock(log); +} + +/* Open foo.gz, verify the header, and load the extra field contents, after + first creating the foo.lock file to gain exclusive access to the foo.* + files. If foo.gz does not exist or is empty, then write the initial header, + extra, and body content of an empty foo.gz log file. If there is an error + creating the lock file due to access restrictions, or an error reading or + writing the foo.gz file, or if the foo.gz file is not a proper log file for + this object (e.g. not a gzip file or does not contain the expected extra + field), then return true. If there is an error, the lock is released. + Otherwise, the lock is left in place. */ +local int log_open(struct log *log) +{ + int op; + + /* release open file resource if left over -- can occur if lock lost + between gzlog_open() and gzlog_write() */ + if (log->fd >= 0) + close(log->fd); + log->fd = -1; + + /* negotiate exclusive access */ + if (log_lock(log) < 0) + return -1; + + /* open the log file, foo.gz */ + strcpy(log->end, ".gz"); + log->fd = open(log->path, O_RDWR | O_CREAT, 0644); + if (log->fd < 0) { + log_close(log); + return -1; + } + + /* if new, initialize foo.gz with an empty log, delete old dictionary */ + if (lseek(log->fd, 0, SEEK_END) == 0) { + if (write(log->fd, log_gzhead, HEAD) != HEAD || + write(log->fd, log_gzext, EXTRA) != EXTRA || + write(log->fd, log_gzbody, BODY) != BODY) { + log_close(log); + return -1; + } + strcpy(log->end, ".dict"); + unlink(log->path); + } + + /* verify log file and load extra field information */ + if ((op = log_head(log)) < 0) { + log_close(log); + return -1; + } + + /* check for interrupted process and if so, recover */ + if (op != NO_OP && log_recover(log, op)) { + log_close(log); + return -1; + } + + /* touch the lock file to prevent another process from grabbing it */ + log_touch(log); + return 0; +} + +/* See gzlog.h for the description of the external methods below */ +gzlog *gzlog_open(char *path) +{ + size_t n; + struct log *log; + + /* check arguments */ + if (path == NULL || *path == 0) + return NULL; + + /* allocate and initialize log structure */ + log = malloc(sizeof(struct log)); + if (log == NULL) + return NULL; + strcpy(log->id, LOGID); + log->fd = -1; + + /* save path and end of path for name construction */ + n = strlen(path); + log->path = malloc(n + 9); /* allow for ".repairs" */ + if (log->path == NULL) { + free(log); + return NULL; + } + strcpy(log->path, path); + log->end = log->path + n; + + /* gain exclusive access and verify log file -- may perform a + recovery operation if needed */ + if (log_open(log)) { + free(log->path); + free(log); + return NULL; + } + + /* return pointer to log structure */ + return log; +} + +/* gzlog_compress() return values: + 0: all good + -1: file i/o error (usually access issue) + -2: memory allocation failure + -3: invalid log pointer argument */ +int gzlog_compress(gzlog *logd) +{ + int fd, ret; + uint block; + size_t len, next; + unsigned char *data, buf[5]; + struct log *log = logd; + + /* check arguments */ + if (log == NULL || strcmp(log->id, LOGID)) + return -3; + + /* see if we lost the lock -- if so get it again and reload the extra + field information (it probably changed), recover last operation if + necessary */ + if (log_check(log) && log_open(log)) + return -1; + + /* create space for uncompressed data */ + len = ((size_t)(log->last - log->first) & ~(((size_t)1 << 10) - 1)) + + log->stored; + if ((data = malloc(len)) == NULL) + return -2; + + /* do statement here is just a cheap trick for error handling */ + do { + /* read in the uncompressed data */ + if (lseek(log->fd, log->first - 1, SEEK_SET) < 0) + break; + next = 0; + while (next < len) { + if (read(log->fd, buf, 5) != 5) + break; + block = PULL2(buf + 1); + if (next + block > len || + read(log->fd, (char *)data + next, block) != block) + break; + next += block; + } + if (lseek(log->fd, 0, SEEK_CUR) != log->last + 4 + log->stored) + break; + log_touch(log); + + /* write the uncompressed data to the .add file */ + strcpy(log->end, ".add"); + fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) + break; + ret = (size_t)write(fd, data, len) != len; + if (ret | close(fd)) + break; + log_touch(log); + + /* write the dictionary for the next compress to the .temp file */ + strcpy(log->end, ".temp"); + fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) + break; + next = DICT > len ? len : DICT; + ret = (size_t)write(fd, (char *)data + len - next, next) != next; + if (ret | close(fd)) + break; + log_touch(log); + + /* roll back to compressed data, mark the compress in progress */ + log->last = log->first; + log->stored = 0; + if (log_mark(log, COMPRESS_OP)) + break; + BAIL(7); + + /* compress and append the data (clears mark) */ + ret = log_compress(log, data, len); + free(data); + return ret; + } while (0); + + /* broke out of do above on i/o error */ + free(data); + return -1; +} + +/* gzlog_write() return values: + 0: all good + -1: file i/o error (usually access issue) + -2: memory allocation failure + -3: invalid log pointer argument */ +int gzlog_write(gzlog *logd, void *data, size_t len) +{ + int fd, ret; + struct log *log = logd; + + /* check arguments */ + if (log == NULL || strcmp(log->id, LOGID)) + return -3; + if (data == NULL || len <= 0) + return 0; + + /* see if we lost the lock -- if so get it again and reload the extra + field information (it probably changed), recover last operation if + necessary */ + if (log_check(log) && log_open(log)) + return -1; + + /* create and write .add file */ + strcpy(log->end, ".add"); + fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) + return -1; + ret = (size_t)write(fd, data, len) != len; + if (ret | close(fd)) + return -1; + log_touch(log); + + /* mark log file with append in progress */ + if (log_mark(log, APPEND_OP)) + return -1; + BAIL(8); + + /* append data (clears mark) */ + if (log_append(log, data, len)) + return -1; + + /* check to see if it's time to compress -- if not, then done */ + if (((log->last - log->first) >> 10) + (log->stored >> 10) < TRIGGER) + return 0; + + /* time to compress */ + return gzlog_compress(log); +} + +/* gzlog_close() return values: + 0: ok + -3: invalid log pointer argument */ +int gzlog_close(gzlog *logd) +{ + struct log *log = logd; + + /* check arguments */ + if (log == NULL || strcmp(log->id, LOGID)) + return -3; + + /* close the log file and release the lock */ + log_close(log); + + /* free structure and return */ + if (log->path != NULL) + free(log->path); + strcpy(log->id, "bad"); + free(log); + return 0; +} diff --git a/zlib-1.2.11/examples/gzlog.h b/zlib-1.2.11/examples/gzlog.h new file mode 100644 index 00000000..86f0cecb --- /dev/null +++ b/zlib-1.2.11/examples/gzlog.h @@ -0,0 +1,91 @@ +/* gzlog.h + Copyright (C) 2004, 2008, 2012 Mark Adler, all rights reserved + version 2.2, 14 Aug 2012 + + This software is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Mark Adler madler@alumni.caltech.edu + */ + +/* Version History: + 1.0 26 Nov 2004 First version + 2.0 25 Apr 2008 Complete redesign for recovery of interrupted operations + Interface changed slightly in that now path is a prefix + Compression now occurs as needed during gzlog_write() + gzlog_write() now always leaves the log file as valid gzip + 2.1 8 Jul 2012 Fix argument checks in gzlog_compress() and gzlog_write() + 2.2 14 Aug 2012 Clean up signed comparisons + */ + +/* + The gzlog object allows writing short messages to a gzipped log file, + opening the log file locked for small bursts, and then closing it. The log + object works by appending stored (uncompressed) data to the gzip file until + 1 MB has been accumulated. At that time, the stored data is compressed, and + replaces the uncompressed data in the file. The log file is truncated to + its new size at that time. After each write operation, the log file is a + valid gzip file that can decompressed to recover what was written. + + The gzlog operations can be interupted at any point due to an application or + system crash, and the log file will be recovered the next time the log is + opened with gzlog_open(). + */ + +#ifndef GZLOG_H +#define GZLOG_H + +/* gzlog object type */ +typedef void gzlog; + +/* Open a gzlog object, creating the log file if it does not exist. Return + NULL on error. Note that gzlog_open() could take a while to complete if it + has to wait to verify that a lock is stale (possibly for five minutes), or + if there is significant contention with other instantiations of this object + when locking the resource. path is the prefix of the file names created by + this object. If path is "foo", then the log file will be "foo.gz", and + other auxiliary files will be created and destroyed during the process: + "foo.dict" for a compression dictionary, "foo.temp" for a temporary (next) + dictionary, "foo.add" for data being added or compressed, "foo.lock" for the + lock file, and "foo.repairs" to log recovery operations performed due to + interrupted gzlog operations. A gzlog_open() followed by a gzlog_close() + will recover a previously interrupted operation, if any. */ +gzlog *gzlog_open(char *path); + +/* Write to a gzlog object. Return zero on success, -1 if there is a file i/o + error on any of the gzlog files (this should not happen if gzlog_open() + succeeded, unless the device has run out of space or leftover auxiliary + files have permissions or ownership that prevent their use), -2 if there is + a memory allocation failure, or -3 if the log argument is invalid (e.g. if + it was not created by gzlog_open()). This function will write data to the + file uncompressed, until 1 MB has been accumulated, at which time that data + will be compressed. The log file will be a valid gzip file upon successful + return. */ +int gzlog_write(gzlog *log, void *data, size_t len); + +/* Force compression of any uncompressed data in the log. This should be used + sparingly, if at all. The main application would be when a log file will + not be appended to again. If this is used to compress frequently while + appending, it will both significantly increase the execution time and + reduce the compression ratio. The return codes are the same as for + gzlog_write(). */ +int gzlog_compress(gzlog *log); + +/* Close a gzlog object. Return zero on success, -3 if the log argument is + invalid. The log object is freed, and so cannot be referenced again. */ +int gzlog_close(gzlog *log); + +#endif diff --git a/zlib-1.2.11/examples/zlib_how.html b/zlib-1.2.11/examples/zlib_how.html new file mode 100644 index 00000000..444ff1c9 --- /dev/null +++ b/zlib-1.2.11/examples/zlib_how.html @@ -0,0 +1,545 @@ + + + + +zlib Usage Example + + + +

zlib Usage Example

+We often get questions about how the deflate() and inflate() functions should be used. +Users wonder when they should provide more input, when they should use more output, +what to do with a Z_BUF_ERROR, how to make sure the process terminates properly, and +so on. So for those who have read zlib.h (a few times), and +would like further edification, below is an annotated example in C of simple routines to compress and decompress +from an input file to an output file using deflate() and inflate() respectively. The +annotations are interspersed between lines of the code. So please read between the lines. +We hope this helps explain some of the intricacies of zlib. +

+Without further adieu, here is the program zpipe.c: +


+/* zpipe.c: example of proper use of zlib's inflate() and deflate()
+   Not copyrighted -- provided to the public domain
+   Version 1.4  11 December 2005  Mark Adler */
+
+/* Version history:
+   1.0  30 Oct 2004  First version
+   1.1   8 Nov 2004  Add void casting for unused return values
+                     Use switch statement for inflate() return values
+   1.2   9 Nov 2004  Add assertions to document zlib guarantees
+   1.3   6 Apr 2005  Remove incorrect assertion in inf()
+   1.4  11 Dec 2005  Add hack to avoid MSDOS end-of-line conversions
+                     Avoid some compiler warnings for input and output buffers
+ */
+
+We now include the header files for the required definitions. From +stdio.h we use fopen(), fread(), fwrite(), +feof(), ferror(), and fclose() for file i/o, and +fputs() for error messages. From string.h we use +strcmp() for command line argument processing. +From assert.h we use the assert() macro. +From zlib.h +we use the basic compression functions deflateInit(), +deflate(), and deflateEnd(), and the basic decompression +functions inflateInit(), inflate(), and +inflateEnd(). +

+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "zlib.h"
+
+This is an ugly hack required to avoid corruption of the input and output data on +Windows/MS-DOS systems. Without this, those systems would assume that the input and output +files are text, and try to convert the end-of-line characters from one standard to +another. That would corrupt binary data, and in particular would render the compressed data unusable. +This sets the input and output to binary which suppresses the end-of-line conversions. +SET_BINARY_MODE() will be used later on stdin and stdout, at the beginning of main(). +

+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
+#  include <fcntl.h>
+#  include <io.h>
+#  define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+#  define SET_BINARY_MODE(file)
+#endif
+
+CHUNK is simply the buffer size for feeding data to and pulling data +from the zlib routines. Larger buffer sizes would be more efficient, +especially for inflate(). If the memory is available, buffers sizes +on the order of 128K or 256K bytes should be used. +

+#define CHUNK 16384
+
+The def() routine compresses data from an input file to an output file. The output data +will be in the zlib format, which is different from the gzip or zip +formats. The zlib format has a very small header of only two bytes to identify it as +a zlib stream and to provide decoding information, and a four-byte trailer with a fast +check value to verify the integrity of the uncompressed data after decoding. +

+/* Compress from file source to file dest until EOF on source.
+   def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_STREAM_ERROR if an invalid compression
+   level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
+   version of the library linked do not match, or Z_ERRNO if there is
+   an error reading or writing the files. */
+int def(FILE *source, FILE *dest, int level)
+{
+
+Here are the local variables for def(). ret will be used for zlib +return codes. flush will keep track of the current flushing state for deflate(), +which is either no flushing, or flush to completion after the end of the input file is reached. +have is the amount of data returned from deflate(). The strm structure +is used to pass information to and from the zlib routines, and to maintain the +deflate() state. in and out are the input and output buffers for +deflate(). +

+    int ret, flush;
+    unsigned have;
+    z_stream strm;
+    unsigned char in[CHUNK];
+    unsigned char out[CHUNK];
+
+The first thing we do is to initialize the zlib state for compression using +deflateInit(). This must be done before the first use of deflate(). +The zalloc, zfree, and opaque fields in the strm +structure must be initialized before calling deflateInit(). Here they are +set to the zlib constant Z_NULL to request that zlib use +the default memory allocation routines. An application may also choose to provide +custom memory allocation routines here. deflateInit() will allocate on the +order of 256K bytes for the internal state. +(See zlib Technical Details.) +

+deflateInit() is called with a pointer to the structure to be initialized and +the compression level, which is an integer in the range of -1 to 9. Lower compression +levels result in faster execution, but less compression. Higher levels result in +greater compression, but slower execution. The zlib constant Z_DEFAULT_COMPRESSION, +equal to -1, +provides a good compromise between compression and speed and is equivalent to level 6. +Level 0 actually does no compression at all, and in fact expands the data slightly to produce +the zlib format (it is not a byte-for-byte copy of the input). +More advanced applications of zlib +may use deflateInit2() here instead. Such an application may want to reduce how +much memory will be used, at some price in compression. Or it may need to request a +gzip header and trailer instead of a zlib header and trailer, or raw +encoding with no header or trailer at all. +

+We must check the return value of deflateInit() against the zlib constant +Z_OK to make sure that it was able to +allocate memory for the internal state, and that the provided arguments were valid. +deflateInit() will also check that the version of zlib that the zlib.h +file came from matches the version of zlib actually linked with the program. This +is especially important for environments in which zlib is a shared library. +

+Note that an application can initialize multiple, independent zlib streams, which can +operate in parallel. The state information maintained in the structure allows the zlib +routines to be reentrant. +


+    /* allocate deflate state */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    ret = deflateInit(&strm, level);
+    if (ret != Z_OK)
+        return ret;
+
+With the pleasantries out of the way, now we can get down to business. The outer do-loop +reads all of the input file and exits at the bottom of the loop once end-of-file is reached. +This loop contains the only call of deflate(). So we must make sure that all of the +input data has been processed and that all of the output data has been generated and consumed +before we fall out of the loop at the bottom. +

+    /* compress until end of file */
+    do {
+
+We start off by reading data from the input file. The number of bytes read is put directly +into avail_in, and a pointer to those bytes is put into next_in. We also +check to see if end-of-file on the input has been reached. If we are at the end of file, then flush is set to the +zlib constant Z_FINISH, which is later passed to deflate() to +indicate that this is the last chunk of input data to compress. We need to use feof() +to check for end-of-file as opposed to seeing if fewer than CHUNK bytes have been read. The +reason is that if the input file length is an exact multiple of CHUNK, we will miss +the fact that we got to the end-of-file, and not know to tell deflate() to finish +up the compressed stream. If we are not yet at the end of the input, then the zlib +constant Z_NO_FLUSH will be passed to deflate to indicate that we are still +in the middle of the uncompressed data. +

+If there is an error in reading from the input file, the process is aborted with +deflateEnd() being called to free the allocated zlib state before returning +the error. We wouldn't want a memory leak, now would we? deflateEnd() can be called +at any time after the state has been initialized. Once that's done, deflateInit() (or +deflateInit2()) would have to be called to start a new compression process. There is +no point here in checking the deflateEnd() return code. The deallocation can't fail. +


+        strm.avail_in = fread(in, 1, CHUNK, source);
+        if (ferror(source)) {
+            (void)deflateEnd(&strm);
+            return Z_ERRNO;
+        }
+        flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
+        strm.next_in = in;
+
+The inner do-loop passes our chunk of input data to deflate(), and then +keeps calling deflate() until it is done producing output. Once there is no more +new output, deflate() is guaranteed to have consumed all of the input, i.e., +avail_in will be zero. +

+        /* run deflate() on input until output buffer not full, finish
+           compression if all of source has been read in */
+        do {
+
+Output space is provided to deflate() by setting avail_out to the number +of available output bytes and next_out to a pointer to that space. +

+            strm.avail_out = CHUNK;
+            strm.next_out = out;
+
+Now we call the compression engine itself, deflate(). It takes as many of the +avail_in bytes at next_in as it can process, and writes as many as +avail_out bytes to next_out. Those counters and pointers are then +updated past the input data consumed and the output data written. It is the amount of +output space available that may limit how much input is consumed. +Hence the inner loop to make sure that +all of the input is consumed by providing more output space each time. Since avail_in +and next_in are updated by deflate(), we don't have to mess with those +between deflate() calls until it's all used up. +

+The parameters to deflate() are a pointer to the strm structure containing +the input and output information and the internal compression engine state, and a parameter +indicating whether and how to flush data to the output. Normally deflate will consume +several K bytes of input data before producing any output (except for the header), in order +to accumulate statistics on the data for optimum compression. It will then put out a burst of +compressed data, and proceed to consume more input before the next burst. Eventually, +deflate() +must be told to terminate the stream, complete the compression with provided input data, and +write out the trailer check value. deflate() will continue to compress normally as long +as the flush parameter is Z_NO_FLUSH. Once the Z_FINISH parameter is provided, +deflate() will begin to complete the compressed output stream. However depending on how +much output space is provided, deflate() may have to be called several times until it +has provided the complete compressed stream, even after it has consumed all of the input. The flush +parameter must continue to be Z_FINISH for those subsequent calls. +

+There are other values of the flush parameter that are used in more advanced applications. You can +force deflate() to produce a burst of output that encodes all of the input data provided +so far, even if it wouldn't have otherwise, for example to control data latency on a link with +compressed data. You can also ask that deflate() do that as well as erase any history up to +that point so that what follows can be decompressed independently, for example for random access +applications. Both requests will degrade compression by an amount depending on how often such +requests are made. +

+deflate() has a return value that can indicate errors, yet we do not check it here. Why +not? Well, it turns out that deflate() can do no wrong here. Let's go through +deflate()'s return values and dispense with them one by one. The possible values are +Z_OK, Z_STREAM_END, Z_STREAM_ERROR, or Z_BUF_ERROR. Z_OK +is, well, ok. Z_STREAM_END is also ok and will be returned for the last call of +deflate(). This is already guaranteed by calling deflate() with Z_FINISH +until it has no more output. Z_STREAM_ERROR is only possible if the stream is not +initialized properly, but we did initialize it properly. There is no harm in checking for +Z_STREAM_ERROR here, for example to check for the possibility that some +other part of the application inadvertently clobbered the memory containing the zlib state. +Z_BUF_ERROR will be explained further below, but +suffice it to say that this is simply an indication that deflate() could not consume +more input or produce more output. deflate() can be called again with more output space +or more available input, which it will be in this code. +


+            ret = deflate(&strm, flush);    /* no bad return value */
+            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+
+Now we compute how much output deflate() provided on the last call, which is the +difference between how much space was provided before the call, and how much output space +is still available after the call. Then that data, if any, is written to the output file. +We can then reuse the output buffer for the next call of deflate(). Again if there +is a file i/o error, we call deflateEnd() before returning to avoid a memory leak. +

+            have = CHUNK - strm.avail_out;
+            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+                (void)deflateEnd(&strm);
+                return Z_ERRNO;
+            }
+
+The inner do-loop is repeated until the last deflate() call fails to fill the +provided output buffer. Then we know that deflate() has done as much as it can with +the provided input, and that all of that input has been consumed. We can then fall out of this +loop and reuse the input buffer. +

+The way we tell that deflate() has no more output is by seeing that it did not fill +the output buffer, leaving avail_out greater than zero. However suppose that +deflate() has no more output, but just so happened to exactly fill the output buffer! +avail_out is zero, and we can't tell that deflate() has done all it can. +As far as we know, deflate() +has more output for us. So we call it again. But now deflate() produces no output +at all, and avail_out remains unchanged as CHUNK. That deflate() call +wasn't able to do anything, either consume input or produce output, and so it returns +Z_BUF_ERROR. (See, I told you I'd cover this later.) However this is not a problem at +all. Now we finally have the desired indication that deflate() is really done, +and so we drop out of the inner loop to provide more input to deflate(). +

+With flush set to Z_FINISH, this final set of deflate() calls will +complete the output stream. Once that is done, subsequent calls of deflate() would return +Z_STREAM_ERROR if the flush parameter is not Z_FINISH, and do no more processing +until the state is reinitialized. +

+Some applications of zlib have two loops that call deflate() +instead of the single inner loop we have here. The first loop would call +without flushing and feed all of the data to deflate(). The second loop would call +deflate() with no more +data and the Z_FINISH parameter to complete the process. As you can see from this +example, that can be avoided by simply keeping track of the current flush state. +


+        } while (strm.avail_out == 0);
+        assert(strm.avail_in == 0);     /* all input will be used */
+
+Now we check to see if we have already processed all of the input file. That information was +saved in the flush variable, so we see if that was set to Z_FINISH. If so, +then we're done and we fall out of the outer loop. We're guaranteed to get Z_STREAM_END +from the last deflate() call, since we ran it until the last chunk of input was +consumed and all of the output was generated. +

+        /* done when last data in file processed */
+    } while (flush != Z_FINISH);
+    assert(ret == Z_STREAM_END);        /* stream will be complete */
+
+The process is complete, but we still need to deallocate the state to avoid a memory leak +(or rather more like a memory hemorrhage if you didn't do this). Then +finally we can return with a happy return value. +

+    /* clean up and return */
+    (void)deflateEnd(&strm);
+    return Z_OK;
+}
+
+Now we do the same thing for decompression in the inf() routine. inf() +decompresses what is hopefully a valid zlib stream from the input file and writes the +uncompressed data to the output file. Much of the discussion above for def() +applies to inf() as well, so the discussion here will focus on the differences between +the two. +

+/* Decompress from file source to file dest until stream ends or EOF.
+   inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
+   allocated for processing, Z_DATA_ERROR if the deflate data is
+   invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
+   the version of the library linked do not match, or Z_ERRNO if there
+   is an error reading or writing the files. */
+int inf(FILE *source, FILE *dest)
+{
+
+The local variables have the same functionality as they do for def(). The +only difference is that there is no flush variable, since inflate() +can tell from the zlib stream itself when the stream is complete. +

+    int ret;
+    unsigned have;
+    z_stream strm;
+    unsigned char in[CHUNK];
+    unsigned char out[CHUNK];
+
+The initialization of the state is the same, except that there is no compression level, +of course, and two more elements of the structure are initialized. avail_in +and next_in must be initialized before calling inflateInit(). This +is because the application has the option to provide the start of the zlib stream in +order for inflateInit() to have access to information about the compression +method to aid in memory allocation. In the current implementation of zlib +(up through versions 1.2.x), the method-dependent memory allocations are deferred to the first call of +inflate() anyway. However those fields must be initialized since later versions +of zlib that provide more compression methods may take advantage of this interface. +In any case, no decompression is performed by inflateInit(), so the +avail_out and next_out fields do not need to be initialized before calling. +

+Here avail_in is set to zero and next_in is set to Z_NULL to +indicate that no input data is being provided. +


+    /* allocate inflate state */
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+    strm.opaque = Z_NULL;
+    strm.avail_in = 0;
+    strm.next_in = Z_NULL;
+    ret = inflateInit(&strm);
+    if (ret != Z_OK)
+        return ret;
+
+The outer do-loop decompresses input until inflate() indicates +that it has reached the end of the compressed data and has produced all of the uncompressed +output. This is in contrast to def() which processes all of the input file. +If end-of-file is reached before the compressed data self-terminates, then the compressed +data is incomplete and an error is returned. +

+    /* decompress until deflate stream ends or end of file */
+    do {
+
+We read input data and set the strm structure accordingly. If we've reached the +end of the input file, then we leave the outer loop and report an error, since the +compressed data is incomplete. Note that we may read more data than is eventually consumed +by inflate(), if the input file continues past the zlib stream. +For applications where zlib streams are embedded in other data, this routine would +need to be modified to return the unused data, or at least indicate how much of the input +data was not used, so the application would know where to pick up after the zlib stream. +

+        strm.avail_in = fread(in, 1, CHUNK, source);
+        if (ferror(source)) {
+            (void)inflateEnd(&strm);
+            return Z_ERRNO;
+        }
+        if (strm.avail_in == 0)
+            break;
+        strm.next_in = in;
+
+The inner do-loop has the same function it did in def(), which is to +keep calling inflate() until has generated all of the output it can with the +provided input. +

+        /* run inflate() on input until output buffer not full */
+        do {
+
+Just like in def(), the same output space is provided for each call of inflate(). +

+            strm.avail_out = CHUNK;
+            strm.next_out = out;
+
+Now we run the decompression engine itself. There is no need to adjust the flush parameter, since +the zlib format is self-terminating. The main difference here is that there are +return values that we need to pay attention to. Z_DATA_ERROR +indicates that inflate() detected an error in the zlib compressed data format, +which means that either the data is not a zlib stream to begin with, or that the data was +corrupted somewhere along the way since it was compressed. The other error to be processed is +Z_MEM_ERROR, which can occur since memory allocation is deferred until inflate() +needs it, unlike deflate(), whose memory is allocated at the start by deflateInit(). +

+Advanced applications may use +deflateSetDictionary() to prime deflate() with a set of likely data to improve the +first 32K or so of compression. This is noted in the zlib header, so inflate() +requests that that dictionary be provided before it can start to decompress. Without the dictionary, +correct decompression is not possible. For this routine, we have no idea what the dictionary is, +so the Z_NEED_DICT indication is converted to a Z_DATA_ERROR. +

+inflate() can also return Z_STREAM_ERROR, which should not be possible here, +but could be checked for as noted above for def(). Z_BUF_ERROR does not need to be +checked for here, for the same reasons noted for def(). Z_STREAM_END will be +checked for later. +


+            ret = inflate(&strm, Z_NO_FLUSH);
+            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
+            switch (ret) {
+            case Z_NEED_DICT:
+                ret = Z_DATA_ERROR;     /* and fall through */
+            case Z_DATA_ERROR:
+            case Z_MEM_ERROR:
+                (void)inflateEnd(&strm);
+                return ret;
+            }
+
+The output of inflate() is handled identically to that of deflate(). +

+            have = CHUNK - strm.avail_out;
+            if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
+                (void)inflateEnd(&strm);
+                return Z_ERRNO;
+            }
+
+The inner do-loop ends when inflate() has no more output as indicated +by not filling the output buffer, just as for deflate(). In this case, we cannot +assert that strm.avail_in will be zero, since the deflate stream may end before the file +does. +

+        } while (strm.avail_out == 0);
+
+The outer do-loop ends when inflate() reports that it has reached the +end of the input zlib stream, has completed the decompression and integrity +check, and has provided all of the output. This is indicated by the inflate() +return value Z_STREAM_END. The inner loop is guaranteed to leave ret +equal to Z_STREAM_END if the last chunk of the input file read contained the end +of the zlib stream. So if the return value is not Z_STREAM_END, the +loop continues to read more input. +

+        /* done when inflate() says it's done */
+    } while (ret != Z_STREAM_END);
+
+At this point, decompression successfully completed, or we broke out of the loop due to no +more data being available from the input file. If the last inflate() return value +is not Z_STREAM_END, then the zlib stream was incomplete and a data error +is returned. Otherwise, we return with a happy return value. Of course, inflateEnd() +is called first to avoid a memory leak. +

+    /* clean up and return */
+    (void)inflateEnd(&strm);
+    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
+}
+
+That ends the routines that directly use zlib. The following routines make this +a command-line program by running data through the above routines from stdin to +stdout, and handling any errors reported by def() or inf(). +

+zerr() is used to interpret the possible error codes from def() +and inf(), as detailed in their comments above, and print out an error message. +Note that these are only a subset of the possible return values from deflate() +and inflate(). +


+/* report a zlib or i/o error */
+void zerr(int ret)
+{
+    fputs("zpipe: ", stderr);
+    switch (ret) {
+    case Z_ERRNO:
+        if (ferror(stdin))
+            fputs("error reading stdin\n", stderr);
+        if (ferror(stdout))
+            fputs("error writing stdout\n", stderr);
+        break;
+    case Z_STREAM_ERROR:
+        fputs("invalid compression level\n", stderr);
+        break;
+    case Z_DATA_ERROR:
+        fputs("invalid or incomplete deflate data\n", stderr);
+        break;
+    case Z_MEM_ERROR:
+        fputs("out of memory\n", stderr);
+        break;
+    case Z_VERSION_ERROR:
+        fputs("zlib version mismatch!\n", stderr);
+    }
+}
+
+Here is the main() routine used to test def() and inf(). The +zpipe command is simply a compression pipe from stdin to stdout, if +no arguments are given, or it is a decompression pipe if zpipe -d is used. If any other +arguments are provided, no compression or decompression is performed. Instead a usage +message is displayed. Examples are zpipe < foo.txt > foo.txt.z to compress, and +zpipe -d < foo.txt.z > foo.txt to decompress. +

+/* compress or decompress from stdin to stdout */
+int main(int argc, char **argv)
+{
+    int ret;
+
+    /* avoid end-of-line conversions */
+    SET_BINARY_MODE(stdin);
+    SET_BINARY_MODE(stdout);
+
+    /* do compression if no arguments */
+    if (argc == 1) {
+        ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
+        if (ret != Z_OK)
+            zerr(ret);
+        return ret;
+    }
+
+    /* do decompression if -d specified */
+    else if (argc == 2 && strcmp(argv[1], "-d") == 0) {
+        ret = inf(stdin, stdout);
+        if (ret != Z_OK)
+            zerr(ret);
+        return ret;
+    }
+
+    /* otherwise, report usage */
+    else {
+        fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
+        return 1;
+    }
+}
+
+
+Copyright (c) 2004, 2005 by Mark Adler
Last modified 11 December 2005
+ + diff --git a/zlib-1.2.11/examples/zpipe.c b/zlib-1.2.11/examples/zpipe.c new file mode 100644 index 00000000..83535d16 --- /dev/null +++ b/zlib-1.2.11/examples/zpipe.c @@ -0,0 +1,205 @@ +/* zpipe.c: example of proper use of zlib's inflate() and deflate() + Not copyrighted -- provided to the public domain + Version 1.4 11 December 2005 Mark Adler */ + +/* Version history: + 1.0 30 Oct 2004 First version + 1.1 8 Nov 2004 Add void casting for unused return values + Use switch statement for inflate() return values + 1.2 9 Nov 2004 Add assertions to document zlib guarantees + 1.3 6 Apr 2005 Remove incorrect assertion in inf() + 1.4 11 Dec 2005 Add hack to avoid MSDOS end-of-line conversions + Avoid some compiler warnings for input and output buffers + */ + +#include +#include +#include +#include "zlib.h" + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) +# include +# include +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +#define CHUNK 16384 + +/* Compress from file source to file dest until EOF on source. + def() returns Z_OK on success, Z_MEM_ERROR if memory could not be + allocated for processing, Z_STREAM_ERROR if an invalid compression + level is supplied, Z_VERSION_ERROR if the version of zlib.h and the + version of the library linked do not match, or Z_ERRNO if there is + an error reading or writing the files. */ +int def(FILE *source, FILE *dest, int level) +{ + int ret, flush; + unsigned have; + z_stream strm; + unsigned char in[CHUNK]; + unsigned char out[CHUNK]; + + /* allocate deflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + ret = deflateInit(&strm, level); + if (ret != Z_OK) + return ret; + + /* compress until end of file */ + do { + strm.avail_in = fread(in, 1, CHUNK, source); + if (ferror(source)) { + (void)deflateEnd(&strm); + return Z_ERRNO; + } + flush = feof(source) ? Z_FINISH : Z_NO_FLUSH; + strm.next_in = in; + + /* run deflate() on input until output buffer not full, finish + compression if all of source has been read in */ + do { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = deflate(&strm, flush); /* no bad return value */ + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + have = CHUNK - strm.avail_out; + if (fwrite(out, 1, have, dest) != have || ferror(dest)) { + (void)deflateEnd(&strm); + return Z_ERRNO; + } + } while (strm.avail_out == 0); + assert(strm.avail_in == 0); /* all input will be used */ + + /* done when last data in file processed */ + } while (flush != Z_FINISH); + assert(ret == Z_STREAM_END); /* stream will be complete */ + + /* clean up and return */ + (void)deflateEnd(&strm); + return Z_OK; +} + +/* Decompress from file source to file dest until stream ends or EOF. + inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be + allocated for processing, Z_DATA_ERROR if the deflate data is + invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and + the version of the library linked do not match, or Z_ERRNO if there + is an error reading or writing the files. */ +int inf(FILE *source, FILE *dest) +{ + int ret; + unsigned have; + z_stream strm; + unsigned char in[CHUNK]; + unsigned char out[CHUNK]; + + /* allocate inflate state */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); + if (ret != Z_OK) + return ret; + + /* decompress until deflate stream ends or end of file */ + do { + strm.avail_in = fread(in, 1, CHUNK, source); + if (ferror(source)) { + (void)inflateEnd(&strm); + return Z_ERRNO; + } + if (strm.avail_in == 0) + break; + strm.next_in = in; + + /* run inflate() on input until output buffer not full */ + do { + strm.avail_out = CHUNK; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); + assert(ret != Z_STREAM_ERROR); /* state not clobbered */ + switch (ret) { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; /* and fall through */ + case Z_DATA_ERROR: + case Z_MEM_ERROR: + (void)inflateEnd(&strm); + return ret; + } + have = CHUNK - strm.avail_out; + if (fwrite(out, 1, have, dest) != have || ferror(dest)) { + (void)inflateEnd(&strm); + return Z_ERRNO; + } + } while (strm.avail_out == 0); + + /* done when inflate() says it's done */ + } while (ret != Z_STREAM_END); + + /* clean up and return */ + (void)inflateEnd(&strm); + return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; +} + +/* report a zlib or i/o error */ +void zerr(int ret) +{ + fputs("zpipe: ", stderr); + switch (ret) { + case Z_ERRNO: + if (ferror(stdin)) + fputs("error reading stdin\n", stderr); + if (ferror(stdout)) + fputs("error writing stdout\n", stderr); + break; + case Z_STREAM_ERROR: + fputs("invalid compression level\n", stderr); + break; + case Z_DATA_ERROR: + fputs("invalid or incomplete deflate data\n", stderr); + break; + case Z_MEM_ERROR: + fputs("out of memory\n", stderr); + break; + case Z_VERSION_ERROR: + fputs("zlib version mismatch!\n", stderr); + } +} + +/* compress or decompress from stdin to stdout */ +int main(int argc, char **argv) +{ + int ret; + + /* avoid end-of-line conversions */ + SET_BINARY_MODE(stdin); + SET_BINARY_MODE(stdout); + + /* do compression if no arguments */ + if (argc == 1) { + ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION); + if (ret != Z_OK) + zerr(ret); + return ret; + } + + /* do decompression if -d specified */ + else if (argc == 2 && strcmp(argv[1], "-d") == 0) { + ret = inf(stdin, stdout); + if (ret != Z_OK) + zerr(ret); + return ret; + } + + /* otherwise, report usage */ + else { + fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr); + return 1; + } +} diff --git a/zlib-1.2.11/examples/zran.c b/zlib-1.2.11/examples/zran.c new file mode 100644 index 00000000..4fec6594 --- /dev/null +++ b/zlib-1.2.11/examples/zran.c @@ -0,0 +1,409 @@ +/* zran.c -- example of zlib/gzip stream indexing and random access + * Copyright (C) 2005, 2012 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + Version 1.1 29 Sep 2012 Mark Adler */ + +/* Version History: + 1.0 29 May 2005 First version + 1.1 29 Sep 2012 Fix memory reallocation error + */ + +/* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary() + for random access of a compressed file. A file containing a zlib or gzip + stream is provided on the command line. The compressed stream is decoded in + its entirety, and an index built with access points about every SPAN bytes + in the uncompressed output. The compressed file is left open, and can then + be read randomly, having to decompress on the average SPAN/2 uncompressed + bytes before getting to the desired block of data. + + An access point can be created at the start of any deflate block, by saving + the starting file offset and bit of that block, and the 32K bytes of + uncompressed data that precede that block. Also the uncompressed offset of + that block is saved to provide a referece for locating a desired starting + point in the uncompressed stream. build_index() works by decompressing the + input zlib or gzip stream a block at a time, and at the end of each block + deciding if enough uncompressed data has gone by to justify the creation of + a new access point. If so, that point is saved in a data structure that + grows as needed to accommodate the points. + + To use the index, an offset in the uncompressed data is provided, for which + the latest access point at or preceding that offset is located in the index. + The input file is positioned to the specified location in the index, and if + necessary the first few bits of the compressed data is read from the file. + inflate is initialized with those bits and the 32K of uncompressed data, and + the decompression then proceeds until the desired offset in the file is + reached. Then the decompression continues to read the desired uncompressed + data from the file. + + Another approach would be to generate the index on demand. In that case, + requests for random access reads from the compressed data would try to use + the index, but if a read far enough past the end of the index is required, + then further index entries would be generated and added. + + There is some fair bit of overhead to starting inflation for the random + access, mainly copying the 32K byte dictionary. So if small pieces of the + file are being accessed, it would make sense to implement a cache to hold + some lookahead and avoid many calls to extract() for small lengths. + + Another way to build an index would be to use inflateCopy(). That would + not be constrained to have access points at block boundaries, but requires + more memory per access point, and also cannot be saved to file due to the + use of pointers in the state. The approach here allows for storage of the + index in a file. + */ + +#include +#include +#include +#include "zlib.h" + +#define local static + +#define SPAN 1048576L /* desired distance between access points */ +#define WINSIZE 32768U /* sliding window size */ +#define CHUNK 16384 /* file input buffer size */ + +/* access point entry */ +struct point { + off_t out; /* corresponding offset in uncompressed data */ + off_t in; /* offset in input file of first full byte */ + int bits; /* number of bits (1-7) from byte at in - 1, or 0 */ + unsigned char window[WINSIZE]; /* preceding 32K of uncompressed data */ +}; + +/* access point list */ +struct access { + int have; /* number of list entries filled in */ + int size; /* number of list entries allocated */ + struct point *list; /* allocated list */ +}; + +/* Deallocate an index built by build_index() */ +local void free_index(struct access *index) +{ + if (index != NULL) { + free(index->list); + free(index); + } +} + +/* Add an entry to the access point list. If out of memory, deallocate the + existing list and return NULL. */ +local struct access *addpoint(struct access *index, int bits, + off_t in, off_t out, unsigned left, unsigned char *window) +{ + struct point *next; + + /* if list is empty, create it (start with eight points) */ + if (index == NULL) { + index = malloc(sizeof(struct access)); + if (index == NULL) return NULL; + index->list = malloc(sizeof(struct point) << 3); + if (index->list == NULL) { + free(index); + return NULL; + } + index->size = 8; + index->have = 0; + } + + /* if list is full, make it bigger */ + else if (index->have == index->size) { + index->size <<= 1; + next = realloc(index->list, sizeof(struct point) * index->size); + if (next == NULL) { + free_index(index); + return NULL; + } + index->list = next; + } + + /* fill in entry and increment how many we have */ + next = index->list + index->have; + next->bits = bits; + next->in = in; + next->out = out; + if (left) + memcpy(next->window, window + WINSIZE - left, left); + if (left < WINSIZE) + memcpy(next->window + left, window, WINSIZE - left); + index->have++; + + /* return list, possibly reallocated */ + return index; +} + +/* Make one entire pass through the compressed stream and build an index, with + access points about every span bytes of uncompressed output -- span is + chosen to balance the speed of random access against the memory requirements + of the list, about 32K bytes per access point. Note that data after the end + of the first zlib or gzip stream in the file is ignored. build_index() + returns the number of access points on success (>= 1), Z_MEM_ERROR for out + of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a + file read error. On success, *built points to the resulting index. */ +local int build_index(FILE *in, off_t span, struct access **built) +{ + int ret; + off_t totin, totout; /* our own total counters to avoid 4GB limit */ + off_t last; /* totout value of last access point */ + struct access *index; /* access points being generated */ + z_stream strm; + unsigned char input[CHUNK]; + unsigned char window[WINSIZE]; + + /* initialize inflate */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, 47); /* automatic zlib or gzip decoding */ + if (ret != Z_OK) + return ret; + + /* inflate the input, maintain a sliding window, and build an index -- this + also validates the integrity of the compressed data using the check + information at the end of the gzip or zlib stream */ + totin = totout = last = 0; + index = NULL; /* will be allocated by first addpoint() */ + strm.avail_out = 0; + do { + /* get some compressed data from input file */ + strm.avail_in = fread(input, 1, CHUNK, in); + if (ferror(in)) { + ret = Z_ERRNO; + goto build_index_error; + } + if (strm.avail_in == 0) { + ret = Z_DATA_ERROR; + goto build_index_error; + } + strm.next_in = input; + + /* process all of that, or until end of stream */ + do { + /* reset sliding window if necessary */ + if (strm.avail_out == 0) { + strm.avail_out = WINSIZE; + strm.next_out = window; + } + + /* inflate until out of input, output, or at end of block -- + update the total input and output counters */ + totin += strm.avail_in; + totout += strm.avail_out; + ret = inflate(&strm, Z_BLOCK); /* return at end of block */ + totin -= strm.avail_in; + totout -= strm.avail_out; + if (ret == Z_NEED_DICT) + ret = Z_DATA_ERROR; + if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) + goto build_index_error; + if (ret == Z_STREAM_END) + break; + + /* if at end of block, consider adding an index entry (note that if + data_type indicates an end-of-block, then all of the + uncompressed data from that block has been delivered, and none + of the compressed data after that block has been consumed, + except for up to seven bits) -- the totout == 0 provides an + entry point after the zlib or gzip header, and assures that the + index always has at least one access point; we avoid creating an + access point after the last block by checking bit 6 of data_type + */ + if ((strm.data_type & 128) && !(strm.data_type & 64) && + (totout == 0 || totout - last > span)) { + index = addpoint(index, strm.data_type & 7, totin, + totout, strm.avail_out, window); + if (index == NULL) { + ret = Z_MEM_ERROR; + goto build_index_error; + } + last = totout; + } + } while (strm.avail_in != 0); + } while (ret != Z_STREAM_END); + + /* clean up and return index (release unused entries in list) */ + (void)inflateEnd(&strm); + index->list = realloc(index->list, sizeof(struct point) * index->have); + index->size = index->have; + *built = index; + return index->size; + + /* return error */ + build_index_error: + (void)inflateEnd(&strm); + if (index != NULL) + free_index(index); + return ret; +} + +/* Use the index to read len bytes from offset into buf, return bytes read or + negative for error (Z_DATA_ERROR or Z_MEM_ERROR). If data is requested past + the end of the uncompressed data, then extract() will return a value less + than len, indicating how much as actually read into buf. This function + should not return a data error unless the file was modified since the index + was generated. extract() may also return Z_ERRNO if there is an error on + reading or seeking the input file. */ +local int extract(FILE *in, struct access *index, off_t offset, + unsigned char *buf, int len) +{ + int ret, skip; + z_stream strm; + struct point *here; + unsigned char input[CHUNK]; + unsigned char discard[WINSIZE]; + + /* proceed only if something reasonable to do */ + if (len < 0) + return 0; + + /* find where in stream to start */ + here = index->list; + ret = index->have; + while (--ret && here[1].out <= offset) + here++; + + /* initialize file and inflate state to start there */ + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, -15); /* raw inflate */ + if (ret != Z_OK) + return ret; + ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET); + if (ret == -1) + goto extract_ret; + if (here->bits) { + ret = getc(in); + if (ret == -1) { + ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR; + goto extract_ret; + } + (void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits)); + } + (void)inflateSetDictionary(&strm, here->window, WINSIZE); + + /* skip uncompressed bytes until offset reached, then satisfy request */ + offset -= here->out; + strm.avail_in = 0; + skip = 1; /* while skipping to offset */ + do { + /* define where to put uncompressed data, and how much */ + if (offset == 0 && skip) { /* at offset now */ + strm.avail_out = len; + strm.next_out = buf; + skip = 0; /* only do this once */ + } + if (offset > WINSIZE) { /* skip WINSIZE bytes */ + strm.avail_out = WINSIZE; + strm.next_out = discard; + offset -= WINSIZE; + } + else if (offset != 0) { /* last skip */ + strm.avail_out = (unsigned)offset; + strm.next_out = discard; + offset = 0; + } + + /* uncompress until avail_out filled, or end of stream */ + do { + if (strm.avail_in == 0) { + strm.avail_in = fread(input, 1, CHUNK, in); + if (ferror(in)) { + ret = Z_ERRNO; + goto extract_ret; + } + if (strm.avail_in == 0) { + ret = Z_DATA_ERROR; + goto extract_ret; + } + strm.next_in = input; + } + ret = inflate(&strm, Z_NO_FLUSH); /* normal inflate */ + if (ret == Z_NEED_DICT) + ret = Z_DATA_ERROR; + if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR) + goto extract_ret; + if (ret == Z_STREAM_END) + break; + } while (strm.avail_out != 0); + + /* if reach end of stream, then don't keep trying to get more */ + if (ret == Z_STREAM_END) + break; + + /* do until offset reached and requested data read, or stream ends */ + } while (skip); + + /* compute number of uncompressed bytes read after offset */ + ret = skip ? 0 : len - strm.avail_out; + + /* clean up and return bytes read or error */ + extract_ret: + (void)inflateEnd(&strm); + return ret; +} + +/* Demonstrate the use of build_index() and extract() by processing the file + provided on the command line, and the extracting 16K from about 2/3rds of + the way through the uncompressed output, and writing that to stdout. */ +int main(int argc, char **argv) +{ + int len; + off_t offset; + FILE *in; + struct access *index = NULL; + unsigned char buf[CHUNK]; + + /* open input file */ + if (argc != 2) { + fprintf(stderr, "usage: zran file.gz\n"); + return 1; + } + in = fopen(argv[1], "rb"); + if (in == NULL) { + fprintf(stderr, "zran: could not open %s for reading\n", argv[1]); + return 1; + } + + /* build index */ + len = build_index(in, SPAN, &index); + if (len < 0) { + fclose(in); + switch (len) { + case Z_MEM_ERROR: + fprintf(stderr, "zran: out of memory\n"); + break; + case Z_DATA_ERROR: + fprintf(stderr, "zran: compressed data error in %s\n", argv[1]); + break; + case Z_ERRNO: + fprintf(stderr, "zran: read error on %s\n", argv[1]); + break; + default: + fprintf(stderr, "zran: error %d while building index\n", len); + } + return 1; + } + fprintf(stderr, "zran: built index with %d access points\n", len); + + /* use index by reading some bytes from an arbitrary offset */ + offset = (index->list[index->have - 1].out << 1) / 3; + len = extract(in, index, offset, buf, CHUNK); + if (len < 0) + fprintf(stderr, "zran: extraction failed: %s error\n", + len == Z_MEM_ERROR ? "out of memory" : "input corrupted"); + else { + fwrite(buf, 1, len, stdout); + fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset); + } + + /* clean up and exit */ + free_index(index); + fclose(in); + return 0; +} diff --git a/zlib-1.2.11/gzclose.c b/zlib-1.2.11/gzclose.c new file mode 100644 index 00000000..caeb99a3 --- /dev/null +++ b/zlib-1.2.11/gzclose.c @@ -0,0 +1,25 @@ +/* gzclose.c -- zlib gzclose() function + * Copyright (C) 2004, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* gzclose() is in a separate file so that it is linked in only if it is used. + That way the other gzclose functions can be used instead to avoid linking in + unneeded compression or decompression routines. */ +int ZEXPORT gzclose(file) + gzFile file; +{ +#ifndef NO_GZCOMPRESS + gz_statep state; + + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file); +#else + return gzclose_r(file); +#endif +} diff --git a/zlib-1.2.11/gzguts.h b/zlib-1.2.11/gzguts.h new file mode 100644 index 00000000..990a4d25 --- /dev/null +++ b/zlib-1.2.11/gzguts.h @@ -0,0 +1,218 @@ +/* gzguts.h -- zlib internal header definitions for gz* operations + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifdef _LARGEFILE64_SOURCE +# ifndef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# endif +# ifdef _FILE_OFFSET_BITS +# undef _FILE_OFFSET_BITS +# endif +#endif + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include +#include "zlib.h" +#ifdef STDC +# include +# include +# include +#endif + +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE +#endif +#include + +#ifdef _WIN32 +# include +#endif + +#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) +# include +#endif + +#if defined(_WIN32) || defined(__CYGWIN__) +# define WIDECHAR +#endif + +#ifdef WINAPI_FAMILY +# define open _open +# define read _read +# define write _write +# define close _close +#endif + +#ifdef NO_DEFLATE /* for compatibility with old definition */ +# define NO_GZCOMPRESS +#endif + +#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(__CYGWIN__) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410) +# ifndef HAVE_VSNPRINTF +# define HAVE_VSNPRINTF +# endif +#endif + +#ifndef HAVE_VSNPRINTF +# ifdef MSDOS +/* vsnprintf may exist on some MS-DOS compilers (DJGPP?), + but for now we just assume it doesn't. */ +# define NO_vsnprintf +# endif +# ifdef __TURBOC__ +# define NO_vsnprintf +# endif +# ifdef WIN32 +/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ +# if !defined(vsnprintf) && !defined(NO_vsnprintf) +# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 ) +# define vsnprintf _vsnprintf +# endif +# endif +# endif +# ifdef __SASC +# define NO_vsnprintf +# endif +# ifdef VMS +# define NO_vsnprintf +# endif +# ifdef __OS400__ +# define NO_vsnprintf +# endif +# ifdef __MVS__ +# define NO_vsnprintf +# endif +#endif + +/* unlike snprintf (which is required in C99), _snprintf does not guarantee + null termination of the result -- however this is only used in gzlib.c where + the result is assured to fit in the space provided */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +# define snprintf _snprintf +#endif + +#ifndef local +# define local static +#endif +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ + +/* gz* functions always use library allocation functions */ +#ifndef STDC + extern voidp malloc OF((uInt size)); + extern void free OF((voidpf ptr)); +#endif + +/* get errno and strerror definition */ +#if defined UNDER_CE +# include +# define zstrerror() gz_strwinerror((DWORD)GetLastError()) +#else +# ifndef NO_STRERROR +# include +# define zstrerror() strerror(errno) +# else +# define zstrerror() "stdio error (consult errno)" +# endif +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); +#endif + +/* default memLevel */ +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif + +/* default i/o buffer size -- double this for output when reading (this and + twice this must be able to fit in an unsigned type) */ +#define GZBUFSIZE 8192 + +/* gzip modes, also provide a little integrity check on the passed structure */ +#define GZ_NONE 0 +#define GZ_READ 7247 +#define GZ_WRITE 31153 +#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */ + +/* values for gz_state how */ +#define LOOK 0 /* look for a gzip header */ +#define COPY 1 /* copy input directly */ +#define GZIP 2 /* decompress a gzip stream */ + +/* internal gzip file state data structure */ +typedef struct { + /* exposed contents for gzgetc() macro */ + struct gzFile_s x; /* "x" for exposed */ + /* x.have: number of bytes available at x.next */ + /* x.next: next output data to deliver or write */ + /* x.pos: current position in uncompressed data */ + /* used for both reading and writing */ + int mode; /* see gzip modes above */ + int fd; /* file descriptor */ + char *path; /* path or fd for error messages */ + unsigned size; /* buffer size, zero if not allocated yet */ + unsigned want; /* requested buffer size, default is GZBUFSIZE */ + unsigned char *in; /* input buffer (double-sized when writing) */ + unsigned char *out; /* output buffer (double-sized when reading) */ + int direct; /* 0 if processing gzip, 1 if transparent */ + /* just for reading */ + int how; /* 0: get header, 1: copy, 2: decompress */ + z_off64_t start; /* where the gzip data started, for rewinding */ + int eof; /* true if end of input file reached */ + int past; /* true if read requested past end */ + /* just for writing */ + int level; /* compression level */ + int strategy; /* compression strategy */ + /* seek request */ + z_off64_t skip; /* amount to skip (already rewound if backwards) */ + int seek; /* true if seek request pending */ + /* error information */ + int err; /* error code */ + char *msg; /* error message */ + /* zlib inflate or deflate stream */ + z_stream strm; /* stream structure in-place (not a pointer) */ +} gz_state; +typedef gz_state FAR *gz_statep; + +/* shared functions */ +void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); +#if defined UNDER_CE +char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); +#endif + +/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t + value -- needed when comparing unsigned to z_off64_t, which is signed + (possible z_off64_t types off_t, off64_t, and long are all signed) */ +#ifdef INT_MAX +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) +#else +unsigned ZLIB_INTERNAL gz_intmax OF((void)); +# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) +#endif diff --git a/zlib-1.2.11/gzlib.c b/zlib-1.2.11/gzlib.c new file mode 100644 index 00000000..4105e6af --- /dev/null +++ b/zlib-1.2.11/gzlib.c @@ -0,0 +1,637 @@ +/* gzlib.c -- zlib functions common to reading and writing gzip files + * Copyright (C) 2004-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__) +# define LSEEK _lseeki64 +#else +#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 +# define LSEEK lseek64 +#else +# define LSEEK lseek +#endif +#endif + +/* Local functions */ +local void gz_reset OF((gz_statep)); +local gzFile gz_open OF((const void *, int, const char *)); + +#if defined UNDER_CE + +/* Map the Windows error number in ERROR to a locale-dependent error message + string and return a pointer to it. Typically, the values for ERROR come + from GetLastError. + + The string pointed to shall not be modified by the application, but may be + overwritten by a subsequent call to gz_strwinerror + + The gz_strwinerror function does not change the current setting of + GetLastError. */ +char ZLIB_INTERNAL *gz_strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +#endif /* UNDER_CE */ + +/* Reset gzip file state */ +local void gz_reset(state) + gz_statep state; +{ + state->x.have = 0; /* no output data available */ + if (state->mode == GZ_READ) { /* for reading ... */ + state->eof = 0; /* not at end of file */ + state->past = 0; /* have not read past end yet */ + state->how = LOOK; /* look for gzip header */ + } + state->seek = 0; /* no seek request pending */ + gz_error(state, Z_OK, NULL); /* clear error */ + state->x.pos = 0; /* no uncompressed data yet */ + state->strm.avail_in = 0; /* no input data yet */ +} + +/* Open a gzip file either by name or file descriptor. */ +local gzFile gz_open(path, fd, mode) + const void *path; + int fd; + const char *mode; +{ + gz_statep state; + z_size_t len; + int oflag; +#ifdef O_CLOEXEC + int cloexec = 0; +#endif +#ifdef O_EXCL + int exclusive = 0; +#endif + + /* check input */ + if (path == NULL) + return NULL; + + /* allocate gzFile structure to return */ + state = (gz_statep)malloc(sizeof(gz_state)); + if (state == NULL) + return NULL; + state->size = 0; /* no buffers allocated yet */ + state->want = GZBUFSIZE; /* requested buffer size */ + state->msg = NULL; /* no error message yet */ + + /* interpret mode */ + state->mode = GZ_NONE; + state->level = Z_DEFAULT_COMPRESSION; + state->strategy = Z_DEFAULT_STRATEGY; + state->direct = 0; + while (*mode) { + if (*mode >= '0' && *mode <= '9') + state->level = *mode - '0'; + else + switch (*mode) { + case 'r': + state->mode = GZ_READ; + break; +#ifndef NO_GZCOMPRESS + case 'w': + state->mode = GZ_WRITE; + break; + case 'a': + state->mode = GZ_APPEND; + break; +#endif + case '+': /* can't read and write at the same time */ + free(state); + return NULL; + case 'b': /* ignore -- will request binary anyway */ + break; +#ifdef O_CLOEXEC + case 'e': + cloexec = 1; + break; +#endif +#ifdef O_EXCL + case 'x': + exclusive = 1; + break; +#endif + case 'f': + state->strategy = Z_FILTERED; + break; + case 'h': + state->strategy = Z_HUFFMAN_ONLY; + break; + case 'R': + state->strategy = Z_RLE; + break; + case 'F': + state->strategy = Z_FIXED; + break; + case 'T': + state->direct = 1; + break; + default: /* could consider as an error, but just ignore */ + ; + } + mode++; + } + + /* must provide an "r", "w", or "a" */ + if (state->mode == GZ_NONE) { + free(state); + return NULL; + } + + /* can't force transparent read */ + if (state->mode == GZ_READ) { + if (state->direct) { + free(state); + return NULL; + } + state->direct = 1; /* for empty file */ + } + + /* save the path name for error messages */ +#ifdef WIDECHAR + if (fd == -2) { + len = wcstombs(NULL, path, 0); + if (len == (z_size_t)-1) + len = 0; + } + else +#endif + len = strlen((const char *)path); + state->path = (char *)malloc(len + 1); + if (state->path == NULL) { + free(state); + return NULL; + } +#ifdef WIDECHAR + if (fd == -2) + if (len) + wcstombs(state->path, path, len + 1); + else + *(state->path) = 0; + else +#endif +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(state->path, len + 1, "%s", (const char *)path); +#else + strcpy(state->path, path); +#endif + + /* compute the flags for open() */ + oflag = +#ifdef O_LARGEFILE + O_LARGEFILE | +#endif +#ifdef O_BINARY + O_BINARY | +#endif +#ifdef O_CLOEXEC + (cloexec ? O_CLOEXEC : 0) | +#endif + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | +#ifdef O_EXCL + (exclusive ? O_EXCL : 0) | +#endif + (state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))); + + /* open the file with the appropriate flags (or just use fd) */ + state->fd = fd > -1 ? fd : ( +#ifdef WIDECHAR + fd == -2 ? _wopen(path, oflag, 0666) : +#endif + open((const char *)path, oflag, 0666)); + if (state->fd == -1) { + free(state->path); + free(state); + return NULL; + } + if (state->mode == GZ_APPEND) { + LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ + state->mode = GZ_WRITE; /* simplify later checks */ + } + + /* save the current position for rewinding (only if reading) */ + if (state->mode == GZ_READ) { + state->start = LSEEK(state->fd, 0, SEEK_CUR); + if (state->start == -1) state->start = 0; + } + + /* initialize stream */ + gz_reset(state); + + /* return stream */ + return (gzFile)state; +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzopen64(path, mode) + const char *path; + const char *mode; +{ + return gz_open(path, -1, mode); +} + +/* -- see zlib.h -- */ +gzFile ZEXPORT gzdopen(fd, mode) + int fd; + const char *mode; +{ + char *path; /* identifier for error messages */ + gzFile gz; + + if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) + return NULL; +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(path, 7 + 3 * sizeof(int), "", fd); +#else + sprintf(path, "", fd); /* for debugging */ +#endif + gz = gz_open(path, fd, mode); + free(path); + return gz; +} + +/* -- see zlib.h -- */ +#ifdef WIDECHAR +gzFile ZEXPORT gzopen_w(path, mode) + const wchar_t *path; + const char *mode; +{ + return gz_open(path, -2, mode); +} +#endif + +/* -- see zlib.h -- */ +int ZEXPORT gzbuffer(file, size) + gzFile file; + unsigned size; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* make sure we haven't already allocated memory */ + if (state->size != 0) + return -1; + + /* check and set requested size */ + if ((size << 1) < size) + return -1; /* need to be able to double it */ + if (size < 2) + size = 2; /* need two bytes to check magic header */ + state->want = size; + return 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzrewind(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* back up and start over */ + if (LSEEK(state->fd, state->start, SEEK_SET) == -1) + return -1; + gz_reset(state); + return 0; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzseek64(file, offset, whence) + gzFile file; + z_off64_t offset; + int whence; +{ + unsigned n; + z_off64_t ret; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* check that there's no error */ + if (state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + + /* can only seek from start or relative to current position */ + if (whence != SEEK_SET && whence != SEEK_CUR) + return -1; + + /* normalize offset to a SEEK_CUR specification */ + if (whence == SEEK_SET) + offset -= state->x.pos; + else if (state->seek) + offset += state->skip; + state->seek = 0; + + /* if within raw area while reading, just go there */ + if (state->mode == GZ_READ && state->how == COPY && + state->x.pos + offset >= 0) { + ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); + if (ret == -1) + return -1; + state->x.have = 0; + state->eof = 0; + state->past = 0; + state->seek = 0; + gz_error(state, Z_OK, NULL); + state->strm.avail_in = 0; + state->x.pos += offset; + return state->x.pos; + } + + /* calculate skip amount, rewinding if needed for back seek when reading */ + if (offset < 0) { + if (state->mode != GZ_READ) /* writing -- can't go backwards */ + return -1; + offset += state->x.pos; + if (offset < 0) /* before start of file! */ + return -1; + if (gzrewind(file) == -1) /* rewind, then skip to offset */ + return -1; + } + + /* if reading, skip what's in output buffer (one less gzgetc() check) */ + if (state->mode == GZ_READ) { + n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? + (unsigned)offset : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; + offset -= n; + } + + /* request skip (if not zero) */ + if (offset) { + state->seek = 1; + state->skip = offset; + } + return state->x.pos + offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzseek(file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + z_off64_t ret; + + ret = gzseek64(file, (z_off64_t)offset, whence); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gztell64(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* return position */ + return state->x.pos + (state->seek ? state->skip : 0); +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gztell(file) + gzFile file; +{ + z_off64_t ret; + + ret = gztell64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +z_off64_t ZEXPORT gzoffset64(file) + gzFile file; +{ + z_off64_t offset; + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return -1; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return -1; + + /* compute and return effective offset in file */ + offset = LSEEK(state->fd, 0, SEEK_CUR); + if (offset == -1) + return -1; + if (state->mode == GZ_READ) /* reading */ + offset -= state->strm.avail_in; /* don't count buffered input */ + return offset; +} + +/* -- see zlib.h -- */ +z_off_t ZEXPORT gzoffset(file) + gzFile file; +{ + z_off64_t ret; + + ret = gzoffset64(file); + return ret == (z_off_t)ret ? (z_off_t)ret : -1; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzeof(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return 0; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return 0; + + /* return end-of-file state */ + return state->mode == GZ_READ ? state->past : 0; +} + +/* -- see zlib.h -- */ +const char * ZEXPORT gzerror(file, errnum) + gzFile file; + int *errnum; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return NULL; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return NULL; + + /* return error information */ + if (errnum != NULL) + *errnum = state->err; + return state->err == Z_MEM_ERROR ? "out of memory" : + (state->msg == NULL ? "" : state->msg); +} + +/* -- see zlib.h -- */ +void ZEXPORT gzclearerr(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure and check integrity */ + if (file == NULL) + return; + state = (gz_statep)file; + if (state->mode != GZ_READ && state->mode != GZ_WRITE) + return; + + /* clear error and end-of-file */ + if (state->mode == GZ_READ) { + state->eof = 0; + state->past = 0; + } + gz_error(state, Z_OK, NULL); +} + +/* Create an error message in allocated memory and set state->err and + state->msg accordingly. Free any previous error message already there. Do + not try to free or allocate space if the error is Z_MEM_ERROR (out of + memory). Simply save the error message as a static string. If there is an + allocation failure constructing the error message, then convert the error to + out of memory. */ +void ZLIB_INTERNAL gz_error(state, err, msg) + gz_statep state; + int err; + const char *msg; +{ + /* free previously allocated message and clear */ + if (state->msg != NULL) { + if (state->err != Z_MEM_ERROR) + free(state->msg); + state->msg = NULL; + } + + /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */ + if (err != Z_OK && err != Z_BUF_ERROR) + state->x.have = 0; + + /* set error code, and if no message, then done */ + state->err = err; + if (msg == NULL) + return; + + /* for an out of memory error, return literal string when requested */ + if (err == Z_MEM_ERROR) + return; + + /* construct error message with path */ + if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == + NULL) { + state->err = Z_MEM_ERROR; + return; + } +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, + "%s%s%s", state->path, ": ", msg); +#else + strcpy(state->msg, state->path); + strcat(state->msg, ": "); + strcat(state->msg, msg); +#endif +} + +#ifndef INT_MAX +/* portably return maximum value for an int (when limits.h presumed not + available) -- we need to do this to cover cases where 2's complement not + used, since C standard permits 1's complement and sign-bit representations, + otherwise we could just use ((unsigned)-1) >> 1 */ +unsigned ZLIB_INTERNAL gz_intmax() +{ + unsigned p, q; + + p = 1; + do { + q = p; + p <<= 1; + p++; + } while (p > q); + return q >> 1; +} +#endif diff --git a/zlib-1.2.11/gzread.c b/zlib-1.2.11/gzread.c new file mode 100644 index 00000000..956b91ea --- /dev/null +++ b/zlib-1.2.11/gzread.c @@ -0,0 +1,654 @@ +/* gzread.c -- zlib functions for reading gzip files + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *)); +local int gz_avail OF((gz_statep)); +local int gz_look OF((gz_statep)); +local int gz_decomp OF((gz_statep)); +local int gz_fetch OF((gz_statep)); +local int gz_skip OF((gz_statep, z_off64_t)); +local z_size_t gz_read OF((gz_statep, voidp, z_size_t)); + +/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from + state->fd, and update state->eof, state->err, and state->msg as appropriate. + This function needs to loop on read(), since read() is not guaranteed to + read the number of bytes requested, depending on the type of descriptor. */ +local int gz_load(state, buf, len, have) + gz_statep state; + unsigned char *buf; + unsigned len; + unsigned *have; +{ + int ret; + unsigned get, max = ((unsigned)-1 >> 2) + 1; + + *have = 0; + do { + get = len - *have; + if (get > max) + get = max; + ret = read(state->fd, buf + *have, get); + if (ret <= 0) + break; + *have += (unsigned)ret; + } while (*have < len); + if (ret < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + if (ret == 0) + state->eof = 1; + return 0; +} + +/* Load up input buffer and set eof flag if last data loaded -- return -1 on + error, 0 otherwise. Note that the eof flag is set when the end of the input + file is reached, even though there may be unused data in the buffer. Once + that data has been used, no more attempts will be made to read the file. + If strm->avail_in != 0, then the current data is moved to the beginning of + the input buffer, and then the remainder of the buffer is loaded with the + available data from the input file. */ +local int gz_avail(state) + gz_statep state; +{ + unsigned got; + z_streamp strm = &(state->strm); + + if (state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + if (state->eof == 0) { + if (strm->avail_in) { /* copy what's there to the start */ + unsigned char *p = state->in; + unsigned const char *q = strm->next_in; + unsigned n = strm->avail_in; + do { + *p++ = *q++; + } while (--n); + } + if (gz_load(state, state->in + strm->avail_in, + state->size - strm->avail_in, &got) == -1) + return -1; + strm->avail_in += got; + strm->next_in = state->in; + } + return 0; +} + +/* Look for gzip header, set up for inflate or copy. state->x.have must be 0. + If this is the first time in, allocate required memory. state->how will be + left unchanged if there is no more input data available, will be set to COPY + if there is no gzip header and direct copying will be performed, or it will + be set to GZIP for decompression. If direct copying, then leftover input + data from the input buffer will be copied to the output buffer. In that + case, all further file reads will be directly to either the output buffer or + a user buffer. If decompressing, the inflate state will be initialized. + gz_look() will return 0 on success or -1 on failure. */ +local int gz_look(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + /* allocate read buffers and inflate memory */ + if (state->size == 0) { + /* allocate buffers */ + state->in = (unsigned char *)malloc(state->want); + state->out = (unsigned char *)malloc(state->want << 1); + if (state->in == NULL || state->out == NULL) { + free(state->out); + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + state->size = state->want; + + /* allocate inflate memory */ + state->strm.zalloc = Z_NULL; + state->strm.zfree = Z_NULL; + state->strm.opaque = Z_NULL; + state->strm.avail_in = 0; + state->strm.next_in = Z_NULL; + if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */ + free(state->out); + free(state->in); + state->size = 0; + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + } + + /* get at least the magic bytes in the input buffer */ + if (strm->avail_in < 2) { + if (gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) + return 0; + } + + /* look for gzip magic bytes -- if there, do gzip decoding (note: there is + a logical dilemma here when considering the case of a partially written + gzip file, to wit, if a single 31 byte is written, then we cannot tell + whether this is a single-byte file, or just a partially written gzip + file -- for here we assume that if a gzip file is being written, then + the header will be written in a single operation, so that reading a + single byte is sufficient indication that it is not a gzip file) */ + if (strm->avail_in > 1 && + strm->next_in[0] == 31 && strm->next_in[1] == 139) { + inflateReset(strm); + state->how = GZIP; + state->direct = 0; + return 0; + } + + /* no gzip header -- if we were decoding gzip before, then this is trailing + garbage. Ignore the trailing garbage and finish. */ + if (state->direct == 0) { + strm->avail_in = 0; + state->eof = 1; + state->x.have = 0; + return 0; + } + + /* doing raw i/o, copy any leftover input to output -- this assumes that + the output buffer is larger than the input buffer, which also assures + space for gzungetc() */ + state->x.next = state->out; + if (strm->avail_in) { + memcpy(state->x.next, strm->next_in, strm->avail_in); + state->x.have = strm->avail_in; + strm->avail_in = 0; + } + state->how = COPY; + state->direct = 1; + return 0; +} + +/* Decompress from input to the provided next_out and avail_out in the state. + On return, state->x.have and state->x.next point to the just decompressed + data. If the gzip stream completes, state->how is reset to LOOK to look for + the next gzip stream or raw data, once state->x.have is depleted. Returns 0 + on success, -1 on failure. */ +local int gz_decomp(state) + gz_statep state; +{ + int ret = Z_OK; + unsigned had; + z_streamp strm = &(state->strm); + + /* fill output buffer up to end of deflate stream */ + had = strm->avail_out; + do { + /* get more input for inflate() */ + if (strm->avail_in == 0 && gz_avail(state) == -1) + return -1; + if (strm->avail_in == 0) { + gz_error(state, Z_BUF_ERROR, "unexpected end of file"); + break; + } + + /* decompress and handle errors */ + ret = inflate(strm, Z_NO_FLUSH); + if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) { + gz_error(state, Z_STREAM_ERROR, + "internal error: inflate stream corrupt"); + return -1; + } + if (ret == Z_MEM_ERROR) { + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + if (ret == Z_DATA_ERROR) { /* deflate stream invalid */ + gz_error(state, Z_DATA_ERROR, + strm->msg == NULL ? "compressed data error" : strm->msg); + return -1; + } + } while (strm->avail_out && ret != Z_STREAM_END); + + /* update available output */ + state->x.have = had - strm->avail_out; + state->x.next = strm->next_out - state->x.have; + + /* if the gzip stream completed successfully, look for another */ + if (ret == Z_STREAM_END) + state->how = LOOK; + + /* good decompression */ + return 0; +} + +/* Fetch data and put it in the output buffer. Assumes state->x.have is 0. + Data is either copied from the input file or decompressed from the input + file depending on state->how. If state->how is LOOK, then a gzip header is + looked for to determine whether to copy or decompress. Returns -1 on error, + otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the + end of the input file has been reached and all data has been processed. */ +local int gz_fetch(state) + gz_statep state; +{ + z_streamp strm = &(state->strm); + + do { + switch(state->how) { + case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */ + if (gz_look(state) == -1) + return -1; + if (state->how == LOOK) + return 0; + break; + case COPY: /* -> COPY */ + if (gz_load(state, state->out, state->size << 1, &(state->x.have)) + == -1) + return -1; + state->x.next = state->out; + return 0; + case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */ + strm->avail_out = state->size << 1; + strm->next_out = state->out; + if (gz_decomp(state) == -1) + return -1; + } + } while (state->x.have == 0 && (!state->eof || strm->avail_in)); + return 0; +} + +/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ +local int gz_skip(state, len) + gz_statep state; + z_off64_t len; +{ + unsigned n; + + /* skip over len bytes or reach end-of-file, whichever comes first */ + while (len) + /* skip over whatever is in output buffer */ + if (state->x.have) { + n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ? + (unsigned)len : state->x.have; + state->x.have -= n; + state->x.next += n; + state->x.pos += n; + len -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && state->strm.avail_in == 0) + break; + + /* need more data to skip -- load up output buffer */ + else { + /* get more output, looking for header if required */ + if (gz_fetch(state) == -1) + return -1; + } + return 0; +} + +/* Read len bytes into buf from file, or less than len up to the end of the + input. Return the number of bytes read. If zero is returned, either the + end of file was reached, or there was an error. state->err must be + consulted in that case to determine which. */ +local z_size_t gz_read(state, buf, len) + gz_statep state; + voidp buf; + z_size_t len; +{ + z_size_t got; + unsigned n; + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return 0; + } + + /* get len bytes to buf, or less than len if at the end */ + got = 0; + do { + /* set n to the maximum amount of len that fits in an unsigned int */ + n = -1; + if (n > len) + n = len; + + /* first just try copying data from the output buffer */ + if (state->x.have) { + if (state->x.have < n) + n = state->x.have; + memcpy(buf, state->x.next, n); + state->x.next += n; + state->x.have -= n; + } + + /* output buffer empty -- return if we're at the end of the input */ + else if (state->eof && state->strm.avail_in == 0) { + state->past = 1; /* tried to read past end */ + break; + } + + /* need output data -- for small len or new stream load up our output + buffer */ + else if (state->how == LOOK || n < (state->size << 1)) { + /* get more output, looking for header if required */ + if (gz_fetch(state) == -1) + return 0; + continue; /* no progress yet -- go back to copy above */ + /* the copy above assures that we will leave with space in the + output buffer, allowing at least one gzungetc() to succeed */ + } + + /* large len -- read directly into user buffer */ + else if (state->how == COPY) { /* read directly */ + if (gz_load(state, (unsigned char *)buf, n, &n) == -1) + return 0; + } + + /* large len -- decompress directly into user buffer */ + else { /* state->how == GZIP */ + state->strm.avail_out = n; + state->strm.next_out = (unsigned char *)buf; + if (gz_decomp(state) == -1) + return 0; + n = state->x.have; + state->x.have = 0; + } + + /* update progress */ + len -= n; + buf = (char *)buf + n; + got += n; + state->x.pos += n; + } while (len); + + /* return number of bytes read into user buffer */ + return got; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzread(file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); + return -1; + } + + /* read len or fewer bytes to buf */ + len = gz_read(state, buf, len); + + /* check for an error */ + if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + + /* return the number of bytes read (this is assured to fit in an int) */ + return (int)len; +} + +/* -- see zlib.h -- */ +z_size_t ZEXPORT gzfread(buf, size, nitems, file) + voidp buf; + z_size_t size; + z_size_t nitems; + gzFile file; +{ + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return 0; + + /* compute bytes to read -- error on overflow */ + len = nitems * size; + if (size && len / size != nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + + /* read len or fewer bytes to buf, return the number of full items read */ + return len ? gz_read(state, buf, len) / size : 0; +} + +/* -- see zlib.h -- */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +#else +# undef gzgetc +#endif +int ZEXPORT gzgetc(file) + gzFile file; +{ + int ret; + unsigned char buf[1]; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* try output buffer (no need to check for skip request) */ + if (state->x.have) { + state->x.have--; + state->x.pos++; + return *(state->x.next)++; + } + + /* nothing there -- try gz_read() */ + ret = gz_read(state, buf, 1); + return ret < 1 ? -1 : buf[0]; +} + +int ZEXPORT gzgetc_(file) +gzFile file; +{ + return gzgetc(file); +} + +/* -- see zlib.h -- */ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return -1; + } + + /* can't push EOF */ + if (c < 0) + return -1; + + /* if output buffer empty, put byte at end (allows more pushing) */ + if (state->x.have == 0) { + state->x.have = 1; + state->x.next = state->out + (state->size << 1) - 1; + state->x.next[0] = (unsigned char)c; + state->x.pos--; + state->past = 0; + return c; + } + + /* if no room, give up (must have already done a gzungetc()) */ + if (state->x.have == (state->size << 1)) { + gz_error(state, Z_DATA_ERROR, "out of room to push characters"); + return -1; + } + + /* slide output data if needed and insert byte before existing data */ + if (state->x.next == state->out) { + unsigned char *src = state->out + state->x.have; + unsigned char *dest = state->out + (state->size << 1); + while (src > state->out) + *--dest = *--src; + state->x.next = dest; + } + state->x.have++; + state->x.next--; + state->x.next[0] = (unsigned char)c; + state->x.pos--; + state->past = 0; + return c; +} + +/* -- see zlib.h -- */ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + unsigned left, n; + char *str; + unsigned char *eol; + gz_statep state; + + /* check parameters and get internal structure */ + if (file == NULL || buf == NULL || len < 1) + return NULL; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return NULL; + + /* process a skip request */ + if (state->seek) { + state->seek = 0; + if (gz_skip(state, state->skip) == -1) + return NULL; + } + + /* copy output bytes up to new line or len - 1, whichever comes first -- + append a terminating zero to the string (we don't check for a zero in + the contents, let the user worry about that) */ + str = buf; + left = (unsigned)len - 1; + if (left) do { + /* assure that something is in the output buffer */ + if (state->x.have == 0 && gz_fetch(state) == -1) + return NULL; /* error */ + if (state->x.have == 0) { /* end of file */ + state->past = 1; /* read past end */ + break; /* return what we have */ + } + + /* look for end-of-line in current output buffer */ + n = state->x.have > left ? left : state->x.have; + eol = (unsigned char *)memchr(state->x.next, '\n', n); + if (eol != NULL) + n = (unsigned)(eol - state->x.next) + 1; + + /* copy through end-of-line, or remainder if not found */ + memcpy(buf, state->x.next, n); + state->x.have -= n; + state->x.next += n; + state->x.pos += n; + left -= n; + buf += n; + } while (left && eol == NULL); + + /* return terminated string, or if nothing, end of file */ + if (buf == str) + return NULL; + buf[0] = 0; + return str; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzdirect(file) + gzFile file; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* if the state is not known, but we can find out, then do so (this is + mainly for right after a gzopen() or gzdopen()) */ + if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0) + (void)gz_look(state); + + /* return 1 if transparent, 0 if processing a gzip stream */ + return state->direct; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_r(file) + gzFile file; +{ + int ret, err; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're reading */ + if (state->mode != GZ_READ) + return Z_STREAM_ERROR; + + /* free memory and close file */ + if (state->size) { + inflateEnd(&(state->strm)); + free(state->out); + free(state->in); + } + err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK; + gz_error(state, Z_OK, NULL); + free(state->path); + ret = close(state->fd); + free(state); + return ret ? Z_ERRNO : err; +} diff --git a/zlib-1.2.11/gzwrite.c b/zlib-1.2.11/gzwrite.c new file mode 100644 index 00000000..c7b5651d --- /dev/null +++ b/zlib-1.2.11/gzwrite.c @@ -0,0 +1,665 @@ +/* gzwrite.c -- zlib functions for writing gzip files + * Copyright (C) 2004-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "gzguts.h" + +/* Local functions */ +local int gz_init OF((gz_statep)); +local int gz_comp OF((gz_statep, int)); +local int gz_zero OF((gz_statep, z_off64_t)); +local z_size_t gz_write OF((gz_statep, voidpc, z_size_t)); + +/* Initialize state for writing a gzip file. Mark initialization by setting + state->size to non-zero. Return -1 on a memory allocation failure, or 0 on + success. */ +local int gz_init(state) + gz_statep state; +{ + int ret; + z_streamp strm = &(state->strm); + + /* allocate input buffer (double size for gzprintf) */ + state->in = (unsigned char *)malloc(state->want << 1); + if (state->in == NULL) { + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* only need output buffer and deflate state if compressing */ + if (!state->direct) { + /* allocate output buffer */ + state->out = (unsigned char *)malloc(state->want); + if (state->out == NULL) { + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + + /* allocate deflate memory, set up for gzip compression */ + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; + strm->opaque = Z_NULL; + ret = deflateInit2(strm, state->level, Z_DEFLATED, + MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); + if (ret != Z_OK) { + free(state->out); + free(state->in); + gz_error(state, Z_MEM_ERROR, "out of memory"); + return -1; + } + strm->next_in = NULL; + } + + /* mark state as initialized */ + state->size = state->want; + + /* initialize write buffer if compressing */ + if (!state->direct) { + strm->avail_out = state->size; + strm->next_out = state->out; + state->x.next = strm->next_out; + } + return 0; +} + +/* Compress whatever is at avail_in and next_in and write to the output file. + Return -1 if there is an error writing to the output file or if gz_init() + fails to allocate memory, otherwise 0. flush is assumed to be a valid + deflate() flush value. If flush is Z_FINISH, then the deflate() state is + reset to start a new gzip stream. If gz->direct is true, then simply write + to the output file without compressing, and ignore flush. */ +local int gz_comp(state, flush) + gz_statep state; + int flush; +{ + int ret, writ; + unsigned have, put, max = ((unsigned)-1 >> 2) + 1; + z_streamp strm = &(state->strm); + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return -1; + + /* write directly if requested */ + if (state->direct) { + while (strm->avail_in) { + put = strm->avail_in > max ? max : strm->avail_in; + writ = write(state->fd, strm->next_in, put); + if (writ < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + strm->avail_in -= (unsigned)writ; + strm->next_in += writ; + } + return 0; + } + + /* run deflate() on provided input until it produces no more output */ + ret = Z_OK; + do { + /* write out current buffer contents if full, or if flushing, but if + doing Z_FINISH then don't write until we get to Z_STREAM_END */ + if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && + (flush != Z_FINISH || ret == Z_STREAM_END))) { + while (strm->next_out > state->x.next) { + put = strm->next_out - state->x.next > (int)max ? max : + (unsigned)(strm->next_out - state->x.next); + writ = write(state->fd, state->x.next, put); + if (writ < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + state->x.next += writ; + } + if (strm->avail_out == 0) { + strm->avail_out = state->size; + strm->next_out = state->out; + state->x.next = state->out; + } + } + + /* compress */ + have = strm->avail_out; + ret = deflate(strm, flush); + if (ret == Z_STREAM_ERROR) { + gz_error(state, Z_STREAM_ERROR, + "internal error: deflate stream corrupt"); + return -1; + } + have -= strm->avail_out; + } while (have); + + /* if that completed a deflate stream, allow another to start */ + if (flush == Z_FINISH) + deflateReset(strm); + + /* all done, no errors */ + return 0; +} + +/* Compress len zeros to output. Return -1 on a write error or memory + allocation failure by gz_comp(), or 0 on success. */ +local int gz_zero(state, len) + gz_statep state; + z_off64_t len; +{ + int first; + unsigned n; + z_streamp strm = &(state->strm); + + /* consume whatever's left in the input buffer */ + if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + + /* compress len zeros (len guaranteed > 0) */ + first = 1; + while (len) { + n = GT_OFF(state->size) || (z_off64_t)state->size > len ? + (unsigned)len : state->size; + if (first) { + memset(state->in, 0, n); + first = 0; + } + strm->avail_in = n; + strm->next_in = state->in; + state->x.pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return -1; + len -= n; + } + return 0; +} + +/* Write len bytes from buf to file. Return the number of bytes written. If + the returned value is less than len, then there was an error. */ +local z_size_t gz_write(state, buf, len) + gz_statep state; + voidpc buf; + z_size_t len; +{ + z_size_t put = len; + + /* if len is zero, avoid unnecessary operations */ + if (len == 0) + return 0; + + /* allocate memory if this is the first time through */ + if (state->size == 0 && gz_init(state) == -1) + return 0; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return 0; + } + + /* for small len, copy to input buffer, otherwise compress directly */ + if (len < state->size) { + /* copy to input buffer, compress when full */ + do { + unsigned have, copy; + + if (state->strm.avail_in == 0) + state->strm.next_in = state->in; + have = (unsigned)((state->strm.next_in + state->strm.avail_in) - + state->in); + copy = state->size - have; + if (copy > len) + copy = len; + memcpy(state->in + have, buf, copy); + state->strm.avail_in += copy; + state->x.pos += copy; + buf = (const char *)buf + copy; + len -= copy; + if (len && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + } while (len); + } + else { + /* consume whatever's left in the input buffer */ + if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + + /* directly compress user buffer to file */ + state->strm.next_in = (z_const Bytef *)buf; + do { + unsigned n = (unsigned)-1; + if (n > len) + n = len; + state->strm.avail_in = n; + state->x.pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + len -= n; + } while (len); + } + + /* input was all buffered or compressed */ + return put; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzwrite(file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); + return 0; + } + + /* write len bytes from buf (the return value will fit in an int) */ + return (int)gz_write(state, buf, len); +} + +/* -- see zlib.h -- */ +z_size_t ZEXPORT gzfwrite(buf, size, nitems, file) + voidpc buf; + z_size_t size; + z_size_t nitems; + gzFile file; +{ + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* compute bytes to read -- error on overflow */ + len = nitems * size; + if (size && len / size != nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + + /* write len bytes to buf, return the number of full items written */ + return len ? gz_write(state, buf, len) / size : 0; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned have; + unsigned char buf[1]; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return -1; + } + + /* try writing to input buffer for speed (state->size == 0 if buffer not + initialized) */ + if (state->size) { + if (strm->avail_in == 0) + strm->next_in = state->in; + have = (unsigned)((strm->next_in + strm->avail_in) - state->in); + if (have < state->size) { + state->in[have] = (unsigned char)c; + strm->avail_in++; + state->x.pos++; + return c & 0xff; + } + } + + /* no room in buffer or not initialized, use gz_write() */ + buf[0] = (unsigned char)c; + if (gz_write(state, buf, 1) != 1) + return -1; + return c & 0xff; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzputs(file, str) + gzFile file; + const char *str; +{ + int ret; + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; + + /* write string */ + len = strlen(str); + ret = gz_write(state, str, len); + return ret == 0 && len != 0 ? -1 : ret; +} + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +#include + +/* -- see zlib.h -- */ +int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) +{ + int len; + unsigned left; + char *next; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return state->err; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return state->err; + } + + /* do the printf() into the input buffer, put length in len -- the input + buffer is double-sized just for this function, so there is guaranteed to + be state->size bytes available after the current contents */ + if (strm->avail_in == 0) + strm->next_in = state->in; + next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in); + next[state->size - 1] = 0; +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void + (void)vsprintf(next, format, va); + for (len = 0; len < state->size; len++) + if (next[len] == 0) break; +# else + len = vsprintf(next, format, va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(next, state->size, format, va); + len = strlen(next); +# else + len = vsnprintf(next, state->size, format, va); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0) + return 0; + + /* update buffer and position, compress first half if past that */ + strm->avail_in += (unsigned)len; + state->x.pos += len; + if (strm->avail_in >= state->size) { + left = strm->avail_in - state->size; + strm->avail_in = state->size; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return state->err; + memcpy(state->in, state->in + state->size, left); + strm->next_in = state->in; + strm->avail_in = left; + } + return len; +} + +int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) +{ + va_list va; + int ret; + + va_start(va, format); + ret = gzvprintf(file, format, va); + va_end(va); + return ret; +} + +#else /* !STDC && !Z_HAVE_STDARG_H */ + +/* -- see zlib.h -- */ +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + unsigned len, left; + char *next; + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that can really pass pointer in ints */ + if (sizeof(int) != sizeof(void *)) + return Z_STREAM_ERROR; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* make sure we have some buffer space */ + if (state->size == 0 && gz_init(state) == -1) + return state->error; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return state->error; + } + + /* do the printf() into the input buffer, put length in len -- the input + buffer is double-sized just for this function, so there is guaranteed to + be state->size bytes available after the current contents */ + if (strm->avail_in == 0) + strm->next_in = state->in; + next = (char *)(strm->next_in + strm->avail_in); + next[state->size - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void + sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, + a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < size; len++) + if (next[len] == 0) + break; +# else + len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, + a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(next); +# else + len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#endif + + /* check that printf() results fit in buffer */ + if (len == 0 || len >= state->size || next[state->size - 1] != 0) + return 0; + + /* update buffer and position, compress first half if past that */ + strm->avail_in += len; + state->x.pos += len; + if (strm->avail_in >= state->size) { + left = strm->avail_in - state->size; + strm->avail_in = state->size; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return state->err; + memcpy(state->in, state->in + state->size, left); + strm->next_in = state->in; + strm->avail_in = left; + } + return (int)len; +} + +#endif + +/* -- see zlib.h -- */ +int ZEXPORT gzflush(file, flush) + gzFile file; + int flush; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* check flush parameter */ + if (flush < 0 || flush > Z_FINISH) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return state->err; + } + + /* compress remaining data with requested flush */ + (void)gz_comp(state, flush); + return state->err; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzsetparams(file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_statep state; + z_streamp strm; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + strm = &(state->strm); + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return Z_STREAM_ERROR; + + /* if no change is requested, then do nothing */ + if (level == state->level && strategy == state->strategy) + return Z_OK; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + return state->err; + } + + /* change compression parameters for subsequent input */ + if (state->size) { + /* flush previous input with previous parameters before changing */ + if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1) + return state->err; + deflateParams(strm, level, strategy); + } + state->level = level; + state->strategy = strategy; + return Z_OK; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzclose_w(file) + gzFile file; +{ + int ret = Z_OK; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return Z_STREAM_ERROR; + state = (gz_statep)file; + + /* check that we're writing */ + if (state->mode != GZ_WRITE) + return Z_STREAM_ERROR; + + /* check for seek request */ + if (state->seek) { + state->seek = 0; + if (gz_zero(state, state->skip) == -1) + ret = state->err; + } + + /* flush, free memory, and close file */ + if (gz_comp(state, Z_FINISH) == -1) + ret = state->err; + if (state->size) { + if (!state->direct) { + (void)deflateEnd(&(state->strm)); + free(state->out); + } + free(state->in); + } + gz_error(state, Z_OK, NULL); + free(state->path); + if (close(state->fd) == -1) + ret = Z_ERRNO; + free(state); + return ret; +} diff --git a/zlib-1.2.11/infback.c b/zlib-1.2.11/infback.c new file mode 100644 index 00000000..59679ecb --- /dev/null +++ b/zlib-1.2.11/infback.c @@ -0,0 +1,640 @@ +/* infback.c -- inflate using a call-back interface + * Copyright (C) 1995-2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + This code is largely copied from inflate.c. Normally either infback.o or + inflate.o would be linked into an application--not both. The interface + with inffast.c is retained so that optimized assembler-coded versions of + inflate_fast() can be used with either inflate.c or infback.c. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +/* function prototypes */ +local void fixedtables OF((struct inflate_state FAR *state)); + +/* + strm provides memory allocation functions in zalloc and zfree, or + Z_NULL to use the library memory allocation functions. + + windowBits is in the range 8..15, and window is a user-supplied + window and output buffer that is 2**windowBits bytes. + */ +int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) +z_streamp strm; +int windowBits; +unsigned char FAR *window; +const char *version; +int stream_size; +{ + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL || window == Z_NULL || + windowBits < 8 || windowBits > 15) + return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *)ZALLOC(strm, 1, + sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->dmax = 32768U; + state->wbits = (uInt)windowBits; + state->wsize = 1U << windowBits; + state->window = window; + state->wnext = 0; + state->whave = 0; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +/* Macros for inflateBack(): */ + +/* Load returned state from inflate_fast() */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Set state from registers for inflate_fast() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Assure that some input is available. If input is requested, but denied, + then return a Z_BUF_ERROR from inflateBack(). */ +#define PULL() \ + do { \ + if (have == 0) { \ + have = in(in_desc, &next); \ + if (have == 0) { \ + next = Z_NULL; \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflateBack() + with an error if there is no input available. */ +#define PULLBYTE() \ + do { \ + PULL(); \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflateBack() with + an error. */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* Assure that some output space is available, by writing out the window + if it's full. If the write fails, return from inflateBack() with a + Z_BUF_ERROR. */ +#define ROOM() \ + do { \ + if (left == 0) { \ + put = state->window; \ + left = state->wsize; \ + state->whave = left; \ + if (out(out_desc, put, left)) { \ + ret = Z_BUF_ERROR; \ + goto inf_leave; \ + } \ + } \ + } while (0) + +/* + strm provides the memory allocation functions and window buffer on input, + and provides information on the unused input on return. For Z_DATA_ERROR + returns, strm will also provide an error message. + + in() and out() are the call-back input and output functions. When + inflateBack() needs more input, it calls in(). When inflateBack() has + filled the window with output, or when it completes with data in the + window, it calls out() to write out the data. The application must not + change the provided input until in() is called again or inflateBack() + returns. The application must not change the window/output buffer until + inflateBack() returns. + + in() and out() are called with a descriptor parameter provided in the + inflateBack() call. This parameter can be a structure that provides the + information required to do the read or write, as well as accumulated + information on the input and output such as totals and check values. + + in() should return zero on failure. out() should return non-zero on + failure. If either in() or out() fails, than inflateBack() returns a + Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it + was in() or out() that caused in the error. Otherwise, inflateBack() + returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format + error, or Z_MEM_ERROR if it could not allocate memory for the state. + inflateBack() can also return Z_STREAM_ERROR if the input parameters + are not correct, i.e. strm is Z_NULL or the state was not initialized. + */ +int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) +z_streamp strm; +in_func in; +void FAR *in_desc; +out_func out; +void FAR *out_desc; +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + /* Check that the strm exists and that the state was initialized */ + if (strm == Z_NULL || strm->state == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* Reset the state */ + strm->msg = Z_NULL; + state->mode = TYPE; + state->last = 0; + state->whave = 0; + next = strm->next_in; + have = next != Z_NULL ? strm->avail_in : 0; + hold = 0; + bits = 0; + put = state->window; + left = state->wsize; + + /* Inflate until end of block marked as last */ + for (;;) + switch (state->mode) { + case TYPE: + /* determine and dispatch block type */ + if (state->last) { + BYTEBITS(); + state->mode = DONE; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN; /* decode codes */ + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + + case STORED: + /* get and verify stored block length */ + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + + /* copy stored block from input to output */ + while (state->length != 0) { + copy = state->length; + PULL(); + ROOM(); + if (copy > have) copy = have; + if (copy > left) copy = left; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + + case TABLE: + /* get dynamic table entries descriptor */ + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + + /* get code length code lengths (not a typo) */ + state->have = 0; + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + + /* get length and distance code code lengths */ + state->have = 0; + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = (unsigned)(state->lens[state->have - 1]); + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (code const FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (code const FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN; + + case LEN: + /* use inflate_fast() if we have enough input and output */ + if (have >= 6 && left >= 258) { + RESTORE(); + if (state->whave < state->wsize) + state->whave = state->wsize - left; + inflate_fast(strm, state->wsize); + LOAD(); + break; + } + + /* get a literal, length, or end-of-block code */ + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + state->length = (unsigned)here.val; + + /* process literal */ + if (here.op == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + ROOM(); + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + } + + /* process end of block */ + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + + /* invalid code */ + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + + /* length code -- get extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + + /* get distance code */ + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + } + DROPBITS(here.bits); + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + + /* get distance extra bits, if any */ + state->extra = (unsigned)(here.op) & 15; + if (state->extra != 0) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + } + if (state->offset > state->wsize - (state->whave < state->wsize ? + left : 0)) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + + /* copy match from window to output */ + do { + ROOM(); + copy = state->wsize - state->offset; + if (copy < left) { + from = put + copy; + copy = left - copy; + } + else { + from = put - state->offset; + copy = left; + } + if (copy > state->length) copy = state->length; + state->length -= copy; + left -= copy; + do { + *put++ = *from++; + } while (--copy); + } while (state->length != 0); + break; + + case DONE: + /* inflate stream terminated properly -- write leftover output */ + ret = Z_STREAM_END; + if (left < state->wsize) { + if (out(out_desc, state->window, state->wsize - left)) + ret = Z_BUF_ERROR; + } + goto inf_leave; + + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + + default: /* can't happen, but makes compilers happy */ + ret = Z_STREAM_ERROR; + goto inf_leave; + } + + /* Return unused input */ + inf_leave: + strm->next_in = next; + strm->avail_in = have; + return ret; +} + +int ZEXPORT inflateBackEnd(strm) +z_streamp strm; +{ + if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + return Z_STREAM_ERROR; + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} diff --git a/zlib-1.2.11/inffast.c b/zlib-1.2.11/inffast.c new file mode 100644 index 00000000..0dbd1dbc --- /dev/null +++ b/zlib-1.2.11/inffast.c @@ -0,0 +1,323 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") +#else + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in; + last = in + (strm->avail_in - 5); + out = strm->next_out; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + *out++ = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + *out++ = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + *out++ = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + *out++ = *from++; + } while (--len); + continue; + } +#endif + } + from = window; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = window; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } while (len > 2); + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in; + strm->next_out = out; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/zlib-1.2.11/inffast.h b/zlib-1.2.11/inffast.h new file mode 100644 index 00000000..e5c1aa4c --- /dev/null +++ b/zlib-1.2.11/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/zlib-1.2.11/inffixed.h b/zlib-1.2.11/inffixed.h new file mode 100644 index 00000000..d6283277 --- /dev/null +++ b/zlib-1.2.11/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/zlib-1.2.11/inflate.c b/zlib-1.2.11/inflate.c new file mode 100644 index 00000000..ac333e8c --- /dev/null +++ b/zlib-1.2.11/inflate.c @@ -0,0 +1,1561 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local int inflateStateCheck OF((z_streamp strm)); +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, + unsigned len)); + +local int inflateStateCheck(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} + +int ZEXPORT inflateResetKeep(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 5; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->strm = strm; + state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += (unsigned)value << state->bits; + state->bits += (uInt)bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, end, copy) +z_streamp strm; +const Bytef *end; +unsigned copy; +{ + struct inflate_state FAR *state; + unsigned dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state->wsize) { + zmemcpy(state->window, end - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, end - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, end - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + if (len > 15 || len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = ZSWAP32(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (const code FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if ((state->wrap & 4) && ( +#ifdef GUNZIP + state->flags ? hold : +#endif + ZSWAP32(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) +z_streamp strm; +Bytef *dictionary; +uInt *dictLength; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long dictid; + int ret; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary identifier */ + if (state->mode == DICT) { + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { + state->mode = MEM; + return Z_MEM_ERROR; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +const unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (inflateStateCheck(source) || dest == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + copy->strm = dest; + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; + return Z_OK; +#else + (void)subvert; + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +int ZEXPORT inflateValidate(strm, check) +z_streamp strm; +int check; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (check) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) + return -(1L << 16); + state = (struct inflate_state FAR *)strm->state; + return (long)(((unsigned long)((long)state->back)) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} + +unsigned long ZEXPORT inflateCodesUsed(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); +} diff --git a/zlib-1.2.11/inflate.h b/zlib-1.2.11/inflate.h new file mode 100644 index 00000000..a46cce6b --- /dev/null +++ b/zlib-1.2.11/inflate.h @@ -0,0 +1,125 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD = 16180, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* State maintained between inflate() calls -- approximately 7K bytes, not + including the allocated sliding window, which is up to 32K bytes. */ +struct inflate_state { + z_streamp strm; /* pointer back to this zlib stream */ + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/zlib-1.2.11/inftrees.c b/zlib-1.2.11/inftrees.c new file mode 100644 index 00000000..2ea08fc1 --- /dev/null +++ b/zlib-1.2.11/inftrees.c @@ -0,0 +1,304 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.11 Copyright 1995-2017 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + unsigned match; /* use base and extra for symbol >= match */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + match = 20; + break; + case LENS: + base = lbase; + extra = lext; + match = 257; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + match = 0; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if (work[sym] + 1U < match) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if (work[sym] >= match) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff != 0) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + next[huff] = here; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/zlib-1.2.11/inftrees.h b/zlib-1.2.11/inftrees.h new file mode 100644 index 00000000..baa53a0b --- /dev/null +++ b/zlib-1.2.11/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/zlib-1.2.11/make_vms.com b/zlib-1.2.11/make_vms.com new file mode 100644 index 00000000..65e9d0cb --- /dev/null +++ b/zlib-1.2.11/make_vms.com @@ -0,0 +1,867 @@ +$! make libz under VMS written by +$! Martin P.J. Zinser +$! +$! In case of problems with the install you might contact me at +$! zinser@zinser.no-ip.info(preferred) or +$! martin.zinser@eurexchange.com (work) +$! +$! Make procedure history for Zlib +$! +$!------------------------------------------------------------------------------ +$! Version history +$! 0.01 20060120 First version to receive a number +$! 0.02 20061008 Adapt to new Makefile.in +$! 0.03 20091224 Add support for large file check +$! 0.04 20100110 Add new gzclose, gzlib, gzread, gzwrite +$! 0.05 20100221 Exchange zlibdefs.h by zconf.h.in +$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new exmples +$! subdir path, update module search in makefile.in +$! 0.07 20120115 Triggered by work done by Alexey Chupahin completly redesigned +$! shared image creation +$! 0.08 20120219 Make it work on VAX again, pre-load missing symbols to shared +$! image +$! 0.09 20120305 SMS. P1 sets builder ("MMK", "MMS", " " (built-in)). +$! "" -> automatic, preference: MMK, MMS, built-in. +$! +$ on error then goto err_exit +$! +$ true = 1 +$ false = 0 +$ tmpnam = "temp_" + f$getjpi("","pid") +$ tt = tmpnam + ".txt" +$ tc = tmpnam + ".c" +$ th = tmpnam + ".h" +$ define/nolog tconfig 'th' +$ its_decc = false +$ its_vaxc = false +$ its_gnuc = false +$ s_case = False +$! +$! Setup variables holding "config" information +$! +$ Make = "''p1'" +$ name = "Zlib" +$ version = "?.?.?" +$ v_string = "ZLIB_VERSION" +$ v_file = "zlib.h" +$ ccopt = "/include = []" +$ lopts = "" +$ dnsrl = "" +$ aconf_in_file = "zconf.h.in#zconf.h_in#zconf_h.in" +$ conf_check_string = "" +$ linkonly = false +$ optfile = name + ".opt" +$ mapfile = name + ".map" +$ libdefs = "" +$ vax = f$getsyi("HW_MODEL").lt.1024 +$ axp = f$getsyi("HW_MODEL").ge.1024 .and. f$getsyi("HW_MODEL").lt.4096 +$ ia64 = f$getsyi("HW_MODEL").ge.4096 +$! +$! 2012-03-05 SMS. +$! Why is this needed? And if it is needed, why not simply ".not. vax"? +$! +$!!! if axp .or. ia64 then set proc/parse=extended +$! +$ whoami = f$parse(f$environment("Procedure"),,,,"NO_CONCEAL") +$ mydef = F$parse(whoami,,,"DEVICE") +$ mydir = f$parse(whoami,,,"DIRECTORY") - "][" +$ myproc = f$parse(whoami,,,"Name") + f$parse(whoami,,,"type") +$! +$! Check for MMK/MMS +$! +$ if (Make .eqs. "") +$ then +$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS" +$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK" +$ else +$ Make = f$edit( Make, "trim") +$ endif +$! +$ gosub find_version +$! +$ open/write topt tmp.opt +$ open/write optf 'optfile' +$! +$ gosub check_opts +$! +$! Look for the compiler used +$! +$ gosub check_compiler +$ close topt +$ close optf +$! +$ if its_decc +$ then +$ ccopt = "/prefix=all" + ccopt +$ if f$trnlnm("SYS") .eqs. "" +$ then +$ if axp +$ then +$ define sys sys$library: +$ else +$ ccopt = "/decc" + ccopt +$ define sys decc$library_include: +$ endif +$ endif +$! +$! 2012-03-05 SMS. +$! Why /NAMES = AS_IS? Why not simply ".not. vax"? And why not on VAX? +$! +$ if axp .or. ia64 +$ then +$ ccopt = ccopt + "/name=as_is/opt=(inline=speed)" +$ s_case = true +$ endif +$ endif +$ if its_vaxc .or. its_gnuc +$ then +$ if f$trnlnm("SYS").eqs."" then define sys sys$library: +$ endif +$! +$! Build a fake configure input header +$! +$ open/write conf_hin config.hin +$ write conf_hin "#undef _LARGEFILE64_SOURCE" +$ close conf_hin +$! +$! +$ i = 0 +$FIND_ACONF: +$ fname = f$element(i,"#",aconf_in_file) +$ if fname .eqs. "#" then goto AMISS_ERR +$ if f$search(fname) .eqs. "" +$ then +$ i = i + 1 +$ goto find_aconf +$ endif +$ open/read/err=aconf_err aconf_in 'fname' +$ open/write aconf zconf.h +$ACONF_LOOP: +$ read/end_of_file=aconf_exit aconf_in line +$ work = f$edit(line, "compress,trim") +$ if f$extract(0,6,work) .nes. "#undef" +$ then +$ if f$extract(0,12,work) .nes. "#cmakedefine" +$ then +$ write aconf line +$ endif +$ else +$ cdef = f$element(1," ",work) +$ gosub check_config +$ endif +$ goto aconf_loop +$ACONF_EXIT: +$ write aconf "" +$ write aconf "/* VMS specifics added by make_vms.com: */" +$ write aconf "#define VMS 1" +$ write aconf "#include " +$ write aconf "#include " +$ write aconf "#ifdef _LARGEFILE" +$ write aconf "# define off64_t __off64_t" +$ write aconf "# define fopen64 fopen" +$ write aconf "# define fseeko64 fseeko" +$ write aconf "# define lseek64 lseek" +$ write aconf "# define ftello64 ftell" +$ write aconf "#endif" +$ write aconf "#if !defined( __VAX) && (__CRTL_VER >= 70312000)" +$ write aconf "# define HAVE_VSNPRINTF" +$ write aconf "#endif" +$ close aconf_in +$ close aconf +$ if f$search("''th'") .nes. "" then delete 'th';* +$! Build the thing plain or with mms +$! +$ write sys$output "Compiling Zlib sources ..." +$ if make.eqs."" +$ then +$ if (f$search( "example.obj;*") .nes. "") then delete example.obj;* +$ if (f$search( "minigzip.obj;*") .nes. "") then delete minigzip.obj;* +$ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" - + adler32.c zlib.h zconf.h +$ CALL MAKE compress.OBJ "CC ''CCOPT' compress" - + compress.c zlib.h zconf.h +$ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" - + crc32.c zlib.h zconf.h +$ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" - + deflate.c deflate.h zutil.h zlib.h zconf.h +$ CALL MAKE gzclose.OBJ "CC ''CCOPT' gzclose" - + gzclose.c zutil.h zlib.h zconf.h +$ CALL MAKE gzlib.OBJ "CC ''CCOPT' gzlib" - + gzlib.c zutil.h zlib.h zconf.h +$ CALL MAKE gzread.OBJ "CC ''CCOPT' gzread" - + gzread.c zutil.h zlib.h zconf.h +$ CALL MAKE gzwrite.OBJ "CC ''CCOPT' gzwrite" - + gzwrite.c zutil.h zlib.h zconf.h +$ CALL MAKE infback.OBJ "CC ''CCOPT' infback" - + infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h +$ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" - + inffast.c zutil.h zlib.h zconf.h inffast.h +$ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" - + inflate.c zutil.h zlib.h zconf.h infblock.h +$ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" - + inftrees.c zutil.h zlib.h zconf.h inftrees.h +$ CALL MAKE trees.OBJ "CC ''CCOPT' trees" - + trees.c deflate.h zutil.h zlib.h zconf.h +$ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" - + uncompr.c zlib.h zconf.h +$ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" - + zutil.c zutil.h zlib.h zconf.h +$ write sys$output "Building Zlib ..." +$ CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ +$ write sys$output "Building example..." +$ CALL MAKE example.OBJ "CC ''CCOPT' [.test]example" - + [.test]example.c zlib.h zconf.h +$ call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb +$ write sys$output "Building minigzip..." +$ CALL MAKE minigzip.OBJ "CC ''CCOPT' [.test]minigzip" - + [.test]minigzip.c zlib.h zconf.h +$ call make minigzip.exe - + "LINK minigzip,libz.olb/lib" - + minigzip.obj libz.olb +$ else +$ gosub crea_mms +$ write sys$output "Make ''name' ''version' with ''Make' " +$ 'make' +$ endif +$! +$! Create shareable image +$! +$ gosub crea_olist +$ write sys$output "Creating libzshr.exe" +$ call map_2_shopt 'mapfile' 'optfile' +$ LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,'optfile'/opt +$ write sys$output "Zlib build completed" +$ delete/nolog tmp.opt;* +$ exit +$AMISS_ERR: +$ write sys$output "No source for config.hin found." +$ write sys$output "Tried any of ''aconf_in_file'" +$ goto err_exit +$CC_ERR: +$ write sys$output "C compiler required to build ''name'" +$ goto err_exit +$ERR_EXIT: +$ set message/facil/ident/sever/text +$ close/nolog optf +$ close/nolog topt +$ close/nolog aconf_in +$ close/nolog aconf +$ close/nolog out +$ close/nolog min +$ close/nolog mod +$ close/nolog h_in +$ write sys$output "Exiting..." +$ exit 2 +$! +$! +$MAKE: SUBROUTINE !SUBROUTINE TO CHECK DEPENDENCIES +$ V = 'F$Verify(0) +$! P1 = What we are trying to make +$! P2 = Command to make it +$! P3 - P8 What it depends on +$ +$ If F$Search(P1) .Eqs. "" Then Goto Makeit +$ Time = F$CvTime(F$File(P1,"RDT")) +$arg=3 +$Loop: +$ Argument = P'arg +$ If Argument .Eqs. "" Then Goto Exit +$ El=0 +$Loop2: +$ File = F$Element(El," ",Argument) +$ If File .Eqs. " " Then Goto Endl +$ AFile = "" +$Loop3: +$ OFile = AFile +$ AFile = F$Search(File) +$ If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl +$ If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit +$ Goto Loop3 +$NextEL: +$ El = El + 1 +$ Goto Loop2 +$EndL: +$ arg=arg+1 +$ If arg .Le. 8 Then Goto Loop +$ Goto Exit +$ +$Makeit: +$ VV=F$VERIFY(0) +$ write sys$output P2 +$ 'P2 +$ VV='F$Verify(VV) +$Exit: +$ If V Then Set Verify +$ENDSUBROUTINE +$!------------------------------------------------------------------------------ +$! +$! Check command line options and set symbols accordingly +$! +$!------------------------------------------------------------------------------ +$! Version history +$! 0.01 20041206 First version to receive a number +$! 0.02 20060126 Add new "HELP" target +$ CHECK_OPTS: +$ i = 1 +$ OPT_LOOP: +$ if i .lt. 9 +$ then +$ cparm = f$edit(p'i',"upcase") +$! +$! Check if parameter actually contains something +$! +$ if f$edit(cparm,"trim") .nes. "" +$ then +$ if cparm .eqs. "DEBUG" +$ then +$ ccopt = ccopt + "/noopt/deb" +$ lopts = lopts + "/deb" +$ endif +$ if f$locate("CCOPT=",cparm) .lt. f$length(cparm) +$ then +$ start = f$locate("=",cparm) + 1 +$ len = f$length(cparm) - start +$ ccopt = ccopt + f$extract(start,len,cparm) +$ if f$locate("AS_IS",f$edit(ccopt,"UPCASE")) .lt. f$length(ccopt) - + then s_case = true +$ endif +$ if cparm .eqs. "LINK" then linkonly = true +$ if f$locate("LOPTS=",cparm) .lt. f$length(cparm) +$ then +$ start = f$locate("=",cparm) + 1 +$ len = f$length(cparm) - start +$ lopts = lopts + f$extract(start,len,cparm) +$ endif +$ if f$locate("CC=",cparm) .lt. f$length(cparm) +$ then +$ start = f$locate("=",cparm) + 1 +$ len = f$length(cparm) - start +$ cc_com = f$extract(start,len,cparm) + if (cc_com .nes. "DECC") .and. - + (cc_com .nes. "VAXC") .and. - + (cc_com .nes. "GNUC") +$ then +$ write sys$output "Unsupported compiler choice ''cc_com' ignored" +$ write sys$output "Use DECC, VAXC, or GNUC instead" +$ else +$ if cc_com .eqs. "DECC" then its_decc = true +$ if cc_com .eqs. "VAXC" then its_vaxc = true +$ if cc_com .eqs. "GNUC" then its_gnuc = true +$ endif +$ endif +$ if f$locate("MAKE=",cparm) .lt. f$length(cparm) +$ then +$ start = f$locate("=",cparm) + 1 +$ len = f$length(cparm) - start +$ mmks = f$extract(start,len,cparm) +$ if (mmks .eqs. "MMK") .or. (mmks .eqs. "MMS") +$ then +$ make = mmks +$ else +$ write sys$output "Unsupported make choice ''mmks' ignored" +$ write sys$output "Use MMK or MMS instead" +$ endif +$ endif +$ if cparm .eqs. "HELP" then gosub bhelp +$ endif +$ i = i + 1 +$ goto opt_loop +$ endif +$ return +$!------------------------------------------------------------------------------ +$! +$! Look for the compiler used +$! +$! Version history +$! 0.01 20040223 First version to receive a number +$! 0.02 20040229 Save/set value of decc$no_rooted_search_lists +$! 0.03 20060202 Extend handling of GNU C +$! 0.04 20090402 Compaq -> hp +$CHECK_COMPILER: +$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc)) +$ then +$ its_decc = (f$search("SYS$SYSTEM:DECC$COMPILER.EXE") .nes. "") +$ its_vaxc = .not. its_decc .and. (F$Search("SYS$System:VAXC.Exe") .nes. "") +$ its_gnuc = .not. (its_decc .or. its_vaxc) .and. (f$trnlnm("gnu_cc") .nes. "") +$ endif +$! +$! Exit if no compiler available +$! +$ if (.not. (its_decc .or. its_vaxc .or. its_gnuc)) +$ then goto CC_ERR +$ else +$ if its_decc +$ then +$ write sys$output "CC compiler check ... hp C" +$ if f$trnlnm("decc$no_rooted_search_lists") .nes. "" +$ then +$ dnrsl = f$trnlnm("decc$no_rooted_search_lists") +$ endif +$ define/nolog decc$no_rooted_search_lists 1 +$ else +$ if its_vaxc then write sys$output "CC compiler check ... VAX C" +$ if its_gnuc +$ then +$ write sys$output "CC compiler check ... GNU C" +$ if f$trnlnm(topt) then write topt "gnu_cc:[000000]gcclib.olb/lib" +$ if f$trnlnm(optf) then write optf "gnu_cc:[000000]gcclib.olb/lib" +$ cc = "gcc" +$ endif +$ if f$trnlnm(topt) then write topt "sys$share:vaxcrtl.exe/share" +$ if f$trnlnm(optf) then write optf "sys$share:vaxcrtl.exe/share" +$ endif +$ endif +$ return +$!------------------------------------------------------------------------------ +$! +$! If MMS/MMK are available dump out the descrip.mms if required +$! +$CREA_MMS: +$ write sys$output "Creating descrip.mms..." +$ create descrip.mms +$ open/append out descrip.mms +$ copy sys$input: out +$ deck +# descrip.mms: MMS description file for building zlib on VMS +# written by Martin P.J. Zinser +# + +OBJS = adler32.obj, compress.obj, crc32.obj, gzclose.obj, gzlib.obj\ + gzread.obj, gzwrite.obj, uncompr.obj, infback.obj\ + deflate.obj, trees.obj, zutil.obj, inflate.obj, \ + inftrees.obj, inffast.obj + +$ eod +$ write out "CFLAGS=", ccopt +$ write out "LOPTS=", lopts +$ write out "all : example.exe minigzip.exe libz.olb" +$ copy sys$input: out +$ deck + @ write sys$output " Example applications available" + +libz.olb : libz.olb($(OBJS)) + @ write sys$output " libz available" + +example.exe : example.obj libz.olb + link $(LOPTS) example,libz.olb/lib + +minigzip.exe : minigzip.obj libz.olb + link $(LOPTS) minigzip,libz.olb/lib + +clean : + delete *.obj;*,libz.olb;*,*.opt;*,*.exe;* + + +# Other dependencies. +adler32.obj : adler32.c zutil.h zlib.h zconf.h +compress.obj : compress.c zlib.h zconf.h +crc32.obj : crc32.c zutil.h zlib.h zconf.h +deflate.obj : deflate.c deflate.h zutil.h zlib.h zconf.h +example.obj : [.test]example.c zlib.h zconf.h +gzclose.obj : gzclose.c zutil.h zlib.h zconf.h +gzlib.obj : gzlib.c zutil.h zlib.h zconf.h +gzread.obj : gzread.c zutil.h zlib.h zconf.h +gzwrite.obj : gzwrite.c zutil.h zlib.h zconf.h +inffast.obj : inffast.c zutil.h zlib.h zconf.h inftrees.h inffast.h +inflate.obj : inflate.c zutil.h zlib.h zconf.h +inftrees.obj : inftrees.c zutil.h zlib.h zconf.h inftrees.h +minigzip.obj : [.test]minigzip.c zlib.h zconf.h +trees.obj : trees.c deflate.h zutil.h zlib.h zconf.h +uncompr.obj : uncompr.c zlib.h zconf.h +zutil.obj : zutil.c zutil.h zlib.h zconf.h +infback.obj : infback.c zutil.h inftrees.h inflate.h inffast.h inffixed.h +$ eod +$ close out +$ return +$!------------------------------------------------------------------------------ +$! +$! Read list of core library sources from makefile.in and create options +$! needed to build shareable image +$! +$CREA_OLIST: +$ open/read min makefile.in +$ open/write mod modules.opt +$ src_check_list = "OBJZ =#OBJG =" +$MRLOOP: +$ read/end=mrdone min rec +$ i = 0 +$SRC_CHECK_LOOP: +$ src_check = f$element(i, "#", src_check_list) +$ i = i+1 +$ if src_check .eqs. "#" then goto mrloop +$ if (f$extract(0,6,rec) .nes. src_check) then goto src_check_loop +$ rec = rec - src_check +$ gosub extra_filnam +$ if (f$element(1,"\",rec) .eqs. "\") then goto mrloop +$MRSLOOP: +$ read/end=mrdone min rec +$ gosub extra_filnam +$ if (f$element(1,"\",rec) .nes. "\") then goto mrsloop +$MRDONE: +$ close min +$ close mod +$ return +$!------------------------------------------------------------------------------ +$! +$! Take record extracted in crea_olist and split it into single filenames +$! +$EXTRA_FILNAM: +$ myrec = f$edit(rec - "\", "trim,compress") +$ i = 0 +$FELOOP: +$ srcfil = f$element(i," ", myrec) +$ if (srcfil .nes. " ") +$ then +$ write mod f$parse(srcfil,,,"NAME"), ".obj" +$ i = i + 1 +$ goto feloop +$ endif +$ return +$!------------------------------------------------------------------------------ +$! +$! Find current Zlib version number +$! +$FIND_VERSION: +$ open/read h_in 'v_file' +$hloop: +$ read/end=hdone h_in rec +$ rec = f$edit(rec,"TRIM") +$ if (f$extract(0,1,rec) .nes. "#") then goto hloop +$ rec = f$edit(rec - "#", "TRIM") +$ if f$element(0," ",rec) .nes. "define" then goto hloop +$ if f$element(1," ",rec) .eqs. v_string +$ then +$ version = 'f$element(2," ",rec)' +$ goto hdone +$ endif +$ goto hloop +$hdone: +$ close h_in +$ return +$!------------------------------------------------------------------------------ +$! +$CHECK_CONFIG: +$! +$ in_ldef = f$locate(cdef,libdefs) +$ if (in_ldef .lt. f$length(libdefs)) +$ then +$ write aconf "#define ''cdef' 1" +$ libdefs = f$extract(0,in_ldef,libdefs) + - + f$extract(in_ldef + f$length(cdef) + 1, - + f$length(libdefs) - in_ldef - f$length(cdef) - 1, - + libdefs) +$ else +$ if (f$type('cdef') .eqs. "INTEGER") +$ then +$ write aconf "#define ''cdef' ", 'cdef' +$ else +$ if (f$type('cdef') .eqs. "STRING") +$ then +$ write aconf "#define ''cdef' ", """", '''cdef'', """" +$ else +$ gosub check_cc_def +$ endif +$ endif +$ endif +$ return +$!------------------------------------------------------------------------------ +$! +$! Check if this is a define relating to the properties of the C/C++ +$! compiler +$! +$ CHECK_CC_DEF: +$ if (cdef .eqs. "_LARGEFILE64_SOURCE") +$ then +$ copy sys$input: 'tc' +$ deck +#include "tconfig" +#define _LARGEFILE +#include + +int main(){ +FILE *fp; + fp = fopen("temp.txt","r"); + fseeko(fp,1,SEEK_SET); + fclose(fp); +} + +$ eod +$ test_inv = false +$ comm_h = false +$ gosub cc_prop_check +$ return +$ endif +$ write aconf "/* ", line, " */" +$ return +$!------------------------------------------------------------------------------ +$! +$! Check for properties of C/C++ compiler +$! +$! Version history +$! 0.01 20031020 First version to receive a number +$! 0.02 20031022 Added logic for defines with value +$! 0.03 20040309 Make sure local config file gets not deleted +$! 0.04 20041230 Also write include for configure run +$! 0.05 20050103 Add processing of "comment defines" +$CC_PROP_CHECK: +$ cc_prop = true +$ is_need = false +$ is_need = (f$extract(0,4,cdef) .eqs. "NEED") .or. (test_inv .eq. true) +$ if f$search(th) .eqs. "" then create 'th' +$ set message/nofac/noident/nosever/notext +$ on error then continue +$ cc 'tmpnam' +$ if .not. ($status) then cc_prop = false +$ on error then continue +$! The headers might lie about the capabilities of the RTL +$ link 'tmpnam',tmp.opt/opt +$ if .not. ($status) then cc_prop = false +$ set message/fac/ident/sever/text +$ on error then goto err_exit +$ delete/nolog 'tmpnam'.*;*/exclude='th' +$ if (cc_prop .and. .not. is_need) .or. - + (.not. cc_prop .and. is_need) +$ then +$ write sys$output "Checking for ''cdef'... yes" +$ if f$type('cdef_val'_yes) .nes. "" +$ then +$ if f$type('cdef_val'_yes) .eqs. "INTEGER" - + then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_yes) +$ if f$type('cdef_val'_yes) .eqs. "STRING" - + then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_yes) +$ else +$ call write_config f$fao("#define !AS 1",cdef) +$ endif +$ if (cdef .eqs. "HAVE_FSEEKO") .or. (cdef .eqs. "_LARGE_FILES") .or. - + (cdef .eqs. "_LARGEFILE64_SOURCE") then - + call write_config f$string("#define _LARGEFILE 1") +$ else +$ write sys$output "Checking for ''cdef'... no" +$ if (comm_h) +$ then + call write_config f$fao("/* !AS */",line) +$ else +$ if f$type('cdef_val'_no) .nes. "" +$ then +$ if f$type('cdef_val'_no) .eqs. "INTEGER" - + then call write_config f$fao("#define !AS !UL",cdef,'cdef_val'_no) +$ if f$type('cdef_val'_no) .eqs. "STRING" - + then call write_config f$fao("#define !AS !AS",cdef,'cdef_val'_no) +$ else +$ call write_config f$fao("#undef !AS",cdef) +$ endif +$ endif +$ endif +$ return +$!------------------------------------------------------------------------------ +$! +$! Check for properties of C/C++ compiler with multiple result values +$! +$! Version history +$! 0.01 20040127 First version +$! 0.02 20050103 Reconcile changes from cc_prop up to version 0.05 +$CC_MPROP_CHECK: +$ cc_prop = true +$ i = 1 +$ idel = 1 +$ MT_LOOP: +$ if f$type(result_'i') .eqs. "STRING" +$ then +$ set message/nofac/noident/nosever/notext +$ on error then continue +$ cc 'tmpnam'_'i' +$ if .not. ($status) then cc_prop = false +$ on error then continue +$! The headers might lie about the capabilities of the RTL +$ link 'tmpnam'_'i',tmp.opt/opt +$ if .not. ($status) then cc_prop = false +$ set message/fac/ident/sever/text +$ on error then goto err_exit +$ delete/nolog 'tmpnam'_'i'.*;* +$ if (cc_prop) +$ then +$ write sys$output "Checking for ''cdef'... ", mdef_'i' +$ if f$type(mdef_'i') .eqs. "INTEGER" - + then call write_config f$fao("#define !AS !UL",cdef,mdef_'i') +$ if f$type('cdef_val'_yes) .eqs. "STRING" - + then call write_config f$fao("#define !AS !AS",cdef,mdef_'i') +$ goto msym_clean +$ else +$ i = i + 1 +$ goto mt_loop +$ endif +$ endif +$ write sys$output "Checking for ''cdef'... no" +$ call write_config f$fao("#undef !AS",cdef) +$ MSYM_CLEAN: +$ if (idel .le. msym_max) +$ then +$ delete/sym mdef_'idel' +$ idel = idel + 1 +$ goto msym_clean +$ endif +$ return +$!------------------------------------------------------------------------------ +$! +$! Write configuration to both permanent and temporary config file +$! +$! Version history +$! 0.01 20031029 First version to receive a number +$! +$WRITE_CONFIG: SUBROUTINE +$ write aconf 'p1' +$ open/append confh 'th' +$ write confh 'p1' +$ close confh +$ENDSUBROUTINE +$!------------------------------------------------------------------------------ +$! +$! Analyze the project map file and create the symbol vector for a shareable +$! image from it +$! +$! Version history +$! 0.01 20120128 First version +$! 0.02 20120226 Add pre-load logic +$! +$ MAP_2_SHOPT: Subroutine +$! +$ SAY := "WRITE_ SYS$OUTPUT" +$! +$ IF F$SEARCH("''P1'") .EQS. "" +$ THEN +$ SAY "MAP_2_SHOPT-E-NOSUCHFILE: Error, inputfile ''p1' not available" +$ goto exit_m2s +$ ENDIF +$ IF "''P2'" .EQS. "" +$ THEN +$ SAY "MAP_2_SHOPT: Error, no output file provided" +$ goto exit_m2s +$ ENDIF +$! +$ module1 = "deflate#deflateEnd#deflateInit_#deflateParams#deflateSetDictionary" +$ module2 = "gzclose#gzerror#gzgetc#gzgets#gzopen#gzprintf#gzputc#gzputs#gzread" +$ module3 = "gzseek#gztell#inflate#inflateEnd#inflateInit_#inflateSetDictionary" +$ module4 = "inflateSync#uncompress#zlibVersion#compress" +$ open/read map 'p1 +$ if axp .or. ia64 +$ then +$ open/write aopt a.opt +$ open/write bopt b.opt +$ write aopt " CASE_SENSITIVE=YES" +$ write bopt "SYMBOL_VECTOR= (-" +$ mod_sym_num = 1 +$ MOD_SYM_LOOP: +$ if f$type(module'mod_sym_num') .nes. "" +$ then +$ mod_in = 0 +$ MOD_SYM_IN: +$ shared_proc = f$element(mod_in, "#", module'mod_sym_num') +$ if shared_proc .nes. "#" +$ then +$ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",- + f$edit(shared_proc,"upcase"),shared_proc) +$ write bopt f$fao("!AS=PROCEDURE,-",shared_proc) +$ mod_in = mod_in + 1 +$ goto mod_sym_in +$ endif +$ mod_sym_num = mod_sym_num + 1 +$ goto mod_sym_loop +$ endif +$MAP_LOOP: +$ read/end=map_end map line +$ if (f$locate("{",line).lt. f$length(line)) .or. - + (f$locate("global:", line) .lt. f$length(line)) +$ then +$ proc = true +$ goto map_loop +$ endif +$ if f$locate("}",line).lt. f$length(line) then proc = false +$ if f$locate("local:", line) .lt. f$length(line) then proc = false +$ if proc +$ then +$ shared_proc = f$edit(line,"collapse") +$ chop_semi = f$locate(";", shared_proc) +$ if chop_semi .lt. f$length(shared_proc) then - + shared_proc = f$extract(0, chop_semi, shared_proc) +$ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",- + f$edit(shared_proc,"upcase"),shared_proc) +$ write bopt f$fao("!AS=PROCEDURE,-",shared_proc) +$ endif +$ goto map_loop +$MAP_END: +$ close/nolog aopt +$ close/nolog bopt +$ open/append libopt 'p2' +$ open/read aopt a.opt +$ open/read bopt b.opt +$ALOOP: +$ read/end=aloop_end aopt line +$ write libopt line +$ goto aloop +$ALOOP_END: +$ close/nolog aopt +$ sv = "" +$BLOOP: +$ read/end=bloop_end bopt svn +$ if (svn.nes."") +$ then +$ if (sv.nes."") then write libopt sv +$ sv = svn +$ endif +$ goto bloop +$BLOOP_END: +$ write libopt f$extract(0,f$length(sv)-2,sv), "-" +$ write libopt ")" +$ close/nolog bopt +$ delete/nolog/noconf a.opt;*,b.opt;* +$ else +$ if vax +$ then +$ open/append libopt 'p2' +$ mod_sym_num = 1 +$ VMOD_SYM_LOOP: +$ if f$type(module'mod_sym_num') .nes. "" +$ then +$ mod_in = 0 +$ VMOD_SYM_IN: +$ shared_proc = f$element(mod_in, "#", module'mod_sym_num') +$ if shared_proc .nes. "#" +$ then +$ write libopt f$fao("UNIVERSAL=!AS",- + f$edit(shared_proc,"upcase")) +$ mod_in = mod_in + 1 +$ goto vmod_sym_in +$ endif +$ mod_sym_num = mod_sym_num + 1 +$ goto vmod_sym_loop +$ endif +$VMAP_LOOP: +$ read/end=vmap_end map line +$ if (f$locate("{",line).lt. f$length(line)) .or. - + (f$locate("global:", line) .lt. f$length(line)) +$ then +$ proc = true +$ goto vmap_loop +$ endif +$ if f$locate("}",line).lt. f$length(line) then proc = false +$ if f$locate("local:", line) .lt. f$length(line) then proc = false +$ if proc +$ then +$ shared_proc = f$edit(line,"collapse") +$ chop_semi = f$locate(";", shared_proc) +$ if chop_semi .lt. f$length(shared_proc) then - + shared_proc = f$extract(0, chop_semi, shared_proc) +$ write libopt f$fao("UNIVERSAL=!AS",- + f$edit(shared_proc,"upcase")) +$ endif +$ goto vmap_loop +$VMAP_END: +$ else +$ write sys$output "Unknown Architecture (Not VAX, AXP, or IA64)" +$ write sys$output "No options file created" +$ endif +$ endif +$ EXIT_M2S: +$ close/nolog map +$ close/nolog libopt +$ endsubroutine diff --git a/zlib-1.2.11/msdos/Makefile.bor b/zlib-1.2.11/msdos/Makefile.bor new file mode 100644 index 00000000..3d12a2c2 --- /dev/null +++ b/zlib-1.2.11/msdos/Makefile.bor @@ -0,0 +1,115 @@ +# Makefile for zlib +# Borland C++ +# Last updated: 15-Mar-2003 + +# To use, do "make -fmakefile.bor" +# To compile in small model, set below: MODEL=s + +# WARNING: the small model is supported but only for small values of +# MAX_WBITS and MAX_MEM_LEVEL. For example: +# -DMAX_WBITS=11 -DDEF_WBITS=11 -DMAX_MEM_LEVEL=3 +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to the LOC macro below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------ Turbo C++, Borland C++ ------------ + +# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) +# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added +# to the declaration of LOC here: +LOC = $(LOCAL_ZLIB) + +# type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. +CPU_TYP = 0 + +# memory model: one of s, m, c, l (small, medium, compact, large) +MODEL=l + +# replace bcc with tcc for Turbo C++ 1.0, with bcc32 for the 32 bit version +CC=bcc +LD=bcc +AR=tlib + +# compiler flags +# replace "-O2" by "-O -G -a -d" for Turbo C++ 1.0 +CFLAGS=-O2 -Z -m$(MODEL) $(LOC) + +LDFLAGS=-m$(MODEL) -f- + + +# variables +ZLIB_LIB = zlib_$(MODEL).lib + +OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj +OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj +OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj +OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj + + +# targets +all: $(ZLIB_LIB) example.exe minigzip.exe + +.c.obj: + $(CC) -c $(CFLAGS) $*.c + +adler32.obj: adler32.c zlib.h zconf.h + +compress.obj: compress.c zlib.h zconf.h + +crc32.obj: crc32.c zlib.h zconf.h crc32.h + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + +gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h + +gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h + +gzread.obj: gzread.c zlib.h zconf.h gzguts.h + +gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h + +infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h + +inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + +trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h + +uncompr.obj: uncompr.c zlib.h zconf.h + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + +example.obj: test/example.c zlib.h zconf.h + +minigzip.obj: test/minigzip.c zlib.h zconf.h + + +# the command line is cut to fit in the MS-DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + -del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) $(OBJP1) + $(AR) $(ZLIB_LIB) $(OBJP2) + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +clean: + -del *.obj + -del *.lib + -del *.exe + -del zlib_*.bak + -del foo.gz diff --git a/zlib-1.2.11/msdos/Makefile.dj2 b/zlib-1.2.11/msdos/Makefile.dj2 new file mode 100644 index 00000000..59d2037d --- /dev/null +++ b/zlib-1.2.11/msdos/Makefile.dj2 @@ -0,0 +1,104 @@ +# Makefile for zlib. Modified for djgpp v2.0 by F. J. Donahoe, 3/15/96. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.dj2; make test -fmakefile.dj2 +# +# To install libz.a, zconf.h and zlib.h in the djgpp directories, type: +# +# make install -fmakefile.dj2 +# +# after first defining LIBRARY_PATH and INCLUDE_PATH in djgpp.env as +# in the sample below if the pattern of the DJGPP distribution is to +# be followed. Remember that, while 'es around <=> are ignored in +# makefiles, they are *not* in batch files or in djgpp.env. +# - - - - - +# [make] +# INCLUDE_PATH=%\>;INCLUDE_PATH%%\DJDIR%\include +# LIBRARY_PATH=%\>;LIBRARY_PATH%%\DJDIR%\lib +# BUTT=-m486 +# - - - - - +# Alternately, these variables may be defined below, overriding the values +# in djgpp.env, as +# INCLUDE_PATH=c:\usr\include +# LIBRARY_PATH=c:\usr\lib + +CC=gcc + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DZLIB_DEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lz +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=libz.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ + uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o + +OBJA = +# to use the asm code: make OBJA=match.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +check: test +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +libz.a: $(OBJS) $(OBJA) + $(AR) $@ $(OBJS) $(OBJA) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + +# INCLUDE_PATH and LIBRARY_PATH were set for [make] in djgpp.env . + +.PHONY : uninstall clean + +install: $(INCL) $(LIBS) + -@if not exist $(INCLUDE_PATH)\nul mkdir $(INCLUDE_PATH) + -@if not exist $(LIBRARY_PATH)\nul mkdir $(LIBRARY_PATH) + $(INSTALL) zlib.h $(INCLUDE_PATH) + $(INSTALL) zconf.h $(INCLUDE_PATH) + $(INSTALL) libz.a $(LIBRARY_PATH) + +uninstall: + $(RM) $(INCLUDE_PATH)\zlib.h + $(RM) $(INCLUDE_PATH)\zconf.h + $(RM) $(LIBRARY_PATH)\libz.a + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) libz.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/zlib-1.2.11/msdos/Makefile.emx b/zlib-1.2.11/msdos/Makefile.emx new file mode 100644 index 00000000..e30f67be --- /dev/null +++ b/zlib-1.2.11/msdos/Makefile.emx @@ -0,0 +1,69 @@ +# Makefile for zlib. Modified for emx 0.9c by Chr. Spieler, 6/17/98. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.emx; make test -fmakefile.emx +# + +CC=gcc + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DZLIB_DEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lzlib +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=zlib.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzclose.o gzlib.o gzread.o gzwrite.o \ + uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +zlib.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + + +.PHONY : clean + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) zlib.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/zlib-1.2.11/msdos/Makefile.msc b/zlib-1.2.11/msdos/Makefile.msc new file mode 100644 index 00000000..ae837861 --- /dev/null +++ b/zlib-1.2.11/msdos/Makefile.msc @@ -0,0 +1,112 @@ +# Makefile for zlib +# Microsoft C 5.1 or later +# Last updated: 19-Mar-2003 + +# To use, do "make makefile.msc" +# To compile in small model, set below: MODEL=S + +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to the LOC macro below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------- Microsoft C 5.1 and later ------------- + +# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) +# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or added +# to the declaration of LOC here: +LOC = $(LOCAL_ZLIB) + +# Type for CPU required: 0: 8086, 1: 80186, 2: 80286, 3: 80386, etc. +CPU_TYP = 0 + +# Memory model: one of S, M, C, L (small, medium, compact, large) +MODEL=L + +CC=cl +CFLAGS=-nologo -A$(MODEL) -G$(CPU_TYP) -W3 -Oait -Gs $(LOC) +#-Ox generates bad code with MSC 5.1 +LIB_CFLAGS=-Zl $(CFLAGS) + +LD=link +LDFLAGS=/noi/e/st:0x1500/noe/farcall/packcode +# "/farcall/packcode" are only useful for `large code' memory models +# but should be a "no-op" for small code models. + + +# variables +ZLIB_LIB = zlib_$(MODEL).lib + +OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj +OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj + + +# targets +all: $(ZLIB_LIB) example.exe minigzip.exe + +.c.obj: + $(CC) -c $(LIB_CFLAGS) $*.c + +adler32.obj: adler32.c zlib.h zconf.h + +compress.obj: compress.c zlib.h zconf.h + +crc32.obj: crc32.c zlib.h zconf.h crc32.h + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + +gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h + +gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h + +gzread.obj: gzread.c zlib.h zconf.h gzguts.h + +gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h + +infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h + +inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + +trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h + +uncompr.obj: uncompr.c zlib.h zconf.h + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + +example.obj: test/example.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + +minigzip.obj: test/minigzip.c zlib.h zconf.h + $(CC) -c $(CFLAGS) $*.c + + +# the command line is cut to fit in the MS-DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + if exist $(ZLIB_LIB) del $(ZLIB_LIB) + lib $(ZLIB_LIB) $(OBJ1); + lib $(ZLIB_LIB) $(OBJ2); + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj,,,$(ZLIB_LIB); + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj,,,$(ZLIB_LIB); + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +clean: + -del *.obj + -del *.lib + -del *.exe + -del *.map + -del zlib_*.bak + -del foo.gz diff --git a/zlib-1.2.11/msdos/Makefile.tc b/zlib-1.2.11/msdos/Makefile.tc new file mode 100644 index 00000000..5aec82a9 --- /dev/null +++ b/zlib-1.2.11/msdos/Makefile.tc @@ -0,0 +1,100 @@ +# Makefile for zlib +# Turbo C 2.01, Turbo C++ 1.01 +# Last updated: 15-Mar-2003 + +# To use, do "make -fmakefile.tc" +# To compile in small model, set below: MODEL=s + +# WARNING: the small model is supported but only for small values of +# MAX_WBITS and MAX_MEM_LEVEL. For example: +# -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 +# If you wish to reduce the memory requirements (default 256K for big +# objects plus a few K), you can add to CFLAGS below: +# -DMAX_MEM_LEVEL=7 -DMAX_WBITS=14 +# See zconf.h for details about the memory requirements. + +# ------------ Turbo C 2.01, Turbo C++ 1.01 ------------ +MODEL=l +CC=tcc +LD=tcc +AR=tlib +# CFLAGS=-O2 -G -Z -m$(MODEL) -DMAX_WBITS=11 -DMAX_MEM_LEVEL=3 +CFLAGS=-O2 -G -Z -m$(MODEL) +LDFLAGS=-m$(MODEL) -f- + + +# variables +ZLIB_LIB = zlib_$(MODEL).lib + +OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj +OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj +OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj +OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj + + +# targets +all: $(ZLIB_LIB) example.exe minigzip.exe + +.c.obj: + $(CC) -c $(CFLAGS) $*.c + +adler32.obj: adler32.c zlib.h zconf.h + +compress.obj: compress.c zlib.h zconf.h + +crc32.obj: crc32.c zlib.h zconf.h crc32.h + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + +gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h + +gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h + +gzread.obj: gzread.c zlib.h zconf.h gzguts.h + +gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h + +infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h + +inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + +trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h + +uncompr.obj: uncompr.c zlib.h zconf.h + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + +example.obj: test/example.c zlib.h zconf.h + +minigzip.obj: test/minigzip.c zlib.h zconf.h + + +# the command line is cut to fit in the MS-DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) + -del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) $(OBJP1) + $(AR) $(ZLIB_LIB) $(OBJP2) + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) + +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +clean: + -del *.obj + -del *.lib + -del *.exe + -del zlib_*.bak + -del foo.gz diff --git a/zlib-1.2.11/nintendods/Makefile b/zlib-1.2.11/nintendods/Makefile new file mode 100644 index 00000000..21337d01 --- /dev/null +++ b/zlib-1.2.11/nintendods/Makefile @@ -0,0 +1,126 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +include $(DEVKITARM)/ds_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +#--------------------------------------------------------------------------------- +TARGET := $(shell basename $(CURDIR)) +BUILD := build +SOURCES := ../../ +DATA := data +INCLUDES := include + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -mthumb -mthumb-interwork + +CFLAGS := -Wall -O2\ + -march=armv5te -mtune=arm946e-s \ + -fomit-frame-pointer -ffast-math \ + $(ARCH) + +CFLAGS += $(INCLUDE) -DARM9 +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions + +ASFLAGS := $(ARCH) -march=armv5te -mtune=arm946e-s +LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(LIBNDS) + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/lib/libz.a + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES := $(addsuffix .o,$(BINFILES)) \ + $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +.PHONY: $(BUILD) clean all + +#--------------------------------------------------------------------------------- +all: $(BUILD) + @[ -d $@ ] || mkdir -p include + @cp ../../*.h include + +lib: + @[ -d $@ ] || mkdir -p $@ + +$(BUILD): lib + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) lib + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT) : $(OFILES) + +#--------------------------------------------------------------------------------- +%.bin.o : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/zlib-1.2.11/nintendods/README b/zlib-1.2.11/nintendods/README new file mode 100644 index 00000000..ba7a37db --- /dev/null +++ b/zlib-1.2.11/nintendods/README @@ -0,0 +1,5 @@ +This Makefile requires devkitARM (http://www.devkitpro.org/category/devkitarm/) and works inside "contrib/nds". It is based on a devkitARM template. + +Eduardo Costa +January 3, 2009 + diff --git a/zlib-1.2.11/old/Makefile.emx b/zlib-1.2.11/old/Makefile.emx new file mode 100644 index 00000000..612b0379 --- /dev/null +++ b/zlib-1.2.11/old/Makefile.emx @@ -0,0 +1,69 @@ +# Makefile for zlib. Modified for emx/rsxnt by Chr. Spieler, 6/16/98. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.emx; make test -fmakefile.emx +# + +CC=gcc -Zwin32 + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DZLIB_DEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lzlib +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=zlib.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \ + gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +zlib.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + + +.PHONY : clean + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) zlib.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/zlib-1.2.11/old/Makefile.riscos b/zlib-1.2.11/old/Makefile.riscos new file mode 100644 index 00000000..57e29d3f --- /dev/null +++ b/zlib-1.2.11/old/Makefile.riscos @@ -0,0 +1,151 @@ +# Project: zlib_1_03 +# Patched for zlib 1.1.2 rw@shadow.org.uk 19980430 +# test works out-of-the-box, installs `somewhere' on demand + +# Toolflags: +CCflags = -c -depend !Depend -IC: -g -throwback -DRISCOS -fah +C++flags = -c -depend !Depend -IC: -throwback +Linkflags = -aif -c++ -o $@ +ObjAsmflags = -throwback -NoCache -depend !Depend +CMHGflags = +LibFileflags = -c -l -o $@ +Squeezeflags = -o $@ + +# change the line below to where _you_ want the library installed. +libdest = lib:zlib + +# Final targets: +@.lib: @.o.adler32 @.o.compress @.o.crc32 @.o.deflate @.o.gzio \ + @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil @.o.trees \ + @.o.uncompr @.o.zutil + LibFile $(LibFileflags) @.o.adler32 @.o.compress @.o.crc32 @.o.deflate \ + @.o.gzio @.o.infblock @.o.infcodes @.o.inffast @.o.inflate @.o.inftrees @.o.infutil \ + @.o.trees @.o.uncompr @.o.zutil +test: @.minigzip @.example @.lib + @copy @.lib @.libc A~C~DF~L~N~P~Q~RS~TV + @echo running tests: hang on. + @/@.minigzip -f -9 libc + @/@.minigzip -d libc-gz + @/@.minigzip -f -1 libc + @/@.minigzip -d libc-gz + @/@.minigzip -h -9 libc + @/@.minigzip -d libc-gz + @/@.minigzip -h -1 libc + @/@.minigzip -d libc-gz + @/@.minigzip -9 libc + @/@.minigzip -d libc-gz + @/@.minigzip -1 libc + @/@.minigzip -d libc-gz + @diff @.lib @.libc + @echo that should have reported '@.lib and @.libc identical' if you have diff. + @/@.example @.fred @.fred + @echo that will have given lots of hello!'s. + +@.minigzip: @.o.minigzip @.lib C:o.Stubs + Link $(Linkflags) @.o.minigzip @.lib C:o.Stubs +@.example: @.o.example @.lib C:o.Stubs + Link $(Linkflags) @.o.example @.lib C:o.Stubs + +install: @.lib + cdir $(libdest) + cdir $(libdest).h + @copy @.h.zlib $(libdest).h.zlib A~C~DF~L~N~P~Q~RS~TV + @copy @.h.zconf $(libdest).h.zconf A~C~DF~L~N~P~Q~RS~TV + @copy @.lib $(libdest).lib A~C~DF~L~N~P~Q~RS~TV + @echo okay, installed zlib in $(libdest) + +clean:; remove @.minigzip + remove @.example + remove @.libc + -wipe @.o.* F~r~cV + remove @.fred + +# User-editable dependencies: +.c.o: + cc $(ccflags) -o $@ $< + +# Static dependencies: + +# Dynamic dependencies: +o.example: c.example +o.example: h.zlib +o.example: h.zconf +o.minigzip: c.minigzip +o.minigzip: h.zlib +o.minigzip: h.zconf +o.adler32: c.adler32 +o.adler32: h.zlib +o.adler32: h.zconf +o.compress: c.compress +o.compress: h.zlib +o.compress: h.zconf +o.crc32: c.crc32 +o.crc32: h.zlib +o.crc32: h.zconf +o.deflate: c.deflate +o.deflate: h.deflate +o.deflate: h.zutil +o.deflate: h.zlib +o.deflate: h.zconf +o.gzio: c.gzio +o.gzio: h.zutil +o.gzio: h.zlib +o.gzio: h.zconf +o.infblock: c.infblock +o.infblock: h.zutil +o.infblock: h.zlib +o.infblock: h.zconf +o.infblock: h.infblock +o.infblock: h.inftrees +o.infblock: h.infcodes +o.infblock: h.infutil +o.infcodes: c.infcodes +o.infcodes: h.zutil +o.infcodes: h.zlib +o.infcodes: h.zconf +o.infcodes: h.inftrees +o.infcodes: h.infblock +o.infcodes: h.infcodes +o.infcodes: h.infutil +o.infcodes: h.inffast +o.inffast: c.inffast +o.inffast: h.zutil +o.inffast: h.zlib +o.inffast: h.zconf +o.inffast: h.inftrees +o.inffast: h.infblock +o.inffast: h.infcodes +o.inffast: h.infutil +o.inffast: h.inffast +o.inflate: c.inflate +o.inflate: h.zutil +o.inflate: h.zlib +o.inflate: h.zconf +o.inflate: h.infblock +o.inftrees: c.inftrees +o.inftrees: h.zutil +o.inftrees: h.zlib +o.inftrees: h.zconf +o.inftrees: h.inftrees +o.inftrees: h.inffixed +o.infutil: c.infutil +o.infutil: h.zutil +o.infutil: h.zlib +o.infutil: h.zconf +o.infutil: h.infblock +o.infutil: h.inftrees +o.infutil: h.infcodes +o.infutil: h.infutil +o.trees: c.trees +o.trees: h.deflate +o.trees: h.zutil +o.trees: h.zlib +o.trees: h.zconf +o.trees: h.trees +o.uncompr: c.uncompr +o.uncompr: h.zlib +o.uncompr: h.zconf +o.zutil: c.zutil +o.zutil: h.zutil +o.zutil: h.zlib +o.zutil: h.zconf diff --git a/zlib-1.2.11/old/README b/zlib-1.2.11/old/README new file mode 100644 index 00000000..800bf079 --- /dev/null +++ b/zlib-1.2.11/old/README @@ -0,0 +1,3 @@ +This directory contains files that have not been updated for zlib 1.2.x + +(Volunteers are encouraged to help clean this up. Thanks.) diff --git a/zlib-1.2.11/old/descrip.mms b/zlib-1.2.11/old/descrip.mms new file mode 100644 index 00000000..7066da5b --- /dev/null +++ b/zlib-1.2.11/old/descrip.mms @@ -0,0 +1,48 @@ +# descrip.mms: MMS description file for building zlib on VMS +# written by Martin P.J. Zinser + +cc_defs = +c_deb = + +.ifdef __DECC__ +pref = /prefix=all +.endif + +OBJS = adler32.obj, compress.obj, crc32.obj, gzio.obj, uncompr.obj,\ + deflate.obj, trees.obj, zutil.obj, inflate.obj, infblock.obj,\ + inftrees.obj, infcodes.obj, infutil.obj, inffast.obj + +CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF) + +all : example.exe minigzip.exe + @ write sys$output " Example applications available" +libz.olb : libz.olb($(OBJS)) + @ write sys$output " libz available" + +example.exe : example.obj libz.olb + link example,libz.olb/lib + +minigzip.exe : minigzip.obj libz.olb + link minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib + +clean : + delete *.obj;*,libz.olb;* + + +# Other dependencies. +adler32.obj : zutil.h zlib.h zconf.h +compress.obj : zlib.h zconf.h +crc32.obj : zutil.h zlib.h zconf.h +deflate.obj : deflate.h zutil.h zlib.h zconf.h +example.obj : zlib.h zconf.h +gzio.obj : zutil.h zlib.h zconf.h +infblock.obj : zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h +infcodes.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h infcodes.h inffast.h +inffast.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h inffast.h +inflate.obj : zutil.h zlib.h zconf.h infblock.h +inftrees.obj : zutil.h zlib.h zconf.h inftrees.h +infutil.obj : zutil.h zlib.h zconf.h inftrees.h infutil.h +minigzip.obj : zlib.h zconf.h +trees.obj : deflate.h zutil.h zlib.h zconf.h +uncompr.obj : zlib.h zconf.h +zutil.obj : zutil.h zlib.h zconf.h diff --git a/zlib-1.2.11/old/os2/Makefile.os2 b/zlib-1.2.11/old/os2/Makefile.os2 new file mode 100644 index 00000000..bb426c0d --- /dev/null +++ b/zlib-1.2.11/old/os2/Makefile.os2 @@ -0,0 +1,136 @@ +# Makefile for zlib under OS/2 using GCC (PGCC) +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile and test, type: +# cp Makefile.os2 .. +# cd .. +# make -f Makefile.os2 test + +# This makefile will build a static library z.lib, a shared library +# z.dll and a import library zdll.lib. You can use either z.lib or +# zdll.lib by specifying either -lz or -lzdll on gcc's command line + +CC=gcc -Zomf -s + +CFLAGS=-O6 -Wall +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-g -DZLIB_DEBUG +#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ +# -Wstrict-prototypes -Wmissing-prototypes + +#################### BUG WARNING: ##################### +## infcodes.c hits a bug in pgcc-1.0, so you have to use either +## -O# where # <= 4 or one of (-fno-ommit-frame-pointer or -fno-force-mem) +## This bug is reportedly fixed in pgcc >1.0, but this was not tested +CFLAGS+=-fno-force-mem + +LDFLAGS=-s -L. -lzdll -Zcrtdll +LDSHARED=$(CC) -s -Zomf -Zdll -Zcrtdll + +VER=1.1.0 +ZLIB=z.lib +SHAREDLIB=z.dll +SHAREDLIBIMP=zdll.lib +LIBS=$(ZLIB) $(SHAREDLIB) $(SHAREDLIBIMP) + +AR=emxomfar cr +IMPLIB=emximp +RANLIB=echo +TAR=tar +SHELL=bash + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ + zutil.o inflate.o infblock.o inftrees.o infcodes.o infutil.o inffast.o + +TEST_OBJS = example.o minigzip.o + +DISTFILES = README INDEX ChangeLog configure Make*[a-z0-9] *.[ch] descrip.mms \ + algorithm.txt zlib.3 msdos/Make*[a-z0-9] msdos/zlib.def msdos/zlib.rc \ + nt/Makefile.nt nt/zlib.dnt contrib/README.contrib contrib/*.txt \ + contrib/asm386/*.asm contrib/asm386/*.c \ + contrib/asm386/*.bat contrib/asm386/zlibvc.d?? contrib/iostream/*.cpp \ + contrib/iostream/*.h contrib/iostream2/*.h contrib/iostream2/*.cpp \ + contrib/untgz/Makefile contrib/untgz/*.c contrib/untgz/*.w32 + +all: example.exe minigzip.exe + +test: all + @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ + echo hello world | ./minigzip | ./minigzip -d || \ + echo ' *** minigzip test FAILED ***' ; \ + if ./example; then \ + echo ' *** zlib test OK ***'; \ + else \ + echo ' *** zlib test FAILED ***'; \ + fi + +$(ZLIB): $(OBJS) + $(AR) $@ $(OBJS) + -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 + +$(SHAREDLIB): $(OBJS) os2/z.def + $(LDSHARED) -o $@ $^ + +$(SHAREDLIBIMP): os2/z.def + $(IMPLIB) -o $@ $^ + +example.exe: example.o $(LIBS) + $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) + +minigzip.exe: minigzip.o $(LIBS) + $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) + +clean: + rm -f *.o *~ example minigzip libz.a libz.so* foo.gz + +distclean: clean + +zip: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c + v=`sed -n -e 's/\.//g' -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + zip -ul9 zlib$$v $(DISTFILES) + mv Makefile~ Makefile + +dist: + mv Makefile Makefile~; cp -p Makefile.in Makefile + rm -f test.c ztest*.c + d=zlib-`sed -n '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`;\ + rm -f $$d.tar.gz; \ + if test ! -d ../$$d; then rm -f ../$$d; ln -s `pwd` ../$$d; fi; \ + files=""; \ + for f in $(DISTFILES); do files="$$files $$d/$$f"; done; \ + cd ..; \ + GZIP=-9 $(TAR) chofz $$d/$$d.tar.gz $$files; \ + if test ! -d $$d; then rm -f $$d; fi + mv Makefile~ Makefile + +tags: + etags *.[ch] + +depend: + makedepend -- $(CFLAGS) -- *.[ch] + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +adler32.o: zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +example.o: zlib.h zconf.h +gzio.o: zutil.h zlib.h zconf.h +infblock.o: infblock.h inftrees.h infcodes.h infutil.h zutil.h zlib.h zconf.h +infcodes.o: zutil.h zlib.h zconf.h +infcodes.o: inftrees.h infblock.h infcodes.h infutil.h inffast.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h +inffast.o: infblock.h infcodes.h infutil.h inffast.h +inflate.o: zutil.h zlib.h zconf.h infblock.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +infutil.o: zutil.h zlib.h zconf.h infblock.h inftrees.h infcodes.h infutil.h +minigzip.o: zlib.h zconf.h +trees.o: deflate.h zutil.h zlib.h zconf.h trees.h +uncompr.o: zlib.h zconf.h +zutil.o: zutil.h zlib.h zconf.h diff --git a/zlib-1.2.11/old/os2/zlib.def b/zlib-1.2.11/old/os2/zlib.def new file mode 100644 index 00000000..4c753f1a --- /dev/null +++ b/zlib-1.2.11/old/os2/zlib.def @@ -0,0 +1,51 @@ +; +; Slightly modified version of ../nt/zlib.dnt :-) +; + +LIBRARY Z +DESCRIPTION "Zlib compression library for OS/2" +CODE PRELOAD MOVEABLE DISCARDABLE +DATA PRELOAD MOVEABLE MULTIPLE + +EXPORTS + adler32 + compress + crc32 + deflate + deflateCopy + deflateEnd + deflateInit2_ + deflateInit_ + deflateParams + deflateReset + deflateSetDictionary + gzclose + gzdopen + gzerror + gzflush + gzopen + gzread + gzwrite + inflate + inflateEnd + inflateInit2_ + inflateInit_ + inflateReset + inflateSetDictionary + inflateSync + uncompress + zlibVersion + gzprintf + gzputc + gzgetc + gzseek + gzrewind + gztell + gzeof + gzsetparams + zError + inflateSyncPoint + get_crc_table + compress2 + gzputs + gzgets diff --git a/zlib-1.2.11/old/visual-basic.txt b/zlib-1.2.11/old/visual-basic.txt new file mode 100644 index 00000000..57efe581 --- /dev/null +++ b/zlib-1.2.11/old/visual-basic.txt @@ -0,0 +1,160 @@ +See below some functions declarations for Visual Basic. + +Frequently Asked Question: + +Q: Each time I use the compress function I get the -5 error (not enough + room in the output buffer). + +A: Make sure that the length of the compressed buffer is passed by + reference ("as any"), not by value ("as long"). Also check that + before the call of compress this length is equal to the total size of + the compressed buffer and not zero. + + +From: "Jon Caruana" +Subject: Re: How to port zlib declares to vb? +Date: Mon, 28 Oct 1996 18:33:03 -0600 + +Got the answer! (I haven't had time to check this but it's what I got, and +looks correct): + +He has the following routines working: + compress + uncompress + gzopen + gzwrite + gzread + gzclose + +Declares follow: (Quoted from Carlos Rios , in Vb4 form) + +#If Win16 Then 'Use Win16 calls. +Declare Function compress Lib "ZLIB.DLL" (ByVal compr As + String, comprLen As Any, ByVal buf As String, ByVal buflen + As Long) As Integer +Declare Function uncompress Lib "ZLIB.DLL" (ByVal uncompr + As String, uncomprLen As Any, ByVal compr As String, ByVal + lcompr As Long) As Integer +Declare Function gzopen Lib "ZLIB.DLL" (ByVal filePath As + String, ByVal mode As String) As Long +Declare Function gzread Lib "ZLIB.DLL" (ByVal file As + Long, ByVal uncompr As String, ByVal uncomprLen As Integer) + As Integer +Declare Function gzwrite Lib "ZLIB.DLL" (ByVal file As + Long, ByVal uncompr As String, ByVal uncomprLen As Integer) + As Integer +Declare Function gzclose Lib "ZLIB.DLL" (ByVal file As + Long) As Integer +#Else +Declare Function compress Lib "ZLIB32.DLL" + (ByVal compr As String, comprLen As Any, ByVal buf As + String, ByVal buflen As Long) As Integer +Declare Function uncompress Lib "ZLIB32.DLL" + (ByVal uncompr As String, uncomprLen As Any, ByVal compr As + String, ByVal lcompr As Long) As Long +Declare Function gzopen Lib "ZLIB32.DLL" + (ByVal file As String, ByVal mode As String) As Long +Declare Function gzread Lib "ZLIB32.DLL" + (ByVal file As Long, ByVal uncompr As String, ByVal + uncomprLen As Long) As Long +Declare Function gzwrite Lib "ZLIB32.DLL" + (ByVal file As Long, ByVal uncompr As String, ByVal + uncomprLen As Long) As Long +Declare Function gzclose Lib "ZLIB32.DLL" + (ByVal file As Long) As Long +#End If + +-Jon Caruana +jon-net@usa.net +Microsoft Sitebuilder Network Level 1 Member - HTML Writer's Guild Member + + +Here is another example from Michael that he +says conforms to the VB guidelines, and that solves the problem of not +knowing the uncompressed size by storing it at the end of the file: + +'Calling the functions: +'bracket meaning: [optional] {Range of possible values} +'Call subCompressFile( [, , [level of compression {1..9}]]) +'Call subUncompressFile() + +Option Explicit +Private lngpvtPcnSml As Long 'Stores value for 'lngPercentSmaller' +Private Const SUCCESS As Long = 0 +Private Const strFilExt As String = ".cpr" +Private Declare Function lngfncCpr Lib "zlib.dll" Alias "compress2" (ByRef +dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long, +ByVal level As Integer) As Long +Private Declare Function lngfncUcp Lib "zlib.dll" Alias "uncompress" (ByRef +dest As Any, ByRef destLen As Any, ByRef src As Any, ByVal srcLen As Long) +As Long + +Public Sub subCompressFile(ByVal strargOriFilPth As String, Optional ByVal +strargCprFilPth As String, Optional ByVal intLvl As Integer = 9) + Dim strCprPth As String + Dim lngOriSiz As Long + Dim lngCprSiz As Long + Dim bytaryOri() As Byte + Dim bytaryCpr() As Byte + lngOriSiz = FileLen(strargOriFilPth) + ReDim bytaryOri(lngOriSiz - 1) + Open strargOriFilPth For Binary Access Read As #1 + Get #1, , bytaryOri() + Close #1 + strCprPth = IIf(strargCprFilPth = "", strargOriFilPth, strargCprFilPth) +'Select file path and name + strCprPth = strCprPth & IIf(Right(strCprPth, Len(strFilExt)) = +strFilExt, "", strFilExt) 'Add file extension if not exists + lngCprSiz = (lngOriSiz * 1.01) + 12 'Compression needs temporary a bit +more space then original file size + ReDim bytaryCpr(lngCprSiz - 1) + If lngfncCpr(bytaryCpr(0), lngCprSiz, bytaryOri(0), lngOriSiz, intLvl) = +SUCCESS Then + lngpvtPcnSml = (1# - (lngCprSiz / lngOriSiz)) * 100 + ReDim Preserve bytaryCpr(lngCprSiz - 1) + Open strCprPth For Binary Access Write As #1 + Put #1, , bytaryCpr() + Put #1, , lngOriSiz 'Add the the original size value to the end +(last 4 bytes) + Close #1 + Else + MsgBox "Compression error" + End If + Erase bytaryCpr + Erase bytaryOri +End Sub + +Public Sub subUncompressFile(ByVal strargFilPth As String) + Dim bytaryCpr() As Byte + Dim bytaryOri() As Byte + Dim lngOriSiz As Long + Dim lngCprSiz As Long + Dim strOriPth As String + lngCprSiz = FileLen(strargFilPth) + ReDim bytaryCpr(lngCprSiz - 1) + Open strargFilPth For Binary Access Read As #1 + Get #1, , bytaryCpr() + Close #1 + 'Read the original file size value: + lngOriSiz = bytaryCpr(lngCprSiz - 1) * (2 ^ 24) _ + + bytaryCpr(lngCprSiz - 2) * (2 ^ 16) _ + + bytaryCpr(lngCprSiz - 3) * (2 ^ 8) _ + + bytaryCpr(lngCprSiz - 4) + ReDim Preserve bytaryCpr(lngCprSiz - 5) 'Cut of the original size value + ReDim bytaryOri(lngOriSiz - 1) + If lngfncUcp(bytaryOri(0), lngOriSiz, bytaryCpr(0), lngCprSiz) = SUCCESS +Then + strOriPth = Left(strargFilPth, Len(strargFilPth) - Len(strFilExt)) + Open strOriPth For Binary Access Write As #1 + Put #1, , bytaryOri() + Close #1 + Else + MsgBox "Uncompression error" + End If + Erase bytaryCpr + Erase bytaryOri +End Sub +Public Property Get lngPercentSmaller() As Long + lngPercentSmaller = lngpvtPcnSml +End Property diff --git a/zlib-1.2.11/os400/README400 b/zlib-1.2.11/os400/README400 new file mode 100644 index 00000000..4f98334f --- /dev/null +++ b/zlib-1.2.11/os400/README400 @@ -0,0 +1,48 @@ + ZLIB version 1.2.11 for OS/400 installation instructions + +1) Download and unpack the zlib tarball to some IFS directory. + (i.e.: /path/to/the/zlib/ifs/source/directory) + + If the installed IFS command suppors gzip format, this is straightforward, +else you have to unpack first to some directory on a system supporting it, +then move the whole directory to the IFS via the network (via SMB or FTP). + +2) Edit the configuration parameters in the compilation script. + + EDTF STMF('/path/to/the/zlib/ifs/source/directory/os400/make.sh') + +Tune the parameters according to your needs if not matching the defaults. +Save the file and exit after edition. + +3) Enter qshell, then work in the zlib OS/400 specific directory. + + QSH + cd /path/to/the/zlib/ifs/source/directory/os400 + +4) Compile and install + + sh make.sh + +The script will: +- create the libraries, objects and IFS directories for the zlib environment, +- compile all modules, +- create a service program, +- create a static and a dynamic binding directory, +- install header files for C/C++ and for ILE/RPG, both for compilation in + DB2 and IFS environments. + +That's all. + + +Notes: For OS/400 ILE RPG programmers, a /copy member defining the ZLIB + API prototypes for ILE RPG can be found in ZLIB/H(ZLIB.INC). + In the ILE environment, the same definitions are available from + file zlib.inc located in the same IFS include directory as the + C/C++ header files. + Please read comments in this member for more information. + + Remember that most foreign textual data are ASCII coded: this + implementation does not handle conversion from/to ASCII, so + text data code conversions must be done explicitely. + + Mainly for the reason above, always open zipped files in binary mode. diff --git a/zlib-1.2.11/os400/bndsrc b/zlib-1.2.11/os400/bndsrc new file mode 100644 index 00000000..5e6e0a2f --- /dev/null +++ b/zlib-1.2.11/os400/bndsrc @@ -0,0 +1,119 @@ +STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ZLIB') + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.1.3 entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("adler32") + EXPORT SYMBOL("compress") + EXPORT SYMBOL("compress2") + EXPORT SYMBOL("crc32") + EXPORT SYMBOL("get_crc_table") + EXPORT SYMBOL("deflate") + EXPORT SYMBOL("deflateEnd") + EXPORT SYMBOL("deflateSetDictionary") + EXPORT SYMBOL("deflateCopy") + EXPORT SYMBOL("deflateReset") + EXPORT SYMBOL("deflateParams") + EXPORT SYMBOL("deflatePrime") + EXPORT SYMBOL("deflateInit_") + EXPORT SYMBOL("deflateInit2_") + EXPORT SYMBOL("gzopen") + EXPORT SYMBOL("gzdopen") + EXPORT SYMBOL("gzsetparams") + EXPORT SYMBOL("gzread") + EXPORT SYMBOL("gzwrite") + EXPORT SYMBOL("gzprintf") + EXPORT SYMBOL("gzputs") + EXPORT SYMBOL("gzgets") + EXPORT SYMBOL("gzputc") + EXPORT SYMBOL("gzgetc") + EXPORT SYMBOL("gzflush") + EXPORT SYMBOL("gzseek") + EXPORT SYMBOL("gzrewind") + EXPORT SYMBOL("gztell") + EXPORT SYMBOL("gzeof") + EXPORT SYMBOL("gzclose") + EXPORT SYMBOL("gzerror") + EXPORT SYMBOL("inflate") + EXPORT SYMBOL("inflateEnd") + EXPORT SYMBOL("inflateSetDictionary") + EXPORT SYMBOL("inflateSync") + EXPORT SYMBOL("inflateReset") + EXPORT SYMBOL("inflateInit_") + EXPORT SYMBOL("inflateInit2_") + EXPORT SYMBOL("inflateSyncPoint") + EXPORT SYMBOL("uncompress") + EXPORT SYMBOL("zlibVersion") + EXPORT SYMBOL("zError") + EXPORT SYMBOL("z_errmsg") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.1 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("compressBound") + EXPORT SYMBOL("deflateBound") + EXPORT SYMBOL("deflatePending") + EXPORT SYMBOL("gzungetc") + EXPORT SYMBOL("gzclearerr") + EXPORT SYMBOL("inflateBack") + EXPORT SYMBOL("inflateBackEnd") + EXPORT SYMBOL("inflateBackInit_") + EXPORT SYMBOL("inflateCopy") + EXPORT SYMBOL("zlibCompileFlags") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.4 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("adler32_combine") + EXPORT SYMBOL("adler32_combine64") + EXPORT SYMBOL("crc32_combine") + EXPORT SYMBOL("crc32_combine64") + EXPORT SYMBOL("deflateSetHeader") + EXPORT SYMBOL("deflateTune") + EXPORT SYMBOL("gzbuffer") + EXPORT SYMBOL("gzclose_r") + EXPORT SYMBOL("gzclose_w") + EXPORT SYMBOL("gzdirect") + EXPORT SYMBOL("gzoffset") + EXPORT SYMBOL("gzoffset64") + EXPORT SYMBOL("gzopen64") + EXPORT SYMBOL("gzseek64") + EXPORT SYMBOL("gztell64") + EXPORT SYMBOL("inflateGetHeader") + EXPORT SYMBOL("inflateMark") + EXPORT SYMBOL("inflatePrime") + EXPORT SYMBOL("inflateReset2") + EXPORT SYMBOL("inflateUndermine") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.6 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("deflateResetKeep") + EXPORT SYMBOL("gzgetc_") + EXPORT SYMBOL("inflateResetKeep") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.8 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("gzvprintf") + EXPORT SYMBOL("inflateGetDictionary") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.9 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("adler32_z") + EXPORT SYMBOL("crc32_z") + EXPORT SYMBOL("deflateGetDictionary") + EXPORT SYMBOL("gzfread") + EXPORT SYMBOL("gzfwrite") + EXPORT SYMBOL("inflateCodesUsed") + EXPORT SYMBOL("inflateValidate") + EXPORT SYMBOL("uncompress2") + +ENDPGMEXP diff --git a/zlib-1.2.11/os400/make.sh b/zlib-1.2.11/os400/make.sh new file mode 100644 index 00000000..19eec117 --- /dev/null +++ b/zlib-1.2.11/os400/make.sh @@ -0,0 +1,366 @@ +#!/bin/sh +# +# ZLIB compilation script for the OS/400. +# +# +# This is a shell script since make is not a standard component of OS/400. + + +################################################################################ +# +# Tunable configuration parameters. +# +################################################################################ + +TARGETLIB='ZLIB' # Target OS/400 program library +STATBNDDIR='ZLIB_A' # Static binding directory. +DYNBNDDIR='ZLIB' # Dynamic binding directory. +SRVPGM="ZLIB" # Service program. +IFSDIR='/zlib' # IFS support base directory. +TGTCCSID='500' # Target CCSID of objects +DEBUG='*NONE' # Debug level +OPTIMIZE='40' # Optimisation level +OUTPUT='*NONE' # Compilation output option. +TGTRLS='V6R1M0' # Target OS release + +export TARGETLIB STATBNDDIR DYNBNDDIR SRVPGM IFSDIR +export TGTCCSID DEBUG OPTIMIZE OUTPUT TGTRLS + + +################################################################################ +# +# OS/400 specific definitions. +# +################################################################################ + +LIBIFSNAME="/QSYS.LIB/${TARGETLIB}.LIB" + + +################################################################################ +# +# Procedures. +# +################################################################################ + +# action_needed dest [src] +# +# dest is an object to build +# if specified, src is an object on which dest depends. +# +# exit 0 (succeeds) if some action has to be taken, else 1. + +action_needed() + +{ + [ ! -e "${1}" ] && return 0 + [ "${2}" ] || return 1 + [ "${1}" -ot "${2}" ] && return 0 + return 1 +} + + +# make_module module_name source_name [additional_definitions] +# +# Compile source name into module if needed. +# As side effect, append the module name to variable MODULES. +# Set LINK to "YES" if the module has been compiled. + +make_module() + +{ + MODULES="${MODULES} ${1}" + MODIFSNAME="${LIBIFSNAME}/${1}.MODULE" + CSRC="`basename \"${2}\"`" + + if action_needed "${MODIFSNAME}" "${2}" + then : + elif [ ! "`sed -e \"//,/<\\\\/source>/!d\" \ + -e '/ tmphdrfile + + # Need to translate to target CCSID. + + CMD="CPY OBJ('`pwd`/tmphdrfile') TOOBJ('${DEST}')" + CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)" + system "${CMD}" + # touch -r "${HFILE}" "${DEST}" + rm -f tmphdrfile + fi + + IFSFILE="${IFSDIR}/include/`basename \"${HFILE}\"`" + + if action_needed "${IFSFILE}" "${DEST}" + then rm -f "${IFSFILE}" + ln -s "${DEST}" "${IFSFILE}" + fi +done + + +# Install the ILE/RPG header file. + + +HFILE="${SCRIPTDIR}/zlib.inc" +DEST="${SRCPF}/ZLIB.INC.MBR" + +if action_needed "${DEST}" "${HFILE}" +then CMD="CPY OBJ('${HFILE}') TOOBJ('${DEST}')" + CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)" + system "${CMD}" + # touch -r "${HFILE}" "${DEST}" +fi + +IFSFILE="${IFSDIR}/include/`basename \"${HFILE}\"`" + +if action_needed "${IFSFILE}" "${DEST}" +then rm -f "${IFSFILE}" + ln -s "${DEST}" "${IFSFILE}" +fi + + +# Create and compile the identification source file. + +echo '#pragma comment(user, "ZLIB version '"${VERSION}"'")' > os400.c +echo '#pragma comment(user, __DATE__)' >> os400.c +echo '#pragma comment(user, __TIME__)' >> os400.c +echo '#pragma comment(copyright, "Copyright (C) 1995-2017 Jean-Loup Gailly, Mark Adler. OS/400 version by P. Monnerat.")' >> os400.c +make_module OS400 os400.c +LINK= # No need to rebuild service program yet. +MODULES= + + +# Get source list. + +CSOURCES=`sed -e '/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Library + + Medium + + 2.0 + + + + zlib + zlib + alain.bonnefoy@icbt.com + Public + public + www.gzip.org/zlib + + + Jean-Loup Gailly,Mark Adler + www.gzip.org/zlib + + zlib@gzip.org + + + A massively spiffy yet delicately unobtrusive compression library. + zlib is designed to be a free, general-purpose, legally unencumbered, lossless data compression library for use on virtually any computer hardware and operating system. + http://www.gzip.org/zlib + + + + + 1.2.11 + Medium + Stable + + + + + + + No License + + + + Software Development/Libraries and Extensions/C Libraries + zlib,compression + qnx6 + qnx6 + None + Developer + + + + + + + + + + + + + + Install + Post + No + Ignore + + No + Optional + + + + + + + + + + + + + InstallOver + zlib + + + + + + + + + + + + + InstallOver + zlib-dev + + + + + + + + + diff --git a/zlib-1.2.11/test/example.c b/zlib-1.2.11/test/example.c new file mode 100644 index 00000000..eee17ce7 --- /dev/null +++ b/zlib-1.2.11/test/example.c @@ -0,0 +1,602 @@ +/* example.c -- usage example of the zlib compression library + * Copyright (C) 1995-2006, 2011, 2016 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" +#include + +#ifdef STDC +# include +# include +#endif + +#if defined(VMS) || defined(RISCOS) +# define TESTFILE "foo-gz" +#else +# define TESTFILE "foo.gz" +#endif + +#define CHECK_ERR(err, msg) { \ + if (err != Z_OK) { \ + fprintf(stderr, "%s error: %d\n", msg, err); \ + exit(1); \ + } \ +} + +static z_const char hello[] = "hello, hello!"; +/* "hello world" would be more standard, but the repeated "hello" + * stresses the compression code better, sorry... + */ + +static const char dictionary[] = "hello"; +static uLong dictId; /* Adler32 value of the dictionary */ + +void test_deflate OF((Byte *compr, uLong comprLen)); +void test_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_deflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_flush OF((Byte *compr, uLong *comprLen)); +void test_sync OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_dict_deflate OF((Byte *compr, uLong comprLen)); +void test_dict_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +int main OF((int argc, char *argv[])); + + +#ifdef Z_SOLO + +void *myalloc OF((void *, unsigned, unsigned)); +void myfree OF((void *, void *)); + +void *myalloc(q, n, m) + void *q; + unsigned n, m; +{ + (void)q; + return calloc(n, m); +} + +void myfree(void *q, void *p) +{ + (void)q; + free(p); +} + +static alloc_func zalloc = myalloc; +static free_func zfree = myfree; + +#else /* !Z_SOLO */ + +static alloc_func zalloc = (alloc_func)0; +static free_func zfree = (free_func)0; + +void test_compress OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_gzio OF((const char *fname, + Byte *uncompr, uLong uncomprLen)); + +/* =========================================================================== + * Test compress() and uncompress() + */ +void test_compress(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + uLong len = (uLong)strlen(hello)+1; + + err = compress(compr, &comprLen, (const Bytef*)hello, len); + CHECK_ERR(err, "compress"); + + strcpy((char*)uncompr, "garbage"); + + err = uncompress(uncompr, &uncomprLen, compr, comprLen); + CHECK_ERR(err, "uncompress"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad uncompress\n"); + exit(1); + } else { + printf("uncompress(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test read/write of .gz files + */ +void test_gzio(fname, uncompr, uncomprLen) + const char *fname; /* compressed file name */ + Byte *uncompr; + uLong uncomprLen; +{ +#ifdef NO_GZCOMPRESS + fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); +#else + int err; + int len = (int)strlen(hello)+1; + gzFile file; + z_off_t pos; + + file = gzopen(fname, "wb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + gzputc(file, 'h'); + if (gzputs(file, "ello") != 4) { + fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); + exit(1); + } + if (gzprintf(file, ", %s!", "hello") != 8) { + fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); + exit(1); + } + gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ + gzclose(file); + + file = gzopen(fname, "rb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + strcpy((char*)uncompr, "garbage"); + + if (gzread(file, uncompr, (unsigned)uncomprLen) != len) { + fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); + exit(1); + } else { + printf("gzread(): %s\n", (char*)uncompr); + } + + pos = gzseek(file, -8L, SEEK_CUR); + if (pos != 6 || gztell(file) != pos) { + fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", + (long)pos, (long)gztell(file)); + exit(1); + } + + if (gzgetc(file) != ' ') { + fprintf(stderr, "gzgetc error\n"); + exit(1); + } + + if (gzungetc(' ', file) != ' ') { + fprintf(stderr, "gzungetc error\n"); + exit(1); + } + + gzgets(file, (char*)uncompr, (int)uncomprLen); + if (strlen((char*)uncompr) != 7) { /* " hello!" */ + fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello + 6)) { + fprintf(stderr, "bad gzgets after gzseek\n"); + exit(1); + } else { + printf("gzgets() after gzseek: %s\n", (char*)uncompr); + } + + gzclose(file); +#endif +} + +#endif /* Z_SOLO */ + +/* =========================================================================== + * Test deflate() with small buffers + */ +void test_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + uLong len = (uLong)strlen(hello)+1; + + c_stream.zalloc = zalloc; + c_stream.zfree = zfree; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != len && c_stream.total_out < comprLen) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + } + /* Finish the stream, still forcing small buffers: */ + for (;;) { + c_stream.avail_out = 1; + err = deflate(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "deflate"); + } + + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with small buffers + */ +void test_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = zalloc; + d_stream.zfree = zfree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 0; + d_stream.next_out = uncompr; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { + d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate\n"); + exit(1); + } else { + printf("inflate(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test deflate() with large buffers and dynamic change of compression level + */ +void test_large_deflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = zalloc; + c_stream.zfree = zfree; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_SPEED); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + /* At this point, uncompr is still mostly zeroes, so it should compress + * very well: + */ + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + if (c_stream.avail_in != 0) { + fprintf(stderr, "deflate not greedy\n"); + exit(1); + } + + /* Feed in already compressed data and switch to no compression: */ + deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); + c_stream.next_in = compr; + c_stream.avail_in = (uInt)comprLen/2; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + /* Switch back to compressing mode: */ + deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with large buffers + */ +void test_large_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = zalloc; + d_stream.zfree = zfree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + for (;;) { + d_stream.next_out = uncompr; /* discard the output */ + d_stream.avail_out = (uInt)uncomprLen; + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "large inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (d_stream.total_out != 2*uncomprLen + comprLen/2) { + fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); + exit(1); + } else { + printf("large_inflate(): OK\n"); + } +} + +/* =========================================================================== + * Test deflate() with full flush + */ +void test_flush(compr, comprLen) + Byte *compr; + uLong *comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + uInt len = (uInt)strlen(hello)+1; + + c_stream.zalloc = zalloc; + c_stream.zfree = zfree; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.next_out = compr; + c_stream.avail_in = 3; + c_stream.avail_out = (uInt)*comprLen; + err = deflate(&c_stream, Z_FULL_FLUSH); + CHECK_ERR(err, "deflate"); + + compr[3]++; /* force an error in first compressed block */ + c_stream.avail_in = len - 3; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + CHECK_ERR(err, "deflate"); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); + + *comprLen = c_stream.total_out; +} + +/* =========================================================================== + * Test inflateSync() + */ +void test_sync(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = zalloc; + d_stream.zfree = zfree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 2; /* just read the zlib header */ + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + err = inflate(&d_stream, Z_NO_FLUSH); + CHECK_ERR(err, "inflate"); + + d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ + err = inflateSync(&d_stream); /* but skip the damaged part */ + CHECK_ERR(err, "inflateSync"); + + err = inflate(&d_stream, Z_FINISH); + if (err != Z_DATA_ERROR) { + fprintf(stderr, "inflate should report DATA_ERROR\n"); + /* Because of incorrect adler32 */ + exit(1); + } + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + printf("after inflateSync(): hel%s\n", (char *)uncompr); +} + +/* =========================================================================== + * Test deflate() with preset dictionary + */ +void test_dict_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = zalloc; + c_stream.zfree = zfree; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + err = deflateSetDictionary(&c_stream, + (const Bytef*)dictionary, (int)sizeof(dictionary)); + CHECK_ERR(err, "deflateSetDictionary"); + + dictId = c_stream.adler; + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.avail_in = (uInt)strlen(hello)+1; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with a preset dictionary + */ +void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = zalloc; + d_stream.zfree = zfree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + for (;;) { + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + if (err == Z_NEED_DICT) { + if (d_stream.adler != dictId) { + fprintf(stderr, "unexpected dictionary"); + exit(1); + } + err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, + (int)sizeof(dictionary)); + } + CHECK_ERR(err, "inflate with dict"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate with dict\n"); + exit(1); + } else { + printf("inflate with dictionary: %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Usage: example [output.gz [input.gz]] + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + Byte *compr, *uncompr; + uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ + uLong uncomprLen = comprLen; + static const char* myVersion = ZLIB_VERSION; + + if (zlibVersion()[0] != myVersion[0]) { + fprintf(stderr, "incompatible zlib version\n"); + exit(1); + + } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { + fprintf(stderr, "warning: different zlib version\n"); + } + + printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", + ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); + + compr = (Byte*)calloc((uInt)comprLen, 1); + uncompr = (Byte*)calloc((uInt)uncomprLen, 1); + /* compr and uncompr are cleared to avoid reading uninitialized + * data and to ensure that uncompr compresses well. + */ + if (compr == Z_NULL || uncompr == Z_NULL) { + printf("out of memory\n"); + exit(1); + } + +#ifdef Z_SOLO + (void)argc; + (void)argv; +#else + test_compress(compr, comprLen, uncompr, uncomprLen); + + test_gzio((argc > 1 ? argv[1] : TESTFILE), + uncompr, uncomprLen); +#endif + + test_deflate(compr, comprLen); + test_inflate(compr, comprLen, uncompr, uncomprLen); + + test_large_deflate(compr, comprLen, uncompr, uncomprLen); + test_large_inflate(compr, comprLen, uncompr, uncomprLen); + + test_flush(compr, &comprLen); + test_sync(compr, comprLen, uncompr, uncomprLen); + comprLen = uncomprLen; + + test_dict_deflate(compr, comprLen); + test_dict_inflate(compr, comprLen, uncompr, uncomprLen); + + free(compr); + free(uncompr); + + return 0; +} diff --git a/zlib-1.2.11/test/infcover.c b/zlib-1.2.11/test/infcover.c new file mode 100644 index 00000000..2be01646 --- /dev/null +++ b/zlib-1.2.11/test/infcover.c @@ -0,0 +1,671 @@ +/* infcover.c -- test zlib's inflate routines with full code coverage + * Copyright (C) 2011, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* to use, do: ./configure --cover && make cover */ + +#include +#include +#include +#include +#include "zlib.h" + +/* get definition of internal structure so we can mess with it (see pull()), + and so we can call inflate_trees() (see cover5()) */ +#define ZLIB_INTERNAL +#include "inftrees.h" +#include "inflate.h" + +#define local static + +/* -- memory tracking routines -- */ + +/* + These memory tracking routines are provided to zlib and track all of zlib's + allocations and deallocations, check for LIFO operations, keep a current + and high water mark of total bytes requested, optionally set a limit on the + total memory that can be allocated, and when done check for memory leaks. + + They are used as follows: + + z_stream strm; + mem_setup(&strm) initializes the memory tracking and sets the + zalloc, zfree, and opaque members of strm to use + memory tracking for all zlib operations on strm + mem_limit(&strm, limit) sets a limit on the total bytes requested -- a + request that exceeds this limit will result in an + allocation failure (returns NULL) -- setting the + limit to zero means no limit, which is the default + after mem_setup() + mem_used(&strm, "msg") prints to stderr "msg" and the total bytes used + mem_high(&strm, "msg") prints to stderr "msg" and the high water mark + mem_done(&strm, "msg") ends memory tracking, releases all allocations + for the tracking as well as leaked zlib blocks, if + any. If there was anything unusual, such as leaked + blocks, non-FIFO frees, or frees of addresses not + allocated, then "msg" and information about the + problem is printed to stderr. If everything is + normal, nothing is printed. mem_done resets the + strm members to Z_NULL to use the default memory + allocation routines on the next zlib initialization + using strm. + */ + +/* these items are strung together in a linked list, one for each allocation */ +struct mem_item { + void *ptr; /* pointer to allocated memory */ + size_t size; /* requested size of allocation */ + struct mem_item *next; /* pointer to next item in list, or NULL */ +}; + +/* this structure is at the root of the linked list, and tracks statistics */ +struct mem_zone { + struct mem_item *first; /* pointer to first item in list, or NULL */ + size_t total, highwater; /* total allocations, and largest total */ + size_t limit; /* memory allocation limit, or 0 if no limit */ + int notlifo, rogue; /* counts of non-LIFO frees and rogue frees */ +}; + +/* memory allocation routine to pass to zlib */ +local void *mem_alloc(void *mem, unsigned count, unsigned size) +{ + void *ptr; + struct mem_item *item; + struct mem_zone *zone = mem; + size_t len = count * (size_t)size; + + /* induced allocation failure */ + if (zone == NULL || (zone->limit && zone->total + len > zone->limit)) + return NULL; + + /* perform allocation using the standard library, fill memory with a + non-zero value to make sure that the code isn't depending on zeros */ + ptr = malloc(len); + if (ptr == NULL) + return NULL; + memset(ptr, 0xa5, len); + + /* create a new item for the list */ + item = malloc(sizeof(struct mem_item)); + if (item == NULL) { + free(ptr); + return NULL; + } + item->ptr = ptr; + item->size = len; + + /* insert item at the beginning of the list */ + item->next = zone->first; + zone->first = item; + + /* update the statistics */ + zone->total += item->size; + if (zone->total > zone->highwater) + zone->highwater = zone->total; + + /* return the allocated memory */ + return ptr; +} + +/* memory free routine to pass to zlib */ +local void mem_free(void *mem, void *ptr) +{ + struct mem_item *item, *next; + struct mem_zone *zone = mem; + + /* if no zone, just do a free */ + if (zone == NULL) { + free(ptr); + return; + } + + /* point next to the item that matches ptr, or NULL if not found -- remove + the item from the linked list if found */ + next = zone->first; + if (next) { + if (next->ptr == ptr) + zone->first = next->next; /* first one is it, remove from list */ + else { + do { /* search the linked list */ + item = next; + next = item->next; + } while (next != NULL && next->ptr != ptr); + if (next) { /* if found, remove from linked list */ + item->next = next->next; + zone->notlifo++; /* not a LIFO free */ + } + + } + } + + /* if found, update the statistics and free the item */ + if (next) { + zone->total -= next->size; + free(next); + } + + /* if not found, update the rogue count */ + else + zone->rogue++; + + /* in any case, do the requested free with the standard library function */ + free(ptr); +} + +/* set up a controlled memory allocation space for monitoring, set the stream + parameters to the controlled routines, with opaque pointing to the space */ +local void mem_setup(z_stream *strm) +{ + struct mem_zone *zone; + + zone = malloc(sizeof(struct mem_zone)); + assert(zone != NULL); + zone->first = NULL; + zone->total = 0; + zone->highwater = 0; + zone->limit = 0; + zone->notlifo = 0; + zone->rogue = 0; + strm->opaque = zone; + strm->zalloc = mem_alloc; + strm->zfree = mem_free; +} + +/* set a limit on the total memory allocation, or 0 to remove the limit */ +local void mem_limit(z_stream *strm, size_t limit) +{ + struct mem_zone *zone = strm->opaque; + + zone->limit = limit; +} + +/* show the current total requested allocations in bytes */ +local void mem_used(z_stream *strm, char *prefix) +{ + struct mem_zone *zone = strm->opaque; + + fprintf(stderr, "%s: %lu allocated\n", prefix, zone->total); +} + +/* show the high water allocation in bytes */ +local void mem_high(z_stream *strm, char *prefix) +{ + struct mem_zone *zone = strm->opaque; + + fprintf(stderr, "%s: %lu high water mark\n", prefix, zone->highwater); +} + +/* release the memory allocation zone -- if there are any surprises, notify */ +local void mem_done(z_stream *strm, char *prefix) +{ + int count = 0; + struct mem_item *item, *next; + struct mem_zone *zone = strm->opaque; + + /* show high water mark */ + mem_high(strm, prefix); + + /* free leftover allocations and item structures, if any */ + item = zone->first; + while (item != NULL) { + free(item->ptr); + next = item->next; + free(item); + item = next; + count++; + } + + /* issue alerts about anything unexpected */ + if (count || zone->total) + fprintf(stderr, "** %s: %lu bytes in %d blocks not freed\n", + prefix, zone->total, count); + if (zone->notlifo) + fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo); + if (zone->rogue) + fprintf(stderr, "** %s: %d frees not recognized\n", + prefix, zone->rogue); + + /* free the zone and delete from the stream */ + free(zone); + strm->opaque = Z_NULL; + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; +} + +/* -- inflate test routines -- */ + +/* Decode a hexadecimal string, set *len to length, in[] to the bytes. This + decodes liberally, in that hex digits can be adjacent, in which case two in + a row writes a byte. Or they can be delimited by any non-hex character, + where the delimiters are ignored except when a single hex digit is followed + by a delimiter, where that single digit writes a byte. The returned data is + allocated and must eventually be freed. NULL is returned if out of memory. + If the length is not needed, then len can be NULL. */ +local unsigned char *h2b(const char *hex, unsigned *len) +{ + unsigned char *in, *re; + unsigned next, val; + + in = malloc((strlen(hex) + 1) >> 1); + if (in == NULL) + return NULL; + next = 0; + val = 1; + do { + if (*hex >= '0' && *hex <= '9') + val = (val << 4) + *hex - '0'; + else if (*hex >= 'A' && *hex <= 'F') + val = (val << 4) + *hex - 'A' + 10; + else if (*hex >= 'a' && *hex <= 'f') + val = (val << 4) + *hex - 'a' + 10; + else if (val != 1 && val < 32) /* one digit followed by delimiter */ + val += 240; /* make it look like two digits */ + if (val > 255) { /* have two digits */ + in[next++] = val & 0xff; /* save the decoded byte */ + val = 1; /* start over */ + } + } while (*hex++); /* go through the loop with the terminating null */ + if (len != NULL) + *len = next; + re = realloc(in, next); + return re == NULL ? in : re; +} + +/* generic inflate() run, where hex is the hexadecimal input data, what is the + text to include in an error message, step is how much input data to feed + inflate() on each call, or zero to feed it all, win is the window bits + parameter to inflateInit2(), len is the size of the output buffer, and err + is the error code expected from the first inflate() call (the second + inflate() call is expected to return Z_STREAM_END). If win is 47, then + header information is collected with inflateGetHeader(). If a zlib stream + is looking for a dictionary, then an empty dictionary is provided. + inflate() is run until all of the input data is consumed. */ +local void inf(char *hex, char *what, unsigned step, int win, unsigned len, + int err) +{ + int ret; + unsigned have; + unsigned char *in, *out; + z_stream strm, copy; + gz_header head; + + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, win); + if (ret != Z_OK) { + mem_done(&strm, what); + return; + } + out = malloc(len); assert(out != NULL); + if (win == 47) { + head.extra = out; + head.extra_max = len; + head.name = out; + head.name_max = len; + head.comment = out; + head.comm_max = len; + ret = inflateGetHeader(&strm, &head); assert(ret == Z_OK); + } + in = h2b(hex, &have); assert(in != NULL); + if (step == 0 || step > have) + step = have; + strm.avail_in = step; + have -= step; + strm.next_in = in; + do { + strm.avail_out = len; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); assert(err == 9 || ret == err); + if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_NEED_DICT) + break; + if (ret == Z_NEED_DICT) { + ret = inflateSetDictionary(&strm, in, 1); + assert(ret == Z_DATA_ERROR); + mem_limit(&strm, 1); + ret = inflateSetDictionary(&strm, out, 0); + assert(ret == Z_MEM_ERROR); + mem_limit(&strm, 0); + ((struct inflate_state *)strm.state)->mode = DICT; + ret = inflateSetDictionary(&strm, out, 0); + assert(ret == Z_OK); + ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_BUF_ERROR); + } + ret = inflateCopy(©, &strm); assert(ret == Z_OK); + ret = inflateEnd(©); assert(ret == Z_OK); + err = 9; /* don't care next time around */ + have += strm.avail_in; + strm.avail_in = step > have ? have : step; + have -= strm.avail_in; + } while (strm.avail_in); + free(in); + free(out); + ret = inflateReset2(&strm, -8); assert(ret == Z_OK); + ret = inflateEnd(&strm); assert(ret == Z_OK); + mem_done(&strm, what); +} + +/* cover all of the lines in inflate.c up to inflate() */ +local void cover_support(void) +{ + int ret; + z_stream strm; + + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); assert(ret == Z_OK); + mem_used(&strm, "inflate init"); + ret = inflatePrime(&strm, 5, 31); assert(ret == Z_OK); + ret = inflatePrime(&strm, -1, 0); assert(ret == Z_OK); + ret = inflateSetDictionary(&strm, Z_NULL, 0); + assert(ret == Z_STREAM_ERROR); + ret = inflateEnd(&strm); assert(ret == Z_OK); + mem_done(&strm, "prime"); + + inf("63 0", "force window allocation", 0, -15, 1, Z_OK); + inf("63 18 5", "force window replacement", 0, -8, 259, Z_OK); + inf("63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, Z_OK); + inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END); + inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR); + + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream)); + assert(ret == Z_VERSION_ERROR); + mem_done(&strm, "wrong version"); + + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); assert(ret == Z_OK); + ret = inflateEnd(&strm); assert(ret == Z_OK); + fputs("inflate built-in memory routines\n", stderr); +} + +/* cover all inflate() header and trailer cases and code after inflate() */ +local void cover_wrap(void) +{ + int ret; + z_stream strm, copy; + unsigned char dict[257]; + + ret = inflate(Z_NULL, 0); assert(ret == Z_STREAM_ERROR); + ret = inflateEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); + ret = inflateCopy(Z_NULL, Z_NULL); assert(ret == Z_STREAM_ERROR); + fputs("inflate bad parameters\n", stderr); + + inf("1f 8b 0 0", "bad gzip method", 0, 31, 0, Z_DATA_ERROR); + inf("1f 8b 8 80", "bad gzip flags", 0, 31, 0, Z_DATA_ERROR); + inf("77 85", "bad zlib method", 0, 15, 0, Z_DATA_ERROR); + inf("8 99", "set window size from header", 0, 0, 0, Z_OK); + inf("78 9c", "bad zlib window size", 0, 8, 0, Z_DATA_ERROR); + inf("78 9c 63 0 0 0 1 0 1", "check adler32", 0, 15, 1, Z_STREAM_END); + inf("1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1, + Z_DATA_ERROR); + inf("1f 8b 8 2 0 0 0 0 0 0 1d 26 3 0 0 0 0 0 0 0 0 0", "check gzip length", + 0, 47, 0, Z_STREAM_END); + inf("78 90", "bad zlib header check", 0, 47, 0, Z_DATA_ERROR); + inf("8 b8 0 0 0 1", "need dictionary", 0, 8, 0, Z_NEED_DICT); + inf("78 9c 63 0", "compute adler32", 0, 15, 1, Z_OK); + + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, -8); + strm.avail_in = 2; + strm.next_in = (void *)"\x63"; + strm.avail_out = 1; + strm.next_out = (void *)&ret; + mem_limit(&strm, 1); + ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); + ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); + mem_limit(&strm, 0); + memset(dict, 0, 257); + ret = inflateSetDictionary(&strm, dict, 257); + assert(ret == Z_OK); + mem_limit(&strm, (sizeof(struct inflate_state) << 1) + 256); + ret = inflatePrime(&strm, 16, 0); assert(ret == Z_OK); + strm.avail_in = 2; + strm.next_in = (void *)"\x80"; + ret = inflateSync(&strm); assert(ret == Z_DATA_ERROR); + ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_STREAM_ERROR); + strm.avail_in = 4; + strm.next_in = (void *)"\0\0\xff\xff"; + ret = inflateSync(&strm); assert(ret == Z_OK); + (void)inflateSyncPoint(&strm); + ret = inflateCopy(©, &strm); assert(ret == Z_MEM_ERROR); + mem_limit(&strm, 0); + ret = inflateUndermine(&strm, 1); assert(ret == Z_DATA_ERROR); + (void)inflateMark(&strm); + ret = inflateEnd(&strm); assert(ret == Z_OK); + mem_done(&strm, "miscellaneous, force memory errors"); +} + +/* input and output functions for inflateBack() */ +local unsigned pull(void *desc, unsigned char **buf) +{ + static unsigned int next = 0; + static unsigned char dat[] = {0x63, 0, 2, 0}; + struct inflate_state *state; + + if (desc == Z_NULL) { + next = 0; + return 0; /* no input (already provided at next_in) */ + } + state = (void *)((z_stream *)desc)->state; + if (state != Z_NULL) + state->mode = SYNC; /* force an otherwise impossible situation */ + return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0; +} + +local int push(void *desc, unsigned char *buf, unsigned len) +{ + buf += len; + return desc != Z_NULL; /* force error if desc not null */ +} + +/* cover inflateBack() up to common deflate data cases and after those */ +local void cover_back(void) +{ + int ret; + z_stream strm; + unsigned char win[32768]; + + ret = inflateBackInit_(Z_NULL, 0, win, 0, 0); + assert(ret == Z_VERSION_ERROR); + ret = inflateBackInit(Z_NULL, 0, win); assert(ret == Z_STREAM_ERROR); + ret = inflateBack(Z_NULL, Z_NULL, Z_NULL, Z_NULL, Z_NULL); + assert(ret == Z_STREAM_ERROR); + ret = inflateBackEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); + fputs("inflateBack bad parameters\n", stderr); + + mem_setup(&strm); + ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); + strm.avail_in = 2; + strm.next_in = (void *)"\x03"; + ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); + assert(ret == Z_STREAM_END); + /* force output error */ + strm.avail_in = 3; + strm.next_in = (void *)"\x63\x00"; + ret = inflateBack(&strm, pull, Z_NULL, push, &strm); + assert(ret == Z_BUF_ERROR); + /* force mode error by mucking with state */ + ret = inflateBack(&strm, pull, &strm, push, Z_NULL); + assert(ret == Z_STREAM_ERROR); + ret = inflateBackEnd(&strm); assert(ret == Z_OK); + mem_done(&strm, "inflateBack bad state"); + + ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); + ret = inflateBackEnd(&strm); assert(ret == Z_OK); + fputs("inflateBack built-in memory routines\n", stderr); +} + +/* do a raw inflate of data in hexadecimal with both inflate and inflateBack */ +local int try(char *hex, char *id, int err) +{ + int ret; + unsigned len, size; + unsigned char *in, *out, *win; + char *prefix; + z_stream strm; + + /* convert to hex */ + in = h2b(hex, &len); + assert(in != NULL); + + /* allocate work areas */ + size = len << 3; + out = malloc(size); + assert(out != NULL); + win = malloc(32768); + assert(win != NULL); + prefix = malloc(strlen(id) + 6); + assert(prefix != NULL); + + /* first with inflate */ + strcpy(prefix, id); + strcat(prefix, "-late"); + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, err < 0 ? 47 : -15); + assert(ret == Z_OK); + strm.avail_in = len; + strm.next_in = in; + do { + strm.avail_out = size; + strm.next_out = out; + ret = inflate(&strm, Z_TREES); + assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR); + if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT) + break; + } while (strm.avail_in || strm.avail_out == 0); + if (err) { + assert(ret == Z_DATA_ERROR); + assert(strcmp(id, strm.msg) == 0); + } + inflateEnd(&strm); + mem_done(&strm, prefix); + + /* then with inflateBack */ + if (err >= 0) { + strcpy(prefix, id); + strcat(prefix, "-back"); + mem_setup(&strm); + ret = inflateBackInit(&strm, 15, win); + assert(ret == Z_OK); + strm.avail_in = len; + strm.next_in = in; + ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); + assert(ret != Z_STREAM_ERROR); + if (err) { + assert(ret == Z_DATA_ERROR); + assert(strcmp(id, strm.msg) == 0); + } + inflateBackEnd(&strm); + mem_done(&strm, prefix); + } + + /* clean up */ + free(prefix); + free(win); + free(out); + free(in); + return ret; +} + +/* cover deflate data cases in both inflate() and inflateBack() */ +local void cover_inflate(void) +{ + try("0 0 0 0 0", "invalid stored block lengths", 1); + try("3 0", "fixed", 0); + try("6", "invalid block type", 1); + try("1 1 0 fe ff 0", "stored", 0); + try("fc 0 0", "too many length or distance symbols", 1); + try("4 0 fe ff", "invalid code lengths set", 1); + try("4 0 24 49 0", "invalid bit length repeat", 1); + try("4 0 24 e9 ff ff", "invalid bit length repeat", 1); + try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1); + try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0", + "invalid literal/lengths set", 1); + try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1); + try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1); + try("2 7e ff ff", "invalid distance code", 1); + try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1); + + /* also trailer mismatch just in inflate() */ + try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1); + try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1", + "incorrect length check", -1); + try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0); + try("5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f", + "long code", 0); + try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0); + try("ed cf c1 b1 2c 47 10 c4 30 fa 6f 35 1d 1 82 59 3d fb be 2e 2a fc f c", + "long distance and extra", 0); + try("ed c0 81 0 0 0 0 80 a0 fd a9 17 a9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0); + inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258, + Z_STREAM_END); + inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK); +} + +/* cover remaining lines in inftrees.c */ +local void cover_trees(void) +{ + int ret; + unsigned bits; + unsigned short lens[16], work[16]; + code *next, table[ENOUGH_DISTS]; + + /* we need to call inflate_table() directly in order to manifest not- + enough errors, since zlib insures that enough is always enough */ + for (bits = 0; bits < 15; bits++) + lens[bits] = (unsigned short)(bits + 1); + lens[15] = 15; + next = table; + bits = 15; + ret = inflate_table(DISTS, lens, 16, &next, &bits, work); + assert(ret == 1); + next = table; + bits = 1; + ret = inflate_table(DISTS, lens, 16, &next, &bits, work); + assert(ret == 1); + fputs("inflate_table not enough errors\n", stderr); +} + +/* cover remaining inffast.c decoding and window copying */ +local void cover_fast(void) +{ + inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68" + " ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR); + inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49" + " 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258, + Z_DATA_ERROR); + inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258, + Z_DATA_ERROR); + inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258, + Z_DATA_ERROR); + inf("d c7 1 ae eb 38 c 4 41 a0 87 72 de df fb 1f b8 36 b1 38 5d ff ff 0", + "fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR); + inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK); + inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0", + "contiguous and wrap around window", 6, -8, 259, Z_OK); + inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259, + Z_STREAM_END); +} + +int main(void) +{ + fprintf(stderr, "%s\n", zlibVersion()); + cover_support(); + cover_wrap(); + cover_back(); + cover_inflate(); + cover_trees(); + cover_fast(); + return 0; +} diff --git a/zlib-1.2.11/test/minigzip.c b/zlib-1.2.11/test/minigzip.c new file mode 100644 index 00000000..e22fb08c --- /dev/null +++ b/zlib-1.2.11/test/minigzip.c @@ -0,0 +1,651 @@ +/* minigzip.c -- simulate gzip using the zlib compression library + * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * minigzip is a minimal implementation of the gzip utility. This is + * only an example of using zlib and isn't meant to replace the + * full-featured gzip. No attempt is made to deal with file systems + * limiting names to 14 or 8+3 characters, etc... Error checking is + * very limited. So use minigzip only for testing; use gzip for the + * real thing. On MSDOS, use only on file names without extension + * or in pipe mode. + */ + +/* @(#) $Id$ */ + +#include "zlib.h" +#include + +#ifdef STDC +# include +# include +#endif + +#ifdef USE_MMAP +# include +# include +# include +#endif + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) +# include +# include +# ifdef UNDER_CE +# include +# endif +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1900 +# define snprintf _snprintf +#endif + +#ifdef VMS +# define unlink delete +# define GZ_SUFFIX "-gz" +#endif +#ifdef RISCOS +# define unlink remove +# define GZ_SUFFIX "-gz" +# define fileno(file) file->__file +#endif +#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fileno */ +#endif + +#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) +#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ + extern int unlink OF((const char *)); +#endif +#endif + +#if defined(UNDER_CE) +# include +# define perror(s) pwinerror(s) + +/* Map the Windows error number in ERROR to a locale-dependent error + message string and return a pointer to it. Typically, the values + for ERROR come from GetLastError. + + The string pointed to shall not be modified by the application, + but may be overwritten by a subsequent call to strwinerror + + The strwinerror function does not change the current setting + of GetLastError. */ + +static char *strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +static void pwinerror (s) + const char *s; +{ + if (s && *s) + fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ())); + else + fprintf(stderr, "%s\n", strwinerror(GetLastError ())); +} + +#endif /* UNDER_CE */ + +#ifndef GZ_SUFFIX +# define GZ_SUFFIX ".gz" +#endif +#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) + +#define BUFLEN 16384 +#define MAX_NAME_LEN 1024 + +#ifdef MAXSEG_64K +# define local static + /* Needed for systems with limitation on stack size. */ +#else +# define local +#endif + +#ifdef Z_SOLO +/* for Z_SOLO, create simplified gz* functions using deflate and inflate */ + +#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE) +# include /* for unlink() */ +#endif + +void *myalloc OF((void *, unsigned, unsigned)); +void myfree OF((void *, void *)); + +void *myalloc(q, n, m) + void *q; + unsigned n, m; +{ + (void)q; + return calloc(n, m); +} + +void myfree(q, p) + void *q, *p; +{ + (void)q; + free(p); +} + +typedef struct gzFile_s { + FILE *file; + int write; + int err; + char *msg; + z_stream strm; +} *gzFile; + +gzFile gzopen OF((const char *, const char *)); +gzFile gzdopen OF((int, const char *)); +gzFile gz_open OF((const char *, int, const char *)); + +gzFile gzopen(path, mode) +const char *path; +const char *mode; +{ + return gz_open(path, -1, mode); +} + +gzFile gzdopen(fd, mode) +int fd; +const char *mode; +{ + return gz_open(NULL, fd, mode); +} + +gzFile gz_open(path, fd, mode) + const char *path; + int fd; + const char *mode; +{ + gzFile gz; + int ret; + + gz = malloc(sizeof(struct gzFile_s)); + if (gz == NULL) + return NULL; + gz->write = strchr(mode, 'w') != NULL; + gz->strm.zalloc = myalloc; + gz->strm.zfree = myfree; + gz->strm.opaque = Z_NULL; + if (gz->write) + ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0); + else { + gz->strm.next_in = 0; + gz->strm.avail_in = Z_NULL; + ret = inflateInit2(&(gz->strm), 15 + 16); + } + if (ret != Z_OK) { + free(gz); + return NULL; + } + gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") : + fopen(path, gz->write ? "wb" : "rb"); + if (gz->file == NULL) { + gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm)); + free(gz); + return NULL; + } + gz->err = 0; + gz->msg = ""; + return gz; +} + +int gzwrite OF((gzFile, const void *, unsigned)); + +int gzwrite(gz, buf, len) + gzFile gz; + const void *buf; + unsigned len; +{ + z_stream *strm; + unsigned char out[BUFLEN]; + + if (gz == NULL || !gz->write) + return 0; + strm = &(gz->strm); + strm->next_in = (void *)buf; + strm->avail_in = len; + do { + strm->next_out = out; + strm->avail_out = BUFLEN; + (void)deflate(strm, Z_NO_FLUSH); + fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); + } while (strm->avail_out == 0); + return len; +} + +int gzread OF((gzFile, void *, unsigned)); + +int gzread(gz, buf, len) + gzFile gz; + void *buf; + unsigned len; +{ + int ret; + unsigned got; + unsigned char in[1]; + z_stream *strm; + + if (gz == NULL || gz->write) + return 0; + if (gz->err) + return 0; + strm = &(gz->strm); + strm->next_out = (void *)buf; + strm->avail_out = len; + do { + got = fread(in, 1, 1, gz->file); + if (got == 0) + break; + strm->next_in = in; + strm->avail_in = 1; + ret = inflate(strm, Z_NO_FLUSH); + if (ret == Z_DATA_ERROR) { + gz->err = Z_DATA_ERROR; + gz->msg = strm->msg; + return 0; + } + if (ret == Z_STREAM_END) + inflateReset(strm); + } while (strm->avail_out); + return len - strm->avail_out; +} + +int gzclose OF((gzFile)); + +int gzclose(gz) + gzFile gz; +{ + z_stream *strm; + unsigned char out[BUFLEN]; + + if (gz == NULL) + return Z_STREAM_ERROR; + strm = &(gz->strm); + if (gz->write) { + strm->next_in = Z_NULL; + strm->avail_in = 0; + do { + strm->next_out = out; + strm->avail_out = BUFLEN; + (void)deflate(strm, Z_FINISH); + fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); + } while (strm->avail_out == 0); + deflateEnd(strm); + } + else + inflateEnd(strm); + fclose(gz->file); + free(gz); + return Z_OK; +} + +const char *gzerror OF((gzFile, int *)); + +const char *gzerror(gz, err) + gzFile gz; + int *err; +{ + *err = gz->err; + return gz->msg; +} + +#endif + +static char *prog; + +void error OF((const char *msg)); +void gz_compress OF((FILE *in, gzFile out)); +#ifdef USE_MMAP +int gz_compress_mmap OF((FILE *in, gzFile out)); +#endif +void gz_uncompress OF((gzFile in, FILE *out)); +void file_compress OF((char *file, char *mode)); +void file_uncompress OF((char *file)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Display error message and exit + */ +void error(msg) + const char *msg; +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + +/* =========================================================================== + * Compress input to output then close both files. + */ + +void gz_compress(in, out) + FILE *in; + gzFile out; +{ + local char buf[BUFLEN]; + int len; + int err; + +#ifdef USE_MMAP + /* Try first compressing with mmap. If mmap fails (minigzip used in a + * pipe), use the normal fread loop. + */ + if (gz_compress_mmap(in, out) == Z_OK) return; +#endif + for (;;) { + len = (int)fread(buf, 1, sizeof(buf), in); + if (ferror(in)) { + perror("fread"); + exit(1); + } + if (len == 0) break; + + if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); + } + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); +} + +#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ + +/* Try compressing the input file at once using mmap. Return Z_OK if + * if success, Z_ERRNO otherwise. + */ +int gz_compress_mmap(in, out) + FILE *in; + gzFile out; +{ + int len; + int err; + int ifd = fileno(in); + caddr_t buf; /* mmap'ed buffer for the entire input file */ + off_t buf_len; /* length of the input file */ + struct stat sb; + + /* Determine the size of the file, needed for mmap: */ + if (fstat(ifd, &sb) < 0) return Z_ERRNO; + buf_len = sb.st_size; + if (buf_len <= 0) return Z_ERRNO; + + /* Now do the actual mmap: */ + buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); + if (buf == (caddr_t)(-1)) return Z_ERRNO; + + /* Compress the whole file at once: */ + len = gzwrite(out, (char *)buf, (unsigned)buf_len); + + if (len != (int)buf_len) error(gzerror(out, &err)); + + munmap(buf, buf_len); + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); + return Z_OK; +} +#endif /* USE_MMAP */ + +/* =========================================================================== + * Uncompress input to output then close both files. + */ +void gz_uncompress(in, out) + gzFile in; + FILE *out; +{ + local char buf[BUFLEN]; + int len; + int err; + + for (;;) { + len = gzread(in, buf, sizeof(buf)); + if (len < 0) error (gzerror(in, &err)); + if (len == 0) break; + + if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { + error("failed fwrite"); + } + } + if (fclose(out)) error("failed fclose"); + + if (gzclose(in) != Z_OK) error("failed gzclose"); +} + + +/* =========================================================================== + * Compress the given file: create a corresponding .gz file and remove the + * original. + */ +void file_compress(file, mode) + char *file; + char *mode; +{ + local char outfile[MAX_NAME_LEN]; + FILE *in; + gzFile out; + + if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { + fprintf(stderr, "%s: filename too long\n", prog); + exit(1); + } + +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX); +#else + strcpy(outfile, file); + strcat(outfile, GZ_SUFFIX); +#endif + + in = fopen(file, "rb"); + if (in == NULL) { + perror(file); + exit(1); + } + out = gzopen(outfile, mode); + if (out == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); + exit(1); + } + gz_compress(in, out); + + unlink(file); +} + + +/* =========================================================================== + * Uncompress the given file and remove the original. + */ +void file_uncompress(file) + char *file; +{ + local char buf[MAX_NAME_LEN]; + char *infile, *outfile; + FILE *out; + gzFile in; + unsigned len = strlen(file); + + if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { + fprintf(stderr, "%s: filename too long\n", prog); + exit(1); + } + +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(buf, sizeof(buf), "%s", file); +#else + strcpy(buf, file); +#endif + + if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { + infile = file; + outfile = buf; + outfile[len-3] = '\0'; + } else { + outfile = file; + infile = buf; +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX); +#else + strcat(infile, GZ_SUFFIX); +#endif + } + in = gzopen(infile, "rb"); + if (in == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); + exit(1); + } + out = fopen(outfile, "wb"); + if (out == NULL) { + perror(file); + exit(1); + } + + gz_uncompress(in, out); + + unlink(infile); +} + + +/* =========================================================================== + * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...] + * -c : write to standard output + * -d : decompress + * -f : compress with Z_FILTERED + * -h : compress with Z_HUFFMAN_ONLY + * -r : compress with Z_RLE + * -1 to -9 : compression level + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + int copyout = 0; + int uncompr = 0; + gzFile file; + char *bname, outmode[20]; + +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(outmode, sizeof(outmode), "%s", "wb6 "); +#else + strcpy(outmode, "wb6 "); +#endif + + prog = argv[0]; + bname = strrchr(argv[0], '/'); + if (bname) + bname++; + else + bname = argv[0]; + argc--, argv++; + + if (!strcmp(bname, "gunzip")) + uncompr = 1; + else if (!strcmp(bname, "zcat")) + copyout = uncompr = 1; + + while (argc > 0) { + if (strcmp(*argv, "-c") == 0) + copyout = 1; + else if (strcmp(*argv, "-d") == 0) + uncompr = 1; + else if (strcmp(*argv, "-f") == 0) + outmode[3] = 'f'; + else if (strcmp(*argv, "-h") == 0) + outmode[3] = 'h'; + else if (strcmp(*argv, "-r") == 0) + outmode[3] = 'R'; + else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && + (*argv)[2] == 0) + outmode[2] = (*argv)[1]; + else + break; + argc--, argv++; + } + if (outmode[3] == ' ') + outmode[3] = 0; + if (argc == 0) { + SET_BINARY_MODE(stdin); + SET_BINARY_MODE(stdout); + if (uncompr) { + file = gzdopen(fileno(stdin), "rb"); + if (file == NULL) error("can't gzdopen stdin"); + gz_uncompress(file, stdout); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + gz_compress(stdin, file); + } + } else { + if (copyout) { + SET_BINARY_MODE(stdout); + } + do { + if (uncompr) { + if (copyout) { + file = gzopen(*argv, "rb"); + if (file == NULL) + fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv); + else + gz_uncompress(file, stdout); + } else { + file_uncompress(*argv); + } + } else { + if (copyout) { + FILE * in = fopen(*argv, "rb"); + + if (in == NULL) { + perror(*argv); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + + gz_compress(in, file); + } + + } else { + file_compress(*argv, outmode); + } + } + } while (argv++, --argc); + } + return 0; +} diff --git a/zlib-1.2.11/treebuild.xml b/zlib-1.2.11/treebuild.xml new file mode 100644 index 00000000..fd75525f --- /dev/null +++ b/zlib-1.2.11/treebuild.xml @@ -0,0 +1,116 @@ + + + + zip compression library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zlib-1.2.11/trees.c b/zlib-1.2.11/trees.c new file mode 100644 index 00000000..50cf4b45 --- /dev/null +++ b/zlib-1.2.11/trees.c @@ -0,0 +1,1203 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2017 Jean-loup Gailly + * detect_data_type() function provided freely by Cosmin Truta, 2006 + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef ZLIB_DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local const static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local const static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local const static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, const ct_data *ltree, + const ct_data *dtree)); +local int detect_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef ZLIB_DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* !ZLIB_DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef ZLIB_DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (ush)value << s->bi_valid; + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= (ush)value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !ZLIB_DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = (int)value;\ + s->bi_buf |= (ush)val << s->bi_valid;\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (ush)(value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* ZLIB_DEBUG */ + + +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ +#ifdef NO_INIT_GLOBAL_POINTERS + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; +#endif + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef ZLIB_DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, + "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void ZLIB_INTERNAL _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef ZLIB_DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (unsigned)(bits + xbits); + if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); + } + if (overflow == 0) return; + + Tracev((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if ((unsigned) tree[m].Len != (unsigned) bits) { + Tracev((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((ulg)bits - tree[m].Len) * tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + unsigned code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + code = (code + bl_count[bits-1]) << 1; + next_code[bits] = (ush)code; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? + s->depth[n] : s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */ + bi_windup(s); /* align on byte boundary */ + put_short(s, (ush)stored_len); + put_short(s, (ush)~stored_len); + zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len); + s->pending += stored_len; +#ifdef ZLIB_DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; + s->bits_sent += 2*16; + s->bits_sent += stored_len<<3; +#endif +} + +/* =========================================================================== + * Flush the bits in the bit buffer to pending output (leaves at most 7 bits) + */ +void ZLIB_INTERNAL _tr_flush_bits(s) + deflate_state *s; +{ + bi_flush(s); +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + */ +void ZLIB_INTERNAL _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef ZLIB_DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and write out the encoded block. + */ +void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int last; /* one if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is binary or text */ + if (s->strm->data_type == Z_UNKNOWN) + s->strm->data_type = detect_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute the block lengths in bytes. */ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, last); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+last, 3); + compress_block(s, (const ct_data *)static_ltree, + (const ct_data *)static_dtree); +#ifdef ZLIB_DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+last, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (const ct_data *)s->dyn_ltree, + (const ct_data *)s->dyn_dtree); +#ifdef ZLIB_DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (last) { + bi_windup(s); +#ifdef ZLIB_DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*last)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int ZLIB_INTERNAL _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + const ct_data *ltree; /* literal tree */ + const ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= (unsigned)base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, + "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); +} + +/* =========================================================================== + * Check if the data type is TEXT or BINARY, using the following algorithm: + * - TEXT if the two conditions below are satisfied: + * a) There are no non-portable control characters belonging to the + * "black list" (0..6, 14..25, 28..31). + * b) There is at least one printable character belonging to the + * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). + * - BINARY otherwise. + * - The following partially-portable control characters form a + * "gray list" that is ignored in this detection algorithm: + * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). + * IN assertion: the fields Freq of dyn_ltree are set. + */ +local int detect_data_type(s) + deflate_state *s; +{ + /* black_mask is the bit mask of black-listed bytes + * set bits 0..6, 14..25, and 28..31 + * 0xf3ffc07f = binary 11110011111111111100000001111111 + */ + unsigned long black_mask = 0xf3ffc07fUL; + int n; + + /* Check for non-textual ("black-listed") bytes. */ + for (n = 0; n <= 31; n++, black_mask >>= 1) + if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0)) + return Z_BINARY; + + /* Check for textual ("white-listed") bytes. */ + if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0 + || s->dyn_ltree[13].Freq != 0) + return Z_TEXT; + for (n = 32; n < LITERALS; n++) + if (s->dyn_ltree[n].Freq != 0) + return Z_TEXT; + + /* There are no "black-listed" or "white-listed" bytes: + * this stream either is empty or has tolerated ("gray-listed") bytes only. + */ + return Z_BINARY; +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef ZLIB_DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} diff --git a/zlib-1.2.11/trees.h b/zlib-1.2.11/trees.h new file mode 100644 index 00000000..d35639d8 --- /dev/null +++ b/zlib-1.2.11/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/zlib-1.2.11/uncompr.c b/zlib-1.2.11/uncompr.c new file mode 100644 index 00000000..f03a1a86 --- /dev/null +++ b/zlib-1.2.11/uncompr.c @@ -0,0 +1,93 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#define ZLIB_INTERNAL +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. *sourceLen is + the byte length of the source buffer. Upon entry, *destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, + *destLen is the size of the decompressed data and *sourceLen is the number + of source bytes consumed. Upon return, source + *sourceLen points to the + first unused input byte. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, or + Z_DATA_ERROR if the input data was corrupted, including if the input data is + an incomplete zlib stream. +*/ +int ZEXPORT uncompress2 (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong *sourceLen; +{ + z_stream stream; + int err; + const uInt max = (uInt)-1; + uLong len, left; + Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */ + + len = *sourceLen; + if (*destLen) { + left = *destLen; + *destLen = 0; + } + else { + left = 1; + dest = buf; + } + + stream.next_in = (z_const Bytef *)source; + stream.avail_in = 0; + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + stream.next_out = dest; + stream.avail_out = 0; + + do { + if (stream.avail_out == 0) { + stream.avail_out = left > (uLong)max ? max : (uInt)left; + left -= stream.avail_out; + } + if (stream.avail_in == 0) { + stream.avail_in = len > (uLong)max ? max : (uInt)len; + len -= stream.avail_in; + } + err = inflate(&stream, Z_NO_FLUSH); + } while (err == Z_OK); + + *sourceLen -= len + stream.avail_in; + if (dest != buf) + *destLen = stream.total_out; + else if (stream.total_out && err == Z_BUF_ERROR) + left = 1; + + inflateEnd(&stream); + return err == Z_STREAM_END ? Z_OK : + err == Z_NEED_DICT ? Z_DATA_ERROR : + err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR : + err; +} + +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return uncompress2(dest, destLen, source, &sourceLen); +} diff --git a/zlib-1.2.11/watcom/watcom_f.mak b/zlib-1.2.11/watcom/watcom_f.mak new file mode 100644 index 00000000..37f4d74c --- /dev/null +++ b/zlib-1.2.11/watcom/watcom_f.mak @@ -0,0 +1,43 @@ +# Makefile for zlib +# OpenWatcom flat model +# Last updated: 28-Dec-2005 + +# To use, do "wmake -f watcom_f.mak" + +C_SOURCE = adler32.c compress.c crc32.c deflate.c & + gzclose.c gzlib.c gzread.c gzwrite.c & + infback.c inffast.c inflate.c inftrees.c & + trees.c uncompr.c zutil.c + +OBJS = adler32.obj compress.obj crc32.obj deflate.obj & + gzclose.obj gzlib.obj gzread.obj gzwrite.obj & + infback.obj inffast.obj inflate.obj inftrees.obj & + trees.obj uncompr.obj zutil.obj + +CC = wcc386 +LINKER = wcl386 +CFLAGS = -zq -mf -3r -fp3 -s -bt=dos -oilrtfm -fr=nul -wx +ZLIB_LIB = zlib_f.lib + +.C.OBJ: + $(CC) $(CFLAGS) $[@ + +all: $(ZLIB_LIB) example.exe minigzip.exe + +$(ZLIB_LIB): $(OBJS) + wlib -b -c $(ZLIB_LIB) -+adler32.obj -+compress.obj -+crc32.obj + wlib -b -c $(ZLIB_LIB) -+gzclose.obj -+gzlib.obj -+gzread.obj -+gzwrite.obj + wlib -b -c $(ZLIB_LIB) -+deflate.obj -+infback.obj + wlib -b -c $(ZLIB_LIB) -+inffast.obj -+inflate.obj -+inftrees.obj + wlib -b -c $(ZLIB_LIB) -+trees.obj -+uncompr.obj -+zutil.obj + +example.exe: $(ZLIB_LIB) example.obj + $(LINKER) -ldos32a -fe=example.exe example.obj $(ZLIB_LIB) + +minigzip.exe: $(ZLIB_LIB) minigzip.obj + $(LINKER) -ldos32a -fe=minigzip.exe minigzip.obj $(ZLIB_LIB) + +clean: .SYMBOLIC + del *.obj + del $(ZLIB_LIB) + @echo Cleaning done diff --git a/zlib-1.2.11/watcom/watcom_l.mak b/zlib-1.2.11/watcom/watcom_l.mak new file mode 100644 index 00000000..193eed7b --- /dev/null +++ b/zlib-1.2.11/watcom/watcom_l.mak @@ -0,0 +1,43 @@ +# Makefile for zlib +# OpenWatcom large model +# Last updated: 28-Dec-2005 + +# To use, do "wmake -f watcom_l.mak" + +C_SOURCE = adler32.c compress.c crc32.c deflate.c & + gzclose.c gzlib.c gzread.c gzwrite.c & + infback.c inffast.c inflate.c inftrees.c & + trees.c uncompr.c zutil.c + +OBJS = adler32.obj compress.obj crc32.obj deflate.obj & + gzclose.obj gzlib.obj gzread.obj gzwrite.obj & + infback.obj inffast.obj inflate.obj inftrees.obj & + trees.obj uncompr.obj zutil.obj + +CC = wcc +LINKER = wcl +CFLAGS = -zq -ml -s -bt=dos -oilrtfm -fr=nul -wx +ZLIB_LIB = zlib_l.lib + +.C.OBJ: + $(CC) $(CFLAGS) $[@ + +all: $(ZLIB_LIB) example.exe minigzip.exe + +$(ZLIB_LIB): $(OBJS) + wlib -b -c $(ZLIB_LIB) -+adler32.obj -+compress.obj -+crc32.obj + wlib -b -c $(ZLIB_LIB) -+gzclose.obj -+gzlib.obj -+gzread.obj -+gzwrite.obj + wlib -b -c $(ZLIB_LIB) -+deflate.obj -+infback.obj + wlib -b -c $(ZLIB_LIB) -+inffast.obj -+inflate.obj -+inftrees.obj + wlib -b -c $(ZLIB_LIB) -+trees.obj -+uncompr.obj -+zutil.obj + +example.exe: $(ZLIB_LIB) example.obj + $(LINKER) -fe=example.exe example.obj $(ZLIB_LIB) + +minigzip.exe: $(ZLIB_LIB) minigzip.obj + $(LINKER) -fe=minigzip.exe minigzip.obj $(ZLIB_LIB) + +clean: .SYMBOLIC + del *.obj + del $(ZLIB_LIB) + @echo Cleaning done diff --git a/zlib-1.2.11/win32/DLL_FAQ.txt b/zlib-1.2.11/win32/DLL_FAQ.txt new file mode 100644 index 00000000..12c00901 --- /dev/null +++ b/zlib-1.2.11/win32/DLL_FAQ.txt @@ -0,0 +1,397 @@ + + Frequently Asked Questions about ZLIB1.DLL + + +This document describes the design, the rationale, and the usage +of the official DLL build of zlib, named ZLIB1.DLL. If you have +general questions about zlib, you should see the file "FAQ" found +in the zlib distribution, or at the following location: + http://www.gzip.org/zlib/zlib_faq.html + + + 1. What is ZLIB1.DLL, and how can I get it? + + - ZLIB1.DLL is the official build of zlib as a DLL. + (Please remark the character '1' in the name.) + + Pointers to a precompiled ZLIB1.DLL can be found in the zlib + web site at: + http://www.zlib.net/ + + Applications that link to ZLIB1.DLL can rely on the following + specification: + + * The exported symbols are exclusively defined in the source + files "zlib.h" and "zlib.def", found in an official zlib + source distribution. + * The symbols are exported by name, not by ordinal. + * The exported names are undecorated. + * The calling convention of functions is "C" (CDECL). + * The ZLIB1.DLL binary is linked to MSVCRT.DLL. + + The archive in which ZLIB1.DLL is bundled contains compiled + test programs that must run with a valid build of ZLIB1.DLL. + It is recommended to download the prebuilt DLL from the zlib + web site, instead of building it yourself, to avoid potential + incompatibilities that could be introduced by your compiler + and build settings. If you do build the DLL yourself, please + make sure that it complies with all the above requirements, + and it runs with the precompiled test programs, bundled with + the original ZLIB1.DLL distribution. + + If, for any reason, you need to build an incompatible DLL, + please use a different file name. + + + 2. Why did you change the name of the DLL to ZLIB1.DLL? + What happened to the old ZLIB.DLL? + + - The old ZLIB.DLL, built from zlib-1.1.4 or earlier, required + compilation settings that were incompatible to those used by + a static build. The DLL settings were supposed to be enabled + by defining the macro ZLIB_DLL, before including "zlib.h". + Incorrect handling of this macro was silently accepted at + build time, resulting in two major problems: + + * ZLIB_DLL was missing from the old makefile. When building + the DLL, not all people added it to the build options. In + consequence, incompatible incarnations of ZLIB.DLL started + to circulate around the net. + + * When switching from using the static library to using the + DLL, applications had to define the ZLIB_DLL macro and + to recompile all the sources that contained calls to zlib + functions. Failure to do so resulted in creating binaries + that were unable to run with the official ZLIB.DLL build. + + The only possible solution that we could foresee was to make + a binary-incompatible change in the DLL interface, in order to + remove the dependency on the ZLIB_DLL macro, and to release + the new DLL under a different name. + + We chose the name ZLIB1.DLL, where '1' indicates the major + zlib version number. We hope that we will not have to break + the binary compatibility again, at least not as long as the + zlib-1.x series will last. + + There is still a ZLIB_DLL macro, that can trigger a more + efficient build and use of the DLL, but compatibility no + longer dependents on it. + + + 3. Can I build ZLIB.DLL from the new zlib sources, and replace + an old ZLIB.DLL, that was built from zlib-1.1.4 or earlier? + + - In principle, you can do it by assigning calling convention + keywords to the macros ZEXPORT and ZEXPORTVA. In practice, + it depends on what you mean by "an old ZLIB.DLL", because the + old DLL exists in several mutually-incompatible versions. + You have to find out first what kind of calling convention is + being used in your particular ZLIB.DLL build, and to use the + same one in the new build. If you don't know what this is all + about, you might be better off if you would just leave the old + DLL intact. + + + 4. Can I compile my application using the new zlib interface, and + link it to an old ZLIB.DLL, that was built from zlib-1.1.4 or + earlier? + + - The official answer is "no"; the real answer depends again on + what kind of ZLIB.DLL you have. Even if you are lucky, this + course of action is unreliable. + + If you rebuild your application and you intend to use a newer + version of zlib (post- 1.1.4), it is strongly recommended to + link it to the new ZLIB1.DLL. + + + 5. Why are the zlib symbols exported by name, and not by ordinal? + + - Although exporting symbols by ordinal is a little faster, it + is risky. Any single glitch in the maintenance or use of the + DEF file that contains the ordinals can result in incompatible + builds and frustrating crashes. Simply put, the benefits of + exporting symbols by ordinal do not justify the risks. + + Technically, it should be possible to maintain ordinals in + the DEF file, and still export the symbols by name. Ordinals + exist in every DLL, and even if the dynamic linking performed + at the DLL startup is searching for names, ordinals serve as + hints, for a faster name lookup. However, if the DEF file + contains ordinals, the Microsoft linker automatically builds + an implib that will cause the executables linked to it to use + those ordinals, and not the names. It is interesting to + notice that the GNU linker for Win32 does not suffer from this + problem. + + It is possible to avoid the DEF file if the exported symbols + are accompanied by a "__declspec(dllexport)" attribute in the + source files. You can do this in zlib by predefining the + ZLIB_DLL macro. + + + 6. I see that the ZLIB1.DLL functions use the "C" (CDECL) calling + convention. Why not use the STDCALL convention? + STDCALL is the standard convention in Win32, and I need it in + my Visual Basic project! + + (For readability, we use CDECL to refer to the convention + triggered by the "__cdecl" keyword, STDCALL to refer to + the convention triggered by "__stdcall", and FASTCALL to + refer to the convention triggered by "__fastcall".) + + - Most of the native Windows API functions (without varargs) use + indeed the WINAPI convention (which translates to STDCALL in + Win32), but the standard C functions use CDECL. If a user + application is intrinsically tied to the Windows API (e.g. + it calls native Windows API functions such as CreateFile()), + sometimes it makes sense to decorate its own functions with + WINAPI. But if ANSI C or POSIX portability is a goal (e.g. + it calls standard C functions such as fopen()), it is not a + sound decision to request the inclusion of , or to + use non-ANSI constructs, for the sole purpose to make the user + functions STDCALL-able. + + The functionality offered by zlib is not in the category of + "Windows functionality", but is more like "C functionality". + + Technically, STDCALL is not bad; in fact, it is slightly + faster than CDECL, and it works with variable-argument + functions, just like CDECL. It is unfortunate that, in spite + of using STDCALL in the Windows API, it is not the default + convention used by the C compilers that run under Windows. + The roots of the problem reside deep inside the unsafety of + the K&R-style function prototypes, where the argument types + are not specified; but that is another story for another day. + + The remaining fact is that CDECL is the default convention. + Even if an explicit convention is hard-coded into the function + prototypes inside C headers, problems may appear. The + necessity to expose the convention in users' callbacks is one + of these problems. + + The calling convention issues are also important when using + zlib in other programming languages. Some of them, like Ada + (GNAT) and Fortran (GNU G77), have C bindings implemented + initially on Unix, and relying on the C calling convention. + On the other hand, the pre- .NET versions of Microsoft Visual + Basic require STDCALL, while Borland Delphi prefers, although + it does not require, FASTCALL. + + In fairness to all possible uses of zlib outside the C + programming language, we choose the default "C" convention. + Anyone interested in different bindings or conventions is + encouraged to maintain specialized projects. The "contrib/" + directory from the zlib distribution already holds a couple + of foreign bindings, such as Ada, C++, and Delphi. + + + 7. I need a DLL for my Visual Basic project. What can I do? + + - Define the ZLIB_WINAPI macro before including "zlib.h", when + building both the DLL and the user application (except that + you don't need to define anything when using the DLL in Visual + Basic). The ZLIB_WINAPI macro will switch on the WINAPI + (STDCALL) convention. The name of this DLL must be different + than the official ZLIB1.DLL. + + Gilles Vollant has contributed a build named ZLIBWAPI.DLL, + with the ZLIB_WINAPI macro turned on, and with the minizip + functionality built in. For more information, please read + the notes inside "contrib/vstudio/readme.txt", found in the + zlib distribution. + + + 8. I need to use zlib in my Microsoft .NET project. What can I + do? + + - Henrik Ravn has contributed a .NET wrapper around zlib. Look + into contrib/dotzlib/, inside the zlib distribution. + + + 9. If my application uses ZLIB1.DLL, should I link it to + MSVCRT.DLL? Why? + + - It is not required, but it is recommended to link your + application to MSVCRT.DLL, if it uses ZLIB1.DLL. + + The executables (.EXE, .DLL, etc.) that are involved in the + same process and are using the C run-time library (i.e. they + are calling standard C functions), must link to the same + library. There are several libraries in the Win32 system: + CRTDLL.DLL, MSVCRT.DLL, the static C libraries, etc. + Since ZLIB1.DLL is linked to MSVCRT.DLL, the executables that + depend on it should also be linked to MSVCRT.DLL. + + +10. Why are you saying that ZLIB1.DLL and my application should + be linked to the same C run-time (CRT) library? I linked my + application and my DLLs to different C libraries (e.g. my + application to a static library, and my DLLs to MSVCRT.DLL), + and everything works fine. + + - If a user library invokes only pure Win32 API (accessible via + and the related headers), its DLL build will work + in any context. But if this library invokes standard C API, + things get more complicated. + + There is a single Win32 library in a Win32 system. Every + function in this library resides in a single DLL module, that + is safe to call from anywhere. On the other hand, there are + multiple versions of the C library, and each of them has its + own separate internal state. Standalone executables and user + DLLs that call standard C functions must link to a C run-time + (CRT) library, be it static or shared (DLL). Intermixing + occurs when an executable (not necessarily standalone) and a + DLL are linked to different CRTs, and both are running in the + same process. + + Intermixing multiple CRTs is possible, as long as their + internal states are kept intact. The Microsoft Knowledge Base + articles KB94248 "HOWTO: Use the C Run-Time" and KB140584 + "HOWTO: Link with the Correct C Run-Time (CRT) Library" + mention the potential problems raised by intermixing. + + If intermixing works for you, it's because your application + and DLLs are avoiding the corruption of each of the CRTs' + internal states, maybe by careful design, or maybe by fortune. + + Also note that linking ZLIB1.DLL to non-Microsoft CRTs, such + as those provided by Borland, raises similar problems. + + +11. Why are you linking ZLIB1.DLL to MSVCRT.DLL? + + - MSVCRT.DLL exists on every Windows 95 with a new service pack + installed, or with Microsoft Internet Explorer 4 or later, and + on all other Windows 4.x or later (Windows 98, Windows NT 4, + or later). It is freely distributable; if not present in the + system, it can be downloaded from Microsoft or from other + software provider for free. + + The fact that MSVCRT.DLL does not exist on a virgin Windows 95 + is not so problematic. Windows 95 is scarcely found nowadays, + Microsoft ended its support a long time ago, and many recent + applications from various vendors, including Microsoft, do not + even run on it. Furthermore, no serious user should run + Windows 95 without a proper update installed. + + +12. Why are you not linking ZLIB1.DLL to + <> ? + + - We considered and abandoned the following alternatives: + + * Linking ZLIB1.DLL to a static C library (LIBC.LIB, or + LIBCMT.LIB) is not a good option. People are using the DLL + mainly to save disk space. If you are linking your program + to a static C library, you may as well consider linking zlib + in statically, too. + + * Linking ZLIB1.DLL to CRTDLL.DLL looks appealing, because + CRTDLL.DLL is present on every Win32 installation. + Unfortunately, it has a series of problems: it does not + work properly with Microsoft's C++ libraries, it does not + provide support for 64-bit file offsets, (and so on...), + and Microsoft discontinued its support a long time ago. + + * Linking ZLIB1.DLL to MSVCR70.DLL or MSVCR71.DLL, supplied + with the Microsoft .NET platform, and Visual C++ 7.0/7.1, + raises problems related to the status of ZLIB1.DLL as a + system component. According to the Microsoft Knowledge Base + article KB326922 "INFO: Redistribution of the Shared C + Runtime Component in Visual C++ .NET", MSVCR70.DLL and + MSVCR71.DLL are not supposed to function as system DLLs, + because they may clash with MSVCRT.DLL. Instead, the + application's installer is supposed to put these DLLs + (if needed) in the application's private directory. + If ZLIB1.DLL depends on a non-system runtime, it cannot + function as a redistributable system component. + + * Linking ZLIB1.DLL to non-Microsoft runtimes, such as + Borland's, or Cygwin's, raises problems related to the + reliable presence of these runtimes on Win32 systems. + It's easier to let the DLL build of zlib up to the people + who distribute these runtimes, and who may proceed as + explained in the answer to Question 14. + + +13. If ZLIB1.DLL cannot be linked to MSVCR70.DLL or MSVCR71.DLL, + how can I build/use ZLIB1.DLL in Microsoft Visual C++ 7.0 + (Visual Studio .NET) or newer? + + - Due to the problems explained in the Microsoft Knowledge Base + article KB326922 (see the previous answer), the C runtime that + comes with the VC7 environment is no longer considered a + system component. That is, it should not be assumed that this + runtime exists, or may be installed in a system directory. + Since ZLIB1.DLL is supposed to be a system component, it may + not depend on a non-system component. + + In order to link ZLIB1.DLL and your application to MSVCRT.DLL + in VC7, you need the library of Visual C++ 6.0 or older. If + you don't have this library at hand, it's probably best not to + use ZLIB1.DLL. + + We are hoping that, in the future, Microsoft will provide a + way to build applications linked to a proper system runtime, + from the Visual C++ environment. Until then, you have a + couple of alternatives, such as linking zlib in statically. + If your application requires dynamic linking, you may proceed + as explained in the answer to Question 14. + + +14. I need to link my own DLL build to a CRT different than + MSVCRT.DLL. What can I do? + + - Feel free to rebuild the DLL from the zlib sources, and link + it the way you want. You should, however, clearly state that + your build is unofficial. You should give it a different file + name, and/or install it in a private directory that can be + accessed by your application only, and is not visible to the + others (i.e. it's neither in the PATH, nor in the SYSTEM or + SYSTEM32 directories). Otherwise, your build may clash with + applications that link to the official build. + + For example, in Cygwin, zlib is linked to the Cygwin runtime + CYGWIN1.DLL, and it is distributed under the name CYGZ.DLL. + + +15. May I include additional pieces of code that I find useful, + link them in ZLIB1.DLL, and export them? + + - No. A legitimate build of ZLIB1.DLL must not include code + that does not originate from the official zlib source code. + But you can make your own private DLL build, under a different + file name, as suggested in the previous answer. + + For example, zlib is a part of the VCL library, distributed + with Borland Delphi and C++ Builder. The DLL build of VCL + is a redistributable file, named VCLxx.DLL. + + +16. May I remove some functionality out of ZLIB1.DLL, by enabling + macros like NO_GZCOMPRESS or NO_GZIP at compile time? + + - No. A legitimate build of ZLIB1.DLL must provide the complete + zlib functionality, as implemented in the official zlib source + code. But you can make your own private DLL build, under a + different file name, as suggested in the previous answer. + + +17. I made my own ZLIB1.DLL build. Can I test it for compliance? + + - We prefer that you download the official DLL from the zlib + web site. If you need something peculiar from this DLL, you + can send your suggestion to the zlib mailing list. + + However, in case you do rebuild the DLL yourself, you can run + it with the test programs found in the DLL distribution. + Running these test programs is not a guarantee of compliance, + but a failure can imply a detected problem. + +** + +This document is written and maintained by +Cosmin Truta diff --git a/zlib-1.2.11/win32/Makefile.bor b/zlib-1.2.11/win32/Makefile.bor new file mode 100644 index 00000000..d152bbb7 --- /dev/null +++ b/zlib-1.2.11/win32/Makefile.bor @@ -0,0 +1,110 @@ +# Makefile for zlib +# Borland C++ for Win32 +# +# Usage: +# make -f win32/Makefile.bor +# make -f win32/Makefile.bor LOCAL_ZLIB=-DASMV OBJA=match.obj OBJPA=+match.obj + +# ------------ Borland C++ ------------ + +# Optional nonstandard preprocessor flags (e.g. -DMAX_MEM_LEVEL=7) +# should be added to the environment via "set LOCAL_ZLIB=-DFOO" or +# added to the declaration of LOC here: +LOC = $(LOCAL_ZLIB) + +CC = bcc32 +AS = bcc32 +LD = bcc32 +AR = tlib +CFLAGS = -a -d -k- -O2 $(LOC) +ASFLAGS = $(LOC) +LDFLAGS = $(LOC) + + +# variables +ZLIB_LIB = zlib.lib + +OBJ1 = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj +OBJ2 = gzwrite.obj infback.obj inffast.obj inflate.obj inftrees.obj trees.obj uncompr.obj zutil.obj +#OBJA = +OBJP1 = +adler32.obj+compress.obj+crc32.obj+deflate.obj+gzclose.obj+gzlib.obj+gzread.obj +OBJP2 = +gzwrite.obj+infback.obj+inffast.obj+inflate.obj+inftrees.obj+trees.obj+uncompr.obj+zutil.obj +#OBJPA= + + +# targets +all: $(ZLIB_LIB) example.exe minigzip.exe + +.c.obj: + $(CC) -c $(CFLAGS) $< + +.asm.obj: + $(AS) -c $(ASFLAGS) $< + +adler32.obj: adler32.c zlib.h zconf.h + +compress.obj: compress.c zlib.h zconf.h + +crc32.obj: crc32.c zlib.h zconf.h crc32.h + +deflate.obj: deflate.c deflate.h zutil.h zlib.h zconf.h + +gzclose.obj: gzclose.c zlib.h zconf.h gzguts.h + +gzlib.obj: gzlib.c zlib.h zconf.h gzguts.h + +gzread.obj: gzread.c zlib.h zconf.h gzguts.h + +gzwrite.obj: gzwrite.c zlib.h zconf.h gzguts.h + +infback.obj: infback.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inffast.obj: inffast.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h + +inflate.obj: inflate.c zutil.h zlib.h zconf.h inftrees.h inflate.h \ + inffast.h inffixed.h + +inftrees.obj: inftrees.c zutil.h zlib.h zconf.h inftrees.h + +trees.obj: trees.c zutil.h zlib.h zconf.h deflate.h trees.h + +uncompr.obj: uncompr.c zlib.h zconf.h + +zutil.obj: zutil.c zutil.h zlib.h zconf.h + +example.obj: test/example.c zlib.h zconf.h + +minigzip.obj: test/minigzip.c zlib.h zconf.h + + +# For the sake of the old Borland make, +# the command line is cut to fit in the MS-DOS 128 byte limit: +$(ZLIB_LIB): $(OBJ1) $(OBJ2) $(OBJA) + -del $(ZLIB_LIB) + $(AR) $(ZLIB_LIB) $(OBJP1) + $(AR) $(ZLIB_LIB) $(OBJP2) + $(AR) $(ZLIB_LIB) $(OBJPA) + + +# testing +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +example.exe: example.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) example.obj $(ZLIB_LIB) + +minigzip.exe: minigzip.obj $(ZLIB_LIB) + $(LD) $(LDFLAGS) minigzip.obj $(ZLIB_LIB) + + +# cleanup +clean: + -del $(ZLIB_LIB) + -del *.obj + -del *.exe + -del *.tds + -del zlib.bak + -del foo.gz diff --git a/zlib-1.2.11/win32/Makefile.gcc b/zlib-1.2.11/win32/Makefile.gcc new file mode 100644 index 00000000..305be50a --- /dev/null +++ b/zlib-1.2.11/win32/Makefile.gcc @@ -0,0 +1,182 @@ +# Makefile for zlib, derived from Makefile.dj2. +# Modified for mingw32 by C. Spieler, 6/16/98. +# Updated for zlib 1.2.x by Christian Spieler and Cosmin Truta, Mar-2003. +# Last updated: Mar 2012. +# Tested under Cygwin and MinGW. + +# Copyright (C) 1995-2003 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type from the top level zlib directory: +# +# make -fwin32/Makefile.gcc; make test testdll -fwin32/Makefile.gcc +# +# To use the asm code, type: +# cp contrib/asm?86/match.S ./match.S +# make LOC=-DASMV OBJA=match.o -fwin32/Makefile.gcc +# +# To install libz.a, zconf.h and zlib.h in the system directories, type: +# +# make install -fwin32/Makefile.gcc +# +# BINARY_PATH, INCLUDE_PATH and LIBRARY_PATH must be set. +# +# To install the shared lib, append SHARED_MODE=1 to the make command : +# +# make install -fwin32/Makefile.gcc SHARED_MODE=1 + +# Note: +# If the platform is *not* MinGW (e.g. it is Cygwin or UWIN), +# the DLL name should be changed from "zlib1.dll". + +STATICLIB = libz.a +SHAREDLIB = zlib1.dll +IMPLIB = libz.dll.a + +# +# Set to 1 if shared object needs to be installed +# +SHARED_MODE=0 + +#LOC = -DASMV +#LOC = -DZLIB_DEBUG -g + +PREFIX = +CC = $(PREFIX)gcc +CFLAGS = $(LOC) -O3 -Wall + +AS = $(CC) +ASFLAGS = $(LOC) -Wall + +LD = $(CC) +LDFLAGS = $(LOC) + +AR = $(PREFIX)ar +ARFLAGS = rcs + +RC = $(PREFIX)windres +RCFLAGS = --define GCC_WINDRES + +STRIP = $(PREFIX)strip + +CP = cp -fp +# If GNU install is available, replace $(CP) with install. +INSTALL = $(CP) +RM = rm -f + +prefix ?= /usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \ + gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o +OBJA = + +all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) example.exe minigzip.exe example_d.exe minigzip_d.exe + +test: example.exe minigzip.exe + ./example + echo hello world | ./minigzip | ./minigzip -d + +testdll: example_d.exe minigzip_d.exe + ./example_d + echo hello world | ./minigzip_d | ./minigzip_d -d + +.c.o: + $(CC) $(CFLAGS) -c -o $@ $< + +.S.o: + $(AS) $(ASFLAGS) -c -o $@ $< + +$(STATICLIB): $(OBJS) $(OBJA) + $(AR) $(ARFLAGS) $@ $(OBJS) $(OBJA) + +$(IMPLIB): $(SHAREDLIB) + +$(SHAREDLIB): win32/zlib.def $(OBJS) $(OBJA) zlibrc.o + $(CC) -shared -Wl,--out-implib,$(IMPLIB) $(LDFLAGS) \ + -o $@ win32/zlib.def $(OBJS) $(OBJA) zlibrc.o + $(STRIP) $@ + +example.exe: example.o $(STATICLIB) + $(LD) $(LDFLAGS) -o $@ example.o $(STATICLIB) + $(STRIP) $@ + +minigzip.exe: minigzip.o $(STATICLIB) + $(LD) $(LDFLAGS) -o $@ minigzip.o $(STATICLIB) + $(STRIP) $@ + +example_d.exe: example.o $(IMPLIB) + $(LD) $(LDFLAGS) -o $@ example.o $(IMPLIB) + $(STRIP) $@ + +minigzip_d.exe: minigzip.o $(IMPLIB) + $(LD) $(LDFLAGS) -o $@ minigzip.o $(IMPLIB) + $(STRIP) $@ + +example.o: test/example.c zlib.h zconf.h + $(CC) $(CFLAGS) -I. -c -o $@ test/example.c + +minigzip.o: test/minigzip.c zlib.h zconf.h + $(CC) $(CFLAGS) -I. -c -o $@ test/minigzip.c + +zlibrc.o: win32/zlib1.rc + $(RC) $(RCFLAGS) -o $@ win32/zlib1.rc + +.PHONY: install uninstall clean + +install: zlib.h zconf.h $(STATICLIB) $(IMPLIB) + @if test -z "$(DESTDIR)$(INCLUDE_PATH)" -o -z "$(DESTDIR)$(LIBRARY_PATH)" -o -z "$(DESTDIR)$(BINARY_PATH)"; then \ + echo INCLUDE_PATH, LIBRARY_PATH, and BINARY_PATH must be specified; \ + exit 1; \ + fi + -@mkdir -p '$(DESTDIR)$(INCLUDE_PATH)' + -@mkdir -p '$(DESTDIR)$(LIBRARY_PATH)' '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig + -if [ "$(SHARED_MODE)" = "1" ]; then \ + mkdir -p '$(DESTDIR)$(BINARY_PATH)'; \ + $(INSTALL) $(SHAREDLIB) '$(DESTDIR)$(BINARY_PATH)'; \ + $(INSTALL) $(IMPLIB) '$(DESTDIR)$(LIBRARY_PATH)'; \ + fi + -$(INSTALL) zlib.h '$(DESTDIR)$(INCLUDE_PATH)' + -$(INSTALL) zconf.h '$(DESTDIR)$(INCLUDE_PATH)' + -$(INSTALL) $(STATICLIB) '$(DESTDIR)$(LIBRARY_PATH)' + sed \ + -e 's|@prefix@|${prefix}|g' \ + -e 's|@exec_prefix@|${exec_prefix}|g' \ + -e 's|@libdir@|$(LIBRARY_PATH)|g' \ + -e 's|@sharedlibdir@|$(LIBRARY_PATH)|g' \ + -e 's|@includedir@|$(INCLUDE_PATH)|g' \ + -e 's|@VERSION@|'`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' zlib.h`'|g' \ + zlib.pc.in > '$(DESTDIR)$(LIBRARY_PATH)'/pkgconfig/zlib.pc + +uninstall: + -if [ "$(SHARED_MODE)" = "1" ]; then \ + $(RM) '$(DESTDIR)$(BINARY_PATH)'/$(SHAREDLIB); \ + $(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(IMPLIB); \ + fi + -$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zlib.h + -$(RM) '$(DESTDIR)$(INCLUDE_PATH)'/zconf.h + -$(RM) '$(DESTDIR)$(LIBRARY_PATH)'/$(STATICLIB) + +clean: + -$(RM) $(STATICLIB) + -$(RM) $(SHAREDLIB) + -$(RM) $(IMPLIB) + -$(RM) *.o + -$(RM) *.exe + -$(RM) foo.gz + +adler32.o: zlib.h zconf.h +compress.o: zlib.h zconf.h +crc32.o: crc32.h zlib.h zconf.h +deflate.o: deflate.h zutil.h zlib.h zconf.h +gzclose.o: zlib.h zconf.h gzguts.h +gzlib.o: zlib.h zconf.h gzguts.h +gzread.o: zlib.h zconf.h gzguts.h +gzwrite.o: zlib.h zconf.h gzguts.h +inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h +inftrees.o: zutil.h zlib.h zconf.h inftrees.h +trees.o: deflate.h zutil.h zlib.h zconf.h trees.h +uncompr.o: zlib.h zconf.h +zutil.o: zutil.h zlib.h zconf.h diff --git a/zlib-1.2.11/win32/Makefile.msc b/zlib-1.2.11/win32/Makefile.msc new file mode 100644 index 00000000..6831882d --- /dev/null +++ b/zlib-1.2.11/win32/Makefile.msc @@ -0,0 +1,163 @@ +# Makefile for zlib using Microsoft (Visual) C +# zlib is copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler +# +# Usage: +# nmake -f win32/Makefile.msc (standard build) +# nmake -f win32/Makefile.msc LOC=-DFOO (nonstandard build) +# nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" \ +# OBJA="inffas32.obj match686.obj" (use ASM code, x86) +# nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -I." \ +# OBJA="inffasx64.obj gvmat64.obj inffas8664.obj" (use ASM code, x64) + +# The toplevel directory of the source tree. +# +TOP = . + +# optional build flags +LOC = + +# variables +STATICLIB = zlib.lib +SHAREDLIB = zlib1.dll +IMPLIB = zdll.lib + +CC = cl +AS = ml +LD = link +AR = lib +RC = rc +CFLAGS = -nologo -MD -W3 -O2 -Oy- -Zi -Fd"zlib" $(LOC) +WFLAGS = -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE +ASFLAGS = -coff -Zi $(LOC) +LDFLAGS = -nologo -debug -incremental:no -opt:ref +ARFLAGS = -nologo +RCFLAGS = /dWIN32 /r + +OBJS = adler32.obj compress.obj crc32.obj deflate.obj gzclose.obj gzlib.obj gzread.obj \ + gzwrite.obj infback.obj inflate.obj inftrees.obj inffast.obj trees.obj uncompr.obj zutil.obj +OBJA = + + +# targets +all: $(STATICLIB) $(SHAREDLIB) $(IMPLIB) \ + example.exe minigzip.exe example_d.exe minigzip_d.exe + +$(STATICLIB): $(OBJS) $(OBJA) + $(AR) $(ARFLAGS) -out:$@ $(OBJS) $(OBJA) + +$(IMPLIB): $(SHAREDLIB) + +$(SHAREDLIB): $(TOP)/win32/zlib.def $(OBJS) $(OBJA) zlib1.res + $(LD) $(LDFLAGS) -def:$(TOP)/win32/zlib.def -dll -implib:$(IMPLIB) \ + -out:$@ -base:0x5A4C0000 $(OBJS) $(OBJA) zlib1.res + if exist $@.manifest \ + mt -nologo -manifest $@.manifest -outputresource:$@;2 + +example.exe: example.obj $(STATICLIB) + $(LD) $(LDFLAGS) example.obj $(STATICLIB) + if exist $@.manifest \ + mt -nologo -manifest $@.manifest -outputresource:$@;1 + +minigzip.exe: minigzip.obj $(STATICLIB) + $(LD) $(LDFLAGS) minigzip.obj $(STATICLIB) + if exist $@.manifest \ + mt -nologo -manifest $@.manifest -outputresource:$@;1 + +example_d.exe: example.obj $(IMPLIB) + $(LD) $(LDFLAGS) -out:$@ example.obj $(IMPLIB) + if exist $@.manifest \ + mt -nologo -manifest $@.manifest -outputresource:$@;1 + +minigzip_d.exe: minigzip.obj $(IMPLIB) + $(LD) $(LDFLAGS) -out:$@ minigzip.obj $(IMPLIB) + if exist $@.manifest \ + mt -nologo -manifest $@.manifest -outputresource:$@;1 + +{$(TOP)}.c.obj: + $(CC) -c $(WFLAGS) $(CFLAGS) $< + +{$(TOP)/test}.c.obj: + $(CC) -c -I$(TOP) $(WFLAGS) $(CFLAGS) $< + +{$(TOP)/contrib/masmx64}.c.obj: + $(CC) -c $(WFLAGS) $(CFLAGS) $< + +{$(TOP)/contrib/masmx64}.asm.obj: + $(AS) -c $(ASFLAGS) $< + +{$(TOP)/contrib/masmx86}.asm.obj: + $(AS) -c $(ASFLAGS) $< + +adler32.obj: $(TOP)/adler32.c $(TOP)/zlib.h $(TOP)/zconf.h + +compress.obj: $(TOP)/compress.c $(TOP)/zlib.h $(TOP)/zconf.h + +crc32.obj: $(TOP)/crc32.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/crc32.h + +deflate.obj: $(TOP)/deflate.c $(TOP)/deflate.h $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h + +gzclose.obj: $(TOP)/gzclose.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h + +gzlib.obj: $(TOP)/gzlib.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h + +gzread.obj: $(TOP)/gzread.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h + +gzwrite.obj: $(TOP)/gzwrite.c $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/gzguts.h + +infback.obj: $(TOP)/infback.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \ + $(TOP)/inffast.h $(TOP)/inffixed.h + +inffast.obj: $(TOP)/inffast.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \ + $(TOP)/inffast.h + +inflate.obj: $(TOP)/inflate.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h $(TOP)/inflate.h \ + $(TOP)/inffast.h $(TOP)/inffixed.h + +inftrees.obj: $(TOP)/inftrees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/inftrees.h + +trees.obj: $(TOP)/trees.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h $(TOP)/deflate.h $(TOP)/trees.h + +uncompr.obj: $(TOP)/uncompr.c $(TOP)/zlib.h $(TOP)/zconf.h + +zutil.obj: $(TOP)/zutil.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h + +gvmat64.obj: $(TOP)/contrib\masmx64\gvmat64.asm + +inffasx64.obj: $(TOP)/contrib\masmx64\inffasx64.asm + +inffas8664.obj: $(TOP)/contrib\masmx64\inffas8664.c $(TOP)/zutil.h $(TOP)/zlib.h $(TOP)/zconf.h \ + $(TOP)/inftrees.h $(TOP)/inflate.h $(TOP)/inffast.h + +inffas32.obj: $(TOP)/contrib\masmx86\inffas32.asm + +match686.obj: $(TOP)/contrib\masmx86\match686.asm + +example.obj: $(TOP)/test/example.c $(TOP)/zlib.h $(TOP)/zconf.h + +minigzip.obj: $(TOP)/test/minigzip.c $(TOP)/zlib.h $(TOP)/zconf.h + +zlib1.res: $(TOP)/win32/zlib1.rc + $(RC) $(RCFLAGS) /fo$@ $(TOP)/win32/zlib1.rc + +# testing +test: example.exe minigzip.exe + example + echo hello world | minigzip | minigzip -d + +testdll: example_d.exe minigzip_d.exe + example_d + echo hello world | minigzip_d | minigzip_d -d + + +# cleanup +clean: + -del $(STATICLIB) + -del $(SHAREDLIB) + -del $(IMPLIB) + -del *.obj + -del *.res + -del *.exp + -del *.exe + -del *.pdb + -del *.manifest + -del foo.gz diff --git a/zlib-1.2.11/win32/README-WIN32.txt b/zlib-1.2.11/win32/README-WIN32.txt new file mode 100644 index 00000000..df7ab7f4 --- /dev/null +++ b/zlib-1.2.11/win32/README-WIN32.txt @@ -0,0 +1,103 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.11 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) +and rfc1952.txt (gzip format). + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). Two compiled +examples are distributed in this package, example and minigzip. The example_d +and minigzip_d flavors validate that the zlib1.dll file is working correctly. + +Questions about zlib should be sent to . The zlib home page +is http://zlib.net/ . Before reporting a problem, please check this site to +verify that you have the latest version of zlib; otherwise get the latest +version and check whether the problem still exists or not. + +PLEASE read DLL_FAQ.txt, and the the zlib FAQ http://zlib.net/zlib_faq.html +before asking for help. + + +Manifest: + +The package zlib-1.2.11-win32-x86.zip will contain the following files: + + README-WIN32.txt This document + ChangeLog Changes since previous zlib packages + DLL_FAQ.txt Frequently asked questions about zlib1.dll + zlib.3.pdf Documentation of this library in Adobe Acrobat format + + example.exe A statically-bound example (using zlib.lib, not the dll) + example.pdb Symbolic information for debugging example.exe + + example_d.exe A zlib1.dll bound example (using zdll.lib) + example_d.pdb Symbolic information for debugging example_d.exe + + minigzip.exe A statically-bound test program (using zlib.lib, not the dll) + minigzip.pdb Symbolic information for debugging minigzip.exe + + minigzip_d.exe A zlib1.dll bound test program (using zdll.lib) + minigzip_d.pdb Symbolic information for debugging minigzip_d.exe + + zlib.h Install these files into the compilers' INCLUDE path to + zconf.h compile programs which use zlib.lib or zdll.lib + + zdll.lib Install these files into the compilers' LIB path if linking + zdll.exp a compiled program to the zlib1.dll binary + + zlib.lib Install these files into the compilers' LIB path to link zlib + zlib.pdb into compiled programs, without zlib1.dll runtime dependency + (zlib.pdb provides debugging info to the compile time linker) + + zlib1.dll Install this binary shared library into the system PATH, or + the program's runtime directory (where the .exe resides) + zlib1.pdb Install in the same directory as zlib1.dll, in order to debug + an application crash using WinDbg or similar tools. + +All .pdb files above are entirely optional, but are very useful to a developer +attempting to diagnose program misbehavior or a crash. Many additional +important files for developers can be found in the zlib127.zip source package +available from http://zlib.net/ - review that package's README file for details. + + +Acknowledgments: + +The deflate format used by zlib was defined by Phil Katz. The deflate and +zlib specifications were written by L. Peter Deutsch. Thanks to all the +people who reported problems and suggested various improvements in zlib; they +are too numerous to cite here. + + +Copyright notice: + + (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. diff --git a/zlib-1.2.11/win32/VisualC.txt b/zlib-1.2.11/win32/VisualC.txt new file mode 100644 index 00000000..1005b219 --- /dev/null +++ b/zlib-1.2.11/win32/VisualC.txt @@ -0,0 +1,3 @@ + +To build zlib using the Microsoft Visual C++ environment, +use the appropriate project from the contrib/vstudio/ directory. diff --git a/zlib-1.2.11/win32/zlib.def b/zlib-1.2.11/win32/zlib.def new file mode 100644 index 00000000..784b1386 --- /dev/null +++ b/zlib-1.2.11/win32/zlib.def @@ -0,0 +1,94 @@ +; zlib data compression library +EXPORTS +; basic functions + zlibVersion + deflate + deflateEnd + inflate + inflateEnd +; advanced functions + deflateSetDictionary + deflateGetDictionary + deflateCopy + deflateReset + deflateParams + deflateTune + deflateBound + deflatePending + deflatePrime + deflateSetHeader + inflateSetDictionary + inflateGetDictionary + inflateSync + inflateCopy + inflateReset + inflateReset2 + inflatePrime + inflateMark + inflateGetHeader + inflateBack + inflateBackEnd + zlibCompileFlags +; utility functions + compress + compress2 + compressBound + uncompress + uncompress2 + gzopen + gzdopen + gzbuffer + gzsetparams + gzread + gzfread + gzwrite + gzfwrite + gzprintf + gzvprintf + gzputs + gzgets + gzputc + gzgetc + gzungetc + gzflush + gzseek + gzrewind + gztell + gzoffset + gzeof + gzdirect + gzclose + gzclose_r + gzclose_w + gzerror + gzclearerr +; large file functions + gzopen64 + gzseek64 + gztell64 + gzoffset64 + adler32_combine64 + crc32_combine64 +; checksum functions + adler32 + adler32_z + crc32 + crc32_z + adler32_combine + crc32_combine +; various hacks, don't look :) + deflateInit_ + deflateInit2_ + inflateInit_ + inflateInit2_ + inflateBackInit_ + gzgetc_ + zError + inflateSyncPoint + get_crc_table + inflateUndermine + inflateValidate + inflateCodesUsed + inflateResetKeep + deflateResetKeep + gzopen_w diff --git a/zlib-1.2.11/win32/zlib1.rc b/zlib-1.2.11/win32/zlib1.rc new file mode 100644 index 00000000..234e641c --- /dev/null +++ b/zlib-1.2.11/win32/zlib1.rc @@ -0,0 +1,40 @@ +#include +#include "../zlib.h" + +#ifdef GCC_WINDRES +VS_VERSION_INFO VERSIONINFO +#else +VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE +#endif + FILEVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 + PRODUCTVERSION ZLIB_VER_MAJOR,ZLIB_VER_MINOR,ZLIB_VER_REVISION,0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS 1 +#else + FILEFLAGS 0 +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + BEGIN + VALUE "FileDescription", "zlib data compression library\0" + VALUE "FileVersion", ZLIB_VERSION "\0" + VALUE "InternalName", "zlib1.dll\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + VALUE "OriginalFilename", "zlib1.dll\0" + VALUE "ProductName", "zlib\0" + VALUE "ProductVersion", ZLIB_VERSION "\0" + VALUE "Comments", "For more information visit http://www.zlib.net/\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/zlib-1.2.11/zconf.h b/zlib-1.2.11/zconf.h new file mode 100644 index 00000000..5e1d68a0 --- /dev/null +++ b/zlib-1.2.11/zconf.h @@ -0,0 +1,534 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/zlib-1.2.11/zconf.h.cmakein b/zlib-1.2.11/zconf.h.cmakein new file mode 100644 index 00000000..a7f24cce --- /dev/null +++ b/zlib-1.2.11/zconf.h.cmakein @@ -0,0 +1,536 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H +#cmakedefine Z_PREFIX +#cmakedefine Z_HAVE_UNISTD_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/zlib-1.2.11/zconf.h.in b/zlib-1.2.11/zconf.h.in new file mode 100644 index 00000000..5e1d68a0 --- /dev/null +++ b/zlib-1.2.11/zconf.h.in @@ -0,0 +1,534 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/zlib-1.2.11/zlib.3 b/zlib-1.2.11/zlib.3 new file mode 100644 index 00000000..bda4eb07 --- /dev/null +++ b/zlib-1.2.11/zlib.3 @@ -0,0 +1,149 @@ +.TH ZLIB 3 "15 Jan 2017" +.SH NAME +zlib \- compression/decompression library +.SH SYNOPSIS +[see +.I zlib.h +for full description] +.SH DESCRIPTION +The +.I zlib +library is a general purpose data compression library. +The code is thread safe, assuming that the standard library functions +used are thread safe, such as memory allocation routines. +It provides in-memory compression and decompression functions, +including integrity checks of the uncompressed data. +This version of the library supports only one compression method (deflation) +but other algorithms may be added later +with the same stream interface. +.LP +Compression can be done in a single step if the buffers are large enough +or can be done by repeated calls of the compression function. +In the latter case, +the application must provide more input and/or consume the output +(providing more output space) before each call. +.LP +The library also supports reading and writing files in +.IR gzip (1) +(.gz) format +with an interface similar to that of stdio. +.LP +The library does not install any signal handler. +The decoder checks the consistency of the compressed data, +so the library should never crash even in the case of corrupted input. +.LP +All functions of the compression library are documented in the file +.IR zlib.h . +The distribution source includes examples of use of the library +in the files +.I test/example.c +and +.IR test/minigzip.c, +as well as other examples in the +.IR examples/ +directory. +.LP +Changes to this version are documented in the file +.I ChangeLog +that accompanies the source. +.LP +.I zlib +is built in to many languages and operating systems, including but not limited to +Java, Python, .NET, PHP, Perl, Ruby, Swift, and Go. +.LP +An experimental package to read and write files in the .zip format, +written on top of +.I zlib +by Gilles Vollant (info@winimage.com), +is available at: +.IP +http://www.winimage.com/zLibDll/minizip.html +and also in the +.I contrib/minizip +directory of the main +.I zlib +source distribution. +.SH "SEE ALSO" +The +.I zlib +web site can be found at: +.IP +http://zlib.net/ +.LP +The data format used by the +.I zlib +library is described by RFC +(Request for Comments) 1950 to 1952 in the files: +.IP +http://tools.ietf.org/html/rfc1950 (for the zlib header and trailer format) +.br +http://tools.ietf.org/html/rfc1951 (for the deflate compressed data format) +.br +http://tools.ietf.org/html/rfc1952 (for the gzip header and trailer format) +.LP +Mark Nelson wrote an article about +.I zlib +for the Jan. 1997 issue of Dr. Dobb's Journal; +a copy of the article is available at: +.IP +http://marknelson.us/1997/01/01/zlib-engine/ +.SH "REPORTING PROBLEMS" +Before reporting a problem, +please check the +.I zlib +web site to verify that you have the latest version of +.IR zlib ; +otherwise, +obtain the latest version and see if the problem still exists. +Please read the +.I zlib +FAQ at: +.IP +http://zlib.net/zlib_faq.html +.LP +before asking for help. +Send questions and/or comments to zlib@gzip.org, +or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). +.SH AUTHORS AND LICENSE +Version 1.2.11 +.LP +Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler +.LP +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. +.LP +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: +.LP +.nr step 1 1 +.IP \n[step]. 3 +The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software +in a product, an acknowledgment in the product documentation would be +appreciated but is not required. +.IP \n+[step]. +Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +.IP \n+[step]. +This notice may not be removed or altered from any source distribution. +.LP +Jean-loup Gailly Mark Adler +.br +jloup@gzip.org madler@alumni.caltech.edu +.LP +The deflate format used by +.I zlib +was defined by Phil Katz. +The deflate and +.I zlib +specifications were written by L. Peter Deutsch. +Thanks to all the people who reported problems and suggested various +improvements in +.IR zlib ; +who are too numerous to cite here. +.LP +UNIX manual page by R. P. C. Rodgers, +U.S. National Library of Medicine (rodgers@nlm.nih.gov). +.\" end of man page diff --git a/zlib-1.2.11/zlib.3.pdf b/zlib-1.2.11/zlib.3.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6fa519c5bdf5df33b2f17549e1df142c619c916c GIT binary patch literal 19318 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 to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/zlib-1.2.11/zlib.map b/zlib-1.2.11/zlib.map new file mode 100644 index 00000000..40fa9db2 --- /dev/null +++ b/zlib-1.2.11/zlib.map @@ -0,0 +1,94 @@ +ZLIB_1.2.0 { + global: + compressBound; + deflateBound; + inflateBack; + inflateBackEnd; + inflateBackInit_; + inflateCopy; + local: + deflate_copyright; + inflate_copyright; + inflate_fast; + inflate_table; + zcalloc; + zcfree; + z_errmsg; + gz_error; + gz_intmax; + _*; +}; + +ZLIB_1.2.0.2 { + gzclearerr; + gzungetc; + zlibCompileFlags; +} ZLIB_1.2.0; + +ZLIB_1.2.0.8 { + deflatePrime; +} ZLIB_1.2.0.2; + +ZLIB_1.2.2 { + adler32_combine; + crc32_combine; + deflateSetHeader; + inflateGetHeader; +} ZLIB_1.2.0.8; + +ZLIB_1.2.2.3 { + deflateTune; + gzdirect; +} ZLIB_1.2.2; + +ZLIB_1.2.2.4 { + inflatePrime; +} ZLIB_1.2.2.3; + +ZLIB_1.2.3.3 { + adler32_combine64; + crc32_combine64; + gzopen64; + gzseek64; + gztell64; + inflateUndermine; +} ZLIB_1.2.2.4; + +ZLIB_1.2.3.4 { + inflateReset2; + inflateMark; +} ZLIB_1.2.3.3; + +ZLIB_1.2.3.5 { + gzbuffer; + gzoffset; + gzoffset64; + gzclose_r; + gzclose_w; +} ZLIB_1.2.3.4; + +ZLIB_1.2.5.1 { + deflatePending; +} ZLIB_1.2.3.5; + +ZLIB_1.2.5.2 { + deflateResetKeep; + gzgetc_; + inflateResetKeep; +} ZLIB_1.2.5.1; + +ZLIB_1.2.7.1 { + inflateGetDictionary; + gzvprintf; +} ZLIB_1.2.5.2; + +ZLIB_1.2.9 { + inflateCodesUsed; + inflateValidate; + uncompress2; + gzfread; + gzfwrite; + deflateGetDictionary; + adler32_z; + crc32_z; +} ZLIB_1.2.7.1; diff --git a/zlib-1.2.11/zlib.pc.cmakein b/zlib-1.2.11/zlib.pc.cmakein new file mode 100644 index 00000000..a5e64293 --- /dev/null +++ b/zlib-1.2.11/zlib.pc.cmakein @@ -0,0 +1,13 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@INSTALL_LIB_DIR@ +sharedlibdir=@INSTALL_LIB_DIR@ +includedir=@INSTALL_INC_DIR@ + +Name: zlib +Description: zlib compression library +Version: @VERSION@ + +Requires: +Libs: -L${libdir} -L${sharedlibdir} -lz +Cflags: -I${includedir} diff --git a/zlib-1.2.11/zlib.pc.in b/zlib-1.2.11/zlib.pc.in new file mode 100644 index 00000000..7e5acf9c --- /dev/null +++ b/zlib-1.2.11/zlib.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +sharedlibdir=@sharedlibdir@ +includedir=@includedir@ + +Name: zlib +Description: zlib compression library +Version: @VERSION@ + +Requires: +Libs: -L${libdir} -L${sharedlibdir} -lz +Cflags: -I${includedir} diff --git a/zlib-1.2.11/zlib2ansi b/zlib-1.2.11/zlib2ansi new file mode 100755 index 00000000..15e3e165 --- /dev/null +++ b/zlib-1.2.11/zlib2ansi @@ -0,0 +1,152 @@ +#!/usr/bin/perl + +# Transform K&R C function definitions into ANSI equivalent. +# +# Author: Paul Marquess +# Version: 1.0 +# Date: 3 October 2006 + +# TODO +# +# Asumes no function pointer parameters. unless they are typedefed. +# Assumes no literal strings that look like function definitions +# Assumes functions start at the beginning of a line + +use strict; +use warnings; + +local $/; +$_ = <>; + +my $sp = qr{ \s* (?: /\* .*? \*/ )? \s* }x; # assume no nested comments + +my $d1 = qr{ $sp (?: [\w\*\s]+ $sp)* $sp \w+ $sp [\[\]\s]* $sp }x ; +my $decl = qr{ $sp (?: \w+ $sp )+ $d1 }xo ; +my $dList = qr{ $sp $decl (?: $sp , $d1 )* $sp ; $sp }xo ; + + +while (s/^ + ( # Start $1 + ( # Start $2 + .*? # Minimal eat content + ( ^ \w [\w\s\*]+ ) # $3 -- function name + \s* # optional whitespace + ) # $2 - Matched up to before parameter list + + \( \s* # Literal "(" + optional whitespace + ( [^\)]+ ) # $4 - one or more anythings except ")" + \s* \) # optional whitespace surrounding a Literal ")" + + ( (?: $dList )+ ) # $5 + + $sp ^ { # literal "{" at start of line + ) # Remember to $1 + //xsom + ) +{ + my $all = $1 ; + my $prefix = $2; + my $param_list = $4 ; + my $params = $5; + + StripComments($params); + StripComments($param_list); + $param_list =~ s/^\s+//; + $param_list =~ s/\s+$//; + + my $i = 0 ; + my %pList = map { $_ => $i++ } + split /\s*,\s*/, $param_list; + my $pMatch = '(\b' . join('|', keys %pList) . '\b)\W*$' ; + + my @params = split /\s*;\s*/, $params; + my @outParams = (); + foreach my $p (@params) + { + if ($p =~ /,/) + { + my @bits = split /\s*,\s*/, $p; + my $first = shift @bits; + $first =~ s/^\s*//; + push @outParams, $first; + $first =~ /^(\w+\s*)/; + my $type = $1 ; + push @outParams, map { $type . $_ } @bits; + } + else + { + $p =~ s/^\s+//; + push @outParams, $p; + } + } + + + my %tmp = map { /$pMatch/; $_ => $pList{$1} } + @outParams ; + + @outParams = map { " $_" } + sort { $tmp{$a} <=> $tmp{$b} } + @outParams ; + + print $prefix ; + print "(\n" . join(",\n", @outParams) . ")\n"; + print "{" ; + +} + +# Output any trailing code. +print ; +exit 0; + + +sub StripComments +{ + + no warnings; + + # Strip C & C++ coments + # From the perlfaq + $_[0] =~ + + s{ + /\* ## Start of /* ... */ comment + [^*]*\*+ ## Non-* followed by 1-or-more *'s + ( + [^/*][^*]*\*+ + )* ## 0-or-more things which don't start with / + ## but do end with '*' + / ## End of /* ... */ comment + + | ## OR C++ Comment + // ## Start of C++ comment // + [^\n]* ## followed by 0-or-more non end of line characters + + | ## OR various things which aren't comments: + + ( + " ## Start of " ... " string + ( + \\. ## Escaped char + | ## OR + [^"\\] ## Non "\ + )* + " ## End of " ... " string + + | ## OR + + ' ## Start of ' ... ' string + ( + \\. ## Escaped char + | ## OR + [^'\\] ## Non '\ + )* + ' ## End of ' ... ' string + + | ## OR + + . ## Anything other char + [^/"'\\]* ## Chars which doesn't start a comment, string or escape + ) + }{$2}gxs; + +} diff --git a/zlib-1.2.11/zutil.c b/zlib-1.2.11/zutil.c new file mode 100644 index 00000000..a76c6b0c --- /dev/null +++ b/zlib-1.2.11/zutil.c @@ -0,0 +1,325 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2017 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" +#ifndef Z_SOLO +# include "gzguts.h" +#endif + +z_const char * const z_errmsg[10] = { + (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ + (z_const char *)"stream end", /* Z_STREAM_END 1 */ + (z_const char *)"", /* Z_OK 0 */ + (z_const char *)"file error", /* Z_ERRNO (-1) */ + (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ + (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ + (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ + (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ + (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ + (z_const char *)"" +}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef ZLIB_DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef ZLIB_DEBUG +#include +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifndef Z_SOLO + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf; + ulg bsize = (ulg)items*size; + + (void)opaque; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + + (void)opaque; + + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + (void)opaque; + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + (void)opaque; + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + (void)opaque; + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + (void)opaque; + free(ptr); +} + +#endif /* MY_ZCALLOC */ + +#endif /* !Z_SOLO */ diff --git a/zlib-1.2.11/zutil.h b/zlib-1.2.11/zutil.h new file mode 100644 index 00000000..b079ea6a --- /dev/null +++ b/zlib-1.2.11/zutil.h @@ -0,0 +1,271 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#if defined(STDC) && !defined(Z_SOLO) +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif +# include +# include +#endif + +#ifdef Z_SOLO + typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ +#endif + +#ifndef local +# define local static +#endif +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 1 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 2 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef __370__ +# if __TARGET_LIB__ < 0x20000000 +# define OS_CODE 4 +# elif __TARGET_LIB__ < 0x40000000 +# define OS_CODE 11 +# else +# define OS_CODE 8 +# endif +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 5 +#endif + +#ifdef OS2 +# define OS_CODE 6 +# if defined(M_I86) && !defined(Z_SOLO) +# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 7 +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +# endif +#endif + +#ifdef __acorn +# define OS_CODE 13 +#endif + +#if defined(WIN32) && !defined(__CYGWIN__) +# define OS_CODE 10 +#endif + +#ifdef _BEOS_ +# define OS_CODE 16 +#endif + +#ifdef __TOS_OS400__ +# define OS_CODE 18 +#endif + +#ifdef __APPLE__ +# define OS_CODE 19 +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) && !defined(MSDOS) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 3 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(pyr) || defined(Z_SOLO) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef ZLIB_DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +#endif /* ZUTIL_H */ From 0d6d045530732b0c27381b0fc22836cc417f5852 Mon Sep 17 00:00:00 2001 From: Panos Date: Wed, 22 Jan 2025 15:47:54 +0000 Subject: [PATCH 10/46] Updated dockerfiles, ci cfg --- .circleci/config.yml | 8 ++++++-- ci/docker/manylinux/Dockerfile.aarch64 | 4 ++-- ci/docker/manylinux/Dockerfile.aarch64_2_24 | 16 +++++++--------- ci/docker/manylinux/Dockerfile.aarch64_2_28 | 16 +++++++--------- .../manylinux/Dockerfile.manylinux_2_24_x86_64 | 16 +++++++--------- .../manylinux/Dockerfile.manylinux_2_28_x86_64 | 16 +++++++--------- 6 files changed, 36 insertions(+), 40 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c515ed82..c83530e8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -94,7 +94,9 @@ jobs: - run: name: Upload Wheel command: | - twine upload --skip-existing -u $PYPI_USER -p $PYPI_PASSWORD wheels/* + if [[ ! -z "$CIRCLE_TAG" ]]; then + twine upload --skip-existing -u $PYPI_USER -p $PYPI_PASSWORD wheels/* + fi manylinux-x86_64: machine: @@ -125,7 +127,9 @@ jobs: - run: name: Upload Wheels command: | - twine upload --skip-existing -u $PYPI_USER -p $PYPI_PASSWORD dist/* wheelhouse/* + if [[ ! -z "$CIRCLE_TAG" ]]; then + twine upload --skip-existing -u $PYPI_USER -p $PYPI_PASSWORD dist/* wheelhouse/* + fi manylinux-aarch64: machine: diff --git a/ci/docker/manylinux/Dockerfile.aarch64 b/ci/docker/manylinux/Dockerfile.aarch64 index ea3b637c..30f888a1 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64 +++ b/ci/docker/manylinux/Dockerfile.aarch64 @@ -7,7 +7,7 @@ ENV CFLAGS="-g0 -s" RUN yum install epel-release -y && yum install zlib-devel cmake3 perl-IPC-Cmd -y -ADD libssh-${LIBSSH_VERSION}.tar.xz libssh.tar.gz +ADD libssh-${LIBSSH_VERSION}.tar.gz libssh.tar.gz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz RUN tar -xzf ${OPENSSL}.tar.gz @@ -23,6 +23,6 @@ RUN mkdir -p build_libssh && cd build_libssh && \ -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF -DUNIT_TESTING=OFF && \ make -j6 install/strip -RUN rm -rf ${OPENSSL}* libssh build_libssh krb5-${KRB}.tar.xz +RUN rm -rf ${OPENSSL}* libssh build_libssh VOLUME /var/cache diff --git a/ci/docker/manylinux/Dockerfile.aarch64_2_24 b/ci/docker/manylinux/Dockerfile.aarch64_2_24 index 68025e38..9ebaca91 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64_2_24 +++ b/ci/docker/manylinux/Dockerfile.aarch64_2_24 @@ -1,17 +1,15 @@ FROM quay.io/pypa/manylinux_2_24_aarch64 -ENV OPENSSL openssl-1.1.1q -ENV LIBSSH 0.10.4 -ENV KRB 1.18.4 -ENV SYSTEM_LIBSSH 1 -ENV CFLAGS "-g0 -s" +ENV OPENSSL=openssl-3.4.0 +ENV LIBSSH_VERSION=0.11.1 +ENV SYSTEM_LIBSSH=1 +ENV CFLAGS="-g0 -s" ENV OPENSSL_ROOT_DIR /usr/lib RUN apt-get update -y && apt-get install zlib1g-dev cmake -y -ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz +ADD libssh-${LIBSSH_VERSION}.tar.gz libssh.tar.gz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz -ADD krb5-${KRB}.tar.xz krb5-${KRB}.tar.xz RUN tar -xzf ${OPENSSL}.tar.gz # Openssl @@ -22,10 +20,10 @@ RUN cd ${OPENSSL} && \ # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ - cmake ../libssh.tar.xz/libssh-${LIBSSH} -DCMAKE_BUILD_TYPE=Release \ + cmake3 ../libssh.tar.gz/libssh -DCMAKE_BUILD_TYPE=Release \ -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF && \ make -j6 install/strip -RUN rm -rf ${OPENSSL}* libssh build_libssh krb5-${KRB}.tar.xz +RUN rm -rf ${OPENSSL}* libssh build_libssh VOLUME /var/cache diff --git a/ci/docker/manylinux/Dockerfile.aarch64_2_28 b/ci/docker/manylinux/Dockerfile.aarch64_2_28 index 870fbafc..2aaab832 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64_2_28 +++ b/ci/docker/manylinux/Dockerfile.aarch64_2_28 @@ -1,17 +1,15 @@ FROM quay.io/pypa/manylinux_2_28_aarch64 -ENV OPENSSL openssl-1.1.1q -ENV LIBSSH 0.10.4 -ENV KRB 1.18.4 -ENV SYSTEM_LIBSSH 1 -ENV CFLAGS "-g0 -s" +ENV OPENSSL=openssl-3.4.0 +ENV LIBSSH_VERSION=0.11.1 +ENV SYSTEM_LIBSSH=1 +ENV CFLAGS="-g0 -s" ENV OPENSSL_ROOT_DIR /usr/lib RUN yum install zlib-devel cmake3 -y -ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz +ADD libssh-${LIBSSH_VERSION}.tar.gz libssh.tar.gz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz -ADD krb5-${KRB}.tar.xz krb5-${KRB}.tar.xz RUN tar -xzf ${OPENSSL}.tar.gz # Openssl @@ -22,10 +20,10 @@ RUN cd ${OPENSSL} && \ # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ - cmake ../libssh.tar.xz/libssh-${LIBSSH} -DCMAKE_BUILD_TYPE=Release \ + cmake3 ../libssh.tar.gz/libssh -DCMAKE_BUILD_TYPE=Release \ -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF && \ make -j6 install/strip -RUN rm -rf ${OPENSSL}* libssh build_libssh krb5-${KRB}.tar.xz +RUN rm -rf ${OPENSSL}* libssh build_libssh VOLUME /var/cache diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 index 3a9c555f..452bbdf2 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 @@ -1,17 +1,15 @@ FROM quay.io/pypa/manylinux_2_24_x86_64 -ENV OPENSSL openssl-1.1.1q -ENV LIBSSH 0.10.4 -ENV KRB 1.18.4 -ENV SYSTEM_LIBSSH 1 -ENV CFLAGS "-g0 -s" +ENV OPENSSL=openssl-3.4.0 +ENV LIBSSH_VERSION=0.11.1 +ENV SYSTEM_LIBSSH=1 +ENV CFLAGS="-g0 -s" ENV OPENSSL_ROOT_DIR /usr/lib RUN apt-get update -y && apt-get install zlib1g-dev cmake -y -ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz +ADD libssh-${LIBSSH_VERSION}.tar.gz libssh.tar.gz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz -ADD krb5-${KRB}.tar.xz krb5-${KRB}.tar.xz RUN tar -xzf ${OPENSSL}.tar.gz # Openssl @@ -22,10 +20,10 @@ RUN cd ${OPENSSL} && \ # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ - cmake ../libssh.tar.xz/libssh-${LIBSSH} -DCMAKE_BUILD_TYPE=Release \ + cmake3 ../libssh.tar.gz/libssh -DCMAKE_BUILD_TYPE=Release \ -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF && \ make -j6 install/strip -RUN rm -rf ${OPENSSL}* libssh build_libssh krb5-${KRB}.tar.xz +RUN rm -rf ${OPENSSL}* libssh build_libssh VOLUME /var/cache diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 index 533d146b..66ec2290 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 @@ -1,17 +1,15 @@ FROM quay.io/pypa/manylinux_2_28_x86_64 -ENV OPENSSL openssl-1.1.1q -ENV LIBSSH 0.10.4 -ENV KRB 1.18.4 -ENV SYSTEM_LIBSSH 1 -ENV CFLAGS "-g0 -s" +ENV OPENSSL=openssl-3.4.0 +ENV LIBSSH_VERSION=0.11.1 +ENV SYSTEM_LIBSSH=1 +ENV CFLAGS="-g0 -s" ENV OPENSSL_ROOT_DIR /usr/lib RUN yum install zlib-devel cmake3 -y -ADD libssh-${LIBSSH}.tar.xz libssh.tar.xz +ADD libssh-${LIBSSH_VERSION}.tar.gz libssh.tar.gz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz -ADD krb5-${KRB}.tar.xz krb5-${KRB}.tar.xz RUN tar -xzf ${OPENSSL}.tar.gz # Openssl @@ -22,10 +20,10 @@ RUN cd ${OPENSSL} && \ # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ - cmake ../libssh.tar.xz/libssh-${LIBSSH} -DCMAKE_BUILD_TYPE=Release \ + cmake3 ../libssh.tar.gz/libssh -DCMAKE_BUILD_TYPE=Release \ -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF && \ make -j6 install/strip -RUN rm -rf ${OPENSSL}* libssh build_libssh krb5-${KRB}.tar.xz +RUN rm -rf ${OPENSSL}* libssh build_libssh VOLUME /var/cache From b4aa009ab4a162889c1fc4716e0bda5c812f185b Mon Sep 17 00:00:00 2001 From: Panos Date: Wed, 22 Jan 2025 16:16:23 +0000 Subject: [PATCH 11/46] Updated dockerfiles --- ci/docker/manylinux/Dockerfile.aarch64 | 1 + ci/docker/manylinux/Dockerfile.aarch64_2_24 | 2 +- ci/docker/manylinux/Dockerfile.aarch64_2_28 | 2 +- ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 | 2 +- ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ci/docker/manylinux/Dockerfile.aarch64 b/ci/docker/manylinux/Dockerfile.aarch64 index 30f888a1..0fa9d263 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64 +++ b/ci/docker/manylinux/Dockerfile.aarch64 @@ -4,6 +4,7 @@ ENV OPENSSL=openssl-3.4.0 ENV LIBSSH_VERSION=0.11.1 ENV SYSTEM_LIBSSH=1 ENV CFLAGS="-g0 -s" +ENV OPENSSL_ROOT_DIR=/usr/lib RUN yum install epel-release -y && yum install zlib-devel cmake3 perl-IPC-Cmd -y diff --git a/ci/docker/manylinux/Dockerfile.aarch64_2_24 b/ci/docker/manylinux/Dockerfile.aarch64_2_24 index 9ebaca91..55ac5fcc 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64_2_24 +++ b/ci/docker/manylinux/Dockerfile.aarch64_2_24 @@ -4,7 +4,7 @@ ENV OPENSSL=openssl-3.4.0 ENV LIBSSH_VERSION=0.11.1 ENV SYSTEM_LIBSSH=1 ENV CFLAGS="-g0 -s" -ENV OPENSSL_ROOT_DIR /usr/lib +ENV OPENSSL_ROOT_DIR=/usr/lib RUN apt-get update -y && apt-get install zlib1g-dev cmake -y diff --git a/ci/docker/manylinux/Dockerfile.aarch64_2_28 b/ci/docker/manylinux/Dockerfile.aarch64_2_28 index 2aaab832..aa60616d 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64_2_28 +++ b/ci/docker/manylinux/Dockerfile.aarch64_2_28 @@ -4,7 +4,7 @@ ENV OPENSSL=openssl-3.4.0 ENV LIBSSH_VERSION=0.11.1 ENV SYSTEM_LIBSSH=1 ENV CFLAGS="-g0 -s" -ENV OPENSSL_ROOT_DIR /usr/lib +ENV OPENSSL_ROOT_DIR=/usr/lib RUN yum install zlib-devel cmake3 -y diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 index 452bbdf2..0b026833 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 @@ -4,7 +4,7 @@ ENV OPENSSL=openssl-3.4.0 ENV LIBSSH_VERSION=0.11.1 ENV SYSTEM_LIBSSH=1 ENV CFLAGS="-g0 -s" -ENV OPENSSL_ROOT_DIR /usr/lib +ENV OPENSSL_ROOT_DIR=/usr/lib RUN apt-get update -y && apt-get install zlib1g-dev cmake -y diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 index 66ec2290..ef687aea 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 @@ -4,7 +4,7 @@ ENV OPENSSL=openssl-3.4.0 ENV LIBSSH_VERSION=0.11.1 ENV SYSTEM_LIBSSH=1 ENV CFLAGS="-g0 -s" -ENV OPENSSL_ROOT_DIR /usr/lib +ENV OPENSSL_ROOT_DIR=/usr/lib RUN yum install zlib-devel cmake3 -y From 8d2201446396999055f94080d968fe1ad08bec1b Mon Sep 17 00:00:00 2001 From: Panos Date: Wed, 22 Jan 2025 16:30:48 +0000 Subject: [PATCH 12/46] Updated dockerfiles --- Changelog.rst | 16 ++++++++++++++++ ci/build-manylinux.sh | 2 +- ci/docker/manylinux/Dockerfile.2014_x86_64 | 4 ++-- ci/docker/manylinux/Dockerfile.aarch64 | 2 +- ci/docker/manylinux/Dockerfile.aarch64_2_24 | 2 +- ci/docker/manylinux/Dockerfile.aarch64_2_28 | 2 +- .../manylinux/Dockerfile.manylinux_2_24_x86_64 | 2 +- .../manylinux/Dockerfile.manylinux_2_28_x86_64 | 2 +- 8 files changed, 24 insertions(+), 8 deletions(-) diff --git a/Changelog.rst b/Changelog.rst index 36e93a23..0524b1b7 100644 --- a/Changelog.rst +++ b/Changelog.rst @@ -1,6 +1,22 @@ Change Log ============= +1.1.1 ++++++ + +Changes +-------- + +No code changes. + + +Packaging +---------- + +* Wheel builds now use embedded libssh. +* Dockerfiles and scripts updates. + + 1.1.0 +++++ diff --git a/ci/build-manylinux.sh b/ci/build-manylinux.sh index adbca5a1..a35c544f 100755 --- a/ci/build-manylinux.sh +++ b/ci/build-manylinux.sh @@ -53,7 +53,7 @@ for docker_file in "${docker_files[@]}"; do fi echo "Docker tag is ${docker_tag}" docker pull $docker_tag || echo - docker build --pull --cache-from $docker_tag ci/docker/manylinux -t $docker_tag -f "${docker_file}" + docker build --progress=plain --pull --cache-from $docker_tag ci/docker/manylinux -t $docker_tag -f "${docker_file}" if [[ -z "${CIRCLE_PULL_REQUEST}" ]]; then docker push $docker_tag; fi docker run --rm -v "$(pwd)":/io $docker_tag /io/ci/build-wheels.sh ls wheelhouse/ diff --git a/ci/docker/manylinux/Dockerfile.2014_x86_64 b/ci/docker/manylinux/Dockerfile.2014_x86_64 index cbedbda1..271911c2 100644 --- a/ci/docker/manylinux/Dockerfile.2014_x86_64 +++ b/ci/docker/manylinux/Dockerfile.2014_x86_64 @@ -5,7 +5,7 @@ ENV LIBSSH_VERSION=0.11.1 ENV SYSTEM_LIBSSH=1 ENV CFLAGS="-g0 -s" -RUN yum install zlib-devel cmake3 perl-IPC-Cmd -y +RUN yum update && install zlib-devel cmake3 perl-IPC-Cmd -y ADD libssh-${LIBSSH_VERSION}.tar.gz libssh.tar.gz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz @@ -20,7 +20,7 @@ RUN cd ${OPENSSL} && \ # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ cmake3 ../libssh.tar.gz/libssh -DCMAKE_BUILD_TYPE=Release \ - -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF -DUNIT_TESTING=OFF && \ + -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF -DWITH_SERVER=OFF && \ make -j6 install/strip RUN rm -rf ${OPENSSL}* libssh build_libssh diff --git a/ci/docker/manylinux/Dockerfile.aarch64 b/ci/docker/manylinux/Dockerfile.aarch64 index 0fa9d263..b6a078cc 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64 +++ b/ci/docker/manylinux/Dockerfile.aarch64 @@ -21,7 +21,7 @@ RUN cd ${OPENSSL} && \ # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ cmake3 ../libssh.tar.gz/libssh -DCMAKE_BUILD_TYPE=Release \ - -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF -DUNIT_TESTING=OFF && \ + -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF -DWITH_SERVER=OFF && \ make -j6 install/strip RUN rm -rf ${OPENSSL}* libssh build_libssh diff --git a/ci/docker/manylinux/Dockerfile.aarch64_2_24 b/ci/docker/manylinux/Dockerfile.aarch64_2_24 index 55ac5fcc..459a5393 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64_2_24 +++ b/ci/docker/manylinux/Dockerfile.aarch64_2_24 @@ -21,7 +21,7 @@ RUN cd ${OPENSSL} && \ # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ cmake3 ../libssh.tar.gz/libssh -DCMAKE_BUILD_TYPE=Release \ - -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF && \ + -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF -DWITH_SERVER=OFF && \ make -j6 install/strip RUN rm -rf ${OPENSSL}* libssh build_libssh diff --git a/ci/docker/manylinux/Dockerfile.aarch64_2_28 b/ci/docker/manylinux/Dockerfile.aarch64_2_28 index aa60616d..da0f41ce 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64_2_28 +++ b/ci/docker/manylinux/Dockerfile.aarch64_2_28 @@ -21,7 +21,7 @@ RUN cd ${OPENSSL} && \ # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ cmake3 ../libssh.tar.gz/libssh -DCMAKE_BUILD_TYPE=Release \ - -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF && \ + -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF -DWITH_SERVER=OFF && \ make -j6 install/strip RUN rm -rf ${OPENSSL}* libssh build_libssh diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 index 0b026833..f368bc97 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 @@ -21,7 +21,7 @@ RUN cd ${OPENSSL} && \ # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ cmake3 ../libssh.tar.gz/libssh -DCMAKE_BUILD_TYPE=Release \ - -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF && \ + -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF -DWITH_SERVER=OFF && \ make -j6 install/strip RUN rm -rf ${OPENSSL}* libssh build_libssh diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 index ef687aea..f96abe70 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 @@ -21,7 +21,7 @@ RUN cd ${OPENSSL} && \ # Libssh RUN mkdir -p build_libssh && cd build_libssh && \ cmake3 ../libssh.tar.gz/libssh -DCMAKE_BUILD_TYPE=Release \ - -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF && \ + -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF -DWITH_SERVER=OFF && \ make -j6 install/strip RUN rm -rf ${OPENSSL}* libssh build_libssh From cb0675823792bd9c1d9f557c57f40774e27427c6 Mon Sep 17 00:00:00 2001 From: Panos Date: Wed, 22 Jan 2025 16:31:20 +0000 Subject: [PATCH 13/46] Updated CI cfg --- .circleci/config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c83530e8..c85ddfa2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -168,8 +168,8 @@ workflows: - "15.0.0" - "16.0.0" context: Docker -# filters: -# tags: -# only: /.*/ -# branches: -# ignore: /.*/ + filters: + tags: + only: /.*/ + branches: + ignore: /.*/ From 4e344503828f620f13556320738817bd17c59c76 Mon Sep 17 00:00:00 2001 From: Panos Date: Wed, 22 Jan 2025 16:33:24 +0000 Subject: [PATCH 14/46] Updated dockerfiles --- ci/docker/manylinux/Dockerfile.2014_x86_64 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/docker/manylinux/Dockerfile.2014_x86_64 b/ci/docker/manylinux/Dockerfile.2014_x86_64 index 271911c2..b2d86f79 100644 --- a/ci/docker/manylinux/Dockerfile.2014_x86_64 +++ b/ci/docker/manylinux/Dockerfile.2014_x86_64 @@ -5,7 +5,7 @@ ENV LIBSSH_VERSION=0.11.1 ENV SYSTEM_LIBSSH=1 ENV CFLAGS="-g0 -s" -RUN yum update && install zlib-devel cmake3 perl-IPC-Cmd -y +RUN yum install zlib-devel cmake3 perl-IPC-Cmd -y ADD libssh-${LIBSSH_VERSION}.tar.gz libssh.tar.gz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz From 02cfb9549e65c340acb1f880f93bac5916f4dede Mon Sep 17 00:00:00 2001 From: Panos Date: Wed, 22 Jan 2025 16:45:50 +0000 Subject: [PATCH 15/46] Added krb5 source. Updated dockerfiles. --- ci/docker/manylinux/Dockerfile.2014_x86_64 | 9 + ci/docker/manylinux/Dockerfile.aarch64 | 10 +- .../Dockerfile.manylinux_2_24_x86_64 | 9 + .../Dockerfile.manylinux_2_28_x86_64 | 9 + krb5-1.21.3/.github/workflows/build.yml | 104 + krb5-1.21.3/.github/workflows/doc.yml | 41 + krb5-1.21.3/NOTICE | 1384 + krb5-1.21.3/README | 578 + krb5-1.21.3/doc/README | 56 + krb5-1.21.3/doc/_static/kerb.css_t | 169 + krb5-1.21.3/doc/_templates/layout.html | 73 + krb5-1.21.3/doc/about.rst | 35 + .../doc/admin/admin_commands/index.rst | 17 + .../doc/admin/admin_commands/k5srvutil.rst | 69 + .../doc/admin/admin_commands/kadmin_local.rst | 985 + .../doc/admin/admin_commands/kadmind.rst | 129 + .../admin/admin_commands/kdb5_ldap_util.rst | 449 + .../doc/admin/admin_commands/kdb5_util.rst | 502 + .../doc/admin/admin_commands/kprop.rst | 60 + .../doc/admin/admin_commands/kpropd.rst | 144 + .../doc/admin/admin_commands/kproplog.rst | 85 + .../doc/admin/admin_commands/krb5kdc.rst | 114 + .../doc/admin/admin_commands/ktutil.rst | 129 + .../doc/admin/admin_commands/sserver.rst | 112 + krb5-1.21.3/doc/admin/advanced/index.rst | 8 + .../doc/admin/advanced/retiring-des.rst | 422 + krb5-1.21.3/doc/admin/appl_servers.rst | 171 + krb5-1.21.3/doc/admin/auth_indicator.rst | 57 + krb5-1.21.3/doc/admin/backup_host.rst | 34 + krb5-1.21.3/doc/admin/conf_files/index.rst | 20 + .../doc/admin/conf_files/kadm5_acl.rst | 163 + krb5-1.21.3/doc/admin/conf_files/kdc_conf.rst | 976 + .../doc/admin/conf_files/krb5_conf.rst | 1251 + krb5-1.21.3/doc/admin/conf_ldap.rst | 132 + krb5-1.21.3/doc/admin/database.rst | 587 + krb5-1.21.3/doc/admin/dbtypes.rst | 149 + krb5-1.21.3/doc/admin/dictionary.rst | 88 + krb5-1.21.3/doc/admin/enctypes.rst | 222 + krb5-1.21.3/doc/admin/env_variables.rst | 4 + krb5-1.21.3/doc/admin/host_config.rst | 235 + krb5-1.21.3/doc/admin/https.rst | 48 + krb5-1.21.3/doc/admin/index.rst | 34 + krb5-1.21.3/doc/admin/install.rst | 21 + krb5-1.21.3/doc/admin/install_appl_srv.rst | 78 + krb5-1.21.3/doc/admin/install_clients.rst | 58 + krb5-1.21.3/doc/admin/install_kdc.rst | 536 + krb5-1.21.3/doc/admin/lockout.rst | 154 + krb5-1.21.3/doc/admin/otp.rst | 100 + krb5-1.21.3/doc/admin/pkinit.rst | 354 + krb5-1.21.3/doc/admin/princ_dns.rst | 126 + krb5-1.21.3/doc/admin/realm_config.rst | 268 + krb5-1.21.3/doc/admin/spake.rst | 56 + krb5-1.21.3/doc/admin/troubleshoot.rst | 135 + krb5-1.21.3/doc/admin/various_envs.rst | 27 + krb5-1.21.3/doc/appdev/gssapi.rst | 727 + krb5-1.21.3/doc/appdev/h5l_mit_apidiff.rst | 28 + krb5-1.21.3/doc/appdev/index.rst | 16 + krb5-1.21.3/doc/appdev/init_creds.rst | 304 + krb5-1.21.3/doc/appdev/princ_handle.rst | 79 + krb5-1.21.3/doc/appdev/refs/api/index.rst | 413 + krb5-1.21.3/doc/appdev/refs/index.rst | 9 + krb5-1.21.3/doc/appdev/refs/macros/index.rst | 397 + krb5-1.21.3/doc/appdev/refs/types/index.rst | 108 + .../doc/appdev/refs/types/krb5_int32.rst | 12 + .../doc/appdev/refs/types/krb5_ui_4.rst | 12 + krb5-1.21.3/doc/appdev/y2038.rst | 28 + krb5-1.21.3/doc/basic/ccache_def.rst | 160 + krb5-1.21.3/doc/basic/date_format.rst | 140 + krb5-1.21.3/doc/basic/index.rst | 14 + krb5-1.21.3/doc/basic/keytab_def.rst | 59 + krb5-1.21.3/doc/basic/rcache_def.rst | 111 + krb5-1.21.3/doc/basic/stash_file_def.rst | 25 + krb5-1.21.3/doc/build/directory_org.rst | 75 + krb5-1.21.3/doc/build/doing_build.rst | 148 + krb5-1.21.3/doc/build/index.rst | 63 + krb5-1.21.3/doc/build/options2configure.rst | 397 + krb5-1.21.3/doc/build/osconf.rst | 26 + krb5-1.21.3/doc/build_this.rst | 82 + krb5-1.21.3/doc/coding-style | 5 + krb5-1.21.3/doc/conf.py | 320 + krb5-1.21.3/doc/contributing.txt | 70 + krb5-1.21.3/doc/copyright.rst | 8 + krb5-1.21.3/doc/doxy_examples/cc_set_config.c | 33 + krb5-1.21.3/doc/doxy_examples/cc_unique.c | 23 + krb5-1.21.3/doc/doxy_examples/error_message.c | 20 + krb5-1.21.3/doc/doxy_examples/tkt_creds.c | 55 + .../doc/doxy_examples/verify_init_creds.c | 28 + .../doc/formats/ccache_file_format.rst | 182 + krb5-1.21.3/doc/formats/cookie.rst | 97 + krb5-1.21.3/doc/formats/freshness_token.rst | 19 + krb5-1.21.3/doc/formats/index.rst | 11 + .../doc/formats/keytab_file_format.rst | 51 + .../doc/formats/rcache_file_format.rst | 50 + krb5-1.21.3/doc/html/.buildinfo | 4 + krb5-1.21.3/doc/html/_sources/about.rst.txt | 35 + .../admin/admin_commands/index.rst.txt | 17 + .../admin/admin_commands/k5srvutil.rst.txt | 69 + .../admin/admin_commands/kadmin_local.rst.txt | 985 + .../admin/admin_commands/kadmind.rst.txt | 129 + .../admin_commands/kdb5_ldap_util.rst.txt | 449 + .../admin/admin_commands/kdb5_util.rst.txt | 502 + .../admin/admin_commands/kprop.rst.txt | 60 + .../admin/admin_commands/kpropd.rst.txt | 144 + .../admin/admin_commands/kproplog.rst.txt | 85 + .../admin/admin_commands/krb5kdc.rst.txt | 114 + .../admin/admin_commands/ktutil.rst.txt | 129 + .../admin/admin_commands/sserver.rst.txt | 112 + .../_sources/admin/advanced/index.rst.txt | 8 + .../admin/advanced/retiring-des.rst.txt | 422 + .../html/_sources/admin/appl_servers.rst.txt | 171 + .../_sources/admin/auth_indicator.rst.txt | 57 + .../html/_sources/admin/backup_host.rst.txt | 34 + .../_sources/admin/conf_files/index.rst.txt | 20 + .../admin/conf_files/kadm5_acl.rst.txt | 163 + .../admin/conf_files/kdc_conf.rst.txt | 976 + .../admin/conf_files/krb5_conf.rst.txt | 1251 + .../doc/html/_sources/admin/conf_ldap.rst.txt | 132 + .../doc/html/_sources/admin/database.rst.txt | 587 + .../doc/html/_sources/admin/dbtypes.rst.txt | 149 + .../html/_sources/admin/dictionary.rst.txt | 88 + .../doc/html/_sources/admin/enctypes.rst.txt | 222 + .../html/_sources/admin/env_variables.rst.txt | 4 + .../html/_sources/admin/host_config.rst.txt | 235 + .../doc/html/_sources/admin/https.rst.txt | 48 + .../doc/html/_sources/admin/index.rst.txt | 34 + .../doc/html/_sources/admin/install.rst.txt | 21 + .../_sources/admin/install_appl_srv.rst.txt | 78 + .../_sources/admin/install_clients.rst.txt | 58 + .../html/_sources/admin/install_kdc.rst.txt | 536 + .../doc/html/_sources/admin/lockout.rst.txt | 154 + .../doc/html/_sources/admin/otp.rst.txt | 100 + .../doc/html/_sources/admin/pkinit.rst.txt | 354 + .../doc/html/_sources/admin/princ_dns.rst.txt | 126 + .../html/_sources/admin/realm_config.rst.txt | 268 + .../doc/html/_sources/admin/spake.rst.txt | 56 + .../html/_sources/admin/troubleshoot.rst.txt | 135 + .../html/_sources/admin/various_envs.rst.txt | 27 + .../doc/html/_sources/appdev/gssapi.rst.txt | 727 + .../_sources/appdev/h5l_mit_apidiff.rst.txt | 28 + .../doc/html/_sources/appdev/index.rst.txt | 16 + .../html/_sources/appdev/init_creds.rst.txt | 304 + .../html/_sources/appdev/princ_handle.rst.txt | 79 + .../_sources/appdev/refs/api/index.rst.txt | 413 + .../refs/api/krb5_425_conv_principal.rst.txt | 59 + .../refs/api/krb5_524_conv_principal.rst.txt | 60 + .../refs/api/krb5_524_convert_creds.rst.txt | 55 + .../refs/api/krb5_address_compare.rst.txt | 47 + .../refs/api/krb5_address_order.rst.txt | 49 + .../refs/api/krb5_address_search.rst.txt | 55 + .../refs/api/krb5_allow_weak_crypto.rst.txt | 49 + .../refs/api/krb5_aname_to_localname.rst.txt | 61 + .../refs/api/krb5_anonymous_principal.rst.txt | 47 + .../refs/api/krb5_anonymous_realm.rst.txt | 47 + .../refs/api/krb5_appdefault_boolean.rst.txt | 57 + .../refs/api/krb5_appdefault_string.rst.txt | 57 + .../refs/api/krb5_auth_con_free.rst.txt | 49 + .../refs/api/krb5_auth_con_genaddrs.rst.txt | 66 + .../krb5_auth_con_get_checksum_func.rst.txt | 49 + .../refs/api/krb5_auth_con_getaddrs.rst.txt | 49 + .../krb5_auth_con_getauthenticator.rst.txt | 51 + .../refs/api/krb5_auth_con_getflags.rst.txt | 60 + .../refs/api/krb5_auth_con_getkey.rst.txt | 51 + .../refs/api/krb5_auth_con_getkey_k.rst.txt | 51 + .../krb5_auth_con_getlocalseqnumber.rst.txt | 51 + .../api/krb5_auth_con_getlocalsubkey.rst.txt | 46 + .../refs/api/krb5_auth_con_getrcache.rst.txt | 51 + .../api/krb5_auth_con_getrecvsubkey.rst.txt | 51 + .../api/krb5_auth_con_getrecvsubkey_k.rst.txt | 51 + .../krb5_auth_con_getremoteseqnumber.rst.txt | 51 + .../api/krb5_auth_con_getremotesubkey.rst.txt | 46 + .../api/krb5_auth_con_getsendsubkey.rst.txt | 51 + .../api/krb5_auth_con_getsendsubkey_k.rst.txt | 51 + .../refs/api/krb5_auth_con_init.rst.txt | 57 + .../api/krb5_auth_con_initivector.rst.txt | 49 + .../krb5_auth_con_set_checksum_func.rst.txt | 53 + .../krb5_auth_con_set_req_cksumtype.rst.txt | 51 + .../refs/api/krb5_auth_con_setaddrs.rst.txt | 56 + .../refs/api/krb5_auth_con_setflags.rst.txt | 60 + .../refs/api/krb5_auth_con_setports.rst.txt | 56 + .../refs/api/krb5_auth_con_setrcache.rst.txt | 51 + .../api/krb5_auth_con_setrecvsubkey.rst.txt | 51 + .../api/krb5_auth_con_setrecvsubkey_k.rst.txt | 55 + .../api/krb5_auth_con_setsendsubkey.rst.txt | 51 + .../api/krb5_auth_con_setsendsubkey_k.rst.txt | 55 + .../api/krb5_auth_con_setuseruserkey.rst.txt | 47 + .../refs/api/krb5_build_principal.rst.txt | 72 + .../api/krb5_build_principal_alloc_va.rst.txt | 66 + .../refs/api/krb5_build_principal_ext.rst.txt | 64 + .../refs/api/krb5_build_principal_va.rst.txt | 50 + .../appdev/refs/api/krb5_c_block_size.rst.txt | 47 + .../refs/api/krb5_c_checksum_length.rst.txt | 47 + .../refs/api/krb5_c_crypto_length.rst.txt | 49 + .../refs/api/krb5_c_crypto_length_iov.rst.txt | 53 + .../appdev/refs/api/krb5_c_decrypt.rst.txt | 65 + .../refs/api/krb5_c_decrypt_iov.rst.txt | 68 + .../refs/api/krb5_c_derive_prfplus.rst.txt | 48 + .../appdev/refs/api/krb5_c_encrypt.rst.txt | 65 + .../refs/api/krb5_c_encrypt_iov.rst.txt | 68 + .../refs/api/krb5_c_encrypt_length.rst.txt | 53 + .../refs/api/krb5_c_enctype_compare.rst.txt | 53 + .../appdev/refs/api/krb5_c_free_state.rst.txt | 47 + .../refs/api/krb5_c_fx_cf2_simple.rst.txt | 57 + .../appdev/refs/api/krb5_c_init_state.rst.txt | 49 + .../api/krb5_c_is_coll_proof_cksum.rst.txt | 43 + .../refs/api/krb5_c_is_keyed_cksum.rst.txt | 43 + .../api/krb5_c_keyed_checksum_types.rst.txt | 53 + .../appdev/refs/api/krb5_c_keylengths.rst.txt | 49 + .../refs/api/krb5_c_make_checksum.rst.txt | 68 + .../refs/api/krb5_c_make_checksum_iov.rst.txt | 68 + .../refs/api/krb5_c_make_random_key.rst.txt | 51 + .../refs/api/krb5_c_padding_length.rst.txt | 53 + .../appdev/refs/api/krb5_c_prf.rst.txt | 53 + .../appdev/refs/api/krb5_c_prf_length.rst.txt | 47 + .../appdev/refs/api/krb5_c_prfplus.rst.txt | 61 + .../api/krb5_c_random_add_entropy.rst.txt | 46 + .../api/krb5_c_random_make_octets.rst.txt | 49 + .../refs/api/krb5_c_random_os_entropy.rst.txt | 46 + .../refs/api/krb5_c_random_seed.rst.txt | 44 + .../refs/api/krb5_c_random_to_key.rst.txt | 64 + .../refs/api/krb5_c_string_to_key.rst.txt | 55 + .../krb5_c_string_to_key_with_params.rst.txt | 57 + .../refs/api/krb5_c_valid_cksumtype.rst.txt | 43 + .../refs/api/krb5_c_valid_enctype.rst.txt | 43 + .../refs/api/krb5_c_verify_checksum.rst.txt | 65 + .../api/krb5_c_verify_checksum_iov.rst.txt | 70 + .../refs/api/krb5_calculate_checksum.rst.txt | 54 + .../refs/api/krb5_cc_cache_match.rst.txt | 56 + .../appdev/refs/api/krb5_cc_close.rst.txt | 52 + .../refs/api/krb5_cc_copy_creds.rst.txt | 47 + .../appdev/refs/api/krb5_cc_default.rst.txt | 54 + .../refs/api/krb5_cc_default_name.rst.txt | 51 + .../appdev/refs/api/krb5_cc_destroy.rst.txt | 52 + .../appdev/refs/api/krb5_cc_dup.rst.txt | 44 + .../refs/api/krb5_cc_end_seq_get.rst.txt | 54 + .../appdev/refs/api/krb5_cc_gen_new.rst.txt | 39 + .../refs/api/krb5_cc_get_config.rst.txt | 58 + .../appdev/refs/api/krb5_cc_get_flags.rst.txt | 55 + .../refs/api/krb5_cc_get_full_name.rst.txt | 52 + .../appdev/refs/api/krb5_cc_get_name.rst.txt | 53 + .../refs/api/krb5_cc_get_principal.rst.txt | 58 + .../appdev/refs/api/krb5_cc_get_type.rst.txt | 45 + .../refs/api/krb5_cc_initialize.rst.txt | 54 + .../appdev/refs/api/krb5_cc_move.rst.txt | 54 + .../refs/api/krb5_cc_new_unique.rst.txt | 52 + .../appdev/refs/api/krb5_cc_next_cred.rst.txt | 60 + .../refs/api/krb5_cc_remove_cred.rst.txt | 64 + .../appdev/refs/api/krb5_cc_resolve.rst.txt | 58 + .../refs/api/krb5_cc_retrieve_cred.rst.txt | 94 + .../appdev/refs/api/krb5_cc_select.rst.txt | 73 + .../refs/api/krb5_cc_set_config.rst.txt | 66 + .../refs/api/krb5_cc_set_default_name.rst.txt | 57 + .../appdev/refs/api/krb5_cc_set_flags.rst.txt | 51 + .../refs/api/krb5_cc_start_seq_get.rst.txt | 59 + .../refs/api/krb5_cc_store_cred.rst.txt | 54 + .../refs/api/krb5_cc_support_switch.rst.txt | 50 + .../appdev/refs/api/krb5_cc_switch.rst.txt | 52 + .../refs/api/krb5_cccol_cursor_free.rst.txt | 48 + .../refs/api/krb5_cccol_cursor_new.rst.txt | 56 + .../refs/api/krb5_cccol_cursor_next.rst.txt | 62 + .../refs/api/krb5_cccol_have_content.rst.txt | 48 + .../refs/api/krb5_change_password.rst.txt | 77 + .../refs/api/krb5_check_clockskew.rst.txt | 54 + .../refs/api/krb5_checksum_size.rst.txt | 44 + .../appdev/refs/api/krb5_chpw_message.rst.txt | 62 + .../refs/api/krb5_cksumtype_to_string.rst.txt | 47 + .../refs/api/krb5_clear_error_message.rst.txt | 40 + .../refs/api/krb5_copy_addresses.rst.txt | 51 + .../refs/api/krb5_copy_authdata.rst.txt | 59 + .../refs/api/krb5_copy_authenticator.rst.txt | 51 + .../refs/api/krb5_copy_checksum.rst.txt | 51 + .../appdev/refs/api/krb5_copy_context.rst.txt | 52 + .../appdev/refs/api/krb5_copy_creds.rst.txt | 51 + .../appdev/refs/api/krb5_copy_data.rst.txt | 51 + .../refs/api/krb5_copy_error_message.rst.txt | 42 + .../refs/api/krb5_copy_keyblock.rst.txt | 51 + .../api/krb5_copy_keyblock_contents.rst.txt | 51 + .../refs/api/krb5_copy_principal.rst.txt | 51 + .../appdev/refs/api/krb5_copy_ticket.rst.txt | 51 + .../krb5_decode_authdata_container.rst.txt | 52 + .../refs/api/krb5_decode_ticket.rst.txt | 45 + .../appdev/refs/api/krb5_decrypt.rst.txt | 52 + .../refs/api/krb5_deltat_to_string.rst.txt | 47 + .../refs/api/krb5_eblock_enctype.rst.txt | 44 + .../krb5_encode_authdata_container.rst.txt | 56 + .../appdev/refs/api/krb5_encrypt.rst.txt | 52 + .../appdev/refs/api/krb5_encrypt_size.rst.txt | 44 + .../refs/api/krb5_enctype_to_name.rst.txt | 57 + .../refs/api/krb5_enctype_to_string.rst.txt | 47 + .../refs/api/krb5_expand_hostname.rst.txt | 52 + .../refs/api/krb5_find_authdata.rst.txt | 56 + .../appdev/refs/api/krb5_finish_key.rst.txt | 44 + .../refs/api/krb5_finish_random_key.rst.txt | 46 + .../refs/api/krb5_free_addresses.rst.txt | 54 + .../api/krb5_free_ap_rep_enc_part.rst.txt | 42 + .../refs/api/krb5_free_authdata.rst.txt | 54 + .../refs/api/krb5_free_authenticator.rst.txt | 42 + .../refs/api/krb5_free_checksum.rst.txt | 42 + .../api/krb5_free_checksum_contents.rst.txt | 42 + .../refs/api/krb5_free_cksumtypes.rst.txt | 42 + .../appdev/refs/api/krb5_free_context.rst.txt | 40 + .../refs/api/krb5_free_cred_contents.rst.txt | 42 + .../appdev/refs/api/krb5_free_creds.rst.txt | 42 + .../appdev/refs/api/krb5_free_data.rst.txt | 42 + .../refs/api/krb5_free_data_contents.rst.txt | 42 + .../refs/api/krb5_free_default_realm.rst.txt | 42 + .../refs/api/krb5_free_enctypes.rst.txt | 46 + .../appdev/refs/api/krb5_free_error.rst.txt | 42 + .../refs/api/krb5_free_error_message.rst.txt | 42 + .../refs/api/krb5_free_host_realm.rst.txt | 48 + .../refs/api/krb5_free_keyblock.rst.txt | 42 + .../api/krb5_free_keyblock_contents.rst.txt | 42 + .../krb5_free_keytab_entry_contents.rst.txt | 53 + .../refs/api/krb5_free_principal.rst.txt | 42 + .../appdev/refs/api/krb5_free_string.rst.txt | 46 + .../refs/api/krb5_free_tgt_creds.rst.txt | 50 + .../appdev/refs/api/krb5_free_ticket.rst.txt | 42 + .../refs/api/krb5_free_unparsed_name.rst.txt | 42 + .../refs/api/krb5_fwd_tgt_creds.rst.txt | 68 + .../refs/api/krb5_get_credentials.rst.txt | 81 + .../api/krb5_get_credentials_renew.rst.txt | 50 + .../api/krb5_get_credentials_validate.rst.txt | 50 + .../refs/api/krb5_get_default_realm.rst.txt | 56 + .../refs/api/krb5_get_error_message.rst.txt | 62 + .../refs/api/krb5_get_etype_info.rst.txt | 72 + .../api/krb5_get_fallback_host_realm.rst.txt | 52 + .../refs/api/krb5_get_host_realm.rst.txt | 63 + .../api/krb5_get_in_tkt_with_keytab.rst.txt | 58 + .../api/krb5_get_in_tkt_with_password.rst.txt | 58 + .../api/krb5_get_in_tkt_with_skey.rst.txt | 58 + .../api/krb5_get_init_creds_keytab.rst.txt | 62 + .../api/krb5_get_init_creds_opt_alloc.rst.txt | 49 + .../api/krb5_get_init_creds_opt_free.rst.txt | 45 + ..._get_init_creds_opt_get_fast_flags.rst.txt | 47 + .../api/krb5_get_init_creds_opt_init.rst.txt | 42 + ...et_init_creds_opt_set_address_list.rst.txt | 42 + ...5_get_init_creds_opt_set_anonymous.rst.txt | 42 + ...et_init_creds_opt_set_canonicalize.rst.txt | 42 + ...eds_opt_set_change_password_prompt.rst.txt | 42 + ..._get_init_creds_opt_set_etype_list.rst.txt | 44 + ...init_creds_opt_set_expire_callback.rst.txt | 78 + ...get_init_creds_opt_set_fast_ccache.rst.txt | 52 + ...nit_creds_opt_set_fast_ccache_name.rst.txt | 48 + ..._get_init_creds_opt_set_fast_flags.rst.txt | 51 + ...get_init_creds_opt_set_forwardable.rst.txt | 42 + ...5_get_init_creds_opt_set_in_ccache.rst.txt | 52 + ..._get_init_creds_opt_set_out_ccache.rst.txt | 44 + .../krb5_get_init_creds_opt_set_pa.rst.txt | 46 + ...get_init_creds_opt_set_pac_request.rst.txt | 52 + ...et_init_creds_opt_set_preauth_list.rst.txt | 44 + ...5_get_init_creds_opt_set_proxiable.rst.txt | 42 + ..._get_init_creds_opt_set_renew_life.rst.txt | 42 + ...5_get_init_creds_opt_set_responder.rst.txt | 50 + .../krb5_get_init_creds_opt_set_salt.rst.txt | 42 + ...b5_get_init_creds_opt_set_tkt_life.rst.txt | 42 + .../api/krb5_get_init_creds_password.rst.txt | 75 + .../api/krb5_get_permitted_enctypes.rst.txt | 53 + .../appdev/refs/api/krb5_get_profile.rst.txt | 56 + .../refs/api/krb5_get_prompt_types.rst.txt | 43 + .../refs/api/krb5_get_renewed_creds.rst.txt | 62 + .../refs/api/krb5_get_server_rcache.rst.txt | 55 + .../refs/api/krb5_get_time_offsets.rst.txt | 51 + .../refs/api/krb5_get_validated_creds.rst.txt | 67 + .../appdev/refs/api/krb5_init_context.rst.txt | 58 + .../api/krb5_init_context_profile.rst.txt | 55 + .../refs/api/krb5_init_creds_free.rst.txt | 42 + .../refs/api/krb5_init_creds_get.rst.txt | 53 + .../api/krb5_init_creds_get_creds.rst.txt | 51 + .../api/krb5_init_creds_get_error.rst.txt | 47 + .../api/krb5_init_creds_get_times.rst.txt | 51 + .../refs/api/krb5_init_creds_init.rst.txt | 63 + .../api/krb5_init_creds_set_keytab.rst.txt | 51 + .../api/krb5_init_creds_set_password.rst.txt | 51 + .../api/krb5_init_creds_set_service.rst.txt | 51 + .../refs/api/krb5_init_creds_step.rst.txt | 69 + .../refs/api/krb5_init_keyblock.rst.txt | 61 + .../refs/api/krb5_init_random_key.rst.txt | 48 + .../refs/api/krb5_init_secure_context.rst.txt | 54 + .../refs/api/krb5_is_config_principal.rst.txt | 45 + .../refs/api/krb5_is_referral_realm.rst.txt | 43 + .../refs/api/krb5_is_thread_safe.rst.txt | 43 + .../appdev/refs/api/krb5_k_create_key.rst.txt | 51 + .../appdev/refs/api/krb5_k_decrypt.rst.txt | 65 + .../refs/api/krb5_k_decrypt_iov.rst.txt | 68 + .../appdev/refs/api/krb5_k_encrypt.rst.txt | 65 + .../refs/api/krb5_k_encrypt_iov.rst.txt | 68 + .../appdev/refs/api/krb5_k_free_key.rst.txt | 39 + .../refs/api/krb5_k_key_enctype.rst.txt | 39 + .../refs/api/krb5_k_key_keyblock.rst.txt | 41 + .../refs/api/krb5_k_make_checksum.rst.txt | 68 + .../refs/api/krb5_k_make_checksum_iov.rst.txt | 68 + .../appdev/refs/api/krb5_k_prf.rst.txt | 61 + .../refs/api/krb5_k_reference_key.rst.txt | 39 + .../refs/api/krb5_k_verify_checksum.rst.txt | 65 + .../api/krb5_k_verify_checksum_iov.rst.txt | 70 + .../refs/api/krb5_kdc_sign_ticket.rst.txt | 65 + .../refs/api/krb5_kdc_verify_ticket.rst.txt | 73 + .../appdev/refs/api/krb5_kt_add_entry.rst.txt | 52 + .../refs/api/krb5_kt_client_default.rst.txt | 56 + .../appdev/refs/api/krb5_kt_close.rst.txt | 45 + .../appdev/refs/api/krb5_kt_default.rst.txt | 52 + .../refs/api/krb5_kt_default_name.rst.txt | 55 + .../appdev/refs/api/krb5_kt_dup.rst.txt | 52 + .../refs/api/krb5_kt_end_seq_get.rst.txt | 54 + .../refs/api/krb5_kt_free_entry.rst.txt | 44 + .../appdev/refs/api/krb5_kt_get_entry.rst.txt | 70 + .../appdev/refs/api/krb5_kt_get_name.rst.txt | 57 + .../appdev/refs/api/krb5_kt_get_type.rst.txt | 45 + .../refs/api/krb5_kt_have_content.rst.txt | 50 + .../refs/api/krb5_kt_next_entry.rst.txt | 57 + .../refs/api/krb5_kt_read_service_key.rst.txt | 68 + .../refs/api/krb5_kt_remove_entry.rst.txt | 51 + .../appdev/refs/api/krb5_kt_resolve.rst.txt | 66 + .../refs/api/krb5_kt_start_seq_get.rst.txt | 54 + .../appdev/refs/api/krb5_kuserok.rst.txt | 51 + .../api/krb5_make_authdata_kdc_issued.rst.txt | 48 + .../refs/api/krb5_marshal_credentials.rst.txt | 55 + .../refs/api/krb5_merge_authdata.rst.txt | 61 + .../appdev/refs/api/krb5_mk_1cred.rst.txt | 60 + .../appdev/refs/api/krb5_mk_error.rst.txt | 51 + .../appdev/refs/api/krb5_mk_ncred.rst.txt | 88 + .../appdev/refs/api/krb5_mk_priv.rst.txt | 79 + .../appdev/refs/api/krb5_mk_rep.rst.txt | 59 + .../appdev/refs/api/krb5_mk_rep_dce.rst.txt | 51 + .../appdev/refs/api/krb5_mk_req.rst.txt | 65 + .../refs/api/krb5_mk_req_extended.rst.txt | 74 + .../appdev/refs/api/krb5_mk_safe.rst.txt | 83 + .../appdev/refs/api/krb5_os_localaddr.rst.txt | 49 + .../refs/api/krb5_pac_add_buffer.rst.txt | 75 + .../appdev/refs/api/krb5_pac_free.rst.txt | 42 + .../refs/api/krb5_pac_get_buffer.rst.txt | 53 + .../refs/api/krb5_pac_get_client_info.rst.txt | 57 + .../refs/api/krb5_pac_get_types.rst.txt | 49 + .../appdev/refs/api/krb5_pac_init.rst.txt | 49 + .../appdev/refs/api/krb5_pac_parse.rst.txt | 53 + .../appdev/refs/api/krb5_pac_sign.rst.txt | 54 + .../appdev/refs/api/krb5_pac_sign_ext.rst.txt | 56 + .../appdev/refs/api/krb5_pac_verify.rst.txt | 69 + .../refs/api/krb5_pac_verify_ext.rst.txt | 60 + .../appdev/refs/api/krb5_parse_name.rst.txt | 78 + .../refs/api/krb5_parse_name_flags.rst.txt | 77 + .../api/krb5_prepend_error_message.rst.txt | 44 + .../refs/api/krb5_principal2salt.rst.txt | 47 + .../refs/api/krb5_principal_compare.rst.txt | 47 + .../krb5_principal_compare_any_realm.rst.txt | 51 + .../api/krb5_principal_compare_flags.rst.txt | 65 + .../appdev/refs/api/krb5_process_key.rst.txt | 46 + .../refs/api/krb5_prompter_posix.rst.txt | 64 + .../appdev/refs/api/krb5_random_key.rst.txt | 48 + .../appdev/refs/api/krb5_rd_cred.rst.txt | 67 + .../appdev/refs/api/krb5_rd_error.rst.txt | 51 + .../appdev/refs/api/krb5_rd_priv.rst.txt | 79 + .../appdev/refs/api/krb5_rd_rep.rst.txt | 57 + .../appdev/refs/api/krb5_rd_rep_dce.rst.txt | 53 + .../appdev/refs/api/krb5_rd_req.rst.txt | 105 + .../appdev/refs/api/krb5_rd_safe.rst.txt | 79 + .../refs/api/krb5_read_password.rst.txt | 71 + .../refs/api/krb5_realm_compare.rst.txt | 47 + .../appdev/refs/api/krb5_recvauth.rst.txt | 68 + .../refs/api/krb5_recvauth_version.rst.txt | 61 + .../api/krb5_responder_get_challenge.rst.txt | 52 + .../api/krb5_responder_list_questions.rst.txt | 50 + .../krb5_responder_otp_challenge_free.rst.txt | 48 + .../krb5_responder_otp_get_challenge.rst.txt | 56 + .../api/krb5_responder_otp_set_answer.rst.txt | 52 + ...b5_responder_pkinit_challenge_free.rst.txt | 48 + ...rb5_responder_pkinit_get_challenge.rst.txt | 56 + .../krb5_responder_pkinit_set_answer.rst.txt | 50 + .../api/krb5_responder_set_answer.rst.txt | 57 + .../refs/api/krb5_salttype_to_string.rst.txt | 47 + .../appdev/refs/api/krb5_sendauth.rst.txt | 98 + .../krb5_server_decrypt_ticket_keytab.rst.txt | 51 + .../refs/api/krb5_set_default_realm.rst.txt | 52 + .../api/krb5_set_default_tgs_enctypes.rst.txt | 61 + .../refs/api/krb5_set_error_message.rst.txt | 44 + .../refs/api/krb5_set_kdc_recv_hook.rst.txt | 52 + .../refs/api/krb5_set_kdc_send_hook.rst.txt | 52 + .../appdev/refs/api/krb5_set_password.rst.txt | 74 + .../krb5_set_password_using_ccache.rst.txt | 74 + .../refs/api/krb5_set_principal_realm.rst.txt | 54 + .../refs/api/krb5_set_real_time.rst.txt | 51 + .../refs/api/krb5_set_trace_callback.rst.txt | 63 + .../refs/api/krb5_set_trace_filename.rst.txt | 61 + .../appdev/refs/api/krb5_sname_match.rst.txt | 59 + .../refs/api/krb5_sname_to_principal.rst.txt | 74 + .../refs/api/krb5_string_to_cksumtype.rst.txt | 45 + .../refs/api/krb5_string_to_deltat.rst.txt | 45 + .../refs/api/krb5_string_to_enctype.rst.txt | 45 + .../refs/api/krb5_string_to_key.rst.txt | 50 + .../refs/api/krb5_string_to_salttype.rst.txt | 45 + .../refs/api/krb5_string_to_timestamp.rst.txt | 45 + .../appdev/refs/api/krb5_timeofday.rst.txt | 52 + .../api/krb5_timestamp_to_sfstring.rst.txt | 53 + .../refs/api/krb5_timestamp_to_string.rst.txt | 51 + .../refs/api/krb5_tkt_creds_free.rst.txt | 46 + .../refs/api/krb5_tkt_creds_get.rst.txt | 53 + .../refs/api/krb5_tkt_creds_get_creds.rst.txt | 55 + .../refs/api/krb5_tkt_creds_get_times.rst.txt | 55 + .../refs/api/krb5_tkt_creds_init.rst.txt | 67 + .../refs/api/krb5_tkt_creds_step.rst.txt | 69 + .../api/krb5_unmarshal_credentials.rst.txt | 55 + .../appdev/refs/api/krb5_unparse_name.rst.txt | 58 + .../refs/api/krb5_unparse_name_ext.rst.txt | 60 + .../refs/api/krb5_unparse_name_flags.rst.txt | 70 + .../api/krb5_unparse_name_flags_ext.rst.txt | 54 + .../appdev/refs/api/krb5_us_timeofday.rst.txt | 54 + .../appdev/refs/api/krb5_use_enctype.rst.txt | 46 + .../krb5_verify_authdata_kdc_issued.rst.txt | 48 + .../refs/api/krb5_verify_checksum.rst.txt | 54 + .../refs/api/krb5_verify_init_creds.rst.txt | 65 + .../krb5_verify_init_creds_opt_init.rst.txt | 40 + ...y_init_creds_opt_set_ap_req_nofail.rst.txt | 46 + .../api/krb5_vprepend_error_message.rst.txt | 46 + .../refs/api/krb5_vset_error_message.rst.txt | 46 + .../refs/api/krb5_vwrap_error_message.rst.txt | 48 + .../refs/api/krb5_wrap_error_message.rst.txt | 46 + .../html/_sources/appdev/refs/index.rst.txt | 9 + .../refs/macros/ADDRTYPE_ADDRPORT.rst.txt | 17 + .../appdev/refs/macros/ADDRTYPE_CHAOS.rst.txt | 17 + .../appdev/refs/macros/ADDRTYPE_DDP.rst.txt | 17 + .../appdev/refs/macros/ADDRTYPE_INET.rst.txt | 17 + .../appdev/refs/macros/ADDRTYPE_INET6.rst.txt | 17 + .../refs/macros/ADDRTYPE_IPPORT.rst.txt | 17 + .../appdev/refs/macros/ADDRTYPE_ISO.rst.txt | 17 + .../refs/macros/ADDRTYPE_IS_LOCAL.rst.txt | 17 + .../refs/macros/ADDRTYPE_NETBIOS.rst.txt | 17 + .../appdev/refs/macros/ADDRTYPE_XNS.rst.txt | 17 + .../refs/macros/AD_TYPE_EXTERNAL.rst.txt | 17 + .../macros/AD_TYPE_FIELD_TYPE_MASK.rst.txt | 17 + .../refs/macros/AD_TYPE_REGISTERED.rst.txt | 17 + .../refs/macros/AD_TYPE_RESERVED.rst.txt | 17 + .../macros/AP_OPTS_ETYPE_NEGOTIATION.rst.txt | 17 + .../macros/AP_OPTS_MUTUAL_REQUIRED.rst.txt | 18 + .../refs/macros/AP_OPTS_RESERVED.rst.txt | 17 + .../macros/AP_OPTS_USE_SESSION_KEY.rst.txt | 18 + .../refs/macros/AP_OPTS_USE_SUBKEY.rst.txt | 18 + .../refs/macros/AP_OPTS_WIRE_MASK.rst.txt | 17 + .../macros/CKSUMTYPE_CMAC_CAMELLIA128.rst.txt | 18 + .../macros/CKSUMTYPE_CMAC_CAMELLIA256.rst.txt | 18 + .../refs/macros/CKSUMTYPE_CRC32.rst.txt | 17 + .../refs/macros/CKSUMTYPE_DESCBC.rst.txt | 17 + .../macros/CKSUMTYPE_HMAC_MD5_ARCFOUR.rst.txt | 18 + .../CKSUMTYPE_HMAC_SHA1_96_AES128.rst.txt | 18 + .../CKSUMTYPE_HMAC_SHA1_96_AES256.rst.txt | 18 + .../macros/CKSUMTYPE_HMAC_SHA1_DES3.rst.txt | 17 + .../CKSUMTYPE_HMAC_SHA256_128_AES128.rst.txt | 18 + .../CKSUMTYPE_HMAC_SHA384_192_AES256.rst.txt | 18 + .../macros/CKSUMTYPE_MD5_HMAC_ARCFOUR.rst.txt | 17 + .../refs/macros/CKSUMTYPE_NIST_SHA.rst.txt | 17 + .../refs/macros/CKSUMTYPE_RSA_MD4.rst.txt | 17 + .../refs/macros/CKSUMTYPE_RSA_MD4_DES.rst.txt | 17 + .../refs/macros/CKSUMTYPE_RSA_MD5.rst.txt | 17 + .../refs/macros/CKSUMTYPE_RSA_MD5_DES.rst.txt | 17 + .../appdev/refs/macros/CKSUMTYPE_SHA1.rst.txt | 18 + .../ENCTYPE_AES128_CTS_HMAC_SHA1_96.rst.txt | 18 + ...ENCTYPE_AES128_CTS_HMAC_SHA256_128.rst.txt | 18 + .../ENCTYPE_AES256_CTS_HMAC_SHA1_96.rst.txt | 18 + ...ENCTYPE_AES256_CTS_HMAC_SHA384_192.rst.txt | 18 + .../refs/macros/ENCTYPE_ARCFOUR_HMAC.rst.txt | 18 + .../macros/ENCTYPE_ARCFOUR_HMAC_EXP.rst.txt | 18 + .../ENCTYPE_CAMELLIA128_CTS_CMAC.rst.txt | 18 + .../ENCTYPE_CAMELLIA256_CTS_CMAC.rst.txt | 18 + .../refs/macros/ENCTYPE_DES3_CBC_ENV.rst.txt | 18 + .../refs/macros/ENCTYPE_DES3_CBC_RAW.rst.txt | 17 + .../refs/macros/ENCTYPE_DES3_CBC_SHA.rst.txt | 17 + .../refs/macros/ENCTYPE_DES3_CBC_SHA1.rst.txt | 17 + .../refs/macros/ENCTYPE_DES_CBC_CRC.rst.txt | 17 + .../refs/macros/ENCTYPE_DES_CBC_MD4.rst.txt | 17 + .../refs/macros/ENCTYPE_DES_CBC_MD5.rst.txt | 17 + .../refs/macros/ENCTYPE_DES_CBC_RAW.rst.txt | 17 + .../refs/macros/ENCTYPE_DES_HMAC_SHA1.rst.txt | 17 + .../refs/macros/ENCTYPE_DSA_SHA1_CMS.rst.txt | 18 + .../refs/macros/ENCTYPE_MD5_RSA_CMS.rst.txt | 18 + .../appdev/refs/macros/ENCTYPE_NULL.rst.txt | 17 + .../refs/macros/ENCTYPE_RC2_CBC_ENV.rst.txt | 18 + .../refs/macros/ENCTYPE_RSA_ENV.rst.txt | 18 + .../macros/ENCTYPE_RSA_ES_OAEP_ENV.rst.txt | 18 + .../refs/macros/ENCTYPE_SHA1_RSA_CMS.rst.txt | 18 + .../refs/macros/ENCTYPE_UNKNOWN.rst.txt | 17 + .../macros/KDC_OPT_ALLOW_POSTDATE.rst.txt | 17 + .../refs/macros/KDC_OPT_CANONICALIZE.rst.txt | 17 + .../macros/KDC_OPT_CNAME_IN_ADDL_TKT.rst.txt | 17 + .../KDC_OPT_DISABLE_TRANSITED_CHECK.rst.txt | 17 + .../macros/KDC_OPT_ENC_TKT_IN_SKEY.rst.txt | 17 + .../refs/macros/KDC_OPT_FORWARDABLE.rst.txt | 17 + .../refs/macros/KDC_OPT_FORWARDED.rst.txt | 17 + .../refs/macros/KDC_OPT_POSTDATED.rst.txt | 17 + .../refs/macros/KDC_OPT_PROXIABLE.rst.txt | 17 + .../appdev/refs/macros/KDC_OPT_PROXY.rst.txt | 17 + .../appdev/refs/macros/KDC_OPT_RENEW.rst.txt | 17 + .../refs/macros/KDC_OPT_RENEWABLE.rst.txt | 17 + .../refs/macros/KDC_OPT_RENEWABLE_OK.rst.txt | 17 + .../macros/KDC_OPT_REQUEST_ANONYMOUS.rst.txt | 17 + .../refs/macros/KDC_OPT_VALIDATE.rst.txt | 17 + .../refs/macros/KDC_TKT_COMMON_MASK.rst.txt | 17 + ...RB5_ALTAUTH_ATT_CHALLENGE_RESPONSE.rst.txt | 18 + .../macros/KRB5_ANONYMOUS_PRINCSTR.rst.txt | 18 + .../macros/KRB5_ANONYMOUS_REALMSTR.rst.txt | 18 + .../appdev/refs/macros/KRB5_AP_REP.rst.txt | 18 + .../appdev/refs/macros/KRB5_AP_REQ.rst.txt | 18 + .../appdev/refs/macros/KRB5_AS_REP.rst.txt | 18 + .../appdev/refs/macros/KRB5_AS_REQ.rst.txt | 18 + .../refs/macros/KRB5_AUTHDATA_AND_OR.rst.txt | 17 + .../macros/KRB5_AUTHDATA_AP_OPTIONS.rst.txt | 17 + .../KRB5_AUTHDATA_AUTH_INDICATOR.rst.txt | 17 + .../refs/macros/KRB5_AUTHDATA_CAMMAC.rst.txt | 17 + .../KRB5_AUTHDATA_ETYPE_NEGOTIATION.rst.txt | 18 + .../macros/KRB5_AUTHDATA_FX_ARMOR.rst.txt | 17 + .../macros/KRB5_AUTHDATA_IF_RELEVANT.rst.txt | 17 + ...KRB5_AUTHDATA_INITIAL_VERIFIED_CAS.rst.txt | 17 + .../macros/KRB5_AUTHDATA_KDC_ISSUED.rst.txt | 17 + .../KRB5_AUTHDATA_MANDATORY_FOR_KDC.rst.txt | 17 + .../refs/macros/KRB5_AUTHDATA_OSF_DCE.rst.txt | 17 + .../refs/macros/KRB5_AUTHDATA_SESAME.rst.txt | 17 + .../macros/KRB5_AUTHDATA_SIGNTICKET.rst.txt | 17 + .../macros/KRB5_AUTHDATA_WIN2K_PAC.rst.txt | 17 + .../KRB5_AUTH_CONTEXT_DO_SEQUENCE.rst.txt | 18 + .../macros/KRB5_AUTH_CONTEXT_DO_TIME.rst.txt | 18 + ...5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR.rst.txt | 18 + ...H_CONTEXT_GENERATE_LOCAL_FULL_ADDR.rst.txt | 18 + ..._AUTH_CONTEXT_GENERATE_REMOTE_ADDR.rst.txt | 18 + ..._CONTEXT_GENERATE_REMOTE_FULL_ADDR.rst.txt | 18 + .../KRB5_AUTH_CONTEXT_PERMIT_ALL.rst.txt | 17 + .../KRB5_AUTH_CONTEXT_RET_SEQUENCE.rst.txt | 18 + .../macros/KRB5_AUTH_CONTEXT_RET_TIME.rst.txt | 18 + .../KRB5_AUTH_CONTEXT_USE_SUBKEY.rst.txt | 17 + .../appdev/refs/macros/KRB5_CRED.rst.txt | 18 + .../macros/KRB5_CRYPTO_TYPE_CHECKSUM.rst.txt | 18 + .../refs/macros/KRB5_CRYPTO_TYPE_DATA.rst.txt | 18 + .../macros/KRB5_CRYPTO_TYPE_EMPTY.rst.txt | 18 + .../macros/KRB5_CRYPTO_TYPE_HEADER.rst.txt | 18 + .../macros/KRB5_CRYPTO_TYPE_PADDING.rst.txt | 18 + .../macros/KRB5_CRYPTO_TYPE_SIGN_ONLY.rst.txt | 18 + .../macros/KRB5_CRYPTO_TYPE_STREAM.rst.txt | 18 + .../macros/KRB5_CRYPTO_TYPE_TRAILER.rst.txt | 18 + .../macros/KRB5_CYBERSAFE_SECUREID.rst.txt | 18 + .../macros/KRB5_DOMAIN_X500_COMPRESS.rst.txt | 18 + .../KRB5_ENCPADATA_REQ_ENC_PA_REP.rst.txt | 18 + .../appdev/refs/macros/KRB5_ERROR.rst.txt | 18 + .../refs/macros/KRB5_FAST_REQUIRED.rst.txt | 18 + .../appdev/refs/macros/KRB5_GC_CACHED.rst.txt | 18 + .../refs/macros/KRB5_GC_CANONICALIZE.rst.txt | 18 + .../KRB5_GC_CONSTRAINED_DELEGATION.rst.txt | 18 + .../refs/macros/KRB5_GC_FORWARDABLE.rst.txt | 18 + .../refs/macros/KRB5_GC_NO_STORE.rst.txt | 18 + .../macros/KRB5_GC_NO_TRANSIT_CHECK.rst.txt | 18 + .../refs/macros/KRB5_GC_USER_USER.rst.txt | 18 + ...B5_GET_INIT_CREDS_OPT_ADDRESS_LIST.rst.txt | 17 + .../KRB5_GET_INIT_CREDS_OPT_ANONYMOUS.rst.txt | 17 + ...B5_GET_INIT_CREDS_OPT_CANONICALIZE.rst.txt | 17 + ...5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT.rst.txt | 17 + ...KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST.rst.txt | 17 + ...RB5_GET_INIT_CREDS_OPT_FORWARDABLE.rst.txt | 17 + ...B5_GET_INIT_CREDS_OPT_PREAUTH_LIST.rst.txt | 17 + .../KRB5_GET_INIT_CREDS_OPT_PROXIABLE.rst.txt | 17 + ...KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE.rst.txt | 17 + .../KRB5_GET_INIT_CREDS_OPT_SALT.rst.txt | 17 + .../KRB5_GET_INIT_CREDS_OPT_TKT_LIFE.rst.txt | 17 + .../refs/macros/KRB5_INIT_CONTEXT_KDC.rst.txt | 18 + .../macros/KRB5_INIT_CONTEXT_SECURE.rst.txt | 18 + ...KRB5_INIT_CREDS_STEP_FLAG_CONTINUE.rst.txt | 18 + .../appdev/refs/macros/KRB5_INT16_MAX.rst.txt | 17 + .../appdev/refs/macros/KRB5_INT16_MIN.rst.txt | 17 + .../appdev/refs/macros/KRB5_INT32_MAX.rst.txt | 17 + .../appdev/refs/macros/KRB5_INT32_MIN.rst.txt | 17 + .../refs/macros/KRB5_KEYUSAGE_AD_ITE.rst.txt | 17 + .../KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM.rst.txt | 17 + .../refs/macros/KRB5_KEYUSAGE_AD_MTE.rst.txt | 17 + .../KRB5_KEYUSAGE_AD_SIGNEDPATH.rst.txt | 17 + .../KRB5_KEYUSAGE_APP_DATA_CKSUM.rst.txt | 17 + .../KRB5_KEYUSAGE_APP_DATA_ENCRYPT.rst.txt | 17 + .../KRB5_KEYUSAGE_AP_REP_ENCPART.rst.txt | 17 + .../macros/KRB5_KEYUSAGE_AP_REQ_AUTH.rst.txt | 17 + .../KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM.rst.txt | 17 + .../KRB5_KEYUSAGE_AS_REP_ENCPART.rst.txt | 17 + .../refs/macros/KRB5_KEYUSAGE_AS_REQ.rst.txt | 17 + .../KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS.rst.txt | 17 + .../refs/macros/KRB5_KEYUSAGE_CAMMAC.rst.txt | 17 + ...KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT.rst.txt | 17 + .../KRB5_KEYUSAGE_ENC_CHALLENGE_KDC.rst.txt | 17 + .../macros/KRB5_KEYUSAGE_FAST_ENC.rst.txt | 17 + .../KRB5_KEYUSAGE_FAST_FINISHED.rst.txt | 17 + .../macros/KRB5_KEYUSAGE_FAST_REP.rst.txt | 17 + .../KRB5_KEYUSAGE_FAST_REQ_CHKSUM.rst.txt | 17 + .../macros/KRB5_KEYUSAGE_GSS_TOK_MIC.rst.txt | 17 + .../KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.rst.txt | 17 + .../KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.rst.txt | 17 + .../KRB5_KEYUSAGE_IAKERB_FINISHED.rst.txt | 17 + .../KRB5_KEYUSAGE_KDC_REP_TICKET.rst.txt | 17 + .../KRB5_KEYUSAGE_KRB_CRED_ENCPART.rst.txt | 17 + .../KRB5_KEYUSAGE_KRB_ERROR_CKSUM.rst.txt | 17 + .../KRB5_KEYUSAGE_KRB_PRIV_ENCPART.rst.txt | 17 + .../KRB5_KEYUSAGE_KRB_SAFE_CKSUM.rst.txt | 17 + .../KRB5_KEYUSAGE_PA_AS_FRESHNESS.rst.txt | 18 + .../macros/KRB5_KEYUSAGE_PA_FX_COOKIE.rst.txt | 18 + .../KRB5_KEYUSAGE_PA_OTP_REQUEST.rst.txt | 18 + .../macros/KRB5_KEYUSAGE_PA_PKINIT_KX.rst.txt | 17 + ...B5_KEYUSAGE_PA_S4U_X509_USER_REPLY.rst.txt | 17 + ..._KEYUSAGE_PA_S4U_X509_USER_REQUEST.rst.txt | 17 + ...B5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.rst.txt | 17 + ..._KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.rst.txt | 17 + .../KRB5_KEYUSAGE_PA_SAM_RESPONSE.rst.txt | 17 + .../refs/macros/KRB5_KEYUSAGE_SPAKE.rst.txt | 17 + ...5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.rst.txt | 17 + ...B5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.rst.txt | 17 + .../KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.rst.txt | 17 + .../KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY.rst.txt | 17 + .../macros/KRB5_KEYUSAGE_TGS_REQ_AUTH.rst.txt | 17 + .../KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM.rst.txt | 17 + .../macros/KRB5_KPASSWD_ACCESSDENIED.rst.txt | 18 + .../macros/KRB5_KPASSWD_AUTHERROR.rst.txt | 18 + .../macros/KRB5_KPASSWD_BAD_VERSION.rst.txt | 18 + .../macros/KRB5_KPASSWD_HARDERROR.rst.txt | 18 + .../KRB5_KPASSWD_INITIAL_FLAG_NEEDED.rst.txt | 18 + .../macros/KRB5_KPASSWD_MALFORMED.rst.txt | 18 + .../macros/KRB5_KPASSWD_SOFTERROR.rst.txt | 18 + .../refs/macros/KRB5_KPASSWD_SUCCESS.rst.txt | 18 + .../macros/KRB5_LRQ_ALL_ACCT_EXPTIME.rst.txt | 17 + .../macros/KRB5_LRQ_ALL_LAST_INITIAL.rst.txt | 17 + .../macros/KRB5_LRQ_ALL_LAST_RENEWAL.rst.txt | 17 + .../refs/macros/KRB5_LRQ_ALL_LAST_REQ.rst.txt | 17 + .../refs/macros/KRB5_LRQ_ALL_LAST_TGT.rst.txt | 17 + .../KRB5_LRQ_ALL_LAST_TGT_ISSUED.rst.txt | 17 + .../macros/KRB5_LRQ_ALL_PW_EXPTIME.rst.txt | 17 + .../appdev/refs/macros/KRB5_LRQ_NONE.rst.txt | 17 + .../macros/KRB5_LRQ_ONE_ACCT_EXPTIME.rst.txt | 17 + .../macros/KRB5_LRQ_ONE_LAST_INITIAL.rst.txt | 17 + .../macros/KRB5_LRQ_ONE_LAST_RENEWAL.rst.txt | 17 + .../refs/macros/KRB5_LRQ_ONE_LAST_REQ.rst.txt | 17 + .../refs/macros/KRB5_LRQ_ONE_LAST_TGT.rst.txt | 17 + .../KRB5_LRQ_ONE_LAST_TGT_ISSUED.rst.txt | 17 + .../macros/KRB5_LRQ_ONE_PW_EXPTIME.rst.txt | 17 + .../KRB5_NT_ENTERPRISE_PRINCIPAL.rst.txt | 18 + .../KRB5_NT_ENT_PRINCIPAL_AND_ID.rst.txt | 18 + .../refs/macros/KRB5_NT_MS_PRINCIPAL.rst.txt | 18 + .../KRB5_NT_MS_PRINCIPAL_AND_ID.rst.txt | 18 + .../refs/macros/KRB5_NT_PRINCIPAL.rst.txt | 18 + .../refs/macros/KRB5_NT_SMTP_NAME.rst.txt | 18 + .../refs/macros/KRB5_NT_SRV_HST.rst.txt | 18 + .../refs/macros/KRB5_NT_SRV_INST.rst.txt | 18 + .../refs/macros/KRB5_NT_SRV_XHST.rst.txt | 18 + .../appdev/refs/macros/KRB5_NT_UID.rst.txt | 18 + .../refs/macros/KRB5_NT_UNKNOWN.rst.txt | 18 + .../refs/macros/KRB5_NT_WELLKNOWN.rst.txt | 18 + .../macros/KRB5_NT_X500_PRINCIPAL.rst.txt | 18 + .../macros/KRB5_PAC_ATTRIBUTES_INFO.rst.txt | 18 + .../macros/KRB5_PAC_CLIENT_CLAIMS.rst.txt | 18 + .../refs/macros/KRB5_PAC_CLIENT_INFO.rst.txt | 18 + .../macros/KRB5_PAC_CREDENTIALS_INFO.rst.txt | 18 + .../macros/KRB5_PAC_DELEGATION_INFO.rst.txt | 18 + .../macros/KRB5_PAC_DEVICE_CLAIMS.rst.txt | 18 + .../refs/macros/KRB5_PAC_DEVICE_INFO.rst.txt | 18 + .../macros/KRB5_PAC_FULL_CHECKSUM.rst.txt | 18 + .../refs/macros/KRB5_PAC_LOGON_INFO.rst.txt | 18 + .../macros/KRB5_PAC_PRIVSVR_CHECKSUM.rst.txt | 18 + .../refs/macros/KRB5_PAC_REQUESTOR.rst.txt | 18 + .../macros/KRB5_PAC_SERVER_CHECKSUM.rst.txt | 18 + .../macros/KRB5_PAC_TICKET_CHECKSUM.rst.txt | 18 + .../refs/macros/KRB5_PAC_UPN_DNS_INFO.rst.txt | 18 + .../refs/macros/KRB5_PADATA_AFS3_SALT.rst.txt | 18 + .../refs/macros/KRB5_PADATA_AP_REQ.rst.txt | 17 + .../macros/KRB5_PADATA_AS_CHECKSUM.rst.txt | 18 + .../macros/KRB5_PADATA_AS_FRESHNESS.rst.txt | 18 + .../KRB5_PADATA_ENCRYPTED_CHALLENGE.rst.txt | 18 + .../KRB5_PADATA_ENC_SANDIA_SECURID.rst.txt | 18 + .../macros/KRB5_PADATA_ENC_TIMESTAMP.rst.txt | 18 + .../macros/KRB5_PADATA_ENC_UNIX_TIME.rst.txt | 18 + .../macros/KRB5_PADATA_ETYPE_INFO.rst.txt | 18 + .../macros/KRB5_PADATA_ETYPE_INFO2.rst.txt | 18 + .../refs/macros/KRB5_PADATA_FOR_USER.rst.txt | 18 + .../refs/macros/KRB5_PADATA_FX_COOKIE.rst.txt | 18 + .../refs/macros/KRB5_PADATA_FX_ERROR.rst.txt | 18 + .../refs/macros/KRB5_PADATA_FX_FAST.rst.txt | 18 + .../KRB5_PADATA_GET_FROM_TYPED_DATA.rst.txt | 18 + .../refs/macros/KRB5_PADATA_NONE.rst.txt | 17 + .../refs/macros/KRB5_PADATA_OSF_DCE.rst.txt | 18 + .../macros/KRB5_PADATA_OTP_CHALLENGE.rst.txt | 18 + .../macros/KRB5_PADATA_OTP_PIN_CHANGE.rst.txt | 18 + .../macros/KRB5_PADATA_OTP_REQUEST.rst.txt | 18 + .../macros/KRB5_PADATA_PAC_OPTIONS.rst.txt | 18 + .../macros/KRB5_PADATA_PAC_REQUEST.rst.txt | 18 + .../refs/macros/KRB5_PADATA_PKINIT_KX.rst.txt | 18 + .../refs/macros/KRB5_PADATA_PK_AS_REP.rst.txt | 18 + .../macros/KRB5_PADATA_PK_AS_REP_OLD.rst.txt | 18 + .../refs/macros/KRB5_PADATA_PK_AS_REQ.rst.txt | 18 + .../macros/KRB5_PADATA_PK_AS_REQ_OLD.rst.txt | 18 + .../refs/macros/KRB5_PADATA_PW_SALT.rst.txt | 18 + .../KRB5_PADATA_REDHAT_IDP_OAUTH2.rst.txt | 18 + .../macros/KRB5_PADATA_REDHAT_PASSKEY.rst.txt | 18 + .../refs/macros/KRB5_PADATA_REFERRAL.rst.txt | 18 + .../macros/KRB5_PADATA_S4U_X509_USER.rst.txt | 18 + .../macros/KRB5_PADATA_SAM_CHALLENGE.rst.txt | 18 + .../KRB5_PADATA_SAM_CHALLENGE_2.rst.txt | 18 + .../macros/KRB5_PADATA_SAM_REDIRECT.rst.txt | 18 + .../macros/KRB5_PADATA_SAM_RESPONSE.rst.txt | 18 + .../macros/KRB5_PADATA_SAM_RESPONSE_2.rst.txt | 18 + .../refs/macros/KRB5_PADATA_SESAME.rst.txt | 18 + .../refs/macros/KRB5_PADATA_SPAKE.rst.txt | 17 + .../KRB5_PADATA_SVR_REFERRAL_INFO.rst.txt | 18 + .../refs/macros/KRB5_PADATA_TGS_REQ.rst.txt | 17 + .../KRB5_PADATA_USE_SPECIFIED_KVNO.rst.txt | 18 + .../KRB5_PRINCIPAL_COMPARE_CASEFOLD.rst.txt | 18 + .../KRB5_PRINCIPAL_COMPARE_ENTERPRISE.rst.txt | 18 + ...RB5_PRINCIPAL_COMPARE_IGNORE_REALM.rst.txt | 18 + .../KRB5_PRINCIPAL_COMPARE_UTF8.rst.txt | 18 + .../KRB5_PRINCIPAL_PARSE_ENTERPRISE.rst.txt | 18 + .../KRB5_PRINCIPAL_PARSE_IGNORE_REALM.rst.txt | 18 + .../KRB5_PRINCIPAL_PARSE_NO_DEF_REALM.rst.txt | 18 + .../KRB5_PRINCIPAL_PARSE_NO_REALM.rst.txt | 18 + ...KRB5_PRINCIPAL_PARSE_REQUIRE_REALM.rst.txt | 18 + .../KRB5_PRINCIPAL_UNPARSE_DISPLAY.rst.txt | 18 + .../KRB5_PRINCIPAL_UNPARSE_NO_REALM.rst.txt | 18 + .../KRB5_PRINCIPAL_UNPARSE_SHORT.rst.txt | 18 + .../appdev/refs/macros/KRB5_PRIV.rst.txt | 18 + .../KRB5_PROMPT_TYPE_NEW_PASSWORD.rst.txt | 18 + ...RB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN.rst.txt | 18 + .../macros/KRB5_PROMPT_TYPE_PASSWORD.rst.txt | 18 + .../macros/KRB5_PROMPT_TYPE_PREAUTH.rst.txt | 18 + .../appdev/refs/macros/KRB5_PVNO.rst.txt | 18 + .../macros/KRB5_REALM_BRANCH_CHAR.rst.txt | 17 + .../macros/KRB5_RECVAUTH_BADAUTHVERS.rst.txt | 17 + .../macros/KRB5_RECVAUTH_SKIP_VERSION.rst.txt | 17 + .../refs/macros/KRB5_REFERRAL_REALM.rst.txt | 18 + ...B5_RESPONDER_OTP_FLAGS_COLLECT_PIN.rst.txt | 18 + ..._RESPONDER_OTP_FLAGS_COLLECT_TOKEN.rst.txt | 18 + .../KRB5_RESPONDER_OTP_FLAGS_NEXTOTP.rst.txt | 18 + ...5_RESPONDER_OTP_FLAGS_SEPARATE_PIN.rst.txt | 18 + ..._RESPONDER_OTP_FORMAT_ALPHANUMERIC.rst.txt | 17 + .../KRB5_RESPONDER_OTP_FORMAT_DECIMAL.rst.txt | 18 + ...5_RESPONDER_OTP_FORMAT_HEXADECIMAL.rst.txt | 17 + ...NIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW.rst.txt | 18 + ...NIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY.rst.txt | 18 + ...PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.rst.txt | 18 + .../KRB5_RESPONDER_QUESTION_OTP.rst.txt | 47 + .../KRB5_RESPONDER_QUESTION_PASSWORD.rst.txt | 19 + .../KRB5_RESPONDER_QUESTION_PKINIT.rst.txt | 34 + .../appdev/refs/macros/KRB5_SAFE.rst.txt | 18 + .../KRB5_SAM_MUST_PK_ENCRYPT_SAD.rst.txt | 18 + .../KRB5_SAM_SEND_ENCRYPTED_SAD.rst.txt | 17 + .../macros/KRB5_SAM_USE_SAD_AS_KEY.rst.txt | 17 + .../refs/macros/KRB5_TC_MATCH_2ND_TKT.rst.txt | 18 + .../macros/KRB5_TC_MATCH_AUTHDATA.rst.txt | 18 + .../refs/macros/KRB5_TC_MATCH_FLAGS.rst.txt | 18 + .../macros/KRB5_TC_MATCH_FLAGS_EXACT.rst.txt | 18 + .../refs/macros/KRB5_TC_MATCH_IS_SKEY.rst.txt | 18 + .../refs/macros/KRB5_TC_MATCH_KTYPE.rst.txt | 18 + .../macros/KRB5_TC_MATCH_SRV_NAMEONLY.rst.txt | 18 + .../refs/macros/KRB5_TC_MATCH_TIMES.rst.txt | 18 + .../macros/KRB5_TC_MATCH_TIMES_EXACT.rst.txt | 18 + .../refs/macros/KRB5_TC_NOTICKET.rst.txt | 17 + .../refs/macros/KRB5_TC_OPENCLOSE.rst.txt | 18 + .../macros/KRB5_TC_SUPPORTED_KTYPES.rst.txt | 18 + .../appdev/refs/macros/KRB5_TGS_NAME.rst.txt | 17 + .../refs/macros/KRB5_TGS_NAME_SIZE.rst.txt | 17 + .../appdev/refs/macros/KRB5_TGS_REP.rst.txt | 18 + .../appdev/refs/macros/KRB5_TGS_REQ.rst.txt | 18 + .../KRB5_TKT_CREDS_STEP_FLAG_CONTINUE.rst.txt | 18 + ...ERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL.rst.txt | 17 + .../macros/KRB5_WELLKNOWN_NAMESTR.rst.txt | 18 + .../LR_TYPE_INTERPRETATION_MASK.rst.txt | 17 + .../macros/LR_TYPE_THIS_SERVER_ONLY.rst.txt | 17 + .../refs/macros/MAX_KEYTAB_NAME_LEN.rst.txt | 18 + .../appdev/refs/macros/MSEC_DIRBIT.rst.txt | 17 + .../appdev/refs/macros/MSEC_VAL_MASK.rst.txt | 17 + .../refs/macros/SALT_TYPE_AFS_LENGTH.rst.txt | 17 + .../refs/macros/SALT_TYPE_NO_LENGTH.rst.txt | 17 + .../appdev/refs/macros/THREEPARAMOPEN.rst.txt | 17 + .../refs/macros/TKT_FLG_ANONYMOUS.rst.txt | 17 + .../refs/macros/TKT_FLG_ENC_PA_REP.rst.txt | 17 + .../refs/macros/TKT_FLG_FORWARDABLE.rst.txt | 17 + .../refs/macros/TKT_FLG_FORWARDED.rst.txt | 17 + .../refs/macros/TKT_FLG_HW_AUTH.rst.txt | 17 + .../refs/macros/TKT_FLG_INITIAL.rst.txt | 17 + .../refs/macros/TKT_FLG_INVALID.rst.txt | 17 + .../refs/macros/TKT_FLG_MAY_POSTDATE.rst.txt | 17 + .../macros/TKT_FLG_OK_AS_DELEGATE.rst.txt | 17 + .../refs/macros/TKT_FLG_POSTDATED.rst.txt | 17 + .../refs/macros/TKT_FLG_PRE_AUTH.rst.txt | 17 + .../refs/macros/TKT_FLG_PROXIABLE.rst.txt | 17 + .../appdev/refs/macros/TKT_FLG_PROXY.rst.txt | 17 + .../refs/macros/TKT_FLG_RENEWABLE.rst.txt | 17 + .../TKT_FLG_TRANSIT_POLICY_CHECKED.rst.txt | 17 + .../appdev/refs/macros/VALID_INT_BITS.rst.txt | 17 + .../refs/macros/VALID_UINT_BITS.rst.txt | 17 + .../_sources/appdev/refs/macros/index.rst.txt | 397 + .../macros/krb524_convert_creds_kdc.rst.txt | 17 + .../refs/macros/krb524_init_ets.rst.txt | 17 + .../appdev/refs/macros/krb5_const.rst.txt | 17 + .../refs/macros/krb5_princ_component.rst.txt | 17 + .../refs/macros/krb5_princ_name.rst.txt | 17 + .../refs/macros/krb5_princ_realm.rst.txt | 17 + .../refs/macros/krb5_princ_set_realm.rst.txt | 17 + .../macros/krb5_princ_set_realm_data.rst.txt | 17 + .../krb5_princ_set_realm_length.rst.txt | 17 + .../refs/macros/krb5_princ_size.rst.txt | 17 + .../refs/macros/krb5_princ_type.rst.txt | 17 + .../appdev/refs/macros/krb5_roundup.rst.txt | 17 + .../appdev/refs/macros/krb5_x.rst.txt | 17 + .../appdev/refs/macros/krb5_xc.rst.txt | 17 + .../_sources/appdev/refs/types/index.rst.txt | 108 + .../appdev/refs/types/krb5_address.rst.txt | 45 + .../appdev/refs/types/krb5_addrtype.rst.txt | 20 + .../appdev/refs/types/krb5_ap_rep.rst.txt | 35 + .../refs/types/krb5_ap_rep_enc_part.rst.txt | 50 + .../appdev/refs/types/krb5_ap_req.rst.txt | 45 + .../refs/types/krb5_auth_context.rst.txt | 20 + .../appdev/refs/types/krb5_authdata.rst.txt | 45 + .../refs/types/krb5_authdatatype.rst.txt | 20 + .../refs/types/krb5_authenticator.rst.txt | 65 + .../appdev/refs/types/krb5_boolean.rst.txt | 20 + .../appdev/refs/types/krb5_cc_cursor.rst.txt | 21 + .../appdev/refs/types/krb5_ccache.rst.txt | 20 + .../refs/types/krb5_cccol_cursor.rst.txt | 21 + .../appdev/refs/types/krb5_checksum.rst.txt | 44 + .../appdev/refs/types/krb5_cksumtype.rst.txt | 20 + .../refs/types/krb5_const_pointer.rst.txt | 20 + .../refs/types/krb5_const_principal.rst.txt | 50 + .../appdev/refs/types/krb5_context.rst.txt | 20 + .../appdev/refs/types/krb5_cred.rst.txt | 45 + .../refs/types/krb5_cred_enc_part.rst.txt | 60 + .../appdev/refs/types/krb5_cred_info.rst.txt | 60 + .../appdev/refs/types/krb5_creds.rst.txt | 80 + .../appdev/refs/types/krb5_crypto_iov.rst.txt | 35 + .../appdev/refs/types/krb5_cryptotype.rst.txt | 20 + .../appdev/refs/types/krb5_data.rst.txt | 39 + .../appdev/refs/types/krb5_deltat.rst.txt | 20 + .../appdev/refs/types/krb5_enc_data.rst.txt | 44 + .../refs/types/krb5_enc_kdc_rep_part.rst.txt | 80 + .../refs/types/krb5_enc_tkt_part.rst.txt | 65 + .../refs/types/krb5_encrypt_block.rst.txt | 39 + .../appdev/refs/types/krb5_enctype.rst.txt | 20 + .../appdev/refs/types/krb5_error.rst.txt | 75 + .../appdev/refs/types/krb5_error_code.rst.txt | 21 + .../types/krb5_expire_callback_func.rst.txt | 20 + .../appdev/refs/types/krb5_flags.rst.txt | 20 + .../types/krb5_get_init_creds_opt.rst.txt | 80 + .../refs/types/krb5_gic_opt_pa_data.rst.txt | 35 + .../types/krb5_init_creds_context.rst.txt | 20 + .../appdev/refs/types/krb5_int16.rst.txt | 20 + .../appdev/refs/types/krb5_int32.rst.txt | 20 + .../appdev/refs/types/krb5_kdc_rep.rst.txt | 60 + .../appdev/refs/types/krb5_kdc_req.rst.txt | 105 + .../appdev/refs/types/krb5_key.rst.txt | 21 + .../appdev/refs/types/krb5_keyblock.rst.txt | 45 + .../appdev/refs/types/krb5_keytab.rst.txt | 20 + .../refs/types/krb5_keytab_entry.rst.txt | 50 + .../appdev/refs/types/krb5_keyusage.rst.txt | 20 + .../appdev/refs/types/krb5_kt_cursor.rst.txt | 20 + .../appdev/refs/types/krb5_kvno.rst.txt | 20 + .../refs/types/krb5_last_req_entry.rst.txt | 40 + .../appdev/refs/types/krb5_magic.rst.txt | 20 + .../types/krb5_mk_req_checksum_func.rst.txt | 21 + .../appdev/refs/types/krb5_msgtype.rst.txt | 20 + .../appdev/refs/types/krb5_octet.rst.txt | 20 + .../appdev/refs/types/krb5_pa_data.rst.txt | 45 + .../appdev/refs/types/krb5_pa_pac_req.rst.txt | 29 + .../krb5_pa_server_referral_data.rst.txt | 49 + .../types/krb5_pa_svr_referral_data.rst.txt | 29 + .../appdev/refs/types/krb5_pac.rst.txt | 21 + .../appdev/refs/types/krb5_pointer.rst.txt | 20 + .../refs/types/krb5_post_recv_fn.rst.txt | 22 + .../refs/types/krb5_pre_send_fn.rst.txt | 24 + .../refs/types/krb5_preauthtype.rst.txt | 20 + .../appdev/refs/types/krb5_principal.rst.txt | 49 + .../refs/types/krb5_principal_data.rst.txt | 49 + .../appdev/refs/types/krb5_prompt.rst.txt | 40 + .../refs/types/krb5_prompt_type.rst.txt | 20 + .../refs/types/krb5_prompter_fct.rst.txt | 21 + .../appdev/refs/types/krb5_pwd_data.rst.txt | 39 + .../appdev/refs/types/krb5_rcache.rst.txt | 20 + .../refs/types/krb5_replay_data.rst.txt | 40 + .../refs/types/krb5_responder_context.rst.txt | 22 + .../refs/types/krb5_responder_fn.rst.txt | 21 + .../krb5_responder_otp_challenge.rst.txt | 34 + .../krb5_responder_otp_tokeninfo.rst.txt | 59 + .../krb5_responder_pkinit_challenge.rst.txt | 29 + .../krb5_responder_pkinit_identity.rst.txt | 34 + .../appdev/refs/types/krb5_response.rst.txt | 49 + .../appdev/refs/types/krb5_ticket.rst.txt | 45 + .../refs/types/krb5_ticket_times.rst.txt | 45 + .../appdev/refs/types/krb5_timestamp.rst.txt | 21 + .../refs/types/krb5_tkt_authent.rst.txt | 45 + .../refs/types/krb5_tkt_creds_context.rst.txt | 20 + .../refs/types/krb5_trace_callback.rst.txt | 20 + .../appdev/refs/types/krb5_trace_info.rst.txt | 30 + .../appdev/refs/types/krb5_transited.rst.txt | 40 + .../appdev/refs/types/krb5_typed_data.rst.txt | 44 + .../appdev/refs/types/krb5_ui_2.rst.txt | 20 + .../appdev/refs/types/krb5_ui_4.rst.txt | 20 + .../types/krb5_verify_init_creds_opt.rst.txt | 34 + .../refs/types/passwd_phrase_element.rst.txt | 39 + .../doc/html/_sources/appdev/y2038.rst.txt | 28 + .../html/_sources/basic/ccache_def.rst.txt | 160 + .../html/_sources/basic/date_format.rst.txt | 140 + .../doc/html/_sources/basic/index.rst.txt | 14 + .../html/_sources/basic/keytab_def.rst.txt | 59 + .../html/_sources/basic/rcache_def.rst.txt | 111 + .../_sources/basic/stash_file_def.rst.txt | 25 + .../html/_sources/build/directory_org.rst.txt | 75 + .../html/_sources/build/doing_build.rst.txt | 148 + .../doc/html/_sources/build/index.rst.txt | 63 + .../_sources/build/options2configure.rst.txt | 397 + .../doc/html/_sources/build/osconf.rst.txt | 26 + .../doc/html/_sources/build_this.rst.txt | 82 + .../doc/html/_sources/copyright.rst.txt | 8 + .../formats/ccache_file_format.rst.txt | 182 + .../doc/html/_sources/formats/cookie.rst.txt | 97 + .../_sources/formats/freshness_token.rst.txt | 19 + .../doc/html/_sources/formats/index.rst.txt | 11 + .../formats/keytab_file_format.rst.txt | 51 + .../formats/rcache_file_format.rst.txt | 50 + krb5-1.21.3/doc/html/_sources/index.rst.txt | 18 + .../doc/html/_sources/mitK5defaults.rst.txt | 79 + .../doc/html/_sources/mitK5features.rst.txt | 699 + .../doc/html/_sources/mitK5license.rst.txt | 11 + .../html/_sources/plugindev/ccselect.rst.txt | 28 + .../html/_sources/plugindev/certauth.rst.txt | 36 + .../html/_sources/plugindev/clpreauth.rst.txt | 54 + .../html/_sources/plugindev/general.rst.txt | 118 + .../html/_sources/plugindev/gssapi.rst.txt | 134 + .../html/_sources/plugindev/hostrealm.rst.txt | 39 + .../doc/html/_sources/plugindev/index.rst.txt | 38 + .../html/_sources/plugindev/internal.rst.txt | 32 + .../_sources/plugindev/kadm5_auth.rst.txt | 35 + .../_sources/plugindev/kadm5_hook.rst.txt | 27 + .../html/_sources/plugindev/kdcpolicy.rst.txt | 24 + .../_sources/plugindev/kdcpreauth.rst.txt | 79 + .../html/_sources/plugindev/localauth.rst.txt | 43 + .../html/_sources/plugindev/locate.rst.txt | 32 + .../html/_sources/plugindev/profile.rst.txt | 96 + .../html/_sources/plugindev/pwqual.rst.txt | 25 + .../doc/html/_sources/resources.rst.txt | 60 + .../doc/html/_sources/user/index.rst.txt | 10 + .../doc/html/_sources/user/pwd_mgmt.rst.txt | 106 + .../doc/html/_sources/user/tkt_mgmt.rst.txt | 314 + .../_sources/user/user_commands/index.rst.txt | 17 + .../user/user_commands/kdestroy.rst.txt | 77 + .../_sources/user/user_commands/kinit.rst.txt | 230 + .../_sources/user/user_commands/klist.rst.txt | 129 + .../user/user_commands/kpasswd.rst.txt | 46 + .../user/user_commands/krb5-config.rst.txt | 83 + .../_sources/user/user_commands/ksu.rst.txt | 411 + .../user/user_commands/kswitch.rst.txt | 50 + .../_sources/user/user_commands/kvno.rst.txt | 119 + .../user/user_commands/sclient.rst.txt | 30 + .../_sources/user/user_config/index.rst.txt | 13 + .../user/user_config/k5identity.rst.txt | 64 + .../_sources/user/user_config/k5login.rst.txt | 54 + .../user/user_config/kerberos.rst.txt | 185 + krb5-1.21.3/doc/html/_static/agogo.css | 538 + krb5-1.21.3/doc/html/_static/basic.css | 905 + krb5-1.21.3/doc/html/_static/bgfooter.png | Bin 0 -> 276 bytes krb5-1.21.3/doc/html/_static/bgtop.png | Bin 0 -> 266 bytes krb5-1.21.3/doc/html/_static/doctools.js | 323 + .../doc/html/_static/documentation_options.js | 12 + krb5-1.21.3/doc/html/_static/file.png | Bin 0 -> 286 bytes krb5-1.21.3/doc/html/_static/jquery.js | 10879 ++++++ krb5-1.21.3/doc/html/_static/kerb.css | 169 + krb5-1.21.3/doc/html/_static/language_data.js | 297 + krb5-1.21.3/doc/html/_static/minus.png | Bin 0 -> 90 bytes krb5-1.21.3/doc/html/_static/plus.png | Bin 0 -> 90 bytes krb5-1.21.3/doc/html/_static/pygments.css | 74 + krb5-1.21.3/doc/html/_static/searchtools.js | 532 + krb5-1.21.3/doc/html/_static/underscore.js | 2042 + krb5-1.21.3/doc/html/about.html | 157 + .../doc/html/admin/admin_commands/index.html | 180 + .../html/admin/admin_commands/k5srvutil.html | 225 + .../admin/admin_commands/kadmin_local.html | 1018 + .../html/admin/admin_commands/kadmind.html | 277 + .../admin/admin_commands/kdb5_ldap_util.html | 551 + .../html/admin/admin_commands/kdb5_util.html | 621 + .../doc/html/admin/admin_commands/kprop.html | 217 + .../doc/html/admin/admin_commands/kpropd.html | 289 + .../html/admin/admin_commands/kproplog.html | 242 + .../html/admin/admin_commands/krb5kdc.html | 262 + .../doc/html/admin/admin_commands/ktutil.html | 292 + .../html/admin/admin_commands/sserver.html | 271 + .../doc/html/admin/advanced/index.html | 160 + .../doc/html/admin/advanced/retiring-des.html | 548 + krb5-1.21.3/doc/html/admin/appl_servers.html | 306 + .../doc/html/admin/auth_indicator.html | 201 + krb5-1.21.3/doc/html/admin/backup_host.html | 184 + .../doc/html/admin/conf_files/index.html | 178 + .../doc/html/admin/conf_files/kadm5_acl.html | 337 + .../doc/html/admin/conf_files/kdc_conf.html | 1073 + .../doc/html/admin/conf_files/krb5_conf.html | 1340 + krb5-1.21.3/doc/html/admin/conf_ldap.html | 275 + krb5-1.21.3/doc/html/admin/database.html | 710 + krb5-1.21.3/doc/html/admin/dbtypes.html | 288 + krb5-1.21.3/doc/html/admin/dictionary.html | 226 + krb5-1.21.3/doc/html/admin/enctypes.html | 402 + krb5-1.21.3/doc/html/admin/env_variables.html | 153 + krb5-1.21.3/doc/html/admin/host_config.html | 362 + krb5-1.21.3/doc/html/admin/https.html | 193 + krb5-1.21.3/doc/html/admin/index.html | 186 + krb5-1.21.3/doc/html/admin/install.html | 197 + .../doc/html/admin/install_appl_srv.html | 225 + .../doc/html/admin/install_clients.html | 207 + krb5-1.21.3/doc/html/admin/install_kdc.html | 653 + krb5-1.21.3/doc/html/admin/lockout.html | 293 + krb5-1.21.3/doc/html/admin/otp.html | 241 + krb5-1.21.3/doc/html/admin/pkinit.html | 482 + krb5-1.21.3/doc/html/admin/princ_dns.html | 268 + krb5-1.21.3/doc/html/admin/realm_config.html | 394 + krb5-1.21.3/doc/html/admin/spake.html | 199 + krb5-1.21.3/doc/html/admin/troubleshoot.html | 266 + krb5-1.21.3/doc/html/admin/various_envs.html | 179 + krb5-1.21.3/doc/html/appdev/gssapi.html | 797 + .../doc/html/appdev/h5l_mit_apidiff.html | 177 + krb5-1.21.3/doc/html/appdev/index.html | 150 + krb5-1.21.3/doc/html/appdev/init_creds.html | 433 + krb5-1.21.3/doc/html/appdev/princ_handle.html | 162 + .../doc/html/appdev/refs/api/index.html | 553 + .../refs/api/krb5_425_conv_principal.html | 162 + .../refs/api/krb5_524_conv_principal.html | 168 + .../refs/api/krb5_524_convert_creds.html | 162 + .../appdev/refs/api/krb5_address_compare.html | 158 + .../appdev/refs/api/krb5_address_order.html | 160 + .../appdev/refs/api/krb5_address_search.html | 162 + .../refs/api/krb5_allow_weak_crypto.html | 158 + .../refs/api/krb5_aname_to_localname.html | 167 + .../refs/api/krb5_anonymous_principal.html | 154 + .../appdev/refs/api/krb5_anonymous_realm.html | 154 + .../refs/api/krb5_appdefault_boolean.html | 159 + .../refs/api/krb5_appdefault_string.html | 159 + .../appdev/refs/api/krb5_auth_con_free.html | 158 + .../refs/api/krb5_auth_con_genaddrs.html | 168 + .../api/krb5_auth_con_get_checksum_func.html | 159 + .../refs/api/krb5_auth_con_getaddrs.html | 159 + .../api/krb5_auth_con_getauthenticator.html | 159 + .../refs/api/krb5_auth_con_getflags.html | 167 + .../appdev/refs/api/krb5_auth_con_getkey.html | 159 + .../refs/api/krb5_auth_con_getkey_k.html | 159 + .../api/krb5_auth_con_getlocalseqnumber.html | 159 + .../api/krb5_auth_con_getlocalsubkey.html | 152 + .../refs/api/krb5_auth_con_getrcache.html | 159 + .../refs/api/krb5_auth_con_getrecvsubkey.html | 159 + .../api/krb5_auth_con_getrecvsubkey_k.html | 159 + .../api/krb5_auth_con_getremoteseqnumber.html | 159 + .../api/krb5_auth_con_getremotesubkey.html | 152 + .../refs/api/krb5_auth_con_getsendsubkey.html | 159 + .../api/krb5_auth_con_getsendsubkey_k.html | 159 + .../appdev/refs/api/krb5_auth_con_init.html | 160 + .../refs/api/krb5_auth_con_initivector.html | 158 + .../api/krb5_auth_con_set_checksum_func.html | 160 + .../api/krb5_auth_con_set_req_cksumtype.html | 159 + .../refs/api/krb5_auth_con_setaddrs.html | 164 + .../refs/api/krb5_auth_con_setflags.html | 167 + .../refs/api/krb5_auth_con_setports.html | 164 + .../refs/api/krb5_auth_con_setrcache.html | 159 + .../refs/api/krb5_auth_con_setrecvsubkey.html | 159 + .../api/krb5_auth_con_setrecvsubkey_k.html | 163 + .../refs/api/krb5_auth_con_setsendsubkey.html | 159 + .../api/krb5_auth_con_setsendsubkey_k.html | 163 + .../api/krb5_auth_con_setuseruserkey.html | 158 + .../appdev/refs/api/krb5_build_principal.html | 170 + .../api/krb5_build_principal_alloc_va.html | 167 + .../refs/api/krb5_build_principal_ext.html | 166 + .../refs/api/krb5_build_principal_va.html | 154 + .../appdev/refs/api/krb5_c_block_size.html | 158 + .../refs/api/krb5_c_checksum_length.html | 158 + .../appdev/refs/api/krb5_c_crypto_length.html | 159 + .../refs/api/krb5_c_crypto_length_iov.html | 160 + .../html/appdev/refs/api/krb5_c_decrypt.html | 166 + .../appdev/refs/api/krb5_c_decrypt_iov.html | 170 + .../refs/api/krb5_c_derive_prfplus.html | 154 + .../html/appdev/refs/api/krb5_c_encrypt.html | 166 + .../appdev/refs/api/krb5_c_encrypt_iov.html | 170 + .../refs/api/krb5_c_encrypt_length.html | 160 + .../refs/api/krb5_c_enctype_compare.html | 160 + .../appdev/refs/api/krb5_c_free_state.html | 158 + .../appdev/refs/api/krb5_c_fx_cf2_simple.html | 162 + .../appdev/refs/api/krb5_c_init_state.html | 159 + .../refs/api/krb5_c_is_coll_proof_cksum.html | 156 + .../refs/api/krb5_c_is_keyed_cksum.html | 156 + .../refs/api/krb5_c_keyed_checksum_types.html | 160 + .../appdev/refs/api/krb5_c_keylengths.html | 159 + .../appdev/refs/api/krb5_c_make_checksum.html | 170 + .../refs/api/krb5_c_make_checksum_iov.html | 170 + .../refs/api/krb5_c_make_random_key.html | 159 + .../refs/api/krb5_c_padding_length.html | 160 + .../doc/html/appdev/refs/api/krb5_c_prf.html | 160 + .../appdev/refs/api/krb5_c_prf_length.html | 158 + .../html/appdev/refs/api/krb5_c_prfplus.html | 164 + .../refs/api/krb5_c_random_add_entropy.html | 152 + .../refs/api/krb5_c_random_make_octets.html | 158 + .../refs/api/krb5_c_random_os_entropy.html | 152 + .../appdev/refs/api/krb5_c_random_seed.html | 151 + .../appdev/refs/api/krb5_c_random_to_key.html | 168 + .../appdev/refs/api/krb5_c_string_to_key.html | 161 + .../api/krb5_c_string_to_key_with_params.html | 162 + .../refs/api/krb5_c_valid_cksumtype.html | 156 + .../appdev/refs/api/krb5_c_valid_enctype.html | 156 + .../refs/api/krb5_c_verify_checksum.html | 166 + .../refs/api/krb5_c_verify_checksum_iov.html | 171 + .../refs/api/krb5_calculate_checksum.html | 156 + .../appdev/refs/api/krb5_cc_cache_match.html | 164 + .../html/appdev/refs/api/krb5_cc_close.html | 163 + .../appdev/refs/api/krb5_cc_copy_creds.html | 158 + .../html/appdev/refs/api/krb5_cc_default.html | 165 + .../appdev/refs/api/krb5_cc_default_name.html | 158 + .../html/appdev/refs/api/krb5_cc_destroy.html | 163 + .../doc/html/appdev/refs/api/krb5_cc_dup.html | 152 + .../appdev/refs/api/krb5_cc_end_seq_get.html | 163 + .../html/appdev/refs/api/krb5_cc_gen_new.html | 150 + .../appdev/refs/api/krb5_cc_get_config.html | 166 + .../appdev/refs/api/krb5_cc_get_flags.html | 162 + .../refs/api/krb5_cc_get_full_name.html | 156 + .../appdev/refs/api/krb5_cc_get_name.html | 161 + .../refs/api/krb5_cc_get_principal.html | 165 + .../appdev/refs/api/krb5_cc_get_type.html | 157 + .../appdev/refs/api/krb5_cc_initialize.html | 164 + .../html/appdev/refs/api/krb5_cc_move.html | 164 + .../appdev/refs/api/krb5_cc_new_unique.html | 164 + .../appdev/refs/api/krb5_cc_next_cred.html | 165 + .../appdev/refs/api/krb5_cc_remove_cred.html | 169 + .../html/appdev/refs/api/krb5_cc_resolve.html | 164 + .../refs/api/krb5_cc_retrieve_cred.html | 179 + .../html/appdev/refs/api/krb5_cc_select.html | 168 + .../appdev/refs/api/krb5_cc_set_config.html | 173 + .../refs/api/krb5_cc_set_default_name.html | 165 + .../appdev/refs/api/krb5_cc_set_flags.html | 159 + .../refs/api/krb5_cc_start_seq_get.html | 163 + .../appdev/refs/api/krb5_cc_store_cred.html | 164 + .../refs/api/krb5_cc_support_switch.html | 162 + .../html/appdev/refs/api/krb5_cc_switch.html | 163 + .../refs/api/krb5_cccol_cursor_free.html | 161 + .../refs/api/krb5_cccol_cursor_new.html | 163 + .../refs/api/krb5_cccol_cursor_next.html | 167 + .../refs/api/krb5_cccol_have_content.html | 161 + .../appdev/refs/api/krb5_change_password.html | 172 + .../appdev/refs/api/krb5_check_clockskew.html | 163 + .../appdev/refs/api/krb5_checksum_size.html | 151 + .../appdev/refs/api/krb5_chpw_message.html | 169 + .../refs/api/krb5_cksumtype_to_string.html | 158 + .../refs/api/krb5_clear_error_message.html | 150 + .../appdev/refs/api/krb5_copy_addresses.html | 159 + .../appdev/refs/api/krb5_copy_authdata.html | 163 + .../refs/api/krb5_copy_authenticator.html | 159 + .../appdev/refs/api/krb5_copy_checksum.html | 159 + .../appdev/refs/api/krb5_copy_context.html | 163 + .../html/appdev/refs/api/krb5_copy_creds.html | 159 + .../html/appdev/refs/api/krb5_copy_data.html | 159 + .../refs/api/krb5_copy_error_message.html | 150 + .../appdev/refs/api/krb5_copy_keyblock.html | 159 + .../refs/api/krb5_copy_keyblock_contents.html | 159 + .../appdev/refs/api/krb5_copy_principal.html | 159 + .../appdev/refs/api/krb5_copy_ticket.html | 159 + .../api/krb5_decode_authdata_container.html | 163 + .../appdev/refs/api/krb5_decode_ticket.html | 157 + .../html/appdev/refs/api/krb5_decrypt.html | 155 + .../refs/api/krb5_deltat_to_string.html | 158 + .../appdev/refs/api/krb5_eblock_enctype.html | 151 + .../api/krb5_encode_authdata_container.html | 164 + .../html/appdev/refs/api/krb5_encrypt.html | 155 + .../appdev/refs/api/krb5_encrypt_size.html | 151 + .../appdev/refs/api/krb5_enctype_to_name.html | 164 + .../refs/api/krb5_enctype_to_string.html | 158 + .../appdev/refs/api/krb5_expand_hostname.html | 156 + .../appdev/refs/api/krb5_find_authdata.html | 158 + .../html/appdev/refs/api/krb5_finish_key.html | 151 + .../refs/api/krb5_finish_random_key.html | 152 + .../appdev/refs/api/krb5_free_addresses.html | 155 + .../refs/api/krb5_free_ap_rep_enc_part.html | 151 + .../appdev/refs/api/krb5_free_authdata.html | 155 + .../refs/api/krb5_free_authenticator.html | 151 + .../appdev/refs/api/krb5_free_checksum.html | 151 + .../refs/api/krb5_free_checksum_contents.html | 151 + .../appdev/refs/api/krb5_free_cksumtypes.html | 150 + .../appdev/refs/api/krb5_free_context.html | 150 + .../refs/api/krb5_free_cred_contents.html | 151 + .../html/appdev/refs/api/krb5_free_creds.html | 151 + .../html/appdev/refs/api/krb5_free_data.html | 151 + .../refs/api/krb5_free_data_contents.html | 151 + .../refs/api/krb5_free_default_realm.html | 150 + .../appdev/refs/api/krb5_free_enctypes.html | 154 + .../html/appdev/refs/api/krb5_free_error.html | 151 + .../refs/api/krb5_free_error_message.html | 150 + .../appdev/refs/api/krb5_free_host_realm.html | 162 + .../appdev/refs/api/krb5_free_keyblock.html | 151 + .../refs/api/krb5_free_keyblock_contents.html | 151 + .../api/krb5_free_keytab_entry_contents.html | 161 + .../appdev/refs/api/krb5_free_principal.html | 150 + .../appdev/refs/api/krb5_free_string.html | 154 + .../appdev/refs/api/krb5_free_tgt_creds.html | 154 + .../appdev/refs/api/krb5_free_ticket.html | 151 + .../refs/api/krb5_free_unparsed_name.html | 150 + .../appdev/refs/api/krb5_fwd_tgt_creds.html | 173 + .../appdev/refs/api/krb5_get_credentials.html | 179 + .../refs/api/krb5_get_credentials_renew.html | 154 + .../api/krb5_get_credentials_validate.html | 154 + .../refs/api/krb5_get_default_realm.html | 164 + .../refs/api/krb5_get_error_message.html | 157 + .../appdev/refs/api/krb5_get_etype_info.html | 175 + .../api/krb5_get_fallback_host_realm.html | 154 + .../appdev/refs/api/krb5_get_host_realm.html | 167 + .../refs/api/krb5_get_in_tkt_with_keytab.html | 158 + .../api/krb5_get_in_tkt_with_password.html | 158 + .../refs/api/krb5_get_in_tkt_with_skey.html | 158 + .../refs/api/krb5_get_init_creds_keytab.html | 168 + .../api/krb5_get_init_creds_opt_alloc.html | 158 + .../api/krb5_get_init_creds_opt_free.html | 154 + ...rb5_get_init_creds_opt_get_fast_flags.html | 158 + .../api/krb5_get_init_creds_opt_init.html | 150 + ...5_get_init_creds_opt_set_address_list.html | 150 + ...krb5_get_init_creds_opt_set_anonymous.html | 151 + ...5_get_init_creds_opt_set_canonicalize.html | 150 + ..._creds_opt_set_change_password_prompt.html | 151 + ...rb5_get_init_creds_opt_set_etype_list.html | 151 + ...et_init_creds_opt_set_expire_callback.html | 167 + ...b5_get_init_creds_opt_set_fast_ccache.html | 156 + ...t_init_creds_opt_set_fast_ccache_name.html | 153 + ...rb5_get_init_creds_opt_set_fast_flags.html | 164 + ...b5_get_init_creds_opt_set_forwardable.html | 150 + ...krb5_get_init_creds_opt_set_in_ccache.html | 156 + ...rb5_get_init_creds_opt_set_out_ccache.html | 152 + .../api/krb5_get_init_creds_opt_set_pa.html | 153 + ...b5_get_init_creds_opt_set_pac_request.html | 156 + ...5_get_init_creds_opt_set_preauth_list.html | 152 + ...krb5_get_init_creds_opt_set_proxiable.html | 150 + ...rb5_get_init_creds_opt_set_renew_life.html | 150 + ...krb5_get_init_creds_opt_set_responder.html | 156 + .../api/krb5_get_init_creds_opt_set_salt.html | 151 + .../krb5_get_init_creds_opt_set_tkt_life.html | 150 + .../api/krb5_get_init_creds_password.html | 179 + .../refs/api/krb5_get_permitted_enctypes.html | 159 + .../appdev/refs/api/krb5_get_profile.html | 164 + .../refs/api/krb5_get_prompt_types.html | 156 + .../refs/api/krb5_get_renewed_creds.html | 167 + .../refs/api/krb5_get_server_rcache.html | 163 + .../refs/api/krb5_get_time_offsets.html | 159 + .../refs/api/krb5_get_validated_creds.html | 172 + .../appdev/refs/api/krb5_init_context.html | 166 + .../refs/api/krb5_init_context_profile.html | 158 + .../appdev/refs/api/krb5_init_creds_free.html | 153 + .../appdev/refs/api/krb5_init_creds_get.html | 161 + .../refs/api/krb5_init_creds_get_creds.html | 159 + .../refs/api/krb5_init_creds_get_error.html | 158 + .../refs/api/krb5_init_creds_get_times.html | 159 + .../appdev/refs/api/krb5_init_creds_init.html | 164 + .../refs/api/krb5_init_creds_set_keytab.html | 159 + .../api/krb5_init_creds_set_password.html | 159 + .../refs/api/krb5_init_creds_set_service.html | 159 + .../appdev/refs/api/krb5_init_creds_step.html | 167 + .../appdev/refs/api/krb5_init_keyblock.html | 164 + .../appdev/refs/api/krb5_init_random_key.html | 153 + .../refs/api/krb5_init_secure_context.html | 163 + .../refs/api/krb5_is_config_principal.html | 157 + .../refs/api/krb5_is_referral_realm.html | 156 + .../appdev/refs/api/krb5_is_thread_safe.html | 156 + .../appdev/refs/api/krb5_k_create_key.html | 159 + .../html/appdev/refs/api/krb5_k_decrypt.html | 166 + .../appdev/refs/api/krb5_k_decrypt_iov.html | 170 + .../html/appdev/refs/api/krb5_k_encrypt.html | 166 + .../appdev/refs/api/krb5_k_encrypt_iov.html | 170 + .../html/appdev/refs/api/krb5_k_free_key.html | 150 + .../appdev/refs/api/krb5_k_key_enctype.html | 150 + .../appdev/refs/api/krb5_k_key_keyblock.html | 151 + .../appdev/refs/api/krb5_k_make_checksum.html | 170 + .../refs/api/krb5_k_make_checksum_iov.html | 170 + .../doc/html/appdev/refs/api/krb5_k_prf.html | 164 + .../appdev/refs/api/krb5_k_reference_key.html | 150 + .../refs/api/krb5_k_verify_checksum.html | 166 + .../refs/api/krb5_k_verify_checksum_iov.html | 171 + .../appdev/refs/api/krb5_kdc_sign_ticket.html | 168 + .../refs/api/krb5_kdc_verify_ticket.html | 171 + .../appdev/refs/api/krb5_kt_add_entry.html | 165 + .../refs/api/krb5_kt_client_default.html | 167 + .../html/appdev/refs/api/krb5_kt_close.html | 157 + .../html/appdev/refs/api/krb5_kt_default.html | 163 + .../appdev/refs/api/krb5_kt_default_name.html | 165 + .../doc/html/appdev/refs/api/krb5_kt_dup.html | 156 + .../appdev/refs/api/krb5_kt_end_seq_get.html | 164 + .../appdev/refs/api/krb5_kt_free_entry.html | 151 + .../appdev/refs/api/krb5_kt_get_entry.html | 168 + .../appdev/refs/api/krb5_kt_get_name.html | 166 + .../appdev/refs/api/krb5_kt_get_type.html | 157 + .../appdev/refs/api/krb5_kt_have_content.html | 162 + .../appdev/refs/api/krb5_kt_next_entry.html | 166 + .../refs/api/krb5_kt_read_service_key.html | 169 + .../appdev/refs/api/krb5_kt_remove_entry.html | 164 + .../html/appdev/refs/api/krb5_kt_resolve.html | 168 + .../refs/api/krb5_kt_start_seq_get.html | 164 + .../html/appdev/refs/api/krb5_kuserok.html | 159 + .../api/krb5_make_authdata_kdc_issued.html | 154 + .../refs/api/krb5_marshal_credentials.html | 160 + .../appdev/refs/api/krb5_merge_authdata.html | 164 + .../html/appdev/refs/api/krb5_mk_1cred.html | 168 + .../html/appdev/refs/api/krb5_mk_error.html | 159 + .../html/appdev/refs/api/krb5_mk_ncred.html | 177 + .../html/appdev/refs/api/krb5_mk_priv.html | 169 + .../doc/html/appdev/refs/api/krb5_mk_rep.html | 161 + .../html/appdev/refs/api/krb5_mk_rep_dce.html | 159 + .../doc/html/appdev/refs/api/krb5_mk_req.html | 165 + .../appdev/refs/api/krb5_mk_req_extended.html | 177 + .../html/appdev/refs/api/krb5_mk_safe.html | 170 + .../appdev/refs/api/krb5_os_localaddr.html | 158 + .../appdev/refs/api/krb5_pac_add_buffer.html | 172 + .../html/appdev/refs/api/krb5_pac_free.html | 151 + .../appdev/refs/api/krb5_pac_get_buffer.html | 160 + .../refs/api/krb5_pac_get_client_info.html | 164 + .../appdev/refs/api/krb5_pac_get_types.html | 159 + .../html/appdev/refs/api/krb5_pac_init.html | 158 + .../html/appdev/refs/api/krb5_pac_parse.html | 160 + .../html/appdev/refs/api/krb5_pac_sign.html | 156 + .../appdev/refs/api/krb5_pac_sign_ext.html | 157 + .../html/appdev/refs/api/krb5_pac_verify.html | 167 + .../appdev/refs/api/krb5_pac_verify_ext.html | 160 + .../html/appdev/refs/api/krb5_parse_name.html | 172 + .../refs/api/krb5_parse_name_flags.html | 178 + .../refs/api/krb5_prepend_error_message.html | 152 + .../appdev/refs/api/krb5_principal2salt.html | 158 + .../refs/api/krb5_principal_compare.html | 158 + .../api/krb5_principal_compare_any_realm.html | 159 + .../api/krb5_principal_compare_flags.html | 172 + .../appdev/refs/api/krb5_process_key.html | 152 + .../appdev/refs/api/krb5_prompter_posix.html | 168 + .../html/appdev/refs/api/krb5_random_key.html | 153 + .../html/appdev/refs/api/krb5_rd_cred.html | 168 + .../html/appdev/refs/api/krb5_rd_error.html | 159 + .../html/appdev/refs/api/krb5_rd_priv.html | 169 + .../doc/html/appdev/refs/api/krb5_rd_rep.html | 161 + .../html/appdev/refs/api/krb5_rd_rep_dce.html | 160 + .../doc/html/appdev/refs/api/krb5_rd_req.html | 178 + .../html/appdev/refs/api/krb5_rd_safe.html | 169 + .../appdev/refs/api/krb5_read_password.html | 172 + .../appdev/refs/api/krb5_realm_compare.html | 158 + .../html/appdev/refs/api/krb5_recvauth.html | 169 + .../refs/api/krb5_recvauth_version.html | 164 + .../api/krb5_responder_get_challenge.html | 156 + .../api/krb5_responder_list_questions.html | 155 + .../krb5_responder_otp_challenge_free.html | 155 + .../api/krb5_responder_otp_get_challenge.html | 157 + .../api/krb5_responder_otp_set_answer.html | 157 + .../krb5_responder_pkinit_challenge_free.html | 155 + .../krb5_responder_pkinit_get_challenge.html | 157 + .../api/krb5_responder_pkinit_set_answer.html | 156 + .../refs/api/krb5_responder_set_answer.html | 164 + .../refs/api/krb5_salttype_to_string.html | 158 + .../html/appdev/refs/api/krb5_sendauth.html | 185 + .../krb5_server_decrypt_ticket_keytab.html | 159 + .../refs/api/krb5_set_default_realm.html | 163 + .../api/krb5_set_default_tgs_enctypes.html | 168 + .../refs/api/krb5_set_error_message.html | 151 + .../refs/api/krb5_set_kdc_recv_hook.html | 158 + .../refs/api/krb5_set_kdc_send_hook.html | 158 + .../appdev/refs/api/krb5_set_password.html | 173 + .../api/krb5_set_password_using_ccache.html | 173 + .../refs/api/krb5_set_principal_realm.html | 164 + .../appdev/refs/api/krb5_set_real_time.html | 159 + .../refs/api/krb5_set_trace_callback.html | 167 + .../refs/api/krb5_set_trace_filename.html | 166 + .../appdev/refs/api/krb5_sname_match.html | 163 + .../refs/api/krb5_sname_to_principal.html | 176 + .../refs/api/krb5_string_to_cksumtype.html | 157 + .../refs/api/krb5_string_to_deltat.html | 157 + .../refs/api/krb5_string_to_enctype.html | 157 + .../appdev/refs/api/krb5_string_to_key.html | 154 + .../refs/api/krb5_string_to_salttype.html | 157 + .../refs/api/krb5_string_to_timestamp.html | 157 + .../html/appdev/refs/api/krb5_timeofday.html | 163 + .../refs/api/krb5_timestamp_to_sfstring.html | 160 + .../refs/api/krb5_timestamp_to_string.html | 159 + .../appdev/refs/api/krb5_tkt_creds_free.html | 154 + .../appdev/refs/api/krb5_tkt_creds_get.html | 162 + .../refs/api/krb5_tkt_creds_get_creds.html | 163 + .../refs/api/krb5_tkt_creds_get_times.html | 163 + .../appdev/refs/api/krb5_tkt_creds_init.html | 167 + .../appdev/refs/api/krb5_tkt_creds_step.html | 168 + .../refs/api/krb5_unmarshal_credentials.html | 160 + .../appdev/refs/api/krb5_unparse_name.html | 165 + .../refs/api/krb5_unparse_name_ext.html | 166 + .../refs/api/krb5_unparse_name_flags.html | 176 + .../refs/api/krb5_unparse_name_flags_ext.html | 165 + .../appdev/refs/api/krb5_us_timeofday.html | 164 + .../appdev/refs/api/krb5_use_enctype.html | 152 + .../api/krb5_verify_authdata_kdc_issued.html | 154 + .../appdev/refs/api/krb5_verify_checksum.html | 156 + .../refs/api/krb5_verify_init_creds.html | 164 + .../api/krb5_verify_init_creds_opt_init.html | 149 + ...rify_init_creds_opt_set_ap_req_nofail.html | 152 + .../refs/api/krb5_vprepend_error_message.html | 153 + .../refs/api/krb5_vset_error_message.html | 152 + .../refs/api/krb5_vwrap_error_message.html | 154 + .../refs/api/krb5_wrap_error_message.html | 153 + krb5-1.21.3/doc/html/appdev/refs/index.html | 146 + .../appdev/refs/macros/ADDRTYPE_ADDRPORT.html | 155 + .../appdev/refs/macros/ADDRTYPE_CHAOS.html | 155 + .../html/appdev/refs/macros/ADDRTYPE_DDP.html | 155 + .../appdev/refs/macros/ADDRTYPE_INET.html | 155 + .../appdev/refs/macros/ADDRTYPE_INET6.html | 155 + .../appdev/refs/macros/ADDRTYPE_IPPORT.html | 155 + .../html/appdev/refs/macros/ADDRTYPE_ISO.html | 155 + .../appdev/refs/macros/ADDRTYPE_IS_LOCAL.html | 155 + .../appdev/refs/macros/ADDRTYPE_NETBIOS.html | 155 + .../html/appdev/refs/macros/ADDRTYPE_XNS.html | 155 + .../appdev/refs/macros/AD_TYPE_EXTERNAL.html | 155 + .../refs/macros/AD_TYPE_FIELD_TYPE_MASK.html | 155 + .../refs/macros/AD_TYPE_REGISTERED.html | 155 + .../appdev/refs/macros/AD_TYPE_RESERVED.html | 155 + .../macros/AP_OPTS_ETYPE_NEGOTIATION.html | 155 + .../refs/macros/AP_OPTS_MUTUAL_REQUIRED.html | 156 + .../appdev/refs/macros/AP_OPTS_RESERVED.html | 155 + .../refs/macros/AP_OPTS_USE_SESSION_KEY.html | 156 + .../refs/macros/AP_OPTS_USE_SUBKEY.html | 156 + .../appdev/refs/macros/AP_OPTS_WIRE_MASK.html | 155 + .../macros/CKSUMTYPE_CMAC_CAMELLIA128.html | 156 + .../macros/CKSUMTYPE_CMAC_CAMELLIA256.html | 156 + .../appdev/refs/macros/CKSUMTYPE_CRC32.html | 155 + .../appdev/refs/macros/CKSUMTYPE_DESCBC.html | 155 + .../macros/CKSUMTYPE_HMAC_MD5_ARCFOUR.html | 156 + .../macros/CKSUMTYPE_HMAC_SHA1_96_AES128.html | 157 + .../macros/CKSUMTYPE_HMAC_SHA1_96_AES256.html | 157 + .../refs/macros/CKSUMTYPE_HMAC_SHA1_DES3.html | 155 + .../CKSUMTYPE_HMAC_SHA256_128_AES128.html | 156 + .../CKSUMTYPE_HMAC_SHA384_192_AES256.html | 156 + .../macros/CKSUMTYPE_MD5_HMAC_ARCFOUR.html | 155 + .../refs/macros/CKSUMTYPE_NIST_SHA.html | 155 + .../appdev/refs/macros/CKSUMTYPE_RSA_MD4.html | 155 + .../refs/macros/CKSUMTYPE_RSA_MD4_DES.html | 155 + .../appdev/refs/macros/CKSUMTYPE_RSA_MD5.html | 155 + .../refs/macros/CKSUMTYPE_RSA_MD5_DES.html | 155 + .../appdev/refs/macros/CKSUMTYPE_SHA1.html | 156 + .../ENCTYPE_AES128_CTS_HMAC_SHA1_96.html | 156 + .../ENCTYPE_AES128_CTS_HMAC_SHA256_128.html | 156 + .../ENCTYPE_AES256_CTS_HMAC_SHA1_96.html | 156 + .../ENCTYPE_AES256_CTS_HMAC_SHA384_192.html | 156 + .../refs/macros/ENCTYPE_ARCFOUR_HMAC.html | 156 + .../refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP.html | 156 + .../macros/ENCTYPE_CAMELLIA128_CTS_CMAC.html | 156 + .../macros/ENCTYPE_CAMELLIA256_CTS_CMAC.html | 156 + .../refs/macros/ENCTYPE_DES3_CBC_ENV.html | 156 + .../refs/macros/ENCTYPE_DES3_CBC_RAW.html | 155 + .../refs/macros/ENCTYPE_DES3_CBC_SHA.html | 155 + .../refs/macros/ENCTYPE_DES3_CBC_SHA1.html | 155 + .../refs/macros/ENCTYPE_DES_CBC_CRC.html | 155 + .../refs/macros/ENCTYPE_DES_CBC_MD4.html | 155 + .../refs/macros/ENCTYPE_DES_CBC_MD5.html | 155 + .../refs/macros/ENCTYPE_DES_CBC_RAW.html | 155 + .../refs/macros/ENCTYPE_DES_HMAC_SHA1.html | 155 + .../refs/macros/ENCTYPE_DSA_SHA1_CMS.html | 156 + .../refs/macros/ENCTYPE_MD5_RSA_CMS.html | 156 + .../html/appdev/refs/macros/ENCTYPE_NULL.html | 155 + .../refs/macros/ENCTYPE_RC2_CBC_ENV.html | 156 + .../appdev/refs/macros/ENCTYPE_RSA_ENV.html | 156 + .../refs/macros/ENCTYPE_RSA_ES_OAEP_ENV.html | 156 + .../refs/macros/ENCTYPE_SHA1_RSA_CMS.html | 156 + .../appdev/refs/macros/ENCTYPE_UNKNOWN.html | 155 + .../refs/macros/KDC_OPT_ALLOW_POSTDATE.html | 155 + .../refs/macros/KDC_OPT_CANONICALIZE.html | 155 + .../macros/KDC_OPT_CNAME_IN_ADDL_TKT.html | 155 + .../KDC_OPT_DISABLE_TRANSITED_CHECK.html | 155 + .../refs/macros/KDC_OPT_ENC_TKT_IN_SKEY.html | 155 + .../refs/macros/KDC_OPT_FORWARDABLE.html | 155 + .../appdev/refs/macros/KDC_OPT_FORWARDED.html | 155 + .../appdev/refs/macros/KDC_OPT_POSTDATED.html | 155 + .../appdev/refs/macros/KDC_OPT_PROXIABLE.html | 155 + .../appdev/refs/macros/KDC_OPT_PROXY.html | 155 + .../appdev/refs/macros/KDC_OPT_RENEW.html | 155 + .../appdev/refs/macros/KDC_OPT_RENEWABLE.html | 155 + .../refs/macros/KDC_OPT_RENEWABLE_OK.html | 155 + .../macros/KDC_OPT_REQUEST_ANONYMOUS.html | 155 + .../appdev/refs/macros/KDC_OPT_VALIDATE.html | 155 + .../refs/macros/KDC_TKT_COMMON_MASK.html | 155 + .../KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE.html | 156 + .../refs/macros/KRB5_ANONYMOUS_PRINCSTR.html | 156 + .../refs/macros/KRB5_ANONYMOUS_REALMSTR.html | 156 + .../html/appdev/refs/macros/KRB5_AP_REP.html | 156 + .../html/appdev/refs/macros/KRB5_AP_REQ.html | 156 + .../html/appdev/refs/macros/KRB5_AS_REP.html | 156 + .../html/appdev/refs/macros/KRB5_AS_REQ.html | 156 + .../refs/macros/KRB5_AUTHDATA_AND_OR.html | 155 + .../refs/macros/KRB5_AUTHDATA_AP_OPTIONS.html | 155 + .../macros/KRB5_AUTHDATA_AUTH_INDICATOR.html | 155 + .../refs/macros/KRB5_AUTHDATA_CAMMAC.html | 155 + .../KRB5_AUTHDATA_ETYPE_NEGOTIATION.html | 156 + .../refs/macros/KRB5_AUTHDATA_FX_ARMOR.html | 155 + .../macros/KRB5_AUTHDATA_IF_RELEVANT.html | 155 + .../KRB5_AUTHDATA_INITIAL_VERIFIED_CAS.html | 155 + .../refs/macros/KRB5_AUTHDATA_KDC_ISSUED.html | 155 + .../KRB5_AUTHDATA_MANDATORY_FOR_KDC.html | 155 + .../refs/macros/KRB5_AUTHDATA_OSF_DCE.html | 155 + .../refs/macros/KRB5_AUTHDATA_SESAME.html | 155 + .../refs/macros/KRB5_AUTHDATA_SIGNTICKET.html | 155 + .../refs/macros/KRB5_AUTHDATA_WIN2K_PAC.html | 155 + .../macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE.html | 156 + .../macros/KRB5_AUTH_CONTEXT_DO_TIME.html | 156 + ...KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR.html | 156 + ...AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR.html | 156 + ...RB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR.html | 156 + ...UTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR.html | 156 + .../macros/KRB5_AUTH_CONTEXT_PERMIT_ALL.html | 155 + .../KRB5_AUTH_CONTEXT_RET_SEQUENCE.html | 156 + .../macros/KRB5_AUTH_CONTEXT_RET_TIME.html | 156 + .../macros/KRB5_AUTH_CONTEXT_USE_SUBKEY.html | 155 + .../html/appdev/refs/macros/KRB5_CRED.html | 156 + .../macros/KRB5_CRYPTO_TYPE_CHECKSUM.html | 156 + .../refs/macros/KRB5_CRYPTO_TYPE_DATA.html | 156 + .../refs/macros/KRB5_CRYPTO_TYPE_EMPTY.html | 156 + .../refs/macros/KRB5_CRYPTO_TYPE_HEADER.html | 156 + .../refs/macros/KRB5_CRYPTO_TYPE_PADDING.html | 156 + .../macros/KRB5_CRYPTO_TYPE_SIGN_ONLY.html | 156 + .../refs/macros/KRB5_CRYPTO_TYPE_STREAM.html | 156 + .../refs/macros/KRB5_CRYPTO_TYPE_TRAILER.html | 156 + .../refs/macros/KRB5_CYBERSAFE_SECUREID.html | 157 + .../macros/KRB5_DOMAIN_X500_COMPRESS.html | 156 + .../macros/KRB5_ENCPADATA_REQ_ENC_PA_REP.html | 156 + .../html/appdev/refs/macros/KRB5_ERROR.html | 156 + .../refs/macros/KRB5_FAST_REQUIRED.html | 156 + .../appdev/refs/macros/KRB5_GC_CACHED.html | 156 + .../refs/macros/KRB5_GC_CANONICALIZE.html | 156 + .../KRB5_GC_CONSTRAINED_DELEGATION.html | 156 + .../refs/macros/KRB5_GC_FORWARDABLE.html | 156 + .../appdev/refs/macros/KRB5_GC_NO_STORE.html | 156 + .../refs/macros/KRB5_GC_NO_TRANSIT_CHECK.html | 156 + .../appdev/refs/macros/KRB5_GC_USER_USER.html | 156 + .../KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST.html | 155 + .../KRB5_GET_INIT_CREDS_OPT_ANONYMOUS.html | 155 + .../KRB5_GET_INIT_CREDS_OPT_CANONICALIZE.html | 155 + ...KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT.html | 155 + .../KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST.html | 155 + .../KRB5_GET_INIT_CREDS_OPT_FORWARDABLE.html | 155 + .../KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST.html | 155 + .../KRB5_GET_INIT_CREDS_OPT_PROXIABLE.html | 155 + .../KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE.html | 155 + .../macros/KRB5_GET_INIT_CREDS_OPT_SALT.html | 155 + .../KRB5_GET_INIT_CREDS_OPT_TKT_LIFE.html | 155 + .../refs/macros/KRB5_INIT_CONTEXT_KDC.html | 156 + .../refs/macros/KRB5_INIT_CONTEXT_SECURE.html | 156 + .../KRB5_INIT_CREDS_STEP_FLAG_CONTINUE.html | 156 + .../appdev/refs/macros/KRB5_INT16_MAX.html | 155 + .../appdev/refs/macros/KRB5_INT16_MIN.html | 155 + .../appdev/refs/macros/KRB5_INT32_MAX.html | 155 + .../appdev/refs/macros/KRB5_INT32_MIN.html | 155 + .../refs/macros/KRB5_KEYUSAGE_AD_ITE.html | 155 + .../KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM.html | 155 + .../refs/macros/KRB5_KEYUSAGE_AD_MTE.html | 155 + .../macros/KRB5_KEYUSAGE_AD_SIGNEDPATH.html | 155 + .../macros/KRB5_KEYUSAGE_APP_DATA_CKSUM.html | 155 + .../KRB5_KEYUSAGE_APP_DATA_ENCRYPT.html | 155 + .../macros/KRB5_KEYUSAGE_AP_REP_ENCPART.html | 155 + .../macros/KRB5_KEYUSAGE_AP_REQ_AUTH.html | 155 + .../KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM.html | 155 + .../macros/KRB5_KEYUSAGE_AS_REP_ENCPART.html | 155 + .../refs/macros/KRB5_KEYUSAGE_AS_REQ.html | 155 + .../KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS.html | 155 + .../refs/macros/KRB5_KEYUSAGE_CAMMAC.html | 155 + .../KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT.html | 155 + .../KRB5_KEYUSAGE_ENC_CHALLENGE_KDC.html | 155 + .../refs/macros/KRB5_KEYUSAGE_FAST_ENC.html | 155 + .../macros/KRB5_KEYUSAGE_FAST_FINISHED.html | 155 + .../refs/macros/KRB5_KEYUSAGE_FAST_REP.html | 155 + .../macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM.html | 155 + .../macros/KRB5_KEYUSAGE_GSS_TOK_MIC.html | 155 + .../KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.html | 155 + .../KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.html | 155 + .../macros/KRB5_KEYUSAGE_IAKERB_FINISHED.html | 155 + .../macros/KRB5_KEYUSAGE_KDC_REP_TICKET.html | 155 + .../KRB5_KEYUSAGE_KRB_CRED_ENCPART.html | 155 + .../macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM.html | 155 + .../KRB5_KEYUSAGE_KRB_PRIV_ENCPART.html | 155 + .../macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM.html | 155 + .../macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS.html | 156 + .../macros/KRB5_KEYUSAGE_PA_FX_COOKIE.html | 156 + .../macros/KRB5_KEYUSAGE_PA_OTP_REQUEST.html | 156 + .../macros/KRB5_KEYUSAGE_PA_PKINIT_KX.html | 155 + .../KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY.html | 155 + ...RB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST.html | 155 + .../KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.html | 155 + ...RB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.html | 155 + .../macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE.html | 155 + .../refs/macros/KRB5_KEYUSAGE_SPAKE.html | 155 + ...KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.html | 155 + .../KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.html | 155 + .../KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.html | 155 + .../KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY.html | 155 + .../macros/KRB5_KEYUSAGE_TGS_REQ_AUTH.html | 155 + .../KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM.html | 155 + .../macros/KRB5_KPASSWD_ACCESSDENIED.html | 156 + .../refs/macros/KRB5_KPASSWD_AUTHERROR.html | 156 + .../refs/macros/KRB5_KPASSWD_BAD_VERSION.html | 156 + .../refs/macros/KRB5_KPASSWD_HARDERROR.html | 156 + .../KRB5_KPASSWD_INITIAL_FLAG_NEEDED.html | 156 + .../refs/macros/KRB5_KPASSWD_MALFORMED.html | 156 + .../refs/macros/KRB5_KPASSWD_SOFTERROR.html | 156 + .../refs/macros/KRB5_KPASSWD_SUCCESS.html | 156 + .../macros/KRB5_LRQ_ALL_ACCT_EXPTIME.html | 155 + .../macros/KRB5_LRQ_ALL_LAST_INITIAL.html | 155 + .../macros/KRB5_LRQ_ALL_LAST_RENEWAL.html | 155 + .../refs/macros/KRB5_LRQ_ALL_LAST_REQ.html | 155 + .../refs/macros/KRB5_LRQ_ALL_LAST_TGT.html | 155 + .../macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED.html | 155 + .../refs/macros/KRB5_LRQ_ALL_PW_EXPTIME.html | 155 + .../appdev/refs/macros/KRB5_LRQ_NONE.html | 155 + .../macros/KRB5_LRQ_ONE_ACCT_EXPTIME.html | 155 + .../macros/KRB5_LRQ_ONE_LAST_INITIAL.html | 155 + .../macros/KRB5_LRQ_ONE_LAST_RENEWAL.html | 155 + .../refs/macros/KRB5_LRQ_ONE_LAST_REQ.html | 155 + .../refs/macros/KRB5_LRQ_ONE_LAST_TGT.html | 155 + .../macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED.html | 155 + .../refs/macros/KRB5_LRQ_ONE_PW_EXPTIME.html | 155 + .../macros/KRB5_NT_ENTERPRISE_PRINCIPAL.html | 156 + .../macros/KRB5_NT_ENT_PRINCIPAL_AND_ID.html | 156 + .../refs/macros/KRB5_NT_MS_PRINCIPAL.html | 156 + .../macros/KRB5_NT_MS_PRINCIPAL_AND_ID.html | 156 + .../appdev/refs/macros/KRB5_NT_PRINCIPAL.html | 156 + .../appdev/refs/macros/KRB5_NT_SMTP_NAME.html | 156 + .../appdev/refs/macros/KRB5_NT_SRV_HST.html | 156 + .../appdev/refs/macros/KRB5_NT_SRV_INST.html | 156 + .../appdev/refs/macros/KRB5_NT_SRV_XHST.html | 156 + .../html/appdev/refs/macros/KRB5_NT_UID.html | 156 + .../appdev/refs/macros/KRB5_NT_UNKNOWN.html | 156 + .../appdev/refs/macros/KRB5_NT_WELLKNOWN.html | 156 + .../refs/macros/KRB5_NT_X500_PRINCIPAL.html | 156 + .../refs/macros/KRB5_PAC_ATTRIBUTES_INFO.html | 156 + .../refs/macros/KRB5_PAC_CLIENT_CLAIMS.html | 156 + .../refs/macros/KRB5_PAC_CLIENT_INFO.html | 156 + .../macros/KRB5_PAC_CREDENTIALS_INFO.html | 156 + .../refs/macros/KRB5_PAC_DELEGATION_INFO.html | 156 + .../refs/macros/KRB5_PAC_DEVICE_CLAIMS.html | 156 + .../refs/macros/KRB5_PAC_DEVICE_INFO.html | 156 + .../refs/macros/KRB5_PAC_FULL_CHECKSUM.html | 156 + .../refs/macros/KRB5_PAC_LOGON_INFO.html | 156 + .../macros/KRB5_PAC_PRIVSVR_CHECKSUM.html | 156 + .../refs/macros/KRB5_PAC_REQUESTOR.html | 156 + .../refs/macros/KRB5_PAC_SERVER_CHECKSUM.html | 156 + .../refs/macros/KRB5_PAC_TICKET_CHECKSUM.html | 156 + .../refs/macros/KRB5_PAC_UPN_DNS_INFO.html | 156 + .../refs/macros/KRB5_PADATA_AFS3_SALT.html | 157 + .../refs/macros/KRB5_PADATA_AP_REQ.html | 155 + .../refs/macros/KRB5_PADATA_AS_CHECKSUM.html | 156 + .../refs/macros/KRB5_PADATA_AS_FRESHNESS.html | 156 + .../KRB5_PADATA_ENCRYPTED_CHALLENGE.html | 156 + .../KRB5_PADATA_ENC_SANDIA_SECURID.html | 157 + .../macros/KRB5_PADATA_ENC_TIMESTAMP.html | 156 + .../macros/KRB5_PADATA_ENC_UNIX_TIME.html | 157 + .../refs/macros/KRB5_PADATA_ETYPE_INFO.html | 157 + .../refs/macros/KRB5_PADATA_ETYPE_INFO2.html | 156 + .../refs/macros/KRB5_PADATA_FOR_USER.html | 156 + .../refs/macros/KRB5_PADATA_FX_COOKIE.html | 156 + .../refs/macros/KRB5_PADATA_FX_ERROR.html | 156 + .../refs/macros/KRB5_PADATA_FX_FAST.html | 156 + .../KRB5_PADATA_GET_FROM_TYPED_DATA.html | 157 + .../appdev/refs/macros/KRB5_PADATA_NONE.html | 155 + .../refs/macros/KRB5_PADATA_OSF_DCE.html | 157 + .../macros/KRB5_PADATA_OTP_CHALLENGE.html | 156 + .../macros/KRB5_PADATA_OTP_PIN_CHANGE.html | 156 + .../refs/macros/KRB5_PADATA_OTP_REQUEST.html | 156 + .../refs/macros/KRB5_PADATA_PAC_OPTIONS.html | 156 + .../refs/macros/KRB5_PADATA_PAC_REQUEST.html | 156 + .../refs/macros/KRB5_PADATA_PKINIT_KX.html | 156 + .../refs/macros/KRB5_PADATA_PK_AS_REP.html | 157 + .../macros/KRB5_PADATA_PK_AS_REP_OLD.html | 156 + .../refs/macros/KRB5_PADATA_PK_AS_REQ.html | 157 + .../macros/KRB5_PADATA_PK_AS_REQ_OLD.html | 156 + .../refs/macros/KRB5_PADATA_PW_SALT.html | 156 + .../macros/KRB5_PADATA_REDHAT_IDP_OAUTH2.html | 156 + .../macros/KRB5_PADATA_REDHAT_PASSKEY.html | 156 + .../refs/macros/KRB5_PADATA_REFERRAL.html | 156 + .../macros/KRB5_PADATA_S4U_X509_USER.html | 156 + .../macros/KRB5_PADATA_SAM_CHALLENGE.html | 156 + .../macros/KRB5_PADATA_SAM_CHALLENGE_2.html | 156 + .../refs/macros/KRB5_PADATA_SAM_REDIRECT.html | 157 + .../refs/macros/KRB5_PADATA_SAM_RESPONSE.html | 156 + .../macros/KRB5_PADATA_SAM_RESPONSE_2.html | 156 + .../refs/macros/KRB5_PADATA_SESAME.html | 157 + .../appdev/refs/macros/KRB5_PADATA_SPAKE.html | 155 + .../macros/KRB5_PADATA_SVR_REFERRAL_INFO.html | 157 + .../refs/macros/KRB5_PADATA_TGS_REQ.html | 155 + .../KRB5_PADATA_USE_SPECIFIED_KVNO.html | 156 + .../KRB5_PRINCIPAL_COMPARE_CASEFOLD.html | 156 + .../KRB5_PRINCIPAL_COMPARE_ENTERPRISE.html | 156 + .../KRB5_PRINCIPAL_COMPARE_IGNORE_REALM.html | 156 + .../macros/KRB5_PRINCIPAL_COMPARE_UTF8.html | 156 + .../KRB5_PRINCIPAL_PARSE_ENTERPRISE.html | 156 + .../KRB5_PRINCIPAL_PARSE_IGNORE_REALM.html | 156 + .../KRB5_PRINCIPAL_PARSE_NO_DEF_REALM.html | 156 + .../macros/KRB5_PRINCIPAL_PARSE_NO_REALM.html | 156 + .../KRB5_PRINCIPAL_PARSE_REQUIRE_REALM.html | 156 + .../KRB5_PRINCIPAL_UNPARSE_DISPLAY.html | 156 + .../KRB5_PRINCIPAL_UNPARSE_NO_REALM.html | 156 + .../macros/KRB5_PRINCIPAL_UNPARSE_SHORT.html | 156 + .../html/appdev/refs/macros/KRB5_PRIV.html | 156 + .../macros/KRB5_PROMPT_TYPE_NEW_PASSWORD.html | 156 + .../KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN.html | 156 + .../macros/KRB5_PROMPT_TYPE_PASSWORD.html | 156 + .../refs/macros/KRB5_PROMPT_TYPE_PREAUTH.html | 156 + .../html/appdev/refs/macros/KRB5_PVNO.html | 156 + .../refs/macros/KRB5_REALM_BRANCH_CHAR.html | 155 + .../macros/KRB5_RECVAUTH_BADAUTHVERS.html | 155 + .../macros/KRB5_RECVAUTH_SKIP_VERSION.html | 155 + .../refs/macros/KRB5_REFERRAL_REALM.html | 156 + .../KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN.html | 156 + ...RB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN.html | 156 + .../KRB5_RESPONDER_OTP_FLAGS_NEXTOTP.html | 157 + ...KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN.html | 157 + ...RB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC.html | 155 + .../KRB5_RESPONDER_OTP_FORMAT_DECIMAL.html | 156 + ...KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL.html | 155 + ...PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW.html | 156 + ...PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY.html | 156 + ...ER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.html | 156 + .../macros/KRB5_RESPONDER_QUESTION_OTP.html | 183 + .../KRB5_RESPONDER_QUESTION_PASSWORD.html | 157 + .../KRB5_RESPONDER_QUESTION_PKINIT.html | 170 + .../html/appdev/refs/macros/KRB5_SAFE.html | 156 + .../macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD.html | 156 + .../macros/KRB5_SAM_SEND_ENCRYPTED_SAD.html | 155 + .../refs/macros/KRB5_SAM_USE_SAD_AS_KEY.html | 155 + .../refs/macros/KRB5_TC_MATCH_2ND_TKT.html | 156 + .../refs/macros/KRB5_TC_MATCH_AUTHDATA.html | 156 + .../refs/macros/KRB5_TC_MATCH_FLAGS.html | 156 + .../macros/KRB5_TC_MATCH_FLAGS_EXACT.html | 156 + .../refs/macros/KRB5_TC_MATCH_IS_SKEY.html | 156 + .../refs/macros/KRB5_TC_MATCH_KTYPE.html | 156 + .../macros/KRB5_TC_MATCH_SRV_NAMEONLY.html | 156 + .../refs/macros/KRB5_TC_MATCH_TIMES.html | 156 + .../macros/KRB5_TC_MATCH_TIMES_EXACT.html | 156 + .../appdev/refs/macros/KRB5_TC_NOTICKET.html | 155 + .../appdev/refs/macros/KRB5_TC_OPENCLOSE.html | 156 + .../refs/macros/KRB5_TC_SUPPORTED_KTYPES.html | 156 + .../appdev/refs/macros/KRB5_TGS_NAME.html | 155 + .../refs/macros/KRB5_TGS_NAME_SIZE.html | 155 + .../html/appdev/refs/macros/KRB5_TGS_REP.html | 156 + .../html/appdev/refs/macros/KRB5_TGS_REQ.html | 156 + .../KRB5_TKT_CREDS_STEP_FLAG_CONTINUE.html | 156 + ...5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL.html | 155 + .../refs/macros/KRB5_WELLKNOWN_NAMESTR.html | 156 + .../macros/LR_TYPE_INTERPRETATION_MASK.html | 155 + .../refs/macros/LR_TYPE_THIS_SERVER_ONLY.html | 155 + .../refs/macros/MAX_KEYTAB_NAME_LEN.html | 156 + .../html/appdev/refs/macros/MSEC_DIRBIT.html | 155 + .../appdev/refs/macros/MSEC_VAL_MASK.html | 155 + .../refs/macros/SALT_TYPE_AFS_LENGTH.html | 155 + .../refs/macros/SALT_TYPE_NO_LENGTH.html | 155 + .../appdev/refs/macros/THREEPARAMOPEN.html | 155 + .../appdev/refs/macros/TKT_FLG_ANONYMOUS.html | 155 + .../refs/macros/TKT_FLG_ENC_PA_REP.html | 155 + .../refs/macros/TKT_FLG_FORWARDABLE.html | 155 + .../appdev/refs/macros/TKT_FLG_FORWARDED.html | 155 + .../appdev/refs/macros/TKT_FLG_HW_AUTH.html | 155 + .../appdev/refs/macros/TKT_FLG_INITIAL.html | 155 + .../appdev/refs/macros/TKT_FLG_INVALID.html | 155 + .../refs/macros/TKT_FLG_MAY_POSTDATE.html | 155 + .../refs/macros/TKT_FLG_OK_AS_DELEGATE.html | 155 + .../appdev/refs/macros/TKT_FLG_POSTDATED.html | 155 + .../appdev/refs/macros/TKT_FLG_PRE_AUTH.html | 155 + .../appdev/refs/macros/TKT_FLG_PROXIABLE.html | 155 + .../appdev/refs/macros/TKT_FLG_PROXY.html | 155 + .../appdev/refs/macros/TKT_FLG_RENEWABLE.html | 155 + .../TKT_FLG_TRANSIT_POLICY_CHECKED.html | 155 + .../appdev/refs/macros/VALID_INT_BITS.html | 155 + .../appdev/refs/macros/VALID_UINT_BITS.html | 155 + .../doc/html/appdev/refs/macros/index.html | 538 + .../refs/macros/krb524_convert_creds_kdc.html | 155 + .../appdev/refs/macros/krb524_init_ets.html | 155 + .../html/appdev/refs/macros/krb5_const.html | 155 + .../refs/macros/krb5_princ_component.html | 155 + .../appdev/refs/macros/krb5_princ_name.html | 155 + .../appdev/refs/macros/krb5_princ_realm.html | 155 + .../refs/macros/krb5_princ_set_realm.html | 155 + .../macros/krb5_princ_set_realm_data.html | 155 + .../macros/krb5_princ_set_realm_length.html | 155 + .../appdev/refs/macros/krb5_princ_size.html | 155 + .../appdev/refs/macros/krb5_princ_type.html | 155 + .../html/appdev/refs/macros/krb5_roundup.html | 155 + .../doc/html/appdev/refs/macros/krb5_x.html | 155 + .../doc/html/appdev/refs/macros/krb5_xc.html | 155 + .../doc/html/appdev/refs/types/index.html | 248 + .../html/appdev/refs/types/krb5_address.html | 176 + .../html/appdev/refs/types/krb5_addrtype.html | 151 + .../html/appdev/refs/types/krb5_ap_rep.html | 168 + .../refs/types/krb5_ap_rep_enc_part.html | 185 + .../html/appdev/refs/types/krb5_ap_req.html | 179 + .../appdev/refs/types/krb5_auth_context.html | 151 + .../html/appdev/refs/types/krb5_authdata.html | 179 + .../appdev/refs/types/krb5_authdatatype.html | 151 + .../appdev/refs/types/krb5_authenticator.html | 204 + .../html/appdev/refs/types/krb5_boolean.html | 151 + .../appdev/refs/types/krb5_cc_cursor.html | 152 + .../html/appdev/refs/types/krb5_ccache.html | 151 + .../appdev/refs/types/krb5_cccol_cursor.html | 152 + .../html/appdev/refs/types/krb5_checksum.html | 175 + .../appdev/refs/types/krb5_cksumtype.html | 151 + .../appdev/refs/types/krb5_const_pointer.html | 151 + .../refs/types/krb5_const_principal.html | 182 + .../html/appdev/refs/types/krb5_context.html | 151 + .../doc/html/appdev/refs/types/krb5_cred.html | 179 + .../appdev/refs/types/krb5_cred_enc_part.html | 196 + .../appdev/refs/types/krb5_cred_info.html | 197 + .../html/appdev/refs/types/krb5_creds.html | 221 + .../appdev/refs/types/krb5_crypto_iov.html | 168 + .../appdev/refs/types/krb5_cryptotype.html | 151 + .../doc/html/appdev/refs/types/krb5_data.html | 170 + .../html/appdev/refs/types/krb5_deltat.html | 151 + .../html/appdev/refs/types/krb5_enc_data.html | 175 + .../refs/types/krb5_enc_kdc_rep_part.html | 222 + .../appdev/refs/types/krb5_enc_tkt_part.html | 203 + .../appdev/refs/types/krb5_encrypt_block.html | 170 + .../html/appdev/refs/types/krb5_enctype.html | 151 + .../html/appdev/refs/types/krb5_error.html | 215 + .../appdev/refs/types/krb5_error_code.html | 153 + .../refs/types/krb5_expire_callback_func.html | 151 + .../html/appdev/refs/types/krb5_flags.html | 151 + .../refs/types/krb5_get_init_creds_opt.html | 211 + .../refs/types/krb5_gic_opt_pa_data.html | 166 + .../refs/types/krb5_init_creds_context.html | 151 + .../html/appdev/refs/types/krb5_int16.html | 151 + .../html/appdev/refs/types/krb5_int32.html | 151 + .../html/appdev/refs/types/krb5_kdc_rep.html | 197 + .../html/appdev/refs/types/krb5_kdc_req.html | 251 + .../doc/html/appdev/refs/types/krb5_key.html | 153 + .../html/appdev/refs/types/krb5_keyblock.html | 176 + .../html/appdev/refs/types/krb5_keytab.html | 151 + .../appdev/refs/types/krb5_keytab_entry.html | 185 + .../html/appdev/refs/types/krb5_keyusage.html | 151 + .../appdev/refs/types/krb5_kt_cursor.html | 151 + .../doc/html/appdev/refs/types/krb5_kvno.html | 151 + .../refs/types/krb5_last_req_entry.html | 173 + .../html/appdev/refs/types/krb5_magic.html | 151 + .../refs/types/krb5_mk_req_checksum_func.html | 152 + .../html/appdev/refs/types/krb5_msgtype.html | 151 + .../html/appdev/refs/types/krb5_octet.html | 151 + .../html/appdev/refs/types/krb5_pa_data.html | 179 + .../appdev/refs/types/krb5_pa_pac_req.html | 161 + .../types/krb5_pa_server_referral_data.html | 180 + .../refs/types/krb5_pa_svr_referral_data.html | 161 + .../doc/html/appdev/refs/types/krb5_pac.html | 152 + .../html/appdev/refs/types/krb5_pointer.html | 151 + .../appdev/refs/types/krb5_post_recv_fn.html | 154 + .../appdev/refs/types/krb5_pre_send_fn.html | 156 + .../appdev/refs/types/krb5_preauthtype.html | 151 + .../appdev/refs/types/krb5_principal.html | 181 + .../refs/types/krb5_principal_data.html | 181 + .../html/appdev/refs/types/krb5_prompt.html | 175 + .../appdev/refs/types/krb5_prompt_type.html | 151 + .../appdev/refs/types/krb5_prompter_fct.html | 152 + .../html/appdev/refs/types/krb5_pwd_data.html | 170 + .../html/appdev/refs/types/krb5_rcache.html | 151 + .../appdev/refs/types/krb5_replay_data.html | 175 + .../refs/types/krb5_responder_context.html | 153 + .../appdev/refs/types/krb5_responder_fn.html | 153 + .../types/krb5_responder_otp_challenge.html | 165 + .../types/krb5_responder_otp_tokeninfo.html | 190 + .../krb5_responder_pkinit_challenge.html | 160 + .../types/krb5_responder_pkinit_identity.html | 165 + .../html/appdev/refs/types/krb5_response.html | 180 + .../html/appdev/refs/types/krb5_ticket.html | 180 + .../appdev/refs/types/krb5_ticket_times.html | 180 + .../appdev/refs/types/krb5_timestamp.html | 153 + .../appdev/refs/types/krb5_tkt_authent.html | 176 + .../refs/types/krb5_tkt_creds_context.html | 151 + .../refs/types/krb5_trace_callback.html | 151 + .../appdev/refs/types/krb5_trace_info.html | 162 + .../appdev/refs/types/krb5_transited.html | 173 + .../appdev/refs/types/krb5_typed_data.html | 175 + .../doc/html/appdev/refs/types/krb5_ui_2.html | 151 + .../doc/html/appdev/refs/types/krb5_ui_4.html | 151 + .../types/krb5_verify_init_creds_opt.html | 166 + .../refs/types/passwd_phrase_element.html | 170 + krb5-1.21.3/doc/html/appdev/y2038.html | 157 + krb5-1.21.3/doc/html/basic/ccache_def.html | 279 + krb5-1.21.3/doc/html/basic/date_format.html | 331 + krb5-1.21.3/doc/html/basic/index.html | 142 + krb5-1.21.3/doc/html/basic/keytab_def.html | 182 + krb5-1.21.3/doc/html/basic/rcache_def.html | 231 + .../doc/html/basic/stash_file_def.html | 150 + krb5-1.21.3/doc/html/build/directory_org.html | 244 + krb5-1.21.3/doc/html/build/doing_build.html | 270 + krb5-1.21.3/doc/html/build/index.html | 190 + .../doc/html/build/options2configure.html | 465 + krb5-1.21.3/doc/html/build/osconf.html | 156 + krb5-1.21.3/doc/html/build_this.html | 202 + krb5-1.21.3/doc/html/copyright.html | 130 + .../doc/html/formats/ccache_file_format.html | 295 + krb5-1.21.3/doc/html/formats/cookie.html | 222 + .../doc/html/formats/freshness_token.html | 149 + krb5-1.21.3/doc/html/formats/index.html | 142 + .../doc/html/formats/keytab_file_format.html | 179 + .../doc/html/formats/rcache_file_format.html | 173 + krb5-1.21.3/doc/html/genindex-A.html | 159 + krb5-1.21.3/doc/html/genindex-C.html | 153 + krb5-1.21.3/doc/html/genindex-E.html | 169 + krb5-1.21.3/doc/html/genindex-K.html | 2077 + krb5-1.21.3/doc/html/genindex-L.html | 123 + krb5-1.21.3/doc/html/genindex-M.html | 125 + krb5-1.21.3/doc/html/genindex-P.html | 127 + krb5-1.21.3/doc/html/genindex-R.html | 184 + krb5-1.21.3/doc/html/genindex-S.html | 123 + krb5-1.21.3/doc/html/genindex-T.html | 151 + krb5-1.21.3/doc/html/genindex-V.html | 123 + krb5-1.21.3/doc/html/genindex-all.html | 2419 ++ krb5-1.21.3/doc/html/genindex.html | 131 + krb5-1.21.3/doc/html/index.html | 136 + krb5-1.21.3/doc/html/mitK5defaults.html | 361 + krb5-1.21.3/doc/html/mitK5features.html | 789 + krb5-1.21.3/doc/html/mitK5license.html | 1301 + krb5-1.21.3/doc/html/objects.inv | Bin 0 -> 49033 bytes krb5-1.21.3/doc/html/plugindev/ccselect.html | 160 + krb5-1.21.3/doc/html/plugindev/certauth.html | 170 + krb5-1.21.3/doc/html/plugindev/clpreauth.html | 187 + krb5-1.21.3/doc/html/plugindev/general.html | 242 + krb5-1.21.3/doc/html/plugindev/gssapi.html | 259 + krb5-1.21.3/doc/html/plugindev/hostrealm.html | 170 + krb5-1.21.3/doc/html/plugindev/index.html | 185 + krb5-1.21.3/doc/html/plugindev/internal.html | 171 + .../doc/html/plugindev/kadm5_auth.html | 169 + .../doc/html/plugindev/kadm5_hook.html | 162 + krb5-1.21.3/doc/html/plugindev/kdcpolicy.html | 160 + .../doc/html/plugindev/kdcpreauth.html | 207 + krb5-1.21.3/doc/html/plugindev/localauth.html | 176 + krb5-1.21.3/doc/html/plugindev/locate.html | 165 + krb5-1.21.3/doc/html/plugindev/profile.html | 229 + krb5-1.21.3/doc/html/plugindev/pwqual.html | 161 + krb5-1.21.3/doc/html/resources.html | 180 + krb5-1.21.3/doc/html/search.html | 144 + krb5-1.21.3/doc/html/searchindex.js | 1 + krb5-1.21.3/doc/html/user/index.html | 167 + krb5-1.21.3/doc/html/user/pwd_mgmt.html | 229 + krb5-1.21.3/doc/html/user/tkt_mgmt.html | 449 + .../doc/html/user/user_commands/index.html | 156 + .../doc/html/user/user_commands/kdestroy.html | 212 + .../doc/html/user/user_commands/kinit.html | 341 + .../doc/html/user/user_commands/klist.html | 254 + .../doc/html/user/user_commands/kpasswd.html | 184 + .../html/user/user_commands/krb5-config.html | 229 + .../doc/html/user/user_commands/ksu.html | 516 + .../doc/html/user/user_commands/kswitch.html | 189 + .../doc/html/user/user_commands/kvno.html | 247 + .../doc/html/user/user_commands/sclient.html | 169 + .../doc/html/user/user_config/index.html | 147 + .../doc/html/user/user_config/k5identity.html | 195 + .../doc/html/user/user_config/k5login.html | 186 + .../doc/html/user/user_config/kerberos.html | 303 + krb5-1.21.3/doc/index.rst | 18 + krb5-1.21.3/doc/iprop-notes.txt | 140 + krb5-1.21.3/doc/kadm5-errmsg.txt | 59 + krb5-1.21.3/doc/kadm5/adb-unit-test.tex | 135 + krb5-1.21.3/doc/kadm5/api-funcspec.tex | 2015 + krb5-1.21.3/doc/kadm5/api-server-design.tex | 1054 + krb5-1.21.3/doc/kadm5/fullpage.sty | 9 + krb5-1.21.3/doc/mitK5defaults.rst | 79 + krb5-1.21.3/doc/mitK5features.rst | 699 + krb5-1.21.3/doc/mitK5license.rst | 11 + krb5-1.21.3/doc/notice.rst | 1271 + krb5-1.21.3/doc/pdf/GMakefile | 64 + krb5-1.21.3/doc/pdf/LICRcyr2utf8.xdy | 101 + krb5-1.21.3/doc/pdf/LICRlatin2utf8.xdy | 239 + krb5-1.21.3/doc/pdf/LatinRules.xdy | 607 + krb5-1.21.3/doc/pdf/admin.pdf | Bin 0 -> 648892 bytes krb5-1.21.3/doc/pdf/admin.tex | 12287 ++++++ krb5-1.21.3/doc/pdf/appdev.pdf | Bin 0 -> 829074 bytes krb5-1.21.3/doc/pdf/appdev.tex | 31210 ++++++++++++++++ krb5-1.21.3/doc/pdf/basic.pdf | Bin 0 -> 185464 bytes krb5-1.21.3/doc/pdf/basic.tex | 918 + krb5-1.21.3/doc/pdf/build.pdf | Bin 0 -> 203594 bytes krb5-1.21.3/doc/pdf/build.tex | 1091 + krb5-1.21.3/doc/pdf/latexmkjarc | 22 + krb5-1.21.3/doc/pdf/latexmkrc | 9 + krb5-1.21.3/doc/pdf/make.bat | 31 + krb5-1.21.3/doc/pdf/plugindev.pdf | Bin 0 -> 199462 bytes krb5-1.21.3/doc/pdf/plugindev.tex | 1020 + krb5-1.21.3/doc/pdf/python.ist | 16 + krb5-1.21.3/doc/pdf/sphinx.sty | 351 + krb5-1.21.3/doc/pdf/sphinx.xdy | 230 + krb5-1.21.3/doc/pdf/sphinxhighlight.sty | 106 + krb5-1.21.3/doc/pdf/sphinxhowto.cls | 102 + .../doc/pdf/sphinxlatexadmonitions.sty | 148 + krb5-1.21.3/doc/pdf/sphinxlatexcontainers.sty | 22 + krb5-1.21.3/doc/pdf/sphinxlatexgraphics.sty | 122 + krb5-1.21.3/doc/pdf/sphinxlatexindbibtoc.sty | 69 + krb5-1.21.3/doc/pdf/sphinxlatexlists.sty | 97 + krb5-1.21.3/doc/pdf/sphinxlatexliterals.sty | 795 + krb5-1.21.3/doc/pdf/sphinxlatexnumfig.sty | 122 + krb5-1.21.3/doc/pdf/sphinxlatexobjects.sty | 200 + krb5-1.21.3/doc/pdf/sphinxlatexshadowbox.sty | 100 + .../doc/pdf/sphinxlatexstyleheadings.sty | 83 + krb5-1.21.3/doc/pdf/sphinxlatexstylepage.sty | 79 + krb5-1.21.3/doc/pdf/sphinxlatexstyletext.sty | 126 + krb5-1.21.3/doc/pdf/sphinxlatextables.sty | 481 + krb5-1.21.3/doc/pdf/sphinxmanual.cls | 128 + krb5-1.21.3/doc/pdf/sphinxmessages.sty | 21 + krb5-1.21.3/doc/pdf/sphinxoptionsgeometry.sty | 54 + krb5-1.21.3/doc/pdf/sphinxoptionshyperref.sty | 35 + krb5-1.21.3/doc/pdf/sphinxpackagecyrillic.sty | 55 + krb5-1.21.3/doc/pdf/sphinxpackagefootnote.sty | 396 + krb5-1.21.3/doc/pdf/user.pdf | Bin 0 -> 254843 bytes krb5-1.21.3/doc/pdf/user.tex | 2456 ++ krb5-1.21.3/doc/plugindev/ccselect.rst | 28 + krb5-1.21.3/doc/plugindev/certauth.rst | 36 + krb5-1.21.3/doc/plugindev/clpreauth.rst | 54 + krb5-1.21.3/doc/plugindev/general.rst | 118 + krb5-1.21.3/doc/plugindev/gssapi.rst | 134 + krb5-1.21.3/doc/plugindev/hostrealm.rst | 39 + krb5-1.21.3/doc/plugindev/index.rst | 38 + krb5-1.21.3/doc/plugindev/internal.rst | 32 + krb5-1.21.3/doc/plugindev/kadm5_auth.rst | 35 + krb5-1.21.3/doc/plugindev/kadm5_hook.rst | 27 + krb5-1.21.3/doc/plugindev/kdcpolicy.rst | 24 + krb5-1.21.3/doc/plugindev/kdcpreauth.rst | 79 + krb5-1.21.3/doc/plugindev/localauth.rst | 43 + krb5-1.21.3/doc/plugindev/locate.rst | 32 + krb5-1.21.3/doc/plugindev/profile.rst | 96 + krb5-1.21.3/doc/plugindev/pwqual.rst | 25 + krb5-1.21.3/doc/resources.rst | 60 + krb5-1.21.3/doc/rpc/design.tex | 1037 + krb5-1.21.3/doc/thread-safe.txt | 241 + krb5-1.21.3/doc/threads.txt | 101 + krb5-1.21.3/doc/tools/README | 62 + krb5-1.21.3/doc/tools/define_document.tmpl | 27 + krb5-1.21.3/doc/tools/docmodel.py | 251 + krb5-1.21.3/doc/tools/doxy.py | 64 + krb5-1.21.3/doc/tools/doxybuilder_funcs.py | 594 + krb5-1.21.3/doc/tools/doxybuilder_types.py | 382 + krb5-1.21.3/doc/tools/func_document.tmpl | 102 + krb5-1.21.3/doc/tools/type_document.tmpl | 43 + krb5-1.21.3/doc/user/index.rst | 10 + krb5-1.21.3/doc/user/pwd_mgmt.rst | 106 + krb5-1.21.3/doc/user/tkt_mgmt.rst | 314 + krb5-1.21.3/doc/user/user_commands/index.rst | 17 + .../doc/user/user_commands/kdestroy.rst | 77 + krb5-1.21.3/doc/user/user_commands/kinit.rst | 230 + krb5-1.21.3/doc/user/user_commands/klist.rst | 129 + .../doc/user/user_commands/kpasswd.rst | 46 + .../doc/user/user_commands/krb5-config.rst | 83 + krb5-1.21.3/doc/user/user_commands/ksu.rst | 411 + .../doc/user/user_commands/kswitch.rst | 50 + krb5-1.21.3/doc/user/user_commands/kvno.rst | 119 + .../doc/user/user_commands/sclient.rst | 30 + krb5-1.21.3/doc/user/user_config/index.rst | 13 + .../doc/user/user_config/k5identity.rst | 64 + krb5-1.21.3/doc/user/user_config/k5login.rst | 54 + krb5-1.21.3/doc/user/user_config/kerberos.rst | 185 + krb5-1.21.3/src/Makefile.in | 693 + krb5-1.21.3/src/aclocal.m4 | 1460 + krb5-1.21.3/src/appl/Makefile.in | 5 + krb5-1.21.3/src/appl/deps | 1 + krb5-1.21.3/src/appl/gss-sample/Makefile.in | 50 + krb5-1.21.3/src/appl/gss-sample/README | 165 + krb5-1.21.3/src/appl/gss-sample/deps | 16 + krb5-1.21.3/src/appl/gss-sample/gss-client.c | 921 + krb5-1.21.3/src/appl/gss-sample/gss-misc.c | 425 + krb5-1.21.3/src/appl/gss-sample/gss-misc.h | 56 + krb5-1.21.3/src/appl/gss-sample/gss-server.c | 912 + .../src/appl/gss-sample/t_gss_sample.py | 133 + krb5-1.21.3/src/appl/sample/Makefile.in | 6 + krb5-1.21.3/src/appl/sample/deps | 1 + krb5-1.21.3/src/appl/sample/sample.h | 33 + .../src/appl/sample/sclient/Makefile.in | 13 + krb5-1.21.3/src/appl/sample/sclient/deps | 1 + krb5-1.21.3/src/appl/sample/sclient/sclient.c | 260 + .../src/appl/sample/sserver/Makefile.in | 13 + krb5-1.21.3/src/appl/sample/sserver/deps | 1 + krb5-1.21.3/src/appl/sample/sserver/sserver.c | 246 + krb5-1.21.3/src/appl/sample/t_sample.py | 22 + krb5-1.21.3/src/appl/simple/Makefile.in | 6 + .../src/appl/simple/client/Makefile.in | 15 + krb5-1.21.3/src/appl/simple/client/deps | 1 + .../src/appl/simple/client/sim_client.c | 290 + krb5-1.21.3/src/appl/simple/deps | 1 + .../src/appl/simple/server/Makefile.in | 15 + krb5-1.21.3/src/appl/simple/server/deps | 1 + .../src/appl/simple/server/sim_server.c | 269 + krb5-1.21.3/src/appl/simple/simple.h | 33 + krb5-1.21.3/src/appl/simple/t_simple.py | 34 + krb5-1.21.3/src/appl/user_user/Makefile.in | 22 + krb5-1.21.3/src/appl/user_user/client.c | 283 + krb5-1.21.3/src/appl/user_user/deps | 1 + krb5-1.21.3/src/appl/user_user/server.c | 247 + krb5-1.21.3/src/appl/user_user/t_user2user.py | 18 + krb5-1.21.3/src/build-tools/Makefile.in | 50 + krb5-1.21.3/src/build-tools/deps | 1 + krb5-1.21.3/src/build-tools/gssrpc.pc.in | 12 + krb5-1.21.3/src/build-tools/kadm-client.pc.in | 11 + krb5-1.21.3/src/build-tools/kadm-server.pc.in | 11 + krb5-1.21.3/src/build-tools/kdb.pc.in | 14 + krb5-1.21.3/src/build-tools/krb5-config.in | 262 + krb5-1.21.3/src/build-tools/krb5-gssapi.pc.in | 10 + krb5-1.21.3/src/build-tools/krb5.pc.in | 14 + .../src/build-tools/mit-krb5-gssapi.pc.in | 11 + krb5-1.21.3/src/build-tools/mit-krb5.pc.in | 15 + krb5-1.21.3/src/build-tools/t_krbconf | 38 + krb5-1.21.3/src/ccapi/Makefile.in | 5 + krb5-1.21.3/src/ccapi/common/Makefile.in | 65 + .../src/ccapi/common/cci_array_internal.c | 312 + .../src/ccapi/common/cci_array_internal.h | 65 + krb5-1.21.3/src/ccapi/common/cci_common.h | 56 + krb5-1.21.3/src/ccapi/common/cci_cred_union.c | 848 + krb5-1.21.3/src/ccapi/common/cci_cred_union.h | 52 + krb5-1.21.3/src/ccapi/common/cci_debugging.c | 54 + krb5-1.21.3/src/ccapi/common/cci_debugging.h | 43 + krb5-1.21.3/src/ccapi/common/cci_identifier.c | 290 + krb5-1.21.3/src/ccapi/common/cci_identifier.h | 64 + krb5-1.21.3/src/ccapi/common/cci_message.c | 213 + krb5-1.21.3/src/ccapi/common/cci_message.h | 52 + .../src/ccapi/common/cci_os_debugging.h | 34 + .../src/ccapi/common/cci_os_identifier.h | 33 + krb5-1.21.3/src/ccapi/common/cci_types.h | 102 + krb5-1.21.3/src/ccapi/common/unix/Makefile.in | 13 + .../src/ccapi/common/win/OldCC/autolock.hxx | 66 + .../src/ccapi/common/win/OldCC/ccutil.cxx | 187 + .../src/ccapi/common/win/OldCC/ccutil.def | 5 + .../src/ccapi/common/win/OldCC/ccutils.c | 133 + .../src/ccapi/common/win/OldCC/ccutils.h | 45 + .../src/ccapi/common/win/OldCC/init.cxx | 187 + .../src/ccapi/common/win/OldCC/init.hxx | 102 + krb5-1.21.3/src/ccapi/common/win/OldCC/name.h | 34 + .../src/ccapi/common/win/OldCC/opts.cxx | 149 + .../src/ccapi/common/win/OldCC/opts.hxx | 56 + .../src/ccapi/common/win/OldCC/secure.cxx | 161 + .../src/ccapi/common/win/OldCC/secure.hxx | 54 + .../src/ccapi/common/win/OldCC/util.cxx | 520 + krb5-1.21.3/src/ccapi/common/win/OldCC/util.h | 85 + .../src/ccapi/common/win/cci_os_debugging.c | 40 + .../src/ccapi/common/win/cci_os_identifier.c | 57 + .../src/ccapi/common/win/ccs_reply.Acf | 31 + .../src/ccapi/common/win/ccs_reply.Idl | 60 + .../src/ccapi/common/win/ccs_request.Acf | 31 + .../src/ccapi/common/win/ccs_request.idl | 58 + krb5-1.21.3/src/ccapi/common/win/tls.c | 77 + krb5-1.21.3/src/ccapi/common/win/tls.h | 71 + krb5-1.21.3/src/ccapi/common/win/win-utils.c | 68 + krb5-1.21.3/src/ccapi/common/win/win-utils.h | 55 + krb5-1.21.3/src/ccapi/deps | 1 + .../src/ccapi/doc/CCAPI-Windows-Design.html | 148 + krb5-1.21.3/src/ccapi/lib/Makefile.in | 61 + krb5-1.21.3/src/ccapi/lib/ccapi.exports | 1 + krb5-1.21.3/src/ccapi/lib/ccapi_ccache.c | 793 + krb5-1.21.3/src/ccapi/lib/ccapi_ccache.h | 105 + .../src/ccapi/lib/ccapi_ccache_iterator.c | 291 + .../src/ccapi/lib/ccapi_ccache_iterator.h | 51 + krb5-1.21.3/src/ccapi/lib/ccapi_context.c | 831 + krb5-1.21.3/src/ccapi/lib/ccapi_context.h | 86 + .../src/ccapi/lib/ccapi_context_change_time.c | 199 + .../src/ccapi/lib/ccapi_context_change_time.h | 41 + krb5-1.21.3/src/ccapi/lib/ccapi_credentials.c | 165 + krb5-1.21.3/src/ccapi/lib/ccapi_credentials.h | 43 + .../ccapi/lib/ccapi_credentials_iterator.c | 246 + .../ccapi/lib/ccapi_credentials_iterator.h | 51 + krb5-1.21.3/src/ccapi/lib/ccapi_err.et | 74 + krb5-1.21.3/src/ccapi/lib/ccapi_ipc.c | 119 + krb5-1.21.3/src/ccapi/lib/ccapi_ipc.h | 45 + krb5-1.21.3/src/ccapi/lib/ccapi_os_ipc.h | 39 + krb5-1.21.3/src/ccapi/lib/ccapi_string.c | 101 + krb5-1.21.3/src/ccapi/lib/ccapi_string.h | 36 + krb5-1.21.3/src/ccapi/lib/ccapi_v2.c | 889 + krb5-1.21.3/src/ccapi/lib/ccapi_v2.exports | 23 + krb5-1.21.3/src/ccapi/lib/deps | 86 + .../src/ccapi/lib/libkrb5-ccapi.exports | 1 + krb5-1.21.3/src/ccapi/lib/unix/Makefile.in | 12 + krb5-1.21.3/src/ccapi/lib/unix/deps | 1 + krb5-1.21.3/src/ccapi/lib/unix/stubs.c | 10 + krb5-1.21.3/src/ccapi/lib/win/Makefile.in | 123 + krb5-1.21.3/src/ccapi/lib/win/OldCC/ccapi.h | 260 + .../src/ccapi/lib/win/OldCC/client.cxx | 388 + krb5-1.21.3/src/ccapi/lib/win/OldCC/client.h | 60 + krb5-1.21.3/src/ccapi/lib/win/WINCCAPI.sln | 20 + krb5-1.21.3/src/ccapi/lib/win/WINCCAPI.vcproj | 111 + .../src/ccapi/lib/win/ccapi_os_ipc.cxx | 365 + .../src/ccapi/lib/win/ccs_reply_proc.c | 91 + krb5-1.21.3/src/ccapi/lib/win/debug.exports | 11 + krb5-1.21.3/src/ccapi/lib/win/dllmain.cxx | 212 + krb5-1.21.3/src/ccapi/lib/win/dllmain.h | 41 + krb5-1.21.3/src/ccapi/server/Makefile.in | 59 + krb5-1.21.3/src/ccapi/server/ccs_array.c | 309 + krb5-1.21.3/src/ccapi/server/ccs_array.h | 132 + .../src/ccapi/server/ccs_cache_collection.c | 1109 + .../src/ccapi/server/ccs_cache_collection.h | 72 + krb5-1.21.3/src/ccapi/server/ccs_callback.c | 238 + krb5-1.21.3/src/ccapi/server/ccs_callback.h | 61 + krb5-1.21.3/src/ccapi/server/ccs_ccache.c | 1183 + krb5-1.21.3/src/ccapi/server/ccs_ccache.h | 82 + .../src/ccapi/server/ccs_ccache_iterator.c | 156 + .../src/ccapi/server/ccs_ccache_iterator.h | 37 + krb5-1.21.3/src/ccapi/server/ccs_client.c | 236 + krb5-1.21.3/src/ccapi/server/ccs_client.h | 52 + krb5-1.21.3/src/ccapi/server/ccs_common.h | 47 + .../src/ccapi/server/ccs_credentials.c | 139 + .../src/ccapi/server/ccs_credentials.h | 46 + .../ccapi/server/ccs_credentials_iterator.c | 158 + .../ccapi/server/ccs_credentials_iterator.h | 37 + krb5-1.21.3/src/ccapi/server/ccs_list.c | 361 + krb5-1.21.3/src/ccapi/server/ccs_list.h | 140 + .../src/ccapi/server/ccs_list_internal.c | 675 + .../src/ccapi/server/ccs_list_internal.h | 94 + krb5-1.21.3/src/ccapi/server/ccs_lock.c | 248 + krb5-1.21.3/src/ccapi/server/ccs_lock.h | 61 + krb5-1.21.3/src/ccapi/server/ccs_lock_state.c | 525 + krb5-1.21.3/src/ccapi/server/ccs_lock_state.h | 51 + krb5-1.21.3/src/ccapi/server/ccs_os_notify.h | 37 + krb5-1.21.3/src/ccapi/server/ccs_os_pipe.h | 42 + krb5-1.21.3/src/ccapi/server/ccs_os_server.h | 40 + krb5-1.21.3/src/ccapi/server/ccs_pipe.c | 58 + krb5-1.21.3/src/ccapi/server/ccs_pipe.h | 42 + krb5-1.21.3/src/ccapi/server/ccs_server.c | 408 + krb5-1.21.3/src/ccapi/server/ccs_server.h | 53 + krb5-1.21.3/src/ccapi/server/ccs_types.h | 120 + krb5-1.21.3/src/ccapi/server/deps | 170 + krb5-1.21.3/src/ccapi/server/unix/Makefile.in | 12 + krb5-1.21.3/src/ccapi/server/unix/deps | 1 + krb5-1.21.3/src/ccapi/server/win/Makefile.in | 114 + krb5-1.21.3/src/ccapi/server/win/Server.sln | 20 + .../src/ccapi/server/win/Server.vcproj | 227 + krb5-1.21.3/src/ccapi/server/win/WorkItem.cpp | 142 + .../src/ccapi/server/win/WorkQueue.cpp | 74 + krb5-1.21.3/src/ccapi/server/win/WorkQueue.h | 51 + .../src/ccapi/server/win/ccs_os_pipe.c | 62 + .../src/ccapi/server/win/ccs_os_server.cpp | 950 + .../src/ccapi/server/win/ccs_request_proc.c | 108 + .../src/ccapi/server/win/ccs_win_pipe.c | 162 + .../src/ccapi/server/win/ccs_win_pipe.h | 68 + krb5-1.21.3/src/ccapi/server/win/workitem.h | 51 + krb5-1.21.3/src/ccapi/test/Makefile.in | 225 + krb5-1.21.3/src/ccapi/test/Makefile.w32 | 75 + krb5-1.21.3/src/ccapi/test/Pingtest.sln | 20 + krb5-1.21.3/src/ccapi/test/deps | 0 krb5-1.21.3/src/ccapi/test/main.c | 90 + krb5-1.21.3/src/ccapi/test/pingtest.c | 110 + krb5-1.21.3/src/ccapi/test/setlib.pl | 10 + krb5-1.21.3/src/ccapi/test/simple_lock_test.c | 91 + .../test_cc_ccache_clear_kdc_time_offset.c | 15 + .../src/ccapi/test/test_cc_ccache_compare.c | 15 + .../src/ccapi/test/test_cc_ccache_destroy.c | 15 + .../test/test_cc_ccache_get_change_time.c | 15 + .../test_cc_ccache_get_credentials_version.c | 15 + .../test/test_cc_ccache_get_kdc_time_offset.c | 15 + .../test_cc_ccache_get_last_default_time.c | 15 + .../src/ccapi/test/test_cc_ccache_get_name.c | 15 + .../ccapi/test/test_cc_ccache_get_principal.c | 15 + .../ccapi/test/test_cc_ccache_iterator_next.c | 15 + .../src/ccapi/test/test_cc_ccache_move.c | 15 + .../test_cc_ccache_new_credentials_iterator.c | 15 + .../src/ccapi/test/test_cc_ccache_release.c | 15 + .../test/test_cc_ccache_remove_credentials.c | 15 + .../ccapi/test/test_cc_ccache_set_default.c | 15 + .../test/test_cc_ccache_set_kdc_time_offset.c | 15 + .../ccapi/test/test_cc_ccache_set_principal.c | 15 + .../test/test_cc_ccache_store_credentials.c | 15 + krb5-1.21.3/src/ccapi/test/test_cc_close.c | 14 + .../src/ccapi/test/test_cc_context_compare.c | 15 + .../test/test_cc_context_create_ccache.c | 15 + .../test_cc_context_create_default_ccache.c | 15 + .../test/test_cc_context_create_new_ccache.c | 15 + .../test/test_cc_context_get_change_time.c | 15 + .../test_cc_context_get_default_ccache_name.c | 15 + .../test_cc_context_new_ccache_iterator.c | 15 + .../ccapi/test/test_cc_context_open_ccache.c | 15 + .../test_cc_context_open_default_ccache.c | 15 + .../src/ccapi/test/test_cc_context_release.c | 15 + krb5-1.21.3/src/ccapi/test/test_cc_create.c | 14 + .../test/test_cc_credentials_iterator_next.c | 16 + krb5-1.21.3/src/ccapi/test/test_cc_destroy.c | 14 + .../src/ccapi/test/test_cc_get_NC_info.c | 14 + .../src/ccapi/test/test_cc_get_change_time.c | 14 + .../src/ccapi/test/test_cc_get_cred_version.c | 14 + krb5-1.21.3/src/ccapi/test/test_cc_get_name.c | 14 + .../src/ccapi/test/test_cc_get_principal.c | 14 + .../src/ccapi/test/test_cc_initialize.c | 15 + krb5-1.21.3/src/ccapi/test/test_cc_open.c | 14 + .../src/ccapi/test/test_cc_remove_cred.c | 14 + .../ccapi/test/test_cc_seq_fetch_NCs_begin.c | 14 + .../ccapi/test/test_cc_seq_fetch_NCs_next.c | 14 + .../test/test_cc_seq_fetch_creds_begin.c | 14 + .../ccapi/test/test_cc_seq_fetch_creds_next.c | 14 + .../src/ccapi/test/test_cc_set_principal.c | 14 + krb5-1.21.3/src/ccapi/test/test_cc_shutdown.c | 14 + krb5-1.21.3/src/ccapi/test/test_cc_store.c | 14 + krb5-1.21.3/src/ccapi/test/test_ccapi.bat | 43 + krb5-1.21.3/src/ccapi/test/test_ccapi.sh | 76 + .../src/ccapi/test/test_ccapi_ccache.c | 1875 + .../src/ccapi/test/test_ccapi_ccache.h | 49 + krb5-1.21.3/src/ccapi/test/test_ccapi_check.c | 37 + krb5-1.21.3/src/ccapi/test/test_ccapi_check.h | 43 + .../src/ccapi/test/test_ccapi_constants.c | 64 + .../src/ccapi/test/test_ccapi_constants.h | 6 + .../src/ccapi/test/test_ccapi_context.c | 987 + .../src/ccapi/test/test_ccapi_context.h | 32 + .../src/ccapi/test/test_ccapi_globals.c | 87 + .../src/ccapi/test/test_ccapi_globals.h | 57 + .../src/ccapi/test/test_ccapi_iterators.c | 246 + .../src/ccapi/test/test_ccapi_iterators.h | 12 + krb5-1.21.3/src/ccapi/test/test_ccapi_log.c | 45 + krb5-1.21.3/src/ccapi/test/test_ccapi_log.h | 20 + krb5-1.21.3/src/ccapi/test/test_ccapi_util.c | 142 + krb5-1.21.3/src/ccapi/test/test_ccapi_util.h | 13 + krb5-1.21.3/src/ccapi/test/test_ccapi_v2.c | 1750 + krb5-1.21.3/src/ccapi/test/test_ccapi_v2.h | 73 + krb5-1.21.3/src/ccapi/test/test_constants.c | 15 + krb5-1.21.3/src/clients/Makefile.in | 7 + krb5-1.21.3/src/clients/deps | 1 + krb5-1.21.3/src/clients/kcpytkt/Makefile.in | 32 + krb5-1.21.3/src/clients/kcpytkt/kcpytkt.c | 174 + krb5-1.21.3/src/clients/kdeltkt/Makefile.in | 32 + krb5-1.21.3/src/clients/kdeltkt/kdeltkt.c | 169 + krb5-1.21.3/src/clients/kdestroy/Makefile.in | 35 + krb5-1.21.3/src/clients/kdestroy/deps | 7 + krb5-1.21.3/src/clients/kdestroy/kdestroy.c | 229 + krb5-1.21.3/src/clients/kinit/Makefile.in | 34 + krb5-1.21.3/src/clients/kinit/deps | 32 + krb5-1.21.3/src/clients/kinit/extern.h | 33 + krb5-1.21.3/src/clients/kinit/kinit.c | 892 + krb5-1.21.3/src/clients/kinit/kinit_kdb.c | 75 + krb5-1.21.3/src/clients/klist/Makefile.in | 35 + krb5-1.21.3/src/clients/klist/deps | 14 + krb5-1.21.3/src/clients/klist/klist.c | 870 + krb5-1.21.3/src/clients/kpasswd/Makefile.in | 33 + krb5-1.21.3/src/clients/kpasswd/deps | 7 + krb5-1.21.3/src/clients/kpasswd/kpasswd.c | 177 + krb5-1.21.3/src/clients/ksu/Makefile.in | 35 + krb5-1.21.3/src/clients/ksu/authorization.c | 710 + krb5-1.21.3/src/clients/ksu/ccache.c | 732 + krb5-1.21.3/src/clients/ksu/deps | 72 + krb5-1.21.3/src/clients/ksu/heuristic.c | 749 + krb5-1.21.3/src/clients/ksu/krb_auth_su.c | 311 + krb5-1.21.3/src/clients/ksu/ksu.h | 247 + krb5-1.21.3/src/clients/ksu/main.c | 1087 + krb5-1.21.3/src/clients/ksu/setenv.c | 174 + krb5-1.21.3/src/clients/ksu/xmalloc.c | 80 + krb5-1.21.3/src/clients/kswitch/Makefile.in | 33 + krb5-1.21.3/src/clients/kswitch/deps | 13 + krb5-1.21.3/src/clients/kswitch/kswitch.c | 129 + krb5-1.21.3/src/clients/kvno/Makefile.in | 39 + krb5-1.21.3/src/clients/kvno/deps | 14 + krb5-1.21.3/src/clients/kvno/kvno.c | 609 + krb5-1.21.3/src/clients/kvno/t_kvno.py | 75 + krb5-1.21.3/src/config-files/Makefile.in | 8 + .../src/config-files/convert-config-files | 84 + krb5-1.21.3/src/config-files/deps | 1 + krb5-1.21.3/src/config-files/kdc.conf | 14 + krb5-1.21.3/src/config-files/krb5.conf | 19 + krb5-1.21.3/src/config-files/mech | 3 + krb5-1.21.3/src/config-files/services.append | 12 + krb5-1.21.3/src/config/ac-archive/README | 9 + .../src/config/ac-archive/ax_pthread.m4 | 522 + .../config/ac-archive/ax_recursive_eval.m4 | 56 + krb5-1.21.3/src/config/config.guess | 1774 + krb5-1.21.3/src/config/config.sub | 1907 + krb5-1.21.3/src/config/install-sh | 295 + krb5-1.21.3/src/config/lib.in | 164 + krb5-1.21.3/src/config/libnodeps.in | 4 + krb5-1.21.3/src/config/libnover.in | 132 + krb5-1.21.3/src/config/libobj.in | 42 + krb5-1.21.3/src/config/libpriv.in | 12 + krb5-1.21.3/src/config/mkinstalldirs | 40 + krb5-1.21.3/src/config/move-if-changed | 17 + krb5-1.21.3/src/config/pkg.m4 | 275 + krb5-1.21.3/src/config/post.in | 242 + krb5-1.21.3/src/config/pre.in | 610 + krb5-1.21.3/src/config/ren2long | 9 + krb5-1.21.3/src/config/ren2long.awk | 75 + krb5-1.21.3/src/config/rm.bat | 32 + krb5-1.21.3/src/config/shlib.conf | 552 + krb5-1.21.3/src/config/wconfig.pl | 77 + krb5-1.21.3/src/config/win-post.in | 128 + krb5-1.21.3/src/config/win-pre.in | 240 + krb5-1.21.3/src/configure | 16426 ++++++++ krb5-1.21.3/src/configure.ac | 1573 + krb5-1.21.3/src/deps | 1 + krb5-1.21.3/src/doc/Doxyfile.in | 15 + krb5-1.21.3/src/doc/Makefile.in | 135 + krb5-1.21.3/src/doc/deps | 1 + krb5-1.21.3/src/doc/version.py.in | 21 + krb5-1.21.3/src/include/CredentialsCache.h | 1529 + krb5-1.21.3/src/include/CredentialsCache2.h | 302 + krb5-1.21.3/src/include/Makefile.in | 160 + krb5-1.21.3/src/include/adm_proto.h | 91 + krb5-1.21.3/src/include/autoconf.h.in | 765 + krb5-1.21.3/src/include/copyright.h | 41 + krb5-1.21.3/src/include/deps | 1 + krb5-1.21.3/src/include/fake-addrinfo.h | 234 + krb5-1.21.3/src/include/foreachaddr.h | 66 + krb5-1.21.3/src/include/gssapi.h | 6 + krb5-1.21.3/src/include/gssrpc/auth.h | 205 + krb5-1.21.3/src/include/gssrpc/auth_gss.h | 148 + krb5-1.21.3/src/include/gssrpc/auth_gssapi.h | 162 + krb5-1.21.3/src/include/gssrpc/auth_unix.h | 82 + krb5-1.21.3/src/include/gssrpc/clnt.h | 346 + krb5-1.21.3/src/include/gssrpc/netdb.h | 58 + krb5-1.21.3/src/include/gssrpc/pmap_clnt.h | 83 + krb5-1.21.3/src/include/gssrpc/pmap_prot.h | 103 + krb5-1.21.3/src/include/gssrpc/pmap_rmt.h | 65 + krb5-1.21.3/src/include/gssrpc/rename.h | 280 + krb5-1.21.3/src/include/gssrpc/rpc.h | 77 + krb5-1.21.3/src/include/gssrpc/rpc_msg.h | 207 + krb5-1.21.3/src/include/gssrpc/svc.h | 336 + krb5-1.21.3/src/include/gssrpc/svc_auth.h | 119 + krb5-1.21.3/src/include/gssrpc/types.hin | 130 + krb5-1.21.3/src/include/gssrpc/xdr.h | 338 + krb5-1.21.3/src/include/iprop.h | 275 + krb5-1.21.3/src/include/iprop_hdr.h | 50 + krb5-1.21.3/src/include/k5-base64.h | 52 + krb5-1.21.3/src/include/k5-buf.h | 177 + krb5-1.21.3/src/include/k5-cmocka.h | 16 + krb5-1.21.3/src/include/k5-der.h | 149 + krb5-1.21.3/src/include/k5-err.h | 69 + krb5-1.21.3/src/include/k5-gmt_mktime.h | 43 + krb5-1.21.3/src/include/k5-hashtab.h | 82 + krb5-1.21.3/src/include/k5-hex.h | 53 + krb5-1.21.3/src/include/k5-input.h | 143 + krb5-1.21.3/src/include/k5-int-pkinit.h | 204 + krb5-1.21.3/src/include/k5-int.h | 2407 ++ krb5-1.21.3/src/include/k5-ipc_stream.h | 77 + krb5-1.21.3/src/include/k5-json.h | 218 + krb5-1.21.3/src/include/k5-platform.h | 1151 + krb5-1.21.3/src/include/k5-plugin.h | 121 + krb5-1.21.3/src/include/k5-queue.h | 637 + krb5-1.21.3/src/include/k5-spake.h | 107 + krb5-1.21.3/src/include/k5-thread.h | 443 + krb5-1.21.3/src/include/k5-tls.h | 104 + krb5-1.21.3/src/include/k5-trace.h | 523 + krb5-1.21.3/src/include/k5-unicode.h | 103 + krb5-1.21.3/src/include/k5-utf8.h | 120 + krb5-1.21.3/src/include/k5-util.h | 88 + krb5-1.21.3/src/include/kcm.h | 120 + krb5-1.21.3/src/include/kdb.h | 1457 + krb5-1.21.3/src/include/kdb_kt.h | 38 + krb5-1.21.3/src/include/kdb_log.h | 113 + krb5-1.21.3/src/include/krad.h | 265 + krb5-1.21.3/src/include/krb5.h | 8 + krb5-1.21.3/src/include/krb5/audit_plugin.h | 270 + .../src/include/krb5/authdata_plugin.h | 216 + .../src/include/krb5/ccselect_plugin.h | 105 + .../src/include/krb5/certauth_plugin.h | 148 + .../src/include/krb5/clpreauth_plugin.h | 346 + .../src/include/krb5/hostrealm_plugin.h | 135 + .../src/include/krb5/kadm5_auth_plugin.h | 306 + .../src/include/krb5/kadm5_hook_plugin.h | 154 + .../src/include/krb5/kdcauthdata_plugin.h | 129 + .../src/include/krb5/kdcpolicy_plugin.h | 128 + .../src/include/krb5/kdcpreauth_plugin.h | 417 + krb5-1.21.3/src/include/krb5/krb5.hin | 8590 +++++ .../src/include/krb5/localauth_plugin.h | 138 + krb5-1.21.3/src/include/krb5/locate_plugin.h | 62 + krb5-1.21.3/src/include/krb5/plugin.h | 46 + krb5-1.21.3/src/include/krb5/preauth_plugin.h | 41 + krb5-1.21.3/src/include/krb5/pwqual_plugin.h | 109 + krb5-1.21.3/src/include/net-server.h | 102 + krb5-1.21.3/src/include/osconf.hin | 141 + krb5-1.21.3/src/include/port-sockets.h | 297 + krb5-1.21.3/src/include/socket-utils.h | 146 + krb5-1.21.3/src/include/win-mac.h | 239 + krb5-1.21.3/src/kadmin/Makefile.in | 6 + krb5-1.21.3/src/kadmin/cli/Makefile.in | 39 + krb5-1.21.3/src/kadmin/cli/deps | 70 + krb5-1.21.3/src/kadmin/cli/getdate.y | 1047 + krb5-1.21.3/src/kadmin/cli/k5srvutil.sh | 123 + krb5-1.21.3/src/kadmin/cli/kadmin.c | 1999 + krb5-1.21.3/src/kadmin/cli/kadmin.h | 82 + krb5-1.21.3/src/kadmin/cli/kadmin_ct.ct | 100 + krb5-1.21.3/src/kadmin/cli/keytab.c | 505 + krb5-1.21.3/src/kadmin/cli/keytab_local.c | 10 + krb5-1.21.3/src/kadmin/cli/ss_wrapper.c | 77 + krb5-1.21.3/src/kadmin/dbutil/Makefile.in | 43 + krb5-1.21.3/src/kadmin/dbutil/deps | 206 + krb5-1.21.3/src/kadmin/dbutil/dump.c | 1650 + krb5-1.21.3/src/kadmin/dbutil/import_err.et | 22 + krb5-1.21.3/src/kadmin/dbutil/kadm5_create.c | 225 + krb5-1.21.3/src/kadmin/dbutil/kdb5_create.c | 478 + krb5-1.21.3/src/kadmin/dbutil/kdb5_destroy.c | 94 + krb5-1.21.3/src/kadmin/dbutil/kdb5_mkey.c | 1334 + krb5-1.21.3/src/kadmin/dbutil/kdb5_stash.c | 139 + krb5-1.21.3/src/kadmin/dbutil/kdb5_util.c | 611 + krb5-1.21.3/src/kadmin/dbutil/kdb5_util.h | 99 + krb5-1.21.3/src/kadmin/dbutil/nstrtok.h | 3 + krb5-1.21.3/src/kadmin/dbutil/ovload.c | 205 + krb5-1.21.3/src/kadmin/dbutil/strtok.c | 105 + krb5-1.21.3/src/kadmin/dbutil/t_tdumputil.c | 115 + krb5-1.21.3/src/kadmin/dbutil/t_tdumputil.py | 30 + krb5-1.21.3/src/kadmin/dbutil/tabdump.c | 658 + krb5-1.21.3/src/kadmin/dbutil/tdumputil.c | 266 + krb5-1.21.3/src/kadmin/dbutil/tdumputil.h | 51 + krb5-1.21.3/src/kadmin/deps | 1 + krb5-1.21.3/src/kadmin/kdbkeys/Makefile.in | 16 + krb5-1.21.3/src/kadmin/kdbkeys/do-test.pl | 56 + krb5-1.21.3/src/kadmin/ktutil/Makefile.in | 30 + krb5-1.21.3/src/kadmin/ktutil/deps | 27 + krb5-1.21.3/src/kadmin/ktutil/ktutil.c | 280 + krb5-1.21.3/src/kadmin/ktutil/ktutil.h | 67 + krb5-1.21.3/src/kadmin/ktutil/ktutil_ct.ct | 59 + krb5-1.21.3/src/kadmin/ktutil/ktutil_funcs.c | 371 + krb5-1.21.3/src/kadmin/scripts/inst-hdrs.sh | 14 + krb5-1.21.3/src/kadmin/server/Makefile.in | 24 + krb5-1.21.3/src/kadmin/server/auth.c | 314 + krb5-1.21.3/src/kadmin/server/auth.h | 85 + krb5-1.21.3/src/kadmin/server/auth_acl.c | 755 + krb5-1.21.3/src/kadmin/server/auth_self.c | 77 + krb5-1.21.3/src/kadmin/server/deps | 176 + krb5-1.21.3/src/kadmin/server/ipropd_svc.c | 619 + krb5-1.21.3/src/kadmin/server/kadm_rpc_svc.c | 363 + krb5-1.21.3/src/kadmin/server/misc.c | 175 + krb5-1.21.3/src/kadmin/server/misc.h | 54 + krb5-1.21.3/src/kadmin/server/ovsec_kadmd.c | 562 + krb5-1.21.3/src/kadmin/server/schpw.c | 469 + krb5-1.21.3/src/kadmin/server/server_stubs.c | 1649 + krb5-1.21.3/src/kdc/Makefile.in | 101 + krb5-1.21.3/src/kdc/authind.c | 123 + krb5-1.21.3/src/kdc/cammac.c | 175 + krb5-1.21.3/src/kdc/deps | 310 + krb5-1.21.3/src/kdc/dispatch.c | 217 + krb5-1.21.3/src/kdc/do_as_req.c | 849 + krb5-1.21.3/src/kdc/do_tgs_req.c | 1229 + krb5-1.21.3/src/kdc/extern.c | 43 + krb5-1.21.3/src/kdc/extern.h | 36 + krb5-1.21.3/src/kdc/fast_util.c | 721 + krb5-1.21.3/src/kdc/kdc5_err.et | 35 + krb5-1.21.3/src/kdc/kdc_audit.c | 332 + krb5-1.21.3/src/kdc/kdc_audit.h | 82 + krb5-1.21.3/src/kdc/kdc_authdata.c | 628 + krb5-1.21.3/src/kdc/kdc_log.c | 235 + krb5-1.21.3/src/kdc/kdc_preauth.c | 1663 + krb5-1.21.3/src/kdc/kdc_preauth_ec.c | 225 + krb5-1.21.3/src/kdc/kdc_preauth_encts.c | 138 + krb5-1.21.3/src/kdc/kdc_transit.c | 414 + krb5-1.21.3/src/kdc/kdc_util.c | 1916 + krb5-1.21.3/src/kdc/kdc_util.h | 562 + krb5-1.21.3/src/kdc/main.c | 1056 + krb5-1.21.3/src/kdc/ndr.c | 331 + krb5-1.21.3/src/kdc/policy.c | 246 + krb5-1.21.3/src/kdc/policy.h | 47 + krb5-1.21.3/src/kdc/realm_data.h | 88 + krb5-1.21.3/src/kdc/replay.c | 231 + krb5-1.21.3/src/kdc/reqstate.h | 54 + krb5-1.21.3/src/kdc/rtest.c | 117 + krb5-1.21.3/src/kdc/rtest.good | 26 + krb5-1.21.3/src/kdc/rtscript | 55 + krb5-1.21.3/src/kdc/t_bigreply.py | 32 + krb5-1.21.3/src/kdc/t_emptytgt.py | 6 + krb5-1.21.3/src/kdc/t_ndr.c | 188 + krb5-1.21.3/src/kdc/t_replay.c | 619 + krb5-1.21.3/src/kdc/t_workers.py | 7 + krb5-1.21.3/src/kdc/tgs_policy.c | 771 + krb5-1.21.3/src/kprop/Makefile.in | 35 + krb5-1.21.3/src/kprop/deps | 74 + krb5-1.21.3/src/kprop/kprop.c | 594 + krb5-1.21.3/src/kprop/kprop.h | 55 + krb5-1.21.3/src/kprop/kprop_util.c | 136 + krb5-1.21.3/src/kprop/kpropd.c | 1620 + krb5-1.21.3/src/kprop/kpropd_rpc.c | 61 + krb5-1.21.3/src/kprop/kproplog.c | 561 + krb5-1.21.3/src/kprop/replica_update | 30 + krb5-1.21.3/src/lib/Makefile.in | 145 + krb5-1.21.3/src/lib/apputils/Makefile.in | 33 + krb5-1.21.3/src/lib/apputils/daemon.c | 96 + krb5-1.21.3/src/lib/apputils/deps | 43 + krb5-1.21.3/src/lib/apputils/net-server.c | 1522 + krb5-1.21.3/src/lib/apputils/udppktinfo.c | 526 + krb5-1.21.3/src/lib/apputils/udppktinfo.h | 58 + krb5-1.21.3/src/lib/comerr32.def | 12 + krb5-1.21.3/src/lib/crypto/ISSUES | 14 + krb5-1.21.3/src/lib/crypto/Makefile.in | 48 + .../src/lib/crypto/builtin/Makefile.in | 48 + .../src/lib/crypto/builtin/aes/Makefile.in | 66 + .../src/lib/crypto/builtin/aes/aes-gen.c | 352 + krb5-1.21.3/src/lib/crypto/builtin/aes/aes.h | 289 + .../src/lib/crypto/builtin/aes/aes.txt | 622 + .../src/lib/crypto/builtin/aes/aescrypt.c | 306 + .../src/lib/crypto/builtin/aes/aeskey.c | 578 + .../src/lib/crypto/builtin/aes/aesopt.h | 786 + .../src/lib/crypto/builtin/aes/aestab.c | 429 + .../src/lib/crypto/builtin/aes/aestab.h | 173 + .../src/lib/crypto/builtin/aes/brg_endian.h | 144 + .../src/lib/crypto/builtin/aes/brg_types.h | 217 + krb5-1.21.3/src/lib/crypto/builtin/aes/deps | 37 + .../src/lib/crypto/builtin/aes/iaesx64.s | 799 + .../src/lib/crypto/builtin/aes/iaesx86.s | 842 + .../lib/crypto/builtin/aes/kresults.expected | 223 + .../lib/crypto/builtin/camellia/Makefile.in | 43 + .../crypto/builtin/camellia/camellia-gen.c | 333 + .../lib/crypto/builtin/camellia/camellia.c | 1544 + .../lib/crypto/builtin/camellia/camellia.h | 125 + .../src/lib/crypto/builtin/camellia/deps | 14 + krb5-1.21.3/src/lib/crypto/builtin/cmac.c | 204 + krb5-1.21.3/src/lib/crypto/builtin/deps | 47 + krb5-1.21.3/src/lib/crypto/builtin/des/ISSUES | 13 + .../src/lib/crypto/builtin/des/Makefile.in | 82 + .../src/lib/crypto/builtin/des/d3_aead.c | 137 + .../src/lib/crypto/builtin/des/d3_kysched.c | 55 + krb5-1.21.3/src/lib/crypto/builtin/des/deps | 146 + .../src/lib/crypto/builtin/des/des_int.h | 285 + .../src/lib/crypto/builtin/des/des_keys.c | 38 + .../src/lib/crypto/builtin/des/destest.c | 240 + .../src/lib/crypto/builtin/des/doc/libdes.doc | 208 + .../src/lib/crypto/builtin/des/f_aead.c | 177 + .../src/lib/crypto/builtin/des/f_cbc.c | 256 + .../src/lib/crypto/builtin/des/f_cksum.c | 141 + .../src/lib/crypto/builtin/des/f_parity.c | 64 + .../src/lib/crypto/builtin/des/f_sched.c | 363 + .../src/lib/crypto/builtin/des/f_tables.c | 375 + .../src/lib/crypto/builtin/des/f_tables.h | 285 + .../src/lib/crypto/builtin/des/key_sched.c | 66 + .../src/lib/crypto/builtin/des/keytest.data | 171 + .../src/lib/crypto/builtin/des/t_verify.c | 395 + .../src/lib/crypto/builtin/des/weak_key.c | 90 + .../crypto/builtin/enc_provider/Makefile.in | 39 + .../src/lib/crypto/builtin/enc_provider/aes.c | 412 + .../crypto/builtin/enc_provider/camellia.c | 319 + .../src/lib/crypto/builtin/enc_provider/deps | 49 + .../lib/crypto/builtin/enc_provider/des3.c | 109 + .../src/lib/crypto/builtin/enc_provider/rc4.c | 194 + .../crypto/builtin/hash_provider/Makefile.in | 38 + .../src/lib/crypto/builtin/hash_provider/deps | 51 + .../crypto/builtin/hash_provider/hash_md4.c | 65 + .../crypto/builtin/hash_provider/hash_md5.c | 65 + .../crypto/builtin/hash_provider/hash_sha1.c | 66 + .../crypto/builtin/hash_provider/hash_sha2.c | 92 + krb5-1.21.3/src/lib/crypto/builtin/hmac.c | 124 + krb5-1.21.3/src/lib/crypto/builtin/kdf.c | 190 + krb5-1.21.3/src/lib/crypto/builtin/md4/ISSUES | 4 + .../src/lib/crypto/builtin/md4/Makefile.in | 33 + krb5-1.21.3/src/lib/crypto/builtin/md4/deps | 14 + krb5-1.21.3/src/lib/crypto/builtin/md4/md4.c | 247 + .../src/lib/crypto/builtin/md4/rsa-md4.h | 90 + krb5-1.21.3/src/lib/crypto/builtin/md5/ISSUES | 4 + .../src/lib/crypto/builtin/md5/Makefile.in | 32 + krb5-1.21.3/src/lib/crypto/builtin/md5/deps | 14 + krb5-1.21.3/src/lib/crypto/builtin/md5/md5.c | 346 + .../src/lib/crypto/builtin/md5/rsa-md5.h | 59 + krb5-1.21.3/src/lib/crypto/builtin/pbkdf2.c | 221 + .../src/lib/crypto/builtin/sha1/ISSUES | 8 + .../src/lib/crypto/builtin/sha1/Makefile.in | 47 + krb5-1.21.3/src/lib/crypto/builtin/sha1/deps | 14 + krb5-1.21.3/src/lib/crypto/builtin/sha1/shs.c | 386 + krb5-1.21.3/src/lib/crypto/builtin/sha1/shs.h | 46 + .../src/lib/crypto/builtin/sha1/t_shs.c | 121 + .../src/lib/crypto/builtin/sha1/t_shs3.c | 594 + .../src/lib/crypto/builtin/sha2/Makefile.in | 26 + krb5-1.21.3/src/lib/crypto/builtin/sha2/deps | 25 + .../src/lib/crypto/builtin/sha2/sha2.h | 78 + .../src/lib/crypto/builtin/sha2/sha256.c | 273 + .../src/lib/crypto/builtin/sha2/sha512.c | 308 + .../src/lib/crypto/crypto_tests/Makefile.in | 147 + .../src/lib/crypto/crypto_tests/Poly.pm | 182 + .../src/lib/crypto/crypto_tests/aes-test.c | 144 + .../crypto_tests/camellia-expect-vt.txt | 1036 + .../lib/crypto/crypto_tests/camellia-test.c | 141 + krb5-1.21.3/src/lib/crypto/crypto_tests/deps | 206 + .../src/lib/crypto/crypto_tests/expect-vk.txt | 1548 + .../src/lib/crypto/crypto_tests/expect-vt.txt | 1036 + .../src/lib/crypto/crypto_tests/t_cf2.c | 98 + .../lib/crypto/crypto_tests/t_cf2.comments | 6 + .../lib/crypto/crypto_tests/t_cf2.expected | 6 + .../src/lib/crypto/crypto_tests/t_cf2.in | 30 + .../src/lib/crypto/crypto_tests/t_cksums.c | 260 + .../src/lib/crypto/crypto_tests/t_cmac.c | 147 + .../src/lib/crypto/crypto_tests/t_cts.c | 151 + .../src/lib/crypto/crypto_tests/t_decrypt.c | 623 + .../src/lib/crypto/crypto_tests/t_derive.c | 375 + .../src/lib/crypto/crypto_tests/t_encrypt.c | 289 + .../src/lib/crypto/crypto_tests/t_fork.c | 117 + .../src/lib/crypto/crypto_tests/t_hmac.c | 263 + .../src/lib/crypto/crypto_tests/t_kperf.c | 123 + .../src/lib/crypto/crypto_tests/t_mdcksum.c | 203 + .../src/lib/crypto/crypto_tests/t_mddriver.c | 256 + .../src/lib/crypto/crypto_tests/t_nfold.c | 160 + .../src/lib/crypto/crypto_tests/t_pkcs5.c | 99 + .../src/lib/crypto/crypto_tests/t_prf.c | 149 + .../lib/crypto/crypto_tests/t_prng.comments | 14 + .../lib/crypto/crypto_tests/t_prng.expected | 4 + .../src/lib/crypto/crypto_tests/t_prng.seed | 25 + .../src/lib/crypto/crypto_tests/t_sha2.c | 145 + .../src/lib/crypto/crypto_tests/t_short.c | 130 + .../src/lib/crypto/crypto_tests/t_str2key.c | 514 + .../lib/crypto/crypto_tests/test/Readme.txt | 22 + .../lib/crypto/crypto_tests/test/cbc_d_m.txt | 7224 ++++ .../lib/crypto/crypto_tests/test/cbc_e_m.txt | 7224 ++++ .../lib/crypto/crypto_tests/test/ecb_d_m.txt | 6024 +++ .../lib/crypto/crypto_tests/test/ecb_e_m.txt | 6024 +++ .../crypto/crypto_tests/test/ecb_iv.readme | 19 + .../lib/crypto/crypto_tests/test/ecb_iv.txt | 123 + .../lib/crypto/crypto_tests/test/ecb_tbl.txt | 1955 + .../lib/crypto/crypto_tests/test/ecb_vk.txt | 2334 ++ .../lib/crypto/crypto_tests/test/ecb_vt.txt | 1566 + .../lib/crypto/crypto_tests/test/katmct.pdf | Bin 0 -> 100812 bytes .../src/lib/crypto/crypto_tests/vb.txt | 87 + .../src/lib/crypto/crypto_tests/vectors.c | 454 + krb5-1.21.3/src/lib/crypto/deps | 1 + krb5-1.21.3/src/lib/crypto/krb/Makefile.in | 188 + krb5-1.21.3/src/lib/crypto/krb/aead.c | 223 + krb5-1.21.3/src/lib/crypto/krb/block_size.c | 42 + krb5-1.21.3/src/lib/crypto/krb/cf2.c | 176 + .../src/lib/crypto/krb/checksum_dk_cmac.c | 59 + .../src/lib/crypto/krb/checksum_dk_hmac.c | 59 + krb5-1.21.3/src/lib/crypto/krb/checksum_etm.c | 65 + .../src/lib/crypto/krb/checksum_hmac_md5.c | 94 + .../src/lib/crypto/krb/checksum_length.c | 42 + .../src/lib/crypto/krb/checksum_unkeyed.c | 36 + .../src/lib/crypto/krb/cksumtype_to_string.c | 42 + krb5-1.21.3/src/lib/crypto/krb/cksumtypes.c | 112 + .../src/lib/crypto/krb/coll_proof_cksum.c | 37 + krb5-1.21.3/src/lib/crypto/krb/crypto_int.h | 674 + .../src/lib/crypto/krb/crypto_length.c | 125 + krb5-1.21.3/src/lib/crypto/krb/decrypt.c | 101 + krb5-1.21.3/src/lib/crypto/krb/decrypt_iov.c | 64 + .../src/lib/crypto/krb/default_state.c | 50 + krb5-1.21.3/src/lib/crypto/krb/deps | 580 + krb5-1.21.3/src/lib/crypto/krb/derive.c | 174 + krb5-1.21.3/src/lib/crypto/krb/enc_dk_cmac.c | 182 + krb5-1.21.3/src/lib/crypto/krb/enc_dk_hmac.c | 269 + krb5-1.21.3/src/lib/crypto/krb/enc_etm.c | 257 + krb5-1.21.3/src/lib/crypto/krb/enc_raw.c | 109 + krb5-1.21.3/src/lib/crypto/krb/enc_rc4.c | 347 + krb5-1.21.3/src/lib/crypto/krb/encrypt.c | 94 + krb5-1.21.3/src/lib/crypto/krb/encrypt_iov.c | 58 + .../src/lib/crypto/krb/encrypt_length.c | 47 + krb5-1.21.3/src/lib/crypto/krb/enctype_util.c | 176 + krb5-1.21.3/src/lib/crypto/krb/etypes.c | 152 + krb5-1.21.3/src/lib/crypto/krb/key.c | 110 + krb5-1.21.3/src/lib/crypto/krb/keyblocks.c | 108 + .../src/lib/crypto/krb/keyed_checksum_types.c | 82 + krb5-1.21.3/src/lib/crypto/krb/keyed_cksum.c | 39 + krb5-1.21.3/src/lib/crypto/krb/keylengths.c | 57 + .../src/lib/crypto/krb/make_checksum.c | 99 + .../src/lib/crypto/krb/make_checksum_iov.c | 94 + .../src/lib/crypto/krb/make_random_key.c | 76 + .../src/lib/crypto/krb/mandatory_sumtype.c | 39 + krb5-1.21.3/src/lib/crypto/krb/nfold.c | 117 + krb5-1.21.3/src/lib/crypto/krb/old_api_glue.c | 390 + krb5-1.21.3/src/lib/crypto/krb/prf.c | 84 + krb5-1.21.3/src/lib/crypto/krb/prf_aes2.c | 42 + krb5-1.21.3/src/lib/crypto/krb/prf_cmac.c | 58 + krb5-1.21.3/src/lib/crypto/krb/prf_des.c | 47 + krb5-1.21.3/src/lib/crypto/krb/prf_dk.c | 70 + krb5-1.21.3/src/lib/crypto/krb/prf_rc4.c | 39 + krb5-1.21.3/src/lib/crypto/krb/prng.c | 153 + .../src/lib/crypto/krb/random_to_key.c | 101 + krb5-1.21.3/src/lib/crypto/krb/s2k_pbkdf2.c | 216 + krb5-1.21.3/src/lib/crypto/krb/s2k_rc4.c | 41 + krb5-1.21.3/src/lib/crypto/krb/state.c | 60 + .../src/lib/crypto/krb/string_to_cksumtype.c | 56 + .../src/lib/crypto/krb/string_to_key.c | 79 + .../src/lib/crypto/krb/valid_cksumtype.c | 39 + .../src/lib/crypto/krb/verify_checksum.c | 98 + .../src/lib/crypto/krb/verify_checksum_iov.c | 101 + .../src/lib/crypto/libk5crypto.exports | 105 + .../src/lib/crypto/openssl/Makefile.in | 44 + krb5-1.21.3/src/lib/crypto/openssl/cmac.c | 93 + krb5-1.21.3/src/lib/crypto/openssl/deps | 58 + .../src/lib/crypto/openssl/des/Makefile.in | 20 + krb5-1.21.3/src/lib/crypto/openssl/des/deps | 14 + .../src/lib/crypto/openssl/des/des_keys.c | 39 + .../crypto/openssl/enc_provider/Makefile.in | 31 + .../src/lib/crypto/openssl/enc_provider/aes.c | 398 + .../crypto/openssl/enc_provider/camellia.c | 448 + .../src/lib/crypto/openssl/enc_provider/deps | 47 + .../lib/crypto/openssl/enc_provider/des3.c | 188 + .../src/lib/crypto/openssl/enc_provider/rc4.c | 170 + .../crypto/openssl/hash_provider/Makefile.in | 20 + .../src/lib/crypto/openssl/hash_provider/deps | 14 + .../crypto/openssl/hash_provider/hash_evp.c | 133 + krb5-1.21.3/src/lib/crypto/openssl/hmac.c | 231 + krb5-1.21.3/src/lib/crypto/openssl/kdf.c | 237 + krb5-1.21.3/src/lib/crypto/openssl/pbkdf2.c | 59 + krb5-1.21.3/src/lib/crypto/openssl/sha256.c | 64 + krb5-1.21.3/src/lib/deps | 1 + krb5-1.21.3/src/lib/gssapi/LICENSE | 91 + krb5-1.21.3/src/lib/gssapi/Makefile.in | 104 + krb5-1.21.3/src/lib/gssapi/README_SAMPLE_APP | 4 + krb5-1.21.3/src/lib/gssapi/deps | 1 + .../src/lib/gssapi/generic/Makefile.in | 172 + krb5-1.21.3/src/lib/gssapi/generic/deps | 97 + .../lib/gssapi/generic/disp_com_err_status.c | 62 + .../lib/gssapi/generic/disp_major_status.c | 301 + krb5-1.21.3/src/lib/gssapi/generic/gssapi.hin | 920 + .../src/lib/gssapi/generic/gssapiP_generic.h | 298 + .../src/lib/gssapi/generic/gssapi_alloc.h | 131 + .../lib/gssapi/generic/gssapi_err_generic.et | 49 + .../src/lib/gssapi/generic/gssapi_ext.h | 650 + .../src/lib/gssapi/generic/gssapi_generic.c | 488 + .../src/lib/gssapi/generic/gssapi_generic.h | 59 + krb5-1.21.3/src/lib/gssapi/generic/maptest.c | 68 + krb5-1.21.3/src/lib/gssapi/generic/oid_ops.c | 553 + .../src/lib/gssapi/generic/rel_buffer.c | 57 + .../src/lib/gssapi/generic/rel_oid_set.c | 61 + .../src/lib/gssapi/generic/t_seqstate.c | 197 + .../src/lib/gssapi/generic/util_buffer.c | 48 + .../src/lib/gssapi/generic/util_buffer_set.c | 126 + .../src/lib/gssapi/generic/util_errmap.c | 264 + .../src/lib/gssapi/generic/util_seqstate.c | 163 + krb5-1.21.3/src/lib/gssapi/generic/util_set.c | 91 + .../src/lib/gssapi/generic/util_token.c | 108 + krb5-1.21.3/src/lib/gssapi/krb5/Makefile.in | 259 + .../src/lib/gssapi/krb5/accept_sec_context.c | 1346 + .../src/lib/gssapi/krb5/acquire_cred.c | 1369 + krb5-1.21.3/src/lib/gssapi/krb5/canon_name.c | 44 + .../src/lib/gssapi/krb5/compare_name.c | 52 + .../src/lib/gssapi/krb5/context_time.c | 58 + krb5-1.21.3/src/lib/gssapi/krb5/copy_ccache.c | 45 + krb5-1.21.3/src/lib/gssapi/krb5/cred_store.c | 50 + .../src/lib/gssapi/krb5/delete_sec_context.c | 99 + krb5-1.21.3/src/lib/gssapi/krb5/deps | 759 + krb5-1.21.3/src/lib/gssapi/krb5/disp_name.c | 81 + krb5-1.21.3/src/lib/gssapi/krb5/disp_status.c | 200 + .../src/lib/gssapi/krb5/duplicate_name.c | 57 + krb5-1.21.3/src/lib/gssapi/krb5/export_cred.c | 477 + krb5-1.21.3/src/lib/gssapi/krb5/export_name.c | 88 + .../src/lib/gssapi/krb5/export_sec_context.c | 96 + .../src/lib/gssapi/krb5/get_tkt_flags.c | 45 + .../src/lib/gssapi/krb5/gssapiP_krb5.h | 1456 + .../src/lib/gssapi/krb5/gssapi_err_krb5.et | 42 + krb5-1.21.3/src/lib/gssapi/krb5/gssapi_krb5.c | 1132 + krb5-1.21.3/src/lib/gssapi/krb5/gssapi_krb5.h | 305 + krb5-1.21.3/src/lib/gssapi/krb5/iakerb.c | 1310 + krb5-1.21.3/src/lib/gssapi/krb5/import_cred.c | 644 + krb5-1.21.3/src/lib/gssapi/krb5/import_name.c | 346 + .../src/lib/gssapi/krb5/import_sec_context.c | 95 + .../src/lib/gssapi/krb5/indicate_mechs.c | 37 + .../src/lib/gssapi/krb5/init_sec_context.c | 1088 + krb5-1.21.3/src/lib/gssapi/krb5/inq_context.c | 373 + krb5-1.21.3/src/lib/gssapi/krb5/inq_cred.c | 288 + krb5-1.21.3/src/lib/gssapi/krb5/inq_names.c | 100 + krb5-1.21.3/src/lib/gssapi/krb5/k5seal.c | 392 + krb5-1.21.3/src/lib/gssapi/krb5/k5sealiov.c | 542 + krb5-1.21.3/src/lib/gssapi/krb5/k5sealv3.c | 522 + krb5-1.21.3/src/lib/gssapi/krb5/k5sealv3iov.c | 468 + krb5-1.21.3/src/lib/gssapi/krb5/k5unseal.c | 476 + krb5-1.21.3/src/lib/gssapi/krb5/k5unsealiov.c | 712 + .../src/lib/gssapi/krb5/krb5_gss_glue.c | 445 + .../src/lib/gssapi/krb5/lucid_context.c | 292 + krb5-1.21.3/src/lib/gssapi/krb5/naming_exts.c | 666 + krb5-1.21.3/src/lib/gssapi/krb5/prf.c | 139 + .../lib/gssapi/krb5/process_context_token.c | 66 + krb5-1.21.3/src/lib/gssapi/krb5/rel_cred.c | 98 + krb5-1.21.3/src/lib/gssapi/krb5/rel_name.c | 47 + krb5-1.21.3/src/lib/gssapi/krb5/rel_oid.c | 78 + .../src/lib/gssapi/krb5/s4u_gss_glue.c | 303 + krb5-1.21.3/src/lib/gssapi/krb5/ser_sctx.c | 698 + .../lib/gssapi/krb5/set_allowable_enctypes.c | 122 + krb5-1.21.3/src/lib/gssapi/krb5/set_ccache.c | 87 + krb5-1.21.3/src/lib/gssapi/krb5/store_cred.c | 223 + krb5-1.21.3/src/lib/gssapi/krb5/util_cksum.c | 270 + krb5-1.21.3/src/lib/gssapi/krb5/util_crypt.c | 738 + krb5-1.21.3/src/lib/gssapi/krb5/util_seed.c | 61 + krb5-1.21.3/src/lib/gssapi/krb5/util_seqnum.c | 102 + krb5-1.21.3/src/lib/gssapi/krb5/val_cred.c | 83 + .../src/lib/gssapi/krb5/wrap_size_limit.c | 178 + .../src/lib/gssapi/libgssapi_krb5.exports | 169 + .../src/lib/gssapi/mechglue/Makefile.in | 228 + krb5-1.21.3/src/lib/gssapi/mechglue/deps | 521 + .../gssapi/mechglue/g_accept_sec_context.c | 407 + .../src/lib/gssapi/mechglue/g_acquire_cred.c | 633 + .../gssapi/mechglue/g_acquire_cred_imp_name.c | 529 + .../gssapi/mechglue/g_acquire_cred_with_pw.c | 524 + .../gssapi/mechglue/g_authorize_localname.c | 226 + .../src/lib/gssapi/mechglue/g_buffer_set.c | 55 + .../src/lib/gssapi/mechglue/g_canon_name.c | 176 + .../src/lib/gssapi/mechglue/g_compare_name.c | 210 + .../gssapi/mechglue/g_complete_auth_token.c | 77 + .../src/lib/gssapi/mechglue/g_context_time.c | 81 + .../lib/gssapi/mechglue/g_decapsulate_token.c | 66 + .../src/lib/gssapi/mechglue/g_del_name_attr.c | 65 + .../gssapi/mechglue/g_delete_sec_context.c | 106 + .../src/lib/gssapi/mechglue/g_dsp_name.c | 118 + .../src/lib/gssapi/mechglue/g_dsp_name_ext.c | 133 + .../src/lib/gssapi/mechglue/g_dsp_status.c | 363 + .../src/lib/gssapi/mechglue/g_dup_name.c | 144 + .../lib/gssapi/mechglue/g_encapsulate_token.c | 65 + .../lib/gssapi/mechglue/g_exp_sec_context.c | 146 + .../src/lib/gssapi/mechglue/g_export_cred.c | 111 + .../src/lib/gssapi/mechglue/g_export_name.c | 58 + .../lib/gssapi/mechglue/g_export_name_comp.c | 78 + .../src/lib/gssapi/mechglue/g_get_name_attr.c | 93 + krb5-1.21.3/src/lib/gssapi/mechglue/g_glue.c | 562 + .../src/lib/gssapi/mechglue/g_imp_cred.c | 177 + .../src/lib/gssapi/mechglue/g_imp_name.c | 333 + .../lib/gssapi/mechglue/g_imp_sec_context.c | 161 + .../lib/gssapi/mechglue/g_init_sec_context.c | 252 + .../src/lib/gssapi/mechglue/g_initialize.c | 1623 + .../src/lib/gssapi/mechglue/g_inq_context.c | 170 + .../lib/gssapi/mechglue/g_inq_context_oid.c | 74 + .../src/lib/gssapi/mechglue/g_inq_cred.c | 230 + .../src/lib/gssapi/mechglue/g_inq_cred_oid.c | 134 + .../src/lib/gssapi/mechglue/g_inq_name.c | 99 + .../src/lib/gssapi/mechglue/g_inq_names.c | 168 + .../lib/gssapi/mechglue/g_map_name_to_any.c | 77 + .../src/lib/gssapi/mechglue/g_mech_invoke.c | 72 + .../src/lib/gssapi/mechglue/g_mechattr.c | 222 + .../src/lib/gssapi/mechglue/g_mechname.c | 116 + .../src/lib/gssapi/mechglue/g_negoex.c | 237 + .../src/lib/gssapi/mechglue/g_oid_ops.c | 112 + krb5-1.21.3/src/lib/gssapi/mechglue/g_prf.c | 91 + .../lib/gssapi/mechglue/g_process_context.c | 84 + .../src/lib/gssapi/mechglue/g_rel_buffer.c | 58 + .../src/lib/gssapi/mechglue/g_rel_cred.c | 99 + .../src/lib/gssapi/mechglue/g_rel_name.c | 86 + .../lib/gssapi/mechglue/g_rel_name_mapping.c | 73 + .../src/lib/gssapi/mechglue/g_rel_oid_set.c | 43 + .../src/lib/gssapi/mechglue/g_saslname.c | 220 + krb5-1.21.3/src/lib/gssapi/mechglue/g_seal.c | 253 + .../gssapi/mechglue/g_set_context_option.c | 93 + .../lib/gssapi/mechglue/g_set_cred_option.c | 197 + .../src/lib/gssapi/mechglue/g_set_name_attr.c | 69 + .../src/lib/gssapi/mechglue/g_set_neg_mechs.c | 72 + krb5-1.21.3/src/lib/gssapi/mechglue/g_sign.c | 136 + .../src/lib/gssapi/mechglue/g_store_cred.c | 266 + .../src/lib/gssapi/mechglue/g_unseal.c | 132 + .../src/lib/gssapi/mechglue/g_unwrap_aead.c | 199 + .../src/lib/gssapi/mechglue/g_unwrap_iov.c | 145 + .../src/lib/gssapi/mechglue/g_verify.c | 108 + .../src/lib/gssapi/mechglue/g_wrap_aead.c | 269 + .../src/lib/gssapi/mechglue/g_wrap_iov.c | 269 + .../lib/gssapi/mechglue/gssd_pname_to_uid.c | 226 + .../src/lib/gssapi/mechglue/mechglue.h | 42 + krb5-1.21.3/src/lib/gssapi/mechglue/mglueP.h | 864 + krb5-1.21.3/src/lib/gssapi/spnego/Makefile.in | 25 + krb5-1.21.3/src/lib/gssapi/spnego/deps | 51 + .../src/lib/gssapi/spnego/gssapiP_negoex.h | 210 + .../src/lib/gssapi/spnego/gssapiP_spnego.h | 698 + .../src/lib/gssapi/spnego/mech_spnego.exports | 1 + .../src/lib/gssapi/spnego/negoex_ctx.c | 788 + .../src/lib/gssapi/spnego/negoex_trace.c | 121 + .../src/lib/gssapi/spnego/negoex_util.c | 813 + .../src/lib/gssapi/spnego/spnego_mech.c | 3824 ++ krb5-1.21.3/src/lib/gssapi32.def | 191 + krb5-1.21.3/src/lib/kadm5/Makefile.in | 113 + krb5-1.21.3/src/lib/kadm5/admin.h | 500 + krb5-1.21.3/src/lib/kadm5/admin_internal.h | 80 + krb5-1.21.3/src/lib/kadm5/admin_xdr.h | 73 + krb5-1.21.3/src/lib/kadm5/alt_prof.c | 799 + krb5-1.21.3/src/lib/kadm5/chpass_util.c | 240 + .../src/lib/kadm5/chpass_util_strings.et | 58 + krb5-1.21.3/src/lib/kadm5/clnt/Makefile.in | 79 + .../src/lib/kadm5/clnt/client_handle.c | 10 + krb5-1.21.3/src/lib/kadm5/clnt/client_init.c | 727 + .../src/lib/kadm5/clnt/client_internal.h | 100 + .../src/lib/kadm5/clnt/client_principal.c | 528 + krb5-1.21.3/src/lib/kadm5/clnt/client_rpc.c | 213 + .../src/lib/kadm5/clnt/clnt_chpass_util.c | 17 + krb5-1.21.3/src/lib/kadm5/clnt/clnt_policy.c | 130 + krb5-1.21.3/src/lib/kadm5/clnt/clnt_privs.c | 28 + krb5-1.21.3/src/lib/kadm5/clnt/deps | 84 + .../lib/kadm5/clnt/libkadm5clnt_mit.exports | 115 + krb5-1.21.3/src/lib/kadm5/deps | 111 + krb5-1.21.3/src/lib/kadm5/kadm_err.et | 70 + krb5-1.21.3/src/lib/kadm5/kadm_rpc.h | 408 + krb5-1.21.3/src/lib/kadm5/kadm_rpc_xdr.c | 1206 + krb5-1.21.3/src/lib/kadm5/logger.c | 791 + krb5-1.21.3/src/lib/kadm5/misc_free.c | 139 + krb5-1.21.3/src/lib/kadm5/server_internal.h | 269 + krb5-1.21.3/src/lib/kadm5/srv/Makefile.in | 93 + krb5-1.21.3/src/lib/kadm5/srv/adb_xdr.c | 106 + krb5-1.21.3/src/lib/kadm5/srv/deps | 258 + krb5-1.21.3/src/lib/kadm5/srv/kadm5_hook.c | 186 + .../src/lib/kadm5/srv/libkadm5srv_mit.exports | 134 + krb5-1.21.3/src/lib/kadm5/srv/pwqual.c | 127 + krb5-1.21.3/src/lib/kadm5/srv/pwqual_dict.c | 257 + krb5-1.21.3/src/lib/kadm5/srv/pwqual_empty.c | 60 + krb5-1.21.3/src/lib/kadm5/srv/pwqual_hesiod.c | 134 + krb5-1.21.3/src/lib/kadm5/srv/pwqual_princ.c | 74 + krb5-1.21.3/src/lib/kadm5/srv/server_handle.c | 10 + krb5-1.21.3/src/lib/kadm5/srv/server_init.c | 362 + krb5-1.21.3/src/lib/kadm5/srv/server_kdb.c | 449 + krb5-1.21.3/src/lib/kadm5/srv/server_misc.c | 158 + .../src/lib/kadm5/srv/svr_chpass_util.c | 17 + krb5-1.21.3/src/lib/kadm5/srv/svr_iters.c | 270 + krb5-1.21.3/src/lib/kadm5/srv/svr_policy.c | 427 + krb5-1.21.3/src/lib/kadm5/srv/svr_principal.c | 2058 + krb5-1.21.3/src/lib/kadm5/str_conv.c | 403 + krb5-1.21.3/src/lib/kadm5/t_kadm5.c | 1326 + krb5-1.21.3/src/lib/kadm5/t_kadm5.py | 45 + krb5-1.21.3/src/lib/kdb/Makefile.in | 84 + krb5-1.21.3/src/lib/kdb/adb_err.et | 16 + krb5-1.21.3/src/lib/kdb/decrypt_key.c | 135 + krb5-1.21.3/src/lib/kdb/deps | 158 + krb5-1.21.3/src/lib/kdb/encrypt_key.c | 114 + krb5-1.21.3/src/lib/kdb/iprop.x | 243 + krb5-1.21.3/src/lib/kdb/iprop_xdr.c | 344 + krb5-1.21.3/src/lib/kdb/kdb5.c | 2781 ++ krb5-1.21.3/src/lib/kdb/kdb5.h | 38 + krb5-1.21.3/src/lib/kdb/kdb5int.h | 40 + krb5-1.21.3/src/lib/kdb/kdb_convert.c | 918 + krb5-1.21.3/src/lib/kdb/kdb_cpw.c | 462 + krb5-1.21.3/src/lib/kdb/kdb_default.c | 551 + krb5-1.21.3/src/lib/kdb/kdb_log.c | 688 + krb5-1.21.3/src/lib/kdb/keytab.c | 229 + krb5-1.21.3/src/lib/kdb/libkdb5.exports | 108 + krb5-1.21.3/src/lib/kdb/t_sort_key_data.c | 96 + krb5-1.21.3/src/lib/kdb/t_stringattr.c | 95 + krb5-1.21.3/src/lib/kdb/t_stringattr.py | 5 + krb5-1.21.3/src/lib/kdb/t_ulog.c | 88 + krb5-1.21.3/src/lib/krad/Makefile.in | 73 + krb5-1.21.3/src/lib/krad/attr.c | 317 + krb5-1.21.3/src/lib/krad/attrset.c | 244 + krb5-1.21.3/src/lib/krad/client.c | 321 + krb5-1.21.3/src/lib/krad/code.c | 111 + krb5-1.21.3/src/lib/krad/deps | 156 + krb5-1.21.3/src/lib/krad/internal.h | 159 + krb5-1.21.3/src/lib/krad/libkrad.exports | 23 + krb5-1.21.3/src/lib/krad/packet.c | 470 + krb5-1.21.3/src/lib/krad/remote.c | 541 + krb5-1.21.3/src/lib/krad/t_attr.c | 89 + krb5-1.21.3/src/lib/krad/t_attrset.c | 98 + krb5-1.21.3/src/lib/krad/t_client.c | 126 + krb5-1.21.3/src/lib/krad/t_code.c | 54 + krb5-1.21.3/src/lib/krad/t_daemon.h | 85 + krb5-1.21.3/src/lib/krad/t_daemon.py | 71 + krb5-1.21.3/src/lib/krad/t_packet.c | 207 + krb5-1.21.3/src/lib/krad/t_remote.c | 170 + krb5-1.21.3/src/lib/krad/t_test.c | 50 + krb5-1.21.3/src/lib/krad/t_test.h | 60 + krb5-1.21.3/src/lib/krb5.rc | 44 + krb5-1.21.3/src/lib/krb5/Makefile.in | 65 + krb5-1.21.3/src/lib/krb5/asn.1/KRB5-asn.py | 436 + krb5-1.21.3/src/lib/krb5/asn.1/Makefile.in | 32 + krb5-1.21.3/src/lib/krb5/asn.1/README.asn1 | 572 + krb5-1.21.3/src/lib/krb5/asn.1/TODO.asn1 | 75 + krb5-1.21.3/src/lib/krb5/asn.1/asn1_encode.c | 1585 + krb5-1.21.3/src/lib/krb5/asn.1/asn1_encode.h | 577 + .../src/lib/krb5/asn.1/asn1_k_encode.c | 1759 + krb5-1.21.3/src/lib/krb5/asn.1/deps | 38 + krb5-1.21.3/src/lib/krb5/asn.1/krbasn1.h | 56 + krb5-1.21.3/src/lib/krb5/asn.1/ldap_key_seq.c | 124 + krb5-1.21.3/src/lib/krb5/ccache/Makefile.in | 166 + krb5-1.21.3/src/lib/krb5/ccache/cc-int.h | 229 + .../src/lib/krb5/ccache/cc_api_macos.c | 727 + krb5-1.21.3/src/lib/krb5/ccache/cc_dir.c | 771 + krb5-1.21.3/src/lib/krb5/ccache/cc_file.c | 1479 + krb5-1.21.3/src/lib/krb5/ccache/cc_kcm.c | 1366 + krb5-1.21.3/src/lib/krb5/ccache/cc_keyring.c | 1749 + krb5-1.21.3/src/lib/krb5/ccache/cc_memory.c | 830 + krb5-1.21.3/src/lib/krb5/ccache/cc_mslsa.c | 2212 ++ krb5-1.21.3/src/lib/krb5/ccache/cc_retr.c | 276 + .../src/lib/krb5/ccache/ccapi/Makefile.in | 25 + krb5-1.21.3/src/lib/krb5/ccache/ccapi/deps | 14 + krb5-1.21.3/src/lib/krb5/ccache/ccapi/stdcc.c | 1020 + krb5-1.21.3/src/lib/krb5/ccache/ccapi/stdcc.h | 108 + .../src/lib/krb5/ccache/ccapi/winccld.c | 101 + .../src/lib/krb5/ccache/ccapi/winccld.h | 47 + krb5-1.21.3/src/lib/krb5/ccache/ccapi_util.c | 425 + krb5-1.21.3/src/lib/krb5/ccache/ccapi_util.h | 50 + krb5-1.21.3/src/lib/krb5/ccache/ccbase.c | 638 + krb5-1.21.3/src/lib/krb5/ccache/cccopy.c | 37 + krb5-1.21.3/src/lib/krb5/ccache/cccursor.c | 282 + krb5-1.21.3/src/lib/krb5/ccache/ccdefault.c | 97 + krb5-1.21.3/src/lib/krb5/ccache/ccdefops.c | 58 + krb5-1.21.3/src/lib/krb5/ccache/ccfns.c | 320 + krb5-1.21.3/src/lib/krb5/ccache/ccmarshal.c | 570 + krb5-1.21.3/src/lib/krb5/ccache/ccselect.c | 204 + .../src/lib/krb5/ccache/ccselect_hostname.c | 146 + .../src/lib/krb5/ccache/ccselect_k5identity.c | 210 + .../src/lib/krb5/ccache/ccselect_realm.c | 95 + krb5-1.21.3/src/lib/krb5/ccache/deps | 249 + krb5-1.21.3/src/lib/krb5/ccache/fcc.h | 41 + krb5-1.21.3/src/lib/krb5/ccache/kcmrpc.defs | 56 + .../src/lib/krb5/ccache/kcmrpc_types.h | 39 + krb5-1.21.3/src/lib/krb5/ccache/scc.h | 88 + krb5-1.21.3/src/lib/krb5/ccache/t_cc.c | 660 + krb5-1.21.3/src/lib/krb5/ccache/t_cccol.c | 363 + krb5-1.21.3/src/lib/krb5/ccache/t_cccol.py | 125 + krb5-1.21.3/src/lib/krb5/ccache/t_cccursor.c | 81 + krb5-1.21.3/src/lib/krb5/ccache/t_marshal.c | 420 + krb5-1.21.3/src/lib/krb5/ccache/t_memory.c | 138 + krb5-1.21.3/src/lib/krb5/ccache/t_stdio.c | 168 + krb5-1.21.3/src/lib/krb5/deps | 16 + .../src/lib/krb5/error_tables/Makefile.in | 63 + .../src/lib/krb5/error_tables/asn1_err.et | 16 + krb5-1.21.3/src/lib/krb5/error_tables/deps | 15 + .../src/lib/krb5/error_tables/init_ets.c | 48 + .../src/lib/krb5/error_tables/k5e1_err.et | 47 + .../src/lib/krb5/error_tables/kdb5_err.et | 89 + .../src/lib/krb5/error_tables/krb524_err.et | 34 + .../src/lib/krb5/error_tables/krb5_err.et | 356 + .../src/lib/krb5/error_tables/kv5m_err.et | 93 + krb5-1.21.3/src/lib/krb5/keytab/Makefile.in | 69 + krb5-1.21.3/src/lib/krb5/keytab/deps | 113 + krb5-1.21.3/src/lib/krb5/keytab/kt-int.h | 47 + krb5-1.21.3/src/lib/krb5/keytab/kt_file.c | 1382 + krb5-1.21.3/src/lib/krb5/keytab/kt_memory.c | 637 + krb5-1.21.3/src/lib/krb5/keytab/ktadd.c | 39 + krb5-1.21.3/src/lib/krb5/keytab/ktbase.c | 221 + krb5-1.21.3/src/lib/krb5/keytab/ktdefault.c | 62 + krb5-1.21.3/src/lib/krb5/keytab/ktfns.c | 214 + krb5-1.21.3/src/lib/krb5/keytab/ktfr_entry.c | 50 + krb5-1.21.3/src/lib/krb5/keytab/ktremove.c | 39 + krb5-1.21.3/src/lib/krb5/keytab/read_servi.c | 84 + krb5-1.21.3/src/lib/krb5/keytab/t_keytab.c | 445 + krb5-1.21.3/src/lib/krb5/krb/Makefile.in | 550 + krb5-1.21.3/src/lib/krb5/krb/addr_comp.c | 45 + krb5-1.21.3/src/lib/krb5/krb/addr_order.c | 60 + krb5-1.21.3/src/lib/krb5/krb/addr_srch.c | 65 + krb5-1.21.3/src/lib/krb5/krb/ai_authdata.c | 341 + krb5-1.21.3/src/lib/krb5/krb/allow_weak.c | 34 + krb5-1.21.3/src/lib/krb5/krb/appdefault.c | 169 + krb5-1.21.3/src/lib/krb5/krb/auth_con.c | 445 + krb5-1.21.3/src/lib/krb5/krb/auth_con.h | 42 + krb5-1.21.3/src/lib/krb5/krb/authdata.c | 1286 + krb5-1.21.3/src/lib/krb5/krb/authdata.h | 104 + krb5-1.21.3/src/lib/krb5/krb/authdata_dec.c | 296 + krb5-1.21.3/src/lib/krb5/krb/authdata_enc.c | 146 + krb5-1.21.3/src/lib/krb5/krb/authdata_exp.c | 95 + krb5-1.21.3/src/lib/krb5/krb/bld_pr_ext.c | 98 + krb5-1.21.3/src/lib/krb5/krb/bld_princ.c | 182 + krb5-1.21.3/src/lib/krb5/krb/brand.c | 72 + krb5-1.21.3/src/lib/krb5/krb/cammac_util.c | 86 + krb5-1.21.3/src/lib/krb5/krb/chk_trans.c | 438 + krb5-1.21.3/src/lib/krb5/krb/chpw.c | 510 + krb5-1.21.3/src/lib/krb5/krb/conv_creds.c | 61 + krb5-1.21.3/src/lib/krb5/krb/conv_princ.c | 361 + krb5-1.21.3/src/lib/krb5/krb/copy_addrs.c | 77 + krb5-1.21.3/src/lib/krb5/krb/copy_athctr.c | 88 + krb5-1.21.3/src/lib/krb5/krb/copy_auth.c | 117 + krb5-1.21.3/src/lib/krb5/krb/copy_cksum.c | 46 + krb5-1.21.3/src/lib/krb5/krb/copy_creds.c | 114 + krb5-1.21.3/src/lib/krb5/krb/copy_ctx.c | 123 + krb5-1.21.3/src/lib/krb5/krb/copy_data.c | 98 + krb5-1.21.3/src/lib/krb5/krb/copy_key.c | 35 + krb5-1.21.3/src/lib/krb5/krb/copy_princ.c | 74 + krb5-1.21.3/src/lib/krb5/krb/copy_tick.c | 122 + krb5-1.21.3/src/lib/krb5/krb/cp_key_cnt.c | 36 + krb5-1.21.3/src/lib/krb5/krb/decode_kdc.c | 86 + krb5-1.21.3/src/lib/krb5/krb/decrypt_tk.c | 71 + krb5-1.21.3/src/lib/krb5/krb/deltat.c | 1697 + krb5-1.21.3/src/lib/krb5/krb/deps | 1452 + krb5-1.21.3/src/lib/krb5/krb/enc_helper.c | 53 + krb5-1.21.3/src/lib/krb5/krb/enc_keyhelper.c | 56 + krb5-1.21.3/src/lib/krb5/krb/encode_kdc.c | 125 + krb5-1.21.3/src/lib/krb5/krb/encrypt_tk.c | 65 + krb5-1.21.3/src/lib/krb5/krb/etype_list.c | 70 + krb5-1.21.3/src/lib/krb5/krb/fast.c | 689 + krb5-1.21.3/src/lib/krb5/krb/fast.h | 114 + krb5-1.21.3/src/lib/krb5/krb/fwd_tgt.c | 186 + krb5-1.21.3/src/lib/krb5/krb/gc_via_tkt.c | 420 + .../src/lib/krb5/krb/gen_save_subkey.c | 56 + krb5-1.21.3/src/lib/krb5/krb/gen_seqnum.c | 63 + krb5-1.21.3/src/lib/krb5/krb/gen_subkey.c | 58 + krb5-1.21.3/src/lib/krb5/krb/get_creds.c | 1353 + krb5-1.21.3/src/lib/krb5/krb/get_etype_info.c | 180 + krb5-1.21.3/src/lib/krb5/krb/get_in_tkt.c | 2095 ++ krb5-1.21.3/src/lib/krb5/krb/gic_keytab.c | 395 + krb5-1.21.3/src/lib/krb5/krb/gic_opt.c | 500 + krb5-1.21.3/src/lib/krb5/krb/gic_pwd.c | 473 + krb5-1.21.3/src/lib/krb5/krb/in_tkt_sky.c | 120 + krb5-1.21.3/src/lib/krb5/krb/init_creds_ctx.h | 92 + krb5-1.21.3/src/lib/krb5/krb/init_ctx.c | 596 + krb5-1.21.3/src/lib/krb5/krb/init_keyblock.c | 35 + krb5-1.21.3/src/lib/krb5/krb/int-proto.h | 401 + krb5-1.21.3/src/lib/krb5/krb/kdc_rep_dc.c | 77 + krb5-1.21.3/src/lib/krb5/krb/kerrs.c | 252 + krb5-1.21.3/src/lib/krb5/krb/kfree.c | 916 + krb5-1.21.3/src/lib/krb5/krb/libdef_parse.c | 152 + krb5-1.21.3/src/lib/krb5/krb/mk_cred.c | 231 + krb5-1.21.3/src/lib/krb5/krb/mk_error.c | 49 + krb5-1.21.3/src/lib/krb5/krb/mk_priv.c | 155 + krb5-1.21.3/src/lib/krb5/krb/mk_rep.c | 152 + krb5-1.21.3/src/lib/krb5/krb/mk_req.c | 89 + krb5-1.21.3/src/lib/krb5/krb/mk_req_ext.c | 400 + krb5-1.21.3/src/lib/krb5/krb/mk_safe.c | 174 + krb5-1.21.3/src/lib/krb5/krb/pac.c | 1279 + krb5-1.21.3/src/lib/krb5/krb/pac_sign.c | 425 + krb5-1.21.3/src/lib/krb5/krb/padata.c | 127 + krb5-1.21.3/src/lib/krb5/krb/parse.c | 238 + .../src/lib/krb5/krb/parse_host_string.c | 124 + krb5-1.21.3/src/lib/krb5/krb/plugin.c | 511 + krb5-1.21.3/src/lib/krb5/krb/pr_to_salt.c | 82 + krb5-1.21.3/src/lib/krb5/krb/preauth2.c | 1068 + krb5-1.21.3/src/lib/krb5/krb/preauth_ec.c | 169 + krb5-1.21.3/src/lib/krb5/krb/preauth_encts.c | 151 + krb5-1.21.3/src/lib/krb5/krb/preauth_otp.c | 1265 + krb5-1.21.3/src/lib/krb5/krb/preauth_pkinit.c | 204 + krb5-1.21.3/src/lib/krb5/krb/preauth_sam2.c | 397 + krb5-1.21.3/src/lib/krb5/krb/princ_comp.c | 167 + krb5-1.21.3/src/lib/krb5/krb/privsafe.c | 382 + krb5-1.21.3/src/lib/krb5/krb/random_str.c | 68 + krb5-1.21.3/src/lib/krb5/krb/rd_cred.c | 204 + krb5-1.21.3/src/lib/krb5/krb/rd_error.c | 44 + krb5-1.21.3/src/lib/krb5/krb/rd_priv.c | 150 + krb5-1.21.3/src/lib/krb5/krb/rd_rep.c | 204 + krb5-1.21.3/src/lib/krb5/krb/rd_req.c | 109 + krb5-1.21.3/src/lib/krb5/krb/rd_req_dec.c | 976 + krb5-1.21.3/src/lib/krb5/krb/rd_safe.c | 178 + krb5-1.21.3/src/lib/krb5/krb/recvauth.c | 240 + krb5-1.21.3/src/lib/krb5/krb/response_items.c | 224 + krb5-1.21.3/src/lib/krb5/krb/s4u_creds.c | 1263 + krb5-1.21.3/src/lib/krb5/krb/send_tgs.c | 300 + krb5-1.21.3/src/lib/krb5/krb/sendauth.c | 206 + krb5-1.21.3/src/lib/krb5/krb/ser_actx.c | 397 + krb5-1.21.3/src/lib/krb5/krb/ser_adata.c | 153 + krb5-1.21.3/src/lib/krb5/krb/ser_addr.c | 157 + krb5-1.21.3/src/lib/krb5/krb/ser_auth.c | 262 + krb5-1.21.3/src/lib/krb5/krb/ser_cksum.c | 155 + krb5-1.21.3/src/lib/krb5/krb/ser_ctx.c | 433 + krb5-1.21.3/src/lib/krb5/krb/ser_key.c | 148 + krb5-1.21.3/src/lib/krb5/krb/ser_princ.c | 138 + krb5-1.21.3/src/lib/krb5/krb/serialize.c | 125 + krb5-1.21.3/src/lib/krb5/krb/set_realm.c | 48 + krb5-1.21.3/src/lib/krb5/krb/sname_match.c | 70 + krb5-1.21.3/src/lib/krb5/krb/srv_dec_tkt.c | 140 + krb5-1.21.3/src/lib/krb5/krb/srv_rcache.c | 41 + krb5-1.21.3/src/lib/krb5/krb/str_conv.c | 319 + krb5-1.21.3/src/lib/krb5/krb/strptime.c | 386 + krb5-1.21.3/src/lib/krb5/krb/t_ad_fx_armor.c | 37 + krb5-1.21.3/src/lib/krb5/krb/t_authdata.c | 113 + krb5-1.21.3/src/lib/krb5/krb/t_cc_config.c | 163 + krb5-1.21.3/src/lib/krb5/krb/t_copy_context.c | 157 + krb5-1.21.3/src/lib/krb5/krb/t_deltat.c | 157 + krb5-1.21.3/src/lib/krb5/krb/t_etypes.c | 230 + krb5-1.21.3/src/lib/krb5/krb/t_expand.c | 3 + krb5-1.21.3/src/lib/krb5/krb/t_expire_warn.c | 106 + krb5-1.21.3/src/lib/krb5/krb/t_expire_warn.py | 68 + .../src/lib/krb5/krb/t_get_etype_info.c | 110 + .../src/lib/krb5/krb/t_get_etype_info.py | 56 + krb5-1.21.3/src/lib/krb5/krb/t_in_ccache.c | 149 + .../src/lib/krb5/krb/t_in_ccache_patypes.py | 84 + krb5-1.21.3/src/lib/krb5/krb/t_kerb.c | 248 + krb5-1.21.3/src/lib/krb5/krb/t_krb5.conf | 53 + krb5-1.21.3/src/lib/krb5/krb/t_pac.c | 1151 + .../src/lib/krb5/krb/t_parse_host_string.c | 247 + krb5-1.21.3/src/lib/krb5/krb/t_princ.c | 404 + krb5-1.21.3/src/lib/krb5/krb/t_ref_kerb.out | 23 + .../src/lib/krb5/krb/t_response_items.c | 94 + krb5-1.21.3/src/lib/krb5/krb/t_ser.c | 347 + krb5-1.21.3/src/lib/krb5/krb/t_sname_match.c | 117 + krb5-1.21.3/src/lib/krb5/krb/t_valid_times.c | 111 + krb5-1.21.3/src/lib/krb5/krb/t_vfy_increds.c | 84 + krb5-1.21.3/src/lib/krb5/krb/t_vfy_increds.py | 107 + krb5-1.21.3/src/lib/krb5/krb/t_walk_rtree.c | 58 + krb5-1.21.3/src/lib/krb5/krb/tgtname.c | 37 + krb5-1.21.3/src/lib/krb5/krb/transit-tests | 56 + krb5-1.21.3/src/lib/krb5/krb/unparse.c | 251 + krb5-1.21.3/src/lib/krb5/krb/val_renew.c | 197 + krb5-1.21.3/src/lib/krb5/krb/valid_times.c | 57 + krb5-1.21.3/src/lib/krb5/krb/vfy_increds.c | 321 + krb5-1.21.3/src/lib/krb5/krb/vic_opt.c | 15 + krb5-1.21.3/src/lib/krb5/krb/walk_rtree.c | 626 + krb5-1.21.3/src/lib/krb5/krb/walktree-tests | 81 + krb5-1.21.3/src/lib/krb5/krb/x-deltat.y | 240 + krb5-1.21.3/src/lib/krb5/krb5_libinit.c | 106 + krb5-1.21.3/src/lib/krb5/krb5_libinit.h | 10 + krb5-1.21.3/src/lib/krb5/libkrb5.exports | 655 + krb5-1.21.3/src/lib/krb5/os/Makefile.in | 267 + krb5-1.21.3/src/lib/krb5/os/accessor.c | 111 + krb5-1.21.3/src/lib/krb5/os/c_ustime.c | 129 + krb5-1.21.3/src/lib/krb5/os/ccdefname.c | 320 + krb5-1.21.3/src/lib/krb5/os/changepw.c | 379 + krb5-1.21.3/src/lib/krb5/os/deps | 570 + krb5-1.21.3/src/lib/krb5/os/dnsglue.c | 513 + krb5-1.21.3/src/lib/krb5/os/dnsglue.h | 156 + krb5-1.21.3/src/lib/krb5/os/dnssrv.c | 327 + krb5-1.21.3/src/lib/krb5/os/expand_path.c | 544 + krb5-1.21.3/src/lib/krb5/os/full_ipadr.c | 83 + krb5-1.21.3/src/lib/krb5/os/gen_port.c | 46 + krb5-1.21.3/src/lib/krb5/os/gen_rname.c | 53 + krb5-1.21.3/src/lib/krb5/os/genaddrs.c | 125 + krb5-1.21.3/src/lib/krb5/os/hostaddr.c | 128 + krb5-1.21.3/src/lib/krb5/os/hostrealm.c | 547 + krb5-1.21.3/src/lib/krb5/os/hostrealm_dns.c | 143 + .../src/lib/krb5/os/hostrealm_domain.c | 128 + .../src/lib/krb5/os/hostrealm_profile.c | 117 + .../src/lib/krb5/os/hostrealm_registry.c | 135 + krb5-1.21.3/src/lib/krb5/os/init_os_ctx.c | 519 + krb5-1.21.3/src/lib/krb5/os/krbfileio.c | 99 + krb5-1.21.3/src/lib/krb5/os/ktdefname.c | 94 + krb5-1.21.3/src/lib/krb5/os/localaddr.c | 1542 + krb5-1.21.3/src/lib/krb5/os/localauth.c | 443 + krb5-1.21.3/src/lib/krb5/os/localauth_an2ln.c | 59 + .../src/lib/krb5/os/localauth_k5login.c | 183 + krb5-1.21.3/src/lib/krb5/os/localauth_names.c | 102 + krb5-1.21.3/src/lib/krb5/os/localauth_rule.c | 335 + krb5-1.21.3/src/lib/krb5/os/locate_kdc.c | 852 + krb5-1.21.3/src/lib/krb5/os/lock_file.c | 182 + krb5-1.21.3/src/lib/krb5/os/mk_faddr.c | 82 + krb5-1.21.3/src/lib/krb5/os/net_read.c | 64 + krb5-1.21.3/src/lib/krb5/os/net_write.c | 81 + krb5-1.21.3/src/lib/krb5/os/os-proto.h | 255 + krb5-1.21.3/src/lib/krb5/os/port2ip.c | 81 + krb5-1.21.3/src/lib/krb5/os/prompter.c | 331 + krb5-1.21.3/src/lib/krb5/os/read_msg.c | 62 + krb5-1.21.3/src/lib/krb5/os/read_pwd.c | 295 + krb5-1.21.3/src/lib/krb5/os/realm_dom.c | 61 + krb5-1.21.3/src/lib/krb5/os/ref_std_conf.out | 11 + krb5-1.21.3/src/lib/krb5/os/sendto_kdc.c | 1613 + krb5-1.21.3/src/lib/krb5/os/sn2princ.c | 380 + krb5-1.21.3/src/lib/krb5/os/t_an_to_ln.c | 42 + krb5-1.21.3/src/lib/krb5/os/t_discover_uri.py | 46 + krb5-1.21.3/src/lib/krb5/os/t_expand_path.c | 18 + krb5-1.21.3/src/lib/krb5/os/t_gifconf.c | 137 + krb5-1.21.3/src/lib/krb5/os/t_kuserok.c | 54 + krb5-1.21.3/src/lib/krb5/os/t_locate_kdc.c | 143 + krb5-1.21.3/src/lib/krb5/os/t_std_conf.c | 224 + krb5-1.21.3/src/lib/krb5/os/t_trace.c | 245 + krb5-1.21.3/src/lib/krb5/os/t_trace.ref | 48 + krb5-1.21.3/src/lib/krb5/os/td_krb5.conf | 19 + krb5-1.21.3/src/lib/krb5/os/thread_safe.c | 37 + krb5-1.21.3/src/lib/krb5/os/timeofday.c | 67 + krb5-1.21.3/src/lib/krb5/os/toffset.c | 119 + krb5-1.21.3/src/lib/krb5/os/trace.c | 489 + krb5-1.21.3/src/lib/krb5/os/unlck_file.c | 34 + krb5-1.21.3/src/lib/krb5/os/ustime.c | 82 + krb5-1.21.3/src/lib/krb5/os/write_msg.c | 76 + krb5-1.21.3/src/lib/krb5/posix/Makefile.in | 15 + krb5-1.21.3/src/lib/krb5/posix/syslog.c | 11 + krb5-1.21.3/src/lib/krb5/rcache/Makefile.in | 52 + krb5-1.21.3/src/lib/krb5/rcache/RELEASE | 17 + krb5-1.21.3/src/lib/krb5/rcache/deps | 81 + krb5-1.21.3/src/lib/krb5/rcache/memrcache.c | 165 + krb5-1.21.3/src/lib/krb5/rcache/memrcache.h | 46 + krb5-1.21.3/src/lib/krb5/rcache/rc-int.h | 57 + krb5-1.21.3/src/lib/krb5/rcache/rc_base.c | 200 + krb5-1.21.3/src/lib/krb5/rcache/rc_dfl.c | 164 + krb5-1.21.3/src/lib/krb5/rcache/rc_file2.c | 266 + krb5-1.21.3/src/lib/krb5/rcache/rc_none.c | 58 + krb5-1.21.3/src/lib/krb5/rcache/t_memrcache.c | 82 + krb5-1.21.3/src/lib/krb5/rcache/t_rcfile2.c | 209 + .../krb5/unicode/CompositionExclusions.txt | 176 + krb5-1.21.3/src/lib/krb5/unicode/Makefile.in | 65 + krb5-1.21.3/src/lib/krb5/unicode/UCD-Terms | 29 + .../src/lib/krb5/unicode/UnicodeData.txt | 13874 +++++++ krb5-1.21.3/src/lib/krb5/unicode/deps | 15 + .../lib/krb5/unicode/ucdata/MUTTUCData.txt | 303 + .../src/lib/krb5/unicode/ucdata/README | 313 + .../src/lib/krb5/unicode/ucdata/api.txt | 401 + .../src/lib/krb5/unicode/ucdata/format.txt | 267 + .../src/lib/krb5/unicode/ucdata/ucdata.c | 1497 + .../src/lib/krb5/unicode/ucdata/ucdata.h | 354 + .../src/lib/krb5/unicode/ucdata/ucdata.man | 504 + .../src/lib/krb5/unicode/ucdata/ucgendat.c | 1945 + .../src/lib/krb5/unicode/ucdata/uctable.h | 14305 +++++++ krb5-1.21.3/src/lib/krb5/unicode/ucstr.c | 233 + krb5-1.21.3/src/lib/krb5_32.def | 512 + krb5-1.21.3/src/lib/rpc/Makefile.in | 235 + krb5-1.21.3/src/lib/rpc/auth_gss.c | 627 + krb5-1.21.3/src/lib/rpc/auth_gssapi.c | 812 + krb5-1.21.3/src/lib/rpc/auth_gssapi_misc.c | 339 + krb5-1.21.3/src/lib/rpc/auth_none.c | 147 + krb5-1.21.3/src/lib/rpc/auth_unix.c | 329 + krb5-1.21.3/src/lib/rpc/authgss_prot.c | 366 + krb5-1.21.3/src/lib/rpc/authunix_prot.c | 65 + krb5-1.21.3/src/lib/rpc/bindresvport.c | 92 + krb5-1.21.3/src/lib/rpc/clnt_generic.c | 110 + krb5-1.21.3/src/lib/rpc/clnt_perror.c | 350 + krb5-1.21.3/src/lib/rpc/clnt_raw.c | 272 + krb5-1.21.3/src/lib/rpc/clnt_simple.c | 131 + krb5-1.21.3/src/lib/rpc/clnt_tcp.c | 509 + krb5-1.21.3/src/lib/rpc/clnt_udp.c | 488 + krb5-1.21.3/src/lib/rpc/deps | 329 + krb5-1.21.3/src/lib/rpc/dyn.c | 555 + krb5-1.21.3/src/lib/rpc/dyn.h | 79 + krb5-1.21.3/src/lib/rpc/dynP.h | 50 + krb5-1.21.3/src/lib/rpc/dyntest.c | 216 + krb5-1.21.3/src/lib/rpc/get_myaddress.c | 120 + krb5-1.21.3/src/lib/rpc/getrpcent.c | 236 + krb5-1.21.3/src/lib/rpc/getrpcport.c | 60 + krb5-1.21.3/src/lib/rpc/gssrpcint.h | 35 + krb5-1.21.3/src/lib/rpc/libgssrpc.exports | 144 + krb5-1.21.3/src/lib/rpc/pmap_clnt.c | 169 + krb5-1.21.3/src/lib/rpc/pmap_getmaps.c | 89 + krb5-1.21.3/src/lib/rpc/pmap_getport.c | 94 + krb5-1.21.3/src/lib/rpc/pmap_prot.c | 57 + krb5-1.21.3/src/lib/rpc/pmap_prot2.c | 116 + krb5-1.21.3/src/lib/rpc/pmap_rmt.c | 414 + krb5-1.21.3/src/lib/rpc/rpc_callmsg.c | 194 + krb5-1.21.3/src/lib/rpc/rpc_commondata.c | 51 + krb5-1.21.3/src/lib/rpc/rpc_dtablesize.c | 66 + krb5-1.21.3/src/lib/rpc/rpc_prot.c | 295 + krb5-1.21.3/src/lib/rpc/svc.c | 536 + krb5-1.21.3/src/lib/rpc/svc_auth.c | 106 + krb5-1.21.3/src/lib/rpc/svc_auth_gss.c | 684 + krb5-1.21.3/src/lib/rpc/svc_auth_gssapi.c | 1132 + krb5-1.21.3/src/lib/rpc/svc_auth_none.c | 74 + krb5-1.21.3/src/lib/rpc/svc_auth_unix.c | 142 + krb5-1.21.3/src/lib/rpc/svc_raw.c | 163 + krb5-1.21.3/src/lib/rpc/svc_run.c | 74 + krb5-1.21.3/src/lib/rpc/svc_simple.c | 150 + krb5-1.21.3/src/lib/rpc/svc_tcp.c | 532 + krb5-1.21.3/src/lib/rpc/svc_udp.c | 545 + krb5-1.21.3/src/lib/rpc/unit-test/Makefile.in | 38 + krb5-1.21.3/src/lib/rpc/unit-test/client.c | 278 + krb5-1.21.3/src/lib/rpc/unit-test/deps | 37 + krb5-1.21.3/src/lib/rpc/unit-test/rpc_test.h | 13 + krb5-1.21.3/src/lib/rpc/unit-test/rpc_test.x | 30 + .../src/lib/rpc/unit-test/rpc_test_clnt.c | 22 + .../src/lib/rpc/unit-test/rpc_test_svc.c | 67 + krb5-1.21.3/src/lib/rpc/unit-test/server.c | 266 + krb5-1.21.3/src/lib/rpc/unit-test/t_rpc.py | 29 + krb5-1.21.3/src/lib/rpc/xdr.c | 677 + krb5-1.21.3/src/lib/rpc/xdr_alloc.c | 150 + krb5-1.21.3/src/lib/rpc/xdr_array.c | 159 + krb5-1.21.3/src/lib/rpc/xdr_float.c | 291 + krb5-1.21.3/src/lib/rpc/xdr_mem.c | 184 + krb5-1.21.3/src/lib/rpc/xdr_rec.c | 571 + krb5-1.21.3/src/lib/rpc/xdr_reference.c | 139 + krb5-1.21.3/src/lib/rpc/xdr_sizeof.c | 165 + krb5-1.21.3/src/lib/rpc/xdr_stdio.c | 172 + krb5-1.21.3/src/lib/win_glue.c | 460 + krb5-1.21.3/src/lib/xpprof32.def | 28 + krb5-1.21.3/src/man/Makefile.in | 152 + krb5-1.21.3/src/man/README | 3 + krb5-1.21.3/src/man/deps | 1 + krb5-1.21.3/src/man/dot.k5identity.5 | 1 + krb5-1.21.3/src/man/dot.k5login.5 | 1 + krb5-1.21.3/src/man/k5identity.man | 103 + krb5-1.21.3/src/man/k5login.man | 96 + krb5-1.21.3/src/man/k5srvutil.man | 95 + krb5-1.21.3/src/man/kadm5.acl.man | 279 + krb5-1.21.3/src/man/kadmin.local.8 | 1 + krb5-1.21.3/src/man/kadmin.man | 1099 + krb5-1.21.3/src/man/kadmind.man | 153 + krb5-1.21.3/src/man/kdb5_ldap_util.man | 527 + krb5-1.21.3/src/man/kdb5_util.man | 559 + krb5-1.21.3/src/man/kdc.conf.man | 1195 + krb5-1.21.3/src/man/kdestroy.man | 95 + krb5-1.21.3/src/man/kerberos.man | 217 + krb5-1.21.3/src/man/kinit.man | 259 + krb5-1.21.3/src/man/klist.man | 158 + krb5-1.21.3/src/man/kpasswd.man | 68 + krb5-1.21.3/src/man/kprop.man | 82 + krb5-1.21.3/src/man/kpropd.man | 171 + krb5-1.21.3/src/man/kproplog.man | 115 + krb5-1.21.3/src/man/krb5-config.man | 141 + krb5-1.21.3/src/man/krb5.conf.man | 1505 + krb5-1.21.3/src/man/krb5kdc.man | 140 + krb5-1.21.3/src/man/ksu.man | 479 + krb5-1.21.3/src/man/kswitch.man | 71 + krb5-1.21.3/src/man/ktutil.man | 164 + krb5-1.21.3/src/man/kvno.man | 141 + krb5-1.21.3/src/man/sclient.man | 54 + krb5-1.21.3/src/man/sserver.man | 198 + krb5-1.21.3/src/patchlevel.h | 57 + krb5-1.21.3/src/plugins/audit/Makefile.in | 22 + krb5-1.21.3/src/plugins/audit/deps | 15 + krb5-1.21.3/src/plugins/audit/j_dict.h | 88 + krb5-1.21.3/src/plugins/audit/kdc_j_encode.c | 930 + krb5-1.21.3/src/plugins/audit/kdc_j_encode.h | 66 + .../src/plugins/audit/libauditjenc.exports | 7 + .../src/plugins/audit/simple/Makefile.in | 27 + .../src/plugins/audit/simple/au_simple_main.c | 263 + krb5-1.21.3/src/plugins/audit/simple/deps | 15 + .../src/plugins/audit/simple/k5audit.exports | 1 + .../src/plugins/audit/test/Makefile.in | 21 + krb5-1.21.3/src/plugins/audit/test/au_test.c | 227 + krb5-1.21.3/src/plugins/audit/test/deps | 14 + .../plugins/audit/test/k5audit_test.exports | 1 + .../plugins/authdata/greet_client/Makefile.in | 20 + .../src/plugins/authdata/greet_client/deps | 13 + .../src/plugins/authdata/greet_client/greet.c | 377 + .../greet_client/greet_client.exports | 1 + .../plugins/authdata/greet_server/Makefile.in | 21 + .../src/plugins/authdata/greet_server/deps | 15 + .../authdata/greet_server/greet_auth.c | 140 + .../greet_server/greet_server.exports | 1 + .../src/plugins/certauth/test/Makefile.in | 20 + .../certauth/test/certauth_test.exports | 3 + krb5-1.21.3/src/plugins/certauth/test/deps | 14 + krb5-1.21.3/src/plugins/certauth/test/main.c | 278 + .../src/plugins/gssapi/negoextest/Makefile.in | 20 + .../src/plugins/gssapi/negoextest/deps | 15 + .../gssapi/negoextest/gss_negoextest.exports | 13 + .../src/plugins/gssapi/negoextest/main.c | 358 + .../src/plugins/hostrealm/test/Makefile.in | 21 + krb5-1.21.3/src/plugins/hostrealm/test/deps | 14 + .../hostrealm/test/hostrealm_test.exports | 2 + krb5-1.21.3/src/plugins/hostrealm/test/main.c | 197 + .../src/plugins/kadm5_auth/test/Makefile.in | 20 + krb5-1.21.3/src/plugins/kadm5_auth/test/deps | 22 + .../kadm5_auth/test/kadm5_auth_test.exports | 2 + .../src/plugins/kadm5_auth/test/main.c | 305 + .../src/plugins/kadm5_hook/test/Makefile.in | 23 + krb5-1.21.3/src/plugins/kadm5_hook/test/deps | 14 + .../kadm5_hook/test/kadm5_hook_test.exports | 1 + .../src/plugins/kadm5_hook/test/main.c | 109 + krb5-1.21.3/src/plugins/kdb/db2/Makefile.in | 83 + .../src/plugins/kdb/db2/adb_openclose.c | 355 + krb5-1.21.3/src/plugins/kdb/db2/adb_policy.c | 383 + krb5-1.21.3/src/plugins/kdb/db2/db2.exports | 1 + krb5-1.21.3/src/plugins/kdb/db2/db2_exp.c | 235 + krb5-1.21.3/src/plugins/kdb/db2/deps | 105 + krb5-1.21.3/src/plugins/kdb/db2/kdb_db2.c | 1560 + krb5-1.21.3/src/plugins/kdb/db2/kdb_db2.h | 143 + krb5-1.21.3/src/plugins/kdb/db2/kdb_xdr.c | 442 + krb5-1.21.3/src/plugins/kdb/db2/kdb_xdr.h | 22 + .../src/plugins/kdb/db2/libdb2/CHANGELOG.db2 | 123 + .../src/plugins/kdb/db2/libdb2/Makefile.in | 32 + .../src/plugins/kdb/db2/libdb2/Makefile.inc | 10 + krb5-1.21.3/src/plugins/kdb/db2/libdb2/README | 16 + .../kdb/db2/libdb2/README.NOT.SLEEPYCAT.DB | 2 + .../src/plugins/kdb/db2/libdb2/README.db2 | 41 + .../plugins/kdb/db2/libdb2/btree/Makefile.in | 15 + .../plugins/kdb/db2/libdb2/btree/Makefile.inc | 7 + .../plugins/kdb/db2/libdb2/btree/bt_close.c | 183 + .../plugins/kdb/db2/libdb2/btree/bt_conv.c | 224 + .../plugins/kdb/db2/libdb2/btree/bt_debug.c | 416 + .../plugins/kdb/db2/libdb2/btree/bt_delete.c | 657 + .../src/plugins/kdb/db2/libdb2/btree/bt_get.c | 105 + .../plugins/kdb/db2/libdb2/btree/bt_open.c | 480 + .../kdb/db2/libdb2/btree/bt_overflow.c | 228 + .../plugins/kdb/db2/libdb2/btree/bt_page.c | 100 + .../src/plugins/kdb/db2/libdb2/btree/bt_put.c | 329 + .../plugins/kdb/db2/libdb2/btree/bt_search.c | 297 + .../src/plugins/kdb/db2/libdb2/btree/bt_seq.c | 616 + .../plugins/kdb/db2/libdb2/btree/bt_split.c | 836 + .../plugins/kdb/db2/libdb2/btree/bt_utils.c | 260 + .../src/plugins/kdb/db2/libdb2/btree/btree.h | 383 + .../src/plugins/kdb/db2/libdb2/btree/deps | 56 + .../src/plugins/kdb/db2/libdb2/btree/extern.h | 101 + .../src/plugins/kdb/db2/libdb2/db/Makefile.in | 12 + .../plugins/kdb/db2/libdb2/db/Makefile.inc | 5 + .../src/plugins/kdb/db2/libdb2/db/db.c | 99 + .../src/plugins/kdb/db2/libdb2/db/deps | 6 + krb5-1.21.3/src/plugins/kdb/db2/libdb2/deps | 1 + .../plugins/kdb/db2/libdb2/docs/btree.3.ps | Bin 0 -> 16754 bytes .../plugins/kdb/db2/libdb2/docs/dbopen.3.ps | Bin 0 -> 26477 bytes .../src/plugins/kdb/db2/libdb2/docs/hash.3.ps | Bin 0 -> 11349 bytes .../kdb/db2/libdb2/docs/hash.usenix.ps | Bin 0 -> 158725 bytes .../kdb/db2/libdb2/docs/libtp.usenix.ps | Bin 0 -> 168155 bytes .../plugins/kdb/db2/libdb2/docs/mpool.3.ps | Bin 0 -> 13573 bytes .../plugins/kdb/db2/libdb2/docs/recno.3.ps | Bin 0 -> 14632 bytes .../plugins/kdb/db2/libdb2/hash/Makefile.in | 14 + .../plugins/kdb/db2/libdb2/hash/Makefile.inc | 6 + .../src/plugins/kdb/db2/libdb2/hash/dbm.c | 359 + .../src/plugins/kdb/db2/libdb2/hash/deps | 37 + .../src/plugins/kdb/db2/libdb2/hash/extern.h | 109 + .../src/plugins/kdb/db2/libdb2/hash/hash.c | 1054 + .../plugins/kdb/db2/libdb2/hash/hash.c.patch | 109 + .../src/plugins/kdb/db2/libdb2/hash/hash.h | 196 + .../plugins/kdb/db2/libdb2/hash/hash_bigkey.c | 481 + .../plugins/kdb/db2/libdb2/hash/hash_debug.c | 106 + .../plugins/kdb/db2/libdb2/hash/hash_func.c | 201 + .../plugins/kdb/db2/libdb2/hash/hash_log2.c | 55 + .../plugins/kdb/db2/libdb2/hash/hash_page.c | 1362 + .../src/plugins/kdb/db2/libdb2/hash/hsearch.c | 107 + .../src/plugins/kdb/db2/libdb2/hash/page.h | 178 + .../plugins/kdb/db2/libdb2/hash/page.h.patch | 42 + .../src/plugins/kdb/db2/libdb2/hash/search.h | 55 + .../plugins/kdb/db2/libdb2/include/config.h | 23 + .../kdb/db2/libdb2/include/db-config.hin | 17 + .../plugins/kdb/db2/libdb2/include/db-dbm.h | 23 + .../plugins/kdb/db2/libdb2/include/db-int.h | 283 + .../plugins/kdb/db2/libdb2/include/db-ndbm.h | 91 + .../plugins/kdb/db2/libdb2/include/db-queue.h | 245 + .../src/plugins/kdb/db2/libdb2/include/db.hin | 190 + .../src/plugins/kdb/db2/libdb2/libdb.exports | 105 + .../plugins/kdb/db2/libdb2/man/Makefile.inc | 7 + .../src/plugins/kdb/db2/libdb2/man/db.man.ps | Bin 0 -> 149053 bytes .../src/plugins/kdb/db2/libdb2/man/db_btree.3 | 246 + .../src/plugins/kdb/db2/libdb2/man/db_hash.3 | 138 + .../src/plugins/kdb/db2/libdb2/man/db_lock.3 | 462 + .../src/plugins/kdb/db2/libdb2/man/db_log.3 | 290 + .../src/plugins/kdb/db2/libdb2/man/db_mpool.3 | 403 + .../src/plugins/kdb/db2/libdb2/man/db_open.3 | 574 + .../src/plugins/kdb/db2/libdb2/man/db_recno.3 | 268 + .../src/plugins/kdb/db2/libdb2/man/db_txn.3 | 373 + .../src/plugins/kdb/db2/libdb2/man/spell.ok | 170 + .../plugins/kdb/db2/libdb2/mpool/Makefile.in | 12 + .../plugins/kdb/db2/libdb2/mpool/Makefile.inc | 5 + .../src/plugins/kdb/db2/libdb2/mpool/README | 7 + .../src/plugins/kdb/db2/libdb2/mpool/deps | 6 + .../src/plugins/kdb/db2/libdb2/mpool/mpool.c | 527 + .../src/plugins/kdb/db2/libdb2/mpool/mpool.h | 117 + .../plugins/kdb/db2/libdb2/recno/Makefile.in | 14 + .../plugins/kdb/db2/libdb2/recno/Makefile.inc | 6 + .../src/plugins/kdb/db2/libdb2/recno/deps | 43 + .../src/plugins/kdb/db2/libdb2/recno/extern.h | 72 + .../plugins/kdb/db2/libdb2/recno/rec_close.c | 188 + .../plugins/kdb/db2/libdb2/recno/rec_delete.c | 197 + .../plugins/kdb/db2/libdb2/recno/rec_get.c | 311 + .../plugins/kdb/db2/libdb2/recno/rec_open.c | 248 + .../plugins/kdb/db2/libdb2/recno/rec_put.c | 281 + .../plugins/kdb/db2/libdb2/recno/rec_search.c | 126 + .../plugins/kdb/db2/libdb2/recno/rec_seq.c | 131 + .../plugins/kdb/db2/libdb2/recno/rec_utils.c | 122 + .../src/plugins/kdb/db2/libdb2/recno/recno.h | 39 + .../plugins/kdb/db2/libdb2/test/Makefile.in | 37 + .../src/plugins/kdb/db2/libdb2/test/README | 74 + .../plugins/kdb/db2/libdb2/test/SEQ_TEST/data | 8 + .../plugins/kdb/db2/libdb2/test/SEQ_TEST/mbox | 399 + .../plugins/kdb/db2/libdb2/test/SEQ_TEST/t.c | 85 + .../kdb/db2/libdb2/test/btree.tests/main.c | 973 + .../src/plugins/kdb/db2/libdb2/test/dbtest.c | 842 + .../src/plugins/kdb/db2/libdb2/test/deps | 1 + .../plugins/kdb/db2/libdb2/test/dictionary | 308 + .../kdb/db2/libdb2/test/hash1.tests/Makefile | 43 + .../kdb/db2/libdb2/test/hash1.tests/driver2.c | 111 + .../kdb/db2/libdb2/test/hash1.tests/makedb.sh | 13 + .../kdb/db2/libdb2/test/hash1.tests/tcreat3.c | 105 + .../kdb/db2/libdb2/test/hash1.tests/tdel.c | 122 + .../kdb/db2/libdb2/test/hash1.tests/testit | 154 + .../kdb/db2/libdb2/test/hash1.tests/thash4.c | 131 + .../kdb/db2/libdb2/test/hash1.tests/tread2.c | 105 + .../kdb/db2/libdb2/test/hash1.tests/tseq.c | 88 + .../kdb/db2/libdb2/test/hash1.tests/tverify.c | 107 + .../kdb/db2/libdb2/test/hash2.tests/README | 72 + .../kdb/db2/libdb2/test/hash2.tests/bigtest.c | 75 + .../db2/libdb2/test/hash2.tests/passtest.c | 184 + .../libdb2/test/hash2.tests/passwd/genpass.c | 22 + .../src/plugins/kdb/db2/libdb2/test/run.test | 1036 + .../src/plugins/kdb/db2/libdb2/test/t.be.txt | 64 + .../src/plugins/kdb/db2/libdb2/test/t.le.txt | 64 + krb5-1.21.3/src/plugins/kdb/db2/lockout.c | 222 + krb5-1.21.3/src/plugins/kdb/db2/pol_xdr.c | 89 + krb5-1.21.3/src/plugins/kdb/db2/policy_db.h | 107 + krb5-1.21.3/src/plugins/kdb/ldap/Makefile.in | 36 + krb5-1.21.3/src/plugins/kdb/ldap/deps | 27 + .../src/plugins/kdb/ldap/kldap.exports | 1 + krb5-1.21.3/src/plugins/kdb/ldap/ldap_exp.c | 86 + .../plugins/kdb/ldap/ldap_util/Makefile.in | 29 + .../src/plugins/kdb/ldap/ldap_util/deps | 104 + .../kdb/ldap/ldap_util/kdb5_ldap_list.c | 275 + .../kdb/ldap/ldap_util/kdb5_ldap_list.h | 44 + .../kdb/ldap/ldap_util/kdb5_ldap_policy.c | 866 + .../kdb/ldap/ldap_util/kdb5_ldap_policy.h | 35 + .../kdb/ldap/ldap_util/kdb5_ldap_realm.c | 1484 + .../kdb/ldap/ldap_util/kdb5_ldap_realm.h | 59 + .../kdb/ldap/ldap_util/kdb5_ldap_services.c | 319 + .../kdb/ldap/ldap_util/kdb5_ldap_services.h | 35 + .../kdb/ldap/ldap_util/kdb5_ldap_util.c | 608 + .../kdb/ldap/ldap_util/kdb5_ldap_util.h | 69 + .../plugins/kdb/ldap/libkdb_ldap/Makefile.in | 70 + .../src/plugins/kdb/ldap/libkdb_ldap/deps | 277 + .../plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c | 317 + .../plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h | 316 + .../kdb/ldap/libkdb_ldap/kdb_ldap_conn.c | 364 + .../plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c | 141 + .../kdb/ldap/libkdb_ldap/kerberos.ldif | 905 + .../ldap/libkdb_ldap/kerberos.openldap.ldif | 68 + .../kdb/ldap/libkdb_ldap/kerberos.schema | 726 + .../kdb/ldap/libkdb_ldap/ldap_create.c | 125 + .../plugins/kdb/ldap/libkdb_ldap/ldap_err.c | 195 + .../plugins/kdb/ldap/libkdb_ldap/ldap_err.h | 13 + .../kdb/ldap/libkdb_ldap/ldap_handle.c | 175 + .../kdb/ldap/libkdb_ldap/ldap_handle.h | 43 + .../kdb/ldap/libkdb_ldap/ldap_krbcontainer.c | 84 + .../kdb/ldap/libkdb_ldap/ldap_krbcontainer.h | 47 + .../plugins/kdb/ldap/libkdb_ldap/ldap_main.h | 38 + .../plugins/kdb/ldap/libkdb_ldap/ldap_misc.c | 1701 + .../plugins/kdb/ldap/libkdb_ldap/ldap_misc.h | 125 + .../kdb/ldap/libkdb_ldap/ldap_principal.c | 628 + .../kdb/ldap/libkdb_ldap/ldap_principal.h | 152 + .../kdb/ldap/libkdb_ldap/ldap_principal2.c | 1751 + .../kdb/ldap/libkdb_ldap/ldap_pwd_policy.c | 469 + .../kdb/ldap/libkdb_ldap/ldap_pwd_policy.h | 51 + .../plugins/kdb/ldap/libkdb_ldap/ldap_realm.c | 926 + .../plugins/kdb/ldap/libkdb_ldap/ldap_realm.h | 98 + .../kdb/ldap/libkdb_ldap/ldap_service_stash.c | 115 + .../kdb/ldap/libkdb_ldap/ldap_service_stash.h | 40 + .../kdb/ldap/libkdb_ldap/ldap_tkt_policy.c | 498 + .../kdb/ldap/libkdb_ldap/ldap_tkt_policy.h | 75 + .../kdb/ldap/libkdb_ldap/libkdb_ldap.exports | 41 + .../plugins/kdb/ldap/libkdb_ldap/lockout.c | 220 + .../plugins/kdb/ldap/libkdb_ldap/princ_xdr.c | 55 + .../plugins/kdb/ldap/libkdb_ldap/princ_xdr.h | 21 + krb5-1.21.3/src/plugins/kdb/lmdb/Makefile.in | 27 + krb5-1.21.3/src/plugins/kdb/lmdb/deps | 53 + krb5-1.21.3/src/plugins/kdb/lmdb/kdb_lmdb.c | 1143 + krb5-1.21.3/src/plugins/kdb/lmdb/klmdb-int.h | 78 + .../src/plugins/kdb/lmdb/klmdb.exports | 1 + krb5-1.21.3/src/plugins/kdb/lmdb/lockout.c | 180 + krb5-1.21.3/src/plugins/kdb/lmdb/marshal.c | 321 + krb5-1.21.3/src/plugins/kdb/test/Makefile.in | 21 + krb5-1.21.3/src/plugins/kdb/test/deps | 15 + krb5-1.21.3/src/plugins/kdb/test/kdb_test.c | 820 + krb5-1.21.3/src/plugins/kdb/test/test.exports | 1 + .../src/plugins/kdcpolicy/test/Makefile.in | 20 + krb5-1.21.3/src/plugins/kdcpolicy/test/deps | 14 + .../kdcpolicy/test/kdcpolicy_test.exports | 1 + krb5-1.21.3/src/plugins/kdcpolicy/test/main.c | 111 + .../src/plugins/localauth/test/Makefile.in | 20 + krb5-1.21.3/src/plugins/localauth/test/deps | 14 + .../localauth/test/localauth_test.exports | 2 + krb5-1.21.3/src/plugins/localauth/test/main.c | 169 + .../src/plugins/preauth/otp/Makefile.in | 31 + krb5-1.21.3/src/plugins/preauth/otp/deps | 28 + krb5-1.21.3/src/plugins/preauth/otp/main.c | 390 + .../src/plugins/preauth/otp/otp.exports | 1 + .../src/plugins/preauth/otp/otp_state.c | 740 + .../src/plugins/preauth/otp/otp_state.h | 60 + .../src/plugins/preauth/pkinit/Makefile.in | 53 + krb5-1.21.3/src/plugins/preauth/pkinit/deps | 115 + .../src/plugins/preauth/pkinit/pkcs11.h | 1353 + .../src/plugins/preauth/pkinit/pkinit.exports | 2 + .../src/plugins/preauth/pkinit/pkinit.h | 385 + .../plugins/preauth/pkinit/pkinit_accessor.c | 110 + .../plugins/preauth/pkinit/pkinit_accessor.h | 74 + .../src/plugins/preauth/pkinit/pkinit_clnt.c | 1514 + .../plugins/preauth/pkinit/pkinit_constants.c | 325 + .../plugins/preauth/pkinit/pkinit_crypto.h | 631 + .../preauth/pkinit/pkinit_crypto_openssl.c | 5814 +++ .../preauth/pkinit/pkinit_crypto_openssl.h | 119 + .../plugins/preauth/pkinit/pkinit_identity.c | 791 + .../plugins/preauth/pkinit/pkinit_kdf_test.c | 227 + .../src/plugins/preauth/pkinit/pkinit_lib.c | 290 + .../plugins/preauth/pkinit/pkinit_matching.c | 751 + .../plugins/preauth/pkinit/pkinit_profile.c | 368 + .../src/plugins/preauth/pkinit/pkinit_srv.c | 1646 + .../src/plugins/preauth/pkinit/pkinit_trace.h | 214 + .../plugins/preauth/securid_sam2/Makefile.in | 27 + .../src/plugins/preauth/securid_sam2/README | 17 + .../src/plugins/preauth/securid_sam2/deps | 0 .../src/plugins/preauth/securid_sam2/extern.h | 60 + .../src/plugins/preauth/securid_sam2/grail.c | 272 + .../plugins/preauth/securid_sam2/securid2.c | 669 + .../preauth/securid_sam2/securid_sam2.exports | 1 + .../preauth/securid_sam2/securid_sam2_main.c | 378 + krb5-1.21.3/src/plugins/preauth/spake/AUTHORS | 16 + .../src/plugins/preauth/spake/Makefile.in | 60 + krb5-1.21.3/src/plugins/preauth/spake/deps | 74 + .../src/plugins/preauth/spake/edwards25519.c | 1753 + .../plugins/preauth/spake/edwards25519_fiat.h | 1289 + .../preauth/spake/edwards25519_tables.h | 7881 ++++ .../src/plugins/preauth/spake/groups.c | 442 + .../src/plugins/preauth/spake/groups.h | 148 + krb5-1.21.3/src/plugins/preauth/spake/iana.c | 108 + krb5-1.21.3/src/plugins/preauth/spake/iana.h | 65 + .../src/plugins/preauth/spake/openssl.c | 316 + .../src/plugins/preauth/spake/spake.def | 3 + .../src/plugins/preauth/spake/spake.exports | 2 + .../src/plugins/preauth/spake/spake_client.c | 388 + .../src/plugins/preauth/spake/spake_kdc.c | 562 + .../src/plugins/preauth/spake/t_krb5.conf | 2 + .../src/plugins/preauth/spake/t_vectors.c | 476 + krb5-1.21.3/src/plugins/preauth/spake/trace.h | 74 + krb5-1.21.3/src/plugins/preauth/spake/util.c | 212 + krb5-1.21.3/src/plugins/preauth/spake/util.h | 56 + .../src/plugins/preauth/test/Makefile.in | 21 + krb5-1.21.3/src/plugins/preauth/test/cltest.c | 253 + krb5-1.21.3/src/plugins/preauth/test/common.c | 61 + krb5-1.21.3/src/plugins/preauth/test/common.h | 41 + krb5-1.21.3/src/plugins/preauth/test/deps | 35 + .../src/plugins/preauth/test/kdctest.c | 220 + .../src/plugins/preauth/test/test.exports | 2 + .../src/plugins/pwqual/test/Makefile.in | 21 + krb5-1.21.3/src/plugins/pwqual/test/deps | 16 + krb5-1.21.3/src/plugins/pwqual/test/main.c | 220 + .../plugins/pwqual/test/pwqual_test.exports | 4 + krb5-1.21.3/src/plugins/tls/k5tls/Makefile.in | 22 + krb5-1.21.3/src/plugins/tls/k5tls/deps | 25 + .../src/plugins/tls/k5tls/k5tls.exports | 1 + krb5-1.21.3/src/plugins/tls/k5tls/notls.c | 53 + krb5-1.21.3/src/plugins/tls/k5tls/openssl.c | 585 + krb5-1.21.3/src/po/Makefile.in | 52 + krb5-1.21.3/src/po/de.po | 9300 +++++ krb5-1.21.3/src/po/deps | 1 + krb5-1.21.3/src/po/en_US.po | 17 + krb5-1.21.3/src/po/ka.po | 9188 +++++ krb5-1.21.3/src/po/mit-krb5.pot | 8855 +++++ krb5-1.21.3/src/prototype/prototype.c | 35 + krb5-1.21.3/src/prototype/prototype.h | 40 + krb5-1.21.3/src/tests/Makefile.in | 201 + krb5-1.21.3/src/tests/adata.c | 381 + krb5-1.21.3/src/tests/asn.1/Makefile.in | 98 + krb5-1.21.3/src/tests/asn.1/README | 28 + krb5-1.21.3/src/tests/asn.1/cammac.asn1 | 30 + krb5-1.21.3/src/tests/asn.1/debug.h | 46 + krb5-1.21.3/src/tests/asn.1/deps | 75 + krb5-1.21.3/src/tests/asn.1/krb5.asn1 | 392 + .../src/tests/asn.1/krb5_decode_leak.c | 676 + .../src/tests/asn.1/krb5_decode_test.c | 1301 + .../src/tests/asn.1/krb5_encode_test.c | 853 + krb5-1.21.3/src/tests/asn.1/ktest.c | 1799 + krb5-1.21.3/src/tests/asn.1/ktest.h | 210 + krb5-1.21.3/src/tests/asn.1/ktest_equal.c | 1054 + krb5-1.21.3/src/tests/asn.1/ktest_equal.h | 154 + krb5-1.21.3/src/tests/asn.1/ldap_encode.out | 1 + krb5-1.21.3/src/tests/asn.1/ldap_trval.out | 30 + krb5-1.21.3/src/tests/asn.1/make-vectors.c | 333 + krb5-1.21.3/src/tests/asn.1/otp.asn1 | 109 + .../src/tests/asn.1/pkinit-agility.asn1 | 99 + krb5-1.21.3/src/tests/asn.1/pkinit.asn1 | 253 + krb5-1.21.3/src/tests/asn.1/pkinit_encode.out | 8 + krb5-1.21.3/src/tests/asn.1/pkinit_trval.out | 97 + krb5-1.21.3/src/tests/asn.1/pkix.asn1 | 654 + .../src/tests/asn.1/reference_encode.out | 78 + krb5-1.21.3/src/tests/asn.1/spake.asn1 | 44 + krb5-1.21.3/src/tests/asn.1/t_trval.c | 107 + krb5-1.21.3/src/tests/asn.1/trval.c | 769 + .../src/tests/asn.1/trval_reference.out | 1587 + krb5-1.21.3/src/tests/asn.1/utility.c | 142 + krb5-1.21.3/src/tests/asn.1/utility.h | 57 + krb5-1.21.3/src/tests/au_dict.json | 64 + krb5-1.21.3/src/tests/conccache.c | 190 + krb5-1.21.3/src/tests/create/Makefile.in | 17 + krb5-1.21.3/src/tests/create/deps | 14 + krb5-1.21.3/src/tests/create/kdb5_mkdums.c | 406 + krb5-1.21.3/src/tests/deps | 181 + krb5-1.21.3/src/tests/dump.c | 42 + krb5-1.21.3/src/tests/dumpfiles/dump | 11 + krb5-1.21.3/src/tests/dumpfiles/dump.16 | 7 + krb5-1.21.3/src/tests/dumpfiles/dump.b7 | 11 + krb5-1.21.3/src/tests/dumpfiles/dump.ov | 9 + krb5-1.21.3/src/tests/dumpfiles/dump.r13 | 11 + krb5-1.21.3/src/tests/dumpfiles/dump.r18 | 11 + krb5-1.21.3/src/tests/etinfo.c | 172 + krb5-1.21.3/src/tests/forward.c | 93 + krb5-1.21.3/src/tests/gcred.c | 124 + krb5-1.21.3/src/tests/gss-threads/Makefile.in | 34 + krb5-1.21.3/src/tests/gss-threads/README | 165 + krb5-1.21.3/src/tests/gss-threads/deps | 15 + .../src/tests/gss-threads/gss-client.c | 865 + krb5-1.21.3/src/tests/gss-threads/gss-misc.c | 410 + krb5-1.21.3/src/tests/gss-threads/gss-misc.h | 51 + .../src/tests/gss-threads/gss-server.c | 850 + krb5-1.21.3/src/tests/gssapi/Makefile.in | 138 + krb5-1.21.3/src/tests/gssapi/ccinit.c | 72 + krb5-1.21.3/src/tests/gssapi/ccrefresh.c | 80 + krb5-1.21.3/src/tests/gssapi/common.c | 282 + krb5-1.21.3/src/tests/gssapi/common.h | 90 + krb5-1.21.3/src/tests/gssapi/deps | 198 + krb5-1.21.3/src/tests/gssapi/reload.c | 83 + krb5-1.21.3/src/tests/gssapi/t_accname.c | 93 + krb5-1.21.3/src/tests/gssapi/t_add_cred.c | 137 + krb5-1.21.3/src/tests/gssapi/t_authind.py | 51 + krb5-1.21.3/src/tests/gssapi/t_bindings.c | 111 + krb5-1.21.3/src/tests/gssapi/t_bindings.py | 43 + krb5-1.21.3/src/tests/gssapi/t_ccselect.c | 90 + krb5-1.21.3/src/tests/gssapi/t_ccselect.py | 164 + krb5-1.21.3/src/tests/gssapi/t_ciflags.c | 120 + .../src/tests/gssapi/t_client_keytab.py | 189 + krb5-1.21.3/src/tests/gssapi/t_context.c | 60 + krb5-1.21.3/src/tests/gssapi/t_credstore.c | 140 + krb5-1.21.3/src/tests/gssapi/t_credstore.py | 97 + krb5-1.21.3/src/tests/gssapi/t_enctypes.c | 205 + krb5-1.21.3/src/tests/gssapi/t_enctypes.py | 147 + krb5-1.21.3/src/tests/gssapi/t_err.c | 126 + krb5-1.21.3/src/tests/gssapi/t_export_cred.c | 115 + krb5-1.21.3/src/tests/gssapi/t_export_cred.py | 50 + krb5-1.21.3/src/tests/gssapi/t_export_name.c | 119 + krb5-1.21.3/src/tests/gssapi/t_gssapi.py | 226 + krb5-1.21.3/src/tests/gssapi/t_gssexts.c | 247 + krb5-1.21.3/src/tests/gssapi/t_imp_cred.c | 101 + krb5-1.21.3/src/tests/gssapi/t_imp_name.c | 94 + krb5-1.21.3/src/tests/gssapi/t_inq_cred.c | 116 + krb5-1.21.3/src/tests/gssapi/t_inq_ctx.c | 241 + .../src/tests/gssapi/t_inq_mechs_name.c | 64 + krb5-1.21.3/src/tests/gssapi/t_invalid.c | 615 + krb5-1.21.3/src/tests/gssapi/t_iov.c | 547 + krb5-1.21.3/src/tests/gssapi/t_lifetime.c | 140 + krb5-1.21.3/src/tests/gssapi/t_namingexts.c | 227 + krb5-1.21.3/src/tests/gssapi/t_negoex.py | 149 + krb5-1.21.3/src/tests/gssapi/t_oid.c | 224 + krb5-1.21.3/src/tests/gssapi/t_pcontok.c | 190 + krb5-1.21.3/src/tests/gssapi/t_prf.c | 190 + krb5-1.21.3/src/tests/gssapi/t_s4u.c | 334 + krb5-1.21.3/src/tests/gssapi/t_s4u.py | 403 + .../src/tests/gssapi/t_s4u2proxy_krb5.c | 164 + krb5-1.21.3/src/tests/gssapi/t_saslname.c | 165 + krb5-1.21.3/src/tests/gssapi/t_spnego.c | 314 + krb5-1.21.3/src/tests/gssapi/t_srcattrs.c | 63 + krb5-1.21.3/src/tests/gssapi/t_store_cred.c | 114 + krb5-1.21.3/src/tests/gssapi/t_store_cred.py | 80 + krb5-1.21.3/src/tests/hammer/Makefile.in | 15 + krb5-1.21.3/src/tests/hammer/deps | 13 + krb5-1.21.3/src/tests/hammer/kdc5_hammer.c | 507 + krb5-1.21.3/src/tests/hammer/pp.c | 27 + krb5-1.21.3/src/tests/hist.c | 99 + krb5-1.21.3/src/tests/hooks.c | 253 + krb5-1.21.3/src/tests/hrealm.c | 99 + krb5-1.21.3/src/tests/icinterleave.c | 128 + krb5-1.21.3/src/tests/icred.c | 144 + krb5-1.21.3/src/tests/jsonwalker.py | 105 + krb5-1.21.3/src/tests/kcmserver.py | 336 + krb5-1.21.3/src/tests/kdbtest.c | 403 + krb5-1.21.3/src/tests/localauth.c | 72 + krb5-1.21.3/src/tests/misc/Makefile.in | 58 + krb5-1.21.3/src/tests/misc/deps | 44 + .../src/tests/misc/test_chpw_message.c | 174 + krb5-1.21.3/src/tests/misc/test_cxx_gss.cpp | 10 + krb5-1.21.3/src/tests/misc/test_cxx_k5int.cpp | 20 + krb5-1.21.3/src/tests/misc/test_cxx_kadm5.cpp | 15 + krb5-1.21.3/src/tests/misc/test_cxx_krb5.cpp | 19 + krb5-1.21.3/src/tests/misc/test_cxx_rpc.cpp | 14 + krb5-1.21.3/src/tests/misc/test_getpw.c | 51 + krb5-1.21.3/src/tests/misc/test_getsockname.c | 117 + krb5-1.21.3/src/tests/misc/test_nfold.c | 66 + krb5-1.21.3/src/tests/pkinit-certs/ca.pem | 29 + .../src/tests/pkinit-certs/generic.p12 | Bin 0 -> 2469 bytes .../src/tests/pkinit-certs/generic.pem | 21 + krb5-1.21.3/src/tests/pkinit-certs/kdc.pem | 29 + .../src/tests/pkinit-certs/make-certs.sh | 172 + .../src/tests/pkinit-certs/privkey-enc.pem | 30 + .../src/tests/pkinit-certs/privkey.pem | 27 + .../src/tests/pkinit-certs/user-enc.p12 | Bin 0 -> 2829 bytes .../src/tests/pkinit-certs/user-upn.p12 | Bin 0 -> 2821 bytes .../src/tests/pkinit-certs/user-upn.pem | 28 + .../src/tests/pkinit-certs/user-upn2.p12 | Bin 0 -> 2805 bytes .../src/tests/pkinit-certs/user-upn2.pem | 28 + .../src/tests/pkinit-certs/user-upn3.p12 | Bin 0 -> 2821 bytes .../src/tests/pkinit-certs/user-upn3.pem | 28 + krb5-1.21.3/src/tests/pkinit-certs/user.p12 | Bin 0 -> 2829 bytes krb5-1.21.3/src/tests/pkinit-certs/user.pem | 28 + krb5-1.21.3/src/tests/plugorder.c | 96 + krb5-1.21.3/src/tests/proxy-certs/ca.pem | 28 + .../src/tests/proxy-certs/make-certs.sh | 124 + .../src/tests/proxy-certs/proxy-badsig.pem | 56 + .../src/tests/proxy-certs/proxy-ideal.pem | 56 + .../src/tests/proxy-certs/proxy-no-match.pem | 54 + .../src/tests/proxy-certs/proxy-san.pem | 56 + .../src/tests/proxy-certs/proxy-subject.pem | 54 + krb5-1.21.3/src/tests/rdreq.c | 118 + krb5-1.21.3/src/tests/replay.c | 172 + krb5-1.21.3/src/tests/responder.c | 431 + krb5-1.21.3/src/tests/s2p.c | 81 + krb5-1.21.3/src/tests/s4u2proxy.c | 147 + krb5-1.21.3/src/tests/s4u2self.c | 128 + krb5-1.21.3/src/tests/shlib/Makefile.in | 23 + krb5-1.21.3/src/tests/shlib/deps | 8 + krb5-1.21.3/src/tests/shlib/t_loader.c | 374 + krb5-1.21.3/src/tests/softpkcs11/Makefile.in | 21 + krb5-1.21.3/src/tests/softpkcs11/deps | 6 + krb5-1.21.3/src/tests/softpkcs11/main.c | 2107 ++ .../src/tests/softpkcs11/softpkcs11.exports | 39 + krb5-1.21.3/src/tests/t_audit.py | 27 + krb5-1.21.3/src/tests/t_authdata.py | 362 + krb5-1.21.3/src/tests/t_bogus_kdc_req.py | 42 + krb5-1.21.3/src/tests/t_ccache.py | 202 + krb5-1.21.3/src/tests/t_certauth.py | 65 + krb5-1.21.3/src/tests/t_changepw.py | 50 + krb5-1.21.3/src/tests/t_crossrealm.py | 192 + krb5-1.21.3/src/tests/t_cve-2012-1014.py | 29 + krb5-1.21.3/src/tests/t_cve-2012-1015.py | 36 + krb5-1.21.3/src/tests/t_cve-2013-1416.py | 13 + krb5-1.21.3/src/tests/t_cve-2013-1417.py | 11 + krb5-1.21.3/src/tests/t_cve-2021-36222.py | 46 + krb5-1.21.3/src/tests/t_dump.py | 94 + krb5-1.21.3/src/tests/t_errmsg.py | 27 + krb5-1.21.3/src/tests/t_etype_info.py | 69 + krb5-1.21.3/src/tests/t_general.py | 74 + krb5-1.21.3/src/tests/t_hooks.py | 8 + krb5-1.21.3/src/tests/t_hostrealm.py | 140 + krb5-1.21.3/src/tests/t_inetd.c | 129 + krb5-1.21.3/src/tests/t_iprop.py | 494 + krb5-1.21.3/src/tests/t_kadm5_auth.py | 80 + krb5-1.21.3/src/tests/t_kadm5_hook.py | 15 + krb5-1.21.3/src/tests/t_kadmin.py | 66 + krb5-1.21.3/src/tests/t_kadmin_acl.py | 352 + krb5-1.21.3/src/tests/t_kadmin_parsing.py | 82 + krb5-1.21.3/src/tests/t_kdb.py | 622 + krb5-1.21.3/src/tests/t_kdb_locking.py | 32 + krb5-1.21.3/src/tests/t_kdc_log.py | 21 + krb5-1.21.3/src/tests/t_kdcoptions.py | 100 + krb5-1.21.3/src/tests/t_kdcpolicy.py | 65 + krb5-1.21.3/src/tests/t_keydata.py | 49 + krb5-1.21.3/src/tests/t_keyrollover.py | 75 + krb5-1.21.3/src/tests/t_keytab.py | 209 + krb5-1.21.3/src/tests/t_kprop.py | 125 + krb5-1.21.3/src/tests/t_localauth.py | 154 + krb5-1.21.3/src/tests/t_mkey.py | 344 + krb5-1.21.3/src/tests/t_otp.py | 272 + krb5-1.21.3/src/tests/t_pkinit.py | 438 + krb5-1.21.3/src/tests/t_policy.py | 217 + krb5-1.21.3/src/tests/t_preauth.py | 265 + krb5-1.21.3/src/tests/t_princflags.py | 138 + krb5-1.21.3/src/tests/t_proxy.py | 220 + krb5-1.21.3/src/tests/t_pwqual.py | 78 + krb5-1.21.3/src/tests/t_rdreq.py | 138 + krb5-1.21.3/src/tests/t_referral.py | 142 + krb5-1.21.3/src/tests/t_renew.py | 122 + krb5-1.21.3/src/tests/t_renprinc.py | 45 + krb5-1.21.3/src/tests/t_replay.py | 6 + krb5-1.21.3/src/tests/t_salt.py | 55 + krb5-1.21.3/src/tests/t_sesskeynego.py | 94 + krb5-1.21.3/src/tests/t_skew.py | 55 + krb5-1.21.3/src/tests/t_sn2princ.py | 167 + krb5-1.21.3/src/tests/t_spake.py | 149 + krb5-1.21.3/src/tests/t_stringattr.py | 41 + krb5-1.21.3/src/tests/t_tabdump.py | 80 + krb5-1.21.3/src/tests/t_u2u.py | 60 + krb5-1.21.3/src/tests/t_unlockiter.py | 20 + krb5-1.21.3/src/tests/t_y2038.py | 79 + krb5-1.21.3/src/tests/test1.c | 192 + krb5-1.21.3/src/tests/threads/Makefile.in | 40 + krb5-1.21.3/src/tests/threads/deps | 27 + krb5-1.21.3/src/tests/threads/gss-perf.c | 455 + krb5-1.21.3/src/tests/threads/init_ctx.c | 273 + krb5-1.21.3/src/tests/threads/prof1.c | 105 + krb5-1.21.3/src/tests/threads/profread.c | 287 + krb5-1.21.3/src/tests/threads/t_rcache.c | 260 + krb5-1.21.3/src/tests/unlockiter.c | 276 + krb5-1.21.3/src/tests/verify/Makefile.in | 16 + krb5-1.21.3/src/tests/verify/deps | 14 + krb5-1.21.3/src/tests/verify/kdb5_verify.c | 449 + krb5-1.21.3/src/tests/verify/pkey.c | 24 + krb5-1.21.3/src/util/Makefile.in | 29 + krb5-1.21.3/src/util/ac_check_krb5.m4 | 58 + krb5-1.21.3/src/util/check-ac-syms | 33 + krb5-1.21.3/src/util/cstyle-file.py | 323 + krb5-1.21.3/src/util/cstyle.py | 188 + krb5-1.21.3/src/util/def-check.pl | 265 + krb5-1.21.3/src/util/depfix.pl | 216 + krb5-1.21.3/src/util/deps | 1 + krb5-1.21.3/src/util/et/ISSUES | 64 + krb5-1.21.3/src/util/et/Makefile.in | 181 + krb5-1.21.3/src/util/et/com_err.3 | 96 + krb5-1.21.3/src/util/et/com_err.c | 176 + krb5-1.21.3/src/util/et/com_err.h | 80 + krb5-1.21.3/src/util/et/com_err.texinfo | 555 + krb5-1.21.3/src/util/et/compile_et.1 | 97 + krb5-1.21.3/src/util/et/compile_et.sh | 36 + krb5-1.21.3/src/util/et/config_script | 22 + krb5-1.21.3/src/util/et/deps | 13 + krb5-1.21.3/src/util/et/error_message.c | 309 + krb5-1.21.3/src/util/et/error_table.h | 32 + krb5-1.21.3/src/util/et/et.exp | 8 + krb5-1.21.3/src/util/et/et.pbexp | 10 + krb5-1.21.3/src/util/et/et1.et | 11 + krb5-1.21.3/src/util/et/et2.et | 11 + krb5-1.21.3/src/util/et/et_c.awk | 219 + krb5-1.21.3/src/util/et/et_c.pl | 289 + krb5-1.21.3/src/util/et/et_h.awk | 162 + krb5-1.21.3/src/util/et/et_h.pl | 234 + krb5-1.21.3/src/util/et/et_name.c | 57 + krb5-1.21.3/src/util/et/libcom_err.exports | 9 + krb5-1.21.3/src/util/et/mit-sipb-copyright.h | 22 + krb5-1.21.3/src/util/et/t_com_err.c | 144 + krb5-1.21.3/src/util/et/test1.et | 69 + krb5-1.21.3/src/util/et/test2.et | 9 + krb5-1.21.3/src/util/et/test_et.c | 77 + krb5-1.21.3/src/util/et/texinfo.tex | 2077 + krb5-1.21.3/src/util/exitsleep.c | 49 + krb5-1.21.3/src/util/export-check.pl | 84 + krb5-1.21.3/src/util/gen-map.pl | 111 + krb5-1.21.3/src/util/gen.pl | 61 + krb5-1.21.3/src/util/getsyms | 63 + krb5-1.21.3/src/util/getsyms.sed | 42 + krb5-1.21.3/src/util/k5test.py | 1437 + krb5-1.21.3/src/util/krb5-batch-reindent.el | 68 + krb5-1.21.3/src/util/krb5-c-style.el | 55 + krb5-1.21.3/src/util/krb5-check-copyright.py | 105 + .../src/util/krb5-hack-cc-mode-caselabel.el | 44 + krb5-1.21.3/src/util/krb5-mark-cstyle.py | 47 + krb5-1.21.3/src/util/krb5-send-pr.sh | 9 + krb5-1.21.3/src/util/ktemplate.pm | 74 + krb5-1.21.3/src/util/lndir | 103 + krb5-1.21.3/src/util/mkrel | 221 + krb5-1.21.3/src/util/princflags.py | 266 + krb5-1.21.3/src/util/profile/Makefile.in | 161 + krb5-1.21.3/src/util/profile/argv_parse.c | 171 + krb5-1.21.3/src/util/profile/argv_parse.h | 46 + krb5-1.21.3/src/util/profile/deps | 56 + krb5-1.21.3/src/util/profile/dosshell.ini | 537 + krb5-1.21.3/src/util/profile/final.expected | 12 + krb5-1.21.3/src/util/profile/final1.ini | 6 + krb5-1.21.3/src/util/profile/final2.ini | 7 + krb5-1.21.3/src/util/profile/final3.ini | 6 + krb5-1.21.3/src/util/profile/final4.ini | 6 + krb5-1.21.3/src/util/profile/final5.ini | 5 + krb5-1.21.3/src/util/profile/krb5.conf | 50 + .../src/util/profile/libprofile.exports | 30 + krb5-1.21.3/src/util/profile/prof_FSp_glue.c | 92 + krb5-1.21.3/src/util/profile/prof_err.et | 78 + krb5-1.21.3/src/util/profile/prof_file.c | 564 + krb5-1.21.3/src/util/profile/prof_get.c | 617 + krb5-1.21.3/src/util/profile/prof_init.c | 666 + krb5-1.21.3/src/util/profile/prof_int.h | 266 + krb5-1.21.3/src/util/profile/prof_parse.c | 634 + krb5-1.21.3/src/util/profile/prof_set.c | 306 + krb5-1.21.3/src/util/profile/prof_tree.c | 700 + krb5-1.21.3/src/util/profile/profile.5 | 72 + krb5-1.21.3/src/util/profile/profile.exp | 35 + krb5-1.21.3/src/util/profile/profile.hin | 295 + krb5-1.21.3/src/util/profile/profile.pbexp | 33 + krb5-1.21.3/src/util/profile/prtest.in | 36 + krb5-1.21.3/src/util/profile/prtest.script | 11 + krb5-1.21.3/src/util/profile/t_profile.c | 389 + krb5-1.21.3/src/util/profile/test.ini | 53 + krb5-1.21.3/src/util/profile/test_load.c | 51 + krb5-1.21.3/src/util/profile/test_parse.c | 55 + krb5-1.21.3/src/util/profile/test_profile.c | 167 + krb5-1.21.3/src/util/profile/test_vtable.c | 303 + .../src/util/profile/testmod/Makefile.in | 21 + krb5-1.21.3/src/util/profile/testmod/deps | 7 + .../src/util/profile/testmod/proftest.exports | 1 + .../src/util/profile/testmod/testmod_main.c | 104 + krb5-1.21.3/src/util/ss/Makefile.in | 129 + krb5-1.21.3/src/util/ss/config_script | 28 + krb5-1.21.3/src/util/ss/copyright.h | 22 + krb5-1.21.3/src/util/ss/ct_c_awk.in | 77 + krb5-1.21.3/src/util/ss/ct_c_sed.in | 161 + krb5-1.21.3/src/util/ss/data.c | 14 + krb5-1.21.3/src/util/ss/deps | 59 + krb5-1.21.3/src/util/ss/error.c | 70 + krb5-1.21.3/src/util/ss/execute_cmd.c | 208 + krb5-1.21.3/src/util/ss/help.c | 156 + krb5-1.21.3/src/util/ss/invocation.c | 131 + krb5-1.21.3/src/util/ss/list_rqs.c | 121 + krb5-1.21.3/src/util/ss/listen.c | 185 + krb5-1.21.3/src/util/ss/mit-sipb-copyright.h | 22 + krb5-1.21.3/src/util/ss/mk_cmds.sh | 29 + krb5-1.21.3/src/util/ss/pager.c | 110 + krb5-1.21.3/src/util/ss/parse.c | 171 + krb5-1.21.3/src/util/ss/prompt.c | 26 + krb5-1.21.3/src/util/ss/request_tbl.c | 66 + krb5-1.21.3/src/util/ss/requests.c | 47 + krb5-1.21.3/src/util/ss/ss.h | 72 + krb5-1.21.3/src/util/ss/ss_err.et | 39 + krb5-1.21.3/src/util/ss/ss_internal.h | 118 + krb5-1.21.3/src/util/ss/std_rqs.ct | 46 + krb5-1.21.3/src/util/ss/test_ss.c | 100 + krb5-1.21.3/src/util/support/Makefile.in | 279 + krb5-1.21.3/src/util/support/base64.c | 145 + krb5-1.21.3/src/util/support/bcmp.c | 44 + krb5-1.21.3/src/util/support/cache-addrinfo.h | 131 + krb5-1.21.3/src/util/support/deps | 116 + krb5-1.21.3/src/util/support/dir_filenames.c | 135 + krb5-1.21.3/src/util/support/errors.c | 122 + krb5-1.21.3/src/util/support/fake-addrinfo.c | 1343 + krb5-1.21.3/src/util/support/fnmatch.c | 207 + krb5-1.21.3/src/util/support/getopt.c | 151 + krb5-1.21.3/src/util/support/getopt_long.c | 232 + krb5-1.21.3/src/util/support/gettimeofday.c | 102 + krb5-1.21.3/src/util/support/gmt_mktime.c | 163 + krb5-1.21.3/src/util/support/hashtab.c | 252 + krb5-1.21.3/src/util/support/hex.c | 116 + krb5-1.21.3/src/util/support/init-addrinfo.c | 68 + krb5-1.21.3/src/util/support/ipc_stream.c | 468 + krb5-1.21.3/src/util/support/json.c | 1090 + krb5-1.21.3/src/util/support/k5buf.c | 275 + .../util/support/libkrb5support-fixed.exports | 99 + krb5-1.21.3/src/util/support/mkstemp.c | 138 + krb5-1.21.3/src/util/support/path.c | 161 + krb5-1.21.3/src/util/support/plugins.c | 598 + krb5-1.21.3/src/util/support/printf.c | 100 + krb5-1.21.3/src/util/support/secure_getenv.c | 111 + krb5-1.21.3/src/util/support/strerror_r.c | 97 + krb5-1.21.3/src/util/support/strlcpy.c | 88 + krb5-1.21.3/src/util/support/supp-int.h | 38 + krb5-1.21.3/src/util/support/t_base64.c | 110 + krb5-1.21.3/src/util/support/t_hashtab.c | 176 + krb5-1.21.3/src/util/support/t_hex.c | 169 + krb5-1.21.3/src/util/support/t_json.c | 329 + krb5-1.21.3/src/util/support/t_k5buf.c | 259 + krb5-1.21.3/src/util/support/t_path.c | 196 + krb5-1.21.3/src/util/support/t_unal.c | 46 + krb5-1.21.3/src/util/support/t_utf16.c | 117 + krb5-1.21.3/src/util/support/t_utf8.c | 209 + krb5-1.21.3/src/util/support/threads.c | 608 + krb5-1.21.3/src/util/support/utf8.c | 168 + krb5-1.21.3/src/util/support/utf8_conv.c | 200 + krb5-1.21.3/src/util/support/zap.c | 41 + krb5-1.21.3/src/util/t_array.pm | 130 + krb5-1.21.3/src/util/t_bimap.pm | 194 + krb5-1.21.3/src/util/t_enum.pm | 133 + krb5-1.21.3/src/util/t_template.pm | 61 + krb5-1.21.3/src/util/t_tsenum.pm | 163 + krb5-1.21.3/src/util/testrealm.py | 83 + krb5-1.21.3/src/util/trim-valgrind-logs | 71 + krb5-1.21.3/src/util/valgrind-suppressions | 85 + krb5-1.21.3/src/util/verto/Makefile.in | 50 + krb5-1.21.3/src/util/verto/README | 40 + krb5-1.21.3/src/util/verto/Symbols.ev | 73 + krb5-1.21.3/src/util/verto/deps | 10 + krb5-1.21.3/src/util/verto/ev.c | 5104 +++ krb5-1.21.3/src/util/verto/ev.h | 854 + krb5-1.21.3/src/util/verto/ev_poll.c | 148 + krb5-1.21.3/src/util/verto/ev_select.c | 314 + krb5-1.21.3/src/util/verto/ev_vars.h | 204 + krb5-1.21.3/src/util/verto/ev_win32.c | 162 + krb5-1.21.3/src/util/verto/ev_wrap.h | 200 + krb5-1.21.3/src/util/verto/libverto.exports | 33 + krb5-1.21.3/src/util/verto/module.c | 56 + krb5-1.21.3/src/util/verto/module.h | 84 + krb5-1.21.3/src/util/verto/verto-k5ev.c | 235 + krb5-1.21.3/src/util/verto/verto-libev.c | 204 + krb5-1.21.3/src/util/verto/verto-module.h | 188 + krb5-1.21.3/src/util/verto/verto.c | 1050 + krb5-1.21.3/src/util/verto/verto.h | 575 + krb5-1.21.3/src/util/windows/Makefile.in | 12 + krb5-1.21.3/src/util/windows/libecho.c | 77 + krb5-1.21.3/src/util/wsgiref-kdcproxy.py | 19 + krb5-1.21.3/src/wconfig.c | 231 + krb5-1.21.3/src/windows/Makefile.in | 6 + krb5-1.21.3/src/windows/README | 321 + krb5-1.21.3/src/windows/include/leasherr.h | 32 + krb5-1.21.3/src/windows/include/leashinfo.h | 2 + krb5-1.21.3/src/windows/include/leashwin.h | 212 + .../src/windows/include/loadfuncs-com_err.h | 44 + .../src/windows/include/loadfuncs-krb5.h | 1825 + .../src/windows/include/loadfuncs-leash.h | 377 + .../src/windows/include/loadfuncs-lsa.h | 45 + .../src/windows/include/loadfuncs-profile.h | 151 + krb5-1.21.3/src/windows/include/loadfuncs.h | 41 + .../windows/installer/wix/Binary/bannrbmp.bmp | Bin 0 -> 126054 bytes .../windows/installer/wix/Binary/completi.ico | Bin 0 -> 2998 bytes .../windows/installer/wix/Binary/custicon.ico | Bin 0 -> 2998 bytes .../windows/installer/wix/Binary/dlgbmp.bmp | Bin 0 -> 631822 bytes .../windows/installer/wix/Binary/exclamic.ico | Bin 0 -> 766 bytes .../src/windows/installer/wix/Binary/info.bmp | Bin 0 -> 1078 bytes .../windows/installer/wix/Binary/insticon.ico | Bin 0 -> 2998 bytes .../src/windows/installer/wix/Binary/new.bmp | Bin 0 -> 318 bytes .../windows/installer/wix/Binary/removico.ico | Bin 0 -> 2998 bytes .../windows/installer/wix/Binary/repairic.ico | Bin 0 -> 2998 bytes .../src/windows/installer/wix/Binary/up.bmp | Bin 0 -> 318 bytes .../src/windows/installer/wix/Makefile | 72 + .../src/windows/installer/wix/athena/krb5.ini | 7 + .../src/windows/installer/wix/config.wxi | 171 + .../windows/installer/wix/custom/custom.cpp | 833 + .../src/windows/installer/wix/custom/custom.h | 82 + .../src/windows/installer/wix/features.wxi | 176 + .../src/windows/installer/wix/files.wxi | 611 + krb5-1.21.3/src/windows/installer/wix/kfw.wxs | 283 + .../src/windows/installer/wix/krb5.ini | 0 .../installer/wix/lang/config_1033.wxi | 76 + .../windows/installer/wix/lang/license.rtf | 102 + .../installer/wix/lang/strings_1033.wxl | 70 + .../windows/installer/wix/lang/ui_1033.wxi | 1240 + .../installer/wix/msi-deployment-guide.txt | 846 + .../src/windows/installer/wix/platform.wxi | 175 + .../src/windows/installer/wix/property.wxi | 88 + .../src/windows/installer/wix/runtime.wxi | 17 + .../windows/installer/wix/runtime_debug.wxi | 14 + .../src/windows/installer/wix/site-local.wxi | 89 + krb5-1.21.3/src/windows/kerberos.ver | 58 + krb5-1.21.3/src/windows/kfwlogon/Makefile.in | 50 + krb5-1.21.3/src/windows/kfwlogon/kfwcommon.c | 1281 + krb5-1.21.3/src/windows/kfwlogon/kfwcpcc.c | 37 + krb5-1.21.3/src/windows/kfwlogon/kfwlogon.c | 623 + krb5-1.21.3/src/windows/kfwlogon/kfwlogon.def | 14 + krb5-1.21.3/src/windows/kfwlogon/kfwlogon.h | 215 + .../src/windows/leash/KrbListTickets.cpp | 389 + krb5-1.21.3/src/windows/leash/Leash.cpp | 1205 + krb5-1.21.3/src/windows/leash/Leash.h | 162 + krb5-1.21.3/src/windows/leash/Leash.rc | 767 + .../src/windows/leash/LeashAboutBox.cpp | 377 + krb5-1.21.3/src/windows/leash/LeashAboutBox.h | 82 + .../src/windows/leash/LeashDebugWindow.cpp | 187 + .../src/windows/leash/LeashDebugWindow.h | 78 + krb5-1.21.3/src/windows/leash/LeashDoc.cpp | 94 + krb5-1.21.3/src/windows/leash/LeashDoc.h | 66 + krb5-1.21.3/src/windows/leash/LeashFrame.cpp | 118 + krb5-1.21.3/src/windows/leash/LeashFrame.h | 50 + .../src/windows/leash/LeashMessageBox.cpp | 83 + .../src/windows/leash/LeashMessageBox.h | 70 + .../src/windows/leash/LeashUIApplication.cpp | 291 + .../src/windows/leash/LeashUIApplication.h | 86 + .../windows/leash/LeashUICommandHandler.cpp | 267 + .../src/windows/leash/LeashUICommandHandler.h | 72 + krb5-1.21.3/src/windows/leash/LeashView.cpp | 2480 ++ krb5-1.21.3/src/windows/leash/LeashView.h | 339 + krb5-1.21.3/src/windows/leash/Lglobals.h | 191 + krb5-1.21.3/src/windows/leash/MainFrm.cpp | 464 + krb5-1.21.3/src/windows/leash/MainFrm.h | 103 + krb5-1.21.3/src/windows/leash/Makefile.in | 70 + krb5-1.21.3/src/windows/leash/StdAfx.cpp | 5 + krb5-1.21.3/src/windows/leash/StdAfx.h | 30 + .../leash/htmlhelp/Images/Change_Password.PNG | Bin 0 -> 4199 bytes .../leash/htmlhelp/Images/Destroy_Ticket.PNG | Bin 0 -> 2489 bytes .../leash/htmlhelp/Images/Get_Ticket.PNG | Bin 0 -> 2040 bytes .../leash/htmlhelp/Images/Home_Tab.PNG | Bin 0 -> 13574 bytes .../leash/htmlhelp/Images/Make_Default.PNG | Bin 0 -> 2902 bytes .../leash/htmlhelp/Images/Options_Tab.PNG | Bin 0 -> 13924 bytes .../leash/htmlhelp/Images/Renew_Ticket.PNG | Bin 0 -> 2440 bytes .../leash/htmlhelp/Images/checkbox.png | Bin 0 -> 619 bytes .../src/windows/leash/htmlhelp/Index.hhk | 444 + .../src/windows/leash/htmlhelp/Leash.css | 215 + .../leash/htmlhelp/MITKerberosHelp.hhp | 106 + .../src/windows/leash/htmlhelp/Makefile.in | 20 + .../src/windows/leash/htmlhelp/TOC.hhc | 188 + .../leash/htmlhelp/html/Change_Password.htm | 51 + .../leash/htmlhelp/html/Command_Line.htm | 26 + .../windows/leash/htmlhelp/html/Debugging.htm | 17 + .../leash/htmlhelp/html/Destroy_Tickets.htm | 63 + .../leash/htmlhelp/html/Encryption_Types.htm | 139 + .../src/windows/leash/htmlhelp/html/FAQ.htm | 104 + .../leash/htmlhelp/html/Forget_Password.htm | 23 + .../leash/htmlhelp/html/Forget_Principals.htm | 50 + .../leash/htmlhelp/html/Get_Tickets.htm | 60 + .../leash/htmlhelp/html/Getting_Started.htm | 117 + .../windows/leash/htmlhelp/html/Glossary.htm | 72 + .../windows/leash/htmlhelp/html/Home_Tab.htm | 83 + .../htmlhelp/html/How_Kerberos_Works.htm | 24 + .../windows/leash/htmlhelp/html/KCPYTKT.htm | 83 + .../windows/leash/htmlhelp/html/KDESTROY.htm | 108 + .../src/windows/leash/htmlhelp/html/KINIT.htm | 193 + .../src/windows/leash/htmlhelp/html/KLIST.htm | 149 + .../windows/leash/htmlhelp/html/KPASSWD.htm | 55 + .../windows/leash/htmlhelp/html/KSWITCH.htm | 80 + .../src/windows/leash/htmlhelp/html/KVNO.htm | 104 + .../windows/leash/htmlhelp/html/Kerberos.htm | 76 + .../htmlhelp/html/Kerberos_Terminology.htm | 105 + .../htmlhelp/html/Keyboard_Shortcuts.htm | 41 + .../windows/leash/htmlhelp/html/MS2MIT.htm | 33 + .../leash/htmlhelp/html/Make_Default.htm | 40 + .../html/Manage_Multiple_Principals.htm | 87 + .../leash/htmlhelp/html/Options_Tab.htm | 181 + .../leash/htmlhelp/html/Password_Tips.htm | 51 + .../windows/leash/htmlhelp/html/Passwords.htm | 63 + .../leash/htmlhelp/html/Principals.htm | 69 + .../leash/htmlhelp/html/Renew_Tickets.htm | 109 + .../leash/htmlhelp/html/Renew_Tickets2.html | 32 + .../leash/htmlhelp/html/Report_Bugs.htm | 23 + .../leash/htmlhelp/html/Ticket_Settings.htm | 175 + .../windows/leash/htmlhelp/html/Tickets.htm | 139 + .../leash/htmlhelp/html/Troubleshooting.htm | 80 + .../leash/htmlhelp/html/Using_Leash_Menus.htm | 136 + .../leash/htmlhelp/html/View_Tickets.htm | 123 + krb5-1.21.3/src/windows/leash/kfwribbon.xml | 135 + krb5-1.21.3/src/windows/leash/reminder.h | 12 + krb5-1.21.3/src/windows/leash/res/Leash.ico | Bin 0 -> 9662 bytes krb5-1.21.3/src/windows/leash/res/Leash.rc2 | 14 + krb5-1.21.3/src/windows/leash/res/Leash2.ico | Bin 0 -> 766 bytes .../src/windows/leash/res/Leash_Doc.ico | Bin 0 -> 25214 bytes .../windows/leash/res/Leash_tickets_green.ico | Bin 0 -> 25214 bytes .../leash/res/Leash_tickets_orange.ico | Bin 0 -> 25214 bytes .../windows/leash/res/Leash_tickets_out.ico | Bin 0 -> 25214 bytes .../windows/leash/res/Leash_tickets_red.ico | Bin 0 -> 25214 bytes .../src/windows/leash/res/Leash_tkt_green.ico | Bin 0 -> 25214 bytes .../windows/leash/res/Leash_tkt_orange.ico | Bin 0 -> 25214 bytes .../src/windows/leash/res/Leash_tkt_red.ico | Bin 0 -> 25214 bytes .../src/windows/leash/res/Leash_toolbar.bmp | Bin 0 -> 1270 bytes .../windows/leash/res/Leash_user_green.ico | Bin 0 -> 25214 bytes .../windows/leash/res/Leash_user_orange.ico | Bin 0 -> 25214 bytes .../src/windows/leash/res/Leash_user_out.ico | Bin 0 -> 25214 bytes .../src/windows/leash/res/Leash_user_red.ico | Bin 0 -> 25214 bytes krb5-1.21.3/src/windows/leash/res/address.ico | Bin 0 -> 25214 bytes .../src/windows/leash/res/cpwlarge.bmp | Bin 0 -> 4152 bytes krb5-1.21.3/src/windows/leash/res/cursor1.cur | Bin 0 -> 326 bytes krb5-1.21.3/src/windows/leash/res/destroy.ico | Bin 0 -> 2862 bytes .../windows/leash/res/destroy_disabled.ico | Bin 0 -> 2862 bytes .../src/windows/leash/res/destroylarge.bmp | Bin 0 -> 4152 bytes .../src/windows/leash/res/encryption.ico | Bin 0 -> 25214 bytes .../src/windows/leash/res/exportlarge.bmp | Bin 0 -> 4152 bytes .../src/windows/leash/res/getticketlarge.bmp | Bin 0 -> 4152 bytes krb5-1.21.3/src/windows/leash/res/import.bmp | Bin 0 -> 3126 bytes .../src/windows/leash/res/importlarge.bmp | Bin 0 -> 4152 bytes krb5-1.21.3/src/windows/leash/res/key.ico | Bin 0 -> 25214 bytes .../windows/leash/res/makedefaultlarge.bmp | Bin 0 -> 4152 bytes krb5-1.21.3/src/windows/leash/res/new.ico | Bin 0 -> 2862 bytes .../src/windows/leash/res/new_disabled.ico | Bin 0 -> 198 bytes .../src/windows/leash/res/newlarge.bmp | Bin 0 -> 4152 bytes .../src/windows/leash/res/openlarge.bmp | Bin 0 -> 4152 bytes .../src/windows/leash/res/password.ico | Bin 0 -> 2862 bytes .../windows/leash/res/password_disabled.ico | Bin 0 -> 198 bytes krb5-1.21.3/src/windows/leash/res/refresh.ico | Bin 0 -> 2862 bytes .../windows/leash/res/refresh_disabled.ico | Bin 0 -> 198 bytes krb5-1.21.3/src/windows/leash/res/renew.ico | Bin 0 -> 2862 bytes .../src/windows/leash/res/renew_disabled.ico | Bin 0 -> 2862 bytes .../src/windows/leash/res/renewlarge.bmp | Bin 0 -> 4152 bytes .../src/windows/leash/res/status_grayK.ico | Bin 0 -> 1218 bytes .../src/windows/leash/res/status_greenK.ico | Bin 0 -> 1218 bytes .../src/windows/leash/res/status_redK.ico | Bin 0 -> 1218 bytes .../src/windows/leash/res/status_yelloK.ico | Bin 0 -> 1218 bytes krb5-1.21.3/src/windows/leash/res/sync.ico | Bin 0 -> 2862 bytes .../src/windows/leash/res/sync_disabled.ico | Bin 0 -> 198 bytes krb5-1.21.3/src/windows/leash/resource.h | 322 + krb5-1.21.3/src/windows/leash/ver.rc | 3 + krb5-1.21.3/src/windows/leashdll/Makefile.in | 58 + .../src/windows/leashdll/krb5routines.c | 838 + krb5-1.21.3/src/windows/leashdll/leash-int.h | 271 + krb5-1.21.3/src/windows/leashdll/leashdll.c | 354 + krb5-1.21.3/src/windows/leashdll/leashdll.h | 182 + krb5-1.21.3/src/windows/leashdll/leasherr.c | 105 + krb5-1.21.3/src/windows/leashdll/leasherr.et | 22 + krb5-1.21.3/src/windows/leashdll/leashids.h | 116 + krb5-1.21.3/src/windows/leashdll/leashw32.def | 74 + krb5-1.21.3/src/windows/leashdll/lsh_pwd.c | 1895 + krb5-1.21.3/src/windows/leashdll/lsh_pwd.rc | 249 + krb5-1.21.3/src/windows/leashdll/lshfunc.c | 2684 ++ krb5-1.21.3/src/windows/leashdll/lshutil.cpp | 596 + krb5-1.21.3/src/windows/leashdll/reminder.h | 12 + .../src/windows/leashdll/res/islogo.bmp | Bin 0 -> 20118 bytes .../src/windows/leashdll/res/leash.ico | Bin 0 -> 9662 bytes krb5-1.21.3/src/windows/leashdll/resource.h | 19 + krb5-1.21.3/src/windows/leashdll/timesync.c | 292 + krb5-1.21.3/src/windows/leashdll/ver.rc | 4 + krb5-1.21.3/src/windows/leashdll/winerr.c | 78 + krb5-1.21.3/src/windows/leashdll/winutil.c | 138 + krb5-1.21.3/src/windows/lib/Makefile.in | 21 + krb5-1.21.3/src/windows/lib/cacheapi.h | 392 + krb5-1.21.3/src/windows/lib/loadfuncs.c | 88 + krb5-1.21.3/src/windows/ms2mit/Makefile.in | 39 + krb5-1.21.3/src/windows/ms2mit/mit2ms.c | 143 + krb5-1.21.3/src/windows/ms2mit/ms2mit.c | 201 + krb5-1.21.3/src/windows/version.rc | 318 + krb5-1.21.3/src/windows/winlevel.h | 31 + 4460 files changed, 948855 insertions(+), 1 deletion(-) create mode 100644 krb5-1.21.3/.github/workflows/build.yml create mode 100644 krb5-1.21.3/.github/workflows/doc.yml create mode 100644 krb5-1.21.3/NOTICE create mode 100644 krb5-1.21.3/README create mode 100644 krb5-1.21.3/doc/README create mode 100644 krb5-1.21.3/doc/_static/kerb.css_t create mode 100644 krb5-1.21.3/doc/_templates/layout.html create mode 100644 krb5-1.21.3/doc/about.rst create mode 100644 krb5-1.21.3/doc/admin/admin_commands/index.rst create mode 100644 krb5-1.21.3/doc/admin/admin_commands/k5srvutil.rst create mode 100644 krb5-1.21.3/doc/admin/admin_commands/kadmin_local.rst create mode 100644 krb5-1.21.3/doc/admin/admin_commands/kadmind.rst create mode 100644 krb5-1.21.3/doc/admin/admin_commands/kdb5_ldap_util.rst create mode 100644 krb5-1.21.3/doc/admin/admin_commands/kdb5_util.rst create mode 100644 krb5-1.21.3/doc/admin/admin_commands/kprop.rst create mode 100644 krb5-1.21.3/doc/admin/admin_commands/kpropd.rst create mode 100644 krb5-1.21.3/doc/admin/admin_commands/kproplog.rst create mode 100644 krb5-1.21.3/doc/admin/admin_commands/krb5kdc.rst create mode 100644 krb5-1.21.3/doc/admin/admin_commands/ktutil.rst create mode 100644 krb5-1.21.3/doc/admin/admin_commands/sserver.rst create mode 100644 krb5-1.21.3/doc/admin/advanced/index.rst create mode 100644 krb5-1.21.3/doc/admin/advanced/retiring-des.rst create mode 100644 krb5-1.21.3/doc/admin/appl_servers.rst create mode 100644 krb5-1.21.3/doc/admin/auth_indicator.rst create mode 100644 krb5-1.21.3/doc/admin/backup_host.rst create mode 100644 krb5-1.21.3/doc/admin/conf_files/index.rst create mode 100644 krb5-1.21.3/doc/admin/conf_files/kadm5_acl.rst create mode 100644 krb5-1.21.3/doc/admin/conf_files/kdc_conf.rst create mode 100644 krb5-1.21.3/doc/admin/conf_files/krb5_conf.rst create mode 100644 krb5-1.21.3/doc/admin/conf_ldap.rst create mode 100644 krb5-1.21.3/doc/admin/database.rst create mode 100644 krb5-1.21.3/doc/admin/dbtypes.rst create mode 100644 krb5-1.21.3/doc/admin/dictionary.rst create mode 100644 krb5-1.21.3/doc/admin/enctypes.rst create mode 100644 krb5-1.21.3/doc/admin/env_variables.rst create mode 100644 krb5-1.21.3/doc/admin/host_config.rst create mode 100644 krb5-1.21.3/doc/admin/https.rst create mode 100644 krb5-1.21.3/doc/admin/index.rst create mode 100644 krb5-1.21.3/doc/admin/install.rst create mode 100644 krb5-1.21.3/doc/admin/install_appl_srv.rst create mode 100644 krb5-1.21.3/doc/admin/install_clients.rst create mode 100644 krb5-1.21.3/doc/admin/install_kdc.rst create mode 100644 krb5-1.21.3/doc/admin/lockout.rst create mode 100644 krb5-1.21.3/doc/admin/otp.rst create mode 100644 krb5-1.21.3/doc/admin/pkinit.rst create mode 100644 krb5-1.21.3/doc/admin/princ_dns.rst create mode 100644 krb5-1.21.3/doc/admin/realm_config.rst create mode 100644 krb5-1.21.3/doc/admin/spake.rst create mode 100644 krb5-1.21.3/doc/admin/troubleshoot.rst create mode 100644 krb5-1.21.3/doc/admin/various_envs.rst create mode 100644 krb5-1.21.3/doc/appdev/gssapi.rst create mode 100644 krb5-1.21.3/doc/appdev/h5l_mit_apidiff.rst create mode 100644 krb5-1.21.3/doc/appdev/index.rst create mode 100644 krb5-1.21.3/doc/appdev/init_creds.rst create mode 100644 krb5-1.21.3/doc/appdev/princ_handle.rst create mode 100644 krb5-1.21.3/doc/appdev/refs/api/index.rst create mode 100644 krb5-1.21.3/doc/appdev/refs/index.rst create mode 100644 krb5-1.21.3/doc/appdev/refs/macros/index.rst create mode 100644 krb5-1.21.3/doc/appdev/refs/types/index.rst create mode 100644 krb5-1.21.3/doc/appdev/refs/types/krb5_int32.rst create mode 100644 krb5-1.21.3/doc/appdev/refs/types/krb5_ui_4.rst create mode 100644 krb5-1.21.3/doc/appdev/y2038.rst create mode 100644 krb5-1.21.3/doc/basic/ccache_def.rst create mode 100644 krb5-1.21.3/doc/basic/date_format.rst create mode 100644 krb5-1.21.3/doc/basic/index.rst create mode 100644 krb5-1.21.3/doc/basic/keytab_def.rst create mode 100644 krb5-1.21.3/doc/basic/rcache_def.rst create mode 100644 krb5-1.21.3/doc/basic/stash_file_def.rst create mode 100644 krb5-1.21.3/doc/build/directory_org.rst create mode 100644 krb5-1.21.3/doc/build/doing_build.rst create mode 100644 krb5-1.21.3/doc/build/index.rst create mode 100644 krb5-1.21.3/doc/build/options2configure.rst create mode 100644 krb5-1.21.3/doc/build/osconf.rst create mode 100644 krb5-1.21.3/doc/build_this.rst create mode 100644 krb5-1.21.3/doc/coding-style create mode 100644 krb5-1.21.3/doc/conf.py create mode 100644 krb5-1.21.3/doc/contributing.txt create mode 100644 krb5-1.21.3/doc/copyright.rst create mode 100644 krb5-1.21.3/doc/doxy_examples/cc_set_config.c create mode 100644 krb5-1.21.3/doc/doxy_examples/cc_unique.c create mode 100755 krb5-1.21.3/doc/doxy_examples/error_message.c create mode 100644 krb5-1.21.3/doc/doxy_examples/tkt_creds.c create mode 100644 krb5-1.21.3/doc/doxy_examples/verify_init_creds.c create mode 100644 krb5-1.21.3/doc/formats/ccache_file_format.rst create mode 100644 krb5-1.21.3/doc/formats/cookie.rst create mode 100644 krb5-1.21.3/doc/formats/freshness_token.rst create mode 100644 krb5-1.21.3/doc/formats/index.rst create mode 100644 krb5-1.21.3/doc/formats/keytab_file_format.rst create mode 100644 krb5-1.21.3/doc/formats/rcache_file_format.rst create mode 100644 krb5-1.21.3/doc/html/.buildinfo create mode 100644 krb5-1.21.3/doc/html/_sources/about.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/admin_commands/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/admin_commands/k5srvutil.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/admin_commands/kadmin_local.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/admin_commands/kadmind.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/admin_commands/kdb5_ldap_util.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/admin_commands/kdb5_util.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/admin_commands/kprop.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/admin_commands/kpropd.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/admin_commands/kproplog.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/admin_commands/krb5kdc.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/admin_commands/ktutil.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/admin_commands/sserver.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/advanced/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/advanced/retiring-des.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/appl_servers.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/auth_indicator.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/backup_host.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/conf_files/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/conf_files/kadm5_acl.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/conf_files/kdc_conf.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/conf_files/krb5_conf.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/conf_ldap.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/database.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/dbtypes.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/dictionary.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/enctypes.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/env_variables.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/host_config.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/https.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/install.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/install_appl_srv.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/install_clients.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/install_kdc.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/lockout.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/otp.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/pkinit.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/princ_dns.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/realm_config.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/spake.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/troubleshoot.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/admin/various_envs.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/gssapi.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/h5l_mit_apidiff.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/init_creds.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/princ_handle.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_425_conv_principal.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_524_conv_principal.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_524_convert_creds.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_address_compare.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_address_order.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_address_search.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_allow_weak_crypto.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_aname_to_localname.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_anonymous_principal.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_anonymous_realm.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_appdefault_boolean.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_appdefault_string.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_free.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_genaddrs.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_get_checksum_func.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getaddrs.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getauthenticator.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getflags.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getkey.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getkey_k.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getlocalseqnumber.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getlocalsubkey.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getrcache.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getrecvsubkey.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getrecvsubkey_k.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getremoteseqnumber.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getremotesubkey.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getsendsubkey.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getsendsubkey_k.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_init.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_initivector.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_set_checksum_func.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_set_req_cksumtype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setaddrs.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setflags.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setports.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setrcache.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setrecvsubkey.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setrecvsubkey_k.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setsendsubkey.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setsendsubkey_k.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setuseruserkey.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal_alloc_va.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal_ext.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal_va.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_block_size.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_checksum_length.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_crypto_length.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_crypto_length_iov.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_decrypt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_decrypt_iov.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_derive_prfplus.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_encrypt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_encrypt_iov.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_encrypt_length.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_enctype_compare.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_free_state.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_fx_cf2_simple.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_init_state.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_is_coll_proof_cksum.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_is_keyed_cksum.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_keyed_checksum_types.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_keylengths.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_make_checksum.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_make_checksum_iov.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_make_random_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_padding_length.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_prf.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_prf_length.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_prfplus.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_add_entropy.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_make_octets.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_os_entropy.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_seed.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_to_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_string_to_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_string_to_key_with_params.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_valid_cksumtype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_valid_enctype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_verify_checksum.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_verify_checksum_iov.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_calculate_checksum.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_cache_match.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_close.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_copy_creds.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_default.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_default_name.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_destroy.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_dup.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_end_seq_get.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_gen_new.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_config.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_flags.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_full_name.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_name.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_principal.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_type.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_initialize.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_move.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_new_unique.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_next_cred.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_remove_cred.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_resolve.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_retrieve_cred.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_select.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_set_config.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_set_default_name.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_set_flags.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_start_seq_get.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_store_cred.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_support_switch.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_switch.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_cursor_free.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_cursor_new.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_cursor_next.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_have_content.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_change_password.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_check_clockskew.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_checksum_size.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_chpw_message.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cksumtype_to_string.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_clear_error_message.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_addresses.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_authdata.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_authenticator.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_checksum.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_context.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_creds.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_data.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_error_message.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_keyblock.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_keyblock_contents.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_principal.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_ticket.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_decode_authdata_container.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_decode_ticket.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_decrypt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_deltat_to_string.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_eblock_enctype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_encode_authdata_container.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_encrypt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_encrypt_size.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_enctype_to_name.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_enctype_to_string.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_expand_hostname.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_find_authdata.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_finish_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_finish_random_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_addresses.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_ap_rep_enc_part.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_authdata.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_authenticator.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_checksum.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_checksum_contents.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_cksumtypes.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_context.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_cred_contents.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_creds.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_data.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_data_contents.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_default_realm.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_enctypes.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_error.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_error_message.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_host_realm.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_keyblock.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_keyblock_contents.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_keytab_entry_contents.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_principal.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_string.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_tgt_creds.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_ticket.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_unparsed_name.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_fwd_tgt_creds.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_credentials.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_credentials_renew.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_credentials_validate.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_default_realm.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_error_message.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_etype_info.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_fallback_host_realm.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_host_realm.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_in_tkt_with_keytab.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_in_tkt_with_password.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_in_tkt_with_skey.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_keytab.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_alloc.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_free.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_get_fast_flags.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_init.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_address_list.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_anonymous.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_canonicalize.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_change_password_prompt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_etype_list.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_expire_callback.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache_name.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_fast_flags.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_forwardable.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_in_ccache.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_out_ccache.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_pa.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_pac_request.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_preauth_list.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_proxiable.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_renew_life.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_responder.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_salt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_tkt_life.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_password.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_permitted_enctypes.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_profile.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_prompt_types.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_renewed_creds.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_server_rcache.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_time_offsets.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_validated_creds.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_context.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_context_profile.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_free.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get_creds.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get_error.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get_times.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_init.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_set_keytab.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_set_password.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_set_service.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_step.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_keyblock.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_random_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_secure_context.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_is_config_principal.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_is_referral_realm.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_is_thread_safe.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_create_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_decrypt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_decrypt_iov.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_encrypt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_encrypt_iov.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_free_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_key_enctype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_key_keyblock.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_make_checksum.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_make_checksum_iov.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_prf.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_reference_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_verify_checksum.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_verify_checksum_iov.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kdc_sign_ticket.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kdc_verify_ticket.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_add_entry.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_client_default.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_close.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_default.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_default_name.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_dup.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_end_seq_get.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_free_entry.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_get_entry.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_get_name.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_get_type.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_have_content.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_next_entry.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_read_service_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_remove_entry.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_resolve.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_start_seq_get.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kuserok.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_make_authdata_kdc_issued.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_marshal_credentials.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_merge_authdata.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_1cred.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_error.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_ncred.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_priv.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_rep.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_rep_dce.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_req.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_req_extended.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_safe.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_os_localaddr.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_add_buffer.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_free.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_get_buffer.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_get_client_info.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_get_types.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_init.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_parse.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_sign.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_sign_ext.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_verify.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_verify_ext.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_parse_name.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_parse_name_flags.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_prepend_error_message.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal2salt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal_compare.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal_compare_any_realm.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal_compare_flags.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_process_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_prompter_posix.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_random_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_cred.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_error.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_priv.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_rep.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_rep_dce.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_req.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_safe.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_read_password.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_realm_compare.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_recvauth.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_recvauth_version.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_get_challenge.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_list_questions.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_otp_challenge_free.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_otp_get_challenge.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_otp_set_answer.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_pkinit_challenge_free.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_pkinit_get_challenge.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_pkinit_set_answer.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_set_answer.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_salttype_to_string.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_sendauth.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_server_decrypt_ticket_keytab.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_default_realm.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_default_tgs_enctypes.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_error_message.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_kdc_recv_hook.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_kdc_send_hook.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_password.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_password_using_ccache.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_principal_realm.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_real_time.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_trace_callback.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_trace_filename.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_sname_match.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_sname_to_principal.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_cksumtype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_deltat.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_enctype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_salttype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_timestamp.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_timeofday.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_timestamp_to_sfstring.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_timestamp_to_string.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_free.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_get.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_get_creds.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_get_times.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_init.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_step.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unmarshal_credentials.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name_ext.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name_flags.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name_flags_ext.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_us_timeofday.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_use_enctype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_authdata_kdc_issued.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_checksum.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_init_creds.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_init_creds_opt_init.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_vprepend_error_message.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_vset_error_message.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_vwrap_error_message.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_wrap_error_message.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_ADDRPORT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_CHAOS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_DDP.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_INET.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_INET6.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_IPPORT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_ISO.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_IS_LOCAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_NETBIOS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_XNS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_EXTERNAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_REGISTERED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_RESERVED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_RESERVED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_USE_SESSION_KEY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_USE_SUBKEY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_WIRE_MASK.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_CRC32.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_DESCBC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_NIST_SHA.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD4.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD5.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_SHA1.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_ENV.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_RAW.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_CRC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_MD4.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_MD5.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_RAW.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_MD5_RSA_CMS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_NULL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_RC2_CBC_ENV.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_RSA_ENV.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_UNKNOWN.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_CANONICALIZE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_FORWARDABLE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_FORWARDED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_POSTDATED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_PROXIABLE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_PROXY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_RENEW.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_RENEWABLE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_RENEWABLE_OK.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_VALIDATE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_TKT_COMMON_MASK.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AP_REP.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AP_REQ.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AS_REP.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AS_REQ.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_AND_OR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_CAMMAC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_SESAME.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CYBERSAFE_SECUREID.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ERROR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_FAST_REQUIRED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_CACHED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_CANONICALIZE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_FORWARDABLE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_NO_STORE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_USER_USER.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INIT_CONTEXT_KDC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT16_MAX.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT16_MIN.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT32_MAX.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT32_MIN.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_SPAKE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_AUTHERROR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_HARDERROR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_MALFORMED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_SOFTERROR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_SUCCESS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_NONE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_PRINCIPAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SMTP_NAME.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SRV_HST.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SRV_INST.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SRV_XHST.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_UID.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_UNKNOWN.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_WELLKNOWN.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_X500_PRINCIPAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_CLIENT_INFO.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_DELEGATION_INFO.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_DEVICE_INFO.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_LOGON_INFO.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_REQUESTOR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AFS3_SALT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AP_REQ.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FOR_USER.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FX_COOKIE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FX_ERROR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FX_FAST.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_NONE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OSF_DCE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OTP_REQUEST.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PAC_REQUEST.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PKINIT_KX.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REP.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PW_SALT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_REFERRAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_S4U_X509_USER.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SESAME.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SPAKE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_TGS_REQ.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRIV.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PVNO.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_REALM_BRANCH_CHAR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_REFERRAL_REALM.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAFE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_FLAGS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_KTYPE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_TIMES.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_NOTICKET.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_OPENCLOSE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_NAME.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_NAME_SIZE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_REP.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_REQ.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/MAX_KEYTAB_NAME_LEN.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/MSEC_DIRBIT.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/MSEC_VAL_MASK.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/SALT_TYPE_AFS_LENGTH.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/SALT_TYPE_NO_LENGTH.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/THREEPARAMOPEN.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_ANONYMOUS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_ENC_PA_REP.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_FORWARDABLE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_FORWARDED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_HW_AUTH.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_INITIAL.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_INVALID.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_MAY_POSTDATE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_POSTDATED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_PRE_AUTH.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_PROXIABLE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_PROXY.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_RENEWABLE.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/VALID_INT_BITS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/VALID_UINT_BITS.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb524_convert_creds_kdc.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb524_init_ets.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_const.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_component.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_name.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_realm.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_set_realm.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_set_realm_data.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_set_realm_length.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_size.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_type.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_roundup.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_x.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_xc.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_address.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_addrtype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ap_rep.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ap_rep_enc_part.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ap_req.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_auth_context.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_authdata.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_authdatatype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_authenticator.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_boolean.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cc_cursor.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ccache.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cccol_cursor.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_checksum.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cksumtype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_const_pointer.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_const_principal.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_context.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cred.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cred_enc_part.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cred_info.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_creds.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_crypto_iov.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cryptotype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_data.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_deltat.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enc_data.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enc_kdc_rep_part.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enc_tkt_part.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_encrypt_block.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enctype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_error.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_error_code.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_expire_callback_func.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_flags.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_get_init_creds_opt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_gic_opt_pa_data.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_init_creds_context.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_int16.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_int32.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kdc_rep.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kdc_req.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_key.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keyblock.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keytab.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keytab_entry.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keyusage.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kt_cursor.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kvno.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_last_req_entry.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_magic.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_mk_req_checksum_func.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_msgtype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_octet.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_data.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_pac_req.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_server_referral_data.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_svr_referral_data.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pac.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pointer.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_post_recv_fn.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pre_send_fn.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_preauthtype.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_principal.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_principal_data.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_prompt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_prompt_type.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_prompter_fct.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pwd_data.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_rcache.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_replay_data.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_context.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_fn.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_otp_challenge.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_otp_tokeninfo.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_pkinit_challenge.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_pkinit_identity.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_response.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ticket.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ticket_times.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_timestamp.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_tkt_authent.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_tkt_creds_context.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_trace_callback.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_trace_info.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_transited.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_typed_data.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ui_2.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ui_4.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_verify_init_creds_opt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/refs/types/passwd_phrase_element.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/appdev/y2038.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/basic/ccache_def.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/basic/date_format.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/basic/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/basic/keytab_def.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/basic/rcache_def.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/basic/stash_file_def.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/build/directory_org.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/build/doing_build.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/build/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/build/options2configure.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/build/osconf.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/build_this.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/copyright.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/formats/ccache_file_format.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/formats/cookie.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/formats/freshness_token.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/formats/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/formats/keytab_file_format.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/formats/rcache_file_format.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/mitK5defaults.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/mitK5features.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/mitK5license.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/ccselect.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/certauth.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/clpreauth.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/general.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/gssapi.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/hostrealm.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/internal.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/kadm5_auth.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/kadm5_hook.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/kdcpolicy.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/kdcpreauth.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/localauth.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/locate.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/profile.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/plugindev/pwqual.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/resources.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/pwd_mgmt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/tkt_mgmt.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_commands/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_commands/kdestroy.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_commands/kinit.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_commands/klist.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_commands/kpasswd.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_commands/krb5-config.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_commands/ksu.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_commands/kswitch.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_commands/kvno.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_commands/sclient.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_config/index.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_config/k5identity.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_config/k5login.rst.txt create mode 100644 krb5-1.21.3/doc/html/_sources/user/user_config/kerberos.rst.txt create mode 100644 krb5-1.21.3/doc/html/_static/agogo.css create mode 100644 krb5-1.21.3/doc/html/_static/basic.css create mode 100644 krb5-1.21.3/doc/html/_static/bgfooter.png create mode 100644 krb5-1.21.3/doc/html/_static/bgtop.png create mode 100644 krb5-1.21.3/doc/html/_static/doctools.js create mode 100644 krb5-1.21.3/doc/html/_static/documentation_options.js create mode 100644 krb5-1.21.3/doc/html/_static/file.png create mode 100644 krb5-1.21.3/doc/html/_static/jquery.js create mode 100644 krb5-1.21.3/doc/html/_static/kerb.css create mode 100644 krb5-1.21.3/doc/html/_static/language_data.js create mode 100644 krb5-1.21.3/doc/html/_static/minus.png create mode 100644 krb5-1.21.3/doc/html/_static/plus.png create mode 100644 krb5-1.21.3/doc/html/_static/pygments.css create mode 100644 krb5-1.21.3/doc/html/_static/searchtools.js create mode 100644 krb5-1.21.3/doc/html/_static/underscore.js create mode 100644 krb5-1.21.3/doc/html/about.html create mode 100644 krb5-1.21.3/doc/html/admin/admin_commands/index.html create mode 100644 krb5-1.21.3/doc/html/admin/admin_commands/k5srvutil.html create mode 100644 krb5-1.21.3/doc/html/admin/admin_commands/kadmin_local.html create mode 100644 krb5-1.21.3/doc/html/admin/admin_commands/kadmind.html create mode 100644 krb5-1.21.3/doc/html/admin/admin_commands/kdb5_ldap_util.html create mode 100644 krb5-1.21.3/doc/html/admin/admin_commands/kdb5_util.html create mode 100644 krb5-1.21.3/doc/html/admin/admin_commands/kprop.html create mode 100644 krb5-1.21.3/doc/html/admin/admin_commands/kpropd.html create mode 100644 krb5-1.21.3/doc/html/admin/admin_commands/kproplog.html create mode 100644 krb5-1.21.3/doc/html/admin/admin_commands/krb5kdc.html create mode 100644 krb5-1.21.3/doc/html/admin/admin_commands/ktutil.html create mode 100644 krb5-1.21.3/doc/html/admin/admin_commands/sserver.html create mode 100644 krb5-1.21.3/doc/html/admin/advanced/index.html create mode 100644 krb5-1.21.3/doc/html/admin/advanced/retiring-des.html create mode 100644 krb5-1.21.3/doc/html/admin/appl_servers.html create mode 100644 krb5-1.21.3/doc/html/admin/auth_indicator.html create mode 100644 krb5-1.21.3/doc/html/admin/backup_host.html create mode 100644 krb5-1.21.3/doc/html/admin/conf_files/index.html create mode 100644 krb5-1.21.3/doc/html/admin/conf_files/kadm5_acl.html create mode 100644 krb5-1.21.3/doc/html/admin/conf_files/kdc_conf.html create mode 100644 krb5-1.21.3/doc/html/admin/conf_files/krb5_conf.html create mode 100644 krb5-1.21.3/doc/html/admin/conf_ldap.html create mode 100644 krb5-1.21.3/doc/html/admin/database.html create mode 100644 krb5-1.21.3/doc/html/admin/dbtypes.html create mode 100644 krb5-1.21.3/doc/html/admin/dictionary.html create mode 100644 krb5-1.21.3/doc/html/admin/enctypes.html create mode 100644 krb5-1.21.3/doc/html/admin/env_variables.html create mode 100644 krb5-1.21.3/doc/html/admin/host_config.html create mode 100644 krb5-1.21.3/doc/html/admin/https.html create mode 100644 krb5-1.21.3/doc/html/admin/index.html create mode 100644 krb5-1.21.3/doc/html/admin/install.html create mode 100644 krb5-1.21.3/doc/html/admin/install_appl_srv.html create mode 100644 krb5-1.21.3/doc/html/admin/install_clients.html create mode 100644 krb5-1.21.3/doc/html/admin/install_kdc.html create mode 100644 krb5-1.21.3/doc/html/admin/lockout.html create mode 100644 krb5-1.21.3/doc/html/admin/otp.html create mode 100644 krb5-1.21.3/doc/html/admin/pkinit.html create mode 100644 krb5-1.21.3/doc/html/admin/princ_dns.html create mode 100644 krb5-1.21.3/doc/html/admin/realm_config.html create mode 100644 krb5-1.21.3/doc/html/admin/spake.html create mode 100644 krb5-1.21.3/doc/html/admin/troubleshoot.html create mode 100644 krb5-1.21.3/doc/html/admin/various_envs.html create mode 100644 krb5-1.21.3/doc/html/appdev/gssapi.html create mode 100644 krb5-1.21.3/doc/html/appdev/h5l_mit_apidiff.html create mode 100644 krb5-1.21.3/doc/html/appdev/index.html create mode 100644 krb5-1.21.3/doc/html/appdev/init_creds.html create mode 100644 krb5-1.21.3/doc/html/appdev/princ_handle.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/index.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_425_conv_principal.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_524_conv_principal.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_524_convert_creds.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_address_compare.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_address_order.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_address_search.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_allow_weak_crypto.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_aname_to_localname.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_anonymous_principal.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_anonymous_realm.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_appdefault_boolean.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_appdefault_string.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_free.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_genaddrs.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_get_checksum_func.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getaddrs.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getauthenticator.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getflags.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getkey.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getkey_k.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getlocalseqnumber.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getlocalsubkey.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getrcache.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getrecvsubkey.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getrecvsubkey_k.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getremoteseqnumber.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getremotesubkey.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getsendsubkey.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getsendsubkey_k.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_init.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_initivector.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_set_checksum_func.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_set_req_cksumtype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setaddrs.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setflags.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setports.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setrcache.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setrecvsubkey.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setrecvsubkey_k.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setsendsubkey.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setsendsubkey_k.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setuseruserkey.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal_alloc_va.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal_ext.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal_va.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_block_size.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_checksum_length.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_crypto_length.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_crypto_length_iov.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_decrypt.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_decrypt_iov.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_derive_prfplus.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_encrypt.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_encrypt_iov.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_encrypt_length.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_enctype_compare.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_free_state.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_fx_cf2_simple.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_init_state.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_is_coll_proof_cksum.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_is_keyed_cksum.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_keyed_checksum_types.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_keylengths.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_make_checksum.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_make_checksum_iov.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_make_random_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_padding_length.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_prf.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_prf_length.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_prfplus.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_add_entropy.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_make_octets.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_os_entropy.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_seed.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_to_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_string_to_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_string_to_key_with_params.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_valid_cksumtype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_valid_enctype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_verify_checksum.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_verify_checksum_iov.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_calculate_checksum.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_cache_match.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_close.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_copy_creds.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_default.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_default_name.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_destroy.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_dup.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_end_seq_get.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_gen_new.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_config.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_flags.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_full_name.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_name.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_principal.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_type.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_initialize.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_move.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_new_unique.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_next_cred.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_remove_cred.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_resolve.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_retrieve_cred.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_select.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_set_config.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_set_default_name.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_set_flags.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_start_seq_get.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_store_cred.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_support_switch.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_switch.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_cursor_free.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_cursor_new.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_cursor_next.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_have_content.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_change_password.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_check_clockskew.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_checksum_size.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_chpw_message.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_cksumtype_to_string.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_clear_error_message.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_addresses.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_authdata.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_authenticator.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_checksum.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_context.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_creds.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_data.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_error_message.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_keyblock.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_keyblock_contents.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_principal.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_ticket.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_decode_authdata_container.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_decode_ticket.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_decrypt.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_deltat_to_string.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_eblock_enctype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_encode_authdata_container.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_encrypt.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_encrypt_size.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_enctype_to_name.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_enctype_to_string.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_expand_hostname.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_find_authdata.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_finish_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_finish_random_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_addresses.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_ap_rep_enc_part.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_authdata.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_authenticator.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_checksum.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_checksum_contents.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_cksumtypes.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_context.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_cred_contents.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_creds.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_data.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_data_contents.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_default_realm.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_enctypes.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_error.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_error_message.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_host_realm.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_keyblock.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_keyblock_contents.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_keytab_entry_contents.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_principal.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_string.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_tgt_creds.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_ticket.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_unparsed_name.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_fwd_tgt_creds.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_credentials.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_credentials_renew.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_credentials_validate.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_default_realm.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_error_message.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_etype_info.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_fallback_host_realm.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_host_realm.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_in_tkt_with_keytab.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_in_tkt_with_password.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_in_tkt_with_skey.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_keytab.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_alloc.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_free.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_get_fast_flags.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_init.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_address_list.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_anonymous.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_canonicalize.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_change_password_prompt.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_etype_list.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_expire_callback.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache_name.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_fast_flags.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_forwardable.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_in_ccache.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_out_ccache.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_pa.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_pac_request.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_preauth_list.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_proxiable.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_renew_life.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_responder.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_salt.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_tkt_life.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_password.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_permitted_enctypes.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_profile.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_prompt_types.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_renewed_creds.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_server_rcache.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_time_offsets.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_validated_creds.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_context.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_context_profile.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_free.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get_creds.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get_error.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get_times.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_init.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_set_keytab.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_set_password.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_set_service.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_step.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_keyblock.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_random_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_secure_context.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_is_config_principal.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_is_referral_realm.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_is_thread_safe.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_create_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_decrypt.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_decrypt_iov.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_encrypt.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_encrypt_iov.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_free_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_key_enctype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_key_keyblock.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_make_checksum.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_make_checksum_iov.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_prf.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_reference_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_verify_checksum.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_verify_checksum_iov.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kdc_sign_ticket.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kdc_verify_ticket.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_add_entry.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_client_default.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_close.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_default.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_default_name.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_dup.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_end_seq_get.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_free_entry.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_get_entry.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_get_name.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_get_type.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_have_content.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_next_entry.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_read_service_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_remove_entry.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_resolve.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_start_seq_get.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_kuserok.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_make_authdata_kdc_issued.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_marshal_credentials.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_merge_authdata.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_1cred.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_error.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_ncred.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_priv.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_rep.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_rep_dce.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_req.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_req_extended.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_safe.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_os_localaddr.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_add_buffer.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_free.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_get_buffer.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_get_client_info.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_get_types.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_init.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_parse.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_sign.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_sign_ext.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_verify.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_verify_ext.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_parse_name.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_parse_name_flags.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_prepend_error_message.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal2salt.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal_compare.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal_compare_any_realm.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal_compare_flags.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_process_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_prompter_posix.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_random_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_cred.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_error.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_priv.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_rep.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_rep_dce.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_req.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_safe.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_read_password.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_realm_compare.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_recvauth.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_recvauth_version.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_get_challenge.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_list_questions.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_otp_challenge_free.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_otp_get_challenge.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_otp_set_answer.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_pkinit_challenge_free.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_pkinit_get_challenge.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_pkinit_set_answer.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_set_answer.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_salttype_to_string.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_sendauth.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_server_decrypt_ticket_keytab.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_default_realm.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_default_tgs_enctypes.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_error_message.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_kdc_recv_hook.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_kdc_send_hook.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_password.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_password_using_ccache.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_principal_realm.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_real_time.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_trace_callback.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_trace_filename.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_sname_match.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_sname_to_principal.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_cksumtype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_deltat.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_enctype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_salttype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_timestamp.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_timeofday.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_timestamp_to_sfstring.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_timestamp_to_string.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_free.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_get.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_get_creds.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_get_times.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_init.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_step.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_unmarshal_credentials.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name_ext.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name_flags.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name_flags_ext.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_us_timeofday.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_use_enctype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_authdata_kdc_issued.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_checksum.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_init_creds.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_init_creds_opt_init.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_vprepend_error_message.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_vset_error_message.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_vwrap_error_message.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/api/krb5_wrap_error_message.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/index.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_ADDRPORT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_CHAOS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_DDP.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_INET.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_INET6.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_IPPORT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_ISO.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_IS_LOCAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_NETBIOS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_XNS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_EXTERNAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_REGISTERED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_RESERVED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_RESERVED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_USE_SESSION_KEY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_USE_SUBKEY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_WIRE_MASK.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_CRC32.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_DESCBC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_NIST_SHA.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD4.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD5.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_SHA1.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_ENV.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_RAW.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_CRC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_MD4.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_MD5.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_RAW.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_MD5_RSA_CMS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_NULL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_RC2_CBC_ENV.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_RSA_ENV.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_UNKNOWN.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_CANONICALIZE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_FORWARDABLE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_FORWARDED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_POSTDATED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_PROXIABLE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_PROXY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_RENEW.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_RENEWABLE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_RENEWABLE_OK.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_VALIDATE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KDC_TKT_COMMON_MASK.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AP_REP.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AP_REQ.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AS_REP.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AS_REQ.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_AND_OR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_CAMMAC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_SESAME.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CYBERSAFE_SECUREID.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ERROR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_FAST_REQUIRED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_CACHED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_CANONICALIZE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_FORWARDABLE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_NO_STORE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_USER_USER.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INIT_CONTEXT_KDC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT16_MAX.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT16_MIN.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT32_MAX.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT32_MIN.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_SPAKE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_AUTHERROR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_HARDERROR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_MALFORMED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_SOFTERROR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_SUCCESS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_NONE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_PRINCIPAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SMTP_NAME.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SRV_HST.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SRV_INST.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SRV_XHST.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_UID.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_UNKNOWN.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_WELLKNOWN.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_X500_PRINCIPAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_CLIENT_INFO.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_DELEGATION_INFO.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_DEVICE_INFO.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_LOGON_INFO.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_REQUESTOR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AFS3_SALT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AP_REQ.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FOR_USER.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FX_COOKIE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FX_ERROR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FX_FAST.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_NONE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OSF_DCE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OTP_REQUEST.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PAC_REQUEST.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PKINIT_KX.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REP.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PW_SALT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_REFERRAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_S4U_X509_USER.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SESAME.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SPAKE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_TGS_REQ.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRIV.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PVNO.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_REALM_BRANCH_CHAR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_REFERRAL_REALM.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAFE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_FLAGS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_KTYPE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_TIMES.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_NOTICKET.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_OPENCLOSE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_NAME.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_NAME_SIZE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_REP.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_REQ.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/MAX_KEYTAB_NAME_LEN.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/MSEC_DIRBIT.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/MSEC_VAL_MASK.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/SALT_TYPE_AFS_LENGTH.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/SALT_TYPE_NO_LENGTH.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/THREEPARAMOPEN.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_ANONYMOUS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_ENC_PA_REP.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_FORWARDABLE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_FORWARDED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_HW_AUTH.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_INITIAL.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_INVALID.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_MAY_POSTDATE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_POSTDATED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_PRE_AUTH.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_PROXIABLE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_PROXY.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_RENEWABLE.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/VALID_INT_BITS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/VALID_UINT_BITS.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/index.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb524_convert_creds_kdc.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb524_init_ets.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb5_const.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_component.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_name.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_realm.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_set_realm.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_set_realm_data.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_set_realm_length.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_size.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_type.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb5_roundup.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb5_x.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/macros/krb5_xc.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/index.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_address.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_addrtype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_ap_rep.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_ap_rep_enc_part.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_ap_req.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_auth_context.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_authdata.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_authdatatype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_authenticator.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_boolean.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_cc_cursor.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_ccache.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_cccol_cursor.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_checksum.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_cksumtype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_const_pointer.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_const_principal.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_context.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_cred.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_cred_enc_part.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_cred_info.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_creds.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_crypto_iov.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_cryptotype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_data.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_deltat.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_enc_data.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_enc_kdc_rep_part.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_enc_tkt_part.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_encrypt_block.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_enctype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_error.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_error_code.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_expire_callback_func.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_flags.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_get_init_creds_opt.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_gic_opt_pa_data.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_init_creds_context.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_int16.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_int32.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_kdc_rep.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_kdc_req.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_key.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_keyblock.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_keytab.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_keytab_entry.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_keyusage.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_kt_cursor.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_kvno.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_last_req_entry.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_magic.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_mk_req_checksum_func.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_msgtype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_octet.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_data.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_pac_req.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_server_referral_data.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_svr_referral_data.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_pac.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_pointer.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_post_recv_fn.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_pre_send_fn.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_preauthtype.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_principal.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_principal_data.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_prompt.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_prompt_type.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_prompter_fct.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_pwd_data.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_rcache.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_replay_data.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_context.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_fn.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_otp_challenge.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_otp_tokeninfo.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_pkinit_challenge.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_pkinit_identity.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_response.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_ticket.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_ticket_times.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_timestamp.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_tkt_authent.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_tkt_creds_context.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_trace_callback.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_trace_info.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_transited.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_typed_data.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_ui_2.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_ui_4.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/krb5_verify_init_creds_opt.html create mode 100644 krb5-1.21.3/doc/html/appdev/refs/types/passwd_phrase_element.html create mode 100644 krb5-1.21.3/doc/html/appdev/y2038.html create mode 100644 krb5-1.21.3/doc/html/basic/ccache_def.html create mode 100644 krb5-1.21.3/doc/html/basic/date_format.html create mode 100644 krb5-1.21.3/doc/html/basic/index.html create mode 100644 krb5-1.21.3/doc/html/basic/keytab_def.html create mode 100644 krb5-1.21.3/doc/html/basic/rcache_def.html create mode 100644 krb5-1.21.3/doc/html/basic/stash_file_def.html create mode 100644 krb5-1.21.3/doc/html/build/directory_org.html create mode 100644 krb5-1.21.3/doc/html/build/doing_build.html create mode 100644 krb5-1.21.3/doc/html/build/index.html create mode 100644 krb5-1.21.3/doc/html/build/options2configure.html create mode 100644 krb5-1.21.3/doc/html/build/osconf.html create mode 100644 krb5-1.21.3/doc/html/build_this.html create mode 100644 krb5-1.21.3/doc/html/copyright.html create mode 100644 krb5-1.21.3/doc/html/formats/ccache_file_format.html create mode 100644 krb5-1.21.3/doc/html/formats/cookie.html create mode 100644 krb5-1.21.3/doc/html/formats/freshness_token.html create mode 100644 krb5-1.21.3/doc/html/formats/index.html create mode 100644 krb5-1.21.3/doc/html/formats/keytab_file_format.html create mode 100644 krb5-1.21.3/doc/html/formats/rcache_file_format.html create mode 100644 krb5-1.21.3/doc/html/genindex-A.html create mode 100644 krb5-1.21.3/doc/html/genindex-C.html create mode 100644 krb5-1.21.3/doc/html/genindex-E.html create mode 100644 krb5-1.21.3/doc/html/genindex-K.html create mode 100644 krb5-1.21.3/doc/html/genindex-L.html create mode 100644 krb5-1.21.3/doc/html/genindex-M.html create mode 100644 krb5-1.21.3/doc/html/genindex-P.html create mode 100644 krb5-1.21.3/doc/html/genindex-R.html create mode 100644 krb5-1.21.3/doc/html/genindex-S.html create mode 100644 krb5-1.21.3/doc/html/genindex-T.html create mode 100644 krb5-1.21.3/doc/html/genindex-V.html create mode 100644 krb5-1.21.3/doc/html/genindex-all.html create mode 100644 krb5-1.21.3/doc/html/genindex.html create mode 100644 krb5-1.21.3/doc/html/index.html create mode 100644 krb5-1.21.3/doc/html/mitK5defaults.html create mode 100644 krb5-1.21.3/doc/html/mitK5features.html create mode 100644 krb5-1.21.3/doc/html/mitK5license.html create mode 100644 krb5-1.21.3/doc/html/objects.inv create mode 100644 krb5-1.21.3/doc/html/plugindev/ccselect.html create mode 100644 krb5-1.21.3/doc/html/plugindev/certauth.html create mode 100644 krb5-1.21.3/doc/html/plugindev/clpreauth.html create mode 100644 krb5-1.21.3/doc/html/plugindev/general.html create mode 100644 krb5-1.21.3/doc/html/plugindev/gssapi.html create mode 100644 krb5-1.21.3/doc/html/plugindev/hostrealm.html create mode 100644 krb5-1.21.3/doc/html/plugindev/index.html create mode 100644 krb5-1.21.3/doc/html/plugindev/internal.html create mode 100644 krb5-1.21.3/doc/html/plugindev/kadm5_auth.html create mode 100644 krb5-1.21.3/doc/html/plugindev/kadm5_hook.html create mode 100644 krb5-1.21.3/doc/html/plugindev/kdcpolicy.html create mode 100644 krb5-1.21.3/doc/html/plugindev/kdcpreauth.html create mode 100644 krb5-1.21.3/doc/html/plugindev/localauth.html create mode 100644 krb5-1.21.3/doc/html/plugindev/locate.html create mode 100644 krb5-1.21.3/doc/html/plugindev/profile.html create mode 100644 krb5-1.21.3/doc/html/plugindev/pwqual.html create mode 100644 krb5-1.21.3/doc/html/resources.html create mode 100644 krb5-1.21.3/doc/html/search.html create mode 100644 krb5-1.21.3/doc/html/searchindex.js create mode 100644 krb5-1.21.3/doc/html/user/index.html create mode 100644 krb5-1.21.3/doc/html/user/pwd_mgmt.html create mode 100644 krb5-1.21.3/doc/html/user/tkt_mgmt.html create mode 100644 krb5-1.21.3/doc/html/user/user_commands/index.html create mode 100644 krb5-1.21.3/doc/html/user/user_commands/kdestroy.html create mode 100644 krb5-1.21.3/doc/html/user/user_commands/kinit.html create mode 100644 krb5-1.21.3/doc/html/user/user_commands/klist.html create mode 100644 krb5-1.21.3/doc/html/user/user_commands/kpasswd.html create mode 100644 krb5-1.21.3/doc/html/user/user_commands/krb5-config.html create mode 100644 krb5-1.21.3/doc/html/user/user_commands/ksu.html create mode 100644 krb5-1.21.3/doc/html/user/user_commands/kswitch.html create mode 100644 krb5-1.21.3/doc/html/user/user_commands/kvno.html create mode 100644 krb5-1.21.3/doc/html/user/user_commands/sclient.html create mode 100644 krb5-1.21.3/doc/html/user/user_config/index.html create mode 100644 krb5-1.21.3/doc/html/user/user_config/k5identity.html create mode 100644 krb5-1.21.3/doc/html/user/user_config/k5login.html create mode 100644 krb5-1.21.3/doc/html/user/user_config/kerberos.html create mode 100644 krb5-1.21.3/doc/index.rst create mode 100644 krb5-1.21.3/doc/iprop-notes.txt create mode 100644 krb5-1.21.3/doc/kadm5-errmsg.txt create mode 100644 krb5-1.21.3/doc/kadm5/adb-unit-test.tex create mode 100644 krb5-1.21.3/doc/kadm5/api-funcspec.tex create mode 100644 krb5-1.21.3/doc/kadm5/api-server-design.tex create mode 100644 krb5-1.21.3/doc/kadm5/fullpage.sty create mode 100644 krb5-1.21.3/doc/mitK5defaults.rst create mode 100644 krb5-1.21.3/doc/mitK5features.rst create mode 100644 krb5-1.21.3/doc/mitK5license.rst create mode 100644 krb5-1.21.3/doc/notice.rst create mode 100644 krb5-1.21.3/doc/pdf/GMakefile create mode 100644 krb5-1.21.3/doc/pdf/LICRcyr2utf8.xdy create mode 100644 krb5-1.21.3/doc/pdf/LICRlatin2utf8.xdy create mode 100644 krb5-1.21.3/doc/pdf/LatinRules.xdy create mode 100644 krb5-1.21.3/doc/pdf/admin.pdf create mode 100644 krb5-1.21.3/doc/pdf/admin.tex create mode 100644 krb5-1.21.3/doc/pdf/appdev.pdf create mode 100644 krb5-1.21.3/doc/pdf/appdev.tex create mode 100644 krb5-1.21.3/doc/pdf/basic.pdf create mode 100644 krb5-1.21.3/doc/pdf/basic.tex create mode 100644 krb5-1.21.3/doc/pdf/build.pdf create mode 100644 krb5-1.21.3/doc/pdf/build.tex create mode 100644 krb5-1.21.3/doc/pdf/latexmkjarc create mode 100644 krb5-1.21.3/doc/pdf/latexmkrc create mode 100644 krb5-1.21.3/doc/pdf/make.bat create mode 100644 krb5-1.21.3/doc/pdf/plugindev.pdf create mode 100644 krb5-1.21.3/doc/pdf/plugindev.tex create mode 100644 krb5-1.21.3/doc/pdf/python.ist create mode 100644 krb5-1.21.3/doc/pdf/sphinx.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinx.xdy create mode 100644 krb5-1.21.3/doc/pdf/sphinxhighlight.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxhowto.cls create mode 100644 krb5-1.21.3/doc/pdf/sphinxlatexadmonitions.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxlatexcontainers.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxlatexgraphics.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxlatexindbibtoc.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxlatexlists.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxlatexliterals.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxlatexnumfig.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxlatexobjects.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxlatexshadowbox.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxlatexstyleheadings.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxlatexstylepage.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxlatexstyletext.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxlatextables.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxmanual.cls create mode 100644 krb5-1.21.3/doc/pdf/sphinxmessages.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxoptionsgeometry.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxoptionshyperref.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxpackagecyrillic.sty create mode 100644 krb5-1.21.3/doc/pdf/sphinxpackagefootnote.sty create mode 100644 krb5-1.21.3/doc/pdf/user.pdf create mode 100644 krb5-1.21.3/doc/pdf/user.tex create mode 100644 krb5-1.21.3/doc/plugindev/ccselect.rst create mode 100644 krb5-1.21.3/doc/plugindev/certauth.rst create mode 100644 krb5-1.21.3/doc/plugindev/clpreauth.rst create mode 100644 krb5-1.21.3/doc/plugindev/general.rst create mode 100644 krb5-1.21.3/doc/plugindev/gssapi.rst create mode 100644 krb5-1.21.3/doc/plugindev/hostrealm.rst create mode 100644 krb5-1.21.3/doc/plugindev/index.rst create mode 100644 krb5-1.21.3/doc/plugindev/internal.rst create mode 100644 krb5-1.21.3/doc/plugindev/kadm5_auth.rst create mode 100644 krb5-1.21.3/doc/plugindev/kadm5_hook.rst create mode 100644 krb5-1.21.3/doc/plugindev/kdcpolicy.rst create mode 100644 krb5-1.21.3/doc/plugindev/kdcpreauth.rst create mode 100644 krb5-1.21.3/doc/plugindev/localauth.rst create mode 100644 krb5-1.21.3/doc/plugindev/locate.rst create mode 100644 krb5-1.21.3/doc/plugindev/profile.rst create mode 100644 krb5-1.21.3/doc/plugindev/pwqual.rst create mode 100644 krb5-1.21.3/doc/resources.rst create mode 100644 krb5-1.21.3/doc/rpc/design.tex create mode 100644 krb5-1.21.3/doc/thread-safe.txt create mode 100644 krb5-1.21.3/doc/threads.txt create mode 100644 krb5-1.21.3/doc/tools/README create mode 100644 krb5-1.21.3/doc/tools/define_document.tmpl create mode 100644 krb5-1.21.3/doc/tools/docmodel.py create mode 100644 krb5-1.21.3/doc/tools/doxy.py create mode 100644 krb5-1.21.3/doc/tools/doxybuilder_funcs.py create mode 100644 krb5-1.21.3/doc/tools/doxybuilder_types.py create mode 100644 krb5-1.21.3/doc/tools/func_document.tmpl create mode 100644 krb5-1.21.3/doc/tools/type_document.tmpl create mode 100644 krb5-1.21.3/doc/user/index.rst create mode 100644 krb5-1.21.3/doc/user/pwd_mgmt.rst create mode 100644 krb5-1.21.3/doc/user/tkt_mgmt.rst create mode 100644 krb5-1.21.3/doc/user/user_commands/index.rst create mode 100644 krb5-1.21.3/doc/user/user_commands/kdestroy.rst create mode 100644 krb5-1.21.3/doc/user/user_commands/kinit.rst create mode 100644 krb5-1.21.3/doc/user/user_commands/klist.rst create mode 100644 krb5-1.21.3/doc/user/user_commands/kpasswd.rst create mode 100644 krb5-1.21.3/doc/user/user_commands/krb5-config.rst create mode 100644 krb5-1.21.3/doc/user/user_commands/ksu.rst create mode 100644 krb5-1.21.3/doc/user/user_commands/kswitch.rst create mode 100644 krb5-1.21.3/doc/user/user_commands/kvno.rst create mode 100644 krb5-1.21.3/doc/user/user_commands/sclient.rst create mode 100644 krb5-1.21.3/doc/user/user_config/index.rst create mode 100644 krb5-1.21.3/doc/user/user_config/k5identity.rst create mode 100644 krb5-1.21.3/doc/user/user_config/k5login.rst create mode 100644 krb5-1.21.3/doc/user/user_config/kerberos.rst create mode 100644 krb5-1.21.3/src/Makefile.in create mode 100644 krb5-1.21.3/src/aclocal.m4 create mode 100644 krb5-1.21.3/src/appl/Makefile.in create mode 100644 krb5-1.21.3/src/appl/deps create mode 100644 krb5-1.21.3/src/appl/gss-sample/Makefile.in create mode 100644 krb5-1.21.3/src/appl/gss-sample/README create mode 100644 krb5-1.21.3/src/appl/gss-sample/deps create mode 100644 krb5-1.21.3/src/appl/gss-sample/gss-client.c create mode 100644 krb5-1.21.3/src/appl/gss-sample/gss-misc.c create mode 100644 krb5-1.21.3/src/appl/gss-sample/gss-misc.h create mode 100644 krb5-1.21.3/src/appl/gss-sample/gss-server.c create mode 100755 krb5-1.21.3/src/appl/gss-sample/t_gss_sample.py create mode 100644 krb5-1.21.3/src/appl/sample/Makefile.in create mode 100644 krb5-1.21.3/src/appl/sample/deps create mode 100644 krb5-1.21.3/src/appl/sample/sample.h create mode 100644 krb5-1.21.3/src/appl/sample/sclient/Makefile.in create mode 100644 krb5-1.21.3/src/appl/sample/sclient/deps create mode 100644 krb5-1.21.3/src/appl/sample/sclient/sclient.c create mode 100644 krb5-1.21.3/src/appl/sample/sserver/Makefile.in create mode 100644 krb5-1.21.3/src/appl/sample/sserver/deps create mode 100644 krb5-1.21.3/src/appl/sample/sserver/sserver.c create mode 100644 krb5-1.21.3/src/appl/sample/t_sample.py create mode 100644 krb5-1.21.3/src/appl/simple/Makefile.in create mode 100644 krb5-1.21.3/src/appl/simple/client/Makefile.in create mode 100644 krb5-1.21.3/src/appl/simple/client/deps create mode 100644 krb5-1.21.3/src/appl/simple/client/sim_client.c create mode 100644 krb5-1.21.3/src/appl/simple/deps create mode 100644 krb5-1.21.3/src/appl/simple/server/Makefile.in create mode 100644 krb5-1.21.3/src/appl/simple/server/deps create mode 100644 krb5-1.21.3/src/appl/simple/server/sim_server.c create mode 100644 krb5-1.21.3/src/appl/simple/simple.h create mode 100644 krb5-1.21.3/src/appl/simple/t_simple.py create mode 100644 krb5-1.21.3/src/appl/user_user/Makefile.in create mode 100644 krb5-1.21.3/src/appl/user_user/client.c create mode 100644 krb5-1.21.3/src/appl/user_user/deps create mode 100644 krb5-1.21.3/src/appl/user_user/server.c create mode 100755 krb5-1.21.3/src/appl/user_user/t_user2user.py create mode 100644 krb5-1.21.3/src/build-tools/Makefile.in create mode 100644 krb5-1.21.3/src/build-tools/deps create mode 100644 krb5-1.21.3/src/build-tools/gssrpc.pc.in create mode 100644 krb5-1.21.3/src/build-tools/kadm-client.pc.in create mode 100644 krb5-1.21.3/src/build-tools/kadm-server.pc.in create mode 100644 krb5-1.21.3/src/build-tools/kdb.pc.in create mode 100755 krb5-1.21.3/src/build-tools/krb5-config.in create mode 100644 krb5-1.21.3/src/build-tools/krb5-gssapi.pc.in create mode 100644 krb5-1.21.3/src/build-tools/krb5.pc.in create mode 100644 krb5-1.21.3/src/build-tools/mit-krb5-gssapi.pc.in create mode 100644 krb5-1.21.3/src/build-tools/mit-krb5.pc.in create mode 100644 krb5-1.21.3/src/build-tools/t_krbconf create mode 100644 krb5-1.21.3/src/ccapi/Makefile.in create mode 100644 krb5-1.21.3/src/ccapi/common/Makefile.in create mode 100644 krb5-1.21.3/src/ccapi/common/cci_array_internal.c create mode 100644 krb5-1.21.3/src/ccapi/common/cci_array_internal.h create mode 100644 krb5-1.21.3/src/ccapi/common/cci_common.h create mode 100644 krb5-1.21.3/src/ccapi/common/cci_cred_union.c create mode 100644 krb5-1.21.3/src/ccapi/common/cci_cred_union.h create mode 100644 krb5-1.21.3/src/ccapi/common/cci_debugging.c create mode 100644 krb5-1.21.3/src/ccapi/common/cci_debugging.h create mode 100644 krb5-1.21.3/src/ccapi/common/cci_identifier.c create mode 100644 krb5-1.21.3/src/ccapi/common/cci_identifier.h create mode 100644 krb5-1.21.3/src/ccapi/common/cci_message.c create mode 100644 krb5-1.21.3/src/ccapi/common/cci_message.h create mode 100644 krb5-1.21.3/src/ccapi/common/cci_os_debugging.h create mode 100644 krb5-1.21.3/src/ccapi/common/cci_os_identifier.h create mode 100644 krb5-1.21.3/src/ccapi/common/cci_types.h create mode 100644 krb5-1.21.3/src/ccapi/common/unix/Makefile.in create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/autolock.hxx create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/ccutil.cxx create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/ccutil.def create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/ccutils.c create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/ccutils.h create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/init.cxx create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/init.hxx create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/name.h create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/opts.cxx create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/opts.hxx create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/secure.cxx create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/secure.hxx create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/util.cxx create mode 100644 krb5-1.21.3/src/ccapi/common/win/OldCC/util.h create mode 100644 krb5-1.21.3/src/ccapi/common/win/cci_os_debugging.c create mode 100644 krb5-1.21.3/src/ccapi/common/win/cci_os_identifier.c create mode 100644 krb5-1.21.3/src/ccapi/common/win/ccs_reply.Acf create mode 100644 krb5-1.21.3/src/ccapi/common/win/ccs_reply.Idl create mode 100644 krb5-1.21.3/src/ccapi/common/win/ccs_request.Acf create mode 100644 krb5-1.21.3/src/ccapi/common/win/ccs_request.idl create mode 100644 krb5-1.21.3/src/ccapi/common/win/tls.c create mode 100644 krb5-1.21.3/src/ccapi/common/win/tls.h create mode 100644 krb5-1.21.3/src/ccapi/common/win/win-utils.c create mode 100644 krb5-1.21.3/src/ccapi/common/win/win-utils.h create mode 100644 krb5-1.21.3/src/ccapi/deps create mode 100644 krb5-1.21.3/src/ccapi/doc/CCAPI-Windows-Design.html create mode 100644 krb5-1.21.3/src/ccapi/lib/Makefile.in create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi.exports create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_ccache.c create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_ccache.h create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_ccache_iterator.c create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_ccache_iterator.h create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_context.c create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_context.h create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_context_change_time.c create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_context_change_time.h create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_credentials.c create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_credentials.h create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_credentials_iterator.c create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_credentials_iterator.h create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_err.et create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_ipc.c create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_ipc.h create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_os_ipc.h create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_string.c create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_string.h create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_v2.c create mode 100644 krb5-1.21.3/src/ccapi/lib/ccapi_v2.exports create mode 100644 krb5-1.21.3/src/ccapi/lib/deps create mode 100644 krb5-1.21.3/src/ccapi/lib/libkrb5-ccapi.exports create mode 100644 krb5-1.21.3/src/ccapi/lib/unix/Makefile.in create mode 100644 krb5-1.21.3/src/ccapi/lib/unix/deps create mode 100644 krb5-1.21.3/src/ccapi/lib/unix/stubs.c create mode 100644 krb5-1.21.3/src/ccapi/lib/win/Makefile.in create mode 100644 krb5-1.21.3/src/ccapi/lib/win/OldCC/ccapi.h create mode 100644 krb5-1.21.3/src/ccapi/lib/win/OldCC/client.cxx create mode 100644 krb5-1.21.3/src/ccapi/lib/win/OldCC/client.h create mode 100644 krb5-1.21.3/src/ccapi/lib/win/WINCCAPI.sln create mode 100644 krb5-1.21.3/src/ccapi/lib/win/WINCCAPI.vcproj create mode 100644 krb5-1.21.3/src/ccapi/lib/win/ccapi_os_ipc.cxx create mode 100644 krb5-1.21.3/src/ccapi/lib/win/ccs_reply_proc.c create mode 100644 krb5-1.21.3/src/ccapi/lib/win/debug.exports create mode 100644 krb5-1.21.3/src/ccapi/lib/win/dllmain.cxx create mode 100644 krb5-1.21.3/src/ccapi/lib/win/dllmain.h create mode 100644 krb5-1.21.3/src/ccapi/server/Makefile.in create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_array.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_array.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_cache_collection.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_cache_collection.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_callback.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_callback.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_ccache.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_ccache.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_ccache_iterator.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_ccache_iterator.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_client.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_client.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_common.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_credentials.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_credentials.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_credentials_iterator.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_credentials_iterator.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_list.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_list.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_list_internal.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_list_internal.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_lock.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_lock.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_lock_state.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_lock_state.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_os_notify.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_os_pipe.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_os_server.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_pipe.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_pipe.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_server.c create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_server.h create mode 100644 krb5-1.21.3/src/ccapi/server/ccs_types.h create mode 100644 krb5-1.21.3/src/ccapi/server/deps create mode 100644 krb5-1.21.3/src/ccapi/server/unix/Makefile.in create mode 100644 krb5-1.21.3/src/ccapi/server/unix/deps create mode 100644 krb5-1.21.3/src/ccapi/server/win/Makefile.in create mode 100644 krb5-1.21.3/src/ccapi/server/win/Server.sln create mode 100644 krb5-1.21.3/src/ccapi/server/win/Server.vcproj create mode 100644 krb5-1.21.3/src/ccapi/server/win/WorkItem.cpp create mode 100644 krb5-1.21.3/src/ccapi/server/win/WorkQueue.cpp create mode 100644 krb5-1.21.3/src/ccapi/server/win/WorkQueue.h create mode 100644 krb5-1.21.3/src/ccapi/server/win/ccs_os_pipe.c create mode 100644 krb5-1.21.3/src/ccapi/server/win/ccs_os_server.cpp create mode 100644 krb5-1.21.3/src/ccapi/server/win/ccs_request_proc.c create mode 100644 krb5-1.21.3/src/ccapi/server/win/ccs_win_pipe.c create mode 100644 krb5-1.21.3/src/ccapi/server/win/ccs_win_pipe.h create mode 100644 krb5-1.21.3/src/ccapi/server/win/workitem.h create mode 100644 krb5-1.21.3/src/ccapi/test/Makefile.in create mode 100644 krb5-1.21.3/src/ccapi/test/Makefile.w32 create mode 100644 krb5-1.21.3/src/ccapi/test/Pingtest.sln create mode 100644 krb5-1.21.3/src/ccapi/test/deps create mode 100644 krb5-1.21.3/src/ccapi/test/main.c create mode 100644 krb5-1.21.3/src/ccapi/test/pingtest.c create mode 100644 krb5-1.21.3/src/ccapi/test/setlib.pl create mode 100644 krb5-1.21.3/src/ccapi/test/simple_lock_test.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_compare.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_destroy.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_change_time.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_credentials_version.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_last_default_time.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_name.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_principal.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_iterator_next.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_move.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_new_credentials_iterator.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_release.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_remove_credentials.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_set_default.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_set_principal.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_ccache_store_credentials.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_close.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_context_compare.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_context_create_ccache.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_context_create_default_ccache.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_context_create_new_ccache.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_context_get_change_time.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_context_get_default_ccache_name.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_context_new_ccache_iterator.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_context_open_ccache.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_context_open_default_ccache.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_context_release.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_create.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_credentials_iterator_next.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_destroy.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_get_NC_info.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_get_change_time.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_get_cred_version.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_get_name.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_get_principal.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_initialize.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_open.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_remove_cred.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_NCs_begin.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_NCs_next.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_creds_begin.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_creds_next.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_set_principal.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_shutdown.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_cc_store.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi.bat create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi.sh create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_ccache.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_ccache.h create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_check.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_check.h create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_constants.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_constants.h create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_context.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_context.h create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_globals.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_globals.h create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_iterators.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_iterators.h create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_log.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_log.h create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_util.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_util.h create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_v2.c create mode 100644 krb5-1.21.3/src/ccapi/test/test_ccapi_v2.h create mode 100644 krb5-1.21.3/src/ccapi/test/test_constants.c create mode 100644 krb5-1.21.3/src/clients/Makefile.in create mode 100644 krb5-1.21.3/src/clients/deps create mode 100644 krb5-1.21.3/src/clients/kcpytkt/Makefile.in create mode 100644 krb5-1.21.3/src/clients/kcpytkt/kcpytkt.c create mode 100644 krb5-1.21.3/src/clients/kdeltkt/Makefile.in create mode 100644 krb5-1.21.3/src/clients/kdeltkt/kdeltkt.c create mode 100644 krb5-1.21.3/src/clients/kdestroy/Makefile.in create mode 100644 krb5-1.21.3/src/clients/kdestroy/deps create mode 100644 krb5-1.21.3/src/clients/kdestroy/kdestroy.c create mode 100644 krb5-1.21.3/src/clients/kinit/Makefile.in create mode 100644 krb5-1.21.3/src/clients/kinit/deps create mode 100644 krb5-1.21.3/src/clients/kinit/extern.h create mode 100644 krb5-1.21.3/src/clients/kinit/kinit.c create mode 100644 krb5-1.21.3/src/clients/kinit/kinit_kdb.c create mode 100644 krb5-1.21.3/src/clients/klist/Makefile.in create mode 100644 krb5-1.21.3/src/clients/klist/deps create mode 100644 krb5-1.21.3/src/clients/klist/klist.c create mode 100644 krb5-1.21.3/src/clients/kpasswd/Makefile.in create mode 100644 krb5-1.21.3/src/clients/kpasswd/deps create mode 100644 krb5-1.21.3/src/clients/kpasswd/kpasswd.c create mode 100644 krb5-1.21.3/src/clients/ksu/Makefile.in create mode 100644 krb5-1.21.3/src/clients/ksu/authorization.c create mode 100644 krb5-1.21.3/src/clients/ksu/ccache.c create mode 100644 krb5-1.21.3/src/clients/ksu/deps create mode 100644 krb5-1.21.3/src/clients/ksu/heuristic.c create mode 100644 krb5-1.21.3/src/clients/ksu/krb_auth_su.c create mode 100644 krb5-1.21.3/src/clients/ksu/ksu.h create mode 100644 krb5-1.21.3/src/clients/ksu/main.c create mode 100644 krb5-1.21.3/src/clients/ksu/setenv.c create mode 100644 krb5-1.21.3/src/clients/ksu/xmalloc.c create mode 100644 krb5-1.21.3/src/clients/kswitch/Makefile.in create mode 100644 krb5-1.21.3/src/clients/kswitch/deps create mode 100644 krb5-1.21.3/src/clients/kswitch/kswitch.c create mode 100644 krb5-1.21.3/src/clients/kvno/Makefile.in create mode 100644 krb5-1.21.3/src/clients/kvno/deps create mode 100644 krb5-1.21.3/src/clients/kvno/kvno.c create mode 100644 krb5-1.21.3/src/clients/kvno/t_kvno.py create mode 100644 krb5-1.21.3/src/config-files/Makefile.in create mode 100644 krb5-1.21.3/src/config-files/convert-config-files create mode 100644 krb5-1.21.3/src/config-files/deps create mode 100644 krb5-1.21.3/src/config-files/kdc.conf create mode 100644 krb5-1.21.3/src/config-files/krb5.conf create mode 100644 krb5-1.21.3/src/config-files/mech create mode 100644 krb5-1.21.3/src/config-files/services.append create mode 100644 krb5-1.21.3/src/config/ac-archive/README create mode 100644 krb5-1.21.3/src/config/ac-archive/ax_pthread.m4 create mode 100644 krb5-1.21.3/src/config/ac-archive/ax_recursive_eval.m4 create mode 100755 krb5-1.21.3/src/config/config.guess create mode 100755 krb5-1.21.3/src/config/config.sub create mode 100755 krb5-1.21.3/src/config/install-sh create mode 100644 krb5-1.21.3/src/config/lib.in create mode 100644 krb5-1.21.3/src/config/libnodeps.in create mode 100644 krb5-1.21.3/src/config/libnover.in create mode 100644 krb5-1.21.3/src/config/libobj.in create mode 100644 krb5-1.21.3/src/config/libpriv.in create mode 100755 krb5-1.21.3/src/config/mkinstalldirs create mode 100755 krb5-1.21.3/src/config/move-if-changed create mode 100644 krb5-1.21.3/src/config/pkg.m4 create mode 100644 krb5-1.21.3/src/config/post.in create mode 100644 krb5-1.21.3/src/config/pre.in create mode 100755 krb5-1.21.3/src/config/ren2long create mode 100644 krb5-1.21.3/src/config/ren2long.awk create mode 100644 krb5-1.21.3/src/config/rm.bat create mode 100644 krb5-1.21.3/src/config/shlib.conf create mode 100755 krb5-1.21.3/src/config/wconfig.pl create mode 100644 krb5-1.21.3/src/config/win-post.in create mode 100644 krb5-1.21.3/src/config/win-pre.in create mode 100755 krb5-1.21.3/src/configure create mode 100644 krb5-1.21.3/src/configure.ac create mode 100644 krb5-1.21.3/src/deps create mode 100644 krb5-1.21.3/src/doc/Doxyfile.in create mode 100644 krb5-1.21.3/src/doc/Makefile.in create mode 100644 krb5-1.21.3/src/doc/deps create mode 100644 krb5-1.21.3/src/doc/version.py.in create mode 100644 krb5-1.21.3/src/include/CredentialsCache.h create mode 100644 krb5-1.21.3/src/include/CredentialsCache2.h create mode 100644 krb5-1.21.3/src/include/Makefile.in create mode 100644 krb5-1.21.3/src/include/adm_proto.h create mode 100644 krb5-1.21.3/src/include/autoconf.h.in create mode 100644 krb5-1.21.3/src/include/copyright.h create mode 100644 krb5-1.21.3/src/include/deps create mode 100644 krb5-1.21.3/src/include/fake-addrinfo.h create mode 100644 krb5-1.21.3/src/include/foreachaddr.h create mode 100644 krb5-1.21.3/src/include/gssapi.h create mode 100644 krb5-1.21.3/src/include/gssrpc/auth.h create mode 100644 krb5-1.21.3/src/include/gssrpc/auth_gss.h create mode 100644 krb5-1.21.3/src/include/gssrpc/auth_gssapi.h create mode 100644 krb5-1.21.3/src/include/gssrpc/auth_unix.h create mode 100644 krb5-1.21.3/src/include/gssrpc/clnt.h create mode 100644 krb5-1.21.3/src/include/gssrpc/netdb.h create mode 100644 krb5-1.21.3/src/include/gssrpc/pmap_clnt.h create mode 100644 krb5-1.21.3/src/include/gssrpc/pmap_prot.h create mode 100644 krb5-1.21.3/src/include/gssrpc/pmap_rmt.h create mode 100644 krb5-1.21.3/src/include/gssrpc/rename.h create mode 100644 krb5-1.21.3/src/include/gssrpc/rpc.h create mode 100644 krb5-1.21.3/src/include/gssrpc/rpc_msg.h create mode 100644 krb5-1.21.3/src/include/gssrpc/svc.h create mode 100644 krb5-1.21.3/src/include/gssrpc/svc_auth.h create mode 100644 krb5-1.21.3/src/include/gssrpc/types.hin create mode 100644 krb5-1.21.3/src/include/gssrpc/xdr.h create mode 100644 krb5-1.21.3/src/include/iprop.h create mode 100644 krb5-1.21.3/src/include/iprop_hdr.h create mode 100644 krb5-1.21.3/src/include/k5-base64.h create mode 100644 krb5-1.21.3/src/include/k5-buf.h create mode 100644 krb5-1.21.3/src/include/k5-cmocka.h create mode 100644 krb5-1.21.3/src/include/k5-der.h create mode 100644 krb5-1.21.3/src/include/k5-err.h create mode 100644 krb5-1.21.3/src/include/k5-gmt_mktime.h create mode 100644 krb5-1.21.3/src/include/k5-hashtab.h create mode 100644 krb5-1.21.3/src/include/k5-hex.h create mode 100644 krb5-1.21.3/src/include/k5-input.h create mode 100644 krb5-1.21.3/src/include/k5-int-pkinit.h create mode 100644 krb5-1.21.3/src/include/k5-int.h create mode 100644 krb5-1.21.3/src/include/k5-ipc_stream.h create mode 100644 krb5-1.21.3/src/include/k5-json.h create mode 100644 krb5-1.21.3/src/include/k5-platform.h create mode 100644 krb5-1.21.3/src/include/k5-plugin.h create mode 100644 krb5-1.21.3/src/include/k5-queue.h create mode 100644 krb5-1.21.3/src/include/k5-spake.h create mode 100644 krb5-1.21.3/src/include/k5-thread.h create mode 100644 krb5-1.21.3/src/include/k5-tls.h create mode 100644 krb5-1.21.3/src/include/k5-trace.h create mode 100644 krb5-1.21.3/src/include/k5-unicode.h create mode 100644 krb5-1.21.3/src/include/k5-utf8.h create mode 100644 krb5-1.21.3/src/include/k5-util.h create mode 100644 krb5-1.21.3/src/include/kcm.h create mode 100644 krb5-1.21.3/src/include/kdb.h create mode 100644 krb5-1.21.3/src/include/kdb_kt.h create mode 100644 krb5-1.21.3/src/include/kdb_log.h create mode 100644 krb5-1.21.3/src/include/krad.h create mode 100644 krb5-1.21.3/src/include/krb5.h create mode 100644 krb5-1.21.3/src/include/krb5/audit_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/authdata_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/ccselect_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/certauth_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/clpreauth_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/hostrealm_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/kadm5_auth_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/kadm5_hook_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/kdcauthdata_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/kdcpolicy_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/kdcpreauth_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/krb5.hin create mode 100644 krb5-1.21.3/src/include/krb5/localauth_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/locate_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/preauth_plugin.h create mode 100644 krb5-1.21.3/src/include/krb5/pwqual_plugin.h create mode 100644 krb5-1.21.3/src/include/net-server.h create mode 100644 krb5-1.21.3/src/include/osconf.hin create mode 100644 krb5-1.21.3/src/include/port-sockets.h create mode 100644 krb5-1.21.3/src/include/socket-utils.h create mode 100644 krb5-1.21.3/src/include/win-mac.h create mode 100644 krb5-1.21.3/src/kadmin/Makefile.in create mode 100644 krb5-1.21.3/src/kadmin/cli/Makefile.in create mode 100644 krb5-1.21.3/src/kadmin/cli/deps create mode 100644 krb5-1.21.3/src/kadmin/cli/getdate.y create mode 100755 krb5-1.21.3/src/kadmin/cli/k5srvutil.sh create mode 100644 krb5-1.21.3/src/kadmin/cli/kadmin.c create mode 100644 krb5-1.21.3/src/kadmin/cli/kadmin.h create mode 100644 krb5-1.21.3/src/kadmin/cli/kadmin_ct.ct create mode 100644 krb5-1.21.3/src/kadmin/cli/keytab.c create mode 100644 krb5-1.21.3/src/kadmin/cli/keytab_local.c create mode 100644 krb5-1.21.3/src/kadmin/cli/ss_wrapper.c create mode 100644 krb5-1.21.3/src/kadmin/dbutil/Makefile.in create mode 100644 krb5-1.21.3/src/kadmin/dbutil/deps create mode 100644 krb5-1.21.3/src/kadmin/dbutil/dump.c create mode 100644 krb5-1.21.3/src/kadmin/dbutil/import_err.et create mode 100644 krb5-1.21.3/src/kadmin/dbutil/kadm5_create.c create mode 100644 krb5-1.21.3/src/kadmin/dbutil/kdb5_create.c create mode 100644 krb5-1.21.3/src/kadmin/dbutil/kdb5_destroy.c create mode 100644 krb5-1.21.3/src/kadmin/dbutil/kdb5_mkey.c create mode 100644 krb5-1.21.3/src/kadmin/dbutil/kdb5_stash.c create mode 100644 krb5-1.21.3/src/kadmin/dbutil/kdb5_util.c create mode 100644 krb5-1.21.3/src/kadmin/dbutil/kdb5_util.h create mode 100644 krb5-1.21.3/src/kadmin/dbutil/nstrtok.h create mode 100644 krb5-1.21.3/src/kadmin/dbutil/ovload.c create mode 100644 krb5-1.21.3/src/kadmin/dbutil/strtok.c create mode 100644 krb5-1.21.3/src/kadmin/dbutil/t_tdumputil.c create mode 100755 krb5-1.21.3/src/kadmin/dbutil/t_tdumputil.py create mode 100644 krb5-1.21.3/src/kadmin/dbutil/tabdump.c create mode 100644 krb5-1.21.3/src/kadmin/dbutil/tdumputil.c create mode 100644 krb5-1.21.3/src/kadmin/dbutil/tdumputil.h create mode 100644 krb5-1.21.3/src/kadmin/deps create mode 100644 krb5-1.21.3/src/kadmin/kdbkeys/Makefile.in create mode 100755 krb5-1.21.3/src/kadmin/kdbkeys/do-test.pl create mode 100644 krb5-1.21.3/src/kadmin/ktutil/Makefile.in create mode 100644 krb5-1.21.3/src/kadmin/ktutil/deps create mode 100644 krb5-1.21.3/src/kadmin/ktutil/ktutil.c create mode 100644 krb5-1.21.3/src/kadmin/ktutil/ktutil.h create mode 100644 krb5-1.21.3/src/kadmin/ktutil/ktutil_ct.ct create mode 100644 krb5-1.21.3/src/kadmin/ktutil/ktutil_funcs.c create mode 100755 krb5-1.21.3/src/kadmin/scripts/inst-hdrs.sh create mode 100644 krb5-1.21.3/src/kadmin/server/Makefile.in create mode 100644 krb5-1.21.3/src/kadmin/server/auth.c create mode 100644 krb5-1.21.3/src/kadmin/server/auth.h create mode 100644 krb5-1.21.3/src/kadmin/server/auth_acl.c create mode 100644 krb5-1.21.3/src/kadmin/server/auth_self.c create mode 100644 krb5-1.21.3/src/kadmin/server/deps create mode 100644 krb5-1.21.3/src/kadmin/server/ipropd_svc.c create mode 100644 krb5-1.21.3/src/kadmin/server/kadm_rpc_svc.c create mode 100644 krb5-1.21.3/src/kadmin/server/misc.c create mode 100644 krb5-1.21.3/src/kadmin/server/misc.h create mode 100644 krb5-1.21.3/src/kadmin/server/ovsec_kadmd.c create mode 100644 krb5-1.21.3/src/kadmin/server/schpw.c create mode 100644 krb5-1.21.3/src/kadmin/server/server_stubs.c create mode 100644 krb5-1.21.3/src/kdc/Makefile.in create mode 100644 krb5-1.21.3/src/kdc/authind.c create mode 100644 krb5-1.21.3/src/kdc/cammac.c create mode 100644 krb5-1.21.3/src/kdc/deps create mode 100644 krb5-1.21.3/src/kdc/dispatch.c create mode 100644 krb5-1.21.3/src/kdc/do_as_req.c create mode 100644 krb5-1.21.3/src/kdc/do_tgs_req.c create mode 100644 krb5-1.21.3/src/kdc/extern.c create mode 100644 krb5-1.21.3/src/kdc/extern.h create mode 100644 krb5-1.21.3/src/kdc/fast_util.c create mode 100644 krb5-1.21.3/src/kdc/kdc5_err.et create mode 100644 krb5-1.21.3/src/kdc/kdc_audit.c create mode 100644 krb5-1.21.3/src/kdc/kdc_audit.h create mode 100644 krb5-1.21.3/src/kdc/kdc_authdata.c create mode 100644 krb5-1.21.3/src/kdc/kdc_log.c create mode 100644 krb5-1.21.3/src/kdc/kdc_preauth.c create mode 100644 krb5-1.21.3/src/kdc/kdc_preauth_ec.c create mode 100644 krb5-1.21.3/src/kdc/kdc_preauth_encts.c create mode 100644 krb5-1.21.3/src/kdc/kdc_transit.c create mode 100644 krb5-1.21.3/src/kdc/kdc_util.c create mode 100644 krb5-1.21.3/src/kdc/kdc_util.h create mode 100644 krb5-1.21.3/src/kdc/main.c create mode 100644 krb5-1.21.3/src/kdc/ndr.c create mode 100644 krb5-1.21.3/src/kdc/policy.c create mode 100644 krb5-1.21.3/src/kdc/policy.h create mode 100644 krb5-1.21.3/src/kdc/realm_data.h create mode 100644 krb5-1.21.3/src/kdc/replay.c create mode 100644 krb5-1.21.3/src/kdc/reqstate.h create mode 100644 krb5-1.21.3/src/kdc/rtest.c create mode 100644 krb5-1.21.3/src/kdc/rtest.good create mode 100755 krb5-1.21.3/src/kdc/rtscript create mode 100644 krb5-1.21.3/src/kdc/t_bigreply.py create mode 100755 krb5-1.21.3/src/kdc/t_emptytgt.py create mode 100644 krb5-1.21.3/src/kdc/t_ndr.c create mode 100644 krb5-1.21.3/src/kdc/t_replay.c create mode 100755 krb5-1.21.3/src/kdc/t_workers.py create mode 100644 krb5-1.21.3/src/kdc/tgs_policy.c create mode 100644 krb5-1.21.3/src/kprop/Makefile.in create mode 100644 krb5-1.21.3/src/kprop/deps create mode 100644 krb5-1.21.3/src/kprop/kprop.c create mode 100644 krb5-1.21.3/src/kprop/kprop.h create mode 100644 krb5-1.21.3/src/kprop/kprop_util.c create mode 100644 krb5-1.21.3/src/kprop/kpropd.c create mode 100644 krb5-1.21.3/src/kprop/kpropd_rpc.c create mode 100644 krb5-1.21.3/src/kprop/kproplog.c create mode 100644 krb5-1.21.3/src/kprop/replica_update create mode 100644 krb5-1.21.3/src/lib/Makefile.in create mode 100644 krb5-1.21.3/src/lib/apputils/Makefile.in create mode 100644 krb5-1.21.3/src/lib/apputils/daemon.c create mode 100644 krb5-1.21.3/src/lib/apputils/deps create mode 100644 krb5-1.21.3/src/lib/apputils/net-server.c create mode 100644 krb5-1.21.3/src/lib/apputils/udppktinfo.c create mode 100644 krb5-1.21.3/src/lib/apputils/udppktinfo.h create mode 100644 krb5-1.21.3/src/lib/comerr32.def create mode 100644 krb5-1.21.3/src/lib/crypto/ISSUES create mode 100644 krb5-1.21.3/src/lib/crypto/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/aes-gen.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/aes.h create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/aes.txt create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/aescrypt.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/aeskey.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/aesopt.h create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/aestab.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/aestab.h create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/brg_endian.h create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/brg_types.h create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/deps create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/iaesx64.s create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/iaesx86.s create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/aes/kresults.expected create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/camellia/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/camellia/camellia-gen.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/camellia/camellia.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/camellia/camellia.h create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/camellia/deps create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/cmac.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/deps create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/ISSUES create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/d3_aead.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/d3_kysched.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/deps create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/des_int.h create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/des_keys.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/destest.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/doc/libdes.doc create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/f_aead.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/f_cbc.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/f_cksum.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/f_parity.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/f_sched.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/f_tables.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/f_tables.h create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/key_sched.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/keytest.data create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/t_verify.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/des/weak_key.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/enc_provider/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/enc_provider/aes.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/enc_provider/camellia.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/enc_provider/deps create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/enc_provider/des3.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/enc_provider/rc4.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/hash_provider/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/hash_provider/deps create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_md4.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_md5.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_sha1.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_sha2.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/hmac.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/kdf.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/md4/ISSUES create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/md4/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/md4/deps create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/md4/md4.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/md4/rsa-md4.h create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/md5/ISSUES create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/md5/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/md5/deps create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/md5/md5.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/md5/rsa-md5.h create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/pbkdf2.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/sha1/ISSUES create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/sha1/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/sha1/deps create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/sha1/shs.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/sha1/shs.h create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/sha1/t_shs.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/sha1/t_shs3.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/sha2/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/sha2/deps create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/sha2/sha2.h create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/sha2/sha256.c create mode 100644 krb5-1.21.3/src/lib/crypto/builtin/sha2/sha512.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/Poly.pm create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/aes-test.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/camellia-expect-vt.txt create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/camellia-test.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/deps create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/expect-vk.txt create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/expect-vt.txt create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.comments create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.expected create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.in create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_cksums.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_cmac.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_cts.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_decrypt.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_derive.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_encrypt.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_fork.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_hmac.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_kperf.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_mdcksum.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_mddriver.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_nfold.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_pkcs5.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_prf.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_prng.comments create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_prng.expected create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_prng.seed create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_sha2.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_short.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/t_str2key.c create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/test/Readme.txt create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/test/cbc_d_m.txt create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/test/cbc_e_m.txt create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_d_m.txt create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_e_m.txt create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_iv.readme create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_iv.txt create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_tbl.txt create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_vk.txt create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_vt.txt create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/test/katmct.pdf create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/vb.txt create mode 100644 krb5-1.21.3/src/lib/crypto/crypto_tests/vectors.c create mode 100644 krb5-1.21.3/src/lib/crypto/deps create mode 100644 krb5-1.21.3/src/lib/crypto/krb/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/krb/aead.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/block_size.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/cf2.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/checksum_dk_cmac.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/checksum_dk_hmac.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/checksum_etm.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/checksum_hmac_md5.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/checksum_length.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/checksum_unkeyed.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/cksumtype_to_string.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/cksumtypes.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/coll_proof_cksum.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/crypto_int.h create mode 100644 krb5-1.21.3/src/lib/crypto/krb/crypto_length.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/decrypt.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/decrypt_iov.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/default_state.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/deps create mode 100644 krb5-1.21.3/src/lib/crypto/krb/derive.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/enc_dk_cmac.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/enc_dk_hmac.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/enc_etm.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/enc_raw.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/enc_rc4.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/encrypt.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/encrypt_iov.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/encrypt_length.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/enctype_util.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/etypes.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/key.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/keyblocks.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/keyed_checksum_types.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/keyed_cksum.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/keylengths.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/make_checksum.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/make_checksum_iov.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/make_random_key.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/mandatory_sumtype.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/nfold.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/old_api_glue.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/prf.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/prf_aes2.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/prf_cmac.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/prf_des.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/prf_dk.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/prf_rc4.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/prng.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/random_to_key.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/s2k_pbkdf2.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/s2k_rc4.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/state.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/string_to_cksumtype.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/string_to_key.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/valid_cksumtype.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/verify_checksum.c create mode 100644 krb5-1.21.3/src/lib/crypto/krb/verify_checksum_iov.c create mode 100644 krb5-1.21.3/src/lib/crypto/libk5crypto.exports create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/cmac.c create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/deps create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/des/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/des/deps create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/des/des_keys.c create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/enc_provider/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/enc_provider/aes.c create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/enc_provider/camellia.c create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/enc_provider/deps create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/enc_provider/des3.c create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/enc_provider/rc4.c create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/hash_provider/Makefile.in create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/hash_provider/deps create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/hash_provider/hash_evp.c create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/hmac.c create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/kdf.c create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/pbkdf2.c create mode 100644 krb5-1.21.3/src/lib/crypto/openssl/sha256.c create mode 100644 krb5-1.21.3/src/lib/deps create mode 100644 krb5-1.21.3/src/lib/gssapi/LICENSE create mode 100644 krb5-1.21.3/src/lib/gssapi/Makefile.in create mode 100644 krb5-1.21.3/src/lib/gssapi/README_SAMPLE_APP create mode 100644 krb5-1.21.3/src/lib/gssapi/deps create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/Makefile.in create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/deps create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/disp_com_err_status.c create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/disp_major_status.c create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/gssapi.hin create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/gssapiP_generic.h create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/gssapi_alloc.h create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/gssapi_err_generic.et create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/gssapi_ext.h create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/gssapi_generic.c create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/gssapi_generic.h create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/maptest.c create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/oid_ops.c create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/rel_buffer.c create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/rel_oid_set.c create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/t_seqstate.c create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/util_buffer.c create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/util_buffer_set.c create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/util_errmap.c create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/util_seqstate.c create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/util_set.c create mode 100644 krb5-1.21.3/src/lib/gssapi/generic/util_token.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/Makefile.in create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/accept_sec_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/acquire_cred.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/canon_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/compare_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/context_time.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/copy_ccache.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/cred_store.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/delete_sec_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/deps create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/disp_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/disp_status.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/duplicate_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/export_cred.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/export_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/export_sec_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/get_tkt_flags.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/gssapiP_krb5.h create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/gssapi_err_krb5.et create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/gssapi_krb5.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/gssapi_krb5.h create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/iakerb.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/import_cred.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/import_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/import_sec_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/indicate_mechs.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/init_sec_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/inq_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/inq_cred.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/inq_names.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/k5seal.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/k5sealiov.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/k5sealv3.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/k5sealv3iov.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/k5unseal.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/k5unsealiov.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/krb5_gss_glue.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/lucid_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/naming_exts.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/prf.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/process_context_token.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/rel_cred.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/rel_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/rel_oid.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/s4u_gss_glue.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/ser_sctx.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/set_allowable_enctypes.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/set_ccache.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/store_cred.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/util_cksum.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/util_crypt.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/util_seed.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/util_seqnum.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/val_cred.c create mode 100644 krb5-1.21.3/src/lib/gssapi/krb5/wrap_size_limit.c create mode 100644 krb5-1.21.3/src/lib/gssapi/libgssapi_krb5.exports create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/Makefile.in create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/deps create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_accept_sec_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_acquire_cred.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_acquire_cred_with_pw.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_authorize_localname.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_buffer_set.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_canon_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_compare_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_complete_auth_token.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_context_time.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_decapsulate_token.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_del_name_attr.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_delete_sec_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_dsp_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_dsp_name_ext.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_dsp_status.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_dup_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_encapsulate_token.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_exp_sec_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_export_cred.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_export_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_export_name_comp.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_get_name_attr.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_glue.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_imp_cred.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_imp_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_imp_sec_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_init_sec_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_initialize.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_context_oid.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_cred.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_cred_oid.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_names.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_map_name_to_any.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_mech_invoke.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_mechattr.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_mechname.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_negoex.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_oid_ops.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_prf.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_process_context.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_buffer.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_cred.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_name.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_name_mapping.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_oid_set.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_saslname.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_seal.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_set_context_option.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_set_cred_option.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_set_name_attr.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_set_neg_mechs.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_sign.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_store_cred.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_unseal.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_unwrap_aead.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_unwrap_iov.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_verify.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_wrap_aead.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/g_wrap_iov.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/gssd_pname_to_uid.c create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/mechglue.h create mode 100644 krb5-1.21.3/src/lib/gssapi/mechglue/mglueP.h create mode 100644 krb5-1.21.3/src/lib/gssapi/spnego/Makefile.in create mode 100644 krb5-1.21.3/src/lib/gssapi/spnego/deps create mode 100644 krb5-1.21.3/src/lib/gssapi/spnego/gssapiP_negoex.h create mode 100644 krb5-1.21.3/src/lib/gssapi/spnego/gssapiP_spnego.h create mode 100644 krb5-1.21.3/src/lib/gssapi/spnego/mech_spnego.exports create mode 100644 krb5-1.21.3/src/lib/gssapi/spnego/negoex_ctx.c create mode 100644 krb5-1.21.3/src/lib/gssapi/spnego/negoex_trace.c create mode 100644 krb5-1.21.3/src/lib/gssapi/spnego/negoex_util.c create mode 100644 krb5-1.21.3/src/lib/gssapi/spnego/spnego_mech.c create mode 100644 krb5-1.21.3/src/lib/gssapi32.def create mode 100644 krb5-1.21.3/src/lib/kadm5/Makefile.in create mode 100644 krb5-1.21.3/src/lib/kadm5/admin.h create mode 100644 krb5-1.21.3/src/lib/kadm5/admin_internal.h create mode 100644 krb5-1.21.3/src/lib/kadm5/admin_xdr.h create mode 100644 krb5-1.21.3/src/lib/kadm5/alt_prof.c create mode 100644 krb5-1.21.3/src/lib/kadm5/chpass_util.c create mode 100644 krb5-1.21.3/src/lib/kadm5/chpass_util_strings.et create mode 100644 krb5-1.21.3/src/lib/kadm5/clnt/Makefile.in create mode 100644 krb5-1.21.3/src/lib/kadm5/clnt/client_handle.c create mode 100644 krb5-1.21.3/src/lib/kadm5/clnt/client_init.c create mode 100644 krb5-1.21.3/src/lib/kadm5/clnt/client_internal.h create mode 100644 krb5-1.21.3/src/lib/kadm5/clnt/client_principal.c create mode 100644 krb5-1.21.3/src/lib/kadm5/clnt/client_rpc.c create mode 100644 krb5-1.21.3/src/lib/kadm5/clnt/clnt_chpass_util.c create mode 100644 krb5-1.21.3/src/lib/kadm5/clnt/clnt_policy.c create mode 100644 krb5-1.21.3/src/lib/kadm5/clnt/clnt_privs.c create mode 100644 krb5-1.21.3/src/lib/kadm5/clnt/deps create mode 100644 krb5-1.21.3/src/lib/kadm5/clnt/libkadm5clnt_mit.exports create mode 100644 krb5-1.21.3/src/lib/kadm5/deps create mode 100644 krb5-1.21.3/src/lib/kadm5/kadm_err.et create mode 100644 krb5-1.21.3/src/lib/kadm5/kadm_rpc.h create mode 100644 krb5-1.21.3/src/lib/kadm5/kadm_rpc_xdr.c create mode 100644 krb5-1.21.3/src/lib/kadm5/logger.c create mode 100644 krb5-1.21.3/src/lib/kadm5/misc_free.c create mode 100644 krb5-1.21.3/src/lib/kadm5/server_internal.h create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/Makefile.in create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/adb_xdr.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/deps create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/kadm5_hook.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/libkadm5srv_mit.exports create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/pwqual.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/pwqual_dict.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/pwqual_empty.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/pwqual_hesiod.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/pwqual_princ.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/server_handle.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/server_init.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/server_kdb.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/server_misc.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/svr_chpass_util.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/svr_iters.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/svr_policy.c create mode 100644 krb5-1.21.3/src/lib/kadm5/srv/svr_principal.c create mode 100644 krb5-1.21.3/src/lib/kadm5/str_conv.c create mode 100644 krb5-1.21.3/src/lib/kadm5/t_kadm5.c create mode 100644 krb5-1.21.3/src/lib/kadm5/t_kadm5.py create mode 100644 krb5-1.21.3/src/lib/kdb/Makefile.in create mode 100644 krb5-1.21.3/src/lib/kdb/adb_err.et create mode 100644 krb5-1.21.3/src/lib/kdb/decrypt_key.c create mode 100644 krb5-1.21.3/src/lib/kdb/deps create mode 100644 krb5-1.21.3/src/lib/kdb/encrypt_key.c create mode 100644 krb5-1.21.3/src/lib/kdb/iprop.x create mode 100644 krb5-1.21.3/src/lib/kdb/iprop_xdr.c create mode 100644 krb5-1.21.3/src/lib/kdb/kdb5.c create mode 100644 krb5-1.21.3/src/lib/kdb/kdb5.h create mode 100644 krb5-1.21.3/src/lib/kdb/kdb5int.h create mode 100644 krb5-1.21.3/src/lib/kdb/kdb_convert.c create mode 100644 krb5-1.21.3/src/lib/kdb/kdb_cpw.c create mode 100644 krb5-1.21.3/src/lib/kdb/kdb_default.c create mode 100644 krb5-1.21.3/src/lib/kdb/kdb_log.c create mode 100644 krb5-1.21.3/src/lib/kdb/keytab.c create mode 100644 krb5-1.21.3/src/lib/kdb/libkdb5.exports create mode 100644 krb5-1.21.3/src/lib/kdb/t_sort_key_data.c create mode 100644 krb5-1.21.3/src/lib/kdb/t_stringattr.c create mode 100755 krb5-1.21.3/src/lib/kdb/t_stringattr.py create mode 100644 krb5-1.21.3/src/lib/kdb/t_ulog.c create mode 100644 krb5-1.21.3/src/lib/krad/Makefile.in create mode 100644 krb5-1.21.3/src/lib/krad/attr.c create mode 100644 krb5-1.21.3/src/lib/krad/attrset.c create mode 100644 krb5-1.21.3/src/lib/krad/client.c create mode 100644 krb5-1.21.3/src/lib/krad/code.c create mode 100644 krb5-1.21.3/src/lib/krad/deps create mode 100644 krb5-1.21.3/src/lib/krad/internal.h create mode 100644 krb5-1.21.3/src/lib/krad/libkrad.exports create mode 100644 krb5-1.21.3/src/lib/krad/packet.c create mode 100644 krb5-1.21.3/src/lib/krad/remote.c create mode 100644 krb5-1.21.3/src/lib/krad/t_attr.c create mode 100644 krb5-1.21.3/src/lib/krad/t_attrset.c create mode 100644 krb5-1.21.3/src/lib/krad/t_client.c create mode 100644 krb5-1.21.3/src/lib/krad/t_code.c create mode 100644 krb5-1.21.3/src/lib/krad/t_daemon.h create mode 100755 krb5-1.21.3/src/lib/krad/t_daemon.py create mode 100644 krb5-1.21.3/src/lib/krad/t_packet.c create mode 100644 krb5-1.21.3/src/lib/krad/t_remote.c create mode 100644 krb5-1.21.3/src/lib/krad/t_test.c create mode 100644 krb5-1.21.3/src/lib/krad/t_test.h create mode 100644 krb5-1.21.3/src/lib/krb5.rc create mode 100644 krb5-1.21.3/src/lib/krb5/Makefile.in create mode 100644 krb5-1.21.3/src/lib/krb5/asn.1/KRB5-asn.py create mode 100644 krb5-1.21.3/src/lib/krb5/asn.1/Makefile.in create mode 100644 krb5-1.21.3/src/lib/krb5/asn.1/README.asn1 create mode 100644 krb5-1.21.3/src/lib/krb5/asn.1/TODO.asn1 create mode 100644 krb5-1.21.3/src/lib/krb5/asn.1/asn1_encode.c create mode 100644 krb5-1.21.3/src/lib/krb5/asn.1/asn1_encode.h create mode 100644 krb5-1.21.3/src/lib/krb5/asn.1/asn1_k_encode.c create mode 100644 krb5-1.21.3/src/lib/krb5/asn.1/deps create mode 100644 krb5-1.21.3/src/lib/krb5/asn.1/krbasn1.h create mode 100644 krb5-1.21.3/src/lib/krb5/asn.1/ldap_key_seq.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/Makefile.in create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/cc-int.h create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/cc_api_macos.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/cc_dir.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/cc_file.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/cc_kcm.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/cc_keyring.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/cc_memory.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/cc_mslsa.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/cc_retr.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccapi/Makefile.in create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccapi/deps create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccapi/stdcc.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccapi/stdcc.h create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccapi/winccld.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccapi/winccld.h create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccapi_util.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccapi_util.h create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccbase.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/cccopy.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/cccursor.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccdefault.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccdefops.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccfns.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccmarshal.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccselect.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccselect_hostname.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccselect_k5identity.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/ccselect_realm.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/deps create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/fcc.h create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/kcmrpc.defs create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/kcmrpc_types.h create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/scc.h create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/t_cc.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/t_cccol.c create mode 100755 krb5-1.21.3/src/lib/krb5/ccache/t_cccol.py create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/t_cccursor.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/t_marshal.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/t_memory.c create mode 100644 krb5-1.21.3/src/lib/krb5/ccache/t_stdio.c create mode 100644 krb5-1.21.3/src/lib/krb5/deps create mode 100644 krb5-1.21.3/src/lib/krb5/error_tables/Makefile.in create mode 100644 krb5-1.21.3/src/lib/krb5/error_tables/asn1_err.et create mode 100644 krb5-1.21.3/src/lib/krb5/error_tables/deps create mode 100644 krb5-1.21.3/src/lib/krb5/error_tables/init_ets.c create mode 100644 krb5-1.21.3/src/lib/krb5/error_tables/k5e1_err.et create mode 100644 krb5-1.21.3/src/lib/krb5/error_tables/kdb5_err.et create mode 100644 krb5-1.21.3/src/lib/krb5/error_tables/krb524_err.et create mode 100644 krb5-1.21.3/src/lib/krb5/error_tables/krb5_err.et create mode 100644 krb5-1.21.3/src/lib/krb5/error_tables/kv5m_err.et create mode 100644 krb5-1.21.3/src/lib/krb5/keytab/Makefile.in create mode 100644 krb5-1.21.3/src/lib/krb5/keytab/deps create mode 100644 krb5-1.21.3/src/lib/krb5/keytab/kt-int.h create mode 100644 krb5-1.21.3/src/lib/krb5/keytab/kt_file.c create mode 100644 krb5-1.21.3/src/lib/krb5/keytab/kt_memory.c create mode 100644 krb5-1.21.3/src/lib/krb5/keytab/ktadd.c create mode 100644 krb5-1.21.3/src/lib/krb5/keytab/ktbase.c create mode 100644 krb5-1.21.3/src/lib/krb5/keytab/ktdefault.c create mode 100644 krb5-1.21.3/src/lib/krb5/keytab/ktfns.c create mode 100644 krb5-1.21.3/src/lib/krb5/keytab/ktfr_entry.c create mode 100644 krb5-1.21.3/src/lib/krb5/keytab/ktremove.c create mode 100644 krb5-1.21.3/src/lib/krb5/keytab/read_servi.c create mode 100644 krb5-1.21.3/src/lib/krb5/keytab/t_keytab.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/Makefile.in create mode 100644 krb5-1.21.3/src/lib/krb5/krb/addr_comp.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/addr_order.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/addr_srch.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/ai_authdata.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/allow_weak.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/appdefault.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/auth_con.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/auth_con.h create mode 100644 krb5-1.21.3/src/lib/krb5/krb/authdata.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/authdata.h create mode 100644 krb5-1.21.3/src/lib/krb5/krb/authdata_dec.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/authdata_enc.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/authdata_exp.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/bld_pr_ext.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/bld_princ.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/brand.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/cammac_util.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/chk_trans.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/chpw.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/conv_creds.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/conv_princ.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/copy_addrs.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/copy_athctr.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/copy_auth.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/copy_cksum.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/copy_creds.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/copy_ctx.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/copy_data.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/copy_key.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/copy_princ.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/copy_tick.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/cp_key_cnt.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/decode_kdc.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/decrypt_tk.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/deltat.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/deps create mode 100644 krb5-1.21.3/src/lib/krb5/krb/enc_helper.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/enc_keyhelper.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/encode_kdc.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/encrypt_tk.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/etype_list.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/fast.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/fast.h create mode 100644 krb5-1.21.3/src/lib/krb5/krb/fwd_tgt.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/gc_via_tkt.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/gen_save_subkey.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/gen_seqnum.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/gen_subkey.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/get_creds.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/get_etype_info.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/get_in_tkt.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/gic_keytab.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/gic_opt.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/gic_pwd.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/in_tkt_sky.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/init_creds_ctx.h create mode 100644 krb5-1.21.3/src/lib/krb5/krb/init_ctx.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/init_keyblock.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/int-proto.h create mode 100644 krb5-1.21.3/src/lib/krb5/krb/kdc_rep_dc.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/kerrs.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/kfree.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/libdef_parse.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/mk_cred.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/mk_error.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/mk_priv.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/mk_rep.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/mk_req.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/mk_req_ext.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/mk_safe.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/pac.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/pac_sign.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/padata.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/parse.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/parse_host_string.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/plugin.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/pr_to_salt.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/preauth2.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/preauth_ec.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/preauth_encts.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/preauth_otp.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/preauth_pkinit.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/preauth_sam2.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/princ_comp.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/privsafe.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/random_str.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/rd_cred.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/rd_error.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/rd_priv.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/rd_rep.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/rd_req.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/rd_req_dec.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/rd_safe.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/recvauth.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/response_items.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/s4u_creds.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/send_tgs.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/sendauth.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/ser_actx.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/ser_adata.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/ser_addr.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/ser_auth.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/ser_cksum.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/ser_ctx.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/ser_key.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/ser_princ.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/serialize.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/set_realm.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/sname_match.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/srv_dec_tkt.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/srv_rcache.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/str_conv.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/strptime.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_ad_fx_armor.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_authdata.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_cc_config.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_copy_context.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_deltat.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_etypes.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_expand.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_expire_warn.c create mode 100755 krb5-1.21.3/src/lib/krb5/krb/t_expire_warn.py create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_get_etype_info.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_get_etype_info.py create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_in_ccache.c create mode 100755 krb5-1.21.3/src/lib/krb5/krb/t_in_ccache_patypes.py create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_kerb.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_krb5.conf create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_pac.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_parse_host_string.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_princ.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_ref_kerb.out create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_response_items.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_ser.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_sname_match.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_valid_times.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_vfy_increds.c create mode 100755 krb5-1.21.3/src/lib/krb5/krb/t_vfy_increds.py create mode 100644 krb5-1.21.3/src/lib/krb5/krb/t_walk_rtree.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/tgtname.c create mode 100755 krb5-1.21.3/src/lib/krb5/krb/transit-tests create mode 100644 krb5-1.21.3/src/lib/krb5/krb/unparse.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/val_renew.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/valid_times.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/vfy_increds.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/vic_opt.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/walk_rtree.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb/walktree-tests create mode 100644 krb5-1.21.3/src/lib/krb5/krb/x-deltat.y create mode 100644 krb5-1.21.3/src/lib/krb5/krb5_libinit.c create mode 100644 krb5-1.21.3/src/lib/krb5/krb5_libinit.h create mode 100644 krb5-1.21.3/src/lib/krb5/libkrb5.exports create mode 100644 krb5-1.21.3/src/lib/krb5/os/Makefile.in create mode 100644 krb5-1.21.3/src/lib/krb5/os/accessor.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/c_ustime.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/ccdefname.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/changepw.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/deps create mode 100644 krb5-1.21.3/src/lib/krb5/os/dnsglue.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/dnsglue.h create mode 100644 krb5-1.21.3/src/lib/krb5/os/dnssrv.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/expand_path.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/full_ipadr.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/gen_port.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/gen_rname.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/genaddrs.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/hostaddr.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/hostrealm.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/hostrealm_dns.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/hostrealm_domain.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/hostrealm_profile.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/hostrealm_registry.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/init_os_ctx.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/krbfileio.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/ktdefname.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/localaddr.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/localauth.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/localauth_an2ln.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/localauth_k5login.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/localauth_names.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/localauth_rule.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/locate_kdc.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/lock_file.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/mk_faddr.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/net_read.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/net_write.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/os-proto.h create mode 100644 krb5-1.21.3/src/lib/krb5/os/port2ip.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/prompter.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/read_msg.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/read_pwd.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/realm_dom.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/ref_std_conf.out create mode 100644 krb5-1.21.3/src/lib/krb5/os/sendto_kdc.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/sn2princ.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/t_an_to_ln.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/t_discover_uri.py create mode 100644 krb5-1.21.3/src/lib/krb5/os/t_expand_path.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/t_gifconf.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/t_kuserok.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/t_locate_kdc.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/t_std_conf.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/t_trace.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/t_trace.ref create mode 100644 krb5-1.21.3/src/lib/krb5/os/td_krb5.conf create mode 100644 krb5-1.21.3/src/lib/krb5/os/thread_safe.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/timeofday.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/toffset.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/trace.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/unlck_file.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/ustime.c create mode 100644 krb5-1.21.3/src/lib/krb5/os/write_msg.c create mode 100644 krb5-1.21.3/src/lib/krb5/posix/Makefile.in create mode 100644 krb5-1.21.3/src/lib/krb5/posix/syslog.c create mode 100644 krb5-1.21.3/src/lib/krb5/rcache/Makefile.in create mode 100644 krb5-1.21.3/src/lib/krb5/rcache/RELEASE create mode 100644 krb5-1.21.3/src/lib/krb5/rcache/deps create mode 100644 krb5-1.21.3/src/lib/krb5/rcache/memrcache.c create mode 100644 krb5-1.21.3/src/lib/krb5/rcache/memrcache.h create mode 100644 krb5-1.21.3/src/lib/krb5/rcache/rc-int.h create mode 100644 krb5-1.21.3/src/lib/krb5/rcache/rc_base.c create mode 100644 krb5-1.21.3/src/lib/krb5/rcache/rc_dfl.c create mode 100644 krb5-1.21.3/src/lib/krb5/rcache/rc_file2.c create mode 100644 krb5-1.21.3/src/lib/krb5/rcache/rc_none.c create mode 100644 krb5-1.21.3/src/lib/krb5/rcache/t_memrcache.c create mode 100644 krb5-1.21.3/src/lib/krb5/rcache/t_rcfile2.c create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/CompositionExclusions.txt create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/Makefile.in create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/UCD-Terms create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/UnicodeData.txt create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/deps create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/ucdata/MUTTUCData.txt create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/ucdata/README create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/ucdata/api.txt create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/ucdata/format.txt create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/ucdata/ucdata.c create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/ucdata/ucdata.h create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/ucdata/ucdata.man create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/ucdata/ucgendat.c create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/ucdata/uctable.h create mode 100644 krb5-1.21.3/src/lib/krb5/unicode/ucstr.c create mode 100644 krb5-1.21.3/src/lib/krb5_32.def create mode 100644 krb5-1.21.3/src/lib/rpc/Makefile.in create mode 100644 krb5-1.21.3/src/lib/rpc/auth_gss.c create mode 100644 krb5-1.21.3/src/lib/rpc/auth_gssapi.c create mode 100644 krb5-1.21.3/src/lib/rpc/auth_gssapi_misc.c create mode 100644 krb5-1.21.3/src/lib/rpc/auth_none.c create mode 100644 krb5-1.21.3/src/lib/rpc/auth_unix.c create mode 100644 krb5-1.21.3/src/lib/rpc/authgss_prot.c create mode 100644 krb5-1.21.3/src/lib/rpc/authunix_prot.c create mode 100644 krb5-1.21.3/src/lib/rpc/bindresvport.c create mode 100644 krb5-1.21.3/src/lib/rpc/clnt_generic.c create mode 100644 krb5-1.21.3/src/lib/rpc/clnt_perror.c create mode 100644 krb5-1.21.3/src/lib/rpc/clnt_raw.c create mode 100644 krb5-1.21.3/src/lib/rpc/clnt_simple.c create mode 100644 krb5-1.21.3/src/lib/rpc/clnt_tcp.c create mode 100644 krb5-1.21.3/src/lib/rpc/clnt_udp.c create mode 100644 krb5-1.21.3/src/lib/rpc/deps create mode 100644 krb5-1.21.3/src/lib/rpc/dyn.c create mode 100644 krb5-1.21.3/src/lib/rpc/dyn.h create mode 100644 krb5-1.21.3/src/lib/rpc/dynP.h create mode 100644 krb5-1.21.3/src/lib/rpc/dyntest.c create mode 100644 krb5-1.21.3/src/lib/rpc/get_myaddress.c create mode 100644 krb5-1.21.3/src/lib/rpc/getrpcent.c create mode 100644 krb5-1.21.3/src/lib/rpc/getrpcport.c create mode 100644 krb5-1.21.3/src/lib/rpc/gssrpcint.h create mode 100644 krb5-1.21.3/src/lib/rpc/libgssrpc.exports create mode 100644 krb5-1.21.3/src/lib/rpc/pmap_clnt.c create mode 100644 krb5-1.21.3/src/lib/rpc/pmap_getmaps.c create mode 100644 krb5-1.21.3/src/lib/rpc/pmap_getport.c create mode 100644 krb5-1.21.3/src/lib/rpc/pmap_prot.c create mode 100644 krb5-1.21.3/src/lib/rpc/pmap_prot2.c create mode 100644 krb5-1.21.3/src/lib/rpc/pmap_rmt.c create mode 100644 krb5-1.21.3/src/lib/rpc/rpc_callmsg.c create mode 100644 krb5-1.21.3/src/lib/rpc/rpc_commondata.c create mode 100644 krb5-1.21.3/src/lib/rpc/rpc_dtablesize.c create mode 100644 krb5-1.21.3/src/lib/rpc/rpc_prot.c create mode 100644 krb5-1.21.3/src/lib/rpc/svc.c create mode 100644 krb5-1.21.3/src/lib/rpc/svc_auth.c create mode 100644 krb5-1.21.3/src/lib/rpc/svc_auth_gss.c create mode 100644 krb5-1.21.3/src/lib/rpc/svc_auth_gssapi.c create mode 100644 krb5-1.21.3/src/lib/rpc/svc_auth_none.c create mode 100644 krb5-1.21.3/src/lib/rpc/svc_auth_unix.c create mode 100644 krb5-1.21.3/src/lib/rpc/svc_raw.c create mode 100644 krb5-1.21.3/src/lib/rpc/svc_run.c create mode 100644 krb5-1.21.3/src/lib/rpc/svc_simple.c create mode 100644 krb5-1.21.3/src/lib/rpc/svc_tcp.c create mode 100644 krb5-1.21.3/src/lib/rpc/svc_udp.c create mode 100644 krb5-1.21.3/src/lib/rpc/unit-test/Makefile.in create mode 100644 krb5-1.21.3/src/lib/rpc/unit-test/client.c create mode 100644 krb5-1.21.3/src/lib/rpc/unit-test/deps create mode 100644 krb5-1.21.3/src/lib/rpc/unit-test/rpc_test.h create mode 100644 krb5-1.21.3/src/lib/rpc/unit-test/rpc_test.x create mode 100644 krb5-1.21.3/src/lib/rpc/unit-test/rpc_test_clnt.c create mode 100644 krb5-1.21.3/src/lib/rpc/unit-test/rpc_test_svc.c create mode 100644 krb5-1.21.3/src/lib/rpc/unit-test/server.c create mode 100644 krb5-1.21.3/src/lib/rpc/unit-test/t_rpc.py create mode 100644 krb5-1.21.3/src/lib/rpc/xdr.c create mode 100644 krb5-1.21.3/src/lib/rpc/xdr_alloc.c create mode 100644 krb5-1.21.3/src/lib/rpc/xdr_array.c create mode 100644 krb5-1.21.3/src/lib/rpc/xdr_float.c create mode 100644 krb5-1.21.3/src/lib/rpc/xdr_mem.c create mode 100644 krb5-1.21.3/src/lib/rpc/xdr_rec.c create mode 100644 krb5-1.21.3/src/lib/rpc/xdr_reference.c create mode 100644 krb5-1.21.3/src/lib/rpc/xdr_sizeof.c create mode 100644 krb5-1.21.3/src/lib/rpc/xdr_stdio.c create mode 100644 krb5-1.21.3/src/lib/win_glue.c create mode 100644 krb5-1.21.3/src/lib/xpprof32.def create mode 100644 krb5-1.21.3/src/man/Makefile.in create mode 100644 krb5-1.21.3/src/man/README create mode 100644 krb5-1.21.3/src/man/deps create mode 100644 krb5-1.21.3/src/man/dot.k5identity.5 create mode 100644 krb5-1.21.3/src/man/dot.k5login.5 create mode 100644 krb5-1.21.3/src/man/k5identity.man create mode 100644 krb5-1.21.3/src/man/k5login.man create mode 100644 krb5-1.21.3/src/man/k5srvutil.man create mode 100644 krb5-1.21.3/src/man/kadm5.acl.man create mode 100644 krb5-1.21.3/src/man/kadmin.local.8 create mode 100644 krb5-1.21.3/src/man/kadmin.man create mode 100644 krb5-1.21.3/src/man/kadmind.man create mode 100644 krb5-1.21.3/src/man/kdb5_ldap_util.man create mode 100644 krb5-1.21.3/src/man/kdb5_util.man create mode 100644 krb5-1.21.3/src/man/kdc.conf.man create mode 100644 krb5-1.21.3/src/man/kdestroy.man create mode 100644 krb5-1.21.3/src/man/kerberos.man create mode 100644 krb5-1.21.3/src/man/kinit.man create mode 100644 krb5-1.21.3/src/man/klist.man create mode 100644 krb5-1.21.3/src/man/kpasswd.man create mode 100644 krb5-1.21.3/src/man/kprop.man create mode 100644 krb5-1.21.3/src/man/kpropd.man create mode 100644 krb5-1.21.3/src/man/kproplog.man create mode 100644 krb5-1.21.3/src/man/krb5-config.man create mode 100644 krb5-1.21.3/src/man/krb5.conf.man create mode 100644 krb5-1.21.3/src/man/krb5kdc.man create mode 100644 krb5-1.21.3/src/man/ksu.man create mode 100644 krb5-1.21.3/src/man/kswitch.man create mode 100644 krb5-1.21.3/src/man/ktutil.man create mode 100644 krb5-1.21.3/src/man/kvno.man create mode 100644 krb5-1.21.3/src/man/sclient.man create mode 100644 krb5-1.21.3/src/man/sserver.man create mode 100644 krb5-1.21.3/src/patchlevel.h create mode 100644 krb5-1.21.3/src/plugins/audit/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/audit/deps create mode 100644 krb5-1.21.3/src/plugins/audit/j_dict.h create mode 100755 krb5-1.21.3/src/plugins/audit/kdc_j_encode.c create mode 100644 krb5-1.21.3/src/plugins/audit/kdc_j_encode.h create mode 100644 krb5-1.21.3/src/plugins/audit/libauditjenc.exports create mode 100644 krb5-1.21.3/src/plugins/audit/simple/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/audit/simple/au_simple_main.c create mode 100644 krb5-1.21.3/src/plugins/audit/simple/deps create mode 100644 krb5-1.21.3/src/plugins/audit/simple/k5audit.exports create mode 100644 krb5-1.21.3/src/plugins/audit/test/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/audit/test/au_test.c create mode 100644 krb5-1.21.3/src/plugins/audit/test/deps create mode 100644 krb5-1.21.3/src/plugins/audit/test/k5audit_test.exports create mode 100644 krb5-1.21.3/src/plugins/authdata/greet_client/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/authdata/greet_client/deps create mode 100644 krb5-1.21.3/src/plugins/authdata/greet_client/greet.c create mode 100644 krb5-1.21.3/src/plugins/authdata/greet_client/greet_client.exports create mode 100644 krb5-1.21.3/src/plugins/authdata/greet_server/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/authdata/greet_server/deps create mode 100644 krb5-1.21.3/src/plugins/authdata/greet_server/greet_auth.c create mode 100644 krb5-1.21.3/src/plugins/authdata/greet_server/greet_server.exports create mode 100644 krb5-1.21.3/src/plugins/certauth/test/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/certauth/test/certauth_test.exports create mode 100644 krb5-1.21.3/src/plugins/certauth/test/deps create mode 100644 krb5-1.21.3/src/plugins/certauth/test/main.c create mode 100644 krb5-1.21.3/src/plugins/gssapi/negoextest/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/gssapi/negoextest/deps create mode 100644 krb5-1.21.3/src/plugins/gssapi/negoextest/gss_negoextest.exports create mode 100644 krb5-1.21.3/src/plugins/gssapi/negoextest/main.c create mode 100644 krb5-1.21.3/src/plugins/hostrealm/test/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/hostrealm/test/deps create mode 100644 krb5-1.21.3/src/plugins/hostrealm/test/hostrealm_test.exports create mode 100644 krb5-1.21.3/src/plugins/hostrealm/test/main.c create mode 100644 krb5-1.21.3/src/plugins/kadm5_auth/test/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kadm5_auth/test/deps create mode 100644 krb5-1.21.3/src/plugins/kadm5_auth/test/kadm5_auth_test.exports create mode 100644 krb5-1.21.3/src/plugins/kadm5_auth/test/main.c create mode 100644 krb5-1.21.3/src/plugins/kadm5_hook/test/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kadm5_hook/test/deps create mode 100644 krb5-1.21.3/src/plugins/kadm5_hook/test/kadm5_hook_test.exports create mode 100644 krb5-1.21.3/src/plugins/kadm5_hook/test/main.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/adb_openclose.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/adb_policy.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/db2.exports create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/db2_exp.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/deps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/kdb_db2.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/kdb_db2.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/kdb_xdr.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/kdb_xdr.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/CHANGELOG.db2 create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/Makefile.inc create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/README create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/README.NOT.SLEEPYCAT.DB create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/README.db2 create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/Makefile.inc create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/bt_close.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/bt_conv.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/bt_debug.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/bt_delete.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/bt_get.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/bt_open.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/bt_overflow.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/bt_page.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/bt_put.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/bt_search.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/bt_seq.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/bt_split.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/bt_utils.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/btree.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/deps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/btree/extern.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/db/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/db/Makefile.inc create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/db/db.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/db/deps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/deps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/docs/btree.3.ps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/docs/dbopen.3.ps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/docs/hash.3.ps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/docs/hash.usenix.ps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/docs/libtp.usenix.ps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/docs/mpool.3.ps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/docs/recno.3.ps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/Makefile.inc create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/dbm.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/deps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/extern.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash.c.patch create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_bigkey.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_debug.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_func.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_log2.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_page.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hsearch.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/page.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/page.h.patch create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/search.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/config.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-config.hin create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-dbm.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-int.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-ndbm.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-queue.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db.hin create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/libdb.exports create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/Makefile.inc create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db.man.ps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_btree.3 create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_hash.3 create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_lock.3 create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_log.3 create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_mpool.3 create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_open.3 create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_recno.3 create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_txn.3 create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/spell.ok create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/Makefile.inc create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/README create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/deps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/mpool.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/mpool.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/Makefile.inc create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/deps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/extern.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_close.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_delete.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_get.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_open.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_put.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_search.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_seq.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_utils.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/recno.h create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/README create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/data create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/mbox create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/t.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/dbtest.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/deps create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/dictionary create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/Makefile create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/driver2.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/makedb.sh create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tcreat3.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tdel.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/testit create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/thash4.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tread2.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tseq.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tverify.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/README create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/bigtest.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/passtest.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/passwd/genpass.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/run.test create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/t.be.txt create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/t.le.txt create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/lockout.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/pol_xdr.c create mode 100644 krb5-1.21.3/src/plugins/kdb/db2/policy_db.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/deps create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/kldap.exports create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/ldap_exp.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/deps create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/deps create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kerberos.openldap.ldif create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_main.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/lockout.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.c create mode 100644 krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.h create mode 100644 krb5-1.21.3/src/plugins/kdb/lmdb/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdb/lmdb/deps create mode 100644 krb5-1.21.3/src/plugins/kdb/lmdb/kdb_lmdb.c create mode 100644 krb5-1.21.3/src/plugins/kdb/lmdb/klmdb-int.h create mode 100644 krb5-1.21.3/src/plugins/kdb/lmdb/klmdb.exports create mode 100644 krb5-1.21.3/src/plugins/kdb/lmdb/lockout.c create mode 100644 krb5-1.21.3/src/plugins/kdb/lmdb/marshal.c create mode 100644 krb5-1.21.3/src/plugins/kdb/test/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdb/test/deps create mode 100644 krb5-1.21.3/src/plugins/kdb/test/kdb_test.c create mode 100644 krb5-1.21.3/src/plugins/kdb/test/test.exports create mode 100644 krb5-1.21.3/src/plugins/kdcpolicy/test/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/kdcpolicy/test/deps create mode 100644 krb5-1.21.3/src/plugins/kdcpolicy/test/kdcpolicy_test.exports create mode 100644 krb5-1.21.3/src/plugins/kdcpolicy/test/main.c create mode 100644 krb5-1.21.3/src/plugins/localauth/test/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/localauth/test/deps create mode 100644 krb5-1.21.3/src/plugins/localauth/test/localauth_test.exports create mode 100644 krb5-1.21.3/src/plugins/localauth/test/main.c create mode 100644 krb5-1.21.3/src/plugins/preauth/otp/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/preauth/otp/deps create mode 100644 krb5-1.21.3/src/plugins/preauth/otp/main.c create mode 100644 krb5-1.21.3/src/plugins/preauth/otp/otp.exports create mode 100644 krb5-1.21.3/src/plugins/preauth/otp/otp_state.c create mode 100644 krb5-1.21.3/src/plugins/preauth/otp/otp_state.h create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/deps create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkcs11.h create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit.exports create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit.h create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_accessor.c create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_accessor.h create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_clnt.c create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_constants.c create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_crypto.h create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_identity.c create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_kdf_test.c create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_lib.c create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_matching.c create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_profile.c create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_srv.c create mode 100644 krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_trace.h create mode 100644 krb5-1.21.3/src/plugins/preauth/securid_sam2/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/preauth/securid_sam2/README create mode 100644 krb5-1.21.3/src/plugins/preauth/securid_sam2/deps create mode 100644 krb5-1.21.3/src/plugins/preauth/securid_sam2/extern.h create mode 100644 krb5-1.21.3/src/plugins/preauth/securid_sam2/grail.c create mode 100644 krb5-1.21.3/src/plugins/preauth/securid_sam2/securid2.c create mode 100644 krb5-1.21.3/src/plugins/preauth/securid_sam2/securid_sam2.exports create mode 100644 krb5-1.21.3/src/plugins/preauth/securid_sam2/securid_sam2_main.c create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/AUTHORS create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/deps create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/edwards25519.c create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/edwards25519_fiat.h create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/edwards25519_tables.h create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/groups.c create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/groups.h create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/iana.c create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/iana.h create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/openssl.c create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/spake.def create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/spake.exports create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/spake_client.c create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/spake_kdc.c create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/t_krb5.conf create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/t_vectors.c create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/trace.h create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/util.c create mode 100644 krb5-1.21.3/src/plugins/preauth/spake/util.h create mode 100644 krb5-1.21.3/src/plugins/preauth/test/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/preauth/test/cltest.c create mode 100644 krb5-1.21.3/src/plugins/preauth/test/common.c create mode 100644 krb5-1.21.3/src/plugins/preauth/test/common.h create mode 100644 krb5-1.21.3/src/plugins/preauth/test/deps create mode 100644 krb5-1.21.3/src/plugins/preauth/test/kdctest.c create mode 100644 krb5-1.21.3/src/plugins/preauth/test/test.exports create mode 100644 krb5-1.21.3/src/plugins/pwqual/test/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/pwqual/test/deps create mode 100644 krb5-1.21.3/src/plugins/pwqual/test/main.c create mode 100644 krb5-1.21.3/src/plugins/pwqual/test/pwqual_test.exports create mode 100644 krb5-1.21.3/src/plugins/tls/k5tls/Makefile.in create mode 100644 krb5-1.21.3/src/plugins/tls/k5tls/deps create mode 100644 krb5-1.21.3/src/plugins/tls/k5tls/k5tls.exports create mode 100644 krb5-1.21.3/src/plugins/tls/k5tls/notls.c create mode 100644 krb5-1.21.3/src/plugins/tls/k5tls/openssl.c create mode 100644 krb5-1.21.3/src/po/Makefile.in create mode 100644 krb5-1.21.3/src/po/de.po create mode 100644 krb5-1.21.3/src/po/deps create mode 100644 krb5-1.21.3/src/po/en_US.po create mode 100644 krb5-1.21.3/src/po/ka.po create mode 100644 krb5-1.21.3/src/po/mit-krb5.pot create mode 100644 krb5-1.21.3/src/prototype/prototype.c create mode 100644 krb5-1.21.3/src/prototype/prototype.h create mode 100644 krb5-1.21.3/src/tests/Makefile.in create mode 100644 krb5-1.21.3/src/tests/adata.c create mode 100644 krb5-1.21.3/src/tests/asn.1/Makefile.in create mode 100644 krb5-1.21.3/src/tests/asn.1/README create mode 100644 krb5-1.21.3/src/tests/asn.1/cammac.asn1 create mode 100644 krb5-1.21.3/src/tests/asn.1/debug.h create mode 100644 krb5-1.21.3/src/tests/asn.1/deps create mode 100644 krb5-1.21.3/src/tests/asn.1/krb5.asn1 create mode 100644 krb5-1.21.3/src/tests/asn.1/krb5_decode_leak.c create mode 100644 krb5-1.21.3/src/tests/asn.1/krb5_decode_test.c create mode 100644 krb5-1.21.3/src/tests/asn.1/krb5_encode_test.c create mode 100644 krb5-1.21.3/src/tests/asn.1/ktest.c create mode 100644 krb5-1.21.3/src/tests/asn.1/ktest.h create mode 100644 krb5-1.21.3/src/tests/asn.1/ktest_equal.c create mode 100644 krb5-1.21.3/src/tests/asn.1/ktest_equal.h create mode 100644 krb5-1.21.3/src/tests/asn.1/ldap_encode.out create mode 100644 krb5-1.21.3/src/tests/asn.1/ldap_trval.out create mode 100644 krb5-1.21.3/src/tests/asn.1/make-vectors.c create mode 100644 krb5-1.21.3/src/tests/asn.1/otp.asn1 create mode 100644 krb5-1.21.3/src/tests/asn.1/pkinit-agility.asn1 create mode 100644 krb5-1.21.3/src/tests/asn.1/pkinit.asn1 create mode 100644 krb5-1.21.3/src/tests/asn.1/pkinit_encode.out create mode 100644 krb5-1.21.3/src/tests/asn.1/pkinit_trval.out create mode 100644 krb5-1.21.3/src/tests/asn.1/pkix.asn1 create mode 100644 krb5-1.21.3/src/tests/asn.1/reference_encode.out create mode 100644 krb5-1.21.3/src/tests/asn.1/spake.asn1 create mode 100644 krb5-1.21.3/src/tests/asn.1/t_trval.c create mode 100644 krb5-1.21.3/src/tests/asn.1/trval.c create mode 100644 krb5-1.21.3/src/tests/asn.1/trval_reference.out create mode 100644 krb5-1.21.3/src/tests/asn.1/utility.c create mode 100644 krb5-1.21.3/src/tests/asn.1/utility.h create mode 100644 krb5-1.21.3/src/tests/au_dict.json create mode 100644 krb5-1.21.3/src/tests/conccache.c create mode 100644 krb5-1.21.3/src/tests/create/Makefile.in create mode 100644 krb5-1.21.3/src/tests/create/deps create mode 100644 krb5-1.21.3/src/tests/create/kdb5_mkdums.c create mode 100644 krb5-1.21.3/src/tests/deps create mode 100644 krb5-1.21.3/src/tests/dump.c create mode 100644 krb5-1.21.3/src/tests/dumpfiles/dump create mode 100644 krb5-1.21.3/src/tests/dumpfiles/dump.16 create mode 100644 krb5-1.21.3/src/tests/dumpfiles/dump.b7 create mode 100644 krb5-1.21.3/src/tests/dumpfiles/dump.ov create mode 100644 krb5-1.21.3/src/tests/dumpfiles/dump.r13 create mode 100644 krb5-1.21.3/src/tests/dumpfiles/dump.r18 create mode 100644 krb5-1.21.3/src/tests/etinfo.c create mode 100644 krb5-1.21.3/src/tests/forward.c create mode 100644 krb5-1.21.3/src/tests/gcred.c create mode 100644 krb5-1.21.3/src/tests/gss-threads/Makefile.in create mode 100644 krb5-1.21.3/src/tests/gss-threads/README create mode 100644 krb5-1.21.3/src/tests/gss-threads/deps create mode 100644 krb5-1.21.3/src/tests/gss-threads/gss-client.c create mode 100644 krb5-1.21.3/src/tests/gss-threads/gss-misc.c create mode 100644 krb5-1.21.3/src/tests/gss-threads/gss-misc.h create mode 100644 krb5-1.21.3/src/tests/gss-threads/gss-server.c create mode 100644 krb5-1.21.3/src/tests/gssapi/Makefile.in create mode 100644 krb5-1.21.3/src/tests/gssapi/ccinit.c create mode 100644 krb5-1.21.3/src/tests/gssapi/ccrefresh.c create mode 100644 krb5-1.21.3/src/tests/gssapi/common.c create mode 100644 krb5-1.21.3/src/tests/gssapi/common.h create mode 100644 krb5-1.21.3/src/tests/gssapi/deps create mode 100644 krb5-1.21.3/src/tests/gssapi/reload.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_accname.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_add_cred.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_authind.py create mode 100644 krb5-1.21.3/src/tests/gssapi/t_bindings.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_bindings.py create mode 100644 krb5-1.21.3/src/tests/gssapi/t_ccselect.c create mode 100755 krb5-1.21.3/src/tests/gssapi/t_ccselect.py create mode 100644 krb5-1.21.3/src/tests/gssapi/t_ciflags.c create mode 100755 krb5-1.21.3/src/tests/gssapi/t_client_keytab.py create mode 100644 krb5-1.21.3/src/tests/gssapi/t_context.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_credstore.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_credstore.py create mode 100644 krb5-1.21.3/src/tests/gssapi/t_enctypes.c create mode 100755 krb5-1.21.3/src/tests/gssapi/t_enctypes.py create mode 100644 krb5-1.21.3/src/tests/gssapi/t_err.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_export_cred.c create mode 100755 krb5-1.21.3/src/tests/gssapi/t_export_cred.py create mode 100644 krb5-1.21.3/src/tests/gssapi/t_export_name.c create mode 100755 krb5-1.21.3/src/tests/gssapi/t_gssapi.py create mode 100644 krb5-1.21.3/src/tests/gssapi/t_gssexts.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_imp_cred.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_imp_name.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_inq_cred.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_inq_ctx.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_inq_mechs_name.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_invalid.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_iov.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_lifetime.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_namingexts.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_negoex.py create mode 100644 krb5-1.21.3/src/tests/gssapi/t_oid.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_pcontok.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_prf.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_s4u.c create mode 100755 krb5-1.21.3/src/tests/gssapi/t_s4u.py create mode 100644 krb5-1.21.3/src/tests/gssapi/t_s4u2proxy_krb5.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_saslname.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_spnego.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_srcattrs.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_store_cred.c create mode 100644 krb5-1.21.3/src/tests/gssapi/t_store_cred.py create mode 100644 krb5-1.21.3/src/tests/hammer/Makefile.in create mode 100644 krb5-1.21.3/src/tests/hammer/deps create mode 100644 krb5-1.21.3/src/tests/hammer/kdc5_hammer.c create mode 100644 krb5-1.21.3/src/tests/hammer/pp.c create mode 100644 krb5-1.21.3/src/tests/hist.c create mode 100644 krb5-1.21.3/src/tests/hooks.c create mode 100644 krb5-1.21.3/src/tests/hrealm.c create mode 100644 krb5-1.21.3/src/tests/icinterleave.c create mode 100644 krb5-1.21.3/src/tests/icred.c create mode 100644 krb5-1.21.3/src/tests/jsonwalker.py create mode 100644 krb5-1.21.3/src/tests/kcmserver.py create mode 100644 krb5-1.21.3/src/tests/kdbtest.c create mode 100644 krb5-1.21.3/src/tests/localauth.c create mode 100644 krb5-1.21.3/src/tests/misc/Makefile.in create mode 100644 krb5-1.21.3/src/tests/misc/deps create mode 100644 krb5-1.21.3/src/tests/misc/test_chpw_message.c create mode 100644 krb5-1.21.3/src/tests/misc/test_cxx_gss.cpp create mode 100644 krb5-1.21.3/src/tests/misc/test_cxx_k5int.cpp create mode 100644 krb5-1.21.3/src/tests/misc/test_cxx_kadm5.cpp create mode 100644 krb5-1.21.3/src/tests/misc/test_cxx_krb5.cpp create mode 100644 krb5-1.21.3/src/tests/misc/test_cxx_rpc.cpp create mode 100644 krb5-1.21.3/src/tests/misc/test_getpw.c create mode 100644 krb5-1.21.3/src/tests/misc/test_getsockname.c create mode 100644 krb5-1.21.3/src/tests/misc/test_nfold.c create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/ca.pem create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/generic.p12 create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/generic.pem create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/kdc.pem create mode 100755 krb5-1.21.3/src/tests/pkinit-certs/make-certs.sh create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/privkey-enc.pem create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/privkey.pem create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/user-enc.p12 create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/user-upn.p12 create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/user-upn.pem create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/user-upn2.p12 create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/user-upn2.pem create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/user-upn3.p12 create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/user-upn3.pem create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/user.p12 create mode 100644 krb5-1.21.3/src/tests/pkinit-certs/user.pem create mode 100644 krb5-1.21.3/src/tests/plugorder.c create mode 100644 krb5-1.21.3/src/tests/proxy-certs/ca.pem create mode 100755 krb5-1.21.3/src/tests/proxy-certs/make-certs.sh create mode 100644 krb5-1.21.3/src/tests/proxy-certs/proxy-badsig.pem create mode 100644 krb5-1.21.3/src/tests/proxy-certs/proxy-ideal.pem create mode 100644 krb5-1.21.3/src/tests/proxy-certs/proxy-no-match.pem create mode 100644 krb5-1.21.3/src/tests/proxy-certs/proxy-san.pem create mode 100644 krb5-1.21.3/src/tests/proxy-certs/proxy-subject.pem create mode 100644 krb5-1.21.3/src/tests/rdreq.c create mode 100644 krb5-1.21.3/src/tests/replay.c create mode 100644 krb5-1.21.3/src/tests/responder.c create mode 100644 krb5-1.21.3/src/tests/s2p.c create mode 100644 krb5-1.21.3/src/tests/s4u2proxy.c create mode 100644 krb5-1.21.3/src/tests/s4u2self.c create mode 100644 krb5-1.21.3/src/tests/shlib/Makefile.in create mode 100644 krb5-1.21.3/src/tests/shlib/deps create mode 100644 krb5-1.21.3/src/tests/shlib/t_loader.c create mode 100644 krb5-1.21.3/src/tests/softpkcs11/Makefile.in create mode 100644 krb5-1.21.3/src/tests/softpkcs11/deps create mode 100644 krb5-1.21.3/src/tests/softpkcs11/main.c create mode 100644 krb5-1.21.3/src/tests/softpkcs11/softpkcs11.exports create mode 100755 krb5-1.21.3/src/tests/t_audit.py create mode 100644 krb5-1.21.3/src/tests/t_authdata.py create mode 100755 krb5-1.21.3/src/tests/t_bogus_kdc_req.py create mode 100755 krb5-1.21.3/src/tests/t_ccache.py create mode 100644 krb5-1.21.3/src/tests/t_certauth.py create mode 100755 krb5-1.21.3/src/tests/t_changepw.py create mode 100755 krb5-1.21.3/src/tests/t_crossrealm.py create mode 100755 krb5-1.21.3/src/tests/t_cve-2012-1014.py create mode 100755 krb5-1.21.3/src/tests/t_cve-2012-1015.py create mode 100755 krb5-1.21.3/src/tests/t_cve-2013-1416.py create mode 100755 krb5-1.21.3/src/tests/t_cve-2013-1417.py create mode 100644 krb5-1.21.3/src/tests/t_cve-2021-36222.py create mode 100755 krb5-1.21.3/src/tests/t_dump.py create mode 100755 krb5-1.21.3/src/tests/t_errmsg.py create mode 100644 krb5-1.21.3/src/tests/t_etype_info.py create mode 100755 krb5-1.21.3/src/tests/t_general.py create mode 100755 krb5-1.21.3/src/tests/t_hooks.py create mode 100755 krb5-1.21.3/src/tests/t_hostrealm.py create mode 100644 krb5-1.21.3/src/tests/t_inetd.c create mode 100755 krb5-1.21.3/src/tests/t_iprop.py create mode 100644 krb5-1.21.3/src/tests/t_kadm5_auth.py create mode 100755 krb5-1.21.3/src/tests/t_kadm5_hook.py create mode 100644 krb5-1.21.3/src/tests/t_kadmin.py create mode 100755 krb5-1.21.3/src/tests/t_kadmin_acl.py create mode 100644 krb5-1.21.3/src/tests/t_kadmin_parsing.py create mode 100755 krb5-1.21.3/src/tests/t_kdb.py create mode 100755 krb5-1.21.3/src/tests/t_kdb_locking.py create mode 100755 krb5-1.21.3/src/tests/t_kdc_log.py create mode 100644 krb5-1.21.3/src/tests/t_kdcoptions.py create mode 100644 krb5-1.21.3/src/tests/t_kdcpolicy.py create mode 100755 krb5-1.21.3/src/tests/t_keydata.py create mode 100755 krb5-1.21.3/src/tests/t_keyrollover.py create mode 100755 krb5-1.21.3/src/tests/t_keytab.py create mode 100755 krb5-1.21.3/src/tests/t_kprop.py create mode 100755 krb5-1.21.3/src/tests/t_localauth.py create mode 100755 krb5-1.21.3/src/tests/t_mkey.py create mode 100755 krb5-1.21.3/src/tests/t_otp.py create mode 100755 krb5-1.21.3/src/tests/t_pkinit.py create mode 100755 krb5-1.21.3/src/tests/t_policy.py create mode 100644 krb5-1.21.3/src/tests/t_preauth.py create mode 100755 krb5-1.21.3/src/tests/t_princflags.py create mode 100755 krb5-1.21.3/src/tests/t_proxy.py create mode 100755 krb5-1.21.3/src/tests/t_pwqual.py create mode 100755 krb5-1.21.3/src/tests/t_rdreq.py create mode 100755 krb5-1.21.3/src/tests/t_referral.py create mode 100755 krb5-1.21.3/src/tests/t_renew.py create mode 100755 krb5-1.21.3/src/tests/t_renprinc.py create mode 100644 krb5-1.21.3/src/tests/t_replay.py create mode 100755 krb5-1.21.3/src/tests/t_salt.py create mode 100755 krb5-1.21.3/src/tests/t_sesskeynego.py create mode 100755 krb5-1.21.3/src/tests/t_skew.py create mode 100755 krb5-1.21.3/src/tests/t_sn2princ.py create mode 100644 krb5-1.21.3/src/tests/t_spake.py create mode 100755 krb5-1.21.3/src/tests/t_stringattr.py create mode 100755 krb5-1.21.3/src/tests/t_tabdump.py create mode 100644 krb5-1.21.3/src/tests/t_u2u.py create mode 100755 krb5-1.21.3/src/tests/t_unlockiter.py create mode 100644 krb5-1.21.3/src/tests/t_y2038.py create mode 100644 krb5-1.21.3/src/tests/test1.c create mode 100644 krb5-1.21.3/src/tests/threads/Makefile.in create mode 100644 krb5-1.21.3/src/tests/threads/deps create mode 100644 krb5-1.21.3/src/tests/threads/gss-perf.c create mode 100644 krb5-1.21.3/src/tests/threads/init_ctx.c create mode 100644 krb5-1.21.3/src/tests/threads/prof1.c create mode 100644 krb5-1.21.3/src/tests/threads/profread.c create mode 100644 krb5-1.21.3/src/tests/threads/t_rcache.c create mode 100644 krb5-1.21.3/src/tests/unlockiter.c create mode 100644 krb5-1.21.3/src/tests/verify/Makefile.in create mode 100644 krb5-1.21.3/src/tests/verify/deps create mode 100644 krb5-1.21.3/src/tests/verify/kdb5_verify.c create mode 100644 krb5-1.21.3/src/tests/verify/pkey.c create mode 100644 krb5-1.21.3/src/util/Makefile.in create mode 100644 krb5-1.21.3/src/util/ac_check_krb5.m4 create mode 100755 krb5-1.21.3/src/util/check-ac-syms create mode 100644 krb5-1.21.3/src/util/cstyle-file.py create mode 100644 krb5-1.21.3/src/util/cstyle.py create mode 100644 krb5-1.21.3/src/util/def-check.pl create mode 100644 krb5-1.21.3/src/util/depfix.pl create mode 100644 krb5-1.21.3/src/util/deps create mode 100644 krb5-1.21.3/src/util/et/ISSUES create mode 100644 krb5-1.21.3/src/util/et/Makefile.in create mode 100644 krb5-1.21.3/src/util/et/com_err.3 create mode 100644 krb5-1.21.3/src/util/et/com_err.c create mode 100644 krb5-1.21.3/src/util/et/com_err.h create mode 100644 krb5-1.21.3/src/util/et/com_err.texinfo create mode 100644 krb5-1.21.3/src/util/et/compile_et.1 create mode 100755 krb5-1.21.3/src/util/et/compile_et.sh create mode 100755 krb5-1.21.3/src/util/et/config_script create mode 100644 krb5-1.21.3/src/util/et/deps create mode 100644 krb5-1.21.3/src/util/et/error_message.c create mode 100644 krb5-1.21.3/src/util/et/error_table.h create mode 100644 krb5-1.21.3/src/util/et/et.exp create mode 100644 krb5-1.21.3/src/util/et/et.pbexp create mode 100644 krb5-1.21.3/src/util/et/et1.et create mode 100644 krb5-1.21.3/src/util/et/et2.et create mode 100644 krb5-1.21.3/src/util/et/et_c.awk create mode 100644 krb5-1.21.3/src/util/et/et_c.pl create mode 100644 krb5-1.21.3/src/util/et/et_h.awk create mode 100644 krb5-1.21.3/src/util/et/et_h.pl create mode 100644 krb5-1.21.3/src/util/et/et_name.c create mode 100644 krb5-1.21.3/src/util/et/libcom_err.exports create mode 100644 krb5-1.21.3/src/util/et/mit-sipb-copyright.h create mode 100644 krb5-1.21.3/src/util/et/t_com_err.c create mode 100644 krb5-1.21.3/src/util/et/test1.et create mode 100644 krb5-1.21.3/src/util/et/test2.et create mode 100644 krb5-1.21.3/src/util/et/test_et.c create mode 100644 krb5-1.21.3/src/util/et/texinfo.tex create mode 100644 krb5-1.21.3/src/util/exitsleep.c create mode 100755 krb5-1.21.3/src/util/export-check.pl create mode 100644 krb5-1.21.3/src/util/gen-map.pl create mode 100644 krb5-1.21.3/src/util/gen.pl create mode 100755 krb5-1.21.3/src/util/getsyms create mode 100644 krb5-1.21.3/src/util/getsyms.sed create mode 100644 krb5-1.21.3/src/util/k5test.py create mode 100644 krb5-1.21.3/src/util/krb5-batch-reindent.el create mode 100644 krb5-1.21.3/src/util/krb5-c-style.el create mode 100644 krb5-1.21.3/src/util/krb5-check-copyright.py create mode 100644 krb5-1.21.3/src/util/krb5-hack-cc-mode-caselabel.el create mode 100644 krb5-1.21.3/src/util/krb5-mark-cstyle.py create mode 100755 krb5-1.21.3/src/util/krb5-send-pr.sh create mode 100644 krb5-1.21.3/src/util/ktemplate.pm create mode 100755 krb5-1.21.3/src/util/lndir create mode 100755 krb5-1.21.3/src/util/mkrel create mode 100644 krb5-1.21.3/src/util/princflags.py create mode 100644 krb5-1.21.3/src/util/profile/Makefile.in create mode 100644 krb5-1.21.3/src/util/profile/argv_parse.c create mode 100644 krb5-1.21.3/src/util/profile/argv_parse.h create mode 100644 krb5-1.21.3/src/util/profile/deps create mode 100644 krb5-1.21.3/src/util/profile/dosshell.ini create mode 100644 krb5-1.21.3/src/util/profile/final.expected create mode 100644 krb5-1.21.3/src/util/profile/final1.ini create mode 100644 krb5-1.21.3/src/util/profile/final2.ini create mode 100644 krb5-1.21.3/src/util/profile/final3.ini create mode 100644 krb5-1.21.3/src/util/profile/final4.ini create mode 100644 krb5-1.21.3/src/util/profile/final5.ini create mode 100644 krb5-1.21.3/src/util/profile/krb5.conf create mode 100644 krb5-1.21.3/src/util/profile/libprofile.exports create mode 100644 krb5-1.21.3/src/util/profile/prof_FSp_glue.c create mode 100644 krb5-1.21.3/src/util/profile/prof_err.et create mode 100644 krb5-1.21.3/src/util/profile/prof_file.c create mode 100644 krb5-1.21.3/src/util/profile/prof_get.c create mode 100644 krb5-1.21.3/src/util/profile/prof_init.c create mode 100644 krb5-1.21.3/src/util/profile/prof_int.h create mode 100644 krb5-1.21.3/src/util/profile/prof_parse.c create mode 100644 krb5-1.21.3/src/util/profile/prof_set.c create mode 100644 krb5-1.21.3/src/util/profile/prof_tree.c create mode 100644 krb5-1.21.3/src/util/profile/profile.5 create mode 100644 krb5-1.21.3/src/util/profile/profile.exp create mode 100644 krb5-1.21.3/src/util/profile/profile.hin create mode 100644 krb5-1.21.3/src/util/profile/profile.pbexp create mode 100644 krb5-1.21.3/src/util/profile/prtest.in create mode 100644 krb5-1.21.3/src/util/profile/prtest.script create mode 100644 krb5-1.21.3/src/util/profile/t_profile.c create mode 100644 krb5-1.21.3/src/util/profile/test.ini create mode 100644 krb5-1.21.3/src/util/profile/test_load.c create mode 100644 krb5-1.21.3/src/util/profile/test_parse.c create mode 100644 krb5-1.21.3/src/util/profile/test_profile.c create mode 100644 krb5-1.21.3/src/util/profile/test_vtable.c create mode 100644 krb5-1.21.3/src/util/profile/testmod/Makefile.in create mode 100644 krb5-1.21.3/src/util/profile/testmod/deps create mode 100644 krb5-1.21.3/src/util/profile/testmod/proftest.exports create mode 100644 krb5-1.21.3/src/util/profile/testmod/testmod_main.c create mode 100644 krb5-1.21.3/src/util/ss/Makefile.in create mode 100755 krb5-1.21.3/src/util/ss/config_script create mode 100644 krb5-1.21.3/src/util/ss/copyright.h create mode 100644 krb5-1.21.3/src/util/ss/ct_c_awk.in create mode 100644 krb5-1.21.3/src/util/ss/ct_c_sed.in create mode 100644 krb5-1.21.3/src/util/ss/data.c create mode 100644 krb5-1.21.3/src/util/ss/deps create mode 100644 krb5-1.21.3/src/util/ss/error.c create mode 100644 krb5-1.21.3/src/util/ss/execute_cmd.c create mode 100644 krb5-1.21.3/src/util/ss/help.c create mode 100644 krb5-1.21.3/src/util/ss/invocation.c create mode 100644 krb5-1.21.3/src/util/ss/list_rqs.c create mode 100644 krb5-1.21.3/src/util/ss/listen.c create mode 100644 krb5-1.21.3/src/util/ss/mit-sipb-copyright.h create mode 100755 krb5-1.21.3/src/util/ss/mk_cmds.sh create mode 100644 krb5-1.21.3/src/util/ss/pager.c create mode 100644 krb5-1.21.3/src/util/ss/parse.c create mode 100644 krb5-1.21.3/src/util/ss/prompt.c create mode 100644 krb5-1.21.3/src/util/ss/request_tbl.c create mode 100644 krb5-1.21.3/src/util/ss/requests.c create mode 100644 krb5-1.21.3/src/util/ss/ss.h create mode 100644 krb5-1.21.3/src/util/ss/ss_err.et create mode 100644 krb5-1.21.3/src/util/ss/ss_internal.h create mode 100644 krb5-1.21.3/src/util/ss/std_rqs.ct create mode 100644 krb5-1.21.3/src/util/ss/test_ss.c create mode 100644 krb5-1.21.3/src/util/support/Makefile.in create mode 100644 krb5-1.21.3/src/util/support/base64.c create mode 100644 krb5-1.21.3/src/util/support/bcmp.c create mode 100644 krb5-1.21.3/src/util/support/cache-addrinfo.h create mode 100644 krb5-1.21.3/src/util/support/deps create mode 100644 krb5-1.21.3/src/util/support/dir_filenames.c create mode 100644 krb5-1.21.3/src/util/support/errors.c create mode 100644 krb5-1.21.3/src/util/support/fake-addrinfo.c create mode 100644 krb5-1.21.3/src/util/support/fnmatch.c create mode 100644 krb5-1.21.3/src/util/support/getopt.c create mode 100644 krb5-1.21.3/src/util/support/getopt_long.c create mode 100644 krb5-1.21.3/src/util/support/gettimeofday.c create mode 100644 krb5-1.21.3/src/util/support/gmt_mktime.c create mode 100644 krb5-1.21.3/src/util/support/hashtab.c create mode 100644 krb5-1.21.3/src/util/support/hex.c create mode 100644 krb5-1.21.3/src/util/support/init-addrinfo.c create mode 100644 krb5-1.21.3/src/util/support/ipc_stream.c create mode 100644 krb5-1.21.3/src/util/support/json.c create mode 100644 krb5-1.21.3/src/util/support/k5buf.c create mode 100644 krb5-1.21.3/src/util/support/libkrb5support-fixed.exports create mode 100644 krb5-1.21.3/src/util/support/mkstemp.c create mode 100644 krb5-1.21.3/src/util/support/path.c create mode 100644 krb5-1.21.3/src/util/support/plugins.c create mode 100644 krb5-1.21.3/src/util/support/printf.c create mode 100644 krb5-1.21.3/src/util/support/secure_getenv.c create mode 100644 krb5-1.21.3/src/util/support/strerror_r.c create mode 100644 krb5-1.21.3/src/util/support/strlcpy.c create mode 100644 krb5-1.21.3/src/util/support/supp-int.h create mode 100644 krb5-1.21.3/src/util/support/t_base64.c create mode 100644 krb5-1.21.3/src/util/support/t_hashtab.c create mode 100644 krb5-1.21.3/src/util/support/t_hex.c create mode 100644 krb5-1.21.3/src/util/support/t_json.c create mode 100644 krb5-1.21.3/src/util/support/t_k5buf.c create mode 100644 krb5-1.21.3/src/util/support/t_path.c create mode 100644 krb5-1.21.3/src/util/support/t_unal.c create mode 100644 krb5-1.21.3/src/util/support/t_utf16.c create mode 100644 krb5-1.21.3/src/util/support/t_utf8.c create mode 100644 krb5-1.21.3/src/util/support/threads.c create mode 100644 krb5-1.21.3/src/util/support/utf8.c create mode 100644 krb5-1.21.3/src/util/support/utf8_conv.c create mode 100644 krb5-1.21.3/src/util/support/zap.c create mode 100644 krb5-1.21.3/src/util/t_array.pm create mode 100644 krb5-1.21.3/src/util/t_bimap.pm create mode 100644 krb5-1.21.3/src/util/t_enum.pm create mode 100644 krb5-1.21.3/src/util/t_template.pm create mode 100644 krb5-1.21.3/src/util/t_tsenum.pm create mode 100644 krb5-1.21.3/src/util/testrealm.py create mode 100755 krb5-1.21.3/src/util/trim-valgrind-logs create mode 100644 krb5-1.21.3/src/util/valgrind-suppressions create mode 100644 krb5-1.21.3/src/util/verto/Makefile.in create mode 100644 krb5-1.21.3/src/util/verto/README create mode 100644 krb5-1.21.3/src/util/verto/Symbols.ev create mode 100644 krb5-1.21.3/src/util/verto/deps create mode 100644 krb5-1.21.3/src/util/verto/ev.c create mode 100644 krb5-1.21.3/src/util/verto/ev.h create mode 100644 krb5-1.21.3/src/util/verto/ev_poll.c create mode 100644 krb5-1.21.3/src/util/verto/ev_select.c create mode 100644 krb5-1.21.3/src/util/verto/ev_vars.h create mode 100644 krb5-1.21.3/src/util/verto/ev_win32.c create mode 100644 krb5-1.21.3/src/util/verto/ev_wrap.h create mode 100644 krb5-1.21.3/src/util/verto/libverto.exports create mode 100644 krb5-1.21.3/src/util/verto/module.c create mode 100644 krb5-1.21.3/src/util/verto/module.h create mode 100644 krb5-1.21.3/src/util/verto/verto-k5ev.c create mode 100644 krb5-1.21.3/src/util/verto/verto-libev.c create mode 100644 krb5-1.21.3/src/util/verto/verto-module.h create mode 100644 krb5-1.21.3/src/util/verto/verto.c create mode 100644 krb5-1.21.3/src/util/verto/verto.h create mode 100644 krb5-1.21.3/src/util/windows/Makefile.in create mode 100644 krb5-1.21.3/src/util/windows/libecho.c create mode 100755 krb5-1.21.3/src/util/wsgiref-kdcproxy.py create mode 100644 krb5-1.21.3/src/wconfig.c create mode 100644 krb5-1.21.3/src/windows/Makefile.in create mode 100644 krb5-1.21.3/src/windows/README create mode 100644 krb5-1.21.3/src/windows/include/leasherr.h create mode 100644 krb5-1.21.3/src/windows/include/leashinfo.h create mode 100644 krb5-1.21.3/src/windows/include/leashwin.h create mode 100644 krb5-1.21.3/src/windows/include/loadfuncs-com_err.h create mode 100644 krb5-1.21.3/src/windows/include/loadfuncs-krb5.h create mode 100644 krb5-1.21.3/src/windows/include/loadfuncs-leash.h create mode 100644 krb5-1.21.3/src/windows/include/loadfuncs-lsa.h create mode 100644 krb5-1.21.3/src/windows/include/loadfuncs-profile.h create mode 100644 krb5-1.21.3/src/windows/include/loadfuncs.h create mode 100644 krb5-1.21.3/src/windows/installer/wix/Binary/bannrbmp.bmp create mode 100644 krb5-1.21.3/src/windows/installer/wix/Binary/completi.ico create mode 100644 krb5-1.21.3/src/windows/installer/wix/Binary/custicon.ico create mode 100644 krb5-1.21.3/src/windows/installer/wix/Binary/dlgbmp.bmp create mode 100644 krb5-1.21.3/src/windows/installer/wix/Binary/exclamic.ico create mode 100644 krb5-1.21.3/src/windows/installer/wix/Binary/info.bmp create mode 100644 krb5-1.21.3/src/windows/installer/wix/Binary/insticon.ico create mode 100644 krb5-1.21.3/src/windows/installer/wix/Binary/new.bmp create mode 100644 krb5-1.21.3/src/windows/installer/wix/Binary/removico.ico create mode 100644 krb5-1.21.3/src/windows/installer/wix/Binary/repairic.ico create mode 100644 krb5-1.21.3/src/windows/installer/wix/Binary/up.bmp create mode 100644 krb5-1.21.3/src/windows/installer/wix/Makefile create mode 100644 krb5-1.21.3/src/windows/installer/wix/athena/krb5.ini create mode 100644 krb5-1.21.3/src/windows/installer/wix/config.wxi create mode 100644 krb5-1.21.3/src/windows/installer/wix/custom/custom.cpp create mode 100644 krb5-1.21.3/src/windows/installer/wix/custom/custom.h create mode 100644 krb5-1.21.3/src/windows/installer/wix/features.wxi create mode 100644 krb5-1.21.3/src/windows/installer/wix/files.wxi create mode 100755 krb5-1.21.3/src/windows/installer/wix/kfw.wxs create mode 100644 krb5-1.21.3/src/windows/installer/wix/krb5.ini create mode 100644 krb5-1.21.3/src/windows/installer/wix/lang/config_1033.wxi create mode 100644 krb5-1.21.3/src/windows/installer/wix/lang/license.rtf create mode 100644 krb5-1.21.3/src/windows/installer/wix/lang/strings_1033.wxl create mode 100644 krb5-1.21.3/src/windows/installer/wix/lang/ui_1033.wxi create mode 100644 krb5-1.21.3/src/windows/installer/wix/msi-deployment-guide.txt create mode 100644 krb5-1.21.3/src/windows/installer/wix/platform.wxi create mode 100644 krb5-1.21.3/src/windows/installer/wix/property.wxi create mode 100644 krb5-1.21.3/src/windows/installer/wix/runtime.wxi create mode 100644 krb5-1.21.3/src/windows/installer/wix/runtime_debug.wxi create mode 100644 krb5-1.21.3/src/windows/installer/wix/site-local.wxi create mode 100644 krb5-1.21.3/src/windows/kerberos.ver create mode 100644 krb5-1.21.3/src/windows/kfwlogon/Makefile.in create mode 100644 krb5-1.21.3/src/windows/kfwlogon/kfwcommon.c create mode 100644 krb5-1.21.3/src/windows/kfwlogon/kfwcpcc.c create mode 100644 krb5-1.21.3/src/windows/kfwlogon/kfwlogon.c create mode 100644 krb5-1.21.3/src/windows/kfwlogon/kfwlogon.def create mode 100644 krb5-1.21.3/src/windows/kfwlogon/kfwlogon.h create mode 100644 krb5-1.21.3/src/windows/leash/KrbListTickets.cpp create mode 100644 krb5-1.21.3/src/windows/leash/Leash.cpp create mode 100644 krb5-1.21.3/src/windows/leash/Leash.h create mode 100644 krb5-1.21.3/src/windows/leash/Leash.rc create mode 100644 krb5-1.21.3/src/windows/leash/LeashAboutBox.cpp create mode 100644 krb5-1.21.3/src/windows/leash/LeashAboutBox.h create mode 100644 krb5-1.21.3/src/windows/leash/LeashDebugWindow.cpp create mode 100644 krb5-1.21.3/src/windows/leash/LeashDebugWindow.h create mode 100644 krb5-1.21.3/src/windows/leash/LeashDoc.cpp create mode 100644 krb5-1.21.3/src/windows/leash/LeashDoc.h create mode 100644 krb5-1.21.3/src/windows/leash/LeashFrame.cpp create mode 100644 krb5-1.21.3/src/windows/leash/LeashFrame.h create mode 100644 krb5-1.21.3/src/windows/leash/LeashMessageBox.cpp create mode 100644 krb5-1.21.3/src/windows/leash/LeashMessageBox.h create mode 100644 krb5-1.21.3/src/windows/leash/LeashUIApplication.cpp create mode 100644 krb5-1.21.3/src/windows/leash/LeashUIApplication.h create mode 100644 krb5-1.21.3/src/windows/leash/LeashUICommandHandler.cpp create mode 100644 krb5-1.21.3/src/windows/leash/LeashUICommandHandler.h create mode 100644 krb5-1.21.3/src/windows/leash/LeashView.cpp create mode 100644 krb5-1.21.3/src/windows/leash/LeashView.h create mode 100644 krb5-1.21.3/src/windows/leash/Lglobals.h create mode 100644 krb5-1.21.3/src/windows/leash/MainFrm.cpp create mode 100644 krb5-1.21.3/src/windows/leash/MainFrm.h create mode 100644 krb5-1.21.3/src/windows/leash/Makefile.in create mode 100644 krb5-1.21.3/src/windows/leash/StdAfx.cpp create mode 100644 krb5-1.21.3/src/windows/leash/StdAfx.h create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/Images/Change_Password.PNG create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/Images/Destroy_Ticket.PNG create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/Images/Get_Ticket.PNG create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/Images/Home_Tab.PNG create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/Images/Make_Default.PNG create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/Images/Options_Tab.PNG create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/Images/Renew_Ticket.PNG create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/Images/checkbox.png create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/Index.hhk create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/Leash.css create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/MITKerberosHelp.hhp create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/Makefile.in create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/TOC.hhc create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Change_Password.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Command_Line.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Debugging.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Destroy_Tickets.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Encryption_Types.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/FAQ.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Forget_Password.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Forget_Principals.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Get_Tickets.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Getting_Started.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Glossary.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Home_Tab.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/How_Kerberos_Works.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/KCPYTKT.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/KDESTROY.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/KINIT.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/KLIST.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/KPASSWD.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/KSWITCH.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/KVNO.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Kerberos.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Kerberos_Terminology.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Keyboard_Shortcuts.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/MS2MIT.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Make_Default.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Manage_Multiple_Principals.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Options_Tab.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Password_Tips.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Passwords.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Principals.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Renew_Tickets.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Renew_Tickets2.html create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Report_Bugs.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Ticket_Settings.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Tickets.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Troubleshooting.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/Using_Leash_Menus.htm create mode 100644 krb5-1.21.3/src/windows/leash/htmlhelp/html/View_Tickets.htm create mode 100644 krb5-1.21.3/src/windows/leash/kfwribbon.xml create mode 100644 krb5-1.21.3/src/windows/leash/reminder.h create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash.rc2 create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash2.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash_Doc.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash_tickets_green.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash_tickets_orange.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash_tickets_out.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash_tickets_red.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash_tkt_green.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash_tkt_orange.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash_tkt_red.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash_toolbar.bmp create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash_user_green.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash_user_orange.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash_user_out.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/Leash_user_red.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/address.ico create mode 100755 krb5-1.21.3/src/windows/leash/res/cpwlarge.bmp create mode 100644 krb5-1.21.3/src/windows/leash/res/cursor1.cur create mode 100644 krb5-1.21.3/src/windows/leash/res/destroy.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/destroy_disabled.ico create mode 100755 krb5-1.21.3/src/windows/leash/res/destroylarge.bmp create mode 100644 krb5-1.21.3/src/windows/leash/res/encryption.ico create mode 100755 krb5-1.21.3/src/windows/leash/res/exportlarge.bmp create mode 100755 krb5-1.21.3/src/windows/leash/res/getticketlarge.bmp create mode 100644 krb5-1.21.3/src/windows/leash/res/import.bmp create mode 100755 krb5-1.21.3/src/windows/leash/res/importlarge.bmp create mode 100644 krb5-1.21.3/src/windows/leash/res/key.ico create mode 100755 krb5-1.21.3/src/windows/leash/res/makedefaultlarge.bmp create mode 100644 krb5-1.21.3/src/windows/leash/res/new.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/new_disabled.ico create mode 100755 krb5-1.21.3/src/windows/leash/res/newlarge.bmp create mode 100755 krb5-1.21.3/src/windows/leash/res/openlarge.bmp create mode 100644 krb5-1.21.3/src/windows/leash/res/password.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/password_disabled.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/refresh.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/refresh_disabled.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/renew.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/renew_disabled.ico create mode 100755 krb5-1.21.3/src/windows/leash/res/renewlarge.bmp create mode 100644 krb5-1.21.3/src/windows/leash/res/status_grayK.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/status_greenK.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/status_redK.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/status_yelloK.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/sync.ico create mode 100644 krb5-1.21.3/src/windows/leash/res/sync_disabled.ico create mode 100644 krb5-1.21.3/src/windows/leash/resource.h create mode 100644 krb5-1.21.3/src/windows/leash/ver.rc create mode 100644 krb5-1.21.3/src/windows/leashdll/Makefile.in create mode 100644 krb5-1.21.3/src/windows/leashdll/krb5routines.c create mode 100644 krb5-1.21.3/src/windows/leashdll/leash-int.h create mode 100644 krb5-1.21.3/src/windows/leashdll/leashdll.c create mode 100644 krb5-1.21.3/src/windows/leashdll/leashdll.h create mode 100644 krb5-1.21.3/src/windows/leashdll/leasherr.c create mode 100644 krb5-1.21.3/src/windows/leashdll/leasherr.et create mode 100644 krb5-1.21.3/src/windows/leashdll/leashids.h create mode 100644 krb5-1.21.3/src/windows/leashdll/leashw32.def create mode 100644 krb5-1.21.3/src/windows/leashdll/lsh_pwd.c create mode 100644 krb5-1.21.3/src/windows/leashdll/lsh_pwd.rc create mode 100644 krb5-1.21.3/src/windows/leashdll/lshfunc.c create mode 100644 krb5-1.21.3/src/windows/leashdll/lshutil.cpp create mode 100644 krb5-1.21.3/src/windows/leashdll/reminder.h create mode 100644 krb5-1.21.3/src/windows/leashdll/res/islogo.bmp create mode 100644 krb5-1.21.3/src/windows/leashdll/res/leash.ico create mode 100644 krb5-1.21.3/src/windows/leashdll/resource.h create mode 100644 krb5-1.21.3/src/windows/leashdll/timesync.c create mode 100644 krb5-1.21.3/src/windows/leashdll/ver.rc create mode 100644 krb5-1.21.3/src/windows/leashdll/winerr.c create mode 100644 krb5-1.21.3/src/windows/leashdll/winutil.c create mode 100644 krb5-1.21.3/src/windows/lib/Makefile.in create mode 100644 krb5-1.21.3/src/windows/lib/cacheapi.h create mode 100644 krb5-1.21.3/src/windows/lib/loadfuncs.c create mode 100644 krb5-1.21.3/src/windows/ms2mit/Makefile.in create mode 100644 krb5-1.21.3/src/windows/ms2mit/mit2ms.c create mode 100644 krb5-1.21.3/src/windows/ms2mit/ms2mit.c create mode 100644 krb5-1.21.3/src/windows/version.rc create mode 100644 krb5-1.21.3/src/windows/winlevel.h diff --git a/ci/docker/manylinux/Dockerfile.2014_x86_64 b/ci/docker/manylinux/Dockerfile.2014_x86_64 index b2d86f79..a41fa161 100644 --- a/ci/docker/manylinux/Dockerfile.2014_x86_64 +++ b/ci/docker/manylinux/Dockerfile.2014_x86_64 @@ -3,6 +3,7 @@ FROM quay.io/pypa/manylinux2014_x86_64 ENV OPENSSL=openssl-3.4.0 ENV LIBSSH_VERSION=0.11.1 ENV SYSTEM_LIBSSH=1 +ENV KRB=1.21.3 ENV CFLAGS="-g0 -s" RUN yum install zlib-devel cmake3 perl-IPC-Cmd -y @@ -10,6 +11,14 @@ RUN yum install zlib-devel cmake3 perl-IPC-Cmd -y ADD libssh-${LIBSSH_VERSION}.tar.gz libssh.tar.gz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz + +# Kerberos +RUN cd krb5-${KRB}/src && \ + ./configure && \ + make -j6 && \ + make install + + RUN tar -xzf ${OPENSSL}.tar.gz # Openssl RUN cd ${OPENSSL} && \ diff --git a/ci/docker/manylinux/Dockerfile.aarch64 b/ci/docker/manylinux/Dockerfile.aarch64 index b6a078cc..92864bbb 100644 --- a/ci/docker/manylinux/Dockerfile.aarch64 +++ b/ci/docker/manylinux/Dockerfile.aarch64 @@ -3,6 +3,7 @@ FROM quay.io/pypa/manylinux2014_aarch64 ENV OPENSSL=openssl-3.4.0 ENV LIBSSH_VERSION=0.11.1 ENV SYSTEM_LIBSSH=1 +ENV KRB=1.21.3 ENV CFLAGS="-g0 -s" ENV OPENSSL_ROOT_DIR=/usr/lib @@ -11,6 +12,13 @@ RUN yum install epel-release -y && yum install zlib-devel cmake3 perl-IPC-Cmd -y ADD libssh-${LIBSSH_VERSION}.tar.gz libssh.tar.gz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz + +RUN cd krb5-${KRB}/src && \ + ./configure && \ + make -j6 && \ + make install + + RUN tar -xzf ${OPENSSL}.tar.gz # Openssl RUN cd ${OPENSSL} && \ @@ -19,7 +27,7 @@ RUN cd ${OPENSSL} && \ # Libssh -RUN mkdir -p build_libssh && cd build_libssh && \ +RUN which gcc; mkdir -p build_libssh && cd build_libssh && \ cmake3 ../libssh.tar.gz/libssh -DCMAKE_BUILD_TYPE=Release \ -DWITH_GSSAPI=ON -DWITH_EXAMPLES=OFF -DWITH_SERVER=OFF && \ make -j6 install/strip diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 index f368bc97..cb65f855 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_24_x86_64 @@ -3,6 +3,7 @@ FROM quay.io/pypa/manylinux_2_24_x86_64 ENV OPENSSL=openssl-3.4.0 ENV LIBSSH_VERSION=0.11.1 ENV SYSTEM_LIBSSH=1 +ENV KRB=1.21.3 ENV CFLAGS="-g0 -s" ENV OPENSSL_ROOT_DIR=/usr/lib @@ -11,6 +12,14 @@ RUN apt-get update -y && apt-get install zlib1g-dev cmake -y ADD libssh-${LIBSSH_VERSION}.tar.gz libssh.tar.gz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz + +# Kerberos +RUN cd krb5-${KRB}/src && \ + ./configure && \ + make -j6 && \ + make install + + RUN tar -xzf ${OPENSSL}.tar.gz # Openssl RUN cd ${OPENSSL} && \ diff --git a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 index f96abe70..8a79e217 100644 --- a/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 +++ b/ci/docker/manylinux/Dockerfile.manylinux_2_28_x86_64 @@ -3,6 +3,7 @@ FROM quay.io/pypa/manylinux_2_28_x86_64 ENV OPENSSL=openssl-3.4.0 ENV LIBSSH_VERSION=0.11.1 ENV SYSTEM_LIBSSH=1 +ENV KRB=1.21.3 ENV CFLAGS="-g0 -s" ENV OPENSSL_ROOT_DIR=/usr/lib @@ -11,6 +12,14 @@ RUN yum install zlib-devel cmake3 -y ADD libssh-${LIBSSH_VERSION}.tar.gz libssh.tar.gz ADD https://www.openssl.org/source/${OPENSSL}.tar.gz ${OPENSSL}.tar.gz + +# Kerberos +RUN cd krb5-${KRB}/src && \ + ./configure && \ + make -j6 && \ + make install + + RUN tar -xzf ${OPENSSL}.tar.gz # Openssl RUN cd ${OPENSSL} && \ diff --git a/krb5-1.21.3/.github/workflows/build.yml b/krb5-1.21.3/.github/workflows/build.yml new file mode 100644 index 00000000..68a4788a --- /dev/null +++ b/krb5-1.21.3/.github/workflows/build.yml @@ -0,0 +1,104 @@ +name: Build + +on: + push: {paths: [src/**, .github/workflows/build.yml]} + pull_request: {paths: [src/**, .github/workflows/build.yml]} + +jobs: + + unix: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + name: [linux-clang, linux-clang-openssl, linux-gcc] + include: + - name: linux-clang + os: ubuntu-latest + compiler: clang + makevars: CPPFLAGS=-Werror + configureopts: --enable-asan + - name: linux-clang-openssl + os: ubuntu-latest + compiler: clang + makevars: CPPFLAGS=-Werror + configureopts: --with-crypto-impl=openssl + - name: linux-gcc + os: ubuntu-latest + compiler: gcc + steps: + - name: Checkout repository + uses: actions/checkout@v1 + - name: Linux setup + if: startsWith(matrix.os, 'ubuntu') + run: | + sudo apt-get update -qq + sudo apt-get install -y bison gettext keyutils ldap-utils libcmocka-dev libldap2-dev libkeyutils-dev libsasl2-dev libssl-dev python3-kdcproxy python3-pip slapd tcsh + pip3 install pyrad + - name: Build + env: + CC: ${{ matrix.compiler }} + MAKEVARS: ${{ matrix.makevars }} + CONFIGURE_OPTS: ${{ matrix.configureopts }} + run: | + cd src + autoreconf + ./configure --enable-maintainer-mode --with-ldap $CONFIGURE_OPTS --prefix=$HOME/inst + make $MAKEVARS + make check + make install + - name: Display skipped tests + run: cat src/skiptests + - name: Check for files unexpectedly not removed by make distclean + run: | + cd src + make distclean + rm -rf autom4te.cache configure include/autoconf.h.in + if [ -n "$(git ls-files -o)" ]; then + echo "Files not removed by make distclean:" + git ls-files -o + exit 1 + fi + + windows: + runs-on: windows-latest + env: + KRB_INSTALL_DIR: C:\kfw + steps: + - name: Checkout repository + uses: actions/checkout@v1 + - name: Setup + shell: cmd + run: | + mkdir %KRB_INSTALL_DIR% + - uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x86 + - name: Build 32-bit + shell: cmd + run: | + cd src + set + set PATH=%PATH%;%wix%bin + nmake -f Makefile.in prep-windows + nmake + nmake install + cd windows\installer\wix + nmake + rename kfw.msi kfw32.msi + - uses: ilammy/msvc-dev-cmd@v1 + with: + arch: x64 + - name: Build 64-bit + shell: cmd + run: | + cd src + set + set PATH=%PATH%;%wix%bin;"%WindowsSdkVerBinPath%"\x86 + nmake clean + nmake + nmake install + cd windows\installer\wix + nmake clean + nmake + rename kfw.msi kfw64.msi diff --git a/krb5-1.21.3/.github/workflows/doc.yml b/krb5-1.21.3/.github/workflows/doc.yml new file mode 100644 index 00000000..f7f6b6b0 --- /dev/null +++ b/krb5-1.21.3/.github/workflows/doc.yml @@ -0,0 +1,41 @@ +name: Doc + +on: + push: {paths: [doc/**, src/doc/*, src/include/krb5/krb5.hin, .github/workflows/doc.yml]} + pull_request: {paths: [doc/**, src/doc/*, src/include/krb5/krb5.hin, .github/workflows/doc.yml]} + +jobs: + doc-older-sphinx: + runs-on: ubuntu-22.04 + steps: + - name: Checkout repository + uses: actions/checkout@v1 + - name: Linux setup + run: | + sudo apt-get update -qq + sudo apt-get install -y doxygen python3-lxml python3-pip python3-sphinx + pip3 install Cheetah3 + - name: Build documentation + run: | + cd src/doc + make -f Makefile.in SPHINX_ARGS=-W htmlsrc + doc-newest-sphinx: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v1 + - name: Linux setup + run: | + sudo apt-get update -qq + sudo apt-get install -y doxygen python3-lxml python3-pip + pip3 install Cheetah3 sphinx + - name: Build documentation + run: | + cd src/doc + make -f Makefile.in SPHINX_ARGS=-W htmlsrc + - name: Upload HTML + uses: actions/upload-artifact@v2 + with: + name: html + path: doc/html + retention-days: 7 diff --git a/krb5-1.21.3/NOTICE b/krb5-1.21.3/NOTICE new file mode 100644 index 00000000..85ecf5a9 --- /dev/null +++ b/krb5-1.21.3/NOTICE @@ -0,0 +1,1384 @@ +Copyright (C) 1985-2024 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. + +Downloading of this software may constitute an export of cryptographic +software from the United States of America that is subject to the +United States Export Administration Regulations (EAR), 15 CFR 730-774. +Additional laws or regulations may apply. It is the responsibility of +the person or entity contemplating export to comply with all +applicable export laws and regulations, including obtaining any +required license from the U.S. government. + +The U.S. government prohibits export of encryption source code to +certain countries and individuals, including, but not limited to, the +countries of Cuba, Iran, North Korea, Sudan, Syria, and residents and +nationals of those countries. + +Documentation components of this software distribution are licensed +under a Creative Commons Attribution-ShareAlike 3.0 Unported License. +(https://creativecommons.org/licenses/by-sa/3.0/) + +Individual source code files are copyright MIT, Cygnus Support, +Novell, OpenVision Technologies, Oracle, Red Hat, Sun Microsystems, +FundsXpress, and others. + +Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, +and Zephyr are trademarks of the Massachusetts Institute of Technology +(MIT). No commercial use of these trademarks may be made without +prior written permission of MIT. + +"Commercial use" means use of a name in a product or other for-profit +manner. It does NOT prevent a commercial firm from referring to the +MIT trademarks in order to convey information (although in doing so, +recognition of their trademark status should be given). + +====================================================================== + +The following copyright and permission notice applies to the +OpenVision Kerberos Administration system located in "kadmin/create", +"kadmin/dbutil", "kadmin/passwd", "kadmin/server", "lib/kadm5", and +portions of "lib/rpc": + + Copyright, OpenVision Technologies, Inc., 1993-1996, All Rights + Reserved + + WARNING: Retrieving the OpenVision Kerberos Administration system + source code, as described below, indicates your acceptance of the + following terms. If you do not agree to the following terms, do + not retrieve the OpenVision Kerberos administration system. + + You may freely use and distribute the Source Code and Object Code + compiled from it, with or without modification, but this Source + Code is provided to you "AS IS" EXCLUSIVE OF ANY WARRANTY, + INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR + FITNESS FOR A PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER + EXPRESS OR IMPLIED. IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY + FOR ANY LOST PROFITS, LOSS OF DATA OR COSTS OF PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES, OR FOR ANY SPECIAL, INDIRECT, OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, INCLUDING, + WITHOUT LIMITATION, THOSE RESULTING FROM THE USE OF THE SOURCE + CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR ANY + OTHER REASON. + + OpenVision retains all copyrights in the donated Source Code. + OpenVision also retains copyright to derivative works of the Source + Code, whether created by OpenVision or by a third party. The + OpenVision copyright notice must be preserved if derivative works + are made based on the donated Source Code. + + OpenVision Technologies, Inc. has donated this Kerberos + Administration system to MIT for inclusion in the standard Kerberos + 5 distribution. This donation underscores our commitment to + continuing Kerberos technology development and our gratitude for + the valuable work which has been performed by MIT and the Kerberos + community. + +====================================================================== + + Portions contributed by Matt Crawford "crawdad@fnal.gov" were work + performed at Fermi National Accelerator Laboratory, which is + operated by Universities Research Association, Inc., under contract + DE-AC02-76CHO3000 with the U.S. Department of Energy. + +====================================================================== + +Portions of "src/lib/crypto" have the following copyright: + + Copyright (C) 1998 by the FundsXpress, INC. + + All rights reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of FundsXpress. not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. FundsXpress makes no representations + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + + THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +====================================================================== + +The implementation of the AES encryption algorithm in +"src/lib/crypto/builtin/aes" has the following copyright: + + Copyright (C) 1998-2013, Brian Gladman, Worcester, UK. All + rights reserved. + + The redistribution and use of this software (with or without + changes) is allowed without the payment of fees or royalties + provided that: + + source code distributions include the above copyright notice, + this list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this + list of conditions and the following disclaimer in their + documentation. + + This software is provided 'as is' with no explicit or implied + warranties in respect of its operation, including, but not limited + to, correctness and fitness for purpose. + +====================================================================== + +Portions contributed by Red Hat, including the pre-authentication +plug-in framework and the NSS crypto implementation, contain the +following copyright: + + Copyright (C) 2006 Red Hat, Inc. + Portions copyright (C) 2006 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. + + * Neither the name of Red Hat, Inc., 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 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. + +====================================================================== + +The bundled verto source code is subject to the following license: + + Copyright 2011 Red Hat, Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + +====================================================================== + +The MS-KKDCP client implementation has the following copyright: + + Copyright 2013,2014 Red Hat, Inc. + + 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. + + 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. + +====================================================================== + +The implementations of GSSAPI mechglue in GSSAPI-SPNEGO in +"src/lib/gssapi", including the following files: + + lib/gssapi/generic/gssapi_err_generic.et + lib/gssapi/mechglue/g_accept_sec_context.c + lib/gssapi/mechglue/g_acquire_cred.c + lib/gssapi/mechglue/g_canon_name.c + lib/gssapi/mechglue/g_compare_name.c + lib/gssapi/mechglue/g_context_time.c + lib/gssapi/mechglue/g_delete_sec_context.c + lib/gssapi/mechglue/g_dsp_name.c + lib/gssapi/mechglue/g_dsp_status.c + lib/gssapi/mechglue/g_dup_name.c + lib/gssapi/mechglue/g_exp_sec_context.c + lib/gssapi/mechglue/g_export_name.c + lib/gssapi/mechglue/g_glue.c + lib/gssapi/mechglue/g_imp_name.c + lib/gssapi/mechglue/g_imp_sec_context.c + lib/gssapi/mechglue/g_init_sec_context.c + lib/gssapi/mechglue/g_initialize.c + lib/gssapi/mechglue/g_inquire_context.c + lib/gssapi/mechglue/g_inquire_cred.c + lib/gssapi/mechglue/g_inquire_names.c + lib/gssapi/mechglue/g_process_context.c + lib/gssapi/mechglue/g_rel_buffer.c + lib/gssapi/mechglue/g_rel_cred.c + lib/gssapi/mechglue/g_rel_name.c + lib/gssapi/mechglue/g_rel_oid_set.c + lib/gssapi/mechglue/g_seal.c + lib/gssapi/mechglue/g_sign.c + lib/gssapi/mechglue/g_store_cred.c + lib/gssapi/mechglue/g_unseal.c + lib/gssapi/mechglue/g_userok.c + lib/gssapi/mechglue/g_utils.c + lib/gssapi/mechglue/g_verify.c + lib/gssapi/mechglue/gssd_pname_to_uid.c + lib/gssapi/mechglue/mglueP.h + lib/gssapi/mechglue/oid_ops.c + lib/gssapi/spnego/gssapiP_spnego.h + lib/gssapi/spnego/spnego_mech.c + +and the initial implementation of incremental propagation, including +the following new or changed files: + + include/iprop_hdr.h + kadmin/server/ipropd_svc.c + lib/kdb/iprop.x + lib/kdb/kdb_convert.c + lib/kdb/kdb_log.c + lib/kdb/kdb_log.h + lib/krb5/error_tables/kdb5_err.et + kprop/kpropd_rpc.c + kprop/kproplog.c + +are subject to the following license: + + Copyright (C) 2004 Sun Microsystems, Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +====================================================================== + +Kerberos V5 includes documentation and software developed at the +University of California at Berkeley, which includes this copyright +notice: + + Copyright (C) 1983 Regents of the University of California. + 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 University 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 REGENTS 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 REGENTS + 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. + +====================================================================== + +Portions contributed by Novell, Inc., including the LDAP database +backend, are subject to the following license: + + Copyright (C) 2004-2005, Novell, Inc. + 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. + + * The copyright holder's name is not 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. + +====================================================================== + +Portions funded by Sandia National Laboratory and developed by the +University of Michigan's Center for Information Technology +Integration, including the PKINIT implementation, are subject to the +following license: + + COPYRIGHT (C) 2006-2007 + THE REGENTS OF THE UNIVERSITY OF MICHIGAN + ALL RIGHTS RESERVED + + Permission is granted to use, copy, create derivative works and + redistribute this software and such derivative works for any + purpose, so long as the name of The University of Michigan is not + used in any advertising or publicity pertaining to the use of + distribution of this software without specific, written prior + authorization. If the above copyright notice or any other + identification of the University of Michigan is included in any + copy of any portion of this software, then the disclaimer below + must also be included. + + THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE + UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND + WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER + EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR + ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR + IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR + IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +====================================================================== + +The pkcs11.h file included in the PKINIT code has the following +license: + + Copyright 2006 g10 Code GmbH + Copyright 2006 Andreas Jellinghaus + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. + +====================================================================== + +Portions contributed by Apple Inc. are subject to the following +license: + + Copyright 2004-2008 Apple Inc. All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of Apple Inc. not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. Apple Inc. makes no representations + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + + THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +====================================================================== + +The implementations of UTF-8 string handling in src/util/support and +src/lib/krb5/unicode are subject to the following copyright and +permission notice: + + The OpenLDAP Public License + Version 2.8, 17 August 2003 + + Redistribution and use of this software and associated + documentation ("Software"), with or without modification, are + permitted provided that the following conditions are met: + + 1. Redistributions in source form must retain copyright + statements and notices, + + 2. Redistributions in binary form must reproduce applicable + copyright statements and notices, this list of conditions, and + the following disclaimer in the documentation and/or other + materials provided with the distribution, and + + 3. Redistributions must contain a verbatim copy of this + document. + + The OpenLDAP Foundation may revise this license from time to time. + Each revision is distinguished by a version number. You may use + this Software under terms of this license revision or under the + terms of any subsequent revision of the license. + + THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS + CONTRIBUTORS "AS IS" AND ANY EXPRESSED 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 OPENLDAP FOUNDATION, ITS + CONTRIBUTORS, OR THE AUTHOR(S) OR OWNER(S) OF THE SOFTWARE 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. + + The names of the authors and copyright holders must not be used in + advertising or otherwise to promote the sale, use or other dealing + in this Software without specific, written prior permission. Title + to copyright in this Software shall at all times remain with + copyright holders. + + OpenLDAP is a registered trademark of the OpenLDAP Foundation. + + Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, + California, USA. All Rights Reserved. Permission to copy and + distribute verbatim copies of this document is granted. + +====================================================================== + +Marked test programs in src/lib/krb5/krb have the following copyright: + + Copyright (C) 2006 Kungliga Tekniska Högskola + (Royal Institute of Technology, Stockholm, Sweden). + 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 KTH 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 KTH AND ITS 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 KTH OR ITS + 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. + +====================================================================== + +The KCM Mach RPC definition file used on macOS has the following +copyright: + + Copyright (C) 2009 Kungliga Tekniska Högskola + (Royal Institute of Technology, Stockholm, Sweden). + All rights reserved. + + Portions Copyright (C) 2009 Apple Inc. 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. + +====================================================================== + +Portions of the RPC implementation in src/lib/rpc and +src/include/gssrpc have the following copyright and permission notice: + + Copyright (C) 2010, Oracle America, Inc. + + 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 "Oracle America, Inc." 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 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. + +====================================================================== + + Copyright (C) 2006,2007,2009 NTT (Nippon Telegraph and Telephone + Corporation). 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 as the first lines of this file unmodified. + + 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. + + THIS SOFTWARE IS PROVIDED BY NTT "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 NTT 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. + +====================================================================== + + Copyright 2000 by Carnegie Mellon University + + All Rights Reserved + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + Carnegie Mellon University not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. + + CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE + FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + SOFTWARE. + +====================================================================== + + Copyright (C) 2002 Naval Research Laboratory (NRL/CCS) + + Permission to use, copy, modify and distribute this software and + its documentation is hereby granted, provided that both the + copyright notice and this permission notice appear in all copies of + the software, derivative works or modified versions, and any + portions thereof. + + NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND + DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER + RESULTING FROM THE USE OF THIS SOFTWARE. + +====================================================================== + + Copyright (C) 2022 United States Government as represented by the + Secretary of the Navy. 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. + +====================================================================== + + Copyright (C) 1991, 1992, 1994 by Cygnus Support. + + Permission to use, copy, modify, and distribute this software and + its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that copyright notice and this permission + notice appear in supporting documentation. Cygnus Support makes no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + +====================================================================== + + Copyright (C) 2006 Secure Endpoints Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +====================================================================== + +Portions of the implementation of the Fortuna-like PRNG are subject to +the following notice: + + Copyright (C) 2005 Marko Kreen + 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + + Copyright (C) 1994 by the University of Southern California + + EXPORT OF THIS SOFTWARE from the United States of America may + require a specific license from the United States Government. It + is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute + this software and its documentation in source and binary forms is + hereby granted, provided that any documentation or other materials + related to such distribution or use acknowledge that the software + was developed by the University of Southern California. + + DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The + University of Southern California MAKES NO REPRESENTATIONS OR + WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + limitation, the University of Southern California MAKES NO + REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY + PARTICULAR PURPOSE. The University of Southern California shall not + be held liable for any liability nor for any direct, indirect, or + consequential damages with respect to any claim by the user or + distributor of the ksu software. + +====================================================================== + + Copyright (C) 1995 + The President and Fellows of Harvard University + + This code is derived from software contributed to Harvard by Jeremy + Rassen. + + 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. All advertising materials mentioning features or use of this + software must display the following acknowledgement: + + This product includes software developed by the University of + California, Berkeley and its contributors. + + 4. Neither the name of the University 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 REGENTS 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 REGENTS + 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. + +====================================================================== + + Copyright (C) 2008 by the Massachusetts Institute of Technology. + Copyright 1995 by Richard P. Basch. All Rights Reserved. + Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. It + is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of Richard P. Basch, Lehman Brothers and M.I.T. not be + used in advertising or publicity pertaining to distribution of the + software without specific, written prior permission. Richard P. + Basch, Lehman Brothers and M.I.T. make no representations about the + suitability of this software for any purpose. It is provided "as + is" without express or implied warranty. + +====================================================================== + +The following notice applies to "src/lib/krb5/krb/strptime.c" and +"src/include/k5-queue.h". + + Copyright (C) 1997, 1998 The NetBSD Foundation, Inc. + All rights reserved. + + This code was contributed to The NetBSD Foundation by Klaus Klein. + + 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. All advertising materials mentioning features or use of this + software must display the following acknowledgement: + + This product includes software developed by the NetBSD + Foundation, Inc. and its contributors. + + 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + +====================================================================== + +The following notice applies to Unicode library files in +"src/lib/krb5/unicode": + + Copyright 1997, 1998, 1999 Computing Research Labs, + New Mexico State University + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE COMPUTING RESEARCH LAB OR + NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +====================================================================== + +The following notice applies to "src/util/support/strlcpy.c": + + Copyright (C) 1998 Todd C. Miller "Todd.Miller@courtesan.com" + + Permission to use, copy, modify, and distribute this software for + any purpose with or without fee is hereby granted, provided that + the above copyright notice and this permission notice appear in all + copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +====================================================================== + +The following notice applies to "src/util/profile/argv_parse.c" and +"src/util/profile/argv_parse.h": + + Copyright 1999 by Theodore Ts'o. + + Permission to use, copy, modify, and distribute this software for + any purpose with or without fee is hereby granted, provided that + the above copyright notice and this permission notice appear in all + copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE + AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (Isn't + it sick that the U.S. culture of lawsuit-happy lawyers requires + this kind of disclaimer?) + +====================================================================== + +The following notice applies to SWIG-generated code in +"src/util/profile/profile_tcl.c": + + Copyright (C) 1999-2000, The University of Chicago + + This file may be freely redistributed without license or fee + provided this copyright message remains intact. + +====================================================================== + +The following notice applies to portiions of "src/lib/rpc" and +"src/include/gssrpc": + + Copyright (C) 2000 The Regents of the University of Michigan. All + rights reserved. + + Copyright (C) 2000 Dug Song "dugsong@UMICH.EDU". All rights + reserved, all wrongs reversed. + + 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 University 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 "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 REGENTS 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. + +====================================================================== + +Implementations of the MD4 algorithm are subject to the following +notice: + + Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + + License to copy and use this software is granted provided that it + is identified as the "RSA Data Security, Inc. MD4 Message Digest + Algorithm" in all material mentioning or referencing this software + or this function. + + License is also granted to make and use derivative works provided + that such works are identified as "derived from the RSA Data + Security, Inc. MD4 Message Digest Algorithm" in all material + mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +====================================================================== + +Implementations of the MD5 algorithm are subject to the following +notice: + + Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + + License to copy and use this software is granted provided that it + is identified as the "RSA Data Security, Inc. MD5 Message- Digest + Algorithm" in all material mentioning or referencing this software + or this function. + + License is also granted to make and use derivative works provided + that such works are identified as "derived from the RSA Data + Security, Inc. MD5 Message-Digest Algorithm" in all material + mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +====================================================================== + +The following notice applies to +"src/lib/crypto/crypto_tests/t_mddriver.c": + + Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All + rights reserved. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" without + express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +====================================================================== + +Portions of "src/lib/krb5" are subject to the following notice: + + Copyright (C) 1994 CyberSAFE Corporation. + Copyright 1990,1991,2007,2008 by the Massachusetts + Institute of Technology. + All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. It + is the responsibility of any person or organization + contemplating export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. Furthermore if you modify this software + you must label your software as modified software and not + distribute it in such a fashion that it might be confused with the + original M.I.T. software. Neither M.I.T., the Open Computing + Security Group, nor CyberSAFE Corporation make any representations + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + +====================================================================== + +Portions contributed by PADL Software are subject to the following +license: + + Copyright (c) 2011, PADL Software Pty Ltd. 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE + 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. + +====================================================================== + +The bundled libev source code is subject to the following license: + + All files in libev are Copyright (C)2007,2008,2009 Marc Alexander + Lehmann. + + 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 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. + + Alternatively, the contents of this package may be used under the + terms of the GNU General Public License ("GPL") version 2 or any + later version, in which case the provisions of the GPL are + applicable instead of the above. If you wish to allow the use of + your version of this package only under the terms of the GPL and + not to allow others to use your version of this file under the BSD + license, indicate your decision by deleting the provisions above + and replace them with the notice and other provisions required by + the GPL in this and the other files of this package. If you do not + delete the provisions above, a recipient may use your version of + this file under either the BSD or the GPL. + +====================================================================== + +Files copied from the Intel AESNI Sample Library are subject to the +following license: + + Copyright (C) 2010, Intel Corporation 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 Intel Corporation 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 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. + +====================================================================== + +The following notice applies to +"src/ccapi/common/win/OldCC/autolock.hxx": + + Copyright (C) 1998 by Danilo Almeida. 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. + +====================================================================== + +The following notice applies to portions of +"src/plugins/preauth/spake/edwards25519.c" and +"src/plugins/preauth/spake/edwards25519_tables.h": + +The MIT License (MIT) + +Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS +file). + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +====================================================================== + +The following notice applies to portions of +"src/plugins/preauth/spake/edwards25519.c": + +Copyright (c) 2015-2016, Google Inc. + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted, provided that the +above copyright notice and this permission notice appear in all +copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/krb5-1.21.3/README b/krb5-1.21.3/README new file mode 100644 index 00000000..6d6f7f16 --- /dev/null +++ b/krb5-1.21.3/README @@ -0,0 +1,578 @@ + Kerberos Version 5, Release 1.21 + + Release Notes + The MIT Kerberos Team + +Copyright and Other Notices +--------------------------- + +Copyright (C) 1985-2024 by the Massachusetts Institute of Technology +and its contributors. All rights reserved. + +Please see the file named NOTICE for additional notices. + +Documentation +------------- + +Unified documentation for Kerberos V5 is available in both HTML and +PDF formats. The table of contents of the HTML format documentation +is at doc/html/index.html, and the PDF format documentation is in the +doc/pdf directory. + +Additionally, you may find copies of the HTML format documentation +online at + + https://web.mit.edu/kerberos/krb5-latest/doc/ + +for the most recent supported release, or at + + https://web.mit.edu/kerberos/krb5-devel/doc/ + +for the release under development. + +More information about Kerberos may be found at + + https://web.mit.edu/kerberos/ + +and at the MIT Kerberos Consortium web site + + https://kerberos.org/ + +Building and Installing Kerberos 5 +---------------------------------- + +Build documentation is in doc/html/build/index.html or +doc/pdf/build.pdf. + +The installation guide is in doc/html/admin/install.html or +doc/pdf/install.pdf. + +If you are attempting to build under Windows, please see the +src/windows/README file. + +Reporting Bugs +-------------- + +Please report any problems/bugs/comments by sending email to +krb5-bugs@mit.edu. + +You may view bug reports by visiting + +https://krbdev.mit.edu/rt/ + +and using the "Guest Login" button. Please note that the web +interface to our bug database is read-only for guests, and the primary +way to interact with our bug database is via email. + +PAC transitions +--------------- + +Beginning with release 1.20, the KDC will include minimal PACs in +tickets instead of AD-SIGNEDPATH authdata. S4U requests (protocol +transition and constrained delegation) must now contain valid PACs in +the incoming tickets. Beginning with release 1.21, service ticket +PACs will contain a new KDC checksum buffer, to mitigate a hash +collision attack against the old KDC checksum. If only some KDCs in a +realm have been upgraded across versions 1.20 or 1.21, the upgraded +KDCs will reject S4U requests containing tickets from non-upgraded +KDCs and vice versa. + +Triple-DES and RC4 transitions +------------------------------ + +Beginning with the krb5-1.21 release, the KDC will not issue tickets +with triple-DES or RC4 session keys unless explicitly configured using +the new allow_des3 and allow_rc4 variables in [libdefaults]. To +facilitate the negotiation of session keys, the KDC will assume that +all services can handle aes256-sha1 session keys unless the service +principal has a session_enctypes string attribute. + +Beginning with the krb5-1.19 release, a warning will be issued if +initial credentials are acquired using the des3-cbc-sha1 encryption +type. Beginning with the krb5-1.21 release, a warning will also be +issued for the arcfour-hmac encryption type. In future releases, +these encryption types will be disabled by default and eventually +removed. + +Beginning with the krb5-1.18 release, all support for single-DES +encryption types has been removed. + +Major changes in 1.21.3 (2024-06-26) +------------------------------------ + +This is a bug fix release. + +* Fix vulnerabilities in GSS message token handling [CVE-2024-37370, + CVE-2024-37371]. + +* Fix a potential bad pointer free in krb5_cccol_have_contents(). + +* Fix a memory leak in the macOS ccache type. + +krb5-1.21.2 changes by ticket ID +-------------------------------- + +9102 Eliminate sim_client include of getopt.h +9103 segfault trying to free a garbage pointer +9104 Work around Doxygen 1.9.7 change +9107 In PKINIT, check for null PKCS7 enveloped fields +9109 memory leak on macos +9115 Fix leak in KDC NDR encoding +9125 Formatting error in realm_config.rst +9128 Fix vulnerabilities in GSS message token handling + +Major changes in 1.21.2 (2023-08-14) +------------------------------------ + +This is a bug fix release. + +* Fix double-free in KDC TGS processing [CVE-2023-39975]. + +krb5-1.21.2 changes by ticket ID +-------------------------------- + +9101 Fix double-free in KDC TGS processing + +Major changes in 1.21.1 (2023-07-10) +------------------------------------ + +This is a bug fix release. + +* Fix potential uninitialized pointer free in kadm5 XDR parsing + [CVE-2023-36054]. + +krb5-1.21.1 changes by ticket ID +-------------------------------- + +9099 Ensure array count consistency in kadm5 RPC + +Major changes in 1.21 (2023-06-05) +---------------------------------- + +User experience: + +* Added a credential cache type providing compatibility with the macOS + 11 native credential cache. + +Developer experience: + +* libkadm5 will use the provided krb5_context object to read + configuration values, instead of creating its own. + +* Added an interface to retrieve the ticket session key from a GSS + context. + +Protocol evolution: + +* The KDC will no longer issue tickets with RC4 or triple-DES session + keys unless explicitly configured with the new allow_rc4 or + allow_des3 variables respectively. + +* The KDC will assume that all services can handle aes256-sha1 session + keys unless the service principal has a session_enctypes string + attribute. + +* Support for PAC full KDC checksums has been added to mitigate an + S4U2Proxy privilege escalation attack. + +* The PKINIT client will advertise a more modern set of supported CMS + algorithms. + +Code quality: + +* Removed unused code in libkrb5, libkrb5support, and the PKINIT + module. + +* Modernized the KDC code for processing TGS requests, the code for + encrypting and decrypting key data, the PAC handling code, and the + GSS library packet parsing and composition code. + +* Improved the test framework's detection of memory errors in daemon + processes when used with asan. + +krb5-1.21 changes by ticket ID +------------------------------ + +9052 Support macOS 11 native credential cache +9053 Make kprop work for dump files larger than 4GB +9054 Replace macros with typedefs in gssrpc types.h +9055 Use SHA-256 instead of SHA-1 for PKINIT CMS digest +9057 Omit LDFLAGS from krb5-config --libs output +9058 Add configure variable for default PKCS#11 module +9059 Use context profile for libkadm5 configuration +9066 Set reasonable supportedCMSTypes in PKINIT +9069 Update error checking for OpenSSL CMS_verify +9071 Add and use ts_interval() helper +9072 Avoid small read overrun in UTF8 normalization +9076 Use memmove() in Unicode functions +9077 Fix aclocal.m4 syntax error for autoconf 2.72 +9078 Fix profile crash on memory exhaustion +9079 Fix preauth crash on memory exhaustion +9080 Fix gic_keytab crash on memory exhaustion +9082 Fix policy DB fallback error handling +9083 Fix kpropd crash with unrecognized option +9084 Add PAC full checksums +9085 Fix read overruns in SPNEGO parsing +9086 Fix possible double-free during KDB creation +9087 Fix meridian type in getdate.y +9088 Use control flow guard flag in Windows builds +9089 Add pac_privsvr_enctype string attribute +9090 Convey realm names to certauth modules +9091 Add GSS_C_INQ_ODBC_SESSION_KEY +9092 Fix maintainer-mode build for binutils 2.37 +9093 Add PA-REDHAT-PASSKEY padata type + +Acknowledgements +---------------- + +Past Sponsors of the MIT Kerberos Consortium: + + Apple + Carnegie Mellon University + Centrify Corporation + Columbia University + Cornell University + The Department of Defense of the United States of America (DoD) + Fidelity Investments + Google + Iowa State University + MIT + Michigan State University + Microsoft + MITRE Corporation + Morgan-Stanley + The National Aeronautics and Space Administration + of the United States of America (NASA) + Network Appliance (NetApp) + Nippon Telephone and Telegraph (NTT) + US Government Office of the National Coordinator for Health + Information Technology (ONC) + Oracle + Pennsylvania State University + Red Hat + Stanford University + TeamF1, Inc. + The University of Alaska + The University of Michigan + The University of Pennsylvania + +Past and present members of the Kerberos Team at MIT: + + Danilo Almeida + Jeffrey Altman + Justin Anderson + Richard Basch + Mitch Berger + Jay Berkenbilt + Andrew Boardman + Bill Bryant + Steve Buckley + Joe Calzaretta + John Carr + Mark Colan + Don Davis + Sarah Day + Alexandra Ellwood + Carlos Garay + Dan Geer + Nancy Gilman + Matt Hancher + Thomas Hardjono + Sam Hartman + Paul Hill + Marc Horowitz + Eva Jacobus + Miroslav Jurisic + Barry Jaspan + Benjamin Kaduk + Geoffrey King + Kevin Koch + John Kohl + HaoQi Li + Jonathan Lin + Peter Litwack + Scott McGuire + Steve Miller + Kevin Mitchell + Cliff Neuman + Paul Park + Ezra Peisach + Chris Provenzano + Ken Raeburn + Jon Rochlis + Jeff Schiller + Jen Selby + Robert Silk + Bill Sommerfeld + Jennifer Steiner + Ralph Swick + Brad Thompson + Harry Tsai + Zhanna Tsitkova + Ted Ts'o + Marshall Vale + Taylor Yu + +The following external contributors have provided code, patches, bug +reports, suggestions, and valuable resources: + + Ian Abbott + Daniel Albers + Brandon Allbery + Russell Allbery + Brian Almeida + Michael B Allen + Pooja Anil + Jeffrey Arbuckle + Heinz-Ado Arnolds + Derek Atkins + Mark Bannister + David Bantz + Alex Baule + Nikhil Benesch + David Benjamin + Thomas Bernard + Adam Bernstein + Arlene Berry + Jeff Blaine + Toby Blake + Radoslav Bodo + Alexander Bokovoy + Sumit Bose + Emmanuel Bouillon + Isaac Boukris + Ulf Bremer + Pavel Březina + Philip Brown + Samuel Cabrero + Michael Calmer + Andrea Campi + Julien Chaffraix + Jacob Champion + Puran Chand + Ravi Channavajhala + Srinivas Cheruku + Leonardo Chiquitto + Rachit Chokshi + Seemant Choudhary + Howard Chu + Andrea Cirulli + Christopher D. Clausen + Kevin Coffman + Simon Cooper + Sylvain Cortes + Ian Crowther + Arran Cudbard-Bell + Adam Dabrowski + Jeff D'Angelo + Nalin Dahyabhai + Mark Davies + Dennis Davis + Alex Dehnert + Misty De Meo + Mark Deneen + Günther Deschner + John Devitofranceschi + Marc Dionne + Roland Dowdeswell + Ken Dreyer + Dorian Ducournau + Viktor Dukhovni + Jason Edgecombe + Mark Eichin + Shawn M. Emery + Douglas E. Engert + Peter Eriksson + Juha Erkkilä + Gilles Espinasse + Sergey Fedorov + Ronni Feldt + Bill Fellows + JC Ferguson + Remi Ferrand + Paul Fertser + Fabiano Fidêncio + Frank Filz + William Fiveash + Jacques Florent + Oliver Freyermuth + Ákos Frohner + Sebastian Galiano + Marcus Granado + Dylan Gray + Norm Green + Scott Grizzard + Helmut Grohne + Steve Grubb + Philip Guenther + Timo Gurr + Dominic Hargreaves + Robbie Harwood + John Hascall + Jakob Haufe + Matthieu Hautreux + Jochen Hein + Paul B. Henson + Kihong Heo + Jeff Hodges + Christopher Hogan + Love Hörnquist Åstrand + Ken Hornstein + Henry B. Hotz + Luke Howard + Jakub Hrozek + Shumon Huque + Jeffrey Hutzelman + Sergey Ilinykh + Wyllys Ingersoll + Holger Isenberg + Spencer Jackson + Diogenes S. Jesus + Mike Jetzer + Pavel Jindra + Brian Johannesmeyer + Joel Johnson + Lutz Justen + Ganesh Kamath + Alexander Karaivanov + Anders Kaseorg + Bar Katz + Zentaro Kavanagh + Mubashir Kazia + W. Trevor King + Patrik Kis + Martin Kittel + Thomas Klausner + Tomasz Kłoczko + Matthew Krupcale + Mikkel Kruse + Reinhard Kugler + Harshawardhan Kulkarni + Tomas Kuthan + Pierre Labastie + Andreas Ladanyi + Chris Leick + Volker Lendecke + Jan iankko Lieskovsky + Todd Lipcon + Oliver Loch + Chris Long + Kevin Longfellow + Frank Lonigro + Jon Looney + Nuno Lopes + Todd Lubin + Ryan Lynch + Glenn Machin + Roland Mainz + Sorin Manolache + Robert Marshall + Andrei Maslennikov + Michael Mattioli + Nathaniel McCallum + Greg McClement + Cameron Meadors + Vipul Mehta + Alexey Melnikov + Ivan A. Melnikov + Franklyn Mendez + Mantas Mikulėnas + Markus Moeller + Kyle Moffett + Jon Moore + Paul Moore + Keiichi Mori + Michael Morony + Robert Morris + Sam Morris + Zbysek Mraz + Edward Murrell + Joshua Neuheisel + Nikos Nikoleris + Demi Obenour + Felipe Ortega + Michael Osipov + Andrej Ota + Dmitri Pal + Javier Palacios + Dilyan Palauzov + Tom Parker + Eric Pauly + Leonard Peirce + Ezra Peisach + Alejandro Perez + Zoran Pericic + W. Michael Petullo + Mark Phalan + Sharwan Ram + Brett Randall + Jonathan Reams + Jonathan Reed + Robert Relyea + Tony Reix + Martin Rex + Pat Riehecky + Julien Rische + Jason Rogers + Matt Rogers + Nate Rosenblum + Solly Ross + Mike Roszkowski + Guillaume Rousse + Joshua Schaeffer + Alexander Scheel + Jens Schleusener + Ryan Schmidt + Andreas Schneider + Paul Seyfert + Tom Shaw + Jim Shi + Jerry Shipman + Peter Shoults + Richard Silverman + Cel Skeggs + Simo Sorce + Anthony Sottile + Michael Spang + Michael Ströder + Bjørn Tore Sund + Ondřej Surý + Joseph Sutton + Joe Travaglini + Sergei Trofimovich + Greg Troxel + Fraser Tweedale + Tim Uglow + Rathor Vipin + Denis Vlasenko + Thomas Wagner + Jorgen Wahlsten + Stef Walter + Max (Weijun) Wang + John Washington + Stef Walter + Xi Wang + Nehal J Wani + Kevin Wasserman + Margaret Wasserman + Marcus Watts + Andreas Wiese + Simon Wilkinson + Nicolas Williams + Ross Wilper + Augustin Wolf + Garrett Wollman + David Woodhouse + Tsu-Phong Wu + Xu Qiang + Neng Xue + Zhaomo Yang + Tianjiao Yin + Nickolai Zeldovich + Bean Zhang + ChenChen Zhou + Hanz van Zijst + Gertjan Zwartjes + +The above is not an exhaustive list; many others have contributed in +various ways to the MIT Kerberos development effort over the years. diff --git a/krb5-1.21.3/doc/README b/krb5-1.21.3/doc/README new file mode 100644 index 00000000..dd26cb04 --- /dev/null +++ b/krb5-1.21.3/doc/README @@ -0,0 +1,56 @@ +BUILDING +======== + +See doc/build_this.rst for details about how to build the +documentation. + + +CONVENTIONS +=========== + +We use the following conventions: + +* Use four-space indentation where indentation levels are arbitrary. + Do not use tabs anywhere. Avoid trailing whitespace at the end of + lines or files. + +* Fill lines to 70 columns (the emacs default) where lines can be + wrapped. + +* For section headers, use === underlines for page titles, --- for + sections, ~~~ for subsections, and ### for sub-subsections. Make + underlines exactly as long as titles. Do not include trailing + punctuation in section headers. Do not capitalize section headers + (except for the first word) except in source files intended to + generate man pages. + +* For bullet lists, use * for top-level bullets and - for sub-bullets. + Do not indent bullet or enumerated lists relative to the surrounding + text. + +* Use italics (*word*) for words representing variables or parameters. + Use boldface (**word**) for command options, subcommands of programs + like kadmin, and krb5.conf/kdc.conf parameter names. Use literal + text (``text``) for examples and multi-component pathnames. For + command names, single-component filenames, and krb5.conf/kdc.conf + section names, use references (like :ref:`kadmin(1)`) if introducing + them, or just use them unadorned otherwise. + +* In man pages for commands with subcommands, make a subsection for + each subcommand. Start the subcommand with an indented synopsis, + then follow with non-indented text describing the subcommand and its + options. See kadmin_local.rst for an example. + +* In man page synopses, put a newline in the RST source before each + option. Put all parts of the synopsis at the same indentation + level. Ideally we would want a hanging indent to the width of the + command or subcommand name, but RST doesn't support that. Use + boldface for literal text in the synopsis, italics for variable + text, and unadorned text for syntax symbols (such as square brackets + to indicate optional parameters). If immediately following one kind + of inline markup with another or putting inline markup next to + punctuation, you may need to use "\ " as a dummy separator. + +* For directives that take a content block (e.g., note, error, and + warning), leave a blank line before the content block (after any + arguments or options that may be present). diff --git a/krb5-1.21.3/doc/_static/kerb.css_t b/krb5-1.21.3/doc/_static/kerb.css_t new file mode 100644 index 00000000..40569b90 --- /dev/null +++ b/krb5-1.21.3/doc/_static/kerb.css_t @@ -0,0 +1,169 @@ +/* + * kerb.css + * ~~~~~~~~~~~ + * + * Sphinx stylesheet -- modification to agogo theme. + * + */ +div.body { + padding-right: .5em; + text-align: left; + overflow-x: hidden; +} + +/* Page layout */ + +div.header, div.content, div.footer { + margin-left: auto; + margin-right: auto; + padding-left: 1em; + padding-right: 1em; + max-width: 60em; +} + +div.header-wrapper { + background: white; + border-bottom: 3px solid #2e3436; + border-top: 13px solid #5d1509; +} + +/* Header */ + +div.header { + padding-top: 10px; + padding-bottom: 0px; +} + +div.header h1 { + font-family: "Georgia", "Times New Roman", serif, black; + font-weight: normal; +} + +div.header h1 a { + color: {{ theme_bgcolor }}; + font-size: 120%; + padding-top: 10px; +} + +div.header div.right a { + color: #fcaf3e; + letter-spacing: .1em; + text-transform: lowercase; + float: right; +} + +div.header div.rel { + font-family: "Georgia", "Times New Roman", serif, black; + font-weight: normal; + margin-bottom: 1.6em; +} + +/* Content */ + +div.document { + width: 80%; + float: left; + margin: 0; + background-color: white; + padding-top: 20px; + padding-bottom: 20px; +} + +div.document div.section h1 { + margin-bottom: 20px; + padding: 1px; + line-height: 130%; +} + +div.document div.section dl { + margin-top: 15px; + margin-bottom: 5px; + padding: 1px; + text-align: left; +} + +/* Sidebar */ + +div.sidebar { + float: right; + font-size: .9em; + width: 20%; + margin: 0; + padding: 0; + background-color: #F9F9F9; +} + +div.sidebar ul { + list-style-type: none; + margin-left: .5em; +} + +div.sidebar li.toctree-l1 a { + margin-left: .5em; +} + +div.sidebar li.toctree-l2 a { + margin-left: .5em; +} + +div.sidebar li.toctree-l3 a { + margin-left: .5em; +} + +div.sidebar li.toctree-l2.current a { + border-right: 2px solid #fcaf3e !important; +} + +div.sidebar li.toctree-l3.current a { + font-weight: bold; +} + +div.sidebar li.toctree-l4 a { + display: none; +} + +div.sidebar input[type=text] { + width: auto; +} + +/* Other body styles */ + +dt:target, .highlighted { + background-color: #c1c1c1; +} + +/* Code displays */ + +pre { + overflow: auto; + overflow-y: hidden; +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +/* ordered lists */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style-type: lower-roman; +} + +ol.upperroman { + list-style-type: upper-roman; +} diff --git a/krb5-1.21.3/doc/_templates/layout.html b/krb5-1.21.3/doc/_templates/layout.html new file mode 100644 index 00000000..f05b9192 --- /dev/null +++ b/krb5-1.21.3/doc/_templates/layout.html @@ -0,0 +1,73 @@ +{% extends "!layout.html" %} +{% set rellinks = [('search', 'Enter search criteria', 'S', 'Search')] + + rellinks + + [('index', 'Full Table of Contents', 'C', 'Contents')] %} + +{# Add a "feedback" button to the rellinks #} +{%- macro feedback_rellinks() %} + {%- for rellink in rellinks|reverse %} + {{ rellink[3] }}{{ reldelim2 }} + {%- endfor %} + feedback +{%- endmacro %} + +{% block footer %} + +{% endblock %} + +{% block header %} +
+
+ {% if logo %} + + {% endif %} + {% block headertitle %} +

{{ shorttitle|e }}

+ {% endblock %} +
+ {{ feedback_rellinks() }} +
+
+
+{% endblock %} + +{%- block sidebartoc %} +

{{ _('On this page') }}

+ {{ toc }} +
+

{{ _('Table of contents') }}

+ {{ toctree(collapse=true, maxdepth=3, titles_only=true, + includehidden=false) }} +
+

Full Table of Contents

+{%- endblock %} + +{%- block sidebarsearch %} +

{{ _('Search') }}

+ +{%- endblock %} diff --git a/krb5-1.21.3/doc/about.rst b/krb5-1.21.3/doc/about.rst new file mode 100644 index 00000000..dfdc31fb --- /dev/null +++ b/krb5-1.21.3/doc/about.rst @@ -0,0 +1,35 @@ +Contributing to the MIT Kerberos Documentation +============================================== + +We are looking for documentation writers and editors who could contribute +towards improving the MIT KC documentation content. If you are an experienced +Kerberos developer and/or administrator, please consider sharing your knowledge +and experience with the Kerberos Community. You can suggest your own topic or +write about any of the topics listed +`here `__. + +If you have any questions, comments, or suggestions on the existing documents, +please send your feedback via email to krb5-bugs@mit.edu. The HTML version of +this documentation has a "FEEDBACK" link to the krb5-bugs@mit.edu email +address with a pre-constructed subject line. + + +Background +---------- + +Starting with release 1.11, the Kerberos documentation set is +unified in a central form. Man pages, HTML documentation, and PDF +documents are compiled from reStructuredText sources, and the application +developer documentation incorporates Doxygen markup from the source +tree. This project was undertaken along the outline described +`here `__. + +Previous versions of Kerberos 5 attempted to maintain separate documentation +in the texinfo format, with separate groff manual pages. Having the API +documentation disjoint from the source code implementing that API +resulted in the documentation becoming stale, and over time the documentation +ceased to match reality. With a fresh start and a source format that is +easier to use and maintain, reStructuredText-based documents should provide +an improved experience for the user. Consolidating all the documentation +formats into a single source document makes the documentation set easier +to maintain. diff --git a/krb5-1.21.3/doc/admin/admin_commands/index.rst b/krb5-1.21.3/doc/admin/admin_commands/index.rst new file mode 100644 index 00000000..e8dc7652 --- /dev/null +++ b/krb5-1.21.3/doc/admin/admin_commands/index.rst @@ -0,0 +1,17 @@ +Administration programs +======================== + +.. toctree:: + :maxdepth: 1 + + kadmin_local.rst + kadmind.rst + kdb5_util.rst + kdb5_ldap_util.rst + krb5kdc.rst + kprop.rst + kpropd.rst + kproplog.rst + ktutil.rst + k5srvutil.rst + sserver.rst diff --git a/krb5-1.21.3/doc/admin/admin_commands/k5srvutil.rst b/krb5-1.21.3/doc/admin/admin_commands/k5srvutil.rst new file mode 100644 index 00000000..79502cf9 --- /dev/null +++ b/krb5-1.21.3/doc/admin/admin_commands/k5srvutil.rst @@ -0,0 +1,69 @@ +.. _k5srvutil(1): + +k5srvutil +========= + +SYNOPSIS +-------- + +**k5srvutil** *operation* +[**-i**] +[**-f** *filename*] +[**-e** *keysalts*] + +DESCRIPTION +----------- + +k5srvutil allows an administrator to list keys currently in +a keytab, to obtain new keys for a principal currently in a keytab, +or to delete non-current keys from a keytab. + +*operation* must be one of the following: + +**list** + Lists the keys in a keytab, showing version number and principal + name. + +**change** + Uses the kadmin protocol to update the keys in the Kerberos + database to new randomly-generated keys, and updates the keys in + the keytab to match. If a key's version number doesn't match the + version number stored in the Kerberos server's database, then the + operation will fail. If the **-i** flag is given, k5srvutil will + prompt for confirmation before changing each key. If the **-k** + option is given, the old and new keys will be displayed. + Ordinarily, keys will be generated with the default encryption + types and key salts. This can be overridden with the **-e** + option. Old keys are retained in the keytab so that existing + tickets continue to work, but **delold** should be used after + such tickets expire, to prevent attacks against the old keys. + +**delold** + Deletes keys that are not the most recent version from the keytab. + This operation should be used some time after a change operation + to remove old keys, after existing tickets issued for the service + have expired. If the **-i** flag is given, then k5srvutil will + prompt for confirmation for each principal. + +**delete** + Deletes particular keys in the keytab, interactively prompting for + each key. + +In all cases, the default keytab is used unless this is overridden by +the **-f** option. + +k5srvutil uses the :ref:`kadmin(1)` program to edit the keytab in +place. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kadmin(1)`, :ref:`ktutil(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/admin/admin_commands/kadmin_local.rst b/krb5-1.21.3/doc/admin/admin_commands/kadmin_local.rst new file mode 100644 index 00000000..2435b3c3 --- /dev/null +++ b/krb5-1.21.3/doc/admin/admin_commands/kadmin_local.rst @@ -0,0 +1,985 @@ +.. _kadmin(1): + +kadmin +====== + +SYNOPSIS +-------- + +.. _kadmin_synopsis: + +**kadmin** +[**-O**\|\ **-N**] +[**-r** *realm*] +[**-p** *principal*] +[**-q** *query*] +[[**-c** *cache_name*]\|[**-k** [**-t** *keytab*]]\|\ **-n**] +[**-w** *password*] +[**-s** *admin_server*\ [:*port*]] +[command args...] + +**kadmin.local** +[**-r** *realm*] +[**-p** *principal*] +[**-q** *query*] +[**-d** *dbname*] +[**-e** *enc*:*salt* ...] +[**-m**] +[**-x** *db_args*] +[command args...] + + +DESCRIPTION +----------- + +kadmin and kadmin.local are command-line interfaces to the Kerberos V5 +administration system. They provide nearly identical functionalities; +the difference is that kadmin.local directly accesses the KDC +database, while kadmin performs operations using :ref:`kadmind(8)`. +Except as explicitly noted otherwise, this man page will use "kadmin" +to refer to both versions. kadmin provides for the maintenance of +Kerberos principals, password policies, and service key tables +(keytabs). + +The remote kadmin client uses Kerberos to authenticate to kadmind +using the service principal ``kadmin/admin`` or ``kadmin/ADMINHOST`` +(where *ADMINHOST* is the fully-qualified hostname of the admin +server). If the credentials cache contains a ticket for one of these +principals, and the **-c** credentials_cache option is specified, that +ticket is used to authenticate to kadmind. Otherwise, the **-p** and +**-k** options are used to specify the client Kerberos principal name +used to authenticate. Once kadmin has determined the principal name, +it requests a service ticket from the KDC, and uses that service +ticket to authenticate to kadmind. + +Since kadmin.local directly accesses the KDC database, it usually must +be run directly on the primary KDC with sufficient permissions to read +the KDC database. If the KDC database uses the LDAP database module, +kadmin.local can be run on any host which can access the LDAP server. + + +OPTIONS +------- + +.. _kadmin_options: + +**-r** *realm* + Use *realm* as the default database realm. + +**-p** *principal* + Use *principal* to authenticate. Otherwise, kadmin will append + ``/admin`` to the primary principal name of the default ccache, + the value of the **USER** environment variable, or the username as + obtained with getpwuid, in order of preference. + +**-k** + Use a keytab to decrypt the KDC response instead of prompting for + a password. In this case, the default principal will be + ``host/hostname``. If there is no keytab specified with the + **-t** option, then the default keytab will be used. + +**-t** *keytab* + Use *keytab* to decrypt the KDC response. This can only be used + with the **-k** option. + +**-n** + Requests anonymous processing. Two types of anonymous principals + are supported. For fully anonymous Kerberos, configure PKINIT on + the KDC and configure **pkinit_anchors** in the client's + :ref:`krb5.conf(5)`. Then use the **-n** option with a principal + of the form ``@REALM`` (an empty principal name followed by the + at-sign and a realm name). If permitted by the KDC, an anonymous + ticket will be returned. A second form of anonymous tickets is + supported; these realm-exposed tickets hide the identity of the + client but not the client's realm. For this mode, use ``kinit + -n`` with a normal principal name. If supported by the KDC, the + principal (but not realm) will be replaced by the anonymous + principal. As of release 1.8, the MIT Kerberos KDC only supports + fully anonymous operation. + +**-c** *credentials_cache* + Use *credentials_cache* as the credentials cache. The cache + should contain a service ticket for the ``kadmin/admin`` or + ``kadmin/ADMINHOST`` (where *ADMINHOST* is the fully-qualified + hostname of the admin server) service; it can be acquired with the + :ref:`kinit(1)` program. If this option is not specified, kadmin + requests a new service ticket from the KDC, and stores it in its + own temporary ccache. + +**-w** *password* + Use *password* instead of prompting for one. Use this option with + care, as it may expose the password to other users on the system + via the process list. + +**-q** *query* + Perform the specified query and then exit. + +**-d** *dbname* + Specifies the name of the KDC database. This option does not + apply to the LDAP database module. + +**-s** *admin_server*\ [:*port*] + Specifies the admin server which kadmin should contact. + +**-m** + If using kadmin.local, prompt for the database master password + instead of reading it from a stash file. + +**-e** "*enc*:*salt* ..." + Sets the keysalt list to be used for any new keys created. See + :ref:`Keysalt_lists` in :ref:`kdc.conf(5)` for a list of possible + values. + +**-O** + Force use of old AUTH_GSSAPI authentication flavor. + +**-N** + Prevent fallback to AUTH_GSSAPI authentication flavor. + +**-x** *db_args* + Specifies the database specific arguments. See the next section + for supported options. + +Starting with release 1.14, if any command-line arguments remain after +the options, they will be treated as a single query to be executed. +This mode of operation is intended for scripts and behaves differently +from the interactive mode in several respects: + +* Query arguments are split by the shell, not by kadmin. +* Informational and warning messages are suppressed. Error messages + and query output (e.g. for **get_principal**) will still be + displayed. +* Confirmation prompts are disabled (as if **-force** was given). + Password prompts will still be issued as required. +* The exit status will be non-zero if the query fails. + +The **-q** option does not carry these behavior differences; the query +will be processed as if it was entered interactively. The **-q** +option cannot be used in combination with a query in the remaining +arguments. + +.. _dboptions: + +DATABASE OPTIONS +---------------- + +Database options can be used to override database-specific defaults. +Supported options for the DB2 module are: + + **-x dbname=**\ \*filename* + Specifies the base filename of the DB2 database. + + **-x lockiter** + Make iteration operations hold the lock for the duration of + the entire operation, rather than temporarily releasing the + lock while handling each principal. This is the default + behavior, but this option exists to allow command line + override of a [dbmodules] setting. First introduced in + release 1.13. + + **-x unlockiter** + Make iteration operations unlock the database for each + principal, instead of holding the lock for the duration of the + entire operation. First introduced in release 1.13. + +Supported options for the LDAP module are: + + **-x host=**\ *ldapuri* + Specifies the LDAP server to connect to by a LDAP URI. + + **-x binddn=**\ *bind_dn* + Specifies the DN used to bind to the LDAP server. + + **-x bindpwd=**\ *password* + Specifies the password or SASL secret used to bind to the LDAP + server. Using this option may expose the password to other + users on the system via the process list; to avoid this, + instead stash the password using the **stashsrvpw** command of + :ref:`kdb5_ldap_util(8)`. + + **-x sasl_mech=**\ *mechanism* + Specifies the SASL mechanism used to bind to the LDAP server. + The bind DN is ignored if a SASL mechanism is used. New in + release 1.13. + + **-x sasl_authcid=**\ *name* + Specifies the authentication name used when binding to the + LDAP server with a SASL mechanism, if the mechanism requires + one. New in release 1.13. + + **-x sasl_authzid=**\ *name* + Specifies the authorization name used when binding to the LDAP + server with a SASL mechanism. New in release 1.13. + + **-x sasl_realm=**\ *realm* + Specifies the realm used when binding to the LDAP server with + a SASL mechanism, if the mechanism uses one. New in release + 1.13. + + **-x debug=**\ *level* + sets the OpenLDAP client library debug level. *level* is an + integer to be interpreted by the library. Debugging messages + are printed to standard error. New in release 1.12. + + +COMMANDS +-------- + +When using the remote client, available commands may be restricted +according to the privileges specified in the :ref:`kadm5.acl(5)` file +on the admin server. + +.. _add_principal: + +add_principal +~~~~~~~~~~~~~ + + **add_principal** [*options*] *newprinc* + +Creates the principal *newprinc*, prompting twice for a password. If +no password policy is specified with the **-policy** option, and the +policy named ``default`` is assigned to the principal if it exists. +However, creating a policy named ``default`` will not automatically +assign this policy to previously existing principals. This policy +assignment can be suppressed with the **-clearpolicy** option. + +This command requires the **add** privilege. + +Aliases: **addprinc**, **ank** + +Options: + +**-expire** *expdate* + (:ref:`getdate` string) The expiration date of the principal. + +**-pwexpire** *pwexpdate* + (:ref:`getdate` string) The password expiration date. + +**-maxlife** *maxlife* + (:ref:`duration` or :ref:`getdate` string) The maximum ticket life + for the principal. + +**-maxrenewlife** *maxrenewlife* + (:ref:`duration` or :ref:`getdate` string) The maximum renewable + life of tickets for the principal. + +**-kvno** *kvno* + The initial key version number. + +**-policy** *policy* + The password policy used by this principal. If not specified, the + policy ``default`` is used if it exists (unless **-clearpolicy** + is specified). + +**-clearpolicy** + Prevents any policy from being assigned when **-policy** is not + specified. + +{-\|+}\ **allow_postdated** + **-allow_postdated** prohibits this principal from obtaining + postdated tickets. **+allow_postdated** clears this flag. + +{-\|+}\ **allow_forwardable** + **-allow_forwardable** prohibits this principal from obtaining + forwardable tickets. **+allow_forwardable** clears this flag. + +{-\|+}\ **allow_renewable** + **-allow_renewable** prohibits this principal from obtaining + renewable tickets. **+allow_renewable** clears this flag. + +{-\|+}\ **allow_proxiable** + **-allow_proxiable** prohibits this principal from obtaining + proxiable tickets. **+allow_proxiable** clears this flag. + +{-\|+}\ **allow_dup_skey** + **-allow_dup_skey** disables user-to-user authentication for this + principal by prohibiting others from obtaining a service ticket + encrypted in this principal's TGT session key. + **+allow_dup_skey** clears this flag. + +{-\|+}\ **requires_preauth** + **+requires_preauth** requires this principal to preauthenticate + before being allowed to kinit. **-requires_preauth** clears this + flag. When **+requires_preauth** is set on a service principal, + the KDC will only issue service tickets for that service principal + if the client's initial authentication was performed using + preauthentication. + +{-\|+}\ **requires_hwauth** + **+requires_hwauth** requires this principal to preauthenticate + using a hardware device before being allowed to kinit. + **-requires_hwauth** clears this flag. When **+requires_hwauth** is + set on a service principal, the KDC will only issue service tickets + for that service principal if the client's initial authentication was + performed using a hardware device to preauthenticate. + +{-\|+}\ **ok_as_delegate** + **+ok_as_delegate** sets the **okay as delegate** flag on tickets + issued with this principal as the service. Clients may use this + flag as a hint that credentials should be delegated when + authenticating to the service. **-ok_as_delegate** clears this + flag. + +{-\|+}\ **allow_svr** + **-allow_svr** prohibits the issuance of service tickets for this + principal. In release 1.17 and later, user-to-user service + tickets are still allowed unless the **-allow_dup_skey** flag is + also set. **+allow_svr** clears this flag. + +{-\|+}\ **allow_tgs_req** + **-allow_tgs_req** specifies that a Ticket-Granting Service (TGS) + request for a service ticket for this principal is not permitted. + **+allow_tgs_req** clears this flag. + +{-\|+}\ **allow_tix** + **-allow_tix** forbids the issuance of any tickets for this + principal. **+allow_tix** clears this flag. + +{-\|+}\ **needchange** + **+needchange** forces a password change on the next initial + authentication to this principal. **-needchange** clears this + flag. + +{-\|+}\ **password_changing_service** + **+password_changing_service** marks this principal as a password + change service principal. + +{-\|+}\ **ok_to_auth_as_delegate** + **+ok_to_auth_as_delegate** allows this principal to acquire + forwardable tickets to itself from arbitrary users, for use with + constrained delegation. + +{-\|+}\ **no_auth_data_required** + **+no_auth_data_required** prevents PAC or AD-SIGNEDPATH data from + being added to service tickets for the principal. + +{-\|+}\ **lockdown_keys** + **+lockdown_keys** prevents keys for this principal from leaving + the KDC via kadmind. The chpass and extract operations are denied + for a principal with this attribute. The chrand operation is + allowed, but will not return the new keys. The delete and rename + operations are also denied if this attribute is set, in order to + prevent a malicious administrator from replacing principals like + krbtgt/* or kadmin/* with new principals without the attribute. + This attribute can be set via the network protocol, but can only + be removed using kadmin.local. + +**-randkey** + Sets the key of the principal to a random value. + +**-nokey** + Causes the principal to be created with no key. New in release + 1.12. + +**-pw** *password* + Sets the password of the principal to the specified string and + does not prompt for a password. Note: using this option in a + shell script may expose the password to other users on the system + via the process list. + +**-e** *enc*:*salt*,... + Uses the specified keysalt list for setting the keys of the + principal. See :ref:`Keysalt_lists` in :ref:`kdc.conf(5)` for a + list of possible values. + +**-x** *db_princ_args* + Indicates database-specific options. The options for the LDAP + database module are: + + **-x dn=**\ *dn* + Specifies the LDAP object that will contain the Kerberos + principal being created. + + **-x linkdn=**\ *dn* + Specifies the LDAP object to which the newly created Kerberos + principal object will point. + + **-x containerdn=**\ *container_dn* + Specifies the container object under which the Kerberos + principal is to be created. + + **-x tktpolicy=**\ *policy* + Associates a ticket policy to the Kerberos principal. + + .. note:: + + - The **containerdn** and **linkdn** options cannot be + specified with the **dn** option. + - If the *dn* or *containerdn* options are not specified while + adding the principal, the principals are created under the + principal container configured in the realm or the realm + container. + - *dn* and *containerdn* should be within the subtrees or + principal container configured in the realm. + +Example:: + + kadmin: addprinc jennifer + No policy specified for "jennifer@ATHENA.MIT.EDU"; + defaulting to no policy. + Enter password for principal jennifer@ATHENA.MIT.EDU: + Re-enter password for principal jennifer@ATHENA.MIT.EDU: + Principal "jennifer@ATHENA.MIT.EDU" created. + kadmin: + +.. _modify_principal: + +modify_principal +~~~~~~~~~~~~~~~~ + + **modify_principal** [*options*] *principal* + +Modifies the specified principal, changing the fields as specified. +The options to **add_principal** also apply to this command, except +for the **-randkey**, **-pw**, and **-e** options. In addition, the +option **-clearpolicy** will clear the current policy of a principal. + +This command requires the *modify* privilege. + +Alias: **modprinc** + +Options (in addition to the **addprinc** options): + +**-unlock** + Unlocks a locked principal (one which has received too many failed + authentication attempts without enough time between them according + to its password policy) so that it can successfully authenticate. + +.. _rename_principal: + +rename_principal +~~~~~~~~~~~~~~~~ + + **rename_principal** [**-force**] *old_principal* *new_principal* + +Renames the specified *old_principal* to *new_principal*. This +command prompts for confirmation, unless the **-force** option is +given. + +This command requires the **add** and **delete** privileges. + +Alias: **renprinc** + +.. _delete_principal: + +delete_principal +~~~~~~~~~~~~~~~~ + + **delete_principal** [**-force**] *principal* + +Deletes the specified *principal* from the database. This command +prompts for deletion, unless the **-force** option is given. + +This command requires the **delete** privilege. + +Alias: **delprinc** + +.. _change_password: + +change_password +~~~~~~~~~~~~~~~ + + **change_password** [*options*] *principal* + +Changes the password of *principal*. Prompts for a new password if +neither **-randkey** or **-pw** is specified. + +This command requires the **changepw** privilege, or that the +principal running the program is the same as the principal being +changed. + +Alias: **cpw** + +The following options are available: + +**-randkey** + Sets the key of the principal to a random value. + +**-pw** *password* + Set the password to the specified string. Using this option in a + script may expose the password to other users on the system via + the process list. + +**-e** *enc*:*salt*,... + Uses the specified keysalt list for setting the keys of the + principal. See :ref:`Keysalt_lists` in :ref:`kdc.conf(5)` for a + list of possible values. + +**-keepold** + Keeps the existing keys in the database. This flag is usually not + necessary except perhaps for ``krbtgt`` principals. + +Example:: + + kadmin: cpw systest + Enter password for principal systest@BLEEP.COM: + Re-enter password for principal systest@BLEEP.COM: + Password for systest@BLEEP.COM changed. + kadmin: + +.. _purgekeys: + +purgekeys +~~~~~~~~~ + + **purgekeys** [**-all**\|\ **-keepkvno** *oldest_kvno_to_keep*] *principal* + +Purges previously retained old keys (e.g., from **change_password +-keepold**) from *principal*. If **-keepkvno** is specified, then +only purges keys with kvnos lower than *oldest_kvno_to_keep*. If +**-all** is specified, then all keys are purged. The **-all** option +is new in release 1.12. + +This command requires the **modify** privilege. + +.. _get_principal: + +get_principal +~~~~~~~~~~~~~ + + **get_principal** [**-terse**] *principal* + +Gets the attributes of principal. With the **-terse** option, outputs +fields as quoted tab-separated strings. + +This command requires the **inquire** privilege, or that the principal +running the the program to be the same as the one being listed. + +Alias: **getprinc** + +Examples:: + + kadmin: getprinc tlyu/admin + Principal: tlyu/admin@BLEEP.COM + Expiration date: [never] + Last password change: Mon Aug 12 14:16:47 EDT 1996 + Password expiration date: [never] + Maximum ticket life: 0 days 10:00:00 + Maximum renewable life: 7 days 00:00:00 + Last modified: Mon Aug 12 14:16:47 EDT 1996 (bjaspan/admin@BLEEP.COM) + Last successful authentication: [never] + Last failed authentication: [never] + Failed password attempts: 0 + Number of keys: 1 + Key: vno 1, aes256-cts-hmac-sha384-192 + MKey: vno 1 + Attributes: + Policy: [none] + + kadmin: getprinc -terse systest + systest@BLEEP.COM 3 86400 604800 1 + 785926535 753241234 785900000 + tlyu/admin@BLEEP.COM 786100034 0 0 + kadmin: + +.. _list_principals: + +list_principals +~~~~~~~~~~~~~~~ + + **list_principals** [*expression*] + +Retrieves all or some principal names. *expression* is a shell-style +glob expression that can contain the wild-card characters ``?``, +``*``, and ``[]``. All principal names matching the expression are +printed. If no expression is provided, all principal names are +printed. If the expression does not contain an ``@`` character, an +``@`` character followed by the local realm is appended to the +expression. + +This command requires the **list** privilege. + +Alias: **listprincs**, **get_principals**, **getprincs** + +Example:: + + kadmin: listprincs test* + test3@SECURE-TEST.OV.COM + test2@SECURE-TEST.OV.COM + test1@SECURE-TEST.OV.COM + testuser@SECURE-TEST.OV.COM + kadmin: + +.. _get_strings: + +get_strings +~~~~~~~~~~~ + + **get_strings** *principal* + +Displays string attributes on *principal*. + +This command requires the **inquire** privilege. + +Alias: **getstrs** + +.. _set_string: + +set_string +~~~~~~~~~~ + + **set_string** *principal* *name* *value* + +Sets a string attribute on *principal*. String attributes are used to +supply per-principal configuration to the KDC and some KDC plugin +modules. The following string attribute names are recognized by the +KDC: + +**require_auth** + Specifies an authentication indicator which is required to + authenticate to the principal as a service. Multiple indicators + can be specified, separated by spaces; in this case any of the + specified indicators will be accepted. (New in release 1.14.) + +**session_enctypes** + Specifies the encryption types supported for session keys when the + principal is authenticated to as a server. See + :ref:`Encryption_types` in :ref:`kdc.conf(5)` for a list of the + accepted values. + +**otp** + Enables One Time Passwords (OTP) preauthentication for a client + *principal*. The *value* is a JSON string representing an array + of objects, each having optional ``type`` and ``username`` fields. + +**pkinit_cert_match** + Specifies a matching expression that defines the certificate + attributes required for the client certificate used by the + principal during PKINIT authentication. The matching expression + is in the same format as those used by the **pkinit_cert_match** + option in :ref:`krb5.conf(5)`. (New in release 1.16.) + +**pac_privsvr_enctype** + Forces the encryption type of the PAC KDC checksum buffers to the + specified encryption type for tickets issued to this server, by + deriving a key from the local krbtgt key if it is of a different + encryption type. It may be necessary to set this value to + "aes256-sha1" on the cross-realm krbtgt entry for an Active + Directory realm when using aes-sha2 keys on the local krbtgt + entry. + +This command requires the **modify** privilege. + +Alias: **setstr** + +Example:: + + set_string host/foo.mit.edu session_enctypes aes128-cts + set_string user@FOO.COM otp "[{""type"":""hotp"",""username"":""al""}]" + +.. _del_string: + +del_string +~~~~~~~~~~ + + **del_string** *principal* *key* + +Deletes a string attribute from *principal*. + +This command requires the **delete** privilege. + +Alias: **delstr** + +.. _add_policy: + +add_policy +~~~~~~~~~~ + + **add_policy** [*options*] *policy* + +Adds a password policy named *policy* to the database. + +This command requires the **add** privilege. + +Alias: **addpol** + +The following options are available: + +**-maxlife** *time* + (:ref:`duration` or :ref:`getdate` string) Sets the maximum + lifetime of a password. + +**-minlife** *time* + (:ref:`duration` or :ref:`getdate` string) Sets the minimum + lifetime of a password. + +**-minlength** *length* + Sets the minimum length of a password. + +**-minclasses** *number* + Sets the minimum number of character classes required in a + password. The five character classes are lower case, upper case, + numbers, punctuation, and whitespace/unprintable characters. + +**-history** *number* + Sets the number of past keys kept for a principal. This option is + not supported with the LDAP KDC database module. + +.. _policy_maxfailure: + +**-maxfailure** *maxnumber* + Sets the number of authentication failures before the principal is + locked. Authentication failures are only tracked for principals + which require preauthentication. The counter of failed attempts + resets to 0 after a successful attempt to authenticate. A + *maxnumber* value of 0 (the default) disables lockout. + +.. _policy_failurecountinterval: + +**-failurecountinterval** *failuretime* + (:ref:`duration` or :ref:`getdate` string) Sets the allowable time + between authentication failures. If an authentication failure + happens after *failuretime* has elapsed since the previous + failure, the number of authentication failures is reset to 1. A + *failuretime* value of 0 (the default) means forever. + +.. _policy_lockoutduration: + +**-lockoutduration** *lockouttime* + (:ref:`duration` or :ref:`getdate` string) Sets the duration for + which the principal is locked from authenticating if too many + authentication failures occur without the specified failure count + interval elapsing. A duration of 0 (the default) means the + principal remains locked out until it is administratively unlocked + with ``modprinc -unlock``. + +**-allowedkeysalts** + Specifies the key/salt tuples supported for long-term keys when + setting or changing a principal's password/keys. See + :ref:`Keysalt_lists` in :ref:`kdc.conf(5)` for a list of the + accepted values, but note that key/salt tuples must be separated + with commas (',') only. To clear the allowed key/salt policy use + a value of '-'. + +Example:: + + kadmin: add_policy -maxlife "2 days" -minlength 5 guests + kadmin: + +.. _modify_policy: + +modify_policy +~~~~~~~~~~~~~ + + **modify_policy** [*options*] *policy* + +Modifies the password policy named *policy*. Options are as described +for **add_policy**. + +This command requires the **modify** privilege. + +Alias: **modpol** + +.. _delete_policy: + +delete_policy +~~~~~~~~~~~~~ + + **delete_policy** [**-force**] *policy* + +Deletes the password policy named *policy*. Prompts for confirmation +before deletion. The command will fail if the policy is in use by any +principals. + +This command requires the **delete** privilege. + +Alias: **delpol** + +Example:: + + kadmin: del_policy guests + Are you sure you want to delete the policy "guests"? + (yes/no): yes + kadmin: + +.. _get_policy: + +get_policy +~~~~~~~~~~ + + **get_policy** [ **-terse** ] *policy* + +Displays the values of the password policy named *policy*. With the +**-terse** flag, outputs the fields as quoted strings separated by +tabs. + +This command requires the **inquire** privilege. + +Alias: **getpol** + +Examples:: + + kadmin: get_policy admin + Policy: admin + Maximum password life: 180 days 00:00:00 + Minimum password life: 00:00:00 + Minimum password length: 6 + Minimum number of password character classes: 2 + Number of old keys kept: 5 + Reference count: 17 + + kadmin: get_policy -terse admin + admin 15552000 0 6 2 5 17 + kadmin: + +The "Reference count" is the number of principals using that policy. +With the LDAP KDC database module, the reference count field is not +meaningful. + +.. _list_policies: + +list_policies +~~~~~~~~~~~~~ + + **list_policies** [*expression*] + +Retrieves all or some policy names. *expression* is a shell-style +glob expression that can contain the wild-card characters ``?``, +``*``, and ``[]``. All policy names matching the expression are +printed. If no expression is provided, all existing policy names are +printed. + +This command requires the **list** privilege. + +Aliases: **listpols**, **get_policies**, **getpols**. + +Examples:: + + kadmin: listpols + test-pol + dict-only + once-a-min + test-pol-nopw + + kadmin: listpols t* + test-pol + test-pol-nopw + kadmin: + +.. _ktadd: + +ktadd +~~~~~ + + | **ktadd** [options] *principal* + | **ktadd** [options] **-glob** *princ-exp* + +Adds a *principal*, or all principals matching *princ-exp*, to a +keytab file. Each principal's keys are randomized in the process. +The rules for *princ-exp* are described in the **list_principals** +command. + +This command requires the **inquire** and **changepw** privileges. +With the **-glob** form, it also requires the **list** privilege. + +The options are: + +**-k[eytab]** *keytab* + Use *keytab* as the keytab file. Otherwise, the default keytab is + used. + +**-e** *enc*:*salt*,... + Uses the specified keysalt list for setting the new keys of the + principal. See :ref:`Keysalt_lists` in :ref:`kdc.conf(5)` for a + list of possible values. + +**-q** + Display less verbose information. + +**-norandkey** + Do not randomize the keys. The keys and their version numbers stay + unchanged. This option cannot be specified in combination with the + **-e** option. + +An entry for each of the principal's unique encryption types is added, +ignoring multiple keys with the same encryption type but different +salt types. + +Alias: **xst** + +Example:: + + kadmin: ktadd -k /tmp/foo-new-keytab host/foo.mit.edu + Entry for principal host/foo.mit.edu@ATHENA.MIT.EDU with kvno 3, + encryption type aes256-cts-hmac-sha1-96 added to keytab + FILE:/tmp/foo-new-keytab + kadmin: + +.. _ktremove: + +ktremove +~~~~~~~~ + + **ktremove** [options] *principal* [*kvno* | *all* | *old*] + +Removes entries for the specified *principal* from a keytab. Requires +no permissions, since this does not require database access. + +If the string "all" is specified, all entries for that principal are +removed; if the string "old" is specified, all entries for that +principal except those with the highest kvno are removed. Otherwise, +the value specified is parsed as an integer, and all entries whose +kvno match that integer are removed. + +The options are: + +**-k[eytab]** *keytab* + Use *keytab* as the keytab file. Otherwise, the default keytab is + used. + +**-q** + Display less verbose information. + +Alias: **ktrem** + +Example:: + + kadmin: ktremove kadmin/admin all + Entry for principal kadmin/admin with kvno 3 removed from keytab + FILE:/etc/krb5.keytab + kadmin: + +lock +~~~~ + +Lock database exclusively. Use with extreme caution! This command +only works with the DB2 KDC database module. + +unlock +~~~~~~ + +Release the exclusive database lock. + +list_requests +~~~~~~~~~~~~~ + +Lists available for kadmin requests. + +Aliases: **lr**, **?** + +quit +~~~~ + +Exit program. If the database was locked, the lock is released. + +Aliases: **exit**, **q** + + +HISTORY +------- + +The kadmin program was originally written by Tom Yu at MIT, as an +interface to the OpenVision Kerberos administration program. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kpasswd(1)`, :ref:`kadmind(8)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/admin/admin_commands/kadmind.rst b/krb5-1.21.3/doc/admin/admin_commands/kadmind.rst new file mode 100644 index 00000000..7e148263 --- /dev/null +++ b/krb5-1.21.3/doc/admin/admin_commands/kadmind.rst @@ -0,0 +1,129 @@ +.. _kadmind(8): + +kadmind +======= + +SYNOPSIS +-------- + +**kadmind** +[**-x** *db_args*] +[**-r** *realm*] +[**-m**] +[**-nofork**] +[**-proponly**] +[**-port** *port-number*] +[**-P** *pid_file*] +[**-p** *kdb5_util_path*] +[**-K** *kprop_path*] +[**-k** *kprop_port*] +[**-F** *dump_file*] + +DESCRIPTION +----------- + +kadmind starts the Kerberos administration server. kadmind typically +runs on the primary Kerberos server, which stores the KDC database. +If the KDC database uses the LDAP module, the administration server +and the KDC server need not run on the same machine. kadmind accepts +remote requests from programs such as :ref:`kadmin(1)` and +:ref:`kpasswd(1)` to administer the information in these database. + +kadmind requires a number of configuration files to be set up in order +for it to work: + +:ref:`kdc.conf(5)` + The KDC configuration file contains configuration information for + the KDC and admin servers. kadmind uses settings in this file to + locate the Kerberos database, and is also affected by the + **acl_file**, **dict_file**, **kadmind_port**, and iprop-related + settings. + +:ref:`kadm5.acl(5)` + kadmind's ACL (access control list) tells it which principals are + allowed to perform administration actions. The pathname to the + ACL file can be specified with the **acl_file** :ref:`kdc.conf(5)` + variable; by default, it is |kdcdir|\ ``/kadm5.acl``. + +After the server begins running, it puts itself in the background and +disassociates itself from its controlling terminal. + +kadmind can be configured for incremental database propagation. +Incremental propagation allows replica KDC servers to receive +principal and policy updates incrementally instead of receiving full +dumps of the database. This facility can be enabled in the +:ref:`kdc.conf(5)` file with the **iprop_enable** option. Incremental +propagation requires the principal ``kiprop/PRIMARY\@REALM`` (where +PRIMARY is the primary KDC's canonical host name, and REALM the realm +name). In release 1.13, this principal is automatically created and +registered into the datebase. + + +OPTIONS +------- + +**-r** *realm* + specifies the realm that kadmind will serve; if it is not + specified, the default realm of the host is used. + +**-m** + causes the master database password to be fetched from the + keyboard (before the server puts itself in the background, if not + invoked with the **-nofork** option) rather than from a file on + disk. + +**-nofork** + causes the server to remain in the foreground and remain + associated to the terminal. + +**-proponly** + causes the server to only listen and respond to Kerberos replica + incremental propagation polling requests. This option can be used + to set up a hierarchical propagation topology where a replica KDC + provides incremental updates to other Kerberos replicas. + +**-port** *port-number* + specifies the port on which the administration server listens for + connections. The default port is determined by the + **kadmind_port** configuration variable in :ref:`kdc.conf(5)`. + +**-P** *pid_file* + specifies the file to which the PID of kadmind process should be + written after it starts up. This file can be used to identify + whether kadmind is still running and to allow init scripts to stop + the correct process. + +**-p** *kdb5_util_path* + specifies the path to the kdb5_util command to use when dumping the + KDB in response to full resync requests when iprop is enabled. + +**-K** *kprop_path* + specifies the path to the kprop command to use to send full dumps + to replicas in response to full resync requests. + +**-k** *kprop_port* + specifies the port by which the kprop process that is spawned by + kadmind connects to the replica kpropd, in order to transfer the + dump file during an iprop full resync request. + +**-F** *dump_file* + specifies the file path to be used for dumping the KDB in response + to full resync requests when iprop is enabled. + +**-x** *db_args* + specifies database-specific arguments. See :ref:`Database Options + ` in :ref:`kadmin(1)` for supported arguments. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kpasswd(1)`, :ref:`kadmin(1)`, :ref:`kdb5_util(8)`, +:ref:`kdb5_ldap_util(8)`, :ref:`kadm5.acl(5)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/admin/admin_commands/kdb5_ldap_util.rst b/krb5-1.21.3/doc/admin/admin_commands/kdb5_ldap_util.rst new file mode 100644 index 00000000..73a920f4 --- /dev/null +++ b/krb5-1.21.3/doc/admin/admin_commands/kdb5_ldap_util.rst @@ -0,0 +1,449 @@ +.. _kdb5_ldap_util(8): + +kdb5_ldap_util +=============== + +SYNOPSIS +-------- + +.. _kdb5_ldap_util_synopsis: + +**kdb5_ldap_util** +[**-D** *user_dn* [**-w** *passwd*]] +[**-H** *ldapuri*] +**command** +[*command_options*] + +.. _kdb5_ldap_util_synopsis_end: + + +DESCRIPTION +----------- + +kdb5_ldap_util allows an administrator to manage realms, Kerberos +services and ticket policies. + + +COMMAND-LINE OPTIONS +-------------------- + +.. _kdb5_ldap_util_options: + +**-r** *realm* + Specifies the realm to be operated on. + +**-D** *user_dn* + Specifies the Distinguished Name (DN) of the user who has + sufficient rights to perform the operation on the LDAP server. + +**-w** *passwd* + Specifies the password of *user_dn*. This option is not + recommended. + +**-H** *ldapuri* + Specifies the URI of the LDAP server. + +By default, kdb5_ldap_util operates on the default realm (as specified +in :ref:`krb5.conf(5)`) and connects and authenticates to the LDAP +server in the same manner as :ref:kadmind(8)` would given the +parameters in :ref:`dbdefaults` in :ref:`kdc.conf(5)`. + +.. _kdb5_ldap_util_options_end: + + +COMMANDS +-------- + +create +~~~~~~ + +.. _kdb5_ldap_util_create: + + **create** + [**-subtrees** *subtree_dn_list*] + [**-sscope** *search_scope*] + [**-containerref** *container_reference_dn*] + [**-k** *mkeytype*] + [**-kv** *mkeyVNO*] + [**-M** *mkeyname*] + [**-m|-P** *password*\|\ **-sf** *stashfilename*] + [**-s**] + [**-maxtktlife** *max_ticket_life*] + [**-maxrenewlife** *max_renewable_ticket_life*] + [*ticket_flags*] + +Creates realm in directory. Options: + +**-subtrees** *subtree_dn_list* + Specifies the list of subtrees containing the principals of a + realm. The list contains the DNs of the subtree objects separated + by colon (``:``). + +**-sscope** *search_scope* + Specifies the scope for searching the principals under the + subtree. The possible values are 1 or one (one level), 2 or sub + (subtrees). + +**-containerref** *container_reference_dn* + Specifies the DN of the container object in which the principals + of a realm will be created. If the container reference is not + configured for a realm, the principals will be created in the + realm container. + +**-k** *mkeytype* + Specifies the key type of the master key in the database. The + default is given by the **master_key_type** variable in + :ref:`kdc.conf(5)`. + +**-kv** *mkeyVNO* + Specifies the version number of the master key in the database; + the default is 1. Note that 0 is not allowed. + +**-M** *mkeyname* + Specifies the principal name for the master key in the database. + If not specified, the name is determined by the + **master_key_name** variable in :ref:`kdc.conf(5)`. + +**-m** + Specifies that the master database password should be read from + the TTY rather than fetched from a file on the disk. + +**-P** *password* + Specifies the master database password. This option is not + recommended. + +**-sf** *stashfilename* + Specifies the stash file of the master database password. + +**-s** + Specifies that the stash file is to be created. + +**-maxtktlife** *max_ticket_life* + (:ref:`getdate` string) Specifies maximum ticket life for + principals in this realm. + +**-maxrenewlife** *max_renewable_ticket_life* + (:ref:`getdate` string) Specifies maximum renewable life of + tickets for principals in this realm. + +*ticket_flags* + Specifies global ticket flags for the realm. Allowable flags are + documented in the description of the **add_principal** command in + :ref:`kadmin(1)`. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu + -r ATHENA.MIT.EDU create -subtrees o=org -sscope SUB + Password for "cn=admin,o=org": + Initializing database for realm 'ATHENA.MIT.EDU' + You will be prompted for the database Master Password. + It is important that you NOT FORGET this password. + Enter KDC database master key: + Re-enter KDC database master key to verify: + +.. _kdb5_ldap_util_create_end: + +modify +~~~~~~ + +.. _kdb5_ldap_util_modify: + + **modify** + [**-subtrees** *subtree_dn_list*] + [**-sscope** *search_scope*] + [**-containerref** *container_reference_dn*] + [**-maxtktlife** *max_ticket_life*] + [**-maxrenewlife** *max_renewable_ticket_life*] + [*ticket_flags*] + +Modifies the attributes of a realm. Options: + +**-subtrees** *subtree_dn_list* + Specifies the list of subtrees containing the principals of a + realm. The list contains the DNs of the subtree objects separated + by colon (``:``). This list replaces the existing list. + +**-sscope** *search_scope* + Specifies the scope for searching the principals under the + subtrees. The possible values are 1 or one (one level), 2 or sub + (subtrees). + +**-containerref** *container_reference_dn* Specifies the DN of the + container object in which the principals of a realm will be + created. + +**-maxtktlife** *max_ticket_life* + (:ref:`getdate` string) Specifies maximum ticket life for + principals in this realm. + +**-maxrenewlife** *max_renewable_ticket_life* + (:ref:`getdate` string) Specifies maximum renewable life of + tickets for principals in this realm. + +*ticket_flags* + Specifies global ticket flags for the realm. Allowable flags are + documented in the description of the **add_principal** command in + :ref:`kadmin(1)`. + +Example:: + + shell% kdb5_ldap_util -r ATHENA.MIT.EDU -D cn=admin,o=org -H + ldaps://ldap-server1.mit.edu modify +requires_preauth + Password for "cn=admin,o=org": + shell% + +.. _kdb5_ldap_util_modify_end: + +view +~~~~ + +.. _kdb5_ldap_util_view: + + **view** + +Displays the attributes of a realm. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu + -r ATHENA.MIT.EDU view + Password for "cn=admin,o=org": + Realm Name: ATHENA.MIT.EDU + Subtree: ou=users,o=org + Subtree: ou=servers,o=org + SearchScope: ONE + Maximum ticket life: 0 days 01:00:00 + Maximum renewable life: 0 days 10:00:00 + Ticket flags: DISALLOW_FORWARDABLE REQUIRES_PWCHANGE + +.. _kdb5_ldap_util_view_end: + +destroy +~~~~~~~ + +.. _kdb5_ldap_util_destroy: + + **destroy** [**-f**] + +Destroys an existing realm. Options: + +**-f** + If specified, will not prompt the user for confirmation. + +Example:: + + shell% kdb5_ldap_util -r ATHENA.MIT.EDU -D cn=admin,o=org -H + ldaps://ldap-server1.mit.edu destroy + Password for "cn=admin,o=org": + Deleting KDC database of 'ATHENA.MIT.EDU', are you sure? + (type 'yes' to confirm)? yes + OK, deleting database of 'ATHENA.MIT.EDU'... + shell% + +.. _kdb5_ldap_util_destroy_end: + +list +~~~~ + +.. _kdb5_ldap_util_list: + + **list** + +Lists the names of realms under the container. + +Example:: + + shell% kdb5_ldap_util -D cn=admin,o=org -H + ldaps://ldap-server1.mit.edu list + Password for "cn=admin,o=org": + ATHENA.MIT.EDU + OPENLDAP.MIT.EDU + MEDIA-LAB.MIT.EDU + shell% + +.. _kdb5_ldap_util_list_end: + +stashsrvpw +~~~~~~~~~~ + +.. _kdb5_ldap_util_stashsrvpw: + + **stashsrvpw** + [**-f** *filename*] + *name* + +Allows an administrator to store the password for service object in a +file so that KDC and Administration server can use it to authenticate +to the LDAP server. Options: + +**-f** *filename* + Specifies the complete path of the service password file. By + default, ``/usr/local/var/service_passwd`` is used. + +*name* + Specifies the name of the object whose password is to be stored. + If :ref:`krb5kdc(8)` or :ref:`kadmind(8)` are configured for + simple binding, this should be the distinguished name it will + use as given by the **ldap_kdc_dn** or **ldap_kadmind_dn** + variable in :ref:`kdc.conf(5)`. If the KDC or kadmind is + configured for SASL binding, this should be the authentication + name it will use as given by the **ldap_kdc_sasl_authcid** or + **ldap_kadmind_sasl_authcid** variable. + +Example:: + + kdb5_ldap_util stashsrvpw -f /home/andrew/conf_keyfile + cn=service-kdc,o=org + Password for "cn=service-kdc,o=org": + Re-enter password for "cn=service-kdc,o=org": + +.. _kdb5_ldap_util_stashsrvpw_end: + +create_policy +~~~~~~~~~~~~~ + +.. _kdb5_ldap_util_create_policy: + + **create_policy** + [**-maxtktlife** *max_ticket_life*] + [**-maxrenewlife** *max_renewable_ticket_life*] + [*ticket_flags*] + *policy_name* + +Creates a ticket policy in the directory. Options: + +**-maxtktlife** *max_ticket_life* + (:ref:`getdate` string) Specifies maximum ticket life for + principals. + +**-maxrenewlife** *max_renewable_ticket_life* + (:ref:`getdate` string) Specifies maximum renewable life of + tickets for principals. + +*ticket_flags* + Specifies the ticket flags. If this option is not specified, by + default, no restriction will be set by the policy. Allowable + flags are documented in the description of the **add_principal** + command in :ref:`kadmin(1)`. + +*policy_name* + Specifies the name of the ticket policy. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu + -r ATHENA.MIT.EDU create_policy -maxtktlife "1 day" + -maxrenewlife "1 week" -allow_postdated +needchange + -allow_forwardable tktpolicy + Password for "cn=admin,o=org": + +.. _kdb5_ldap_util_create_policy_end: + +modify_policy +~~~~~~~~~~~~~ + +.. _kdb5_ldap_util_modify_policy: + + **modify_policy** + [**-maxtktlife** *max_ticket_life*] + [**-maxrenewlife** *max_renewable_ticket_life*] + [*ticket_flags*] + *policy_name* + +Modifies the attributes of a ticket policy. Options are same as for +**create_policy**. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H + ldaps://ldap-server1.mit.edu -r ATHENA.MIT.EDU modify_policy + -maxtktlife "60 minutes" -maxrenewlife "10 hours" + +allow_postdated -requires_preauth tktpolicy + Password for "cn=admin,o=org": + +.. _kdb5_ldap_util_modify_policy_end: + +view_policy +~~~~~~~~~~~ + +.. _kdb5_ldap_util_view_policy: + + **view_policy** + *policy_name* + +Displays the attributes of the named ticket policy. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu + -r ATHENA.MIT.EDU view_policy tktpolicy + Password for "cn=admin,o=org": + Ticket policy: tktpolicy + Maximum ticket life: 0 days 01:00:00 + Maximum renewable life: 0 days 10:00:00 + Ticket flags: DISALLOW_FORWARDABLE REQUIRES_PWCHANGE + +.. _kdb5_ldap_util_view_policy_end: + +destroy_policy +~~~~~~~~~~~~~~ + +.. _kdb5_ldap_util_destroy_policy: + + **destroy_policy** + [**-force**] + *policy_name* + +Destroys an existing ticket policy. Options: + +**-force** + Forces the deletion of the policy object. If not specified, the + user will be prompted for confirmation before deleting the policy. + +*policy_name* + Specifies the name of the ticket policy. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu + -r ATHENA.MIT.EDU destroy_policy tktpolicy + Password for "cn=admin,o=org": + This will delete the policy object 'tktpolicy', are you sure? + (type 'yes' to confirm)? yes + ** policy object 'tktpolicy' deleted. + +.. _kdb5_ldap_util_destroy_policy_end: + +list_policy +~~~~~~~~~~~ + +.. _kdb5_ldap_util_list_policy: + + **list_policy** + +Lists ticket policies. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu + -r ATHENA.MIT.EDU list_policy + Password for "cn=admin,o=org": + tktpolicy + tmppolicy + userpolicy + +.. _kdb5_ldap_util_list_policy_end: + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kadmin(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/admin/admin_commands/kdb5_util.rst b/krb5-1.21.3/doc/admin/admin_commands/kdb5_util.rst new file mode 100644 index 00000000..444c58bc --- /dev/null +++ b/krb5-1.21.3/doc/admin/admin_commands/kdb5_util.rst @@ -0,0 +1,502 @@ +.. _kdb5_util(8): + +kdb5_util +========= + +SYNOPSIS +-------- + +.. _kdb5_util_synopsis: + +**kdb5_util** +[**-r** *realm*] +[**-d** *dbname*] +[**-k** *mkeytype*] +[**-kv** *mkeyVNO*] +[**-M** *mkeyname*] +[**-m**] +[**-sf** *stashfilename*] +[**-P** *password*] +[**-x** *db_args*] +*command* [*command_options*] + +.. _kdb5_util_synopsis_end: + +DESCRIPTION +----------- + +kdb5_util allows an administrator to perform maintenance procedures on +the KDC database. Databases can be created, destroyed, and dumped to +or loaded from ASCII files. kdb5_util can create a Kerberos master +key stash file or perform live rollover of the master key. + +When kdb5_util is run, it attempts to acquire the master key and open +the database. However, execution continues regardless of whether or +not kdb5_util successfully opens the database, because the database +may not exist yet or the stash file may be corrupt. + +Note that some KDC database modules may not support all kdb5_util +commands. + + +COMMAND-LINE OPTIONS +-------------------- + +.. _kdb5_util_options: + +**-r** *realm* + specifies the Kerberos realm of the database. + +**-d** *dbname* + specifies the name under which the principal database is stored; + by default the database is that listed in :ref:`kdc.conf(5)`. The + password policy database and lock files are also derived from this + value. + +**-k** *mkeytype* + specifies the key type of the master key in the database. The + default is given by the **master_key_type** variable in + :ref:`kdc.conf(5)`. + +**-kv** *mkeyVNO* + Specifies the version number of the master key in the database; + the default is 1. Note that 0 is not allowed. + +**-M** *mkeyname* + principal name for the master key in the database. If not + specified, the name is determined by the **master_key_name** + variable in :ref:`kdc.conf(5)`. + +**-m** + specifies that the master database password should be read from + the keyboard rather than fetched from a file on disk. + +**-sf** *stash_file* + specifies the stash filename of the master database password. If + not specified, the filename is determined by the + **key_stash_file** variable in :ref:`kdc.conf(5)`. + +**-P** *password* + specifies the master database password. Using this option may + expose the password to other users on the system via the process + list. + +**-x** *db_args* + specifies database-specific options. See :ref:`kadmin(1)` for + supported options. + +.. _kdb5_util_options_end: + + +COMMANDS +-------- + +create +~~~~~~ + +.. _kdb5_util_create: + + **create** [**-s**] + +Creates a new database. If the **-s** option is specified, the stash +file is also created. This command fails if the database already +exists. If the command is successful, the database is opened just as +if it had already existed when the program was first run. + +.. _kdb5_util_create_end: + +destroy +~~~~~~~ + +.. _kdb5_util_destroy: + + **destroy** [**-f**] + +Destroys the database, first overwriting the disk sectors and then +unlinking the files, after prompting the user for confirmation. With +the **-f** argument, does not prompt the user. + +.. _kdb5_util_destroy_end: + +stash +~~~~~ + +.. _kdb5_util_stash: + + **stash** [**-f** *keyfile*] + +Stores the master principal's keys in a stash file. The **-f** +argument can be used to override the *keyfile* specified in +:ref:`kdc.conf(5)`. + +.. _kdb5_util_stash_end: + +dump +~~~~ + +.. _kdb5_util_dump: + + **dump** [**-b7**\|\ **-r13**\|\ **-r18**] + [**-verbose**] [**-mkey_convert**] [**-new_mkey_file** + *mkey_file*] [**-rev**] [**-recurse**] [*filename* + [*principals*...]] + +Dumps the current Kerberos and KADM5 database into an ASCII file. By +default, the database is dumped in current format, "kdb5_util +load_dump version 7". If filename is not specified, or is the string +"-", the dump is sent to standard output. Options: + +**-b7** + causes the dump to be in the Kerberos 5 Beta 7 format ("kdb5_util + load_dump version 4"). This was the dump format produced on + releases prior to 1.2.2. + +**-r13** + causes the dump to be in the Kerberos 5 1.3 format ("kdb5_util + load_dump version 5"). This was the dump format produced on + releases prior to 1.8. + +**-r18** + causes the dump to be in the Kerberos 5 1.8 format ("kdb5_util + load_dump version 6"). This was the dump format produced on + releases prior to 1.11. + +**-verbose** + causes the name of each principal and policy to be printed as it + is dumped. + +**-mkey_convert** + prompts for a new master key. This new master key will be used to + re-encrypt principal key data in the dumpfile. The principal keys + themselves will not be changed. + +**-new_mkey_file** *mkey_file* + the filename of a stash file. The master key in this stash file + will be used to re-encrypt the key data in the dumpfile. The key + data in the database will not be changed. + +**-rev** + dumps in reverse order. This may recover principals that do not + dump normally, in cases where database corruption has occurred. + +**-recurse** + causes the dump to walk the database recursively (btree only). + This may recover principals that do not dump normally, in cases + where database corruption has occurred. In cases of such + corruption, this option will probably retrieve more principals + than the **-rev** option will. + + .. versionchanged:: 1.15 + Release 1.15 restored the functionality of the **-recurse** + option. + + .. versionchanged:: 1.5 + The **-recurse** option ceased working until release 1.15, + doing a normal dump instead of a recursive traversal. + +.. _kdb5_util_dump_end: + +load +~~~~ + +.. _kdb5_util_load: + + **load** [**-b7**\|\ **-r13**\|\ **-r18**] [**-hash**] + [**-verbose**] [**-update**] *filename* + +Loads a database dump from the named file into the named database. If +no option is given to determine the format of the dump file, the +format is detected automatically and handled as appropriate. Unless +the **-update** option is given, **load** creates a new database +containing only the data in the dump file, overwriting the contents of +any previously existing database. Note that when using the LDAP KDC +database module, the **-update** flag is required. + +Options: + +**-b7** + requires the database to be in the Kerberos 5 Beta 7 format + ("kdb5_util load_dump version 4"). This was the dump format + produced on releases prior to 1.2.2. + +**-r13** + requires the database to be in Kerberos 5 1.3 format ("kdb5_util + load_dump version 5"). This was the dump format produced on + releases prior to 1.8. + +**-r18** + requires the database to be in Kerberos 5 1.8 format ("kdb5_util + load_dump version 6"). This was the dump format produced on + releases prior to 1.11. + +**-hash** + stores the database in hash format, if using the DB2 database + type. If this option is not specified, the database will be + stored in btree format. This option is not recommended, as + databases stored in hash format are known to corrupt data and lose + principals. + +**-verbose** + causes the name of each principal and policy to be printed as it + is dumped. + +**-update** + records from the dump file are added to or updated in the existing + database. Otherwise, a new database is created containing only + what is in the dump file and the old one destroyed upon successful + completion. + +.. _kdb5_util_load_end: + +ark +~~~ + + **ark** [**-e** *enc*:*salt*,...] *principal* + +Adds new random keys to *principal* at the next available key version +number. Keys for the current highest key version number will be +preserved. The **-e** option specifies the list of encryption and +salt types to be used for the new keys. + +add_mkey +~~~~~~~~ + + **add_mkey** [**-e** *etype*] [**-s**] + +Adds a new master key to the master key principal, but does not mark +it as active. Existing master keys will remain. The **-e** option +specifies the encryption type of the new master key; see +:ref:`Encryption_types` in :ref:`kdc.conf(5)` for a list of possible +values. The **-s** option stashes the new master key in the stash +file, which will be created if it doesn't already exist. + +After a new master key is added, it should be propagated to replica +servers via a manual or periodic invocation of :ref:`kprop(8)`. Then, +the stash files on the replica servers should be updated with the +kdb5_util **stash** command. Once those steps are complete, the key +is ready to be marked active with the kdb5_util **use_mkey** command. + +use_mkey +~~~~~~~~ + + **use_mkey** *mkeyVNO* [*time*] + +Sets the activation time of the master key specified by *mkeyVNO*. +Once a master key becomes active, it will be used to encrypt newly +created principal keys. If no *time* argument is given, the current +time is used, causing the specified master key version to become +active immediately. The format for *time* is :ref:`getdate` string. + +After a new master key becomes active, the kdb5_util +**update_princ_encryption** command can be used to update all +principal keys to be encrypted in the new master key. + +list_mkeys +~~~~~~~~~~ + + **list_mkeys** + +List all master keys, from most recent to earliest, in the master key +principal. The output will show the kvno, enctype, and salt type for +each mkey, similar to the output of :ref:`kadmin(1)` **getprinc**. A +``*`` following an mkey denotes the currently active master key. + +purge_mkeys +~~~~~~~~~~~ + + **purge_mkeys** [**-f**] [**-n**] [**-v**] + +Delete master keys from the master key principal that are not used to +protect any principals. This command can be used to remove old master +keys all principal keys are protected by a newer master key. + +**-f** + does not prompt for confirmation. + +**-n** + performs a dry run, showing master keys that would be purged, but + not actually purging any keys. + +**-v** + gives more verbose output. + +update_princ_encryption +~~~~~~~~~~~~~~~~~~~~~~~ + + **update_princ_encryption** [**-f**] [**-n**] [**-v**] + [*princ-pattern*] + +Update all principal records (or only those matching the +*princ-pattern* glob pattern) to re-encrypt the key data using the +active database master key, if they are encrypted using a different +version, and give a count at the end of the number of principals +updated. If the **-f** option is not given, ask for confirmation +before starting to make changes. The **-v** option causes each +principal processed to be listed, with an indication as to whether it +needed updating or not. The **-n** option performs a dry run, only +showing the actions which would have been taken. + +tabdump +~~~~~~~ + + **tabdump** [**-H**] [**-c**] [**-e**] [**-n**] [**-o** *outfile*] + *dumptype* + +Dump selected fields of the database in a tabular format suitable for +reporting (e.g., using traditional Unix text processing tools) or +importing into relational databases. The data format is tab-separated +(default), or optionally comma-separated (CSV), with a fixed number of +columns. The output begins with a header line containing field names, +unless suppression is requested using the **-H** option. + +The *dumptype* parameter specifies the name of an output table (see +below). + +Options: + +**-H** + suppress writing the field names in a header line + +**-c** + use comma separated values (CSV) format, with minimal quoting, + instead of the default tab-separated (unquoted, unescaped) format + +**-e** + write empty hexadecimal string fields as empty fields instead of + as "-1". + +**-n** + produce numeric output for fields that normally have symbolic + output, such as enctypes and flag names. Also requests output of + time stamps as decimal POSIX time_t values. + +**-o** *outfile* + write the dump to the specified output file instead of to standard + output + +Dump types: + +**keydata** + principal encryption key information, including actual key data + (which is still encrypted in the master key) + + **name** + principal name + **keyindex** + index of this key in the principal's key list + **kvno** + key version number + **enctype** + encryption type + **key** + key data as a hexadecimal string + **salttype** + salt type + **salt** + salt data as a hexadecimal string + +**keyinfo** + principal encryption key information (as in **keydata** above), + excluding actual key data + +**princ_flags** + principal boolean attributes. Flag names print as hexadecimal + numbers if the **-n** option is specified, and all flag positions + are printed regardless of whether or not they are set. If **-n** + is not specified, print all known flag names for each principal, + but only print hexadecimal flag names if the corresponding flag is + set. + + **name** + principal name + **flag** + flag name + **value** + boolean value (0 for clear, or 1 for set) + +**princ_lockout** + state information used for tracking repeated password failures + + **name** + principal name + **last_success** + time stamp of most recent successful authentication + **last_failed** + time stamp of most recent failed authentication + **fail_count** + count of failed attempts + +**princ_meta** + principal metadata + + **name** + principal name + **modby** + name of last principal to modify this principal + **modtime** + timestamp of last modification + **lastpwd** + timestamp of last password change + **policy** + policy object name + **mkvno** + key version number of the master key that encrypts this + principal's key data + **hist_kvno** + key version number of the history key that encrypts the key + history data for this principal + +**princ_stringattrs** + string attributes (key/value pairs) + + **name** + principal name + **key** + attribute name + **value** + attribute value + +**princ_tktpolicy** + per-principal ticket policy data, including maximum ticket + lifetimes + + **name** + principal name + **expiration** + principal expiration date + **pw_expiration** + password expiration date + **max_life** + maximum ticket lifetime + **max_renew_life** + maximum renewable ticket lifetime + +Examples:: + + $ kdb5_util tabdump -o keyinfo.txt keyinfo + $ cat keyinfo.txt + name keyindex kvno enctype salttype salt + K/M@EXAMPLE.COM 0 1 aes256-cts-hmac-sha384-192 normal -1 + foo@EXAMPLE.COM 0 1 aes128-cts-hmac-sha1-96 normal -1 + bar@EXAMPLE.COM 0 1 aes128-cts-hmac-sha1-96 normal -1 + $ sqlite3 + sqlite> .mode tabs + sqlite> .import keyinfo.txt keyinfo + sqlite> select * from keyinfo where enctype like 'aes256-%'; + K/M@EXAMPLE.COM 1 1 aes256-cts-hmac-sha384-192 normal -1 + sqlite> .quit + $ awk -F'\t' '$4 ~ /aes256-/ { print }' keyinfo.txt + K/M@EXAMPLE.COM 1 1 aes256-cts-hmac-sha384-192 normal -1 + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kadmin(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/admin/admin_commands/kprop.rst b/krb5-1.21.3/doc/admin/admin_commands/kprop.rst new file mode 100644 index 00000000..a118b262 --- /dev/null +++ b/krb5-1.21.3/doc/admin/admin_commands/kprop.rst @@ -0,0 +1,60 @@ +.. _kprop(8): + +kprop +===== + +SYNOPSIS +-------- + +**kprop** +[**-r** *realm*] +[**-f** *file*] +[**-d**] +[**-P** *port*] +[**-s** *keytab*] +*replica_host* + + +DESCRIPTION +----------- + +kprop is used to securely propagate a Kerberos V5 database dump file +from the primary Kerberos server to a replica Kerberos server, which is +specified by *replica_host*. The dump file must be created by +:ref:`kdb5_util(8)`. + + +OPTIONS +------- + +**-r** *realm* + Specifies the realm of the primary server. + +**-f** *file* + Specifies the filename where the dumped principal database file is + to be found; by default the dumped database file is normally + |kdcdir|\ ``/replica_datatrans``. + +**-P** *port* + Specifies the port to use to contact the :ref:`kpropd(8)` server + on the remote host. + +**-d** + Prints debugging information. + +**-s** *keytab* + Specifies the location of the keytab file. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kpropd(8)`, :ref:`kdb5_util(8)`, :ref:`krb5kdc(8)`, +:ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/admin/admin_commands/kpropd.rst b/krb5-1.21.3/doc/admin/admin_commands/kpropd.rst new file mode 100644 index 00000000..30c66c7e --- /dev/null +++ b/krb5-1.21.3/doc/admin/admin_commands/kpropd.rst @@ -0,0 +1,144 @@ +.. _kpropd(8): + +kpropd +====== + +SYNOPSIS +-------- + +**kpropd** +[**-r** *realm*] +[**-A** *admin_server*] +[**-a** *acl_file*] +[**-f** *replica_dumpfile*] +[**-F** *principal_database*] +[**-p** *kdb5_util_prog*] +[**-P** *port*] +[**--pid-file**\ =\ *pid_file*] +[**-D**] +[**-d**] +[**-s** *keytab_file*] + +DESCRIPTION +----------- + +The *kpropd* command runs on the replica KDC server. It listens for +update requests made by the :ref:`kprop(8)` program. If incremental +propagation is enabled, it periodically requests incremental updates +from the primary KDC. + +When the replica receives a kprop request from the primary, kpropd +accepts the dumped KDC database and places it in a file, and then runs +:ref:`kdb5_util(8)` to load the dumped database into the active +database which is used by :ref:`krb5kdc(8)`. This allows the primary +Kerberos server to use :ref:`kprop(8)` to propagate its database to +the replica servers. Upon a successful download of the KDC database +file, the replica Kerberos server will have an up-to-date KDC +database. + +Where incremental propagation is not used, kpropd is commonly invoked +out of inetd(8) as a nowait service. This is done by adding a line to +the ``/etc/inetd.conf`` file which looks like this:: + + kprop stream tcp nowait root /usr/local/sbin/kpropd kpropd + +kpropd can also run as a standalone daemon, backgrounding itself and +waiting for connections on port 754 (or the port specified with the +**-P** option if given). Standalone mode is required for incremental +propagation. Starting in release 1.11, kpropd automatically detects +whether it was run from inetd and runs in standalone mode if it is +not. Prior to release 1.11, the **-S** option is required to run +kpropd in standalone mode; this option is now accepted for backward +compatibility but does nothing. + +Incremental propagation may be enabled with the **iprop_enable** +variable in :ref:`kdc.conf(5)`. If incremental propagation is +enabled, the replica periodically polls the primary KDC for updates, at +an interval determined by the **iprop_replica_poll** variable. If the +replica receives updates, kpropd updates its log file with any updates +from the primary. :ref:`kproplog(8)` can be used to view a summary of +the update entry log on the replica KDC. If incremental propagation +is enabled, the principal ``kiprop/replicahostname@REALM`` (where +*replicahostname* is the name of the replica KDC host, and *REALM* is +the name of the Kerberos realm) must be present in the replica's +keytab file. + +:ref:`kproplog(8)` can be used to force full replication when iprop is +enabled. + + +OPTIONS +-------- + +**-r** *realm* + Specifies the realm of the primary server. + +**-A** *admin_server* + Specifies the server to be contacted for incremental updates; by + default, the primary admin server is contacted. + +**-f** *file* + Specifies the filename where the dumped principal database file is + to be stored; by default the dumped database file is |kdcdir|\ + ``/from_master``. + +**-F** *kerberos_db* + Path to the Kerberos database file, if not the default. + +**-p** + Allows the user to specify the pathname to the :ref:`kdb5_util(8)` + program; by default the pathname used is |sbindir|\ + ``/kdb5_util``. + +**-D** + In this mode, kpropd will not detach itself from the current job + and run in the background. Instead, it will run in the + foreground. + +**-d** + Turn on debug mode. kpropd will print out debugging messages + during the database propogation and will run in the foreground + (implies **-D**). + +**-P** + Allow for an alternate port number for kpropd to listen on. This + is only useful in combination with the **-S** option. + +**-a** *acl_file* + Allows the user to specify the path to the kpropd.acl file; by + default the path used is |kdcdir|\ ``/kpropd.acl``. + +**--pid-file**\ =\ *pid_file* + In standalone mode, write the process ID of the daemon into + *pid_file*. + +**-s** *keytab_file* + Path to a keytab to use for acquiring acceptor credentials. + +**-x** *db_args* + Database-specific arguments. See :ref:`Database Options + ` in :ref:`kadmin(1)` for supported arguments. + + +FILES +----- + +kpropd.acl + Access file for kpropd; the default location is + ``/usr/local/var/krb5kdc/kpropd.acl``. Each entry is a line + containing the principal of a host from which the local machine + will allow Kerberos database propagation via :ref:`kprop(8)`. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kprop(8)`, :ref:`kdb5_util(8)`, :ref:`krb5kdc(8)`, +:ref:`kerberos(7)`, inetd(8) diff --git a/krb5-1.21.3/doc/admin/admin_commands/kproplog.rst b/krb5-1.21.3/doc/admin/admin_commands/kproplog.rst new file mode 100644 index 00000000..3b72cfa0 --- /dev/null +++ b/krb5-1.21.3/doc/admin/admin_commands/kproplog.rst @@ -0,0 +1,85 @@ +.. _kproplog(8): + +kproplog +======== + +SYNOPSIS +-------- + +**kproplog** [**-h**] [**-e** *num*] [-v] +**kproplog** [-R] + + +DESCRIPTION +----------- + +The kproplog command displays the contents of the KDC database update +log to standard output. It can be used to keep track of incremental +updates to the principal database. The update log file contains the +update log maintained by the :ref:`kadmind(8)` process on the primary +KDC server and the :ref:`kpropd(8)` process on the replica KDC +servers. When updates occur, they are logged to this file. +Subsequently any KDC replica configured for incremental updates will +request the current data from the primary KDC and update their log +file with any updates returned. + +The kproplog command requires read access to the update log file. It +will display update entries only for the KDC it runs on. + +If no options are specified, kproplog displays a summary of the update +log. If invoked on the primary, kproplog also displays all of the +update entries. If invoked on a replica KDC server, kproplog displays +only a summary of the updates, which includes the serial number of the +last update received and the associated time stamp of the last update. + + +OPTIONS +------- + +**-R** + Reset the update log. This forces full resynchronization. If + used on a replica then that replica will request a full resync. + If used on the primary then all replicas will request full + resyncs. + +**-h** + Display a summary of the update log. This information includes + the database version number, state of the database, the number of + updates in the log, the time stamp of the first and last update, + and the version number of the first and last update entry. + +**-e** *num* + Display the last *num* update entries in the log. This is useful + when debugging synchronization between KDC servers. + +**-v** + Display individual attributes per update. An example of the + output generated for one entry:: + + Update Entry + Update serial # : 4 + Update operation : Add + Update principal : test@EXAMPLE.COM + Update size : 424 + Update committed : True + Update time stamp : Fri Feb 20 23:37:42 2004 + Attributes changed : 6 + Principal + Key data + Password last changed + Modifying principal + Modification time + TL data + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kpropd(8)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/admin/admin_commands/krb5kdc.rst b/krb5-1.21.3/doc/admin/admin_commands/krb5kdc.rst new file mode 100644 index 00000000..631a0de8 --- /dev/null +++ b/krb5-1.21.3/doc/admin/admin_commands/krb5kdc.rst @@ -0,0 +1,114 @@ +.. _krb5kdc(8): + +krb5kdc +======= + +SYNOPSIS +-------- + +**krb5kdc** +[**-x** *db_args*] +[**-d** *dbname*] +[**-k** *keytype*] +[**-M** *mkeyname*] +[**-p** *portnum*] +[**-m**] +[**-r** *realm*] +[**-n**] +[**-w** *numworkers*] +[**-P** *pid_file*] +[**-T** *time_offset*] + + +DESCRIPTION +----------- + +krb5kdc is the Kerberos version 5 Authentication Service and Key +Distribution Center (AS/KDC). + + +OPTIONS +------- + +The **-r** *realm* option specifies the realm for which the server +should provide service. This option may be specified multiple times +to serve multiple realms. If no **-r** option is given, the default +realm (as specified in :ref:`krb5.conf(5)`) will be served. + +The **-d** *dbname* option specifies the name under which the +principal database can be found. This option does not apply to the +LDAP database. + +The **-k** *keytype* option specifies the key type of the master key +to be entered manually as a password when **-m** is given; the default +is |defmkey|. + +The **-M** *mkeyname* option specifies the principal name for the +master key in the database (usually ``K/M`` in the KDC's realm). + +The **-m** option specifies that the master database password should +be fetched from the keyboard rather than from a stash file. + +The **-n** option specifies that the KDC does not put itself in the +background and does not disassociate itself from the terminal. + +The **-P** *pid_file* option tells the KDC to write its PID into +*pid_file* after it starts up. This can be used to identify whether +the KDC is still running and to allow init scripts to stop the correct +process. + +The **-p** *portnum* option specifies the default UDP and TCP port +numbers which the KDC should listen on for Kerberos version 5 +requests, as a comma-separated list. This value overrides the port +numbers specified in the :ref:`kdcdefaults` section of +:ref:`kdc.conf(5)`, but may be overridden by realm-specific values. +If no value is given from any source, the default port is 88. + +The **-w** *numworkers* option tells the KDC to fork *numworkers* +processes to listen to the KDC ports and process requests in parallel. +The top level KDC process (whose pid is recorded in the pid file if +the **-P** option is also given) acts as a supervisor. The supervisor +will relay SIGHUP signals to the worker subprocesses, and will +terminate the worker subprocess if the it is itself terminated or if +any other worker process exits. + +The **-x** *db_args* option specifies database-specific arguments. +See :ref:`Database Options ` in :ref:`kadmin(1)` for +supported arguments. + +The **-T** *offset* option specifies a time offset, in seconds, which +the KDC will operate under. It is intended only for testing purposes. + +EXAMPLE +------- + +The KDC may service requests for multiple realms (maximum 32 realms). +The realms are listed on the command line. Per-realm options that can +be specified on the command line pertain for each realm that follows +it and are superseded by subsequent definitions of the same option. + +For example:: + + krb5kdc -p 2001 -r REALM1 -p 2002 -r REALM2 -r REALM3 + +specifies that the KDC listen on port 2001 for REALM1 and on port 2002 +for REALM2 and REALM3. Additionally, per-realm parameters may be +specified in the :ref:`kdc.conf(5)` file. The location of this file +may be specified by the **KRB5_KDC_PROFILE** environment variable. +Per-realm parameters specified in this file take precedence over +options specified on the command line. See the :ref:`kdc.conf(5)` +description for further details. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kdb5_util(8)`, :ref:`kdc.conf(5)`, :ref:`krb5.conf(5)`, +:ref:`kdb5_ldap_util(8)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/admin/admin_commands/ktutil.rst b/krb5-1.21.3/doc/admin/admin_commands/ktutil.rst new file mode 100644 index 00000000..fd83f0ad --- /dev/null +++ b/krb5-1.21.3/doc/admin/admin_commands/ktutil.rst @@ -0,0 +1,129 @@ +.. _ktutil(1): + +ktutil +====== + +SYNOPSIS +-------- + +**ktutil** + + +DESCRIPTION +----------- + +The ktutil command invokes a command interface from which an +administrator can read, write, or edit entries in a keytab. (Kerberos +V4 srvtab files are no longer supported.) + + +COMMANDS +-------- + +list +~~~~ + + **list** [**-t**] [**-k**] [**-e**] + +Displays the current keylist. If **-t**, **-k**, and/or **-e** are +specified, also display the timestamp, key contents, or enctype +(respectively). + +Alias: **l** + +read_kt +~~~~~~~ + + **read_kt** *keytab* + +Read the Kerberos V5 keytab file *keytab* into the current keylist. + +Alias: **rkt** + +write_kt +~~~~~~~~ + + **write_kt** *keytab* + +Write the current keylist into the Kerberos V5 keytab file *keytab*. + +Alias: **wkt** + +clear_list +~~~~~~~~~~ + + **clear_list** + +Clear the current keylist. + +Alias: **clear** + +delete_entry +~~~~~~~~~~~~ + + **delete_entry** *slot* + +Delete the entry in slot number *slot* from the current keylist. + +Alias: **delent** + +add_entry +~~~~~~~~~ + + **add_entry** {**-key**\|\ **-password**} **-p** *principal* + **-k** *kvno* [**-e** *enctype*] [**-f**\|\ **-s** *salt*] + +Add *principal* to keylist using key or password. If the **-f** flag +is specified, salt information will be fetched from the KDC; in this +case the **-e** flag may be omitted, or it may be supplied to force a +particular enctype. If the **-f** flag is not specified, the **-e** +flag must be specified, and the default salt will be used unless +overridden with the **-s** option. + +Alias: **addent** + +list_requests +~~~~~~~~~~~~~ + + **list_requests** + +Displays a listing of available commands. + +Aliases: **lr**, **?** + +quit +~~~~ + + **quit** + +Quits ktutil. + +Aliases: **exit**, **q** + + +EXAMPLE +------- + + :: + + ktutil: add_entry -password -p alice@BLEEP.COM -k 1 -e + aes128-cts-hmac-sha1-96 + Password for alice@BLEEP.COM: + ktutil: add_entry -password -p alice@BLEEP.COM -k 1 -e + aes256-cts-hmac-sha1-96 + Password for alice@BLEEP.COM: + ktutil: write_kt alice.keytab + ktutil: + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kadmin(1)`, :ref:`kdb5_util(8)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/admin/admin_commands/sserver.rst b/krb5-1.21.3/doc/admin/admin_commands/sserver.rst new file mode 100644 index 00000000..a8dcf5d5 --- /dev/null +++ b/krb5-1.21.3/doc/admin/admin_commands/sserver.rst @@ -0,0 +1,112 @@ +.. _sserver(8): + +sserver +======= + +SYNOPSIS +-------- + +**sserver** +[ **-p** *port* ] +[ **-S** *keytab* ] +[ *server_port* ] + + +DESCRIPTION +----------- + +sserver and :ref:`sclient(1)` are a simple demonstration client/server +application. When sclient connects to sserver, it performs a Kerberos +authentication, and then sserver returns to sclient the Kerberos +principal which was used for the Kerberos authentication. It makes a +good test that Kerberos has been successfully installed on a machine. + +The service name used by sserver and sclient is sample. Hence, +sserver will require that there be a keytab entry for the service +``sample/hostname.domain.name@REALM.NAME``. This keytab is generated +using the :ref:`kadmin(1)` program. The keytab file is usually +installed as |keytab|. + +The **-S** option allows for a different keytab than the default. + +sserver is normally invoked out of inetd(8), using a line in +``/etc/inetd.conf`` that looks like this:: + + sample stream tcp nowait root /usr/local/sbin/sserver sserver + +Since ``sample`` is normally not a port defined in ``/etc/services``, +you will usually have to add a line to ``/etc/services`` which looks +like this:: + + sample 13135/tcp + +When using sclient, you will first have to have an entry in the +Kerberos database, by using :ref:`kadmin(1)`, and then you have to get +Kerberos tickets, by using :ref:`kinit(1)`. Also, if you are running +the sclient program on a different host than the sserver it will be +connecting to, be sure that both hosts have an entry in /etc/services +for the sample tcp port, and that the same port number is in both +files. + +When you run sclient you should see something like this:: + + sendauth succeeded, reply is: + reply len 32, contents: + You are nlgilman@JIMI.MIT.EDU + + +COMMON ERROR MESSAGES +--------------------- + +1) kinit returns the error:: + + kinit: Client not found in Kerberos database while getting + initial credentials + + This means that you didn't create an entry for your username in the + Kerberos database. + +2) sclient returns the error:: + + unknown service sample/tcp; check /etc/services + + This means that you don't have an entry in /etc/services for the + sample tcp port. + +3) sclient returns the error:: + + connect: Connection refused + + This probably means you didn't edit /etc/inetd.conf correctly, or + you didn't restart inetd after editing inetd.conf. + +4) sclient returns the error:: + + sclient: Server not found in Kerberos database while using + sendauth + + This means that the ``sample/hostname@LOCAL.REALM`` service was not + defined in the Kerberos database; it should be created using + :ref:`kadmin(1)`, and a keytab file needs to be generated to make + the key for that service principal available for sclient. + +5) sclient returns the error:: + + sendauth rejected, error reply is: + "No such file or directory" + + This probably means sserver couldn't find the keytab file. It was + probably not installed in the proper directory. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`sclient(1)`, :ref:`kerberos(7)`, services(5), inetd(8) diff --git a/krb5-1.21.3/doc/admin/advanced/index.rst b/krb5-1.21.3/doc/admin/advanced/index.rst new file mode 100644 index 00000000..834f453c --- /dev/null +++ b/krb5-1.21.3/doc/admin/advanced/index.rst @@ -0,0 +1,8 @@ +Advanced topics +=============== + + +.. toctree:: + :maxdepth: 1 + + retiring-des.rst diff --git a/krb5-1.21.3/doc/admin/advanced/retiring-des.rst b/krb5-1.21.3/doc/admin/advanced/retiring-des.rst new file mode 100644 index 00000000..38f76d3f --- /dev/null +++ b/krb5-1.21.3/doc/admin/advanced/retiring-des.rst @@ -0,0 +1,422 @@ +.. _retiring-des: + +Retiring DES +======================= + +Version 5 of the Kerberos protocol was originally implemented using +the Data Encryption Standard (DES) as a block cipher for encryption. +While it was considered secure at the time, advancements in computational +ability have rendered DES vulnerable to brute force attacks on its 56-bit +keyspace. As such, it is now considered insecure and should not be +used (:rfc:`6649`). + +History +------- + +DES was used in the original Kerberos implementation, and was the +only cryptosystem in krb5 1.0. Partial support for triple-DES (3DES) was +added in version 1.1, with full support following in version 1.2. +The Advanced Encryption Standard (AES), which supersedes DES, gained +partial support in version 1.3.0 of krb5 and full support in version 1.3.2. +However, deployments of krb5 using Kerberos databases created with older +versions of krb5 will not necessarily start using strong crypto for +ordinary operation without administrator intervention. + +MIT krb5 began flagging deprecated encryption types with release 1.17, +and removed DES (single-DES) support in release 1.18. As a +consequence, a release prior to 1.18 is required to perform these +migrations. + +Types of keys +------------- + +* The database master key: This key is not exposed to user requests, + but is used to encrypt other key material stored in the kerberos + database. The database master key is currently stored as ``K/M`` + by default. +* Password-derived keys: User principals frequently have keys + derived from a password. When a new password is set, the KDC + uses various string2key functions to generate keys in the database + for that principal. +* Keytab keys: Application server principals generally use random + keys which are not derived from a password. When the database + entry is created, the KDC generates random keys of various enctypes + to enter in the database, which are conveyed to the application server + and stored in a keytab. +* Session keys: These are short-term keys generated by the KDC while + processing client requests, with an enctype selected by the KDC. + +For details on the various enctypes and how enctypes are selected by the KDC +for session keys and client/server long-term keys, see :ref:`enctypes`. +When using the :ref:`kadmin(1)` interface to generate new long-term keys, +the **-e** argument can be used to force a particular set of enctypes, +overriding the KDC default values. + +.. note:: + + When the KDC is selecting a session key, it has no knowledge about the + kerberos installation on the server which will receive the service ticket, + only what keys are in the database for the service principal. + In order to allow uninterrupted operation to + clients while migrating away from DES, care must be taken to ensure that + kerberos installations on application server machines are configured to + support newer encryption types before keys of those new encryption types + are created in the Kerberos database for those server principals. + +Upgrade procedure +----------------- + +This procedure assumes that the KDC software has already been upgraded +to a modern version of krb5 that supports non-DES keys, so that the +only remaining task is to update the actual keys used to service requests. +The realm used for demonstrating this procedure, ZONE.MIT.EDU, +is an example of the worst-case scenario, where all keys in the realm +are DES. The realm was initially created with a very old version of krb5, +and **supported_enctypes** in :ref:`kdc.conf(5)` was set to a value +appropriate when the KDC was installed, but was not updated as the KDC +was upgraded: + +:: + + [realms] + ZONE.MIT.EDU = { + [...] + master_key_type = des-cbc-crc + supported_enctypes = des-cbc-crc:normal des:normal des:v4 des:norealm des:onlyrealm des:afs3 + } + +This resulted in the keys for all principals in the realm being forced +to DES-only, unless specifically requested using :ref:`kadmin(1)`. + +Before starting the upgrade, all KDCs were running krb5 1.11, +and the database entries for some "high-value" principals were: + +:: + + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'getprinc krbtgt/ZONE.MIT.EDU' + [...] + Number of keys: 1 + Key: vno 1, des-cbc-crc:v4 + [...] + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'getprinc kadmin/admin' + [...] + Number of keys: 1 + Key: vno 15, des-cbc-crc + [...] + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'getprinc kadmin/changepw' + [...] + Number of keys: 1 + Key: vno 14, des-cbc-crc + [...] + +The ``krbtgt/REALM`` key appears to have never been changed since creation +(its kvno is 1), and all three database entries have only a des-cbc-crc key. + +The krbtgt key and KDC keys +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Perhaps the biggest single-step improvement in the security of the cell +is gained by strengthening the key of the ticket-granting service principal, +``krbtgt/REALM``---if this principal's key is compromised, so is the +entire realm. Since the server that will handle service tickets +for this principal is the KDC itself, it is easy to guarantee that it +will be configured to support any encryption types which might be +selected. However, the default KDC behavior when creating new keys is to +remove the old keys, which would invalidate all existing tickets issued +against that principal, rendering the TGTs cached by clients useless. +Instead, a new key can be created with the old key retained, so that +existing tickets will still function until their scheduled expiry +(see :ref:`changing_krbtgt_key`). + +:: + + [root@casio krb5kdc]# enctypes=aes256-cts-hmac-sha1-96:normal,\ + > aes128-cts-hmac-sha1-96:normal,des3-hmac-sha1:normal,des-cbc-crc:normal + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q "cpw -e ${enctypes} -randkey \ + > -keepold krbtgt/ZONE.MIT.EDU" + Authenticating as principal root/admin@ZONE.MIT.EDU with password. + Key for "krbtgt/ZONE.MIT.EDU@ZONE.MIT.EDU" randomized. + +.. note:: + + The new ``krbtgt@REALM`` key should be propagated to replica KDCs + immediately so that TGTs issued by the primary KDC can be used to + issue service tickets on replica KDCs. Replica KDCs will refuse + requests using the new TGT kvno until the new krbtgt entry has + been propagated to them. + +It is necessary to explicitly specify the enctypes for the new database +entry, since **supported_enctypes** has not been changed. Leaving +**supported_enctypes** unchanged makes a potential rollback operation +easier, since all new keys of new enctypes are the result of explicit +administrator action and can be easily enumerated. +Upgrading the krbtgt key should have minimal user-visible disruption other +than that described in the note above, since only clients which list the +new enctypes as supported will use them, per the procedure +in :ref:`session_key_selection`. +Once the krbtgt key is updated, the session and ticket keys for user +TGTs will be strong keys, but subsequent requests +for service tickets will still get DES keys until the service principals +have new keys generated. Application service +remains uninterrupted due to the key-selection procedure on the KDC. + +After the change, the database entry is now: + +:: + + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'getprinc krbtgt/ZONE.MIT.EDU' + [...] + Number of keys: 5 + Key: vno 2, aes256-cts-hmac-sha1-96 + Key: vno 2, aes128-cts-hmac-sha1-96 + Key: vno 2, des3-cbc-sha1 + Key: vno 2, des-cbc-crc + Key: vno 1, des-cbc-crc:v4 + [...] + +Since the expected disruptions from rekeying the krbtgt principal are +minor, after a short testing period, it is +appropriate to rekey the other high-value principals, ``kadmin/admin@REALM`` +and ``kadmin/changepw@REALM``. These are the service principals used for +changing user passwords and updating application keytabs. The kadmin +and password-changing services are regular kerberized services, so the +session-key-selection algorithm described in :ref:`session_key_selection` +applies. It is particularly important to have strong session keys for +these services, since user passwords and new long-term keys are conveyed +over the encrypted channel. + +:: + + [root@casio krb5kdc]# enctypes=aes256-cts-hmac-sha1-96:normal,\ + > aes128-cts-hmac-sha1-96:normal,des3-hmac-sha1:normal + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q "cpw -e ${enctypes} -randkey \ + > kadmin/admin" + Authenticating as principal root/admin@ZONE.MIT.EDU with password. + Key for "kadmin/admin@ZONE.MIT.EDU" randomized. + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q "cpw -e ${enctypes} -randkey \ + > kadmin/changepw" + Authenticating as principal root/admin@ZONE.MIT.EDU with password. + Key for "kadmin/changepw@ZONE.MIT.EDU" randomized. + +It is not necessary to retain a single-DES key for these services, since +password changes are not part of normal daily workflow, and disruption +from a client failure is likely to be minimal. Furthermore, if a kerberos +client experiences failure changing a user password or keytab key, +this indicates that that client will become inoperative once services +are rekeyed to non-DES enctypes. Such problems can be detected early +at this stage, giving more time for corrective action. + +Adding strong keys to application servers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Before switching the default enctypes for new keys over to strong enctypes, +it may be desired to test upgrading a handful of services with the +new configuration before flipping the switch for the defaults. This +still requires using the **-e** argument in :ref:`kadmin(1)` to get non-default +enctypes: + +:: + + [root@casio krb5kdc]# enctypes=aes256-cts-hmac-sha1-96:normal,\ + > aes128-cts-hmac-sha1-96:normal,des3-cbc-sha1:normal,des-cbc-crc:normal + [root@casio krb5kdc]# kadmin -r ZONE.MIT.EDU -p zephyr/zephyr@ZONE.MIT.EDU -k -t \ + > /etc/zephyr/krb5.keytab -q "ktadd -e ${enctypes} \ + > -k /etc/zephyr/krb5.keytab zephyr/zephyr@ZONE.MIT.EDU" + Authenticating as principal zephyr/zephyr@ZONE.MIT.EDU with keytab /etc/zephyr/krb5.keytab. + Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 4, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/zephyr/krb5.keytab. + Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 4, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/zephyr/krb5.keytab. + Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 4, encryption type des3-cbc-sha1 added to keytab WRFILE:/etc/zephyr/krb5.keytab. + Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 4, encryption type des-cbc-crc added to keytab WRFILE:/etc/zephyr/krb5.keytab. + +Be sure to remove the old keys from the application keytab, per best +practice. + +:: + + [root@casio krb5kdc]# k5srvutil -f /etc/zephyr/krb5.keytab delold + Authenticating as principal zephyr/zephyr@ZONE.MIT.EDU with keytab /etc/zephyr/krb5.keytab. + Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 3 removed from keytab WRFILE:/etc/zephyr/krb5.keytab. + +Adding strong keys by default +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once the high-visibility services have been rekeyed, it is probably +appropriate to change :ref:`kdc.conf(5)` to generate keys with the new +encryption types by default. This enables server administrators to generate +new enctypes with the **change** subcommand of :ref:`k5srvutil(1)`, +and causes user password +changes to add new encryption types for their entries. It will probably +be necessary to implement administrative controls to cause all user +principal keys to be updated in a reasonable period of time, whether +by forcing password changes or a password synchronization service that +has access to the current password and can add the new keys. + +:: + + [realms] + ZONE.MIT.EDU = { + supported_enctypes = aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des3-hmac-sha1:normal des-cbc-crc:normal + +.. note:: + + The krb5kdc process must be restarted for these changes to take effect. + +At this point, all service administrators can update their services and the +servers behind them to take advantage of strong cryptography. +If necessary, the server's krb5 installation should be configured and/or +upgraded to a version supporting non-DES keys. See :ref:`enctypes` for +krb5 version and configuration settings. +Only when the service is configured to accept non-DES keys should +the key version number be incremented and new keys generated +(``k5srvutil change && k5srvutil delold``). + +:: + + root@dr-willy:~# k5srvutil change + Authenticating as principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with keytab /etc/krb5.keytab. + Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 3, encryption type AES-256 CTS mode with 96-bit SHA-1 HMAC added to keytab WRFILE:/etc/krb5.keytab. + Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 3, encryption type AES-128 CTS mode with 96-bit SHA-1 HMAC added to keytab WRFILE:/etc/krb5.keytab. + Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 3, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/etc/krb5.keytab. + Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 3, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/etc/krb5.keytab. + root@dr-willy:~# klist -e -k -t /etc/krb5.keytab + Keytab name: WRFILE:/etc/krb5.keytab + KVNO Timestamp Principal + ---- ----------------- -------------------------------------------------------- + 2 10/10/12 17:03:59 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (DES cbc mode with CRC-32) + 3 12/12/12 15:31:19 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (AES-256 CTS mode with 96-bit SHA-1 HMAC) + 3 12/12/12 15:31:19 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (AES-128 CTS mode with 96-bit SHA-1 HMAC) + 3 12/12/12 15:31:19 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (Triple DES cbc mode with HMAC/sha1) + 3 12/12/12 15:31:19 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (DES cbc mode with CRC-32) + root@dr-willy:~# k5srvutil delold + Authenticating as principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with keytab /etc/krb5.keytab. + Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 2 removed from keytab WRFILE:/etc/krb5.keytab. + +When a single service principal is shared by multiple backend servers in +a load-balanced environment, it may be necessary to schedule downtime +or adjust the population in the load-balanced pool in order to propagate +the updated keytab to all hosts in the pool with minimal service interruption. + +Removing DES keys from usage +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This situation remains something of a testing or transitory state, +as new DES keys are still being generated, and will be used if requested +by a client. To make more progress removing DES from the realm, the KDC +should be configured to not generate such keys by default. + +.. note:: + + An attacker posing as a client can implement a brute force attack against + a DES key for any principal, if that key is in the current (highest-kvno) + key list. This attack is only possible if **allow_weak_crypto = true** + is enabled on the KDC. Setting the **+requires_preauth** flag on a + principal forces this attack to be an online attack, much slower than + the offline attack otherwise available to the attacker. However, setting + this flag on a service principal is not always advisable; see the entry in + :ref:`add_principal` for details. + +The following KDC configuration will not generate DES keys by default: + +:: + + [realms] + ZONE.MIT.EDU = { + supported_enctypes = aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des3-hmac-sha1:normal + +.. note:: + + As before, the KDC process must be restarted for this change to take + effect. It is best practice to update kdc.conf on all KDCs, not just the + primary, to avoid unpleasant surprises should the primary fail and a + replica need to be promoted. + +It is now appropriate to remove the legacy single-DES key from the +``krbtgt/REALM`` entry: + +:: + + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q "cpw -randkey -keepold \ + > krbtgt/ZONE.MIT.EDU" + Authenticating as principal host/admin@ATHENA.MIT.EDU with password. + Key for "krbtgt/ZONE.MIT.EDU@ZONE.MIT.EDU" randomized. + +After the maximum ticket lifetime has passed, the old database entry +should be removed. + +:: + + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'purgekeys krbtgt/ZONE.MIT.EDU' + Authenticating as principal root/admin@ZONE.MIT.EDU with password. + Old keys for principal "krbtgt/ZONE.MIT.EDU@ZONE.MIT.EDU" purged. + +After the KDC is restarted with the new **supported_enctypes**, +all user password changes and application keytab updates will not +generate DES keys by default. + +:: + + contents-vnder-pressvre:~> kpasswd zonetest@ZONE.MIT.EDU + Password for zonetest@ZONE.MIT.EDU: [enter old password] + Enter new password: [enter new password] + Enter it again: [enter new password] + Password changed. + contents-vnder-pressvre:~> kadmin -r ZONE.MIT.EDU -q 'getprinc zonetest' + [...] + Number of keys: 3 + Key: vno 9, aes256-cts-hmac-sha1-96 + Key: vno 9, aes128-cts-hmac-sha1-96 + Key: vno 9, des3-cbc-sha1 + [...] + + [kaduk@glossolalia ~]$ kadmin -p kaduk@ZONE.MIT.EDU -r ZONE.MIT.EDU -k \ + > -t kaduk-zone.keytab -q 'ktadd -k kaduk-zone.keytab kaduk@ZONE.MIT.EDU' + Authenticating as principal kaduk@ZONE.MIT.EDU with keytab kaduk-zone.keytab. + Entry for principal kaduk@ZONE.MIT.EDU with kvno 3, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:kaduk-zone.keytab. + Entry for principal kaduk@ZONE.MIT.EDU with kvno 3, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:kaduk-zone.keytab. + Entry for principal kaduk@ZONE.MIT.EDU with kvno 3, encryption type des3-cbc-sha1 added to keytab WRFILE:kaduk-zone.keytab. + +Once all principals have been re-keyed, DES support can be disabled on the +KDC (**allow_weak_crypto = false**), and client machines can remove +**allow_weak_crypto = true** from their :ref:`krb5.conf(5)` configuration +files, completing the migration. **allow_weak_crypto** takes precedence over +all places where DES enctypes could be explicitly configured. DES keys will +not be used, even if they are present, when **allow_weak_crypto = false**. + +Support for legacy services +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If there remain legacy services which do not support non-DES enctypes +(such as older versions of AFS), **allow_weak_crypto** must remain +enabled on the KDC. Client machines need not have this setting, +though---applications which require DES can use API calls to allow +weak crypto on a per-request basis, overriding the system krb5.conf. +However, having **allow_weak_crypto** set on the KDC means that any +principals which have a DES key in the database could still use those +keys. To minimize the use of DES in the realm and restrict it to just +legacy services which require DES, it is necessary to remove all other +DES keys. The realm has been configured such that at password and +keytab change, no DES keys will be generated by default. The task +then reduces to requiring user password changes and having server +administrators update their service keytabs. Administrative outreach +will be necessary, and if the desire to eliminate DES is sufficiently +strong, the KDC administrators may choose to randkey any principals +which have not been rekeyed after some timeout period, forcing the +user to contact the helpdesk for access. + +The Database Master Key +----------------------- + +This procedure does not alter ``K/M@REALM``, the key used to encrypt key +material in the Kerberos database. (This is the key stored in the stash file +on the KDC if stash files are used.) However, the security risk of +a single-DES key for ``K/M`` is minimal, given that access to material +encrypted in ``K/M`` (the Kerberos database) is generally tightly controlled. +If an attacker can gain access to the encrypted database, they likely +have access to the stash file as well, rendering the weak cryptography +broken by non-cryptographic means. As such, upgrading ``K/M`` to a stronger +encryption type is unlikely to be a high-priority task. + +Is is possible to upgrade the master key used for the database, if +desired. Using :ref:`kdb5_util(8)`'s **add_mkey**, **use_mkey**, and +**update_princ_encryption** commands, a new master key can be added +and activated for use on new key material, and the existing entries +converted to the new master key. diff --git a/krb5-1.21.3/doc/admin/appl_servers.rst b/krb5-1.21.3/doc/admin/appl_servers.rst new file mode 100644 index 00000000..e9d16e87 --- /dev/null +++ b/krb5-1.21.3/doc/admin/appl_servers.rst @@ -0,0 +1,171 @@ +Application servers +=================== + +If you need to install the Kerberos V5 programs on an application +server, please refer to the Kerberos V5 Installation Guide. Once you +have installed the software, you need to add that host to the Kerberos +database (see :ref:`principals`), and generate a keytab for that host, +that contains the host's key. You also need to make sure the host's +clock is within your maximum clock skew of the KDCs. + + +Keytabs +------- + +A keytab is a host's copy of its own keylist, which is analogous to a +user's password. An application server that needs to authenticate +itself to the KDC has to have a keytab that contains its own principal +and key. Just as it is important for users to protect their +passwords, it is equally important for hosts to protect their keytabs. +You should always store keytab files on local disk, and make them +readable only by root, and you should never send a keytab file over a +network in the clear. Ideally, you should run the :ref:`kadmin(1)` +command to extract a keytab on the host on which the keytab is to +reside. + + +.. _add_princ_kt: + +Adding principals to keytabs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To generate a keytab, or to add a principal to an existing keytab, use +the **ktadd** command from kadmin. Here is a sample session, using +configuration files that enable only AES encryption:: + + kadmin: ktadd host/daffodil.mit.edu@ATHENA.MIT.EDU + Entry for principal host/daffodil.mit.edu with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab + Entry for principal host/daffodil.mit.edu with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab + + +Removing principals from keytabs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To remove a principal from an existing keytab, use the kadmin +**ktremove** command:: + + kadmin: ktremove host/daffodil.mit.edu@ATHENA.MIT.EDU + Entry for principal host/daffodil.mit.edu with kvno 2 removed from keytab FILE:/etc/krb5.keytab. + Entry for principal host/daffodil.mit.edu with kvno 2 removed from keytab FILE:/etc/krb5.keytab. + + +Using a keytab to acquire client credentials +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +While keytabs are ordinarily used to accept credentials from clients, +they can also be used to acquire initial credentials, allowing one +service to authenticate to another. + +To manually obtain credentials using a keytab, use the :ref:`kinit(1)` +**-k** option, together with the **-t** option if the keytab is not in +the default location. + +Beginning with release 1.11, GSSAPI applications can be configured to +automatically obtain initial credentials from a keytab as needed. The +recommended configuration is as follows: + +#. Create a keytab containing a single entry for the desired client + identity. + +#. Place the keytab in a location readable by the service, and set the + **KRB5_CLIENT_KTNAME** environment variable to its filename. + Alternatively, use the **default_client_keytab_name** profile + variable in :ref:`libdefaults`, or use the default location of + |ckeytab|. + +#. Set **KRB5CCNAME** to a filename writable by the service, which + will not be used for any other purpose. Do not manually obtain + credentials at this location. (Another credential cache type + besides **FILE** can be used if desired, as long the cache will not + conflict with another use. A **MEMORY** cache can be used if the + service runs as a long-lived process. See :ref:`ccache_definition` + for details.) + +#. Start the service. When it authenticates using GSSAPI, it will + automatically obtain credentials from the client keytab into the + specified credential cache, and refresh them before they expire. + + +Clock Skew +---------- + +A Kerberos application server host must keep its clock synchronized or +it will reject authentication requests from clients. Modern operating +systems typically provide a facility to maintain the correct time; +make sure it is enabled. This is especially important on virtual +machines, where clocks tend to drift more rapidly than normal machine +clocks. + +The default allowable clock skew is controlled by the **clockskew** +variable in :ref:`libdefaults`. + + +Getting DNS information correct +------------------------------- + +Several aspects of Kerberos rely on name service. When a hostname is +used to name a service, clients may canonicalize the hostname using +forward and possibly reverse name resolution. The result of this +canonicalization must match the principal entry in the host's keytab, +or authentication will fail. To work with all client canonicalization +configurations, each host's canonical name must be the fully-qualified +host name (including the domain), and each host's IP address must +reverse-resolve to the canonical name. + +Configuration of hostnames varies by operating system. On the +application server itself, canonicalization will typically use the +``/etc/hosts`` file rather than the DNS. Ensure that the line for the +server's hostname is in the following form:: + + IP address fully-qualified hostname aliases + +Here is a sample ``/etc/hosts`` file:: + + # this is a comment + 127.0.0.1 localhost localhost.mit.edu + 10.0.0.6 daffodil.mit.edu daffodil trillium wake-robin + +The output of ``klist -k`` for this example host should look like:: + + viola# klist -k + Keytab name: /etc/krb5.keytab + KVNO Principal + ---- ------------------------------------------------------------ + 2 host/daffodil.mit.edu@ATHENA.MIT.EDU + +If you were to ssh to this host with a fresh credentials cache (ticket +file), and then :ref:`klist(1)`, the output should list a service +principal of ``host/daffodil.mit.edu@ATHENA.MIT.EDU``. + + +.. _conf_firewall: + +Configuring your firewall to work with Kerberos V5 +-------------------------------------------------- + +If you need off-site users to be able to get Kerberos tickets in your +realm, they must be able to get to your KDC. This requires either +that you have a replica KDC outside your firewall, or that you +configure your firewall to allow UDP requests into at least one of +your KDCs, on whichever port the KDC is running. (The default is port +88; other ports may be specified in the KDC's :ref:`kdc.conf(5)` +file.) Similarly, if you need off-site users to be able to change +their passwords in your realm, they must be able to get to your +Kerberos admin server on the kpasswd port (which defaults to 464). If +you need off-site users to be able to administer your Kerberos realm, +they must be able to get to your Kerberos admin server on the +administrative port (which defaults to 749). + +If your on-site users inside your firewall will need to get to KDCs in +other realms, you will also need to configure your firewall to allow +outgoing TCP and UDP requests to port 88, and to port 464 to allow +password changes. If your on-site users inside your firewall will +need to get to Kerberos admin servers in other realms, you will also +need to allow outgoing TCP and UDP requests to port 749. + +If any of your KDCs are outside your firewall, you will need to allow +kprop requests to get through to the remote KDC. :ref:`kprop(8)` uses +the ``krb5_prop`` service on port 754 (tcp). + +The book *UNIX System Security*, by David Curry, is a good starting +point for learning to configure firewalls. diff --git a/krb5-1.21.3/doc/admin/auth_indicator.rst b/krb5-1.21.3/doc/admin/auth_indicator.rst new file mode 100644 index 00000000..b13905e9 --- /dev/null +++ b/krb5-1.21.3/doc/admin/auth_indicator.rst @@ -0,0 +1,57 @@ +.. _auth_indicator: + +Authentication indicators +========================= + +As of release 1.14, the KDC can be configured to annotate tickets if +the client authenticated using a stronger preauthentication mechanism +such as :ref:`PKINIT ` or :ref:`OTP `. These +annotations are called "authentication indicators." Service +principals can be configured to require particular authentication +indicators in order to authenticate to that service. An +authentication indicator value can be any string chosen by the KDC +administrator; there are no pre-set values. + +To use authentication indicators with PKINIT or OTP, first configure +the KDC to include an indicator when that preauthentication mechanism +is used. For PKINIT, use the **pkinit_indicator** variable in +:ref:`kdc.conf(5)`. For OTP, use the **indicator** variable in the +token type definition, or specify the indicators in the **otp** user +string as described in :ref:`otp_preauth`. + +To require an indicator to be present in order to authenticate to a +service principal, set the **require_auth** string attribute on the +principal to the indicator value to be required. If you wish to allow +one of several indicators to be accepted, you can specify multiple +indicator values separated by spaces. + +For example, a realm could be configured to set the authentication +indicator value "strong" when PKINIT is used to authenticate, using a +setting in the :ref:`kdc_realms` subsection:: + + pkinit_indicator = strong + +A service principal could be configured to require the "strong" +authentication indicator value:: + + $ kadmin setstr host/high.value.server require_auth strong + Password for user/admin@KRBTEST.COM: + +A user who authenticates with PKINIT would be able to obtain a ticket +for the service principal:: + + $ kinit -X X509_user_identity=FILE:/my/cert.pem,/my/key.pem user + $ kvno host/high.value.server + host/high.value.server@KRBTEST.COM: kvno = 1 + +but a user who authenticates with a password would not:: + + $ kinit user + Password for user@KRBTEST.COM: + $ kvno host/high.value.server + kvno: KDC policy rejects request while getting credentials for + host/high.value.server@KRBTEST.COM + +GSSAPI server applications can inspect authentication indicators +through the :ref:`auth-indicators ` name +attribute. diff --git a/krb5-1.21.3/doc/admin/backup_host.rst b/krb5-1.21.3/doc/admin/backup_host.rst new file mode 100644 index 00000000..8914551c --- /dev/null +++ b/krb5-1.21.3/doc/admin/backup_host.rst @@ -0,0 +1,34 @@ +Backups of secure hosts +======================= + +When you back up a secure host, you should exclude the host's keytab +file from the backup. If someone obtained a copy of the keytab from a +backup, that person could make any host masquerade as the host whose +keytab was compromised. In many configurations, knowledge of the +host's keytab also allows root access to the host. This could be +particularly dangerous if the compromised keytab was from one of your +KDCs. If the machine has a disk crash and the keytab file is lost, it +is easy to generate another keytab file. (See :ref:`add_princ_kt`.) +If you are unable to exclude particular files from backups, you should +ensure that the backups are kept as secure as the host's root +password. + + +Backing up the Kerberos database +-------------------------------- + +As with any file, it is possible that your Kerberos database could +become corrupted. If this happens on one of the replica KDCs, you +might never notice, since the next automatic propagation of the +database would install a fresh copy. However, if it happens to the +primary KDC, the corrupted database would be propagated to all of the +replicas during the next propagation. For this reason, MIT recommends +that you back up your Kerberos database regularly. Because the primary +KDC is continuously dumping the database to a file in order to +propagate it to the replica KDCs, it is a simple matter to have a cron +job periodically copy the dump file to a secure machine elsewhere on +your network. (Of course, it is important to make the host where +these backups are stored as secure as your KDCs, and to encrypt its +transmission across your network.) Then if your database becomes +corrupted, you can load the most recent dump onto the primary KDC. +(See :ref:`restore_from_dump`.) diff --git a/krb5-1.21.3/doc/admin/conf_files/index.rst b/krb5-1.21.3/doc/admin/conf_files/index.rst new file mode 100644 index 00000000..a04836ac --- /dev/null +++ b/krb5-1.21.3/doc/admin/conf_files/index.rst @@ -0,0 +1,20 @@ +Configuration Files +=================== + +Kerberos uses configuration files to allow administrators to specify +settings on a per-machine basis. :ref:`krb5.conf(5)` applies to all +applications using the Kerboros library, on clients and servers. +For KDC-specific applications, additional settings can be specified in +:ref:`kdc.conf(5)`; the two files are merged into a configuration profile +used by applications accessing the KDC database directly. :ref:`kadm5.acl(5)` +is also only used on the KDC, it controls permissions for modifying the +KDC database. + +Contents +-------- +.. toctree:: + :maxdepth: 1 + + krb5_conf + kdc_conf + kadm5_acl diff --git a/krb5-1.21.3/doc/admin/conf_files/kadm5_acl.rst b/krb5-1.21.3/doc/admin/conf_files/kadm5_acl.rst new file mode 100644 index 00000000..290bf0e0 --- /dev/null +++ b/krb5-1.21.3/doc/admin/conf_files/kadm5_acl.rst @@ -0,0 +1,163 @@ +.. _kadm5.acl(5): + +kadm5.acl +========= + +DESCRIPTION +----------- + +The Kerberos :ref:`kadmind(8)` daemon uses an Access Control List +(ACL) file to manage access rights to the Kerberos database. +For operations that affect principals, the ACL file also controls +which principals can operate on which other principals. + +The default location of the Kerberos ACL file is +|kdcdir|\ ``/kadm5.acl`` unless this is overridden by the *acl_file* +variable in :ref:`kdc.conf(5)`. + +SYNTAX +------ + +Empty lines and lines starting with the sharp sign (``#``) are +ignored. Lines containing ACL entries have the format:: + + principal permissions [target_principal [restrictions] ] + +.. note:: + + Line order in the ACL file is important. The first matching entry + will control access for an actor principal on a target principal. + +*principal* + (Partially or fully qualified Kerberos principal name.) Specifies + the principal whose permissions are to be set. + + Each component of the name may be wildcarded using the ``*`` + character. + +*permissions* + Specifies what operations may or may not be performed by a + *principal* matching a particular entry. This is a string of one or + more of the following list of characters or their upper-case + counterparts. If the character is *upper-case*, then the operation + is disallowed. If the character is *lower-case*, then the operation + is permitted. + + == ====================================================== + a [Dis]allows the addition of principals or policies + c [Dis]allows the changing of passwords for principals + d [Dis]allows the deletion of principals or policies + e [Dis]allows the extraction of principal keys + i [Dis]allows inquiries about principals or policies + l [Dis]allows the listing of all principals or policies + m [Dis]allows the modification of principals or policies + p [Dis]allows the propagation of the principal database (used in :ref:`incr_db_prop`) + s [Dis]allows the explicit setting of the key for a principal + x Short for admcilsp. All privileges (except ``e``) + \* Same as x. + == ====================================================== + +.. note:: + + The ``extract`` privilege is not included in the wildcard + privilege; it must be explicitly assigned. This privilege + allows the user to extract keys from the database, and must be + handled with great care to avoid disclosure of important keys + like those of the kadmin/* or krbtgt/* principals. The + **lockdown_keys** principal attribute can be used to prevent + key extraction from specific principals regardless of the + granted privilege. + +*target_principal* + (Optional. Partially or fully qualified Kerberos principal name.) + Specifies the principal on which *permissions* may be applied. + Each component of the name may be wildcarded using the ``*`` + character. + + *target_principal* can also include back-references to *principal*, + in which ``*number`` matches the corresponding wildcard in + *principal*. + +*restrictions* + (Optional) A string of flags. Allowed restrictions are: + + {+\|-}\ *flagname* + flag is forced to the indicated value. The permissible flags + are the same as those for the **default_principal_flags** + variable in :ref:`kdc.conf(5)`. + + *-clearpolicy* + policy is forced to be empty. + + *-policy pol* + policy is forced to be *pol*. + + -{*expire, pwexpire, maxlife, maxrenewlife*} *time* + (:ref:`getdate` string) associated value will be forced to + MIN(*time*, requested value). + + The above flags act as restrictions on any add or modify operation + which is allowed due to that ACL line. + +.. warning:: + + If the kadmind ACL file is modified, the kadmind daemon needs to be + restarted for changes to take effect. + +EXAMPLE +------- + +Here is an example of a kadm5.acl file:: + + */admin@ATHENA.MIT.EDU * # line 1 + joeadmin@ATHENA.MIT.EDU ADMCIL # line 2 + joeadmin/*@ATHENA.MIT.EDU i */root@ATHENA.MIT.EDU # line 3 + */root@ATHENA.MIT.EDU ci *1@ATHENA.MIT.EDU # line 4 + */root@ATHENA.MIT.EDU l * # line 5 + sms@ATHENA.MIT.EDU x * -maxlife 9h -postdateable # line 6 + +(line 1) Any principal in the ``ATHENA.MIT.EDU`` realm with an +``admin`` instance has all administrative privileges except extracting +keys. + +(lines 1-3) The user ``joeadmin`` has all permissions except +extracting keys with his ``admin`` instance, +``joeadmin/admin@ATHENA.MIT.EDU`` (matches line 1). He has no +permissions at all with his null instance, ``joeadmin@ATHENA.MIT.EDU`` +(matches line 2). His ``root`` and other non-``admin``, non-null +instances (e.g., ``extra`` or ``dbadmin``) have inquire permissions +with any principal that has the instance ``root`` (matches line 3). + +(line 4) Any ``root`` principal in ``ATHENA.MIT.EDU`` can inquire +or change the password of their null instance, but not any other +null instance. (Here, ``*1`` denotes a back-reference to the +component matching the first wildcard in the actor principal.) + +(line 5) Any ``root`` principal in ``ATHENA.MIT.EDU`` can generate +the list of principals in the database, and the list of policies +in the database. This line is separate from line 4, because list +permission can only be granted globally, not to specific target +principals. + +(line 6) Finally, the Service Management System principal +``sms@ATHENA.MIT.EDU`` has all permissions except extracting keys, but +any principal that it creates or modifies will not be able to get +postdateable tickets or tickets with a life of longer than 9 hours. + +MODULE BEHAVIOR +--------------- + +The ACL file can coexist with other authorization modules in release +1.16 and later, as configured in the :ref:`kadm5_auth` section of +:ref:`krb5.conf(5)`. The ACL file will positively authorize +operations according to the rules above, but will never +authoritatively deny an operation, so other modules can authorize +operations in addition to those authorized by the ACL file. + +To operate without an ACL file, set the *acl_file* variable in +:ref:`kdc.conf(5)` to the empty string with ``acl_file = ""``. + +SEE ALSO +-------- + +:ref:`kdc.conf(5)`, :ref:`kadmind(8)` diff --git a/krb5-1.21.3/doc/admin/conf_files/kdc_conf.rst b/krb5-1.21.3/doc/admin/conf_files/kdc_conf.rst new file mode 100644 index 00000000..74a0a2ac --- /dev/null +++ b/krb5-1.21.3/doc/admin/conf_files/kdc_conf.rst @@ -0,0 +1,976 @@ +.. _kdc.conf(5): + +kdc.conf +======== + +The kdc.conf file supplements :ref:`krb5.conf(5)` for programs which +are typically only used on a KDC, such as the :ref:`krb5kdc(8)` and +:ref:`kadmind(8)` daemons and the :ref:`kdb5_util(8)` program. +Relations documented here may also be specified in krb5.conf; for the +KDC programs mentioned, krb5.conf and kdc.conf will be merged into a +single configuration profile. + +Normally, the kdc.conf file is found in the KDC state directory, +|kdcdir|. You can override the default location by setting the +environment variable **KRB5_KDC_PROFILE**. + +Please note that you need to restart the KDC daemon for any configuration +changes to take effect. + +Structure +--------- + +The kdc.conf file is set up in the same format as the +:ref:`krb5.conf(5)` file. + + +Sections +-------- + +The kdc.conf file may contain the following sections: + +==================== ================================================= +:ref:`kdcdefaults` Default values for KDC behavior +:ref:`kdc_realms` Realm-specific database configuration and settings +:ref:`dbdefaults` Default database settings +:ref:`dbmodules` Per-database settings +:ref:`logging` Controls how Kerberos daemons perform logging +==================== ================================================= + + +.. _kdcdefaults: + +[kdcdefaults] +~~~~~~~~~~~~~ + +Some relations in the [kdcdefaults] section specify default values for +realm variables, to be used if the [realms] subsection does not +contain a relation for the tag. See the :ref:`kdc_realms` section for +the definitions of these relations. + +* **host_based_services** +* **kdc_listen** +* **kdc_ports** +* **kdc_tcp_listen** +* **kdc_tcp_ports** +* **no_host_referral** +* **restrict_anonymous_to_tgt** + +The following [kdcdefaults] variables have no per-realm equivalent: + +**kdc_max_dgram_reply_size** + Specifies the maximum packet size that can be sent over UDP. The + default value is 4096 bytes. + +**kdc_tcp_listen_backlog** + (Integer.) Set the size of the listen queue length for the KDC + daemon. The value may be limited by OS settings. The default + value is 5. + +**spake_preauth_kdc_challenge** + (String.) Specifies the group for a SPAKE optimistic challenge. + See the **spake_preauth_groups** variable in :ref:`libdefaults` + for possible values. The default is not to issue an optimistic + challenge. (New in release 1.17.) + + +.. _kdc_realms: + +[realms] +~~~~~~~~ + +Each tag in the [realms] section is the name of a Kerberos realm. The +value of the tag is a subsection where the relations define KDC +parameters for that particular realm. The following example shows how +to define one parameter for the ATHENA.MIT.EDU realm:: + + [realms] + ATHENA.MIT.EDU = { + max_renewable_life = 7d 0h 0m 0s + } + +The following tags may be specified in a [realms] subsection: + +**acl_file** + (String.) Location of the access control list file that + :ref:`kadmind(8)` uses to determine which principals are allowed + which permissions on the Kerberos database. To operate without an + ACL file, set this relation to the empty string with ``acl_file = + ""``. The default value is |kdcdir|\ ``/kadm5.acl``. For more + information on Kerberos ACL file see :ref:`kadm5.acl(5)`. + +**database_module** + (String.) This relation indicates the name of the configuration + section under :ref:`dbmodules` for database-specific parameters + used by the loadable database library. The default value is the + realm name. If this configuration section does not exist, default + values will be used for all database parameters. + +**database_name** + (String, deprecated.) This relation specifies the location of the + Kerberos database for this realm, if the DB2 module is being used + and the :ref:`dbmodules` configuration section does not specify a + database name. The default value is |kdcdir|\ ``/principal``. + +**default_principal_expiration** + (:ref:`abstime` string.) Specifies the default expiration date of + principals created in this realm. The default value is 0, which + means no expiration date. + +**default_principal_flags** + (Flag string.) Specifies the default attributes of principals + created in this realm. The format for this string is a + comma-separated list of flags, with '+' before each flag that + should be enabled and '-' before each flag that should be + disabled. The **postdateable**, **forwardable**, **tgt-based**, + **renewable**, **proxiable**, **dup-skey**, **allow-tickets**, and + **service** flags default to enabled. + + There are a number of possible flags: + + **allow-tickets** + Enabling this flag means that the KDC will issue tickets for + this principal. Disabling this flag essentially deactivates + the principal within this realm. + + **dup-skey** + Enabling this flag allows the KDC to issue user-to-user + service tickets for this principal. + + **forwardable** + Enabling this flag allows the principal to obtain forwardable + tickets. + + **hwauth** + If this flag is enabled, then the principal is required to + preauthenticate using a hardware device before receiving any + tickets. + + **no-auth-data-required** + Enabling this flag prevents PAC or AD-SIGNEDPATH data from + being added to service tickets for the principal. + + **ok-as-delegate** + If this flag is enabled, it hints the client that credentials + can and should be delegated when authenticating to the + service. + + **ok-to-auth-as-delegate** + Enabling this flag allows the principal to use S4USelf tickets. + + **postdateable** + Enabling this flag allows the principal to obtain postdateable + tickets. + + **preauth** + If this flag is enabled on a client principal, then that + principal is required to preauthenticate to the KDC before + receiving any tickets. On a service principal, enabling this + flag means that service tickets for this principal will only + be issued to clients with a TGT that has the preauthenticated + bit set. + + **proxiable** + Enabling this flag allows the principal to obtain proxy + tickets. + + **pwchange** + Enabling this flag forces a password change for this + principal. + + **pwservice** + If this flag is enabled, it marks this principal as a password + change service. This should only be used in special cases, + for example, if a user's password has expired, then the user + has to get tickets for that principal without going through + the normal password authentication in order to be able to + change the password. + + **renewable** + Enabling this flag allows the principal to obtain renewable + tickets. + + **service** + Enabling this flag allows the the KDC to issue service tickets + for this principal. In release 1.17 and later, user-to-user + service tickets are still allowed if the **dup-skey** flag is + set. + + **tgt-based** + Enabling this flag allows a principal to obtain tickets based + on a ticket-granting-ticket, rather than repeating the + authentication process that was used to obtain the TGT. + +**dict_file** + (String.) Location of the dictionary file containing strings that + are not allowed as passwords. The file should contain one string + per line, with no additional whitespace. If none is specified or + if there is no policy assigned to the principal, no dictionary + checks of passwords will be performed. + +**disable_pac** + (Boolean value.) If true, the KDC will not issue PACs for this + realm, and S4U2Self and S4U2Proxy operations will be disabled. + The default is false, which will permit the KDC to issue PACs. + New in release 1.20. + +**encrypted_challenge_indicator** + (String.) Specifies the authentication indicator value that the KDC + asserts into tickets obtained using FAST encrypted challenge + pre-authentication. New in 1.16. + +**host_based_services** + (Whitespace- or comma-separated list.) Lists services which will + get host-based referral processing even if the server principal is + not marked as host-based by the client. + +**iprop_enable** + (Boolean value.) Specifies whether incremental database + propagation is enabled. The default value is false. + +**iprop_ulogsize** + (Integer.) Specifies the maximum number of log entries to be + retained for incremental propagation. The default value is 1000. + Prior to release 1.11, the maximum value was 2500. New in release + 1.19. + +**iprop_master_ulogsize** + The name for **iprop_ulogsize** prior to release 1.19. Its value is + used as a fallback if **iprop_ulogsize** is not specified. + +**iprop_replica_poll** + (Delta time string.) Specifies how often the replica KDC polls + for new updates from the primary. The default value is ``2m`` + (that is, two minutes). New in release 1.17. + +**iprop_slave_poll** + (Delta time string.) The name for **iprop_replica_poll** prior to + release 1.17. Its value is used as a fallback if + **iprop_replica_poll** is not specified. + +**iprop_listen** + (Whitespace- or comma-separated list.) Specifies the iprop RPC + listening addresses and/or ports for the :ref:`kadmind(8)` daemon. + Each entry may be an interface address, a port number, or an + address and port number separated by a colon. If the address + contains colons, enclose it in square brackets. If no address is + specified, the wildcard address is used. If kadmind fails to bind + to any of the specified addresses, it will fail to start. The + default (when **iprop_enable** is true) is to bind to the wildcard + address at the port specified in **iprop_port**. New in release + 1.15. + +**iprop_port** + (Port number.) Specifies the port number to be used for + incremental propagation. When **iprop_enable** is true, this + relation is required in the replica KDC configuration file, and + this relation or **iprop_listen** is required in the primary + configuration file, as there is no default port number. Port + numbers specified in **iprop_listen** entries will override this + port number for the :ref:`kadmind(8)` daemon. + +**iprop_resync_timeout** + (Delta time string.) Specifies the amount of time to wait for a + full propagation to complete. This is optional in configuration + files, and is used by replica KDCs only. The default value is 5 + minutes (``5m``). New in release 1.11. + +**iprop_logfile** + (File name.) Specifies where the update log file for the realm + database is to be stored. The default is to use the + **database_name** entry from the realms section of the krb5 config + file, with ``.ulog`` appended. (NOTE: If **database_name** isn't + specified in the realms section, perhaps because the LDAP database + back end is being used, or the file name is specified in the + [dbmodules] section, then the hard-coded default for + **database_name** is used. Determination of the **iprop_logfile** + default value will not use values from the [dbmodules] section.) + +**kadmind_listen** + (Whitespace- or comma-separated list.) Specifies the kadmin RPC + listening addresses and/or ports for the :ref:`kadmind(8)` daemon. + Each entry may be an interface address, a port number, or an + address and port number separated by a colon. If the address + contains colons, enclose it in square brackets. If no address is + specified, the wildcard address is used. If kadmind fails to bind + to any of the specified addresses, it will fail to start. The + default is to bind to the wildcard address at the port specified + in **kadmind_port**, or the standard kadmin port (749). New in + release 1.15. + +**kadmind_port** + (Port number.) Specifies the port on which the :ref:`kadmind(8)` + daemon is to listen for this realm. Port numbers specified in + **kadmind_listen** entries will override this port number. The + assigned port for kadmind is 749, which is used by default. + +**key_stash_file** + (String.) Specifies the location where the master key has been + stored (via kdb5_util stash). The default is |kdcdir|\ + ``/.k5.REALM``, where *REALM* is the Kerberos realm. + +**kdc_listen** + (Whitespace- or comma-separated list.) Specifies the UDP + listening addresses and/or ports for the :ref:`krb5kdc(8)` daemon. + Each entry may be an interface address, a port number, or an + address and port number separated by a colon. If the address + contains colons, enclose it in square brackets. If no address is + specified, the wildcard address is used. If no port is specified, + the standard port (88) is used. If the KDC daemon fails to bind + to any of the specified addresses, it will fail to start. The + default is to bind to the wildcard address on the standard port. + New in release 1.15. + +**kdc_ports** + (Whitespace- or comma-separated list, deprecated.) Prior to + release 1.15, this relation lists the ports for the + :ref:`krb5kdc(8)` daemon to listen on for UDP requests. In + release 1.15 and later, it has the same meaning as **kdc_listen** + if that relation is not defined. + +**kdc_tcp_listen** + (Whitespace- or comma-separated list.) Specifies the TCP + listening addresses and/or ports for the :ref:`krb5kdc(8)` daemon. + Each entry may be an interface address, a port number, or an + address and port number separated by a colon. If the address + contains colons, enclose it in square brackets. If no address is + specified, the wildcard address is used. If no port is specified, + the standard port (88) is used. To disable listening on TCP, set + this relation to the empty string with ``kdc_tcp_listen = ""``. + If the KDC daemon fails to bind to any of the specified addresses, + it will fail to start. The default is to bind to the wildcard + address on the standard port. New in release 1.15. + +**kdc_tcp_ports** + (Whitespace- or comma-separated list, deprecated.) Prior to + release 1.15, this relation lists the ports for the + :ref:`krb5kdc(8)` daemon to listen on for UDP requests. In + release 1.15 and later, it has the same meaning as + **kdc_tcp_listen** if that relation is not defined. + +**kpasswd_listen** + (Comma-separated list.) Specifies the kpasswd listening addresses + and/or ports for the :ref:`kadmind(8)` daemon. Each entry may be + an interface address, a port number, or an address and port number + separated by a colon. If the address contains colons, enclose it + in square brackets. If no address is specified, the wildcard + address is used. If kadmind fails to bind to any of the specified + addresses, it will fail to start. The default is to bind to the + wildcard address at the port specified in **kpasswd_port**, or the + standard kpasswd port (464). New in release 1.15. + +**kpasswd_port** + (Port number.) Specifies the port on which the :ref:`kadmind(8)` + daemon is to listen for password change requests for this realm. + Port numbers specified in **kpasswd_listen** entries will override + this port number. The assigned port for password change requests + is 464, which is used by default. + +**master_key_name** + (String.) Specifies the name of the principal associated with the + master key. The default is ``K/M``. + +**master_key_type** + (Key type string.) Specifies the master key's key type. The + default value for this is |defmkey|. For a list of all possible + values, see :ref:`Encryption_types`. + +**max_life** + (:ref:`duration` string.) Specifies the maximum time period for + which a ticket may be valid in this realm. The default value is + 24 hours. + +**max_renewable_life** + (:ref:`duration` string.) Specifies the maximum time period + during which a valid ticket may be renewed in this realm. + The default value is 0. + +**no_host_referral** + (Whitespace- or comma-separated list.) Lists services to block + from getting host-based referral processing, even if the client + marks the server principal as host-based or the service is also + listed in **host_based_services**. ``no_host_referral = *`` will + disable referral processing altogether. + +**reject_bad_transit** + (Boolean value.) If set to true, the KDC will check the list of + transited realms for cross-realm tickets against the transit path + computed from the realm names and the capaths section of its + :ref:`krb5.conf(5)` file; if the path in the ticket to be issued + contains any realms not in the computed path, the ticket will not + be issued, and an error will be returned to the client instead. + If this value is set to false, such tickets will be issued + anyways, and it will be left up to the application server to + validate the realm transit path. + + If the disable-transited-check flag is set in the incoming + request, this check is not performed at all. Having the + **reject_bad_transit** option will cause such ticket requests to + be rejected always. + + This transit path checking and config file option currently apply + only to TGS requests. + + The default value is true. + +**restrict_anonymous_to_tgt** + (Boolean value.) If set to true, the KDC will reject ticket + requests from anonymous principals to service principals other + than the realm's ticket-granting service. This option allows + anonymous PKINIT to be enabled for use as FAST armor tickets + without allowing anonymous authentication to services. The + default value is false. New in release 1.9. + +**spake_preauth_indicator** + (String.) Specifies an authentication indicator value that the + KDC asserts into tickets obtained using SPAKE pre-authentication. + The default is not to add any indicators. This option may be + specified multiple times. New in release 1.17. + +**supported_enctypes** + (List of *key*:*salt* strings.) Specifies the default key/salt + combinations of principals for this realm. Any principals created + through :ref:`kadmin(1)` will have keys of these types. The + default value for this tag is |defkeysalts|. For lists of + possible values, see :ref:`Keysalt_lists`. + + +.. _dbdefaults: + +[dbdefaults] +~~~~~~~~~~~~ + +The [dbdefaults] section specifies default values for some database +parameters, to be used if the [dbmodules] subsection does not contain +a relation for the tag. See the :ref:`dbmodules` section for the +definitions of these relations. + +* **ldap_kerberos_container_dn** +* **ldap_kdc_dn** +* **ldap_kdc_sasl_authcid** +* **ldap_kdc_sasl_authzid** +* **ldap_kdc_sasl_mech** +* **ldap_kdc_sasl_realm** +* **ldap_kadmind_dn** +* **ldap_kadmind_sasl_authcid** +* **ldap_kadmind_sasl_authzid** +* **ldap_kadmind_sasl_mech** +* **ldap_kadmind_sasl_realm** +* **ldap_service_password_file** +* **ldap_conns_per_server** + + +.. _dbmodules: + +[dbmodules] +~~~~~~~~~~~ + +The [dbmodules] section contains parameters used by the KDC database +library and database modules. Each tag in the [dbmodules] section is +the name of a Kerberos realm or a section name specified by a realm's +**database_module** parameter. The following example shows how to +define one database parameter for the ATHENA.MIT.EDU realm:: + + [dbmodules] + ATHENA.MIT.EDU = { + disable_last_success = true + } + +The following tags may be specified in a [dbmodules] subsection: + +**database_name** + This DB2-specific tag indicates the location of the database in + the filesystem. The default is |kdcdir|\ ``/principal``. + +**db_library** + This tag indicates the name of the loadable database module. The + value should be ``db2`` for the DB2 module, ``klmdb`` for the LMDB + module, or ``kldap`` for the LDAP module. + +**disable_last_success** + If set to ``true``, suppresses KDC updates to the "Last successful + authentication" field of principal entries requiring + preauthentication. Setting this flag may improve performance. + (Principal entries which do not require preauthentication never + update the "Last successful authentication" field.). First + introduced in release 1.9. + +**disable_lockout** + If set to ``true``, suppresses KDC updates to the "Last failed + authentication" and "Failed password attempts" fields of principal + entries requiring preauthentication. Setting this flag may + improve performance, but also disables account lockout. First + introduced in release 1.9. + +**ldap_conns_per_server** + This LDAP-specific tag indicates the number of connections to be + maintained per LDAP server. + +**ldap_kdc_dn** and **ldap_kadmind_dn** + These LDAP-specific tags indicate the default DN for binding to + the LDAP server. The :ref:`krb5kdc(8)` daemon uses + **ldap_kdc_dn**, while the :ref:`kadmind(8)` daemon and other + administrative programs use **ldap_kadmind_dn**. The kadmind DN + must have the rights to read and write the Kerberos data in the + LDAP database. The KDC DN must have the same rights, unless + **disable_lockout** and **disable_last_success** are true, in + which case it only needs to have rights to read the Kerberos data. + These tags are ignored if a SASL mechanism is set with + **ldap_kdc_sasl_mech** or **ldap_kadmind_sasl_mech**. + +**ldap_kdc_sasl_mech** and **ldap_kadmind_sasl_mech** + These LDAP-specific tags specify the SASL mechanism (such as + ``EXTERNAL``) to use when binding to the LDAP server. New in + release 1.13. + +**ldap_kdc_sasl_authcid** and **ldap_kadmind_sasl_authcid** + These LDAP-specific tags specify the SASL authentication identity + to use when binding to the LDAP server. Not all SASL mechanisms + require an authentication identity. If the SASL mechanism + requires a secret (such as the password for ``DIGEST-MD5``), these + tags also determine the name within the + **ldap_service_password_file** where the secret is stashed. New + in release 1.13. + +**ldap_kdc_sasl_authzid** and **ldap_kadmind_sasl_authzid** + These LDAP-specific tags specify the SASL authorization identity + to use when binding to the LDAP server. In most circumstances + they do not need to be specified. New in release 1.13. + +**ldap_kdc_sasl_realm** and **ldap_kadmind_sasl_realm** + These LDAP-specific tags specify the SASL realm to use when + binding to the LDAP server. In most circumstances they do not + need to be set. New in release 1.13. + +**ldap_kerberos_container_dn** + This LDAP-specific tag indicates the DN of the container object + where the realm objects will be located. + +**ldap_servers** + This LDAP-specific tag indicates the list of LDAP servers that the + Kerberos servers can connect to. The list of LDAP servers is + whitespace-separated. The LDAP server is specified by a LDAP URI. + It is recommended to use ``ldapi:`` or ``ldaps:`` URLs to connect + to the LDAP server. + +**ldap_service_password_file** + This LDAP-specific tag indicates the file containing the stashed + passwords (created by ``kdb5_ldap_util stashsrvpw``) for the + **ldap_kdc_dn** and **ldap_kadmind_dn** objects, or for the + **ldap_kdc_sasl_authcid** or **ldap_kadmind_sasl_authcid** names + for SASL authentication. This file must be kept secure. + +**mapsize** + This LMDB-specific tag indicates the maximum size of the two + database environments in megabytes. The default value is 128. + Increase this value to address "Environment mapsize limit reached" + errors. New in release 1.17. + +**max_readers** + This LMDB-specific tag indicates the maximum number of concurrent + reading processes for the databases. The default value is 128. + New in release 1.17. + +**nosync** + This LMDB-specific tag can be set to improve the throughput of + kadmind and other administrative agents, at the expense of + durability (recent database changes may not survive a power outage + or other sudden reboot). It does not affect the throughput of the + KDC. The default value is false. New in release 1.17. + +**unlockiter** + If set to ``true``, this DB2-specific tag causes iteration + operations to release the database lock while processing each + principal. Setting this flag to ``true`` can prevent extended + blocking of KDC or kadmin operations when dumps of large databases + are in progress. First introduced in release 1.13. + +The following tag may be specified directly in the [dbmodules] +section to control where database modules are loaded from: + +**db_module_dir** + This tag controls where the plugin system looks for database + modules. The value should be an absolute path. + +.. _logging: + +[logging] +~~~~~~~~~ + +The [logging] section indicates how :ref:`krb5kdc(8)` and +:ref:`kadmind(8)` perform logging. It may contain the following +relations: + +**admin_server** + Specifies how :ref:`kadmind(8)` performs logging. + +**kdc** + Specifies how :ref:`krb5kdc(8)` performs logging. + +**default** + Specifies how either daemon performs logging in the absence of + relations specific to the daemon. + +**debug** + (Boolean value.) Specifies whether debugging messages are + included in log outputs other than SYSLOG. Debugging messages are + always included in the system log output because syslog performs + its own priority filtering. The default value is false. New in + release 1.15. + +Logging specifications may have the following forms: + +**FILE=**\ *filename* or **FILE:**\ *filename* + This value causes the daemon's logging messages to go to the + *filename*. If the ``=`` form is used, the file is overwritten. + If the ``:`` form is used, the file is appended to. + +**STDERR** + This value causes the daemon's logging messages to go to its + standard error stream. + +**CONSOLE** + This value causes the daemon's logging messages to go to the + console, if the system supports it. + +**DEVICE=**\ ** + This causes the daemon's logging messages to go to the specified + device. + +**SYSLOG**\ [\ **:**\ *severity*\ [\ **:**\ *facility*\ ]] + This causes the daemon's logging messages to go to the system log. + + For backward compatibility, a severity argument may be specified, + and must be specified in order to specify a facility. This + argument will be ignored. + + The facility argument specifies the facility under which the + messages are logged. This may be any of the following facilities + supported by the syslog(3) call minus the LOG\_ prefix: **KERN**, + **USER**, **MAIL**, **DAEMON**, **AUTH**, **LPR**, **NEWS**, + **UUCP**, **CRON**, and **LOCAL0** through **LOCAL7**. If no + facility is specified, the default is **AUTH**. + +In the following example, the logging messages from the KDC will go to +the console and to the system log under the facility LOG_DAEMON, and +the logging messages from the administrative server will be appended +to the file ``/var/adm/kadmin.log`` and sent to the device +``/dev/tty04``. :: + + [logging] + kdc = CONSOLE + kdc = SYSLOG:INFO:DAEMON + admin_server = FILE:/var/adm/kadmin.log + admin_server = DEVICE=/dev/tty04 + +If no logging specification is given, the default is to use syslog. +To disable logging entirely, specify ``default = DEVICE=/dev/null``. + + +.. _otp: + +[otp] +~~~~~ + +Each subsection of [otp] is the name of an OTP token type. The tags +within the subsection define the configuration required to forward a +One Time Password request to a RADIUS server. + +For each token type, the following tags may be specified: + +**server** + This is the server to send the RADIUS request to. It can be a + hostname with optional port, an ip address with optional port, or + a Unix domain socket address. The default is + |kdcdir|\ ``/.socket``. + +**secret** + This tag indicates a filename (which may be relative to |kdcdir|) + containing the secret used to encrypt the RADIUS packets. The + secret should appear in the first line of the file by itself; + leading and trailing whitespace on the line will be removed. If + the value of **server** is a Unix domain socket address, this tag + is optional, and an empty secret will be used if it is not + specified. Otherwise, this tag is required. + +**timeout** + An integer which specifies the time in seconds during which the + KDC should attempt to contact the RADIUS server. This tag is the + total time across all retries and should be less than the time + which an OTP value remains valid for. The default is 5 seconds. + +**retries** + This tag specifies the number of retries to make to the RADIUS + server. The default is 3 retries (4 tries). + +**strip_realm** + If this tag is ``true``, the principal without the realm will be + passed to the RADIUS server. Otherwise, the realm will be + included. The default value is ``true``. + +**indicator** + This tag specifies an authentication indicator to be included in + the ticket if this token type is used to authenticate. This + option may be specified multiple times. (New in release 1.14.) + +In the following example, requests are sent to a remote server via UDP:: + + [otp] + MyRemoteTokenType = { + server = radius.mydomain.com:1812 + secret = SEmfiajf42$ + timeout = 15 + retries = 5 + strip_realm = true + } + +An implicit default token type named ``DEFAULT`` is defined for when +the per-principal configuration does not specify a token type. Its +configuration is shown below. You may override this token type to +something applicable for your situation:: + + [otp] + DEFAULT = { + strip_realm = false + } + +PKINIT options +-------------- + +.. note:: + + The following are pkinit-specific options. These values may + be specified in [kdcdefaults] as global defaults, or within + a realm-specific subsection of [realms]. Also note that a + realm-specific value over-rides, does not add to, a generic + [kdcdefaults] specification. The search order is: + +1. realm-specific subsection of [realms]:: + + [realms] + EXAMPLE.COM = { + pkinit_anchors = FILE:/usr/local/example.com.crt + } + +2. generic value in the [kdcdefaults] section:: + + [kdcdefaults] + pkinit_anchors = DIR:/usr/local/generic_trusted_cas/ + +For information about the syntax of some of these options, see +:ref:`Specifying PKINIT identity information ` in +:ref:`krb5.conf(5)`. + +**pkinit_anchors** + Specifies the location of trusted anchor (root) certificates which + the KDC trusts to sign client certificates. This option is + required if pkinit is to be supported by the KDC. This option may + be specified multiple times. + +**pkinit_dh_min_bits** + Specifies the minimum number of bits the KDC is willing to accept + for a client's Diffie-Hellman key. The default is 2048. + +**pkinit_allow_upn** + Specifies that the KDC is willing to accept client certificates + with the Microsoft UserPrincipalName (UPN) Subject Alternative + Name (SAN). This means the KDC accepts the binding of the UPN in + the certificate to the Kerberos principal name. The default value + is false. + + Without this option, the KDC will only accept certificates with + the id-pkinit-san as defined in :rfc:`4556`. There is currently + no option to disable SAN checking in the KDC. + +**pkinit_eku_checking** + This option specifies what Extended Key Usage (EKU) values the KDC + is willing to accept in client certificates. The values + recognized in the kdc.conf file are: + + **kpClientAuth** + This is the default value and specifies that client + certificates must have the id-pkinit-KPClientAuth EKU as + defined in :rfc:`4556`. + + **scLogin** + If scLogin is specified, client certificates with the + Microsoft Smart Card Login EKU (id-ms-kp-sc-logon) will be + accepted. + + **none** + If none is specified, then client certificates will not be + checked to verify they have an acceptable EKU. The use of + this option is not recommended. + +**pkinit_identity** + Specifies the location of the KDC's X.509 identity information. + This option is required if pkinit is to be supported by the KDC. + +**pkinit_indicator** + Specifies an authentication indicator to include in the ticket if + pkinit is used to authenticate. This option may be specified + multiple times. (New in release 1.14.) + +**pkinit_pool** + Specifies the location of intermediate certificates which may be + used by the KDC to complete the trust chain between a client's + certificate and a trusted anchor. This option may be specified + multiple times. + +**pkinit_revoke** + Specifies the location of Certificate Revocation List (CRL) + information to be used by the KDC when verifying the validity of + client certificates. This option may be specified multiple times. + +**pkinit_require_crl_checking** + The default certificate verification process will always check the + available revocation information to see if a certificate has been + revoked. If a match is found for the certificate in a CRL, + verification fails. If the certificate being verified is not + listed in a CRL, or there is no CRL present for its issuing CA, + and **pkinit_require_crl_checking** is false, then verification + succeeds. + + However, if **pkinit_require_crl_checking** is true and there is + no CRL information available for the issuing CA, then verification + fails. + + **pkinit_require_crl_checking** should be set to true if the + policy is such that up-to-date CRLs must be present for every CA. + +**pkinit_require_freshness** + Specifies whether to require clients to include a freshness token + in PKINIT requests. The default value is false. (New in release + 1.17.) + +.. _Encryption_types: + +Encryption types +---------------- + +Any tag in the configuration files which requires a list of encryption +types can be set to some combination of the following strings. +Encryption types marked as "weak" and "deprecated" are available for +compatibility but not recommended for use. + +==================================================== ========================================================= +des3-cbc-raw Triple DES cbc mode raw (weak) +des3-cbc-sha1 des3-hmac-sha1 des3-cbc-sha1-kd Triple DES cbc mode with HMAC/sha1 (deprecated) +aes256-cts-hmac-sha1-96 aes256-cts aes256-sha1 AES-256 CTS mode with 96-bit SHA-1 HMAC +aes128-cts-hmac-sha1-96 aes128-cts aes128-sha1 AES-128 CTS mode with 96-bit SHA-1 HMAC +aes256-cts-hmac-sha384-192 aes256-sha2 AES-256 CTS mode with 192-bit SHA-384 HMAC +aes128-cts-hmac-sha256-128 aes128-sha2 AES-128 CTS mode with 128-bit SHA-256 HMAC +arcfour-hmac rc4-hmac arcfour-hmac-md5 RC4 with HMAC/MD5 (deprecated) +arcfour-hmac-exp rc4-hmac-exp arcfour-hmac-md5-exp Exportable RC4 with HMAC/MD5 (weak) +camellia256-cts-cmac camellia256-cts Camellia-256 CTS mode with CMAC +camellia128-cts-cmac camellia128-cts Camellia-128 CTS mode with CMAC +des3 The triple DES family: des3-cbc-sha1 +aes The AES family: aes256-cts-hmac-sha1-96, aes128-cts-hmac-sha1-96, aes256-cts-hmac-sha384-192, and aes128-cts-hmac-sha256-128 +rc4 The RC4 family: arcfour-hmac +camellia The Camellia family: camellia256-cts-cmac and camellia128-cts-cmac +==================================================== ========================================================= + +The string **DEFAULT** can be used to refer to the default set of +types for the variable in question. Types or families can be removed +from the current list by prefixing them with a minus sign ("-"). +Types or families can be prefixed with a plus sign ("+") for symmetry; +it has the same meaning as just listing the type or family. For +example, "``DEFAULT -rc4``" would be the default set of encryption +types with RC4 types removed, and "``des3 DEFAULT``" would be the +default set of encryption types with triple DES types moved to the +front. + +While **aes128-cts** and **aes256-cts** are supported for all Kerberos +operations, they are not supported by very old versions of our GSSAPI +implementation (krb5-1.3.1 and earlier). Services running versions of +krb5 without AES support must not be given keys of these encryption +types in the KDC database. + +The **aes128-sha2** and **aes256-sha2** encryption types are new in +release 1.15. Services running versions of krb5 without support for +these newer encryption types must not be given keys of these +encryption types in the KDC database. + + +.. _Keysalt_lists: + +Keysalt lists +------------- + +Kerberos keys for users are usually derived from passwords. Kerberos +commands and configuration parameters that affect generation of keys +take lists of enctype-salttype ("keysalt") pairs, known as *keysalt +lists*. Each keysalt pair is an enctype name followed by a salttype +name, in the format *enc*:*salt*. Individual keysalt list members are +separated by comma (",") characters or space characters. For example:: + + kadmin -e aes256-cts:normal,aes128-cts:normal + +would start up kadmin so that by default it would generate +password-derived keys for the **aes256-cts** and **aes128-cts** +encryption types, using a **normal** salt. + +To ensure that people who happen to pick the same password do not have +the same key, Kerberos 5 incorporates more information into the key +using something called a salt. The supported salt types are as +follows: + +================= ============================================ +normal default for Kerberos Version 5 +norealm same as the default, without using realm information +onlyrealm uses only realm information as the salt +special generate a random salt +================= ============================================ + + +Sample kdc.conf File +-------------------- + +Here's an example of a kdc.conf file:: + + [kdcdefaults] + kdc_listen = 88 + kdc_tcp_listen = 88 + [realms] + ATHENA.MIT.EDU = { + kadmind_port = 749 + max_life = 12h 0m 0s + max_renewable_life = 7d 0h 0m 0s + master_key_type = aes256-cts-hmac-sha1-96 + supported_enctypes = aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal + database_module = openldap_ldapconf + } + + [logging] + kdc = FILE:/usr/local/var/krb5kdc/kdc.log + admin_server = FILE:/usr/local/var/krb5kdc/kadmin.log + + [dbdefaults] + ldap_kerberos_container_dn = cn=krbcontainer,dc=mit,dc=edu + + [dbmodules] + openldap_ldapconf = { + db_library = kldap + disable_last_success = true + ldap_kdc_dn = "cn=krbadmin,dc=mit,dc=edu" + # this object needs to have read rights on + # the realm container and principal subtrees + ldap_kadmind_dn = "cn=krbadmin,dc=mit,dc=edu" + # this object needs to have read and write rights on + # the realm container and principal subtrees + ldap_service_password_file = /etc/kerberos/service.keyfile + ldap_servers = ldaps://kerberos.mit.edu + ldap_conns_per_server = 5 + } + + +FILES +------ + +|kdcdir|\ ``/kdc.conf`` + + +SEE ALSO +--------- + +:ref:`krb5.conf(5)`, :ref:`krb5kdc(8)`, :ref:`kadm5.acl(5)` diff --git a/krb5-1.21.3/doc/admin/conf_files/krb5_conf.rst b/krb5-1.21.3/doc/admin/conf_files/krb5_conf.rst new file mode 100644 index 00000000..ecdf9175 --- /dev/null +++ b/krb5-1.21.3/doc/admin/conf_files/krb5_conf.rst @@ -0,0 +1,1251 @@ +.. _krb5.conf(5): + +krb5.conf +========= + +The krb5.conf file contains Kerberos configuration information, +including the locations of KDCs and admin servers for the Kerberos +realms of interest, defaults for the current realm and for Kerberos +applications, and mappings of hostnames onto Kerberos realms. +Normally, you should install your krb5.conf file in the directory +``/etc``. You can override the default location by setting the +environment variable **KRB5_CONFIG**. Multiple colon-separated +filenames may be specified in **KRB5_CONFIG**; all files which are +present will be read. Starting in release 1.14, directory names can +also be specified in **KRB5_CONFIG**; all files within the directory +whose names consist solely of alphanumeric characters, dashes, or +underscores will be read. + + +Structure +--------- + +The krb5.conf file is set up in the style of a Windows INI file. +Lines beginning with '#' or ';' (possibly after initial whitespace) +are ignored as comments. Sections are headed by the section name, in +square brackets. Each section may contain zero or more relations, of +the form:: + + foo = bar + +or:: + + fubar = { + foo = bar + baz = quux + } + +Placing a '\*' after the closing bracket of a section name indicates +that the section is *final*, meaning that if the same section appears +within a later file specified in **KRB5_CONFIG**, it will be ignored. +A subsection can be marked as final by placing a '\*' after either the +tag name or the closing brace. + +The krb5.conf file can include other files using either of the +following directives at the beginning of a line:: + + include FILENAME + includedir DIRNAME + +*FILENAME* or *DIRNAME* should be an absolute path. The named file or +directory must exist and be readable. Including a directory includes +all files within the directory whose names consist solely of +alphanumeric characters, dashes, or underscores. Starting in release +1.15, files with names ending in ".conf" are also included, unless the +name begins with ".". Included profile files are syntactically +independent of their parents, so each included file must begin with a +section header. Starting in release 1.17, files are read in +alphanumeric order; in previous releases, they may be read in any +order. + +The krb5.conf file can specify that configuration should be obtained +from a loadable module, rather than the file itself, using the +following directive at the beginning of a line before any section +headers:: + + module MODULEPATH:RESIDUAL + +*MODULEPATH* may be relative to the library path of the krb5 +installation, or it may be an absolute path. *RESIDUAL* is provided +to the module at initialization time. If krb5.conf uses a module +directive, :ref:`kdc.conf(5)` should also use one if it exists. + + +Sections +-------- + +The krb5.conf file may contain the following sections: + +=================== ======================================================= +:ref:`libdefaults` Settings used by the Kerberos V5 library +:ref:`realms` Realm-specific contact information and settings +:ref:`domain_realm` Maps server hostnames to Kerberos realms +:ref:`capaths` Authentication paths for non-hierarchical cross-realm +:ref:`appdefaults` Settings used by some Kerberos V5 applications +:ref:`plugins` Controls plugin module registration +=================== ======================================================= + +Additionally, krb5.conf may include any of the relations described in +:ref:`kdc.conf(5)`, but it is not a recommended practice. + +.. _libdefaults: + +[libdefaults] +~~~~~~~~~~~~~ + +The libdefaults section may contain any of the following relations: + +**allow_des3** + Permit the KDC to issue tickets with des3-cbc-sha1 session keys. + In future releases, this flag will allow des3-cbc-sha1 to be used + at all. The default value for this tag is false. (Added in + release 1.21.) + +**allow_rc4** + Permit the KDC to issue tickets with arcfour-hmac session keys. + In future releases, this flag will allow arcfour-hmac to be used + at all. The default value for this tag is false. (Added in + release 1.21.) + +**allow_weak_crypto** + If this flag is set to false, then weak encryption types (as noted + in :ref:`Encryption_types` in :ref:`kdc.conf(5)`) will be filtered + out of the lists **default_tgs_enctypes**, + **default_tkt_enctypes**, and **permitted_enctypes**. The default + value for this tag is false. + +**canonicalize** + If this flag is set to true, initial ticket requests to the KDC + will request canonicalization of the client principal name, and + answers with different client principals than the requested + principal will be accepted. The default value is false. + +**ccache_type** + This parameter determines the format of credential cache types + created by :ref:`kinit(1)` or other programs. The default value + is 4, which represents the most current format. Smaller values + can be used for compatibility with very old implementations of + Kerberos which interact with credential caches on the same host. + +**clockskew** + Sets the maximum allowable amount of clockskew in seconds that the + library will tolerate before assuming that a Kerberos message is + invalid. The default value is 300 seconds, or five minutes. + + The clockskew setting is also used when evaluating ticket start + and expiration times. For example, tickets that have reached + their expiration time can still be used (and renewed if they are + renewable tickets) if they have been expired for a shorter + duration than the **clockskew** setting. + +**default_ccache_name** + This relation specifies the name of the default credential cache. + The default is |ccache|. This relation is subject to parameter + expansion (see below). New in release 1.11. + +**default_client_keytab_name** + This relation specifies the name of the default keytab for + obtaining client credentials. The default is |ckeytab|. This + relation is subject to parameter expansion (see below). + New in release 1.11. + +**default_keytab_name** + This relation specifies the default keytab name to be used by + application servers such as sshd. The default is |keytab|. This + relation is subject to parameter expansion (see below). + +**default_rcache_name** + This relation specifies the name of the default replay cache. + The default is ``dfl:``. This relation is subject to parameter + expansion (see below). New in release 1.18. + +**default_realm** + Identifies the default Kerberos realm for the client. Set its + value to your Kerberos realm. If this value is not set, then a + realm must be specified with every Kerberos principal when + invoking programs such as :ref:`kinit(1)`. + +**default_tgs_enctypes** + Identifies the supported list of session key encryption types that + the client should request when making a TGS-REQ, in order of + preference from highest to lowest. The list may be delimited with + commas or whitespace. See :ref:`Encryption_types` in + :ref:`kdc.conf(5)` for a list of the accepted values for this tag. + Starting in release 1.18, the default value is the value of + **permitted_enctypes**. For previous releases or if + **permitted_enctypes** is not set, the default value is + |defetypes|. + + Do not set this unless required for specific backward + compatibility purposes; stale values of this setting can prevent + clients from taking advantage of new stronger enctypes when the + libraries are upgraded. + +**default_tkt_enctypes** + Identifies the supported list of session key encryption types that + the client should request when making an AS-REQ, in order of + preference from highest to lowest. The format is the same as for + default_tgs_enctypes. Starting in release 1.18, the default + value is the value of **permitted_enctypes**. For previous + releases or if **permitted_enctypes** is not set, the default + value is |defetypes|. + + Do not set this unless required for specific backward + compatibility purposes; stale values of this setting can prevent + clients from taking advantage of new stronger enctypes when the + libraries are upgraded. + +**dns_canonicalize_hostname** + Indicate whether name lookups will be used to canonicalize + hostnames for use in service principal names. Setting this flag + to false can improve security by reducing reliance on DNS, but + means that short hostnames will not be canonicalized to + fully-qualified hostnames. If this option is set to ``fallback`` (new + in release 1.18), DNS canonicalization will only be performed the + server hostname is not found with the original name when + requesting credentials. The default value is true. + +**dns_lookup_kdc** + Indicate whether DNS SRV records should be used to locate the KDCs + and other servers for a realm, if they are not listed in the + krb5.conf information for the realm. (Note that the admin_server + entry must be in the krb5.conf realm information in order to + contact kadmind, because the DNS implementation for kadmin is + incomplete.) + + Enabling this option does open up a type of denial-of-service + attack, if someone spoofs the DNS records and redirects you to + another server. However, it's no worse than a denial of service, + because that fake KDC will be unable to decode anything you send + it (besides the initial ticket request, which has no encrypted + data), and anything the fake KDC sends will not be trusted without + verification using some secret that it won't know. + +**dns_uri_lookup** + Indicate whether DNS URI records should be used to locate the KDCs + and other servers for a realm, if they are not listed in the + krb5.conf information for the realm. SRV records are used as a + fallback if no URI records were found. The default value is true. + New in release 1.15. + +**enforce_ok_as_delegate** + If this flag to true, GSSAPI credential delegation will be + disabled when the ``ok-as-delegate`` flag is not set in the + service ticket. If this flag is false, the ``ok-as-delegate`` + ticket flag is only enforced when an application specifically + requests enforcement. The default value is false. + +**err_fmt** + This relation allows for custom error message formatting. If a + value is set, error messages will be formatted by substituting a + normal error message for %M and an error code for %C in the value. + +**extra_addresses** + This allows a computer to use multiple local addresses, in order + to allow Kerberos to work in a network that uses NATs while still + using address-restricted tickets. The addresses should be in a + comma-separated list. This option has no effect if + **noaddresses** is true. + +**forwardable** + If this flag is true, initial tickets will be forwardable by + default, if allowed by the KDC. The default value is false. + +**ignore_acceptor_hostname** + When accepting GSSAPI or krb5 security contexts for host-based + service principals, ignore any hostname passed by the calling + application, and allow clients to authenticate to any service + principal in the keytab matching the service name and realm name + (if given). This option can improve the administrative + flexibility of server applications on multihomed hosts, but could + compromise the security of virtual hosting environments. The + default value is false. New in release 1.10. + +**k5login_authoritative** + If this flag is true, principals must be listed in a local user's + k5login file to be granted login access, if a :ref:`.k5login(5)` + file exists. If this flag is false, a principal may still be + granted login access through other mechanisms even if a k5login + file exists but does not list the principal. The default value is + true. + +**k5login_directory** + If set, the library will look for a local user's k5login file + within the named directory, with a filename corresponding to the + local username. If not set, the library will look for k5login + files in the user's home directory, with the filename .k5login. + For security reasons, .k5login files must be owned by + the local user or by root. + +**kcm_mach_service** + On macOS only, determines the name of the bootstrap service used to + contact the KCM daemon for the KCM credential cache type. If the + value is ``-``, Mach RPC will not be used to contact the KCM + daemon. The default value is ``org.h5l.kcm``. + +**kcm_socket** + Determines the path to the Unix domain socket used to access the + KCM daemon for the KCM credential cache type. If the value is + ``-``, Unix domain sockets will not be used to contact the KCM + daemon. The default value is + ``/var/run/.heim_org.h5l.kcm-socket``. + +**kdc_default_options** + Default KDC options (Xored for multiple values) when requesting + initial tickets. By default it is set to 0x00000010 + (KDC_OPT_RENEWABLE_OK). + +**kdc_timesync** + Accepted values for this relation are 1 or 0. If it is nonzero, + client machines will compute the difference between their time and + the time returned by the KDC in the timestamps in the tickets and + use this value to correct for an inaccurate system clock when + requesting service tickets or authenticating to services. This + corrective factor is only used by the Kerberos library; it is not + used to change the system clock. The default value is 1. + +**noaddresses** + If this flag is true, requests for initial tickets will not be + made with address restrictions set, allowing the tickets to be + used across NATs. The default value is true. + +**permitted_enctypes** + Identifies the encryption types that servers will permit for + session keys and for ticket and authenticator encryption, ordered + by preference from highest to lowest. Starting in release 1.18, + this tag also acts as the default value for + **default_tgs_enctypes** and **default_tkt_enctypes**. The + default value for this tag is |defetypes|. + +**plugin_base_dir** + If set, determines the base directory where krb5 plugins are + located. The default value is the ``krb5/plugins`` subdirectory + of the krb5 library directory. This relation is subject to + parameter expansion (see below) in release 1.17 and later. + +**preferred_preauth_types** + This allows you to set the preferred preauthentication types which + the client will attempt before others which may be advertised by a + KDC. The default value for this setting is "17, 16, 15, 14", + which forces libkrb5 to attempt to use PKINIT if it is supported. + +**proxiable** + If this flag is true, initial tickets will be proxiable by + default, if allowed by the KDC. The default value is false. + +**qualify_shortname** + If this string is set, it determines the domain suffix for + single-component hostnames when DNS canonicalization is not used + (either because **dns_canonicalize_hostname** is false or because + forward canonicalization failed). The default value is the first + search domain of the system's DNS configuration. To disable + qualification of shortnames, set this relation to the empty string + with ``qualify_shortname = ""``. (New in release 1.18.) + +**rdns** + If this flag is true, reverse name lookup will be used in addition + to forward name lookup to canonicalizing hostnames for use in + service principal names. If **dns_canonicalize_hostname** is set + to false, this flag has no effect. The default value is true. + +**realm_try_domains** + Indicate whether a host's domain components should be used to + determine the Kerberos realm of the host. The value of this + variable is an integer: -1 means not to search, 0 means to try the + host's domain itself, 1 means to also try the domain's immediate + parent, and so forth. The library's usual mechanism for locating + Kerberos realms is used to determine whether a domain is a valid + realm, which may involve consulting DNS if **dns_lookup_kdc** is + set. The default is not to search domain components. + +**renew_lifetime** + (:ref:`duration` string.) Sets the default renewable lifetime + for initial ticket requests. The default value is 0. + +**spake_preauth_groups** + A whitespace or comma-separated list of words which specifies the + groups allowed for SPAKE preauthentication. The possible values + are: + + ============ ================================ + edwards25519 Edwards25519 curve (:rfc:`7748`) + P-256 NIST P-256 curve (:rfc:`5480`) + P-384 NIST P-384 curve (:rfc:`5480`) + P-521 NIST P-521 curve (:rfc:`5480`) + ============ ================================ + + The default value for the client is ``edwards25519``. The default + value for the KDC is empty. New in release 1.17. + +**ticket_lifetime** + (:ref:`duration` string.) Sets the default lifetime for initial + ticket requests. The default value is 1 day. + +**udp_preference_limit** + When sending a message to the KDC, the library will try using TCP + before UDP if the size of the message is above + **udp_preference_limit**. If the message is smaller than + **udp_preference_limit**, then UDP will be tried before TCP. + Regardless of the size, both protocols will be tried if the first + attempt fails. + +**verify_ap_req_nofail** + If this flag is true, then an attempt to verify initial + credentials will fail if the client machine does not have a + keytab. The default value is false. + +**client_aware_channel_bindings** + If this flag is true, then all application protocol authentication + requests will be flagged to indicate that the application supports + channel bindings when operating over a secure channel. The + default value is false. + +.. _realms: + +[realms] +~~~~~~~~ + +Each tag in the [realms] section of the file is the name of a Kerberos +realm. The value of the tag is a subsection with relations that +define the properties of that particular realm. For each realm, the +following tags may be specified in the realm's subsection: + +**admin_server** + Identifies the host where the administration server is running. + Typically, this is the primary Kerberos server. This tag must be + given a value in order to communicate with the :ref:`kadmind(8)` + server for the realm. + +**auth_to_local** + This tag allows you to set a general rule for mapping principal + names to local user names. It will be used if there is not an + explicit mapping for the principal name that is being + translated. The possible values are: + + **RULE:**\ *exp* + The local name will be formulated from *exp*. + + The format for *exp* is **[**\ *n*\ **:**\ *string*\ **](**\ + *regexp*\ **)s/**\ *pattern*\ **/**\ *replacement*\ **/g**. + The integer *n* indicates how many components the target + principal should have. If this matches, then a string will be + formed from *string*, substituting the realm of the principal + for ``$0`` and the *n*'th component of the principal for + ``$n`` (e.g., if the principal was ``johndoe/admin`` then + ``[2:$2$1foo]`` would result in the string + ``adminjohndoefoo``). If this string matches *regexp*, then + the ``s//[g]`` substitution command will be run over the + string. The optional **g** will cause the substitution to be + global over the *string*, instead of replacing only the first + match in the *string*. + + **DEFAULT** + The principal name will be used as the local user name. If + the principal has more than one component or is not in the + default realm, this rule is not applicable and the conversion + will fail. + + For example:: + + [realms] + ATHENA.MIT.EDU = { + auth_to_local = RULE:[2:$1](johndoe)s/^.*$/guest/ + auth_to_local = RULE:[2:$1;$2](^.*;admin$)s/;admin$// + auth_to_local = RULE:[2:$2](^.*;root)s/^.*$/root/ + auth_to_local = DEFAULT + } + + would result in any principal without ``root`` or ``admin`` as the + second component to be translated with the default rule. A + principal with a second component of ``admin`` will become its + first component. ``root`` will be used as the local name for any + principal with a second component of ``root``. The exception to + these two rules are any principals ``johndoe/*``, which will + always get the local name ``guest``. + +**auth_to_local_names** + This subsection allows you to set explicit mappings from principal + names to local user names. The tag is the mapping name, and the + value is the corresponding local user name. + +**default_domain** + This tag specifies the domain used to expand hostnames when + translating Kerberos 4 service principals to Kerberos 5 principals + (for example, when converting ``rcmd.hostname`` to + ``host/hostname.domain``). + +**disable_encrypted_timestamp** + If this flag is true, the client will not perform encrypted + timestamp preauthentication if requested by the KDC. Setting this + flag can help to prevent dictionary attacks by active attackers, + if the realm's KDCs support SPAKE preauthentication or if initial + authentication always uses another mechanism or always uses FAST. + This flag persists across client referrals during initial + authentication. This flag does not prevent the KDC from offering + encrypted timestamp. New in release 1.17. + +**http_anchors** + When KDCs and kpasswd servers are accessed through HTTPS proxies, this tag + can be used to specify the location of the CA certificate which should be + trusted to issue the certificate for a proxy server. If left unspecified, + the system-wide default set of CA certificates is used. + + The syntax for values is similar to that of values for the + **pkinit_anchors** tag: + + **FILE:** *filename* + + *filename* is assumed to be the name of an OpenSSL-style ca-bundle file. + + **DIR:** *dirname* + + *dirname* is assumed to be an directory which contains CA certificates. + All files in the directory will be examined; if they contain certificates + (in PEM format), they will be used. + + **ENV:** *envvar* + + *envvar* specifies the name of an environment variable which has been set + to a value conforming to one of the previous values. For example, + ``ENV:X509_PROXY_CA``, where environment variable ``X509_PROXY_CA`` has + been set to ``FILE:/tmp/my_proxy.pem``. + +**kdc** + The name or address of a host running a KDC for that realm. An + optional port number, separated from the hostname by a colon, may + be included. If the name or address contains colons (for example, + if it is an IPv6 address), enclose it in square brackets to + distinguish the colon from a port separator. For your computer to + be able to communicate with the KDC for each realm, this tag must + be given a value in each realm subsection in the configuration + file, or there must be DNS SRV records specifying the KDCs. + +**kpasswd_server** + Points to the server where all the password changes are performed. + If there is no such entry, DNS will be queried (unless forbidden + by **dns_lookup_kdc**). Finally, port 464 on the **admin_server** + host will be tried. + +**master_kdc** + The name for **primary_kdc** prior to release 1.19. Its value is + used as a fallback if **primary_kdc** is not specified. + +**primary_kdc** + Identifies the primary KDC(s). Currently, this tag is used in only + one case: If an attempt to get credentials fails because of an + invalid password, the client software will attempt to contact the + primary KDC, in case the user's password has just been changed, and + the updated database has not been propagated to the replica + servers yet. New in release 1.19. + +**v4_instance_convert** + This subsection allows the administrator to configure exceptions + to the **default_domain** mapping rule. It contains V4 instances + (the tag name) which should be translated to some specific + hostname (the tag value) as the second component in a Kerberos V5 + principal name. + +**v4_realm** + This relation is used by the krb524 library routines when + converting a V5 principal name to a V4 principal name. It is used + when the V4 realm name and the V5 realm name are not the same, but + still share the same principal names and passwords. The tag value + is the Kerberos V4 realm name. + + +.. _domain_realm: + +[domain_realm] +~~~~~~~~~~~~~~ + +The [domain_realm] section provides a translation from hostnames to +Kerberos realms. Each tag is a domain name, providing the mapping for +that domain and all subdomains. If the tag begins with a period +(``.``) then it applies only to subdomains. The Kerberos realm may be +identified either in the realms_ section or using DNS SRV records. +Tag names should be in lower case. For example:: + + [domain_realm] + crash.mit.edu = TEST.ATHENA.MIT.EDU + .dev.mit.edu = TEST.ATHENA.MIT.EDU + mit.edu = ATHENA.MIT.EDU + +maps the host with the name ``crash.mit.edu`` into the +``TEST.ATHENA.MIT.EDU`` realm. The second entry maps all hosts under the +domain ``dev.mit.edu`` into the ``TEST.ATHENA.MIT.EDU`` realm, but not +the host with the name ``dev.mit.edu``. That host is matched +by the third entry, which maps the host ``mit.edu`` and all hosts +under the domain ``mit.edu`` that do not match a preceding rule +into the realm ``ATHENA.MIT.EDU``. + +If no translation entry applies to a hostname used for a service +principal for a service ticket request, the library will try to get a +referral to the appropriate realm from the client realm's KDC. If +that does not succeed, the host's realm is considered to be the +hostname's domain portion converted to uppercase, unless the +**realm_try_domains** setting in [libdefaults] causes a different +parent domain to be used. + + +.. _capaths: + +[capaths] +~~~~~~~~~ + +In order to perform direct (non-hierarchical) cross-realm +authentication, configuration is needed to determine the +authentication paths between realms. + +A client will use this section to find the authentication path between +its realm and the realm of the server. The server will use this +section to verify the authentication path used by the client, by +checking the transited field of the received ticket. + +There is a tag for each participating client realm, and each tag has +subtags for each of the server realms. The value of the subtags is an +intermediate realm which may participate in the cross-realm +authentication. The subtags may be repeated if there is more then one +intermediate realm. A value of "." means that the two realms share +keys directly, and no intermediate realms should be allowed to +participate. + +Only those entries which will be needed on the client or the server +need to be present. A client needs a tag for its local realm with +subtags for all the realms of servers it will need to authenticate to. +A server needs a tag for each realm of the clients it will serve, with +a subtag of the server realm. + +For example, ``ANL.GOV``, ``PNL.GOV``, and ``NERSC.GOV`` all wish to +use the ``ES.NET`` realm as an intermediate realm. ANL has a sub +realm of ``TEST.ANL.GOV`` which will authenticate with ``NERSC.GOV`` +but not ``PNL.GOV``. The [capaths] section for ``ANL.GOV`` systems +would look like this:: + + [capaths] + ANL.GOV = { + TEST.ANL.GOV = . + PNL.GOV = ES.NET + NERSC.GOV = ES.NET + ES.NET = . + } + TEST.ANL.GOV = { + ANL.GOV = . + } + PNL.GOV = { + ANL.GOV = ES.NET + } + NERSC.GOV = { + ANL.GOV = ES.NET + } + ES.NET = { + ANL.GOV = . + } + +The [capaths] section of the configuration file used on ``NERSC.GOV`` +systems would look like this:: + + [capaths] + NERSC.GOV = { + ANL.GOV = ES.NET + TEST.ANL.GOV = ES.NET + TEST.ANL.GOV = ANL.GOV + PNL.GOV = ES.NET + ES.NET = . + } + ANL.GOV = { + NERSC.GOV = ES.NET + } + PNL.GOV = { + NERSC.GOV = ES.NET + } + ES.NET = { + NERSC.GOV = . + } + TEST.ANL.GOV = { + NERSC.GOV = ANL.GOV + NERSC.GOV = ES.NET + } + +When a subtag is used more than once within a tag, clients will use +the order of values to determine the path. The order of values is not +important to servers. + + +.. _appdefaults: + +[appdefaults] +~~~~~~~~~~~~~ + +Each tag in the [appdefaults] section names a Kerberos V5 application +or an option that is used by some Kerberos V5 application[s]. The +value of the tag defines the default behaviors for that application. + +For example:: + + [appdefaults] + telnet = { + ATHENA.MIT.EDU = { + option1 = false + } + } + telnet = { + option1 = true + option2 = true + } + ATHENA.MIT.EDU = { + option2 = false + } + option2 = true + +The above four ways of specifying the value of an option are shown in +order of decreasing precedence. In this example, if telnet is running +in the realm EXAMPLE.COM, it should, by default, have option1 and +option2 set to true. However, a telnet program in the realm +``ATHENA.MIT.EDU`` should have ``option1`` set to false and +``option2`` set to true. Any other programs in ATHENA.MIT.EDU should +have ``option2`` set to false by default. Any programs running in +other realms should have ``option2`` set to true. + +The list of specifiable options for each application may be found in +that application's man pages. The application defaults specified here +are overridden by those specified in the realms_ section. + + +.. _plugins: + +[plugins] +~~~~~~~~~ + + * pwqual_ interface + * kadm5_hook_ interface + * clpreauth_ and kdcpreauth_ interfaces + +Tags in the [plugins] section can be used to register dynamic plugin +modules and to turn modules on and off. Not every krb5 pluggable +interface uses the [plugins] section; the ones that do are documented +here. + +New in release 1.9. + +Each pluggable interface corresponds to a subsection of [plugins]. +All subsections support the same tags: + +**disable** + This tag may have multiple values. If there are values for this + tag, then the named modules will be disabled for the pluggable + interface. + +**enable_only** + This tag may have multiple values. If there are values for this + tag, then only the named modules will be enabled for the pluggable + interface. + +**module** + This tag may have multiple values. Each value is a string of the + form ``modulename:pathname``, which causes the shared object + located at *pathname* to be registered as a dynamic module named + *modulename* for the pluggable interface. If *pathname* is not an + absolute path, it will be treated as relative to the + **plugin_base_dir** value from :ref:`libdefaults`. + +For pluggable interfaces where module order matters, modules +registered with a **module** tag normally come first, in the order +they are registered, followed by built-in modules in the order they +are documented below. If **enable_only** tags are used, then the +order of those tags overrides the normal module order. + +The following subsections are currently supported within the [plugins] +section: + +.. _ccselect: + +ccselect interface +################## + +The ccselect subsection controls modules for credential cache +selection within a cache collection. In addition to any registered +dynamic modules, the following built-in modules exist (and may be +disabled with the disable tag): + +**k5identity** + Uses a .k5identity file in the user's home directory to select a + client principal + +**realm** + Uses the service realm to guess an appropriate cache from the + collection + +**hostname** + If the service principal is host-based, uses the service hostname + to guess an appropriate cache from the collection + +.. _pwqual: + +pwqual interface +################ + +The pwqual subsection controls modules for the password quality +interface, which is used to reject weak passwords when passwords are +changed. The following built-in modules exist for this interface: + +**dict** + Checks against the realm dictionary file + +**empty** + Rejects empty passwords + +**hesiod** + Checks against user information stored in Hesiod (only if Kerberos + was built with Hesiod support) + +**princ** + Checks against components of the principal name + +.. _kadm5_hook: + +kadm5_hook interface +#################### + +The kadm5_hook interface provides plugins with information on +principal creation, modification, password changes and deletion. This +interface can be used to write a plugin to synchronize MIT Kerberos +with another database such as Active Directory. No plugins are built +in for this interface. + +.. _kadm5_auth: + +kadm5_auth interface +#################### + +The kadm5_auth section (introduced in release 1.16) controls modules +for the kadmin authorization interface, which determines whether a +client principal is allowed to perform a kadmin operation. The +following built-in modules exist for this interface: + +**acl** + This module reads the :ref:`kadm5.acl(5)` file, and authorizes + operations which are allowed according to the rules in the file. + +**self** + This module authorizes self-service operations including password + changes, creation of new random keys, fetching the client's + principal record or string attributes, and fetching the policy + record associated with the client principal. + +.. _clpreauth: + +.. _kdcpreauth: + +clpreauth and kdcpreauth interfaces +################################### + +The clpreauth and kdcpreauth interfaces allow plugin modules to +provide client and KDC preauthentication mechanisms. The following +built-in modules exist for these interfaces: + +**pkinit** + This module implements the PKINIT preauthentication mechanism. + +**encrypted_challenge** + This module implements the encrypted challenge FAST factor. + +**encrypted_timestamp** + This module implements the encrypted timestamp mechanism. + +.. _hostrealm: + +hostrealm interface +################### + +The hostrealm section (introduced in release 1.12) controls modules +for the host-to-realm interface, which affects the local mapping of +hostnames to realm names and the choice of default realm. The following +built-in modules exist for this interface: + +**profile** + This module consults the [domain_realm] section of the profile for + authoritative host-to-realm mappings, and the **default_realm** + variable for the default realm. + +**dns** + This module looks for DNS records for fallback host-to-realm + mappings and the default realm. It only operates if the + **dns_lookup_realm** variable is set to true. + +**domain** + This module applies heuristics for fallback host-to-realm + mappings. It implements the **realm_try_domains** variable, and + uses the uppercased parent domain of the hostname if that does not + produce a result. + +.. _localauth: + +localauth interface +################### + +The localauth section (introduced in release 1.12) controls modules +for the local authorization interface, which affects the relationship +between Kerberos principals and local system accounts. The following +built-in modules exist for this interface: + +**default** + This module implements the **DEFAULT** type for **auth_to_local** + values. + +**rule** + This module implements the **RULE** type for **auth_to_local** + values. + +**names** + This module looks for an **auth_to_local_names** mapping for the + principal name. + +**auth_to_local** + This module processes **auth_to_local** values in the default + realm's section, and applies the default method if no + **auth_to_local** values exist. + +**k5login** + This module authorizes a principal to a local account according to + the account's :ref:`.k5login(5)` file. + +**an2ln** + This module authorizes a principal to a local account if the + principal name maps to the local account name. + +.. _certauth: + +certauth interface +################## + +The certauth section (introduced in release 1.16) controls modules for +the certificate authorization interface, which determines whether a +certificate is allowed to preauthenticate a user via PKINIT. The +following built-in modules exist for this interface: + +**pkinit_san** + This module authorizes the certificate if it contains a PKINIT + Subject Alternative Name for the requested client principal, or a + Microsoft UPN SAN matching the principal if **pkinit_allow_upn** + is set to true for the realm. + +**pkinit_eku** + This module rejects the certificate if it does not contain an + Extended Key Usage attribute consistent with the + **pkinit_eku_checking** value for the realm. + +**dbmatch** + This module authorizes or rejects the certificate according to + whether it matches the **pkinit_cert_match** string attribute on + the client principal, if that attribute is present. + + +PKINIT options +-------------- + +.. note:: + + The following are PKINIT-specific options. These values may + be specified in [libdefaults] as global defaults, or within + a realm-specific subsection of [libdefaults], or may be + specified as realm-specific values in the [realms] section. + A realm-specific value overrides, not adds to, a generic + [libdefaults] specification. The search order is: + +1. realm-specific subsection of [libdefaults]:: + + [libdefaults] + EXAMPLE.COM = { + pkinit_anchors = FILE:/usr/local/example.com.crt + } + +2. realm-specific value in the [realms] section:: + + [realms] + OTHERREALM.ORG = { + pkinit_anchors = FILE:/usr/local/otherrealm.org.crt + } + +3. generic value in the [libdefaults] section:: + + [libdefaults] + pkinit_anchors = DIR:/usr/local/generic_trusted_cas/ + + +.. _pkinit_identity: + +Specifying PKINIT identity information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The syntax for specifying Public Key identity, trust, and revocation +information for PKINIT is as follows: + +**FILE:**\ *filename*\ [**,**\ *keyfilename*] + This option has context-specific behavior. + + In **pkinit_identity** or **pkinit_identities**, *filename* + specifies the name of a PEM-format file containing the user's + certificate. If *keyfilename* is not specified, the user's + private key is expected to be in *filename* as well. Otherwise, + *keyfilename* is the name of the file containing the private key. + + In **pkinit_anchors** or **pkinit_pool**, *filename* is assumed to + be the name of an OpenSSL-style ca-bundle file. + +**DIR:**\ *dirname* + This option has context-specific behavior. + + In **pkinit_identity** or **pkinit_identities**, *dirname* + specifies a directory with files named ``*.crt`` and ``*.key`` + where the first part of the file name is the same for matching + pairs of certificate and private key files. When a file with a + name ending with ``.crt`` is found, a matching file ending with + ``.key`` is assumed to contain the private key. If no such file + is found, then the certificate in the ``.crt`` is not used. + + In **pkinit_anchors** or **pkinit_pool**, *dirname* is assumed to + be an OpenSSL-style hashed CA directory where each CA cert is + stored in a file named ``hash-of-ca-cert.#``. This infrastructure + is encouraged, but all files in the directory will be examined and + if they contain certificates (in PEM format), they will be used. + + In **pkinit_revoke**, *dirname* is assumed to be an OpenSSL-style + hashed CA directory where each revocation list is stored in a file + named ``hash-of-ca-cert.r#``. This infrastructure is encouraged, + but all files in the directory will be examined and if they + contain a revocation list (in PEM format), they will be used. + +**PKCS12:**\ *filename* + *filename* is the name of a PKCS #12 format file, containing the + user's certificate and private key. + +**PKCS11:**\ [**module_name=**]\ *modname*\ [**:slotid=**\ *slot-id*][**:token=**\ *token-label*][**:certid=**\ *cert-id*][**:certlabel=**\ *cert-label*] + All keyword/values are optional. *modname* specifies the location + of a library implementing PKCS #11. If a value is encountered + with no keyword, it is assumed to be the *modname*. If no + module-name is specified, the default is |pkcs11_modname|. + ``slotid=`` and/or ``token=`` may be specified to force the use of + a particular smard card reader or token if there is more than one + available. ``certid=`` and/or ``certlabel=`` may be specified to + force the selection of a particular certificate on the device. + See the **pkinit_cert_match** configuration option for more ways + to select a particular certificate to use for PKINIT. + +**ENV:**\ *envvar* + *envvar* specifies the name of an environment variable which has + been set to a value conforming to one of the previous values. For + example, ``ENV:X509_PROXY``, where environment variable + ``X509_PROXY`` has been set to ``FILE:/tmp/my_proxy.pem``. + + +PKINIT krb5.conf options +~~~~~~~~~~~~~~~~~~~~~~~~ + +**pkinit_anchors** + Specifies the location of trusted anchor (root) certificates which + the client trusts to sign KDC certificates. This option may be + specified multiple times. These values from the config file are + not used if the user specifies X509_anchors on the command line. + +**pkinit_cert_match** + Specifies matching rules that the client certificate must match + before it is used to attempt PKINIT authentication. If a user has + multiple certificates available (on a smart card, or via other + media), there must be exactly one certificate chosen before + attempting PKINIT authentication. This option may be specified + multiple times. All the available certificates are checked + against each rule in order until there is a match of exactly one + certificate. + + The Subject and Issuer comparison strings are the :rfc:`2253` + string representations from the certificate Subject DN and Issuer + DN values. + + The syntax of the matching rules is: + + [*relation-operator*\ ]\ *component-rule* ... + + where: + + *relation-operator* + can be either ``&&``, meaning all component rules must match, + or ``||``, meaning only one component rule must match. The + default is ``&&``. + + *component-rule* + can be one of the following. Note that there is no + punctuation or whitespace between component rules. + + | ****\ *regular-expression* + | ****\ *regular-expression* + | ****\ *regular-expression* + | ****\ *extended-key-usage-list* + | ****\ *key-usage-list* + + *extended-key-usage-list* is a comma-separated list of + required Extended Key Usage values. All values in the list + must be present in the certificate. Extended Key Usage values + can be: + + * pkinit + * msScLogin + * clientAuth + * emailProtection + + *key-usage-list* is a comma-separated list of required Key + Usage values. All values in the list must be present in the + certificate. Key Usage values can be: + + * digitalSignature + * keyEncipherment + + Examples:: + + pkinit_cert_match = ||.*DoE.*.*@EXAMPLE.COM + pkinit_cert_match = &&msScLogin,clientAuth.*DoE.* + pkinit_cert_match = msScLogin,clientAuthdigitalSignature + +**pkinit_eku_checking** + This option specifies what Extended Key Usage value the KDC + certificate presented to the client must contain. (Note that if + the KDC certificate has the pkinit SubjectAlternativeName encoded + as the Kerberos TGS name, EKU checking is not necessary since the + issuing CA has certified this as a KDC certificate.) The values + recognized in the krb5.conf file are: + + **kpKDC** + This is the default value and specifies that the KDC must have + the id-pkinit-KPKdc EKU as defined in :rfc:`4556`. + + **kpServerAuth** + If **kpServerAuth** is specified, a KDC certificate with the + id-kp-serverAuth EKU will be accepted. This key usage value + is used in most commercially issued server certificates. + + **none** + If **none** is specified, then the KDC certificate will not be + checked to verify it has an acceptable EKU. The use of this + option is not recommended. + +**pkinit_dh_min_bits** + Specifies the size of the Diffie-Hellman key the client will + attempt to use. The acceptable values are 1024, 2048, and 4096. + The default is 2048. + +**pkinit_identities** + Specifies the location(s) to be used to find the user's X.509 + identity information. If this option is specified multiple times, + each value is attempted in order until certificates are found. + Note that these values are not used if the user specifies + **X509_user_identity** on the command line. + +**pkinit_kdc_hostname** + The presence of this option indicates that the client is willing + to accept a KDC certificate with a dNSName SAN (Subject + Alternative Name) rather than requiring the id-pkinit-san as + defined in :rfc:`4556`. This option may be specified multiple + times. Its value should contain the acceptable hostname for the + KDC (as contained in its certificate). + +**pkinit_pool** + Specifies the location of intermediate certificates which may be + used by the client to complete the trust chain between a KDC + certificate and a trusted anchor. This option may be specified + multiple times. + +**pkinit_require_crl_checking** + The default certificate verification process will always check the + available revocation information to see if a certificate has been + revoked. If a match is found for the certificate in a CRL, + verification fails. If the certificate being verified is not + listed in a CRL, or there is no CRL present for its issuing CA, + and **pkinit_require_crl_checking** is false, then verification + succeeds. + + However, if **pkinit_require_crl_checking** is true and there is + no CRL information available for the issuing CA, then verification + fails. + + **pkinit_require_crl_checking** should be set to true if the + policy is such that up-to-date CRLs must be present for every CA. + +**pkinit_revoke** + Specifies the location of Certificate Revocation List (CRL) + information to be used by the client when verifying the validity + of the KDC certificate presented. This option may be specified + multiple times. + + +.. _parameter_expansion: + +Parameter expansion +------------------- + +Starting with release 1.11, several variables, such as +**default_keytab_name**, allow parameters to be expanded. +Valid parameters are: + + ================= =================================================== + %{TEMP} Temporary directory + %{uid} Unix real UID or Windows SID + %{euid} Unix effective user ID or Windows SID + %{USERID} Same as %{uid} + %{null} Empty string + %{LIBDIR} Installation library directory + %{BINDIR} Installation binary directory + %{SBINDIR} Installation admin binary directory + %{username} (Unix) Username of effective user ID + %{APPDATA} (Windows) Roaming application data for current user + %{COMMON_APPDATA} (Windows) Application data for all users + %{LOCAL_APPDATA} (Windows) Local application data for current user + %{SYSTEM} (Windows) Windows system folder + %{WINDOWS} (Windows) Windows folder + %{USERCONFIG} (Windows) Per-user MIT krb5 config file directory + %{COMMONCONFIG} (Windows) Common MIT krb5 config file directory + ================= =================================================== + +Sample krb5.conf file +--------------------- + +Here is an example of a generic krb5.conf file:: + + [libdefaults] + default_realm = ATHENA.MIT.EDU + dns_lookup_kdc = true + dns_lookup_realm = false + + [realms] + ATHENA.MIT.EDU = { + kdc = kerberos.mit.edu + kdc = kerberos-1.mit.edu + kdc = kerberos-2.mit.edu + admin_server = kerberos.mit.edu + primary_kdc = kerberos.mit.edu + } + EXAMPLE.COM = { + kdc = kerberos.example.com + kdc = kerberos-1.example.com + admin_server = kerberos.example.com + } + + [domain_realm] + mit.edu = ATHENA.MIT.EDU + + [capaths] + ATHENA.MIT.EDU = { + EXAMPLE.COM = . + } + EXAMPLE.COM = { + ATHENA.MIT.EDU = . + } + +FILES +----- + +|krb5conf| + + +SEE ALSO +-------- + +syslog(3) diff --git a/krb5-1.21.3/doc/admin/conf_ldap.rst b/krb5-1.21.3/doc/admin/conf_ldap.rst new file mode 100644 index 00000000..65542c1a --- /dev/null +++ b/krb5-1.21.3/doc/admin/conf_ldap.rst @@ -0,0 +1,132 @@ +.. _conf_ldap: + +Configuring Kerberos with OpenLDAP back-end +=========================================== + + + 1. Make sure the LDAP server is using local authentication + (``ldapi://``) or TLS (``ldaps``). See + https://www.openldap.org/doc/admin/tls.html for instructions on + configuring TLS support in OpenLDAP. + + 2. Add the Kerberos schema file to the LDAP Server using the OpenLDAP + LDIF file from the krb5 source directory + (``src/plugins/kdb/ldap/libkdb_ldap/kerberos.openldap.ldif``). + The following example uses local authentication:: + + ldapadd -Y EXTERNAL -H ldapi:/// -f /path/to/kerberos.openldap.ldif + + 3. Choose DNs for the :ref:`krb5kdc(8)` and :ref:`kadmind(8)` servers + to bind to the LDAP server, and create them if necessary. Specify + these DNs with the **ldap_kdc_dn** and **ldap_kadmind_dn** + directives in :ref:`kdc.conf(5)`. The kadmind DN will also be + used for administrative commands such as :ref:`kdb5_util(8)`. + + Alternatively, you may configure krb5kdc and kadmind to use SASL + authentication to access the LDAP server; see the :ref:`dbmodules` + relations **ldap_kdc_sasl_mech** and similar. + + 4. Specify a location for the LDAP service password file by setting + **ldap_service_password_file**. Use ``kdb5_ldap_util stashsrvpw`` + to stash passwords for the KDC and kadmind DNs chosen above. For + example:: + + kdb5_ldap_util stashsrvpw -f /path/to/service.keyfile cn=krbadmin,dc=example,dc=com + + Skip this step if you are using SASL authentication and the + mechanism does not require a password. + + 5. Choose a DN for the global Kerberos container entry (but do not + create the entry at this time). Specify this DN with the + **ldap_kerberos_container_dn** directive in :ref:`kdc.conf(5)`. + Realm container entries will be created underneath this DN. + Principal entries may exist either underneath the realm container + (the default) or in separate trees referenced from the realm + container. + + 6. Configure the LDAP server ACLs to enable the KDC and kadmin server + DNs to read and write the Kerberos data. If + **disable_last_success** and **disable_lockout** are both set to + true in the :ref:`dbmodules` subsection for the realm, then the + KDC DN only requires read access to the Kerberos data. + + Sample access control information:: + + access to dn.base="" + by * read + + access to dn.base="cn=Subschema" + by * read + + # Provide access to the realm container. + access to dn.subtree= "cn=EXAMPLE.COM,cn=krbcontainer,dc=example,dc=com" + by dn.exact="cn=kdc-service,dc=example,dc=com" write + by dn.exact="cn=adm-service,dc=example,dc=com" write + by * none + + # Provide access to principals, if not underneath the realm container. + access to dn.subtree= "ou=users,dc=example,dc=com" + by dn.exact="cn=kdc-service,dc=example,dc=com" write + by dn.exact="cn=adm-service,dc=example,dc=com" write + by * none + + access to * + by * read + + If the locations of the container and principals or the DNs of the + service objects for a realm are changed then this information + should be updated. + + 7. In :ref:`kdc.conf(5)`, make sure the following relations are set + in the :ref:`dbmodules` subsection for the realm:: + + db_library (set to ``kldap``) + ldap_kerberos_container_dn + ldap_kdc_dn + ldap_kadmind_dn + ldap_service_password_file + ldap_servers + + 8. Create the realm using :ref:`kdb5_ldap_util(8)`: + + kdb5_ldap_util create -subtrees ou=users,dc=example,dc=com -s + + Use the **-subtrees** option if the principals are to exist in a + separate subtree from the realm container. Before executing the + command, make sure that the subtree mentioned above + ``(ou=users,dc=example,dc=com)`` exists. If the principals will + exist underneath the realm container, omit the **-subtrees** option + and do not worry about creating the principal subtree. + + For more information, refer to the section :ref:`ops_on_ldap`. + + The realm object is created under the + **ldap_kerberos_container_dn** specified in the configuration + file. This operation will also create the Kerberos container, if + not present already. This container can be used to store + information related to multiple realms. + + 9. Add an ``eq`` index for ``krbPrincipalName`` to speed up principal + lookup operations. See + https://www.openldap.org/doc/admin/tuning.html#Indexes for + details. + +With the LDAP back end it is possible to provide aliases for principal +entries. Currently we provide no administrative utilities for +creating aliases, so it must be done by direct manipulation of the +LDAP entries. + +An entry with aliases contains multiple values of the +*krbPrincipalName* attribute. Since LDAP attribute values are not +ordered, it is necessary to specify which principal name is canonical, +by using the *krbCanonicalName* attribute. Therefore, to create +aliases for an entry, first set the *krbCanonicalName* attribute of +the entry to the canonical principal name (which should be identical +to the pre-existing *krbPrincipalName* value), and then add additional +*krbPrincipalName* attributes for the aliases. + +Principal aliases are only returned by the KDC when the client +requests canonicalization. Canonicalization is normally requested for +service principals; for client principals, an explicit flag is often +required (e.g., ``kinit -C``) and canonicalization is only performed +for initial ticket requests. diff --git a/krb5-1.21.3/doc/admin/database.rst b/krb5-1.21.3/doc/admin/database.rst new file mode 100644 index 00000000..2fd07242 --- /dev/null +++ b/krb5-1.21.3/doc/admin/database.rst @@ -0,0 +1,587 @@ +Database administration +======================= + +A Kerberos database contains all of a realm's Kerberos principals, +their passwords, and other administrative information about each +principal. For the most part, you will use the :ref:`kdb5_util(8)` +program to manipulate the Kerberos database as a whole, and the +:ref:`kadmin(1)` program to make changes to the entries in the +database. (One notable exception is that users will use the +:ref:`kpasswd(1)` program to change their own passwords.) The kadmin +program has its own command-line interface, to which you type the +database administrating commands. + +:ref:`kdb5_util(8)` provides a means to create, delete, load, or dump +a Kerberos database. It also contains commands to roll over the +database master key, and to stash a copy of the key so that the +:ref:`kadmind(8)` and :ref:`krb5kdc(8)` daemons can use the database +without manual input. + +:ref:`kadmin(1)` provides for the maintenance of Kerberos principals, +password policies, and service key tables (keytabs). Normally it +operates as a network client using Kerberos authentication to +communicate with :ref:`kadmind(8)`, but there is also a variant, named +kadmin.local, which directly accesses the Kerberos database on the +local filesystem (or through LDAP). kadmin.local is necessary to set +up enough of the database to be able to use the remote version. + +kadmin can authenticate to the admin server using the service +principal ``kadmin/admin`` or ``kadmin/HOST`` (where *HOST* is the +hostname of the admin server). If the credentials cache contains a +ticket for either service principal and the **-c** ccache option is +specified, that ticket is used to authenticate to KADM5. Otherwise, +the **-p** and **-k** options are used to specify the client Kerberos +principal name used to authenticate. Once kadmin has determined the +principal name, it requests a ``kadmin/admin`` Kerberos service ticket +from the KDC, and uses that service ticket to authenticate to KADM5. + +See :ref:`kadmin(1)` for the available kadmin and kadmin.local +commands and options. + + +.. _principals: + +Principals +---------- + +Each entry in the Kerberos database contains a Kerberos principal and +the attributes and policies associated with that principal. + +To add a principal to the database, use the :ref:`kadmin(1)` +**add_principal** command. User principals should usually be created +with the ``+requires_preauth -allow_svr`` options to help mitigate +dictionary attacks (see :ref:`dictionary`):: + + kadmin: addprinc +requires_preauth -allow_svr alice + Enter password for principal "alice@KRBTEST.COM": + Re-enter password for principal "alice@KRBTEST.COM": + +User principals which will authenticate with :ref:`pkinit` should +instead by created with the ``-nokey`` option: + + kadmin: addprinc -nokey alice + +Service principals can be created with the ``-nokey`` option; +long-term keys will be added when a keytab is generated:: + + kadmin: addprinc -nokey host/foo.mit.edu + kadmin: ktadd -k foo.keytab host/foo.mit.edu + Entry for principal host/foo.mit.edu with kvno 1, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:foo.keytab. + Entry for principal host/foo.mit.edu with kvno 1, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:foo.keytab. + +To modify attributes of an existing principal, use the kadmin +**modify_principal** command:: + + kadmin: modprinc -expire tomorrow alice + Principal "alice@KRBTEST.COM" modified. + +To delete a principal, use the kadmin **delete_principal** command:: + + kadmin: delprinc alice + Are you sure you want to delete the principal "alice@KRBTEST.COM"? (yes/no): yes + Principal "alice@KRBTEST.COM" deleted. + Make sure that you have removed this principal from all ACLs before reusing. + +To change a principal's password, use the kadmin **change_password** +command. Password changes made through kadmin are subject to the same +password policies as would apply to password changes made through +:ref:`kpasswd(1)`. + +To view the attributes of a principal, use the kadmin` +**get_principal** command. + +To generate a listing of principals, use the kadmin +**list_principals** command. + + +.. _policies: + +Policies +-------- + +A policy is a set of rules governing passwords. Policies can dictate +minimum and maximum password lifetimes, minimum number of characters +and character classes a password must contain, and the number of old +passwords kept in the database. + +To add a new policy, use the :ref:`kadmin(1)` **add_policy** command:: + + kadmin: addpol -maxlife "1 year" -history 3 stduser + +To modify attributes of a principal, use the kadmin **modify_policy** +command. To delete a policy, use the kadmin **delete_policy** +command. + +To associate a policy with a principal, use the kadmin +**modify_principal** command with the **-policy** option: + + kadmin: modprinc -policy stduser alice + Principal "alice@KRBTEST.COM" modified. + +A principal entry may be associated with a nonexistent policy, either +because the policy did not exist at the time of associated or was +deleted afterwards. kadmin will warn when associated a principal with +a nonexistent policy, and will annotate the policy name with "[does +not exist]" in the **get_principal** output. + + +.. _updating_history_key: + +Updating the history key +~~~~~~~~~~~~~~~~~~~~~~~~ + +If a policy specifies a number of old keys kept of two or more, the +stored old keys are encrypted in a history key, which is found in the +key data of the ``kadmin/history`` principal. + +Currently there is no support for proper rollover of the history key, +but you can change the history key (for example, to use a better +encryption type) at the cost of invalidating currently stored old +keys. To change the history key, run:: + + kadmin: change_password -randkey kadmin/history + +This command will fail if you specify the **-keepold** flag. Only one +new history key will be created, even if you specify multiple key/salt +combinations. + +In the future, we plan to migrate towards encrypting old keys in the +master key instead of the history key, and implementing proper +rollover support for stored old keys. + + +.. _privileges: + +Privileges +---------- + +Administrative privileges for the Kerberos database are stored in the +file :ref:`kadm5.acl(5)`. + +.. note:: + + A common use of an admin instance is so you can grant + separate permissions (such as administrator access to the + Kerberos database) to a separate Kerberos principal. For + example, the user ``joeadmin`` might have a principal for + his administrative use, called ``joeadmin/admin``. This + way, ``joeadmin`` would obtain ``joeadmin/admin`` tickets + only when he actually needs to use those permissions. + + +.. _db_operations: + +Operations on the Kerberos database +----------------------------------- + +The :ref:`kdb5_util(8)` command is the primary tool for administrating +the Kerberos database when using the DB2 or LMDB modules (see +:ref:`dbtypes`). Creating a database is described in +:ref:`create_db`. + +To create a stash file using the master password (because the database +was not created with one using the ``create -s`` flag, or after +restoring from a backup which did not contain the stash file), use the +kdb5_util **stash** command:: + + $ kdb5_util stash + kdb5_util: Cannot find/read stored master key while reading master key + kdb5_util: Warning: proceeding without master key + Enter KDC database master key: <= Type the KDC database master password. + +To destroy a database, use the kdb5_util destroy command:: + + $ kdb5_util destroy + Deleting KDC database stored in '/var/krb5kdc/principal', are you sure? + (type 'yes' to confirm)? yes + OK, deleting database '/var/krb5kdc/principal'... + ** Database '/var/krb5kdc/principal' destroyed. + + +.. _restore_from_dump: + +Dumping and loading a Kerberos database +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To dump a Kerberos database into a text file for backup or transfer +purposes, use the :ref:`kdb5_util(8)` **dump** command on one of the +KDCs:: + + $ kdb5_util dump dumpfile + + $ kbd5_util dump -verbose dumpfile + kadmin/admin@ATHENA.MIT.EDU + krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU + kadmin/history@ATHENA.MIT.EDU + K/M@ATHENA.MIT.EDU + kadmin/changepw@ATHENA.MIT.EDU + +You may specify which principals to dump, using full principal names +including realm:: + + $ kdb5_util dump -verbose someprincs K/M@ATHENA.MIT.EDU kadmin/admin@ATHENA.MIT.EDU + kadmin/admin@ATHENA.MIT.EDU + K/M@ATHENA.MIT.EDU + +To restore a Kerberos database dump from a file, use the +:ref:`kdb5_util(8)` **load** command:: + + $ kdb5_util load dumpfile + +To update an existing database with a partial dump file containing +only some principals, use the ``-update`` flag:: + + $ kdb5_util load -update someprincs + +.. note:: + + If the database file exists, and the *-update* flag was not + given, *kdb5_util* will overwrite the existing database. + + +.. _updating_master_key: + +Updating the master key +~~~~~~~~~~~~~~~~~~~~~~~ + +Starting with release 1.7, :ref:`kdb5_util(8)` allows the master key +to be changed using a rollover process, with minimal loss of +availability. To roll over the master key, follow these steps: + +#. On the primary KDC, run ``kdb5_util list_mkeys`` to view the + current master key version number (KVNO). If you have never rolled + over the master key before, this will likely be version 1:: + + $ kdb5_util list_mkeys + Master keys for Principal: K/M@KRBTEST.COM + KVNO: 1, Enctype: aes256-cts-hmac-sha384-192, Active on: Thu Jan 01 00:00:00 UTC 1970 * + +#. On the primary KDC, run ``kdb5_util use_mkey 1`` to ensure that a + master key activation list is present in the database. This step + is unnecessary in release 1.11.4 or later, or if the database was + initially created with release 1.7 or later. + +#. On the primary KDC, run ``kdb5_util add_mkey -s`` to create a new + master key and write it to the stash file. Enter a secure password + when prompted. If this is the first time you are changing the + master key, the new key will have version 2. The new master key + will not be used until you make it active. + +#. Propagate the database to all replica KDCs, either manually or by + waiting until the next scheduled propagation. If you do not have + any replica KDCs, you can skip this and the next step. + +#. On each replica KDC, run ``kdb5_util list_mkeys`` to verify that + the new master key is present, and then ``kdb5_util stash`` to + write the new master key to the replica KDC's stash file. + +#. On the primary KDC, run ``kdb5_util use_mkey 2`` to begin using the + new master key. Replace ``2`` with the version of the new master + key, as appropriate. You can optionally specify a date for the new + master key to become active; by default, it will become active + immediately. Prior to release 1.12, :ref:`kadmind(8)` must be + restarted for this change to take full effect. + +#. On the primary KDC, run ``kdb5_util update_princ_encryption``. + This command will iterate over the database and re-encrypt all keys + in the new master key. If the database is large and uses DB2, the + primary KDC will become unavailable while this command runs, but + clients should fail over to replica KDCs (if any are present) + during this time period. In release 1.13 and later, you can + instead run ``kdb5_util -x unlockiter update_princ_encryption`` to + use unlocked iteration; this variant will take longer, but will + keep the database available to the KDC and kadmind while it runs. + +#. Wait until the above changes have propagated to all replica KDCs + and until all running KDC and kadmind processes have serviced + requests using updated principal entries. + +#. On the primary KDC, run ``kdb5_util purge_mkeys`` to clean up the + old master key. + + +.. _ops_on_ldap: + +Operations on the LDAP database +------------------------------- + +The :ref:`kdb5_ldap_util(8)` command is the primary tool for +administrating the Kerberos database when using the LDAP module. +Creating an LDAP Kerberos database is describe in :ref:`conf_ldap`. + +To view a list of realms in the LDAP database, use the kdb5_ldap_util +**list** command:: + + $ kdb5_ldap_util list + KRBTEST.COM + +To modify the attributes of a realm, use the kdb5_ldap_util **modify** +command. For example, to change the default realm's maximum ticket +life:: + + $ kdb5_ldap_util modify -maxtktlife "10 hours" + +To display the attributes of a realm, use the kdb5_ldap_util **view** +command:: + + $ kdb5_ldap_util view + Realm Name: KRBTEST.COM + Maximum Ticket Life: 0 days 00:10:00 + +To remove a realm from the LDAP database, destroying its contents, use +the kdb5_ldap_util **destroy** command:: + + $ kdb5_ldap_util destroy + Deleting KDC database of 'KRBTEST.COM', are you sure? + (type 'yes' to confirm)? yes + OK, deleting database of 'KRBTEST.COM'... + ** Database of 'KRBTEST.COM' destroyed. + + +Ticket Policy operations +~~~~~~~~~~~~~~~~~~~~~~~~ + +Unlike the DB2 and LMDB modules, the LDAP module supports ticket +policy objects, which can be associated with principals to restrict +maximum ticket lifetimes and set mandatory principal flags. Ticket +policy objects are distinct from the password policies described +earlier on this page, and are chiefly managed through kdb5_ldap_util +rather than kadmin. To create a new ticket policy, use the +kdb5_ldap_util **create_policy** command:: + + $ kdb5_ldap_util create_policy -maxrenewlife "2 days" users + +To associate a ticket policy with a principal, use the +:ref:`kadmin(1)` **modify_principal** (or **add_principal**) command +with the **-x tktpolicy=**\ *policy* option:: + + $ kadmin.local modprinc -x tktpolicy=users alice + +To remove a ticket policy reference from a principal, use the same +command with an empty *policy*:: + + $ kadmin.local modprinc -x tktpolicy= alice + +To list the existing ticket policy objects, use the kdb5_ldap_util +**list_policy** command:: + + $ kdb5_ldap_util list_policy + users + +To modify the attributes of a ticket policy object, use the +kdb5_ldap_util **modify_policy** command:: + + $ kdb5_ldap_util modify_policy -allow_svr +requires_preauth users + +To view the attributes of a ticket policy object, use the +kdb5_ldap_util **view_policy** command:: + + $ kdb5_ldap_util view_policy users + Ticket policy: users + Maximum renewable life: 2 days 00:00:00 + Ticket flags: REQUIRES_PRE_AUTH DISALLOW_SVR + +To destroy an ticket policy object, use the kdb5_ldap_util +**destroy_policy** command:: + + $ kdb5_ldap_util destroy_policy users + This will delete the policy object 'users', are you sure? + (type 'yes' to confirm)? yes + ** policy object 'users' deleted. + + +.. _xrealm_authn: + +Cross-realm authentication +-------------------------- + +In order for a KDC in one realm to authenticate Kerberos users in a +different realm, it must share a key with the KDC in the other realm. +In both databases, there must be krbtgt service principals for both realms. +For example, if you need to do cross-realm authentication between the realms +``ATHENA.MIT.EDU`` and ``EXAMPLE.COM``, you would need to add the +principals ``krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU`` and +``krbtgt/ATHENA.MIT.EDU@EXAMPLE.COM`` to both databases. +These principals must all have the same passwords, key version +numbers, and encryption types; this may require explicitly setting +the key version number with the **-kvno** option. + +In the ATHENA.MIT.EDU and EXAMPLE.COM cross-realm case, the administrators +would run the following commands on the KDCs in both realms:: + + shell%: kadmin.local -e "aes256-cts:normal" + kadmin: addprinc -requires_preauth krbtgt/ATHENA.MIT.EDU@EXAMPLE.COM + Enter password for principal krbtgt/ATHENA.MIT.EDU@EXAMPLE.COM: + Re-enter password for principal krbtgt/ATHENA.MIT.EDU@EXAMPLE.COM: + kadmin: addprinc -requires_preauth krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU + Enter password for principal krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU: + Enter password for principal krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU: + kadmin: + +.. note:: + + Even if most principals in a realm are generally created + with the **requires_preauth** flag enabled, this flag is not + desirable on cross-realm authentication keys because doing + so makes it impossible to disable preauthentication on a + service-by-service basis. Disabling it as in the example + above is recommended. + +.. note:: + + It is very important that these principals have good + passwords. MIT recommends that TGT principal passwords be + at least 26 characters of random ASCII text. + + +.. _changing_krbtgt_key: + +Changing the krbtgt key +----------------------- + +A Kerberos Ticket Granting Ticket (TGT) is a service ticket for the +principal ``krbtgt/REALM``. The key for this principal is created +when the Kerberos database is initialized and need not be changed. +However, it will only have the encryption types supported by the KDC +at the time of the initial database creation. To allow use of newer +encryption types for the TGT, this key has to be changed. + +Changing this key using the normal :ref:`kadmin(1)` +**change_password** command would invalidate any previously issued +TGTs. Therefore, when changing this key, normally one should use the +**-keepold** flag to change_password to retain the previous key in the +database as well as the new key. For example:: + + kadmin: change_password -randkey -keepold krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU + +.. warning:: + + After issuing this command, the old key is still valid + and is still vulnerable to (for instance) brute force + attacks. To completely retire an old key or encryption + type, run the kadmin **purgekeys** command to delete keys + with older kvnos, ideally first making sure that all + tickets issued with the old keys have expired. + +Only the first krbtgt key of the newest key version is used to encrypt +ticket-granting tickets. However, the set of encryption types present +in the krbtgt keys is used by default to determine the session key +types supported by the krbtgt service (see +:ref:`session_key_selection`). Because non-MIT Kerberos clients +sometimes send a limited set of encryption types when making AS +requests, it can be important for the krbtgt service to support +multiple encryption types. This can be accomplished by giving the +krbtgt principal multiple keys, which is usually as simple as not +specifying any **-e** option when changing the krbtgt key, or by +setting the **session_enctypes** string attribute on the krbtgt +principal (see :ref:`set_string`). + +Due to a bug in releases 1.8 through 1.13, renewed and forwarded +tickets may not work if the original ticket was obtained prior to a +krbtgt key change and the modified ticket is obtained afterwards. +Upgrading the KDC to release 1.14 or later will correct this bug. + + +.. _incr_db_prop: + +Incremental database propagation +-------------------------------- + +Overview +~~~~~~~~ + +At some very large sites, dumping and transmitting the database can +take more time than is desirable for changes to propagate from the +primary KDC to the replica KDCs. The incremental propagation support +added in the 1.7 release is intended to address this. + +With incremental propagation enabled, all programs on the primary KDC +that change the database also write information about the changes to +an "update log" file, maintained as a circular buffer of a certain +size. A process on each replica KDC connects to a service on the +primary KDC (currently implemented in the :ref:`kadmind(8)` server) and +periodically requests the changes that have been made since the last +check. By default, this check is done every two minutes. + +Incremental propagation uses the following entries in the per-realm +data in the KDC config file (See :ref:`kdc.conf(5)`): + +====================== =============== =========================================== +iprop_enable *boolean* If *true*, then incremental propagation is enabled, and (as noted below) normal kprop propagation is disabled. The default is *false*. +iprop_master_ulogsize *integer* Indicates the number of entries that should be retained in the update log. The default is 1000; the maximum number is 2500. +iprop_replica_poll *time interval* Indicates how often the replica should poll the primary KDC for changes to the database. The default is two minutes. +iprop_port *integer* Specifies the port number to be used for incremental propagation. This is required in both primary and replica configuration files. +iprop_resync_timeout *integer* Specifies the number of seconds to wait for a full propagation to complete. This is optional on replica configurations. Defaults to 300 seconds (5 minutes). +iprop_logfile *file name* Specifies where the update log file for the realm database is to be stored. The default is to use the *database_name* entry from the realms section of the config file :ref:`kdc.conf(5)`, with *.ulog* appended. (NOTE: If database_name isn't specified in the realms section, perhaps because the LDAP database back end is being used, or the file name is specified in the *dbmodules* section, then the hard-coded default for *database_name* is used. Determination of the *iprop_logfile* default value will not use values from the *dbmodules* section.) +====================== =============== =========================================== + +Both primary and replica sides must have a principal named +``kiprop/hostname`` (where *hostname* is the lowercase, +fully-qualified, canonical name for the host) registered in the +Kerberos database, and have keys for that principal stored in the +default keytab file (|keytab|). The ``kiprop/hostname`` principal may +have been created automatically for the primary KDC, but it must +always be created for replica KDCs. + +On the primary KDC side, the ``kiprop/hostname`` principal must be +listed in the kadmind ACL file :ref:`kadm5.acl(5)`, and given the +**p** privilege (see :ref:`privileges`). + +On the replica KDC side, :ref:`kpropd(8)` should be run. When +incremental propagation is enabled, it will connect to the kadmind on +the primary KDC and start requesting updates. + +The normal kprop mechanism is disabled by the incremental propagation +support. However, if the replica has been unable to fetch changes +from the primary KDC for too long (network problems, perhaps), the log +on the primary may wrap around and overwrite some of the updates that +the replica has not yet retrieved. In this case, the replica will +instruct the primary KDC to dump the current database out to a file +and invoke a one-time kprop propagation, with special options to also +convey the point in the update log at which the replica should resume +fetching incremental updates. Thus, all the keytab and ACL setup +previously described for kprop propagation is still needed. + +If an environment has a large number of replicas, it may be desirable +to arrange them in a hierarchy instead of having the primary serve +updates to every replica. To do this, run ``kadmind -proponly`` on +each intermediate replica, and ``kpropd -A upstreamhostname`` on +downstream replicas to direct each one to the appropriate upstream +replica. + +There are several known restrictions in the current implementation: + +- The incremental update protocol does not transport changes to policy + objects. Any policy changes on the primary will result in full + resyncs to all replicas. +- The replica's KDB module must support locking; it cannot be using the + LDAP KDB module. +- The primary and replica must be able to initiate TCP connections in + both directions, without an intervening NAT. + + +Sun/MIT incremental propagation differences +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sun donated the original code for supporting incremental database +propagation to MIT. Some changes have been made in the MIT source +tree that will be visible to administrators. (These notes are based +on Sun's patches. Changes to Sun's implementation since then may not +be reflected here.) + +The Sun config file support looks for ``sunw_dbprop_enable``, +``sunw_dbprop_master_ulogsize``, and ``sunw_dbprop_slave_poll``. + +The incremental propagation service is implemented as an ONC RPC +service. In the Sun implementation, the service is registered with +rpcbind (also known as portmapper) and the client looks up the port +number to contact. In the MIT implementation, where interaction with +some modern versions of rpcbind doesn't always work well, the port +number must be specified in the config file on both the primary and +replica sides. + +The Sun implementation hard-codes pathnames in ``/var/krb5`` for the +update log and the per-replica kprop dump files. In the MIT +implementation, the pathname for the update log is specified in the +config file, and the per-replica dump files are stored in +|kdcdir|\ ``/replica_datatrans_hostname``. diff --git a/krb5-1.21.3/doc/admin/dbtypes.rst b/krb5-1.21.3/doc/admin/dbtypes.rst new file mode 100644 index 00000000..04748176 --- /dev/null +++ b/krb5-1.21.3/doc/admin/dbtypes.rst @@ -0,0 +1,149 @@ +.. _dbtypes: + +Database types +============== + +A Kerberos database can be implemented with one of three built-in +database providers, called KDB modules. Software which incorporates +the MIT krb5 KDC may also provide its own KDB module. The following +subsections describe the three built-in KDB modules and the +configuration specific to them. + +The database type can be configured with the **db_library** variable +in the :ref:`dbmodules` subsection for the realm. For example:: + + [dbmodules] + ATHENA.MIT.EDU = { + db_library = db2 + } + +If the ``ATHENA.MIT.EDU`` realm subsection contains a +**database_module** setting, then the subsection within +``[dbmodules]`` should use that name instead of ``ATHENA.MIT.EDU``. + +To transition from one database type to another, stop the +:ref:`kadmind(8)` service, use ``kdb5_util dump`` to create a dump +file, change the **db_library** value and set any appropriate +configuration for the new database type, and use ``kdb5_util load`` to +create and populate the new database. If the new database type is +LDAP, create the new database using ``kdb5_ldap_util`` and populate it +from the dump file using ``kdb5_util load -update``. Then restart the +:ref:`krb5kdc(8)` and :ref:`kadmind(8)` services. + + +Berkeley database module (db2) +------------------------------ + +The default KDB module is ``db2``, which uses a version of the +Berkeley DB library. It creates four files based on the database +pathname. If the pathname ends with ``principal`` then the four files +are: + +* ``principal``, containing principal entry data +* ``principal.ok``, a lock file for the principal database +* ``principal.kadm5``, containing policy object data +* ``principal.kadm5.lock``, a lock file for the policy database + +For large databases, the :ref:`kdb5_util(8)` **dump** command (perhaps +invoked by :ref:`kprop(8)` or by :ref:`kadmind(8)` for incremental +propagation) may cause :ref:`krb5kdc(8)` to stop for a noticeable +period of time while it iterates over the database. This delay can be +avoided by disabling account lockout features so that the KDC does not +perform database writes (see :ref:`disable_lockout`). Alternatively, +a slower form of iteration can be enabled by setting the +**unlockiter** variable to ``true``. For example:: + + [dbmodules] + ATHENA.MIT.EDU = { + db_library = db2 + unlockiter = true + } + +In rare cases, a power failure or other unclean system shutdown may +cause inconsistencies in the internal pointers within a database file, +such that ``kdb5_util dump`` cannot retrieve all principal entries in +the database. In this situation, it may be possible to retrieve all +of the principal data by running ``kdb5_util dump -recurse`` to +iterate over the database using the tree pointers instead of the +iteration pointers. Running ``kdb5_util dump -rev`` to iterate over +the database backwards may also retrieve some of the data which is not +retrieved by a normal dump operation. + + +Lightning Memory-Mapped Database module (klmdb) +----------------------------------------------- + +The klmdb module was added in release 1.17. It uses the LMDB library, +and may offer better performance and reliability than the db2 module. +It creates four files based on the database pathname. If the pathname +ends with ``principal``, then the four files are: + +* ``principal.mdb``, containing policy object data and most principal + entry data +* ``principal.mdb-lock``, a lock file for the primary database +* ``principal.lockout.mdb``, containing the account lockout attributes + (last successful authentication time, last failed authentication + time, and number of failed attempts) for each principal entry +* ``principal.lockout.mdb-lock``, a lock file for the lockout database + +Separating out the lockout attributes ensures that the KDC will never +block on an administrative operation such as a database dump or load. +It also allows the KDC to operate without write access to the primary +database. If both account lockout features are disabled (see +:ref:`disable_lockout`), the lockout database files will be created +but will not subsequently be opened, and the account lockout +attributes will always have zero values. + +Because LMDB creates a memory map to the database files, it requires a +configured memory map size which also determines the maximum size of +the database. This size is applied equally to the two databases, so +twice the configured size will be consumed in the process address +space; this is primarily a limitation on 32-bit platforms. The +default value of 128 megabytes should be sufficient for several +hundred thousand principal entries. If the limit is reached, kadmin +operations will fail and the error message "Environment mapsize limit +reached" will appear in the kadmind log file. In this case, the +**mapsize** variable can be used to increase the map size. The +following example sets the map size to 512 megabytes:: + + [dbmodules] + ATHENA.MIT.EDU = { + db_library = klmdb + mapsize = 512 + } + +LMDB has a configurable maximum number of readers. The default value +of 128 should be sufficient for most deployments. If you are going to +use a large number of KDC worker processes, it may be necessary to set +the **max_readers** variable to a larger number. + +By default, LMDB synchronizes database files to disk after each write +transaction to ensure durability in the case of an unclean system +shutdown. The klmdb module always turns synchronization off for the +lockout database to ensure reasonable KDC performance, but leaves it +on for the primary database. If high throughput for administrative +operations (including password changes) is required, the **nosync** +variable can be set to "true" to disable synchronization for the +primary database. + +The klmdb module does not support explicit locking with the +:ref:`kadmin(1)` **lock** command. + + +LDAP module (kldap) +------------------- + +The kldap module stores principal and policy data using an LDAP +server. To use it you must configure an LDAP server to use the +Kerberos schema. See :ref:`conf_ldap` for details. + +Because :ref:`krb5kdc(8)` is single-threaded, latency in LDAP database +accesses may limit KDC operation throughput. If the LDAP server is +located on the same server host as the KDC and accessed through an +``ldapi://`` URL, latency should be minimal. If this is not possible, +consider starting multiple KDC worker processes with the +:ref:`krb5kdc(8)` **-w** option to enable concurrent processing of KDC +requests. + +The kldap module does not support explicit locking with the +:ref:`kadmin(1)` **lock** command. diff --git a/krb5-1.21.3/doc/admin/dictionary.rst b/krb5-1.21.3/doc/admin/dictionary.rst new file mode 100644 index 00000000..a5c57868 --- /dev/null +++ b/krb5-1.21.3/doc/admin/dictionary.rst @@ -0,0 +1,88 @@ +.. _dictionary: + +Addressing dictionary attack risks +================================== + +Kerberos initial authentication is normally secured using the client +principal's long-term key, which for users is generally derived from a +password. Using a pasword-derived long-term key carries the risk of a +dictionary attack, where an attacker tries a sequence of possible +passwords, possibly requiring much less effort than would be required +to try all possible values of the key. Even if :ref:`password policy +objects ` are used to force users not to pick trivial +passwords, dictionary attacks can sometimes be successful against a +significant fraction of the users in a realm. Dictionary attacks are +not a concern for principals using random keys. + +A dictionary attack may be online or offline. An online dictionary +attack is performed by trying each password in a separate request to +the KDC, and is therefore visible to the KDC and also limited in speed +by the KDC's processing power and the network capacity between the +client and the KDC. Online dictionary attacks can be mitigated using +:ref:`account lockout `. This measure is not totally +satisfactory, as it makes it easy for an attacker to deny access to a +client principal. + +An offline dictionary attack is performed by obtaining a ciphertext +generated using the password-derived key, and trying each password +against the ciphertext. This category of attack is invisible to the +KDC and can be performed much faster than an online attack. The +attack will generally take much longer with more recent encryption +types (particularly the ones based on AES), because those encryption +types use a much more expensive string-to-key function. However, the +best defense is to deny the attacker access to a useful ciphertext. +The required defensive measures depend on the attacker's level of +network access. + +An off-path attacker has no access to packets sent between legitimate +users and the KDC. An off-path attacker could gain access to an +attackable ciphertext either by making an AS request for a client +principal which does not have the **+requires_preauth** flag, or by +making a TGS request (after authenticating as a different user) for a +server principal which does not have the **-allow_svr** flag. To +address off-path attackers, a KDC administrator should set those flags +on principals with password-derived keys:: + + kadmin: add_principal +requires_preauth -allow_svr princname + +An attacker with passive network access (one who can monitor packets +sent between legitimate users and the KDC, but cannot change them or +insert their own packets) can gain access to an attackable ciphertext +by observing an authentication by a user using the most common form of +preauthentication, encrypted timestamp. Any of the following methods +can prevent dictionary attacks by attackers with passive network +access: + +* Enabling :ref:`SPAKE preauthentication ` (added in release + 1.17) on the KDC, and ensuring that all clients are able to support + it. + +* Using an :ref:`HTTPS proxy ` for communication with the KDC, + if the attacker cannot monitor communication between the proxy + server and the KDC. + +* Using FAST, protecting the initial authentication with either a + random key (such as a host key) or with :ref:`anonymous PKINIT + `. + +An attacker with active network access (one who can inject or modify +packets sent between legitimate users and the KDC) can try to fool the +client software into sending an attackable ciphertext using an +encryption type and salt string of the attacker's choosing. Any of the +following methods can prevent dictionary attacks by active attackers: + +* Enabling SPAKE preauthentication and setting the + **disable_encrypted_timestamp** variable to ``true`` in the + :ref:`realms` subsection of the client configuration. + +* Using an HTTPS proxy as described above, configured in the client's + krb5.conf realm configuration. If :ref:`KDC discovery + ` is used to locate a proxy server, an active + attacker may be able to use DNS spoofing to cause the client to use + a different HTTPS server or to not use HTTPS. + +* Using FAST as described above. + +If :ref:`PKINIT ` or :ref:`OTP ` are used for +initial authentication, the principal's long-term keys are not used +and dictionary attacks are usually not a concern. diff --git a/krb5-1.21.3/doc/admin/enctypes.rst b/krb5-1.21.3/doc/admin/enctypes.rst new file mode 100644 index 00000000..dce19ad4 --- /dev/null +++ b/krb5-1.21.3/doc/admin/enctypes.rst @@ -0,0 +1,222 @@ +.. _enctypes: + +Encryption types +================ + +Kerberos can use a variety of cipher algorithms to protect data. A +Kerberos **encryption type** (also known as an **enctype**) is a +specific combination of a cipher algorithm with an integrity algorithm +to provide both confidentiality and integrity to data. + + +Enctypes in requests +-------------------- + +Clients make two types of requests (KDC-REQ) to the KDC: AS-REQs and +TGS-REQs. The client uses the AS-REQ to obtain initial tickets +(typically a Ticket-Granting Ticket (TGT)), and uses the TGS-REQ to +obtain service tickets. + +The KDC uses three different keys when issuing a ticket to a client: + +* The long-term key of the service: the KDC uses this to encrypt the + actual service ticket. The KDC only uses the first long-term key in + the most recent kvno for this purpose. + +* The session key: the KDC randomly chooses this key and places one + copy inside the ticket and the other copy inside the encrypted part + of the reply. + +* The reply-encrypting key: the KDC uses this to encrypt the reply it + sends to the client. For AS replies, this is a long-term key of the + client principal. For TGS replies, this is either the session key of the + authenticating ticket, or a subsession key. + +Each of these keys is of a specific enctype. + +Each request type allows the client to submit a list of enctypes that +it is willing to accept. For the AS-REQ, this list affects both the +session key selection and the reply-encrypting key selection. For the +TGS-REQ, this list only affects the session key selection. + + +.. _session_key_selection: + +Session key selection +--------------------- + +The KDC chooses the session key enctype by taking the intersection of +its **permitted_enctypes** list, the list of long-term keys for the +most recent kvno of the service, and the client's requested list of +enctypes. Starting in krb5-1.21, all services are assumed to support +aes256-cts-hmac-sha1-96; also, des3-cbc-sha1 and arcfour-hmac session +keys will not be issued by default. + +Starting in krb5-1.11, it is possible to set a string attribute on a +service principal to control what session key enctypes the KDC may +issue for service tickets for that principal, overriding the service's +long-term keys and the assumption of aes256-cts-hmac-sha1-96 support. +See :ref:`set_string` in :ref:`kadmin(1)` for details. + + +Choosing enctypes for a service +------------------------------- + +Generally, a service should have a key of the strongest +enctype that both it and the KDC support. If the KDC is running a +release earlier than krb5-1.11, it is also useful to generate an +additional key for each enctype that the service can support. The KDC +will only use the first key in the list of long-term keys for encrypting +the service ticket, but the additional long-term keys indicate the +other enctypes that the service supports. + +As noted above, starting with release krb5-1.11, there are additional +configuration settings that control session key enctype selection +independently of the set of long-term keys that the KDC has stored for +a service principal. + + +Configuration variables +----------------------- + +The following ``[libdefaults]`` settings in :ref:`krb5.conf(5)` will +affect how enctypes are chosen. + +**allow_weak_crypto** + defaults to *false* starting with krb5-1.8. When *false*, removes + weak enctypes from **permitted_enctypes**, + **default_tkt_enctypes**, and **default_tgs_enctypes**. Do not + set this to *true* unless the use of weak enctypes is an + acceptable risk for your environment and the weak enctypes are + required for backward compatibility. + +**allow_des3** + was added in release 1.21 and defaults to *false*. Unless this + flag is set to *true*, the KDC will not issue tickets with + des3-cbc-sha1 session keys. In a future release, this flag will + control whether des3-cbc-sha1 is permitted in similar fashion to + weak enctypes. + +**allow_rc4** + was added in release 1.21 and defaults to *false*. Unless this + flag is set to *true*, the KDC will not issue tickets with + arcfour-hmac session keys. In a future release, this flag will + control whether arcfour-hmac is permitted in similar fashion to + weak enctypes. + +**permitted_enctypes** + controls the set of enctypes that a service will permit for + session keys and for ticket and authenticator encryption. The KDC + and other programs that access the Kerberos database will ignore + keys of non-permitted enctypes. Starting in release 1.18, this + setting also acts as the default for **default_tkt_enctypes** and + **default_tgs_enctypes**. + +**default_tkt_enctypes** + controls the default set of enctypes that the Kerberos client + library requests when making an AS-REQ. Do not set this unless + required for specific backward compatibility purposes; stale + values of this setting can prevent clients from taking advantage + of new stronger enctypes when the libraries are upgraded. + +**default_tgs_enctypes** + controls the default set of enctypes that the Kerberos client + library requests when making a TGS-REQ. Do not set this unless + required for specific backward compatibility purposes; stale + values of this setting can prevent clients from taking advantage + of new stronger enctypes when the libraries are upgraded. + +The following per-realm setting in :ref:`kdc.conf(5)` affects the +generation of long-term keys. + +**supported_enctypes** + controls the default set of enctype-salttype pairs that :ref:`kadmind(8)` + will use for generating long-term keys, either randomly or from + passwords + + +Enctype compatibility +--------------------- + +See :ref:`Encryption_types` for additional information about enctypes. + +========================== ========== ======== ======= +enctype weak? krb5 Windows +========================== ========== ======== ======= +des-cbc-crc weak <1.18 >=2000 +des-cbc-md4 weak <1.18 ? +des-cbc-md5 weak <1.18 >=2000 +des3-cbc-sha1 deprecated >=1.1 none +arcfour-hmac deprecated >=1.3 >=2000 +arcfour-hmac-exp weak >=1.3 >=2000 +aes128-cts-hmac-sha1-96 >=1.3 >=Vista +aes256-cts-hmac-sha1-96 >=1.3 >=Vista +aes128-cts-hmac-sha256-128 >=1.15 none +aes256-cts-hmac-sha384-192 >=1.15 none +camellia128-cts-cmac >=1.9 none +camellia256-cts-cmac >=1.9 none +========================== ========== ======== ======= + +krb5 releases 1.18 and later do not support single-DES. krb5 releases +1.8 and later disable the single-DES enctypes by default. Microsoft +Windows releases Windows 7 and later disable single-DES enctypes by +default. + +krb5 releases 1.17 and later flag deprecated encryption types +(including ``des3-cbc-sha1`` and ``arcfour-hmac``) in KDC logs and +kadmin output. krb5 release 1.19 issues a warning during initial +authentication if ``des3-cbc-sha1`` is used. Future releases will +disable ``des3-cbc-sha1`` by default and eventually remove support for +it. + + +Migrating away from older encryption types +------------------------------------------ + +Administrator intervention may be required to migrate a realm away +from legacy encryption types, especially if the realm was created +using krb5 release 1.2 or earlier. This migration should be performed +before upgrading to krb5 versions which disable or remove support for +legacy encryption types. + +If there is a **supported_enctypes** setting in :ref:`kdc.conf(5)` on +the KDC, make sure that it does not include weak or deprecated +encryption types. This will ensure that newly created keys do not use +those encryption types by default. + +Check the ``krbtgt/REALM`` principal using the :ref:`kadmin(1)` +**getprinc** command. If it lists a weak or deprecated encryption +type as the first key, it must be migrated using the procedure in +:ref:`changing_krbtgt_key`. + +Check the ``kadmin/history`` principal, which should have only one key +entry. If it uses a weak or deprecated encryption type, it should be +upgraded following the notes in :ref:`updating_history_key`. + +Check the other kadmin principals: kadmin/changepw, kadmin/admin, and +any kadmin/hostname principals that may exist. These principals can +be upgraded with **change_password -randkey** in kadmin. + +Check the ``K/M`` entry. If it uses a weak or deprecated encryption +type, it should be upgraded following the procedure in +:ref:`updating_master_key`. + +User and service principals using legacy encryption types can be +enumerated with the :ref:`kdb5_util(8)` **tabdump keyinfo** command. + +Service principals can be migrated with a keytab rotation on the +service host, which can be accomplished using the :ref:`k5srvutil(1)` +**change** and **delold** commands. Allow enough time for existing +tickets to expire between the change and delold operations. + +User principals with password-based keys can be migrated with a +password change. The realm administrator can set a password +expiration date using the :ref:`kadmin(1)` **modify_principal +-pwexpire** command to force a password change. + +If a legacy encryption type has not yet been disabled by default in +the version of krb5 running on the KDC, it can be disabled +administratively with the **permitted_enctypes** variable. For +example, setting **permitted_enctypes** to ``DEFAULT -des3 -rc4`` will +cause any database keys of the triple-DES and RC4 encryption types to +be ignored. diff --git a/krb5-1.21.3/doc/admin/env_variables.rst b/krb5-1.21.3/doc/admin/env_variables.rst new file mode 100644 index 00000000..a2d15bea --- /dev/null +++ b/krb5-1.21.3/doc/admin/env_variables.rst @@ -0,0 +1,4 @@ +Environment variables +===================== + +This content has moved to :ref:`kerberos(7)`. diff --git a/krb5-1.21.3/doc/admin/host_config.rst b/krb5-1.21.3/doc/admin/host_config.rst new file mode 100644 index 00000000..4e1db025 --- /dev/null +++ b/krb5-1.21.3/doc/admin/host_config.rst @@ -0,0 +1,235 @@ +Host configuration +================== + +All hosts running Kerberos software, whether they are clients, +application servers, or KDCs, can be configured using +:ref:`krb5.conf(5)`. Here we describe some of the behavior changes +you might want to make. + + +Default realm +------------- + +In the :ref:`libdefaults` section, the **default_realm** realm +relation sets the default Kerberos realm. For example:: + + [libdefaults] + default_realm = ATHENA.MIT.EDU + +The default realm affects Kerberos behavior in the following ways: + +* When a principal name is parsed from text, the default realm is used + if no ``@REALM`` component is specified. + +* The default realm affects login authorization as described below. + +* For programs which operate on a Kerberos database, the default realm + is used to determine which database to operate on, unless the **-r** + parameter is given to specify a realm. + +* A server program may use the default realm when looking up its key + in a :ref:`keytab file `, if its realm is not + determined by :ref:`domain_realm` configuration or by the server + program itself. + +* If :ref:`kinit(1)` is passed the **-n** flag, it requests anonymous + tickets from the default realm. + +In some situations, these uses of the default realm might conflict. +For example, it might be desirable for principal name parsing to use +one realm by default, but for login authorization to use a second +realm. In this situation, the first realm can be configured as the +default realm, and **auth_to_local** relations can be used as +described below to use the second realm for login authorization. + + +.. _login_authorization: + +Login authorization +------------------- + +If a host runs a Kerberos-enabled login service such as OpenSSH with +GSSAPIAuthentication enabled, login authorization rules determine +whether a Kerberos principal is allowed to access a local account. + +By default, a Kerberos principal is allowed access to an account if +its realm matches the default realm and its name matches the account +name. (For historical reasons, access is also granted by default if +the name has two components and the second component matches the +default realm; for instance, ``alice/ATHENA.MIT.EDU@ATHENA.MIT.EDU`` +is granted access to the ``alice`` account if ``ATHENA.MIT.EDU`` is +the default realm.) + +The simplest way to control local access is using :ref:`.k5login(5)` +files. To use these, place a ``.k5login`` file in the home directory +of each account listing the principal names which should have login +access to that account. If it is not desirable to use ``.k5login`` +files located in account home directories, the **k5login_directory** +relation in the :ref:`libdefaults` section can specify a directory +containing one file per account uname. + +By default, if a ``.k5login`` file is present, it controls +authorization both positively and negatively--any principal name +contained in the file is granted access and any other principal name +is denied access, even if it would have had access if the ``.k5login`` +file didn't exist. The **k5login_authoritative** relation in the +:ref:`libdefaults` section can be set to false to make ``.k5login`` +files provide positive authorization only. + +The **auth_to_local** relation in the :ref:`realms` section for the +default realm can specify pattern-matching rules to control login +authorization. For example, the following configuration allows access +to principals from a different realm than the default realm:: + + [realms] + DEFAULT.REALM = { + # Allow access to principals from OTHER.REALM. + # + # [1:$1@$0] matches single-component principal names and creates + # a selection string containing the principal name and realm. + # + # (.*@OTHER\.REALM) matches against the selection string, so that + # only principals in OTHER.REALM are matched. + # + # s/@OTHER\.REALM$// removes the realm name, leaving behind the + # principal name as the account name. + auth_to_local = RULE:[1:$1@$0](.*@OTHER\.REALM)s/@OTHER\.REALM$// + + # Also allow principals from the default realm. Omit this line + # to only allow access to principals in OTHER.REALM. + auth_to_local = DEFAULT + } + +The **auth_to_local_names** subsection of the :ref:`realms` section +for the default realm can specify explicit mappings from principal +names to local accounts. The key used in this subsection is the +principal name without realm, so it is only safe to use in a Kerberos +environment with a single realm or a tightly controlled set of realms. +An example use of **auth_to_local_names** might be:: + + [realms] + ATHENA.MIT.EDU = { + auth_to_local_names = { + # Careful, these match principals in any realm! + host/example.com = hostaccount + fred = localfred + } + } + +Local authorization behavior can also be modified using plugin +modules; see :ref:`hostrealm_plugin` for details. + + +.. _plugin_config: + +Plugin module configuration +--------------------------- + +Many aspects of Kerberos behavior, such as client preauthentication +and KDC service location, can be modified through the use of plugin +modules. For most of these behaviors, you can use the :ref:`plugins` +section of krb5.conf to register third-party modules, and to switch +off registered or built-in modules. + +A plugin module takes the form of a Unix shared object +(``modname.so``) or Windows DLL (``modname.dll``). If you have +installed a third-party plugin module and want to register it, you do +so using the **module** relation in the appropriate subsection of the +[plugins] section. The value for **module** must give the module name +and the path to the module, separated by a colon. The module name +will often be the same as the shared object's name, but in unusual +cases (such as a shared object which implements multiple modules for +the same interface) it might not be. For example, to register a +client preauthentication module named ``mypreauth`` installed at +``/path/to/mypreauth.so``, you could write:: + + [plugins] + clpreauth = { + module = mypreauth:/path/to/mypreauth.so + } + +Many of the pluggable behaviors in MIT krb5 contain built-in modules +which can be switched off. You can disable a built-in module (or one +you have registered) using the **disable** directive in the +appropriate subsection of the [plugins] section. For example, to +disable the use of .k5identity files to select credential caches, you +could write:: + + [plugins] + ccselect = { + disable = k5identity + } + +If you want to disable multiple modules, specify the **disable** +directive multiple times, giving one module to disable each time. + +Alternatively, you can explicitly specify which modules you want to be +enabled for that behavior using the **enable_only** directive. For +example, to make :ref:`kadmind(8)` check password quality using only a +module you have registered, and no other mechanism, you could write:: + + [plugins] + pwqual = { + module = mymodule:/path/to/mymodule.so + enable_only = mymodule + } + +Again, if you want to specify multiple modules, specify the +**enable_only** directive multiple times, giving one module to enable +each time. + +Some Kerberos interfaces use different mechanisms to register plugin +modules. + + +KDC location modules +~~~~~~~~~~~~~~~~~~~~ + +For historical reasons, modules to control how KDC servers are located +are registered simply by placing the shared object or DLL into the +"libkrb5" subdirectory of the krb5 plugin directory, which defaults to +|libdir|\ ``/krb5/plugins``. For example, Samba's winbind krb5 +locator plugin would be registered by placing its shared object in +|libdir|\ ``/krb5/plugins/libkrb5/winbind_krb5_locator.so``. + + +.. _gssapi_plugin_config: + +GSSAPI mechanism modules +~~~~~~~~~~~~~~~~~~~~~~~~ + +GSSAPI mechanism modules are registered using the file +|sysconfdir|\ ``/gss/mech`` or configuration files in the +|sysconfdir|\ ``/gss/mech.d`` directory with a ``.conf`` +suffix. Each line in these files has the form:: + + name oid pathname [options] + +Only the name, oid, and pathname are required. *name* is the +mechanism name, which may be used for debugging or logging purposes. +*oid* is the object identifier of the GSSAPI mechanism to be +registered. *pathname* is a path to the module shared object or DLL. +*options* (if present) are options provided to the plugin module, +surrounded in square brackets. *type* (if present) can be used to +indicate a special type of module. Currently the only special module +type is "interposer", for a module designed to intercept calls to +other mechanisms. + +If the environment variable **GSS_MECH_CONFIG** is set, its value is +used as the sole mechanism configuration filename. + + +.. _profile_plugin_config: + +Configuration profile modules +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A configuration profile module replaces the information source for +:ref:`krb5.conf(5)` itself. To use a profile module, begin krb5.conf +with the line:: + + module PATHNAME:STRING + +where *PATHNAME* is a path to the module shared object or DLL, and +*STRING* is a string to provide to the module. The module will then +take over, and the rest of krb5.conf will be ignored. diff --git a/krb5-1.21.3/doc/admin/https.rst b/krb5-1.21.3/doc/admin/https.rst new file mode 100644 index 00000000..b4e68b2b --- /dev/null +++ b/krb5-1.21.3/doc/admin/https.rst @@ -0,0 +1,48 @@ +.. _https: + +HTTPS proxy configuration +========================= + +In addition to being able to use UDP or TCP to communicate directly +with a KDC as is outlined in RFC4120, and with kpasswd services in a +similar fashion, the client libraries can attempt to use an HTTPS +proxy server to communicate with a KDC or kpasswd service, using the +protocol outlined in [MS-KKDCP]. + +Communicating with a KDC through an HTTPS proxy allows clients to +contact servers when network firewalls might otherwise prevent them +from doing so. The use of TLS also encrypts all traffic between the +clients and the KDC, preventing observers from conducting password +dictionary attacks or from observing the client and server principals +being authenticated, at additional computational cost to both clients +and servers. + +An HTTPS proxy server is provided as a feature in some versions of +Microsoft Windows Server, and a WSGI implementation named `kdcproxy` +is available in the python package index. + + +Configuring the clients +----------------------- + +To use an HTTPS proxy, a client host must trust the CA which issued +that proxy's SSL certificate. If that CA's certificate is not in the +system-wide default set of trusted certificates, configure the +following relation in the client host's :ref:`krb5.conf(5)` file in +the appropriate :ref:`realms` subsection:: + + http_anchors = FILE:/etc/krb5/cacert.pem + +Adjust the pathname to match the path of the file which contains a +copy of the CA's certificate. The `http_anchors` option is documented +more fully in :ref:`krb5.conf(5)`. + +Configure the client to access the KDC and kpasswd service by +specifying their locations in its :ref:`krb5.conf(5)` file in the form +of HTTPS URLs for the proxy server:: + + kdc = https://server.fqdn/KdcProxy + kpasswd_server = https://server.fqdn/KdcProxy + +If the proxy and client are properly configured, client commands such +as ``kinit``, ``kvno``, and ``kpasswd`` should all function normally. diff --git a/krb5-1.21.3/doc/admin/index.rst b/krb5-1.21.3/doc/admin/index.rst new file mode 100644 index 00000000..d87b003a --- /dev/null +++ b/krb5-1.21.3/doc/admin/index.rst @@ -0,0 +1,34 @@ +For administrators +================== + +.. toctree:: + :maxdepth: 1 + + install.rst + conf_files/index.rst + realm_config.rst + database.rst + dbtypes.rst + lockout.rst + conf_ldap.rst + appl_servers.rst + host_config.rst + backup_host.rst + pkinit.rst + otp.rst + spake.rst + dictionary.rst + princ_dns.rst + enctypes.rst + https.rst + auth_indicator.rst + +.. toctree:: + :maxdepth: 1 + + admin_commands/index.rst + ../mitK5defaults.rst + env_variables.rst + troubleshoot.rst + advanced/index.rst + various_envs.rst diff --git a/krb5-1.21.3/doc/admin/install.rst b/krb5-1.21.3/doc/admin/install.rst new file mode 100644 index 00000000..01434a40 --- /dev/null +++ b/krb5-1.21.3/doc/admin/install.rst @@ -0,0 +1,21 @@ +Installation guide +================== + +Contents +-------- + +.. toctree:: + :maxdepth: 2 + + install_kdc.rst + install_clients.rst + install_appl_srv.rst + + +Additional references +--------------------- + +#. Debian: `Setting up MIT Kerberos 5 + `_ +#. Solaris: `Configuring the Kerberos Service + `_ diff --git a/krb5-1.21.3/doc/admin/install_appl_srv.rst b/krb5-1.21.3/doc/admin/install_appl_srv.rst new file mode 100644 index 00000000..2e198138 --- /dev/null +++ b/krb5-1.21.3/doc/admin/install_appl_srv.rst @@ -0,0 +1,78 @@ +UNIX Application Servers +======================== + +An application server is a host that provides one or more services +over the network. Application servers can be "secure" or "insecure." +A "secure" host is set up to require authentication from every client +connecting to it. An "insecure" host will still provide Kerberos +authentication, but will also allow unauthenticated clients to +connect. + +If you have Kerberos V5 installed on all of your client machines, MIT +recommends that you make your hosts secure, to take advantage of the +security that Kerberos authentication affords. However, if you have +some clients that do not have Kerberos V5 installed, you can run an +insecure server, and still take advantage of Kerberos V5's single +sign-on capability. + + +.. _keytab_file: + +The keytab file +--------------- + +All Kerberos server machines need a keytab file to authenticate to the +KDC. By default on UNIX-like systems this file is named |keytab|. +The keytab file is an local copy of the host's key. The keytab file +is a potential point of entry for a break-in, and if compromised, +would allow unrestricted access to its host. The keytab file should +be readable only by root, and should exist only on the machine's local +disk. The file should not be part of any backup of the machine, +unless access to the backup data is secured as tightly as access to +the machine's root password. + +In order to generate a keytab for a host, the host must have a +principal in the Kerberos database. The procedure for adding hosts to +the database is described fully in :ref:`principals`. (See +:ref:`replica_host_key` for a brief description.) The keytab is +generated by running :ref:`kadmin(1)` and issuing the :ref:`ktadd` +command. + +For example, to generate a keytab file to allow the host +``trillium.mit.edu`` to authenticate for the services host, ftp, and +pop, the administrator ``joeadmin`` would issue the command (on +``trillium.mit.edu``):: + + trillium% kadmin + Authenticating as principal root/admin@ATHENA.MIT.EDU with password. + Password for root/admin@ATHENA.MIT.EDU: + kadmin: ktadd host/trillium.mit.edu ftp/trillium.mit.edu pop/trillium.mit.edu + Entry for principal host/trillium.mit.edu@ATHENA.MIT.EDU with kvno 3, encryption type aes256-cts-hmac-sha384-192 added to keytab FILE:/etc/krb5.keytab. + kadmin: Entry for principal ftp/trillium.mit.edu@ATHENA.MIT.EDU with kvno 3, encryption type aes256-cts-hmac-sha384-192 added to keytab FILE:/etc/krb5.keytab. + kadmin: Entry for principal pop/trillium.mit.edu@ATHENA.MIT.EDU with kvno 3, encryption type aes256-cts-hmac-sha384-192 added to keytab FILE:/etc/krb5.keytab. + kadmin: quit + trillium% + +If you generate the keytab file on another host, you need to get a +copy of the keytab file onto the destination host (``trillium``, in +the above example) without sending it unencrypted over the network. + + +Some advice about secure hosts +------------------------------ + +Kerberos V5 can protect your host from certain types of break-ins, but +it is possible to install Kerberos V5 and still leave your host +vulnerable to attack. Obviously an installation guide is not the +place to try to include an exhaustive list of countermeasures for +every possible attack, but it is worth noting some of the larger holes +and how to close them. + +We recommend that backups of secure machines exclude the keytab file +(|keytab|). If this is not possible, the backups should at least be +done locally, rather than over a network, and the backup tapes should +be physically secured. + +The keytab file and any programs run by root, including the Kerberos +V5 binaries, should be kept on local disk. The keytab file should be +readable only by root. diff --git a/krb5-1.21.3/doc/admin/install_clients.rst b/krb5-1.21.3/doc/admin/install_clients.rst new file mode 100644 index 00000000..f2c87d07 --- /dev/null +++ b/krb5-1.21.3/doc/admin/install_clients.rst @@ -0,0 +1,58 @@ +Installing and configuring UNIX client machines +=============================================== + +The Kerberized client programs include :ref:`kinit(1)`, +:ref:`klist(1)`, :ref:`kdestroy(1)`, and :ref:`kpasswd(1)`. All of +these programs are in the directory |bindir|. + +You can often integrate Kerberos with the login system on client +machines, typically through the use of PAM. The details vary by +operating system, and should be covered in your operating system's +documentation. If you do this, you will need to make sure your users +know to use their Kerberos passwords when they log in. + +You will also need to educate your users to use the ticket management +programs kinit, klist, and kdestroy. If you do not have Kerberos +password changing integrated into the native password program (again, +typically through PAM), you will need to educate users to use kpasswd +in place of its non-Kerberos counterparts passwd. + + +Client machine configuration files +---------------------------------- + +Each machine running Kerberos should have a :ref:`krb5.conf(5)` file. +At a minimum, it should define a **default_realm** setting in +:ref:`libdefaults`. If you are not using DNS SRV records +(:ref:`kdc_hostnames`) or URI records (:ref:`kdc_discovery`), it must +also contain a :ref:`realms` section containing information for your +realm's KDCs. + +Consider setting **rdns** to false in order to reduce your dependence +on precisely correct DNS information for service hostnames. Turning +this flag off means that service hostnames will be canonicalized +through forward name resolution (which adds your domain name to +unqualified hostnames, and resolves CNAME records in DNS), but not +through reverse address lookup. The default value of this flag is +true for historical reasons only. + +If you anticipate users frequently logging into remote hosts +(e.g., using ssh) using forwardable credentials, consider setting +**forwardable** to true so that users obtain forwardable tickets by +default. Otherwise users will need to use ``kinit -f`` to get +forwardable tickets. + +Consider adjusting the **ticket_lifetime** setting to match the likely +length of sessions for your users. For instance, if most of your +users will be logging in for an eight-hour workday, you could set the +default to ten hours so that tickets obtained in the morning expire +shortly after the end of the workday. Users can still manually +request longer tickets when necessary, up to the maximum allowed by +each user's principal record on the KDC. + +If a client host may access services in different realms, it may be +useful to define a :ref:`domain_realm` mapping so that clients know +which hosts belong to which realms. However, if your clients and KDC +are running release 1.7 or later, it is also reasonable to leave this +section out on client machines and just define it in the KDC's +krb5.conf. diff --git a/krb5-1.21.3/doc/admin/install_kdc.rst b/krb5-1.21.3/doc/admin/install_kdc.rst new file mode 100644 index 00000000..8cab6514 --- /dev/null +++ b/krb5-1.21.3/doc/admin/install_kdc.rst @@ -0,0 +1,536 @@ +Installing KDCs +=============== + +When setting up Kerberos in a production environment, it is best to +have multiple replica KDCs alongside with a primary KDC to ensure the +continued availability of the Kerberized services. Each KDC contains +a copy of the Kerberos database. The primary KDC contains the +writable copy of the realm database, which it replicates to the +replica KDCs at regular intervals. All database changes (such as +password changes) are made on the primary KDC. Replica KDCs provide +Kerberos ticket-granting services, but not database administration, +when the primary KDC is unavailable. MIT recommends that you install +all of your KDCs to be able to function as either the primary or one +of the replicas. This will enable you to easily switch your primary +KDC with one of the replicas if necessary (see +:ref:`switch_primary_replica`). This installation procedure is based +on that recommendation. + +.. warning:: + + - The Kerberos system relies on the availability of correct time + information. Ensure that the primary and all replica KDCs have + properly synchronized clocks. + + - It is best to install and run KDCs on secured and dedicated + hardware with limited access. If your KDC is also a file + server, FTP server, Web server, or even just a client machine, + someone who obtained root access through a security hole in any + of those areas could potentially gain access to the Kerberos + database. + + +Install and configure the primary KDC +------------------------------------- + +Install Kerberos either from the OS-provided packages or from the +source (See :ref:`do_build`). + +.. note:: + + For the purpose of this document we will use the following + names:: + + kerberos.mit.edu - primary KDC + kerberos-1.mit.edu - replica KDC + ATHENA.MIT.EDU - realm name + .k5.ATHENA.MIT.EDU - stash file + admin/admin - admin principal + + See :ref:`mitK5defaults` for the default names and locations + of the relevant to this topic files. Adjust the names and + paths to your system environment. + + +Edit KDC configuration files +---------------------------- + +Modify the configuration files, :ref:`krb5.conf(5)` and +:ref:`kdc.conf(5)`, to reflect the correct information (such as +domain-realm mappings and Kerberos servers names) for your realm. +(See :ref:`mitK5defaults` for the recommended default locations for +these files). + +Most of the tags in the configuration have default values that will +work well for most sites. There are some tags in the +:ref:`krb5.conf(5)` file whose values must be specified, and this +section will explain those. + +If the locations for these configuration files differs from the +default ones, set **KRB5_CONFIG** and **KRB5_KDC_PROFILE** environment +variables to point to the krb5.conf and kdc.conf respectively. For +example:: + + export KRB5_CONFIG=/yourdir/krb5.conf + export KRB5_KDC_PROFILE=/yourdir/kdc.conf + + +krb5.conf +~~~~~~~~~ + +If you are not using DNS TXT records (see :ref:`mapping_hostnames`), +you must specify the **default_realm** in the :ref:`libdefaults` +section. If you are not using DNS URI or SRV records (see +:ref:`kdc_hostnames` and :ref:`kdc_discovery`), you must include the +**kdc** tag for each *realm* in the :ref:`realms` section. To +communicate with the kadmin server in each realm, the **admin_server** +tag must be set in the +:ref:`realms` section. + +An example krb5.conf file:: + + [libdefaults] + default_realm = ATHENA.MIT.EDU + + [realms] + ATHENA.MIT.EDU = { + kdc = kerberos.mit.edu + kdc = kerberos-1.mit.edu + admin_server = kerberos.mit.edu + } + + +kdc.conf +~~~~~~~~ + +The kdc.conf file can be used to control the listening ports of the +KDC and kadmind, as well as realm-specific defaults, the database type +and location, and logging. + +An example kdc.conf file:: + + [kdcdefaults] + kdc_listen = 88 + kdc_tcp_listen = 88 + + [realms] + ATHENA.MIT.EDU = { + kadmind_port = 749 + max_life = 12h 0m 0s + max_renewable_life = 7d 0h 0m 0s + master_key_type = aes256-cts + supported_enctypes = aes256-cts:normal aes128-cts:normal + # If the default location does not suit your setup, + # explicitly configure the following values: + # database_name = /var/krb5kdc/principal + # key_stash_file = /var/krb5kdc/.k5.ATHENA.MIT.EDU + # acl_file = /var/krb5kdc/kadm5.acl + } + + [logging] + # By default, the KDC and kadmind will log output using + # syslog. You can instead send log output to files like this: + kdc = FILE:/var/log/krb5kdc.log + admin_server = FILE:/var/log/kadmin.log + default = FILE:/var/log/krb5lib.log + +Replace ``ATHENA.MIT.EDU`` and ``kerberos.mit.edu`` with the name of +your Kerberos realm and server respectively. + +.. note:: + + You have to have write permission on the target directories + (these directories must exist) used by **database_name**, + **key_stash_file**, and **acl_file**. + + +.. _create_db: + +Create the KDC database +----------------------- + +You will use the :ref:`kdb5_util(8)` command on the primary KDC to +create the Kerberos database and the optional :ref:`stash_definition`. + +.. note:: + + If you choose not to install a stash file, the KDC will + prompt you for the master key each time it starts up. This + means that the KDC will not be able to start automatically, + such as after a system reboot. + +:ref:`kdb5_util(8)` will prompt you for the master password for the +Kerberos database. This password can be any string. A good password +is one you can remember, but that no one else can guess. Examples of +bad passwords are words that can be found in a dictionary, any common +or popular name, especially a famous person (or cartoon character), +your username in any form (e.g., forward, backward, repeated twice, +etc.), and any of the sample passwords that appear in this manual. +One example of a password which might be good if it did not appear in +this manual is "MITiys4K5!", which represents the sentence "MIT is +your source for Kerberos 5!" (It's the first letter of each word, +substituting the numeral "4" for the word "for", and includes the +punctuation mark at the end.) + +The following is an example of how to create a Kerberos database and +stash file on the primary KDC, using the :ref:`kdb5_util(8)` command. +Replace ``ATHENA.MIT.EDU`` with the name of your Kerberos realm:: + + shell% kdb5_util create -r ATHENA.MIT.EDU -s + + Initializing database '/usr/local/var/krb5kdc/principal' for realm 'ATHENA.MIT.EDU', + master key name 'K/M@ATHENA.MIT.EDU' + You will be prompted for the database Master Password. + It is important that you NOT FORGET this password. + Enter KDC database master key: <= Type the master password. + Re-enter KDC database master key to verify: <= Type it again. + shell% + +This will create five files in |kdcdir| (or at the locations specified +in :ref:`kdc.conf(5)`): + +* two Kerberos database files, ``principal``, and ``principal.ok`` +* the Kerberos administrative database file, ``principal.kadm5`` +* the administrative database lock file, ``principal.kadm5.lock`` +* the stash file, in this example ``.k5.ATHENA.MIT.EDU``. If you do + not want a stash file, run the above command without the **-s** + option. + +For more information on administrating Kerberos database see +:ref:`db_operations`. + + +.. _admin_acl: + +Add administrators to the ACL file +---------------------------------- + +Next, you need create an Access Control List (ACL) file and put the +Kerberos principal of at least one of the administrators into it. +This file is used by the :ref:`kadmind(8)` daemon to control which +principals may view and make privileged modifications to the Kerberos +database files. The ACL filename is determined by the **acl_file** +variable in :ref:`kdc.conf(5)`; the default is |kdcdir|\ +``/kadm5.acl``. + +For more information on Kerberos ACL file see :ref:`kadm5.acl(5)`. + +.. _addadmin_kdb: + +Add administrators to the Kerberos database +------------------------------------------- + +Next you need to add administrative principals (i.e., principals who +are allowed to administer Kerberos database) to the Kerberos database. +You *must* add at least one principal now to allow communication +between the Kerberos administration daemon kadmind and the kadmin +program over the network for further administration. To do this, use +the kadmin.local utility on the primary KDC. kadmin.local is designed +to be run on the primary KDC host without using Kerberos +authentication to an admin server; instead, it must have read and +write access to the Kerberos database on the local filesystem. + +The administrative principals you create should be the ones you added +to the ACL file (see :ref:`admin_acl`). + +In the following example, the administrative principal ``admin/admin`` +is created:: + + shell% kadmin.local + + kadmin.local: addprinc admin/admin@ATHENA.MIT.EDU + + No policy specified for "admin/admin@ATHENA.MIT.EDU"; + assigning "default". + Enter password for principal admin/admin@ATHENA.MIT.EDU: <= Enter a password. + Re-enter password for principal admin/admin@ATHENA.MIT.EDU: <= Type it again. + Principal "admin/admin@ATHENA.MIT.EDU" created. + kadmin.local: + +.. _start_kdc_daemons: + +Start the Kerberos daemons on the primary KDC +--------------------------------------------- + +At this point, you are ready to start the Kerberos KDC +(:ref:`krb5kdc(8)`) and administrative daemons on the primary KDC. To +do so, type:: + + shell% krb5kdc + shell% kadmind + +Each server daemon will fork and run in the background. + +.. note:: + + Assuming you want these daemons to start up automatically at + boot time, you can add them to the KDC's ``/etc/rc`` or + ``/etc/inittab`` file. You need to have a + :ref:`stash_definition` in order to do this. + +You can verify that they started properly by checking for their +startup messages in the logging locations you defined in +:ref:`krb5.conf(5)` (see :ref:`logging`). For example:: + + shell% tail /var/log/krb5kdc.log + Dec 02 12:35:47 beeblebrox krb5kdc[3187](info): commencing operation + shell% tail /var/log/kadmin.log + Dec 02 12:35:52 beeblebrox kadmind[3189](info): starting + +Any errors the daemons encounter while starting will also be listed in +the logging output. + +As an additional verification, check if :ref:`kinit(1)` succeeds +against the principals that you have created on the previous step +(:ref:`addadmin_kdb`). Run:: + + shell% kinit admin/admin@ATHENA.MIT.EDU + + +Install the replica KDCs +------------------------ + +You are now ready to start configuring the replica KDCs. + +.. note:: + + Assuming you are setting the KDCs up so that you can easily + switch the primary KDC with one of the replicas, you should + perform each of these steps on the primary KDC as well as + the replica KDCs, unless these instructions specify + otherwise. + + +.. _replica_host_key: + +Create host keytabs for replica KDCs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each KDC needs a ``host`` key in the Kerberos database. These keys +are used for mutual authentication when propagating the database dump +file from the primary KDC to the secondary KDC servers. + +On the primary KDC, connect to administrative interface and create the +host principal for each of the KDCs' ``host`` services. For example, +if the primary KDC were called ``kerberos.mit.edu``, and you had a +replica KDC named ``kerberos-1.mit.edu``, you would type the +following:: + + shell% kadmin + kadmin: addprinc -randkey host/kerberos.mit.edu + No policy specified for "host/kerberos.mit.edu@ATHENA.MIT.EDU"; assigning "default" + Principal "host/kerberos.mit.edu@ATHENA.MIT.EDU" created. + + kadmin: addprinc -randkey host/kerberos-1.mit.edu + No policy specified for "host/kerberos-1.mit.edu@ATHENA.MIT.EDU"; assigning "default" + Principal "host/kerberos-1.mit.edu@ATHENA.MIT.EDU" created. + +It is not strictly necessary to have the primary KDC server in the +Kerberos database, but it can be handy if you want to be able to swap +the primary KDC with one of the replicas. + +Next, extract ``host`` random keys for all participating KDCs and +store them in each host's default keytab file. Ideally, you should +extract each keytab locally on its own KDC. If this is not feasible, +you should use an encrypted session to send them across the network. +To extract a keytab directly on a replica KDC called +``kerberos-1.mit.edu``, you would execute the following command:: + + kadmin: ktadd host/kerberos-1.mit.edu + Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption + type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab. + Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption + type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab. + Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption + type aes256-cts-hmac-sha384-192 added to keytab FILE:/etc/krb5.keytab. + Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption + type arcfour-hmac added to keytab FILE:/etc/krb5.keytab. + +If you are instead extracting a keytab for the replica KDC called +``kerberos-1.mit.edu`` on the primary KDC, you should use a dedicated +temporary keytab file for that machine's keytab:: + + kadmin: ktadd -k /tmp/kerberos-1.keytab host/kerberos-1.mit.edu + Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption + type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab. + Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption + type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab. + +The file ``/tmp/kerberos-1.keytab`` can then be installed as +``/etc/krb5.keytab`` on the host ``kerberos-1.mit.edu``. + + +Configure replica KDCs +~~~~~~~~~~~~~~~~~~~~~~ + +Database propagation copies the contents of the primary's database, +but does not propagate configuration files, stash files, or the kadm5 +ACL file. The following files must be copied by hand to each replica +(see :ref:`mitK5defaults` for the default locations for these files): + +* krb5.conf +* kdc.conf +* kadm5.acl +* master key stash file + +Move the copied files into their appropriate directories, exactly as +on the primary KDC. kadm5.acl is only needed to allow a replica to +swap with the primary KDC. + +The database is propagated from the primary KDC to the replica KDCs +via the :ref:`kpropd(8)` daemon. You must explicitly specify the +principals which are allowed to provide Kerberos dump updates on the +replica machine with a new database. Create a file named kpropd.acl +in the KDC state directory containing the ``host`` principals for each +of the KDCs:: + + host/kerberos.mit.edu@ATHENA.MIT.EDU + host/kerberos-1.mit.edu@ATHENA.MIT.EDU + +.. note:: + + If you expect that the primary and replica KDCs will be + switched at some point of time, list the host principals + from all participating KDC servers in kpropd.acl files on + all of the KDCs. Otherwise, you only need to list the + primary KDC's host principal in the kpropd.acl files of the + replica KDCs. + +Then, add the following line to ``/etc/inetd.conf`` on each KDC +(adjust the path to kpropd):: + + krb5_prop stream tcp nowait root /usr/local/sbin/kpropd kpropd + +You also need to add the following line to ``/etc/services`` on each +KDC, if it is not already present (assuming that the default port is +used):: + + krb5_prop 754/tcp # Kerberos replica propagation + +Restart inetd daemon. + +Alternatively, start :ref:`kpropd(8)` as a stand-alone daemon. This is +required when incremental propagation is enabled. + +Now that the replica KDC is able to accept database propagation, +you’ll need to propagate the database from the primary server. + +NOTE: Do not start the replica KDC yet; you still do not have a copy +of the primary's database. + + +.. _kprop_to_replicas: + +Propagate the database to each replica KDC +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +First, create a dump file of the database on the primary KDC, as +follows:: + + shell% kdb5_util dump /usr/local/var/krb5kdc/replica_datatrans + +Then, manually propagate the database to each replica KDC, as in the +following example:: + + shell% kprop -f /usr/local/var/krb5kdc/replica_datatrans kerberos-1.mit.edu + + Database propagation to kerberos-1.mit.edu: SUCCEEDED + +You will need a script to dump and propagate the database. The +following is an example of a Bourne shell script that will do this. + +.. note:: + + Remember that you need to replace ``/usr/local/var/krb5kdc`` + with the name of the KDC state directory. + +:: + + #!/bin/sh + + kdclist = "kerberos-1.mit.edu kerberos-2.mit.edu" + + kdb5_util dump /usr/local/var/krb5kdc/replica_datatrans + + for kdc in $kdclist + do + kprop -f /usr/local/var/krb5kdc/replica_datatrans $kdc + done + +You will need to set up a cron job to run this script at the intervals +you decided on earlier (see :ref:`db_prop`). + +Now that the replica KDC has a copy of the Kerberos database, you can +start the krb5kdc daemon:: + + shell% krb5kdc + +As with the primary KDC, you will probably want to add this command to +the KDCs' ``/etc/rc`` or ``/etc/inittab`` files, so they will start +the krb5kdc daemon automatically at boot time. + + +Propagation failed? +################### + +You may encounter the following error messages. For a more detailed +discussion on possible causes and solutions click on the error link +to be redirected to :ref:`troubleshoot` section. + +.. include:: ./troubleshoot.rst + :start-after: _prop_failed_start: + :end-before: _prop_failed_end: + + +Add Kerberos principals to the database +--------------------------------------- + +Once your KDCs are set up and running, you are ready to use +:ref:`kadmin(1)` to load principals for your users, hosts, and other +services into the Kerberos database. This procedure is described +fully in :ref:`principals`. + +You may occasionally want to use one of your replica KDCs as the +primary. This might happen if you are upgrading the primary KDC, or +if your primary KDC has a disk crash. See the following section for +the instructions. + + +.. _switch_primary_replica: + +Switching primary and replica KDCs +---------------------------------- + +You may occasionally want to use one of your replica KDCs as the +primary. This might happen if you are upgrading the primary KDC, or +if your primary KDC has a disk crash. + +Assuming you have configured all of your KDCs to be able to function +as either the primary KDC or a replica KDC (as this document +recommends), all you need to do to make the changeover is: + +If the primary KDC is still running, do the following on the *old* +primary KDC: + +#. Kill the kadmind process. +#. Disable the cron job that propagates the database. +#. Run your database propagation script manually, to ensure that the + replicas all have the latest copy of the database (see + :ref:`kprop_to_replicas`). + +On the *new* primary KDC: + +#. Start the :ref:`kadmind(8)` daemon (see :ref:`start_kdc_daemons`). +#. Set up the cron job to propagate the database (see + :ref:`kprop_to_replicas`). +#. Switch the CNAMEs of the old and new primary KDCs. If you can't do + this, you'll need to change the :ref:`krb5.conf(5)` file on every + client machine in your Kerberos realm. + + +Incremental database propagation +-------------------------------- + +If you expect your Kerberos database to become large, you may wish to +set up incremental propagation to replica KDCs. See +:ref:`incr_db_prop` for details. diff --git a/krb5-1.21.3/doc/admin/lockout.rst b/krb5-1.21.3/doc/admin/lockout.rst new file mode 100644 index 00000000..cce44903 --- /dev/null +++ b/krb5-1.21.3/doc/admin/lockout.rst @@ -0,0 +1,154 @@ +.. _lockout: + +Account lockout +=============== + +As of release 1.8, the KDC can be configured to lock out principals +after a number of failed authentication attempts within a period of +time. Account lockout can make it more difficult to attack a +principal's password by brute force, but also makes it easy for an +attacker to deny access to a principal. + + +Configuring account lockout +--------------------------- + +Account lockout only works for principals with the +**+requires_preauth** flag set. Without this flag, the KDC cannot +know whether or not a client successfully decrypted the ticket it +issued. It is also important to set the **-allow_svr** flag on a +principal to protect its password from an off-line dictionary attack +through a TGS request. You can set these flags on a principal with +:ref:`kadmin(1)` as follows:: + + kadmin: modprinc +requires_preauth -allow_svr PRINCNAME + +Account lockout parameters are configured via :ref:`policy objects +`. There may be an existing policy associated with user +principals (such as the "default" policy), or you may need to create a +new one and associate it with each user principal. + +The policy parameters related to account lockout are: + +* :ref:`maxfailure `: the number of failed attempts + before the principal is locked out +* :ref:`failurecountinterval `: the + allowable interval between failed attempts +* :ref:`lockoutduration `: the amount of time + a principal is locked out for + +Here is an example of setting these parameters on a new policy and +associating it with a principal:: + + kadmin: addpol -maxfailure 10 -failurecountinterval 180 + -lockoutduration 60 lockout_policy + kadmin: modprinc -policy lockout_policy PRINCNAME + + +Testing account lockout +----------------------- + +To test that account lockout is working, try authenticating as the +principal (hopefully not one that might be in use) multiple times with +the wrong password. For instance, if **maxfailure** is set to 2, you +might see:: + + $ kinit user + Password for user@KRBTEST.COM: + kinit: Password incorrect while getting initial credentials + $ kinit user + Password for user@KRBTEST.COM: + kinit: Password incorrect while getting initial credentials + $ kinit user + kinit: Client's credentials have been revoked while getting initial credentials + + +Account lockout principal state +------------------------------- + +A principal entry keeps three pieces of state related to account +lockout: + +* The time of last successful authentication +* The time of last failed authentication +* A counter of failed attempts + +The time of last successful authentication is not actually needed for +the account lockout system to function, but may be of administrative +interest. These fields can be observed with the **getprinc** kadmin +command. For example:: + + kadmin: getprinc user + Principal: user@KRBTEST.COM + ... + Last successful authentication: [never] + Last failed authentication: Mon Dec 03 12:30:33 EST 2012 + Failed password attempts: 2 + ... + +A principal which has been locked out can be administratively unlocked +with the **-unlock** option to the **modprinc** kadmin command:: + + kadmin: modprinc -unlock PRINCNAME + +This command will reset the number of failed attempts to 0. + + +KDC replication and account lockout +----------------------------------- + +The account lockout state of a principal is not replicated by either +traditional :ref:`kprop(8)` or incremental propagation. Because of +this, the number of attempts an attacker can make within a time period +is multiplied by the number of KDCs. For instance, if the +**maxfailure** parameter on a policy is 10 and there are four KDCs in +the environment (a primary and three replicas), an attacker could make +as many as 40 attempts before the principal is locked out on all four +KDCs. + +An administrative unlock is propagated from the primary to the replica +KDCs during the next propagation. Propagation of an administrative +unlock will cause the counter of failed attempts on each replica to +reset to 1 on the next failure. + +If a KDC environment uses a replication strategy other than kprop or +incremental propagation, such as the LDAP KDB module with multi-master +LDAP replication, then account lockout state may be replicated between +KDCs and the concerns of this section may not apply. + + +.. _disable_lockout: + +KDC performance and account lockout +----------------------------------- + +In order to fully track account lockout state, the KDC must write to +the the database on each successful and failed authentication. +Writing to the database is generally more expensive than reading from +it, so these writes may have a significant impact on KDC performance. +As of release 1.9, it is possible to turn off account lockout state +tracking in order to improve performance, by setting the +**disable_last_success** and **disable_lockout** variables in the +database module subsection of :ref:`kdc.conf(5)`. For example:: + + [dbmodules] + DB = { + disable_last_success = true + disable_lockout = true + } + +Of the two variables, setting **disable_last_success** will usually +have the largest positive impact on performance, and will still allow +account lockout policies to operate. However, it will make it +impossible to observe the last successful authentication time with +kadmin. + + +KDC setup and account lockout +----------------------------- + +To update the account lockout state on principals, the KDC must be +able to write to the principal database. For the DB2 module, no +special setup is required. For the LDAP module, the KDC DN must be +granted write access to the principal objects. If the KDC DN has only +read access, account lockout will not function. diff --git a/krb5-1.21.3/doc/admin/otp.rst b/krb5-1.21.3/doc/admin/otp.rst new file mode 100644 index 00000000..29dc520f --- /dev/null +++ b/krb5-1.21.3/doc/admin/otp.rst @@ -0,0 +1,100 @@ +.. _otp_preauth: + +OTP Preauthentication +===================== + +OTP is a preauthentication mechanism for Kerberos 5 which uses One +Time Passwords (OTP) to authenticate the client to the KDC. The OTP +is passed to the KDC over an encrypted FAST channel in clear-text. +The KDC uses the password along with per-user configuration to proxy +the request to a third-party RADIUS system. This enables +out-of-the-box compatibility with a large number of already widely +deployed proprietary systems. + +Additionally, our implementation of the OTP system allows for the +passing of RADIUS requests over a UNIX domain stream socket. This +permits the use of a local companion daemon which can handle the +details of authentication. + + +Defining token types +-------------------- + +Token types are defined in either :ref:`krb5.conf(5)` or +:ref:`kdc.conf(5)` according to the following format:: + + [otp] + = { + server = (default: see below) + secret = + timeout = (default: 5 [seconds]) + retries = (default: 3) + strip_realm = (default: true) + indicator = (default: none) + } + +If the server field begins with '/', it will be interpreted as a UNIX +socket. Otherwise, it is assumed to be in the format host:port. When +a UNIX domain socket is specified, the secret field is optional and an +empty secret is used by default. If the server field is not +specified, it defaults to |kdcrundir|\ ``/.socket``. + +When forwarding the request over RADIUS, by default the principal is +used in the User-Name attribute of the RADIUS packet. The strip_realm +parameter controls whether the principal is forwarded with or without +the realm portion. + +If an indicator field is present, tickets issued using this token type +will be annotated with the specified authentication indicator (see +:ref:`auth_indicator`). This key may be specified multiple times to +add multiple indicators. + + +The default token type +---------------------- + +A default token type is used internally when no token type is specified for a +given user. It is defined as follows:: + + [otp] + DEFAULT = { + strip_realm = false + } + +The administrator may override the internal ``DEFAULT`` token type +simply by defining a configuration with the same name. + + +Token instance configuration +---------------------------- + +To enable OTP for a client principal, the administrator must define +the **otp** string attribute for that principal. (See +:ref:`set_string`.) The **otp** user string is a JSON string of the +format: + +.. code-block:: xml + + [{ + "type": , + "username": , + "indicators": [, ...] + }, ...] + +This is an array of token objects. Both fields of token objects are +optional. The **type** field names the token type of this token; if +not specified, it defaults to ``DEFAULT``. The **username** field +specifies the value to be sent in the User-Name RADIUS attribute. If +not specified, the principal name is sent, with or without realm as +defined in the token type. The **indicators** field specifies a list +of authentication indicators to annotate tickets with, overriding any +indicators specified in the token type. + +For ease of configuration, an empty array (``[]``) is treated as +equivalent to one DEFAULT token (``[{}]``). + + +Other considerations +-------------------- + +#. FAST is required for OTP to work. diff --git a/krb5-1.21.3/doc/admin/pkinit.rst b/krb5-1.21.3/doc/admin/pkinit.rst new file mode 100644 index 00000000..45817dac --- /dev/null +++ b/krb5-1.21.3/doc/admin/pkinit.rst @@ -0,0 +1,354 @@ +.. _pkinit: + +PKINIT configuration +==================== + +PKINIT is a preauthentication mechanism for Kerberos 5 which uses +X.509 certificates to authenticate the KDC to clients and vice versa. +PKINIT can also be used to enable anonymity support, allowing clients +to communicate securely with the KDC or with application servers +without authenticating as a particular client principal. + + +Creating certificates +--------------------- + +PKINIT requires an X.509 certificate for the KDC and one for each +client principal which will authenticate using PKINIT. For anonymous +PKINIT, a KDC certificate is required, but client certificates are +not. A commercially issued server certificate can be used for the KDC +certificate, but generally cannot be used for client certificates. + +The instruction in this section describe how to establish a +certificate authority and create standard PKINIT certificates. Skip +this section if you are using a commercially issued server certificate +as the KDC certificate for anonymous PKINIT, or if you are configuring +a client to use an Active Directory KDC. + + +Generating a certificate authority certificate +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can establish a new certificate authority (CA) for use with a +PKINIT deployment with the commands:: + + openssl genrsa -out cakey.pem 2048 + openssl req -key cakey.pem -new -x509 -out cacert.pem -days 3650 + +The second command will ask for the values of several certificate +fields. These fields can be set to any values. You can adjust the +expiration time of the CA certificate by changing the number after +``-days``. Since the CA certificate must be deployed to client +machines each time it changes, it should normally have an expiration +time far in the future; however, expiration times after 2037 may cause +interoperability issues in rare circumstances. + +The result of these commands will be two files, cakey.pem and +cacert.pem. cakey.pem will contain a 2048-bit RSA private key, which +must be carefully protected. cacert.pem will contain the CA +certificate, which must be placed in the filesystems of the KDC and +each client host. cakey.pem will be required to create KDC and client +certificates. + + +Generating a KDC certificate +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A KDC certificate for use with PKINIT is required to have some unusual +fields, which makes generating them with OpenSSL somewhat complicated. +First, you will need a file containing the following:: + + [kdc_cert] + basicConstraints=CA:FALSE + keyUsage=nonRepudiation,digitalSignature,keyEncipherment,keyAgreement + extendedKeyUsage=1.3.6.1.5.2.3.5 + subjectKeyIdentifier=hash + authorityKeyIdentifier=keyid,issuer + issuerAltName=issuer:copy + subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name + + [kdc_princ_name] + realm=EXP:0,GeneralString:${ENV::REALM} + principal_name=EXP:1,SEQUENCE:kdc_principal_seq + + [kdc_principal_seq] + name_type=EXP:0,INTEGER:2 + name_string=EXP:1,SEQUENCE:kdc_principals + + [kdc_principals] + princ1=GeneralString:krbtgt + princ2=GeneralString:${ENV::REALM} + +If the above contents are placed in extensions.kdc, you can generate +and sign a KDC certificate with the following commands:: + + openssl genrsa -out kdckey.pem 2048 + openssl req -new -out kdc.req -key kdckey.pem + env REALM=YOUR_REALMNAME openssl x509 -req -in kdc.req \ + -CAkey cakey.pem -CA cacert.pem -out kdc.pem -days 365 \ + -extfile extensions.kdc -extensions kdc_cert -CAcreateserial + rm kdc.req + +The second command will ask for the values of certificate fields, +which can be set to any values. In the third command, substitute your +KDC's realm name for YOUR_REALMNAME. You can adjust the certificate's +expiration date by changing the number after ``-days``. Remember to +create a new KDC certificate before the old one expires. + +The result of this operation will be in two files, kdckey.pem and +kdc.pem. Both files must be placed in the KDC's filesystem. +kdckey.pem, which contains the KDC's private key, must be carefully +protected. + +If you examine the KDC certificate with ``openssl x509 -in kdc.pem +-text -noout``, OpenSSL will not know how to display the KDC principal +name in the Subject Alternative Name extension, so it will appear as +``othername:``. This is normal and does not mean +anything is wrong with the KDC certificate. + + +Generating client certificates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +PKINIT client certificates also must have some unusual certificate +fields. To generate a client certificate with OpenSSL for a +single-component principal name, you will need an extensions file +(different from the KDC extensions file above) containing:: + + [client_cert] + basicConstraints=CA:FALSE + keyUsage=digitalSignature,keyEncipherment,keyAgreement + extendedKeyUsage=1.3.6.1.5.2.3.4 + subjectKeyIdentifier=hash + authorityKeyIdentifier=keyid,issuer + issuerAltName=issuer:copy + subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:princ_name + + [princ_name] + realm=EXP:0,GeneralString:${ENV::REALM} + principal_name=EXP:1,SEQUENCE:principal_seq + + [principal_seq] + name_type=EXP:0,INTEGER:1 + name_string=EXP:1,SEQUENCE:principals + + [principals] + princ1=GeneralString:${ENV::CLIENT} + +If the above contents are placed in extensions.client, you can +generate and sign a client certificate with the following commands:: + + openssl genrsa -out clientkey.pem 2048 + openssl req -new -key clientkey.pem -out client.req + env REALM=YOUR_REALMNAME CLIENT=YOUR_PRINCNAME openssl x509 \ + -CAkey cakey.pem -CA cacert.pem -req -in client.req \ + -extensions client_cert -extfile extensions.client \ + -days 365 -out client.pem + rm client.req + +Normally, the first two commands should be run on the client host, and +the resulting client.req file transferred to the certificate authority +host for the third command. As in the previous steps, the second +command will ask for the values of certificate fields, which can be +set to any values. In the third command, substitute your realm's name +for YOUR_REALMNAME and the client's principal name (without realm) for +YOUR_PRINCNAME. You can adjust the certificate's expiration date by +changing the number after ``-days``. + +The result of this operation will be two files, clientkey.pem and +client.pem. Both files must be present on the client's host; +clientkey.pem, which contains the client's private key, must be +protected from access by others. + +As in the KDC certificate, OpenSSL will display the client principal +name as ``othername:`` in the Subject Alternative Name +extension of a PKINIT client certificate. + +If the client principal name contains more than one component +(e.g. ``host/example.com@REALM``), the ``[principals]`` section of +``extensions.client`` must be altered to contain multiple entries. +(Simply setting ``CLIENT`` to ``host/example.com`` would generate a +certificate for ``host\/example.com@REALM`` which would not match the +multi-component principal name.) For a two-component principal, the +section should read:: + + [principals] + princ1=GeneralString:${ENV::CLIENT1} + princ2=GeneralString:${ENV::CLIENT2} + +The environment variables ``CLIENT1`` and ``CLIENT2`` must then be set +to the first and second components when running ``openssl x509``. + + +Configuring the KDC +------------------- + +The KDC must have filesystem access to the KDC certificate (kdc.pem) +and the KDC private key (kdckey.pem). Configure the following +relation in the KDC's :ref:`kdc.conf(5)` file, either in the +:ref:`kdcdefaults` section or in a :ref:`kdc_realms` subsection (with +appropriate pathnames):: + + pkinit_identity = FILE:/var/lib/krb5kdc/kdc.pem,/var/lib/krb5kdc/kdckey.pem + +If any clients will authenticate using regular (as opposed to +anonymous) PKINIT, the KDC must also have filesystem access to the CA +certificate (cacert.pem), and the following configuration (with the +appropriate pathname):: + + pkinit_anchors = FILE:/var/lib/krb5kdc/cacert.pem + +Because of the larger size of requests and responses using PKINIT, you +may also need to allow TCP access to the KDC:: + + kdc_tcp_listen = 88 + +Restart the :ref:`krb5kdc(8)` daemon to pick up the configuration +changes. + +The principal entry for each PKINIT-using client must be configured to +require preauthentication. Ensure this with the command:: + + kadmin -q 'modprinc +requires_preauth YOUR_PRINCNAME' + +Starting with release 1.12, it is possible to remove the long-term +keys of a principal entry, which can save some space in the database +and help to clarify some PKINIT-related error conditions by not asking +for a password:: + + kadmin -q 'purgekeys -all YOUR_PRINCNAME' + +These principal options can also be specified at principal creation +time as follows:: + + kadmin -q 'add_principal +requires_preauth -nokey YOUR_PRINCNAME' + +By default, the KDC requires PKINIT client certificates to have the +standard Extended Key Usage and Subject Alternative Name attributes +for PKINIT. Starting in release 1.16, it is possible to authorize +client certificates based on the subject or other criteria instead of +the standard PKINIT Subject Alternative Name, by setting the +**pkinit_cert_match** string attribute on each client principal entry. +For example:: + + kadmin set_string user@REALM pkinit_cert_match "CN=user@REALM$" + +The **pkinit_cert_match** string attribute follows the syntax used by +the :ref:`krb5.conf(5)` **pkinit_cert_match** relation. To allow the +use of non-PKINIT client certificates, it will also be necessary to +disable key usage checking using the **pkinit_eku_checking** relation; +for example:: + + [kdcdefaults] + pkinit_eku_checking = none + + + +Configuring the clients +----------------------- + +Client hosts must be configured to trust the issuing authority for the +KDC certificate. For a newly established certificate authority, the +client host must have filesystem access to the CA certificate +(cacert.pem) and the following relation in :ref:`krb5.conf(5)` in the +appropriate :ref:`realms` subsection (with appropriate pathnames):: + + pkinit_anchors = FILE:/etc/krb5/cacert.pem + +If the KDC certificate is a commercially issued server certificate, +the issuing certificate is most likely included in a system directory. +You can specify it by filename as above, or specify the whole +directory like so:: + + pkinit_anchors = DIR:/etc/ssl/certs + +A commercially issued server certificate will usually not have the +standard PKINIT principal name or Extended Key Usage extensions, so +the following additional configuration is required:: + + pkinit_eku_checking = kpServerAuth + pkinit_kdc_hostname = hostname.of.kdc.certificate + +Multiple **pkinit_kdc_hostname** relations can be configured to +recognize multiple KDC certificates. If the KDC is an Active +Directory domain controller, setting **pkinit_kdc_hostname** is +necessary, but it should not be necessary to set +**pkinit_eku_checking**. + +To perform regular (as opposed to anonymous) PKINIT authentication, a +client host must have filesystem access to a client certificate +(client.pem), and the corresponding private key (clientkey.pem). +Configure the following relations in the client host's +:ref:`krb5.conf(5)` file in the appropriate :ref:`realms` subsection +(with appropriate pathnames):: + + pkinit_identities = FILE:/etc/krb5/client.pem,/etc/krb5/clientkey.pem + +If the KDC and client are properly configured, it should now be +possible to run ``kinit username`` without entering a password. + + +.. _anonymous_pkinit: + +Anonymous PKINIT +---------------- + +Anonymity support in Kerberos allows a client to obtain a ticket +without authenticating as any particular principal. Such a ticket can +be used as a FAST armor ticket, or to securely communicate with an +application server anonymously. + +To configure anonymity support, you must generate or otherwise procure +a KDC certificate and configure the KDC host, but you do not need to +generate any client certificates. On the KDC, you must set the +**pkinit_identity** variable to provide the KDC certificate, but do +not need to set the **pkinit_anchors** variable or store the issuing +certificate if you won't have any client certificates to verify. On +client hosts, you must set the **pkinit_anchors** variable (and +possibly **pkinit_kdc_hostname** and **pkinit_eku_checking**) in order +to trust the issuing authority for the KDC certificate, but do not +need to set the **pkinit_identities** variable. + +Anonymity support is not enabled by default. To enable it, you must +create the principal ``WELLKNOWN/ANONYMOUS`` using the command:: + + kadmin -q 'addprinc -randkey WELLKNOWN/ANONYMOUS' + +Some Kerberos deployments include application servers which lack +proper access control, and grant some level of access to any user who +can authenticate. In such an environment, enabling anonymity support +on the KDC would present a security issue. If you need to enable +anonymity support for TGTs (for use as FAST armor tickets) without +enabling anonymous authentication to application servers, you can set +the variable **restrict_anonymous_to_tgt** to ``true`` in the +appropriate :ref:`kdc_realms` subsection of the KDC's +:ref:`kdc.conf(5)` file. + +To obtain anonymous credentials on a client, run ``kinit -n``, or +``kinit -n @REALMNAME`` to specify a realm. The resulting tickets +will have the client name ``WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS``. + + +Freshness tokens +---------------- + +Freshness tokens can ensure that the client has recently had access to +its certificate private key. If freshness tokens are not required by +the KDC, a client program with temporary possession of the private key +can compose requests for future timestamps and use them later. + +In release 1.17 and later, freshness tokens are supported by the +client and are sent by the KDC when the client indicates support for +them. Because not all clients support freshness tokens yet, they are +not required by default. To check if freshness tokens are supported +by a realm's clients, look in the KDC logs for the lines:: + + PKINIT: freshness token received from + PKINIT: no freshness token received from + +To require freshness tokens for all clients in a realm (except for +clients authenticating anonymously), set the +**pkinit_require_freshness** variable to ``true`` in the appropriate +:ref:`kdc_realms` subsection of the KDC's :ref:`kdc.conf(5)` file. To +test that this option is in effect, run ``kinit -X disable_freshness`` +and verify that authentication is unsuccessful. diff --git a/krb5-1.21.3/doc/admin/princ_dns.rst b/krb5-1.21.3/doc/admin/princ_dns.rst new file mode 100644 index 00000000..e558cd48 --- /dev/null +++ b/krb5-1.21.3/doc/admin/princ_dns.rst @@ -0,0 +1,126 @@ +Principal names and DNS +======================= + +Kerberos clients can do DNS lookups to canonicalize service principal +names. This can cause difficulties when setting up Kerberos +application servers, especially when the client's name for the service +is different from what the service thinks its name is. + + +Service principal names +----------------------- + +A frequently used kind of principal name is the host-based service +principal name. This kind of principal name has two components: a +service name and a hostname. For example, ``imap/imap.example.com`` +is the principal name of the "imap" service on the host +"imap.example.com". Other possible service names for the first +component include "host" (remote login services such as ssh), "HTTP", +and "nfs" (Network File System). + +Service administrators often publish well-known hostname aliases that +they would prefer users to use instead of the canonical name of the +service host. This gives service administrators more flexibility in +deploying services. For example, a shell login server might be named +"long-vanity-hostname.example.com", but users will naturally prefer to +type something like "login.example.com". Hostname aliases also allow +for administrators to set up load balancing for some sorts of services +based on rotating ``CNAME`` records in DNS. + + +Service principal canonicalization +---------------------------------- + +In the MIT krb5 client library, canonicalization of host-based service +principals is controlled by the **dns_canonicalize_hostname**, +**rnds**, and **qualify_shortname** variables in :ref:`libdefaults`. + +If **dns_canonicalize_hostname** is set to ``true`` (the default +value), the client performs forward resolution by looking up the IPv4 +and/or IPv6 addresses of the hostname using ``getaddrinfo()``. This +process will typically add a domain suffix to the hostname if needed, +and follow CNAME records in the DNS. If **rdns** is also set to +``true`` (the default), the client will then perform a reverse lookup +of the first returned Internet address using ``getnameinfo()``, +finding the name associated with the PTR record. + +If **dns_canonicalize_hostname** is set to ``false``, the hostname is +not canonicalized using DNS. If the hostname has only one component +(i.e. it contains no "." characters), the host's primary DNS search +domain will be appended, if there is one. The **qualify_shortname** +variable can be used to override or disable this suffix. + +If **dns_canonicalize_hostname** is set to ``fallback`` (added in +release 1.18), the hostname is initially treated according to the +rules for ``dns_canonicalize_hostname=false``. If a ticket request +fails because the service principal is unknown, the hostname will be +canonicalized according to the rules for +``dns_canonicalize_hostname=true`` and the request will be retried. + +In all cases, the hostname is converted to lowercase, and any trailing +dot is removed. + + + +Reverse DNS mismatches +---------------------- + +Sometimes, an enterprise will have control over its forward DNS but +not its reverse DNS. The reverse DNS is sometimes under the control +of the Internet service provider of the enterprise, and the enterprise +may not have much influence in setting up reverse DNS records for its +address space. If there are difficulties with getting forward and +reverse DNS to match, it is best to set ``rdns = false`` on client +machines. + + +Overriding application behavior +------------------------------- + +Applications can choose to use a default hostname component in their +service principal name when accepting authentication, which avoids +some sorts of hostname mismatches. Because not all relevant +applications do this yet, using the :ref:`krb5.conf(5)` setting:: + + [libdefaults] + ignore_acceptor_hostname = true + +will allow the Kerberos library to override the application's choice +of service principal hostname and will allow a server program to +accept incoming authentications using any key in its keytab that +matches the service name and realm name (if given). This setting +defaults to "false" and is available in releases krb5-1.10 and later. + + +Provisioning keytabs +-------------------- + +One service principal entry that should be in the keytab is a +principal whose hostname component is the canonical hostname that +``getaddrinfo()`` reports for all known aliases for the host. If the +reverse DNS information does not match this canonical hostname, an +additional service principal entry should be in the keytab for this +different hostname. + + +Specific application advice +--------------------------- + +Secure shell (ssh) +~~~~~~~~~~~~~~~~~~ + +Setting ``GSSAPIStrictAcceptorCheck = no`` in the configuration file +of modern versions of the openssh daemon will allow the daemon to try +any key in its keytab when accepting a connection, rather than looking +for the keytab entry that matches the host's own idea of its name +(typically the name that ``gethostname()`` returns). This requires +krb5-1.10 or later. + +OpenLDAP (ldapsearch, etc.) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +OpenLDAP's SASL implementation performs reverse DNS lookup in order to +canonicalize service principal names, even if **rdns** is set to +``false`` in the Kerberos configuration. To disable this behavior, +add ``SASL_NOCANON on`` to ``ldap.conf``, or set the +``LDAPSASL_NOCANON`` environment variable. diff --git a/krb5-1.21.3/doc/admin/realm_config.rst b/krb5-1.21.3/doc/admin/realm_config.rst new file mode 100644 index 00000000..9f5ad507 --- /dev/null +++ b/krb5-1.21.3/doc/admin/realm_config.rst @@ -0,0 +1,268 @@ +Realm configuration decisions +============================= + +Before installing Kerberos V5, it is necessary to consider the +following issues: + +* The name of your Kerberos realm (or the name of each realm, if you + need more than one). +* How you will assign your hostnames to Kerberos realms. +* Which ports your KDC and and kadmind services will use, if they will + not be using the default ports. +* How many replica KDCs you need and where they should be located. +* The hostnames of your primary and replica KDCs. +* How frequently you will propagate the database from the primary KDC + to the replica KDCs. + + +Realm name +---------- + +Although your Kerberos realm can be any ASCII string, convention is to +make it the same as your domain name, in upper-case letters. + +For example, hosts in the domain ``example.com`` would be in the +Kerberos realm:: + + EXAMPLE.COM + +If you need multiple Kerberos realms, MIT recommends that you use +descriptive names which end with your domain name, such as:: + + BOSTON.EXAMPLE.COM + HOUSTON.EXAMPLE.COM + + +.. _mapping_hostnames: + +Mapping hostnames onto Kerberos realms +-------------------------------------- + +Mapping hostnames onto Kerberos realms is done in one of three ways. + +The first mechanism works through a set of rules in the +:ref:`domain_realm` section of :ref:`krb5.conf(5)`. You can specify +mappings for an entire domain or on a per-hostname basis. Typically +you would do this by specifying the mappings for a given domain or +subdomain and listing the exceptions. + +The second mechanism is to use KDC host-based service referrals. With +this method, the KDC's krb5.conf has a full [domain_realm] mapping for +hosts, but the clients do not, or have mappings for only a subset of +the hosts they might contact. When a client needs to contact a server +host for which it has no mapping, it will ask the client realm's KDC +for the service ticket, and will receive a referral to the appropriate +service realm. + +To use referrals, clients must be running MIT krb5 1.6 or later, and +the KDC must be running MIT krb5 1.7 or later. The +**host_based_services** and **no_host_referral** variables in the +:ref:`kdc_realms` section of :ref:`kdc.conf(5)` can be used to +fine-tune referral behavior on the KDC. + +It is also possible for clients to use DNS TXT records, if +**dns_lookup_realm** is enabled in :ref:`krb5.conf(5)`. Such lookups +are disabled by default because DNS is an insecure protocol and security +holes could result if DNS records are spoofed. If enabled, the client +will try to look up a TXT record formed by prepending the prefix +``_kerberos`` to the hostname in question. If that record is not +found, the client will attempt a lookup by prepending ``_kerberos`` to the +host's domain name, then its parent domain, up to the top-level domain. +For the hostname ``boston.engineering.example.com``, the names looked up +would be:: + + _kerberos.boston.engineering.example.com + _kerberos.engineering.example.com + _kerberos.example.com + _kerberos.com + +The value of the first TXT record found is taken as the realm name. + +Even if you do not choose to use this mechanism within your site, +you may wish to set it up anyway, for use when interacting with other sites. + + +Ports for the KDC and admin services +------------------------------------ + +The default ports used by Kerberos are port 88 for the KDC and port +749 for the admin server. You can, however, choose to run on other +ports, as long as they are specified in each host's +:ref:`krb5.conf(5)` files or in DNS SRV records, and the +:ref:`kdc.conf(5)` file on each KDC. For a more thorough treatment of +port numbers used by the Kerberos V5 programs, refer to the +:ref:`conf_firewall`. + + +Replica KDCs +------------ + +Replica KDCs provide an additional source of Kerberos ticket-granting +services in the event of inaccessibility of the primary KDC. The +number of replica KDCs you need and the decision of where to place them, +both physically and logically, depends on the specifics of your +network. + +Kerberos authentication requires that each client be able to contact a +KDC. Therefore, you need to anticipate any likely reason a KDC might +be unavailable and have a replica KDC to take up the slack. + +Some considerations include: + +* Have at least one replica KDC as a backup, for when the primary KDC + is down, is being upgraded, or is otherwise unavailable. +* If your network is split such that a network outage is likely to + cause a network partition (some segment or segments of the network + to become cut off or isolated from other segments), have a replica + KDC accessible to each segment. +* If possible, have at least one replica KDC in a different building + from the primary, in case of power outages, fires, or other + localized disasters. + + +.. _kdc_hostnames: + +Hostnames for KDCs +------------------ + +MIT recommends that your KDCs have a predefined set of CNAME records +(DNS hostname aliases), such as ``kerberos`` for the primary KDC and +``kerberos-1``, ``kerberos-2``, ... for the replica KDCs. This way, +if you need to swap a machine, you only need to change a DNS entry, +rather than having to change hostnames. + +As of MIT krb5 1.4, clients can locate a realm's KDCs through DNS +using SRV records (:rfc:`2782`), assuming the Kerberos realm name is +also a DNS domain name. These records indicate the hostname and port +number to contact for that service, optionally with weighting and +prioritization. The domain name used in the SRV record name is the +realm name. Several different Kerberos-related service names are +used: + +_kerberos._udp + This is for contacting any KDC by UDP. This entry will be used + the most often. Normally you should list port 88 on each of your + KDCs. +_kerberos._tcp + This is for contacting any KDC by TCP. Normally you should use + port 88. This entry should be omitted if the KDC does not listen + on TCP ports, as was the default prior to release 1.13. +_kerberos-master._udp + This entry should refer to those KDCs, if any, that will + immediately see password changes to the Kerberos database. If a + user is logging in and the password appears to be incorrect, the + client will retry with the primary KDC before failing with an + "incorrect password" error given. + + If you have only one KDC, or for whatever reason there is no + accessible KDC that would get database changes faster than the + others, you do not need to define this entry. +_kerberos-adm._tcp + This should list port 749 on your primary KDC. Support for it is + not complete at this time, but it will eventually be used by the + :ref:`kadmin(1)` program and related utilities. For now, you will + also need the **admin_server** variable in :ref:`krb5.conf(5)`. +_kerberos-master._tcp + The corresponding TCP port for _kerberos-master._udp, assuming the + primary KDC listens on a TCP port. +_kpasswd._udp + This entry should list port 464 on your primary KDC. It is used + when a user changes her password. If this entry is not defined + but a _kerberos-adm._tcp entry is defined, the client will use the + _kerberos-adm._tcp entry with the port number changed to 464. +_kpasswd._tcp + The corresponding TCP port for _kpasswd._udp. + +The DNS SRV specification requires that the hostnames listed be the +canonical names, not aliases. So, for example, you might include the +following records in your (BIND-style) zone file:: + + $ORIGIN foobar.com. + _kerberos TXT "FOOBAR.COM" + kerberos CNAME daisy + kerberos-1 CNAME use-the-force-luke + kerberos-2 CNAME bunny-rabbit + _kerberos._udp SRV 0 0 88 daisy + SRV 0 0 88 use-the-force-luke + SRV 0 0 88 bunny-rabbit + _kerberos-master._udp SRV 0 0 88 daisy + _kerberos-adm._tcp SRV 0 0 749 daisy + _kpasswd._udp SRV 0 0 464 daisy + +Clients can also be configured with the explicit location of services +using the **kdc**, **master_kdc**, **admin_server**, and +**kpasswd_server** variables in the :ref:`realms` section of +:ref:`krb5.conf(5)`. Even if some clients will be configured with +explicit server locations, providing SRV records will still benefit +unconfigured clients, and be useful for other sites. + + +.. _kdc_discovery: + +KDC Discovery +------------- + +As of MIT krb5 1.15, clients can also locate KDCs in DNS through URI +records (:rfc:`7553`). Limitations with the SRV record format may +result in extra DNS queries in situations where a client must failover +to other transport types, or find a primary server. The URI record +can convey more information about a realm's KDCs with a single query. + +The client performs a query for the following URI records: + +* ``_kerberos.REALM`` for finding KDCs. +* ``_kerberos-adm.REALM`` for finding kadmin services. +* ``_kpasswd.REALM`` for finding password services. + +The URI record includes a priority, weight, and a URI string that +consists of case-insensitive colon separated fields, in the form +``scheme:[flags]:transport:residual``. + +* *scheme* defines the registered URI type. It should always be + ``krb5srv``. +* *flags* contains zero or more flag characters. Currently the only + valid flag is ``m``, which indicates that the record is for a + primary server. +* *transport* defines the transport type of the residual URL or + address. Accepted values are ``tcp``, ``udp``, or ``kkdcp`` for the + MS-KKDCP type. +* *residual* contains the hostname, IP address, or URL to be + contacted using the specified transport, with an optional port + extension. The MS-KKDCP transport type uses a HTTPS URL, and can + include a port and/or path extension. + +An example of URI records in a zone file:: + + _kerberos.EXAMPLE.COM URI 10 1 krb5srv:m:tcp:kdc1.example.com + URI 20 1 krb5srv:m:udp:kdc2.example.com:89 + URI 40 1 krb5srv::udp:10.10.0.23 + URI 30 1 krb5srv::kkdcp:https://proxy:89/auth + +URI lookups are enabled by default, and can be disabled by setting +**dns_uri_lookup** in the :ref:`libdefaults` section of +:ref:`krb5.conf(5)` to False. When enabled, URI lookups take +precedence over SRV lookups, falling back to SRV lookups if no URI +records are found. + + +.. _db_prop: + +Database propagation +-------------------- + +The Kerberos database resides on the primary KDC, and must be +propagated regularly (usually by a cron job) to the replica KDCs. In +deciding how frequently the propagation should happen, you will need +to balance the amount of time the propagation takes against the +maximum reasonable amount of time a user should have to wait for a +password change to take effect. + +If the propagation time is longer than this maximum reasonable time +(e.g., you have a particularly large database, you have a lot of +replicas, or you experience frequent network delays), you may wish to +cut down on your propagation delay by performing the propagation in +parallel. To do this, have the primary KDC propagate the database to +one set of replicas, and then have each of these replicas propagate +the database to additional replicas. + +See also :ref:`incr_db_prop` diff --git a/krb5-1.21.3/doc/admin/spake.rst b/krb5-1.21.3/doc/admin/spake.rst new file mode 100644 index 00000000..001f9291 --- /dev/null +++ b/krb5-1.21.3/doc/admin/spake.rst @@ -0,0 +1,56 @@ +.. _spake: + +SPAKE Preauthentication +======================= + +SPAKE preauthentication (added in release 1.17) uses public key +cryptography techniques to protect against :ref:`password dictionary +attacks `. Unlike :ref:`PKINIT `, it does not +require any additional infrastructure such as certificates; it simply +needs to be turned on. Using SPAKE preauthentication may modestly +increase the CPU and network load on the KDC. + +SPAKE preauthentication can use one of four elliptic curve groups for +its password-authenticated key exchange. The recommended group is +``edwards25519``; three NIST curves (``P-256``, ``P-384``, and +``P-521``) are also supported. + +By default, SPAKE with the ``edwards25519`` group is enabled on +clients, but the KDC does not offer SPAKE by default. To turn it on, +set the **spake_preauth_groups** variable in :ref:`libdefaults` to a +list of allowed groups. This variable affects both the client and the +KDC. Simply setting it to ``edwards25519`` is recommended:: + + [libdefaults] + spake_preauth_groups = edwards25519 + +Set the **+requires_preauth** and **-allow_svr** flags on client +principal entries, as you would for any preauthentication mechanism:: + + kadmin: modprinc +requires_preauth -allow_svr PRINCNAME + +Clients which do not implement SPAKE preauthentication will fall back +to encrypted timestamp. + +An active attacker can force a fallback to encrypted timestamp by +modifying the initial KDC response, defeating the protection against +dictionary attacks. To prevent this fallback on clients which do +implement SPAKE preauthentication, set the +**disable_encrypted_timestamp** variable to ``true`` in the +:ref:`realms` subsection for realms whose KDCs offer SPAKE +preauthentication. + +By default, SPAKE preauthentication requires an extra network round +trip to the KDC during initial authentication. If most of the clients +in a realm support SPAKE, this extra round trip can be eliminated +using an optimistic challenge, by setting the +**spake_preauth_kdc_challenge** variable in :ref:`kdcdefaults` to a +single group name:: + + [kdcdefaults] + spake_preauth_kdc_challenge = edwards25519 + +Using optimistic challenge will cause the KDC to do extra work for +initial authentication requests that do not result in SPAKE +preauthentication, but will save work when SPAKE preauthentication is +used. diff --git a/krb5-1.21.3/doc/admin/troubleshoot.rst b/krb5-1.21.3/doc/admin/troubleshoot.rst new file mode 100644 index 00000000..ade5e1f8 --- /dev/null +++ b/krb5-1.21.3/doc/admin/troubleshoot.rst @@ -0,0 +1,135 @@ +.. _troubleshoot: + +Troubleshooting +=============== + +.. _trace_logging: + +Trace logging +------------- + +Most programs using MIT krb5 1.9 or later can be made to provide +information about internal krb5 library operations using trace +logging. To enable this, set the **KRB5_TRACE** environment variable +to a filename before running the program. On many operating systems, +the filename ``/dev/stdout`` can be used to send trace logging output +to standard output. + +Some programs do not honor **KRB5_TRACE**, either because they use +secure library contexts (this generally applies to setuid programs and +parts of the login system) or because they take direct control of the +trace logging system using the API. + +Here is a short example showing trace logging output for an invocation +of the :ref:`kvno(1)` command:: + + shell% env KRB5_TRACE=/dev/stdout kvno krbtgt/KRBTEST.COM + [9138] 1332348778.823276: Getting credentials user@KRBTEST.COM -> + krbtgt/KRBTEST.COM@KRBTEST.COM using ccache + FILE:/me/krb5/build/testdir/ccache + [9138] 1332348778.823381: Retrieving user@KRBTEST.COM -> + krbtgt/KRBTEST.COM@KRBTEST.COM from + FILE:/me/krb5/build/testdir/ccache with result: 0/Unknown code 0 + krbtgt/KRBTEST.COM@KRBTEST.COM: kvno = 1 + + +List of errors +-------------- + +Frequently seen errors +~~~~~~~~~~~~~~~~~~~~~~ + +#. :ref:`init_creds_ETYPE_NOSUPP` + +#. :ref:`cert_chain_ETYPE_NOSUPP` + +#. :ref:`err_cert_chain_cert_expired` + + +Errors seen by admins +~~~~~~~~~~~~~~~~~~~~~ + +.. _prop_failed_start: + +#. :ref:`kprop_no_route` + +#. :ref:`kprop_con_refused` + +#. :ref:`kprop_sendauth_exchange` + +.. _prop_failed_end: + +----- + +.. _init_creds_etype_nosupp: + +KDC has no support for encryption type while getting initial credentials +........................................................................ + +.. _cert_chain_etype_nosupp: + + +credential verification failed: KDC has no support for encryption type +...................................................................... + +This most commonly happens when trying to use a principal with only +DES keys, in a release (MIT krb5 1.7 or later) which disables DES by +default. DES encryption is considered weak due to its inadequate key +size. If you cannot migrate away from its use, you can re-enable DES +by adding ``allow_weak_crypto = true`` to the :ref:`libdefaults` +section of :ref:`krb5.conf(5)`. + + +.. _err_cert_chain_cert_expired: + +Cannot create cert chain: certificate has expired +................................................. + +This error message indicates that PKINIT authentication failed because +the client certificate, KDC certificate, or one of the certificates in +the signing chain above them has expired. + +If the KDC certificate has expired, this message appears in the KDC +log file, and the client will receive a "Preauthentication failed" +error. (Prior to release 1.11, the KDC log file message erroneously +appears as "Out of memory". Prior to release 1.12, the client will +receive a "Generic error".) + +If the client or a signing certificate has expired, this message may +appear in trace_logging_ output from :ref:`kinit(1)` or, starting in +release 1.12, as an error message from kinit or another program which +gets initial tickets. The error message is more likely to appear +properly on the client if the principal entry has no long-term keys. + +.. _kprop_no_route: + +kprop: No route to host while connecting to server +.................................................. + +Make sure that the hostname of the replica KDC (as given to kprop) is +correct, and that any firewalls between the primary and the replica +allow a connection on port 754. + +.. _kprop_con_refused: + +kprop: Connection refused while connecting to server +.................................................... + +If the replica KDC is intended to run kpropd out of inetd, make sure +that inetd is configured to accept krb5_prop connections. inetd may +need to be restarted or sent a SIGHUP to recognize the new +configuration. If the replica is intended to run kpropd in standalone +mode, make sure that it is running. + +.. _kprop_sendauth_exchange: + +kprop: Server rejected authentication (during sendauth exchange) while authenticating to server +............................................................................................... + +Make sure that: + +#. The time is synchronized between the primary and replica KDCs. +#. The master stash file was copied from the primary to the expected + location on the replica. +#. The replica has a keytab file in the default location containing a + ``host`` principal for the replica's hostname. diff --git a/krb5-1.21.3/doc/admin/various_envs.rst b/krb5-1.21.3/doc/admin/various_envs.rst new file mode 100644 index 00000000..64c1795f --- /dev/null +++ b/krb5-1.21.3/doc/admin/various_envs.rst @@ -0,0 +1,27 @@ +Various links +============= + +Whitepapers +----------- + +#. https://kerberos.org/software/whitepapers.html + + +Tutorials +--------- + +#. Fulvio Ricciardi _ + + +Troubleshooting +--------------- + +#. https://wiki.ncsa.illinois.edu/display/ITS/Windows+Kerberos+Troubleshooting + +#. https://www.shrubbery.net/solaris9ab/SUNWaadm/SYSADV6/p27.html + +#. https://docs.oracle.com/cd/E19253-01/816-4557/trouble-1/index.html + +#. https://docs.microsoft.com/en-us/previous-versions/tn-archive/bb463167(v=technet.10)#EBAA + +#. https://bugs.launchpad.net/ubuntu/+source/libpam-heimdal/+bug/86528 diff --git a/krb5-1.21.3/doc/appdev/gssapi.rst b/krb5-1.21.3/doc/appdev/gssapi.rst new file mode 100644 index 00000000..339fd6c7 --- /dev/null +++ b/krb5-1.21.3/doc/appdev/gssapi.rst @@ -0,0 +1,727 @@ +Developing with GSSAPI +====================== + +The GSSAPI (Generic Security Services API) allows applications to +communicate securely using Kerberos 5 or other security mechanisms. +We recommend using the GSSAPI (or a higher-level framework which +encompasses GSSAPI, such as SASL) for secure network communication +over using the libkrb5 API directly. + +GSSAPIv2 is specified in :rfc:`2743` and :rfc:`2744`. Also see +:rfc:`7546` for a description of how to use the GSSAPI in a client or +server program. + +This documentation will describe how various ways of using the +GSSAPI will behave with the krb5 mechanism as implemented in MIT krb5, +as well as krb5-specific extensions to the GSSAPI. + + +Name types +---------- + +A GSSAPI application can name a local or remote entity by calling +gss_import_name_, specifying a name type and a value. The following +name types are supported by the krb5 mechanism: + +* **GSS_C_NT_HOSTBASED_SERVICE**: The value should be a string of the + form ``service`` or ``service@hostname``. This is the most common + way to name target services when initiating a security context, and + is the most likely name type to work across multiple mechanisms. + +* **GSS_KRB5_NT_PRINCIPAL_NAME**: The value should be a principal name + string. This name type only works with the krb5 mechanism, and is + defined in the ```` header. + +* **GSS_C_NT_USER_NAME** or **GSS_C_NULL_OID**: The value is treated + as an unparsed principal name string, as above. These name types + may work with mechanisms other than krb5, but will have different + interpretations in those mechanisms. **GSS_C_NT_USER_NAME** is + intended to be used with a local username, which will parse into a + single-component principal in the default realm. + +* **GSS_C_NT_ANONYMOUS**: The value is ignored. The anonymous + principal is used, allowing a client to authenticate to a server + without asserting a particular identity (which may or may not be + allowed by a particular server or Kerberos realm). + +* **GSS_C_NT_MACHINE_UID_NAME**: The value is uid_t object. On + Unix-like systems, the username of the uid is looked up in the + system user database and the resulting username is parsed as a + principal name. + +* **GSS_C_NT_STRING_UID_NAME**: As above, but the value is a decimal + string representation of the uid. + +* **GSS_C_NT_EXPORT_NAME**: The value must be the result of a + gss_export_name_ call. + +* **GSS_KRB5_NT_ENTERPRISE_NAME**: The value should be a krb5 + enterprise name string (see :rfc:`6806` section 5), in the form + ``user@suffix``. This name type is used to convey alias names, and + is defined in the ```` header. (New in + release 1.17.) + +* **GSS_KRB5_NT_X509_CERT**: The value should be an X.509 certificate + encoded according to :rfc:`5280`. This name form can be used for + the desired_name parameter of gss_acquire_cred_impersonate_name(), + to identify the S4U2Self user by certificate. (New in release + 1.19.) + + +Initiator credentials +--------------------- + +A GSSAPI client application uses gss_init_sec_context_ to establish a +security context. The *initiator_cred_handle* parameter determines +what tickets are used to establish the connection. An application can +either pass **GSS_C_NO_CREDENTIAL** to use the default client +credential, or it can use gss_acquire_cred_ beforehand to acquire an +initiator credential. The call to gss_acquire_cred_ may include a +*desired_name* parameter, or it may pass **GSS_C_NO_NAME** if it does +not have a specific name preference. + +If the desired name for a krb5 initiator credential is a host-based +name, it is converted to a principal name of the form +``service/hostname`` in the local realm, where *hostname* is the local +hostname if not specified. The hostname will be canonicalized using +forward name resolution, and possibly also using reverse name +resolution depending on the value of the **rdns** variable in +:ref:`libdefaults`. + +If a desired name is specified in the call to gss_acquire_cred_, the +krb5 mechanism will attempt to find existing tickets for that client +principal name in the default credential cache or collection. If the +default cache type does not support a collection, and the default +cache contains credentials for a different principal than the desired +name, a **GSS_S_CRED_UNAVAIL** error will be returned with a minor +code indicating a mismatch. + +If no existing tickets are available for the desired name, but the +name has an entry in the default client :ref:`keytab_definition`, the +krb5 mechanism will acquire initial tickets for the name using the +default client keytab. + +If no desired name is specified, credential acquisition will be +deferred until the credential is used in a call to +gss_init_sec_context_ or gss_inquire_cred_. If the call is to +gss_init_sec_context_, the target name will be used to choose a client +principal name using the credential cache selection facility. (This +facility might, for instance, try to choose existing tickets for a +client principal in the same realm as the target service). If there +are no existing tickets for the chosen principal, but it is present in +the default client keytab, the krb5 mechanism will acquire initial +tickets using the keytab. + +If the target name cannot be used to select a client principal +(because the credentials are used in a call to gss_inquire_cred_), or +if the credential cache selection facility cannot choose a principal +for it, the default credential cache will be selected if it exists and +contains tickets. + +If the default credential cache does not exist, but the default client +keytab does, the krb5 mechanism will try to acquire initial tickets +for the first principal in the default client keytab. + +If the krb5 mechanism acquires initial tickets using the default +client keytab, the resulting tickets will be stored in the default +cache or collection, and will be refreshed by future calls to +gss_acquire_cred_ as they approach their expire time. + + +Acceptor names +-------------- + +A GSSAPI server application uses gss_accept_sec_context_ to establish +a security context based on tokens provided by the client. The +*acceptor_cred_handle* parameter determines what +:ref:`keytab_definition` entries may be authenticated to by the +client, if the krb5 mechanism is used. + +The simplest choice is to pass **GSS_C_NO_CREDENTIAL** as the acceptor +credential. In this case, clients may authenticate to any service +principal in the default keytab (typically |keytab|, or the value of +the **KRB5_KTNAME** environment variable). This is the recommended +approach if the server application has no specific requirements to the +contrary. + +A server may acquire an acceptor credential with gss_acquire_cred_ and +a *cred_usage* of **GSS_C_ACCEPT** or **GSS_C_BOTH**. If the +*desired_name* parameter is **GSS_C_NO_NAME**, then clients will be +allowed to authenticate to any service principal in the default +keytab, just as if no acceptor credential was supplied. + +If a server wishes to specify a *desired_name* to gss_acquire_cred_, +the most common choice is a host-based name. If the host-based +*desired_name* contains just a *service*, then clients will be allowed +to authenticate to any host-based service principal (that is, a +principal of the form ``service/hostname@REALM``) for the named +service, regardless of hostname or realm, as long as it is present in +the default keytab. If the input name contains both a *service* and a +*hostname*, clients will be allowed to authenticate to any host-based +principal for the named service and hostname, regardless of realm. + +.. note:: + + If a *hostname* is specified, it will be canonicalized + using forward name resolution, and possibly also using + reverse name resolution depending on the value of the + **rdns** variable in :ref:`libdefaults`. + +.. note:: + + If the **ignore_acceptor_hostname** variable in + :ref:`libdefaults` is enabled, then *hostname* will be + ignored even if one is specified in the input name. + +.. note:: + + In MIT krb5 versions prior to 1.10, and in Heimdal's + implementation of the krb5 mechanism, an input name with + just a *service* is treated like an input name of + ``service@localhostname``, where *localhostname* is the + string returned by gethostname(). + +If the *desired_name* is a krb5 principal name or a local system name +type which is mapped to a krb5 principal name, clients will only be +allowed to authenticate to that principal in the default keytab. + + +Name Attributes +--------------- + +In release 1.8 or later, the gss_inquire_name_ and +gss_get_name_attribute_ functions, specified in :rfc:`6680`, can be +used to retrieve name attributes from the *src_name* returned by +gss_accept_sec_context_. The following attributes are defined when +the krb5 mechanism is used: + +.. _gssapi_authind_attr: + +* "auth-indicators" attribute: + +This attribute will be included in the gss_inquire_name_ output if the +ticket contains :ref:`authentication indicators `. +One indicator is returned per invocation of gss_get_name_attribute_, +so multiple invocations may be necessary to retrieve all of the +indicators from the ticket. (New in release 1.15.) + + +Credential store extensions +--------------------------- + +Beginning with release 1.11, the following GSSAPI extensions declared +in ```` can be used to specify how credentials +are acquired or stored:: + + struct gss_key_value_element_struct { + const char *key; + const char *value; + }; + typedef struct gss_key_value_element_struct gss_key_value_element_desc; + + struct gss_key_value_set_struct { + OM_uint32 count; + gss_key_value_element_desc *elements; + }; + typedef const struct gss_key_value_set_struct gss_key_value_set_desc; + typedef const gss_key_value_set_desc *gss_const_key_value_set_t; + + OM_uint32 gss_acquire_cred_from(OM_uint32 *minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec); + + OM_uint32 gss_store_cred_into(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + gss_cred_usage_t cred_usage, + const gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_const_key_value_set_t cred_store, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored); + +The additional *cred_store* parameter allows the caller to specify +information about how the credentials should be obtained and stored. +The following options are supported by the krb5 mechanism: + +* **ccache**: For acquiring initiator credentials, the name of the + :ref:`credential cache ` to which the handle will + refer. For storing credentials, the name of the cache or collection + where the credentials will be stored (see below). + +* **client_keytab**: For acquiring initiator credentials, the name of + the :ref:`keytab ` which will be used, if + necessary, to refresh the credentials in the cache. + +* **keytab**: For acquiring acceptor credentials, the name of the + :ref:`keytab ` to which the handle will refer. + In release 1.19 and later, this option also determines the keytab to + be used for verification when initiator credentials are acquired + using a password and verified. + +* **password**: For acquiring initiator credentials, this option + instructs the mechanism to acquire fresh credentials into a unique + memory credential cache. This option may not be used with the + **ccache** or **client_keytab** options, and a *desired_name* must + be specified. (New in release 1.19.) + +* **rcache**: For acquiring acceptor credentials, the name of the + :ref:`replay cache ` to be used when processing + the initiator tokens. (New in release 1.13.) + +* **verify**: For acquiring initiator credentials, this option + instructs the mechanism to verify the credentials by obtaining a + ticket to a service with a known key. The service key is obtained + from the keytab specified with the **keytab** option or the default + keytab. The value may be the name of a principal in the keytab, or + the empty string. If the empty string is given, any ``host`` + service principal in the keytab may be used. (New in release 1.19.) + +In release 1.20 or later, if a collection name is specified for +**cache** in a call to gss_store_cred_into(), an existing cache for +the client principal within the collection will be selected, or a new +cache will be created within the collection. If *overwrite_cred* is +false and the selected credential cache already exists, a +**GSS_S_DUPLICATE_ELEMENT** error will be returned. If *default_cred* +is true, the primary cache of the collection will be switched to the +selected cache. + + +Importing and exporting credentials +----------------------------------- + +The following GSSAPI extensions can be used to import and export +credentials (declared in ````):: + + OM_uint32 gss_export_cred(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + gss_buffer_t token); + + OM_uint32 gss_import_cred(OM_uint32 *minor_status, + gss_buffer_t token, + gss_cred_id_t *cred_handle); + +The first function serializes a GSSAPI credential handle into a +buffer; the second unseralizes a buffer into a GSSAPI credential +handle. Serializing a credential does not destroy it. If any of the +mechanisms used in *cred_handle* do not support serialization, +gss_export_cred will return **GSS_S_UNAVAILABLE**. As with other +GSSAPI serialization functions, these extensions are only intended to +work with a matching implementation on the other side; they do not +serialize credentials in a standardized format. + +A serialized credential may contain secret information such as ticket +session keys. The serialization format does not protect this +information from eavesdropping or tampering. The calling application +must take care to protect the serialized credential when communicating +it over an insecure channel or to an untrusted party. + +A krb5 GSSAPI credential may contain references to a credential cache, +a client keytab, an acceptor keytab, and a replay cache. These +resources are normally serialized as references to their external +locations (such as the filename of the credential cache). Because of +this, a serialized krb5 credential can only be imported by a process +with similar privileges to the exporter. A serialized credential +should not be trusted if it originates from a source with lower +privileges than the importer, as it may contain references to external +credential cache, keytab, or replay cache resources not accessible to +the originator. + +An exception to the above rule applies when a krb5 GSSAPI credential +refers to a memory credential cache, as is normally the case for +delegated credentials received by gss_accept_sec_context_. In this +case, the contents of the credential cache are serialized, so that the +resulting token may be imported even if the original memory credential +cache no longer exists. + + +Constrained delegation (S4U) +---------------------------- + +The Microsoft S4U2Self and S4U2Proxy Kerberos protocol extensions +allow an intermediate service to acquire credentials from a client to +a target service without requiring the client to delegate a +ticket-granting ticket, if the KDC is configured to allow it. + +To perform a constrained delegation operation, the intermediate +service must submit to the KDC an "evidence ticket" from the client to +the intermediate service. An evidence ticket can be acquired when the +client authenticates to the intermediate service with Kerberos, or +with an S4U2Self request if the KDC allows it. The MIT krb5 GSSAPI +library represents an evidence ticket using a "proxy credential", +which is a special kind of gss_cred_id_t object whose underlying +credential cache contains the evidence ticket and a krbtgt ticket for +the intermediate service. + +To acquire a proxy credential during client authentication, the +service should first create an acceptor credential using the +**GSS_C_BOTH** usage. The application should then pass this +credential as the *acceptor_cred_handle* to gss_accept_sec_context_, +and also pass a *delegated_cred_handle* output parameter to receive a +proxy credential containing the evidence ticket. The output value of +*delegated_cred_handle* may be a delegated ticket-granting ticket if +the client sent one, or a proxy credential if not. If the library can +determine that the client's ticket is not a valid evidence ticket, it +will place **GSS_C_NO_CREDENTIAL** in *delegated_cred_handle*. + +To acquire a proxy credential using an S4U2Self request, the service +can use the following GSSAPI extension:: + + OM_uint32 gss_acquire_cred_impersonate_name(OM_uint32 *minor_status, + gss_cred_id_t icred, + gss_name_t desired_name, + OM_uint32 time_req, + gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec); + +The parameters to this function are similar to those of +gss_acquire_cred_, except that *icred* is used to make an S4U2Self +request to the KDC for a ticket from *desired_name* to the +intermediate service. Both *icred* and *desired_name* are required +for this function; passing **GSS_C_NO_CREDENTIAL** or +**GSS_C_NO_NAME** will cause the call to fail. *icred* must contain a +krbtgt ticket for the intermediate service. The result of this +operation is a proxy credential. (Prior to release 1.18, the result +of this operation may be a regular credential for *desired_name*, if +the KDC issues a non-forwardable ticket.) + +Once the intermediate service has a proxy credential, it can simply +pass it to gss_init_sec_context_ as the *initiator_cred_handle* +parameter, and the desired service as the *target_name* parameter. +The GSSAPI library will present the krbtgt ticket and evidence ticket +in the proxy credential to the KDC in an S4U2Proxy request; if the +intermediate service has the appropriate permissions, the KDC will +issue a ticket from the client to the target service. The GSSAPI +library will then use this ticket to authenticate to the target +service. + +If an application needs to find out whether a credential it holds is a +proxy credential and the name of the intermediate service, it can +query the credential with the **GSS_KRB5_GET_CRED_IMPERSONATOR** OID +(new in release 1.16, declared in ````) using +the gss_inquire_cred_by_oid extension (declared in +````):: + + OM_uint32 gss_inquire_cred_by_oid(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + gss_OID desired_object, + gss_buffer_set_t *data_set); + +If the call succeeds and *cred_handle* is a proxy credential, +*data_set* will be set to a single-element buffer set containing the +unparsed principal name of the intermediate service. If *cred_handle* +is not a proxy credential, *data_set* will be set to an empty buffer +set. If the library does not support the query, +gss_inquire_cred_by_oid will return **GSS_S_UNAVAILABLE**. + + +AEAD message wrapping +--------------------- + +The following GSSAPI extensions (declared in +````) can be used to wrap and unwrap messages +with additional "associated data" which is integrity-checked but is +not included in the output buffer:: + + OM_uint32 gss_wrap_aead(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, gss_qop_t qop_req, + gss_buffer_t input_assoc_buffer, + gss_buffer_t input_payload_buffer, + int *conf_state, + gss_buffer_t output_message_buffer); + + OM_uint32 gss_unwrap_aead(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t input_assoc_buffer, + gss_buffer_t output_payload_buffer, + int *conf_state, + gss_qop_t *qop_state); + +Wrap tokens created with gss_wrap_aead will successfully unwrap only +if the same *input_assoc_buffer* contents are presented to +gss_unwrap_aead. + + +IOV message wrapping +-------------------- + +The following extensions (declared in ````) can +be used for in-place encryption, fine-grained control over wrap token +layout, and for constructing wrap tokens compatible with Microsoft DCE +RPC:: + + typedef struct gss_iov_buffer_desc_struct { + OM_uint32 type; + gss_buffer_desc buffer; + } gss_iov_buffer_desc, *gss_iov_buffer_t; + + OM_uint32 gss_wrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, int iov_count); + + OM_uint32 gss_unwrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, int iov_count); + + OM_uint32 gss_wrap_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count); + + OM_uint32 gss_release_iov_buffer(OM_uint32 *minor_status, + gss_iov_buffer_desc *iov, + int iov_count); + +The caller of gss_wrap_iov provides an array of gss_iov_buffer_desc +structures, each containing a type and a gss_buffer_desc structure. +Valid types include: + +* **GSS_C_BUFFER_TYPE_DATA**: A data buffer to be included in the + token, and to be encrypted or decrypted in-place if the token is + confidentiality-protected. + +* **GSS_C_BUFFER_TYPE_HEADER**: The GSSAPI wrap token header and + underlying cryptographic header. + +* **GSS_C_BUFFER_TYPE_TRAILER**: The cryptographic trailer, if one is + required. + +* **GSS_C_BUFFER_TYPE_PADDING**: Padding to be combined with the data + during encryption and decryption. (The implementation may choose to + place padding in the trailer buffer, in which case it will set the + padding buffer length to 0.) + +* **GSS_C_BUFFER_TYPE_STREAM**: For unwrapping only, a buffer + containing a complete wrap token in standard format to be unwrapped. + +* **GSS_C_BUFFER_TYPE_SIGN_ONLY**: A buffer to be included in the + token's integrity protection checksum, but not to be encrypted or + included in the token itself. + +For gss_wrap_iov, the IOV list should contain one HEADER buffer, +followed by zero or more SIGN_ONLY buffers, followed by one or more +DATA buffers, followed by a TRAILER buffer. The memory pointed to by +the buffers is not required to be contiguous or in any particular +order. If *conf_req_flag* is true, DATA buffers will be encrypted +in-place, while SIGN_ONLY buffers will not be modified. + +The type of an output buffer may be combined with +**GSS_C_BUFFER_FLAG_ALLOCATE** to request that gss_wrap_iov allocate +the buffer contents. If gss_wrap_iov allocates a buffer, it sets the +**GSS_C_BUFFER_FLAG_ALLOCATED** flag on the buffer type. +gss_release_iov_buffer can be used to release all allocated buffers +within an iov list and unset their allocated flags. Here is an +example of how gss_wrap_iov can be used with allocation requested +(*ctx* is assumed to be a previously established gss_ctx_id_t):: + + OM_uint32 major, minor; + gss_iov_buffer_desc iov[4]; + char str[] = "message"; + + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE; + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[1].buffer.value = str; + iov[1].buffer.length = strlen(str); + iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_FLAG_ALLOCATE; + iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_FLAG_ALLOCATE; + + major = gss_wrap_iov(&minor, ctx, 1, GSS_C_QOP_DEFAULT, NULL, + iov, 4); + if (GSS_ERROR(major)) + handle_error(major, minor); + + /* Transmit or otherwise use resulting buffers. */ + + (void)gss_release_iov_buffer(&minor, iov, 4); + +If the caller does not choose to request buffer allocation by +gss_wrap_iov, it should first call gss_wrap_iov_length to query the +lengths of the HEADER, PADDING, and TRAILER buffers. DATA buffers +must be provided in the iov list so that padding length can be +computed correctly, but the output buffers need not be initialized. +Here is an example of using gss_wrap_iov_length and gss_wrap_iov:: + + OM_uint32 major, minor; + gss_iov_buffer_desc iov[4]; + char str[1024] = "message", *ptr; + + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[1].buffer.value = str; + iov[1].buffer.length = strlen(str); + + iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING; + iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER; + + major = gss_wrap_iov_length(&minor, ctx, 1, GSS_C_QOP_DEFAULT, + NULL, iov, 4); + if (GSS_ERROR(major)) + handle_error(major, minor); + if (strlen(str) + iov[0].buffer.length + iov[2].buffer.length + + iov[3].buffer.length > sizeof(str)) + handle_out_of_space_error(); + ptr = str + strlen(str); + iov[0].buffer.value = ptr; + ptr += iov[0].buffer.length; + iov[2].buffer.value = ptr; + ptr += iov[2].buffer.length; + iov[3].buffer.value = ptr; + + major = gss_wrap_iov(&minor, ctx, 1, GSS_C_QOP_DEFAULT, NULL, + iov, 4); + if (GSS_ERROR(major)) + handle_error(major, minor); + +If the context was established using the **GSS_C_DCE_STYLE** flag +(described in :rfc:`4757`), wrap tokens compatible with Microsoft DCE +RPC can be constructed. In this case, the IOV list must include a +SIGN_ONLY buffer, a DATA buffer, a second SIGN_ONLY buffer, and a +HEADER buffer in that order (the order of the buffer contents remains +arbitrary). The application must pad the DATA buffer to a multiple of +16 bytes as no padding or trailer buffer is used. + +gss_unwrap_iov may be called with an IOV list just like one which +would be provided to gss_wrap_iov. DATA buffers will be decrypted +in-place if they were encrypted, and SIGN_ONLY buffers will not be +modified. + +Alternatively, gss_unwrap_iov may be called with a single STREAM +buffer, zero or more SIGN_ONLY buffers, and a single DATA buffer. The +STREAM buffer is interpreted as a complete wrap token. The STREAM +buffer will be modified in-place to decrypt its contents. The DATA +buffer will be initialized to point to the decrypted data within the +STREAM buffer, unless it has the **GSS_C_BUFFER_FLAG_ALLOCATE** flag +set, in which case it will be initialized with a copy of the decrypted +data. Here is an example (*token* and *token_len* are assumed to be a +pre-existing pointer and length for a modifiable region of data):: + + OM_uint32 major, minor; + gss_iov_buffer_desc iov[2]; + + iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM; + iov[0].buffer.value = token; + iov[0].buffer.length = token_len; + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + major = gss_unwrap_iov(&minor, ctx, NULL, NULL, iov, 2); + if (GSS_ERROR(major)) + handle_error(major, minor); + + /* Decrypted data is in iov[1].buffer, pointing to a subregion of + * token. */ + +.. _gssapi_mic_token: + +IOV MIC tokens +-------------- + +The following extensions (declared in ````) can +be used in release 1.12 or later to construct and verify MIC tokens +using an IOV list:: + + OM_uint32 gss_get_mic_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t qop_req, + gss_iov_buffer_desc *iov, + int iov_count); + + OM_uint32 gss_get_mic_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t qop_req, + gss_iov_buffer_desc *iov, + iov_count); + + OM_uint32 gss_verify_mic_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count); + +The caller of gss_get_mic_iov provides an array of gss_iov_buffer_desc +structures, each containing a type and a gss_buffer_desc structure. +Valid types include: + +* **GSS_C_BUFFER_TYPE_DATA** and **GSS_C_BUFFER_TYPE_SIGN_ONLY**: The + corresponding buffer for each of these types will be signed for the + MIC token, in the order provided. + +* **GSS_C_BUFFER_TYPE_MIC_TOKEN**: The GSSAPI MIC token. + +The type of the MIC_TOKEN buffer may be combined with +**GSS_C_BUFFER_FLAG_ALLOCATE** to request that gss_get_mic_iov +allocate the buffer contents. If gss_get_mic_iov allocates the +buffer, it sets the **GSS_C_BUFFER_FLAG_ALLOCATED** flag on the buffer +type. gss_release_iov_buffer can be used to release all allocated +buffers within an iov list and unset their allocated flags. Here is +an example of how gss_get_mic_iov can be used with allocation +requested (*ctx* is assumed to be a previously established +gss_ctx_id_t):: + + OM_uint32 major, minor; + gss_iov_buffer_desc iov[3]; + + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[0].buffer.value = "sign1"; + iov[0].buffer.length = 5; + iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[1].buffer.value = "sign2"; + iov[1].buffer.length = 5; + iov[2].type = GSS_IOV_BUFFER_TYPE_MIC_TOKEN | GSS_IOV_BUFFER_FLAG_ALLOCATE; + + major = gss_get_mic_iov(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 3); + if (GSS_ERROR(major)) + handle_error(major, minor); + + /* Transmit or otherwise use iov[2].buffer. */ + + (void)gss_release_iov_buffer(&minor, iov, 3); + +If the caller does not choose to request buffer allocation by +gss_get_mic_iov, it should first call gss_get_mic_iov_length to query +the length of the MIC_TOKEN buffer. Here is an example of using +gss_get_mic_iov_length and gss_get_mic_iov:: + + OM_uint32 major, minor; + gss_iov_buffer_desc iov[2]; + char data[1024]; + + iov[0].type = GSS_IOV_BUFFER_TYPE_MIC_TOKEN; + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[1].buffer.value = "message"; + iov[1].buffer.length = 7; + + major = gss_get_mic_iov_length(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 2); + if (GSS_ERROR(major)) + handle_error(major, minor); + if (iov[0].buffer.length > sizeof(data)) + handle_out_of_space_error(); + iov[0].buffer.value = data; + + major = gss_get_mic_iov(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 2); + if (GSS_ERROR(major)) + handle_error(major, minor); + + +.. _gss_accept_sec_context: https://tools.ietf.org/html/rfc2744.html#section-5.1 +.. _gss_acquire_cred: https://tools.ietf.org/html/rfc2744.html#section-5.2 +.. _gss_export_name: https://tools.ietf.org/html/rfc2744.html#section-5.13 +.. _gss_get_name_attribute: https://tools.ietf.org/html/6680.html#section-7.5 +.. _gss_import_name: https://tools.ietf.org/html/rfc2744.html#section-5.16 +.. _gss_init_sec_context: https://tools.ietf.org/html/rfc2744.html#section-5.19 +.. _gss_inquire_name: https://tools.ietf.org/html/rfc6680.txt#section-7.4 +.. _gss_inquire_cred: https://tools.ietf.org/html/rfc2744.html#section-5.21 diff --git a/krb5-1.21.3/doc/appdev/h5l_mit_apidiff.rst b/krb5-1.21.3/doc/appdev/h5l_mit_apidiff.rst new file mode 100644 index 00000000..b721b57b --- /dev/null +++ b/krb5-1.21.3/doc/appdev/h5l_mit_apidiff.rst @@ -0,0 +1,28 @@ +Differences between Heimdal and MIT Kerberos API +================================================ + +.. tabularcolumns:: |l|l| + +.. table:: + + ======================================== ================================================= + :c:func:`krb5_auth_con_getaddrs()` H5l: If either of the pointers to local_addr + and remote_addr is not NULL, it is freed + first and then reallocated before being + populated with the content of corresponding + address from authentication context. + :c:func:`krb5_auth_con_setaddrs()` H5l: If either address is NULL, the previous + address remains in place + :c:func:`krb5_auth_con_setports()` H5l: Not implemented as of version 1.3.3 + :c:func:`krb5_auth_con_setrecvsubkey()` H5l: If either port is NULL, the previous + port remains in place + :c:func:`krb5_auth_con_setsendsubkey()` H5l: Not implemented as of version 1.3.3 + :c:func:`krb5_cc_set_config()` MIT: Before version 1.10 it was assumed that + the last argument *data* is ALWAYS non-zero. + :c:func:`krb5_cccol_last_change_time()` MIT: not implemented + :c:func:`krb5_set_default_realm()` H5l: Caches the computed default realm context + field. If the second argument is NULL, + it tries to retrieve it from libdefaults or DNS. + MIT: Computes the default realm each time + if it wasn't explicitly set in the context + ======================================== ================================================= diff --git a/krb5-1.21.3/doc/appdev/index.rst b/krb5-1.21.3/doc/appdev/index.rst new file mode 100644 index 00000000..961bb1e9 --- /dev/null +++ b/krb5-1.21.3/doc/appdev/index.rst @@ -0,0 +1,16 @@ +For application developers +========================== + +.. toctree:: + :maxdepth: 1 + + gssapi.rst + y2038.rst + h5l_mit_apidiff.rst + init_creds.rst + princ_handle.rst + +.. toctree:: + :maxdepth: 1 + + refs/index.rst diff --git a/krb5-1.21.3/doc/appdev/init_creds.rst b/krb5-1.21.3/doc/appdev/init_creds.rst new file mode 100644 index 00000000..5c3c0a87 --- /dev/null +++ b/krb5-1.21.3/doc/appdev/init_creds.rst @@ -0,0 +1,304 @@ +Initial credentials +=================== + +Software that performs tasks such as logging users into a computer +when they type their Kerberos password needs to get initial +credentials (usually ticket granting tickets) from Kerberos. Such +software shares some behavior with the :ref:`kinit(1)` program. + +Whenever a program grants access to a resource (such as a local login +session on a desktop computer) based on a user successfully getting +initial Kerberos credentials, it must verify those credentials against +a secure shared secret (e.g., a host keytab) to ensure that the user +credentials actually originate from a legitimate KDC. Failure to +perform this verification is a critical vulnerability, because a +malicious user can execute the "Zanarotti attack": the user constructs +a fake response that appears to come from the legitimate KDC, but +whose contents come from an attacker-controlled KDC. + +Some applications read a Kerberos password over the network (ideally +over a secure channel), which they then verify against the KDC. While +this technique may be the only practical way to integrate Kerberos +into some existing legacy systems, its use is contrary to the original +design goals of Kerberos. + +The function :c:func:`krb5_get_init_creds_password` will get initial +credentials for a client using a password. An application that needs +to verify the credentials can call :c:func:`krb5_verify_init_creds`. +Here is an example of code to obtain and verify TGT credentials, given +strings *princname* and *password* for the client principal name and +password:: + + krb5_error_code ret; + krb5_creds creds; + krb5_principal client_princ = NULL; + + memset(&creds, 0, sizeof(creds)); + ret = krb5_parse_name(context, princname, &client_princ); + if (ret) + goto cleanup; + ret = krb5_get_init_creds_password(context, &creds, client_princ, + password, NULL, NULL, 0, NULL, NULL); + if (ret) + goto cleanup; + ret = krb5_verify_init_creds(context, &creds, NULL, NULL, NULL, NULL); + + cleanup: + krb5_free_principal(context, client_princ); + krb5_free_cred_contents(context, &creds); + return ret; + +Options for get_init_creds +-------------------------- + +The function :c:func:`krb5_get_init_creds_password` takes an options +parameter (which can be a null pointer). Use the function +:c:func:`krb5_get_init_creds_opt_alloc` to allocate an options +structure, and :c:func:`krb5_get_init_creds_opt_free` to free it. For +example:: + + krb5_error_code ret; + krb5_get_init_creds_opt *opt = NULL; + krb5_creds creds; + + memset(&creds, 0, sizeof(creds)); + ret = krb5_get_init_creds_opt_alloc(context, &opt); + if (ret) + goto cleanup; + krb5_get_init_creds_opt_set_tkt_life(opt, 24 * 60 * 60); + ret = krb5_get_init_creds_password(context, &creds, client_princ, + password, NULL, NULL, 0, NULL, opt); + if (ret) + goto cleanup; + + cleanup: + krb5_get_init_creds_opt_free(context, opt); + krb5_free_cred_contents(context, &creds); + return ret; + +Getting anonymous credentials +----------------------------- + +As of release 1.8, it is possible to obtain fully anonymous or +partially anonymous (realm-exposed) credentials, if the KDC supports +it. The MIT KDC supports issuing fully anonymous credentials as of +release 1.8 if configured appropriately (see :ref:`anonymous_pkinit`), +but does not support issuing realm-exposed anonymous credentials at +this time. + +To obtain fully anonymous credentials, call +:c:func:`krb5_get_init_creds_opt_set_anonymous` on the options +structure to set the anonymous flag, and specify a client principal +with the KDC's realm and a single empty data component (the principal +obtained by parsing ``@``\ *realmname*). Authentication will take +place using anonymous PKINIT; if successful, the client principal of +the resulting tickets will be +``WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS``. Here is an example:: + + krb5_get_init_creds_opt_set_anonymous(opt, 1); + ret = krb5_build_principal(context, &client_princ, strlen(myrealm), + myrealm, "", (char *)NULL); + if (ret) + goto cleanup; + ret = krb5_get_init_creds_password(context, &creds, client_princ, + password, NULL, NULL, 0, NULL, opt); + if (ret) + goto cleanup; + +To obtain realm-exposed anonymous credentials, set the anonymous flag +on the options structure as above, but specify a normal client +principal in order to prove membership in the realm. Authentication +will take place as it normally does; if successful, the client +principal of the resulting tickets will be ``WELLKNOWN/ANONYMOUS@``\ +*realmname*. + +User interaction +---------------- + +Authenticating a user usually requires the entry of secret +information, such as a password. A password can be supplied directly +to :c:func:`krb5_get_init_creds_password` via the *password* +parameter, or the application can supply prompter and/or responder +callbacks instead. If callbacks are used, the user can also be +queried for other secret information such as a PIN, informed of +impending password expiration, or prompted to change a password which +has expired. + +Prompter callback +~~~~~~~~~~~~~~~~~ + +A prompter callback can be specified via the *prompter* and *data* +parameters to :c:func:`krb5_get_init_creds_password`. The prompter +will be invoked each time the krb5 library has a question to ask or +information to present. When the prompter callback is invoked, the +*banner* argument (if not null) is intended to be displayed to the +user, and the questions to be answered are specified in the *prompts* +array. Each prompt contains a text question in the *prompt* field, a +*hidden* bit to indicate whether the answer should be hidden from +display, and a storage area for the answer in the *reply* field. The +callback should fill in each question's ``reply->data`` with the +answer, up to a maximum number of ``reply->length`` bytes, and then +reset ``reply->length`` to the length of the answer. + +A prompter callback can call :c:func:`krb5_get_prompt_types` to get an +array of type constants corresponding to the prompts, to get +programmatic information about the semantic meaning of the questions. +:c:func:`krb5_get_prompt_types` may return a null pointer if no prompt +type information is available. + +Text-based applications can use a built-in text prompter +implementation by supplying :c:func:`krb5_prompter_posix` as the +*prompter* parameter and a null pointer as the *data* parameter. For +example:: + + ret = krb5_get_init_creds_password(context, &creds, client_princ, + NULL, krb5_prompter_posix, NULL, 0, + NULL, NULL); + +Responder callback +~~~~~~~~~~~~~~~~~~ + +A responder callback can be specified through the init_creds options +using the :c:func:`krb5_get_init_creds_opt_set_responder` function. +Responder callbacks can present a more sophisticated user interface +for authentication secrets. The responder callback is usually invoked +only once per authentication, with a list of questions produced by all +of the allowed preauthentication mechanisms. + +When the responder callback is invoked, the *rctx* argument can be +accessed to obtain the list of questions and to answer them. The +:c:func:`krb5_responder_list_questions` function retrieves an array of +question types. For each question type, the +:c:func:`krb5_responder_get_challenge` function retrieves additional +information about the question, if applicable, and the +:c:func:`krb5_responder_set_answer` function sets the answer. + +Responder question types, challenges, and answers are UTF-8 strings. +The question type is a well-known string; the meaning of the challenge +and answer depend on the question type. If an application does not +understand a question type, it cannot interpret the challenge or +provide an answer. Failing to answer a question typically results in +the prompter callback being used as a fallback. + +Password question +################# + +The :c:macro:`KRB5_RESPONDER_QUESTION_PASSWORD` (or ``"password"``) +question type requests the user's password. This question does not +have a challenge, and the response is simply the password string. + +One-time password question +########################## + +The :c:macro:`KRB5_RESPONDER_QUESTION_OTP` (or ``"otp"``) question +type requests a choice among one-time password tokens and the PIN and +value for the chosen token. The challenge and answer are JSON-encoded +strings, but an application can use convenience functions to avoid +doing any JSON processing itself. + +The :c:func:`krb5_responder_otp_get_challenge` function decodes the +challenge into a krb5_responder_otp_challenge structure. The +:c:func:`krb5_responder_otp_set_answer` function selects one of the +token information elements from the challenge and supplies the value +and pin for that token. + +PKINIT password or PIN question +############################### + +The :c:macro:`KRB5_RESPONDER_QUESTION_PKINIT` (or ``"pkinit"``) question +type requests PINs for hardware devices and/or passwords for encrypted +credentials which are stored on disk, potentially also supplying +information about the state of the hardware devices. The challenge and +answer are JSON-encoded strings, but an application can use convenience +functions to avoid doing any JSON processing itself. + +The :c:func:`krb5_responder_pkinit_get_challenge` function decodes the +challenges into a krb5_responder_pkinit_challenge structure. The +:c:func:`krb5_responder_pkinit_set_answer` function can be used to +supply the PIN or password for a particular client credential, and can +be called multiple times. + +Example +####### + +Here is an example of using a responder callback:: + + static krb5_error_code + my_responder(krb5_context context, void *data, + krb5_responder_context rctx) + { + krb5_error_code ret; + krb5_responder_otp_challenge *chl; + + if (krb5_responder_get_challenge(context, rctx, + KRB5_RESPONDER_QUESTION_PASSWORD)) { + ret = krb5_responder_set_answer(context, rctx, + KRB5_RESPONDER_QUESTION_PASSWORD, + "open sesame"); + if (ret) + return ret; + } + ret = krb5_responder_otp_get_challenge(context, rctx, &chl); + if (ret == 0 && chl != NULL) { + ret = krb5_responder_otp_set_answer(context, rctx, 0, "1234", + NULL); + krb5_responder_otp_challenge_free(context, rctx, chl); + if (ret) + return ret; + } + return 0; + } + + static krb5_error_code + get_creds(krb5_context context, krb5_principal client_princ) + { + krb5_error_code ret; + krb5_get_init_creds_opt *opt = NULL; + krb5_creds creds; + + memset(&creds, 0, sizeof(creds)); + ret = krb5_get_init_creds_opt_alloc(context, &opt); + if (ret) + goto cleanup; + ret = krb5_get_init_creds_opt_set_responder(context, opt, my_responder, + NULL); + if (ret) + goto cleanup; + ret = krb5_get_init_creds_password(context, &creds, client_princ, + NULL, NULL, NULL, 0, NULL, opt); + + cleanup: + krb5_get_init_creds_opt_free(context, opt); + krb5_free_cred_contents(context, &creds); + return ret; + } + +Verifying initial credentials +----------------------------- + +Use the function :c:func:`krb5_verify_init_creds` to verify initial +credentials. It takes an options structure (which can be a null +pointer). Use :c:func:`krb5_verify_init_creds_opt_init` to initialize +the caller-allocated options structure, and +:c:func:`krb5_verify_init_creds_opt_set_ap_req_nofail` to set the +"nofail" option. For example:: + + krb5_verify_init_creds_opt vopt; + + krb5_verify_init_creds_opt_init(&vopt); + krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, 1); + ret = krb5_verify_init_creds(context, &creds, NULL, NULL, NULL, &vopt); + +The confusingly named "nofail" option, when set, means that the +verification must actually succeed in order for +:c:func:`krb5_verify_init_creds` to indicate success. The default +state of this option (cleared) means that if there is no key material +available to verify the user credentials, the verification will +succeed anyway. (The default can be changed by a configuration file +setting.) + +This accommodates a use case where a large number of unkeyed shared +desktop workstations need to allow users to log in using Kerberos. +The security risks from this practice are mitigated by the absence of +valuable state on the shared workstations---any valuable resources +that the users would access reside on networked servers. diff --git a/krb5-1.21.3/doc/appdev/princ_handle.rst b/krb5-1.21.3/doc/appdev/princ_handle.rst new file mode 100644 index 00000000..455f00a4 --- /dev/null +++ b/krb5-1.21.3/doc/appdev/princ_handle.rst @@ -0,0 +1,79 @@ +Principal manipulation and parsing +================================== + +Kerberos principal structure + +.. + +:c:type:`krb5_principal_data` + +:c:type:`krb5_principal` + +.. + +Create and free principal + +.. + +:c:func:`krb5_build_principal()` + +:c:func:`krb5_build_principal_alloc_va()` + +:c:func:`krb5_build_principal_ext()` + +:c:func:`krb5_copy_principal()` + +:c:func:`krb5_free_principal()` + +:c:func:`krb5_cc_get_principal()` + +.. + +Comparing + +.. + +:c:func:`krb5_principal_compare()` + +:c:func:`krb5_principal_compare_flags()` + +:c:func:`krb5_principal_compare_any_realm()` + +:c:func:`krb5_sname_match()` + +:c:func:`krb5_sname_to_principal()` + +.. + + +Parsing: + +.. + +:c:func:`krb5_parse_name()` + +:c:func:`krb5_parse_name_flags()` + +:c:func:`krb5_unparse_name()` + +:c:func:`krb5_unparse_name_flags()` + +.. + +Utilities: + +.. + +:c:func:`krb5_is_config_principal()` + +:c:func:`krb5_kuserok()` + +:c:func:`krb5_set_password()` + +:c:func:`krb5_set_password_using_ccache()` + +:c:func:`krb5_set_principal_realm()` + +:c:func:`krb5_realm_compare()` + +.. diff --git a/krb5-1.21.3/doc/appdev/refs/api/index.rst b/krb5-1.21.3/doc/appdev/refs/api/index.rst new file mode 100644 index 00000000..d12be47c --- /dev/null +++ b/krb5-1.21.3/doc/appdev/refs/api/index.rst @@ -0,0 +1,413 @@ +krb5 API +======== + + +Frequently used public interfaces +---------------------------------- + +.. toctree:: + :maxdepth: 1 + + krb5_build_principal.rst + krb5_build_principal_alloc_va.rst + krb5_build_principal_ext.rst + krb5_cc_close.rst + krb5_cc_default.rst + krb5_cc_default_name.rst + krb5_cc_destroy.rst + krb5_cc_dup.rst + krb5_cc_get_name.rst + krb5_cc_get_principal.rst + krb5_cc_get_type.rst + krb5_cc_initialize.rst + krb5_cc_new_unique.rst + krb5_cc_resolve.rst + krb5_change_password.rst + krb5_chpw_message.rst + krb5_expand_hostname.rst + krb5_free_context.rst + krb5_free_error_message.rst + krb5_free_principal.rst + krb5_fwd_tgt_creds.rst + krb5_get_default_realm.rst + krb5_get_error_message.rst + krb5_get_host_realm.rst + krb5_get_credentials.rst + krb5_get_fallback_host_realm.rst + krb5_get_init_creds_keytab.rst + krb5_get_init_creds_opt_alloc.rst + krb5_get_init_creds_opt_free.rst + krb5_get_init_creds_opt_get_fast_flags.rst + krb5_get_init_creds_opt_set_address_list.rst + krb5_get_init_creds_opt_set_anonymous.rst + krb5_get_init_creds_opt_set_canonicalize.rst + krb5_get_init_creds_opt_set_change_password_prompt.rst + krb5_get_init_creds_opt_set_etype_list.rst + krb5_get_init_creds_opt_set_expire_callback.rst + krb5_get_init_creds_opt_set_fast_ccache.rst + krb5_get_init_creds_opt_set_fast_ccache_name.rst + krb5_get_init_creds_opt_set_fast_flags.rst + krb5_get_init_creds_opt_set_forwardable.rst + krb5_get_init_creds_opt_set_in_ccache.rst + krb5_get_init_creds_opt_set_out_ccache.rst + krb5_get_init_creds_opt_set_pa.rst + krb5_get_init_creds_opt_set_pac_request.rst + krb5_get_init_creds_opt_set_preauth_list.rst + krb5_get_init_creds_opt_set_proxiable.rst + krb5_get_init_creds_opt_set_renew_life.rst + krb5_get_init_creds_opt_set_responder.rst + krb5_get_init_creds_opt_set_salt.rst + krb5_get_init_creds_opt_set_tkt_life.rst + krb5_get_init_creds_password.rst + krb5_get_profile.rst + krb5_get_prompt_types.rst + krb5_get_renewed_creds.rst + krb5_get_validated_creds.rst + krb5_init_context.rst + krb5_init_secure_context.rst + krb5_is_config_principal.rst + krb5_is_thread_safe.rst + krb5_kt_close.rst + krb5_kt_client_default.rst + krb5_kt_default.rst + krb5_kt_default_name.rst + krb5_kt_dup.rst + krb5_kt_get_name.rst + krb5_kt_get_type.rst + krb5_kt_resolve.rst + krb5_kuserok.rst + krb5_parse_name.rst + krb5_parse_name_flags.rst + krb5_principal_compare.rst + krb5_principal_compare_any_realm.rst + krb5_principal_compare_flags.rst + krb5_prompter_posix.rst + krb5_realm_compare.rst + krb5_responder_get_challenge.rst + krb5_responder_list_questions.rst + krb5_responder_set_answer.rst + krb5_responder_otp_get_challenge.rst + krb5_responder_otp_set_answer.rst + krb5_responder_otp_challenge_free.rst + krb5_responder_pkinit_get_challenge.rst + krb5_responder_pkinit_set_answer.rst + krb5_responder_pkinit_challenge_free.rst + krb5_set_default_realm.rst + krb5_set_password.rst + krb5_set_password_using_ccache.rst + krb5_set_principal_realm.rst + krb5_set_trace_callback.rst + krb5_set_trace_filename.rst + krb5_sname_match.rst + krb5_sname_to_principal.rst + krb5_unparse_name.rst + krb5_unparse_name_ext.rst + krb5_unparse_name_flags.rst + krb5_unparse_name_flags_ext.rst + krb5_us_timeofday.rst + krb5_verify_authdata_kdc_issued.rst + +Rarely used public interfaces +-------------------------------- + +.. toctree:: + :maxdepth: 1 + + krb5_425_conv_principal.rst + krb5_524_conv_principal.rst + krb5_address_compare.rst + krb5_address_order.rst + krb5_address_search.rst + krb5_allow_weak_crypto.rst + krb5_aname_to_localname.rst + krb5_anonymous_principal.rst + krb5_anonymous_realm.rst + krb5_appdefault_boolean.rst + krb5_appdefault_string.rst + krb5_auth_con_free.rst + krb5_auth_con_genaddrs.rst + krb5_auth_con_get_checksum_func.rst + krb5_auth_con_getaddrs.rst + krb5_auth_con_getauthenticator.rst + krb5_auth_con_getflags.rst + krb5_auth_con_getkey.rst + krb5_auth_con_getkey_k.rst + krb5_auth_con_getlocalseqnumber.rst + krb5_auth_con_getrcache.rst + krb5_auth_con_getrecvsubkey.rst + krb5_auth_con_getrecvsubkey_k.rst + krb5_auth_con_getremoteseqnumber.rst + krb5_auth_con_getsendsubkey.rst + krb5_auth_con_getsendsubkey_k.rst + krb5_auth_con_init.rst + krb5_auth_con_set_checksum_func.rst + krb5_auth_con_set_req_cksumtype.rst + krb5_auth_con_setaddrs.rst + krb5_auth_con_setflags.rst + krb5_auth_con_setports.rst + krb5_auth_con_setrcache.rst + krb5_auth_con_setrecvsubkey.rst + krb5_auth_con_setrecvsubkey_k.rst + krb5_auth_con_setsendsubkey.rst + krb5_auth_con_setsendsubkey_k.rst + krb5_auth_con_setuseruserkey.rst + krb5_cc_cache_match.rst + krb5_cc_copy_creds.rst + krb5_cc_end_seq_get.rst + krb5_cc_get_config.rst + krb5_cc_get_flags.rst + krb5_cc_get_full_name.rst + krb5_cc_move.rst + krb5_cc_next_cred.rst + krb5_cc_remove_cred.rst + krb5_cc_retrieve_cred.rst + krb5_cc_select.rst + krb5_cc_set_config.rst + krb5_cc_set_default_name.rst + krb5_cc_set_flags.rst + krb5_cc_start_seq_get.rst + krb5_cc_store_cred.rst + krb5_cc_support_switch.rst + krb5_cc_switch.rst + krb5_cccol_cursor_free.rst + krb5_cccol_cursor_new.rst + krb5_cccol_cursor_next.rst + krb5_cccol_have_content.rst + krb5_clear_error_message.rst + krb5_check_clockskew.rst + krb5_copy_addresses.rst + krb5_copy_authdata.rst + krb5_copy_authenticator.rst + krb5_copy_checksum.rst + krb5_copy_context.rst + krb5_copy_creds.rst + krb5_copy_data.rst + krb5_copy_error_message.rst + krb5_copy_keyblock.rst + krb5_copy_keyblock_contents.rst + krb5_copy_principal.rst + krb5_copy_ticket.rst + krb5_find_authdata.rst + krb5_free_addresses.rst + krb5_free_ap_rep_enc_part.rst + krb5_free_authdata.rst + krb5_free_authenticator.rst + krb5_free_cred_contents.rst + krb5_free_creds.rst + krb5_free_data.rst + krb5_free_data_contents.rst + krb5_free_default_realm.rst + krb5_free_enctypes.rst + krb5_free_error.rst + krb5_free_host_realm.rst + krb5_free_keyblock.rst + krb5_free_keyblock_contents.rst + krb5_free_keytab_entry_contents.rst + krb5_free_string.rst + krb5_free_ticket.rst + krb5_free_unparsed_name.rst + krb5_get_etype_info.rst + krb5_get_permitted_enctypes.rst + krb5_get_server_rcache.rst + krb5_get_time_offsets.rst + krb5_init_context_profile.rst + krb5_init_creds_free.rst + krb5_init_creds_get.rst + krb5_init_creds_get_creds.rst + krb5_init_creds_get_error.rst + krb5_init_creds_get_times.rst + krb5_init_creds_init.rst + krb5_init_creds_set_keytab.rst + krb5_init_creds_set_password.rst + krb5_init_creds_set_service.rst + krb5_init_creds_step.rst + krb5_init_keyblock.rst + krb5_is_referral_realm.rst + krb5_kdc_sign_ticket.rst + krb5_kdc_verify_ticket.rst + krb5_kt_add_entry.rst + krb5_kt_end_seq_get.rst + krb5_kt_get_entry.rst + krb5_kt_have_content.rst + krb5_kt_next_entry.rst + krb5_kt_read_service_key.rst + krb5_kt_remove_entry.rst + krb5_kt_start_seq_get.rst + krb5_make_authdata_kdc_issued.rst + krb5_marshal_credentials.rst + krb5_merge_authdata.rst + krb5_mk_1cred.rst + krb5_mk_error.rst + krb5_mk_ncred.rst + krb5_mk_priv.rst + krb5_mk_rep.rst + krb5_mk_rep_dce.rst + krb5_mk_req.rst + krb5_mk_req_extended.rst + krb5_mk_safe.rst + krb5_os_localaddr.rst + krb5_pac_add_buffer.rst + krb5_pac_free.rst + krb5_pac_get_buffer.rst + krb5_pac_get_types.rst + krb5_pac_init.rst + krb5_pac_parse.rst + krb5_pac_sign.rst + krb5_pac_sign_ext.rst + krb5_pac_verify.rst + krb5_pac_verify_ext.rst + krb5_pac_get_client_info.rst + krb5_prepend_error_message.rst + krb5_principal2salt.rst + krb5_rd_cred.rst + krb5_rd_error.rst + krb5_rd_priv.rst + krb5_rd_rep.rst + krb5_rd_rep_dce.rst + krb5_rd_req.rst + krb5_rd_safe.rst + krb5_read_password.rst + krb5_salttype_to_string.rst + krb5_server_decrypt_ticket_keytab.rst + krb5_set_default_tgs_enctypes.rst + krb5_set_error_message.rst + krb5_set_kdc_recv_hook.rst + krb5_set_kdc_send_hook.rst + krb5_set_real_time.rst + krb5_string_to_cksumtype.rst + krb5_string_to_deltat.rst + krb5_string_to_enctype.rst + krb5_string_to_salttype.rst + krb5_string_to_timestamp.rst + krb5_timeofday.rst + krb5_timestamp_to_sfstring.rst + krb5_timestamp_to_string.rst + krb5_tkt_creds_free.rst + krb5_tkt_creds_get.rst + krb5_tkt_creds_get_creds.rst + krb5_tkt_creds_get_times.rst + krb5_tkt_creds_init.rst + krb5_tkt_creds_step.rst + krb5_unmarshal_credentials.rst + krb5_verify_init_creds.rst + krb5_verify_init_creds_opt_init.rst + krb5_verify_init_creds_opt_set_ap_req_nofail.rst + krb5_vprepend_error_message.rst + krb5_vset_error_message.rst + krb5_vwrap_error_message.rst + krb5_wrap_error_message.rst + + +Public interfaces that should not be called directly +------------------------------------------------------- + +.. toctree:: + :maxdepth: 1 + + krb5_c_block_size.rst + krb5_c_checksum_length.rst + krb5_c_crypto_length.rst + krb5_c_crypto_length_iov.rst + krb5_c_decrypt.rst + krb5_c_decrypt_iov.rst + krb5_c_derive_prfplus.rst + krb5_c_encrypt.rst + krb5_c_encrypt_iov.rst + krb5_c_encrypt_length.rst + krb5_c_enctype_compare.rst + krb5_c_free_state.rst + krb5_c_fx_cf2_simple.rst + krb5_c_init_state.rst + krb5_c_is_coll_proof_cksum.rst + krb5_c_is_keyed_cksum.rst + krb5_c_keyed_checksum_types.rst + krb5_c_keylengths.rst + krb5_c_make_checksum.rst + krb5_c_make_checksum_iov.rst + krb5_c_make_random_key.rst + krb5_c_padding_length.rst + krb5_c_prf.rst + krb5_c_prfplus.rst + krb5_c_prf_length.rst + krb5_c_random_add_entropy.rst + krb5_c_random_make_octets.rst + krb5_c_random_os_entropy.rst + krb5_c_random_to_key.rst + krb5_c_string_to_key.rst + krb5_c_string_to_key_with_params.rst + krb5_c_valid_cksumtype.rst + krb5_c_valid_enctype.rst + krb5_c_verify_checksum.rst + krb5_c_verify_checksum_iov.rst + krb5_cksumtype_to_string.rst + krb5_decode_authdata_container.rst + krb5_decode_ticket.rst + krb5_deltat_to_string.rst + krb5_encode_authdata_container.rst + krb5_enctype_to_name.rst + krb5_enctype_to_string.rst + krb5_free_checksum.rst + krb5_free_checksum_contents.rst + krb5_free_cksumtypes.rst + krb5_free_tgt_creds.rst + krb5_k_create_key.rst + krb5_k_decrypt.rst + krb5_k_decrypt_iov.rst + krb5_k_encrypt.rst + krb5_k_encrypt_iov.rst + krb5_k_free_key.rst + krb5_k_key_enctype.rst + krb5_k_key_keyblock.rst + krb5_k_make_checksum.rst + krb5_k_make_checksum_iov.rst + krb5_k_prf.rst + krb5_k_reference_key.rst + krb5_k_verify_checksum.rst + krb5_k_verify_checksum_iov.rst + + +Legacy convenience interfaces +------------------------------ + +.. toctree:: + :maxdepth: 1 + + krb5_recvauth.rst + krb5_recvauth_version.rst + krb5_sendauth.rst + + +Deprecated public interfaces +------------------------------ + +.. toctree:: + :maxdepth: 1 + + krb5_524_convert_creds.rst + krb5_auth_con_getlocalsubkey.rst + krb5_auth_con_getremotesubkey.rst + krb5_auth_con_initivector.rst + krb5_build_principal_va.rst + krb5_c_random_seed.rst + krb5_calculate_checksum.rst + krb5_checksum_size.rst + krb5_encrypt.rst + krb5_decrypt.rst + krb5_eblock_enctype.rst + krb5_encrypt_size.rst + krb5_finish_key.rst + krb5_finish_random_key.rst + krb5_cc_gen_new.rst + krb5_get_credentials_renew.rst + krb5_get_credentials_validate.rst + krb5_get_in_tkt_with_password.rst + krb5_get_in_tkt_with_skey.rst + krb5_get_in_tkt_with_keytab.rst + krb5_get_init_creds_opt_init.rst + krb5_init_random_key.rst + krb5_kt_free_entry.rst + krb5_random_key.rst + krb5_process_key.rst + krb5_string_to_key.rst + krb5_use_enctype.rst + krb5_verify_checksum.rst diff --git a/krb5-1.21.3/doc/appdev/refs/index.rst b/krb5-1.21.3/doc/appdev/refs/index.rst new file mode 100644 index 00000000..37a895f3 --- /dev/null +++ b/krb5-1.21.3/doc/appdev/refs/index.rst @@ -0,0 +1,9 @@ +Complete reference - API and datatypes +====================================== + +.. toctree:: + :maxdepth: 1 + + api/index.rst + types/index.rst + macros/index.rst diff --git a/krb5-1.21.3/doc/appdev/refs/macros/index.rst b/krb5-1.21.3/doc/appdev/refs/macros/index.rst new file mode 100644 index 00000000..45fe160d --- /dev/null +++ b/krb5-1.21.3/doc/appdev/refs/macros/index.rst @@ -0,0 +1,397 @@ +krb5 simple macros +========================= + +Public +------- + +.. toctree:: + :maxdepth: 1 + + ADDRTYPE_ADDRPORT.rst + ADDRTYPE_CHAOS.rst + ADDRTYPE_DDP.rst + ADDRTYPE_INET.rst + ADDRTYPE_INET6.rst + ADDRTYPE_IPPORT.rst + ADDRTYPE_ISO.rst + ADDRTYPE_IS_LOCAL.rst + ADDRTYPE_NETBIOS.rst + ADDRTYPE_XNS.rst + AD_TYPE_EXTERNAL.rst + AD_TYPE_FIELD_TYPE_MASK.rst + AD_TYPE_REGISTERED.rst + AD_TYPE_RESERVED.rst + AP_OPTS_ETYPE_NEGOTIATION.rst + AP_OPTS_MUTUAL_REQUIRED.rst + AP_OPTS_RESERVED.rst + AP_OPTS_USE_SESSION_KEY.rst + AP_OPTS_USE_SUBKEY.rst + AP_OPTS_WIRE_MASK.rst + CKSUMTYPE_CMAC_CAMELLIA128.rst + CKSUMTYPE_CMAC_CAMELLIA256.rst + CKSUMTYPE_CRC32.rst + CKSUMTYPE_DESCBC.rst + CKSUMTYPE_HMAC_MD5_ARCFOUR.rst + CKSUMTYPE_HMAC_SHA1_96_AES128.rst + CKSUMTYPE_HMAC_SHA1_96_AES256.rst + CKSUMTYPE_HMAC_SHA256_128_AES128.rst + CKSUMTYPE_HMAC_SHA384_192_AES256.rst + CKSUMTYPE_HMAC_SHA1_DES3.rst + CKSUMTYPE_MD5_HMAC_ARCFOUR.rst + CKSUMTYPE_NIST_SHA.rst + CKSUMTYPE_RSA_MD4.rst + CKSUMTYPE_RSA_MD4_DES.rst + CKSUMTYPE_RSA_MD5.rst + CKSUMTYPE_RSA_MD5_DES.rst + CKSUMTYPE_SHA1.rst + ENCTYPE_AES128_CTS_HMAC_SHA1_96.rst + ENCTYPE_AES128_CTS_HMAC_SHA256_128.rst + ENCTYPE_AES256_CTS_HMAC_SHA1_96.rst + ENCTYPE_AES256_CTS_HMAC_SHA384_192.rst + ENCTYPE_ARCFOUR_HMAC.rst + ENCTYPE_ARCFOUR_HMAC_EXP.rst + ENCTYPE_CAMELLIA128_CTS_CMAC.rst + ENCTYPE_CAMELLIA256_CTS_CMAC.rst + ENCTYPE_DES3_CBC_ENV.rst + ENCTYPE_DES3_CBC_RAW.rst + ENCTYPE_DES3_CBC_SHA.rst + ENCTYPE_DES3_CBC_SHA1.rst + ENCTYPE_DES_CBC_CRC.rst + ENCTYPE_DES_CBC_MD4.rst + ENCTYPE_DES_CBC_MD5.rst + ENCTYPE_DES_CBC_RAW.rst + ENCTYPE_DES_HMAC_SHA1.rst + ENCTYPE_DSA_SHA1_CMS.rst + ENCTYPE_MD5_RSA_CMS.rst + ENCTYPE_NULL.rst + ENCTYPE_RC2_CBC_ENV.rst + ENCTYPE_RSA_ENV.rst + ENCTYPE_RSA_ES_OAEP_ENV.rst + ENCTYPE_SHA1_RSA_CMS.rst + ENCTYPE_UNKNOWN.rst + KDC_OPT_ALLOW_POSTDATE.rst + KDC_OPT_CANONICALIZE.rst + KDC_OPT_CNAME_IN_ADDL_TKT.rst + KDC_OPT_DISABLE_TRANSITED_CHECK.rst + KDC_OPT_ENC_TKT_IN_SKEY.rst + KDC_OPT_FORWARDABLE.rst + KDC_OPT_FORWARDED.rst + KDC_OPT_POSTDATED.rst + KDC_OPT_PROXIABLE.rst + KDC_OPT_PROXY.rst + KDC_OPT_RENEW.rst + KDC_OPT_RENEWABLE.rst + KDC_OPT_RENEWABLE_OK.rst + KDC_OPT_REQUEST_ANONYMOUS.rst + KDC_OPT_VALIDATE.rst + KDC_TKT_COMMON_MASK.rst + KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE.rst + KRB5_ANONYMOUS_PRINCSTR.rst + KRB5_ANONYMOUS_REALMSTR.rst + KRB5_AP_REP.rst + KRB5_AP_REQ.rst + KRB5_AS_REP.rst + KRB5_AS_REQ.rst + KRB5_AUTHDATA_AND_OR.rst + KRB5_AUTHDATA_AP_OPTIONS.rst + KRB5_AUTHDATA_AUTH_INDICATOR.rst + KRB5_AUTHDATA_CAMMAC.rst + KRB5_AUTHDATA_ETYPE_NEGOTIATION.rst + KRB5_AUTHDATA_FX_ARMOR.rst + KRB5_AUTHDATA_IF_RELEVANT.rst + KRB5_AUTHDATA_INITIAL_VERIFIED_CAS.rst + KRB5_AUTHDATA_KDC_ISSUED.rst + KRB5_AUTHDATA_MANDATORY_FOR_KDC.rst + KRB5_AUTHDATA_OSF_DCE.rst + KRB5_AUTHDATA_SESAME.rst + KRB5_AUTHDATA_SIGNTICKET.rst + KRB5_AUTHDATA_WIN2K_PAC.rst + KRB5_AUTH_CONTEXT_DO_SEQUENCE.rst + KRB5_AUTH_CONTEXT_DO_TIME.rst + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR.rst + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR.rst + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR.rst + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR.rst + KRB5_AUTH_CONTEXT_PERMIT_ALL.rst + KRB5_AUTH_CONTEXT_RET_SEQUENCE.rst + KRB5_AUTH_CONTEXT_RET_TIME.rst + KRB5_AUTH_CONTEXT_USE_SUBKEY.rst + KRB5_CRED.rst + KRB5_CRYPTO_TYPE_CHECKSUM.rst + KRB5_CRYPTO_TYPE_DATA.rst + KRB5_CRYPTO_TYPE_EMPTY.rst + KRB5_CRYPTO_TYPE_HEADER.rst + KRB5_CRYPTO_TYPE_PADDING.rst + KRB5_CRYPTO_TYPE_SIGN_ONLY.rst + KRB5_CRYPTO_TYPE_STREAM.rst + KRB5_CRYPTO_TYPE_TRAILER.rst + KRB5_CYBERSAFE_SECUREID.rst + KRB5_DOMAIN_X500_COMPRESS.rst + KRB5_ENCPADATA_REQ_ENC_PA_REP.rst + KRB5_ERROR.rst + KRB5_FAST_REQUIRED.rst + KRB5_GC_CACHED.rst + KRB5_GC_CANONICALIZE.rst + KRB5_GC_CONSTRAINED_DELEGATION.rst + KRB5_GC_FORWARDABLE.rst + KRB5_GC_NO_STORE.rst + KRB5_GC_NO_TRANSIT_CHECK.rst + KRB5_GC_USER_USER.rst + KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST.rst + KRB5_GET_INIT_CREDS_OPT_ANONYMOUS.rst + KRB5_GET_INIT_CREDS_OPT_CANONICALIZE.rst + KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT.rst + KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST.rst + KRB5_GET_INIT_CREDS_OPT_FORWARDABLE.rst + KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST.rst + KRB5_GET_INIT_CREDS_OPT_PROXIABLE.rst + KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE.rst + KRB5_GET_INIT_CREDS_OPT_SALT.rst + KRB5_GET_INIT_CREDS_OPT_TKT_LIFE.rst + KRB5_INIT_CONTEXT_SECURE.rst + KRB5_INIT_CONTEXT_KDC.rst + KRB5_INIT_CREDS_STEP_FLAG_CONTINUE.rst + KRB5_INT16_MAX.rst + KRB5_INT16_MIN.rst + KRB5_INT32_MAX.rst + KRB5_INT32_MIN.rst + KRB5_KEYUSAGE_AD_ITE.rst + KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM.rst + KRB5_KEYUSAGE_AD_MTE.rst + KRB5_KEYUSAGE_AD_SIGNEDPATH.rst + KRB5_KEYUSAGE_APP_DATA_CKSUM.rst + KRB5_KEYUSAGE_APP_DATA_ENCRYPT.rst + KRB5_KEYUSAGE_AP_REP_ENCPART.rst + KRB5_KEYUSAGE_AP_REQ_AUTH.rst + KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM.rst + KRB5_KEYUSAGE_AS_REP_ENCPART.rst + KRB5_KEYUSAGE_AS_REQ.rst + KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS.rst + KRB5_KEYUSAGE_CAMMAC.rst + KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT.rst + KRB5_KEYUSAGE_ENC_CHALLENGE_KDC.rst + KRB5_KEYUSAGE_FAST_ENC.rst + KRB5_KEYUSAGE_FAST_FINISHED.rst + KRB5_KEYUSAGE_FAST_REP.rst + KRB5_KEYUSAGE_FAST_REQ_CHKSUM.rst + KRB5_KEYUSAGE_GSS_TOK_MIC.rst + KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.rst + KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.rst + KRB5_KEYUSAGE_IAKERB_FINISHED.rst + KRB5_KEYUSAGE_KDC_REP_TICKET.rst + KRB5_KEYUSAGE_KRB_CRED_ENCPART.rst + KRB5_KEYUSAGE_KRB_ERROR_CKSUM.rst + KRB5_KEYUSAGE_KRB_PRIV_ENCPART.rst + KRB5_KEYUSAGE_KRB_SAFE_CKSUM.rst + KRB5_KEYUSAGE_PA_AS_FRESHNESS.rst + KRB5_KEYUSAGE_PA_FX_COOKIE.rst + KRB5_KEYUSAGE_PA_OTP_REQUEST.rst + KRB5_KEYUSAGE_PA_PKINIT_KX.rst + KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY.rst + KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST.rst + KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.rst + KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.rst + KRB5_KEYUSAGE_PA_SAM_RESPONSE.rst + KRB5_KEYUSAGE_SPAKE.rst + KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.rst + KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.rst + KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.rst + KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY.rst + KRB5_KEYUSAGE_TGS_REQ_AUTH.rst + KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM.rst + KRB5_KPASSWD_ACCESSDENIED.rst + KRB5_KPASSWD_AUTHERROR.rst + KRB5_KPASSWD_BAD_VERSION.rst + KRB5_KPASSWD_HARDERROR.rst + KRB5_KPASSWD_INITIAL_FLAG_NEEDED.rst + KRB5_KPASSWD_MALFORMED.rst + KRB5_KPASSWD_SOFTERROR.rst + KRB5_KPASSWD_SUCCESS.rst + KRB5_LRQ_ALL_ACCT_EXPTIME.rst + KRB5_LRQ_ALL_LAST_INITIAL.rst + KRB5_LRQ_ALL_LAST_RENEWAL.rst + KRB5_LRQ_ALL_LAST_REQ.rst + KRB5_LRQ_ALL_LAST_TGT.rst + KRB5_LRQ_ALL_LAST_TGT_ISSUED.rst + KRB5_LRQ_ALL_PW_EXPTIME.rst + KRB5_LRQ_NONE.rst + KRB5_LRQ_ONE_ACCT_EXPTIME.rst + KRB5_LRQ_ONE_LAST_INITIAL.rst + KRB5_LRQ_ONE_LAST_RENEWAL.rst + KRB5_LRQ_ONE_LAST_REQ.rst + KRB5_LRQ_ONE_LAST_TGT.rst + KRB5_LRQ_ONE_LAST_TGT_ISSUED.rst + KRB5_LRQ_ONE_PW_EXPTIME.rst + KRB5_NT_ENTERPRISE_PRINCIPAL.rst + KRB5_NT_ENT_PRINCIPAL_AND_ID.rst + KRB5_NT_MS_PRINCIPAL.rst + KRB5_NT_MS_PRINCIPAL_AND_ID.rst + KRB5_NT_PRINCIPAL.rst + KRB5_NT_SMTP_NAME.rst + KRB5_NT_SRV_HST.rst + KRB5_NT_SRV_INST.rst + KRB5_NT_SRV_XHST.rst + KRB5_NT_UID.rst + KRB5_NT_UNKNOWN.rst + KRB5_NT_WELLKNOWN.rst + KRB5_NT_X500_PRINCIPAL.rst + KRB5_PAC_ATTRIBUTES_INFO.rst + KRB5_PAC_CLIENT_INFO.rst + KRB5_PAC_CLIENT_CLAIMS.rst + KRB5_PAC_CREDENTIALS_INFO.rst + KRB5_PAC_DELEGATION_INFO.rst + KRB5_PAC_DEVICE_CLAIMS.rst + KRB5_PAC_DEVICE_INFO.rst + KRB5_PAC_LOGON_INFO.rst + KRB5_PAC_PRIVSVR_CHECKSUM.rst + KRB5_PAC_REQUESTOR.rst + KRB5_PAC_SERVER_CHECKSUM.rst + KRB5_PAC_TICKET_CHECKSUM.rst + KRB5_PAC_UPN_DNS_INFO.rst + KRB5_PAC_FULL_CHECKSUM.rst + KRB5_PADATA_AFS3_SALT.rst + KRB5_PADATA_AP_REQ.rst + KRB5_PADATA_AS_CHECKSUM.rst + KRB5_PADATA_AS_FRESHNESS.rst + KRB5_PADATA_ENCRYPTED_CHALLENGE.rst + KRB5_PADATA_ENC_SANDIA_SECURID.rst + KRB5_PADATA_ENC_TIMESTAMP.rst + KRB5_PADATA_ENC_UNIX_TIME.rst + KRB5_PADATA_ETYPE_INFO.rst + KRB5_PADATA_ETYPE_INFO2.rst + KRB5_PADATA_FOR_USER.rst + KRB5_PADATA_FX_COOKIE.rst + KRB5_PADATA_FX_ERROR.rst + KRB5_PADATA_FX_FAST.rst + KRB5_PADATA_GET_FROM_TYPED_DATA.rst + KRB5_PADATA_NONE.rst + KRB5_PADATA_OSF_DCE.rst + KRB5_PADATA_OTP_CHALLENGE.rst + KRB5_PADATA_OTP_PIN_CHANGE.rst + KRB5_PADATA_OTP_REQUEST.rst + KRB5_PADATA_PAC_OPTIONS.rst + KRB5_PADATA_PAC_REQUEST.rst + KRB5_PADATA_PKINIT_KX.rst + KRB5_PADATA_PK_AS_REP.rst + KRB5_PADATA_PK_AS_REP_OLD.rst + KRB5_PADATA_PK_AS_REQ.rst + KRB5_PADATA_PK_AS_REQ_OLD.rst + KRB5_PADATA_PW_SALT.rst + KRB5_PADATA_REFERRAL.rst + KRB5_PADATA_S4U_X509_USER.rst + KRB5_PADATA_SAM_CHALLENGE.rst + KRB5_PADATA_SAM_CHALLENGE_2.rst + KRB5_PADATA_SAM_REDIRECT.rst + KRB5_PADATA_SAM_RESPONSE.rst + KRB5_PADATA_SAM_RESPONSE_2.rst + KRB5_PADATA_SESAME.rst + KRB5_PADATA_SPAKE.rst + KRB5_PADATA_REDHAT_IDP_OAUTH2.rst + KRB5_PADATA_REDHAT_PASSKEY.rst + KRB5_PADATA_SVR_REFERRAL_INFO.rst + KRB5_PADATA_TGS_REQ.rst + KRB5_PADATA_USE_SPECIFIED_KVNO.rst + KRB5_PRINCIPAL_COMPARE_CASEFOLD.rst + KRB5_PRINCIPAL_COMPARE_ENTERPRISE.rst + KRB5_PRINCIPAL_COMPARE_IGNORE_REALM.rst + KRB5_PRINCIPAL_COMPARE_UTF8.rst + KRB5_PRINCIPAL_PARSE_ENTERPRISE.rst + KRB5_PRINCIPAL_PARSE_IGNORE_REALM.rst + KRB5_PRINCIPAL_PARSE_NO_DEF_REALM.rst + KRB5_PRINCIPAL_PARSE_NO_REALM.rst + KRB5_PRINCIPAL_PARSE_REQUIRE_REALM.rst + KRB5_PRINCIPAL_UNPARSE_DISPLAY.rst + KRB5_PRINCIPAL_UNPARSE_NO_REALM.rst + KRB5_PRINCIPAL_UNPARSE_SHORT.rst + KRB5_PRIV.rst + KRB5_PROMPT_TYPE_NEW_PASSWORD.rst + KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN.rst + KRB5_PROMPT_TYPE_PASSWORD.rst + KRB5_PROMPT_TYPE_PREAUTH.rst + KRB5_PVNO.rst + KRB5_REALM_BRANCH_CHAR.rst + KRB5_RECVAUTH_BADAUTHVERS.rst + KRB5_RECVAUTH_SKIP_VERSION.rst + KRB5_REFERRAL_REALM.rst + KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW.rst + KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY.rst + KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.rst + KRB5_RESPONDER_QUESTION_PKINIT.rst + KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN.rst + KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN.rst + KRB5_RESPONDER_OTP_FLAGS_NEXTOTP.rst + KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN.rst + KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC.rst + KRB5_RESPONDER_OTP_FORMAT_DECIMAL.rst + KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL.rst + KRB5_RESPONDER_QUESTION_OTP.rst + KRB5_RESPONDER_QUESTION_PASSWORD.rst + KRB5_SAFE.rst + KRB5_SAM_MUST_PK_ENCRYPT_SAD.rst + KRB5_SAM_SEND_ENCRYPTED_SAD.rst + KRB5_SAM_USE_SAD_AS_KEY.rst + KRB5_TC_MATCH_2ND_TKT.rst + KRB5_TC_MATCH_AUTHDATA.rst + KRB5_TC_MATCH_FLAGS.rst + KRB5_TC_MATCH_FLAGS_EXACT.rst + KRB5_TC_MATCH_IS_SKEY.rst + KRB5_TC_MATCH_KTYPE.rst + KRB5_TC_MATCH_SRV_NAMEONLY.rst + KRB5_TC_MATCH_TIMES.rst + KRB5_TC_MATCH_TIMES_EXACT.rst + KRB5_TC_NOTICKET.rst + KRB5_TC_OPENCLOSE.rst + KRB5_TC_SUPPORTED_KTYPES.rst + KRB5_TGS_NAME.rst + KRB5_TGS_NAME_SIZE.rst + KRB5_TGS_REP.rst + KRB5_TGS_REQ.rst + KRB5_TKT_CREDS_STEP_FLAG_CONTINUE.rst + KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL.rst + KRB5_WELLKNOWN_NAMESTR.rst + LR_TYPE_INTERPRETATION_MASK.rst + LR_TYPE_THIS_SERVER_ONLY.rst + MAX_KEYTAB_NAME_LEN.rst + MSEC_DIRBIT.rst + MSEC_VAL_MASK.rst + SALT_TYPE_AFS_LENGTH.rst + SALT_TYPE_NO_LENGTH.rst + THREEPARAMOPEN.rst + TKT_FLG_ANONYMOUS.rst + TKT_FLG_ENC_PA_REP.rst + TKT_FLG_FORWARDABLE.rst + TKT_FLG_FORWARDED.rst + TKT_FLG_HW_AUTH.rst + TKT_FLG_INITIAL.rst + TKT_FLG_INVALID.rst + TKT_FLG_MAY_POSTDATE.rst + TKT_FLG_OK_AS_DELEGATE.rst + TKT_FLG_POSTDATED.rst + TKT_FLG_PRE_AUTH.rst + TKT_FLG_PROXIABLE.rst + TKT_FLG_PROXY.rst + TKT_FLG_RENEWABLE.rst + TKT_FLG_TRANSIT_POLICY_CHECKED.rst + VALID_INT_BITS.rst + VALID_UINT_BITS.rst + krb5_const.rst + krb5_princ_component.rst + krb5_princ_name.rst + krb5_princ_realm.rst + krb5_princ_set_realm.rst + krb5_princ_set_realm_data.rst + krb5_princ_set_realm_length.rst + krb5_princ_size.rst + krb5_princ_type.rst + krb5_roundup.rst + krb5_x.rst + krb5_xc.rst + +Deprecated macros +------------------------------ + +.. toctree:: + :maxdepth: 1 + + krb524_convert_creds_kdc.rst + krb524_init_ets.rst diff --git a/krb5-1.21.3/doc/appdev/refs/types/index.rst b/krb5-1.21.3/doc/appdev/refs/types/index.rst new file mode 100644 index 00000000..d8d2a8f3 --- /dev/null +++ b/krb5-1.21.3/doc/appdev/refs/types/index.rst @@ -0,0 +1,108 @@ +krb5 types and structures +========================= + +Public +------- + +.. toctree:: + :maxdepth: 1 + + krb5_address.rst + krb5_addrtype.rst + krb5_ap_req.rst + krb5_ap_rep.rst + krb5_ap_rep_enc_part.rst + krb5_authdata.rst + krb5_authdatatype.rst + krb5_authenticator.rst + krb5_boolean.rst + krb5_checksum.rst + krb5_const_pointer.rst + krb5_const_principal.rst + krb5_cred.rst + krb5_cred_enc_part.rst + krb5_cred_info.rst + krb5_creds.rst + krb5_crypto_iov.rst + krb5_cryptotype.rst + krb5_data.rst + krb5_deltat.rst + krb5_enc_data.rst + krb5_enc_kdc_rep_part.rst + krb5_enc_tkt_part.rst + krb5_encrypt_block.rst + krb5_enctype.rst + krb5_error.rst + krb5_error_code.rst + krb5_expire_callback_func.rst + krb5_flags.rst + krb5_get_init_creds_opt.rst + krb5_gic_opt_pa_data.rst + krb5_int16.rst + krb5_int32.rst + krb5_kdc_rep.rst + krb5_kdc_req.rst + krb5_keyblock.rst + krb5_keytab_entry.rst + krb5_keyusage.rst + krb5_kt_cursor.rst + krb5_kvno.rst + krb5_last_req_entry.rst + krb5_magic.rst + krb5_mk_req_checksum_func.rst + krb5_msgtype.rst + krb5_octet.rst + krb5_pa_pac_req.rst + krb5_pa_server_referral_data.rst + krb5_pa_svr_referral_data.rst + krb5_pa_data.rst + krb5_pointer.rst + krb5_post_recv_fn.rst + krb5_pre_send_fn.rst + krb5_preauthtype.rst + krb5_principal.rst + krb5_principal_data.rst + krb5_prompt.rst + krb5_prompt_type.rst + krb5_prompter_fct.rst + krb5_pwd_data.rst + krb5_responder_context.rst + krb5_responder_fn.rst + krb5_responder_otp_challenge.rst + krb5_responder_otp_tokeninfo.rst + krb5_responder_pkinit_challenge.rst + krb5_responder_pkinit_identity.rst + krb5_response.rst + krb5_replay_data.rst + krb5_ticket.rst + krb5_ticket_times.rst + krb5_timestamp.rst + krb5_tkt_authent.rst + krb5_trace_callback.rst + krb5_trace_info.rst + krb5_transited.rst + krb5_typed_data.rst + krb5_ui_2.rst + krb5_ui_4.rst + krb5_verify_init_creds_opt.rst + passwd_phrase_element.rst + + +Internal +--------- + +.. toctree:: + :maxdepth: 1 + + krb5_auth_context.rst + krb5_cksumtype + krb5_context.rst + krb5_cc_cursor.rst + krb5_ccache.rst + krb5_cccol_cursor.rst + krb5_init_creds_context.rst + krb5_key.rst + krb5_keytab.rst + krb5_pac.rst + krb5_rcache.rst + krb5_tkt_creds_context.rst diff --git a/krb5-1.21.3/doc/appdev/refs/types/krb5_int32.rst b/krb5-1.21.3/doc/appdev/refs/types/krb5_int32.rst new file mode 100644 index 00000000..28baafa3 --- /dev/null +++ b/krb5-1.21.3/doc/appdev/refs/types/krb5_int32.rst @@ -0,0 +1,12 @@ +.. highlight:: c + +.. _krb5-int32-struct: + +krb5_int32 +========== + +.. +.. c:type:: krb5_int32 +.. + +krb5_int32 is a signed 32-bit integer type diff --git a/krb5-1.21.3/doc/appdev/refs/types/krb5_ui_4.rst b/krb5-1.21.3/doc/appdev/refs/types/krb5_ui_4.rst new file mode 100644 index 00000000..73eb38cf --- /dev/null +++ b/krb5-1.21.3/doc/appdev/refs/types/krb5_ui_4.rst @@ -0,0 +1,12 @@ +.. highlight:: c + +.. _krb5-ui4-struct: + +krb5_ui_4 +========== + +.. +.. c:type:: krb5_ui_4 +.. + +krb5_ui_4 is an unsigned 32-bit integer type. diff --git a/krb5-1.21.3/doc/appdev/y2038.rst b/krb5-1.21.3/doc/appdev/y2038.rst new file mode 100644 index 00000000..bc4122da --- /dev/null +++ b/krb5-1.21.3/doc/appdev/y2038.rst @@ -0,0 +1,28 @@ +Year 2038 considerations for uses of krb5_timestamp +=================================================== + +POSIX time values, which measure the number of seconds since January 1 +1970, will exceed the maximum value representable in a signed 32-bit +integer in January 2038. This documentation describes considerations +for consumers of the MIT krb5 libraries. + +Applications or libraries which use libkrb5 and consume the timestamps +included in credentials or other structures make use of the +:c:type:`krb5_timestamp` type. For historical reasons, krb5_timestamp +is a signed 32-bit integer, even on platforms where a larger type is +natively used to represent time values. To behave properly for time +values after January 2038, calling code should cast krb5_timestamp +values to uint32_t, and then to time_t:: + + (time_t)(uint32_t)timestamp + +Used in this way, krb5_timestamp values can represent time values up +until February 2106, provided that the platform uses a 64-bit or +larger time_t type. This usage will also remain safe if a later +version of MIT krb5 changes krb5_timestamp to an unsigned 32-bit +integer. + +The GSSAPI only uses representations of time intervals, not absolute +times. Callers of the GSSAPI should require no changes to behave +correctly after January 2038, provided that they use MIT krb5 release +1.16 or later. diff --git a/krb5-1.21.3/doc/basic/ccache_def.rst b/krb5-1.21.3/doc/basic/ccache_def.rst new file mode 100644 index 00000000..53542add --- /dev/null +++ b/krb5-1.21.3/doc/basic/ccache_def.rst @@ -0,0 +1,160 @@ +.. _ccache_definition: + +Credential cache +================ + +A credential cache (or "ccache") holds Kerberos credentials while they +remain valid and, generally, while the user's session lasts, so that +authenticating to a service multiple times (e.g., connecting to a web +or mail server more than once) doesn't require contacting the KDC +every time. + +A credential cache usually contains one initial ticket which is +obtained using a password or another form of identity verification. +If this ticket is a ticket-granting ticket, it can be used to obtain +additional credentials without the password. Because the credential +cache does not store the password, less long-term damage can be done +to the user's account if the machine is compromised. + +A credentials cache stores a default client principal name, set when +the cache is created. This is the name shown at the top of the +:ref:`klist(1)` *-A* output. + +Each normal cache entry includes a service principal name, a client +principal name (which, in some ccache types, need not be the same as +the default), lifetime information, and flags, along with the +credential itself. There are also other entries, indicated by special +names, that store additional information. + + +ccache types +------------ + +The credential cache interface, like the :ref:`keytab_definition` and +:ref:`rcache_definition` interfaces, uses `TYPE:value` strings to +indicate the type of credential cache and any associated cache naming +data to use. + +There are several kinds of credentials cache supported in the MIT +Kerberos library. Not all are supported on every platform. In most +cases, it should be correct to use the default type built into the +library. + +#. **API** is only implemented on Windows. It communicates with a + server process that holds the credentials in memory for the user, + rather than writing them to disk. + +#. **DIR** points to the storage location of the collection of the + credential caches in *FILE:* format. It is most useful when dealing + with multiple Kerberos realms and KDCs. For release 1.10 the + directory must already exist. In post-1.10 releases the + requirement is for parent directory to exist and the current + process must have permissions to create the directory if it does + not exist. See :ref:`col_ccache` for details. New in release 1.10. + The following residual forms are supported: + + * DIR:dirname + * DIR::dirpath/filename - a single cache within the directory + + Switching to a ccache of the latter type causes it to become the + primary for the directory. + +#. **FILE** caches are the simplest and most portable. A simple flat + file format is used to store one credential after another. This is + the default ccache type if no type is specified in a ccache name. + +#. **KCM** caches work by contacting a daemon process called ``kcm`` + to perform cache operations. If the cache name is just ``KCM:``, + the default cache as determined by the KCM daemon will be used. + Newly created caches must generally be named ``KCM:uid:name``, + where *uid* is the effective user ID of the running process. + + KCM client support is new in release 1.13. A KCM daemon has not + yet been implemented in MIT krb5, but the client will interoperate + with the KCM daemon implemented by Heimdal. macOS 10.7 and higher + provides a KCM daemon as part of the operating system, and the + **KCM** cache type is used as the default cache on that platform in + a default build. + +#. **KEYRING** is Linux-specific, and uses the kernel keyring support + to store credential data in unswappable kernel memory where only + the current user should be able to access it. The following + residual forms are supported: + + * KEYRING:name + * KEYRING:process:name - process keyring + * KEYRING:thread:name - thread keyring + + Starting with release 1.12 the *KEYRING* type supports collections. + The following new residual forms were added: + + * KEYRING:session:name - session keyring + * KEYRING:user:name - user keyring + * KEYRING:persistent:uidnumber - persistent per-UID collection. + Unlike the user keyring, this collection survives after the user + logs out, until the cache credentials expire. This type of + ccache requires support from the kernel; otherwise, it will fall + back to the user keyring. + + See :ref:`col_ccache` for details. + +#. **MEMORY** caches are for storage of credentials that don't need to + be made available outside of the current process. For example, a + memory ccache is used by :ref:`kadmin(1)` to store the + administrative ticket used to contact the admin server. Memory + ccaches are faster than file ccaches and are automatically + destroyed when the process exits. + +#. **MSLSA** is a Windows-specific cache type that accesses the + Windows credential store. + + +.. _col_ccache: + +Collections of caches +--------------------- + +Some credential cache types can support collections of multiple +caches. One of the caches in the collection is designated as the +*primary* and will be used when the collection is resolved as a cache. +When a collection-enabled cache type is the default cache for a +process, applications can search the specified collection for a +specific client principal, and GSSAPI applications will automatically +select between the caches in the collection based on criteria such as +the target service realm. + +Credential cache collections are new in release 1.10, with support +from the **DIR** and **API** ccache types. Starting in release 1.12, +collections are also supported by the **KEYRING** ccache type. +Collections are supported by the **KCM** ccache type in release 1.13. + + +Tool alterations to use cache collection +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* :ref:`kdestroy(1)` *-A* will destroy all caches in the collection. +* If the default cache type supports switching, :ref:`kinit(1)` + *princname* will search the collection for a matching cache and + store credentials there, or will store credentials in a new unique + cache of the default type if no existing cache for the principal + exists. Either way, kinit will switch to the selected cache. +* :ref:`klist(1)` *-l* will list the caches in the collection. +* :ref:`klist(1)` *-A* will show the content of all caches in the + collection. +* :ref:`kswitch(1)` *-p princname* will search the collection for a + matching cache and switch to it. +* :ref:`kswitch(1)` *-c cachename* will switch to a specified cache. + + +Default ccache name +------------------- + +The default credential cache name is determined by the following, in +descending order of priority: + +#. The **KRB5CCNAME** environment variable. For example, + ``KRB5CCNAME=DIR:/mydir/``. + +#. The **default_ccache_name** profile variable in :ref:`libdefaults`. + +#. The hardcoded default, |ccache|. diff --git a/krb5-1.21.3/doc/basic/date_format.rst b/krb5-1.21.3/doc/basic/date_format.rst new file mode 100644 index 00000000..6ee82ce6 --- /dev/null +++ b/krb5-1.21.3/doc/basic/date_format.rst @@ -0,0 +1,140 @@ +.. _datetime: + +Supported date and time formats +=============================== + +.. _duration: + +Time duration +------------- + +This format is used to express a time duration in the Kerberos +configuration files and user commands. The allowed formats are: + + ====================== ============== ============ + Format Example Value + ---------------------- -------------- ------------ + h:m[:s] 36:00 36 hours + NdNhNmNs 8h30s 8 hours 30 seconds + N (number of seconds) 3600 1 hour + ====================== ============== ============ + +Here *N* denotes a number, *d* - days, *h* - hours, *m* - minutes, +*s* - seconds. + +.. note:: + + The time interval should not exceed 2147483647 seconds. + +Examples:: + + Request a ticket valid for one hour, five hours, 30 minutes + and 10 days respectively: + + kinit -l 3600 + kinit -l 5:00 + kinit -l 30m + kinit -l "10d 0h 0m 0s" + + +.. _getdate: + +getdate time +------------ + +Some of the kadmin and kdb5_util commands take a date-time in a +human-readable format. Some of the acceptable date-time +strings are: + + +-----------+------------------+-----------------+ + | | Format | Example | + +===========+==================+=================+ + | Date | mm/dd/yy | 07/27/12 | + | +------------------+-----------------+ + | | month dd, yyyy | Jul 27, 2012 | + | +------------------+-----------------+ + | | yyyy-mm-dd | 2012-07-27 | + +-----------+------------------+-----------------+ + | Absolute | HH:mm[:ss]pp | 08:30 PM | + | time +------------------+-----------------+ + | | hh:mm[:ss] | 20:30 | + +-----------+------------------+-----------------+ + | Relative | N tt | 30 sec | + | time | | | + +-----------+------------------+-----------------+ + | Time zone | Z | EST | + | +------------------+-----------------+ + | | z | -0400 | + +-----------+------------------+-----------------+ + +(See :ref:`abbreviation`.) + +Examples:: + + Create a principal that expires on the date indicated: + addprinc test1 -expire "3/27/12 10:00:07 EST" + addprinc test2 -expire "January 23, 2015 10:05pm" + addprinc test3 -expire "22:00 GMT" + Add a principal that will expire in 30 minutes: + addprinc test4 -expire "30 minutes" + + +.. _abstime: + +Absolute time +------------- + +This rarely used date-time format can be noted in one of the +following ways: + + + +------------------------+----------------------+--------------+ + | Format | Example | Value | + +========================+======================+==============+ + | yyyymmddhhmmss | 20141231235900 | One minute | + +------------------------+----------------------+ before 2015 | + | yyyy.mm.dd.hh.mm.ss | 2014.12.31.23.59.00 | | + +------------------------+----------------------+ | + | yymmddhhmmss | 141231235900 | | + +------------------------+----------------------+ | + | yy.mm.dd.hh.mm.ss | 14.12.31.23.59.00 | | + +------------------------+----------------------+ | + | dd-month-yyyy:hh:mm:ss | 31-Dec-2014:23:59:00 | | + +------------------------+----------------------+--------------+ + | hh:mm:ss | 20:00:00 | 8 o'clock in | + +------------------------+----------------------+ the evening | + | hhmmss | 200000 | | + +------------------------+----------------------+--------------+ + +(See :ref:`abbreviation`.) + +Example:: + + Set the default expiration date to July 27, 2012 at 20:30 + default_principal_expiration = 20120727203000 + + +.. _abbreviation: + +Abbreviations used in this document +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +| *month* : locale’s month name or its abbreviation; +| *dd* : day of month (01-31); +| *HH* : hours (00-12); +| *hh* : hours (00-23); +| *mm* : in time - minutes (00-59); in date - month (01-12); +| *N* : number; +| *pp* : AM or PM; +| *ss* : seconds (00-60); +| *tt* : time units (hours, minutes, min, seconds, sec); +| *yyyy* : year; +| *yy* : last two digits of the year; +| *Z* : alphabetic time zone abbreviation; +| *z* : numeric time zone; + +.. note:: + + - If the date specification contains spaces, you may need to + enclose it in double quotes; + - All keywords are case-insensitive. diff --git a/krb5-1.21.3/doc/basic/index.rst b/krb5-1.21.3/doc/basic/index.rst new file mode 100644 index 00000000..87a9b547 --- /dev/null +++ b/krb5-1.21.3/doc/basic/index.rst @@ -0,0 +1,14 @@ +.. _basic_concepts: + +Kerberos V5 concepts +==================== + + +.. toctree:: + :maxdepth: 1 + + ccache_def + keytab_def + rcache_def + stash_file_def + date_format diff --git a/krb5-1.21.3/doc/basic/keytab_def.rst b/krb5-1.21.3/doc/basic/keytab_def.rst new file mode 100644 index 00000000..6c7fcc3b --- /dev/null +++ b/krb5-1.21.3/doc/basic/keytab_def.rst @@ -0,0 +1,59 @@ +.. _keytab_definition: + +keytab +====== + +A keytab (short for "key table") stores long-term keys for one or more +principals. Keytabs are normally represented by files in a standard +format, although in rare cases they can be represented in other ways. +Keytabs are used most often to allow server applications to accept +authentications from clients, but can also be used to obtain initial +credentials for client applications. + +Keytabs are named using the format *type*\ ``:``\ *value*. Usually +*type* is ``FILE`` and *value* is the absolute pathname of the file. +The other possible value for *type* is ``MEMORY``, which indicates a +temporary keytab stored in the memory of the current process. + +A keytab contains one or more entries, where each entry consists of a +timestamp (indicating when the entry was written to the keytab), a +principal name, a key version number, an encryption type, and the +encryption key itself. + +A keytab can be displayed using the :ref:`klist(1)` command with the +``-k`` option. Keytabs can be created or appended to by extracting +keys from the KDC database using the :ref:`kadmin(1)` :ref:`ktadd` +command. Keytabs can be manipulated using the :ref:`ktutil(1)` and +:ref:`k5srvutil(1)` commands. + + +Default keytab +-------------- + +The default keytab is used by server applications if the application +does not request a specific keytab. The name of the default keytab is +determined by the following, in decreasing order of preference: + +#. The **KRB5_KTNAME** environment variable. + +#. The **default_keytab_name** profile variable in :ref:`libdefaults`. + +#. The hardcoded default, |keytab|. + + +Default client keytab +--------------------- + +The default client keytab is used, if it is present and readable, to +automatically obtain initial credentials for GSSAPI client +applications. The principal name of the first entry in the client +keytab is used by default when obtaining initial credentials. The +name of the default client keytab is determined by the following, in +decreasing order of preference: + +#. The **KRB5_CLIENT_KTNAME** environment variable. + +#. The **default_client_keytab_name** profile variable in + :ref:`libdefaults`. + +#. The hardcoded default, |ckeytab|. diff --git a/krb5-1.21.3/doc/basic/rcache_def.rst b/krb5-1.21.3/doc/basic/rcache_def.rst new file mode 100644 index 00000000..a80cf5af --- /dev/null +++ b/krb5-1.21.3/doc/basic/rcache_def.rst @@ -0,0 +1,111 @@ +.. _rcache_definition: + +replay cache +============ + +A replay cache (or "rcache") keeps track of all authenticators +recently presented to a service. If a duplicate authentication +request is detected in the replay cache, an error message is sent to +the application program. + +The replay cache interface, like the credential cache and +:ref:`keytab_definition` interfaces, uses `type:residual` strings to +indicate the type of replay cache and any associated cache naming +data to use. + +Background information +---------------------- + +Some Kerberos or GSSAPI services use a simple authentication mechanism +where a message is sent containing an authenticator, which establishes +the encryption key that the client will use for talking to the +service. But nothing about that prevents an eavesdropper from +recording the messages sent by the client, establishing a new +connection, and re-sending or "replaying" the same messages; the +replayed authenticator will establish the same encryption key for the +new session, and the following messages will be decrypted and +processed. The attacker may not know what the messages say, and can't +generate new messages under the same encryption key, but in some +instances it may be harmful to the user (or helpful to the attacker) +to cause the server to see the same messages again a second time. For +example, if the legitimate client sends "delete first message in +mailbox", a replay from an attacker may delete another, different +"first" message. (Protocol design to guard against such problems has +been discussed in :rfc:`4120#section-10`.) + +Even if one protocol uses further protection to verify that the client +side of the connection actually knows the encryption keys (and thus is +presumably a legitimate user), if another service uses the same +service principal name, it may be possible to record an authenticator +used with the first protocol and "replay" it against the second. + +The replay cache mitigates these attacks somewhat, by keeping track of +authenticators that have been seen until their five-minute window +expires. Different authenticators generated by multiple connections +from the same legitimate client will generally have different +timestamps, and thus will not be considered the same. + +This mechanism isn't perfect. If a message is sent to one application +server but a man-in-the-middle attacker can prevent it from actually +arriving at that server, the attacker could then use the authenticator +(once!) against a different service on the same host. This could be a +problem if the message from the client included something more than +authentication in the first message that could be useful to the +attacker (which is uncommon; in most protocols the server has to +indicate a successful authentication before the client sends +additional messages), or if the simple act of presenting the +authenticator triggers some interesting action in the service being +attacked. + +Replay cache types +------------------ + +Unlike the credential cache and keytab interfaces, replay cache types +are in lowercase. The following types are defined: + +#. **none** disables the replay cache. The residual value is ignored. + +#. **file2** (new in release 1.18) uses a hash-based format to store + replay records. The file may grow to accommodate hash collisions. + The residual value is the filename. + +#. **dfl** is the default type if no environment variable or + configuration specifies a different type. It stores replay data in + a file2 replay cache with a filename based on the effective uid. + The residual value is ignored. + +For the dfl type, the location of the replay cache file is determined +as follows: + +#. The directory is taken from the **KRB5RCACHEDIR** environment + variable, or the **TMPDIR** environment variable, or a temporary + directory determined at configuration time such as ``/var/tmp``, in + descending order of preference. + +#. The filename is ``krb5_EUID.rcache2`` where EUID is the effective + uid of the process. + +#. The file is opened without following symbolic links, and ownership + of the file is verified to match the effective uid. + +On Windows, the directory for the dfl type is the local appdata +directory, unless overridden by the **KRB5RCACHEDIR** environment +variable. The filename on Windows is ``krb5.rcache2``, and the file +is opened normally. + +Default replay cache name +------------------------- + +The default replay cache name is determined by the following, in +descending order of priority: + +#. The **KRB5RCACHENAME** environment variable (new in release 1.18). + +#. The **KRB5RCACHETYPE** environment variable. If this variable is + set, the residual value is empty. + +#. The **default_rcache_name** profile variable in :ref:`libdefaults` + (new in release 1.18). + +#. If none of the above are set, the default replay cache name is + ``dfl:``. diff --git a/krb5-1.21.3/doc/basic/stash_file_def.rst b/krb5-1.21.3/doc/basic/stash_file_def.rst new file mode 100644 index 00000000..256e2c27 --- /dev/null +++ b/krb5-1.21.3/doc/basic/stash_file_def.rst @@ -0,0 +1,25 @@ +.. _stash_definition: + + +stash file +============ + +The stash file is a local copy of the master key that resides in +encrypted form on the KDC's local disk. The stash file is used to +authenticate the KDC to itself automatically before starting the +:ref:`kadmind(8)` and :ref:`krb5kdc(8)` daemons (e.g., as part of the +machine's boot sequence). The stash file, like the keytab file (see +:ref:`keytab_file`) is a potential point-of-entry for a break-in, and +if compromised, would allow unrestricted access to the Kerberos +database. If you choose to install a stash file, it should be +readable only by root, and should exist only on the KDC's local disk. +The file should not be part of any backup of the machine, unless +access to the backup data is secured as tightly as access to the +master password itself. + +.. note:: + + If you choose not to install a stash file, the KDC will prompt you for the master key each time it starts up. + This means that the KDC will not be able to start automatically, such as after a system reboot. + + diff --git a/krb5-1.21.3/doc/build/directory_org.rst b/krb5-1.21.3/doc/build/directory_org.rst new file mode 100644 index 00000000..109b69a3 --- /dev/null +++ b/krb5-1.21.3/doc/build/directory_org.rst @@ -0,0 +1,75 @@ +Organization of the source directory +==================================== + +Below is a brief overview of the organization of the complete source +directory. More detailed descriptions follow. + +=============== ============================================== +appl Kerberos application client and server programs +ccapi Credential cache services +clients Kerberos V5 user programs (See :ref:`user_commands`) +config Configure scripts +config-files Sample Kerberos configuration files +include include files needed to build the Kerberos system +kadmin Administrative interface to the Kerberos database: :ref:`kadmin(1)`, :ref:`kdb5_util(8)`, :ref:`ktutil(1)`. +kdc Kerberos V5 Authentication Service and Key Distribution Center +lib_ Libraries for use with/by Kerberos V5 +plugins Kerberos plugins directory +po Localization infrastructure +prototype Templates files containing the MIT copyright message and a placeholder for the title and description of the file. +kprop Utilities for propagating the database to replica KDCs :ref:`kprop(8)` and :ref:`kpropd(8)` +tests Test suite +util_ Various utilities for building/configuring the code, sending bug reports, etc. +windows Source code for building Kerberos V5 on Windows (see windows/README) +=============== ============================================== + + +.. _lib: + +lib +--- + +The lib directory contain several subdirectories as well as some +definition and glue files. + + - The apputils directory contains the code for the generic network + servicing. + - The crypto subdirectory contains the Kerberos V5 encryption + library. + - The gssapi library contains the Generic Security Services API, + which is a library of commands to be used in secure client-server + communication. + - The kadm5 directory contains the libraries for the KADM5 + administration utilities. + - The Kerberos 5 database libraries are contained in kdb. + - The krb5 directory contains Kerberos 5 API. + - The rpc directory contains the API for the Kerberos Remote + Procedure Call protocol. + + +.. _util: + +util +---- + +The util directory contains several utility programs and libraries. + - the programs used to configure and build the code, such as + autoconf, lndir, kbuild, reconf, and makedepend, are in this + directory. + - the profile directory contains most of the functions which parse + the Kerberos configuration files (krb5.conf and kdc.conf). + - the Kerberos error table library and utilities (et); + - the Sub-system library and utilities (ss); + - database utilities (db2); + - pseudo-terminal utilities (pty); + - bug-reporting program send-pr; + - a generic support library support used by several of our other + libraries; + - the build infrastructure for building lightweight Kerberos client + (collected-client-lib) + - the tool for validating Kerberos configuration files + (confvalidator); + - the toolkit for kernel integrators for building krb5 code subsets + (gss-kernel-lib); + - source code for building Kerberos V5 on MacOS (mac) + - Windows getopt operations (windows) diff --git a/krb5-1.21.3/doc/build/doing_build.rst b/krb5-1.21.3/doc/build/doing_build.rst new file mode 100644 index 00000000..59cb546c --- /dev/null +++ b/krb5-1.21.3/doc/build/doing_build.rst @@ -0,0 +1,148 @@ +Doing the build +=============== + +.. _do_build: + +Building within a single tree +----------------------------- + +If you only need to build Kerberos for one platform, using a single +directory tree which contains both the source files and the object +files is the simplest. However, if you need to maintain Kerberos for +a large number of platforms, you will probably want to use separate +build trees for each platform. We recommend that you look at OS +Incompatibilities, for notes that we have on particular operating +systems. + +If you don't want separate build trees for each architecture, then use +the following abbreviated procedure:: + + cd /u1/krb5-VERSION/src + ./configure + make + +That's it! + +Building with separate build directories +---------------------------------------- + +If you wish to keep separate build directories for each platform, you +can do so using the following procedure. (Note, this requires that +your make program support VPATH. GNU's make will provide this +functionality, for example.) If your make program does not support +this, see the next section. + +For example, if you wish to store the binaries in ``tmpbuild`` build +directory you might use the following procedure:: + + mkdir /u1/tmpbuild + cd /u1/tmpbuild + /u1/krb5-VERSION/src/configure + make + + +Building using lndir +-------------------- + +If you wish to keep separate build directories for each platform, and +you do not have access to a make program which supports VPATH, all is +not lost. You can use the lndir program to create symbolic link trees +in your build directory. + +For example, if you wish to create a build directory for solaris +binaries you might use the following procedure:: + + mkdir /u1/krb5-VERSION/solaris + cd /u1/krb5-VERSION/solaris + /u1/krb5-VERSION/src/util/lndir `pwd`/../src + ./configure + make + +You must give an absolute pathname to lndir because it has a bug that +makes it fail for relative pathnames. Note that this version differs +from the latest version as distributed and installed by the +XConsortium with X11R6. Either version should be acceptable. + + +Installing the binaries +----------------------- + +Once you have built Kerberos, you should install the binaries. You can +do this by running:: + + make install + +If you want to install the binaries into a destination directory that +is not their final destination, which may be convenient if you want to +build a binary distribution to be deployed on multiple hosts, you may +use:: + + make install DESTDIR=/path/to/destdir + +This will install the binaries under *DESTDIR/PREFIX*, e.g., the user +programs will install into *DESTDIR/PREFIX/bin*, the libraries into +*DESTDIR/PREFIX/lib*, etc. *DESTDIR* must be an absolute path. + +Some implementations of make allow multiple commands to be run in +parallel, for faster builds. We test our Makefiles in parallel builds +with GNU make only; they may not be compatible with other parallel +build implementations. + + +Testing the build +----------------- + +The Kerberos V5 distribution comes with built-in regression tests. To +run them, simply type the following command while in the top-level +build directory (i.e., the directory where you sent typed make to +start building Kerberos; see :ref:`do_build`):: + + make check + +On some operating systems, you have to run ``make install`` before +running ``make check``, or the test suite will pick up installed +versions of Kerberos libraries rather than the newly built ones. You +can install into a prefix that isn't in the system library search +path, though. Alternatively, you can configure with +**-**\ **-disable-rpath**, which renders the build tree less suitable +for installation, but allows testing without interference from +previously installed libraries. + +There are additional regression tests available, which are not run +by ``make check``. These tests require manual setup and teardown of +support infrastructure which is not easily automated, or require +excessive resources for ordinary use. The procedure for running +the manual tests is documented at +https://k5wiki.kerberos.org/wiki/Manual_Testing. + + +Cleaning up the build +--------------------- + +* Use ``make clean`` to remove all files generated by running make + command. +* Use ``make distclean`` to remove all files generated by running + ./configure script. After running ``make distclean`` your source + tree (ideally) should look like the raw (just un-tarred) source + tree. + +Using autoconf +-------------- + +(If you are not a developer, you can ignore this section.) + +In the Kerberos V5 source directory, there is a configure script which +automatically determines the compilation environment and creates the +proper Makefiles for a particular platform. This configure script is +generated using autoconf, which you should already have installed if +you will be making changes to ``src/configure.in``. + +Normal users will not need to worry about running autoconf; the +distribution comes with the configure script already prebuilt. + +The autoconf package comes with a script called ``autoreconf`` that +will automatically run ``autoconf`` and ``autoheader`` as needed. You +should run ``autoreconf`` from the top source directory, e.g.:: + + cd /u1/krb5-VERSION/src + autoreconf --verbose diff --git a/krb5-1.21.3/doc/build/index.rst b/krb5-1.21.3/doc/build/index.rst new file mode 100644 index 00000000..f321d020 --- /dev/null +++ b/krb5-1.21.3/doc/build/index.rst @@ -0,0 +1,63 @@ +.. _build_V5: + +Building Kerberos V5 +==================== + +This section details how to build and install MIT Kerberos software +from the source. + +Prerequisites +------------- + +In order to build Kerberos V5, you will need approximately 60-70 +megabytes of disk space. The exact amount will vary depending on the +platform and whether the distribution is compiled with debugging +symbol tables or not. + +Your C compiler must conform to ANSI C (ISO/IEC 9899:1990, "c89"). +Some operating systems do not have an ANSI C compiler, or their +default compiler requires extra command-line options to enable ANSI C +conformance. + +If you wish to keep a separate build tree, which contains the compiled +\*.o file and executables, separate from your source tree, you will +need a make program which supports **VPATH**, or you will need to use +a tool such as lndir to produce a symbolic link tree for your build +tree. + +Obtaining the software +---------------------- + +The source code can be obtained from MIT Kerberos Distribution page, +at https://kerberos.org/dist/index.html. +The MIT Kerberos distribution comes in an archive file, generally +named krb5-VERSION-signed.tar, where *VERSION* is a placeholder for +the major and minor versions of MIT Kerberos. (For example, MIT +Kerberos 1.9 has major version "1" and minor version "9".) + +The krb5-VERSION-signed.tar contains a compressed tar file consisting +of the sources for all of Kerberos (generally named +krb5-VERSION.tar.gz) and a PGP signature file for this source tree +(generally named krb5-VERSION.tar.gz.asc). MIT highly recommends that +you verify the integrity of the source code using this signature, +e.g., by running:: + + tar xf krb5-VERSION-signed.tar + gpg --verify krb5-VERSION.tar.gz.asc + +Unpack krb5-VERSION.tar.gz in some directory. In this section we will assume +that you have chosen the top directory of the distribution the directory +``/u1/krb5-VERSION``. + +Review the README file for the license, copyright and other sprecific to the +distribution information. + +Contents +-------- +.. toctree:: + :maxdepth: 1 + + directory_org.rst + doing_build.rst + options2configure.rst + osconf.rst diff --git a/krb5-1.21.3/doc/build/options2configure.rst b/krb5-1.21.3/doc/build/options2configure.rst new file mode 100644 index 00000000..e879b18b --- /dev/null +++ b/krb5-1.21.3/doc/build/options2configure.rst @@ -0,0 +1,397 @@ +.. _options2configure: + +Options to *configure* +====================== + +There are a number of options to configure which you can use to +control how the Kerberos distribution is built. + +Most commonly used options +-------------------------- + +**-**\ **-help** + Provides help to configure. This will list the set of commonly + used options for building Kerberos. + +**-**\ **-prefix=**\ *PREFIX* + By default, Kerberos will install the package's files rooted at + ``/usr/local``. If you desire to place the binaries into the + directory *PREFIX*, use this option. + +**-**\ **-exec-prefix=**\ *EXECPREFIX* + This option allows one to separate the architecture independent + programs from the host-dependent files (configuration files, + manual pages). Use this option to install architecture-dependent + programs in *EXECPREFIX*. The default location is the value of + specified by **-**\ **-prefix** option. + +**-**\ **-localstatedir=**\ *LOCALSTATEDIR* + This option sets the directory for locally modifiable + single-machine data. In Kerberos, this mostly is useful for + setting a location for the KDC data files, as they will be + installed in ``LOCALSTATEDIR/krb5kdc``, which is by default + ``PREFIX/var/krb5kdc``. + +**-**\ **-with-netlib**\ [=\ *libs*] + Allows for suppression of or replacement of network libraries. By + default, Kerberos V5 configuration will look for ``-lnsl`` and + ``-lsocket``. If your operating system has a broken resolver + library or fails to pass the tests in ``src/tests/resolv``, you + will need to use this option. + +**-**\ **-enable-dns-for-realm** + Enable the use of DNS to look up a host's Kerberos realm, + if the information is not provided in + :ref:`krb5.conf(5)`. See :ref:`mapping_hostnames` + for information about using DNS to determine the default realm. + DNS lookups for realm names are disabled by default. + +**-**\ **-with-system-et** + Use an installed version of the error-table (et) support software, + the compile_et program, the com_err.h header file and the com_err + library. If these are not in the default locations, you may wish + to specify ``CPPFLAGS=-I/some/dir`` and + ``LDFLAGS=-L/some/other/dir`` options at configuration time as + well. + + If this option is not given, a version supplied with the Kerberos + sources will be built and installed along with the rest of the + Kerberos tree, for Kerberos applications to link against. + +**-**\ **-with-system-ss** + Use an installed version of the subsystem command-line interface + software, the mk_cmds program, the ``ss/ss.h`` header file and the + ss library. If these are not in the default locations, you may + wish to specify ``CPPFLAGS=-I/some/dir`` and + ``LDFLAGS=-L/some/other/dir`` options at configuration time as + well. See also the **SS_LIB** option. + + If this option is not given, the ss library supplied with the + Kerberos sources will be compiled and linked into those programs + that need it; it will not be installed separately. + +**-**\ **-with-system-db** + Use an installed version of the Berkeley DB package, which must + provide an API compatible with version 1.85. This option is + unsupported and untested. In particular, we do not know if the + database-rename code used in the dumpfile load operation will + behave properly. + + If this option is not given, a version supplied with the Kerberos + sources will be built and installed. (We are not updating this + version at this time because of licensing issues with newer + versions that we haven't investigated sufficiently yet.) + + +Environment variables +--------------------- + +**CC=**\ *COMPILER* + Use *COMPILER* as the C compiler. + +**CFLAGS=**\ *FLAGS* + Use *FLAGS* as the default set of C compiler flags. + +**CPP=**\ *CPP* + C preprocessor to use. (e.g., ``CPP='gcc -E'``) + +**CPPFLAGS=**\ *CPPOPTS* + Use *CPPOPTS* as the default set of C preprocessor flags. The + most common use of this option is to select certain #define's for + use with the operating system's include files. + + +**DB_HEADER=**\ *headername* + If db.h is not the correct header file to include to compile + against the Berkeley DB 1.85 API, specify the correct header file + name with this option. For example, ``DB_HEADER=db3/db_185.h``. + +**DB_LIB=**\ *libs*... + If ``-ldb`` is not the correct library specification for the + Berkeley DB library version to be used, override it with this + option. For example, ``DB_LIB=-ldb-3.3``. + +**DEFCCNAME=**\ *ccachename* + Override the built-in default credential cache name. + For example, ``DEFCCNAME=DIR:/var/run/user/%{USERID}/ccache`` + See :ref:`parameter_expansion` for information about supported + parameter expansions. + +**DEFCKTNAME=**\ *keytabname* + Override the built-in default client keytab name. + The format is the same as for *DEFCCNAME*. + +**DEFKTNAME=**\ *keytabname* + Override the built-in default keytab name. + The format is the same as for *DEFCCNAME*. + +**LD=**\ *LINKER* + Use *LINKER* as the default loader if it should be different from + C compiler as specified above. + +**LDFLAGS=**\ *LDOPTS* + This option informs the linker where to get additional libraries + (e.g., ``-L``). + +**LIBS=**\ *LDNAME* + This option allows one to specify libraries to be passed to the + linker (e.g., ``-l``) + +**PKCS11_MODNAME=**\ *library* + Override the built-in default PKCS11 library name. + +**SS_LIB=**\ *libs*... + If ``-lss`` is not the correct way to link in your installed ss + library, for example if additional support libraries are needed, + specify the correct link options here. Some variants of this + library are around which allow for Emacs-like line editing, but + different versions require different support libraries to be + explicitly specified. + + This option is ignored if **-**\ **-with-system-ss** is not specified. + +**YACC** + The 'Yet Another C Compiler' implementation to use. Defaults to + the first program found out of: '`bison -y`', '`byacc`', + '`yacc`'. + +**YFLAGS** + The list of arguments that will be passed by default to $YACC. + This script will default YFLAGS to the empty string to avoid a + default value of ``-d`` given by some make applications. + + +Fine tuning of the installation directories +------------------------------------------- + +**-**\ **-bindir=**\ *DIR* + User executables. Defaults to ``EXECPREFIX/bin``, where + *EXECPREFIX* is the path specified by **-**\ **-exec-prefix** + configuration option. + +**-**\ **-sbindir=**\ *DIR* + System admin executables. Defaults to ``EXECPREFIX/sbin``, where + *EXECPREFIX* is the path specified by **-**\ **-exec-prefix** + configuration option. + +**-**\ **-sysconfdir=**\ *DIR* + Read-only single-machine data such as krb5.conf. + Defaults to ``PREFIX/etc``, where + *PREFIX* is the path specified by **-**\ **-prefix** configuration + option. + +**-**\ **-libdir=**\ *DIR* + Object code libraries. Defaults to ``EXECPREFIX/lib``, where + *EXECPREFIX* is the path specified by **-**\ **-exec-prefix** + configuration option. + +**-**\ **-includedir=**\ *DIR* + C header files. Defaults to ``PREFIX/include``, where *PREFIX* is + the path specified by **-**\ **-prefix** configuration option. + +**-**\ **-datarootdir=**\ *DATAROOTDIR* + Read-only architecture-independent data root. Defaults to + ``PREFIX/share``, where *PREFIX* is the path specified by + **-**\ **-prefix** configuration option. + +**-**\ **-datadir=**\ *DIR* + Read-only architecture-independent data. Defaults to path + specified by **-**\ **-datarootdir** configuration option. + +**-**\ **-localedir=**\ *DIR* + Locale-dependent data. Defaults to ``DATAROOTDIR/locale``, where + *DATAROOTDIR* is the path specified by **-**\ **-datarootdir** + configuration option. + +**-**\ **-mandir=**\ *DIR* + Man documentation. Defaults to ``DATAROOTDIR/man``, where + *DATAROOTDIR* is the path specified by **-**\ **-datarootdir** + configuration option. + + +Program names +------------- + +**-**\ **-program-prefix=**\ *PREFIX* + Prepend *PREFIX* to the names of the programs when installing + them. For example, specifying ``--program-prefix=mit-`` at the + configure time will cause the program named ``abc`` to be + installed as ``mit-abc``. + +**-**\ **-program-suffix=**\ *SUFFIX* + Append *SUFFIX* to the names of the programs when installing them. + For example, specifying ``--program-suffix=-mit`` at the configure + time will cause the program named ``abc`` to be installed as + ``abc-mit``. + +**-**\ **-program-transform-name=**\ *PROGRAM* + Run ``sed -e PROGRAM`` on installed program names. (*PROGRAM* is a + sed script). + + +System types +------------ + +**-**\ **-build=**\ *BUILD* + Configure for building on *BUILD* + (e.g., ``--build=x86_64-linux-gnu``). + +**-**\ **-host=**\ *HOST* + Cross-compile to build programs to run on *HOST* + (e.g., ``--host=x86_64-linux-gnu``). By default, Kerberos V5 + configuration will look for "build" option. + + +Optional features +----------------- + +**-**\ **-disable-option-checking** + Ignore unrecognized --enable/--with options. + +**-**\ **-disable-**\ *FEATURE* + Do not include *FEATURE* (same as --enable-FEATURE=no). + +**-**\ **-enable-**\ *FEATURE*\ [=\ *ARG*] + Include *FEATURE* [ARG=yes]. + +**-**\ **-enable-maintainer-mode** + Enable rebuilding of source files, Makefiles, etc. + +**-**\ **-disable-delayed-initialization** + Initialize library code when loaded. Defaults to delay until + first use. + +**-**\ **-disable-thread-support** + Don't enable thread support. Defaults to enabled. + +**-**\ **-disable-rpath** + Suppress run path flags in link lines. + +**-**\ **-enable-athena** + Build with MIT Project Athena configuration. + +**-**\ **-disable-kdc-lookaside-cache** + Disable the cache which detects client retransmits. + +**-**\ **-disable-pkinit** + Disable PKINIT plugin support. + +**-**\ **-disable-aesni** + Disable support for using AES instructions on x86 platforms. + +**-**\ **-enable-asan**\ [=\ *ARG*] + Enable building with asan memory error checking. If *ARG* is + given, it controls the -fsanitize compilation flag value (the + default is "address"). + + +Optional packages +----------------- + +**-**\ **-with-**\ *PACKAGE*\ [=ARG\] + Use *PACKAGE* (e.g., ``--with-imap``). The default value of *ARG* + is ``yes``. + +**-**\ **-without-**\ *PACKAGE* + Do not use *PACKAGE* (same as ``--with-PACKAGE=no``) + (e.g., ``--without-libedit``). + +**-**\ **-with-size-optimizations** + Enable a few optimizations to reduce code size possibly at some + run-time cost. + +**-**\ **-with-system-et** + Use the com_err library and compile_et utility that are already + installed on the system, instead of building and installing + local versions. + +**-**\ **-with-system-ss** + Use the ss library and mk_cmds utility that are already installed + on the system, instead of building and using private versions. + +**-**\ **-with-system-db** + Use the berkeley db utility already installed on the system, + instead of using a private version. This option is not + recommended; enabling it may result in incompatibility with key + databases originating on other systems. + +**-**\ **-with-netlib=**\ *LIBS* + Use the resolver library specified in *LIBS*. Use this variable + if the C library resolver is insufficient or broken. + +**-**\ **-with-hesiod=**\ *path* + Compile with Hesiod support. The *path* points to the Hesiod + directory. By default Hesiod is unsupported. + +**-**\ **-with-ldap** + Compile OpenLDAP database backend module. + +**-**\ **-with-lmdb** + Compile LMDB database backend module. + +**-**\ **-with-vague-errors** + Do not send helpful errors to client. For example, if the KDC + should return only vague error codes to clients. + +**-**\ **-with-crypto-impl=**\ *IMPL* + Use specified crypto implementation (e.g., **-**\ + **-with-crypto-impl=**\ *openssl*). The default is the native MIT + Kerberos implementation ``builtin``. The other currently + implemented crypto backend is ``openssl``. (See + :ref:`mitK5features`) + +**-**\ **-without-libedit** + Do not compile and link against libedit. Some utilities will no + longer offer command history or completion in interactive mode if + libedit is disabled. + +**-**\ **-with-readline** + Compile and link against GNU readline, as an alternative to libedit. + +**-**\ **-with-system-verto** + Use an installed version of libverto. If the libverto header and + library are not in default locations, you may wish to specify + ``CPPFLAGS=-I/some/dir`` and ``LDFLAGS=-L/some/other/dir`` options + at configuration time as well. + + If this option is not given, the build system will try to detect + an installed version of libverto and use it if it is found. + Otherwise, a version supplied with the Kerberos sources will be + built and installed. The built-in version does not contain the + full set of back-end modules and is not a suitable general + replacement for the upstream version, but will work for the + purposes of Kerberos. + + Specifying **-**\ **-without-system-verto** will cause the built-in + version of libverto to be used unconditionally. + +**-**\ **-with-krb5-config=**\ *PATH* + Use the krb5-config program at *PATH* to obtain the build-time + default credential cache, keytab, and client keytab names. The + default is to use ``krb5-config`` from the program path. Specify + ``--without-krb5-config`` to disable the use of krb5-config and + use the usual built-in defaults. + +**-**\ **-without-keyutils** + Build without libkeyutils support. This disables the KEYRING + credential cache type. + + +Examples +-------- + +For example, in order to configure Kerberos on a Solaris machine using +the suncc compiler with the optimizer turned on, run the configure +script with the following options:: + + % ./configure CC=suncc CFLAGS=-O + +For a slightly more complicated example, consider a system where +several packages to be used by Kerberos are installed in +``/usr/foobar``, including Berkeley DB 3.3, and an ss library that +needs to link against the curses library. The configuration of +Kerberos might be done thus:: + + ./configure CPPFLAGS=-I/usr/foobar/include LDFLAGS=-L/usr/foobar/lib \ + --with-system-et --with-system-ss --with-system-db \ + SS_LIB='-lss -lcurses' DB_HEADER=db3/db_185.h DB_LIB=-ldb-3.3 diff --git a/krb5-1.21.3/doc/build/osconf.rst b/krb5-1.21.3/doc/build/osconf.rst new file mode 100644 index 00000000..22ee6804 --- /dev/null +++ b/krb5-1.21.3/doc/build/osconf.rst @@ -0,0 +1,26 @@ +osconf.hin +========== + +There is one configuration file which you may wish to edit to control +various compile-time parameters in the Kerberos distribution:: + + include/osconf.hin + +The list that follows is by no means complete, just some of the more +interesting variables. + +**DEFAULT_PROFILE_PATH** + The pathname to the file which contains the profiles for the known + realms, their KDCs, etc. The default value is |krb5conf|. +**DEFAULT_KEYTAB_NAME** + The type and pathname to the default server keytab file. The + default is |keytab|. +**DEFAULT_KDC_ENCTYPE** + The default encryption type for the KDC database master key. The + default value is |defmkey|. +**RCTMPDIR** + The directory which stores replay caches. The default is + ``/var/tmp``. +**DEFAULT_KDB_FILE** + The location of the default database. The default value is + |kdcdir|\ ``/principal``. diff --git a/krb5-1.21.3/doc/build_this.rst b/krb5-1.21.3/doc/build_this.rst new file mode 100644 index 00000000..9be7360a --- /dev/null +++ b/krb5-1.21.3/doc/build_this.rst @@ -0,0 +1,82 @@ +How to build this documentation from the source +=============================================== + +Pre-requisites for a simple build, or to update man pages: + +* Sphinx 1.0.4 or higher (See https://www.sphinx-doc.org) with the + autodoc extension installed. + +Additional prerequisites to include the API reference based on Doxygen +markup: + +* Python 2.5 with the Cheetah, lxml, and xml modules +* Doxygen + + +Simple build without API reference +---------------------------------- + +To test simple changes to the RST sources, you can build the +documentation without the Doxygen reference by running, from the doc +directory:: + + sphinx-build . test_html + +You will see a number of warnings about missing files. This is +expected. If there is not already a ``doc/version.py`` file, you will +need to create one by first running ``make version.py`` in the +``src/doc`` directory of a configured build tree. + + +Updating man pages +------------------ + +Man pages are generated from the RST sources and checked into the +``src/man`` directory of the repository. This allows man pages to be +installed without requiring Sphinx when using a source checkout. To +regenerate these files, run ``make man`` from the man subdirectory +of a configured build tree. You can also do this from an unconfigured +source tree with:: + + cd src/man + make -f Makefile.in top_srcdir=.. srcdir=. man + make clean + +As with the simple build, it is normal to see warnings about missing +files when rebuilding the man pages. + + +Building for a release tarball or web site +------------------------------------------ + +To generate documentation in HTML format, run ``make html`` in the +``doc`` subdirectory of a configured build tree (the build directory +corresponding to ``src/doc``, not the top-level ``doc`` directory). +The output will be placed in the top-level ``doc/html`` directory. +This build will include the API reference generated from Doxygen +markup in the source tree. + +Documentation generated this way will use symbolic names for paths +(like ``BINDIR`` for the directory containing user programs), with the +symbolic names being links to a table showing typical values for those +paths. + +You can also do this from an unconfigured source tree with:: + + cd src/doc + make -f Makefile.in SPHINX_ARGS= htmlsrc + + +Building for an OS package or site documentation +------------------------------------------------ + +To generate documentation specific to a build of MIT krb5 as you have +configured it, run ``make substhtml`` in the ``doc`` subdirectory of a +configured build tree (the build directory corresponding to +``src/doc``, not the top-level ``doc`` directory). The output will be +placed in the ``html_subst`` subdirectory of that build directory. +This build will include the API reference. + +Documentation generated this way will use concrete paths (like +``/usr/local/bin`` for the directory containing user programs, for a +default custom build). diff --git a/krb5-1.21.3/doc/coding-style b/krb5-1.21.3/doc/coding-style new file mode 100644 index 00000000..58a10893 --- /dev/null +++ b/krb5-1.21.3/doc/coding-style @@ -0,0 +1,5 @@ +Please see + + https://k5wiki.kerberos.org/wiki/Coding_style + +for the current coding style. diff --git a/krb5-1.21.3/doc/conf.py b/krb5-1.21.3/doc/conf.py new file mode 100644 index 00000000..ecf9020a --- /dev/null +++ b/krb5-1.21.3/doc/conf.py @@ -0,0 +1,320 @@ +# -*- coding: utf-8 -*- +# +# MIT Kerberos documentation build configuration file, created by +# sphinx-quickstart on Wed Oct 13 09:14:03 2010. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +#extensions = ['sphinx.ext.autodoc', 'sphinxcontrib.doxylink'] +extensions = ['sphinx.ext.autodoc'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +if 'notice' in tags: + master_doc = 'notice' +else: + master_doc = 'index' + +# General information about the project. +project = u'MIT Kerberos' +copyright = u'1985-2024, MIT' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +exec(open("version.py").read()) +# The short X.Y version. +r_list = [r_major, r_minor] +if r_patch: + r_list += [r_patch] +version = '.'.join(map(str, r_list)) +# The full version, including alpha/beta/rc tags. +release = version +if r_tail: + release += '-' + r_tail + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +today = ' ' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# When we can rely on Sphinx 1.8 (released Sep 2018) we can just set: +# html_css_files = ['kerb.css'] +# But in the meantime, we add this file using either a way that works +# after 1.8 or a way that works before 4.0. +def setup(app): + if callable(getattr(app, 'add_css_file', None)): + app.add_css_file('kerb.css') + else: + app.add_stylesheet('kerb.css') + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# html_theme = 'default' +html_theme = 'agogo' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +html_theme_options = { "linkcolor": "#881f0d", "footerbg": "#5d1509", + "bgcolor": "#5d1509", "documentwidth": "80%", + "pagewidth": "auto", "sidebarwidth": "20%" } + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +html_title = "MIT Kerberos Documentation" + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +if os.environ.get('HTML_LOGO'): + html_logo = os.environ['HTML_LOGO'] + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +html_split_index = True + +# If true, links to the reST sources are added to the pages. +html_show_sourcelink = False + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g., ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'MIT Kerberos' + +pointsize = '10pt' + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('admin/index', 'admin.tex', u"Kerberos Administration Guide", u'MIT', + 'manual'), + ('appdev/index', 'appdev.tex', u"Kerberos Application Developer Guide", + u'MIT', 'manual'), + ('basic/index', 'basic.tex', u"Kerberos Concepts", u'MIT', 'manual'), + ('build/index', 'build.tex', u"Building MIT Kerberos", u'MIT', 'manual'), + ('plugindev/index', 'plugindev.tex', u"Kerberos Plugin Module Developer Guide", + u'MIT', 'manual'), + ('user/index', 'user.tex', u"Kerberos User Guide", u'MIT', 'manual') +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + +if 'mansubs' in tags: + bindir = '``@BINDIR@``' + sbindir = '``@SBINDIR@``' + libdir = '``@LIBDIR@``' + localstatedir = '``@LOCALSTATEDIR@``' + runstatedir = '``@RUNSTATEDIR@``' + sysconfdir = '``@SYSCONFDIR@``' + ccache = '``@CCNAME@``' + keytab = '``@KTNAME@``' + ckeytab = '``@CKTNAME@``' + pkcs11_modname = '``@PKCS11MOD@``' +elif 'pathsubs' in tags: + # Read configured paths from a file produced by the build system. + exec(open("paths.py").read()) +else: + bindir = ':ref:`BINDIR `' + sbindir = ':ref:`SBINDIR `' + libdir = ':ref:`LIBDIR `' + localstatedir = ':ref:`LOCALSTATEDIR `' + runstatedir = ':ref:`RUNSTATEDIR `' + sysconfdir = ':ref:`SYSCONFDIR `' + ccache = ':ref:`DEFCCNAME `' + keytab = ':ref:`DEFKTNAME `' + ckeytab = ':ref:`DEFCKTNAME `' + pkcs11_modname = ':ref:`PKCS11_MODNAME `' + +rst_epilog = '\n' + +if 'notice' in tags: + exclude_patterns = [ 'admin', 'appdev', 'basic', 'build', + 'plugindev', 'user' ] + exclude_patterns += [ 'about.rst', 'build_this.rst', 'copyright.rst', + 'index.rst', 'mitK5*.rst', 'resources.rst' ] + rst_epilog += '.. |copy| replace:: \(C\)' +else: + exclude_patterns += [ 'notice.rst' ] + rst_epilog += '.. |bindir| replace:: %s\n' % bindir + rst_epilog += '.. |sbindir| replace:: %s\n' % sbindir + rst_epilog += '.. |libdir| replace:: %s\n' % libdir + rst_epilog += '.. |kdcdir| replace:: %s\\ ``/krb5kdc``\n' % localstatedir + rst_epilog += '.. |kdcrundir| replace:: %s\\ ``/krb5kdc``\n' % runstatedir + rst_epilog += '.. |sysconfdir| replace:: %s\n' % sysconfdir + rst_epilog += '.. |ccache| replace:: %s\n' % ccache + rst_epilog += '.. |keytab| replace:: %s\n' % keytab + rst_epilog += '.. |ckeytab| replace:: %s\n' % ckeytab + rst_epilog += '.. |pkcs11_modname| replace:: %s\n' % pkcs11_modname + rst_epilog += ''' +.. |krb5conf| replace:: ``/etc/krb5.conf`` +.. |defkeysalts| replace:: ``aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal`` +.. |defetypes| replace:: ``aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac`` +.. |defmkey| replace:: ``aes256-cts-hmac-sha1-96`` +.. |copy| unicode:: U+000A9 +''' + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('user/user_commands/kinit', 'kinit', u'obtain and cache Kerberos ticket-granting ticket', [u'MIT'], 1), + ('user/user_commands/klist', 'klist', u'list cached Kerberos tickets', [u'MIT'], 1), + ('user/user_commands/kdestroy', 'kdestroy', u'destroy Kerberos tickets', [u'MIT'], 1), + ('user/user_commands/kswitch', 'kswitch', u'switch primary ticket cache', [u'MIT'], 1), + ('user/user_commands/kpasswd', 'kpasswd', u'change a user\'s Kerberos password', [u'MIT'], 1), + ('user/user_commands/kvno', 'kvno', u'print key version numbers of Kerberos principals', [u'MIT'], 1), + ('user/user_commands/ksu', 'ksu', u'Kerberized super-user', [u'MIT'], 1), + ('user/user_commands/krb5-config', 'krb5-config', u'tool for linking against MIT Kerberos libraries', [u'MIT'], 1), + ('user/user_config/k5login', 'k5login', u'Kerberos V5 acl file for host access', [u'MIT'], 5), + ('user/user_config/k5identity', 'k5identity', u'Kerberos V5 client principal selection rules', [u'MIT'], 5), + ('user/user_config/kerberos', 'kerberos', u'Overview of using Kerberos', [u'MIT'], 7), + ('admin/admin_commands/krb5kdc', 'krb5kdc', u'Kerberos V5 KDC', [u'MIT'], 8), + ('admin/admin_commands/kadmin_local', 'kadmin', u'Kerberos V5 database administration program', [u'MIT'], 1), + ('admin/admin_commands/kprop', 'kprop', u'propagate a Kerberos V5 principal database to a replica server', [u'MIT'], 8), + ('admin/admin_commands/kproplog', 'kproplog', u'display the contents of the Kerberos principal update log', [u'MIT'], 8), + ('admin/admin_commands/kpropd', 'kpropd', u'Kerberos V5 replica KDC update server', [u'MIT'], 8), + ('admin/admin_commands/kdb5_util', 'kdb5_util', u'Kerberos database maintenance utility', [u'MIT'], 8), + ('admin/admin_commands/ktutil', 'ktutil', u'Kerberos keytab file maintenance utility', [u'MIT'], 1), + ('admin/admin_commands/k5srvutil', 'k5srvutil', u'host key table (keytab) manipulation utility', [u'MIT'], 1), + ('admin/admin_commands/kadmind', 'kadmind', u'KADM5 administration server', [u'MIT'], 8), + ('admin/admin_commands/kdb5_ldap_util', 'kdb5_ldap_util', u'Kerberos configuration utility', [u'MIT'], 8), + ('admin/conf_files/krb5_conf', 'krb5.conf', u'Kerberos configuration file', [u'MIT'], 5), + ('admin/conf_files/kdc_conf', 'kdc.conf', u'Kerberos V5 KDC configuration file', [u'MIT'], 5), + ('admin/conf_files/kadm5_acl', 'kadm5.acl', u'Kerberos ACL file', [u'MIT'], 5), + ('user/user_commands/sclient', 'sclient', u'sample Kerberos version 5 client', [u'MIT'], 1), + ('admin/admin_commands/sserver', 'sserver', u'sample Kerberos version 5 server', [u'MIT'], 8), +] diff --git a/krb5-1.21.3/doc/contributing.txt b/krb5-1.21.3/doc/contributing.txt new file mode 100644 index 00000000..776c5d58 --- /dev/null +++ b/krb5-1.21.3/doc/contributing.txt @@ -0,0 +1,70 @@ + Contributing to MIT Kerberos + +DESIGN +====== + +If you are planning to contribute a substantial amount of work, please +ensure that you have a discussion about the design on the +krbdev@mit.edu list. Some changes may require coordination with +standards groups. For example, interface changes and extensions for +the GSS-API should be discussed in the IETF KITTEN Working Group. + +STYLE +===== + +Please follow the guidelines in doc/coding-style for new code. For +existing code, please preserve its existing indentation and brace +conventions. These existing conventions usually resemble the +guidelines in doc/coding-style. Exceptions to the style in +doc/coding-style are usually large past contributions or imports from +other parties. These include (not an exhaustive list): + + src/appl/bsd + src/appl/gssftp + src/appl/telnet + src/kadmin + src/lib/kadm5 + src/lib/gssapi/mechglue + src/lib/rpc + +PATCHES +======= + +We prefer patches in either unified or context diff format (diff -u or +diff -c). As is usual practice, please specify the original file +before the modified file on the diff command line. It's also useful +to perform the diff from the top level of the tree, e.g., + + diff -ur src.orig src + +It's even more useful if you use our anonymous Subversion repository +at + + svn://anonsvn.mit.edu/krb5 + +and use "svn diff" (or "svk diff" if you prefer to use SVK) to +generate your patches. + +It is much easier for us to integrate patches which are generated +against current code on the trunk. Please ensure that your source +tree is up-to-date before generating your patch. + +COPYRIGHT +========= + +If you are submitting substantial quantities of new code, or are +substantially modifying existing code, please be clear about the +copyright status of your contributions. Note that if your +contribution was created in the course of your employment, your +employer may own copyright in your contribution. + +We prefer that MIT receives the ownership of the contributions, but +will generally accept contributed code with copyright owned by other +parties provided that the license conditions are substantially +identical to the existing license on the MIT krb5 code. + +Appropriate copyright notices and license terms should be added to new +or changed files, unless the contributed code is being assigned to the +already-listed copyright holder in the file, or the contribution is +being released to the public domain. Please make sure that the +year in the copyright statement is kept up-to-date. diff --git a/krb5-1.21.3/doc/copyright.rst b/krb5-1.21.3/doc/copyright.rst new file mode 100644 index 00000000..85ecebec --- /dev/null +++ b/krb5-1.21.3/doc/copyright.rst @@ -0,0 +1,8 @@ +Copyright +========= + +Copyright |copy| 1985-2024 by the Massachusetts Institute of +Technology and its contributors. All rights reserved. + +See :ref:`mitK5license` for additional copyright and license +information. diff --git a/krb5-1.21.3/doc/doxy_examples/cc_set_config.c b/krb5-1.21.3/doc/doxy_examples/cc_set_config.c new file mode 100644 index 00000000..838ff7e2 --- /dev/null +++ b/krb5-1.21.3/doc/doxy_examples/cc_set_config.c @@ -0,0 +1,33 @@ +/** @example cc_set_config.c + * + * Usage examples for krb5_cc_set_config and krb5_cc_get_config functions + */ +#include + +krb5_error_code +func_set(krb5_context context, krb5_ccache id, + krb5_const_principal principal, const char *key) +{ + krb5_data config_data; + + config_data.data = "yes"; + config_data.length = strlen(config_data.data); + return krb5_cc_set_config(context, id, principal, key, &config_data); +} + +krb5_error_code +func_get(krb5_context context, krb5_ccache id, + krb5_const_principal principal, const char *key) +{ + krb5_data config_data; + krb5_error_code ret; + + config_data.data = NULL; + ret = krb5_cc_get_config(context, id, principal, key, &config_data); + if (ret){ + return ret; + } + /* do something */ + krb5_free_data_contents(context, &config_data); + return ret; +} diff --git a/krb5-1.21.3/doc/doxy_examples/cc_unique.c b/krb5-1.21.3/doc/doxy_examples/cc_unique.c new file mode 100644 index 00000000..0a03edb5 --- /dev/null +++ b/krb5-1.21.3/doc/doxy_examples/cc_unique.c @@ -0,0 +1,23 @@ +/** @example cc_unique.c + * + * Usage example for krb5_cc_new_unique function + */ +#include "k5-int.h" + +krb5_error_code +func(krb5_context context) +{ + krb5_error_code ret; + krb5_ccache ccache = NULL; + + ret = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache); + if (ret){ + ccache = NULL; + return ret; + } + /* do something */ + if (ccache) + (void)krb5_cc_destroy(context, ccache); + return 0; +} + diff --git a/krb5-1.21.3/doc/doxy_examples/error_message.c b/krb5-1.21.3/doc/doxy_examples/error_message.c new file mode 100755 index 00000000..1e156976 --- /dev/null +++ b/krb5-1.21.3/doc/doxy_examples/error_message.c @@ -0,0 +1,20 @@ +/** @example error_message.c + * + * Demo for krb5_get/set/free_error_message function family + */ +#include + +krb5_error_code +func(krb5_context context) +{ + krb5_error_code ret; + + ret = krb5_func(context); + if (ret) { + const char *err_str = krb5_get_error_message(context, ret); + krb5_set_error_message(context, ret, + "Failed krb5_func: %s", err_str); + krb5_free_error_message(context, err_str); + } +} + diff --git a/krb5-1.21.3/doc/doxy_examples/tkt_creds.c b/krb5-1.21.3/doc/doxy_examples/tkt_creds.c new file mode 100644 index 00000000..9ddf5cc8 --- /dev/null +++ b/krb5-1.21.3/doc/doxy_examples/tkt_creds.c @@ -0,0 +1,55 @@ +/** @example tkt_creds.c + * + * Usage example for krb5_tkt_creds function family + */ +#include "krb5.h" + +krb5_error_code +func(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_creds **out_creds) +{ + krb5_error_code code = KRB5_OK; + krb5_creds *ncreds = NULL; + krb5_tkt_creds_context ctx = NULL; + + *out_creds = NULL; + + /* Allocate a container. */ + ncreds = k5alloc(sizeof(*ncreds), &code); + if (ncreds == NULL) + goto cleanup; + + /* Make and execute a krb5_tkt_creds context to get the credential. */ + code = krb5_tkt_creds_init(context, ccache, in_creds, options, &ctx); + if (code != KRB5_OK) + goto cleanup; + code = krb5_tkt_creds_get(context, ctx); + if (code != KRB5_OK) + goto cleanup; + code = krb5_tkt_creds_get_creds(context, ctx, ncreds); + if (code != KRB5_OK) + goto cleanup; + + *out_creds = ncreds; + ncreds = NULL; + +cleanup: + krb5_free_creds(context, ncreds); + krb5_tkt_creds_free(context, ctx); + return code; +} + +/* Allocate zeroed memory; set *code to 0 on success or ENOMEM on failure. */ +static inline void * +k5alloc(size_t len, krb5_error_code *code) +{ + void *ptr; + + /* Allocate at least one byte since zero-byte allocs may return NULL. */ + ptr = calloc((len > 0) ? len : 1, 1); + *code = (ptr == NULL) ? ENOMEM : 0; + return ptr; +} + + diff --git a/krb5-1.21.3/doc/doxy_examples/verify_init_creds.c b/krb5-1.21.3/doc/doxy_examples/verify_init_creds.c new file mode 100644 index 00000000..c22e2528 --- /dev/null +++ b/krb5-1.21.3/doc/doxy_examples/verify_init_creds.c @@ -0,0 +1,28 @@ +/** @example verify_init_creds.c + * + * Usage example for krb5_verify_init_creds function family + */ +#include "k5-int.h" + +krb5_error_code +func(krb5_context context, krb5_creds *creds, krb5_principal server_principal) +{ + krb5_error_code ret = KRB5_OK; + krb5_verify_init_creds_opt options; + + krb5_verify_init_creds_opt_init (&options); + krb5_verify_init_creds_opt_set_ap_req_nofail (&options, 1); + + ret = krb5_verify_init_creds(context, + creds, + server_principal, + NULL /* use default keytab */, + NULL /* don't store creds in ccache */, + &options); + if (ret) { + /* error while verifying credentials for server */ + } + + return ret; +} + diff --git a/krb5-1.21.3/doc/formats/ccache_file_format.rst b/krb5-1.21.3/doc/formats/ccache_file_format.rst new file mode 100644 index 00000000..6138c1b5 --- /dev/null +++ b/krb5-1.21.3/doc/formats/ccache_file_format.rst @@ -0,0 +1,182 @@ +.. _ccache_file_format: + +Credential cache file format +============================ + +There are four versions of the file format used by the FILE credential +cache type. The first byte of the file always has the value 5, and +the value of the second byte contains the version number (1 through +4). Versions 1 and 2 of the file format use native byte order for integer +representations. Versions 3 and 4 always use big-endian byte order. + +After the two-byte version indicator, the file has three parts: the +header (in version 4 only), the default principal name, and a sequence +of credentials. + + +Header format +------------- + +The header appears only in format version 4. It begins with a 16-bit +integer giving the length of the entire header, followed by a sequence +of fields. Each field consists of a 16-bit tag, a 16-bit length, and +a value of the given length. A file format implementation should +ignore fields with unknown tags. + +At this time there is only one defined header field. Its tag value is +1, its length is always 8, and its contents are two 32-bit integers +giving the seconds and microseconds of the time offset of the KDC +relative to the client. Adding this offset to the current time on the +client should give the current time on the KDC, if that offset has not +changed since the initial authentication. + + +.. _cache_principal_format: + +Principal format +---------------- + +The default principal is marshalled using the following informal +grammar:: + + principal ::= + name type (32 bits) [omitted in version 1] + count of components (32 bits) [includes realm in version 1] + realm (data) + component1 (data) + component2 (data) + ... + + data ::= + length (32 bits) + value (length bytes) + +There is no external framing on the default principal, so it must be +parsed according to the above grammar in order to find the sequence of +credentials which follows. + + +.. _ccache_credential_format: + +Credential format +----------------- + +The credential format uses the following informal grammar (referencing +the ``principal`` and ``data`` types from the previous section):: + + credential ::= + client (principal) + server (principal) + keyblock (keyblock) + authtime (32 bits) + starttime (32 bits) + endtime (32 bits) + renew_till (32 bits) + is_skey (1 byte, 0 or 1) + ticket_flags (32 bits) + addresses (addresses) + authdata (authdata) + ticket (data) + second_ticket (data) + + keyblock ::= + enctype (16 bits) [repeated twice in version 3] + data + + addresses ::= + count (32 bits) + address1 + address2 + ... + + address ::= + addrtype (16 bits) + data + + authdata ::= + count (32 bits) + authdata1 + authdata2 + ... + + authdata ::= + ad_type (16 bits) + data + +There is no external framing on a marshalled credential, so it must be +parsed according to the above grammar in order to find the next +credential. There is also no count of credentials or marker at the +end of the sequence of credentials; the sequence ends when the file +ends. + + +Credential cache configuration entries +-------------------------------------- + +Configuration entries are encoded as credential entries. The client +principal of the entry is the default principal of the cache. The +server principal has the realm ``X-CACHECONF:`` and two or three +components, the first of which is ``krb5_ccache_conf_data``. The +server principal's second component is the configuration key. The +third component, if it exists, is a principal to which the +configuration key is associated. The configuration value is stored in +the ticket field of the entry. All other entry fields are zeroed. + +Programs using credential caches must be aware of configuration +entries for several reasons: + +* A program which displays the contents of a cache should not + generally display configuration entries. + +* The ticket field of a configuration entry is not (usually) a valid + encoding of a Kerberos ticket. An implementation must not treat the + cache file as malformed if it cannot decode the ticket field. + +* Configuration entries have an endtime field of 0 and might therefore + always be considered expired, but they should not be treated as + unimportant as a result. For instance, a program which copies + credentials from one cache to another should not omit configuration + entries because of the endtime. + +The following configuration keys are currently used in MIT krb5: + +fast_avail + The presence of this key with a non-empty value indicates that the + KDC asserted support for FAST (see :rfc:`6113`) during the initial + authentication, using the negotiation method described in + :rfc:`6806` section 11. This key is not associated with any + principal. + +pa_config_data + The value of this key contains a JSON object representation of + parameters remembered by the preauthentication mechanism used + during the initial authentication. These parameters may be used + when refreshing credentials. This key is associated with the + server principal of the initial authentication (usually the local + krbtgt principal of the client realm). + +pa_type + The value of this key is the ASCII decimal representation of the + preauth type number used during the initial authentication. This + key is associated with the server principal of the initial + authentication. + +proxy_impersonator + The presence of this key indicates that the cache is a synthetic + delegated credential for use with S4U2Proxy. The value is the + name of the intermediate service whose TGT can be used to make + S4U2Proxy requests for target services. This key is not + associated with any principal. + +refresh_time + The presence of this key indicates that the cache was acquired by + the GSS mechanism using a client keytab. The value is the ASCII + decimal representation of a timestamp at which the GSS mechanism + should attempt to refresh the credential cache from the client + keytab. + +start_realm + This key indicates the realm of the ticket-granting ticket to be + used for TGS requests, when making a referrals request or + beginning a cross-realm request. If it is not present, the client + realm is used. diff --git a/krb5-1.21.3/doc/formats/cookie.rst b/krb5-1.21.3/doc/formats/cookie.rst new file mode 100644 index 00000000..e32365da --- /dev/null +++ b/krb5-1.21.3/doc/formats/cookie.rst @@ -0,0 +1,97 @@ +KDC cookie format +================= + +:rfc:`6113` section 5.2 specifies a pa-data type PA-FX-COOKIE, which +clients are required to reflect back to the KDC during +pre-authentication. The MIT krb5 KDC uses the following formats for +cookies. + + +Trivial cookie (version 0) +-------------------------- + +If there is no pre-authentication mechanism state information to save, +a trivial cookie containing the value "MIT" is used. A trivial cookie +is needed to indicate that the conversation can continue. + + +Secure cookie (version 1) +------------------------- + +In release 1.14 and later, a secure cookie can be sent if there is any +mechanism state to save for the next request. A secure cookie +contains the concatenation of the following: + +* the four bytes "MIT1" +* a four-byte big-endian kvno value +* an :rfc:`3961` ciphertext + +The ciphertext is encrypted in the cookie key with key usage +number 513. The cookie key is derived from a key in the local krbtgt +principal entry for the realm (e.g. ``krbtgt/KRBTEST.COM@KRBTEST.COM`` +if the request is to the ``KRBTEST.COM`` realm). The first krbtgt key +for the indicated kvno value is combined with the client principal as +follows:: + + cookie-key <- random-to-key(PRF+(tgt-key, "COOKIE" | client-princ)) + +where **random-to-key** is the :rfc:`3961` random-to-key operation for +the krbtgt key's encryption type, **PRF+** is defined in :rfc:`6113`, +and ``|`` denotes concatenation. *client-princ* is the request client +principal name with realm, marshalled according to :rfc:`1964` section +2.1.1. + +The plain text of the encrypted part of a cookie is the DER encoding +of the following ASN.1 type:: + + SecureCookie ::= SEQUENCE { + time INTEGER, + data SEQUENCE OF PA-DATA, + ... + } + +The time field represents the cookie creation time; for brevity, it is +encoded as an integer giving the POSIX timestamp rather than as an +ASN.1 GeneralizedTime value. The data field contains one element for +each pre-authentication type which requires saved state. For +mechanisms which have separate request and reply types, the request +type is used; this allows the KDC to determine whether a cookie is +relevant to a request by comparing the request pa-data types to the +cookie data types. + +SPAKE cookie format (version 1) +------------------------------- + +Inside the SecureCookie wrapper, a data value of type 151 contains +state for SPAKE pre-authentication. This data is the concatenation of +the following: + +* a two-byte big-endian version number with the value 1 +* a two-byte big-endian stage number +* a four-byte big-endian group number +* a four-byte big-endian length and data for the SPAKE value +* a four-byte big-endian length and data for the transcript hash +* zero or more second factor records, each consisting of: + - a four-byte big-endian second-factor type + - a four-byte big-endian length and data + +The stage value is 0 if the cookie was sent with a challenge message. +Otherwise it is 1 for the first encdata message sent by the KDC during +an exchange, 2 for the second, etc.. + +The group value indicates the group number used in the SPAKE challenge. + +For a stage-0 cookie, the SPAKE value is the KDC private key, +represented in the scalar marshalling form of the group. For other +cookies, the SPAKE value is the SPAKE result K, represented in the +group element marshalling form. + +For a stage-0 cookie, the transcript hash is the intermediate hash +after updating with the client support message (if one was sent) and +challenge. For other cookies it is the final hash. + +For a stage-0 cookie, there may be any number of second-factor +records, including none; a second-factor type need not create a state +field if it does not need one, and no record is created for SF-NONE. +For other cookies, there must be exactly one second-factor record +corresponding to the factor type chosen by the client. diff --git a/krb5-1.21.3/doc/formats/freshness_token.rst b/krb5-1.21.3/doc/formats/freshness_token.rst new file mode 100644 index 00000000..3127621a --- /dev/null +++ b/krb5-1.21.3/doc/formats/freshness_token.rst @@ -0,0 +1,19 @@ +PKINIT freshness tokens +======================= + +:rfc:`8070` specifies a pa-data type PA_AS_FRESHNESS, which clients +should reflect within signed PKINIT data to prove recent access to the +client certificate private key. The contents of a freshness token are +left to the KDC implementation. The MIT krb5 KDC uses the following +format for freshness tokens (starting in release 1.17): + +* a four-byte big-endian POSIX timestamp +* a four-byte big-endian key version number +* an :rfc:`3961` checksum, with no ASN.1 wrapper + +The checksum is computed using the first key in the local krbtgt +principal entry for the realm (e.g. ``krbtgt/KRBTEST.COM@KRBTEST.COM`` +if the request is to the ``KRBTEST.COM`` realm) of the indicated key +version. The checksum type must be the mandatory checksum type for +the encryption type of the krbtgt key. The key usage value for the +checksum is 514. diff --git a/krb5-1.21.3/doc/formats/index.rst b/krb5-1.21.3/doc/formats/index.rst new file mode 100644 index 00000000..47dea12f --- /dev/null +++ b/krb5-1.21.3/doc/formats/index.rst @@ -0,0 +1,11 @@ +Protocols and file formats +========================== + +.. toctree:: + :maxdepth: 1 + + ccache_file_format + keytab_file_format + rcache_file_format + cookie + freshness_token diff --git a/krb5-1.21.3/doc/formats/keytab_file_format.rst b/krb5-1.21.3/doc/formats/keytab_file_format.rst new file mode 100644 index 00000000..8424d058 --- /dev/null +++ b/krb5-1.21.3/doc/formats/keytab_file_format.rst @@ -0,0 +1,51 @@ +.. _keytab_file_format: + +Keytab file format +================== + +There are two versions of the file format used by the FILE keytab +type. The first byte of the file always has the value 5, and the +value of the second byte contains the version number (1 or 2). +Version 1 of the file format uses native byte order for integer +representations. Version 2 always uses big-endian byte order. + +After the two-byte version indicator, the file contains a sequence of +signed 32-bit record lengths followed by key records or holes. A +positive record length indicates a valid key entry whose size is equal +to or less than the record length. A negative length indicates a +zero-filled hole whose size is the inverse of the length. A length of +0 indicates the end of the file. + + +Key entry format +---------------- + +A key entry may be smaller in size than the record length which +precedes it, because it may have replaced a hole which is larger than +the key entry. Key entries use the following informal grammar:: + + entry ::= + principal + timestamp (32 bits) + key version (8 bits) + enctype (16 bits) + key length (16 bits) + key contents + key version (32 bits) [in release 1.14 and later] + + principal ::= + count of components (16 bits) [includes realm in version 1] + realm (data) + component1 (data) + component2 (data) + ... + name type (32 bits) [omitted in version 1] + + data ::= + length (16 bits) + value (length bytes) + +The 32-bit key version overrides the 8-bit key version. To determine +if it is present, the implementation must check that at least 4 bytes +remain in the record after the other fields are read, and that the +value of the 32-bit integer contained in those bytes is non-zero. diff --git a/krb5-1.21.3/doc/formats/rcache_file_format.rst b/krb5-1.21.3/doc/formats/rcache_file_format.rst new file mode 100644 index 00000000..42ee8281 --- /dev/null +++ b/krb5-1.21.3/doc/formats/rcache_file_format.rst @@ -0,0 +1,50 @@ +Replay cache file format +======================== + +This section documents the second version of the replay cache file +format, used by the "file2" replay cache type (new in release 1.18). +The first version of the file replay cache format is not documented. + +All accesses to the replay cache file take place under an exclusive +POSIX or Windows file lock, obtained when the file is opened and +released when it is closed. Replay cache files are automatically +created when first accessed. + +For each store operation, a tag is derived from the checksum part of +the :RFC:`3961` ciphertext of the authenticator. The checksum is +coerced to a fixed length of 12 bytes, either through truncation or +right-padding with zero bytes. A four-byte timestamp is appended to +the tag to produce a total record length of 16 bytes. + +Bytes 0 through 15 of the file contain a hash seed for the SipHash-2-4 +algorithm (siphash_); this field is populated with random bytes when +the file is first created. All remaining bytes are divided into a +series of expanding hash tables: + +* Bytes 16-16383: hash table 1 (1023 slots) +* Bytes 16384-49151: hash table 2 (2048 slots) +* Bytes 49152-114687: hash table 3 (4096 slots) +* ... + +Only some hash tables will be present in the file at any specific +time, and the final table may be only partially filled. Replay cache +files may be sparse if the filesystem supports it. + +For each table present in the file, the tag is hashed with SipHash-2-4 +using the seed recorded in the file. The first byte of the seed is +incremented by one (modulo 256) for each table after the first. The +resulting hash value is taken modulo one less than the table size +(1022 for the first hash table, 2047 for the second) to produce the +index. The record may be found at the slot given by the index or at +the next slot. + +All candidate locations for the record must be searched until a slot +is found with a timestamp of zero (indicating a slot which has never +been written to) or an offset is reached at or beyond the end of the +file. Any candidate location with a timestamp value of zero, with a +timestamp value less than the current time minus clockskew, or at or +beyond the end of the file is available for writing. When all +candidate locations have been searched without finding a match, the +new entry is written to the earliest candidate available for writing. + +.. _siphash: https://131002.net/siphash/siphash.pdf diff --git a/krb5-1.21.3/doc/html/.buildinfo b/krb5-1.21.3/doc/html/.buildinfo new file mode 100644 index 00000000..a9714486 --- /dev/null +++ b/krb5-1.21.3/doc/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 9ca503a4e24138fa47d4451ee9426bb5 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/krb5-1.21.3/doc/html/_sources/about.rst.txt b/krb5-1.21.3/doc/html/_sources/about.rst.txt new file mode 100644 index 00000000..dfdc31fb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/about.rst.txt @@ -0,0 +1,35 @@ +Contributing to the MIT Kerberos Documentation +============================================== + +We are looking for documentation writers and editors who could contribute +towards improving the MIT KC documentation content. If you are an experienced +Kerberos developer and/or administrator, please consider sharing your knowledge +and experience with the Kerberos Community. You can suggest your own topic or +write about any of the topics listed +`here `__. + +If you have any questions, comments, or suggestions on the existing documents, +please send your feedback via email to krb5-bugs@mit.edu. The HTML version of +this documentation has a "FEEDBACK" link to the krb5-bugs@mit.edu email +address with a pre-constructed subject line. + + +Background +---------- + +Starting with release 1.11, the Kerberos documentation set is +unified in a central form. Man pages, HTML documentation, and PDF +documents are compiled from reStructuredText sources, and the application +developer documentation incorporates Doxygen markup from the source +tree. This project was undertaken along the outline described +`here `__. + +Previous versions of Kerberos 5 attempted to maintain separate documentation +in the texinfo format, with separate groff manual pages. Having the API +documentation disjoint from the source code implementing that API +resulted in the documentation becoming stale, and over time the documentation +ceased to match reality. With a fresh start and a source format that is +easier to use and maintain, reStructuredText-based documents should provide +an improved experience for the user. Consolidating all the documentation +formats into a single source document makes the documentation set easier +to maintain. diff --git a/krb5-1.21.3/doc/html/_sources/admin/admin_commands/index.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/index.rst.txt new file mode 100644 index 00000000..e8dc7652 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/index.rst.txt @@ -0,0 +1,17 @@ +Administration programs +======================== + +.. toctree:: + :maxdepth: 1 + + kadmin_local.rst + kadmind.rst + kdb5_util.rst + kdb5_ldap_util.rst + krb5kdc.rst + kprop.rst + kpropd.rst + kproplog.rst + ktutil.rst + k5srvutil.rst + sserver.rst diff --git a/krb5-1.21.3/doc/html/_sources/admin/admin_commands/k5srvutil.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/k5srvutil.rst.txt new file mode 100644 index 00000000..79502cf9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/k5srvutil.rst.txt @@ -0,0 +1,69 @@ +.. _k5srvutil(1): + +k5srvutil +========= + +SYNOPSIS +-------- + +**k5srvutil** *operation* +[**-i**] +[**-f** *filename*] +[**-e** *keysalts*] + +DESCRIPTION +----------- + +k5srvutil allows an administrator to list keys currently in +a keytab, to obtain new keys for a principal currently in a keytab, +or to delete non-current keys from a keytab. + +*operation* must be one of the following: + +**list** + Lists the keys in a keytab, showing version number and principal + name. + +**change** + Uses the kadmin protocol to update the keys in the Kerberos + database to new randomly-generated keys, and updates the keys in + the keytab to match. If a key's version number doesn't match the + version number stored in the Kerberos server's database, then the + operation will fail. If the **-i** flag is given, k5srvutil will + prompt for confirmation before changing each key. If the **-k** + option is given, the old and new keys will be displayed. + Ordinarily, keys will be generated with the default encryption + types and key salts. This can be overridden with the **-e** + option. Old keys are retained in the keytab so that existing + tickets continue to work, but **delold** should be used after + such tickets expire, to prevent attacks against the old keys. + +**delold** + Deletes keys that are not the most recent version from the keytab. + This operation should be used some time after a change operation + to remove old keys, after existing tickets issued for the service + have expired. If the **-i** flag is given, then k5srvutil will + prompt for confirmation for each principal. + +**delete** + Deletes particular keys in the keytab, interactively prompting for + each key. + +In all cases, the default keytab is used unless this is overridden by +the **-f** option. + +k5srvutil uses the :ref:`kadmin(1)` program to edit the keytab in +place. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kadmin(1)`, :ref:`ktutil(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kadmin_local.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kadmin_local.rst.txt new file mode 100644 index 00000000..2435b3c3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kadmin_local.rst.txt @@ -0,0 +1,985 @@ +.. _kadmin(1): + +kadmin +====== + +SYNOPSIS +-------- + +.. _kadmin_synopsis: + +**kadmin** +[**-O**\|\ **-N**] +[**-r** *realm*] +[**-p** *principal*] +[**-q** *query*] +[[**-c** *cache_name*]\|[**-k** [**-t** *keytab*]]\|\ **-n**] +[**-w** *password*] +[**-s** *admin_server*\ [:*port*]] +[command args...] + +**kadmin.local** +[**-r** *realm*] +[**-p** *principal*] +[**-q** *query*] +[**-d** *dbname*] +[**-e** *enc*:*salt* ...] +[**-m**] +[**-x** *db_args*] +[command args...] + + +DESCRIPTION +----------- + +kadmin and kadmin.local are command-line interfaces to the Kerberos V5 +administration system. They provide nearly identical functionalities; +the difference is that kadmin.local directly accesses the KDC +database, while kadmin performs operations using :ref:`kadmind(8)`. +Except as explicitly noted otherwise, this man page will use "kadmin" +to refer to both versions. kadmin provides for the maintenance of +Kerberos principals, password policies, and service key tables +(keytabs). + +The remote kadmin client uses Kerberos to authenticate to kadmind +using the service principal ``kadmin/admin`` or ``kadmin/ADMINHOST`` +(where *ADMINHOST* is the fully-qualified hostname of the admin +server). If the credentials cache contains a ticket for one of these +principals, and the **-c** credentials_cache option is specified, that +ticket is used to authenticate to kadmind. Otherwise, the **-p** and +**-k** options are used to specify the client Kerberos principal name +used to authenticate. Once kadmin has determined the principal name, +it requests a service ticket from the KDC, and uses that service +ticket to authenticate to kadmind. + +Since kadmin.local directly accesses the KDC database, it usually must +be run directly on the primary KDC with sufficient permissions to read +the KDC database. If the KDC database uses the LDAP database module, +kadmin.local can be run on any host which can access the LDAP server. + + +OPTIONS +------- + +.. _kadmin_options: + +**-r** *realm* + Use *realm* as the default database realm. + +**-p** *principal* + Use *principal* to authenticate. Otherwise, kadmin will append + ``/admin`` to the primary principal name of the default ccache, + the value of the **USER** environment variable, or the username as + obtained with getpwuid, in order of preference. + +**-k** + Use a keytab to decrypt the KDC response instead of prompting for + a password. In this case, the default principal will be + ``host/hostname``. If there is no keytab specified with the + **-t** option, then the default keytab will be used. + +**-t** *keytab* + Use *keytab* to decrypt the KDC response. This can only be used + with the **-k** option. + +**-n** + Requests anonymous processing. Two types of anonymous principals + are supported. For fully anonymous Kerberos, configure PKINIT on + the KDC and configure **pkinit_anchors** in the client's + :ref:`krb5.conf(5)`. Then use the **-n** option with a principal + of the form ``@REALM`` (an empty principal name followed by the + at-sign and a realm name). If permitted by the KDC, an anonymous + ticket will be returned. A second form of anonymous tickets is + supported; these realm-exposed tickets hide the identity of the + client but not the client's realm. For this mode, use ``kinit + -n`` with a normal principal name. If supported by the KDC, the + principal (but not realm) will be replaced by the anonymous + principal. As of release 1.8, the MIT Kerberos KDC only supports + fully anonymous operation. + +**-c** *credentials_cache* + Use *credentials_cache* as the credentials cache. The cache + should contain a service ticket for the ``kadmin/admin`` or + ``kadmin/ADMINHOST`` (where *ADMINHOST* is the fully-qualified + hostname of the admin server) service; it can be acquired with the + :ref:`kinit(1)` program. If this option is not specified, kadmin + requests a new service ticket from the KDC, and stores it in its + own temporary ccache. + +**-w** *password* + Use *password* instead of prompting for one. Use this option with + care, as it may expose the password to other users on the system + via the process list. + +**-q** *query* + Perform the specified query and then exit. + +**-d** *dbname* + Specifies the name of the KDC database. This option does not + apply to the LDAP database module. + +**-s** *admin_server*\ [:*port*] + Specifies the admin server which kadmin should contact. + +**-m** + If using kadmin.local, prompt for the database master password + instead of reading it from a stash file. + +**-e** "*enc*:*salt* ..." + Sets the keysalt list to be used for any new keys created. See + :ref:`Keysalt_lists` in :ref:`kdc.conf(5)` for a list of possible + values. + +**-O** + Force use of old AUTH_GSSAPI authentication flavor. + +**-N** + Prevent fallback to AUTH_GSSAPI authentication flavor. + +**-x** *db_args* + Specifies the database specific arguments. See the next section + for supported options. + +Starting with release 1.14, if any command-line arguments remain after +the options, they will be treated as a single query to be executed. +This mode of operation is intended for scripts and behaves differently +from the interactive mode in several respects: + +* Query arguments are split by the shell, not by kadmin. +* Informational and warning messages are suppressed. Error messages + and query output (e.g. for **get_principal**) will still be + displayed. +* Confirmation prompts are disabled (as if **-force** was given). + Password prompts will still be issued as required. +* The exit status will be non-zero if the query fails. + +The **-q** option does not carry these behavior differences; the query +will be processed as if it was entered interactively. The **-q** +option cannot be used in combination with a query in the remaining +arguments. + +.. _dboptions: + +DATABASE OPTIONS +---------------- + +Database options can be used to override database-specific defaults. +Supported options for the DB2 module are: + + **-x dbname=**\ \*filename* + Specifies the base filename of the DB2 database. + + **-x lockiter** + Make iteration operations hold the lock for the duration of + the entire operation, rather than temporarily releasing the + lock while handling each principal. This is the default + behavior, but this option exists to allow command line + override of a [dbmodules] setting. First introduced in + release 1.13. + + **-x unlockiter** + Make iteration operations unlock the database for each + principal, instead of holding the lock for the duration of the + entire operation. First introduced in release 1.13. + +Supported options for the LDAP module are: + + **-x host=**\ *ldapuri* + Specifies the LDAP server to connect to by a LDAP URI. + + **-x binddn=**\ *bind_dn* + Specifies the DN used to bind to the LDAP server. + + **-x bindpwd=**\ *password* + Specifies the password or SASL secret used to bind to the LDAP + server. Using this option may expose the password to other + users on the system via the process list; to avoid this, + instead stash the password using the **stashsrvpw** command of + :ref:`kdb5_ldap_util(8)`. + + **-x sasl_mech=**\ *mechanism* + Specifies the SASL mechanism used to bind to the LDAP server. + The bind DN is ignored if a SASL mechanism is used. New in + release 1.13. + + **-x sasl_authcid=**\ *name* + Specifies the authentication name used when binding to the + LDAP server with a SASL mechanism, if the mechanism requires + one. New in release 1.13. + + **-x sasl_authzid=**\ *name* + Specifies the authorization name used when binding to the LDAP + server with a SASL mechanism. New in release 1.13. + + **-x sasl_realm=**\ *realm* + Specifies the realm used when binding to the LDAP server with + a SASL mechanism, if the mechanism uses one. New in release + 1.13. + + **-x debug=**\ *level* + sets the OpenLDAP client library debug level. *level* is an + integer to be interpreted by the library. Debugging messages + are printed to standard error. New in release 1.12. + + +COMMANDS +-------- + +When using the remote client, available commands may be restricted +according to the privileges specified in the :ref:`kadm5.acl(5)` file +on the admin server. + +.. _add_principal: + +add_principal +~~~~~~~~~~~~~ + + **add_principal** [*options*] *newprinc* + +Creates the principal *newprinc*, prompting twice for a password. If +no password policy is specified with the **-policy** option, and the +policy named ``default`` is assigned to the principal if it exists. +However, creating a policy named ``default`` will not automatically +assign this policy to previously existing principals. This policy +assignment can be suppressed with the **-clearpolicy** option. + +This command requires the **add** privilege. + +Aliases: **addprinc**, **ank** + +Options: + +**-expire** *expdate* + (:ref:`getdate` string) The expiration date of the principal. + +**-pwexpire** *pwexpdate* + (:ref:`getdate` string) The password expiration date. + +**-maxlife** *maxlife* + (:ref:`duration` or :ref:`getdate` string) The maximum ticket life + for the principal. + +**-maxrenewlife** *maxrenewlife* + (:ref:`duration` or :ref:`getdate` string) The maximum renewable + life of tickets for the principal. + +**-kvno** *kvno* + The initial key version number. + +**-policy** *policy* + The password policy used by this principal. If not specified, the + policy ``default`` is used if it exists (unless **-clearpolicy** + is specified). + +**-clearpolicy** + Prevents any policy from being assigned when **-policy** is not + specified. + +{-\|+}\ **allow_postdated** + **-allow_postdated** prohibits this principal from obtaining + postdated tickets. **+allow_postdated** clears this flag. + +{-\|+}\ **allow_forwardable** + **-allow_forwardable** prohibits this principal from obtaining + forwardable tickets. **+allow_forwardable** clears this flag. + +{-\|+}\ **allow_renewable** + **-allow_renewable** prohibits this principal from obtaining + renewable tickets. **+allow_renewable** clears this flag. + +{-\|+}\ **allow_proxiable** + **-allow_proxiable** prohibits this principal from obtaining + proxiable tickets. **+allow_proxiable** clears this flag. + +{-\|+}\ **allow_dup_skey** + **-allow_dup_skey** disables user-to-user authentication for this + principal by prohibiting others from obtaining a service ticket + encrypted in this principal's TGT session key. + **+allow_dup_skey** clears this flag. + +{-\|+}\ **requires_preauth** + **+requires_preauth** requires this principal to preauthenticate + before being allowed to kinit. **-requires_preauth** clears this + flag. When **+requires_preauth** is set on a service principal, + the KDC will only issue service tickets for that service principal + if the client's initial authentication was performed using + preauthentication. + +{-\|+}\ **requires_hwauth** + **+requires_hwauth** requires this principal to preauthenticate + using a hardware device before being allowed to kinit. + **-requires_hwauth** clears this flag. When **+requires_hwauth** is + set on a service principal, the KDC will only issue service tickets + for that service principal if the client's initial authentication was + performed using a hardware device to preauthenticate. + +{-\|+}\ **ok_as_delegate** + **+ok_as_delegate** sets the **okay as delegate** flag on tickets + issued with this principal as the service. Clients may use this + flag as a hint that credentials should be delegated when + authenticating to the service. **-ok_as_delegate** clears this + flag. + +{-\|+}\ **allow_svr** + **-allow_svr** prohibits the issuance of service tickets for this + principal. In release 1.17 and later, user-to-user service + tickets are still allowed unless the **-allow_dup_skey** flag is + also set. **+allow_svr** clears this flag. + +{-\|+}\ **allow_tgs_req** + **-allow_tgs_req** specifies that a Ticket-Granting Service (TGS) + request for a service ticket for this principal is not permitted. + **+allow_tgs_req** clears this flag. + +{-\|+}\ **allow_tix** + **-allow_tix** forbids the issuance of any tickets for this + principal. **+allow_tix** clears this flag. + +{-\|+}\ **needchange** + **+needchange** forces a password change on the next initial + authentication to this principal. **-needchange** clears this + flag. + +{-\|+}\ **password_changing_service** + **+password_changing_service** marks this principal as a password + change service principal. + +{-\|+}\ **ok_to_auth_as_delegate** + **+ok_to_auth_as_delegate** allows this principal to acquire + forwardable tickets to itself from arbitrary users, for use with + constrained delegation. + +{-\|+}\ **no_auth_data_required** + **+no_auth_data_required** prevents PAC or AD-SIGNEDPATH data from + being added to service tickets for the principal. + +{-\|+}\ **lockdown_keys** + **+lockdown_keys** prevents keys for this principal from leaving + the KDC via kadmind. The chpass and extract operations are denied + for a principal with this attribute. The chrand operation is + allowed, but will not return the new keys. The delete and rename + operations are also denied if this attribute is set, in order to + prevent a malicious administrator from replacing principals like + krbtgt/* or kadmin/* with new principals without the attribute. + This attribute can be set via the network protocol, but can only + be removed using kadmin.local. + +**-randkey** + Sets the key of the principal to a random value. + +**-nokey** + Causes the principal to be created with no key. New in release + 1.12. + +**-pw** *password* + Sets the password of the principal to the specified string and + does not prompt for a password. Note: using this option in a + shell script may expose the password to other users on the system + via the process list. + +**-e** *enc*:*salt*,... + Uses the specified keysalt list for setting the keys of the + principal. See :ref:`Keysalt_lists` in :ref:`kdc.conf(5)` for a + list of possible values. + +**-x** *db_princ_args* + Indicates database-specific options. The options for the LDAP + database module are: + + **-x dn=**\ *dn* + Specifies the LDAP object that will contain the Kerberos + principal being created. + + **-x linkdn=**\ *dn* + Specifies the LDAP object to which the newly created Kerberos + principal object will point. + + **-x containerdn=**\ *container_dn* + Specifies the container object under which the Kerberos + principal is to be created. + + **-x tktpolicy=**\ *policy* + Associates a ticket policy to the Kerberos principal. + + .. note:: + + - The **containerdn** and **linkdn** options cannot be + specified with the **dn** option. + - If the *dn* or *containerdn* options are not specified while + adding the principal, the principals are created under the + principal container configured in the realm or the realm + container. + - *dn* and *containerdn* should be within the subtrees or + principal container configured in the realm. + +Example:: + + kadmin: addprinc jennifer + No policy specified for "jennifer@ATHENA.MIT.EDU"; + defaulting to no policy. + Enter password for principal jennifer@ATHENA.MIT.EDU: + Re-enter password for principal jennifer@ATHENA.MIT.EDU: + Principal "jennifer@ATHENA.MIT.EDU" created. + kadmin: + +.. _modify_principal: + +modify_principal +~~~~~~~~~~~~~~~~ + + **modify_principal** [*options*] *principal* + +Modifies the specified principal, changing the fields as specified. +The options to **add_principal** also apply to this command, except +for the **-randkey**, **-pw**, and **-e** options. In addition, the +option **-clearpolicy** will clear the current policy of a principal. + +This command requires the *modify* privilege. + +Alias: **modprinc** + +Options (in addition to the **addprinc** options): + +**-unlock** + Unlocks a locked principal (one which has received too many failed + authentication attempts without enough time between them according + to its password policy) so that it can successfully authenticate. + +.. _rename_principal: + +rename_principal +~~~~~~~~~~~~~~~~ + + **rename_principal** [**-force**] *old_principal* *new_principal* + +Renames the specified *old_principal* to *new_principal*. This +command prompts for confirmation, unless the **-force** option is +given. + +This command requires the **add** and **delete** privileges. + +Alias: **renprinc** + +.. _delete_principal: + +delete_principal +~~~~~~~~~~~~~~~~ + + **delete_principal** [**-force**] *principal* + +Deletes the specified *principal* from the database. This command +prompts for deletion, unless the **-force** option is given. + +This command requires the **delete** privilege. + +Alias: **delprinc** + +.. _change_password: + +change_password +~~~~~~~~~~~~~~~ + + **change_password** [*options*] *principal* + +Changes the password of *principal*. Prompts for a new password if +neither **-randkey** or **-pw** is specified. + +This command requires the **changepw** privilege, or that the +principal running the program is the same as the principal being +changed. + +Alias: **cpw** + +The following options are available: + +**-randkey** + Sets the key of the principal to a random value. + +**-pw** *password* + Set the password to the specified string. Using this option in a + script may expose the password to other users on the system via + the process list. + +**-e** *enc*:*salt*,... + Uses the specified keysalt list for setting the keys of the + principal. See :ref:`Keysalt_lists` in :ref:`kdc.conf(5)` for a + list of possible values. + +**-keepold** + Keeps the existing keys in the database. This flag is usually not + necessary except perhaps for ``krbtgt`` principals. + +Example:: + + kadmin: cpw systest + Enter password for principal systest@BLEEP.COM: + Re-enter password for principal systest@BLEEP.COM: + Password for systest@BLEEP.COM changed. + kadmin: + +.. _purgekeys: + +purgekeys +~~~~~~~~~ + + **purgekeys** [**-all**\|\ **-keepkvno** *oldest_kvno_to_keep*] *principal* + +Purges previously retained old keys (e.g., from **change_password +-keepold**) from *principal*. If **-keepkvno** is specified, then +only purges keys with kvnos lower than *oldest_kvno_to_keep*. If +**-all** is specified, then all keys are purged. The **-all** option +is new in release 1.12. + +This command requires the **modify** privilege. + +.. _get_principal: + +get_principal +~~~~~~~~~~~~~ + + **get_principal** [**-terse**] *principal* + +Gets the attributes of principal. With the **-terse** option, outputs +fields as quoted tab-separated strings. + +This command requires the **inquire** privilege, or that the principal +running the the program to be the same as the one being listed. + +Alias: **getprinc** + +Examples:: + + kadmin: getprinc tlyu/admin + Principal: tlyu/admin@BLEEP.COM + Expiration date: [never] + Last password change: Mon Aug 12 14:16:47 EDT 1996 + Password expiration date: [never] + Maximum ticket life: 0 days 10:00:00 + Maximum renewable life: 7 days 00:00:00 + Last modified: Mon Aug 12 14:16:47 EDT 1996 (bjaspan/admin@BLEEP.COM) + Last successful authentication: [never] + Last failed authentication: [never] + Failed password attempts: 0 + Number of keys: 1 + Key: vno 1, aes256-cts-hmac-sha384-192 + MKey: vno 1 + Attributes: + Policy: [none] + + kadmin: getprinc -terse systest + systest@BLEEP.COM 3 86400 604800 1 + 785926535 753241234 785900000 + tlyu/admin@BLEEP.COM 786100034 0 0 + kadmin: + +.. _list_principals: + +list_principals +~~~~~~~~~~~~~~~ + + **list_principals** [*expression*] + +Retrieves all or some principal names. *expression* is a shell-style +glob expression that can contain the wild-card characters ``?``, +``*``, and ``[]``. All principal names matching the expression are +printed. If no expression is provided, all principal names are +printed. If the expression does not contain an ``@`` character, an +``@`` character followed by the local realm is appended to the +expression. + +This command requires the **list** privilege. + +Alias: **listprincs**, **get_principals**, **getprincs** + +Example:: + + kadmin: listprincs test* + test3@SECURE-TEST.OV.COM + test2@SECURE-TEST.OV.COM + test1@SECURE-TEST.OV.COM + testuser@SECURE-TEST.OV.COM + kadmin: + +.. _get_strings: + +get_strings +~~~~~~~~~~~ + + **get_strings** *principal* + +Displays string attributes on *principal*. + +This command requires the **inquire** privilege. + +Alias: **getstrs** + +.. _set_string: + +set_string +~~~~~~~~~~ + + **set_string** *principal* *name* *value* + +Sets a string attribute on *principal*. String attributes are used to +supply per-principal configuration to the KDC and some KDC plugin +modules. The following string attribute names are recognized by the +KDC: + +**require_auth** + Specifies an authentication indicator which is required to + authenticate to the principal as a service. Multiple indicators + can be specified, separated by spaces; in this case any of the + specified indicators will be accepted. (New in release 1.14.) + +**session_enctypes** + Specifies the encryption types supported for session keys when the + principal is authenticated to as a server. See + :ref:`Encryption_types` in :ref:`kdc.conf(5)` for a list of the + accepted values. + +**otp** + Enables One Time Passwords (OTP) preauthentication for a client + *principal*. The *value* is a JSON string representing an array + of objects, each having optional ``type`` and ``username`` fields. + +**pkinit_cert_match** + Specifies a matching expression that defines the certificate + attributes required for the client certificate used by the + principal during PKINIT authentication. The matching expression + is in the same format as those used by the **pkinit_cert_match** + option in :ref:`krb5.conf(5)`. (New in release 1.16.) + +**pac_privsvr_enctype** + Forces the encryption type of the PAC KDC checksum buffers to the + specified encryption type for tickets issued to this server, by + deriving a key from the local krbtgt key if it is of a different + encryption type. It may be necessary to set this value to + "aes256-sha1" on the cross-realm krbtgt entry for an Active + Directory realm when using aes-sha2 keys on the local krbtgt + entry. + +This command requires the **modify** privilege. + +Alias: **setstr** + +Example:: + + set_string host/foo.mit.edu session_enctypes aes128-cts + set_string user@FOO.COM otp "[{""type"":""hotp"",""username"":""al""}]" + +.. _del_string: + +del_string +~~~~~~~~~~ + + **del_string** *principal* *key* + +Deletes a string attribute from *principal*. + +This command requires the **delete** privilege. + +Alias: **delstr** + +.. _add_policy: + +add_policy +~~~~~~~~~~ + + **add_policy** [*options*] *policy* + +Adds a password policy named *policy* to the database. + +This command requires the **add** privilege. + +Alias: **addpol** + +The following options are available: + +**-maxlife** *time* + (:ref:`duration` or :ref:`getdate` string) Sets the maximum + lifetime of a password. + +**-minlife** *time* + (:ref:`duration` or :ref:`getdate` string) Sets the minimum + lifetime of a password. + +**-minlength** *length* + Sets the minimum length of a password. + +**-minclasses** *number* + Sets the minimum number of character classes required in a + password. The five character classes are lower case, upper case, + numbers, punctuation, and whitespace/unprintable characters. + +**-history** *number* + Sets the number of past keys kept for a principal. This option is + not supported with the LDAP KDC database module. + +.. _policy_maxfailure: + +**-maxfailure** *maxnumber* + Sets the number of authentication failures before the principal is + locked. Authentication failures are only tracked for principals + which require preauthentication. The counter of failed attempts + resets to 0 after a successful attempt to authenticate. A + *maxnumber* value of 0 (the default) disables lockout. + +.. _policy_failurecountinterval: + +**-failurecountinterval** *failuretime* + (:ref:`duration` or :ref:`getdate` string) Sets the allowable time + between authentication failures. If an authentication failure + happens after *failuretime* has elapsed since the previous + failure, the number of authentication failures is reset to 1. A + *failuretime* value of 0 (the default) means forever. + +.. _policy_lockoutduration: + +**-lockoutduration** *lockouttime* + (:ref:`duration` or :ref:`getdate` string) Sets the duration for + which the principal is locked from authenticating if too many + authentication failures occur without the specified failure count + interval elapsing. A duration of 0 (the default) means the + principal remains locked out until it is administratively unlocked + with ``modprinc -unlock``. + +**-allowedkeysalts** + Specifies the key/salt tuples supported for long-term keys when + setting or changing a principal's password/keys. See + :ref:`Keysalt_lists` in :ref:`kdc.conf(5)` for a list of the + accepted values, but note that key/salt tuples must be separated + with commas (',') only. To clear the allowed key/salt policy use + a value of '-'. + +Example:: + + kadmin: add_policy -maxlife "2 days" -minlength 5 guests + kadmin: + +.. _modify_policy: + +modify_policy +~~~~~~~~~~~~~ + + **modify_policy** [*options*] *policy* + +Modifies the password policy named *policy*. Options are as described +for **add_policy**. + +This command requires the **modify** privilege. + +Alias: **modpol** + +.. _delete_policy: + +delete_policy +~~~~~~~~~~~~~ + + **delete_policy** [**-force**] *policy* + +Deletes the password policy named *policy*. Prompts for confirmation +before deletion. The command will fail if the policy is in use by any +principals. + +This command requires the **delete** privilege. + +Alias: **delpol** + +Example:: + + kadmin: del_policy guests + Are you sure you want to delete the policy "guests"? + (yes/no): yes + kadmin: + +.. _get_policy: + +get_policy +~~~~~~~~~~ + + **get_policy** [ **-terse** ] *policy* + +Displays the values of the password policy named *policy*. With the +**-terse** flag, outputs the fields as quoted strings separated by +tabs. + +This command requires the **inquire** privilege. + +Alias: **getpol** + +Examples:: + + kadmin: get_policy admin + Policy: admin + Maximum password life: 180 days 00:00:00 + Minimum password life: 00:00:00 + Minimum password length: 6 + Minimum number of password character classes: 2 + Number of old keys kept: 5 + Reference count: 17 + + kadmin: get_policy -terse admin + admin 15552000 0 6 2 5 17 + kadmin: + +The "Reference count" is the number of principals using that policy. +With the LDAP KDC database module, the reference count field is not +meaningful. + +.. _list_policies: + +list_policies +~~~~~~~~~~~~~ + + **list_policies** [*expression*] + +Retrieves all or some policy names. *expression* is a shell-style +glob expression that can contain the wild-card characters ``?``, +``*``, and ``[]``. All policy names matching the expression are +printed. If no expression is provided, all existing policy names are +printed. + +This command requires the **list** privilege. + +Aliases: **listpols**, **get_policies**, **getpols**. + +Examples:: + + kadmin: listpols + test-pol + dict-only + once-a-min + test-pol-nopw + + kadmin: listpols t* + test-pol + test-pol-nopw + kadmin: + +.. _ktadd: + +ktadd +~~~~~ + + | **ktadd** [options] *principal* + | **ktadd** [options] **-glob** *princ-exp* + +Adds a *principal*, or all principals matching *princ-exp*, to a +keytab file. Each principal's keys are randomized in the process. +The rules for *princ-exp* are described in the **list_principals** +command. + +This command requires the **inquire** and **changepw** privileges. +With the **-glob** form, it also requires the **list** privilege. + +The options are: + +**-k[eytab]** *keytab* + Use *keytab* as the keytab file. Otherwise, the default keytab is + used. + +**-e** *enc*:*salt*,... + Uses the specified keysalt list for setting the new keys of the + principal. See :ref:`Keysalt_lists` in :ref:`kdc.conf(5)` for a + list of possible values. + +**-q** + Display less verbose information. + +**-norandkey** + Do not randomize the keys. The keys and their version numbers stay + unchanged. This option cannot be specified in combination with the + **-e** option. + +An entry for each of the principal's unique encryption types is added, +ignoring multiple keys with the same encryption type but different +salt types. + +Alias: **xst** + +Example:: + + kadmin: ktadd -k /tmp/foo-new-keytab host/foo.mit.edu + Entry for principal host/foo.mit.edu@ATHENA.MIT.EDU with kvno 3, + encryption type aes256-cts-hmac-sha1-96 added to keytab + FILE:/tmp/foo-new-keytab + kadmin: + +.. _ktremove: + +ktremove +~~~~~~~~ + + **ktremove** [options] *principal* [*kvno* | *all* | *old*] + +Removes entries for the specified *principal* from a keytab. Requires +no permissions, since this does not require database access. + +If the string "all" is specified, all entries for that principal are +removed; if the string "old" is specified, all entries for that +principal except those with the highest kvno are removed. Otherwise, +the value specified is parsed as an integer, and all entries whose +kvno match that integer are removed. + +The options are: + +**-k[eytab]** *keytab* + Use *keytab* as the keytab file. Otherwise, the default keytab is + used. + +**-q** + Display less verbose information. + +Alias: **ktrem** + +Example:: + + kadmin: ktremove kadmin/admin all + Entry for principal kadmin/admin with kvno 3 removed from keytab + FILE:/etc/krb5.keytab + kadmin: + +lock +~~~~ + +Lock database exclusively. Use with extreme caution! This command +only works with the DB2 KDC database module. + +unlock +~~~~~~ + +Release the exclusive database lock. + +list_requests +~~~~~~~~~~~~~ + +Lists available for kadmin requests. + +Aliases: **lr**, **?** + +quit +~~~~ + +Exit program. If the database was locked, the lock is released. + +Aliases: **exit**, **q** + + +HISTORY +------- + +The kadmin program was originally written by Tom Yu at MIT, as an +interface to the OpenVision Kerberos administration program. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kpasswd(1)`, :ref:`kadmind(8)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kadmind.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kadmind.rst.txt new file mode 100644 index 00000000..7e148263 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kadmind.rst.txt @@ -0,0 +1,129 @@ +.. _kadmind(8): + +kadmind +======= + +SYNOPSIS +-------- + +**kadmind** +[**-x** *db_args*] +[**-r** *realm*] +[**-m**] +[**-nofork**] +[**-proponly**] +[**-port** *port-number*] +[**-P** *pid_file*] +[**-p** *kdb5_util_path*] +[**-K** *kprop_path*] +[**-k** *kprop_port*] +[**-F** *dump_file*] + +DESCRIPTION +----------- + +kadmind starts the Kerberos administration server. kadmind typically +runs on the primary Kerberos server, which stores the KDC database. +If the KDC database uses the LDAP module, the administration server +and the KDC server need not run on the same machine. kadmind accepts +remote requests from programs such as :ref:`kadmin(1)` and +:ref:`kpasswd(1)` to administer the information in these database. + +kadmind requires a number of configuration files to be set up in order +for it to work: + +:ref:`kdc.conf(5)` + The KDC configuration file contains configuration information for + the KDC and admin servers. kadmind uses settings in this file to + locate the Kerberos database, and is also affected by the + **acl_file**, **dict_file**, **kadmind_port**, and iprop-related + settings. + +:ref:`kadm5.acl(5)` + kadmind's ACL (access control list) tells it which principals are + allowed to perform administration actions. The pathname to the + ACL file can be specified with the **acl_file** :ref:`kdc.conf(5)` + variable; by default, it is |kdcdir|\ ``/kadm5.acl``. + +After the server begins running, it puts itself in the background and +disassociates itself from its controlling terminal. + +kadmind can be configured for incremental database propagation. +Incremental propagation allows replica KDC servers to receive +principal and policy updates incrementally instead of receiving full +dumps of the database. This facility can be enabled in the +:ref:`kdc.conf(5)` file with the **iprop_enable** option. Incremental +propagation requires the principal ``kiprop/PRIMARY\@REALM`` (where +PRIMARY is the primary KDC's canonical host name, and REALM the realm +name). In release 1.13, this principal is automatically created and +registered into the datebase. + + +OPTIONS +------- + +**-r** *realm* + specifies the realm that kadmind will serve; if it is not + specified, the default realm of the host is used. + +**-m** + causes the master database password to be fetched from the + keyboard (before the server puts itself in the background, if not + invoked with the **-nofork** option) rather than from a file on + disk. + +**-nofork** + causes the server to remain in the foreground and remain + associated to the terminal. + +**-proponly** + causes the server to only listen and respond to Kerberos replica + incremental propagation polling requests. This option can be used + to set up a hierarchical propagation topology where a replica KDC + provides incremental updates to other Kerberos replicas. + +**-port** *port-number* + specifies the port on which the administration server listens for + connections. The default port is determined by the + **kadmind_port** configuration variable in :ref:`kdc.conf(5)`. + +**-P** *pid_file* + specifies the file to which the PID of kadmind process should be + written after it starts up. This file can be used to identify + whether kadmind is still running and to allow init scripts to stop + the correct process. + +**-p** *kdb5_util_path* + specifies the path to the kdb5_util command to use when dumping the + KDB in response to full resync requests when iprop is enabled. + +**-K** *kprop_path* + specifies the path to the kprop command to use to send full dumps + to replicas in response to full resync requests. + +**-k** *kprop_port* + specifies the port by which the kprop process that is spawned by + kadmind connects to the replica kpropd, in order to transfer the + dump file during an iprop full resync request. + +**-F** *dump_file* + specifies the file path to be used for dumping the KDB in response + to full resync requests when iprop is enabled. + +**-x** *db_args* + specifies database-specific arguments. See :ref:`Database Options + ` in :ref:`kadmin(1)` for supported arguments. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kpasswd(1)`, :ref:`kadmin(1)`, :ref:`kdb5_util(8)`, +:ref:`kdb5_ldap_util(8)`, :ref:`kadm5.acl(5)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kdb5_ldap_util.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kdb5_ldap_util.rst.txt new file mode 100644 index 00000000..73a920f4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kdb5_ldap_util.rst.txt @@ -0,0 +1,449 @@ +.. _kdb5_ldap_util(8): + +kdb5_ldap_util +=============== + +SYNOPSIS +-------- + +.. _kdb5_ldap_util_synopsis: + +**kdb5_ldap_util** +[**-D** *user_dn* [**-w** *passwd*]] +[**-H** *ldapuri*] +**command** +[*command_options*] + +.. _kdb5_ldap_util_synopsis_end: + + +DESCRIPTION +----------- + +kdb5_ldap_util allows an administrator to manage realms, Kerberos +services and ticket policies. + + +COMMAND-LINE OPTIONS +-------------------- + +.. _kdb5_ldap_util_options: + +**-r** *realm* + Specifies the realm to be operated on. + +**-D** *user_dn* + Specifies the Distinguished Name (DN) of the user who has + sufficient rights to perform the operation on the LDAP server. + +**-w** *passwd* + Specifies the password of *user_dn*. This option is not + recommended. + +**-H** *ldapuri* + Specifies the URI of the LDAP server. + +By default, kdb5_ldap_util operates on the default realm (as specified +in :ref:`krb5.conf(5)`) and connects and authenticates to the LDAP +server in the same manner as :ref:kadmind(8)` would given the +parameters in :ref:`dbdefaults` in :ref:`kdc.conf(5)`. + +.. _kdb5_ldap_util_options_end: + + +COMMANDS +-------- + +create +~~~~~~ + +.. _kdb5_ldap_util_create: + + **create** + [**-subtrees** *subtree_dn_list*] + [**-sscope** *search_scope*] + [**-containerref** *container_reference_dn*] + [**-k** *mkeytype*] + [**-kv** *mkeyVNO*] + [**-M** *mkeyname*] + [**-m|-P** *password*\|\ **-sf** *stashfilename*] + [**-s**] + [**-maxtktlife** *max_ticket_life*] + [**-maxrenewlife** *max_renewable_ticket_life*] + [*ticket_flags*] + +Creates realm in directory. Options: + +**-subtrees** *subtree_dn_list* + Specifies the list of subtrees containing the principals of a + realm. The list contains the DNs of the subtree objects separated + by colon (``:``). + +**-sscope** *search_scope* + Specifies the scope for searching the principals under the + subtree. The possible values are 1 or one (one level), 2 or sub + (subtrees). + +**-containerref** *container_reference_dn* + Specifies the DN of the container object in which the principals + of a realm will be created. If the container reference is not + configured for a realm, the principals will be created in the + realm container. + +**-k** *mkeytype* + Specifies the key type of the master key in the database. The + default is given by the **master_key_type** variable in + :ref:`kdc.conf(5)`. + +**-kv** *mkeyVNO* + Specifies the version number of the master key in the database; + the default is 1. Note that 0 is not allowed. + +**-M** *mkeyname* + Specifies the principal name for the master key in the database. + If not specified, the name is determined by the + **master_key_name** variable in :ref:`kdc.conf(5)`. + +**-m** + Specifies that the master database password should be read from + the TTY rather than fetched from a file on the disk. + +**-P** *password* + Specifies the master database password. This option is not + recommended. + +**-sf** *stashfilename* + Specifies the stash file of the master database password. + +**-s** + Specifies that the stash file is to be created. + +**-maxtktlife** *max_ticket_life* + (:ref:`getdate` string) Specifies maximum ticket life for + principals in this realm. + +**-maxrenewlife** *max_renewable_ticket_life* + (:ref:`getdate` string) Specifies maximum renewable life of + tickets for principals in this realm. + +*ticket_flags* + Specifies global ticket flags for the realm. Allowable flags are + documented in the description of the **add_principal** command in + :ref:`kadmin(1)`. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu + -r ATHENA.MIT.EDU create -subtrees o=org -sscope SUB + Password for "cn=admin,o=org": + Initializing database for realm 'ATHENA.MIT.EDU' + You will be prompted for the database Master Password. + It is important that you NOT FORGET this password. + Enter KDC database master key: + Re-enter KDC database master key to verify: + +.. _kdb5_ldap_util_create_end: + +modify +~~~~~~ + +.. _kdb5_ldap_util_modify: + + **modify** + [**-subtrees** *subtree_dn_list*] + [**-sscope** *search_scope*] + [**-containerref** *container_reference_dn*] + [**-maxtktlife** *max_ticket_life*] + [**-maxrenewlife** *max_renewable_ticket_life*] + [*ticket_flags*] + +Modifies the attributes of a realm. Options: + +**-subtrees** *subtree_dn_list* + Specifies the list of subtrees containing the principals of a + realm. The list contains the DNs of the subtree objects separated + by colon (``:``). This list replaces the existing list. + +**-sscope** *search_scope* + Specifies the scope for searching the principals under the + subtrees. The possible values are 1 or one (one level), 2 or sub + (subtrees). + +**-containerref** *container_reference_dn* Specifies the DN of the + container object in which the principals of a realm will be + created. + +**-maxtktlife** *max_ticket_life* + (:ref:`getdate` string) Specifies maximum ticket life for + principals in this realm. + +**-maxrenewlife** *max_renewable_ticket_life* + (:ref:`getdate` string) Specifies maximum renewable life of + tickets for principals in this realm. + +*ticket_flags* + Specifies global ticket flags for the realm. Allowable flags are + documented in the description of the **add_principal** command in + :ref:`kadmin(1)`. + +Example:: + + shell% kdb5_ldap_util -r ATHENA.MIT.EDU -D cn=admin,o=org -H + ldaps://ldap-server1.mit.edu modify +requires_preauth + Password for "cn=admin,o=org": + shell% + +.. _kdb5_ldap_util_modify_end: + +view +~~~~ + +.. _kdb5_ldap_util_view: + + **view** + +Displays the attributes of a realm. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu + -r ATHENA.MIT.EDU view + Password for "cn=admin,o=org": + Realm Name: ATHENA.MIT.EDU + Subtree: ou=users,o=org + Subtree: ou=servers,o=org + SearchScope: ONE + Maximum ticket life: 0 days 01:00:00 + Maximum renewable life: 0 days 10:00:00 + Ticket flags: DISALLOW_FORWARDABLE REQUIRES_PWCHANGE + +.. _kdb5_ldap_util_view_end: + +destroy +~~~~~~~ + +.. _kdb5_ldap_util_destroy: + + **destroy** [**-f**] + +Destroys an existing realm. Options: + +**-f** + If specified, will not prompt the user for confirmation. + +Example:: + + shell% kdb5_ldap_util -r ATHENA.MIT.EDU -D cn=admin,o=org -H + ldaps://ldap-server1.mit.edu destroy + Password for "cn=admin,o=org": + Deleting KDC database of 'ATHENA.MIT.EDU', are you sure? + (type 'yes' to confirm)? yes + OK, deleting database of 'ATHENA.MIT.EDU'... + shell% + +.. _kdb5_ldap_util_destroy_end: + +list +~~~~ + +.. _kdb5_ldap_util_list: + + **list** + +Lists the names of realms under the container. + +Example:: + + shell% kdb5_ldap_util -D cn=admin,o=org -H + ldaps://ldap-server1.mit.edu list + Password for "cn=admin,o=org": + ATHENA.MIT.EDU + OPENLDAP.MIT.EDU + MEDIA-LAB.MIT.EDU + shell% + +.. _kdb5_ldap_util_list_end: + +stashsrvpw +~~~~~~~~~~ + +.. _kdb5_ldap_util_stashsrvpw: + + **stashsrvpw** + [**-f** *filename*] + *name* + +Allows an administrator to store the password for service object in a +file so that KDC and Administration server can use it to authenticate +to the LDAP server. Options: + +**-f** *filename* + Specifies the complete path of the service password file. By + default, ``/usr/local/var/service_passwd`` is used. + +*name* + Specifies the name of the object whose password is to be stored. + If :ref:`krb5kdc(8)` or :ref:`kadmind(8)` are configured for + simple binding, this should be the distinguished name it will + use as given by the **ldap_kdc_dn** or **ldap_kadmind_dn** + variable in :ref:`kdc.conf(5)`. If the KDC or kadmind is + configured for SASL binding, this should be the authentication + name it will use as given by the **ldap_kdc_sasl_authcid** or + **ldap_kadmind_sasl_authcid** variable. + +Example:: + + kdb5_ldap_util stashsrvpw -f /home/andrew/conf_keyfile + cn=service-kdc,o=org + Password for "cn=service-kdc,o=org": + Re-enter password for "cn=service-kdc,o=org": + +.. _kdb5_ldap_util_stashsrvpw_end: + +create_policy +~~~~~~~~~~~~~ + +.. _kdb5_ldap_util_create_policy: + + **create_policy** + [**-maxtktlife** *max_ticket_life*] + [**-maxrenewlife** *max_renewable_ticket_life*] + [*ticket_flags*] + *policy_name* + +Creates a ticket policy in the directory. Options: + +**-maxtktlife** *max_ticket_life* + (:ref:`getdate` string) Specifies maximum ticket life for + principals. + +**-maxrenewlife** *max_renewable_ticket_life* + (:ref:`getdate` string) Specifies maximum renewable life of + tickets for principals. + +*ticket_flags* + Specifies the ticket flags. If this option is not specified, by + default, no restriction will be set by the policy. Allowable + flags are documented in the description of the **add_principal** + command in :ref:`kadmin(1)`. + +*policy_name* + Specifies the name of the ticket policy. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu + -r ATHENA.MIT.EDU create_policy -maxtktlife "1 day" + -maxrenewlife "1 week" -allow_postdated +needchange + -allow_forwardable tktpolicy + Password for "cn=admin,o=org": + +.. _kdb5_ldap_util_create_policy_end: + +modify_policy +~~~~~~~~~~~~~ + +.. _kdb5_ldap_util_modify_policy: + + **modify_policy** + [**-maxtktlife** *max_ticket_life*] + [**-maxrenewlife** *max_renewable_ticket_life*] + [*ticket_flags*] + *policy_name* + +Modifies the attributes of a ticket policy. Options are same as for +**create_policy**. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H + ldaps://ldap-server1.mit.edu -r ATHENA.MIT.EDU modify_policy + -maxtktlife "60 minutes" -maxrenewlife "10 hours" + +allow_postdated -requires_preauth tktpolicy + Password for "cn=admin,o=org": + +.. _kdb5_ldap_util_modify_policy_end: + +view_policy +~~~~~~~~~~~ + +.. _kdb5_ldap_util_view_policy: + + **view_policy** + *policy_name* + +Displays the attributes of the named ticket policy. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu + -r ATHENA.MIT.EDU view_policy tktpolicy + Password for "cn=admin,o=org": + Ticket policy: tktpolicy + Maximum ticket life: 0 days 01:00:00 + Maximum renewable life: 0 days 10:00:00 + Ticket flags: DISALLOW_FORWARDABLE REQUIRES_PWCHANGE + +.. _kdb5_ldap_util_view_policy_end: + +destroy_policy +~~~~~~~~~~~~~~ + +.. _kdb5_ldap_util_destroy_policy: + + **destroy_policy** + [**-force**] + *policy_name* + +Destroys an existing ticket policy. Options: + +**-force** + Forces the deletion of the policy object. If not specified, the + user will be prompted for confirmation before deleting the policy. + +*policy_name* + Specifies the name of the ticket policy. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu + -r ATHENA.MIT.EDU destroy_policy tktpolicy + Password for "cn=admin,o=org": + This will delete the policy object 'tktpolicy', are you sure? + (type 'yes' to confirm)? yes + ** policy object 'tktpolicy' deleted. + +.. _kdb5_ldap_util_destroy_policy_end: + +list_policy +~~~~~~~~~~~ + +.. _kdb5_ldap_util_list_policy: + + **list_policy** + +Lists ticket policies. + +Example:: + + kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu + -r ATHENA.MIT.EDU list_policy + Password for "cn=admin,o=org": + tktpolicy + tmppolicy + userpolicy + +.. _kdb5_ldap_util_list_policy_end: + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kadmin(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kdb5_util.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kdb5_util.rst.txt new file mode 100644 index 00000000..444c58bc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kdb5_util.rst.txt @@ -0,0 +1,502 @@ +.. _kdb5_util(8): + +kdb5_util +========= + +SYNOPSIS +-------- + +.. _kdb5_util_synopsis: + +**kdb5_util** +[**-r** *realm*] +[**-d** *dbname*] +[**-k** *mkeytype*] +[**-kv** *mkeyVNO*] +[**-M** *mkeyname*] +[**-m**] +[**-sf** *stashfilename*] +[**-P** *password*] +[**-x** *db_args*] +*command* [*command_options*] + +.. _kdb5_util_synopsis_end: + +DESCRIPTION +----------- + +kdb5_util allows an administrator to perform maintenance procedures on +the KDC database. Databases can be created, destroyed, and dumped to +or loaded from ASCII files. kdb5_util can create a Kerberos master +key stash file or perform live rollover of the master key. + +When kdb5_util is run, it attempts to acquire the master key and open +the database. However, execution continues regardless of whether or +not kdb5_util successfully opens the database, because the database +may not exist yet or the stash file may be corrupt. + +Note that some KDC database modules may not support all kdb5_util +commands. + + +COMMAND-LINE OPTIONS +-------------------- + +.. _kdb5_util_options: + +**-r** *realm* + specifies the Kerberos realm of the database. + +**-d** *dbname* + specifies the name under which the principal database is stored; + by default the database is that listed in :ref:`kdc.conf(5)`. The + password policy database and lock files are also derived from this + value. + +**-k** *mkeytype* + specifies the key type of the master key in the database. The + default is given by the **master_key_type** variable in + :ref:`kdc.conf(5)`. + +**-kv** *mkeyVNO* + Specifies the version number of the master key in the database; + the default is 1. Note that 0 is not allowed. + +**-M** *mkeyname* + principal name for the master key in the database. If not + specified, the name is determined by the **master_key_name** + variable in :ref:`kdc.conf(5)`. + +**-m** + specifies that the master database password should be read from + the keyboard rather than fetched from a file on disk. + +**-sf** *stash_file* + specifies the stash filename of the master database password. If + not specified, the filename is determined by the + **key_stash_file** variable in :ref:`kdc.conf(5)`. + +**-P** *password* + specifies the master database password. Using this option may + expose the password to other users on the system via the process + list. + +**-x** *db_args* + specifies database-specific options. See :ref:`kadmin(1)` for + supported options. + +.. _kdb5_util_options_end: + + +COMMANDS +-------- + +create +~~~~~~ + +.. _kdb5_util_create: + + **create** [**-s**] + +Creates a new database. If the **-s** option is specified, the stash +file is also created. This command fails if the database already +exists. If the command is successful, the database is opened just as +if it had already existed when the program was first run. + +.. _kdb5_util_create_end: + +destroy +~~~~~~~ + +.. _kdb5_util_destroy: + + **destroy** [**-f**] + +Destroys the database, first overwriting the disk sectors and then +unlinking the files, after prompting the user for confirmation. With +the **-f** argument, does not prompt the user. + +.. _kdb5_util_destroy_end: + +stash +~~~~~ + +.. _kdb5_util_stash: + + **stash** [**-f** *keyfile*] + +Stores the master principal's keys in a stash file. The **-f** +argument can be used to override the *keyfile* specified in +:ref:`kdc.conf(5)`. + +.. _kdb5_util_stash_end: + +dump +~~~~ + +.. _kdb5_util_dump: + + **dump** [**-b7**\|\ **-r13**\|\ **-r18**] + [**-verbose**] [**-mkey_convert**] [**-new_mkey_file** + *mkey_file*] [**-rev**] [**-recurse**] [*filename* + [*principals*...]] + +Dumps the current Kerberos and KADM5 database into an ASCII file. By +default, the database is dumped in current format, "kdb5_util +load_dump version 7". If filename is not specified, or is the string +"-", the dump is sent to standard output. Options: + +**-b7** + causes the dump to be in the Kerberos 5 Beta 7 format ("kdb5_util + load_dump version 4"). This was the dump format produced on + releases prior to 1.2.2. + +**-r13** + causes the dump to be in the Kerberos 5 1.3 format ("kdb5_util + load_dump version 5"). This was the dump format produced on + releases prior to 1.8. + +**-r18** + causes the dump to be in the Kerberos 5 1.8 format ("kdb5_util + load_dump version 6"). This was the dump format produced on + releases prior to 1.11. + +**-verbose** + causes the name of each principal and policy to be printed as it + is dumped. + +**-mkey_convert** + prompts for a new master key. This new master key will be used to + re-encrypt principal key data in the dumpfile. The principal keys + themselves will not be changed. + +**-new_mkey_file** *mkey_file* + the filename of a stash file. The master key in this stash file + will be used to re-encrypt the key data in the dumpfile. The key + data in the database will not be changed. + +**-rev** + dumps in reverse order. This may recover principals that do not + dump normally, in cases where database corruption has occurred. + +**-recurse** + causes the dump to walk the database recursively (btree only). + This may recover principals that do not dump normally, in cases + where database corruption has occurred. In cases of such + corruption, this option will probably retrieve more principals + than the **-rev** option will. + + .. versionchanged:: 1.15 + Release 1.15 restored the functionality of the **-recurse** + option. + + .. versionchanged:: 1.5 + The **-recurse** option ceased working until release 1.15, + doing a normal dump instead of a recursive traversal. + +.. _kdb5_util_dump_end: + +load +~~~~ + +.. _kdb5_util_load: + + **load** [**-b7**\|\ **-r13**\|\ **-r18**] [**-hash**] + [**-verbose**] [**-update**] *filename* + +Loads a database dump from the named file into the named database. If +no option is given to determine the format of the dump file, the +format is detected automatically and handled as appropriate. Unless +the **-update** option is given, **load** creates a new database +containing only the data in the dump file, overwriting the contents of +any previously existing database. Note that when using the LDAP KDC +database module, the **-update** flag is required. + +Options: + +**-b7** + requires the database to be in the Kerberos 5 Beta 7 format + ("kdb5_util load_dump version 4"). This was the dump format + produced on releases prior to 1.2.2. + +**-r13** + requires the database to be in Kerberos 5 1.3 format ("kdb5_util + load_dump version 5"). This was the dump format produced on + releases prior to 1.8. + +**-r18** + requires the database to be in Kerberos 5 1.8 format ("kdb5_util + load_dump version 6"). This was the dump format produced on + releases prior to 1.11. + +**-hash** + stores the database in hash format, if using the DB2 database + type. If this option is not specified, the database will be + stored in btree format. This option is not recommended, as + databases stored in hash format are known to corrupt data and lose + principals. + +**-verbose** + causes the name of each principal and policy to be printed as it + is dumped. + +**-update** + records from the dump file are added to or updated in the existing + database. Otherwise, a new database is created containing only + what is in the dump file and the old one destroyed upon successful + completion. + +.. _kdb5_util_load_end: + +ark +~~~ + + **ark** [**-e** *enc*:*salt*,...] *principal* + +Adds new random keys to *principal* at the next available key version +number. Keys for the current highest key version number will be +preserved. The **-e** option specifies the list of encryption and +salt types to be used for the new keys. + +add_mkey +~~~~~~~~ + + **add_mkey** [**-e** *etype*] [**-s**] + +Adds a new master key to the master key principal, but does not mark +it as active. Existing master keys will remain. The **-e** option +specifies the encryption type of the new master key; see +:ref:`Encryption_types` in :ref:`kdc.conf(5)` for a list of possible +values. The **-s** option stashes the new master key in the stash +file, which will be created if it doesn't already exist. + +After a new master key is added, it should be propagated to replica +servers via a manual or periodic invocation of :ref:`kprop(8)`. Then, +the stash files on the replica servers should be updated with the +kdb5_util **stash** command. Once those steps are complete, the key +is ready to be marked active with the kdb5_util **use_mkey** command. + +use_mkey +~~~~~~~~ + + **use_mkey** *mkeyVNO* [*time*] + +Sets the activation time of the master key specified by *mkeyVNO*. +Once a master key becomes active, it will be used to encrypt newly +created principal keys. If no *time* argument is given, the current +time is used, causing the specified master key version to become +active immediately. The format for *time* is :ref:`getdate` string. + +After a new master key becomes active, the kdb5_util +**update_princ_encryption** command can be used to update all +principal keys to be encrypted in the new master key. + +list_mkeys +~~~~~~~~~~ + + **list_mkeys** + +List all master keys, from most recent to earliest, in the master key +principal. The output will show the kvno, enctype, and salt type for +each mkey, similar to the output of :ref:`kadmin(1)` **getprinc**. A +``*`` following an mkey denotes the currently active master key. + +purge_mkeys +~~~~~~~~~~~ + + **purge_mkeys** [**-f**] [**-n**] [**-v**] + +Delete master keys from the master key principal that are not used to +protect any principals. This command can be used to remove old master +keys all principal keys are protected by a newer master key. + +**-f** + does not prompt for confirmation. + +**-n** + performs a dry run, showing master keys that would be purged, but + not actually purging any keys. + +**-v** + gives more verbose output. + +update_princ_encryption +~~~~~~~~~~~~~~~~~~~~~~~ + + **update_princ_encryption** [**-f**] [**-n**] [**-v**] + [*princ-pattern*] + +Update all principal records (or only those matching the +*princ-pattern* glob pattern) to re-encrypt the key data using the +active database master key, if they are encrypted using a different +version, and give a count at the end of the number of principals +updated. If the **-f** option is not given, ask for confirmation +before starting to make changes. The **-v** option causes each +principal processed to be listed, with an indication as to whether it +needed updating or not. The **-n** option performs a dry run, only +showing the actions which would have been taken. + +tabdump +~~~~~~~ + + **tabdump** [**-H**] [**-c**] [**-e**] [**-n**] [**-o** *outfile*] + *dumptype* + +Dump selected fields of the database in a tabular format suitable for +reporting (e.g., using traditional Unix text processing tools) or +importing into relational databases. The data format is tab-separated +(default), or optionally comma-separated (CSV), with a fixed number of +columns. The output begins with a header line containing field names, +unless suppression is requested using the **-H** option. + +The *dumptype* parameter specifies the name of an output table (see +below). + +Options: + +**-H** + suppress writing the field names in a header line + +**-c** + use comma separated values (CSV) format, with minimal quoting, + instead of the default tab-separated (unquoted, unescaped) format + +**-e** + write empty hexadecimal string fields as empty fields instead of + as "-1". + +**-n** + produce numeric output for fields that normally have symbolic + output, such as enctypes and flag names. Also requests output of + time stamps as decimal POSIX time_t values. + +**-o** *outfile* + write the dump to the specified output file instead of to standard + output + +Dump types: + +**keydata** + principal encryption key information, including actual key data + (which is still encrypted in the master key) + + **name** + principal name + **keyindex** + index of this key in the principal's key list + **kvno** + key version number + **enctype** + encryption type + **key** + key data as a hexadecimal string + **salttype** + salt type + **salt** + salt data as a hexadecimal string + +**keyinfo** + principal encryption key information (as in **keydata** above), + excluding actual key data + +**princ_flags** + principal boolean attributes. Flag names print as hexadecimal + numbers if the **-n** option is specified, and all flag positions + are printed regardless of whether or not they are set. If **-n** + is not specified, print all known flag names for each principal, + but only print hexadecimal flag names if the corresponding flag is + set. + + **name** + principal name + **flag** + flag name + **value** + boolean value (0 for clear, or 1 for set) + +**princ_lockout** + state information used for tracking repeated password failures + + **name** + principal name + **last_success** + time stamp of most recent successful authentication + **last_failed** + time stamp of most recent failed authentication + **fail_count** + count of failed attempts + +**princ_meta** + principal metadata + + **name** + principal name + **modby** + name of last principal to modify this principal + **modtime** + timestamp of last modification + **lastpwd** + timestamp of last password change + **policy** + policy object name + **mkvno** + key version number of the master key that encrypts this + principal's key data + **hist_kvno** + key version number of the history key that encrypts the key + history data for this principal + +**princ_stringattrs** + string attributes (key/value pairs) + + **name** + principal name + **key** + attribute name + **value** + attribute value + +**princ_tktpolicy** + per-principal ticket policy data, including maximum ticket + lifetimes + + **name** + principal name + **expiration** + principal expiration date + **pw_expiration** + password expiration date + **max_life** + maximum ticket lifetime + **max_renew_life** + maximum renewable ticket lifetime + +Examples:: + + $ kdb5_util tabdump -o keyinfo.txt keyinfo + $ cat keyinfo.txt + name keyindex kvno enctype salttype salt + K/M@EXAMPLE.COM 0 1 aes256-cts-hmac-sha384-192 normal -1 + foo@EXAMPLE.COM 0 1 aes128-cts-hmac-sha1-96 normal -1 + bar@EXAMPLE.COM 0 1 aes128-cts-hmac-sha1-96 normal -1 + $ sqlite3 + sqlite> .mode tabs + sqlite> .import keyinfo.txt keyinfo + sqlite> select * from keyinfo where enctype like 'aes256-%'; + K/M@EXAMPLE.COM 1 1 aes256-cts-hmac-sha384-192 normal -1 + sqlite> .quit + $ awk -F'\t' '$4 ~ /aes256-/ { print }' keyinfo.txt + K/M@EXAMPLE.COM 1 1 aes256-cts-hmac-sha384-192 normal -1 + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kadmin(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kprop.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kprop.rst.txt new file mode 100644 index 00000000..a118b262 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kprop.rst.txt @@ -0,0 +1,60 @@ +.. _kprop(8): + +kprop +===== + +SYNOPSIS +-------- + +**kprop** +[**-r** *realm*] +[**-f** *file*] +[**-d**] +[**-P** *port*] +[**-s** *keytab*] +*replica_host* + + +DESCRIPTION +----------- + +kprop is used to securely propagate a Kerberos V5 database dump file +from the primary Kerberos server to a replica Kerberos server, which is +specified by *replica_host*. The dump file must be created by +:ref:`kdb5_util(8)`. + + +OPTIONS +------- + +**-r** *realm* + Specifies the realm of the primary server. + +**-f** *file* + Specifies the filename where the dumped principal database file is + to be found; by default the dumped database file is normally + |kdcdir|\ ``/replica_datatrans``. + +**-P** *port* + Specifies the port to use to contact the :ref:`kpropd(8)` server + on the remote host. + +**-d** + Prints debugging information. + +**-s** *keytab* + Specifies the location of the keytab file. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kpropd(8)`, :ref:`kdb5_util(8)`, :ref:`krb5kdc(8)`, +:ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kpropd.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kpropd.rst.txt new file mode 100644 index 00000000..30c66c7e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kpropd.rst.txt @@ -0,0 +1,144 @@ +.. _kpropd(8): + +kpropd +====== + +SYNOPSIS +-------- + +**kpropd** +[**-r** *realm*] +[**-A** *admin_server*] +[**-a** *acl_file*] +[**-f** *replica_dumpfile*] +[**-F** *principal_database*] +[**-p** *kdb5_util_prog*] +[**-P** *port*] +[**--pid-file**\ =\ *pid_file*] +[**-D**] +[**-d**] +[**-s** *keytab_file*] + +DESCRIPTION +----------- + +The *kpropd* command runs on the replica KDC server. It listens for +update requests made by the :ref:`kprop(8)` program. If incremental +propagation is enabled, it periodically requests incremental updates +from the primary KDC. + +When the replica receives a kprop request from the primary, kpropd +accepts the dumped KDC database and places it in a file, and then runs +:ref:`kdb5_util(8)` to load the dumped database into the active +database which is used by :ref:`krb5kdc(8)`. This allows the primary +Kerberos server to use :ref:`kprop(8)` to propagate its database to +the replica servers. Upon a successful download of the KDC database +file, the replica Kerberos server will have an up-to-date KDC +database. + +Where incremental propagation is not used, kpropd is commonly invoked +out of inetd(8) as a nowait service. This is done by adding a line to +the ``/etc/inetd.conf`` file which looks like this:: + + kprop stream tcp nowait root /usr/local/sbin/kpropd kpropd + +kpropd can also run as a standalone daemon, backgrounding itself and +waiting for connections on port 754 (or the port specified with the +**-P** option if given). Standalone mode is required for incremental +propagation. Starting in release 1.11, kpropd automatically detects +whether it was run from inetd and runs in standalone mode if it is +not. Prior to release 1.11, the **-S** option is required to run +kpropd in standalone mode; this option is now accepted for backward +compatibility but does nothing. + +Incremental propagation may be enabled with the **iprop_enable** +variable in :ref:`kdc.conf(5)`. If incremental propagation is +enabled, the replica periodically polls the primary KDC for updates, at +an interval determined by the **iprop_replica_poll** variable. If the +replica receives updates, kpropd updates its log file with any updates +from the primary. :ref:`kproplog(8)` can be used to view a summary of +the update entry log on the replica KDC. If incremental propagation +is enabled, the principal ``kiprop/replicahostname@REALM`` (where +*replicahostname* is the name of the replica KDC host, and *REALM* is +the name of the Kerberos realm) must be present in the replica's +keytab file. + +:ref:`kproplog(8)` can be used to force full replication when iprop is +enabled. + + +OPTIONS +-------- + +**-r** *realm* + Specifies the realm of the primary server. + +**-A** *admin_server* + Specifies the server to be contacted for incremental updates; by + default, the primary admin server is contacted. + +**-f** *file* + Specifies the filename where the dumped principal database file is + to be stored; by default the dumped database file is |kdcdir|\ + ``/from_master``. + +**-F** *kerberos_db* + Path to the Kerberos database file, if not the default. + +**-p** + Allows the user to specify the pathname to the :ref:`kdb5_util(8)` + program; by default the pathname used is |sbindir|\ + ``/kdb5_util``. + +**-D** + In this mode, kpropd will not detach itself from the current job + and run in the background. Instead, it will run in the + foreground. + +**-d** + Turn on debug mode. kpropd will print out debugging messages + during the database propogation and will run in the foreground + (implies **-D**). + +**-P** + Allow for an alternate port number for kpropd to listen on. This + is only useful in combination with the **-S** option. + +**-a** *acl_file* + Allows the user to specify the path to the kpropd.acl file; by + default the path used is |kdcdir|\ ``/kpropd.acl``. + +**--pid-file**\ =\ *pid_file* + In standalone mode, write the process ID of the daemon into + *pid_file*. + +**-s** *keytab_file* + Path to a keytab to use for acquiring acceptor credentials. + +**-x** *db_args* + Database-specific arguments. See :ref:`Database Options + ` in :ref:`kadmin(1)` for supported arguments. + + +FILES +----- + +kpropd.acl + Access file for kpropd; the default location is + ``/usr/local/var/krb5kdc/kpropd.acl``. Each entry is a line + containing the principal of a host from which the local machine + will allow Kerberos database propagation via :ref:`kprop(8)`. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kprop(8)`, :ref:`kdb5_util(8)`, :ref:`krb5kdc(8)`, +:ref:`kerberos(7)`, inetd(8) diff --git a/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kproplog.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kproplog.rst.txt new file mode 100644 index 00000000..3b72cfa0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/kproplog.rst.txt @@ -0,0 +1,85 @@ +.. _kproplog(8): + +kproplog +======== + +SYNOPSIS +-------- + +**kproplog** [**-h**] [**-e** *num*] [-v] +**kproplog** [-R] + + +DESCRIPTION +----------- + +The kproplog command displays the contents of the KDC database update +log to standard output. It can be used to keep track of incremental +updates to the principal database. The update log file contains the +update log maintained by the :ref:`kadmind(8)` process on the primary +KDC server and the :ref:`kpropd(8)` process on the replica KDC +servers. When updates occur, they are logged to this file. +Subsequently any KDC replica configured for incremental updates will +request the current data from the primary KDC and update their log +file with any updates returned. + +The kproplog command requires read access to the update log file. It +will display update entries only for the KDC it runs on. + +If no options are specified, kproplog displays a summary of the update +log. If invoked on the primary, kproplog also displays all of the +update entries. If invoked on a replica KDC server, kproplog displays +only a summary of the updates, which includes the serial number of the +last update received and the associated time stamp of the last update. + + +OPTIONS +------- + +**-R** + Reset the update log. This forces full resynchronization. If + used on a replica then that replica will request a full resync. + If used on the primary then all replicas will request full + resyncs. + +**-h** + Display a summary of the update log. This information includes + the database version number, state of the database, the number of + updates in the log, the time stamp of the first and last update, + and the version number of the first and last update entry. + +**-e** *num* + Display the last *num* update entries in the log. This is useful + when debugging synchronization between KDC servers. + +**-v** + Display individual attributes per update. An example of the + output generated for one entry:: + + Update Entry + Update serial # : 4 + Update operation : Add + Update principal : test@EXAMPLE.COM + Update size : 424 + Update committed : True + Update time stamp : Fri Feb 20 23:37:42 2004 + Attributes changed : 6 + Principal + Key data + Password last changed + Modifying principal + Modification time + TL data + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kpropd(8)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/admin/admin_commands/krb5kdc.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/krb5kdc.rst.txt new file mode 100644 index 00000000..631a0de8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/krb5kdc.rst.txt @@ -0,0 +1,114 @@ +.. _krb5kdc(8): + +krb5kdc +======= + +SYNOPSIS +-------- + +**krb5kdc** +[**-x** *db_args*] +[**-d** *dbname*] +[**-k** *keytype*] +[**-M** *mkeyname*] +[**-p** *portnum*] +[**-m**] +[**-r** *realm*] +[**-n**] +[**-w** *numworkers*] +[**-P** *pid_file*] +[**-T** *time_offset*] + + +DESCRIPTION +----------- + +krb5kdc is the Kerberos version 5 Authentication Service and Key +Distribution Center (AS/KDC). + + +OPTIONS +------- + +The **-r** *realm* option specifies the realm for which the server +should provide service. This option may be specified multiple times +to serve multiple realms. If no **-r** option is given, the default +realm (as specified in :ref:`krb5.conf(5)`) will be served. + +The **-d** *dbname* option specifies the name under which the +principal database can be found. This option does not apply to the +LDAP database. + +The **-k** *keytype* option specifies the key type of the master key +to be entered manually as a password when **-m** is given; the default +is |defmkey|. + +The **-M** *mkeyname* option specifies the principal name for the +master key in the database (usually ``K/M`` in the KDC's realm). + +The **-m** option specifies that the master database password should +be fetched from the keyboard rather than from a stash file. + +The **-n** option specifies that the KDC does not put itself in the +background and does not disassociate itself from the terminal. + +The **-P** *pid_file* option tells the KDC to write its PID into +*pid_file* after it starts up. This can be used to identify whether +the KDC is still running and to allow init scripts to stop the correct +process. + +The **-p** *portnum* option specifies the default UDP and TCP port +numbers which the KDC should listen on for Kerberos version 5 +requests, as a comma-separated list. This value overrides the port +numbers specified in the :ref:`kdcdefaults` section of +:ref:`kdc.conf(5)`, but may be overridden by realm-specific values. +If no value is given from any source, the default port is 88. + +The **-w** *numworkers* option tells the KDC to fork *numworkers* +processes to listen to the KDC ports and process requests in parallel. +The top level KDC process (whose pid is recorded in the pid file if +the **-P** option is also given) acts as a supervisor. The supervisor +will relay SIGHUP signals to the worker subprocesses, and will +terminate the worker subprocess if the it is itself terminated or if +any other worker process exits. + +The **-x** *db_args* option specifies database-specific arguments. +See :ref:`Database Options ` in :ref:`kadmin(1)` for +supported arguments. + +The **-T** *offset* option specifies a time offset, in seconds, which +the KDC will operate under. It is intended only for testing purposes. + +EXAMPLE +------- + +The KDC may service requests for multiple realms (maximum 32 realms). +The realms are listed on the command line. Per-realm options that can +be specified on the command line pertain for each realm that follows +it and are superseded by subsequent definitions of the same option. + +For example:: + + krb5kdc -p 2001 -r REALM1 -p 2002 -r REALM2 -r REALM3 + +specifies that the KDC listen on port 2001 for REALM1 and on port 2002 +for REALM2 and REALM3. Additionally, per-realm parameters may be +specified in the :ref:`kdc.conf(5)` file. The location of this file +may be specified by the **KRB5_KDC_PROFILE** environment variable. +Per-realm parameters specified in this file take precedence over +options specified on the command line. See the :ref:`kdc.conf(5)` +description for further details. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kdb5_util(8)`, :ref:`kdc.conf(5)`, :ref:`krb5.conf(5)`, +:ref:`kdb5_ldap_util(8)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/admin/admin_commands/ktutil.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/ktutil.rst.txt new file mode 100644 index 00000000..fd83f0ad --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/ktutil.rst.txt @@ -0,0 +1,129 @@ +.. _ktutil(1): + +ktutil +====== + +SYNOPSIS +-------- + +**ktutil** + + +DESCRIPTION +----------- + +The ktutil command invokes a command interface from which an +administrator can read, write, or edit entries in a keytab. (Kerberos +V4 srvtab files are no longer supported.) + + +COMMANDS +-------- + +list +~~~~ + + **list** [**-t**] [**-k**] [**-e**] + +Displays the current keylist. If **-t**, **-k**, and/or **-e** are +specified, also display the timestamp, key contents, or enctype +(respectively). + +Alias: **l** + +read_kt +~~~~~~~ + + **read_kt** *keytab* + +Read the Kerberos V5 keytab file *keytab* into the current keylist. + +Alias: **rkt** + +write_kt +~~~~~~~~ + + **write_kt** *keytab* + +Write the current keylist into the Kerberos V5 keytab file *keytab*. + +Alias: **wkt** + +clear_list +~~~~~~~~~~ + + **clear_list** + +Clear the current keylist. + +Alias: **clear** + +delete_entry +~~~~~~~~~~~~ + + **delete_entry** *slot* + +Delete the entry in slot number *slot* from the current keylist. + +Alias: **delent** + +add_entry +~~~~~~~~~ + + **add_entry** {**-key**\|\ **-password**} **-p** *principal* + **-k** *kvno* [**-e** *enctype*] [**-f**\|\ **-s** *salt*] + +Add *principal* to keylist using key or password. If the **-f** flag +is specified, salt information will be fetched from the KDC; in this +case the **-e** flag may be omitted, or it may be supplied to force a +particular enctype. If the **-f** flag is not specified, the **-e** +flag must be specified, and the default salt will be used unless +overridden with the **-s** option. + +Alias: **addent** + +list_requests +~~~~~~~~~~~~~ + + **list_requests** + +Displays a listing of available commands. + +Aliases: **lr**, **?** + +quit +~~~~ + + **quit** + +Quits ktutil. + +Aliases: **exit**, **q** + + +EXAMPLE +------- + + :: + + ktutil: add_entry -password -p alice@BLEEP.COM -k 1 -e + aes128-cts-hmac-sha1-96 + Password for alice@BLEEP.COM: + ktutil: add_entry -password -p alice@BLEEP.COM -k 1 -e + aes256-cts-hmac-sha1-96 + Password for alice@BLEEP.COM: + ktutil: write_kt alice.keytab + ktutil: + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kadmin(1)`, :ref:`kdb5_util(8)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/admin/admin_commands/sserver.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/sserver.rst.txt new file mode 100644 index 00000000..a8dcf5d5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/admin_commands/sserver.rst.txt @@ -0,0 +1,112 @@ +.. _sserver(8): + +sserver +======= + +SYNOPSIS +-------- + +**sserver** +[ **-p** *port* ] +[ **-S** *keytab* ] +[ *server_port* ] + + +DESCRIPTION +----------- + +sserver and :ref:`sclient(1)` are a simple demonstration client/server +application. When sclient connects to sserver, it performs a Kerberos +authentication, and then sserver returns to sclient the Kerberos +principal which was used for the Kerberos authentication. It makes a +good test that Kerberos has been successfully installed on a machine. + +The service name used by sserver and sclient is sample. Hence, +sserver will require that there be a keytab entry for the service +``sample/hostname.domain.name@REALM.NAME``. This keytab is generated +using the :ref:`kadmin(1)` program. The keytab file is usually +installed as |keytab|. + +The **-S** option allows for a different keytab than the default. + +sserver is normally invoked out of inetd(8), using a line in +``/etc/inetd.conf`` that looks like this:: + + sample stream tcp nowait root /usr/local/sbin/sserver sserver + +Since ``sample`` is normally not a port defined in ``/etc/services``, +you will usually have to add a line to ``/etc/services`` which looks +like this:: + + sample 13135/tcp + +When using sclient, you will first have to have an entry in the +Kerberos database, by using :ref:`kadmin(1)`, and then you have to get +Kerberos tickets, by using :ref:`kinit(1)`. Also, if you are running +the sclient program on a different host than the sserver it will be +connecting to, be sure that both hosts have an entry in /etc/services +for the sample tcp port, and that the same port number is in both +files. + +When you run sclient you should see something like this:: + + sendauth succeeded, reply is: + reply len 32, contents: + You are nlgilman@JIMI.MIT.EDU + + +COMMON ERROR MESSAGES +--------------------- + +1) kinit returns the error:: + + kinit: Client not found in Kerberos database while getting + initial credentials + + This means that you didn't create an entry for your username in the + Kerberos database. + +2) sclient returns the error:: + + unknown service sample/tcp; check /etc/services + + This means that you don't have an entry in /etc/services for the + sample tcp port. + +3) sclient returns the error:: + + connect: Connection refused + + This probably means you didn't edit /etc/inetd.conf correctly, or + you didn't restart inetd after editing inetd.conf. + +4) sclient returns the error:: + + sclient: Server not found in Kerberos database while using + sendauth + + This means that the ``sample/hostname@LOCAL.REALM`` service was not + defined in the Kerberos database; it should be created using + :ref:`kadmin(1)`, and a keytab file needs to be generated to make + the key for that service principal available for sclient. + +5) sclient returns the error:: + + sendauth rejected, error reply is: + "No such file or directory" + + This probably means sserver couldn't find the keytab file. It was + probably not installed in the proper directory. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`sclient(1)`, :ref:`kerberos(7)`, services(5), inetd(8) diff --git a/krb5-1.21.3/doc/html/_sources/admin/advanced/index.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/advanced/index.rst.txt new file mode 100644 index 00000000..834f453c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/advanced/index.rst.txt @@ -0,0 +1,8 @@ +Advanced topics +=============== + + +.. toctree:: + :maxdepth: 1 + + retiring-des.rst diff --git a/krb5-1.21.3/doc/html/_sources/admin/advanced/retiring-des.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/advanced/retiring-des.rst.txt new file mode 100644 index 00000000..38f76d3f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/advanced/retiring-des.rst.txt @@ -0,0 +1,422 @@ +.. _retiring-des: + +Retiring DES +======================= + +Version 5 of the Kerberos protocol was originally implemented using +the Data Encryption Standard (DES) as a block cipher for encryption. +While it was considered secure at the time, advancements in computational +ability have rendered DES vulnerable to brute force attacks on its 56-bit +keyspace. As such, it is now considered insecure and should not be +used (:rfc:`6649`). + +History +------- + +DES was used in the original Kerberos implementation, and was the +only cryptosystem in krb5 1.0. Partial support for triple-DES (3DES) was +added in version 1.1, with full support following in version 1.2. +The Advanced Encryption Standard (AES), which supersedes DES, gained +partial support in version 1.3.0 of krb5 and full support in version 1.3.2. +However, deployments of krb5 using Kerberos databases created with older +versions of krb5 will not necessarily start using strong crypto for +ordinary operation without administrator intervention. + +MIT krb5 began flagging deprecated encryption types with release 1.17, +and removed DES (single-DES) support in release 1.18. As a +consequence, a release prior to 1.18 is required to perform these +migrations. + +Types of keys +------------- + +* The database master key: This key is not exposed to user requests, + but is used to encrypt other key material stored in the kerberos + database. The database master key is currently stored as ``K/M`` + by default. +* Password-derived keys: User principals frequently have keys + derived from a password. When a new password is set, the KDC + uses various string2key functions to generate keys in the database + for that principal. +* Keytab keys: Application server principals generally use random + keys which are not derived from a password. When the database + entry is created, the KDC generates random keys of various enctypes + to enter in the database, which are conveyed to the application server + and stored in a keytab. +* Session keys: These are short-term keys generated by the KDC while + processing client requests, with an enctype selected by the KDC. + +For details on the various enctypes and how enctypes are selected by the KDC +for session keys and client/server long-term keys, see :ref:`enctypes`. +When using the :ref:`kadmin(1)` interface to generate new long-term keys, +the **-e** argument can be used to force a particular set of enctypes, +overriding the KDC default values. + +.. note:: + + When the KDC is selecting a session key, it has no knowledge about the + kerberos installation on the server which will receive the service ticket, + only what keys are in the database for the service principal. + In order to allow uninterrupted operation to + clients while migrating away from DES, care must be taken to ensure that + kerberos installations on application server machines are configured to + support newer encryption types before keys of those new encryption types + are created in the Kerberos database for those server principals. + +Upgrade procedure +----------------- + +This procedure assumes that the KDC software has already been upgraded +to a modern version of krb5 that supports non-DES keys, so that the +only remaining task is to update the actual keys used to service requests. +The realm used for demonstrating this procedure, ZONE.MIT.EDU, +is an example of the worst-case scenario, where all keys in the realm +are DES. The realm was initially created with a very old version of krb5, +and **supported_enctypes** in :ref:`kdc.conf(5)` was set to a value +appropriate when the KDC was installed, but was not updated as the KDC +was upgraded: + +:: + + [realms] + ZONE.MIT.EDU = { + [...] + master_key_type = des-cbc-crc + supported_enctypes = des-cbc-crc:normal des:normal des:v4 des:norealm des:onlyrealm des:afs3 + } + +This resulted in the keys for all principals in the realm being forced +to DES-only, unless specifically requested using :ref:`kadmin(1)`. + +Before starting the upgrade, all KDCs were running krb5 1.11, +and the database entries for some "high-value" principals were: + +:: + + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'getprinc krbtgt/ZONE.MIT.EDU' + [...] + Number of keys: 1 + Key: vno 1, des-cbc-crc:v4 + [...] + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'getprinc kadmin/admin' + [...] + Number of keys: 1 + Key: vno 15, des-cbc-crc + [...] + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'getprinc kadmin/changepw' + [...] + Number of keys: 1 + Key: vno 14, des-cbc-crc + [...] + +The ``krbtgt/REALM`` key appears to have never been changed since creation +(its kvno is 1), and all three database entries have only a des-cbc-crc key. + +The krbtgt key and KDC keys +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Perhaps the biggest single-step improvement in the security of the cell +is gained by strengthening the key of the ticket-granting service principal, +``krbtgt/REALM``---if this principal's key is compromised, so is the +entire realm. Since the server that will handle service tickets +for this principal is the KDC itself, it is easy to guarantee that it +will be configured to support any encryption types which might be +selected. However, the default KDC behavior when creating new keys is to +remove the old keys, which would invalidate all existing tickets issued +against that principal, rendering the TGTs cached by clients useless. +Instead, a new key can be created with the old key retained, so that +existing tickets will still function until their scheduled expiry +(see :ref:`changing_krbtgt_key`). + +:: + + [root@casio krb5kdc]# enctypes=aes256-cts-hmac-sha1-96:normal,\ + > aes128-cts-hmac-sha1-96:normal,des3-hmac-sha1:normal,des-cbc-crc:normal + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q "cpw -e ${enctypes} -randkey \ + > -keepold krbtgt/ZONE.MIT.EDU" + Authenticating as principal root/admin@ZONE.MIT.EDU with password. + Key for "krbtgt/ZONE.MIT.EDU@ZONE.MIT.EDU" randomized. + +.. note:: + + The new ``krbtgt@REALM`` key should be propagated to replica KDCs + immediately so that TGTs issued by the primary KDC can be used to + issue service tickets on replica KDCs. Replica KDCs will refuse + requests using the new TGT kvno until the new krbtgt entry has + been propagated to them. + +It is necessary to explicitly specify the enctypes for the new database +entry, since **supported_enctypes** has not been changed. Leaving +**supported_enctypes** unchanged makes a potential rollback operation +easier, since all new keys of new enctypes are the result of explicit +administrator action and can be easily enumerated. +Upgrading the krbtgt key should have minimal user-visible disruption other +than that described in the note above, since only clients which list the +new enctypes as supported will use them, per the procedure +in :ref:`session_key_selection`. +Once the krbtgt key is updated, the session and ticket keys for user +TGTs will be strong keys, but subsequent requests +for service tickets will still get DES keys until the service principals +have new keys generated. Application service +remains uninterrupted due to the key-selection procedure on the KDC. + +After the change, the database entry is now: + +:: + + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'getprinc krbtgt/ZONE.MIT.EDU' + [...] + Number of keys: 5 + Key: vno 2, aes256-cts-hmac-sha1-96 + Key: vno 2, aes128-cts-hmac-sha1-96 + Key: vno 2, des3-cbc-sha1 + Key: vno 2, des-cbc-crc + Key: vno 1, des-cbc-crc:v4 + [...] + +Since the expected disruptions from rekeying the krbtgt principal are +minor, after a short testing period, it is +appropriate to rekey the other high-value principals, ``kadmin/admin@REALM`` +and ``kadmin/changepw@REALM``. These are the service principals used for +changing user passwords and updating application keytabs. The kadmin +and password-changing services are regular kerberized services, so the +session-key-selection algorithm described in :ref:`session_key_selection` +applies. It is particularly important to have strong session keys for +these services, since user passwords and new long-term keys are conveyed +over the encrypted channel. + +:: + + [root@casio krb5kdc]# enctypes=aes256-cts-hmac-sha1-96:normal,\ + > aes128-cts-hmac-sha1-96:normal,des3-hmac-sha1:normal + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q "cpw -e ${enctypes} -randkey \ + > kadmin/admin" + Authenticating as principal root/admin@ZONE.MIT.EDU with password. + Key for "kadmin/admin@ZONE.MIT.EDU" randomized. + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q "cpw -e ${enctypes} -randkey \ + > kadmin/changepw" + Authenticating as principal root/admin@ZONE.MIT.EDU with password. + Key for "kadmin/changepw@ZONE.MIT.EDU" randomized. + +It is not necessary to retain a single-DES key for these services, since +password changes are not part of normal daily workflow, and disruption +from a client failure is likely to be minimal. Furthermore, if a kerberos +client experiences failure changing a user password or keytab key, +this indicates that that client will become inoperative once services +are rekeyed to non-DES enctypes. Such problems can be detected early +at this stage, giving more time for corrective action. + +Adding strong keys to application servers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Before switching the default enctypes for new keys over to strong enctypes, +it may be desired to test upgrading a handful of services with the +new configuration before flipping the switch for the defaults. This +still requires using the **-e** argument in :ref:`kadmin(1)` to get non-default +enctypes: + +:: + + [root@casio krb5kdc]# enctypes=aes256-cts-hmac-sha1-96:normal,\ + > aes128-cts-hmac-sha1-96:normal,des3-cbc-sha1:normal,des-cbc-crc:normal + [root@casio krb5kdc]# kadmin -r ZONE.MIT.EDU -p zephyr/zephyr@ZONE.MIT.EDU -k -t \ + > /etc/zephyr/krb5.keytab -q "ktadd -e ${enctypes} \ + > -k /etc/zephyr/krb5.keytab zephyr/zephyr@ZONE.MIT.EDU" + Authenticating as principal zephyr/zephyr@ZONE.MIT.EDU with keytab /etc/zephyr/krb5.keytab. + Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 4, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/zephyr/krb5.keytab. + Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 4, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/zephyr/krb5.keytab. + Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 4, encryption type des3-cbc-sha1 added to keytab WRFILE:/etc/zephyr/krb5.keytab. + Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 4, encryption type des-cbc-crc added to keytab WRFILE:/etc/zephyr/krb5.keytab. + +Be sure to remove the old keys from the application keytab, per best +practice. + +:: + + [root@casio krb5kdc]# k5srvutil -f /etc/zephyr/krb5.keytab delold + Authenticating as principal zephyr/zephyr@ZONE.MIT.EDU with keytab /etc/zephyr/krb5.keytab. + Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 3 removed from keytab WRFILE:/etc/zephyr/krb5.keytab. + +Adding strong keys by default +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once the high-visibility services have been rekeyed, it is probably +appropriate to change :ref:`kdc.conf(5)` to generate keys with the new +encryption types by default. This enables server administrators to generate +new enctypes with the **change** subcommand of :ref:`k5srvutil(1)`, +and causes user password +changes to add new encryption types for their entries. It will probably +be necessary to implement administrative controls to cause all user +principal keys to be updated in a reasonable period of time, whether +by forcing password changes or a password synchronization service that +has access to the current password and can add the new keys. + +:: + + [realms] + ZONE.MIT.EDU = { + supported_enctypes = aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des3-hmac-sha1:normal des-cbc-crc:normal + +.. note:: + + The krb5kdc process must be restarted for these changes to take effect. + +At this point, all service administrators can update their services and the +servers behind them to take advantage of strong cryptography. +If necessary, the server's krb5 installation should be configured and/or +upgraded to a version supporting non-DES keys. See :ref:`enctypes` for +krb5 version and configuration settings. +Only when the service is configured to accept non-DES keys should +the key version number be incremented and new keys generated +(``k5srvutil change && k5srvutil delold``). + +:: + + root@dr-willy:~# k5srvutil change + Authenticating as principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with keytab /etc/krb5.keytab. + Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 3, encryption type AES-256 CTS mode with 96-bit SHA-1 HMAC added to keytab WRFILE:/etc/krb5.keytab. + Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 3, encryption type AES-128 CTS mode with 96-bit SHA-1 HMAC added to keytab WRFILE:/etc/krb5.keytab. + Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 3, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/etc/krb5.keytab. + Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 3, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/etc/krb5.keytab. + root@dr-willy:~# klist -e -k -t /etc/krb5.keytab + Keytab name: WRFILE:/etc/krb5.keytab + KVNO Timestamp Principal + ---- ----------------- -------------------------------------------------------- + 2 10/10/12 17:03:59 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (DES cbc mode with CRC-32) + 3 12/12/12 15:31:19 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (AES-256 CTS mode with 96-bit SHA-1 HMAC) + 3 12/12/12 15:31:19 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (AES-128 CTS mode with 96-bit SHA-1 HMAC) + 3 12/12/12 15:31:19 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (Triple DES cbc mode with HMAC/sha1) + 3 12/12/12 15:31:19 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (DES cbc mode with CRC-32) + root@dr-willy:~# k5srvutil delold + Authenticating as principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with keytab /etc/krb5.keytab. + Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 2 removed from keytab WRFILE:/etc/krb5.keytab. + +When a single service principal is shared by multiple backend servers in +a load-balanced environment, it may be necessary to schedule downtime +or adjust the population in the load-balanced pool in order to propagate +the updated keytab to all hosts in the pool with minimal service interruption. + +Removing DES keys from usage +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This situation remains something of a testing or transitory state, +as new DES keys are still being generated, and will be used if requested +by a client. To make more progress removing DES from the realm, the KDC +should be configured to not generate such keys by default. + +.. note:: + + An attacker posing as a client can implement a brute force attack against + a DES key for any principal, if that key is in the current (highest-kvno) + key list. This attack is only possible if **allow_weak_crypto = true** + is enabled on the KDC. Setting the **+requires_preauth** flag on a + principal forces this attack to be an online attack, much slower than + the offline attack otherwise available to the attacker. However, setting + this flag on a service principal is not always advisable; see the entry in + :ref:`add_principal` for details. + +The following KDC configuration will not generate DES keys by default: + +:: + + [realms] + ZONE.MIT.EDU = { + supported_enctypes = aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des3-hmac-sha1:normal + +.. note:: + + As before, the KDC process must be restarted for this change to take + effect. It is best practice to update kdc.conf on all KDCs, not just the + primary, to avoid unpleasant surprises should the primary fail and a + replica need to be promoted. + +It is now appropriate to remove the legacy single-DES key from the +``krbtgt/REALM`` entry: + +:: + + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q "cpw -randkey -keepold \ + > krbtgt/ZONE.MIT.EDU" + Authenticating as principal host/admin@ATHENA.MIT.EDU with password. + Key for "krbtgt/ZONE.MIT.EDU@ZONE.MIT.EDU" randomized. + +After the maximum ticket lifetime has passed, the old database entry +should be removed. + +:: + + [root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'purgekeys krbtgt/ZONE.MIT.EDU' + Authenticating as principal root/admin@ZONE.MIT.EDU with password. + Old keys for principal "krbtgt/ZONE.MIT.EDU@ZONE.MIT.EDU" purged. + +After the KDC is restarted with the new **supported_enctypes**, +all user password changes and application keytab updates will not +generate DES keys by default. + +:: + + contents-vnder-pressvre:~> kpasswd zonetest@ZONE.MIT.EDU + Password for zonetest@ZONE.MIT.EDU: [enter old password] + Enter new password: [enter new password] + Enter it again: [enter new password] + Password changed. + contents-vnder-pressvre:~> kadmin -r ZONE.MIT.EDU -q 'getprinc zonetest' + [...] + Number of keys: 3 + Key: vno 9, aes256-cts-hmac-sha1-96 + Key: vno 9, aes128-cts-hmac-sha1-96 + Key: vno 9, des3-cbc-sha1 + [...] + + [kaduk@glossolalia ~]$ kadmin -p kaduk@ZONE.MIT.EDU -r ZONE.MIT.EDU -k \ + > -t kaduk-zone.keytab -q 'ktadd -k kaduk-zone.keytab kaduk@ZONE.MIT.EDU' + Authenticating as principal kaduk@ZONE.MIT.EDU with keytab kaduk-zone.keytab. + Entry for principal kaduk@ZONE.MIT.EDU with kvno 3, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:kaduk-zone.keytab. + Entry for principal kaduk@ZONE.MIT.EDU with kvno 3, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:kaduk-zone.keytab. + Entry for principal kaduk@ZONE.MIT.EDU with kvno 3, encryption type des3-cbc-sha1 added to keytab WRFILE:kaduk-zone.keytab. + +Once all principals have been re-keyed, DES support can be disabled on the +KDC (**allow_weak_crypto = false**), and client machines can remove +**allow_weak_crypto = true** from their :ref:`krb5.conf(5)` configuration +files, completing the migration. **allow_weak_crypto** takes precedence over +all places where DES enctypes could be explicitly configured. DES keys will +not be used, even if they are present, when **allow_weak_crypto = false**. + +Support for legacy services +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If there remain legacy services which do not support non-DES enctypes +(such as older versions of AFS), **allow_weak_crypto** must remain +enabled on the KDC. Client machines need not have this setting, +though---applications which require DES can use API calls to allow +weak crypto on a per-request basis, overriding the system krb5.conf. +However, having **allow_weak_crypto** set on the KDC means that any +principals which have a DES key in the database could still use those +keys. To minimize the use of DES in the realm and restrict it to just +legacy services which require DES, it is necessary to remove all other +DES keys. The realm has been configured such that at password and +keytab change, no DES keys will be generated by default. The task +then reduces to requiring user password changes and having server +administrators update their service keytabs. Administrative outreach +will be necessary, and if the desire to eliminate DES is sufficiently +strong, the KDC administrators may choose to randkey any principals +which have not been rekeyed after some timeout period, forcing the +user to contact the helpdesk for access. + +The Database Master Key +----------------------- + +This procedure does not alter ``K/M@REALM``, the key used to encrypt key +material in the Kerberos database. (This is the key stored in the stash file +on the KDC if stash files are used.) However, the security risk of +a single-DES key for ``K/M`` is minimal, given that access to material +encrypted in ``K/M`` (the Kerberos database) is generally tightly controlled. +If an attacker can gain access to the encrypted database, they likely +have access to the stash file as well, rendering the weak cryptography +broken by non-cryptographic means. As such, upgrading ``K/M`` to a stronger +encryption type is unlikely to be a high-priority task. + +Is is possible to upgrade the master key used for the database, if +desired. Using :ref:`kdb5_util(8)`'s **add_mkey**, **use_mkey**, and +**update_princ_encryption** commands, a new master key can be added +and activated for use on new key material, and the existing entries +converted to the new master key. diff --git a/krb5-1.21.3/doc/html/_sources/admin/appl_servers.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/appl_servers.rst.txt new file mode 100644 index 00000000..e9d16e87 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/appl_servers.rst.txt @@ -0,0 +1,171 @@ +Application servers +=================== + +If you need to install the Kerberos V5 programs on an application +server, please refer to the Kerberos V5 Installation Guide. Once you +have installed the software, you need to add that host to the Kerberos +database (see :ref:`principals`), and generate a keytab for that host, +that contains the host's key. You also need to make sure the host's +clock is within your maximum clock skew of the KDCs. + + +Keytabs +------- + +A keytab is a host's copy of its own keylist, which is analogous to a +user's password. An application server that needs to authenticate +itself to the KDC has to have a keytab that contains its own principal +and key. Just as it is important for users to protect their +passwords, it is equally important for hosts to protect their keytabs. +You should always store keytab files on local disk, and make them +readable only by root, and you should never send a keytab file over a +network in the clear. Ideally, you should run the :ref:`kadmin(1)` +command to extract a keytab on the host on which the keytab is to +reside. + + +.. _add_princ_kt: + +Adding principals to keytabs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To generate a keytab, or to add a principal to an existing keytab, use +the **ktadd** command from kadmin. Here is a sample session, using +configuration files that enable only AES encryption:: + + kadmin: ktadd host/daffodil.mit.edu@ATHENA.MIT.EDU + Entry for principal host/daffodil.mit.edu with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab + Entry for principal host/daffodil.mit.edu with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab + + +Removing principals from keytabs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To remove a principal from an existing keytab, use the kadmin +**ktremove** command:: + + kadmin: ktremove host/daffodil.mit.edu@ATHENA.MIT.EDU + Entry for principal host/daffodil.mit.edu with kvno 2 removed from keytab FILE:/etc/krb5.keytab. + Entry for principal host/daffodil.mit.edu with kvno 2 removed from keytab FILE:/etc/krb5.keytab. + + +Using a keytab to acquire client credentials +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +While keytabs are ordinarily used to accept credentials from clients, +they can also be used to acquire initial credentials, allowing one +service to authenticate to another. + +To manually obtain credentials using a keytab, use the :ref:`kinit(1)` +**-k** option, together with the **-t** option if the keytab is not in +the default location. + +Beginning with release 1.11, GSSAPI applications can be configured to +automatically obtain initial credentials from a keytab as needed. The +recommended configuration is as follows: + +#. Create a keytab containing a single entry for the desired client + identity. + +#. Place the keytab in a location readable by the service, and set the + **KRB5_CLIENT_KTNAME** environment variable to its filename. + Alternatively, use the **default_client_keytab_name** profile + variable in :ref:`libdefaults`, or use the default location of + |ckeytab|. + +#. Set **KRB5CCNAME** to a filename writable by the service, which + will not be used for any other purpose. Do not manually obtain + credentials at this location. (Another credential cache type + besides **FILE** can be used if desired, as long the cache will not + conflict with another use. A **MEMORY** cache can be used if the + service runs as a long-lived process. See :ref:`ccache_definition` + for details.) + +#. Start the service. When it authenticates using GSSAPI, it will + automatically obtain credentials from the client keytab into the + specified credential cache, and refresh them before they expire. + + +Clock Skew +---------- + +A Kerberos application server host must keep its clock synchronized or +it will reject authentication requests from clients. Modern operating +systems typically provide a facility to maintain the correct time; +make sure it is enabled. This is especially important on virtual +machines, where clocks tend to drift more rapidly than normal machine +clocks. + +The default allowable clock skew is controlled by the **clockskew** +variable in :ref:`libdefaults`. + + +Getting DNS information correct +------------------------------- + +Several aspects of Kerberos rely on name service. When a hostname is +used to name a service, clients may canonicalize the hostname using +forward and possibly reverse name resolution. The result of this +canonicalization must match the principal entry in the host's keytab, +or authentication will fail. To work with all client canonicalization +configurations, each host's canonical name must be the fully-qualified +host name (including the domain), and each host's IP address must +reverse-resolve to the canonical name. + +Configuration of hostnames varies by operating system. On the +application server itself, canonicalization will typically use the +``/etc/hosts`` file rather than the DNS. Ensure that the line for the +server's hostname is in the following form:: + + IP address fully-qualified hostname aliases + +Here is a sample ``/etc/hosts`` file:: + + # this is a comment + 127.0.0.1 localhost localhost.mit.edu + 10.0.0.6 daffodil.mit.edu daffodil trillium wake-robin + +The output of ``klist -k`` for this example host should look like:: + + viola# klist -k + Keytab name: /etc/krb5.keytab + KVNO Principal + ---- ------------------------------------------------------------ + 2 host/daffodil.mit.edu@ATHENA.MIT.EDU + +If you were to ssh to this host with a fresh credentials cache (ticket +file), and then :ref:`klist(1)`, the output should list a service +principal of ``host/daffodil.mit.edu@ATHENA.MIT.EDU``. + + +.. _conf_firewall: + +Configuring your firewall to work with Kerberos V5 +-------------------------------------------------- + +If you need off-site users to be able to get Kerberos tickets in your +realm, they must be able to get to your KDC. This requires either +that you have a replica KDC outside your firewall, or that you +configure your firewall to allow UDP requests into at least one of +your KDCs, on whichever port the KDC is running. (The default is port +88; other ports may be specified in the KDC's :ref:`kdc.conf(5)` +file.) Similarly, if you need off-site users to be able to change +their passwords in your realm, they must be able to get to your +Kerberos admin server on the kpasswd port (which defaults to 464). If +you need off-site users to be able to administer your Kerberos realm, +they must be able to get to your Kerberos admin server on the +administrative port (which defaults to 749). + +If your on-site users inside your firewall will need to get to KDCs in +other realms, you will also need to configure your firewall to allow +outgoing TCP and UDP requests to port 88, and to port 464 to allow +password changes. If your on-site users inside your firewall will +need to get to Kerberos admin servers in other realms, you will also +need to allow outgoing TCP and UDP requests to port 749. + +If any of your KDCs are outside your firewall, you will need to allow +kprop requests to get through to the remote KDC. :ref:`kprop(8)` uses +the ``krb5_prop`` service on port 754 (tcp). + +The book *UNIX System Security*, by David Curry, is a good starting +point for learning to configure firewalls. diff --git a/krb5-1.21.3/doc/html/_sources/admin/auth_indicator.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/auth_indicator.rst.txt new file mode 100644 index 00000000..b13905e9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/auth_indicator.rst.txt @@ -0,0 +1,57 @@ +.. _auth_indicator: + +Authentication indicators +========================= + +As of release 1.14, the KDC can be configured to annotate tickets if +the client authenticated using a stronger preauthentication mechanism +such as :ref:`PKINIT ` or :ref:`OTP `. These +annotations are called "authentication indicators." Service +principals can be configured to require particular authentication +indicators in order to authenticate to that service. An +authentication indicator value can be any string chosen by the KDC +administrator; there are no pre-set values. + +To use authentication indicators with PKINIT or OTP, first configure +the KDC to include an indicator when that preauthentication mechanism +is used. For PKINIT, use the **pkinit_indicator** variable in +:ref:`kdc.conf(5)`. For OTP, use the **indicator** variable in the +token type definition, or specify the indicators in the **otp** user +string as described in :ref:`otp_preauth`. + +To require an indicator to be present in order to authenticate to a +service principal, set the **require_auth** string attribute on the +principal to the indicator value to be required. If you wish to allow +one of several indicators to be accepted, you can specify multiple +indicator values separated by spaces. + +For example, a realm could be configured to set the authentication +indicator value "strong" when PKINIT is used to authenticate, using a +setting in the :ref:`kdc_realms` subsection:: + + pkinit_indicator = strong + +A service principal could be configured to require the "strong" +authentication indicator value:: + + $ kadmin setstr host/high.value.server require_auth strong + Password for user/admin@KRBTEST.COM: + +A user who authenticates with PKINIT would be able to obtain a ticket +for the service principal:: + + $ kinit -X X509_user_identity=FILE:/my/cert.pem,/my/key.pem user + $ kvno host/high.value.server + host/high.value.server@KRBTEST.COM: kvno = 1 + +but a user who authenticates with a password would not:: + + $ kinit user + Password for user@KRBTEST.COM: + $ kvno host/high.value.server + kvno: KDC policy rejects request while getting credentials for + host/high.value.server@KRBTEST.COM + +GSSAPI server applications can inspect authentication indicators +through the :ref:`auth-indicators ` name +attribute. diff --git a/krb5-1.21.3/doc/html/_sources/admin/backup_host.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/backup_host.rst.txt new file mode 100644 index 00000000..8914551c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/backup_host.rst.txt @@ -0,0 +1,34 @@ +Backups of secure hosts +======================= + +When you back up a secure host, you should exclude the host's keytab +file from the backup. If someone obtained a copy of the keytab from a +backup, that person could make any host masquerade as the host whose +keytab was compromised. In many configurations, knowledge of the +host's keytab also allows root access to the host. This could be +particularly dangerous if the compromised keytab was from one of your +KDCs. If the machine has a disk crash and the keytab file is lost, it +is easy to generate another keytab file. (See :ref:`add_princ_kt`.) +If you are unable to exclude particular files from backups, you should +ensure that the backups are kept as secure as the host's root +password. + + +Backing up the Kerberos database +-------------------------------- + +As with any file, it is possible that your Kerberos database could +become corrupted. If this happens on one of the replica KDCs, you +might never notice, since the next automatic propagation of the +database would install a fresh copy. However, if it happens to the +primary KDC, the corrupted database would be propagated to all of the +replicas during the next propagation. For this reason, MIT recommends +that you back up your Kerberos database regularly. Because the primary +KDC is continuously dumping the database to a file in order to +propagate it to the replica KDCs, it is a simple matter to have a cron +job periodically copy the dump file to a secure machine elsewhere on +your network. (Of course, it is important to make the host where +these backups are stored as secure as your KDCs, and to encrypt its +transmission across your network.) Then if your database becomes +corrupted, you can load the most recent dump onto the primary KDC. +(See :ref:`restore_from_dump`.) diff --git a/krb5-1.21.3/doc/html/_sources/admin/conf_files/index.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/conf_files/index.rst.txt new file mode 100644 index 00000000..a04836ac --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/conf_files/index.rst.txt @@ -0,0 +1,20 @@ +Configuration Files +=================== + +Kerberos uses configuration files to allow administrators to specify +settings on a per-machine basis. :ref:`krb5.conf(5)` applies to all +applications using the Kerboros library, on clients and servers. +For KDC-specific applications, additional settings can be specified in +:ref:`kdc.conf(5)`; the two files are merged into a configuration profile +used by applications accessing the KDC database directly. :ref:`kadm5.acl(5)` +is also only used on the KDC, it controls permissions for modifying the +KDC database. + +Contents +-------- +.. toctree:: + :maxdepth: 1 + + krb5_conf + kdc_conf + kadm5_acl diff --git a/krb5-1.21.3/doc/html/_sources/admin/conf_files/kadm5_acl.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/conf_files/kadm5_acl.rst.txt new file mode 100644 index 00000000..290bf0e0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/conf_files/kadm5_acl.rst.txt @@ -0,0 +1,163 @@ +.. _kadm5.acl(5): + +kadm5.acl +========= + +DESCRIPTION +----------- + +The Kerberos :ref:`kadmind(8)` daemon uses an Access Control List +(ACL) file to manage access rights to the Kerberos database. +For operations that affect principals, the ACL file also controls +which principals can operate on which other principals. + +The default location of the Kerberos ACL file is +|kdcdir|\ ``/kadm5.acl`` unless this is overridden by the *acl_file* +variable in :ref:`kdc.conf(5)`. + +SYNTAX +------ + +Empty lines and lines starting with the sharp sign (``#``) are +ignored. Lines containing ACL entries have the format:: + + principal permissions [target_principal [restrictions] ] + +.. note:: + + Line order in the ACL file is important. The first matching entry + will control access for an actor principal on a target principal. + +*principal* + (Partially or fully qualified Kerberos principal name.) Specifies + the principal whose permissions are to be set. + + Each component of the name may be wildcarded using the ``*`` + character. + +*permissions* + Specifies what operations may or may not be performed by a + *principal* matching a particular entry. This is a string of one or + more of the following list of characters or their upper-case + counterparts. If the character is *upper-case*, then the operation + is disallowed. If the character is *lower-case*, then the operation + is permitted. + + == ====================================================== + a [Dis]allows the addition of principals or policies + c [Dis]allows the changing of passwords for principals + d [Dis]allows the deletion of principals or policies + e [Dis]allows the extraction of principal keys + i [Dis]allows inquiries about principals or policies + l [Dis]allows the listing of all principals or policies + m [Dis]allows the modification of principals or policies + p [Dis]allows the propagation of the principal database (used in :ref:`incr_db_prop`) + s [Dis]allows the explicit setting of the key for a principal + x Short for admcilsp. All privileges (except ``e``) + \* Same as x. + == ====================================================== + +.. note:: + + The ``extract`` privilege is not included in the wildcard + privilege; it must be explicitly assigned. This privilege + allows the user to extract keys from the database, and must be + handled with great care to avoid disclosure of important keys + like those of the kadmin/* or krbtgt/* principals. The + **lockdown_keys** principal attribute can be used to prevent + key extraction from specific principals regardless of the + granted privilege. + +*target_principal* + (Optional. Partially or fully qualified Kerberos principal name.) + Specifies the principal on which *permissions* may be applied. + Each component of the name may be wildcarded using the ``*`` + character. + + *target_principal* can also include back-references to *principal*, + in which ``*number`` matches the corresponding wildcard in + *principal*. + +*restrictions* + (Optional) A string of flags. Allowed restrictions are: + + {+\|-}\ *flagname* + flag is forced to the indicated value. The permissible flags + are the same as those for the **default_principal_flags** + variable in :ref:`kdc.conf(5)`. + + *-clearpolicy* + policy is forced to be empty. + + *-policy pol* + policy is forced to be *pol*. + + -{*expire, pwexpire, maxlife, maxrenewlife*} *time* + (:ref:`getdate` string) associated value will be forced to + MIN(*time*, requested value). + + The above flags act as restrictions on any add or modify operation + which is allowed due to that ACL line. + +.. warning:: + + If the kadmind ACL file is modified, the kadmind daemon needs to be + restarted for changes to take effect. + +EXAMPLE +------- + +Here is an example of a kadm5.acl file:: + + */admin@ATHENA.MIT.EDU * # line 1 + joeadmin@ATHENA.MIT.EDU ADMCIL # line 2 + joeadmin/*@ATHENA.MIT.EDU i */root@ATHENA.MIT.EDU # line 3 + */root@ATHENA.MIT.EDU ci *1@ATHENA.MIT.EDU # line 4 + */root@ATHENA.MIT.EDU l * # line 5 + sms@ATHENA.MIT.EDU x * -maxlife 9h -postdateable # line 6 + +(line 1) Any principal in the ``ATHENA.MIT.EDU`` realm with an +``admin`` instance has all administrative privileges except extracting +keys. + +(lines 1-3) The user ``joeadmin`` has all permissions except +extracting keys with his ``admin`` instance, +``joeadmin/admin@ATHENA.MIT.EDU`` (matches line 1). He has no +permissions at all with his null instance, ``joeadmin@ATHENA.MIT.EDU`` +(matches line 2). His ``root`` and other non-``admin``, non-null +instances (e.g., ``extra`` or ``dbadmin``) have inquire permissions +with any principal that has the instance ``root`` (matches line 3). + +(line 4) Any ``root`` principal in ``ATHENA.MIT.EDU`` can inquire +or change the password of their null instance, but not any other +null instance. (Here, ``*1`` denotes a back-reference to the +component matching the first wildcard in the actor principal.) + +(line 5) Any ``root`` principal in ``ATHENA.MIT.EDU`` can generate +the list of principals in the database, and the list of policies +in the database. This line is separate from line 4, because list +permission can only be granted globally, not to specific target +principals. + +(line 6) Finally, the Service Management System principal +``sms@ATHENA.MIT.EDU`` has all permissions except extracting keys, but +any principal that it creates or modifies will not be able to get +postdateable tickets or tickets with a life of longer than 9 hours. + +MODULE BEHAVIOR +--------------- + +The ACL file can coexist with other authorization modules in release +1.16 and later, as configured in the :ref:`kadm5_auth` section of +:ref:`krb5.conf(5)`. The ACL file will positively authorize +operations according to the rules above, but will never +authoritatively deny an operation, so other modules can authorize +operations in addition to those authorized by the ACL file. + +To operate without an ACL file, set the *acl_file* variable in +:ref:`kdc.conf(5)` to the empty string with ``acl_file = ""``. + +SEE ALSO +-------- + +:ref:`kdc.conf(5)`, :ref:`kadmind(8)` diff --git a/krb5-1.21.3/doc/html/_sources/admin/conf_files/kdc_conf.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/conf_files/kdc_conf.rst.txt new file mode 100644 index 00000000..74a0a2ac --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/conf_files/kdc_conf.rst.txt @@ -0,0 +1,976 @@ +.. _kdc.conf(5): + +kdc.conf +======== + +The kdc.conf file supplements :ref:`krb5.conf(5)` for programs which +are typically only used on a KDC, such as the :ref:`krb5kdc(8)` and +:ref:`kadmind(8)` daemons and the :ref:`kdb5_util(8)` program. +Relations documented here may also be specified in krb5.conf; for the +KDC programs mentioned, krb5.conf and kdc.conf will be merged into a +single configuration profile. + +Normally, the kdc.conf file is found in the KDC state directory, +|kdcdir|. You can override the default location by setting the +environment variable **KRB5_KDC_PROFILE**. + +Please note that you need to restart the KDC daemon for any configuration +changes to take effect. + +Structure +--------- + +The kdc.conf file is set up in the same format as the +:ref:`krb5.conf(5)` file. + + +Sections +-------- + +The kdc.conf file may contain the following sections: + +==================== ================================================= +:ref:`kdcdefaults` Default values for KDC behavior +:ref:`kdc_realms` Realm-specific database configuration and settings +:ref:`dbdefaults` Default database settings +:ref:`dbmodules` Per-database settings +:ref:`logging` Controls how Kerberos daemons perform logging +==================== ================================================= + + +.. _kdcdefaults: + +[kdcdefaults] +~~~~~~~~~~~~~ + +Some relations in the [kdcdefaults] section specify default values for +realm variables, to be used if the [realms] subsection does not +contain a relation for the tag. See the :ref:`kdc_realms` section for +the definitions of these relations. + +* **host_based_services** +* **kdc_listen** +* **kdc_ports** +* **kdc_tcp_listen** +* **kdc_tcp_ports** +* **no_host_referral** +* **restrict_anonymous_to_tgt** + +The following [kdcdefaults] variables have no per-realm equivalent: + +**kdc_max_dgram_reply_size** + Specifies the maximum packet size that can be sent over UDP. The + default value is 4096 bytes. + +**kdc_tcp_listen_backlog** + (Integer.) Set the size of the listen queue length for the KDC + daemon. The value may be limited by OS settings. The default + value is 5. + +**spake_preauth_kdc_challenge** + (String.) Specifies the group for a SPAKE optimistic challenge. + See the **spake_preauth_groups** variable in :ref:`libdefaults` + for possible values. The default is not to issue an optimistic + challenge. (New in release 1.17.) + + +.. _kdc_realms: + +[realms] +~~~~~~~~ + +Each tag in the [realms] section is the name of a Kerberos realm. The +value of the tag is a subsection where the relations define KDC +parameters for that particular realm. The following example shows how +to define one parameter for the ATHENA.MIT.EDU realm:: + + [realms] + ATHENA.MIT.EDU = { + max_renewable_life = 7d 0h 0m 0s + } + +The following tags may be specified in a [realms] subsection: + +**acl_file** + (String.) Location of the access control list file that + :ref:`kadmind(8)` uses to determine which principals are allowed + which permissions on the Kerberos database. To operate without an + ACL file, set this relation to the empty string with ``acl_file = + ""``. The default value is |kdcdir|\ ``/kadm5.acl``. For more + information on Kerberos ACL file see :ref:`kadm5.acl(5)`. + +**database_module** + (String.) This relation indicates the name of the configuration + section under :ref:`dbmodules` for database-specific parameters + used by the loadable database library. The default value is the + realm name. If this configuration section does not exist, default + values will be used for all database parameters. + +**database_name** + (String, deprecated.) This relation specifies the location of the + Kerberos database for this realm, if the DB2 module is being used + and the :ref:`dbmodules` configuration section does not specify a + database name. The default value is |kdcdir|\ ``/principal``. + +**default_principal_expiration** + (:ref:`abstime` string.) Specifies the default expiration date of + principals created in this realm. The default value is 0, which + means no expiration date. + +**default_principal_flags** + (Flag string.) Specifies the default attributes of principals + created in this realm. The format for this string is a + comma-separated list of flags, with '+' before each flag that + should be enabled and '-' before each flag that should be + disabled. The **postdateable**, **forwardable**, **tgt-based**, + **renewable**, **proxiable**, **dup-skey**, **allow-tickets**, and + **service** flags default to enabled. + + There are a number of possible flags: + + **allow-tickets** + Enabling this flag means that the KDC will issue tickets for + this principal. Disabling this flag essentially deactivates + the principal within this realm. + + **dup-skey** + Enabling this flag allows the KDC to issue user-to-user + service tickets for this principal. + + **forwardable** + Enabling this flag allows the principal to obtain forwardable + tickets. + + **hwauth** + If this flag is enabled, then the principal is required to + preauthenticate using a hardware device before receiving any + tickets. + + **no-auth-data-required** + Enabling this flag prevents PAC or AD-SIGNEDPATH data from + being added to service tickets for the principal. + + **ok-as-delegate** + If this flag is enabled, it hints the client that credentials + can and should be delegated when authenticating to the + service. + + **ok-to-auth-as-delegate** + Enabling this flag allows the principal to use S4USelf tickets. + + **postdateable** + Enabling this flag allows the principal to obtain postdateable + tickets. + + **preauth** + If this flag is enabled on a client principal, then that + principal is required to preauthenticate to the KDC before + receiving any tickets. On a service principal, enabling this + flag means that service tickets for this principal will only + be issued to clients with a TGT that has the preauthenticated + bit set. + + **proxiable** + Enabling this flag allows the principal to obtain proxy + tickets. + + **pwchange** + Enabling this flag forces a password change for this + principal. + + **pwservice** + If this flag is enabled, it marks this principal as a password + change service. This should only be used in special cases, + for example, if a user's password has expired, then the user + has to get tickets for that principal without going through + the normal password authentication in order to be able to + change the password. + + **renewable** + Enabling this flag allows the principal to obtain renewable + tickets. + + **service** + Enabling this flag allows the the KDC to issue service tickets + for this principal. In release 1.17 and later, user-to-user + service tickets are still allowed if the **dup-skey** flag is + set. + + **tgt-based** + Enabling this flag allows a principal to obtain tickets based + on a ticket-granting-ticket, rather than repeating the + authentication process that was used to obtain the TGT. + +**dict_file** + (String.) Location of the dictionary file containing strings that + are not allowed as passwords. The file should contain one string + per line, with no additional whitespace. If none is specified or + if there is no policy assigned to the principal, no dictionary + checks of passwords will be performed. + +**disable_pac** + (Boolean value.) If true, the KDC will not issue PACs for this + realm, and S4U2Self and S4U2Proxy operations will be disabled. + The default is false, which will permit the KDC to issue PACs. + New in release 1.20. + +**encrypted_challenge_indicator** + (String.) Specifies the authentication indicator value that the KDC + asserts into tickets obtained using FAST encrypted challenge + pre-authentication. New in 1.16. + +**host_based_services** + (Whitespace- or comma-separated list.) Lists services which will + get host-based referral processing even if the server principal is + not marked as host-based by the client. + +**iprop_enable** + (Boolean value.) Specifies whether incremental database + propagation is enabled. The default value is false. + +**iprop_ulogsize** + (Integer.) Specifies the maximum number of log entries to be + retained for incremental propagation. The default value is 1000. + Prior to release 1.11, the maximum value was 2500. New in release + 1.19. + +**iprop_master_ulogsize** + The name for **iprop_ulogsize** prior to release 1.19. Its value is + used as a fallback if **iprop_ulogsize** is not specified. + +**iprop_replica_poll** + (Delta time string.) Specifies how often the replica KDC polls + for new updates from the primary. The default value is ``2m`` + (that is, two minutes). New in release 1.17. + +**iprop_slave_poll** + (Delta time string.) The name for **iprop_replica_poll** prior to + release 1.17. Its value is used as a fallback if + **iprop_replica_poll** is not specified. + +**iprop_listen** + (Whitespace- or comma-separated list.) Specifies the iprop RPC + listening addresses and/or ports for the :ref:`kadmind(8)` daemon. + Each entry may be an interface address, a port number, or an + address and port number separated by a colon. If the address + contains colons, enclose it in square brackets. If no address is + specified, the wildcard address is used. If kadmind fails to bind + to any of the specified addresses, it will fail to start. The + default (when **iprop_enable** is true) is to bind to the wildcard + address at the port specified in **iprop_port**. New in release + 1.15. + +**iprop_port** + (Port number.) Specifies the port number to be used for + incremental propagation. When **iprop_enable** is true, this + relation is required in the replica KDC configuration file, and + this relation or **iprop_listen** is required in the primary + configuration file, as there is no default port number. Port + numbers specified in **iprop_listen** entries will override this + port number for the :ref:`kadmind(8)` daemon. + +**iprop_resync_timeout** + (Delta time string.) Specifies the amount of time to wait for a + full propagation to complete. This is optional in configuration + files, and is used by replica KDCs only. The default value is 5 + minutes (``5m``). New in release 1.11. + +**iprop_logfile** + (File name.) Specifies where the update log file for the realm + database is to be stored. The default is to use the + **database_name** entry from the realms section of the krb5 config + file, with ``.ulog`` appended. (NOTE: If **database_name** isn't + specified in the realms section, perhaps because the LDAP database + back end is being used, or the file name is specified in the + [dbmodules] section, then the hard-coded default for + **database_name** is used. Determination of the **iprop_logfile** + default value will not use values from the [dbmodules] section.) + +**kadmind_listen** + (Whitespace- or comma-separated list.) Specifies the kadmin RPC + listening addresses and/or ports for the :ref:`kadmind(8)` daemon. + Each entry may be an interface address, a port number, or an + address and port number separated by a colon. If the address + contains colons, enclose it in square brackets. If no address is + specified, the wildcard address is used. If kadmind fails to bind + to any of the specified addresses, it will fail to start. The + default is to bind to the wildcard address at the port specified + in **kadmind_port**, or the standard kadmin port (749). New in + release 1.15. + +**kadmind_port** + (Port number.) Specifies the port on which the :ref:`kadmind(8)` + daemon is to listen for this realm. Port numbers specified in + **kadmind_listen** entries will override this port number. The + assigned port for kadmind is 749, which is used by default. + +**key_stash_file** + (String.) Specifies the location where the master key has been + stored (via kdb5_util stash). The default is |kdcdir|\ + ``/.k5.REALM``, where *REALM* is the Kerberos realm. + +**kdc_listen** + (Whitespace- or comma-separated list.) Specifies the UDP + listening addresses and/or ports for the :ref:`krb5kdc(8)` daemon. + Each entry may be an interface address, a port number, or an + address and port number separated by a colon. If the address + contains colons, enclose it in square brackets. If no address is + specified, the wildcard address is used. If no port is specified, + the standard port (88) is used. If the KDC daemon fails to bind + to any of the specified addresses, it will fail to start. The + default is to bind to the wildcard address on the standard port. + New in release 1.15. + +**kdc_ports** + (Whitespace- or comma-separated list, deprecated.) Prior to + release 1.15, this relation lists the ports for the + :ref:`krb5kdc(8)` daemon to listen on for UDP requests. In + release 1.15 and later, it has the same meaning as **kdc_listen** + if that relation is not defined. + +**kdc_tcp_listen** + (Whitespace- or comma-separated list.) Specifies the TCP + listening addresses and/or ports for the :ref:`krb5kdc(8)` daemon. + Each entry may be an interface address, a port number, or an + address and port number separated by a colon. If the address + contains colons, enclose it in square brackets. If no address is + specified, the wildcard address is used. If no port is specified, + the standard port (88) is used. To disable listening on TCP, set + this relation to the empty string with ``kdc_tcp_listen = ""``. + If the KDC daemon fails to bind to any of the specified addresses, + it will fail to start. The default is to bind to the wildcard + address on the standard port. New in release 1.15. + +**kdc_tcp_ports** + (Whitespace- or comma-separated list, deprecated.) Prior to + release 1.15, this relation lists the ports for the + :ref:`krb5kdc(8)` daemon to listen on for UDP requests. In + release 1.15 and later, it has the same meaning as + **kdc_tcp_listen** if that relation is not defined. + +**kpasswd_listen** + (Comma-separated list.) Specifies the kpasswd listening addresses + and/or ports for the :ref:`kadmind(8)` daemon. Each entry may be + an interface address, a port number, or an address and port number + separated by a colon. If the address contains colons, enclose it + in square brackets. If no address is specified, the wildcard + address is used. If kadmind fails to bind to any of the specified + addresses, it will fail to start. The default is to bind to the + wildcard address at the port specified in **kpasswd_port**, or the + standard kpasswd port (464). New in release 1.15. + +**kpasswd_port** + (Port number.) Specifies the port on which the :ref:`kadmind(8)` + daemon is to listen for password change requests for this realm. + Port numbers specified in **kpasswd_listen** entries will override + this port number. The assigned port for password change requests + is 464, which is used by default. + +**master_key_name** + (String.) Specifies the name of the principal associated with the + master key. The default is ``K/M``. + +**master_key_type** + (Key type string.) Specifies the master key's key type. The + default value for this is |defmkey|. For a list of all possible + values, see :ref:`Encryption_types`. + +**max_life** + (:ref:`duration` string.) Specifies the maximum time period for + which a ticket may be valid in this realm. The default value is + 24 hours. + +**max_renewable_life** + (:ref:`duration` string.) Specifies the maximum time period + during which a valid ticket may be renewed in this realm. + The default value is 0. + +**no_host_referral** + (Whitespace- or comma-separated list.) Lists services to block + from getting host-based referral processing, even if the client + marks the server principal as host-based or the service is also + listed in **host_based_services**. ``no_host_referral = *`` will + disable referral processing altogether. + +**reject_bad_transit** + (Boolean value.) If set to true, the KDC will check the list of + transited realms for cross-realm tickets against the transit path + computed from the realm names and the capaths section of its + :ref:`krb5.conf(5)` file; if the path in the ticket to be issued + contains any realms not in the computed path, the ticket will not + be issued, and an error will be returned to the client instead. + If this value is set to false, such tickets will be issued + anyways, and it will be left up to the application server to + validate the realm transit path. + + If the disable-transited-check flag is set in the incoming + request, this check is not performed at all. Having the + **reject_bad_transit** option will cause such ticket requests to + be rejected always. + + This transit path checking and config file option currently apply + only to TGS requests. + + The default value is true. + +**restrict_anonymous_to_tgt** + (Boolean value.) If set to true, the KDC will reject ticket + requests from anonymous principals to service principals other + than the realm's ticket-granting service. This option allows + anonymous PKINIT to be enabled for use as FAST armor tickets + without allowing anonymous authentication to services. The + default value is false. New in release 1.9. + +**spake_preauth_indicator** + (String.) Specifies an authentication indicator value that the + KDC asserts into tickets obtained using SPAKE pre-authentication. + The default is not to add any indicators. This option may be + specified multiple times. New in release 1.17. + +**supported_enctypes** + (List of *key*:*salt* strings.) Specifies the default key/salt + combinations of principals for this realm. Any principals created + through :ref:`kadmin(1)` will have keys of these types. The + default value for this tag is |defkeysalts|. For lists of + possible values, see :ref:`Keysalt_lists`. + + +.. _dbdefaults: + +[dbdefaults] +~~~~~~~~~~~~ + +The [dbdefaults] section specifies default values for some database +parameters, to be used if the [dbmodules] subsection does not contain +a relation for the tag. See the :ref:`dbmodules` section for the +definitions of these relations. + +* **ldap_kerberos_container_dn** +* **ldap_kdc_dn** +* **ldap_kdc_sasl_authcid** +* **ldap_kdc_sasl_authzid** +* **ldap_kdc_sasl_mech** +* **ldap_kdc_sasl_realm** +* **ldap_kadmind_dn** +* **ldap_kadmind_sasl_authcid** +* **ldap_kadmind_sasl_authzid** +* **ldap_kadmind_sasl_mech** +* **ldap_kadmind_sasl_realm** +* **ldap_service_password_file** +* **ldap_conns_per_server** + + +.. _dbmodules: + +[dbmodules] +~~~~~~~~~~~ + +The [dbmodules] section contains parameters used by the KDC database +library and database modules. Each tag in the [dbmodules] section is +the name of a Kerberos realm or a section name specified by a realm's +**database_module** parameter. The following example shows how to +define one database parameter for the ATHENA.MIT.EDU realm:: + + [dbmodules] + ATHENA.MIT.EDU = { + disable_last_success = true + } + +The following tags may be specified in a [dbmodules] subsection: + +**database_name** + This DB2-specific tag indicates the location of the database in + the filesystem. The default is |kdcdir|\ ``/principal``. + +**db_library** + This tag indicates the name of the loadable database module. The + value should be ``db2`` for the DB2 module, ``klmdb`` for the LMDB + module, or ``kldap`` for the LDAP module. + +**disable_last_success** + If set to ``true``, suppresses KDC updates to the "Last successful + authentication" field of principal entries requiring + preauthentication. Setting this flag may improve performance. + (Principal entries which do not require preauthentication never + update the "Last successful authentication" field.). First + introduced in release 1.9. + +**disable_lockout** + If set to ``true``, suppresses KDC updates to the "Last failed + authentication" and "Failed password attempts" fields of principal + entries requiring preauthentication. Setting this flag may + improve performance, but also disables account lockout. First + introduced in release 1.9. + +**ldap_conns_per_server** + This LDAP-specific tag indicates the number of connections to be + maintained per LDAP server. + +**ldap_kdc_dn** and **ldap_kadmind_dn** + These LDAP-specific tags indicate the default DN for binding to + the LDAP server. The :ref:`krb5kdc(8)` daemon uses + **ldap_kdc_dn**, while the :ref:`kadmind(8)` daemon and other + administrative programs use **ldap_kadmind_dn**. The kadmind DN + must have the rights to read and write the Kerberos data in the + LDAP database. The KDC DN must have the same rights, unless + **disable_lockout** and **disable_last_success** are true, in + which case it only needs to have rights to read the Kerberos data. + These tags are ignored if a SASL mechanism is set with + **ldap_kdc_sasl_mech** or **ldap_kadmind_sasl_mech**. + +**ldap_kdc_sasl_mech** and **ldap_kadmind_sasl_mech** + These LDAP-specific tags specify the SASL mechanism (such as + ``EXTERNAL``) to use when binding to the LDAP server. New in + release 1.13. + +**ldap_kdc_sasl_authcid** and **ldap_kadmind_sasl_authcid** + These LDAP-specific tags specify the SASL authentication identity + to use when binding to the LDAP server. Not all SASL mechanisms + require an authentication identity. If the SASL mechanism + requires a secret (such as the password for ``DIGEST-MD5``), these + tags also determine the name within the + **ldap_service_password_file** where the secret is stashed. New + in release 1.13. + +**ldap_kdc_sasl_authzid** and **ldap_kadmind_sasl_authzid** + These LDAP-specific tags specify the SASL authorization identity + to use when binding to the LDAP server. In most circumstances + they do not need to be specified. New in release 1.13. + +**ldap_kdc_sasl_realm** and **ldap_kadmind_sasl_realm** + These LDAP-specific tags specify the SASL realm to use when + binding to the LDAP server. In most circumstances they do not + need to be set. New in release 1.13. + +**ldap_kerberos_container_dn** + This LDAP-specific tag indicates the DN of the container object + where the realm objects will be located. + +**ldap_servers** + This LDAP-specific tag indicates the list of LDAP servers that the + Kerberos servers can connect to. The list of LDAP servers is + whitespace-separated. The LDAP server is specified by a LDAP URI. + It is recommended to use ``ldapi:`` or ``ldaps:`` URLs to connect + to the LDAP server. + +**ldap_service_password_file** + This LDAP-specific tag indicates the file containing the stashed + passwords (created by ``kdb5_ldap_util stashsrvpw``) for the + **ldap_kdc_dn** and **ldap_kadmind_dn** objects, or for the + **ldap_kdc_sasl_authcid** or **ldap_kadmind_sasl_authcid** names + for SASL authentication. This file must be kept secure. + +**mapsize** + This LMDB-specific tag indicates the maximum size of the two + database environments in megabytes. The default value is 128. + Increase this value to address "Environment mapsize limit reached" + errors. New in release 1.17. + +**max_readers** + This LMDB-specific tag indicates the maximum number of concurrent + reading processes for the databases. The default value is 128. + New in release 1.17. + +**nosync** + This LMDB-specific tag can be set to improve the throughput of + kadmind and other administrative agents, at the expense of + durability (recent database changes may not survive a power outage + or other sudden reboot). It does not affect the throughput of the + KDC. The default value is false. New in release 1.17. + +**unlockiter** + If set to ``true``, this DB2-specific tag causes iteration + operations to release the database lock while processing each + principal. Setting this flag to ``true`` can prevent extended + blocking of KDC or kadmin operations when dumps of large databases + are in progress. First introduced in release 1.13. + +The following tag may be specified directly in the [dbmodules] +section to control where database modules are loaded from: + +**db_module_dir** + This tag controls where the plugin system looks for database + modules. The value should be an absolute path. + +.. _logging: + +[logging] +~~~~~~~~~ + +The [logging] section indicates how :ref:`krb5kdc(8)` and +:ref:`kadmind(8)` perform logging. It may contain the following +relations: + +**admin_server** + Specifies how :ref:`kadmind(8)` performs logging. + +**kdc** + Specifies how :ref:`krb5kdc(8)` performs logging. + +**default** + Specifies how either daemon performs logging in the absence of + relations specific to the daemon. + +**debug** + (Boolean value.) Specifies whether debugging messages are + included in log outputs other than SYSLOG. Debugging messages are + always included in the system log output because syslog performs + its own priority filtering. The default value is false. New in + release 1.15. + +Logging specifications may have the following forms: + +**FILE=**\ *filename* or **FILE:**\ *filename* + This value causes the daemon's logging messages to go to the + *filename*. If the ``=`` form is used, the file is overwritten. + If the ``:`` form is used, the file is appended to. + +**STDERR** + This value causes the daemon's logging messages to go to its + standard error stream. + +**CONSOLE** + This value causes the daemon's logging messages to go to the + console, if the system supports it. + +**DEVICE=**\ ** + This causes the daemon's logging messages to go to the specified + device. + +**SYSLOG**\ [\ **:**\ *severity*\ [\ **:**\ *facility*\ ]] + This causes the daemon's logging messages to go to the system log. + + For backward compatibility, a severity argument may be specified, + and must be specified in order to specify a facility. This + argument will be ignored. + + The facility argument specifies the facility under which the + messages are logged. This may be any of the following facilities + supported by the syslog(3) call minus the LOG\_ prefix: **KERN**, + **USER**, **MAIL**, **DAEMON**, **AUTH**, **LPR**, **NEWS**, + **UUCP**, **CRON**, and **LOCAL0** through **LOCAL7**. If no + facility is specified, the default is **AUTH**. + +In the following example, the logging messages from the KDC will go to +the console and to the system log under the facility LOG_DAEMON, and +the logging messages from the administrative server will be appended +to the file ``/var/adm/kadmin.log`` and sent to the device +``/dev/tty04``. :: + + [logging] + kdc = CONSOLE + kdc = SYSLOG:INFO:DAEMON + admin_server = FILE:/var/adm/kadmin.log + admin_server = DEVICE=/dev/tty04 + +If no logging specification is given, the default is to use syslog. +To disable logging entirely, specify ``default = DEVICE=/dev/null``. + + +.. _otp: + +[otp] +~~~~~ + +Each subsection of [otp] is the name of an OTP token type. The tags +within the subsection define the configuration required to forward a +One Time Password request to a RADIUS server. + +For each token type, the following tags may be specified: + +**server** + This is the server to send the RADIUS request to. It can be a + hostname with optional port, an ip address with optional port, or + a Unix domain socket address. The default is + |kdcdir|\ ``/.socket``. + +**secret** + This tag indicates a filename (which may be relative to |kdcdir|) + containing the secret used to encrypt the RADIUS packets. The + secret should appear in the first line of the file by itself; + leading and trailing whitespace on the line will be removed. If + the value of **server** is a Unix domain socket address, this tag + is optional, and an empty secret will be used if it is not + specified. Otherwise, this tag is required. + +**timeout** + An integer which specifies the time in seconds during which the + KDC should attempt to contact the RADIUS server. This tag is the + total time across all retries and should be less than the time + which an OTP value remains valid for. The default is 5 seconds. + +**retries** + This tag specifies the number of retries to make to the RADIUS + server. The default is 3 retries (4 tries). + +**strip_realm** + If this tag is ``true``, the principal without the realm will be + passed to the RADIUS server. Otherwise, the realm will be + included. The default value is ``true``. + +**indicator** + This tag specifies an authentication indicator to be included in + the ticket if this token type is used to authenticate. This + option may be specified multiple times. (New in release 1.14.) + +In the following example, requests are sent to a remote server via UDP:: + + [otp] + MyRemoteTokenType = { + server = radius.mydomain.com:1812 + secret = SEmfiajf42$ + timeout = 15 + retries = 5 + strip_realm = true + } + +An implicit default token type named ``DEFAULT`` is defined for when +the per-principal configuration does not specify a token type. Its +configuration is shown below. You may override this token type to +something applicable for your situation:: + + [otp] + DEFAULT = { + strip_realm = false + } + +PKINIT options +-------------- + +.. note:: + + The following are pkinit-specific options. These values may + be specified in [kdcdefaults] as global defaults, or within + a realm-specific subsection of [realms]. Also note that a + realm-specific value over-rides, does not add to, a generic + [kdcdefaults] specification. The search order is: + +1. realm-specific subsection of [realms]:: + + [realms] + EXAMPLE.COM = { + pkinit_anchors = FILE:/usr/local/example.com.crt + } + +2. generic value in the [kdcdefaults] section:: + + [kdcdefaults] + pkinit_anchors = DIR:/usr/local/generic_trusted_cas/ + +For information about the syntax of some of these options, see +:ref:`Specifying PKINIT identity information ` in +:ref:`krb5.conf(5)`. + +**pkinit_anchors** + Specifies the location of trusted anchor (root) certificates which + the KDC trusts to sign client certificates. This option is + required if pkinit is to be supported by the KDC. This option may + be specified multiple times. + +**pkinit_dh_min_bits** + Specifies the minimum number of bits the KDC is willing to accept + for a client's Diffie-Hellman key. The default is 2048. + +**pkinit_allow_upn** + Specifies that the KDC is willing to accept client certificates + with the Microsoft UserPrincipalName (UPN) Subject Alternative + Name (SAN). This means the KDC accepts the binding of the UPN in + the certificate to the Kerberos principal name. The default value + is false. + + Without this option, the KDC will only accept certificates with + the id-pkinit-san as defined in :rfc:`4556`. There is currently + no option to disable SAN checking in the KDC. + +**pkinit_eku_checking** + This option specifies what Extended Key Usage (EKU) values the KDC + is willing to accept in client certificates. The values + recognized in the kdc.conf file are: + + **kpClientAuth** + This is the default value and specifies that client + certificates must have the id-pkinit-KPClientAuth EKU as + defined in :rfc:`4556`. + + **scLogin** + If scLogin is specified, client certificates with the + Microsoft Smart Card Login EKU (id-ms-kp-sc-logon) will be + accepted. + + **none** + If none is specified, then client certificates will not be + checked to verify they have an acceptable EKU. The use of + this option is not recommended. + +**pkinit_identity** + Specifies the location of the KDC's X.509 identity information. + This option is required if pkinit is to be supported by the KDC. + +**pkinit_indicator** + Specifies an authentication indicator to include in the ticket if + pkinit is used to authenticate. This option may be specified + multiple times. (New in release 1.14.) + +**pkinit_pool** + Specifies the location of intermediate certificates which may be + used by the KDC to complete the trust chain between a client's + certificate and a trusted anchor. This option may be specified + multiple times. + +**pkinit_revoke** + Specifies the location of Certificate Revocation List (CRL) + information to be used by the KDC when verifying the validity of + client certificates. This option may be specified multiple times. + +**pkinit_require_crl_checking** + The default certificate verification process will always check the + available revocation information to see if a certificate has been + revoked. If a match is found for the certificate in a CRL, + verification fails. If the certificate being verified is not + listed in a CRL, or there is no CRL present for its issuing CA, + and **pkinit_require_crl_checking** is false, then verification + succeeds. + + However, if **pkinit_require_crl_checking** is true and there is + no CRL information available for the issuing CA, then verification + fails. + + **pkinit_require_crl_checking** should be set to true if the + policy is such that up-to-date CRLs must be present for every CA. + +**pkinit_require_freshness** + Specifies whether to require clients to include a freshness token + in PKINIT requests. The default value is false. (New in release + 1.17.) + +.. _Encryption_types: + +Encryption types +---------------- + +Any tag in the configuration files which requires a list of encryption +types can be set to some combination of the following strings. +Encryption types marked as "weak" and "deprecated" are available for +compatibility but not recommended for use. + +==================================================== ========================================================= +des3-cbc-raw Triple DES cbc mode raw (weak) +des3-cbc-sha1 des3-hmac-sha1 des3-cbc-sha1-kd Triple DES cbc mode with HMAC/sha1 (deprecated) +aes256-cts-hmac-sha1-96 aes256-cts aes256-sha1 AES-256 CTS mode with 96-bit SHA-1 HMAC +aes128-cts-hmac-sha1-96 aes128-cts aes128-sha1 AES-128 CTS mode with 96-bit SHA-1 HMAC +aes256-cts-hmac-sha384-192 aes256-sha2 AES-256 CTS mode with 192-bit SHA-384 HMAC +aes128-cts-hmac-sha256-128 aes128-sha2 AES-128 CTS mode with 128-bit SHA-256 HMAC +arcfour-hmac rc4-hmac arcfour-hmac-md5 RC4 with HMAC/MD5 (deprecated) +arcfour-hmac-exp rc4-hmac-exp arcfour-hmac-md5-exp Exportable RC4 with HMAC/MD5 (weak) +camellia256-cts-cmac camellia256-cts Camellia-256 CTS mode with CMAC +camellia128-cts-cmac camellia128-cts Camellia-128 CTS mode with CMAC +des3 The triple DES family: des3-cbc-sha1 +aes The AES family: aes256-cts-hmac-sha1-96, aes128-cts-hmac-sha1-96, aes256-cts-hmac-sha384-192, and aes128-cts-hmac-sha256-128 +rc4 The RC4 family: arcfour-hmac +camellia The Camellia family: camellia256-cts-cmac and camellia128-cts-cmac +==================================================== ========================================================= + +The string **DEFAULT** can be used to refer to the default set of +types for the variable in question. Types or families can be removed +from the current list by prefixing them with a minus sign ("-"). +Types or families can be prefixed with a plus sign ("+") for symmetry; +it has the same meaning as just listing the type or family. For +example, "``DEFAULT -rc4``" would be the default set of encryption +types with RC4 types removed, and "``des3 DEFAULT``" would be the +default set of encryption types with triple DES types moved to the +front. + +While **aes128-cts** and **aes256-cts** are supported for all Kerberos +operations, they are not supported by very old versions of our GSSAPI +implementation (krb5-1.3.1 and earlier). Services running versions of +krb5 without AES support must not be given keys of these encryption +types in the KDC database. + +The **aes128-sha2** and **aes256-sha2** encryption types are new in +release 1.15. Services running versions of krb5 without support for +these newer encryption types must not be given keys of these +encryption types in the KDC database. + + +.. _Keysalt_lists: + +Keysalt lists +------------- + +Kerberos keys for users are usually derived from passwords. Kerberos +commands and configuration parameters that affect generation of keys +take lists of enctype-salttype ("keysalt") pairs, known as *keysalt +lists*. Each keysalt pair is an enctype name followed by a salttype +name, in the format *enc*:*salt*. Individual keysalt list members are +separated by comma (",") characters or space characters. For example:: + + kadmin -e aes256-cts:normal,aes128-cts:normal + +would start up kadmin so that by default it would generate +password-derived keys for the **aes256-cts** and **aes128-cts** +encryption types, using a **normal** salt. + +To ensure that people who happen to pick the same password do not have +the same key, Kerberos 5 incorporates more information into the key +using something called a salt. The supported salt types are as +follows: + +================= ============================================ +normal default for Kerberos Version 5 +norealm same as the default, without using realm information +onlyrealm uses only realm information as the salt +special generate a random salt +================= ============================================ + + +Sample kdc.conf File +-------------------- + +Here's an example of a kdc.conf file:: + + [kdcdefaults] + kdc_listen = 88 + kdc_tcp_listen = 88 + [realms] + ATHENA.MIT.EDU = { + kadmind_port = 749 + max_life = 12h 0m 0s + max_renewable_life = 7d 0h 0m 0s + master_key_type = aes256-cts-hmac-sha1-96 + supported_enctypes = aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal + database_module = openldap_ldapconf + } + + [logging] + kdc = FILE:/usr/local/var/krb5kdc/kdc.log + admin_server = FILE:/usr/local/var/krb5kdc/kadmin.log + + [dbdefaults] + ldap_kerberos_container_dn = cn=krbcontainer,dc=mit,dc=edu + + [dbmodules] + openldap_ldapconf = { + db_library = kldap + disable_last_success = true + ldap_kdc_dn = "cn=krbadmin,dc=mit,dc=edu" + # this object needs to have read rights on + # the realm container and principal subtrees + ldap_kadmind_dn = "cn=krbadmin,dc=mit,dc=edu" + # this object needs to have read and write rights on + # the realm container and principal subtrees + ldap_service_password_file = /etc/kerberos/service.keyfile + ldap_servers = ldaps://kerberos.mit.edu + ldap_conns_per_server = 5 + } + + +FILES +------ + +|kdcdir|\ ``/kdc.conf`` + + +SEE ALSO +--------- + +:ref:`krb5.conf(5)`, :ref:`krb5kdc(8)`, :ref:`kadm5.acl(5)` diff --git a/krb5-1.21.3/doc/html/_sources/admin/conf_files/krb5_conf.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/conf_files/krb5_conf.rst.txt new file mode 100644 index 00000000..ecdf9175 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/conf_files/krb5_conf.rst.txt @@ -0,0 +1,1251 @@ +.. _krb5.conf(5): + +krb5.conf +========= + +The krb5.conf file contains Kerberos configuration information, +including the locations of KDCs and admin servers for the Kerberos +realms of interest, defaults for the current realm and for Kerberos +applications, and mappings of hostnames onto Kerberos realms. +Normally, you should install your krb5.conf file in the directory +``/etc``. You can override the default location by setting the +environment variable **KRB5_CONFIG**. Multiple colon-separated +filenames may be specified in **KRB5_CONFIG**; all files which are +present will be read. Starting in release 1.14, directory names can +also be specified in **KRB5_CONFIG**; all files within the directory +whose names consist solely of alphanumeric characters, dashes, or +underscores will be read. + + +Structure +--------- + +The krb5.conf file is set up in the style of a Windows INI file. +Lines beginning with '#' or ';' (possibly after initial whitespace) +are ignored as comments. Sections are headed by the section name, in +square brackets. Each section may contain zero or more relations, of +the form:: + + foo = bar + +or:: + + fubar = { + foo = bar + baz = quux + } + +Placing a '\*' after the closing bracket of a section name indicates +that the section is *final*, meaning that if the same section appears +within a later file specified in **KRB5_CONFIG**, it will be ignored. +A subsection can be marked as final by placing a '\*' after either the +tag name or the closing brace. + +The krb5.conf file can include other files using either of the +following directives at the beginning of a line:: + + include FILENAME + includedir DIRNAME + +*FILENAME* or *DIRNAME* should be an absolute path. The named file or +directory must exist and be readable. Including a directory includes +all files within the directory whose names consist solely of +alphanumeric characters, dashes, or underscores. Starting in release +1.15, files with names ending in ".conf" are also included, unless the +name begins with ".". Included profile files are syntactically +independent of their parents, so each included file must begin with a +section header. Starting in release 1.17, files are read in +alphanumeric order; in previous releases, they may be read in any +order. + +The krb5.conf file can specify that configuration should be obtained +from a loadable module, rather than the file itself, using the +following directive at the beginning of a line before any section +headers:: + + module MODULEPATH:RESIDUAL + +*MODULEPATH* may be relative to the library path of the krb5 +installation, or it may be an absolute path. *RESIDUAL* is provided +to the module at initialization time. If krb5.conf uses a module +directive, :ref:`kdc.conf(5)` should also use one if it exists. + + +Sections +-------- + +The krb5.conf file may contain the following sections: + +=================== ======================================================= +:ref:`libdefaults` Settings used by the Kerberos V5 library +:ref:`realms` Realm-specific contact information and settings +:ref:`domain_realm` Maps server hostnames to Kerberos realms +:ref:`capaths` Authentication paths for non-hierarchical cross-realm +:ref:`appdefaults` Settings used by some Kerberos V5 applications +:ref:`plugins` Controls plugin module registration +=================== ======================================================= + +Additionally, krb5.conf may include any of the relations described in +:ref:`kdc.conf(5)`, but it is not a recommended practice. + +.. _libdefaults: + +[libdefaults] +~~~~~~~~~~~~~ + +The libdefaults section may contain any of the following relations: + +**allow_des3** + Permit the KDC to issue tickets with des3-cbc-sha1 session keys. + In future releases, this flag will allow des3-cbc-sha1 to be used + at all. The default value for this tag is false. (Added in + release 1.21.) + +**allow_rc4** + Permit the KDC to issue tickets with arcfour-hmac session keys. + In future releases, this flag will allow arcfour-hmac to be used + at all. The default value for this tag is false. (Added in + release 1.21.) + +**allow_weak_crypto** + If this flag is set to false, then weak encryption types (as noted + in :ref:`Encryption_types` in :ref:`kdc.conf(5)`) will be filtered + out of the lists **default_tgs_enctypes**, + **default_tkt_enctypes**, and **permitted_enctypes**. The default + value for this tag is false. + +**canonicalize** + If this flag is set to true, initial ticket requests to the KDC + will request canonicalization of the client principal name, and + answers with different client principals than the requested + principal will be accepted. The default value is false. + +**ccache_type** + This parameter determines the format of credential cache types + created by :ref:`kinit(1)` or other programs. The default value + is 4, which represents the most current format. Smaller values + can be used for compatibility with very old implementations of + Kerberos which interact with credential caches on the same host. + +**clockskew** + Sets the maximum allowable amount of clockskew in seconds that the + library will tolerate before assuming that a Kerberos message is + invalid. The default value is 300 seconds, or five minutes. + + The clockskew setting is also used when evaluating ticket start + and expiration times. For example, tickets that have reached + their expiration time can still be used (and renewed if they are + renewable tickets) if they have been expired for a shorter + duration than the **clockskew** setting. + +**default_ccache_name** + This relation specifies the name of the default credential cache. + The default is |ccache|. This relation is subject to parameter + expansion (see below). New in release 1.11. + +**default_client_keytab_name** + This relation specifies the name of the default keytab for + obtaining client credentials. The default is |ckeytab|. This + relation is subject to parameter expansion (see below). + New in release 1.11. + +**default_keytab_name** + This relation specifies the default keytab name to be used by + application servers such as sshd. The default is |keytab|. This + relation is subject to parameter expansion (see below). + +**default_rcache_name** + This relation specifies the name of the default replay cache. + The default is ``dfl:``. This relation is subject to parameter + expansion (see below). New in release 1.18. + +**default_realm** + Identifies the default Kerberos realm for the client. Set its + value to your Kerberos realm. If this value is not set, then a + realm must be specified with every Kerberos principal when + invoking programs such as :ref:`kinit(1)`. + +**default_tgs_enctypes** + Identifies the supported list of session key encryption types that + the client should request when making a TGS-REQ, in order of + preference from highest to lowest. The list may be delimited with + commas or whitespace. See :ref:`Encryption_types` in + :ref:`kdc.conf(5)` for a list of the accepted values for this tag. + Starting in release 1.18, the default value is the value of + **permitted_enctypes**. For previous releases or if + **permitted_enctypes** is not set, the default value is + |defetypes|. + + Do not set this unless required for specific backward + compatibility purposes; stale values of this setting can prevent + clients from taking advantage of new stronger enctypes when the + libraries are upgraded. + +**default_tkt_enctypes** + Identifies the supported list of session key encryption types that + the client should request when making an AS-REQ, in order of + preference from highest to lowest. The format is the same as for + default_tgs_enctypes. Starting in release 1.18, the default + value is the value of **permitted_enctypes**. For previous + releases or if **permitted_enctypes** is not set, the default + value is |defetypes|. + + Do not set this unless required for specific backward + compatibility purposes; stale values of this setting can prevent + clients from taking advantage of new stronger enctypes when the + libraries are upgraded. + +**dns_canonicalize_hostname** + Indicate whether name lookups will be used to canonicalize + hostnames for use in service principal names. Setting this flag + to false can improve security by reducing reliance on DNS, but + means that short hostnames will not be canonicalized to + fully-qualified hostnames. If this option is set to ``fallback`` (new + in release 1.18), DNS canonicalization will only be performed the + server hostname is not found with the original name when + requesting credentials. The default value is true. + +**dns_lookup_kdc** + Indicate whether DNS SRV records should be used to locate the KDCs + and other servers for a realm, if they are not listed in the + krb5.conf information for the realm. (Note that the admin_server + entry must be in the krb5.conf realm information in order to + contact kadmind, because the DNS implementation for kadmin is + incomplete.) + + Enabling this option does open up a type of denial-of-service + attack, if someone spoofs the DNS records and redirects you to + another server. However, it's no worse than a denial of service, + because that fake KDC will be unable to decode anything you send + it (besides the initial ticket request, which has no encrypted + data), and anything the fake KDC sends will not be trusted without + verification using some secret that it won't know. + +**dns_uri_lookup** + Indicate whether DNS URI records should be used to locate the KDCs + and other servers for a realm, if they are not listed in the + krb5.conf information for the realm. SRV records are used as a + fallback if no URI records were found. The default value is true. + New in release 1.15. + +**enforce_ok_as_delegate** + If this flag to true, GSSAPI credential delegation will be + disabled when the ``ok-as-delegate`` flag is not set in the + service ticket. If this flag is false, the ``ok-as-delegate`` + ticket flag is only enforced when an application specifically + requests enforcement. The default value is false. + +**err_fmt** + This relation allows for custom error message formatting. If a + value is set, error messages will be formatted by substituting a + normal error message for %M and an error code for %C in the value. + +**extra_addresses** + This allows a computer to use multiple local addresses, in order + to allow Kerberos to work in a network that uses NATs while still + using address-restricted tickets. The addresses should be in a + comma-separated list. This option has no effect if + **noaddresses** is true. + +**forwardable** + If this flag is true, initial tickets will be forwardable by + default, if allowed by the KDC. The default value is false. + +**ignore_acceptor_hostname** + When accepting GSSAPI or krb5 security contexts for host-based + service principals, ignore any hostname passed by the calling + application, and allow clients to authenticate to any service + principal in the keytab matching the service name and realm name + (if given). This option can improve the administrative + flexibility of server applications on multihomed hosts, but could + compromise the security of virtual hosting environments. The + default value is false. New in release 1.10. + +**k5login_authoritative** + If this flag is true, principals must be listed in a local user's + k5login file to be granted login access, if a :ref:`.k5login(5)` + file exists. If this flag is false, a principal may still be + granted login access through other mechanisms even if a k5login + file exists but does not list the principal. The default value is + true. + +**k5login_directory** + If set, the library will look for a local user's k5login file + within the named directory, with a filename corresponding to the + local username. If not set, the library will look for k5login + files in the user's home directory, with the filename .k5login. + For security reasons, .k5login files must be owned by + the local user or by root. + +**kcm_mach_service** + On macOS only, determines the name of the bootstrap service used to + contact the KCM daemon for the KCM credential cache type. If the + value is ``-``, Mach RPC will not be used to contact the KCM + daemon. The default value is ``org.h5l.kcm``. + +**kcm_socket** + Determines the path to the Unix domain socket used to access the + KCM daemon for the KCM credential cache type. If the value is + ``-``, Unix domain sockets will not be used to contact the KCM + daemon. The default value is + ``/var/run/.heim_org.h5l.kcm-socket``. + +**kdc_default_options** + Default KDC options (Xored for multiple values) when requesting + initial tickets. By default it is set to 0x00000010 + (KDC_OPT_RENEWABLE_OK). + +**kdc_timesync** + Accepted values for this relation are 1 or 0. If it is nonzero, + client machines will compute the difference between their time and + the time returned by the KDC in the timestamps in the tickets and + use this value to correct for an inaccurate system clock when + requesting service tickets or authenticating to services. This + corrective factor is only used by the Kerberos library; it is not + used to change the system clock. The default value is 1. + +**noaddresses** + If this flag is true, requests for initial tickets will not be + made with address restrictions set, allowing the tickets to be + used across NATs. The default value is true. + +**permitted_enctypes** + Identifies the encryption types that servers will permit for + session keys and for ticket and authenticator encryption, ordered + by preference from highest to lowest. Starting in release 1.18, + this tag also acts as the default value for + **default_tgs_enctypes** and **default_tkt_enctypes**. The + default value for this tag is |defetypes|. + +**plugin_base_dir** + If set, determines the base directory where krb5 plugins are + located. The default value is the ``krb5/plugins`` subdirectory + of the krb5 library directory. This relation is subject to + parameter expansion (see below) in release 1.17 and later. + +**preferred_preauth_types** + This allows you to set the preferred preauthentication types which + the client will attempt before others which may be advertised by a + KDC. The default value for this setting is "17, 16, 15, 14", + which forces libkrb5 to attempt to use PKINIT if it is supported. + +**proxiable** + If this flag is true, initial tickets will be proxiable by + default, if allowed by the KDC. The default value is false. + +**qualify_shortname** + If this string is set, it determines the domain suffix for + single-component hostnames when DNS canonicalization is not used + (either because **dns_canonicalize_hostname** is false or because + forward canonicalization failed). The default value is the first + search domain of the system's DNS configuration. To disable + qualification of shortnames, set this relation to the empty string + with ``qualify_shortname = ""``. (New in release 1.18.) + +**rdns** + If this flag is true, reverse name lookup will be used in addition + to forward name lookup to canonicalizing hostnames for use in + service principal names. If **dns_canonicalize_hostname** is set + to false, this flag has no effect. The default value is true. + +**realm_try_domains** + Indicate whether a host's domain components should be used to + determine the Kerberos realm of the host. The value of this + variable is an integer: -1 means not to search, 0 means to try the + host's domain itself, 1 means to also try the domain's immediate + parent, and so forth. The library's usual mechanism for locating + Kerberos realms is used to determine whether a domain is a valid + realm, which may involve consulting DNS if **dns_lookup_kdc** is + set. The default is not to search domain components. + +**renew_lifetime** + (:ref:`duration` string.) Sets the default renewable lifetime + for initial ticket requests. The default value is 0. + +**spake_preauth_groups** + A whitespace or comma-separated list of words which specifies the + groups allowed for SPAKE preauthentication. The possible values + are: + + ============ ================================ + edwards25519 Edwards25519 curve (:rfc:`7748`) + P-256 NIST P-256 curve (:rfc:`5480`) + P-384 NIST P-384 curve (:rfc:`5480`) + P-521 NIST P-521 curve (:rfc:`5480`) + ============ ================================ + + The default value for the client is ``edwards25519``. The default + value for the KDC is empty. New in release 1.17. + +**ticket_lifetime** + (:ref:`duration` string.) Sets the default lifetime for initial + ticket requests. The default value is 1 day. + +**udp_preference_limit** + When sending a message to the KDC, the library will try using TCP + before UDP if the size of the message is above + **udp_preference_limit**. If the message is smaller than + **udp_preference_limit**, then UDP will be tried before TCP. + Regardless of the size, both protocols will be tried if the first + attempt fails. + +**verify_ap_req_nofail** + If this flag is true, then an attempt to verify initial + credentials will fail if the client machine does not have a + keytab. The default value is false. + +**client_aware_channel_bindings** + If this flag is true, then all application protocol authentication + requests will be flagged to indicate that the application supports + channel bindings when operating over a secure channel. The + default value is false. + +.. _realms: + +[realms] +~~~~~~~~ + +Each tag in the [realms] section of the file is the name of a Kerberos +realm. The value of the tag is a subsection with relations that +define the properties of that particular realm. For each realm, the +following tags may be specified in the realm's subsection: + +**admin_server** + Identifies the host where the administration server is running. + Typically, this is the primary Kerberos server. This tag must be + given a value in order to communicate with the :ref:`kadmind(8)` + server for the realm. + +**auth_to_local** + This tag allows you to set a general rule for mapping principal + names to local user names. It will be used if there is not an + explicit mapping for the principal name that is being + translated. The possible values are: + + **RULE:**\ *exp* + The local name will be formulated from *exp*. + + The format for *exp* is **[**\ *n*\ **:**\ *string*\ **](**\ + *regexp*\ **)s/**\ *pattern*\ **/**\ *replacement*\ **/g**. + The integer *n* indicates how many components the target + principal should have. If this matches, then a string will be + formed from *string*, substituting the realm of the principal + for ``$0`` and the *n*'th component of the principal for + ``$n`` (e.g., if the principal was ``johndoe/admin`` then + ``[2:$2$1foo]`` would result in the string + ``adminjohndoefoo``). If this string matches *regexp*, then + the ``s//[g]`` substitution command will be run over the + string. The optional **g** will cause the substitution to be + global over the *string*, instead of replacing only the first + match in the *string*. + + **DEFAULT** + The principal name will be used as the local user name. If + the principal has more than one component or is not in the + default realm, this rule is not applicable and the conversion + will fail. + + For example:: + + [realms] + ATHENA.MIT.EDU = { + auth_to_local = RULE:[2:$1](johndoe)s/^.*$/guest/ + auth_to_local = RULE:[2:$1;$2](^.*;admin$)s/;admin$// + auth_to_local = RULE:[2:$2](^.*;root)s/^.*$/root/ + auth_to_local = DEFAULT + } + + would result in any principal without ``root`` or ``admin`` as the + second component to be translated with the default rule. A + principal with a second component of ``admin`` will become its + first component. ``root`` will be used as the local name for any + principal with a second component of ``root``. The exception to + these two rules are any principals ``johndoe/*``, which will + always get the local name ``guest``. + +**auth_to_local_names** + This subsection allows you to set explicit mappings from principal + names to local user names. The tag is the mapping name, and the + value is the corresponding local user name. + +**default_domain** + This tag specifies the domain used to expand hostnames when + translating Kerberos 4 service principals to Kerberos 5 principals + (for example, when converting ``rcmd.hostname`` to + ``host/hostname.domain``). + +**disable_encrypted_timestamp** + If this flag is true, the client will not perform encrypted + timestamp preauthentication if requested by the KDC. Setting this + flag can help to prevent dictionary attacks by active attackers, + if the realm's KDCs support SPAKE preauthentication or if initial + authentication always uses another mechanism or always uses FAST. + This flag persists across client referrals during initial + authentication. This flag does not prevent the KDC from offering + encrypted timestamp. New in release 1.17. + +**http_anchors** + When KDCs and kpasswd servers are accessed through HTTPS proxies, this tag + can be used to specify the location of the CA certificate which should be + trusted to issue the certificate for a proxy server. If left unspecified, + the system-wide default set of CA certificates is used. + + The syntax for values is similar to that of values for the + **pkinit_anchors** tag: + + **FILE:** *filename* + + *filename* is assumed to be the name of an OpenSSL-style ca-bundle file. + + **DIR:** *dirname* + + *dirname* is assumed to be an directory which contains CA certificates. + All files in the directory will be examined; if they contain certificates + (in PEM format), they will be used. + + **ENV:** *envvar* + + *envvar* specifies the name of an environment variable which has been set + to a value conforming to one of the previous values. For example, + ``ENV:X509_PROXY_CA``, where environment variable ``X509_PROXY_CA`` has + been set to ``FILE:/tmp/my_proxy.pem``. + +**kdc** + The name or address of a host running a KDC for that realm. An + optional port number, separated from the hostname by a colon, may + be included. If the name or address contains colons (for example, + if it is an IPv6 address), enclose it in square brackets to + distinguish the colon from a port separator. For your computer to + be able to communicate with the KDC for each realm, this tag must + be given a value in each realm subsection in the configuration + file, or there must be DNS SRV records specifying the KDCs. + +**kpasswd_server** + Points to the server where all the password changes are performed. + If there is no such entry, DNS will be queried (unless forbidden + by **dns_lookup_kdc**). Finally, port 464 on the **admin_server** + host will be tried. + +**master_kdc** + The name for **primary_kdc** prior to release 1.19. Its value is + used as a fallback if **primary_kdc** is not specified. + +**primary_kdc** + Identifies the primary KDC(s). Currently, this tag is used in only + one case: If an attempt to get credentials fails because of an + invalid password, the client software will attempt to contact the + primary KDC, in case the user's password has just been changed, and + the updated database has not been propagated to the replica + servers yet. New in release 1.19. + +**v4_instance_convert** + This subsection allows the administrator to configure exceptions + to the **default_domain** mapping rule. It contains V4 instances + (the tag name) which should be translated to some specific + hostname (the tag value) as the second component in a Kerberos V5 + principal name. + +**v4_realm** + This relation is used by the krb524 library routines when + converting a V5 principal name to a V4 principal name. It is used + when the V4 realm name and the V5 realm name are not the same, but + still share the same principal names and passwords. The tag value + is the Kerberos V4 realm name. + + +.. _domain_realm: + +[domain_realm] +~~~~~~~~~~~~~~ + +The [domain_realm] section provides a translation from hostnames to +Kerberos realms. Each tag is a domain name, providing the mapping for +that domain and all subdomains. If the tag begins with a period +(``.``) then it applies only to subdomains. The Kerberos realm may be +identified either in the realms_ section or using DNS SRV records. +Tag names should be in lower case. For example:: + + [domain_realm] + crash.mit.edu = TEST.ATHENA.MIT.EDU + .dev.mit.edu = TEST.ATHENA.MIT.EDU + mit.edu = ATHENA.MIT.EDU + +maps the host with the name ``crash.mit.edu`` into the +``TEST.ATHENA.MIT.EDU`` realm. The second entry maps all hosts under the +domain ``dev.mit.edu`` into the ``TEST.ATHENA.MIT.EDU`` realm, but not +the host with the name ``dev.mit.edu``. That host is matched +by the third entry, which maps the host ``mit.edu`` and all hosts +under the domain ``mit.edu`` that do not match a preceding rule +into the realm ``ATHENA.MIT.EDU``. + +If no translation entry applies to a hostname used for a service +principal for a service ticket request, the library will try to get a +referral to the appropriate realm from the client realm's KDC. If +that does not succeed, the host's realm is considered to be the +hostname's domain portion converted to uppercase, unless the +**realm_try_domains** setting in [libdefaults] causes a different +parent domain to be used. + + +.. _capaths: + +[capaths] +~~~~~~~~~ + +In order to perform direct (non-hierarchical) cross-realm +authentication, configuration is needed to determine the +authentication paths between realms. + +A client will use this section to find the authentication path between +its realm and the realm of the server. The server will use this +section to verify the authentication path used by the client, by +checking the transited field of the received ticket. + +There is a tag for each participating client realm, and each tag has +subtags for each of the server realms. The value of the subtags is an +intermediate realm which may participate in the cross-realm +authentication. The subtags may be repeated if there is more then one +intermediate realm. A value of "." means that the two realms share +keys directly, and no intermediate realms should be allowed to +participate. + +Only those entries which will be needed on the client or the server +need to be present. A client needs a tag for its local realm with +subtags for all the realms of servers it will need to authenticate to. +A server needs a tag for each realm of the clients it will serve, with +a subtag of the server realm. + +For example, ``ANL.GOV``, ``PNL.GOV``, and ``NERSC.GOV`` all wish to +use the ``ES.NET`` realm as an intermediate realm. ANL has a sub +realm of ``TEST.ANL.GOV`` which will authenticate with ``NERSC.GOV`` +but not ``PNL.GOV``. The [capaths] section for ``ANL.GOV`` systems +would look like this:: + + [capaths] + ANL.GOV = { + TEST.ANL.GOV = . + PNL.GOV = ES.NET + NERSC.GOV = ES.NET + ES.NET = . + } + TEST.ANL.GOV = { + ANL.GOV = . + } + PNL.GOV = { + ANL.GOV = ES.NET + } + NERSC.GOV = { + ANL.GOV = ES.NET + } + ES.NET = { + ANL.GOV = . + } + +The [capaths] section of the configuration file used on ``NERSC.GOV`` +systems would look like this:: + + [capaths] + NERSC.GOV = { + ANL.GOV = ES.NET + TEST.ANL.GOV = ES.NET + TEST.ANL.GOV = ANL.GOV + PNL.GOV = ES.NET + ES.NET = . + } + ANL.GOV = { + NERSC.GOV = ES.NET + } + PNL.GOV = { + NERSC.GOV = ES.NET + } + ES.NET = { + NERSC.GOV = . + } + TEST.ANL.GOV = { + NERSC.GOV = ANL.GOV + NERSC.GOV = ES.NET + } + +When a subtag is used more than once within a tag, clients will use +the order of values to determine the path. The order of values is not +important to servers. + + +.. _appdefaults: + +[appdefaults] +~~~~~~~~~~~~~ + +Each tag in the [appdefaults] section names a Kerberos V5 application +or an option that is used by some Kerberos V5 application[s]. The +value of the tag defines the default behaviors for that application. + +For example:: + + [appdefaults] + telnet = { + ATHENA.MIT.EDU = { + option1 = false + } + } + telnet = { + option1 = true + option2 = true + } + ATHENA.MIT.EDU = { + option2 = false + } + option2 = true + +The above four ways of specifying the value of an option are shown in +order of decreasing precedence. In this example, if telnet is running +in the realm EXAMPLE.COM, it should, by default, have option1 and +option2 set to true. However, a telnet program in the realm +``ATHENA.MIT.EDU`` should have ``option1`` set to false and +``option2`` set to true. Any other programs in ATHENA.MIT.EDU should +have ``option2`` set to false by default. Any programs running in +other realms should have ``option2`` set to true. + +The list of specifiable options for each application may be found in +that application's man pages. The application defaults specified here +are overridden by those specified in the realms_ section. + + +.. _plugins: + +[plugins] +~~~~~~~~~ + + * pwqual_ interface + * kadm5_hook_ interface + * clpreauth_ and kdcpreauth_ interfaces + +Tags in the [plugins] section can be used to register dynamic plugin +modules and to turn modules on and off. Not every krb5 pluggable +interface uses the [plugins] section; the ones that do are documented +here. + +New in release 1.9. + +Each pluggable interface corresponds to a subsection of [plugins]. +All subsections support the same tags: + +**disable** + This tag may have multiple values. If there are values for this + tag, then the named modules will be disabled for the pluggable + interface. + +**enable_only** + This tag may have multiple values. If there are values for this + tag, then only the named modules will be enabled for the pluggable + interface. + +**module** + This tag may have multiple values. Each value is a string of the + form ``modulename:pathname``, which causes the shared object + located at *pathname* to be registered as a dynamic module named + *modulename* for the pluggable interface. If *pathname* is not an + absolute path, it will be treated as relative to the + **plugin_base_dir** value from :ref:`libdefaults`. + +For pluggable interfaces where module order matters, modules +registered with a **module** tag normally come first, in the order +they are registered, followed by built-in modules in the order they +are documented below. If **enable_only** tags are used, then the +order of those tags overrides the normal module order. + +The following subsections are currently supported within the [plugins] +section: + +.. _ccselect: + +ccselect interface +################## + +The ccselect subsection controls modules for credential cache +selection within a cache collection. In addition to any registered +dynamic modules, the following built-in modules exist (and may be +disabled with the disable tag): + +**k5identity** + Uses a .k5identity file in the user's home directory to select a + client principal + +**realm** + Uses the service realm to guess an appropriate cache from the + collection + +**hostname** + If the service principal is host-based, uses the service hostname + to guess an appropriate cache from the collection + +.. _pwqual: + +pwqual interface +################ + +The pwqual subsection controls modules for the password quality +interface, which is used to reject weak passwords when passwords are +changed. The following built-in modules exist for this interface: + +**dict** + Checks against the realm dictionary file + +**empty** + Rejects empty passwords + +**hesiod** + Checks against user information stored in Hesiod (only if Kerberos + was built with Hesiod support) + +**princ** + Checks against components of the principal name + +.. _kadm5_hook: + +kadm5_hook interface +#################### + +The kadm5_hook interface provides plugins with information on +principal creation, modification, password changes and deletion. This +interface can be used to write a plugin to synchronize MIT Kerberos +with another database such as Active Directory. No plugins are built +in for this interface. + +.. _kadm5_auth: + +kadm5_auth interface +#################### + +The kadm5_auth section (introduced in release 1.16) controls modules +for the kadmin authorization interface, which determines whether a +client principal is allowed to perform a kadmin operation. The +following built-in modules exist for this interface: + +**acl** + This module reads the :ref:`kadm5.acl(5)` file, and authorizes + operations which are allowed according to the rules in the file. + +**self** + This module authorizes self-service operations including password + changes, creation of new random keys, fetching the client's + principal record or string attributes, and fetching the policy + record associated with the client principal. + +.. _clpreauth: + +.. _kdcpreauth: + +clpreauth and kdcpreauth interfaces +################################### + +The clpreauth and kdcpreauth interfaces allow plugin modules to +provide client and KDC preauthentication mechanisms. The following +built-in modules exist for these interfaces: + +**pkinit** + This module implements the PKINIT preauthentication mechanism. + +**encrypted_challenge** + This module implements the encrypted challenge FAST factor. + +**encrypted_timestamp** + This module implements the encrypted timestamp mechanism. + +.. _hostrealm: + +hostrealm interface +################### + +The hostrealm section (introduced in release 1.12) controls modules +for the host-to-realm interface, which affects the local mapping of +hostnames to realm names and the choice of default realm. The following +built-in modules exist for this interface: + +**profile** + This module consults the [domain_realm] section of the profile for + authoritative host-to-realm mappings, and the **default_realm** + variable for the default realm. + +**dns** + This module looks for DNS records for fallback host-to-realm + mappings and the default realm. It only operates if the + **dns_lookup_realm** variable is set to true. + +**domain** + This module applies heuristics for fallback host-to-realm + mappings. It implements the **realm_try_domains** variable, and + uses the uppercased parent domain of the hostname if that does not + produce a result. + +.. _localauth: + +localauth interface +################### + +The localauth section (introduced in release 1.12) controls modules +for the local authorization interface, which affects the relationship +between Kerberos principals and local system accounts. The following +built-in modules exist for this interface: + +**default** + This module implements the **DEFAULT** type for **auth_to_local** + values. + +**rule** + This module implements the **RULE** type for **auth_to_local** + values. + +**names** + This module looks for an **auth_to_local_names** mapping for the + principal name. + +**auth_to_local** + This module processes **auth_to_local** values in the default + realm's section, and applies the default method if no + **auth_to_local** values exist. + +**k5login** + This module authorizes a principal to a local account according to + the account's :ref:`.k5login(5)` file. + +**an2ln** + This module authorizes a principal to a local account if the + principal name maps to the local account name. + +.. _certauth: + +certauth interface +################## + +The certauth section (introduced in release 1.16) controls modules for +the certificate authorization interface, which determines whether a +certificate is allowed to preauthenticate a user via PKINIT. The +following built-in modules exist for this interface: + +**pkinit_san** + This module authorizes the certificate if it contains a PKINIT + Subject Alternative Name for the requested client principal, or a + Microsoft UPN SAN matching the principal if **pkinit_allow_upn** + is set to true for the realm. + +**pkinit_eku** + This module rejects the certificate if it does not contain an + Extended Key Usage attribute consistent with the + **pkinit_eku_checking** value for the realm. + +**dbmatch** + This module authorizes or rejects the certificate according to + whether it matches the **pkinit_cert_match** string attribute on + the client principal, if that attribute is present. + + +PKINIT options +-------------- + +.. note:: + + The following are PKINIT-specific options. These values may + be specified in [libdefaults] as global defaults, or within + a realm-specific subsection of [libdefaults], or may be + specified as realm-specific values in the [realms] section. + A realm-specific value overrides, not adds to, a generic + [libdefaults] specification. The search order is: + +1. realm-specific subsection of [libdefaults]:: + + [libdefaults] + EXAMPLE.COM = { + pkinit_anchors = FILE:/usr/local/example.com.crt + } + +2. realm-specific value in the [realms] section:: + + [realms] + OTHERREALM.ORG = { + pkinit_anchors = FILE:/usr/local/otherrealm.org.crt + } + +3. generic value in the [libdefaults] section:: + + [libdefaults] + pkinit_anchors = DIR:/usr/local/generic_trusted_cas/ + + +.. _pkinit_identity: + +Specifying PKINIT identity information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The syntax for specifying Public Key identity, trust, and revocation +information for PKINIT is as follows: + +**FILE:**\ *filename*\ [**,**\ *keyfilename*] + This option has context-specific behavior. + + In **pkinit_identity** or **pkinit_identities**, *filename* + specifies the name of a PEM-format file containing the user's + certificate. If *keyfilename* is not specified, the user's + private key is expected to be in *filename* as well. Otherwise, + *keyfilename* is the name of the file containing the private key. + + In **pkinit_anchors** or **pkinit_pool**, *filename* is assumed to + be the name of an OpenSSL-style ca-bundle file. + +**DIR:**\ *dirname* + This option has context-specific behavior. + + In **pkinit_identity** or **pkinit_identities**, *dirname* + specifies a directory with files named ``*.crt`` and ``*.key`` + where the first part of the file name is the same for matching + pairs of certificate and private key files. When a file with a + name ending with ``.crt`` is found, a matching file ending with + ``.key`` is assumed to contain the private key. If no such file + is found, then the certificate in the ``.crt`` is not used. + + In **pkinit_anchors** or **pkinit_pool**, *dirname* is assumed to + be an OpenSSL-style hashed CA directory where each CA cert is + stored in a file named ``hash-of-ca-cert.#``. This infrastructure + is encouraged, but all files in the directory will be examined and + if they contain certificates (in PEM format), they will be used. + + In **pkinit_revoke**, *dirname* is assumed to be an OpenSSL-style + hashed CA directory where each revocation list is stored in a file + named ``hash-of-ca-cert.r#``. This infrastructure is encouraged, + but all files in the directory will be examined and if they + contain a revocation list (in PEM format), they will be used. + +**PKCS12:**\ *filename* + *filename* is the name of a PKCS #12 format file, containing the + user's certificate and private key. + +**PKCS11:**\ [**module_name=**]\ *modname*\ [**:slotid=**\ *slot-id*][**:token=**\ *token-label*][**:certid=**\ *cert-id*][**:certlabel=**\ *cert-label*] + All keyword/values are optional. *modname* specifies the location + of a library implementing PKCS #11. If a value is encountered + with no keyword, it is assumed to be the *modname*. If no + module-name is specified, the default is |pkcs11_modname|. + ``slotid=`` and/or ``token=`` may be specified to force the use of + a particular smard card reader or token if there is more than one + available. ``certid=`` and/or ``certlabel=`` may be specified to + force the selection of a particular certificate on the device. + See the **pkinit_cert_match** configuration option for more ways + to select a particular certificate to use for PKINIT. + +**ENV:**\ *envvar* + *envvar* specifies the name of an environment variable which has + been set to a value conforming to one of the previous values. For + example, ``ENV:X509_PROXY``, where environment variable + ``X509_PROXY`` has been set to ``FILE:/tmp/my_proxy.pem``. + + +PKINIT krb5.conf options +~~~~~~~~~~~~~~~~~~~~~~~~ + +**pkinit_anchors** + Specifies the location of trusted anchor (root) certificates which + the client trusts to sign KDC certificates. This option may be + specified multiple times. These values from the config file are + not used if the user specifies X509_anchors on the command line. + +**pkinit_cert_match** + Specifies matching rules that the client certificate must match + before it is used to attempt PKINIT authentication. If a user has + multiple certificates available (on a smart card, or via other + media), there must be exactly one certificate chosen before + attempting PKINIT authentication. This option may be specified + multiple times. All the available certificates are checked + against each rule in order until there is a match of exactly one + certificate. + + The Subject and Issuer comparison strings are the :rfc:`2253` + string representations from the certificate Subject DN and Issuer + DN values. + + The syntax of the matching rules is: + + [*relation-operator*\ ]\ *component-rule* ... + + where: + + *relation-operator* + can be either ``&&``, meaning all component rules must match, + or ``||``, meaning only one component rule must match. The + default is ``&&``. + + *component-rule* + can be one of the following. Note that there is no + punctuation or whitespace between component rules. + + | ****\ *regular-expression* + | ****\ *regular-expression* + | ****\ *regular-expression* + | ****\ *extended-key-usage-list* + | ****\ *key-usage-list* + + *extended-key-usage-list* is a comma-separated list of + required Extended Key Usage values. All values in the list + must be present in the certificate. Extended Key Usage values + can be: + + * pkinit + * msScLogin + * clientAuth + * emailProtection + + *key-usage-list* is a comma-separated list of required Key + Usage values. All values in the list must be present in the + certificate. Key Usage values can be: + + * digitalSignature + * keyEncipherment + + Examples:: + + pkinit_cert_match = ||.*DoE.*.*@EXAMPLE.COM + pkinit_cert_match = &&msScLogin,clientAuth.*DoE.* + pkinit_cert_match = msScLogin,clientAuthdigitalSignature + +**pkinit_eku_checking** + This option specifies what Extended Key Usage value the KDC + certificate presented to the client must contain. (Note that if + the KDC certificate has the pkinit SubjectAlternativeName encoded + as the Kerberos TGS name, EKU checking is not necessary since the + issuing CA has certified this as a KDC certificate.) The values + recognized in the krb5.conf file are: + + **kpKDC** + This is the default value and specifies that the KDC must have + the id-pkinit-KPKdc EKU as defined in :rfc:`4556`. + + **kpServerAuth** + If **kpServerAuth** is specified, a KDC certificate with the + id-kp-serverAuth EKU will be accepted. This key usage value + is used in most commercially issued server certificates. + + **none** + If **none** is specified, then the KDC certificate will not be + checked to verify it has an acceptable EKU. The use of this + option is not recommended. + +**pkinit_dh_min_bits** + Specifies the size of the Diffie-Hellman key the client will + attempt to use. The acceptable values are 1024, 2048, and 4096. + The default is 2048. + +**pkinit_identities** + Specifies the location(s) to be used to find the user's X.509 + identity information. If this option is specified multiple times, + each value is attempted in order until certificates are found. + Note that these values are not used if the user specifies + **X509_user_identity** on the command line. + +**pkinit_kdc_hostname** + The presence of this option indicates that the client is willing + to accept a KDC certificate with a dNSName SAN (Subject + Alternative Name) rather than requiring the id-pkinit-san as + defined in :rfc:`4556`. This option may be specified multiple + times. Its value should contain the acceptable hostname for the + KDC (as contained in its certificate). + +**pkinit_pool** + Specifies the location of intermediate certificates which may be + used by the client to complete the trust chain between a KDC + certificate and a trusted anchor. This option may be specified + multiple times. + +**pkinit_require_crl_checking** + The default certificate verification process will always check the + available revocation information to see if a certificate has been + revoked. If a match is found for the certificate in a CRL, + verification fails. If the certificate being verified is not + listed in a CRL, or there is no CRL present for its issuing CA, + and **pkinit_require_crl_checking** is false, then verification + succeeds. + + However, if **pkinit_require_crl_checking** is true and there is + no CRL information available for the issuing CA, then verification + fails. + + **pkinit_require_crl_checking** should be set to true if the + policy is such that up-to-date CRLs must be present for every CA. + +**pkinit_revoke** + Specifies the location of Certificate Revocation List (CRL) + information to be used by the client when verifying the validity + of the KDC certificate presented. This option may be specified + multiple times. + + +.. _parameter_expansion: + +Parameter expansion +------------------- + +Starting with release 1.11, several variables, such as +**default_keytab_name**, allow parameters to be expanded. +Valid parameters are: + + ================= =================================================== + %{TEMP} Temporary directory + %{uid} Unix real UID or Windows SID + %{euid} Unix effective user ID or Windows SID + %{USERID} Same as %{uid} + %{null} Empty string + %{LIBDIR} Installation library directory + %{BINDIR} Installation binary directory + %{SBINDIR} Installation admin binary directory + %{username} (Unix) Username of effective user ID + %{APPDATA} (Windows) Roaming application data for current user + %{COMMON_APPDATA} (Windows) Application data for all users + %{LOCAL_APPDATA} (Windows) Local application data for current user + %{SYSTEM} (Windows) Windows system folder + %{WINDOWS} (Windows) Windows folder + %{USERCONFIG} (Windows) Per-user MIT krb5 config file directory + %{COMMONCONFIG} (Windows) Common MIT krb5 config file directory + ================= =================================================== + +Sample krb5.conf file +--------------------- + +Here is an example of a generic krb5.conf file:: + + [libdefaults] + default_realm = ATHENA.MIT.EDU + dns_lookup_kdc = true + dns_lookup_realm = false + + [realms] + ATHENA.MIT.EDU = { + kdc = kerberos.mit.edu + kdc = kerberos-1.mit.edu + kdc = kerberos-2.mit.edu + admin_server = kerberos.mit.edu + primary_kdc = kerberos.mit.edu + } + EXAMPLE.COM = { + kdc = kerberos.example.com + kdc = kerberos-1.example.com + admin_server = kerberos.example.com + } + + [domain_realm] + mit.edu = ATHENA.MIT.EDU + + [capaths] + ATHENA.MIT.EDU = { + EXAMPLE.COM = . + } + EXAMPLE.COM = { + ATHENA.MIT.EDU = . + } + +FILES +----- + +|krb5conf| + + +SEE ALSO +-------- + +syslog(3) diff --git a/krb5-1.21.3/doc/html/_sources/admin/conf_ldap.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/conf_ldap.rst.txt new file mode 100644 index 00000000..65542c1a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/conf_ldap.rst.txt @@ -0,0 +1,132 @@ +.. _conf_ldap: + +Configuring Kerberos with OpenLDAP back-end +=========================================== + + + 1. Make sure the LDAP server is using local authentication + (``ldapi://``) or TLS (``ldaps``). See + https://www.openldap.org/doc/admin/tls.html for instructions on + configuring TLS support in OpenLDAP. + + 2. Add the Kerberos schema file to the LDAP Server using the OpenLDAP + LDIF file from the krb5 source directory + (``src/plugins/kdb/ldap/libkdb_ldap/kerberos.openldap.ldif``). + The following example uses local authentication:: + + ldapadd -Y EXTERNAL -H ldapi:/// -f /path/to/kerberos.openldap.ldif + + 3. Choose DNs for the :ref:`krb5kdc(8)` and :ref:`kadmind(8)` servers + to bind to the LDAP server, and create them if necessary. Specify + these DNs with the **ldap_kdc_dn** and **ldap_kadmind_dn** + directives in :ref:`kdc.conf(5)`. The kadmind DN will also be + used for administrative commands such as :ref:`kdb5_util(8)`. + + Alternatively, you may configure krb5kdc and kadmind to use SASL + authentication to access the LDAP server; see the :ref:`dbmodules` + relations **ldap_kdc_sasl_mech** and similar. + + 4. Specify a location for the LDAP service password file by setting + **ldap_service_password_file**. Use ``kdb5_ldap_util stashsrvpw`` + to stash passwords for the KDC and kadmind DNs chosen above. For + example:: + + kdb5_ldap_util stashsrvpw -f /path/to/service.keyfile cn=krbadmin,dc=example,dc=com + + Skip this step if you are using SASL authentication and the + mechanism does not require a password. + + 5. Choose a DN for the global Kerberos container entry (but do not + create the entry at this time). Specify this DN with the + **ldap_kerberos_container_dn** directive in :ref:`kdc.conf(5)`. + Realm container entries will be created underneath this DN. + Principal entries may exist either underneath the realm container + (the default) or in separate trees referenced from the realm + container. + + 6. Configure the LDAP server ACLs to enable the KDC and kadmin server + DNs to read and write the Kerberos data. If + **disable_last_success** and **disable_lockout** are both set to + true in the :ref:`dbmodules` subsection for the realm, then the + KDC DN only requires read access to the Kerberos data. + + Sample access control information:: + + access to dn.base="" + by * read + + access to dn.base="cn=Subschema" + by * read + + # Provide access to the realm container. + access to dn.subtree= "cn=EXAMPLE.COM,cn=krbcontainer,dc=example,dc=com" + by dn.exact="cn=kdc-service,dc=example,dc=com" write + by dn.exact="cn=adm-service,dc=example,dc=com" write + by * none + + # Provide access to principals, if not underneath the realm container. + access to dn.subtree= "ou=users,dc=example,dc=com" + by dn.exact="cn=kdc-service,dc=example,dc=com" write + by dn.exact="cn=adm-service,dc=example,dc=com" write + by * none + + access to * + by * read + + If the locations of the container and principals or the DNs of the + service objects for a realm are changed then this information + should be updated. + + 7. In :ref:`kdc.conf(5)`, make sure the following relations are set + in the :ref:`dbmodules` subsection for the realm:: + + db_library (set to ``kldap``) + ldap_kerberos_container_dn + ldap_kdc_dn + ldap_kadmind_dn + ldap_service_password_file + ldap_servers + + 8. Create the realm using :ref:`kdb5_ldap_util(8)`: + + kdb5_ldap_util create -subtrees ou=users,dc=example,dc=com -s + + Use the **-subtrees** option if the principals are to exist in a + separate subtree from the realm container. Before executing the + command, make sure that the subtree mentioned above + ``(ou=users,dc=example,dc=com)`` exists. If the principals will + exist underneath the realm container, omit the **-subtrees** option + and do not worry about creating the principal subtree. + + For more information, refer to the section :ref:`ops_on_ldap`. + + The realm object is created under the + **ldap_kerberos_container_dn** specified in the configuration + file. This operation will also create the Kerberos container, if + not present already. This container can be used to store + information related to multiple realms. + + 9. Add an ``eq`` index for ``krbPrincipalName`` to speed up principal + lookup operations. See + https://www.openldap.org/doc/admin/tuning.html#Indexes for + details. + +With the LDAP back end it is possible to provide aliases for principal +entries. Currently we provide no administrative utilities for +creating aliases, so it must be done by direct manipulation of the +LDAP entries. + +An entry with aliases contains multiple values of the +*krbPrincipalName* attribute. Since LDAP attribute values are not +ordered, it is necessary to specify which principal name is canonical, +by using the *krbCanonicalName* attribute. Therefore, to create +aliases for an entry, first set the *krbCanonicalName* attribute of +the entry to the canonical principal name (which should be identical +to the pre-existing *krbPrincipalName* value), and then add additional +*krbPrincipalName* attributes for the aliases. + +Principal aliases are only returned by the KDC when the client +requests canonicalization. Canonicalization is normally requested for +service principals; for client principals, an explicit flag is often +required (e.g., ``kinit -C``) and canonicalization is only performed +for initial ticket requests. diff --git a/krb5-1.21.3/doc/html/_sources/admin/database.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/database.rst.txt new file mode 100644 index 00000000..2fd07242 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/database.rst.txt @@ -0,0 +1,587 @@ +Database administration +======================= + +A Kerberos database contains all of a realm's Kerberos principals, +their passwords, and other administrative information about each +principal. For the most part, you will use the :ref:`kdb5_util(8)` +program to manipulate the Kerberos database as a whole, and the +:ref:`kadmin(1)` program to make changes to the entries in the +database. (One notable exception is that users will use the +:ref:`kpasswd(1)` program to change their own passwords.) The kadmin +program has its own command-line interface, to which you type the +database administrating commands. + +:ref:`kdb5_util(8)` provides a means to create, delete, load, or dump +a Kerberos database. It also contains commands to roll over the +database master key, and to stash a copy of the key so that the +:ref:`kadmind(8)` and :ref:`krb5kdc(8)` daemons can use the database +without manual input. + +:ref:`kadmin(1)` provides for the maintenance of Kerberos principals, +password policies, and service key tables (keytabs). Normally it +operates as a network client using Kerberos authentication to +communicate with :ref:`kadmind(8)`, but there is also a variant, named +kadmin.local, which directly accesses the Kerberos database on the +local filesystem (or through LDAP). kadmin.local is necessary to set +up enough of the database to be able to use the remote version. + +kadmin can authenticate to the admin server using the service +principal ``kadmin/admin`` or ``kadmin/HOST`` (where *HOST* is the +hostname of the admin server). If the credentials cache contains a +ticket for either service principal and the **-c** ccache option is +specified, that ticket is used to authenticate to KADM5. Otherwise, +the **-p** and **-k** options are used to specify the client Kerberos +principal name used to authenticate. Once kadmin has determined the +principal name, it requests a ``kadmin/admin`` Kerberos service ticket +from the KDC, and uses that service ticket to authenticate to KADM5. + +See :ref:`kadmin(1)` for the available kadmin and kadmin.local +commands and options. + + +.. _principals: + +Principals +---------- + +Each entry in the Kerberos database contains a Kerberos principal and +the attributes and policies associated with that principal. + +To add a principal to the database, use the :ref:`kadmin(1)` +**add_principal** command. User principals should usually be created +with the ``+requires_preauth -allow_svr`` options to help mitigate +dictionary attacks (see :ref:`dictionary`):: + + kadmin: addprinc +requires_preauth -allow_svr alice + Enter password for principal "alice@KRBTEST.COM": + Re-enter password for principal "alice@KRBTEST.COM": + +User principals which will authenticate with :ref:`pkinit` should +instead by created with the ``-nokey`` option: + + kadmin: addprinc -nokey alice + +Service principals can be created with the ``-nokey`` option; +long-term keys will be added when a keytab is generated:: + + kadmin: addprinc -nokey host/foo.mit.edu + kadmin: ktadd -k foo.keytab host/foo.mit.edu + Entry for principal host/foo.mit.edu with kvno 1, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:foo.keytab. + Entry for principal host/foo.mit.edu with kvno 1, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:foo.keytab. + +To modify attributes of an existing principal, use the kadmin +**modify_principal** command:: + + kadmin: modprinc -expire tomorrow alice + Principal "alice@KRBTEST.COM" modified. + +To delete a principal, use the kadmin **delete_principal** command:: + + kadmin: delprinc alice + Are you sure you want to delete the principal "alice@KRBTEST.COM"? (yes/no): yes + Principal "alice@KRBTEST.COM" deleted. + Make sure that you have removed this principal from all ACLs before reusing. + +To change a principal's password, use the kadmin **change_password** +command. Password changes made through kadmin are subject to the same +password policies as would apply to password changes made through +:ref:`kpasswd(1)`. + +To view the attributes of a principal, use the kadmin` +**get_principal** command. + +To generate a listing of principals, use the kadmin +**list_principals** command. + + +.. _policies: + +Policies +-------- + +A policy is a set of rules governing passwords. Policies can dictate +minimum and maximum password lifetimes, minimum number of characters +and character classes a password must contain, and the number of old +passwords kept in the database. + +To add a new policy, use the :ref:`kadmin(1)` **add_policy** command:: + + kadmin: addpol -maxlife "1 year" -history 3 stduser + +To modify attributes of a principal, use the kadmin **modify_policy** +command. To delete a policy, use the kadmin **delete_policy** +command. + +To associate a policy with a principal, use the kadmin +**modify_principal** command with the **-policy** option: + + kadmin: modprinc -policy stduser alice + Principal "alice@KRBTEST.COM" modified. + +A principal entry may be associated with a nonexistent policy, either +because the policy did not exist at the time of associated or was +deleted afterwards. kadmin will warn when associated a principal with +a nonexistent policy, and will annotate the policy name with "[does +not exist]" in the **get_principal** output. + + +.. _updating_history_key: + +Updating the history key +~~~~~~~~~~~~~~~~~~~~~~~~ + +If a policy specifies a number of old keys kept of two or more, the +stored old keys are encrypted in a history key, which is found in the +key data of the ``kadmin/history`` principal. + +Currently there is no support for proper rollover of the history key, +but you can change the history key (for example, to use a better +encryption type) at the cost of invalidating currently stored old +keys. To change the history key, run:: + + kadmin: change_password -randkey kadmin/history + +This command will fail if you specify the **-keepold** flag. Only one +new history key will be created, even if you specify multiple key/salt +combinations. + +In the future, we plan to migrate towards encrypting old keys in the +master key instead of the history key, and implementing proper +rollover support for stored old keys. + + +.. _privileges: + +Privileges +---------- + +Administrative privileges for the Kerberos database are stored in the +file :ref:`kadm5.acl(5)`. + +.. note:: + + A common use of an admin instance is so you can grant + separate permissions (such as administrator access to the + Kerberos database) to a separate Kerberos principal. For + example, the user ``joeadmin`` might have a principal for + his administrative use, called ``joeadmin/admin``. This + way, ``joeadmin`` would obtain ``joeadmin/admin`` tickets + only when he actually needs to use those permissions. + + +.. _db_operations: + +Operations on the Kerberos database +----------------------------------- + +The :ref:`kdb5_util(8)` command is the primary tool for administrating +the Kerberos database when using the DB2 or LMDB modules (see +:ref:`dbtypes`). Creating a database is described in +:ref:`create_db`. + +To create a stash file using the master password (because the database +was not created with one using the ``create -s`` flag, or after +restoring from a backup which did not contain the stash file), use the +kdb5_util **stash** command:: + + $ kdb5_util stash + kdb5_util: Cannot find/read stored master key while reading master key + kdb5_util: Warning: proceeding without master key + Enter KDC database master key: <= Type the KDC database master password. + +To destroy a database, use the kdb5_util destroy command:: + + $ kdb5_util destroy + Deleting KDC database stored in '/var/krb5kdc/principal', are you sure? + (type 'yes' to confirm)? yes + OK, deleting database '/var/krb5kdc/principal'... + ** Database '/var/krb5kdc/principal' destroyed. + + +.. _restore_from_dump: + +Dumping and loading a Kerberos database +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To dump a Kerberos database into a text file for backup or transfer +purposes, use the :ref:`kdb5_util(8)` **dump** command on one of the +KDCs:: + + $ kdb5_util dump dumpfile + + $ kbd5_util dump -verbose dumpfile + kadmin/admin@ATHENA.MIT.EDU + krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU + kadmin/history@ATHENA.MIT.EDU + K/M@ATHENA.MIT.EDU + kadmin/changepw@ATHENA.MIT.EDU + +You may specify which principals to dump, using full principal names +including realm:: + + $ kdb5_util dump -verbose someprincs K/M@ATHENA.MIT.EDU kadmin/admin@ATHENA.MIT.EDU + kadmin/admin@ATHENA.MIT.EDU + K/M@ATHENA.MIT.EDU + +To restore a Kerberos database dump from a file, use the +:ref:`kdb5_util(8)` **load** command:: + + $ kdb5_util load dumpfile + +To update an existing database with a partial dump file containing +only some principals, use the ``-update`` flag:: + + $ kdb5_util load -update someprincs + +.. note:: + + If the database file exists, and the *-update* flag was not + given, *kdb5_util* will overwrite the existing database. + + +.. _updating_master_key: + +Updating the master key +~~~~~~~~~~~~~~~~~~~~~~~ + +Starting with release 1.7, :ref:`kdb5_util(8)` allows the master key +to be changed using a rollover process, with minimal loss of +availability. To roll over the master key, follow these steps: + +#. On the primary KDC, run ``kdb5_util list_mkeys`` to view the + current master key version number (KVNO). If you have never rolled + over the master key before, this will likely be version 1:: + + $ kdb5_util list_mkeys + Master keys for Principal: K/M@KRBTEST.COM + KVNO: 1, Enctype: aes256-cts-hmac-sha384-192, Active on: Thu Jan 01 00:00:00 UTC 1970 * + +#. On the primary KDC, run ``kdb5_util use_mkey 1`` to ensure that a + master key activation list is present in the database. This step + is unnecessary in release 1.11.4 or later, or if the database was + initially created with release 1.7 or later. + +#. On the primary KDC, run ``kdb5_util add_mkey -s`` to create a new + master key and write it to the stash file. Enter a secure password + when prompted. If this is the first time you are changing the + master key, the new key will have version 2. The new master key + will not be used until you make it active. + +#. Propagate the database to all replica KDCs, either manually or by + waiting until the next scheduled propagation. If you do not have + any replica KDCs, you can skip this and the next step. + +#. On each replica KDC, run ``kdb5_util list_mkeys`` to verify that + the new master key is present, and then ``kdb5_util stash`` to + write the new master key to the replica KDC's stash file. + +#. On the primary KDC, run ``kdb5_util use_mkey 2`` to begin using the + new master key. Replace ``2`` with the version of the new master + key, as appropriate. You can optionally specify a date for the new + master key to become active; by default, it will become active + immediately. Prior to release 1.12, :ref:`kadmind(8)` must be + restarted for this change to take full effect. + +#. On the primary KDC, run ``kdb5_util update_princ_encryption``. + This command will iterate over the database and re-encrypt all keys + in the new master key. If the database is large and uses DB2, the + primary KDC will become unavailable while this command runs, but + clients should fail over to replica KDCs (if any are present) + during this time period. In release 1.13 and later, you can + instead run ``kdb5_util -x unlockiter update_princ_encryption`` to + use unlocked iteration; this variant will take longer, but will + keep the database available to the KDC and kadmind while it runs. + +#. Wait until the above changes have propagated to all replica KDCs + and until all running KDC and kadmind processes have serviced + requests using updated principal entries. + +#. On the primary KDC, run ``kdb5_util purge_mkeys`` to clean up the + old master key. + + +.. _ops_on_ldap: + +Operations on the LDAP database +------------------------------- + +The :ref:`kdb5_ldap_util(8)` command is the primary tool for +administrating the Kerberos database when using the LDAP module. +Creating an LDAP Kerberos database is describe in :ref:`conf_ldap`. + +To view a list of realms in the LDAP database, use the kdb5_ldap_util +**list** command:: + + $ kdb5_ldap_util list + KRBTEST.COM + +To modify the attributes of a realm, use the kdb5_ldap_util **modify** +command. For example, to change the default realm's maximum ticket +life:: + + $ kdb5_ldap_util modify -maxtktlife "10 hours" + +To display the attributes of a realm, use the kdb5_ldap_util **view** +command:: + + $ kdb5_ldap_util view + Realm Name: KRBTEST.COM + Maximum Ticket Life: 0 days 00:10:00 + +To remove a realm from the LDAP database, destroying its contents, use +the kdb5_ldap_util **destroy** command:: + + $ kdb5_ldap_util destroy + Deleting KDC database of 'KRBTEST.COM', are you sure? + (type 'yes' to confirm)? yes + OK, deleting database of 'KRBTEST.COM'... + ** Database of 'KRBTEST.COM' destroyed. + + +Ticket Policy operations +~~~~~~~~~~~~~~~~~~~~~~~~ + +Unlike the DB2 and LMDB modules, the LDAP module supports ticket +policy objects, which can be associated with principals to restrict +maximum ticket lifetimes and set mandatory principal flags. Ticket +policy objects are distinct from the password policies described +earlier on this page, and are chiefly managed through kdb5_ldap_util +rather than kadmin. To create a new ticket policy, use the +kdb5_ldap_util **create_policy** command:: + + $ kdb5_ldap_util create_policy -maxrenewlife "2 days" users + +To associate a ticket policy with a principal, use the +:ref:`kadmin(1)` **modify_principal** (or **add_principal**) command +with the **-x tktpolicy=**\ *policy* option:: + + $ kadmin.local modprinc -x tktpolicy=users alice + +To remove a ticket policy reference from a principal, use the same +command with an empty *policy*:: + + $ kadmin.local modprinc -x tktpolicy= alice + +To list the existing ticket policy objects, use the kdb5_ldap_util +**list_policy** command:: + + $ kdb5_ldap_util list_policy + users + +To modify the attributes of a ticket policy object, use the +kdb5_ldap_util **modify_policy** command:: + + $ kdb5_ldap_util modify_policy -allow_svr +requires_preauth users + +To view the attributes of a ticket policy object, use the +kdb5_ldap_util **view_policy** command:: + + $ kdb5_ldap_util view_policy users + Ticket policy: users + Maximum renewable life: 2 days 00:00:00 + Ticket flags: REQUIRES_PRE_AUTH DISALLOW_SVR + +To destroy an ticket policy object, use the kdb5_ldap_util +**destroy_policy** command:: + + $ kdb5_ldap_util destroy_policy users + This will delete the policy object 'users', are you sure? + (type 'yes' to confirm)? yes + ** policy object 'users' deleted. + + +.. _xrealm_authn: + +Cross-realm authentication +-------------------------- + +In order for a KDC in one realm to authenticate Kerberos users in a +different realm, it must share a key with the KDC in the other realm. +In both databases, there must be krbtgt service principals for both realms. +For example, if you need to do cross-realm authentication between the realms +``ATHENA.MIT.EDU`` and ``EXAMPLE.COM``, you would need to add the +principals ``krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU`` and +``krbtgt/ATHENA.MIT.EDU@EXAMPLE.COM`` to both databases. +These principals must all have the same passwords, key version +numbers, and encryption types; this may require explicitly setting +the key version number with the **-kvno** option. + +In the ATHENA.MIT.EDU and EXAMPLE.COM cross-realm case, the administrators +would run the following commands on the KDCs in both realms:: + + shell%: kadmin.local -e "aes256-cts:normal" + kadmin: addprinc -requires_preauth krbtgt/ATHENA.MIT.EDU@EXAMPLE.COM + Enter password for principal krbtgt/ATHENA.MIT.EDU@EXAMPLE.COM: + Re-enter password for principal krbtgt/ATHENA.MIT.EDU@EXAMPLE.COM: + kadmin: addprinc -requires_preauth krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU + Enter password for principal krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU: + Enter password for principal krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU: + kadmin: + +.. note:: + + Even if most principals in a realm are generally created + with the **requires_preauth** flag enabled, this flag is not + desirable on cross-realm authentication keys because doing + so makes it impossible to disable preauthentication on a + service-by-service basis. Disabling it as in the example + above is recommended. + +.. note:: + + It is very important that these principals have good + passwords. MIT recommends that TGT principal passwords be + at least 26 characters of random ASCII text. + + +.. _changing_krbtgt_key: + +Changing the krbtgt key +----------------------- + +A Kerberos Ticket Granting Ticket (TGT) is a service ticket for the +principal ``krbtgt/REALM``. The key for this principal is created +when the Kerberos database is initialized and need not be changed. +However, it will only have the encryption types supported by the KDC +at the time of the initial database creation. To allow use of newer +encryption types for the TGT, this key has to be changed. + +Changing this key using the normal :ref:`kadmin(1)` +**change_password** command would invalidate any previously issued +TGTs. Therefore, when changing this key, normally one should use the +**-keepold** flag to change_password to retain the previous key in the +database as well as the new key. For example:: + + kadmin: change_password -randkey -keepold krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU + +.. warning:: + + After issuing this command, the old key is still valid + and is still vulnerable to (for instance) brute force + attacks. To completely retire an old key or encryption + type, run the kadmin **purgekeys** command to delete keys + with older kvnos, ideally first making sure that all + tickets issued with the old keys have expired. + +Only the first krbtgt key of the newest key version is used to encrypt +ticket-granting tickets. However, the set of encryption types present +in the krbtgt keys is used by default to determine the session key +types supported by the krbtgt service (see +:ref:`session_key_selection`). Because non-MIT Kerberos clients +sometimes send a limited set of encryption types when making AS +requests, it can be important for the krbtgt service to support +multiple encryption types. This can be accomplished by giving the +krbtgt principal multiple keys, which is usually as simple as not +specifying any **-e** option when changing the krbtgt key, or by +setting the **session_enctypes** string attribute on the krbtgt +principal (see :ref:`set_string`). + +Due to a bug in releases 1.8 through 1.13, renewed and forwarded +tickets may not work if the original ticket was obtained prior to a +krbtgt key change and the modified ticket is obtained afterwards. +Upgrading the KDC to release 1.14 or later will correct this bug. + + +.. _incr_db_prop: + +Incremental database propagation +-------------------------------- + +Overview +~~~~~~~~ + +At some very large sites, dumping and transmitting the database can +take more time than is desirable for changes to propagate from the +primary KDC to the replica KDCs. The incremental propagation support +added in the 1.7 release is intended to address this. + +With incremental propagation enabled, all programs on the primary KDC +that change the database also write information about the changes to +an "update log" file, maintained as a circular buffer of a certain +size. A process on each replica KDC connects to a service on the +primary KDC (currently implemented in the :ref:`kadmind(8)` server) and +periodically requests the changes that have been made since the last +check. By default, this check is done every two minutes. + +Incremental propagation uses the following entries in the per-realm +data in the KDC config file (See :ref:`kdc.conf(5)`): + +====================== =============== =========================================== +iprop_enable *boolean* If *true*, then incremental propagation is enabled, and (as noted below) normal kprop propagation is disabled. The default is *false*. +iprop_master_ulogsize *integer* Indicates the number of entries that should be retained in the update log. The default is 1000; the maximum number is 2500. +iprop_replica_poll *time interval* Indicates how often the replica should poll the primary KDC for changes to the database. The default is two minutes. +iprop_port *integer* Specifies the port number to be used for incremental propagation. This is required in both primary and replica configuration files. +iprop_resync_timeout *integer* Specifies the number of seconds to wait for a full propagation to complete. This is optional on replica configurations. Defaults to 300 seconds (5 minutes). +iprop_logfile *file name* Specifies where the update log file for the realm database is to be stored. The default is to use the *database_name* entry from the realms section of the config file :ref:`kdc.conf(5)`, with *.ulog* appended. (NOTE: If database_name isn't specified in the realms section, perhaps because the LDAP database back end is being used, or the file name is specified in the *dbmodules* section, then the hard-coded default for *database_name* is used. Determination of the *iprop_logfile* default value will not use values from the *dbmodules* section.) +====================== =============== =========================================== + +Both primary and replica sides must have a principal named +``kiprop/hostname`` (where *hostname* is the lowercase, +fully-qualified, canonical name for the host) registered in the +Kerberos database, and have keys for that principal stored in the +default keytab file (|keytab|). The ``kiprop/hostname`` principal may +have been created automatically for the primary KDC, but it must +always be created for replica KDCs. + +On the primary KDC side, the ``kiprop/hostname`` principal must be +listed in the kadmind ACL file :ref:`kadm5.acl(5)`, and given the +**p** privilege (see :ref:`privileges`). + +On the replica KDC side, :ref:`kpropd(8)` should be run. When +incremental propagation is enabled, it will connect to the kadmind on +the primary KDC and start requesting updates. + +The normal kprop mechanism is disabled by the incremental propagation +support. However, if the replica has been unable to fetch changes +from the primary KDC for too long (network problems, perhaps), the log +on the primary may wrap around and overwrite some of the updates that +the replica has not yet retrieved. In this case, the replica will +instruct the primary KDC to dump the current database out to a file +and invoke a one-time kprop propagation, with special options to also +convey the point in the update log at which the replica should resume +fetching incremental updates. Thus, all the keytab and ACL setup +previously described for kprop propagation is still needed. + +If an environment has a large number of replicas, it may be desirable +to arrange them in a hierarchy instead of having the primary serve +updates to every replica. To do this, run ``kadmind -proponly`` on +each intermediate replica, and ``kpropd -A upstreamhostname`` on +downstream replicas to direct each one to the appropriate upstream +replica. + +There are several known restrictions in the current implementation: + +- The incremental update protocol does not transport changes to policy + objects. Any policy changes on the primary will result in full + resyncs to all replicas. +- The replica's KDB module must support locking; it cannot be using the + LDAP KDB module. +- The primary and replica must be able to initiate TCP connections in + both directions, without an intervening NAT. + + +Sun/MIT incremental propagation differences +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sun donated the original code for supporting incremental database +propagation to MIT. Some changes have been made in the MIT source +tree that will be visible to administrators. (These notes are based +on Sun's patches. Changes to Sun's implementation since then may not +be reflected here.) + +The Sun config file support looks for ``sunw_dbprop_enable``, +``sunw_dbprop_master_ulogsize``, and ``sunw_dbprop_slave_poll``. + +The incremental propagation service is implemented as an ONC RPC +service. In the Sun implementation, the service is registered with +rpcbind (also known as portmapper) and the client looks up the port +number to contact. In the MIT implementation, where interaction with +some modern versions of rpcbind doesn't always work well, the port +number must be specified in the config file on both the primary and +replica sides. + +The Sun implementation hard-codes pathnames in ``/var/krb5`` for the +update log and the per-replica kprop dump files. In the MIT +implementation, the pathname for the update log is specified in the +config file, and the per-replica dump files are stored in +|kdcdir|\ ``/replica_datatrans_hostname``. diff --git a/krb5-1.21.3/doc/html/_sources/admin/dbtypes.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/dbtypes.rst.txt new file mode 100644 index 00000000..04748176 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/dbtypes.rst.txt @@ -0,0 +1,149 @@ +.. _dbtypes: + +Database types +============== + +A Kerberos database can be implemented with one of three built-in +database providers, called KDB modules. Software which incorporates +the MIT krb5 KDC may also provide its own KDB module. The following +subsections describe the three built-in KDB modules and the +configuration specific to them. + +The database type can be configured with the **db_library** variable +in the :ref:`dbmodules` subsection for the realm. For example:: + + [dbmodules] + ATHENA.MIT.EDU = { + db_library = db2 + } + +If the ``ATHENA.MIT.EDU`` realm subsection contains a +**database_module** setting, then the subsection within +``[dbmodules]`` should use that name instead of ``ATHENA.MIT.EDU``. + +To transition from one database type to another, stop the +:ref:`kadmind(8)` service, use ``kdb5_util dump`` to create a dump +file, change the **db_library** value and set any appropriate +configuration for the new database type, and use ``kdb5_util load`` to +create and populate the new database. If the new database type is +LDAP, create the new database using ``kdb5_ldap_util`` and populate it +from the dump file using ``kdb5_util load -update``. Then restart the +:ref:`krb5kdc(8)` and :ref:`kadmind(8)` services. + + +Berkeley database module (db2) +------------------------------ + +The default KDB module is ``db2``, which uses a version of the +Berkeley DB library. It creates four files based on the database +pathname. If the pathname ends with ``principal`` then the four files +are: + +* ``principal``, containing principal entry data +* ``principal.ok``, a lock file for the principal database +* ``principal.kadm5``, containing policy object data +* ``principal.kadm5.lock``, a lock file for the policy database + +For large databases, the :ref:`kdb5_util(8)` **dump** command (perhaps +invoked by :ref:`kprop(8)` or by :ref:`kadmind(8)` for incremental +propagation) may cause :ref:`krb5kdc(8)` to stop for a noticeable +period of time while it iterates over the database. This delay can be +avoided by disabling account lockout features so that the KDC does not +perform database writes (see :ref:`disable_lockout`). Alternatively, +a slower form of iteration can be enabled by setting the +**unlockiter** variable to ``true``. For example:: + + [dbmodules] + ATHENA.MIT.EDU = { + db_library = db2 + unlockiter = true + } + +In rare cases, a power failure or other unclean system shutdown may +cause inconsistencies in the internal pointers within a database file, +such that ``kdb5_util dump`` cannot retrieve all principal entries in +the database. In this situation, it may be possible to retrieve all +of the principal data by running ``kdb5_util dump -recurse`` to +iterate over the database using the tree pointers instead of the +iteration pointers. Running ``kdb5_util dump -rev`` to iterate over +the database backwards may also retrieve some of the data which is not +retrieved by a normal dump operation. + + +Lightning Memory-Mapped Database module (klmdb) +----------------------------------------------- + +The klmdb module was added in release 1.17. It uses the LMDB library, +and may offer better performance and reliability than the db2 module. +It creates four files based on the database pathname. If the pathname +ends with ``principal``, then the four files are: + +* ``principal.mdb``, containing policy object data and most principal + entry data +* ``principal.mdb-lock``, a lock file for the primary database +* ``principal.lockout.mdb``, containing the account lockout attributes + (last successful authentication time, last failed authentication + time, and number of failed attempts) for each principal entry +* ``principal.lockout.mdb-lock``, a lock file for the lockout database + +Separating out the lockout attributes ensures that the KDC will never +block on an administrative operation such as a database dump or load. +It also allows the KDC to operate without write access to the primary +database. If both account lockout features are disabled (see +:ref:`disable_lockout`), the lockout database files will be created +but will not subsequently be opened, and the account lockout +attributes will always have zero values. + +Because LMDB creates a memory map to the database files, it requires a +configured memory map size which also determines the maximum size of +the database. This size is applied equally to the two databases, so +twice the configured size will be consumed in the process address +space; this is primarily a limitation on 32-bit platforms. The +default value of 128 megabytes should be sufficient for several +hundred thousand principal entries. If the limit is reached, kadmin +operations will fail and the error message "Environment mapsize limit +reached" will appear in the kadmind log file. In this case, the +**mapsize** variable can be used to increase the map size. The +following example sets the map size to 512 megabytes:: + + [dbmodules] + ATHENA.MIT.EDU = { + db_library = klmdb + mapsize = 512 + } + +LMDB has a configurable maximum number of readers. The default value +of 128 should be sufficient for most deployments. If you are going to +use a large number of KDC worker processes, it may be necessary to set +the **max_readers** variable to a larger number. + +By default, LMDB synchronizes database files to disk after each write +transaction to ensure durability in the case of an unclean system +shutdown. The klmdb module always turns synchronization off for the +lockout database to ensure reasonable KDC performance, but leaves it +on for the primary database. If high throughput for administrative +operations (including password changes) is required, the **nosync** +variable can be set to "true" to disable synchronization for the +primary database. + +The klmdb module does not support explicit locking with the +:ref:`kadmin(1)` **lock** command. + + +LDAP module (kldap) +------------------- + +The kldap module stores principal and policy data using an LDAP +server. To use it you must configure an LDAP server to use the +Kerberos schema. See :ref:`conf_ldap` for details. + +Because :ref:`krb5kdc(8)` is single-threaded, latency in LDAP database +accesses may limit KDC operation throughput. If the LDAP server is +located on the same server host as the KDC and accessed through an +``ldapi://`` URL, latency should be minimal. If this is not possible, +consider starting multiple KDC worker processes with the +:ref:`krb5kdc(8)` **-w** option to enable concurrent processing of KDC +requests. + +The kldap module does not support explicit locking with the +:ref:`kadmin(1)` **lock** command. diff --git a/krb5-1.21.3/doc/html/_sources/admin/dictionary.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/dictionary.rst.txt new file mode 100644 index 00000000..a5c57868 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/dictionary.rst.txt @@ -0,0 +1,88 @@ +.. _dictionary: + +Addressing dictionary attack risks +================================== + +Kerberos initial authentication is normally secured using the client +principal's long-term key, which for users is generally derived from a +password. Using a pasword-derived long-term key carries the risk of a +dictionary attack, where an attacker tries a sequence of possible +passwords, possibly requiring much less effort than would be required +to try all possible values of the key. Even if :ref:`password policy +objects ` are used to force users not to pick trivial +passwords, dictionary attacks can sometimes be successful against a +significant fraction of the users in a realm. Dictionary attacks are +not a concern for principals using random keys. + +A dictionary attack may be online or offline. An online dictionary +attack is performed by trying each password in a separate request to +the KDC, and is therefore visible to the KDC and also limited in speed +by the KDC's processing power and the network capacity between the +client and the KDC. Online dictionary attacks can be mitigated using +:ref:`account lockout `. This measure is not totally +satisfactory, as it makes it easy for an attacker to deny access to a +client principal. + +An offline dictionary attack is performed by obtaining a ciphertext +generated using the password-derived key, and trying each password +against the ciphertext. This category of attack is invisible to the +KDC and can be performed much faster than an online attack. The +attack will generally take much longer with more recent encryption +types (particularly the ones based on AES), because those encryption +types use a much more expensive string-to-key function. However, the +best defense is to deny the attacker access to a useful ciphertext. +The required defensive measures depend on the attacker's level of +network access. + +An off-path attacker has no access to packets sent between legitimate +users and the KDC. An off-path attacker could gain access to an +attackable ciphertext either by making an AS request for a client +principal which does not have the **+requires_preauth** flag, or by +making a TGS request (after authenticating as a different user) for a +server principal which does not have the **-allow_svr** flag. To +address off-path attackers, a KDC administrator should set those flags +on principals with password-derived keys:: + + kadmin: add_principal +requires_preauth -allow_svr princname + +An attacker with passive network access (one who can monitor packets +sent between legitimate users and the KDC, but cannot change them or +insert their own packets) can gain access to an attackable ciphertext +by observing an authentication by a user using the most common form of +preauthentication, encrypted timestamp. Any of the following methods +can prevent dictionary attacks by attackers with passive network +access: + +* Enabling :ref:`SPAKE preauthentication ` (added in release + 1.17) on the KDC, and ensuring that all clients are able to support + it. + +* Using an :ref:`HTTPS proxy ` for communication with the KDC, + if the attacker cannot monitor communication between the proxy + server and the KDC. + +* Using FAST, protecting the initial authentication with either a + random key (such as a host key) or with :ref:`anonymous PKINIT + `. + +An attacker with active network access (one who can inject or modify +packets sent between legitimate users and the KDC) can try to fool the +client software into sending an attackable ciphertext using an +encryption type and salt string of the attacker's choosing. Any of the +following methods can prevent dictionary attacks by active attackers: + +* Enabling SPAKE preauthentication and setting the + **disable_encrypted_timestamp** variable to ``true`` in the + :ref:`realms` subsection of the client configuration. + +* Using an HTTPS proxy as described above, configured in the client's + krb5.conf realm configuration. If :ref:`KDC discovery + ` is used to locate a proxy server, an active + attacker may be able to use DNS spoofing to cause the client to use + a different HTTPS server or to not use HTTPS. + +* Using FAST as described above. + +If :ref:`PKINIT ` or :ref:`OTP ` are used for +initial authentication, the principal's long-term keys are not used +and dictionary attacks are usually not a concern. diff --git a/krb5-1.21.3/doc/html/_sources/admin/enctypes.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/enctypes.rst.txt new file mode 100644 index 00000000..dce19ad4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/enctypes.rst.txt @@ -0,0 +1,222 @@ +.. _enctypes: + +Encryption types +================ + +Kerberos can use a variety of cipher algorithms to protect data. A +Kerberos **encryption type** (also known as an **enctype**) is a +specific combination of a cipher algorithm with an integrity algorithm +to provide both confidentiality and integrity to data. + + +Enctypes in requests +-------------------- + +Clients make two types of requests (KDC-REQ) to the KDC: AS-REQs and +TGS-REQs. The client uses the AS-REQ to obtain initial tickets +(typically a Ticket-Granting Ticket (TGT)), and uses the TGS-REQ to +obtain service tickets. + +The KDC uses three different keys when issuing a ticket to a client: + +* The long-term key of the service: the KDC uses this to encrypt the + actual service ticket. The KDC only uses the first long-term key in + the most recent kvno for this purpose. + +* The session key: the KDC randomly chooses this key and places one + copy inside the ticket and the other copy inside the encrypted part + of the reply. + +* The reply-encrypting key: the KDC uses this to encrypt the reply it + sends to the client. For AS replies, this is a long-term key of the + client principal. For TGS replies, this is either the session key of the + authenticating ticket, or a subsession key. + +Each of these keys is of a specific enctype. + +Each request type allows the client to submit a list of enctypes that +it is willing to accept. For the AS-REQ, this list affects both the +session key selection and the reply-encrypting key selection. For the +TGS-REQ, this list only affects the session key selection. + + +.. _session_key_selection: + +Session key selection +--------------------- + +The KDC chooses the session key enctype by taking the intersection of +its **permitted_enctypes** list, the list of long-term keys for the +most recent kvno of the service, and the client's requested list of +enctypes. Starting in krb5-1.21, all services are assumed to support +aes256-cts-hmac-sha1-96; also, des3-cbc-sha1 and arcfour-hmac session +keys will not be issued by default. + +Starting in krb5-1.11, it is possible to set a string attribute on a +service principal to control what session key enctypes the KDC may +issue for service tickets for that principal, overriding the service's +long-term keys and the assumption of aes256-cts-hmac-sha1-96 support. +See :ref:`set_string` in :ref:`kadmin(1)` for details. + + +Choosing enctypes for a service +------------------------------- + +Generally, a service should have a key of the strongest +enctype that both it and the KDC support. If the KDC is running a +release earlier than krb5-1.11, it is also useful to generate an +additional key for each enctype that the service can support. The KDC +will only use the first key in the list of long-term keys for encrypting +the service ticket, but the additional long-term keys indicate the +other enctypes that the service supports. + +As noted above, starting with release krb5-1.11, there are additional +configuration settings that control session key enctype selection +independently of the set of long-term keys that the KDC has stored for +a service principal. + + +Configuration variables +----------------------- + +The following ``[libdefaults]`` settings in :ref:`krb5.conf(5)` will +affect how enctypes are chosen. + +**allow_weak_crypto** + defaults to *false* starting with krb5-1.8. When *false*, removes + weak enctypes from **permitted_enctypes**, + **default_tkt_enctypes**, and **default_tgs_enctypes**. Do not + set this to *true* unless the use of weak enctypes is an + acceptable risk for your environment and the weak enctypes are + required for backward compatibility. + +**allow_des3** + was added in release 1.21 and defaults to *false*. Unless this + flag is set to *true*, the KDC will not issue tickets with + des3-cbc-sha1 session keys. In a future release, this flag will + control whether des3-cbc-sha1 is permitted in similar fashion to + weak enctypes. + +**allow_rc4** + was added in release 1.21 and defaults to *false*. Unless this + flag is set to *true*, the KDC will not issue tickets with + arcfour-hmac session keys. In a future release, this flag will + control whether arcfour-hmac is permitted in similar fashion to + weak enctypes. + +**permitted_enctypes** + controls the set of enctypes that a service will permit for + session keys and for ticket and authenticator encryption. The KDC + and other programs that access the Kerberos database will ignore + keys of non-permitted enctypes. Starting in release 1.18, this + setting also acts as the default for **default_tkt_enctypes** and + **default_tgs_enctypes**. + +**default_tkt_enctypes** + controls the default set of enctypes that the Kerberos client + library requests when making an AS-REQ. Do not set this unless + required for specific backward compatibility purposes; stale + values of this setting can prevent clients from taking advantage + of new stronger enctypes when the libraries are upgraded. + +**default_tgs_enctypes** + controls the default set of enctypes that the Kerberos client + library requests when making a TGS-REQ. Do not set this unless + required for specific backward compatibility purposes; stale + values of this setting can prevent clients from taking advantage + of new stronger enctypes when the libraries are upgraded. + +The following per-realm setting in :ref:`kdc.conf(5)` affects the +generation of long-term keys. + +**supported_enctypes** + controls the default set of enctype-salttype pairs that :ref:`kadmind(8)` + will use for generating long-term keys, either randomly or from + passwords + + +Enctype compatibility +--------------------- + +See :ref:`Encryption_types` for additional information about enctypes. + +========================== ========== ======== ======= +enctype weak? krb5 Windows +========================== ========== ======== ======= +des-cbc-crc weak <1.18 >=2000 +des-cbc-md4 weak <1.18 ? +des-cbc-md5 weak <1.18 >=2000 +des3-cbc-sha1 deprecated >=1.1 none +arcfour-hmac deprecated >=1.3 >=2000 +arcfour-hmac-exp weak >=1.3 >=2000 +aes128-cts-hmac-sha1-96 >=1.3 >=Vista +aes256-cts-hmac-sha1-96 >=1.3 >=Vista +aes128-cts-hmac-sha256-128 >=1.15 none +aes256-cts-hmac-sha384-192 >=1.15 none +camellia128-cts-cmac >=1.9 none +camellia256-cts-cmac >=1.9 none +========================== ========== ======== ======= + +krb5 releases 1.18 and later do not support single-DES. krb5 releases +1.8 and later disable the single-DES enctypes by default. Microsoft +Windows releases Windows 7 and later disable single-DES enctypes by +default. + +krb5 releases 1.17 and later flag deprecated encryption types +(including ``des3-cbc-sha1`` and ``arcfour-hmac``) in KDC logs and +kadmin output. krb5 release 1.19 issues a warning during initial +authentication if ``des3-cbc-sha1`` is used. Future releases will +disable ``des3-cbc-sha1`` by default and eventually remove support for +it. + + +Migrating away from older encryption types +------------------------------------------ + +Administrator intervention may be required to migrate a realm away +from legacy encryption types, especially if the realm was created +using krb5 release 1.2 or earlier. This migration should be performed +before upgrading to krb5 versions which disable or remove support for +legacy encryption types. + +If there is a **supported_enctypes** setting in :ref:`kdc.conf(5)` on +the KDC, make sure that it does not include weak or deprecated +encryption types. This will ensure that newly created keys do not use +those encryption types by default. + +Check the ``krbtgt/REALM`` principal using the :ref:`kadmin(1)` +**getprinc** command. If it lists a weak or deprecated encryption +type as the first key, it must be migrated using the procedure in +:ref:`changing_krbtgt_key`. + +Check the ``kadmin/history`` principal, which should have only one key +entry. If it uses a weak or deprecated encryption type, it should be +upgraded following the notes in :ref:`updating_history_key`. + +Check the other kadmin principals: kadmin/changepw, kadmin/admin, and +any kadmin/hostname principals that may exist. These principals can +be upgraded with **change_password -randkey** in kadmin. + +Check the ``K/M`` entry. If it uses a weak or deprecated encryption +type, it should be upgraded following the procedure in +:ref:`updating_master_key`. + +User and service principals using legacy encryption types can be +enumerated with the :ref:`kdb5_util(8)` **tabdump keyinfo** command. + +Service principals can be migrated with a keytab rotation on the +service host, which can be accomplished using the :ref:`k5srvutil(1)` +**change** and **delold** commands. Allow enough time for existing +tickets to expire between the change and delold operations. + +User principals with password-based keys can be migrated with a +password change. The realm administrator can set a password +expiration date using the :ref:`kadmin(1)` **modify_principal +-pwexpire** command to force a password change. + +If a legacy encryption type has not yet been disabled by default in +the version of krb5 running on the KDC, it can be disabled +administratively with the **permitted_enctypes** variable. For +example, setting **permitted_enctypes** to ``DEFAULT -des3 -rc4`` will +cause any database keys of the triple-DES and RC4 encryption types to +be ignored. diff --git a/krb5-1.21.3/doc/html/_sources/admin/env_variables.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/env_variables.rst.txt new file mode 100644 index 00000000..a2d15bea --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/env_variables.rst.txt @@ -0,0 +1,4 @@ +Environment variables +===================== + +This content has moved to :ref:`kerberos(7)`. diff --git a/krb5-1.21.3/doc/html/_sources/admin/host_config.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/host_config.rst.txt new file mode 100644 index 00000000..4e1db025 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/host_config.rst.txt @@ -0,0 +1,235 @@ +Host configuration +================== + +All hosts running Kerberos software, whether they are clients, +application servers, or KDCs, can be configured using +:ref:`krb5.conf(5)`. Here we describe some of the behavior changes +you might want to make. + + +Default realm +------------- + +In the :ref:`libdefaults` section, the **default_realm** realm +relation sets the default Kerberos realm. For example:: + + [libdefaults] + default_realm = ATHENA.MIT.EDU + +The default realm affects Kerberos behavior in the following ways: + +* When a principal name is parsed from text, the default realm is used + if no ``@REALM`` component is specified. + +* The default realm affects login authorization as described below. + +* For programs which operate on a Kerberos database, the default realm + is used to determine which database to operate on, unless the **-r** + parameter is given to specify a realm. + +* A server program may use the default realm when looking up its key + in a :ref:`keytab file `, if its realm is not + determined by :ref:`domain_realm` configuration or by the server + program itself. + +* If :ref:`kinit(1)` is passed the **-n** flag, it requests anonymous + tickets from the default realm. + +In some situations, these uses of the default realm might conflict. +For example, it might be desirable for principal name parsing to use +one realm by default, but for login authorization to use a second +realm. In this situation, the first realm can be configured as the +default realm, and **auth_to_local** relations can be used as +described below to use the second realm for login authorization. + + +.. _login_authorization: + +Login authorization +------------------- + +If a host runs a Kerberos-enabled login service such as OpenSSH with +GSSAPIAuthentication enabled, login authorization rules determine +whether a Kerberos principal is allowed to access a local account. + +By default, a Kerberos principal is allowed access to an account if +its realm matches the default realm and its name matches the account +name. (For historical reasons, access is also granted by default if +the name has two components and the second component matches the +default realm; for instance, ``alice/ATHENA.MIT.EDU@ATHENA.MIT.EDU`` +is granted access to the ``alice`` account if ``ATHENA.MIT.EDU`` is +the default realm.) + +The simplest way to control local access is using :ref:`.k5login(5)` +files. To use these, place a ``.k5login`` file in the home directory +of each account listing the principal names which should have login +access to that account. If it is not desirable to use ``.k5login`` +files located in account home directories, the **k5login_directory** +relation in the :ref:`libdefaults` section can specify a directory +containing one file per account uname. + +By default, if a ``.k5login`` file is present, it controls +authorization both positively and negatively--any principal name +contained in the file is granted access and any other principal name +is denied access, even if it would have had access if the ``.k5login`` +file didn't exist. The **k5login_authoritative** relation in the +:ref:`libdefaults` section can be set to false to make ``.k5login`` +files provide positive authorization only. + +The **auth_to_local** relation in the :ref:`realms` section for the +default realm can specify pattern-matching rules to control login +authorization. For example, the following configuration allows access +to principals from a different realm than the default realm:: + + [realms] + DEFAULT.REALM = { + # Allow access to principals from OTHER.REALM. + # + # [1:$1@$0] matches single-component principal names and creates + # a selection string containing the principal name and realm. + # + # (.*@OTHER\.REALM) matches against the selection string, so that + # only principals in OTHER.REALM are matched. + # + # s/@OTHER\.REALM$// removes the realm name, leaving behind the + # principal name as the account name. + auth_to_local = RULE:[1:$1@$0](.*@OTHER\.REALM)s/@OTHER\.REALM$// + + # Also allow principals from the default realm. Omit this line + # to only allow access to principals in OTHER.REALM. + auth_to_local = DEFAULT + } + +The **auth_to_local_names** subsection of the :ref:`realms` section +for the default realm can specify explicit mappings from principal +names to local accounts. The key used in this subsection is the +principal name without realm, so it is only safe to use in a Kerberos +environment with a single realm or a tightly controlled set of realms. +An example use of **auth_to_local_names** might be:: + + [realms] + ATHENA.MIT.EDU = { + auth_to_local_names = { + # Careful, these match principals in any realm! + host/example.com = hostaccount + fred = localfred + } + } + +Local authorization behavior can also be modified using plugin +modules; see :ref:`hostrealm_plugin` for details. + + +.. _plugin_config: + +Plugin module configuration +--------------------------- + +Many aspects of Kerberos behavior, such as client preauthentication +and KDC service location, can be modified through the use of plugin +modules. For most of these behaviors, you can use the :ref:`plugins` +section of krb5.conf to register third-party modules, and to switch +off registered or built-in modules. + +A plugin module takes the form of a Unix shared object +(``modname.so``) or Windows DLL (``modname.dll``). If you have +installed a third-party plugin module and want to register it, you do +so using the **module** relation in the appropriate subsection of the +[plugins] section. The value for **module** must give the module name +and the path to the module, separated by a colon. The module name +will often be the same as the shared object's name, but in unusual +cases (such as a shared object which implements multiple modules for +the same interface) it might not be. For example, to register a +client preauthentication module named ``mypreauth`` installed at +``/path/to/mypreauth.so``, you could write:: + + [plugins] + clpreauth = { + module = mypreauth:/path/to/mypreauth.so + } + +Many of the pluggable behaviors in MIT krb5 contain built-in modules +which can be switched off. You can disable a built-in module (or one +you have registered) using the **disable** directive in the +appropriate subsection of the [plugins] section. For example, to +disable the use of .k5identity files to select credential caches, you +could write:: + + [plugins] + ccselect = { + disable = k5identity + } + +If you want to disable multiple modules, specify the **disable** +directive multiple times, giving one module to disable each time. + +Alternatively, you can explicitly specify which modules you want to be +enabled for that behavior using the **enable_only** directive. For +example, to make :ref:`kadmind(8)` check password quality using only a +module you have registered, and no other mechanism, you could write:: + + [plugins] + pwqual = { + module = mymodule:/path/to/mymodule.so + enable_only = mymodule + } + +Again, if you want to specify multiple modules, specify the +**enable_only** directive multiple times, giving one module to enable +each time. + +Some Kerberos interfaces use different mechanisms to register plugin +modules. + + +KDC location modules +~~~~~~~~~~~~~~~~~~~~ + +For historical reasons, modules to control how KDC servers are located +are registered simply by placing the shared object or DLL into the +"libkrb5" subdirectory of the krb5 plugin directory, which defaults to +|libdir|\ ``/krb5/plugins``. For example, Samba's winbind krb5 +locator plugin would be registered by placing its shared object in +|libdir|\ ``/krb5/plugins/libkrb5/winbind_krb5_locator.so``. + + +.. _gssapi_plugin_config: + +GSSAPI mechanism modules +~~~~~~~~~~~~~~~~~~~~~~~~ + +GSSAPI mechanism modules are registered using the file +|sysconfdir|\ ``/gss/mech`` or configuration files in the +|sysconfdir|\ ``/gss/mech.d`` directory with a ``.conf`` +suffix. Each line in these files has the form:: + + name oid pathname [options] + +Only the name, oid, and pathname are required. *name* is the +mechanism name, which may be used for debugging or logging purposes. +*oid* is the object identifier of the GSSAPI mechanism to be +registered. *pathname* is a path to the module shared object or DLL. +*options* (if present) are options provided to the plugin module, +surrounded in square brackets. *type* (if present) can be used to +indicate a special type of module. Currently the only special module +type is "interposer", for a module designed to intercept calls to +other mechanisms. + +If the environment variable **GSS_MECH_CONFIG** is set, its value is +used as the sole mechanism configuration filename. + + +.. _profile_plugin_config: + +Configuration profile modules +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A configuration profile module replaces the information source for +:ref:`krb5.conf(5)` itself. To use a profile module, begin krb5.conf +with the line:: + + module PATHNAME:STRING + +where *PATHNAME* is a path to the module shared object or DLL, and +*STRING* is a string to provide to the module. The module will then +take over, and the rest of krb5.conf will be ignored. diff --git a/krb5-1.21.3/doc/html/_sources/admin/https.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/https.rst.txt new file mode 100644 index 00000000..b4e68b2b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/https.rst.txt @@ -0,0 +1,48 @@ +.. _https: + +HTTPS proxy configuration +========================= + +In addition to being able to use UDP or TCP to communicate directly +with a KDC as is outlined in RFC4120, and with kpasswd services in a +similar fashion, the client libraries can attempt to use an HTTPS +proxy server to communicate with a KDC or kpasswd service, using the +protocol outlined in [MS-KKDCP]. + +Communicating with a KDC through an HTTPS proxy allows clients to +contact servers when network firewalls might otherwise prevent them +from doing so. The use of TLS also encrypts all traffic between the +clients and the KDC, preventing observers from conducting password +dictionary attacks or from observing the client and server principals +being authenticated, at additional computational cost to both clients +and servers. + +An HTTPS proxy server is provided as a feature in some versions of +Microsoft Windows Server, and a WSGI implementation named `kdcproxy` +is available in the python package index. + + +Configuring the clients +----------------------- + +To use an HTTPS proxy, a client host must trust the CA which issued +that proxy's SSL certificate. If that CA's certificate is not in the +system-wide default set of trusted certificates, configure the +following relation in the client host's :ref:`krb5.conf(5)` file in +the appropriate :ref:`realms` subsection:: + + http_anchors = FILE:/etc/krb5/cacert.pem + +Adjust the pathname to match the path of the file which contains a +copy of the CA's certificate. The `http_anchors` option is documented +more fully in :ref:`krb5.conf(5)`. + +Configure the client to access the KDC and kpasswd service by +specifying their locations in its :ref:`krb5.conf(5)` file in the form +of HTTPS URLs for the proxy server:: + + kdc = https://server.fqdn/KdcProxy + kpasswd_server = https://server.fqdn/KdcProxy + +If the proxy and client are properly configured, client commands such +as ``kinit``, ``kvno``, and ``kpasswd`` should all function normally. diff --git a/krb5-1.21.3/doc/html/_sources/admin/index.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/index.rst.txt new file mode 100644 index 00000000..d87b003a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/index.rst.txt @@ -0,0 +1,34 @@ +For administrators +================== + +.. toctree:: + :maxdepth: 1 + + install.rst + conf_files/index.rst + realm_config.rst + database.rst + dbtypes.rst + lockout.rst + conf_ldap.rst + appl_servers.rst + host_config.rst + backup_host.rst + pkinit.rst + otp.rst + spake.rst + dictionary.rst + princ_dns.rst + enctypes.rst + https.rst + auth_indicator.rst + +.. toctree:: + :maxdepth: 1 + + admin_commands/index.rst + ../mitK5defaults.rst + env_variables.rst + troubleshoot.rst + advanced/index.rst + various_envs.rst diff --git a/krb5-1.21.3/doc/html/_sources/admin/install.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/install.rst.txt new file mode 100644 index 00000000..01434a40 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/install.rst.txt @@ -0,0 +1,21 @@ +Installation guide +================== + +Contents +-------- + +.. toctree:: + :maxdepth: 2 + + install_kdc.rst + install_clients.rst + install_appl_srv.rst + + +Additional references +--------------------- + +#. Debian: `Setting up MIT Kerberos 5 + `_ +#. Solaris: `Configuring the Kerberos Service + `_ diff --git a/krb5-1.21.3/doc/html/_sources/admin/install_appl_srv.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/install_appl_srv.rst.txt new file mode 100644 index 00000000..2e198138 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/install_appl_srv.rst.txt @@ -0,0 +1,78 @@ +UNIX Application Servers +======================== + +An application server is a host that provides one or more services +over the network. Application servers can be "secure" or "insecure." +A "secure" host is set up to require authentication from every client +connecting to it. An "insecure" host will still provide Kerberos +authentication, but will also allow unauthenticated clients to +connect. + +If you have Kerberos V5 installed on all of your client machines, MIT +recommends that you make your hosts secure, to take advantage of the +security that Kerberos authentication affords. However, if you have +some clients that do not have Kerberos V5 installed, you can run an +insecure server, and still take advantage of Kerberos V5's single +sign-on capability. + + +.. _keytab_file: + +The keytab file +--------------- + +All Kerberos server machines need a keytab file to authenticate to the +KDC. By default on UNIX-like systems this file is named |keytab|. +The keytab file is an local copy of the host's key. The keytab file +is a potential point of entry for a break-in, and if compromised, +would allow unrestricted access to its host. The keytab file should +be readable only by root, and should exist only on the machine's local +disk. The file should not be part of any backup of the machine, +unless access to the backup data is secured as tightly as access to +the machine's root password. + +In order to generate a keytab for a host, the host must have a +principal in the Kerberos database. The procedure for adding hosts to +the database is described fully in :ref:`principals`. (See +:ref:`replica_host_key` for a brief description.) The keytab is +generated by running :ref:`kadmin(1)` and issuing the :ref:`ktadd` +command. + +For example, to generate a keytab file to allow the host +``trillium.mit.edu`` to authenticate for the services host, ftp, and +pop, the administrator ``joeadmin`` would issue the command (on +``trillium.mit.edu``):: + + trillium% kadmin + Authenticating as principal root/admin@ATHENA.MIT.EDU with password. + Password for root/admin@ATHENA.MIT.EDU: + kadmin: ktadd host/trillium.mit.edu ftp/trillium.mit.edu pop/trillium.mit.edu + Entry for principal host/trillium.mit.edu@ATHENA.MIT.EDU with kvno 3, encryption type aes256-cts-hmac-sha384-192 added to keytab FILE:/etc/krb5.keytab. + kadmin: Entry for principal ftp/trillium.mit.edu@ATHENA.MIT.EDU with kvno 3, encryption type aes256-cts-hmac-sha384-192 added to keytab FILE:/etc/krb5.keytab. + kadmin: Entry for principal pop/trillium.mit.edu@ATHENA.MIT.EDU with kvno 3, encryption type aes256-cts-hmac-sha384-192 added to keytab FILE:/etc/krb5.keytab. + kadmin: quit + trillium% + +If you generate the keytab file on another host, you need to get a +copy of the keytab file onto the destination host (``trillium``, in +the above example) without sending it unencrypted over the network. + + +Some advice about secure hosts +------------------------------ + +Kerberos V5 can protect your host from certain types of break-ins, but +it is possible to install Kerberos V5 and still leave your host +vulnerable to attack. Obviously an installation guide is not the +place to try to include an exhaustive list of countermeasures for +every possible attack, but it is worth noting some of the larger holes +and how to close them. + +We recommend that backups of secure machines exclude the keytab file +(|keytab|). If this is not possible, the backups should at least be +done locally, rather than over a network, and the backup tapes should +be physically secured. + +The keytab file and any programs run by root, including the Kerberos +V5 binaries, should be kept on local disk. The keytab file should be +readable only by root. diff --git a/krb5-1.21.3/doc/html/_sources/admin/install_clients.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/install_clients.rst.txt new file mode 100644 index 00000000..f2c87d07 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/install_clients.rst.txt @@ -0,0 +1,58 @@ +Installing and configuring UNIX client machines +=============================================== + +The Kerberized client programs include :ref:`kinit(1)`, +:ref:`klist(1)`, :ref:`kdestroy(1)`, and :ref:`kpasswd(1)`. All of +these programs are in the directory |bindir|. + +You can often integrate Kerberos with the login system on client +machines, typically through the use of PAM. The details vary by +operating system, and should be covered in your operating system's +documentation. If you do this, you will need to make sure your users +know to use their Kerberos passwords when they log in. + +You will also need to educate your users to use the ticket management +programs kinit, klist, and kdestroy. If you do not have Kerberos +password changing integrated into the native password program (again, +typically through PAM), you will need to educate users to use kpasswd +in place of its non-Kerberos counterparts passwd. + + +Client machine configuration files +---------------------------------- + +Each machine running Kerberos should have a :ref:`krb5.conf(5)` file. +At a minimum, it should define a **default_realm** setting in +:ref:`libdefaults`. If you are not using DNS SRV records +(:ref:`kdc_hostnames`) or URI records (:ref:`kdc_discovery`), it must +also contain a :ref:`realms` section containing information for your +realm's KDCs. + +Consider setting **rdns** to false in order to reduce your dependence +on precisely correct DNS information for service hostnames. Turning +this flag off means that service hostnames will be canonicalized +through forward name resolution (which adds your domain name to +unqualified hostnames, and resolves CNAME records in DNS), but not +through reverse address lookup. The default value of this flag is +true for historical reasons only. + +If you anticipate users frequently logging into remote hosts +(e.g., using ssh) using forwardable credentials, consider setting +**forwardable** to true so that users obtain forwardable tickets by +default. Otherwise users will need to use ``kinit -f`` to get +forwardable tickets. + +Consider adjusting the **ticket_lifetime** setting to match the likely +length of sessions for your users. For instance, if most of your +users will be logging in for an eight-hour workday, you could set the +default to ten hours so that tickets obtained in the morning expire +shortly after the end of the workday. Users can still manually +request longer tickets when necessary, up to the maximum allowed by +each user's principal record on the KDC. + +If a client host may access services in different realms, it may be +useful to define a :ref:`domain_realm` mapping so that clients know +which hosts belong to which realms. However, if your clients and KDC +are running release 1.7 or later, it is also reasonable to leave this +section out on client machines and just define it in the KDC's +krb5.conf. diff --git a/krb5-1.21.3/doc/html/_sources/admin/install_kdc.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/install_kdc.rst.txt new file mode 100644 index 00000000..8cab6514 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/install_kdc.rst.txt @@ -0,0 +1,536 @@ +Installing KDCs +=============== + +When setting up Kerberos in a production environment, it is best to +have multiple replica KDCs alongside with a primary KDC to ensure the +continued availability of the Kerberized services. Each KDC contains +a copy of the Kerberos database. The primary KDC contains the +writable copy of the realm database, which it replicates to the +replica KDCs at regular intervals. All database changes (such as +password changes) are made on the primary KDC. Replica KDCs provide +Kerberos ticket-granting services, but not database administration, +when the primary KDC is unavailable. MIT recommends that you install +all of your KDCs to be able to function as either the primary or one +of the replicas. This will enable you to easily switch your primary +KDC with one of the replicas if necessary (see +:ref:`switch_primary_replica`). This installation procedure is based +on that recommendation. + +.. warning:: + + - The Kerberos system relies on the availability of correct time + information. Ensure that the primary and all replica KDCs have + properly synchronized clocks. + + - It is best to install and run KDCs on secured and dedicated + hardware with limited access. If your KDC is also a file + server, FTP server, Web server, or even just a client machine, + someone who obtained root access through a security hole in any + of those areas could potentially gain access to the Kerberos + database. + + +Install and configure the primary KDC +------------------------------------- + +Install Kerberos either from the OS-provided packages or from the +source (See :ref:`do_build`). + +.. note:: + + For the purpose of this document we will use the following + names:: + + kerberos.mit.edu - primary KDC + kerberos-1.mit.edu - replica KDC + ATHENA.MIT.EDU - realm name + .k5.ATHENA.MIT.EDU - stash file + admin/admin - admin principal + + See :ref:`mitK5defaults` for the default names and locations + of the relevant to this topic files. Adjust the names and + paths to your system environment. + + +Edit KDC configuration files +---------------------------- + +Modify the configuration files, :ref:`krb5.conf(5)` and +:ref:`kdc.conf(5)`, to reflect the correct information (such as +domain-realm mappings and Kerberos servers names) for your realm. +(See :ref:`mitK5defaults` for the recommended default locations for +these files). + +Most of the tags in the configuration have default values that will +work well for most sites. There are some tags in the +:ref:`krb5.conf(5)` file whose values must be specified, and this +section will explain those. + +If the locations for these configuration files differs from the +default ones, set **KRB5_CONFIG** and **KRB5_KDC_PROFILE** environment +variables to point to the krb5.conf and kdc.conf respectively. For +example:: + + export KRB5_CONFIG=/yourdir/krb5.conf + export KRB5_KDC_PROFILE=/yourdir/kdc.conf + + +krb5.conf +~~~~~~~~~ + +If you are not using DNS TXT records (see :ref:`mapping_hostnames`), +you must specify the **default_realm** in the :ref:`libdefaults` +section. If you are not using DNS URI or SRV records (see +:ref:`kdc_hostnames` and :ref:`kdc_discovery`), you must include the +**kdc** tag for each *realm* in the :ref:`realms` section. To +communicate with the kadmin server in each realm, the **admin_server** +tag must be set in the +:ref:`realms` section. + +An example krb5.conf file:: + + [libdefaults] + default_realm = ATHENA.MIT.EDU + + [realms] + ATHENA.MIT.EDU = { + kdc = kerberos.mit.edu + kdc = kerberos-1.mit.edu + admin_server = kerberos.mit.edu + } + + +kdc.conf +~~~~~~~~ + +The kdc.conf file can be used to control the listening ports of the +KDC and kadmind, as well as realm-specific defaults, the database type +and location, and logging. + +An example kdc.conf file:: + + [kdcdefaults] + kdc_listen = 88 + kdc_tcp_listen = 88 + + [realms] + ATHENA.MIT.EDU = { + kadmind_port = 749 + max_life = 12h 0m 0s + max_renewable_life = 7d 0h 0m 0s + master_key_type = aes256-cts + supported_enctypes = aes256-cts:normal aes128-cts:normal + # If the default location does not suit your setup, + # explicitly configure the following values: + # database_name = /var/krb5kdc/principal + # key_stash_file = /var/krb5kdc/.k5.ATHENA.MIT.EDU + # acl_file = /var/krb5kdc/kadm5.acl + } + + [logging] + # By default, the KDC and kadmind will log output using + # syslog. You can instead send log output to files like this: + kdc = FILE:/var/log/krb5kdc.log + admin_server = FILE:/var/log/kadmin.log + default = FILE:/var/log/krb5lib.log + +Replace ``ATHENA.MIT.EDU`` and ``kerberos.mit.edu`` with the name of +your Kerberos realm and server respectively. + +.. note:: + + You have to have write permission on the target directories + (these directories must exist) used by **database_name**, + **key_stash_file**, and **acl_file**. + + +.. _create_db: + +Create the KDC database +----------------------- + +You will use the :ref:`kdb5_util(8)` command on the primary KDC to +create the Kerberos database and the optional :ref:`stash_definition`. + +.. note:: + + If you choose not to install a stash file, the KDC will + prompt you for the master key each time it starts up. This + means that the KDC will not be able to start automatically, + such as after a system reboot. + +:ref:`kdb5_util(8)` will prompt you for the master password for the +Kerberos database. This password can be any string. A good password +is one you can remember, but that no one else can guess. Examples of +bad passwords are words that can be found in a dictionary, any common +or popular name, especially a famous person (or cartoon character), +your username in any form (e.g., forward, backward, repeated twice, +etc.), and any of the sample passwords that appear in this manual. +One example of a password which might be good if it did not appear in +this manual is "MITiys4K5!", which represents the sentence "MIT is +your source for Kerberos 5!" (It's the first letter of each word, +substituting the numeral "4" for the word "for", and includes the +punctuation mark at the end.) + +The following is an example of how to create a Kerberos database and +stash file on the primary KDC, using the :ref:`kdb5_util(8)` command. +Replace ``ATHENA.MIT.EDU`` with the name of your Kerberos realm:: + + shell% kdb5_util create -r ATHENA.MIT.EDU -s + + Initializing database '/usr/local/var/krb5kdc/principal' for realm 'ATHENA.MIT.EDU', + master key name 'K/M@ATHENA.MIT.EDU' + You will be prompted for the database Master Password. + It is important that you NOT FORGET this password. + Enter KDC database master key: <= Type the master password. + Re-enter KDC database master key to verify: <= Type it again. + shell% + +This will create five files in |kdcdir| (or at the locations specified +in :ref:`kdc.conf(5)`): + +* two Kerberos database files, ``principal``, and ``principal.ok`` +* the Kerberos administrative database file, ``principal.kadm5`` +* the administrative database lock file, ``principal.kadm5.lock`` +* the stash file, in this example ``.k5.ATHENA.MIT.EDU``. If you do + not want a stash file, run the above command without the **-s** + option. + +For more information on administrating Kerberos database see +:ref:`db_operations`. + + +.. _admin_acl: + +Add administrators to the ACL file +---------------------------------- + +Next, you need create an Access Control List (ACL) file and put the +Kerberos principal of at least one of the administrators into it. +This file is used by the :ref:`kadmind(8)` daemon to control which +principals may view and make privileged modifications to the Kerberos +database files. The ACL filename is determined by the **acl_file** +variable in :ref:`kdc.conf(5)`; the default is |kdcdir|\ +``/kadm5.acl``. + +For more information on Kerberos ACL file see :ref:`kadm5.acl(5)`. + +.. _addadmin_kdb: + +Add administrators to the Kerberos database +------------------------------------------- + +Next you need to add administrative principals (i.e., principals who +are allowed to administer Kerberos database) to the Kerberos database. +You *must* add at least one principal now to allow communication +between the Kerberos administration daemon kadmind and the kadmin +program over the network for further administration. To do this, use +the kadmin.local utility on the primary KDC. kadmin.local is designed +to be run on the primary KDC host without using Kerberos +authentication to an admin server; instead, it must have read and +write access to the Kerberos database on the local filesystem. + +The administrative principals you create should be the ones you added +to the ACL file (see :ref:`admin_acl`). + +In the following example, the administrative principal ``admin/admin`` +is created:: + + shell% kadmin.local + + kadmin.local: addprinc admin/admin@ATHENA.MIT.EDU + + No policy specified for "admin/admin@ATHENA.MIT.EDU"; + assigning "default". + Enter password for principal admin/admin@ATHENA.MIT.EDU: <= Enter a password. + Re-enter password for principal admin/admin@ATHENA.MIT.EDU: <= Type it again. + Principal "admin/admin@ATHENA.MIT.EDU" created. + kadmin.local: + +.. _start_kdc_daemons: + +Start the Kerberos daemons on the primary KDC +--------------------------------------------- + +At this point, you are ready to start the Kerberos KDC +(:ref:`krb5kdc(8)`) and administrative daemons on the primary KDC. To +do so, type:: + + shell% krb5kdc + shell% kadmind + +Each server daemon will fork and run in the background. + +.. note:: + + Assuming you want these daemons to start up automatically at + boot time, you can add them to the KDC's ``/etc/rc`` or + ``/etc/inittab`` file. You need to have a + :ref:`stash_definition` in order to do this. + +You can verify that they started properly by checking for their +startup messages in the logging locations you defined in +:ref:`krb5.conf(5)` (see :ref:`logging`). For example:: + + shell% tail /var/log/krb5kdc.log + Dec 02 12:35:47 beeblebrox krb5kdc[3187](info): commencing operation + shell% tail /var/log/kadmin.log + Dec 02 12:35:52 beeblebrox kadmind[3189](info): starting + +Any errors the daemons encounter while starting will also be listed in +the logging output. + +As an additional verification, check if :ref:`kinit(1)` succeeds +against the principals that you have created on the previous step +(:ref:`addadmin_kdb`). Run:: + + shell% kinit admin/admin@ATHENA.MIT.EDU + + +Install the replica KDCs +------------------------ + +You are now ready to start configuring the replica KDCs. + +.. note:: + + Assuming you are setting the KDCs up so that you can easily + switch the primary KDC with one of the replicas, you should + perform each of these steps on the primary KDC as well as + the replica KDCs, unless these instructions specify + otherwise. + + +.. _replica_host_key: + +Create host keytabs for replica KDCs +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each KDC needs a ``host`` key in the Kerberos database. These keys +are used for mutual authentication when propagating the database dump +file from the primary KDC to the secondary KDC servers. + +On the primary KDC, connect to administrative interface and create the +host principal for each of the KDCs' ``host`` services. For example, +if the primary KDC were called ``kerberos.mit.edu``, and you had a +replica KDC named ``kerberos-1.mit.edu``, you would type the +following:: + + shell% kadmin + kadmin: addprinc -randkey host/kerberos.mit.edu + No policy specified for "host/kerberos.mit.edu@ATHENA.MIT.EDU"; assigning "default" + Principal "host/kerberos.mit.edu@ATHENA.MIT.EDU" created. + + kadmin: addprinc -randkey host/kerberos-1.mit.edu + No policy specified for "host/kerberos-1.mit.edu@ATHENA.MIT.EDU"; assigning "default" + Principal "host/kerberos-1.mit.edu@ATHENA.MIT.EDU" created. + +It is not strictly necessary to have the primary KDC server in the +Kerberos database, but it can be handy if you want to be able to swap +the primary KDC with one of the replicas. + +Next, extract ``host`` random keys for all participating KDCs and +store them in each host's default keytab file. Ideally, you should +extract each keytab locally on its own KDC. If this is not feasible, +you should use an encrypted session to send them across the network. +To extract a keytab directly on a replica KDC called +``kerberos-1.mit.edu``, you would execute the following command:: + + kadmin: ktadd host/kerberos-1.mit.edu + Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption + type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab. + Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption + type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab. + Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption + type aes256-cts-hmac-sha384-192 added to keytab FILE:/etc/krb5.keytab. + Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption + type arcfour-hmac added to keytab FILE:/etc/krb5.keytab. + +If you are instead extracting a keytab for the replica KDC called +``kerberos-1.mit.edu`` on the primary KDC, you should use a dedicated +temporary keytab file for that machine's keytab:: + + kadmin: ktadd -k /tmp/kerberos-1.keytab host/kerberos-1.mit.edu + Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption + type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab. + Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption + type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab. + +The file ``/tmp/kerberos-1.keytab`` can then be installed as +``/etc/krb5.keytab`` on the host ``kerberos-1.mit.edu``. + + +Configure replica KDCs +~~~~~~~~~~~~~~~~~~~~~~ + +Database propagation copies the contents of the primary's database, +but does not propagate configuration files, stash files, or the kadm5 +ACL file. The following files must be copied by hand to each replica +(see :ref:`mitK5defaults` for the default locations for these files): + +* krb5.conf +* kdc.conf +* kadm5.acl +* master key stash file + +Move the copied files into their appropriate directories, exactly as +on the primary KDC. kadm5.acl is only needed to allow a replica to +swap with the primary KDC. + +The database is propagated from the primary KDC to the replica KDCs +via the :ref:`kpropd(8)` daemon. You must explicitly specify the +principals which are allowed to provide Kerberos dump updates on the +replica machine with a new database. Create a file named kpropd.acl +in the KDC state directory containing the ``host`` principals for each +of the KDCs:: + + host/kerberos.mit.edu@ATHENA.MIT.EDU + host/kerberos-1.mit.edu@ATHENA.MIT.EDU + +.. note:: + + If you expect that the primary and replica KDCs will be + switched at some point of time, list the host principals + from all participating KDC servers in kpropd.acl files on + all of the KDCs. Otherwise, you only need to list the + primary KDC's host principal in the kpropd.acl files of the + replica KDCs. + +Then, add the following line to ``/etc/inetd.conf`` on each KDC +(adjust the path to kpropd):: + + krb5_prop stream tcp nowait root /usr/local/sbin/kpropd kpropd + +You also need to add the following line to ``/etc/services`` on each +KDC, if it is not already present (assuming that the default port is +used):: + + krb5_prop 754/tcp # Kerberos replica propagation + +Restart inetd daemon. + +Alternatively, start :ref:`kpropd(8)` as a stand-alone daemon. This is +required when incremental propagation is enabled. + +Now that the replica KDC is able to accept database propagation, +you’ll need to propagate the database from the primary server. + +NOTE: Do not start the replica KDC yet; you still do not have a copy +of the primary's database. + + +.. _kprop_to_replicas: + +Propagate the database to each replica KDC +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +First, create a dump file of the database on the primary KDC, as +follows:: + + shell% kdb5_util dump /usr/local/var/krb5kdc/replica_datatrans + +Then, manually propagate the database to each replica KDC, as in the +following example:: + + shell% kprop -f /usr/local/var/krb5kdc/replica_datatrans kerberos-1.mit.edu + + Database propagation to kerberos-1.mit.edu: SUCCEEDED + +You will need a script to dump and propagate the database. The +following is an example of a Bourne shell script that will do this. + +.. note:: + + Remember that you need to replace ``/usr/local/var/krb5kdc`` + with the name of the KDC state directory. + +:: + + #!/bin/sh + + kdclist = "kerberos-1.mit.edu kerberos-2.mit.edu" + + kdb5_util dump /usr/local/var/krb5kdc/replica_datatrans + + for kdc in $kdclist + do + kprop -f /usr/local/var/krb5kdc/replica_datatrans $kdc + done + +You will need to set up a cron job to run this script at the intervals +you decided on earlier (see :ref:`db_prop`). + +Now that the replica KDC has a copy of the Kerberos database, you can +start the krb5kdc daemon:: + + shell% krb5kdc + +As with the primary KDC, you will probably want to add this command to +the KDCs' ``/etc/rc`` or ``/etc/inittab`` files, so they will start +the krb5kdc daemon automatically at boot time. + + +Propagation failed? +################### + +You may encounter the following error messages. For a more detailed +discussion on possible causes and solutions click on the error link +to be redirected to :ref:`troubleshoot` section. + +.. include:: ./troubleshoot.rst + :start-after: _prop_failed_start: + :end-before: _prop_failed_end: + + +Add Kerberos principals to the database +--------------------------------------- + +Once your KDCs are set up and running, you are ready to use +:ref:`kadmin(1)` to load principals for your users, hosts, and other +services into the Kerberos database. This procedure is described +fully in :ref:`principals`. + +You may occasionally want to use one of your replica KDCs as the +primary. This might happen if you are upgrading the primary KDC, or +if your primary KDC has a disk crash. See the following section for +the instructions. + + +.. _switch_primary_replica: + +Switching primary and replica KDCs +---------------------------------- + +You may occasionally want to use one of your replica KDCs as the +primary. This might happen if you are upgrading the primary KDC, or +if your primary KDC has a disk crash. + +Assuming you have configured all of your KDCs to be able to function +as either the primary KDC or a replica KDC (as this document +recommends), all you need to do to make the changeover is: + +If the primary KDC is still running, do the following on the *old* +primary KDC: + +#. Kill the kadmind process. +#. Disable the cron job that propagates the database. +#. Run your database propagation script manually, to ensure that the + replicas all have the latest copy of the database (see + :ref:`kprop_to_replicas`). + +On the *new* primary KDC: + +#. Start the :ref:`kadmind(8)` daemon (see :ref:`start_kdc_daemons`). +#. Set up the cron job to propagate the database (see + :ref:`kprop_to_replicas`). +#. Switch the CNAMEs of the old and new primary KDCs. If you can't do + this, you'll need to change the :ref:`krb5.conf(5)` file on every + client machine in your Kerberos realm. + + +Incremental database propagation +-------------------------------- + +If you expect your Kerberos database to become large, you may wish to +set up incremental propagation to replica KDCs. See +:ref:`incr_db_prop` for details. diff --git a/krb5-1.21.3/doc/html/_sources/admin/lockout.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/lockout.rst.txt new file mode 100644 index 00000000..cce44903 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/lockout.rst.txt @@ -0,0 +1,154 @@ +.. _lockout: + +Account lockout +=============== + +As of release 1.8, the KDC can be configured to lock out principals +after a number of failed authentication attempts within a period of +time. Account lockout can make it more difficult to attack a +principal's password by brute force, but also makes it easy for an +attacker to deny access to a principal. + + +Configuring account lockout +--------------------------- + +Account lockout only works for principals with the +**+requires_preauth** flag set. Without this flag, the KDC cannot +know whether or not a client successfully decrypted the ticket it +issued. It is also important to set the **-allow_svr** flag on a +principal to protect its password from an off-line dictionary attack +through a TGS request. You can set these flags on a principal with +:ref:`kadmin(1)` as follows:: + + kadmin: modprinc +requires_preauth -allow_svr PRINCNAME + +Account lockout parameters are configured via :ref:`policy objects +`. There may be an existing policy associated with user +principals (such as the "default" policy), or you may need to create a +new one and associate it with each user principal. + +The policy parameters related to account lockout are: + +* :ref:`maxfailure `: the number of failed attempts + before the principal is locked out +* :ref:`failurecountinterval `: the + allowable interval between failed attempts +* :ref:`lockoutduration `: the amount of time + a principal is locked out for + +Here is an example of setting these parameters on a new policy and +associating it with a principal:: + + kadmin: addpol -maxfailure 10 -failurecountinterval 180 + -lockoutduration 60 lockout_policy + kadmin: modprinc -policy lockout_policy PRINCNAME + + +Testing account lockout +----------------------- + +To test that account lockout is working, try authenticating as the +principal (hopefully not one that might be in use) multiple times with +the wrong password. For instance, if **maxfailure** is set to 2, you +might see:: + + $ kinit user + Password for user@KRBTEST.COM: + kinit: Password incorrect while getting initial credentials + $ kinit user + Password for user@KRBTEST.COM: + kinit: Password incorrect while getting initial credentials + $ kinit user + kinit: Client's credentials have been revoked while getting initial credentials + + +Account lockout principal state +------------------------------- + +A principal entry keeps three pieces of state related to account +lockout: + +* The time of last successful authentication +* The time of last failed authentication +* A counter of failed attempts + +The time of last successful authentication is not actually needed for +the account lockout system to function, but may be of administrative +interest. These fields can be observed with the **getprinc** kadmin +command. For example:: + + kadmin: getprinc user + Principal: user@KRBTEST.COM + ... + Last successful authentication: [never] + Last failed authentication: Mon Dec 03 12:30:33 EST 2012 + Failed password attempts: 2 + ... + +A principal which has been locked out can be administratively unlocked +with the **-unlock** option to the **modprinc** kadmin command:: + + kadmin: modprinc -unlock PRINCNAME + +This command will reset the number of failed attempts to 0. + + +KDC replication and account lockout +----------------------------------- + +The account lockout state of a principal is not replicated by either +traditional :ref:`kprop(8)` or incremental propagation. Because of +this, the number of attempts an attacker can make within a time period +is multiplied by the number of KDCs. For instance, if the +**maxfailure** parameter on a policy is 10 and there are four KDCs in +the environment (a primary and three replicas), an attacker could make +as many as 40 attempts before the principal is locked out on all four +KDCs. + +An administrative unlock is propagated from the primary to the replica +KDCs during the next propagation. Propagation of an administrative +unlock will cause the counter of failed attempts on each replica to +reset to 1 on the next failure. + +If a KDC environment uses a replication strategy other than kprop or +incremental propagation, such as the LDAP KDB module with multi-master +LDAP replication, then account lockout state may be replicated between +KDCs and the concerns of this section may not apply. + + +.. _disable_lockout: + +KDC performance and account lockout +----------------------------------- + +In order to fully track account lockout state, the KDC must write to +the the database on each successful and failed authentication. +Writing to the database is generally more expensive than reading from +it, so these writes may have a significant impact on KDC performance. +As of release 1.9, it is possible to turn off account lockout state +tracking in order to improve performance, by setting the +**disable_last_success** and **disable_lockout** variables in the +database module subsection of :ref:`kdc.conf(5)`. For example:: + + [dbmodules] + DB = { + disable_last_success = true + disable_lockout = true + } + +Of the two variables, setting **disable_last_success** will usually +have the largest positive impact on performance, and will still allow +account lockout policies to operate. However, it will make it +impossible to observe the last successful authentication time with +kadmin. + + +KDC setup and account lockout +----------------------------- + +To update the account lockout state on principals, the KDC must be +able to write to the principal database. For the DB2 module, no +special setup is required. For the LDAP module, the KDC DN must be +granted write access to the principal objects. If the KDC DN has only +read access, account lockout will not function. diff --git a/krb5-1.21.3/doc/html/_sources/admin/otp.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/otp.rst.txt new file mode 100644 index 00000000..29dc520f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/otp.rst.txt @@ -0,0 +1,100 @@ +.. _otp_preauth: + +OTP Preauthentication +===================== + +OTP is a preauthentication mechanism for Kerberos 5 which uses One +Time Passwords (OTP) to authenticate the client to the KDC. The OTP +is passed to the KDC over an encrypted FAST channel in clear-text. +The KDC uses the password along with per-user configuration to proxy +the request to a third-party RADIUS system. This enables +out-of-the-box compatibility with a large number of already widely +deployed proprietary systems. + +Additionally, our implementation of the OTP system allows for the +passing of RADIUS requests over a UNIX domain stream socket. This +permits the use of a local companion daemon which can handle the +details of authentication. + + +Defining token types +-------------------- + +Token types are defined in either :ref:`krb5.conf(5)` or +:ref:`kdc.conf(5)` according to the following format:: + + [otp] + = { + server = (default: see below) + secret = + timeout = (default: 5 [seconds]) + retries = (default: 3) + strip_realm = (default: true) + indicator = (default: none) + } + +If the server field begins with '/', it will be interpreted as a UNIX +socket. Otherwise, it is assumed to be in the format host:port. When +a UNIX domain socket is specified, the secret field is optional and an +empty secret is used by default. If the server field is not +specified, it defaults to |kdcrundir|\ ``/.socket``. + +When forwarding the request over RADIUS, by default the principal is +used in the User-Name attribute of the RADIUS packet. The strip_realm +parameter controls whether the principal is forwarded with or without +the realm portion. + +If an indicator field is present, tickets issued using this token type +will be annotated with the specified authentication indicator (see +:ref:`auth_indicator`). This key may be specified multiple times to +add multiple indicators. + + +The default token type +---------------------- + +A default token type is used internally when no token type is specified for a +given user. It is defined as follows:: + + [otp] + DEFAULT = { + strip_realm = false + } + +The administrator may override the internal ``DEFAULT`` token type +simply by defining a configuration with the same name. + + +Token instance configuration +---------------------------- + +To enable OTP for a client principal, the administrator must define +the **otp** string attribute for that principal. (See +:ref:`set_string`.) The **otp** user string is a JSON string of the +format: + +.. code-block:: xml + + [{ + "type": , + "username": , + "indicators": [, ...] + }, ...] + +This is an array of token objects. Both fields of token objects are +optional. The **type** field names the token type of this token; if +not specified, it defaults to ``DEFAULT``. The **username** field +specifies the value to be sent in the User-Name RADIUS attribute. If +not specified, the principal name is sent, with or without realm as +defined in the token type. The **indicators** field specifies a list +of authentication indicators to annotate tickets with, overriding any +indicators specified in the token type. + +For ease of configuration, an empty array (``[]``) is treated as +equivalent to one DEFAULT token (``[{}]``). + + +Other considerations +-------------------- + +#. FAST is required for OTP to work. diff --git a/krb5-1.21.3/doc/html/_sources/admin/pkinit.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/pkinit.rst.txt new file mode 100644 index 00000000..45817dac --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/pkinit.rst.txt @@ -0,0 +1,354 @@ +.. _pkinit: + +PKINIT configuration +==================== + +PKINIT is a preauthentication mechanism for Kerberos 5 which uses +X.509 certificates to authenticate the KDC to clients and vice versa. +PKINIT can also be used to enable anonymity support, allowing clients +to communicate securely with the KDC or with application servers +without authenticating as a particular client principal. + + +Creating certificates +--------------------- + +PKINIT requires an X.509 certificate for the KDC and one for each +client principal which will authenticate using PKINIT. For anonymous +PKINIT, a KDC certificate is required, but client certificates are +not. A commercially issued server certificate can be used for the KDC +certificate, but generally cannot be used for client certificates. + +The instruction in this section describe how to establish a +certificate authority and create standard PKINIT certificates. Skip +this section if you are using a commercially issued server certificate +as the KDC certificate for anonymous PKINIT, or if you are configuring +a client to use an Active Directory KDC. + + +Generating a certificate authority certificate +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can establish a new certificate authority (CA) for use with a +PKINIT deployment with the commands:: + + openssl genrsa -out cakey.pem 2048 + openssl req -key cakey.pem -new -x509 -out cacert.pem -days 3650 + +The second command will ask for the values of several certificate +fields. These fields can be set to any values. You can adjust the +expiration time of the CA certificate by changing the number after +``-days``. Since the CA certificate must be deployed to client +machines each time it changes, it should normally have an expiration +time far in the future; however, expiration times after 2037 may cause +interoperability issues in rare circumstances. + +The result of these commands will be two files, cakey.pem and +cacert.pem. cakey.pem will contain a 2048-bit RSA private key, which +must be carefully protected. cacert.pem will contain the CA +certificate, which must be placed in the filesystems of the KDC and +each client host. cakey.pem will be required to create KDC and client +certificates. + + +Generating a KDC certificate +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A KDC certificate for use with PKINIT is required to have some unusual +fields, which makes generating them with OpenSSL somewhat complicated. +First, you will need a file containing the following:: + + [kdc_cert] + basicConstraints=CA:FALSE + keyUsage=nonRepudiation,digitalSignature,keyEncipherment,keyAgreement + extendedKeyUsage=1.3.6.1.5.2.3.5 + subjectKeyIdentifier=hash + authorityKeyIdentifier=keyid,issuer + issuerAltName=issuer:copy + subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name + + [kdc_princ_name] + realm=EXP:0,GeneralString:${ENV::REALM} + principal_name=EXP:1,SEQUENCE:kdc_principal_seq + + [kdc_principal_seq] + name_type=EXP:0,INTEGER:2 + name_string=EXP:1,SEQUENCE:kdc_principals + + [kdc_principals] + princ1=GeneralString:krbtgt + princ2=GeneralString:${ENV::REALM} + +If the above contents are placed in extensions.kdc, you can generate +and sign a KDC certificate with the following commands:: + + openssl genrsa -out kdckey.pem 2048 + openssl req -new -out kdc.req -key kdckey.pem + env REALM=YOUR_REALMNAME openssl x509 -req -in kdc.req \ + -CAkey cakey.pem -CA cacert.pem -out kdc.pem -days 365 \ + -extfile extensions.kdc -extensions kdc_cert -CAcreateserial + rm kdc.req + +The second command will ask for the values of certificate fields, +which can be set to any values. In the third command, substitute your +KDC's realm name for YOUR_REALMNAME. You can adjust the certificate's +expiration date by changing the number after ``-days``. Remember to +create a new KDC certificate before the old one expires. + +The result of this operation will be in two files, kdckey.pem and +kdc.pem. Both files must be placed in the KDC's filesystem. +kdckey.pem, which contains the KDC's private key, must be carefully +protected. + +If you examine the KDC certificate with ``openssl x509 -in kdc.pem +-text -noout``, OpenSSL will not know how to display the KDC principal +name in the Subject Alternative Name extension, so it will appear as +``othername:``. This is normal and does not mean +anything is wrong with the KDC certificate. + + +Generating client certificates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +PKINIT client certificates also must have some unusual certificate +fields. To generate a client certificate with OpenSSL for a +single-component principal name, you will need an extensions file +(different from the KDC extensions file above) containing:: + + [client_cert] + basicConstraints=CA:FALSE + keyUsage=digitalSignature,keyEncipherment,keyAgreement + extendedKeyUsage=1.3.6.1.5.2.3.4 + subjectKeyIdentifier=hash + authorityKeyIdentifier=keyid,issuer + issuerAltName=issuer:copy + subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:princ_name + + [princ_name] + realm=EXP:0,GeneralString:${ENV::REALM} + principal_name=EXP:1,SEQUENCE:principal_seq + + [principal_seq] + name_type=EXP:0,INTEGER:1 + name_string=EXP:1,SEQUENCE:principals + + [principals] + princ1=GeneralString:${ENV::CLIENT} + +If the above contents are placed in extensions.client, you can +generate and sign a client certificate with the following commands:: + + openssl genrsa -out clientkey.pem 2048 + openssl req -new -key clientkey.pem -out client.req + env REALM=YOUR_REALMNAME CLIENT=YOUR_PRINCNAME openssl x509 \ + -CAkey cakey.pem -CA cacert.pem -req -in client.req \ + -extensions client_cert -extfile extensions.client \ + -days 365 -out client.pem + rm client.req + +Normally, the first two commands should be run on the client host, and +the resulting client.req file transferred to the certificate authority +host for the third command. As in the previous steps, the second +command will ask for the values of certificate fields, which can be +set to any values. In the third command, substitute your realm's name +for YOUR_REALMNAME and the client's principal name (without realm) for +YOUR_PRINCNAME. You can adjust the certificate's expiration date by +changing the number after ``-days``. + +The result of this operation will be two files, clientkey.pem and +client.pem. Both files must be present on the client's host; +clientkey.pem, which contains the client's private key, must be +protected from access by others. + +As in the KDC certificate, OpenSSL will display the client principal +name as ``othername:`` in the Subject Alternative Name +extension of a PKINIT client certificate. + +If the client principal name contains more than one component +(e.g. ``host/example.com@REALM``), the ``[principals]`` section of +``extensions.client`` must be altered to contain multiple entries. +(Simply setting ``CLIENT`` to ``host/example.com`` would generate a +certificate for ``host\/example.com@REALM`` which would not match the +multi-component principal name.) For a two-component principal, the +section should read:: + + [principals] + princ1=GeneralString:${ENV::CLIENT1} + princ2=GeneralString:${ENV::CLIENT2} + +The environment variables ``CLIENT1`` and ``CLIENT2`` must then be set +to the first and second components when running ``openssl x509``. + + +Configuring the KDC +------------------- + +The KDC must have filesystem access to the KDC certificate (kdc.pem) +and the KDC private key (kdckey.pem). Configure the following +relation in the KDC's :ref:`kdc.conf(5)` file, either in the +:ref:`kdcdefaults` section or in a :ref:`kdc_realms` subsection (with +appropriate pathnames):: + + pkinit_identity = FILE:/var/lib/krb5kdc/kdc.pem,/var/lib/krb5kdc/kdckey.pem + +If any clients will authenticate using regular (as opposed to +anonymous) PKINIT, the KDC must also have filesystem access to the CA +certificate (cacert.pem), and the following configuration (with the +appropriate pathname):: + + pkinit_anchors = FILE:/var/lib/krb5kdc/cacert.pem + +Because of the larger size of requests and responses using PKINIT, you +may also need to allow TCP access to the KDC:: + + kdc_tcp_listen = 88 + +Restart the :ref:`krb5kdc(8)` daemon to pick up the configuration +changes. + +The principal entry for each PKINIT-using client must be configured to +require preauthentication. Ensure this with the command:: + + kadmin -q 'modprinc +requires_preauth YOUR_PRINCNAME' + +Starting with release 1.12, it is possible to remove the long-term +keys of a principal entry, which can save some space in the database +and help to clarify some PKINIT-related error conditions by not asking +for a password:: + + kadmin -q 'purgekeys -all YOUR_PRINCNAME' + +These principal options can also be specified at principal creation +time as follows:: + + kadmin -q 'add_principal +requires_preauth -nokey YOUR_PRINCNAME' + +By default, the KDC requires PKINIT client certificates to have the +standard Extended Key Usage and Subject Alternative Name attributes +for PKINIT. Starting in release 1.16, it is possible to authorize +client certificates based on the subject or other criteria instead of +the standard PKINIT Subject Alternative Name, by setting the +**pkinit_cert_match** string attribute on each client principal entry. +For example:: + + kadmin set_string user@REALM pkinit_cert_match "CN=user@REALM$" + +The **pkinit_cert_match** string attribute follows the syntax used by +the :ref:`krb5.conf(5)` **pkinit_cert_match** relation. To allow the +use of non-PKINIT client certificates, it will also be necessary to +disable key usage checking using the **pkinit_eku_checking** relation; +for example:: + + [kdcdefaults] + pkinit_eku_checking = none + + + +Configuring the clients +----------------------- + +Client hosts must be configured to trust the issuing authority for the +KDC certificate. For a newly established certificate authority, the +client host must have filesystem access to the CA certificate +(cacert.pem) and the following relation in :ref:`krb5.conf(5)` in the +appropriate :ref:`realms` subsection (with appropriate pathnames):: + + pkinit_anchors = FILE:/etc/krb5/cacert.pem + +If the KDC certificate is a commercially issued server certificate, +the issuing certificate is most likely included in a system directory. +You can specify it by filename as above, or specify the whole +directory like so:: + + pkinit_anchors = DIR:/etc/ssl/certs + +A commercially issued server certificate will usually not have the +standard PKINIT principal name or Extended Key Usage extensions, so +the following additional configuration is required:: + + pkinit_eku_checking = kpServerAuth + pkinit_kdc_hostname = hostname.of.kdc.certificate + +Multiple **pkinit_kdc_hostname** relations can be configured to +recognize multiple KDC certificates. If the KDC is an Active +Directory domain controller, setting **pkinit_kdc_hostname** is +necessary, but it should not be necessary to set +**pkinit_eku_checking**. + +To perform regular (as opposed to anonymous) PKINIT authentication, a +client host must have filesystem access to a client certificate +(client.pem), and the corresponding private key (clientkey.pem). +Configure the following relations in the client host's +:ref:`krb5.conf(5)` file in the appropriate :ref:`realms` subsection +(with appropriate pathnames):: + + pkinit_identities = FILE:/etc/krb5/client.pem,/etc/krb5/clientkey.pem + +If the KDC and client are properly configured, it should now be +possible to run ``kinit username`` without entering a password. + + +.. _anonymous_pkinit: + +Anonymous PKINIT +---------------- + +Anonymity support in Kerberos allows a client to obtain a ticket +without authenticating as any particular principal. Such a ticket can +be used as a FAST armor ticket, or to securely communicate with an +application server anonymously. + +To configure anonymity support, you must generate or otherwise procure +a KDC certificate and configure the KDC host, but you do not need to +generate any client certificates. On the KDC, you must set the +**pkinit_identity** variable to provide the KDC certificate, but do +not need to set the **pkinit_anchors** variable or store the issuing +certificate if you won't have any client certificates to verify. On +client hosts, you must set the **pkinit_anchors** variable (and +possibly **pkinit_kdc_hostname** and **pkinit_eku_checking**) in order +to trust the issuing authority for the KDC certificate, but do not +need to set the **pkinit_identities** variable. + +Anonymity support is not enabled by default. To enable it, you must +create the principal ``WELLKNOWN/ANONYMOUS`` using the command:: + + kadmin -q 'addprinc -randkey WELLKNOWN/ANONYMOUS' + +Some Kerberos deployments include application servers which lack +proper access control, and grant some level of access to any user who +can authenticate. In such an environment, enabling anonymity support +on the KDC would present a security issue. If you need to enable +anonymity support for TGTs (for use as FAST armor tickets) without +enabling anonymous authentication to application servers, you can set +the variable **restrict_anonymous_to_tgt** to ``true`` in the +appropriate :ref:`kdc_realms` subsection of the KDC's +:ref:`kdc.conf(5)` file. + +To obtain anonymous credentials on a client, run ``kinit -n``, or +``kinit -n @REALMNAME`` to specify a realm. The resulting tickets +will have the client name ``WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS``. + + +Freshness tokens +---------------- + +Freshness tokens can ensure that the client has recently had access to +its certificate private key. If freshness tokens are not required by +the KDC, a client program with temporary possession of the private key +can compose requests for future timestamps and use them later. + +In release 1.17 and later, freshness tokens are supported by the +client and are sent by the KDC when the client indicates support for +them. Because not all clients support freshness tokens yet, they are +not required by default. To check if freshness tokens are supported +by a realm's clients, look in the KDC logs for the lines:: + + PKINIT: freshness token received from + PKINIT: no freshness token received from + +To require freshness tokens for all clients in a realm (except for +clients authenticating anonymously), set the +**pkinit_require_freshness** variable to ``true`` in the appropriate +:ref:`kdc_realms` subsection of the KDC's :ref:`kdc.conf(5)` file. To +test that this option is in effect, run ``kinit -X disable_freshness`` +and verify that authentication is unsuccessful. diff --git a/krb5-1.21.3/doc/html/_sources/admin/princ_dns.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/princ_dns.rst.txt new file mode 100644 index 00000000..e558cd48 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/princ_dns.rst.txt @@ -0,0 +1,126 @@ +Principal names and DNS +======================= + +Kerberos clients can do DNS lookups to canonicalize service principal +names. This can cause difficulties when setting up Kerberos +application servers, especially when the client's name for the service +is different from what the service thinks its name is. + + +Service principal names +----------------------- + +A frequently used kind of principal name is the host-based service +principal name. This kind of principal name has two components: a +service name and a hostname. For example, ``imap/imap.example.com`` +is the principal name of the "imap" service on the host +"imap.example.com". Other possible service names for the first +component include "host" (remote login services such as ssh), "HTTP", +and "nfs" (Network File System). + +Service administrators often publish well-known hostname aliases that +they would prefer users to use instead of the canonical name of the +service host. This gives service administrators more flexibility in +deploying services. For example, a shell login server might be named +"long-vanity-hostname.example.com", but users will naturally prefer to +type something like "login.example.com". Hostname aliases also allow +for administrators to set up load balancing for some sorts of services +based on rotating ``CNAME`` records in DNS. + + +Service principal canonicalization +---------------------------------- + +In the MIT krb5 client library, canonicalization of host-based service +principals is controlled by the **dns_canonicalize_hostname**, +**rnds**, and **qualify_shortname** variables in :ref:`libdefaults`. + +If **dns_canonicalize_hostname** is set to ``true`` (the default +value), the client performs forward resolution by looking up the IPv4 +and/or IPv6 addresses of the hostname using ``getaddrinfo()``. This +process will typically add a domain suffix to the hostname if needed, +and follow CNAME records in the DNS. If **rdns** is also set to +``true`` (the default), the client will then perform a reverse lookup +of the first returned Internet address using ``getnameinfo()``, +finding the name associated with the PTR record. + +If **dns_canonicalize_hostname** is set to ``false``, the hostname is +not canonicalized using DNS. If the hostname has only one component +(i.e. it contains no "." characters), the host's primary DNS search +domain will be appended, if there is one. The **qualify_shortname** +variable can be used to override or disable this suffix. + +If **dns_canonicalize_hostname** is set to ``fallback`` (added in +release 1.18), the hostname is initially treated according to the +rules for ``dns_canonicalize_hostname=false``. If a ticket request +fails because the service principal is unknown, the hostname will be +canonicalized according to the rules for +``dns_canonicalize_hostname=true`` and the request will be retried. + +In all cases, the hostname is converted to lowercase, and any trailing +dot is removed. + + + +Reverse DNS mismatches +---------------------- + +Sometimes, an enterprise will have control over its forward DNS but +not its reverse DNS. The reverse DNS is sometimes under the control +of the Internet service provider of the enterprise, and the enterprise +may not have much influence in setting up reverse DNS records for its +address space. If there are difficulties with getting forward and +reverse DNS to match, it is best to set ``rdns = false`` on client +machines. + + +Overriding application behavior +------------------------------- + +Applications can choose to use a default hostname component in their +service principal name when accepting authentication, which avoids +some sorts of hostname mismatches. Because not all relevant +applications do this yet, using the :ref:`krb5.conf(5)` setting:: + + [libdefaults] + ignore_acceptor_hostname = true + +will allow the Kerberos library to override the application's choice +of service principal hostname and will allow a server program to +accept incoming authentications using any key in its keytab that +matches the service name and realm name (if given). This setting +defaults to "false" and is available in releases krb5-1.10 and later. + + +Provisioning keytabs +-------------------- + +One service principal entry that should be in the keytab is a +principal whose hostname component is the canonical hostname that +``getaddrinfo()`` reports for all known aliases for the host. If the +reverse DNS information does not match this canonical hostname, an +additional service principal entry should be in the keytab for this +different hostname. + + +Specific application advice +--------------------------- + +Secure shell (ssh) +~~~~~~~~~~~~~~~~~~ + +Setting ``GSSAPIStrictAcceptorCheck = no`` in the configuration file +of modern versions of the openssh daemon will allow the daemon to try +any key in its keytab when accepting a connection, rather than looking +for the keytab entry that matches the host's own idea of its name +(typically the name that ``gethostname()`` returns). This requires +krb5-1.10 or later. + +OpenLDAP (ldapsearch, etc.) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +OpenLDAP's SASL implementation performs reverse DNS lookup in order to +canonicalize service principal names, even if **rdns** is set to +``false`` in the Kerberos configuration. To disable this behavior, +add ``SASL_NOCANON on`` to ``ldap.conf``, or set the +``LDAPSASL_NOCANON`` environment variable. diff --git a/krb5-1.21.3/doc/html/_sources/admin/realm_config.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/realm_config.rst.txt new file mode 100644 index 00000000..9f5ad507 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/realm_config.rst.txt @@ -0,0 +1,268 @@ +Realm configuration decisions +============================= + +Before installing Kerberos V5, it is necessary to consider the +following issues: + +* The name of your Kerberos realm (or the name of each realm, if you + need more than one). +* How you will assign your hostnames to Kerberos realms. +* Which ports your KDC and and kadmind services will use, if they will + not be using the default ports. +* How many replica KDCs you need and where they should be located. +* The hostnames of your primary and replica KDCs. +* How frequently you will propagate the database from the primary KDC + to the replica KDCs. + + +Realm name +---------- + +Although your Kerberos realm can be any ASCII string, convention is to +make it the same as your domain name, in upper-case letters. + +For example, hosts in the domain ``example.com`` would be in the +Kerberos realm:: + + EXAMPLE.COM + +If you need multiple Kerberos realms, MIT recommends that you use +descriptive names which end with your domain name, such as:: + + BOSTON.EXAMPLE.COM + HOUSTON.EXAMPLE.COM + + +.. _mapping_hostnames: + +Mapping hostnames onto Kerberos realms +-------------------------------------- + +Mapping hostnames onto Kerberos realms is done in one of three ways. + +The first mechanism works through a set of rules in the +:ref:`domain_realm` section of :ref:`krb5.conf(5)`. You can specify +mappings for an entire domain or on a per-hostname basis. Typically +you would do this by specifying the mappings for a given domain or +subdomain and listing the exceptions. + +The second mechanism is to use KDC host-based service referrals. With +this method, the KDC's krb5.conf has a full [domain_realm] mapping for +hosts, but the clients do not, or have mappings for only a subset of +the hosts they might contact. When a client needs to contact a server +host for which it has no mapping, it will ask the client realm's KDC +for the service ticket, and will receive a referral to the appropriate +service realm. + +To use referrals, clients must be running MIT krb5 1.6 or later, and +the KDC must be running MIT krb5 1.7 or later. The +**host_based_services** and **no_host_referral** variables in the +:ref:`kdc_realms` section of :ref:`kdc.conf(5)` can be used to +fine-tune referral behavior on the KDC. + +It is also possible for clients to use DNS TXT records, if +**dns_lookup_realm** is enabled in :ref:`krb5.conf(5)`. Such lookups +are disabled by default because DNS is an insecure protocol and security +holes could result if DNS records are spoofed. If enabled, the client +will try to look up a TXT record formed by prepending the prefix +``_kerberos`` to the hostname in question. If that record is not +found, the client will attempt a lookup by prepending ``_kerberos`` to the +host's domain name, then its parent domain, up to the top-level domain. +For the hostname ``boston.engineering.example.com``, the names looked up +would be:: + + _kerberos.boston.engineering.example.com + _kerberos.engineering.example.com + _kerberos.example.com + _kerberos.com + +The value of the first TXT record found is taken as the realm name. + +Even if you do not choose to use this mechanism within your site, +you may wish to set it up anyway, for use when interacting with other sites. + + +Ports for the KDC and admin services +------------------------------------ + +The default ports used by Kerberos are port 88 for the KDC and port +749 for the admin server. You can, however, choose to run on other +ports, as long as they are specified in each host's +:ref:`krb5.conf(5)` files or in DNS SRV records, and the +:ref:`kdc.conf(5)` file on each KDC. For a more thorough treatment of +port numbers used by the Kerberos V5 programs, refer to the +:ref:`conf_firewall`. + + +Replica KDCs +------------ + +Replica KDCs provide an additional source of Kerberos ticket-granting +services in the event of inaccessibility of the primary KDC. The +number of replica KDCs you need and the decision of where to place them, +both physically and logically, depends on the specifics of your +network. + +Kerberos authentication requires that each client be able to contact a +KDC. Therefore, you need to anticipate any likely reason a KDC might +be unavailable and have a replica KDC to take up the slack. + +Some considerations include: + +* Have at least one replica KDC as a backup, for when the primary KDC + is down, is being upgraded, or is otherwise unavailable. +* If your network is split such that a network outage is likely to + cause a network partition (some segment or segments of the network + to become cut off or isolated from other segments), have a replica + KDC accessible to each segment. +* If possible, have at least one replica KDC in a different building + from the primary, in case of power outages, fires, or other + localized disasters. + + +.. _kdc_hostnames: + +Hostnames for KDCs +------------------ + +MIT recommends that your KDCs have a predefined set of CNAME records +(DNS hostname aliases), such as ``kerberos`` for the primary KDC and +``kerberos-1``, ``kerberos-2``, ... for the replica KDCs. This way, +if you need to swap a machine, you only need to change a DNS entry, +rather than having to change hostnames. + +As of MIT krb5 1.4, clients can locate a realm's KDCs through DNS +using SRV records (:rfc:`2782`), assuming the Kerberos realm name is +also a DNS domain name. These records indicate the hostname and port +number to contact for that service, optionally with weighting and +prioritization. The domain name used in the SRV record name is the +realm name. Several different Kerberos-related service names are +used: + +_kerberos._udp + This is for contacting any KDC by UDP. This entry will be used + the most often. Normally you should list port 88 on each of your + KDCs. +_kerberos._tcp + This is for contacting any KDC by TCP. Normally you should use + port 88. This entry should be omitted if the KDC does not listen + on TCP ports, as was the default prior to release 1.13. +_kerberos-master._udp + This entry should refer to those KDCs, if any, that will + immediately see password changes to the Kerberos database. If a + user is logging in and the password appears to be incorrect, the + client will retry with the primary KDC before failing with an + "incorrect password" error given. + + If you have only one KDC, or for whatever reason there is no + accessible KDC that would get database changes faster than the + others, you do not need to define this entry. +_kerberos-adm._tcp + This should list port 749 on your primary KDC. Support for it is + not complete at this time, but it will eventually be used by the + :ref:`kadmin(1)` program and related utilities. For now, you will + also need the **admin_server** variable in :ref:`krb5.conf(5)`. +_kerberos-master._tcp + The corresponding TCP port for _kerberos-master._udp, assuming the + primary KDC listens on a TCP port. +_kpasswd._udp + This entry should list port 464 on your primary KDC. It is used + when a user changes her password. If this entry is not defined + but a _kerberos-adm._tcp entry is defined, the client will use the + _kerberos-adm._tcp entry with the port number changed to 464. +_kpasswd._tcp + The corresponding TCP port for _kpasswd._udp. + +The DNS SRV specification requires that the hostnames listed be the +canonical names, not aliases. So, for example, you might include the +following records in your (BIND-style) zone file:: + + $ORIGIN foobar.com. + _kerberos TXT "FOOBAR.COM" + kerberos CNAME daisy + kerberos-1 CNAME use-the-force-luke + kerberos-2 CNAME bunny-rabbit + _kerberos._udp SRV 0 0 88 daisy + SRV 0 0 88 use-the-force-luke + SRV 0 0 88 bunny-rabbit + _kerberos-master._udp SRV 0 0 88 daisy + _kerberos-adm._tcp SRV 0 0 749 daisy + _kpasswd._udp SRV 0 0 464 daisy + +Clients can also be configured with the explicit location of services +using the **kdc**, **master_kdc**, **admin_server**, and +**kpasswd_server** variables in the :ref:`realms` section of +:ref:`krb5.conf(5)`. Even if some clients will be configured with +explicit server locations, providing SRV records will still benefit +unconfigured clients, and be useful for other sites. + + +.. _kdc_discovery: + +KDC Discovery +------------- + +As of MIT krb5 1.15, clients can also locate KDCs in DNS through URI +records (:rfc:`7553`). Limitations with the SRV record format may +result in extra DNS queries in situations where a client must failover +to other transport types, or find a primary server. The URI record +can convey more information about a realm's KDCs with a single query. + +The client performs a query for the following URI records: + +* ``_kerberos.REALM`` for finding KDCs. +* ``_kerberos-adm.REALM`` for finding kadmin services. +* ``_kpasswd.REALM`` for finding password services. + +The URI record includes a priority, weight, and a URI string that +consists of case-insensitive colon separated fields, in the form +``scheme:[flags]:transport:residual``. + +* *scheme* defines the registered URI type. It should always be + ``krb5srv``. +* *flags* contains zero or more flag characters. Currently the only + valid flag is ``m``, which indicates that the record is for a + primary server. +* *transport* defines the transport type of the residual URL or + address. Accepted values are ``tcp``, ``udp``, or ``kkdcp`` for the + MS-KKDCP type. +* *residual* contains the hostname, IP address, or URL to be + contacted using the specified transport, with an optional port + extension. The MS-KKDCP transport type uses a HTTPS URL, and can + include a port and/or path extension. + +An example of URI records in a zone file:: + + _kerberos.EXAMPLE.COM URI 10 1 krb5srv:m:tcp:kdc1.example.com + URI 20 1 krb5srv:m:udp:kdc2.example.com:89 + URI 40 1 krb5srv::udp:10.10.0.23 + URI 30 1 krb5srv::kkdcp:https://proxy:89/auth + +URI lookups are enabled by default, and can be disabled by setting +**dns_uri_lookup** in the :ref:`libdefaults` section of +:ref:`krb5.conf(5)` to False. When enabled, URI lookups take +precedence over SRV lookups, falling back to SRV lookups if no URI +records are found. + + +.. _db_prop: + +Database propagation +-------------------- + +The Kerberos database resides on the primary KDC, and must be +propagated regularly (usually by a cron job) to the replica KDCs. In +deciding how frequently the propagation should happen, you will need +to balance the amount of time the propagation takes against the +maximum reasonable amount of time a user should have to wait for a +password change to take effect. + +If the propagation time is longer than this maximum reasonable time +(e.g., you have a particularly large database, you have a lot of +replicas, or you experience frequent network delays), you may wish to +cut down on your propagation delay by performing the propagation in +parallel. To do this, have the primary KDC propagate the database to +one set of replicas, and then have each of these replicas propagate +the database to additional replicas. + +See also :ref:`incr_db_prop` diff --git a/krb5-1.21.3/doc/html/_sources/admin/spake.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/spake.rst.txt new file mode 100644 index 00000000..001f9291 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/spake.rst.txt @@ -0,0 +1,56 @@ +.. _spake: + +SPAKE Preauthentication +======================= + +SPAKE preauthentication (added in release 1.17) uses public key +cryptography techniques to protect against :ref:`password dictionary +attacks `. Unlike :ref:`PKINIT `, it does not +require any additional infrastructure such as certificates; it simply +needs to be turned on. Using SPAKE preauthentication may modestly +increase the CPU and network load on the KDC. + +SPAKE preauthentication can use one of four elliptic curve groups for +its password-authenticated key exchange. The recommended group is +``edwards25519``; three NIST curves (``P-256``, ``P-384``, and +``P-521``) are also supported. + +By default, SPAKE with the ``edwards25519`` group is enabled on +clients, but the KDC does not offer SPAKE by default. To turn it on, +set the **spake_preauth_groups** variable in :ref:`libdefaults` to a +list of allowed groups. This variable affects both the client and the +KDC. Simply setting it to ``edwards25519`` is recommended:: + + [libdefaults] + spake_preauth_groups = edwards25519 + +Set the **+requires_preauth** and **-allow_svr** flags on client +principal entries, as you would for any preauthentication mechanism:: + + kadmin: modprinc +requires_preauth -allow_svr PRINCNAME + +Clients which do not implement SPAKE preauthentication will fall back +to encrypted timestamp. + +An active attacker can force a fallback to encrypted timestamp by +modifying the initial KDC response, defeating the protection against +dictionary attacks. To prevent this fallback on clients which do +implement SPAKE preauthentication, set the +**disable_encrypted_timestamp** variable to ``true`` in the +:ref:`realms` subsection for realms whose KDCs offer SPAKE +preauthentication. + +By default, SPAKE preauthentication requires an extra network round +trip to the KDC during initial authentication. If most of the clients +in a realm support SPAKE, this extra round trip can be eliminated +using an optimistic challenge, by setting the +**spake_preauth_kdc_challenge** variable in :ref:`kdcdefaults` to a +single group name:: + + [kdcdefaults] + spake_preauth_kdc_challenge = edwards25519 + +Using optimistic challenge will cause the KDC to do extra work for +initial authentication requests that do not result in SPAKE +preauthentication, but will save work when SPAKE preauthentication is +used. diff --git a/krb5-1.21.3/doc/html/_sources/admin/troubleshoot.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/troubleshoot.rst.txt new file mode 100644 index 00000000..ade5e1f8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/troubleshoot.rst.txt @@ -0,0 +1,135 @@ +.. _troubleshoot: + +Troubleshooting +=============== + +.. _trace_logging: + +Trace logging +------------- + +Most programs using MIT krb5 1.9 or later can be made to provide +information about internal krb5 library operations using trace +logging. To enable this, set the **KRB5_TRACE** environment variable +to a filename before running the program. On many operating systems, +the filename ``/dev/stdout`` can be used to send trace logging output +to standard output. + +Some programs do not honor **KRB5_TRACE**, either because they use +secure library contexts (this generally applies to setuid programs and +parts of the login system) or because they take direct control of the +trace logging system using the API. + +Here is a short example showing trace logging output for an invocation +of the :ref:`kvno(1)` command:: + + shell% env KRB5_TRACE=/dev/stdout kvno krbtgt/KRBTEST.COM + [9138] 1332348778.823276: Getting credentials user@KRBTEST.COM -> + krbtgt/KRBTEST.COM@KRBTEST.COM using ccache + FILE:/me/krb5/build/testdir/ccache + [9138] 1332348778.823381: Retrieving user@KRBTEST.COM -> + krbtgt/KRBTEST.COM@KRBTEST.COM from + FILE:/me/krb5/build/testdir/ccache with result: 0/Unknown code 0 + krbtgt/KRBTEST.COM@KRBTEST.COM: kvno = 1 + + +List of errors +-------------- + +Frequently seen errors +~~~~~~~~~~~~~~~~~~~~~~ + +#. :ref:`init_creds_ETYPE_NOSUPP` + +#. :ref:`cert_chain_ETYPE_NOSUPP` + +#. :ref:`err_cert_chain_cert_expired` + + +Errors seen by admins +~~~~~~~~~~~~~~~~~~~~~ + +.. _prop_failed_start: + +#. :ref:`kprop_no_route` + +#. :ref:`kprop_con_refused` + +#. :ref:`kprop_sendauth_exchange` + +.. _prop_failed_end: + +----- + +.. _init_creds_etype_nosupp: + +KDC has no support for encryption type while getting initial credentials +........................................................................ + +.. _cert_chain_etype_nosupp: + + +credential verification failed: KDC has no support for encryption type +...................................................................... + +This most commonly happens when trying to use a principal with only +DES keys, in a release (MIT krb5 1.7 or later) which disables DES by +default. DES encryption is considered weak due to its inadequate key +size. If you cannot migrate away from its use, you can re-enable DES +by adding ``allow_weak_crypto = true`` to the :ref:`libdefaults` +section of :ref:`krb5.conf(5)`. + + +.. _err_cert_chain_cert_expired: + +Cannot create cert chain: certificate has expired +................................................. + +This error message indicates that PKINIT authentication failed because +the client certificate, KDC certificate, or one of the certificates in +the signing chain above them has expired. + +If the KDC certificate has expired, this message appears in the KDC +log file, and the client will receive a "Preauthentication failed" +error. (Prior to release 1.11, the KDC log file message erroneously +appears as "Out of memory". Prior to release 1.12, the client will +receive a "Generic error".) + +If the client or a signing certificate has expired, this message may +appear in trace_logging_ output from :ref:`kinit(1)` or, starting in +release 1.12, as an error message from kinit or another program which +gets initial tickets. The error message is more likely to appear +properly on the client if the principal entry has no long-term keys. + +.. _kprop_no_route: + +kprop: No route to host while connecting to server +.................................................. + +Make sure that the hostname of the replica KDC (as given to kprop) is +correct, and that any firewalls between the primary and the replica +allow a connection on port 754. + +.. _kprop_con_refused: + +kprop: Connection refused while connecting to server +.................................................... + +If the replica KDC is intended to run kpropd out of inetd, make sure +that inetd is configured to accept krb5_prop connections. inetd may +need to be restarted or sent a SIGHUP to recognize the new +configuration. If the replica is intended to run kpropd in standalone +mode, make sure that it is running. + +.. _kprop_sendauth_exchange: + +kprop: Server rejected authentication (during sendauth exchange) while authenticating to server +............................................................................................... + +Make sure that: + +#. The time is synchronized between the primary and replica KDCs. +#. The master stash file was copied from the primary to the expected + location on the replica. +#. The replica has a keytab file in the default location containing a + ``host`` principal for the replica's hostname. diff --git a/krb5-1.21.3/doc/html/_sources/admin/various_envs.rst.txt b/krb5-1.21.3/doc/html/_sources/admin/various_envs.rst.txt new file mode 100644 index 00000000..64c1795f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/admin/various_envs.rst.txt @@ -0,0 +1,27 @@ +Various links +============= + +Whitepapers +----------- + +#. https://kerberos.org/software/whitepapers.html + + +Tutorials +--------- + +#. Fulvio Ricciardi _ + + +Troubleshooting +--------------- + +#. https://wiki.ncsa.illinois.edu/display/ITS/Windows+Kerberos+Troubleshooting + +#. https://www.shrubbery.net/solaris9ab/SUNWaadm/SYSADV6/p27.html + +#. https://docs.oracle.com/cd/E19253-01/816-4557/trouble-1/index.html + +#. https://docs.microsoft.com/en-us/previous-versions/tn-archive/bb463167(v=technet.10)#EBAA + +#. https://bugs.launchpad.net/ubuntu/+source/libpam-heimdal/+bug/86528 diff --git a/krb5-1.21.3/doc/html/_sources/appdev/gssapi.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/gssapi.rst.txt new file mode 100644 index 00000000..339fd6c7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/gssapi.rst.txt @@ -0,0 +1,727 @@ +Developing with GSSAPI +====================== + +The GSSAPI (Generic Security Services API) allows applications to +communicate securely using Kerberos 5 or other security mechanisms. +We recommend using the GSSAPI (or a higher-level framework which +encompasses GSSAPI, such as SASL) for secure network communication +over using the libkrb5 API directly. + +GSSAPIv2 is specified in :rfc:`2743` and :rfc:`2744`. Also see +:rfc:`7546` for a description of how to use the GSSAPI in a client or +server program. + +This documentation will describe how various ways of using the +GSSAPI will behave with the krb5 mechanism as implemented in MIT krb5, +as well as krb5-specific extensions to the GSSAPI. + + +Name types +---------- + +A GSSAPI application can name a local or remote entity by calling +gss_import_name_, specifying a name type and a value. The following +name types are supported by the krb5 mechanism: + +* **GSS_C_NT_HOSTBASED_SERVICE**: The value should be a string of the + form ``service`` or ``service@hostname``. This is the most common + way to name target services when initiating a security context, and + is the most likely name type to work across multiple mechanisms. + +* **GSS_KRB5_NT_PRINCIPAL_NAME**: The value should be a principal name + string. This name type only works with the krb5 mechanism, and is + defined in the ```` header. + +* **GSS_C_NT_USER_NAME** or **GSS_C_NULL_OID**: The value is treated + as an unparsed principal name string, as above. These name types + may work with mechanisms other than krb5, but will have different + interpretations in those mechanisms. **GSS_C_NT_USER_NAME** is + intended to be used with a local username, which will parse into a + single-component principal in the default realm. + +* **GSS_C_NT_ANONYMOUS**: The value is ignored. The anonymous + principal is used, allowing a client to authenticate to a server + without asserting a particular identity (which may or may not be + allowed by a particular server or Kerberos realm). + +* **GSS_C_NT_MACHINE_UID_NAME**: The value is uid_t object. On + Unix-like systems, the username of the uid is looked up in the + system user database and the resulting username is parsed as a + principal name. + +* **GSS_C_NT_STRING_UID_NAME**: As above, but the value is a decimal + string representation of the uid. + +* **GSS_C_NT_EXPORT_NAME**: The value must be the result of a + gss_export_name_ call. + +* **GSS_KRB5_NT_ENTERPRISE_NAME**: The value should be a krb5 + enterprise name string (see :rfc:`6806` section 5), in the form + ``user@suffix``. This name type is used to convey alias names, and + is defined in the ```` header. (New in + release 1.17.) + +* **GSS_KRB5_NT_X509_CERT**: The value should be an X.509 certificate + encoded according to :rfc:`5280`. This name form can be used for + the desired_name parameter of gss_acquire_cred_impersonate_name(), + to identify the S4U2Self user by certificate. (New in release + 1.19.) + + +Initiator credentials +--------------------- + +A GSSAPI client application uses gss_init_sec_context_ to establish a +security context. The *initiator_cred_handle* parameter determines +what tickets are used to establish the connection. An application can +either pass **GSS_C_NO_CREDENTIAL** to use the default client +credential, or it can use gss_acquire_cred_ beforehand to acquire an +initiator credential. The call to gss_acquire_cred_ may include a +*desired_name* parameter, or it may pass **GSS_C_NO_NAME** if it does +not have a specific name preference. + +If the desired name for a krb5 initiator credential is a host-based +name, it is converted to a principal name of the form +``service/hostname`` in the local realm, where *hostname* is the local +hostname if not specified. The hostname will be canonicalized using +forward name resolution, and possibly also using reverse name +resolution depending on the value of the **rdns** variable in +:ref:`libdefaults`. + +If a desired name is specified in the call to gss_acquire_cred_, the +krb5 mechanism will attempt to find existing tickets for that client +principal name in the default credential cache or collection. If the +default cache type does not support a collection, and the default +cache contains credentials for a different principal than the desired +name, a **GSS_S_CRED_UNAVAIL** error will be returned with a minor +code indicating a mismatch. + +If no existing tickets are available for the desired name, but the +name has an entry in the default client :ref:`keytab_definition`, the +krb5 mechanism will acquire initial tickets for the name using the +default client keytab. + +If no desired name is specified, credential acquisition will be +deferred until the credential is used in a call to +gss_init_sec_context_ or gss_inquire_cred_. If the call is to +gss_init_sec_context_, the target name will be used to choose a client +principal name using the credential cache selection facility. (This +facility might, for instance, try to choose existing tickets for a +client principal in the same realm as the target service). If there +are no existing tickets for the chosen principal, but it is present in +the default client keytab, the krb5 mechanism will acquire initial +tickets using the keytab. + +If the target name cannot be used to select a client principal +(because the credentials are used in a call to gss_inquire_cred_), or +if the credential cache selection facility cannot choose a principal +for it, the default credential cache will be selected if it exists and +contains tickets. + +If the default credential cache does not exist, but the default client +keytab does, the krb5 mechanism will try to acquire initial tickets +for the first principal in the default client keytab. + +If the krb5 mechanism acquires initial tickets using the default +client keytab, the resulting tickets will be stored in the default +cache or collection, and will be refreshed by future calls to +gss_acquire_cred_ as they approach their expire time. + + +Acceptor names +-------------- + +A GSSAPI server application uses gss_accept_sec_context_ to establish +a security context based on tokens provided by the client. The +*acceptor_cred_handle* parameter determines what +:ref:`keytab_definition` entries may be authenticated to by the +client, if the krb5 mechanism is used. + +The simplest choice is to pass **GSS_C_NO_CREDENTIAL** as the acceptor +credential. In this case, clients may authenticate to any service +principal in the default keytab (typically |keytab|, or the value of +the **KRB5_KTNAME** environment variable). This is the recommended +approach if the server application has no specific requirements to the +contrary. + +A server may acquire an acceptor credential with gss_acquire_cred_ and +a *cred_usage* of **GSS_C_ACCEPT** or **GSS_C_BOTH**. If the +*desired_name* parameter is **GSS_C_NO_NAME**, then clients will be +allowed to authenticate to any service principal in the default +keytab, just as if no acceptor credential was supplied. + +If a server wishes to specify a *desired_name* to gss_acquire_cred_, +the most common choice is a host-based name. If the host-based +*desired_name* contains just a *service*, then clients will be allowed +to authenticate to any host-based service principal (that is, a +principal of the form ``service/hostname@REALM``) for the named +service, regardless of hostname or realm, as long as it is present in +the default keytab. If the input name contains both a *service* and a +*hostname*, clients will be allowed to authenticate to any host-based +principal for the named service and hostname, regardless of realm. + +.. note:: + + If a *hostname* is specified, it will be canonicalized + using forward name resolution, and possibly also using + reverse name resolution depending on the value of the + **rdns** variable in :ref:`libdefaults`. + +.. note:: + + If the **ignore_acceptor_hostname** variable in + :ref:`libdefaults` is enabled, then *hostname* will be + ignored even if one is specified in the input name. + +.. note:: + + In MIT krb5 versions prior to 1.10, and in Heimdal's + implementation of the krb5 mechanism, an input name with + just a *service* is treated like an input name of + ``service@localhostname``, where *localhostname* is the + string returned by gethostname(). + +If the *desired_name* is a krb5 principal name or a local system name +type which is mapped to a krb5 principal name, clients will only be +allowed to authenticate to that principal in the default keytab. + + +Name Attributes +--------------- + +In release 1.8 or later, the gss_inquire_name_ and +gss_get_name_attribute_ functions, specified in :rfc:`6680`, can be +used to retrieve name attributes from the *src_name* returned by +gss_accept_sec_context_. The following attributes are defined when +the krb5 mechanism is used: + +.. _gssapi_authind_attr: + +* "auth-indicators" attribute: + +This attribute will be included in the gss_inquire_name_ output if the +ticket contains :ref:`authentication indicators `. +One indicator is returned per invocation of gss_get_name_attribute_, +so multiple invocations may be necessary to retrieve all of the +indicators from the ticket. (New in release 1.15.) + + +Credential store extensions +--------------------------- + +Beginning with release 1.11, the following GSSAPI extensions declared +in ```` can be used to specify how credentials +are acquired or stored:: + + struct gss_key_value_element_struct { + const char *key; + const char *value; + }; + typedef struct gss_key_value_element_struct gss_key_value_element_desc; + + struct gss_key_value_set_struct { + OM_uint32 count; + gss_key_value_element_desc *elements; + }; + typedef const struct gss_key_value_set_struct gss_key_value_set_desc; + typedef const gss_key_value_set_desc *gss_const_key_value_set_t; + + OM_uint32 gss_acquire_cred_from(OM_uint32 *minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec); + + OM_uint32 gss_store_cred_into(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + gss_cred_usage_t cred_usage, + const gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_const_key_value_set_t cred_store, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored); + +The additional *cred_store* parameter allows the caller to specify +information about how the credentials should be obtained and stored. +The following options are supported by the krb5 mechanism: + +* **ccache**: For acquiring initiator credentials, the name of the + :ref:`credential cache ` to which the handle will + refer. For storing credentials, the name of the cache or collection + where the credentials will be stored (see below). + +* **client_keytab**: For acquiring initiator credentials, the name of + the :ref:`keytab ` which will be used, if + necessary, to refresh the credentials in the cache. + +* **keytab**: For acquiring acceptor credentials, the name of the + :ref:`keytab ` to which the handle will refer. + In release 1.19 and later, this option also determines the keytab to + be used for verification when initiator credentials are acquired + using a password and verified. + +* **password**: For acquiring initiator credentials, this option + instructs the mechanism to acquire fresh credentials into a unique + memory credential cache. This option may not be used with the + **ccache** or **client_keytab** options, and a *desired_name* must + be specified. (New in release 1.19.) + +* **rcache**: For acquiring acceptor credentials, the name of the + :ref:`replay cache ` to be used when processing + the initiator tokens. (New in release 1.13.) + +* **verify**: For acquiring initiator credentials, this option + instructs the mechanism to verify the credentials by obtaining a + ticket to a service with a known key. The service key is obtained + from the keytab specified with the **keytab** option or the default + keytab. The value may be the name of a principal in the keytab, or + the empty string. If the empty string is given, any ``host`` + service principal in the keytab may be used. (New in release 1.19.) + +In release 1.20 or later, if a collection name is specified for +**cache** in a call to gss_store_cred_into(), an existing cache for +the client principal within the collection will be selected, or a new +cache will be created within the collection. If *overwrite_cred* is +false and the selected credential cache already exists, a +**GSS_S_DUPLICATE_ELEMENT** error will be returned. If *default_cred* +is true, the primary cache of the collection will be switched to the +selected cache. + + +Importing and exporting credentials +----------------------------------- + +The following GSSAPI extensions can be used to import and export +credentials (declared in ````):: + + OM_uint32 gss_export_cred(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + gss_buffer_t token); + + OM_uint32 gss_import_cred(OM_uint32 *minor_status, + gss_buffer_t token, + gss_cred_id_t *cred_handle); + +The first function serializes a GSSAPI credential handle into a +buffer; the second unseralizes a buffer into a GSSAPI credential +handle. Serializing a credential does not destroy it. If any of the +mechanisms used in *cred_handle* do not support serialization, +gss_export_cred will return **GSS_S_UNAVAILABLE**. As with other +GSSAPI serialization functions, these extensions are only intended to +work with a matching implementation on the other side; they do not +serialize credentials in a standardized format. + +A serialized credential may contain secret information such as ticket +session keys. The serialization format does not protect this +information from eavesdropping or tampering. The calling application +must take care to protect the serialized credential when communicating +it over an insecure channel or to an untrusted party. + +A krb5 GSSAPI credential may contain references to a credential cache, +a client keytab, an acceptor keytab, and a replay cache. These +resources are normally serialized as references to their external +locations (such as the filename of the credential cache). Because of +this, a serialized krb5 credential can only be imported by a process +with similar privileges to the exporter. A serialized credential +should not be trusted if it originates from a source with lower +privileges than the importer, as it may contain references to external +credential cache, keytab, or replay cache resources not accessible to +the originator. + +An exception to the above rule applies when a krb5 GSSAPI credential +refers to a memory credential cache, as is normally the case for +delegated credentials received by gss_accept_sec_context_. In this +case, the contents of the credential cache are serialized, so that the +resulting token may be imported even if the original memory credential +cache no longer exists. + + +Constrained delegation (S4U) +---------------------------- + +The Microsoft S4U2Self and S4U2Proxy Kerberos protocol extensions +allow an intermediate service to acquire credentials from a client to +a target service without requiring the client to delegate a +ticket-granting ticket, if the KDC is configured to allow it. + +To perform a constrained delegation operation, the intermediate +service must submit to the KDC an "evidence ticket" from the client to +the intermediate service. An evidence ticket can be acquired when the +client authenticates to the intermediate service with Kerberos, or +with an S4U2Self request if the KDC allows it. The MIT krb5 GSSAPI +library represents an evidence ticket using a "proxy credential", +which is a special kind of gss_cred_id_t object whose underlying +credential cache contains the evidence ticket and a krbtgt ticket for +the intermediate service. + +To acquire a proxy credential during client authentication, the +service should first create an acceptor credential using the +**GSS_C_BOTH** usage. The application should then pass this +credential as the *acceptor_cred_handle* to gss_accept_sec_context_, +and also pass a *delegated_cred_handle* output parameter to receive a +proxy credential containing the evidence ticket. The output value of +*delegated_cred_handle* may be a delegated ticket-granting ticket if +the client sent one, or a proxy credential if not. If the library can +determine that the client's ticket is not a valid evidence ticket, it +will place **GSS_C_NO_CREDENTIAL** in *delegated_cred_handle*. + +To acquire a proxy credential using an S4U2Self request, the service +can use the following GSSAPI extension:: + + OM_uint32 gss_acquire_cred_impersonate_name(OM_uint32 *minor_status, + gss_cred_id_t icred, + gss_name_t desired_name, + OM_uint32 time_req, + gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec); + +The parameters to this function are similar to those of +gss_acquire_cred_, except that *icred* is used to make an S4U2Self +request to the KDC for a ticket from *desired_name* to the +intermediate service. Both *icred* and *desired_name* are required +for this function; passing **GSS_C_NO_CREDENTIAL** or +**GSS_C_NO_NAME** will cause the call to fail. *icred* must contain a +krbtgt ticket for the intermediate service. The result of this +operation is a proxy credential. (Prior to release 1.18, the result +of this operation may be a regular credential for *desired_name*, if +the KDC issues a non-forwardable ticket.) + +Once the intermediate service has a proxy credential, it can simply +pass it to gss_init_sec_context_ as the *initiator_cred_handle* +parameter, and the desired service as the *target_name* parameter. +The GSSAPI library will present the krbtgt ticket and evidence ticket +in the proxy credential to the KDC in an S4U2Proxy request; if the +intermediate service has the appropriate permissions, the KDC will +issue a ticket from the client to the target service. The GSSAPI +library will then use this ticket to authenticate to the target +service. + +If an application needs to find out whether a credential it holds is a +proxy credential and the name of the intermediate service, it can +query the credential with the **GSS_KRB5_GET_CRED_IMPERSONATOR** OID +(new in release 1.16, declared in ````) using +the gss_inquire_cred_by_oid extension (declared in +````):: + + OM_uint32 gss_inquire_cred_by_oid(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + gss_OID desired_object, + gss_buffer_set_t *data_set); + +If the call succeeds and *cred_handle* is a proxy credential, +*data_set* will be set to a single-element buffer set containing the +unparsed principal name of the intermediate service. If *cred_handle* +is not a proxy credential, *data_set* will be set to an empty buffer +set. If the library does not support the query, +gss_inquire_cred_by_oid will return **GSS_S_UNAVAILABLE**. + + +AEAD message wrapping +--------------------- + +The following GSSAPI extensions (declared in +````) can be used to wrap and unwrap messages +with additional "associated data" which is integrity-checked but is +not included in the output buffer:: + + OM_uint32 gss_wrap_aead(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, gss_qop_t qop_req, + gss_buffer_t input_assoc_buffer, + gss_buffer_t input_payload_buffer, + int *conf_state, + gss_buffer_t output_message_buffer); + + OM_uint32 gss_unwrap_aead(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t input_assoc_buffer, + gss_buffer_t output_payload_buffer, + int *conf_state, + gss_qop_t *qop_state); + +Wrap tokens created with gss_wrap_aead will successfully unwrap only +if the same *input_assoc_buffer* contents are presented to +gss_unwrap_aead. + + +IOV message wrapping +-------------------- + +The following extensions (declared in ````) can +be used for in-place encryption, fine-grained control over wrap token +layout, and for constructing wrap tokens compatible with Microsoft DCE +RPC:: + + typedef struct gss_iov_buffer_desc_struct { + OM_uint32 type; + gss_buffer_desc buffer; + } gss_iov_buffer_desc, *gss_iov_buffer_t; + + OM_uint32 gss_wrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, int iov_count); + + OM_uint32 gss_unwrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, int iov_count); + + OM_uint32 gss_wrap_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count); + + OM_uint32 gss_release_iov_buffer(OM_uint32 *minor_status, + gss_iov_buffer_desc *iov, + int iov_count); + +The caller of gss_wrap_iov provides an array of gss_iov_buffer_desc +structures, each containing a type and a gss_buffer_desc structure. +Valid types include: + +* **GSS_C_BUFFER_TYPE_DATA**: A data buffer to be included in the + token, and to be encrypted or decrypted in-place if the token is + confidentiality-protected. + +* **GSS_C_BUFFER_TYPE_HEADER**: The GSSAPI wrap token header and + underlying cryptographic header. + +* **GSS_C_BUFFER_TYPE_TRAILER**: The cryptographic trailer, if one is + required. + +* **GSS_C_BUFFER_TYPE_PADDING**: Padding to be combined with the data + during encryption and decryption. (The implementation may choose to + place padding in the trailer buffer, in which case it will set the + padding buffer length to 0.) + +* **GSS_C_BUFFER_TYPE_STREAM**: For unwrapping only, a buffer + containing a complete wrap token in standard format to be unwrapped. + +* **GSS_C_BUFFER_TYPE_SIGN_ONLY**: A buffer to be included in the + token's integrity protection checksum, but not to be encrypted or + included in the token itself. + +For gss_wrap_iov, the IOV list should contain one HEADER buffer, +followed by zero or more SIGN_ONLY buffers, followed by one or more +DATA buffers, followed by a TRAILER buffer. The memory pointed to by +the buffers is not required to be contiguous or in any particular +order. If *conf_req_flag* is true, DATA buffers will be encrypted +in-place, while SIGN_ONLY buffers will not be modified. + +The type of an output buffer may be combined with +**GSS_C_BUFFER_FLAG_ALLOCATE** to request that gss_wrap_iov allocate +the buffer contents. If gss_wrap_iov allocates a buffer, it sets the +**GSS_C_BUFFER_FLAG_ALLOCATED** flag on the buffer type. +gss_release_iov_buffer can be used to release all allocated buffers +within an iov list and unset their allocated flags. Here is an +example of how gss_wrap_iov can be used with allocation requested +(*ctx* is assumed to be a previously established gss_ctx_id_t):: + + OM_uint32 major, minor; + gss_iov_buffer_desc iov[4]; + char str[] = "message"; + + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE; + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[1].buffer.value = str; + iov[1].buffer.length = strlen(str); + iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_FLAG_ALLOCATE; + iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_FLAG_ALLOCATE; + + major = gss_wrap_iov(&minor, ctx, 1, GSS_C_QOP_DEFAULT, NULL, + iov, 4); + if (GSS_ERROR(major)) + handle_error(major, minor); + + /* Transmit or otherwise use resulting buffers. */ + + (void)gss_release_iov_buffer(&minor, iov, 4); + +If the caller does not choose to request buffer allocation by +gss_wrap_iov, it should first call gss_wrap_iov_length to query the +lengths of the HEADER, PADDING, and TRAILER buffers. DATA buffers +must be provided in the iov list so that padding length can be +computed correctly, but the output buffers need not be initialized. +Here is an example of using gss_wrap_iov_length and gss_wrap_iov:: + + OM_uint32 major, minor; + gss_iov_buffer_desc iov[4]; + char str[1024] = "message", *ptr; + + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[1].buffer.value = str; + iov[1].buffer.length = strlen(str); + + iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING; + iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER; + + major = gss_wrap_iov_length(&minor, ctx, 1, GSS_C_QOP_DEFAULT, + NULL, iov, 4); + if (GSS_ERROR(major)) + handle_error(major, minor); + if (strlen(str) + iov[0].buffer.length + iov[2].buffer.length + + iov[3].buffer.length > sizeof(str)) + handle_out_of_space_error(); + ptr = str + strlen(str); + iov[0].buffer.value = ptr; + ptr += iov[0].buffer.length; + iov[2].buffer.value = ptr; + ptr += iov[2].buffer.length; + iov[3].buffer.value = ptr; + + major = gss_wrap_iov(&minor, ctx, 1, GSS_C_QOP_DEFAULT, NULL, + iov, 4); + if (GSS_ERROR(major)) + handle_error(major, minor); + +If the context was established using the **GSS_C_DCE_STYLE** flag +(described in :rfc:`4757`), wrap tokens compatible with Microsoft DCE +RPC can be constructed. In this case, the IOV list must include a +SIGN_ONLY buffer, a DATA buffer, a second SIGN_ONLY buffer, and a +HEADER buffer in that order (the order of the buffer contents remains +arbitrary). The application must pad the DATA buffer to a multiple of +16 bytes as no padding or trailer buffer is used. + +gss_unwrap_iov may be called with an IOV list just like one which +would be provided to gss_wrap_iov. DATA buffers will be decrypted +in-place if they were encrypted, and SIGN_ONLY buffers will not be +modified. + +Alternatively, gss_unwrap_iov may be called with a single STREAM +buffer, zero or more SIGN_ONLY buffers, and a single DATA buffer. The +STREAM buffer is interpreted as a complete wrap token. The STREAM +buffer will be modified in-place to decrypt its contents. The DATA +buffer will be initialized to point to the decrypted data within the +STREAM buffer, unless it has the **GSS_C_BUFFER_FLAG_ALLOCATE** flag +set, in which case it will be initialized with a copy of the decrypted +data. Here is an example (*token* and *token_len* are assumed to be a +pre-existing pointer and length for a modifiable region of data):: + + OM_uint32 major, minor; + gss_iov_buffer_desc iov[2]; + + iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM; + iov[0].buffer.value = token; + iov[0].buffer.length = token_len; + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + major = gss_unwrap_iov(&minor, ctx, NULL, NULL, iov, 2); + if (GSS_ERROR(major)) + handle_error(major, minor); + + /* Decrypted data is in iov[1].buffer, pointing to a subregion of + * token. */ + +.. _gssapi_mic_token: + +IOV MIC tokens +-------------- + +The following extensions (declared in ````) can +be used in release 1.12 or later to construct and verify MIC tokens +using an IOV list:: + + OM_uint32 gss_get_mic_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t qop_req, + gss_iov_buffer_desc *iov, + int iov_count); + + OM_uint32 gss_get_mic_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t qop_req, + gss_iov_buffer_desc *iov, + iov_count); + + OM_uint32 gss_verify_mic_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count); + +The caller of gss_get_mic_iov provides an array of gss_iov_buffer_desc +structures, each containing a type and a gss_buffer_desc structure. +Valid types include: + +* **GSS_C_BUFFER_TYPE_DATA** and **GSS_C_BUFFER_TYPE_SIGN_ONLY**: The + corresponding buffer for each of these types will be signed for the + MIC token, in the order provided. + +* **GSS_C_BUFFER_TYPE_MIC_TOKEN**: The GSSAPI MIC token. + +The type of the MIC_TOKEN buffer may be combined with +**GSS_C_BUFFER_FLAG_ALLOCATE** to request that gss_get_mic_iov +allocate the buffer contents. If gss_get_mic_iov allocates the +buffer, it sets the **GSS_C_BUFFER_FLAG_ALLOCATED** flag on the buffer +type. gss_release_iov_buffer can be used to release all allocated +buffers within an iov list and unset their allocated flags. Here is +an example of how gss_get_mic_iov can be used with allocation +requested (*ctx* is assumed to be a previously established +gss_ctx_id_t):: + + OM_uint32 major, minor; + gss_iov_buffer_desc iov[3]; + + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[0].buffer.value = "sign1"; + iov[0].buffer.length = 5; + iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[1].buffer.value = "sign2"; + iov[1].buffer.length = 5; + iov[2].type = GSS_IOV_BUFFER_TYPE_MIC_TOKEN | GSS_IOV_BUFFER_FLAG_ALLOCATE; + + major = gss_get_mic_iov(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 3); + if (GSS_ERROR(major)) + handle_error(major, minor); + + /* Transmit or otherwise use iov[2].buffer. */ + + (void)gss_release_iov_buffer(&minor, iov, 3); + +If the caller does not choose to request buffer allocation by +gss_get_mic_iov, it should first call gss_get_mic_iov_length to query +the length of the MIC_TOKEN buffer. Here is an example of using +gss_get_mic_iov_length and gss_get_mic_iov:: + + OM_uint32 major, minor; + gss_iov_buffer_desc iov[2]; + char data[1024]; + + iov[0].type = GSS_IOV_BUFFER_TYPE_MIC_TOKEN; + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[1].buffer.value = "message"; + iov[1].buffer.length = 7; + + major = gss_get_mic_iov_length(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 2); + if (GSS_ERROR(major)) + handle_error(major, minor); + if (iov[0].buffer.length > sizeof(data)) + handle_out_of_space_error(); + iov[0].buffer.value = data; + + major = gss_get_mic_iov(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 2); + if (GSS_ERROR(major)) + handle_error(major, minor); + + +.. _gss_accept_sec_context: https://tools.ietf.org/html/rfc2744.html#section-5.1 +.. _gss_acquire_cred: https://tools.ietf.org/html/rfc2744.html#section-5.2 +.. _gss_export_name: https://tools.ietf.org/html/rfc2744.html#section-5.13 +.. _gss_get_name_attribute: https://tools.ietf.org/html/6680.html#section-7.5 +.. _gss_import_name: https://tools.ietf.org/html/rfc2744.html#section-5.16 +.. _gss_init_sec_context: https://tools.ietf.org/html/rfc2744.html#section-5.19 +.. _gss_inquire_name: https://tools.ietf.org/html/rfc6680.txt#section-7.4 +.. _gss_inquire_cred: https://tools.ietf.org/html/rfc2744.html#section-5.21 diff --git a/krb5-1.21.3/doc/html/_sources/appdev/h5l_mit_apidiff.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/h5l_mit_apidiff.rst.txt new file mode 100644 index 00000000..b721b57b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/h5l_mit_apidiff.rst.txt @@ -0,0 +1,28 @@ +Differences between Heimdal and MIT Kerberos API +================================================ + +.. tabularcolumns:: |l|l| + +.. table:: + + ======================================== ================================================= + :c:func:`krb5_auth_con_getaddrs()` H5l: If either of the pointers to local_addr + and remote_addr is not NULL, it is freed + first and then reallocated before being + populated with the content of corresponding + address from authentication context. + :c:func:`krb5_auth_con_setaddrs()` H5l: If either address is NULL, the previous + address remains in place + :c:func:`krb5_auth_con_setports()` H5l: Not implemented as of version 1.3.3 + :c:func:`krb5_auth_con_setrecvsubkey()` H5l: If either port is NULL, the previous + port remains in place + :c:func:`krb5_auth_con_setsendsubkey()` H5l: Not implemented as of version 1.3.3 + :c:func:`krb5_cc_set_config()` MIT: Before version 1.10 it was assumed that + the last argument *data* is ALWAYS non-zero. + :c:func:`krb5_cccol_last_change_time()` MIT: not implemented + :c:func:`krb5_set_default_realm()` H5l: Caches the computed default realm context + field. If the second argument is NULL, + it tries to retrieve it from libdefaults or DNS. + MIT: Computes the default realm each time + if it wasn't explicitly set in the context + ======================================== ================================================= diff --git a/krb5-1.21.3/doc/html/_sources/appdev/index.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/index.rst.txt new file mode 100644 index 00000000..961bb1e9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/index.rst.txt @@ -0,0 +1,16 @@ +For application developers +========================== + +.. toctree:: + :maxdepth: 1 + + gssapi.rst + y2038.rst + h5l_mit_apidiff.rst + init_creds.rst + princ_handle.rst + +.. toctree:: + :maxdepth: 1 + + refs/index.rst diff --git a/krb5-1.21.3/doc/html/_sources/appdev/init_creds.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/init_creds.rst.txt new file mode 100644 index 00000000..5c3c0a87 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/init_creds.rst.txt @@ -0,0 +1,304 @@ +Initial credentials +=================== + +Software that performs tasks such as logging users into a computer +when they type their Kerberos password needs to get initial +credentials (usually ticket granting tickets) from Kerberos. Such +software shares some behavior with the :ref:`kinit(1)` program. + +Whenever a program grants access to a resource (such as a local login +session on a desktop computer) based on a user successfully getting +initial Kerberos credentials, it must verify those credentials against +a secure shared secret (e.g., a host keytab) to ensure that the user +credentials actually originate from a legitimate KDC. Failure to +perform this verification is a critical vulnerability, because a +malicious user can execute the "Zanarotti attack": the user constructs +a fake response that appears to come from the legitimate KDC, but +whose contents come from an attacker-controlled KDC. + +Some applications read a Kerberos password over the network (ideally +over a secure channel), which they then verify against the KDC. While +this technique may be the only practical way to integrate Kerberos +into some existing legacy systems, its use is contrary to the original +design goals of Kerberos. + +The function :c:func:`krb5_get_init_creds_password` will get initial +credentials for a client using a password. An application that needs +to verify the credentials can call :c:func:`krb5_verify_init_creds`. +Here is an example of code to obtain and verify TGT credentials, given +strings *princname* and *password* for the client principal name and +password:: + + krb5_error_code ret; + krb5_creds creds; + krb5_principal client_princ = NULL; + + memset(&creds, 0, sizeof(creds)); + ret = krb5_parse_name(context, princname, &client_princ); + if (ret) + goto cleanup; + ret = krb5_get_init_creds_password(context, &creds, client_princ, + password, NULL, NULL, 0, NULL, NULL); + if (ret) + goto cleanup; + ret = krb5_verify_init_creds(context, &creds, NULL, NULL, NULL, NULL); + + cleanup: + krb5_free_principal(context, client_princ); + krb5_free_cred_contents(context, &creds); + return ret; + +Options for get_init_creds +-------------------------- + +The function :c:func:`krb5_get_init_creds_password` takes an options +parameter (which can be a null pointer). Use the function +:c:func:`krb5_get_init_creds_opt_alloc` to allocate an options +structure, and :c:func:`krb5_get_init_creds_opt_free` to free it. For +example:: + + krb5_error_code ret; + krb5_get_init_creds_opt *opt = NULL; + krb5_creds creds; + + memset(&creds, 0, sizeof(creds)); + ret = krb5_get_init_creds_opt_alloc(context, &opt); + if (ret) + goto cleanup; + krb5_get_init_creds_opt_set_tkt_life(opt, 24 * 60 * 60); + ret = krb5_get_init_creds_password(context, &creds, client_princ, + password, NULL, NULL, 0, NULL, opt); + if (ret) + goto cleanup; + + cleanup: + krb5_get_init_creds_opt_free(context, opt); + krb5_free_cred_contents(context, &creds); + return ret; + +Getting anonymous credentials +----------------------------- + +As of release 1.8, it is possible to obtain fully anonymous or +partially anonymous (realm-exposed) credentials, if the KDC supports +it. The MIT KDC supports issuing fully anonymous credentials as of +release 1.8 if configured appropriately (see :ref:`anonymous_pkinit`), +but does not support issuing realm-exposed anonymous credentials at +this time. + +To obtain fully anonymous credentials, call +:c:func:`krb5_get_init_creds_opt_set_anonymous` on the options +structure to set the anonymous flag, and specify a client principal +with the KDC's realm and a single empty data component (the principal +obtained by parsing ``@``\ *realmname*). Authentication will take +place using anonymous PKINIT; if successful, the client principal of +the resulting tickets will be +``WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS``. Here is an example:: + + krb5_get_init_creds_opt_set_anonymous(opt, 1); + ret = krb5_build_principal(context, &client_princ, strlen(myrealm), + myrealm, "", (char *)NULL); + if (ret) + goto cleanup; + ret = krb5_get_init_creds_password(context, &creds, client_princ, + password, NULL, NULL, 0, NULL, opt); + if (ret) + goto cleanup; + +To obtain realm-exposed anonymous credentials, set the anonymous flag +on the options structure as above, but specify a normal client +principal in order to prove membership in the realm. Authentication +will take place as it normally does; if successful, the client +principal of the resulting tickets will be ``WELLKNOWN/ANONYMOUS@``\ +*realmname*. + +User interaction +---------------- + +Authenticating a user usually requires the entry of secret +information, such as a password. A password can be supplied directly +to :c:func:`krb5_get_init_creds_password` via the *password* +parameter, or the application can supply prompter and/or responder +callbacks instead. If callbacks are used, the user can also be +queried for other secret information such as a PIN, informed of +impending password expiration, or prompted to change a password which +has expired. + +Prompter callback +~~~~~~~~~~~~~~~~~ + +A prompter callback can be specified via the *prompter* and *data* +parameters to :c:func:`krb5_get_init_creds_password`. The prompter +will be invoked each time the krb5 library has a question to ask or +information to present. When the prompter callback is invoked, the +*banner* argument (if not null) is intended to be displayed to the +user, and the questions to be answered are specified in the *prompts* +array. Each prompt contains a text question in the *prompt* field, a +*hidden* bit to indicate whether the answer should be hidden from +display, and a storage area for the answer in the *reply* field. The +callback should fill in each question's ``reply->data`` with the +answer, up to a maximum number of ``reply->length`` bytes, and then +reset ``reply->length`` to the length of the answer. + +A prompter callback can call :c:func:`krb5_get_prompt_types` to get an +array of type constants corresponding to the prompts, to get +programmatic information about the semantic meaning of the questions. +:c:func:`krb5_get_prompt_types` may return a null pointer if no prompt +type information is available. + +Text-based applications can use a built-in text prompter +implementation by supplying :c:func:`krb5_prompter_posix` as the +*prompter* parameter and a null pointer as the *data* parameter. For +example:: + + ret = krb5_get_init_creds_password(context, &creds, client_princ, + NULL, krb5_prompter_posix, NULL, 0, + NULL, NULL); + +Responder callback +~~~~~~~~~~~~~~~~~~ + +A responder callback can be specified through the init_creds options +using the :c:func:`krb5_get_init_creds_opt_set_responder` function. +Responder callbacks can present a more sophisticated user interface +for authentication secrets. The responder callback is usually invoked +only once per authentication, with a list of questions produced by all +of the allowed preauthentication mechanisms. + +When the responder callback is invoked, the *rctx* argument can be +accessed to obtain the list of questions and to answer them. The +:c:func:`krb5_responder_list_questions` function retrieves an array of +question types. For each question type, the +:c:func:`krb5_responder_get_challenge` function retrieves additional +information about the question, if applicable, and the +:c:func:`krb5_responder_set_answer` function sets the answer. + +Responder question types, challenges, and answers are UTF-8 strings. +The question type is a well-known string; the meaning of the challenge +and answer depend on the question type. If an application does not +understand a question type, it cannot interpret the challenge or +provide an answer. Failing to answer a question typically results in +the prompter callback being used as a fallback. + +Password question +################# + +The :c:macro:`KRB5_RESPONDER_QUESTION_PASSWORD` (or ``"password"``) +question type requests the user's password. This question does not +have a challenge, and the response is simply the password string. + +One-time password question +########################## + +The :c:macro:`KRB5_RESPONDER_QUESTION_OTP` (or ``"otp"``) question +type requests a choice among one-time password tokens and the PIN and +value for the chosen token. The challenge and answer are JSON-encoded +strings, but an application can use convenience functions to avoid +doing any JSON processing itself. + +The :c:func:`krb5_responder_otp_get_challenge` function decodes the +challenge into a krb5_responder_otp_challenge structure. The +:c:func:`krb5_responder_otp_set_answer` function selects one of the +token information elements from the challenge and supplies the value +and pin for that token. + +PKINIT password or PIN question +############################### + +The :c:macro:`KRB5_RESPONDER_QUESTION_PKINIT` (or ``"pkinit"``) question +type requests PINs for hardware devices and/or passwords for encrypted +credentials which are stored on disk, potentially also supplying +information about the state of the hardware devices. The challenge and +answer are JSON-encoded strings, but an application can use convenience +functions to avoid doing any JSON processing itself. + +The :c:func:`krb5_responder_pkinit_get_challenge` function decodes the +challenges into a krb5_responder_pkinit_challenge structure. The +:c:func:`krb5_responder_pkinit_set_answer` function can be used to +supply the PIN or password for a particular client credential, and can +be called multiple times. + +Example +####### + +Here is an example of using a responder callback:: + + static krb5_error_code + my_responder(krb5_context context, void *data, + krb5_responder_context rctx) + { + krb5_error_code ret; + krb5_responder_otp_challenge *chl; + + if (krb5_responder_get_challenge(context, rctx, + KRB5_RESPONDER_QUESTION_PASSWORD)) { + ret = krb5_responder_set_answer(context, rctx, + KRB5_RESPONDER_QUESTION_PASSWORD, + "open sesame"); + if (ret) + return ret; + } + ret = krb5_responder_otp_get_challenge(context, rctx, &chl); + if (ret == 0 && chl != NULL) { + ret = krb5_responder_otp_set_answer(context, rctx, 0, "1234", + NULL); + krb5_responder_otp_challenge_free(context, rctx, chl); + if (ret) + return ret; + } + return 0; + } + + static krb5_error_code + get_creds(krb5_context context, krb5_principal client_princ) + { + krb5_error_code ret; + krb5_get_init_creds_opt *opt = NULL; + krb5_creds creds; + + memset(&creds, 0, sizeof(creds)); + ret = krb5_get_init_creds_opt_alloc(context, &opt); + if (ret) + goto cleanup; + ret = krb5_get_init_creds_opt_set_responder(context, opt, my_responder, + NULL); + if (ret) + goto cleanup; + ret = krb5_get_init_creds_password(context, &creds, client_princ, + NULL, NULL, NULL, 0, NULL, opt); + + cleanup: + krb5_get_init_creds_opt_free(context, opt); + krb5_free_cred_contents(context, &creds); + return ret; + } + +Verifying initial credentials +----------------------------- + +Use the function :c:func:`krb5_verify_init_creds` to verify initial +credentials. It takes an options structure (which can be a null +pointer). Use :c:func:`krb5_verify_init_creds_opt_init` to initialize +the caller-allocated options structure, and +:c:func:`krb5_verify_init_creds_opt_set_ap_req_nofail` to set the +"nofail" option. For example:: + + krb5_verify_init_creds_opt vopt; + + krb5_verify_init_creds_opt_init(&vopt); + krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, 1); + ret = krb5_verify_init_creds(context, &creds, NULL, NULL, NULL, &vopt); + +The confusingly named "nofail" option, when set, means that the +verification must actually succeed in order for +:c:func:`krb5_verify_init_creds` to indicate success. The default +state of this option (cleared) means that if there is no key material +available to verify the user credentials, the verification will +succeed anyway. (The default can be changed by a configuration file +setting.) + +This accommodates a use case where a large number of unkeyed shared +desktop workstations need to allow users to log in using Kerberos. +The security risks from this practice are mitigated by the absence of +valuable state on the shared workstations---any valuable resources +that the users would access reside on networked servers. diff --git a/krb5-1.21.3/doc/html/_sources/appdev/princ_handle.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/princ_handle.rst.txt new file mode 100644 index 00000000..455f00a4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/princ_handle.rst.txt @@ -0,0 +1,79 @@ +Principal manipulation and parsing +================================== + +Kerberos principal structure + +.. + +:c:type:`krb5_principal_data` + +:c:type:`krb5_principal` + +.. + +Create and free principal + +.. + +:c:func:`krb5_build_principal()` + +:c:func:`krb5_build_principal_alloc_va()` + +:c:func:`krb5_build_principal_ext()` + +:c:func:`krb5_copy_principal()` + +:c:func:`krb5_free_principal()` + +:c:func:`krb5_cc_get_principal()` + +.. + +Comparing + +.. + +:c:func:`krb5_principal_compare()` + +:c:func:`krb5_principal_compare_flags()` + +:c:func:`krb5_principal_compare_any_realm()` + +:c:func:`krb5_sname_match()` + +:c:func:`krb5_sname_to_principal()` + +.. + + +Parsing: + +.. + +:c:func:`krb5_parse_name()` + +:c:func:`krb5_parse_name_flags()` + +:c:func:`krb5_unparse_name()` + +:c:func:`krb5_unparse_name_flags()` + +.. + +Utilities: + +.. + +:c:func:`krb5_is_config_principal()` + +:c:func:`krb5_kuserok()` + +:c:func:`krb5_set_password()` + +:c:func:`krb5_set_password_using_ccache()` + +:c:func:`krb5_set_principal_realm()` + +:c:func:`krb5_realm_compare()` + +.. diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/index.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/index.rst.txt new file mode 100644 index 00000000..d12be47c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/index.rst.txt @@ -0,0 +1,413 @@ +krb5 API +======== + + +Frequently used public interfaces +---------------------------------- + +.. toctree:: + :maxdepth: 1 + + krb5_build_principal.rst + krb5_build_principal_alloc_va.rst + krb5_build_principal_ext.rst + krb5_cc_close.rst + krb5_cc_default.rst + krb5_cc_default_name.rst + krb5_cc_destroy.rst + krb5_cc_dup.rst + krb5_cc_get_name.rst + krb5_cc_get_principal.rst + krb5_cc_get_type.rst + krb5_cc_initialize.rst + krb5_cc_new_unique.rst + krb5_cc_resolve.rst + krb5_change_password.rst + krb5_chpw_message.rst + krb5_expand_hostname.rst + krb5_free_context.rst + krb5_free_error_message.rst + krb5_free_principal.rst + krb5_fwd_tgt_creds.rst + krb5_get_default_realm.rst + krb5_get_error_message.rst + krb5_get_host_realm.rst + krb5_get_credentials.rst + krb5_get_fallback_host_realm.rst + krb5_get_init_creds_keytab.rst + krb5_get_init_creds_opt_alloc.rst + krb5_get_init_creds_opt_free.rst + krb5_get_init_creds_opt_get_fast_flags.rst + krb5_get_init_creds_opt_set_address_list.rst + krb5_get_init_creds_opt_set_anonymous.rst + krb5_get_init_creds_opt_set_canonicalize.rst + krb5_get_init_creds_opt_set_change_password_prompt.rst + krb5_get_init_creds_opt_set_etype_list.rst + krb5_get_init_creds_opt_set_expire_callback.rst + krb5_get_init_creds_opt_set_fast_ccache.rst + krb5_get_init_creds_opt_set_fast_ccache_name.rst + krb5_get_init_creds_opt_set_fast_flags.rst + krb5_get_init_creds_opt_set_forwardable.rst + krb5_get_init_creds_opt_set_in_ccache.rst + krb5_get_init_creds_opt_set_out_ccache.rst + krb5_get_init_creds_opt_set_pa.rst + krb5_get_init_creds_opt_set_pac_request.rst + krb5_get_init_creds_opt_set_preauth_list.rst + krb5_get_init_creds_opt_set_proxiable.rst + krb5_get_init_creds_opt_set_renew_life.rst + krb5_get_init_creds_opt_set_responder.rst + krb5_get_init_creds_opt_set_salt.rst + krb5_get_init_creds_opt_set_tkt_life.rst + krb5_get_init_creds_password.rst + krb5_get_profile.rst + krb5_get_prompt_types.rst + krb5_get_renewed_creds.rst + krb5_get_validated_creds.rst + krb5_init_context.rst + krb5_init_secure_context.rst + krb5_is_config_principal.rst + krb5_is_thread_safe.rst + krb5_kt_close.rst + krb5_kt_client_default.rst + krb5_kt_default.rst + krb5_kt_default_name.rst + krb5_kt_dup.rst + krb5_kt_get_name.rst + krb5_kt_get_type.rst + krb5_kt_resolve.rst + krb5_kuserok.rst + krb5_parse_name.rst + krb5_parse_name_flags.rst + krb5_principal_compare.rst + krb5_principal_compare_any_realm.rst + krb5_principal_compare_flags.rst + krb5_prompter_posix.rst + krb5_realm_compare.rst + krb5_responder_get_challenge.rst + krb5_responder_list_questions.rst + krb5_responder_set_answer.rst + krb5_responder_otp_get_challenge.rst + krb5_responder_otp_set_answer.rst + krb5_responder_otp_challenge_free.rst + krb5_responder_pkinit_get_challenge.rst + krb5_responder_pkinit_set_answer.rst + krb5_responder_pkinit_challenge_free.rst + krb5_set_default_realm.rst + krb5_set_password.rst + krb5_set_password_using_ccache.rst + krb5_set_principal_realm.rst + krb5_set_trace_callback.rst + krb5_set_trace_filename.rst + krb5_sname_match.rst + krb5_sname_to_principal.rst + krb5_unparse_name.rst + krb5_unparse_name_ext.rst + krb5_unparse_name_flags.rst + krb5_unparse_name_flags_ext.rst + krb5_us_timeofday.rst + krb5_verify_authdata_kdc_issued.rst + +Rarely used public interfaces +-------------------------------- + +.. toctree:: + :maxdepth: 1 + + krb5_425_conv_principal.rst + krb5_524_conv_principal.rst + krb5_address_compare.rst + krb5_address_order.rst + krb5_address_search.rst + krb5_allow_weak_crypto.rst + krb5_aname_to_localname.rst + krb5_anonymous_principal.rst + krb5_anonymous_realm.rst + krb5_appdefault_boolean.rst + krb5_appdefault_string.rst + krb5_auth_con_free.rst + krb5_auth_con_genaddrs.rst + krb5_auth_con_get_checksum_func.rst + krb5_auth_con_getaddrs.rst + krb5_auth_con_getauthenticator.rst + krb5_auth_con_getflags.rst + krb5_auth_con_getkey.rst + krb5_auth_con_getkey_k.rst + krb5_auth_con_getlocalseqnumber.rst + krb5_auth_con_getrcache.rst + krb5_auth_con_getrecvsubkey.rst + krb5_auth_con_getrecvsubkey_k.rst + krb5_auth_con_getremoteseqnumber.rst + krb5_auth_con_getsendsubkey.rst + krb5_auth_con_getsendsubkey_k.rst + krb5_auth_con_init.rst + krb5_auth_con_set_checksum_func.rst + krb5_auth_con_set_req_cksumtype.rst + krb5_auth_con_setaddrs.rst + krb5_auth_con_setflags.rst + krb5_auth_con_setports.rst + krb5_auth_con_setrcache.rst + krb5_auth_con_setrecvsubkey.rst + krb5_auth_con_setrecvsubkey_k.rst + krb5_auth_con_setsendsubkey.rst + krb5_auth_con_setsendsubkey_k.rst + krb5_auth_con_setuseruserkey.rst + krb5_cc_cache_match.rst + krb5_cc_copy_creds.rst + krb5_cc_end_seq_get.rst + krb5_cc_get_config.rst + krb5_cc_get_flags.rst + krb5_cc_get_full_name.rst + krb5_cc_move.rst + krb5_cc_next_cred.rst + krb5_cc_remove_cred.rst + krb5_cc_retrieve_cred.rst + krb5_cc_select.rst + krb5_cc_set_config.rst + krb5_cc_set_default_name.rst + krb5_cc_set_flags.rst + krb5_cc_start_seq_get.rst + krb5_cc_store_cred.rst + krb5_cc_support_switch.rst + krb5_cc_switch.rst + krb5_cccol_cursor_free.rst + krb5_cccol_cursor_new.rst + krb5_cccol_cursor_next.rst + krb5_cccol_have_content.rst + krb5_clear_error_message.rst + krb5_check_clockskew.rst + krb5_copy_addresses.rst + krb5_copy_authdata.rst + krb5_copy_authenticator.rst + krb5_copy_checksum.rst + krb5_copy_context.rst + krb5_copy_creds.rst + krb5_copy_data.rst + krb5_copy_error_message.rst + krb5_copy_keyblock.rst + krb5_copy_keyblock_contents.rst + krb5_copy_principal.rst + krb5_copy_ticket.rst + krb5_find_authdata.rst + krb5_free_addresses.rst + krb5_free_ap_rep_enc_part.rst + krb5_free_authdata.rst + krb5_free_authenticator.rst + krb5_free_cred_contents.rst + krb5_free_creds.rst + krb5_free_data.rst + krb5_free_data_contents.rst + krb5_free_default_realm.rst + krb5_free_enctypes.rst + krb5_free_error.rst + krb5_free_host_realm.rst + krb5_free_keyblock.rst + krb5_free_keyblock_contents.rst + krb5_free_keytab_entry_contents.rst + krb5_free_string.rst + krb5_free_ticket.rst + krb5_free_unparsed_name.rst + krb5_get_etype_info.rst + krb5_get_permitted_enctypes.rst + krb5_get_server_rcache.rst + krb5_get_time_offsets.rst + krb5_init_context_profile.rst + krb5_init_creds_free.rst + krb5_init_creds_get.rst + krb5_init_creds_get_creds.rst + krb5_init_creds_get_error.rst + krb5_init_creds_get_times.rst + krb5_init_creds_init.rst + krb5_init_creds_set_keytab.rst + krb5_init_creds_set_password.rst + krb5_init_creds_set_service.rst + krb5_init_creds_step.rst + krb5_init_keyblock.rst + krb5_is_referral_realm.rst + krb5_kdc_sign_ticket.rst + krb5_kdc_verify_ticket.rst + krb5_kt_add_entry.rst + krb5_kt_end_seq_get.rst + krb5_kt_get_entry.rst + krb5_kt_have_content.rst + krb5_kt_next_entry.rst + krb5_kt_read_service_key.rst + krb5_kt_remove_entry.rst + krb5_kt_start_seq_get.rst + krb5_make_authdata_kdc_issued.rst + krb5_marshal_credentials.rst + krb5_merge_authdata.rst + krb5_mk_1cred.rst + krb5_mk_error.rst + krb5_mk_ncred.rst + krb5_mk_priv.rst + krb5_mk_rep.rst + krb5_mk_rep_dce.rst + krb5_mk_req.rst + krb5_mk_req_extended.rst + krb5_mk_safe.rst + krb5_os_localaddr.rst + krb5_pac_add_buffer.rst + krb5_pac_free.rst + krb5_pac_get_buffer.rst + krb5_pac_get_types.rst + krb5_pac_init.rst + krb5_pac_parse.rst + krb5_pac_sign.rst + krb5_pac_sign_ext.rst + krb5_pac_verify.rst + krb5_pac_verify_ext.rst + krb5_pac_get_client_info.rst + krb5_prepend_error_message.rst + krb5_principal2salt.rst + krb5_rd_cred.rst + krb5_rd_error.rst + krb5_rd_priv.rst + krb5_rd_rep.rst + krb5_rd_rep_dce.rst + krb5_rd_req.rst + krb5_rd_safe.rst + krb5_read_password.rst + krb5_salttype_to_string.rst + krb5_server_decrypt_ticket_keytab.rst + krb5_set_default_tgs_enctypes.rst + krb5_set_error_message.rst + krb5_set_kdc_recv_hook.rst + krb5_set_kdc_send_hook.rst + krb5_set_real_time.rst + krb5_string_to_cksumtype.rst + krb5_string_to_deltat.rst + krb5_string_to_enctype.rst + krb5_string_to_salttype.rst + krb5_string_to_timestamp.rst + krb5_timeofday.rst + krb5_timestamp_to_sfstring.rst + krb5_timestamp_to_string.rst + krb5_tkt_creds_free.rst + krb5_tkt_creds_get.rst + krb5_tkt_creds_get_creds.rst + krb5_tkt_creds_get_times.rst + krb5_tkt_creds_init.rst + krb5_tkt_creds_step.rst + krb5_unmarshal_credentials.rst + krb5_verify_init_creds.rst + krb5_verify_init_creds_opt_init.rst + krb5_verify_init_creds_opt_set_ap_req_nofail.rst + krb5_vprepend_error_message.rst + krb5_vset_error_message.rst + krb5_vwrap_error_message.rst + krb5_wrap_error_message.rst + + +Public interfaces that should not be called directly +------------------------------------------------------- + +.. toctree:: + :maxdepth: 1 + + krb5_c_block_size.rst + krb5_c_checksum_length.rst + krb5_c_crypto_length.rst + krb5_c_crypto_length_iov.rst + krb5_c_decrypt.rst + krb5_c_decrypt_iov.rst + krb5_c_derive_prfplus.rst + krb5_c_encrypt.rst + krb5_c_encrypt_iov.rst + krb5_c_encrypt_length.rst + krb5_c_enctype_compare.rst + krb5_c_free_state.rst + krb5_c_fx_cf2_simple.rst + krb5_c_init_state.rst + krb5_c_is_coll_proof_cksum.rst + krb5_c_is_keyed_cksum.rst + krb5_c_keyed_checksum_types.rst + krb5_c_keylengths.rst + krb5_c_make_checksum.rst + krb5_c_make_checksum_iov.rst + krb5_c_make_random_key.rst + krb5_c_padding_length.rst + krb5_c_prf.rst + krb5_c_prfplus.rst + krb5_c_prf_length.rst + krb5_c_random_add_entropy.rst + krb5_c_random_make_octets.rst + krb5_c_random_os_entropy.rst + krb5_c_random_to_key.rst + krb5_c_string_to_key.rst + krb5_c_string_to_key_with_params.rst + krb5_c_valid_cksumtype.rst + krb5_c_valid_enctype.rst + krb5_c_verify_checksum.rst + krb5_c_verify_checksum_iov.rst + krb5_cksumtype_to_string.rst + krb5_decode_authdata_container.rst + krb5_decode_ticket.rst + krb5_deltat_to_string.rst + krb5_encode_authdata_container.rst + krb5_enctype_to_name.rst + krb5_enctype_to_string.rst + krb5_free_checksum.rst + krb5_free_checksum_contents.rst + krb5_free_cksumtypes.rst + krb5_free_tgt_creds.rst + krb5_k_create_key.rst + krb5_k_decrypt.rst + krb5_k_decrypt_iov.rst + krb5_k_encrypt.rst + krb5_k_encrypt_iov.rst + krb5_k_free_key.rst + krb5_k_key_enctype.rst + krb5_k_key_keyblock.rst + krb5_k_make_checksum.rst + krb5_k_make_checksum_iov.rst + krb5_k_prf.rst + krb5_k_reference_key.rst + krb5_k_verify_checksum.rst + krb5_k_verify_checksum_iov.rst + + +Legacy convenience interfaces +------------------------------ + +.. toctree:: + :maxdepth: 1 + + krb5_recvauth.rst + krb5_recvauth_version.rst + krb5_sendauth.rst + + +Deprecated public interfaces +------------------------------ + +.. toctree:: + :maxdepth: 1 + + krb5_524_convert_creds.rst + krb5_auth_con_getlocalsubkey.rst + krb5_auth_con_getremotesubkey.rst + krb5_auth_con_initivector.rst + krb5_build_principal_va.rst + krb5_c_random_seed.rst + krb5_calculate_checksum.rst + krb5_checksum_size.rst + krb5_encrypt.rst + krb5_decrypt.rst + krb5_eblock_enctype.rst + krb5_encrypt_size.rst + krb5_finish_key.rst + krb5_finish_random_key.rst + krb5_cc_gen_new.rst + krb5_get_credentials_renew.rst + krb5_get_credentials_validate.rst + krb5_get_in_tkt_with_password.rst + krb5_get_in_tkt_with_skey.rst + krb5_get_in_tkt_with_keytab.rst + krb5_get_init_creds_opt_init.rst + krb5_init_random_key.rst + krb5_kt_free_entry.rst + krb5_random_key.rst + krb5_process_key.rst + krb5_string_to_key.rst + krb5_use_enctype.rst + krb5_verify_checksum.rst diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_425_conv_principal.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_425_conv_principal.rst.txt new file mode 100644 index 00000000..6673b5bd --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_425_conv_principal.rst.txt @@ -0,0 +1,59 @@ +krb5_425_conv_principal - Convert a Kerberos V4 principal to a Kerberos V5 principal. +======================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_425_conv_principal(krb5_context context, const char * name, const char * instance, const char * realm, krb5_principal * princ) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **name** - V4 name + + **[in]** **instance** - V4 instance + + **[in]** **realm** - Realm + + **[out]** **princ** - V5 principal + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function builds a *princ* from V4 specification based on given input *name.instance@realm* . + + + +Use krb5_free_principal() to free *princ* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_524_conv_principal.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_524_conv_principal.rst.txt new file mode 100644 index 00000000..14b2fc10 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_524_conv_principal.rst.txt @@ -0,0 +1,60 @@ +krb5_524_conv_principal - Convert a Kerberos V5 principal to a Kerberos V4 principal. +======================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_524_conv_principal(krb5_context context, krb5_const_principal princ, char * name, char * inst, char * realm) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **princ** - V5 Principal + + **[out]** **name** - V4 principal's name to be filled in + + **[out]** **inst** - V4 principal's instance name to be filled in + + **[out]** **realm** - Principal's realm name to be filled in + + +.. + + +:retval: + - 0 Success + - KRB5_INVALID_PRINCIPAL Invalid principal name + - KRB5_CONFIG_CANTOPEN Can't open or find Kerberos configuration file + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function separates a V5 principal *princ* into *name* , *instance* , and *realm* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_524_convert_creds.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_524_convert_creds.rst.txt new file mode 100644 index 00000000..f8d96f0d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_524_convert_creds.rst.txt @@ -0,0 +1,55 @@ +krb5_524_convert_creds - Convert a Kerberos V5 credentials to a Kerberos V4 credentials. +========================================================================================== + +.. + +.. c:function:: int krb5_524_convert_creds(krb5_context context, krb5_creds * v5creds, struct credentials * v4creds) + +.. + + +:param: + + **context** + + **v5creds** + + **v4creds** + + +.. + + +:retval: + - KRB524_KRB4_DISABLED (always) + + +.. + + + + + + + + + + + + + + +.. + + + + + + +.. note:: + + Not implemented + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_address_compare.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_address_compare.rst.txt new file mode 100644 index 00000000..7665fc70 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_address_compare.rst.txt @@ -0,0 +1,47 @@ +krb5_address_compare - Compare two Kerberos addresses. +======================================================== + +.. + +.. c:function:: krb5_boolean krb5_address_compare(krb5_context context, const krb5_address * addr1, const krb5_address * addr2) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **addr1** - First address to be compared + + **[in]** **addr2** - Second address to be compared + + +.. + + + +:return: + - TRUE if the addresses are the same, FALSE otherwise + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_address_order.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_address_order.rst.txt new file mode 100644 index 00000000..2ba9aab6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_address_order.rst.txt @@ -0,0 +1,49 @@ +krb5_address_order - Return an ordering of the specified addresses. +===================================================================== + +.. + +.. c:function:: int krb5_address_order(krb5_context context, const krb5_address * addr1, const krb5_address * addr2) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **addr1** - First address + + **[in]** **addr2** - Second address + + +.. + + +:retval: + - 0 if The two addresses are the same + - < 0 First address is less than second + - > 0 First address is greater than second + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_address_search.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_address_search.rst.txt new file mode 100644 index 00000000..2bc68c49 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_address_search.rst.txt @@ -0,0 +1,55 @@ +krb5_address_search - Search a list of addresses for a specified address. +=========================================================================== + +.. + +.. c:function:: krb5_boolean krb5_address_search(krb5_context context, const krb5_address * addr, krb5_address *const * addrlist) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **addr** - Address to search for + + **[in]** **addrlist** - Address list to be searched (or NULL) + + +.. + + + +:return: + - TRUE if addr is listed in addrlist , or addrlist is NULL; FALSE otherwise + +.. + + + + + + + + + + + + + + +.. + + + + + + +.. note:: + + If *addrlist* contains only a NetBIOS addresses, it will be treated as a null list. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_allow_weak_crypto.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_allow_weak_crypto.rst.txt new file mode 100644 index 00000000..87e69ed2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_allow_weak_crypto.rst.txt @@ -0,0 +1,49 @@ +krb5_allow_weak_crypto - Allow the application to override the profile's allow_weak_crypto setting. +===================================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_allow_weak_crypto(krb5_context context, krb5_boolean enable) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enable** - Boolean flag + + +.. + + +:retval: + - 0 (always) + + +.. + + + + + + + +This function allows an application to override the allow_weak_crypto setting. It is primarily for use by aklog. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_aname_to_localname.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_aname_to_localname.rst.txt new file mode 100644 index 00000000..c6162940 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_aname_to_localname.rst.txt @@ -0,0 +1,61 @@ +krb5_aname_to_localname - Convert a principal name to a local name. +===================================================================== + +.. + +.. c:function:: krb5_error_code krb5_aname_to_localname(krb5_context context, krb5_const_principal aname, int lnsize_in, char * lname) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **aname** - Principal name + + **[in]** **lnsize_in** - Space available in *lname* + + **[out]** **lname** - Local name buffer to be filled in + + +.. + + +:retval: + - 0 Success + - System errors + + +:return: + - Kerberos error codes + +.. + + + + + + + +If *aname* does not correspond to any local account, KRB5_LNAME_NOTRANS is returned. If *lnsize_in* is too small for the local name, KRB5_CONFIG_NOTENUFSPACE is returned. + + + +Local names, rather than principal names, can be used by programs that translate to an environment-specific name (for example, a user account name). + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_anonymous_principal.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_anonymous_principal.rst.txt new file mode 100644 index 00000000..0b715e11 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_anonymous_principal.rst.txt @@ -0,0 +1,47 @@ +krb5_anonymous_principal - Build an anonymous principal. +========================================================== + +.. + +.. c:function:: krb5_const_principal krb5_anonymous_principal(void None) + +.. + + +:param: + + **None** + + +.. + + + +.. + + + + + + + +This function returns constant storage that must not be freed. + + + + + + + + + + +.. + +.. seealso:: + #KRB5_ANONYMOUS_PRINCSTR + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_anonymous_realm.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_anonymous_realm.rst.txt new file mode 100644 index 00000000..ec3cc4e3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_anonymous_realm.rst.txt @@ -0,0 +1,47 @@ +krb5_anonymous_realm - Return an anonymous realm data. +======================================================== + +.. + +.. c:function:: const krb5_data * krb5_anonymous_realm(void None) + +.. + + +:param: + + **None** + + +.. + + + +.. + + + + + + + +This function returns constant storage that must not be freed. + + + + + + + + + + +.. + +.. seealso:: + #KRB5_ANONYMOUS_REALMSTR + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_appdefault_boolean.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_appdefault_boolean.rst.txt new file mode 100644 index 00000000..60802e5b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_appdefault_boolean.rst.txt @@ -0,0 +1,57 @@ +krb5_appdefault_boolean - Retrieve a boolean value from the appdefaults section of krb5.conf. +=============================================================================================== + +.. + +.. c:function:: void krb5_appdefault_boolean(krb5_context context, const char * appname, const krb5_data * realm, const char * option, int default_value, int * ret_value) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **appname** - Application name + + **[in]** **realm** - Realm name + + **[in]** **option** - Option to be checked + + **[in]** **default_value** - Default value to return if no match is found + + **[out]** **ret_value** - Boolean value of *option* + + +.. + + + +.. + + + + + + + +This function gets the application defaults for *option* based on the given *appname* and/or *realm* . + + + + + + + + + + +.. + +.. seealso:: + krb5_appdefault_string() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_appdefault_string.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_appdefault_string.rst.txt new file mode 100644 index 00000000..1909f1b3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_appdefault_string.rst.txt @@ -0,0 +1,57 @@ +krb5_appdefault_string - Retrieve a string value from the appdefaults section of krb5.conf. +============================================================================================= + +.. + +.. c:function:: void krb5_appdefault_string(krb5_context context, const char * appname, const krb5_data * realm, const char * option, const char * default_value, char ** ret_value) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **appname** - Application name + + **[in]** **realm** - Realm name + + **[in]** **option** - Option to be checked + + **[in]** **default_value** - Default value to return if no match is found + + **[out]** **ret_value** - String value of *option* + + +.. + + + +.. + + + + + + + +This function gets the application defaults for *option* based on the given *appname* and/or *realm* . + + + + + + + + + + +.. + +.. seealso:: + krb5_appdefault_boolean() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_free.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_free.rst.txt new file mode 100644 index 00000000..93a8d690 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_free.rst.txt @@ -0,0 +1,49 @@ +krb5_auth_con_free - Free a krb5_auth_context structure. +========================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_free(krb5_context context, krb5_auth_context auth_context) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context to be freed + + +.. + + +:retval: + - 0 (always) + + +.. + + + + + + + +This function frees an auth context allocated by krb5_auth_con_init(). + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_genaddrs.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_genaddrs.rst.txt new file mode 100644 index 00000000..f61c2318 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_genaddrs.rst.txt @@ -0,0 +1,66 @@ +krb5_auth_con_genaddrs - Generate auth context addresses from a connected socket. +=================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_genaddrs(krb5_context context, krb5_auth_context auth_context, int infd, int flags) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **infd** - Connected socket descriptor + + **[in]** **flags** - Flags + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function sets the local and/or remote addresses in *auth_context* based on the local and remote endpoints of the socket *infd* . The following flags determine the operations performed: + + + + + + - #KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR Generate local address. + + + - #KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR Generate remote address. + + + - #KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR Generate local address and port. + + + - #KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR Generate remote address and port. + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_get_checksum_func.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_get_checksum_func.rst.txt new file mode 100644 index 00000000..e3a42742 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_get_checksum_func.rst.txt @@ -0,0 +1,49 @@ +krb5_auth_con_get_checksum_func - Get the checksum callback from an auth context. +=================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_get_checksum_func(krb5_context context, krb5_auth_context auth_context, krb5_mk_req_checksum_func * func, void ** data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[out]** **func** - Checksum callback + + **[out]** **data** - Callback argument + + +.. + + +:retval: + - 0 (always) + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getaddrs.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getaddrs.rst.txt new file mode 100644 index 00000000..12252940 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getaddrs.rst.txt @@ -0,0 +1,49 @@ +krb5_auth_con_getaddrs - Retrieve address fields from an auth context. +======================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address ** local_addr, krb5_address ** remote_addr) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[out]** **local_addr** - Local address (NULL if not needed) + + **[out]** **remote_addr** - Remote address (NULL if not needed) + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getauthenticator.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getauthenticator.rst.txt new file mode 100644 index 00000000..0e67df91 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getauthenticator.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_getauthenticator - Retrieve the authenticator from an auth context. +=================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getauthenticator(krb5_context context, krb5_auth_context auth_context, krb5_authenticator ** authenticator) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[out]** **authenticator** - Authenticator + + +.. + + +:retval: + - 0 Success. Otherwise - Kerberos error codes + + +.. + + + + + + + +Use krb5_free_authenticator() to free *authenticator* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getflags.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getflags.rst.txt new file mode 100644 index 00000000..db9020e2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getflags.rst.txt @@ -0,0 +1,60 @@ +krb5_auth_con_getflags - Retrieve flags from a krb5_auth_context structure. +============================================================================= + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 * flags) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[out]** **flags** - Flags bit mask + + +.. + + +:retval: + - 0 (always) + + +.. + + + + + + + +Valid values for *flags* are: + + - #KRB5_AUTH_CONTEXT_DO_TIME Use timestamps + + + - #KRB5_AUTH_CONTEXT_RET_TIME Save timestamps + + + - #KRB5_AUTH_CONTEXT_DO_SEQUENCE Use sequence numbers + + + - #KRB5_AUTH_CONTEXT_RET_SEQUENCE Save sequence numbers + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getkey.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getkey.rst.txt new file mode 100644 index 00000000..b5abc855 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getkey.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_getkey - Retrieve the session key from an auth context as a keyblock. +===================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock ** keyblock) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[out]** **keyblock** - Session key + + +.. + + +:retval: + - 0 Success. Otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a keyblock containing the session key from *auth_context* . Use krb5_free_keyblock() to free *keyblock* when it is no longer needed + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getkey_k.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getkey_k.rst.txt new file mode 100644 index 00000000..4d87db92 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getkey_k.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_getkey_k - Retrieve the session key from an auth context. +========================================================================= + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getkey_k(krb5_context context, krb5_auth_context auth_context, krb5_key * key) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[out]** **key** - Session key + + +.. + + +:retval: + - 0 (always) + + +.. + + + + + + + +This function sets *key* to the session key from *auth_context* . Use krb5_k_free_key() to release *key* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getlocalseqnumber.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getlocalseqnumber.rst.txt new file mode 100644 index 00000000..0b340a3f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getlocalseqnumber.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_getlocalseqnumber - Retrieve the local sequence number from an auth context. +============================================================================================ + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getlocalseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 * seqnumber) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[out]** **seqnumber** - Local sequence number + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Retrieve the local sequence number from *auth_context* and return it in *seqnumber* . The #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag must be set in *auth_context* for this function to be useful. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getlocalsubkey.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getlocalsubkey.rst.txt new file mode 100644 index 00000000..a938d749 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getlocalsubkey.rst.txt @@ -0,0 +1,46 @@ +krb5_auth_con_getlocalsubkey +============================ + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getlocalsubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock ** keyblock) + +.. + + +:param: + + **context** + + **auth_context** + + **keyblock** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_auth_con_getsendsubkey(). + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getrcache.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getrcache.rst.txt new file mode 100644 index 00000000..c5066364 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getrcache.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_getrcache - Retrieve the replay cache from an auth context. +=========================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache * rcache) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[out]** **rcache** - Replay cache handle + + +.. + + +:retval: + - 0 (always) + + +.. + + + + + + + +This function fetches the replay cache from *auth_context* . The caller should not close *rcache* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getrecvsubkey.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getrecvsubkey.rst.txt new file mode 100644 index 00000000..ece6d0c1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getrecvsubkey.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_getrecvsubkey - Retrieve the receiving subkey from an auth context as a keyblock. +================================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock ** keyblock) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **ac** - Authentication context + + **[out]** **keyblock** - Receiving subkey + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a keyblock containing the receiving subkey from *auth_context* . Use krb5_free_keyblock() to free *keyblock* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getrecvsubkey_k.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getrecvsubkey_k.rst.txt new file mode 100644 index 00000000..7caf5b03 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getrecvsubkey_k.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_getrecvsubkey_k - Retrieve the receiving subkey from an auth context as a keyblock. +=================================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getrecvsubkey_k(krb5_context ctx, krb5_auth_context ac, krb5_key * key) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **ac** - Authentication context + + **[out]** **key** - Receiving subkey + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function sets *key* to the receiving subkey from *auth_context* . Use krb5_k_free_key() to release *key* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getremoteseqnumber.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getremoteseqnumber.rst.txt new file mode 100644 index 00000000..8f2a7ffd --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getremoteseqnumber.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_getremoteseqnumber - Retrieve the remote sequence number from an auth context. +============================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getremoteseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 * seqnumber) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[out]** **seqnumber** - Remote sequence number + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Retrieve the remote sequence number from *auth_context* and return it in *seqnumber* . The #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag must be set in *auth_context* for this function to be useful. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getremotesubkey.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getremotesubkey.rst.txt new file mode 100644 index 00000000..25f42d90 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getremotesubkey.rst.txt @@ -0,0 +1,46 @@ +krb5_auth_con_getremotesubkey +============================= + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getremotesubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock ** keyblock) + +.. + + +:param: + + **context** + + **auth_context** + + **keyblock** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_auth_con_getrecvsubkey(). + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getsendsubkey.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getsendsubkey.rst.txt new file mode 100644 index 00000000..fa7c6cf9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getsendsubkey.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_getsendsubkey - Retrieve the send subkey from an auth context as a keyblock. +============================================================================================ + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock ** keyblock) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **ac** - Authentication context + + **[out]** **keyblock** - Send subkey + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a keyblock containing the send subkey from *auth_context* . Use krb5_free_keyblock() to free *keyblock* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getsendsubkey_k.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getsendsubkey_k.rst.txt new file mode 100644 index 00000000..bfbbf574 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_getsendsubkey_k.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_getsendsubkey_k - Retrieve the send subkey from an auth context. +================================================================================ + +.. + +.. c:function:: krb5_error_code krb5_auth_con_getsendsubkey_k(krb5_context ctx, krb5_auth_context ac, krb5_key * key) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **ac** - Authentication context + + **[out]** **key** - Send subkey + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function sets *key* to the send subkey from *auth_context* . Use krb5_k_free_key() to release *key* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_init.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_init.rst.txt new file mode 100644 index 00000000..9f61f30b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_init.rst.txt @@ -0,0 +1,57 @@ +krb5_auth_con_init - Create and initialize an authentication context. +======================================================================= + +.. + +.. c:function:: krb5_error_code krb5_auth_con_init(krb5_context context, krb5_auth_context * auth_context) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **auth_context** - Authentication context + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates an authentication context to hold configuration and state relevant to krb5 functions for authenticating principals and protecting messages once authentication has occurred. + + + +By default, flags for the context are set to enable the use of the replay cache (#KRB5_AUTH_CONTEXT_DO_TIME), but not sequence numbers. Use krb5_auth_con_setflags() to change the flags. + + + +The allocated *auth_context* must be freed with krb5_auth_con_free() when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_initivector.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_initivector.rst.txt new file mode 100644 index 00000000..31e8403d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_initivector.rst.txt @@ -0,0 +1,49 @@ +krb5_auth_con_initivector - Cause an auth context to use cipher state. +======================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_initivector(krb5_context context, krb5_auth_context auth_context) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Prepare *auth_context* to use cipher state when krb5_mk_priv() or krb5_rd_priv() encrypt or decrypt data. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_set_checksum_func.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_set_checksum_func.rst.txt new file mode 100644 index 00000000..c7f19f0d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_set_checksum_func.rst.txt @@ -0,0 +1,53 @@ +krb5_auth_con_set_checksum_func - Set a checksum callback in an auth context. +=============================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_set_checksum_func(krb5_context context, krb5_auth_context auth_context, krb5_mk_req_checksum_func func, void * data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **func** - Checksum callback + + **[in]** **data** - Callback argument + + +.. + + +:retval: + - 0 (always) + + +.. + + + + + + + +Set a callback to obtain checksum data in krb5_mk_req(). The callback will be invoked after the subkey and local sequence number are stored in *auth_context* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_set_req_cksumtype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_set_req_cksumtype.rst.txt new file mode 100644 index 00000000..4a79bfd6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_set_req_cksumtype.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_set_req_cksumtype - Set checksum type in an an auth context. +============================================================================ + +.. + +.. c:function:: krb5_error_code krb5_auth_con_set_req_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **cksumtype** - Checksum type + + +.. + + +:retval: + - 0 Success. Otherwise - Kerberos error codes + + +.. + + + + + + + +This function sets the checksum type in *auth_context* to be used by krb5_mk_req() for the authenticator checksum. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setaddrs.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setaddrs.rst.txt new file mode 100644 index 00000000..0a9a8e80 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setaddrs.rst.txt @@ -0,0 +1,56 @@ +krb5_auth_con_setaddrs - Set the local and remote addresses in an auth context. +================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_auth_con_setaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address * local_addr, krb5_address * remote_addr) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **local_addr** - Local address + + **[in]** **remote_addr** - Remote address + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function releases the storage assigned to the contents of the local and remote addresses of *auth_context* and then sets them to *local_addr* and *remote_addr* respectively. + + + + + + + + + + +.. + +.. seealso:: + krb5_auth_con_genaddrs() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setflags.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setflags.rst.txt new file mode 100644 index 00000000..d8cb6e71 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setflags.rst.txt @@ -0,0 +1,60 @@ +krb5_auth_con_setflags - Set a flags field in a krb5_auth_context structure. +============================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_setflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 flags) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **flags** - Flags bit mask + + +.. + + +:retval: + - 0 (always) + + +.. + + + + + + + +Valid values for *flags* are: + + - #KRB5_AUTH_CONTEXT_DO_TIME Use timestamps + + + - #KRB5_AUTH_CONTEXT_RET_TIME Save timestamps + + + - #KRB5_AUTH_CONTEXT_DO_SEQUENCE Use sequence numbers + + + - #KRB5_AUTH_CONTEXT_RET_SEQUENCE Save sequence numbers + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setports.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setports.rst.txt new file mode 100644 index 00000000..e64c4219 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setports.rst.txt @@ -0,0 +1,56 @@ +krb5_auth_con_setports - Set local and remote port fields in an auth context. +=============================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_setports(krb5_context context, krb5_auth_context auth_context, krb5_address * local_port, krb5_address * remote_port) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **local_port** - Local port + + **[in]** **remote_port** - Remote port + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function releases the storage assigned to the contents of the local and remote ports of *auth_context* and then sets them to *local_port* and *remote_port* respectively. + + + + + + + + + + +.. + +.. seealso:: + krb5_auth_con_genaddrs() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setrcache.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setrcache.rst.txt new file mode 100644 index 00000000..0a37e8ae --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setrcache.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_setrcache - Set the replay cache in an auth context. +==================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_setrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache rcache) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **rcache** - Replay cache haddle + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function sets the replay cache in *auth_context* to *rcache* . *rcache* will be closed when *auth_context* is freed, so the caller should relinquish that responsibility. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setrecvsubkey.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setrecvsubkey.rst.txt new file mode 100644 index 00000000..7e43d914 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setrecvsubkey.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_setrecvsubkey - Set the receiving subkey in an auth context with a keyblock. +============================================================================================ + +.. + +.. c:function:: krb5_error_code krb5_auth_con_setrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock * keyblock) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **ac** - Authentication context + + **[in]** **keyblock** - Receiving subkey + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function sets the receiving subkey in *ac* to a copy of *keyblock* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setrecvsubkey_k.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setrecvsubkey_k.rst.txt new file mode 100644 index 00000000..feafaabf --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setrecvsubkey_k.rst.txt @@ -0,0 +1,55 @@ +krb5_auth_con_setrecvsubkey_k - Set the receiving subkey in an auth context. +============================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_setrecvsubkey_k(krb5_context ctx, krb5_auth_context ac, krb5_key key) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **ac** - Authentication context + + **[in]** **key** - Receiving subkey + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function sets the receiving subkey in *ac* to *key* , incrementing its reference count. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.9 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setsendsubkey.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setsendsubkey.rst.txt new file mode 100644 index 00000000..47f746b5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setsendsubkey.rst.txt @@ -0,0 +1,51 @@ +krb5_auth_con_setsendsubkey - Set the send subkey in an auth context with a keyblock. +======================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_auth_con_setsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock * keyblock) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **ac** - Authentication context + + **[in]** **keyblock** - Send subkey + + +.. + + +:retval: + - 0 Success. Otherwise - Kerberos error codes + + +.. + + + + + + + +This function sets the send subkey in *ac* to a copy of *keyblock* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setsendsubkey_k.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setsendsubkey_k.rst.txt new file mode 100644 index 00000000..59fd7392 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setsendsubkey_k.rst.txt @@ -0,0 +1,55 @@ +krb5_auth_con_setsendsubkey_k - Set the send subkey in an auth context. +========================================================================= + +.. + +.. c:function:: krb5_error_code krb5_auth_con_setsendsubkey_k(krb5_context ctx, krb5_auth_context ac, krb5_key key) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **ac** - Authentication context + + **[out]** **key** - Send subkey + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function sets the send subkey in *ac* to *key* , incrementing its reference count. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.9 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setuseruserkey.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setuseruserkey.rst.txt new file mode 100644 index 00000000..11d9249d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_auth_con_setuseruserkey.rst.txt @@ -0,0 +1,47 @@ +krb5_auth_con_setuseruserkey - Set the session key in an auth context. +======================================================================== + +.. + +.. c:function:: krb5_error_code krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock * keyblock) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **keyblock** - User key + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal.rst.txt new file mode 100644 index 00000000..fddcb462 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal.rst.txt @@ -0,0 +1,72 @@ +krb5_build_principal - Build a principal name using null-terminated strings. +============================================================================== + +.. + +.. c:function:: krb5_error_code krb5_build_principal(krb5_context context, krb5_principal * princ, unsigned int rlen, const char * realm, ... ) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **princ** - Principal name + + **[in]** **rlen** - Realm name length + + **[in]** **realm** - Realm name + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Call krb5_free_principal() to free *princ* when it is no longer needed. + + + +Beginning with release 1.20, the name type of the principal will be inferred as **KRB5_NT_SRV_INST** or **KRB5_NT_WELLKNOWN** based on the principal name. The type will be **KRB5_NT_PRINCIPAL** if a type cannot be inferred. + + + + + + + + + + + + + + +.. + + + + + + +.. note:: + + krb5_build_principal() and krb5_build_principal_alloc_va() perform the same task. krb5_build_principal() takes variadic arguments. krb5_build_principal_alloc_va() takes a pre-computed *varargs* pointer. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal_alloc_va.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal_alloc_va.rst.txt new file mode 100644 index 00000000..904f4161 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal_alloc_va.rst.txt @@ -0,0 +1,66 @@ +krb5_build_principal_alloc_va - Build a principal name, using a precomputed variable argument list. +===================================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_build_principal_alloc_va(krb5_context context, krb5_principal * princ, unsigned int rlen, const char * realm, va_list ap) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **princ** - Principal structure + + **[in]** **rlen** - Realm name length + + **[in]** **realm** - Realm name + + **[in]** **ap** - List of char * components, ending with NULL + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Similar to krb5_build_principal(), this function builds a principal name, but its name components are specified as a va_list. + + + +Use krb5_free_principal() to deallocate *princ* when it is no longer needed. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal_ext.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal_ext.rst.txt new file mode 100644 index 00000000..6f1b3ba6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal_ext.rst.txt @@ -0,0 +1,64 @@ +krb5_build_principal_ext - Build a principal name using length-counted strings. +================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_build_principal_ext(krb5_context context, krb5_principal * princ, unsigned int rlen, const char * realm, ... ) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **princ** - Principal name + + **[in]** **rlen** - Realm name length + + **[in]** **realm** - Realm name + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function creates a principal from a length-counted string and a variable-length list of length-counted components. The list of components ends with the first 0 length argument (so it is not possible to specify an empty component with this function). Call krb5_free_principal() to free allocated memory for principal when it is no longer needed. + + + +Beginning with release 1.20, the name type of the principal will be inferred as **KRB5_NT_SRV_INST** or **KRB5_NT_WELLKNOWN** based on the principal name. The type will be **KRB5_NT_PRINCIPAL** if a type cannot be inferred. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal_va.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal_va.rst.txt new file mode 100644 index 00000000..a30c39f1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_build_principal_va.rst.txt @@ -0,0 +1,50 @@ +krb5_build_principal_va +======================= + +.. + +.. c:function:: krb5_error_code krb5_build_principal_va(krb5_context context, krb5_principal princ, unsigned int rlen, const char * realm, va_list ap) + +.. + + +:param: + + **context** + + **princ** + + **rlen** + + **realm** + + **ap** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_build_principal_alloc_va(). + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_block_size.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_block_size.rst.txt new file mode 100644 index 00000000..4c4a13ea --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_block_size.rst.txt @@ -0,0 +1,47 @@ +krb5_c_block_size - Return cipher block size. +=============================================== + +.. + +.. c:function:: krb5_error_code krb5_c_block_size(krb5_context context, krb5_enctype enctype, size_t * blocksize) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enctype** - Encryption type + + **[out]** **blocksize** - Block size for *enctype* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_checksum_length.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_checksum_length.rst.txt new file mode 100644 index 00000000..644e34bf --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_checksum_length.rst.txt @@ -0,0 +1,47 @@ +krb5_c_checksum_length - Return the length of checksums for a checksum type. +============================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_checksum_length(krb5_context context, krb5_cksumtype cksumtype, size_t * length) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cksumtype** - Checksum type + + **[out]** **length** - Checksum length + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_crypto_length.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_crypto_length.rst.txt new file mode 100644 index 00000000..5a38d3b0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_crypto_length.rst.txt @@ -0,0 +1,49 @@ +krb5_c_crypto_length - Return a length of a message field specific to the encryption type. +============================================================================================ + +.. + +.. c:function:: krb5_error_code krb5_c_crypto_length(krb5_context context, krb5_enctype enctype, krb5_cryptotype type, unsigned int * size) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enctype** - Encryption type + + **[in]** **type** - Type field (See KRB5_CRYPTO_TYPE macros) + + **[out]** **size** - Length of the *type* specific to *enctype* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_crypto_length_iov.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_crypto_length_iov.rst.txt new file mode 100644 index 00000000..cb4d18d1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_crypto_length_iov.rst.txt @@ -0,0 +1,53 @@ +krb5_c_crypto_length_iov - Fill in lengths for header, trailer and padding in a IOV array. +============================================================================================ + +.. + +.. c:function:: krb5_error_code krb5_c_crypto_length_iov(krb5_context context, krb5_enctype enctype, krb5_crypto_iov * data, size_t num_data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enctype** - Encryption type + + **[inout]** **data** - IOV array + + **[in]** **num_data** - Size of *data* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Padding is set to the actual padding required based on the provided *data* buffers. Typically this API is used after setting up the data buffers and #KRB5_CRYPTO_TYPE_SIGN_ONLY buffers, but before actually allocating header, trailer and padding. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_decrypt.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_decrypt.rst.txt new file mode 100644 index 00000000..e8371559 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_decrypt.rst.txt @@ -0,0 +1,65 @@ +krb5_c_decrypt - Decrypt data using a key (operates on keyblock). +=================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_decrypt(krb5_context context, const krb5_keyblock * key, krb5_keyusage usage, const krb5_data * cipher_state, const krb5_enc_data * input, krb5_data * output) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Encryption key + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[inout]** **cipher_state** - Cipher state; specify NULL if not needed + + **[in]** **input** - Encrypted data + + **[out]** **output** - Decrypted data + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function decrypts the data block *input* and stores the output into *output* . The actual decryption key will be derived from *key* and *usage* if key derivation is specified for the encryption type. If non-null, *cipher_state* specifies the beginning state for the decryption operation, and is updated with the state to be passed as input to the next operation. + + + + + + + + + + +.. + + + + + + +.. note:: + + The caller must initialize *output* and allocate at least enough space for the result. The usual practice is to allocate an output buffer as long as the ciphertext, and let krb5_c_decrypt() trim *output->length* . For some enctypes, the resulting *output->length* may include padding bytes. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_decrypt_iov.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_decrypt_iov.rst.txt new file mode 100644 index 00000000..96dd9a25 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_decrypt_iov.rst.txt @@ -0,0 +1,68 @@ +krb5_c_decrypt_iov - Decrypt data in place supporting AEAD (operates on keyblock). +==================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_decrypt_iov(krb5_context context, const krb5_keyblock * keyblock, krb5_keyusage usage, const krb5_data * cipher_state, krb5_crypto_iov * data, size_t num_data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **keyblock** - Encryption key + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[in]** **cipher_state** - Cipher state; specify NULL if not needed + + **[inout]** **data** - IOV array. Modified in-place. + + **[in]** **num_data** - Size of *data* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function decrypts the data block *data* and stores the output in-place. The actual decryption key will be derived from *keyblock* and *usage* if key derivation is specified for the encryption type. If non-null, *cipher_state* specifies the beginning state for the decryption operation, and is updated with the state to be passed as input to the next operation. The caller must allocate the right number of krb5_crypto_iov structures before calling into this API. + + + + + + + + + + +.. + +.. seealso:: + krb5_c_decrypt_iov() + + + + + + +.. note:: + + On return from a krb5_c_decrypt_iov() call, the *data->length* in the iov structure are adjusted to reflect actual lengths of the ciphertext used. For example, if the padding length is too large, the length will be reduced. Lengths are never increased. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_derive_prfplus.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_derive_prfplus.rst.txt new file mode 100644 index 00000000..fdb62c50 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_derive_prfplus.rst.txt @@ -0,0 +1,48 @@ +krb5_c_derive_prfplus - Derive a key using some input data (via RFC 6113 PRF+). +================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_c_derive_prfplus(krb5_context context, const krb5_keyblock * k, const krb5_data * input, krb5_enctype enctype, krb5_keyblock ** out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **k** - KDC contribution key + + **[in]** **input** - Input string + + **[in]** **enctype** - Output key enctype (or **ENCTYPE_NULL** ) + + **[out]** **out** - Derived keyblock + + +.. + + + +.. + + + + + + + +This function uses PRF+ as defined in RFC 6113 to derive a key from another key and an input string. If *enctype* is **ENCTYPE_NULL** , the output key will have the same enctype as the input key. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_encrypt.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_encrypt.rst.txt new file mode 100644 index 00000000..b67a8db6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_encrypt.rst.txt @@ -0,0 +1,65 @@ +krb5_c_encrypt - Encrypt data using a key (operates on keyblock). +=================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_encrypt(krb5_context context, const krb5_keyblock * key, krb5_keyusage usage, const krb5_data * cipher_state, const krb5_data * input, krb5_enc_data * output) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Encryption key + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[inout]** **cipher_state** - Cipher state; specify NULL if not needed + + **[in]** **input** - Data to be encrypted + + **[out]** **output** - Encrypted data + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function encrypts the data block *input* and stores the outputinto *output* . The actual encryption key will be derived from *key* and *usage* if key derivation is specified for the encryption type. If non-null, *cipher_state* specifies the beginning state for the encryption operation, and is updated with the state to be passed as input to the next operation. + + + + + + + + + + +.. + + + + + + +.. note:: + + The caller must initialize *output* and allocate at least enough space for the result (using krb5_c_encrypt_length() to determine the amount of space needed). *output->length* will be set to the actual length of the ciphertext. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_encrypt_iov.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_encrypt_iov.rst.txt new file mode 100644 index 00000000..619bc8c5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_encrypt_iov.rst.txt @@ -0,0 +1,68 @@ +krb5_c_encrypt_iov - Encrypt data in place supporting AEAD (operates on keyblock). +==================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_encrypt_iov(krb5_context context, const krb5_keyblock * keyblock, krb5_keyusage usage, const krb5_data * cipher_state, krb5_crypto_iov * data, size_t num_data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **keyblock** - Encryption key + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[in]** **cipher_state** - Cipher state; specify NULL if not needed + + **[inout]** **data** - IOV array. Modified in-place. + + **[in]** **num_data** - Size of *data* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function encrypts the data block *data* and stores the output in-place. The actual encryption key will be derived from *keyblock* and *usage* if key derivation is specified for the encryption type. If non-null, *cipher_state* specifies the beginning state for the encryption operation, and is updated with the state to be passed as input to the next operation. The caller must allocate the right number of krb5_crypto_iov structures before calling into this API. + + + + + + + + + + +.. + +.. seealso:: + krb5_c_decrypt_iov() + + + + + + +.. note:: + + On return from a krb5_c_encrypt_iov() call, the *data->length* in the iov structure are adjusted to reflect actual lengths of the ciphertext used. For example, if the padding length is too large, the length will be reduced. Lengths are never increased. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_encrypt_length.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_encrypt_length.rst.txt new file mode 100644 index 00000000..a459c3a4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_encrypt_length.rst.txt @@ -0,0 +1,53 @@ +krb5_c_encrypt_length - Compute encrypted data length. +======================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_encrypt_length(krb5_context context, krb5_enctype enctype, size_t inputlen, size_t * length) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enctype** - Encryption type + + **[in]** **inputlen** - Length of the data to be encrypted + + **[out]** **length** - Length of the encrypted data + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function computes the length of the ciphertext produced by encrypting *inputlen* bytes including padding, confounder, and checksum. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_enctype_compare.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_enctype_compare.rst.txt new file mode 100644 index 00000000..156cdd23 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_enctype_compare.rst.txt @@ -0,0 +1,53 @@ +krb5_c_enctype_compare - Compare two encryption types. +======================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_enctype_compare(krb5_context context, krb5_enctype e1, krb5_enctype e2, krb5_boolean * similar) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **e1** - First encryption type + + **[in]** **e2** - Second encryption type + + **[out]** **similar** - **TRUE** if types are similar, **FALSE** if not + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function determines whether two encryption types use the same kind of keys. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_free_state.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_free_state.rst.txt new file mode 100644 index 00000000..18da478c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_free_state.rst.txt @@ -0,0 +1,47 @@ +krb5_c_free_state - Free a cipher state previously allocated by krb5_c_init_state(). +====================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_free_state(krb5_context context, const krb5_keyblock * key, krb5_data * state) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Key + + **[in]** **state** - Cipher state to be freed + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_fx_cf2_simple.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_fx_cf2_simple.rst.txt new file mode 100644 index 00000000..0d9cf9d5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_fx_cf2_simple.rst.txt @@ -0,0 +1,57 @@ +krb5_c_fx_cf2_simple - Compute the KRB-FX-CF2 combination of two keys and pepper strings. +=========================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_fx_cf2_simple(krb5_context context, const krb5_keyblock * k1, const char * pepper1, const krb5_keyblock * k2, const char * pepper2, krb5_keyblock ** out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **k1** - KDC contribution key + + **[in]** **pepper1** - String"PKINIT" + + **[in]** **k2** - Reply key + + **[in]** **pepper2** - String"KeyExchange" + + **[out]** **out** - Output key + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function computes the KRB-FX-CF2 function over its inputs and places the results in a newly allocated keyblock. This function is simple in that it assumes that *pepper1* and *pepper2* are C strings with no internal nulls and that the enctype of the result will be the same as that of *k1* . *k1* and *k2* may be of different enctypes. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_init_state.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_init_state.rst.txt new file mode 100644 index 00000000..b6a3065d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_init_state.rst.txt @@ -0,0 +1,49 @@ +krb5_c_init_state - Initialize a new cipher state. +==================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_init_state(krb5_context context, const krb5_keyblock * key, krb5_keyusage usage, krb5_data * new_state) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Key + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[out]** **new_state** - New cipher state + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_is_coll_proof_cksum.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_is_coll_proof_cksum.rst.txt new file mode 100644 index 00000000..478f2466 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_is_coll_proof_cksum.rst.txt @@ -0,0 +1,43 @@ +krb5_c_is_coll_proof_cksum - Test whether a checksum type is collision-proof. +=============================================================================== + +.. + +.. c:function:: krb5_boolean krb5_c_is_coll_proof_cksum(krb5_cksumtype ctype) + +.. + + +:param: + + **[in]** **ctype** - Checksum type + + +.. + + + +:return: + - TRUE if ctype is collision-proof, FALSE if it is not collision-proof or not a valid checksum type. + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_is_keyed_cksum.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_is_keyed_cksum.rst.txt new file mode 100644 index 00000000..ed6e6ab4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_is_keyed_cksum.rst.txt @@ -0,0 +1,43 @@ +krb5_c_is_keyed_cksum - Test whether a checksum type is keyed. +================================================================ + +.. + +.. c:function:: krb5_boolean krb5_c_is_keyed_cksum(krb5_cksumtype ctype) + +.. + + +:param: + + **[in]** **ctype** - Checksum type + + +.. + + + +:return: + - TRUE if ctype is a keyed checksum type, FALSE otherwise. + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_keyed_checksum_types.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_keyed_checksum_types.rst.txt new file mode 100644 index 00000000..37e18000 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_keyed_checksum_types.rst.txt @@ -0,0 +1,53 @@ +krb5_c_keyed_checksum_types - Return a list of keyed checksum types usable with an encryption type. +===================================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_keyed_checksum_types(krb5_context context, krb5_enctype enctype, unsigned int * count, krb5_cksumtype ** cksumtypes) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enctype** - Encryption type + + **[out]** **count** - Count of allowable checksum types + + **[out]** **cksumtypes** - Array of allowable checksum types + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Use krb5_free_cksumtypes() to free *cksumtypes* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_keylengths.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_keylengths.rst.txt new file mode 100644 index 00000000..9b195c43 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_keylengths.rst.txt @@ -0,0 +1,49 @@ +krb5_c_keylengths - Return length of the specified key in bytes. +================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_keylengths(krb5_context context, krb5_enctype enctype, size_t * keybytes, size_t * keylength) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enctype** - Encryption type + + **[out]** **keybytes** - Number of bytes required to make a key + + **[out]** **keylength** - Length of final key + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_make_checksum.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_make_checksum.rst.txt new file mode 100644 index 00000000..bf057e20 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_make_checksum.rst.txt @@ -0,0 +1,68 @@ +krb5_c_make_checksum - Compute a checksum (operates on keyblock). +=================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype, const krb5_keyblock * key, krb5_keyusage usage, const krb5_data * input, krb5_checksum * cksum) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cksumtype** - Checksum type (0 for mandatory type) + + **[in]** **key** - Encryption key for a keyed checksum + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[in]** **input** - Input data + + **[out]** **cksum** - Generated checksum + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function computes a checksum of type *cksumtype* over *input* , using *key* if the checksum type is a keyed checksum. If *cksumtype* is 0 and *key* is non-null, the checksum type will be the mandatory-to-implement checksum type for the key's encryption type. The actual checksum key will be derived from *key* and *usage* if key derivation is specified for the checksum type. The newly created *cksum* must be released by calling krb5_free_checksum_contents() when it is no longer needed. + + + + + + + + + + +.. + +.. seealso:: + krb5_c_verify_checksum() + + + + + + +.. note:: + + This function is similar to krb5_k_make_checksum(), but operates on keyblock *key* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_make_checksum_iov.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_make_checksum_iov.rst.txt new file mode 100644 index 00000000..fe1d921c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_make_checksum_iov.rst.txt @@ -0,0 +1,68 @@ +krb5_c_make_checksum_iov - Fill in a checksum element in IOV array (operates on keyblock) +=========================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_make_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, const krb5_keyblock * key, krb5_keyusage usage, krb5_crypto_iov * data, size_t num_data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cksumtype** - Checksum type (0 for mandatory type) + + **[in]** **key** - Encryption key for a keyed checksum + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[inout]** **data** - IOV array + + **[in]** **num_data** - Size of *data* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Create a checksum in the #KRB5_CRYPTO_TYPE_CHECKSUM element over #KRB5_CRYPTO_TYPE_DATA and #KRB5_CRYPTO_TYPE_SIGN_ONLY chunks in *data* . Only the #KRB5_CRYPTO_TYPE_CHECKSUM region is modified. + + + + + + + + + + +.. + +.. seealso:: + krb5_c_verify_checksum_iov() + + + + + + +.. note:: + + This function is similar to krb5_k_make_checksum_iov(), but operates on keyblock *key* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_make_random_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_make_random_key.rst.txt new file mode 100644 index 00000000..bcf7e28d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_make_random_key.rst.txt @@ -0,0 +1,51 @@ +krb5_c_make_random_key - Generate an enctype-specific random encryption key. +============================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_make_random_key(krb5_context context, krb5_enctype enctype, krb5_keyblock * k5_random_key) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enctype** - Encryption type of the generated key + + **[out]** **k5_random_key** - An allocated and initialized keyblock + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Use krb5_free_keyblock_contents() to free *k5_random_key* when no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_padding_length.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_padding_length.rst.txt new file mode 100644 index 00000000..35471bf1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_padding_length.rst.txt @@ -0,0 +1,53 @@ +krb5_c_padding_length - Return a number of padding octets. +============================================================ + +.. + +.. c:function:: krb5_error_code krb5_c_padding_length(krb5_context context, krb5_enctype enctype, size_t data_length, unsigned int * size) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enctype** - Encryption type + + **[in]** **data_length** - Length of the plaintext to pad + + **[out]** **size** - Number of padding octets + + +.. + + +:retval: + - 0 Success; otherwise - KRB5_BAD_ENCTYPE + + +.. + + + + + + + +This function returns the number of the padding octets required to pad *data_length* octets of plaintext. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_prf.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_prf.rst.txt new file mode 100644 index 00000000..2bf18e57 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_prf.rst.txt @@ -0,0 +1,53 @@ +krb5_c_prf - Generate enctype-specific pseudo-random bytes. +============================================================= + +.. + +.. c:function:: krb5_error_code krb5_c_prf(krb5_context context, const krb5_keyblock * keyblock, krb5_data * input, krb5_data * output) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **keyblock** - Key + + **[in]** **input** - Input data + + **[out]** **output** - Output data + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function selects a pseudo-random function based on *keyblock* and computes its value over *input* , placing the result into *output* . The caller must preinitialize *output* and allocate space for the result, using krb5_c_prf_length() to determine the required length. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_prf_length.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_prf_length.rst.txt new file mode 100644 index 00000000..ff20e291 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_prf_length.rst.txt @@ -0,0 +1,47 @@ +krb5_c_prf_length - Get the output length of pseudo-random functions for an encryption type. +============================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_prf_length(krb5_context context, krb5_enctype enctype, size_t * len) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enctype** - Encryption type + + **[out]** **len** - Length of PRF output + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_prfplus.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_prfplus.rst.txt new file mode 100644 index 00000000..682a8f46 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_prfplus.rst.txt @@ -0,0 +1,61 @@ +krb5_c_prfplus - Generate pseudo-random bytes using RFC 6113 PRF+. +==================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_prfplus(krb5_context context, const krb5_keyblock * k, const krb5_data * input, krb5_data * output) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **k** - KDC contribution key + + **[in]** **input** - Input data + + **[out]** **output** - Pseudo-random output buffer + + +.. + + + +:return: + - 0 on success, E2BIG if output->length is too large for PRF+ to generate, ENOMEM on allocation failure, or an error code from krb5_c_prf() + +.. + + + + + + + +This function fills *output* with PRF+(k, input) as defined in RFC 6113 section 5.1. The caller must preinitialize *output* and allocate the desired amount of space. The length of the pseudo-random output will match the length of *output* . + + + + + + + + + + +.. + + + + + + +.. note:: + + RFC 4402 defines a different PRF+ operation. This function does not implement that operation. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_add_entropy.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_add_entropy.rst.txt new file mode 100644 index 00000000..cfd87797 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_add_entropy.rst.txt @@ -0,0 +1,46 @@ +krb5_c_random_add_entropy +========================= + +.. + +.. c:function:: krb5_error_code krb5_c_random_add_entropy(krb5_context context, unsigned int randsource, const krb5_data * data) + +.. + + +:param: + + **context** + + **randsource** + + **data** + + +.. + + + +.. + + +DEPRECATED This call is no longer necessary. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_make_octets.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_make_octets.rst.txt new file mode 100644 index 00000000..91a1159b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_make_octets.rst.txt @@ -0,0 +1,49 @@ +krb5_c_random_make_octets - Generate pseudo-random bytes. +=========================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_random_make_octets(krb5_context context, krb5_data * data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **data** - Random data + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Fills in *data* with bytes from the PRNG used by krb5 crypto operations. The caller must preinitialize *data* and allocate the desired amount of space. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_os_entropy.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_os_entropy.rst.txt new file mode 100644 index 00000000..d4a66bdd --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_os_entropy.rst.txt @@ -0,0 +1,46 @@ +krb5_c_random_os_entropy +======================== + +.. + +.. c:function:: krb5_error_code krb5_c_random_os_entropy(krb5_context context, int strong, int * success) + +.. + + +:param: + + **context** + + **strong** + + **success** + + +.. + + + +.. + + +DEPRECATED This call is no longer necessary. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_seed.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_seed.rst.txt new file mode 100644 index 00000000..0b47a86e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_seed.rst.txt @@ -0,0 +1,44 @@ +krb5_c_random_seed +================== + +.. + +.. c:function:: krb5_error_code krb5_c_random_seed(krb5_context context, krb5_data * data) + +.. + + +:param: + + **context** + + **data** + + +.. + + + +.. + + +DEPRECATED This call is no longer necessary. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_to_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_to_key.rst.txt new file mode 100644 index 00000000..192e9d7e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_random_to_key.rst.txt @@ -0,0 +1,64 @@ +krb5_c_random_to_key - Generate an enctype-specific key from random data. +=========================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_random_to_key(krb5_context context, krb5_enctype enctype, krb5_data * random_data, krb5_keyblock * k5_random_key) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enctype** - Encryption type + + **[in]** **random_data** - Random input data + + **[out]** **k5_random_key** - Resulting key + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function takes random input data *random_data* and produces a valid key *k5_random_key* for a given *enctype* . + + + + + + + + + + +.. + +.. seealso:: + krb5_c_keylengths() + + + + + + +.. note:: + + It is assumed that *k5_random_key* has already been initialized and *k5_random_key->contents* has been allocated with the correct length. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_string_to_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_string_to_key.rst.txt new file mode 100644 index 00000000..0720b634 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_string_to_key.rst.txt @@ -0,0 +1,55 @@ +krb5_c_string_to_key - Convert a string (such a password) to a key. +===================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_string_to_key(krb5_context context, krb5_enctype enctype, const krb5_data * string, const krb5_data * salt, krb5_keyblock * key) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enctype** - Encryption type + + **[in]** **string** - String to be converted + + **[in]** **salt** - Salt value + + **[out]** **key** - Generated key + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function converts *string* to a *key* of encryption type *enctype* , using the specified *salt* . The newly created *key* must be released by calling krb5_free_keyblock_contents() when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_string_to_key_with_params.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_string_to_key_with_params.rst.txt new file mode 100644 index 00000000..6348a40a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_string_to_key_with_params.rst.txt @@ -0,0 +1,57 @@ +krb5_c_string_to_key_with_params - Convert a string (such as a password) to a key with additional parameters. +=============================================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_string_to_key_with_params(krb5_context context, krb5_enctype enctype, const krb5_data * string, const krb5_data * salt, const krb5_data * params, krb5_keyblock * key) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enctype** - Encryption type + + **[in]** **string** - String to be converted + + **[in]** **salt** - Salt value + + **[in]** **params** - Parameters + + **[out]** **key** - Generated key + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function is similar to krb5_c_string_to_key(), but also takes parameters which may affect the algorithm in an enctype-dependent way. The newly created *key* must be released by calling krb5_free_keyblock_contents() when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_valid_cksumtype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_valid_cksumtype.rst.txt new file mode 100644 index 00000000..0cc7787f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_valid_cksumtype.rst.txt @@ -0,0 +1,43 @@ +krb5_c_valid_cksumtype - Verify that specified checksum type is a valid Kerberos checksum type. +================================================================================================= + +.. + +.. c:function:: krb5_boolean krb5_c_valid_cksumtype(krb5_cksumtype ctype) + +.. + + +:param: + + **[in]** **ctype** - Checksum type + + +.. + + + +:return: + - TRUE if ctype is valid, FALSE if not + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_valid_enctype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_valid_enctype.rst.txt new file mode 100644 index 00000000..f5adeee8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_valid_enctype.rst.txt @@ -0,0 +1,43 @@ +krb5_c_valid_enctype - Verify that a specified encryption type is a valid Kerberos encryption type. +===================================================================================================== + +.. + +.. c:function:: krb5_boolean krb5_c_valid_enctype(krb5_enctype ktype) + +.. + + +:param: + + **[in]** **ktype** - Encryption type + + +.. + + + +:return: + - TRUE if ktype is valid, FALSE if not + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_verify_checksum.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_verify_checksum.rst.txt new file mode 100644 index 00000000..823d5707 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_verify_checksum.rst.txt @@ -0,0 +1,65 @@ +krb5_c_verify_checksum - Verify a checksum (operates on keyblock). +==================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_verify_checksum(krb5_context context, const krb5_keyblock * key, krb5_keyusage usage, const krb5_data * data, const krb5_checksum * cksum, krb5_boolean * valid) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Encryption key for a keyed checksum + + **[in]** **usage** - *key* usage + + **[in]** **data** - Data to be used to compute a new checksum using *key* to compare *cksum* against + + **[in]** **cksum** - Checksum to be verified + + **[out]** **valid** - Non-zero for success, zero for failure + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function verifies that *cksum* is a valid checksum for *data* . If the checksum type of *cksum* is a keyed checksum, *key* is used to verify the checksum. If the checksum type in *cksum* is 0 and *key* is not NULL, the mandatory checksum type for *key* will be used. The actual checksum key will be derived from *key* and *usage* if key derivation is specified for the checksum type. + + + + + + + + + + +.. + + + + + + +.. note:: + + This function is similar to krb5_k_verify_checksum(), but operates on keyblock *key* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_verify_checksum_iov.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_verify_checksum_iov.rst.txt new file mode 100644 index 00000000..237c01f1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_c_verify_checksum_iov.rst.txt @@ -0,0 +1,70 @@ +krb5_c_verify_checksum_iov - Validate a checksum element in IOV array (operates on keyblock). +=============================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_c_verify_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, const krb5_keyblock * key, krb5_keyusage usage, const krb5_crypto_iov * data, size_t num_data, krb5_boolean * valid) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cksumtype** - Checksum type (0 for mandatory type) + + **[in]** **key** - Encryption key for a keyed checksum + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[in]** **data** - IOV array + + **[in]** **num_data** - Size of *data* + + **[out]** **valid** - Non-zero for success, zero for failure + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Confirm that the checksum in the #KRB5_CRYPTO_TYPE_CHECKSUM element is a valid checksum of the #KRB5_CRYPTO_TYPE_DATA and #KRB5_CRYPTO_TYPE_SIGN_ONLY regions in the iov. + + + + + + + + + + +.. + +.. seealso:: + krb5_c_make_checksum_iov() + + + + + + +.. note:: + + This function is similar to krb5_k_verify_checksum_iov(), but operates on keyblock *key* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_calculate_checksum.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_calculate_checksum.rst.txt new file mode 100644 index 00000000..ef40b12e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_calculate_checksum.rst.txt @@ -0,0 +1,54 @@ +krb5_calculate_checksum +======================= + +.. + +.. c:function:: krb5_error_code krb5_calculate_checksum(krb5_context context, krb5_cksumtype ctype, krb5_const_pointer in, size_t in_length, krb5_const_pointer seed, size_t seed_length, krb5_checksum * outcksum) + +.. + + +:param: + + **context** + + **ctype** + + **in** + + **in_length** + + **seed** + + **seed_length** + + **outcksum** + + +.. + + + +.. + + +DEPRECATED See krb5_c_make_checksum() + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_cache_match.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_cache_match.rst.txt new file mode 100644 index 00000000..3e01acca --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_cache_match.rst.txt @@ -0,0 +1,56 @@ +krb5_cc_cache_match - Find a credential cache with a specified client principal. +================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_cache_match(krb5_context context, krb5_principal client, krb5_ccache * cache_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **client** - Client principal + + **[out]** **cache_out** - Credential cache handle + + +.. + + +:retval: + - 0 Success + - KRB5_CC_NOTFOUND None + + +.. + + + + + + + +Find a cache within the collection whose default principal is *client* . Use *krb5_cc_close* to close *ccache* when it is no longer needed. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.10 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_close.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_close.rst.txt new file mode 100644 index 00000000..6a58c9a2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_close.rst.txt @@ -0,0 +1,52 @@ +krb5_cc_close - Close a credential cache handle. +================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_close(krb5_context context, krb5_ccache cache) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function closes a credential cache handle *cache* without affecting the contents of the cache. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_copy_creds.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_copy_creds.rst.txt new file mode 100644 index 00000000..f3af7c11 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_copy_creds.rst.txt @@ -0,0 +1,47 @@ +krb5_cc_copy_creds - Copy a credential cache. +=============================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_copy_creds(krb5_context context, krb5_ccache incc, krb5_ccache outcc) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **incc** - Credential cache to be copied + + **[out]** **outcc** - Copy of credential cache to be filled in + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_default.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_default.rst.txt new file mode 100644 index 00000000..a734335f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_default.rst.txt @@ -0,0 +1,54 @@ +krb5_cc_default - Resolve the default credential cache name. +============================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_default(krb5_context context, krb5_ccache * ccache) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **ccache** - Pointer to credential cache name + + +.. + + +:retval: + - 0 Success + - KV5M_CONTEXT Bad magic number for _krb5_context structure + - KRB5_FCC_INTERNAL The name of the default credential cache cannot be obtained + + +:return: + - Kerberos error codes + +.. + + + + + + + +Create a handle to the default credential cache as given by krb5_cc_default_name(). + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_default_name.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_default_name.rst.txt new file mode 100644 index 00000000..d9f3e7d0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_default_name.rst.txt @@ -0,0 +1,51 @@ +krb5_cc_default_name - Return the name of the default credential cache. +========================================================================= + +.. + +.. c:function:: const char * krb5_cc_default_name(krb5_context context) + +.. + + +:param: + + **[in]** **context** - Library context + + +.. + + + +:return: + - Name of default credential cache for the current user. + +.. + + + + + + + +Return a pointer to the default credential cache name for *context* , as determined by a prior call to krb5_cc_set_default_name(), by the KRB5CCNAME environment variable, by the default_ccache_name profile variable, or by the operating system or build-time default value. The returned value must not be modified or freed by the caller. The returned value becomes invalid when *context* is destroyed krb5_free_context() or if a subsequent call to krb5_cc_set_default_name() is made on *context* . + + + +The default credential cache name is cached in *context* between calls to this function, so if the value of KRB5CCNAME changes in the process environment after the first call to this function on, that change will not be reflected in later calls with the same context. The caller can invoke krb5_cc_set_default_name() with a NULL value of *name* to clear the cached value and force the default name to be recomputed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_destroy.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_destroy.rst.txt new file mode 100644 index 00000000..12254719 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_destroy.rst.txt @@ -0,0 +1,52 @@ +krb5_cc_destroy - Destroy a credential cache. +=============================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_destroy(krb5_context context, krb5_ccache cache) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + +.. + + +:retval: + - 0 Success + + +:return: + - Permission errors + +.. + + + + + + + +This function destroys any existing contents of *cache* and closes the handle to it. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_dup.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_dup.rst.txt new file mode 100644 index 00000000..00179a0b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_dup.rst.txt @@ -0,0 +1,44 @@ +krb5_cc_dup - Duplicate ccache handle. +======================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_dup(krb5_context context, krb5_ccache in, krb5_ccache * out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **in** - Credential cache handle to be duplicated + + **[out]** **out** - Credential cache handle + + +.. + + + +.. + + + + + + + +Create a new handle referring to the same cache as *in* . The new handle and *in* can be closed independently. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_end_seq_get.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_end_seq_get.rst.txt new file mode 100644 index 00000000..0b4fb656 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_end_seq_get.rst.txt @@ -0,0 +1,54 @@ +krb5_cc_end_seq_get - Finish a series of sequential processing credential cache entries. +========================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_end_seq_get(krb5_context context, krb5_ccache cache, krb5_cc_cursor * cursor) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + **[in]** **cursor** - Cursor + + +.. + + +:retval: + - 0 (always) + + +.. + + + + + + + +This function finishes processing credential cache entries and invalidates *cursor* . + + + + + + + + + + +.. + +.. seealso:: + krb5_cc_start_seq_get(), krb5_cc_next_cred() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_gen_new.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_gen_new.rst.txt new file mode 100644 index 00000000..3672b362 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_gen_new.rst.txt @@ -0,0 +1,39 @@ +krb5_cc_gen_new +=============== + +.. + +.. c:function:: krb5_error_code krb5_cc_gen_new(krb5_context context, krb5_ccache * cache) + +.. + + +:param: + + **context** + + **cache** + + +.. + + + +.. + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_config.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_config.rst.txt new file mode 100644 index 00000000..3c5576ed --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_config.rst.txt @@ -0,0 +1,58 @@ +krb5_cc_get_config - Get a configuration value from a credential cache. +========================================================================= + +.. + +.. c:function:: krb5_error_code krb5_cc_get_config(krb5_context context, krb5_ccache id, krb5_const_principal principal, const char * key, krb5_data * data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **id** - Credential cache handle + + **[in]** **principal** - Configuration for this principal; if NULL, global for the whole cache + + **[in]** **key** - Name of config variable + + **[out]** **data** - Data to be fetched + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Use krb5_free_data_contents() to free *data* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_flags.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_flags.rst.txt new file mode 100644 index 00000000..ca764c8b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_flags.rst.txt @@ -0,0 +1,55 @@ +krb5_cc_get_flags - Retrieve flags from a credential cache structure. +======================================================================= + +.. + +.. c:function:: krb5_error_code krb5_cc_get_flags(krb5_context context, krb5_ccache cache, krb5_flags * flags) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + **[out]** **flags** - Flag bit mask + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + +.. warning:: + + For memory credential cache always returns a flag mask of 0. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_full_name.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_full_name.rst.txt new file mode 100644 index 00000000..fdab6616 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_full_name.rst.txt @@ -0,0 +1,52 @@ +krb5_cc_get_full_name - Retrieve the full name of a credential cache. +======================================================================= + +.. + +.. c:function:: krb5_error_code krb5_cc_get_full_name(krb5_context context, krb5_ccache cache, char ** fullname_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + **[out]** **fullname_out** - Full name of cache + + +.. + + + +.. + + + + + + + +Use krb5_free_string() to free *fullname_out* when it is no longer needed. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.10 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_name.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_name.rst.txt new file mode 100644 index 00000000..3115b0b0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_name.rst.txt @@ -0,0 +1,53 @@ +krb5_cc_get_name - Retrieve the name, but not type of a credential cache. +=========================================================================== + +.. + +.. c:function:: const char * krb5_cc_get_name(krb5_context context, krb5_ccache cache) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + +.. + + + +:return: + - On success - the name of the credential cache. + +.. + + + + + + + + + + + + + + +.. + + + + + +.. warning:: + + Returns the name of the credential cache. The result is an alias into *cache* and should not be freed or modified by the caller. This name does not include the cache type, so should not be used as input to krb5_cc_resolve(). + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_principal.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_principal.rst.txt new file mode 100644 index 00000000..059d10a2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_principal.rst.txt @@ -0,0 +1,58 @@ +krb5_cc_get_principal - Get the default principal of a credential cache. +========================================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_get_principal(krb5_context context, krb5_ccache cache, krb5_principal * principal) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + **[out]** **principal** - Primary principal + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Returns the default client principal of a credential cache as set by krb5_cc_initialize(). + + + +Use krb5_free_principal() to free *principal* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_type.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_type.rst.txt new file mode 100644 index 00000000..a970bd6d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_get_type.rst.txt @@ -0,0 +1,45 @@ +krb5_cc_get_type - Retrieve the type of a credential cache. +============================================================= + +.. + +.. c:function:: const char * krb5_cc_get_type(krb5_context context, krb5_ccache cache) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + +.. + + + +:return: + - The type of a credential cache as an alias that must not be modified or freed by the caller. + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_initialize.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_initialize.rst.txt new file mode 100644 index 00000000..d306a292 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_initialize.rst.txt @@ -0,0 +1,54 @@ +krb5_cc_initialize - Initialize a credential cache. +===================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_initialize(krb5_context context, krb5_ccache cache, krb5_principal principal) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + **[in]** **principal** - Default principal name + + +.. + + +:retval: + - 0 Success + + +:return: + - System errors; Permission errors; Kerberos error codes + +.. + + + + + + + +Destroy any existing contents of *cache* and initialize it for the default principal *principal* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_move.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_move.rst.txt new file mode 100644 index 00000000..ba9f0fd1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_move.rst.txt @@ -0,0 +1,54 @@ +krb5_cc_move - Move a credential cache. +========================================= + +.. + +.. c:function:: krb5_error_code krb5_cc_move(krb5_context context, krb5_ccache src, krb5_ccache dst) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **src** - The credential cache to move the content from + + **[in]** **dst** - The credential cache to move the content to + + +.. + + +:retval: + - 0 Success; src is closed. + + +:return: + - Kerberos error codes; src is still allocated. + +.. + + + + + + + +This function reinitializes *dst* and populates it with the credentials and default principal of *src* ; then, if successful, destroys *src* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_new_unique.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_new_unique.rst.txt new file mode 100644 index 00000000..e4313c07 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_new_unique.rst.txt @@ -0,0 +1,52 @@ +krb5_cc_new_unique - Create a new credential cache of the specified type with a unique name. +============================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_new_unique(krb5_context context, const char * type, const char * hint, krb5_ccache * id) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **type** - Credential cache type name + + **[in]** **hint** - Unused + + **[out]** **id** - Credential cache handle + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_next_cred.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_next_cred.rst.txt new file mode 100644 index 00000000..e9d7b1e4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_next_cred.rst.txt @@ -0,0 +1,60 @@ +krb5_cc_next_cred - Retrieve the next entry from the credential cache. +======================================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_next_cred(krb5_context context, krb5_ccache cache, krb5_cc_cursor * cursor, krb5_creds * creds) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + **[in]** **cursor** - Cursor + + **[out]** **creds** - Next credential cache entry + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function fills in *creds* with the next entry in *cache* and advances *cursor* . + + + +Use krb5_free_cred_contents() to free *creds* when it is no longer needed. + + + + + + + + + + +.. + +.. seealso:: + krb5_cc_start_seq_get(), krb5_end_seq_get() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_remove_cred.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_remove_cred.rst.txt new file mode 100644 index 00000000..274f8c50 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_remove_cred.rst.txt @@ -0,0 +1,64 @@ +krb5_cc_remove_cred - Remove credentials from a credential cache. +=================================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags, krb5_creds * creds) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + **[in]** **flags** - Bitwise-ORed search flags + + **[in]** **creds** - Credentials to be matched + + +.. + + +:retval: + - KRB5_CC_NOSUPP Not implemented for this cache type + + +:return: + - No matches found; Data cannot be deleted; Kerberos error codes + +.. + + + + + + + +This function accepts the same flag values as krb5_cc_retrieve_cred(). + + + + + + + + + + +.. + + + + + +.. warning:: + + This function is not implemented for some cache types. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_resolve.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_resolve.rst.txt new file mode 100644 index 00000000..746ac6c2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_resolve.rst.txt @@ -0,0 +1,58 @@ +krb5_cc_resolve - Resolve a credential cache name. +==================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_resolve(krb5_context context, const char * name, krb5_ccache * cache) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **name** - Credential cache name to be resolved + + **[out]** **cache** - Credential cache handle + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Fills in *cache* with a *cache* handle that corresponds to the name in *name* . *name* should be of the form **type:residual** , and *type* must be a type known to the library. If the *name* does not contain a colon, interpret it as a file name. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_retrieve_cred.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_retrieve_cred.rst.txt new file mode 100644 index 00000000..3674f97d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_retrieve_cred.rst.txt @@ -0,0 +1,94 @@ +krb5_cc_retrieve_cred - Retrieve a specified credentials from a credential cache. +=================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_retrieve_cred(krb5_context context, krb5_ccache cache, krb5_flags flags, krb5_creds * mcreds, krb5_creds * creds) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + **[in]** **flags** - Flags bit mask + + **[in]** **mcreds** - Credentials to match + + **[out]** **creds** - Credentials matching the requested value + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function searches a credential cache for credentials matching *mcreds* and returns it if found. + + + +Valid values for *flags* are: + + + + + + - #KRB5_TC_MATCH_TIMES The requested lifetime must be at least as great as in *mcreds* . + + + - #KRB5_TC_MATCH_IS_SKEY The *is_skey* field much match exactly. + + + - #KRB5_TC_MATCH_FLAGS Flags set in *mcreds* must be set. + + + - #KRB5_TC_MATCH_TIMES_EXACT The requested lifetime must match exactly. + + + - #KRB5_TC_MATCH_FLAGS_EXACT Flags must match exactly. + + + - #KRB5_TC_MATCH_AUTHDATA The authorization data must match. + + + - #KRB5_TC_MATCH_SRV_NAMEONLY Only the name portion of the principal name must match, not the realm. + + + - #KRB5_TC_MATCH_2ND_TKT The second tickets must match. + + + - #KRB5_TC_MATCH_KTYPE The encryption key types must match. + + + - #KRB5_TC_SUPPORTED_KTYPES Check all matching entries that have any supported encryption type and return the one with the encryption type listed earliest. + + Use krb5_free_cred_contents() to free *creds* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_select.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_select.rst.txt new file mode 100644 index 00000000..c221a65b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_select.rst.txt @@ -0,0 +1,73 @@ +krb5_cc_select - Select a credential cache to use with a server principal. +============================================================================ + +.. + +.. c:function:: krb5_error_code krb5_cc_select(krb5_context context, krb5_principal server, krb5_ccache * cache_out, krb5_principal * princ_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **server** - Server principal + + **[out]** **cache_out** - Credential cache handle + + **[out]** **princ_out** - Client principal + + +.. + + + +:return: + - If an appropriate cache is found, 0 is returned, cache_out is set to the selected cache, and princ_out is set to the default principal of that cache. + +.. + + + + + + + +Select a cache within the collection containing credentials most appropriate for use with *server* , according to configured rules and heuristics. + + + +Use krb5_cc_close() to release *cache_out* when it is no longer needed. Use krb5_free_principal() to release *princ_out* when it is no longer needed. Note that *princ_out* is set in some error conditions. + + + +If the appropriate client principal can be authoritatively determined but the cache collection contains no credentials for that principal, then KRB5_CC_NOTFOUND is returned, *cache_out* is set to NULL, and *princ_out* is set to the appropriate client principal. + + + +If no configured mechanism can determine the appropriate cache or principal, KRB5_CC_NOTFOUND is returned and *cache_out* and *princ_out* are set to NULL. + + + +Any other error code indicates a fatal error in the processing of a cache selection mechanism. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.10 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_set_config.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_set_config.rst.txt new file mode 100644 index 00000000..fdcc6139 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_set_config.rst.txt @@ -0,0 +1,66 @@ +krb5_cc_set_config - Store a configuration value in a credential cache. +========================================================================= + +.. + +.. c:function:: krb5_error_code krb5_cc_set_config(krb5_context context, krb5_ccache id, krb5_const_principal principal, const char * key, krb5_data * data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **id** - Credential cache handle + + **[in]** **principal** - Configuration for a specific principal; if NULL, global for the whole cache + + **[in]** **key** - Name of config variable + + **[in]** **data** - Data to store, or NULL to remove + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + + + + + + + + +.. + + + + + +.. warning:: + + Before version 1.10 *data* was assumed to be always non-null. + + +.. note:: + + Existing configuration under the same key is over-written. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_set_default_name.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_set_default_name.rst.txt new file mode 100644 index 00000000..6c78ac6c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_set_default_name.rst.txt @@ -0,0 +1,57 @@ +krb5_cc_set_default_name - Set the default credential cache name. +=================================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_set_default_name(krb5_context context, const char * name) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **name** - Default credential cache name or NULL + + +.. + + +:retval: + - 0 Success + - KV5M_CONTEXT Bad magic number for _krb5_context structure + + +:return: + - Kerberos error codes + +.. + + + + + + + +Set the default credential cache name to *name* for future operations using *context* . If *name* is NULL, clear any previous application-set default name and forget any cached value of the default name for *context* . + + + +Calls to this function invalidate the result of any previous calls to krb5_cc_default_name() using *context* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_set_flags.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_set_flags.rst.txt new file mode 100644 index 00000000..d68d8748 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_set_flags.rst.txt @@ -0,0 +1,51 @@ +krb5_cc_set_flags - Set options flags on a credential cache. +============================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_set_flags(krb5_context context, krb5_ccache cache, krb5_flags flags) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + **[in]** **flags** - Flag bit mask + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function resets *cache* flags to *flags* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_start_seq_get.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_start_seq_get.rst.txt new file mode 100644 index 00000000..84fa02ba --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_start_seq_get.rst.txt @@ -0,0 +1,59 @@ +krb5_cc_start_seq_get - Prepare to sequentially read every credential in a credential cache. +============================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_start_seq_get(krb5_context context, krb5_ccache cache, krb5_cc_cursor * cursor) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + **[out]** **cursor** - Cursor + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +krb5_cc_end_seq_get() must be called to complete the retrieve operation. + + + + + + + + + + +.. + + + + + + +.. note:: + + If the cache represented by *cache* is modified between the time of the call to this function and the time of the final krb5_cc_end_seq_get(), these changes may not be reflected in the results of krb5_cc_next_cred() calls. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_store_cred.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_store_cred.rst.txt new file mode 100644 index 00000000..1cc27ccc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_store_cred.rst.txt @@ -0,0 +1,54 @@ +krb5_cc_store_cred - Store credentials in a credential cache. +=============================================================== + +.. + +.. c:function:: krb5_error_code krb5_cc_store_cred(krb5_context context, krb5_ccache cache, krb5_creds * creds) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + **[in]** **creds** - Credentials to be stored in cache + + +.. + + +:retval: + - 0 Success + + +:return: + - Permission errors; storage failure errors; Kerberos error codes + +.. + + + + + + + +This function stores *creds* into *cache* . If *creds->server* and the server in the decoded ticket *creds->ticket* differ, the credentials will be stored under both server principal names. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_support_switch.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_support_switch.rst.txt new file mode 100644 index 00000000..394629b0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_support_switch.rst.txt @@ -0,0 +1,50 @@ +krb5_cc_support_switch - Determine whether a credential cache type supports switching. +======================================================================================== + +.. + +.. c:function:: krb5_boolean krb5_cc_support_switch(krb5_context context, const char * type) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **type** - Credential cache type + + +.. + + +:retval: + - TRUE if type supports switching + - FALSE if it does not or is not a valid credential cache type. + + +.. + + + + + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.10 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_switch.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_switch.rst.txt new file mode 100644 index 00000000..ef4c570d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cc_switch.rst.txt @@ -0,0 +1,52 @@ +krb5_cc_switch - Make a credential cache the primary cache for its collection. +================================================================================ + +.. + +.. c:function:: krb5_error_code krb5_cc_switch(krb5_context context, krb5_ccache cache) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cache** - Credential cache handle + + +.. + + +:retval: + - 0 Success, or the type of cache doesn't support switching + + +:return: + - Kerberos error codes + +.. + + + + + + + +If the type of *cache* supports it, set *cache* to be the primary credential cache for the collection it belongs to. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_cursor_free.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_cursor_free.rst.txt new file mode 100644 index 00000000..ce397b92 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_cursor_free.rst.txt @@ -0,0 +1,48 @@ +krb5_cccol_cursor_free - Free a credential cache collection cursor. +===================================================================== + +.. + +.. c:function:: krb5_error_code krb5_cccol_cursor_free(krb5_context context, krb5_cccol_cursor * cursor) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cursor** - Cursor + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + +.. seealso:: + krb5_cccol_cursor_new(), krb5_cccol_cursor_next() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_cursor_new.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_cursor_new.rst.txt new file mode 100644 index 00000000..b1673332 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_cursor_new.rst.txt @@ -0,0 +1,56 @@ +krb5_cccol_cursor_new - Prepare to iterate over the collection of known credential caches. +============================================================================================ + +.. + +.. c:function:: krb5_error_code krb5_cccol_cursor_new(krb5_context context, krb5_cccol_cursor * cursor) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **cursor** - Cursor + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Get a new cache iteration *cursor* that will iterate over all known credential caches independent of type. + + + +Use krb5_cccol_cursor_free() to release *cursor* when it is no longer needed. + + + + + + + + + + +.. + +.. seealso:: + krb5_cccol_cursor_next() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_cursor_next.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_cursor_next.rst.txt new file mode 100644 index 00000000..d019a049 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_cursor_next.rst.txt @@ -0,0 +1,62 @@ +krb5_cccol_cursor_next - Get the next credential cache in the collection. +=========================================================================== + +.. + +.. c:function:: krb5_error_code krb5_cccol_cursor_next(krb5_context context, krb5_cccol_cursor cursor, krb5_ccache * ccache) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cursor** - Cursor + + **[out]** **ccache** - Credential cache handle + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Use krb5_cc_close() to close *ccache* when it is no longer needed. + + + + + + + + + + +.. + +.. seealso:: + krb5_cccol_cursor_new(), krb5_cccol_cursor_free() + + + + + + +.. note:: + + When all caches are iterated over and the end of the list is reached, *ccache* is set to NULL. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_have_content.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_have_content.rst.txt new file mode 100644 index 00000000..d1c7426e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cccol_have_content.rst.txt @@ -0,0 +1,48 @@ +krb5_cccol_have_content - Check if the credential cache collection contains any initialized caches. +===================================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_cccol_have_content(krb5_context context) + +.. + + +:param: + + **[in]** **context** - Library context + + +.. + + +:retval: + - 0 At least one initialized cache is present in the collection + - KRB5_CC_NOTFOUND The collection contains no caches + + +.. + + + + + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.11 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_change_password.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_change_password.rst.txt new file mode 100644 index 00000000..05a3eb95 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_change_password.rst.txt @@ -0,0 +1,77 @@ +krb5_change_password - Change a password for an existing Kerberos account. +============================================================================ + +.. + +.. c:function:: krb5_error_code krb5_change_password(krb5_context context, krb5_creds * creds, const char * newpw, int * result_code, krb5_data * result_code_string, krb5_data * result_string) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **creds** - Credentials for kadmin/changepw service + + **[in]** **newpw** - New password + + **[out]** **result_code** - Numeric error code from server + + **[out]** **result_code_string** - String equivalent to *result_code* + + **[out]** **result_string** - Change password response from the KDC + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Change the password for the existing principal identified by *creds* . + + + +The possible values of the output *result_code* are: + + + + + + - #KRB5_KPASSWD_SUCCESS (0) - success + + + - #KRB5_KPASSWD_MALFORMED (1) - Malformed request error + + + - #KRB5_KPASSWD_HARDERROR (2) - Server error + + + - #KRB5_KPASSWD_AUTHERROR (3) - Authentication error + + + - #KRB5_KPASSWD_SOFTERROR (4) - Password change rejected + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_check_clockskew.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_check_clockskew.rst.txt new file mode 100644 index 00000000..4999d485 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_check_clockskew.rst.txt @@ -0,0 +1,54 @@ +krb5_check_clockskew - Check if a timestamp is within the allowed clock skew of the current time. +=================================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_check_clockskew(krb5_context context, krb5_timestamp date) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **date** - Timestamp to check + + +.. + + +:retval: + - 0 Success + - KRB5KRB_AP_ERR_SKEW date is not within allowable clock skew + + +.. + + + + + + + +This function checks if *date* is close enough to the current time according to the configured allowable clock skew. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.10 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_checksum_size.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_checksum_size.rst.txt new file mode 100644 index 00000000..5a676991 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_checksum_size.rst.txt @@ -0,0 +1,44 @@ +krb5_checksum_size +================== + +.. + +.. c:function:: size_t krb5_checksum_size(krb5_context context, krb5_cksumtype ctype) + +.. + + +:param: + + **context** + + **ctype** + + +.. + + + +.. + + +DEPRECATED See krb5_c_checksum_length() + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_chpw_message.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_chpw_message.rst.txt new file mode 100644 index 00000000..3f4919e5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_chpw_message.rst.txt @@ -0,0 +1,62 @@ +krb5_chpw_message - Get a result message for changing or setting a password. +============================================================================== + +.. + +.. c:function:: krb5_error_code krb5_chpw_message(krb5_context context, const krb5_data * server_string, char ** message_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **server_string** - Data returned from the remote system + + **[out]** **message_out** - A message displayable to the user + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function processes the *server_string* returned in the *result_string* parameter of krb5_change_password(), krb5_set_password(), and related functions, and returns a displayable string. If *server_string* contains Active Directory structured policy information, it will be converted into human-readable text. + + + +Use krb5_free_string() to free *message_out* when it is no longer needed. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.11 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cksumtype_to_string.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cksumtype_to_string.rst.txt new file mode 100644 index 00000000..a297c8f9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_cksumtype_to_string.rst.txt @@ -0,0 +1,47 @@ +krb5_cksumtype_to_string - Convert a checksum type to a string. +================================================================= + +.. + +.. c:function:: krb5_error_code krb5_cksumtype_to_string(krb5_cksumtype cksumtype, char * buffer, size_t buflen) + +.. + + +:param: + + **[in]** **cksumtype** - Checksum type + + **[out]** **buffer** - Buffer to hold converted checksum type + + **[in]** **buflen** - Storage available in *buffer* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_clear_error_message.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_clear_error_message.rst.txt new file mode 100644 index 00000000..c988ca3a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_clear_error_message.rst.txt @@ -0,0 +1,40 @@ +krb5_clear_error_message - Clear the extended error message in a context. +=========================================================================== + +.. + +.. c:function:: void krb5_clear_error_message(krb5_context ctx) + +.. + + +:param: + + **[in]** **ctx** - Library context + + +.. + + + +.. + + + + + + + +This function unsets the extended error message in a context, to ensure that it is not mistakenly applied to another occurrence of the same error code. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_addresses.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_addresses.rst.txt new file mode 100644 index 00000000..e1f85b89 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_addresses.rst.txt @@ -0,0 +1,51 @@ +krb5_copy_addresses - Copy an array of addresses. +=================================================== + +.. + +.. c:function:: krb5_error_code krb5_copy_addresses(krb5_context context, krb5_address *const * inaddr, krb5_address *** outaddr) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **inaddr** - Array of addresses to be copied + + **[out]** **outaddr** - Copy of array of addresses + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a new address array containing a copy of *inaddr* . Use krb5_free_addresses() to free *outaddr* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_authdata.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_authdata.rst.txt new file mode 100644 index 00000000..518b95e6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_authdata.rst.txt @@ -0,0 +1,59 @@ +krb5_copy_authdata - Copy an authorization data list. +======================================================= + +.. + +.. c:function:: krb5_error_code krb5_copy_authdata(krb5_context context, krb5_authdata *const * in_authdat, krb5_authdata *** out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **in_authdat** - List of *krb5_authdata* structures + + **[out]** **out** - New array of *krb5_authdata* structures + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a new authorization data list containing a copy of *in_authdat* , which must be null-terminated. Use krb5_free_authdata() to free *out* when it is no longer needed. + + + + + + + + + + +.. + + + + + + +.. note:: + + The last array entry in *in_authdat* must be a NULL pointer. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_authenticator.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_authenticator.rst.txt new file mode 100644 index 00000000..a3d043cd --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_authenticator.rst.txt @@ -0,0 +1,51 @@ +krb5_copy_authenticator - Copy a krb5_authenticator structure. +================================================================ + +.. + +.. c:function:: krb5_error_code krb5_copy_authenticator(krb5_context context, const krb5_authenticator * authfrom, krb5_authenticator ** authto) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **authfrom** - krb5_authenticator structure to be copied + + **[out]** **authto** - Copy of krb5_authenticator structure + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a new krb5_authenticator structure with the content of *authfrom* . Use krb5_free_authenticator() to free *authto* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_checksum.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_checksum.rst.txt new file mode 100644 index 00000000..3e94c3ca --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_checksum.rst.txt @@ -0,0 +1,51 @@ +krb5_copy_checksum - Copy a krb5_checksum structure. +====================================================== + +.. + +.. c:function:: krb5_error_code krb5_copy_checksum(krb5_context context, const krb5_checksum * ckfrom, krb5_checksum ** ckto) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ckfrom** - Checksum to be copied + + **[out]** **ckto** - Copy of krb5_checksum structure + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a new krb5_checksum structure with the contents of *ckfrom* . Use krb5_free_checksum() to free *ckto* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_context.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_context.rst.txt new file mode 100644 index 00000000..50df96fc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_context.rst.txt @@ -0,0 +1,52 @@ +krb5_copy_context - Copy a krb5_context structure. +==================================================== + +.. + +.. c:function:: krb5_error_code krb5_copy_context(krb5_context ctx, krb5_context * nctx_out) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[out]** **nctx_out** - New context structure + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +The newly created context must be released by calling krb5_free_context() when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_creds.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_creds.rst.txt new file mode 100644 index 00000000..ac7df356 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_creds.rst.txt @@ -0,0 +1,51 @@ +krb5_copy_creds - Copy a krb5_creds structure. +================================================ + +.. + +.. c:function:: krb5_error_code krb5_copy_creds(krb5_context context, const krb5_creds * incred, krb5_creds ** outcred) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **incred** - Credentials structure to be copied + + **[out]** **outcred** - Copy of *incred* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a new credential with the contents of *incred* . Use krb5_free_creds() to free *outcred* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_data.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_data.rst.txt new file mode 100644 index 00000000..a7714f0e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_data.rst.txt @@ -0,0 +1,51 @@ +krb5_copy_data - Copy a krb5_data object. +=========================================== + +.. + +.. c:function:: krb5_error_code krb5_copy_data(krb5_context context, const krb5_data * indata, krb5_data ** outdata) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **indata** - Data object to be copied + + **[out]** **outdata** - Copy of *indata* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a new krb5_data object with the contents of *indata* . Use krb5_free_data() to free *outdata* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_error_message.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_error_message.rst.txt new file mode 100644 index 00000000..3904cabf --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_error_message.rst.txt @@ -0,0 +1,42 @@ +krb5_copy_error_message - Copy the most recent extended error message from one context to another. +==================================================================================================== + +.. + +.. c:function:: void krb5_copy_error_message(krb5_context dest_ctx, krb5_context src_ctx) + +.. + + +:param: + + **[in]** **dest_ctx** - Library context to copy message to + + **[in]** **src_ctx** - Library context with current message + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_keyblock.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_keyblock.rst.txt new file mode 100644 index 00000000..a9b1bcf2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_keyblock.rst.txt @@ -0,0 +1,51 @@ +krb5_copy_keyblock - Copy a keyblock. +======================================= + +.. + +.. c:function:: krb5_error_code krb5_copy_keyblock(krb5_context context, const krb5_keyblock * from, krb5_keyblock ** to) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **from** - Keyblock to be copied + + **[out]** **to** - Copy of keyblock *from* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a new keyblock with the same contents as *from* . Use krb5_free_keyblock() to free *to* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_keyblock_contents.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_keyblock_contents.rst.txt new file mode 100644 index 00000000..c485dac8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_keyblock_contents.rst.txt @@ -0,0 +1,51 @@ +krb5_copy_keyblock_contents - Copy the contents of a keyblock. +================================================================ + +.. + +.. c:function:: krb5_error_code krb5_copy_keyblock_contents(krb5_context context, const krb5_keyblock * from, krb5_keyblock * to) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **from** - Key to be copied + + **[out]** **to** - Output key + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function copies the contents of *from* to *to* . Use krb5_free_keyblock_contents() to free *to* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_principal.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_principal.rst.txt new file mode 100644 index 00000000..1db2d06f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_principal.rst.txt @@ -0,0 +1,51 @@ +krb5_copy_principal - Copy a principal. +========================================= + +.. + +.. c:function:: krb5_error_code krb5_copy_principal(krb5_context context, krb5_const_principal inprinc, krb5_principal * outprinc) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **inprinc** - Principal to be copied + + **[out]** **outprinc** - Copy of *inprinc* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a new principal structure with the contents of *inprinc* . Use krb5_free_principal() to free *outprinc* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_ticket.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_ticket.rst.txt new file mode 100644 index 00000000..db434f7b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_copy_ticket.rst.txt @@ -0,0 +1,51 @@ +krb5_copy_ticket - Copy a krb5_ticket structure. +================================================== + +.. + +.. c:function:: krb5_error_code krb5_copy_ticket(krb5_context context, const krb5_ticket * from, krb5_ticket ** pto) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **from** - Ticket to be copied + + **[out]** **pto** - Copy of ticket + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a new krb5_ticket structure containing the contents of *from* . Use krb5_free_ticket() to free *pto* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_decode_authdata_container.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_decode_authdata_container.rst.txt new file mode 100644 index 00000000..6a93d7bb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_decode_authdata_container.rst.txt @@ -0,0 +1,52 @@ +krb5_decode_authdata_container - Unwrap authorization data. +============================================================= + +.. + +.. c:function:: krb5_error_code krb5_decode_authdata_container(krb5_context context, krb5_authdatatype type, const krb5_authdata * container, krb5_authdata *** authdata) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **type** - Container type (see KRB5_AUTHDATA macros) + + **[in]** **container** - Authorization data to be decoded + + **[out]** **authdata** - List of decoded authorization data + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + +.. seealso:: + krb5_encode_authdata_container() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_decode_ticket.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_decode_ticket.rst.txt new file mode 100644 index 00000000..8f2cf821 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_decode_ticket.rst.txt @@ -0,0 +1,45 @@ +krb5_decode_ticket - Decode an ASN.1-formatted ticket. +======================================================== + +.. + +.. c:function:: krb5_error_code krb5_decode_ticket(const krb5_data * code, krb5_ticket ** rep) + +.. + + +:param: + + **[in]** **code** - ASN.1-formatted ticket + + **[out]** **rep** - Decoded ticket information + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_decrypt.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_decrypt.rst.txt new file mode 100644 index 00000000..eb8123ff --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_decrypt.rst.txt @@ -0,0 +1,52 @@ +krb5_decrypt +============ + +.. + +.. c:function:: krb5_error_code krb5_decrypt(krb5_context context, krb5_const_pointer inptr, krb5_pointer outptr, size_t size, krb5_encrypt_block * eblock, krb5_pointer ivec) + +.. + + +:param: + + **context** + + **inptr** + + **outptr** + + **size** + + **eblock** + + **ivec** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_c_* API family. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_deltat_to_string.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_deltat_to_string.rst.txt new file mode 100644 index 00000000..3b66ba3b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_deltat_to_string.rst.txt @@ -0,0 +1,47 @@ +krb5_deltat_to_string - Convert a relative time value to a string. +==================================================================== + +.. + +.. c:function:: krb5_error_code krb5_deltat_to_string(krb5_deltat deltat, char * buffer, size_t buflen) + +.. + + +:param: + + **[in]** **deltat** - Relative time value to convert + + **[out]** **buffer** - Buffer to hold time string + + **[in]** **buflen** - Storage available in *buffer* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_eblock_enctype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_eblock_enctype.rst.txt new file mode 100644 index 00000000..c621a6df --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_eblock_enctype.rst.txt @@ -0,0 +1,44 @@ +krb5_eblock_enctype +=================== + +.. + +.. c:function:: krb5_enctype krb5_eblock_enctype(krb5_context context, const krb5_encrypt_block * eblock) + +.. + + +:param: + + **context** + + **eblock** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_c_* API family. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_encode_authdata_container.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_encode_authdata_container.rst.txt new file mode 100644 index 00000000..3bf9d776 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_encode_authdata_container.rst.txt @@ -0,0 +1,56 @@ +krb5_encode_authdata_container - Wrap authorization data in a container. +========================================================================== + +.. + +.. c:function:: krb5_error_code krb5_encode_authdata_container(krb5_context context, krb5_authdatatype type, krb5_authdata *const * authdata, krb5_authdata *** container) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **type** - Container type (see KRB5_AUTHDATA macros) + + **[in]** **authdata** - List of authorization data to be encoded + + **[out]** **container** - List of encoded authorization data + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +The result is returned in *container* as a single-element list. + + + + + + + + + + +.. + +.. seealso:: + krb5_decode_authdata_container() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_encrypt.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_encrypt.rst.txt new file mode 100644 index 00000000..56e93be1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_encrypt.rst.txt @@ -0,0 +1,52 @@ +krb5_encrypt +============ + +.. + +.. c:function:: krb5_error_code krb5_encrypt(krb5_context context, krb5_const_pointer inptr, krb5_pointer outptr, size_t size, krb5_encrypt_block * eblock, krb5_pointer ivec) + +.. + + +:param: + + **context** + + **inptr** + + **outptr** + + **size** + + **eblock** + + **ivec** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_c_* API family. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_encrypt_size.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_encrypt_size.rst.txt new file mode 100644 index 00000000..f331490f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_encrypt_size.rst.txt @@ -0,0 +1,44 @@ +krb5_encrypt_size +================= + +.. + +.. c:function:: size_t krb5_encrypt_size(size_t length, krb5_enctype crypto) + +.. + + +:param: + + **length** + + **crypto** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_c_* API family. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_enctype_to_name.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_enctype_to_name.rst.txt new file mode 100644 index 00000000..d830697c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_enctype_to_name.rst.txt @@ -0,0 +1,57 @@ +krb5_enctype_to_name - Convert an encryption type to a name or alias. +======================================================================= + +.. + +.. c:function:: krb5_error_code krb5_enctype_to_name(krb5_enctype enctype, krb5_boolean shortest, char * buffer, size_t buflen) + +.. + + +:param: + + **[in]** **enctype** - Encryption type + + **[in]** **shortest** - Flag + + **[out]** **buffer** - Buffer to hold encryption type string + + **[in]** **buflen** - Storage available in *buffer* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +If *shortest* is FALSE, this function returns the enctype's canonical name (like"aes128-cts-hmac-sha1-96"). If *shortest* is TRUE, it return the enctype's shortest alias (like"aes128-cts"). + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.9 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_enctype_to_string.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_enctype_to_string.rst.txt new file mode 100644 index 00000000..d46d83eb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_enctype_to_string.rst.txt @@ -0,0 +1,47 @@ +krb5_enctype_to_string - Convert an encryption type to a string. +================================================================== + +.. + +.. c:function:: krb5_error_code krb5_enctype_to_string(krb5_enctype enctype, char * buffer, size_t buflen) + +.. + + +:param: + + **[in]** **enctype** - Encryption type + + **[out]** **buffer** - Buffer to hold encryption type string + + **[in]** **buflen** - Storage available in *buffer* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_expand_hostname.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_expand_hostname.rst.txt new file mode 100644 index 00000000..0acc9592 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_expand_hostname.rst.txt @@ -0,0 +1,52 @@ +krb5_expand_hostname - Canonicalize a hostname, possibly using name service. +============================================================================== + +.. + +.. c:function:: krb5_error_code krb5_expand_hostname(krb5_context context, const char * host, char ** canonhost_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **host** - Input hostname + + **[out]** **canonhost_out** - Canonicalized hostname + + +.. + + + +.. + + + + + + + +This function canonicalizes orig_hostname, possibly using name service lookups if configuration permits. Use krb5_free_string() to free *canonhost_out* when it is no longer needed. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.15 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_find_authdata.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_find_authdata.rst.txt new file mode 100644 index 00000000..793e6578 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_find_authdata.rst.txt @@ -0,0 +1,56 @@ +krb5_find_authdata - Find authorization data elements. +======================================================== + +.. + +.. c:function:: krb5_error_code krb5_find_authdata(krb5_context context, krb5_authdata *const * ticket_authdata, krb5_authdata *const * ap_req_authdata, krb5_authdatatype ad_type, krb5_authdata *** results) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ticket_authdata** - Authorization data list from ticket + + **[in]** **ap_req_authdata** - Authorization data list from AP request + + **[in]** **ad_type** - Authorization data type to find + + **[out]** **results** - List of matching entries + + +.. + + + +.. + + + + + + + +This function searches *ticket_authdata* and *ap_req_authdata* for elements of type *ad_type* . Either input list may be NULL, in which case it will not be searched; otherwise, the input lists must be terminated by NULL entries. This function will search inside AD-IF-RELEVANT containers if found in either list. Use krb5_free_authdata() to free *results* when it is no longer needed. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.10 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_finish_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_finish_key.rst.txt new file mode 100644 index 00000000..a9f3da59 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_finish_key.rst.txt @@ -0,0 +1,44 @@ +krb5_finish_key +=============== + +.. + +.. c:function:: krb5_error_code krb5_finish_key(krb5_context context, krb5_encrypt_block * eblock) + +.. + + +:param: + + **context** + + **eblock** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_c_* API family. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_finish_random_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_finish_random_key.rst.txt new file mode 100644 index 00000000..26c8b59d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_finish_random_key.rst.txt @@ -0,0 +1,46 @@ +krb5_finish_random_key +====================== + +.. + +.. c:function:: krb5_error_code krb5_finish_random_key(krb5_context context, const krb5_encrypt_block * eblock, krb5_pointer * ptr) + +.. + + +:param: + + **context** + + **eblock** + + **ptr** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_c_* API family. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_addresses.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_addresses.rst.txt new file mode 100644 index 00000000..6717f529 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_addresses.rst.txt @@ -0,0 +1,54 @@ +krb5_free_addresses - Free the data stored in array of addresses. +=================================================================== + +.. + +.. c:function:: void krb5_free_addresses(krb5_context context, krb5_address ** val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Array of addresses to be freed + + +.. + + + +.. + + + + + + + +This function frees the contents of *val* and the array itself. + + + + + + + + + + +.. + + + + + + +.. note:: + + The last entry in the array must be a NULL pointer. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_ap_rep_enc_part.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_ap_rep_enc_part.rst.txt new file mode 100644 index 00000000..33f24e89 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_ap_rep_enc_part.rst.txt @@ -0,0 +1,42 @@ +krb5_free_ap_rep_enc_part - Free a krb5_ap_rep_enc_part structure. +==================================================================== + +.. + +.. c:function:: void krb5_free_ap_rep_enc_part(krb5_context context, krb5_ap_rep_enc_part * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - AP-REP enc part to be freed + + +.. + + + +.. + + + + + + + +This function frees the contents of *val* and the structure itself. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_authdata.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_authdata.rst.txt new file mode 100644 index 00000000..e2b3e90b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_authdata.rst.txt @@ -0,0 +1,54 @@ +krb5_free_authdata - Free the storage assigned to array of authentication data. +================================================================================= + +.. + +.. c:function:: void krb5_free_authdata(krb5_context context, krb5_authdata ** val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Array of authentication data to be freed + + +.. + + + +.. + + + + + + + +This function frees the contents of *val* and the array itself. + + + + + + + + + + +.. + + + + + + +.. note:: + + The last entry in the array must be a NULL pointer. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_authenticator.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_authenticator.rst.txt new file mode 100644 index 00000000..505a508a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_authenticator.rst.txt @@ -0,0 +1,42 @@ +krb5_free_authenticator - Free a krb5_authenticator structure. +================================================================ + +.. + +.. c:function:: void krb5_free_authenticator(krb5_context context, krb5_authenticator * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Authenticator structure to be freed + + +.. + + + +.. + + + + + + + +This function frees the contents of *val* and the structure itself. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_checksum.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_checksum.rst.txt new file mode 100644 index 00000000..7809f6cf --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_checksum.rst.txt @@ -0,0 +1,42 @@ +krb5_free_checksum - Free a krb5_checksum structure. +====================================================== + +.. + +.. c:function:: void krb5_free_checksum(krb5_context context, krb5_checksum * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Checksum structure to be freed + + +.. + + + +.. + + + + + + + +This function frees the contents of *val* and the structure itself. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_checksum_contents.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_checksum_contents.rst.txt new file mode 100644 index 00000000..4ef12c3b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_checksum_contents.rst.txt @@ -0,0 +1,42 @@ +krb5_free_checksum_contents - Free the contents of a krb5_checksum structure. +=============================================================================== + +.. + +.. c:function:: void krb5_free_checksum_contents(krb5_context context, krb5_checksum * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Checksum structure to free contents of + + +.. + + + +.. + + + + + + + +This function frees the contents of *val* , but not the structure itself. It sets the checksum's data pointer to null and (beginning in release 1.19) sets its length to zero. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_cksumtypes.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_cksumtypes.rst.txt new file mode 100644 index 00000000..d4d0d288 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_cksumtypes.rst.txt @@ -0,0 +1,42 @@ +krb5_free_cksumtypes - Free an array of checksum types. +========================================================= + +.. + +.. c:function:: void krb5_free_cksumtypes(krb5_context context, krb5_cksumtype * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Array of checksum types to be freed + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_context.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_context.rst.txt new file mode 100644 index 00000000..d403c21f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_context.rst.txt @@ -0,0 +1,40 @@ +krb5_free_context - Free a krb5 library context. +================================================== + +.. + +.. c:function:: void krb5_free_context(krb5_context context) + +.. + + +:param: + + **[in]** **context** - Library context + + +.. + + + +.. + + + + + + + +This function frees a *context* that was created by krb5_init_context() or krb5_init_secure_context(). + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_cred_contents.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_cred_contents.rst.txt new file mode 100644 index 00000000..cc267880 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_cred_contents.rst.txt @@ -0,0 +1,42 @@ +krb5_free_cred_contents - Free the contents of a krb5_creds structure. +======================================================================== + +.. + +.. c:function:: void krb5_free_cred_contents(krb5_context context, krb5_creds * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Credential structure to free contents of + + +.. + + + +.. + + + + + + + +This function frees the contents of *val* , but not the structure itself. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_creds.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_creds.rst.txt new file mode 100644 index 00000000..c78ecdfc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_creds.rst.txt @@ -0,0 +1,42 @@ +krb5_free_creds - Free a krb5_creds structure. +================================================ + +.. + +.. c:function:: void krb5_free_creds(krb5_context context, krb5_creds * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Credential structure to be freed. + + +.. + + + +.. + + + + + + + +This function frees the contents of *val* and the structure itself. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_data.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_data.rst.txt new file mode 100644 index 00000000..8cd23a50 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_data.rst.txt @@ -0,0 +1,42 @@ +krb5_free_data - Free a krb5_data structure. +============================================== + +.. + +.. c:function:: void krb5_free_data(krb5_context context, krb5_data * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Data structure to be freed + + +.. + + + +.. + + + + + + + +This function frees the contents of *val* and the structure itself. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_data_contents.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_data_contents.rst.txt new file mode 100644 index 00000000..c64ded12 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_data_contents.rst.txt @@ -0,0 +1,42 @@ +krb5_free_data_contents - Free the contents of a krb5_data structure and zero the data field. +=============================================================================================== + +.. + +.. c:function:: void krb5_free_data_contents(krb5_context context, krb5_data * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Data structure to free contents of + + +.. + + + +.. + + + + + + + +This function frees the contents of *val* , but not the structure itself. It sets the structure's data pointer to null and (beginning in release 1.19) sets its length to zero. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_default_realm.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_default_realm.rst.txt new file mode 100644 index 00000000..a0a3babf --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_default_realm.rst.txt @@ -0,0 +1,42 @@ +krb5_free_default_realm - Free a default realm string returned by krb5_get_default_realm(). +============================================================================================= + +.. + +.. c:function:: void krb5_free_default_realm(krb5_context context, char * lrealm) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **lrealm** - Realm to be freed + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_enctypes.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_enctypes.rst.txt new file mode 100644 index 00000000..e1189cb0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_enctypes.rst.txt @@ -0,0 +1,46 @@ +krb5_free_enctypes - Free an array of encryption types. +========================================================= + +.. + +.. c:function:: void krb5_free_enctypes(krb5_context context, krb5_enctype * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Array of enctypes to be freed + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.12 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_error.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_error.rst.txt new file mode 100644 index 00000000..e31daf09 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_error.rst.txt @@ -0,0 +1,42 @@ +krb5_free_error - Free an error allocated by krb5_read_error() or krb5_sendauth(). +==================================================================================== + +.. + +.. c:function:: void krb5_free_error(krb5_context context, krb5_error * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Error data structure to be freed + + +.. + + + +.. + + + + + + + +This function frees the contents of *val* and the structure itself. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_error_message.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_error_message.rst.txt new file mode 100644 index 00000000..923647af --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_error_message.rst.txt @@ -0,0 +1,42 @@ +krb5_free_error_message - Free an error message generated by krb5_get_error_message(). +======================================================================================== + +.. + +.. c:function:: void krb5_free_error_message(krb5_context ctx, const char * msg) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **msg** - Pointer to error message + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_host_realm.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_host_realm.rst.txt new file mode 100644 index 00000000..1a733b12 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_host_realm.rst.txt @@ -0,0 +1,48 @@ +krb5_free_host_realm - Free the memory allocated by krb5_get_host_realm(). +============================================================================ + +.. + +.. c:function:: krb5_error_code krb5_free_host_realm(krb5_context context, char *const * realmlist) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **realmlist** - List of realm names to be released + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_keyblock.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_keyblock.rst.txt new file mode 100644 index 00000000..ec58604c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_keyblock.rst.txt @@ -0,0 +1,42 @@ +krb5_free_keyblock - Free a krb5_keyblock structure. +====================================================== + +.. + +.. c:function:: void krb5_free_keyblock(krb5_context context, krb5_keyblock * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Keyblock to be freed + + +.. + + + +.. + + + + + + + +This function frees the contents of *val* and the structure itself. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_keyblock_contents.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_keyblock_contents.rst.txt new file mode 100644 index 00000000..264444e7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_keyblock_contents.rst.txt @@ -0,0 +1,42 @@ +krb5_free_keyblock_contents - Free the contents of a krb5_keyblock structure. +=============================================================================== + +.. + +.. c:function:: void krb5_free_keyblock_contents(krb5_context context, krb5_keyblock * key) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Keyblock to be freed + + +.. + + + +.. + + + + + + + +This function frees the contents of *key* , but not the structure itself. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_keytab_entry_contents.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_keytab_entry_contents.rst.txt new file mode 100644 index 00000000..adecfe2f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_keytab_entry_contents.rst.txt @@ -0,0 +1,53 @@ +krb5_free_keytab_entry_contents - Free the contents of a key table entry. +=========================================================================== + +.. + +.. c:function:: krb5_error_code krb5_free_keytab_entry_contents(krb5_context context, krb5_keytab_entry * entry) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **entry** - Key table entry whose contents are to be freed + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + + +.. note:: + + The pointer is not freed. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_principal.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_principal.rst.txt new file mode 100644 index 00000000..218369af --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_principal.rst.txt @@ -0,0 +1,42 @@ +krb5_free_principal - Free the storage assigned to a principal. +================================================================= + +.. + +.. c:function:: void krb5_free_principal(krb5_context context, krb5_principal val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Principal to be freed + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_string.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_string.rst.txt new file mode 100644 index 00000000..4c7bcac3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_string.rst.txt @@ -0,0 +1,46 @@ +krb5_free_string - Free a string allocated by a krb5 function. +================================================================ + +.. + +.. c:function:: void krb5_free_string(krb5_context context, char * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - String to be freed + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.10 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_tgt_creds.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_tgt_creds.rst.txt new file mode 100644 index 00000000..f885fc0c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_tgt_creds.rst.txt @@ -0,0 +1,50 @@ +krb5_free_tgt_creds - Free an array of credential structures. +=============================================================== + +.. + +.. c:function:: void krb5_free_tgt_creds(krb5_context context, krb5_creds ** tgts) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **tgts** - Null-terminated array of credentials to free + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + + +.. note:: + + The last entry in the array *tgts* must be a NULL pointer. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_ticket.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_ticket.rst.txt new file mode 100644 index 00000000..f523917c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_ticket.rst.txt @@ -0,0 +1,42 @@ +krb5_free_ticket - Free a ticket. +=================================== + +.. + +.. c:function:: void krb5_free_ticket(krb5_context context, krb5_ticket * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Ticket to be freed + + +.. + + + +.. + + + + + + + +This function frees the contents of *val* and the structure itself. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_unparsed_name.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_unparsed_name.rst.txt new file mode 100644 index 00000000..b6f9e162 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_free_unparsed_name.rst.txt @@ -0,0 +1,42 @@ +krb5_free_unparsed_name - Free a string representation of a principal. +======================================================================== + +.. + +.. c:function:: void krb5_free_unparsed_name(krb5_context context, char * val) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **val** - Name string to be freed + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_fwd_tgt_creds.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_fwd_tgt_creds.rst.txt new file mode 100644 index 00000000..bfda237f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_fwd_tgt_creds.rst.txt @@ -0,0 +1,68 @@ +krb5_fwd_tgt_creds - Get a forwarded TGT and format a KRB-CRED message. +========================================================================= + +.. + +.. c:function:: krb5_error_code krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, const char * rhost, krb5_principal client, krb5_principal server, krb5_ccache cc, int forwardable, krb5_data * outbuf) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **rhost** - Remote host + + **[in]** **client** - Client principal of TGT + + **[in]** **server** - Principal of server to receive TGT + + **[in]** **cc** - Credential cache handle (NULL to use default) + + **[in]** **forwardable** - Whether TGT should be forwardable + + **[out]** **outbuf** - KRB-CRED message + + +.. + + +:retval: + - 0 Success + - ENOMEM Insufficient memory + - KRB5_PRINC_NOMATCH Requested principal and ticket do not match + - KRB5_NO_TKT_SUPPLIED Request did not supply a ticket + - KRB5_CC_BADNAME Credential cache name or principal name malformed + + +:return: + - Kerberos error codes + +.. + + + + + + + +Get a TGT for use at the remote host *rhost* and format it into a KRB-CRED message. If *rhost* is NULL and *server* is of type #KRB5_NT_SRV_HST, the second component of *server* will be used. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_credentials.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_credentials.rst.txt new file mode 100644 index 00000000..7a72b39a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_credentials.rst.txt @@ -0,0 +1,81 @@ +krb5_get_credentials - Get an additional ticket. +================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_credentials(krb5_context context, krb5_flags options, krb5_ccache ccache, krb5_creds * in_creds, krb5_creds ** out_creds) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **options** - Options + + **[in]** **ccache** - Credential cache handle + + **[in]** **in_creds** - Input credentials + + **[out]** **out_creds** - Output updated credentials + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Use *ccache* or a TGS exchange to get a service ticket matching *in_creds* . + + + +Valid values for *options* are: + + - #KRB5_GC_CACHED Search only credential cache for the ticket + + + - #KRB5_GC_USER_USER Return a user to user authentication ticket + + *in_creds* must be non-null. *in_creds->client* and *in_creds->server* must be filled in to specify the client and the server respectively. If any authorization data needs to be requested for the service ticket (such as restrictions on how the ticket can be used), specify it in *in_creds->authdata* ; otherwise set *in_creds->authdata* to NULL. The session key type is specified in *in_creds->keyblock.enctype* , if it is nonzero. + + + +The expiration date is specified in *in_creds->times.endtime* . The KDC may return tickets with an earlier expiration date. If *in_creds->times.endtime* is set to 0, the latest possible expiration date will be requested. + + + +Any returned ticket and intermediate ticket-granting tickets are stored in *ccache* . + + + +Use krb5_free_creds() to free *out_creds* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_credentials_renew.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_credentials_renew.rst.txt new file mode 100644 index 00000000..75aac540 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_credentials_renew.rst.txt @@ -0,0 +1,50 @@ +krb5_get_credentials_renew +========================== + +.. + +.. c:function:: krb5_error_code krb5_get_credentials_renew(krb5_context context, krb5_flags options, krb5_ccache ccache, krb5_creds * in_creds, krb5_creds ** out_creds) + +.. + + +:param: + + **context** + + **options** + + **ccache** + + **in_creds** + + **out_creds** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_get_renewed_creds. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_credentials_validate.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_credentials_validate.rst.txt new file mode 100644 index 00000000..29033b9d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_credentials_validate.rst.txt @@ -0,0 +1,50 @@ +krb5_get_credentials_validate +============================= + +.. + +.. c:function:: krb5_error_code krb5_get_credentials_validate(krb5_context context, krb5_flags options, krb5_ccache ccache, krb5_creds * in_creds, krb5_creds ** out_creds) + +.. + + +:param: + + **context** + + **options** + + **ccache** + + **in_creds** + + **out_creds** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_get_validated_creds. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_default_realm.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_default_realm.rst.txt new file mode 100644 index 00000000..093bfa9e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_default_realm.rst.txt @@ -0,0 +1,56 @@ +krb5_get_default_realm - Retrieve the default realm. +====================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_default_realm(krb5_context context, char ** lrealm) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **lrealm** - Default realm name + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Retrieves the default realm to be used if no user-specified realm is available. + + + +Use krb5_free_default_realm() to free *lrealm* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_error_message.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_error_message.rst.txt new file mode 100644 index 00000000..16bac2f2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_error_message.rst.txt @@ -0,0 +1,62 @@ +krb5_get_error_message - Get the (possibly extended) error message for a code. +================================================================================ + +.. + +.. c:function:: const char * krb5_get_error_message(krb5_context ctx, krb5_error_code code) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **code** - Error code + + +.. + + + +.. + + + + + + + +The behavior of krb5_get_error_message() is only defined the first time it is called after a failed call to a krb5 function using the same context, and only when the error code passed in is the same as that returned by the krb5 function. + + + +This function never returns NULL, so its result may be used unconditionally as a C string. + + + +The string returned by this function must be freed using krb5_free_error_message() + + + + + + + + + + +.. + + + + + + +.. note:: + + Future versions may return the same string for the second and following calls. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_etype_info.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_etype_info.rst.txt new file mode 100644 index 00000000..63425f56 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_etype_info.rst.txt @@ -0,0 +1,72 @@ +krb5_get_etype_info - Retrieve enctype, salt and s2kparams from KDC. +====================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_etype_info(krb5_context context, krb5_principal principal, krb5_get_init_creds_opt * opt, krb5_enctype * enctype_out, krb5_data * salt_out, krb5_data * s2kparams_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **principal** - Principal whose information is requested + + **[in]** **opt** - Initial credential options + + **[out]** **enctype_out** - The enctype chosen by KDC + + **[out]** **salt_out** - Salt returned from KDC + + **[out]** **s2kparams_out** - String-to-key parameters returned from KDC + + +.. + + +:retval: + - 0 Success + + +:return: + - A Kerberos error code + +.. + + + + + + + +Send an initial ticket request for *principal* and extract the encryption type, salt type, and string-to-key parameters from the KDC response. If the KDC provides no etype-info, set *enctype_out* to **ENCTYPE_NULL** and set *salt_out* and *s2kparams_out* to empty. If the KDC etype-info provides no salt, compute the default salt and place it in *salt_out* . If the KDC etype-info provides no string-to-key parameters, set *s2kparams_out* to empty. + + + + *opt* may be used to specify options which affect the initial request, such as request encryption types or a FAST armor cache (see krb5_get_init_creds_opt_set_etype_list() and krb5_get_init_creds_opt_set_fast_ccache_name()). + + + +Use krb5_free_data_contents() to free *salt_out* and *s2kparams_out* when they are no longer needed. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.17 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_fallback_host_realm.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_fallback_host_realm.rst.txt new file mode 100644 index 00000000..0a7d1a3c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_fallback_host_realm.rst.txt @@ -0,0 +1,52 @@ +krb5_get_fallback_host_realm +============================ + +.. + +.. c:function:: krb5_error_code krb5_get_fallback_host_realm(krb5_context context, krb5_data * hdata, char *** realmsp) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **hdata** - Host name (or NULL) + + **[out]** **realmsp** - Null-terminated list of realm names + + +.. + + + +.. + + + + + + + +Fill in *realmsp* with a pointer to a null-terminated list of realm names obtained through heuristics or insecure resolution methods which have lower priority than KDC referrals. + + + +If *host* is NULL, the local host's realms are determined. + + + +Use krb5_free_host_realm() to release *realmsp* when it is no longer needed. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_host_realm.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_host_realm.rst.txt new file mode 100644 index 00000000..32ceb2ad --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_host_realm.rst.txt @@ -0,0 +1,63 @@ +krb5_get_host_realm - Get the Kerberos realm names for a host. +================================================================ + +.. + +.. c:function:: krb5_error_code krb5_get_host_realm(krb5_context context, const char * host, char *** realmsp) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **host** - Host name (or NULL) + + **[out]** **realmsp** - Null-terminated list of realm names + + +.. + + +:retval: + - 0 Success + - ENOMEM Insufficient memory + + +:return: + - Kerberos error codes + +.. + + + + + + + +Fill in *realmsp* with a pointer to a null-terminated list of realm names. If there are no known realms for the host, a list containing the referral (empty) realm is returned. + + + +If *host* is NULL, the local host's realms are determined. + + + +Use krb5_free_host_realm() to release *realmsp* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_in_tkt_with_keytab.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_in_tkt_with_keytab.rst.txt new file mode 100644 index 00000000..23a25153 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_in_tkt_with_keytab.rst.txt @@ -0,0 +1,58 @@ +krb5_get_in_tkt_with_keytab +=========================== + +.. + +.. c:function:: krb5_error_code krb5_get_in_tkt_with_keytab(krb5_context context, krb5_flags options, krb5_address *const * addrs, krb5_enctype * ktypes, krb5_preauthtype * pre_auth_types, krb5_keytab arg_keytab, krb5_ccache ccache, krb5_creds * creds, krb5_kdc_rep ** ret_as_reply) + +.. + + +:param: + + **context** + + **options** + + **addrs** + + **ktypes** + + **pre_auth_types** + + **arg_keytab** + + **ccache** + + **creds** + + **ret_as_reply** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_get_init_creds_keytab(). + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_in_tkt_with_password.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_in_tkt_with_password.rst.txt new file mode 100644 index 00000000..c0782f8b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_in_tkt_with_password.rst.txt @@ -0,0 +1,58 @@ +krb5_get_in_tkt_with_password +============================= + +.. + +.. c:function:: krb5_error_code krb5_get_in_tkt_with_password(krb5_context context, krb5_flags options, krb5_address *const * addrs, krb5_enctype * ktypes, krb5_preauthtype * pre_auth_types, const char * password, krb5_ccache ccache, krb5_creds * creds, krb5_kdc_rep ** ret_as_reply) + +.. + + +:param: + + **context** + + **options** + + **addrs** + + **ktypes** + + **pre_auth_types** + + **password** + + **ccache** + + **creds** + + **ret_as_reply** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_get_init_creds_password(). + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_in_tkt_with_skey.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_in_tkt_with_skey.rst.txt new file mode 100644 index 00000000..fed7f0b4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_in_tkt_with_skey.rst.txt @@ -0,0 +1,58 @@ +krb5_get_in_tkt_with_skey +========================= + +.. + +.. c:function:: krb5_error_code krb5_get_in_tkt_with_skey(krb5_context context, krb5_flags options, krb5_address *const * addrs, krb5_enctype * ktypes, krb5_preauthtype * pre_auth_types, const krb5_keyblock * key, krb5_ccache ccache, krb5_creds * creds, krb5_kdc_rep ** ret_as_reply) + +.. + + +:param: + + **context** + + **options** + + **addrs** + + **ktypes** + + **pre_auth_types** + + **key** + + **ccache** + + **creds** + + **ret_as_reply** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_get_init_creds(). + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_keytab.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_keytab.rst.txt new file mode 100644 index 00000000..32ce5cb6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_keytab.rst.txt @@ -0,0 +1,62 @@ +krb5_get_init_creds_keytab - Get initial credentials using a key table. +========================================================================= + +.. + +.. c:function:: krb5_error_code krb5_get_init_creds_keytab(krb5_context context, krb5_creds * creds, krb5_principal client, krb5_keytab arg_keytab, krb5_deltat start_time, const char * in_tkt_service, krb5_get_init_creds_opt * k5_gic_options) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **creds** - New credentials + + **[in]** **client** - Client principal + + **[in]** **arg_keytab** - Key table handle + + **[in]** **start_time** - Time when ticket becomes valid (0 for now) + + **[in]** **in_tkt_service** - Service name of initial credentials (or NULL) + + **[in]** **k5_gic_options** - Initial credential options + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function requests KDC for an initial credentials for *client* using a client key stored in *arg_keytab* . If *in_tkt_service* is specified, it is parsed as a principal name (with the realm ignored) and used as the service principal for the request; otherwise the ticket-granting service is used. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_alloc.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_alloc.rst.txt new file mode 100644 index 00000000..b8826089 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_alloc.rst.txt @@ -0,0 +1,49 @@ +krb5_get_init_creds_opt_alloc - Allocate a new initial credential options structure. +====================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_init_creds_opt_alloc(krb5_context context, krb5_get_init_creds_opt ** opt) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **opt** - New options structure + + +.. + + +:retval: + - 0 - Success; Kerberos errors otherwise. + + +.. + + + + + + + +This function is the preferred way to create an options structure for getting initial credentials, and is required to make use of certain options. Use krb5_get_init_creds_opt_free() to free *opt* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_free.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_free.rst.txt new file mode 100644 index 00000000..94ddbf6b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_free.rst.txt @@ -0,0 +1,45 @@ +krb5_get_init_creds_opt_free - Free initial credential options. +================================================================= + +.. + +.. c:function:: void krb5_get_init_creds_opt_free(krb5_context context, krb5_get_init_creds_opt * opt) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **opt** - Options structure to free + + +.. + + + +.. + + + + + + + + + + + + + + +.. + +.. seealso:: + krb5_get_init_creds_opt_alloc() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_get_fast_flags.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_get_fast_flags.rst.txt new file mode 100644 index 00000000..b38ddacf --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_get_fast_flags.rst.txt @@ -0,0 +1,47 @@ +krb5_get_init_creds_opt_get_fast_flags - Retrieve FAST flags from initial credential options. +=============================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_init_creds_opt_get_fast_flags(krb5_context context, krb5_get_init_creds_opt * opt, krb5_flags * out_flags) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **opt** - Options + + **[out]** **out_flags** - FAST flags + + +.. + + +:retval: + - 0 - Success; Kerberos errors otherwise. + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_init.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_init.rst.txt new file mode 100644 index 00000000..1cbaa9ab --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_init.rst.txt @@ -0,0 +1,42 @@ +krb5_get_init_creds_opt_init +============================ + +.. + +.. c:function:: void krb5_get_init_creds_opt_init(krb5_get_init_creds_opt * opt) + +.. + + +:param: + + **opt** + + +.. + + + +.. + + +DEPRECATED Use krb5_get_init_creds_opt_alloc() instead. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_address_list.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_address_list.rst.txt new file mode 100644 index 00000000..e460a46e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_address_list.rst.txt @@ -0,0 +1,42 @@ +krb5_get_init_creds_opt_set_address_list - Set address restrictions in initial credential options. +==================================================================================================== + +.. + +.. c:function:: void krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt * opt, krb5_address ** addresses) + +.. + + +:param: + + **[in]** **opt** - Options structure + + **[in]** **addresses** - Null-terminated array of addresses + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_anonymous.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_anonymous.rst.txt new file mode 100644 index 00000000..6953b2c5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_anonymous.rst.txt @@ -0,0 +1,42 @@ +krb5_get_init_creds_opt_set_anonymous - Set or unset the anonymous flag in initial credential options. +======================================================================================================== + +.. + +.. c:function:: void krb5_get_init_creds_opt_set_anonymous(krb5_get_init_creds_opt * opt, int anonymous) + +.. + + +:param: + + **[in]** **opt** - Options structure + + **[in]** **anonymous** - Whether to make an anonymous request + + +.. + + + +.. + + + + + + + +This function may be used to request anonymous credentials from the KDC by setting *anonymous* to non-zero. Note that anonymous credentials are only a request; clients must verify that credentials are anonymous if that is a requirement. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_canonicalize.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_canonicalize.rst.txt new file mode 100644 index 00000000..099644fe --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_canonicalize.rst.txt @@ -0,0 +1,42 @@ +krb5_get_init_creds_opt_set_canonicalize - Set or unset the canonicalize flag in initial credential options. +============================================================================================================== + +.. + +.. c:function:: void krb5_get_init_creds_opt_set_canonicalize(krb5_get_init_creds_opt * opt, int canonicalize) + +.. + + +:param: + + **[in]** **opt** - Options structure + + **[in]** **canonicalize** - Whether to canonicalize client principal + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_change_password_prompt.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_change_password_prompt.rst.txt new file mode 100644 index 00000000..f8859329 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_change_password_prompt.rst.txt @@ -0,0 +1,42 @@ +krb5_get_init_creds_opt_set_change_password_prompt - Set or unset change-password-prompt flag in initial credential options. +============================================================================================================================== + +.. + +.. c:function:: void krb5_get_init_creds_opt_set_change_password_prompt(krb5_get_init_creds_opt * opt, int prompt) + +.. + + +:param: + + **[in]** **opt** - Options structure + + **[in]** **prompt** - Whether to prompt to change password + + +.. + + + +.. + + + + + + + +This flag is on by default. It controls whether krb5_get_init_creds_password() will react to an expired-password error by prompting for a new password and attempting to change the old one. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_etype_list.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_etype_list.rst.txt new file mode 100644 index 00000000..ac6f8ab6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_etype_list.rst.txt @@ -0,0 +1,44 @@ +krb5_get_init_creds_opt_set_etype_list - Set allowable encryption types in initial credential options. +======================================================================================================== + +.. + +.. c:function:: void krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt * opt, krb5_enctype * etype_list, int etype_list_length) + +.. + + +:param: + + **[in]** **opt** - Options structure + + **[in]** **etype_list** - Array of encryption types + + **[in]** **etype_list_length** - Length of *etype_list* + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_expire_callback.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_expire_callback.rst.txt new file mode 100644 index 00000000..6715de3e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_expire_callback.rst.txt @@ -0,0 +1,78 @@ +krb5_get_init_creds_opt_set_expire_callback - Set an expiration callback in initial credential options. +========================================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_get_init_creds_opt_set_expire_callback(krb5_context context, krb5_get_init_creds_opt * opt, krb5_expire_callback_func cb, void * data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **opt** - Options structure + + **[in]** **cb** - Callback function + + **[in]** **data** - Callback argument + + +.. + + + +.. + + + + + + + +Set a callback to receive password and account expiration times. + + + + *cb* will be invoked if and only if credentials are successfully acquired. The callback will receive the *context* from the calling function and the *data* argument supplied with this API. The remaining arguments should be interpreted as follows: + + + +If *is_last_req* is true, then the KDC reply contained last-req entries which unambiguously indicated the password expiration, account expiration, or both. (If either value was not present, the corresponding argument will be 0.) Furthermore, a non-zero *password_expiration* should be taken as a suggestion from the KDC that a warning be displayed. + + + +If *is_last_req* is false, then *account_expiration* will be 0 and *password_expiration* will contain the expiration time of either the password or account, or 0 if no expiration time was indicated in the KDC reply. The callback should independently decide whether to display a password expiration warning. + + + +Note that *cb* may be invoked even if credentials are being acquired for the kadmin/changepw service in order to change the password. It is the caller's responsibility to avoid displaying a password expiry warning in this case. + + + + + + + + + + +.. + + + + + +.. warning:: + + Setting an expire callback with this API will cause krb5_get_init_creds_password() not to send password expiry warnings to the prompter, as it ordinarily may. + + + + +.. note:: + + New in 1.9 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache.rst.txt new file mode 100644 index 00000000..0124a3c0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache.rst.txt @@ -0,0 +1,52 @@ +krb5_get_init_creds_opt_set_fast_ccache - Set FAST armor cache in initial credential options. +=============================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_init_creds_opt_set_fast_ccache(krb5_context context, krb5_get_init_creds_opt * opt, krb5_ccache ccache) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **opt** - Options + + **[in]** **ccache** - Credential cache handle + + +.. + + + +.. + + + + + + + +This function is similar to krb5_get_init_creds_opt_set_fast_ccache_name(), but uses a credential cache handle instead of a name. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.9 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache_name.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache_name.rst.txt new file mode 100644 index 00000000..b7d7710d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache_name.rst.txt @@ -0,0 +1,48 @@ +krb5_get_init_creds_opt_set_fast_ccache_name - Set location of FAST armor ccache in initial credential options. +================================================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_get_init_creds_opt_set_fast_ccache_name(krb5_context context, krb5_get_init_creds_opt * opt, const char * fast_ccache_name) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **opt** - Options + + **[in]** **fast_ccache_name** - Credential cache name + + +.. + + + +.. + + + + + + + +Sets the location of a credential cache containing an armor ticket to protect an initial credential exchange using the FAST protocol extension. + + + +In version 1.7, setting an armor ccache requires that FAST be used for the exchange. In version 1.8 or later, setting the armor ccache causes FAST to be used if the KDC supports it; krb5_get_init_creds_opt_set_fast_flags() must be used to require that FAST be used. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_fast_flags.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_fast_flags.rst.txt new file mode 100644 index 00000000..77e9fa04 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_fast_flags.rst.txt @@ -0,0 +1,51 @@ +krb5_get_init_creds_opt_set_fast_flags - Set FAST flags in initial credential options. +======================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_init_creds_opt_set_fast_flags(krb5_context context, krb5_get_init_creds_opt * opt, krb5_flags flags) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **opt** - Options + + **[in]** **flags** - FAST flags + + +.. + + +:retval: + - 0 - Success; Kerberos errors otherwise. + + +.. + + + + + + + +The following flag values are valid: + + - #KRB5_FAST_REQUIRED - Require FAST to be used + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_forwardable.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_forwardable.rst.txt new file mode 100644 index 00000000..50d64b8c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_forwardable.rst.txt @@ -0,0 +1,42 @@ +krb5_get_init_creds_opt_set_forwardable - Set or unset the forwardable flag in initial credential options. +============================================================================================================ + +.. + +.. c:function:: void krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt * opt, int forwardable) + +.. + + +:param: + + **[in]** **opt** - Options structure + + **[in]** **forwardable** - Whether credentials should be forwardable + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_in_ccache.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_in_ccache.rst.txt new file mode 100644 index 00000000..41d51176 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_in_ccache.rst.txt @@ -0,0 +1,52 @@ +krb5_get_init_creds_opt_set_in_ccache - Set an input credential cache in initial credential options. +====================================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_init_creds_opt_set_in_ccache(krb5_context context, krb5_get_init_creds_opt * opt, krb5_ccache ccache) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **opt** - Options + + **[in]** **ccache** - Credential cache handle + + +.. + + + +.. + + + + + + + +If an input credential cache is set, then the krb5_get_init_creds family of APIs will read settings from it. Setting an input ccache is desirable when the application wishes to perform authentication in the same way (using the same preauthentication mechanisms, and making the same non-security- sensitive choices) as the previous authentication attempt, which stored information in the passed-in ccache. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.11 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_out_ccache.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_out_ccache.rst.txt new file mode 100644 index 00000000..dcb1cf60 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_out_ccache.rst.txt @@ -0,0 +1,44 @@ +krb5_get_init_creds_opt_set_out_ccache - Set an output credential cache in initial credential options. +======================================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_init_creds_opt_set_out_ccache(krb5_context context, krb5_get_init_creds_opt * opt, krb5_ccache ccache) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **opt** - Options + + **[in]** **ccache** - Credential cache handle + + +.. + + + +.. + + + + + + + +If an output credential cache is set, then the krb5_get_init_creds family of APIs will write credentials to it. Setting an output ccache is desirable both because it simplifies calling code and because it permits the krb5_get_init_creds APIs to write out configuration information about the realm to the ccache. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_pa.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_pa.rst.txt new file mode 100644 index 00000000..a610fa0c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_pa.rst.txt @@ -0,0 +1,46 @@ +krb5_get_init_creds_opt_set_pa - Supply options for preauthentication in initial credential options. +====================================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_init_creds_opt_set_pa(krb5_context context, krb5_get_init_creds_opt * opt, const char * attr, const char * value) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **opt** - Options structure + + **[in]** **attr** - Preauthentication option name + + **[in]** **value** - Preauthentication option value + + +.. + + + +.. + + + + + + + +This function allows the caller to supply options for preauthentication. The values of *attr* and *value* are supplied to each preauthentication module available within *context* . + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_pac_request.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_pac_request.rst.txt new file mode 100644 index 00000000..ed46081b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_pac_request.rst.txt @@ -0,0 +1,52 @@ +krb5_get_init_creds_opt_set_pac_request - Ask the KDC to include or not include a PAC in the ticket. +====================================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_init_creds_opt_set_pac_request(krb5_context context, krb5_get_init_creds_opt * opt, krb5_boolean req_pac) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **opt** - Options structure + + **[in]** **req_pac** - Whether to request a PAC or not + + +.. + + + +.. + + + + + + + +If this option is set, the AS request will include a PAC-REQUEST pa-data item explicitly asking the KDC to either include or not include a privilege attribute certificate in the ticket authorization data. By default, no request is made; typically the KDC will default to including a PAC if it supports them. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.15 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_preauth_list.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_preauth_list.rst.txt new file mode 100644 index 00000000..1e7b647f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_preauth_list.rst.txt @@ -0,0 +1,44 @@ +krb5_get_init_creds_opt_set_preauth_list - Set preauthentication types in initial credential options. +======================================================================================================= + +.. + +.. c:function:: void krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt * opt, krb5_preauthtype * preauth_list, int preauth_list_length) + +.. + + +:param: + + **[in]** **opt** - Options structure + + **[in]** **preauth_list** - Array of preauthentication types + + **[in]** **preauth_list_length** - Length of *preauth_list* + + +.. + + + +.. + + + + + + + +This function can be used to perform optimistic preauthentication when getting initial credentials, in combination with krb5_get_init_creds_opt_set_salt() and krb5_get_init_creds_opt_set_pa(). + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_proxiable.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_proxiable.rst.txt new file mode 100644 index 00000000..7ced7273 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_proxiable.rst.txt @@ -0,0 +1,42 @@ +krb5_get_init_creds_opt_set_proxiable - Set or unset the proxiable flag in initial credential options. +======================================================================================================== + +.. + +.. c:function:: void krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt * opt, int proxiable) + +.. + + +:param: + + **[in]** **opt** - Options structure + + **[in]** **proxiable** - Whether credentials should be proxiable + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_renew_life.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_renew_life.rst.txt new file mode 100644 index 00000000..58e938d9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_renew_life.rst.txt @@ -0,0 +1,42 @@ +krb5_get_init_creds_opt_set_renew_life - Set the ticket renewal lifetime in initial credential options. +========================================================================================================= + +.. + +.. c:function:: void krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt * opt, krb5_deltat renew_life) + +.. + + +:param: + + **[in]** **opt** - Pointer to *options* field + + **[in]** **renew_life** - Ticket renewal lifetime + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_responder.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_responder.rst.txt new file mode 100644 index 00000000..220ba403 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_responder.rst.txt @@ -0,0 +1,50 @@ +krb5_get_init_creds_opt_set_responder - Set the responder function in initial credential options. +=================================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_init_creds_opt_set_responder(krb5_context context, krb5_get_init_creds_opt * opt, krb5_responder_fn responder, void * data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **opt** - Options structure + + **[in]** **responder** - Responder function + + **[in]** **data** - Responder data argument + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.11 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_salt.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_salt.rst.txt new file mode 100644 index 00000000..22512f67 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_salt.rst.txt @@ -0,0 +1,42 @@ +krb5_get_init_creds_opt_set_salt - Set salt for optimistic preauthentication in initial credential options. +============================================================================================================= + +.. + +.. c:function:: void krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt * opt, krb5_data * salt) + +.. + + +:param: + + **[in]** **opt** - Options structure + + **[in]** **salt** - Salt data + + +.. + + + +.. + + + + + + + +When getting initial credentials with a password, a salt string it used to convert the password to a key. Normally this salt is obtained from the first KDC reply, but when performing optimistic preauthentication, the client may need to supply the salt string with this function. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_tkt_life.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_tkt_life.rst.txt new file mode 100644 index 00000000..a5c1f685 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_opt_set_tkt_life.rst.txt @@ -0,0 +1,42 @@ +krb5_get_init_creds_opt_set_tkt_life - Set the ticket lifetime in initial credential options. +=============================================================================================== + +.. + +.. c:function:: void krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt * opt, krb5_deltat tkt_life) + +.. + + +:param: + + **[in]** **opt** - Options structure + + **[in]** **tkt_life** - Ticket lifetime + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_password.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_password.rst.txt new file mode 100644 index 00000000..1c6fd685 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_init_creds_password.rst.txt @@ -0,0 +1,75 @@ +krb5_get_init_creds_password - Get initial credentials using a password. +========================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_init_creds_password(krb5_context context, krb5_creds * creds, krb5_principal client, const char * password, krb5_prompter_fct prompter, void * data, krb5_deltat start_time, const char * in_tkt_service, krb5_get_init_creds_opt * k5_gic_options) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **creds** - New credentials + + **[in]** **client** - Client principal + + **[in]** **password** - Password (or NULL) + + **[in]** **prompter** - Prompter function + + **[in]** **data** - Prompter callback data + + **[in]** **start_time** - Time when ticket becomes valid (0 for now) + + **[in]** **in_tkt_service** - Service name of initial credentials (or NULL) + + **[in]** **k5_gic_options** - Initial credential options + + +.. + + +:retval: + - 0 Success + - EINVAL Invalid argument + - KRB5_KDC_UNREACH Cannot contact any KDC for requested realm + - KRB5_PREAUTH_FAILED Generic Pre-athentication failure + - KRB5_LIBOS_PWDINTR Password read interrupted + - KRB5_REALM_CANT_RESOLVE Cannot resolve network address for KDC in requested realm + - KRB5KDC_ERR_KEY_EXP Password has expired + - KRB5_LIBOS_BADPWDMATCH Password mismatch + - KRB5_CHPW_PWDNULL New password cannot be zero length + - KRB5_CHPW_FAIL Password change failed + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function requests KDC for an initial credentials for *client* using *password* . If *password* is NULL, a password will be prompted for using *prompter* if necessary. If *in_tkt_service* is specified, it is parsed as a principal name (with the realm ignored) and used as the service principal for the request; otherwise the ticket-granting service is used. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_permitted_enctypes.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_permitted_enctypes.rst.txt new file mode 100644 index 00000000..a5776405 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_permitted_enctypes.rst.txt @@ -0,0 +1,53 @@ +krb5_get_permitted_enctypes - Return a list of encryption types permitted for session keys. +============================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_get_permitted_enctypes(krb5_context context, krb5_enctype ** ktypes) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **ktypes** - Zero-terminated list of encryption types + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function returns the list of encryption types permitted for session keys within *context* , as determined by configuration or by a previous call to krb5_set_default_tgs_enctypes(). + + + +Use krb5_free_enctypes() to free *ktypes* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_profile.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_profile.rst.txt new file mode 100644 index 00000000..4ef2949a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_profile.rst.txt @@ -0,0 +1,56 @@ +krb5_get_profile - Retrieve configuration profile from the context. +===================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_profile(krb5_context context, struct _profile_t ** profile) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **profile** - Pointer to data read from a configuration file + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function creates a new *profile* object that reflects profile in the supplied *context* . + + + +The *profile* object may be freed with profile_release() function. See profile.h and profile API for more details. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_prompt_types.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_prompt_types.rst.txt new file mode 100644 index 00000000..4cf9748c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_prompt_types.rst.txt @@ -0,0 +1,43 @@ +krb5_get_prompt_types - Get prompt types array from a context. +================================================================ + +.. + +.. c:function:: krb5_prompt_type * krb5_get_prompt_types(krb5_context context) + +.. + + +:param: + + **[in]** **context** - Library context + + +.. + + + +:return: + - Pointer to an array of prompt types corresponding to the prompter's prompts arguments. Each type has one of the following values: #KRB5_PROMPT_TYPE_PASSWORD #KRB5_PROMPT_TYPE_NEW_PASSWORD #KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN #KRB5_PROMPT_TYPE_PREAUTH + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_renewed_creds.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_renewed_creds.rst.txt new file mode 100644 index 00000000..21458f85 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_renewed_creds.rst.txt @@ -0,0 +1,62 @@ +krb5_get_renewed_creds - Get renewed credential from KDC using an existing credential. +======================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_renewed_creds(krb5_context context, krb5_creds * creds, krb5_principal client, krb5_ccache ccache, const char * in_tkt_service) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **creds** - Renewed credentials + + **[in]** **client** - Client principal name + + **[in]** **ccache** - Credential cache + + **[in]** **in_tkt_service** - Server principal string (or NULL) + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function gets a renewed credential using an existing one from *ccache* . If *in_tkt_service* is specified, it is parsed (with the realm part ignored) and used as the server principal of the credential; otherwise, the ticket-granting service is used. + + + +If successful, the renewed credential is placed in *creds* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_server_rcache.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_server_rcache.rst.txt new file mode 100644 index 00000000..38bb1305 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_server_rcache.rst.txt @@ -0,0 +1,55 @@ +krb5_get_server_rcache - Generate a replay cache object for server use and open it. +===================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_server_rcache(krb5_context context, const krb5_data * piece, krb5_rcache * rcptr) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **piece** - Unused (replay cache identifier) + + **[out]** **rcptr** - Handle to an open rcache + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a handle to the default replay cache. Use krb5_rc_close() to close *rcptr* when it is no longer needed. + + + + + + + + + + +.. + + + + +.. note:: + + Prior to release 1.18, this function creates a handle to a different replay cache for each unique value of *piece* . + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_time_offsets.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_time_offsets.rst.txt new file mode 100644 index 00000000..9bdd8ecb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_time_offsets.rst.txt @@ -0,0 +1,51 @@ +krb5_get_time_offsets - Return the time offsets from the os context. +====================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_time_offsets(krb5_context context, krb5_timestamp * seconds, krb5_int32 * microseconds) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **seconds** - Time offset, seconds portion + + **[out]** **microseconds** - Time offset, microseconds portion + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function returns the time offsets in *context* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_validated_creds.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_validated_creds.rst.txt new file mode 100644 index 00000000..e1bf3107 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_get_validated_creds.rst.txt @@ -0,0 +1,67 @@ +krb5_get_validated_creds - Get validated credentials from the KDC. +==================================================================== + +.. + +.. c:function:: krb5_error_code krb5_get_validated_creds(krb5_context context, krb5_creds * creds, krb5_principal client, krb5_ccache ccache, const char * in_tkt_service) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **creds** - Validated credentials + + **[in]** **client** - Client principal name + + **[in]** **ccache** - Credential cache + + **[in]** **in_tkt_service** - Server principal string (or NULL) + + +.. + + +:retval: + - 0 Success + - KRB5_NO_2ND_TKT Request missing second ticket + - KRB5_NO_TKT_SUPPLIED Request did not supply a ticket + - KRB5_PRINC_NOMATCH Requested principal and ticket do not match + - KRB5_KDCREP_MODIFIED KDC reply did not match expectations + - KRB5_KDCREP_SKEW Clock skew too great in KDC reply + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function gets a validated credential using a postdated credential from *ccache* . If *in_tkt_service* is specified, it is parsed (with the realm part ignored) and used as the server principal of the credential; otherwise, the ticket-granting service is used. + + + +If successful, the validated credential is placed in *creds* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_context.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_context.rst.txt new file mode 100644 index 00000000..df00c2da --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_context.rst.txt @@ -0,0 +1,58 @@ +krb5_init_context - Create a krb5 library context. +==================================================== + +.. + +.. c:function:: krb5_error_code krb5_init_context(krb5_context * context) + +.. + + +:param: + + **[out]** **context** - Library context + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +The *context* must be released by calling krb5_free_context() when it is no longer needed. + + + + + + + + + + +.. + + + + + +.. warning:: + + Any program or module that needs the Kerberos code to not trust the environment must use krb5_init_secure_context(), or clean out the environment. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_context_profile.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_context_profile.rst.txt new file mode 100644 index 00000000..d92f0995 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_context_profile.rst.txt @@ -0,0 +1,55 @@ +krb5_init_context_profile - Create a krb5 library context using a specified profile. +====================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_init_context_profile(struct _profile_t * profile, krb5_flags flags, krb5_context * context) + +.. + + +:param: + + **[in]** **profile** - Profile object (NULL to create default profile) + + **[in]** **flags** - Context initialization flags + + **[out]** **context** - Library context + + +.. + + + +.. + + + + + + + +Create a context structure, optionally using a specified profile and initialization flags. If *profile* is NULL, the default profile will be created from config files. If *profile* is non-null, a copy of it will be made for the new context; the caller should still clean up its copy. Valid flag values are: + + + + + + - #KRB5_INIT_CONTEXT_SECURE Ignore environment variables + + + - #KRB5_INIT_CONTEXT_KDC Use KDC configuration if creating profile + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_free.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_free.rst.txt new file mode 100644 index 00000000..9b6f5500 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_free.rst.txt @@ -0,0 +1,42 @@ +krb5_init_creds_free - Free an initial credentials context. +============================================================= + +.. + +.. c:function:: void krb5_init_creds_free(krb5_context context, krb5_init_creds_context ctx) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - Initial credentials context + + +.. + + + +.. + + + + + + + + *context* must be the same as the one passed to krb5_init_creds_init() for this initial credentials context. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get.rst.txt new file mode 100644 index 00000000..00e070ae --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get.rst.txt @@ -0,0 +1,53 @@ +krb5_init_creds_get - Acquire credentials using an initial credentials context. +================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_init_creds_get(krb5_context context, krb5_init_creds_context ctx) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - Initial credentials context + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function synchronously obtains credentials using a context created by krb5_init_creds_init(). On successful return, the credentials can be retrieved with krb5_init_creds_get_creds(). + + + + *context* must be the same as the one passed to krb5_init_creds_init() for this initial credentials context. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get_creds.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get_creds.rst.txt new file mode 100644 index 00000000..777f7f88 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get_creds.rst.txt @@ -0,0 +1,51 @@ +krb5_init_creds_get_creds - Retrieve acquired credentials from an initial credentials context. +================================================================================================ + +.. + +.. c:function:: krb5_error_code krb5_init_creds_get_creds(krb5_context context, krb5_init_creds_context ctx, krb5_creds * creds) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - Initial credentials context + + **[out]** **creds** - Acquired credentials + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function copies the acquired initial credentials from *ctx* into *creds* , after the successful completion of krb5_init_creds_get() or krb5_init_creds_step(). Use krb5_free_cred_contents() to free *creds* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get_error.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get_error.rst.txt new file mode 100644 index 00000000..66aea0b8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get_error.rst.txt @@ -0,0 +1,47 @@ +krb5_init_creds_get_error - Get the last error from KDC from an initial credentials context. +============================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_init_creds_get_error(krb5_context context, krb5_init_creds_context ctx, krb5_error ** error) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - Initial credentials context + + **[out]** **error** - Error from KDC, or NULL if none was received + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get_times.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get_times.rst.txt new file mode 100644 index 00000000..e856df1d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_get_times.rst.txt @@ -0,0 +1,51 @@ +krb5_init_creds_get_times - Retrieve ticket times from an initial credentials context. +======================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_init_creds_get_times(krb5_context context, krb5_init_creds_context ctx, krb5_ticket_times * times) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - Initial credentials context + + **[out]** **times** - Ticket times for acquired credentials + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +The initial credentials context must have completed obtaining credentials via either krb5_init_creds_get() or krb5_init_creds_step(). + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_init.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_init.rst.txt new file mode 100644 index 00000000..ed8096b8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_init.rst.txt @@ -0,0 +1,63 @@ +krb5_init_creds_init - Create a context for acquiring initial credentials. +============================================================================ + +.. + +.. c:function:: krb5_error_code krb5_init_creds_init(krb5_context context, krb5_principal client, krb5_prompter_fct prompter, void * data, krb5_deltat start_time, krb5_get_init_creds_opt * options, krb5_init_creds_context * ctx) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **client** - Client principal to get initial creds for + + **[in]** **prompter** - Prompter callback + + **[in]** **data** - Prompter callback argument + + **[in]** **start_time** - Time when credentials become valid (0 for now) + + **[in]** **options** - Options structure (NULL for default) + + **[out]** **ctx** - New initial credentials context + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a new context for acquiring initial credentials. Use krb5_init_creds_free() to free *ctx* when it is no longer needed. + + + +Any subsequent calls to krb5_init_creds_step(), krb5_init_creds_get(), or krb5_init_creds_free() for this initial credentials context must use the same *context* argument as the one passed to this function. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_set_keytab.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_set_keytab.rst.txt new file mode 100644 index 00000000..222755aa --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_set_keytab.rst.txt @@ -0,0 +1,51 @@ +krb5_init_creds_set_keytab - Specify a keytab to use for acquiring initial credentials. +========================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_init_creds_set_keytab(krb5_context context, krb5_init_creds_context ctx, krb5_keytab keytab) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - Initial credentials context + + **[in]** **keytab** - Key table handle + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function supplies a keytab containing the client key for an initial credentials request. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_set_password.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_set_password.rst.txt new file mode 100644 index 00000000..10ad140d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_set_password.rst.txt @@ -0,0 +1,51 @@ +krb5_init_creds_set_password - Set a password for acquiring initial credentials. +================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_init_creds_set_password(krb5_context context, krb5_init_creds_context ctx, const char * password) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - Initial credentials context + + **[in]** **password** - Password + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function supplies a password to be used to construct the client key for an initial credentials request. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_set_service.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_set_service.rst.txt new file mode 100644 index 00000000..d08ffc7d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_set_service.rst.txt @@ -0,0 +1,51 @@ +krb5_init_creds_set_service - Specify a service principal for acquiring initial credentials. +============================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_init_creds_set_service(krb5_context context, krb5_init_creds_context ctx, const char * service) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - Initial credentials context + + **[in]** **service** - Service principal string + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function supplies a service principal string to acquire initial credentials for instead of the default krbtgt service. *service* is parsed as a principal name; any realm part is ignored. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_step.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_step.rst.txt new file mode 100644 index 00000000..4f425510 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_creds_step.rst.txt @@ -0,0 +1,69 @@ +krb5_init_creds_step - Get the next KDC request for acquiring initial credentials. +==================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_init_creds_step(krb5_context context, krb5_init_creds_context ctx, krb5_data * in, krb5_data * out, krb5_data * realm, unsigned int * flags) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - Initial credentials context + + **[in]** **in** - KDC response (empty on the first call) + + **[out]** **out** - Next KDC request + + **[out]** **realm** - Realm for next KDC request + + **[out]** **flags** - Output flags + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function constructs the next KDC request in an initial credential exchange, allowing the caller to control the transport of KDC requests and replies. On the first call, *in* should be set to an empty buffer; on subsequent calls, it should be set to the KDC's reply to the previous request. + + + +If more requests are needed, *flags* will be set to #KRB5_INIT_CREDS_STEP_FLAG_CONTINUE and the next request will be placed in *out* . If no more requests are needed, *flags* will not contain #KRB5_INIT_CREDS_STEP_FLAG_CONTINUE and *out* will be empty. + + + +If this function returns **KRB5KRB_ERR_RESPONSE_TOO_BIG** , the caller should transmit the next request using TCP rather than UDP. If this function returns any other error, the initial credential exchange has failed. + + + + *context* must be the same as the one passed to krb5_init_creds_init() for this initial credentials context. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_keyblock.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_keyblock.rst.txt new file mode 100644 index 00000000..cc6109de --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_keyblock.rst.txt @@ -0,0 +1,61 @@ +krb5_init_keyblock - Initialize an empty krb5_keyblock . +========================================================== + +.. + +.. c:function:: krb5_error_code krb5_init_keyblock(krb5_context context, krb5_enctype enctype, size_t length, krb5_keyblock ** out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enctype** - Encryption type + + **[in]** **length** - Length of keyblock (or 0) + + **[out]** **out** - New keyblock structure + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Initialize a new keyblock and allocate storage for the contents of the key. It is legal to pass in a length of 0, in which case contents are left unallocated. Use krb5_free_keyblock() to free *out* when it is no longer needed. + + + + + + + + + + +.. + + + + + + +.. note:: + + If *length* is set to 0, contents are left unallocated. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_random_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_random_key.rst.txt new file mode 100644 index 00000000..271d7274 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_random_key.rst.txt @@ -0,0 +1,48 @@ +krb5_init_random_key +==================== + +.. + +.. c:function:: krb5_error_code krb5_init_random_key(krb5_context context, const krb5_encrypt_block * eblock, const krb5_keyblock * keyblock, krb5_pointer * ptr) + +.. + + +:param: + + **context** + + **eblock** + + **keyblock** + + **ptr** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_c_* API family. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_secure_context.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_secure_context.rst.txt new file mode 100644 index 00000000..83c41cdb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_init_secure_context.rst.txt @@ -0,0 +1,54 @@ +krb5_init_secure_context - Create a krb5 library context using only configuration files. +========================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_init_secure_context(krb5_context * context) + +.. + + +:param: + + **[out]** **context** - Library context + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Create a context structure, using only system configuration files. All information passed through the environment variables is ignored. + + + +The *context* must be released by calling krb5_free_context() when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_is_config_principal.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_is_config_principal.rst.txt new file mode 100644 index 00000000..8c1ef806 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_is_config_principal.rst.txt @@ -0,0 +1,45 @@ +krb5_is_config_principal - Test whether a principal is a configuration principal. +=================================================================================== + +.. + +.. c:function:: krb5_boolean krb5_is_config_principal(krb5_context context, krb5_const_principal principal) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **principal** - Principal to check + + +.. + + + +:return: + - TRUE if the principal is a configuration principal (generated part of krb5_cc_set_config()); FALSE otherwise. + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_is_referral_realm.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_is_referral_realm.rst.txt new file mode 100644 index 00000000..89916c32 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_is_referral_realm.rst.txt @@ -0,0 +1,43 @@ +krb5_is_referral_realm - Check for a match with KRB5_REFERRAL_REALM. +====================================================================== + +.. + +.. c:function:: krb5_boolean krb5_is_referral_realm(const krb5_data * r) + +.. + + +:param: + + **[in]** **r** - Realm to check + + +.. + + + +:return: + - TRUE if r is zero-length, FALSE otherwise + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_is_thread_safe.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_is_thread_safe.rst.txt new file mode 100644 index 00000000..812a2c32 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_is_thread_safe.rst.txt @@ -0,0 +1,43 @@ +krb5_is_thread_safe - Test whether the Kerberos library was built with multithread support. +============================================================================================= + +.. + +.. c:function:: krb5_boolean krb5_is_thread_safe(void None) + +.. + + +:param: + + **None** + + +.. + + +:retval: + - TRUE if the library is threadsafe; FALSE otherwise + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_create_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_create_key.rst.txt new file mode 100644 index 00000000..204d0209 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_create_key.rst.txt @@ -0,0 +1,51 @@ +krb5_k_create_key - Create a krb5_key from the enctype and key data in a keyblock. +==================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_k_create_key(krb5_context context, const krb5_keyblock * key_data, krb5_key * out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key_data** - Keyblock + + **[out]** **out** - Opaque key + + +.. + + +:retval: + - 0 Success; otherwise - KRB5_BAD_ENCTYPE + + +.. + + + + + + + +The reference count on a key *out* is set to 1. Use krb5_k_free_key() to free *out* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_decrypt.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_decrypt.rst.txt new file mode 100644 index 00000000..3c170041 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_decrypt.rst.txt @@ -0,0 +1,65 @@ +krb5_k_decrypt - Decrypt data using a key (operates on opaque key). +===================================================================== + +.. + +.. c:function:: krb5_error_code krb5_k_decrypt(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data * cipher_state, const krb5_enc_data * input, krb5_data * output) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Encryption key + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[inout]** **cipher_state** - Cipher state; specify NULL if not needed + + **[in]** **input** - Encrypted data + + **[out]** **output** - Decrypted data + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function decrypts the data block *input* and stores the output into *output* . The actual decryption key will be derived from *key* and *usage* if key derivation is specified for the encryption type. If non-null, *cipher_state* specifies the beginning state for the decryption operation, and is updated with the state to be passed as input to the next operation. + + + + + + + + + + +.. + + + + + + +.. note:: + + The caller must initialize *output* and allocate at least enough space for the result. The usual practice is to allocate an output buffer as long as the ciphertext, and let krb5_c_decrypt() trim *output->length* . For some enctypes, the resulting *output->length* may include padding bytes. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_decrypt_iov.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_decrypt_iov.rst.txt new file mode 100644 index 00000000..3156b439 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_decrypt_iov.rst.txt @@ -0,0 +1,68 @@ +krb5_k_decrypt_iov - Decrypt data in place supporting AEAD (operates on opaque key). +====================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_k_decrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data * cipher_state, krb5_crypto_iov * data, size_t num_data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Encryption key + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[in]** **cipher_state** - Cipher state; specify NULL if not needed + + **[inout]** **data** - IOV array. Modified in-place. + + **[in]** **num_data** - Size of *data* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function decrypts the data block *data* and stores the output in-place. The actual decryption key will be derived from *key* and *usage* if key derivation is specified for the encryption type. If non-null, *cipher_state* specifies the beginning state for the decryption operation, and is updated with the state to be passed as input to the next operation. The caller must allocate the right number of krb5_crypto_iov structures before calling into this API. + + + + + + + + + + +.. + +.. seealso:: + krb5_k_encrypt_iov() + + + + + + +.. note:: + + On return from a krb5_c_decrypt_iov() call, the *data->length* in the iov structure are adjusted to reflect actual lengths of the ciphertext used. For example, if the padding length is too large, the length will be reduced. Lengths are never increased. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_encrypt.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_encrypt.rst.txt new file mode 100644 index 00000000..797f9d2a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_encrypt.rst.txt @@ -0,0 +1,65 @@ +krb5_k_encrypt - Encrypt data using a key (operates on opaque key). +===================================================================== + +.. + +.. c:function:: krb5_error_code krb5_k_encrypt(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data * cipher_state, const krb5_data * input, krb5_enc_data * output) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Encryption key + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[inout]** **cipher_state** - Cipher state; specify NULL if not needed + + **[in]** **input** - Data to be encrypted + + **[out]** **output** - Encrypted data + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function encrypts the data block *input* and stores the output into *output* . The actual encryption key will be derived from *key* and *usage* if key derivation is specified for the encryption type. If non-null, *cipher_state* specifies the beginning state for the encryption operation, and is updated with the state to be passed as input to the next operation. + + + + + + + + + + +.. + + + + + + +.. note:: + + The caller must initialize *output* and allocate at least enough space for the result (using krb5_c_encrypt_length() to determine the amount of space needed). *output->length* will be set to the actual length of the ciphertext. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_encrypt_iov.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_encrypt_iov.rst.txt new file mode 100644 index 00000000..e715e26e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_encrypt_iov.rst.txt @@ -0,0 +1,68 @@ +krb5_k_encrypt_iov - Encrypt data in place supporting AEAD (operates on opaque key). +====================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_k_encrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data * cipher_state, krb5_crypto_iov * data, size_t num_data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Encryption key + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[in]** **cipher_state** - Cipher state; specify NULL if not needed + + **[inout]** **data** - IOV array. Modified in-place. + + **[in]** **num_data** - Size of *data* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function encrypts the data block *data* and stores the output in-place. The actual encryption key will be derived from *key* and *usage* if key derivation is specified for the encryption type. If non-null, *cipher_state* specifies the beginning state for the encryption operation, and is updated with the state to be passed as input to the next operation. The caller must allocate the right number of krb5_crypto_iov structures before calling into this API. + + + + + + + + + + +.. + +.. seealso:: + krb5_k_decrypt_iov() + + + + + + +.. note:: + + On return from a krb5_c_encrypt_iov() call, the *data->length* in the iov structure are adjusted to reflect actual lengths of the ciphertext used. For example, if the padding length is too large, the length will be reduced. Lengths are never increased. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_free_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_free_key.rst.txt new file mode 100644 index 00000000..c1060f6d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_free_key.rst.txt @@ -0,0 +1,39 @@ +krb5_k_free_key - Decrement the reference count on a key and free it if it hits zero. +======================================================================================= + +.. + +.. c:function:: void krb5_k_free_key(krb5_context context, krb5_key key) + +.. + + +:param: + + **context** + + **key** + + +.. + + + +.. + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_key_enctype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_key_enctype.rst.txt new file mode 100644 index 00000000..d77a541e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_key_enctype.rst.txt @@ -0,0 +1,39 @@ +krb5_k_key_enctype - Retrieve the enctype of a krb5_key structure. +==================================================================== + +.. + +.. c:function:: krb5_enctype krb5_k_key_enctype(krb5_context context, krb5_key key) + +.. + + +:param: + + **context** + + **key** + + +.. + + + +.. + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_key_keyblock.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_key_keyblock.rst.txt new file mode 100644 index 00000000..efd782c9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_key_keyblock.rst.txt @@ -0,0 +1,41 @@ +krb5_k_key_keyblock - Retrieve a copy of the keyblock from a krb5_key structure. +================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_k_key_keyblock(krb5_context context, krb5_key key, krb5_keyblock ** key_data) + +.. + + +:param: + + **context** + + **key** + + **key_data** + + +.. + + + +.. + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_make_checksum.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_make_checksum.rst.txt new file mode 100644 index 00000000..3f66c0f0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_make_checksum.rst.txt @@ -0,0 +1,68 @@ +krb5_k_make_checksum - Compute a checksum (operates on opaque key). +===================================================================== + +.. + +.. c:function:: krb5_error_code krb5_k_make_checksum(krb5_context context, krb5_cksumtype cksumtype, krb5_key key, krb5_keyusage usage, const krb5_data * input, krb5_checksum * cksum) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cksumtype** - Checksum type (0 for mandatory type) + + **[in]** **key** - Encryption key for a keyed checksum + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[in]** **input** - Input data + + **[out]** **cksum** - Generated checksum + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function computes a checksum of type *cksumtype* over *input* , using *key* if the checksum type is a keyed checksum. If *cksumtype* is 0 and *key* is non-null, the checksum type will be the mandatory-to-implement checksum type for the key's encryption type. The actual checksum key will be derived from *key* and *usage* if key derivation is specified for the checksum type. The newly created *cksum* must be released by calling krb5_free_checksum_contents() when it is no longer needed. + + + + + + + + + + +.. + +.. seealso:: + krb5_c_verify_checksum() + + + + + + +.. note:: + + This function is similar to krb5_c_make_checksum(), but operates on opaque *key* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_make_checksum_iov.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_make_checksum_iov.rst.txt new file mode 100644 index 00000000..a25d8ec1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_make_checksum_iov.rst.txt @@ -0,0 +1,68 @@ +krb5_k_make_checksum_iov - Fill in a checksum element in IOV array (operates on opaque key) +============================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_k_make_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, krb5_key key, krb5_keyusage usage, krb5_crypto_iov * data, size_t num_data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cksumtype** - Checksum type (0 for mandatory type) + + **[in]** **key** - Encryption key for a keyed checksum + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[inout]** **data** - IOV array + + **[in]** **num_data** - Size of *data* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Create a checksum in the #KRB5_CRYPTO_TYPE_CHECKSUM element over #KRB5_CRYPTO_TYPE_DATA and #KRB5_CRYPTO_TYPE_SIGN_ONLY chunks in *data* . Only the #KRB5_CRYPTO_TYPE_CHECKSUM region is modified. + + + + + + + + + + +.. + +.. seealso:: + krb5_k_verify_checksum_iov() + + + + + + +.. note:: + + This function is similar to krb5_c_make_checksum_iov(), but operates on opaque *key* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_prf.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_prf.rst.txt new file mode 100644 index 00000000..69b75d83 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_prf.rst.txt @@ -0,0 +1,61 @@ +krb5_k_prf - Generate enctype-specific pseudo-random bytes (operates on opaque key). +====================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_k_prf(krb5_context context, krb5_key key, krb5_data * input, krb5_data * output) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Key + + **[in]** **input** - Input data + + **[out]** **output** - Output data + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function selects a pseudo-random function based on *key* and computes its value over *input* , placing the result into *output* . The caller must preinitialize *output* and allocate space for the result. + + + + + + + + + + +.. + + + + + + +.. note:: + + This function is similar to krb5_c_prf(), but operates on opaque *key* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_reference_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_reference_key.rst.txt new file mode 100644 index 00000000..06b4629e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_reference_key.rst.txt @@ -0,0 +1,39 @@ +krb5_k_reference_key - Increment the reference count on a key. +================================================================ + +.. + +.. c:function:: void krb5_k_reference_key(krb5_context context, krb5_key key) + +.. + + +:param: + + **context** + + **key** + + +.. + + + +.. + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_verify_checksum.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_verify_checksum.rst.txt new file mode 100644 index 00000000..fe591953 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_verify_checksum.rst.txt @@ -0,0 +1,65 @@ +krb5_k_verify_checksum - Verify a checksum (operates on opaque key). +====================================================================== + +.. + +.. c:function:: krb5_error_code krb5_k_verify_checksum(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data * data, const krb5_checksum * cksum, krb5_boolean * valid) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Encryption key for a keyed checksum + + **[in]** **usage** - *key* usage + + **[in]** **data** - Data to be used to compute a new checksum using *key* to compare *cksum* against + + **[in]** **cksum** - Checksum to be verified + + **[out]** **valid** - Non-zero for success, zero for failure + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function verifies that *cksum* is a valid checksum for *data* . If the checksum type of *cksum* is a keyed checksum, *key* is used to verify the checksum. If the checksum type in *cksum* is 0 and *key* is not NULL, the mandatory checksum type for *key* will be used. The actual checksum key will be derived from *key* and *usage* if key derivation is specified for the checksum type. + + + + + + + + + + +.. + + + + + + +.. note:: + + This function is similar to krb5_c_verify_checksum(), but operates on opaque *key* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_verify_checksum_iov.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_verify_checksum_iov.rst.txt new file mode 100644 index 00000000..af4cffee --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_k_verify_checksum_iov.rst.txt @@ -0,0 +1,70 @@ +krb5_k_verify_checksum_iov - Validate a checksum element in IOV array (operates on opaque key). +================================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_k_verify_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, krb5_key key, krb5_keyusage usage, const krb5_crypto_iov * data, size_t num_data, krb5_boolean * valid) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **cksumtype** - Checksum type (0 for mandatory type) + + **[in]** **key** - Encryption key for a keyed checksum + + **[in]** **usage** - Key usage (see KRB5_KEYUSAGE macros) + + **[in]** **data** - IOV array + + **[in]** **num_data** - Size of *data* + + **[out]** **valid** - Non-zero for success, zero for failure + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Confirm that the checksum in the #KRB5_CRYPTO_TYPE_CHECKSUM element is a valid checksum of the #KRB5_CRYPTO_TYPE_DATA and #KRB5_CRYPTO_TYPE_SIGN_ONLY regions in the iov. + + + + + + + + + + +.. + +.. seealso:: + krb5_k_make_checksum_iov() + + + + + + +.. note:: + + This function is similar to krb5_c_verify_checksum_iov(), but operates on opaque *key* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kdc_sign_ticket.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kdc_sign_ticket.rst.txt new file mode 100644 index 00000000..4697e455 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kdc_sign_ticket.rst.txt @@ -0,0 +1,65 @@ +krb5_kdc_sign_ticket - Sign a PAC, possibly including a ticket signature. +=========================================================================== + +.. + +.. c:function:: krb5_error_code krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part * enc_tkt, const krb5_pac pac, krb5_const_principal server_princ, krb5_const_principal client_princ, const krb5_keyblock * server, const krb5_keyblock * privsvr, krb5_boolean with_realm) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enc_tkt** - The ticket for the signature + + **[in]** **pac** - PAC handle + + **[in]** **server_princ** - Canonical ticket server name + + **[in]** **client_princ** - PAC_CLIENT_INFO principal (or NULL) + + **[in]** **server** - Key for server checksum + + **[in]** **privsvr** - Key for KDC and ticket checksum + + **[in]** **with_realm** - If true, include the realm of *principal* + + +.. + + +:retval: + - 0 on success, otherwise - Kerberos error codes + + +.. + + + + + + + +Sign *pac* using the keys *server* and *privsvr* . Include a ticket signature over *enc_tkt* if *server_princ* is not a TGS or kadmin/changepw principal name. Add the signed PAC's encoding to the authorization data of *enc_tkt* in the first slot, wrapped in an AD-IF-RELEVANT container. If *client_princ* is non-null, add a PAC_CLIENT_INFO buffer, including the realm if *with_realm* is true. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.20 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kdc_verify_ticket.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kdc_verify_ticket.rst.txt new file mode 100644 index 00000000..29fdd3a3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kdc_verify_ticket.rst.txt @@ -0,0 +1,73 @@ +krb5_kdc_verify_ticket - Verify a PAC, possibly including ticket signature. +============================================================================= + +.. + +.. c:function:: krb5_error_code krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part * enc_tkt, krb5_const_principal server_princ, const krb5_keyblock * server, const krb5_keyblock * privsvr, krb5_pac * pac_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enc_tkt** - Ticket enc-part, possibly containing a PAC + + **[in]** **server_princ** - Canonicalized name of ticket server + + **[in]** **server** - Key to validate server checksum (or NULL) + + **[in]** **privsvr** - Key to validate KDC checksum (or NULL) + + **[out]** **pac_out** - Verified PAC (NULL if no PAC included) + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +If a PAC is present in *enc_tkt* , verify its signatures. If *privsvr* is not NULL and *server_princ* is not a krbtgt or kadmin/changepw service, require a ticket signature over *enc_tkt* in addition to the KDC signature. Place the verified PAC in *pac_out* . If an invalid PAC signature is found, return an error matching the Windows KDC protocol code for that condition as closely as possible. + + + +If no PAC is present in *enc_tkt* , set *pac_out* to NULL and return successfully. + + + + + + + + + + +.. + + + + + + +.. note:: + + This function does not validate the PAC_CLIENT_INFO buffer. If a specific value is expected, the caller can make a separate call to krb5_pac_verify_ext() with a principal but no keys. + + + +.. note:: + + New in 1.20 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_add_entry.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_add_entry.rst.txt new file mode 100644 index 00000000..f762d360 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_add_entry.rst.txt @@ -0,0 +1,52 @@ +krb5_kt_add_entry - Add a new entry to a key table. +===================================================== + +.. + +.. c:function:: krb5_error_code krb5_kt_add_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry * entry) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **id** - Key table handle + + **[in]** **entry** - Entry to be added + + +.. + + +:retval: + - 0 Success + - ENOMEM Insufficient memory + - KRB5_KT_NOWRITE Key table is not writeable + + +:return: + - Kerberos error codes + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_client_default.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_client_default.rst.txt new file mode 100644 index 00000000..8f5663bc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_client_default.rst.txt @@ -0,0 +1,56 @@ +krb5_kt_client_default - Resolve the default client key table. +================================================================ + +.. + +.. c:function:: krb5_error_code krb5_kt_client_default(krb5_context context, krb5_keytab * keytab_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **keytab_out** - Key table handle + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Fill *keytab_out* with a handle to the default client key table. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.11 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_close.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_close.rst.txt new file mode 100644 index 00000000..4761ad68 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_close.rst.txt @@ -0,0 +1,45 @@ +krb5_kt_close - Close a key table handle. +=========================================== + +.. + +.. c:function:: krb5_error_code krb5_kt_close(krb5_context context, krb5_keytab keytab) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **keytab** - Key table handle + + +.. + + +:retval: + - 0 None + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_default.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_default.rst.txt new file mode 100644 index 00000000..35f5a660 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_default.rst.txt @@ -0,0 +1,52 @@ +krb5_kt_default - Resolve the default key table. +================================================== + +.. + +.. c:function:: krb5_error_code krb5_kt_default(krb5_context context, krb5_keytab * id) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **id** - Key table handle + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Set *id* to a handle to the default key table. The key table is not opened. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_default_name.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_default_name.rst.txt new file mode 100644 index 00000000..6f9e558f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_default_name.rst.txt @@ -0,0 +1,55 @@ +krb5_kt_default_name - Get the default key table name. +======================================================== + +.. + +.. c:function:: krb5_error_code krb5_kt_default_name(krb5_context context, char * name, int name_size) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **name** - Default key table name + + **[in]** **name_size** - Space available in *name* + + +.. + + +:retval: + - 0 Success + - KRB5_CONFIG_NOTENUFSPACE Buffer is too short + + +:return: + - Kerberos error codes + +.. + + + + + + + +Fill *name* with the name of the default key table for *context* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_dup.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_dup.rst.txt new file mode 100644 index 00000000..74546350 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_dup.rst.txt @@ -0,0 +1,52 @@ +krb5_kt_dup - Duplicate keytab handle. +======================================== + +.. + +.. c:function:: krb5_error_code krb5_kt_dup(krb5_context context, krb5_keytab in, krb5_keytab * out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **in** - Key table handle to be duplicated + + **[out]** **out** - Key table handle + + +.. + + + +.. + + + + + + + +Create a new handle referring to the same key table as *in* . The new handle and *in* can be closed independently. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.12 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_end_seq_get.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_end_seq_get.rst.txt new file mode 100644 index 00000000..c22443ae --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_end_seq_get.rst.txt @@ -0,0 +1,54 @@ +krb5_kt_end_seq_get - Release a keytab cursor. +================================================ + +.. + +.. c:function:: krb5_error_code krb5_kt_end_seq_get(krb5_context context, krb5_keytab keytab, krb5_kt_cursor * cursor) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **keytab** - Key table handle + + **[out]** **cursor** - Cursor + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function should be called to release the cursor created by krb5_kt_start_seq_get(). + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_free_entry.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_free_entry.rst.txt new file mode 100644 index 00000000..5eaa118f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_free_entry.rst.txt @@ -0,0 +1,44 @@ +krb5_kt_free_entry +================== + +.. + +.. c:function:: krb5_error_code krb5_kt_free_entry(krb5_context context, krb5_keytab_entry * entry) + +.. + + +:param: + + **context** + + **entry** + + +.. + + + +.. + + +DEPRECATED Use krb5_free_keytab_entry_contents instead. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_get_entry.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_get_entry.rst.txt new file mode 100644 index 00000000..d5779002 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_get_entry.rst.txt @@ -0,0 +1,70 @@ +krb5_kt_get_entry - Get an entry from a key table. +==================================================== + +.. + +.. c:function:: krb5_error_code krb5_kt_get_entry(krb5_context context, krb5_keytab keytab, krb5_const_principal principal, krb5_kvno vno, krb5_enctype enctype, krb5_keytab_entry * entry) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **keytab** - Key table handle + + **[in]** **principal** - Principal name + + **[in]** **vno** - Key version number (0 for highest available) + + **[in]** **enctype** - Encryption type (0 zero for any enctype) + + **[out]** **entry** - Returned entry from key table + + +.. + + +:retval: + - 0 Success + - Kerberos error codes on failure + + +.. + + + + + + + +Retrieve an entry from a key table which matches the *keytab* , *principal* , *vno* , and *enctype* . If *vno* is zero, retrieve the highest-numbered kvno matching the other fields. If *enctype* is 0, match any enctype. + + + +Use krb5_free_keytab_entry_contents() to free *entry* when it is no longer needed. + + + + + + + + + + +.. + + + + + + +.. note:: + + If *vno* is zero, the function retrieves the highest-numbered-kvno entry that matches the specified principal. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_get_name.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_get_name.rst.txt new file mode 100644 index 00000000..5d36dbba --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_get_name.rst.txt @@ -0,0 +1,57 @@ +krb5_kt_get_name - Get a key table name. +========================================== + +.. + +.. c:function:: krb5_error_code krb5_kt_get_name(krb5_context context, krb5_keytab keytab, char * name, unsigned int namelen) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **keytab** - Key table handle + + **[out]** **name** - Key table name + + **[in]** **namelen** - Maximum length to fill in name + + +.. + + +:retval: + - 0 Success + - KRB5_KT_NAME_TOOLONG Key table name does not fit in namelen bytes + + +:return: + - Kerberos error codes + +.. + + + + + + + +Fill *name* with the name of *keytab* including the type and delimiter. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_get_type.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_get_type.rst.txt new file mode 100644 index 00000000..c675af8f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_get_type.rst.txt @@ -0,0 +1,45 @@ +krb5_kt_get_type - Return the type of a key table. +==================================================== + +.. + +.. c:function:: const char * krb5_kt_get_type(krb5_context context, krb5_keytab keytab) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **keytab** - Key table handle + + +.. + + + +:return: + - The type of a key table as an alias that must not be modified or freed by the caller. + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_have_content.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_have_content.rst.txt new file mode 100644 index 00000000..dffa94e6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_have_content.rst.txt @@ -0,0 +1,50 @@ +krb5_kt_have_content - Check if a keytab exists and contains entries. +======================================================================= + +.. + +.. c:function:: krb5_error_code krb5_kt_have_content(krb5_context context, krb5_keytab keytab) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **keytab** - Key table handle + + +.. + + +:retval: + - 0 Keytab exists and contains entries + - KRB5_KT_NOTFOUND Keytab does not contain entries + + +.. + + + + + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.11 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_next_entry.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_next_entry.rst.txt new file mode 100644 index 00000000..a8715175 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_next_entry.rst.txt @@ -0,0 +1,57 @@ +krb5_kt_next_entry - Retrieve the next entry from the key table. +================================================================== + +.. + +.. c:function:: krb5_error_code krb5_kt_next_entry(krb5_context context, krb5_keytab keytab, krb5_keytab_entry * entry, krb5_kt_cursor * cursor) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **keytab** - Key table handle + + **[out]** **entry** - Returned key table entry + + **[in]** **cursor** - Key table cursor + + +.. + + +:retval: + - 0 Success + - KRB5_KT_END - if the last entry was reached + + +:return: + - Kerberos error codes + +.. + + + + + + + +Return the next sequential entry in *keytab* and advance *cursor* . Callers must release the returned entry with krb5_kt_free_entry(). + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_read_service_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_read_service_key.rst.txt new file mode 100644 index 00000000..acb8ca86 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_read_service_key.rst.txt @@ -0,0 +1,68 @@ +krb5_kt_read_service_key - Retrieve a service key from a key table. +===================================================================== + +.. + +.. c:function:: krb5_error_code krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg, krb5_principal principal, krb5_kvno vno, krb5_enctype enctype, krb5_keyblock ** key) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **keyprocarg** - Name of a key table (NULL to use default name) + + **[in]** **principal** - Service principal + + **[in]** **vno** - Key version number (0 for highest available) + + **[in]** **enctype** - Encryption type (0 for any type) + + **[out]** **key** - Service key from key table + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error code if not found or keyprocarg is invalid. + +.. + + + + + + + +Open and search the specified key table for the entry identified by *principal* , *enctype* , and *vno* . If no key is found, return an error code. + + + +The default key table is used, unless *keyprocarg* is non-null. *keyprocarg* designates a specific key table. + + + +Use krb5_free_keyblock() to free *key* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_remove_entry.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_remove_entry.rst.txt new file mode 100644 index 00000000..10c1705a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_remove_entry.rst.txt @@ -0,0 +1,51 @@ +krb5_kt_remove_entry - Remove an entry from a key table. +========================================================== + +.. + +.. c:function:: krb5_error_code krb5_kt_remove_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry * entry) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **id** - Key table handle + + **[in]** **entry** - Entry to remove from key table + + +.. + + +:retval: + - 0 Success + - KRB5_KT_NOWRITE Key table is not writable + + +:return: + - Kerberos error codes + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_resolve.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_resolve.rst.txt new file mode 100644 index 00000000..4ece77d8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_resolve.rst.txt @@ -0,0 +1,66 @@ +krb5_kt_resolve - Get a handle for a key table. +================================================= + +.. + +.. c:function:: krb5_error_code krb5_kt_resolve(krb5_context context, const char * name, krb5_keytab * ktid) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **name** - Name of the key table + + **[out]** **ktid** - Key table handle + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Resolve the key table name *name* and set *ktid* to a handle identifying the key table. Use krb5_kt_close() to free *ktid* when it is no longer needed. + + + + *name* must be of the form **type:residual** , where *type* must be a type known to the library and *residual* portion should be specific to the particular keytab type. If no *type* is given, the default is **FILE** . + + + +If *name* is of type **FILE** , the keytab file is not opened by this call. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_start_seq_get.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_start_seq_get.rst.txt new file mode 100644 index 00000000..cbe107be --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kt_start_seq_get.rst.txt @@ -0,0 +1,54 @@ +krb5_kt_start_seq_get - Start a sequential retrieval of key table entries. +============================================================================ + +.. + +.. c:function:: krb5_error_code krb5_kt_start_seq_get(krb5_context context, krb5_keytab keytab, krb5_kt_cursor * cursor) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **keytab** - Key table handle + + **[out]** **cursor** - Cursor + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Prepare to read sequentially every key in the specified key table. Use krb5_kt_end_seq_get() to release the cursor when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kuserok.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kuserok.rst.txt new file mode 100644 index 00000000..7dbd15f7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_kuserok.rst.txt @@ -0,0 +1,51 @@ +krb5_kuserok - Determine if a principal is authorized to log in as a local user. +================================================================================== + +.. + +.. c:function:: krb5_boolean krb5_kuserok(krb5_context context, krb5_principal principal, const char * luser) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **principal** - Principal name + + **[in]** **luser** - Local username + + +.. + + +:retval: + - TRUE Principal is authorized to log in as user; FALSE otherwise. + + +.. + + + + + + + +Determine whether *principal* is authorized to log in as a local user *luser* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_make_authdata_kdc_issued.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_make_authdata_kdc_issued.rst.txt new file mode 100644 index 00000000..e671af5f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_make_authdata_kdc_issued.rst.txt @@ -0,0 +1,48 @@ +krb5_make_authdata_kdc_issued - Encode and sign AD-KDCIssued authorization data. +================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_make_authdata_kdc_issued(krb5_context context, const krb5_keyblock * key, krb5_const_principal issuer, krb5_authdata *const * authdata, krb5_authdata *** ad_kdcissued) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Session key + + **[in]** **issuer** - The name of the issuing principal + + **[in]** **authdata** - List of authorization data to be signed + + **[out]** **ad_kdcissued** - List containing AD-KDCIssued authdata + + +.. + + + +.. + + + + + + + +This function wraps a list of authorization data entries *authdata* in an AD-KDCIssued container (see RFC 4120 section 5.2.6.2) signed with *key* . The result is returned in *ad_kdcissued* as a single-element list. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_marshal_credentials.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_marshal_credentials.rst.txt new file mode 100644 index 00000000..de1c8f8e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_marshal_credentials.rst.txt @@ -0,0 +1,55 @@ +krb5_marshal_credentials - Serialize a krb5_creds object. +=========================================================== + +.. + +.. c:function:: krb5_error_code krb5_marshal_credentials(krb5_context context, krb5_creds * in_creds, krb5_data ** data_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **in_creds** - The credentials object to serialize + + **[out]** **data_out** - The serialized credentials + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Serialize *creds* in the format used by the FILE ccache format (vesion 4) and KCM ccache protocol. + + + +Use krb5_free_data() to free *data_out* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_merge_authdata.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_merge_authdata.rst.txt new file mode 100644 index 00000000..6be3fbef --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_merge_authdata.rst.txt @@ -0,0 +1,61 @@ +krb5_merge_authdata - Merge two authorization data lists into a new list. +=========================================================================== + +.. + +.. c:function:: krb5_error_code krb5_merge_authdata(krb5_context context, krb5_authdata *const * inauthdat1, krb5_authdata *const * inauthdat2, krb5_authdata *** outauthdat) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **inauthdat1** - First list of *krb5_authdata* structures + + **[in]** **inauthdat2** - Second list of *krb5_authdata* structures + + **[out]** **outauthdat** - Merged list of *krb5_authdata* structures + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Merge two authdata arrays, such as the array from a ticket and authenticator. Use krb5_free_authdata() to free *outauthdat* when it is no longer needed. + + + + + + + + + + +.. + + + + + + +.. note:: + + The last array entry in *inauthdat1* and *inauthdat2* must be a NULL pointer. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_1cred.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_1cred.rst.txt new file mode 100644 index 00000000..7244e3be --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_1cred.rst.txt @@ -0,0 +1,60 @@ +krb5_mk_1cred - Format a KRB-CRED message for a single set of credentials. +============================================================================ + +.. + +.. c:function:: krb5_error_code krb5_mk_1cred(krb5_context context, krb5_auth_context auth_context, krb5_creds * creds, krb5_data ** der_out, krb5_replay_data * rdata_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **creds** - Pointer to credentials + + **[out]** **der_out** - Encoded credentials + + **[out]** **rdata_out** - Replay cache data (NULL if not needed) + + +.. + + +:retval: + - 0 Success + - ENOMEM Insufficient memory + - KRB5_RC_REQUIRED Message replay detection requires rcache parameter + + +:return: + - Kerberos error codes + +.. + + + + + + + +This is a convenience function that calls krb5_mk_ncred() with a single set of credentials. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_error.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_error.rst.txt new file mode 100644 index 00000000..59405b26 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_error.rst.txt @@ -0,0 +1,51 @@ +krb5_mk_error - Format and encode a KRB_ERROR message. +======================================================== + +.. + +.. c:function:: krb5_error_code krb5_mk_error(krb5_context context, const krb5_error * dec_err, krb5_data * enc_err) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **dec_err** - Error structure to be encoded + + **[out]** **enc_err** - Encoded error structure + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates a **KRB_ERROR** message in *enc_err* . Use krb5_free_data_contents() to free *enc_err* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_ncred.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_ncred.rst.txt new file mode 100644 index 00000000..7a074b6d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_ncred.rst.txt @@ -0,0 +1,88 @@ +krb5_mk_ncred - Format a KRB-CRED message for an array of credentials. +======================================================================== + +.. + +.. c:function:: krb5_error_code krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, krb5_creds ** creds, krb5_data ** der_out, krb5_replay_data * rdata_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **creds** - Null-terminated array of credentials + + **[out]** **der_out** - Encoded credentials + + **[out]** **rdata_out** - Replay cache information (NULL if not needed) + + +.. + + +:retval: + - 0 Success + - ENOMEM Insufficient memory + - KRB5_RC_REQUIRED Message replay detection requires rcache parameter + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function takes an array of credentials *creds* and formats a **KRB-CRED** message *der_out* to pass to krb5_rd_cred(). + + + +The local and remote addresses in *auth_context* are optional; if either is specified, they are used to form the sender and receiver addresses in the KRB-CRED message. + + + +If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in *auth_context* , an entry for the message is entered in an in-memory replay cache to detect if the message is reflected by an attacker. If #KRB5_AUTH_CONTEXT_DO_TIME is not set, no replay cache is used. If #KRB5_AUTH_CONTEXT_RET_TIME is set in *auth_context* , the timestamp used for the KRB-CRED message is stored in *rdata_out* . + + + +If either #KRB5_AUTH_CONTEXT_DO_SEQUENCE or #KRB5_AUTH_CONTEXT_RET_SEQUENCE is set, the *auth_context* local sequence number is included in the KRB-CRED message and then incremented. If #KRB5_AUTH_CONTEXT_RET_SEQUENCE is set, the sequence number used is stored in *rdata_out* . + + + +Use krb5_free_data_contents() to free *der_out* when it is no longer needed. + + + +The message will be encrypted using the send subkey of *auth_context* if it is present, or the session key otherwise. If neither key is present, the credentials will not be encrypted, and the message should only be sent over a secure channel. No replay cache entry is used in this case. + + + + + + + + + + +.. + + + + + + +.. note:: + + The *rdata_out* argument is required if the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in *auth_context* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_priv.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_priv.rst.txt new file mode 100644 index 00000000..0d9922ec --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_priv.rst.txt @@ -0,0 +1,79 @@ +krb5_mk_priv - Format a KRB-PRIV message. +=========================================== + +.. + +.. c:function:: krb5_error_code krb5_mk_priv(krb5_context context, krb5_auth_context auth_context, const krb5_data * userdata, krb5_data * der_out, krb5_replay_data * rdata_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **userdata** - User data for **KRB-PRIV** message + + **[out]** **der_out** - Formatted **KRB-PRIV** message + + **[out]** **rdata_out** - Replay data (NULL if not needed) + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function is similar to krb5_mk_safe(), but the message is encrypted and integrity-protected, not just integrity-protected. + + + +The local address in *auth_context* must be set, and is used to form the sender address used in the KRB-PRIV message. The remote address is optional; if specified, it will be used to form the receiver address used in the message. + + + +If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in *auth_context* , a timestamp is included in the KRB-PRIV message, and an entry for the message is entered in an in-memory replay cache to detect if the message is reflected by an attacker. If #KRB5_AUTH_CONTEXT_DO_TIME is not set, no replay cache is used. If #KRB5_AUTH_CONTEXT_RET_TIME is set in *auth_context* , a timestamp is included in the KRB-PRIV message and is stored in *rdata_out* . + + + +If either #KRB5_AUTH_CONTEXT_DO_SEQUENCE or #KRB5_AUTH_CONTEXT_RET_SEQUENCE is set, the *auth_context* local sequence number is included in the KRB-PRIV message and then incremented. If #KRB5_AUTH_CONTEXT_RET_SEQUENCE is set, the sequence number used is stored in *rdata_out* . + + + +Use krb5_free_data_contents() to free *der_out* when it is no longer needed. + + + + + + + + + + +.. + + + + + + +.. note:: + + The *rdata_out* argument is required if the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in *auth_context* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_rep.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_rep.rst.txt new file mode 100644 index 00000000..29091a1b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_rep.rst.txt @@ -0,0 +1,59 @@ +krb5_mk_rep - Format and encrypt a KRB_AP_REP message. +======================================================== + +.. + +.. c:function:: krb5_error_code krb5_mk_rep(krb5_context context, krb5_auth_context auth_context, krb5_data * outbuf) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[out]** **outbuf** - **AP-REP** message + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function fills in *outbuf* with an AP-REP message using information from *auth_context* . + + + +If the flags in *auth_context* indicate that a sequence number should be used (either #KRB5_AUTH_CONTEXT_DO_SEQUENCE or #KRB5_AUTH_CONTEXT_RET_SEQUENCE) and the local sequence number in *auth_context* is 0, a new number will be generated with krb5_generate_seq_number(). + + + +Use krb5_free_data_contents() to free *outbuf* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_rep_dce.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_rep_dce.rst.txt new file mode 100644 index 00000000..31cc1828 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_rep_dce.rst.txt @@ -0,0 +1,51 @@ +krb5_mk_rep_dce - Format and encrypt a KRB_AP_REP message for DCE RPC. +======================================================================== + +.. + +.. c:function:: krb5_error_code krb5_mk_rep_dce(krb5_context context, krb5_auth_context auth_context, krb5_data * outbuf) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[out]** **outbuf** - **AP-REP** message + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Use krb5_free_data_contents() to free *outbuf* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_req.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_req.rst.txt new file mode 100644 index 00000000..08033bbd --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_req.rst.txt @@ -0,0 +1,65 @@ +krb5_mk_req - Create a KRB_AP_REQ message. +============================================ + +.. + +.. c:function:: krb5_error_code krb5_mk_req(krb5_context context, krb5_auth_context * auth_context, krb5_flags ap_req_options, const char * service, const char * hostname, krb5_data * in_data, krb5_ccache ccache, krb5_data * outbuf) + +.. + + +:param: + + **[in]** **context** - Library context + + **[inout]** **auth_context** - Pre-existing or newly created auth context + + **[in]** **ap_req_options** - Options (see AP_OPTS macros) + + **[in]** **service** - Service name, or NULL to use **"host"** + + **[in]** **hostname** - Host name, or NULL to use local hostname + + **[in]** **in_data** - Application data to be checksummed in the authenticator, or NULL + + **[in]** **ccache** - Credential cache used to obtain credentials for the desired service. + + **[out]** **outbuf** - **AP-REQ** message + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function is similar to krb5_mk_req_extended() except that it uses a given *hostname* , *service* , and *ccache* to construct a service principal name and obtain credentials. + + + +Use krb5_free_data_contents() to free *outbuf* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_req_extended.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_req_extended.rst.txt new file mode 100644 index 00000000..532af977 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_req_extended.rst.txt @@ -0,0 +1,74 @@ +krb5_mk_req_extended - Create a KRB_AP_REQ message using supplied credentials. +================================================================================ + +.. + +.. c:function:: krb5_error_code krb5_mk_req_extended(krb5_context context, krb5_auth_context * auth_context, krb5_flags ap_req_options, krb5_data * in_data, krb5_creds * in_creds, krb5_data * outbuf) + +.. + + +:param: + + **[in]** **context** - Library context + + **[inout]** **auth_context** - Pre-existing or newly created auth context + + **[in]** **ap_req_options** - Options (see AP_OPTS macros) + + **[in]** **in_data** - Application data to be checksummed in the authenticator, or NULL + + **[in]** **in_creds** - Credentials for the service with valid ticket and key + + **[out]** **outbuf** - **AP-REQ** message + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Valid *ap_req_options* are: + + - #AP_OPTS_USE_SESSION_KEY - Use the session key when creating the request used for user to user authentication. + + + - #AP_OPTS_MUTUAL_REQUIRED - Request a mutual authentication packet from the receiver. + + + - #AP_OPTS_USE_SUBKEY - Generate a subsession key from the current session key obtained from the credentials. + + This function creates a KRB_AP_REQ message using supplied credentials *in_creds* . *auth_context* may point to an existing auth context or to NULL, in which case a new one will be created. If *in_data* is non-null, a checksum of it will be included in the authenticator contained in the KRB_AP_REQ message. Use krb5_free_data_contents() to free *outbuf* when it is no longer needed. + + + +On successful return, the authenticator is stored in *auth_context* with the *client* and *checksum* fields nulled out. (This is to prevent pointer-sharing problems; the caller should not need these fields anyway, since the caller supplied them.) + + + + + + + + + + +.. + +.. seealso:: + krb5_mk_req() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_safe.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_safe.rst.txt new file mode 100644 index 00000000..f9a67be4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_mk_safe.rst.txt @@ -0,0 +1,83 @@ +krb5_mk_safe - Format a KRB-SAFE message. +=========================================== + +.. + +.. c:function:: krb5_error_code krb5_mk_safe(krb5_context context, krb5_auth_context auth_context, const krb5_data * userdata, krb5_data * der_out, krb5_replay_data * rdata_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **userdata** - User data in the message + + **[out]** **der_out** - Formatted **KRB-SAFE** buffer + + **[out]** **rdata_out** - Replay data. Specify NULL if not needed + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function creates an integrity protected **KRB-SAFE** message using data supplied by the application. + + + +Fields in *auth_context* specify the checksum type, the keyblock that can be used to seed the checksum, full addresses (host and port) for the sender and receiver, and KRB5_AUTH_CONTEXT flags. + + + +The local address in *auth_context* must be set, and is used to form the sender address used in the KRB-SAFE message. The remote address is optional; if specified, it will be used to form the receiver address used in the message. + + + +If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in *auth_context* , a timestamp is included in the KRB-SAFE message, and an entry for the message is entered in an in-memory replay cache to detect if the message is reflected by an attacker. If #KRB5_AUTH_CONTEXT_DO_TIME is not set, no replay cache is used. If #KRB5_AUTH_CONTEXT_RET_TIME is set in *auth_context* , a timestamp is included in the KRB-SAFE message and is stored in *rdata_out* . + + + +If either #KRB5_AUTH_CONTEXT_DO_SEQUENCE or #KRB5_AUTH_CONTEXT_RET_SEQUENCE is set, the *auth_context* local sequence number is included in the KRB-SAFE message and then incremented. If #KRB5_AUTH_CONTEXT_RET_SEQUENCE is set, the sequence number used is stored in *rdata_out* . + + + +Use krb5_free_data_contents() to free *der_out* when it is no longer needed. + + + + + + + + + + +.. + + + + + + +.. note:: + + The *rdata_out* argument is required if the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in *auth_context* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_os_localaddr.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_os_localaddr.rst.txt new file mode 100644 index 00000000..e0b01ff5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_os_localaddr.rst.txt @@ -0,0 +1,49 @@ +krb5_os_localaddr - Return all interface addresses for this host. +=================================================================== + +.. + +.. c:function:: krb5_error_code krb5_os_localaddr(krb5_context context, krb5_address *** addr) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **addr** - Array of krb5_address pointers, ending with NULL + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Use krb5_free_addresses() to free *addr* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_add_buffer.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_add_buffer.rst.txt new file mode 100644 index 00000000..4c153c23 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_add_buffer.rst.txt @@ -0,0 +1,75 @@ +krb5_pac_add_buffer - Add a buffer to a PAC handle. +===================================================== + +.. + +.. c:function:: krb5_error_code krb5_pac_add_buffer(krb5_context context, krb5_pac pac, krb5_ui_4 type, const krb5_data * data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **pac** - PAC handle + + **[in]** **type** - Buffer type + + **[in]** **data** - contents + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function adds a buffer of type *type* and contents *data* to *pac* if there isn't already a buffer of this type present. + + + +The valid values of *type* is one of the following: + + - #KRB5_PAC_LOGON_INFO - Logon information + + + - #KRB5_PAC_CREDENTIALS_INFO - Credentials information + + + - #KRB5_PAC_SERVER_CHECKSUM - Server checksum + + + - #KRB5_PAC_PRIVSVR_CHECKSUM - KDC checksum + + + - #KRB5_PAC_CLIENT_INFO - Client name and ticket information + + + - #KRB5_PAC_DELEGATION_INFO - Constrained delegation information + + + - #KRB5_PAC_UPN_DNS_INFO - User principal name and DNS information + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_free.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_free.rst.txt new file mode 100644 index 00000000..9b204bef --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_free.rst.txt @@ -0,0 +1,42 @@ +krb5_pac_free - Free a PAC handle. +==================================== + +.. + +.. c:function:: void krb5_pac_free(krb5_context context, krb5_pac pac) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **pac** - PAC to be freed + + +.. + + + +.. + + + + + + + +This function frees the contents of *pac* and the structure itself. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_get_buffer.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_get_buffer.rst.txt new file mode 100644 index 00000000..b4361f9b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_get_buffer.rst.txt @@ -0,0 +1,53 @@ +krb5_pac_get_buffer - Retrieve a buffer value from a PAC. +=========================================================== + +.. + +.. c:function:: krb5_error_code krb5_pac_get_buffer(krb5_context context, krb5_pac pac, krb5_ui_4 type, krb5_data * data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **pac** - PAC handle + + **[in]** **type** - Type of buffer to retrieve + + **[out]** **data** - Buffer value + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Use krb5_free_data_contents() to free *data* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_get_client_info.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_get_client_info.rst.txt new file mode 100644 index 00000000..4c628c46 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_get_client_info.rst.txt @@ -0,0 +1,57 @@ +krb5_pac_get_client_info - Read client information from a PAC. +================================================================ + +.. + +.. c:function:: krb5_error_code krb5_pac_get_client_info(krb5_context context, const krb5_pac pac, krb5_timestamp * authtime_out, char ** princname_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **pac** - PAC handle + + **[out]** **authtime_out** - Authentication timestamp (NULL if not needed) + + **[out]** **princname_out** - Client account name + + +.. + + +:retval: + - 0 on success, ENOENT if no PAC_CLIENT_INFO buffer is present in pac , ERANGE if the buffer contains invalid lengths. + + +.. + + + + + + + +Read the PAC_CLIENT_INFO buffer in *pac* . Place the client account name as a string in *princname_out* . If *authtime_out* is not NULL, place the initial authentication timestamp in *authtime_out* . + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.18 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_get_types.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_get_types.rst.txt new file mode 100644 index 00000000..bce3b2c8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_get_types.rst.txt @@ -0,0 +1,49 @@ +krb5_pac_get_types - Return an array of buffer types in a PAC handle. +======================================================================= + +.. + +.. c:function:: krb5_error_code krb5_pac_get_types(krb5_context context, krb5_pac pac, size_t * len, krb5_ui_4 ** types) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **pac** - PAC handle + + **[out]** **len** - Number of entries in *types* + + **[out]** **types** - Array of buffer types + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_init.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_init.rst.txt new file mode 100644 index 00000000..d4a248bc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_init.rst.txt @@ -0,0 +1,49 @@ +krb5_pac_init - Create an empty Privilege Attribute Certificate (PAC) handle. +=============================================================================== + +.. + +.. c:function:: krb5_error_code krb5_pac_init(krb5_context context, krb5_pac * pac) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **pac** - New PAC handle + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Use krb5_pac_free() to free *pac* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_parse.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_parse.rst.txt new file mode 100644 index 00000000..e770e929 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_parse.rst.txt @@ -0,0 +1,53 @@ +krb5_pac_parse - Unparse an encoded PAC into a new handle. +============================================================ + +.. + +.. c:function:: krb5_error_code krb5_pac_parse(krb5_context context, const void * ptr, size_t len, krb5_pac * pac) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ptr** - PAC buffer + + **[in]** **len** - Length of *ptr* + + **[out]** **pac** - PAC handle + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Use krb5_pac_free() to free *pac* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_sign.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_sign.rst.txt new file mode 100644 index 00000000..9b2499a8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_sign.rst.txt @@ -0,0 +1,54 @@ +krb5_pac_sign +============= + +.. + +.. c:function:: krb5_error_code krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime, krb5_const_principal principal, const krb5_keyblock * server_key, const krb5_keyblock * privsvr_key, krb5_data * data) + +.. + + +:param: + + **context** + + **pac** + + **authtime** + + **principal** + + **server_key** + + **privsvr_key** + + **data** + + +.. + + + +.. + + +DEPRECATED Use krb5_kdc_sign_ticket() instead. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_sign_ext.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_sign_ext.rst.txt new file mode 100644 index 00000000..46f1552b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_sign_ext.rst.txt @@ -0,0 +1,56 @@ +krb5_pac_sign_ext +================= + +.. + +.. c:function:: krb5_error_code krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, krb5_const_principal principal, const krb5_keyblock * server_key, const krb5_keyblock * privsvr_key, krb5_boolean with_realm, krb5_data * data) + +.. + + +:param: + + **context** + + **pac** + + **authtime** + + **principal** + + **server_key** + + **privsvr_key** + + **with_realm** + + **data** + + +.. + + + +.. + + +DEPRECATED Use krb5_kdc_sign_ticket() instead. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_verify.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_verify.rst.txt new file mode 100644 index 00000000..338b43a1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_verify.rst.txt @@ -0,0 +1,69 @@ +krb5_pac_verify - Verify a PAC. +================================= + +.. + +.. c:function:: krb5_error_code krb5_pac_verify(krb5_context context, const krb5_pac pac, krb5_timestamp authtime, krb5_const_principal principal, const krb5_keyblock * server, const krb5_keyblock * privsvr) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **pac** - PAC handle + + **[in]** **authtime** - Expected timestamp + + **[in]** **principal** - Expected principal name (or NULL) + + **[in]** **server** - Key to validate server checksum (or NULL) + + **[in]** **privsvr** - Key to validate KDC checksum (or NULL) + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function validates *pac* against the supplied *server* , *privsvr* , *principal* and *authtime* . If *principal* is NULL, the principal and authtime are not verified. If *server* or *privsvr* is NULL, the corresponding checksum is not verified. + + + +If successful, *pac* is marked as verified. + + + + + + + + + + +.. + + + + + + +.. note:: + + A checksum mismatch can occur if the PAC was copied from a cross-realm TGT by an ignorant KDC; also macOS Server Open Directory (as of 10.6) generates PACs with no server checksum at all. One should consider not failing the whole authentication because of this reason, but, instead, treating the ticket as if it did not contain a PAC or marking the PAC information as non-verified. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_verify_ext.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_verify_ext.rst.txt new file mode 100644 index 00000000..41ffcdf6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_pac_verify_ext.rst.txt @@ -0,0 +1,60 @@ +krb5_pac_verify_ext - Verify a PAC, possibly from a specified realm. +====================================================================== + +.. + +.. c:function:: krb5_error_code krb5_pac_verify_ext(krb5_context context, const krb5_pac pac, krb5_timestamp authtime, krb5_const_principal principal, const krb5_keyblock * server, const krb5_keyblock * privsvr, krb5_boolean with_realm) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **pac** - PAC handle + + **[in]** **authtime** - Expected timestamp + + **[in]** **principal** - Expected principal name (or NULL) + + **[in]** **server** - Key to validate server checksum (or NULL) + + **[in]** **privsvr** - Key to validate KDC checksum (or NULL) + + **[in]** **with_realm** - If true, expect the realm of *principal* + + +.. + + + +.. + + + + + + + +This function is similar to krb5_pac_verify(), but adds a parameter *with_realm* . If *with_realm* is true, the PAC_CLIENT_INFO field is expected to include the realm of *principal* as well as the name. This flag is necessary to verify PACs in cross-realm S4U2Self referral TGTs. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.17 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_parse_name.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_parse_name.rst.txt new file mode 100644 index 00000000..835337d4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_parse_name.rst.txt @@ -0,0 +1,78 @@ +krb5_parse_name - Convert a string principal name to a krb5_principal structure. +================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_parse_name(krb5_context context, const char * name, krb5_principal * principal_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **name** - String representation of a principal name + + **[out]** **principal_out** - New principal + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Convert a string representation of a principal name to a krb5_principal structure. + + + +A string representation of a Kerberos name consists of one or more principal name components, separated by slashes, optionally followed by the @ character and a realm name. If the realm name is not specified, the local realm is used. + + + +To use the slash and @ symbols as part of a component (quoted) instead of using them as a component separator or as a realm prefix), put a backslash () character in front of the symbol. Similarly, newline, tab, backspace, and NULL characters can be included in a component by using **n** , **t** , **b** or **0** , respectively. + + + +Beginning with release 1.20, the name type of the principal will be inferred as **KRB5_NT_SRV_INST** or **KRB5_NT_WELLKNOWN** based on the principal name. The type will be **KRB5_NT_PRINCIPAL** if a type cannot be inferred. + + + +Use krb5_free_principal() to free *principal_out* when it is no longer needed. + + + + + + + + + + +.. + + + + + + +.. note:: + + The realm in a Kerberos *name* cannot contain slash, colon, or NULL characters. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_parse_name_flags.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_parse_name_flags.rst.txt new file mode 100644 index 00000000..68cbc7c5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_parse_name_flags.rst.txt @@ -0,0 +1,77 @@ +krb5_parse_name_flags - Convert a string principal name to a krb5_principal with flags. +========================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_parse_name_flags(krb5_context context, const char * name, int flags, krb5_principal * principal_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **name** - String representation of a principal name + + **[in]** **flags** - Flag + + **[out]** **principal_out** - New principal + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Similar to krb5_parse_name(), this function converts a single-string representation of a principal name to a krb5_principal structure. + + + +The following flags are valid: + + - #KRB5_PRINCIPAL_PARSE_NO_REALM - no realm must be present in *name* + + + - #KRB5_PRINCIPAL_PARSE_REQUIRE_REALM - realm must be present in *name* + + + - #KRB5_PRINCIPAL_PARSE_ENTERPRISE - create single-component enterprise principal + + + - #KRB5_PRINCIPAL_PARSE_IGNORE_REALM - ignore realm if present in *name* + + If **KRB5_PRINCIPAL_PARSE_NO_REALM** or **KRB5_PRINCIPAL_PARSE_IGNORE_REALM** is specified in *flags* , the realm of the new principal will be empty. Otherwise, the default realm for *context* will be used if *name* does not specify a realm. + + + +Use krb5_free_principal() to free *principal_out* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_prepend_error_message.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_prepend_error_message.rst.txt new file mode 100644 index 00000000..6503ab16 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_prepend_error_message.rst.txt @@ -0,0 +1,44 @@ +krb5_prepend_error_message - Add a prefix to the message for an error code. +============================================================================= + +.. + +.. c:function:: void krb5_prepend_error_message(krb5_context ctx, krb5_error_code code, const char * fmt, ... ) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **code** - Error code + + **[in]** **fmt** - Format string for error message prefix + + +.. + + + +.. + + + + + + + +Format a message and prepend it to the current message for *code* . The prefix will be separated from the old message with a colon and space. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal2salt.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal2salt.rst.txt new file mode 100644 index 00000000..ff0f3416 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal2salt.rst.txt @@ -0,0 +1,47 @@ +krb5_principal2salt - Convert a principal name into the default salt for that principal. +========================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_principal2salt(krb5_context context, krb5_const_principal pr, krb5_data * ret) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **pr** - Principal name + + **[out]** **ret** - Default salt for *pr* to be filled in + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal_compare.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal_compare.rst.txt new file mode 100644 index 00000000..269efe31 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal_compare.rst.txt @@ -0,0 +1,47 @@ +krb5_principal_compare - Compare two principals. +================================================== + +.. + +.. c:function:: krb5_boolean krb5_principal_compare(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **princ1** - First principal + + **[in]** **princ2** - Second principal + + +.. + + +:retval: + - TRUE if the principals are the same; FALSE otherwise + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal_compare_any_realm.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal_compare_any_realm.rst.txt new file mode 100644 index 00000000..72c02a66 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal_compare_any_realm.rst.txt @@ -0,0 +1,51 @@ +krb5_principal_compare_any_realm - Compare two principals ignoring realm components. +====================================================================================== + +.. + +.. c:function:: krb5_boolean krb5_principal_compare_any_realm(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **princ1** - First principal + + **[in]** **princ2** - Second principal + + +.. + + +:retval: + - TRUE if the principals are the same; FALSE otherwise + + +.. + + + + + + + +Similar to krb5_principal_compare(), but do not compare the realm components of the principals. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal_compare_flags.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal_compare_flags.rst.txt new file mode 100644 index 00000000..df8fc5bd --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_principal_compare_flags.rst.txt @@ -0,0 +1,65 @@ +krb5_principal_compare_flags - Compare two principals with additional flags. +============================================================================== + +.. + +.. c:function:: krb5_boolean krb5_principal_compare_flags(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2, int flags) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **princ1** - First principal + + **[in]** **princ2** - Second principal + + **[in]** **flags** - Flags + + +.. + + +:retval: + - TRUE if the principal names are the same; FALSE otherwise + + +.. + + + + + + + +Valid flags are: + + - #KRB5_PRINCIPAL_COMPARE_IGNORE_REALM - ignore realm component + + + - #KRB5_PRINCIPAL_COMPARE_ENTERPRISE - UPNs as real principals + + + - #KRB5_PRINCIPAL_COMPARE_CASEFOLD case-insensitive + + + - #KRB5_PRINCIPAL_COMPARE_UTF8 - treat principals as UTF-8 + + + + + + + + +.. + +.. seealso:: + krb5_principal_compare() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_process_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_process_key.rst.txt new file mode 100644 index 00000000..3d08b5dc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_process_key.rst.txt @@ -0,0 +1,46 @@ +krb5_process_key +================ + +.. + +.. c:function:: krb5_error_code krb5_process_key(krb5_context context, krb5_encrypt_block * eblock, const krb5_keyblock * key) + +.. + + +:param: + + **context** + + **eblock** + + **key** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_c_* API family. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_prompter_posix.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_prompter_posix.rst.txt new file mode 100644 index 00000000..b4012cac --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_prompter_posix.rst.txt @@ -0,0 +1,64 @@ +krb5_prompter_posix - Prompt user for password. +================================================= + +.. + +.. c:function:: krb5_error_code krb5_prompter_posix(krb5_context context, void * data, const char * name, const char * banner, int num_prompts, krb5_prompt prompts) + +.. + + +:param: + + **[in]** **context** - Library context + + **data** - Unused (callback argument) + + **[in]** **name** - Name to output during prompt + + **[in]** **banner** - Banner to output during prompt + + **[in]** **num_prompts** - Number of prompts in *prompts* + + **[in]** **prompts** - Array of prompts and replies + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function is intended to be used as a prompter callback for krb5_get_init_creds_password() or krb5_init_creds_init(). + + + +Writes *name* and *banner* to stdout, each followed by a newline, then writes each prompt field in the *prompts* array, followed by":", and sets the reply field of the entry to a line of input read from stdin. If the hidden flag is set for a prompt, then terminal echoing is turned off when input is read. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_random_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_random_key.rst.txt new file mode 100644 index 00000000..d8e81ba3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_random_key.rst.txt @@ -0,0 +1,48 @@ +krb5_random_key +=============== + +.. + +.. c:function:: krb5_error_code krb5_random_key(krb5_context context, const krb5_encrypt_block * eblock, krb5_pointer ptr, krb5_keyblock ** keyblock) + +.. + + +:param: + + **context** + + **eblock** + + **ptr** + + **keyblock** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_c_* API family. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_cred.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_cred.rst.txt new file mode 100644 index 00000000..556a2604 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_cred.rst.txt @@ -0,0 +1,67 @@ +krb5_rd_cred - Read and validate a KRB-CRED message. +====================================================== + +.. + +.. c:function:: krb5_error_code krb5_rd_cred(krb5_context context, krb5_auth_context auth_context, krb5_data * creddata, krb5_creds *** creds_out, krb5_replay_data * rdata_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **creddata** - **KRB-CRED** message + + **[out]** **creds_out** - Null-terminated array of forwarded credentials + + **[out]** **rdata_out** - Replay data (NULL if not needed) + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + *creddata* will be decrypted using the receiving subkey if it is present in *auth_context* , or the session key if the receiving subkey is not present or fails to decrypt the message. + + + +Use krb5_free_tgt_creds() to free *creds_out* when it is no longer needed. + + + + + + + + + + +.. + + + + + + +.. note:: + + The *rdata_out* argument is required if the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in *auth_context* .` + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_error.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_error.rst.txt new file mode 100644 index 00000000..a748a620 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_error.rst.txt @@ -0,0 +1,51 @@ +krb5_rd_error - Decode a KRB-ERROR message. +============================================= + +.. + +.. c:function:: krb5_error_code krb5_rd_error(krb5_context context, const krb5_data * enc_errbuf, krb5_error ** dec_error) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **enc_errbuf** - Encoded error message + + **[out]** **dec_error** - Decoded error message + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function processes **KRB-ERROR** message *enc_errbuf* and returns an allocated structure *dec_error* containing the error message. Use krb5_free_error() to free *dec_error* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_priv.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_priv.rst.txt new file mode 100644 index 00000000..f2690f41 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_priv.rst.txt @@ -0,0 +1,79 @@ +krb5_rd_priv - Process a KRB-PRIV message. +============================================ + +.. + +.. c:function:: krb5_error_code krb5_rd_priv(krb5_context context, krb5_auth_context auth_context, const krb5_data * inbuf, krb5_data * userdata_out, krb5_replay_data * rdata_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication structure + + **[in]** **inbuf** - **KRB-PRIV** message to be parsed + + **[out]** **userdata_out** - Data parsed from **KRB-PRIV** message + + **[out]** **rdata_out** - Replay data. Specify NULL if not needed + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function parses a **KRB-PRIV** message, verifies its integrity, and stores its unencrypted data into *userdata_out* . + + + +If *auth_context* has a remote address set, the address will be used to verify the sender address in the KRB-PRIV message. If *auth_context* has a local address set, it will be used to verify the receiver address in the KRB-PRIV message if the message contains one. + + + +If the #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag is set in *auth_context* , the sequence number of the KRB-PRIV message is checked against the remote sequence number field of *auth_context* . Otherwise, the sequence number is not used. + + + +If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in *auth_context* , then the timestamp in the message is verified to be within the permitted clock skew of the current time, and the message is checked against an in-memory replay cache to detect reflections or replays. + + + +Use krb5_free_data_contents() to free *userdata_out* when it is no longer needed. + + + + + + + + + + +.. + + + + + + +.. note:: + + The *rdata_out* argument is required if the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in *auth_context* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_rep.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_rep.rst.txt new file mode 100644 index 00000000..e2acba84 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_rep.rst.txt @@ -0,0 +1,57 @@ +krb5_rd_rep - Parse and decrypt a KRB_AP_REP message. +======================================================= + +.. + +.. c:function:: krb5_error_code krb5_rd_rep(krb5_context context, krb5_auth_context auth_context, const krb5_data * inbuf, krb5_ap_rep_enc_part ** repl) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **inbuf** - AP-REP message + + **[out]** **repl** - Decrypted reply message + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function parses, decrypts and verifies a message from *inbuf* and fills in *repl* with a pointer to allocated memory containing the fields from the encrypted response. + + + +Use krb5_free_ap_rep_enc_part() to free *repl* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_rep_dce.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_rep_dce.rst.txt new file mode 100644 index 00000000..c82ef431 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_rep_dce.rst.txt @@ -0,0 +1,53 @@ +krb5_rd_rep_dce - Parse and decrypt a KRB_AP_REP message for DCE RPC. +======================================================================= + +.. + +.. c:function:: krb5_error_code krb5_rd_rep_dce(krb5_context context, krb5_auth_context auth_context, const krb5_data * inbuf, krb5_ui_4 * nonce) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **inbuf** - AP-REP message + + **[out]** **nonce** - Sequence number from the decrypted reply + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function parses, decrypts and verifies a message from *inbuf* and fills in *nonce* with a decrypted reply sequence number. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_req.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_req.rst.txt new file mode 100644 index 00000000..e5b9d73c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_req.rst.txt @@ -0,0 +1,105 @@ +krb5_rd_req - Parse and decrypt a KRB_AP_REQ message. +======================================================= + +.. + +.. c:function:: krb5_error_code krb5_rd_req(krb5_context context, krb5_auth_context * auth_context, const krb5_data * inbuf, krb5_const_principal server, krb5_keytab keytab, krb5_flags * ap_req_options, krb5_ticket ** ticket) + +.. + + +:param: + + **[in]** **context** - Library context + + **[inout]** **auth_context** - Pre-existing or newly created auth context + + **[in]** **inbuf** - AP-REQ message to be parsed + + **[in]** **server** - Matching principal for server, or NULL to allow any principal in keytab + + **[in]** **keytab** - Key table, or NULL to use the default + + **[out]** **ap_req_options** - If non-null, the AP-REQ flags on output + + **[out]** **ticket** - If non-null, ticket from the AP-REQ message + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function parses, decrypts and verifies a AP-REQ message from *inbuf* and stores the authenticator in *auth_context* . + + + +If a keyblock was specified in *auth_context* using krb5_auth_con_setuseruserkey(), that key is used to decrypt the ticket in AP-REQ message and *keytab* is ignored. In this case, *server* should be specified as a complete principal name to allow for proper transited-path checking and replay cache selection. + + + +Otherwise, the decryption key is obtained from *keytab* , or from the default keytab if it is NULL. In this case, *server* may be a complete principal name, a matching principal (see krb5_sname_match()), or NULL to match any principal name. The keys tried against the encrypted part of the ticket are determined as follows: + + + + + + - If *server* is a complete principal name, then its entry in *keytab* is tried. + + + - Otherwise, if *keytab* is iterable, then all entries in *keytab* which match *server* are tried. + + + - Otherwise, the server principal in the ticket must match *server* , and its entry in *keytab* is tried. + + + + + +The client specified in the decrypted authenticator must match the client specified in the decrypted ticket. + + + +If the *remote_addr* field of *auth_context* is set, the request must come from that address. + + + +If a replay cache handle is provided in the *auth_context* , the authenticator and ticket are verified against it. If no conflict is found, the new authenticator is then stored in the replay cache of *auth_context* . + + + +Various other checks are performed on the decoded data, including cross-realm policy, clockskew, and ticket validation times. + + + +On success the authenticator, subkey, and remote sequence number of the request are stored in *auth_context* . If the #AP_OPTS_MUTUAL_REQUIRED bit is set, the local sequence number is XORed with the remote sequence number in the request. + + + +Use krb5_free_ticket() to free *ticket* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_safe.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_safe.rst.txt new file mode 100644 index 00000000..5166c550 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_rd_safe.rst.txt @@ -0,0 +1,79 @@ +krb5_rd_safe - Process KRB-SAFE message. +========================================== + +.. + +.. c:function:: krb5_error_code krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, const krb5_data * inbuf, krb5_data * userdata_out, krb5_replay_data * rdata_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **auth_context** - Authentication context + + **[in]** **inbuf** - **KRB-SAFE** message to be parsed + + **[out]** **userdata_out** - Data parsed from **KRB-SAFE** message + + **[out]** **rdata_out** - Replay data. Specify NULL if not needed + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function parses a **KRB-SAFE** message, verifies its integrity, and stores its data into *userdata_out* . + + + +If *auth_context* has a remote address set, the address will be used to verify the sender address in the KRB-SAFE message. If *auth_context* has a local address set, it will be used to verify the receiver address in the KRB-SAFE message if the message contains one. + + + +If the #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag is set in *auth_context* , the sequence number of the KRB-SAFE message is checked against the remote sequence number field of *auth_context* . Otherwise, the sequence number is not used. + + + +If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in *auth_context* , then the timestamp in the message is verified to be within the permitted clock skew of the current time, and the message is checked against an in-memory replay cache to detect reflections or replays. + + + +Use krb5_free_data_contents() to free *userdata_out* when it is no longer needed. + + + + + + + + + + +.. + + + + + + +.. note:: + + The *rdata_out* argument is required if the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in *auth_context* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_read_password.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_read_password.rst.txt new file mode 100644 index 00000000..877fe6e6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_read_password.rst.txt @@ -0,0 +1,71 @@ +krb5_read_password - Read a password from keyboard input. +=========================================================== + +.. + +.. c:function:: krb5_error_code krb5_read_password(krb5_context context, const char * prompt, const char * prompt2, char * return_pwd, unsigned int * size_return) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **prompt** - First user prompt when reading password + + **[in]** **prompt2** - Second user prompt (NULL to prompt only once) + + **[out]** **return_pwd** - Returned password + + **[inout]** **size_return** - On input, maximum size of password; on output, size of password read + + +.. + + +:retval: + - 0 Success + + +:return: + - Error in reading or verifying the password + - Kerberos error codes + +.. + + + + + + + +This function reads a password from keyboard input and stores it in *return_pwd* . *size_return* should be set by the caller to the amount of storage space available in *return_pwd* ; on successful return, it will be set to the length of the password read. + + + + *prompt* is printed to the terminal, followed by":", and then a password is read from the keyboard. + + + +If *prompt2* is NULL, the password is read only once. Otherwise, *prompt2* is printed to the terminal and a second password is read. If the two passwords entered are not identical, KRB5_LIBOS_BADPWDMATCH is returned. + + + +Echoing is turned off when the password is read. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_realm_compare.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_realm_compare.rst.txt new file mode 100644 index 00000000..f9df1b02 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_realm_compare.rst.txt @@ -0,0 +1,47 @@ +krb5_realm_compare - Compare the realms of two principals. +============================================================ + +.. + +.. c:function:: krb5_boolean krb5_realm_compare(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **princ1** - First principal + + **[in]** **princ2** - Second principal + + +.. + + +:retval: + - TRUE if the realm names are the same; FALSE otherwise + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_recvauth.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_recvauth.rst.txt new file mode 100644 index 00000000..0cc70cf8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_recvauth.rst.txt @@ -0,0 +1,68 @@ +krb5_recvauth - Server function for sendauth protocol. +======================================================== + +.. + +.. c:function:: krb5_error_code krb5_recvauth(krb5_context context, krb5_auth_context * auth_context, krb5_pointer fd, char * appl_version, krb5_principal server, krb5_int32 flags, krb5_keytab keytab, krb5_ticket ** ticket) + +.. + + +:param: + + **[in]** **context** - Library context + + **[inout]** **auth_context** - Pre-existing or newly created auth context + + **[in]** **fd** - File descriptor + + **[in]** **appl_version** - Application protocol version to be matched against the client's application version + + **[in]** **server** - Server principal (NULL for any in *keytab* ) + + **[in]** **flags** - Additional specifications + + **[in]** **keytab** - Key table containing service keys + + **[out]** **ticket** - Ticket (NULL if not needed) + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function performs the server side of a sendauth/recvauth exchange by sending and receiving messages over *fd* . + + + +Use krb5_free_ticket() to free *ticket* when it is no longer needed. + + + + + + + + + + +.. + +.. seealso:: + krb5_sendauth() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_recvauth_version.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_recvauth_version.rst.txt new file mode 100644 index 00000000..4ec26ab0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_recvauth_version.rst.txt @@ -0,0 +1,61 @@ +krb5_recvauth_version - Server function for sendauth protocol with version parameter. +======================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_recvauth_version(krb5_context context, krb5_auth_context * auth_context, krb5_pointer fd, krb5_principal server, krb5_int32 flags, krb5_keytab keytab, krb5_ticket ** ticket, krb5_data * version) + +.. + + +:param: + + **[in]** **context** - Library context + + **[inout]** **auth_context** - Pre-existing or newly created auth context + + **[in]** **fd** - File descriptor + + **[in]** **server** - Server principal (NULL for any in *keytab* ) + + **[in]** **flags** - Additional specifications + + **[in]** **keytab** - Decryption key + + **[out]** **ticket** - Ticket (NULL if not needed) + + **[out]** **version** - sendauth protocol version (NULL if not needed) + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function is similar to krb5_recvauth() with the additional output information place into *version* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_get_challenge.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_get_challenge.rst.txt new file mode 100644 index 00000000..ae1edc9a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_get_challenge.rst.txt @@ -0,0 +1,52 @@ +krb5_responder_get_challenge - Retrieve the challenge data for a given question in the responder context. +=========================================================================================================== + +.. + +.. c:function:: const char * krb5_responder_get_challenge(krb5_context ctx, krb5_responder_context rctx, const char * question) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **rctx** - Responder context + + **[in]** **question** - Question name + + +.. + + + +.. + + + + + + + +Return a pointer to a C string containing the challenge for *question* within *rctx* , or NULL if the question is not present in *rctx* . The structure of the question depends on the question name, but will always be printable UTF-8 text. The returned pointer is an alias, valid only as long as the lifetime of *rctx* , and should not be modified or freed by the caller. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.11 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_list_questions.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_list_questions.rst.txt new file mode 100644 index 00000000..03491ced --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_list_questions.rst.txt @@ -0,0 +1,50 @@ +krb5_responder_list_questions - List the question names contained in the responder context. +============================================================================================= + +.. + +.. c:function:: const char *const * krb5_responder_list_questions(krb5_context ctx, krb5_responder_context rctx) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **rctx** - Responder context + + +.. + + + +.. + + + + + + + +Return a pointer to a null-terminated list of question names which are present in *rctx* . The pointer is an alias, valid only as long as the lifetime of *rctx* , and should not be modified or freed by the caller. A question's challenge can be retrieved using krb5_responder_get_challenge() and answered using krb5_responder_set_answer(). + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.11 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_otp_challenge_free.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_otp_challenge_free.rst.txt new file mode 100644 index 00000000..a92db44d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_otp_challenge_free.rst.txt @@ -0,0 +1,48 @@ +krb5_responder_otp_challenge_free - Free the value returned by krb5_responder_otp_get_challenge(). +==================================================================================================== + +.. + +.. c:function:: void krb5_responder_otp_challenge_free(krb5_context ctx, krb5_responder_context rctx, krb5_responder_otp_challenge * chl) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **rctx** - Responder context + + **[in]** **chl** - The challenge to free + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.11 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_otp_get_challenge.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_otp_get_challenge.rst.txt new file mode 100644 index 00000000..7f7755db --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_otp_get_challenge.rst.txt @@ -0,0 +1,56 @@ +krb5_responder_otp_get_challenge - Decode the KRB5_RESPONDER_QUESTION_OTP to a C struct. +========================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_responder_otp_get_challenge(krb5_context ctx, krb5_responder_context rctx, krb5_responder_otp_challenge ** chl) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **rctx** - Responder context + + **[out]** **chl** - Challenge structure + + +.. + + + +.. + + + + + + + +A convenience function which parses the KRB5_RESPONDER_QUESTION_OTP question challenge data, making it available in native C. The main feature of this function is the ability to interact with OTP tokens without parsing the JSON. + + + +The returned value must be passed to krb5_responder_otp_challenge_free() to be freed. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.11 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_otp_set_answer.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_otp_set_answer.rst.txt new file mode 100644 index 00000000..0535a206 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_otp_set_answer.rst.txt @@ -0,0 +1,52 @@ +krb5_responder_otp_set_answer - Answer the KRB5_RESPONDER_QUESTION_OTP question. +================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_responder_otp_set_answer(krb5_context ctx, krb5_responder_context rctx, size_t ti, const char * value, const char * pin) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **rctx** - Responder context + + **[in]** **ti** - The index of the tokeninfo selected + + **[in]** **value** - The value to set, or NULL for none + + **[in]** **pin** - The pin to set, or NULL for none + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.11 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_pkinit_challenge_free.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_pkinit_challenge_free.rst.txt new file mode 100644 index 00000000..a017b2e6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_pkinit_challenge_free.rst.txt @@ -0,0 +1,48 @@ +krb5_responder_pkinit_challenge_free - Free the value returned by krb5_responder_pkinit_get_challenge(). +========================================================================================================== + +.. + +.. c:function:: void krb5_responder_pkinit_challenge_free(krb5_context ctx, krb5_responder_context rctx, krb5_responder_pkinit_challenge * chl) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **rctx** - Responder context + + **[in]** **chl** - The challenge to free + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.12 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_pkinit_get_challenge.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_pkinit_get_challenge.rst.txt new file mode 100644 index 00000000..4204e50a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_pkinit_get_challenge.rst.txt @@ -0,0 +1,56 @@ +krb5_responder_pkinit_get_challenge - Decode the KRB5_RESPONDER_QUESTION_PKINIT to a C struct. +================================================================================================ + +.. + +.. c:function:: krb5_error_code krb5_responder_pkinit_get_challenge(krb5_context ctx, krb5_responder_context rctx, krb5_responder_pkinit_challenge ** chl_out) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **rctx** - Responder context + + **[out]** **chl_out** - Challenge structure + + +.. + + + +.. + + + + + + + +A convenience function which parses the KRB5_RESPONDER_QUESTION_PKINIT question challenge data, making it available in native C. The main feature of this function is the ability to read the challenge without parsing the JSON. + + + +The returned value must be passed to krb5_responder_pkinit_challenge_free() to be freed. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.12 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_pkinit_set_answer.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_pkinit_set_answer.rst.txt new file mode 100644 index 00000000..dc8fa57c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_pkinit_set_answer.rst.txt @@ -0,0 +1,50 @@ +krb5_responder_pkinit_set_answer - Answer the KRB5_RESPONDER_QUESTION_PKINIT question for one identity. +========================================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_responder_pkinit_set_answer(krb5_context ctx, krb5_responder_context rctx, const char * identity, const char * pin) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **rctx** - Responder context + + **[in]** **identity** - The identity for which a PIN is being supplied + + **[in]** **pin** - The provided PIN, or NULL for none + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.12 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_set_answer.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_set_answer.rst.txt new file mode 100644 index 00000000..c5b588aa --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_responder_set_answer.rst.txt @@ -0,0 +1,57 @@ +krb5_responder_set_answer - Answer a named question in the responder context. +=============================================================================== + +.. + +.. c:function:: krb5_error_code krb5_responder_set_answer(krb5_context ctx, krb5_responder_context rctx, const char * question, const char * answer) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **rctx** - Responder context + + **[in]** **question** - Question name + + **[in]** **answer** - The string to set (MUST be printable UTF-8) + + +.. + + +:retval: + - EINVAL question is not present within rctx + + +.. + + + + + + + +This function supplies an answer to *question* within *rctx* . The appropriate form of the answer depends on the question name. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.11 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_salttype_to_string.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_salttype_to_string.rst.txt new file mode 100644 index 00000000..e0e44a6b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_salttype_to_string.rst.txt @@ -0,0 +1,47 @@ +krb5_salttype_to_string - Convert a salt type to a string. +============================================================ + +.. + +.. c:function:: krb5_error_code krb5_salttype_to_string(krb5_int32 salttype, char * buffer, size_t buflen) + +.. + + +:param: + + **[in]** **salttype** - Salttype to convert + + **[out]** **buffer** - Buffer to receive the converted string + + **[in]** **buflen** - Storage available in *buffer* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_sendauth.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_sendauth.rst.txt new file mode 100644 index 00000000..40ef384b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_sendauth.rst.txt @@ -0,0 +1,98 @@ +krb5_sendauth - Client function for sendauth protocol. +======================================================== + +.. + +.. c:function:: krb5_error_code krb5_sendauth(krb5_context context, krb5_auth_context * auth_context, krb5_pointer fd, char * appl_version, krb5_principal client, krb5_principal server, krb5_flags ap_req_options, krb5_data * in_data, krb5_creds * in_creds, krb5_ccache ccache, krb5_error ** error, krb5_ap_rep_enc_part ** rep_result, krb5_creds ** out_creds) + +.. + + +:param: + + **[in]** **context** - Library context + + **[inout]** **auth_context** - Pre-existing or newly created auth context + + **[in]** **fd** - File descriptor that describes network socket + + **[in]** **appl_version** - Application protocol version to be matched with the receiver's application version + + **[in]** **client** - Client principal + + **[in]** **server** - Server principal + + **[in]** **ap_req_options** - Options (see AP_OPTS macros) + + **[in]** **in_data** - Data to be sent to the server + + **[in]** **in_creds** - Input credentials, or NULL to use *ccache* + + **[in]** **ccache** - Credential cache + + **[out]** **error** - If non-null, contains KRB_ERROR message returned from server + + **[out]** **rep_result** - If non-null and *ap_req_options* is #AP_OPTS_MUTUAL_REQUIRED, contains the result of mutual authentication exchange + + **[out]** **out_creds** - If non-null, the retrieved credentials + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function performs the client side of a sendauth/recvauth exchange by sending and receiving messages over *fd* . + + + +Credentials may be specified in three ways: + + + + + + - If *in_creds* is NULL, credentials are obtained with krb5_get_credentials() using the principals *client* and *server* . *server* must be non-null; *client* may NULL to use the default principal of *ccache* . + + + + - If *in_creds* is non-null, but does not contain a ticket, credentials for the exchange are obtained with krb5_get_credentials() using *in_creds* . In this case, the values of *client* and *server* are unused. + + + + - If *in_creds* is a complete credentials structure, it used directly. In this case, the values of *client* , *server* , and *ccache* are unused. + + If the server is using a different application protocol than that specified in *appl_version* , an error will be returned. + + + +Use krb5_free_creds() to free *out_creds* , krb5_free_ap_rep_enc_part() to free *rep_result* , and krb5_free_error() to free *error* when they are no longer needed. + + + + + + + + + + +.. + +.. seealso:: + krb5_recvauth() + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_server_decrypt_ticket_keytab.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_server_decrypt_ticket_keytab.rst.txt new file mode 100644 index 00000000..0ec03371 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_server_decrypt_ticket_keytab.rst.txt @@ -0,0 +1,51 @@ +krb5_server_decrypt_ticket_keytab - Decrypt a ticket using the specified key table. +===================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_server_decrypt_ticket_keytab(krb5_context context, const krb5_keytab kt, krb5_ticket * ticket) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **kt** - Key table + + **[in]** **ticket** - Ticket to be decrypted + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function takes a *ticket* as input and decrypts it using key data from *kt* . The result is placed into *ticket->enc_part2* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_default_realm.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_default_realm.rst.txt new file mode 100644 index 00000000..d9ac43d5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_default_realm.rst.txt @@ -0,0 +1,52 @@ +krb5_set_default_realm - Override the default realm for the specified context. +================================================================================ + +.. + +.. c:function:: krb5_error_code krb5_set_default_realm(krb5_context context, const char * lrealm) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **lrealm** - Realm name for the default realm + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +If *lrealm* is NULL, clear the default realm setting. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_default_tgs_enctypes.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_default_tgs_enctypes.rst.txt new file mode 100644 index 00000000..870ca63d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_default_tgs_enctypes.rst.txt @@ -0,0 +1,61 @@ +krb5_set_default_tgs_enctypes - Set default TGS encryption types in a krb5_context structure. +=============================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_set_default_tgs_enctypes(krb5_context context, const krb5_enctype * etypes) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **etypes** - Encryption type(s) to set + + +.. + + +:retval: + - 0 Success + - KRB5_PROG_ETYPE_NOSUPP Program lacks support for encryption type + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function sets the default enctype list for TGS requests made using *context* to *etypes* . + + + + + + + + + + +.. + + + + + + +.. note:: + + This overrides the default list (from config file or built-in). + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_error_message.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_error_message.rst.txt new file mode 100644 index 00000000..86bf9b7c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_error_message.rst.txt @@ -0,0 +1,44 @@ +krb5_set_error_message - Set an extended error message for an error code. +=========================================================================== + +.. + +.. c:function:: void krb5_set_error_message(krb5_context ctx, krb5_error_code code, const char * fmt, ... ) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **code** - Error code + + **[in]** **fmt** - Error string for the error code + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_kdc_recv_hook.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_kdc_recv_hook.rst.txt new file mode 100644 index 00000000..70c48cca --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_kdc_recv_hook.rst.txt @@ -0,0 +1,52 @@ +krb5_set_kdc_recv_hook - Set a KDC post-receive hook function. +================================================================ + +.. + +.. c:function:: void krb5_set_kdc_recv_hook(krb5_context context, krb5_post_recv_fn recv_hook, void * data) + +.. + + +:param: + + **[in]** **context** - The library context. + + **[in]** **recv_hook** - Hook function (or NULL to disable the hook) + + **[in]** **data** - Callback data to be passed to *recv_hook* + + +.. + + + +.. + + + + + + + + *recv_hook* will be called after a reply is received from a KDC during a call to a library function such as krb5_get_credentials(). The hook function may inspect or override the reply. This hook will not be executed if the pre-send hook returns a synthetic reply. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.15 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_kdc_send_hook.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_kdc_send_hook.rst.txt new file mode 100644 index 00000000..d2696db9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_kdc_send_hook.rst.txt @@ -0,0 +1,52 @@ +krb5_set_kdc_send_hook - Set a KDC pre-send hook function. +============================================================ + +.. + +.. c:function:: void krb5_set_kdc_send_hook(krb5_context context, krb5_pre_send_fn send_hook, void * data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **send_hook** - Hook function (or NULL to disable the hook) + + **[in]** **data** - Callback data to be passed to *send_hook* + + +.. + + + +.. + + + + + + + + *send_hook* will be called before messages are sent to KDCs by library functions such as krb5_get_credentials(). The hook function may inspect, override, or synthesize its own reply to the message. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.15 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_password.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_password.rst.txt new file mode 100644 index 00000000..ff80c966 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_password.rst.txt @@ -0,0 +1,74 @@ +krb5_set_password - Set a password for a principal using specified credentials. +================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_set_password(krb5_context context, krb5_creds * creds, const char * newpw, krb5_principal change_password_for, int * result_code, krb5_data * result_code_string, krb5_data * result_string) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **creds** - Credentials for kadmin/changepw service + + **[in]** **newpw** - New password + + **[in]** **change_password_for** - Change the password for this principal + + **[out]** **result_code** - Numeric error code from server + + **[out]** **result_code_string** - String equivalent to *result_code* + + **[out]** **result_string** - Data returned from the remote system + + +.. + + +:retval: + - 0 Success and result_code is set to #KRB5_KPASSWD_SUCCESS. + + +:return: + - Kerberos error codes. + +.. + + + + + + + +This function uses the credentials *creds* to set the password *newpw* for the principal *change_password_for* . It implements the set password operation of RFC 3244, for interoperability with Microsoft Windows implementations. + + + +The error code and strings are returned in *result_code* , *result_code_string* and *result_string* . + + + + + + + + + + +.. + + + + + + +.. note:: + + If *change_password_for* is NULL, the change is performed on the current principal. If *change_password_for* is non-null, the change is performed on the principal name passed in *change_password_for* . + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_password_using_ccache.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_password_using_ccache.rst.txt new file mode 100644 index 00000000..24bf4be7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_password_using_ccache.rst.txt @@ -0,0 +1,74 @@ +krb5_set_password_using_ccache - Set a password for a principal using cached credentials. +=========================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_set_password_using_ccache(krb5_context context, krb5_ccache ccache, const char * newpw, krb5_principal change_password_for, int * result_code, krb5_data * result_code_string, krb5_data * result_string) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ccache** - Credential cache + + **[in]** **newpw** - New password + + **[in]** **change_password_for** - Change the password for this principal + + **[out]** **result_code** - Numeric error code from server + + **[out]** **result_code_string** - String equivalent to *result_code* + + **[out]** **result_string** - Data returned from the remote system + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function uses the cached credentials from *ccache* to set the password *newpw* for the principal *change_password_for* . It implements RFC 3244 set password operation (interoperable with MS Windows implementations) using the credential cache. + + + +The error code and strings are returned in *result_code* , *result_code_string* and *result_string* . + + + + + + + + + + +.. + + + + + + +.. note:: + + If *change_password_for* is set to NULL, the change is performed on the default principal in *ccache* . If *change_password_for* is non null, the change is performed on the specified principal. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_principal_realm.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_principal_realm.rst.txt new file mode 100644 index 00000000..0319b338 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_principal_realm.rst.txt @@ -0,0 +1,54 @@ +krb5_set_principal_realm - Set the realm field of a principal. +================================================================ + +.. + +.. c:function:: krb5_error_code krb5_set_principal_realm(krb5_context context, krb5_principal principal, const char * realm) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **principal** - Principal name + + **[in]** **realm** - Realm name + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +Set the realm name part of *principal* to *realm* , overwriting the previous realm. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_real_time.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_real_time.rst.txt new file mode 100644 index 00000000..18d7a6b5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_real_time.rst.txt @@ -0,0 +1,51 @@ +krb5_set_real_time - Set time offset field in a krb5_context structure. +========================================================================= + +.. + +.. c:function:: krb5_error_code krb5_set_real_time(krb5_context context, krb5_timestamp seconds, krb5_int32 microseconds) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **seconds** - Real time, seconds portion + + **[in]** **microseconds** - Real time, microseconds portion + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function sets the time offset in *context* to the difference between the system time and the real time as determined by *seconds* and *microseconds* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_trace_callback.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_trace_callback.rst.txt new file mode 100644 index 00000000..4c31ddb6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_trace_callback.rst.txt @@ -0,0 +1,63 @@ +krb5_set_trace_callback - Specify a callback function for trace events. +========================================================================= + +.. + +.. c:function:: krb5_error_code krb5_set_trace_callback(krb5_context context, krb5_trace_callback fn, void * cb_data) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **fn** - Callback function + + **[in]** **cb_data** - Callback data + + +.. + + + +:return: + - Returns KRB5_TRACE_NOSUPP if tracing is not supported in the library (unless fn is NULL). + +.. + + + + + + + +Specify a callback for trace events occurring in krb5 operations performed within *context* . *fn* will be invoked with *context* as the first argument, *cb_data* as the last argument, and a pointer to a krb5_trace_info as the second argument. If the trace callback is reset via this function or *context* is destroyed, *fn* will be invoked with a NULL second argument so it can clean up *cb_data* . Supply a NULL value for *fn* to disable trace callbacks within *context* . + + + + + + + + + + +.. + + + + + + +.. note:: + + This function overrides the information passed through the *KRB5_TRACE* environment variable. + + + +.. note:: + + New in 1.9 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_trace_filename.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_trace_filename.rst.txt new file mode 100644 index 00000000..6d75325a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_set_trace_filename.rst.txt @@ -0,0 +1,61 @@ +krb5_set_trace_filename - Specify a file name for directing trace events. +=========================================================================== + +.. + +.. c:function:: krb5_error_code krb5_set_trace_filename(krb5_context context, const char * filename) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **filename** - File name + + +.. + + +:retval: + - KRB5_TRACE_NOSUPP Tracing is not supported in the library. + + +.. + + + + + + + +Open *filename* for appending (creating it, if necessary) and set up a callback to write trace events to it. + + + + + + + + + + +.. + + + + + + +.. note:: + + This function overrides the information passed through the *KRB5_TRACE* environment variable. + + + +.. note:: + + New in 1.9 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_sname_match.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_sname_match.rst.txt new file mode 100644 index 00000000..c3750006 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_sname_match.rst.txt @@ -0,0 +1,59 @@ +krb5_sname_match - Test whether a principal matches a matching principal. +=========================================================================== + +.. + +.. c:function:: krb5_boolean krb5_sname_match(krb5_context context, krb5_const_principal matching, krb5_const_principal princ) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **matching** - Matching principal + + **[in]** **princ** - Principal to test + + +.. + + + +:return: + - TRUE if princ matches matching , FALSE otherwise. + +.. + + + + + + + +If *matching* is NULL, return TRUE. If *matching* is not a matching principal, return the value of krb5_principal_compare(context, matching, princ). + + + + + + + + + + +.. + + + + + + +.. note:: + + A matching principal is a host-based principal with an empty realm and/or second data component (hostname). Profile configuration may cause the hostname to be ignored even if it is present. A principal matches a matching principal if the former has the same non-empty (and non-ignored) components of the latter. + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_sname_to_principal.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_sname_to_principal.rst.txt new file mode 100644 index 00000000..6dd15ddb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_sname_to_principal.rst.txt @@ -0,0 +1,74 @@ +krb5_sname_to_principal - Generate a full principal name from a service name. +=============================================================================== + +.. + +.. c:function:: krb5_error_code krb5_sname_to_principal(krb5_context context, const char * hostname, const char * sname, krb5_int32 type, krb5_principal * ret_princ) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **hostname** - Host name, or NULL to use local host + + **[in]** **sname** - Service name, or NULL to use **"host"** + + **[in]** **type** - Principal type + + **[out]** **ret_princ** - Generated principal + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function converts a *hostname* and *sname* into *krb5_principal* structure *ret_princ* . The returned principal will be of the form *sname\/hostname@REALM* where REALM is determined by krb5_get_host_realm(). In some cases this may be the referral (empty) realm. + + + +The *type* can be one of the following: + + + + + + - #KRB5_NT_SRV_HST canonicalizes the host name before looking up the realm and generating the principal. + + + + - #KRB5_NT_UNKNOWN accepts the hostname as given, and does not canonicalize it. + + Use krb5_free_principal to free *ret_princ* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_cksumtype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_cksumtype.rst.txt new file mode 100644 index 00000000..8ad07f79 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_cksumtype.rst.txt @@ -0,0 +1,45 @@ +krb5_string_to_cksumtype - Convert a string to a checksum type. +================================================================= + +.. + +.. c:function:: krb5_error_code krb5_string_to_cksumtype(char * string, krb5_cksumtype * cksumtypep) + +.. + + +:param: + + **[in]** **string** - String to be converted + + **[out]** **cksumtypep** - Checksum type to be filled in + + +.. + + +:retval: + - 0 Success; otherwise - EINVAL + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_deltat.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_deltat.rst.txt new file mode 100644 index 00000000..0f1b9584 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_deltat.rst.txt @@ -0,0 +1,45 @@ +krb5_string_to_deltat - Convert a string to a delta time value. +================================================================= + +.. + +.. c:function:: krb5_error_code krb5_string_to_deltat(char * string, krb5_deltat * deltatp) + +.. + + +:param: + + **[in]** **string** - String to be converted + + **[out]** **deltatp** - Delta time to be filled in + + +.. + + +:retval: + - 0 Success; otherwise - KRB5_DELTAT_BADFORMAT + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_enctype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_enctype.rst.txt new file mode 100644 index 00000000..173251f6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_enctype.rst.txt @@ -0,0 +1,45 @@ +krb5_string_to_enctype - Convert a string to an encryption type. +================================================================== + +.. + +.. c:function:: krb5_error_code krb5_string_to_enctype(char * string, krb5_enctype * enctypep) + +.. + + +:param: + + **[in]** **string** - String to convert to an encryption type + + **[out]** **enctypep** - Encryption type + + +.. + + +:retval: + - 0 Success; otherwise - EINVAL + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_key.rst.txt new file mode 100644 index 00000000..3f44b9d5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_key.rst.txt @@ -0,0 +1,50 @@ +krb5_string_to_key +================== + +.. + +.. c:function:: krb5_error_code krb5_string_to_key(krb5_context context, const krb5_encrypt_block * eblock, krb5_keyblock * keyblock, const krb5_data * data, const krb5_data * salt) + +.. + + +:param: + + **context** + + **eblock** + + **keyblock** + + **data** + + **salt** + + +.. + + + +.. + + +DEPRECATED See krb5_c_string_to_key() + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_salttype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_salttype.rst.txt new file mode 100644 index 00000000..36978f4b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_salttype.rst.txt @@ -0,0 +1,45 @@ +krb5_string_to_salttype - Convert a string to a salt type. +============================================================ + +.. + +.. c:function:: krb5_error_code krb5_string_to_salttype(char * string, krb5_int32 * salttypep) + +.. + + +:param: + + **[in]** **string** - String to convert to an encryption type + + **[out]** **salttypep** - Salt type to be filled in + + +.. + + +:retval: + - 0 Success; otherwise - EINVAL + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_timestamp.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_timestamp.rst.txt new file mode 100644 index 00000000..11b6d1e9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_string_to_timestamp.rst.txt @@ -0,0 +1,45 @@ +krb5_string_to_timestamp - Convert a string to a timestamp. +============================================================= + +.. + +.. c:function:: krb5_error_code krb5_string_to_timestamp(char * string, krb5_timestamp * timestampp) + +.. + + +:param: + + **[in]** **string** - String to be converted + + **[out]** **timestampp** - Pointer to timestamp + + +.. + + +:retval: + - 0 Success; otherwise - EINVAL + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_timeofday.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_timeofday.rst.txt new file mode 100644 index 00000000..dc1c9029 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_timeofday.rst.txt @@ -0,0 +1,52 @@ +krb5_timeofday - Retrieve the current time with context specific time offset adjustment. +========================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_timeofday(krb5_context context, krb5_timestamp * timeret) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **timeret** - Timestamp to fill in + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function retrieves the system time of day with the context specific time offset adjustment. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_timestamp_to_sfstring.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_timestamp_to_sfstring.rst.txt new file mode 100644 index 00000000..3750c45d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_timestamp_to_sfstring.rst.txt @@ -0,0 +1,53 @@ +krb5_timestamp_to_sfstring - Convert a timestamp to a string, with optional output padding. +============================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_timestamp_to_sfstring(krb5_timestamp timestamp, char * buffer, size_t buflen, char * pad) + +.. + + +:param: + + **[in]** **timestamp** - Timestamp to convert + + **[out]** **buffer** - Buffer to hold the converted timestamp + + **[in]** **buflen** - Length of buffer + + **[in]** **pad** - Optional value to pad *buffer* if converted timestamp does not fill it + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +If *pad* is not NULL, *buffer* is padded out to *buflen* - 1 characters with the value of * *pad* . + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_timestamp_to_string.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_timestamp_to_string.rst.txt new file mode 100644 index 00000000..1c4c71eb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_timestamp_to_string.rst.txt @@ -0,0 +1,51 @@ +krb5_timestamp_to_string - Convert a timestamp to a string. +============================================================= + +.. + +.. c:function:: krb5_error_code krb5_timestamp_to_string(krb5_timestamp timestamp, char * buffer, size_t buflen) + +.. + + +:param: + + **[in]** **timestamp** - Timestamp to convert + + **[out]** **buffer** - Buffer to hold converted timestamp + + **[in]** **buflen** - Storage available in *buffer* + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +The string is returned in the locale's appropriate date and time representation. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_free.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_free.rst.txt new file mode 100644 index 00000000..623ed5be --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_free.rst.txt @@ -0,0 +1,46 @@ +krb5_tkt_creds_free - Free a TGS request context. +=================================================== + +.. + +.. c:function:: void krb5_tkt_creds_free(krb5_context context, krb5_tkt_creds_context ctx) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - TGS request context + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.9 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_get.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_get.rst.txt new file mode 100644 index 00000000..a193ce92 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_get.rst.txt @@ -0,0 +1,53 @@ +krb5_tkt_creds_get - Synchronously obtain credentials using a TGS request context. +==================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_tkt_creds_get(krb5_context context, krb5_tkt_creds_context ctx) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - TGS request context + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function synchronously obtains credentials using a context created by krb5_tkt_creds_init(). On successful return, the credentials can be retrieved with krb5_tkt_creds_get_creds(). + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.9 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_get_creds.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_get_creds.rst.txt new file mode 100644 index 00000000..309e8d47 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_get_creds.rst.txt @@ -0,0 +1,55 @@ +krb5_tkt_creds_get_creds - Retrieve acquired credentials from a TGS request context. +====================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_tkt_creds_get_creds(krb5_context context, krb5_tkt_creds_context ctx, krb5_creds * creds) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - TGS request context + + **[out]** **creds** - Acquired credentials + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function copies the acquired initial credentials from *ctx* into *creds* , after the successful completion of krb5_tkt_creds_get() or krb5_tkt_creds_step(). Use krb5_free_cred_contents() to free *creds* when it is no longer needed. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.9 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_get_times.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_get_times.rst.txt new file mode 100644 index 00000000..19c9f980 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_get_times.rst.txt @@ -0,0 +1,55 @@ +krb5_tkt_creds_get_times - Retrieve ticket times from a TGS request context. +============================================================================== + +.. + +.. c:function:: krb5_error_code krb5_tkt_creds_get_times(krb5_context context, krb5_tkt_creds_context ctx, krb5_ticket_times * times) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - TGS request context + + **[out]** **times** - Ticket times for acquired credentials + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +The TGS request context must have completed obtaining credentials via either krb5_tkt_creds_get() or krb5_tkt_creds_step(). + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.9 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_init.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_init.rst.txt new file mode 100644 index 00000000..3ec4a35d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_init.rst.txt @@ -0,0 +1,67 @@ +krb5_tkt_creds_init - Create a context to get credentials from a KDC's Ticket Granting Service. +================================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_tkt_creds_init(krb5_context context, krb5_ccache ccache, krb5_creds * creds, krb5_flags options, krb5_tkt_creds_context * ctx) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ccache** - Credential cache handle + + **[in]** **creds** - Input credentials + + **[in]** **options** - Options (see KRB5_GC macros) + + **[out]** **ctx** - New TGS request context + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function prepares to obtain credentials matching *creds* , either by retrieving them from *ccache* or by making requests to ticket-granting services beginning with a ticket-granting ticket for the client principal's realm. + + + +The resulting TGS acquisition context can be used asynchronously with krb5_tkt_creds_step() or synchronously with krb5_tkt_creds_get(). See also krb5_get_credentials() for synchronous use. + + + +Use krb5_tkt_creds_free() to free *ctx* when it is no longer needed. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.9 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_step.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_step.rst.txt new file mode 100644 index 00000000..919f47c7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_tkt_creds_step.rst.txt @@ -0,0 +1,69 @@ +krb5_tkt_creds_step - Get the next KDC request in a TGS exchange. +=================================================================== + +.. + +.. c:function:: krb5_error_code krb5_tkt_creds_step(krb5_context context, krb5_tkt_creds_context ctx, krb5_data * in, krb5_data * out, krb5_data * realm, unsigned int * flags) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **ctx** - TGS request context + + **[in]** **in** - KDC response (empty on the first call) + + **[out]** **out** - Next KDC request + + **[out]** **realm** - Realm for next KDC request + + **[out]** **flags** - Output flags + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function constructs the next KDC request for a TGS exchange, allowing the caller to control the transport of KDC requests and replies. On the first call, *in* should be set to an empty buffer; on subsequent calls, it should be set to the KDC's reply to the previous request. + + + +If more requests are needed, *flags* will be set to #KRB5_TKT_CREDS_STEP_FLAG_CONTINUE and the next request will be placed in *out* . If no more requests are needed, *flags* will not contain #KRB5_TKT_CREDS_STEP_FLAG_CONTINUE and *out* will be empty. + + + +If this function returns **KRB5KRB_ERR_RESPONSE_TOO_BIG** , the caller should transmit the next request using TCP rather than UDP. If this function returns any other error, the TGS exchange has failed. + + + + + + + + + + +.. + + + + +.. note:: + + New in 1.9 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unmarshal_credentials.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unmarshal_credentials.rst.txt new file mode 100644 index 00000000..bbab8765 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unmarshal_credentials.rst.txt @@ -0,0 +1,55 @@ +krb5_unmarshal_credentials - Deserialize a krb5_creds object. +=============================================================== + +.. + +.. c:function:: krb5_error_code krb5_unmarshal_credentials(krb5_context context, const krb5_data * data, krb5_creds ** creds_out) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **data** - The serialized credentials + + **[out]** **creds_out** - The resulting creds object + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +Deserialize *data* to credentials in the format used by the FILE ccache format (vesion 4) and KCM ccache protocol. + + + +Use krb5_free_creds() to free *creds_out* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name.rst.txt new file mode 100644 index 00000000..90ecea70 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name.rst.txt @@ -0,0 +1,58 @@ +krb5_unparse_name - Convert a krb5_principal structure to a string representation. +==================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_unparse_name(krb5_context context, krb5_const_principal principal, char ** name) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **principal** - Principal + + **[out]** **name** - String representation of principal name + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +The resulting string representation uses the format and quoting conventions described for krb5_parse_name(). + + + +Use krb5_free_unparsed_name() to free *name* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name_ext.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name_ext.rst.txt new file mode 100644 index 00000000..6456632f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name_ext.rst.txt @@ -0,0 +1,60 @@ +krb5_unparse_name_ext - Convert krb5_principal structure to string and length. +================================================================================ + +.. + +.. c:function:: krb5_error_code krb5_unparse_name_ext(krb5_context context, krb5_const_principal principal, char ** name, unsigned int * size) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **principal** - Principal + + **[inout]** **name** - String representation of principal name + + **[inout]** **size** - Size of unparsed name + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes. On failure name is set to NULL + +.. + + + + + + + +This function is similar to krb5_unparse_name(), but allows the use of an existing buffer for the result. If size is not NULL, then *name* must point to either NULL or an existing buffer of at least the size pointed to by *size* . The buffer will be allocated or resized if necessary, with the new pointer stored into *name* . Whether or not the buffer is resized, the necessary space for the result, including null terminator, will be stored into *size* . + + + +If size is NULL, this function behaves exactly as krb5_unparse_name(). + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name_flags.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name_flags.rst.txt new file mode 100644 index 00000000..dce93531 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name_flags.rst.txt @@ -0,0 +1,70 @@ +krb5_unparse_name_flags - Convert krb5_principal structure to a string with flags. +==================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_unparse_name_flags(krb5_context context, krb5_const_principal principal, int flags, char ** name) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **principal** - Principal + + **[in]** **flags** - Flags + + **[out]** **name** - String representation of principal name + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes. On failure name is set to NULL + +.. + + + + + + + +Similar to krb5_unparse_name(), this function converts a krb5_principal structure to a string representation. + + + +The following flags are valid: + + - #KRB5_PRINCIPAL_UNPARSE_SHORT - omit realm if it is the local realm + + + - #KRB5_PRINCIPAL_UNPARSE_NO_REALM - omit realm + + + - #KRB5_PRINCIPAL_UNPARSE_DISPLAY - do not quote special characters + + Use krb5_free_unparsed_name() to free *name* when it is no longer needed. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name_flags_ext.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name_flags_ext.rst.txt new file mode 100644 index 00000000..aa713bda --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_unparse_name_flags_ext.rst.txt @@ -0,0 +1,54 @@ +krb5_unparse_name_flags_ext - Convert krb5_principal structure to string format with flags. +============================================================================================= + +.. + +.. c:function:: krb5_error_code krb5_unparse_name_flags_ext(krb5_context context, krb5_const_principal principal, int flags, char ** name, unsigned int * size) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **principal** - Principal + + **[in]** **flags** - Flags + + **[out]** **name** - Single string format of principal name + + **[out]** **size** - Size of unparsed name buffer + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes. On failure name is set to NULL + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_us_timeofday.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_us_timeofday.rst.txt new file mode 100644 index 00000000..ba4ef808 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_us_timeofday.rst.txt @@ -0,0 +1,54 @@ +krb5_us_timeofday - Retrieve the system time of day, in sec and ms, since the epoch. +====================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_us_timeofday(krb5_context context, krb5_timestamp * seconds, krb5_int32 * microseconds) + +.. + + +:param: + + **[in]** **context** - Library context + + **[out]** **seconds** - System timeofday, seconds portion + + **[out]** **microseconds** - System timeofday, microseconds portion + + +.. + + +:retval: + - 0 Success + + +:return: + - Kerberos error codes + +.. + + + + + + + +This function retrieves the system time of day with the context specific time offset adjustment. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_use_enctype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_use_enctype.rst.txt new file mode 100644 index 00000000..10b3fa71 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_use_enctype.rst.txt @@ -0,0 +1,46 @@ +krb5_use_enctype +================ + +.. + +.. c:function:: krb5_error_code krb5_use_enctype(krb5_context context, krb5_encrypt_block * eblock, krb5_enctype enctype) + +.. + + +:param: + + **context** + + **eblock** + + **enctype** + + +.. + + + +.. + + +DEPRECATED Replaced by krb5_c_* API family. + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_authdata_kdc_issued.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_authdata_kdc_issued.rst.txt new file mode 100644 index 00000000..30971392 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_authdata_kdc_issued.rst.txt @@ -0,0 +1,48 @@ +krb5_verify_authdata_kdc_issued - Unwrap and verify AD-KDCIssued authorization data. +====================================================================================== + +.. + +.. c:function:: krb5_error_code krb5_verify_authdata_kdc_issued(krb5_context context, const krb5_keyblock * key, const krb5_authdata * ad_kdcissued, krb5_principal * issuer, krb5_authdata *** authdata) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **key** - Session key + + **[in]** **ad_kdcissued** - AD-KDCIssued authorization data to be unwrapped + + **[out]** **issuer** - Name of issuing principal (or NULL) + + **[out]** **authdata** - Unwrapped list of authorization data + + +.. + + + +.. + + + + + + + +This function unwraps an AD-KDCIssued authdatum (see RFC 4120 section 5.2.6.2) and verifies its signature against *key* . The issuer field of the authdatum element is returned in *issuer* , and the unwrapped list of authdata is returned in *authdata* . + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_checksum.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_checksum.rst.txt new file mode 100644 index 00000000..0ddf6318 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_checksum.rst.txt @@ -0,0 +1,54 @@ +krb5_verify_checksum +==================== + +.. + +.. c:function:: krb5_error_code krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype, const krb5_checksum * cksum, krb5_const_pointer in, size_t in_length, krb5_const_pointer seed, size_t seed_length) + +.. + + +:param: + + **context** + + **ctype** + + **cksum** + + **in** + + **in_length** + + **seed** + + **seed_length** + + +.. + + + +.. + + +DEPRECATED See krb5_c_verify_checksum() + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_init_creds.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_init_creds.rst.txt new file mode 100644 index 00000000..1788cad3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_init_creds.rst.txt @@ -0,0 +1,65 @@ +krb5_verify_init_creds - Verify initial credentials against a keytab. +======================================================================= + +.. + +.. c:function:: krb5_error_code krb5_verify_init_creds(krb5_context context, krb5_creds * creds, krb5_principal server, krb5_keytab keytab, krb5_ccache * ccache, krb5_verify_init_creds_opt * options) + +.. + + +:param: + + **[in]** **context** - Library context + + **[in]** **creds** - Initial credentials to be verified + + **[in]** **server** - Server principal (or NULL) + + **[in]** **keytab** - Key table (NULL to use default keytab) + + **[in]** **ccache** - Credential cache for fetched creds (or NULL) + + **[in]** **options** - Verification options (NULL for default options) + + +.. + + +:retval: + - 0 Success; otherwise - Kerberos error codes + + +.. + + + + + + + +This function attempts to verify that *creds* were obtained from a KDC with knowledge of a key in *keytab* , or the default keytab if *keytab* is NULL. If *server* is provided, the highest-kvno key entry for that principal name is used to verify the credentials; otherwise, all unique"host"service principals in the keytab are tried. + + + +If the specified keytab does not exist, or is empty, or cannot be read, or does not contain an entry for *server* , then credential verification may be skipped unless configuration demands that it succeed. The caller can control this behavior by providing a verification options structure; see krb5_verify_init_creds_opt_init() and krb5_verify_init_creds_opt_set_ap_req_nofail(). + + + +If *ccache* is NULL, any additional credentials fetched during the verification process will be destroyed. If *ccache* points to NULL, a memory ccache will be created for the additional credentials and returned in *ccache* . If *ccache* points to a valid credential cache handle, the additional credentials will be stored in that cache. + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_init_creds_opt_init.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_init_creds_opt_init.rst.txt new file mode 100644 index 00000000..a55fd3aa --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_init_creds_opt_init.rst.txt @@ -0,0 +1,40 @@ +krb5_verify_init_creds_opt_init - Initialize a credential verification options structure. +=========================================================================================== + +.. + +.. c:function:: void krb5_verify_init_creds_opt_init(krb5_verify_init_creds_opt * k5_vic_options) + +.. + + +:param: + + **[in]** **k5_vic_options** - Verification options structure + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail.rst.txt new file mode 100644 index 00000000..870f448f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail.rst.txt @@ -0,0 +1,46 @@ +krb5_verify_init_creds_opt_set_ap_req_nofail - Set whether credential verification is required. +================================================================================================= + +.. + +.. c:function:: void krb5_verify_init_creds_opt_set_ap_req_nofail(krb5_verify_init_creds_opt * k5_vic_options, int ap_req_nofail) + +.. + + +:param: + + **[in]** **k5_vic_options** - Verification options structure + + **[in]** **ap_req_nofail** - Whether to require successful verification + + +.. + + + +.. + + + + + + + +This function determines how krb5_verify_init_creds() behaves if no keytab information is available. If *ap_req_nofail* is **FALSE** , verification will be skipped in this case and krb5_verify_init_creds() will return successfully. If *ap_req_nofail* is **TRUE** , krb5_verify_init_creds() will not return successfully unless verification can be performed. + + + +If this function is not used, the behavior of krb5_verify_init_creds() is determined through configuration. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_vprepend_error_message.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_vprepend_error_message.rst.txt new file mode 100644 index 00000000..53003d1c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_vprepend_error_message.rst.txt @@ -0,0 +1,46 @@ +krb5_vprepend_error_message - Add a prefix to the message for an error code using a va_list. +============================================================================================== + +.. + +.. c:function:: void krb5_vprepend_error_message(krb5_context ctx, krb5_error_code code, const char * fmt, va_list args) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **code** - Error code + + **[in]** **fmt** - Format string for error message prefix + + **[in]** **args** - List of vprintf(3) style arguments + + +.. + + + +.. + + + + + + + +This function is similar to krb5_prepend_error_message(), but uses a va_list instead of variadic arguments. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_vset_error_message.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_vset_error_message.rst.txt new file mode 100644 index 00000000..fcb4b699 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_vset_error_message.rst.txt @@ -0,0 +1,46 @@ +krb5_vset_error_message - Set an extended error message for an error code using a va_list. +============================================================================================ + +.. + +.. c:function:: void krb5_vset_error_message(krb5_context ctx, krb5_error_code code, const char * fmt, va_list args) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **code** - Error code + + **[in]** **fmt** - Error string for the error code + + **[in]** **args** - List of vprintf(3) style arguments + + +.. + + + +.. + + + + + + + + + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_vwrap_error_message.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_vwrap_error_message.rst.txt new file mode 100644 index 00000000..d860efe4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_vwrap_error_message.rst.txt @@ -0,0 +1,48 @@ +krb5_vwrap_error_message - Add a prefix to a different error code's message using a va_list. +============================================================================================== + +.. + +.. c:function:: void krb5_vwrap_error_message(krb5_context ctx, krb5_error_code old_code, krb5_error_code code, const char * fmt, va_list args) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **old_code** - Previous error code + + **[in]** **code** - Error code + + **[in]** **fmt** - Format string for error message prefix + + **[in]** **args** - List of vprintf(3) style arguments + + +.. + + + +.. + + + + + + + +This function is similar to krb5_wrap_error_message(), but uses a va_list instead of variadic arguments. + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_wrap_error_message.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_wrap_error_message.rst.txt new file mode 100644 index 00000000..b599ae78 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/api/krb5_wrap_error_message.rst.txt @@ -0,0 +1,46 @@ +krb5_wrap_error_message - Add a prefix to a different error code's message. +============================================================================= + +.. + +.. c:function:: void krb5_wrap_error_message(krb5_context ctx, krb5_error_code old_code, krb5_error_code code, const char * fmt, ... ) + +.. + + +:param: + + **[in]** **ctx** - Library context + + **[in]** **old_code** - Previous error code + + **[in]** **code** - Error code + + **[in]** **fmt** - Format string for error message prefix + + +.. + + + +.. + + + + + + + +Format a message and prepend it to the message for *old_code* . The prefix will be separated from the old message with a colon and space. Set the resulting message as the extended error message for *code* . + + + + + + +.. + + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/index.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/index.rst.txt new file mode 100644 index 00000000..37a895f3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/index.rst.txt @@ -0,0 +1,9 @@ +Complete reference - API and datatypes +====================================== + +.. toctree:: + :maxdepth: 1 + + api/index.rst + types/index.rst + macros/index.rst diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_ADDRPORT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_ADDRPORT.rst.txt new file mode 100644 index 00000000..ec4c2835 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_ADDRPORT.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ADDRTYPE-ADDRPORT-data: + +ADDRTYPE_ADDRPORT +================= + +.. +.. data:: ADDRTYPE_ADDRPORT +.. + + + + +======================== ====================== +``ADDRTYPE_ADDRPORT`` ``0x0100`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_CHAOS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_CHAOS.rst.txt new file mode 100644 index 00000000..7285be14 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_CHAOS.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ADDRTYPE-CHAOS-data: + +ADDRTYPE_CHAOS +============== + +.. +.. data:: ADDRTYPE_CHAOS +.. + + + + +===================== ====================== +``ADDRTYPE_CHAOS`` ``0x0005`` +===================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_DDP.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_DDP.rst.txt new file mode 100644 index 00000000..bbf67c14 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_DDP.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ADDRTYPE-DDP-data: + +ADDRTYPE_DDP +============ + +.. +.. data:: ADDRTYPE_DDP +.. + + + + +=================== ====================== +``ADDRTYPE_DDP`` ``0x0010`` +=================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_INET.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_INET.rst.txt new file mode 100644 index 00000000..e40013b0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_INET.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ADDRTYPE-INET-data: + +ADDRTYPE_INET +============= + +.. +.. data:: ADDRTYPE_INET +.. + + + + +==================== ====================== +``ADDRTYPE_INET`` ``0x0002`` +==================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_INET6.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_INET6.rst.txt new file mode 100644 index 00000000..f1c6c852 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_INET6.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ADDRTYPE-INET6-data: + +ADDRTYPE_INET6 +============== + +.. +.. data:: ADDRTYPE_INET6 +.. + + + + +===================== ====================== +``ADDRTYPE_INET6`` ``0x0018`` +===================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_IPPORT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_IPPORT.rst.txt new file mode 100644 index 00000000..09030d66 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_IPPORT.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ADDRTYPE-IPPORT-data: + +ADDRTYPE_IPPORT +=============== + +.. +.. data:: ADDRTYPE_IPPORT +.. + + + + +====================== ====================== +``ADDRTYPE_IPPORT`` ``0x0101`` +====================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_ISO.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_ISO.rst.txt new file mode 100644 index 00000000..3feb1fb0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_ISO.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ADDRTYPE-ISO-data: + +ADDRTYPE_ISO +============ + +.. +.. data:: ADDRTYPE_ISO +.. + + + + +=================== ====================== +``ADDRTYPE_ISO`` ``0x0007`` +=================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_IS_LOCAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_IS_LOCAL.rst.txt new file mode 100644 index 00000000..9f091b41 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_IS_LOCAL.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ADDRTYPE-IS-LOCAL-data: + +ADDRTYPE_IS_LOCAL +================= + +.. +.. data:: ADDRTYPE_IS_LOCAL +.. + + + + +================================== ====================== +``ADDRTYPE_IS_LOCAL (addrtype)`` ``(addrtype & 0x8000)`` +================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_NETBIOS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_NETBIOS.rst.txt new file mode 100644 index 00000000..1c62e3d8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_NETBIOS.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ADDRTYPE-NETBIOS-data: + +ADDRTYPE_NETBIOS +================ + +.. +.. data:: ADDRTYPE_NETBIOS +.. + + + + +======================= ====================== +``ADDRTYPE_NETBIOS`` ``0x0014`` +======================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_XNS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_XNS.rst.txt new file mode 100644 index 00000000..8c30dcdd --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ADDRTYPE_XNS.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ADDRTYPE-XNS-data: + +ADDRTYPE_XNS +============ + +.. +.. data:: ADDRTYPE_XNS +.. + + + + +=================== ====================== +``ADDRTYPE_XNS`` ``0x0006`` +=================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_EXTERNAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_EXTERNAL.rst.txt new file mode 100644 index 00000000..eacafc20 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_EXTERNAL.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _AD-TYPE-EXTERNAL-data: + +AD_TYPE_EXTERNAL +================ + +.. +.. data:: AD_TYPE_EXTERNAL +.. + + + + +======================= ====================== +``AD_TYPE_EXTERNAL`` ``0x4000`` +======================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK.rst.txt new file mode 100644 index 00000000..fefb9843 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _AD-TYPE-FIELD-TYPE-MASK-data: + +AD_TYPE_FIELD_TYPE_MASK +======================= + +.. +.. data:: AD_TYPE_FIELD_TYPE_MASK +.. + + + + +============================== ====================== +``AD_TYPE_FIELD_TYPE_MASK`` ``0x1fff`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_REGISTERED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_REGISTERED.rst.txt new file mode 100644 index 00000000..4907e159 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_REGISTERED.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _AD-TYPE-REGISTERED-data: + +AD_TYPE_REGISTERED +================== + +.. +.. data:: AD_TYPE_REGISTERED +.. + + + + +========================= ====================== +``AD_TYPE_REGISTERED`` ``0x2000`` +========================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_RESERVED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_RESERVED.rst.txt new file mode 100644 index 00000000..5ae5ea33 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AD_TYPE_RESERVED.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _AD-TYPE-RESERVED-data: + +AD_TYPE_RESERVED +================ + +.. +.. data:: AD_TYPE_RESERVED +.. + + + + +======================= ====================== +``AD_TYPE_RESERVED`` ``0x8000`` +======================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION.rst.txt new file mode 100644 index 00000000..4bea16d0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _AP-OPTS-ETYPE-NEGOTIATION-data: + +AP_OPTS_ETYPE_NEGOTIATION +========================= + +.. +.. data:: AP_OPTS_ETYPE_NEGOTIATION +.. + + + + +================================ ====================== +``AP_OPTS_ETYPE_NEGOTIATION`` ``0x00000002`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED.rst.txt new file mode 100644 index 00000000..b3e6e592 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _AP-OPTS-MUTUAL-REQUIRED-data: + +AP_OPTS_MUTUAL_REQUIRED +======================= + +.. +.. data:: AP_OPTS_MUTUAL_REQUIRED +.. + +Perform a mutual authentication exchange. + + + +============================== ====================== +``AP_OPTS_MUTUAL_REQUIRED`` ``0x20000000`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_RESERVED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_RESERVED.rst.txt new file mode 100644 index 00000000..7961b63c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_RESERVED.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _AP-OPTS-RESERVED-data: + +AP_OPTS_RESERVED +================ + +.. +.. data:: AP_OPTS_RESERVED +.. + + + + +======================= ====================== +``AP_OPTS_RESERVED`` ``0x80000000`` +======================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_USE_SESSION_KEY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_USE_SESSION_KEY.rst.txt new file mode 100644 index 00000000..1742a2ff --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_USE_SESSION_KEY.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _AP-OPTS-USE-SESSION-KEY-data: + +AP_OPTS_USE_SESSION_KEY +======================= + +.. +.. data:: AP_OPTS_USE_SESSION_KEY +.. + +Use session key. + + + +============================== ====================== +``AP_OPTS_USE_SESSION_KEY`` ``0x40000000`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_USE_SUBKEY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_USE_SUBKEY.rst.txt new file mode 100644 index 00000000..77bf41d9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_USE_SUBKEY.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _AP-OPTS-USE-SUBKEY-data: + +AP_OPTS_USE_SUBKEY +================== + +.. +.. data:: AP_OPTS_USE_SUBKEY +.. + +Generate a subsession key from the current session key obtained from the credentials. + + + +========================= ====================== +``AP_OPTS_USE_SUBKEY`` ``0x00000001`` +========================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_WIRE_MASK.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_WIRE_MASK.rst.txt new file mode 100644 index 00000000..36328d55 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/AP_OPTS_WIRE_MASK.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _AP-OPTS-WIRE-MASK-data: + +AP_OPTS_WIRE_MASK +================= + +.. +.. data:: AP_OPTS_WIRE_MASK +.. + + + + +======================== ====================== +``AP_OPTS_WIRE_MASK`` ``0xfffffff0`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128.rst.txt new file mode 100644 index 00000000..1a61f154 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _CKSUMTYPE-CMAC-CAMELLIA128-data: + +CKSUMTYPE_CMAC_CAMELLIA128 +========================== + +.. +.. data:: CKSUMTYPE_CMAC_CAMELLIA128 +.. + +RFC 6803. + + + +================================= ====================== +``CKSUMTYPE_CMAC_CAMELLIA128`` ``0x0011`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256.rst.txt new file mode 100644 index 00000000..91f2c166 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _CKSUMTYPE-CMAC-CAMELLIA256-data: + +CKSUMTYPE_CMAC_CAMELLIA256 +========================== + +.. +.. data:: CKSUMTYPE_CMAC_CAMELLIA256 +.. + +RFC 6803. + + + +================================= ====================== +``CKSUMTYPE_CMAC_CAMELLIA256`` ``0x0012`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_CRC32.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_CRC32.rst.txt new file mode 100644 index 00000000..6d0c4a31 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_CRC32.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _CKSUMTYPE-CRC32-data: + +CKSUMTYPE_CRC32 +=============== + +.. +.. data:: CKSUMTYPE_CRC32 +.. + + + + +====================== ====================== +``CKSUMTYPE_CRC32`` ``0x0001`` +====================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_DESCBC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_DESCBC.rst.txt new file mode 100644 index 00000000..830ddb88 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_DESCBC.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _CKSUMTYPE-DESCBC-data: + +CKSUMTYPE_DESCBC +================ + +.. +.. data:: CKSUMTYPE_DESCBC +.. + + + + +======================= ====================== +``CKSUMTYPE_DESCBC`` ``0x0004`` +======================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR.rst.txt new file mode 100644 index 00000000..9163bd36 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _CKSUMTYPE-HMAC-MD5-ARCFOUR-data: + +CKSUMTYPE_HMAC_MD5_ARCFOUR +========================== + +.. +.. data:: CKSUMTYPE_HMAC_MD5_ARCFOUR +.. + +RFC 4757. + + + +================================= ====================== +``CKSUMTYPE_HMAC_MD5_ARCFOUR`` ``-138`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128.rst.txt new file mode 100644 index 00000000..5d28bbe0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _CKSUMTYPE-HMAC-SHA1-96-AES128-data: + +CKSUMTYPE_HMAC_SHA1_96_AES128 +============================= + +.. +.. data:: CKSUMTYPE_HMAC_SHA1_96_AES128 +.. + +RFC 3962. + +Used with ENCTYPE_AES128_CTS_HMAC_SHA1_96 + +==================================== ====================== +``CKSUMTYPE_HMAC_SHA1_96_AES128`` ``0x000f`` +==================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256.rst.txt new file mode 100644 index 00000000..71ba018c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _CKSUMTYPE-HMAC-SHA1-96-AES256-data: + +CKSUMTYPE_HMAC_SHA1_96_AES256 +============================= + +.. +.. data:: CKSUMTYPE_HMAC_SHA1_96_AES256 +.. + +RFC 3962. + +Used with ENCTYPE_AES256_CTS_HMAC_SHA1_96 + +==================================== ====================== +``CKSUMTYPE_HMAC_SHA1_96_AES256`` ``0x0010`` +==================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3.rst.txt new file mode 100644 index 00000000..c6c76f2a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _CKSUMTYPE-HMAC-SHA1-DES3-data: + +CKSUMTYPE_HMAC_SHA1_DES3 +======================== + +.. +.. data:: CKSUMTYPE_HMAC_SHA1_DES3 +.. + + + + +=============================== ====================== +``CKSUMTYPE_HMAC_SHA1_DES3`` ``0x000c`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128.rst.txt new file mode 100644 index 00000000..77f956e0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _CKSUMTYPE-HMAC-SHA256-128-AES128-data: + +CKSUMTYPE_HMAC_SHA256_128_AES128 +================================ + +.. +.. data:: CKSUMTYPE_HMAC_SHA256_128_AES128 +.. + +RFC 8009. + + + +======================================= ====================== +``CKSUMTYPE_HMAC_SHA256_128_AES128`` ``0x0013`` +======================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256.rst.txt new file mode 100644 index 00000000..b95628d5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _CKSUMTYPE-HMAC-SHA384-192-AES256-data: + +CKSUMTYPE_HMAC_SHA384_192_AES256 +================================ + +.. +.. data:: CKSUMTYPE_HMAC_SHA384_192_AES256 +.. + +RFC 8009. + + + +======================================= ====================== +``CKSUMTYPE_HMAC_SHA384_192_AES256`` ``0x0014`` +======================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR.rst.txt new file mode 100644 index 00000000..97d84fe8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _CKSUMTYPE-MD5-HMAC-ARCFOUR-data: + +CKSUMTYPE_MD5_HMAC_ARCFOUR +========================== + +.. +.. data:: CKSUMTYPE_MD5_HMAC_ARCFOUR +.. + + + + +================================= ====================== +``CKSUMTYPE_MD5_HMAC_ARCFOUR`` ``-137 /* Microsoft netlogon */`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_NIST_SHA.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_NIST_SHA.rst.txt new file mode 100644 index 00000000..3524028e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_NIST_SHA.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _CKSUMTYPE-NIST-SHA-data: + +CKSUMTYPE_NIST_SHA +================== + +.. +.. data:: CKSUMTYPE_NIST_SHA +.. + + + + +========================= ====================== +``CKSUMTYPE_NIST_SHA`` ``0x0009`` +========================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD4.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD4.rst.txt new file mode 100644 index 00000000..02a4248b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD4.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _CKSUMTYPE-RSA-MD4-data: + +CKSUMTYPE_RSA_MD4 +================= + +.. +.. data:: CKSUMTYPE_RSA_MD4 +.. + + + + +======================== ====================== +``CKSUMTYPE_RSA_MD4`` ``0x0002`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES.rst.txt new file mode 100644 index 00000000..7e5cc058 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _CKSUMTYPE-RSA-MD4-DES-data: + +CKSUMTYPE_RSA_MD4_DES +===================== + +.. +.. data:: CKSUMTYPE_RSA_MD4_DES +.. + + + + +============================ ====================== +``CKSUMTYPE_RSA_MD4_DES`` ``0x0003`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD5.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD5.rst.txt new file mode 100644 index 00000000..e94f0b45 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD5.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _CKSUMTYPE-RSA-MD5-data: + +CKSUMTYPE_RSA_MD5 +================= + +.. +.. data:: CKSUMTYPE_RSA_MD5 +.. + + + + +======================== ====================== +``CKSUMTYPE_RSA_MD5`` ``0x0007`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES.rst.txt new file mode 100644 index 00000000..87c321f5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _CKSUMTYPE-RSA-MD5-DES-data: + +CKSUMTYPE_RSA_MD5_DES +===================== + +.. +.. data:: CKSUMTYPE_RSA_MD5_DES +.. + + + + +============================ ====================== +``CKSUMTYPE_RSA_MD5_DES`` ``0x0008`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_SHA1.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_SHA1.rst.txt new file mode 100644 index 00000000..a0f24bd5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/CKSUMTYPE_SHA1.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _CKSUMTYPE-SHA1-data: + +CKSUMTYPE_SHA1 +============== + +.. +.. data:: CKSUMTYPE_SHA1 +.. + +RFC 3961. + + + +===================== ====================== +``CKSUMTYPE_SHA1`` ``0x000e`` +===================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96.rst.txt new file mode 100644 index 00000000..b66ae72b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-AES128-CTS-HMAC-SHA1-96-data: + +ENCTYPE_AES128_CTS_HMAC_SHA1_96 +=============================== + +.. +.. data:: ENCTYPE_AES128_CTS_HMAC_SHA1_96 +.. + +RFC 3962. + + + +====================================== ====================== +``ENCTYPE_AES128_CTS_HMAC_SHA1_96`` ``0x0011`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128.rst.txt new file mode 100644 index 00000000..3f83a1bf --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-AES128-CTS-HMAC-SHA256-128-data: + +ENCTYPE_AES128_CTS_HMAC_SHA256_128 +================================== + +.. +.. data:: ENCTYPE_AES128_CTS_HMAC_SHA256_128 +.. + +RFC 8009. + + + +========================================= ====================== +``ENCTYPE_AES128_CTS_HMAC_SHA256_128`` ``0x0013`` +========================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96.rst.txt new file mode 100644 index 00000000..4d216964 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-AES256-CTS-HMAC-SHA1-96-data: + +ENCTYPE_AES256_CTS_HMAC_SHA1_96 +=============================== + +.. +.. data:: ENCTYPE_AES256_CTS_HMAC_SHA1_96 +.. + +RFC 3962. + + + +====================================== ====================== +``ENCTYPE_AES256_CTS_HMAC_SHA1_96`` ``0x0012`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192.rst.txt new file mode 100644 index 00000000..76c8e4b7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-AES256-CTS-HMAC-SHA384-192-data: + +ENCTYPE_AES256_CTS_HMAC_SHA384_192 +================================== + +.. +.. data:: ENCTYPE_AES256_CTS_HMAC_SHA384_192 +.. + +RFC 8009. + + + +========================================= ====================== +``ENCTYPE_AES256_CTS_HMAC_SHA384_192`` ``0x0014`` +========================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC.rst.txt new file mode 100644 index 00000000..54200453 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-ARCFOUR-HMAC-data: + +ENCTYPE_ARCFOUR_HMAC +==================== + +.. +.. data:: ENCTYPE_ARCFOUR_HMAC +.. + +RFC 4757. + + + +=========================== ====================== +``ENCTYPE_ARCFOUR_HMAC`` ``0x0017`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP.rst.txt new file mode 100644 index 00000000..140c3412 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-ARCFOUR-HMAC-EXP-data: + +ENCTYPE_ARCFOUR_HMAC_EXP +======================== + +.. +.. data:: ENCTYPE_ARCFOUR_HMAC_EXP +.. + +RFC 4757. + + + +=============================== ====================== +``ENCTYPE_ARCFOUR_HMAC_EXP`` ``0x0018`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC.rst.txt new file mode 100644 index 00000000..e08e8e3f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-CAMELLIA128-CTS-CMAC-data: + +ENCTYPE_CAMELLIA128_CTS_CMAC +============================ + +.. +.. data:: ENCTYPE_CAMELLIA128_CTS_CMAC +.. + +RFC 6803. + + + +=================================== ====================== +``ENCTYPE_CAMELLIA128_CTS_CMAC`` ``0x0019`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC.rst.txt new file mode 100644 index 00000000..7f7d64c8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-CAMELLIA256-CTS-CMAC-data: + +ENCTYPE_CAMELLIA256_CTS_CMAC +============================ + +.. +.. data:: ENCTYPE_CAMELLIA256_CTS_CMAC +.. + +RFC 6803. + + + +=================================== ====================== +``ENCTYPE_CAMELLIA256_CTS_CMAC`` ``0x001a`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_ENV.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_ENV.rst.txt new file mode 100644 index 00000000..62358d2f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_ENV.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-DES3-CBC-ENV-data: + +ENCTYPE_DES3_CBC_ENV +==================== + +.. +.. data:: ENCTYPE_DES3_CBC_ENV +.. + +DES-3 cbc mode, CMS enveloped data. + + + +=========================== ====================== +``ENCTYPE_DES3_CBC_ENV`` ``0x000f`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_RAW.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_RAW.rst.txt new file mode 100644 index 00000000..1f323133 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_RAW.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ENCTYPE-DES3-CBC-RAW-data: + +ENCTYPE_DES3_CBC_RAW +==================== + +.. +.. data:: ENCTYPE_DES3_CBC_RAW +.. + + + + +=========================== ====================== +``ENCTYPE_DES3_CBC_RAW`` ``0x0006`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA.rst.txt new file mode 100644 index 00000000..3d14182b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ENCTYPE-DES3-CBC-SHA-data: + +ENCTYPE_DES3_CBC_SHA +==================== + +.. +.. data:: ENCTYPE_DES3_CBC_SHA +.. + + + + +=========================== ====================== +``ENCTYPE_DES3_CBC_SHA`` ``0x0005`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1.rst.txt new file mode 100644 index 00000000..6ad9a185 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ENCTYPE-DES3-CBC-SHA1-data: + +ENCTYPE_DES3_CBC_SHA1 +===================== + +.. +.. data:: ENCTYPE_DES3_CBC_SHA1 +.. + + + + +============================ ====================== +``ENCTYPE_DES3_CBC_SHA1`` ``0x0010`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_CRC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_CRC.rst.txt new file mode 100644 index 00000000..a442821b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_CRC.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ENCTYPE-DES-CBC-CRC-data: + +ENCTYPE_DES_CBC_CRC +=================== + +.. +.. data:: ENCTYPE_DES_CBC_CRC +.. + + + + +========================== ====================== +``ENCTYPE_DES_CBC_CRC`` ``0x0001`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_MD4.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_MD4.rst.txt new file mode 100644 index 00000000..2b227deb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_MD4.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ENCTYPE-DES-CBC-MD4-data: + +ENCTYPE_DES_CBC_MD4 +=================== + +.. +.. data:: ENCTYPE_DES_CBC_MD4 +.. + + + + +========================== ====================== +``ENCTYPE_DES_CBC_MD4`` ``0x0002`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_MD5.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_MD5.rst.txt new file mode 100644 index 00000000..d4edca90 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_MD5.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ENCTYPE-DES-CBC-MD5-data: + +ENCTYPE_DES_CBC_MD5 +=================== + +.. +.. data:: ENCTYPE_DES_CBC_MD5 +.. + + + + +========================== ====================== +``ENCTYPE_DES_CBC_MD5`` ``0x0003`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_RAW.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_RAW.rst.txt new file mode 100644 index 00000000..e3de8120 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_CBC_RAW.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ENCTYPE-DES-CBC-RAW-data: + +ENCTYPE_DES_CBC_RAW +=================== + +.. +.. data:: ENCTYPE_DES_CBC_RAW +.. + + + + +========================== ====================== +``ENCTYPE_DES_CBC_RAW`` ``0x0004`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1.rst.txt new file mode 100644 index 00000000..9494faed --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ENCTYPE-DES-HMAC-SHA1-data: + +ENCTYPE_DES_HMAC_SHA1 +===================== + +.. +.. data:: ENCTYPE_DES_HMAC_SHA1 +.. + + + + +============================ ====================== +``ENCTYPE_DES_HMAC_SHA1`` ``0x0008`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS.rst.txt new file mode 100644 index 00000000..fca77e48 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-DSA-SHA1-CMS-data: + +ENCTYPE_DSA_SHA1_CMS +==================== + +.. +.. data:: ENCTYPE_DSA_SHA1_CMS +.. + +DSA with SHA1, CMS signature. + + + +=========================== ====================== +``ENCTYPE_DSA_SHA1_CMS`` ``0x0009`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_MD5_RSA_CMS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_MD5_RSA_CMS.rst.txt new file mode 100644 index 00000000..5d4cc6b5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_MD5_RSA_CMS.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-MD5-RSA-CMS-data: + +ENCTYPE_MD5_RSA_CMS +=================== + +.. +.. data:: ENCTYPE_MD5_RSA_CMS +.. + +MD5 with RSA, CMS signature. + + + +========================== ====================== +``ENCTYPE_MD5_RSA_CMS`` ``0x000a`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_NULL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_NULL.rst.txt new file mode 100644 index 00000000..1a62c065 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_NULL.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ENCTYPE-NULL-data: + +ENCTYPE_NULL +============ + +.. +.. data:: ENCTYPE_NULL +.. + + + + +=================== ====================== +``ENCTYPE_NULL`` ``0x0000`` +=================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_RC2_CBC_ENV.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_RC2_CBC_ENV.rst.txt new file mode 100644 index 00000000..3dc732bb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_RC2_CBC_ENV.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-RC2-CBC-ENV-data: + +ENCTYPE_RC2_CBC_ENV +=================== + +.. +.. data:: ENCTYPE_RC2_CBC_ENV +.. + +RC2 cbc mode, CMS enveloped data. + + + +========================== ====================== +``ENCTYPE_RC2_CBC_ENV`` ``0x000c`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_RSA_ENV.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_RSA_ENV.rst.txt new file mode 100644 index 00000000..0f065716 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_RSA_ENV.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-RSA-ENV-data: + +ENCTYPE_RSA_ENV +=============== + +.. +.. data:: ENCTYPE_RSA_ENV +.. + +RSA encryption, CMS enveloped data. + + + +====================== ====================== +``ENCTYPE_RSA_ENV`` ``0x000d`` +====================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV.rst.txt new file mode 100644 index 00000000..1d7cfc0d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-RSA-ES-OAEP-ENV-data: + +ENCTYPE_RSA_ES_OAEP_ENV +======================= + +.. +.. data:: ENCTYPE_RSA_ES_OAEP_ENV +.. + +RSA w/OEAP encryption, CMS enveloped data. + + + +============================== ====================== +``ENCTYPE_RSA_ES_OAEP_ENV`` ``0x000e`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS.rst.txt new file mode 100644 index 00000000..a8cfe754 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _ENCTYPE-SHA1-RSA-CMS-data: + +ENCTYPE_SHA1_RSA_CMS +==================== + +.. +.. data:: ENCTYPE_SHA1_RSA_CMS +.. + +SHA1 with RSA, CMS signature. + + + +=========================== ====================== +``ENCTYPE_SHA1_RSA_CMS`` ``0x000b`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_UNKNOWN.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_UNKNOWN.rst.txt new file mode 100644 index 00000000..44f86879 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/ENCTYPE_UNKNOWN.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _ENCTYPE-UNKNOWN-data: + +ENCTYPE_UNKNOWN +=============== + +.. +.. data:: ENCTYPE_UNKNOWN +.. + + + + +====================== ====================== +``ENCTYPE_UNKNOWN`` ``0x01ff`` +====================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE.rst.txt new file mode 100644 index 00000000..64508eeb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-ALLOW-POSTDATE-data: + +KDC_OPT_ALLOW_POSTDATE +====================== + +.. +.. data:: KDC_OPT_ALLOW_POSTDATE +.. + + + + +============================= ====================== +``KDC_OPT_ALLOW_POSTDATE`` ``0x04000000`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_CANONICALIZE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_CANONICALIZE.rst.txt new file mode 100644 index 00000000..05f20bdc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_CANONICALIZE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-CANONICALIZE-data: + +KDC_OPT_CANONICALIZE +==================== + +.. +.. data:: KDC_OPT_CANONICALIZE +.. + + + + +=========================== ====================== +``KDC_OPT_CANONICALIZE`` ``0x00010000`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT.rst.txt new file mode 100644 index 00000000..bf9a9717 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-CNAME-IN-ADDL-TKT-data: + +KDC_OPT_CNAME_IN_ADDL_TKT +========================= + +.. +.. data:: KDC_OPT_CNAME_IN_ADDL_TKT +.. + + + + +================================ ====================== +``KDC_OPT_CNAME_IN_ADDL_TKT`` ``0x00020000`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK.rst.txt new file mode 100644 index 00000000..c0ac5294 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-DISABLE-TRANSITED-CHECK-data: + +KDC_OPT_DISABLE_TRANSITED_CHECK +=============================== + +.. +.. data:: KDC_OPT_DISABLE_TRANSITED_CHECK +.. + + + + +====================================== ====================== +``KDC_OPT_DISABLE_TRANSITED_CHECK`` ``0x00000020`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY.rst.txt new file mode 100644 index 00000000..ca72eccd --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-ENC-TKT-IN-SKEY-data: + +KDC_OPT_ENC_TKT_IN_SKEY +======================= + +.. +.. data:: KDC_OPT_ENC_TKT_IN_SKEY +.. + + + + +============================== ====================== +``KDC_OPT_ENC_TKT_IN_SKEY`` ``0x00000008`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_FORWARDABLE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_FORWARDABLE.rst.txt new file mode 100644 index 00000000..171ea002 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_FORWARDABLE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-FORWARDABLE-data: + +KDC_OPT_FORWARDABLE +=================== + +.. +.. data:: KDC_OPT_FORWARDABLE +.. + + + + +========================== ====================== +``KDC_OPT_FORWARDABLE`` ``0x40000000`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_FORWARDED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_FORWARDED.rst.txt new file mode 100644 index 00000000..ddfd30c8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_FORWARDED.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-FORWARDED-data: + +KDC_OPT_FORWARDED +================= + +.. +.. data:: KDC_OPT_FORWARDED +.. + + + + +======================== ====================== +``KDC_OPT_FORWARDED`` ``0x20000000`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_POSTDATED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_POSTDATED.rst.txt new file mode 100644 index 00000000..a6af6435 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_POSTDATED.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-POSTDATED-data: + +KDC_OPT_POSTDATED +================= + +.. +.. data:: KDC_OPT_POSTDATED +.. + + + + +======================== ====================== +``KDC_OPT_POSTDATED`` ``0x02000000`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_PROXIABLE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_PROXIABLE.rst.txt new file mode 100644 index 00000000..5a874547 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_PROXIABLE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-PROXIABLE-data: + +KDC_OPT_PROXIABLE +================= + +.. +.. data:: KDC_OPT_PROXIABLE +.. + + + + +======================== ====================== +``KDC_OPT_PROXIABLE`` ``0x10000000`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_PROXY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_PROXY.rst.txt new file mode 100644 index 00000000..64c4f0ae --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_PROXY.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-PROXY-data: + +KDC_OPT_PROXY +============= + +.. +.. data:: KDC_OPT_PROXY +.. + + + + +==================== ====================== +``KDC_OPT_PROXY`` ``0x08000000`` +==================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_RENEW.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_RENEW.rst.txt new file mode 100644 index 00000000..23e48761 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_RENEW.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-RENEW-data: + +KDC_OPT_RENEW +============= + +.. +.. data:: KDC_OPT_RENEW +.. + + + + +==================== ====================== +``KDC_OPT_RENEW`` ``0x00000002`` +==================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_RENEWABLE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_RENEWABLE.rst.txt new file mode 100644 index 00000000..d7f13ca5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_RENEWABLE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-RENEWABLE-data: + +KDC_OPT_RENEWABLE +================= + +.. +.. data:: KDC_OPT_RENEWABLE +.. + + + + +======================== ====================== +``KDC_OPT_RENEWABLE`` ``0x00800000`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_RENEWABLE_OK.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_RENEWABLE_OK.rst.txt new file mode 100644 index 00000000..0d082e1a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_RENEWABLE_OK.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-RENEWABLE-OK-data: + +KDC_OPT_RENEWABLE_OK +==================== + +.. +.. data:: KDC_OPT_RENEWABLE_OK +.. + + + + +=========================== ====================== +``KDC_OPT_RENEWABLE_OK`` ``0x00000010`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS.rst.txt new file mode 100644 index 00000000..7a14ec6e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-REQUEST-ANONYMOUS-data: + +KDC_OPT_REQUEST_ANONYMOUS +========================= + +.. +.. data:: KDC_OPT_REQUEST_ANONYMOUS +.. + + + + +================================ ====================== +``KDC_OPT_REQUEST_ANONYMOUS`` ``0x00008000`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_VALIDATE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_VALIDATE.rst.txt new file mode 100644 index 00000000..666beccb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_OPT_VALIDATE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-OPT-VALIDATE-data: + +KDC_OPT_VALIDATE +================ + +.. +.. data:: KDC_OPT_VALIDATE +.. + + + + +======================= ====================== +``KDC_OPT_VALIDATE`` ``0x00000001`` +======================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_TKT_COMMON_MASK.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_TKT_COMMON_MASK.rst.txt new file mode 100644 index 00000000..e2cb9603 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KDC_TKT_COMMON_MASK.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KDC-TKT-COMMON-MASK-data: + +KDC_TKT_COMMON_MASK +=================== + +.. +.. data:: KDC_TKT_COMMON_MASK +.. + + + + +========================== ====================== +``KDC_TKT_COMMON_MASK`` ``0x54800000`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE.rst.txt new file mode 100644 index 00000000..ddc0ea0e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-ALTAUTH-ATT-CHALLENGE-RESPONSE-data: + +KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE +=================================== + +.. +.. data:: KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE +.. + +alternate authentication types + + + +========================================== ====================== +``KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE`` ``64`` +========================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR.rst.txt new file mode 100644 index 00000000..1d1644e3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-ANONYMOUS-PRINCSTR-data: + +KRB5_ANONYMOUS_PRINCSTR +======================= + +.. +.. data:: KRB5_ANONYMOUS_PRINCSTR +.. + +Anonymous principal name. + + + +============================== ====================== +``KRB5_ANONYMOUS_PRINCSTR`` ``"ANONYMOUS"`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR.rst.txt new file mode 100644 index 00000000..e9ab94d0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-ANONYMOUS-REALMSTR-data: + +KRB5_ANONYMOUS_REALMSTR +======================= + +.. +.. data:: KRB5_ANONYMOUS_REALMSTR +.. + +Anonymous realm. + + + +============================== ====================== +``KRB5_ANONYMOUS_REALMSTR`` ``"WELLKNOWN:ANONYMOUS"`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AP_REP.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AP_REP.rst.txt new file mode 100644 index 00000000..4e50adf4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AP_REP.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-AP-REP-data: + +KRB5_AP_REP +=========== + +.. +.. data:: KRB5_AP_REP +.. + +Response to mutual AP request. + + + +================== ====================== +``KRB5_AP_REP`` ``((krb5_msgtype)15)`` +================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AP_REQ.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AP_REQ.rst.txt new file mode 100644 index 00000000..e92d37ea --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AP_REQ.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-AP-REQ-data: + +KRB5_AP_REQ +=========== + +.. +.. data:: KRB5_AP_REQ +.. + +Auth req to application server. + + + +================== ====================== +``KRB5_AP_REQ`` ``((krb5_msgtype)14)`` +================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AS_REP.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AS_REP.rst.txt new file mode 100644 index 00000000..69eb7041 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AS_REP.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-AS-REP-data: + +KRB5_AS_REP +=========== + +.. +.. data:: KRB5_AS_REP +.. + +Response to AS request. + + + +================== ====================== +``KRB5_AS_REP`` ``((krb5_msgtype)11)`` +================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AS_REQ.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AS_REQ.rst.txt new file mode 100644 index 00000000..85501063 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AS_REQ.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-AS-REQ-data: + +KRB5_AS_REQ +=========== + +.. +.. data:: KRB5_AS_REQ +.. + +Initial authentication request. + + + +================== ====================== +``KRB5_AS_REQ`` ``((krb5_msgtype)10)`` +================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_AND_OR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_AND_OR.rst.txt new file mode 100644 index 00000000..a1abcbd2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_AND_OR.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-AND-OR-data: + +KRB5_AUTHDATA_AND_OR +==================== + +.. +.. data:: KRB5_AUTHDATA_AND_OR +.. + + + + +=========================== ====================== +``KRB5_AUTHDATA_AND_OR`` ``5`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS.rst.txt new file mode 100644 index 00000000..87970252 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-AP-OPTIONS-data: + +KRB5_AUTHDATA_AP_OPTIONS +======================== + +.. +.. data:: KRB5_AUTHDATA_AP_OPTIONS +.. + + + + +=============================== ====================== +``KRB5_AUTHDATA_AP_OPTIONS`` ``143`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR.rst.txt new file mode 100644 index 00000000..ae1178ea --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-AUTH-INDICATOR-data: + +KRB5_AUTHDATA_AUTH_INDICATOR +============================ + +.. +.. data:: KRB5_AUTHDATA_AUTH_INDICATOR +.. + + + + +=================================== ====================== +``KRB5_AUTHDATA_AUTH_INDICATOR`` ``97`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_CAMMAC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_CAMMAC.rst.txt new file mode 100644 index 00000000..e6a239ea --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_CAMMAC.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-CAMMAC-data: + +KRB5_AUTHDATA_CAMMAC +==================== + +.. +.. data:: KRB5_AUTHDATA_CAMMAC +.. + + + + +=========================== ====================== +``KRB5_AUTHDATA_CAMMAC`` ``96`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION.rst.txt new file mode 100644 index 00000000..04621391 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-ETYPE-NEGOTIATION-data: + +KRB5_AUTHDATA_ETYPE_NEGOTIATION +=============================== + +.. +.. data:: KRB5_AUTHDATA_ETYPE_NEGOTIATION +.. + +RFC 4537. + + + +====================================== ====================== +``KRB5_AUTHDATA_ETYPE_NEGOTIATION`` ``129`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR.rst.txt new file mode 100644 index 00000000..1982e835 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-FX-ARMOR-data: + +KRB5_AUTHDATA_FX_ARMOR +====================== + +.. +.. data:: KRB5_AUTHDATA_FX_ARMOR +.. + + + + +============================= ====================== +``KRB5_AUTHDATA_FX_ARMOR`` ``71`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT.rst.txt new file mode 100644 index 00000000..ff0b2439 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-IF-RELEVANT-data: + +KRB5_AUTHDATA_IF_RELEVANT +========================= + +.. +.. data:: KRB5_AUTHDATA_IF_RELEVANT +.. + + + + +================================ ====================== +``KRB5_AUTHDATA_IF_RELEVANT`` ``1`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS.rst.txt new file mode 100644 index 00000000..5e76101c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-INITIAL-VERIFIED-CAS-data: + +KRB5_AUTHDATA_INITIAL_VERIFIED_CAS +================================== + +.. +.. data:: KRB5_AUTHDATA_INITIAL_VERIFIED_CAS +.. + + + + +========================================= ====================== +``KRB5_AUTHDATA_INITIAL_VERIFIED_CAS`` ``9`` +========================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED.rst.txt new file mode 100644 index 00000000..e566040c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-KDC-ISSUED-data: + +KRB5_AUTHDATA_KDC_ISSUED +======================== + +.. +.. data:: KRB5_AUTHDATA_KDC_ISSUED +.. + + + + +=============================== ====================== +``KRB5_AUTHDATA_KDC_ISSUED`` ``4`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC.rst.txt new file mode 100644 index 00000000..50eacee7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-MANDATORY-FOR-KDC-data: + +KRB5_AUTHDATA_MANDATORY_FOR_KDC +=============================== + +.. +.. data:: KRB5_AUTHDATA_MANDATORY_FOR_KDC +.. + + + + +====================================== ====================== +``KRB5_AUTHDATA_MANDATORY_FOR_KDC`` ``8`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE.rst.txt new file mode 100644 index 00000000..a545b9fa --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-OSF-DCE-data: + +KRB5_AUTHDATA_OSF_DCE +===================== + +.. +.. data:: KRB5_AUTHDATA_OSF_DCE +.. + + + + +============================ ====================== +``KRB5_AUTHDATA_OSF_DCE`` ``64`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_SESAME.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_SESAME.rst.txt new file mode 100644 index 00000000..c21e3a11 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_SESAME.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-SESAME-data: + +KRB5_AUTHDATA_SESAME +==================== + +.. +.. data:: KRB5_AUTHDATA_SESAME +.. + + + + +=========================== ====================== +``KRB5_AUTHDATA_SESAME`` ``65`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET.rst.txt new file mode 100644 index 00000000..cff5f6f7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-SIGNTICKET-data: + +KRB5_AUTHDATA_SIGNTICKET +======================== + +.. +.. data:: KRB5_AUTHDATA_SIGNTICKET +.. + + + + +=============================== ====================== +``KRB5_AUTHDATA_SIGNTICKET`` ``512`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC.rst.txt new file mode 100644 index 00000000..b7ecde0b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTHDATA-WIN2K-PAC-data: + +KRB5_AUTHDATA_WIN2K_PAC +======================= + +.. +.. data:: KRB5_AUTHDATA_WIN2K_PAC +.. + + + + +============================== ====================== +``KRB5_AUTHDATA_WIN2K_PAC`` ``128`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE.rst.txt new file mode 100644 index 00000000..b0e214c1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-AUTH-CONTEXT-DO-SEQUENCE-data: + +KRB5_AUTH_CONTEXT_DO_SEQUENCE +============================= + +.. +.. data:: KRB5_AUTH_CONTEXT_DO_SEQUENCE +.. + +Prevent replays with sequence numbers. + + + +==================================== ====================== +``KRB5_AUTH_CONTEXT_DO_SEQUENCE`` ``0x00000004`` +==================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME.rst.txt new file mode 100644 index 00000000..09815b7b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-AUTH-CONTEXT-DO-TIME-data: + +KRB5_AUTH_CONTEXT_DO_TIME +========================= + +.. +.. data:: KRB5_AUTH_CONTEXT_DO_TIME +.. + +Prevent replays with timestamps and replay cache. + + + +================================ ====================== +``KRB5_AUTH_CONTEXT_DO_TIME`` ``0x00000001`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR.rst.txt new file mode 100644 index 00000000..16a15cff --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-AUTH-CONTEXT-GENERATE-LOCAL-ADDR-data: + +KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR +===================================== + +.. +.. data:: KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR +.. + +Generate the local network address. + + + +============================================ ====================== +``KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR`` ``0x00000001`` +============================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR.rst.txt new file mode 100644 index 00000000..b74824f0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-AUTH-CONTEXT-GENERATE-LOCAL-FULL-ADDR-data: + +KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR +========================================== + +.. +.. data:: KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR +.. + +Generate the local network address and the local port. + + + +================================================= ====================== +``KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR`` ``0x00000004`` +================================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR.rst.txt new file mode 100644 index 00000000..d8ee93bd --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-AUTH-CONTEXT-GENERATE-REMOTE-ADDR-data: + +KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR +====================================== + +.. +.. data:: KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR +.. + +Generate the remote network address. + + + +============================================= ====================== +``KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR`` ``0x00000002`` +============================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR.rst.txt new file mode 100644 index 00000000..a70428ab --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-AUTH-CONTEXT-GENERATE-REMOTE-FULL-ADDR-data: + +KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR +=========================================== + +.. +.. data:: KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR +.. + +Generate the remote network address and the remote port. + + + +================================================== ====================== +``KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR`` ``0x00000008`` +================================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL.rst.txt new file mode 100644 index 00000000..7ed17e79 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTH-CONTEXT-PERMIT-ALL-data: + +KRB5_AUTH_CONTEXT_PERMIT_ALL +============================ + +.. +.. data:: KRB5_AUTH_CONTEXT_PERMIT_ALL +.. + + + + +=================================== ====================== +``KRB5_AUTH_CONTEXT_PERMIT_ALL`` ``0x00000010`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE.rst.txt new file mode 100644 index 00000000..d9e67d66 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-AUTH-CONTEXT-RET-SEQUENCE-data: + +KRB5_AUTH_CONTEXT_RET_SEQUENCE +============================== + +.. +.. data:: KRB5_AUTH_CONTEXT_RET_SEQUENCE +.. + +Save sequence numbers for application. + + + +===================================== ====================== +``KRB5_AUTH_CONTEXT_RET_SEQUENCE`` ``0x00000008`` +===================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME.rst.txt new file mode 100644 index 00000000..bebc83d9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-AUTH-CONTEXT-RET-TIME-data: + +KRB5_AUTH_CONTEXT_RET_TIME +========================== + +.. +.. data:: KRB5_AUTH_CONTEXT_RET_TIME +.. + +Save timestamps for application. + + + +================================= ====================== +``KRB5_AUTH_CONTEXT_RET_TIME`` ``0x00000002`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY.rst.txt new file mode 100644 index 00000000..481e7557 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-AUTH-CONTEXT-USE-SUBKEY-data: + +KRB5_AUTH_CONTEXT_USE_SUBKEY +============================ + +.. +.. data:: KRB5_AUTH_CONTEXT_USE_SUBKEY +.. + + + + +=================================== ====================== +``KRB5_AUTH_CONTEXT_USE_SUBKEY`` ``0x00000020`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRED.rst.txt new file mode 100644 index 00000000..f4cb55e7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRED.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-CRED-data: + +KRB5_CRED +========= + +.. +.. data:: KRB5_CRED +.. + +Cred forwarding message. + + + +================ ====================== +``KRB5_CRED`` ``((krb5_msgtype)22)`` +================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM.rst.txt new file mode 100644 index 00000000..f882f79b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-CRYPTO-TYPE-CHECKSUM-data: + +KRB5_CRYPTO_TYPE_CHECKSUM +========================= + +.. +.. data:: KRB5_CRYPTO_TYPE_CHECKSUM +.. + +[out] checksum for MIC + + + +================================ ====================== +``KRB5_CRYPTO_TYPE_CHECKSUM`` ``6`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA.rst.txt new file mode 100644 index 00000000..2dd2ea41 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-CRYPTO-TYPE-DATA-data: + +KRB5_CRYPTO_TYPE_DATA +===================== + +.. +.. data:: KRB5_CRYPTO_TYPE_DATA +.. + +[in, out] plaintext + + + +============================ ====================== +``KRB5_CRYPTO_TYPE_DATA`` ``2`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY.rst.txt new file mode 100644 index 00000000..dab70ced --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-CRYPTO-TYPE-EMPTY-data: + +KRB5_CRYPTO_TYPE_EMPTY +====================== + +.. +.. data:: KRB5_CRYPTO_TYPE_EMPTY +.. + +[in] ignored + + + +============================= ====================== +``KRB5_CRYPTO_TYPE_EMPTY`` ``0`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER.rst.txt new file mode 100644 index 00000000..a3263c24 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-CRYPTO-TYPE-HEADER-data: + +KRB5_CRYPTO_TYPE_HEADER +======================= + +.. +.. data:: KRB5_CRYPTO_TYPE_HEADER +.. + +[out] header + + + +============================== ====================== +``KRB5_CRYPTO_TYPE_HEADER`` ``1`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING.rst.txt new file mode 100644 index 00000000..44d50728 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-CRYPTO-TYPE-PADDING-data: + +KRB5_CRYPTO_TYPE_PADDING +======================== + +.. +.. data:: KRB5_CRYPTO_TYPE_PADDING +.. + +[out] padding + + + +=============================== ====================== +``KRB5_CRYPTO_TYPE_PADDING`` ``4`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY.rst.txt new file mode 100644 index 00000000..a8b9f8a8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-CRYPTO-TYPE-SIGN-ONLY-data: + +KRB5_CRYPTO_TYPE_SIGN_ONLY +========================== + +.. +.. data:: KRB5_CRYPTO_TYPE_SIGN_ONLY +.. + +[in] associated data + + + +================================= ====================== +``KRB5_CRYPTO_TYPE_SIGN_ONLY`` ``3`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM.rst.txt new file mode 100644 index 00000000..e58f6825 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-CRYPTO-TYPE-STREAM-data: + +KRB5_CRYPTO_TYPE_STREAM +======================= + +.. +.. data:: KRB5_CRYPTO_TYPE_STREAM +.. + +[in] entire message without decomposing the structure into header, data and trailer buffers + + + +============================== ====================== +``KRB5_CRYPTO_TYPE_STREAM`` ``7`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER.rst.txt new file mode 100644 index 00000000..bf78ea02 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-CRYPTO-TYPE-TRAILER-data: + +KRB5_CRYPTO_TYPE_TRAILER +======================== + +.. +.. data:: KRB5_CRYPTO_TYPE_TRAILER +.. + +[out] checksum for encrypt + + + +=============================== ====================== +``KRB5_CRYPTO_TYPE_TRAILER`` ``5`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CYBERSAFE_SECUREID.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CYBERSAFE_SECUREID.rst.txt new file mode 100644 index 00000000..0b79861b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_CYBERSAFE_SECUREID.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-CYBERSAFE-SECUREID-data: + +KRB5_CYBERSAFE_SECUREID +======================= + +.. +.. data:: KRB5_CYBERSAFE_SECUREID +.. + +Cybersafe. + +RFC 4120 + +============================== ====================== +``KRB5_CYBERSAFE_SECUREID`` ``9`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS.rst.txt new file mode 100644 index 00000000..7bf71f8f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-DOMAIN-X500-COMPRESS-data: + +KRB5_DOMAIN_X500_COMPRESS +========================= + +.. +.. data:: KRB5_DOMAIN_X500_COMPRESS +.. + +Transited encoding types. + + + +================================ ====================== +``KRB5_DOMAIN_X500_COMPRESS`` ``1`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP.rst.txt new file mode 100644 index 00000000..fe828898 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-ENCPADATA-REQ-ENC-PA-REP-data: + +KRB5_ENCPADATA_REQ_ENC_PA_REP +============================= + +.. +.. data:: KRB5_ENCPADATA_REQ_ENC_PA_REP +.. + +RFC 6806. + + + +==================================== ====================== +``KRB5_ENCPADATA_REQ_ENC_PA_REP`` ``149`` +==================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ERROR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ERROR.rst.txt new file mode 100644 index 00000000..901f9452 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_ERROR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-ERROR-data: + +KRB5_ERROR +========== + +.. +.. data:: KRB5_ERROR +.. + +Error response. + + + +================= ====================== +``KRB5_ERROR`` ``((krb5_msgtype)30)`` +================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_FAST_REQUIRED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_FAST_REQUIRED.rst.txt new file mode 100644 index 00000000..936423d2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_FAST_REQUIRED.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-FAST-REQUIRED-data: + +KRB5_FAST_REQUIRED +================== + +.. +.. data:: KRB5_FAST_REQUIRED +.. + +Require KDC to support FAST. + + + +========================= ====================== +``KRB5_FAST_REQUIRED`` ``0x0001`` +========================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_CACHED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_CACHED.rst.txt new file mode 100644 index 00000000..df1e7e5f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_CACHED.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-GC-CACHED-data: + +KRB5_GC_CACHED +============== + +.. +.. data:: KRB5_GC_CACHED +.. + +Want cached ticket only. + + + +===================== ====================== +``KRB5_GC_CACHED`` ``2`` +===================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_CANONICALIZE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_CANONICALIZE.rst.txt new file mode 100644 index 00000000..93ea301b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_CANONICALIZE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-GC-CANONICALIZE-data: + +KRB5_GC_CANONICALIZE +==================== + +.. +.. data:: KRB5_GC_CANONICALIZE +.. + +Set canonicalize KDC option. + + + +=========================== ====================== +``KRB5_GC_CANONICALIZE`` ``4`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION.rst.txt new file mode 100644 index 00000000..3a3ed03a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-GC-CONSTRAINED-DELEGATION-data: + +KRB5_GC_CONSTRAINED_DELEGATION +============================== + +.. +.. data:: KRB5_GC_CONSTRAINED_DELEGATION +.. + +Constrained delegation. + + + +===================================== ====================== +``KRB5_GC_CONSTRAINED_DELEGATION`` ``64`` +===================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_FORWARDABLE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_FORWARDABLE.rst.txt new file mode 100644 index 00000000..0fbe57a9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_FORWARDABLE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-GC-FORWARDABLE-data: + +KRB5_GC_FORWARDABLE +=================== + +.. +.. data:: KRB5_GC_FORWARDABLE +.. + +Acquire forwardable tickets. + + + +========================== ====================== +``KRB5_GC_FORWARDABLE`` ``16`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_NO_STORE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_NO_STORE.rst.txt new file mode 100644 index 00000000..1640bc29 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_NO_STORE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-GC-NO-STORE-data: + +KRB5_GC_NO_STORE +================ + +.. +.. data:: KRB5_GC_NO_STORE +.. + +Do not store in credential cache. + + + +======================= ====================== +``KRB5_GC_NO_STORE`` ``8`` +======================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK.rst.txt new file mode 100644 index 00000000..da1b5cd7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-GC-NO-TRANSIT-CHECK-data: + +KRB5_GC_NO_TRANSIT_CHECK +======================== + +.. +.. data:: KRB5_GC_NO_TRANSIT_CHECK +.. + +Disable transited check. + + + +=============================== ====================== +``KRB5_GC_NO_TRANSIT_CHECK`` ``32`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_USER_USER.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_USER_USER.rst.txt new file mode 100644 index 00000000..2fc073f8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GC_USER_USER.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-GC-USER-USER-data: + +KRB5_GC_USER_USER +================= + +.. +.. data:: KRB5_GC_USER_USER +.. + +Want user-user ticket. + + + +======================== ====================== +``KRB5_GC_USER_USER`` ``1`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST.rst.txt new file mode 100644 index 00000000..d0ae5fb9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-GET-INIT-CREDS-OPT-ADDRESS-LIST-data: + +KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST +==================================== + +.. +.. data:: KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST +.. + + + + +=========================================== ====================== +``KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST`` ``0x0020`` +=========================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS.rst.txt new file mode 100644 index 00000000..2f4281ee --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-GET-INIT-CREDS-OPT-ANONYMOUS-data: + +KRB5_GET_INIT_CREDS_OPT_ANONYMOUS +================================= + +.. +.. data:: KRB5_GET_INIT_CREDS_OPT_ANONYMOUS +.. + + + + +======================================== ====================== +``KRB5_GET_INIT_CREDS_OPT_ANONYMOUS`` ``0x0400`` +======================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE.rst.txt new file mode 100644 index 00000000..921c8730 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-GET-INIT-CREDS-OPT-CANONICALIZE-data: + +KRB5_GET_INIT_CREDS_OPT_CANONICALIZE +==================================== + +.. +.. data:: KRB5_GET_INIT_CREDS_OPT_CANONICALIZE +.. + + + + +=========================================== ====================== +``KRB5_GET_INIT_CREDS_OPT_CANONICALIZE`` ``0x0200`` +=========================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT.rst.txt new file mode 100644 index 00000000..5182abf8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-GET-INIT-CREDS-OPT-CHG-PWD-PRMPT-data: + +KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT +===================================== + +.. +.. data:: KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT +.. + + + + +============================================ ====================== +``KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT`` ``0x0100`` +============================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST.rst.txt new file mode 100644 index 00000000..975417af --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-GET-INIT-CREDS-OPT-ETYPE-LIST-data: + +KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST +================================== + +.. +.. data:: KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST +.. + + + + +========================================= ====================== +``KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST`` ``0x0010`` +========================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE.rst.txt new file mode 100644 index 00000000..8946b555 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-GET-INIT-CREDS-OPT-FORWARDABLE-data: + +KRB5_GET_INIT_CREDS_OPT_FORWARDABLE +=================================== + +.. +.. data:: KRB5_GET_INIT_CREDS_OPT_FORWARDABLE +.. + + + + +========================================== ====================== +``KRB5_GET_INIT_CREDS_OPT_FORWARDABLE`` ``0x0004`` +========================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST.rst.txt new file mode 100644 index 00000000..023783c6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-GET-INIT-CREDS-OPT-PREAUTH-LIST-data: + +KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST +==================================== + +.. +.. data:: KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST +.. + + + + +=========================================== ====================== +``KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST`` ``0x0040`` +=========================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE.rst.txt new file mode 100644 index 00000000..5cb3217f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-GET-INIT-CREDS-OPT-PROXIABLE-data: + +KRB5_GET_INIT_CREDS_OPT_PROXIABLE +================================= + +.. +.. data:: KRB5_GET_INIT_CREDS_OPT_PROXIABLE +.. + + + + +======================================== ====================== +``KRB5_GET_INIT_CREDS_OPT_PROXIABLE`` ``0x0008`` +======================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE.rst.txt new file mode 100644 index 00000000..342ad6fc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-GET-INIT-CREDS-OPT-RENEW-LIFE-data: + +KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE +================================== + +.. +.. data:: KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE +.. + + + + +========================================= ====================== +``KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE`` ``0x0002`` +========================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT.rst.txt new file mode 100644 index 00000000..f3854eb0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-GET-INIT-CREDS-OPT-SALT-data: + +KRB5_GET_INIT_CREDS_OPT_SALT +============================ + +.. +.. data:: KRB5_GET_INIT_CREDS_OPT_SALT +.. + + + + +=================================== ====================== +``KRB5_GET_INIT_CREDS_OPT_SALT`` ``0x0080`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE.rst.txt new file mode 100644 index 00000000..9f719b86 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-GET-INIT-CREDS-OPT-TKT-LIFE-data: + +KRB5_GET_INIT_CREDS_OPT_TKT_LIFE +================================ + +.. +.. data:: KRB5_GET_INIT_CREDS_OPT_TKT_LIFE +.. + + + + +======================================= ====================== +``KRB5_GET_INIT_CREDS_OPT_TKT_LIFE`` ``0x0001`` +======================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INIT_CONTEXT_KDC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INIT_CONTEXT_KDC.rst.txt new file mode 100644 index 00000000..7d2ecf0a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INIT_CONTEXT_KDC.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-INIT-CONTEXT-KDC-data: + +KRB5_INIT_CONTEXT_KDC +===================== + +.. +.. data:: KRB5_INIT_CONTEXT_KDC +.. + +Use KDC configuration if available. + + + +============================ ====================== +``KRB5_INIT_CONTEXT_KDC`` ``0x2`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE.rst.txt new file mode 100644 index 00000000..299b48f8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-INIT-CONTEXT-SECURE-data: + +KRB5_INIT_CONTEXT_SECURE +======================== + +.. +.. data:: KRB5_INIT_CONTEXT_SECURE +.. + +Use secure context configuration. + + + +=============================== ====================== +``KRB5_INIT_CONTEXT_SECURE`` ``0x1`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE.rst.txt new file mode 100644 index 00000000..7981dc0f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-INIT-CREDS-STEP-FLAG-CONTINUE-data: + +KRB5_INIT_CREDS_STEP_FLAG_CONTINUE +================================== + +.. +.. data:: KRB5_INIT_CREDS_STEP_FLAG_CONTINUE +.. + +More responses needed. + + + +========================================= ====================== +``KRB5_INIT_CREDS_STEP_FLAG_CONTINUE`` ``0x1`` +========================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT16_MAX.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT16_MAX.rst.txt new file mode 100644 index 00000000..ac18b597 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT16_MAX.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-INT16-MAX-data: + +KRB5_INT16_MAX +============== + +.. +.. data:: KRB5_INT16_MAX +.. + + + + +===================== ====================== +``KRB5_INT16_MAX`` ``65535`` +===================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT16_MIN.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT16_MIN.rst.txt new file mode 100644 index 00000000..1bcfaa82 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT16_MIN.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-INT16-MIN-data: + +KRB5_INT16_MIN +============== + +.. +.. data:: KRB5_INT16_MIN +.. + + + + +===================== ====================== +``KRB5_INT16_MIN`` ``(-KRB5_INT16_MAX-1)`` +===================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT32_MAX.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT32_MAX.rst.txt new file mode 100644 index 00000000..a041c979 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT32_MAX.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-INT32-MAX-data: + +KRB5_INT32_MAX +============== + +.. +.. data:: KRB5_INT32_MAX +.. + + + + +===================== ====================== +``KRB5_INT32_MAX`` ``2147483647`` +===================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT32_MIN.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT32_MIN.rst.txt new file mode 100644 index 00000000..20192101 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_INT32_MIN.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-INT32-MIN-data: + +KRB5_INT32_MIN +============== + +.. +.. data:: KRB5_INT32_MIN +.. + + + + +===================== ====================== +``KRB5_INT32_MIN`` ``(-KRB5_INT32_MAX-1)`` +===================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE.rst.txt new file mode 100644 index 00000000..efd51241 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-AD-ITE-data: + +KRB5_KEYUSAGE_AD_ITE +==================== + +.. +.. data:: KRB5_KEYUSAGE_AD_ITE +.. + + + + +=========================== ====================== +``KRB5_KEYUSAGE_AD_ITE`` ``21`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM.rst.txt new file mode 100644 index 00000000..f2cdd071 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-AD-KDCISSUED-CKSUM-data: + +KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM +================================ + +.. +.. data:: KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM +.. + + + + +======================================= ====================== +``KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM`` ``19`` +======================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE.rst.txt new file mode 100644 index 00000000..0cab9a2d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-AD-MTE-data: + +KRB5_KEYUSAGE_AD_MTE +==================== + +.. +.. data:: KRB5_KEYUSAGE_AD_MTE +.. + + + + +=========================== ====================== +``KRB5_KEYUSAGE_AD_MTE`` ``20`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH.rst.txt new file mode 100644 index 00000000..fada88e0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-AD-SIGNEDPATH-data: + +KRB5_KEYUSAGE_AD_SIGNEDPATH +=========================== + +.. +.. data:: KRB5_KEYUSAGE_AD_SIGNEDPATH +.. + + + + +================================== ====================== +``KRB5_KEYUSAGE_AD_SIGNEDPATH`` ``-21`` +================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM.rst.txt new file mode 100644 index 00000000..2f909eab --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-APP-DATA-CKSUM-data: + +KRB5_KEYUSAGE_APP_DATA_CKSUM +============================ + +.. +.. data:: KRB5_KEYUSAGE_APP_DATA_CKSUM +.. + + + + +=================================== ====================== +``KRB5_KEYUSAGE_APP_DATA_CKSUM`` ``17`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT.rst.txt new file mode 100644 index 00000000..2b3e840b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-APP-DATA-ENCRYPT-data: + +KRB5_KEYUSAGE_APP_DATA_ENCRYPT +============================== + +.. +.. data:: KRB5_KEYUSAGE_APP_DATA_ENCRYPT +.. + + + + +===================================== ====================== +``KRB5_KEYUSAGE_APP_DATA_ENCRYPT`` ``16`` +===================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART.rst.txt new file mode 100644 index 00000000..bab584ff --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-AP-REP-ENCPART-data: + +KRB5_KEYUSAGE_AP_REP_ENCPART +============================ + +.. +.. data:: KRB5_KEYUSAGE_AP_REP_ENCPART +.. + + + + +=================================== ====================== +``KRB5_KEYUSAGE_AP_REP_ENCPART`` ``12`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH.rst.txt new file mode 100644 index 00000000..83fe216e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-AP-REQ-AUTH-data: + +KRB5_KEYUSAGE_AP_REQ_AUTH +========================= + +.. +.. data:: KRB5_KEYUSAGE_AP_REQ_AUTH +.. + + + + +================================ ====================== +``KRB5_KEYUSAGE_AP_REQ_AUTH`` ``11`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM.rst.txt new file mode 100644 index 00000000..54d18a9d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-AP-REQ-AUTH-CKSUM-data: + +KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM +=============================== + +.. +.. data:: KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM +.. + + + + +====================================== ====================== +``KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM`` ``10`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART.rst.txt new file mode 100644 index 00000000..d666d88c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-AS-REP-ENCPART-data: + +KRB5_KEYUSAGE_AS_REP_ENCPART +============================ + +.. +.. data:: KRB5_KEYUSAGE_AS_REP_ENCPART +.. + + + + +=================================== ====================== +``KRB5_KEYUSAGE_AS_REP_ENCPART`` ``3`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ.rst.txt new file mode 100644 index 00000000..0626b0ae --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-AS-REQ-data: + +KRB5_KEYUSAGE_AS_REQ +==================== + +.. +.. data:: KRB5_KEYUSAGE_AS_REQ +.. + + + + +=========================== ====================== +``KRB5_KEYUSAGE_AS_REQ`` ``56`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS.rst.txt new file mode 100644 index 00000000..6552938f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-AS-REQ-PA-ENC-TS-data: + +KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS +============================== + +.. +.. data:: KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS +.. + + + + +===================================== ====================== +``KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS`` ``1`` +===================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC.rst.txt new file mode 100644 index 00000000..0f7c7b12 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-CAMMAC-data: + +KRB5_KEYUSAGE_CAMMAC +==================== + +.. +.. data:: KRB5_KEYUSAGE_CAMMAC +.. + + + + +=========================== ====================== +``KRB5_KEYUSAGE_CAMMAC`` ``64`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT.rst.txt new file mode 100644 index 00000000..1f27210c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-ENC-CHALLENGE-CLIENT-data: + +KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT +================================== + +.. +.. data:: KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT +.. + + + + +========================================= ====================== +``KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT`` ``54`` +========================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC.rst.txt new file mode 100644 index 00000000..ec53ab1a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-ENC-CHALLENGE-KDC-data: + +KRB5_KEYUSAGE_ENC_CHALLENGE_KDC +=============================== + +.. +.. data:: KRB5_KEYUSAGE_ENC_CHALLENGE_KDC +.. + + + + +====================================== ====================== +``KRB5_KEYUSAGE_ENC_CHALLENGE_KDC`` ``55`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC.rst.txt new file mode 100644 index 00000000..0936f56a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-FAST-ENC-data: + +KRB5_KEYUSAGE_FAST_ENC +====================== + +.. +.. data:: KRB5_KEYUSAGE_FAST_ENC +.. + + + + +============================= ====================== +``KRB5_KEYUSAGE_FAST_ENC`` ``51`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED.rst.txt new file mode 100644 index 00000000..e66fd0f4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-FAST-FINISHED-data: + +KRB5_KEYUSAGE_FAST_FINISHED +=========================== + +.. +.. data:: KRB5_KEYUSAGE_FAST_FINISHED +.. + + + + +================================== ====================== +``KRB5_KEYUSAGE_FAST_FINISHED`` ``53`` +================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP.rst.txt new file mode 100644 index 00000000..076714bc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-FAST-REP-data: + +KRB5_KEYUSAGE_FAST_REP +====================== + +.. +.. data:: KRB5_KEYUSAGE_FAST_REP +.. + + + + +============================= ====================== +``KRB5_KEYUSAGE_FAST_REP`` ``52`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM.rst.txt new file mode 100644 index 00000000..257d006b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-FAST-REQ-CHKSUM-data: + +KRB5_KEYUSAGE_FAST_REQ_CHKSUM +============================= + +.. +.. data:: KRB5_KEYUSAGE_FAST_REQ_CHKSUM +.. + + + + +==================================== ====================== +``KRB5_KEYUSAGE_FAST_REQ_CHKSUM`` ``50`` +==================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC.rst.txt new file mode 100644 index 00000000..c1ae9317 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-GSS-TOK-MIC-data: + +KRB5_KEYUSAGE_GSS_TOK_MIC +========================= + +.. +.. data:: KRB5_KEYUSAGE_GSS_TOK_MIC +.. + + + + +================================ ====================== +``KRB5_KEYUSAGE_GSS_TOK_MIC`` ``22`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.rst.txt new file mode 100644 index 00000000..35a1ba74 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-GSS-TOK-WRAP-INTEG-data: + +KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG +================================ + +.. +.. data:: KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG +.. + + + + +======================================= ====================== +``KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG`` ``23`` +======================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.rst.txt new file mode 100644 index 00000000..c3df9b36 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-GSS-TOK-WRAP-PRIV-data: + +KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV +=============================== + +.. +.. data:: KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV +.. + + + + +====================================== ====================== +``KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV`` ``24`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED.rst.txt new file mode 100644 index 00000000..e17ba0b7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-IAKERB-FINISHED-data: + +KRB5_KEYUSAGE_IAKERB_FINISHED +============================= + +.. +.. data:: KRB5_KEYUSAGE_IAKERB_FINISHED +.. + + + + +==================================== ====================== +``KRB5_KEYUSAGE_IAKERB_FINISHED`` ``42`` +==================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET.rst.txt new file mode 100644 index 00000000..9203b56f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-KDC-REP-TICKET-data: + +KRB5_KEYUSAGE_KDC_REP_TICKET +============================ + +.. +.. data:: KRB5_KEYUSAGE_KDC_REP_TICKET +.. + + + + +=================================== ====================== +``KRB5_KEYUSAGE_KDC_REP_TICKET`` ``2`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART.rst.txt new file mode 100644 index 00000000..823c2ead --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-KRB-CRED-ENCPART-data: + +KRB5_KEYUSAGE_KRB_CRED_ENCPART +============================== + +.. +.. data:: KRB5_KEYUSAGE_KRB_CRED_ENCPART +.. + + + + +===================================== ====================== +``KRB5_KEYUSAGE_KRB_CRED_ENCPART`` ``14`` +===================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM.rst.txt new file mode 100644 index 00000000..8986ac08 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-KRB-ERROR-CKSUM-data: + +KRB5_KEYUSAGE_KRB_ERROR_CKSUM +============================= + +.. +.. data:: KRB5_KEYUSAGE_KRB_ERROR_CKSUM +.. + + + + +==================================== ====================== +``KRB5_KEYUSAGE_KRB_ERROR_CKSUM`` ``18`` +==================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART.rst.txt new file mode 100644 index 00000000..696ab74b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-KRB-PRIV-ENCPART-data: + +KRB5_KEYUSAGE_KRB_PRIV_ENCPART +============================== + +.. +.. data:: KRB5_KEYUSAGE_KRB_PRIV_ENCPART +.. + + + + +===================================== ====================== +``KRB5_KEYUSAGE_KRB_PRIV_ENCPART`` ``13`` +===================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM.rst.txt new file mode 100644 index 00000000..07493e66 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-KRB-SAFE-CKSUM-data: + +KRB5_KEYUSAGE_KRB_SAFE_CKSUM +============================ + +.. +.. data:: KRB5_KEYUSAGE_KRB_SAFE_CKSUM +.. + + + + +=================================== ====================== +``KRB5_KEYUSAGE_KRB_SAFE_CKSUM`` ``15`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS.rst.txt new file mode 100644 index 00000000..66e29627 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-PA-AS-FRESHNESS-data: + +KRB5_KEYUSAGE_PA_AS_FRESHNESS +============================= + +.. +.. data:: KRB5_KEYUSAGE_PA_AS_FRESHNESS +.. + +Used for freshness tokens. + + + +==================================== ====================== +``KRB5_KEYUSAGE_PA_AS_FRESHNESS`` ``514`` +==================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE.rst.txt new file mode 100644 index 00000000..709c8c39 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-PA-FX-COOKIE-data: + +KRB5_KEYUSAGE_PA_FX_COOKIE +========================== + +.. +.. data:: KRB5_KEYUSAGE_PA_FX_COOKIE +.. + +Used for encrypted FAST cookies. + + + +================================= ====================== +``KRB5_KEYUSAGE_PA_FX_COOKIE`` ``513`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST.rst.txt new file mode 100644 index 00000000..cfc6946d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-PA-OTP-REQUEST-data: + +KRB5_KEYUSAGE_PA_OTP_REQUEST +============================ + +.. +.. data:: KRB5_KEYUSAGE_PA_OTP_REQUEST +.. + +See RFC 6560 section 4.2. + + + +=================================== ====================== +``KRB5_KEYUSAGE_PA_OTP_REQUEST`` ``45`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX.rst.txt new file mode 100644 index 00000000..a0c61921 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-PA-PKINIT-KX-data: + +KRB5_KEYUSAGE_PA_PKINIT_KX +========================== + +.. +.. data:: KRB5_KEYUSAGE_PA_PKINIT_KX +.. + + + + +================================= ====================== +``KRB5_KEYUSAGE_PA_PKINIT_KX`` ``44`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY.rst.txt new file mode 100644 index 00000000..adab35dc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-PA-S4U-X509-USER-REPLY-data: + +KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY +==================================== + +.. +.. data:: KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY +.. + + + + +=========================================== ====================== +``KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY`` ``27`` +=========================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST.rst.txt new file mode 100644 index 00000000..03fff049 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-PA-S4U-X509-USER-REQUEST-data: + +KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST +====================================== + +.. +.. data:: KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST +.. + + + + +============================================= ====================== +``KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST`` ``26`` +============================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.rst.txt new file mode 100644 index 00000000..eff8ef82 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-PA-SAM-CHALLENGE-CKSUM-data: + +KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM +==================================== + +.. +.. data:: KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM +.. + + + + +=========================================== ====================== +``KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM`` ``25`` +=========================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.rst.txt new file mode 100644 index 00000000..1928646e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-PA-SAM-CHALLENGE-TRACKID-data: + +KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID +====================================== + +.. +.. data:: KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID +.. + + + + +============================================= ====================== +``KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID`` ``26`` +============================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE.rst.txt new file mode 100644 index 00000000..93b83048 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-PA-SAM-RESPONSE-data: + +KRB5_KEYUSAGE_PA_SAM_RESPONSE +============================= + +.. +.. data:: KRB5_KEYUSAGE_PA_SAM_RESPONSE +.. + + + + +==================================== ====================== +``KRB5_KEYUSAGE_PA_SAM_RESPONSE`` ``27`` +==================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_SPAKE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_SPAKE.rst.txt new file mode 100644 index 00000000..db6ccb67 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_SPAKE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-SPAKE-data: + +KRB5_KEYUSAGE_SPAKE +=================== + +.. +.. data:: KRB5_KEYUSAGE_SPAKE +.. + + + + +========================== ====================== +``KRB5_KEYUSAGE_SPAKE`` ``65`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.rst.txt new file mode 100644 index 00000000..56151c1b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-TGS-REP-ENCPART-SESSKEY-data: + +KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY +===================================== + +.. +.. data:: KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY +.. + + + + +============================================ ====================== +``KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY`` ``8`` +============================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.rst.txt new file mode 100644 index 00000000..ee0548c4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-TGS-REP-ENCPART-SUBKEY-data: + +KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY +==================================== + +.. +.. data:: KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY +.. + + + + +=========================================== ====================== +``KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY`` ``9`` +=========================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.rst.txt new file mode 100644 index 00000000..dc93ba77 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-TGS-REQ-AD-SESSKEY-data: + +KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY +================================ + +.. +.. data:: KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY +.. + + + + +======================================= ====================== +``KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY`` ``4`` +======================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY.rst.txt new file mode 100644 index 00000000..c48b8643 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-TGS-REQ-AD-SUBKEY-data: + +KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY +=============================== + +.. +.. data:: KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY +.. + + + + +====================================== ====================== +``KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY`` ``5`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH.rst.txt new file mode 100644 index 00000000..d50140f2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-TGS-REQ-AUTH-data: + +KRB5_KEYUSAGE_TGS_REQ_AUTH +========================== + +.. +.. data:: KRB5_KEYUSAGE_TGS_REQ_AUTH +.. + + + + +================================= ====================== +``KRB5_KEYUSAGE_TGS_REQ_AUTH`` ``7`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM.rst.txt new file mode 100644 index 00000000..a9245b4c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-KEYUSAGE-TGS-REQ-AUTH-CKSUM-data: + +KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM +================================ + +.. +.. data:: KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM +.. + + + + +======================================= ====================== +``KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM`` ``6`` +======================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED.rst.txt new file mode 100644 index 00000000..56d44af2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-KPASSWD-ACCESSDENIED-data: + +KRB5_KPASSWD_ACCESSDENIED +========================= + +.. +.. data:: KRB5_KPASSWD_ACCESSDENIED +.. + +Not authorized. + + + +================================ ====================== +``KRB5_KPASSWD_ACCESSDENIED`` ``5`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_AUTHERROR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_AUTHERROR.rst.txt new file mode 100644 index 00000000..356208ae --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_AUTHERROR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-KPASSWD-AUTHERROR-data: + +KRB5_KPASSWD_AUTHERROR +====================== + +.. +.. data:: KRB5_KPASSWD_AUTHERROR +.. + +Authentication error. + + + +============================= ====================== +``KRB5_KPASSWD_AUTHERROR`` ``3`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION.rst.txt new file mode 100644 index 00000000..7c6d0908 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-KPASSWD-BAD-VERSION-data: + +KRB5_KPASSWD_BAD_VERSION +======================== + +.. +.. data:: KRB5_KPASSWD_BAD_VERSION +.. + +Unknown RPC version. + + + +=============================== ====================== +``KRB5_KPASSWD_BAD_VERSION`` ``6`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_HARDERROR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_HARDERROR.rst.txt new file mode 100644 index 00000000..dbdb777e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_HARDERROR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-KPASSWD-HARDERROR-data: + +KRB5_KPASSWD_HARDERROR +====================== + +.. +.. data:: KRB5_KPASSWD_HARDERROR +.. + +Server error. + + + +============================= ====================== +``KRB5_KPASSWD_HARDERROR`` ``2`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED.rst.txt new file mode 100644 index 00000000..e4385673 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-KPASSWD-INITIAL-FLAG-NEEDED-data: + +KRB5_KPASSWD_INITIAL_FLAG_NEEDED +================================ + +.. +.. data:: KRB5_KPASSWD_INITIAL_FLAG_NEEDED +.. + +The presented credentials were not obtained using a password directly. + + + +======================================= ====================== +``KRB5_KPASSWD_INITIAL_FLAG_NEEDED`` ``7`` +======================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_MALFORMED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_MALFORMED.rst.txt new file mode 100644 index 00000000..8aa3a90c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_MALFORMED.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-KPASSWD-MALFORMED-data: + +KRB5_KPASSWD_MALFORMED +====================== + +.. +.. data:: KRB5_KPASSWD_MALFORMED +.. + +Malformed request. + + + +============================= ====================== +``KRB5_KPASSWD_MALFORMED`` ``1`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_SOFTERROR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_SOFTERROR.rst.txt new file mode 100644 index 00000000..2d1cb307 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_SOFTERROR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-KPASSWD-SOFTERROR-data: + +KRB5_KPASSWD_SOFTERROR +====================== + +.. +.. data:: KRB5_KPASSWD_SOFTERROR +.. + +Password change rejected. + + + +============================= ====================== +``KRB5_KPASSWD_SOFTERROR`` ``4`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_SUCCESS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_SUCCESS.rst.txt new file mode 100644 index 00000000..6cad3cf7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_KPASSWD_SUCCESS.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-KPASSWD-SUCCESS-data: + +KRB5_KPASSWD_SUCCESS +==================== + +.. +.. data:: KRB5_KPASSWD_SUCCESS +.. + +Success. + + + +=========================== ====================== +``KRB5_KPASSWD_SUCCESS`` ``0`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME.rst.txt new file mode 100644 index 00000000..3f33bd03 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ALL-ACCT-EXPTIME-data: + +KRB5_LRQ_ALL_ACCT_EXPTIME +========================= + +.. +.. data:: KRB5_LRQ_ALL_ACCT_EXPTIME +.. + + + + +================================ ====================== +``KRB5_LRQ_ALL_ACCT_EXPTIME`` ``7`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL.rst.txt new file mode 100644 index 00000000..5d90c8ef --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ALL-LAST-INITIAL-data: + +KRB5_LRQ_ALL_LAST_INITIAL +========================= + +.. +.. data:: KRB5_LRQ_ALL_LAST_INITIAL +.. + + + + +================================ ====================== +``KRB5_LRQ_ALL_LAST_INITIAL`` ``2`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL.rst.txt new file mode 100644 index 00000000..f7854969 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ALL-LAST-RENEWAL-data: + +KRB5_LRQ_ALL_LAST_RENEWAL +========================= + +.. +.. data:: KRB5_LRQ_ALL_LAST_RENEWAL +.. + + + + +================================ ====================== +``KRB5_LRQ_ALL_LAST_RENEWAL`` ``4`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ.rst.txt new file mode 100644 index 00000000..2b98c985 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ALL-LAST-REQ-data: + +KRB5_LRQ_ALL_LAST_REQ +===================== + +.. +.. data:: KRB5_LRQ_ALL_LAST_REQ +.. + + + + +============================ ====================== +``KRB5_LRQ_ALL_LAST_REQ`` ``5`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT.rst.txt new file mode 100644 index 00000000..4a7b5b1e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ALL-LAST-TGT-data: + +KRB5_LRQ_ALL_LAST_TGT +===================== + +.. +.. data:: KRB5_LRQ_ALL_LAST_TGT +.. + + + + +============================ ====================== +``KRB5_LRQ_ALL_LAST_TGT`` ``1`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED.rst.txt new file mode 100644 index 00000000..646b61a3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ALL-LAST-TGT-ISSUED-data: + +KRB5_LRQ_ALL_LAST_TGT_ISSUED +============================ + +.. +.. data:: KRB5_LRQ_ALL_LAST_TGT_ISSUED +.. + + + + +=================================== ====================== +``KRB5_LRQ_ALL_LAST_TGT_ISSUED`` ``3`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME.rst.txt new file mode 100644 index 00000000..f88a1c78 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ALL-PW-EXPTIME-data: + +KRB5_LRQ_ALL_PW_EXPTIME +======================= + +.. +.. data:: KRB5_LRQ_ALL_PW_EXPTIME +.. + + + + +============================== ====================== +``KRB5_LRQ_ALL_PW_EXPTIME`` ``6`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_NONE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_NONE.rst.txt new file mode 100644 index 00000000..1a816fed --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_NONE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-NONE-data: + +KRB5_LRQ_NONE +============= + +.. +.. data:: KRB5_LRQ_NONE +.. + + + + +==================== ====================== +``KRB5_LRQ_NONE`` ``0`` +==================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME.rst.txt new file mode 100644 index 00000000..842f1d78 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ONE-ACCT-EXPTIME-data: + +KRB5_LRQ_ONE_ACCT_EXPTIME +========================= + +.. +.. data:: KRB5_LRQ_ONE_ACCT_EXPTIME +.. + + + + +================================ ====================== +``KRB5_LRQ_ONE_ACCT_EXPTIME`` ``(-7)`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL.rst.txt new file mode 100644 index 00000000..c79efcca --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ONE-LAST-INITIAL-data: + +KRB5_LRQ_ONE_LAST_INITIAL +========================= + +.. +.. data:: KRB5_LRQ_ONE_LAST_INITIAL +.. + + + + +================================ ====================== +``KRB5_LRQ_ONE_LAST_INITIAL`` ``(-2)`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL.rst.txt new file mode 100644 index 00000000..dd9f70ec --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ONE-LAST-RENEWAL-data: + +KRB5_LRQ_ONE_LAST_RENEWAL +========================= + +.. +.. data:: KRB5_LRQ_ONE_LAST_RENEWAL +.. + + + + +================================ ====================== +``KRB5_LRQ_ONE_LAST_RENEWAL`` ``(-4)`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ.rst.txt new file mode 100644 index 00000000..da502338 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ONE-LAST-REQ-data: + +KRB5_LRQ_ONE_LAST_REQ +===================== + +.. +.. data:: KRB5_LRQ_ONE_LAST_REQ +.. + + + + +============================ ====================== +``KRB5_LRQ_ONE_LAST_REQ`` ``(-5)`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT.rst.txt new file mode 100644 index 00000000..f57c5473 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ONE-LAST-TGT-data: + +KRB5_LRQ_ONE_LAST_TGT +===================== + +.. +.. data:: KRB5_LRQ_ONE_LAST_TGT +.. + + + + +============================ ====================== +``KRB5_LRQ_ONE_LAST_TGT`` ``(-1)`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED.rst.txt new file mode 100644 index 00000000..44702a41 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ONE-LAST-TGT-ISSUED-data: + +KRB5_LRQ_ONE_LAST_TGT_ISSUED +============================ + +.. +.. data:: KRB5_LRQ_ONE_LAST_TGT_ISSUED +.. + + + + +=================================== ====================== +``KRB5_LRQ_ONE_LAST_TGT_ISSUED`` ``(-3)`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME.rst.txt new file mode 100644 index 00000000..4710a605 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-LRQ-ONE-PW-EXPTIME-data: + +KRB5_LRQ_ONE_PW_EXPTIME +======================= + +.. +.. data:: KRB5_LRQ_ONE_PW_EXPTIME +.. + + + + +============================== ====================== +``KRB5_LRQ_ONE_PW_EXPTIME`` ``(-6)`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL.rst.txt new file mode 100644 index 00000000..3511088c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-NT-ENTERPRISE-PRINCIPAL-data: + +KRB5_NT_ENTERPRISE_PRINCIPAL +============================ + +.. +.. data:: KRB5_NT_ENTERPRISE_PRINCIPAL +.. + +Windows 2000 UPN. + + + +=================================== ====================== +``KRB5_NT_ENTERPRISE_PRINCIPAL`` ``10`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID.rst.txt new file mode 100644 index 00000000..28f7eb39 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-NT-ENT-PRINCIPAL-AND-ID-data: + +KRB5_NT_ENT_PRINCIPAL_AND_ID +============================ + +.. +.. data:: KRB5_NT_ENT_PRINCIPAL_AND_ID +.. + +NT 4 style name and SID. + + + +=================================== ====================== +``KRB5_NT_ENT_PRINCIPAL_AND_ID`` ``-130`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL.rst.txt new file mode 100644 index 00000000..80801f6d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-NT-MS-PRINCIPAL-data: + +KRB5_NT_MS_PRINCIPAL +==================== + +.. +.. data:: KRB5_NT_MS_PRINCIPAL +.. + +Windows 2000 UPN and SID. + + + +=========================== ====================== +``KRB5_NT_MS_PRINCIPAL`` ``-128`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID.rst.txt new file mode 100644 index 00000000..7388c64a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-NT-MS-PRINCIPAL-AND-ID-data: + +KRB5_NT_MS_PRINCIPAL_AND_ID +=========================== + +.. +.. data:: KRB5_NT_MS_PRINCIPAL_AND_ID +.. + +NT 4 style name. + + + +================================== ====================== +``KRB5_NT_MS_PRINCIPAL_AND_ID`` ``-129`` +================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_PRINCIPAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_PRINCIPAL.rst.txt new file mode 100644 index 00000000..49309a52 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_PRINCIPAL.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-NT-PRINCIPAL-data: + +KRB5_NT_PRINCIPAL +================= + +.. +.. data:: KRB5_NT_PRINCIPAL +.. + +Just the name of the principal as in DCE, or for users. + + + +======================== ====================== +``KRB5_NT_PRINCIPAL`` ``1`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SMTP_NAME.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SMTP_NAME.rst.txt new file mode 100644 index 00000000..1d411335 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SMTP_NAME.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-NT-SMTP-NAME-data: + +KRB5_NT_SMTP_NAME +================= + +.. +.. data:: KRB5_NT_SMTP_NAME +.. + +Name in form of SMTP email name. + + + +======================== ====================== +``KRB5_NT_SMTP_NAME`` ``7`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SRV_HST.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SRV_HST.rst.txt new file mode 100644 index 00000000..7a96e400 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SRV_HST.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-NT-SRV-HST-data: + +KRB5_NT_SRV_HST +=============== + +.. +.. data:: KRB5_NT_SRV_HST +.. + +Service with host name as instance (telnet, rcommands) + + + +====================== ====================== +``KRB5_NT_SRV_HST`` ``3`` +====================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SRV_INST.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SRV_INST.rst.txt new file mode 100644 index 00000000..8beee817 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SRV_INST.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-NT-SRV-INST-data: + +KRB5_NT_SRV_INST +================ + +.. +.. data:: KRB5_NT_SRV_INST +.. + +Service and other unique instance (krbtgt) + + + +======================= ====================== +``KRB5_NT_SRV_INST`` ``2`` +======================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SRV_XHST.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SRV_XHST.rst.txt new file mode 100644 index 00000000..03e0f0d7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_SRV_XHST.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-NT-SRV-XHST-data: + +KRB5_NT_SRV_XHST +================ + +.. +.. data:: KRB5_NT_SRV_XHST +.. + +Service with host as remaining components. + + + +======================= ====================== +``KRB5_NT_SRV_XHST`` ``4`` +======================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_UID.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_UID.rst.txt new file mode 100644 index 00000000..76f278c5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_UID.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-NT-UID-data: + +KRB5_NT_UID +=========== + +.. +.. data:: KRB5_NT_UID +.. + +Unique ID. + + + +================== ====================== +``KRB5_NT_UID`` ``5`` +================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_UNKNOWN.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_UNKNOWN.rst.txt new file mode 100644 index 00000000..04636d46 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_UNKNOWN.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-NT-UNKNOWN-data: + +KRB5_NT_UNKNOWN +=============== + +.. +.. data:: KRB5_NT_UNKNOWN +.. + +Name type not known. + + + +====================== ====================== +``KRB5_NT_UNKNOWN`` ``0`` +====================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_WELLKNOWN.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_WELLKNOWN.rst.txt new file mode 100644 index 00000000..2d7c1b9b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_WELLKNOWN.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-NT-WELLKNOWN-data: + +KRB5_NT_WELLKNOWN +================= + +.. +.. data:: KRB5_NT_WELLKNOWN +.. + +Well-known (special) principal. + + + +======================== ====================== +``KRB5_NT_WELLKNOWN`` ``11`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_X500_PRINCIPAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_X500_PRINCIPAL.rst.txt new file mode 100644 index 00000000..fdd994c6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_NT_X500_PRINCIPAL.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-NT-X500-PRINCIPAL-data: + +KRB5_NT_X500_PRINCIPAL +====================== + +.. +.. data:: KRB5_NT_X500_PRINCIPAL +.. + +PKINIT. + + + +============================= ====================== +``KRB5_NT_X500_PRINCIPAL`` ``6`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO.rst.txt new file mode 100644 index 00000000..da248a8d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-ATTRIBUTES-INFO-data: + +KRB5_PAC_ATTRIBUTES_INFO +======================== + +.. +.. data:: KRB5_PAC_ATTRIBUTES_INFO +.. + +PAC attributes. + + + +=============================== ====================== +``KRB5_PAC_ATTRIBUTES_INFO`` ``17`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS.rst.txt new file mode 100644 index 00000000..4e940486 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-CLIENT-CLAIMS-data: + +KRB5_PAC_CLIENT_CLAIMS +====================== + +.. +.. data:: KRB5_PAC_CLIENT_CLAIMS +.. + +Client claims information. + + + +============================= ====================== +``KRB5_PAC_CLIENT_CLAIMS`` ``13`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_CLIENT_INFO.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_CLIENT_INFO.rst.txt new file mode 100644 index 00000000..846e21d0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_CLIENT_INFO.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-CLIENT-INFO-data: + +KRB5_PAC_CLIENT_INFO +==================== + +.. +.. data:: KRB5_PAC_CLIENT_INFO +.. + +Client name and ticket info. + + + +=========================== ====================== +``KRB5_PAC_CLIENT_INFO`` ``10`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO.rst.txt new file mode 100644 index 00000000..ae454f0e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-CREDENTIALS-INFO-data: + +KRB5_PAC_CREDENTIALS_INFO +========================= + +.. +.. data:: KRB5_PAC_CREDENTIALS_INFO +.. + +Credentials information. + + + +================================ ====================== +``KRB5_PAC_CREDENTIALS_INFO`` ``2`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_DELEGATION_INFO.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_DELEGATION_INFO.rst.txt new file mode 100644 index 00000000..6c93933b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_DELEGATION_INFO.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-DELEGATION-INFO-data: + +KRB5_PAC_DELEGATION_INFO +======================== + +.. +.. data:: KRB5_PAC_DELEGATION_INFO +.. + +Constrained delegation info. + + + +=============================== ====================== +``KRB5_PAC_DELEGATION_INFO`` ``11`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS.rst.txt new file mode 100644 index 00000000..36659dee --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-DEVICE-CLAIMS-data: + +KRB5_PAC_DEVICE_CLAIMS +====================== + +.. +.. data:: KRB5_PAC_DEVICE_CLAIMS +.. + +Device claims information. + + + +============================= ====================== +``KRB5_PAC_DEVICE_CLAIMS`` ``15`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_DEVICE_INFO.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_DEVICE_INFO.rst.txt new file mode 100644 index 00000000..d7e88127 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_DEVICE_INFO.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-DEVICE-INFO-data: + +KRB5_PAC_DEVICE_INFO +==================== + +.. +.. data:: KRB5_PAC_DEVICE_INFO +.. + +Device information. + + + +=========================== ====================== +``KRB5_PAC_DEVICE_INFO`` ``14`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM.rst.txt new file mode 100644 index 00000000..c9512888 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-FULL-CHECKSUM-data: + +KRB5_PAC_FULL_CHECKSUM +====================== + +.. +.. data:: KRB5_PAC_FULL_CHECKSUM +.. + +KDC full checksum. + + + +============================= ====================== +``KRB5_PAC_FULL_CHECKSUM`` ``19`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_LOGON_INFO.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_LOGON_INFO.rst.txt new file mode 100644 index 00000000..83424eb4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_LOGON_INFO.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-LOGON-INFO-data: + +KRB5_PAC_LOGON_INFO +=================== + +.. +.. data:: KRB5_PAC_LOGON_INFO +.. + +Logon information. + + + +========================== ====================== +``KRB5_PAC_LOGON_INFO`` ``1`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM.rst.txt new file mode 100644 index 00000000..75e1e667 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-PRIVSVR-CHECKSUM-data: + +KRB5_PAC_PRIVSVR_CHECKSUM +========================= + +.. +.. data:: KRB5_PAC_PRIVSVR_CHECKSUM +.. + +KDC checksum. + + + +================================ ====================== +``KRB5_PAC_PRIVSVR_CHECKSUM`` ``7`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_REQUESTOR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_REQUESTOR.rst.txt new file mode 100644 index 00000000..4bffb7f0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_REQUESTOR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-REQUESTOR-data: + +KRB5_PAC_REQUESTOR +================== + +.. +.. data:: KRB5_PAC_REQUESTOR +.. + +PAC requestor SID. + + + +========================= ====================== +``KRB5_PAC_REQUESTOR`` ``18`` +========================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM.rst.txt new file mode 100644 index 00000000..1f094041 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-SERVER-CHECKSUM-data: + +KRB5_PAC_SERVER_CHECKSUM +======================== + +.. +.. data:: KRB5_PAC_SERVER_CHECKSUM +.. + +Server checksum. + + + +=============================== ====================== +``KRB5_PAC_SERVER_CHECKSUM`` ``6`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM.rst.txt new file mode 100644 index 00000000..9ab24b14 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-TICKET-CHECKSUM-data: + +KRB5_PAC_TICKET_CHECKSUM +======================== + +.. +.. data:: KRB5_PAC_TICKET_CHECKSUM +.. + +Ticket checksum. + + + +=============================== ====================== +``KRB5_PAC_TICKET_CHECKSUM`` ``16`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO.rst.txt new file mode 100644 index 00000000..08a5cbd1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PAC-UPN-DNS-INFO-data: + +KRB5_PAC_UPN_DNS_INFO +===================== + +.. +.. data:: KRB5_PAC_UPN_DNS_INFO +.. + +User principal name and DNS info. + + + +============================ ====================== +``KRB5_PAC_UPN_DNS_INFO`` ``12`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AFS3_SALT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AFS3_SALT.rst.txt new file mode 100644 index 00000000..f2609c68 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AFS3_SALT.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-AFS3-SALT-data: + +KRB5_PADATA_AFS3_SALT +===================== + +.. +.. data:: KRB5_PADATA_AFS3_SALT +.. + +Cygnus. + +RFC 4120, 3961 + +============================ ====================== +``KRB5_PADATA_AFS3_SALT`` ``10`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AP_REQ.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AP_REQ.rst.txt new file mode 100644 index 00000000..32b4d2ff --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AP_REQ.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-PADATA-AP-REQ-data: + +KRB5_PADATA_AP_REQ +================== + +.. +.. data:: KRB5_PADATA_AP_REQ +.. + + + + +========================= ====================== +``KRB5_PADATA_AP_REQ`` ``1`` +========================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM.rst.txt new file mode 100644 index 00000000..d0487a01 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-AS-CHECKSUM-data: + +KRB5_PADATA_AS_CHECKSUM +======================= + +.. +.. data:: KRB5_PADATA_AS_CHECKSUM +.. + +AS checksum. + + + +============================== ====================== +``KRB5_PADATA_AS_CHECKSUM`` ``132`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS.rst.txt new file mode 100644 index 00000000..084b39db --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-AS-FRESHNESS-data: + +KRB5_PADATA_AS_FRESHNESS +======================== + +.. +.. data:: KRB5_PADATA_AS_FRESHNESS +.. + +RFC 8070. + + + +=============================== ====================== +``KRB5_PADATA_AS_FRESHNESS`` ``150`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE.rst.txt new file mode 100644 index 00000000..f0efc2e5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-ENCRYPTED-CHALLENGE-data: + +KRB5_PADATA_ENCRYPTED_CHALLENGE +=============================== + +.. +.. data:: KRB5_PADATA_ENCRYPTED_CHALLENGE +.. + +RFC 6113. + + + +====================================== ====================== +``KRB5_PADATA_ENCRYPTED_CHALLENGE`` ``138`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID.rst.txt new file mode 100644 index 00000000..9aaec10e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-ENC-SANDIA-SECURID-data: + +KRB5_PADATA_ENC_SANDIA_SECURID +============================== + +.. +.. data:: KRB5_PADATA_ENC_SANDIA_SECURID +.. + +SecurId passcode. + +RFC 4120 + +===================================== ====================== +``KRB5_PADATA_ENC_SANDIA_SECURID`` ``6`` +===================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP.rst.txt new file mode 100644 index 00000000..d40145f1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-ENC-TIMESTAMP-data: + +KRB5_PADATA_ENC_TIMESTAMP +========================= + +.. +.. data:: KRB5_PADATA_ENC_TIMESTAMP +.. + +RFC 4120. + + + +================================ ====================== +``KRB5_PADATA_ENC_TIMESTAMP`` ``2`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME.rst.txt new file mode 100644 index 00000000..755a84e9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-ENC-UNIX-TIME-data: + +KRB5_PADATA_ENC_UNIX_TIME +========================= + +.. +.. data:: KRB5_PADATA_ENC_UNIX_TIME +.. + +timestamp encrypted in key. + +RFC 4120 + +================================ ====================== +``KRB5_PADATA_ENC_UNIX_TIME`` ``5`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO.rst.txt new file mode 100644 index 00000000..4341a526 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-ETYPE-INFO-data: + +KRB5_PADATA_ETYPE_INFO +====================== + +.. +.. data:: KRB5_PADATA_ETYPE_INFO +.. + +Etype info for preauth. + +RFC 4120 + +============================= ====================== +``KRB5_PADATA_ETYPE_INFO`` ``11`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2.rst.txt new file mode 100644 index 00000000..3335112a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-ETYPE-INFO2-data: + +KRB5_PADATA_ETYPE_INFO2 +======================= + +.. +.. data:: KRB5_PADATA_ETYPE_INFO2 +.. + +RFC 4120. + + + +============================== ====================== +``KRB5_PADATA_ETYPE_INFO2`` ``19`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FOR_USER.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FOR_USER.rst.txt new file mode 100644 index 00000000..cb914247 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FOR_USER.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-FOR-USER-data: + +KRB5_PADATA_FOR_USER +==================== + +.. +.. data:: KRB5_PADATA_FOR_USER +.. + +username protocol transition request + + + +=========================== ====================== +``KRB5_PADATA_FOR_USER`` ``129`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FX_COOKIE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FX_COOKIE.rst.txt new file mode 100644 index 00000000..f8390741 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FX_COOKIE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-FX-COOKIE-data: + +KRB5_PADATA_FX_COOKIE +===================== + +.. +.. data:: KRB5_PADATA_FX_COOKIE +.. + +RFC 6113. + + + +============================ ====================== +``KRB5_PADATA_FX_COOKIE`` ``133`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FX_ERROR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FX_ERROR.rst.txt new file mode 100644 index 00000000..93cf047a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FX_ERROR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-FX-ERROR-data: + +KRB5_PADATA_FX_ERROR +==================== + +.. +.. data:: KRB5_PADATA_FX_ERROR +.. + +RFC 6113. + + + +=========================== ====================== +``KRB5_PADATA_FX_ERROR`` ``137`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FX_FAST.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FX_FAST.rst.txt new file mode 100644 index 00000000..67ce1d8d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_FX_FAST.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-FX-FAST-data: + +KRB5_PADATA_FX_FAST +=================== + +.. +.. data:: KRB5_PADATA_FX_FAST +.. + +RFC 6113. + + + +========================== ====================== +``KRB5_PADATA_FX_FAST`` ``136`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA.rst.txt new file mode 100644 index 00000000..75e7a866 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-GET-FROM-TYPED-DATA-data: + +KRB5_PADATA_GET_FROM_TYPED_DATA +=============================== + +.. +.. data:: KRB5_PADATA_GET_FROM_TYPED_DATA +.. + +Embedded in typed data. + +RFC 4120 + +====================================== ====================== +``KRB5_PADATA_GET_FROM_TYPED_DATA`` ``22`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_NONE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_NONE.rst.txt new file mode 100644 index 00000000..f1c0d44e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_NONE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-PADATA-NONE-data: + +KRB5_PADATA_NONE +================ + +.. +.. data:: KRB5_PADATA_NONE +.. + + + + +======================= ====================== +``KRB5_PADATA_NONE`` ``0`` +======================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OSF_DCE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OSF_DCE.rst.txt new file mode 100644 index 00000000..2f83465c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OSF_DCE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-OSF-DCE-data: + +KRB5_PADATA_OSF_DCE +=================== + +.. +.. data:: KRB5_PADATA_OSF_DCE +.. + +OSF DCE. + +RFC 4120 + +========================== ====================== +``KRB5_PADATA_OSF_DCE`` ``8`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE.rst.txt new file mode 100644 index 00000000..cfff48c6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-OTP-CHALLENGE-data: + +KRB5_PADATA_OTP_CHALLENGE +========================= + +.. +.. data:: KRB5_PADATA_OTP_CHALLENGE +.. + +RFC 6560 section 4.1. + + + +================================ ====================== +``KRB5_PADATA_OTP_CHALLENGE`` ``141`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE.rst.txt new file mode 100644 index 00000000..35a4b163 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-OTP-PIN-CHANGE-data: + +KRB5_PADATA_OTP_PIN_CHANGE +========================== + +.. +.. data:: KRB5_PADATA_OTP_PIN_CHANGE +.. + +RFC 6560 section 4.3. + + + +================================= ====================== +``KRB5_PADATA_OTP_PIN_CHANGE`` ``144`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OTP_REQUEST.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OTP_REQUEST.rst.txt new file mode 100644 index 00000000..90ba56e1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_OTP_REQUEST.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-OTP-REQUEST-data: + +KRB5_PADATA_OTP_REQUEST +======================= + +.. +.. data:: KRB5_PADATA_OTP_REQUEST +.. + +RFC 6560 section 4.2. + + + +============================== ====================== +``KRB5_PADATA_OTP_REQUEST`` ``142`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS.rst.txt new file mode 100644 index 00000000..46722ce6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-PAC-OPTIONS-data: + +KRB5_PADATA_PAC_OPTIONS +======================= + +.. +.. data:: KRB5_PADATA_PAC_OPTIONS +.. + +MS-KILE and MS-SFU. + + + +============================== ====================== +``KRB5_PADATA_PAC_OPTIONS`` ``167`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PAC_REQUEST.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PAC_REQUEST.rst.txt new file mode 100644 index 00000000..5147ce98 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PAC_REQUEST.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-PAC-REQUEST-data: + +KRB5_PADATA_PAC_REQUEST +======================= + +.. +.. data:: KRB5_PADATA_PAC_REQUEST +.. + +include Windows PAC + + + +============================== ====================== +``KRB5_PADATA_PAC_REQUEST`` ``128`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PKINIT_KX.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PKINIT_KX.rst.txt new file mode 100644 index 00000000..71930745 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PKINIT_KX.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-PKINIT-KX-data: + +KRB5_PADATA_PKINIT_KX +===================== + +.. +.. data:: KRB5_PADATA_PKINIT_KX +.. + +RFC 6112. + + + +============================ ====================== +``KRB5_PADATA_PKINIT_KX`` ``147`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REP.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REP.rst.txt new file mode 100644 index 00000000..5d7be824 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REP.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-PK-AS-REP-data: + +KRB5_PADATA_PK_AS_REP +===================== + +.. +.. data:: KRB5_PADATA_PK_AS_REP +.. + +PKINIT. + +RFC 4556 + +============================ ====================== +``KRB5_PADATA_PK_AS_REP`` ``17`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD.rst.txt new file mode 100644 index 00000000..1f782d2d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-PK-AS-REP-OLD-data: + +KRB5_PADATA_PK_AS_REP_OLD +========================= + +.. +.. data:: KRB5_PADATA_PK_AS_REP_OLD +.. + +PKINIT. + + + +================================ ====================== +``KRB5_PADATA_PK_AS_REP_OLD`` ``15`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ.rst.txt new file mode 100644 index 00000000..a291aa36 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-PK-AS-REQ-data: + +KRB5_PADATA_PK_AS_REQ +===================== + +.. +.. data:: KRB5_PADATA_PK_AS_REQ +.. + +PKINIT. + +RFC 4556 + +============================ ====================== +``KRB5_PADATA_PK_AS_REQ`` ``16`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD.rst.txt new file mode 100644 index 00000000..b3454c5f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-PK-AS-REQ-OLD-data: + +KRB5_PADATA_PK_AS_REQ_OLD +========================= + +.. +.. data:: KRB5_PADATA_PK_AS_REQ_OLD +.. + +PKINIT. + + + +================================ ====================== +``KRB5_PADATA_PK_AS_REQ_OLD`` ``14`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PW_SALT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PW_SALT.rst.txt new file mode 100644 index 00000000..9a006da7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_PW_SALT.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-PW-SALT-data: + +KRB5_PADATA_PW_SALT +=================== + +.. +.. data:: KRB5_PADATA_PW_SALT +.. + +RFC 4120. + + + +========================== ====================== +``KRB5_PADATA_PW_SALT`` ``3`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2.rst.txt new file mode 100644 index 00000000..b88f7916 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-REDHAT-IDP-OAUTH2-data: + +KRB5_PADATA_REDHAT_IDP_OAUTH2 +============================= + +.. +.. data:: KRB5_PADATA_REDHAT_IDP_OAUTH2 +.. + +Red Hat IdP mechanism. + + + +==================================== ====================== +``KRB5_PADATA_REDHAT_IDP_OAUTH2`` ``152`` +==================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY.rst.txt new file mode 100644 index 00000000..76cb77b8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-REDHAT-PASSKEY-data: + +KRB5_PADATA_REDHAT_PASSKEY +========================== + +.. +.. data:: KRB5_PADATA_REDHAT_PASSKEY +.. + +Red Hat Passkey mechanism. + + + +================================= ====================== +``KRB5_PADATA_REDHAT_PASSKEY`` ``153`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_REFERRAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_REFERRAL.rst.txt new file mode 100644 index 00000000..eb2c571e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_REFERRAL.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-REFERRAL-data: + +KRB5_PADATA_REFERRAL +==================== + +.. +.. data:: KRB5_PADATA_REFERRAL +.. + +draft referral system + + + +=========================== ====================== +``KRB5_PADATA_REFERRAL`` ``25`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_S4U_X509_USER.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_S4U_X509_USER.rst.txt new file mode 100644 index 00000000..566ed4dc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_S4U_X509_USER.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-S4U-X509-USER-data: + +KRB5_PADATA_S4U_X509_USER +========================= + +.. +.. data:: KRB5_PADATA_S4U_X509_USER +.. + +certificate protocol transition request + + + +================================ ====================== +``KRB5_PADATA_S4U_X509_USER`` ``130`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE.rst.txt new file mode 100644 index 00000000..fd1dc607 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-SAM-CHALLENGE-data: + +KRB5_PADATA_SAM_CHALLENGE +========================= + +.. +.. data:: KRB5_PADATA_SAM_CHALLENGE +.. + +SAM/OTP. + + + +================================ ====================== +``KRB5_PADATA_SAM_CHALLENGE`` ``12`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2.rst.txt new file mode 100644 index 00000000..9d77eb76 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-SAM-CHALLENGE-2-data: + +KRB5_PADATA_SAM_CHALLENGE_2 +=========================== + +.. +.. data:: KRB5_PADATA_SAM_CHALLENGE_2 +.. + +draft challenge system, updated + + + +================================== ====================== +``KRB5_PADATA_SAM_CHALLENGE_2`` ``30`` +================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT.rst.txt new file mode 100644 index 00000000..93fbeac2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-SAM-REDIRECT-data: + +KRB5_PADATA_SAM_REDIRECT +======================== + +.. +.. data:: KRB5_PADATA_SAM_REDIRECT +.. + +SAM/OTP. + +RFC 4120 + +=============================== ====================== +``KRB5_PADATA_SAM_REDIRECT`` ``21`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE.rst.txt new file mode 100644 index 00000000..14a18d48 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-SAM-RESPONSE-data: + +KRB5_PADATA_SAM_RESPONSE +======================== + +.. +.. data:: KRB5_PADATA_SAM_RESPONSE +.. + +SAM/OTP. + + + +=============================== ====================== +``KRB5_PADATA_SAM_RESPONSE`` ``13`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2.rst.txt new file mode 100644 index 00000000..265c60b1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-SAM-RESPONSE-2-data: + +KRB5_PADATA_SAM_RESPONSE_2 +========================== + +.. +.. data:: KRB5_PADATA_SAM_RESPONSE_2 +.. + +draft challenge system, updated + + + +================================= ====================== +``KRB5_PADATA_SAM_RESPONSE_2`` ``31`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SESAME.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SESAME.rst.txt new file mode 100644 index 00000000..f653d8ea --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SESAME.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-SESAME-data: + +KRB5_PADATA_SESAME +================== + +.. +.. data:: KRB5_PADATA_SESAME +.. + +Sesame project. + +RFC 4120 + +========================= ====================== +``KRB5_PADATA_SESAME`` ``7`` +========================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SPAKE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SPAKE.rst.txt new file mode 100644 index 00000000..16887a6c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SPAKE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-PADATA-SPAKE-data: + +KRB5_PADATA_SPAKE +================= + +.. +.. data:: KRB5_PADATA_SPAKE +.. + + + + +======================== ====================== +``KRB5_PADATA_SPAKE`` ``151`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO.rst.txt new file mode 100644 index 00000000..c3897c3d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-SVR-REFERRAL-INFO-data: + +KRB5_PADATA_SVR_REFERRAL_INFO +============================= + +.. +.. data:: KRB5_PADATA_SVR_REFERRAL_INFO +.. + +Windows 2000 referrals. + +RFC 6820 + +==================================== ====================== +``KRB5_PADATA_SVR_REFERRAL_INFO`` ``20`` +==================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_TGS_REQ.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_TGS_REQ.rst.txt new file mode 100644 index 00000000..75f5a26e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_TGS_REQ.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-PADATA-TGS-REQ-data: + +KRB5_PADATA_TGS_REQ +=================== + +.. +.. data:: KRB5_PADATA_TGS_REQ +.. + + + + +========================== ====================== +``KRB5_PADATA_TGS_REQ`` ``KRB5_PADATA_AP_REQ`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO.rst.txt new file mode 100644 index 00000000..159c3026 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PADATA-USE-SPECIFIED-KVNO-data: + +KRB5_PADATA_USE_SPECIFIED_KVNO +============================== + +.. +.. data:: KRB5_PADATA_USE_SPECIFIED_KVNO +.. + +RFC 4120. + + + +===================================== ====================== +``KRB5_PADATA_USE_SPECIFIED_KVNO`` ``20`` +===================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD.rst.txt new file mode 100644 index 00000000..63c43ba7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PRINCIPAL-COMPARE-CASEFOLD-data: + +KRB5_PRINCIPAL_COMPARE_CASEFOLD +=============================== + +.. +.. data:: KRB5_PRINCIPAL_COMPARE_CASEFOLD +.. + +case-insensitive + + + +====================================== ====================== +``KRB5_PRINCIPAL_COMPARE_CASEFOLD`` ``4`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE.rst.txt new file mode 100644 index 00000000..121f8264 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PRINCIPAL-COMPARE-ENTERPRISE-data: + +KRB5_PRINCIPAL_COMPARE_ENTERPRISE +================================= + +.. +.. data:: KRB5_PRINCIPAL_COMPARE_ENTERPRISE +.. + +UPNs as real principals. + + + +======================================== ====================== +``KRB5_PRINCIPAL_COMPARE_ENTERPRISE`` ``2`` +======================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM.rst.txt new file mode 100644 index 00000000..fdbe0dd9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PRINCIPAL-COMPARE-IGNORE-REALM-data: + +KRB5_PRINCIPAL_COMPARE_IGNORE_REALM +=================================== + +.. +.. data:: KRB5_PRINCIPAL_COMPARE_IGNORE_REALM +.. + +ignore realm component + + + +========================================== ====================== +``KRB5_PRINCIPAL_COMPARE_IGNORE_REALM`` ``1`` +========================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8.rst.txt new file mode 100644 index 00000000..9e0f76bc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PRINCIPAL-COMPARE-UTF8-data: + +KRB5_PRINCIPAL_COMPARE_UTF8 +=========================== + +.. +.. data:: KRB5_PRINCIPAL_COMPARE_UTF8 +.. + +treat principals as UTF-8 + + + +================================== ====================== +``KRB5_PRINCIPAL_COMPARE_UTF8`` ``8`` +================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE.rst.txt new file mode 100644 index 00000000..5b5df427 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PRINCIPAL-PARSE-ENTERPRISE-data: + +KRB5_PRINCIPAL_PARSE_ENTERPRISE +=============================== + +.. +.. data:: KRB5_PRINCIPAL_PARSE_ENTERPRISE +.. + +Create single-component enterprise principle. + + + +====================================== ====================== +``KRB5_PRINCIPAL_PARSE_ENTERPRISE`` ``0x4`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM.rst.txt new file mode 100644 index 00000000..786cfce6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PRINCIPAL-PARSE-IGNORE-REALM-data: + +KRB5_PRINCIPAL_PARSE_IGNORE_REALM +================================= + +.. +.. data:: KRB5_PRINCIPAL_PARSE_IGNORE_REALM +.. + +Ignore realm if present. + + + +======================================== ====================== +``KRB5_PRINCIPAL_PARSE_IGNORE_REALM`` ``0x8`` +======================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM.rst.txt new file mode 100644 index 00000000..c07956ce --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PRINCIPAL-PARSE-NO-DEF-REALM-data: + +KRB5_PRINCIPAL_PARSE_NO_DEF_REALM +================================= + +.. +.. data:: KRB5_PRINCIPAL_PARSE_NO_DEF_REALM +.. + +Don't add default realm. + + + +======================================== ====================== +``KRB5_PRINCIPAL_PARSE_NO_DEF_REALM`` ``0x10`` +======================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM.rst.txt new file mode 100644 index 00000000..6d241738 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PRINCIPAL-PARSE-NO-REALM-data: + +KRB5_PRINCIPAL_PARSE_NO_REALM +============================= + +.. +.. data:: KRB5_PRINCIPAL_PARSE_NO_REALM +.. + +Error if realm is present. + + + +==================================== ====================== +``KRB5_PRINCIPAL_PARSE_NO_REALM`` ``0x1`` +==================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM.rst.txt new file mode 100644 index 00000000..ec3c4248 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PRINCIPAL-PARSE-REQUIRE-REALM-data: + +KRB5_PRINCIPAL_PARSE_REQUIRE_REALM +================================== + +.. +.. data:: KRB5_PRINCIPAL_PARSE_REQUIRE_REALM +.. + +Error if realm is not present. + + + +========================================= ====================== +``KRB5_PRINCIPAL_PARSE_REQUIRE_REALM`` ``0x2`` +========================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY.rst.txt new file mode 100644 index 00000000..2a648a23 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PRINCIPAL-UNPARSE-DISPLAY-data: + +KRB5_PRINCIPAL_UNPARSE_DISPLAY +============================== + +.. +.. data:: KRB5_PRINCIPAL_UNPARSE_DISPLAY +.. + +Don't escape special characters. + + + +===================================== ====================== +``KRB5_PRINCIPAL_UNPARSE_DISPLAY`` ``0x4`` +===================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM.rst.txt new file mode 100644 index 00000000..277b53ef --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PRINCIPAL-UNPARSE-NO-REALM-data: + +KRB5_PRINCIPAL_UNPARSE_NO_REALM +=============================== + +.. +.. data:: KRB5_PRINCIPAL_UNPARSE_NO_REALM +.. + +Omit realm always. + + + +====================================== ====================== +``KRB5_PRINCIPAL_UNPARSE_NO_REALM`` ``0x2`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT.rst.txt new file mode 100644 index 00000000..08aeb625 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PRINCIPAL-UNPARSE-SHORT-data: + +KRB5_PRINCIPAL_UNPARSE_SHORT +============================ + +.. +.. data:: KRB5_PRINCIPAL_UNPARSE_SHORT +.. + +Omit realm if it is the local realm. + + + +=================================== ====================== +``KRB5_PRINCIPAL_UNPARSE_SHORT`` ``0x1`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRIV.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRIV.rst.txt new file mode 100644 index 00000000..a55392c0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PRIV.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PRIV-data: + +KRB5_PRIV +========= + +.. +.. data:: KRB5_PRIV +.. + +Private application message. + + + +================ ====================== +``KRB5_PRIV`` ``((krb5_msgtype)21)`` +================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD.rst.txt new file mode 100644 index 00000000..6af358ff --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PROMPT-TYPE-NEW-PASSWORD-data: + +KRB5_PROMPT_TYPE_NEW_PASSWORD +============================= + +.. +.. data:: KRB5_PROMPT_TYPE_NEW_PASSWORD +.. + +Prompt for new password (during password change) + + + +==================================== ====================== +``KRB5_PROMPT_TYPE_NEW_PASSWORD`` ``0x2`` +==================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN.rst.txt new file mode 100644 index 00000000..bd9e9233 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PROMPT-TYPE-NEW-PASSWORD-AGAIN-data: + +KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN +=================================== + +.. +.. data:: KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN +.. + +Prompt for new password again. + + + +========================================== ====================== +``KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN`` ``0x3`` +========================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD.rst.txt new file mode 100644 index 00000000..135a5652 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PROMPT-TYPE-PASSWORD-data: + +KRB5_PROMPT_TYPE_PASSWORD +========================= + +.. +.. data:: KRB5_PROMPT_TYPE_PASSWORD +.. + +Prompt for password. + + + +================================ ====================== +``KRB5_PROMPT_TYPE_PASSWORD`` ``0x1`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH.rst.txt new file mode 100644 index 00000000..11b64feb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PROMPT-TYPE-PREAUTH-data: + +KRB5_PROMPT_TYPE_PREAUTH +======================== + +.. +.. data:: KRB5_PROMPT_TYPE_PREAUTH +.. + +Prompt for preauthentication data (such as an OTP value) + + + +=============================== ====================== +``KRB5_PROMPT_TYPE_PREAUTH`` ``0x4`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PVNO.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PVNO.rst.txt new file mode 100644 index 00000000..7bdda5d9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_PVNO.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-PVNO-data: + +KRB5_PVNO +========= + +.. +.. data:: KRB5_PVNO +.. + +Protocol version number. + + + +================ ====================== +``KRB5_PVNO`` ``5`` +================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_REALM_BRANCH_CHAR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_REALM_BRANCH_CHAR.rst.txt new file mode 100644 index 00000000..96c3e58f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_REALM_BRANCH_CHAR.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-REALM-BRANCH-CHAR-data: + +KRB5_REALM_BRANCH_CHAR +====================== + +.. +.. data:: KRB5_REALM_BRANCH_CHAR +.. + + + + +============================= ====================== +``KRB5_REALM_BRANCH_CHAR`` ``'.'`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS.rst.txt new file mode 100644 index 00000000..c7666441 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-RECVAUTH-BADAUTHVERS-data: + +KRB5_RECVAUTH_BADAUTHVERS +========================= + +.. +.. data:: KRB5_RECVAUTH_BADAUTHVERS +.. + + + + +================================ ====================== +``KRB5_RECVAUTH_BADAUTHVERS`` ``0x0002`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION.rst.txt new file mode 100644 index 00000000..63fd124d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-RECVAUTH-SKIP-VERSION-data: + +KRB5_RECVAUTH_SKIP_VERSION +========================== + +.. +.. data:: KRB5_RECVAUTH_SKIP_VERSION +.. + + + + +================================= ====================== +``KRB5_RECVAUTH_SKIP_VERSION`` ``0x0001`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_REFERRAL_REALM.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_REFERRAL_REALM.rst.txt new file mode 100644 index 00000000..f5a65b1e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_REFERRAL_REALM.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-REFERRAL-REALM-data: + +KRB5_REFERRAL_REALM +=================== + +.. +.. data:: KRB5_REFERRAL_REALM +.. + +Constant for realm referrals. + + + +========================== ====================== +``KRB5_REFERRAL_REALM`` ``""`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN.rst.txt new file mode 100644 index 00000000..413b6349 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-RESPONDER-OTP-FLAGS-COLLECT-PIN-data: + +KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN +==================================== + +.. +.. data:: KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN +.. + +This flag indicates that the PIN value MUST be collected. + + + +=========================================== ====================== +``KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN`` ``0x0002`` +=========================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN.rst.txt new file mode 100644 index 00000000..1a78999f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-RESPONDER-OTP-FLAGS-COLLECT-TOKEN-data: + +KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN +====================================== + +.. +.. data:: KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN +.. + +This flag indicates that the token value MUST be collected. + + + +============================================= ====================== +``KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN`` ``0x0001`` +============================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP.rst.txt new file mode 100644 index 00000000..26e230a0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-RESPONDER-OTP-FLAGS-NEXTOTP-data: + +KRB5_RESPONDER_OTP_FLAGS_NEXTOTP +================================ + +.. +.. data:: KRB5_RESPONDER_OTP_FLAGS_NEXTOTP +.. + +This flag indicates that the token is now in re-synchronization mode with the server. + +The user is expected to reply with the next code displayed on the token. + +======================================= ====================== +``KRB5_RESPONDER_OTP_FLAGS_NEXTOTP`` ``0x0004`` +======================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN.rst.txt new file mode 100644 index 00000000..ddd3d488 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-RESPONDER-OTP-FLAGS-SEPARATE-PIN-data: + +KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN +===================================== + +.. +.. data:: KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN +.. + +This flag indicates that the PIN MUST be returned as a separate item. + +This flag only takes effect if KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN is set. If this flag is not set, the responder may either concatenate PIN + token value and store it as "value" in the answer or it may return them separately. If they are returned separately, they will be concatenated internally. + +============================================ ====================== +``KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN`` ``0x0008`` +============================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC.rst.txt new file mode 100644 index 00000000..96beff5f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-RESPONDER-OTP-FORMAT-ALPHANUMERIC-data: + +KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC +====================================== + +.. +.. data:: KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC +.. + + + + +============================================= ====================== +``KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC`` ``2`` +============================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL.rst.txt new file mode 100644 index 00000000..11544558 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-RESPONDER-OTP-FORMAT-DECIMAL-data: + +KRB5_RESPONDER_OTP_FORMAT_DECIMAL +================================= + +.. +.. data:: KRB5_RESPONDER_OTP_FORMAT_DECIMAL +.. + +These format constants identify the format of the token value. + + + +======================================== ====================== +``KRB5_RESPONDER_OTP_FORMAT_DECIMAL`` ``0`` +======================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL.rst.txt new file mode 100644 index 00000000..77ecfb11 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-RESPONDER-OTP-FORMAT-HEXADECIMAL-data: + +KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL +===================================== + +.. +.. data:: KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL +.. + + + + +============================================ ====================== +``KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL`` ``1`` +============================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW.rst.txt new file mode 100644 index 00000000..99aa5478 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-RESPONDER-PKINIT-FLAGS-TOKEN-USER-PIN-COUNT-LOW-data: + +KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW +==================================================== + +.. +.. data:: KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW +.. + +This flag indicates that an incorrect PIN was supplied at least once since the last time the correct PIN was supplied. + + + +=========================================================== ====================== +``KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW`` ``(1 << 0)`` +=========================================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY.rst.txt new file mode 100644 index 00000000..ecf2ca0d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-RESPONDER-PKINIT-FLAGS-TOKEN-USER-PIN-FINAL-TRY-data: + +KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY +==================================================== + +.. +.. data:: KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY +.. + +This flag indicates that supplying an incorrect PIN will cause the token to lock itself. + + + +=========================================================== ====================== +``KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY`` ``(1 << 1)`` +=========================================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.rst.txt new file mode 100644 index 00000000..3974c52f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-RESPONDER-PKINIT-FLAGS-TOKEN-USER-PIN-LOCKED-data: + +KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED +================================================= + +.. +.. data:: KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED +.. + +This flag indicates that the user PIN is locked, and you can't log in to the token with it. + + + +======================================================== ====================== +``KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED`` ``(1 << 2)`` +======================================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP.rst.txt new file mode 100644 index 00000000..47ad1732 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP.rst.txt @@ -0,0 +1,47 @@ +.. highlight:: c + +.. _KRB5-RESPONDER-QUESTION-OTP-data: + +KRB5_RESPONDER_QUESTION_OTP +=========================== + +.. +.. data:: KRB5_RESPONDER_QUESTION_OTP +.. + +OTP responder question. + +The OTP responder question is asked when the KDC indicates that an OTP value is required in order to complete the authentication. The JSON format of the challenge is: +:: + + { + "service": , + "tokenInfo": [ + { + "flags": , + "vendor": , + "challenge": , + "length": , + "format": , + "tokenID": , + "algID": , + }, + ... + ] + } + +The answer to the question MUST be JSON formatted: +:: + + { + "tokeninfo": , + "value": , + "pin": , + } + +For more detail, please see RFC 6560. + + +================================== ====================== +``KRB5_RESPONDER_QUESTION_OTP`` ``"otp"`` +================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD.rst.txt new file mode 100644 index 00000000..057eac4a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD.rst.txt @@ -0,0 +1,19 @@ +.. highlight:: c + +.. _KRB5-RESPONDER-QUESTION-PASSWORD-data: + +KRB5_RESPONDER_QUESTION_PASSWORD +================================ + +.. +.. data:: KRB5_RESPONDER_QUESTION_PASSWORD +.. + +Long-term password responder question. + +This question is asked when the long-term password is needed. It has no challenge and the response is simply the password string. + + +======================================= ====================== +``KRB5_RESPONDER_QUESTION_PASSWORD`` ``"password"`` +======================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT.rst.txt new file mode 100644 index 00000000..0fb11c73 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT.rst.txt @@ -0,0 +1,34 @@ +.. highlight:: c + +.. _KRB5-RESPONDER-QUESTION-PKINIT-data: + +KRB5_RESPONDER_QUESTION_PKINIT +============================== + +.. +.. data:: KRB5_RESPONDER_QUESTION_PKINIT +.. + +PKINIT responder question. + +The PKINIT responder question is asked when the client needs a password that's being used to protect key information, and is formatted as a JSON object. A specific identity's flags value, if not zero, is the bitwise-OR of one or more of the KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_* flags defined below, and possibly other flags to be added later. Any resemblance to similarly-named CKF_* values in the PKCS#11 API should not be depended on. +:: + + { + identity : flags , + ... + } + +The answer to the question MUST be JSON formatted: +:: + + { + identity : password , + ... + } + + + +===================================== ====================== +``KRB5_RESPONDER_QUESTION_PKINIT`` ``"pkinit"`` +===================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAFE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAFE.rst.txt new file mode 100644 index 00000000..4210e4f4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAFE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-SAFE-data: + +KRB5_SAFE +========= + +.. +.. data:: KRB5_SAFE +.. + +Safe application message. + + + +================ ====================== +``KRB5_SAFE`` ``((krb5_msgtype)20)`` +================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD.rst.txt new file mode 100644 index 00000000..e8c8c570 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-SAM-MUST-PK-ENCRYPT-SAD-data: + +KRB5_SAM_MUST_PK_ENCRYPT_SAD +============================ + +.. +.. data:: KRB5_SAM_MUST_PK_ENCRYPT_SAD +.. + +currently must be zero + + + +=================================== ====================== +``KRB5_SAM_MUST_PK_ENCRYPT_SAD`` ``0x20000000`` +=================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD.rst.txt new file mode 100644 index 00000000..fcd56bea --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-SAM-SEND-ENCRYPTED-SAD-data: + +KRB5_SAM_SEND_ENCRYPTED_SAD +=========================== + +.. +.. data:: KRB5_SAM_SEND_ENCRYPTED_SAD +.. + + + + +================================== ====================== +``KRB5_SAM_SEND_ENCRYPTED_SAD`` ``0x40000000`` +================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY.rst.txt new file mode 100644 index 00000000..beae65cd --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-SAM-USE-SAD-AS-KEY-data: + +KRB5_SAM_USE_SAD_AS_KEY +======================= + +.. +.. data:: KRB5_SAM_USE_SAD_AS_KEY +.. + + + + +============================== ====================== +``KRB5_SAM_USE_SAD_AS_KEY`` ``0x80000000`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT.rst.txt new file mode 100644 index 00000000..fb5e39b9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TC-MATCH-2ND-TKT-data: + +KRB5_TC_MATCH_2ND_TKT +===================== + +.. +.. data:: KRB5_TC_MATCH_2ND_TKT +.. + +The second ticket must match. + + + +============================ ====================== +``KRB5_TC_MATCH_2ND_TKT`` ``0x00000080`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA.rst.txt new file mode 100644 index 00000000..d78b8487 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TC-MATCH-AUTHDATA-data: + +KRB5_TC_MATCH_AUTHDATA +====================== + +.. +.. data:: KRB5_TC_MATCH_AUTHDATA +.. + +The authorization data must match. + + + +============================= ====================== +``KRB5_TC_MATCH_AUTHDATA`` ``0x00000020`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_FLAGS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_FLAGS.rst.txt new file mode 100644 index 00000000..0fac98fc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_FLAGS.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TC-MATCH-FLAGS-data: + +KRB5_TC_MATCH_FLAGS +=================== + +.. +.. data:: KRB5_TC_MATCH_FLAGS +.. + +All the flags set in the match credentials must be set. + + + +========================== ====================== +``KRB5_TC_MATCH_FLAGS`` ``0x00000004`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT.rst.txt new file mode 100644 index 00000000..9e3480ab --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TC-MATCH-FLAGS-EXACT-data: + +KRB5_TC_MATCH_FLAGS_EXACT +========================= + +.. +.. data:: KRB5_TC_MATCH_FLAGS_EXACT +.. + +All the flags must match exactly. + + + +================================ ====================== +``KRB5_TC_MATCH_FLAGS_EXACT`` ``0x00000010`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY.rst.txt new file mode 100644 index 00000000..98799934 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TC-MATCH-IS-SKEY-data: + +KRB5_TC_MATCH_IS_SKEY +===================== + +.. +.. data:: KRB5_TC_MATCH_IS_SKEY +.. + +The is_skey field must match exactly. + + + +============================ ====================== +``KRB5_TC_MATCH_IS_SKEY`` ``0x00000002`` +============================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_KTYPE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_KTYPE.rst.txt new file mode 100644 index 00000000..e5bf18c4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_KTYPE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TC-MATCH-KTYPE-data: + +KRB5_TC_MATCH_KTYPE +=================== + +.. +.. data:: KRB5_TC_MATCH_KTYPE +.. + +The encryption key type must match. + + + +========================== ====================== +``KRB5_TC_MATCH_KTYPE`` ``0x00000100`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY.rst.txt new file mode 100644 index 00000000..ca79db32 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TC-MATCH-SRV-NAMEONLY-data: + +KRB5_TC_MATCH_SRV_NAMEONLY +========================== + +.. +.. data:: KRB5_TC_MATCH_SRV_NAMEONLY +.. + +Only the name portion of the principal name must match. + + + +================================= ====================== +``KRB5_TC_MATCH_SRV_NAMEONLY`` ``0x00000040`` +================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_TIMES.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_TIMES.rst.txt new file mode 100644 index 00000000..628ee32e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_TIMES.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TC-MATCH-TIMES-data: + +KRB5_TC_MATCH_TIMES +=================== + +.. +.. data:: KRB5_TC_MATCH_TIMES +.. + +The requested lifetime must be at least as great as the time specified. + + + +========================== ====================== +``KRB5_TC_MATCH_TIMES`` ``0x00000001`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT.rst.txt new file mode 100644 index 00000000..9d0ffce6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TC-MATCH-TIMES-EXACT-data: + +KRB5_TC_MATCH_TIMES_EXACT +========================= + +.. +.. data:: KRB5_TC_MATCH_TIMES_EXACT +.. + +All the time fields must match exactly. + + + +================================ ====================== +``KRB5_TC_MATCH_TIMES_EXACT`` ``0x00000008`` +================================ ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_NOTICKET.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_NOTICKET.rst.txt new file mode 100644 index 00000000..76e9a01f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_NOTICKET.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-TC-NOTICKET-data: + +KRB5_TC_NOTICKET +================ + +.. +.. data:: KRB5_TC_NOTICKET +.. + + + + +======================= ====================== +``KRB5_TC_NOTICKET`` ``0x00000002`` +======================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_OPENCLOSE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_OPENCLOSE.rst.txt new file mode 100644 index 00000000..83d94560 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_OPENCLOSE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TC-OPENCLOSE-data: + +KRB5_TC_OPENCLOSE +================= + +.. +.. data:: KRB5_TC_OPENCLOSE +.. + +Open and close the file for each cache operation. + + + +======================== ====================== +``KRB5_TC_OPENCLOSE`` ``0x00000001`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES.rst.txt new file mode 100644 index 00000000..ecd20381 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TC-SUPPORTED-KTYPES-data: + +KRB5_TC_SUPPORTED_KTYPES +======================== + +.. +.. data:: KRB5_TC_SUPPORTED_KTYPES +.. + +The supported key types must match. + + + +=============================== ====================== +``KRB5_TC_SUPPORTED_KTYPES`` ``0x00000200`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_NAME.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_NAME.rst.txt new file mode 100644 index 00000000..32b22b00 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_NAME.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-TGS-NAME-data: + +KRB5_TGS_NAME +============= + +.. +.. data:: KRB5_TGS_NAME +.. + + + + +==================== ====================== +``KRB5_TGS_NAME`` ``"krbtgt"`` +==================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_NAME_SIZE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_NAME_SIZE.rst.txt new file mode 100644 index 00000000..71adc91d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_NAME_SIZE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-TGS-NAME-SIZE-data: + +KRB5_TGS_NAME_SIZE +================== + +.. +.. data:: KRB5_TGS_NAME_SIZE +.. + + + + +========================= ====================== +``KRB5_TGS_NAME_SIZE`` ``6`` +========================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_REP.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_REP.rst.txt new file mode 100644 index 00000000..f3dbfe87 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_REP.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TGS-REP-data: + +KRB5_TGS_REP +============ + +.. +.. data:: KRB5_TGS_REP +.. + +Response to TGS request. + + + +=================== ====================== +``KRB5_TGS_REP`` ``((krb5_msgtype)13)`` +=================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_REQ.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_REQ.rst.txt new file mode 100644 index 00000000..1b574227 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TGS_REQ.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TGS-REQ-data: + +KRB5_TGS_REQ +============ + +.. +.. data:: KRB5_TGS_REQ +.. + +Ticket granting server request. + + + +=================== ====================== +``KRB5_TGS_REQ`` ``((krb5_msgtype)12)`` +=================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE.rst.txt new file mode 100644 index 00000000..fa01e45c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-TKT-CREDS-STEP-FLAG-CONTINUE-data: + +KRB5_TKT_CREDS_STEP_FLAG_CONTINUE +================================= + +.. +.. data:: KRB5_TKT_CREDS_STEP_FLAG_CONTINUE +.. + +More responses needed. + + + +======================================== ====================== +``KRB5_TKT_CREDS_STEP_FLAG_CONTINUE`` ``0x1`` +======================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL.rst.txt new file mode 100644 index 00000000..1925137f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _KRB5-VERIFY-INIT-CREDS-OPT-AP-REQ-NOFAIL-data: + +KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL +======================================== + +.. +.. data:: KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL +.. + + + + +=============================================== ====================== +``KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL`` ``0x0001`` +=============================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR.rst.txt new file mode 100644 index 00000000..6c24427e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _KRB5-WELLKNOWN-NAMESTR-data: + +KRB5_WELLKNOWN_NAMESTR +====================== + +.. +.. data:: KRB5_WELLKNOWN_NAMESTR +.. + +First component of NT_WELLKNOWN principals. + + + +============================= ====================== +``KRB5_WELLKNOWN_NAMESTR`` ``"WELLKNOWN"`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK.rst.txt new file mode 100644 index 00000000..47513d56 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _LR-TYPE-INTERPRETATION-MASK-data: + +LR_TYPE_INTERPRETATION_MASK +=========================== + +.. +.. data:: LR_TYPE_INTERPRETATION_MASK +.. + + + + +================================== ====================== +``LR_TYPE_INTERPRETATION_MASK`` ``0x7fff`` +================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY.rst.txt new file mode 100644 index 00000000..4db68f9a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _LR-TYPE-THIS-SERVER-ONLY-data: + +LR_TYPE_THIS_SERVER_ONLY +======================== + +.. +.. data:: LR_TYPE_THIS_SERVER_ONLY +.. + + + + +=============================== ====================== +``LR_TYPE_THIS_SERVER_ONLY`` ``0x8000`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/MAX_KEYTAB_NAME_LEN.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/MAX_KEYTAB_NAME_LEN.rst.txt new file mode 100644 index 00000000..ae0e1e2a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/MAX_KEYTAB_NAME_LEN.rst.txt @@ -0,0 +1,18 @@ +.. highlight:: c + +.. _MAX-KEYTAB-NAME-LEN-data: + +MAX_KEYTAB_NAME_LEN +=================== + +.. +.. data:: MAX_KEYTAB_NAME_LEN +.. + +Long enough for MAXPATHLEN + some extra. + + + +========================== ====================== +``MAX_KEYTAB_NAME_LEN`` ``1100`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/MSEC_DIRBIT.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/MSEC_DIRBIT.rst.txt new file mode 100644 index 00000000..e2686b0a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/MSEC_DIRBIT.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _MSEC-DIRBIT-data: + +MSEC_DIRBIT +=========== + +.. +.. data:: MSEC_DIRBIT +.. + + + + +================== ====================== +``MSEC_DIRBIT`` ``0x8000`` +================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/MSEC_VAL_MASK.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/MSEC_VAL_MASK.rst.txt new file mode 100644 index 00000000..23905a4e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/MSEC_VAL_MASK.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _MSEC-VAL-MASK-data: + +MSEC_VAL_MASK +============= + +.. +.. data:: MSEC_VAL_MASK +.. + + + + +==================== ====================== +``MSEC_VAL_MASK`` ``0x7fff`` +==================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/SALT_TYPE_AFS_LENGTH.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/SALT_TYPE_AFS_LENGTH.rst.txt new file mode 100644 index 00000000..235b81f2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/SALT_TYPE_AFS_LENGTH.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _SALT-TYPE-AFS-LENGTH-data: + +SALT_TYPE_AFS_LENGTH +==================== + +.. +.. data:: SALT_TYPE_AFS_LENGTH +.. + + + + +=========================== ====================== +``SALT_TYPE_AFS_LENGTH`` ``UINT_MAX`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/SALT_TYPE_NO_LENGTH.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/SALT_TYPE_NO_LENGTH.rst.txt new file mode 100644 index 00000000..7cf62df5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/SALT_TYPE_NO_LENGTH.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _SALT-TYPE-NO-LENGTH-data: + +SALT_TYPE_NO_LENGTH +=================== + +.. +.. data:: SALT_TYPE_NO_LENGTH +.. + + + + +========================== ====================== +``SALT_TYPE_NO_LENGTH`` ``UINT_MAX`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/THREEPARAMOPEN.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/THREEPARAMOPEN.rst.txt new file mode 100644 index 00000000..e61eb0ad --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/THREEPARAMOPEN.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _THREEPARAMOPEN-data: + +THREEPARAMOPEN +============== + +.. +.. data:: THREEPARAMOPEN +.. + + + + +============================== ====================== +``THREEPARAMOPEN (x, y, z)`` ``open(x,y,z)`` +============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_ANONYMOUS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_ANONYMOUS.rst.txt new file mode 100644 index 00000000..696ca809 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_ANONYMOUS.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-ANONYMOUS-data: + +TKT_FLG_ANONYMOUS +================= + +.. +.. data:: TKT_FLG_ANONYMOUS +.. + + + + +======================== ====================== +``TKT_FLG_ANONYMOUS`` ``0x00008000`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_ENC_PA_REP.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_ENC_PA_REP.rst.txt new file mode 100644 index 00000000..b575553e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_ENC_PA_REP.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-ENC-PA-REP-data: + +TKT_FLG_ENC_PA_REP +================== + +.. +.. data:: TKT_FLG_ENC_PA_REP +.. + + + + +========================= ====================== +``TKT_FLG_ENC_PA_REP`` ``0x00010000`` +========================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_FORWARDABLE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_FORWARDABLE.rst.txt new file mode 100644 index 00000000..ede984cb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_FORWARDABLE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-FORWARDABLE-data: + +TKT_FLG_FORWARDABLE +=================== + +.. +.. data:: TKT_FLG_FORWARDABLE +.. + + + + +========================== ====================== +``TKT_FLG_FORWARDABLE`` ``0x40000000`` +========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_FORWARDED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_FORWARDED.rst.txt new file mode 100644 index 00000000..0f3d490d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_FORWARDED.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-FORWARDED-data: + +TKT_FLG_FORWARDED +================= + +.. +.. data:: TKT_FLG_FORWARDED +.. + + + + +======================== ====================== +``TKT_FLG_FORWARDED`` ``0x20000000`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_HW_AUTH.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_HW_AUTH.rst.txt new file mode 100644 index 00000000..30baa34e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_HW_AUTH.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-HW-AUTH-data: + +TKT_FLG_HW_AUTH +=============== + +.. +.. data:: TKT_FLG_HW_AUTH +.. + + + + +====================== ====================== +``TKT_FLG_HW_AUTH`` ``0x00100000`` +====================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_INITIAL.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_INITIAL.rst.txt new file mode 100644 index 00000000..6e3d8c31 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_INITIAL.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-INITIAL-data: + +TKT_FLG_INITIAL +=============== + +.. +.. data:: TKT_FLG_INITIAL +.. + + + + +====================== ====================== +``TKT_FLG_INITIAL`` ``0x00400000`` +====================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_INVALID.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_INVALID.rst.txt new file mode 100644 index 00000000..8d4465bb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_INVALID.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-INVALID-data: + +TKT_FLG_INVALID +=============== + +.. +.. data:: TKT_FLG_INVALID +.. + + + + +====================== ====================== +``TKT_FLG_INVALID`` ``0x01000000`` +====================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_MAY_POSTDATE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_MAY_POSTDATE.rst.txt new file mode 100644 index 00000000..935d05e7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_MAY_POSTDATE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-MAY-POSTDATE-data: + +TKT_FLG_MAY_POSTDATE +==================== + +.. +.. data:: TKT_FLG_MAY_POSTDATE +.. + + + + +=========================== ====================== +``TKT_FLG_MAY_POSTDATE`` ``0x04000000`` +=========================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE.rst.txt new file mode 100644 index 00000000..bee1deb2 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-OK-AS-DELEGATE-data: + +TKT_FLG_OK_AS_DELEGATE +====================== + +.. +.. data:: TKT_FLG_OK_AS_DELEGATE +.. + + + + +============================= ====================== +``TKT_FLG_OK_AS_DELEGATE`` ``0x00040000`` +============================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_POSTDATED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_POSTDATED.rst.txt new file mode 100644 index 00000000..46a5cf67 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_POSTDATED.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-POSTDATED-data: + +TKT_FLG_POSTDATED +================= + +.. +.. data:: TKT_FLG_POSTDATED +.. + + + + +======================== ====================== +``TKT_FLG_POSTDATED`` ``0x02000000`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_PRE_AUTH.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_PRE_AUTH.rst.txt new file mode 100644 index 00000000..69735bd1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_PRE_AUTH.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-PRE-AUTH-data: + +TKT_FLG_PRE_AUTH +================ + +.. +.. data:: TKT_FLG_PRE_AUTH +.. + + + + +======================= ====================== +``TKT_FLG_PRE_AUTH`` ``0x00200000`` +======================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_PROXIABLE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_PROXIABLE.rst.txt new file mode 100644 index 00000000..c73a62d6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_PROXIABLE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-PROXIABLE-data: + +TKT_FLG_PROXIABLE +================= + +.. +.. data:: TKT_FLG_PROXIABLE +.. + + + + +======================== ====================== +``TKT_FLG_PROXIABLE`` ``0x10000000`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_PROXY.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_PROXY.rst.txt new file mode 100644 index 00000000..b749830e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_PROXY.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-PROXY-data: + +TKT_FLG_PROXY +============= + +.. +.. data:: TKT_FLG_PROXY +.. + + + + +==================== ====================== +``TKT_FLG_PROXY`` ``0x08000000`` +==================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_RENEWABLE.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_RENEWABLE.rst.txt new file mode 100644 index 00000000..5d87dc97 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_RENEWABLE.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-RENEWABLE-data: + +TKT_FLG_RENEWABLE +================= + +.. +.. data:: TKT_FLG_RENEWABLE +.. + + + + +======================== ====================== +``TKT_FLG_RENEWABLE`` ``0x00800000`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED.rst.txt new file mode 100644 index 00000000..082a1f09 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _TKT-FLG-TRANSIT-POLICY-CHECKED-data: + +TKT_FLG_TRANSIT_POLICY_CHECKED +============================== + +.. +.. data:: TKT_FLG_TRANSIT_POLICY_CHECKED +.. + + + + +===================================== ====================== +``TKT_FLG_TRANSIT_POLICY_CHECKED`` ``0x00080000`` +===================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/VALID_INT_BITS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/VALID_INT_BITS.rst.txt new file mode 100644 index 00000000..0267d421 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/VALID_INT_BITS.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _VALID-INT-BITS-data: + +VALID_INT_BITS +============== + +.. +.. data:: VALID_INT_BITS +.. + + + + +===================== ====================== +``VALID_INT_BITS`` ``INT_MAX`` +===================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/VALID_UINT_BITS.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/VALID_UINT_BITS.rst.txt new file mode 100644 index 00000000..efba9a80 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/VALID_UINT_BITS.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _VALID-UINT-BITS-data: + +VALID_UINT_BITS +=============== + +.. +.. data:: VALID_UINT_BITS +.. + + + + +====================== ====================== +``VALID_UINT_BITS`` ``UINT_MAX`` +====================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/index.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/index.rst.txt new file mode 100644 index 00000000..45fe160d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/index.rst.txt @@ -0,0 +1,397 @@ +krb5 simple macros +========================= + +Public +------- + +.. toctree:: + :maxdepth: 1 + + ADDRTYPE_ADDRPORT.rst + ADDRTYPE_CHAOS.rst + ADDRTYPE_DDP.rst + ADDRTYPE_INET.rst + ADDRTYPE_INET6.rst + ADDRTYPE_IPPORT.rst + ADDRTYPE_ISO.rst + ADDRTYPE_IS_LOCAL.rst + ADDRTYPE_NETBIOS.rst + ADDRTYPE_XNS.rst + AD_TYPE_EXTERNAL.rst + AD_TYPE_FIELD_TYPE_MASK.rst + AD_TYPE_REGISTERED.rst + AD_TYPE_RESERVED.rst + AP_OPTS_ETYPE_NEGOTIATION.rst + AP_OPTS_MUTUAL_REQUIRED.rst + AP_OPTS_RESERVED.rst + AP_OPTS_USE_SESSION_KEY.rst + AP_OPTS_USE_SUBKEY.rst + AP_OPTS_WIRE_MASK.rst + CKSUMTYPE_CMAC_CAMELLIA128.rst + CKSUMTYPE_CMAC_CAMELLIA256.rst + CKSUMTYPE_CRC32.rst + CKSUMTYPE_DESCBC.rst + CKSUMTYPE_HMAC_MD5_ARCFOUR.rst + CKSUMTYPE_HMAC_SHA1_96_AES128.rst + CKSUMTYPE_HMAC_SHA1_96_AES256.rst + CKSUMTYPE_HMAC_SHA256_128_AES128.rst + CKSUMTYPE_HMAC_SHA384_192_AES256.rst + CKSUMTYPE_HMAC_SHA1_DES3.rst + CKSUMTYPE_MD5_HMAC_ARCFOUR.rst + CKSUMTYPE_NIST_SHA.rst + CKSUMTYPE_RSA_MD4.rst + CKSUMTYPE_RSA_MD4_DES.rst + CKSUMTYPE_RSA_MD5.rst + CKSUMTYPE_RSA_MD5_DES.rst + CKSUMTYPE_SHA1.rst + ENCTYPE_AES128_CTS_HMAC_SHA1_96.rst + ENCTYPE_AES128_CTS_HMAC_SHA256_128.rst + ENCTYPE_AES256_CTS_HMAC_SHA1_96.rst + ENCTYPE_AES256_CTS_HMAC_SHA384_192.rst + ENCTYPE_ARCFOUR_HMAC.rst + ENCTYPE_ARCFOUR_HMAC_EXP.rst + ENCTYPE_CAMELLIA128_CTS_CMAC.rst + ENCTYPE_CAMELLIA256_CTS_CMAC.rst + ENCTYPE_DES3_CBC_ENV.rst + ENCTYPE_DES3_CBC_RAW.rst + ENCTYPE_DES3_CBC_SHA.rst + ENCTYPE_DES3_CBC_SHA1.rst + ENCTYPE_DES_CBC_CRC.rst + ENCTYPE_DES_CBC_MD4.rst + ENCTYPE_DES_CBC_MD5.rst + ENCTYPE_DES_CBC_RAW.rst + ENCTYPE_DES_HMAC_SHA1.rst + ENCTYPE_DSA_SHA1_CMS.rst + ENCTYPE_MD5_RSA_CMS.rst + ENCTYPE_NULL.rst + ENCTYPE_RC2_CBC_ENV.rst + ENCTYPE_RSA_ENV.rst + ENCTYPE_RSA_ES_OAEP_ENV.rst + ENCTYPE_SHA1_RSA_CMS.rst + ENCTYPE_UNKNOWN.rst + KDC_OPT_ALLOW_POSTDATE.rst + KDC_OPT_CANONICALIZE.rst + KDC_OPT_CNAME_IN_ADDL_TKT.rst + KDC_OPT_DISABLE_TRANSITED_CHECK.rst + KDC_OPT_ENC_TKT_IN_SKEY.rst + KDC_OPT_FORWARDABLE.rst + KDC_OPT_FORWARDED.rst + KDC_OPT_POSTDATED.rst + KDC_OPT_PROXIABLE.rst + KDC_OPT_PROXY.rst + KDC_OPT_RENEW.rst + KDC_OPT_RENEWABLE.rst + KDC_OPT_RENEWABLE_OK.rst + KDC_OPT_REQUEST_ANONYMOUS.rst + KDC_OPT_VALIDATE.rst + KDC_TKT_COMMON_MASK.rst + KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE.rst + KRB5_ANONYMOUS_PRINCSTR.rst + KRB5_ANONYMOUS_REALMSTR.rst + KRB5_AP_REP.rst + KRB5_AP_REQ.rst + KRB5_AS_REP.rst + KRB5_AS_REQ.rst + KRB5_AUTHDATA_AND_OR.rst + KRB5_AUTHDATA_AP_OPTIONS.rst + KRB5_AUTHDATA_AUTH_INDICATOR.rst + KRB5_AUTHDATA_CAMMAC.rst + KRB5_AUTHDATA_ETYPE_NEGOTIATION.rst + KRB5_AUTHDATA_FX_ARMOR.rst + KRB5_AUTHDATA_IF_RELEVANT.rst + KRB5_AUTHDATA_INITIAL_VERIFIED_CAS.rst + KRB5_AUTHDATA_KDC_ISSUED.rst + KRB5_AUTHDATA_MANDATORY_FOR_KDC.rst + KRB5_AUTHDATA_OSF_DCE.rst + KRB5_AUTHDATA_SESAME.rst + KRB5_AUTHDATA_SIGNTICKET.rst + KRB5_AUTHDATA_WIN2K_PAC.rst + KRB5_AUTH_CONTEXT_DO_SEQUENCE.rst + KRB5_AUTH_CONTEXT_DO_TIME.rst + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR.rst + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR.rst + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR.rst + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR.rst + KRB5_AUTH_CONTEXT_PERMIT_ALL.rst + KRB5_AUTH_CONTEXT_RET_SEQUENCE.rst + KRB5_AUTH_CONTEXT_RET_TIME.rst + KRB5_AUTH_CONTEXT_USE_SUBKEY.rst + KRB5_CRED.rst + KRB5_CRYPTO_TYPE_CHECKSUM.rst + KRB5_CRYPTO_TYPE_DATA.rst + KRB5_CRYPTO_TYPE_EMPTY.rst + KRB5_CRYPTO_TYPE_HEADER.rst + KRB5_CRYPTO_TYPE_PADDING.rst + KRB5_CRYPTO_TYPE_SIGN_ONLY.rst + KRB5_CRYPTO_TYPE_STREAM.rst + KRB5_CRYPTO_TYPE_TRAILER.rst + KRB5_CYBERSAFE_SECUREID.rst + KRB5_DOMAIN_X500_COMPRESS.rst + KRB5_ENCPADATA_REQ_ENC_PA_REP.rst + KRB5_ERROR.rst + KRB5_FAST_REQUIRED.rst + KRB5_GC_CACHED.rst + KRB5_GC_CANONICALIZE.rst + KRB5_GC_CONSTRAINED_DELEGATION.rst + KRB5_GC_FORWARDABLE.rst + KRB5_GC_NO_STORE.rst + KRB5_GC_NO_TRANSIT_CHECK.rst + KRB5_GC_USER_USER.rst + KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST.rst + KRB5_GET_INIT_CREDS_OPT_ANONYMOUS.rst + KRB5_GET_INIT_CREDS_OPT_CANONICALIZE.rst + KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT.rst + KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST.rst + KRB5_GET_INIT_CREDS_OPT_FORWARDABLE.rst + KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST.rst + KRB5_GET_INIT_CREDS_OPT_PROXIABLE.rst + KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE.rst + KRB5_GET_INIT_CREDS_OPT_SALT.rst + KRB5_GET_INIT_CREDS_OPT_TKT_LIFE.rst + KRB5_INIT_CONTEXT_SECURE.rst + KRB5_INIT_CONTEXT_KDC.rst + KRB5_INIT_CREDS_STEP_FLAG_CONTINUE.rst + KRB5_INT16_MAX.rst + KRB5_INT16_MIN.rst + KRB5_INT32_MAX.rst + KRB5_INT32_MIN.rst + KRB5_KEYUSAGE_AD_ITE.rst + KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM.rst + KRB5_KEYUSAGE_AD_MTE.rst + KRB5_KEYUSAGE_AD_SIGNEDPATH.rst + KRB5_KEYUSAGE_APP_DATA_CKSUM.rst + KRB5_KEYUSAGE_APP_DATA_ENCRYPT.rst + KRB5_KEYUSAGE_AP_REP_ENCPART.rst + KRB5_KEYUSAGE_AP_REQ_AUTH.rst + KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM.rst + KRB5_KEYUSAGE_AS_REP_ENCPART.rst + KRB5_KEYUSAGE_AS_REQ.rst + KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS.rst + KRB5_KEYUSAGE_CAMMAC.rst + KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT.rst + KRB5_KEYUSAGE_ENC_CHALLENGE_KDC.rst + KRB5_KEYUSAGE_FAST_ENC.rst + KRB5_KEYUSAGE_FAST_FINISHED.rst + KRB5_KEYUSAGE_FAST_REP.rst + KRB5_KEYUSAGE_FAST_REQ_CHKSUM.rst + KRB5_KEYUSAGE_GSS_TOK_MIC.rst + KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.rst + KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.rst + KRB5_KEYUSAGE_IAKERB_FINISHED.rst + KRB5_KEYUSAGE_KDC_REP_TICKET.rst + KRB5_KEYUSAGE_KRB_CRED_ENCPART.rst + KRB5_KEYUSAGE_KRB_ERROR_CKSUM.rst + KRB5_KEYUSAGE_KRB_PRIV_ENCPART.rst + KRB5_KEYUSAGE_KRB_SAFE_CKSUM.rst + KRB5_KEYUSAGE_PA_AS_FRESHNESS.rst + KRB5_KEYUSAGE_PA_FX_COOKIE.rst + KRB5_KEYUSAGE_PA_OTP_REQUEST.rst + KRB5_KEYUSAGE_PA_PKINIT_KX.rst + KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY.rst + KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST.rst + KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.rst + KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.rst + KRB5_KEYUSAGE_PA_SAM_RESPONSE.rst + KRB5_KEYUSAGE_SPAKE.rst + KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.rst + KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.rst + KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.rst + KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY.rst + KRB5_KEYUSAGE_TGS_REQ_AUTH.rst + KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM.rst + KRB5_KPASSWD_ACCESSDENIED.rst + KRB5_KPASSWD_AUTHERROR.rst + KRB5_KPASSWD_BAD_VERSION.rst + KRB5_KPASSWD_HARDERROR.rst + KRB5_KPASSWD_INITIAL_FLAG_NEEDED.rst + KRB5_KPASSWD_MALFORMED.rst + KRB5_KPASSWD_SOFTERROR.rst + KRB5_KPASSWD_SUCCESS.rst + KRB5_LRQ_ALL_ACCT_EXPTIME.rst + KRB5_LRQ_ALL_LAST_INITIAL.rst + KRB5_LRQ_ALL_LAST_RENEWAL.rst + KRB5_LRQ_ALL_LAST_REQ.rst + KRB5_LRQ_ALL_LAST_TGT.rst + KRB5_LRQ_ALL_LAST_TGT_ISSUED.rst + KRB5_LRQ_ALL_PW_EXPTIME.rst + KRB5_LRQ_NONE.rst + KRB5_LRQ_ONE_ACCT_EXPTIME.rst + KRB5_LRQ_ONE_LAST_INITIAL.rst + KRB5_LRQ_ONE_LAST_RENEWAL.rst + KRB5_LRQ_ONE_LAST_REQ.rst + KRB5_LRQ_ONE_LAST_TGT.rst + KRB5_LRQ_ONE_LAST_TGT_ISSUED.rst + KRB5_LRQ_ONE_PW_EXPTIME.rst + KRB5_NT_ENTERPRISE_PRINCIPAL.rst + KRB5_NT_ENT_PRINCIPAL_AND_ID.rst + KRB5_NT_MS_PRINCIPAL.rst + KRB5_NT_MS_PRINCIPAL_AND_ID.rst + KRB5_NT_PRINCIPAL.rst + KRB5_NT_SMTP_NAME.rst + KRB5_NT_SRV_HST.rst + KRB5_NT_SRV_INST.rst + KRB5_NT_SRV_XHST.rst + KRB5_NT_UID.rst + KRB5_NT_UNKNOWN.rst + KRB5_NT_WELLKNOWN.rst + KRB5_NT_X500_PRINCIPAL.rst + KRB5_PAC_ATTRIBUTES_INFO.rst + KRB5_PAC_CLIENT_INFO.rst + KRB5_PAC_CLIENT_CLAIMS.rst + KRB5_PAC_CREDENTIALS_INFO.rst + KRB5_PAC_DELEGATION_INFO.rst + KRB5_PAC_DEVICE_CLAIMS.rst + KRB5_PAC_DEVICE_INFO.rst + KRB5_PAC_LOGON_INFO.rst + KRB5_PAC_PRIVSVR_CHECKSUM.rst + KRB5_PAC_REQUESTOR.rst + KRB5_PAC_SERVER_CHECKSUM.rst + KRB5_PAC_TICKET_CHECKSUM.rst + KRB5_PAC_UPN_DNS_INFO.rst + KRB5_PAC_FULL_CHECKSUM.rst + KRB5_PADATA_AFS3_SALT.rst + KRB5_PADATA_AP_REQ.rst + KRB5_PADATA_AS_CHECKSUM.rst + KRB5_PADATA_AS_FRESHNESS.rst + KRB5_PADATA_ENCRYPTED_CHALLENGE.rst + KRB5_PADATA_ENC_SANDIA_SECURID.rst + KRB5_PADATA_ENC_TIMESTAMP.rst + KRB5_PADATA_ENC_UNIX_TIME.rst + KRB5_PADATA_ETYPE_INFO.rst + KRB5_PADATA_ETYPE_INFO2.rst + KRB5_PADATA_FOR_USER.rst + KRB5_PADATA_FX_COOKIE.rst + KRB5_PADATA_FX_ERROR.rst + KRB5_PADATA_FX_FAST.rst + KRB5_PADATA_GET_FROM_TYPED_DATA.rst + KRB5_PADATA_NONE.rst + KRB5_PADATA_OSF_DCE.rst + KRB5_PADATA_OTP_CHALLENGE.rst + KRB5_PADATA_OTP_PIN_CHANGE.rst + KRB5_PADATA_OTP_REQUEST.rst + KRB5_PADATA_PAC_OPTIONS.rst + KRB5_PADATA_PAC_REQUEST.rst + KRB5_PADATA_PKINIT_KX.rst + KRB5_PADATA_PK_AS_REP.rst + KRB5_PADATA_PK_AS_REP_OLD.rst + KRB5_PADATA_PK_AS_REQ.rst + KRB5_PADATA_PK_AS_REQ_OLD.rst + KRB5_PADATA_PW_SALT.rst + KRB5_PADATA_REFERRAL.rst + KRB5_PADATA_S4U_X509_USER.rst + KRB5_PADATA_SAM_CHALLENGE.rst + KRB5_PADATA_SAM_CHALLENGE_2.rst + KRB5_PADATA_SAM_REDIRECT.rst + KRB5_PADATA_SAM_RESPONSE.rst + KRB5_PADATA_SAM_RESPONSE_2.rst + KRB5_PADATA_SESAME.rst + KRB5_PADATA_SPAKE.rst + KRB5_PADATA_REDHAT_IDP_OAUTH2.rst + KRB5_PADATA_REDHAT_PASSKEY.rst + KRB5_PADATA_SVR_REFERRAL_INFO.rst + KRB5_PADATA_TGS_REQ.rst + KRB5_PADATA_USE_SPECIFIED_KVNO.rst + KRB5_PRINCIPAL_COMPARE_CASEFOLD.rst + KRB5_PRINCIPAL_COMPARE_ENTERPRISE.rst + KRB5_PRINCIPAL_COMPARE_IGNORE_REALM.rst + KRB5_PRINCIPAL_COMPARE_UTF8.rst + KRB5_PRINCIPAL_PARSE_ENTERPRISE.rst + KRB5_PRINCIPAL_PARSE_IGNORE_REALM.rst + KRB5_PRINCIPAL_PARSE_NO_DEF_REALM.rst + KRB5_PRINCIPAL_PARSE_NO_REALM.rst + KRB5_PRINCIPAL_PARSE_REQUIRE_REALM.rst + KRB5_PRINCIPAL_UNPARSE_DISPLAY.rst + KRB5_PRINCIPAL_UNPARSE_NO_REALM.rst + KRB5_PRINCIPAL_UNPARSE_SHORT.rst + KRB5_PRIV.rst + KRB5_PROMPT_TYPE_NEW_PASSWORD.rst + KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN.rst + KRB5_PROMPT_TYPE_PASSWORD.rst + KRB5_PROMPT_TYPE_PREAUTH.rst + KRB5_PVNO.rst + KRB5_REALM_BRANCH_CHAR.rst + KRB5_RECVAUTH_BADAUTHVERS.rst + KRB5_RECVAUTH_SKIP_VERSION.rst + KRB5_REFERRAL_REALM.rst + KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW.rst + KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY.rst + KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.rst + KRB5_RESPONDER_QUESTION_PKINIT.rst + KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN.rst + KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN.rst + KRB5_RESPONDER_OTP_FLAGS_NEXTOTP.rst + KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN.rst + KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC.rst + KRB5_RESPONDER_OTP_FORMAT_DECIMAL.rst + KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL.rst + KRB5_RESPONDER_QUESTION_OTP.rst + KRB5_RESPONDER_QUESTION_PASSWORD.rst + KRB5_SAFE.rst + KRB5_SAM_MUST_PK_ENCRYPT_SAD.rst + KRB5_SAM_SEND_ENCRYPTED_SAD.rst + KRB5_SAM_USE_SAD_AS_KEY.rst + KRB5_TC_MATCH_2ND_TKT.rst + KRB5_TC_MATCH_AUTHDATA.rst + KRB5_TC_MATCH_FLAGS.rst + KRB5_TC_MATCH_FLAGS_EXACT.rst + KRB5_TC_MATCH_IS_SKEY.rst + KRB5_TC_MATCH_KTYPE.rst + KRB5_TC_MATCH_SRV_NAMEONLY.rst + KRB5_TC_MATCH_TIMES.rst + KRB5_TC_MATCH_TIMES_EXACT.rst + KRB5_TC_NOTICKET.rst + KRB5_TC_OPENCLOSE.rst + KRB5_TC_SUPPORTED_KTYPES.rst + KRB5_TGS_NAME.rst + KRB5_TGS_NAME_SIZE.rst + KRB5_TGS_REP.rst + KRB5_TGS_REQ.rst + KRB5_TKT_CREDS_STEP_FLAG_CONTINUE.rst + KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL.rst + KRB5_WELLKNOWN_NAMESTR.rst + LR_TYPE_INTERPRETATION_MASK.rst + LR_TYPE_THIS_SERVER_ONLY.rst + MAX_KEYTAB_NAME_LEN.rst + MSEC_DIRBIT.rst + MSEC_VAL_MASK.rst + SALT_TYPE_AFS_LENGTH.rst + SALT_TYPE_NO_LENGTH.rst + THREEPARAMOPEN.rst + TKT_FLG_ANONYMOUS.rst + TKT_FLG_ENC_PA_REP.rst + TKT_FLG_FORWARDABLE.rst + TKT_FLG_FORWARDED.rst + TKT_FLG_HW_AUTH.rst + TKT_FLG_INITIAL.rst + TKT_FLG_INVALID.rst + TKT_FLG_MAY_POSTDATE.rst + TKT_FLG_OK_AS_DELEGATE.rst + TKT_FLG_POSTDATED.rst + TKT_FLG_PRE_AUTH.rst + TKT_FLG_PROXIABLE.rst + TKT_FLG_PROXY.rst + TKT_FLG_RENEWABLE.rst + TKT_FLG_TRANSIT_POLICY_CHECKED.rst + VALID_INT_BITS.rst + VALID_UINT_BITS.rst + krb5_const.rst + krb5_princ_component.rst + krb5_princ_name.rst + krb5_princ_realm.rst + krb5_princ_set_realm.rst + krb5_princ_set_realm_data.rst + krb5_princ_set_realm_length.rst + krb5_princ_size.rst + krb5_princ_type.rst + krb5_roundup.rst + krb5_x.rst + krb5_xc.rst + +Deprecated macros +------------------------------ + +.. toctree:: + :maxdepth: 1 + + krb524_convert_creds_kdc.rst + krb524_init_ets.rst diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb524_convert_creds_kdc.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb524_convert_creds_kdc.rst.txt new file mode 100644 index 00000000..9316160f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb524_convert_creds_kdc.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb524-convert-creds-kdc-data: + +krb524_convert_creds_kdc +======================== + +.. +.. data:: krb524_convert_creds_kdc +.. + + + + +=============================== ====================== +``krb524_convert_creds_kdc`` ``krb5_524_convert_creds`` +=============================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb524_init_ets.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb524_init_ets.rst.txt new file mode 100644 index 00000000..dfb8e202 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb524_init_ets.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb524-init-ets-data: + +krb524_init_ets +=============== + +.. +.. data:: krb524_init_ets +.. + + + + +========================= ====================== +``krb524_init_ets (x)`` ``(0)`` +========================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_const.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_const.rst.txt new file mode 100644 index 00000000..1baaa096 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_const.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb5-const-data: + +krb5_const +========== + +.. +.. data:: krb5_const +.. + + + + +================= ====================== +``krb5_const`` ``const`` +================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_component.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_component.rst.txt new file mode 100644 index 00000000..cdca4bff --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_component.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb5-princ-component-data: + +krb5_princ_component +==================== + +.. +.. data:: krb5_princ_component +.. + + + + +============================================== ====================== +``krb5_princ_component (context, princ, i)`` `` (((i) < krb5_princ_size(context, princ)) ? (princ)->data + (i) : NULL)`` +============================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_name.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_name.rst.txt new file mode 100644 index 00000000..31481305 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_name.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb5-princ-name-data: + +krb5_princ_name +=============== + +.. +.. data:: krb5_princ_name +.. + + + + +====================================== ====================== +``krb5_princ_name (context, princ)`` ``(princ)->data`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_realm.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_realm.rst.txt new file mode 100644 index 00000000..562a2675 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_realm.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb5-princ-realm-data: + +krb5_princ_realm +================ + +.. +.. data:: krb5_princ_realm +.. + + + + +======================================= ====================== +``krb5_princ_realm (context, princ)`` ``(&(princ)->realm)`` +======================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_set_realm.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_set_realm.rst.txt new file mode 100644 index 00000000..dc05314a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_set_realm.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb5-princ-set-realm-data: + +krb5_princ_set_realm +==================== + +.. +.. data:: krb5_princ_set_realm +.. + + + + +================================================== ====================== +``krb5_princ_set_realm (context, princ, value)`` ``((princ)->realm = *(value))`` +================================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_set_realm_data.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_set_realm_data.rst.txt new file mode 100644 index 00000000..4ded1b3a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_set_realm_data.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb5-princ-set-realm-data-data: + +krb5_princ_set_realm_data +========================= + +.. +.. data:: krb5_princ_set_realm_data +.. + + + + +======================================================= ====================== +``krb5_princ_set_realm_data (context, princ, value)`` ``(princ)->realm.data = (value)`` +======================================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_set_realm_length.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_set_realm_length.rst.txt new file mode 100644 index 00000000..81ea192b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_set_realm_length.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb5-princ-set-realm-length-data: + +krb5_princ_set_realm_length +=========================== + +.. +.. data:: krb5_princ_set_realm_length +.. + + + + +========================================================= ====================== +``krb5_princ_set_realm_length (context, princ, value)`` ``(princ)->realm.length = (value)`` +========================================================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_size.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_size.rst.txt new file mode 100644 index 00000000..251fad5d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_size.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb5-princ-size-data: + +krb5_princ_size +=============== + +.. +.. data:: krb5_princ_size +.. + + + + +====================================== ====================== +``krb5_princ_size (context, princ)`` ``(princ)->length`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_type.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_type.rst.txt new file mode 100644 index 00000000..a4ff8a4b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_princ_type.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb5-princ-type-data: + +krb5_princ_type +=============== + +.. +.. data:: krb5_princ_type +.. + + + + +====================================== ====================== +``krb5_princ_type (context, princ)`` ``(princ)->type`` +====================================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_roundup.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_roundup.rst.txt new file mode 100644 index 00000000..db81d04b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_roundup.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb5-roundup-data: + +krb5_roundup +============ + +.. +.. data:: krb5_roundup +.. + + + + +========================= ====================== +``krb5_roundup (x, y)`` ``((((x) + (y) - 1)/(y))*(y))`` +========================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_x.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_x.rst.txt new file mode 100644 index 00000000..eaf3f869 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_x.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb5-x-data: + +krb5_x +====== + +.. +.. data:: krb5_x +.. + + + + +======================== ====================== +``krb5_x (ptr, args)`` ``((ptr)?((*(ptr)) args):(abort(),1))`` +======================== ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_xc.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_xc.rst.txt new file mode 100644 index 00000000..4d452672 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/macros/krb5_xc.rst.txt @@ -0,0 +1,17 @@ +.. highlight:: c + +.. _krb5-xc-data: + +krb5_xc +======= + +.. +.. data:: krb5_xc +.. + + + + +========================= ====================== +``krb5_xc (ptr, args)`` ``((ptr)?((*(ptr)) args):(abort(),(char*)0))`` +========================= ====================== diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/index.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/index.rst.txt new file mode 100644 index 00000000..d8d2a8f3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/index.rst.txt @@ -0,0 +1,108 @@ +krb5 types and structures +========================= + +Public +------- + +.. toctree:: + :maxdepth: 1 + + krb5_address.rst + krb5_addrtype.rst + krb5_ap_req.rst + krb5_ap_rep.rst + krb5_ap_rep_enc_part.rst + krb5_authdata.rst + krb5_authdatatype.rst + krb5_authenticator.rst + krb5_boolean.rst + krb5_checksum.rst + krb5_const_pointer.rst + krb5_const_principal.rst + krb5_cred.rst + krb5_cred_enc_part.rst + krb5_cred_info.rst + krb5_creds.rst + krb5_crypto_iov.rst + krb5_cryptotype.rst + krb5_data.rst + krb5_deltat.rst + krb5_enc_data.rst + krb5_enc_kdc_rep_part.rst + krb5_enc_tkt_part.rst + krb5_encrypt_block.rst + krb5_enctype.rst + krb5_error.rst + krb5_error_code.rst + krb5_expire_callback_func.rst + krb5_flags.rst + krb5_get_init_creds_opt.rst + krb5_gic_opt_pa_data.rst + krb5_int16.rst + krb5_int32.rst + krb5_kdc_rep.rst + krb5_kdc_req.rst + krb5_keyblock.rst + krb5_keytab_entry.rst + krb5_keyusage.rst + krb5_kt_cursor.rst + krb5_kvno.rst + krb5_last_req_entry.rst + krb5_magic.rst + krb5_mk_req_checksum_func.rst + krb5_msgtype.rst + krb5_octet.rst + krb5_pa_pac_req.rst + krb5_pa_server_referral_data.rst + krb5_pa_svr_referral_data.rst + krb5_pa_data.rst + krb5_pointer.rst + krb5_post_recv_fn.rst + krb5_pre_send_fn.rst + krb5_preauthtype.rst + krb5_principal.rst + krb5_principal_data.rst + krb5_prompt.rst + krb5_prompt_type.rst + krb5_prompter_fct.rst + krb5_pwd_data.rst + krb5_responder_context.rst + krb5_responder_fn.rst + krb5_responder_otp_challenge.rst + krb5_responder_otp_tokeninfo.rst + krb5_responder_pkinit_challenge.rst + krb5_responder_pkinit_identity.rst + krb5_response.rst + krb5_replay_data.rst + krb5_ticket.rst + krb5_ticket_times.rst + krb5_timestamp.rst + krb5_tkt_authent.rst + krb5_trace_callback.rst + krb5_trace_info.rst + krb5_transited.rst + krb5_typed_data.rst + krb5_ui_2.rst + krb5_ui_4.rst + krb5_verify_init_creds_opt.rst + passwd_phrase_element.rst + + +Internal +--------- + +.. toctree:: + :maxdepth: 1 + + krb5_auth_context.rst + krb5_cksumtype + krb5_context.rst + krb5_cc_cursor.rst + krb5_ccache.rst + krb5_cccol_cursor.rst + krb5_init_creds_context.rst + krb5_key.rst + krb5_keytab.rst + krb5_pac.rst + krb5_rcache.rst + krb5_tkt_creds_context.rst diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_address.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_address.rst.txt new file mode 100644 index 00000000..1b433789 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_address.rst.txt @@ -0,0 +1,45 @@ +.. highlight:: c + +.. _krb5-address-struct: + +krb5_address +============ + +.. +.. c:type:: krb5_address +.. + +Structure for address. + + + +Declaration +------------ + +typedef struct _krb5_address krb5_address + + +Members +--------- + + +.. c:member:: krb5_magic krb5_address.magic + + + + +.. c:member:: krb5_addrtype krb5_address.addrtype + + + + +.. c:member:: unsigned int krb5_address.length + + + + +.. c:member:: krb5_octet * krb5_address.contents + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_addrtype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_addrtype.rst.txt new file mode 100644 index 00000000..4c619163 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_addrtype.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-addrtype-struct: + +krb5_addrtype +============= + +.. +.. c:type:: krb5_addrtype +.. + + + + +Declaration +------------ + +typedef krb5_int32 krb5_addrtype + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ap_rep.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ap_rep.rst.txt new file mode 100644 index 00000000..e2e7e7df --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ap_rep.rst.txt @@ -0,0 +1,35 @@ +.. highlight:: c + +.. _krb5-ap-rep-struct: + +krb5_ap_rep +=========== + +.. +.. c:type:: krb5_ap_rep +.. + +C representaton of AP-REP message. + +The server's response to a client's request for mutual authentication. + +Declaration +------------ + +typedef struct _krb5_ap_rep krb5_ap_rep + + +Members +--------- + + +.. c:member:: krb5_magic krb5_ap_rep.magic + + + + +.. c:member:: krb5_enc_data krb5_ap_rep.enc_part + + Ciphertext of ApRepEncPart. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ap_rep_enc_part.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ap_rep_enc_part.rst.txt new file mode 100644 index 00000000..b7191783 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ap_rep_enc_part.rst.txt @@ -0,0 +1,50 @@ +.. highlight:: c + +.. _krb5-ap-rep-enc-part-struct: + +krb5_ap_rep_enc_part +==================== + +.. +.. c:type:: krb5_ap_rep_enc_part +.. + +Cleartext that is encrypted and put into :c:type:`_krb5_ap_rep` . + + + +Declaration +------------ + +typedef struct _krb5_ap_rep_enc_part krb5_ap_rep_enc_part + + +Members +--------- + + +.. c:member:: krb5_magic krb5_ap_rep_enc_part.magic + + + + +.. c:member:: krb5_timestamp krb5_ap_rep_enc_part.ctime + + Client time, seconds portion. + + +.. c:member:: krb5_int32 krb5_ap_rep_enc_part.cusec + + Client time, microseconds portion. + + +.. c:member:: krb5_keyblock * krb5_ap_rep_enc_part.subkey + + Subkey (optional) + + +.. c:member:: krb5_ui_4 krb5_ap_rep_enc_part.seq_number + + Sequence number. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ap_req.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ap_req.rst.txt new file mode 100644 index 00000000..8d9642c7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ap_req.rst.txt @@ -0,0 +1,45 @@ +.. highlight:: c + +.. _krb5-ap-req-struct: + +krb5_ap_req +=========== + +.. +.. c:type:: krb5_ap_req +.. + +Authentication header. + + + +Declaration +------------ + +typedef struct _krb5_ap_req krb5_ap_req + + +Members +--------- + + +.. c:member:: krb5_magic krb5_ap_req.magic + + + + +.. c:member:: krb5_flags krb5_ap_req.ap_options + + Requested options. + + +.. c:member:: krb5_ticket * krb5_ap_req.ticket + + Ticket. + + +.. c:member:: krb5_enc_data krb5_ap_req.authenticator + + Encrypted authenticator. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_auth_context.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_auth_context.rst.txt new file mode 100644 index 00000000..e0f302c5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_auth_context.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-auth-context-struct: + +krb5_auth_context +================= + +.. +.. c:type:: krb5_auth_context +.. + + + + +Declaration +------------ + +typedef struct _krb5_auth_context\* krb5_auth_context + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_authdata.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_authdata.rst.txt new file mode 100644 index 00000000..6419a059 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_authdata.rst.txt @@ -0,0 +1,45 @@ +.. highlight:: c + +.. _krb5-authdata-struct: + +krb5_authdata +============= + +.. +.. c:type:: krb5_authdata +.. + +Structure for auth data. + + + +Declaration +------------ + +typedef struct _krb5_authdata krb5_authdata + + +Members +--------- + + +.. c:member:: krb5_magic krb5_authdata.magic + + + + +.. c:member:: krb5_authdatatype krb5_authdata.ad_type + + ADTYPE. + + +.. c:member:: unsigned int krb5_authdata.length + + Length of data. + + +.. c:member:: krb5_octet * krb5_authdata.contents + + Data. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_authdatatype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_authdatatype.rst.txt new file mode 100644 index 00000000..01c23d97 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_authdatatype.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-authdatatype-struct: + +krb5_authdatatype +================= + +.. +.. c:type:: krb5_authdatatype +.. + + + + +Declaration +------------ + +typedef krb5_int32 krb5_authdatatype + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_authenticator.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_authenticator.rst.txt new file mode 100644 index 00000000..4b2b1c92 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_authenticator.rst.txt @@ -0,0 +1,65 @@ +.. highlight:: c + +.. _krb5-authenticator-struct: + +krb5_authenticator +================== + +.. +.. c:type:: krb5_authenticator +.. + +Ticket authenticator. + +The C representation of an unencrypted authenticator. + +Declaration +------------ + +typedef struct _krb5_authenticator krb5_authenticator + + +Members +--------- + + +.. c:member:: krb5_magic krb5_authenticator.magic + + + + +.. c:member:: krb5_principal krb5_authenticator.client + + client name/realm + + +.. c:member:: krb5_checksum * krb5_authenticator.checksum + + checksum, includes type, optional + + +.. c:member:: krb5_int32 krb5_authenticator.cusec + + client usec portion + + +.. c:member:: krb5_timestamp krb5_authenticator.ctime + + client sec portion + + +.. c:member:: krb5_keyblock * krb5_authenticator.subkey + + true session key, optional + + +.. c:member:: krb5_ui_4 krb5_authenticator.seq_number + + sequence #, optional + + +.. c:member:: krb5_authdata ** krb5_authenticator.authorization_data + + authoriazation data + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_boolean.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_boolean.rst.txt new file mode 100644 index 00000000..f9be9b41 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_boolean.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-boolean-struct: + +krb5_boolean +============ + +.. +.. c:type:: krb5_boolean +.. + + + + +Declaration +------------ + +typedef unsigned int krb5_boolean + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cc_cursor.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cc_cursor.rst.txt new file mode 100644 index 00000000..97da560d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cc_cursor.rst.txt @@ -0,0 +1,21 @@ +.. highlight:: c + +.. _krb5-cc-cursor-struct: + +krb5_cc_cursor +============== + +.. +.. c:type:: krb5_cc_cursor +.. + +Cursor for sequential lookup. + + + +Declaration +------------ + +typedef krb5_pointer krb5_cc_cursor + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ccache.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ccache.rst.txt new file mode 100644 index 00000000..86317f5f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ccache.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-ccache-struct: + +krb5_ccache +=========== + +.. +.. c:type:: krb5_ccache +.. + + + + +Declaration +------------ + +typedef struct _krb5_ccache\* krb5_ccache + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cccol_cursor.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cccol_cursor.rst.txt new file mode 100644 index 00000000..13095b1c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cccol_cursor.rst.txt @@ -0,0 +1,21 @@ +.. highlight:: c + +.. _krb5-cccol-cursor-struct: + +krb5_cccol_cursor +================= + +.. +.. c:type:: krb5_cccol_cursor +.. + +Cursor for iterating over all ccaches. + + + +Declaration +------------ + +typedef struct _krb5_cccol_cursor\* krb5_cccol_cursor + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_checksum.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_checksum.rst.txt new file mode 100644 index 00000000..de4cc011 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_checksum.rst.txt @@ -0,0 +1,44 @@ +.. highlight:: c + +.. _krb5-checksum-struct: + +krb5_checksum +============= + +.. +.. c:type:: krb5_checksum +.. + + + + +Declaration +------------ + +typedef struct _krb5_checksum krb5_checksum + + +Members +--------- + + +.. c:member:: krb5_magic krb5_checksum.magic + + + + +.. c:member:: krb5_cksumtype krb5_checksum.checksum_type + + + + +.. c:member:: unsigned int krb5_checksum.length + + + + +.. c:member:: krb5_octet * krb5_checksum.contents + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cksumtype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cksumtype.rst.txt new file mode 100644 index 00000000..52a757a4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cksumtype.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-cksumtype-struct: + +krb5_cksumtype +============== + +.. +.. c:type:: krb5_cksumtype +.. + + + + +Declaration +------------ + +typedef krb5_int32 krb5_cksumtype + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_const_pointer.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_const_pointer.rst.txt new file mode 100644 index 00000000..7b70b430 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_const_pointer.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-const-pointer-struct: + +krb5_const_pointer +================== + +.. +.. c:type:: krb5_const_pointer +.. + + + + +Declaration +------------ + +typedef void const\* krb5_const_pointer + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_const_principal.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_const_principal.rst.txt new file mode 100644 index 00000000..37131f6a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_const_principal.rst.txt @@ -0,0 +1,50 @@ +.. highlight:: c + +.. _krb5-const-principal-struct: + +krb5_const_principal +==================== + +.. +.. c:type:: krb5_const_principal +.. + +Constant version of :c:type:`krb5_principal_data` . + + + +Declaration +------------ + +typedef const krb5_principal_data\* krb5_const_principal + + +Members +--------- + + +.. c:member:: krb5_magic krb5_const_principal.magic + + + + +.. c:member:: krb5_data krb5_const_principal.realm + + + + +.. c:member:: krb5_data * krb5_const_principal.data + + An array of strings. + + +.. c:member:: krb5_int32 krb5_const_principal.length + + + + +.. c:member:: krb5_int32 krb5_const_principal.type + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_context.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_context.rst.txt new file mode 100644 index 00000000..8390b9cd --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_context.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-context-struct: + +krb5_context +============ + +.. +.. c:type:: krb5_context +.. + + + + +Declaration +------------ + +typedef struct _krb5_context\* krb5_context + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cred.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cred.rst.txt new file mode 100644 index 00000000..500d0162 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cred.rst.txt @@ -0,0 +1,45 @@ +.. highlight:: c + +.. _krb5-cred-struct: + +krb5_cred +========= + +.. +.. c:type:: krb5_cred +.. + +Credentials data structure. + + + +Declaration +------------ + +typedef struct _krb5_cred krb5_cred + + +Members +--------- + + +.. c:member:: krb5_magic krb5_cred.magic + + + + +.. c:member:: krb5_ticket ** krb5_cred.tickets + + Tickets. + + +.. c:member:: krb5_enc_data krb5_cred.enc_part + + Encrypted part. + + +.. c:member:: krb5_cred_enc_part * krb5_cred.enc_part2 + + Unencrypted version, if available. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cred_enc_part.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cred_enc_part.rst.txt new file mode 100644 index 00000000..a69650a5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cred_enc_part.rst.txt @@ -0,0 +1,60 @@ +.. highlight:: c + +.. _krb5-cred-enc-part-struct: + +krb5_cred_enc_part +================== + +.. +.. c:type:: krb5_cred_enc_part +.. + +Cleartext credentials information. + + + +Declaration +------------ + +typedef struct _krb5_cred_enc_part krb5_cred_enc_part + + +Members +--------- + + +.. c:member:: krb5_magic krb5_cred_enc_part.magic + + + + +.. c:member:: krb5_int32 krb5_cred_enc_part.nonce + + Nonce (optional) + + +.. c:member:: krb5_timestamp krb5_cred_enc_part.timestamp + + Generation time, seconds portion. + + +.. c:member:: krb5_int32 krb5_cred_enc_part.usec + + Generation time, microseconds portion. + + +.. c:member:: krb5_address * krb5_cred_enc_part.s_address + + Sender address (optional) + + +.. c:member:: krb5_address * krb5_cred_enc_part.r_address + + Recipient address (optional) + + +.. c:member:: krb5_cred_info ** krb5_cred_enc_part.ticket_info + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cred_info.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cred_info.rst.txt new file mode 100644 index 00000000..f0dcc34a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cred_info.rst.txt @@ -0,0 +1,60 @@ +.. highlight:: c + +.. _krb5-cred-info-struct: + +krb5_cred_info +============== + +.. +.. c:type:: krb5_cred_info +.. + +Credentials information inserted into *EncKrbCredPart* . + + + +Declaration +------------ + +typedef struct _krb5_cred_info krb5_cred_info + + +Members +--------- + + +.. c:member:: krb5_magic krb5_cred_info.magic + + + + +.. c:member:: krb5_keyblock * krb5_cred_info.session + + Session key used to encrypt ticket. + + +.. c:member:: krb5_principal krb5_cred_info.client + + Client principal and realm. + + +.. c:member:: krb5_principal krb5_cred_info.server + + Server principal and realm. + + +.. c:member:: krb5_flags krb5_cred_info.flags + + Ticket flags. + + +.. c:member:: krb5_ticket_times krb5_cred_info.times + + Auth, start, end, renew_till. + + +.. c:member:: krb5_address ** krb5_cred_info.caddrs + + Array of pointers to addrs (optional) + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_creds.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_creds.rst.txt new file mode 100644 index 00000000..68c0c663 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_creds.rst.txt @@ -0,0 +1,80 @@ +.. highlight:: c + +.. _krb5-creds-struct: + +krb5_creds +========== + +.. +.. c:type:: krb5_creds +.. + +Credentials structure including ticket, session key, and lifetime info. + + + +Declaration +------------ + +typedef struct _krb5_creds krb5_creds + + +Members +--------- + + +.. c:member:: krb5_magic krb5_creds.magic + + + + +.. c:member:: krb5_principal krb5_creds.client + + client's principal identifier + + +.. c:member:: krb5_principal krb5_creds.server + + server's principal identifier + + +.. c:member:: krb5_keyblock krb5_creds.keyblock + + session encryption key info + + +.. c:member:: krb5_ticket_times krb5_creds.times + + lifetime info + + +.. c:member:: krb5_boolean krb5_creds.is_skey + + true if ticket is encrypted in another ticket's skey + + +.. c:member:: krb5_flags krb5_creds.ticket_flags + + flags in ticket + + +.. c:member:: krb5_address ** krb5_creds.addresses + + addrs in ticket + + +.. c:member:: krb5_data krb5_creds.ticket + + ticket string itself + + +.. c:member:: krb5_data krb5_creds.second_ticket + + second ticket, if related to ticket (via DUPLICATE-SKEY or ENC-TKT-IN-SKEY) + + +.. c:member:: krb5_authdata ** krb5_creds.authdata + + authorization data + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_crypto_iov.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_crypto_iov.rst.txt new file mode 100644 index 00000000..e4eb787b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_crypto_iov.rst.txt @@ -0,0 +1,35 @@ +.. highlight:: c + +.. _krb5-crypto-iov-struct: + +krb5_crypto_iov +=============== + +.. +.. c:type:: krb5_crypto_iov +.. + +Structure to describe a region of text to be encrypted or decrypted. + +The *flags* member describes the type of the iov. The *data* member points to the memory that will be manipulated. All iov APIs take a pointer to the first element of an array of krb5_crypto_iov's along with the size of that array. Buffer contents are manipulated in-place; data is overwritten. Callers must allocate the right number of krb5_crypto_iov structures before calling into an iov API. + +Declaration +------------ + +typedef struct _krb5_crypto_iov krb5_crypto_iov + + +Members +--------- + + +.. c:member:: krb5_cryptotype krb5_crypto_iov.flags + + iov type (see KRB5_CRYPTO_TYPE macros) + + +.. c:member:: krb5_data krb5_crypto_iov.data + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cryptotype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cryptotype.rst.txt new file mode 100644 index 00000000..1e49e351 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_cryptotype.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-cryptotype-struct: + +krb5_cryptotype +=============== + +.. +.. c:type:: krb5_cryptotype +.. + + + + +Declaration +------------ + +typedef krb5_int32 krb5_cryptotype + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_data.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_data.rst.txt new file mode 100644 index 00000000..98cc3a76 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_data.rst.txt @@ -0,0 +1,39 @@ +.. highlight:: c + +.. _krb5-data-struct: + +krb5_data +========= + +.. +.. c:type:: krb5_data +.. + + + + +Declaration +------------ + +typedef struct _krb5_data krb5_data + + +Members +--------- + + +.. c:member:: krb5_magic krb5_data.magic + + + + +.. c:member:: unsigned int krb5_data.length + + + + +.. c:member:: char * krb5_data.data + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_deltat.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_deltat.rst.txt new file mode 100644 index 00000000..bfefbe88 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_deltat.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-deltat-struct: + +krb5_deltat +=========== + +.. +.. c:type:: krb5_deltat +.. + + + + +Declaration +------------ + +typedef krb5_int32 krb5_deltat + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enc_data.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enc_data.rst.txt new file mode 100644 index 00000000..0f874c7f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enc_data.rst.txt @@ -0,0 +1,44 @@ +.. highlight:: c + +.. _krb5-enc-data-struct: + +krb5_enc_data +============= + +.. +.. c:type:: krb5_enc_data +.. + + + + +Declaration +------------ + +typedef struct _krb5_enc_data krb5_enc_data + + +Members +--------- + + +.. c:member:: krb5_magic krb5_enc_data.magic + + + + +.. c:member:: krb5_enctype krb5_enc_data.enctype + + + + +.. c:member:: krb5_kvno krb5_enc_data.kvno + + + + +.. c:member:: krb5_data krb5_enc_data.ciphertext + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enc_kdc_rep_part.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enc_kdc_rep_part.rst.txt new file mode 100644 index 00000000..7c7a2460 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enc_kdc_rep_part.rst.txt @@ -0,0 +1,80 @@ +.. highlight:: c + +.. _krb5-enc-kdc-rep-part-struct: + +krb5_enc_kdc_rep_part +===================== + +.. +.. c:type:: krb5_enc_kdc_rep_part +.. + +C representation of *EncKDCRepPart* protocol message. + +This is the cleartext message that is encrypted and inserted in *KDC-REP* . + +Declaration +------------ + +typedef struct _krb5_enc_kdc_rep_part krb5_enc_kdc_rep_part + + +Members +--------- + + +.. c:member:: krb5_magic krb5_enc_kdc_rep_part.magic + + + + +.. c:member:: krb5_msgtype krb5_enc_kdc_rep_part.msg_type + + krb5 message type + + +.. c:member:: krb5_keyblock * krb5_enc_kdc_rep_part.session + + Session key. + + +.. c:member:: krb5_last_req_entry ** krb5_enc_kdc_rep_part.last_req + + Array of pointers to entries. + + +.. c:member:: krb5_int32 krb5_enc_kdc_rep_part.nonce + + Nonce from request. + + +.. c:member:: krb5_timestamp krb5_enc_kdc_rep_part.key_exp + + Expiration date. + + +.. c:member:: krb5_flags krb5_enc_kdc_rep_part.flags + + Ticket flags. + + +.. c:member:: krb5_ticket_times krb5_enc_kdc_rep_part.times + + Lifetime info. + + +.. c:member:: krb5_principal krb5_enc_kdc_rep_part.server + + Server's principal identifier. + + +.. c:member:: krb5_address ** krb5_enc_kdc_rep_part.caddrs + + Array of ptrs to addrs, optional. + + +.. c:member:: krb5_pa_data ** krb5_enc_kdc_rep_part.enc_padata + + Encrypted preauthentication data. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enc_tkt_part.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enc_tkt_part.rst.txt new file mode 100644 index 00000000..05cbe481 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enc_tkt_part.rst.txt @@ -0,0 +1,65 @@ +.. highlight:: c + +.. _krb5-enc-tkt-part-struct: + +krb5_enc_tkt_part +================= + +.. +.. c:type:: krb5_enc_tkt_part +.. + +Encrypted part of ticket. + + + +Declaration +------------ + +typedef struct _krb5_enc_tkt_part krb5_enc_tkt_part + + +Members +--------- + + +.. c:member:: krb5_magic krb5_enc_tkt_part.magic + + + + +.. c:member:: krb5_flags krb5_enc_tkt_part.flags + + flags + + +.. c:member:: krb5_keyblock * krb5_enc_tkt_part.session + + session key: includes enctype + + +.. c:member:: krb5_principal krb5_enc_tkt_part.client + + client name/realm + + +.. c:member:: krb5_transited krb5_enc_tkt_part.transited + + list of transited realms + + +.. c:member:: krb5_ticket_times krb5_enc_tkt_part.times + + auth, start, end, renew_till + + +.. c:member:: krb5_address ** krb5_enc_tkt_part.caddrs + + array of ptrs to addresses + + +.. c:member:: krb5_authdata ** krb5_enc_tkt_part.authorization_data + + auth data + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_encrypt_block.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_encrypt_block.rst.txt new file mode 100644 index 00000000..daf2fa50 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_encrypt_block.rst.txt @@ -0,0 +1,39 @@ +.. highlight:: c + +.. _krb5-encrypt-block-struct: + +krb5_encrypt_block +================== + +.. +.. c:type:: krb5_encrypt_block +.. + + + + +Declaration +------------ + +typedef struct _krb5_encrypt_block krb5_encrypt_block + + +Members +--------- + + +.. c:member:: krb5_magic krb5_encrypt_block.magic + + + + +.. c:member:: krb5_enctype krb5_encrypt_block.crypto_entry + + + + +.. c:member:: krb5_keyblock * krb5_encrypt_block.key + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enctype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enctype.rst.txt new file mode 100644 index 00000000..c820bf8e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_enctype.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-enctype-struct: + +krb5_enctype +============ + +.. +.. c:type:: krb5_enctype +.. + + + + +Declaration +------------ + +typedef krb5_int32 krb5_enctype + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_error.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_error.rst.txt new file mode 100644 index 00000000..29a64665 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_error.rst.txt @@ -0,0 +1,75 @@ +.. highlight:: c + +.. _krb5-error-struct: + +krb5_error +========== + +.. +.. c:type:: krb5_error +.. + +Error message structure. + + + +Declaration +------------ + +typedef struct _krb5_error krb5_error + + +Members +--------- + + +.. c:member:: krb5_magic krb5_error.magic + + + + +.. c:member:: krb5_timestamp krb5_error.ctime + + Client sec portion; optional. + + +.. c:member:: krb5_int32 krb5_error.cusec + + Client usec portion; optional. + + +.. c:member:: krb5_int32 krb5_error.susec + + Server usec portion. + + +.. c:member:: krb5_timestamp krb5_error.stime + + Server sec portion. + + +.. c:member:: krb5_ui_4 krb5_error.error + + Error code (protocol error #'s) + + +.. c:member:: krb5_principal krb5_error.client + + Client principal and realm. + + +.. c:member:: krb5_principal krb5_error.server + + Server principal and realm. + + +.. c:member:: krb5_data krb5_error.text + + Descriptive text. + + +.. c:member:: krb5_data krb5_error.e_data + + Additional error-describing data. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_error_code.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_error_code.rst.txt new file mode 100644 index 00000000..58d374ba --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_error_code.rst.txt @@ -0,0 +1,21 @@ +.. highlight:: c + +.. _krb5-error-code-struct: + +krb5_error_code +=============== + +.. +.. c:type:: krb5_error_code +.. + +Used to convey an operation status. + +The value 0 indicates success; any other values are com_err codes. Use krb5_get_error_message() to obtain a string describing the error. + +Declaration +------------ + +typedef krb5_int32 krb5_error_code + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_expire_callback_func.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_expire_callback_func.rst.txt new file mode 100644 index 00000000..13b1f217 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_expire_callback_func.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-expire-callback-func-struct: + +krb5_expire_callback_func +========================= + +.. +.. c:type:: krb5_expire_callback_func +.. + + + + +Declaration +------------ + +typedef void( \* krb5_expire_callback_func) (krb5_context context, void \*data, krb5_timestamp password_expiration, krb5_timestamp account_expiration, krb5_boolean is_last_req) + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_flags.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_flags.rst.txt new file mode 100644 index 00000000..398a5e95 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_flags.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-flags-struct: + +krb5_flags +========== + +.. +.. c:type:: krb5_flags +.. + + + + +Declaration +------------ + +typedef krb5_int32 krb5_flags + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_get_init_creds_opt.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_get_init_creds_opt.rst.txt new file mode 100644 index 00000000..19742f20 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_get_init_creds_opt.rst.txt @@ -0,0 +1,80 @@ +.. highlight:: c + +.. _krb5-get-init-creds-opt-struct: + +krb5_get_init_creds_opt +======================= + +.. +.. c:type:: krb5_get_init_creds_opt +.. + +Store options for *_krb5_get_init_creds* . + + + +Declaration +------------ + +typedef struct _krb5_get_init_creds_opt krb5_get_init_creds_opt + + +Members +--------- + + +.. c:member:: krb5_flags krb5_get_init_creds_opt.flags + + + + +.. c:member:: krb5_deltat krb5_get_init_creds_opt.tkt_life + + + + +.. c:member:: krb5_deltat krb5_get_init_creds_opt.renew_life + + + + +.. c:member:: int krb5_get_init_creds_opt.forwardable + + + + +.. c:member:: int krb5_get_init_creds_opt.proxiable + + + + +.. c:member:: krb5_enctype * krb5_get_init_creds_opt.etype_list + + + + +.. c:member:: int krb5_get_init_creds_opt.etype_list_length + + + + +.. c:member:: krb5_address ** krb5_get_init_creds_opt.address_list + + + + +.. c:member:: krb5_preauthtype * krb5_get_init_creds_opt.preauth_list + + + + +.. c:member:: int krb5_get_init_creds_opt.preauth_list_length + + + + +.. c:member:: krb5_data * krb5_get_init_creds_opt.salt + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_gic_opt_pa_data.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_gic_opt_pa_data.rst.txt new file mode 100644 index 00000000..cef8a469 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_gic_opt_pa_data.rst.txt @@ -0,0 +1,35 @@ +.. highlight:: c + +.. _krb5-gic-opt-pa-data-struct: + +krb5_gic_opt_pa_data +==================== + +.. +.. c:type:: krb5_gic_opt_pa_data +.. + +Generic preauth option attribute/value pairs. + + + +Declaration +------------ + +typedef struct _krb5_gic_opt_pa_data krb5_gic_opt_pa_data + + +Members +--------- + + +.. c:member:: char * krb5_gic_opt_pa_data.attr + + + + +.. c:member:: char * krb5_gic_opt_pa_data.value + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_init_creds_context.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_init_creds_context.rst.txt new file mode 100644 index 00000000..22c4af36 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_init_creds_context.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-init-creds-context-struct: + +krb5_init_creds_context +======================= + +.. +.. c:type:: krb5_init_creds_context +.. + + + + +Declaration +------------ + +typedef struct _krb5_init_creds_context\* krb5_init_creds_context + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_int16.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_int16.rst.txt new file mode 100644 index 00000000..9686c306 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_int16.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-int16-struct: + +krb5_int16 +========== + +.. +.. c:type:: krb5_int16 +.. + + + + +Declaration +------------ + +typedef int16_t krb5_int16 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_int32.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_int32.rst.txt new file mode 100644 index 00000000..cab1a43f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_int32.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-int32-struct: + +krb5_int32 +========== + +.. +.. c:type:: krb5_int32 +.. + + + + +Declaration +------------ + +typedef int32_t krb5_int32 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kdc_rep.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kdc_rep.rst.txt new file mode 100644 index 00000000..5e742dfc --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kdc_rep.rst.txt @@ -0,0 +1,60 @@ +.. highlight:: c + +.. _krb5-kdc-rep-struct: + +krb5_kdc_rep +============ + +.. +.. c:type:: krb5_kdc_rep +.. + +Representation of the *KDC-REP* protocol message. + + + +Declaration +------------ + +typedef struct _krb5_kdc_rep krb5_kdc_rep + + +Members +--------- + + +.. c:member:: krb5_magic krb5_kdc_rep.magic + + + + +.. c:member:: krb5_msgtype krb5_kdc_rep.msg_type + + KRB5_AS_REP or KRB5_KDC_REP. + + +.. c:member:: krb5_pa_data ** krb5_kdc_rep.padata + + Preauthentication data from KDC. + + +.. c:member:: krb5_principal krb5_kdc_rep.client + + Client principal and realm. + + +.. c:member:: krb5_ticket * krb5_kdc_rep.ticket + + Ticket. + + +.. c:member:: krb5_enc_data krb5_kdc_rep.enc_part + + Encrypted part of reply. + + +.. c:member:: krb5_enc_kdc_rep_part * krb5_kdc_rep.enc_part2 + + Unencrypted version, if available. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kdc_req.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kdc_req.rst.txt new file mode 100644 index 00000000..51e3512c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kdc_req.rst.txt @@ -0,0 +1,105 @@ +.. highlight:: c + +.. _krb5-kdc-req-struct: + +krb5_kdc_req +============ + +.. +.. c:type:: krb5_kdc_req +.. + +C representation of KDC-REQ protocol message, including KDC-REQ-BODY. + + + +Declaration +------------ + +typedef struct _krb5_kdc_req krb5_kdc_req + + +Members +--------- + + +.. c:member:: krb5_magic krb5_kdc_req.magic + + + + +.. c:member:: krb5_msgtype krb5_kdc_req.msg_type + + KRB5_AS_REQ or KRB5_TGS_REQ. + + +.. c:member:: krb5_pa_data ** krb5_kdc_req.padata + + Preauthentication data. + + +.. c:member:: krb5_flags krb5_kdc_req.kdc_options + + Requested options. + + +.. c:member:: krb5_principal krb5_kdc_req.client + + Client principal and realm. + + +.. c:member:: krb5_principal krb5_kdc_req.server + + Server principal and realm. + + +.. c:member:: krb5_timestamp krb5_kdc_req.from + + Requested start time. + + +.. c:member:: krb5_timestamp krb5_kdc_req.till + + Requested end time. + + +.. c:member:: krb5_timestamp krb5_kdc_req.rtime + + Requested renewable end time. + + +.. c:member:: krb5_int32 krb5_kdc_req.nonce + + Nonce to match request and response. + + +.. c:member:: int krb5_kdc_req.nktypes + + Number of enctypes. + + +.. c:member:: krb5_enctype * krb5_kdc_req.ktype + + Requested enctypes. + + +.. c:member:: krb5_address ** krb5_kdc_req.addresses + + Requested addresses (optional) + + +.. c:member:: krb5_enc_data krb5_kdc_req.authorization_data + + Encrypted authz data (optional) + + +.. c:member:: krb5_authdata ** krb5_kdc_req.unenc_authdata + + Unencrypted authz data. + + +.. c:member:: krb5_ticket ** krb5_kdc_req.second_ticket + + Second ticket array (optional) + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_key.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_key.rst.txt new file mode 100644 index 00000000..580d4107 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_key.rst.txt @@ -0,0 +1,21 @@ +.. highlight:: c + +.. _krb5-key-struct: + +krb5_key +======== + +.. +.. c:type:: krb5_key +.. + +Opaque identifier for a key. + +Use with the krb5_k APIs for better performance for repeated operations with the same key and usage. Key identifiers must not be used simultaneously within multiple threads, as they may contain mutable internal state and are not mutex-protected. + +Declaration +------------ + +typedef struct krb5_key_st\* krb5_key + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keyblock.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keyblock.rst.txt new file mode 100644 index 00000000..a6c08225 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keyblock.rst.txt @@ -0,0 +1,45 @@ +.. highlight:: c + +.. _krb5-keyblock-struct: + +krb5_keyblock +============= + +.. +.. c:type:: krb5_keyblock +.. + +Exposed contents of a key. + + + +Declaration +------------ + +typedef struct _krb5_keyblock krb5_keyblock + + +Members +--------- + + +.. c:member:: krb5_magic krb5_keyblock.magic + + + + +.. c:member:: krb5_enctype krb5_keyblock.enctype + + + + +.. c:member:: unsigned int krb5_keyblock.length + + + + +.. c:member:: krb5_octet * krb5_keyblock.contents + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keytab.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keytab.rst.txt new file mode 100644 index 00000000..879a92b4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keytab.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-keytab-struct: + +krb5_keytab +=========== + +.. +.. c:type:: krb5_keytab +.. + + + + +Declaration +------------ + +typedef struct _krb5_kt\* krb5_keytab + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keytab_entry.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keytab_entry.rst.txt new file mode 100644 index 00000000..a727744f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keytab_entry.rst.txt @@ -0,0 +1,50 @@ +.. highlight:: c + +.. _krb5-keytab-entry-struct: + +krb5_keytab_entry +================= + +.. +.. c:type:: krb5_keytab_entry +.. + +A key table entry. + + + +Declaration +------------ + +typedef struct krb5_keytab_entry_st krb5_keytab_entry + + +Members +--------- + + +.. c:member:: krb5_magic krb5_keytab_entry.magic + + + + +.. c:member:: krb5_principal krb5_keytab_entry.principal + + Principal of this key. + + +.. c:member:: krb5_timestamp krb5_keytab_entry.timestamp + + Time entry written to keytable. + + +.. c:member:: krb5_kvno krb5_keytab_entry.vno + + Key version number. + + +.. c:member:: krb5_keyblock krb5_keytab_entry.key + + The secret key. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keyusage.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keyusage.rst.txt new file mode 100644 index 00000000..6e2358f0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_keyusage.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-keyusage-struct: + +krb5_keyusage +============= + +.. +.. c:type:: krb5_keyusage +.. + + + + +Declaration +------------ + +typedef krb5_int32 krb5_keyusage + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kt_cursor.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kt_cursor.rst.txt new file mode 100644 index 00000000..0b374624 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kt_cursor.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-kt-cursor-struct: + +krb5_kt_cursor +============== + +.. +.. c:type:: krb5_kt_cursor +.. + + + + +Declaration +------------ + +typedef krb5_pointer krb5_kt_cursor + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kvno.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kvno.rst.txt new file mode 100644 index 00000000..ad766bb7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_kvno.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-kvno-struct: + +krb5_kvno +========= + +.. +.. c:type:: krb5_kvno +.. + + + + +Declaration +------------ + +typedef unsigned int krb5_kvno + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_last_req_entry.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_last_req_entry.rst.txt new file mode 100644 index 00000000..437472ed --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_last_req_entry.rst.txt @@ -0,0 +1,40 @@ +.. highlight:: c + +.. _krb5-last-req-entry-struct: + +krb5_last_req_entry +=================== + +.. +.. c:type:: krb5_last_req_entry +.. + +Last request entry. + + + +Declaration +------------ + +typedef struct _krb5_last_req_entry krb5_last_req_entry + + +Members +--------- + + +.. c:member:: krb5_magic krb5_last_req_entry.magic + + + + +.. c:member:: krb5_int32 krb5_last_req_entry.lr_type + + LR type. + + +.. c:member:: krb5_timestamp krb5_last_req_entry.value + + Timestamp. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_magic.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_magic.rst.txt new file mode 100644 index 00000000..7d3fc24c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_magic.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-magic-struct: + +krb5_magic +========== + +.. +.. c:type:: krb5_magic +.. + + + + +Declaration +------------ + +typedef krb5_error_code krb5_magic + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_mk_req_checksum_func.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_mk_req_checksum_func.rst.txt new file mode 100644 index 00000000..fa0dd01c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_mk_req_checksum_func.rst.txt @@ -0,0 +1,21 @@ +.. highlight:: c + +.. _krb5-mk-req-checksum-func-struct: + +krb5_mk_req_checksum_func +========================= + +.. +.. c:type:: krb5_mk_req_checksum_func +.. + +Type of function used as a callback to generate checksum data for mk_req. + + + +Declaration +------------ + +typedef krb5_error_code( \* krb5_mk_req_checksum_func) (krb5_context, krb5_auth_context, void \*, krb5_data \*\*) + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_msgtype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_msgtype.rst.txt new file mode 100644 index 00000000..b1e08cd5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_msgtype.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-msgtype-struct: + +krb5_msgtype +============ + +.. +.. c:type:: krb5_msgtype +.. + + + + +Declaration +------------ + +typedef unsigned int krb5_msgtype + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_octet.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_octet.rst.txt new file mode 100644 index 00000000..b6802e20 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_octet.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-octet-struct: + +krb5_octet +========== + +.. +.. c:type:: krb5_octet +.. + + + + +Declaration +------------ + +typedef uint8_t krb5_octet + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_data.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_data.rst.txt new file mode 100644 index 00000000..390f810f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_data.rst.txt @@ -0,0 +1,45 @@ +.. highlight:: c + +.. _krb5-pa-data-struct: + +krb5_pa_data +============ + +.. +.. c:type:: krb5_pa_data +.. + +Pre-authentication data. + + + +Declaration +------------ + +typedef struct _krb5_pa_data krb5_pa_data + + +Members +--------- + + +.. c:member:: krb5_magic krb5_pa_data.magic + + + + +.. c:member:: krb5_preauthtype krb5_pa_data.pa_type + + Preauthentication data type. + + +.. c:member:: unsigned int krb5_pa_data.length + + Length of data. + + +.. c:member:: krb5_octet * krb5_pa_data.contents + + Data. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_pac_req.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_pac_req.rst.txt new file mode 100644 index 00000000..de072e95 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_pac_req.rst.txt @@ -0,0 +1,29 @@ +.. highlight:: c + +.. _krb5-pa-pac-req-struct: + +krb5_pa_pac_req +=============== + +.. +.. c:type:: krb5_pa_pac_req +.. + + + + +Declaration +------------ + +typedef struct _krb5_pa_pac_req krb5_pa_pac_req + + +Members +--------- + + +.. c:member:: krb5_boolean krb5_pa_pac_req.include_pac + + TRUE if a PAC should be included in TGS-REP. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_server_referral_data.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_server_referral_data.rst.txt new file mode 100644 index 00000000..f9037d22 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_server_referral_data.rst.txt @@ -0,0 +1,49 @@ +.. highlight:: c + +.. _krb5-pa-server-referral-data-struct: + +krb5_pa_server_referral_data +============================ + +.. +.. c:type:: krb5_pa_server_referral_data +.. + + + + +Declaration +------------ + +typedef struct _krb5_pa_server_referral_data krb5_pa_server_referral_data + + +Members +--------- + + +.. c:member:: krb5_data * krb5_pa_server_referral_data.referred_realm + + + + +.. c:member:: krb5_principal krb5_pa_server_referral_data.true_principal_name + + + + +.. c:member:: krb5_principal krb5_pa_server_referral_data.requested_principal_name + + + + +.. c:member:: krb5_timestamp krb5_pa_server_referral_data.referral_valid_until + + + + +.. c:member:: krb5_checksum krb5_pa_server_referral_data.rep_cksum + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_svr_referral_data.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_svr_referral_data.rst.txt new file mode 100644 index 00000000..8ec298d5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pa_svr_referral_data.rst.txt @@ -0,0 +1,29 @@ +.. highlight:: c + +.. _krb5-pa-svr-referral-data-struct: + +krb5_pa_svr_referral_data +========================= + +.. +.. c:type:: krb5_pa_svr_referral_data +.. + + + + +Declaration +------------ + +typedef struct _krb5_pa_svr_referral_data krb5_pa_svr_referral_data + + +Members +--------- + + +.. c:member:: krb5_principal krb5_pa_svr_referral_data.principal + + Referred name, only realm is required. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pac.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pac.rst.txt new file mode 100644 index 00000000..603733c9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pac.rst.txt @@ -0,0 +1,21 @@ +.. highlight:: c + +.. _krb5-pac-struct: + +krb5_pac +======== + +.. +.. c:type:: krb5_pac +.. + +PAC data structure to convey authorization information. + + + +Declaration +------------ + +typedef struct krb5_pac_data\* krb5_pac + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pointer.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pointer.rst.txt new file mode 100644 index 00000000..e9a9ddd3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pointer.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-pointer-struct: + +krb5_pointer +============ + +.. +.. c:type:: krb5_pointer +.. + + + + +Declaration +------------ + +typedef void\* krb5_pointer + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_post_recv_fn.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_post_recv_fn.rst.txt new file mode 100644 index 00000000..54a64681 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_post_recv_fn.rst.txt @@ -0,0 +1,22 @@ +.. highlight:: c + +.. _krb5-post-recv-fn-struct: + +krb5_post_recv_fn +================= + +.. +.. c:type:: krb5_post_recv_fn +.. + +Hook function for inspecting or overriding KDC replies. + +If *code* is non-zero, KDC communication failed and *reply* should be ignored. The hook function may return *code* or a different error code, or may synthesize a reply by setting *new_reply_out* and return successfully. +The hook function should use krb5_copy_data() to construct the value for *new_reply_out* , to ensure that it can be freed correctly by the library. + +Declaration +------------ + +typedef krb5_error_code( \* krb5_post_recv_fn) (krb5_context context, void \*data, krb5_error_code code, const krb5_data \*realm, const krb5_data \*message, const krb5_data \*reply, krb5_data \*\*new_reply_out) + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pre_send_fn.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pre_send_fn.rst.txt new file mode 100644 index 00000000..76c3f9ab --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pre_send_fn.rst.txt @@ -0,0 +1,24 @@ +.. highlight:: c + +.. _krb5-pre-send-fn-struct: + +krb5_pre_send_fn +================ + +.. +.. c:type:: krb5_pre_send_fn +.. + +Hook function for inspecting or modifying messages sent to KDCs. + +If the hook function sets *new_reply_out* , *message* will not be sent to the KDC, and the given reply will used instead. +If the hook function sets *new_message_out* , the given message will be sent to the KDC in place of *message* . +If the hook function returns successfully without setting either output, *message* will be sent to the KDC normally. +The hook function should use krb5_copy_data() to construct the value for *new_message_out* or *reply_out* , to ensure that it can be freed correctly by the library. + +Declaration +------------ + +typedef krb5_error_code( \* krb5_pre_send_fn) (krb5_context context, void \*data, const krb5_data \*realm, const krb5_data \*message, krb5_data \*\*new_message_out, krb5_data \*\*new_reply_out) + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_preauthtype.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_preauthtype.rst.txt new file mode 100644 index 00000000..7cd85875 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_preauthtype.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-preauthtype-struct: + +krb5_preauthtype +================ + +.. +.. c:type:: krb5_preauthtype +.. + + + + +Declaration +------------ + +typedef krb5_int32 krb5_preauthtype + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_principal.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_principal.rst.txt new file mode 100644 index 00000000..818b66f1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_principal.rst.txt @@ -0,0 +1,49 @@ +.. highlight:: c + +.. _krb5-principal-struct: + +krb5_principal +============== + +.. +.. c:type:: krb5_principal +.. + + + + +Declaration +------------ + +typedef krb5_principal_data\* krb5_principal + + +Members +--------- + + +.. c:member:: krb5_magic krb5_principal.magic + + + + +.. c:member:: krb5_data krb5_principal.realm + + + + +.. c:member:: krb5_data * krb5_principal.data + + An array of strings. + + +.. c:member:: krb5_int32 krb5_principal.length + + + + +.. c:member:: krb5_int32 krb5_principal.type + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_principal_data.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_principal_data.rst.txt new file mode 100644 index 00000000..f58c45b7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_principal_data.rst.txt @@ -0,0 +1,49 @@ +.. highlight:: c + +.. _krb5-principal-data-struct: + +krb5_principal_data +=================== + +.. +.. c:type:: krb5_principal_data +.. + + + + +Declaration +------------ + +typedef struct krb5_principal_data krb5_principal_data + + +Members +--------- + + +.. c:member:: krb5_magic krb5_principal_data.magic + + + + +.. c:member:: krb5_data krb5_principal_data.realm + + + + +.. c:member:: krb5_data * krb5_principal_data.data + + An array of strings. + + +.. c:member:: krb5_int32 krb5_principal_data.length + + + + +.. c:member:: krb5_int32 krb5_principal_data.type + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_prompt.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_prompt.rst.txt new file mode 100644 index 00000000..f31ac703 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_prompt.rst.txt @@ -0,0 +1,40 @@ +.. highlight:: c + +.. _krb5-prompt-struct: + +krb5_prompt +=========== + +.. +.. c:type:: krb5_prompt +.. + +Text for prompt used in prompter callback function. + + + +Declaration +------------ + +typedef struct _krb5_prompt krb5_prompt + + +Members +--------- + + +.. c:member:: char * krb5_prompt.prompt + + The prompt to show to the user. + + +.. c:member:: int krb5_prompt.hidden + + Boolean; informative prompt or hidden (e.g. + PIN) + +.. c:member:: krb5_data * krb5_prompt.reply + + Must be allocated before call to prompt routine. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_prompt_type.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_prompt_type.rst.txt new file mode 100644 index 00000000..e36044c4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_prompt_type.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-prompt-type-struct: + +krb5_prompt_type +================ + +.. +.. c:type:: krb5_prompt_type +.. + + + + +Declaration +------------ + +typedef krb5_int32 krb5_prompt_type + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_prompter_fct.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_prompter_fct.rst.txt new file mode 100644 index 00000000..99cdc95e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_prompter_fct.rst.txt @@ -0,0 +1,21 @@ +.. highlight:: c + +.. _krb5-prompter-fct-struct: + +krb5_prompter_fct +================= + +.. +.. c:type:: krb5_prompter_fct +.. + +Pointer to a prompter callback function. + + + +Declaration +------------ + +typedef krb5_error_code( \* krb5_prompter_fct) (krb5_context context, void \*data, const char \*name, const char \*banner, int num_prompts, krb5_prompt prompts[]) + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pwd_data.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pwd_data.rst.txt new file mode 100644 index 00000000..5797d23f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_pwd_data.rst.txt @@ -0,0 +1,39 @@ +.. highlight:: c + +.. _krb5-pwd-data-struct: + +krb5_pwd_data +============= + +.. +.. c:type:: krb5_pwd_data +.. + + + + +Declaration +------------ + +typedef struct _krb5_pwd_data krb5_pwd_data + + +Members +--------- + + +.. c:member:: krb5_magic krb5_pwd_data.magic + + + + +.. c:member:: int krb5_pwd_data.sequence_count + + + + +.. c:member:: passwd_phrase_element ** krb5_pwd_data.element + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_rcache.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_rcache.rst.txt new file mode 100644 index 00000000..8d08c3a4 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_rcache.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-rcache-struct: + +krb5_rcache +=========== + +.. +.. c:type:: krb5_rcache +.. + + + + +Declaration +------------ + +typedef struct krb5_rc_st\* krb5_rcache + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_replay_data.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_replay_data.rst.txt new file mode 100644 index 00000000..afd88127 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_replay_data.rst.txt @@ -0,0 +1,40 @@ +.. highlight:: c + +.. _krb5-replay-data-struct: + +krb5_replay_data +================ + +.. +.. c:type:: krb5_replay_data +.. + +Replay data. + +Sequence number and timestamp information output by krb5_rd_priv() and krb5_rd_safe(). + +Declaration +------------ + +typedef struct krb5_replay_data krb5_replay_data + + +Members +--------- + + +.. c:member:: krb5_timestamp krb5_replay_data.timestamp + + Timestamp, seconds portion. + + +.. c:member:: krb5_int32 krb5_replay_data.usec + + Timestamp, microseconds portion. + + +.. c:member:: krb5_ui_4 krb5_replay_data.seq + + Sequence number. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_context.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_context.rst.txt new file mode 100644 index 00000000..be5ccc42 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_context.rst.txt @@ -0,0 +1,22 @@ +.. highlight:: c + +.. _krb5-responder-context-struct: + +krb5_responder_context +====================== + +.. +.. c:type:: krb5_responder_context +.. + +A container for a set of preauthentication questions and answers. + +A responder context is supplied by the krb5 authentication system to a krb5_responder_fn callback. It contains a list of questions and can receive answers. Questions contained in a responder context can be listed using krb5_responder_list_questions(), retrieved using krb5_responder_get_challenge(), or answered using krb5_responder_set_answer(). The form of a question's challenge and answer depend on the question name. + + +Declaration +------------ + +typedef struct krb5_responder_context_st\* krb5_responder_context + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_fn.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_fn.rst.txt new file mode 100644 index 00000000..a66fa6c0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_fn.rst.txt @@ -0,0 +1,21 @@ +.. highlight:: c + +.. _krb5-responder-fn-struct: + +krb5_responder_fn +================= + +.. +.. c:type:: krb5_responder_fn +.. + +Responder function for an initial credential exchange. + +If a required question is unanswered, the prompter may be called. + +Declaration +------------ + +typedef krb5_error_code( \* krb5_responder_fn) (krb5_context ctx, void \*data, krb5_responder_context rctx) + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_otp_challenge.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_otp_challenge.rst.txt new file mode 100644 index 00000000..9001a574 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_otp_challenge.rst.txt @@ -0,0 +1,34 @@ +.. highlight:: c + +.. _krb5-responder-otp-challenge-struct: + +krb5_responder_otp_challenge +============================ + +.. +.. c:type:: krb5_responder_otp_challenge +.. + + + + +Declaration +------------ + +typedef struct _krb5_responder_otp_challenge krb5_responder_otp_challenge + + +Members +--------- + + +.. c:member:: char * krb5_responder_otp_challenge.service + + + + +.. c:member:: krb5_responder_otp_tokeninfo ** krb5_responder_otp_challenge.tokeninfo + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_otp_tokeninfo.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_otp_tokeninfo.rst.txt new file mode 100644 index 00000000..18c53c88 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_otp_tokeninfo.rst.txt @@ -0,0 +1,59 @@ +.. highlight:: c + +.. _krb5-responder-otp-tokeninfo-struct: + +krb5_responder_otp_tokeninfo +============================ + +.. +.. c:type:: krb5_responder_otp_tokeninfo +.. + + + + +Declaration +------------ + +typedef struct _krb5_responder_otp_tokeninfo krb5_responder_otp_tokeninfo + + +Members +--------- + + +.. c:member:: krb5_flags krb5_responder_otp_tokeninfo.flags + + + + +.. c:member:: krb5_int32 krb5_responder_otp_tokeninfo.format + + + + +.. c:member:: krb5_int32 krb5_responder_otp_tokeninfo.length + + + + +.. c:member:: char * krb5_responder_otp_tokeninfo.vendor + + + + +.. c:member:: char * krb5_responder_otp_tokeninfo.challenge + + + + +.. c:member:: char * krb5_responder_otp_tokeninfo.token_id + + + + +.. c:member:: char * krb5_responder_otp_tokeninfo.alg_id + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_pkinit_challenge.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_pkinit_challenge.rst.txt new file mode 100644 index 00000000..7e35621d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_pkinit_challenge.rst.txt @@ -0,0 +1,29 @@ +.. highlight:: c + +.. _krb5-responder-pkinit-challenge-struct: + +krb5_responder_pkinit_challenge +=============================== + +.. +.. c:type:: krb5_responder_pkinit_challenge +.. + + + + +Declaration +------------ + +typedef struct _krb5_responder_pkinit_challenge krb5_responder_pkinit_challenge + + +Members +--------- + + +.. c:member:: krb5_responder_pkinit_identity ** krb5_responder_pkinit_challenge.identities + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_pkinit_identity.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_pkinit_identity.rst.txt new file mode 100644 index 00000000..9535693b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_responder_pkinit_identity.rst.txt @@ -0,0 +1,34 @@ +.. highlight:: c + +.. _krb5-responder-pkinit-identity-struct: + +krb5_responder_pkinit_identity +============================== + +.. +.. c:type:: krb5_responder_pkinit_identity +.. + + + + +Declaration +------------ + +typedef struct _krb5_responder_pkinit_identity krb5_responder_pkinit_identity + + +Members +--------- + + +.. c:member:: char * krb5_responder_pkinit_identity.identity + + + + +.. c:member:: krb5_int32 krb5_responder_pkinit_identity.token_flags + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_response.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_response.rst.txt new file mode 100644 index 00000000..1e31caa6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_response.rst.txt @@ -0,0 +1,49 @@ +.. highlight:: c + +.. _krb5-response-struct: + +krb5_response +============= + +.. +.. c:type:: krb5_response +.. + + + + +Declaration +------------ + +typedef struct _krb5_response krb5_response + + +Members +--------- + + +.. c:member:: krb5_magic krb5_response.magic + + + + +.. c:member:: krb5_octet krb5_response.message_type + + + + +.. c:member:: krb5_data krb5_response.response + + + + +.. c:member:: krb5_int32 krb5_response.expected_nonce + + + + +.. c:member:: krb5_timestamp krb5_response.request_time + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ticket.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ticket.rst.txt new file mode 100644 index 00000000..b1f9e6ad --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ticket.rst.txt @@ -0,0 +1,45 @@ +.. highlight:: c + +.. _krb5-ticket-struct: + +krb5_ticket +=========== + +.. +.. c:type:: krb5_ticket +.. + +Ticket structure. + +The C representation of the ticket message, with a pointer to the C representation of the encrypted part. + +Declaration +------------ + +typedef struct _krb5_ticket krb5_ticket + + +Members +--------- + + +.. c:member:: krb5_magic krb5_ticket.magic + + + + +.. c:member:: krb5_principal krb5_ticket.server + + server name/realm + + +.. c:member:: krb5_enc_data krb5_ticket.enc_part + + encryption type, kvno, encrypted encoding + + +.. c:member:: krb5_enc_tkt_part * krb5_ticket.enc_part2 + + ptr to decrypted version, if available + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ticket_times.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ticket_times.rst.txt new file mode 100644 index 00000000..60f7fd53 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ticket_times.rst.txt @@ -0,0 +1,45 @@ +.. highlight:: c + +.. _krb5-ticket-times-struct: + +krb5_ticket_times +================= + +.. +.. c:type:: krb5_ticket_times +.. + +Ticket start time, end time, and renewal duration. + + + +Declaration +------------ + +typedef struct _krb5_ticket_times krb5_ticket_times + + +Members +--------- + + +.. c:member:: krb5_timestamp krb5_ticket_times.authtime + + Time at which KDC issued the initial ticket that corresponds to this ticket. + + +.. c:member:: krb5_timestamp krb5_ticket_times.starttime + + optional in ticket, if not present, use *authtime* + + +.. c:member:: krb5_timestamp krb5_ticket_times.endtime + + Ticket expiration time. + + +.. c:member:: krb5_timestamp krb5_ticket_times.renew_till + + Latest time at which renewal of ticket can be valid. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_timestamp.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_timestamp.rst.txt new file mode 100644 index 00000000..4a13d685 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_timestamp.rst.txt @@ -0,0 +1,21 @@ +.. highlight:: c + +.. _krb5-timestamp-struct: + +krb5_timestamp +============== + +.. +.. c:type:: krb5_timestamp +.. + +Represents a timestamp in seconds since the POSIX epoch. + +This legacy type is used frequently in the ABI, but cannot represent timestamps after 2038 as a positive number. Code which uses this type should cast values of it to uint32_t so that negative values are treated as timestamps between 2038 and 2106 on platforms with 64-bit time_t. + +Declaration +------------ + +typedef krb5_int32 krb5_timestamp + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_tkt_authent.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_tkt_authent.rst.txt new file mode 100644 index 00000000..bbc53e77 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_tkt_authent.rst.txt @@ -0,0 +1,45 @@ +.. highlight:: c + +.. _krb5-tkt-authent-struct: + +krb5_tkt_authent +================ + +.. +.. c:type:: krb5_tkt_authent +.. + +Ticket authentication data. + + + +Declaration +------------ + +typedef struct _krb5_tkt_authent krb5_tkt_authent + + +Members +--------- + + +.. c:member:: krb5_magic krb5_tkt_authent.magic + + + + +.. c:member:: krb5_ticket * krb5_tkt_authent.ticket + + + + +.. c:member:: krb5_authenticator * krb5_tkt_authent.authenticator + + + + +.. c:member:: krb5_flags krb5_tkt_authent.ap_options + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_tkt_creds_context.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_tkt_creds_context.rst.txt new file mode 100644 index 00000000..95c9625f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_tkt_creds_context.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-tkt-creds-context-struct: + +krb5_tkt_creds_context +====================== + +.. +.. c:type:: krb5_tkt_creds_context +.. + + + + +Declaration +------------ + +typedef struct _krb5_tkt_creds_context\* krb5_tkt_creds_context + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_trace_callback.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_trace_callback.rst.txt new file mode 100644 index 00000000..f201ec18 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_trace_callback.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-trace-callback-struct: + +krb5_trace_callback +=================== + +.. +.. c:type:: krb5_trace_callback +.. + + + + +Declaration +------------ + +typedef void( \* krb5_trace_callback) (krb5_context context, const krb5_trace_info \*info, void \*cb_data) + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_trace_info.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_trace_info.rst.txt new file mode 100644 index 00000000..0a90a4ef --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_trace_info.rst.txt @@ -0,0 +1,30 @@ +.. highlight:: c + +.. _krb5-trace-info-struct: + +krb5_trace_info +=============== + +.. +.. c:type:: krb5_trace_info +.. + +A wrapper for passing information to a *krb5_trace_callback* . + +Currently, it only contains the formatted message as determined the the format string and arguments of the tracing macro, but it may be extended to contain more fields in the future. + +Declaration +------------ + +typedef struct _krb5_trace_info krb5_trace_info + + +Members +--------- + + +.. c:member:: const char * krb5_trace_info.message + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_transited.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_transited.rst.txt new file mode 100644 index 00000000..2c3751ab --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_transited.rst.txt @@ -0,0 +1,40 @@ +.. highlight:: c + +.. _krb5-transited-struct: + +krb5_transited +============== + +.. +.. c:type:: krb5_transited +.. + +Structure for transited encoding. + + + +Declaration +------------ + +typedef struct _krb5_transited krb5_transited + + +Members +--------- + + +.. c:member:: krb5_magic krb5_transited.magic + + + + +.. c:member:: krb5_octet krb5_transited.tr_type + + Transited encoding type. + + +.. c:member:: krb5_data krb5_transited.tr_contents + + Contents. + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_typed_data.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_typed_data.rst.txt new file mode 100644 index 00000000..0894be9c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_typed_data.rst.txt @@ -0,0 +1,44 @@ +.. highlight:: c + +.. _krb5-typed-data-struct: + +krb5_typed_data +=============== + +.. +.. c:type:: krb5_typed_data +.. + + + + +Declaration +------------ + +typedef struct _krb5_typed_data krb5_typed_data + + +Members +--------- + + +.. c:member:: krb5_magic krb5_typed_data.magic + + + + +.. c:member:: krb5_int32 krb5_typed_data.type + + + + +.. c:member:: unsigned int krb5_typed_data.length + + + + +.. c:member:: krb5_octet * krb5_typed_data.data + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ui_2.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ui_2.rst.txt new file mode 100644 index 00000000..ed07896f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ui_2.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-ui-2-struct: + +krb5_ui_2 +========= + +.. +.. c:type:: krb5_ui_2 +.. + + + + +Declaration +------------ + +typedef uint16_t krb5_ui_2 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ui_4.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ui_4.rst.txt new file mode 100644 index 00000000..4e754133 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_ui_4.rst.txt @@ -0,0 +1,20 @@ +.. highlight:: c + +.. _krb5-ui-4-struct: + +krb5_ui_4 +========= + +.. +.. c:type:: krb5_ui_4 +.. + + + + +Declaration +------------ + +typedef uint32_t krb5_ui_4 + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_verify_init_creds_opt.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_verify_init_creds_opt.rst.txt new file mode 100644 index 00000000..c46fd9d3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/krb5_verify_init_creds_opt.rst.txt @@ -0,0 +1,34 @@ +.. highlight:: c + +.. _krb5-verify-init-creds-opt-struct: + +krb5_verify_init_creds_opt +========================== + +.. +.. c:type:: krb5_verify_init_creds_opt +.. + + + + +Declaration +------------ + +typedef struct _krb5_verify_init_creds_opt krb5_verify_init_creds_opt + + +Members +--------- + + +.. c:member:: krb5_flags krb5_verify_init_creds_opt.flags + + + + +.. c:member:: int krb5_verify_init_creds_opt.ap_req_nofail + + boolean + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/refs/types/passwd_phrase_element.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/passwd_phrase_element.rst.txt new file mode 100644 index 00000000..41532ee1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/refs/types/passwd_phrase_element.rst.txt @@ -0,0 +1,39 @@ +.. highlight:: c + +.. _passwd-phrase-element-struct: + +passwd_phrase_element +===================== + +.. +.. c:type:: passwd_phrase_element +.. + + + + +Declaration +------------ + +typedef struct _passwd_phrase_element passwd_phrase_element + + +Members +--------- + + +.. c:member:: krb5_magic passwd_phrase_element.magic + + + + +.. c:member:: krb5_data * passwd_phrase_element.passwd + + + + +.. c:member:: krb5_data * passwd_phrase_element.phrase + + + + diff --git a/krb5-1.21.3/doc/html/_sources/appdev/y2038.rst.txt b/krb5-1.21.3/doc/html/_sources/appdev/y2038.rst.txt new file mode 100644 index 00000000..bc4122da --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/appdev/y2038.rst.txt @@ -0,0 +1,28 @@ +Year 2038 considerations for uses of krb5_timestamp +=================================================== + +POSIX time values, which measure the number of seconds since January 1 +1970, will exceed the maximum value representable in a signed 32-bit +integer in January 2038. This documentation describes considerations +for consumers of the MIT krb5 libraries. + +Applications or libraries which use libkrb5 and consume the timestamps +included in credentials or other structures make use of the +:c:type:`krb5_timestamp` type. For historical reasons, krb5_timestamp +is a signed 32-bit integer, even on platforms where a larger type is +natively used to represent time values. To behave properly for time +values after January 2038, calling code should cast krb5_timestamp +values to uint32_t, and then to time_t:: + + (time_t)(uint32_t)timestamp + +Used in this way, krb5_timestamp values can represent time values up +until February 2106, provided that the platform uses a 64-bit or +larger time_t type. This usage will also remain safe if a later +version of MIT krb5 changes krb5_timestamp to an unsigned 32-bit +integer. + +The GSSAPI only uses representations of time intervals, not absolute +times. Callers of the GSSAPI should require no changes to behave +correctly after January 2038, provided that they use MIT krb5 release +1.16 or later. diff --git a/krb5-1.21.3/doc/html/_sources/basic/ccache_def.rst.txt b/krb5-1.21.3/doc/html/_sources/basic/ccache_def.rst.txt new file mode 100644 index 00000000..53542add --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/basic/ccache_def.rst.txt @@ -0,0 +1,160 @@ +.. _ccache_definition: + +Credential cache +================ + +A credential cache (or "ccache") holds Kerberos credentials while they +remain valid and, generally, while the user's session lasts, so that +authenticating to a service multiple times (e.g., connecting to a web +or mail server more than once) doesn't require contacting the KDC +every time. + +A credential cache usually contains one initial ticket which is +obtained using a password or another form of identity verification. +If this ticket is a ticket-granting ticket, it can be used to obtain +additional credentials without the password. Because the credential +cache does not store the password, less long-term damage can be done +to the user's account if the machine is compromised. + +A credentials cache stores a default client principal name, set when +the cache is created. This is the name shown at the top of the +:ref:`klist(1)` *-A* output. + +Each normal cache entry includes a service principal name, a client +principal name (which, in some ccache types, need not be the same as +the default), lifetime information, and flags, along with the +credential itself. There are also other entries, indicated by special +names, that store additional information. + + +ccache types +------------ + +The credential cache interface, like the :ref:`keytab_definition` and +:ref:`rcache_definition` interfaces, uses `TYPE:value` strings to +indicate the type of credential cache and any associated cache naming +data to use. + +There are several kinds of credentials cache supported in the MIT +Kerberos library. Not all are supported on every platform. In most +cases, it should be correct to use the default type built into the +library. + +#. **API** is only implemented on Windows. It communicates with a + server process that holds the credentials in memory for the user, + rather than writing them to disk. + +#. **DIR** points to the storage location of the collection of the + credential caches in *FILE:* format. It is most useful when dealing + with multiple Kerberos realms and KDCs. For release 1.10 the + directory must already exist. In post-1.10 releases the + requirement is for parent directory to exist and the current + process must have permissions to create the directory if it does + not exist. See :ref:`col_ccache` for details. New in release 1.10. + The following residual forms are supported: + + * DIR:dirname + * DIR::dirpath/filename - a single cache within the directory + + Switching to a ccache of the latter type causes it to become the + primary for the directory. + +#. **FILE** caches are the simplest and most portable. A simple flat + file format is used to store one credential after another. This is + the default ccache type if no type is specified in a ccache name. + +#. **KCM** caches work by contacting a daemon process called ``kcm`` + to perform cache operations. If the cache name is just ``KCM:``, + the default cache as determined by the KCM daemon will be used. + Newly created caches must generally be named ``KCM:uid:name``, + where *uid* is the effective user ID of the running process. + + KCM client support is new in release 1.13. A KCM daemon has not + yet been implemented in MIT krb5, but the client will interoperate + with the KCM daemon implemented by Heimdal. macOS 10.7 and higher + provides a KCM daemon as part of the operating system, and the + **KCM** cache type is used as the default cache on that platform in + a default build. + +#. **KEYRING** is Linux-specific, and uses the kernel keyring support + to store credential data in unswappable kernel memory where only + the current user should be able to access it. The following + residual forms are supported: + + * KEYRING:name + * KEYRING:process:name - process keyring + * KEYRING:thread:name - thread keyring + + Starting with release 1.12 the *KEYRING* type supports collections. + The following new residual forms were added: + + * KEYRING:session:name - session keyring + * KEYRING:user:name - user keyring + * KEYRING:persistent:uidnumber - persistent per-UID collection. + Unlike the user keyring, this collection survives after the user + logs out, until the cache credentials expire. This type of + ccache requires support from the kernel; otherwise, it will fall + back to the user keyring. + + See :ref:`col_ccache` for details. + +#. **MEMORY** caches are for storage of credentials that don't need to + be made available outside of the current process. For example, a + memory ccache is used by :ref:`kadmin(1)` to store the + administrative ticket used to contact the admin server. Memory + ccaches are faster than file ccaches and are automatically + destroyed when the process exits. + +#. **MSLSA** is a Windows-specific cache type that accesses the + Windows credential store. + + +.. _col_ccache: + +Collections of caches +--------------------- + +Some credential cache types can support collections of multiple +caches. One of the caches in the collection is designated as the +*primary* and will be used when the collection is resolved as a cache. +When a collection-enabled cache type is the default cache for a +process, applications can search the specified collection for a +specific client principal, and GSSAPI applications will automatically +select between the caches in the collection based on criteria such as +the target service realm. + +Credential cache collections are new in release 1.10, with support +from the **DIR** and **API** ccache types. Starting in release 1.12, +collections are also supported by the **KEYRING** ccache type. +Collections are supported by the **KCM** ccache type in release 1.13. + + +Tool alterations to use cache collection +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* :ref:`kdestroy(1)` *-A* will destroy all caches in the collection. +* If the default cache type supports switching, :ref:`kinit(1)` + *princname* will search the collection for a matching cache and + store credentials there, or will store credentials in a new unique + cache of the default type if no existing cache for the principal + exists. Either way, kinit will switch to the selected cache. +* :ref:`klist(1)` *-l* will list the caches in the collection. +* :ref:`klist(1)` *-A* will show the content of all caches in the + collection. +* :ref:`kswitch(1)` *-p princname* will search the collection for a + matching cache and switch to it. +* :ref:`kswitch(1)` *-c cachename* will switch to a specified cache. + + +Default ccache name +------------------- + +The default credential cache name is determined by the following, in +descending order of priority: + +#. The **KRB5CCNAME** environment variable. For example, + ``KRB5CCNAME=DIR:/mydir/``. + +#. The **default_ccache_name** profile variable in :ref:`libdefaults`. + +#. The hardcoded default, |ccache|. diff --git a/krb5-1.21.3/doc/html/_sources/basic/date_format.rst.txt b/krb5-1.21.3/doc/html/_sources/basic/date_format.rst.txt new file mode 100644 index 00000000..6ee82ce6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/basic/date_format.rst.txt @@ -0,0 +1,140 @@ +.. _datetime: + +Supported date and time formats +=============================== + +.. _duration: + +Time duration +------------- + +This format is used to express a time duration in the Kerberos +configuration files and user commands. The allowed formats are: + + ====================== ============== ============ + Format Example Value + ---------------------- -------------- ------------ + h:m[:s] 36:00 36 hours + NdNhNmNs 8h30s 8 hours 30 seconds + N (number of seconds) 3600 1 hour + ====================== ============== ============ + +Here *N* denotes a number, *d* - days, *h* - hours, *m* - minutes, +*s* - seconds. + +.. note:: + + The time interval should not exceed 2147483647 seconds. + +Examples:: + + Request a ticket valid for one hour, five hours, 30 minutes + and 10 days respectively: + + kinit -l 3600 + kinit -l 5:00 + kinit -l 30m + kinit -l "10d 0h 0m 0s" + + +.. _getdate: + +getdate time +------------ + +Some of the kadmin and kdb5_util commands take a date-time in a +human-readable format. Some of the acceptable date-time +strings are: + + +-----------+------------------+-----------------+ + | | Format | Example | + +===========+==================+=================+ + | Date | mm/dd/yy | 07/27/12 | + | +------------------+-----------------+ + | | month dd, yyyy | Jul 27, 2012 | + | +------------------+-----------------+ + | | yyyy-mm-dd | 2012-07-27 | + +-----------+------------------+-----------------+ + | Absolute | HH:mm[:ss]pp | 08:30 PM | + | time +------------------+-----------------+ + | | hh:mm[:ss] | 20:30 | + +-----------+------------------+-----------------+ + | Relative | N tt | 30 sec | + | time | | | + +-----------+------------------+-----------------+ + | Time zone | Z | EST | + | +------------------+-----------------+ + | | z | -0400 | + +-----------+------------------+-----------------+ + +(See :ref:`abbreviation`.) + +Examples:: + + Create a principal that expires on the date indicated: + addprinc test1 -expire "3/27/12 10:00:07 EST" + addprinc test2 -expire "January 23, 2015 10:05pm" + addprinc test3 -expire "22:00 GMT" + Add a principal that will expire in 30 minutes: + addprinc test4 -expire "30 minutes" + + +.. _abstime: + +Absolute time +------------- + +This rarely used date-time format can be noted in one of the +following ways: + + + +------------------------+----------------------+--------------+ + | Format | Example | Value | + +========================+======================+==============+ + | yyyymmddhhmmss | 20141231235900 | One minute | + +------------------------+----------------------+ before 2015 | + | yyyy.mm.dd.hh.mm.ss | 2014.12.31.23.59.00 | | + +------------------------+----------------------+ | + | yymmddhhmmss | 141231235900 | | + +------------------------+----------------------+ | + | yy.mm.dd.hh.mm.ss | 14.12.31.23.59.00 | | + +------------------------+----------------------+ | + | dd-month-yyyy:hh:mm:ss | 31-Dec-2014:23:59:00 | | + +------------------------+----------------------+--------------+ + | hh:mm:ss | 20:00:00 | 8 o'clock in | + +------------------------+----------------------+ the evening | + | hhmmss | 200000 | | + +------------------------+----------------------+--------------+ + +(See :ref:`abbreviation`.) + +Example:: + + Set the default expiration date to July 27, 2012 at 20:30 + default_principal_expiration = 20120727203000 + + +.. _abbreviation: + +Abbreviations used in this document +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +| *month* : locale’s month name or its abbreviation; +| *dd* : day of month (01-31); +| *HH* : hours (00-12); +| *hh* : hours (00-23); +| *mm* : in time - minutes (00-59); in date - month (01-12); +| *N* : number; +| *pp* : AM or PM; +| *ss* : seconds (00-60); +| *tt* : time units (hours, minutes, min, seconds, sec); +| *yyyy* : year; +| *yy* : last two digits of the year; +| *Z* : alphabetic time zone abbreviation; +| *z* : numeric time zone; + +.. note:: + + - If the date specification contains spaces, you may need to + enclose it in double quotes; + - All keywords are case-insensitive. diff --git a/krb5-1.21.3/doc/html/_sources/basic/index.rst.txt b/krb5-1.21.3/doc/html/_sources/basic/index.rst.txt new file mode 100644 index 00000000..87a9b547 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/basic/index.rst.txt @@ -0,0 +1,14 @@ +.. _basic_concepts: + +Kerberos V5 concepts +==================== + + +.. toctree:: + :maxdepth: 1 + + ccache_def + keytab_def + rcache_def + stash_file_def + date_format diff --git a/krb5-1.21.3/doc/html/_sources/basic/keytab_def.rst.txt b/krb5-1.21.3/doc/html/_sources/basic/keytab_def.rst.txt new file mode 100644 index 00000000..6c7fcc3b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/basic/keytab_def.rst.txt @@ -0,0 +1,59 @@ +.. _keytab_definition: + +keytab +====== + +A keytab (short for "key table") stores long-term keys for one or more +principals. Keytabs are normally represented by files in a standard +format, although in rare cases they can be represented in other ways. +Keytabs are used most often to allow server applications to accept +authentications from clients, but can also be used to obtain initial +credentials for client applications. + +Keytabs are named using the format *type*\ ``:``\ *value*. Usually +*type* is ``FILE`` and *value* is the absolute pathname of the file. +The other possible value for *type* is ``MEMORY``, which indicates a +temporary keytab stored in the memory of the current process. + +A keytab contains one or more entries, where each entry consists of a +timestamp (indicating when the entry was written to the keytab), a +principal name, a key version number, an encryption type, and the +encryption key itself. + +A keytab can be displayed using the :ref:`klist(1)` command with the +``-k`` option. Keytabs can be created or appended to by extracting +keys from the KDC database using the :ref:`kadmin(1)` :ref:`ktadd` +command. Keytabs can be manipulated using the :ref:`ktutil(1)` and +:ref:`k5srvutil(1)` commands. + + +Default keytab +-------------- + +The default keytab is used by server applications if the application +does not request a specific keytab. The name of the default keytab is +determined by the following, in decreasing order of preference: + +#. The **KRB5_KTNAME** environment variable. + +#. The **default_keytab_name** profile variable in :ref:`libdefaults`. + +#. The hardcoded default, |keytab|. + + +Default client keytab +--------------------- + +The default client keytab is used, if it is present and readable, to +automatically obtain initial credentials for GSSAPI client +applications. The principal name of the first entry in the client +keytab is used by default when obtaining initial credentials. The +name of the default client keytab is determined by the following, in +decreasing order of preference: + +#. The **KRB5_CLIENT_KTNAME** environment variable. + +#. The **default_client_keytab_name** profile variable in + :ref:`libdefaults`. + +#. The hardcoded default, |ckeytab|. diff --git a/krb5-1.21.3/doc/html/_sources/basic/rcache_def.rst.txt b/krb5-1.21.3/doc/html/_sources/basic/rcache_def.rst.txt new file mode 100644 index 00000000..a80cf5af --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/basic/rcache_def.rst.txt @@ -0,0 +1,111 @@ +.. _rcache_definition: + +replay cache +============ + +A replay cache (or "rcache") keeps track of all authenticators +recently presented to a service. If a duplicate authentication +request is detected in the replay cache, an error message is sent to +the application program. + +The replay cache interface, like the credential cache and +:ref:`keytab_definition` interfaces, uses `type:residual` strings to +indicate the type of replay cache and any associated cache naming +data to use. + +Background information +---------------------- + +Some Kerberos or GSSAPI services use a simple authentication mechanism +where a message is sent containing an authenticator, which establishes +the encryption key that the client will use for talking to the +service. But nothing about that prevents an eavesdropper from +recording the messages sent by the client, establishing a new +connection, and re-sending or "replaying" the same messages; the +replayed authenticator will establish the same encryption key for the +new session, and the following messages will be decrypted and +processed. The attacker may not know what the messages say, and can't +generate new messages under the same encryption key, but in some +instances it may be harmful to the user (or helpful to the attacker) +to cause the server to see the same messages again a second time. For +example, if the legitimate client sends "delete first message in +mailbox", a replay from an attacker may delete another, different +"first" message. (Protocol design to guard against such problems has +been discussed in :rfc:`4120#section-10`.) + +Even if one protocol uses further protection to verify that the client +side of the connection actually knows the encryption keys (and thus is +presumably a legitimate user), if another service uses the same +service principal name, it may be possible to record an authenticator +used with the first protocol and "replay" it against the second. + +The replay cache mitigates these attacks somewhat, by keeping track of +authenticators that have been seen until their five-minute window +expires. Different authenticators generated by multiple connections +from the same legitimate client will generally have different +timestamps, and thus will not be considered the same. + +This mechanism isn't perfect. If a message is sent to one application +server but a man-in-the-middle attacker can prevent it from actually +arriving at that server, the attacker could then use the authenticator +(once!) against a different service on the same host. This could be a +problem if the message from the client included something more than +authentication in the first message that could be useful to the +attacker (which is uncommon; in most protocols the server has to +indicate a successful authentication before the client sends +additional messages), or if the simple act of presenting the +authenticator triggers some interesting action in the service being +attacked. + +Replay cache types +------------------ + +Unlike the credential cache and keytab interfaces, replay cache types +are in lowercase. The following types are defined: + +#. **none** disables the replay cache. The residual value is ignored. + +#. **file2** (new in release 1.18) uses a hash-based format to store + replay records. The file may grow to accommodate hash collisions. + The residual value is the filename. + +#. **dfl** is the default type if no environment variable or + configuration specifies a different type. It stores replay data in + a file2 replay cache with a filename based on the effective uid. + The residual value is ignored. + +For the dfl type, the location of the replay cache file is determined +as follows: + +#. The directory is taken from the **KRB5RCACHEDIR** environment + variable, or the **TMPDIR** environment variable, or a temporary + directory determined at configuration time such as ``/var/tmp``, in + descending order of preference. + +#. The filename is ``krb5_EUID.rcache2`` where EUID is the effective + uid of the process. + +#. The file is opened without following symbolic links, and ownership + of the file is verified to match the effective uid. + +On Windows, the directory for the dfl type is the local appdata +directory, unless overridden by the **KRB5RCACHEDIR** environment +variable. The filename on Windows is ``krb5.rcache2``, and the file +is opened normally. + +Default replay cache name +------------------------- + +The default replay cache name is determined by the following, in +descending order of priority: + +#. The **KRB5RCACHENAME** environment variable (new in release 1.18). + +#. The **KRB5RCACHETYPE** environment variable. If this variable is + set, the residual value is empty. + +#. The **default_rcache_name** profile variable in :ref:`libdefaults` + (new in release 1.18). + +#. If none of the above are set, the default replay cache name is + ``dfl:``. diff --git a/krb5-1.21.3/doc/html/_sources/basic/stash_file_def.rst.txt b/krb5-1.21.3/doc/html/_sources/basic/stash_file_def.rst.txt new file mode 100644 index 00000000..256e2c27 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/basic/stash_file_def.rst.txt @@ -0,0 +1,25 @@ +.. _stash_definition: + + +stash file +============ + +The stash file is a local copy of the master key that resides in +encrypted form on the KDC's local disk. The stash file is used to +authenticate the KDC to itself automatically before starting the +:ref:`kadmind(8)` and :ref:`krb5kdc(8)` daemons (e.g., as part of the +machine's boot sequence). The stash file, like the keytab file (see +:ref:`keytab_file`) is a potential point-of-entry for a break-in, and +if compromised, would allow unrestricted access to the Kerberos +database. If you choose to install a stash file, it should be +readable only by root, and should exist only on the KDC's local disk. +The file should not be part of any backup of the machine, unless +access to the backup data is secured as tightly as access to the +master password itself. + +.. note:: + + If you choose not to install a stash file, the KDC will prompt you for the master key each time it starts up. + This means that the KDC will not be able to start automatically, such as after a system reboot. + + diff --git a/krb5-1.21.3/doc/html/_sources/build/directory_org.rst.txt b/krb5-1.21.3/doc/html/_sources/build/directory_org.rst.txt new file mode 100644 index 00000000..109b69a3 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/build/directory_org.rst.txt @@ -0,0 +1,75 @@ +Organization of the source directory +==================================== + +Below is a brief overview of the organization of the complete source +directory. More detailed descriptions follow. + +=============== ============================================== +appl Kerberos application client and server programs +ccapi Credential cache services +clients Kerberos V5 user programs (See :ref:`user_commands`) +config Configure scripts +config-files Sample Kerberos configuration files +include include files needed to build the Kerberos system +kadmin Administrative interface to the Kerberos database: :ref:`kadmin(1)`, :ref:`kdb5_util(8)`, :ref:`ktutil(1)`. +kdc Kerberos V5 Authentication Service and Key Distribution Center +lib_ Libraries for use with/by Kerberos V5 +plugins Kerberos plugins directory +po Localization infrastructure +prototype Templates files containing the MIT copyright message and a placeholder for the title and description of the file. +kprop Utilities for propagating the database to replica KDCs :ref:`kprop(8)` and :ref:`kpropd(8)` +tests Test suite +util_ Various utilities for building/configuring the code, sending bug reports, etc. +windows Source code for building Kerberos V5 on Windows (see windows/README) +=============== ============================================== + + +.. _lib: + +lib +--- + +The lib directory contain several subdirectories as well as some +definition and glue files. + + - The apputils directory contains the code for the generic network + servicing. + - The crypto subdirectory contains the Kerberos V5 encryption + library. + - The gssapi library contains the Generic Security Services API, + which is a library of commands to be used in secure client-server + communication. + - The kadm5 directory contains the libraries for the KADM5 + administration utilities. + - The Kerberos 5 database libraries are contained in kdb. + - The krb5 directory contains Kerberos 5 API. + - The rpc directory contains the API for the Kerberos Remote + Procedure Call protocol. + + +.. _util: + +util +---- + +The util directory contains several utility programs and libraries. + - the programs used to configure and build the code, such as + autoconf, lndir, kbuild, reconf, and makedepend, are in this + directory. + - the profile directory contains most of the functions which parse + the Kerberos configuration files (krb5.conf and kdc.conf). + - the Kerberos error table library and utilities (et); + - the Sub-system library and utilities (ss); + - database utilities (db2); + - pseudo-terminal utilities (pty); + - bug-reporting program send-pr; + - a generic support library support used by several of our other + libraries; + - the build infrastructure for building lightweight Kerberos client + (collected-client-lib) + - the tool for validating Kerberos configuration files + (confvalidator); + - the toolkit for kernel integrators for building krb5 code subsets + (gss-kernel-lib); + - source code for building Kerberos V5 on MacOS (mac) + - Windows getopt operations (windows) diff --git a/krb5-1.21.3/doc/html/_sources/build/doing_build.rst.txt b/krb5-1.21.3/doc/html/_sources/build/doing_build.rst.txt new file mode 100644 index 00000000..59cb546c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/build/doing_build.rst.txt @@ -0,0 +1,148 @@ +Doing the build +=============== + +.. _do_build: + +Building within a single tree +----------------------------- + +If you only need to build Kerberos for one platform, using a single +directory tree which contains both the source files and the object +files is the simplest. However, if you need to maintain Kerberos for +a large number of platforms, you will probably want to use separate +build trees for each platform. We recommend that you look at OS +Incompatibilities, for notes that we have on particular operating +systems. + +If you don't want separate build trees for each architecture, then use +the following abbreviated procedure:: + + cd /u1/krb5-VERSION/src + ./configure + make + +That's it! + +Building with separate build directories +---------------------------------------- + +If you wish to keep separate build directories for each platform, you +can do so using the following procedure. (Note, this requires that +your make program support VPATH. GNU's make will provide this +functionality, for example.) If your make program does not support +this, see the next section. + +For example, if you wish to store the binaries in ``tmpbuild`` build +directory you might use the following procedure:: + + mkdir /u1/tmpbuild + cd /u1/tmpbuild + /u1/krb5-VERSION/src/configure + make + + +Building using lndir +-------------------- + +If you wish to keep separate build directories for each platform, and +you do not have access to a make program which supports VPATH, all is +not lost. You can use the lndir program to create symbolic link trees +in your build directory. + +For example, if you wish to create a build directory for solaris +binaries you might use the following procedure:: + + mkdir /u1/krb5-VERSION/solaris + cd /u1/krb5-VERSION/solaris + /u1/krb5-VERSION/src/util/lndir `pwd`/../src + ./configure + make + +You must give an absolute pathname to lndir because it has a bug that +makes it fail for relative pathnames. Note that this version differs +from the latest version as distributed and installed by the +XConsortium with X11R6. Either version should be acceptable. + + +Installing the binaries +----------------------- + +Once you have built Kerberos, you should install the binaries. You can +do this by running:: + + make install + +If you want to install the binaries into a destination directory that +is not their final destination, which may be convenient if you want to +build a binary distribution to be deployed on multiple hosts, you may +use:: + + make install DESTDIR=/path/to/destdir + +This will install the binaries under *DESTDIR/PREFIX*, e.g., the user +programs will install into *DESTDIR/PREFIX/bin*, the libraries into +*DESTDIR/PREFIX/lib*, etc. *DESTDIR* must be an absolute path. + +Some implementations of make allow multiple commands to be run in +parallel, for faster builds. We test our Makefiles in parallel builds +with GNU make only; they may not be compatible with other parallel +build implementations. + + +Testing the build +----------------- + +The Kerberos V5 distribution comes with built-in regression tests. To +run them, simply type the following command while in the top-level +build directory (i.e., the directory where you sent typed make to +start building Kerberos; see :ref:`do_build`):: + + make check + +On some operating systems, you have to run ``make install`` before +running ``make check``, or the test suite will pick up installed +versions of Kerberos libraries rather than the newly built ones. You +can install into a prefix that isn't in the system library search +path, though. Alternatively, you can configure with +**-**\ **-disable-rpath**, which renders the build tree less suitable +for installation, but allows testing without interference from +previously installed libraries. + +There are additional regression tests available, which are not run +by ``make check``. These tests require manual setup and teardown of +support infrastructure which is not easily automated, or require +excessive resources for ordinary use. The procedure for running +the manual tests is documented at +https://k5wiki.kerberos.org/wiki/Manual_Testing. + + +Cleaning up the build +--------------------- + +* Use ``make clean`` to remove all files generated by running make + command. +* Use ``make distclean`` to remove all files generated by running + ./configure script. After running ``make distclean`` your source + tree (ideally) should look like the raw (just un-tarred) source + tree. + +Using autoconf +-------------- + +(If you are not a developer, you can ignore this section.) + +In the Kerberos V5 source directory, there is a configure script which +automatically determines the compilation environment and creates the +proper Makefiles for a particular platform. This configure script is +generated using autoconf, which you should already have installed if +you will be making changes to ``src/configure.in``. + +Normal users will not need to worry about running autoconf; the +distribution comes with the configure script already prebuilt. + +The autoconf package comes with a script called ``autoreconf`` that +will automatically run ``autoconf`` and ``autoheader`` as needed. You +should run ``autoreconf`` from the top source directory, e.g.:: + + cd /u1/krb5-VERSION/src + autoreconf --verbose diff --git a/krb5-1.21.3/doc/html/_sources/build/index.rst.txt b/krb5-1.21.3/doc/html/_sources/build/index.rst.txt new file mode 100644 index 00000000..f321d020 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/build/index.rst.txt @@ -0,0 +1,63 @@ +.. _build_V5: + +Building Kerberos V5 +==================== + +This section details how to build and install MIT Kerberos software +from the source. + +Prerequisites +------------- + +In order to build Kerberos V5, you will need approximately 60-70 +megabytes of disk space. The exact amount will vary depending on the +platform and whether the distribution is compiled with debugging +symbol tables or not. + +Your C compiler must conform to ANSI C (ISO/IEC 9899:1990, "c89"). +Some operating systems do not have an ANSI C compiler, or their +default compiler requires extra command-line options to enable ANSI C +conformance. + +If you wish to keep a separate build tree, which contains the compiled +\*.o file and executables, separate from your source tree, you will +need a make program which supports **VPATH**, or you will need to use +a tool such as lndir to produce a symbolic link tree for your build +tree. + +Obtaining the software +---------------------- + +The source code can be obtained from MIT Kerberos Distribution page, +at https://kerberos.org/dist/index.html. +The MIT Kerberos distribution comes in an archive file, generally +named krb5-VERSION-signed.tar, where *VERSION* is a placeholder for +the major and minor versions of MIT Kerberos. (For example, MIT +Kerberos 1.9 has major version "1" and minor version "9".) + +The krb5-VERSION-signed.tar contains a compressed tar file consisting +of the sources for all of Kerberos (generally named +krb5-VERSION.tar.gz) and a PGP signature file for this source tree +(generally named krb5-VERSION.tar.gz.asc). MIT highly recommends that +you verify the integrity of the source code using this signature, +e.g., by running:: + + tar xf krb5-VERSION-signed.tar + gpg --verify krb5-VERSION.tar.gz.asc + +Unpack krb5-VERSION.tar.gz in some directory. In this section we will assume +that you have chosen the top directory of the distribution the directory +``/u1/krb5-VERSION``. + +Review the README file for the license, copyright and other sprecific to the +distribution information. + +Contents +-------- +.. toctree:: + :maxdepth: 1 + + directory_org.rst + doing_build.rst + options2configure.rst + osconf.rst diff --git a/krb5-1.21.3/doc/html/_sources/build/options2configure.rst.txt b/krb5-1.21.3/doc/html/_sources/build/options2configure.rst.txt new file mode 100644 index 00000000..e879b18b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/build/options2configure.rst.txt @@ -0,0 +1,397 @@ +.. _options2configure: + +Options to *configure* +====================== + +There are a number of options to configure which you can use to +control how the Kerberos distribution is built. + +Most commonly used options +-------------------------- + +**-**\ **-help** + Provides help to configure. This will list the set of commonly + used options for building Kerberos. + +**-**\ **-prefix=**\ *PREFIX* + By default, Kerberos will install the package's files rooted at + ``/usr/local``. If you desire to place the binaries into the + directory *PREFIX*, use this option. + +**-**\ **-exec-prefix=**\ *EXECPREFIX* + This option allows one to separate the architecture independent + programs from the host-dependent files (configuration files, + manual pages). Use this option to install architecture-dependent + programs in *EXECPREFIX*. The default location is the value of + specified by **-**\ **-prefix** option. + +**-**\ **-localstatedir=**\ *LOCALSTATEDIR* + This option sets the directory for locally modifiable + single-machine data. In Kerberos, this mostly is useful for + setting a location for the KDC data files, as they will be + installed in ``LOCALSTATEDIR/krb5kdc``, which is by default + ``PREFIX/var/krb5kdc``. + +**-**\ **-with-netlib**\ [=\ *libs*] + Allows for suppression of or replacement of network libraries. By + default, Kerberos V5 configuration will look for ``-lnsl`` and + ``-lsocket``. If your operating system has a broken resolver + library or fails to pass the tests in ``src/tests/resolv``, you + will need to use this option. + +**-**\ **-enable-dns-for-realm** + Enable the use of DNS to look up a host's Kerberos realm, + if the information is not provided in + :ref:`krb5.conf(5)`. See :ref:`mapping_hostnames` + for information about using DNS to determine the default realm. + DNS lookups for realm names are disabled by default. + +**-**\ **-with-system-et** + Use an installed version of the error-table (et) support software, + the compile_et program, the com_err.h header file and the com_err + library. If these are not in the default locations, you may wish + to specify ``CPPFLAGS=-I/some/dir`` and + ``LDFLAGS=-L/some/other/dir`` options at configuration time as + well. + + If this option is not given, a version supplied with the Kerberos + sources will be built and installed along with the rest of the + Kerberos tree, for Kerberos applications to link against. + +**-**\ **-with-system-ss** + Use an installed version of the subsystem command-line interface + software, the mk_cmds program, the ``ss/ss.h`` header file and the + ss library. If these are not in the default locations, you may + wish to specify ``CPPFLAGS=-I/some/dir`` and + ``LDFLAGS=-L/some/other/dir`` options at configuration time as + well. See also the **SS_LIB** option. + + If this option is not given, the ss library supplied with the + Kerberos sources will be compiled and linked into those programs + that need it; it will not be installed separately. + +**-**\ **-with-system-db** + Use an installed version of the Berkeley DB package, which must + provide an API compatible with version 1.85. This option is + unsupported and untested. In particular, we do not know if the + database-rename code used in the dumpfile load operation will + behave properly. + + If this option is not given, a version supplied with the Kerberos + sources will be built and installed. (We are not updating this + version at this time because of licensing issues with newer + versions that we haven't investigated sufficiently yet.) + + +Environment variables +--------------------- + +**CC=**\ *COMPILER* + Use *COMPILER* as the C compiler. + +**CFLAGS=**\ *FLAGS* + Use *FLAGS* as the default set of C compiler flags. + +**CPP=**\ *CPP* + C preprocessor to use. (e.g., ``CPP='gcc -E'``) + +**CPPFLAGS=**\ *CPPOPTS* + Use *CPPOPTS* as the default set of C preprocessor flags. The + most common use of this option is to select certain #define's for + use with the operating system's include files. + + +**DB_HEADER=**\ *headername* + If db.h is not the correct header file to include to compile + against the Berkeley DB 1.85 API, specify the correct header file + name with this option. For example, ``DB_HEADER=db3/db_185.h``. + +**DB_LIB=**\ *libs*... + If ``-ldb`` is not the correct library specification for the + Berkeley DB library version to be used, override it with this + option. For example, ``DB_LIB=-ldb-3.3``. + +**DEFCCNAME=**\ *ccachename* + Override the built-in default credential cache name. + For example, ``DEFCCNAME=DIR:/var/run/user/%{USERID}/ccache`` + See :ref:`parameter_expansion` for information about supported + parameter expansions. + +**DEFCKTNAME=**\ *keytabname* + Override the built-in default client keytab name. + The format is the same as for *DEFCCNAME*. + +**DEFKTNAME=**\ *keytabname* + Override the built-in default keytab name. + The format is the same as for *DEFCCNAME*. + +**LD=**\ *LINKER* + Use *LINKER* as the default loader if it should be different from + C compiler as specified above. + +**LDFLAGS=**\ *LDOPTS* + This option informs the linker where to get additional libraries + (e.g., ``-L``). + +**LIBS=**\ *LDNAME* + This option allows one to specify libraries to be passed to the + linker (e.g., ``-l``) + +**PKCS11_MODNAME=**\ *library* + Override the built-in default PKCS11 library name. + +**SS_LIB=**\ *libs*... + If ``-lss`` is not the correct way to link in your installed ss + library, for example if additional support libraries are needed, + specify the correct link options here. Some variants of this + library are around which allow for Emacs-like line editing, but + different versions require different support libraries to be + explicitly specified. + + This option is ignored if **-**\ **-with-system-ss** is not specified. + +**YACC** + The 'Yet Another C Compiler' implementation to use. Defaults to + the first program found out of: '`bison -y`', '`byacc`', + '`yacc`'. + +**YFLAGS** + The list of arguments that will be passed by default to $YACC. + This script will default YFLAGS to the empty string to avoid a + default value of ``-d`` given by some make applications. + + +Fine tuning of the installation directories +------------------------------------------- + +**-**\ **-bindir=**\ *DIR* + User executables. Defaults to ``EXECPREFIX/bin``, where + *EXECPREFIX* is the path specified by **-**\ **-exec-prefix** + configuration option. + +**-**\ **-sbindir=**\ *DIR* + System admin executables. Defaults to ``EXECPREFIX/sbin``, where + *EXECPREFIX* is the path specified by **-**\ **-exec-prefix** + configuration option. + +**-**\ **-sysconfdir=**\ *DIR* + Read-only single-machine data such as krb5.conf. + Defaults to ``PREFIX/etc``, where + *PREFIX* is the path specified by **-**\ **-prefix** configuration + option. + +**-**\ **-libdir=**\ *DIR* + Object code libraries. Defaults to ``EXECPREFIX/lib``, where + *EXECPREFIX* is the path specified by **-**\ **-exec-prefix** + configuration option. + +**-**\ **-includedir=**\ *DIR* + C header files. Defaults to ``PREFIX/include``, where *PREFIX* is + the path specified by **-**\ **-prefix** configuration option. + +**-**\ **-datarootdir=**\ *DATAROOTDIR* + Read-only architecture-independent data root. Defaults to + ``PREFIX/share``, where *PREFIX* is the path specified by + **-**\ **-prefix** configuration option. + +**-**\ **-datadir=**\ *DIR* + Read-only architecture-independent data. Defaults to path + specified by **-**\ **-datarootdir** configuration option. + +**-**\ **-localedir=**\ *DIR* + Locale-dependent data. Defaults to ``DATAROOTDIR/locale``, where + *DATAROOTDIR* is the path specified by **-**\ **-datarootdir** + configuration option. + +**-**\ **-mandir=**\ *DIR* + Man documentation. Defaults to ``DATAROOTDIR/man``, where + *DATAROOTDIR* is the path specified by **-**\ **-datarootdir** + configuration option. + + +Program names +------------- + +**-**\ **-program-prefix=**\ *PREFIX* + Prepend *PREFIX* to the names of the programs when installing + them. For example, specifying ``--program-prefix=mit-`` at the + configure time will cause the program named ``abc`` to be + installed as ``mit-abc``. + +**-**\ **-program-suffix=**\ *SUFFIX* + Append *SUFFIX* to the names of the programs when installing them. + For example, specifying ``--program-suffix=-mit`` at the configure + time will cause the program named ``abc`` to be installed as + ``abc-mit``. + +**-**\ **-program-transform-name=**\ *PROGRAM* + Run ``sed -e PROGRAM`` on installed program names. (*PROGRAM* is a + sed script). + + +System types +------------ + +**-**\ **-build=**\ *BUILD* + Configure for building on *BUILD* + (e.g., ``--build=x86_64-linux-gnu``). + +**-**\ **-host=**\ *HOST* + Cross-compile to build programs to run on *HOST* + (e.g., ``--host=x86_64-linux-gnu``). By default, Kerberos V5 + configuration will look for "build" option. + + +Optional features +----------------- + +**-**\ **-disable-option-checking** + Ignore unrecognized --enable/--with options. + +**-**\ **-disable-**\ *FEATURE* + Do not include *FEATURE* (same as --enable-FEATURE=no). + +**-**\ **-enable-**\ *FEATURE*\ [=\ *ARG*] + Include *FEATURE* [ARG=yes]. + +**-**\ **-enable-maintainer-mode** + Enable rebuilding of source files, Makefiles, etc. + +**-**\ **-disable-delayed-initialization** + Initialize library code when loaded. Defaults to delay until + first use. + +**-**\ **-disable-thread-support** + Don't enable thread support. Defaults to enabled. + +**-**\ **-disable-rpath** + Suppress run path flags in link lines. + +**-**\ **-enable-athena** + Build with MIT Project Athena configuration. + +**-**\ **-disable-kdc-lookaside-cache** + Disable the cache which detects client retransmits. + +**-**\ **-disable-pkinit** + Disable PKINIT plugin support. + +**-**\ **-disable-aesni** + Disable support for using AES instructions on x86 platforms. + +**-**\ **-enable-asan**\ [=\ *ARG*] + Enable building with asan memory error checking. If *ARG* is + given, it controls the -fsanitize compilation flag value (the + default is "address"). + + +Optional packages +----------------- + +**-**\ **-with-**\ *PACKAGE*\ [=ARG\] + Use *PACKAGE* (e.g., ``--with-imap``). The default value of *ARG* + is ``yes``. + +**-**\ **-without-**\ *PACKAGE* + Do not use *PACKAGE* (same as ``--with-PACKAGE=no``) + (e.g., ``--without-libedit``). + +**-**\ **-with-size-optimizations** + Enable a few optimizations to reduce code size possibly at some + run-time cost. + +**-**\ **-with-system-et** + Use the com_err library and compile_et utility that are already + installed on the system, instead of building and installing + local versions. + +**-**\ **-with-system-ss** + Use the ss library and mk_cmds utility that are already installed + on the system, instead of building and using private versions. + +**-**\ **-with-system-db** + Use the berkeley db utility already installed on the system, + instead of using a private version. This option is not + recommended; enabling it may result in incompatibility with key + databases originating on other systems. + +**-**\ **-with-netlib=**\ *LIBS* + Use the resolver library specified in *LIBS*. Use this variable + if the C library resolver is insufficient or broken. + +**-**\ **-with-hesiod=**\ *path* + Compile with Hesiod support. The *path* points to the Hesiod + directory. By default Hesiod is unsupported. + +**-**\ **-with-ldap** + Compile OpenLDAP database backend module. + +**-**\ **-with-lmdb** + Compile LMDB database backend module. + +**-**\ **-with-vague-errors** + Do not send helpful errors to client. For example, if the KDC + should return only vague error codes to clients. + +**-**\ **-with-crypto-impl=**\ *IMPL* + Use specified crypto implementation (e.g., **-**\ + **-with-crypto-impl=**\ *openssl*). The default is the native MIT + Kerberos implementation ``builtin``. The other currently + implemented crypto backend is ``openssl``. (See + :ref:`mitK5features`) + +**-**\ **-without-libedit** + Do not compile and link against libedit. Some utilities will no + longer offer command history or completion in interactive mode if + libedit is disabled. + +**-**\ **-with-readline** + Compile and link against GNU readline, as an alternative to libedit. + +**-**\ **-with-system-verto** + Use an installed version of libverto. If the libverto header and + library are not in default locations, you may wish to specify + ``CPPFLAGS=-I/some/dir`` and ``LDFLAGS=-L/some/other/dir`` options + at configuration time as well. + + If this option is not given, the build system will try to detect + an installed version of libverto and use it if it is found. + Otherwise, a version supplied with the Kerberos sources will be + built and installed. The built-in version does not contain the + full set of back-end modules and is not a suitable general + replacement for the upstream version, but will work for the + purposes of Kerberos. + + Specifying **-**\ **-without-system-verto** will cause the built-in + version of libverto to be used unconditionally. + +**-**\ **-with-krb5-config=**\ *PATH* + Use the krb5-config program at *PATH* to obtain the build-time + default credential cache, keytab, and client keytab names. The + default is to use ``krb5-config`` from the program path. Specify + ``--without-krb5-config`` to disable the use of krb5-config and + use the usual built-in defaults. + +**-**\ **-without-keyutils** + Build without libkeyutils support. This disables the KEYRING + credential cache type. + + +Examples +-------- + +For example, in order to configure Kerberos on a Solaris machine using +the suncc compiler with the optimizer turned on, run the configure +script with the following options:: + + % ./configure CC=suncc CFLAGS=-O + +For a slightly more complicated example, consider a system where +several packages to be used by Kerberos are installed in +``/usr/foobar``, including Berkeley DB 3.3, and an ss library that +needs to link against the curses library. The configuration of +Kerberos might be done thus:: + + ./configure CPPFLAGS=-I/usr/foobar/include LDFLAGS=-L/usr/foobar/lib \ + --with-system-et --with-system-ss --with-system-db \ + SS_LIB='-lss -lcurses' DB_HEADER=db3/db_185.h DB_LIB=-ldb-3.3 diff --git a/krb5-1.21.3/doc/html/_sources/build/osconf.rst.txt b/krb5-1.21.3/doc/html/_sources/build/osconf.rst.txt new file mode 100644 index 00000000..22ee6804 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/build/osconf.rst.txt @@ -0,0 +1,26 @@ +osconf.hin +========== + +There is one configuration file which you may wish to edit to control +various compile-time parameters in the Kerberos distribution:: + + include/osconf.hin + +The list that follows is by no means complete, just some of the more +interesting variables. + +**DEFAULT_PROFILE_PATH** + The pathname to the file which contains the profiles for the known + realms, their KDCs, etc. The default value is |krb5conf|. +**DEFAULT_KEYTAB_NAME** + The type and pathname to the default server keytab file. The + default is |keytab|. +**DEFAULT_KDC_ENCTYPE** + The default encryption type for the KDC database master key. The + default value is |defmkey|. +**RCTMPDIR** + The directory which stores replay caches. The default is + ``/var/tmp``. +**DEFAULT_KDB_FILE** + The location of the default database. The default value is + |kdcdir|\ ``/principal``. diff --git a/krb5-1.21.3/doc/html/_sources/build_this.rst.txt b/krb5-1.21.3/doc/html/_sources/build_this.rst.txt new file mode 100644 index 00000000..9be7360a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/build_this.rst.txt @@ -0,0 +1,82 @@ +How to build this documentation from the source +=============================================== + +Pre-requisites for a simple build, or to update man pages: + +* Sphinx 1.0.4 or higher (See https://www.sphinx-doc.org) with the + autodoc extension installed. + +Additional prerequisites to include the API reference based on Doxygen +markup: + +* Python 2.5 with the Cheetah, lxml, and xml modules +* Doxygen + + +Simple build without API reference +---------------------------------- + +To test simple changes to the RST sources, you can build the +documentation without the Doxygen reference by running, from the doc +directory:: + + sphinx-build . test_html + +You will see a number of warnings about missing files. This is +expected. If there is not already a ``doc/version.py`` file, you will +need to create one by first running ``make version.py`` in the +``src/doc`` directory of a configured build tree. + + +Updating man pages +------------------ + +Man pages are generated from the RST sources and checked into the +``src/man`` directory of the repository. This allows man pages to be +installed without requiring Sphinx when using a source checkout. To +regenerate these files, run ``make man`` from the man subdirectory +of a configured build tree. You can also do this from an unconfigured +source tree with:: + + cd src/man + make -f Makefile.in top_srcdir=.. srcdir=. man + make clean + +As with the simple build, it is normal to see warnings about missing +files when rebuilding the man pages. + + +Building for a release tarball or web site +------------------------------------------ + +To generate documentation in HTML format, run ``make html`` in the +``doc`` subdirectory of a configured build tree (the build directory +corresponding to ``src/doc``, not the top-level ``doc`` directory). +The output will be placed in the top-level ``doc/html`` directory. +This build will include the API reference generated from Doxygen +markup in the source tree. + +Documentation generated this way will use symbolic names for paths +(like ``BINDIR`` for the directory containing user programs), with the +symbolic names being links to a table showing typical values for those +paths. + +You can also do this from an unconfigured source tree with:: + + cd src/doc + make -f Makefile.in SPHINX_ARGS= htmlsrc + + +Building for an OS package or site documentation +------------------------------------------------ + +To generate documentation specific to a build of MIT krb5 as you have +configured it, run ``make substhtml`` in the ``doc`` subdirectory of a +configured build tree (the build directory corresponding to +``src/doc``, not the top-level ``doc`` directory). The output will be +placed in the ``html_subst`` subdirectory of that build directory. +This build will include the API reference. + +Documentation generated this way will use concrete paths (like +``/usr/local/bin`` for the directory containing user programs, for a +default custom build). diff --git a/krb5-1.21.3/doc/html/_sources/copyright.rst.txt b/krb5-1.21.3/doc/html/_sources/copyright.rst.txt new file mode 100644 index 00000000..85ecebec --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/copyright.rst.txt @@ -0,0 +1,8 @@ +Copyright +========= + +Copyright |copy| 1985-2024 by the Massachusetts Institute of +Technology and its contributors. All rights reserved. + +See :ref:`mitK5license` for additional copyright and license +information. diff --git a/krb5-1.21.3/doc/html/_sources/formats/ccache_file_format.rst.txt b/krb5-1.21.3/doc/html/_sources/formats/ccache_file_format.rst.txt new file mode 100644 index 00000000..6138c1b5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/formats/ccache_file_format.rst.txt @@ -0,0 +1,182 @@ +.. _ccache_file_format: + +Credential cache file format +============================ + +There are four versions of the file format used by the FILE credential +cache type. The first byte of the file always has the value 5, and +the value of the second byte contains the version number (1 through +4). Versions 1 and 2 of the file format use native byte order for integer +representations. Versions 3 and 4 always use big-endian byte order. + +After the two-byte version indicator, the file has three parts: the +header (in version 4 only), the default principal name, and a sequence +of credentials. + + +Header format +------------- + +The header appears only in format version 4. It begins with a 16-bit +integer giving the length of the entire header, followed by a sequence +of fields. Each field consists of a 16-bit tag, a 16-bit length, and +a value of the given length. A file format implementation should +ignore fields with unknown tags. + +At this time there is only one defined header field. Its tag value is +1, its length is always 8, and its contents are two 32-bit integers +giving the seconds and microseconds of the time offset of the KDC +relative to the client. Adding this offset to the current time on the +client should give the current time on the KDC, if that offset has not +changed since the initial authentication. + + +.. _cache_principal_format: + +Principal format +---------------- + +The default principal is marshalled using the following informal +grammar:: + + principal ::= + name type (32 bits) [omitted in version 1] + count of components (32 bits) [includes realm in version 1] + realm (data) + component1 (data) + component2 (data) + ... + + data ::= + length (32 bits) + value (length bytes) + +There is no external framing on the default principal, so it must be +parsed according to the above grammar in order to find the sequence of +credentials which follows. + + +.. _ccache_credential_format: + +Credential format +----------------- + +The credential format uses the following informal grammar (referencing +the ``principal`` and ``data`` types from the previous section):: + + credential ::= + client (principal) + server (principal) + keyblock (keyblock) + authtime (32 bits) + starttime (32 bits) + endtime (32 bits) + renew_till (32 bits) + is_skey (1 byte, 0 or 1) + ticket_flags (32 bits) + addresses (addresses) + authdata (authdata) + ticket (data) + second_ticket (data) + + keyblock ::= + enctype (16 bits) [repeated twice in version 3] + data + + addresses ::= + count (32 bits) + address1 + address2 + ... + + address ::= + addrtype (16 bits) + data + + authdata ::= + count (32 bits) + authdata1 + authdata2 + ... + + authdata ::= + ad_type (16 bits) + data + +There is no external framing on a marshalled credential, so it must be +parsed according to the above grammar in order to find the next +credential. There is also no count of credentials or marker at the +end of the sequence of credentials; the sequence ends when the file +ends. + + +Credential cache configuration entries +-------------------------------------- + +Configuration entries are encoded as credential entries. The client +principal of the entry is the default principal of the cache. The +server principal has the realm ``X-CACHECONF:`` and two or three +components, the first of which is ``krb5_ccache_conf_data``. The +server principal's second component is the configuration key. The +third component, if it exists, is a principal to which the +configuration key is associated. The configuration value is stored in +the ticket field of the entry. All other entry fields are zeroed. + +Programs using credential caches must be aware of configuration +entries for several reasons: + +* A program which displays the contents of a cache should not + generally display configuration entries. + +* The ticket field of a configuration entry is not (usually) a valid + encoding of a Kerberos ticket. An implementation must not treat the + cache file as malformed if it cannot decode the ticket field. + +* Configuration entries have an endtime field of 0 and might therefore + always be considered expired, but they should not be treated as + unimportant as a result. For instance, a program which copies + credentials from one cache to another should not omit configuration + entries because of the endtime. + +The following configuration keys are currently used in MIT krb5: + +fast_avail + The presence of this key with a non-empty value indicates that the + KDC asserted support for FAST (see :rfc:`6113`) during the initial + authentication, using the negotiation method described in + :rfc:`6806` section 11. This key is not associated with any + principal. + +pa_config_data + The value of this key contains a JSON object representation of + parameters remembered by the preauthentication mechanism used + during the initial authentication. These parameters may be used + when refreshing credentials. This key is associated with the + server principal of the initial authentication (usually the local + krbtgt principal of the client realm). + +pa_type + The value of this key is the ASCII decimal representation of the + preauth type number used during the initial authentication. This + key is associated with the server principal of the initial + authentication. + +proxy_impersonator + The presence of this key indicates that the cache is a synthetic + delegated credential for use with S4U2Proxy. The value is the + name of the intermediate service whose TGT can be used to make + S4U2Proxy requests for target services. This key is not + associated with any principal. + +refresh_time + The presence of this key indicates that the cache was acquired by + the GSS mechanism using a client keytab. The value is the ASCII + decimal representation of a timestamp at which the GSS mechanism + should attempt to refresh the credential cache from the client + keytab. + +start_realm + This key indicates the realm of the ticket-granting ticket to be + used for TGS requests, when making a referrals request or + beginning a cross-realm request. If it is not present, the client + realm is used. diff --git a/krb5-1.21.3/doc/html/_sources/formats/cookie.rst.txt b/krb5-1.21.3/doc/html/_sources/formats/cookie.rst.txt new file mode 100644 index 00000000..e32365da --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/formats/cookie.rst.txt @@ -0,0 +1,97 @@ +KDC cookie format +================= + +:rfc:`6113` section 5.2 specifies a pa-data type PA-FX-COOKIE, which +clients are required to reflect back to the KDC during +pre-authentication. The MIT krb5 KDC uses the following formats for +cookies. + + +Trivial cookie (version 0) +-------------------------- + +If there is no pre-authentication mechanism state information to save, +a trivial cookie containing the value "MIT" is used. A trivial cookie +is needed to indicate that the conversation can continue. + + +Secure cookie (version 1) +------------------------- + +In release 1.14 and later, a secure cookie can be sent if there is any +mechanism state to save for the next request. A secure cookie +contains the concatenation of the following: + +* the four bytes "MIT1" +* a four-byte big-endian kvno value +* an :rfc:`3961` ciphertext + +The ciphertext is encrypted in the cookie key with key usage +number 513. The cookie key is derived from a key in the local krbtgt +principal entry for the realm (e.g. ``krbtgt/KRBTEST.COM@KRBTEST.COM`` +if the request is to the ``KRBTEST.COM`` realm). The first krbtgt key +for the indicated kvno value is combined with the client principal as +follows:: + + cookie-key <- random-to-key(PRF+(tgt-key, "COOKIE" | client-princ)) + +where **random-to-key** is the :rfc:`3961` random-to-key operation for +the krbtgt key's encryption type, **PRF+** is defined in :rfc:`6113`, +and ``|`` denotes concatenation. *client-princ* is the request client +principal name with realm, marshalled according to :rfc:`1964` section +2.1.1. + +The plain text of the encrypted part of a cookie is the DER encoding +of the following ASN.1 type:: + + SecureCookie ::= SEQUENCE { + time INTEGER, + data SEQUENCE OF PA-DATA, + ... + } + +The time field represents the cookie creation time; for brevity, it is +encoded as an integer giving the POSIX timestamp rather than as an +ASN.1 GeneralizedTime value. The data field contains one element for +each pre-authentication type which requires saved state. For +mechanisms which have separate request and reply types, the request +type is used; this allows the KDC to determine whether a cookie is +relevant to a request by comparing the request pa-data types to the +cookie data types. + +SPAKE cookie format (version 1) +------------------------------- + +Inside the SecureCookie wrapper, a data value of type 151 contains +state for SPAKE pre-authentication. This data is the concatenation of +the following: + +* a two-byte big-endian version number with the value 1 +* a two-byte big-endian stage number +* a four-byte big-endian group number +* a four-byte big-endian length and data for the SPAKE value +* a four-byte big-endian length and data for the transcript hash +* zero or more second factor records, each consisting of: + - a four-byte big-endian second-factor type + - a four-byte big-endian length and data + +The stage value is 0 if the cookie was sent with a challenge message. +Otherwise it is 1 for the first encdata message sent by the KDC during +an exchange, 2 for the second, etc.. + +The group value indicates the group number used in the SPAKE challenge. + +For a stage-0 cookie, the SPAKE value is the KDC private key, +represented in the scalar marshalling form of the group. For other +cookies, the SPAKE value is the SPAKE result K, represented in the +group element marshalling form. + +For a stage-0 cookie, the transcript hash is the intermediate hash +after updating with the client support message (if one was sent) and +challenge. For other cookies it is the final hash. + +For a stage-0 cookie, there may be any number of second-factor +records, including none; a second-factor type need not create a state +field if it does not need one, and no record is created for SF-NONE. +For other cookies, there must be exactly one second-factor record +corresponding to the factor type chosen by the client. diff --git a/krb5-1.21.3/doc/html/_sources/formats/freshness_token.rst.txt b/krb5-1.21.3/doc/html/_sources/formats/freshness_token.rst.txt new file mode 100644 index 00000000..3127621a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/formats/freshness_token.rst.txt @@ -0,0 +1,19 @@ +PKINIT freshness tokens +======================= + +:rfc:`8070` specifies a pa-data type PA_AS_FRESHNESS, which clients +should reflect within signed PKINIT data to prove recent access to the +client certificate private key. The contents of a freshness token are +left to the KDC implementation. The MIT krb5 KDC uses the following +format for freshness tokens (starting in release 1.17): + +* a four-byte big-endian POSIX timestamp +* a four-byte big-endian key version number +* an :rfc:`3961` checksum, with no ASN.1 wrapper + +The checksum is computed using the first key in the local krbtgt +principal entry for the realm (e.g. ``krbtgt/KRBTEST.COM@KRBTEST.COM`` +if the request is to the ``KRBTEST.COM`` realm) of the indicated key +version. The checksum type must be the mandatory checksum type for +the encryption type of the krbtgt key. The key usage value for the +checksum is 514. diff --git a/krb5-1.21.3/doc/html/_sources/formats/index.rst.txt b/krb5-1.21.3/doc/html/_sources/formats/index.rst.txt new file mode 100644 index 00000000..47dea12f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/formats/index.rst.txt @@ -0,0 +1,11 @@ +Protocols and file formats +========================== + +.. toctree:: + :maxdepth: 1 + + ccache_file_format + keytab_file_format + rcache_file_format + cookie + freshness_token diff --git a/krb5-1.21.3/doc/html/_sources/formats/keytab_file_format.rst.txt b/krb5-1.21.3/doc/html/_sources/formats/keytab_file_format.rst.txt new file mode 100644 index 00000000..8424d058 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/formats/keytab_file_format.rst.txt @@ -0,0 +1,51 @@ +.. _keytab_file_format: + +Keytab file format +================== + +There are two versions of the file format used by the FILE keytab +type. The first byte of the file always has the value 5, and the +value of the second byte contains the version number (1 or 2). +Version 1 of the file format uses native byte order for integer +representations. Version 2 always uses big-endian byte order. + +After the two-byte version indicator, the file contains a sequence of +signed 32-bit record lengths followed by key records or holes. A +positive record length indicates a valid key entry whose size is equal +to or less than the record length. A negative length indicates a +zero-filled hole whose size is the inverse of the length. A length of +0 indicates the end of the file. + + +Key entry format +---------------- + +A key entry may be smaller in size than the record length which +precedes it, because it may have replaced a hole which is larger than +the key entry. Key entries use the following informal grammar:: + + entry ::= + principal + timestamp (32 bits) + key version (8 bits) + enctype (16 bits) + key length (16 bits) + key contents + key version (32 bits) [in release 1.14 and later] + + principal ::= + count of components (16 bits) [includes realm in version 1] + realm (data) + component1 (data) + component2 (data) + ... + name type (32 bits) [omitted in version 1] + + data ::= + length (16 bits) + value (length bytes) + +The 32-bit key version overrides the 8-bit key version. To determine +if it is present, the implementation must check that at least 4 bytes +remain in the record after the other fields are read, and that the +value of the 32-bit integer contained in those bytes is non-zero. diff --git a/krb5-1.21.3/doc/html/_sources/formats/rcache_file_format.rst.txt b/krb5-1.21.3/doc/html/_sources/formats/rcache_file_format.rst.txt new file mode 100644 index 00000000..42ee8281 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/formats/rcache_file_format.rst.txt @@ -0,0 +1,50 @@ +Replay cache file format +======================== + +This section documents the second version of the replay cache file +format, used by the "file2" replay cache type (new in release 1.18). +The first version of the file replay cache format is not documented. + +All accesses to the replay cache file take place under an exclusive +POSIX or Windows file lock, obtained when the file is opened and +released when it is closed. Replay cache files are automatically +created when first accessed. + +For each store operation, a tag is derived from the checksum part of +the :RFC:`3961` ciphertext of the authenticator. The checksum is +coerced to a fixed length of 12 bytes, either through truncation or +right-padding with zero bytes. A four-byte timestamp is appended to +the tag to produce a total record length of 16 bytes. + +Bytes 0 through 15 of the file contain a hash seed for the SipHash-2-4 +algorithm (siphash_); this field is populated with random bytes when +the file is first created. All remaining bytes are divided into a +series of expanding hash tables: + +* Bytes 16-16383: hash table 1 (1023 slots) +* Bytes 16384-49151: hash table 2 (2048 slots) +* Bytes 49152-114687: hash table 3 (4096 slots) +* ... + +Only some hash tables will be present in the file at any specific +time, and the final table may be only partially filled. Replay cache +files may be sparse if the filesystem supports it. + +For each table present in the file, the tag is hashed with SipHash-2-4 +using the seed recorded in the file. The first byte of the seed is +incremented by one (modulo 256) for each table after the first. The +resulting hash value is taken modulo one less than the table size +(1022 for the first hash table, 2047 for the second) to produce the +index. The record may be found at the slot given by the index or at +the next slot. + +All candidate locations for the record must be searched until a slot +is found with a timestamp of zero (indicating a slot which has never +been written to) or an offset is reached at or beyond the end of the +file. Any candidate location with a timestamp value of zero, with a +timestamp value less than the current time minus clockskew, or at or +beyond the end of the file is available for writing. When all +candidate locations have been searched without finding a match, the +new entry is written to the earliest candidate available for writing. + +.. _siphash: https://131002.net/siphash/siphash.pdf diff --git a/krb5-1.21.3/doc/html/_sources/index.rst.txt b/krb5-1.21.3/doc/html/_sources/index.rst.txt new file mode 100644 index 00000000..543a9d1b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/index.rst.txt @@ -0,0 +1,18 @@ +MIT Kerberos Documentation (|release|) +====================================== + + +.. toctree:: + :maxdepth: 1 + + user/index.rst + admin/index.rst + appdev/index.rst + plugindev/index.rst + build/index.rst + basic/index.rst + formats/index.rst + mitK5features.rst + build_this.rst + about.rst + resources diff --git a/krb5-1.21.3/doc/html/_sources/mitK5defaults.rst.txt b/krb5-1.21.3/doc/html/_sources/mitK5defaults.rst.txt new file mode 100644 index 00000000..aea7af3d --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/mitK5defaults.rst.txt @@ -0,0 +1,79 @@ +.. _mitK5defaults: + +MIT Kerberos defaults +===================== + +General defaults +---------------- + +========================================== ============================= ==================== +Description Default Environment +========================================== ============================= ==================== +:ref:`keytab_definition` file |keytab| **KRB5_KTNAME** +Client :ref:`keytab_definition` file |ckeytab| **KRB5_CLIENT_KTNAME** +Kerberos config file :ref:`krb5.conf(5)` |krb5conf|\ ``:``\ **KRB5_CONFIG** + |sysconfdir|\ ``/krb5.conf`` +KDC config file :ref:`kdc.conf(5)` |kdcdir|\ ``/kdc.conf`` **KRB5_KDC_PROFILE** +GSS mechanism config file |sysconfdir|\ ``/gss/mech`` **GSS_MECH_CONFIG** +KDC database path (DB2) |kdcdir|\ ``/principal`` +Master key :ref:`stash_definition` |kdcdir|\ ``/.k5.``\ *realm* +Admin server ACL file :ref:`kadm5.acl(5)` |kdcdir|\ ``/kadm5.acl`` +OTP socket directory |kdcrundir| +Plugin base directory |libdir|\ ``/krb5/plugins`` +:ref:`rcache_definition` directory ``/var/tmp`` **KRB5RCACHEDIR** +Master key default enctype |defmkey| +Default :ref:`keysalt list` |defkeysalts| +Permitted enctypes |defetypes| +KDC default port 88 +Admin server port 749 +Password change port 464 +========================================== ============================= ==================== + + +Replica KDC propagation defaults +-------------------------------- + +This table shows defaults used by the :ref:`kprop(8)` and +:ref:`kpropd(8)` programs. + +========================== ================================ =========== +Description Default Environment +========================== ================================ =========== +kprop database dump file |kdcdir|\ ``/replica_datatrans`` +kpropd temporary dump file |kdcdir|\ ``/from_master`` +kdb5_util location |sbindir|\ ``/kdb5_util`` +kprop location |sbindir|\ ``/kprop`` +kpropd ACL file |kdcdir|\ ``/kpropd.acl`` +kprop port 754 KPROP_PORT +========================== ================================ =========== + + +.. _paths: + +Default paths for Unix-like systems +----------------------------------- + +On Unix-like systems, some paths used by MIT krb5 depend on parameters +chosen at build time. For a custom build, these paths default to +subdirectories of ``/usr/local``. When MIT krb5 is integrated into an +operating system, the paths are generally chosen to match the +operating system's filesystem layout. + +========================== ============== =========================== =========================== +Description Symbolic name Custom build path Typical OS path +========================== ============== =========================== =========================== +User programs BINDIR ``/usr/local/bin`` ``/usr/bin`` +Libraries and plugins LIBDIR ``/usr/local/lib`` ``/usr/lib`` +Parent of KDC state dir LOCALSTATEDIR ``/usr/local/var`` ``/var`` +Parent of KDC runtime dir RUNSTATEDIR ``/usr/local/var/run`` ``/run`` +Administrative programs SBINDIR ``/usr/local/sbin`` ``/usr/sbin`` +Alternate krb5.conf dir SYSCONFDIR ``/usr/local/etc`` ``/etc`` +Default ccache name DEFCCNAME ``FILE:/tmp/krb5cc_%{uid}`` ``FILE:/tmp/krb5cc_%{uid}`` +Default keytab name DEFKTNAME ``FILE:/etc/krb5.keytab`` ``FILE:/etc/krb5.keytab`` +Default PKCS11 module PKCS11_MODNAME ``opensc-pkcs11.so`` ``opensc-pkcs11.so`` +========================== ============== =========================== =========================== + +The default client keytab name (DEFCKTNAME) typically defaults to +``FILE:/usr/local/var/krb5/user/%{euid}/client.keytab`` for a custom +build. A native build will typically use a path which will vary +according to the operating system's layout of ``/var``. diff --git a/krb5-1.21.3/doc/html/_sources/mitK5features.rst.txt b/krb5-1.21.3/doc/html/_sources/mitK5features.rst.txt new file mode 100644 index 00000000..10effcf1 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/mitK5features.rst.txt @@ -0,0 +1,699 @@ +.. highlight:: rst + +.. toctree:: + :hidden: + + mitK5license.rst + +.. _mitK5features: + +MIT Kerberos features +===================== + +https://web.mit.edu/kerberos + + +Quick facts +----------- + +License - :ref:`mitK5license` + +Releases: + - Latest stable: https://web.mit.edu/kerberos/krb5-1.20/ + - Supported: https://web.mit.edu/kerberos/krb5-1.19/ + - Release cycle: approximately 12 months + +Supported platforms \/ OS distributions: + - Windows (KfW 4.0): Windows 7, Vista, XP + - Solaris: SPARC, x86_64/x86 + - GNU/Linux: Debian x86_64/x86, Ubuntu x86_64/x86, RedHat x86_64/x86 + - BSD: NetBSD x86_64/x86 + +Crypto backends: + - builtin - MIT Kerberos native crypto library + - OpenSSL (1.0\+) - https://www.openssl.org + +Database backends: LDAP, DB2, LMDB + +krb4 support: Kerberos 5 release < 1.8 + +DES support: Kerberos 5 release < 1.18 (See :ref:`retiring-des`) + +Interoperability +---------------- + +`Microsoft` + +Starting from release 1.7: + +* Follow client principal referrals in the client library when + obtaining initial tickets. + +* KDC can issue realm referrals for service principals based on domain names. + +* Extensions supporting DCE RPC, including three-leg GSS context setup + and unencapsulated GSS tokens inside SPNEGO. + +* Microsoft GSS_WrapEX, implemented using the gss_iov API, which is + similar to the equivalent SSPI functionality. This is needed to + support some instances of DCE RPC. + +* NTLM recognition support in GSS-API, to facilitate dropping in an + NTLM implementation for improved compatibility with older releases + of Microsoft Windows. + +* KDC support for principal aliases, if the back end supports them. + Currently, only the LDAP back end supports aliases. + +* Support Microsoft set/change password (:rfc:`3244`) protocol in + kadmind. + +* Implement client and KDC support for GSS_C_DELEG_POLICY_FLAG, which + allows a GSS application to request credential delegation only if + permitted by KDC policy. + + +Starting from release 1.8: + +* Microsoft Services for User (S4U) compatibility + + +`Heimdal` + +* Support for KCM credential cache starting from release 1.13 + +Feature list +------------ + +For more information on the specific project see https://k5wiki.kerberos.org/wiki/Projects + +Release 1.7 + - Credentials delegation :rfc:`5896` + - Cross-realm authentication and referrals :rfc:`6806` + - Master key migration + - PKINIT :rfc:`4556` :ref:`pkinit` + +Release 1.8 + - Anonymous PKINIT :rfc:`6112` :ref:`anonymous_pkinit` + - Constrained delegation + - IAKERB https://tools.ietf.org/html/draft-ietf-krb-wg-iakerb-02 + - Heimdal bridge plugin for KDC backend + - GSS-API S4U extensions https://msdn.microsoft.com/en-us/library/cc246071 + - GSS-API naming extensions :rfc:`6680` + - GSS-API extensions for storing delegated credentials :rfc:`5588` + +Release 1.9 + - Advance warning on password expiry + - Camellia encryption (CTS-CMAC mode) :rfc:`6803` + - KDC support for SecurID preauthentication + - kadmin over IPv6 + - Trace logging :ref:`trace_logging` + - GSSAPI/KRB5 multi-realm support + - Plugin to test password quality :ref:`pwqual_plugin` + - Plugin to synchronize password changes :ref:`kadm5_hook_plugin` + - Parallel KDC + - GSS-API extensions for SASL GS2 bridge :rfc:`5801` :rfc:`5587` + - Purging old keys + - Naming extensions for delegation chain + - Password expiration API + - Windows client support (build-only) + - IPv6 support in iprop + +Release 1.10 + - Plugin interface for configuration :ref:`profile_plugin` + - Credentials for multiple identities :ref:`ccselect_plugin` + +Release 1.11 + - Client support for FAST OTP :rfc:`6560` + - GSS-API extensions for credential locations + - Responder mechanism + +Release 1.12 + - Plugin to control krb5_aname_to_localname and krb5_kuserok behavior :ref:`localauth_plugin` + - Plugin to control hostname-to-realm mappings and the default realm :ref:`hostrealm_plugin` + - GSSAPI extensions for constructing MIC tokens using IOV lists :ref:`gssapi_mic_token` + - Principal may refer to nonexistent policies `Policy Refcount project `_ + - Support for having no long-term keys for a principal `Principals Without Keys project `_ + - Collection support to the KEYRING credential cache type on Linux :ref:`ccache_definition` + - FAST OTP preauthentication module for the KDC which uses RADIUS to validate OTP token values :ref:`otp_preauth` + - Experimental Audit plugin for KDC processing `Audit project `_ + +Release 1.13 + + - Add support for accessing KDCs via an HTTPS proxy server using + the `MS-KKDCP + `_ + protocol. + - Add support for `hierarchical incremental propagation + `_, + where replicas can act as intermediates between an upstream primary + and other downstream replicas. + - Add support for configuring GSS mechanisms using + ``/etc/gss/mech.d/*.conf`` files in addition to + ``/etc/gss/mech``. + - Add support to the LDAP KDB module for `binding to the LDAP + server using SASL + `_. + - The KDC listens for TCP connections by default. + - Fix a minor key disclosure vulnerability where using the + "keepold" option to the kadmin randkey operation could return the + old keys. `[CVE-2014-5351] + `_ + - Add client support for the Kerberos Cache Manager protocol. If + the host is running a Heimdal kcm daemon, caches served by the + daemon can be accessed with the KCM: cache type. + - When built on macOS 10.7 and higher, use "KCM:" as the default + cachetype, unless overridden by command-line options or + krb5-config values. + - Add support for doing unlocked database dumps for the DB2 KDC + back end, which would allow the KDC and kadmind to continue + accessing the database during lengthy database dumps. + +Release 1.14 + + * Administrator experience + + - Add a new kdb5_util tabdump command to provide reporting-friendly + tabular dump formats (tab-separated or CSV) for the KDC database. + Unlike the normal dump format, each output table has a fixed number + of fields. Some tables include human-readable forms of data that + are opaque in ordinary dump files. This format is also suitable for + importing into relational databases for complex queries. + - Add support to kadmin and kadmin.local for specifying a single + command line following any global options, where the command + arguments are split by the shell--for example, "kadmin getprinc + principalname". Commands issued this way do not prompt for + confirmation or display warning messages, and exit with non-zero + status if the operation fails. + - Accept the same principal flag names in kadmin as we do for the + default_principal_flags kdc.conf variable, and vice versa. Also + accept flag specifiers in the form that kadmin prints, as well as + hexadecimal numbers. + - Remove the triple-DES and RC4 encryption types from the default + value of supported_enctypes, which determines the default key and + salt types for new password-derived keys. By default, keys will + only created only for AES128 and AES256. This mitigates some types + of password guessing attacks. + - Add support for directory names in the KRB5_CONFIG and + KRB5_KDC_PROFILE environment variables. + - Add support for authentication indicators, which are ticket + annotations to indicate the strength of the initial authentication. + Add support for the "require_auth" string attribute, which can be + set on server principal entries to require an indicator when + authenticating to the server. + - Add support for key version numbers larger than 255 in keytab files, + and for version numbers up to 65535 in KDC databases. + - Transmit only one ETYPE-INFO and/or ETYPE-INFO2 entry from the KDC + during pre-authentication, corresponding to the client's most + preferred encryption type. + - Add support for server name identification (SNI) when proxying KDC + requests over HTTPS. + - Add support for the err_fmt profile parameter, which can be used to + generate custom-formatted error messages. + + * Developer experience: + + - Change gss_acquire_cred_with_password() to acquire credentials into + a private memory credential cache. Applications can use + gss_store_cred() to make the resulting credentials visible to other + processes. + - Change gss_acquire_cred() and SPNEGO not to acquire credentials for + IAKERB or for non-standard variants of the krb5 mechanism OID unless + explicitly requested. (SPNEGO will still accept the Microsoft + variant of the krb5 mechanism OID during negotiation.) + - Change gss_accept_sec_context() not to accept tokens for IAKERB or + for non-standard variants of the krb5 mechanism OID unless an + acceptor credential is acquired for those mechanisms. + - Change gss_acquire_cred() to immediately resolve credentials if the + time_rec parameter is not NULL, so that a correct expiration time + can be returned. Normally credential resolution is delayed until + the target name is known. + - Add krb5_prepend_error_message() and krb5_wrap_error_message() APIs, + which can be used by plugin modules or applications to add prefixes + to existing detailed error messages. + - Add krb5_c_prfplus() and krb5_c_derive_prfplus() APIs, which + implement the RFC 6113 PRF+ operation and key derivation using PRF+. + - Add support for pre-authentication mechanisms which use multiple + round trips, using the the KDC_ERR_MORE_PREAUTH_DATA_REQUIRED error + code. Add get_cookie() and set_cookie() callbacks to the kdcpreauth + interface; these callbacks can be used to save marshalled state + information in an encrypted cookie for the next request. + - Add a client_key() callback to the kdcpreauth interface to retrieve + the chosen client key, corresponding to the ETYPE-INFO2 entry sent + by the KDC. + - Add an add_auth_indicator() callback to the kdcpreauth interface, + allowing pre-authentication modules to assert authentication + indicators. + - Add support for the GSS_KRB5_CRED_NO_CI_FLAGS_X cred option to + suppress sending the confidentiality and integrity flags in GSS + initiator tokens unless they are requested by the caller. These + flags control the negotiated SASL security layer for the Microsoft + GSS-SPNEGO SASL mechanism. + - Make the FILE credential cache implementation less prone to + corruption issues in multi-threaded programs, especially on + platforms with support for open file description locks. + + * Performance: + + - On replica KDCs, poll the primary KDC immediately after + processing a full resync, and do not require two full resyncs + after the primary KDC's log file is reset. + +Release 1.15 + +* Administrator experience: + + - Add support to kadmin for remote extraction of current keys + without changing them (requires a special kadmin permission that + is excluded from the wildcard permission), with the exception of + highly protected keys. + + - Add a lockdown_keys principal attribute to prevent retrieval of + the principal's keys (old or new) via the kadmin protocol. In + newly created databases, this attribute is set on the krbtgt and + kadmin principals. + + - Restore recursive dump capability for DB2 back end, so sites can + more easily recover from database corruption resulting from power + failure events. + + - Add DNS auto-discovery of KDC and kpasswd servers from URI + records, in addition to SRV records. URI records can convey TCP + and UDP servers and primary KDC status in a single DNS lookup, and + can also point to HTTPS proxy servers. + + - Add support for password history to the LDAP back end. + + - Add support for principal renaming to the LDAP back end. + + - Use the getrandom system call on supported Linux kernels to avoid + blocking problems when getting entropy from the operating system. + +* Code quality: + + - Clean up numerous compilation warnings. + + - Remove various infrequently built modules, including some preauth + modules that were not built by default. + +* Developer experience: + + - Add support for building with OpenSSL 1.1. + + - Use SHA-256 instead of MD5 for (non-cryptographic) hashing of + authenticators in the replay cache. This helps sites that must + build with FIPS 140 conformant libraries that lack MD5. + +* Protocol evolution: + + - Add support for the AES-SHA2 enctypes, which allows sites to + conform to Suite B crypto requirements. + +Release 1.16 + +* Administrator experience: + + - The KDC can match PKINIT client certificates against the + "pkinit_cert_match" string attribute on the client principal + entry, using the same syntax as the existing "pkinit_cert_match" + profile option. + + - The ktutil addent command supports the "-k 0" option to ignore the + key version, and the "-s" option to use a non-default salt string. + + - kpropd supports a --pid-file option to write a pid file at + startup, when it is run in standalone mode. + + - The "encrypted_challenge_indicator" realm option can be used to + attach an authentication indicator to tickets obtained using FAST + encrypted challenge pre-authentication. + + - Localization support can be disabled at build time with the + --disable-nls configure option. + +* Developer experience: + + - The kdcpolicy pluggable interface allows modules control whether + tickets are issued by the KDC. + + - The kadm5_auth pluggable interface allows modules to control + whether kadmind grants access to a kadmin request. + + - The certauth pluggable interface allows modules to control which + PKINIT client certificates can authenticate to which client + principals. + + - KDB modules can use the client and KDC interface IP addresses to + determine whether to allow an AS request. + + - GSS applications can query the bit strength of a krb5 GSS context + using the GSS_C_SEC_CONTEXT_SASL_SSF OID with + gss_inquire_sec_context_by_oid(). + + - GSS applications can query the impersonator name of a krb5 GSS + credential using the GSS_KRB5_GET_CRED_IMPERSONATOR OID with + gss_inquire_cred_by_oid(). + + - kdcpreauth modules can query the KDC for the canonicalized + requested client principal name, or match a principal name against + the requested client principal name with canonicalization. + +* Protocol evolution: + + - The client library will continue to try pre-authentication + mechanisms after most failure conditions. + + - The KDC will issue trivially renewable tickets (where the + renewable lifetime is equal to or less than the ticket lifetime) + if requested by the client, to be friendlier to scripts. + + - The client library will use a random nonce for TGS requests + instead of the current system time. + + - For the RC4 string-to-key or PAC operations, UTF-16 is supported + (previously only UCS-2 was supported). + + - When matching PKINIT client certificates, UPN SANs will be matched + correctly as UPNs, with canonicalization. + +* User experience: + + - Dates after the year 2038 are accepted (provided that the platform + time facilities support them), through the year 2106. + + - Automatic credential cache selection based on the client realm + will take into account the fallback realm and the service + hostname. + + - Referral and alternate cross-realm TGTs will not be cached, + avoiding some scenarios where they can be added to the credential + cache multiple times. + + - A German translation has been added. + +* Code quality: + + - The build is warning-clean under clang with the configured warning + options. + + - The automated test suite runs cleanly under AddressSanitizer. + +Release 1.17 + +* Administrator experience: + + - A new Kerberos database module using the Lightning Memory-Mapped + Database library (LMDB) has been added. The LMDB KDB module + should be more performant and more robust than the DB2 module, and + may become the default module for new databases in a future + release. + + - "kdb5_util dump" will no longer dump policy entries when specific + principal names are requested. + +* Developer experience: + + - The new krb5_get_etype_info() API can be used to retrieve enctype, + salt, and string-to-key parameters from the KDC for a client + principal. + + - The new GSS_KRB5_NT_ENTERPRISE_NAME name type allows enterprise + principal names to be used with GSS-API functions. + + - KDC and kadmind modules which call com_err() will now write to the + log file in a format more consistent with other log messages. + + - Programs which use large numbers of memory credential caches + should perform better. + +* Protocol evolution: + + - The SPAKE pre-authentication mechanism is now supported. This + mechanism protects against password dictionary attacks without + requiring any additional infrastructure such as certificates. + SPAKE is enabled by default on clients, but must be manually + enabled on the KDC for this release. + + - PKINIT freshness tokens are now supported. Freshness tokens can + protect against scenarios where an attacker uses temporary access + to a smart card to generate authentication requests for the + future. + + - Password change operations now prefer TCP over UDP, to avoid + spurious error messages about replays when a response packet is + dropped. + + - The KDC now supports cross-realm S4U2Self requests when used with + a third-party KDB module such as Samba's. The client code for + cross-realm S4U2Self requests is also now more robust. + +* User experience: + + - The new ktutil addent -f flag can be used to fetch salt + information from the KDC for password-based keys. + + - The new kdestroy -p option can be used to destroy a credential + cache within a collection by client principal name. + + - The Kerberos man page has been restored, and documents the + environment variables that affect programs using the Kerberos + library. + +* Code quality: + + - Python test scripts now use Python 3. + + - Python test scripts now display markers in verbose output, making + it easier to find where a failure occurred within the scripts. + + - The Windows build system has been simplified and updated to work + with more recent versions of Visual Studio. A large volume of + unused Windows-specific code has been removed. Visual Studio 2013 + or later is now required. + +Release 1.18 + +* Administrator experience: + + - Remove support for single-DES encryption types. + + - Change the replay cache format to be more efficient and robust. + Replay cache filenames using the new format end with ``.rcache2`` + by default. + + - setuid programs will automatically ignore environment variables + that normally affect krb5 API functions, even if the caller does + not use krb5_init_secure_context(). + + - Add an ``enforce_ok_as_delegate`` krb5.conf relation to disable + credential forwarding during GSSAPI authentication unless the KDC + sets the ok-as-delegate bit in the service ticket. + +* Developer experience: + + - Implement krb5_cc_remove_cred() for all credential cache types. + + - Add the krb5_pac_get_client_info() API to get the client account + name from a PAC. + +* Protocol evolution: + + - Add KDC support for S4U2Self requests where the user is identified + by X.509 certificate. (Requires support for certificate lookup + from a third-party KDB module.) + + - Remove support for an old ("draft 9") variant of PKINIT. + + - Add support for Microsoft NegoEx. (Requires one or more + third-party GSS modules implementing NegoEx mechanisms.) + +* User experience: + + - Add support for ``dns_canonicalize_hostname=fallback``, causing + host-based principal names to be tried first without DNS + canonicalization, and again with DNS canonicalization if the + un-canonicalized server is not found. + + - Expand single-component hostnames in hhost-based principal names + when DNS canonicalization is not used, adding the system's first + DNS search path as a suffix. Add a ``qualify_shortname`` + krb5.conf relation to override this suffix or disable expansion. + +* Code quality: + + - The libkrb5 serialization code (used to export and import krb5 GSS + security contexts) has been simplified and made type-safe. + + - The libkrb5 code for creating KRB-PRIV, KRB-SAFE, and KRB-CRED + messages has been revised to conform to current coding practices. + + - The test suite has been modified to work with macOS System + Integrity Protection enabled. + + - The test suite incorporates soft-pkcs11 so that PKINIT PKCS11 + support can always be tested. + +Release 1.19 + +* Administrator experience: + + - When a client keytab is present, the GSSAPI krb5 mech will refresh + credentials even if the current credentials were acquired + manually. + + - It is now harder to accidentally delete the K/M entry from a KDB. + +* Developer experience: + + - gss_acquire_cred_from() now supports the "password" and "verify" + options, allowing credentials to be acquired via password and + verified using a keytab key. + + - When an application accepts a GSS security context, the new + GSS_C_CHANNEL_BOUND_FLAG will be set if the initiator and acceptor + both provided matching channel bindings. + + - Added the GSS_KRB5_NT_X509_CERT name type, allowing S4U2Self + requests to identify the desired client principal by certificate. + + - PKINIT certauth modules can now cause the hw-authent flag to be + set in issued tickets. + + - The krb5_init_creds_step() API will now issue the same password + expiration warnings as krb5_get_init_creds_password(). + +* Protocol evolution: + + - Added client and KDC support for Microsoft's Resource-Based + Constrained Delegation, which allows cross-realm S4U2Proxy + requests. A third-party database module is required for KDC + support. + + - kadmin/admin is now the preferred server principal name for kadmin + connections, and the host-based form is no longer created by + default. The client will still try the host-based form as a + fallback. + + - Added client and server support for Microsoft's + KERB_AP_OPTIONS_CBT extension, which causes channel bindings to be + required for the initiator if the acceptor provided them. The + client will send this option if the client_aware_gss_bindings + profile option is set. + +User experience: + + - The default setting of dns_canonicalize_realm is now "fallback". + Hostnames provided from applications will be tried in principal + names as given (possibly with shortname qualification), falling + back to the canonicalized name. + + - kinit will now issue a warning if the des3-cbc-sha1 encryption + type is used in the reply. This encryption type will be + deprecated and removed in future releases. + + - Added kvno flags --out-cache, --no-store, and --cached-only + (inspired by Heimdal's kgetcred). + +Release 1.20 + +* Administrator experience: + + - Added a "disable_pac" realm relation to suppress adding PAC + authdata to tickets, for realms which do not need to support S4U + requests. + + - Most credential cache types will use atomic replacement when a + cache is reinitialized using kinit or refreshed from the client + keytab. + + - kprop can now propagate databases with a dump size larger than + 4GB, if both the client and server are upgraded. + + - kprop can now work over NATs that change the destination IP + address, if the client is upgraded. + +* Developer experience: + + - Updated the KDB interface. The sign_authdata() method is replaced + with the issue_pac() method, allowing KDB modules to add logon + info and other buffers to the PAC issued by the KDC. + + - Host-based initiator names are better supported in the GSS krb5 + mechanism. + +* Protocol evolution: + + - Replaced AD-SIGNEDPATH authdata with minimal PACs. + + - To avoid spurious replay errors, password change requests will not + be attempted over UDP until the attempt over TCP fails. + + - PKINIT will sign its CMS messages with SHA-256 instead of SHA-1. + +* Code quality: + + - Updated all code using OpenSSL to be compatible with OpenSSL 3. + + - Reorganized the libk5crypto build system to allow the OpenSSL + back-end to pull in material from the builtin back-end depending + on the OpenSSL version. + + - Simplified the PRNG logic to always use the platform PRNG. + + - Converted the remaining Tcl tests to Python. + +Release 1.21 + +* User experience: + + - Added a credential cache type providing compatibility with the + macOS 11 native credential cache. + +* Developer experience: + + - libkadm5 will use the provided krb5_context object to read + configuration values, instead of creating its own. + + - Added an interface to retrieve the ticket session key from a GSS + context. + +* Protocol evolution: + + - The KDC will no longer issue tickets with RC4 or triple-DES + session keys unless explicitly configured with the new allow_rc4 + or allow_des3 variables respectively. + + - The KDC will assume that all services can handle aes256-sha1 + session keys unless the service principal has a session_enctypes + string attribute. + + - Support for PAC full KDC checksums has been added to mitigate an + S4U2Proxy privilege escalation attack. + + - The PKINIT client will advertise a more modern set of supported + CMS algorithms. + +* Code quality: + + - Removed unused code in libkrb5, libkrb5support, and the PKINIT + module. + + - Modernized the KDC code for processing TGS requests, the code for + encrypting and decrypting key data, the PAC handling code, and the + GSS library packet parsing and composition code. + + - Improved the test framework's detection of memory errors in daemon + processes when used with asan. + +`Pre-authentication mechanisms` + +- PW-SALT :rfc:`4120#section-5.2.7.3` +- ENC-TIMESTAMP :rfc:`4120#section-5.2.7.2` +- SAM-2 +- FAST negotiation framework (release 1.8) :rfc:`6113` +- PKINIT with FAST on client (release 1.10) :rfc:`6113` +- PKINIT :rfc:`4556` +- FX-COOKIE :rfc:`6113#section-5.2` +- S4U-X509-USER (release 1.8) https://msdn.microsoft.com/en-us/library/cc246091 +- OTP (release 1.12) :ref:`otp_preauth` +- SPAKE (release 1.17) :ref:`spake` diff --git a/krb5-1.21.3/doc/html/_sources/mitK5license.rst.txt b/krb5-1.21.3/doc/html/_sources/mitK5license.rst.txt new file mode 100644 index 00000000..e23edbfb --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/mitK5license.rst.txt @@ -0,0 +1,11 @@ +.. _mitK5license: + +MIT Kerberos License information +================================ + +.. toctree:: + :hidden: + + copyright.rst + +.. include:: notice.rst diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/ccselect.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/ccselect.rst.txt new file mode 100644 index 00000000..1253fe6b --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/ccselect.rst.txt @@ -0,0 +1,28 @@ +.. _ccselect_plugin: + +Credential cache selection interface (ccselect) +=============================================== + +The ccselect interface allows modules to control how credential caches +are chosen when a GSSAPI client contacts a service. For a detailed +description of the ccselect interface, see the header file +````. + +The primary ccselect method is **choose**, which accepts a server +principal as input and returns a ccache and/or principal name as +output. A module can use the krb5_cccol APIs to iterate over the +cache collection in order to find an appropriate ccache to use. + +.. TODO: add reference to the admin guide for ccaches and cache + collections when we have appropriate sections. + +A module can create and destroy per-library-context state objects by +implementing the **init** and **fini** methods. State objects have +the type krb5_ccselect_moddata, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object. + +A module can have one of two priorities, "authoritative" or +"heuristic". Results from authoritative modules, if any are +available, will take priority over results from heuristic modules. A +module communicates its priority as a result of the **init** method. diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/certauth.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/certauth.rst.txt new file mode 100644 index 00000000..3740c5f7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/certauth.rst.txt @@ -0,0 +1,36 @@ +.. _certauth_plugin: + +PKINIT certificate authorization interface (certauth) +===================================================== + +The certauth interface was first introduced in release 1.16. It +allows customization of the X.509 certificate attribute requirements +placed on certificates used by PKINIT enabled clients. For a detailed +description of the certauth interface, see the header file +```` + +A certauth module implements the **authorize** method to determine +whether a client's certificate is authorized to authenticate a client +principal. **authorize** receives the DER-encoded certificate, the +requested client principal, and a pointer to the client's +krb5_db_entry (for modules that link against libkdb5). The method +must decode the certificate and inspect its attributes to determine if +it should authorize PKINIT authentication. It returns the +authorization status and optionally outputs a list of authentication +indicator strings to be added to the ticket. + +Beginning in release 1.19, the authorize method can request that the +hardware authentication bit be set in the ticket by returning +**KRB5_CERTAUTH_HWAUTH**. Beginning in release 1.20, the authorize +method can return **KRB5_CERTAUTH_HWAUTH_PASS** to request that the +hardware authentication bit be set in the ticket but otherwise defer +authorization to another certauth module. A module must use its own +internal or library-provided ASN.1 certificate decoder. + +A module can optionally create and destroy module data with the +**init** and **fini** methods. Module data objects last for the +lifetime of the KDC process. + +If a module allocates and returns a list of authentication indicators +from **authorize**, it must also implement the **free_ind** method +to free the list. diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/clpreauth.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/clpreauth.rst.txt new file mode 100644 index 00000000..38aa52e8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/clpreauth.rst.txt @@ -0,0 +1,54 @@ +Client preauthentication interface (clpreauth) +============================================== + +During an initial ticket request, a KDC may ask a client to prove its +knowledge of the password before issuing an encrypted ticket, or to +use credentials other than a password. This process is called +preauthentication, and is described in :rfc:`4120` and :rfc:`6113`. +The clpreauth interface allows the addition of client support for +preauthentication mechanisms beyond those included in the core MIT +krb5 code base. For a detailed description of the clpreauth +interface, see the header file ```` (or +```` before release 1.12). + +A clpreauth module is generally responsible for: + +* Supplying a list of preauth type numbers used by the module in the + **pa_type_list** field of the vtable structure. + +* Indicating what kind of preauthentication mechanism it implements, + with the **flags** method. In the most common case, this method + just returns ``PA_REAL``, indicating that it implements a normal + preauthentication type. + +* Examining the padata information included in a PREAUTH_REQUIRED or + MORE_PREAUTH_DATA_REQUIRED error and producing padata values for the + next AS request. This is done with the **process** method. + +* Examining the padata information included in a successful ticket + reply, possibly verifying the KDC identity and computing a reply + key. This is also done with the **process** method. + +* For preauthentication types which support it, recovering from errors + by examining the error data from the KDC and producing a padata + value for another AS request. This is done with the **tryagain** + method. + +* Receiving option information (supplied by ``kinit -X`` or by an + application), with the **gic_opts** method. + +A clpreauth module can create and destroy per-library-context and +per-request state objects by implementing the **init**, **fini**, +**request_init**, and **request_fini** methods. Per-context state +objects have the type krb5_clpreauth_moddata, and per-request state +objects have the type krb5_clpreauth_modreq. These are abstract +pointer types; a module should typically cast these to internal +types for the state objects. + +The **process** and **tryagain** methods have access to a callback +function and handle (called a "rock") which can be used to get +additional information about the current request, including the +expected enctype of the AS reply, the FAST armor key, and the client +long-term key (prompting for the user password if necessary). A +callback can also be used to replace the AS reply key if the +preauthentication mechanism computes one. diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/general.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/general.rst.txt new file mode 100644 index 00000000..fba9bf6e --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/general.rst.txt @@ -0,0 +1,118 @@ +General plugin concepts +======================= + +A krb5 dynamic plugin module is a Unix shared object or Windows DLL. +Typically, the source code for a dynamic plugin module should live in +its own project with a build system using automake_ and libtool_, or +tools with similar functionality. + +A plugin module must define a specific symbol name, which depends on +the pluggable interface and module name. For most pluggable +interfaces, the exported symbol is a function named +``INTERFACE_MODULE_initvt``, where *INTERFACE* is the name of the +pluggable interface and *MODULE* is the name of the module. For these +interfaces, it is possible for one shared object or DLL to implement +multiple plugin modules, either for the same pluggable interface or +for different ones. For example, a shared object could implement both +KDC and client preauthentication mechanisms, by exporting functions +named ``kdcpreauth_mymech_initvt`` and ``clpreauth_mymech_initvt``. + +.. note: The profile, locate, and GSSAPI mechglue pluggable interfaces + follow different conventions. See the documentation for + those interfaces for details. The remainder of this section + applies to pluggable interfaces which use the standard + conventions. + +A plugin module implementation should include the header file +````, where *INTERFACE* is the name of the +pluggable interface. For instance, a ccselect plugin module +implementation should use ``#include ``. + +.. note: clpreauth and kdcpreauth module implementations should + include . + +initvt functions have the following prototype:: + + krb5_error_code interface_modname_initvt(krb5_context context, + int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +and should do the following: + +1. Check that the supplied maj_ver argument is supported by the + module. If it is not supported, the function should return + KRB5_PLUGIN_VER_NOTSUPP. + +2. Cast the supplied vtable pointer to the structure type + corresponding to the major version, as documented in the pluggable + interface header file. + +3. Fill in the structure fields with pointers to method functions and + static data, stopping at the field indicated by the supplied minor + version. Fields for unimplemented optional methods can be left + alone; it is not necessary to initialize them to NULL. + +In most cases, the context argument will not be used. The initvt +function should not allocate memory; think of it as a glorified +structure initializer. Each pluggable interface defines methods for +allocating and freeing module state if doing so is necessary for the +interface. + +Pluggable interfaces typically include a **name** field in the vtable +structure, which should be filled in with a pointer to a string +literal containing the module name. + +Here is an example of what an initvt function might look like for a +fictional pluggable interface named fences, for a module named +"wicker":: + + krb5_error_code + fences_wicker_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) + { + krb5_ccselect_vtable vt; + + if (maj_ver == 1) { + krb5_fences_vtable vt = (krb5_fences_vtable)vtable; + vt->name = "wicker"; + vt->slats = wicker_slats; + vt->braces = wicker_braces; + } else if (maj_ver == 2) { + krb5_fences_vtable_v2 vt = (krb5_fences_vtable_v2)vtable; + vt->name = "wicker"; + vt->material = wicker_material; + vt->construction = wicker_construction; + if (min_ver < 2) + return 0; + vt->footing = wicker_footing; + if (min_ver < 3) + return 0; + vt->appearance = wicker_appearance; + } else { + return KRB5_PLUGIN_VER_NOTSUPP; + } + return 0; + } + +Logging from KDC and kadmind plugin modules +------------------------------------------- + +Plugin modules for the KDC or kadmind daemons can write to the +configured logging outputs (see :ref:`logging`) by calling the +**com_err** function. The first argument (*whoami*) is ignored. If +the second argument (*code*) is zero, the formatted message is logged +at informational severity; otherwise, the formatted message is logged +at error severity and includes the error message for the supplied +code. Here are examples:: + + com_err("", 0, "Client message contains %d items", nitems); + com_err("", retval, "while decoding client message"); + +(The behavior described above is new in release 1.17. In prior +releases, the *whoami* argument is included for some logging output +types, the logged message does not include the usual header for some +output types, and the severity for syslog outputs is configured as +part of the logging specification, defaulting to error severity.) + +.. _automake: https://www.gnu.org/software/automake/ +.. _libtool: https://www.gnu.org/software/libtool/ diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/gssapi.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/gssapi.rst.txt new file mode 100644 index 00000000..0918d151 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/gssapi.rst.txt @@ -0,0 +1,134 @@ +GSSAPI mechanism interface +========================== + +The GSSAPI library in MIT krb5 can load mechanism modules to augment +the set of built-in mechanisms. + +.. note: The GSSAPI loadable mechanism interface does not follow the + normal conventions for MIT krb5 pluggable interfaces. + +A mechanism module is a Unix shared object or Windows DLL, built +separately from the krb5 tree. Modules are loaded according to the +GSS mechanism config files described in :ref:`gssapi_plugin_config`. + +For the most part, a GSSAPI mechanism module exports the same +functions as would a GSSAPI implementation itself, with the same +function signatures. The mechanism selection layer within the GSSAPI +library (called the "mechglue") will dispatch calls from the +application to the module if the module's mechanism is requested. If +a module does not wish to implement a GSSAPI extension, it can simply +refrain from exporting it, and the mechglue will fail gracefully if +the application calls that function. + +The mechglue does not invoke a module's **gss_add_cred**, +**gss_add_cred_from**, **gss_add_cred_impersonate_name**, or +**gss_add_cred_with_password** function. A mechanism only needs to +implement the "acquire" variants of those functions. + +A module does not need to coordinate its minor status codes with those +of other mechanisms. If the mechglue detects conflicts, it will map +the mechanism's status codes onto unique values, and then map them +back again when **gss_display_status** is called. + + +NegoEx modules +-------------- + +Some Windows GSSAPI mechanisms can only be negotiated via a Microsoft +extension to SPNEGO called NegoEx. Beginning with release 1.18, +mechanism modules can support NegoEx as follows: + +* Implement the gssspi_query_meta_data(), gssspi_exchange_meta_data(), + and gssspi_query_mechanism_info() SPIs declared in + ````. + +* Implement gss_inquire_sec_context_by_oid() and answer the + **GSS_C_INQ_NEGOEX_KEY** and **GSS_C_INQ_NEGOEX_VERIFY_KEY** OIDs + to provide the checksum keys for outgoing and incoming checksums, + respectively. The answer must be in two buffers: the first buffer + contains the key contents, and the second buffer contains the key + encryption type as a four-byte little-endian integer. + +By default, NegoEx mechanisms will not be directly negotiated via +SPNEGO. If direct SPNEGO negotiation is required for +interoperability, implement gss_inquire_attrs_for_mech() and assert +the GSS_C_MA_NEGOEX_AND_SPNEGO attribute (along with any applicable +RFC 5587 attributes). + + +Interposer modules +------------------ + +The mechglue also supports a kind of loadable module, called an +interposer module, which intercepts calls to existing mechanisms +rather than implementing a new mechanism. + +An interposer module must export the symbol **gss_mech_interposer** +with the following signature:: + + gss_OID_set gss_mech_interposer(gss_OID mech_type); + +This function is invoked with the OID of the interposer mechanism as +specified in the mechanism config file, and returns a set of mechanism +OIDs to be interposed. The returned OID set must have been created +using the mechglue's gss_create_empty_oid_set and +gss_add_oid_set_member functions. + +An interposer module must use the prefix ``gssi_`` for the GSSAPI +functions it exports, instead of the prefix ``gss_``. In most cases, +unexported ``gssi_`` functions will result in failure from their +corresponding ``gss_`` calls. + +An interposer module can link against the GSSAPI library in order to +make calls to the original mechanism. To do so, it must specify a +special mechanism OID which is the concatention of the interposer's +own OID byte string and the original mechanism's OID byte string. + +Functions that do not accept a mechanism argument directly require no +special handling, with the following exceptions: + +Since **gss_accept_sec_context** does not accept a mechanism argument, +an interposer mechanism must, in order to invoke the original +mechanism's function, acquire a credential for the concatenated OID +and pass that as the *verifier_cred_handle* parameter. + +Since **gss_import_name**, **gss_import_cred**, and +**gss_import_sec_context** do not accept mechanism parameters, the SPI +has been extended to include variants which do. This allows the +interposer module to know which mechanism should be used to interpret +the token. These functions have the following signatures:: + + OM_uint32 gssi_import_sec_context_by_mech(OM_uint32 *minor_status, + gss_OID desired_mech, gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle); + + OM_uint32 gssi_import_name_by_mech(OM_uint32 *minor_status, + gss_OID mech_type, gss_buffer_t input_name_buffer, + gss_OID input_name_type, gss_name_t output_name); + + OM_uint32 gssi_import_cred_by_mech(OM_uint32 *minor_status, + gss_OID mech_type, gss_buffer_t token, + gss_cred_id_t *cred_handle); + +To re-enter the original mechanism when importing tokens for the above +functions, the interposer module must wrap the mechanism token in the +mechglue's format, using the concatenated OID (except in +**gss_import_name**). The mechglue token formats are: + +* For **gss_import_sec_context**, a four-byte OID length in big-endian + order, followed by the concatenated OID, followed by the mechanism + token. + +* For **gss_import_name**, the bytes 04 01, followed by a two-byte OID + length in big-endian order, followed by the mechanism OID, followed + by a four-byte token length in big-endian order, followed by the + mechanism token. Unlike most uses of OIDs in the API, the mechanism + OID encoding must include the DER tag and length for an object + identifier (06 followed by the DER length of the OID byte string), + and this prefix must be included in the two-byte OID length. + input_name_type must also be set to GSS_C_NT_EXPORT_NAME. + +* For **gss_import_cred**, a four-byte OID length in big-endian order, + followed by the concatenated OID, followed by a four-byte token + length in big-endian order, followed by the mechanism token. This + sequence may be repeated multiple times. diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/hostrealm.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/hostrealm.rst.txt new file mode 100644 index 00000000..4d488ef7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/hostrealm.rst.txt @@ -0,0 +1,39 @@ +.. _hostrealm_plugin: + +Host-to-realm interface (hostrealm) +=================================== + +The host-to-realm interface was first introduced in release 1.12. It +allows modules to control the local mapping of hostnames to realm +names as well as the default realm. For a detailed description of the +hostrealm interface, see the header file +````. + +Although the mapping methods in the hostrealm interface return a list +of one or more realms, only the first realm in the list is currently +used by callers. Callers may begin using later responses in the +future. + +Any mapping method may return KRB5_PLUGIN_NO_HANDLE to defer +processing to a later module. + +A module can create and destroy per-library-context state objects +using the **init** and **fini** methods. If the module does not need +any state, it does not need to implement these methods. + +The optional **host_realm** method allows a module to determine +authoritative realm mappings for a hostname. The first authoritative +mapping is used in preference to KDC referrals when getting service +credentials. + +The optional **fallback_realm** method allows a module to determine +fallback mappings for a hostname. The first fallback mapping is tried +if there is no authoritative mapping for a realm, and KDC referrals +failed to produce a successful result. + +The optional **default_realm** method allows a module to determine the +local default realm. + +If a module implements any of the above methods, it must also +implement **free_list** to ensure that memory is allocated and +deallocated consistently. diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/index.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/index.rst.txt new file mode 100644 index 00000000..5e783463 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/index.rst.txt @@ -0,0 +1,38 @@ +For plugin module developers +============================ + +Kerberos plugin modules allow increased control over MIT krb5 library +and server behavior. This guide describes how to create dynamic +plugin modules and the currently available pluggable interfaces. + +See :ref:`plugin_config` for information on how to register dynamic +plugin modules and how to enable and disable modules via +:ref:`krb5.conf(5)`. + +.. TODO: update the above reference when we have a free-form section + in the admin guide about plugin configuration + + +Contents +-------- + +.. toctree:: + :maxdepth: 2 + + general.rst + clpreauth.rst + kdcpreauth.rst + ccselect.rst + pwqual.rst + kadm5_hook.rst + kadm5_auth.rst + hostrealm.rst + localauth.rst + locate.rst + profile.rst + gssapi.rst + internal.rst + certauth.rst + kdcpolicy.rst + +.. TODO: GSSAPI mechanism plugins diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/internal.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/internal.rst.txt new file mode 100644 index 00000000..99e30bb7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/internal.rst.txt @@ -0,0 +1,32 @@ +Internal pluggable interfaces +============================= + +Following are brief discussions of pluggable interfaces which have not +yet been made public. These interfaces are functional, but the +interfaces are likely to change in incompatible ways from release to +release. In some cases, it may be necessary to copy header files from +the krb5 source tree to use an internal interface. Use these with +care, and expect to need to update your modules for each new release +of MIT krb5. + + +Kerberos database interface (KDB) +--------------------------------- + +A KDB module implements a database back end for KDC principal and +policy information, and can also control many aspects of KDC behavior. +For a full description of the interface, see the header file +````. + +The KDB pluggable interface is often referred to as the DAL (Database +Access Layer). + + +Authorization data interface (authdata) +--------------------------------------- + +The authdata interface allows a module to provide (from the KDC) or +consume (in application servers) authorization data of types beyond +those handled by the core MIT krb5 code base. The interface is +defined in the header file ````, which is not +installed by the build. diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/kadm5_auth.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/kadm5_auth.rst.txt new file mode 100644 index 00000000..b4839617 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/kadm5_auth.rst.txt @@ -0,0 +1,35 @@ +.. _kadm5_auth_plugin: + +kadmin authorization interface (kadm5_auth) +=========================================== + +The kadm5_auth interface (new in release 1.16) allows modules to +determine whether a client principal is authorized to perform an +operation in the kadmin protocol, and to apply restrictions to +principal operations. For a detailed description of the kadm5_auth +interface, see the header file ````. + +A module can create and destroy per-process state objects by +implementing the **init** and **fini** methods. State objects have +the type kadm5_auth_modinfo, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object. + +The kadm5_auth interface has one method for each kadmin operation, +with parameters specific to the operation. Each method can return +either 0 to authorize access, KRB5_PLUGIN_NO_HANDLE to defer the +decision to other modules, or another error (canonically EPERM) to +authoritatively deny access. Access is granted if at least one module +grants access and no module authoritatively denies access. + +The **addprinc** and **modprinc** methods can also impose restrictions +on the principal operation by returning a ``struct +kadm5_auth_restrictions`` object. The module should also implement +the **free_restrictions** method if it dynamically allocates +restrictions objects for principal operations. + +kadm5_auth modules can optionally inspect principal or policy objects. +To do this, the module must also include ```` to gain +access to the structure definitions for those objects. As the kadmin +interface is explicitly not as stable as other public interfaces, +modules which do this may not retain compatibility across releases. diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/kadm5_hook.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/kadm5_hook.rst.txt new file mode 100644 index 00000000..ece3eacf --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/kadm5_hook.rst.txt @@ -0,0 +1,27 @@ +.. _kadm5_hook_plugin: + +KADM5 hook interface (kadm5_hook) +================================= + +The kadm5_hook interface allows modules to perform actions when +changes are made to the Kerberos database through :ref:`kadmin(1)`. +For a detailed description of the kadm5_hook interface, see the header +file ````. + +The kadm5_hook interface has five primary methods: **chpass**, +**create**, **modify**, **remove**, and **rename**. (The **rename** +method was introduced in release 1.14.) Each of these methods is +called twice when the corresponding administrative action takes place, +once before the action is committed and once afterwards. A module can +prevent the action from taking place by returning an error code during +the pre-commit stage. + +A module can create and destroy per-process state objects by +implementing the **init** and **fini** methods. State objects have +the type kadm5_hook_modinfo, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object. + +Because the kadm5_hook interface is tied closely to the kadmin +interface (which is explicitly unstable), it may not remain as stable +across versions as other public pluggable interfaces. diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/kdcpolicy.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/kdcpolicy.rst.txt new file mode 100644 index 00000000..74f21f08 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/kdcpolicy.rst.txt @@ -0,0 +1,24 @@ +.. _kdcpolicy_plugin: + +KDC policy interface (kdcpolicy) +================================ + +The kdcpolicy interface was first introduced in release 1.16. It +allows modules to veto otherwise valid AS and TGS requests or restrict +the lifetime and renew time of the resulting ticket. For a detailed +description of the kdcpolicy interface, see the header file +````. + +The optional **check_as** and **check_tgs** functions allow the module +to perform access control. Additionally, a module can create and +destroy module data with the **init** and **fini** methods. Module +data objects last for the lifetime of the KDC process, and are +provided to all other methods. The data has the type +krb5_kdcpolicy_moddata, which should be cast to the appropriate +internal type. + +kdcpolicy modules can optionally inspect principal entries. To do +this, the module must also include ```` to gain access to the +principal entry structure definition. As the KDB interface is +explicitly not as stable as other public interfaces, modules which do +this may not retain compatibility across releases. diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/kdcpreauth.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/kdcpreauth.rst.txt new file mode 100644 index 00000000..ab7f3a90 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/kdcpreauth.rst.txt @@ -0,0 +1,79 @@ +KDC preauthentication interface (kdcpreauth) +============================================ + +The kdcpreauth interface allows the addition of KDC support for +preauthentication mechanisms beyond those included in the core MIT +krb5 code base. For a detailed description of the kdcpreauth +interface, see the header file ```` (or +```` before release 1.12). + +A kdcpreauth module is generally responsible for: + +* Supplying a list of preauth type numbers used by the module in the + **pa_type_list** field of the vtable structure. + +* Indicating what kind of preauthentication mechanism it implements, + with the **flags** method. If the mechanism computes a new reply + key, it must specify the ``PA_REPLACES_KEY`` flag. If the mechanism + is generally only used with hardware tokens, the ``PA_HARDWARE`` + flag allows the mechanism to work with principals which have the + **requires_hwauth** flag set. + +* Producing a padata value to be sent with a preauth_required error, + with the **edata** method. + +* Examining a padata value sent by a client and verifying that it + proves knowledge of the appropriate client credential information. + This is done with the **verify** method. + +* Producing a padata response value for the client, and possibly + computing a reply key. This is done with the **return_padata** + method. + +A module can create and destroy per-KDC state objects by implementing +the **init** and **fini** methods. Per-KDC state objects have the +type krb5_kdcpreauth_moddata, which is an abstract pointer types. A +module should typically cast this to an internal type for the state +object. + +A module can create a per-request state object by returning one in the +**verify** method, receiving it in the **return_padata** method, and +destroying it in the **free_modreq** method. Note that these state +objects only apply to the processing of a single AS request packet, +not to an entire authentication exchange (since an authentication +exchange may remain unfinished by the client or may involve multiple +different KDC hosts). Per-request state objects have the type +krb5_kdcpreauth_modreq, which is an abstract pointer type. + +The **edata**, **verify**, and **return_padata** methods have access +to a callback function and handle (called a "rock") which can be used +to get additional information about the current request, including the +maximum allowable clock skew, the client's long-term keys, the +DER-encoded request body, the FAST armor key, string attributes on the +client's database entry, and the client's database entry itself. The +**verify** method can assert one or more authentication indicators to +be included in the issued ticket using the ``add_auth_indicator`` +callback (new in release 1.14). + +A module can generate state information to be included with the next +client request using the ``set_cookie`` callback (new in release +1.14). On the next request, the module can read this state +information using the ``get_cookie`` callback. Cookie information is +encrypted, timestamped, and transmitted to the client in a +``PA-FX-COOKIE`` pa-data item. Older clients may not support cookies +and therefore may not transmit the cookie in the next request; in this +case, ``get_cookie`` will not yield the saved information. + +If a module implements a mechanism which requires multiple round +trips, its **verify** method can respond with the code +``KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED`` and a list of pa-data in +the *e_data* parameter to be processed by the client. + +The **edata** and **verify** methods can be implemented +asynchronously. Because of this, they do not return values directly +to the caller, but must instead invoke responder functions with their +results. A synchronous implementation can invoke the responder +function immediately. An asynchronous implementation can use the +callback to get an event context for use with the libverto_ API. + +.. _libverto: https://fedorahosted.org/libverto/ diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/localauth.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/localauth.rst.txt new file mode 100644 index 00000000..6f396a9c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/localauth.rst.txt @@ -0,0 +1,43 @@ +.. _localauth_plugin: + +Local authorization interface (localauth) +========================================= + +The localauth interface was first introduced in release 1.12. It +allows modules to control the relationship between Kerberos principals +and local system accounts. When an application calls +:c:func:`krb5_kuserok` or :c:func:`krb5_aname_to_localname`, localauth +modules are consulted to determine the result. For a detailed +description of the localauth interface, see the header file +````. + +A module can create and destroy per-library-context state objects +using the **init** and **fini** methods. If the module does not need +any state, it does not need to implement these methods. + +The optional **userok** method allows a module to control the behavior +of :c:func:`krb5_kuserok`. The module receives the authenticated name +and the local account name as inputs, and can return either 0 to +authorize access, KRB5_PLUGIN_NO_HANDLE to defer the decision to other +modules, or another error (canonically EPERM) to authoritatively deny +access. Access is granted if at least one module grants access and no +module authoritatively denies access. + +The optional **an2ln** method can work in two different ways. If the +module sets an array of uppercase type names in **an2ln_types**, then +the module's **an2ln** method will only be invoked by +:c:func:`krb5_aname_to_localname` if an **auth_to_local** value in +:ref:`krb5.conf(5)` refers to one of the module's types. In this +case, the *type* and *residual* arguments will give the type name and +residual string of the **auth_to_local** value. + +If the module does not set **an2ln_types** but does implement +**an2ln**, the module's **an2ln** method will be invoked for all +:c:func:`krb5_aname_to_localname` operations unless an earlier module +determines a mapping, with *type* and *residual* set to NULL. The +module can return KRB5_LNAME_NO_TRANS to defer mapping to later +modules. + +If a module implements **an2ln**, it must also implement +**free_string** to ensure that memory is allocated and deallocated +consistently. diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/locate.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/locate.rst.txt new file mode 100644 index 00000000..fca6a4da --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/locate.rst.txt @@ -0,0 +1,32 @@ +Server location interface (locate) +================================== + +The locate interface allows modules to control how KDCs and similar +services are located by clients. For a detailed description of the +ccselect interface, see the header file ````. + +.. note: The locate interface does not follow the normal conventions + for MIT krb5 pluggable interfaces, because it was made public + before those conventions were established. + +A locate module exports a structure object of type +krb5plugin_service_locate_ftable, with the name ``service_locator``. +The structure contains a minor version and pointers to the module's +methods. + +The primary locate method is **lookup**, which accepts a service type, +realm name, desired socket type, and desired address family (which +will be AF_UNSPEC if no specific address family is desired). The +method should invoke the callback function once for each server +address it wants to return, passing a socket type (SOCK_STREAM for TCP +or SOCK_DGRAM for UDP) and socket address. The **lookup** method +should return 0 if it has authoritatively determined the server +addresses for the realm, KRB5_PLUGIN_NO_HANDLE if it wants to let +other location mechanisms determine the server addresses, or another +code if it experienced a failure which should abort the location +process. + +A module can create and destroy per-library-context state objects by +implementing the **init** and **fini** methods. State objects have +the type void \*, and should be cast to an internal type for the state +object. diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/profile.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/profile.rst.txt new file mode 100644 index 00000000..209c0644 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/profile.rst.txt @@ -0,0 +1,96 @@ +.. _profile_plugin: + +Configuration interface (profile) +================================= + +The profile interface allows a module to control how krb5 +configuration information is obtained by the Kerberos library and +applications. For a detailed description of the profile interface, +see the header file ````. + +.. note:: + + The profile interface does not follow the normal conventions + for MIT krb5 pluggable interfaces, because it is part of a + lower-level component of the krb5 library. + +As with other types of plugin modules, a profile module is a Unix +shared object or Windows DLL, built separately from the krb5 tree. +The krb5 library will dynamically load and use a profile plugin module +if it reads a ``module`` directive at the beginning of krb5.conf, as +described in :ref:`profile_plugin_config`. + +A profile module exports a function named ``profile_module_init`` +matching the signature of the profile_module_init_fn type. This +function accepts a residual string, which may be used to help locate +the configuration source. The function fills in a vtable and may also +create a per-profile state object. If the module uses state objects, +it should implement the **copy** and **cleanup** methods to manage +them. + +A basic read-only profile module need only implement the +**get_values** and **free_values** methods. The **get_values** method +accepts a null-terminated list of C string names (e.g., an array +containing "libdefaults", "clockskew", and NULL for the **clockskew** +variable in the :ref:`libdefaults` section) and returns a +null-terminated list of values, which will be cleaned up with the +**free_values** method when the caller is done with them. + +Iterable profile modules must also define the **iterator_create**, +**iterator**, **iterator_free**, and **free_string** methods. The +core krb5 code does not require profiles to be iterable, but some +applications may iterate over the krb5 profile object in order to +present configuration interfaces. + +Writable profile modules must also define the **writable**, +**modified**, **update_relation**, **rename_section**, +**add_relation**, and **flush** methods. The core krb5 code does not +require profiles to be writable, but some applications may write to +the krb5 profile in order to present configuration interfaces. + +The following is an example of a very basic read-only profile module +which returns a hardcoded value for the **default_realm** variable in +:ref:`libdefaults`, and provides no other configuration information. +(For conciseness, the example omits code for checking the return +values of malloc and strdup.) :: + + #include + #include + #include + + static long + get_values(void *cbdata, const char *const *names, char ***values) + { + if (names[0] != NULL && strcmp(names[0], "libdefaults") == 0 && + names[1] != NULL && strcmp(names[1], "default_realm") == 0) { + *values = malloc(2 * sizeof(char *)); + (*values)[0] = strdup("ATHENA.MIT.EDU"); + (*values)[1] = NULL; + return 0; + } + return PROF_NO_RELATION; + } + + static void + free_values(void *cbdata, char **values) + { + char **v; + + for (v = values; *v; v++) + free(*v); + free(values); + } + + long + profile_module_init(const char *residual, struct profile_vtable *vtable, + void **cb_ret); + + long + profile_module_init(const char *residual, struct profile_vtable *vtable, + void **cb_ret) + { + *cb_ret = NULL; + vtable->get_values = get_values; + vtable->free_values = free_values; + return 0; + } diff --git a/krb5-1.21.3/doc/html/_sources/plugindev/pwqual.rst.txt b/krb5-1.21.3/doc/html/_sources/plugindev/pwqual.rst.txt new file mode 100644 index 00000000..523b95c5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/plugindev/pwqual.rst.txt @@ -0,0 +1,25 @@ +.. _pwqual_plugin: + +Password quality interface (pwqual) +=================================== + +The pwqual interface allows modules to control what passwords are +allowed when a user changes passwords. For a detailed description of +the pwqual interface, see the header file ````. + +The primary pwqual method is **check**, which receives a password as +input and returns success (0) or a ``KADM5_PASS_Q_`` failure code +depending on whether the password is allowed. The **check** method +also receives the principal name and the name of the principal's +password policy as input; although there is no stable interface for +the module to obtain the fields of the password policy, it can define +its own configuration or data store based on the policy name. + +A module can create and destroy per-process state objects by +implementing the **open** and **close** methods. State objects have +the type krb5_pwqual_moddata, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object. The **open** method also receives the name of the realm's +dictionary file (as configured by the **dict_file** variable in the +:ref:`kdc_realms` section of :ref:`kdc.conf(5)`) if it wishes to use +it. diff --git a/krb5-1.21.3/doc/html/_sources/resources.rst.txt b/krb5-1.21.3/doc/html/_sources/resources.rst.txt new file mode 100644 index 00000000..2ac2791c --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/resources.rst.txt @@ -0,0 +1,60 @@ +Resources +========= + +Mailing lists +------------- + +* kerberos@mit.edu is a community resource for discussion and + questions about MIT krb5 and other Kerberos implementations. To + subscribe to the list, please follow the instructions at + https://mailman.mit.edu/mailman/listinfo/kerberos. +* krbdev@mit.edu is the primary list for developers of MIT Kerberos. + To subscribe to the list, please follow the instructions at + https://mailman.mit.edu/mailman/listinfo/krbdev. +* krb5-bugs@mit.edu is notified when a ticket is created or updated. + This list helps track bugs and feature requests. + In addition, this list is used to track documentation criticism + and recommendations for improvements. +* krbcore@mit.edu is a private list for the MIT krb5 core team. Send + mail to this list if you need to contact the core team. +* krbcore-security@mit.edu is the point of contact for security problems + with MIT Kerberos. Please use PGP-encrypted mail to report possible + vulnerabilities to this list. + + +IRC channels +------------ + +The IRC channel `#kerberos` on libera.chat is a community resource for +general Kerberos discussion and support. + +The main IRC channel for MIT Kerberos development is `#krbdev` on +Libera Chat. + +For more information about Libera Chat, see https://libera.chat/. + + +Archives +-------- + +* The archive https://mailman.mit.edu/pipermail/kerberos/ contains + past postings from the `kerberos@mit.edu` list. + +* The https://mailman.mit.edu/pipermail/krbdev/ contains past postings + from the `krbdev@mit.edu` list. + + +Wiki +---- + +The wiki at https://k5wiki.kerberos.org/ contains useful information +for developers working on the MIT Kerberos source code. Some of the +information on the wiki may be useful for advanced users or system +administrators. + +Web pages +--------- + +* https://web.mit.edu/kerberos/ is the MIT Kerberos software web page. + +* https://kerberos.org/ is the MIT Kerberos Consortium web page. diff --git a/krb5-1.21.3/doc/html/_sources/user/index.rst.txt b/krb5-1.21.3/doc/html/_sources/user/index.rst.txt new file mode 100644 index 00000000..233c3ef5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/index.rst.txt @@ -0,0 +1,10 @@ +For users +========= + +.. toctree:: + :maxdepth: 2 + + pwd_mgmt.rst + tkt_mgmt.rst + user_config/index.rst + user_commands/index.rst diff --git a/krb5-1.21.3/doc/html/_sources/user/pwd_mgmt.rst.txt b/krb5-1.21.3/doc/html/_sources/user/pwd_mgmt.rst.txt new file mode 100644 index 00000000..ed7d459f --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/pwd_mgmt.rst.txt @@ -0,0 +1,106 @@ +Password management +=================== + +Your password is the only way Kerberos has of verifying your identity. +If someone finds out your password, that person can masquerade as +you---send email that comes from you, read, edit, or delete your files, +or log into other hosts as you---and no one will be able to tell the +difference. For this reason, it is important that you choose a good +password, and keep it secret. If you need to give access to your +account to someone else, you can do so through Kerberos (see +:ref:`grant_access`). You should never tell your password to anyone, +including your system administrator, for any reason. You should +change your password frequently, particularly any time you think +someone may have found out what it is. + + +Changing your password +---------------------- + +To change your Kerberos password, use the :ref:`kpasswd(1)` command. +It will ask you for your old password (to prevent someone else from +walking up to your computer when you're not there and changing your +password), and then prompt you for the new one twice. (The reason you +have to type it twice is to make sure you have typed it correctly.) +For example, user ``david`` would do the following:: + + shell% kpasswd + Password for david: <- Type your old password. + Enter new password: <- Type your new password. + Enter it again: <- Type the new password again. + Password changed. + shell% + +If ``david`` typed the incorrect old password, he would get the +following message:: + + shell% kpasswd + Password for david: <- Type the incorrect old password. + kpasswd: Password incorrect while getting initial ticket + shell% + +If you make a mistake and don't type the new password the same way +twice, kpasswd will ask you to try again:: + + shell% kpasswd + Password for david: <- Type the old password. + Enter new password: <- Type the new password. + Enter it again: <- Type a different new password. + kpasswd: Password mismatch while reading password + shell% + +Once you change your password, it takes some time for the change to +propagate through the system. Depending on how your system is set up, +this might be anywhere from a few minutes to an hour or more. If you +need to get new Kerberos tickets shortly after changing your password, +try the new password. If the new password doesn't work, try again +using the old one. + + +.. _grant_access: + +Granting access to your account +------------------------------- + +If you need to give someone access to log into your account, you can +do so through Kerberos, without telling the person your password. +Simply create a file called :ref:`.k5login(5)` in your home directory. +This file should contain the Kerberos principal of each person to whom +you wish to give access. Each principal must be on a separate line. +Here is a sample .k5login file:: + + jennifer@ATHENA.MIT.EDU + david@EXAMPLE.COM + +This file would allow the users ``jennifer`` and ``david`` to use your +user ID, provided that they had Kerberos tickets in their respective +realms. If you will be logging into other hosts across a network, you +will want to include your own Kerberos principal in your .k5login file +on each of these hosts. + +Using a .k5login file is much safer than giving out your password, +because: + +* You can take access away any time simply by removing the principal + from your .k5login file. + +* Although the user has full access to your account on one particular + host (or set of hosts if your .k5login file is shared, e.g., over + NFS), that user does not inherit your network privileges. + +* Kerberos keeps a log of who obtains tickets, so a system + administrator could find out, if necessary, who was capable of using + your user ID at a particular time. + +One common application is to have a .k5login file in root's home +directory, giving root access to that machine to the Kerberos +principals listed. This allows system administrators to allow users +to become root locally, or to log in remotely as root, without their +having to give out the root password, and without anyone having to +type the root password over the network. + + +Password quality verification +----------------------------- + +TODO diff --git a/krb5-1.21.3/doc/html/_sources/user/tkt_mgmt.rst.txt b/krb5-1.21.3/doc/html/_sources/user/tkt_mgmt.rst.txt new file mode 100644 index 00000000..9ec7f1e7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/tkt_mgmt.rst.txt @@ -0,0 +1,314 @@ +Ticket management +================= + +On many systems, Kerberos is built into the login program, and you get +tickets automatically when you log in. Other programs, such as ssh, +can forward copies of your tickets to a remote host. Most of these +programs also automatically destroy your tickets when they exit. +However, MIT recommends that you explicitly destroy your Kerberos +tickets when you are through with them, just to be sure. One way to +help ensure that this happens is to add the :ref:`kdestroy(1)` command +to your .logout file. Additionally, if you are going to be away from +your machine and are concerned about an intruder using your +permissions, it is safest to either destroy all copies of your +tickets, or use a screensaver that locks the screen. + + +Kerberos ticket properties +-------------------------- + +There are various properties that Kerberos tickets can have: + +If a ticket is **forwardable**, then the KDC can issue a new ticket +(with a different network address, if necessary) based on the +forwardable ticket. This allows for authentication forwarding without +requiring a password to be typed in again. For example, if a user +with a forwardable TGT logs into a remote system, the KDC could issue +a new TGT for that user with the network address of the remote system, +allowing authentication on that host to work as though the user were +logged in locally. + +When the KDC creates a new ticket based on a forwardable ticket, it +sets the **forwarded** flag on that new ticket. Any tickets that are +created based on a ticket with the forwarded flag set will also have +their forwarded flags set. + +A **proxiable** ticket is similar to a forwardable ticket in that it +allows a service to take on the identity of the client. Unlike a +forwardable ticket, however, a proxiable ticket is only issued for +specific services. In other words, a ticket-granting ticket cannot be +issued based on a ticket that is proxiable but not forwardable. + +A **proxy** ticket is one that was issued based on a proxiable ticket. + +A **postdated** ticket is issued with the invalid flag set. After the +starting time listed on the ticket, it can be presented to the KDC to +obtain valid tickets. + +Ticket-granting tickets with the **postdateable** flag set can be used +to obtain postdated service tickets. + +**Renewable** tickets can be used to obtain new session keys without +the user entering their password again. A renewable ticket has two +expiration times. The first is the time at which this particular +ticket expires. The second is the latest possible expiration time for +any ticket issued based on this renewable ticket. + +A ticket with the **initial flag** set was issued based on the +authentication protocol, and not on a ticket-granting ticket. +Application servers that wish to ensure that the user's key has been +recently presented for verification could specify that this flag must +be set to accept the ticket. + +An **invalid** ticket must be rejected by application servers. +Postdated tickets are usually issued with this flag set, and must be +validated by the KDC before they can be used. + +A **preauthenticated** ticket is one that was only issued after the +client requesting the ticket had authenticated itself to the KDC. + +The **hardware authentication** flag is set on a ticket which required +the use of hardware for authentication. The hardware is expected to +be possessed only by the client which requested the tickets. + +If a ticket has the **transit policy** checked flag set, then the KDC +that issued this ticket implements the transited-realm check policy +and checked the transited-realms list on the ticket. The +transited-realms list contains a list of all intermediate realms +between the realm of the KDC that issued the first ticket and that of +the one that issued the current ticket. If this flag is not set, then +the application server must check the transited realms itself or else +reject the ticket. + +The **okay as delegate** flag indicates that the server specified in +the ticket is suitable as a delegate as determined by the policy of +that realm. Some client applications may use this flag to decide +whether to forward tickets to a remote host, although many +applications do not honor it. + +An **anonymous** ticket is one in which the named principal is a +generic principal for that realm; it does not actually specify the +individual that will be using the ticket. This ticket is meant only +to securely distribute a session key. + + +.. _obtain_tkt: + +Obtaining tickets with kinit +---------------------------- + +If your site has integrated Kerberos V5 with the login system, you +will get Kerberos tickets automatically when you log in. Otherwise, +you may need to explicitly obtain your Kerberos tickets, using the +:ref:`kinit(1)` program. Similarly, if your Kerberos tickets expire, +use the kinit program to obtain new ones. + +To use the kinit program, simply type ``kinit`` and then type your +password at the prompt. For example, Jennifer (whose username is +``jennifer``) works for Bleep, Inc. (a fictitious company with the +domain name mit.edu and the Kerberos realm ATHENA.MIT.EDU). She would +type:: + + shell% kinit + Password for jennifer@ATHENA.MIT.EDU: <-- [Type jennifer's password here.] + shell% + +If you type your password incorrectly, kinit will give you the +following error message:: + + shell% kinit + Password for jennifer@ATHENA.MIT.EDU: <-- [Type the wrong password here.] + kinit: Password incorrect + shell% + +and you won't get Kerberos tickets. + +By default, kinit assumes you want tickets for your own username in +your default realm. Suppose Jennifer's friend David is visiting, and +he wants to borrow a window to check his mail. David needs to get +tickets for himself in his own realm, EXAMPLE.COM. He would type:: + + shell% kinit david@EXAMPLE.COM + Password for david@EXAMPLE.COM: <-- [Type david's password here.] + shell% + +David would then have tickets which he could use to log onto his own +machine. Note that he typed his password locally on Jennifer's +machine, but it never went over the network. Kerberos on the local +host performed the authentication to the KDC in the other realm. + +If you want to be able to forward your tickets to another host, you +need to request forwardable tickets. You do this by specifying the +**-f** option:: + + shell% kinit -f + Password for jennifer@ATHENA.MIT.EDU: <-- [Type your password here.] + shell% + +Note that kinit does not tell you that it obtained forwardable +tickets; you can verify this using the :ref:`klist(1)` command (see +:ref:`view_tkt`). + +Normally, your tickets are good for your system's default ticket +lifetime, which is ten hours on many systems. You can specify a +different ticket lifetime with the **-l** option. Add the letter +**s** to the value for seconds, **m** for minutes, **h** for hours, or +**d** for days. For example, to obtain forwardable tickets for +``david@EXAMPLE.COM`` that would be good for three hours, you would +type:: + + shell% kinit -f -l 3h david@EXAMPLE.COM + Password for david@EXAMPLE.COM: <-- [Type david's password here.] + shell% + +.. note:: + + You cannot mix units; specifying a lifetime of 3h30m would + result in an error. Note also that most systems specify a + maximum ticket lifetime. If you request a longer ticket + lifetime, it will be automatically truncated to the maximum + lifetime. + + +.. _view_tkt: + +Viewing tickets with klist +-------------------------- + +The :ref:`klist(1)` command shows your tickets. When you first obtain +tickets, you will have only the ticket-granting ticket. The listing +would look like this:: + + shell% klist + Ticket cache: /tmp/krb5cc_ttypa + Default principal: jennifer@ATHENA.MIT.EDU + + Valid starting Expires Service principal + 06/07/04 19:49:21 06/08/04 05:49:19 krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU + shell% + +The ticket cache is the location of your ticket file. In the above +example, this file is named ``/tmp/krb5cc_ttypa``. The default +principal is your Kerberos principal. + +The "valid starting" and "expires" fields describe the period of time +during which the ticket is valid. The "service principal" describes +each ticket. The ticket-granting ticket has a first component +``krbtgt``, and a second component which is the realm name. + +Now, if ``jennifer`` connected to the machine ``daffodil.mit.edu``, +and then typed "klist" again, she would have gotten the following +result:: + + shell% klist + Ticket cache: /tmp/krb5cc_ttypa + Default principal: jennifer@ATHENA.MIT.EDU + + Valid starting Expires Service principal + 06/07/04 19:49:21 06/08/04 05:49:19 krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU + 06/07/04 20:22:30 06/08/04 05:49:19 host/daffodil.mit.edu@ATHENA.MIT.EDU + shell% + +Here's what happened: when ``jennifer`` used ssh to connect to the +host ``daffodil.mit.edu``, the ssh program presented her +ticket-granting ticket to the KDC and requested a host ticket for the +host ``daffodil.mit.edu``. The KDC sent the host ticket, which ssh +then presented to the host ``daffodil.mit.edu``, and she was allowed +to log in without typing her password. + +Suppose your Kerberos tickets allow you to log into a host in another +domain, such as ``trillium.example.com``, which is also in another +Kerberos realm, ``EXAMPLE.COM``. If you ssh to this host, you will +receive a ticket-granting ticket for the realm ``EXAMPLE.COM``, plus +the new host ticket for ``trillium.example.com``. klist will now +show:: + + shell% klist + Ticket cache: /tmp/krb5cc_ttypa + Default principal: jennifer@ATHENA.MIT.EDU + + Valid starting Expires Service principal + 06/07/04 19:49:21 06/08/04 05:49:19 krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU + 06/07/04 20:22:30 06/08/04 05:49:19 host/daffodil.mit.edu@ATHENA.MIT.EDU + 06/07/04 20:24:18 06/08/04 05:49:19 krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU + 06/07/04 20:24:18 06/08/04 05:49:19 host/trillium.example.com@EXAMPLE.COM + shell% + +Depending on your host's and realm's configuration, you may also see a +ticket with the service principal ``host/trillium.example.com@``. If +so, this means that your host did not know what realm +trillium.example.com is in, so it asked the ``ATHENA.MIT.EDU`` KDC for +a referral. The next time you connect to ``trillium.example.com``, +the odd-looking entry will be used to avoid needing to ask for a +referral again. + +You can use the **-f** option to view the flags that apply to your +tickets. The flags are: + +===== ========================= + F Forwardable + f forwarded + P Proxiable + p proxy + D postDateable + d postdated + R Renewable + I Initial + i invalid + H Hardware authenticated + A preAuthenticated + T Transit policy checked + O Okay as delegate + a anonymous +===== ========================= + +Here is a sample listing. In this example, the user *jennifer* +obtained her initial tickets (**I**), which are forwardable (**F**) +and postdated (**d**) but not yet validated (**i**):: + + shell% klist -f + Ticket cache: /tmp/krb5cc_320 + Default principal: jennifer@ATHENA.MIT.EDU + + Valid starting Expires Service principal + 31/07/05 19:06:25 31/07/05 19:16:25 krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU + Flags: FdiI + shell% + +In the following example, the user *david*'s tickets were forwarded +(**f**) to this host from another host. The tickets are reforwardable +(**F**):: + + shell% klist -f + Ticket cache: /tmp/krb5cc_p11795 + Default principal: david@EXAMPLE.COM + + Valid starting Expires Service principal + 07/31/05 11:52:29 07/31/05 21:11:23 krbtgt/EXAMPLE.COM@EXAMPLE.COM + Flags: Ff + 07/31/05 12:03:48 07/31/05 21:11:23 host/trillium.example.com@EXAMPLE.COM + Flags: Ff + shell% + + +Destroying tickets with kdestroy +-------------------------------- + +Your Kerberos tickets are proof that you are indeed yourself, and +tickets could be stolen if someone gains access to a computer where +they are stored. If this happens, the person who has them can +masquerade as you until they expire. For this reason, you should +destroy your Kerberos tickets when you are away from your computer. + +Destroying your tickets is easy. Simply type kdestroy:: + + shell% kdestroy + shell% + +If :ref:`kdestroy(1)` fails to destroy your tickets, it will beep and +give an error message. For example, if kdestroy can't find any +tickets to destroy, it will give the following message:: + + shell% kdestroy + kdestroy: No credentials cache file found while destroying cache + shell% diff --git a/krb5-1.21.3/doc/html/_sources/user/user_commands/index.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_commands/index.rst.txt new file mode 100644 index 00000000..7ce86a14 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_commands/index.rst.txt @@ -0,0 +1,17 @@ +.. _user_commands: + +User commands +============= + +.. toctree:: + :maxdepth: 1 + + kdestroy.rst + kinit.rst + klist.rst + kpasswd.rst + krb5-config.rst + ksu.rst + kswitch.rst + kvno.rst + sclient.rst diff --git a/krb5-1.21.3/doc/html/_sources/user/user_commands/kdestroy.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_commands/kdestroy.rst.txt new file mode 100644 index 00000000..b15846f9 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_commands/kdestroy.rst.txt @@ -0,0 +1,77 @@ +.. _kdestroy(1): + +kdestroy +======== + +SYNOPSIS +-------- + +**kdestroy** +[**-A**] +[**-q**] +[**-c** *cache_name*] +[**-p** *princ_name*] + + +DESCRIPTION +----------- + +The kdestroy utility destroys the user's active Kerberos authorization +tickets by overwriting and deleting the credentials cache that +contains them. If the credentials cache is not specified, the default +credentials cache is destroyed. + + +OPTIONS +------- + +**-A** + Destroys all caches in the collection, if a cache collection is + available. May be used with the **-c** option to specify the + collection to be destroyed. + +**-q** + Run quietly. Normally kdestroy beeps if it fails to destroy the + user's tickets. The **-q** flag suppresses this behavior. + +**-c** *cache_name* + Use *cache_name* as the credentials (ticket) cache name and + location; if this option is not used, the default cache name and + location are used. + + The default credentials cache may vary between systems. If the + **KRB5CCNAME** environment variable is set, its value is used to + name the default ticket cache. + +**-p** *princ_name* + If a cache collection is available, destroy the cache for + *princ_name* instead of the primary cache. May be used with the + **-c** option to specify the collection to be searched. + + +NOTE +---- + +Most installations recommend that you place the kdestroy command in +your .logout file, so that your tickets are destroyed automatically +when you log out. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +FILES +----- + +|ccache| + Default location of Kerberos 5 credentials cache + + +SEE ALSO +-------- + +:ref:`kinit(1)`, :ref:`klist(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/user/user_commands/kinit.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_commands/kinit.rst.txt new file mode 100644 index 00000000..5b105e35 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_commands/kinit.rst.txt @@ -0,0 +1,230 @@ +.. _kinit(1): + +kinit +===== + +SYNOPSIS +-------- + +**kinit** +[**-V**] +[**-l** *lifetime*] +[**-s** *start_time*] +[**-r** *renewable_life*] +[**-p** | -**P**] +[**-f** | -**F**] +[**-a**] +[**-A**] +[**-C**] +[**-E**] +[**-v**] +[**-R**] +[**-k** [**-i** | -**t** *keytab_file*]] +[**-c** *cache_name*] +[**-n**] +[**-S** *service_name*] +[**-I** *input_ccache*] +[**-T** *armor_ccache*] +[**-X** *attribute*\ [=\ *value*]] +[**--request-pac** | **--no-request-pac**] +[*principal*] + + +DESCRIPTION +----------- + +kinit obtains and caches an initial ticket-granting ticket for +*principal*. If *principal* is absent, kinit chooses an appropriate +principal name based on existing credential cache contents or the +local username of the user invoking kinit. Some options modify the +choice of principal name. + + +OPTIONS +------- + +**-V** + display verbose output. + +**-l** *lifetime* + (:ref:`duration` string.) Requests a ticket with the lifetime + *lifetime*. + + For example, ``kinit -l 5:30`` or ``kinit -l 5h30m``. + + If the **-l** option is not specified, the default ticket lifetime + (configured by each site) is used. Specifying a ticket lifetime + longer than the maximum ticket lifetime (configured by each site) + will not override the configured maximum ticket lifetime. + +**-s** *start_time* + (:ref:`duration` string.) Requests a postdated ticket. Postdated + tickets are issued with the **invalid** flag set, and need to be + resubmitted to the KDC for validation before use. + + *start_time* specifies the duration of the delay before the ticket + can become valid. + +**-r** *renewable_life* + (:ref:`duration` string.) Requests renewable tickets, with a total + lifetime of *renewable_life*. + +**-f** + requests forwardable tickets. + +**-F** + requests non-forwardable tickets. + +**-p** + requests proxiable tickets. + +**-P** + requests non-proxiable tickets. + +**-a** + requests tickets restricted to the host's local address[es]. + +**-A** + requests tickets not restricted by address. + +**-C** + requests canonicalization of the principal name, and allows the + KDC to reply with a different client principal from the one + requested. + +**-E** + treats the principal name as an enterprise name. + +**-v** + requests that the ticket-granting ticket in the cache (with the + **invalid** flag set) be passed to the KDC for validation. If the + ticket is within its requested time range, the cache is replaced + with the validated ticket. + +**-R** + requests renewal of the ticket-granting ticket. Note that an + expired ticket cannot be renewed, even if the ticket is still + within its renewable life. + + Note that renewable tickets that have expired as reported by + :ref:`klist(1)` may sometimes be renewed using this option, + because the KDC applies a grace period to account for client-KDC + clock skew. See :ref:`krb5.conf(5)` **clockskew** setting. + +**-k** [**-i** | **-t** *keytab_file*] + requests a ticket, obtained from a key in the local host's keytab. + The location of the keytab may be specified with the **-t** + *keytab_file* option, or with the **-i** option to specify the use + of the default client keytab; otherwise the default keytab will be + used. By default, a host ticket for the local host is requested, + but any principal may be specified. On a KDC, the special keytab + location ``KDB:`` can be used to indicate that kinit should open + the KDC database and look up the key directly. This permits an + administrator to obtain tickets as any principal that supports + authentication based on the key. + +**-n** + Requests anonymous processing. Two types of anonymous principals + are supported. + + For fully anonymous Kerberos, configure pkinit on the KDC and + configure **pkinit_anchors** in the client's :ref:`krb5.conf(5)`. + Then use the **-n** option with a principal of the form ``@REALM`` + (an empty principal name followed by the at-sign and a realm + name). If permitted by the KDC, an anonymous ticket will be + returned. + + A second form of anonymous tickets is supported; these + realm-exposed tickets hide the identity of the client but not the + client's realm. For this mode, use ``kinit -n`` with a normal + principal name. If supported by the KDC, the principal (but not + realm) will be replaced by the anonymous principal. + + As of release 1.8, the MIT Kerberos KDC only supports fully + anonymous operation. + +**-I** *input_ccache* + + Specifies the name of a credentials cache that already contains a + ticket. When obtaining that ticket, if information about how that + ticket was obtained was also stored to the cache, that information + will be used to affect how new credentials are obtained, including + preselecting the same methods of authenticating to the KDC. + +**-T** *armor_ccache* + Specifies the name of a credentials cache that already contains a + ticket. If supported by the KDC, this cache will be used to armor + the request, preventing offline dictionary attacks and allowing + the use of additional preauthentication mechanisms. Armoring also + makes sure that the response from the KDC is not modified in + transit. + +**-c** *cache_name* + use *cache_name* as the Kerberos 5 credentials (ticket) cache + location. If this option is not used, the default cache location + is used. + + The default cache location may vary between systems. If the + **KRB5CCNAME** environment variable is set, its value is used to + locate the default cache. If a principal name is specified and + the type of the default cache supports a collection (such as the + DIR type), an existing cache containing credentials for the + principal is selected or a new one is created and becomes the new + primary cache. Otherwise, any existing contents of the default + cache are destroyed by kinit. + +**-S** *service_name* + specify an alternate service name to use when getting initial + tickets. + +**-X** *attribute*\ [=\ *value*] + specify a pre-authentication *attribute* and *value* to be + interpreted by pre-authentication modules. The acceptable + attribute and value values vary from module to module. This + option may be specified multiple times to specify multiple + attributes. If no value is specified, it is assumed to be "yes". + + The following attributes are recognized by the PKINIT + pre-authentication mechanism: + + **X509_user_identity**\ =\ *value* + specify where to find user's X509 identity information + + **X509_anchors**\ =\ *value* + specify where to find trusted X509 anchor information + + **flag_RSA_PROTOCOL**\ [**=yes**] + specify use of RSA, rather than the default Diffie-Hellman + protocol + + **disable_freshness**\ [**=yes**] + disable sending freshness tokens (for testing purposes only) + +**--request-pac** | **--no-request-pac** + mutually exclusive. If **--request-pac** is set, ask the KDC to + include a PAC in authdata; if **--no-request-pac** is set, ask the + KDC not to include a PAC; if neither are set, the KDC will follow + its default, which is typically is to include a PAC if doing so is + supported. + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +FILES +----- + +|ccache| + default location of Kerberos 5 credentials cache + +|keytab| + default location for the local host's keytab. + + +SEE ALSO +-------- + +:ref:`klist(1)`, :ref:`kdestroy(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/user/user_commands/klist.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_commands/klist.rst.txt new file mode 100644 index 00000000..eb556450 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_commands/klist.rst.txt @@ -0,0 +1,129 @@ +.. _klist(1): + +klist +===== + +SYNOPSIS +-------- + +**klist** +[**-e**] +[[**-c**] [**-l**] [**-A**] [**-f**] [**-s**] [**-a** [**-n**]]] +[**-C**] +[**-k** [**-i**] [**-t**] [**-K**]] +[**-V**] +[**-d**] +[*cache_name*\|\ *keytab_name*] + + +DESCRIPTION +----------- + +klist lists the Kerberos principal and Kerberos tickets held in a +credentials cache, or the keys held in a keytab file. + + +OPTIONS +------- + +**-e** + Displays the encryption types of the session key and the ticket + for each credential in the credential cache, or each key in the + keytab file. + +**-l** + If a cache collection is available, displays a table summarizing + the caches present in the collection. + +**-A** + If a cache collection is available, displays the contents of all + of the caches in the collection. + +**-c** + List tickets held in a credentials cache. This is the default if + neither **-c** nor **-k** is specified. + +**-f** + Shows the flags present in the credentials, using the following + abbreviations:: + + F Forwardable + f forwarded + P Proxiable + p proxy + D postDateable + d postdated + R Renewable + I Initial + i invalid + H Hardware authenticated + A preAuthenticated + T Transit policy checked + O Okay as delegate + a anonymous + +**-s** + Causes klist to run silently (produce no output). klist will exit + with status 1 if the credentials cache cannot be read or is + expired, and with status 0 otherwise. + +**-a** + Display list of addresses in credentials. + +**-n** + Show numeric addresses instead of reverse-resolving addresses. + +**-C** + List configuration data that has been stored in the credentials + cache when klist encounters it. By default, configuration data + is not listed. + +**-k** + List keys held in a keytab file. + +**-i** + In combination with **-k**, defaults to using the default client + keytab instead of the default acceptor keytab, if no name is + given. + +**-t** + Display the time entry timestamps for each keytab entry in the + keytab file. + +**-K** + Display the value of the encryption key in each keytab entry in + the keytab file. + +**-d** + Display the authdata types (if any) for each entry. + +**-V** + Display the Kerberos version number and exit. + +If *cache_name* or *keytab_name* is not specified, klist will display +the credentials in the default credentials cache or keytab file as +appropriate. If the **KRB5CCNAME** environment variable is set, its +value is used to locate the default ticket cache. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +FILES +----- + +|ccache| + Default location of Kerberos 5 credentials cache + +|keytab| + Default location for the local host's keytab file. + + +SEE ALSO +-------- + +:ref:`kinit(1)`, :ref:`kdestroy(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/user/user_commands/kpasswd.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_commands/kpasswd.rst.txt new file mode 100644 index 00000000..0583bbd0 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_commands/kpasswd.rst.txt @@ -0,0 +1,46 @@ +.. _kpasswd(1): + +kpasswd +======= + +SYNOPSIS +-------- + +**kpasswd** [*principal*] + + +DESCRIPTION +----------- + +The kpasswd command is used to change a Kerberos principal's password. +kpasswd first prompts for the current Kerberos password, then prompts +the user twice for the new password, and the password is changed. + +If the principal is governed by a policy that specifies the length +and/or number of character classes required in the new password, the +new password must conform to the policy. (The five character classes +are lower case, upper case, numbers, punctuation, and all other +characters.) + + +OPTIONS +------- + +*principal* + Change the password for the Kerberos principal principal. + Otherwise, kpasswd uses the principal name from an existing ccache + if there is one; if not, the principal is derived from the + identity of the user invoking the kpasswd command. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kadmin(1)`, :ref:`kadmind(8)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/user/user_commands/krb5-config.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_commands/krb5-config.rst.txt new file mode 100644 index 00000000..2c09141a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_commands/krb5-config.rst.txt @@ -0,0 +1,83 @@ +.. _krb5-config(1): + +krb5-config +=========== + +SYNOPSIS +-------- + +**krb5-config** +[**-**\ **-help** | **-**\ **-all** | **-**\ **-version** | **-**\ **-vendor** | **-**\ **-prefix** | **-**\ **-exec-prefix** | **-**\ **-defccname** | **-**\ **-defktname** | **-**\ **-defcktname** | **-**\ **-cflags** | **-**\ **-libs** [*libraries*]] + + +DESCRIPTION +----------- + +krb5-config tells the application programmer what flags to use to compile +and link programs against the installed Kerberos libraries. + + +OPTIONS +------- + +**-**\ **-help** + prints a usage message. This is the default behavior when no options + are specified. + +**-**\ **-all** + prints the version, vendor, prefix, and exec-prefix. + +**-**\ **-version** + prints the version number of the Kerberos installation. + +**-**\ **-vendor** + prints the name of the vendor of the Kerberos installation. + +**-**\ **-prefix** + prints the prefix for which the Kerberos installation was built. + +**-**\ **-exec-prefix** + prints the prefix for executables for which the Kerberos installation + was built. + +**-**\ **-defccname** + prints the built-in default credentials cache location. + +**-**\ **-defktname** + prints the built-in default keytab location. + +**-**\ **-defcktname** + prints the built-in default client (initiator) keytab location. + +**-**\ **-cflags** + prints the compilation flags used to build the Kerberos installation. + +**-**\ **-libs** [*library*] + prints the compiler options needed to link against *library*. + Allowed values for *library* are: + + ============ =============================================== + krb5 Kerberos 5 applications (default) + gssapi GSSAPI applications with Kerberos 5 bindings + kadm-client Kadmin client + kadm-server Kadmin server + kdb Applications that access the Kerberos database + ============ =============================================== + +EXAMPLES +-------- + +krb5-config is particularly useful for compiling against a Kerberos +installation that was installed in a non-standard location. For example, +a Kerberos installation that is installed in ``/opt/krb5/`` but uses +libraries in ``/usr/local/lib/`` for text localization would produce +the following output:: + + shell% krb5-config --libs krb5 + -L/opt/krb5/lib -Wl,-rpath -Wl,/opt/krb5/lib -L/usr/local/lib -lkrb5 -lk5crypto -lcom_err + + +SEE ALSO +-------- + +:ref:`kerberos(7)`, cc(1) diff --git a/krb5-1.21.3/doc/html/_sources/user/user_commands/ksu.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_commands/ksu.rst.txt new file mode 100644 index 00000000..93373822 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_commands/ksu.rst.txt @@ -0,0 +1,411 @@ +.. _ksu(1): + +ksu +=== + +SYNOPSIS +-------- + +**ksu** +[ *target_user* ] +[ **-n** *target_principal_name* ] +[ **-c** *source_cache_name* ] +[ **-k** ] +[ **-r** time ] +[ **-p** | **-P**] +[ **-f** | **-F**] +[ **-l** *lifetime* ] +[ **-z | Z** ] +[ **-q** ] +[ **-e** *command* [ args ... ] ] [ **-a** [ args ... ] ] + + +REQUIREMENTS +------------ + +Must have Kerberos version 5 installed to compile ksu. Must have a +Kerberos version 5 server running to use ksu. + + +DESCRIPTION +----------- + +ksu is a Kerberized version of the su program that has two missions: +one is to securely change the real and effective user ID to that of +the target user, and the other is to create a new security context. + +.. note:: + + For the sake of clarity, all references to and attributes of + the user invoking the program will start with "source" + (e.g., "source user", "source cache", etc.). + + Likewise, all references to and attributes of the target + account will start with "target". + +AUTHENTICATION +-------------- + +To fulfill the first mission, ksu operates in two phases: +authentication and authorization. Resolving the target principal name +is the first step in authentication. The user can either specify his +principal name with the **-n** option (e.g., ``-n jqpublic@USC.EDU``) +or a default principal name will be assigned using a heuristic +described in the OPTIONS section (see **-n** option). The target user +name must be the first argument to ksu; if not specified root is the +default. If ``.`` is specified then the target user will be the +source user (e.g., ``ksu .``). If the source user is root or the +target user is the source user, no authentication or authorization +takes place. Otherwise, ksu looks for an appropriate Kerberos ticket +in the source cache. + +The ticket can either be for the end-server or a ticket granting +ticket (TGT) for the target principal's realm. If the ticket for the +end-server is already in the cache, it's decrypted and verified. If +it's not in the cache but the TGT is, the TGT is used to obtain the +ticket for the end-server. The end-server ticket is then verified. +If neither ticket is in the cache, but ksu is compiled with the +**GET_TGT_VIA_PASSWD** define, the user will be prompted for a +Kerberos password which will then be used to get a TGT. If the user +is logged in remotely and does not have a secure channel, the password +may be exposed. If neither ticket is in the cache and +**GET_TGT_VIA_PASSWD** is not defined, authentication fails. + + +AUTHORIZATION +------------- + +This section describes authorization of the source user when ksu is +invoked without the **-e** option. For a description of the **-e** +option, see the OPTIONS section. + +Upon successful authentication, ksu checks whether the target +principal is authorized to access the target account. In the target +user's home directory, ksu attempts to access two authorization files: +:ref:`.k5login(5)` and .k5users. In the .k5login file each line +contains the name of a principal that is authorized to access the +account. + +For example:: + + jqpublic@USC.EDU + jqpublic/secure@USC.EDU + jqpublic/admin@USC.EDU + +The format of .k5users is the same, except the principal name may be +followed by a list of commands that the principal is authorized to +execute (see the **-e** option in the OPTIONS section for details). + +Thus if the target principal name is found in the .k5login file the +source user is authorized to access the target account. Otherwise ksu +looks in the .k5users file. If the target principal name is found +without any trailing commands or followed only by ``*`` then the +source user is authorized. If either .k5login or .k5users exist but +an appropriate entry for the target principal does not exist then +access is denied. If neither file exists then the principal will be +granted access to the account according to the aname->lname mapping +rules. Otherwise, authorization fails. + + +EXECUTION OF THE TARGET SHELL +----------------------------- + +Upon successful authentication and authorization, ksu proceeds in a +similar fashion to su. The environment is unmodified with the +exception of USER, HOME and SHELL variables. If the target user is +not root, USER gets set to the target user name. Otherwise USER +remains unchanged. Both HOME and SHELL are set to the target login's +default values. In addition, the environment variable **KRB5CCNAME** +gets set to the name of the target cache. The real and effective user +ID are changed to that of the target user. The target user's shell is +then invoked (the shell name is specified in the password file). Upon +termination of the shell, ksu deletes the target cache (unless ksu is +invoked with the **-k** option). This is implemented by first doing a +fork and then an exec, instead of just exec, as done by su. + + +CREATING A NEW SECURITY CONTEXT +------------------------------- + +ksu can be used to create a new security context for the target +program (either the target shell, or command specified via the **-e** +option). The target program inherits a set of credentials from the +source user. By default, this set includes all of the credentials in +the source cache plus any additional credentials obtained during +authentication. The source user is able to limit the credentials in +this set by using **-z** or **-Z** option. **-z** restricts the copy +of tickets from the source cache to the target cache to only the +tickets where client == the target principal name. The **-Z** option +provides the target user with a fresh target cache (no creds in the +cache). Note that for security reasons, when the source user is root +and target user is non-root, **-z** option is the default mode of +operation. + +While no authentication takes place if the source user is root or is +the same as the target user, additional tickets can still be obtained +for the target cache. If **-n** is specified and no credentials can +be copied to the target cache, the source user is prompted for a +Kerberos password (unless **-Z** specified or **GET_TGT_VIA_PASSWD** +is undefined). If successful, a TGT is obtained from the Kerberos +server and stored in the target cache. Otherwise, if a password is +not provided (user hit return) ksu continues in a normal mode of +operation (the target cache will not contain the desired TGT). If the +wrong password is typed in, ksu fails. + +.. note:: + + During authentication, only the tickets that could be + obtained without providing a password are cached in the + source cache. + + +OPTIONS +------- + +**-n** *target_principal_name* + Specify a Kerberos target principal name. Used in authentication + and authorization phases of ksu. + + If ksu is invoked without **-n**, a default principal name is + assigned via the following heuristic: + + * Case 1: source user is non-root. + + If the target user is the source user the default principal name + is set to the default principal of the source cache. If the + cache does not exist then the default principal name is set to + ``target_user@local_realm``. If the source and target users are + different and neither ``~target_user/.k5users`` nor + ``~target_user/.k5login`` exist then the default principal name + is ``target_user_login_name@local_realm``. Otherwise, starting + with the first principal listed below, ksu checks if the + principal is authorized to access the target account and whether + there is a legitimate ticket for that principal in the source + cache. If both conditions are met that principal becomes the + default target principal, otherwise go to the next principal. + + a) default principal of the source cache + b) target_user\@local_realm + c) source_user\@local_realm + + If a-c fails try any principal for which there is a ticket in + the source cache and that is authorized to access the target + account. If that fails select the first principal that is + authorized to access the target account from the above list. If + none are authorized and ksu is configured with + **PRINC_LOOK_AHEAD** turned on, select the default principal as + follows: + + For each candidate in the above list, select an authorized + principal that has the same realm name and first part of the + principal name equal to the prefix of the candidate. For + example if candidate a) is ``jqpublic@ISI.EDU`` and + ``jqpublic/secure@ISI.EDU`` is authorized to access the target + account then the default principal is set to + ``jqpublic/secure@ISI.EDU``. + + * Case 2: source user is root. + + If the target user is non-root then the default principal name + is ``target_user@local_realm``. Else, if the source cache + exists the default principal name is set to the default + principal of the source cache. If the source cache does not + exist, default principal name is set to ``root\@local_realm``. + +**-c** *source_cache_name* + + Specify source cache name (e.g., ``-c FILE:/tmp/my_cache``). If + **-c** option is not used then the name is obtained from + **KRB5CCNAME** environment variable. If **KRB5CCNAME** is not + defined the source cache name is set to ``krb5cc_``. + The target cache name is automatically set to ``krb5cc_.(gen_sym())``, where gen_sym generates a new number such that + the resulting cache does not already exist. For example:: + + krb5cc_1984.2 + +**-k** + Do not delete the target cache upon termination of the target + shell or a command (**-e** command). Without **-k**, ksu deletes + the target cache. + +**-z** + Restrict the copy of tickets from the source cache to the target + cache to only the tickets where client == the target principal + name. Use the **-n** option if you want the tickets for other then + the default principal. Note that the **-z** option is mutually + exclusive with the **-Z** option. + +**-Z** + Don't copy any tickets from the source cache to the target cache. + Just create a fresh target cache, where the default principal name + of the cache is initialized to the target principal name. Note + that the **-Z** option is mutually exclusive with the **-z** + option. + +**-q** + Suppress the printing of status messages. + +Ticket granting ticket options: + +**-l** *lifetime* **-r** *time* **-p** **-P** **-f** **-F** + The ticket granting ticket options only apply to the case where + there are no appropriate tickets in the cache to authenticate the + source user. In this case if ksu is configured to prompt users + for a Kerberos password (**GET_TGT_VIA_PASSWD** is defined), the + ticket granting ticket options that are specified will be used + when getting a ticket granting ticket from the Kerberos server. + +**-l** *lifetime* + (:ref:`duration` string.) Specifies the lifetime to be requested + for the ticket; if this option is not specified, the default ticket + lifetime (12 hours) is used instead. + +**-r** *time* + (:ref:`duration` string.) Specifies that the **renewable** option + should be requested for the ticket, and specifies the desired + total lifetime of the ticket. + +**-p** + specifies that the **proxiable** option should be requested for + the ticket. + +**-P** + specifies that the **proxiable** option should not be requested + for the ticket, even if the default configuration is to ask for + proxiable tickets. + +**-f** + option specifies that the **forwardable** option should be + requested for the ticket. + +**-F** + option specifies that the **forwardable** option should not be + requested for the ticket, even if the default configuration is to + ask for forwardable tickets. + +**-e** *command* [*args* ...] + ksu proceeds exactly the same as if it was invoked without the + **-e** option, except instead of executing the target shell, ksu + executes the specified command. Example of usage:: + + ksu bob -e ls -lag + + The authorization algorithm for **-e** is as follows: + + If the source user is root or source user == target user, no + authorization takes place and the command is executed. If source + user id != 0, and ``~target_user/.k5users`` file does not exist, + authorization fails. Otherwise, ``~target_user/.k5users`` file + must have an appropriate entry for target principal to get + authorized. + + The .k5users file format: + + A single principal entry on each line that may be followed by a + list of commands that the principal is authorized to execute. A + principal name followed by a ``*`` means that the user is + authorized to execute any command. Thus, in the following + example:: + + jqpublic@USC.EDU ls mail /local/kerberos/klist + jqpublic/secure@USC.EDU * + jqpublic/admin@USC.EDU + + ``jqpublic@USC.EDU`` is only authorized to execute ``ls``, + ``mail`` and ``klist`` commands. ``jqpublic/secure@USC.EDU`` is + authorized to execute any command. ``jqpublic/admin@USC.EDU`` is + not authorized to execute any command. Note, that + ``jqpublic/admin@USC.EDU`` is authorized to execute the target + shell (regular ksu, without the **-e** option) but + ``jqpublic@USC.EDU`` is not. + + The commands listed after the principal name must be either a full + path names or just the program name. In the second case, + **CMD_PATH** specifying the location of authorized programs must + be defined at the compilation time of ksu. Which command gets + executed? + + If the source user is root or the target user is the source user + or the user is authorized to execute any command (``*`` entry) + then command can be either a full or a relative path leading to + the target program. Otherwise, the user must specify either a + full path or just the program name. + +**-a** *args* + Specify arguments to be passed to the target shell. Note that all + flags and parameters following -a will be passed to the shell, + thus all options intended for ksu must precede **-a**. + + The **-a** option can be used to simulate the **-e** option if + used as follows:: + + -a -c [command [arguments]]. + + **-c** is interpreted by the c-shell to execute the command. + + +INSTALLATION INSTRUCTIONS +------------------------- + +ksu can be compiled with the following four flags: + +**GET_TGT_VIA_PASSWD** + In case no appropriate tickets are found in the source cache, the + user will be prompted for a Kerberos password. The password is + then used to get a ticket granting ticket from the Kerberos + server. The danger of configuring ksu with this macro is if the + source user is logged in remotely and does not have a secure + channel, the password may get exposed. + +**PRINC_LOOK_AHEAD** + During the resolution of the default principal name, + **PRINC_LOOK_AHEAD** enables ksu to find principal names in + the .k5users file as described in the OPTIONS section + (see **-n** option). + +**CMD_PATH** + Specifies a list of directories containing programs that users are + authorized to execute (via .k5users file). + +**HAVE_GETUSERSHELL** + If the source user is non-root, ksu insists that the target user's + shell to be invoked is a "legal shell". *getusershell(3)* is + called to obtain the names of "legal shells". Note that the + target user's shell is obtained from the passwd file. + +Sample configuration:: + + KSU_OPTS = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/bin /usr/ucb /local/bin" + +ksu should be owned by root and have the set user id bit turned on. + +ksu attempts to get a ticket for the end server just as Kerberized +telnet and rlogin. Thus, there must be an entry for the server in the +Kerberos database (e.g., ``host/nii.isi.edu@ISI.EDU``). The keytab +file must be in an appropriate location. + + +SIDE EFFECTS +------------ + +ksu deletes all expired tickets from the source cache. + + +AUTHOR OF KSU +------------- + +GENNADY (ARI) MEDVINSKY + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kerberos(7)`, :ref:`kinit(1)` diff --git a/krb5-1.21.3/doc/html/_sources/user/user_commands/kswitch.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_commands/kswitch.rst.txt new file mode 100644 index 00000000..010332e6 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_commands/kswitch.rst.txt @@ -0,0 +1,50 @@ +.. _kswitch(1): + +kswitch +======= + +SYNOPSIS +-------- + +**kswitch** +{**-c** *cachename*\|\ **-p** *principal*} + + +DESCRIPTION +----------- + +kswitch makes the specified credential cache the primary cache for the +collection, if a cache collection is available. + + +OPTIONS +------- + +**-c** *cachename* + Directly specifies the credential cache to be made primary. + +**-p** *principal* + Causes the cache collection to be searched for a cache containing + credentials for *principal*. If one is found, that collection is + made primary. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +FILES +----- + +|ccache| + Default location of Kerberos 5 credentials cache + + +SEE ALSO +-------- + +:ref:`kinit(1)`, :ref:`kdestroy(1)`, :ref:`klist(1)`, +:ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/user/user_commands/kvno.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_commands/kvno.rst.txt new file mode 100644 index 00000000..970fbb47 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_commands/kvno.rst.txt @@ -0,0 +1,119 @@ +.. _kvno(1): + +kvno +==== + +SYNOPSIS +-------- + +**kvno** +[**-c** *ccache*] +[**-e** *etype*] +[**-k** *keytab*] +[**-q**] +[**-u** | **-S** *sname*] +[**-P**] +[**--cached-only**] +[**--no-store**] +[**--out-cache** *cache*] +[[{**-F** *cert_file* | {**-I** | **-U**} *for_user*} [**-P**]] | **--u2u** *ccache*] +*service1 service2* ... + + +DESCRIPTION +----------- + +kvno acquires a service ticket for the specified Kerberos principals +and prints out the key version numbers of each. + + +OPTIONS +------- + +**-c** *ccache* + Specifies the name of a credentials cache to use (if not the + default) + +**-e** *etype* + Specifies the enctype which will be requested for the session key + of all the services named on the command line. This is useful in + certain backward compatibility situations. + +**-k** *keytab* + Decrypt the acquired tickets using *keytab* to confirm their + validity. + +**-q** + Suppress printing output when successful. If a service ticket + cannot be obtained, an error message will still be printed and + kvno will exit with nonzero status. + +**-u** + Use the unknown name type in requested service principal names. + This option Cannot be used with *-S*. + +**-P** + Specifies that the *service1 service2* ... arguments are to be + treated as services for which credentials should be acquired using + constrained delegation. This option is only valid when used in + conjunction with protocol transition. + +**-S** *sname* + Specifies that the *service1 service2* ... arguments are + interpreted as hostnames, and the service principals are to be + constructed from those hostnames and the service name *sname*. + The service hostnames will be canonicalized according to the usual + rules for constructing service principals. + +**-I** *for_user* + Specifies that protocol transition (S4U2Self) is to be used to + acquire a ticket on behalf of *for_user*. If constrained + delegation is not requested, the service name must match the + credentials cache client principal. + +**-U** *for_user* + Same as -I, but treats *for_user* as an enterprise name. + +**-F** *cert_file* + Specifies that protocol transition is to be used, identifying the + client principal with the X.509 certificate in *cert_file*. The + certificate file must be in PEM format. + +**--cached-only** + Only retrieve credentials already present in the cache, not from + the KDC. (Added in release 1.19.) + +**--no-store** + Do not store retrieved credentials in the cache. If + **--out-cache** is also specified, credentials will still be + stored into the output credential cache. (Added in release 1.19.) + +**--out-cache** *ccache* + Initialize *ccache* and store all retrieved credentials into it. + Do not store acquired credentials in the input cache. (Added in + release 1.19.) + +**--u2u** *ccache* + Requests a user-to-user ticket. *ccache* must contain a local + krbtgt ticket for the server principal. The reported version + number will typically be 0, as the resulting ticket is not + encrypted in the server's long-term key. + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +FILES +----- + +|ccache| + Default location of the credentials cache + + +SEE ALSO +-------- + +:ref:`kinit(1)`, :ref:`kdestroy(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/user/user_commands/sclient.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_commands/sclient.rst.txt new file mode 100644 index 00000000..1e3d38f8 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_commands/sclient.rst.txt @@ -0,0 +1,30 @@ +.. _sclient(1): + +sclient +======= + +SYNOPSIS +-------- + +**sclient** *remotehost* + + +DESCRIPTION +----------- + +sclient is a sample application, primarily useful for testing +purposes. It contacts a sample server :ref:`sserver(8)` and +authenticates to it using Kerberos version 5 tickets, then displays +the server's response. + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kinit(1)`, :ref:`sserver(8)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/html/_sources/user/user_config/index.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_config/index.rst.txt new file mode 100644 index 00000000..ad0dc1a7 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_config/index.rst.txt @@ -0,0 +1,13 @@ +User config files +================= + +The following files in your home directory can be used to control the +behavior of Kerberos as it applies to your account (unless they have +been disabled by your host's configuration): + +.. toctree:: + :maxdepth: 1 + + kerberos.rst + k5login.rst + k5identity.rst diff --git a/krb5-1.21.3/doc/html/_sources/user/user_config/k5identity.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_config/k5identity.rst.txt new file mode 100644 index 00000000..cf5d95e5 --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_config/k5identity.rst.txt @@ -0,0 +1,64 @@ +.. _.k5identity(5): + +.k5identity +=========== + +DESCRIPTION +----------- + +The .k5identity file, which resides in a user's home directory, +contains a list of rules for selecting a client principals based on +the server being accessed. These rules are used to choose a +credential cache within the cache collection when possible. + +Blank lines and lines beginning with ``#`` are ignored. Each line has +the form: + + *principal* *field*\=\ *value* ... + +If the server principal meets all of the field constraints, then +principal is chosen as the client principal. The following fields are +recognized: + +**realm** + If the realm of the server principal is known, it is matched + against *value*, which may be a pattern using shell wildcards. + For host-based server principals, the realm will generally only be + known if there is a :ref:`domain_realm` section in + :ref:`krb5.conf(5)` with a mapping for the hostname. + +**service** + If the server principal is a host-based principal, its service + component is matched against *value*, which may be a pattern using + shell wildcards. + +**host** + If the server principal is a host-based principal, its hostname + component is converted to lower case and matched against *value*, + which may be a pattern using shell wildcards. + + If the server principal matches the constraints of multiple lines + in the .k5identity file, the principal from the first matching + line is used. If no line matches, credentials will be selected + some other way, such as the realm heuristic or the current primary + cache. + + +EXAMPLE +------- + +The following example .k5identity file selects the client principal +``alice@KRBTEST.COM`` if the server principal is within that realm, +the principal ``alice/root@EXAMPLE.COM`` if the server host is within +a servers subdomain, and the principal ``alice/mail@EXAMPLE.COM`` when +accessing the IMAP service on ``mail.example.com``:: + + alice@KRBTEST.COM realm=KRBTEST.COM + alice/root@EXAMPLE.COM host=*.servers.example.com + alice/mail@EXAMPLE.COM host=mail.example.com service=imap + + +SEE ALSO +-------- + +kerberos(1), :ref:`krb5.conf(5)` diff --git a/krb5-1.21.3/doc/html/_sources/user/user_config/k5login.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_config/k5login.rst.txt new file mode 100644 index 00000000..8a9753da --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_config/k5login.rst.txt @@ -0,0 +1,54 @@ +.. _.k5login(5): + +.k5login +======== + +DESCRIPTION +----------- + +The .k5login file, which resides in a user's home directory, contains +a list of the Kerberos principals. Anyone with valid tickets for a +principal in the file is allowed host access with the UID of the user +in whose home directory the file resides. One common use is to place +a .k5login file in root's home directory, thereby granting system +administrators remote root access to the host via Kerberos. + + +EXAMPLES +-------- + +Suppose the user ``alice`` had a .k5login file in her home directory +containing just the following line:: + + bob@FOOBAR.ORG + +This would allow ``bob`` to use Kerberos network applications, such as +ssh(1), to access ``alice``'s account, using ``bob``'s Kerberos +tickets. In a default configuration (with **k5login_authoritative** set +to true in :ref:`krb5.conf(5)`), this .k5login file would not let +``alice`` use those network applications to access her account, since +she is not listed! With no .k5login file, or with **k5login_authoritative** +set to false, a default rule would permit the principal ``alice`` in the +machine's default realm to access the ``alice`` account. + +Let us further suppose that ``alice`` is a system administrator. +Alice and the other system administrators would have their principals +in root's .k5login file on each host:: + + alice@BLEEP.COM + + joeadmin/root@BLEEP.COM + +This would allow either system administrator to log in to these hosts +using their Kerberos tickets instead of having to type the root +password. Note that because ``bob`` retains the Kerberos tickets for +his own principal, ``bob@FOOBAR.ORG``, he would not have any of the +privileges that require ``alice``'s tickets, such as root access to +any of the site's hosts, or the ability to change ``alice``'s +password. + + +SEE ALSO +-------- + +kerberos(1) diff --git a/krb5-1.21.3/doc/html/_sources/user/user_config/kerberos.rst.txt b/krb5-1.21.3/doc/html/_sources/user/user_config/kerberos.rst.txt new file mode 100644 index 00000000..1830447a --- /dev/null +++ b/krb5-1.21.3/doc/html/_sources/user/user_config/kerberos.rst.txt @@ -0,0 +1,185 @@ +.. _kerberos(7): + +kerberos +======== + +DESCRIPTION +----------- + +The Kerberos system authenticates individual users in a network +environment. After authenticating yourself to Kerberos, you can use +Kerberos-enabled programs without having to present passwords or +certificates to those programs. + +If you receive the following response from :ref:`kinit(1)`: + +kinit: Client not found in Kerberos database while getting initial +credentials + +you haven't been registered as a Kerberos user. See your system +administrator. + +A Kerberos name usually contains three parts. The first is the +**primary**, which is usually a user's or service's name. The second +is the **instance**, which in the case of a user is usually null. +Some users may have privileged instances, however, such as ``root`` or +``admin``. In the case of a service, the instance is the fully +qualified name of the machine on which it runs; i.e. there can be an +ssh service running on the machine ABC (ssh/ABC@REALM), which is +different from the ssh service running on the machine XYZ +(ssh/XYZ@REALM). The third part of a Kerberos name is the **realm**. +The realm corresponds to the Kerberos service providing authentication +for the principal. Realms are conventionally all-uppercase, and often +match the end of hostnames in the realm (for instance, host01.example.com +might be in realm EXAMPLE.COM). + +When writing a Kerberos name, the principal name is separated from the +instance (if not null) by a slash, and the realm (if not the local +realm) follows, preceded by an "@" sign. The following are examples +of valid Kerberos names:: + + david + jennifer/admin + joeuser@BLEEP.COM + cbrown/root@FUBAR.ORG + +When you authenticate yourself with Kerberos you get an initial +Kerberos **ticket**. (A Kerberos ticket is an encrypted protocol +message that provides authentication.) Kerberos uses this ticket for +network utilities such as ssh. The ticket transactions are done +transparently, so you don't have to worry about their management. + +Note, however, that tickets expire. Administrators may configure more +privileged tickets, such as those with service or instance of ``root`` +or ``admin``, to expire in a few minutes, while tickets that carry +more ordinary privileges may be good for several hours or a day. If +your login session extends beyond the time limit, you will have to +re-authenticate yourself to Kerberos to get new tickets using the +:ref:`kinit(1)` command. + +Some tickets are **renewable** beyond their initial lifetime. This +means that ``kinit -R`` can extend their lifetime without requiring +you to re-authenticate. + +If you wish to delete your local tickets, use the :ref:`kdestroy(1)` +command. + +Kerberos tickets can be forwarded. In order to forward tickets, you +must request **forwardable** tickets when you kinit. Once you have +forwardable tickets, most Kerberos programs have a command line option +to forward them to the remote host. This can be useful for, e.g., +running kinit on your local machine and then sshing into another to do +work. Note that this should not be done on untrusted machines since +they will then have your tickets. + +ENVIRONMENT VARIABLES +--------------------- + +Several environment variables affect the operation of Kerberos-enabled +programs. These include: + +**KRB5CCNAME** + Default name for the credentials cache file, in the form + *TYPE*:*residual*. The type of the default cache may determine + the availability of a cache collection. ``FILE`` is not a + collection type; ``KEYRING``, ``DIR``, and ``KCM`` are. + + If not set, the value of **default_ccache_name** from + configuration files (see **KRB5_CONFIG**) will be used. If that + is also not set, the default *type* is ``FILE``, and the + *residual* is the path /tmp/krb5cc_*uid*, where *uid* is the + decimal user ID of the user. + +**KRB5_KTNAME** + Specifies the location of the default keytab file, in the form + *TYPE*:*residual*. If no *type* is present, the **FILE** type is + assumed and *residual* is the pathname of the keytab file. If + unset, |keytab| will be used. + +**KRB5_CONFIG** + Specifies the location of the Kerberos configuration file. The + default is |sysconfdir|\ ``/krb5.conf``. Multiple filenames can + be specified, separated by a colon; all files which are present + will be read. + +**KRB5_KDC_PROFILE** + Specifies the location of the KDC configuration file, which + contains additional configuration directives for the Key + Distribution Center daemon and associated programs. The default + is |kdcdir|\ ``/kdc.conf``. + +**KRB5RCACHENAME** + (New in release 1.18) Specifies the location of the default replay + cache, in the form *type*:*residual*. The ``file2`` type with a + pathname residual specifies a replay cache file in the version-2 + format in the specified location. The ``none`` type (residual is + ignored) disables the replay cache. The ``dfl`` type (residual is + ignored) indicates the default, which uses a file2 replay cache in + a temporary directory. The default is ``dfl:``. + +**KRB5RCACHETYPE** + Specifies the type of the default replay cache, if + **KRB5RCACHENAME** is unspecified. No residual can be specified, + so ``none`` and ``dfl`` are the only useful types. + +**KRB5RCACHEDIR** + Specifies the directory used by the ``dfl`` replay cache type. + The default is the value of the **TMPDIR** environment variable, + or ``/var/tmp`` if **TMPDIR** is not set. + +**KRB5_TRACE** + Specifies a filename to write trace log output to. Trace logs can + help illuminate decisions made internally by the Kerberos + libraries. For example, ``env KRB5_TRACE=/dev/stderr kinit`` + would send tracing information for :ref:`kinit(1)` to + ``/dev/stderr``. The default is not to write trace log output + anywhere. + +**KRB5_CLIENT_KTNAME** + Default client keytab file name. If unset, |ckeytab| will be + used). + +**KPROP_PORT** + :ref:`kprop(8)` port to use. Defaults to 754. + +**GSS_MECH_CONFIG** + Specifies a filename containing GSSAPI mechanism module + configuration. The default is to read |sysconfdir|\ ``/gss/mech`` + and files with a ``.conf`` suffix within the directory + |sysconfdir|\ ``/gss/mech.d``. + +Most environment variables are disabled for certain programs, such as +login system programs and setuid programs, which are designed to be +secure when run within an untrusted process environment. + +SEE ALSO +-------- + +:ref:`kdestroy(1)`, :ref:`kinit(1)`, :ref:`klist(1)`, +:ref:`kswitch(1)`, :ref:`kpasswd(1)`, :ref:`ksu(1)`, +:ref:`krb5.conf(5)`, :ref:`kdc.conf(5)`, :ref:`kadmin(1)`, +:ref:`kadmind(8)`, :ref:`kdb5_util(8)`, :ref:`krb5kdc(8)` + +BUGS +---- + +AUTHORS +------- + +| Steve Miller, MIT Project Athena/Digital Equipment Corporation +| Clifford Neuman, MIT Project Athena +| Greg Hudson, MIT Kerberos Consortium +| Robbie Harwood, Red Hat, Inc. + +HISTORY +------- + +The MIT Kerberos 5 implementation was developed at MIT, with +contributions from many outside parties. It is currently maintained +by the MIT Kerberos Consortium. + +RESTRICTIONS +------------ + +Copyright 1985, 1986, 1989-1996, 2002, 2011, 2018 Masachusetts +Institute of Technology diff --git a/krb5-1.21.3/doc/html/_static/agogo.css b/krb5-1.21.3/doc/html/_static/agogo.css new file mode 100644 index 00000000..f13ad80b --- /dev/null +++ b/krb5-1.21.3/doc/html/_static/agogo.css @@ -0,0 +1,538 @@ +/* + * agogo.css_t + * ~~~~~~~~~~~ + * + * Sphinx stylesheet -- agogo theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +* { + margin: 0px; + padding: 0px; +} + +body { + font-family: "Verdana", Arial, sans-serif; + line-height: 1.4em; + color: black; + background-color: #5d1509; +} + + +/* Page layout */ + +div.header, div.content, div.footer { + width: auto; + margin-left: auto; + margin-right: auto; +} + +div.header-wrapper { + background: #555573 url(bgtop.png) top left repeat-x; + border-bottom: 3px solid #2e3436; +} + + +/* Default body styles */ +a { + color: #881f0d; +} + +div.bodywrapper a, div.footer a { + text-decoration: underline; +} + +.clearer { + clear: both; +} + +.left { + float: left; +} + +.right { + float: right; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +h1, h2, h3, h4 { + font-family: "Georgia", "Times New Roman", serif; + font-weight: normal; + color: #3465a4; + margin-bottom: .8em; +} + +h1 { + color: #204a87; +} + +h2 { + padding-bottom: .5em; + border-bottom: 1px solid #3465a4; +} + +a.headerlink { + visibility: hidden; + color: #dddddd; + padding-left: .3em; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +img { + border: 0; +} + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 2px 7px 1px 7px; + border-left: 0.2em solid black; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +dt:target, .highlighted { + background-color: #fbe54e; +} + +/* Header */ + +div.header { + padding-top: 10px; + padding-bottom: 10px; +} + +div.header .headertitle { + font-family: "Georgia", "Times New Roman", serif; + font-weight: normal; + font-size: 180%; + letter-spacing: .08em; + margin-bottom: .8em; +} + +div.header .headertitle a { + color: white; +} + +div.header div.rel { + margin-top: 1em; +} + +div.header div.rel a { + color: #fcaf3e; + letter-spacing: .1em; + text-transform: uppercase; +} + +p.logo { + float: right; +} + +img.logo { + border: 0; +} + + +/* Content */ +div.content-wrapper { + background-color: white; + padding-top: 20px; + padding-bottom: 20px; +} + +div.document { + width: 80%; + float: left; +} + +div.body { + padding-right: 2em; + text-align: justify; +} + +div.document h1 { + line-height: 120%; +} + +div.document ul { + margin: 1.5em; + list-style-type: square; +} + +div.document dd { + margin-left: 1.2em; + margin-top: .4em; + margin-bottom: 1em; +} + +div.document .section { + margin-top: 1.7em; +} +div.document .section:first-child { + margin-top: 0px; +} + +div.document div.highlight { + padding: 3px; + border-top: 2px solid #dddddd; + border-bottom: 2px solid #dddddd; + margin-top: .8em; + margin-bottom: .8em; +} + +div.document div.literal-block-wrapper { + margin-top: .8em; + margin-bottom: .8em; +} + +div.document div.literal-block-wrapper div.highlight { + margin: 0; +} + +div.document div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.document div.code-block-caption span.caption-text { +} + +div.document h2 { + margin-top: .7em; +} + +div.document p { + margin-bottom: .5em; +} + +div.document li.toctree-l1 { + margin-bottom: 1em; +} + +div.document .descname { + font-weight: bold; +} + +div.document .sig-paren { + font-size: larger; +} + +div.document .docutils.literal { + background-color: #eeeeec; + padding: 1px; +} + +div.document .docutils.xref.literal { + background-color: transparent; + padding: 0px; +} + +div.document blockquote { + margin: 1em; +} + +div.document ol { + margin: 1.5em; +} + + +/* Sidebar */ + +div.sidebar { + width: 20%; + float: right; + font-size: .9em; +} + +div.sidebar a, div.header a { + text-decoration: none; +} + +div.sidebar a:hover, div.header a:hover { + text-decoration: underline; +} + +div.sidebar h3 { + color: #2e3436; + text-transform: uppercase; + font-size: 130%; + letter-spacing: .1em; +} + +div.sidebar ul { + list-style-type: none; +} + +div.sidebar li.toctree-l1 a { + display: block; + padding: 1px; + border: 1px solid #dddddd; + background-color: #eeeeec; + margin-bottom: .4em; + padding-left: 3px; + color: #2e3436; +} + +div.sidebar li.toctree-l2 a { + background-color: transparent; + border: none; + margin-left: 1em; + border-bottom: 1px solid #dddddd; +} + +div.sidebar li.toctree-l3 a { + background-color: transparent; + border: none; + margin-left: 2em; + border-bottom: 1px solid #dddddd; +} + +div.sidebar li.toctree-l2:last-child a { + border-bottom: none; +} + +div.sidebar li.toctree-l1.current a { + border-right: 5px solid #fcaf3e; +} + +div.sidebar li.toctree-l1.current li.toctree-l2 a { + border-right: none; +} + +div.sidebar input[type="text"] { + width: 170px; +} + +div.sidebar input[type="submit"] { + width: 30px; +} + + +/* Footer */ + +div.footer-wrapper { + background: #5d1509; + border-top: 4px solid #babdb6; + padding-top: 10px; + padding-bottom: 10px; + min-height: 80px; +} + +div.footer, div.footer a { + color: #888a85; +} + +div.footer .right { + text-align: right; +} + +div.footer .left { + text-transform: uppercase; +} + + +/* Styles copied from basic theme */ + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-right { + text-align: right; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- viewcode extension ---------------------------------------------------- */ + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family:: "Verdana", Arial, sans-serif; +} + +div.viewcode-block:target { + margin: -1px -3px; + padding: 0 3px; + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; +} + +div.code-block-caption { + background-color: #ddd; + color: #333; + padding: 2px 5px; + font-size: small; +} + +/* -- math display ---------------------------------------------------------- */ + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/_static/basic.css b/krb5-1.21.3/doc/html/_static/basic.css new file mode 100644 index 00000000..5f55daeb --- /dev/null +++ b/krb5-1.21.3/doc/html/_static/basic.css @@ -0,0 +1,905 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 20%; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 450px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a.brackets:before, +span.brackets > a:before{ + content: "["; +} + +a.brackets:after, +span.brackets > a:after { + content: "]"; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +dl.footnote > dt, +dl.citation > dt { + float: left; + margin-right: 0.5em; +} + +dl.footnote > dd, +dl.citation > dd { + margin-bottom: 0em; +} + +dl.footnote > dd:after, +dl.citation > dd:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dt:after { + content: ":"; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/_static/bgfooter.png b/krb5-1.21.3/doc/html/_static/bgfooter.png new file mode 100644 index 0000000000000000000000000000000000000000..b7c7cadd4e6978aa7081fe672fcf5afc97516bda GIT binary patch literal 276 zcmV+v0qg#WP)qvnR6EfsQ*t~7O=UY2%BZy- zs#7>Lw$#|1-#yb5jZ8}CcXenmE?Bb?+emvZy3eu4G&!aT9i`%Ot1U0%(#mRx?NNc)^t8TJHA0R4$Di^IIL4X9&MVm&N-9#bE;?}xqq}wTrc0WUU#YK z#2JfT+O{=ipwX3&j4H~AegD$wD(9Ee_Le?vx(rq^B%Dj?^+nzae0J!bK00|W&N)Yz aUi|<^NiO;Hz(H~V0000P0IhA`JcOe?|*M3M!YD+&^mI=Y=U~-8S>8l1XAJ*3?jZZ Q8UO$Q07*qoM6N<$f;!4|TmS$7 literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/doc/html/_static/doctools.js b/krb5-1.21.3/doc/html/_static/doctools.js new file mode 100644 index 00000000..8cbf1b16 --- /dev/null +++ b/krb5-1.21.3/doc/html/_static/doctools.js @@ -0,0 +1,323 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) { + this.initOnKeyListeners(); + } + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated === 'undefined') + return string; + return (typeof translated === 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated === 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) === 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this === '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keydown(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box, textarea, dropdown or button + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT' + && activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey + && !event.shiftKey) { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + break; + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + break; + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/krb5-1.21.3/doc/html/_static/documentation_options.js b/krb5-1.21.3/doc/html/_static/documentation_options.js new file mode 100644 index 00000000..f212ba68 --- /dev/null +++ b/krb5-1.21.3/doc/html/_static/documentation_options.js @@ -0,0 +1,12 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '1.21.3', + LANGUAGE: 'None', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false +}; \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/_static/file.png b/krb5-1.21.3/doc/html/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/doc/html/_static/jquery.js b/krb5-1.21.3/doc/html/_static/jquery.js new file mode 100644 index 00000000..624bca82 --- /dev/null +++ b/krb5-1.21.3/doc/html/_static/jquery.js @@ -0,0 +1,10879 @@ +/*! + * jQuery JavaScript Library v3.6.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.6.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.6 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2021-02-16 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +} +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the primary Deferred + primary = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + primary.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( primary.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return primary.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); + } + + return primary.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + + // Support: Chrome 86+ + // In Chrome, if an element having a focusout handler is blurred by + // clicking outside of it, it invokes the handler synchronously. If + // that handler calls `.remove()` on the element, the data is cleared, + // leaving `result` undefined. We need to guard against this. + return result && result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + which: true +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + // Suppress native focus or blur as it's already being fired + // in leverageNative. + _default: function() { + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + // + // Support: Firefox 70+ + // Only Firefox includes border widths + // in computed dimensions. (gh-4529) + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; + tr.style.cssText = "border:1px solid"; + + // Support: Chrome 86+ + // Height set through cssText does not get applied. + // Computed height then comes back as 0. + tr.style.height = "1px"; + trChild.style.height = "9px"; + + // Support: Android 8 Chrome 86+ + // In our bodyBackground.html iframe, + // display for all div elements is set to "inline", + // which causes a problem only in Android 8 Chrome 86. + // Ensuring the div is display: block + // gets around this issue. + trChild.style.display = "block"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + + parseInt( trStyle.borderTopWidth, 10 ) + + parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml, parserErrorElem; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) {} + + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ).filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ).map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + +originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script but not if jsonp + if ( !isSuccess && + jQuery.inArray( "script", s.dataTypes ) > -1 && + jQuery.inArray( "json", s.dataTypes ) < 0 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Contributing to the MIT Kerberos Documentation

+

We are looking for documentation writers and editors who could contribute +towards improving the MIT KC documentation content. If you are an experienced +Kerberos developer and/or administrator, please consider sharing your knowledge +and experience with the Kerberos Community. You can suggest your own topic or +write about any of the topics listed +here.

+

If you have any questions, comments, or suggestions on the existing documents, +please send your feedback via email to krb5-bugs@mit.edu. The HTML version of +this documentation has a “FEEDBACK” link to the krb5-bugs@mit.edu email +address with a pre-constructed subject line.

+
+

Background

+

Starting with release 1.11, the Kerberos documentation set is +unified in a central form. Man pages, HTML documentation, and PDF +documents are compiled from reStructuredText sources, and the application +developer documentation incorporates Doxygen markup from the source +tree. This project was undertaken along the outline described +here.

+

Previous versions of Kerberos 5 attempted to maintain separate documentation +in the texinfo format, with separate groff manual pages. Having the API +documentation disjoint from the source code implementing that API +resulted in the documentation becoming stale, and over time the documentation +ceased to match reality. With a fresh start and a source format that is +easier to use and maintain, reStructuredText-based documents should provide +an improved experience for the user. Consolidating all the documentation +formats into a single source document makes the documentation set easier +to maintain.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/admin_commands/index.html b/krb5-1.21.3/doc/html/admin/admin_commands/index.html new file mode 100644 index 00000000..42935051 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/admin_commands/index.html @@ -0,0 +1,180 @@ + + + + + + + + + Administration programs — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/admin_commands/k5srvutil.html b/krb5-1.21.3/doc/html/admin/admin_commands/k5srvutil.html new file mode 100644 index 00000000..e2e3bc5f --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/admin_commands/k5srvutil.html @@ -0,0 +1,225 @@ + + + + + + + + + k5srvutil — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

k5srvutil

+
+

SYNOPSIS

+

k5srvutil operation +[-i] +[-f filename] +[-e keysalts]

+
+
+

DESCRIPTION

+

k5srvutil allows an administrator to list keys currently in +a keytab, to obtain new keys for a principal currently in a keytab, +or to delete non-current keys from a keytab.

+

operation must be one of the following:

+
+
list

Lists the keys in a keytab, showing version number and principal +name.

+
+
change

Uses the kadmin protocol to update the keys in the Kerberos +database to new randomly-generated keys, and updates the keys in +the keytab to match. If a key’s version number doesn’t match the +version number stored in the Kerberos server’s database, then the +operation will fail. If the -i flag is given, k5srvutil will +prompt for confirmation before changing each key. If the -k +option is given, the old and new keys will be displayed. +Ordinarily, keys will be generated with the default encryption +types and key salts. This can be overridden with the -e +option. Old keys are retained in the keytab so that existing +tickets continue to work, but delold should be used after +such tickets expire, to prevent attacks against the old keys.

+
+
delold

Deletes keys that are not the most recent version from the keytab. +This operation should be used some time after a change operation +to remove old keys, after existing tickets issued for the service +have expired. If the -i flag is given, then k5srvutil will +prompt for confirmation for each principal.

+
+
delete

Deletes particular keys in the keytab, interactively prompting for +each key.

+
+
+

In all cases, the default keytab is used unless this is overridden by +the -f option.

+

k5srvutil uses the kadmin program to edit the keytab in +place.

+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

kadmin, ktutil, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/admin_commands/kadmin_local.html b/krb5-1.21.3/doc/html/admin/admin_commands/kadmin_local.html new file mode 100644 index 00000000..1b6e42b3 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/admin_commands/kadmin_local.html @@ -0,0 +1,1018 @@ + + + + + + + + + kadmin — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kadmin

+
+

SYNOPSIS

+

kadmin +[-O|-N] +[-r realm] +[-p principal] +[-q query] +[[-c cache_name]|[-k [-t keytab]]|-n] +[-w password] +[-s admin_server[:port]] +[command args…]

+

kadmin.local +[-r realm] +[-p principal] +[-q query] +[-d dbname] +[-e enc:salt …] +[-m] +[-x db_args] +[command args…]

+
+
+

DESCRIPTION

+

kadmin and kadmin.local are command-line interfaces to the Kerberos V5 +administration system. They provide nearly identical functionalities; +the difference is that kadmin.local directly accesses the KDC +database, while kadmin performs operations using kadmind. +Except as explicitly noted otherwise, this man page will use “kadmin” +to refer to both versions. kadmin provides for the maintenance of +Kerberos principals, password policies, and service key tables +(keytabs).

+

The remote kadmin client uses Kerberos to authenticate to kadmind +using the service principal kadmin/admin or kadmin/ADMINHOST +(where ADMINHOST is the fully-qualified hostname of the admin +server). If the credentials cache contains a ticket for one of these +principals, and the -c credentials_cache option is specified, that +ticket is used to authenticate to kadmind. Otherwise, the -p and +-k options are used to specify the client Kerberos principal name +used to authenticate. Once kadmin has determined the principal name, +it requests a service ticket from the KDC, and uses that service +ticket to authenticate to kadmind.

+

Since kadmin.local directly accesses the KDC database, it usually must +be run directly on the primary KDC with sufficient permissions to read +the KDC database. If the KDC database uses the LDAP database module, +kadmin.local can be run on any host which can access the LDAP server.

+
+
+

OPTIONS

+
+
-r realm

Use realm as the default database realm.

+
+
-p principal

Use principal to authenticate. Otherwise, kadmin will append +/admin to the primary principal name of the default ccache, +the value of the USER environment variable, or the username as +obtained with getpwuid, in order of preference.

+
+
-k

Use a keytab to decrypt the KDC response instead of prompting for +a password. In this case, the default principal will be +host/hostname. If there is no keytab specified with the +-t option, then the default keytab will be used.

+
+
-t keytab

Use keytab to decrypt the KDC response. This can only be used +with the -k option.

+
+
-n

Requests anonymous processing. Two types of anonymous principals +are supported. For fully anonymous Kerberos, configure PKINIT on +the KDC and configure pkinit_anchors in the client’s +krb5.conf. Then use the -n option with a principal +of the form @REALM (an empty principal name followed by the +at-sign and a realm name). If permitted by the KDC, an anonymous +ticket will be returned. A second form of anonymous tickets is +supported; these realm-exposed tickets hide the identity of the +client but not the client’s realm. For this mode, use kinit +-n with a normal principal name. If supported by the KDC, the +principal (but not realm) will be replaced by the anonymous +principal. As of release 1.8, the MIT Kerberos KDC only supports +fully anonymous operation.

+
+
-c credentials_cache

Use credentials_cache as the credentials cache. The cache +should contain a service ticket for the kadmin/admin or +kadmin/ADMINHOST (where ADMINHOST is the fully-qualified +hostname of the admin server) service; it can be acquired with the +kinit program. If this option is not specified, kadmin +requests a new service ticket from the KDC, and stores it in its +own temporary ccache.

+
+
-w password

Use password instead of prompting for one. Use this option with +care, as it may expose the password to other users on the system +via the process list.

+
+
-q query

Perform the specified query and then exit.

+
+
-d dbname

Specifies the name of the KDC database. This option does not +apply to the LDAP database module.

+
+
-s admin_server[:port]

Specifies the admin server which kadmin should contact.

+
+
-m

If using kadmin.local, prompt for the database master password +instead of reading it from a stash file.

+
+
-eenc:salt …”

Sets the keysalt list to be used for any new keys created. See +Keysalt lists in kdc.conf for a list of possible +values.

+
+
-O

Force use of old AUTH_GSSAPI authentication flavor.

+
+
-N

Prevent fallback to AUTH_GSSAPI authentication flavor.

+
+
-x db_args

Specifies the database specific arguments. See the next section +for supported options.

+
+
+

Starting with release 1.14, if any command-line arguments remain after +the options, they will be treated as a single query to be executed. +This mode of operation is intended for scripts and behaves differently +from the interactive mode in several respects:

+
    +
  • Query arguments are split by the shell, not by kadmin.

  • +
  • Informational and warning messages are suppressed. Error messages +and query output (e.g. for get_principal) will still be +displayed.

  • +
  • Confirmation prompts are disabled (as if -force was given). +Password prompts will still be issued as required.

  • +
  • The exit status will be non-zero if the query fails.

  • +
+

The -q option does not carry these behavior differences; the query +will be processed as if it was entered interactively. The -q +option cannot be used in combination with a query in the remaining +arguments.

+
+
+

DATABASE OPTIONS

+

Database options can be used to override database-specific defaults. +Supported options for the DB2 module are:

+
+
+
-x dbname=*filename*

Specifies the base filename of the DB2 database.

+
+
-x lockiter

Make iteration operations hold the lock for the duration of +the entire operation, rather than temporarily releasing the +lock while handling each principal. This is the default +behavior, but this option exists to allow command line +override of a [dbmodules] setting. First introduced in +release 1.13.

+
+
-x unlockiter

Make iteration operations unlock the database for each +principal, instead of holding the lock for the duration of the +entire operation. First introduced in release 1.13.

+
+
+
+

Supported options for the LDAP module are:

+
+
+
-x host=ldapuri

Specifies the LDAP server to connect to by a LDAP URI.

+
+
-x binddn=bind_dn

Specifies the DN used to bind to the LDAP server.

+
+
-x bindpwd=password

Specifies the password or SASL secret used to bind to the LDAP +server. Using this option may expose the password to other +users on the system via the process list; to avoid this, +instead stash the password using the stashsrvpw command of +kdb5_ldap_util.

+
+
-x sasl_mech=mechanism

Specifies the SASL mechanism used to bind to the LDAP server. +The bind DN is ignored if a SASL mechanism is used. New in +release 1.13.

+
+
-x sasl_authcid=name

Specifies the authentication name used when binding to the +LDAP server with a SASL mechanism, if the mechanism requires +one. New in release 1.13.

+
+
-x sasl_authzid=name

Specifies the authorization name used when binding to the LDAP +server with a SASL mechanism. New in release 1.13.

+
+
-x sasl_realm=realm

Specifies the realm used when binding to the LDAP server with +a SASL mechanism, if the mechanism uses one. New in release +1.13.

+
+
-x debug=level

sets the OpenLDAP client library debug level. level is an +integer to be interpreted by the library. Debugging messages +are printed to standard error. New in release 1.12.

+
+
+
+
+
+

COMMANDS

+

When using the remote client, available commands may be restricted +according to the privileges specified in the kadm5.acl file +on the admin server.

+
+

add_principal

+
+

add_principal [options] newprinc

+
+

Creates the principal newprinc, prompting twice for a password. If +no password policy is specified with the -policy option, and the +policy named default is assigned to the principal if it exists. +However, creating a policy named default will not automatically +assign this policy to previously existing principals. This policy +assignment can be suppressed with the -clearpolicy option.

+

This command requires the add privilege.

+

Aliases: addprinc, ank

+

Options:

+
+
-expire expdate

(getdate time string) The expiration date of the principal.

+
+
-pwexpire pwexpdate

(getdate time string) The password expiration date.

+
+
-maxlife maxlife

(Time duration or getdate time string) The maximum ticket life +for the principal.

+
+
-maxrenewlife maxrenewlife

(Time duration or getdate time string) The maximum renewable +life of tickets for the principal.

+
+
-kvno kvno

The initial key version number.

+
+
-policy policy

The password policy used by this principal. If not specified, the +policy default is used if it exists (unless -clearpolicy +is specified).

+
+
-clearpolicy

Prevents any policy from being assigned when -policy is not +specified.

+
+
{-|+}allow_postdated

-allow_postdated prohibits this principal from obtaining +postdated tickets. +allow_postdated clears this flag.

+
+
{-|+}allow_forwardable

-allow_forwardable prohibits this principal from obtaining +forwardable tickets. +allow_forwardable clears this flag.

+
+
{-|+}allow_renewable

-allow_renewable prohibits this principal from obtaining +renewable tickets. +allow_renewable clears this flag.

+
+
{-|+}allow_proxiable

-allow_proxiable prohibits this principal from obtaining +proxiable tickets. +allow_proxiable clears this flag.

+
+
{-|+}allow_dup_skey

-allow_dup_skey disables user-to-user authentication for this +principal by prohibiting others from obtaining a service ticket +encrypted in this principal’s TGT session key. ++allow_dup_skey clears this flag.

+
+
{-|+}requires_preauth

+requires_preauth requires this principal to preauthenticate +before being allowed to kinit. -requires_preauth clears this +flag. When +requires_preauth is set on a service principal, +the KDC will only issue service tickets for that service principal +if the client’s initial authentication was performed using +preauthentication.

+
+
{-|+}requires_hwauth

+requires_hwauth requires this principal to preauthenticate +using a hardware device before being allowed to kinit. +-requires_hwauth clears this flag. When +requires_hwauth is +set on a service principal, the KDC will only issue service tickets +for that service principal if the client’s initial authentication was +performed using a hardware device to preauthenticate.

+
+
{-|+}ok_as_delegate

+ok_as_delegate sets the okay as delegate flag on tickets +issued with this principal as the service. Clients may use this +flag as a hint that credentials should be delegated when +authenticating to the service. -ok_as_delegate clears this +flag.

+
+
{-|+}allow_svr

-allow_svr prohibits the issuance of service tickets for this +principal. In release 1.17 and later, user-to-user service +tickets are still allowed unless the -allow_dup_skey flag is +also set. +allow_svr clears this flag.

+
+
{-|+}allow_tgs_req

-allow_tgs_req specifies that a Ticket-Granting Service (TGS) +request for a service ticket for this principal is not permitted. ++allow_tgs_req clears this flag.

+
+
{-|+}allow_tix

-allow_tix forbids the issuance of any tickets for this +principal. +allow_tix clears this flag.

+
+
{-|+}needchange

+needchange forces a password change on the next initial +authentication to this principal. -needchange clears this +flag.

+
+
{-|+}password_changing_service

+password_changing_service marks this principal as a password +change service principal.

+
+
{-|+}ok_to_auth_as_delegate

+ok_to_auth_as_delegate allows this principal to acquire +forwardable tickets to itself from arbitrary users, for use with +constrained delegation.

+
+
{-|+}no_auth_data_required

+no_auth_data_required prevents PAC or AD-SIGNEDPATH data from +being added to service tickets for the principal.

+
+
{-|+}lockdown_keys

+lockdown_keys prevents keys for this principal from leaving +the KDC via kadmind. The chpass and extract operations are denied +for a principal with this attribute. The chrand operation is +allowed, but will not return the new keys. The delete and rename +operations are also denied if this attribute is set, in order to +prevent a malicious administrator from replacing principals like +krbtgt/* or kadmin/* with new principals without the attribute. +This attribute can be set via the network protocol, but can only +be removed using kadmin.local.

+
+
-randkey

Sets the key of the principal to a random value.

+
+
-nokey

Causes the principal to be created with no key. New in release +1.12.

+
+
-pw password

Sets the password of the principal to the specified string and +does not prompt for a password. Note: using this option in a +shell script may expose the password to other users on the system +via the process list.

+
+
-e enc:salt,…

Uses the specified keysalt list for setting the keys of the +principal. See Keysalt lists in kdc.conf for a +list of possible values.

+
+
-x db_princ_args

Indicates database-specific options. The options for the LDAP +database module are:

+
+
-x dn=dn

Specifies the LDAP object that will contain the Kerberos +principal being created.

+
+
-x linkdn=dn

Specifies the LDAP object to which the newly created Kerberos +principal object will point.

+
+
-x containerdn=container_dn

Specifies the container object under which the Kerberos +principal is to be created.

+
+
-x tktpolicy=policy

Associates a ticket policy to the Kerberos principal.

+
+
+
+

Note

+
    +
  • The containerdn and linkdn options cannot be +specified with the dn option.

  • +
  • If the dn or containerdn options are not specified while +adding the principal, the principals are created under the +principal container configured in the realm or the realm +container.

  • +
  • dn and containerdn should be within the subtrees or +principal container configured in the realm.

  • +
+
+
+
+

Example:

+
kadmin: addprinc jennifer
+No policy specified for "jennifer@ATHENA.MIT.EDU";
+defaulting to no policy.
+Enter password for principal jennifer@ATHENA.MIT.EDU:
+Re-enter password for principal jennifer@ATHENA.MIT.EDU:
+Principal "jennifer@ATHENA.MIT.EDU" created.
+kadmin:
+
+
+
+
+

modify_principal

+
+

modify_principal [options] principal

+
+

Modifies the specified principal, changing the fields as specified. +The options to add_principal also apply to this command, except +for the -randkey, -pw, and -e options. In addition, the +option -clearpolicy will clear the current policy of a principal.

+

This command requires the modify privilege.

+

Alias: modprinc

+

Options (in addition to the addprinc options):

+
+
-unlock

Unlocks a locked principal (one which has received too many failed +authentication attempts without enough time between them according +to its password policy) so that it can successfully authenticate.

+
+
+
+
+

rename_principal

+
+

rename_principal [-force] old_principal new_principal

+
+

Renames the specified old_principal to new_principal. This +command prompts for confirmation, unless the -force option is +given.

+

This command requires the add and delete privileges.

+

Alias: renprinc

+
+
+

delete_principal

+
+

delete_principal [-force] principal

+
+

Deletes the specified principal from the database. This command +prompts for deletion, unless the -force option is given.

+

This command requires the delete privilege.

+

Alias: delprinc

+
+
+

change_password

+
+

change_password [options] principal

+
+

Changes the password of principal. Prompts for a new password if +neither -randkey or -pw is specified.

+

This command requires the changepw privilege, or that the +principal running the program is the same as the principal being +changed.

+

Alias: cpw

+

The following options are available:

+
+
-randkey

Sets the key of the principal to a random value.

+
+
-pw password

Set the password to the specified string. Using this option in a +script may expose the password to other users on the system via +the process list.

+
+
-e enc:salt,…

Uses the specified keysalt list for setting the keys of the +principal. See Keysalt lists in kdc.conf for a +list of possible values.

+
+
-keepold

Keeps the existing keys in the database. This flag is usually not +necessary except perhaps for krbtgt principals.

+
+
+

Example:

+
kadmin: cpw systest
+Enter password for principal systest@BLEEP.COM:
+Re-enter password for principal systest@BLEEP.COM:
+Password for systest@BLEEP.COM changed.
+kadmin:
+
+
+
+
+

purgekeys

+
+

purgekeys [-all|-keepkvno oldest_kvno_to_keep] principal

+
+

Purges previously retained old keys (e.g., from change_password +-keepold) from principal. If -keepkvno is specified, then +only purges keys with kvnos lower than oldest_kvno_to_keep. If +-all is specified, then all keys are purged. The -all option +is new in release 1.12.

+

This command requires the modify privilege.

+
+
+

get_principal

+
+

get_principal [-terse] principal

+
+

Gets the attributes of principal. With the -terse option, outputs +fields as quoted tab-separated strings.

+

This command requires the inquire privilege, or that the principal +running the the program to be the same as the one being listed.

+

Alias: getprinc

+

Examples:

+
kadmin: getprinc tlyu/admin
+Principal: tlyu/admin@BLEEP.COM
+Expiration date: [never]
+Last password change: Mon Aug 12 14:16:47 EDT 1996
+Password expiration date: [never]
+Maximum ticket life: 0 days 10:00:00
+Maximum renewable life: 7 days 00:00:00
+Last modified: Mon Aug 12 14:16:47 EDT 1996 (bjaspan/admin@BLEEP.COM)
+Last successful authentication: [never]
+Last failed authentication: [never]
+Failed password attempts: 0
+Number of keys: 1
+Key: vno 1, aes256-cts-hmac-sha384-192
+MKey: vno 1
+Attributes:
+Policy: [none]
+
+kadmin: getprinc -terse systest
+systest@BLEEP.COM   3    86400     604800    1
+785926535 753241234 785900000
+tlyu/admin@BLEEP.COM     786100034 0    0
+kadmin:
+
+
+
+
+

list_principals

+
+

list_principals [expression]

+
+

Retrieves all or some principal names. expression is a shell-style +glob expression that can contain the wild-card characters ?, +*, and []. All principal names matching the expression are +printed. If no expression is provided, all principal names are +printed. If the expression does not contain an @ character, an +@ character followed by the local realm is appended to the +expression.

+

This command requires the list privilege.

+

Alias: listprincs, get_principals, getprincs

+

Example:

+
kadmin:  listprincs test*
+test3@SECURE-TEST.OV.COM
+test2@SECURE-TEST.OV.COM
+test1@SECURE-TEST.OV.COM
+testuser@SECURE-TEST.OV.COM
+kadmin:
+
+
+
+
+

get_strings

+
+

get_strings principal

+
+

Displays string attributes on principal.

+

This command requires the inquire privilege.

+

Alias: getstrs

+
+
+

set_string

+
+

set_string principal name value

+
+

Sets a string attribute on principal. String attributes are used to +supply per-principal configuration to the KDC and some KDC plugin +modules. The following string attribute names are recognized by the +KDC:

+
+
require_auth

Specifies an authentication indicator which is required to +authenticate to the principal as a service. Multiple indicators +can be specified, separated by spaces; in this case any of the +specified indicators will be accepted. (New in release 1.14.)

+
+
session_enctypes

Specifies the encryption types supported for session keys when the +principal is authenticated to as a server. See +Encryption types in kdc.conf for a list of the +accepted values.

+
+
otp

Enables One Time Passwords (OTP) preauthentication for a client +principal. The value is a JSON string representing an array +of objects, each having optional type and username fields.

+
+
pkinit_cert_match

Specifies a matching expression that defines the certificate +attributes required for the client certificate used by the +principal during PKINIT authentication. The matching expression +is in the same format as those used by the pkinit_cert_match +option in krb5.conf. (New in release 1.16.)

+
+
pac_privsvr_enctype

Forces the encryption type of the PAC KDC checksum buffers to the +specified encryption type for tickets issued to this server, by +deriving a key from the local krbtgt key if it is of a different +encryption type. It may be necessary to set this value to +“aes256-sha1” on the cross-realm krbtgt entry for an Active +Directory realm when using aes-sha2 keys on the local krbtgt +entry.

+
+
+

This command requires the modify privilege.

+

Alias: setstr

+

Example:

+
set_string host/foo.mit.edu session_enctypes aes128-cts
+set_string user@FOO.COM otp "[{""type"":""hotp"",""username"":""al""}]"
+
+
+
+
+

del_string

+
+

del_string principal key

+
+

Deletes a string attribute from principal.

+

This command requires the delete privilege.

+

Alias: delstr

+
+
+

add_policy

+
+

add_policy [options] policy

+
+

Adds a password policy named policy to the database.

+

This command requires the add privilege.

+

Alias: addpol

+

The following options are available:

+
+
-maxlife time

(Time duration or getdate time string) Sets the maximum +lifetime of a password.

+
+
-minlife time

(Time duration or getdate time string) Sets the minimum +lifetime of a password.

+
+
-minlength length

Sets the minimum length of a password.

+
+
-minclasses number

Sets the minimum number of character classes required in a +password. The five character classes are lower case, upper case, +numbers, punctuation, and whitespace/unprintable characters.

+
+
-history number

Sets the number of past keys kept for a principal. This option is +not supported with the LDAP KDC database module.

+
+
+
+
-maxfailure maxnumber

Sets the number of authentication failures before the principal is +locked. Authentication failures are only tracked for principals +which require preauthentication. The counter of failed attempts +resets to 0 after a successful attempt to authenticate. A +maxnumber value of 0 (the default) disables lockout.

+
+
+
+
-failurecountinterval failuretime

(Time duration or getdate time string) Sets the allowable time +between authentication failures. If an authentication failure +happens after failuretime has elapsed since the previous +failure, the number of authentication failures is reset to 1. A +failuretime value of 0 (the default) means forever.

+
+
+
+
-lockoutduration lockouttime

(Time duration or getdate time string) Sets the duration for +which the principal is locked from authenticating if too many +authentication failures occur without the specified failure count +interval elapsing. A duration of 0 (the default) means the +principal remains locked out until it is administratively unlocked +with modprinc -unlock.

+
+
-allowedkeysalts

Specifies the key/salt tuples supported for long-term keys when +setting or changing a principal’s password/keys. See +Keysalt lists in kdc.conf for a list of the +accepted values, but note that key/salt tuples must be separated +with commas (‘,’) only. To clear the allowed key/salt policy use +a value of ‘-‘.

+
+
+

Example:

+
kadmin: add_policy -maxlife "2 days" -minlength 5 guests
+kadmin:
+
+
+
+
+

modify_policy

+
+

modify_policy [options] policy

+
+

Modifies the password policy named policy. Options are as described +for add_policy.

+

This command requires the modify privilege.

+

Alias: modpol

+
+
+

delete_policy

+
+

delete_policy [-force] policy

+
+

Deletes the password policy named policy. Prompts for confirmation +before deletion. The command will fail if the policy is in use by any +principals.

+

This command requires the delete privilege.

+

Alias: delpol

+

Example:

+
kadmin: del_policy guests
+Are you sure you want to delete the policy "guests"?
+(yes/no): yes
+kadmin:
+
+
+
+
+

get_policy

+
+

get_policy [ -terse ] policy

+
+

Displays the values of the password policy named policy. With the +-terse flag, outputs the fields as quoted strings separated by +tabs.

+

This command requires the inquire privilege.

+

Alias: getpol

+

Examples:

+
kadmin: get_policy admin
+Policy: admin
+Maximum password life: 180 days 00:00:00
+Minimum password life: 00:00:00
+Minimum password length: 6
+Minimum number of password character classes: 2
+Number of old keys kept: 5
+Reference count: 17
+
+kadmin: get_policy -terse admin
+admin     15552000  0    6    2    5    17
+kadmin:
+
+
+

The “Reference count” is the number of principals using that policy. +With the LDAP KDC database module, the reference count field is not +meaningful.

+
+
+

list_policies

+
+

list_policies [expression]

+
+

Retrieves all or some policy names. expression is a shell-style +glob expression that can contain the wild-card characters ?, +*, and []. All policy names matching the expression are +printed. If no expression is provided, all existing policy names are +printed.

+

This command requires the list privilege.

+

Aliases: listpols, get_policies, getpols.

+

Examples:

+
kadmin:  listpols
+test-pol
+dict-only
+once-a-min
+test-pol-nopw
+
+kadmin:  listpols t*
+test-pol
+test-pol-nopw
+kadmin:
+
+
+
+
+

ktadd

+
+
+
ktadd [options] principal
+
ktadd [options] -glob princ-exp
+
+
+

Adds a principal, or all principals matching princ-exp, to a +keytab file. Each principal’s keys are randomized in the process. +The rules for princ-exp are described in the list_principals +command.

+

This command requires the inquire and changepw privileges. +With the -glob form, it also requires the list privilege.

+

The options are:

+
+
-k[eytab] keytab

Use keytab as the keytab file. Otherwise, the default keytab is +used.

+
+
-e enc:salt,…

Uses the specified keysalt list for setting the new keys of the +principal. See Keysalt lists in kdc.conf for a +list of possible values.

+
+
-q

Display less verbose information.

+
+
-norandkey

Do not randomize the keys. The keys and their version numbers stay +unchanged. This option cannot be specified in combination with the +-e option.

+
+
+

An entry for each of the principal’s unique encryption types is added, +ignoring multiple keys with the same encryption type but different +salt types.

+

Alias: xst

+

Example:

+
kadmin: ktadd -k /tmp/foo-new-keytab host/foo.mit.edu
+Entry for principal host/foo.mit.edu@ATHENA.MIT.EDU with kvno 3,
+     encryption type aes256-cts-hmac-sha1-96 added to keytab
+     FILE:/tmp/foo-new-keytab
+kadmin:
+
+
+
+
+

ktremove

+
+

ktremove [options] principal [kvno | all | old]

+
+

Removes entries for the specified principal from a keytab. Requires +no permissions, since this does not require database access.

+

If the string “all” is specified, all entries for that principal are +removed; if the string “old” is specified, all entries for that +principal except those with the highest kvno are removed. Otherwise, +the value specified is parsed as an integer, and all entries whose +kvno match that integer are removed.

+

The options are:

+
+
-k[eytab] keytab

Use keytab as the keytab file. Otherwise, the default keytab is +used.

+
+
-q

Display less verbose information.

+
+
+

Alias: ktrem

+

Example:

+
kadmin: ktremove kadmin/admin all
+Entry for principal kadmin/admin with kvno 3 removed from keytab
+     FILE:/etc/krb5.keytab
+kadmin:
+
+
+
+
+

lock

+

Lock database exclusively. Use with extreme caution! This command +only works with the DB2 KDC database module.

+
+
+

unlock

+

Release the exclusive database lock.

+
+
+

list_requests

+

Lists available for kadmin requests.

+

Aliases: lr, ?

+
+
+

quit

+

Exit program. If the database was locked, the lock is released.

+

Aliases: exit, q

+
+
+
+

HISTORY

+

The kadmin program was originally written by Tom Yu at MIT, as an +interface to the OpenVision Kerberos administration program.

+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

kpasswd, kadmind, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/admin_commands/kadmind.html b/krb5-1.21.3/doc/html/admin/admin_commands/kadmind.html new file mode 100644 index 00000000..66b384d7 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/admin_commands/kadmind.html @@ -0,0 +1,277 @@ + + + + + + + + + kadmind — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kadmind

+
+

SYNOPSIS

+

kadmind +[-x db_args] +[-r realm] +[-m] +[-nofork] +[-proponly] +[-port port-number] +[-P pid_file] +[-p kdb5_util_path] +[-K kprop_path] +[-k kprop_port] +[-F dump_file]

+
+
+

DESCRIPTION

+

kadmind starts the Kerberos administration server. kadmind typically +runs on the primary Kerberos server, which stores the KDC database. +If the KDC database uses the LDAP module, the administration server +and the KDC server need not run on the same machine. kadmind accepts +remote requests from programs such as kadmin and +kpasswd to administer the information in these database.

+

kadmind requires a number of configuration files to be set up in order +for it to work:

+
+
kdc.conf

The KDC configuration file contains configuration information for +the KDC and admin servers. kadmind uses settings in this file to +locate the Kerberos database, and is also affected by the +acl_file, dict_file, kadmind_port, and iprop-related +settings.

+
+
kadm5.acl

kadmind’s ACL (access control list) tells it which principals are +allowed to perform administration actions. The pathname to the +ACL file can be specified with the acl_file kdc.conf +variable; by default, it is LOCALSTATEDIR/krb5kdc/kadm5.acl.

+
+
+

After the server begins running, it puts itself in the background and +disassociates itself from its controlling terminal.

+

kadmind can be configured for incremental database propagation. +Incremental propagation allows replica KDC servers to receive +principal and policy updates incrementally instead of receiving full +dumps of the database. This facility can be enabled in the +kdc.conf file with the iprop_enable option. Incremental +propagation requires the principal kiprop/PRIMARY\@REALM (where +PRIMARY is the primary KDC’s canonical host name, and REALM the realm +name). In release 1.13, this principal is automatically created and +registered into the datebase.

+
+
+

OPTIONS

+
+
-r realm

specifies the realm that kadmind will serve; if it is not +specified, the default realm of the host is used.

+
+
-m

causes the master database password to be fetched from the +keyboard (before the server puts itself in the background, if not +invoked with the -nofork option) rather than from a file on +disk.

+
+
-nofork

causes the server to remain in the foreground and remain +associated to the terminal.

+
+
-proponly

causes the server to only listen and respond to Kerberos replica +incremental propagation polling requests. This option can be used +to set up a hierarchical propagation topology where a replica KDC +provides incremental updates to other Kerberos replicas.

+
+
-port port-number

specifies the port on which the administration server listens for +connections. The default port is determined by the +kadmind_port configuration variable in kdc.conf.

+
+
-P pid_file

specifies the file to which the PID of kadmind process should be +written after it starts up. This file can be used to identify +whether kadmind is still running and to allow init scripts to stop +the correct process.

+
+
-p kdb5_util_path

specifies the path to the kdb5_util command to use when dumping the +KDB in response to full resync requests when iprop is enabled.

+
+
-K kprop_path

specifies the path to the kprop command to use to send full dumps +to replicas in response to full resync requests.

+
+
-k kprop_port

specifies the port by which the kprop process that is spawned by +kadmind connects to the replica kpropd, in order to transfer the +dump file during an iprop full resync request.

+
+
-F dump_file

specifies the file path to be used for dumping the KDB in response +to full resync requests when iprop is enabled.

+
+
-x db_args

specifies database-specific arguments. See Database Options in kadmin for supported arguments.

+
+
+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

kpasswd, kadmin, kdb5_util, +kdb5_ldap_util, kadm5.acl, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/admin_commands/kdb5_ldap_util.html b/krb5-1.21.3/doc/html/admin/admin_commands/kdb5_ldap_util.html new file mode 100644 index 00000000..7b6321b5 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/admin_commands/kdb5_ldap_util.html @@ -0,0 +1,551 @@ + + + + + + + + + kdb5_ldap_util — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kdb5_ldap_util

+
+

SYNOPSIS

+

kdb5_ldap_util +[-D user_dn [-w passwd]] +[-H ldapuri] +command +[command_options]

+
+
+

DESCRIPTION

+

kdb5_ldap_util allows an administrator to manage realms, Kerberos +services and ticket policies.

+
+
+

COMMAND-LINE OPTIONS

+
+
-r realm

Specifies the realm to be operated on.

+
+
-D user_dn

Specifies the Distinguished Name (DN) of the user who has +sufficient rights to perform the operation on the LDAP server.

+
+
-w passwd

Specifies the password of user_dn. This option is not +recommended.

+
+
-H ldapuri

Specifies the URI of the LDAP server.

+
+
+

By default, kdb5_ldap_util operates on the default realm (as specified +in krb5.conf) and connects and authenticates to the LDAP +server in the same manner as :ref:kadmind(8)` would given the +parameters in [dbdefaults] in kdc.conf.

+
+
+

COMMANDS

+
+

create

+
+

create +[-subtrees subtree_dn_list] +[-sscope search_scope] +[-containerref container_reference_dn] +[-k mkeytype] +[-kv mkeyVNO] +[-M mkeyname] +[-m|-P password|-sf stashfilename] +[-s] +[-maxtktlife max_ticket_life] +[-maxrenewlife max_renewable_ticket_life] +[ticket_flags]

+
+

Creates realm in directory. Options:

+
+
-subtrees subtree_dn_list

Specifies the list of subtrees containing the principals of a +realm. The list contains the DNs of the subtree objects separated +by colon (:).

+
+
-sscope search_scope

Specifies the scope for searching the principals under the +subtree. The possible values are 1 or one (one level), 2 or sub +(subtrees).

+
+
-containerref container_reference_dn

Specifies the DN of the container object in which the principals +of a realm will be created. If the container reference is not +configured for a realm, the principals will be created in the +realm container.

+
+
-k mkeytype

Specifies the key type of the master key in the database. The +default is given by the master_key_type variable in +kdc.conf.

+
+
-kv mkeyVNO

Specifies the version number of the master key in the database; +the default is 1. Note that 0 is not allowed.

+
+
-M mkeyname

Specifies the principal name for the master key in the database. +If not specified, the name is determined by the +master_key_name variable in kdc.conf.

+
+
-m

Specifies that the master database password should be read from +the TTY rather than fetched from a file on the disk.

+
+
-P password

Specifies the master database password. This option is not +recommended.

+
+
-sf stashfilename

Specifies the stash file of the master database password.

+
+
-s

Specifies that the stash file is to be created.

+
+
-maxtktlife max_ticket_life

(getdate time string) Specifies maximum ticket life for +principals in this realm.

+
+
-maxrenewlife max_renewable_ticket_life

(getdate time string) Specifies maximum renewable life of +tickets for principals in this realm.

+
+
ticket_flags

Specifies global ticket flags for the realm. Allowable flags are +documented in the description of the add_principal command in +kadmin.

+
+
+

Example:

+
kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu
+    -r ATHENA.MIT.EDU create -subtrees o=org -sscope SUB
+Password for "cn=admin,o=org":
+Initializing database for realm 'ATHENA.MIT.EDU'
+You will be prompted for the database Master Password.
+It is important that you NOT FORGET this password.
+Enter KDC database master key:
+Re-enter KDC database master key to verify:
+
+
+
+
+

modify

+
+

modify +[-subtrees subtree_dn_list] +[-sscope search_scope] +[-containerref container_reference_dn] +[-maxtktlife max_ticket_life] +[-maxrenewlife max_renewable_ticket_life] +[ticket_flags]

+
+

Modifies the attributes of a realm. Options:

+
+
-subtrees subtree_dn_list

Specifies the list of subtrees containing the principals of a +realm. The list contains the DNs of the subtree objects separated +by colon (:). This list replaces the existing list.

+
+
-sscope search_scope

Specifies the scope for searching the principals under the +subtrees. The possible values are 1 or one (one level), 2 or sub +(subtrees).

+
+
-containerref container_reference_dn Specifies the DN of the

container object in which the principals of a realm will be +created.

+
+
-maxtktlife max_ticket_life

(getdate time string) Specifies maximum ticket life for +principals in this realm.

+
+
-maxrenewlife max_renewable_ticket_life

(getdate time string) Specifies maximum renewable life of +tickets for principals in this realm.

+
+
ticket_flags

Specifies global ticket flags for the realm. Allowable flags are +documented in the description of the add_principal command in +kadmin.

+
+
+

Example:

+
shell% kdb5_ldap_util -r ATHENA.MIT.EDU -D cn=admin,o=org -H
+    ldaps://ldap-server1.mit.edu modify +requires_preauth
+Password for "cn=admin,o=org":
+shell%
+
+
+
+
+

view

+
+

view

+
+

Displays the attributes of a realm.

+

Example:

+
kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu
+    -r ATHENA.MIT.EDU view
+Password for "cn=admin,o=org":
+Realm Name: ATHENA.MIT.EDU
+Subtree: ou=users,o=org
+Subtree: ou=servers,o=org
+SearchScope: ONE
+Maximum ticket life: 0 days 01:00:00
+Maximum renewable life: 0 days 10:00:00
+Ticket flags: DISALLOW_FORWARDABLE REQUIRES_PWCHANGE
+
+
+
+
+

destroy

+
+

destroy [-f]

+
+

Destroys an existing realm. Options:

+
+
-f

If specified, will not prompt the user for confirmation.

+
+
+

Example:

+
shell% kdb5_ldap_util -r ATHENA.MIT.EDU -D cn=admin,o=org -H
+    ldaps://ldap-server1.mit.edu destroy
+Password for "cn=admin,o=org":
+Deleting KDC database of 'ATHENA.MIT.EDU', are you sure?
+(type 'yes' to confirm)? yes
+OK, deleting database of 'ATHENA.MIT.EDU'...
+shell%
+
+
+
+
+

list

+
+

list

+
+

Lists the names of realms under the container.

+

Example:

+
shell% kdb5_ldap_util -D cn=admin,o=org -H
+    ldaps://ldap-server1.mit.edu list
+Password for "cn=admin,o=org":
+ATHENA.MIT.EDU
+OPENLDAP.MIT.EDU
+MEDIA-LAB.MIT.EDU
+shell%
+
+
+
+
+

stashsrvpw

+
+

stashsrvpw +[-f filename] +name

+
+

Allows an administrator to store the password for service object in a +file so that KDC and Administration server can use it to authenticate +to the LDAP server. Options:

+
+
-f filename

Specifies the complete path of the service password file. By +default, /usr/local/var/service_passwd is used.

+
+
name

Specifies the name of the object whose password is to be stored. +If krb5kdc or kadmind are configured for +simple binding, this should be the distinguished name it will +use as given by the ldap_kdc_dn or ldap_kadmind_dn +variable in kdc.conf. If the KDC or kadmind is +configured for SASL binding, this should be the authentication +name it will use as given by the ldap_kdc_sasl_authcid or +ldap_kadmind_sasl_authcid variable.

+
+
+

Example:

+
kdb5_ldap_util stashsrvpw -f /home/andrew/conf_keyfile
+    cn=service-kdc,o=org
+Password for "cn=service-kdc,o=org":
+Re-enter password for "cn=service-kdc,o=org":
+
+
+
+
+

create_policy

+
+

create_policy +[-maxtktlife max_ticket_life] +[-maxrenewlife max_renewable_ticket_life] +[ticket_flags] +policy_name

+
+

Creates a ticket policy in the directory. Options:

+
+
-maxtktlife max_ticket_life

(getdate time string) Specifies maximum ticket life for +principals.

+
+
-maxrenewlife max_renewable_ticket_life

(getdate time string) Specifies maximum renewable life of +tickets for principals.

+
+
ticket_flags

Specifies the ticket flags. If this option is not specified, by +default, no restriction will be set by the policy. Allowable +flags are documented in the description of the add_principal +command in kadmin.

+
+
policy_name

Specifies the name of the ticket policy.

+
+
+

Example:

+
kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu
+    -r ATHENA.MIT.EDU create_policy -maxtktlife "1 day"
+    -maxrenewlife "1 week" -allow_postdated +needchange
+    -allow_forwardable tktpolicy
+Password for "cn=admin,o=org":
+
+
+
+
+

modify_policy

+
+

modify_policy +[-maxtktlife max_ticket_life] +[-maxrenewlife max_renewable_ticket_life] +[ticket_flags] +policy_name

+
+

Modifies the attributes of a ticket policy. Options are same as for +create_policy.

+

Example:

+
kdb5_ldap_util -D cn=admin,o=org -H
+    ldaps://ldap-server1.mit.edu -r ATHENA.MIT.EDU modify_policy
+    -maxtktlife "60 minutes" -maxrenewlife "10 hours"
+    +allow_postdated -requires_preauth tktpolicy
+Password for "cn=admin,o=org":
+
+
+
+
+

view_policy

+
+

view_policy +policy_name

+
+

Displays the attributes of the named ticket policy.

+

Example:

+
kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu
+    -r ATHENA.MIT.EDU view_policy tktpolicy
+Password for "cn=admin,o=org":
+Ticket policy: tktpolicy
+Maximum ticket life: 0 days 01:00:00
+Maximum renewable life: 0 days 10:00:00
+Ticket flags: DISALLOW_FORWARDABLE REQUIRES_PWCHANGE
+
+
+
+
+

destroy_policy

+
+

destroy_policy +[-force] +policy_name

+
+

Destroys an existing ticket policy. Options:

+
+
-force

Forces the deletion of the policy object. If not specified, the +user will be prompted for confirmation before deleting the policy.

+
+
policy_name

Specifies the name of the ticket policy.

+
+
+

Example:

+
kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu
+    -r ATHENA.MIT.EDU destroy_policy tktpolicy
+Password for "cn=admin,o=org":
+This will delete the policy object 'tktpolicy', are you sure?
+(type 'yes' to confirm)? yes
+** policy object 'tktpolicy' deleted.
+
+
+
+
+

list_policy

+
+

list_policy

+
+

Lists ticket policies.

+

Example:

+
kdb5_ldap_util -D cn=admin,o=org -H ldaps://ldap-server1.mit.edu
+    -r ATHENA.MIT.EDU list_policy
+Password for "cn=admin,o=org":
+tktpolicy
+tmppolicy
+userpolicy
+
+
+
+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

kadmin, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/admin_commands/kdb5_util.html b/krb5-1.21.3/doc/html/admin/admin_commands/kdb5_util.html new file mode 100644 index 00000000..eb50fcd7 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/admin_commands/kdb5_util.html @@ -0,0 +1,621 @@ + + + + + + + + + kdb5_util — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kdb5_util

+
+

SYNOPSIS

+

kdb5_util +[-r realm] +[-d dbname] +[-k mkeytype] +[-kv mkeyVNO] +[-M mkeyname] +[-m] +[-sf stashfilename] +[-P password] +[-x db_args] +command [command_options]

+
+
+

DESCRIPTION

+

kdb5_util allows an administrator to perform maintenance procedures on +the KDC database. Databases can be created, destroyed, and dumped to +or loaded from ASCII files. kdb5_util can create a Kerberos master +key stash file or perform live rollover of the master key.

+

When kdb5_util is run, it attempts to acquire the master key and open +the database. However, execution continues regardless of whether or +not kdb5_util successfully opens the database, because the database +may not exist yet or the stash file may be corrupt.

+

Note that some KDC database modules may not support all kdb5_util +commands.

+
+
+

COMMAND-LINE OPTIONS

+
+
-r realm

specifies the Kerberos realm of the database.

+
+
-d dbname

specifies the name under which the principal database is stored; +by default the database is that listed in kdc.conf. The +password policy database and lock files are also derived from this +value.

+
+
-k mkeytype

specifies the key type of the master key in the database. The +default is given by the master_key_type variable in +kdc.conf.

+
+
-kv mkeyVNO

Specifies the version number of the master key in the database; +the default is 1. Note that 0 is not allowed.

+
+
-M mkeyname

principal name for the master key in the database. If not +specified, the name is determined by the master_key_name +variable in kdc.conf.

+
+
-m

specifies that the master database password should be read from +the keyboard rather than fetched from a file on disk.

+
+
-sf stash_file

specifies the stash filename of the master database password. If +not specified, the filename is determined by the +key_stash_file variable in kdc.conf.

+
+
-P password

specifies the master database password. Using this option may +expose the password to other users on the system via the process +list.

+
+
-x db_args

specifies database-specific options. See kadmin for +supported options.

+
+
+
+
+

COMMANDS

+
+

create

+
+

create [-s]

+
+

Creates a new database. If the -s option is specified, the stash +file is also created. This command fails if the database already +exists. If the command is successful, the database is opened just as +if it had already existed when the program was first run.

+
+
+

destroy

+
+

destroy [-f]

+
+

Destroys the database, first overwriting the disk sectors and then +unlinking the files, after prompting the user for confirmation. With +the -f argument, does not prompt the user.

+
+
+

stash

+
+

stash [-f keyfile]

+
+

Stores the master principal’s keys in a stash file. The -f +argument can be used to override the keyfile specified in +kdc.conf.

+
+
+

dump

+
+

dump [-b7|-r13|-r18] +[-verbose] [-mkey_convert] [-new_mkey_file +mkey_file] [-rev] [-recurse] [filename +[principals…]]

+
+

Dumps the current Kerberos and KADM5 database into an ASCII file. By +default, the database is dumped in current format, “kdb5_util +load_dump version 7”. If filename is not specified, or is the string +“-”, the dump is sent to standard output. Options:

+
+
-b7

causes the dump to be in the Kerberos 5 Beta 7 format (“kdb5_util +load_dump version 4”). This was the dump format produced on +releases prior to 1.2.2.

+
+
-r13

causes the dump to be in the Kerberos 5 1.3 format (“kdb5_util +load_dump version 5”). This was the dump format produced on +releases prior to 1.8.

+
+
-r18

causes the dump to be in the Kerberos 5 1.8 format (“kdb5_util +load_dump version 6”). This was the dump format produced on +releases prior to 1.11.

+
+
-verbose

causes the name of each principal and policy to be printed as it +is dumped.

+
+
-mkey_convert

prompts for a new master key. This new master key will be used to +re-encrypt principal key data in the dumpfile. The principal keys +themselves will not be changed.

+
+
-new_mkey_file mkey_file

the filename of a stash file. The master key in this stash file +will be used to re-encrypt the key data in the dumpfile. The key +data in the database will not be changed.

+
+
-rev

dumps in reverse order. This may recover principals that do not +dump normally, in cases where database corruption has occurred.

+
+
-recurse

causes the dump to walk the database recursively (btree only). +This may recover principals that do not dump normally, in cases +where database corruption has occurred. In cases of such +corruption, this option will probably retrieve more principals +than the -rev option will.

+
+

Changed in version 1.15: Release 1.15 restored the functionality of the -recurse +option.

+
+
+

Changed in version 1.5: The -recurse option ceased working until release 1.15, +doing a normal dump instead of a recursive traversal.

+
+
+
+
+
+

load

+
+

load [-b7|-r13|-r18] [-hash] +[-verbose] [-update] filename

+
+

Loads a database dump from the named file into the named database. If +no option is given to determine the format of the dump file, the +format is detected automatically and handled as appropriate. Unless +the -update option is given, load creates a new database +containing only the data in the dump file, overwriting the contents of +any previously existing database. Note that when using the LDAP KDC +database module, the -update flag is required.

+

Options:

+
+
-b7

requires the database to be in the Kerberos 5 Beta 7 format +(“kdb5_util load_dump version 4”). This was the dump format +produced on releases prior to 1.2.2.

+
+
-r13

requires the database to be in Kerberos 5 1.3 format (“kdb5_util +load_dump version 5”). This was the dump format produced on +releases prior to 1.8.

+
+
-r18

requires the database to be in Kerberos 5 1.8 format (“kdb5_util +load_dump version 6”). This was the dump format produced on +releases prior to 1.11.

+
+
-hash

stores the database in hash format, if using the DB2 database +type. If this option is not specified, the database will be +stored in btree format. This option is not recommended, as +databases stored in hash format are known to corrupt data and lose +principals.

+
+
-verbose

causes the name of each principal and policy to be printed as it +is dumped.

+
+
-update

records from the dump file are added to or updated in the existing +database. Otherwise, a new database is created containing only +what is in the dump file and the old one destroyed upon successful +completion.

+
+
+
+
+

ark

+
+

ark [-e enc:salt,…] principal

+
+

Adds new random keys to principal at the next available key version +number. Keys for the current highest key version number will be +preserved. The -e option specifies the list of encryption and +salt types to be used for the new keys.

+
+
+

add_mkey

+
+

add_mkey [-e etype] [-s]

+
+

Adds a new master key to the master key principal, but does not mark +it as active. Existing master keys will remain. The -e option +specifies the encryption type of the new master key; see +Encryption types in kdc.conf for a list of possible +values. The -s option stashes the new master key in the stash +file, which will be created if it doesn’t already exist.

+

After a new master key is added, it should be propagated to replica +servers via a manual or periodic invocation of kprop. Then, +the stash files on the replica servers should be updated with the +kdb5_util stash command. Once those steps are complete, the key +is ready to be marked active with the kdb5_util use_mkey command.

+
+
+

use_mkey

+
+

use_mkey mkeyVNO [time]

+
+

Sets the activation time of the master key specified by mkeyVNO. +Once a master key becomes active, it will be used to encrypt newly +created principal keys. If no time argument is given, the current +time is used, causing the specified master key version to become +active immediately. The format for time is getdate time string.

+

After a new master key becomes active, the kdb5_util +update_princ_encryption command can be used to update all +principal keys to be encrypted in the new master key.

+
+
+

list_mkeys

+
+

list_mkeys

+
+

List all master keys, from most recent to earliest, in the master key +principal. The output will show the kvno, enctype, and salt type for +each mkey, similar to the output of kadmin getprinc. A +* following an mkey denotes the currently active master key.

+
+
+

purge_mkeys

+
+

purge_mkeys [-f] [-n] [-v]

+
+

Delete master keys from the master key principal that are not used to +protect any principals. This command can be used to remove old master +keys all principal keys are protected by a newer master key.

+
+
-f

does not prompt for confirmation.

+
+
-n

performs a dry run, showing master keys that would be purged, but +not actually purging any keys.

+
+
-v

gives more verbose output.

+
+
+
+
+

update_princ_encryption

+
+

update_princ_encryption [-f] [-n] [-v] +[princ-pattern]

+
+

Update all principal records (or only those matching the +princ-pattern glob pattern) to re-encrypt the key data using the +active database master key, if they are encrypted using a different +version, and give a count at the end of the number of principals +updated. If the -f option is not given, ask for confirmation +before starting to make changes. The -v option causes each +principal processed to be listed, with an indication as to whether it +needed updating or not. The -n option performs a dry run, only +showing the actions which would have been taken.

+
+
+

tabdump

+
+

tabdump [-H] [-c] [-e] [-n] [-o outfile] +dumptype

+
+

Dump selected fields of the database in a tabular format suitable for +reporting (e.g., using traditional Unix text processing tools) or +importing into relational databases. The data format is tab-separated +(default), or optionally comma-separated (CSV), with a fixed number of +columns. The output begins with a header line containing field names, +unless suppression is requested using the -H option.

+

The dumptype parameter specifies the name of an output table (see +below).

+

Options:

+
+
-H

suppress writing the field names in a header line

+
+
-c

use comma separated values (CSV) format, with minimal quoting, +instead of the default tab-separated (unquoted, unescaped) format

+
+
-e

write empty hexadecimal string fields as empty fields instead of +as “-1”.

+
+
-n

produce numeric output for fields that normally have symbolic +output, such as enctypes and flag names. Also requests output of +time stamps as decimal POSIX time_t values.

+
+
-o outfile

write the dump to the specified output file instead of to standard +output

+
+
+

Dump types:

+
+
keydata

principal encryption key information, including actual key data +(which is still encrypted in the master key)

+
+
name

principal name

+
+
keyindex

index of this key in the principal’s key list

+
+
kvno

key version number

+
+
enctype

encryption type

+
+
key

key data as a hexadecimal string

+
+
salttype

salt type

+
+
salt

salt data as a hexadecimal string

+
+
+
+
keyinfo

principal encryption key information (as in keydata above), +excluding actual key data

+
+
princ_flags

principal boolean attributes. Flag names print as hexadecimal +numbers if the -n option is specified, and all flag positions +are printed regardless of whether or not they are set. If -n +is not specified, print all known flag names for each principal, +but only print hexadecimal flag names if the corresponding flag is +set.

+
+
name

principal name

+
+
flag

flag name

+
+
value

boolean value (0 for clear, or 1 for set)

+
+
+
+
princ_lockout

state information used for tracking repeated password failures

+
+
name

principal name

+
+
last_success

time stamp of most recent successful authentication

+
+
last_failed

time stamp of most recent failed authentication

+
+
fail_count

count of failed attempts

+
+
+
+
princ_meta

principal metadata

+
+
name

principal name

+
+
modby

name of last principal to modify this principal

+
+
modtime

timestamp of last modification

+
+
lastpwd

timestamp of last password change

+
+
policy

policy object name

+
+
mkvno

key version number of the master key that encrypts this +principal’s key data

+
+
hist_kvno

key version number of the history key that encrypts the key +history data for this principal

+
+
+
+
princ_stringattrs

string attributes (key/value pairs)

+
+
name

principal name

+
+
key

attribute name

+
+
value

attribute value

+
+
+
+
princ_tktpolicy

per-principal ticket policy data, including maximum ticket +lifetimes

+
+
name

principal name

+
+
expiration

principal expiration date

+
+
pw_expiration

password expiration date

+
+
max_life

maximum ticket lifetime

+
+
max_renew_life

maximum renewable ticket lifetime

+
+
+
+
+

Examples:

+
$ kdb5_util tabdump -o keyinfo.txt keyinfo
+$ cat keyinfo.txt
+name        keyindex        kvno    enctype salttype        salt
+K/M@EXAMPLE.COM     0       1       aes256-cts-hmac-sha384-192      normal  -1
+foo@EXAMPLE.COM     0       1       aes128-cts-hmac-sha1-96 normal  -1
+bar@EXAMPLE.COM     0       1       aes128-cts-hmac-sha1-96 normal  -1
+$ sqlite3
+sqlite> .mode tabs
+sqlite> .import keyinfo.txt keyinfo
+sqlite> select * from keyinfo where enctype like 'aes256-%';
+K/M@EXAMPLE.COM     1       1       aes256-cts-hmac-sha384-192      normal  -1
+sqlite> .quit
+$ awk -F'\t' '$4 ~ /aes256-/ { print }' keyinfo.txt
+K/M@EXAMPLE.COM     1       1       aes256-cts-hmac-sha384-192      normal  -1
+
+
+
+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

kadmin, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/admin_commands/kprop.html b/krb5-1.21.3/doc/html/admin/admin_commands/kprop.html new file mode 100644 index 00000000..71d2f701 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/admin_commands/kprop.html @@ -0,0 +1,217 @@ + + + + + + + + + kprop — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kprop

+
+

SYNOPSIS

+

kprop +[-r realm] +[-f file] +[-d] +[-P port] +[-s keytab] +replica_host

+
+
+

DESCRIPTION

+

kprop is used to securely propagate a Kerberos V5 database dump file +from the primary Kerberos server to a replica Kerberos server, which is +specified by replica_host. The dump file must be created by +kdb5_util.

+
+
+

OPTIONS

+
+
-r realm

Specifies the realm of the primary server.

+
+
-f file

Specifies the filename where the dumped principal database file is +to be found; by default the dumped database file is normally +LOCALSTATEDIR/krb5kdc/replica_datatrans.

+
+
-P port

Specifies the port to use to contact the kpropd server +on the remote host.

+
+
-d

Prints debugging information.

+
+
-s keytab

Specifies the location of the keytab file.

+
+
+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

kpropd, kdb5_util, krb5kdc, +kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/admin_commands/kpropd.html b/krb5-1.21.3/doc/html/admin/admin_commands/kpropd.html new file mode 100644 index 00000000..4b9a07f0 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/admin_commands/kpropd.html @@ -0,0 +1,289 @@ + + + + + + + + + kpropd — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kpropd

+
+

SYNOPSIS

+

kpropd +[-r realm] +[-A admin_server] +[-a acl_file] +[-f replica_dumpfile] +[-F principal_database] +[-p kdb5_util_prog] +[-P port] +[–pid-file=pid_file] +[-D] +[-d] +[-s keytab_file]

+
+
+

DESCRIPTION

+

The kpropd command runs on the replica KDC server. It listens for +update requests made by the kprop program. If incremental +propagation is enabled, it periodically requests incremental updates +from the primary KDC.

+

When the replica receives a kprop request from the primary, kpropd +accepts the dumped KDC database and places it in a file, and then runs +kdb5_util to load the dumped database into the active +database which is used by krb5kdc. This allows the primary +Kerberos server to use kprop to propagate its database to +the replica servers. Upon a successful download of the KDC database +file, the replica Kerberos server will have an up-to-date KDC +database.

+

Where incremental propagation is not used, kpropd is commonly invoked +out of inetd(8) as a nowait service. This is done by adding a line to +the /etc/inetd.conf file which looks like this:

+
kprop  stream  tcp  nowait  root  /usr/local/sbin/kpropd  kpropd
+
+
+

kpropd can also run as a standalone daemon, backgrounding itself and +waiting for connections on port 754 (or the port specified with the +-P option if given). Standalone mode is required for incremental +propagation. Starting in release 1.11, kpropd automatically detects +whether it was run from inetd and runs in standalone mode if it is +not. Prior to release 1.11, the -S option is required to run +kpropd in standalone mode; this option is now accepted for backward +compatibility but does nothing.

+

Incremental propagation may be enabled with the iprop_enable +variable in kdc.conf. If incremental propagation is +enabled, the replica periodically polls the primary KDC for updates, at +an interval determined by the iprop_replica_poll variable. If the +replica receives updates, kpropd updates its log file with any updates +from the primary. kproplog can be used to view a summary of +the update entry log on the replica KDC. If incremental propagation +is enabled, the principal kiprop/replicahostname@REALM (where +replicahostname is the name of the replica KDC host, and REALM is +the name of the Kerberos realm) must be present in the replica’s +keytab file.

+

kproplog can be used to force full replication when iprop is +enabled.

+
+
+

OPTIONS

+
+
-r realm

Specifies the realm of the primary server.

+
+
-A admin_server

Specifies the server to be contacted for incremental updates; by +default, the primary admin server is contacted.

+
+
-f file

Specifies the filename where the dumped principal database file is +to be stored; by default the dumped database file is LOCALSTATEDIR/krb5kdc/from_master.

+
+
-F kerberos_db

Path to the Kerberos database file, if not the default.

+
+
-p

Allows the user to specify the pathname to the kdb5_util +program; by default the pathname used is SBINDIR/kdb5_util.

+
+
-D

In this mode, kpropd will not detach itself from the current job +and run in the background. Instead, it will run in the +foreground.

+
+
-d

Turn on debug mode. kpropd will print out debugging messages +during the database propogation and will run in the foreground +(implies -D).

+
+
-P

Allow for an alternate port number for kpropd to listen on. This +is only useful in combination with the -S option.

+
+
-a acl_file

Allows the user to specify the path to the kpropd.acl file; by +default the path used is LOCALSTATEDIR/krb5kdc/kpropd.acl.

+
+
–pid-file=pid_file

In standalone mode, write the process ID of the daemon into +pid_file.

+
+
-s keytab_file

Path to a keytab to use for acquiring acceptor credentials.

+
+
-x db_args

Database-specific arguments. See Database Options in kadmin for supported arguments.

+
+
+
+
+

FILES

+
+
kpropd.acl

Access file for kpropd; the default location is +/usr/local/var/krb5kdc/kpropd.acl. Each entry is a line +containing the principal of a host from which the local machine +will allow Kerberos database propagation via kprop.

+
+
+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

kprop, kdb5_util, krb5kdc, +kerberos, inetd(8)

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/admin_commands/kproplog.html b/krb5-1.21.3/doc/html/admin/admin_commands/kproplog.html new file mode 100644 index 00000000..498e5814 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/admin_commands/kproplog.html @@ -0,0 +1,242 @@ + + + + + + + + + kproplog — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kproplog

+
+

SYNOPSIS

+

kproplog [-h] [-e num] [-v] +kproplog [-R]

+
+
+

DESCRIPTION

+

The kproplog command displays the contents of the KDC database update +log to standard output. It can be used to keep track of incremental +updates to the principal database. The update log file contains the +update log maintained by the kadmind process on the primary +KDC server and the kpropd process on the replica KDC +servers. When updates occur, they are logged to this file. +Subsequently any KDC replica configured for incremental updates will +request the current data from the primary KDC and update their log +file with any updates returned.

+

The kproplog command requires read access to the update log file. It +will display update entries only for the KDC it runs on.

+

If no options are specified, kproplog displays a summary of the update +log. If invoked on the primary, kproplog also displays all of the +update entries. If invoked on a replica KDC server, kproplog displays +only a summary of the updates, which includes the serial number of the +last update received and the associated time stamp of the last update.

+
+
+

OPTIONS

+
+
-R

Reset the update log. This forces full resynchronization. If +used on a replica then that replica will request a full resync. +If used on the primary then all replicas will request full +resyncs.

+
+
-h

Display a summary of the update log. This information includes +the database version number, state of the database, the number of +updates in the log, the time stamp of the first and last update, +and the version number of the first and last update entry.

+
+
-e num

Display the last num update entries in the log. This is useful +when debugging synchronization between KDC servers.

+
+
-v

Display individual attributes per update. An example of the +output generated for one entry:

+
Update Entry
+   Update serial # : 4
+   Update operation : Add
+   Update principal : test@EXAMPLE.COM
+   Update size : 424
+   Update committed : True
+   Update time stamp : Fri Feb 20 23:37:42 2004
+   Attributes changed : 6
+         Principal
+         Key data
+         Password last changed
+         Modifying principal
+         Modification time
+         TL data
+
+
+
+
+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

kpropd, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/admin_commands/krb5kdc.html b/krb5-1.21.3/doc/html/admin/admin_commands/krb5kdc.html new file mode 100644 index 00000000..b7c6d993 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/admin_commands/krb5kdc.html @@ -0,0 +1,262 @@ + + + + + + + + + krb5kdc — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5kdc

+
+

SYNOPSIS

+

krb5kdc +[-x db_args] +[-d dbname] +[-k keytype] +[-M mkeyname] +[-p portnum] +[-m] +[-r realm] +[-n] +[-w numworkers] +[-P pid_file] +[-T time_offset]

+
+
+

DESCRIPTION

+

krb5kdc is the Kerberos version 5 Authentication Service and Key +Distribution Center (AS/KDC).

+
+
+

OPTIONS

+

The -r realm option specifies the realm for which the server +should provide service. This option may be specified multiple times +to serve multiple realms. If no -r option is given, the default +realm (as specified in krb5.conf) will be served.

+

The -d dbname option specifies the name under which the +principal database can be found. This option does not apply to the +LDAP database.

+

The -k keytype option specifies the key type of the master key +to be entered manually as a password when -m is given; the default +is aes256-cts-hmac-sha1-96.

+

The -M mkeyname option specifies the principal name for the +master key in the database (usually K/M in the KDC’s realm).

+

The -m option specifies that the master database password should +be fetched from the keyboard rather than from a stash file.

+

The -n option specifies that the KDC does not put itself in the +background and does not disassociate itself from the terminal.

+

The -P pid_file option tells the KDC to write its PID into +pid_file after it starts up. This can be used to identify whether +the KDC is still running and to allow init scripts to stop the correct +process.

+

The -p portnum option specifies the default UDP and TCP port +numbers which the KDC should listen on for Kerberos version 5 +requests, as a comma-separated list. This value overrides the port +numbers specified in the [kdcdefaults] section of +kdc.conf, but may be overridden by realm-specific values. +If no value is given from any source, the default port is 88.

+

The -w numworkers option tells the KDC to fork numworkers +processes to listen to the KDC ports and process requests in parallel. +The top level KDC process (whose pid is recorded in the pid file if +the -P option is also given) acts as a supervisor. The supervisor +will relay SIGHUP signals to the worker subprocesses, and will +terminate the worker subprocess if the it is itself terminated or if +any other worker process exits.

+

The -x db_args option specifies database-specific arguments. +See Database Options in kadmin for +supported arguments.

+

The -T offset option specifies a time offset, in seconds, which +the KDC will operate under. It is intended only for testing purposes.

+
+
+

EXAMPLE

+

The KDC may service requests for multiple realms (maximum 32 realms). +The realms are listed on the command line. Per-realm options that can +be specified on the command line pertain for each realm that follows +it and are superseded by subsequent definitions of the same option.

+

For example:

+
krb5kdc -p 2001 -r REALM1 -p 2002 -r REALM2 -r REALM3
+
+
+

specifies that the KDC listen on port 2001 for REALM1 and on port 2002 +for REALM2 and REALM3. Additionally, per-realm parameters may be +specified in the kdc.conf file. The location of this file +may be specified by the KRB5_KDC_PROFILE environment variable. +Per-realm parameters specified in this file take precedence over +options specified on the command line. See the kdc.conf +description for further details.

+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

kdb5_util, kdc.conf, krb5.conf, +kdb5_ldap_util, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/admin_commands/ktutil.html b/krb5-1.21.3/doc/html/admin/admin_commands/ktutil.html new file mode 100644 index 00000000..93e66f84 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/admin_commands/ktutil.html @@ -0,0 +1,292 @@ + + + + + + + + + ktutil — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

ktutil

+
+

SYNOPSIS

+

ktutil

+
+
+

DESCRIPTION

+

The ktutil command invokes a command interface from which an +administrator can read, write, or edit entries in a keytab. (Kerberos +V4 srvtab files are no longer supported.)

+
+
+

COMMANDS

+
+

list

+
+

list [-t] [-k] [-e]

+
+

Displays the current keylist. If -t, -k, and/or -e are +specified, also display the timestamp, key contents, or enctype +(respectively).

+

Alias: l

+
+
+

read_kt

+
+

read_kt keytab

+
+

Read the Kerberos V5 keytab file keytab into the current keylist.

+

Alias: rkt

+
+
+

write_kt

+
+

write_kt keytab

+
+

Write the current keylist into the Kerberos V5 keytab file keytab.

+

Alias: wkt

+
+
+

clear_list

+
+

clear_list

+
+

Clear the current keylist.

+

Alias: clear

+
+
+

delete_entry

+
+

delete_entry slot

+
+

Delete the entry in slot number slot from the current keylist.

+

Alias: delent

+
+
+

add_entry

+
+

add_entry {-key|-password} -p principal +-k kvno [-e enctype] [-f|-s salt]

+
+

Add principal to keylist using key or password. If the -f flag +is specified, salt information will be fetched from the KDC; in this +case the -e flag may be omitted, or it may be supplied to force a +particular enctype. If the -f flag is not specified, the -e +flag must be specified, and the default salt will be used unless +overridden with the -s option.

+

Alias: addent

+
+
+

list_requests

+
+

list_requests

+
+

Displays a listing of available commands.

+

Aliases: lr, ?

+
+
+

quit

+
+

quit

+
+

Quits ktutil.

+

Aliases: exit, q

+
+
+
+

EXAMPLE

+
+
ktutil:  add_entry -password -p alice@BLEEP.COM -k 1 -e
+    aes128-cts-hmac-sha1-96
+Password for alice@BLEEP.COM:
+ktutil:  add_entry -password -p alice@BLEEP.COM -k 1 -e
+    aes256-cts-hmac-sha1-96
+Password for alice@BLEEP.COM:
+ktutil:  write_kt alice.keytab
+ktutil:
+
+
+
+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

kadmin, kdb5_util, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/admin_commands/sserver.html b/krb5-1.21.3/doc/html/admin/admin_commands/sserver.html new file mode 100644 index 00000000..b8db93f5 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/admin_commands/sserver.html @@ -0,0 +1,271 @@ + + + + + + + + + sserver — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

sserver

+
+

SYNOPSIS

+

sserver +[ -p port ] +[ -S keytab ] +[ server_port ]

+
+
+

DESCRIPTION

+

sserver and sclient are a simple demonstration client/server +application. When sclient connects to sserver, it performs a Kerberos +authentication, and then sserver returns to sclient the Kerberos +principal which was used for the Kerberos authentication. It makes a +good test that Kerberos has been successfully installed on a machine.

+

The service name used by sserver and sclient is sample. Hence, +sserver will require that there be a keytab entry for the service +sample/hostname.domain.name@REALM.NAME. This keytab is generated +using the kadmin program. The keytab file is usually +installed as DEFKTNAME.

+

The -S option allows for a different keytab than the default.

+

sserver is normally invoked out of inetd(8), using a line in +/etc/inetd.conf that looks like this:

+
sample stream tcp nowait root /usr/local/sbin/sserver sserver
+
+
+

Since sample is normally not a port defined in /etc/services, +you will usually have to add a line to /etc/services which looks +like this:

+
sample          13135/tcp
+
+
+

When using sclient, you will first have to have an entry in the +Kerberos database, by using kadmin, and then you have to get +Kerberos tickets, by using kinit. Also, if you are running +the sclient program on a different host than the sserver it will be +connecting to, be sure that both hosts have an entry in /etc/services +for the sample tcp port, and that the same port number is in both +files.

+

When you run sclient you should see something like this:

+
sendauth succeeded, reply is:
+reply len 32, contents:
+You are nlgilman@JIMI.MIT.EDU
+
+
+
+
+

COMMON ERROR MESSAGES

+
    +
  1. kinit returns the error:

    +
    kinit: Client not found in Kerberos database while getting
    +       initial credentials
    +
    +
    +

    This means that you didn’t create an entry for your username in the +Kerberos database.

    +
  2. +
  3. sclient returns the error:

    +
    unknown service sample/tcp; check /etc/services
    +
    +
    +

    This means that you don’t have an entry in /etc/services for the +sample tcp port.

    +
  4. +
  5. sclient returns the error:

    +
    connect: Connection refused
    +
    +
    +

    This probably means you didn’t edit /etc/inetd.conf correctly, or +you didn’t restart inetd after editing inetd.conf.

    +
  6. +
  7. sclient returns the error:

    +
    sclient: Server not found in Kerberos database while using
    +         sendauth
    +
    +
    +

    This means that the sample/hostname@LOCAL.REALM service was not +defined in the Kerberos database; it should be created using +kadmin, and a keytab file needs to be generated to make +the key for that service principal available for sclient.

    +
  8. +
  9. sclient returns the error:

    +
    sendauth rejected, error reply is:
    +    "No such file or directory"
    +
    +
    +

    This probably means sserver couldn’t find the keytab file. It was +probably not installed in the proper directory.

    +
  10. +
+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

sclient, kerberos, services(5), inetd(8)

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/advanced/index.html b/krb5-1.21.3/doc/html/admin/advanced/index.html new file mode 100644 index 00000000..5b65f238 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/advanced/index.html @@ -0,0 +1,160 @@ + + + + + + + + + Advanced topics — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/advanced/retiring-des.html b/krb5-1.21.3/doc/html/admin/advanced/retiring-des.html new file mode 100644 index 00000000..40ba435f --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/advanced/retiring-des.html @@ -0,0 +1,548 @@ + + + + + + + + + Retiring DES — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Retiring DES

+

Version 5 of the Kerberos protocol was originally implemented using +the Data Encryption Standard (DES) as a block cipher for encryption. +While it was considered secure at the time, advancements in computational +ability have rendered DES vulnerable to brute force attacks on its 56-bit +keyspace. As such, it is now considered insecure and should not be +used (RFC 6649).

+
+

History

+

DES was used in the original Kerberos implementation, and was the +only cryptosystem in krb5 1.0. Partial support for triple-DES (3DES) was +added in version 1.1, with full support following in version 1.2. +The Advanced Encryption Standard (AES), which supersedes DES, gained +partial support in version 1.3.0 of krb5 and full support in version 1.3.2. +However, deployments of krb5 using Kerberos databases created with older +versions of krb5 will not necessarily start using strong crypto for +ordinary operation without administrator intervention.

+

MIT krb5 began flagging deprecated encryption types with release 1.17, +and removed DES (single-DES) support in release 1.18. As a +consequence, a release prior to 1.18 is required to perform these +migrations.

+
+
+

Types of keys

+
    +
  • The database master key: This key is not exposed to user requests, +but is used to encrypt other key material stored in the kerberos +database. The database master key is currently stored as K/M +by default.

  • +
  • Password-derived keys: User principals frequently have keys +derived from a password. When a new password is set, the KDC +uses various string2key functions to generate keys in the database +for that principal.

  • +
  • Keytab keys: Application server principals generally use random +keys which are not derived from a password. When the database +entry is created, the KDC generates random keys of various enctypes +to enter in the database, which are conveyed to the application server +and stored in a keytab.

  • +
  • Session keys: These are short-term keys generated by the KDC while +processing client requests, with an enctype selected by the KDC.

  • +
+

For details on the various enctypes and how enctypes are selected by the KDC +for session keys and client/server long-term keys, see Encryption types. +When using the kadmin interface to generate new long-term keys, +the -e argument can be used to force a particular set of enctypes, +overriding the KDC default values.

+
+

Note

+

When the KDC is selecting a session key, it has no knowledge about the +kerberos installation on the server which will receive the service ticket, +only what keys are in the database for the service principal. +In order to allow uninterrupted operation to +clients while migrating away from DES, care must be taken to ensure that +kerberos installations on application server machines are configured to +support newer encryption types before keys of those new encryption types +are created in the Kerberos database for those server principals.

+
+
+
+

Upgrade procedure

+

This procedure assumes that the KDC software has already been upgraded +to a modern version of krb5 that supports non-DES keys, so that the +only remaining task is to update the actual keys used to service requests. +The realm used for demonstrating this procedure, ZONE.MIT.EDU, +is an example of the worst-case scenario, where all keys in the realm +are DES. The realm was initially created with a very old version of krb5, +and supported_enctypes in kdc.conf was set to a value +appropriate when the KDC was installed, but was not updated as the KDC +was upgraded:

+
[realms]
+        ZONE.MIT.EDU = {
+                [...]
+                master_key_type = des-cbc-crc
+                supported_enctypes = des-cbc-crc:normal des:normal des:v4 des:norealm des:onlyrealm des:afs3
+        }
+
+
+

This resulted in the keys for all principals in the realm being forced +to DES-only, unless specifically requested using kadmin.

+

Before starting the upgrade, all KDCs were running krb5 1.11, +and the database entries for some “high-value” principals were:

+
[root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'getprinc krbtgt/ZONE.MIT.EDU'
+[...]
+Number of keys: 1
+Key: vno 1, des-cbc-crc:v4
+[...]
+[root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'getprinc kadmin/admin'
+[...]
+Number of keys: 1
+Key: vno 15, des-cbc-crc
+[...]
+[root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'getprinc kadmin/changepw'
+[...]
+Number of keys: 1
+Key: vno 14, des-cbc-crc
+[...]
+
+
+

The krbtgt/REALM key appears to have never been changed since creation +(its kvno is 1), and all three database entries have only a des-cbc-crc key.

+
+

The krbtgt key and KDC keys

+

Perhaps the biggest single-step improvement in the security of the cell +is gained by strengthening the key of the ticket-granting service principal, +krbtgt/REALM—if this principal’s key is compromised, so is the +entire realm. Since the server that will handle service tickets +for this principal is the KDC itself, it is easy to guarantee that it +will be configured to support any encryption types which might be +selected. However, the default KDC behavior when creating new keys is to +remove the old keys, which would invalidate all existing tickets issued +against that principal, rendering the TGTs cached by clients useless. +Instead, a new key can be created with the old key retained, so that +existing tickets will still function until their scheduled expiry +(see Changing the krbtgt key).

+
[root@casio krb5kdc]# enctypes=aes256-cts-hmac-sha1-96:normal,\
+> aes128-cts-hmac-sha1-96:normal,des3-hmac-sha1:normal,des-cbc-crc:normal
+[root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q "cpw -e ${enctypes} -randkey \
+> -keepold krbtgt/ZONE.MIT.EDU"
+Authenticating as principal root/admin@ZONE.MIT.EDU with password.
+Key for "krbtgt/ZONE.MIT.EDU@ZONE.MIT.EDU" randomized.
+
+
+
+

Note

+

The new krbtgt@REALM key should be propagated to replica KDCs +immediately so that TGTs issued by the primary KDC can be used to +issue service tickets on replica KDCs. Replica KDCs will refuse +requests using the new TGT kvno until the new krbtgt entry has +been propagated to them.

+
+

It is necessary to explicitly specify the enctypes for the new database +entry, since supported_enctypes has not been changed. Leaving +supported_enctypes unchanged makes a potential rollback operation +easier, since all new keys of new enctypes are the result of explicit +administrator action and can be easily enumerated. +Upgrading the krbtgt key should have minimal user-visible disruption other +than that described in the note above, since only clients which list the +new enctypes as supported will use them, per the procedure +in Session key selection. +Once the krbtgt key is updated, the session and ticket keys for user +TGTs will be strong keys, but subsequent requests +for service tickets will still get DES keys until the service principals +have new keys generated. Application service +remains uninterrupted due to the key-selection procedure on the KDC.

+

After the change, the database entry is now:

+
[root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'getprinc krbtgt/ZONE.MIT.EDU'
+[...]
+Number of keys: 5
+Key: vno 2, aes256-cts-hmac-sha1-96
+Key: vno 2, aes128-cts-hmac-sha1-96
+Key: vno 2, des3-cbc-sha1
+Key: vno 2, des-cbc-crc
+Key: vno 1, des-cbc-crc:v4
+[...]
+
+
+

Since the expected disruptions from rekeying the krbtgt principal are +minor, after a short testing period, it is +appropriate to rekey the other high-value principals, kadmin/admin@REALM +and kadmin/changepw@REALM. These are the service principals used for +changing user passwords and updating application keytabs. The kadmin +and password-changing services are regular kerberized services, so the +session-key-selection algorithm described in Session key selection +applies. It is particularly important to have strong session keys for +these services, since user passwords and new long-term keys are conveyed +over the encrypted channel.

+
[root@casio krb5kdc]# enctypes=aes256-cts-hmac-sha1-96:normal,\
+> aes128-cts-hmac-sha1-96:normal,des3-hmac-sha1:normal
+[root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q "cpw -e ${enctypes} -randkey \
+> kadmin/admin"
+Authenticating as principal root/admin@ZONE.MIT.EDU with password.
+Key for "kadmin/admin@ZONE.MIT.EDU" randomized.
+[root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q "cpw -e ${enctypes} -randkey \
+> kadmin/changepw"
+Authenticating as principal root/admin@ZONE.MIT.EDU with password.
+Key for "kadmin/changepw@ZONE.MIT.EDU" randomized.
+
+
+

It is not necessary to retain a single-DES key for these services, since +password changes are not part of normal daily workflow, and disruption +from a client failure is likely to be minimal. Furthermore, if a kerberos +client experiences failure changing a user password or keytab key, +this indicates that that client will become inoperative once services +are rekeyed to non-DES enctypes. Such problems can be detected early +at this stage, giving more time for corrective action.

+
+
+

Adding strong keys to application servers

+

Before switching the default enctypes for new keys over to strong enctypes, +it may be desired to test upgrading a handful of services with the +new configuration before flipping the switch for the defaults. This +still requires using the -e argument in kadmin to get non-default +enctypes:

+
[root@casio krb5kdc]# enctypes=aes256-cts-hmac-sha1-96:normal,\
+> aes128-cts-hmac-sha1-96:normal,des3-cbc-sha1:normal,des-cbc-crc:normal
+[root@casio krb5kdc]# kadmin -r ZONE.MIT.EDU -p zephyr/zephyr@ZONE.MIT.EDU -k -t \
+> /etc/zephyr/krb5.keytab  -q "ktadd -e ${enctypes} \
+> -k /etc/zephyr/krb5.keytab zephyr/zephyr@ZONE.MIT.EDU"
+Authenticating as principal zephyr/zephyr@ZONE.MIT.EDU with keytab /etc/zephyr/krb5.keytab.
+Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 4, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:/etc/zephyr/krb5.keytab.
+Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 4, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:/etc/zephyr/krb5.keytab.
+Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 4, encryption type des3-cbc-sha1 added to keytab WRFILE:/etc/zephyr/krb5.keytab.
+Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 4, encryption type des-cbc-crc added to keytab WRFILE:/etc/zephyr/krb5.keytab.
+
+
+

Be sure to remove the old keys from the application keytab, per best +practice.

+
[root@casio krb5kdc]# k5srvutil -f /etc/zephyr/krb5.keytab delold
+Authenticating as principal zephyr/zephyr@ZONE.MIT.EDU with keytab /etc/zephyr/krb5.keytab.
+Entry for principal zephyr/zephyr@ZONE.MIT.EDU with kvno 3 removed from keytab WRFILE:/etc/zephyr/krb5.keytab.
+
+
+
+
+

Adding strong keys by default

+

Once the high-visibility services have been rekeyed, it is probably +appropriate to change kdc.conf to generate keys with the new +encryption types by default. This enables server administrators to generate +new enctypes with the change subcommand of k5srvutil, +and causes user password +changes to add new encryption types for their entries. It will probably +be necessary to implement administrative controls to cause all user +principal keys to be updated in a reasonable period of time, whether +by forcing password changes or a password synchronization service that +has access to the current password and can add the new keys.

+
[realms]
+        ZONE.MIT.EDU = {
+                supported_enctypes = aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des3-hmac-sha1:normal des-cbc-crc:normal
+
+
+
+

Note

+

The krb5kdc process must be restarted for these changes to take effect.

+
+

At this point, all service administrators can update their services and the +servers behind them to take advantage of strong cryptography. +If necessary, the server’s krb5 installation should be configured and/or +upgraded to a version supporting non-DES keys. See Encryption types for +krb5 version and configuration settings. +Only when the service is configured to accept non-DES keys should +the key version number be incremented and new keys generated +(k5srvutil change && k5srvutil delold).

+
root@dr-willy:~# k5srvutil change
+Authenticating as principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with keytab /etc/krb5.keytab.
+Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 3, encryption type AES-256 CTS mode with 96-bit SHA-1 HMAC added to keytab WRFILE:/etc/krb5.keytab.
+Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 3, encryption type AES-128 CTS mode with 96-bit SHA-1 HMAC added to keytab WRFILE:/etc/krb5.keytab.
+Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 3, encryption type Triple DES cbc mode with HMAC/sha1 added to keytab WRFILE:/etc/krb5.keytab.
+Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 3, encryption type DES cbc mode with CRC-32 added to keytab WRFILE:/etc/krb5.keytab.
+root@dr-willy:~# klist -e -k -t /etc/krb5.keytab
+Keytab name: WRFILE:/etc/krb5.keytab
+KVNO Timestamp         Principal
+---- ----------------- --------------------------------------------------------
+   2 10/10/12 17:03:59 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (DES cbc mode with CRC-32)
+   3 12/12/12 15:31:19 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (AES-256 CTS mode with 96-bit SHA-1 HMAC)
+   3 12/12/12 15:31:19 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (AES-128 CTS mode with 96-bit SHA-1 HMAC)
+   3 12/12/12 15:31:19 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (Triple DES cbc mode with HMAC/sha1)
+   3 12/12/12 15:31:19 host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU (DES cbc mode with CRC-32)
+root@dr-willy:~# k5srvutil delold
+Authenticating as principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with keytab /etc/krb5.keytab.
+Entry for principal host/dr-willy.xvm.mit.edu@ZONE.MIT.EDU with kvno 2 removed from keytab WRFILE:/etc/krb5.keytab.
+
+
+

When a single service principal is shared by multiple backend servers in +a load-balanced environment, it may be necessary to schedule downtime +or adjust the population in the load-balanced pool in order to propagate +the updated keytab to all hosts in the pool with minimal service interruption.

+
+
+

Removing DES keys from usage

+

This situation remains something of a testing or transitory state, +as new DES keys are still being generated, and will be used if requested +by a client. To make more progress removing DES from the realm, the KDC +should be configured to not generate such keys by default.

+
+

Note

+

An attacker posing as a client can implement a brute force attack against +a DES key for any principal, if that key is in the current (highest-kvno) +key list. This attack is only possible if allow_weak_crypto = true +is enabled on the KDC. Setting the +requires_preauth flag on a +principal forces this attack to be an online attack, much slower than +the offline attack otherwise available to the attacker. However, setting +this flag on a service principal is not always advisable; see the entry in +add_principal for details.

+
+

The following KDC configuration will not generate DES keys by default:

+
[realms]
+        ZONE.MIT.EDU = {
+                supported_enctypes = aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des3-hmac-sha1:normal
+
+
+
+

Note

+

As before, the KDC process must be restarted for this change to take +effect. It is best practice to update kdc.conf on all KDCs, not just the +primary, to avoid unpleasant surprises should the primary fail and a +replica need to be promoted.

+
+

It is now appropriate to remove the legacy single-DES key from the +krbtgt/REALM entry:

+
[root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q "cpw -randkey -keepold \
+> krbtgt/ZONE.MIT.EDU"
+Authenticating as principal host/admin@ATHENA.MIT.EDU with password.
+Key for "krbtgt/ZONE.MIT.EDU@ZONE.MIT.EDU" randomized.
+
+
+

After the maximum ticket lifetime has passed, the old database entry +should be removed.

+
[root@casio krb5kdc]# kadmin.local -r ZONE.MIT.EDU -q 'purgekeys krbtgt/ZONE.MIT.EDU'
+Authenticating as principal root/admin@ZONE.MIT.EDU with password.
+Old keys for principal "krbtgt/ZONE.MIT.EDU@ZONE.MIT.EDU" purged.
+
+
+

After the KDC is restarted with the new supported_enctypes, +all user password changes and application keytab updates will not +generate DES keys by default.

+
contents-vnder-pressvre:~> kpasswd zonetest@ZONE.MIT.EDU
+Password for zonetest@ZONE.MIT.EDU:  [enter old password]
+Enter new password:                  [enter new password]
+Enter it again:                      [enter new password]
+Password changed.
+contents-vnder-pressvre:~> kadmin -r ZONE.MIT.EDU -q 'getprinc zonetest'
+[...]
+Number of keys: 3
+Key: vno 9, aes256-cts-hmac-sha1-96
+Key: vno 9, aes128-cts-hmac-sha1-96
+Key: vno 9, des3-cbc-sha1
+[...]
+
+[kaduk@glossolalia ~]$ kadmin -p kaduk@ZONE.MIT.EDU -r ZONE.MIT.EDU -k \
+> -t kaduk-zone.keytab -q 'ktadd -k kaduk-zone.keytab kaduk@ZONE.MIT.EDU'
+Authenticating as principal kaduk@ZONE.MIT.EDU with keytab kaduk-zone.keytab.
+Entry for principal kaduk@ZONE.MIT.EDU with kvno 3, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:kaduk-zone.keytab.
+Entry for principal kaduk@ZONE.MIT.EDU with kvno 3, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:kaduk-zone.keytab.
+Entry for principal kaduk@ZONE.MIT.EDU with kvno 3, encryption type des3-cbc-sha1 added to keytab WRFILE:kaduk-zone.keytab.
+
+
+

Once all principals have been re-keyed, DES support can be disabled on the +KDC (allow_weak_crypto = false), and client machines can remove +allow_weak_crypto = true from their krb5.conf configuration +files, completing the migration. allow_weak_crypto takes precedence over +all places where DES enctypes could be explicitly configured. DES keys will +not be used, even if they are present, when allow_weak_crypto = false.

+
+
+

Support for legacy services

+

If there remain legacy services which do not support non-DES enctypes +(such as older versions of AFS), allow_weak_crypto must remain +enabled on the KDC. Client machines need not have this setting, +though—applications which require DES can use API calls to allow +weak crypto on a per-request basis, overriding the system krb5.conf. +However, having allow_weak_crypto set on the KDC means that any +principals which have a DES key in the database could still use those +keys. To minimize the use of DES in the realm and restrict it to just +legacy services which require DES, it is necessary to remove all other +DES keys. The realm has been configured such that at password and +keytab change, no DES keys will be generated by default. The task +then reduces to requiring user password changes and having server +administrators update their service keytabs. Administrative outreach +will be necessary, and if the desire to eliminate DES is sufficiently +strong, the KDC administrators may choose to randkey any principals +which have not been rekeyed after some timeout period, forcing the +user to contact the helpdesk for access.

+
+
+
+

The Database Master Key

+

This procedure does not alter K/M@REALM, the key used to encrypt key +material in the Kerberos database. (This is the key stored in the stash file +on the KDC if stash files are used.) However, the security risk of +a single-DES key for K/M is minimal, given that access to material +encrypted in K/M (the Kerberos database) is generally tightly controlled. +If an attacker can gain access to the encrypted database, they likely +have access to the stash file as well, rendering the weak cryptography +broken by non-cryptographic means. As such, upgrading K/M to a stronger +encryption type is unlikely to be a high-priority task.

+

Is is possible to upgrade the master key used for the database, if +desired. Using kdb5_util’s add_mkey, use_mkey, and +update_princ_encryption commands, a new master key can be added +and activated for use on new key material, and the existing entries +converted to the new master key.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/appl_servers.html b/krb5-1.21.3/doc/html/admin/appl_servers.html new file mode 100644 index 00000000..4b92f4f5 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/appl_servers.html @@ -0,0 +1,306 @@ + + + + + + + + + Application servers — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Application servers

+

If you need to install the Kerberos V5 programs on an application +server, please refer to the Kerberos V5 Installation Guide. Once you +have installed the software, you need to add that host to the Kerberos +database (see Principals), and generate a keytab for that host, +that contains the host’s key. You also need to make sure the host’s +clock is within your maximum clock skew of the KDCs.

+
+

Keytabs

+

A keytab is a host’s copy of its own keylist, which is analogous to a +user’s password. An application server that needs to authenticate +itself to the KDC has to have a keytab that contains its own principal +and key. Just as it is important for users to protect their +passwords, it is equally important for hosts to protect their keytabs. +You should always store keytab files on local disk, and make them +readable only by root, and you should never send a keytab file over a +network in the clear. Ideally, you should run the kadmin +command to extract a keytab on the host on which the keytab is to +reside.

+
+

Adding principals to keytabs

+

To generate a keytab, or to add a principal to an existing keytab, use +the ktadd command from kadmin. Here is a sample session, using +configuration files that enable only AES encryption:

+
kadmin: ktadd host/daffodil.mit.edu@ATHENA.MIT.EDU
+Entry for principal host/daffodil.mit.edu with kvno 2, encryption type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab
+Entry for principal host/daffodil.mit.edu with kvno 2, encryption type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab
+
+
+
+
+

Removing principals from keytabs

+

To remove a principal from an existing keytab, use the kadmin +ktremove command:

+
kadmin:  ktremove host/daffodil.mit.edu@ATHENA.MIT.EDU
+Entry for principal host/daffodil.mit.edu with kvno 2 removed from keytab FILE:/etc/krb5.keytab.
+Entry for principal host/daffodil.mit.edu with kvno 2 removed from keytab FILE:/etc/krb5.keytab.
+
+
+
+
+

Using a keytab to acquire client credentials

+

While keytabs are ordinarily used to accept credentials from clients, +they can also be used to acquire initial credentials, allowing one +service to authenticate to another.

+

To manually obtain credentials using a keytab, use the kinit +-k option, together with the -t option if the keytab is not in +the default location.

+

Beginning with release 1.11, GSSAPI applications can be configured to +automatically obtain initial credentials from a keytab as needed. The +recommended configuration is as follows:

+
    +
  1. Create a keytab containing a single entry for the desired client +identity.

  2. +
  3. Place the keytab in a location readable by the service, and set the +KRB5_CLIENT_KTNAME environment variable to its filename. +Alternatively, use the default_client_keytab_name profile +variable in [libdefaults], or use the default location of +DEFCKTNAME.

  4. +
  5. Set KRB5CCNAME to a filename writable by the service, which +will not be used for any other purpose. Do not manually obtain +credentials at this location. (Another credential cache type +besides FILE can be used if desired, as long the cache will not +conflict with another use. A MEMORY cache can be used if the +service runs as a long-lived process. See Credential cache +for details.)

  6. +
  7. Start the service. When it authenticates using GSSAPI, it will +automatically obtain credentials from the client keytab into the +specified credential cache, and refresh them before they expire.

  8. +
+
+
+
+

Clock Skew

+

A Kerberos application server host must keep its clock synchronized or +it will reject authentication requests from clients. Modern operating +systems typically provide a facility to maintain the correct time; +make sure it is enabled. This is especially important on virtual +machines, where clocks tend to drift more rapidly than normal machine +clocks.

+

The default allowable clock skew is controlled by the clockskew +variable in [libdefaults].

+
+
+

Getting DNS information correct

+

Several aspects of Kerberos rely on name service. When a hostname is +used to name a service, clients may canonicalize the hostname using +forward and possibly reverse name resolution. The result of this +canonicalization must match the principal entry in the host’s keytab, +or authentication will fail. To work with all client canonicalization +configurations, each host’s canonical name must be the fully-qualified +host name (including the domain), and each host’s IP address must +reverse-resolve to the canonical name.

+

Configuration of hostnames varies by operating system. On the +application server itself, canonicalization will typically use the +/etc/hosts file rather than the DNS. Ensure that the line for the +server’s hostname is in the following form:

+
IP address      fully-qualified hostname        aliases
+
+
+

Here is a sample /etc/hosts file:

+
# this is a comment
+127.0.0.1      localhost localhost.mit.edu
+10.0.0.6       daffodil.mit.edu daffodil trillium wake-robin
+
+
+

The output of klist -k for this example host should look like:

+
viola# klist -k
+Keytab name: /etc/krb5.keytab
+KVNO Principal
+---- ------------------------------------------------------------
+   2 host/daffodil.mit.edu@ATHENA.MIT.EDU
+
+
+

If you were to ssh to this host with a fresh credentials cache (ticket +file), and then klist, the output should list a service +principal of host/daffodil.mit.edu@ATHENA.MIT.EDU.

+
+
+

Configuring your firewall to work with Kerberos V5

+

If you need off-site users to be able to get Kerberos tickets in your +realm, they must be able to get to your KDC. This requires either +that you have a replica KDC outside your firewall, or that you +configure your firewall to allow UDP requests into at least one of +your KDCs, on whichever port the KDC is running. (The default is port +88; other ports may be specified in the KDC’s kdc.conf +file.) Similarly, if you need off-site users to be able to change +their passwords in your realm, they must be able to get to your +Kerberos admin server on the kpasswd port (which defaults to 464). If +you need off-site users to be able to administer your Kerberos realm, +they must be able to get to your Kerberos admin server on the +administrative port (which defaults to 749).

+

If your on-site users inside your firewall will need to get to KDCs in +other realms, you will also need to configure your firewall to allow +outgoing TCP and UDP requests to port 88, and to port 464 to allow +password changes. If your on-site users inside your firewall will +need to get to Kerberos admin servers in other realms, you will also +need to allow outgoing TCP and UDP requests to port 749.

+

If any of your KDCs are outside your firewall, you will need to allow +kprop requests to get through to the remote KDC. kprop uses +the krb5_prop service on port 754 (tcp).

+

The book UNIX System Security, by David Curry, is a good starting +point for learning to configure firewalls.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/auth_indicator.html b/krb5-1.21.3/doc/html/admin/auth_indicator.html new file mode 100644 index 00000000..1ac39373 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/auth_indicator.html @@ -0,0 +1,201 @@ + + + + + + + + + Authentication indicators — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Authentication indicators

+

As of release 1.14, the KDC can be configured to annotate tickets if +the client authenticated using a stronger preauthentication mechanism +such as PKINIT or OTP. These +annotations are called “authentication indicators.” Service +principals can be configured to require particular authentication +indicators in order to authenticate to that service. An +authentication indicator value can be any string chosen by the KDC +administrator; there are no pre-set values.

+

To use authentication indicators with PKINIT or OTP, first configure +the KDC to include an indicator when that preauthentication mechanism +is used. For PKINIT, use the pkinit_indicator variable in +kdc.conf. For OTP, use the indicator variable in the +token type definition, or specify the indicators in the otp user +string as described in OTP Preauthentication.

+

To require an indicator to be present in order to authenticate to a +service principal, set the require_auth string attribute on the +principal to the indicator value to be required. If you wish to allow +one of several indicators to be accepted, you can specify multiple +indicator values separated by spaces.

+

For example, a realm could be configured to set the authentication +indicator value “strong” when PKINIT is used to authenticate, using a +setting in the [realms] subsection:

+
pkinit_indicator = strong
+
+
+

A service principal could be configured to require the “strong” +authentication indicator value:

+
$ kadmin setstr host/high.value.server require_auth strong
+Password for user/admin@KRBTEST.COM:
+
+
+

A user who authenticates with PKINIT would be able to obtain a ticket +for the service principal:

+
$ kinit -X X509_user_identity=FILE:/my/cert.pem,/my/key.pem user
+$ kvno host/high.value.server
+host/high.value.server@KRBTEST.COM: kvno = 1
+
+
+

but a user who authenticates with a password would not:

+
$ kinit user
+Password for user@KRBTEST.COM:
+$ kvno host/high.value.server
+kvno: KDC policy rejects request while getting credentials for
+  host/high.value.server@KRBTEST.COM
+
+
+

GSSAPI server applications can inspect authentication indicators +through the auth-indicators name +attribute.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/backup_host.html b/krb5-1.21.3/doc/html/admin/backup_host.html new file mode 100644 index 00000000..ebf2954a --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/backup_host.html @@ -0,0 +1,184 @@ + + + + + + + + + Backups of secure hosts — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Backups of secure hosts

+

When you back up a secure host, you should exclude the host’s keytab +file from the backup. If someone obtained a copy of the keytab from a +backup, that person could make any host masquerade as the host whose +keytab was compromised. In many configurations, knowledge of the +host’s keytab also allows root access to the host. This could be +particularly dangerous if the compromised keytab was from one of your +KDCs. If the machine has a disk crash and the keytab file is lost, it +is easy to generate another keytab file. (See Adding principals to keytabs.) +If you are unable to exclude particular files from backups, you should +ensure that the backups are kept as secure as the host’s root +password.

+
+

Backing up the Kerberos database

+

As with any file, it is possible that your Kerberos database could +become corrupted. If this happens on one of the replica KDCs, you +might never notice, since the next automatic propagation of the +database would install a fresh copy. However, if it happens to the +primary KDC, the corrupted database would be propagated to all of the +replicas during the next propagation. For this reason, MIT recommends +that you back up your Kerberos database regularly. Because the primary +KDC is continuously dumping the database to a file in order to +propagate it to the replica KDCs, it is a simple matter to have a cron +job periodically copy the dump file to a secure machine elsewhere on +your network. (Of course, it is important to make the host where +these backups are stored as secure as your KDCs, and to encrypt its +transmission across your network.) Then if your database becomes +corrupted, you can load the most recent dump onto the primary KDC. +(See Dumping and loading a Kerberos database.)

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/conf_files/index.html b/krb5-1.21.3/doc/html/admin/conf_files/index.html new file mode 100644 index 00000000..57c59b1e --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/conf_files/index.html @@ -0,0 +1,178 @@ + + + + + + + + + Configuration Files — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Configuration Files

+

Kerberos uses configuration files to allow administrators to specify +settings on a per-machine basis. krb5.conf applies to all +applications using the Kerboros library, on clients and servers. +For KDC-specific applications, additional settings can be specified in +kdc.conf; the two files are merged into a configuration profile +used by applications accessing the KDC database directly. kadm5.acl +is also only used on the KDC, it controls permissions for modifying the +KDC database.

+
+

Contents

+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/conf_files/kadm5_acl.html b/krb5-1.21.3/doc/html/admin/conf_files/kadm5_acl.html new file mode 100644 index 00000000..611864b3 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/conf_files/kadm5_acl.html @@ -0,0 +1,337 @@ + + + + + + + + + kadm5.acl — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kadm5.acl

+
+

DESCRIPTION

+

The Kerberos kadmind daemon uses an Access Control List +(ACL) file to manage access rights to the Kerberos database. +For operations that affect principals, the ACL file also controls +which principals can operate on which other principals.

+

The default location of the Kerberos ACL file is +LOCALSTATEDIR/krb5kdc/kadm5.acl unless this is overridden by the acl_file +variable in kdc.conf.

+
+
+

SYNTAX

+

Empty lines and lines starting with the sharp sign (#) are +ignored. Lines containing ACL entries have the format:

+
principal  permissions  [target_principal  [restrictions] ]
+
+
+
+

Note

+

Line order in the ACL file is important. The first matching entry +will control access for an actor principal on a target principal.

+
+
+
principal

(Partially or fully qualified Kerberos principal name.) Specifies +the principal whose permissions are to be set.

+

Each component of the name may be wildcarded using the * +character.

+
+
permissions

Specifies what operations may or may not be performed by a +principal matching a particular entry. This is a string of one or +more of the following list of characters or their upper-case +counterparts. If the character is upper-case, then the operation +is disallowed. If the character is lower-case, then the operation +is permitted.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

a

[Dis]allows the addition of principals or policies

c

[Dis]allows the changing of passwords for principals

d

[Dis]allows the deletion of principals or policies

e

[Dis]allows the extraction of principal keys

i

[Dis]allows inquiries about principals or policies

l

[Dis]allows the listing of all principals or policies

m

[Dis]allows the modification of principals or policies

p

[Dis]allows the propagation of the principal database (used in Incremental database propagation)

s

[Dis]allows the explicit setting of the key for a principal

x

Short for admcilsp. All privileges (except e)

*

Same as x.

+
+
+
+

Note

+

The extract privilege is not included in the wildcard +privilege; it must be explicitly assigned. This privilege +allows the user to extract keys from the database, and must be +handled with great care to avoid disclosure of important keys +like those of the kadmin/* or krbtgt/* principals. The +lockdown_keys principal attribute can be used to prevent +key extraction from specific principals regardless of the +granted privilege.

+
+
+
target_principal

(Optional. Partially or fully qualified Kerberos principal name.) +Specifies the principal on which permissions may be applied. +Each component of the name may be wildcarded using the * +character.

+

target_principal can also include back-references to principal, +in which *number matches the corresponding wildcard in +principal.

+
+
restrictions

(Optional) A string of flags. Allowed restrictions are:

+
+
+
{+|-}flagname

flag is forced to the indicated value. The permissible flags +are the same as those for the default_principal_flags +variable in kdc.conf.

+
+
-clearpolicy

policy is forced to be empty.

+
+
-policy pol

policy is forced to be pol.

+
+
-{expire, pwexpire, maxlife, maxrenewlife} time

(getdate time string) associated value will be forced to +MIN(time, requested value).

+
+
+
+

The above flags act as restrictions on any add or modify operation +which is allowed due to that ACL line.

+
+
+
+

Warning

+

If the kadmind ACL file is modified, the kadmind daemon needs to be +restarted for changes to take effect.

+
+
+
+

EXAMPLE

+

Here is an example of a kadm5.acl file:

+
*/admin@ATHENA.MIT.EDU    *                               # line 1
+joeadmin@ATHENA.MIT.EDU   ADMCIL                          # line 2
+joeadmin/*@ATHENA.MIT.EDU i   */root@ATHENA.MIT.EDU       # line 3
+*/root@ATHENA.MIT.EDU     ci  *1@ATHENA.MIT.EDU           # line 4
+*/root@ATHENA.MIT.EDU     l   *                           # line 5
+sms@ATHENA.MIT.EDU        x   * -maxlife 9h -postdateable # line 6
+
+
+

(line 1) Any principal in the ATHENA.MIT.EDU realm with an +admin instance has all administrative privileges except extracting +keys.

+

(lines 1-3) The user joeadmin has all permissions except +extracting keys with his admin instance, +joeadmin/admin@ATHENA.MIT.EDU (matches line 1). He has no +permissions at all with his null instance, joeadmin@ATHENA.MIT.EDU +(matches line 2). His root and other non-admin, non-null +instances (e.g., extra or dbadmin) have inquire permissions +with any principal that has the instance root (matches line 3).

+

(line 4) Any root principal in ATHENA.MIT.EDU can inquire +or change the password of their null instance, but not any other +null instance. (Here, *1 denotes a back-reference to the +component matching the first wildcard in the actor principal.)

+

(line 5) Any root principal in ATHENA.MIT.EDU can generate +the list of principals in the database, and the list of policies +in the database. This line is separate from line 4, because list +permission can only be granted globally, not to specific target +principals.

+

(line 6) Finally, the Service Management System principal +sms@ATHENA.MIT.EDU has all permissions except extracting keys, but +any principal that it creates or modifies will not be able to get +postdateable tickets or tickets with a life of longer than 9 hours.

+
+
+

MODULE BEHAVIOR

+

The ACL file can coexist with other authorization modules in release +1.16 and later, as configured in the kadm5_auth interface section of +krb5.conf. The ACL file will positively authorize +operations according to the rules above, but will never +authoritatively deny an operation, so other modules can authorize +operations in addition to those authorized by the ACL file.

+

To operate without an ACL file, set the acl_file variable in +kdc.conf to the empty string with acl_file = "".

+
+
+

SEE ALSO

+

kdc.conf, kadmind

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/conf_files/kdc_conf.html b/krb5-1.21.3/doc/html/admin/conf_files/kdc_conf.html new file mode 100644 index 00000000..dc6876d6 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/conf_files/kdc_conf.html @@ -0,0 +1,1073 @@ + + + + + + + + + kdc.conf — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kdc.conf

+

The kdc.conf file supplements krb5.conf for programs which +are typically only used on a KDC, such as the krb5kdc and +kadmind daemons and the kdb5_util program. +Relations documented here may also be specified in krb5.conf; for the +KDC programs mentioned, krb5.conf and kdc.conf will be merged into a +single configuration profile.

+

Normally, the kdc.conf file is found in the KDC state directory, +LOCALSTATEDIR/krb5kdc. You can override the default location by setting the +environment variable KRB5_KDC_PROFILE.

+

Please note that you need to restart the KDC daemon for any configuration +changes to take effect.

+
+

Structure

+

The kdc.conf file is set up in the same format as the +krb5.conf file.

+
+
+

Sections

+

The kdc.conf file may contain the following sections:

+ ++++ + + + + + + + + + + + + + + + + + +

[kdcdefaults]

Default values for KDC behavior

[realms]

Realm-specific database configuration and settings

[dbdefaults]

Default database settings

[dbmodules]

Per-database settings

[logging]

Controls how Kerberos daemons perform logging

+
+

[kdcdefaults]

+

Some relations in the [kdcdefaults] section specify default values for +realm variables, to be used if the [realms] subsection does not +contain a relation for the tag. See the [realms] section for +the definitions of these relations.

+
    +
  • host_based_services

  • +
  • kdc_listen

  • +
  • kdc_ports

  • +
  • kdc_tcp_listen

  • +
  • kdc_tcp_ports

  • +
  • no_host_referral

  • +
  • restrict_anonymous_to_tgt

  • +
+

The following [kdcdefaults] variables have no per-realm equivalent:

+
+
kdc_max_dgram_reply_size

Specifies the maximum packet size that can be sent over UDP. The +default value is 4096 bytes.

+
+
kdc_tcp_listen_backlog

(Integer.) Set the size of the listen queue length for the KDC +daemon. The value may be limited by OS settings. The default +value is 5.

+
+
spake_preauth_kdc_challenge

(String.) Specifies the group for a SPAKE optimistic challenge. +See the spake_preauth_groups variable in [libdefaults] +for possible values. The default is not to issue an optimistic +challenge. (New in release 1.17.)

+
+
+
+
+

[realms]

+

Each tag in the [realms] section is the name of a Kerberos realm. The +value of the tag is a subsection where the relations define KDC +parameters for that particular realm. The following example shows how +to define one parameter for the ATHENA.MIT.EDU realm:

+
[realms]
+    ATHENA.MIT.EDU = {
+        max_renewable_life = 7d 0h 0m 0s
+    }
+
+
+

The following tags may be specified in a [realms] subsection:

+
+
acl_file

(String.) Location of the access control list file that +kadmind uses to determine which principals are allowed +which permissions on the Kerberos database. To operate without an +ACL file, set this relation to the empty string with acl_file = +"". The default value is LOCALSTATEDIR/krb5kdc/kadm5.acl. For more +information on Kerberos ACL file see kadm5.acl.

+
+
database_module

(String.) This relation indicates the name of the configuration +section under [dbmodules] for database-specific parameters +used by the loadable database library. The default value is the +realm name. If this configuration section does not exist, default +values will be used for all database parameters.

+
+
database_name

(String, deprecated.) This relation specifies the location of the +Kerberos database for this realm, if the DB2 module is being used +and the [dbmodules] configuration section does not specify a +database name. The default value is LOCALSTATEDIR/krb5kdc/principal.

+
+
default_principal_expiration

(Absolute time string.) Specifies the default expiration date of +principals created in this realm. The default value is 0, which +means no expiration date.

+
+
default_principal_flags

(Flag string.) Specifies the default attributes of principals +created in this realm. The format for this string is a +comma-separated list of flags, with ‘+’ before each flag that +should be enabled and ‘-’ before each flag that should be +disabled. The postdateable, forwardable, tgt-based, +renewable, proxiable, dup-skey, allow-tickets, and +service flags default to enabled.

+

There are a number of possible flags:

+
+
allow-tickets

Enabling this flag means that the KDC will issue tickets for +this principal. Disabling this flag essentially deactivates +the principal within this realm.

+
+
dup-skey

Enabling this flag allows the KDC to issue user-to-user +service tickets for this principal.

+
+
forwardable

Enabling this flag allows the principal to obtain forwardable +tickets.

+
+
hwauth

If this flag is enabled, then the principal is required to +preauthenticate using a hardware device before receiving any +tickets.

+
+
no-auth-data-required

Enabling this flag prevents PAC or AD-SIGNEDPATH data from +being added to service tickets for the principal.

+
+
ok-as-delegate

If this flag is enabled, it hints the client that credentials +can and should be delegated when authenticating to the +service.

+
+
ok-to-auth-as-delegate

Enabling this flag allows the principal to use S4USelf tickets.

+
+
postdateable

Enabling this flag allows the principal to obtain postdateable +tickets.

+
+
preauth

If this flag is enabled on a client principal, then that +principal is required to preauthenticate to the KDC before +receiving any tickets. On a service principal, enabling this +flag means that service tickets for this principal will only +be issued to clients with a TGT that has the preauthenticated +bit set.

+
+
proxiable

Enabling this flag allows the principal to obtain proxy +tickets.

+
+
pwchange

Enabling this flag forces a password change for this +principal.

+
+
pwservice

If this flag is enabled, it marks this principal as a password +change service. This should only be used in special cases, +for example, if a user’s password has expired, then the user +has to get tickets for that principal without going through +the normal password authentication in order to be able to +change the password.

+
+
renewable

Enabling this flag allows the principal to obtain renewable +tickets.

+
+
service

Enabling this flag allows the the KDC to issue service tickets +for this principal. In release 1.17 and later, user-to-user +service tickets are still allowed if the dup-skey flag is +set.

+
+
tgt-based

Enabling this flag allows a principal to obtain tickets based +on a ticket-granting-ticket, rather than repeating the +authentication process that was used to obtain the TGT.

+
+
+
+
dict_file

(String.) Location of the dictionary file containing strings that +are not allowed as passwords. The file should contain one string +per line, with no additional whitespace. If none is specified or +if there is no policy assigned to the principal, no dictionary +checks of passwords will be performed.

+
+
disable_pac

(Boolean value.) If true, the KDC will not issue PACs for this +realm, and S4U2Self and S4U2Proxy operations will be disabled. +The default is false, which will permit the KDC to issue PACs. +New in release 1.20.

+
+
encrypted_challenge_indicator

(String.) Specifies the authentication indicator value that the KDC +asserts into tickets obtained using FAST encrypted challenge +pre-authentication. New in 1.16.

+
+
host_based_services

(Whitespace- or comma-separated list.) Lists services which will +get host-based referral processing even if the server principal is +not marked as host-based by the client.

+
+
iprop_enable

(Boolean value.) Specifies whether incremental database +propagation is enabled. The default value is false.

+
+
iprop_ulogsize

(Integer.) Specifies the maximum number of log entries to be +retained for incremental propagation. The default value is 1000. +Prior to release 1.11, the maximum value was 2500. New in release +1.19.

+
+
iprop_master_ulogsize

The name for iprop_ulogsize prior to release 1.19. Its value is +used as a fallback if iprop_ulogsize is not specified.

+
+
iprop_replica_poll

(Delta time string.) Specifies how often the replica KDC polls +for new updates from the primary. The default value is 2m +(that is, two minutes). New in release 1.17.

+
+
iprop_slave_poll

(Delta time string.) The name for iprop_replica_poll prior to +release 1.17. Its value is used as a fallback if +iprop_replica_poll is not specified.

+
+
iprop_listen

(Whitespace- or comma-separated list.) Specifies the iprop RPC +listening addresses and/or ports for the kadmind daemon. +Each entry may be an interface address, a port number, or an +address and port number separated by a colon. If the address +contains colons, enclose it in square brackets. If no address is +specified, the wildcard address is used. If kadmind fails to bind +to any of the specified addresses, it will fail to start. The +default (when iprop_enable is true) is to bind to the wildcard +address at the port specified in iprop_port. New in release +1.15.

+
+
iprop_port

(Port number.) Specifies the port number to be used for +incremental propagation. When iprop_enable is true, this +relation is required in the replica KDC configuration file, and +this relation or iprop_listen is required in the primary +configuration file, as there is no default port number. Port +numbers specified in iprop_listen entries will override this +port number for the kadmind daemon.

+
+
iprop_resync_timeout

(Delta time string.) Specifies the amount of time to wait for a +full propagation to complete. This is optional in configuration +files, and is used by replica KDCs only. The default value is 5 +minutes (5m). New in release 1.11.

+
+
iprop_logfile

(File name.) Specifies where the update log file for the realm +database is to be stored. The default is to use the +database_name entry from the realms section of the krb5 config +file, with .ulog appended. (NOTE: If database_name isn’t +specified in the realms section, perhaps because the LDAP database +back end is being used, or the file name is specified in the +[dbmodules] section, then the hard-coded default for +database_name is used. Determination of the iprop_logfile +default value will not use values from the [dbmodules] section.)

+
+
kadmind_listen

(Whitespace- or comma-separated list.) Specifies the kadmin RPC +listening addresses and/or ports for the kadmind daemon. +Each entry may be an interface address, a port number, or an +address and port number separated by a colon. If the address +contains colons, enclose it in square brackets. If no address is +specified, the wildcard address is used. If kadmind fails to bind +to any of the specified addresses, it will fail to start. The +default is to bind to the wildcard address at the port specified +in kadmind_port, or the standard kadmin port (749). New in +release 1.15.

+
+
kadmind_port

(Port number.) Specifies the port on which the kadmind +daemon is to listen for this realm. Port numbers specified in +kadmind_listen entries will override this port number. The +assigned port for kadmind is 749, which is used by default.

+
+
key_stash_file

(String.) Specifies the location where the master key has been +stored (via kdb5_util stash). The default is LOCALSTATEDIR/krb5kdc/.k5.REALM, where REALM is the Kerberos realm.

+
+
kdc_listen

(Whitespace- or comma-separated list.) Specifies the UDP +listening addresses and/or ports for the krb5kdc daemon. +Each entry may be an interface address, a port number, or an +address and port number separated by a colon. If the address +contains colons, enclose it in square brackets. If no address is +specified, the wildcard address is used. If no port is specified, +the standard port (88) is used. If the KDC daemon fails to bind +to any of the specified addresses, it will fail to start. The +default is to bind to the wildcard address on the standard port. +New in release 1.15.

+
+
kdc_ports

(Whitespace- or comma-separated list, deprecated.) Prior to +release 1.15, this relation lists the ports for the +krb5kdc daemon to listen on for UDP requests. In +release 1.15 and later, it has the same meaning as kdc_listen +if that relation is not defined.

+
+
kdc_tcp_listen

(Whitespace- or comma-separated list.) Specifies the TCP +listening addresses and/or ports for the krb5kdc daemon. +Each entry may be an interface address, a port number, or an +address and port number separated by a colon. If the address +contains colons, enclose it in square brackets. If no address is +specified, the wildcard address is used. If no port is specified, +the standard port (88) is used. To disable listening on TCP, set +this relation to the empty string with kdc_tcp_listen = "". +If the KDC daemon fails to bind to any of the specified addresses, +it will fail to start. The default is to bind to the wildcard +address on the standard port. New in release 1.15.

+
+
kdc_tcp_ports

(Whitespace- or comma-separated list, deprecated.) Prior to +release 1.15, this relation lists the ports for the +krb5kdc daemon to listen on for UDP requests. In +release 1.15 and later, it has the same meaning as +kdc_tcp_listen if that relation is not defined.

+
+
kpasswd_listen

(Comma-separated list.) Specifies the kpasswd listening addresses +and/or ports for the kadmind daemon. Each entry may be +an interface address, a port number, or an address and port number +separated by a colon. If the address contains colons, enclose it +in square brackets. If no address is specified, the wildcard +address is used. If kadmind fails to bind to any of the specified +addresses, it will fail to start. The default is to bind to the +wildcard address at the port specified in kpasswd_port, or the +standard kpasswd port (464). New in release 1.15.

+
+
kpasswd_port

(Port number.) Specifies the port on which the kadmind +daemon is to listen for password change requests for this realm. +Port numbers specified in kpasswd_listen entries will override +this port number. The assigned port for password change requests +is 464, which is used by default.

+
+
master_key_name

(String.) Specifies the name of the principal associated with the +master key. The default is K/M.

+
+
master_key_type

(Key type string.) Specifies the master key’s key type. The +default value for this is aes256-cts-hmac-sha1-96. For a list of all possible +values, see Encryption types.

+
+
max_life

(Time duration string.) Specifies the maximum time period for +which a ticket may be valid in this realm. The default value is +24 hours.

+
+
max_renewable_life

(Time duration string.) Specifies the maximum time period +during which a valid ticket may be renewed in this realm. +The default value is 0.

+
+
no_host_referral

(Whitespace- or comma-separated list.) Lists services to block +from getting host-based referral processing, even if the client +marks the server principal as host-based or the service is also +listed in host_based_services. no_host_referral = * will +disable referral processing altogether.

+
+
reject_bad_transit

(Boolean value.) If set to true, the KDC will check the list of +transited realms for cross-realm tickets against the transit path +computed from the realm names and the capaths section of its +krb5.conf file; if the path in the ticket to be issued +contains any realms not in the computed path, the ticket will not +be issued, and an error will be returned to the client instead. +If this value is set to false, such tickets will be issued +anyways, and it will be left up to the application server to +validate the realm transit path.

+

If the disable-transited-check flag is set in the incoming +request, this check is not performed at all. Having the +reject_bad_transit option will cause such ticket requests to +be rejected always.

+

This transit path checking and config file option currently apply +only to TGS requests.

+

The default value is true.

+
+
restrict_anonymous_to_tgt

(Boolean value.) If set to true, the KDC will reject ticket +requests from anonymous principals to service principals other +than the realm’s ticket-granting service. This option allows +anonymous PKINIT to be enabled for use as FAST armor tickets +without allowing anonymous authentication to services. The +default value is false. New in release 1.9.

+
+
spake_preauth_indicator

(String.) Specifies an authentication indicator value that the +KDC asserts into tickets obtained using SPAKE pre-authentication. +The default is not to add any indicators. This option may be +specified multiple times. New in release 1.17.

+
+
supported_enctypes

(List of key:salt strings.) Specifies the default key/salt +combinations of principals for this realm. Any principals created +through kadmin will have keys of these types. The +default value for this tag is aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal. For lists of +possible values, see Keysalt lists.

+
+
+
+
+

[dbdefaults]

+

The [dbdefaults] section specifies default values for some database +parameters, to be used if the [dbmodules] subsection does not contain +a relation for the tag. See the [dbmodules] section for the +definitions of these relations.

+
    +
  • ldap_kerberos_container_dn

  • +
  • ldap_kdc_dn

  • +
  • ldap_kdc_sasl_authcid

  • +
  • ldap_kdc_sasl_authzid

  • +
  • ldap_kdc_sasl_mech

  • +
  • ldap_kdc_sasl_realm

  • +
  • ldap_kadmind_dn

  • +
  • ldap_kadmind_sasl_authcid

  • +
  • ldap_kadmind_sasl_authzid

  • +
  • ldap_kadmind_sasl_mech

  • +
  • ldap_kadmind_sasl_realm

  • +
  • ldap_service_password_file

  • +
  • ldap_conns_per_server

  • +
+
+
+

[dbmodules]

+

The [dbmodules] section contains parameters used by the KDC database +library and database modules. Each tag in the [dbmodules] section is +the name of a Kerberos realm or a section name specified by a realm’s +database_module parameter. The following example shows how to +define one database parameter for the ATHENA.MIT.EDU realm:

+
[dbmodules]
+    ATHENA.MIT.EDU = {
+        disable_last_success = true
+    }
+
+
+

The following tags may be specified in a [dbmodules] subsection:

+
+
database_name

This DB2-specific tag indicates the location of the database in +the filesystem. The default is LOCALSTATEDIR/krb5kdc/principal.

+
+
db_library

This tag indicates the name of the loadable database module. The +value should be db2 for the DB2 module, klmdb for the LMDB +module, or kldap for the LDAP module.

+
+
disable_last_success

If set to true, suppresses KDC updates to the “Last successful +authentication” field of principal entries requiring +preauthentication. Setting this flag may improve performance. +(Principal entries which do not require preauthentication never +update the “Last successful authentication” field.). First +introduced in release 1.9.

+
+
disable_lockout

If set to true, suppresses KDC updates to the “Last failed +authentication” and “Failed password attempts” fields of principal +entries requiring preauthentication. Setting this flag may +improve performance, but also disables account lockout. First +introduced in release 1.9.

+
+
ldap_conns_per_server

This LDAP-specific tag indicates the number of connections to be +maintained per LDAP server.

+
+
ldap_kdc_dn and ldap_kadmind_dn

These LDAP-specific tags indicate the default DN for binding to +the LDAP server. The krb5kdc daemon uses +ldap_kdc_dn, while the kadmind daemon and other +administrative programs use ldap_kadmind_dn. The kadmind DN +must have the rights to read and write the Kerberos data in the +LDAP database. The KDC DN must have the same rights, unless +disable_lockout and disable_last_success are true, in +which case it only needs to have rights to read the Kerberos data. +These tags are ignored if a SASL mechanism is set with +ldap_kdc_sasl_mech or ldap_kadmind_sasl_mech.

+
+
ldap_kdc_sasl_mech and ldap_kadmind_sasl_mech

These LDAP-specific tags specify the SASL mechanism (such as +EXTERNAL) to use when binding to the LDAP server. New in +release 1.13.

+
+
ldap_kdc_sasl_authcid and ldap_kadmind_sasl_authcid

These LDAP-specific tags specify the SASL authentication identity +to use when binding to the LDAP server. Not all SASL mechanisms +require an authentication identity. If the SASL mechanism +requires a secret (such as the password for DIGEST-MD5), these +tags also determine the name within the +ldap_service_password_file where the secret is stashed. New +in release 1.13.

+
+
ldap_kdc_sasl_authzid and ldap_kadmind_sasl_authzid

These LDAP-specific tags specify the SASL authorization identity +to use when binding to the LDAP server. In most circumstances +they do not need to be specified. New in release 1.13.

+
+
ldap_kdc_sasl_realm and ldap_kadmind_sasl_realm

These LDAP-specific tags specify the SASL realm to use when +binding to the LDAP server. In most circumstances they do not +need to be set. New in release 1.13.

+
+
ldap_kerberos_container_dn

This LDAP-specific tag indicates the DN of the container object +where the realm objects will be located.

+
+
ldap_servers

This LDAP-specific tag indicates the list of LDAP servers that the +Kerberos servers can connect to. The list of LDAP servers is +whitespace-separated. The LDAP server is specified by a LDAP URI. +It is recommended to use ldapi: or ldaps: URLs to connect +to the LDAP server.

+
+
ldap_service_password_file

This LDAP-specific tag indicates the file containing the stashed +passwords (created by kdb5_ldap_util stashsrvpw) for the +ldap_kdc_dn and ldap_kadmind_dn objects, or for the +ldap_kdc_sasl_authcid or ldap_kadmind_sasl_authcid names +for SASL authentication. This file must be kept secure.

+
+
mapsize

This LMDB-specific tag indicates the maximum size of the two +database environments in megabytes. The default value is 128. +Increase this value to address “Environment mapsize limit reached” +errors. New in release 1.17.

+
+
max_readers

This LMDB-specific tag indicates the maximum number of concurrent +reading processes for the databases. The default value is 128. +New in release 1.17.

+
+
nosync

This LMDB-specific tag can be set to improve the throughput of +kadmind and other administrative agents, at the expense of +durability (recent database changes may not survive a power outage +or other sudden reboot). It does not affect the throughput of the +KDC. The default value is false. New in release 1.17.

+
+
unlockiter

If set to true, this DB2-specific tag causes iteration +operations to release the database lock while processing each +principal. Setting this flag to true can prevent extended +blocking of KDC or kadmin operations when dumps of large databases +are in progress. First introduced in release 1.13.

+
+
+

The following tag may be specified directly in the [dbmodules] +section to control where database modules are loaded from:

+
+
db_module_dir

This tag controls where the plugin system looks for database +modules. The value should be an absolute path.

+
+
+
+
+

[logging]

+

The [logging] section indicates how krb5kdc and +kadmind perform logging. It may contain the following +relations:

+
+
admin_server

Specifies how kadmind performs logging.

+
+
kdc

Specifies how krb5kdc performs logging.

+
+
default

Specifies how either daemon performs logging in the absence of +relations specific to the daemon.

+
+
debug

(Boolean value.) Specifies whether debugging messages are +included in log outputs other than SYSLOG. Debugging messages are +always included in the system log output because syslog performs +its own priority filtering. The default value is false. New in +release 1.15.

+
+
+

Logging specifications may have the following forms:

+
+
FILE=filename or FILE:filename

This value causes the daemon’s logging messages to go to the +filename. If the = form is used, the file is overwritten. +If the : form is used, the file is appended to.

+
+
STDERR

This value causes the daemon’s logging messages to go to its +standard error stream.

+
+
CONSOLE

This value causes the daemon’s logging messages to go to the +console, if the system supports it.

+
+
DEVICE=<devicename>

This causes the daemon’s logging messages to go to the specified +device.

+
+
SYSLOG[:severity[:facility]]

This causes the daemon’s logging messages to go to the system log.

+

For backward compatibility, a severity argument may be specified, +and must be specified in order to specify a facility. This +argument will be ignored.

+

The facility argument specifies the facility under which the +messages are logged. This may be any of the following facilities +supported by the syslog(3) call minus the LOG_ prefix: KERN, +USER, MAIL, DAEMON, AUTH, LPR, NEWS, +UUCP, CRON, and LOCAL0 through LOCAL7. If no +facility is specified, the default is AUTH.

+
+
+

In the following example, the logging messages from the KDC will go to +the console and to the system log under the facility LOG_DAEMON, and +the logging messages from the administrative server will be appended +to the file /var/adm/kadmin.log and sent to the device +/dev/tty04.

+
[logging]
+    kdc = CONSOLE
+    kdc = SYSLOG:INFO:DAEMON
+    admin_server = FILE:/var/adm/kadmin.log
+    admin_server = DEVICE=/dev/tty04
+
+
+

If no logging specification is given, the default is to use syslog. +To disable logging entirely, specify default = DEVICE=/dev/null.

+
+
+

[otp]

+

Each subsection of [otp] is the name of an OTP token type. The tags +within the subsection define the configuration required to forward a +One Time Password request to a RADIUS server.

+

For each token type, the following tags may be specified:

+
+
server

This is the server to send the RADIUS request to. It can be a +hostname with optional port, an ip address with optional port, or +a Unix domain socket address. The default is +LOCALSTATEDIR/krb5kdc/<name>.socket.

+
+
secret

This tag indicates a filename (which may be relative to LOCALSTATEDIR/krb5kdc) +containing the secret used to encrypt the RADIUS packets. The +secret should appear in the first line of the file by itself; +leading and trailing whitespace on the line will be removed. If +the value of server is a Unix domain socket address, this tag +is optional, and an empty secret will be used if it is not +specified. Otherwise, this tag is required.

+
+
timeout

An integer which specifies the time in seconds during which the +KDC should attempt to contact the RADIUS server. This tag is the +total time across all retries and should be less than the time +which an OTP value remains valid for. The default is 5 seconds.

+
+
retries

This tag specifies the number of retries to make to the RADIUS +server. The default is 3 retries (4 tries).

+
+
strip_realm

If this tag is true, the principal without the realm will be +passed to the RADIUS server. Otherwise, the realm will be +included. The default value is true.

+
+
indicator

This tag specifies an authentication indicator to be included in +the ticket if this token type is used to authenticate. This +option may be specified multiple times. (New in release 1.14.)

+
+
+

In the following example, requests are sent to a remote server via UDP:

+
[otp]
+    MyRemoteTokenType = {
+        server = radius.mydomain.com:1812
+        secret = SEmfiajf42$
+        timeout = 15
+        retries = 5
+        strip_realm = true
+    }
+
+
+

An implicit default token type named DEFAULT is defined for when +the per-principal configuration does not specify a token type. Its +configuration is shown below. You may override this token type to +something applicable for your situation:

+
[otp]
+    DEFAULT = {
+        strip_realm = false
+    }
+
+
+
+
+
+

PKINIT options

+
+

Note

+

The following are pkinit-specific options. These values may +be specified in [kdcdefaults] as global defaults, or within +a realm-specific subsection of [realms]. Also note that a +realm-specific value over-rides, does not add to, a generic +[kdcdefaults] specification. The search order is:

+
+
    +
  1. realm-specific subsection of [realms]:

    +
    [realms]
    +    EXAMPLE.COM = {
    +        pkinit_anchors = FILE:/usr/local/example.com.crt
    +    }
    +
    +
    +
  2. +
  3. generic value in the [kdcdefaults] section:

    +
    [kdcdefaults]
    +    pkinit_anchors = DIR:/usr/local/generic_trusted_cas/
    +
    +
    +
  4. +
+

For information about the syntax of some of these options, see +Specifying PKINIT identity information in +krb5.conf.

+
+
pkinit_anchors

Specifies the location of trusted anchor (root) certificates which +the KDC trusts to sign client certificates. This option is +required if pkinit is to be supported by the KDC. This option may +be specified multiple times.

+
+
pkinit_dh_min_bits

Specifies the minimum number of bits the KDC is willing to accept +for a client’s Diffie-Hellman key. The default is 2048.

+
+
pkinit_allow_upn

Specifies that the KDC is willing to accept client certificates +with the Microsoft UserPrincipalName (UPN) Subject Alternative +Name (SAN). This means the KDC accepts the binding of the UPN in +the certificate to the Kerberos principal name. The default value +is false.

+

Without this option, the KDC will only accept certificates with +the id-pkinit-san as defined in RFC 4556. There is currently +no option to disable SAN checking in the KDC.

+
+
pkinit_eku_checking

This option specifies what Extended Key Usage (EKU) values the KDC +is willing to accept in client certificates. The values +recognized in the kdc.conf file are:

+
+
kpClientAuth

This is the default value and specifies that client +certificates must have the id-pkinit-KPClientAuth EKU as +defined in RFC 4556.

+
+
scLogin

If scLogin is specified, client certificates with the +Microsoft Smart Card Login EKU (id-ms-kp-sc-logon) will be +accepted.

+
+
none

If none is specified, then client certificates will not be +checked to verify they have an acceptable EKU. The use of +this option is not recommended.

+
+
+
+
pkinit_identity

Specifies the location of the KDC’s X.509 identity information. +This option is required if pkinit is to be supported by the KDC.

+
+
pkinit_indicator

Specifies an authentication indicator to include in the ticket if +pkinit is used to authenticate. This option may be specified +multiple times. (New in release 1.14.)

+
+
pkinit_pool

Specifies the location of intermediate certificates which may be +used by the KDC to complete the trust chain between a client’s +certificate and a trusted anchor. This option may be specified +multiple times.

+
+
pkinit_revoke

Specifies the location of Certificate Revocation List (CRL) +information to be used by the KDC when verifying the validity of +client certificates. This option may be specified multiple times.

+
+
pkinit_require_crl_checking

The default certificate verification process will always check the +available revocation information to see if a certificate has been +revoked. If a match is found for the certificate in a CRL, +verification fails. If the certificate being verified is not +listed in a CRL, or there is no CRL present for its issuing CA, +and pkinit_require_crl_checking is false, then verification +succeeds.

+

However, if pkinit_require_crl_checking is true and there is +no CRL information available for the issuing CA, then verification +fails.

+

pkinit_require_crl_checking should be set to true if the +policy is such that up-to-date CRLs must be present for every CA.

+
+
pkinit_require_freshness

Specifies whether to require clients to include a freshness token +in PKINIT requests. The default value is false. (New in release +1.17.)

+
+
+
+
+

Encryption types

+

Any tag in the configuration files which requires a list of encryption +types can be set to some combination of the following strings. +Encryption types marked as “weak” and “deprecated” are available for +compatibility but not recommended for use.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

des3-cbc-raw

Triple DES cbc mode raw (weak)

des3-cbc-sha1 des3-hmac-sha1 des3-cbc-sha1-kd

Triple DES cbc mode with HMAC/sha1 (deprecated)

aes256-cts-hmac-sha1-96 aes256-cts aes256-sha1

AES-256 CTS mode with 96-bit SHA-1 HMAC

aes128-cts-hmac-sha1-96 aes128-cts aes128-sha1

AES-128 CTS mode with 96-bit SHA-1 HMAC

aes256-cts-hmac-sha384-192 aes256-sha2

AES-256 CTS mode with 192-bit SHA-384 HMAC

aes128-cts-hmac-sha256-128 aes128-sha2

AES-128 CTS mode with 128-bit SHA-256 HMAC

arcfour-hmac rc4-hmac arcfour-hmac-md5

RC4 with HMAC/MD5 (deprecated)

arcfour-hmac-exp rc4-hmac-exp arcfour-hmac-md5-exp

Exportable RC4 with HMAC/MD5 (weak)

camellia256-cts-cmac camellia256-cts

Camellia-256 CTS mode with CMAC

camellia128-cts-cmac camellia128-cts

Camellia-128 CTS mode with CMAC

des3

The triple DES family: des3-cbc-sha1

aes

The AES family: aes256-cts-hmac-sha1-96, aes128-cts-hmac-sha1-96, aes256-cts-hmac-sha384-192, and aes128-cts-hmac-sha256-128

rc4

The RC4 family: arcfour-hmac

camellia

The Camellia family: camellia256-cts-cmac and camellia128-cts-cmac

+

The string DEFAULT can be used to refer to the default set of +types for the variable in question. Types or families can be removed +from the current list by prefixing them with a minus sign (“-“). +Types or families can be prefixed with a plus sign (“+”) for symmetry; +it has the same meaning as just listing the type or family. For +example, “DEFAULT -rc4” would be the default set of encryption +types with RC4 types removed, and “des3 DEFAULT” would be the +default set of encryption types with triple DES types moved to the +front.

+

While aes128-cts and aes256-cts are supported for all Kerberos +operations, they are not supported by very old versions of our GSSAPI +implementation (krb5-1.3.1 and earlier). Services running versions of +krb5 without AES support must not be given keys of these encryption +types in the KDC database.

+

The aes128-sha2 and aes256-sha2 encryption types are new in +release 1.15. Services running versions of krb5 without support for +these newer encryption types must not be given keys of these +encryption types in the KDC database.

+
+
+

Keysalt lists

+

Kerberos keys for users are usually derived from passwords. Kerberos +commands and configuration parameters that affect generation of keys +take lists of enctype-salttype (“keysalt”) pairs, known as keysalt +lists. Each keysalt pair is an enctype name followed by a salttype +name, in the format enc:salt. Individual keysalt list members are +separated by comma (“,”) characters or space characters. For example:

+
kadmin -e aes256-cts:normal,aes128-cts:normal
+
+
+

would start up kadmin so that by default it would generate +password-derived keys for the aes256-cts and aes128-cts +encryption types, using a normal salt.

+

To ensure that people who happen to pick the same password do not have +the same key, Kerberos 5 incorporates more information into the key +using something called a salt. The supported salt types are as +follows:

+ ++++ + + + + + + + + + + + + + + +

normal

default for Kerberos Version 5

norealm

same as the default, without using realm information

onlyrealm

uses only realm information as the salt

special

generate a random salt

+
+
+

Sample kdc.conf File

+

Here’s an example of a kdc.conf file:

+
[kdcdefaults]
+    kdc_listen = 88
+    kdc_tcp_listen = 88
+[realms]
+    ATHENA.MIT.EDU = {
+        kadmind_port = 749
+        max_life = 12h 0m 0s
+        max_renewable_life = 7d 0h 0m 0s
+        master_key_type = aes256-cts-hmac-sha1-96
+        supported_enctypes = aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal
+        database_module = openldap_ldapconf
+    }
+
+[logging]
+    kdc = FILE:/usr/local/var/krb5kdc/kdc.log
+    admin_server = FILE:/usr/local/var/krb5kdc/kadmin.log
+
+[dbdefaults]
+    ldap_kerberos_container_dn = cn=krbcontainer,dc=mit,dc=edu
+
+[dbmodules]
+    openldap_ldapconf = {
+        db_library = kldap
+        disable_last_success = true
+        ldap_kdc_dn = "cn=krbadmin,dc=mit,dc=edu"
+            # this object needs to have read rights on
+            # the realm container and principal subtrees
+        ldap_kadmind_dn = "cn=krbadmin,dc=mit,dc=edu"
+            # this object needs to have read and write rights on
+            # the realm container and principal subtrees
+        ldap_service_password_file = /etc/kerberos/service.keyfile
+        ldap_servers = ldaps://kerberos.mit.edu
+        ldap_conns_per_server = 5
+    }
+
+
+
+
+

FILES

+

LOCALSTATEDIR/krb5kdc/kdc.conf

+
+
+

SEE ALSO

+

krb5.conf, krb5kdc, kadm5.acl

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/conf_files/krb5_conf.html b/krb5-1.21.3/doc/html/admin/conf_files/krb5_conf.html new file mode 100644 index 00000000..7c922675 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/conf_files/krb5_conf.html @@ -0,0 +1,1340 @@ + + + + + + + + + krb5.conf — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5.conf

+

The krb5.conf file contains Kerberos configuration information, +including the locations of KDCs and admin servers for the Kerberos +realms of interest, defaults for the current realm and for Kerberos +applications, and mappings of hostnames onto Kerberos realms. +Normally, you should install your krb5.conf file in the directory +/etc. You can override the default location by setting the +environment variable KRB5_CONFIG. Multiple colon-separated +filenames may be specified in KRB5_CONFIG; all files which are +present will be read. Starting in release 1.14, directory names can +also be specified in KRB5_CONFIG; all files within the directory +whose names consist solely of alphanumeric characters, dashes, or +underscores will be read.

+
+

Structure

+

The krb5.conf file is set up in the style of a Windows INI file. +Lines beginning with ‘#’ or ‘;’ (possibly after initial whitespace) +are ignored as comments. Sections are headed by the section name, in +square brackets. Each section may contain zero or more relations, of +the form:

+
foo = bar
+
+
+

or:

+
fubar = {
+    foo = bar
+    baz = quux
+}
+
+
+

Placing a ‘*’ after the closing bracket of a section name indicates +that the section is final, meaning that if the same section appears +within a later file specified in KRB5_CONFIG, it will be ignored. +A subsection can be marked as final by placing a ‘*’ after either the +tag name or the closing brace.

+

The krb5.conf file can include other files using either of the +following directives at the beginning of a line:

+
include FILENAME
+includedir DIRNAME
+
+
+

FILENAME or DIRNAME should be an absolute path. The named file or +directory must exist and be readable. Including a directory includes +all files within the directory whose names consist solely of +alphanumeric characters, dashes, or underscores. Starting in release +1.15, files with names ending in “.conf” are also included, unless the +name begins with “.”. Included profile files are syntactically +independent of their parents, so each included file must begin with a +section header. Starting in release 1.17, files are read in +alphanumeric order; in previous releases, they may be read in any +order.

+

The krb5.conf file can specify that configuration should be obtained +from a loadable module, rather than the file itself, using the +following directive at the beginning of a line before any section +headers:

+
module MODULEPATH:RESIDUAL
+
+
+

MODULEPATH may be relative to the library path of the krb5 +installation, or it may be an absolute path. RESIDUAL is provided +to the module at initialization time. If krb5.conf uses a module +directive, kdc.conf should also use one if it exists.

+
+
+

Sections

+

The krb5.conf file may contain the following sections:

+ ++++ + + + + + + + + + + + + + + + + + + + + +

[libdefaults]

Settings used by the Kerberos V5 library

[realms]

Realm-specific contact information and settings

[domain_realm]

Maps server hostnames to Kerberos realms

[capaths]

Authentication paths for non-hierarchical cross-realm

[appdefaults]

Settings used by some Kerberos V5 applications

[plugins]

Controls plugin module registration

+

Additionally, krb5.conf may include any of the relations described in +kdc.conf, but it is not a recommended practice.

+
+

[libdefaults]

+

The libdefaults section may contain any of the following relations:

+
+
allow_des3

Permit the KDC to issue tickets with des3-cbc-sha1 session keys. +In future releases, this flag will allow des3-cbc-sha1 to be used +at all. The default value for this tag is false. (Added in +release 1.21.)

+
+
allow_rc4

Permit the KDC to issue tickets with arcfour-hmac session keys. +In future releases, this flag will allow arcfour-hmac to be used +at all. The default value for this tag is false. (Added in +release 1.21.)

+
+
allow_weak_crypto

If this flag is set to false, then weak encryption types (as noted +in Encryption types in kdc.conf) will be filtered +out of the lists default_tgs_enctypes, +default_tkt_enctypes, and permitted_enctypes. The default +value for this tag is false.

+
+
canonicalize

If this flag is set to true, initial ticket requests to the KDC +will request canonicalization of the client principal name, and +answers with different client principals than the requested +principal will be accepted. The default value is false.

+
+
ccache_type

This parameter determines the format of credential cache types +created by kinit or other programs. The default value +is 4, which represents the most current format. Smaller values +can be used for compatibility with very old implementations of +Kerberos which interact with credential caches on the same host.

+
+
clockskew

Sets the maximum allowable amount of clockskew in seconds that the +library will tolerate before assuming that a Kerberos message is +invalid. The default value is 300 seconds, or five minutes.

+

The clockskew setting is also used when evaluating ticket start +and expiration times. For example, tickets that have reached +their expiration time can still be used (and renewed if they are +renewable tickets) if they have been expired for a shorter +duration than the clockskew setting.

+
+
default_ccache_name

This relation specifies the name of the default credential cache. +The default is DEFCCNAME. This relation is subject to parameter +expansion (see below). New in release 1.11.

+
+
default_client_keytab_name

This relation specifies the name of the default keytab for +obtaining client credentials. The default is DEFCKTNAME. This +relation is subject to parameter expansion (see below). +New in release 1.11.

+
+
default_keytab_name

This relation specifies the default keytab name to be used by +application servers such as sshd. The default is DEFKTNAME. This +relation is subject to parameter expansion (see below).

+
+
default_rcache_name

This relation specifies the name of the default replay cache. +The default is dfl:. This relation is subject to parameter +expansion (see below). New in release 1.18.

+
+
default_realm

Identifies the default Kerberos realm for the client. Set its +value to your Kerberos realm. If this value is not set, then a +realm must be specified with every Kerberos principal when +invoking programs such as kinit.

+
+
default_tgs_enctypes

Identifies the supported list of session key encryption types that +the client should request when making a TGS-REQ, in order of +preference from highest to lowest. The list may be delimited with +commas or whitespace. See Encryption types in +kdc.conf for a list of the accepted values for this tag. +Starting in release 1.18, the default value is the value of +permitted_enctypes. For previous releases or if +permitted_enctypes is not set, the default value is +aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac.

+

Do not set this unless required for specific backward +compatibility purposes; stale values of this setting can prevent +clients from taking advantage of new stronger enctypes when the +libraries are upgraded.

+
+
default_tkt_enctypes

Identifies the supported list of session key encryption types that +the client should request when making an AS-REQ, in order of +preference from highest to lowest. The format is the same as for +default_tgs_enctypes. Starting in release 1.18, the default +value is the value of permitted_enctypes. For previous +releases or if permitted_enctypes is not set, the default +value is aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac.

+

Do not set this unless required for specific backward +compatibility purposes; stale values of this setting can prevent +clients from taking advantage of new stronger enctypes when the +libraries are upgraded.

+
+
dns_canonicalize_hostname

Indicate whether name lookups will be used to canonicalize +hostnames for use in service principal names. Setting this flag +to false can improve security by reducing reliance on DNS, but +means that short hostnames will not be canonicalized to +fully-qualified hostnames. If this option is set to fallback (new +in release 1.18), DNS canonicalization will only be performed the +server hostname is not found with the original name when +requesting credentials. The default value is true.

+
+
dns_lookup_kdc

Indicate whether DNS SRV records should be used to locate the KDCs +and other servers for a realm, if they are not listed in the +krb5.conf information for the realm. (Note that the admin_server +entry must be in the krb5.conf realm information in order to +contact kadmind, because the DNS implementation for kadmin is +incomplete.)

+

Enabling this option does open up a type of denial-of-service +attack, if someone spoofs the DNS records and redirects you to +another server. However, it’s no worse than a denial of service, +because that fake KDC will be unable to decode anything you send +it (besides the initial ticket request, which has no encrypted +data), and anything the fake KDC sends will not be trusted without +verification using some secret that it won’t know.

+
+
dns_uri_lookup

Indicate whether DNS URI records should be used to locate the KDCs +and other servers for a realm, if they are not listed in the +krb5.conf information for the realm. SRV records are used as a +fallback if no URI records were found. The default value is true. +New in release 1.15.

+
+
enforce_ok_as_delegate

If this flag to true, GSSAPI credential delegation will be +disabled when the ok-as-delegate flag is not set in the +service ticket. If this flag is false, the ok-as-delegate +ticket flag is only enforced when an application specifically +requests enforcement. The default value is false.

+
+
err_fmt

This relation allows for custom error message formatting. If a +value is set, error messages will be formatted by substituting a +normal error message for %M and an error code for %C in the value.

+
+
extra_addresses

This allows a computer to use multiple local addresses, in order +to allow Kerberos to work in a network that uses NATs while still +using address-restricted tickets. The addresses should be in a +comma-separated list. This option has no effect if +noaddresses is true.

+
+
forwardable

If this flag is true, initial tickets will be forwardable by +default, if allowed by the KDC. The default value is false.

+
+
ignore_acceptor_hostname

When accepting GSSAPI or krb5 security contexts for host-based +service principals, ignore any hostname passed by the calling +application, and allow clients to authenticate to any service +principal in the keytab matching the service name and realm name +(if given). This option can improve the administrative +flexibility of server applications on multihomed hosts, but could +compromise the security of virtual hosting environments. The +default value is false. New in release 1.10.

+
+
k5login_authoritative

If this flag is true, principals must be listed in a local user’s +k5login file to be granted login access, if a .k5login +file exists. If this flag is false, a principal may still be +granted login access through other mechanisms even if a k5login +file exists but does not list the principal. The default value is +true.

+
+
k5login_directory

If set, the library will look for a local user’s k5login file +within the named directory, with a filename corresponding to the +local username. If not set, the library will look for k5login +files in the user’s home directory, with the filename .k5login. +For security reasons, .k5login files must be owned by +the local user or by root.

+
+
kcm_mach_service

On macOS only, determines the name of the bootstrap service used to +contact the KCM daemon for the KCM credential cache type. If the +value is -, Mach RPC will not be used to contact the KCM +daemon. The default value is org.h5l.kcm.

+
+
kcm_socket

Determines the path to the Unix domain socket used to access the +KCM daemon for the KCM credential cache type. If the value is +-, Unix domain sockets will not be used to contact the KCM +daemon. The default value is +/var/run/.heim_org.h5l.kcm-socket.

+
+
kdc_default_options

Default KDC options (Xored for multiple values) when requesting +initial tickets. By default it is set to 0x00000010 +(KDC_OPT_RENEWABLE_OK).

+
+
kdc_timesync

Accepted values for this relation are 1 or 0. If it is nonzero, +client machines will compute the difference between their time and +the time returned by the KDC in the timestamps in the tickets and +use this value to correct for an inaccurate system clock when +requesting service tickets or authenticating to services. This +corrective factor is only used by the Kerberos library; it is not +used to change the system clock. The default value is 1.

+
+
noaddresses

If this flag is true, requests for initial tickets will not be +made with address restrictions set, allowing the tickets to be +used across NATs. The default value is true.

+
+
permitted_enctypes

Identifies the encryption types that servers will permit for +session keys and for ticket and authenticator encryption, ordered +by preference from highest to lowest. Starting in release 1.18, +this tag also acts as the default value for +default_tgs_enctypes and default_tkt_enctypes. The +default value for this tag is aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac.

+
+
plugin_base_dir

If set, determines the base directory where krb5 plugins are +located. The default value is the krb5/plugins subdirectory +of the krb5 library directory. This relation is subject to +parameter expansion (see below) in release 1.17 and later.

+
+
preferred_preauth_types

This allows you to set the preferred preauthentication types which +the client will attempt before others which may be advertised by a +KDC. The default value for this setting is “17, 16, 15, 14”, +which forces libkrb5 to attempt to use PKINIT if it is supported.

+
+
proxiable

If this flag is true, initial tickets will be proxiable by +default, if allowed by the KDC. The default value is false.

+
+
qualify_shortname

If this string is set, it determines the domain suffix for +single-component hostnames when DNS canonicalization is not used +(either because dns_canonicalize_hostname is false or because +forward canonicalization failed). The default value is the first +search domain of the system’s DNS configuration. To disable +qualification of shortnames, set this relation to the empty string +with qualify_shortname = "". (New in release 1.18.)

+
+
rdns

If this flag is true, reverse name lookup will be used in addition +to forward name lookup to canonicalizing hostnames for use in +service principal names. If dns_canonicalize_hostname is set +to false, this flag has no effect. The default value is true.

+
+
realm_try_domains

Indicate whether a host’s domain components should be used to +determine the Kerberos realm of the host. The value of this +variable is an integer: -1 means not to search, 0 means to try the +host’s domain itself, 1 means to also try the domain’s immediate +parent, and so forth. The library’s usual mechanism for locating +Kerberos realms is used to determine whether a domain is a valid +realm, which may involve consulting DNS if dns_lookup_kdc is +set. The default is not to search domain components.

+
+
renew_lifetime

(Time duration string.) Sets the default renewable lifetime +for initial ticket requests. The default value is 0.

+
+
spake_preauth_groups

A whitespace or comma-separated list of words which specifies the +groups allowed for SPAKE preauthentication. The possible values +are:

+ ++++ + + + + + + + + + + + + + + +

edwards25519

Edwards25519 curve (RFC 7748)

P-256

NIST P-256 curve (RFC 5480)

P-384

NIST P-384 curve (RFC 5480)

P-521

NIST P-521 curve (RFC 5480)

+

The default value for the client is edwards25519. The default +value for the KDC is empty. New in release 1.17.

+
+
ticket_lifetime

(Time duration string.) Sets the default lifetime for initial +ticket requests. The default value is 1 day.

+
+
udp_preference_limit

When sending a message to the KDC, the library will try using TCP +before UDP if the size of the message is above +udp_preference_limit. If the message is smaller than +udp_preference_limit, then UDP will be tried before TCP. +Regardless of the size, both protocols will be tried if the first +attempt fails.

+
+
verify_ap_req_nofail

If this flag is true, then an attempt to verify initial +credentials will fail if the client machine does not have a +keytab. The default value is false.

+
+
client_aware_channel_bindings

If this flag is true, then all application protocol authentication +requests will be flagged to indicate that the application supports +channel bindings when operating over a secure channel. The +default value is false.

+
+
+
+
+

[realms]

+

Each tag in the [realms] section of the file is the name of a Kerberos +realm. The value of the tag is a subsection with relations that +define the properties of that particular realm. For each realm, the +following tags may be specified in the realm’s subsection:

+
+
admin_server

Identifies the host where the administration server is running. +Typically, this is the primary Kerberos server. This tag must be +given a value in order to communicate with the kadmind +server for the realm.

+
+
auth_to_local

This tag allows you to set a general rule for mapping principal +names to local user names. It will be used if there is not an +explicit mapping for the principal name that is being +translated. The possible values are:

+
+
RULE:exp

The local name will be formulated from exp.

+

The format for exp is [n:string](regexp)s/pattern/replacement/g. +The integer n indicates how many components the target +principal should have. If this matches, then a string will be +formed from string, substituting the realm of the principal +for $0 and the n’th component of the principal for +$n (e.g., if the principal was johndoe/admin then +[2:$2$1foo] would result in the string +adminjohndoefoo). If this string matches regexp, then +the s//[g] substitution command will be run over the +string. The optional g will cause the substitution to be +global over the string, instead of replacing only the first +match in the string.

+
+
DEFAULT

The principal name will be used as the local user name. If +the principal has more than one component or is not in the +default realm, this rule is not applicable and the conversion +will fail.

+
+
+

For example:

+
[realms]
+    ATHENA.MIT.EDU = {
+        auth_to_local = RULE:[2:$1](johndoe)s/^.*$/guest/
+        auth_to_local = RULE:[2:$1;$2](^.*;admin$)s/;admin$//
+        auth_to_local = RULE:[2:$2](^.*;root)s/^.*$/root/
+        auth_to_local = DEFAULT
+    }
+
+
+

would result in any principal without root or admin as the +second component to be translated with the default rule. A +principal with a second component of admin will become its +first component. root will be used as the local name for any +principal with a second component of root. The exception to +these two rules are any principals johndoe/*, which will +always get the local name guest.

+
+
auth_to_local_names

This subsection allows you to set explicit mappings from principal +names to local user names. The tag is the mapping name, and the +value is the corresponding local user name.

+
+
default_domain

This tag specifies the domain used to expand hostnames when +translating Kerberos 4 service principals to Kerberos 5 principals +(for example, when converting rcmd.hostname to +host/hostname.domain).

+
+
disable_encrypted_timestamp

If this flag is true, the client will not perform encrypted +timestamp preauthentication if requested by the KDC. Setting this +flag can help to prevent dictionary attacks by active attackers, +if the realm’s KDCs support SPAKE preauthentication or if initial +authentication always uses another mechanism or always uses FAST. +This flag persists across client referrals during initial +authentication. This flag does not prevent the KDC from offering +encrypted timestamp. New in release 1.17.

+
+
http_anchors

When KDCs and kpasswd servers are accessed through HTTPS proxies, this tag +can be used to specify the location of the CA certificate which should be +trusted to issue the certificate for a proxy server. If left unspecified, +the system-wide default set of CA certificates is used.

+

The syntax for values is similar to that of values for the +pkinit_anchors tag:

+

FILE: filename

+

filename is assumed to be the name of an OpenSSL-style ca-bundle file.

+

DIR: dirname

+

dirname is assumed to be an directory which contains CA certificates. +All files in the directory will be examined; if they contain certificates +(in PEM format), they will be used.

+

ENV: envvar

+

envvar specifies the name of an environment variable which has been set +to a value conforming to one of the previous values. For example, +ENV:X509_PROXY_CA, where environment variable X509_PROXY_CA has +been set to FILE:/tmp/my_proxy.pem.

+
+
kdc

The name or address of a host running a KDC for that realm. An +optional port number, separated from the hostname by a colon, may +be included. If the name or address contains colons (for example, +if it is an IPv6 address), enclose it in square brackets to +distinguish the colon from a port separator. For your computer to +be able to communicate with the KDC for each realm, this tag must +be given a value in each realm subsection in the configuration +file, or there must be DNS SRV records specifying the KDCs.

+
+
kpasswd_server

Points to the server where all the password changes are performed. +If there is no such entry, DNS will be queried (unless forbidden +by dns_lookup_kdc). Finally, port 464 on the admin_server +host will be tried.

+
+
master_kdc

The name for primary_kdc prior to release 1.19. Its value is +used as a fallback if primary_kdc is not specified.

+
+
primary_kdc

Identifies the primary KDC(s). Currently, this tag is used in only +one case: If an attempt to get credentials fails because of an +invalid password, the client software will attempt to contact the +primary KDC, in case the user’s password has just been changed, and +the updated database has not been propagated to the replica +servers yet. New in release 1.19.

+
+
v4_instance_convert

This subsection allows the administrator to configure exceptions +to the default_domain mapping rule. It contains V4 instances +(the tag name) which should be translated to some specific +hostname (the tag value) as the second component in a Kerberos V5 +principal name.

+
+
v4_realm

This relation is used by the krb524 library routines when +converting a V5 principal name to a V4 principal name. It is used +when the V4 realm name and the V5 realm name are not the same, but +still share the same principal names and passwords. The tag value +is the Kerberos V4 realm name.

+
+
+
+
+

[domain_realm]

+

The [domain_realm] section provides a translation from hostnames to +Kerberos realms. Each tag is a domain name, providing the mapping for +that domain and all subdomains. If the tag begins with a period +(.) then it applies only to subdomains. The Kerberos realm may be +identified either in the realms section or using DNS SRV records. +Tag names should be in lower case. For example:

+
[domain_realm]
+    crash.mit.edu = TEST.ATHENA.MIT.EDU
+    .dev.mit.edu = TEST.ATHENA.MIT.EDU
+    mit.edu = ATHENA.MIT.EDU
+
+
+

maps the host with the name crash.mit.edu into the +TEST.ATHENA.MIT.EDU realm. The second entry maps all hosts under the +domain dev.mit.edu into the TEST.ATHENA.MIT.EDU realm, but not +the host with the name dev.mit.edu. That host is matched +by the third entry, which maps the host mit.edu and all hosts +under the domain mit.edu that do not match a preceding rule +into the realm ATHENA.MIT.EDU.

+

If no translation entry applies to a hostname used for a service +principal for a service ticket request, the library will try to get a +referral to the appropriate realm from the client realm’s KDC. If +that does not succeed, the host’s realm is considered to be the +hostname’s domain portion converted to uppercase, unless the +realm_try_domains setting in [libdefaults] causes a different +parent domain to be used.

+
+
+

[capaths]

+

In order to perform direct (non-hierarchical) cross-realm +authentication, configuration is needed to determine the +authentication paths between realms.

+

A client will use this section to find the authentication path between +its realm and the realm of the server. The server will use this +section to verify the authentication path used by the client, by +checking the transited field of the received ticket.

+

There is a tag for each participating client realm, and each tag has +subtags for each of the server realms. The value of the subtags is an +intermediate realm which may participate in the cross-realm +authentication. The subtags may be repeated if there is more then one +intermediate realm. A value of “.” means that the two realms share +keys directly, and no intermediate realms should be allowed to +participate.

+

Only those entries which will be needed on the client or the server +need to be present. A client needs a tag for its local realm with +subtags for all the realms of servers it will need to authenticate to. +A server needs a tag for each realm of the clients it will serve, with +a subtag of the server realm.

+

For example, ANL.GOV, PNL.GOV, and NERSC.GOV all wish to +use the ES.NET realm as an intermediate realm. ANL has a sub +realm of TEST.ANL.GOV which will authenticate with NERSC.GOV +but not PNL.GOV. The [capaths] section for ANL.GOV systems +would look like this:

+
[capaths]
+    ANL.GOV = {
+        TEST.ANL.GOV = .
+        PNL.GOV = ES.NET
+        NERSC.GOV = ES.NET
+        ES.NET = .
+    }
+    TEST.ANL.GOV = {
+        ANL.GOV = .
+    }
+    PNL.GOV = {
+        ANL.GOV = ES.NET
+    }
+    NERSC.GOV = {
+        ANL.GOV = ES.NET
+    }
+    ES.NET = {
+        ANL.GOV = .
+    }
+
+
+

The [capaths] section of the configuration file used on NERSC.GOV +systems would look like this:

+
[capaths]
+    NERSC.GOV = {
+        ANL.GOV = ES.NET
+        TEST.ANL.GOV = ES.NET
+        TEST.ANL.GOV = ANL.GOV
+        PNL.GOV = ES.NET
+        ES.NET = .
+    }
+    ANL.GOV = {
+        NERSC.GOV = ES.NET
+    }
+    PNL.GOV = {
+        NERSC.GOV = ES.NET
+    }
+    ES.NET = {
+        NERSC.GOV = .
+    }
+    TEST.ANL.GOV = {
+        NERSC.GOV = ANL.GOV
+        NERSC.GOV = ES.NET
+    }
+
+
+

When a subtag is used more than once within a tag, clients will use +the order of values to determine the path. The order of values is not +important to servers.

+
+
+

[appdefaults]

+

Each tag in the [appdefaults] section names a Kerberos V5 application +or an option that is used by some Kerberos V5 application[s]. The +value of the tag defines the default behaviors for that application.

+

For example:

+
[appdefaults]
+    telnet = {
+        ATHENA.MIT.EDU = {
+            option1 = false
+        }
+    }
+    telnet = {
+        option1 = true
+        option2 = true
+    }
+    ATHENA.MIT.EDU = {
+        option2 = false
+    }
+    option2 = true
+
+
+

The above four ways of specifying the value of an option are shown in +order of decreasing precedence. In this example, if telnet is running +in the realm EXAMPLE.COM, it should, by default, have option1 and +option2 set to true. However, a telnet program in the realm +ATHENA.MIT.EDU should have option1 set to false and +option2 set to true. Any other programs in ATHENA.MIT.EDU should +have option2 set to false by default. Any programs running in +other realms should have option2 set to true.

+

The list of specifiable options for each application may be found in +that application’s man pages. The application defaults specified here +are overridden by those specified in the realms section.

+
+
+

[plugins]

+
+
+
+

Tags in the [plugins] section can be used to register dynamic plugin +modules and to turn modules on and off. Not every krb5 pluggable +interface uses the [plugins] section; the ones that do are documented +here.

+

New in release 1.9.

+

Each pluggable interface corresponds to a subsection of [plugins]. +All subsections support the same tags:

+
+
disable

This tag may have multiple values. If there are values for this +tag, then the named modules will be disabled for the pluggable +interface.

+
+
enable_only

This tag may have multiple values. If there are values for this +tag, then only the named modules will be enabled for the pluggable +interface.

+
+
module

This tag may have multiple values. Each value is a string of the +form modulename:pathname, which causes the shared object +located at pathname to be registered as a dynamic module named +modulename for the pluggable interface. If pathname is not an +absolute path, it will be treated as relative to the +plugin_base_dir value from [libdefaults].

+
+
+

For pluggable interfaces where module order matters, modules +registered with a module tag normally come first, in the order +they are registered, followed by built-in modules in the order they +are documented below. If enable_only tags are used, then the +order of those tags overrides the normal module order.

+

The following subsections are currently supported within the [plugins] +section:

+
+

ccselect interface

+

The ccselect subsection controls modules for credential cache +selection within a cache collection. In addition to any registered +dynamic modules, the following built-in modules exist (and may be +disabled with the disable tag):

+
+
k5identity

Uses a .k5identity file in the user’s home directory to select a +client principal

+
+
realm

Uses the service realm to guess an appropriate cache from the +collection

+
+
hostname

If the service principal is host-based, uses the service hostname +to guess an appropriate cache from the collection

+
+
+
+
+

pwqual interface

+

The pwqual subsection controls modules for the password quality +interface, which is used to reject weak passwords when passwords are +changed. The following built-in modules exist for this interface:

+
+
dict

Checks against the realm dictionary file

+
+
empty

Rejects empty passwords

+
+
hesiod

Checks against user information stored in Hesiod (only if Kerberos +was built with Hesiod support)

+
+
princ

Checks against components of the principal name

+
+
+
+
+

kadm5_hook interface

+

The kadm5_hook interface provides plugins with information on +principal creation, modification, password changes and deletion. This +interface can be used to write a plugin to synchronize MIT Kerberos +with another database such as Active Directory. No plugins are built +in for this interface.

+
+
+

kadm5_auth interface

+

The kadm5_auth section (introduced in release 1.16) controls modules +for the kadmin authorization interface, which determines whether a +client principal is allowed to perform a kadmin operation. The +following built-in modules exist for this interface:

+
+
acl

This module reads the kadm5.acl file, and authorizes +operations which are allowed according to the rules in the file.

+
+
self

This module authorizes self-service operations including password +changes, creation of new random keys, fetching the client’s +principal record or string attributes, and fetching the policy +record associated with the client principal.

+
+
+
+
+

clpreauth and kdcpreauth interfaces

+

The clpreauth and kdcpreauth interfaces allow plugin modules to +provide client and KDC preauthentication mechanisms. The following +built-in modules exist for these interfaces:

+
+
pkinit

This module implements the PKINIT preauthentication mechanism.

+
+
encrypted_challenge

This module implements the encrypted challenge FAST factor.

+
+
encrypted_timestamp

This module implements the encrypted timestamp mechanism.

+
+
+
+
+

hostrealm interface

+

The hostrealm section (introduced in release 1.12) controls modules +for the host-to-realm interface, which affects the local mapping of +hostnames to realm names and the choice of default realm. The following +built-in modules exist for this interface:

+
+
profile

This module consults the [domain_realm] section of the profile for +authoritative host-to-realm mappings, and the default_realm +variable for the default realm.

+
+
dns

This module looks for DNS records for fallback host-to-realm +mappings and the default realm. It only operates if the +dns_lookup_realm variable is set to true.

+
+
domain

This module applies heuristics for fallback host-to-realm +mappings. It implements the realm_try_domains variable, and +uses the uppercased parent domain of the hostname if that does not +produce a result.

+
+
+
+
+

localauth interface

+

The localauth section (introduced in release 1.12) controls modules +for the local authorization interface, which affects the relationship +between Kerberos principals and local system accounts. The following +built-in modules exist for this interface:

+
+
default

This module implements the DEFAULT type for auth_to_local +values.

+
+
rule

This module implements the RULE type for auth_to_local +values.

+
+
names

This module looks for an auth_to_local_names mapping for the +principal name.

+
+
auth_to_local

This module processes auth_to_local values in the default +realm’s section, and applies the default method if no +auth_to_local values exist.

+
+
k5login

This module authorizes a principal to a local account according to +the account’s .k5login file.

+
+
an2ln

This module authorizes a principal to a local account if the +principal name maps to the local account name.

+
+
+
+
+

certauth interface

+

The certauth section (introduced in release 1.16) controls modules for +the certificate authorization interface, which determines whether a +certificate is allowed to preauthenticate a user via PKINIT. The +following built-in modules exist for this interface:

+
+
pkinit_san

This module authorizes the certificate if it contains a PKINIT +Subject Alternative Name for the requested client principal, or a +Microsoft UPN SAN matching the principal if pkinit_allow_upn +is set to true for the realm.

+
+
pkinit_eku

This module rejects the certificate if it does not contain an +Extended Key Usage attribute consistent with the +pkinit_eku_checking value for the realm.

+
+
dbmatch

This module authorizes or rejects the certificate according to +whether it matches the pkinit_cert_match string attribute on +the client principal, if that attribute is present.

+
+
+
+
+
+
+

PKINIT options

+
+

Note

+

The following are PKINIT-specific options. These values may +be specified in [libdefaults] as global defaults, or within +a realm-specific subsection of [libdefaults], or may be +specified as realm-specific values in the [realms] section. +A realm-specific value overrides, not adds to, a generic +[libdefaults] specification. The search order is:

+
+
    +
  1. realm-specific subsection of [libdefaults]:

    +
    [libdefaults]
    +    EXAMPLE.COM = {
    +        pkinit_anchors = FILE:/usr/local/example.com.crt
    +    }
    +
    +
    +
  2. +
  3. realm-specific value in the [realms] section:

    +
    [realms]
    +    OTHERREALM.ORG = {
    +        pkinit_anchors = FILE:/usr/local/otherrealm.org.crt
    +    }
    +
    +
    +
  4. +
  5. generic value in the [libdefaults] section:

    +
    [libdefaults]
    +    pkinit_anchors = DIR:/usr/local/generic_trusted_cas/
    +
    +
    +
  6. +
+
+

Specifying PKINIT identity information

+

The syntax for specifying Public Key identity, trust, and revocation +information for PKINIT is as follows:

+
+
FILE:filename[,keyfilename]

This option has context-specific behavior.

+

In pkinit_identity or pkinit_identities, filename +specifies the name of a PEM-format file containing the user’s +certificate. If keyfilename is not specified, the user’s +private key is expected to be in filename as well. Otherwise, +keyfilename is the name of the file containing the private key.

+

In pkinit_anchors or pkinit_pool, filename is assumed to +be the name of an OpenSSL-style ca-bundle file.

+
+
DIR:dirname

This option has context-specific behavior.

+

In pkinit_identity or pkinit_identities, dirname +specifies a directory with files named *.crt and *.key +where the first part of the file name is the same for matching +pairs of certificate and private key files. When a file with a +name ending with .crt is found, a matching file ending with +.key is assumed to contain the private key. If no such file +is found, then the certificate in the .crt is not used.

+

In pkinit_anchors or pkinit_pool, dirname is assumed to +be an OpenSSL-style hashed CA directory where each CA cert is +stored in a file named hash-of-ca-cert.#. This infrastructure +is encouraged, but all files in the directory will be examined and +if they contain certificates (in PEM format), they will be used.

+

In pkinit_revoke, dirname is assumed to be an OpenSSL-style +hashed CA directory where each revocation list is stored in a file +named hash-of-ca-cert.r#. This infrastructure is encouraged, +but all files in the directory will be examined and if they +contain a revocation list (in PEM format), they will be used.

+
+
PKCS12:filename

filename is the name of a PKCS #12 format file, containing the +user’s certificate and private key.

+
+
PKCS11:[module_name=]modname[:slotid=slot-id][:token=token-label][:certid=cert-id][:certlabel=cert-label]

All keyword/values are optional. modname specifies the location +of a library implementing PKCS #11. If a value is encountered +with no keyword, it is assumed to be the modname. If no +module-name is specified, the default is PKCS11_MODNAME. +slotid= and/or token= may be specified to force the use of +a particular smard card reader or token if there is more than one +available. certid= and/or certlabel= may be specified to +force the selection of a particular certificate on the device. +See the pkinit_cert_match configuration option for more ways +to select a particular certificate to use for PKINIT.

+
+
ENV:envvar

envvar specifies the name of an environment variable which has +been set to a value conforming to one of the previous values. For +example, ENV:X509_PROXY, where environment variable +X509_PROXY has been set to FILE:/tmp/my_proxy.pem.

+
+
+
+
+

PKINIT krb5.conf options

+
+
pkinit_anchors

Specifies the location of trusted anchor (root) certificates which +the client trusts to sign KDC certificates. This option may be +specified multiple times. These values from the config file are +not used if the user specifies X509_anchors on the command line.

+
+
pkinit_cert_match

Specifies matching rules that the client certificate must match +before it is used to attempt PKINIT authentication. If a user has +multiple certificates available (on a smart card, or via other +media), there must be exactly one certificate chosen before +attempting PKINIT authentication. This option may be specified +multiple times. All the available certificates are checked +against each rule in order until there is a match of exactly one +certificate.

+

The Subject and Issuer comparison strings are the RFC 2253 +string representations from the certificate Subject DN and Issuer +DN values.

+

The syntax of the matching rules is:

+
+

[relation-operator]component-rule

+
+

where:

+
+
relation-operator

can be either &&, meaning all component rules must match, +or ||, meaning only one component rule must match. The +default is &&.

+
+
component-rule

can be one of the following. Note that there is no +punctuation or whitespace between component rules.

+
+
+
<SUBJECT>regular-expression
+
<ISSUER>regular-expression
+
<SAN>regular-expression
+
<EKU>extended-key-usage-list
+
<KU>key-usage-list
+
+
+

extended-key-usage-list is a comma-separated list of +required Extended Key Usage values. All values in the list +must be present in the certificate. Extended Key Usage values +can be:

+
    +
  • pkinit

  • +
  • msScLogin

  • +
  • clientAuth

  • +
  • emailProtection

  • +
+

key-usage-list is a comma-separated list of required Key +Usage values. All values in the list must be present in the +certificate. Key Usage values can be:

+
    +
  • digitalSignature

  • +
  • keyEncipherment

  • +
+
+
+

Examples:

+
pkinit_cert_match = ||<SUBJECT>.*DoE.*<SAN>.*@EXAMPLE.COM
+pkinit_cert_match = &&<EKU>msScLogin,clientAuth<ISSUER>.*DoE.*
+pkinit_cert_match = <EKU>msScLogin,clientAuth<KU>digitalSignature
+
+
+
+
pkinit_eku_checking

This option specifies what Extended Key Usage value the KDC +certificate presented to the client must contain. (Note that if +the KDC certificate has the pkinit SubjectAlternativeName encoded +as the Kerberos TGS name, EKU checking is not necessary since the +issuing CA has certified this as a KDC certificate.) The values +recognized in the krb5.conf file are:

+
+
kpKDC

This is the default value and specifies that the KDC must have +the id-pkinit-KPKdc EKU as defined in RFC 4556.

+
+
kpServerAuth

If kpServerAuth is specified, a KDC certificate with the +id-kp-serverAuth EKU will be accepted. This key usage value +is used in most commercially issued server certificates.

+
+
none

If none is specified, then the KDC certificate will not be +checked to verify it has an acceptable EKU. The use of this +option is not recommended.

+
+
+
+
pkinit_dh_min_bits

Specifies the size of the Diffie-Hellman key the client will +attempt to use. The acceptable values are 1024, 2048, and 4096. +The default is 2048.

+
+
pkinit_identities

Specifies the location(s) to be used to find the user’s X.509 +identity information. If this option is specified multiple times, +each value is attempted in order until certificates are found. +Note that these values are not used if the user specifies +X509_user_identity on the command line.

+
+
pkinit_kdc_hostname

The presence of this option indicates that the client is willing +to accept a KDC certificate with a dNSName SAN (Subject +Alternative Name) rather than requiring the id-pkinit-san as +defined in RFC 4556. This option may be specified multiple +times. Its value should contain the acceptable hostname for the +KDC (as contained in its certificate).

+
+
pkinit_pool

Specifies the location of intermediate certificates which may be +used by the client to complete the trust chain between a KDC +certificate and a trusted anchor. This option may be specified +multiple times.

+
+
pkinit_require_crl_checking

The default certificate verification process will always check the +available revocation information to see if a certificate has been +revoked. If a match is found for the certificate in a CRL, +verification fails. If the certificate being verified is not +listed in a CRL, or there is no CRL present for its issuing CA, +and pkinit_require_crl_checking is false, then verification +succeeds.

+

However, if pkinit_require_crl_checking is true and there is +no CRL information available for the issuing CA, then verification +fails.

+

pkinit_require_crl_checking should be set to true if the +policy is such that up-to-date CRLs must be present for every CA.

+
+
pkinit_revoke

Specifies the location of Certificate Revocation List (CRL) +information to be used by the client when verifying the validity +of the KDC certificate presented. This option may be specified +multiple times.

+
+
+
+
+
+

Parameter expansion

+

Starting with release 1.11, several variables, such as +default_keytab_name, allow parameters to be expanded. +Valid parameters are:

+
+
++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

%{TEMP}

Temporary directory

%{uid}

Unix real UID or Windows SID

%{euid}

Unix effective user ID or Windows SID

%{USERID}

Same as %{uid}

%{null}

Empty string

%{LIBDIR}

Installation library directory

%{BINDIR}

Installation binary directory

%{SBINDIR}

Installation admin binary directory

%{username}

(Unix) Username of effective user ID

%{APPDATA}

(Windows) Roaming application data for current user

%{COMMON_APPDATA}

(Windows) Application data for all users

%{LOCAL_APPDATA}

(Windows) Local application data for current user

%{SYSTEM}

(Windows) Windows system folder

%{WINDOWS}

(Windows) Windows folder

%{USERCONFIG}

(Windows) Per-user MIT krb5 config file directory

%{COMMONCONFIG}

(Windows) Common MIT krb5 config file directory

+
+
+
+

Sample krb5.conf file

+

Here is an example of a generic krb5.conf file:

+
[libdefaults]
+    default_realm = ATHENA.MIT.EDU
+    dns_lookup_kdc = true
+    dns_lookup_realm = false
+
+[realms]
+    ATHENA.MIT.EDU = {
+        kdc = kerberos.mit.edu
+        kdc = kerberos-1.mit.edu
+        kdc = kerberos-2.mit.edu
+        admin_server = kerberos.mit.edu
+        primary_kdc = kerberos.mit.edu
+    }
+    EXAMPLE.COM = {
+        kdc = kerberos.example.com
+        kdc = kerberos-1.example.com
+        admin_server = kerberos.example.com
+    }
+
+[domain_realm]
+    mit.edu = ATHENA.MIT.EDU
+
+[capaths]
+    ATHENA.MIT.EDU = {
+           EXAMPLE.COM = .
+    }
+    EXAMPLE.COM = {
+           ATHENA.MIT.EDU = .
+    }
+
+
+
+
+

FILES

+

/etc/krb5.conf

+
+
+

SEE ALSO

+

syslog(3)

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/conf_ldap.html b/krb5-1.21.3/doc/html/admin/conf_ldap.html new file mode 100644 index 00000000..c5b390b5 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/conf_ldap.html @@ -0,0 +1,275 @@ + + + + + + + + + Configuring Kerberos with OpenLDAP back-end — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Configuring Kerberos with OpenLDAP back-end

+
+
    +
  1. Make sure the LDAP server is using local authentication +(ldapi://) or TLS (ldaps). See +https://www.openldap.org/doc/admin/tls.html for instructions on +configuring TLS support in OpenLDAP.

  2. +
  3. Add the Kerberos schema file to the LDAP Server using the OpenLDAP +LDIF file from the krb5 source directory +(src/plugins/kdb/ldap/libkdb_ldap/kerberos.openldap.ldif). +The following example uses local authentication:

    +
    ldapadd -Y EXTERNAL -H ldapi:/// -f /path/to/kerberos.openldap.ldif
    +
    +
    +
  4. +
  5. Choose DNs for the krb5kdc and kadmind servers +to bind to the LDAP server, and create them if necessary. Specify +these DNs with the ldap_kdc_dn and ldap_kadmind_dn +directives in kdc.conf. The kadmind DN will also be +used for administrative commands such as kdb5_util.

    +

    Alternatively, you may configure krb5kdc and kadmind to use SASL +authentication to access the LDAP server; see the [dbmodules] +relations ldap_kdc_sasl_mech and similar.

    +
  6. +
  7. Specify a location for the LDAP service password file by setting +ldap_service_password_file. Use kdb5_ldap_util stashsrvpw +to stash passwords for the KDC and kadmind DNs chosen above. For +example:

    +
    kdb5_ldap_util stashsrvpw -f /path/to/service.keyfile cn=krbadmin,dc=example,dc=com
    +
    +
    +

    Skip this step if you are using SASL authentication and the +mechanism does not require a password.

    +
  8. +
  9. Choose a DN for the global Kerberos container entry (but do not +create the entry at this time). Specify this DN with the +ldap_kerberos_container_dn directive in kdc.conf. +Realm container entries will be created underneath this DN. +Principal entries may exist either underneath the realm container +(the default) or in separate trees referenced from the realm +container.

  10. +
  11. Configure the LDAP server ACLs to enable the KDC and kadmin server +DNs to read and write the Kerberos data. If +disable_last_success and disable_lockout are both set to +true in the [dbmodules] subsection for the realm, then the +KDC DN only requires read access to the Kerberos data.

    +

    Sample access control information:

    +
    access to dn.base=""
    +    by * read
    +
    +access to dn.base="cn=Subschema"
    +    by * read
    +
    +# Provide access to the realm container.
    +access to dn.subtree= "cn=EXAMPLE.COM,cn=krbcontainer,dc=example,dc=com"
    +    by dn.exact="cn=kdc-service,dc=example,dc=com" write
    +    by dn.exact="cn=adm-service,dc=example,dc=com" write
    +    by * none
    +
    +# Provide access to principals, if not underneath the realm container.
    +access to dn.subtree= "ou=users,dc=example,dc=com"
    +    by dn.exact="cn=kdc-service,dc=example,dc=com" write
    +    by dn.exact="cn=adm-service,dc=example,dc=com" write
    +    by * none
    +
    +access to *
    +    by * read
    +
    +
    +

    If the locations of the container and principals or the DNs of the +service objects for a realm are changed then this information +should be updated.

    +
  12. +
  13. In kdc.conf, make sure the following relations are set +in the [dbmodules] subsection for the realm:

    +
    db_library (set to ``kldap``)
    +ldap_kerberos_container_dn
    +ldap_kdc_dn
    +ldap_kadmind_dn
    +ldap_service_password_file
    +ldap_servers
    +
    +
    +
  14. +
  15. Create the realm using kdb5_ldap_util:

    +
    +

    kdb5_ldap_util create -subtrees ou=users,dc=example,dc=com -s

    +
    +

    Use the -subtrees option if the principals are to exist in a +separate subtree from the realm container. Before executing the +command, make sure that the subtree mentioned above +(ou=users,dc=example,dc=com) exists. If the principals will +exist underneath the realm container, omit the -subtrees option +and do not worry about creating the principal subtree.

    +

    For more information, refer to the section Operations on the LDAP database.

    +

    The realm object is created under the +ldap_kerberos_container_dn specified in the configuration +file. This operation will also create the Kerberos container, if +not present already. This container can be used to store +information related to multiple realms.

    +
  16. +
  17. Add an eq index for krbPrincipalName to speed up principal +lookup operations. See +https://www.openldap.org/doc/admin/tuning.html#Indexes for +details.

  18. +
+
+

With the LDAP back end it is possible to provide aliases for principal +entries. Currently we provide no administrative utilities for +creating aliases, so it must be done by direct manipulation of the +LDAP entries.

+

An entry with aliases contains multiple values of the +krbPrincipalName attribute. Since LDAP attribute values are not +ordered, it is necessary to specify which principal name is canonical, +by using the krbCanonicalName attribute. Therefore, to create +aliases for an entry, first set the krbCanonicalName attribute of +the entry to the canonical principal name (which should be identical +to the pre-existing krbPrincipalName value), and then add additional +krbPrincipalName attributes for the aliases.

+

Principal aliases are only returned by the KDC when the client +requests canonicalization. Canonicalization is normally requested for +service principals; for client principals, an explicit flag is often +required (e.g., kinit -C) and canonicalization is only performed +for initial ticket requests.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/database.html b/krb5-1.21.3/doc/html/admin/database.html new file mode 100644 index 00000000..2c668f64 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/database.html @@ -0,0 +1,710 @@ + + + + + + + + + Database administration — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Database administration

+

A Kerberos database contains all of a realm’s Kerberos principals, +their passwords, and other administrative information about each +principal. For the most part, you will use the kdb5_util +program to manipulate the Kerberos database as a whole, and the +kadmin program to make changes to the entries in the +database. (One notable exception is that users will use the +kpasswd program to change their own passwords.) The kadmin +program has its own command-line interface, to which you type the +database administrating commands.

+

kdb5_util provides a means to create, delete, load, or dump +a Kerberos database. It also contains commands to roll over the +database master key, and to stash a copy of the key so that the +kadmind and krb5kdc daemons can use the database +without manual input.

+

kadmin provides for the maintenance of Kerberos principals, +password policies, and service key tables (keytabs). Normally it +operates as a network client using Kerberos authentication to +communicate with kadmind, but there is also a variant, named +kadmin.local, which directly accesses the Kerberos database on the +local filesystem (or through LDAP). kadmin.local is necessary to set +up enough of the database to be able to use the remote version.

+

kadmin can authenticate to the admin server using the service +principal kadmin/admin or kadmin/HOST (where HOST is the +hostname of the admin server). If the credentials cache contains a +ticket for either service principal and the -c ccache option is +specified, that ticket is used to authenticate to KADM5. Otherwise, +the -p and -k options are used to specify the client Kerberos +principal name used to authenticate. Once kadmin has determined the +principal name, it requests a kadmin/admin Kerberos service ticket +from the KDC, and uses that service ticket to authenticate to KADM5.

+

See kadmin for the available kadmin and kadmin.local +commands and options.

+
+

Principals

+

Each entry in the Kerberos database contains a Kerberos principal and +the attributes and policies associated with that principal.

+

To add a principal to the database, use the kadmin +add_principal command. User principals should usually be created +with the +requires_preauth -allow_svr options to help mitigate +dictionary attacks (see Addressing dictionary attack risks):

+
kadmin: addprinc +requires_preauth -allow_svr alice
+Enter password for principal "alice@KRBTEST.COM":
+Re-enter password for principal "alice@KRBTEST.COM":
+
+
+

User principals which will authenticate with PKINIT configuration should +instead by created with the -nokey option:

+
+

kadmin: addprinc -nokey alice

+
+

Service principals can be created with the -nokey option; +long-term keys will be added when a keytab is generated:

+
kadmin: addprinc -nokey host/foo.mit.edu
+kadmin: ktadd -k foo.keytab host/foo.mit.edu
+Entry for principal host/foo.mit.edu with kvno 1, encryption type aes256-cts-hmac-sha1-96 added to keytab WRFILE:foo.keytab.
+Entry for principal host/foo.mit.edu with kvno 1, encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:foo.keytab.
+
+
+

To modify attributes of an existing principal, use the kadmin +modify_principal command:

+
kadmin: modprinc -expire tomorrow alice
+Principal "alice@KRBTEST.COM" modified.
+
+
+

To delete a principal, use the kadmin delete_principal command:

+
kadmin: delprinc alice
+Are you sure you want to delete the principal "alice@KRBTEST.COM"? (yes/no): yes
+Principal "alice@KRBTEST.COM" deleted.
+Make sure that you have removed this principal from all ACLs before reusing.
+
+
+

To change a principal’s password, use the kadmin change_password +command. Password changes made through kadmin are subject to the same +password policies as would apply to password changes made through +kpasswd.

+

To view the attributes of a principal, use the kadmin` +get_principal command.

+

To generate a listing of principals, use the kadmin +list_principals command.

+
+
+

Policies

+

A policy is a set of rules governing passwords. Policies can dictate +minimum and maximum password lifetimes, minimum number of characters +and character classes a password must contain, and the number of old +passwords kept in the database.

+

To add a new policy, use the kadmin add_policy command:

+
kadmin: addpol -maxlife "1 year" -history 3 stduser
+
+
+

To modify attributes of a principal, use the kadmin modify_policy +command. To delete a policy, use the kadmin delete_policy +command.

+

To associate a policy with a principal, use the kadmin +modify_principal command with the -policy option:

+
+

kadmin: modprinc -policy stduser alice +Principal “alice@KRBTEST.COM” modified.

+
+

A principal entry may be associated with a nonexistent policy, either +because the policy did not exist at the time of associated or was +deleted afterwards. kadmin will warn when associated a principal with +a nonexistent policy, and will annotate the policy name with “[does +not exist]” in the get_principal output.

+
+

Updating the history key

+

If a policy specifies a number of old keys kept of two or more, the +stored old keys are encrypted in a history key, which is found in the +key data of the kadmin/history principal.

+

Currently there is no support for proper rollover of the history key, +but you can change the history key (for example, to use a better +encryption type) at the cost of invalidating currently stored old +keys. To change the history key, run:

+
kadmin: change_password -randkey kadmin/history
+
+
+

This command will fail if you specify the -keepold flag. Only one +new history key will be created, even if you specify multiple key/salt +combinations.

+

In the future, we plan to migrate towards encrypting old keys in the +master key instead of the history key, and implementing proper +rollover support for stored old keys.

+
+
+
+

Privileges

+

Administrative privileges for the Kerberos database are stored in the +file kadm5.acl.

+
+

Note

+

A common use of an admin instance is so you can grant +separate permissions (such as administrator access to the +Kerberos database) to a separate Kerberos principal. For +example, the user joeadmin might have a principal for +his administrative use, called joeadmin/admin. This +way, joeadmin would obtain joeadmin/admin tickets +only when he actually needs to use those permissions.

+
+
+
+

Operations on the Kerberos database

+

The kdb5_util command is the primary tool for administrating +the Kerberos database when using the DB2 or LMDB modules (see +Database types). Creating a database is described in +Create the KDC database.

+

To create a stash file using the master password (because the database +was not created with one using the create -s flag, or after +restoring from a backup which did not contain the stash file), use the +kdb5_util stash command:

+
$ kdb5_util stash
+kdb5_util: Cannot find/read stored master key while reading master key
+kdb5_util: Warning: proceeding without master key
+Enter KDC database master key:  <= Type the KDC database master password.
+
+
+

To destroy a database, use the kdb5_util destroy command:

+
$ kdb5_util destroy
+Deleting KDC database stored in '/var/krb5kdc/principal', are you sure?
+(type 'yes' to confirm)? yes
+OK, deleting database '/var/krb5kdc/principal'...
+** Database '/var/krb5kdc/principal' destroyed.
+
+
+
+

Dumping and loading a Kerberos database

+

To dump a Kerberos database into a text file for backup or transfer +purposes, use the kdb5_util dump command on one of the +KDCs:

+
$ kdb5_util dump dumpfile
+
+$ kbd5_util dump -verbose dumpfile
+kadmin/admin@ATHENA.MIT.EDU
+krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU
+kadmin/history@ATHENA.MIT.EDU
+K/M@ATHENA.MIT.EDU
+kadmin/changepw@ATHENA.MIT.EDU
+
+
+

You may specify which principals to dump, using full principal names +including realm:

+
$ kdb5_util dump -verbose someprincs K/M@ATHENA.MIT.EDU kadmin/admin@ATHENA.MIT.EDU
+kadmin/admin@ATHENA.MIT.EDU
+K/M@ATHENA.MIT.EDU
+
+
+

To restore a Kerberos database dump from a file, use the +kdb5_util load command:

+
$ kdb5_util load dumpfile
+
+
+

To update an existing database with a partial dump file containing +only some principals, use the -update flag:

+
$ kdb5_util load -update someprincs
+
+
+
+

Note

+

If the database file exists, and the -update flag was not +given, kdb5_util will overwrite the existing database.

+
+
+
+

Updating the master key

+

Starting with release 1.7, kdb5_util allows the master key +to be changed using a rollover process, with minimal loss of +availability. To roll over the master key, follow these steps:

+
    +
  1. On the primary KDC, run kdb5_util list_mkeys to view the +current master key version number (KVNO). If you have never rolled +over the master key before, this will likely be version 1:

    +
    $ kdb5_util list_mkeys
    +Master keys for Principal: K/M@KRBTEST.COM
    +KVNO: 1, Enctype: aes256-cts-hmac-sha384-192, Active on: Thu Jan 01 00:00:00 UTC 1970 *
    +
    +
    +
  2. +
  3. On the primary KDC, run kdb5_util use_mkey 1 to ensure that a +master key activation list is present in the database. This step +is unnecessary in release 1.11.4 or later, or if the database was +initially created with release 1.7 or later.

  4. +
  5. On the primary KDC, run kdb5_util add_mkey -s to create a new +master key and write it to the stash file. Enter a secure password +when prompted. If this is the first time you are changing the +master key, the new key will have version 2. The new master key +will not be used until you make it active.

  6. +
  7. Propagate the database to all replica KDCs, either manually or by +waiting until the next scheduled propagation. If you do not have +any replica KDCs, you can skip this and the next step.

  8. +
  9. On each replica KDC, run kdb5_util list_mkeys to verify that +the new master key is present, and then kdb5_util stash to +write the new master key to the replica KDC’s stash file.

  10. +
  11. On the primary KDC, run kdb5_util use_mkey 2 to begin using the +new master key. Replace 2 with the version of the new master +key, as appropriate. You can optionally specify a date for the new +master key to become active; by default, it will become active +immediately. Prior to release 1.12, kadmind must be +restarted for this change to take full effect.

  12. +
  13. On the primary KDC, run kdb5_util update_princ_encryption. +This command will iterate over the database and re-encrypt all keys +in the new master key. If the database is large and uses DB2, the +primary KDC will become unavailable while this command runs, but +clients should fail over to replica KDCs (if any are present) +during this time period. In release 1.13 and later, you can +instead run kdb5_util -x unlockiter update_princ_encryption to +use unlocked iteration; this variant will take longer, but will +keep the database available to the KDC and kadmind while it runs.

  14. +
  15. Wait until the above changes have propagated to all replica KDCs +and until all running KDC and kadmind processes have serviced +requests using updated principal entries.

  16. +
  17. On the primary KDC, run kdb5_util purge_mkeys to clean up the +old master key.

  18. +
+
+
+
+

Operations on the LDAP database

+

The kdb5_ldap_util command is the primary tool for +administrating the Kerberos database when using the LDAP module. +Creating an LDAP Kerberos database is describe in Configuring Kerberos with OpenLDAP back-end.

+

To view a list of realms in the LDAP database, use the kdb5_ldap_util +list command:

+
$ kdb5_ldap_util list
+KRBTEST.COM
+
+
+

To modify the attributes of a realm, use the kdb5_ldap_util modify +command. For example, to change the default realm’s maximum ticket +life:

+
$ kdb5_ldap_util modify -maxtktlife "10 hours"
+
+
+

To display the attributes of a realm, use the kdb5_ldap_util view +command:

+
$ kdb5_ldap_util view
+               Realm Name: KRBTEST.COM
+      Maximum Ticket Life: 0 days 00:10:00
+
+
+

To remove a realm from the LDAP database, destroying its contents, use +the kdb5_ldap_util destroy command:

+
$ kdb5_ldap_util destroy
+Deleting KDC database of 'KRBTEST.COM', are you sure?
+(type 'yes' to confirm)? yes
+OK, deleting database of 'KRBTEST.COM'...
+** Database of 'KRBTEST.COM' destroyed.
+
+
+
+

Ticket Policy operations

+

Unlike the DB2 and LMDB modules, the LDAP module supports ticket +policy objects, which can be associated with principals to restrict +maximum ticket lifetimes and set mandatory principal flags. Ticket +policy objects are distinct from the password policies described +earlier on this page, and are chiefly managed through kdb5_ldap_util +rather than kadmin. To create a new ticket policy, use the +kdb5_ldap_util create_policy command:

+
$ kdb5_ldap_util create_policy -maxrenewlife "2 days" users
+
+
+

To associate a ticket policy with a principal, use the +kadmin modify_principal (or add_principal) command +with the -x tktpolicy=policy option:

+
$ kadmin.local modprinc -x tktpolicy=users alice
+
+
+

To remove a ticket policy reference from a principal, use the same +command with an empty policy:

+
$ kadmin.local modprinc -x tktpolicy= alice
+
+
+

To list the existing ticket policy objects, use the kdb5_ldap_util +list_policy command:

+
$ kdb5_ldap_util list_policy
+users
+
+
+

To modify the attributes of a ticket policy object, use the +kdb5_ldap_util modify_policy command:

+
$ kdb5_ldap_util modify_policy -allow_svr +requires_preauth users
+
+
+

To view the attributes of a ticket policy object, use the +kdb5_ldap_util view_policy command:

+
$ kdb5_ldap_util view_policy users
+            Ticket policy: users
+   Maximum renewable life: 2 days 00:00:00
+             Ticket flags: REQUIRES_PRE_AUTH DISALLOW_SVR
+
+
+

To destroy an ticket policy object, use the kdb5_ldap_util +destroy_policy command:

+
$ kdb5_ldap_util destroy_policy users
+This will delete the policy object 'users', are you sure?
+(type 'yes' to confirm)? yes
+** policy object 'users' deleted.
+
+
+
+
+
+

Cross-realm authentication

+

In order for a KDC in one realm to authenticate Kerberos users in a +different realm, it must share a key with the KDC in the other realm. +In both databases, there must be krbtgt service principals for both realms. +For example, if you need to do cross-realm authentication between the realms +ATHENA.MIT.EDU and EXAMPLE.COM, you would need to add the +principals krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU and +krbtgt/ATHENA.MIT.EDU@EXAMPLE.COM to both databases. +These principals must all have the same passwords, key version +numbers, and encryption types; this may require explicitly setting +the key version number with the -kvno option.

+

In the ATHENA.MIT.EDU and EXAMPLE.COM cross-realm case, the administrators +would run the following commands on the KDCs in both realms:

+
shell%: kadmin.local -e "aes256-cts:normal"
+kadmin: addprinc -requires_preauth krbtgt/ATHENA.MIT.EDU@EXAMPLE.COM
+Enter password for principal krbtgt/ATHENA.MIT.EDU@EXAMPLE.COM:
+Re-enter password for principal krbtgt/ATHENA.MIT.EDU@EXAMPLE.COM:
+kadmin: addprinc -requires_preauth krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU
+Enter password for principal krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU:
+Enter password for principal krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU:
+kadmin:
+
+
+
+

Note

+

Even if most principals in a realm are generally created +with the requires_preauth flag enabled, this flag is not +desirable on cross-realm authentication keys because doing +so makes it impossible to disable preauthentication on a +service-by-service basis. Disabling it as in the example +above is recommended.

+
+
+

Note

+

It is very important that these principals have good +passwords. MIT recommends that TGT principal passwords be +at least 26 characters of random ASCII text.

+
+
+
+

Changing the krbtgt key

+

A Kerberos Ticket Granting Ticket (TGT) is a service ticket for the +principal krbtgt/REALM. The key for this principal is created +when the Kerberos database is initialized and need not be changed. +However, it will only have the encryption types supported by the KDC +at the time of the initial database creation. To allow use of newer +encryption types for the TGT, this key has to be changed.

+

Changing this key using the normal kadmin +change_password command would invalidate any previously issued +TGTs. Therefore, when changing this key, normally one should use the +-keepold flag to change_password to retain the previous key in the +database as well as the new key. For example:

+
kadmin: change_password -randkey -keepold krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU
+
+
+
+

Warning

+

After issuing this command, the old key is still valid +and is still vulnerable to (for instance) brute force +attacks. To completely retire an old key or encryption +type, run the kadmin purgekeys command to delete keys +with older kvnos, ideally first making sure that all +tickets issued with the old keys have expired.

+
+

Only the first krbtgt key of the newest key version is used to encrypt +ticket-granting tickets. However, the set of encryption types present +in the krbtgt keys is used by default to determine the session key +types supported by the krbtgt service (see +Session key selection). Because non-MIT Kerberos clients +sometimes send a limited set of encryption types when making AS +requests, it can be important for the krbtgt service to support +multiple encryption types. This can be accomplished by giving the +krbtgt principal multiple keys, which is usually as simple as not +specifying any -e option when changing the krbtgt key, or by +setting the session_enctypes string attribute on the krbtgt +principal (see set_string).

+

Due to a bug in releases 1.8 through 1.13, renewed and forwarded +tickets may not work if the original ticket was obtained prior to a +krbtgt key change and the modified ticket is obtained afterwards. +Upgrading the KDC to release 1.14 or later will correct this bug.

+
+
+

Incremental database propagation

+
+

Overview

+

At some very large sites, dumping and transmitting the database can +take more time than is desirable for changes to propagate from the +primary KDC to the replica KDCs. The incremental propagation support +added in the 1.7 release is intended to address this.

+

With incremental propagation enabled, all programs on the primary KDC +that change the database also write information about the changes to +an “update log” file, maintained as a circular buffer of a certain +size. A process on each replica KDC connects to a service on the +primary KDC (currently implemented in the kadmind server) and +periodically requests the changes that have been made since the last +check. By default, this check is done every two minutes.

+

Incremental propagation uses the following entries in the per-realm +data in the KDC config file (See kdc.conf):

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +

iprop_enable

boolean

If true, then incremental propagation is enabled, and (as noted below) normal kprop propagation is disabled. The default is false.

iprop_master_ulogsize

integer

Indicates the number of entries that should be retained in the update log. The default is 1000; the maximum number is 2500.

iprop_replica_poll

time interval

Indicates how often the replica should poll the primary KDC for changes to the database. The default is two minutes.

iprop_port

integer

Specifies the port number to be used for incremental propagation. This is required in both primary and replica configuration files.

iprop_resync_timeout

integer

Specifies the number of seconds to wait for a full propagation to complete. This is optional on replica configurations. Defaults to 300 seconds (5 minutes).

iprop_logfile

file name

Specifies where the update log file for the realm database is to be stored. The default is to use the database_name entry from the realms section of the config file kdc.conf, with .ulog appended. (NOTE: If database_name isn’t specified in the realms section, perhaps because the LDAP database back end is being used, or the file name is specified in the dbmodules section, then the hard-coded default for database_name is used. Determination of the iprop_logfile default value will not use values from the dbmodules section.)

+

Both primary and replica sides must have a principal named +kiprop/hostname (where hostname is the lowercase, +fully-qualified, canonical name for the host) registered in the +Kerberos database, and have keys for that principal stored in the +default keytab file (DEFKTNAME). The kiprop/hostname principal may +have been created automatically for the primary KDC, but it must +always be created for replica KDCs.

+

On the primary KDC side, the kiprop/hostname principal must be +listed in the kadmind ACL file kadm5.acl, and given the +p privilege (see Privileges).

+

On the replica KDC side, kpropd should be run. When +incremental propagation is enabled, it will connect to the kadmind on +the primary KDC and start requesting updates.

+

The normal kprop mechanism is disabled by the incremental propagation +support. However, if the replica has been unable to fetch changes +from the primary KDC for too long (network problems, perhaps), the log +on the primary may wrap around and overwrite some of the updates that +the replica has not yet retrieved. In this case, the replica will +instruct the primary KDC to dump the current database out to a file +and invoke a one-time kprop propagation, with special options to also +convey the point in the update log at which the replica should resume +fetching incremental updates. Thus, all the keytab and ACL setup +previously described for kprop propagation is still needed.

+

If an environment has a large number of replicas, it may be desirable +to arrange them in a hierarchy instead of having the primary serve +updates to every replica. To do this, run kadmind -proponly on +each intermediate replica, and kpropd -A upstreamhostname on +downstream replicas to direct each one to the appropriate upstream +replica.

+

There are several known restrictions in the current implementation:

+
    +
  • The incremental update protocol does not transport changes to policy +objects. Any policy changes on the primary will result in full +resyncs to all replicas.

  • +
  • The replica’s KDB module must support locking; it cannot be using the +LDAP KDB module.

  • +
  • The primary and replica must be able to initiate TCP connections in +both directions, without an intervening NAT.

  • +
+
+
+

Sun/MIT incremental propagation differences

+

Sun donated the original code for supporting incremental database +propagation to MIT. Some changes have been made in the MIT source +tree that will be visible to administrators. (These notes are based +on Sun’s patches. Changes to Sun’s implementation since then may not +be reflected here.)

+

The Sun config file support looks for sunw_dbprop_enable, +sunw_dbprop_master_ulogsize, and sunw_dbprop_slave_poll.

+

The incremental propagation service is implemented as an ONC RPC +service. In the Sun implementation, the service is registered with +rpcbind (also known as portmapper) and the client looks up the port +number to contact. In the MIT implementation, where interaction with +some modern versions of rpcbind doesn’t always work well, the port +number must be specified in the config file on both the primary and +replica sides.

+

The Sun implementation hard-codes pathnames in /var/krb5 for the +update log and the per-replica kprop dump files. In the MIT +implementation, the pathname for the update log is specified in the +config file, and the per-replica dump files are stored in +LOCALSTATEDIR/krb5kdc/replica_datatrans_hostname.

+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/dbtypes.html b/krb5-1.21.3/doc/html/admin/dbtypes.html new file mode 100644 index 00000000..af0f101f --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/dbtypes.html @@ -0,0 +1,288 @@ + + + + + + + + + Database types — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Database types

+

A Kerberos database can be implemented with one of three built-in +database providers, called KDB modules. Software which incorporates +the MIT krb5 KDC may also provide its own KDB module. The following +subsections describe the three built-in KDB modules and the +configuration specific to them.

+

The database type can be configured with the db_library variable +in the [dbmodules] subsection for the realm. For example:

+
[dbmodules]
+    ATHENA.MIT.EDU = {
+        db_library = db2
+    }
+
+
+

If the ATHENA.MIT.EDU realm subsection contains a +database_module setting, then the subsection within +[dbmodules] should use that name instead of ATHENA.MIT.EDU.

+

To transition from one database type to another, stop the +kadmind service, use kdb5_util dump to create a dump +file, change the db_library value and set any appropriate +configuration for the new database type, and use kdb5_util load to +create and populate the new database. If the new database type is +LDAP, create the new database using kdb5_ldap_util and populate it +from the dump file using kdb5_util load -update. Then restart the +krb5kdc and kadmind services.

+
+

Berkeley database module (db2)

+

The default KDB module is db2, which uses a version of the +Berkeley DB library. It creates four files based on the database +pathname. If the pathname ends with principal then the four files +are:

+
    +
  • principal, containing principal entry data

  • +
  • principal.ok, a lock file for the principal database

  • +
  • principal.kadm5, containing policy object data

  • +
  • principal.kadm5.lock, a lock file for the policy database

  • +
+

For large databases, the kdb5_util dump command (perhaps +invoked by kprop or by kadmind for incremental +propagation) may cause krb5kdc to stop for a noticeable +period of time while it iterates over the database. This delay can be +avoided by disabling account lockout features so that the KDC does not +perform database writes (see KDC performance and account lockout). Alternatively, +a slower form of iteration can be enabled by setting the +unlockiter variable to true. For example:

+
[dbmodules]
+    ATHENA.MIT.EDU = {
+        db_library = db2
+        unlockiter = true
+    }
+
+
+

In rare cases, a power failure or other unclean system shutdown may +cause inconsistencies in the internal pointers within a database file, +such that kdb5_util dump cannot retrieve all principal entries in +the database. In this situation, it may be possible to retrieve all +of the principal data by running kdb5_util dump -recurse to +iterate over the database using the tree pointers instead of the +iteration pointers. Running kdb5_util dump -rev to iterate over +the database backwards may also retrieve some of the data which is not +retrieved by a normal dump operation.

+
+
+

Lightning Memory-Mapped Database module (klmdb)

+

The klmdb module was added in release 1.17. It uses the LMDB library, +and may offer better performance and reliability than the db2 module. +It creates four files based on the database pathname. If the pathname +ends with principal, then the four files are:

+
    +
  • principal.mdb, containing policy object data and most principal +entry data

  • +
  • principal.mdb-lock, a lock file for the primary database

  • +
  • principal.lockout.mdb, containing the account lockout attributes +(last successful authentication time, last failed authentication +time, and number of failed attempts) for each principal entry

  • +
  • principal.lockout.mdb-lock, a lock file for the lockout database

  • +
+

Separating out the lockout attributes ensures that the KDC will never +block on an administrative operation such as a database dump or load. +It also allows the KDC to operate without write access to the primary +database. If both account lockout features are disabled (see +KDC performance and account lockout), the lockout database files will be created +but will not subsequently be opened, and the account lockout +attributes will always have zero values.

+

Because LMDB creates a memory map to the database files, it requires a +configured memory map size which also determines the maximum size of +the database. This size is applied equally to the two databases, so +twice the configured size will be consumed in the process address +space; this is primarily a limitation on 32-bit platforms. The +default value of 128 megabytes should be sufficient for several +hundred thousand principal entries. If the limit is reached, kadmin +operations will fail and the error message “Environment mapsize limit +reached” will appear in the kadmind log file. In this case, the +mapsize variable can be used to increase the map size. The +following example sets the map size to 512 megabytes:

+
[dbmodules]
+    ATHENA.MIT.EDU = {
+        db_library = klmdb
+        mapsize = 512
+    }
+
+
+

LMDB has a configurable maximum number of readers. The default value +of 128 should be sufficient for most deployments. If you are going to +use a large number of KDC worker processes, it may be necessary to set +the max_readers variable to a larger number.

+

By default, LMDB synchronizes database files to disk after each write +transaction to ensure durability in the case of an unclean system +shutdown. The klmdb module always turns synchronization off for the +lockout database to ensure reasonable KDC performance, but leaves it +on for the primary database. If high throughput for administrative +operations (including password changes) is required, the nosync +variable can be set to “true” to disable synchronization for the +primary database.

+

The klmdb module does not support explicit locking with the +kadmin lock command.

+
+
+

LDAP module (kldap)

+

The kldap module stores principal and policy data using an LDAP +server. To use it you must configure an LDAP server to use the +Kerberos schema. See Configuring Kerberos with OpenLDAP back-end for details.

+

Because krb5kdc is single-threaded, latency in LDAP database +accesses may limit KDC operation throughput. If the LDAP server is +located on the same server host as the KDC and accessed through an +ldapi:// URL, latency should be minimal. If this is not possible, +consider starting multiple KDC worker processes with the +krb5kdc -w option to enable concurrent processing of KDC +requests.

+

The kldap module does not support explicit locking with the +kadmin lock command.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/dictionary.html b/krb5-1.21.3/doc/html/admin/dictionary.html new file mode 100644 index 00000000..c9b44139 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/dictionary.html @@ -0,0 +1,226 @@ + + + + + + + + + Addressing dictionary attack risks — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Addressing dictionary attack risks

+

Kerberos initial authentication is normally secured using the client +principal’s long-term key, which for users is generally derived from a +password. Using a pasword-derived long-term key carries the risk of a +dictionary attack, where an attacker tries a sequence of possible +passwords, possibly requiring much less effort than would be required +to try all possible values of the key. Even if password policy +objects are used to force users not to pick trivial +passwords, dictionary attacks can sometimes be successful against a +significant fraction of the users in a realm. Dictionary attacks are +not a concern for principals using random keys.

+

A dictionary attack may be online or offline. An online dictionary +attack is performed by trying each password in a separate request to +the KDC, and is therefore visible to the KDC and also limited in speed +by the KDC’s processing power and the network capacity between the +client and the KDC. Online dictionary attacks can be mitigated using +account lockout. This measure is not totally +satisfactory, as it makes it easy for an attacker to deny access to a +client principal.

+

An offline dictionary attack is performed by obtaining a ciphertext +generated using the password-derived key, and trying each password +against the ciphertext. This category of attack is invisible to the +KDC and can be performed much faster than an online attack. The +attack will generally take much longer with more recent encryption +types (particularly the ones based on AES), because those encryption +types use a much more expensive string-to-key function. However, the +best defense is to deny the attacker access to a useful ciphertext. +The required defensive measures depend on the attacker’s level of +network access.

+

An off-path attacker has no access to packets sent between legitimate +users and the KDC. An off-path attacker could gain access to an +attackable ciphertext either by making an AS request for a client +principal which does not have the +requires_preauth flag, or by +making a TGS request (after authenticating as a different user) for a +server principal which does not have the -allow_svr flag. To +address off-path attackers, a KDC administrator should set those flags +on principals with password-derived keys:

+
kadmin: add_principal +requires_preauth -allow_svr princname
+
+
+

An attacker with passive network access (one who can monitor packets +sent between legitimate users and the KDC, but cannot change them or +insert their own packets) can gain access to an attackable ciphertext +by observing an authentication by a user using the most common form of +preauthentication, encrypted timestamp. Any of the following methods +can prevent dictionary attacks by attackers with passive network +access:

+
    +
  • Enabling SPAKE preauthentication (added in release +1.17) on the KDC, and ensuring that all clients are able to support +it.

  • +
  • Using an HTTPS proxy for communication with the KDC, +if the attacker cannot monitor communication between the proxy +server and the KDC.

  • +
  • Using FAST, protecting the initial authentication with either a +random key (such as a host key) or with anonymous PKINIT.

  • +
+

An attacker with active network access (one who can inject or modify +packets sent between legitimate users and the KDC) can try to fool the +client software into sending an attackable ciphertext using an +encryption type and salt string of the attacker’s choosing. Any of the +following methods can prevent dictionary attacks by active attackers:

+
    +
  • Enabling SPAKE preauthentication and setting the +disable_encrypted_timestamp variable to true in the +[realms] subsection of the client configuration.

  • +
  • Using an HTTPS proxy as described above, configured in the client’s +krb5.conf realm configuration. If KDC discovery is used to locate a proxy server, an active +attacker may be able to use DNS spoofing to cause the client to use +a different HTTPS server or to not use HTTPS.

  • +
  • Using FAST as described above.

  • +
+

If PKINIT or OTP are used for +initial authentication, the principal’s long-term keys are not used +and dictionary attacks are usually not a concern.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/enctypes.html b/krb5-1.21.3/doc/html/admin/enctypes.html new file mode 100644 index 00000000..cfe92410 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/enctypes.html @@ -0,0 +1,402 @@ + + + + + + + + + Encryption types — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Encryption types

+

Kerberos can use a variety of cipher algorithms to protect data. A +Kerberos encryption type (also known as an enctype) is a +specific combination of a cipher algorithm with an integrity algorithm +to provide both confidentiality and integrity to data.

+
+

Enctypes in requests

+

Clients make two types of requests (KDC-REQ) to the KDC: AS-REQs and +TGS-REQs. The client uses the AS-REQ to obtain initial tickets +(typically a Ticket-Granting Ticket (TGT)), and uses the TGS-REQ to +obtain service tickets.

+

The KDC uses three different keys when issuing a ticket to a client:

+
    +
  • The long-term key of the service: the KDC uses this to encrypt the +actual service ticket. The KDC only uses the first long-term key in +the most recent kvno for this purpose.

  • +
  • The session key: the KDC randomly chooses this key and places one +copy inside the ticket and the other copy inside the encrypted part +of the reply.

  • +
  • The reply-encrypting key: the KDC uses this to encrypt the reply it +sends to the client. For AS replies, this is a long-term key of the +client principal. For TGS replies, this is either the session key of the +authenticating ticket, or a subsession key.

  • +
+

Each of these keys is of a specific enctype.

+

Each request type allows the client to submit a list of enctypes that +it is willing to accept. For the AS-REQ, this list affects both the +session key selection and the reply-encrypting key selection. For the +TGS-REQ, this list only affects the session key selection.

+
+
+

Session key selection

+

The KDC chooses the session key enctype by taking the intersection of +its permitted_enctypes list, the list of long-term keys for the +most recent kvno of the service, and the client’s requested list of +enctypes. Starting in krb5-1.21, all services are assumed to support +aes256-cts-hmac-sha1-96; also, des3-cbc-sha1 and arcfour-hmac session +keys will not be issued by default.

+

Starting in krb5-1.11, it is possible to set a string attribute on a +service principal to control what session key enctypes the KDC may +issue for service tickets for that principal, overriding the service’s +long-term keys and the assumption of aes256-cts-hmac-sha1-96 support. +See set_string in kadmin for details.

+
+
+

Choosing enctypes for a service

+

Generally, a service should have a key of the strongest +enctype that both it and the KDC support. If the KDC is running a +release earlier than krb5-1.11, it is also useful to generate an +additional key for each enctype that the service can support. The KDC +will only use the first key in the list of long-term keys for encrypting +the service ticket, but the additional long-term keys indicate the +other enctypes that the service supports.

+

As noted above, starting with release krb5-1.11, there are additional +configuration settings that control session key enctype selection +independently of the set of long-term keys that the KDC has stored for +a service principal.

+
+
+

Configuration variables

+

The following [libdefaults] settings in krb5.conf will +affect how enctypes are chosen.

+
+
allow_weak_crypto

defaults to false starting with krb5-1.8. When false, removes +weak enctypes from permitted_enctypes, +default_tkt_enctypes, and default_tgs_enctypes. Do not +set this to true unless the use of weak enctypes is an +acceptable risk for your environment and the weak enctypes are +required for backward compatibility.

+
+
allow_des3

was added in release 1.21 and defaults to false. Unless this +flag is set to true, the KDC will not issue tickets with +des3-cbc-sha1 session keys. In a future release, this flag will +control whether des3-cbc-sha1 is permitted in similar fashion to +weak enctypes.

+
+
allow_rc4

was added in release 1.21 and defaults to false. Unless this +flag is set to true, the KDC will not issue tickets with +arcfour-hmac session keys. In a future release, this flag will +control whether arcfour-hmac is permitted in similar fashion to +weak enctypes.

+
+
permitted_enctypes

controls the set of enctypes that a service will permit for +session keys and for ticket and authenticator encryption. The KDC +and other programs that access the Kerberos database will ignore +keys of non-permitted enctypes. Starting in release 1.18, this +setting also acts as the default for default_tkt_enctypes and +default_tgs_enctypes.

+
+
default_tkt_enctypes

controls the default set of enctypes that the Kerberos client +library requests when making an AS-REQ. Do not set this unless +required for specific backward compatibility purposes; stale +values of this setting can prevent clients from taking advantage +of new stronger enctypes when the libraries are upgraded.

+
+
default_tgs_enctypes

controls the default set of enctypes that the Kerberos client +library requests when making a TGS-REQ. Do not set this unless +required for specific backward compatibility purposes; stale +values of this setting can prevent clients from taking advantage +of new stronger enctypes when the libraries are upgraded.

+
+
+

The following per-realm setting in kdc.conf affects the +generation of long-term keys.

+
+
supported_enctypes

controls the default set of enctype-salttype pairs that kadmind +will use for generating long-term keys, either randomly or from +passwords

+
+
+
+
+

Enctype compatibility

+

See Encryption types for additional information about enctypes.

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

enctype

weak?

krb5

Windows

des-cbc-crc

weak

<1.18

>=2000

des-cbc-md4

weak

<1.18

?

des-cbc-md5

weak

<1.18

>=2000

des3-cbc-sha1

deprecated

>=1.1

none

arcfour-hmac

deprecated

>=1.3

>=2000

arcfour-hmac-exp

weak

>=1.3

>=2000

aes128-cts-hmac-sha1-96

>=1.3

>=Vista

aes256-cts-hmac-sha1-96

>=1.3

>=Vista

aes128-cts-hmac-sha256-128

>=1.15

none

aes256-cts-hmac-sha384-192

>=1.15

none

camellia128-cts-cmac

>=1.9

none

camellia256-cts-cmac

>=1.9

none

+

krb5 releases 1.18 and later do not support single-DES. krb5 releases +1.8 and later disable the single-DES enctypes by default. Microsoft +Windows releases Windows 7 and later disable single-DES enctypes by +default.

+

krb5 releases 1.17 and later flag deprecated encryption types +(including des3-cbc-sha1 and arcfour-hmac) in KDC logs and +kadmin output. krb5 release 1.19 issues a warning during initial +authentication if des3-cbc-sha1 is used. Future releases will +disable des3-cbc-sha1 by default and eventually remove support for +it.

+
+
+

Migrating away from older encryption types

+

Administrator intervention may be required to migrate a realm away +from legacy encryption types, especially if the realm was created +using krb5 release 1.2 or earlier. This migration should be performed +before upgrading to krb5 versions which disable or remove support for +legacy encryption types.

+

If there is a supported_enctypes setting in kdc.conf on +the KDC, make sure that it does not include weak or deprecated +encryption types. This will ensure that newly created keys do not use +those encryption types by default.

+

Check the krbtgt/REALM principal using the kadmin +getprinc command. If it lists a weak or deprecated encryption +type as the first key, it must be migrated using the procedure in +Changing the krbtgt key.

+

Check the kadmin/history principal, which should have only one key +entry. If it uses a weak or deprecated encryption type, it should be +upgraded following the notes in Updating the history key.

+

Check the other kadmin principals: kadmin/changepw, kadmin/admin, and +any kadmin/hostname principals that may exist. These principals can +be upgraded with change_password -randkey in kadmin.

+

Check the K/M entry. If it uses a weak or deprecated encryption +type, it should be upgraded following the procedure in +Updating the master key.

+

User and service principals using legacy encryption types can be +enumerated with the kdb5_util tabdump keyinfo command.

+

Service principals can be migrated with a keytab rotation on the +service host, which can be accomplished using the k5srvutil +change and delold commands. Allow enough time for existing +tickets to expire between the change and delold operations.

+

User principals with password-based keys can be migrated with a +password change. The realm administrator can set a password +expiration date using the kadmin modify_principal +-pwexpire command to force a password change.

+

If a legacy encryption type has not yet been disabled by default in +the version of krb5 running on the KDC, it can be disabled +administratively with the permitted_enctypes variable. For +example, setting permitted_enctypes to DEFAULT -des3 -rc4 will +cause any database keys of the triple-DES and RC4 encryption types to +be ignored.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/env_variables.html b/krb5-1.21.3/doc/html/admin/env_variables.html new file mode 100644 index 00000000..d7bbc8f5 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/env_variables.html @@ -0,0 +1,153 @@ + + + + + + + + + Environment variables — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/host_config.html b/krb5-1.21.3/doc/html/admin/host_config.html new file mode 100644 index 00000000..709c6dcf --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/host_config.html @@ -0,0 +1,362 @@ + + + + + + + + + Host configuration — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Host configuration

+

All hosts running Kerberos software, whether they are clients, +application servers, or KDCs, can be configured using +krb5.conf. Here we describe some of the behavior changes +you might want to make.

+
+

Default realm

+

In the [libdefaults] section, the default_realm realm +relation sets the default Kerberos realm. For example:

+
[libdefaults]
+    default_realm = ATHENA.MIT.EDU
+
+
+

The default realm affects Kerberos behavior in the following ways:

+
    +
  • When a principal name is parsed from text, the default realm is used +if no @REALM component is specified.

  • +
  • The default realm affects login authorization as described below.

  • +
  • For programs which operate on a Kerberos database, the default realm +is used to determine which database to operate on, unless the -r +parameter is given to specify a realm.

  • +
  • A server program may use the default realm when looking up its key +in a keytab file, if its realm is not +determined by [domain_realm] configuration or by the server +program itself.

  • +
  • If kinit is passed the -n flag, it requests anonymous +tickets from the default realm.

  • +
+

In some situations, these uses of the default realm might conflict. +For example, it might be desirable for principal name parsing to use +one realm by default, but for login authorization to use a second +realm. In this situation, the first realm can be configured as the +default realm, and auth_to_local relations can be used as +described below to use the second realm for login authorization.

+
+
+

Login authorization

+

If a host runs a Kerberos-enabled login service such as OpenSSH with +GSSAPIAuthentication enabled, login authorization rules determine +whether a Kerberos principal is allowed to access a local account.

+

By default, a Kerberos principal is allowed access to an account if +its realm matches the default realm and its name matches the account +name. (For historical reasons, access is also granted by default if +the name has two components and the second component matches the +default realm; for instance, alice/ATHENA.MIT.EDU@ATHENA.MIT.EDU +is granted access to the alice account if ATHENA.MIT.EDU is +the default realm.)

+

The simplest way to control local access is using .k5login +files. To use these, place a .k5login file in the home directory +of each account listing the principal names which should have login +access to that account. If it is not desirable to use .k5login +files located in account home directories, the k5login_directory +relation in the [libdefaults] section can specify a directory +containing one file per account uname.

+

By default, if a .k5login file is present, it controls +authorization both positively and negatively–any principal name +contained in the file is granted access and any other principal name +is denied access, even if it would have had access if the .k5login +file didn’t exist. The k5login_authoritative relation in the +[libdefaults] section can be set to false to make .k5login +files provide positive authorization only.

+

The auth_to_local relation in the [realms] section for the +default realm can specify pattern-matching rules to control login +authorization. For example, the following configuration allows access +to principals from a different realm than the default realm:

+
[realms]
+    DEFAULT.REALM = {
+        # Allow access to principals from OTHER.REALM.
+        #
+        # [1:$1@$0] matches single-component principal names and creates
+        # a selection string containing the principal name and realm.
+        #
+        # (.*@OTHER\.REALM) matches against the selection string, so that
+        # only principals in OTHER.REALM are matched.
+        #
+        # s/@OTHER\.REALM$// removes the realm name, leaving behind the
+        # principal name as the account name.
+        auth_to_local = RULE:[1:$1@$0](.*@OTHER\.REALM)s/@OTHER\.REALM$//
+
+        # Also allow principals from the default realm.  Omit this line
+        # to only allow access to principals in OTHER.REALM.
+        auth_to_local = DEFAULT
+    }
+
+
+

The auth_to_local_names subsection of the [realms] section +for the default realm can specify explicit mappings from principal +names to local accounts. The key used in this subsection is the +principal name without realm, so it is only safe to use in a Kerberos +environment with a single realm or a tightly controlled set of realms. +An example use of auth_to_local_names might be:

+
[realms]
+    ATHENA.MIT.EDU = {
+        auth_to_local_names = {
+            # Careful, these match principals in any realm!
+            host/example.com = hostaccount
+            fred = localfred
+        }
+    }
+
+
+

Local authorization behavior can also be modified using plugin +modules; see Host-to-realm interface (hostrealm) for details.

+
+
+

Plugin module configuration

+

Many aspects of Kerberos behavior, such as client preauthentication +and KDC service location, can be modified through the use of plugin +modules. For most of these behaviors, you can use the [plugins] +section of krb5.conf to register third-party modules, and to switch +off registered or built-in modules.

+

A plugin module takes the form of a Unix shared object +(modname.so) or Windows DLL (modname.dll). If you have +installed a third-party plugin module and want to register it, you do +so using the module relation in the appropriate subsection of the +[plugins] section. The value for module must give the module name +and the path to the module, separated by a colon. The module name +will often be the same as the shared object’s name, but in unusual +cases (such as a shared object which implements multiple modules for +the same interface) it might not be. For example, to register a +client preauthentication module named mypreauth installed at +/path/to/mypreauth.so, you could write:

+
[plugins]
+    clpreauth = {
+        module = mypreauth:/path/to/mypreauth.so
+    }
+
+
+

Many of the pluggable behaviors in MIT krb5 contain built-in modules +which can be switched off. You can disable a built-in module (or one +you have registered) using the disable directive in the +appropriate subsection of the [plugins] section. For example, to +disable the use of .k5identity files to select credential caches, you +could write:

+
[plugins]
+    ccselect = {
+        disable = k5identity
+    }
+
+
+

If you want to disable multiple modules, specify the disable +directive multiple times, giving one module to disable each time.

+

Alternatively, you can explicitly specify which modules you want to be +enabled for that behavior using the enable_only directive. For +example, to make kadmind check password quality using only a +module you have registered, and no other mechanism, you could write:

+
[plugins]
+    pwqual = {
+        module = mymodule:/path/to/mymodule.so
+        enable_only = mymodule
+    }
+
+
+

Again, if you want to specify multiple modules, specify the +enable_only directive multiple times, giving one module to enable +each time.

+

Some Kerberos interfaces use different mechanisms to register plugin +modules.

+
+

KDC location modules

+

For historical reasons, modules to control how KDC servers are located +are registered simply by placing the shared object or DLL into the +“libkrb5” subdirectory of the krb5 plugin directory, which defaults to +LIBDIR/krb5/plugins. For example, Samba’s winbind krb5 +locator plugin would be registered by placing its shared object in +LIBDIR/krb5/plugins/libkrb5/winbind_krb5_locator.so.

+
+
+

GSSAPI mechanism modules

+

GSSAPI mechanism modules are registered using the file +SYSCONFDIR/gss/mech or configuration files in the +SYSCONFDIR/gss/mech.d directory with a .conf +suffix. Each line in these files has the form:

+
name  oid  pathname  [options]  <type>
+
+
+

Only the name, oid, and pathname are required. name is the +mechanism name, which may be used for debugging or logging purposes. +oid is the object identifier of the GSSAPI mechanism to be +registered. pathname is a path to the module shared object or DLL. +options (if present) are options provided to the plugin module, +surrounded in square brackets. type (if present) can be used to +indicate a special type of module. Currently the only special module +type is “interposer”, for a module designed to intercept calls to +other mechanisms.

+

If the environment variable GSS_MECH_CONFIG is set, its value is +used as the sole mechanism configuration filename.

+
+
+

Configuration profile modules

+

A configuration profile module replaces the information source for +krb5.conf itself. To use a profile module, begin krb5.conf +with the line:

+
module PATHNAME:STRING
+
+
+

where PATHNAME is a path to the module shared object or DLL, and +STRING is a string to provide to the module. The module will then +take over, and the rest of krb5.conf will be ignored.

+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/https.html b/krb5-1.21.3/doc/html/admin/https.html new file mode 100644 index 00000000..7047915b --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/https.html @@ -0,0 +1,193 @@ + + + + + + + + + HTTPS proxy configuration — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

HTTPS proxy configuration

+

In addition to being able to use UDP or TCP to communicate directly +with a KDC as is outlined in RFC4120, and with kpasswd services in a +similar fashion, the client libraries can attempt to use an HTTPS +proxy server to communicate with a KDC or kpasswd service, using the +protocol outlined in [MS-KKDCP].

+

Communicating with a KDC through an HTTPS proxy allows clients to +contact servers when network firewalls might otherwise prevent them +from doing so. The use of TLS also encrypts all traffic between the +clients and the KDC, preventing observers from conducting password +dictionary attacks or from observing the client and server principals +being authenticated, at additional computational cost to both clients +and servers.

+

An HTTPS proxy server is provided as a feature in some versions of +Microsoft Windows Server, and a WSGI implementation named kdcproxy +is available in the python package index.

+
+

Configuring the clients

+

To use an HTTPS proxy, a client host must trust the CA which issued +that proxy’s SSL certificate. If that CA’s certificate is not in the +system-wide default set of trusted certificates, configure the +following relation in the client host’s krb5.conf file in +the appropriate [realms] subsection:

+
http_anchors = FILE:/etc/krb5/cacert.pem
+
+
+

Adjust the pathname to match the path of the file which contains a +copy of the CA’s certificate. The http_anchors option is documented +more fully in krb5.conf.

+

Configure the client to access the KDC and kpasswd service by +specifying their locations in its krb5.conf file in the form +of HTTPS URLs for the proxy server:

+
kdc = https://server.fqdn/KdcProxy
+kpasswd_server = https://server.fqdn/KdcProxy
+
+
+

If the proxy and client are properly configured, client commands such +as kinit, kvno, and kpasswd should all function normally.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/index.html b/krb5-1.21.3/doc/html/admin/index.html new file mode 100644 index 00000000..0e2bf2f4 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/index.html @@ -0,0 +1,186 @@ + + + + + + + + + For administrators — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+ + +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/install.html b/krb5-1.21.3/doc/html/admin/install.html new file mode 100644 index 00000000..3c27a010 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/install.html @@ -0,0 +1,197 @@ + + + + + + + + + Installation guide — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+ + +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/install_appl_srv.html b/krb5-1.21.3/doc/html/admin/install_appl_srv.html new file mode 100644 index 00000000..14536e42 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/install_appl_srv.html @@ -0,0 +1,225 @@ + + + + + + + + + UNIX Application Servers — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

UNIX Application Servers

+

An application server is a host that provides one or more services +over the network. Application servers can be “secure” or “insecure.” +A “secure” host is set up to require authentication from every client +connecting to it. An “insecure” host will still provide Kerberos +authentication, but will also allow unauthenticated clients to +connect.

+

If you have Kerberos V5 installed on all of your client machines, MIT +recommends that you make your hosts secure, to take advantage of the +security that Kerberos authentication affords. However, if you have +some clients that do not have Kerberos V5 installed, you can run an +insecure server, and still take advantage of Kerberos V5’s single +sign-on capability.

+
+

The keytab file

+

All Kerberos server machines need a keytab file to authenticate to the +KDC. By default on UNIX-like systems this file is named DEFKTNAME. +The keytab file is an local copy of the host’s key. The keytab file +is a potential point of entry for a break-in, and if compromised, +would allow unrestricted access to its host. The keytab file should +be readable only by root, and should exist only on the machine’s local +disk. The file should not be part of any backup of the machine, +unless access to the backup data is secured as tightly as access to +the machine’s root password.

+

In order to generate a keytab for a host, the host must have a +principal in the Kerberos database. The procedure for adding hosts to +the database is described fully in Principals. (See +Create host keytabs for replica KDCs for a brief description.) The keytab is +generated by running kadmin and issuing the ktadd +command.

+

For example, to generate a keytab file to allow the host +trillium.mit.edu to authenticate for the services host, ftp, and +pop, the administrator joeadmin would issue the command (on +trillium.mit.edu):

+
trillium% kadmin
+Authenticating as principal root/admin@ATHENA.MIT.EDU with password.
+Password for root/admin@ATHENA.MIT.EDU:
+kadmin: ktadd host/trillium.mit.edu ftp/trillium.mit.edu pop/trillium.mit.edu
+Entry for principal host/trillium.mit.edu@ATHENA.MIT.EDU with kvno 3, encryption type aes256-cts-hmac-sha384-192 added to keytab FILE:/etc/krb5.keytab.
+kadmin: Entry for principal ftp/trillium.mit.edu@ATHENA.MIT.EDU with kvno 3, encryption type aes256-cts-hmac-sha384-192 added to keytab FILE:/etc/krb5.keytab.
+kadmin: Entry for principal pop/trillium.mit.edu@ATHENA.MIT.EDU with kvno 3, encryption type aes256-cts-hmac-sha384-192 added to keytab FILE:/etc/krb5.keytab.
+kadmin: quit
+trillium%
+
+
+

If you generate the keytab file on another host, you need to get a +copy of the keytab file onto the destination host (trillium, in +the above example) without sending it unencrypted over the network.

+
+
+

Some advice about secure hosts

+

Kerberos V5 can protect your host from certain types of break-ins, but +it is possible to install Kerberos V5 and still leave your host +vulnerable to attack. Obviously an installation guide is not the +place to try to include an exhaustive list of countermeasures for +every possible attack, but it is worth noting some of the larger holes +and how to close them.

+

We recommend that backups of secure machines exclude the keytab file +(DEFKTNAME). If this is not possible, the backups should at least be +done locally, rather than over a network, and the backup tapes should +be physically secured.

+

The keytab file and any programs run by root, including the Kerberos +V5 binaries, should be kept on local disk. The keytab file should be +readable only by root.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/install_clients.html b/krb5-1.21.3/doc/html/admin/install_clients.html new file mode 100644 index 00000000..928576e3 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/install_clients.html @@ -0,0 +1,207 @@ + + + + + + + + + Installing and configuring UNIX client machines — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Installing and configuring UNIX client machines

+

The Kerberized client programs include kinit, +klist, kdestroy, and kpasswd. All of +these programs are in the directory BINDIR.

+

You can often integrate Kerberos with the login system on client +machines, typically through the use of PAM. The details vary by +operating system, and should be covered in your operating system’s +documentation. If you do this, you will need to make sure your users +know to use their Kerberos passwords when they log in.

+

You will also need to educate your users to use the ticket management +programs kinit, klist, and kdestroy. If you do not have Kerberos +password changing integrated into the native password program (again, +typically through PAM), you will need to educate users to use kpasswd +in place of its non-Kerberos counterparts passwd.

+
+

Client machine configuration files

+

Each machine running Kerberos should have a krb5.conf file. +At a minimum, it should define a default_realm setting in +[libdefaults]. If you are not using DNS SRV records +(Hostnames for KDCs) or URI records (KDC Discovery), it must +also contain a [realms] section containing information for your +realm’s KDCs.

+

Consider setting rdns to false in order to reduce your dependence +on precisely correct DNS information for service hostnames. Turning +this flag off means that service hostnames will be canonicalized +through forward name resolution (which adds your domain name to +unqualified hostnames, and resolves CNAME records in DNS), but not +through reverse address lookup. The default value of this flag is +true for historical reasons only.

+

If you anticipate users frequently logging into remote hosts +(e.g., using ssh) using forwardable credentials, consider setting +forwardable to true so that users obtain forwardable tickets by +default. Otherwise users will need to use kinit -f to get +forwardable tickets.

+

Consider adjusting the ticket_lifetime setting to match the likely +length of sessions for your users. For instance, if most of your +users will be logging in for an eight-hour workday, you could set the +default to ten hours so that tickets obtained in the morning expire +shortly after the end of the workday. Users can still manually +request longer tickets when necessary, up to the maximum allowed by +each user’s principal record on the KDC.

+

If a client host may access services in different realms, it may be +useful to define a [domain_realm] mapping so that clients know +which hosts belong to which realms. However, if your clients and KDC +are running release 1.7 or later, it is also reasonable to leave this +section out on client machines and just define it in the KDC’s +krb5.conf.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/install_kdc.html b/krb5-1.21.3/doc/html/admin/install_kdc.html new file mode 100644 index 00000000..6f251913 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/install_kdc.html @@ -0,0 +1,653 @@ + + + + + + + + + Installing KDCs — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Installing KDCs

+

When setting up Kerberos in a production environment, it is best to +have multiple replica KDCs alongside with a primary KDC to ensure the +continued availability of the Kerberized services. Each KDC contains +a copy of the Kerberos database. The primary KDC contains the +writable copy of the realm database, which it replicates to the +replica KDCs at regular intervals. All database changes (such as +password changes) are made on the primary KDC. Replica KDCs provide +Kerberos ticket-granting services, but not database administration, +when the primary KDC is unavailable. MIT recommends that you install +all of your KDCs to be able to function as either the primary or one +of the replicas. This will enable you to easily switch your primary +KDC with one of the replicas if necessary (see +Switching primary and replica KDCs). This installation procedure is based +on that recommendation.

+
+

Warning

+
    +
  • The Kerberos system relies on the availability of correct time +information. Ensure that the primary and all replica KDCs have +properly synchronized clocks.

  • +
  • It is best to install and run KDCs on secured and dedicated +hardware with limited access. If your KDC is also a file +server, FTP server, Web server, or even just a client machine, +someone who obtained root access through a security hole in any +of those areas could potentially gain access to the Kerberos +database.

  • +
+
+
+

Install and configure the primary KDC

+

Install Kerberos either from the OS-provided packages or from the +source (See Building within a single tree).

+
+

Note

+

For the purpose of this document we will use the following +names:

+
kerberos.mit.edu    - primary KDC
+kerberos-1.mit.edu  - replica KDC
+ATHENA.MIT.EDU      - realm name
+.k5.ATHENA.MIT.EDU  - stash file
+admin/admin         - admin principal
+
+
+

See MIT Kerberos defaults for the default names and locations +of the relevant to this topic files. Adjust the names and +paths to your system environment.

+
+
+
+

Edit KDC configuration files

+

Modify the configuration files, krb5.conf and +kdc.conf, to reflect the correct information (such as +domain-realm mappings and Kerberos servers names) for your realm. +(See MIT Kerberos defaults for the recommended default locations for +these files).

+

Most of the tags in the configuration have default values that will +work well for most sites. There are some tags in the +krb5.conf file whose values must be specified, and this +section will explain those.

+

If the locations for these configuration files differs from the +default ones, set KRB5_CONFIG and KRB5_KDC_PROFILE environment +variables to point to the krb5.conf and kdc.conf respectively. For +example:

+
export KRB5_CONFIG=/yourdir/krb5.conf
+export KRB5_KDC_PROFILE=/yourdir/kdc.conf
+
+
+
+

krb5.conf

+

If you are not using DNS TXT records (see Mapping hostnames onto Kerberos realms), +you must specify the default_realm in the [libdefaults] +section. If you are not using DNS URI or SRV records (see +Hostnames for KDCs and KDC Discovery), you must include the +kdc tag for each realm in the [realms] section. To +communicate with the kadmin server in each realm, the admin_server +tag must be set in the +[realms] section.

+

An example krb5.conf file:

+
[libdefaults]
+    default_realm = ATHENA.MIT.EDU
+
+[realms]
+    ATHENA.MIT.EDU = {
+        kdc = kerberos.mit.edu
+        kdc = kerberos-1.mit.edu
+        admin_server = kerberos.mit.edu
+    }
+
+
+
+
+

kdc.conf

+

The kdc.conf file can be used to control the listening ports of the +KDC and kadmind, as well as realm-specific defaults, the database type +and location, and logging.

+

An example kdc.conf file:

+
[kdcdefaults]
+    kdc_listen = 88
+    kdc_tcp_listen = 88
+
+[realms]
+    ATHENA.MIT.EDU = {
+        kadmind_port = 749
+        max_life = 12h 0m 0s
+        max_renewable_life = 7d 0h 0m 0s
+        master_key_type = aes256-cts
+        supported_enctypes = aes256-cts:normal aes128-cts:normal
+        # If the default location does not suit your setup,
+        # explicitly configure the following values:
+        #    database_name = /var/krb5kdc/principal
+        #    key_stash_file = /var/krb5kdc/.k5.ATHENA.MIT.EDU
+        #    acl_file = /var/krb5kdc/kadm5.acl
+    }
+
+[logging]
+    # By default, the KDC and kadmind will log output using
+    # syslog.  You can instead send log output to files like this:
+    kdc = FILE:/var/log/krb5kdc.log
+    admin_server = FILE:/var/log/kadmin.log
+    default = FILE:/var/log/krb5lib.log
+
+
+

Replace ATHENA.MIT.EDU and kerberos.mit.edu with the name of +your Kerberos realm and server respectively.

+
+

Note

+

You have to have write permission on the target directories +(these directories must exist) used by database_name, +key_stash_file, and acl_file.

+
+
+
+
+

Create the KDC database

+

You will use the kdb5_util command on the primary KDC to +create the Kerberos database and the optional stash file.

+
+

Note

+

If you choose not to install a stash file, the KDC will +prompt you for the master key each time it starts up. This +means that the KDC will not be able to start automatically, +such as after a system reboot.

+
+

kdb5_util will prompt you for the master password for the +Kerberos database. This password can be any string. A good password +is one you can remember, but that no one else can guess. Examples of +bad passwords are words that can be found in a dictionary, any common +or popular name, especially a famous person (or cartoon character), +your username in any form (e.g., forward, backward, repeated twice, +etc.), and any of the sample passwords that appear in this manual. +One example of a password which might be good if it did not appear in +this manual is “MITiys4K5!”, which represents the sentence “MIT is +your source for Kerberos 5!” (It’s the first letter of each word, +substituting the numeral “4” for the word “for”, and includes the +punctuation mark at the end.)

+

The following is an example of how to create a Kerberos database and +stash file on the primary KDC, using the kdb5_util command. +Replace ATHENA.MIT.EDU with the name of your Kerberos realm:

+
shell% kdb5_util create -r ATHENA.MIT.EDU -s
+
+Initializing database '/usr/local/var/krb5kdc/principal' for realm 'ATHENA.MIT.EDU',
+master key name 'K/M@ATHENA.MIT.EDU'
+You will be prompted for the database Master Password.
+It is important that you NOT FORGET this password.
+Enter KDC database master key:  <= Type the master password.
+Re-enter KDC database master key to verify:  <= Type it again.
+shell%
+
+
+

This will create five files in LOCALSTATEDIR/krb5kdc (or at the locations specified +in kdc.conf):

+
    +
  • two Kerberos database files, principal, and principal.ok

  • +
  • the Kerberos administrative database file, principal.kadm5

  • +
  • the administrative database lock file, principal.kadm5.lock

  • +
  • the stash file, in this example .k5.ATHENA.MIT.EDU. If you do +not want a stash file, run the above command without the -s +option.

  • +
+

For more information on administrating Kerberos database see +Operations on the Kerberos database.

+
+
+

Add administrators to the ACL file

+

Next, you need create an Access Control List (ACL) file and put the +Kerberos principal of at least one of the administrators into it. +This file is used by the kadmind daemon to control which +principals may view and make privileged modifications to the Kerberos +database files. The ACL filename is determined by the acl_file +variable in kdc.conf; the default is LOCALSTATEDIR/krb5kdc/kadm5.acl.

+

For more information on Kerberos ACL file see kadm5.acl.

+
+
+

Add administrators to the Kerberos database

+

Next you need to add administrative principals (i.e., principals who +are allowed to administer Kerberos database) to the Kerberos database. +You must add at least one principal now to allow communication +between the Kerberos administration daemon kadmind and the kadmin +program over the network for further administration. To do this, use +the kadmin.local utility on the primary KDC. kadmin.local is designed +to be run on the primary KDC host without using Kerberos +authentication to an admin server; instead, it must have read and +write access to the Kerberos database on the local filesystem.

+

The administrative principals you create should be the ones you added +to the ACL file (see Add administrators to the ACL file).

+

In the following example, the administrative principal admin/admin +is created:

+
shell% kadmin.local
+
+kadmin.local: addprinc admin/admin@ATHENA.MIT.EDU
+
+No policy specified for "admin/admin@ATHENA.MIT.EDU";
+assigning "default".
+Enter password for principal admin/admin@ATHENA.MIT.EDU:  <= Enter a password.
+Re-enter password for principal admin/admin@ATHENA.MIT.EDU:  <= Type it again.
+Principal "admin/admin@ATHENA.MIT.EDU" created.
+kadmin.local:
+
+
+
+
+

Start the Kerberos daemons on the primary KDC

+

At this point, you are ready to start the Kerberos KDC +(krb5kdc) and administrative daemons on the primary KDC. To +do so, type:

+
shell% krb5kdc
+shell% kadmind
+
+
+

Each server daemon will fork and run in the background.

+
+

Note

+

Assuming you want these daemons to start up automatically at +boot time, you can add them to the KDC’s /etc/rc or +/etc/inittab file. You need to have a +stash file in order to do this.

+
+

You can verify that they started properly by checking for their +startup messages in the logging locations you defined in +krb5.conf (see [logging]). For example:

+
shell% tail /var/log/krb5kdc.log
+Dec 02 12:35:47 beeblebrox krb5kdc[3187](info): commencing operation
+shell% tail /var/log/kadmin.log
+Dec 02 12:35:52 beeblebrox kadmind[3189](info): starting
+
+
+

Any errors the daemons encounter while starting will also be listed in +the logging output.

+

As an additional verification, check if kinit succeeds +against the principals that you have created on the previous step +(Add administrators to the Kerberos database). Run:

+
shell% kinit admin/admin@ATHENA.MIT.EDU
+
+
+
+
+

Install the replica KDCs

+

You are now ready to start configuring the replica KDCs.

+
+

Note

+

Assuming you are setting the KDCs up so that you can easily +switch the primary KDC with one of the replicas, you should +perform each of these steps on the primary KDC as well as +the replica KDCs, unless these instructions specify +otherwise.

+
+
+

Create host keytabs for replica KDCs

+

Each KDC needs a host key in the Kerberos database. These keys +are used for mutual authentication when propagating the database dump +file from the primary KDC to the secondary KDC servers.

+

On the primary KDC, connect to administrative interface and create the +host principal for each of the KDCs’ host services. For example, +if the primary KDC were called kerberos.mit.edu, and you had a +replica KDC named kerberos-1.mit.edu, you would type the +following:

+
shell% kadmin
+kadmin: addprinc -randkey host/kerberos.mit.edu
+No policy specified for "host/kerberos.mit.edu@ATHENA.MIT.EDU"; assigning "default"
+Principal "host/kerberos.mit.edu@ATHENA.MIT.EDU" created.
+
+kadmin: addprinc -randkey host/kerberos-1.mit.edu
+No policy specified for "host/kerberos-1.mit.edu@ATHENA.MIT.EDU"; assigning "default"
+Principal "host/kerberos-1.mit.edu@ATHENA.MIT.EDU" created.
+
+
+

It is not strictly necessary to have the primary KDC server in the +Kerberos database, but it can be handy if you want to be able to swap +the primary KDC with one of the replicas.

+

Next, extract host random keys for all participating KDCs and +store them in each host’s default keytab file. Ideally, you should +extract each keytab locally on its own KDC. If this is not feasible, +you should use an encrypted session to send them across the network. +To extract a keytab directly on a replica KDC called +kerberos-1.mit.edu, you would execute the following command:

+
kadmin: ktadd host/kerberos-1.mit.edu
+Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption
+    type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
+Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption
+    type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
+Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption
+    type aes256-cts-hmac-sha384-192 added to keytab FILE:/etc/krb5.keytab.
+Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption
+    type arcfour-hmac added to keytab FILE:/etc/krb5.keytab.
+
+
+

If you are instead extracting a keytab for the replica KDC called +kerberos-1.mit.edu on the primary KDC, you should use a dedicated +temporary keytab file for that machine’s keytab:

+
kadmin: ktadd -k /tmp/kerberos-1.keytab host/kerberos-1.mit.edu
+Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption
+    type aes256-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
+Entry for principal host/kerberos-1.mit.edu with kvno 2, encryption
+    type aes128-cts-hmac-sha1-96 added to keytab FILE:/etc/krb5.keytab.
+
+
+

The file /tmp/kerberos-1.keytab can then be installed as +/etc/krb5.keytab on the host kerberos-1.mit.edu.

+
+
+

Configure replica KDCs

+

Database propagation copies the contents of the primary’s database, +but does not propagate configuration files, stash files, or the kadm5 +ACL file. The following files must be copied by hand to each replica +(see MIT Kerberos defaults for the default locations for these files):

+
    +
  • krb5.conf

  • +
  • kdc.conf

  • +
  • kadm5.acl

  • +
  • master key stash file

  • +
+

Move the copied files into their appropriate directories, exactly as +on the primary KDC. kadm5.acl is only needed to allow a replica to +swap with the primary KDC.

+

The database is propagated from the primary KDC to the replica KDCs +via the kpropd daemon. You must explicitly specify the +principals which are allowed to provide Kerberos dump updates on the +replica machine with a new database. Create a file named kpropd.acl +in the KDC state directory containing the host principals for each +of the KDCs:

+
host/kerberos.mit.edu@ATHENA.MIT.EDU
+host/kerberos-1.mit.edu@ATHENA.MIT.EDU
+
+
+
+

Note

+

If you expect that the primary and replica KDCs will be +switched at some point of time, list the host principals +from all participating KDC servers in kpropd.acl files on +all of the KDCs. Otherwise, you only need to list the +primary KDC’s host principal in the kpropd.acl files of the +replica KDCs.

+
+

Then, add the following line to /etc/inetd.conf on each KDC +(adjust the path to kpropd):

+
krb5_prop stream tcp nowait root /usr/local/sbin/kpropd kpropd
+
+
+

You also need to add the following line to /etc/services on each +KDC, if it is not already present (assuming that the default port is +used):

+
krb5_prop       754/tcp               # Kerberos replica propagation
+
+
+

Restart inetd daemon.

+

Alternatively, start kpropd as a stand-alone daemon. This is +required when incremental propagation is enabled.

+

Now that the replica KDC is able to accept database propagation, +you’ll need to propagate the database from the primary server.

+

NOTE: Do not start the replica KDC yet; you still do not have a copy +of the primary’s database.

+
+
+

Propagate the database to each replica KDC

+

First, create a dump file of the database on the primary KDC, as +follows:

+
shell% kdb5_util dump /usr/local/var/krb5kdc/replica_datatrans
+
+
+

Then, manually propagate the database to each replica KDC, as in the +following example:

+
shell% kprop -f /usr/local/var/krb5kdc/replica_datatrans kerberos-1.mit.edu
+
+Database propagation to kerberos-1.mit.edu: SUCCEEDED
+
+
+

You will need a script to dump and propagate the database. The +following is an example of a Bourne shell script that will do this.

+
+

Note

+

Remember that you need to replace /usr/local/var/krb5kdc +with the name of the KDC state directory.

+
+
#!/bin/sh
+
+kdclist = "kerberos-1.mit.edu kerberos-2.mit.edu"
+
+kdb5_util dump /usr/local/var/krb5kdc/replica_datatrans
+
+for kdc in $kdclist
+do
+    kprop -f /usr/local/var/krb5kdc/replica_datatrans $kdc
+done
+
+
+

You will need to set up a cron job to run this script at the intervals +you decided on earlier (see Database propagation).

+

Now that the replica KDC has a copy of the Kerberos database, you can +start the krb5kdc daemon:

+
shell% krb5kdc
+
+
+

As with the primary KDC, you will probably want to add this command to +the KDCs’ /etc/rc or /etc/inittab files, so they will start +the krb5kdc daemon automatically at boot time.

+
+

Propagation failed?

+

You may encounter the following error messages. For a more detailed +discussion on possible causes and solutions click on the error link +to be redirected to Troubleshooting section.

+
    +
  1. kprop: No route to host while connecting to server

  2. +
  3. kprop: Connection refused while connecting to server

  4. +
  5. kprop: Server rejected authentication (during sendauth exchange) while authenticating to server

  6. +
+
+
+
+
+

Add Kerberos principals to the database

+

Once your KDCs are set up and running, you are ready to use +kadmin to load principals for your users, hosts, and other +services into the Kerberos database. This procedure is described +fully in Principals.

+

You may occasionally want to use one of your replica KDCs as the +primary. This might happen if you are upgrading the primary KDC, or +if your primary KDC has a disk crash. See the following section for +the instructions.

+
+
+

Switching primary and replica KDCs

+

You may occasionally want to use one of your replica KDCs as the +primary. This might happen if you are upgrading the primary KDC, or +if your primary KDC has a disk crash.

+

Assuming you have configured all of your KDCs to be able to function +as either the primary KDC or a replica KDC (as this document +recommends), all you need to do to make the changeover is:

+

If the primary KDC is still running, do the following on the old +primary KDC:

+
    +
  1. Kill the kadmind process.

  2. +
  3. Disable the cron job that propagates the database.

  4. +
  5. Run your database propagation script manually, to ensure that the +replicas all have the latest copy of the database (see +Propagate the database to each replica KDC).

  6. +
+

On the new primary KDC:

+
    +
  1. Start the kadmind daemon (see Start the Kerberos daemons on the primary KDC).

  2. +
  3. Set up the cron job to propagate the database (see +Propagate the database to each replica KDC).

  4. +
  5. Switch the CNAMEs of the old and new primary KDCs. If you can’t do +this, you’ll need to change the krb5.conf file on every +client machine in your Kerberos realm.

  6. +
+
+
+

Incremental database propagation

+

If you expect your Kerberos database to become large, you may wish to +set up incremental propagation to replica KDCs. See +Incremental database propagation for details.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/lockout.html b/krb5-1.21.3/doc/html/admin/lockout.html new file mode 100644 index 00000000..8f6d4507 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/lockout.html @@ -0,0 +1,293 @@ + + + + + + + + + Account lockout — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Account lockout

+

As of release 1.8, the KDC can be configured to lock out principals +after a number of failed authentication attempts within a period of +time. Account lockout can make it more difficult to attack a +principal’s password by brute force, but also makes it easy for an +attacker to deny access to a principal.

+
+

Configuring account lockout

+

Account lockout only works for principals with the ++requires_preauth flag set. Without this flag, the KDC cannot +know whether or not a client successfully decrypted the ticket it +issued. It is also important to set the -allow_svr flag on a +principal to protect its password from an off-line dictionary attack +through a TGS request. You can set these flags on a principal with +kadmin as follows:

+
kadmin: modprinc +requires_preauth -allow_svr PRINCNAME
+
+
+

Account lockout parameters are configured via policy objects. There may be an existing policy associated with user +principals (such as the “default” policy), or you may need to create a +new one and associate it with each user principal.

+

The policy parameters related to account lockout are:

+ +

Here is an example of setting these parameters on a new policy and +associating it with a principal:

+
kadmin: addpol -maxfailure 10 -failurecountinterval 180
+    -lockoutduration 60 lockout_policy
+kadmin: modprinc -policy lockout_policy PRINCNAME
+
+
+
+
+

Testing account lockout

+

To test that account lockout is working, try authenticating as the +principal (hopefully not one that might be in use) multiple times with +the wrong password. For instance, if maxfailure is set to 2, you +might see:

+
$ kinit user
+Password for user@KRBTEST.COM:
+kinit: Password incorrect while getting initial credentials
+$ kinit user
+Password for user@KRBTEST.COM:
+kinit: Password incorrect while getting initial credentials
+$ kinit user
+kinit: Client's credentials have been revoked while getting initial credentials
+
+
+
+
+

Account lockout principal state

+

A principal entry keeps three pieces of state related to account +lockout:

+
    +
  • The time of last successful authentication

  • +
  • The time of last failed authentication

  • +
  • A counter of failed attempts

  • +
+

The time of last successful authentication is not actually needed for +the account lockout system to function, but may be of administrative +interest. These fields can be observed with the getprinc kadmin +command. For example:

+
kadmin: getprinc user
+Principal: user@KRBTEST.COM
+...
+Last successful authentication: [never]
+Last failed authentication: Mon Dec 03 12:30:33 EST 2012
+Failed password attempts: 2
+...
+
+
+

A principal which has been locked out can be administratively unlocked +with the -unlock option to the modprinc kadmin command:

+
kadmin: modprinc -unlock PRINCNAME
+
+
+

This command will reset the number of failed attempts to 0.

+
+
+

KDC replication and account lockout

+

The account lockout state of a principal is not replicated by either +traditional kprop or incremental propagation. Because of +this, the number of attempts an attacker can make within a time period +is multiplied by the number of KDCs. For instance, if the +maxfailure parameter on a policy is 10 and there are four KDCs in +the environment (a primary and three replicas), an attacker could make +as many as 40 attempts before the principal is locked out on all four +KDCs.

+

An administrative unlock is propagated from the primary to the replica +KDCs during the next propagation. Propagation of an administrative +unlock will cause the counter of failed attempts on each replica to +reset to 1 on the next failure.

+

If a KDC environment uses a replication strategy other than kprop or +incremental propagation, such as the LDAP KDB module with multi-master +LDAP replication, then account lockout state may be replicated between +KDCs and the concerns of this section may not apply.

+
+
+

KDC performance and account lockout

+

In order to fully track account lockout state, the KDC must write to +the the database on each successful and failed authentication. +Writing to the database is generally more expensive than reading from +it, so these writes may have a significant impact on KDC performance. +As of release 1.9, it is possible to turn off account lockout state +tracking in order to improve performance, by setting the +disable_last_success and disable_lockout variables in the +database module subsection of kdc.conf. For example:

+
[dbmodules]
+    DB = {
+        disable_last_success = true
+        disable_lockout = true
+    }
+
+
+

Of the two variables, setting disable_last_success will usually +have the largest positive impact on performance, and will still allow +account lockout policies to operate. However, it will make it +impossible to observe the last successful authentication time with +kadmin.

+
+
+

KDC setup and account lockout

+

To update the account lockout state on principals, the KDC must be +able to write to the principal database. For the DB2 module, no +special setup is required. For the LDAP module, the KDC DN must be +granted write access to the principal objects. If the KDC DN has only +read access, account lockout will not function.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/otp.html b/krb5-1.21.3/doc/html/admin/otp.html new file mode 100644 index 00000000..042a0d03 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/otp.html @@ -0,0 +1,241 @@ + + + + + + + + + OTP Preauthentication — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

OTP Preauthentication

+

OTP is a preauthentication mechanism for Kerberos 5 which uses One +Time Passwords (OTP) to authenticate the client to the KDC. The OTP +is passed to the KDC over an encrypted FAST channel in clear-text. +The KDC uses the password along with per-user configuration to proxy +the request to a third-party RADIUS system. This enables +out-of-the-box compatibility with a large number of already widely +deployed proprietary systems.

+

Additionally, our implementation of the OTP system allows for the +passing of RADIUS requests over a UNIX domain stream socket. This +permits the use of a local companion daemon which can handle the +details of authentication.

+
+

Defining token types

+

Token types are defined in either krb5.conf or +kdc.conf according to the following format:

+
[otp]
+    <name> = {
+        server = <host:port or filename> (default: see below)
+        secret = <filename>
+        timeout = <integer> (default: 5 [seconds])
+        retries = <integer> (default: 3)
+        strip_realm = <boolean> (default: true)
+        indicator = <string> (default: none)
+    }
+
+
+

If the server field begins with ‘/’, it will be interpreted as a UNIX +socket. Otherwise, it is assumed to be in the format host:port. When +a UNIX domain socket is specified, the secret field is optional and an +empty secret is used by default. If the server field is not +specified, it defaults to RUNSTATEDIR/krb5kdc/<name>.socket.

+

When forwarding the request over RADIUS, by default the principal is +used in the User-Name attribute of the RADIUS packet. The strip_realm +parameter controls whether the principal is forwarded with or without +the realm portion.

+

If an indicator field is present, tickets issued using this token type +will be annotated with the specified authentication indicator (see +Authentication indicators). This key may be specified multiple times to +add multiple indicators.

+
+
+

The default token type

+

A default token type is used internally when no token type is specified for a +given user. It is defined as follows:

+
[otp]
+    DEFAULT = {
+        strip_realm = false
+    }
+
+
+

The administrator may override the internal DEFAULT token type +simply by defining a configuration with the same name.

+
+
+

Token instance configuration

+

To enable OTP for a client principal, the administrator must define +the otp string attribute for that principal. (See +set_string.) The otp user string is a JSON string of the +format:

+
[{
+    "type": <string>,
+    "username": <string>,
+    "indicators": [<string>, ...]
+ }, ...]
+
+
+

This is an array of token objects. Both fields of token objects are +optional. The type field names the token type of this token; if +not specified, it defaults to DEFAULT. The username field +specifies the value to be sent in the User-Name RADIUS attribute. If +not specified, the principal name is sent, with or without realm as +defined in the token type. The indicators field specifies a list +of authentication indicators to annotate tickets with, overriding any +indicators specified in the token type.

+

For ease of configuration, an empty array ([]) is treated as +equivalent to one DEFAULT token ([{}]).

+
+
+

Other considerations

+
    +
  1. FAST is required for OTP to work.

  2. +
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/pkinit.html b/krb5-1.21.3/doc/html/admin/pkinit.html new file mode 100644 index 00000000..40791a2e --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/pkinit.html @@ -0,0 +1,482 @@ + + + + + + + + + PKINIT configuration — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

PKINIT configuration

+

PKINIT is a preauthentication mechanism for Kerberos 5 which uses +X.509 certificates to authenticate the KDC to clients and vice versa. +PKINIT can also be used to enable anonymity support, allowing clients +to communicate securely with the KDC or with application servers +without authenticating as a particular client principal.

+
+

Creating certificates

+

PKINIT requires an X.509 certificate for the KDC and one for each +client principal which will authenticate using PKINIT. For anonymous +PKINIT, a KDC certificate is required, but client certificates are +not. A commercially issued server certificate can be used for the KDC +certificate, but generally cannot be used for client certificates.

+

The instruction in this section describe how to establish a +certificate authority and create standard PKINIT certificates. Skip +this section if you are using a commercially issued server certificate +as the KDC certificate for anonymous PKINIT, or if you are configuring +a client to use an Active Directory KDC.

+
+

Generating a certificate authority certificate

+

You can establish a new certificate authority (CA) for use with a +PKINIT deployment with the commands:

+
openssl genrsa -out cakey.pem 2048
+openssl req -key cakey.pem -new -x509 -out cacert.pem -days 3650
+
+
+

The second command will ask for the values of several certificate +fields. These fields can be set to any values. You can adjust the +expiration time of the CA certificate by changing the number after +-days. Since the CA certificate must be deployed to client +machines each time it changes, it should normally have an expiration +time far in the future; however, expiration times after 2037 may cause +interoperability issues in rare circumstances.

+

The result of these commands will be two files, cakey.pem and +cacert.pem. cakey.pem will contain a 2048-bit RSA private key, which +must be carefully protected. cacert.pem will contain the CA +certificate, which must be placed in the filesystems of the KDC and +each client host. cakey.pem will be required to create KDC and client +certificates.

+
+
+

Generating a KDC certificate

+

A KDC certificate for use with PKINIT is required to have some unusual +fields, which makes generating them with OpenSSL somewhat complicated. +First, you will need a file containing the following:

+
[kdc_cert]
+basicConstraints=CA:FALSE
+keyUsage=nonRepudiation,digitalSignature,keyEncipherment,keyAgreement
+extendedKeyUsage=1.3.6.1.5.2.3.5
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+issuerAltName=issuer:copy
+subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name
+
+[kdc_princ_name]
+realm=EXP:0,GeneralString:${ENV::REALM}
+principal_name=EXP:1,SEQUENCE:kdc_principal_seq
+
+[kdc_principal_seq]
+name_type=EXP:0,INTEGER:2
+name_string=EXP:1,SEQUENCE:kdc_principals
+
+[kdc_principals]
+princ1=GeneralString:krbtgt
+princ2=GeneralString:${ENV::REALM}
+
+
+

If the above contents are placed in extensions.kdc, you can generate +and sign a KDC certificate with the following commands:

+
openssl genrsa -out kdckey.pem 2048
+openssl req -new -out kdc.req -key kdckey.pem
+env REALM=YOUR_REALMNAME openssl x509 -req -in kdc.req \
+    -CAkey cakey.pem -CA cacert.pem -out kdc.pem -days 365 \
+    -extfile extensions.kdc -extensions kdc_cert -CAcreateserial
+rm kdc.req
+
+
+

The second command will ask for the values of certificate fields, +which can be set to any values. In the third command, substitute your +KDC’s realm name for YOUR_REALMNAME. You can adjust the certificate’s +expiration date by changing the number after -days. Remember to +create a new KDC certificate before the old one expires.

+

The result of this operation will be in two files, kdckey.pem and +kdc.pem. Both files must be placed in the KDC’s filesystem. +kdckey.pem, which contains the KDC’s private key, must be carefully +protected.

+

If you examine the KDC certificate with openssl x509 -in kdc.pem +-text -noout, OpenSSL will not know how to display the KDC principal +name in the Subject Alternative Name extension, so it will appear as +othername:<unsupported>. This is normal and does not mean +anything is wrong with the KDC certificate.

+
+
+

Generating client certificates

+

PKINIT client certificates also must have some unusual certificate +fields. To generate a client certificate with OpenSSL for a +single-component principal name, you will need an extensions file +(different from the KDC extensions file above) containing:

+
[client_cert]
+basicConstraints=CA:FALSE
+keyUsage=digitalSignature,keyEncipherment,keyAgreement
+extendedKeyUsage=1.3.6.1.5.2.3.4
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer
+issuerAltName=issuer:copy
+subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:princ_name
+
+[princ_name]
+realm=EXP:0,GeneralString:${ENV::REALM}
+principal_name=EXP:1,SEQUENCE:principal_seq
+
+[principal_seq]
+name_type=EXP:0,INTEGER:1
+name_string=EXP:1,SEQUENCE:principals
+
+[principals]
+princ1=GeneralString:${ENV::CLIENT}
+
+
+

If the above contents are placed in extensions.client, you can +generate and sign a client certificate with the following commands:

+
openssl genrsa -out clientkey.pem 2048
+openssl req -new -key clientkey.pem -out client.req
+env REALM=YOUR_REALMNAME CLIENT=YOUR_PRINCNAME openssl x509 \
+    -CAkey cakey.pem -CA cacert.pem -req -in client.req \
+    -extensions client_cert -extfile extensions.client \
+    -days 365 -out client.pem
+rm client.req
+
+
+

Normally, the first two commands should be run on the client host, and +the resulting client.req file transferred to the certificate authority +host for the third command. As in the previous steps, the second +command will ask for the values of certificate fields, which can be +set to any values. In the third command, substitute your realm’s name +for YOUR_REALMNAME and the client’s principal name (without realm) for +YOUR_PRINCNAME. You can adjust the certificate’s expiration date by +changing the number after -days.

+

The result of this operation will be two files, clientkey.pem and +client.pem. Both files must be present on the client’s host; +clientkey.pem, which contains the client’s private key, must be +protected from access by others.

+

As in the KDC certificate, OpenSSL will display the client principal +name as othername:<unsupported> in the Subject Alternative Name +extension of a PKINIT client certificate.

+

If the client principal name contains more than one component +(e.g. host/example.com@REALM), the [principals] section of +extensions.client must be altered to contain multiple entries. +(Simply setting CLIENT to host/example.com would generate a +certificate for host\/example.com@REALM which would not match the +multi-component principal name.) For a two-component principal, the +section should read:

+
[principals]
+princ1=GeneralString:${ENV::CLIENT1}
+princ2=GeneralString:${ENV::CLIENT2}
+
+
+

The environment variables CLIENT1 and CLIENT2 must then be set +to the first and second components when running openssl x509.

+
+
+
+

Configuring the KDC

+

The KDC must have filesystem access to the KDC certificate (kdc.pem) +and the KDC private key (kdckey.pem). Configure the following +relation in the KDC’s kdc.conf file, either in the +[kdcdefaults] section or in a [realms] subsection (with +appropriate pathnames):

+
pkinit_identity = FILE:/var/lib/krb5kdc/kdc.pem,/var/lib/krb5kdc/kdckey.pem
+
+
+

If any clients will authenticate using regular (as opposed to +anonymous) PKINIT, the KDC must also have filesystem access to the CA +certificate (cacert.pem), and the following configuration (with the +appropriate pathname):

+
pkinit_anchors = FILE:/var/lib/krb5kdc/cacert.pem
+
+
+

Because of the larger size of requests and responses using PKINIT, you +may also need to allow TCP access to the KDC:

+
kdc_tcp_listen = 88
+
+
+

Restart the krb5kdc daemon to pick up the configuration +changes.

+

The principal entry for each PKINIT-using client must be configured to +require preauthentication. Ensure this with the command:

+
kadmin -q 'modprinc +requires_preauth YOUR_PRINCNAME'
+
+
+

Starting with release 1.12, it is possible to remove the long-term +keys of a principal entry, which can save some space in the database +and help to clarify some PKINIT-related error conditions by not asking +for a password:

+
kadmin -q 'purgekeys -all YOUR_PRINCNAME'
+
+
+

These principal options can also be specified at principal creation +time as follows:

+
kadmin -q 'add_principal +requires_preauth -nokey YOUR_PRINCNAME'
+
+
+

By default, the KDC requires PKINIT client certificates to have the +standard Extended Key Usage and Subject Alternative Name attributes +for PKINIT. Starting in release 1.16, it is possible to authorize +client certificates based on the subject or other criteria instead of +the standard PKINIT Subject Alternative Name, by setting the +pkinit_cert_match string attribute on each client principal entry. +For example:

+
kadmin set_string user@REALM pkinit_cert_match "<SUBJECT>CN=user@REALM$"
+
+
+

The pkinit_cert_match string attribute follows the syntax used by +the krb5.conf pkinit_cert_match relation. To allow the +use of non-PKINIT client certificates, it will also be necessary to +disable key usage checking using the pkinit_eku_checking relation; +for example:

+
[kdcdefaults]
+    pkinit_eku_checking = none
+
+
+
+
+

Configuring the clients

+

Client hosts must be configured to trust the issuing authority for the +KDC certificate. For a newly established certificate authority, the +client host must have filesystem access to the CA certificate +(cacert.pem) and the following relation in krb5.conf in the +appropriate [realms] subsection (with appropriate pathnames):

+
pkinit_anchors = FILE:/etc/krb5/cacert.pem
+
+
+

If the KDC certificate is a commercially issued server certificate, +the issuing certificate is most likely included in a system directory. +You can specify it by filename as above, or specify the whole +directory like so:

+
pkinit_anchors = DIR:/etc/ssl/certs
+
+
+

A commercially issued server certificate will usually not have the +standard PKINIT principal name or Extended Key Usage extensions, so +the following additional configuration is required:

+
pkinit_eku_checking = kpServerAuth
+pkinit_kdc_hostname = hostname.of.kdc.certificate
+
+
+

Multiple pkinit_kdc_hostname relations can be configured to +recognize multiple KDC certificates. If the KDC is an Active +Directory domain controller, setting pkinit_kdc_hostname is +necessary, but it should not be necessary to set +pkinit_eku_checking.

+

To perform regular (as opposed to anonymous) PKINIT authentication, a +client host must have filesystem access to a client certificate +(client.pem), and the corresponding private key (clientkey.pem). +Configure the following relations in the client host’s +krb5.conf file in the appropriate [realms] subsection +(with appropriate pathnames):

+
pkinit_identities = FILE:/etc/krb5/client.pem,/etc/krb5/clientkey.pem
+
+
+

If the KDC and client are properly configured, it should now be +possible to run kinit username without entering a password.

+
+
+

Anonymous PKINIT

+

Anonymity support in Kerberos allows a client to obtain a ticket +without authenticating as any particular principal. Such a ticket can +be used as a FAST armor ticket, or to securely communicate with an +application server anonymously.

+

To configure anonymity support, you must generate or otherwise procure +a KDC certificate and configure the KDC host, but you do not need to +generate any client certificates. On the KDC, you must set the +pkinit_identity variable to provide the KDC certificate, but do +not need to set the pkinit_anchors variable or store the issuing +certificate if you won’t have any client certificates to verify. On +client hosts, you must set the pkinit_anchors variable (and +possibly pkinit_kdc_hostname and pkinit_eku_checking) in order +to trust the issuing authority for the KDC certificate, but do not +need to set the pkinit_identities variable.

+

Anonymity support is not enabled by default. To enable it, you must +create the principal WELLKNOWN/ANONYMOUS using the command:

+
kadmin -q 'addprinc -randkey WELLKNOWN/ANONYMOUS'
+
+
+

Some Kerberos deployments include application servers which lack +proper access control, and grant some level of access to any user who +can authenticate. In such an environment, enabling anonymity support +on the KDC would present a security issue. If you need to enable +anonymity support for TGTs (for use as FAST armor tickets) without +enabling anonymous authentication to application servers, you can set +the variable restrict_anonymous_to_tgt to true in the +appropriate [realms] subsection of the KDC’s +kdc.conf file.

+

To obtain anonymous credentials on a client, run kinit -n, or +kinit -n @REALMNAME to specify a realm. The resulting tickets +will have the client name WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS.

+
+
+

Freshness tokens

+

Freshness tokens can ensure that the client has recently had access to +its certificate private key. If freshness tokens are not required by +the KDC, a client program with temporary possession of the private key +can compose requests for future timestamps and use them later.

+

In release 1.17 and later, freshness tokens are supported by the +client and are sent by the KDC when the client indicates support for +them. Because not all clients support freshness tokens yet, they are +not required by default. To check if freshness tokens are supported +by a realm’s clients, look in the KDC logs for the lines:

+
PKINIT: freshness token received from <client principal>
+PKINIT: no freshness token received from <client principal>
+
+
+

To require freshness tokens for all clients in a realm (except for +clients authenticating anonymously), set the +pkinit_require_freshness variable to true in the appropriate +[realms] subsection of the KDC’s kdc.conf file. To +test that this option is in effect, run kinit -X disable_freshness +and verify that authentication is unsuccessful.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/princ_dns.html b/krb5-1.21.3/doc/html/admin/princ_dns.html new file mode 100644 index 00000000..845f788e --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/princ_dns.html @@ -0,0 +1,268 @@ + + + + + + + + + Principal names and DNS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Principal names and DNS

+

Kerberos clients can do DNS lookups to canonicalize service principal +names. This can cause difficulties when setting up Kerberos +application servers, especially when the client’s name for the service +is different from what the service thinks its name is.

+
+

Service principal names

+

A frequently used kind of principal name is the host-based service +principal name. This kind of principal name has two components: a +service name and a hostname. For example, imap/imap.example.com +is the principal name of the “imap” service on the host +“imap.example.com”. Other possible service names for the first +component include “host” (remote login services such as ssh), “HTTP”, +and “nfs” (Network File System).

+

Service administrators often publish well-known hostname aliases that +they would prefer users to use instead of the canonical name of the +service host. This gives service administrators more flexibility in +deploying services. For example, a shell login server might be named +“long-vanity-hostname.example.com”, but users will naturally prefer to +type something like “login.example.com”. Hostname aliases also allow +for administrators to set up load balancing for some sorts of services +based on rotating CNAME records in DNS.

+
+
+

Service principal canonicalization

+

In the MIT krb5 client library, canonicalization of host-based service +principals is controlled by the dns_canonicalize_hostname, +rnds, and qualify_shortname variables in [libdefaults].

+

If dns_canonicalize_hostname is set to true (the default +value), the client performs forward resolution by looking up the IPv4 +and/or IPv6 addresses of the hostname using getaddrinfo(). This +process will typically add a domain suffix to the hostname if needed, +and follow CNAME records in the DNS. If rdns is also set to +true (the default), the client will then perform a reverse lookup +of the first returned Internet address using getnameinfo(), +finding the name associated with the PTR record.

+

If dns_canonicalize_hostname is set to false, the hostname is +not canonicalized using DNS. If the hostname has only one component +(i.e. it contains no “.” characters), the host’s primary DNS search +domain will be appended, if there is one. The qualify_shortname +variable can be used to override or disable this suffix.

+

If dns_canonicalize_hostname is set to fallback (added in +release 1.18), the hostname is initially treated according to the +rules for dns_canonicalize_hostname=false. If a ticket request +fails because the service principal is unknown, the hostname will be +canonicalized according to the rules for +dns_canonicalize_hostname=true and the request will be retried.

+

In all cases, the hostname is converted to lowercase, and any trailing +dot is removed.

+
+
+

Reverse DNS mismatches

+

Sometimes, an enterprise will have control over its forward DNS but +not its reverse DNS. The reverse DNS is sometimes under the control +of the Internet service provider of the enterprise, and the enterprise +may not have much influence in setting up reverse DNS records for its +address space. If there are difficulties with getting forward and +reverse DNS to match, it is best to set rdns = false on client +machines.

+
+
+

Overriding application behavior

+

Applications can choose to use a default hostname component in their +service principal name when accepting authentication, which avoids +some sorts of hostname mismatches. Because not all relevant +applications do this yet, using the krb5.conf setting:

+
[libdefaults]
+    ignore_acceptor_hostname = true
+
+
+

will allow the Kerberos library to override the application’s choice +of service principal hostname and will allow a server program to +accept incoming authentications using any key in its keytab that +matches the service name and realm name (if given). This setting +defaults to “false” and is available in releases krb5-1.10 and later.

+
+
+

Provisioning keytabs

+

One service principal entry that should be in the keytab is a +principal whose hostname component is the canonical hostname that +getaddrinfo() reports for all known aliases for the host. If the +reverse DNS information does not match this canonical hostname, an +additional service principal entry should be in the keytab for this +different hostname.

+
+
+

Specific application advice

+
+

Secure shell (ssh)

+

Setting GSSAPIStrictAcceptorCheck = no in the configuration file +of modern versions of the openssh daemon will allow the daemon to try +any key in its keytab when accepting a connection, rather than looking +for the keytab entry that matches the host’s own idea of its name +(typically the name that gethostname() returns). This requires +krb5-1.10 or later.

+
+
+

OpenLDAP (ldapsearch, etc.)

+

OpenLDAP’s SASL implementation performs reverse DNS lookup in order to +canonicalize service principal names, even if rdns is set to +false in the Kerberos configuration. To disable this behavior, +add SASL_NOCANON on to ldap.conf, or set the +LDAPSASL_NOCANON environment variable.

+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/realm_config.html b/krb5-1.21.3/doc/html/admin/realm_config.html new file mode 100644 index 00000000..f90ab88f --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/realm_config.html @@ -0,0 +1,394 @@ + + + + + + + + + Realm configuration decisions — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Realm configuration decisions

+

Before installing Kerberos V5, it is necessary to consider the +following issues:

+
    +
  • The name of your Kerberos realm (or the name of each realm, if you +need more than one).

  • +
  • How you will assign your hostnames to Kerberos realms.

  • +
  • Which ports your KDC and and kadmind services will use, if they will +not be using the default ports.

  • +
  • How many replica KDCs you need and where they should be located.

  • +
  • The hostnames of your primary and replica KDCs.

  • +
  • How frequently you will propagate the database from the primary KDC +to the replica KDCs.

  • +
+
+

Realm name

+

Although your Kerberos realm can be any ASCII string, convention is to +make it the same as your domain name, in upper-case letters.

+

For example, hosts in the domain example.com would be in the +Kerberos realm:

+
EXAMPLE.COM
+
+
+

If you need multiple Kerberos realms, MIT recommends that you use +descriptive names which end with your domain name, such as:

+
BOSTON.EXAMPLE.COM
+HOUSTON.EXAMPLE.COM
+
+
+
+
+

Mapping hostnames onto Kerberos realms

+

Mapping hostnames onto Kerberos realms is done in one of three ways.

+

The first mechanism works through a set of rules in the +[domain_realm] section of krb5.conf. You can specify +mappings for an entire domain or on a per-hostname basis. Typically +you would do this by specifying the mappings for a given domain or +subdomain and listing the exceptions.

+

The second mechanism is to use KDC host-based service referrals. With +this method, the KDC’s krb5.conf has a full [domain_realm] mapping for +hosts, but the clients do not, or have mappings for only a subset of +the hosts they might contact. When a client needs to contact a server +host for which it has no mapping, it will ask the client realm’s KDC +for the service ticket, and will receive a referral to the appropriate +service realm.

+

To use referrals, clients must be running MIT krb5 1.6 or later, and +the KDC must be running MIT krb5 1.7 or later. The +host_based_services and no_host_referral variables in the +[realms] section of kdc.conf can be used to +fine-tune referral behavior on the KDC.

+

It is also possible for clients to use DNS TXT records, if +dns_lookup_realm is enabled in krb5.conf. Such lookups +are disabled by default because DNS is an insecure protocol and security +holes could result if DNS records are spoofed. If enabled, the client +will try to look up a TXT record formed by prepending the prefix +_kerberos to the hostname in question. If that record is not +found, the client will attempt a lookup by prepending _kerberos to the +host’s domain name, then its parent domain, up to the top-level domain. +For the hostname boston.engineering.example.com, the names looked up +would be:

+
_kerberos.boston.engineering.example.com
+_kerberos.engineering.example.com
+_kerberos.example.com
+_kerberos.com
+
+
+

The value of the first TXT record found is taken as the realm name.

+

Even if you do not choose to use this mechanism within your site, +you may wish to set it up anyway, for use when interacting with other sites.

+
+
+

Ports for the KDC and admin services

+

The default ports used by Kerberos are port 88 for the KDC and port +749 for the admin server. You can, however, choose to run on other +ports, as long as they are specified in each host’s +krb5.conf files or in DNS SRV records, and the +kdc.conf file on each KDC. For a more thorough treatment of +port numbers used by the Kerberos V5 programs, refer to the +Configuring your firewall to work with Kerberos V5.

+
+
+

Replica KDCs

+

Replica KDCs provide an additional source of Kerberos ticket-granting +services in the event of inaccessibility of the primary KDC. The +number of replica KDCs you need and the decision of where to place them, +both physically and logically, depends on the specifics of your +network.

+

Kerberos authentication requires that each client be able to contact a +KDC. Therefore, you need to anticipate any likely reason a KDC might +be unavailable and have a replica KDC to take up the slack.

+

Some considerations include:

+
    +
  • Have at least one replica KDC as a backup, for when the primary KDC +is down, is being upgraded, or is otherwise unavailable.

  • +
  • If your network is split such that a network outage is likely to +cause a network partition (some segment or segments of the network +to become cut off or isolated from other segments), have a replica +KDC accessible to each segment.

  • +
  • If possible, have at least one replica KDC in a different building +from the primary, in case of power outages, fires, or other +localized disasters.

  • +
+
+
+

Hostnames for KDCs

+

MIT recommends that your KDCs have a predefined set of CNAME records +(DNS hostname aliases), such as kerberos for the primary KDC and +kerberos-1, kerberos-2, … for the replica KDCs. This way, +if you need to swap a machine, you only need to change a DNS entry, +rather than having to change hostnames.

+

As of MIT krb5 1.4, clients can locate a realm’s KDCs through DNS +using SRV records (RFC 2782), assuming the Kerberos realm name is +also a DNS domain name. These records indicate the hostname and port +number to contact for that service, optionally with weighting and +prioritization. The domain name used in the SRV record name is the +realm name. Several different Kerberos-related service names are +used:

+
+
_kerberos._udp

This is for contacting any KDC by UDP. This entry will be used +the most often. Normally you should list port 88 on each of your +KDCs.

+
+
_kerberos._tcp

This is for contacting any KDC by TCP. Normally you should use +port 88. This entry should be omitted if the KDC does not listen +on TCP ports, as was the default prior to release 1.13.

+
+
_kerberos-master._udp

This entry should refer to those KDCs, if any, that will +immediately see password changes to the Kerberos database. If a +user is logging in and the password appears to be incorrect, the +client will retry with the primary KDC before failing with an +“incorrect password” error given.

+

If you have only one KDC, or for whatever reason there is no +accessible KDC that would get database changes faster than the +others, you do not need to define this entry.

+
+
_kerberos-adm._tcp

This should list port 749 on your primary KDC. Support for it is +not complete at this time, but it will eventually be used by the +kadmin program and related utilities. For now, you will +also need the admin_server variable in krb5.conf.

+
+
_kerberos-master._tcp

The corresponding TCP port for _kerberos-master._udp, assuming the +primary KDC listens on a TCP port.

+
+
_kpasswd._udp

This entry should list port 464 on your primary KDC. It is used +when a user changes her password. If this entry is not defined +but a _kerberos-adm._tcp entry is defined, the client will use the +_kerberos-adm._tcp entry with the port number changed to 464.

+
+
_kpasswd._tcp

The corresponding TCP port for _kpasswd._udp.

+
+
+

The DNS SRV specification requires that the hostnames listed be the +canonical names, not aliases. So, for example, you might include the +following records in your (BIND-style) zone file:

+
$ORIGIN foobar.com.
+_kerberos               TXT       "FOOBAR.COM"
+kerberos                CNAME     daisy
+kerberos-1              CNAME     use-the-force-luke
+kerberos-2              CNAME     bunny-rabbit
+_kerberos._udp          SRV       0 0 88 daisy
+                        SRV       0 0 88 use-the-force-luke
+                        SRV       0 0 88 bunny-rabbit
+_kerberos-master._udp   SRV       0 0 88 daisy
+_kerberos-adm._tcp      SRV       0 0 749 daisy
+_kpasswd._udp           SRV       0 0 464 daisy
+
+
+

Clients can also be configured with the explicit location of services +using the kdc, master_kdc, admin_server, and +kpasswd_server variables in the [realms] section of +krb5.conf. Even if some clients will be configured with +explicit server locations, providing SRV records will still benefit +unconfigured clients, and be useful for other sites.

+
+
+

KDC Discovery

+

As of MIT krb5 1.15, clients can also locate KDCs in DNS through URI +records (RFC 7553). Limitations with the SRV record format may +result in extra DNS queries in situations where a client must failover +to other transport types, or find a primary server. The URI record +can convey more information about a realm’s KDCs with a single query.

+

The client performs a query for the following URI records:

+
    +
  • _kerberos.REALM for finding KDCs.

  • +
  • _kerberos-adm.REALM for finding kadmin services.

  • +
  • _kpasswd.REALM for finding password services.

  • +
+

The URI record includes a priority, weight, and a URI string that +consists of case-insensitive colon separated fields, in the form +scheme:[flags]:transport:residual.

+
    +
  • scheme defines the registered URI type. It should always be +krb5srv.

  • +
  • flags contains zero or more flag characters. Currently the only +valid flag is m, which indicates that the record is for a +primary server.

  • +
  • transport defines the transport type of the residual URL or +address. Accepted values are tcp, udp, or kkdcp for the +MS-KKDCP type.

  • +
  • residual contains the hostname, IP address, or URL to be +contacted using the specified transport, with an optional port +extension. The MS-KKDCP transport type uses a HTTPS URL, and can +include a port and/or path extension.

  • +
+

An example of URI records in a zone file:

+
_kerberos.EXAMPLE.COM  URI  10 1 krb5srv:m:tcp:kdc1.example.com
+                       URI  20 1 krb5srv:m:udp:kdc2.example.com:89
+                       URI  40 1 krb5srv::udp:10.10.0.23
+                       URI  30 1 krb5srv::kkdcp:https://proxy:89/auth
+
+
+

URI lookups are enabled by default, and can be disabled by setting +dns_uri_lookup in the [libdefaults] section of +krb5.conf to False. When enabled, URI lookups take +precedence over SRV lookups, falling back to SRV lookups if no URI +records are found.

+
+
+

Database propagation

+

The Kerberos database resides on the primary KDC, and must be +propagated regularly (usually by a cron job) to the replica KDCs. In +deciding how frequently the propagation should happen, you will need +to balance the amount of time the propagation takes against the +maximum reasonable amount of time a user should have to wait for a +password change to take effect.

+

If the propagation time is longer than this maximum reasonable time +(e.g., you have a particularly large database, you have a lot of +replicas, or you experience frequent network delays), you may wish to +cut down on your propagation delay by performing the propagation in +parallel. To do this, have the primary KDC propagate the database to +one set of replicas, and then have each of these replicas propagate +the database to additional replicas.

+

See also Incremental database propagation

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/spake.html b/krb5-1.21.3/doc/html/admin/spake.html new file mode 100644 index 00000000..39c9ee58 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/spake.html @@ -0,0 +1,199 @@ + + + + + + + + + SPAKE Preauthentication — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

SPAKE Preauthentication

+

SPAKE preauthentication (added in release 1.17) uses public key +cryptography techniques to protect against password dictionary +attacks. Unlike PKINIT, it does not +require any additional infrastructure such as certificates; it simply +needs to be turned on. Using SPAKE preauthentication may modestly +increase the CPU and network load on the KDC.

+

SPAKE preauthentication can use one of four elliptic curve groups for +its password-authenticated key exchange. The recommended group is +edwards25519; three NIST curves (P-256, P-384, and +P-521) are also supported.

+

By default, SPAKE with the edwards25519 group is enabled on +clients, but the KDC does not offer SPAKE by default. To turn it on, +set the spake_preauth_groups variable in [libdefaults] to a +list of allowed groups. This variable affects both the client and the +KDC. Simply setting it to edwards25519 is recommended:

+
[libdefaults]
+    spake_preauth_groups = edwards25519
+
+
+

Set the +requires_preauth and -allow_svr flags on client +principal entries, as you would for any preauthentication mechanism:

+
kadmin: modprinc +requires_preauth -allow_svr PRINCNAME
+
+
+

Clients which do not implement SPAKE preauthentication will fall back +to encrypted timestamp.

+

An active attacker can force a fallback to encrypted timestamp by +modifying the initial KDC response, defeating the protection against +dictionary attacks. To prevent this fallback on clients which do +implement SPAKE preauthentication, set the +disable_encrypted_timestamp variable to true in the +[realms] subsection for realms whose KDCs offer SPAKE +preauthentication.

+

By default, SPAKE preauthentication requires an extra network round +trip to the KDC during initial authentication. If most of the clients +in a realm support SPAKE, this extra round trip can be eliminated +using an optimistic challenge, by setting the +spake_preauth_kdc_challenge variable in [kdcdefaults] to a +single group name:

+
[kdcdefaults]
+    spake_preauth_kdc_challenge = edwards25519
+
+
+

Using optimistic challenge will cause the KDC to do extra work for +initial authentication requests that do not result in SPAKE +preauthentication, but will save work when SPAKE preauthentication is +used.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/troubleshoot.html b/krb5-1.21.3/doc/html/admin/troubleshoot.html new file mode 100644 index 00000000..493abbf0 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/troubleshoot.html @@ -0,0 +1,266 @@ + + + + + + + + + Troubleshooting — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Troubleshooting

+
+

Trace logging

+

Most programs using MIT krb5 1.9 or later can be made to provide +information about internal krb5 library operations using trace +logging. To enable this, set the KRB5_TRACE environment variable +to a filename before running the program. On many operating systems, +the filename /dev/stdout can be used to send trace logging output +to standard output.

+

Some programs do not honor KRB5_TRACE, either because they use +secure library contexts (this generally applies to setuid programs and +parts of the login system) or because they take direct control of the +trace logging system using the API.

+

Here is a short example showing trace logging output for an invocation +of the kvno command:

+
shell% env KRB5_TRACE=/dev/stdout kvno krbtgt/KRBTEST.COM
+[9138] 1332348778.823276: Getting credentials user@KRBTEST.COM ->
+    krbtgt/KRBTEST.COM@KRBTEST.COM using ccache
+    FILE:/me/krb5/build/testdir/ccache
+[9138] 1332348778.823381: Retrieving user@KRBTEST.COM ->
+    krbtgt/KRBTEST.COM@KRBTEST.COM from
+    FILE:/me/krb5/build/testdir/ccache with result: 0/Unknown code 0
+krbtgt/KRBTEST.COM@KRBTEST.COM: kvno = 1
+
+
+
+
+

List of errors

+
+

Frequently seen errors

+
    +
  1. KDC has no support for encryption type while getting initial credentials

  2. +
  3. credential verification failed: KDC has no support for encryption type

  4. +
  5. Cannot create cert chain: certificate has expired

  6. +
+
+
+

Errors seen by admins

+
    +
  1. kprop: No route to host while connecting to server

  2. +
  3. kprop: Connection refused while connecting to server

  4. +
  5. kprop: Server rejected authentication (during sendauth exchange) while authenticating to server

  6. +
+
+
+

KDC has no support for encryption type while getting initial credentials

+
+
+

credential verification failed: KDC has no support for encryption type

+

This most commonly happens when trying to use a principal with only +DES keys, in a release (MIT krb5 1.7 or later) which disables DES by +default. DES encryption is considered weak due to its inadequate key +size. If you cannot migrate away from its use, you can re-enable DES +by adding allow_weak_crypto = true to the [libdefaults] +section of krb5.conf.

+
+
+

Cannot create cert chain: certificate has expired

+

This error message indicates that PKINIT authentication failed because +the client certificate, KDC certificate, or one of the certificates in +the signing chain above them has expired.

+

If the KDC certificate has expired, this message appears in the KDC +log file, and the client will receive a “Preauthentication failed” +error. (Prior to release 1.11, the KDC log file message erroneously +appears as “Out of memory”. Prior to release 1.12, the client will +receive a “Generic error”.)

+

If the client or a signing certificate has expired, this message may +appear in trace_logging output from kinit or, starting in +release 1.12, as an error message from kinit or another program which +gets initial tickets. The error message is more likely to appear +properly on the client if the principal entry has no long-term keys.

+
+
+

kprop: No route to host while connecting to server

+

Make sure that the hostname of the replica KDC (as given to kprop) is +correct, and that any firewalls between the primary and the replica +allow a connection on port 754.

+
+
+

kprop: Connection refused while connecting to server

+

If the replica KDC is intended to run kpropd out of inetd, make sure +that inetd is configured to accept krb5_prop connections. inetd may +need to be restarted or sent a SIGHUP to recognize the new +configuration. If the replica is intended to run kpropd in standalone +mode, make sure that it is running.

+
+
+

kprop: Server rejected authentication (during sendauth exchange) while authenticating to server

+

Make sure that:

+
    +
  1. The time is synchronized between the primary and replica KDCs.

  2. +
  3. The master stash file was copied from the primary to the expected +location on the replica.

  4. +
  5. The replica has a keytab file in the default location containing a +host principal for the replica’s hostname.

  6. +
+
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/admin/various_envs.html b/krb5-1.21.3/doc/html/admin/various_envs.html new file mode 100644 index 00000000..14d3c535 --- /dev/null +++ b/krb5-1.21.3/doc/html/admin/various_envs.html @@ -0,0 +1,179 @@ + + + + + + + + + Various links — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+ + +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/gssapi.html b/krb5-1.21.3/doc/html/appdev/gssapi.html new file mode 100644 index 00000000..c51274a4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/gssapi.html @@ -0,0 +1,797 @@ + + + + + + + + + Developing with GSSAPI — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Developing with GSSAPI

+

The GSSAPI (Generic Security Services API) allows applications to +communicate securely using Kerberos 5 or other security mechanisms. +We recommend using the GSSAPI (or a higher-level framework which +encompasses GSSAPI, such as SASL) for secure network communication +over using the libkrb5 API directly.

+

GSSAPIv2 is specified in RFC 2743 and RFC 2744. Also see +RFC 7546 for a description of how to use the GSSAPI in a client or +server program.

+

This documentation will describe how various ways of using the +GSSAPI will behave with the krb5 mechanism as implemented in MIT krb5, +as well as krb5-specific extensions to the GSSAPI.

+
+

Name types

+

A GSSAPI application can name a local or remote entity by calling +gss_import_name, specifying a name type and a value. The following +name types are supported by the krb5 mechanism:

+
    +
  • GSS_C_NT_HOSTBASED_SERVICE: The value should be a string of the +form service or service@hostname. This is the most common +way to name target services when initiating a security context, and +is the most likely name type to work across multiple mechanisms.

  • +
  • GSS_KRB5_NT_PRINCIPAL_NAME: The value should be a principal name +string. This name type only works with the krb5 mechanism, and is +defined in the <gssapi/gssapi_krb5.h> header.

  • +
  • GSS_C_NT_USER_NAME or GSS_C_NULL_OID: The value is treated +as an unparsed principal name string, as above. These name types +may work with mechanisms other than krb5, but will have different +interpretations in those mechanisms. GSS_C_NT_USER_NAME is +intended to be used with a local username, which will parse into a +single-component principal in the default realm.

  • +
  • GSS_C_NT_ANONYMOUS: The value is ignored. The anonymous +principal is used, allowing a client to authenticate to a server +without asserting a particular identity (which may or may not be +allowed by a particular server or Kerberos realm).

  • +
  • GSS_C_NT_MACHINE_UID_NAME: The value is uid_t object. On +Unix-like systems, the username of the uid is looked up in the +system user database and the resulting username is parsed as a +principal name.

  • +
  • GSS_C_NT_STRING_UID_NAME: As above, but the value is a decimal +string representation of the uid.

  • +
  • GSS_C_NT_EXPORT_NAME: The value must be the result of a +gss_export_name call.

  • +
  • GSS_KRB5_NT_ENTERPRISE_NAME: The value should be a krb5 +enterprise name string (see RFC 6806 section 5), in the form +user@suffix. This name type is used to convey alias names, and +is defined in the <gssapi/gssapi_krb5.h> header. (New in +release 1.17.)

  • +
  • GSS_KRB5_NT_X509_CERT: The value should be an X.509 certificate +encoded according to RFC 5280. This name form can be used for +the desired_name parameter of gss_acquire_cred_impersonate_name(), +to identify the S4U2Self user by certificate. (New in release +1.19.)

  • +
+
+
+

Initiator credentials

+

A GSSAPI client application uses gss_init_sec_context to establish a +security context. The initiator_cred_handle parameter determines +what tickets are used to establish the connection. An application can +either pass GSS_C_NO_CREDENTIAL to use the default client +credential, or it can use gss_acquire_cred beforehand to acquire an +initiator credential. The call to gss_acquire_cred may include a +desired_name parameter, or it may pass GSS_C_NO_NAME if it does +not have a specific name preference.

+

If the desired name for a krb5 initiator credential is a host-based +name, it is converted to a principal name of the form +service/hostname in the local realm, where hostname is the local +hostname if not specified. The hostname will be canonicalized using +forward name resolution, and possibly also using reverse name +resolution depending on the value of the rdns variable in +[libdefaults].

+

If a desired name is specified in the call to gss_acquire_cred, the +krb5 mechanism will attempt to find existing tickets for that client +principal name in the default credential cache or collection. If the +default cache type does not support a collection, and the default +cache contains credentials for a different principal than the desired +name, a GSS_S_CRED_UNAVAIL error will be returned with a minor +code indicating a mismatch.

+

If no existing tickets are available for the desired name, but the +name has an entry in the default client keytab, the +krb5 mechanism will acquire initial tickets for the name using the +default client keytab.

+

If no desired name is specified, credential acquisition will be +deferred until the credential is used in a call to +gss_init_sec_context or gss_inquire_cred. If the call is to +gss_init_sec_context, the target name will be used to choose a client +principal name using the credential cache selection facility. (This +facility might, for instance, try to choose existing tickets for a +client principal in the same realm as the target service). If there +are no existing tickets for the chosen principal, but it is present in +the default client keytab, the krb5 mechanism will acquire initial +tickets using the keytab.

+

If the target name cannot be used to select a client principal +(because the credentials are used in a call to gss_inquire_cred), or +if the credential cache selection facility cannot choose a principal +for it, the default credential cache will be selected if it exists and +contains tickets.

+

If the default credential cache does not exist, but the default client +keytab does, the krb5 mechanism will try to acquire initial tickets +for the first principal in the default client keytab.

+

If the krb5 mechanism acquires initial tickets using the default +client keytab, the resulting tickets will be stored in the default +cache or collection, and will be refreshed by future calls to +gss_acquire_cred as they approach their expire time.

+
+
+

Acceptor names

+

A GSSAPI server application uses gss_accept_sec_context to establish +a security context based on tokens provided by the client. The +acceptor_cred_handle parameter determines what +keytab entries may be authenticated to by the +client, if the krb5 mechanism is used.

+

The simplest choice is to pass GSS_C_NO_CREDENTIAL as the acceptor +credential. In this case, clients may authenticate to any service +principal in the default keytab (typically DEFKTNAME, or the value of +the KRB5_KTNAME environment variable). This is the recommended +approach if the server application has no specific requirements to the +contrary.

+

A server may acquire an acceptor credential with gss_acquire_cred and +a cred_usage of GSS_C_ACCEPT or GSS_C_BOTH. If the +desired_name parameter is GSS_C_NO_NAME, then clients will be +allowed to authenticate to any service principal in the default +keytab, just as if no acceptor credential was supplied.

+

If a server wishes to specify a desired_name to gss_acquire_cred, +the most common choice is a host-based name. If the host-based +desired_name contains just a service, then clients will be allowed +to authenticate to any host-based service principal (that is, a +principal of the form service/hostname@REALM) for the named +service, regardless of hostname or realm, as long as it is present in +the default keytab. If the input name contains both a service and a +hostname, clients will be allowed to authenticate to any host-based +principal for the named service and hostname, regardless of realm.

+
+

Note

+

If a hostname is specified, it will be canonicalized +using forward name resolution, and possibly also using +reverse name resolution depending on the value of the +rdns variable in [libdefaults].

+
+
+

Note

+

If the ignore_acceptor_hostname variable in +[libdefaults] is enabled, then hostname will be +ignored even if one is specified in the input name.

+
+
+

Note

+

In MIT krb5 versions prior to 1.10, and in Heimdal’s +implementation of the krb5 mechanism, an input name with +just a service is treated like an input name of +service@localhostname, where localhostname is the +string returned by gethostname().

+
+

If the desired_name is a krb5 principal name or a local system name +type which is mapped to a krb5 principal name, clients will only be +allowed to authenticate to that principal in the default keytab.

+
+
+

Name Attributes

+

In release 1.8 or later, the gss_inquire_name and +gss_get_name_attribute functions, specified in RFC 6680, can be +used to retrieve name attributes from the src_name returned by +gss_accept_sec_context. The following attributes are defined when +the krb5 mechanism is used:

+
    +
  • “auth-indicators” attribute:

  • +
+

This attribute will be included in the gss_inquire_name output if the +ticket contains authentication indicators. +One indicator is returned per invocation of gss_get_name_attribute, +so multiple invocations may be necessary to retrieve all of the +indicators from the ticket. (New in release 1.15.)

+
+
+

Credential store extensions

+

Beginning with release 1.11, the following GSSAPI extensions declared +in <gssapi/gssapi_ext.h> can be used to specify how credentials +are acquired or stored:

+
struct gss_key_value_element_struct {
+    const char *key;
+    const char *value;
+};
+typedef struct gss_key_value_element_struct gss_key_value_element_desc;
+
+struct gss_key_value_set_struct {
+    OM_uint32 count;
+    gss_key_value_element_desc *elements;
+};
+typedef const struct gss_key_value_set_struct gss_key_value_set_desc;
+typedef const gss_key_value_set_desc *gss_const_key_value_set_t;
+
+OM_uint32 gss_acquire_cred_from(OM_uint32 *minor_status,
+                                const gss_name_t desired_name,
+                                OM_uint32 time_req,
+                                const gss_OID_set desired_mechs,
+                                gss_cred_usage_t cred_usage,
+                                gss_const_key_value_set_t cred_store,
+                                gss_cred_id_t *output_cred_handle,
+                                gss_OID_set *actual_mechs,
+                                OM_uint32 *time_rec);
+
+OM_uint32 gss_store_cred_into(OM_uint32 *minor_status,
+                              gss_cred_id_t input_cred_handle,
+                              gss_cred_usage_t cred_usage,
+                              const gss_OID desired_mech,
+                              OM_uint32 overwrite_cred,
+                              OM_uint32 default_cred,
+                              gss_const_key_value_set_t cred_store,
+                              gss_OID_set *elements_stored,
+                              gss_cred_usage_t *cred_usage_stored);
+
+
+

The additional cred_store parameter allows the caller to specify +information about how the credentials should be obtained and stored. +The following options are supported by the krb5 mechanism:

+
    +
  • ccache: For acquiring initiator credentials, the name of the +credential cache to which the handle will +refer. For storing credentials, the name of the cache or collection +where the credentials will be stored (see below).

  • +
  • client_keytab: For acquiring initiator credentials, the name of +the keytab which will be used, if +necessary, to refresh the credentials in the cache.

  • +
  • keytab: For acquiring acceptor credentials, the name of the +keytab to which the handle will refer. +In release 1.19 and later, this option also determines the keytab to +be used for verification when initiator credentials are acquired +using a password and verified.

  • +
  • password: For acquiring initiator credentials, this option +instructs the mechanism to acquire fresh credentials into a unique +memory credential cache. This option may not be used with the +ccache or client_keytab options, and a desired_name must +be specified. (New in release 1.19.)

  • +
  • rcache: For acquiring acceptor credentials, the name of the +replay cache to be used when processing +the initiator tokens. (New in release 1.13.)

  • +
  • verify: For acquiring initiator credentials, this option +instructs the mechanism to verify the credentials by obtaining a +ticket to a service with a known key. The service key is obtained +from the keytab specified with the keytab option or the default +keytab. The value may be the name of a principal in the keytab, or +the empty string. If the empty string is given, any host +service principal in the keytab may be used. (New in release 1.19.)

  • +
+

In release 1.20 or later, if a collection name is specified for +cache in a call to gss_store_cred_into(), an existing cache for +the client principal within the collection will be selected, or a new +cache will be created within the collection. If overwrite_cred is +false and the selected credential cache already exists, a +GSS_S_DUPLICATE_ELEMENT error will be returned. If default_cred +is true, the primary cache of the collection will be switched to the +selected cache.

+
+
+

Importing and exporting credentials

+

The following GSSAPI extensions can be used to import and export +credentials (declared in <gssapi/gssapi_ext.h>):

+
OM_uint32 gss_export_cred(OM_uint32 *minor_status,
+                          gss_cred_id_t cred_handle,
+                          gss_buffer_t token);
+
+OM_uint32 gss_import_cred(OM_uint32 *minor_status,
+                          gss_buffer_t token,
+                          gss_cred_id_t *cred_handle);
+
+
+

The first function serializes a GSSAPI credential handle into a +buffer; the second unseralizes a buffer into a GSSAPI credential +handle. Serializing a credential does not destroy it. If any of the +mechanisms used in cred_handle do not support serialization, +gss_export_cred will return GSS_S_UNAVAILABLE. As with other +GSSAPI serialization functions, these extensions are only intended to +work with a matching implementation on the other side; they do not +serialize credentials in a standardized format.

+

A serialized credential may contain secret information such as ticket +session keys. The serialization format does not protect this +information from eavesdropping or tampering. The calling application +must take care to protect the serialized credential when communicating +it over an insecure channel or to an untrusted party.

+

A krb5 GSSAPI credential may contain references to a credential cache, +a client keytab, an acceptor keytab, and a replay cache. These +resources are normally serialized as references to their external +locations (such as the filename of the credential cache). Because of +this, a serialized krb5 credential can only be imported by a process +with similar privileges to the exporter. A serialized credential +should not be trusted if it originates from a source with lower +privileges than the importer, as it may contain references to external +credential cache, keytab, or replay cache resources not accessible to +the originator.

+

An exception to the above rule applies when a krb5 GSSAPI credential +refers to a memory credential cache, as is normally the case for +delegated credentials received by gss_accept_sec_context. In this +case, the contents of the credential cache are serialized, so that the +resulting token may be imported even if the original memory credential +cache no longer exists.

+
+
+

Constrained delegation (S4U)

+

The Microsoft S4U2Self and S4U2Proxy Kerberos protocol extensions +allow an intermediate service to acquire credentials from a client to +a target service without requiring the client to delegate a +ticket-granting ticket, if the KDC is configured to allow it.

+

To perform a constrained delegation operation, the intermediate +service must submit to the KDC an “evidence ticket” from the client to +the intermediate service. An evidence ticket can be acquired when the +client authenticates to the intermediate service with Kerberos, or +with an S4U2Self request if the KDC allows it. The MIT krb5 GSSAPI +library represents an evidence ticket using a “proxy credential”, +which is a special kind of gss_cred_id_t object whose underlying +credential cache contains the evidence ticket and a krbtgt ticket for +the intermediate service.

+

To acquire a proxy credential during client authentication, the +service should first create an acceptor credential using the +GSS_C_BOTH usage. The application should then pass this +credential as the acceptor_cred_handle to gss_accept_sec_context, +and also pass a delegated_cred_handle output parameter to receive a +proxy credential containing the evidence ticket. The output value of +delegated_cred_handle may be a delegated ticket-granting ticket if +the client sent one, or a proxy credential if not. If the library can +determine that the client’s ticket is not a valid evidence ticket, it +will place GSS_C_NO_CREDENTIAL in delegated_cred_handle.

+

To acquire a proxy credential using an S4U2Self request, the service +can use the following GSSAPI extension:

+
OM_uint32 gss_acquire_cred_impersonate_name(OM_uint32 *minor_status,
+                                            gss_cred_id_t icred,
+                                            gss_name_t desired_name,
+                                            OM_uint32 time_req,
+                                            gss_OID_set desired_mechs,
+                                            gss_cred_usage_t cred_usage,
+                                            gss_cred_id_t *output_cred,
+                                            gss_OID_set *actual_mechs,
+                                            OM_uint32 *time_rec);
+
+
+

The parameters to this function are similar to those of +gss_acquire_cred, except that icred is used to make an S4U2Self +request to the KDC for a ticket from desired_name to the +intermediate service. Both icred and desired_name are required +for this function; passing GSS_C_NO_CREDENTIAL or +GSS_C_NO_NAME will cause the call to fail. icred must contain a +krbtgt ticket for the intermediate service. The result of this +operation is a proxy credential. (Prior to release 1.18, the result +of this operation may be a regular credential for desired_name, if +the KDC issues a non-forwardable ticket.)

+

Once the intermediate service has a proxy credential, it can simply +pass it to gss_init_sec_context as the initiator_cred_handle +parameter, and the desired service as the target_name parameter. +The GSSAPI library will present the krbtgt ticket and evidence ticket +in the proxy credential to the KDC in an S4U2Proxy request; if the +intermediate service has the appropriate permissions, the KDC will +issue a ticket from the client to the target service. The GSSAPI +library will then use this ticket to authenticate to the target +service.

+

If an application needs to find out whether a credential it holds is a +proxy credential and the name of the intermediate service, it can +query the credential with the GSS_KRB5_GET_CRED_IMPERSONATOR OID +(new in release 1.16, declared in <gssapi/gssapi_krb5.h>) using +the gss_inquire_cred_by_oid extension (declared in +<gssapi/gssapi_ext.h>):

+
OM_uint32 gss_inquire_cred_by_oid(OM_uint32 *minor_status,
+                                  const gss_cred_id_t cred_handle,
+                                  gss_OID desired_object,
+                                  gss_buffer_set_t *data_set);
+
+
+

If the call succeeds and cred_handle is a proxy credential, +data_set will be set to a single-element buffer set containing the +unparsed principal name of the intermediate service. If cred_handle +is not a proxy credential, data_set will be set to an empty buffer +set. If the library does not support the query, +gss_inquire_cred_by_oid will return GSS_S_UNAVAILABLE.

+
+
+

AEAD message wrapping

+

The following GSSAPI extensions (declared in +<gssapi/gssapi_ext.h>) can be used to wrap and unwrap messages +with additional “associated data” which is integrity-checked but is +not included in the output buffer:

+
OM_uint32 gss_wrap_aead(OM_uint32 *minor_status,
+                        gss_ctx_id_t context_handle,
+                        int conf_req_flag, gss_qop_t qop_req,
+                        gss_buffer_t input_assoc_buffer,
+                        gss_buffer_t input_payload_buffer,
+                        int *conf_state,
+                        gss_buffer_t output_message_buffer);
+
+OM_uint32 gss_unwrap_aead(OM_uint32 *minor_status,
+                          gss_ctx_id_t context_handle,
+                          gss_buffer_t input_message_buffer,
+                          gss_buffer_t input_assoc_buffer,
+                          gss_buffer_t output_payload_buffer,
+                          int *conf_state,
+                          gss_qop_t *qop_state);
+
+
+

Wrap tokens created with gss_wrap_aead will successfully unwrap only +if the same input_assoc_buffer contents are presented to +gss_unwrap_aead.

+
+
+

IOV message wrapping

+

The following extensions (declared in <gssapi/gssapi_ext.h>) can +be used for in-place encryption, fine-grained control over wrap token +layout, and for constructing wrap tokens compatible with Microsoft DCE +RPC:

+
typedef struct gss_iov_buffer_desc_struct {
+    OM_uint32 type;
+    gss_buffer_desc buffer;
+} gss_iov_buffer_desc, *gss_iov_buffer_t;
+
+OM_uint32 gss_wrap_iov(OM_uint32 *minor_status,
+                       gss_ctx_id_t context_handle,
+                       int conf_req_flag, gss_qop_t qop_req,
+                       int *conf_state,
+                       gss_iov_buffer_desc *iov, int iov_count);
+
+OM_uint32 gss_unwrap_iov(OM_uint32 *minor_status,
+                         gss_ctx_id_t context_handle,
+                         int *conf_state, gss_qop_t *qop_state,
+                         gss_iov_buffer_desc *iov, int iov_count);
+
+OM_uint32 gss_wrap_iov_length(OM_uint32 *minor_status,
+                              gss_ctx_id_t context_handle,
+                              int conf_req_flag,
+                              gss_qop_t qop_req, int *conf_state,
+                              gss_iov_buffer_desc *iov,
+                              int iov_count);
+
+OM_uint32 gss_release_iov_buffer(OM_uint32 *minor_status,
+                                 gss_iov_buffer_desc *iov,
+                                 int iov_count);
+
+
+

The caller of gss_wrap_iov provides an array of gss_iov_buffer_desc +structures, each containing a type and a gss_buffer_desc structure. +Valid types include:

+
    +
  • GSS_C_BUFFER_TYPE_DATA: A data buffer to be included in the +token, and to be encrypted or decrypted in-place if the token is +confidentiality-protected.

  • +
  • GSS_C_BUFFER_TYPE_HEADER: The GSSAPI wrap token header and +underlying cryptographic header.

  • +
  • GSS_C_BUFFER_TYPE_TRAILER: The cryptographic trailer, if one is +required.

  • +
  • GSS_C_BUFFER_TYPE_PADDING: Padding to be combined with the data +during encryption and decryption. (The implementation may choose to +place padding in the trailer buffer, in which case it will set the +padding buffer length to 0.)

  • +
  • GSS_C_BUFFER_TYPE_STREAM: For unwrapping only, a buffer +containing a complete wrap token in standard format to be unwrapped.

  • +
  • GSS_C_BUFFER_TYPE_SIGN_ONLY: A buffer to be included in the +token’s integrity protection checksum, but not to be encrypted or +included in the token itself.

  • +
+

For gss_wrap_iov, the IOV list should contain one HEADER buffer, +followed by zero or more SIGN_ONLY buffers, followed by one or more +DATA buffers, followed by a TRAILER buffer. The memory pointed to by +the buffers is not required to be contiguous or in any particular +order. If conf_req_flag is true, DATA buffers will be encrypted +in-place, while SIGN_ONLY buffers will not be modified.

+

The type of an output buffer may be combined with +GSS_C_BUFFER_FLAG_ALLOCATE to request that gss_wrap_iov allocate +the buffer contents. If gss_wrap_iov allocates a buffer, it sets the +GSS_C_BUFFER_FLAG_ALLOCATED flag on the buffer type. +gss_release_iov_buffer can be used to release all allocated buffers +within an iov list and unset their allocated flags. Here is an +example of how gss_wrap_iov can be used with allocation requested +(ctx is assumed to be a previously established gss_ctx_id_t):

+
OM_uint32 major, minor;
+gss_iov_buffer_desc iov[4];
+char str[] = "message";
+
+iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
+iov[1].buffer.value = str;
+iov[1].buffer.length = strlen(str);
+iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+
+major = gss_wrap_iov(&minor, ctx, 1, GSS_C_QOP_DEFAULT, NULL,
+                     iov, 4);
+if (GSS_ERROR(major))
+    handle_error(major, minor);
+
+/* Transmit or otherwise use resulting buffers. */
+
+(void)gss_release_iov_buffer(&minor, iov, 4);
+
+
+

If the caller does not choose to request buffer allocation by +gss_wrap_iov, it should first call gss_wrap_iov_length to query the +lengths of the HEADER, PADDING, and TRAILER buffers. DATA buffers +must be provided in the iov list so that padding length can be +computed correctly, but the output buffers need not be initialized. +Here is an example of using gss_wrap_iov_length and gss_wrap_iov:

+
OM_uint32 major, minor;
+gss_iov_buffer_desc iov[4];
+char str[1024] = "message", *ptr;
+
+iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
+iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
+iov[1].buffer.value = str;
+iov[1].buffer.length = strlen(str);
+
+iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING;
+iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER;
+
+major = gss_wrap_iov_length(&minor, ctx, 1, GSS_C_QOP_DEFAULT,
+                            NULL, iov, 4);
+if (GSS_ERROR(major))
+    handle_error(major, minor);
+if (strlen(str) + iov[0].buffer.length + iov[2].buffer.length +
+    iov[3].buffer.length > sizeof(str))
+    handle_out_of_space_error();
+ptr = str + strlen(str);
+iov[0].buffer.value = ptr;
+ptr += iov[0].buffer.length;
+iov[2].buffer.value = ptr;
+ptr += iov[2].buffer.length;
+iov[3].buffer.value = ptr;
+
+major = gss_wrap_iov(&minor, ctx, 1, GSS_C_QOP_DEFAULT, NULL,
+                     iov, 4);
+if (GSS_ERROR(major))
+    handle_error(major, minor);
+
+
+

If the context was established using the GSS_C_DCE_STYLE flag +(described in RFC 4757), wrap tokens compatible with Microsoft DCE +RPC can be constructed. In this case, the IOV list must include a +SIGN_ONLY buffer, a DATA buffer, a second SIGN_ONLY buffer, and a +HEADER buffer in that order (the order of the buffer contents remains +arbitrary). The application must pad the DATA buffer to a multiple of +16 bytes as no padding or trailer buffer is used.

+

gss_unwrap_iov may be called with an IOV list just like one which +would be provided to gss_wrap_iov. DATA buffers will be decrypted +in-place if they were encrypted, and SIGN_ONLY buffers will not be +modified.

+

Alternatively, gss_unwrap_iov may be called with a single STREAM +buffer, zero or more SIGN_ONLY buffers, and a single DATA buffer. The +STREAM buffer is interpreted as a complete wrap token. The STREAM +buffer will be modified in-place to decrypt its contents. The DATA +buffer will be initialized to point to the decrypted data within the +STREAM buffer, unless it has the GSS_C_BUFFER_FLAG_ALLOCATE flag +set, in which case it will be initialized with a copy of the decrypted +data. Here is an example (token and token_len are assumed to be a +pre-existing pointer and length for a modifiable region of data):

+
OM_uint32 major, minor;
+gss_iov_buffer_desc iov[2];
+
+iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM;
+iov[0].buffer.value = token;
+iov[0].buffer.length = token_len;
+iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
+major = gss_unwrap_iov(&minor, ctx, NULL, NULL, iov, 2);
+if (GSS_ERROR(major))
+    handle_error(major, minor);
+
+/* Decrypted data is in iov[1].buffer, pointing to a subregion of
+ * token. */
+
+
+
+
+

IOV MIC tokens

+

The following extensions (declared in <gssapi/gssapi_ext.h>) can +be used in release 1.12 or later to construct and verify MIC tokens +using an IOV list:

+
OM_uint32 gss_get_mic_iov(OM_uint32 *minor_status,
+                          gss_ctx_id_t context_handle,
+                          gss_qop_t qop_req,
+                          gss_iov_buffer_desc *iov,
+                          int iov_count);
+
+OM_uint32 gss_get_mic_iov_length(OM_uint32 *minor_status,
+                                 gss_ctx_id_t context_handle,
+                                 gss_qop_t qop_req,
+                                 gss_iov_buffer_desc *iov,
+                                 iov_count);
+
+OM_uint32 gss_verify_mic_iov(OM_uint32 *minor_status,
+                             gss_ctx_id_t context_handle,
+                             gss_qop_t *qop_state,
+                             gss_iov_buffer_desc *iov,
+                             int iov_count);
+
+
+

The caller of gss_get_mic_iov provides an array of gss_iov_buffer_desc +structures, each containing a type and a gss_buffer_desc structure. +Valid types include:

+
    +
  • GSS_C_BUFFER_TYPE_DATA and GSS_C_BUFFER_TYPE_SIGN_ONLY: The +corresponding buffer for each of these types will be signed for the +MIC token, in the order provided.

  • +
  • GSS_C_BUFFER_TYPE_MIC_TOKEN: The GSSAPI MIC token.

  • +
+

The type of the MIC_TOKEN buffer may be combined with +GSS_C_BUFFER_FLAG_ALLOCATE to request that gss_get_mic_iov +allocate the buffer contents. If gss_get_mic_iov allocates the +buffer, it sets the GSS_C_BUFFER_FLAG_ALLOCATED flag on the buffer +type. gss_release_iov_buffer can be used to release all allocated +buffers within an iov list and unset their allocated flags. Here is +an example of how gss_get_mic_iov can be used with allocation +requested (ctx is assumed to be a previously established +gss_ctx_id_t):

+
OM_uint32 major, minor;
+gss_iov_buffer_desc iov[3];
+
+iov[0].type = GSS_IOV_BUFFER_TYPE_DATA;
+iov[0].buffer.value = "sign1";
+iov[0].buffer.length = 5;
+iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
+iov[1].buffer.value = "sign2";
+iov[1].buffer.length = 5;
+iov[2].type = GSS_IOV_BUFFER_TYPE_MIC_TOKEN | GSS_IOV_BUFFER_FLAG_ALLOCATE;
+
+major = gss_get_mic_iov(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 3);
+if (GSS_ERROR(major))
+    handle_error(major, minor);
+
+/* Transmit or otherwise use iov[2].buffer. */
+
+(void)gss_release_iov_buffer(&minor, iov, 3);
+
+
+

If the caller does not choose to request buffer allocation by +gss_get_mic_iov, it should first call gss_get_mic_iov_length to query +the length of the MIC_TOKEN buffer. Here is an example of using +gss_get_mic_iov_length and gss_get_mic_iov:

+
OM_uint32 major, minor;
+gss_iov_buffer_desc iov[2];
+char data[1024];
+
+iov[0].type = GSS_IOV_BUFFER_TYPE_MIC_TOKEN;
+iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
+iov[1].buffer.value = "message";
+iov[1].buffer.length = 7;
+
+major = gss_get_mic_iov_length(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 2);
+if (GSS_ERROR(major))
+    handle_error(major, minor);
+if (iov[0].buffer.length > sizeof(data))
+    handle_out_of_space_error();
+iov[0].buffer.value = data;
+
+major = gss_get_mic_iov(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 2);
+if (GSS_ERROR(major))
+    handle_error(major, minor);
+
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/h5l_mit_apidiff.html b/krb5-1.21.3/doc/html/appdev/h5l_mit_apidiff.html new file mode 100644 index 00000000..4894254a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/h5l_mit_apidiff.html @@ -0,0 +1,177 @@ + + + + + + + + + Differences between Heimdal and MIT Kerberos API — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Differences between Heimdal and MIT Kerberos API

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +

krb5_auth_con_getaddrs()

H5l: If either of the pointers to local_addr +and remote_addr is not NULL, it is freed +first and then reallocated before being +populated with the content of corresponding +address from authentication context.

krb5_auth_con_setaddrs()

H5l: If either address is NULL, the previous +address remains in place

krb5_auth_con_setports()

H5l: Not implemented as of version 1.3.3

krb5_auth_con_setrecvsubkey()

H5l: If either port is NULL, the previous +port remains in place

krb5_auth_con_setsendsubkey()

H5l: Not implemented as of version 1.3.3

krb5_cc_set_config()

MIT: Before version 1.10 it was assumed that +the last argument data is ALWAYS non-zero.

krb5_cccol_last_change_time()

MIT: not implemented

krb5_set_default_realm()

H5l: Caches the computed default realm context +field. If the second argument is NULL, +it tries to retrieve it from libdefaults or DNS. +MIT: Computes the default realm each time +if it wasn’t explicitly set in the context

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/index.html b/krb5-1.21.3/doc/html/appdev/index.html new file mode 100644 index 00000000..a776af53 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/index.html @@ -0,0 +1,150 @@ + + + + + + + + + For application developers — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/init_creds.html b/krb5-1.21.3/doc/html/appdev/init_creds.html new file mode 100644 index 00000000..8822189c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/init_creds.html @@ -0,0 +1,433 @@ + + + + + + + + + Initial credentials — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Initial credentials

+

Software that performs tasks such as logging users into a computer +when they type their Kerberos password needs to get initial +credentials (usually ticket granting tickets) from Kerberos. Such +software shares some behavior with the kinit program.

+

Whenever a program grants access to a resource (such as a local login +session on a desktop computer) based on a user successfully getting +initial Kerberos credentials, it must verify those credentials against +a secure shared secret (e.g., a host keytab) to ensure that the user +credentials actually originate from a legitimate KDC. Failure to +perform this verification is a critical vulnerability, because a +malicious user can execute the “Zanarotti attack”: the user constructs +a fake response that appears to come from the legitimate KDC, but +whose contents come from an attacker-controlled KDC.

+

Some applications read a Kerberos password over the network (ideally +over a secure channel), which they then verify against the KDC. While +this technique may be the only practical way to integrate Kerberos +into some existing legacy systems, its use is contrary to the original +design goals of Kerberos.

+

The function krb5_get_init_creds_password() will get initial +credentials for a client using a password. An application that needs +to verify the credentials can call krb5_verify_init_creds(). +Here is an example of code to obtain and verify TGT credentials, given +strings princname and password for the client principal name and +password:

+
krb5_error_code ret;
+krb5_creds creds;
+krb5_principal client_princ = NULL;
+
+memset(&creds, 0, sizeof(creds));
+ret = krb5_parse_name(context, princname, &client_princ);
+if (ret)
+    goto cleanup;
+ret = krb5_get_init_creds_password(context, &creds, client_princ,
+                                   password, NULL, NULL, 0, NULL, NULL);
+if (ret)
+    goto cleanup;
+ret = krb5_verify_init_creds(context, &creds, NULL, NULL, NULL, NULL);
+
+cleanup:
+krb5_free_principal(context, client_princ);
+krb5_free_cred_contents(context, &creds);
+return ret;
+
+
+
+

Options for get_init_creds

+

The function krb5_get_init_creds_password() takes an options +parameter (which can be a null pointer). Use the function +krb5_get_init_creds_opt_alloc() to allocate an options +structure, and krb5_get_init_creds_opt_free() to free it. For +example:

+
krb5_error_code ret;
+krb5_get_init_creds_opt *opt = NULL;
+krb5_creds creds;
+
+memset(&creds, 0, sizeof(creds));
+ret = krb5_get_init_creds_opt_alloc(context, &opt);
+if (ret)
+    goto cleanup;
+krb5_get_init_creds_opt_set_tkt_life(opt, 24 * 60 * 60);
+ret = krb5_get_init_creds_password(context, &creds, client_princ,
+                                   password, NULL, NULL, 0, NULL, opt);
+if (ret)
+    goto cleanup;
+
+cleanup:
+krb5_get_init_creds_opt_free(context, opt);
+krb5_free_cred_contents(context, &creds);
+return ret;
+
+
+
+
+

Getting anonymous credentials

+

As of release 1.8, it is possible to obtain fully anonymous or +partially anonymous (realm-exposed) credentials, if the KDC supports +it. The MIT KDC supports issuing fully anonymous credentials as of +release 1.8 if configured appropriately (see Anonymous PKINIT), +but does not support issuing realm-exposed anonymous credentials at +this time.

+

To obtain fully anonymous credentials, call +krb5_get_init_creds_opt_set_anonymous() on the options +structure to set the anonymous flag, and specify a client principal +with the KDC’s realm and a single empty data component (the principal +obtained by parsing @realmname). Authentication will take +place using anonymous PKINIT; if successful, the client principal of +the resulting tickets will be +WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS. Here is an example:

+
krb5_get_init_creds_opt_set_anonymous(opt, 1);
+ret = krb5_build_principal(context, &client_princ, strlen(myrealm),
+                           myrealm, "", (char *)NULL);
+if (ret)
+    goto cleanup;
+ret = krb5_get_init_creds_password(context, &creds, client_princ,
+                                   password, NULL, NULL, 0, NULL, opt);
+if (ret)
+    goto cleanup;
+
+
+

To obtain realm-exposed anonymous credentials, set the anonymous flag +on the options structure as above, but specify a normal client +principal in order to prove membership in the realm. Authentication +will take place as it normally does; if successful, the client +principal of the resulting tickets will be WELLKNOWN/ANONYMOUS@realmname.

+
+
+

User interaction

+

Authenticating a user usually requires the entry of secret +information, such as a password. A password can be supplied directly +to krb5_get_init_creds_password() via the password +parameter, or the application can supply prompter and/or responder +callbacks instead. If callbacks are used, the user can also be +queried for other secret information such as a PIN, informed of +impending password expiration, or prompted to change a password which +has expired.

+
+

Prompter callback

+

A prompter callback can be specified via the prompter and data +parameters to krb5_get_init_creds_password(). The prompter +will be invoked each time the krb5 library has a question to ask or +information to present. When the prompter callback is invoked, the +banner argument (if not null) is intended to be displayed to the +user, and the questions to be answered are specified in the prompts +array. Each prompt contains a text question in the prompt field, a +hidden bit to indicate whether the answer should be hidden from +display, and a storage area for the answer in the reply field. The +callback should fill in each question’s reply->data with the +answer, up to a maximum number of reply->length bytes, and then +reset reply->length to the length of the answer.

+

A prompter callback can call krb5_get_prompt_types() to get an +array of type constants corresponding to the prompts, to get +programmatic information about the semantic meaning of the questions. +krb5_get_prompt_types() may return a null pointer if no prompt +type information is available.

+

Text-based applications can use a built-in text prompter +implementation by supplying krb5_prompter_posix() as the +prompter parameter and a null pointer as the data parameter. For +example:

+
ret = krb5_get_init_creds_password(context, &creds, client_princ,
+                                   NULL, krb5_prompter_posix, NULL, 0,
+                                   NULL, NULL);
+
+
+
+
+

Responder callback

+

A responder callback can be specified through the init_creds options +using the krb5_get_init_creds_opt_set_responder() function. +Responder callbacks can present a more sophisticated user interface +for authentication secrets. The responder callback is usually invoked +only once per authentication, with a list of questions produced by all +of the allowed preauthentication mechanisms.

+

When the responder callback is invoked, the rctx argument can be +accessed to obtain the list of questions and to answer them. The +krb5_responder_list_questions() function retrieves an array of +question types. For each question type, the +krb5_responder_get_challenge() function retrieves additional +information about the question, if applicable, and the +krb5_responder_set_answer() function sets the answer.

+

Responder question types, challenges, and answers are UTF-8 strings. +The question type is a well-known string; the meaning of the challenge +and answer depend on the question type. If an application does not +understand a question type, it cannot interpret the challenge or +provide an answer. Failing to answer a question typically results in +the prompter callback being used as a fallback.

+
+

Password question

+

The KRB5_RESPONDER_QUESTION_PASSWORD (or "password") +question type requests the user’s password. This question does not +have a challenge, and the response is simply the password string.

+
+
+

One-time password question

+

The KRB5_RESPONDER_QUESTION_OTP (or "otp") question +type requests a choice among one-time password tokens and the PIN and +value for the chosen token. The challenge and answer are JSON-encoded +strings, but an application can use convenience functions to avoid +doing any JSON processing itself.

+

The krb5_responder_otp_get_challenge() function decodes the +challenge into a krb5_responder_otp_challenge structure. The +krb5_responder_otp_set_answer() function selects one of the +token information elements from the challenge and supplies the value +and pin for that token.

+
+
+

PKINIT password or PIN question

+

The KRB5_RESPONDER_QUESTION_PKINIT (or "pkinit") question +type requests PINs for hardware devices and/or passwords for encrypted +credentials which are stored on disk, potentially also supplying +information about the state of the hardware devices. The challenge and +answer are JSON-encoded strings, but an application can use convenience +functions to avoid doing any JSON processing itself.

+

The krb5_responder_pkinit_get_challenge() function decodes the +challenges into a krb5_responder_pkinit_challenge structure. The +krb5_responder_pkinit_set_answer() function can be used to +supply the PIN or password for a particular client credential, and can +be called multiple times.

+
+
+

Example

+

Here is an example of using a responder callback:

+
static krb5_error_code
+my_responder(krb5_context context, void *data,
+             krb5_responder_context rctx)
+{
+    krb5_error_code ret;
+    krb5_responder_otp_challenge *chl;
+
+    if (krb5_responder_get_challenge(context, rctx,
+                                     KRB5_RESPONDER_QUESTION_PASSWORD)) {
+        ret = krb5_responder_set_answer(context, rctx,
+                                        KRB5_RESPONDER_QUESTION_PASSWORD,
+                                        "open sesame");
+        if (ret)
+            return ret;
+    }
+    ret = krb5_responder_otp_get_challenge(context, rctx, &chl);
+    if (ret == 0 && chl != NULL) {
+        ret = krb5_responder_otp_set_answer(context, rctx, 0, "1234",
+                                            NULL);
+        krb5_responder_otp_challenge_free(context, rctx, chl);
+        if (ret)
+            return ret;
+    }
+    return 0;
+}
+
+static krb5_error_code
+get_creds(krb5_context context, krb5_principal client_princ)
+{
+    krb5_error_code ret;
+    krb5_get_init_creds_opt *opt = NULL;
+    krb5_creds creds;
+
+    memset(&creds, 0, sizeof(creds));
+    ret = krb5_get_init_creds_opt_alloc(context, &opt);
+    if (ret)
+        goto cleanup;
+    ret = krb5_get_init_creds_opt_set_responder(context, opt, my_responder,
+                                                NULL);
+    if (ret)
+        goto cleanup;
+    ret = krb5_get_init_creds_password(context, &creds, client_princ,
+                                       NULL, NULL, NULL, 0, NULL, opt);
+
+cleanup:
+    krb5_get_init_creds_opt_free(context, opt);
+    krb5_free_cred_contents(context, &creds);
+    return ret;
+}
+
+
+
+
+
+
+

Verifying initial credentials

+

Use the function krb5_verify_init_creds() to verify initial +credentials. It takes an options structure (which can be a null +pointer). Use krb5_verify_init_creds_opt_init() to initialize +the caller-allocated options structure, and +krb5_verify_init_creds_opt_set_ap_req_nofail() to set the +“nofail” option. For example:

+
krb5_verify_init_creds_opt vopt;
+
+krb5_verify_init_creds_opt_init(&vopt);
+krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, 1);
+ret = krb5_verify_init_creds(context, &creds, NULL, NULL, NULL, &vopt);
+
+
+

The confusingly named “nofail” option, when set, means that the +verification must actually succeed in order for +krb5_verify_init_creds() to indicate success. The default +state of this option (cleared) means that if there is no key material +available to verify the user credentials, the verification will +succeed anyway. (The default can be changed by a configuration file +setting.)

+

This accommodates a use case where a large number of unkeyed shared +desktop workstations need to allow users to log in using Kerberos. +The security risks from this practice are mitigated by the absence of +valuable state on the shared workstations—any valuable resources +that the users would access reside on networked servers.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/princ_handle.html b/krb5-1.21.3/doc/html/appdev/princ_handle.html new file mode 100644 index 00000000..ec58321a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/princ_handle.html @@ -0,0 +1,162 @@ + + + + + + + + + Principal manipulation and parsing — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/index.html b/krb5-1.21.3/doc/html/appdev/refs/api/index.html new file mode 100644 index 00000000..93ee0b7d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/index.html @@ -0,0 +1,553 @@ + + + + + + + + + krb5 API — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5 API

+
+

Frequently used public interfaces

+
+ +
+
+
+

Rarely used public interfaces

+
+ +
+
+
+

Public interfaces that should not be called directly

+
+ +
+
+
+

Legacy convenience interfaces

+ +
+
+

Deprecated public interfaces

+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_425_conv_principal.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_425_conv_principal.html new file mode 100644 index 00000000..036e97f2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_425_conv_principal.html @@ -0,0 +1,162 @@ + + + + + + + + + krb5_425_conv_principal - Convert a Kerberos V4 principal to a Kerberos V5 principal. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_425_conv_principal - Convert a Kerberos V4 principal to a Kerberos V5 principal.

+
+
+krb5_error_code krb5_425_conv_principal(krb5_context context, const char *name, const char *instance, const char *realm, krb5_principal *princ)
+
+ +
+
param
+

[in] context - Library context

+

[in] name - V4 name

+

[in] instance - V4 instance

+

[in] realm - Realm

+

[out] princ - V5 principal

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function builds a princ from V4 specification based on given input name.instance@realm .

+

Use krb5_free_principal() to free princ when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_524_conv_principal.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_524_conv_principal.html new file mode 100644 index 00000000..3d67076a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_524_conv_principal.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_524_conv_principal - Convert a Kerberos V5 principal to a Kerberos V4 principal. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_524_conv_principal - Convert a Kerberos V5 principal to a Kerberos V4 principal.

+
+
+krb5_error_code krb5_524_conv_principal(krb5_context context, krb5_const_principal princ, char *name, char *inst, char *realm)
+
+ +
+
param
+

[in] context - Library context

+

[in] princ - V5 Principal

+

[out] name - V4 principal’s name to be filled in

+

[out] inst - V4 principal’s instance name to be filled in

+

[out] realm - Principal’s realm name to be filled in

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • KRB5_INVALID_PRINCIPAL Invalid principal name

  • +
  • KRB5_CONFIG_CANTOPEN Can’t open or find Kerberos configuration file

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function separates a V5 principal princ into name , instance , and realm .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_524_convert_creds.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_524_convert_creds.html new file mode 100644 index 00000000..1e0e7f03 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_524_convert_creds.html @@ -0,0 +1,162 @@ + + + + + + + + + krb5_524_convert_creds - Convert a Kerberos V5 credentials to a Kerberos V4 credentials. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_524_convert_creds - Convert a Kerberos V5 credentials to a Kerberos V4 credentials.

+
+
+int krb5_524_convert_creds(krb5_context context, krb5_creds *v5creds, struct credentials *v4creds)
+
+ +
+
param
+

context

+

v5creds

+

v4creds

+
+
+
+
retval
+
    +
  • KRB524_KRB4_DISABLED (always)

  • +
+
+
+
+

Note

+

Not implemented

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_address_compare.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_address_compare.html new file mode 100644 index 00000000..61566692 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_address_compare.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_address_compare - Compare two Kerberos addresses. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_address_compare - Compare two Kerberos addresses.

+
+
+krb5_boolean krb5_address_compare(krb5_context context, const krb5_address *addr1, const krb5_address *addr2)
+
+ +
+
param
+

[in] context - Library context

+

[in] addr1 - First address to be compared

+

[in] addr2 - Second address to be compared

+
+
+
+
return
+
    +
  • TRUE if the addresses are the same, FALSE otherwise

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_address_order.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_address_order.html new file mode 100644 index 00000000..aee5c35c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_address_order.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_address_order - Return an ordering of the specified addresses. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_address_order - Return an ordering of the specified addresses.

+
+
+int krb5_address_order(krb5_context context, const krb5_address *addr1, const krb5_address *addr2)
+
+ +
+
param
+

[in] context - Library context

+

[in] addr1 - First address

+

[in] addr2 - Second address

+
+
+
+
retval
+
    +
  • 0 if The two addresses are the same

  • +
  • < 0 First address is less than second

  • +
  • > 0 First address is greater than second

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_address_search.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_address_search.html new file mode 100644 index 00000000..842da157 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_address_search.html @@ -0,0 +1,162 @@ + + + + + + + + + krb5_address_search - Search a list of addresses for a specified address. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_address_search - Search a list of addresses for a specified address.

+
+ +
+ +
+
param
+

[in] context - Library context

+

[in] addr - Address to search for

+

[in] addrlist - Address list to be searched (or NULL)

+
+
+
+
return
+
    +
  • TRUE if addr is listed in addrlist , or addrlist is NULL; FALSE otherwise

  • +
+
+
+
+

Note

+

If addrlist contains only a NetBIOS addresses, it will be treated as a null list.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_allow_weak_crypto.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_allow_weak_crypto.html new file mode 100644 index 00000000..2f0509f5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_allow_weak_crypto.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_allow_weak_crypto - Allow the application to override the profile’s allow_weak_crypto setting. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_allow_weak_crypto - Allow the application to override the profile’s allow_weak_crypto setting.

+
+
+krb5_error_code krb5_allow_weak_crypto(krb5_context context, krb5_boolean enable)
+
+ +
+
param
+

[in] context - Library context

+

[in] enable - Boolean flag

+
+
+
+
retval
+
    +
  • 0 (always)

  • +
+
+
+

This function allows an application to override the allow_weak_crypto setting. It is primarily for use by aklog.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_aname_to_localname.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_aname_to_localname.html new file mode 100644 index 00000000..f3bd88ec --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_aname_to_localname.html @@ -0,0 +1,167 @@ + + + + + + + + + krb5_aname_to_localname - Convert a principal name to a local name. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_aname_to_localname - Convert a principal name to a local name.

+
+
+krb5_error_code krb5_aname_to_localname(krb5_context context, krb5_const_principal aname, int lnsize_in, char *lname)
+
+ +
+
param
+

[in] context - Library context

+

[in] aname - Principal name

+

[in] lnsize_in - Space available in lname

+

[out] lname - Local name buffer to be filled in

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • System errors

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

If aname does not correspond to any local account, KRB5_LNAME_NOTRANS is returned. If lnsize_in is too small for the local name, KRB5_CONFIG_NOTENUFSPACE is returned.

+

Local names, rather than principal names, can be used by programs that translate to an environment-specific name (for example, a user account name).

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_anonymous_principal.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_anonymous_principal.html new file mode 100644 index 00000000..43176b16 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_anonymous_principal.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_anonymous_principal - Build an anonymous principal. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_anonymous_realm.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_anonymous_realm.html new file mode 100644 index 00000000..912343ef --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_anonymous_realm.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_anonymous_realm - Return an anonymous realm data. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_appdefault_boolean.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_appdefault_boolean.html new file mode 100644 index 00000000..1d669d84 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_appdefault_boolean.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_appdefault_boolean - Retrieve a boolean value from the appdefaults section of krb5.conf. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_appdefault_boolean - Retrieve a boolean value from the appdefaults section of krb5.conf.

+
+
+void krb5_appdefault_boolean(krb5_context context, const char *appname, const krb5_data *realm, const char *option, int default_value, int *ret_value)
+
+ +
+
param
+

[in] context - Library context

+

[in] appname - Application name

+

[in] realm - Realm name

+

[in] option - Option to be checked

+

[in] default_value - Default value to return if no match is found

+

[out] ret_value - Boolean value of option

+
+
+

This function gets the application defaults for option based on the given appname and/or realm .

+
+

See also

+

krb5_appdefault_string()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_appdefault_string.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_appdefault_string.html new file mode 100644 index 00000000..c3c9e8a9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_appdefault_string.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_appdefault_string - Retrieve a string value from the appdefaults section of krb5.conf. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_appdefault_string - Retrieve a string value from the appdefaults section of krb5.conf.

+
+
+void krb5_appdefault_string(krb5_context context, const char *appname, const krb5_data *realm, const char *option, const char *default_value, char **ret_value)
+
+ +
+
param
+

[in] context - Library context

+

[in] appname - Application name

+

[in] realm - Realm name

+

[in] option - Option to be checked

+

[in] default_value - Default value to return if no match is found

+

[out] ret_value - String value of option

+
+
+

This function gets the application defaults for option based on the given appname and/or realm .

+
+

See also

+

krb5_appdefault_boolean()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_free.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_free.html new file mode 100644 index 00000000..b7aed116 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_free.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_auth_con_free - Free a krb5_auth_context structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_free - Free a krb5_auth_context structure.

+
+
+krb5_error_code krb5_auth_con_free(krb5_context context, krb5_auth_context auth_context)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context to be freed

+
+
+
+
retval
+
    +
  • 0 (always)

  • +
+
+
+

This function frees an auth context allocated by krb5_auth_con_init().

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_genaddrs.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_genaddrs.html new file mode 100644 index 00000000..2d99915c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_genaddrs.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_auth_con_genaddrs - Generate auth context addresses from a connected socket. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_genaddrs - Generate auth context addresses from a connected socket.

+
+
+krb5_error_code krb5_auth_con_genaddrs(krb5_context context, krb5_auth_context auth_context, int infd, int flags)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] infd - Connected socket descriptor

+

[in] flags - Flags

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function sets the local and/or remote addresses in auth_context based on the local and remote endpoints of the socket infd . The following flags determine the operations performed:

+
+
    +
  • #KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR Generate local address.

  • +
  • #KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR Generate remote address.

  • +
  • #KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR Generate local address and port.

  • +
  • #KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR Generate remote address and port.

  • +
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_get_checksum_func.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_get_checksum_func.html new file mode 100644 index 00000000..ed6064b3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_get_checksum_func.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_get_checksum_func - Get the checksum callback from an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_get_checksum_func - Get the checksum callback from an auth context.

+
+
+krb5_error_code krb5_auth_con_get_checksum_func(krb5_context context, krb5_auth_context auth_context, krb5_mk_req_checksum_func *func, void **data)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[out] func - Checksum callback

+

[out] data - Callback argument

+
+
+
+
retval
+
    +
  • 0 (always)

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getaddrs.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getaddrs.html new file mode 100644 index 00000000..6815e293 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getaddrs.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_getaddrs - Retrieve address fields from an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_getaddrs - Retrieve address fields from an auth context.

+
+
+krb5_error_code krb5_auth_con_getaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address **local_addr, krb5_address **remote_addr)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[out] local_addr - Local address (NULL if not needed)

+

[out] remote_addr - Remote address (NULL if not needed)

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getauthenticator.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getauthenticator.html new file mode 100644 index 00000000..55c82200 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getauthenticator.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_getauthenticator - Retrieve the authenticator from an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_getauthenticator - Retrieve the authenticator from an auth context.

+
+
+krb5_error_code krb5_auth_con_getauthenticator(krb5_context context, krb5_auth_context auth_context, krb5_authenticator **authenticator)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[out] authenticator - Authenticator

+
+
+
+
retval
+
    +
  • 0 Success. Otherwise - Kerberos error codes

  • +
+
+
+

Use krb5_free_authenticator() to free authenticator when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getflags.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getflags.html new file mode 100644 index 00000000..45879ca4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getflags.html @@ -0,0 +1,167 @@ + + + + + + + + + krb5_auth_con_getflags - Retrieve flags from a krb5_auth_context structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_getflags - Retrieve flags from a krb5_auth_context structure.

+
+
+krb5_error_code krb5_auth_con_getflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 *flags)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[out] flags - Flags bit mask

+
+
+
+
retval
+
    +
  • 0 (always)

  • +
+
+
+

Valid values for flags are:

+
+
    +
  • #KRB5_AUTH_CONTEXT_DO_TIME Use timestamps

  • +
  • #KRB5_AUTH_CONTEXT_RET_TIME Save timestamps

  • +
  • #KRB5_AUTH_CONTEXT_DO_SEQUENCE Use sequence numbers

  • +
  • #KRB5_AUTH_CONTEXT_RET_SEQUENCE Save sequence numbers

  • +
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getkey.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getkey.html new file mode 100644 index 00000000..0e3216b7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getkey.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_getkey - Retrieve the session key from an auth context as a keyblock. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_getkey - Retrieve the session key from an auth context as a keyblock.

+
+
+krb5_error_code krb5_auth_con_getkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[out] keyblock - Session key

+
+
+
+
retval
+
    +
  • 0 Success. Otherwise - Kerberos error codes

  • +
+
+
+

This function creates a keyblock containing the session key from auth_context . Use krb5_free_keyblock() to free keyblock when it is no longer needed

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getkey_k.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getkey_k.html new file mode 100644 index 00000000..9a00fefe --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getkey_k.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_getkey_k - Retrieve the session key from an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_getkey_k - Retrieve the session key from an auth context.

+
+
+krb5_error_code krb5_auth_con_getkey_k(krb5_context context, krb5_auth_context auth_context, krb5_key *key)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[out] key - Session key

+
+
+
+
retval
+
    +
  • 0 (always)

  • +
+
+
+

This function sets key to the session key from auth_context . Use krb5_k_free_key() to release key when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getlocalseqnumber.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getlocalseqnumber.html new file mode 100644 index 00000000..441299c5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getlocalseqnumber.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_getlocalseqnumber - Retrieve the local sequence number from an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_getlocalseqnumber - Retrieve the local sequence number from an auth context.

+
+
+krb5_error_code krb5_auth_con_getlocalseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[out] seqnumber - Local sequence number

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Retrieve the local sequence number from auth_context and return it in seqnumber . The #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag must be set in auth_context for this function to be useful.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getlocalsubkey.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getlocalsubkey.html new file mode 100644 index 00000000..dc0b5fe7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getlocalsubkey.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_auth_con_getlocalsubkey — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getrcache.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getrcache.html new file mode 100644 index 00000000..0d432a5e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getrcache.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_getrcache - Retrieve the replay cache from an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_getrcache - Retrieve the replay cache from an auth context.

+
+
+krb5_error_code krb5_auth_con_getrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache *rcache)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[out] rcache - Replay cache handle

+
+
+
+
retval
+
    +
  • 0 (always)

  • +
+
+
+

This function fetches the replay cache from auth_context . The caller should not close rcache .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getrecvsubkey.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getrecvsubkey.html new file mode 100644 index 00000000..38304c09 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getrecvsubkey.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_getrecvsubkey - Retrieve the receiving subkey from an auth context as a keyblock. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_getrecvsubkey - Retrieve the receiving subkey from an auth context as a keyblock.

+
+
+krb5_error_code krb5_auth_con_getrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] ac - Authentication context

+

[out] keyblock - Receiving subkey

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a keyblock containing the receiving subkey from auth_context . Use krb5_free_keyblock() to free keyblock when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getrecvsubkey_k.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getrecvsubkey_k.html new file mode 100644 index 00000000..112ea8c6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getrecvsubkey_k.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_getrecvsubkey_k - Retrieve the receiving subkey from an auth context as a keyblock. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_getrecvsubkey_k - Retrieve the receiving subkey from an auth context as a keyblock.

+
+
+krb5_error_code krb5_auth_con_getrecvsubkey_k(krb5_context ctx, krb5_auth_context ac, krb5_key *key)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] ac - Authentication context

+

[out] key - Receiving subkey

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function sets key to the receiving subkey from auth_context . Use krb5_k_free_key() to release key when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getremoteseqnumber.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getremoteseqnumber.html new file mode 100644 index 00000000..60c5a7d0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getremoteseqnumber.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_getremoteseqnumber - Retrieve the remote sequence number from an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_getremoteseqnumber - Retrieve the remote sequence number from an auth context.

+
+
+krb5_error_code krb5_auth_con_getremoteseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[out] seqnumber - Remote sequence number

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Retrieve the remote sequence number from auth_context and return it in seqnumber . The #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag must be set in auth_context for this function to be useful.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getremotesubkey.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getremotesubkey.html new file mode 100644 index 00000000..76c1d128 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getremotesubkey.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_auth_con_getremotesubkey — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getsendsubkey.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getsendsubkey.html new file mode 100644 index 00000000..efeeb3be --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getsendsubkey.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_getsendsubkey - Retrieve the send subkey from an auth context as a keyblock. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_getsendsubkey - Retrieve the send subkey from an auth context as a keyblock.

+
+
+krb5_error_code krb5_auth_con_getsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] ac - Authentication context

+

[out] keyblock - Send subkey

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a keyblock containing the send subkey from auth_context . Use krb5_free_keyblock() to free keyblock when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getsendsubkey_k.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getsendsubkey_k.html new file mode 100644 index 00000000..ddbc602b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_getsendsubkey_k.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_getsendsubkey_k - Retrieve the send subkey from an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_getsendsubkey_k - Retrieve the send subkey from an auth context.

+
+
+krb5_error_code krb5_auth_con_getsendsubkey_k(krb5_context ctx, krb5_auth_context ac, krb5_key *key)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] ac - Authentication context

+

[out] key - Send subkey

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function sets key to the send subkey from auth_context . Use krb5_k_free_key() to release key when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_init.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_init.html new file mode 100644 index 00000000..69cffb3e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_init.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_auth_con_init - Create and initialize an authentication context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_init - Create and initialize an authentication context.

+
+
+krb5_error_code krb5_auth_con_init(krb5_context context, krb5_auth_context *auth_context)
+
+ +
+
param
+

[in] context - Library context

+

[out] auth_context - Authentication context

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates an authentication context to hold configuration and state relevant to krb5 functions for authenticating principals and protecting messages once authentication has occurred.

+

By default, flags for the context are set to enable the use of the replay cache (#KRB5_AUTH_CONTEXT_DO_TIME), but not sequence numbers. Use krb5_auth_con_setflags() to change the flags.

+

The allocated auth_context must be freed with krb5_auth_con_free() when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_initivector.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_initivector.html new file mode 100644 index 00000000..03000f72 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_initivector.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_auth_con_initivector - Cause an auth context to use cipher state. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_initivector - Cause an auth context to use cipher state.

+
+
+krb5_error_code krb5_auth_con_initivector(krb5_context context, krb5_auth_context auth_context)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Prepare auth_context to use cipher state when krb5_mk_priv() or krb5_rd_priv() encrypt or decrypt data.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_set_checksum_func.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_set_checksum_func.html new file mode 100644 index 00000000..f6bdfdbe --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_set_checksum_func.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_auth_con_set_checksum_func - Set a checksum callback in an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_set_checksum_func - Set a checksum callback in an auth context.

+
+
+krb5_error_code krb5_auth_con_set_checksum_func(krb5_context context, krb5_auth_context auth_context, krb5_mk_req_checksum_func func, void *data)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] func - Checksum callback

+

[in] data - Callback argument

+
+
+
+
retval
+
    +
  • 0 (always)

  • +
+
+
+

Set a callback to obtain checksum data in krb5_mk_req(). The callback will be invoked after the subkey and local sequence number are stored in auth_context .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_set_req_cksumtype.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_set_req_cksumtype.html new file mode 100644 index 00000000..267309de --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_set_req_cksumtype.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_set_req_cksumtype - Set checksum type in an an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_set_req_cksumtype - Set checksum type in an an auth context.

+
+
+krb5_error_code krb5_auth_con_set_req_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] cksumtype - Checksum type

+
+
+
+
retval
+
    +
  • 0 Success. Otherwise - Kerberos error codes

  • +
+
+
+

This function sets the checksum type in auth_context to be used by krb5_mk_req() for the authenticator checksum.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setaddrs.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setaddrs.html new file mode 100644 index 00000000..bc62882c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setaddrs.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_auth_con_setaddrs - Set the local and remote addresses in an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_setaddrs - Set the local and remote addresses in an auth context.

+
+
+krb5_error_code krb5_auth_con_setaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address *local_addr, krb5_address *remote_addr)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] local_addr - Local address

+

[in] remote_addr - Remote address

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function releases the storage assigned to the contents of the local and remote addresses of auth_context and then sets them to local_addr and remote_addr respectively.

+
+

See also

+

krb5_auth_con_genaddrs()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setflags.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setflags.html new file mode 100644 index 00000000..98f5ed54 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setflags.html @@ -0,0 +1,167 @@ + + + + + + + + + krb5_auth_con_setflags - Set a flags field in a krb5_auth_context structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_setflags - Set a flags field in a krb5_auth_context structure.

+
+
+krb5_error_code krb5_auth_con_setflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 flags)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] flags - Flags bit mask

+
+
+
+
retval
+
    +
  • 0 (always)

  • +
+
+
+

Valid values for flags are:

+
+
    +
  • #KRB5_AUTH_CONTEXT_DO_TIME Use timestamps

  • +
  • #KRB5_AUTH_CONTEXT_RET_TIME Save timestamps

  • +
  • #KRB5_AUTH_CONTEXT_DO_SEQUENCE Use sequence numbers

  • +
  • #KRB5_AUTH_CONTEXT_RET_SEQUENCE Save sequence numbers

  • +
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setports.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setports.html new file mode 100644 index 00000000..6a28f812 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setports.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_auth_con_setports - Set local and remote port fields in an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_setports - Set local and remote port fields in an auth context.

+
+
+krb5_error_code krb5_auth_con_setports(krb5_context context, krb5_auth_context auth_context, krb5_address *local_port, krb5_address *remote_port)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] local_port - Local port

+

[in] remote_port - Remote port

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function releases the storage assigned to the contents of the local and remote ports of auth_context and then sets them to local_port and remote_port respectively.

+
+

See also

+

krb5_auth_con_genaddrs()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setrcache.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setrcache.html new file mode 100644 index 00000000..a0654219 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setrcache.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_setrcache - Set the replay cache in an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_setrcache - Set the replay cache in an auth context.

+
+
+krb5_error_code krb5_auth_con_setrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache rcache)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] rcache - Replay cache haddle

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function sets the replay cache in auth_context to rcache . rcache will be closed when auth_context is freed, so the caller should relinquish that responsibility.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setrecvsubkey.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setrecvsubkey.html new file mode 100644 index 00000000..9236396b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setrecvsubkey.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_setrecvsubkey - Set the receiving subkey in an auth context with a keyblock. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_setrecvsubkey - Set the receiving subkey in an auth context with a keyblock.

+
+
+krb5_error_code krb5_auth_con_setrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock *keyblock)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] ac - Authentication context

+

[in] keyblock - Receiving subkey

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function sets the receiving subkey in ac to a copy of keyblock .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setrecvsubkey_k.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setrecvsubkey_k.html new file mode 100644 index 00000000..1f59b660 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setrecvsubkey_k.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_auth_con_setrecvsubkey_k - Set the receiving subkey in an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_setrecvsubkey_k - Set the receiving subkey in an auth context.

+
+
+krb5_error_code krb5_auth_con_setrecvsubkey_k(krb5_context ctx, krb5_auth_context ac, krb5_key key)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] ac - Authentication context

+

[in] key - Receiving subkey

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function sets the receiving subkey in ac to key , incrementing its reference count.

+
+

Note

+

New in 1.9

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setsendsubkey.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setsendsubkey.html new file mode 100644 index 00000000..6c2fe8e3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setsendsubkey.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_auth_con_setsendsubkey - Set the send subkey in an auth context with a keyblock. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_setsendsubkey - Set the send subkey in an auth context with a keyblock.

+
+
+krb5_error_code krb5_auth_con_setsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock *keyblock)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] ac - Authentication context

+

[in] keyblock - Send subkey

+
+
+
+
retval
+
    +
  • 0 Success. Otherwise - Kerberos error codes

  • +
+
+
+

This function sets the send subkey in ac to a copy of keyblock .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setsendsubkey_k.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setsendsubkey_k.html new file mode 100644 index 00000000..4047613f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setsendsubkey_k.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_auth_con_setsendsubkey_k - Set the send subkey in an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_setsendsubkey_k - Set the send subkey in an auth context.

+
+
+krb5_error_code krb5_auth_con_setsendsubkey_k(krb5_context ctx, krb5_auth_context ac, krb5_key key)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] ac - Authentication context

+

[out] key - Send subkey

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function sets the send subkey in ac to key , incrementing its reference count.

+
+

Note

+

New in 1.9

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setuseruserkey.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setuseruserkey.html new file mode 100644 index 00000000..a7929a2a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_auth_con_setuseruserkey.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_auth_con_setuseruserkey - Set the session key in an auth context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_auth_con_setuseruserkey - Set the session key in an auth context.

+
+
+krb5_error_code krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] keyblock - User key

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal.html new file mode 100644 index 00000000..93c490cc --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal.html @@ -0,0 +1,170 @@ + + + + + + + + + krb5_build_principal - Build a principal name using null-terminated strings. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_build_principal - Build a principal name using null-terminated strings.

+
+
+krb5_error_code krb5_build_principal(krb5_context context, krb5_principal *princ, unsigned int rlen, const char *realm, ...)
+
+ +
+
param
+

[in] context - Library context

+

[out] princ - Principal name

+

[in] rlen - Realm name length

+

[in] realm - Realm name

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Call krb5_free_principal() to free princ when it is no longer needed.

+

Beginning with release 1.20, the name type of the principal will be inferred as KRB5_NT_SRV_INST or KRB5_NT_WELLKNOWN based on the principal name. The type will be KRB5_NT_PRINCIPAL if a type cannot be inferred.

+
+

Note

+

krb5_build_principal() and krb5_build_principal_alloc_va() perform the same task. krb5_build_principal() takes variadic arguments. krb5_build_principal_alloc_va() takes a pre-computed varargs pointer.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal_alloc_va.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal_alloc_va.html new file mode 100644 index 00000000..ba3999b4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal_alloc_va.html @@ -0,0 +1,167 @@ + + + + + + + + + krb5_build_principal_alloc_va - Build a principal name, using a precomputed variable argument list. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_build_principal_alloc_va - Build a principal name, using a precomputed variable argument list.

+
+
+krb5_error_code krb5_build_principal_alloc_va(krb5_context context, krb5_principal *princ, unsigned int rlen, const char *realm, va_list ap)
+
+ +
+
param
+

[in] context - Library context

+

[out] princ - Principal structure

+

[in] rlen - Realm name length

+

[in] realm - Realm name

+

[in] ap - List of char * components, ending with NULL

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Similar to krb5_build_principal(), this function builds a principal name, but its name components are specified as a va_list.

+

Use krb5_free_principal() to deallocate princ when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal_ext.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal_ext.html new file mode 100644 index 00000000..ec469c6e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal_ext.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_build_principal_ext - Build a principal name using length-counted strings. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_build_principal_ext - Build a principal name using length-counted strings.

+
+
+krb5_error_code krb5_build_principal_ext(krb5_context context, krb5_principal *princ, unsigned int rlen, const char *realm, ...)
+
+ +
+
param
+

[in] context - Library context

+

[out] princ - Principal name

+

[in] rlen - Realm name length

+

[in] realm - Realm name

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function creates a principal from a length-counted string and a variable-length list of length-counted components. The list of components ends with the first 0 length argument (so it is not possible to specify an empty component with this function). Call krb5_free_principal() to free allocated memory for principal when it is no longer needed.

+

Beginning with release 1.20, the name type of the principal will be inferred as KRB5_NT_SRV_INST or KRB5_NT_WELLKNOWN based on the principal name. The type will be KRB5_NT_PRINCIPAL if a type cannot be inferred.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal_va.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal_va.html new file mode 100644 index 00000000..bf55bd2c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_build_principal_va.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_build_principal_va — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_block_size.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_block_size.html new file mode 100644 index 00000000..437bfc76 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_block_size.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_c_block_size - Return cipher block size. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_block_size - Return cipher block size.

+
+
+krb5_error_code krb5_c_block_size(krb5_context context, krb5_enctype enctype, size_t *blocksize)
+
+ +
+
param
+

[in] context - Library context

+

[in] enctype - Encryption type

+

[out] blocksize - Block size for enctype

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_checksum_length.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_checksum_length.html new file mode 100644 index 00000000..6b78619f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_checksum_length.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_c_checksum_length - Return the length of checksums for a checksum type. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_checksum_length - Return the length of checksums for a checksum type.

+
+
+krb5_error_code krb5_c_checksum_length(krb5_context context, krb5_cksumtype cksumtype, size_t *length)
+
+ +
+
param
+

[in] context - Library context

+

[in] cksumtype - Checksum type

+

[out] length - Checksum length

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_crypto_length.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_crypto_length.html new file mode 100644 index 00000000..aaf59923 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_crypto_length.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_c_crypto_length - Return a length of a message field specific to the encryption type. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_crypto_length - Return a length of a message field specific to the encryption type.

+
+
+krb5_error_code krb5_c_crypto_length(krb5_context context, krb5_enctype enctype, krb5_cryptotype type, unsigned int *size)
+
+ +
+
param
+

[in] context - Library context

+

[in] enctype - Encryption type

+

[in] type - Type field (See KRB5_CRYPTO_TYPE macros)

+

[out] size - Length of the type specific to enctype

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_crypto_length_iov.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_crypto_length_iov.html new file mode 100644 index 00000000..cc75f56e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_crypto_length_iov.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_c_crypto_length_iov - Fill in lengths for header, trailer and padding in a IOV array. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_crypto_length_iov - Fill in lengths for header, trailer and padding in a IOV array.

+
+
+krb5_error_code krb5_c_crypto_length_iov(krb5_context context, krb5_enctype enctype, krb5_crypto_iov *data, size_t num_data)
+
+ +
+
param
+

[in] context - Library context

+

[in] enctype - Encryption type

+

[inout] data - IOV array

+

[in] num_data - Size of data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Padding is set to the actual padding required based on the provided data buffers. Typically this API is used after setting up the data buffers and #KRB5_CRYPTO_TYPE_SIGN_ONLY buffers, but before actually allocating header, trailer and padding.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_decrypt.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_decrypt.html new file mode 100644 index 00000000..e9a33ab6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_decrypt.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_c_decrypt - Decrypt data using a key (operates on keyblock). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_decrypt - Decrypt data using a key (operates on keyblock).

+
+
+krb5_error_code krb5_c_decrypt(krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *cipher_state, const krb5_enc_data *input, krb5_data *output)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Encryption key

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[inout] cipher_state - Cipher state; specify NULL if not needed

+

[in] input - Encrypted data

+

[out] output - Decrypted data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function decrypts the data block input and stores the output into output . The actual decryption key will be derived from key and usage if key derivation is specified for the encryption type. If non-null, cipher_state specifies the beginning state for the decryption operation, and is updated with the state to be passed as input to the next operation.

+
+

Note

+

The caller must initialize output and allocate at least enough space for the result. The usual practice is to allocate an output buffer as long as the ciphertext, and let krb5_c_decrypt() trim output->length . For some enctypes, the resulting output->length may include padding bytes.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_decrypt_iov.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_decrypt_iov.html new file mode 100644 index 00000000..f8133269 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_decrypt_iov.html @@ -0,0 +1,170 @@ + + + + + + + + + krb5_c_decrypt_iov - Decrypt data in place supporting AEAD (operates on keyblock). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_decrypt_iov - Decrypt data in place supporting AEAD (operates on keyblock).

+
+
+krb5_error_code krb5_c_decrypt_iov(krb5_context context, const krb5_keyblock *keyblock, krb5_keyusage usage, const krb5_data *cipher_state, krb5_crypto_iov *data, size_t num_data)
+
+ +
+
param
+

[in] context - Library context

+

[in] keyblock - Encryption key

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[in] cipher_state - Cipher state; specify NULL if not needed

+

[inout] data - IOV array. Modified in-place.

+

[in] num_data - Size of data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function decrypts the data block data and stores the output in-place. The actual decryption key will be derived from keyblock and usage if key derivation is specified for the encryption type. If non-null, cipher_state specifies the beginning state for the decryption operation, and is updated with the state to be passed as input to the next operation. The caller must allocate the right number of krb5_crypto_iov structures before calling into this API.

+
+

See also

+

krb5_c_decrypt_iov()

+
+
+

Note

+

On return from a krb5_c_decrypt_iov() call, the data->length in the iov structure are adjusted to reflect actual lengths of the ciphertext used. For example, if the padding length is too large, the length will be reduced. Lengths are never increased.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_derive_prfplus.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_derive_prfplus.html new file mode 100644 index 00000000..302dcb75 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_derive_prfplus.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_c_derive_prfplus - Derive a key using some input data (via RFC 6113 PRF+). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_derive_prfplus - Derive a key using some input data (via RFC 6113 PRF+).

+
+
+krb5_error_code krb5_c_derive_prfplus(krb5_context context, const krb5_keyblock *k, const krb5_data *input, krb5_enctype enctype, krb5_keyblock **out)
+
+ +
+
param
+

[in] context - Library context

+

[in] k - KDC contribution key

+

[in] input - Input string

+

[in] enctype - Output key enctype (or ENCTYPE_NULL )

+

[out] out - Derived keyblock

+
+
+

This function uses PRF+ as defined in RFC 6113 to derive a key from another key and an input string. If enctype is ENCTYPE_NULL , the output key will have the same enctype as the input key.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_encrypt.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_encrypt.html new file mode 100644 index 00000000..bb448ade --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_encrypt.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_c_encrypt - Encrypt data using a key (operates on keyblock). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_encrypt - Encrypt data using a key (operates on keyblock).

+
+
+krb5_error_code krb5_c_encrypt(krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *cipher_state, const krb5_data *input, krb5_enc_data *output)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Encryption key

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[inout] cipher_state - Cipher state; specify NULL if not needed

+

[in] input - Data to be encrypted

+

[out] output - Encrypted data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function encrypts the data block input and stores the outputinto output . The actual encryption key will be derived from key and usage if key derivation is specified for the encryption type. If non-null, cipher_state specifies the beginning state for the encryption operation, and is updated with the state to be passed as input to the next operation.

+
+

Note

+

The caller must initialize output and allocate at least enough space for the result (using krb5_c_encrypt_length() to determine the amount of space needed). output->length will be set to the actual length of the ciphertext.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_encrypt_iov.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_encrypt_iov.html new file mode 100644 index 00000000..b5dde9b8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_encrypt_iov.html @@ -0,0 +1,170 @@ + + + + + + + + + krb5_c_encrypt_iov - Encrypt data in place supporting AEAD (operates on keyblock). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_encrypt_iov - Encrypt data in place supporting AEAD (operates on keyblock).

+
+
+krb5_error_code krb5_c_encrypt_iov(krb5_context context, const krb5_keyblock *keyblock, krb5_keyusage usage, const krb5_data *cipher_state, krb5_crypto_iov *data, size_t num_data)
+
+ +
+
param
+

[in] context - Library context

+

[in] keyblock - Encryption key

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[in] cipher_state - Cipher state; specify NULL if not needed

+

[inout] data - IOV array. Modified in-place.

+

[in] num_data - Size of data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function encrypts the data block data and stores the output in-place. The actual encryption key will be derived from keyblock and usage if key derivation is specified for the encryption type. If non-null, cipher_state specifies the beginning state for the encryption operation, and is updated with the state to be passed as input to the next operation. The caller must allocate the right number of krb5_crypto_iov structures before calling into this API.

+
+

See also

+

krb5_c_decrypt_iov()

+
+
+

Note

+

On return from a krb5_c_encrypt_iov() call, the data->length in the iov structure are adjusted to reflect actual lengths of the ciphertext used. For example, if the padding length is too large, the length will be reduced. Lengths are never increased.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_encrypt_length.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_encrypt_length.html new file mode 100644 index 00000000..674be48e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_encrypt_length.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_c_encrypt_length - Compute encrypted data length. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_encrypt_length - Compute encrypted data length.

+
+
+krb5_error_code krb5_c_encrypt_length(krb5_context context, krb5_enctype enctype, size_t inputlen, size_t *length)
+
+ +
+
param
+

[in] context - Library context

+

[in] enctype - Encryption type

+

[in] inputlen - Length of the data to be encrypted

+

[out] length - Length of the encrypted data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function computes the length of the ciphertext produced by encrypting inputlen bytes including padding, confounder, and checksum.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_enctype_compare.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_enctype_compare.html new file mode 100644 index 00000000..37c63a9b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_enctype_compare.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_c_enctype_compare - Compare two encryption types. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_enctype_compare - Compare two encryption types.

+
+
+krb5_error_code krb5_c_enctype_compare(krb5_context context, krb5_enctype e1, krb5_enctype e2, krb5_boolean *similar)
+
+ +
+
param
+

[in] context - Library context

+

[in] e1 - First encryption type

+

[in] e2 - Second encryption type

+

[out] similar - TRUE if types are similar, FALSE if not

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function determines whether two encryption types use the same kind of keys.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_free_state.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_free_state.html new file mode 100644 index 00000000..fea85338 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_free_state.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_c_free_state - Free a cipher state previously allocated by krb5_c_init_state(). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_free_state - Free a cipher state previously allocated by krb5_c_init_state().

+
+
+krb5_error_code krb5_c_free_state(krb5_context context, const krb5_keyblock *key, krb5_data *state)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Key

+

[in] state - Cipher state to be freed

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_fx_cf2_simple.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_fx_cf2_simple.html new file mode 100644 index 00000000..165828e8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_fx_cf2_simple.html @@ -0,0 +1,162 @@ + + + + + + + + + krb5_c_fx_cf2_simple - Compute the KRB-FX-CF2 combination of two keys and pepper strings. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_fx_cf2_simple - Compute the KRB-FX-CF2 combination of two keys and pepper strings.

+
+
+krb5_error_code krb5_c_fx_cf2_simple(krb5_context context, const krb5_keyblock *k1, const char *pepper1, const krb5_keyblock *k2, const char *pepper2, krb5_keyblock **out)
+
+ +
+
param
+

[in] context - Library context

+

[in] k1 - KDC contribution key

+

[in] pepper1 - String”PKINIT”

+

[in] k2 - Reply key

+

[in] pepper2 - String”KeyExchange”

+

[out] out - Output key

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function computes the KRB-FX-CF2 function over its inputs and places the results in a newly allocated keyblock. This function is simple in that it assumes that pepper1 and pepper2 are C strings with no internal nulls and that the enctype of the result will be the same as that of k1 . k1 and k2 may be of different enctypes.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_init_state.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_init_state.html new file mode 100644 index 00000000..7b7d4122 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_init_state.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_c_init_state - Initialize a new cipher state. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_init_state - Initialize a new cipher state.

+
+
+krb5_error_code krb5_c_init_state(krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, krb5_data *new_state)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Key

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[out] new_state - New cipher state

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_is_coll_proof_cksum.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_is_coll_proof_cksum.html new file mode 100644 index 00000000..c00941b0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_is_coll_proof_cksum.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_c_is_coll_proof_cksum - Test whether a checksum type is collision-proof. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_is_coll_proof_cksum - Test whether a checksum type is collision-proof.

+
+
+krb5_boolean krb5_c_is_coll_proof_cksum(krb5_cksumtype ctype)
+
+ +
+
param
+

[in] ctype - Checksum type

+
+
+
+
return
+
    +
  • TRUE if ctype is collision-proof, FALSE if it is not collision-proof or not a valid checksum type.

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_is_keyed_cksum.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_is_keyed_cksum.html new file mode 100644 index 00000000..9cbc6281 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_is_keyed_cksum.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_c_is_keyed_cksum - Test whether a checksum type is keyed. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_keyed_checksum_types.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_keyed_checksum_types.html new file mode 100644 index 00000000..a4223002 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_keyed_checksum_types.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_c_keyed_checksum_types - Return a list of keyed checksum types usable with an encryption type. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_keyed_checksum_types - Return a list of keyed checksum types usable with an encryption type.

+
+
+krb5_error_code krb5_c_keyed_checksum_types(krb5_context context, krb5_enctype enctype, unsigned int *count, krb5_cksumtype **cksumtypes)
+
+ +
+
param
+

[in] context - Library context

+

[in] enctype - Encryption type

+

[out] count - Count of allowable checksum types

+

[out] cksumtypes - Array of allowable checksum types

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Use krb5_free_cksumtypes() to free cksumtypes when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_keylengths.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_keylengths.html new file mode 100644 index 00000000..240fa83c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_keylengths.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_c_keylengths - Return length of the specified key in bytes. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_keylengths - Return length of the specified key in bytes.

+
+
+krb5_error_code krb5_c_keylengths(krb5_context context, krb5_enctype enctype, size_t *keybytes, size_t *keylength)
+
+ +
+
param
+

[in] context - Library context

+

[in] enctype - Encryption type

+

[out] keybytes - Number of bytes required to make a key

+

[out] keylength - Length of final key

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_make_checksum.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_make_checksum.html new file mode 100644 index 00000000..ffdde623 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_make_checksum.html @@ -0,0 +1,170 @@ + + + + + + + + + krb5_c_make_checksum - Compute a checksum (operates on keyblock). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_make_checksum - Compute a checksum (operates on keyblock).

+
+
+krb5_error_code krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *input, krb5_checksum *cksum)
+
+ +
+
param
+

[in] context - Library context

+

[in] cksumtype - Checksum type (0 for mandatory type)

+

[in] key - Encryption key for a keyed checksum

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[in] input - Input data

+

[out] cksum - Generated checksum

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function computes a checksum of type cksumtype over input , using key if the checksum type is a keyed checksum. If cksumtype is 0 and key is non-null, the checksum type will be the mandatory-to-implement checksum type for the key’s encryption type. The actual checksum key will be derived from key and usage if key derivation is specified for the checksum type. The newly created cksum must be released by calling krb5_free_checksum_contents() when it is no longer needed.

+
+

See also

+

krb5_c_verify_checksum()

+
+
+

Note

+

This function is similar to krb5_k_make_checksum(), but operates on keyblock key .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_make_checksum_iov.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_make_checksum_iov.html new file mode 100644 index 00000000..d9b1341f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_make_checksum_iov.html @@ -0,0 +1,170 @@ + + + + + + + + + krb5_c_make_checksum_iov - Fill in a checksum element in IOV array (operates on keyblock) — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_make_checksum_iov - Fill in a checksum element in IOV array (operates on keyblock)

+
+
+krb5_error_code krb5_c_make_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, const krb5_keyblock *key, krb5_keyusage usage, krb5_crypto_iov *data, size_t num_data)
+
+ +
+
param
+

[in] context - Library context

+

[in] cksumtype - Checksum type (0 for mandatory type)

+

[in] key - Encryption key for a keyed checksum

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[inout] data - IOV array

+

[in] num_data - Size of data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Create a checksum in the #KRB5_CRYPTO_TYPE_CHECKSUM element over #KRB5_CRYPTO_TYPE_DATA and #KRB5_CRYPTO_TYPE_SIGN_ONLY chunks in data . Only the #KRB5_CRYPTO_TYPE_CHECKSUM region is modified.

+
+

See also

+

krb5_c_verify_checksum_iov()

+
+
+

Note

+

This function is similar to krb5_k_make_checksum_iov(), but operates on keyblock key .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_make_random_key.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_make_random_key.html new file mode 100644 index 00000000..3ad46d16 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_make_random_key.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_c_make_random_key - Generate an enctype-specific random encryption key. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_make_random_key - Generate an enctype-specific random encryption key.

+
+
+krb5_error_code krb5_c_make_random_key(krb5_context context, krb5_enctype enctype, krb5_keyblock *k5_random_key)
+
+ +
+
param
+

[in] context - Library context

+

[in] enctype - Encryption type of the generated key

+

[out] k5_random_key - An allocated and initialized keyblock

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Use krb5_free_keyblock_contents() to free k5_random_key when no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_padding_length.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_padding_length.html new file mode 100644 index 00000000..0efa8703 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_padding_length.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_c_padding_length - Return a number of padding octets. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_padding_length - Return a number of padding octets.

+
+
+krb5_error_code krb5_c_padding_length(krb5_context context, krb5_enctype enctype, size_t data_length, unsigned int *size)
+
+ +
+
param
+

[in] context - Library context

+

[in] enctype - Encryption type

+

[in] data_length - Length of the plaintext to pad

+

[out] size - Number of padding octets

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - KRB5_BAD_ENCTYPE

  • +
+
+
+

This function returns the number of the padding octets required to pad data_length octets of plaintext.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_prf.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_prf.html new file mode 100644 index 00000000..656241f4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_prf.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_c_prf - Generate enctype-specific pseudo-random bytes. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_prf - Generate enctype-specific pseudo-random bytes.

+
+
+krb5_error_code krb5_c_prf(krb5_context context, const krb5_keyblock *keyblock, krb5_data *input, krb5_data *output)
+
+ +
+
param
+

[in] context - Library context

+

[in] keyblock - Key

+

[in] input - Input data

+

[out] output - Output data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function selects a pseudo-random function based on keyblock and computes its value over input , placing the result into output . The caller must preinitialize output and allocate space for the result, using krb5_c_prf_length() to determine the required length.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_prf_length.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_prf_length.html new file mode 100644 index 00000000..b9f9fb2a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_prf_length.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_c_prf_length - Get the output length of pseudo-random functions for an encryption type. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_prf_length - Get the output length of pseudo-random functions for an encryption type.

+
+
+krb5_error_code krb5_c_prf_length(krb5_context context, krb5_enctype enctype, size_t *len)
+
+ +
+
param
+

[in] context - Library context

+

[in] enctype - Encryption type

+

[out] len - Length of PRF output

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_prfplus.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_prfplus.html new file mode 100644 index 00000000..1308bffa --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_prfplus.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_c_prfplus - Generate pseudo-random bytes using RFC 6113 PRF+. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_prfplus - Generate pseudo-random bytes using RFC 6113 PRF+.

+
+
+krb5_error_code krb5_c_prfplus(krb5_context context, const krb5_keyblock *k, const krb5_data *input, krb5_data *output)
+
+ +
+
param
+

[in] context - Library context

+

[in] k - KDC contribution key

+

[in] input - Input data

+

[out] output - Pseudo-random output buffer

+
+
+
+
return
+
    +
  • 0 on success, E2BIG if output->length is too large for PRF+ to generate, ENOMEM on allocation failure, or an error code from krb5_c_prf()

  • +
+
+
+

This function fills output with PRF+(k, input) as defined in RFC 6113 section 5.1. The caller must preinitialize output and allocate the desired amount of space. The length of the pseudo-random output will match the length of output .

+
+

Note

+

RFC 4402 defines a different PRF+ operation. This function does not implement that operation.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_add_entropy.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_add_entropy.html new file mode 100644 index 00000000..4486b2c0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_add_entropy.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_c_random_add_entropy — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_make_octets.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_make_octets.html new file mode 100644 index 00000000..c917e7a1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_make_octets.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_c_random_make_octets - Generate pseudo-random bytes. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_random_make_octets - Generate pseudo-random bytes.

+
+
+krb5_error_code krb5_c_random_make_octets(krb5_context context, krb5_data *data)
+
+ +
+
param
+

[in] context - Library context

+

[out] data - Random data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Fills in data with bytes from the PRNG used by krb5 crypto operations. The caller must preinitialize data and allocate the desired amount of space.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_os_entropy.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_os_entropy.html new file mode 100644 index 00000000..08a47c82 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_os_entropy.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_c_random_os_entropy — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_seed.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_seed.html new file mode 100644 index 00000000..44749637 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_seed.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_c_random_seed — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_to_key.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_to_key.html new file mode 100644 index 00000000..961108e2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_random_to_key.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_c_random_to_key - Generate an enctype-specific key from random data. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_random_to_key - Generate an enctype-specific key from random data.

+
+
+krb5_error_code krb5_c_random_to_key(krb5_context context, krb5_enctype enctype, krb5_data *random_data, krb5_keyblock *k5_random_key)
+
+ +
+
param
+

[in] context - Library context

+

[in] enctype - Encryption type

+

[in] random_data - Random input data

+

[out] k5_random_key - Resulting key

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function takes random input data random_data and produces a valid key k5_random_key for a given enctype .

+
+

See also

+

krb5_c_keylengths()

+
+
+

Note

+

It is assumed that k5_random_key has already been initialized and k5_random_key->contents has been allocated with the correct length.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_string_to_key.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_string_to_key.html new file mode 100644 index 00000000..6e577708 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_string_to_key.html @@ -0,0 +1,161 @@ + + + + + + + + + krb5_c_string_to_key - Convert a string (such a password) to a key. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_string_to_key - Convert a string (such a password) to a key.

+
+
+krb5_error_code krb5_c_string_to_key(krb5_context context, krb5_enctype enctype, const krb5_data *string, const krb5_data *salt, krb5_keyblock *key)
+
+ +
+
param
+

[in] context - Library context

+

[in] enctype - Encryption type

+

[in] string - String to be converted

+

[in] salt - Salt value

+

[out] key - Generated key

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function converts string to a key of encryption type enctype , using the specified salt . The newly created key must be released by calling krb5_free_keyblock_contents() when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_string_to_key_with_params.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_string_to_key_with_params.html new file mode 100644 index 00000000..a2a1a14d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_string_to_key_with_params.html @@ -0,0 +1,162 @@ + + + + + + + + + krb5_c_string_to_key_with_params - Convert a string (such as a password) to a key with additional parameters. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_string_to_key_with_params - Convert a string (such as a password) to a key with additional parameters.

+
+
+krb5_error_code krb5_c_string_to_key_with_params(krb5_context context, krb5_enctype enctype, const krb5_data *string, const krb5_data *salt, const krb5_data *params, krb5_keyblock *key)
+
+ +
+
param
+

[in] context - Library context

+

[in] enctype - Encryption type

+

[in] string - String to be converted

+

[in] salt - Salt value

+

[in] params - Parameters

+

[out] key - Generated key

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function is similar to krb5_c_string_to_key(), but also takes parameters which may affect the algorithm in an enctype-dependent way. The newly created key must be released by calling krb5_free_keyblock_contents() when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_valid_cksumtype.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_valid_cksumtype.html new file mode 100644 index 00000000..e37da7bf --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_valid_cksumtype.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_c_valid_cksumtype - Verify that specified checksum type is a valid Kerberos checksum type. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_valid_enctype.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_valid_enctype.html new file mode 100644 index 00000000..3eb00ff9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_valid_enctype.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_c_valid_enctype - Verify that a specified encryption type is a valid Kerberos encryption type. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_verify_checksum.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_verify_checksum.html new file mode 100644 index 00000000..e2d99c29 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_verify_checksum.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_c_verify_checksum - Verify a checksum (operates on keyblock). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_verify_checksum - Verify a checksum (operates on keyblock).

+
+
+krb5_error_code krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *data, const krb5_checksum *cksum, krb5_boolean *valid)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Encryption key for a keyed checksum

+

[in] usage - key usage

+

[in] data - Data to be used to compute a new checksum using key to compare cksum against

+

[in] cksum - Checksum to be verified

+

[out] valid - Non-zero for success, zero for failure

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function verifies that cksum is a valid checksum for data . If the checksum type of cksum is a keyed checksum, key is used to verify the checksum. If the checksum type in cksum is 0 and key is not NULL, the mandatory checksum type for key will be used. The actual checksum key will be derived from key and usage if key derivation is specified for the checksum type.

+
+

Note

+

This function is similar to krb5_k_verify_checksum(), but operates on keyblock key .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_verify_checksum_iov.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_verify_checksum_iov.html new file mode 100644 index 00000000..ce0c9699 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_c_verify_checksum_iov.html @@ -0,0 +1,171 @@ + + + + + + + + + krb5_c_verify_checksum_iov - Validate a checksum element in IOV array (operates on keyblock). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_c_verify_checksum_iov - Validate a checksum element in IOV array (operates on keyblock).

+
+
+krb5_error_code krb5_c_verify_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, const krb5_keyblock *key, krb5_keyusage usage, const krb5_crypto_iov *data, size_t num_data, krb5_boolean *valid)
+
+ +
+
param
+

[in] context - Library context

+

[in] cksumtype - Checksum type (0 for mandatory type)

+

[in] key - Encryption key for a keyed checksum

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[in] data - IOV array

+

[in] num_data - Size of data

+

[out] valid - Non-zero for success, zero for failure

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Confirm that the checksum in the #KRB5_CRYPTO_TYPE_CHECKSUM element is a valid checksum of the #KRB5_CRYPTO_TYPE_DATA and #KRB5_CRYPTO_TYPE_SIGN_ONLY regions in the iov.

+
+

See also

+

krb5_c_make_checksum_iov()

+
+
+

Note

+

This function is similar to krb5_k_verify_checksum_iov(), but operates on keyblock key .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_calculate_checksum.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_calculate_checksum.html new file mode 100644 index 00000000..7d429889 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_calculate_checksum.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_calculate_checksum — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_cache_match.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_cache_match.html new file mode 100644 index 00000000..8f858217 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_cache_match.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_cc_cache_match - Find a credential cache with a specified client principal. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_cache_match - Find a credential cache with a specified client principal.

+
+
+krb5_error_code krb5_cc_cache_match(krb5_context context, krb5_principal client, krb5_ccache *cache_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] client - Client principal

+

[out] cache_out - Credential cache handle

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • KRB5_CC_NOTFOUND None

  • +
+
+
+

Find a cache within the collection whose default principal is client . Use krb5_cc_close to close ccache when it is no longer needed.

+
+

Note

+

New in 1.10

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_close.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_close.html new file mode 100644 index 00000000..66b7fb2c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_close.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_cc_close - Close a credential cache handle. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_close - Close a credential cache handle.

+
+
+krb5_error_code krb5_cc_close(krb5_context context, krb5_ccache cache)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function closes a credential cache handle cache without affecting the contents of the cache.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_copy_creds.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_copy_creds.html new file mode 100644 index 00000000..d5e2b462 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_copy_creds.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_cc_copy_creds - Copy a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_copy_creds - Copy a credential cache.

+
+
+krb5_error_code krb5_cc_copy_creds(krb5_context context, krb5_ccache incc, krb5_ccache outcc)
+
+ +
+
param
+

[in] context - Library context

+

[in] incc - Credential cache to be copied

+

[out] outcc - Copy of credential cache to be filled in

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_default.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_default.html new file mode 100644 index 00000000..15fa748b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_default.html @@ -0,0 +1,165 @@ + + + + + + + + + krb5_cc_default - Resolve the default credential cache name. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_default - Resolve the default credential cache name.

+
+
+krb5_error_code krb5_cc_default(krb5_context context, krb5_ccache *ccache)
+
+ +
+
param
+

[in] context - Library context

+

[out] ccache - Pointer to credential cache name

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • KV5M_CONTEXT Bad magic number for _krb5_context structure

  • +
  • KRB5_FCC_INTERNAL The name of the default credential cache cannot be obtained

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Create a handle to the default credential cache as given by krb5_cc_default_name().

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_default_name.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_default_name.html new file mode 100644 index 00000000..eda52320 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_default_name.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_cc_default_name - Return the name of the default credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_default_name - Return the name of the default credential cache.

+
+
+const char *krb5_cc_default_name(krb5_context context)
+
+ +
+
param
+

[in] context - Library context

+
+
+
+
return
+
    +
  • Name of default credential cache for the current user.

  • +
+
+
+

Return a pointer to the default credential cache name for context , as determined by a prior call to krb5_cc_set_default_name(), by the KRB5CCNAME environment variable, by the default_ccache_name profile variable, or by the operating system or build-time default value. The returned value must not be modified or freed by the caller. The returned value becomes invalid when context is destroyed krb5_free_context() or if a subsequent call to krb5_cc_set_default_name() is made on context .

+

The default credential cache name is cached in context between calls to this function, so if the value of KRB5CCNAME changes in the process environment after the first call to this function on, that change will not be reflected in later calls with the same context. The caller can invoke krb5_cc_set_default_name() with a NULL value of name to clear the cached value and force the default name to be recomputed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_destroy.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_destroy.html new file mode 100644 index 00000000..016e2690 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_destroy.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_cc_destroy - Destroy a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_destroy - Destroy a credential cache.

+
+
+krb5_error_code krb5_cc_destroy(krb5_context context, krb5_ccache cache)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Permission errors

  • +
+
+
+

This function destroys any existing contents of cache and closes the handle to it.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_dup.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_dup.html new file mode 100644 index 00000000..028e294b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_dup.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_cc_dup - Duplicate ccache handle. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_dup - Duplicate ccache handle.

+
+
+krb5_error_code krb5_cc_dup(krb5_context context, krb5_ccache in, krb5_ccache *out)
+
+ +
+
param
+

[in] context - Library context

+

[in] in - Credential cache handle to be duplicated

+

[out] out - Credential cache handle

+
+
+

Create a new handle referring to the same cache as in . The new handle and in can be closed independently.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_end_seq_get.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_end_seq_get.html new file mode 100644 index 00000000..fd6fee3d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_end_seq_get.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_cc_end_seq_get - Finish a series of sequential processing credential cache entries. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_end_seq_get - Finish a series of sequential processing credential cache entries.

+
+
+krb5_error_code krb5_cc_end_seq_get(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+

[in] cursor - Cursor

+
+
+
+
retval
+
    +
  • 0 (always)

  • +
+
+
+

This function finishes processing credential cache entries and invalidates cursor .

+
+

See also

+

krb5_cc_start_seq_get(), krb5_cc_next_cred()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_gen_new.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_gen_new.html new file mode 100644 index 00000000..7ff44dc2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_gen_new.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_cc_gen_new — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_config.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_config.html new file mode 100644 index 00000000..c0bb4cea --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_config.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_cc_get_config - Get a configuration value from a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_get_config - Get a configuration value from a credential cache.

+
+
+krb5_error_code krb5_cc_get_config(krb5_context context, krb5_ccache id, krb5_const_principal principal, const char *key, krb5_data *data)
+
+ +
+
param
+

[in] context - Library context

+

[in] id - Credential cache handle

+

[in] principal - Configuration for this principal; if NULL, global for the whole cache

+

[in] key - Name of config variable

+

[out] data - Data to be fetched

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Use krb5_free_data_contents() to free data when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_flags.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_flags.html new file mode 100644 index 00000000..708f965a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_flags.html @@ -0,0 +1,162 @@ + + + + + + + + + krb5_cc_get_flags - Retrieve flags from a credential cache structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_get_flags - Retrieve flags from a credential cache structure.

+
+
+krb5_error_code krb5_cc_get_flags(krb5_context context, krb5_ccache cache, krb5_flags *flags)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+

[out] flags - Flag bit mask

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+

Warning

+

For memory credential cache always returns a flag mask of 0.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_full_name.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_full_name.html new file mode 100644 index 00000000..5a10794b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_full_name.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_cc_get_full_name - Retrieve the full name of a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_get_full_name - Retrieve the full name of a credential cache.

+
+
+krb5_error_code krb5_cc_get_full_name(krb5_context context, krb5_ccache cache, char **fullname_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+

[out] fullname_out - Full name of cache

+
+
+

Use krb5_free_string() to free fullname_out when it is no longer needed.

+
+

Note

+

New in 1.10

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_name.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_name.html new file mode 100644 index 00000000..01eb9aa1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_name.html @@ -0,0 +1,161 @@ + + + + + + + + + krb5_cc_get_name - Retrieve the name, but not type of a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_get_name - Retrieve the name, but not type of a credential cache.

+
+
+const char *krb5_cc_get_name(krb5_context context, krb5_ccache cache)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+
+
+
+
return
+
    +
  • On success - the name of the credential cache.

  • +
+
+
+
+

Warning

+

Returns the name of the credential cache. The result is an alias into cache and should not be freed or modified by the caller. This name does not include the cache type, so should not be used as input to krb5_cc_resolve().

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_principal.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_principal.html new file mode 100644 index 00000000..d0ad967e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_principal.html @@ -0,0 +1,165 @@ + + + + + + + + + krb5_cc_get_principal - Get the default principal of a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_get_principal - Get the default principal of a credential cache.

+
+
+krb5_error_code krb5_cc_get_principal(krb5_context context, krb5_ccache cache, krb5_principal *principal)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+

[out] principal - Primary principal

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Returns the default client principal of a credential cache as set by krb5_cc_initialize().

+

Use krb5_free_principal() to free principal when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_type.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_type.html new file mode 100644 index 00000000..e97c529b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_get_type.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_cc_get_type - Retrieve the type of a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_get_type - Retrieve the type of a credential cache.

+
+
+const char *krb5_cc_get_type(krb5_context context, krb5_ccache cache)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+
+
+
+
return
+
    +
  • The type of a credential cache as an alias that must not be modified or freed by the caller.

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_initialize.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_initialize.html new file mode 100644 index 00000000..0d98dee3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_initialize.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_cc_initialize - Initialize a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_initialize - Initialize a credential cache.

+
+
+krb5_error_code krb5_cc_initialize(krb5_context context, krb5_ccache cache, krb5_principal principal)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+

[in] principal - Default principal name

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • System errors; Permission errors; Kerberos error codes

  • +
+
+
+

Destroy any existing contents of cache and initialize it for the default principal principal .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_move.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_move.html new file mode 100644 index 00000000..2c474cb8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_move.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_cc_move - Move a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_move - Move a credential cache.

+
+
+krb5_error_code krb5_cc_move(krb5_context context, krb5_ccache src, krb5_ccache dst)
+
+ +
+
param
+

[in] context - Library context

+

[in] src - The credential cache to move the content from

+

[in] dst - The credential cache to move the content to

+
+
+
+
retval
+
    +
  • 0 Success; src is closed.

  • +
+
+
return
+
    +
  • Kerberos error codes; src is still allocated.

  • +
+
+
+

This function reinitializes dst and populates it with the credentials and default principal of src ; then, if successful, destroys src .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_new_unique.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_new_unique.html new file mode 100644 index 00000000..7f116e87 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_new_unique.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_cc_new_unique - Create a new credential cache of the specified type with a unique name. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_new_unique - Create a new credential cache of the specified type with a unique name.

+
+
+krb5_error_code krb5_cc_new_unique(krb5_context context, const char *type, const char *hint, krb5_ccache *id)
+
+ +
+
param
+

[in] context - Library context

+

[in] type - Credential cache type name

+

[in] hint - Unused

+

[out] id - Credential cache handle

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_next_cred.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_next_cred.html new file mode 100644 index 00000000..0430d9c1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_next_cred.html @@ -0,0 +1,165 @@ + + + + + + + + + krb5_cc_next_cred - Retrieve the next entry from the credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_next_cred - Retrieve the next entry from the credential cache.

+
+
+krb5_error_code krb5_cc_next_cred(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor, krb5_creds *creds)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+

[in] cursor - Cursor

+

[out] creds - Next credential cache entry

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function fills in creds with the next entry in cache and advances cursor .

+

Use krb5_free_cred_contents() to free creds when it is no longer needed.

+
+

See also

+

krb5_cc_start_seq_get(), krb5_end_seq_get()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_remove_cred.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_remove_cred.html new file mode 100644 index 00000000..552b6d68 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_remove_cred.html @@ -0,0 +1,169 @@ + + + + + + + + + krb5_cc_remove_cred - Remove credentials from a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_remove_cred - Remove credentials from a credential cache.

+
+
+krb5_error_code krb5_cc_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags, krb5_creds *creds)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+

[in] flags - Bitwise-ORed search flags

+

[in] creds - Credentials to be matched

+
+
+
+
retval
+
    +
  • KRB5_CC_NOSUPP Not implemented for this cache type

  • +
+
+
return
+
    +
  • No matches found; Data cannot be deleted; Kerberos error codes

  • +
+
+
+

This function accepts the same flag values as krb5_cc_retrieve_cred().

+
+

Warning

+

This function is not implemented for some cache types.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_resolve.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_resolve.html new file mode 100644 index 00000000..4145693c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_resolve.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_cc_resolve - Resolve a credential cache name. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_resolve - Resolve a credential cache name.

+
+
+krb5_error_code krb5_cc_resolve(krb5_context context, const char *name, krb5_ccache *cache)
+
+ +
+
param
+

[in] context - Library context

+

[in] name - Credential cache name to be resolved

+

[out] cache - Credential cache handle

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Fills in cache with a cache handle that corresponds to the name in name . name should be of the form type:residual , and type must be a type known to the library. If the name does not contain a colon, interpret it as a file name.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_retrieve_cred.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_retrieve_cred.html new file mode 100644 index 00000000..ec432bc6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_retrieve_cred.html @@ -0,0 +1,179 @@ + + + + + + + + + krb5_cc_retrieve_cred - Retrieve a specified credentials from a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_retrieve_cred - Retrieve a specified credentials from a credential cache.

+
+
+krb5_error_code krb5_cc_retrieve_cred(krb5_context context, krb5_ccache cache, krb5_flags flags, krb5_creds *mcreds, krb5_creds *creds)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+

[in] flags - Flags bit mask

+

[in] mcreds - Credentials to match

+

[out] creds - Credentials matching the requested value

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function searches a credential cache for credentials matching mcreds and returns it if found.

+

Valid values for flags are:

+
+
+
    +
  • #KRB5_TC_MATCH_TIMES The requested lifetime must be at least as great as in mcreds .

  • +
  • #KRB5_TC_MATCH_IS_SKEY The is_skey field much match exactly.

  • +
  • #KRB5_TC_MATCH_FLAGS Flags set in mcreds must be set.

  • +
  • #KRB5_TC_MATCH_TIMES_EXACT The requested lifetime must match exactly.

  • +
  • #KRB5_TC_MATCH_FLAGS_EXACT Flags must match exactly.

  • +
  • #KRB5_TC_MATCH_AUTHDATA The authorization data must match.

  • +
  • #KRB5_TC_MATCH_SRV_NAMEONLY Only the name portion of the principal name must match, not the realm.

  • +
  • #KRB5_TC_MATCH_2ND_TKT The second tickets must match.

  • +
  • #KRB5_TC_MATCH_KTYPE The encryption key types must match.

  • +
  • #KRB5_TC_SUPPORTED_KTYPES Check all matching entries that have any supported encryption type and return the one with the encryption type listed earliest.

  • +
+
+

Use krb5_free_cred_contents() to free creds when it is no longer needed.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_select.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_select.html new file mode 100644 index 00000000..e9fcc2c7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_select.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_cc_select - Select a credential cache to use with a server principal. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_select - Select a credential cache to use with a server principal.

+
+
+krb5_error_code krb5_cc_select(krb5_context context, krb5_principal server, krb5_ccache *cache_out, krb5_principal *princ_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] server - Server principal

+

[out] cache_out - Credential cache handle

+

[out] princ_out - Client principal

+
+
+
+
return
+
    +
  • If an appropriate cache is found, 0 is returned, cache_out is set to the selected cache, and princ_out is set to the default principal of that cache.

  • +
+
+
+

Select a cache within the collection containing credentials most appropriate for use with server , according to configured rules and heuristics.

+

Use krb5_cc_close() to release cache_out when it is no longer needed. Use krb5_free_principal() to release princ_out when it is no longer needed. Note that princ_out is set in some error conditions.

+

If the appropriate client principal can be authoritatively determined but the cache collection contains no credentials for that principal, then KRB5_CC_NOTFOUND is returned, cache_out is set to NULL, and princ_out is set to the appropriate client principal.

+

If no configured mechanism can determine the appropriate cache or principal, KRB5_CC_NOTFOUND is returned and cache_out and princ_out are set to NULL.

+

Any other error code indicates a fatal error in the processing of a cache selection mechanism.

+
+

Note

+

New in 1.10

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_set_config.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_set_config.html new file mode 100644 index 00000000..ef7220fc --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_set_config.html @@ -0,0 +1,173 @@ + + + + + + + + + krb5_cc_set_config - Store a configuration value in a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_set_config - Store a configuration value in a credential cache.

+
+
+krb5_error_code krb5_cc_set_config(krb5_context context, krb5_ccache id, krb5_const_principal principal, const char *key, krb5_data *data)
+
+ +
+
param
+

[in] context - Library context

+

[in] id - Credential cache handle

+

[in] principal - Configuration for a specific principal; if NULL, global for the whole cache

+

[in] key - Name of config variable

+

[in] data - Data to store, or NULL to remove

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+
+

Warning

+

Before version 1.10 data was assumed to be always non-null.

+
+
+

Note

+

Existing configuration under the same key is over-written.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_set_default_name.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_set_default_name.html new file mode 100644 index 00000000..b9329376 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_set_default_name.html @@ -0,0 +1,165 @@ + + + + + + + + + krb5_cc_set_default_name - Set the default credential cache name. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_set_default_name - Set the default credential cache name.

+
+
+krb5_error_code krb5_cc_set_default_name(krb5_context context, const char *name)
+
+ +
+
param
+

[in] context - Library context

+

[in] name - Default credential cache name or NULL

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • KV5M_CONTEXT Bad magic number for _krb5_context structure

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Set the default credential cache name to name for future operations using context . If name is NULL, clear any previous application-set default name and forget any cached value of the default name for context .

+

Calls to this function invalidate the result of any previous calls to krb5_cc_default_name() using context .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_set_flags.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_set_flags.html new file mode 100644 index 00000000..e6a95794 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_set_flags.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_cc_set_flags - Set options flags on a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_set_flags - Set options flags on a credential cache.

+
+
+krb5_error_code krb5_cc_set_flags(krb5_context context, krb5_ccache cache, krb5_flags flags)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+

[in] flags - Flag bit mask

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function resets cache flags to flags .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_start_seq_get.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_start_seq_get.html new file mode 100644 index 00000000..d4d41c8f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_start_seq_get.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_cc_start_seq_get - Prepare to sequentially read every credential in a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_start_seq_get - Prepare to sequentially read every credential in a credential cache.

+
+
+krb5_error_code krb5_cc_start_seq_get(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+

[out] cursor - Cursor

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

krb5_cc_end_seq_get() must be called to complete the retrieve operation.

+
+

Note

+

If the cache represented by cache is modified between the time of the call to this function and the time of the final krb5_cc_end_seq_get(), these changes may not be reflected in the results of krb5_cc_next_cred() calls.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_store_cred.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_store_cred.html new file mode 100644 index 00000000..47bd1354 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_store_cred.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_cc_store_cred - Store credentials in a credential cache. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_store_cred - Store credentials in a credential cache.

+
+
+krb5_error_code krb5_cc_store_cred(krb5_context context, krb5_ccache cache, krb5_creds *creds)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+

[in] creds - Credentials to be stored in cache

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Permission errors; storage failure errors; Kerberos error codes

  • +
+
+
+

This function stores creds into cache . If creds->server and the server in the decoded ticket creds->ticket differ, the credentials will be stored under both server principal names.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_support_switch.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_support_switch.html new file mode 100644 index 00000000..ae2078d2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_support_switch.html @@ -0,0 +1,162 @@ + + + + + + + + + krb5_cc_support_switch - Determine whether a credential cache type supports switching. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_support_switch - Determine whether a credential cache type supports switching.

+
+
+krb5_boolean krb5_cc_support_switch(krb5_context context, const char *type)
+
+ +
+
param
+

[in] context - Library context

+

[in] type - Credential cache type

+
+
+
+
retval
+
    +
  • TRUE if type supports switching

  • +
  • FALSE if it does not or is not a valid credential cache type.

  • +
+
+
+
+

Note

+

New in 1.10

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_switch.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_switch.html new file mode 100644 index 00000000..a4673185 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cc_switch.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_cc_switch - Make a credential cache the primary cache for its collection. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cc_switch - Make a credential cache the primary cache for its collection.

+
+
+krb5_error_code krb5_cc_switch(krb5_context context, krb5_ccache cache)
+
+ +
+
param
+

[in] context - Library context

+

[in] cache - Credential cache handle

+
+
+
+
retval
+
    +
  • 0 Success, or the type of cache doesn’t support switching

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

If the type of cache supports it, set cache to be the primary credential cache for the collection it belongs to.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_cursor_free.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_cursor_free.html new file mode 100644 index 00000000..6167b696 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_cursor_free.html @@ -0,0 +1,161 @@ + + + + + + + + + krb5_cccol_cursor_free - Free a credential cache collection cursor. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cccol_cursor_free - Free a credential cache collection cursor.

+
+
+krb5_error_code krb5_cccol_cursor_free(krb5_context context, krb5_cccol_cursor *cursor)
+
+ +
+
param
+

[in] context - Library context

+

[in] cursor - Cursor

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+

See also

+

krb5_cccol_cursor_new(), krb5_cccol_cursor_next()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_cursor_new.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_cursor_new.html new file mode 100644 index 00000000..ffbb6d3e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_cursor_new.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_cccol_cursor_new - Prepare to iterate over the collection of known credential caches. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cccol_cursor_new - Prepare to iterate over the collection of known credential caches.

+
+
+krb5_error_code krb5_cccol_cursor_new(krb5_context context, krb5_cccol_cursor *cursor)
+
+ +
+
param
+

[in] context - Library context

+

[out] cursor - Cursor

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Get a new cache iteration cursor that will iterate over all known credential caches independent of type.

+

Use krb5_cccol_cursor_free() to release cursor when it is no longer needed.

+
+

See also

+

krb5_cccol_cursor_next()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_cursor_next.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_cursor_next.html new file mode 100644 index 00000000..79962cc2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_cursor_next.html @@ -0,0 +1,167 @@ + + + + + + + + + krb5_cccol_cursor_next - Get the next credential cache in the collection. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cccol_cursor_next - Get the next credential cache in the collection.

+
+
+krb5_error_code krb5_cccol_cursor_next(krb5_context context, krb5_cccol_cursor cursor, krb5_ccache *ccache)
+
+ +
+
param
+

[in] context - Library context

+

[in] cursor - Cursor

+

[out] ccache - Credential cache handle

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Use krb5_cc_close() to close ccache when it is no longer needed.

+
+

See also

+

krb5_cccol_cursor_new(), krb5_cccol_cursor_free()

+
+
+

Note

+

When all caches are iterated over and the end of the list is reached, ccache is set to NULL.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_have_content.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_have_content.html new file mode 100644 index 00000000..df061ced --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cccol_have_content.html @@ -0,0 +1,161 @@ + + + + + + + + + krb5_cccol_have_content - Check if the credential cache collection contains any initialized caches. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cccol_have_content - Check if the credential cache collection contains any initialized caches.

+
+
+krb5_error_code krb5_cccol_have_content(krb5_context context)
+
+ +
+
param
+

[in] context - Library context

+
+
+
+
retval
+
    +
  • 0 At least one initialized cache is present in the collection

  • +
  • KRB5_CC_NOTFOUND The collection contains no caches

  • +
+
+
+
+

Note

+

New in 1.11

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_change_password.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_change_password.html new file mode 100644 index 00000000..2be3e6c7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_change_password.html @@ -0,0 +1,172 @@ + + + + + + + + + krb5_change_password - Change a password for an existing Kerberos account. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_change_password - Change a password for an existing Kerberos account.

+
+
+krb5_error_code krb5_change_password(krb5_context context, krb5_creds *creds, const char *newpw, int *result_code, krb5_data *result_code_string, krb5_data *result_string)
+
+ +
+
param
+

[in] context - Library context

+

[in] creds - Credentials for kadmin/changepw service

+

[in] newpw - New password

+

[out] result_code - Numeric error code from server

+

[out] result_code_string - String equivalent to result_code

+

[out] result_string - Change password response from the KDC

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Change the password for the existing principal identified by creds .

+

The possible values of the output result_code are:

+
+
    +
  • #KRB5_KPASSWD_SUCCESS (0) - success

  • +
  • #KRB5_KPASSWD_MALFORMED (1) - Malformed request error

  • +
  • #KRB5_KPASSWD_HARDERROR (2) - Server error

  • +
  • #KRB5_KPASSWD_AUTHERROR (3) - Authentication error

  • +
  • #KRB5_KPASSWD_SOFTERROR (4) - Password change rejected

  • +
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_check_clockskew.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_check_clockskew.html new file mode 100644 index 00000000..ab5896da --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_check_clockskew.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_check_clockskew - Check if a timestamp is within the allowed clock skew of the current time. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_check_clockskew - Check if a timestamp is within the allowed clock skew of the current time.

+
+
+krb5_error_code krb5_check_clockskew(krb5_context context, krb5_timestamp date)
+
+ +
+
param
+

[in] context - Library context

+

[in] date - Timestamp to check

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • KRB5KRB_AP_ERR_SKEW date is not within allowable clock skew

  • +
+
+
+

This function checks if date is close enough to the current time according to the configured allowable clock skew.

+
+

Note

+

New in 1.10

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_checksum_size.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_checksum_size.html new file mode 100644 index 00000000..893ff4b8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_checksum_size.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_checksum_size — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_chpw_message.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_chpw_message.html new file mode 100644 index 00000000..6a8ea88b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_chpw_message.html @@ -0,0 +1,169 @@ + + + + + + + + + krb5_chpw_message - Get a result message for changing or setting a password. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_chpw_message - Get a result message for changing or setting a password.

+
+
+krb5_error_code krb5_chpw_message(krb5_context context, const krb5_data *server_string, char **message_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] server_string - Data returned from the remote system

+

[out] message_out - A message displayable to the user

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function processes the server_string returned in the result_string parameter of krb5_change_password(), krb5_set_password(), and related functions, and returns a displayable string. If server_string contains Active Directory structured policy information, it will be converted into human-readable text.

+

Use krb5_free_string() to free message_out when it is no longer needed.

+
+

Note

+

New in 1.11

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cksumtype_to_string.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cksumtype_to_string.html new file mode 100644 index 00000000..0246b8be --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_cksumtype_to_string.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_cksumtype_to_string - Convert a checksum type to a string. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cksumtype_to_string - Convert a checksum type to a string.

+
+
+krb5_error_code krb5_cksumtype_to_string(krb5_cksumtype cksumtype, char *buffer, size_t buflen)
+
+ +
+
param
+

[in] cksumtype - Checksum type

+

[out] buffer - Buffer to hold converted checksum type

+

[in] buflen - Storage available in buffer

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_clear_error_message.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_clear_error_message.html new file mode 100644 index 00000000..181e13e5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_clear_error_message.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_clear_error_message - Clear the extended error message in a context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_clear_error_message - Clear the extended error message in a context.

+
+
+void krb5_clear_error_message(krb5_context ctx)
+
+ +
+
param
+

[in] ctx - Library context

+
+
+

This function unsets the extended error message in a context, to ensure that it is not mistakenly applied to another occurrence of the same error code.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_addresses.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_addresses.html new file mode 100644 index 00000000..bd2419a3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_addresses.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_copy_addresses - Copy an array of addresses. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_copy_addresses - Copy an array of addresses.

+
+
+krb5_error_code krb5_copy_addresses(krb5_context context, krb5_address *const *inaddr, krb5_address ***outaddr)
+
+ +
+
param
+

[in] context - Library context

+

[in] inaddr - Array of addresses to be copied

+

[out] outaddr - Copy of array of addresses

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a new address array containing a copy of inaddr . Use krb5_free_addresses() to free outaddr when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_authdata.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_authdata.html new file mode 100644 index 00000000..e9ab3e65 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_authdata.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_copy_authdata - Copy an authorization data list. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_copy_authdata - Copy an authorization data list.

+
+
+krb5_error_code krb5_copy_authdata(krb5_context context, krb5_authdata *const *in_authdat, krb5_authdata ***out)
+
+ +
+
param
+

[in] context - Library context

+

[in] in_authdat - List of krb5_authdata structures

+

[out] out - New array of krb5_authdata structures

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a new authorization data list containing a copy of in_authdat , which must be null-terminated. Use krb5_free_authdata() to free out when it is no longer needed.

+
+

Note

+

The last array entry in in_authdat must be a NULL pointer.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_authenticator.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_authenticator.html new file mode 100644 index 00000000..3152f25e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_authenticator.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_copy_authenticator - Copy a krb5_authenticator structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_copy_authenticator - Copy a krb5_authenticator structure.

+
+
+krb5_error_code krb5_copy_authenticator(krb5_context context, const krb5_authenticator *authfrom, krb5_authenticator **authto)
+
+ +
+
param
+

[in] context - Library context

+

[in] authfrom - krb5_authenticator structure to be copied

+

[out] authto - Copy of krb5_authenticator structure

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a new krb5_authenticator structure with the content of authfrom . Use krb5_free_authenticator() to free authto when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_checksum.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_checksum.html new file mode 100644 index 00000000..27e6189e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_checksum.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_copy_checksum - Copy a krb5_checksum structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_copy_checksum - Copy a krb5_checksum structure.

+
+
+krb5_error_code krb5_copy_checksum(krb5_context context, const krb5_checksum *ckfrom, krb5_checksum **ckto)
+
+ +
+
param
+

[in] context - Library context

+

[in] ckfrom - Checksum to be copied

+

[out] ckto - Copy of krb5_checksum structure

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a new krb5_checksum structure with the contents of ckfrom . Use krb5_free_checksum() to free ckto when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_context.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_context.html new file mode 100644 index 00000000..c70c65d0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_context.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_copy_context - Copy a krb5_context structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_copy_context - Copy a krb5_context structure.

+
+
+krb5_error_code krb5_copy_context(krb5_context ctx, krb5_context *nctx_out)
+
+ +
+
param
+

[in] ctx - Library context

+

[out] nctx_out - New context structure

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

The newly created context must be released by calling krb5_free_context() when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_creds.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_creds.html new file mode 100644 index 00000000..888f0642 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_creds.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_copy_creds - Copy a krb5_creds structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_copy_creds - Copy a krb5_creds structure.

+
+
+krb5_error_code krb5_copy_creds(krb5_context context, const krb5_creds *incred, krb5_creds **outcred)
+
+ +
+
param
+

[in] context - Library context

+

[in] incred - Credentials structure to be copied

+

[out] outcred - Copy of incred

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a new credential with the contents of incred . Use krb5_free_creds() to free outcred when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_data.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_data.html new file mode 100644 index 00000000..8db97660 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_data.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_copy_data - Copy a krb5_data object. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_copy_data - Copy a krb5_data object.

+
+
+krb5_error_code krb5_copy_data(krb5_context context, const krb5_data *indata, krb5_data **outdata)
+
+ +
+
param
+

[in] context - Library context

+

[in] indata - Data object to be copied

+

[out] outdata - Copy of indata

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a new krb5_data object with the contents of indata . Use krb5_free_data() to free outdata when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_error_message.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_error_message.html new file mode 100644 index 00000000..9619774c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_error_message.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_copy_error_message - Copy the most recent extended error message from one context to another. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_keyblock.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_keyblock.html new file mode 100644 index 00000000..53b17d04 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_keyblock.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_copy_keyblock - Copy a keyblock. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_copy_keyblock - Copy a keyblock.

+
+
+krb5_error_code krb5_copy_keyblock(krb5_context context, const krb5_keyblock *from, krb5_keyblock **to)
+
+ +
+
param
+

[in] context - Library context

+

[in] from - Keyblock to be copied

+

[out] to - Copy of keyblock from

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a new keyblock with the same contents as from . Use krb5_free_keyblock() to free to when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_keyblock_contents.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_keyblock_contents.html new file mode 100644 index 00000000..807e5c1f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_keyblock_contents.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_copy_keyblock_contents - Copy the contents of a keyblock. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_copy_keyblock_contents - Copy the contents of a keyblock.

+
+
+krb5_error_code krb5_copy_keyblock_contents(krb5_context context, const krb5_keyblock *from, krb5_keyblock *to)
+
+ +
+
param
+

[in] context - Library context

+

[in] from - Key to be copied

+

[out] to - Output key

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function copies the contents of from to to . Use krb5_free_keyblock_contents() to free to when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_principal.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_principal.html new file mode 100644 index 00000000..65e48948 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_principal.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_copy_principal - Copy a principal. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_copy_principal - Copy a principal.

+
+
+krb5_error_code krb5_copy_principal(krb5_context context, krb5_const_principal inprinc, krb5_principal *outprinc)
+
+ +
+
param
+

[in] context - Library context

+

[in] inprinc - Principal to be copied

+

[out] outprinc - Copy of inprinc

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a new principal structure with the contents of inprinc . Use krb5_free_principal() to free outprinc when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_ticket.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_ticket.html new file mode 100644 index 00000000..63cbd1f0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_copy_ticket.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_copy_ticket - Copy a krb5_ticket structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_copy_ticket - Copy a krb5_ticket structure.

+
+
+krb5_error_code krb5_copy_ticket(krb5_context context, const krb5_ticket *from, krb5_ticket **pto)
+
+ +
+
param
+

[in] context - Library context

+

[in] from - Ticket to be copied

+

[out] pto - Copy of ticket

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a new krb5_ticket structure containing the contents of from . Use krb5_free_ticket() to free pto when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_decode_authdata_container.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_decode_authdata_container.html new file mode 100644 index 00000000..dcb1eb74 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_decode_authdata_container.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_decode_authdata_container - Unwrap authorization data. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_decode_authdata_container - Unwrap authorization data.

+
+
+krb5_error_code krb5_decode_authdata_container(krb5_context context, krb5_authdatatype type, const krb5_authdata *container, krb5_authdata ***authdata)
+
+ +
+
param
+

[in] context - Library context

+

[in] type - Container type (see KRB5_AUTHDATA macros)

+

[in] container - Authorization data to be decoded

+

[out] authdata - List of decoded authorization data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+

See also

+

krb5_encode_authdata_container()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_decode_ticket.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_decode_ticket.html new file mode 100644 index 00000000..2ee5227b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_decode_ticket.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_decode_ticket - Decode an ASN.1-formatted ticket. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_decrypt.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_decrypt.html new file mode 100644 index 00000000..dac5f0e1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_decrypt.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_decrypt — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_deltat_to_string.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_deltat_to_string.html new file mode 100644 index 00000000..911cb0c2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_deltat_to_string.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_deltat_to_string - Convert a relative time value to a string. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_deltat_to_string - Convert a relative time value to a string.

+
+
+krb5_error_code krb5_deltat_to_string(krb5_deltat deltat, char *buffer, size_t buflen)
+
+ +
+
param
+

[in] deltat - Relative time value to convert

+

[out] buffer - Buffer to hold time string

+

[in] buflen - Storage available in buffer

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_eblock_enctype.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_eblock_enctype.html new file mode 100644 index 00000000..46a44a01 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_eblock_enctype.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_eblock_enctype — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_encode_authdata_container.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_encode_authdata_container.html new file mode 100644 index 00000000..3bb14a9b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_encode_authdata_container.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_encode_authdata_container - Wrap authorization data in a container. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_encode_authdata_container - Wrap authorization data in a container.

+
+
+krb5_error_code krb5_encode_authdata_container(krb5_context context, krb5_authdatatype type, krb5_authdata *const *authdata, krb5_authdata ***container)
+
+ +
+
param
+

[in] context - Library context

+

[in] type - Container type (see KRB5_AUTHDATA macros)

+

[in] authdata - List of authorization data to be encoded

+

[out] container - List of encoded authorization data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

The result is returned in container as a single-element list.

+
+

See also

+

krb5_decode_authdata_container()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_encrypt.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_encrypt.html new file mode 100644 index 00000000..76414f03 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_encrypt.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_encrypt — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_encrypt_size.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_encrypt_size.html new file mode 100644 index 00000000..cf818b2c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_encrypt_size.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_encrypt_size — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_enctype_to_name.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_enctype_to_name.html new file mode 100644 index 00000000..46fc5d84 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_enctype_to_name.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_enctype_to_name - Convert an encryption type to a name or alias. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_enctype_to_name - Convert an encryption type to a name or alias.

+
+
+krb5_error_code krb5_enctype_to_name(krb5_enctype enctype, krb5_boolean shortest, char *buffer, size_t buflen)
+
+ +
+
param
+

[in] enctype - Encryption type

+

[in] shortest - Flag

+

[out] buffer - Buffer to hold encryption type string

+

[in] buflen - Storage available in buffer

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

If shortest is FALSE, this function returns the enctype’s canonical name (like”aes128-cts-hmac-sha1-96”). If shortest is TRUE, it return the enctype’s shortest alias (like”aes128-cts”).

+
+

Note

+

New in 1.9

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_enctype_to_string.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_enctype_to_string.html new file mode 100644 index 00000000..82695b07 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_enctype_to_string.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_enctype_to_string - Convert an encryption type to a string. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_enctype_to_string - Convert an encryption type to a string.

+
+
+krb5_error_code krb5_enctype_to_string(krb5_enctype enctype, char *buffer, size_t buflen)
+
+ +
+
param
+

[in] enctype - Encryption type

+

[out] buffer - Buffer to hold encryption type string

+

[in] buflen - Storage available in buffer

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_expand_hostname.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_expand_hostname.html new file mode 100644 index 00000000..afd64130 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_expand_hostname.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_expand_hostname - Canonicalize a hostname, possibly using name service. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_expand_hostname - Canonicalize a hostname, possibly using name service.

+
+
+krb5_error_code krb5_expand_hostname(krb5_context context, const char *host, char **canonhost_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] host - Input hostname

+

[out] canonhost_out - Canonicalized hostname

+
+
+

This function canonicalizes orig_hostname, possibly using name service lookups if configuration permits. Use krb5_free_string() to free canonhost_out when it is no longer needed.

+
+

Note

+

New in 1.15

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_find_authdata.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_find_authdata.html new file mode 100644 index 00000000..71c21943 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_find_authdata.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_find_authdata - Find authorization data elements. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_find_authdata - Find authorization data elements.

+
+
+krb5_error_code krb5_find_authdata(krb5_context context, krb5_authdata *const *ticket_authdata, krb5_authdata *const *ap_req_authdata, krb5_authdatatype ad_type, krb5_authdata ***results)
+
+ +
+
param
+

[in] context - Library context

+

[in] ticket_authdata - Authorization data list from ticket

+

[in] ap_req_authdata - Authorization data list from AP request

+

[in] ad_type - Authorization data type to find

+

[out] results - List of matching entries

+
+
+

This function searches ticket_authdata and ap_req_authdata for elements of type ad_type . Either input list may be NULL, in which case it will not be searched; otherwise, the input lists must be terminated by NULL entries. This function will search inside AD-IF-RELEVANT containers if found in either list. Use krb5_free_authdata() to free results when it is no longer needed.

+
+

Note

+

New in 1.10

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_finish_key.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_finish_key.html new file mode 100644 index 00000000..94313bbd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_finish_key.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_finish_key — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_finish_random_key.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_finish_random_key.html new file mode 100644 index 00000000..bfdeb4ff --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_finish_random_key.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_finish_random_key — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_addresses.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_addresses.html new file mode 100644 index 00000000..deaab411 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_addresses.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_free_addresses - Free the data stored in array of addresses. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_addresses - Free the data stored in array of addresses.

+
+
+void krb5_free_addresses(krb5_context context, krb5_address **val)
+
+ +
+
param
+

[in] context - Library context

+

[in] val - Array of addresses to be freed

+
+
+

This function frees the contents of val and the array itself.

+
+

Note

+

The last entry in the array must be a NULL pointer.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_ap_rep_enc_part.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_ap_rep_enc_part.html new file mode 100644 index 00000000..9c15e48f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_ap_rep_enc_part.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_free_ap_rep_enc_part - Free a krb5_ap_rep_enc_part structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_ap_rep_enc_part - Free a krb5_ap_rep_enc_part structure.

+
+
+void krb5_free_ap_rep_enc_part(krb5_context context, krb5_ap_rep_enc_part *val)
+
+ +
+
param
+

[in] context - Library context

+

[in] val - AP-REP enc part to be freed

+
+
+

This function frees the contents of val and the structure itself.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_authdata.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_authdata.html new file mode 100644 index 00000000..1c521889 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_authdata.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_free_authdata - Free the storage assigned to array of authentication data. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_authdata - Free the storage assigned to array of authentication data.

+
+
+void krb5_free_authdata(krb5_context context, krb5_authdata **val)
+
+ +
+
param
+

[in] context - Library context

+

[in] val - Array of authentication data to be freed

+
+
+

This function frees the contents of val and the array itself.

+
+

Note

+

The last entry in the array must be a NULL pointer.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_authenticator.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_authenticator.html new file mode 100644 index 00000000..897427ef --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_authenticator.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_free_authenticator - Free a krb5_authenticator structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_authenticator - Free a krb5_authenticator structure.

+
+
+void krb5_free_authenticator(krb5_context context, krb5_authenticator *val)
+
+ +
+
param
+

[in] context - Library context

+

[in] val - Authenticator structure to be freed

+
+
+

This function frees the contents of val and the structure itself.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_checksum.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_checksum.html new file mode 100644 index 00000000..3f366e65 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_checksum.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_free_checksum - Free a krb5_checksum structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_checksum - Free a krb5_checksum structure.

+
+
+void krb5_free_checksum(krb5_context context, krb5_checksum *val)
+
+ +
+
param
+

[in] context - Library context

+

[in] val - Checksum structure to be freed

+
+
+

This function frees the contents of val and the structure itself.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_checksum_contents.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_checksum_contents.html new file mode 100644 index 00000000..74e81e83 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_checksum_contents.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_free_checksum_contents - Free the contents of a krb5_checksum structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_checksum_contents - Free the contents of a krb5_checksum structure.

+
+
+void krb5_free_checksum_contents(krb5_context context, krb5_checksum *val)
+
+ +
+
param
+

[in] context - Library context

+

[in] val - Checksum structure to free contents of

+
+
+

This function frees the contents of val , but not the structure itself. It sets the checksum’s data pointer to null and (beginning in release 1.19) sets its length to zero.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_cksumtypes.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_cksumtypes.html new file mode 100644 index 00000000..7c9c207a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_cksumtypes.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_free_cksumtypes - Free an array of checksum types. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_context.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_context.html new file mode 100644 index 00000000..253bfb23 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_context.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_free_context - Free a krb5 library context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_cred_contents.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_cred_contents.html new file mode 100644 index 00000000..181d6d4f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_cred_contents.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_free_cred_contents - Free the contents of a krb5_creds structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_cred_contents - Free the contents of a krb5_creds structure.

+
+
+void krb5_free_cred_contents(krb5_context context, krb5_creds *val)
+
+ +
+
param
+

[in] context - Library context

+

[in] val - Credential structure to free contents of

+
+
+

This function frees the contents of val , but not the structure itself.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_creds.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_creds.html new file mode 100644 index 00000000..521beb0d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_creds.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_free_creds - Free a krb5_creds structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_creds - Free a krb5_creds structure.

+
+
+void krb5_free_creds(krb5_context context, krb5_creds *val)
+
+ +
+
param
+

[in] context - Library context

+

[in] val - Credential structure to be freed.

+
+
+

This function frees the contents of val and the structure itself.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_data.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_data.html new file mode 100644 index 00000000..341bd1ab --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_data.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_free_data - Free a krb5_data structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_data_contents.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_data_contents.html new file mode 100644 index 00000000..dbb44185 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_data_contents.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_free_data_contents - Free the contents of a krb5_data structure and zero the data field. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_data_contents - Free the contents of a krb5_data structure and zero the data field.

+
+
+void krb5_free_data_contents(krb5_context context, krb5_data *val)
+
+ +
+
param
+

[in] context - Library context

+

[in] val - Data structure to free contents of

+
+
+

This function frees the contents of val , but not the structure itself. It sets the structure’s data pointer to null and (beginning in release 1.19) sets its length to zero.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_default_realm.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_default_realm.html new file mode 100644 index 00000000..f2ebf4a8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_default_realm.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_free_default_realm - Free a default realm string returned by krb5_get_default_realm(). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_enctypes.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_enctypes.html new file mode 100644 index 00000000..3a8ffe25 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_enctypes.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_free_enctypes - Free an array of encryption types. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_error.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_error.html new file mode 100644 index 00000000..321051e3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_error.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_free_error - Free an error allocated by krb5_read_error() or krb5_sendauth(). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_error - Free an error allocated by krb5_read_error() or krb5_sendauth().

+
+
+void krb5_free_error(krb5_context context, krb5_error *val)
+
+ +
+
param
+

[in] context - Library context

+

[in] val - Error data structure to be freed

+
+
+

This function frees the contents of val and the structure itself.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_error_message.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_error_message.html new file mode 100644 index 00000000..010c0e38 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_error_message.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_free_error_message - Free an error message generated by krb5_get_error_message(). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_host_realm.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_host_realm.html new file mode 100644 index 00000000..b095c77c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_host_realm.html @@ -0,0 +1,162 @@ + + + + + + + + + krb5_free_host_realm - Free the memory allocated by krb5_get_host_realm(). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_host_realm - Free the memory allocated by krb5_get_host_realm().

+
+
+krb5_error_code krb5_free_host_realm(krb5_context context, char *const *realmlist)
+
+ +
+
param
+

[in] context - Library context

+

[in] realmlist - List of realm names to be released

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_keyblock.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_keyblock.html new file mode 100644 index 00000000..8a0a83f5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_keyblock.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_free_keyblock - Free a krb5_keyblock structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_keyblock_contents.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_keyblock_contents.html new file mode 100644 index 00000000..1e477ec9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_keyblock_contents.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_free_keyblock_contents - Free the contents of a krb5_keyblock structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_keyblock_contents - Free the contents of a krb5_keyblock structure.

+
+
+void krb5_free_keyblock_contents(krb5_context context, krb5_keyblock *key)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Keyblock to be freed

+
+
+

This function frees the contents of key , but not the structure itself.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_keytab_entry_contents.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_keytab_entry_contents.html new file mode 100644 index 00000000..ca780f4e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_keytab_entry_contents.html @@ -0,0 +1,161 @@ + + + + + + + + + krb5_free_keytab_entry_contents - Free the contents of a key table entry. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_keytab_entry_contents - Free the contents of a key table entry.

+
+
+krb5_error_code krb5_free_keytab_entry_contents(krb5_context context, krb5_keytab_entry *entry)
+
+ +
+
param
+

[in] context - Library context

+

[in] entry - Key table entry whose contents are to be freed

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+

Note

+

The pointer is not freed.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_principal.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_principal.html new file mode 100644 index 00000000..496366a4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_principal.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_free_principal - Free the storage assigned to a principal. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_string.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_string.html new file mode 100644 index 00000000..c02087a4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_string.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_free_string - Free a string allocated by a krb5 function. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_tgt_creds.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_tgt_creds.html new file mode 100644 index 00000000..f9027940 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_tgt_creds.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_free_tgt_creds - Free an array of credential structures. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_free_tgt_creds - Free an array of credential structures.

+
+
+void krb5_free_tgt_creds(krb5_context context, krb5_creds **tgts)
+
+ +
+
param
+

[in] context - Library context

+

[in] tgts - Null-terminated array of credentials to free

+
+
+
+

Note

+

The last entry in the array tgts must be a NULL pointer.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_ticket.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_ticket.html new file mode 100644 index 00000000..3e022993 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_ticket.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_free_ticket - Free a ticket. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_unparsed_name.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_unparsed_name.html new file mode 100644 index 00000000..a6faa009 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_free_unparsed_name.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_free_unparsed_name - Free a string representation of a principal. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_fwd_tgt_creds.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_fwd_tgt_creds.html new file mode 100644 index 00000000..16429b1b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_fwd_tgt_creds.html @@ -0,0 +1,173 @@ + + + + + + + + + krb5_fwd_tgt_creds - Get a forwarded TGT and format a KRB-CRED message. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_fwd_tgt_creds - Get a forwarded TGT and format a KRB-CRED message.

+
+
+krb5_error_code krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, const char *rhost, krb5_principal client, krb5_principal server, krb5_ccache cc, int forwardable, krb5_data *outbuf)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] rhost - Remote host

+

[in] client - Client principal of TGT

+

[in] server - Principal of server to receive TGT

+

[in] cc - Credential cache handle (NULL to use default)

+

[in] forwardable - Whether TGT should be forwardable

+

[out] outbuf - KRB-CRED message

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • ENOMEM Insufficient memory

  • +
  • KRB5_PRINC_NOMATCH Requested principal and ticket do not match

  • +
  • KRB5_NO_TKT_SUPPLIED Request did not supply a ticket

  • +
  • KRB5_CC_BADNAME Credential cache name or principal name malformed

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Get a TGT for use at the remote host rhost and format it into a KRB-CRED message. If rhost is NULL and server is of type #KRB5_NT_SRV_HST, the second component of server will be used.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_credentials.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_credentials.html new file mode 100644 index 00000000..bb68b8f9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_credentials.html @@ -0,0 +1,179 @@ + + + + + + + + + krb5_get_credentials - Get an additional ticket. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_credentials - Get an additional ticket.

+
+
+krb5_error_code krb5_get_credentials(krb5_context context, krb5_flags options, krb5_ccache ccache, krb5_creds *in_creds, krb5_creds **out_creds)
+
+ +
+
param
+

[in] context - Library context

+

[in] options - Options

+

[in] ccache - Credential cache handle

+

[in] in_creds - Input credentials

+

[out] out_creds - Output updated credentials

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Use ccache or a TGS exchange to get a service ticket matching in_creds .

+

Valid values for options are:

+
+
+
    +
  • #KRB5_GC_CACHED Search only credential cache for the ticket

  • +
  • #KRB5_GC_USER_USER Return a user to user authentication ticket

  • +
+
+

in_creds must be non-null. in_creds->client and in_creds->server must be filled in to specify the client and the server respectively. If any authorization data needs to be requested for the service ticket (such as restrictions on how the ticket can be used), specify it in in_creds->authdata ; otherwise set in_creds->authdata to NULL. The session key type is specified in in_creds->keyblock.enctype , if it is nonzero.

+
+

The expiration date is specified in in_creds->times.endtime . The KDC may return tickets with an earlier expiration date. If in_creds->times.endtime is set to 0, the latest possible expiration date will be requested.

+

Any returned ticket and intermediate ticket-granting tickets are stored in ccache .

+

Use krb5_free_creds() to free out_creds when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_credentials_renew.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_credentials_renew.html new file mode 100644 index 00000000..930f2fad --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_credentials_renew.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_get_credentials_renew — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_credentials_validate.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_credentials_validate.html new file mode 100644 index 00000000..6b2ded9f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_credentials_validate.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_get_credentials_validate — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_default_realm.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_default_realm.html new file mode 100644 index 00000000..a9a6e85e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_default_realm.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_get_default_realm - Retrieve the default realm. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_default_realm - Retrieve the default realm.

+
+
+krb5_error_code krb5_get_default_realm(krb5_context context, char **lrealm)
+
+ +
+
param
+

[in] context - Library context

+

[out] lrealm - Default realm name

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Retrieves the default realm to be used if no user-specified realm is available.

+

Use krb5_free_default_realm() to free lrealm when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_error_message.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_error_message.html new file mode 100644 index 00000000..8ec00800 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_error_message.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_get_error_message - Get the (possibly extended) error message for a code. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_error_message - Get the (possibly extended) error message for a code.

+
+
+const char *krb5_get_error_message(krb5_context ctx, krb5_error_code code)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] code - Error code

+
+
+

The behavior of krb5_get_error_message() is only defined the first time it is called after a failed call to a krb5 function using the same context, and only when the error code passed in is the same as that returned by the krb5 function.

+

This function never returns NULL, so its result may be used unconditionally as a C string.

+

The string returned by this function must be freed using krb5_free_error_message()

+
+

Note

+

Future versions may return the same string for the second and following calls.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_etype_info.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_etype_info.html new file mode 100644 index 00000000..3cb66001 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_etype_info.html @@ -0,0 +1,175 @@ + + + + + + + + + krb5_get_etype_info - Retrieve enctype, salt and s2kparams from KDC. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_etype_info - Retrieve enctype, salt and s2kparams from KDC.

+
+
+krb5_error_code krb5_get_etype_info(krb5_context context, krb5_principal principal, krb5_get_init_creds_opt *opt, krb5_enctype *enctype_out, krb5_data *salt_out, krb5_data *s2kparams_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] principal - Principal whose information is requested

+

[in] opt - Initial credential options

+

[out] enctype_out - The enctype chosen by KDC

+

[out] salt_out - Salt returned from KDC

+

[out] s2kparams_out - String-to-key parameters returned from KDC

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • A Kerberos error code

  • +
+
+
+

Send an initial ticket request for principal and extract the encryption type, salt type, and string-to-key parameters from the KDC response. If the KDC provides no etype-info, set enctype_out to ENCTYPE_NULL and set salt_out and s2kparams_out to empty. If the KDC etype-info provides no salt, compute the default salt and place it in salt_out . If the KDC etype-info provides no string-to-key parameters, set s2kparams_out to empty.

+
+

opt may be used to specify options which affect the initial request, such as request encryption types or a FAST armor cache (see krb5_get_init_creds_opt_set_etype_list() and krb5_get_init_creds_opt_set_fast_ccache_name()).

+
+

Use krb5_free_data_contents() to free salt_out and s2kparams_out when they are no longer needed.

+
+

Note

+

New in 1.17

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_fallback_host_realm.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_fallback_host_realm.html new file mode 100644 index 00000000..41d978b7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_fallback_host_realm.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_get_fallback_host_realm — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_fallback_host_realm

+
+
+krb5_error_code krb5_get_fallback_host_realm(krb5_context context, krb5_data *hdata, char ***realmsp)
+
+ +
+
param
+

[in] context - Library context

+

[in] hdata - Host name (or NULL)

+

[out] realmsp - Null-terminated list of realm names

+
+
+

Fill in realmsp with a pointer to a null-terminated list of realm names obtained through heuristics or insecure resolution methods which have lower priority than KDC referrals.

+

If host is NULL, the local host’s realms are determined.

+

Use krb5_free_host_realm() to release realmsp when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_host_realm.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_host_realm.html new file mode 100644 index 00000000..8594425c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_host_realm.html @@ -0,0 +1,167 @@ + + + + + + + + + krb5_get_host_realm - Get the Kerberos realm names for a host. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_host_realm - Get the Kerberos realm names for a host.

+
+
+krb5_error_code krb5_get_host_realm(krb5_context context, const char *host, char ***realmsp)
+
+ +
+
param
+

[in] context - Library context

+

[in] host - Host name (or NULL)

+

[out] realmsp - Null-terminated list of realm names

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • ENOMEM Insufficient memory

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Fill in realmsp with a pointer to a null-terminated list of realm names. If there are no known realms for the host, a list containing the referral (empty) realm is returned.

+

If host is NULL, the local host’s realms are determined.

+

Use krb5_free_host_realm() to release realmsp when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_in_tkt_with_keytab.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_in_tkt_with_keytab.html new file mode 100644 index 00000000..d546b065 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_in_tkt_with_keytab.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_get_in_tkt_with_keytab — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_in_tkt_with_keytab

+
+
+krb5_error_code krb5_get_in_tkt_with_keytab(krb5_context context, krb5_flags options, krb5_address *const *addrs, krb5_enctype *ktypes, krb5_preauthtype *pre_auth_types, krb5_keytab arg_keytab, krb5_ccache ccache, krb5_creds *creds, krb5_kdc_rep **ret_as_reply)
+
+ +
+
param
+

context

+

options

+

addrs

+

ktypes

+

pre_auth_types

+

arg_keytab

+

ccache

+

creds

+

ret_as_reply

+
+
+

DEPRECATED Replaced by krb5_get_init_creds_keytab().

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_in_tkt_with_password.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_in_tkt_with_password.html new file mode 100644 index 00000000..d303e0b9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_in_tkt_with_password.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_get_in_tkt_with_password — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_in_tkt_with_password

+
+
+krb5_error_code krb5_get_in_tkt_with_password(krb5_context context, krb5_flags options, krb5_address *const *addrs, krb5_enctype *ktypes, krb5_preauthtype *pre_auth_types, const char *password, krb5_ccache ccache, krb5_creds *creds, krb5_kdc_rep **ret_as_reply)
+
+ +
+
param
+

context

+

options

+

addrs

+

ktypes

+

pre_auth_types

+

password

+

ccache

+

creds

+

ret_as_reply

+
+
+

DEPRECATED Replaced by krb5_get_init_creds_password().

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_in_tkt_with_skey.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_in_tkt_with_skey.html new file mode 100644 index 00000000..11a5661e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_in_tkt_with_skey.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_get_in_tkt_with_skey — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_in_tkt_with_skey

+
+
+krb5_error_code krb5_get_in_tkt_with_skey(krb5_context context, krb5_flags options, krb5_address *const *addrs, krb5_enctype *ktypes, krb5_preauthtype *pre_auth_types, const krb5_keyblock *key, krb5_ccache ccache, krb5_creds *creds, krb5_kdc_rep **ret_as_reply)
+
+ +
+
param
+

context

+

options

+

addrs

+

ktypes

+

pre_auth_types

+

key

+

ccache

+

creds

+

ret_as_reply

+
+
+

DEPRECATED Replaced by krb5_get_init_creds().

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_keytab.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_keytab.html new file mode 100644 index 00000000..760fc283 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_keytab.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_get_init_creds_keytab - Get initial credentials using a key table. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_keytab - Get initial credentials using a key table.

+
+
+krb5_error_code krb5_get_init_creds_keytab(krb5_context context, krb5_creds *creds, krb5_principal client, krb5_keytab arg_keytab, krb5_deltat start_time, const char *in_tkt_service, krb5_get_init_creds_opt *k5_gic_options)
+
+ +
+
param
+

[in] context - Library context

+

[out] creds - New credentials

+

[in] client - Client principal

+

[in] arg_keytab - Key table handle

+

[in] start_time - Time when ticket becomes valid (0 for now)

+

[in] in_tkt_service - Service name of initial credentials (or NULL)

+

[in] k5_gic_options - Initial credential options

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function requests KDC for an initial credentials for client using a client key stored in arg_keytab . If in_tkt_service is specified, it is parsed as a principal name (with the realm ignored) and used as the service principal for the request; otherwise the ticket-granting service is used.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_alloc.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_alloc.html new file mode 100644 index 00000000..584d8035 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_alloc.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_get_init_creds_opt_alloc - Allocate a new initial credential options structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_alloc - Allocate a new initial credential options structure.

+
+
+krb5_error_code krb5_get_init_creds_opt_alloc(krb5_context context, krb5_get_init_creds_opt **opt)
+
+ +
+
param
+

[in] context - Library context

+

[out] opt - New options structure

+
+
+
+
retval
+
    +
  • 0 - Success; Kerberos errors otherwise.

  • +
+
+
+

This function is the preferred way to create an options structure for getting initial credentials, and is required to make use of certain options. Use krb5_get_init_creds_opt_free() to free opt when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_free.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_free.html new file mode 100644 index 00000000..622b94a1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_free.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_get_init_creds_opt_free - Free initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_get_fast_flags.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_get_fast_flags.html new file mode 100644 index 00000000..9f189db8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_get_fast_flags.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_get_init_creds_opt_get_fast_flags - Retrieve FAST flags from initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_get_fast_flags - Retrieve FAST flags from initial credential options.

+
+
+krb5_error_code krb5_get_init_creds_opt_get_fast_flags(krb5_context context, krb5_get_init_creds_opt *opt, krb5_flags *out_flags)
+
+ +
+
param
+

[in] context - Library context

+

[in] opt - Options

+

[out] out_flags - FAST flags

+
+
+
+
retval
+
    +
  • 0 - Success; Kerberos errors otherwise.

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_init.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_init.html new file mode 100644 index 00000000..6bbaa0a0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_init.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_get_init_creds_opt_init — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_address_list.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_address_list.html new file mode 100644 index 00000000..a4a03beb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_address_list.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_get_init_creds_opt_set_address_list - Set address restrictions in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_anonymous.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_anonymous.html new file mode 100644 index 00000000..104511d1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_anonymous.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_get_init_creds_opt_set_anonymous - Set or unset the anonymous flag in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_anonymous - Set or unset the anonymous flag in initial credential options.

+
+
+void krb5_get_init_creds_opt_set_anonymous(krb5_get_init_creds_opt *opt, int anonymous)
+
+ +
+
param
+

[in] opt - Options structure

+

[in] anonymous - Whether to make an anonymous request

+
+
+

This function may be used to request anonymous credentials from the KDC by setting anonymous to non-zero. Note that anonymous credentials are only a request; clients must verify that credentials are anonymous if that is a requirement.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_canonicalize.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_canonicalize.html new file mode 100644 index 00000000..c424621a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_canonicalize.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_get_init_creds_opt_set_canonicalize - Set or unset the canonicalize flag in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_canonicalize - Set or unset the canonicalize flag in initial credential options.

+
+
+void krb5_get_init_creds_opt_set_canonicalize(krb5_get_init_creds_opt *opt, int canonicalize)
+
+ +
+
param
+

[in] opt - Options structure

+

[in] canonicalize - Whether to canonicalize client principal

+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_change_password_prompt.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_change_password_prompt.html new file mode 100644 index 00000000..97f4aaac --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_change_password_prompt.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_get_init_creds_opt_set_change_password_prompt - Set or unset change-password-prompt flag in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_change_password_prompt - Set or unset change-password-prompt flag in initial credential options.

+
+
+void krb5_get_init_creds_opt_set_change_password_prompt(krb5_get_init_creds_opt *opt, int prompt)
+
+ +
+
param
+

[in] opt - Options structure

+

[in] prompt - Whether to prompt to change password

+
+
+

This flag is on by default. It controls whether krb5_get_init_creds_password() will react to an expired-password error by prompting for a new password and attempting to change the old one.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_etype_list.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_etype_list.html new file mode 100644 index 00000000..f8480408 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_etype_list.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_get_init_creds_opt_set_etype_list - Set allowable encryption types in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_etype_list - Set allowable encryption types in initial credential options.

+
+
+void krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt, krb5_enctype *etype_list, int etype_list_length)
+
+ +
+
param
+

[in] opt - Options structure

+

[in] etype_list - Array of encryption types

+

[in] etype_list_length - Length of etype_list

+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_expire_callback.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_expire_callback.html new file mode 100644 index 00000000..3d00dbfa --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_expire_callback.html @@ -0,0 +1,167 @@ + + + + + + + + + krb5_get_init_creds_opt_set_expire_callback - Set an expiration callback in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_expire_callback - Set an expiration callback in initial credential options.

+
+
+krb5_error_code krb5_get_init_creds_opt_set_expire_callback(krb5_context context, krb5_get_init_creds_opt *opt, krb5_expire_callback_func cb, void *data)
+
+ +
+
param
+

[in] context - Library context

+

[in] opt - Options structure

+

[in] cb - Callback function

+

[in] data - Callback argument

+
+
+

Set a callback to receive password and account expiration times.

+
+

cb will be invoked if and only if credentials are successfully acquired. The callback will receive the context from the calling function and the data argument supplied with this API. The remaining arguments should be interpreted as follows:

+
+

If is_last_req is true, then the KDC reply contained last-req entries which unambiguously indicated the password expiration, account expiration, or both. (If either value was not present, the corresponding argument will be 0.) Furthermore, a non-zero password_expiration should be taken as a suggestion from the KDC that a warning be displayed.

+

If is_last_req is false, then account_expiration will be 0 and password_expiration will contain the expiration time of either the password or account, or 0 if no expiration time was indicated in the KDC reply. The callback should independently decide whether to display a password expiration warning.

+

Note that cb may be invoked even if credentials are being acquired for the kadmin/changepw service in order to change the password. It is the caller’s responsibility to avoid displaying a password expiry warning in this case.

+
+

Warning

+

Setting an expire callback with this API will cause krb5_get_init_creds_password() not to send password expiry warnings to the prompter, as it ordinarily may.

+
+
+

Note

+

New in 1.9

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache.html new file mode 100644 index 00000000..70be5633 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_get_init_creds_opt_set_fast_ccache - Set FAST armor cache in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_fast_ccache - Set FAST armor cache in initial credential options.

+
+
+krb5_error_code krb5_get_init_creds_opt_set_fast_ccache(krb5_context context, krb5_get_init_creds_opt *opt, krb5_ccache ccache)
+
+ +
+
param
+

[in] context - Library context

+

[in] opt - Options

+

[in] ccache - Credential cache handle

+
+
+

This function is similar to krb5_get_init_creds_opt_set_fast_ccache_name(), but uses a credential cache handle instead of a name.

+
+

Note

+

New in 1.9

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache_name.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache_name.html new file mode 100644 index 00000000..adb50036 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache_name.html @@ -0,0 +1,153 @@ + + + + + + + + + krb5_get_init_creds_opt_set_fast_ccache_name - Set location of FAST armor ccache in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_fast_ccache_name - Set location of FAST armor ccache in initial credential options.

+
+
+krb5_error_code krb5_get_init_creds_opt_set_fast_ccache_name(krb5_context context, krb5_get_init_creds_opt *opt, const char *fast_ccache_name)
+
+ +
+
param
+

[in] context - Library context

+

[in] opt - Options

+

[in] fast_ccache_name - Credential cache name

+
+
+

Sets the location of a credential cache containing an armor ticket to protect an initial credential exchange using the FAST protocol extension.

+

In version 1.7, setting an armor ccache requires that FAST be used for the exchange. In version 1.8 or later, setting the armor ccache causes FAST to be used if the KDC supports it; krb5_get_init_creds_opt_set_fast_flags() must be used to require that FAST be used.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_fast_flags.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_fast_flags.html new file mode 100644 index 00000000..6c011196 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_fast_flags.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_get_init_creds_opt_set_fast_flags - Set FAST flags in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_fast_flags - Set FAST flags in initial credential options.

+
+
+krb5_error_code krb5_get_init_creds_opt_set_fast_flags(krb5_context context, krb5_get_init_creds_opt *opt, krb5_flags flags)
+
+ +
+
param
+

[in] context - Library context

+

[in] opt - Options

+

[in] flags - FAST flags

+
+
+
+
retval
+
    +
  • 0 - Success; Kerberos errors otherwise.

  • +
+
+
+

The following flag values are valid:

+
+
    +
  • #KRB5_FAST_REQUIRED - Require FAST to be used

  • +
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_forwardable.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_forwardable.html new file mode 100644 index 00000000..793b939d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_forwardable.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_get_init_creds_opt_set_forwardable - Set or unset the forwardable flag in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_forwardable - Set or unset the forwardable flag in initial credential options.

+
+
+void krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt, int forwardable)
+
+ +
+
param
+

[in] opt - Options structure

+

[in] forwardable - Whether credentials should be forwardable

+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_in_ccache.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_in_ccache.html new file mode 100644 index 00000000..165986df --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_in_ccache.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_get_init_creds_opt_set_in_ccache - Set an input credential cache in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_in_ccache - Set an input credential cache in initial credential options.

+
+
+krb5_error_code krb5_get_init_creds_opt_set_in_ccache(krb5_context context, krb5_get_init_creds_opt *opt, krb5_ccache ccache)
+
+ +
+
param
+

[in] context - Library context

+

[in] opt - Options

+

[in] ccache - Credential cache handle

+
+
+

If an input credential cache is set, then the krb5_get_init_creds family of APIs will read settings from it. Setting an input ccache is desirable when the application wishes to perform authentication in the same way (using the same preauthentication mechanisms, and making the same non-security- sensitive choices) as the previous authentication attempt, which stored information in the passed-in ccache.

+
+

Note

+

New in 1.11

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_out_ccache.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_out_ccache.html new file mode 100644 index 00000000..a57acf2d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_out_ccache.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_get_init_creds_opt_set_out_ccache - Set an output credential cache in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_out_ccache - Set an output credential cache in initial credential options.

+
+
+krb5_error_code krb5_get_init_creds_opt_set_out_ccache(krb5_context context, krb5_get_init_creds_opt *opt, krb5_ccache ccache)
+
+ +
+
param
+

[in] context - Library context

+

[in] opt - Options

+

[in] ccache - Credential cache handle

+
+
+

If an output credential cache is set, then the krb5_get_init_creds family of APIs will write credentials to it. Setting an output ccache is desirable both because it simplifies calling code and because it permits the krb5_get_init_creds APIs to write out configuration information about the realm to the ccache.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_pa.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_pa.html new file mode 100644 index 00000000..131a76d0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_pa.html @@ -0,0 +1,153 @@ + + + + + + + + + krb5_get_init_creds_opt_set_pa - Supply options for preauthentication in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_pa - Supply options for preauthentication in initial credential options.

+
+
+krb5_error_code krb5_get_init_creds_opt_set_pa(krb5_context context, krb5_get_init_creds_opt *opt, const char *attr, const char *value)
+
+ +
+
param
+

[in] context - Library context

+

[in] opt - Options structure

+

[in] attr - Preauthentication option name

+

[in] value - Preauthentication option value

+
+
+

This function allows the caller to supply options for preauthentication. The values of attr and value are supplied to each preauthentication module available within context .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_pac_request.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_pac_request.html new file mode 100644 index 00000000..58a337d9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_pac_request.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_get_init_creds_opt_set_pac_request - Ask the KDC to include or not include a PAC in the ticket. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_pac_request - Ask the KDC to include or not include a PAC in the ticket.

+
+
+krb5_error_code krb5_get_init_creds_opt_set_pac_request(krb5_context context, krb5_get_init_creds_opt *opt, krb5_boolean req_pac)
+
+ +
+
param
+

[in] context - Library context

+

[in] opt - Options structure

+

[in] req_pac - Whether to request a PAC or not

+
+
+

If this option is set, the AS request will include a PAC-REQUEST pa-data item explicitly asking the KDC to either include or not include a privilege attribute certificate in the ticket authorization data. By default, no request is made; typically the KDC will default to including a PAC if it supports them.

+
+

Note

+

New in 1.15

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_preauth_list.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_preauth_list.html new file mode 100644 index 00000000..94f4b41c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_preauth_list.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_get_init_creds_opt_set_preauth_list - Set preauthentication types in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_preauth_list - Set preauthentication types in initial credential options.

+
+
+void krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, krb5_preauthtype *preauth_list, int preauth_list_length)
+
+ +
+
param
+

[in] opt - Options structure

+

[in] preauth_list - Array of preauthentication types

+

[in] preauth_list_length - Length of preauth_list

+
+
+

This function can be used to perform optimistic preauthentication when getting initial credentials, in combination with krb5_get_init_creds_opt_set_salt() and krb5_get_init_creds_opt_set_pa().

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_proxiable.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_proxiable.html new file mode 100644 index 00000000..fb570f30 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_proxiable.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_get_init_creds_opt_set_proxiable - Set or unset the proxiable flag in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_renew_life.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_renew_life.html new file mode 100644 index 00000000..b671b95a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_renew_life.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_get_init_creds_opt_set_renew_life - Set the ticket renewal lifetime in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_responder.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_responder.html new file mode 100644 index 00000000..1f2ff115 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_responder.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_get_init_creds_opt_set_responder - Set the responder function in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_responder - Set the responder function in initial credential options.

+
+
+krb5_error_code krb5_get_init_creds_opt_set_responder(krb5_context context, krb5_get_init_creds_opt *opt, krb5_responder_fn responder, void *data)
+
+ +
+
param
+

[in] context - Library context

+

[in] opt - Options structure

+

[in] responder - Responder function

+

[in] data - Responder data argument

+
+
+
+

Note

+

New in 1.11

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_salt.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_salt.html new file mode 100644 index 00000000..6609f377 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_salt.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_get_init_creds_opt_set_salt - Set salt for optimistic preauthentication in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt_set_salt - Set salt for optimistic preauthentication in initial credential options.

+
+
+void krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, krb5_data *salt)
+
+ +
+
param
+

[in] opt - Options structure

+

[in] salt - Salt data

+
+
+

When getting initial credentials with a password, a salt string it used to convert the password to a key. Normally this salt is obtained from the first KDC reply, but when performing optimistic preauthentication, the client may need to supply the salt string with this function.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_tkt_life.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_tkt_life.html new file mode 100644 index 00000000..ef0e23ee --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_opt_set_tkt_life.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_get_init_creds_opt_set_tkt_life - Set the ticket lifetime in initial credential options. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_password.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_password.html new file mode 100644 index 00000000..db25a9cb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_init_creds_password.html @@ -0,0 +1,179 @@ + + + + + + + + + krb5_get_init_creds_password - Get initial credentials using a password. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_password - Get initial credentials using a password.

+
+
+krb5_error_code krb5_get_init_creds_password(krb5_context context, krb5_creds *creds, krb5_principal client, const char *password, krb5_prompter_fct prompter, void *data, krb5_deltat start_time, const char *in_tkt_service, krb5_get_init_creds_opt *k5_gic_options)
+
+ +
+
param
+

[in] context - Library context

+

[out] creds - New credentials

+

[in] client - Client principal

+

[in] password - Password (or NULL)

+

[in] prompter - Prompter function

+

[in] data - Prompter callback data

+

[in] start_time - Time when ticket becomes valid (0 for now)

+

[in] in_tkt_service - Service name of initial credentials (or NULL)

+

[in] k5_gic_options - Initial credential options

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • EINVAL Invalid argument

  • +
  • KRB5_KDC_UNREACH Cannot contact any KDC for requested realm

  • +
  • KRB5_PREAUTH_FAILED Generic Pre-athentication failure

  • +
  • KRB5_LIBOS_PWDINTR Password read interrupted

  • +
  • KRB5_REALM_CANT_RESOLVE Cannot resolve network address for KDC in requested realm

  • +
  • KRB5KDC_ERR_KEY_EXP Password has expired

  • +
  • KRB5_LIBOS_BADPWDMATCH Password mismatch

  • +
  • KRB5_CHPW_PWDNULL New password cannot be zero length

  • +
  • KRB5_CHPW_FAIL Password change failed

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function requests KDC for an initial credentials for client using password . If password is NULL, a password will be prompted for using prompter if necessary. If in_tkt_service is specified, it is parsed as a principal name (with the realm ignored) and used as the service principal for the request; otherwise the ticket-granting service is used.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_permitted_enctypes.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_permitted_enctypes.html new file mode 100644 index 00000000..917e809d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_permitted_enctypes.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_get_permitted_enctypes - Return a list of encryption types permitted for session keys. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_permitted_enctypes - Return a list of encryption types permitted for session keys.

+
+
+krb5_error_code krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes)
+
+ +
+
param
+

[in] context - Library context

+

[out] ktypes - Zero-terminated list of encryption types

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function returns the list of encryption types permitted for session keys within context , as determined by configuration or by a previous call to krb5_set_default_tgs_enctypes().

+

Use krb5_free_enctypes() to free ktypes when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_profile.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_profile.html new file mode 100644 index 00000000..e8b92e71 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_profile.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_get_profile - Retrieve configuration profile from the context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_profile - Retrieve configuration profile from the context.

+
+
+krb5_error_code krb5_get_profile(krb5_context context, struct _profile_t **profile)
+
+ +
+
param
+

[in] context - Library context

+

[out] profile - Pointer to data read from a configuration file

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function creates a new profile object that reflects profile in the supplied context .

+

The profile object may be freed with profile_release() function. See profile.h and profile API for more details.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_prompt_types.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_prompt_types.html new file mode 100644 index 00000000..60406fc3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_prompt_types.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_get_prompt_types - Get prompt types array from a context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_prompt_types - Get prompt types array from a context.

+
+
+krb5_prompt_type *krb5_get_prompt_types(krb5_context context)
+
+ +
+
param
+

[in] context - Library context

+
+
+
+
return
+
    +
  • Pointer to an array of prompt types corresponding to the prompter’s prompts arguments. Each type has one of the following values: #KRB5_PROMPT_TYPE_PASSWORD #KRB5_PROMPT_TYPE_NEW_PASSWORD #KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN #KRB5_PROMPT_TYPE_PREAUTH

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_renewed_creds.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_renewed_creds.html new file mode 100644 index 00000000..654c48b1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_renewed_creds.html @@ -0,0 +1,167 @@ + + + + + + + + + krb5_get_renewed_creds - Get renewed credential from KDC using an existing credential. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_renewed_creds - Get renewed credential from KDC using an existing credential.

+
+
+krb5_error_code krb5_get_renewed_creds(krb5_context context, krb5_creds *creds, krb5_principal client, krb5_ccache ccache, const char *in_tkt_service)
+
+ +
+
param
+

[in] context - Library context

+

[out] creds - Renewed credentials

+

[in] client - Client principal name

+

[in] ccache - Credential cache

+

[in] in_tkt_service - Server principal string (or NULL)

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function gets a renewed credential using an existing one from ccache . If in_tkt_service is specified, it is parsed (with the realm part ignored) and used as the server principal of the credential; otherwise, the ticket-granting service is used.

+

If successful, the renewed credential is placed in creds .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_server_rcache.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_server_rcache.html new file mode 100644 index 00000000..e0c037ff --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_server_rcache.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_get_server_rcache - Generate a replay cache object for server use and open it. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_server_rcache - Generate a replay cache object for server use and open it.

+
+
+krb5_error_code krb5_get_server_rcache(krb5_context context, const krb5_data *piece, krb5_rcache *rcptr)
+
+ +
+
param
+

[in] context - Library context

+

[in] piece - Unused (replay cache identifier)

+

[out] rcptr - Handle to an open rcache

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a handle to the default replay cache. Use krb5_rc_close() to close rcptr when it is no longer needed.

+
+

Note

+

Prior to release 1.18, this function creates a handle to a different replay cache for each unique value of piece .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_time_offsets.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_time_offsets.html new file mode 100644 index 00000000..61f73adf --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_time_offsets.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_get_time_offsets - Return the time offsets from the os context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_time_offsets - Return the time offsets from the os context.

+
+
+krb5_error_code krb5_get_time_offsets(krb5_context context, krb5_timestamp *seconds, krb5_int32 *microseconds)
+
+ +
+
param
+

[in] context - Library context

+

[out] seconds - Time offset, seconds portion

+

[out] microseconds - Time offset, microseconds portion

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function returns the time offsets in context .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_validated_creds.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_validated_creds.html new file mode 100644 index 00000000..a9230042 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_get_validated_creds.html @@ -0,0 +1,172 @@ + + + + + + + + + krb5_get_validated_creds - Get validated credentials from the KDC. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_validated_creds - Get validated credentials from the KDC.

+
+
+krb5_error_code krb5_get_validated_creds(krb5_context context, krb5_creds *creds, krb5_principal client, krb5_ccache ccache, const char *in_tkt_service)
+
+ +
+
param
+

[in] context - Library context

+

[out] creds - Validated credentials

+

[in] client - Client principal name

+

[in] ccache - Credential cache

+

[in] in_tkt_service - Server principal string (or NULL)

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • KRB5_NO_2ND_TKT Request missing second ticket

  • +
  • KRB5_NO_TKT_SUPPLIED Request did not supply a ticket

  • +
  • KRB5_PRINC_NOMATCH Requested principal and ticket do not match

  • +
  • KRB5_KDCREP_MODIFIED KDC reply did not match expectations

  • +
  • KRB5_KDCREP_SKEW Clock skew too great in KDC reply

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function gets a validated credential using a postdated credential from ccache . If in_tkt_service is specified, it is parsed (with the realm part ignored) and used as the server principal of the credential; otherwise, the ticket-granting service is used.

+

If successful, the validated credential is placed in creds .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_context.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_context.html new file mode 100644 index 00000000..af327010 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_context.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_init_context - Create a krb5 library context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_context - Create a krb5 library context.

+
+
+krb5_error_code krb5_init_context(krb5_context *context)
+
+ +
+
param
+

[out] context - Library context

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

The context must be released by calling krb5_free_context() when it is no longer needed.

+
+

Warning

+

Any program or module that needs the Kerberos code to not trust the environment must use krb5_init_secure_context(), or clean out the environment.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_context_profile.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_context_profile.html new file mode 100644 index 00000000..595e064c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_context_profile.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_init_context_profile - Create a krb5 library context using a specified profile. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_context_profile - Create a krb5 library context using a specified profile.

+
+
+krb5_error_code krb5_init_context_profile(struct _profile_t *profile, krb5_flags flags, krb5_context *context)
+
+ +
+
param
+

[in] profile - Profile object (NULL to create default profile)

+

[in] flags - Context initialization flags

+

[out] context - Library context

+
+
+

Create a context structure, optionally using a specified profile and initialization flags. If profile is NULL, the default profile will be created from config files. If profile is non-null, a copy of it will be made for the new context; the caller should still clean up its copy. Valid flag values are:

+
+
    +
  • #KRB5_INIT_CONTEXT_SECURE Ignore environment variables

  • +
  • #KRB5_INIT_CONTEXT_KDC Use KDC configuration if creating profile

  • +
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_free.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_free.html new file mode 100644 index 00000000..fa1a3a13 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_free.html @@ -0,0 +1,153 @@ + + + + + + + + + krb5_init_creds_free - Free an initial credentials context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_creds_free - Free an initial credentials context.

+
+
+void krb5_init_creds_free(krb5_context context, krb5_init_creds_context ctx)
+
+ +
+
param
+

[in] context - Library context

+

[in] ctx - Initial credentials context

+
+
+
+

context must be the same as the one passed to krb5_init_creds_init() for this initial credentials context.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get.html new file mode 100644 index 00000000..f5d82127 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get.html @@ -0,0 +1,161 @@ + + + + + + + + + krb5_init_creds_get - Acquire credentials using an initial credentials context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_creds_get - Acquire credentials using an initial credentials context.

+
+
+krb5_error_code krb5_init_creds_get(krb5_context context, krb5_init_creds_context ctx)
+
+ +
+
param
+

[in] context - Library context

+

[in] ctx - Initial credentials context

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function synchronously obtains credentials using a context created by krb5_init_creds_init(). On successful return, the credentials can be retrieved with krb5_init_creds_get_creds().

+
+

context must be the same as the one passed to krb5_init_creds_init() for this initial credentials context.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get_creds.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get_creds.html new file mode 100644 index 00000000..cc7320eb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get_creds.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_init_creds_get_creds - Retrieve acquired credentials from an initial credentials context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_creds_get_creds - Retrieve acquired credentials from an initial credentials context.

+
+
+krb5_error_code krb5_init_creds_get_creds(krb5_context context, krb5_init_creds_context ctx, krb5_creds *creds)
+
+ +
+
param
+

[in] context - Library context

+

[in] ctx - Initial credentials context

+

[out] creds - Acquired credentials

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function copies the acquired initial credentials from ctx into creds , after the successful completion of krb5_init_creds_get() or krb5_init_creds_step(). Use krb5_free_cred_contents() to free creds when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get_error.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get_error.html new file mode 100644 index 00000000..42ae200c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get_error.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_init_creds_get_error - Get the last error from KDC from an initial credentials context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_creds_get_error - Get the last error from KDC from an initial credentials context.

+
+
+krb5_error_code krb5_init_creds_get_error(krb5_context context, krb5_init_creds_context ctx, krb5_error **error)
+
+ +
+
param
+

[in] context - Library context

+

[in] ctx - Initial credentials context

+

[out] error - Error from KDC, or NULL if none was received

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get_times.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get_times.html new file mode 100644 index 00000000..1f17b9e3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_get_times.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_init_creds_get_times - Retrieve ticket times from an initial credentials context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_creds_get_times - Retrieve ticket times from an initial credentials context.

+
+
+krb5_error_code krb5_init_creds_get_times(krb5_context context, krb5_init_creds_context ctx, krb5_ticket_times *times)
+
+ +
+
param
+

[in] context - Library context

+

[in] ctx - Initial credentials context

+

[out] times - Ticket times for acquired credentials

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

The initial credentials context must have completed obtaining credentials via either krb5_init_creds_get() or krb5_init_creds_step().

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_init.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_init.html new file mode 100644 index 00000000..ace909ae --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_init.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_init_creds_init - Create a context for acquiring initial credentials. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_creds_init - Create a context for acquiring initial credentials.

+
+
+krb5_error_code krb5_init_creds_init(krb5_context context, krb5_principal client, krb5_prompter_fct prompter, void *data, krb5_deltat start_time, krb5_get_init_creds_opt *options, krb5_init_creds_context *ctx)
+
+ +
+
param
+

[in] context - Library context

+

[in] client - Client principal to get initial creds for

+

[in] prompter - Prompter callback

+

[in] data - Prompter callback argument

+

[in] start_time - Time when credentials become valid (0 for now)

+

[in] options - Options structure (NULL for default)

+

[out] ctx - New initial credentials context

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a new context for acquiring initial credentials. Use krb5_init_creds_free() to free ctx when it is no longer needed.

+

Any subsequent calls to krb5_init_creds_step(), krb5_init_creds_get(), or krb5_init_creds_free() for this initial credentials context must use the same context argument as the one passed to this function.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_set_keytab.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_set_keytab.html new file mode 100644 index 00000000..359f2269 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_set_keytab.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_init_creds_set_keytab - Specify a keytab to use for acquiring initial credentials. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_creds_set_keytab - Specify a keytab to use for acquiring initial credentials.

+
+
+krb5_error_code krb5_init_creds_set_keytab(krb5_context context, krb5_init_creds_context ctx, krb5_keytab keytab)
+
+ +
+
param
+

[in] context - Library context

+

[in] ctx - Initial credentials context

+

[in] keytab - Key table handle

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function supplies a keytab containing the client key for an initial credentials request.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_set_password.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_set_password.html new file mode 100644 index 00000000..1c723871 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_set_password.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_init_creds_set_password - Set a password for acquiring initial credentials. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_creds_set_password - Set a password for acquiring initial credentials.

+
+
+krb5_error_code krb5_init_creds_set_password(krb5_context context, krb5_init_creds_context ctx, const char *password)
+
+ +
+
param
+

[in] context - Library context

+

[in] ctx - Initial credentials context

+

[in] password - Password

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function supplies a password to be used to construct the client key for an initial credentials request.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_set_service.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_set_service.html new file mode 100644 index 00000000..0aacd833 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_set_service.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_init_creds_set_service - Specify a service principal for acquiring initial credentials. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_creds_set_service - Specify a service principal for acquiring initial credentials.

+
+
+krb5_error_code krb5_init_creds_set_service(krb5_context context, krb5_init_creds_context ctx, const char *service)
+
+ +
+
param
+

[in] context - Library context

+

[in] ctx - Initial credentials context

+

[in] service - Service principal string

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function supplies a service principal string to acquire initial credentials for instead of the default krbtgt service. service is parsed as a principal name; any realm part is ignored.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_step.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_step.html new file mode 100644 index 00000000..41d643c3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_creds_step.html @@ -0,0 +1,167 @@ + + + + + + + + + krb5_init_creds_step - Get the next KDC request for acquiring initial credentials. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_creds_step - Get the next KDC request for acquiring initial credentials.

+
+
+krb5_error_code krb5_init_creds_step(krb5_context context, krb5_init_creds_context ctx, krb5_data *in, krb5_data *out, krb5_data *realm, unsigned int *flags)
+
+ +
+
param
+

[in] context - Library context

+

[in] ctx - Initial credentials context

+

[in] in - KDC response (empty on the first call)

+

[out] out - Next KDC request

+

[out] realm - Realm for next KDC request

+

[out] flags - Output flags

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function constructs the next KDC request in an initial credential exchange, allowing the caller to control the transport of KDC requests and replies. On the first call, in should be set to an empty buffer; on subsequent calls, it should be set to the KDC’s reply to the previous request.

+

If more requests are needed, flags will be set to #KRB5_INIT_CREDS_STEP_FLAG_CONTINUE and the next request will be placed in out . If no more requests are needed, flags will not contain #KRB5_INIT_CREDS_STEP_FLAG_CONTINUE and out will be empty.

+

If this function returns KRB5KRB_ERR_RESPONSE_TOO_BIG , the caller should transmit the next request using TCP rather than UDP. If this function returns any other error, the initial credential exchange has failed.

+
+

context must be the same as the one passed to krb5_init_creds_init() for this initial credentials context.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_keyblock.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_keyblock.html new file mode 100644 index 00000000..5b41041a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_keyblock.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_init_keyblock - Initialize an empty krb5_keyblock . — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_keyblock - Initialize an empty krb5_keyblock .

+
+
+krb5_error_code krb5_init_keyblock(krb5_context context, krb5_enctype enctype, size_t length, krb5_keyblock **out)
+
+ +
+
param
+

[in] context - Library context

+

[in] enctype - Encryption type

+

[in] length - Length of keyblock (or 0)

+

[out] out - New keyblock structure

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Initialize a new keyblock and allocate storage for the contents of the key. It is legal to pass in a length of 0, in which case contents are left unallocated. Use krb5_free_keyblock() to free out when it is no longer needed.

+
+

Note

+

If length is set to 0, contents are left unallocated.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_random_key.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_random_key.html new file mode 100644 index 00000000..2af5648f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_random_key.html @@ -0,0 +1,153 @@ + + + + + + + + + krb5_init_random_key — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_secure_context.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_secure_context.html new file mode 100644 index 00000000..fdfdac95 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_init_secure_context.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_init_secure_context - Create a krb5 library context using only configuration files. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_init_secure_context - Create a krb5 library context using only configuration files.

+
+
+krb5_error_code krb5_init_secure_context(krb5_context *context)
+
+ +
+
param
+

[out] context - Library context

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Create a context structure, using only system configuration files. All information passed through the environment variables is ignored.

+

The context must be released by calling krb5_free_context() when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_is_config_principal.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_is_config_principal.html new file mode 100644 index 00000000..f9da536e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_is_config_principal.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_is_config_principal - Test whether a principal is a configuration principal. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_is_config_principal - Test whether a principal is a configuration principal.

+
+
+krb5_boolean krb5_is_config_principal(krb5_context context, krb5_const_principal principal)
+
+ +
+
param
+

[in] context - Library context

+

[in] principal - Principal to check

+
+
+
+
return
+
    +
  • TRUE if the principal is a configuration principal (generated part of krb5_cc_set_config()); FALSE otherwise.

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_is_referral_realm.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_is_referral_realm.html new file mode 100644 index 00000000..490230ec --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_is_referral_realm.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_is_referral_realm - Check for a match with KRB5_REFERRAL_REALM. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_is_thread_safe.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_is_thread_safe.html new file mode 100644 index 00000000..76b425d6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_is_thread_safe.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_is_thread_safe - Test whether the Kerberos library was built with multithread support. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_create_key.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_create_key.html new file mode 100644 index 00000000..bcdf3869 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_create_key.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_k_create_key - Create a krb5_key from the enctype and key data in a keyblock. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_k_create_key - Create a krb5_key from the enctype and key data in a keyblock.

+
+
+krb5_error_code krb5_k_create_key(krb5_context context, const krb5_keyblock *key_data, krb5_key *out)
+
+ +
+
param
+

[in] context - Library context

+

[in] key_data - Keyblock

+

[out] out - Opaque key

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - KRB5_BAD_ENCTYPE

  • +
+
+
+

The reference count on a key out is set to 1. Use krb5_k_free_key() to free out when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_decrypt.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_decrypt.html new file mode 100644 index 00000000..70b2c7c7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_decrypt.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_k_decrypt - Decrypt data using a key (operates on opaque key). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_k_decrypt - Decrypt data using a key (operates on opaque key).

+
+
+krb5_error_code krb5_k_decrypt(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data *cipher_state, const krb5_enc_data *input, krb5_data *output)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Encryption key

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[inout] cipher_state - Cipher state; specify NULL if not needed

+

[in] input - Encrypted data

+

[out] output - Decrypted data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function decrypts the data block input and stores the output into output . The actual decryption key will be derived from key and usage if key derivation is specified for the encryption type. If non-null, cipher_state specifies the beginning state for the decryption operation, and is updated with the state to be passed as input to the next operation.

+
+

Note

+

The caller must initialize output and allocate at least enough space for the result. The usual practice is to allocate an output buffer as long as the ciphertext, and let krb5_c_decrypt() trim output->length . For some enctypes, the resulting output->length may include padding bytes.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_decrypt_iov.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_decrypt_iov.html new file mode 100644 index 00000000..5a5bd202 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_decrypt_iov.html @@ -0,0 +1,170 @@ + + + + + + + + + krb5_k_decrypt_iov - Decrypt data in place supporting AEAD (operates on opaque key). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_k_decrypt_iov - Decrypt data in place supporting AEAD (operates on opaque key).

+
+
+krb5_error_code krb5_k_decrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data *cipher_state, krb5_crypto_iov *data, size_t num_data)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Encryption key

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[in] cipher_state - Cipher state; specify NULL if not needed

+

[inout] data - IOV array. Modified in-place.

+

[in] num_data - Size of data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function decrypts the data block data and stores the output in-place. The actual decryption key will be derived from key and usage if key derivation is specified for the encryption type. If non-null, cipher_state specifies the beginning state for the decryption operation, and is updated with the state to be passed as input to the next operation. The caller must allocate the right number of krb5_crypto_iov structures before calling into this API.

+
+

See also

+

krb5_k_encrypt_iov()

+
+
+

Note

+

On return from a krb5_c_decrypt_iov() call, the data->length in the iov structure are adjusted to reflect actual lengths of the ciphertext used. For example, if the padding length is too large, the length will be reduced. Lengths are never increased.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_encrypt.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_encrypt.html new file mode 100644 index 00000000..c4c484f7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_encrypt.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_k_encrypt - Encrypt data using a key (operates on opaque key). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_k_encrypt - Encrypt data using a key (operates on opaque key).

+
+
+krb5_error_code krb5_k_encrypt(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data *cipher_state, const krb5_data *input, krb5_enc_data *output)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Encryption key

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[inout] cipher_state - Cipher state; specify NULL if not needed

+

[in] input - Data to be encrypted

+

[out] output - Encrypted data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function encrypts the data block input and stores the output into output . The actual encryption key will be derived from key and usage if key derivation is specified for the encryption type. If non-null, cipher_state specifies the beginning state for the encryption operation, and is updated with the state to be passed as input to the next operation.

+
+

Note

+

The caller must initialize output and allocate at least enough space for the result (using krb5_c_encrypt_length() to determine the amount of space needed). output->length will be set to the actual length of the ciphertext.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_encrypt_iov.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_encrypt_iov.html new file mode 100644 index 00000000..744a2602 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_encrypt_iov.html @@ -0,0 +1,170 @@ + + + + + + + + + krb5_k_encrypt_iov - Encrypt data in place supporting AEAD (operates on opaque key). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_k_encrypt_iov - Encrypt data in place supporting AEAD (operates on opaque key).

+
+
+krb5_error_code krb5_k_encrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data *cipher_state, krb5_crypto_iov *data, size_t num_data)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Encryption key

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[in] cipher_state - Cipher state; specify NULL if not needed

+

[inout] data - IOV array. Modified in-place.

+

[in] num_data - Size of data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function encrypts the data block data and stores the output in-place. The actual encryption key will be derived from key and usage if key derivation is specified for the encryption type. If non-null, cipher_state specifies the beginning state for the encryption operation, and is updated with the state to be passed as input to the next operation. The caller must allocate the right number of krb5_crypto_iov structures before calling into this API.

+
+

See also

+

krb5_k_decrypt_iov()

+
+
+

Note

+

On return from a krb5_c_encrypt_iov() call, the data->length in the iov structure are adjusted to reflect actual lengths of the ciphertext used. For example, if the padding length is too large, the length will be reduced. Lengths are never increased.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_free_key.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_free_key.html new file mode 100644 index 00000000..e05b5d47 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_free_key.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_k_free_key - Decrement the reference count on a key and free it if it hits zero. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_key_enctype.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_key_enctype.html new file mode 100644 index 00000000..97c4c1e4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_key_enctype.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_k_key_enctype - Retrieve the enctype of a krb5_key structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_key_keyblock.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_key_keyblock.html new file mode 100644 index 00000000..a32ab7a5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_key_keyblock.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_k_key_keyblock - Retrieve a copy of the keyblock from a krb5_key structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_make_checksum.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_make_checksum.html new file mode 100644 index 00000000..3b5e70d8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_make_checksum.html @@ -0,0 +1,170 @@ + + + + + + + + + krb5_k_make_checksum - Compute a checksum (operates on opaque key). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_k_make_checksum - Compute a checksum (operates on opaque key).

+
+
+krb5_error_code krb5_k_make_checksum(krb5_context context, krb5_cksumtype cksumtype, krb5_key key, krb5_keyusage usage, const krb5_data *input, krb5_checksum *cksum)
+
+ +
+
param
+

[in] context - Library context

+

[in] cksumtype - Checksum type (0 for mandatory type)

+

[in] key - Encryption key for a keyed checksum

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[in] input - Input data

+

[out] cksum - Generated checksum

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function computes a checksum of type cksumtype over input , using key if the checksum type is a keyed checksum. If cksumtype is 0 and key is non-null, the checksum type will be the mandatory-to-implement checksum type for the key’s encryption type. The actual checksum key will be derived from key and usage if key derivation is specified for the checksum type. The newly created cksum must be released by calling krb5_free_checksum_contents() when it is no longer needed.

+
+

See also

+

krb5_c_verify_checksum()

+
+
+

Note

+

This function is similar to krb5_c_make_checksum(), but operates on opaque key .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_make_checksum_iov.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_make_checksum_iov.html new file mode 100644 index 00000000..8222f676 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_make_checksum_iov.html @@ -0,0 +1,170 @@ + + + + + + + + + krb5_k_make_checksum_iov - Fill in a checksum element in IOV array (operates on opaque key) — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_k_make_checksum_iov - Fill in a checksum element in IOV array (operates on opaque key)

+
+
+krb5_error_code krb5_k_make_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, krb5_key key, krb5_keyusage usage, krb5_crypto_iov *data, size_t num_data)
+
+ +
+
param
+

[in] context - Library context

+

[in] cksumtype - Checksum type (0 for mandatory type)

+

[in] key - Encryption key for a keyed checksum

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[inout] data - IOV array

+

[in] num_data - Size of data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Create a checksum in the #KRB5_CRYPTO_TYPE_CHECKSUM element over #KRB5_CRYPTO_TYPE_DATA and #KRB5_CRYPTO_TYPE_SIGN_ONLY chunks in data . Only the #KRB5_CRYPTO_TYPE_CHECKSUM region is modified.

+
+

See also

+

krb5_k_verify_checksum_iov()

+
+
+

Note

+

This function is similar to krb5_c_make_checksum_iov(), but operates on opaque key .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_prf.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_prf.html new file mode 100644 index 00000000..12a3387b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_prf.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_k_prf - Generate enctype-specific pseudo-random bytes (operates on opaque key). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_k_prf - Generate enctype-specific pseudo-random bytes (operates on opaque key).

+
+
+krb5_error_code krb5_k_prf(krb5_context context, krb5_key key, krb5_data *input, krb5_data *output)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Key

+

[in] input - Input data

+

[out] output - Output data

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function selects a pseudo-random function based on key and computes its value over input , placing the result into output . The caller must preinitialize output and allocate space for the result.

+
+

Note

+

This function is similar to krb5_c_prf(), but operates on opaque key .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_reference_key.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_reference_key.html new file mode 100644 index 00000000..8b271f67 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_reference_key.html @@ -0,0 +1,150 @@ + + + + + + + + + krb5_k_reference_key - Increment the reference count on a key. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_verify_checksum.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_verify_checksum.html new file mode 100644 index 00000000..7990872a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_verify_checksum.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_k_verify_checksum - Verify a checksum (operates on opaque key). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_k_verify_checksum - Verify a checksum (operates on opaque key).

+
+
+krb5_error_code krb5_k_verify_checksum(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data *data, const krb5_checksum *cksum, krb5_boolean *valid)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Encryption key for a keyed checksum

+

[in] usage - key usage

+

[in] data - Data to be used to compute a new checksum using key to compare cksum against

+

[in] cksum - Checksum to be verified

+

[out] valid - Non-zero for success, zero for failure

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function verifies that cksum is a valid checksum for data . If the checksum type of cksum is a keyed checksum, key is used to verify the checksum. If the checksum type in cksum is 0 and key is not NULL, the mandatory checksum type for key will be used. The actual checksum key will be derived from key and usage if key derivation is specified for the checksum type.

+
+

Note

+

This function is similar to krb5_c_verify_checksum(), but operates on opaque key .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_verify_checksum_iov.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_verify_checksum_iov.html new file mode 100644 index 00000000..4e95e0cd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_k_verify_checksum_iov.html @@ -0,0 +1,171 @@ + + + + + + + + + krb5_k_verify_checksum_iov - Validate a checksum element in IOV array (operates on opaque key). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_k_verify_checksum_iov - Validate a checksum element in IOV array (operates on opaque key).

+
+
+krb5_error_code krb5_k_verify_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, krb5_key key, krb5_keyusage usage, const krb5_crypto_iov *data, size_t num_data, krb5_boolean *valid)
+
+ +
+
param
+

[in] context - Library context

+

[in] cksumtype - Checksum type (0 for mandatory type)

+

[in] key - Encryption key for a keyed checksum

+

[in] usage - Key usage (see KRB5_KEYUSAGE macros)

+

[in] data - IOV array

+

[in] num_data - Size of data

+

[out] valid - Non-zero for success, zero for failure

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Confirm that the checksum in the #KRB5_CRYPTO_TYPE_CHECKSUM element is a valid checksum of the #KRB5_CRYPTO_TYPE_DATA and #KRB5_CRYPTO_TYPE_SIGN_ONLY regions in the iov.

+
+

See also

+

krb5_k_make_checksum_iov()

+
+
+

Note

+

This function is similar to krb5_c_verify_checksum_iov(), but operates on opaque key .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kdc_sign_ticket.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kdc_sign_ticket.html new file mode 100644 index 00000000..9430e829 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kdc_sign_ticket.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_kdc_sign_ticket - Sign a PAC, possibly including a ticket signature. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kdc_sign_ticket - Sign a PAC, possibly including a ticket signature.

+
+
+krb5_error_code krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt, const krb5_pac pac, krb5_const_principal server_princ, krb5_const_principal client_princ, const krb5_keyblock *server, const krb5_keyblock *privsvr, krb5_boolean with_realm)
+
+ +
+
param
+

[in] context - Library context

+

[in] enc_tkt - The ticket for the signature

+

[in] pac - PAC handle

+

[in] server_princ - Canonical ticket server name

+

[in] client_princ - PAC_CLIENT_INFO principal (or NULL)

+

[in] server - Key for server checksum

+

[in] privsvr - Key for KDC and ticket checksum

+

[in] with_realm - If true, include the realm of principal

+
+
+
+
retval
+
    +
  • 0 on success, otherwise - Kerberos error codes

  • +
+
+
+

Sign pac using the keys server and privsvr . Include a ticket signature over enc_tkt if server_princ is not a TGS or kadmin/changepw principal name. Add the signed PAC’s encoding to the authorization data of enc_tkt in the first slot, wrapped in an AD-IF-RELEVANT container. If client_princ is non-null, add a PAC_CLIENT_INFO buffer, including the realm if with_realm is true.

+
+

Note

+

New in 1.20

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kdc_verify_ticket.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kdc_verify_ticket.html new file mode 100644 index 00000000..1e2d6ea2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kdc_verify_ticket.html @@ -0,0 +1,171 @@ + + + + + + + + + krb5_kdc_verify_ticket - Verify a PAC, possibly including ticket signature. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kdc_verify_ticket - Verify a PAC, possibly including ticket signature.

+
+
+krb5_error_code krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, krb5_const_principal server_princ, const krb5_keyblock *server, const krb5_keyblock *privsvr, krb5_pac *pac_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] enc_tkt - Ticket enc-part, possibly containing a PAC

+

[in] server_princ - Canonicalized name of ticket server

+

[in] server - Key to validate server checksum (or NULL)

+

[in] privsvr - Key to validate KDC checksum (or NULL)

+

[out] pac_out - Verified PAC (NULL if no PAC included)

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

If a PAC is present in enc_tkt , verify its signatures. If privsvr is not NULL and server_princ is not a krbtgt or kadmin/changepw service, require a ticket signature over enc_tkt in addition to the KDC signature. Place the verified PAC in pac_out . If an invalid PAC signature is found, return an error matching the Windows KDC protocol code for that condition as closely as possible.

+

If no PAC is present in enc_tkt , set pac_out to NULL and return successfully.

+
+

Note

+

This function does not validate the PAC_CLIENT_INFO buffer. If a specific value is expected, the caller can make a separate call to krb5_pac_verify_ext() with a principal but no keys.

+
+
+

Note

+

New in 1.20

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_add_entry.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_add_entry.html new file mode 100644 index 00000000..8bc7aa68 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_add_entry.html @@ -0,0 +1,165 @@ + + + + + + + + + krb5_kt_add_entry - Add a new entry to a key table. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_add_entry - Add a new entry to a key table.

+
+
+krb5_error_code krb5_kt_add_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry)
+
+ +
+
param
+

[in] context - Library context

+

[in] id - Key table handle

+

[in] entry - Entry to be added

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • ENOMEM Insufficient memory

  • +
  • KRB5_KT_NOWRITE Key table is not writeable

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_client_default.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_client_default.html new file mode 100644 index 00000000..d26d5e99 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_client_default.html @@ -0,0 +1,167 @@ + + + + + + + + + krb5_kt_client_default - Resolve the default client key table. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_client_default - Resolve the default client key table.

+
+
+krb5_error_code krb5_kt_client_default(krb5_context context, krb5_keytab *keytab_out)
+
+ +
+
param
+

[in] context - Library context

+

[out] keytab_out - Key table handle

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Fill keytab_out with a handle to the default client key table.

+
+

Note

+

New in 1.11

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_close.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_close.html new file mode 100644 index 00000000..0e9e2cd0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_close.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_kt_close - Close a key table handle. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_default.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_default.html new file mode 100644 index 00000000..0f94a7f8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_default.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_kt_default - Resolve the default key table. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_default - Resolve the default key table.

+
+
+krb5_error_code krb5_kt_default(krb5_context context, krb5_keytab *id)
+
+ +
+
param
+

[in] context - Library context

+

[out] id - Key table handle

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Set id to a handle to the default key table. The key table is not opened.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_default_name.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_default_name.html new file mode 100644 index 00000000..8384b119 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_default_name.html @@ -0,0 +1,165 @@ + + + + + + + + + krb5_kt_default_name - Get the default key table name. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_default_name - Get the default key table name.

+
+
+krb5_error_code krb5_kt_default_name(krb5_context context, char *name, int name_size)
+
+ +
+
param
+

[in] context - Library context

+

[out] name - Default key table name

+

[in] name_size - Space available in name

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • KRB5_CONFIG_NOTENUFSPACE Buffer is too short

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Fill name with the name of the default key table for context .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_dup.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_dup.html new file mode 100644 index 00000000..cf8806f9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_dup.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_kt_dup - Duplicate keytab handle. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_dup - Duplicate keytab handle.

+
+
+krb5_error_code krb5_kt_dup(krb5_context context, krb5_keytab in, krb5_keytab *out)
+
+ +
+
param
+

[in] context - Library context

+

[in] in - Key table handle to be duplicated

+

[out] out - Key table handle

+
+
+

Create a new handle referring to the same key table as in . The new handle and in can be closed independently.

+
+

Note

+

New in 1.12

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_end_seq_get.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_end_seq_get.html new file mode 100644 index 00000000..95019bb2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_end_seq_get.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_kt_end_seq_get - Release a keytab cursor. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_end_seq_get - Release a keytab cursor.

+
+
+krb5_error_code krb5_kt_end_seq_get(krb5_context context, krb5_keytab keytab, krb5_kt_cursor *cursor)
+
+ +
+
param
+

[in] context - Library context

+

[in] keytab - Key table handle

+

[out] cursor - Cursor

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function should be called to release the cursor created by krb5_kt_start_seq_get().

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_free_entry.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_free_entry.html new file mode 100644 index 00000000..cc4af5dc --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_free_entry.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_kt_free_entry — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_get_entry.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_get_entry.html new file mode 100644 index 00000000..7f6ed3d0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_get_entry.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_kt_get_entry - Get an entry from a key table. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_get_entry - Get an entry from a key table.

+
+
+krb5_error_code krb5_kt_get_entry(krb5_context context, krb5_keytab keytab, krb5_const_principal principal, krb5_kvno vno, krb5_enctype enctype, krb5_keytab_entry *entry)
+
+ +
+
param
+

[in] context - Library context

+

[in] keytab - Key table handle

+

[in] principal - Principal name

+

[in] vno - Key version number (0 for highest available)

+

[in] enctype - Encryption type (0 zero for any enctype)

+

[out] entry - Returned entry from key table

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • Kerberos error codes on failure

  • +
+
+
+

Retrieve an entry from a key table which matches the keytab , principal , vno , and enctype . If vno is zero, retrieve the highest-numbered kvno matching the other fields. If enctype is 0, match any enctype.

+

Use krb5_free_keytab_entry_contents() to free entry when it is no longer needed.

+
+

Note

+

If vno is zero, the function retrieves the highest-numbered-kvno entry that matches the specified principal.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_get_name.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_get_name.html new file mode 100644 index 00000000..58d6f2c2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_get_name.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_kt_get_name - Get a key table name. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_get_name - Get a key table name.

+
+
+krb5_error_code krb5_kt_get_name(krb5_context context, krb5_keytab keytab, char *name, unsigned int namelen)
+
+ +
+
param
+

[in] context - Library context

+

[in] keytab - Key table handle

+

[out] name - Key table name

+

[in] namelen - Maximum length to fill in name

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • KRB5_KT_NAME_TOOLONG Key table name does not fit in namelen bytes

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Fill name with the name of keytab including the type and delimiter.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_get_type.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_get_type.html new file mode 100644 index 00000000..f1ab854e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_get_type.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_kt_get_type - Return the type of a key table. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_get_type - Return the type of a key table.

+
+
+const char *krb5_kt_get_type(krb5_context context, krb5_keytab keytab)
+
+ +
+
param
+

[in] context - Library context

+

[in] keytab - Key table handle

+
+
+
+
return
+
    +
  • The type of a key table as an alias that must not be modified or freed by the caller.

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_have_content.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_have_content.html new file mode 100644 index 00000000..a61872bf --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_have_content.html @@ -0,0 +1,162 @@ + + + + + + + + + krb5_kt_have_content - Check if a keytab exists and contains entries. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_have_content - Check if a keytab exists and contains entries.

+
+
+krb5_error_code krb5_kt_have_content(krb5_context context, krb5_keytab keytab)
+
+ +
+
param
+

[in] context - Library context

+

[in] keytab - Key table handle

+
+
+
+
retval
+
    +
  • 0 Keytab exists and contains entries

  • +
  • KRB5_KT_NOTFOUND Keytab does not contain entries

  • +
+
+
+
+

Note

+

New in 1.11

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_next_entry.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_next_entry.html new file mode 100644 index 00000000..de69878a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_next_entry.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_kt_next_entry - Retrieve the next entry from the key table. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_next_entry - Retrieve the next entry from the key table.

+
+
+krb5_error_code krb5_kt_next_entry(krb5_context context, krb5_keytab keytab, krb5_keytab_entry *entry, krb5_kt_cursor *cursor)
+
+ +
+
param
+

[in] context - Library context

+

[in] keytab - Key table handle

+

[out] entry - Returned key table entry

+

[in] cursor - Key table cursor

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • KRB5_KT_END - if the last entry was reached

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Return the next sequential entry in keytab and advance cursor . Callers must release the returned entry with krb5_kt_free_entry().

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_read_service_key.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_read_service_key.html new file mode 100644 index 00000000..2fd57a75 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_read_service_key.html @@ -0,0 +1,169 @@ + + + + + + + + + krb5_kt_read_service_key - Retrieve a service key from a key table. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_read_service_key - Retrieve a service key from a key table.

+
+
+krb5_error_code krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg, krb5_principal principal, krb5_kvno vno, krb5_enctype enctype, krb5_keyblock **key)
+
+ +
+
param
+

[in] context - Library context

+

[in] keyprocarg - Name of a key table (NULL to use default name)

+

[in] principal - Service principal

+

[in] vno - Key version number (0 for highest available)

+

[in] enctype - Encryption type (0 for any type)

+

[out] key - Service key from key table

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error code if not found or keyprocarg is invalid.

  • +
+
+
+

Open and search the specified key table for the entry identified by principal , enctype , and vno . If no key is found, return an error code.

+

The default key table is used, unless keyprocarg is non-null. keyprocarg designates a specific key table.

+

Use krb5_free_keyblock() to free key when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_remove_entry.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_remove_entry.html new file mode 100644 index 00000000..2f0ab7fe --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_remove_entry.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_kt_remove_entry - Remove an entry from a key table. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_remove_entry - Remove an entry from a key table.

+
+
+krb5_error_code krb5_kt_remove_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry)
+
+ +
+
param
+

[in] context - Library context

+

[in] id - Key table handle

+

[in] entry - Entry to remove from key table

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • KRB5_KT_NOWRITE Key table is not writable

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_resolve.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_resolve.html new file mode 100644 index 00000000..a801e5c5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_resolve.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_kt_resolve - Get a handle for a key table. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_resolve - Get a handle for a key table.

+
+
+krb5_error_code krb5_kt_resolve(krb5_context context, const char *name, krb5_keytab *ktid)
+
+ +
+
param
+

[in] context - Library context

+

[in] name - Name of the key table

+

[out] ktid - Key table handle

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Resolve the key table name name and set ktid to a handle identifying the key table. Use krb5_kt_close() to free ktid when it is no longer needed.

+
+

name must be of the form type:residual , where type must be a type known to the library and residual portion should be specific to the particular keytab type. If no type is given, the default is FILE .

+
+

If name is of type FILE , the keytab file is not opened by this call.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_start_seq_get.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_start_seq_get.html new file mode 100644 index 00000000..821c872a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kt_start_seq_get.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_kt_start_seq_get - Start a sequential retrieval of key table entries. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kt_start_seq_get - Start a sequential retrieval of key table entries.

+
+
+krb5_error_code krb5_kt_start_seq_get(krb5_context context, krb5_keytab keytab, krb5_kt_cursor *cursor)
+
+ +
+
param
+

[in] context - Library context

+

[in] keytab - Key table handle

+

[out] cursor - Cursor

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Prepare to read sequentially every key in the specified key table. Use krb5_kt_end_seq_get() to release the cursor when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kuserok.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kuserok.html new file mode 100644 index 00000000..9a87f53c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_kuserok.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_kuserok - Determine if a principal is authorized to log in as a local user. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kuserok - Determine if a principal is authorized to log in as a local user.

+
+
+krb5_boolean krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser)
+
+ +
+
param
+

[in] context - Library context

+

[in] principal - Principal name

+

[in] luser - Local username

+
+
+
+
retval
+
    +
  • TRUE Principal is authorized to log in as user; FALSE otherwise.

  • +
+
+
+

Determine whether principal is authorized to log in as a local user luser .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_make_authdata_kdc_issued.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_make_authdata_kdc_issued.html new file mode 100644 index 00000000..07f29e54 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_make_authdata_kdc_issued.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_make_authdata_kdc_issued - Encode and sign AD-KDCIssued authorization data. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_make_authdata_kdc_issued - Encode and sign AD-KDCIssued authorization data.

+
+
+krb5_error_code krb5_make_authdata_kdc_issued(krb5_context context, const krb5_keyblock *key, krb5_const_principal issuer, krb5_authdata *const *authdata, krb5_authdata ***ad_kdcissued)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Session key

+

[in] issuer - The name of the issuing principal

+

[in] authdata - List of authorization data to be signed

+

[out] ad_kdcissued - List containing AD-KDCIssued authdata

+
+
+

This function wraps a list of authorization data entries authdata in an AD-KDCIssued container (see RFC 4120 section 5.2.6.2) signed with key . The result is returned in ad_kdcissued as a single-element list.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_marshal_credentials.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_marshal_credentials.html new file mode 100644 index 00000000..e529478d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_marshal_credentials.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_marshal_credentials - Serialize a krb5_creds object. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_marshal_credentials - Serialize a krb5_creds object.

+
+
+krb5_error_code krb5_marshal_credentials(krb5_context context, krb5_creds *in_creds, krb5_data **data_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] in_creds - The credentials object to serialize

+

[out] data_out - The serialized credentials

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Serialize creds in the format used by the FILE ccache format (vesion 4) and KCM ccache protocol.

+

Use krb5_free_data() to free data_out when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_merge_authdata.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_merge_authdata.html new file mode 100644 index 00000000..dfc79e02 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_merge_authdata.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_merge_authdata - Merge two authorization data lists into a new list. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_merge_authdata - Merge two authorization data lists into a new list.

+
+
+krb5_error_code krb5_merge_authdata(krb5_context context, krb5_authdata *const *inauthdat1, krb5_authdata *const *inauthdat2, krb5_authdata ***outauthdat)
+
+ +
+
param
+

[in] context - Library context

+

[in] inauthdat1 - First list of krb5_authdata structures

+

[in] inauthdat2 - Second list of krb5_authdata structures

+

[out] outauthdat - Merged list of krb5_authdata structures

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Merge two authdata arrays, such as the array from a ticket and authenticator. Use krb5_free_authdata() to free outauthdat when it is no longer needed.

+
+

Note

+

The last array entry in inauthdat1 and inauthdat2 must be a NULL pointer.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_1cred.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_1cred.html new file mode 100644 index 00000000..513f13ea --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_1cred.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_mk_1cred - Format a KRB-CRED message for a single set of credentials. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_mk_1cred - Format a KRB-CRED message for a single set of credentials.

+
+
+krb5_error_code krb5_mk_1cred(krb5_context context, krb5_auth_context auth_context, krb5_creds *creds, krb5_data **der_out, krb5_replay_data *rdata_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] creds - Pointer to credentials

+

[out] der_out - Encoded credentials

+

[out] rdata_out - Replay cache data (NULL if not needed)

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • ENOMEM Insufficient memory

  • +
  • KRB5_RC_REQUIRED Message replay detection requires rcache parameter

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This is a convenience function that calls krb5_mk_ncred() with a single set of credentials.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_error.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_error.html new file mode 100644 index 00000000..19fdbd98 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_error.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_mk_error - Format and encode a KRB_ERROR message. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_mk_error - Format and encode a KRB_ERROR message.

+
+
+krb5_error_code krb5_mk_error(krb5_context context, const krb5_error *dec_err, krb5_data *enc_err)
+
+ +
+
param
+

[in] context - Library context

+

[in] dec_err - Error structure to be encoded

+

[out] enc_err - Encoded error structure

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates a KRB_ERROR message in enc_err . Use krb5_free_data_contents() to free enc_err when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_ncred.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_ncred.html new file mode 100644 index 00000000..85684bb8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_ncred.html @@ -0,0 +1,177 @@ + + + + + + + + + krb5_mk_ncred - Format a KRB-CRED message for an array of credentials. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_mk_ncred - Format a KRB-CRED message for an array of credentials.

+
+
+krb5_error_code krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, krb5_creds **creds, krb5_data **der_out, krb5_replay_data *rdata_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] creds - Null-terminated array of credentials

+

[out] der_out - Encoded credentials

+

[out] rdata_out - Replay cache information (NULL if not needed)

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • ENOMEM Insufficient memory

  • +
  • KRB5_RC_REQUIRED Message replay detection requires rcache parameter

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function takes an array of credentials creds and formats a KRB-CRED message der_out to pass to krb5_rd_cred().

+

The local and remote addresses in auth_context are optional; if either is specified, they are used to form the sender and receiver addresses in the KRB-CRED message.

+

If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in auth_context , an entry for the message is entered in an in-memory replay cache to detect if the message is reflected by an attacker. If #KRB5_AUTH_CONTEXT_DO_TIME is not set, no replay cache is used. If #KRB5_AUTH_CONTEXT_RET_TIME is set in auth_context , the timestamp used for the KRB-CRED message is stored in rdata_out .

+

If either #KRB5_AUTH_CONTEXT_DO_SEQUENCE or #KRB5_AUTH_CONTEXT_RET_SEQUENCE is set, the auth_context local sequence number is included in the KRB-CRED message and then incremented. If #KRB5_AUTH_CONTEXT_RET_SEQUENCE is set, the sequence number used is stored in rdata_out .

+

Use krb5_free_data_contents() to free der_out when it is no longer needed.

+

The message will be encrypted using the send subkey of auth_context if it is present, or the session key otherwise. If neither key is present, the credentials will not be encrypted, and the message should only be sent over a secure channel. No replay cache entry is used in this case.

+
+

Note

+

The rdata_out argument is required if the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in auth_context .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_priv.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_priv.html new file mode 100644 index 00000000..7f4fdddc --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_priv.html @@ -0,0 +1,169 @@ + + + + + + + + + krb5_mk_priv - Format a KRB-PRIV message. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_mk_priv - Format a KRB-PRIV message.

+
+
+krb5_error_code krb5_mk_priv(krb5_context context, krb5_auth_context auth_context, const krb5_data *userdata, krb5_data *der_out, krb5_replay_data *rdata_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] userdata - User data for KRB-PRIV message

+

[out] der_out - Formatted KRB-PRIV message

+

[out] rdata_out - Replay data (NULL if not needed)

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function is similar to krb5_mk_safe(), but the message is encrypted and integrity-protected, not just integrity-protected.

+

The local address in auth_context must be set, and is used to form the sender address used in the KRB-PRIV message. The remote address is optional; if specified, it will be used to form the receiver address used in the message.

+

If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in auth_context , a timestamp is included in the KRB-PRIV message, and an entry for the message is entered in an in-memory replay cache to detect if the message is reflected by an attacker. If #KRB5_AUTH_CONTEXT_DO_TIME is not set, no replay cache is used. If #KRB5_AUTH_CONTEXT_RET_TIME is set in auth_context , a timestamp is included in the KRB-PRIV message and is stored in rdata_out .

+

If either #KRB5_AUTH_CONTEXT_DO_SEQUENCE or #KRB5_AUTH_CONTEXT_RET_SEQUENCE is set, the auth_context local sequence number is included in the KRB-PRIV message and then incremented. If #KRB5_AUTH_CONTEXT_RET_SEQUENCE is set, the sequence number used is stored in rdata_out .

+

Use krb5_free_data_contents() to free der_out when it is no longer needed.

+
+

Note

+

The rdata_out argument is required if the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in auth_context .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_rep.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_rep.html new file mode 100644 index 00000000..fabc30f8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_rep.html @@ -0,0 +1,161 @@ + + + + + + + + + krb5_mk_rep - Format and encrypt a KRB_AP_REP message. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_mk_rep - Format and encrypt a KRB_AP_REP message.

+
+
+krb5_error_code krb5_mk_rep(krb5_context context, krb5_auth_context auth_context, krb5_data *outbuf)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[out] outbuf - AP-REP message

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function fills in outbuf with an AP-REP message using information from auth_context .

+

If the flags in auth_context indicate that a sequence number should be used (either #KRB5_AUTH_CONTEXT_DO_SEQUENCE or #KRB5_AUTH_CONTEXT_RET_SEQUENCE) and the local sequence number in auth_context is 0, a new number will be generated with krb5_generate_seq_number().

+

Use krb5_free_data_contents() to free outbuf when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_rep_dce.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_rep_dce.html new file mode 100644 index 00000000..703716fe --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_rep_dce.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_mk_rep_dce - Format and encrypt a KRB_AP_REP message for DCE RPC. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_mk_rep_dce - Format and encrypt a KRB_AP_REP message for DCE RPC.

+
+
+krb5_error_code krb5_mk_rep_dce(krb5_context context, krb5_auth_context auth_context, krb5_data *outbuf)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[out] outbuf - AP-REP message

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Use krb5_free_data_contents() to free outbuf when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_req.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_req.html new file mode 100644 index 00000000..dd3ecfd3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_req.html @@ -0,0 +1,165 @@ + + + + + + + + + krb5_mk_req - Create a KRB_AP_REQ message. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_mk_req - Create a KRB_AP_REQ message.

+
+
+krb5_error_code krb5_mk_req(krb5_context context, krb5_auth_context *auth_context, krb5_flags ap_req_options, const char *service, const char *hostname, krb5_data *in_data, krb5_ccache ccache, krb5_data *outbuf)
+
+ +
+
param
+

[in] context - Library context

+

[inout] auth_context - Pre-existing or newly created auth context

+

[in] ap_req_options - Options (see AP_OPTS macros)

+

[in] service - Service name, or NULL to use “host”

+

[in] hostname - Host name, or NULL to use local hostname

+

[in] in_data - Application data to be checksummed in the authenticator, or NULL

+

[in] ccache - Credential cache used to obtain credentials for the desired service.

+

[out] outbuf - AP-REQ message

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function is similar to krb5_mk_req_extended() except that it uses a given hostname , service , and ccache to construct a service principal name and obtain credentials.

+

Use krb5_free_data_contents() to free outbuf when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_req_extended.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_req_extended.html new file mode 100644 index 00000000..8378d044 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_req_extended.html @@ -0,0 +1,177 @@ + + + + + + + + + krb5_mk_req_extended - Create a KRB_AP_REQ message using supplied credentials. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_mk_req_extended - Create a KRB_AP_REQ message using supplied credentials.

+
+
+krb5_error_code krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context, krb5_flags ap_req_options, krb5_data *in_data, krb5_creds *in_creds, krb5_data *outbuf)
+
+ +
+
param
+

[in] context - Library context

+

[inout] auth_context - Pre-existing or newly created auth context

+

[in] ap_req_options - Options (see AP_OPTS macros)

+

[in] in_data - Application data to be checksummed in the authenticator, or NULL

+

[in] in_creds - Credentials for the service with valid ticket and key

+

[out] outbuf - AP-REQ message

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Valid ap_req_options are:

+
+
+
    +
  • #AP_OPTS_USE_SESSION_KEY - Use the session key when creating the request used for user to user authentication.

  • +
  • #AP_OPTS_MUTUAL_REQUIRED - Request a mutual authentication packet from the receiver.

  • +
  • #AP_OPTS_USE_SUBKEY - Generate a subsession key from the current session key obtained from the credentials.

  • +
+
+

This function creates a KRB_AP_REQ message using supplied credentials in_creds . auth_context may point to an existing auth context or to NULL, in which case a new one will be created. If in_data is non-null, a checksum of it will be included in the authenticator contained in the KRB_AP_REQ message. Use krb5_free_data_contents() to free outbuf when it is no longer needed.

+
+

On successful return, the authenticator is stored in auth_context with the client and checksum fields nulled out. (This is to prevent pointer-sharing problems; the caller should not need these fields anyway, since the caller supplied them.)

+
+

See also

+

krb5_mk_req()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_safe.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_safe.html new file mode 100644 index 00000000..c1125e04 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_mk_safe.html @@ -0,0 +1,170 @@ + + + + + + + + + krb5_mk_safe - Format a KRB-SAFE message. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_mk_safe - Format a KRB-SAFE message.

+
+
+krb5_error_code krb5_mk_safe(krb5_context context, krb5_auth_context auth_context, const krb5_data *userdata, krb5_data *der_out, krb5_replay_data *rdata_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] userdata - User data in the message

+

[out] der_out - Formatted KRB-SAFE buffer

+

[out] rdata_out - Replay data. Specify NULL if not needed

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function creates an integrity protected KRB-SAFE message using data supplied by the application.

+

Fields in auth_context specify the checksum type, the keyblock that can be used to seed the checksum, full addresses (host and port) for the sender and receiver, and KRB5_AUTH_CONTEXT flags.

+

The local address in auth_context must be set, and is used to form the sender address used in the KRB-SAFE message. The remote address is optional; if specified, it will be used to form the receiver address used in the message.

+

If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in auth_context , a timestamp is included in the KRB-SAFE message, and an entry for the message is entered in an in-memory replay cache to detect if the message is reflected by an attacker. If #KRB5_AUTH_CONTEXT_DO_TIME is not set, no replay cache is used. If #KRB5_AUTH_CONTEXT_RET_TIME is set in auth_context , a timestamp is included in the KRB-SAFE message and is stored in rdata_out .

+

If either #KRB5_AUTH_CONTEXT_DO_SEQUENCE or #KRB5_AUTH_CONTEXT_RET_SEQUENCE is set, the auth_context local sequence number is included in the KRB-SAFE message and then incremented. If #KRB5_AUTH_CONTEXT_RET_SEQUENCE is set, the sequence number used is stored in rdata_out .

+

Use krb5_free_data_contents() to free der_out when it is no longer needed.

+
+

Note

+

The rdata_out argument is required if the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in auth_context .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_os_localaddr.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_os_localaddr.html new file mode 100644 index 00000000..732658cb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_os_localaddr.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_os_localaddr - Return all interface addresses for this host. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_os_localaddr - Return all interface addresses for this host.

+
+
+krb5_error_code krb5_os_localaddr(krb5_context context, krb5_address ***addr)
+
+ +
+
param
+

[in] context - Library context

+

[out] addr - Array of krb5_address pointers, ending with NULL

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Use krb5_free_addresses() to free addr when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_add_buffer.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_add_buffer.html new file mode 100644 index 00000000..cfeb870d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_add_buffer.html @@ -0,0 +1,172 @@ + + + + + + + + + krb5_pac_add_buffer - Add a buffer to a PAC handle. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_pac_add_buffer - Add a buffer to a PAC handle.

+
+
+krb5_error_code krb5_pac_add_buffer(krb5_context context, krb5_pac pac, krb5_ui_4 type, const krb5_data *data)
+
+ +
+
param
+

[in] context - Library context

+

[in] pac - PAC handle

+

[in] type - Buffer type

+

[in] data - contents

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function adds a buffer of type type and contents data to pac if there isn’t already a buffer of this type present.

+

The valid values of type is one of the following:

+
+
    +
  • #KRB5_PAC_LOGON_INFO - Logon information

  • +
  • #KRB5_PAC_CREDENTIALS_INFO - Credentials information

  • +
  • #KRB5_PAC_SERVER_CHECKSUM - Server checksum

  • +
  • #KRB5_PAC_PRIVSVR_CHECKSUM - KDC checksum

  • +
  • #KRB5_PAC_CLIENT_INFO - Client name and ticket information

  • +
  • #KRB5_PAC_DELEGATION_INFO - Constrained delegation information

  • +
  • #KRB5_PAC_UPN_DNS_INFO - User principal name and DNS information

  • +
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_free.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_free.html new file mode 100644 index 00000000..282b4fff --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_free.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_pac_free - Free a PAC handle. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_get_buffer.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_get_buffer.html new file mode 100644 index 00000000..1b18f026 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_get_buffer.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_pac_get_buffer - Retrieve a buffer value from a PAC. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_pac_get_buffer - Retrieve a buffer value from a PAC.

+
+
+krb5_error_code krb5_pac_get_buffer(krb5_context context, krb5_pac pac, krb5_ui_4 type, krb5_data *data)
+
+ +
+
param
+

[in] context - Library context

+

[in] pac - PAC handle

+

[in] type - Type of buffer to retrieve

+

[out] data - Buffer value

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Use krb5_free_data_contents() to free data when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_get_client_info.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_get_client_info.html new file mode 100644 index 00000000..73ea56b1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_get_client_info.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_pac_get_client_info - Read client information from a PAC. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_pac_get_client_info - Read client information from a PAC.

+
+
+krb5_error_code krb5_pac_get_client_info(krb5_context context, const krb5_pac pac, krb5_timestamp *authtime_out, char **princname_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] pac - PAC handle

+

[out] authtime_out - Authentication timestamp (NULL if not needed)

+

[out] princname_out - Client account name

+
+
+
+
retval
+
    +
  • 0 on success, ENOENT if no PAC_CLIENT_INFO buffer is present in pac , ERANGE if the buffer contains invalid lengths.

  • +
+
+
+

Read the PAC_CLIENT_INFO buffer in pac . Place the client account name as a string in princname_out . If authtime_out is not NULL, place the initial authentication timestamp in authtime_out .

+
+

Note

+

New in 1.18

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_get_types.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_get_types.html new file mode 100644 index 00000000..49061b7e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_get_types.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_pac_get_types - Return an array of buffer types in a PAC handle. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_pac_get_types - Return an array of buffer types in a PAC handle.

+
+
+krb5_error_code krb5_pac_get_types(krb5_context context, krb5_pac pac, size_t *len, krb5_ui_4 **types)
+
+ +
+
param
+

[in] context - Library context

+

[in] pac - PAC handle

+

[out] len - Number of entries in types

+

[out] types - Array of buffer types

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_init.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_init.html new file mode 100644 index 00000000..d54e2f05 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_init.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_pac_init - Create an empty Privilege Attribute Certificate (PAC) handle. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_pac_init - Create an empty Privilege Attribute Certificate (PAC) handle.

+
+
+krb5_error_code krb5_pac_init(krb5_context context, krb5_pac *pac)
+
+ +
+
param
+

[in] context - Library context

+

[out] pac - New PAC handle

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Use krb5_pac_free() to free pac when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_parse.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_parse.html new file mode 100644 index 00000000..99fd68ad --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_parse.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_pac_parse - Unparse an encoded PAC into a new handle. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_pac_parse - Unparse an encoded PAC into a new handle.

+
+
+krb5_error_code krb5_pac_parse(krb5_context context, const void *ptr, size_t len, krb5_pac *pac)
+
+ +
+
param
+

[in] context - Library context

+

[in] ptr - PAC buffer

+

[in] len - Length of ptr

+

[out] pac - PAC handle

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Use krb5_pac_free() to free pac when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_sign.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_sign.html new file mode 100644 index 00000000..3339fd13 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_sign.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_pac_sign — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_sign_ext.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_sign_ext.html new file mode 100644 index 00000000..c09f4cfb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_sign_ext.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_pac_sign_ext — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_verify.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_verify.html new file mode 100644 index 00000000..97c18d61 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_verify.html @@ -0,0 +1,167 @@ + + + + + + + + + krb5_pac_verify - Verify a PAC. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_pac_verify - Verify a PAC.

+
+
+krb5_error_code krb5_pac_verify(krb5_context context, const krb5_pac pac, krb5_timestamp authtime, krb5_const_principal principal, const krb5_keyblock *server, const krb5_keyblock *privsvr)
+
+ +
+
param
+

[in] context - Library context

+

[in] pac - PAC handle

+

[in] authtime - Expected timestamp

+

[in] principal - Expected principal name (or NULL)

+

[in] server - Key to validate server checksum (or NULL)

+

[in] privsvr - Key to validate KDC checksum (or NULL)

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function validates pac against the supplied server , privsvr , principal and authtime . If principal is NULL, the principal and authtime are not verified. If server or privsvr is NULL, the corresponding checksum is not verified.

+

If successful, pac is marked as verified.

+
+

Note

+

A checksum mismatch can occur if the PAC was copied from a cross-realm TGT by an ignorant KDC; also macOS Server Open Directory (as of 10.6) generates PACs with no server checksum at all. One should consider not failing the whole authentication because of this reason, but, instead, treating the ticket as if it did not contain a PAC or marking the PAC information as non-verified.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_verify_ext.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_verify_ext.html new file mode 100644 index 00000000..13fa7f5b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_pac_verify_ext.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_pac_verify_ext - Verify a PAC, possibly from a specified realm. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_pac_verify_ext - Verify a PAC, possibly from a specified realm.

+
+
+krb5_error_code krb5_pac_verify_ext(krb5_context context, const krb5_pac pac, krb5_timestamp authtime, krb5_const_principal principal, const krb5_keyblock *server, const krb5_keyblock *privsvr, krb5_boolean with_realm)
+
+ +
+
param
+

[in] context - Library context

+

[in] pac - PAC handle

+

[in] authtime - Expected timestamp

+

[in] principal - Expected principal name (or NULL)

+

[in] server - Key to validate server checksum (or NULL)

+

[in] privsvr - Key to validate KDC checksum (or NULL)

+

[in] with_realm - If true, expect the realm of principal

+
+
+

This function is similar to krb5_pac_verify(), but adds a parameter with_realm . If with_realm is true, the PAC_CLIENT_INFO field is expected to include the realm of principal as well as the name. This flag is necessary to verify PACs in cross-realm S4U2Self referral TGTs.

+
+

Note

+

New in 1.17

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_parse_name.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_parse_name.html new file mode 100644 index 00000000..09e3ab99 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_parse_name.html @@ -0,0 +1,172 @@ + + + + + + + + + krb5_parse_name - Convert a string principal name to a krb5_principal structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_parse_name - Convert a string principal name to a krb5_principal structure.

+
+
+krb5_error_code krb5_parse_name(krb5_context context, const char *name, krb5_principal *principal_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] name - String representation of a principal name

+

[out] principal_out - New principal

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Convert a string representation of a principal name to a krb5_principal structure.

+

A string representation of a Kerberos name consists of one or more principal name components, separated by slashes, optionally followed by the @ character and a realm name. If the realm name is not specified, the local realm is used.

+

To use the slash and @ symbols as part of a component (quoted) instead of using them as a component separator or as a realm prefix), put a backslash () character in front of the symbol. Similarly, newline, tab, backspace, and NULL characters can be included in a component by using n , t , b or 0 , respectively.

+

Beginning with release 1.20, the name type of the principal will be inferred as KRB5_NT_SRV_INST or KRB5_NT_WELLKNOWN based on the principal name. The type will be KRB5_NT_PRINCIPAL if a type cannot be inferred.

+

Use krb5_free_principal() to free principal_out when it is no longer needed.

+
+

Note

+

The realm in a Kerberos name cannot contain slash, colon, or NULL characters.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_parse_name_flags.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_parse_name_flags.html new file mode 100644 index 00000000..2cdcba32 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_parse_name_flags.html @@ -0,0 +1,178 @@ + + + + + + + + + krb5_parse_name_flags - Convert a string principal name to a krb5_principal with flags. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_parse_name_flags - Convert a string principal name to a krb5_principal with flags.

+
+
+krb5_error_code krb5_parse_name_flags(krb5_context context, const char *name, int flags, krb5_principal *principal_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] name - String representation of a principal name

+

[in] flags - Flag

+

[out] principal_out - New principal

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Similar to krb5_parse_name(), this function converts a single-string representation of a principal name to a krb5_principal structure.

+

The following flags are valid:

+
+
+
    +
  • #KRB5_PRINCIPAL_PARSE_NO_REALM - no realm must be present in name

  • +
  • #KRB5_PRINCIPAL_PARSE_REQUIRE_REALM - realm must be present in name

  • +
  • #KRB5_PRINCIPAL_PARSE_ENTERPRISE - create single-component enterprise principal

  • +
  • #KRB5_PRINCIPAL_PARSE_IGNORE_REALM - ignore realm if present in name

  • +
+
+

If KRB5_PRINCIPAL_PARSE_NO_REALM or KRB5_PRINCIPAL_PARSE_IGNORE_REALM is specified in flags , the realm of the new principal will be empty. Otherwise, the default realm for context will be used if name does not specify a realm.

+
+

Use krb5_free_principal() to free principal_out when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_prepend_error_message.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_prepend_error_message.html new file mode 100644 index 00000000..e25835a1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_prepend_error_message.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_prepend_error_message - Add a prefix to the message for an error code. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_prepend_error_message - Add a prefix to the message for an error code.

+
+
+void krb5_prepend_error_message(krb5_context ctx, krb5_error_code code, const char *fmt, ...)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] code - Error code

+

[in] fmt - Format string for error message prefix

+
+
+

Format a message and prepend it to the current message for code . The prefix will be separated from the old message with a colon and space.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal2salt.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal2salt.html new file mode 100644 index 00000000..324eb1e2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal2salt.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_principal2salt - Convert a principal name into the default salt for that principal. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_principal2salt - Convert a principal name into the default salt for that principal.

+
+
+krb5_error_code krb5_principal2salt(krb5_context context, krb5_const_principal pr, krb5_data *ret)
+
+ +
+
param
+

[in] context - Library context

+

[in] pr - Principal name

+

[out] ret - Default salt for pr to be filled in

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal_compare.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal_compare.html new file mode 100644 index 00000000..e91ef239 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal_compare.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_principal_compare - Compare two principals. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_principal_compare - Compare two principals.

+
+
+krb5_boolean krb5_principal_compare(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2)
+
+ +
+
param
+

[in] context - Library context

+

[in] princ1 - First principal

+

[in] princ2 - Second principal

+
+
+
+
retval
+
    +
  • TRUE if the principals are the same; FALSE otherwise

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal_compare_any_realm.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal_compare_any_realm.html new file mode 100644 index 00000000..23b8e214 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal_compare_any_realm.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_principal_compare_any_realm - Compare two principals ignoring realm components. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_principal_compare_any_realm - Compare two principals ignoring realm components.

+
+
+krb5_boolean krb5_principal_compare_any_realm(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2)
+
+ +
+
param
+

[in] context - Library context

+

[in] princ1 - First principal

+

[in] princ2 - Second principal

+
+
+
+
retval
+
    +
  • TRUE if the principals are the same; FALSE otherwise

  • +
+
+
+

Similar to krb5_principal_compare(), but do not compare the realm components of the principals.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal_compare_flags.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal_compare_flags.html new file mode 100644 index 00000000..b32ea27c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_principal_compare_flags.html @@ -0,0 +1,172 @@ + + + + + + + + + krb5_principal_compare_flags - Compare two principals with additional flags. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_principal_compare_flags - Compare two principals with additional flags.

+
+
+krb5_boolean krb5_principal_compare_flags(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2, int flags)
+
+ +
+
param
+

[in] context - Library context

+

[in] princ1 - First principal

+

[in] princ2 - Second principal

+

[in] flags - Flags

+
+
+
+
retval
+
    +
  • TRUE if the principal names are the same; FALSE otherwise

  • +
+
+
+

Valid flags are:

+
+
    +
  • #KRB5_PRINCIPAL_COMPARE_IGNORE_REALM - ignore realm component

  • +
  • #KRB5_PRINCIPAL_COMPARE_ENTERPRISE - UPNs as real principals

  • +
  • #KRB5_PRINCIPAL_COMPARE_CASEFOLD case-insensitive

  • +
  • #KRB5_PRINCIPAL_COMPARE_UTF8 - treat principals as UTF-8

  • +
+
+
+

See also

+

krb5_principal_compare()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_process_key.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_process_key.html new file mode 100644 index 00000000..374053af --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_process_key.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_process_key — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_prompter_posix.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_prompter_posix.html new file mode 100644 index 00000000..67b03c04 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_prompter_posix.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_prompter_posix - Prompt user for password. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_prompter_posix - Prompt user for password.

+
+
+krb5_error_code krb5_prompter_posix(krb5_context context, void *data, const char *name, const char *banner, int num_prompts, krb5_prompt prompts)
+
+ +
+
param
+

[in] context - Library context

+

data - Unused (callback argument)

+

[in] name - Name to output during prompt

+

[in] banner - Banner to output during prompt

+

[in] num_prompts - Number of prompts in prompts

+

[in] prompts - Array of prompts and replies

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function is intended to be used as a prompter callback for krb5_get_init_creds_password() or krb5_init_creds_init().

+

Writes name and banner to stdout, each followed by a newline, then writes each prompt field in the prompts array, followed by”:”, and sets the reply field of the entry to a line of input read from stdin. If the hidden flag is set for a prompt, then terminal echoing is turned off when input is read.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_random_key.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_random_key.html new file mode 100644 index 00000000..cd4338f8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_random_key.html @@ -0,0 +1,153 @@ + + + + + + + + + krb5_random_key — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_cred.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_cred.html new file mode 100644 index 00000000..4ef508fd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_cred.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_rd_cred - Read and validate a KRB-CRED message. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_rd_cred - Read and validate a KRB-CRED message.

+
+
+krb5_error_code krb5_rd_cred(krb5_context context, krb5_auth_context auth_context, krb5_data *creddata, krb5_creds ***creds_out, krb5_replay_data *rdata_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] creddata - KRB-CRED message

+

[out] creds_out - Null-terminated array of forwarded credentials

+

[out] rdata_out - Replay data (NULL if not needed)

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+

creddata will be decrypted using the receiving subkey if it is present in auth_context , or the session key if the receiving subkey is not present or fails to decrypt the message.

+
+

Use krb5_free_tgt_creds() to free creds_out when it is no longer needed.

+
+

Note

+

The rdata_out argument is required if the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in auth_context .`

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_error.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_error.html new file mode 100644 index 00000000..9eadc789 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_error.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_rd_error - Decode a KRB-ERROR message. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_rd_error - Decode a KRB-ERROR message.

+
+
+krb5_error_code krb5_rd_error(krb5_context context, const krb5_data *enc_errbuf, krb5_error **dec_error)
+
+ +
+
param
+

[in] context - Library context

+

[in] enc_errbuf - Encoded error message

+

[out] dec_error - Decoded error message

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function processes KRB-ERROR message enc_errbuf and returns an allocated structure dec_error containing the error message. Use krb5_free_error() to free dec_error when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_priv.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_priv.html new file mode 100644 index 00000000..490134e6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_priv.html @@ -0,0 +1,169 @@ + + + + + + + + + krb5_rd_priv - Process a KRB-PRIV message. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_rd_priv - Process a KRB-PRIV message.

+
+
+krb5_error_code krb5_rd_priv(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_data *userdata_out, krb5_replay_data *rdata_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication structure

+

[in] inbuf - KRB-PRIV message to be parsed

+

[out] userdata_out - Data parsed from KRB-PRIV message

+

[out] rdata_out - Replay data. Specify NULL if not needed

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function parses a KRB-PRIV message, verifies its integrity, and stores its unencrypted data into userdata_out .

+

If auth_context has a remote address set, the address will be used to verify the sender address in the KRB-PRIV message. If auth_context has a local address set, it will be used to verify the receiver address in the KRB-PRIV message if the message contains one.

+

If the #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag is set in auth_context , the sequence number of the KRB-PRIV message is checked against the remote sequence number field of auth_context . Otherwise, the sequence number is not used.

+

If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in auth_context , then the timestamp in the message is verified to be within the permitted clock skew of the current time, and the message is checked against an in-memory replay cache to detect reflections or replays.

+

Use krb5_free_data_contents() to free userdata_out when it is no longer needed.

+
+

Note

+

The rdata_out argument is required if the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in auth_context .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_rep.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_rep.html new file mode 100644 index 00000000..e9f96fbf --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_rep.html @@ -0,0 +1,161 @@ + + + + + + + + + krb5_rd_rep - Parse and decrypt a KRB_AP_REP message. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_rd_rep - Parse and decrypt a KRB_AP_REP message.

+
+
+krb5_error_code krb5_rd_rep(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_ap_rep_enc_part **repl)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] inbuf - AP-REP message

+

[out] repl - Decrypted reply message

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function parses, decrypts and verifies a message from inbuf and fills in repl with a pointer to allocated memory containing the fields from the encrypted response.

+

Use krb5_free_ap_rep_enc_part() to free repl when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_rep_dce.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_rep_dce.html new file mode 100644 index 00000000..6c1b92be --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_rep_dce.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_rd_rep_dce - Parse and decrypt a KRB_AP_REP message for DCE RPC. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_rd_rep_dce - Parse and decrypt a KRB_AP_REP message for DCE RPC.

+
+
+krb5_error_code krb5_rd_rep_dce(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_ui_4 *nonce)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] inbuf - AP-REP message

+

[out] nonce - Sequence number from the decrypted reply

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function parses, decrypts and verifies a message from inbuf and fills in nonce with a decrypted reply sequence number.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_req.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_req.html new file mode 100644 index 00000000..9f25dad0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_req.html @@ -0,0 +1,178 @@ + + + + + + + + + krb5_rd_req - Parse and decrypt a KRB_AP_REQ message. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_rd_req - Parse and decrypt a KRB_AP_REQ message.

+
+
+krb5_error_code krb5_rd_req(krb5_context context, krb5_auth_context *auth_context, const krb5_data *inbuf, krb5_const_principal server, krb5_keytab keytab, krb5_flags *ap_req_options, krb5_ticket **ticket)
+
+ +
+
param
+

[in] context - Library context

+

[inout] auth_context - Pre-existing or newly created auth context

+

[in] inbuf - AP-REQ message to be parsed

+

[in] server - Matching principal for server, or NULL to allow any principal in keytab

+

[in] keytab - Key table, or NULL to use the default

+

[out] ap_req_options - If non-null, the AP-REQ flags on output

+

[out] ticket - If non-null, ticket from the AP-REQ message

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function parses, decrypts and verifies a AP-REQ message from inbuf and stores the authenticator in auth_context .

+

If a keyblock was specified in auth_context using krb5_auth_con_setuseruserkey(), that key is used to decrypt the ticket in AP-REQ message and keytab is ignored. In this case, server should be specified as a complete principal name to allow for proper transited-path checking and replay cache selection.

+

Otherwise, the decryption key is obtained from keytab , or from the default keytab if it is NULL. In this case, server may be a complete principal name, a matching principal (see krb5_sname_match()), or NULL to match any principal name. The keys tried against the encrypted part of the ticket are determined as follows:

+
+
    +
  • If server is a complete principal name, then its entry in keytab is tried.

  • +
  • Otherwise, if keytab is iterable, then all entries in keytab which match server are tried.

  • +
  • Otherwise, the server principal in the ticket must match server , and its entry in keytab is tried.

  • +
+
+

The client specified in the decrypted authenticator must match the client specified in the decrypted ticket.

+

If the remote_addr field of auth_context is set, the request must come from that address.

+

If a replay cache handle is provided in the auth_context , the authenticator and ticket are verified against it. If no conflict is found, the new authenticator is then stored in the replay cache of auth_context .

+

Various other checks are performed on the decoded data, including cross-realm policy, clockskew, and ticket validation times.

+

On success the authenticator, subkey, and remote sequence number of the request are stored in auth_context . If the #AP_OPTS_MUTUAL_REQUIRED bit is set, the local sequence number is XORed with the remote sequence number in the request.

+

Use krb5_free_ticket() to free ticket when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_safe.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_safe.html new file mode 100644 index 00000000..7559b1cf --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_rd_safe.html @@ -0,0 +1,169 @@ + + + + + + + + + krb5_rd_safe - Process KRB-SAFE message. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_rd_safe - Process KRB-SAFE message.

+
+
+krb5_error_code krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_data *userdata_out, krb5_replay_data *rdata_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] auth_context - Authentication context

+

[in] inbuf - KRB-SAFE message to be parsed

+

[out] userdata_out - Data parsed from KRB-SAFE message

+

[out] rdata_out - Replay data. Specify NULL if not needed

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function parses a KRB-SAFE message, verifies its integrity, and stores its data into userdata_out .

+

If auth_context has a remote address set, the address will be used to verify the sender address in the KRB-SAFE message. If auth_context has a local address set, it will be used to verify the receiver address in the KRB-SAFE message if the message contains one.

+

If the #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag is set in auth_context , the sequence number of the KRB-SAFE message is checked against the remote sequence number field of auth_context . Otherwise, the sequence number is not used.

+

If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in auth_context , then the timestamp in the message is verified to be within the permitted clock skew of the current time, and the message is checked against an in-memory replay cache to detect reflections or replays.

+

Use krb5_free_data_contents() to free userdata_out when it is no longer needed.

+
+

Note

+

The rdata_out argument is required if the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in auth_context .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_read_password.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_read_password.html new file mode 100644 index 00000000..0e5d899f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_read_password.html @@ -0,0 +1,172 @@ + + + + + + + + + krb5_read_password - Read a password from keyboard input. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_read_password - Read a password from keyboard input.

+
+
+krb5_error_code krb5_read_password(krb5_context context, const char *prompt, const char *prompt2, char *return_pwd, unsigned int *size_return)
+
+ +
+
param
+

[in] context - Library context

+

[in] prompt - First user prompt when reading password

+

[in] prompt2 - Second user prompt (NULL to prompt only once)

+

[out] return_pwd - Returned password

+

[inout] size_return - On input, maximum size of password; on output, size of password read

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Error in reading or verifying the password

  • +
  • Kerberos error codes

  • +
+
+
+

This function reads a password from keyboard input and stores it in return_pwd . size_return should be set by the caller to the amount of storage space available in return_pwd ; on successful return, it will be set to the length of the password read.

+
+

prompt is printed to the terminal, followed by”:”, and then a password is read from the keyboard.

+
+

If prompt2 is NULL, the password is read only once. Otherwise, prompt2 is printed to the terminal and a second password is read. If the two passwords entered are not identical, KRB5_LIBOS_BADPWDMATCH is returned.

+

Echoing is turned off when the password is read.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_realm_compare.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_realm_compare.html new file mode 100644 index 00000000..72baaeef --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_realm_compare.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_realm_compare - Compare the realms of two principals. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_realm_compare - Compare the realms of two principals.

+
+
+krb5_boolean krb5_realm_compare(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2)
+
+ +
+
param
+

[in] context - Library context

+

[in] princ1 - First principal

+

[in] princ2 - Second principal

+
+
+
+
retval
+
    +
  • TRUE if the realm names are the same; FALSE otherwise

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_recvauth.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_recvauth.html new file mode 100644 index 00000000..85e5983a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_recvauth.html @@ -0,0 +1,169 @@ + + + + + + + + + krb5_recvauth - Server function for sendauth protocol. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_recvauth - Server function for sendauth protocol.

+
+
+krb5_error_code krb5_recvauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fd, char *appl_version, krb5_principal server, krb5_int32 flags, krb5_keytab keytab, krb5_ticket **ticket)
+
+ +
+
param
+

[in] context - Library context

+

[inout] auth_context - Pre-existing or newly created auth context

+

[in] fd - File descriptor

+

[in] appl_version - Application protocol version to be matched against the client’s application version

+

[in] server - Server principal (NULL for any in keytab )

+

[in] flags - Additional specifications

+

[in] keytab - Key table containing service keys

+

[out] ticket - Ticket (NULL if not needed)

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function performs the server side of a sendauth/recvauth exchange by sending and receiving messages over fd .

+

Use krb5_free_ticket() to free ticket when it is no longer needed.

+
+

See also

+

krb5_sendauth()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_recvauth_version.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_recvauth_version.html new file mode 100644 index 00000000..6729f343 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_recvauth_version.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_recvauth_version - Server function for sendauth protocol with version parameter. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_recvauth_version - Server function for sendauth protocol with version parameter.

+
+
+krb5_error_code krb5_recvauth_version(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fd, krb5_principal server, krb5_int32 flags, krb5_keytab keytab, krb5_ticket **ticket, krb5_data *version)
+
+ +
+
param
+

[in] context - Library context

+

[inout] auth_context - Pre-existing or newly created auth context

+

[in] fd - File descriptor

+

[in] server - Server principal (NULL for any in keytab )

+

[in] flags - Additional specifications

+

[in] keytab - Decryption key

+

[out] ticket - Ticket (NULL if not needed)

+

[out] version - sendauth protocol version (NULL if not needed)

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function is similar to krb5_recvauth() with the additional output information place into version .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_get_challenge.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_get_challenge.html new file mode 100644 index 00000000..ce371663 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_get_challenge.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_responder_get_challenge - Retrieve the challenge data for a given question in the responder context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_responder_get_challenge - Retrieve the challenge data for a given question in the responder context.

+
+
+const char *krb5_responder_get_challenge(krb5_context ctx, krb5_responder_context rctx, const char *question)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] rctx - Responder context

+

[in] question - Question name

+
+
+

Return a pointer to a C string containing the challenge for question within rctx , or NULL if the question is not present in rctx . The structure of the question depends on the question name, but will always be printable UTF-8 text. The returned pointer is an alias, valid only as long as the lifetime of rctx , and should not be modified or freed by the caller.

+
+

Note

+

New in 1.11

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_list_questions.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_list_questions.html new file mode 100644 index 00000000..a4b4449d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_list_questions.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_responder_list_questions - List the question names contained in the responder context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_responder_list_questions - List the question names contained in the responder context.

+
+
+const char *const *krb5_responder_list_questions(krb5_context ctx, krb5_responder_context rctx)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] rctx - Responder context

+
+
+

Return a pointer to a null-terminated list of question names which are present in rctx . The pointer is an alias, valid only as long as the lifetime of rctx , and should not be modified or freed by the caller. A question’s challenge can be retrieved using krb5_responder_get_challenge() and answered using krb5_responder_set_answer().

+
+

Note

+

New in 1.11

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_otp_challenge_free.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_otp_challenge_free.html new file mode 100644 index 00000000..ce409406 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_otp_challenge_free.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_responder_otp_challenge_free - Free the value returned by krb5_responder_otp_get_challenge(). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_otp_get_challenge.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_otp_get_challenge.html new file mode 100644 index 00000000..6ab6f1ac --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_otp_get_challenge.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_responder_otp_get_challenge - Decode the KRB5_RESPONDER_QUESTION_OTP to a C struct. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_responder_otp_get_challenge - Decode the KRB5_RESPONDER_QUESTION_OTP to a C struct.

+
+
+krb5_error_code krb5_responder_otp_get_challenge(krb5_context ctx, krb5_responder_context rctx, krb5_responder_otp_challenge **chl)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] rctx - Responder context

+

[out] chl - Challenge structure

+
+
+

A convenience function which parses the KRB5_RESPONDER_QUESTION_OTP question challenge data, making it available in native C. The main feature of this function is the ability to interact with OTP tokens without parsing the JSON.

+

The returned value must be passed to krb5_responder_otp_challenge_free() to be freed.

+
+

Note

+

New in 1.11

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_otp_set_answer.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_otp_set_answer.html new file mode 100644 index 00000000..52b7433c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_otp_set_answer.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_responder_otp_set_answer - Answer the KRB5_RESPONDER_QUESTION_OTP question. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_responder_otp_set_answer - Answer the KRB5_RESPONDER_QUESTION_OTP question.

+
+
+krb5_error_code krb5_responder_otp_set_answer(krb5_context ctx, krb5_responder_context rctx, size_t ti, const char *value, const char *pin)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] rctx - Responder context

+

[in] ti - The index of the tokeninfo selected

+

[in] value - The value to set, or NULL for none

+

[in] pin - The pin to set, or NULL for none

+
+
+
+

Note

+

New in 1.11

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_pkinit_challenge_free.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_pkinit_challenge_free.html new file mode 100644 index 00000000..2de5e9a2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_pkinit_challenge_free.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_responder_pkinit_challenge_free - Free the value returned by krb5_responder_pkinit_get_challenge(). — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_pkinit_get_challenge.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_pkinit_get_challenge.html new file mode 100644 index 00000000..04b4a7ca --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_pkinit_get_challenge.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_responder_pkinit_get_challenge - Decode the KRB5_RESPONDER_QUESTION_PKINIT to a C struct. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_responder_pkinit_get_challenge - Decode the KRB5_RESPONDER_QUESTION_PKINIT to a C struct.

+
+
+krb5_error_code krb5_responder_pkinit_get_challenge(krb5_context ctx, krb5_responder_context rctx, krb5_responder_pkinit_challenge **chl_out)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] rctx - Responder context

+

[out] chl_out - Challenge structure

+
+
+

A convenience function which parses the KRB5_RESPONDER_QUESTION_PKINIT question challenge data, making it available in native C. The main feature of this function is the ability to read the challenge without parsing the JSON.

+

The returned value must be passed to krb5_responder_pkinit_challenge_free() to be freed.

+
+

Note

+

New in 1.12

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_pkinit_set_answer.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_pkinit_set_answer.html new file mode 100644 index 00000000..50e905eb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_pkinit_set_answer.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_responder_pkinit_set_answer - Answer the KRB5_RESPONDER_QUESTION_PKINIT question for one identity. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_responder_pkinit_set_answer - Answer the KRB5_RESPONDER_QUESTION_PKINIT question for one identity.

+
+
+krb5_error_code krb5_responder_pkinit_set_answer(krb5_context ctx, krb5_responder_context rctx, const char *identity, const char *pin)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] rctx - Responder context

+

[in] identity - The identity for which a PIN is being supplied

+

[in] pin - The provided PIN, or NULL for none

+
+
+
+

Note

+

New in 1.12

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_set_answer.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_set_answer.html new file mode 100644 index 00000000..eebea59e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_responder_set_answer.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_responder_set_answer - Answer a named question in the responder context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_responder_set_answer - Answer a named question in the responder context.

+
+
+krb5_error_code krb5_responder_set_answer(krb5_context ctx, krb5_responder_context rctx, const char *question, const char *answer)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] rctx - Responder context

+

[in] question - Question name

+

[in] answer - The string to set (MUST be printable UTF-8)

+
+
+
+
retval
+
    +
  • EINVAL question is not present within rctx

  • +
+
+
+

This function supplies an answer to question within rctx . The appropriate form of the answer depends on the question name.

+
+

Note

+

New in 1.11

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_salttype_to_string.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_salttype_to_string.html new file mode 100644 index 00000000..ad9d90d1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_salttype_to_string.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_salttype_to_string - Convert a salt type to a string. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_salttype_to_string - Convert a salt type to a string.

+
+
+krb5_error_code krb5_salttype_to_string(krb5_int32 salttype, char *buffer, size_t buflen)
+
+ +
+
param
+

[in] salttype - Salttype to convert

+

[out] buffer - Buffer to receive the converted string

+

[in] buflen - Storage available in buffer

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_sendauth.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_sendauth.html new file mode 100644 index 00000000..cdf295e6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_sendauth.html @@ -0,0 +1,185 @@ + + + + + + + + + krb5_sendauth - Client function for sendauth protocol. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_sendauth - Client function for sendauth protocol.

+
+
+krb5_error_code krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fd, char *appl_version, krb5_principal client, krb5_principal server, krb5_flags ap_req_options, krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, krb5_error **error, krb5_ap_rep_enc_part **rep_result, krb5_creds **out_creds)
+
+ +
+
param
+

[in] context - Library context

+

[inout] auth_context - Pre-existing or newly created auth context

+

[in] fd - File descriptor that describes network socket

+

[in] appl_version - Application protocol version to be matched with the receiver’s application version

+

[in] client - Client principal

+

[in] server - Server principal

+

[in] ap_req_options - Options (see AP_OPTS macros)

+

[in] in_data - Data to be sent to the server

+

[in] in_creds - Input credentials, or NULL to use ccache

+

[in] ccache - Credential cache

+

[out] error - If non-null, contains KRB_ERROR message returned from server

+

[out] rep_result - If non-null and ap_req_options is #AP_OPTS_MUTUAL_REQUIRED, contains the result of mutual authentication exchange

+

[out] out_creds - If non-null, the retrieved credentials

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function performs the client side of a sendauth/recvauth exchange by sending and receiving messages over fd .

+

Credentials may be specified in three ways:

+
+
+
    +
  • If in_creds is NULL, credentials are obtained with krb5_get_credentials() using the principals client and server . server must be non-null; client may NULL to use the default principal of ccache .

  • +
  • If in_creds is non-null, but does not contain a ticket, credentials for the exchange are obtained with krb5_get_credentials() using in_creds . In this case, the values of client and server are unused.

  • +
  • If in_creds is a complete credentials structure, it used directly. In this case, the values of client , server , and ccache are unused.

  • +
+
+

If the server is using a different application protocol than that specified in appl_version , an error will be returned.

+
+

Use krb5_free_creds() to free out_creds , krb5_free_ap_rep_enc_part() to free rep_result , and krb5_free_error() to free error when they are no longer needed.

+
+

See also

+

krb5_recvauth()

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_server_decrypt_ticket_keytab.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_server_decrypt_ticket_keytab.html new file mode 100644 index 00000000..119bad02 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_server_decrypt_ticket_keytab.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_server_decrypt_ticket_keytab - Decrypt a ticket using the specified key table. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_server_decrypt_ticket_keytab - Decrypt a ticket using the specified key table.

+
+
+krb5_error_code krb5_server_decrypt_ticket_keytab(krb5_context context, const krb5_keytab kt, krb5_ticket *ticket)
+
+ +
+
param
+

[in] context - Library context

+

[in] kt - Key table

+

[in] ticket - Ticket to be decrypted

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function takes a ticket as input and decrypts it using key data from kt . The result is placed into ticket->enc_part2 .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_default_realm.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_default_realm.html new file mode 100644 index 00000000..a8fb3c4c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_default_realm.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_set_default_realm - Override the default realm for the specified context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_set_default_realm - Override the default realm for the specified context.

+
+
+krb5_error_code krb5_set_default_realm(krb5_context context, const char *lrealm)
+
+ +
+
param
+

[in] context - Library context

+

[in] lrealm - Realm name for the default realm

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

If lrealm is NULL, clear the default realm setting.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_default_tgs_enctypes.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_default_tgs_enctypes.html new file mode 100644 index 00000000..16d311c4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_default_tgs_enctypes.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_set_default_tgs_enctypes - Set default TGS encryption types in a krb5_context structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_set_default_tgs_enctypes - Set default TGS encryption types in a krb5_context structure.

+
+
+krb5_error_code krb5_set_default_tgs_enctypes(krb5_context context, const krb5_enctype *etypes)
+
+ +
+
param
+

[in] context - Library context

+

[in] etypes - Encryption type(s) to set

+
+
+
+
retval
+
    +
  • 0 Success

  • +
  • KRB5_PROG_ETYPE_NOSUPP Program lacks support for encryption type

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function sets the default enctype list for TGS requests made using context to etypes .

+
+

Note

+

This overrides the default list (from config file or built-in).

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_error_message.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_error_message.html new file mode 100644 index 00000000..95d6cab5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_error_message.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_set_error_message - Set an extended error message for an error code. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_kdc_recv_hook.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_kdc_recv_hook.html new file mode 100644 index 00000000..b26d79d5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_kdc_recv_hook.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_set_kdc_recv_hook - Set a KDC post-receive hook function. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_set_kdc_recv_hook - Set a KDC post-receive hook function.

+
+
+void krb5_set_kdc_recv_hook(krb5_context context, krb5_post_recv_fn recv_hook, void *data)
+
+ +
+
param
+

[in] context - The library context.

+

[in] recv_hook - Hook function (or NULL to disable the hook)

+

[in] data - Callback data to be passed to recv_hook

+
+
+
+

recv_hook will be called after a reply is received from a KDC during a call to a library function such as krb5_get_credentials(). The hook function may inspect or override the reply. This hook will not be executed if the pre-send hook returns a synthetic reply.

+
+
+

Note

+

New in 1.15

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_kdc_send_hook.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_kdc_send_hook.html new file mode 100644 index 00000000..7d617965 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_kdc_send_hook.html @@ -0,0 +1,158 @@ + + + + + + + + + krb5_set_kdc_send_hook - Set a KDC pre-send hook function. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_set_kdc_send_hook - Set a KDC pre-send hook function.

+
+
+void krb5_set_kdc_send_hook(krb5_context context, krb5_pre_send_fn send_hook, void *data)
+
+ +
+
param
+

[in] context - Library context

+

[in] send_hook - Hook function (or NULL to disable the hook)

+

[in] data - Callback data to be passed to send_hook

+
+
+
+

send_hook will be called before messages are sent to KDCs by library functions such as krb5_get_credentials(). The hook function may inspect, override, or synthesize its own reply to the message.

+
+
+

Note

+

New in 1.15

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_password.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_password.html new file mode 100644 index 00000000..322450d8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_password.html @@ -0,0 +1,173 @@ + + + + + + + + + krb5_set_password - Set a password for a principal using specified credentials. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_set_password - Set a password for a principal using specified credentials.

+
+
+krb5_error_code krb5_set_password(krb5_context context, krb5_creds *creds, const char *newpw, krb5_principal change_password_for, int *result_code, krb5_data *result_code_string, krb5_data *result_string)
+
+ +
+
param
+

[in] context - Library context

+

[in] creds - Credentials for kadmin/changepw service

+

[in] newpw - New password

+

[in] change_password_for - Change the password for this principal

+

[out] result_code - Numeric error code from server

+

[out] result_code_string - String equivalent to result_code

+

[out] result_string - Data returned from the remote system

+
+
+
+
retval
+
    +
  • 0 Success and result_code is set to #KRB5_KPASSWD_SUCCESS.

  • +
+
+
return
+
    +
  • Kerberos error codes.

  • +
+
+
+

This function uses the credentials creds to set the password newpw for the principal change_password_for . It implements the set password operation of RFC 3244, for interoperability with Microsoft Windows implementations.

+

The error code and strings are returned in result_code , result_code_string and result_string .

+
+

Note

+

If change_password_for is NULL, the change is performed on the current principal. If change_password_for is non-null, the change is performed on the principal name passed in change_password_for .

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_password_using_ccache.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_password_using_ccache.html new file mode 100644 index 00000000..58450ef5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_password_using_ccache.html @@ -0,0 +1,173 @@ + + + + + + + + + krb5_set_password_using_ccache - Set a password for a principal using cached credentials. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_set_password_using_ccache - Set a password for a principal using cached credentials.

+
+
+krb5_error_code krb5_set_password_using_ccache(krb5_context context, krb5_ccache ccache, const char *newpw, krb5_principal change_password_for, int *result_code, krb5_data *result_code_string, krb5_data *result_string)
+
+ +
+
param
+

[in] context - Library context

+

[in] ccache - Credential cache

+

[in] newpw - New password

+

[in] change_password_for - Change the password for this principal

+

[out] result_code - Numeric error code from server

+

[out] result_code_string - String equivalent to result_code

+

[out] result_string - Data returned from the remote system

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function uses the cached credentials from ccache to set the password newpw for the principal change_password_for . It implements RFC 3244 set password operation (interoperable with MS Windows implementations) using the credential cache.

+

The error code and strings are returned in result_code , result_code_string and result_string .

+
+

Note

+

If change_password_for is set to NULL, the change is performed on the default principal in ccache . If change_password_for is non null, the change is performed on the specified principal.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_principal_realm.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_principal_realm.html new file mode 100644 index 00000000..b50b287d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_principal_realm.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_set_principal_realm - Set the realm field of a principal. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_set_principal_realm - Set the realm field of a principal.

+
+
+krb5_error_code krb5_set_principal_realm(krb5_context context, krb5_principal principal, const char *realm)
+
+ +
+
param
+

[in] context - Library context

+

[in] principal - Principal name

+

[in] realm - Realm name

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

Set the realm name part of principal to realm , overwriting the previous realm.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_real_time.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_real_time.html new file mode 100644 index 00000000..2786085b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_real_time.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_set_real_time - Set time offset field in a krb5_context structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_set_real_time - Set time offset field in a krb5_context structure.

+
+
+krb5_error_code krb5_set_real_time(krb5_context context, krb5_timestamp seconds, krb5_int32 microseconds)
+
+ +
+
param
+

[in] context - Library context

+

[in] seconds - Real time, seconds portion

+

[in] microseconds - Real time, microseconds portion

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function sets the time offset in context to the difference between the system time and the real time as determined by seconds and microseconds .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_trace_callback.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_trace_callback.html new file mode 100644 index 00000000..d307a729 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_trace_callback.html @@ -0,0 +1,167 @@ + + + + + + + + + krb5_set_trace_callback - Specify a callback function for trace events. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_set_trace_callback - Specify a callback function for trace events.

+
+
+krb5_error_code krb5_set_trace_callback(krb5_context context, krb5_trace_callback fn, void *cb_data)
+
+ +
+
param
+

[in] context - Library context

+

[in] fn - Callback function

+

[in] cb_data - Callback data

+
+
+
+
return
+
    +
  • Returns KRB5_TRACE_NOSUPP if tracing is not supported in the library (unless fn is NULL).

  • +
+
+
+

Specify a callback for trace events occurring in krb5 operations performed within context . fn will be invoked with context as the first argument, cb_data as the last argument, and a pointer to a krb5_trace_info as the second argument. If the trace callback is reset via this function or context is destroyed, fn will be invoked with a NULL second argument so it can clean up cb_data . Supply a NULL value for fn to disable trace callbacks within context .

+
+

Note

+

This function overrides the information passed through the KRB5_TRACE environment variable.

+
+
+

Note

+

New in 1.9

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_trace_filename.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_trace_filename.html new file mode 100644 index 00000000..b3cb27ed --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_set_trace_filename.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_set_trace_filename - Specify a file name for directing trace events. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_set_trace_filename - Specify a file name for directing trace events.

+
+
+krb5_error_code krb5_set_trace_filename(krb5_context context, const char *filename)
+
+ +
+
param
+

[in] context - Library context

+

[in] filename - File name

+
+
+
+
retval
+
    +
  • KRB5_TRACE_NOSUPP Tracing is not supported in the library.

  • +
+
+
+

Open filename for appending (creating it, if necessary) and set up a callback to write trace events to it.

+
+

Note

+

This function overrides the information passed through the KRB5_TRACE environment variable.

+
+
+

Note

+

New in 1.9

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_sname_match.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_sname_match.html new file mode 100644 index 00000000..254f7841 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_sname_match.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_sname_match - Test whether a principal matches a matching principal. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_sname_match - Test whether a principal matches a matching principal.

+
+
+krb5_boolean krb5_sname_match(krb5_context context, krb5_const_principal matching, krb5_const_principal princ)
+
+ +
+
param
+

[in] context - Library context

+

[in] matching - Matching principal

+

[in] princ - Principal to test

+
+
+
+
return
+
    +
  • TRUE if princ matches matching , FALSE otherwise.

  • +
+
+
+

If matching is NULL, return TRUE. If matching is not a matching principal, return the value of krb5_principal_compare(context, matching, princ).

+
+

Note

+

A matching principal is a host-based principal with an empty realm and/or second data component (hostname). Profile configuration may cause the hostname to be ignored even if it is present. A principal matches a matching principal if the former has the same non-empty (and non-ignored) components of the latter.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_sname_to_principal.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_sname_to_principal.html new file mode 100644 index 00000000..342e0811 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_sname_to_principal.html @@ -0,0 +1,176 @@ + + + + + + + + + krb5_sname_to_principal - Generate a full principal name from a service name. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_sname_to_principal - Generate a full principal name from a service name.

+
+
+krb5_error_code krb5_sname_to_principal(krb5_context context, const char *hostname, const char *sname, krb5_int32 type, krb5_principal *ret_princ)
+
+ +
+
param
+

[in] context - Library context

+

[in] hostname - Host name, or NULL to use local host

+

[in] sname - Service name, or NULL to use “host”

+

[in] type - Principal type

+

[out] ret_princ - Generated principal

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function converts a hostname and sname into krb5_principal structure ret_princ . The returned principal will be of the form sname/hostname@REALM where REALM is determined by krb5_get_host_realm(). In some cases this may be the referral (empty) realm.

+

The type can be one of the following:

+
+
+
    +
  • #KRB5_NT_SRV_HST canonicalizes the host name before looking up the realm and generating the principal.

  • +
  • #KRB5_NT_UNKNOWN accepts the hostname as given, and does not canonicalize it.

  • +
+
+

Use krb5_free_principal to free ret_princ when it is no longer needed.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_cksumtype.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_cksumtype.html new file mode 100644 index 00000000..6d8b1382 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_cksumtype.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_string_to_cksumtype - Convert a string to a checksum type. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_string_to_cksumtype - Convert a string to a checksum type.

+
+
+krb5_error_code krb5_string_to_cksumtype(char *string, krb5_cksumtype *cksumtypep)
+
+ +
+
param
+

[in] string - String to be converted

+

[out] cksumtypep - Checksum type to be filled in

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - EINVAL

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_deltat.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_deltat.html new file mode 100644 index 00000000..a87380da --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_deltat.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_string_to_deltat - Convert a string to a delta time value. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_string_to_deltat - Convert a string to a delta time value.

+
+
+krb5_error_code krb5_string_to_deltat(char *string, krb5_deltat *deltatp)
+
+ +
+
param
+

[in] string - String to be converted

+

[out] deltatp - Delta time to be filled in

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - KRB5_DELTAT_BADFORMAT

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_enctype.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_enctype.html new file mode 100644 index 00000000..0e89d17f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_enctype.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_string_to_enctype - Convert a string to an encryption type. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_string_to_enctype - Convert a string to an encryption type.

+
+
+krb5_error_code krb5_string_to_enctype(char *string, krb5_enctype *enctypep)
+
+ +
+
param
+

[in] string - String to convert to an encryption type

+

[out] enctypep - Encryption type

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - EINVAL

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_key.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_key.html new file mode 100644 index 00000000..3a3bd918 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_key.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_string_to_key — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_salttype.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_salttype.html new file mode 100644 index 00000000..8c6def7c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_salttype.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_string_to_salttype - Convert a string to a salt type. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_string_to_salttype - Convert a string to a salt type.

+
+
+krb5_error_code krb5_string_to_salttype(char *string, krb5_int32 *salttypep)
+
+ +
+
param
+

[in] string - String to convert to an encryption type

+

[out] salttypep - Salt type to be filled in

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - EINVAL

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_timestamp.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_timestamp.html new file mode 100644 index 00000000..9e9dd025 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_string_to_timestamp.html @@ -0,0 +1,157 @@ + + + + + + + + + krb5_string_to_timestamp - Convert a string to a timestamp. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_string_to_timestamp - Convert a string to a timestamp.

+
+
+krb5_error_code krb5_string_to_timestamp(char *string, krb5_timestamp *timestampp)
+
+ +
+
param
+

[in] string - String to be converted

+

[out] timestampp - Pointer to timestamp

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - EINVAL

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_timeofday.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_timeofday.html new file mode 100644 index 00000000..f60f4bd5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_timeofday.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_timeofday - Retrieve the current time with context specific time offset adjustment. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_timeofday - Retrieve the current time with context specific time offset adjustment.

+
+
+krb5_error_code krb5_timeofday(krb5_context context, krb5_timestamp *timeret)
+
+ +
+
param
+

[in] context - Library context

+

[out] timeret - Timestamp to fill in

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function retrieves the system time of day with the context specific time offset adjustment.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_timestamp_to_sfstring.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_timestamp_to_sfstring.html new file mode 100644 index 00000000..8ce57c5e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_timestamp_to_sfstring.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_timestamp_to_sfstring - Convert a timestamp to a string, with optional output padding. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_timestamp_to_sfstring - Convert a timestamp to a string, with optional output padding.

+
+
+krb5_error_code krb5_timestamp_to_sfstring(krb5_timestamp timestamp, char *buffer, size_t buflen, char *pad)
+
+ +
+
param
+

[in] timestamp - Timestamp to convert

+

[out] buffer - Buffer to hold the converted timestamp

+

[in] buflen - Length of buffer

+

[in] pad - Optional value to pad buffer if converted timestamp does not fill it

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

If pad is not NULL, buffer is padded out to buflen - 1 characters with the value of * pad .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_timestamp_to_string.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_timestamp_to_string.html new file mode 100644 index 00000000..62370c13 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_timestamp_to_string.html @@ -0,0 +1,159 @@ + + + + + + + + + krb5_timestamp_to_string - Convert a timestamp to a string. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_timestamp_to_string - Convert a timestamp to a string.

+
+
+krb5_error_code krb5_timestamp_to_string(krb5_timestamp timestamp, char *buffer, size_t buflen)
+
+ +
+
param
+

[in] timestamp - Timestamp to convert

+

[out] buffer - Buffer to hold converted timestamp

+

[in] buflen - Storage available in buffer

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

The string is returned in the locale’s appropriate date and time representation.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_free.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_free.html new file mode 100644 index 00000000..e7122d6c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_free.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_tkt_creds_free - Free a TGS request context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_get.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_get.html new file mode 100644 index 00000000..efb93e70 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_get.html @@ -0,0 +1,162 @@ + + + + + + + + + krb5_tkt_creds_get - Synchronously obtain credentials using a TGS request context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_tkt_creds_get - Synchronously obtain credentials using a TGS request context.

+
+
+krb5_error_code krb5_tkt_creds_get(krb5_context context, krb5_tkt_creds_context ctx)
+
+ +
+
param
+

[in] context - Library context

+

[in] ctx - TGS request context

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function synchronously obtains credentials using a context created by krb5_tkt_creds_init(). On successful return, the credentials can be retrieved with krb5_tkt_creds_get_creds().

+
+

Note

+

New in 1.9

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_get_creds.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_get_creds.html new file mode 100644 index 00000000..4b73a258 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_get_creds.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_tkt_creds_get_creds - Retrieve acquired credentials from a TGS request context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_tkt_creds_get_creds - Retrieve acquired credentials from a TGS request context.

+
+
+krb5_error_code krb5_tkt_creds_get_creds(krb5_context context, krb5_tkt_creds_context ctx, krb5_creds *creds)
+
+ +
+
param
+

[in] context - Library context

+

[in] ctx - TGS request context

+

[out] creds - Acquired credentials

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function copies the acquired initial credentials from ctx into creds , after the successful completion of krb5_tkt_creds_get() or krb5_tkt_creds_step(). Use krb5_free_cred_contents() to free creds when it is no longer needed.

+
+

Note

+

New in 1.9

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_get_times.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_get_times.html new file mode 100644 index 00000000..5cfbf4c0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_get_times.html @@ -0,0 +1,163 @@ + + + + + + + + + krb5_tkt_creds_get_times - Retrieve ticket times from a TGS request context. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_tkt_creds_get_times - Retrieve ticket times from a TGS request context.

+
+
+krb5_error_code krb5_tkt_creds_get_times(krb5_context context, krb5_tkt_creds_context ctx, krb5_ticket_times *times)
+
+ +
+
param
+

[in] context - Library context

+

[in] ctx - TGS request context

+

[out] times - Ticket times for acquired credentials

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

The TGS request context must have completed obtaining credentials via either krb5_tkt_creds_get() or krb5_tkt_creds_step().

+
+

Note

+

New in 1.9

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_init.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_init.html new file mode 100644 index 00000000..05298502 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_init.html @@ -0,0 +1,167 @@ + + + + + + + + + krb5_tkt_creds_init - Create a context to get credentials from a KDC’s Ticket Granting Service. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_tkt_creds_init - Create a context to get credentials from a KDC’s Ticket Granting Service.

+
+
+krb5_error_code krb5_tkt_creds_init(krb5_context context, krb5_ccache ccache, krb5_creds *creds, krb5_flags options, krb5_tkt_creds_context *ctx)
+
+ +
+
param
+

[in] context - Library context

+

[in] ccache - Credential cache handle

+

[in] creds - Input credentials

+

[in] options - Options (see KRB5_GC macros)

+

[out] ctx - New TGS request context

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function prepares to obtain credentials matching creds , either by retrieving them from ccache or by making requests to ticket-granting services beginning with a ticket-granting ticket for the client principal’s realm.

+

The resulting TGS acquisition context can be used asynchronously with krb5_tkt_creds_step() or synchronously with krb5_tkt_creds_get(). See also krb5_get_credentials() for synchronous use.

+

Use krb5_tkt_creds_free() to free ctx when it is no longer needed.

+
+

Note

+

New in 1.9

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_step.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_step.html new file mode 100644 index 00000000..7eeb50f2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_tkt_creds_step.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_tkt_creds_step - Get the next KDC request in a TGS exchange. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_tkt_creds_step - Get the next KDC request in a TGS exchange.

+
+
+krb5_error_code krb5_tkt_creds_step(krb5_context context, krb5_tkt_creds_context ctx, krb5_data *in, krb5_data *out, krb5_data *realm, unsigned int *flags)
+
+ +
+
param
+

[in] context - Library context

+

[in] ctx - TGS request context

+

[in] in - KDC response (empty on the first call)

+

[out] out - Next KDC request

+

[out] realm - Realm for next KDC request

+

[out] flags - Output flags

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function constructs the next KDC request for a TGS exchange, allowing the caller to control the transport of KDC requests and replies. On the first call, in should be set to an empty buffer; on subsequent calls, it should be set to the KDC’s reply to the previous request.

+

If more requests are needed, flags will be set to #KRB5_TKT_CREDS_STEP_FLAG_CONTINUE and the next request will be placed in out . If no more requests are needed, flags will not contain #KRB5_TKT_CREDS_STEP_FLAG_CONTINUE and out will be empty.

+

If this function returns KRB5KRB_ERR_RESPONSE_TOO_BIG , the caller should transmit the next request using TCP rather than UDP. If this function returns any other error, the TGS exchange has failed.

+
+

Note

+

New in 1.9

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unmarshal_credentials.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unmarshal_credentials.html new file mode 100644 index 00000000..2f2c3594 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unmarshal_credentials.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_unmarshal_credentials - Deserialize a krb5_creds object. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_unmarshal_credentials - Deserialize a krb5_creds object.

+
+
+krb5_error_code krb5_unmarshal_credentials(krb5_context context, const krb5_data *data, krb5_creds **creds_out)
+
+ +
+
param
+

[in] context - Library context

+

[in] data - The serialized credentials

+

[out] creds_out - The resulting creds object

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

Deserialize data to credentials in the format used by the FILE ccache format (vesion 4) and KCM ccache protocol.

+

Use krb5_free_creds() to free creds_out when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name.html new file mode 100644 index 00000000..8e3a717b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name.html @@ -0,0 +1,165 @@ + + + + + + + + + krb5_unparse_name - Convert a krb5_principal structure to a string representation. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_unparse_name - Convert a krb5_principal structure to a string representation.

+
+
+krb5_error_code krb5_unparse_name(krb5_context context, krb5_const_principal principal, char **name)
+
+ +
+
param
+

[in] context - Library context

+

[in] principal - Principal

+

[out] name - String representation of principal name

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

The resulting string representation uses the format and quoting conventions described for krb5_parse_name().

+

Use krb5_free_unparsed_name() to free name when it is no longer needed.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name_ext.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name_ext.html new file mode 100644 index 00000000..cdb3f3f5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name_ext.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_unparse_name_ext - Convert krb5_principal structure to string and length. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_unparse_name_ext - Convert krb5_principal structure to string and length.

+
+
+krb5_error_code krb5_unparse_name_ext(krb5_context context, krb5_const_principal principal, char **name, unsigned int *size)
+
+ +
+
param
+

[in] context - Library context

+

[in] principal - Principal

+

[inout] name - String representation of principal name

+

[inout] size - Size of unparsed name

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes. On failure name is set to NULL

  • +
+
+
+

This function is similar to krb5_unparse_name(), but allows the use of an existing buffer for the result. If size is not NULL, then name must point to either NULL or an existing buffer of at least the size pointed to by size . The buffer will be allocated or resized if necessary, with the new pointer stored into name . Whether or not the buffer is resized, the necessary space for the result, including null terminator, will be stored into size .

+

If size is NULL, this function behaves exactly as krb5_unparse_name().

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name_flags.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name_flags.html new file mode 100644 index 00000000..68687f4d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name_flags.html @@ -0,0 +1,176 @@ + + + + + + + + + krb5_unparse_name_flags - Convert krb5_principal structure to a string with flags. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_unparse_name_flags - Convert krb5_principal structure to a string with flags.

+
+
+krb5_error_code krb5_unparse_name_flags(krb5_context context, krb5_const_principal principal, int flags, char **name)
+
+ +
+
param
+

[in] context - Library context

+

[in] principal - Principal

+

[in] flags - Flags

+

[out] name - String representation of principal name

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes. On failure name is set to NULL

  • +
+
+
+

Similar to krb5_unparse_name(), this function converts a krb5_principal structure to a string representation.

+

The following flags are valid:

+
+
+
    +
  • #KRB5_PRINCIPAL_UNPARSE_SHORT - omit realm if it is the local realm

  • +
  • #KRB5_PRINCIPAL_UNPARSE_NO_REALM - omit realm

  • +
  • #KRB5_PRINCIPAL_UNPARSE_DISPLAY - do not quote special characters

  • +
+
+

Use krb5_free_unparsed_name() to free name when it is no longer needed.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name_flags_ext.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name_flags_ext.html new file mode 100644 index 00000000..bfda9aca --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_unparse_name_flags_ext.html @@ -0,0 +1,165 @@ + + + + + + + + + krb5_unparse_name_flags_ext - Convert krb5_principal structure to string format with flags. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_unparse_name_flags_ext - Convert krb5_principal structure to string format with flags.

+
+
+krb5_error_code krb5_unparse_name_flags_ext(krb5_context context, krb5_const_principal principal, int flags, char **name, unsigned int *size)
+
+ +
+
param
+

[in] context - Library context

+

[in] principal - Principal

+

[in] flags - Flags

+

[out] name - Single string format of principal name

+

[out] size - Size of unparsed name buffer

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes. On failure name is set to NULL

  • +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_us_timeofday.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_us_timeofday.html new file mode 100644 index 00000000..3b2b4322 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_us_timeofday.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_us_timeofday - Retrieve the system time of day, in sec and ms, since the epoch. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_us_timeofday - Retrieve the system time of day, in sec and ms, since the epoch.

+
+
+krb5_error_code krb5_us_timeofday(krb5_context context, krb5_timestamp *seconds, krb5_int32 *microseconds)
+
+ +
+
param
+

[in] context - Library context

+

[out] seconds - System timeofday, seconds portion

+

[out] microseconds - System timeofday, microseconds portion

+
+
+
+
retval
+
    +
  • 0 Success

  • +
+
+
return
+
    +
  • Kerberos error codes

  • +
+
+
+

This function retrieves the system time of day with the context specific time offset adjustment.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_use_enctype.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_use_enctype.html new file mode 100644 index 00000000..dd9fbcd4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_use_enctype.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_use_enctype — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_authdata_kdc_issued.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_authdata_kdc_issued.html new file mode 100644 index 00000000..4cdbb644 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_authdata_kdc_issued.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_verify_authdata_kdc_issued - Unwrap and verify AD-KDCIssued authorization data. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_verify_authdata_kdc_issued - Unwrap and verify AD-KDCIssued authorization data.

+
+
+krb5_error_code krb5_verify_authdata_kdc_issued(krb5_context context, const krb5_keyblock *key, const krb5_authdata *ad_kdcissued, krb5_principal *issuer, krb5_authdata ***authdata)
+
+ +
+
param
+

[in] context - Library context

+

[in] key - Session key

+

[in] ad_kdcissued - AD-KDCIssued authorization data to be unwrapped

+

[out] issuer - Name of issuing principal (or NULL)

+

[out] authdata - Unwrapped list of authorization data

+
+
+

This function unwraps an AD-KDCIssued authdatum (see RFC 4120 section 5.2.6.2) and verifies its signature against key . The issuer field of the authdatum element is returned in issuer , and the unwrapped list of authdata is returned in authdata .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_checksum.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_checksum.html new file mode 100644 index 00000000..aaca4728 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_checksum.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_verify_checksum — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_init_creds.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_init_creds.html new file mode 100644 index 00000000..7f705b7b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_init_creds.html @@ -0,0 +1,164 @@ + + + + + + + + + krb5_verify_init_creds - Verify initial credentials against a keytab. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_verify_init_creds - Verify initial credentials against a keytab.

+
+
+krb5_error_code krb5_verify_init_creds(krb5_context context, krb5_creds *creds, krb5_principal server, krb5_keytab keytab, krb5_ccache *ccache, krb5_verify_init_creds_opt *options)
+
+ +
+
param
+

[in] context - Library context

+

[in] creds - Initial credentials to be verified

+

[in] server - Server principal (or NULL)

+

[in] keytab - Key table (NULL to use default keytab)

+

[in] ccache - Credential cache for fetched creds (or NULL)

+

[in] options - Verification options (NULL for default options)

+
+
+
+
retval
+
    +
  • 0 Success; otherwise - Kerberos error codes

  • +
+
+
+

This function attempts to verify that creds were obtained from a KDC with knowledge of a key in keytab , or the default keytab if keytab is NULL. If server is provided, the highest-kvno key entry for that principal name is used to verify the credentials; otherwise, all unique”host”service principals in the keytab are tried.

+

If the specified keytab does not exist, or is empty, or cannot be read, or does not contain an entry for server , then credential verification may be skipped unless configuration demands that it succeed. The caller can control this behavior by providing a verification options structure; see krb5_verify_init_creds_opt_init() and krb5_verify_init_creds_opt_set_ap_req_nofail().

+

If ccache is NULL, any additional credentials fetched during the verification process will be destroyed. If ccache points to NULL, a memory ccache will be created for the additional credentials and returned in ccache . If ccache points to a valid credential cache handle, the additional credentials will be stored in that cache.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_init_creds_opt_init.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_init_creds_opt_init.html new file mode 100644 index 00000000..cc849396 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_init_creds_opt_init.html @@ -0,0 +1,149 @@ + + + + + + + + + krb5_verify_init_creds_opt_init - Initialize a credential verification options structure. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail.html new file mode 100644 index 00000000..e126c5b7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_verify_init_creds_opt_set_ap_req_nofail - Set whether credential verification is required. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_verify_init_creds_opt_set_ap_req_nofail - Set whether credential verification is required.

+
+
+void krb5_verify_init_creds_opt_set_ap_req_nofail(krb5_verify_init_creds_opt *k5_vic_options, int ap_req_nofail)
+
+ +
+
param
+

[in] k5_vic_options - Verification options structure

+

[in] ap_req_nofail - Whether to require successful verification

+
+
+

This function determines how krb5_verify_init_creds() behaves if no keytab information is available. If ap_req_nofail is FALSE , verification will be skipped in this case and krb5_verify_init_creds() will return successfully. If ap_req_nofail is TRUE , krb5_verify_init_creds() will not return successfully unless verification can be performed.

+

If this function is not used, the behavior of krb5_verify_init_creds() is determined through configuration.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_vprepend_error_message.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_vprepend_error_message.html new file mode 100644 index 00000000..94277fe3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_vprepend_error_message.html @@ -0,0 +1,153 @@ + + + + + + + + + krb5_vprepend_error_message - Add a prefix to the message for an error code using a va_list. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_vprepend_error_message - Add a prefix to the message for an error code using a va_list.

+
+
+void krb5_vprepend_error_message(krb5_context ctx, krb5_error_code code, const char *fmt, va_list args)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] code - Error code

+

[in] fmt - Format string for error message prefix

+

[in] args - List of vprintf(3) style arguments

+
+
+

This function is similar to krb5_prepend_error_message(), but uses a va_list instead of variadic arguments.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_vset_error_message.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_vset_error_message.html new file mode 100644 index 00000000..f53ce2d3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_vset_error_message.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_vset_error_message - Set an extended error message for an error code using a va_list. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_vset_error_message - Set an extended error message for an error code using a va_list.

+
+
+void krb5_vset_error_message(krb5_context ctx, krb5_error_code code, const char *fmt, va_list args)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] code - Error code

+

[in] fmt - Error string for the error code

+

[in] args - List of vprintf(3) style arguments

+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_vwrap_error_message.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_vwrap_error_message.html new file mode 100644 index 00000000..0609d8f7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_vwrap_error_message.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_vwrap_error_message - Add a prefix to a different error code’s message using a va_list. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_vwrap_error_message - Add a prefix to a different error code’s message using a va_list.

+
+
+void krb5_vwrap_error_message(krb5_context ctx, krb5_error_code old_code, krb5_error_code code, const char *fmt, va_list args)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] old_code - Previous error code

+

[in] code - Error code

+

[in] fmt - Format string for error message prefix

+

[in] args - List of vprintf(3) style arguments

+
+
+

This function is similar to krb5_wrap_error_message(), but uses a va_list instead of variadic arguments.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/api/krb5_wrap_error_message.html b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_wrap_error_message.html new file mode 100644 index 00000000..f0568ced --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/api/krb5_wrap_error_message.html @@ -0,0 +1,153 @@ + + + + + + + + + krb5_wrap_error_message - Add a prefix to a different error code’s message. — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_wrap_error_message - Add a prefix to a different error code’s message.

+
+
+void krb5_wrap_error_message(krb5_context ctx, krb5_error_code old_code, krb5_error_code code, const char *fmt, ...)
+
+ +
+
param
+

[in] ctx - Library context

+

[in] old_code - Previous error code

+

[in] code - Error code

+

[in] fmt - Format string for error message prefix

+
+
+

Format a message and prepend it to the message for old_code . The prefix will be separated from the old message with a colon and space. Set the resulting message as the extended error message for code .

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/index.html b/krb5-1.21.3/doc/html/appdev/refs/index.html new file mode 100644 index 00000000..9d77bd5b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/index.html @@ -0,0 +1,146 @@ + + + + + + + + + Complete reference - API and datatypes — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_ADDRPORT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_ADDRPORT.html new file mode 100644 index 00000000..4a690bd9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_ADDRPORT.html @@ -0,0 +1,155 @@ + + + + + + + + + ADDRTYPE_ADDRPORT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_CHAOS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_CHAOS.html new file mode 100644 index 00000000..1ba3684f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_CHAOS.html @@ -0,0 +1,155 @@ + + + + + + + + + ADDRTYPE_CHAOS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_DDP.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_DDP.html new file mode 100644 index 00000000..17b6bc4f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_DDP.html @@ -0,0 +1,155 @@ + + + + + + + + + ADDRTYPE_DDP — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_INET.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_INET.html new file mode 100644 index 00000000..de1e0ea9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_INET.html @@ -0,0 +1,155 @@ + + + + + + + + + ADDRTYPE_INET — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_INET6.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_INET6.html new file mode 100644 index 00000000..3c049203 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_INET6.html @@ -0,0 +1,155 @@ + + + + + + + + + ADDRTYPE_INET6 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_IPPORT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_IPPORT.html new file mode 100644 index 00000000..8a8e968c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_IPPORT.html @@ -0,0 +1,155 @@ + + + + + + + + + ADDRTYPE_IPPORT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_ISO.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_ISO.html new file mode 100644 index 00000000..9ae4173d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_ISO.html @@ -0,0 +1,155 @@ + + + + + + + + + ADDRTYPE_ISO — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_IS_LOCAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_IS_LOCAL.html new file mode 100644 index 00000000..56b8c503 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_IS_LOCAL.html @@ -0,0 +1,155 @@ + + + + + + + + + ADDRTYPE_IS_LOCAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_NETBIOS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_NETBIOS.html new file mode 100644 index 00000000..a202f72a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_NETBIOS.html @@ -0,0 +1,155 @@ + + + + + + + + + ADDRTYPE_NETBIOS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_XNS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_XNS.html new file mode 100644 index 00000000..a2aaa371 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ADDRTYPE_XNS.html @@ -0,0 +1,155 @@ + + + + + + + + + ADDRTYPE_XNS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_EXTERNAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_EXTERNAL.html new file mode 100644 index 00000000..5a47c981 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_EXTERNAL.html @@ -0,0 +1,155 @@ + + + + + + + + + AD_TYPE_EXTERNAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK.html b/krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK.html new file mode 100644 index 00000000..c9cdcd8d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK.html @@ -0,0 +1,155 @@ + + + + + + + + + AD_TYPE_FIELD_TYPE_MASK — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_REGISTERED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_REGISTERED.html new file mode 100644 index 00000000..f4a358dc --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_REGISTERED.html @@ -0,0 +1,155 @@ + + + + + + + + + AD_TYPE_REGISTERED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_RESERVED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_RESERVED.html new file mode 100644 index 00000000..dd39e3cd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/AD_TYPE_RESERVED.html @@ -0,0 +1,155 @@ + + + + + + + + + AD_TYPE_RESERVED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION.html b/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION.html new file mode 100644 index 00000000..ec6f3da7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION.html @@ -0,0 +1,155 @@ + + + + + + + + + AP_OPTS_ETYPE_NEGOTIATION — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED.html new file mode 100644 index 00000000..168ed1b0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED.html @@ -0,0 +1,156 @@ + + + + + + + + + AP_OPTS_MUTUAL_REQUIRED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_RESERVED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_RESERVED.html new file mode 100644 index 00000000..0767b785 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_RESERVED.html @@ -0,0 +1,155 @@ + + + + + + + + + AP_OPTS_RESERVED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_USE_SESSION_KEY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_USE_SESSION_KEY.html new file mode 100644 index 00000000..744de31d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_USE_SESSION_KEY.html @@ -0,0 +1,156 @@ + + + + + + + + + AP_OPTS_USE_SESSION_KEY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_USE_SUBKEY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_USE_SUBKEY.html new file mode 100644 index 00000000..1e30f4c1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_USE_SUBKEY.html @@ -0,0 +1,156 @@ + + + + + + + + + AP_OPTS_USE_SUBKEY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_WIRE_MASK.html b/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_WIRE_MASK.html new file mode 100644 index 00000000..6008a911 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/AP_OPTS_WIRE_MASK.html @@ -0,0 +1,155 @@ + + + + + + + + + AP_OPTS_WIRE_MASK — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128.html new file mode 100644 index 00000000..d9321d28 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128.html @@ -0,0 +1,156 @@ + + + + + + + + + CKSUMTYPE_CMAC_CAMELLIA128 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256.html new file mode 100644 index 00000000..589c5898 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256.html @@ -0,0 +1,156 @@ + + + + + + + + + CKSUMTYPE_CMAC_CAMELLIA256 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_CRC32.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_CRC32.html new file mode 100644 index 00000000..1bf66b00 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_CRC32.html @@ -0,0 +1,155 @@ + + + + + + + + + CKSUMTYPE_CRC32 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_DESCBC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_DESCBC.html new file mode 100644 index 00000000..042bf661 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_DESCBC.html @@ -0,0 +1,155 @@ + + + + + + + + + CKSUMTYPE_DESCBC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR.html new file mode 100644 index 00000000..23c1f670 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR.html @@ -0,0 +1,156 @@ + + + + + + + + + CKSUMTYPE_HMAC_MD5_ARCFOUR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128.html new file mode 100644 index 00000000..d35c0a29 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128.html @@ -0,0 +1,157 @@ + + + + + + + + + CKSUMTYPE_HMAC_SHA1_96_AES128 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256.html new file mode 100644 index 00000000..08b21dc0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256.html @@ -0,0 +1,157 @@ + + + + + + + + + CKSUMTYPE_HMAC_SHA1_96_AES256 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3.html new file mode 100644 index 00000000..bf3433cd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3.html @@ -0,0 +1,155 @@ + + + + + + + + + CKSUMTYPE_HMAC_SHA1_DES3 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128.html new file mode 100644 index 00000000..91b508c0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128.html @@ -0,0 +1,156 @@ + + + + + + + + + CKSUMTYPE_HMAC_SHA256_128_AES128 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256.html new file mode 100644 index 00000000..357b75e3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256.html @@ -0,0 +1,156 @@ + + + + + + + + + CKSUMTYPE_HMAC_SHA384_192_AES256 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR.html new file mode 100644 index 00000000..561e2406 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR.html @@ -0,0 +1,155 @@ + + + + + + + + + CKSUMTYPE_MD5_HMAC_ARCFOUR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_NIST_SHA.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_NIST_SHA.html new file mode 100644 index 00000000..78169f07 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_NIST_SHA.html @@ -0,0 +1,155 @@ + + + + + + + + + CKSUMTYPE_NIST_SHA — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD4.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD4.html new file mode 100644 index 00000000..8763a528 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD4.html @@ -0,0 +1,155 @@ + + + + + + + + + CKSUMTYPE_RSA_MD4 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES.html new file mode 100644 index 00000000..4828b9fc --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES.html @@ -0,0 +1,155 @@ + + + + + + + + + CKSUMTYPE_RSA_MD4_DES — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD5.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD5.html new file mode 100644 index 00000000..3a231320 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD5.html @@ -0,0 +1,155 @@ + + + + + + + + + CKSUMTYPE_RSA_MD5 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES.html new file mode 100644 index 00000000..47bb1428 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES.html @@ -0,0 +1,155 @@ + + + + + + + + + CKSUMTYPE_RSA_MD5_DES — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_SHA1.html b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_SHA1.html new file mode 100644 index 00000000..03a47722 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/CKSUMTYPE_SHA1.html @@ -0,0 +1,156 @@ + + + + + + + + + CKSUMTYPE_SHA1 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96.html new file mode 100644 index 00000000..84907dbe --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_AES128_CTS_HMAC_SHA1_96 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128.html new file mode 100644 index 00000000..cf7d6dbb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_AES128_CTS_HMAC_SHA256_128 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96.html new file mode 100644 index 00000000..b1236939 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_AES256_CTS_HMAC_SHA1_96 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192.html new file mode 100644 index 00000000..45cb40b1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_AES256_CTS_HMAC_SHA384_192 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC.html new file mode 100644 index 00000000..81404587 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_ARCFOUR_HMAC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP.html new file mode 100644 index 00000000..d8540d50 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_ARCFOUR_HMAC_EXP — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC.html new file mode 100644 index 00000000..e4ac076f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_CAMELLIA128_CTS_CMAC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC.html new file mode 100644 index 00000000..4188976c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_CAMELLIA256_CTS_CMAC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_ENV.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_ENV.html new file mode 100644 index 00000000..ef5824a1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_ENV.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_DES3_CBC_ENV — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_RAW.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_RAW.html new file mode 100644 index 00000000..ac77c0b8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_RAW.html @@ -0,0 +1,155 @@ + + + + + + + + + ENCTYPE_DES3_CBC_RAW — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA.html new file mode 100644 index 00000000..d1339c5e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA.html @@ -0,0 +1,155 @@ + + + + + + + + + ENCTYPE_DES3_CBC_SHA — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1.html new file mode 100644 index 00000000..fffeb10e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1.html @@ -0,0 +1,155 @@ + + + + + + + + + ENCTYPE_DES3_CBC_SHA1 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_CRC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_CRC.html new file mode 100644 index 00000000..d27ac671 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_CRC.html @@ -0,0 +1,155 @@ + + + + + + + + + ENCTYPE_DES_CBC_CRC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_MD4.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_MD4.html new file mode 100644 index 00000000..713b165d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_MD4.html @@ -0,0 +1,155 @@ + + + + + + + + + ENCTYPE_DES_CBC_MD4 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_MD5.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_MD5.html new file mode 100644 index 00000000..ff8f67f3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_MD5.html @@ -0,0 +1,155 @@ + + + + + + + + + ENCTYPE_DES_CBC_MD5 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_RAW.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_RAW.html new file mode 100644 index 00000000..2b00c5fd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_CBC_RAW.html @@ -0,0 +1,155 @@ + + + + + + + + + ENCTYPE_DES_CBC_RAW — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1.html new file mode 100644 index 00000000..ce2ba381 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1.html @@ -0,0 +1,155 @@ + + + + + + + + + ENCTYPE_DES_HMAC_SHA1 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS.html new file mode 100644 index 00000000..25cbe168 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_DSA_SHA1_CMS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_MD5_RSA_CMS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_MD5_RSA_CMS.html new file mode 100644 index 00000000..f8ddb844 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_MD5_RSA_CMS.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_MD5_RSA_CMS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_NULL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_NULL.html new file mode 100644 index 00000000..470a8321 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_NULL.html @@ -0,0 +1,155 @@ + + + + + + + + + ENCTYPE_NULL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_RC2_CBC_ENV.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_RC2_CBC_ENV.html new file mode 100644 index 00000000..723f07e7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_RC2_CBC_ENV.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_RC2_CBC_ENV — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_RSA_ENV.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_RSA_ENV.html new file mode 100644 index 00000000..954a7b4b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_RSA_ENV.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_RSA_ENV — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV.html new file mode 100644 index 00000000..e6850077 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_RSA_ES_OAEP_ENV — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS.html new file mode 100644 index 00000000..036a26da --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS.html @@ -0,0 +1,156 @@ + + + + + + + + + ENCTYPE_SHA1_RSA_CMS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_UNKNOWN.html b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_UNKNOWN.html new file mode 100644 index 00000000..87adccda --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/ENCTYPE_UNKNOWN.html @@ -0,0 +1,155 @@ + + + + + + + + + ENCTYPE_UNKNOWN — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE.html new file mode 100644 index 00000000..2588bf41 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_ALLOW_POSTDATE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_CANONICALIZE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_CANONICALIZE.html new file mode 100644 index 00000000..d09d2419 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_CANONICALIZE.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_CANONICALIZE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT.html new file mode 100644 index 00000000..77c24f7e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_CNAME_IN_ADDL_TKT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK.html new file mode 100644 index 00000000..6991b8cd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_DISABLE_TRANSITED_CHECK — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY.html new file mode 100644 index 00000000..cab56838 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_ENC_TKT_IN_SKEY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_FORWARDABLE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_FORWARDABLE.html new file mode 100644 index 00000000..a498762a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_FORWARDABLE.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_FORWARDABLE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_FORWARDED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_FORWARDED.html new file mode 100644 index 00000000..2406fb8f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_FORWARDED.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_FORWARDED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_POSTDATED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_POSTDATED.html new file mode 100644 index 00000000..3e592eef --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_POSTDATED.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_POSTDATED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_PROXIABLE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_PROXIABLE.html new file mode 100644 index 00000000..9a1d6329 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_PROXIABLE.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_PROXIABLE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_PROXY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_PROXY.html new file mode 100644 index 00000000..9afc01d4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_PROXY.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_PROXY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_RENEW.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_RENEW.html new file mode 100644 index 00000000..1530a3bd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_RENEW.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_RENEW — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_RENEWABLE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_RENEWABLE.html new file mode 100644 index 00000000..7e6cce5e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_RENEWABLE.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_RENEWABLE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_RENEWABLE_OK.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_RENEWABLE_OK.html new file mode 100644 index 00000000..fa7a46ff --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_RENEWABLE_OK.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_RENEWABLE_OK — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS.html new file mode 100644 index 00000000..86f81fe8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_REQUEST_ANONYMOUS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_VALIDATE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_VALIDATE.html new file mode 100644 index 00000000..2c5e3a25 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_OPT_VALIDATE.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_OPT_VALIDATE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_TKT_COMMON_MASK.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_TKT_COMMON_MASK.html new file mode 100644 index 00000000..fdb24401 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KDC_TKT_COMMON_MASK.html @@ -0,0 +1,155 @@ + + + + + + + + + KDC_TKT_COMMON_MASK — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE.html new file mode 100644 index 00000000..1b17d417 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR.html new file mode 100644 index 00000000..cf18a4da --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_ANONYMOUS_PRINCSTR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR.html new file mode 100644 index 00000000..86788b7c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_ANONYMOUS_REALMSTR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AP_REP.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AP_REP.html new file mode 100644 index 00000000..ee080adb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AP_REP.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_AP_REP — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AP_REQ.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AP_REQ.html new file mode 100644 index 00000000..39d61c1a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AP_REQ.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_AP_REQ — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AS_REP.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AS_REP.html new file mode 100644 index 00000000..dcb25ad5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AS_REP.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_AS_REP — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AS_REQ.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AS_REQ.html new file mode 100644 index 00000000..42bcd972 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AS_REQ.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_AS_REQ — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_AND_OR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_AND_OR.html new file mode 100644 index 00000000..70fff114 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_AND_OR.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTHDATA_AND_OR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS.html new file mode 100644 index 00000000..4e0a933d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTHDATA_AP_OPTIONS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR.html new file mode 100644 index 00000000..82afcd62 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTHDATA_AUTH_INDICATOR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_CAMMAC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_CAMMAC.html new file mode 100644 index 00000000..7082a8b7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_CAMMAC.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTHDATA_CAMMAC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION.html new file mode 100644 index 00000000..f418aa0c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_AUTHDATA_ETYPE_NEGOTIATION — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR.html new file mode 100644 index 00000000..e5a1920c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTHDATA_FX_ARMOR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT.html new file mode 100644 index 00000000..98120239 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTHDATA_IF_RELEVANT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS.html new file mode 100644 index 00000000..39c6ac2f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTHDATA_INITIAL_VERIFIED_CAS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED.html new file mode 100644 index 00000000..7e813f0a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTHDATA_KDC_ISSUED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC.html new file mode 100644 index 00000000..9b124c94 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTHDATA_MANDATORY_FOR_KDC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE.html new file mode 100644 index 00000000..dfcc6487 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTHDATA_OSF_DCE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_SESAME.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_SESAME.html new file mode 100644 index 00000000..120e7ce8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_SESAME.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTHDATA_SESAME — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET.html new file mode 100644 index 00000000..bbce7738 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTHDATA_SIGNTICKET — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC.html new file mode 100644 index 00000000..dbb62a3b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTHDATA_WIN2K_PAC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE.html new file mode 100644 index 00000000..41ae605a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_AUTH_CONTEXT_DO_SEQUENCE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME.html new file mode 100644 index 00000000..f33df20c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_AUTH_CONTEXT_DO_TIME — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR.html new file mode 100644 index 00000000..de82c37d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR.html new file mode 100644 index 00000000..52ff5672 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR.html new file mode 100644 index 00000000..1c589911 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR.html new file mode 100644 index 00000000..24f41b7c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL.html new file mode 100644 index 00000000..82dad6a9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTH_CONTEXT_PERMIT_ALL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE.html new file mode 100644 index 00000000..7e0adf83 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_AUTH_CONTEXT_RET_SEQUENCE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME.html new file mode 100644 index 00000000..fc0b6ce3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_AUTH_CONTEXT_RET_TIME — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY.html new file mode 100644 index 00000000..57bbb1f5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_AUTH_CONTEXT_USE_SUBKEY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRED.html new file mode 100644 index 00000000..dff7b7b8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRED.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_CRED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM.html new file mode 100644 index 00000000..715b25c3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_CRYPTO_TYPE_CHECKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA.html new file mode 100644 index 00000000..226fc9eb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_CRYPTO_TYPE_DATA — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY.html new file mode 100644 index 00000000..e895e4c3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_CRYPTO_TYPE_EMPTY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER.html new file mode 100644 index 00000000..ced3ac96 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_CRYPTO_TYPE_HEADER — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING.html new file mode 100644 index 00000000..a6c2bcae --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_CRYPTO_TYPE_PADDING — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY.html new file mode 100644 index 00000000..1c1aeaf0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_CRYPTO_TYPE_SIGN_ONLY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM.html new file mode 100644 index 00000000..79997368 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_CRYPTO_TYPE_STREAM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER.html new file mode 100644 index 00000000..f3b67981 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_CRYPTO_TYPE_TRAILER — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CYBERSAFE_SECUREID.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CYBERSAFE_SECUREID.html new file mode 100644 index 00000000..ab69e2ca --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_CYBERSAFE_SECUREID.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_CYBERSAFE_SECUREID — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS.html new file mode 100644 index 00000000..dc467886 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_DOMAIN_X500_COMPRESS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP.html new file mode 100644 index 00000000..7d555dbc --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_ENCPADATA_REQ_ENC_PA_REP — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ERROR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ERROR.html new file mode 100644 index 00000000..f62c0f80 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_ERROR.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_ERROR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_FAST_REQUIRED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_FAST_REQUIRED.html new file mode 100644 index 00000000..93accd57 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_FAST_REQUIRED.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_FAST_REQUIRED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_CACHED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_CACHED.html new file mode 100644 index 00000000..a14f2dfa --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_CACHED.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_GC_CACHED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_CANONICALIZE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_CANONICALIZE.html new file mode 100644 index 00000000..4b95ab58 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_CANONICALIZE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_GC_CANONICALIZE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION.html new file mode 100644 index 00000000..fa83ca8c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_GC_CONSTRAINED_DELEGATION — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_FORWARDABLE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_FORWARDABLE.html new file mode 100644 index 00000000..1c902021 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_FORWARDABLE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_GC_FORWARDABLE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_NO_STORE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_NO_STORE.html new file mode 100644 index 00000000..0d295ef1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_NO_STORE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_GC_NO_STORE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK.html new file mode 100644 index 00000000..5bbb5a91 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_GC_NO_TRANSIT_CHECK — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_USER_USER.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_USER_USER.html new file mode 100644 index 00000000..f29ef86e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GC_USER_USER.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_GC_USER_USER — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST.html new file mode 100644 index 00000000..23e88cf0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS.html new file mode 100644 index 00000000..7a30c695 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_GET_INIT_CREDS_OPT_ANONYMOUS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE.html new file mode 100644 index 00000000..1644df0b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_GET_INIT_CREDS_OPT_CANONICALIZE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT.html new file mode 100644 index 00000000..c246fe80 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST.html new file mode 100644 index 00000000..16fb25df --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE.html new file mode 100644 index 00000000..74a0055c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_GET_INIT_CREDS_OPT_FORWARDABLE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST.html new file mode 100644 index 00000000..52a7f824 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE.html new file mode 100644 index 00000000..c26dce11 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_GET_INIT_CREDS_OPT_PROXIABLE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE.html new file mode 100644 index 00000000..ff000ba6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT.html new file mode 100644 index 00000000..373b1277 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_GET_INIT_CREDS_OPT_SALT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE.html new file mode 100644 index 00000000..01cd6a15 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_GET_INIT_CREDS_OPT_TKT_LIFE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INIT_CONTEXT_KDC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INIT_CONTEXT_KDC.html new file mode 100644 index 00000000..355450bb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INIT_CONTEXT_KDC.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_INIT_CONTEXT_KDC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE.html new file mode 100644 index 00000000..54eb8e4a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_INIT_CONTEXT_SECURE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE.html new file mode 100644 index 00000000..bdb4060b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_INIT_CREDS_STEP_FLAG_CONTINUE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT16_MAX.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT16_MAX.html new file mode 100644 index 00000000..f40df445 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT16_MAX.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_INT16_MAX — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT16_MIN.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT16_MIN.html new file mode 100644 index 00000000..4dfa1b9f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT16_MIN.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_INT16_MIN — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT32_MAX.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT32_MAX.html new file mode 100644 index 00000000..e1101c51 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT32_MAX.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_INT32_MAX — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT32_MIN.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT32_MIN.html new file mode 100644 index 00000000..96792cb3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_INT32_MIN.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_INT32_MIN — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE.html new file mode 100644 index 00000000..15ce11f0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_AD_ITE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM.html new file mode 100644 index 00000000..e5132d76 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE.html new file mode 100644 index 00000000..1390823c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_AD_MTE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH.html new file mode 100644 index 00000000..f29a8003 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_AD_SIGNEDPATH — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM.html new file mode 100644 index 00000000..157bb001 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_APP_DATA_CKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT.html new file mode 100644 index 00000000..148b4241 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_APP_DATA_ENCRYPT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART.html new file mode 100644 index 00000000..42a81593 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_AP_REP_ENCPART — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH.html new file mode 100644 index 00000000..2afec23e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_AP_REQ_AUTH — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM.html new file mode 100644 index 00000000..fe7b9a02 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART.html new file mode 100644 index 00000000..684eab34 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_AS_REP_ENCPART — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ.html new file mode 100644 index 00000000..ee4b5c97 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_AS_REQ — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS.html new file mode 100644 index 00000000..347d8084 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC.html new file mode 100644 index 00000000..55ef8a23 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_CAMMAC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT.html new file mode 100644 index 00000000..07e06c93 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC.html new file mode 100644 index 00000000..eb1dad66 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_ENC_CHALLENGE_KDC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC.html new file mode 100644 index 00000000..05d84c73 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_FAST_ENC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED.html new file mode 100644 index 00000000..8cac3ee3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_FAST_FINISHED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP.html new file mode 100644 index 00000000..468a1372 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_FAST_REP — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM.html new file mode 100644 index 00000000..04a5fda6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_FAST_REQ_CHKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC.html new file mode 100644 index 00000000..644df17e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_GSS_TOK_MIC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.html new file mode 100644 index 00000000..e8f10482 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.html new file mode 100644 index 00000000..3007f386 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED.html new file mode 100644 index 00000000..2c95a450 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_IAKERB_FINISHED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET.html new file mode 100644 index 00000000..acd0b536 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_KDC_REP_TICKET — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART.html new file mode 100644 index 00000000..e11c08f5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_KRB_CRED_ENCPART — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM.html new file mode 100644 index 00000000..060342a2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_KRB_ERROR_CKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART.html new file mode 100644 index 00000000..68a4880f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_KRB_PRIV_ENCPART — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM.html new file mode 100644 index 00000000..ba018d6d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_KRB_SAFE_CKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS.html new file mode 100644 index 00000000..d9c80b7a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_KEYUSAGE_PA_AS_FRESHNESS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE.html new file mode 100644 index 00000000..e8292e4f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_KEYUSAGE_PA_FX_COOKIE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST.html new file mode 100644 index 00000000..e89df956 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_KEYUSAGE_PA_OTP_REQUEST — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX.html new file mode 100644 index 00000000..40868aa9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_PA_PKINIT_KX — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY.html new file mode 100644 index 00000000..ae63d69b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST.html new file mode 100644 index 00000000..6274c41c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.html new file mode 100644 index 00000000..a0e3d1bb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.html new file mode 100644 index 00000000..ec6428aa --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE.html new file mode 100644 index 00000000..44e7ff24 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_PA_SAM_RESPONSE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_SPAKE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_SPAKE.html new file mode 100644 index 00000000..10c5646b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_SPAKE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_SPAKE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.html new file mode 100644 index 00000000..3d08678f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.html new file mode 100644 index 00000000..2c588309 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.html new file mode 100644 index 00000000..7a7f6dbe --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY.html new file mode 100644 index 00000000..41e1cfaa --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH.html new file mode 100644 index 00000000..d2797ff5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_TGS_REQ_AUTH — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM.html new file mode 100644 index 00000000..656d6db8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED.html new file mode 100644 index 00000000..8cca01a4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_KPASSWD_ACCESSDENIED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_AUTHERROR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_AUTHERROR.html new file mode 100644 index 00000000..dac7c727 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_AUTHERROR.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_KPASSWD_AUTHERROR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION.html new file mode 100644 index 00000000..8c7797e6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_KPASSWD_BAD_VERSION — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_HARDERROR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_HARDERROR.html new file mode 100644 index 00000000..548a9491 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_HARDERROR.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_KPASSWD_HARDERROR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED.html new file mode 100644 index 00000000..ed33f90c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_KPASSWD_INITIAL_FLAG_NEEDED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_MALFORMED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_MALFORMED.html new file mode 100644 index 00000000..02531d2e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_MALFORMED.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_KPASSWD_MALFORMED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_SOFTERROR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_SOFTERROR.html new file mode 100644 index 00000000..3e148d5c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_SOFTERROR.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_KPASSWD_SOFTERROR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_SUCCESS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_SUCCESS.html new file mode 100644 index 00000000..5a34deae --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_KPASSWD_SUCCESS.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_KPASSWD_SUCCESS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME.html new file mode 100644 index 00000000..4df404e2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ALL_ACCT_EXPTIME — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL.html new file mode 100644 index 00000000..3fa64341 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ALL_LAST_INITIAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL.html new file mode 100644 index 00000000..f5c91b47 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ALL_LAST_RENEWAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ.html new file mode 100644 index 00000000..b8ca647f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ALL_LAST_REQ — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT.html new file mode 100644 index 00000000..1cad65d9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ALL_LAST_TGT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED.html new file mode 100644 index 00000000..c640d128 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ALL_LAST_TGT_ISSUED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME.html new file mode 100644 index 00000000..922f0cb7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ALL_PW_EXPTIME — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_NONE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_NONE.html new file mode 100644 index 00000000..94908791 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_NONE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_NONE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME.html new file mode 100644 index 00000000..04158f6e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ONE_ACCT_EXPTIME — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL.html new file mode 100644 index 00000000..c636173c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ONE_LAST_INITIAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL.html new file mode 100644 index 00000000..699a6e6b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ONE_LAST_RENEWAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ.html new file mode 100644 index 00000000..67cc996d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ONE_LAST_REQ — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT.html new file mode 100644 index 00000000..db11dfd5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ONE_LAST_TGT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED.html new file mode 100644 index 00000000..e577d4a4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ONE_LAST_TGT_ISSUED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME.html new file mode 100644 index 00000000..19aa6125 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_LRQ_ONE_PW_EXPTIME — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL.html new file mode 100644 index 00000000..1fac3dc6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_NT_ENTERPRISE_PRINCIPAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID.html new file mode 100644 index 00000000..3f8c4a54 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_NT_ENT_PRINCIPAL_AND_ID — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL.html new file mode 100644 index 00000000..a4c6d64c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_NT_MS_PRINCIPAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID.html new file mode 100644 index 00000000..4f094861 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_NT_MS_PRINCIPAL_AND_ID — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_PRINCIPAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_PRINCIPAL.html new file mode 100644 index 00000000..8417f080 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_PRINCIPAL.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_NT_PRINCIPAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SMTP_NAME.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SMTP_NAME.html new file mode 100644 index 00000000..713f7d04 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SMTP_NAME.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_NT_SMTP_NAME — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SRV_HST.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SRV_HST.html new file mode 100644 index 00000000..ea39be06 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SRV_HST.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_NT_SRV_HST — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SRV_INST.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SRV_INST.html new file mode 100644 index 00000000..e06767b5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SRV_INST.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_NT_SRV_INST — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SRV_XHST.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SRV_XHST.html new file mode 100644 index 00000000..58ff5a38 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_SRV_XHST.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_NT_SRV_XHST — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_UID.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_UID.html new file mode 100644 index 00000000..9f07d918 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_UID.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_NT_UID — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_UNKNOWN.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_UNKNOWN.html new file mode 100644 index 00000000..1fafad87 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_UNKNOWN.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_NT_UNKNOWN — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_WELLKNOWN.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_WELLKNOWN.html new file mode 100644 index 00000000..ae4e8efd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_WELLKNOWN.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_NT_WELLKNOWN — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_X500_PRINCIPAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_X500_PRINCIPAL.html new file mode 100644 index 00000000..97cd623b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_NT_X500_PRINCIPAL.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_NT_X500_PRINCIPAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO.html new file mode 100644 index 00000000..e06554a7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_ATTRIBUTES_INFO — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS.html new file mode 100644 index 00000000..cbc6f1b8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_CLIENT_CLAIMS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_CLIENT_INFO.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_CLIENT_INFO.html new file mode 100644 index 00000000..0baaa306 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_CLIENT_INFO.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_CLIENT_INFO — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO.html new file mode 100644 index 00000000..4a8affa0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_CREDENTIALS_INFO — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_DELEGATION_INFO.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_DELEGATION_INFO.html new file mode 100644 index 00000000..f64e5e49 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_DELEGATION_INFO.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_DELEGATION_INFO — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS.html new file mode 100644 index 00000000..fd4c885b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_DEVICE_CLAIMS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_DEVICE_INFO.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_DEVICE_INFO.html new file mode 100644 index 00000000..013bb185 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_DEVICE_INFO.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_DEVICE_INFO — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM.html new file mode 100644 index 00000000..353d4dd9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_FULL_CHECKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_LOGON_INFO.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_LOGON_INFO.html new file mode 100644 index 00000000..bfc0234b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_LOGON_INFO.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_LOGON_INFO — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM.html new file mode 100644 index 00000000..3ffdbb29 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_PRIVSVR_CHECKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_REQUESTOR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_REQUESTOR.html new file mode 100644 index 00000000..47817b39 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_REQUESTOR.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_REQUESTOR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM.html new file mode 100644 index 00000000..d24eb72f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_SERVER_CHECKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM.html new file mode 100644 index 00000000..fb62d2bd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_TICKET_CHECKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO.html new file mode 100644 index 00000000..fd41ee25 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PAC_UPN_DNS_INFO — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AFS3_SALT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AFS3_SALT.html new file mode 100644 index 00000000..dbcf8818 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AFS3_SALT.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_PADATA_AFS3_SALT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AP_REQ.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AP_REQ.html new file mode 100644 index 00000000..79e93cdc --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AP_REQ.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_PADATA_AP_REQ — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM.html new file mode 100644 index 00000000..e792ee2c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_AS_CHECKSUM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS.html new file mode 100644 index 00000000..591d530e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_AS_FRESHNESS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE.html new file mode 100644 index 00000000..cdec0985 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_ENCRYPTED_CHALLENGE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID.html new file mode 100644 index 00000000..0aabef98 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_PADATA_ENC_SANDIA_SECURID — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP.html new file mode 100644 index 00000000..d2ded004 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_ENC_TIMESTAMP — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME.html new file mode 100644 index 00000000..3bf213c5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_PADATA_ENC_UNIX_TIME — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO.html new file mode 100644 index 00000000..a3f9dec3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_PADATA_ETYPE_INFO — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2.html new file mode 100644 index 00000000..26dcb563 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_ETYPE_INFO2 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FOR_USER.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FOR_USER.html new file mode 100644 index 00000000..a27a4a42 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FOR_USER.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_FOR_USER — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FX_COOKIE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FX_COOKIE.html new file mode 100644 index 00000000..441bf7a7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FX_COOKIE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_FX_COOKIE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FX_ERROR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FX_ERROR.html new file mode 100644 index 00000000..cc138b81 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FX_ERROR.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_FX_ERROR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FX_FAST.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FX_FAST.html new file mode 100644 index 00000000..ec6a02d8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_FX_FAST.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_FX_FAST — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA.html new file mode 100644 index 00000000..694b3a39 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_PADATA_GET_FROM_TYPED_DATA — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_NONE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_NONE.html new file mode 100644 index 00000000..53ac73b9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_NONE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_PADATA_NONE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OSF_DCE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OSF_DCE.html new file mode 100644 index 00000000..e52e1823 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OSF_DCE.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_PADATA_OSF_DCE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE.html new file mode 100644 index 00000000..73b98513 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_OTP_CHALLENGE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE.html new file mode 100644 index 00000000..9b40085c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_OTP_PIN_CHANGE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OTP_REQUEST.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OTP_REQUEST.html new file mode 100644 index 00000000..e1555bde --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_OTP_REQUEST.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_OTP_REQUEST — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS.html new file mode 100644 index 00000000..127483eb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_PAC_OPTIONS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PAC_REQUEST.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PAC_REQUEST.html new file mode 100644 index 00000000..33f40044 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PAC_REQUEST.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_PAC_REQUEST — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PKINIT_KX.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PKINIT_KX.html new file mode 100644 index 00000000..bd7cb1a8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PKINIT_KX.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_PKINIT_KX — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REP.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REP.html new file mode 100644 index 00000000..6c26c165 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REP.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_PADATA_PK_AS_REP — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD.html new file mode 100644 index 00000000..6720716b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_PK_AS_REP_OLD — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ.html new file mode 100644 index 00000000..1381c3f6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_PADATA_PK_AS_REQ — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD.html new file mode 100644 index 00000000..2f6f8a02 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_PK_AS_REQ_OLD — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PW_SALT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PW_SALT.html new file mode 100644 index 00000000..82779459 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_PW_SALT.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_PW_SALT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2.html new file mode 100644 index 00000000..90a848b4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_REDHAT_IDP_OAUTH2 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY.html new file mode 100644 index 00000000..c7716401 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_REDHAT_PASSKEY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_REFERRAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_REFERRAL.html new file mode 100644 index 00000000..60769bc8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_REFERRAL.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_REFERRAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_S4U_X509_USER.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_S4U_X509_USER.html new file mode 100644 index 00000000..dab60d42 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_S4U_X509_USER.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_S4U_X509_USER — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE.html new file mode 100644 index 00000000..d9470ce8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_SAM_CHALLENGE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2.html new file mode 100644 index 00000000..93c5e28c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_SAM_CHALLENGE_2 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT.html new file mode 100644 index 00000000..9afb8585 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_PADATA_SAM_REDIRECT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE.html new file mode 100644 index 00000000..90dd4098 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_SAM_RESPONSE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2.html new file mode 100644 index 00000000..35cfcc56 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_SAM_RESPONSE_2 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SESAME.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SESAME.html new file mode 100644 index 00000000..29d865fb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SESAME.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_PADATA_SESAME — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SPAKE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SPAKE.html new file mode 100644 index 00000000..ff33e801 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SPAKE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_PADATA_SPAKE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO.html new file mode 100644 index 00000000..73c39f7b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_PADATA_SVR_REFERRAL_INFO — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_TGS_REQ.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_TGS_REQ.html new file mode 100644 index 00000000..e9373351 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_TGS_REQ.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_PADATA_TGS_REQ — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO.html new file mode 100644 index 00000000..26579093 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PADATA_USE_SPECIFIED_KVNO — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD.html new file mode 100644 index 00000000..299fcdce --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PRINCIPAL_COMPARE_CASEFOLD — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE.html new file mode 100644 index 00000000..30caf5b2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PRINCIPAL_COMPARE_ENTERPRISE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM.html new file mode 100644 index 00000000..17e389d9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PRINCIPAL_COMPARE_IGNORE_REALM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8.html new file mode 100644 index 00000000..d9344c89 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PRINCIPAL_COMPARE_UTF8 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE.html new file mode 100644 index 00000000..70a1e25b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PRINCIPAL_PARSE_ENTERPRISE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM.html new file mode 100644 index 00000000..39d64c35 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PRINCIPAL_PARSE_IGNORE_REALM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM.html new file mode 100644 index 00000000..3f72f4e0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PRINCIPAL_PARSE_NO_DEF_REALM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM.html new file mode 100644 index 00000000..5fd992a2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PRINCIPAL_PARSE_NO_REALM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM.html new file mode 100644 index 00000000..f5095cbd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PRINCIPAL_PARSE_REQUIRE_REALM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY.html new file mode 100644 index 00000000..31fe3d22 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PRINCIPAL_UNPARSE_DISPLAY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM.html new file mode 100644 index 00000000..966c02a1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PRINCIPAL_UNPARSE_NO_REALM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT.html new file mode 100644 index 00000000..d3428444 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PRINCIPAL_UNPARSE_SHORT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRIV.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRIV.html new file mode 100644 index 00000000..cc916c5c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PRIV.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PRIV — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD.html new file mode 100644 index 00000000..b7804380 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PROMPT_TYPE_NEW_PASSWORD — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN.html new file mode 100644 index 00000000..804677e0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD.html new file mode 100644 index 00000000..502e9e54 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PROMPT_TYPE_PASSWORD — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH.html new file mode 100644 index 00000000..b171ba7b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PROMPT_TYPE_PREAUTH — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PVNO.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PVNO.html new file mode 100644 index 00000000..38745ac3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_PVNO.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_PVNO — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_REALM_BRANCH_CHAR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_REALM_BRANCH_CHAR.html new file mode 100644 index 00000000..bc709d69 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_REALM_BRANCH_CHAR.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_REALM_BRANCH_CHAR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS.html new file mode 100644 index 00000000..b46c6741 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_RECVAUTH_BADAUTHVERS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION.html new file mode 100644 index 00000000..e082baba --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_RECVAUTH_SKIP_VERSION — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_REFERRAL_REALM.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_REFERRAL_REALM.html new file mode 100644 index 00000000..0b9a4ac2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_REFERRAL_REALM.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_REFERRAL_REALM — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN.html new file mode 100644 index 00000000..623466c8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN.html new file mode 100644 index 00000000..cebd9b69 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP.html new file mode 100644 index 00000000..7ddab447 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_RESPONDER_OTP_FLAGS_NEXTOTP — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

KRB5_RESPONDER_OTP_FLAGS_NEXTOTP

+
+
+KRB5_RESPONDER_OTP_FLAGS_NEXTOTP
+
+ +

This flag indicates that the token is now in re-synchronization mode with the server.

+

The user is expected to reply with the next code displayed on the token.

+ ++++ + + + + + +

KRB5_RESPONDER_OTP_FLAGS_NEXTOTP

0x0004

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN.html new file mode 100644 index 00000000..82e90dd4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN

+
+
+KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN
+
+ +

This flag indicates that the PIN MUST be returned as a separate item.

+

This flag only takes effect if KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN is set. If this flag is not set, the responder may either concatenate PIN + token value and store it as “value” in the answer or it may return them separately. If they are returned separately, they will be concatenated internally.

+ ++++ + + + + + +

KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN

0x0008

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC.html new file mode 100644 index 00000000..54e9f962 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL.html new file mode 100644 index 00000000..bddbd49c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_RESPONDER_OTP_FORMAT_DECIMAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL.html new file mode 100644 index 00000000..e914ac60 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW.html new file mode 100644 index 00000000..112c8885 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW

+
+
+KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW
+
+ +

This flag indicates that an incorrect PIN was supplied at least once since the last time the correct PIN was supplied.

+ ++++ + + + + + +

KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW

(1 << 0)

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY.html new file mode 100644 index 00000000..2bf60dd7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY

+
+
+KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY
+
+ +

This flag indicates that supplying an incorrect PIN will cause the token to lock itself.

+ ++++ + + + + + +

KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY

(1 << 1)

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.html new file mode 100644 index 00000000..b1a4bfbe --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED

+
+
+KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED
+
+ +

This flag indicates that the user PIN is locked, and you can’t log in to the token with it.

+ ++++ + + + + + +

KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED

(1 << 2)

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP.html new file mode 100644 index 00000000..c0a0447c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP.html @@ -0,0 +1,183 @@ + + + + + + + + + KRB5_RESPONDER_QUESTION_OTP — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

KRB5_RESPONDER_QUESTION_OTP

+
+
+KRB5_RESPONDER_QUESTION_OTP
+
+ +

OTP responder question.

+

The OTP responder question is asked when the KDC indicates that an OTP value is required in order to complete the authentication. The JSON format of the challenge is:

+
{
+  "service": <string (optional)>,
+  "tokenInfo": [
+    {
+      "flags":     <number>,
+      "vendor":    <string (optional)>,
+      "challenge": <string (optional)>,
+      "length":    <number (optional)>,
+      "format":    <number (optional)>,
+      "tokenID":   <string (optional)>,
+      "algID":     <string (optional)>,
+    },
+    ...
+  ]
+}
+
+
+

The answer to the question MUST be JSON formatted:

+
{
+  "tokeninfo": <number>,
+  "value":     <string (optional)>,
+  "pin":       <string (optional)>,
+}
+
+
+

For more detail, please see RFC 6560.

+ ++++ + + + + + +

KRB5_RESPONDER_QUESTION_OTP

"otp"

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD.html new file mode 100644 index 00000000..02444d31 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD.html @@ -0,0 +1,157 @@ + + + + + + + + + KRB5_RESPONDER_QUESTION_PASSWORD — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

KRB5_RESPONDER_QUESTION_PASSWORD

+
+
+KRB5_RESPONDER_QUESTION_PASSWORD
+
+ +

Long-term password responder question.

+

This question is asked when the long-term password is needed. It has no challenge and the response is simply the password string.

+ ++++ + + + + + +

KRB5_RESPONDER_QUESTION_PASSWORD

"password"

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT.html new file mode 100644 index 00000000..9555cd40 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT.html @@ -0,0 +1,170 @@ + + + + + + + + + KRB5_RESPONDER_QUESTION_PKINIT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

KRB5_RESPONDER_QUESTION_PKINIT

+
+
+KRB5_RESPONDER_QUESTION_PKINIT
+
+ +

PKINIT responder question.

+

The PKINIT responder question is asked when the client needs a password that’s being used to protect key information, and is formatted as a JSON object. A specific identity’s flags value, if not zero, is the bitwise-OR of one or more of the KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_* flags defined below, and possibly other flags to be added later. Any resemblance to similarly-named CKF_* values in the PKCS#11 API should not be depended on.

+
{
+    identity <string> : flags <number>,
+    ...
+}
+
+
+

The answer to the question MUST be JSON formatted:

+
{
+    identity <string> : password <string>,
+    ...
+}
+
+
+ ++++ + + + + + +

KRB5_RESPONDER_QUESTION_PKINIT

"pkinit"

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAFE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAFE.html new file mode 100644 index 00000000..28aa5416 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAFE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_SAFE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD.html new file mode 100644 index 00000000..91e0a11f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_SAM_MUST_PK_ENCRYPT_SAD — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD.html new file mode 100644 index 00000000..fc84dd56 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_SAM_SEND_ENCRYPTED_SAD — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY.html new file mode 100644 index 00000000..ab16bebd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_SAM_USE_SAD_AS_KEY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT.html new file mode 100644 index 00000000..a0f0bc2c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TC_MATCH_2ND_TKT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA.html new file mode 100644 index 00000000..56fd2b0a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TC_MATCH_AUTHDATA — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_FLAGS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_FLAGS.html new file mode 100644 index 00000000..ba64fc52 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_FLAGS.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TC_MATCH_FLAGS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT.html new file mode 100644 index 00000000..9277e5f9 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TC_MATCH_FLAGS_EXACT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY.html new file mode 100644 index 00000000..05f51208 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TC_MATCH_IS_SKEY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_KTYPE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_KTYPE.html new file mode 100644 index 00000000..26a09f4e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_KTYPE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TC_MATCH_KTYPE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY.html new file mode 100644 index 00000000..21a46395 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TC_MATCH_SRV_NAMEONLY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_TIMES.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_TIMES.html new file mode 100644 index 00000000..706fa811 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_TIMES.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TC_MATCH_TIMES — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT.html new file mode 100644 index 00000000..b4ced03c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TC_MATCH_TIMES_EXACT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_NOTICKET.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_NOTICKET.html new file mode 100644 index 00000000..a538e81c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_NOTICKET.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_TC_NOTICKET — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_OPENCLOSE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_OPENCLOSE.html new file mode 100644 index 00000000..d29a659d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_OPENCLOSE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TC_OPENCLOSE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES.html new file mode 100644 index 00000000..804f3f96 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TC_SUPPORTED_KTYPES — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_NAME.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_NAME.html new file mode 100644 index 00000000..fc50c9d2 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_NAME.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_TGS_NAME — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_NAME_SIZE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_NAME_SIZE.html new file mode 100644 index 00000000..17165999 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_NAME_SIZE.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_TGS_NAME_SIZE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_REP.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_REP.html new file mode 100644 index 00000000..1de7c9e8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_REP.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TGS_REP — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_REQ.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_REQ.html new file mode 100644 index 00000000..17b6805d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TGS_REQ.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TGS_REQ — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE.html new file mode 100644 index 00000000..6f4074cd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_TKT_CREDS_STEP_FLAG_CONTINUE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL.html new file mode 100644 index 00000000..209ec907 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL.html @@ -0,0 +1,155 @@ + + + + + + + + + KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR.html b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR.html new file mode 100644 index 00000000..b26465ae --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR.html @@ -0,0 +1,156 @@ + + + + + + + + + KRB5_WELLKNOWN_NAMESTR — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK.html b/krb5-1.21.3/doc/html/appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK.html new file mode 100644 index 00000000..ab9812dd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK.html @@ -0,0 +1,155 @@ + + + + + + + + + LR_TYPE_INTERPRETATION_MASK — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY.html new file mode 100644 index 00000000..c54eaae6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY.html @@ -0,0 +1,155 @@ + + + + + + + + + LR_TYPE_THIS_SERVER_ONLY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/MAX_KEYTAB_NAME_LEN.html b/krb5-1.21.3/doc/html/appdev/refs/macros/MAX_KEYTAB_NAME_LEN.html new file mode 100644 index 00000000..9bae5d74 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/MAX_KEYTAB_NAME_LEN.html @@ -0,0 +1,156 @@ + + + + + + + + + MAX_KEYTAB_NAME_LEN — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/MSEC_DIRBIT.html b/krb5-1.21.3/doc/html/appdev/refs/macros/MSEC_DIRBIT.html new file mode 100644 index 00000000..e706689f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/MSEC_DIRBIT.html @@ -0,0 +1,155 @@ + + + + + + + + + MSEC_DIRBIT — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/MSEC_VAL_MASK.html b/krb5-1.21.3/doc/html/appdev/refs/macros/MSEC_VAL_MASK.html new file mode 100644 index 00000000..8e39c74c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/MSEC_VAL_MASK.html @@ -0,0 +1,155 @@ + + + + + + + + + MSEC_VAL_MASK — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/SALT_TYPE_AFS_LENGTH.html b/krb5-1.21.3/doc/html/appdev/refs/macros/SALT_TYPE_AFS_LENGTH.html new file mode 100644 index 00000000..fde0badb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/SALT_TYPE_AFS_LENGTH.html @@ -0,0 +1,155 @@ + + + + + + + + + SALT_TYPE_AFS_LENGTH — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/SALT_TYPE_NO_LENGTH.html b/krb5-1.21.3/doc/html/appdev/refs/macros/SALT_TYPE_NO_LENGTH.html new file mode 100644 index 00000000..e63ffe42 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/SALT_TYPE_NO_LENGTH.html @@ -0,0 +1,155 @@ + + + + + + + + + SALT_TYPE_NO_LENGTH — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/THREEPARAMOPEN.html b/krb5-1.21.3/doc/html/appdev/refs/macros/THREEPARAMOPEN.html new file mode 100644 index 00000000..48e6dbe5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/THREEPARAMOPEN.html @@ -0,0 +1,155 @@ + + + + + + + + + THREEPARAMOPEN — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_ANONYMOUS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_ANONYMOUS.html new file mode 100644 index 00000000..eb6bf255 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_ANONYMOUS.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_ANONYMOUS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_ENC_PA_REP.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_ENC_PA_REP.html new file mode 100644 index 00000000..9d8646f5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_ENC_PA_REP.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_ENC_PA_REP — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_FORWARDABLE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_FORWARDABLE.html new file mode 100644 index 00000000..ae4dea63 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_FORWARDABLE.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_FORWARDABLE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_FORWARDED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_FORWARDED.html new file mode 100644 index 00000000..6c11f1ef --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_FORWARDED.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_FORWARDED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_HW_AUTH.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_HW_AUTH.html new file mode 100644 index 00000000..d24e78cd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_HW_AUTH.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_HW_AUTH — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_INITIAL.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_INITIAL.html new file mode 100644 index 00000000..fdbd605f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_INITIAL.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_INITIAL — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_INVALID.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_INVALID.html new file mode 100644 index 00000000..59690bdd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_INVALID.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_INVALID — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_MAY_POSTDATE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_MAY_POSTDATE.html new file mode 100644 index 00000000..90215b3f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_MAY_POSTDATE.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_MAY_POSTDATE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE.html new file mode 100644 index 00000000..f8720858 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_OK_AS_DELEGATE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_POSTDATED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_POSTDATED.html new file mode 100644 index 00000000..7876d7fb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_POSTDATED.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_POSTDATED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_PRE_AUTH.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_PRE_AUTH.html new file mode 100644 index 00000000..7986b172 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_PRE_AUTH.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_PRE_AUTH — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_PROXIABLE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_PROXIABLE.html new file mode 100644 index 00000000..6442711a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_PROXIABLE.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_PROXIABLE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_PROXY.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_PROXY.html new file mode 100644 index 00000000..e92bfd30 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_PROXY.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_PROXY — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_RENEWABLE.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_RENEWABLE.html new file mode 100644 index 00000000..c64c3421 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_RENEWABLE.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_RENEWABLE — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED.html b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED.html new file mode 100644 index 00000000..1948ba86 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED.html @@ -0,0 +1,155 @@ + + + + + + + + + TKT_FLG_TRANSIT_POLICY_CHECKED — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/VALID_INT_BITS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/VALID_INT_BITS.html new file mode 100644 index 00000000..8667fdf6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/VALID_INT_BITS.html @@ -0,0 +1,155 @@ + + + + + + + + + VALID_INT_BITS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/VALID_UINT_BITS.html b/krb5-1.21.3/doc/html/appdev/refs/macros/VALID_UINT_BITS.html new file mode 100644 index 00000000..e3369ff5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/VALID_UINT_BITS.html @@ -0,0 +1,155 @@ + + + + + + + + + VALID_UINT_BITS — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/index.html b/krb5-1.21.3/doc/html/appdev/refs/macros/index.html new file mode 100644 index 00000000..c29da0e3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/index.html @@ -0,0 +1,538 @@ + + + + + + + + + krb5 simple macros — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5 simple macros

+
+

Public

+
+ +
+
+
+

Deprecated macros

+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb524_convert_creds_kdc.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb524_convert_creds_kdc.html new file mode 100644 index 00000000..43b9edd6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb524_convert_creds_kdc.html @@ -0,0 +1,155 @@ + + + + + + + + + krb524_convert_creds_kdc — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb524_init_ets.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb524_init_ets.html new file mode 100644 index 00000000..c9e8d245 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb524_init_ets.html @@ -0,0 +1,155 @@ + + + + + + + + + krb524_init_ets — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_const.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_const.html new file mode 100644 index 00000000..f7a465cd --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_const.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_const — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_component.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_component.html new file mode 100644 index 00000000..9213f53f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_component.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_princ_component — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_name.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_name.html new file mode 100644 index 00000000..1d74bab1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_name.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_princ_name — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_realm.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_realm.html new file mode 100644 index 00000000..b823d83c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_realm.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_princ_realm — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_set_realm.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_set_realm.html new file mode 100644 index 00000000..46911bbf --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_set_realm.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_princ_set_realm — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_set_realm_data.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_set_realm_data.html new file mode 100644 index 00000000..7efffde6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_set_realm_data.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_princ_set_realm_data — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_set_realm_length.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_set_realm_length.html new file mode 100644 index 00000000..f40014ca --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_set_realm_length.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_princ_set_realm_length — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_size.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_size.html new file mode 100644 index 00000000..e3c40b40 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_size.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_princ_size — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_type.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_type.html new file mode 100644 index 00000000..3f4cfe16 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_princ_type.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_princ_type — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_roundup.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_roundup.html new file mode 100644 index 00000000..5760e26e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_roundup.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_roundup — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_x.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_x.html new file mode 100644 index 00000000..5dbad632 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_x.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_x — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_xc.html b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_xc.html new file mode 100644 index 00000000..936738c5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/macros/krb5_xc.html @@ -0,0 +1,155 @@ + + + + + + + + + krb5_xc — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/index.html b/krb5-1.21.3/doc/html/appdev/refs/types/index.html new file mode 100644 index 00000000..5e9535b8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/index.html @@ -0,0 +1,248 @@ + + + + + + + + + krb5 types and structures — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5 types and structures

+
+

Public

+ +
+
+

Internal

+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_address.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_address.html new file mode 100644 index 00000000..294f8cd3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_address.html @@ -0,0 +1,176 @@ + + + + + + + + + krb5_address — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_addrtype.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_addrtype.html new file mode 100644 index 00000000..b628f07c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_addrtype.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_addrtype — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ap_rep.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ap_rep.html new file mode 100644 index 00000000..9e545b12 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ap_rep.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_ap_rep — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_ap_rep

+
+
+type krb5_ap_rep
+
+ +

C representaton of AP-REP message.

+

The server’s response to a client’s request for mutual authentication.

+
+

Declaration

+

typedef struct _krb5_ap_rep krb5_ap_rep

+
+
+

Members

+
+
+krb5_magic krb5_ap_rep.magic
+
+ +
+
+krb5_enc_data krb5_ap_rep.enc_part
+

Ciphertext of ApRepEncPart.

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ap_rep_enc_part.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ap_rep_enc_part.html new file mode 100644 index 00000000..dc828802 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ap_rep_enc_part.html @@ -0,0 +1,185 @@ + + + + + + + + + krb5_ap_rep_enc_part — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_ap_rep_enc_part

+
+
+type krb5_ap_rep_enc_part
+
+ +

Cleartext that is encrypted and put into _krb5_ap_rep .

+
+

Declaration

+

typedef struct _krb5_ap_rep_enc_part krb5_ap_rep_enc_part

+
+
+

Members

+
+
+krb5_magic krb5_ap_rep_enc_part.magic
+
+ +
+
+krb5_timestamp krb5_ap_rep_enc_part.ctime
+

Client time, seconds portion.

+
+ +
+
+krb5_int32 krb5_ap_rep_enc_part.cusec
+

Client time, microseconds portion.

+
+ +
+
+krb5_keyblock *krb5_ap_rep_enc_part.subkey
+

Subkey (optional)

+
+ +
+
+krb5_ui_4 krb5_ap_rep_enc_part.seq_number
+

Sequence number.

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ap_req.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ap_req.html new file mode 100644 index 00000000..ca351ebf --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ap_req.html @@ -0,0 +1,179 @@ + + + + + + + + + krb5_ap_req — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_auth_context.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_auth_context.html new file mode 100644 index 00000000..ed1bad76 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_auth_context.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_auth_context — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_authdata.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_authdata.html new file mode 100644 index 00000000..80b6c041 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_authdata.html @@ -0,0 +1,179 @@ + + + + + + + + + krb5_authdata — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_authdatatype.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_authdatatype.html new file mode 100644 index 00000000..46a50acb --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_authdatatype.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_authdatatype — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_authenticator.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_authenticator.html new file mode 100644 index 00000000..cdf6a7b3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_authenticator.html @@ -0,0 +1,204 @@ + + + + + + + + + krb5_authenticator — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_authenticator

+
+
+type krb5_authenticator
+
+ +

Ticket authenticator.

+

The C representation of an unencrypted authenticator.

+
+

Declaration

+

typedef struct _krb5_authenticator krb5_authenticator

+
+
+

Members

+
+
+krb5_magic krb5_authenticator.magic
+
+ +
+
+krb5_principal krb5_authenticator.client
+

client name/realm

+
+ +
+
+krb5_checksum *krb5_authenticator.checksum
+

checksum, includes type, optional

+
+ +
+
+krb5_int32 krb5_authenticator.cusec
+

client usec portion

+
+ +
+
+krb5_timestamp krb5_authenticator.ctime
+

client sec portion

+
+ +
+
+krb5_keyblock *krb5_authenticator.subkey
+

true session key, optional

+
+ +
+
+krb5_ui_4 krb5_authenticator.seq_number
+

sequence #, optional

+
+ +
+
+krb5_authdata **krb5_authenticator.authorization_data
+

authoriazation data

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_boolean.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_boolean.html new file mode 100644 index 00000000..4e87bd02 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_boolean.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_boolean — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cc_cursor.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cc_cursor.html new file mode 100644 index 00000000..5863dd69 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cc_cursor.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_cc_cursor — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ccache.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ccache.html new file mode 100644 index 00000000..a6049bd5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ccache.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_ccache — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cccol_cursor.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cccol_cursor.html new file mode 100644 index 00000000..32946183 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cccol_cursor.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_cccol_cursor — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_checksum.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_checksum.html new file mode 100644 index 00000000..e4cfae98 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_checksum.html @@ -0,0 +1,175 @@ + + + + + + + + + krb5_checksum — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cksumtype.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cksumtype.html new file mode 100644 index 00000000..8fa5a316 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cksumtype.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_cksumtype — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_const_pointer.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_const_pointer.html new file mode 100644 index 00000000..9c53bc7c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_const_pointer.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_const_pointer — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_const_principal.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_const_principal.html new file mode 100644 index 00000000..fa0778d0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_const_principal.html @@ -0,0 +1,182 @@ + + + + + + + + + krb5_const_principal — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_context.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_context.html new file mode 100644 index 00000000..888b289d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_context.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_context — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cred.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cred.html new file mode 100644 index 00000000..7971ac68 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cred.html @@ -0,0 +1,179 @@ + + + + + + + + + krb5_cred — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cred_enc_part.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cred_enc_part.html new file mode 100644 index 00000000..eaa49890 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cred_enc_part.html @@ -0,0 +1,196 @@ + + + + + + + + + krb5_cred_enc_part — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cred_enc_part

+
+
+type krb5_cred_enc_part
+
+ +

Cleartext credentials information.

+
+

Declaration

+

typedef struct _krb5_cred_enc_part krb5_cred_enc_part

+
+
+

Members

+
+
+krb5_magic krb5_cred_enc_part.magic
+
+ +
+
+krb5_int32 krb5_cred_enc_part.nonce
+

Nonce (optional)

+
+ +
+
+krb5_timestamp krb5_cred_enc_part.timestamp
+

Generation time, seconds portion.

+
+ +
+
+krb5_int32 krb5_cred_enc_part.usec
+

Generation time, microseconds portion.

+
+ +
+
+krb5_address *krb5_cred_enc_part.s_address
+

Sender address (optional)

+
+ +
+
+krb5_address *krb5_cred_enc_part.r_address
+

Recipient address (optional)

+
+ +
+
+krb5_cred_info **krb5_cred_enc_part.ticket_info
+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cred_info.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cred_info.html new file mode 100644 index 00000000..a97bbe15 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cred_info.html @@ -0,0 +1,197 @@ + + + + + + + + + krb5_cred_info — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_cred_info

+
+
+type krb5_cred_info
+
+ +

Credentials information inserted into EncKrbCredPart .

+
+

Declaration

+

typedef struct _krb5_cred_info krb5_cred_info

+
+
+

Members

+
+
+krb5_magic krb5_cred_info.magic
+
+ +
+
+krb5_keyblock *krb5_cred_info.session
+

Session key used to encrypt ticket.

+
+ +
+
+krb5_principal krb5_cred_info.client
+

Client principal and realm.

+
+ +
+
+krb5_principal krb5_cred_info.server
+

Server principal and realm.

+
+ +
+
+krb5_flags krb5_cred_info.flags
+

Ticket flags.

+
+ +
+
+krb5_ticket_times krb5_cred_info.times
+

Auth, start, end, renew_till.

+
+ +
+
+krb5_address **krb5_cred_info.caddrs
+

Array of pointers to addrs (optional)

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_creds.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_creds.html new file mode 100644 index 00000000..fc4068e0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_creds.html @@ -0,0 +1,221 @@ + + + + + + + + + krb5_creds — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_creds

+
+
+type krb5_creds
+
+ +

Credentials structure including ticket, session key, and lifetime info.

+
+

Declaration

+

typedef struct _krb5_creds krb5_creds

+
+
+

Members

+
+
+krb5_magic krb5_creds.magic
+
+ +
+
+krb5_principal krb5_creds.client
+

client’s principal identifier

+
+ +
+
+krb5_principal krb5_creds.server
+

server’s principal identifier

+
+ +
+
+krb5_keyblock krb5_creds.keyblock
+

session encryption key info

+
+ +
+
+krb5_ticket_times krb5_creds.times
+

lifetime info

+
+ +
+
+krb5_boolean krb5_creds.is_skey
+

true if ticket is encrypted in another ticket’s skey

+
+ +
+
+krb5_flags krb5_creds.ticket_flags
+

flags in ticket

+
+ +
+
+krb5_address **krb5_creds.addresses
+

addrs in ticket

+
+ +
+
+krb5_data krb5_creds.ticket
+

ticket string itself

+
+ +
+
+krb5_data krb5_creds.second_ticket
+

second ticket, if related to ticket (via DUPLICATE-SKEY or ENC-TKT-IN-SKEY)

+
+ +
+
+krb5_authdata **krb5_creds.authdata
+

authorization data

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_crypto_iov.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_crypto_iov.html new file mode 100644 index 00000000..49488104 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_crypto_iov.html @@ -0,0 +1,168 @@ + + + + + + + + + krb5_crypto_iov — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_crypto_iov

+
+
+type krb5_crypto_iov
+
+ +

Structure to describe a region of text to be encrypted or decrypted.

+

The flags member describes the type of the iov. The data member points to the memory that will be manipulated. All iov APIs take a pointer to the first element of an array of krb5_crypto_iov’s along with the size of that array. Buffer contents are manipulated in-place; data is overwritten. Callers must allocate the right number of krb5_crypto_iov structures before calling into an iov API.

+
+

Declaration

+

typedef struct _krb5_crypto_iov krb5_crypto_iov

+
+
+

Members

+
+
+krb5_cryptotype krb5_crypto_iov.flags
+

iov type (see KRB5_CRYPTO_TYPE macros)

+
+ +
+
+krb5_data krb5_crypto_iov.data
+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cryptotype.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cryptotype.html new file mode 100644 index 00000000..f985b312 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_cryptotype.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_cryptotype — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_data.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_data.html new file mode 100644 index 00000000..d1502f2c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_data.html @@ -0,0 +1,170 @@ + + + + + + + + + krb5_data — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_deltat.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_deltat.html new file mode 100644 index 00000000..29f739e6 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_deltat.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_deltat — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_enc_data.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_enc_data.html new file mode 100644 index 00000000..94dd49d4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_enc_data.html @@ -0,0 +1,175 @@ + + + + + + + + + krb5_enc_data — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_enc_kdc_rep_part.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_enc_kdc_rep_part.html new file mode 100644 index 00000000..22f821c5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_enc_kdc_rep_part.html @@ -0,0 +1,222 @@ + + + + + + + + + krb5_enc_kdc_rep_part — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_enc_kdc_rep_part

+
+
+type krb5_enc_kdc_rep_part
+
+ +

C representation of EncKDCRepPart protocol message.

+

This is the cleartext message that is encrypted and inserted in KDC-REP .

+
+

Declaration

+

typedef struct _krb5_enc_kdc_rep_part krb5_enc_kdc_rep_part

+
+
+

Members

+
+
+krb5_magic krb5_enc_kdc_rep_part.magic
+
+ +
+
+krb5_msgtype krb5_enc_kdc_rep_part.msg_type
+

krb5 message type

+
+ +
+
+krb5_keyblock *krb5_enc_kdc_rep_part.session
+

Session key.

+
+ +
+
+krb5_last_req_entry **krb5_enc_kdc_rep_part.last_req
+

Array of pointers to entries.

+
+ +
+
+krb5_int32 krb5_enc_kdc_rep_part.nonce
+

Nonce from request.

+
+ +
+
+krb5_timestamp krb5_enc_kdc_rep_part.key_exp
+

Expiration date.

+
+ +
+
+krb5_flags krb5_enc_kdc_rep_part.flags
+

Ticket flags.

+
+ +
+
+krb5_ticket_times krb5_enc_kdc_rep_part.times
+

Lifetime info.

+
+ +
+
+krb5_principal krb5_enc_kdc_rep_part.server
+

Server’s principal identifier.

+
+ +
+
+krb5_address **krb5_enc_kdc_rep_part.caddrs
+

Array of ptrs to addrs, optional.

+
+ +
+
+krb5_pa_data **krb5_enc_kdc_rep_part.enc_padata
+

Encrypted preauthentication data.

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_enc_tkt_part.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_enc_tkt_part.html new file mode 100644 index 00000000..407dbe92 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_enc_tkt_part.html @@ -0,0 +1,203 @@ + + + + + + + + + krb5_enc_tkt_part — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_enc_tkt_part

+
+
+type krb5_enc_tkt_part
+
+ +

Encrypted part of ticket.

+
+

Declaration

+

typedef struct _krb5_enc_tkt_part krb5_enc_tkt_part

+
+
+

Members

+
+
+krb5_magic krb5_enc_tkt_part.magic
+
+ +
+
+krb5_flags krb5_enc_tkt_part.flags
+

flags

+
+ +
+
+krb5_keyblock *krb5_enc_tkt_part.session
+

session key: includes enctype

+
+ +
+
+krb5_principal krb5_enc_tkt_part.client
+

client name/realm

+
+ +
+
+krb5_transited krb5_enc_tkt_part.transited
+

list of transited realms

+
+ +
+
+krb5_ticket_times krb5_enc_tkt_part.times
+

auth, start, end, renew_till

+
+ +
+
+krb5_address **krb5_enc_tkt_part.caddrs
+

array of ptrs to addresses

+
+ +
+
+krb5_authdata **krb5_enc_tkt_part.authorization_data
+

auth data

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_encrypt_block.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_encrypt_block.html new file mode 100644 index 00000000..3e0ce11b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_encrypt_block.html @@ -0,0 +1,170 @@ + + + + + + + + + krb5_encrypt_block — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_enctype.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_enctype.html new file mode 100644 index 00000000..918ec935 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_enctype.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_enctype — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_error.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_error.html new file mode 100644 index 00000000..5210c84c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_error.html @@ -0,0 +1,215 @@ + + + + + + + + + krb5_error — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_error

+
+
+type krb5_error
+
+ +

Error message structure.

+
+

Declaration

+

typedef struct _krb5_error krb5_error

+
+
+

Members

+
+
+krb5_magic krb5_error.magic
+
+ +
+
+krb5_timestamp krb5_error.ctime
+

Client sec portion; optional.

+
+ +
+
+krb5_int32 krb5_error.cusec
+

Client usec portion; optional.

+
+ +
+
+krb5_int32 krb5_error.susec
+

Server usec portion.

+
+ +
+
+krb5_timestamp krb5_error.stime
+

Server sec portion.

+
+ +
+
+krb5_ui_4 krb5_error.error
+

Error code (protocol error #’s)

+
+ +
+
+krb5_principal krb5_error.client
+

Client principal and realm.

+
+ +
+
+krb5_principal krb5_error.server
+

Server principal and realm.

+
+ +
+
+krb5_data krb5_error.text
+

Descriptive text.

+
+ +
+
+krb5_data krb5_error.e_data
+

Additional error-describing data.

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_error_code.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_error_code.html new file mode 100644 index 00000000..e4208b21 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_error_code.html @@ -0,0 +1,153 @@ + + + + + + + + + krb5_error_code — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_error_code

+
+
+type krb5_error_code
+
+ +

Used to convey an operation status.

+

The value 0 indicates success; any other values are com_err codes. Use krb5_get_error_message() to obtain a string describing the error.

+
+

Declaration

+

typedef krb5_int32 krb5_error_code

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_expire_callback_func.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_expire_callback_func.html new file mode 100644 index 00000000..b0c5bd00 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_expire_callback_func.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_expire_callback_func — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_expire_callback_func

+
+
+type krb5_expire_callback_func
+
+ +
+

Declaration

+

typedef void( * krb5_expire_callback_func) (krb5_context context, void *data, krb5_timestamp password_expiration, krb5_timestamp account_expiration, krb5_boolean is_last_req)

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_flags.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_flags.html new file mode 100644 index 00000000..866bac03 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_flags.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_flags — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_get_init_creds_opt.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_get_init_creds_opt.html new file mode 100644 index 00000000..d1fc0b89 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_get_init_creds_opt.html @@ -0,0 +1,211 @@ + + + + + + + + + krb5_get_init_creds_opt — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_get_init_creds_opt

+
+
+type krb5_get_init_creds_opt
+
+ +

Store options for _krb5_get_init_creds .

+
+

Declaration

+

typedef struct _krb5_get_init_creds_opt krb5_get_init_creds_opt

+
+
+

Members

+
+
+krb5_flags krb5_get_init_creds_opt.flags
+
+ +
+
+krb5_deltat krb5_get_init_creds_opt.tkt_life
+
+ +
+
+krb5_deltat krb5_get_init_creds_opt.renew_life
+
+ +
+
+int krb5_get_init_creds_opt.forwardable
+
+ +
+
+int krb5_get_init_creds_opt.proxiable
+
+ +
+
+krb5_enctype *krb5_get_init_creds_opt.etype_list
+
+ +
+
+int krb5_get_init_creds_opt.etype_list_length
+
+ +
+
+krb5_address **krb5_get_init_creds_opt.address_list
+
+ +
+
+krb5_preauthtype *krb5_get_init_creds_opt.preauth_list
+
+ +
+
+int krb5_get_init_creds_opt.preauth_list_length
+
+ +
+
+krb5_data *krb5_get_init_creds_opt.salt
+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_gic_opt_pa_data.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_gic_opt_pa_data.html new file mode 100644 index 00000000..af32551e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_gic_opt_pa_data.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_gic_opt_pa_data — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_init_creds_context.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_init_creds_context.html new file mode 100644 index 00000000..19258a09 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_init_creds_context.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_init_creds_context — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_int16.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_int16.html new file mode 100644 index 00000000..8a1f56d5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_int16.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_int16 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_int32.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_int32.html new file mode 100644 index 00000000..04bf44ce --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_int32.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_int32 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_kdc_rep.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_kdc_rep.html new file mode 100644 index 00000000..4b8d42a3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_kdc_rep.html @@ -0,0 +1,197 @@ + + + + + + + + + krb5_kdc_rep — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kdc_rep

+
+
+type krb5_kdc_rep
+
+ +

Representation of the KDC-REP protocol message.

+
+

Declaration

+

typedef struct _krb5_kdc_rep krb5_kdc_rep

+
+
+

Members

+
+
+krb5_magic krb5_kdc_rep.magic
+
+ +
+
+krb5_msgtype krb5_kdc_rep.msg_type
+

KRB5_AS_REP or KRB5_KDC_REP.

+
+ +
+
+krb5_pa_data **krb5_kdc_rep.padata
+

Preauthentication data from KDC.

+
+ +
+
+krb5_principal krb5_kdc_rep.client
+

Client principal and realm.

+
+ +
+
+krb5_ticket *krb5_kdc_rep.ticket
+

Ticket.

+
+ +
+
+krb5_enc_data krb5_kdc_rep.enc_part
+

Encrypted part of reply.

+
+ +
+
+krb5_enc_kdc_rep_part *krb5_kdc_rep.enc_part2
+

Unencrypted version, if available.

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_kdc_req.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_kdc_req.html new file mode 100644 index 00000000..9c66ff83 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_kdc_req.html @@ -0,0 +1,251 @@ + + + + + + + + + krb5_kdc_req — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_kdc_req

+
+
+type krb5_kdc_req
+
+ +

C representation of KDC-REQ protocol message, including KDC-REQ-BODY.

+
+

Declaration

+

typedef struct _krb5_kdc_req krb5_kdc_req

+
+
+

Members

+
+
+krb5_magic krb5_kdc_req.magic
+
+ +
+
+krb5_msgtype krb5_kdc_req.msg_type
+

KRB5_AS_REQ or KRB5_TGS_REQ.

+
+ +
+
+krb5_pa_data **krb5_kdc_req.padata
+

Preauthentication data.

+
+ +
+
+krb5_flags krb5_kdc_req.kdc_options
+

Requested options.

+
+ +
+
+krb5_principal krb5_kdc_req.client
+

Client principal and realm.

+
+ +
+
+krb5_principal krb5_kdc_req.server
+

Server principal and realm.

+
+ +
+
+krb5_timestamp krb5_kdc_req.from
+

Requested start time.

+
+ +
+
+krb5_timestamp krb5_kdc_req.till
+

Requested end time.

+
+ +
+
+krb5_timestamp krb5_kdc_req.rtime
+

Requested renewable end time.

+
+ +
+
+krb5_int32 krb5_kdc_req.nonce
+

Nonce to match request and response.

+
+ +
+
+int krb5_kdc_req.nktypes
+

Number of enctypes.

+
+ +
+
+krb5_enctype *krb5_kdc_req.ktype
+

Requested enctypes.

+
+ +
+
+krb5_address **krb5_kdc_req.addresses
+

Requested addresses (optional)

+
+ +
+
+krb5_enc_data krb5_kdc_req.authorization_data
+

Encrypted authz data (optional)

+
+ +
+
+krb5_authdata **krb5_kdc_req.unenc_authdata
+

Unencrypted authz data.

+
+ +
+
+krb5_ticket **krb5_kdc_req.second_ticket
+

Second ticket array (optional)

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_key.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_key.html new file mode 100644 index 00000000..00522596 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_key.html @@ -0,0 +1,153 @@ + + + + + + + + + krb5_key — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_key

+
+
+type krb5_key
+
+ +

Opaque identifier for a key.

+

Use with the krb5_k APIs for better performance for repeated operations with the same key and usage. Key identifiers must not be used simultaneously within multiple threads, as they may contain mutable internal state and are not mutex-protected.

+
+

Declaration

+

typedef struct krb5_key_st* krb5_key

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_keyblock.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_keyblock.html new file mode 100644 index 00000000..794bc5c3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_keyblock.html @@ -0,0 +1,176 @@ + + + + + + + + + krb5_keyblock — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_keytab.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_keytab.html new file mode 100644 index 00000000..7c677bde --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_keytab.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_keytab — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_keytab_entry.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_keytab_entry.html new file mode 100644 index 00000000..dfe62e01 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_keytab_entry.html @@ -0,0 +1,185 @@ + + + + + + + + + krb5_keytab_entry — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_keytab_entry

+
+
+type krb5_keytab_entry
+
+ +

A key table entry.

+
+

Declaration

+

typedef struct krb5_keytab_entry_st krb5_keytab_entry

+
+
+

Members

+
+
+krb5_magic krb5_keytab_entry.magic
+
+ +
+
+krb5_principal krb5_keytab_entry.principal
+

Principal of this key.

+
+ +
+
+krb5_timestamp krb5_keytab_entry.timestamp
+

Time entry written to keytable.

+
+ +
+
+krb5_kvno krb5_keytab_entry.vno
+

Key version number.

+
+ +
+
+krb5_keyblock krb5_keytab_entry.key
+

The secret key.

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_keyusage.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_keyusage.html new file mode 100644 index 00000000..e67cdeaf --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_keyusage.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_keyusage — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_kt_cursor.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_kt_cursor.html new file mode 100644 index 00000000..e104a8ff --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_kt_cursor.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_kt_cursor — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_kvno.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_kvno.html new file mode 100644 index 00000000..6fbdbbba --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_kvno.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_kvno — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_last_req_entry.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_last_req_entry.html new file mode 100644 index 00000000..d3d35412 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_last_req_entry.html @@ -0,0 +1,173 @@ + + + + + + + + + krb5_last_req_entry — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_magic.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_magic.html new file mode 100644 index 00000000..67dc66b8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_magic.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_magic — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_mk_req_checksum_func.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_mk_req_checksum_func.html new file mode 100644 index 00000000..89a5e6d3 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_mk_req_checksum_func.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_mk_req_checksum_func — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_mk_req_checksum_func

+
+
+type krb5_mk_req_checksum_func
+
+ +

Type of function used as a callback to generate checksum data for mk_req.

+
+

Declaration

+

typedef krb5_error_code( * krb5_mk_req_checksum_func) (krb5_context, krb5_auth_context, void *, krb5_data **)

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_msgtype.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_msgtype.html new file mode 100644 index 00000000..1e9a840e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_msgtype.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_msgtype — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_octet.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_octet.html new file mode 100644 index 00000000..295e7db1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_octet.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_octet — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_data.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_data.html new file mode 100644 index 00000000..a79a22a5 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_data.html @@ -0,0 +1,179 @@ + + + + + + + + + krb5_pa_data — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_pa_data

+
+
+type krb5_pa_data
+
+ +

Pre-authentication data.

+
+

Declaration

+

typedef struct _krb5_pa_data krb5_pa_data

+
+
+

Members

+
+
+krb5_magic krb5_pa_data.magic
+
+ +
+
+krb5_preauthtype krb5_pa_data.pa_type
+

Preauthentication data type.

+
+ +
+
+unsigned int krb5_pa_data.length
+

Length of data.

+
+ +
+
+krb5_octet *krb5_pa_data.contents
+

Data.

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_pac_req.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_pac_req.html new file mode 100644 index 00000000..c527b344 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_pac_req.html @@ -0,0 +1,161 @@ + + + + + + + + + krb5_pa_pac_req — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_server_referral_data.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_server_referral_data.html new file mode 100644 index 00000000..aa7f2d81 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_server_referral_data.html @@ -0,0 +1,180 @@ + + + + + + + + + krb5_pa_server_referral_data — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_svr_referral_data.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_svr_referral_data.html new file mode 100644 index 00000000..37e22bdc --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pa_svr_referral_data.html @@ -0,0 +1,161 @@ + + + + + + + + + krb5_pa_svr_referral_data — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pac.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pac.html new file mode 100644 index 00000000..a17a0861 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pac.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_pac — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pointer.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pointer.html new file mode 100644 index 00000000..5e0f69af --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pointer.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_pointer — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_post_recv_fn.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_post_recv_fn.html new file mode 100644 index 00000000..6d869a24 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_post_recv_fn.html @@ -0,0 +1,154 @@ + + + + + + + + + krb5_post_recv_fn — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_post_recv_fn

+
+
+type krb5_post_recv_fn
+
+ +

Hook function for inspecting or overriding KDC replies.

+

If code is non-zero, KDC communication failed and reply should be ignored. The hook function may return code or a different error code, or may synthesize a reply by setting new_reply_out and return successfully. +The hook function should use krb5_copy_data() to construct the value for new_reply_out , to ensure that it can be freed correctly by the library.

+
+

Declaration

+

typedef krb5_error_code( * krb5_post_recv_fn) (krb5_context context, void *data, krb5_error_code code, const krb5_data *realm, const krb5_data *message, const krb5_data *reply, krb5_data **new_reply_out)

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pre_send_fn.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pre_send_fn.html new file mode 100644 index 00000000..b1169b03 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pre_send_fn.html @@ -0,0 +1,156 @@ + + + + + + + + + krb5_pre_send_fn — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_pre_send_fn

+
+
+type krb5_pre_send_fn
+
+ +

Hook function for inspecting or modifying messages sent to KDCs.

+

If the hook function sets new_reply_out , message will not be sent to the KDC, and the given reply will used instead. +If the hook function sets new_message_out , the given message will be sent to the KDC in place of message . +If the hook function returns successfully without setting either output, message will be sent to the KDC normally. +The hook function should use krb5_copy_data() to construct the value for new_message_out or reply_out , to ensure that it can be freed correctly by the library.

+
+

Declaration

+

typedef krb5_error_code( * krb5_pre_send_fn) (krb5_context context, void *data, const krb5_data *realm, const krb5_data *message, krb5_data **new_message_out, krb5_data **new_reply_out)

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_preauthtype.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_preauthtype.html new file mode 100644 index 00000000..2f60eae8 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_preauthtype.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_preauthtype — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_principal.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_principal.html new file mode 100644 index 00000000..686e1594 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_principal.html @@ -0,0 +1,181 @@ + + + + + + + + + krb5_principal — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_principal_data.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_principal_data.html new file mode 100644 index 00000000..26bf9e45 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_principal_data.html @@ -0,0 +1,181 @@ + + + + + + + + + krb5_principal_data — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_prompt.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_prompt.html new file mode 100644 index 00000000..0161b756 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_prompt.html @@ -0,0 +1,175 @@ + + + + + + + + + krb5_prompt — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_prompt

+
+
+type krb5_prompt
+
+ +

Text for prompt used in prompter callback function.

+
+

Declaration

+

typedef struct _krb5_prompt krb5_prompt

+
+
+

Members

+
+
+char *krb5_prompt.prompt
+

The prompt to show to the user.

+
+ +
+
+int krb5_prompt.hidden
+

Boolean; informative prompt or hidden (e.g. +PIN)

+
+ +
+
+krb5_data *krb5_prompt.reply
+

Must be allocated before call to prompt routine.

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_prompt_type.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_prompt_type.html new file mode 100644 index 00000000..959791e4 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_prompt_type.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_prompt_type — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_prompter_fct.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_prompter_fct.html new file mode 100644 index 00000000..2b37cc81 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_prompter_fct.html @@ -0,0 +1,152 @@ + + + + + + + + + krb5_prompter_fct — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_prompter_fct

+
+
+type krb5_prompter_fct
+
+ +

Pointer to a prompter callback function.

+
+

Declaration

+

typedef krb5_error_code( * krb5_prompter_fct) (krb5_context context, void *data, const char *name, const char *banner, int num_prompts, krb5_prompt prompts[])

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pwd_data.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pwd_data.html new file mode 100644 index 00000000..ac55ef76 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_pwd_data.html @@ -0,0 +1,170 @@ + + + + + + + + + krb5_pwd_data — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_rcache.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_rcache.html new file mode 100644 index 00000000..46104344 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_rcache.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_rcache — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_replay_data.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_replay_data.html new file mode 100644 index 00000000..05316c4a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_replay_data.html @@ -0,0 +1,175 @@ + + + + + + + + + krb5_replay_data — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_replay_data

+
+
+type krb5_replay_data
+
+ +

Replay data.

+

Sequence number and timestamp information output by krb5_rd_priv() and krb5_rd_safe().

+
+

Declaration

+

typedef struct krb5_replay_data krb5_replay_data

+
+
+

Members

+
+
+krb5_timestamp krb5_replay_data.timestamp
+

Timestamp, seconds portion.

+
+ +
+
+krb5_int32 krb5_replay_data.usec
+

Timestamp, microseconds portion.

+
+ +
+
+krb5_ui_4 krb5_replay_data.seq
+

Sequence number.

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_context.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_context.html new file mode 100644 index 00000000..3c33214d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_context.html @@ -0,0 +1,153 @@ + + + + + + + + + krb5_responder_context — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_responder_context

+
+
+type krb5_responder_context
+
+ +

A container for a set of preauthentication questions and answers.

+

A responder context is supplied by the krb5 authentication system to a krb5_responder_fn callback. It contains a list of questions and can receive answers. Questions contained in a responder context can be listed using krb5_responder_list_questions(), retrieved using krb5_responder_get_challenge(), or answered using krb5_responder_set_answer(). The form of a question’s challenge and answer depend on the question name.

+
+

Declaration

+

typedef struct krb5_responder_context_st* krb5_responder_context

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_fn.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_fn.html new file mode 100644 index 00000000..e285563b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_fn.html @@ -0,0 +1,153 @@ + + + + + + + + + krb5_responder_fn — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_responder_fn

+
+
+type krb5_responder_fn
+
+ +

Responder function for an initial credential exchange.

+

If a required question is unanswered, the prompter may be called.

+
+

Declaration

+

typedef krb5_error_code( * krb5_responder_fn) (krb5_context ctx, void *data, krb5_responder_context rctx)

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_otp_challenge.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_otp_challenge.html new file mode 100644 index 00000000..df3f3346 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_otp_challenge.html @@ -0,0 +1,165 @@ + + + + + + + + + krb5_responder_otp_challenge — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_otp_tokeninfo.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_otp_tokeninfo.html new file mode 100644 index 00000000..6d4517de --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_otp_tokeninfo.html @@ -0,0 +1,190 @@ + + + + + + + + + krb5_responder_otp_tokeninfo — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_pkinit_challenge.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_pkinit_challenge.html new file mode 100644 index 00000000..9dba192a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_pkinit_challenge.html @@ -0,0 +1,160 @@ + + + + + + + + + krb5_responder_pkinit_challenge — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_pkinit_identity.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_pkinit_identity.html new file mode 100644 index 00000000..2124232f --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_responder_pkinit_identity.html @@ -0,0 +1,165 @@ + + + + + + + + + krb5_responder_pkinit_identity — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_response.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_response.html new file mode 100644 index 00000000..a1b4a297 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_response.html @@ -0,0 +1,180 @@ + + + + + + + + + krb5_response — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ticket.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ticket.html new file mode 100644 index 00000000..f0e8c51d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ticket.html @@ -0,0 +1,180 @@ + + + + + + + + + krb5_ticket — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_ticket

+
+
+type krb5_ticket
+
+ +

Ticket structure.

+

The C representation of the ticket message, with a pointer to the C representation of the encrypted part.

+
+

Declaration

+

typedef struct _krb5_ticket krb5_ticket

+
+
+

Members

+
+
+krb5_magic krb5_ticket.magic
+
+ +
+
+krb5_principal krb5_ticket.server
+

server name/realm

+
+ +
+
+krb5_enc_data krb5_ticket.enc_part
+

encryption type, kvno, encrypted encoding

+
+ +
+
+krb5_enc_tkt_part *krb5_ticket.enc_part2
+

ptr to decrypted version, if available

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ticket_times.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ticket_times.html new file mode 100644 index 00000000..47f1592b --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ticket_times.html @@ -0,0 +1,180 @@ + + + + + + + + + krb5_ticket_times — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_ticket_times

+
+
+type krb5_ticket_times
+
+ +

Ticket start time, end time, and renewal duration.

+
+

Declaration

+

typedef struct _krb5_ticket_times krb5_ticket_times

+
+
+

Members

+
+
+krb5_timestamp krb5_ticket_times.authtime
+

Time at which KDC issued the initial ticket that corresponds to this ticket.

+
+ +
+
+krb5_timestamp krb5_ticket_times.starttime
+

optional in ticket, if not present, use authtime

+
+ +
+
+krb5_timestamp krb5_ticket_times.endtime
+

Ticket expiration time.

+
+ +
+
+krb5_timestamp krb5_ticket_times.renew_till
+

Latest time at which renewal of ticket can be valid.

+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_timestamp.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_timestamp.html new file mode 100644 index 00000000..c685c841 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_timestamp.html @@ -0,0 +1,153 @@ + + + + + + + + + krb5_timestamp — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_timestamp

+
+
+type krb5_timestamp
+
+ +

Represents a timestamp in seconds since the POSIX epoch.

+

This legacy type is used frequently in the ABI, but cannot represent timestamps after 2038 as a positive number. Code which uses this type should cast values of it to uint32_t so that negative values are treated as timestamps between 2038 and 2106 on platforms with 64-bit time_t.

+
+

Declaration

+

typedef krb5_int32 krb5_timestamp

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_tkt_authent.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_tkt_authent.html new file mode 100644 index 00000000..0994a78d --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_tkt_authent.html @@ -0,0 +1,176 @@ + + + + + + + + + krb5_tkt_authent — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_tkt_creds_context.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_tkt_creds_context.html new file mode 100644 index 00000000..d2a79447 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_tkt_creds_context.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_tkt_creds_context — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_trace_callback.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_trace_callback.html new file mode 100644 index 00000000..6c2bb4e7 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_trace_callback.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_trace_callback — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_trace_info.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_trace_info.html new file mode 100644 index 00000000..94b0e15e --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_trace_info.html @@ -0,0 +1,162 @@ + + + + + + + + + krb5_trace_info — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5_trace_info

+
+
+type krb5_trace_info
+
+ +

A wrapper for passing information to a krb5_trace_callback .

+

Currently, it only contains the formatted message as determined the the format string and arguments of the tracing macro, but it may be extended to contain more fields in the future.

+
+

Declaration

+

typedef struct _krb5_trace_info krb5_trace_info

+
+
+

Members

+
+
+const char *krb5_trace_info.message
+
+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_transited.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_transited.html new file mode 100644 index 00000000..0fadf97a --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_transited.html @@ -0,0 +1,173 @@ + + + + + + + + + krb5_transited — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_typed_data.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_typed_data.html new file mode 100644 index 00000000..17519a0c --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_typed_data.html @@ -0,0 +1,175 @@ + + + + + + + + + krb5_typed_data — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ui_2.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ui_2.html new file mode 100644 index 00000000..9306af05 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ui_2.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_ui_2 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ui_4.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ui_4.html new file mode 100644 index 00000000..f9086331 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_ui_4.html @@ -0,0 +1,151 @@ + + + + + + + + + krb5_ui_4 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/krb5_verify_init_creds_opt.html b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_verify_init_creds_opt.html new file mode 100644 index 00000000..464cf4e0 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/krb5_verify_init_creds_opt.html @@ -0,0 +1,166 @@ + + + + + + + + + krb5_verify_init_creds_opt — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/refs/types/passwd_phrase_element.html b/krb5-1.21.3/doc/html/appdev/refs/types/passwd_phrase_element.html new file mode 100644 index 00000000..392020e1 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/refs/types/passwd_phrase_element.html @@ -0,0 +1,170 @@ + + + + + + + + + passwd_phrase_element — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/appdev/y2038.html b/krb5-1.21.3/doc/html/appdev/y2038.html new file mode 100644 index 00000000..f0be8657 --- /dev/null +++ b/krb5-1.21.3/doc/html/appdev/y2038.html @@ -0,0 +1,157 @@ + + + + + + + + + Year 2038 considerations for uses of krb5_timestamp — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Year 2038 considerations for uses of krb5_timestamp

+

POSIX time values, which measure the number of seconds since January 1 +1970, will exceed the maximum value representable in a signed 32-bit +integer in January 2038. This documentation describes considerations +for consumers of the MIT krb5 libraries.

+

Applications or libraries which use libkrb5 and consume the timestamps +included in credentials or other structures make use of the +krb5_timestamp type. For historical reasons, krb5_timestamp +is a signed 32-bit integer, even on platforms where a larger type is +natively used to represent time values. To behave properly for time +values after January 2038, calling code should cast krb5_timestamp +values to uint32_t, and then to time_t:

+
(time_t)(uint32_t)timestamp
+
+
+

Used in this way, krb5_timestamp values can represent time values up +until February 2106, provided that the platform uses a 64-bit or +larger time_t type. This usage will also remain safe if a later +version of MIT krb5 changes krb5_timestamp to an unsigned 32-bit +integer.

+

The GSSAPI only uses representations of time intervals, not absolute +times. Callers of the GSSAPI should require no changes to behave +correctly after January 2038, provided that they use MIT krb5 release +1.16 or later.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/basic/ccache_def.html b/krb5-1.21.3/doc/html/basic/ccache_def.html new file mode 100644 index 00000000..9728a8b5 --- /dev/null +++ b/krb5-1.21.3/doc/html/basic/ccache_def.html @@ -0,0 +1,279 @@ + + + + + + + + + Credential cache — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Credential cache

+

A credential cache (or “ccache”) holds Kerberos credentials while they +remain valid and, generally, while the user’s session lasts, so that +authenticating to a service multiple times (e.g., connecting to a web +or mail server more than once) doesn’t require contacting the KDC +every time.

+

A credential cache usually contains one initial ticket which is +obtained using a password or another form of identity verification. +If this ticket is a ticket-granting ticket, it can be used to obtain +additional credentials without the password. Because the credential +cache does not store the password, less long-term damage can be done +to the user’s account if the machine is compromised.

+

A credentials cache stores a default client principal name, set when +the cache is created. This is the name shown at the top of the +klist -A output.

+

Each normal cache entry includes a service principal name, a client +principal name (which, in some ccache types, need not be the same as +the default), lifetime information, and flags, along with the +credential itself. There are also other entries, indicated by special +names, that store additional information.

+
+

ccache types

+

The credential cache interface, like the keytab and +replay cache interfaces, uses TYPE:value strings to +indicate the type of credential cache and any associated cache naming +data to use.

+

There are several kinds of credentials cache supported in the MIT +Kerberos library. Not all are supported on every platform. In most +cases, it should be correct to use the default type built into the +library.

+
    +
  1. API is only implemented on Windows. It communicates with a +server process that holds the credentials in memory for the user, +rather than writing them to disk.

  2. +
  3. DIR points to the storage location of the collection of the +credential caches in FILE: format. It is most useful when dealing +with multiple Kerberos realms and KDCs. For release 1.10 the +directory must already exist. In post-1.10 releases the +requirement is for parent directory to exist and the current +process must have permissions to create the directory if it does +not exist. See Collections of caches for details. New in release 1.10. +The following residual forms are supported:

    +
      +
    • DIR:dirname

    • +
    • DIR::dirpath/filename - a single cache within the directory

    • +
    +

    Switching to a ccache of the latter type causes it to become the +primary for the directory.

    +
  4. +
  5. FILE caches are the simplest and most portable. A simple flat +file format is used to store one credential after another. This is +the default ccache type if no type is specified in a ccache name.

  6. +
  7. KCM caches work by contacting a daemon process called kcm +to perform cache operations. If the cache name is just KCM:, +the default cache as determined by the KCM daemon will be used. +Newly created caches must generally be named KCM:uid:name, +where uid is the effective user ID of the running process.

    +

    KCM client support is new in release 1.13. A KCM daemon has not +yet been implemented in MIT krb5, but the client will interoperate +with the KCM daemon implemented by Heimdal. macOS 10.7 and higher +provides a KCM daemon as part of the operating system, and the +KCM cache type is used as the default cache on that platform in +a default build.

    +
  8. +
  9. KEYRING is Linux-specific, and uses the kernel keyring support +to store credential data in unswappable kernel memory where only +the current user should be able to access it. The following +residual forms are supported:

    +
      +
    • KEYRING:name

    • +
    • KEYRING:process:name - process keyring

    • +
    • KEYRING:thread:name - thread keyring

    • +
    +

    Starting with release 1.12 the KEYRING type supports collections. +The following new residual forms were added:

    +
      +
    • KEYRING:session:name - session keyring

    • +
    • KEYRING:user:name - user keyring

    • +
    • KEYRING:persistent:uidnumber - persistent per-UID collection. +Unlike the user keyring, this collection survives after the user +logs out, until the cache credentials expire. This type of +ccache requires support from the kernel; otherwise, it will fall +back to the user keyring.

    • +
    +

    See Collections of caches for details.

    +
  10. +
  11. MEMORY caches are for storage of credentials that don’t need to +be made available outside of the current process. For example, a +memory ccache is used by kadmin to store the +administrative ticket used to contact the admin server. Memory +ccaches are faster than file ccaches and are automatically +destroyed when the process exits.

  12. +
  13. MSLSA is a Windows-specific cache type that accesses the +Windows credential store.

  14. +
+
+
+

Collections of caches

+

Some credential cache types can support collections of multiple +caches. One of the caches in the collection is designated as the +primary and will be used when the collection is resolved as a cache. +When a collection-enabled cache type is the default cache for a +process, applications can search the specified collection for a +specific client principal, and GSSAPI applications will automatically +select between the caches in the collection based on criteria such as +the target service realm.

+

Credential cache collections are new in release 1.10, with support +from the DIR and API ccache types. Starting in release 1.12, +collections are also supported by the KEYRING ccache type. +Collections are supported by the KCM ccache type in release 1.13.

+
+

Tool alterations to use cache collection

+
    +
  • kdestroy -A will destroy all caches in the collection.

  • +
  • If the default cache type supports switching, kinit +princname will search the collection for a matching cache and +store credentials there, or will store credentials in a new unique +cache of the default type if no existing cache for the principal +exists. Either way, kinit will switch to the selected cache.

  • +
  • klist -l will list the caches in the collection.

  • +
  • klist -A will show the content of all caches in the +collection.

  • +
  • kswitch -p princname will search the collection for a +matching cache and switch to it.

  • +
  • kswitch -c cachename will switch to a specified cache.

  • +
+
+
+
+

Default ccache name

+

The default credential cache name is determined by the following, in +descending order of priority:

+
    +
  1. The KRB5CCNAME environment variable. For example, +KRB5CCNAME=DIR:/mydir/.

  2. +
  3. The default_ccache_name profile variable in [libdefaults].

  4. +
  5. The hardcoded default, DEFCCNAME.

  6. +
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/basic/date_format.html b/krb5-1.21.3/doc/html/basic/date_format.html new file mode 100644 index 00000000..a32cb472 --- /dev/null +++ b/krb5-1.21.3/doc/html/basic/date_format.html @@ -0,0 +1,331 @@ + + + + + + + + + Supported date and time formats — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Supported date and time formats

+
+

Time duration

+

This format is used to express a time duration in the Kerberos +configuration files and user commands. The allowed formats are:

+
+
+++++ + + + + + + + + + + + + + + + + + + +

Format

Example

Value

h:m[:s]

36:00

36 hours

NdNhNmNs

8h30s

8 hours 30 seconds

N (number of seconds)

3600

1 hour

+
+

Here N denotes a number, d - days, h - hours, m - minutes, +s - seconds.

+
+

Note

+

The time interval should not exceed 2147483647 seconds.

+
+

Examples:

+
Request a ticket valid for one hour, five hours, 30 minutes
+and 10 days respectively:
+
+  kinit -l 3600
+  kinit -l 5:00
+  kinit -l 30m
+  kinit -l "10d 0h 0m 0s"
+
+
+
+
+

getdate time

+

Some of the kadmin and kdb5_util commands take a date-time in a +human-readable format. Some of the acceptable date-time +strings are:

+
+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Format

Example

Date

mm/dd/yy

07/27/12

month dd, yyyy

Jul 27, 2012

yyyy-mm-dd

2012-07-27

Absolute +time

HH:mm[:ss]pp

08:30 PM

hh:mm[:ss]

20:30

Relative +time

N tt

30 sec

Time zone

Z

EST

z

-0400

+
+

(See Abbreviations used in this document.)

+

Examples:

+
Create a principal that expires on the date indicated:
+    addprinc test1 -expire "3/27/12 10:00:07 EST"
+    addprinc test2 -expire "January 23, 2015 10:05pm"
+    addprinc test3 -expire "22:00 GMT"
+Add a principal that will expire in 30 minutes:
+    addprinc test4 -expire "30 minutes"
+
+
+
+
+

Absolute time

+

This rarely used date-time format can be noted in one of the +following ways:

+
+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Format

Example

Value

yyyymmddhhmmss

20141231235900

One minute +before 2015

yyyy.mm.dd.hh.mm.ss

2014.12.31.23.59.00

yymmddhhmmss

141231235900

yy.mm.dd.hh.mm.ss

14.12.31.23.59.00

dd-month-yyyy:hh:mm:ss

31-Dec-2014:23:59:00

hh:mm:ss

20:00:00

8 o’clock in +the evening

hhmmss

200000

+
+

(See Abbreviations used in this document.)

+

Example:

+
Set the default expiration date to July 27, 2012 at 20:30
+default_principal_expiration = 20120727203000
+
+
+
+

Abbreviations used in this document

+
+
month : locale’s month name or its abbreviation;
+
dd : day of month (01-31);
+
HH : hours (00-12);
+
hh : hours (00-23);
+
mm : in time - minutes (00-59); in date - month (01-12);
+
N : number;
+
pp : AM or PM;
+
ss : seconds (00-60);
+
tt : time units (hours, minutes, min, seconds, sec);
+
yyyy : year;
+
yy : last two digits of the year;
+
Z : alphabetic time zone abbreviation;
+
z : numeric time zone;
+
+
+

Note

+
    +
  • If the date specification contains spaces, you may need to +enclose it in double quotes;

  • +
  • All keywords are case-insensitive.

  • +
+
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/basic/index.html b/krb5-1.21.3/doc/html/basic/index.html new file mode 100644 index 00000000..0a84a1d7 --- /dev/null +++ b/krb5-1.21.3/doc/html/basic/index.html @@ -0,0 +1,142 @@ + + + + + + + + + Kerberos V5 concepts — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/basic/keytab_def.html b/krb5-1.21.3/doc/html/basic/keytab_def.html new file mode 100644 index 00000000..e92a57ff --- /dev/null +++ b/krb5-1.21.3/doc/html/basic/keytab_def.html @@ -0,0 +1,182 @@ + + + + + + + + + keytab — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

keytab

+

A keytab (short for “key table”) stores long-term keys for one or more +principals. Keytabs are normally represented by files in a standard +format, although in rare cases they can be represented in other ways. +Keytabs are used most often to allow server applications to accept +authentications from clients, but can also be used to obtain initial +credentials for client applications.

+

Keytabs are named using the format type:value. Usually +type is FILE and value is the absolute pathname of the file. +The other possible value for type is MEMORY, which indicates a +temporary keytab stored in the memory of the current process.

+

A keytab contains one or more entries, where each entry consists of a +timestamp (indicating when the entry was written to the keytab), a +principal name, a key version number, an encryption type, and the +encryption key itself.

+

A keytab can be displayed using the klist command with the +-k option. Keytabs can be created or appended to by extracting +keys from the KDC database using the kadmin ktadd +command. Keytabs can be manipulated using the ktutil and +k5srvutil commands.

+
+

Default keytab

+

The default keytab is used by server applications if the application +does not request a specific keytab. The name of the default keytab is +determined by the following, in decreasing order of preference:

+
    +
  1. The KRB5_KTNAME environment variable.

  2. +
  3. The default_keytab_name profile variable in [libdefaults].

  4. +
  5. The hardcoded default, DEFKTNAME.

  6. +
+
+
+

Default client keytab

+

The default client keytab is used, if it is present and readable, to +automatically obtain initial credentials for GSSAPI client +applications. The principal name of the first entry in the client +keytab is used by default when obtaining initial credentials. The +name of the default client keytab is determined by the following, in +decreasing order of preference:

+
    +
  1. The KRB5_CLIENT_KTNAME environment variable.

  2. +
  3. The default_client_keytab_name profile variable in +[libdefaults].

  4. +
  5. The hardcoded default, DEFCKTNAME.

  6. +
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/basic/rcache_def.html b/krb5-1.21.3/doc/html/basic/rcache_def.html new file mode 100644 index 00000000..3e8d53a4 --- /dev/null +++ b/krb5-1.21.3/doc/html/basic/rcache_def.html @@ -0,0 +1,231 @@ + + + + + + + + + replay cache — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

replay cache

+

A replay cache (or “rcache”) keeps track of all authenticators +recently presented to a service. If a duplicate authentication +request is detected in the replay cache, an error message is sent to +the application program.

+

The replay cache interface, like the credential cache and +keytab interfaces, uses type:residual strings to +indicate the type of replay cache and any associated cache naming +data to use.

+
+

Background information

+

Some Kerberos or GSSAPI services use a simple authentication mechanism +where a message is sent containing an authenticator, which establishes +the encryption key that the client will use for talking to the +service. But nothing about that prevents an eavesdropper from +recording the messages sent by the client, establishing a new +connection, and re-sending or “replaying” the same messages; the +replayed authenticator will establish the same encryption key for the +new session, and the following messages will be decrypted and +processed. The attacker may not know what the messages say, and can’t +generate new messages under the same encryption key, but in some +instances it may be harmful to the user (or helpful to the attacker) +to cause the server to see the same messages again a second time. For +example, if the legitimate client sends “delete first message in +mailbox”, a replay from an attacker may delete another, different +“first” message. (Protocol design to guard against such problems has +been discussed in RFC 4120#section-10.)

+

Even if one protocol uses further protection to verify that the client +side of the connection actually knows the encryption keys (and thus is +presumably a legitimate user), if another service uses the same +service principal name, it may be possible to record an authenticator +used with the first protocol and “replay” it against the second.

+

The replay cache mitigates these attacks somewhat, by keeping track of +authenticators that have been seen until their five-minute window +expires. Different authenticators generated by multiple connections +from the same legitimate client will generally have different +timestamps, and thus will not be considered the same.

+

This mechanism isn’t perfect. If a message is sent to one application +server but a man-in-the-middle attacker can prevent it from actually +arriving at that server, the attacker could then use the authenticator +(once!) against a different service on the same host. This could be a +problem if the message from the client included something more than +authentication in the first message that could be useful to the +attacker (which is uncommon; in most protocols the server has to +indicate a successful authentication before the client sends +additional messages), or if the simple act of presenting the +authenticator triggers some interesting action in the service being +attacked.

+
+
+

Replay cache types

+

Unlike the credential cache and keytab interfaces, replay cache types +are in lowercase. The following types are defined:

+
    +
  1. none disables the replay cache. The residual value is ignored.

  2. +
  3. file2 (new in release 1.18) uses a hash-based format to store +replay records. The file may grow to accommodate hash collisions. +The residual value is the filename.

  4. +
  5. dfl is the default type if no environment variable or +configuration specifies a different type. It stores replay data in +a file2 replay cache with a filename based on the effective uid. +The residual value is ignored.

  6. +
+

For the dfl type, the location of the replay cache file is determined +as follows:

+
    +
  1. The directory is taken from the KRB5RCACHEDIR environment +variable, or the TMPDIR environment variable, or a temporary +directory determined at configuration time such as /var/tmp, in +descending order of preference.

  2. +
  3. The filename is krb5_EUID.rcache2 where EUID is the effective +uid of the process.

  4. +
  5. The file is opened without following symbolic links, and ownership +of the file is verified to match the effective uid.

  6. +
+

On Windows, the directory for the dfl type is the local appdata +directory, unless overridden by the KRB5RCACHEDIR environment +variable. The filename on Windows is krb5.rcache2, and the file +is opened normally.

+
+
+

Default replay cache name

+

The default replay cache name is determined by the following, in +descending order of priority:

+
    +
  1. The KRB5RCACHENAME environment variable (new in release 1.18).

  2. +
  3. The KRB5RCACHETYPE environment variable. If this variable is +set, the residual value is empty.

  4. +
  5. The default_rcache_name profile variable in [libdefaults] +(new in release 1.18).

  6. +
  7. If none of the above are set, the default replay cache name is +dfl:.

  8. +
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/basic/stash_file_def.html b/krb5-1.21.3/doc/html/basic/stash_file_def.html new file mode 100644 index 00000000..b993668f --- /dev/null +++ b/krb5-1.21.3/doc/html/basic/stash_file_def.html @@ -0,0 +1,150 @@ + + + + + + + + + stash file — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

stash file

+

The stash file is a local copy of the master key that resides in +encrypted form on the KDC’s local disk. The stash file is used to +authenticate the KDC to itself automatically before starting the +kadmind and krb5kdc daemons (e.g., as part of the +machine’s boot sequence). The stash file, like the keytab file (see +The keytab file) is a potential point-of-entry for a break-in, and +if compromised, would allow unrestricted access to the Kerberos +database. If you choose to install a stash file, it should be +readable only by root, and should exist only on the KDC’s local disk. +The file should not be part of any backup of the machine, unless +access to the backup data is secured as tightly as access to the +master password itself.

+
+

Note

+

If you choose not to install a stash file, the KDC will prompt you for the master key each time it starts up. +This means that the KDC will not be able to start automatically, such as after a system reboot.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/build/directory_org.html b/krb5-1.21.3/doc/html/build/directory_org.html new file mode 100644 index 00000000..783269a3 --- /dev/null +++ b/krb5-1.21.3/doc/html/build/directory_org.html @@ -0,0 +1,244 @@ + + + + + + + + + Organization of the source directory — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Organization of the source directory

+

Below is a brief overview of the organization of the complete source +directory. More detailed descriptions follow.

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

appl

Kerberos application client and server programs

ccapi

Credential cache services

clients

Kerberos V5 user programs (See User commands)

config

Configure scripts

config-files

Sample Kerberos configuration files

include

include files needed to build the Kerberos system

kadmin

Administrative interface to the Kerberos database: kadmin, kdb5_util, ktutil.

kdc

Kerberos V5 Authentication Service and Key Distribution Center

lib

Libraries for use with/by Kerberos V5

plugins

Kerberos plugins directory

po

Localization infrastructure

prototype

Templates files containing the MIT copyright message and a placeholder for the title and description of the file.

kprop

Utilities for propagating the database to replica KDCs kprop and kpropd

tests

Test suite

util

Various utilities for building/configuring the code, sending bug reports, etc.

windows

Source code for building Kerberos V5 on Windows (see windows/README)

+
+

lib

+

The lib directory contain several subdirectories as well as some +definition and glue files.

+
+
    +
  • The apputils directory contains the code for the generic network +servicing.

  • +
  • The crypto subdirectory contains the Kerberos V5 encryption +library.

  • +
  • The gssapi library contains the Generic Security Services API, +which is a library of commands to be used in secure client-server +communication.

  • +
  • The kadm5 directory contains the libraries for the KADM5 +administration utilities.

  • +
  • The Kerberos 5 database libraries are contained in kdb.

  • +
  • The krb5 directory contains Kerberos 5 API.

  • +
  • The rpc directory contains the API for the Kerberos Remote +Procedure Call protocol.

  • +
+
+
+
+

util

+
+
The util directory contains several utility programs and libraries.
    +
  • the programs used to configure and build the code, such as +autoconf, lndir, kbuild, reconf, and makedepend, are in this +directory.

  • +
  • the profile directory contains most of the functions which parse +the Kerberos configuration files (krb5.conf and kdc.conf).

  • +
  • the Kerberos error table library and utilities (et);

  • +
  • the Sub-system library and utilities (ss);

  • +
  • database utilities (db2);

  • +
  • pseudo-terminal utilities (pty);

  • +
  • bug-reporting program send-pr;

  • +
  • a generic support library support used by several of our other +libraries;

  • +
  • the build infrastructure for building lightweight Kerberos client +(collected-client-lib)

  • +
  • the tool for validating Kerberos configuration files +(confvalidator);

  • +
  • the toolkit for kernel integrators for building krb5 code subsets +(gss-kernel-lib);

  • +
  • source code for building Kerberos V5 on MacOS (mac)

  • +
  • Windows getopt operations (windows)

  • +
+
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/build/doing_build.html b/krb5-1.21.3/doc/html/build/doing_build.html new file mode 100644 index 00000000..4b5b1b64 --- /dev/null +++ b/krb5-1.21.3/doc/html/build/doing_build.html @@ -0,0 +1,270 @@ + + + + + + + + + Doing the build — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Doing the build

+
+

Building within a single tree

+

If you only need to build Kerberos for one platform, using a single +directory tree which contains both the source files and the object +files is the simplest. However, if you need to maintain Kerberos for +a large number of platforms, you will probably want to use separate +build trees for each platform. We recommend that you look at OS +Incompatibilities, for notes that we have on particular operating +systems.

+

If you don’t want separate build trees for each architecture, then use +the following abbreviated procedure:

+
cd /u1/krb5-VERSION/src
+./configure
+make
+
+
+

That’s it!

+
+
+

Building with separate build directories

+

If you wish to keep separate build directories for each platform, you +can do so using the following procedure. (Note, this requires that +your make program support VPATH. GNU’s make will provide this +functionality, for example.) If your make program does not support +this, see the next section.

+

For example, if you wish to store the binaries in tmpbuild build +directory you might use the following procedure:

+
mkdir /u1/tmpbuild
+cd /u1/tmpbuild
+/u1/krb5-VERSION/src/configure
+make
+
+
+
+
+

Building using lndir

+

If you wish to keep separate build directories for each platform, and +you do not have access to a make program which supports VPATH, all is +not lost. You can use the lndir program to create symbolic link trees +in your build directory.

+

For example, if you wish to create a build directory for solaris +binaries you might use the following procedure:

+
mkdir /u1/krb5-VERSION/solaris
+cd /u1/krb5-VERSION/solaris
+/u1/krb5-VERSION/src/util/lndir `pwd`/../src
+./configure
+make
+
+
+

You must give an absolute pathname to lndir because it has a bug that +makes it fail for relative pathnames. Note that this version differs +from the latest version as distributed and installed by the +XConsortium with X11R6. Either version should be acceptable.

+
+
+

Installing the binaries

+

Once you have built Kerberos, you should install the binaries. You can +do this by running:

+
make install
+
+
+

If you want to install the binaries into a destination directory that +is not their final destination, which may be convenient if you want to +build a binary distribution to be deployed on multiple hosts, you may +use:

+
make install DESTDIR=/path/to/destdir
+
+
+

This will install the binaries under DESTDIR/PREFIX, e.g., the user +programs will install into DESTDIR/PREFIX/bin, the libraries into +DESTDIR/PREFIX/lib, etc. DESTDIR must be an absolute path.

+

Some implementations of make allow multiple commands to be run in +parallel, for faster builds. We test our Makefiles in parallel builds +with GNU make only; they may not be compatible with other parallel +build implementations.

+
+
+

Testing the build

+

The Kerberos V5 distribution comes with built-in regression tests. To +run them, simply type the following command while in the top-level +build directory (i.e., the directory where you sent typed make to +start building Kerberos; see Building within a single tree):

+
make check
+
+
+

On some operating systems, you have to run make install before +running make check, or the test suite will pick up installed +versions of Kerberos libraries rather than the newly built ones. You +can install into a prefix that isn’t in the system library search +path, though. Alternatively, you can configure with +--disable-rpath, which renders the build tree less suitable +for installation, but allows testing without interference from +previously installed libraries.

+

There are additional regression tests available, which are not run +by make check. These tests require manual setup and teardown of +support infrastructure which is not easily automated, or require +excessive resources for ordinary use. The procedure for running +the manual tests is documented at +https://k5wiki.kerberos.org/wiki/Manual_Testing.

+
+
+

Cleaning up the build

+
    +
  • Use make clean to remove all files generated by running make +command.

  • +
  • Use make distclean to remove all files generated by running +./configure script. After running make distclean your source +tree (ideally) should look like the raw (just un-tarred) source +tree.

  • +
+
+
+

Using autoconf

+

(If you are not a developer, you can ignore this section.)

+

In the Kerberos V5 source directory, there is a configure script which +automatically determines the compilation environment and creates the +proper Makefiles for a particular platform. This configure script is +generated using autoconf, which you should already have installed if +you will be making changes to src/configure.in.

+

Normal users will not need to worry about running autoconf; the +distribution comes with the configure script already prebuilt.

+

The autoconf package comes with a script called autoreconf that +will automatically run autoconf and autoheader as needed. You +should run autoreconf from the top source directory, e.g.:

+
cd /u1/krb5-VERSION/src
+autoreconf --verbose
+
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/build/index.html b/krb5-1.21.3/doc/html/build/index.html new file mode 100644 index 00000000..afee334f --- /dev/null +++ b/krb5-1.21.3/doc/html/build/index.html @@ -0,0 +1,190 @@ + + + + + + + + + Building Kerberos V5 — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Building Kerberos V5

+

This section details how to build and install MIT Kerberos software +from the source.

+
+

Prerequisites

+

In order to build Kerberos V5, you will need approximately 60-70 +megabytes of disk space. The exact amount will vary depending on the +platform and whether the distribution is compiled with debugging +symbol tables or not.

+

Your C compiler must conform to ANSI C (ISO/IEC 9899:1990, “c89”). +Some operating systems do not have an ANSI C compiler, or their +default compiler requires extra command-line options to enable ANSI C +conformance.

+

If you wish to keep a separate build tree, which contains the compiled +*.o file and executables, separate from your source tree, you will +need a make program which supports VPATH, or you will need to use +a tool such as lndir to produce a symbolic link tree for your build +tree.

+
+
+

Obtaining the software

+

The source code can be obtained from MIT Kerberos Distribution page, +at https://kerberos.org/dist/index.html. +The MIT Kerberos distribution comes in an archive file, generally +named krb5-VERSION-signed.tar, where VERSION is a placeholder for +the major and minor versions of MIT Kerberos. (For example, MIT +Kerberos 1.9 has major version “1” and minor version “9”.)

+

The krb5-VERSION-signed.tar contains a compressed tar file consisting +of the sources for all of Kerberos (generally named +krb5-VERSION.tar.gz) and a PGP signature file for this source tree +(generally named krb5-VERSION.tar.gz.asc). MIT highly recommends that +you verify the integrity of the source code using this signature, +e.g., by running:

+
tar xf krb5-VERSION-signed.tar
+gpg --verify krb5-VERSION.tar.gz.asc
+
+
+

Unpack krb5-VERSION.tar.gz in some directory. In this section we will assume +that you have chosen the top directory of the distribution the directory +/u1/krb5-VERSION.

+

Review the README file for the license, copyright and other sprecific to the +distribution information.

+
+
+

Contents

+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/build/options2configure.html b/krb5-1.21.3/doc/html/build/options2configure.html new file mode 100644 index 00000000..0acd915d --- /dev/null +++ b/krb5-1.21.3/doc/html/build/options2configure.html @@ -0,0 +1,465 @@ + + + + + + + + + Options to configure — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Options to configure

+

There are a number of options to configure which you can use to +control how the Kerberos distribution is built.

+
+

Most commonly used options

+
+
--help

Provides help to configure. This will list the set of commonly +used options for building Kerberos.

+
+
--prefix=PREFIX

By default, Kerberos will install the package’s files rooted at +/usr/local. If you desire to place the binaries into the +directory PREFIX, use this option.

+
+
--exec-prefix=EXECPREFIX

This option allows one to separate the architecture independent +programs from the host-dependent files (configuration files, +manual pages). Use this option to install architecture-dependent +programs in EXECPREFIX. The default location is the value of +specified by --prefix option.

+
+
--localstatedir=LOCALSTATEDIR

This option sets the directory for locally modifiable +single-machine data. In Kerberos, this mostly is useful for +setting a location for the KDC data files, as they will be +installed in LOCALSTATEDIR/krb5kdc, which is by default +PREFIX/var/krb5kdc.

+
+
--with-netlib[=libs]

Allows for suppression of or replacement of network libraries. By +default, Kerberos V5 configuration will look for -lnsl and +-lsocket. If your operating system has a broken resolver +library or fails to pass the tests in src/tests/resolv, you +will need to use this option.

+
+
--enable-dns-for-realm

Enable the use of DNS to look up a host’s Kerberos realm, +if the information is not provided in +krb5.conf. See Mapping hostnames onto Kerberos realms +for information about using DNS to determine the default realm. +DNS lookups for realm names are disabled by default.

+
+
--with-system-et

Use an installed version of the error-table (et) support software, +the compile_et program, the com_err.h header file and the com_err +library. If these are not in the default locations, you may wish +to specify CPPFLAGS=-I/some/dir and +LDFLAGS=-L/some/other/dir options at configuration time as +well.

+

If this option is not given, a version supplied with the Kerberos +sources will be built and installed along with the rest of the +Kerberos tree, for Kerberos applications to link against.

+
+
--with-system-ss

Use an installed version of the subsystem command-line interface +software, the mk_cmds program, the ss/ss.h header file and the +ss library. If these are not in the default locations, you may +wish to specify CPPFLAGS=-I/some/dir and +LDFLAGS=-L/some/other/dir options at configuration time as +well. See also the SS_LIB option.

+

If this option is not given, the ss library supplied with the +Kerberos sources will be compiled and linked into those programs +that need it; it will not be installed separately.

+
+
--with-system-db

Use an installed version of the Berkeley DB package, which must +provide an API compatible with version 1.85. This option is +unsupported and untested. In particular, we do not know if the +database-rename code used in the dumpfile load operation will +behave properly.

+

If this option is not given, a version supplied with the Kerberos +sources will be built and installed. (We are not updating this +version at this time because of licensing issues with newer +versions that we haven’t investigated sufficiently yet.)

+
+
+
+
+

Environment variables

+
+
CC=COMPILER

Use COMPILER as the C compiler.

+
+
CFLAGS=FLAGS

Use FLAGS as the default set of C compiler flags.

+
+
CPP=CPP

C preprocessor to use. (e.g., CPP='gcc -E')

+
+
CPPFLAGS=CPPOPTS

Use CPPOPTS as the default set of C preprocessor flags. The +most common use of this option is to select certain #define’s for +use with the operating system’s include files.

+
+
DB_HEADER=headername

If db.h is not the correct header file to include to compile +against the Berkeley DB 1.85 API, specify the correct header file +name with this option. For example, DB_HEADER=db3/db_185.h.

+
+
DB_LIB=libs

If -ldb is not the correct library specification for the +Berkeley DB library version to be used, override it with this +option. For example, DB_LIB=-ldb-3.3.

+
+
DEFCCNAME=ccachename

Override the built-in default credential cache name. +For example, DEFCCNAME=DIR:/var/run/user/%{USERID}/ccache +See Parameter expansion for information about supported +parameter expansions.

+
+
DEFCKTNAME=keytabname

Override the built-in default client keytab name. +The format is the same as for DEFCCNAME.

+
+
DEFKTNAME=keytabname

Override the built-in default keytab name. +The format is the same as for DEFCCNAME.

+
+
LD=LINKER

Use LINKER as the default loader if it should be different from +C compiler as specified above.

+
+
LDFLAGS=LDOPTS

This option informs the linker where to get additional libraries +(e.g., -L<lib dir>).

+
+
LIBS=LDNAME

This option allows one to specify libraries to be passed to the +linker (e.g., -l<library>)

+
+
PKCS11_MODNAME=library

Override the built-in default PKCS11 library name.

+
+
SS_LIB=libs

If -lss is not the correct way to link in your installed ss +library, for example if additional support libraries are needed, +specify the correct link options here. Some variants of this +library are around which allow for Emacs-like line editing, but +different versions require different support libraries to be +explicitly specified.

+

This option is ignored if --with-system-ss is not specified.

+
+
YACC

The ‘Yet Another C Compiler’ implementation to use. Defaults to +the first program found out of: ‘bison -y’, ‘byacc’, +‘yacc’.

+
+
YFLAGS

The list of arguments that will be passed by default to $YACC. +This script will default YFLAGS to the empty string to avoid a +default value of -d given by some make applications.

+
+
+
+
+

Fine tuning of the installation directories

+
+
--bindir=DIR

User executables. Defaults to EXECPREFIX/bin, where +EXECPREFIX is the path specified by --exec-prefix +configuration option.

+
+
--sbindir=DIR

System admin executables. Defaults to EXECPREFIX/sbin, where +EXECPREFIX is the path specified by --exec-prefix +configuration option.

+
+
--sysconfdir=DIR

Read-only single-machine data such as krb5.conf. +Defaults to PREFIX/etc, where +PREFIX is the path specified by --prefix configuration +option.

+
+
--libdir=DIR

Object code libraries. Defaults to EXECPREFIX/lib, where +EXECPREFIX is the path specified by --exec-prefix +configuration option.

+
+
--includedir=DIR

C header files. Defaults to PREFIX/include, where PREFIX is +the path specified by --prefix configuration option.

+
+
--datarootdir=DATAROOTDIR

Read-only architecture-independent data root. Defaults to +PREFIX/share, where PREFIX is the path specified by +--prefix configuration option.

+
+
--datadir=DIR

Read-only architecture-independent data. Defaults to path +specified by --datarootdir configuration option.

+
+
--localedir=DIR

Locale-dependent data. Defaults to DATAROOTDIR/locale, where +DATAROOTDIR is the path specified by --datarootdir +configuration option.

+
+
--mandir=DIR

Man documentation. Defaults to DATAROOTDIR/man, where +DATAROOTDIR is the path specified by --datarootdir +configuration option.

+
+
+
+
+

Program names

+
+
--program-prefix=PREFIX

Prepend PREFIX to the names of the programs when installing +them. For example, specifying --program-prefix=mit- at the +configure time will cause the program named abc to be +installed as mit-abc.

+
+
--program-suffix=SUFFIX

Append SUFFIX to the names of the programs when installing them. +For example, specifying --program-suffix=-mit at the configure +time will cause the program named abc to be installed as +abc-mit.

+
+
--program-transform-name=PROGRAM

Run sed -e PROGRAM on installed program names. (PROGRAM is a +sed script).

+
+
+
+
+

System types

+
+
--build=BUILD

Configure for building on BUILD +(e.g., --build=x86_64-linux-gnu).

+
+
--host=HOST

Cross-compile to build programs to run on HOST +(e.g., --host=x86_64-linux-gnu). By default, Kerberos V5 +configuration will look for “build” option.

+
+
+
+
+

Optional features

+
+
--disable-option-checking

Ignore unrecognized –enable/–with options.

+
+
--disable-FEATURE

Do not include FEATURE (same as –enable-FEATURE=no).

+
+
--enable-FEATURE[=ARG]

Include FEATURE [ARG=yes].

+
+
--enable-maintainer-mode

Enable rebuilding of source files, Makefiles, etc.

+
+
--disable-delayed-initialization

Initialize library code when loaded. Defaults to delay until +first use.

+
+
--disable-thread-support

Don’t enable thread support. Defaults to enabled.

+
+
--disable-rpath

Suppress run path flags in link lines.

+
+
--enable-athena

Build with MIT Project Athena configuration.

+
+
--disable-kdc-lookaside-cache

Disable the cache which detects client retransmits.

+
+
--disable-pkinit

Disable PKINIT plugin support.

+
+
--disable-aesni

Disable support for using AES instructions on x86 platforms.

+
+
--enable-asan[=ARG]

Enable building with asan memory error checking. If ARG is +given, it controls the -fsanitize compilation flag value (the +default is “address”).

+
+
+
+
+

Optional packages

+
+
--with-PACKAGE[=ARG]

Use PACKAGE (e.g., --with-imap). The default value of ARG +is yes.

+
+
--without-PACKAGE

Do not use PACKAGE (same as --with-PACKAGE=no) +(e.g., --without-libedit).

+
+
--with-size-optimizations

Enable a few optimizations to reduce code size possibly at some +run-time cost.

+
+
--with-system-et

Use the com_err library and compile_et utility that are already +installed on the system, instead of building and installing +local versions.

+
+
--with-system-ss

Use the ss library and mk_cmds utility that are already installed +on the system, instead of building and using private versions.

+
+
--with-system-db

Use the berkeley db utility already installed on the system, +instead of using a private version. This option is not +recommended; enabling it may result in incompatibility with key +databases originating on other systems.

+
+
--with-netlib=LIBS

Use the resolver library specified in LIBS. Use this variable +if the C library resolver is insufficient or broken.

+
+
--with-hesiod=path

Compile with Hesiod support. The path points to the Hesiod +directory. By default Hesiod is unsupported.

+
+
--with-ldap

Compile OpenLDAP database backend module.

+
+
--with-lmdb

Compile LMDB database backend module.

+
+
--with-vague-errors

Do not send helpful errors to client. For example, if the KDC +should return only vague error codes to clients.

+
+
--with-crypto-impl=IMPL

Use specified crypto implementation (e.g., --with-crypto-impl=openssl). The default is the native MIT +Kerberos implementation builtin. The other currently +implemented crypto backend is openssl. (See +MIT Kerberos features)

+
+
--without-libedit

Do not compile and link against libedit. Some utilities will no +longer offer command history or completion in interactive mode if +libedit is disabled.

+
+
--with-readline

Compile and link against GNU readline, as an alternative to libedit.

+
+
--with-system-verto

Use an installed version of libverto. If the libverto header and +library are not in default locations, you may wish to specify +CPPFLAGS=-I/some/dir and LDFLAGS=-L/some/other/dir options +at configuration time as well.

+

If this option is not given, the build system will try to detect +an installed version of libverto and use it if it is found. +Otherwise, a version supplied with the Kerberos sources will be +built and installed. The built-in version does not contain the +full set of back-end modules and is not a suitable general +replacement for the upstream version, but will work for the +purposes of Kerberos.

+

Specifying --without-system-verto will cause the built-in +version of libverto to be used unconditionally.

+
+
--with-krb5-config=PATH

Use the krb5-config program at PATH to obtain the build-time +default credential cache, keytab, and client keytab names. The +default is to use krb5-config from the program path. Specify +--without-krb5-config to disable the use of krb5-config and +use the usual built-in defaults.

+
+
--without-keyutils

Build without libkeyutils support. This disables the KEYRING +credential cache type.

+
+
+
+
+

Examples

+

For example, in order to configure Kerberos on a Solaris machine using +the suncc compiler with the optimizer turned on, run the configure +script with the following options:

+
% ./configure CC=suncc CFLAGS=-O
+
+
+

For a slightly more complicated example, consider a system where +several packages to be used by Kerberos are installed in +/usr/foobar, including Berkeley DB 3.3, and an ss library that +needs to link against the curses library. The configuration of +Kerberos might be done thus:

+
./configure CPPFLAGS=-I/usr/foobar/include LDFLAGS=-L/usr/foobar/lib \
+--with-system-et --with-system-ss --with-system-db  \
+SS_LIB='-lss -lcurses'  DB_HEADER=db3/db_185.h DB_LIB=-ldb-3.3
+
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/build/osconf.html b/krb5-1.21.3/doc/html/build/osconf.html new file mode 100644 index 00000000..39d694c4 --- /dev/null +++ b/krb5-1.21.3/doc/html/build/osconf.html @@ -0,0 +1,156 @@ + + + + + + + + + osconf.hin — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

osconf.hin

+

There is one configuration file which you may wish to edit to control +various compile-time parameters in the Kerberos distribution:

+
include/osconf.hin
+
+
+

The list that follows is by no means complete, just some of the more +interesting variables.

+
+
DEFAULT_PROFILE_PATH

The pathname to the file which contains the profiles for the known +realms, their KDCs, etc. The default value is /etc/krb5.conf.

+
+
DEFAULT_KEYTAB_NAME

The type and pathname to the default server keytab file. The +default is DEFKTNAME.

+
+
DEFAULT_KDC_ENCTYPE

The default encryption type for the KDC database master key. The +default value is aes256-cts-hmac-sha1-96.

+
+
RCTMPDIR

The directory which stores replay caches. The default is +/var/tmp.

+
+
DEFAULT_KDB_FILE

The location of the default database. The default value is +LOCALSTATEDIR/krb5kdc/principal.

+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/build_this.html b/krb5-1.21.3/doc/html/build_this.html new file mode 100644 index 00000000..f6d3e32d --- /dev/null +++ b/krb5-1.21.3/doc/html/build_this.html @@ -0,0 +1,202 @@ + + + + + + + + + How to build this documentation from the source — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

How to build this documentation from the source

+

Pre-requisites for a simple build, or to update man pages:

+ +

Additional prerequisites to include the API reference based on Doxygen +markup:

+
    +
  • Python 2.5 with the Cheetah, lxml, and xml modules

  • +
  • Doxygen

  • +
+
+

Simple build without API reference

+

To test simple changes to the RST sources, you can build the +documentation without the Doxygen reference by running, from the doc +directory:

+
sphinx-build . test_html
+
+
+

You will see a number of warnings about missing files. This is +expected. If there is not already a doc/version.py file, you will +need to create one by first running make version.py in the +src/doc directory of a configured build tree.

+
+
+

Updating man pages

+

Man pages are generated from the RST sources and checked into the +src/man directory of the repository. This allows man pages to be +installed without requiring Sphinx when using a source checkout. To +regenerate these files, run make man from the man subdirectory +of a configured build tree. You can also do this from an unconfigured +source tree with:

+
cd src/man
+make -f Makefile.in top_srcdir=.. srcdir=. man
+make clean
+
+
+

As with the simple build, it is normal to see warnings about missing +files when rebuilding the man pages.

+
+
+

Building for a release tarball or web site

+

To generate documentation in HTML format, run make html in the +doc subdirectory of a configured build tree (the build directory +corresponding to src/doc, not the top-level doc directory). +The output will be placed in the top-level doc/html directory. +This build will include the API reference generated from Doxygen +markup in the source tree.

+

Documentation generated this way will use symbolic names for paths +(like BINDIR for the directory containing user programs), with the +symbolic names being links to a table showing typical values for those +paths.

+

You can also do this from an unconfigured source tree with:

+
cd src/doc
+make -f Makefile.in SPHINX_ARGS= htmlsrc
+
+
+
+
+

Building for an OS package or site documentation

+

To generate documentation specific to a build of MIT krb5 as you have +configured it, run make substhtml in the doc subdirectory of a +configured build tree (the build directory corresponding to +src/doc, not the top-level doc directory). The output will be +placed in the html_subst subdirectory of that build directory. +This build will include the API reference.

+

Documentation generated this way will use concrete paths (like +/usr/local/bin for the directory containing user programs, for a +default custom build).

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/copyright.html b/krb5-1.21.3/doc/html/copyright.html new file mode 100644 index 00000000..7d624bf5 --- /dev/null +++ b/krb5-1.21.3/doc/html/copyright.html @@ -0,0 +1,130 @@ + + + + + + + + + Copyright — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ + + + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/formats/ccache_file_format.html b/krb5-1.21.3/doc/html/formats/ccache_file_format.html new file mode 100644 index 00000000..0218ef0c --- /dev/null +++ b/krb5-1.21.3/doc/html/formats/ccache_file_format.html @@ -0,0 +1,295 @@ + + + + + + + + + Credential cache file format — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Credential cache file format

+

There are four versions of the file format used by the FILE credential +cache type. The first byte of the file always has the value 5, and +the value of the second byte contains the version number (1 through +4). Versions 1 and 2 of the file format use native byte order for integer +representations. Versions 3 and 4 always use big-endian byte order.

+

After the two-byte version indicator, the file has three parts: the +header (in version 4 only), the default principal name, and a sequence +of credentials.

+
+

Header format

+

The header appears only in format version 4. It begins with a 16-bit +integer giving the length of the entire header, followed by a sequence +of fields. Each field consists of a 16-bit tag, a 16-bit length, and +a value of the given length. A file format implementation should +ignore fields with unknown tags.

+

At this time there is only one defined header field. Its tag value is +1, its length is always 8, and its contents are two 32-bit integers +giving the seconds and microseconds of the time offset of the KDC +relative to the client. Adding this offset to the current time on the +client should give the current time on the KDC, if that offset has not +changed since the initial authentication.

+
+
+

Principal format

+

The default principal is marshalled using the following informal +grammar:

+
principal ::=
+    name type (32 bits) [omitted in version 1]
+    count of components (32 bits) [includes realm in version 1]
+    realm (data)
+    component1 (data)
+    component2 (data)
+    ...
+
+data ::=
+    length (32 bits)
+    value (length bytes)
+
+
+

There is no external framing on the default principal, so it must be +parsed according to the above grammar in order to find the sequence of +credentials which follows.

+
+
+

Credential format

+

The credential format uses the following informal grammar (referencing +the principal and data types from the previous section):

+
credential ::=
+    client (principal)
+    server (principal)
+    keyblock (keyblock)
+    authtime (32 bits)
+    starttime (32 bits)
+    endtime (32 bits)
+    renew_till (32 bits)
+    is_skey (1 byte, 0 or 1)
+    ticket_flags (32 bits)
+    addresses (addresses)
+    authdata (authdata)
+    ticket (data)
+    second_ticket (data)
+
+keyblock ::=
+    enctype (16 bits) [repeated twice in version 3]
+    data
+
+addresses ::=
+    count (32 bits)
+    address1
+    address2
+    ...
+
+address ::=
+    addrtype (16 bits)
+    data
+
+authdata ::=
+    count (32 bits)
+    authdata1
+    authdata2
+    ...
+
+authdata ::=
+    ad_type (16 bits)
+    data
+
+
+

There is no external framing on a marshalled credential, so it must be +parsed according to the above grammar in order to find the next +credential. There is also no count of credentials or marker at the +end of the sequence of credentials; the sequence ends when the file +ends.

+
+
+

Credential cache configuration entries

+

Configuration entries are encoded as credential entries. The client +principal of the entry is the default principal of the cache. The +server principal has the realm X-CACHECONF: and two or three +components, the first of which is krb5_ccache_conf_data. The +server principal’s second component is the configuration key. The +third component, if it exists, is a principal to which the +configuration key is associated. The configuration value is stored in +the ticket field of the entry. All other entry fields are zeroed.

+

Programs using credential caches must be aware of configuration +entries for several reasons:

+
    +
  • A program which displays the contents of a cache should not +generally display configuration entries.

  • +
  • The ticket field of a configuration entry is not (usually) a valid +encoding of a Kerberos ticket. An implementation must not treat the +cache file as malformed if it cannot decode the ticket field.

  • +
  • Configuration entries have an endtime field of 0 and might therefore +always be considered expired, but they should not be treated as +unimportant as a result. For instance, a program which copies +credentials from one cache to another should not omit configuration +entries because of the endtime.

  • +
+

The following configuration keys are currently used in MIT krb5:

+
+
fast_avail

The presence of this key with a non-empty value indicates that the +KDC asserted support for FAST (see RFC 6113) during the initial +authentication, using the negotiation method described in +RFC 6806 section 11. This key is not associated with any +principal.

+
+
pa_config_data

The value of this key contains a JSON object representation of +parameters remembered by the preauthentication mechanism used +during the initial authentication. These parameters may be used +when refreshing credentials. This key is associated with the +server principal of the initial authentication (usually the local +krbtgt principal of the client realm).

+
+
pa_type

The value of this key is the ASCII decimal representation of the +preauth type number used during the initial authentication. This +key is associated with the server principal of the initial +authentication.

+
+
proxy_impersonator

The presence of this key indicates that the cache is a synthetic +delegated credential for use with S4U2Proxy. The value is the +name of the intermediate service whose TGT can be used to make +S4U2Proxy requests for target services. This key is not +associated with any principal.

+
+
refresh_time

The presence of this key indicates that the cache was acquired by +the GSS mechanism using a client keytab. The value is the ASCII +decimal representation of a timestamp at which the GSS mechanism +should attempt to refresh the credential cache from the client +keytab.

+
+
start_realm

This key indicates the realm of the ticket-granting ticket to be +used for TGS requests, when making a referrals request or +beginning a cross-realm request. If it is not present, the client +realm is used.

+
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/formats/cookie.html b/krb5-1.21.3/doc/html/formats/cookie.html new file mode 100644 index 00000000..f35a5e6e --- /dev/null +++ b/krb5-1.21.3/doc/html/formats/cookie.html @@ -0,0 +1,222 @@ + + + + + + + + + KDC cookie format — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ + + + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/formats/freshness_token.html b/krb5-1.21.3/doc/html/formats/freshness_token.html new file mode 100644 index 00000000..dda48da4 --- /dev/null +++ b/krb5-1.21.3/doc/html/formats/freshness_token.html @@ -0,0 +1,149 @@ + + + + + + + + + PKINIT freshness tokens — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

PKINIT freshness tokens

+

RFC 8070 specifies a pa-data type PA_AS_FRESHNESS, which clients +should reflect within signed PKINIT data to prove recent access to the +client certificate private key. The contents of a freshness token are +left to the KDC implementation. The MIT krb5 KDC uses the following +format for freshness tokens (starting in release 1.17):

+
    +
  • a four-byte big-endian POSIX timestamp

  • +
  • a four-byte big-endian key version number

  • +
  • an RFC 3961 checksum, with no ASN.1 wrapper

  • +
+

The checksum is computed using the first key in the local krbtgt +principal entry for the realm (e.g. krbtgt/KRBTEST.COM@KRBTEST.COM +if the request is to the KRBTEST.COM realm) of the indicated key +version. The checksum type must be the mandatory checksum type for +the encryption type of the krbtgt key. The key usage value for the +checksum is 514.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/formats/index.html b/krb5-1.21.3/doc/html/formats/index.html new file mode 100644 index 00000000..ac18e321 --- /dev/null +++ b/krb5-1.21.3/doc/html/formats/index.html @@ -0,0 +1,142 @@ + + + + + + + + + Protocols and file formats — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/formats/keytab_file_format.html b/krb5-1.21.3/doc/html/formats/keytab_file_format.html new file mode 100644 index 00000000..69572421 --- /dev/null +++ b/krb5-1.21.3/doc/html/formats/keytab_file_format.html @@ -0,0 +1,179 @@ + + + + + + + + + Keytab file format — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Keytab file format

+

There are two versions of the file format used by the FILE keytab +type. The first byte of the file always has the value 5, and the +value of the second byte contains the version number (1 or 2). +Version 1 of the file format uses native byte order for integer +representations. Version 2 always uses big-endian byte order.

+

After the two-byte version indicator, the file contains a sequence of +signed 32-bit record lengths followed by key records or holes. A +positive record length indicates a valid key entry whose size is equal +to or less than the record length. A negative length indicates a +zero-filled hole whose size is the inverse of the length. A length of +0 indicates the end of the file.

+
+

Key entry format

+

A key entry may be smaller in size than the record length which +precedes it, because it may have replaced a hole which is larger than +the key entry. Key entries use the following informal grammar:

+
entry ::=
+    principal
+    timestamp (32 bits)
+    key version (8 bits)
+    enctype (16 bits)
+    key length (16 bits)
+    key contents
+    key version (32 bits) [in release 1.14 and later]
+
+principal ::=
+    count of components (16 bits) [includes realm in version 1]
+    realm (data)
+    component1 (data)
+    component2 (data)
+    ...
+    name type (32 bits) [omitted in version 1]
+
+data ::=
+    length (16 bits)
+    value (length bytes)
+
+
+

The 32-bit key version overrides the 8-bit key version. To determine +if it is present, the implementation must check that at least 4 bytes +remain in the record after the other fields are read, and that the +value of the 32-bit integer contained in those bytes is non-zero.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/formats/rcache_file_format.html b/krb5-1.21.3/doc/html/formats/rcache_file_format.html new file mode 100644 index 00000000..bacb4db8 --- /dev/null +++ b/krb5-1.21.3/doc/html/formats/rcache_file_format.html @@ -0,0 +1,173 @@ + + + + + + + + + Replay cache file format — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Replay cache file format

+

This section documents the second version of the replay cache file +format, used by the “file2” replay cache type (new in release 1.18). +The first version of the file replay cache format is not documented.

+

All accesses to the replay cache file take place under an exclusive +POSIX or Windows file lock, obtained when the file is opened and +released when it is closed. Replay cache files are automatically +created when first accessed.

+

For each store operation, a tag is derived from the checksum part of +the RFC 3961 ciphertext of the authenticator. The checksum is +coerced to a fixed length of 12 bytes, either through truncation or +right-padding with zero bytes. A four-byte timestamp is appended to +the tag to produce a total record length of 16 bytes.

+

Bytes 0 through 15 of the file contain a hash seed for the SipHash-2-4 +algorithm (siphash); this field is populated with random bytes when +the file is first created. All remaining bytes are divided into a +series of expanding hash tables:

+
    +
  • Bytes 16-16383: hash table 1 (1023 slots)

  • +
  • Bytes 16384-49151: hash table 2 (2048 slots)

  • +
  • Bytes 49152-114687: hash table 3 (4096 slots)

  • +
  • +
+

Only some hash tables will be present in the file at any specific +time, and the final table may be only partially filled. Replay cache +files may be sparse if the filesystem supports it.

+

For each table present in the file, the tag is hashed with SipHash-2-4 +using the seed recorded in the file. The first byte of the seed is +incremented by one (modulo 256) for each table after the first. The +resulting hash value is taken modulo one less than the table size +(1022 for the first hash table, 2047 for the second) to produce the +index. The record may be found at the slot given by the index or at +the next slot.

+

All candidate locations for the record must be searched until a slot +is found with a timestamp of zero (indicating a slot which has never +been written to) or an offset is reached at or beyond the end of the +file. Any candidate location with a timestamp value of zero, with a +timestamp value less than the current time minus clockskew, or at or +beyond the end of the file is available for writing. When all +candidate locations have been searched without finding a match, the +new entry is written to the earliest candidate available for writing.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/genindex-A.html b/krb5-1.21.3/doc/html/genindex-A.html new file mode 100644 index 00000000..5df5a686 --- /dev/null +++ b/krb5-1.21.3/doc/html/genindex-A.html @@ -0,0 +1,159 @@ + + + + + + + + + Index — MIT Kerberos Documentation + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/genindex-C.html b/krb5-1.21.3/doc/html/genindex-C.html new file mode 100644 index 00000000..a835f4e8 --- /dev/null +++ b/krb5-1.21.3/doc/html/genindex-C.html @@ -0,0 +1,153 @@ + + + + + + + + + Index — MIT Kerberos Documentation + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/genindex-E.html b/krb5-1.21.3/doc/html/genindex-E.html new file mode 100644 index 00000000..ef547165 --- /dev/null +++ b/krb5-1.21.3/doc/html/genindex-E.html @@ -0,0 +1,169 @@ + + + + + + + + + Index — MIT Kerberos Documentation + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ +
+
+ + +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/genindex-K.html b/krb5-1.21.3/doc/html/genindex-K.html new file mode 100644 index 00000000..b1845589 --- /dev/null +++ b/krb5-1.21.3/doc/html/genindex-K.html @@ -0,0 +1,2077 @@ + + + + + + + + + Index — MIT Kerberos Documentation + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ + +

Index – K

+ + + + +
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/genindex-L.html b/krb5-1.21.3/doc/html/genindex-L.html new file mode 100644 index 00000000..8e047258 --- /dev/null +++ b/krb5-1.21.3/doc/html/genindex-L.html @@ -0,0 +1,123 @@ + + + + + + + + + Index — MIT Kerberos Documentation + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/genindex-M.html b/krb5-1.21.3/doc/html/genindex-M.html new file mode 100644 index 00000000..a9db824e --- /dev/null +++ b/krb5-1.21.3/doc/html/genindex-M.html @@ -0,0 +1,125 @@ + + + + + + + + + Index — MIT Kerberos Documentation + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/genindex-P.html b/krb5-1.21.3/doc/html/genindex-P.html new file mode 100644 index 00000000..4c8a2c2d --- /dev/null +++ b/krb5-1.21.3/doc/html/genindex-P.html @@ -0,0 +1,127 @@ + + + + + + + + + Index — MIT Kerberos Documentation + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/genindex-R.html b/krb5-1.21.3/doc/html/genindex-R.html new file mode 100644 index 00000000..0f04f26b --- /dev/null +++ b/krb5-1.21.3/doc/html/genindex-R.html @@ -0,0 +1,184 @@ + + + + + + + + + Index — MIT Kerberos Documentation + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/genindex-S.html b/krb5-1.21.3/doc/html/genindex-S.html new file mode 100644 index 00000000..e6748716 --- /dev/null +++ b/krb5-1.21.3/doc/html/genindex-S.html @@ -0,0 +1,123 @@ + + + + + + + + + Index — MIT Kerberos Documentation + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/genindex-T.html b/krb5-1.21.3/doc/html/genindex-T.html new file mode 100644 index 00000000..f7366661 --- /dev/null +++ b/krb5-1.21.3/doc/html/genindex-T.html @@ -0,0 +1,151 @@ + + + + + + + + + Index — MIT Kerberos Documentation + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/genindex-V.html b/krb5-1.21.3/doc/html/genindex-V.html new file mode 100644 index 00000000..b538ae78 --- /dev/null +++ b/krb5-1.21.3/doc/html/genindex-V.html @@ -0,0 +1,123 @@ + + + + + + + + + Index — MIT Kerberos Documentation + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/genindex-all.html b/krb5-1.21.3/doc/html/genindex-all.html new file mode 100644 index 00000000..51736b6a --- /dev/null +++ b/krb5-1.21.3/doc/html/genindex-all.html @@ -0,0 +1,2419 @@ + + + + + + + + Index — MIT Kerberos Documentation + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ + +

Index

+ +
+ A + | C + | E + | K + | L + | M + | P + | R + | S + | T + | V + +
+

A

+ + + +
+ +

C

+ + + +
+ +

E

+ + + +
+ +

K

+ + + +
+ +

L

+ + + +
+ +

M

+ + + +
+ +

P

+ + + +
+ +

R

+ + +
+ +

S

+ + + +
+ +

T

+ + + +
+ +

V

+ + + +
+ + + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/genindex.html b/krb5-1.21.3/doc/html/genindex.html new file mode 100644 index 00000000..6da01634 --- /dev/null +++ b/krb5-1.21.3/doc/html/genindex.html @@ -0,0 +1,131 @@ + + + + + + + + Index — MIT Kerberos Documentation + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ + +

Index

+ +

Index pages by letter:

+ +
+

A + | C + | E + | K + | L + | M + | P + | R + | S + | T + | V +

+ +

Full index on one page + (can be huge)

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/index.html b/krb5-1.21.3/doc/html/index.html new file mode 100644 index 00000000..7f0a29e3 --- /dev/null +++ b/krb5-1.21.3/doc/html/index.html @@ -0,0 +1,136 @@ + + + + + + + + + MIT Kerberos Documentation (1.21.3) — MIT Kerberos Documentation + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/mitK5defaults.html b/krb5-1.21.3/doc/html/mitK5defaults.html new file mode 100644 index 00000000..5c604f27 --- /dev/null +++ b/krb5-1.21.3/doc/html/mitK5defaults.html @@ -0,0 +1,361 @@ + + + + + + + + + MIT Kerberos defaults — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

MIT Kerberos defaults

+
+

General defaults

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Description

Default

Environment

keytab file

DEFKTNAME

KRB5_KTNAME

Client keytab file

DEFCKTNAME

KRB5_CLIENT_KTNAME

Kerberos config file krb5.conf

/etc/krb5.conf:SYSCONFDIR/krb5.conf

KRB5_CONFIG

KDC config file kdc.conf

LOCALSTATEDIR/krb5kdc/kdc.conf

KRB5_KDC_PROFILE

GSS mechanism config file

SYSCONFDIR/gss/mech

GSS_MECH_CONFIG

KDC database path (DB2)

LOCALSTATEDIR/krb5kdc/principal

Master key stash file

LOCALSTATEDIR/krb5kdc/.k5.realm

Admin server ACL file kadm5.acl

LOCALSTATEDIR/krb5kdc/kadm5.acl

OTP socket directory

RUNSTATEDIR/krb5kdc

Plugin base directory

LIBDIR/krb5/plugins

replay cache directory

/var/tmp

KRB5RCACHEDIR

Master key default enctype

aes256-cts-hmac-sha1-96

Default keysalt list

aes256-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:normal

Permitted enctypes

aes256-cts-hmac-sha1-96 aes128-cts-hmac-sha1-96 aes256-cts-hmac-sha384-192 aes128-cts-hmac-sha256-128 des3-cbc-sha1 arcfour-hmac-md5 camellia256-cts-cmac camellia128-cts-cmac

KDC default port

88

Admin server port

749

Password change port

464

+
+
+

Replica KDC propagation defaults

+

This table shows defaults used by the kprop and +kpropd programs.

+ +++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Description

Default

Environment

kprop database dump file

LOCALSTATEDIR/krb5kdc/replica_datatrans

kpropd temporary dump file

LOCALSTATEDIR/krb5kdc/from_master

kdb5_util location

SBINDIR/kdb5_util

kprop location

SBINDIR/kprop

kpropd ACL file

LOCALSTATEDIR/krb5kdc/kpropd.acl

kprop port

754

KPROP_PORT

+
+
+

Default paths for Unix-like systems

+

On Unix-like systems, some paths used by MIT krb5 depend on parameters +chosen at build time. For a custom build, these paths default to +subdirectories of /usr/local. When MIT krb5 is integrated into an +operating system, the paths are generally chosen to match the +operating system’s filesystem layout.

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Description

Symbolic name

Custom build path

Typical OS path

User programs

BINDIR

/usr/local/bin

/usr/bin

Libraries and plugins

LIBDIR

/usr/local/lib

/usr/lib

Parent of KDC state dir

LOCALSTATEDIR

/usr/local/var

/var

Parent of KDC runtime dir

RUNSTATEDIR

/usr/local/var/run

/run

Administrative programs

SBINDIR

/usr/local/sbin

/usr/sbin

Alternate krb5.conf dir

SYSCONFDIR

/usr/local/etc

/etc

Default ccache name

DEFCCNAME

FILE:/tmp/krb5cc_%{uid}

FILE:/tmp/krb5cc_%{uid}

Default keytab name

DEFKTNAME

FILE:/etc/krb5.keytab

FILE:/etc/krb5.keytab

Default PKCS11 module

PKCS11_MODNAME

opensc-pkcs11.so

opensc-pkcs11.so

+

The default client keytab name (DEFCKTNAME) typically defaults to +FILE:/usr/local/var/krb5/user/%{euid}/client.keytab for a custom +build. A native build will typically use a path which will vary +according to the operating system’s layout of /var.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/mitK5features.html b/krb5-1.21.3/doc/html/mitK5features.html new file mode 100644 index 00000000..6a5397db --- /dev/null +++ b/krb5-1.21.3/doc/html/mitK5features.html @@ -0,0 +1,789 @@ + + + + + + + + + MIT Kerberos features — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+

MIT Kerberos features

+

https://web.mit.edu/kerberos

+
+

Quick facts

+

License - MIT Kerberos License information

+
+
Releases:
+
+
Supported platforms / OS distributions:
    +
  • Windows (KfW 4.0): Windows 7, Vista, XP

  • +
  • Solaris: SPARC, x86_64/x86

  • +
  • GNU/Linux: Debian x86_64/x86, Ubuntu x86_64/x86, RedHat x86_64/x86

  • +
  • BSD: NetBSD x86_64/x86

  • +
+
+
Crypto backends:
+
+
+

Database backends: LDAP, DB2, LMDB

+

krb4 support: Kerberos 5 release < 1.8

+

DES support: Kerberos 5 release < 1.18 (See Retiring DES)

+
+
+

Interoperability

+

Microsoft

+

Starting from release 1.7:

+
    +
  • Follow client principal referrals in the client library when +obtaining initial tickets.

  • +
  • KDC can issue realm referrals for service principals based on domain names.

  • +
  • Extensions supporting DCE RPC, including three-leg GSS context setup +and unencapsulated GSS tokens inside SPNEGO.

  • +
  • Microsoft GSS_WrapEX, implemented using the gss_iov API, which is +similar to the equivalent SSPI functionality. This is needed to +support some instances of DCE RPC.

  • +
  • NTLM recognition support in GSS-API, to facilitate dropping in an +NTLM implementation for improved compatibility with older releases +of Microsoft Windows.

  • +
  • KDC support for principal aliases, if the back end supports them. +Currently, only the LDAP back end supports aliases.

  • +
  • Support Microsoft set/change password (RFC 3244) protocol in +kadmind.

  • +
  • Implement client and KDC support for GSS_C_DELEG_POLICY_FLAG, which +allows a GSS application to request credential delegation only if +permitted by KDC policy.

  • +
+

Starting from release 1.8:

+
    +
  • Microsoft Services for User (S4U) compatibility

  • +
+

Heimdal

+
    +
  • Support for KCM credential cache starting from release 1.13

  • +
+
+
+

Feature list

+

For more information on the specific project see https://k5wiki.kerberos.org/wiki/Projects

+
+
Release 1.7
+
+
Release 1.8
+
+
Release 1.9
    +
  • Advance warning on password expiry

  • +
  • Camellia encryption (CTS-CMAC mode) RFC 6803

  • +
  • KDC support for SecurID preauthentication

  • +
  • kadmin over IPv6

  • +
  • Trace logging Trace logging

  • +
  • GSSAPI/KRB5 multi-realm support

  • +
  • Plugin to test password quality Password quality interface (pwqual)

  • +
  • Plugin to synchronize password changes KADM5 hook interface (kadm5_hook)

  • +
  • Parallel KDC

  • +
  • GSS-API extensions for SASL GS2 bridge RFC 5801 RFC 5587

  • +
  • Purging old keys

  • +
  • Naming extensions for delegation chain

  • +
  • Password expiration API

  • +
  • Windows client support (build-only)

  • +
  • IPv6 support in iprop

  • +
+
+
Release 1.10
+
+
Release 1.11
    +
  • Client support for FAST OTP RFC 6560

  • +
  • GSS-API extensions for credential locations

  • +
  • Responder mechanism

  • +
+
+
Release 1.12
+
+
+

Release 1.13

+
+
    +
  • Add support for accessing KDCs via an HTTPS proxy server using +the MS-KKDCP +protocol.

  • +
  • Add support for hierarchical incremental propagation, +where replicas can act as intermediates between an upstream primary +and other downstream replicas.

  • +
  • Add support for configuring GSS mechanisms using +/etc/gss/mech.d/*.conf files in addition to +/etc/gss/mech.

  • +
  • Add support to the LDAP KDB module for binding to the LDAP +server using SASL.

  • +
  • The KDC listens for TCP connections by default.

  • +
  • Fix a minor key disclosure vulnerability where using the +“keepold” option to the kadmin randkey operation could return the +old keys. [CVE-2014-5351]

  • +
  • Add client support for the Kerberos Cache Manager protocol. If +the host is running a Heimdal kcm daemon, caches served by the +daemon can be accessed with the KCM: cache type.

  • +
  • When built on macOS 10.7 and higher, use “KCM:” as the default +cachetype, unless overridden by command-line options or +krb5-config values.

  • +
  • Add support for doing unlocked database dumps for the DB2 KDC +back end, which would allow the KDC and kadmind to continue +accessing the database during lengthy database dumps.

  • +
+
+

Release 1.14

+
+
    +
  • Administrator experience

    +
      +
    • Add a new kdb5_util tabdump command to provide reporting-friendly +tabular dump formats (tab-separated or CSV) for the KDC database. +Unlike the normal dump format, each output table has a fixed number +of fields. Some tables include human-readable forms of data that +are opaque in ordinary dump files. This format is also suitable for +importing into relational databases for complex queries.

    • +
    • Add support to kadmin and kadmin.local for specifying a single +command line following any global options, where the command +arguments are split by the shell–for example, “kadmin getprinc +principalname”. Commands issued this way do not prompt for +confirmation or display warning messages, and exit with non-zero +status if the operation fails.

    • +
    • Accept the same principal flag names in kadmin as we do for the +default_principal_flags kdc.conf variable, and vice versa. Also +accept flag specifiers in the form that kadmin prints, as well as +hexadecimal numbers.

    • +
    • Remove the triple-DES and RC4 encryption types from the default +value of supported_enctypes, which determines the default key and +salt types for new password-derived keys. By default, keys will +only created only for AES128 and AES256. This mitigates some types +of password guessing attacks.

    • +
    • Add support for directory names in the KRB5_CONFIG and +KRB5_KDC_PROFILE environment variables.

    • +
    • Add support for authentication indicators, which are ticket +annotations to indicate the strength of the initial authentication. +Add support for the “require_auth” string attribute, which can be +set on server principal entries to require an indicator when +authenticating to the server.

    • +
    • Add support for key version numbers larger than 255 in keytab files, +and for version numbers up to 65535 in KDC databases.

    • +
    • Transmit only one ETYPE-INFO and/or ETYPE-INFO2 entry from the KDC +during pre-authentication, corresponding to the client’s most +preferred encryption type.

    • +
    • Add support for server name identification (SNI) when proxying KDC +requests over HTTPS.

    • +
    • Add support for the err_fmt profile parameter, which can be used to +generate custom-formatted error messages.

    • +
    +
  • +
  • Developer experience:

    +
      +
    • Change gss_acquire_cred_with_password() to acquire credentials into +a private memory credential cache. Applications can use +gss_store_cred() to make the resulting credentials visible to other +processes.

    • +
    • Change gss_acquire_cred() and SPNEGO not to acquire credentials for +IAKERB or for non-standard variants of the krb5 mechanism OID unless +explicitly requested. (SPNEGO will still accept the Microsoft +variant of the krb5 mechanism OID during negotiation.)

    • +
    • Change gss_accept_sec_context() not to accept tokens for IAKERB or +for non-standard variants of the krb5 mechanism OID unless an +acceptor credential is acquired for those mechanisms.

    • +
    • Change gss_acquire_cred() to immediately resolve credentials if the +time_rec parameter is not NULL, so that a correct expiration time +can be returned. Normally credential resolution is delayed until +the target name is known.

    • +
    • Add krb5_prepend_error_message() and krb5_wrap_error_message() APIs, +which can be used by plugin modules or applications to add prefixes +to existing detailed error messages.

    • +
    • Add krb5_c_prfplus() and krb5_c_derive_prfplus() APIs, which +implement the RFC 6113 PRF+ operation and key derivation using PRF+.

    • +
    • Add support for pre-authentication mechanisms which use multiple +round trips, using the the KDC_ERR_MORE_PREAUTH_DATA_REQUIRED error +code. Add get_cookie() and set_cookie() callbacks to the kdcpreauth +interface; these callbacks can be used to save marshalled state +information in an encrypted cookie for the next request.

    • +
    • Add a client_key() callback to the kdcpreauth interface to retrieve +the chosen client key, corresponding to the ETYPE-INFO2 entry sent +by the KDC.

    • +
    • Add an add_auth_indicator() callback to the kdcpreauth interface, +allowing pre-authentication modules to assert authentication +indicators.

    • +
    • Add support for the GSS_KRB5_CRED_NO_CI_FLAGS_X cred option to +suppress sending the confidentiality and integrity flags in GSS +initiator tokens unless they are requested by the caller. These +flags control the negotiated SASL security layer for the Microsoft +GSS-SPNEGO SASL mechanism.

    • +
    • Make the FILE credential cache implementation less prone to +corruption issues in multi-threaded programs, especially on +platforms with support for open file description locks.

    • +
    +
  • +
  • Performance:

    +
      +
    • On replica KDCs, poll the primary KDC immediately after +processing a full resync, and do not require two full resyncs +after the primary KDC’s log file is reset.

    • +
    +
  • +
+
+

Release 1.15

+
    +
  • Administrator experience:

    +
      +
    • Add support to kadmin for remote extraction of current keys +without changing them (requires a special kadmin permission that +is excluded from the wildcard permission), with the exception of +highly protected keys.

    • +
    • Add a lockdown_keys principal attribute to prevent retrieval of +the principal’s keys (old or new) via the kadmin protocol. In +newly created databases, this attribute is set on the krbtgt and +kadmin principals.

    • +
    • Restore recursive dump capability for DB2 back end, so sites can +more easily recover from database corruption resulting from power +failure events.

    • +
    • Add DNS auto-discovery of KDC and kpasswd servers from URI +records, in addition to SRV records. URI records can convey TCP +and UDP servers and primary KDC status in a single DNS lookup, and +can also point to HTTPS proxy servers.

    • +
    • Add support for password history to the LDAP back end.

    • +
    • Add support for principal renaming to the LDAP back end.

    • +
    • Use the getrandom system call on supported Linux kernels to avoid +blocking problems when getting entropy from the operating system.

    • +
    +
  • +
  • Code quality:

    +
      +
    • Clean up numerous compilation warnings.

    • +
    • Remove various infrequently built modules, including some preauth +modules that were not built by default.

    • +
    +
  • +
  • Developer experience:

    +
      +
    • Add support for building with OpenSSL 1.1.

    • +
    • Use SHA-256 instead of MD5 for (non-cryptographic) hashing of +authenticators in the replay cache. This helps sites that must +build with FIPS 140 conformant libraries that lack MD5.

    • +
    +
  • +
  • Protocol evolution:

    +
      +
    • Add support for the AES-SHA2 enctypes, which allows sites to +conform to Suite B crypto requirements.

    • +
    +
  • +
+

Release 1.16

+
    +
  • Administrator experience:

    +
      +
    • The KDC can match PKINIT client certificates against the +“pkinit_cert_match” string attribute on the client principal +entry, using the same syntax as the existing “pkinit_cert_match” +profile option.

    • +
    • The ktutil addent command supports the “-k 0” option to ignore the +key version, and the “-s” option to use a non-default salt string.

    • +
    • kpropd supports a –pid-file option to write a pid file at +startup, when it is run in standalone mode.

    • +
    • The “encrypted_challenge_indicator” realm option can be used to +attach an authentication indicator to tickets obtained using FAST +encrypted challenge pre-authentication.

    • +
    • Localization support can be disabled at build time with the +–disable-nls configure option.

    • +
    +
  • +
  • Developer experience:

    +
      +
    • The kdcpolicy pluggable interface allows modules control whether +tickets are issued by the KDC.

    • +
    • The kadm5_auth pluggable interface allows modules to control +whether kadmind grants access to a kadmin request.

    • +
    • The certauth pluggable interface allows modules to control which +PKINIT client certificates can authenticate to which client +principals.

    • +
    • KDB modules can use the client and KDC interface IP addresses to +determine whether to allow an AS request.

    • +
    • GSS applications can query the bit strength of a krb5 GSS context +using the GSS_C_SEC_CONTEXT_SASL_SSF OID with +gss_inquire_sec_context_by_oid().

    • +
    • GSS applications can query the impersonator name of a krb5 GSS +credential using the GSS_KRB5_GET_CRED_IMPERSONATOR OID with +gss_inquire_cred_by_oid().

    • +
    • kdcpreauth modules can query the KDC for the canonicalized +requested client principal name, or match a principal name against +the requested client principal name with canonicalization.

    • +
    +
  • +
  • Protocol evolution:

    +
      +
    • The client library will continue to try pre-authentication +mechanisms after most failure conditions.

    • +
    • The KDC will issue trivially renewable tickets (where the +renewable lifetime is equal to or less than the ticket lifetime) +if requested by the client, to be friendlier to scripts.

    • +
    • The client library will use a random nonce for TGS requests +instead of the current system time.

    • +
    • For the RC4 string-to-key or PAC operations, UTF-16 is supported +(previously only UCS-2 was supported).

    • +
    • When matching PKINIT client certificates, UPN SANs will be matched +correctly as UPNs, with canonicalization.

    • +
    +
  • +
  • User experience:

    +
      +
    • Dates after the year 2038 are accepted (provided that the platform +time facilities support them), through the year 2106.

    • +
    • Automatic credential cache selection based on the client realm +will take into account the fallback realm and the service +hostname.

    • +
    • Referral and alternate cross-realm TGTs will not be cached, +avoiding some scenarios where they can be added to the credential +cache multiple times.

    • +
    • A German translation has been added.

    • +
    +
  • +
  • Code quality:

    +
      +
    • The build is warning-clean under clang with the configured warning +options.

    • +
    • The automated test suite runs cleanly under AddressSanitizer.

    • +
    +
  • +
+

Release 1.17

+
    +
  • Administrator experience:

    +
      +
    • A new Kerberos database module using the Lightning Memory-Mapped +Database library (LMDB) has been added. The LMDB KDB module +should be more performant and more robust than the DB2 module, and +may become the default module for new databases in a future +release.

    • +
    • “kdb5_util dump” will no longer dump policy entries when specific +principal names are requested.

    • +
    +
  • +
  • Developer experience:

    +
      +
    • The new krb5_get_etype_info() API can be used to retrieve enctype, +salt, and string-to-key parameters from the KDC for a client +principal.

    • +
    • The new GSS_KRB5_NT_ENTERPRISE_NAME name type allows enterprise +principal names to be used with GSS-API functions.

    • +
    • KDC and kadmind modules which call com_err() will now write to the +log file in a format more consistent with other log messages.

    • +
    • Programs which use large numbers of memory credential caches +should perform better.

    • +
    +
  • +
  • Protocol evolution:

    +
      +
    • The SPAKE pre-authentication mechanism is now supported. This +mechanism protects against password dictionary attacks without +requiring any additional infrastructure such as certificates. +SPAKE is enabled by default on clients, but must be manually +enabled on the KDC for this release.

    • +
    • PKINIT freshness tokens are now supported. Freshness tokens can +protect against scenarios where an attacker uses temporary access +to a smart card to generate authentication requests for the +future.

    • +
    • Password change operations now prefer TCP over UDP, to avoid +spurious error messages about replays when a response packet is +dropped.

    • +
    • The KDC now supports cross-realm S4U2Self requests when used with +a third-party KDB module such as Samba’s. The client code for +cross-realm S4U2Self requests is also now more robust.

    • +
    +
  • +
  • User experience:

    +
      +
    • The new ktutil addent -f flag can be used to fetch salt +information from the KDC for password-based keys.

    • +
    • The new kdestroy -p option can be used to destroy a credential +cache within a collection by client principal name.

    • +
    • The Kerberos man page has been restored, and documents the +environment variables that affect programs using the Kerberos +library.

    • +
    +
  • +
  • Code quality:

    +
      +
    • Python test scripts now use Python 3.

    • +
    • Python test scripts now display markers in verbose output, making +it easier to find where a failure occurred within the scripts.

    • +
    • The Windows build system has been simplified and updated to work +with more recent versions of Visual Studio. A large volume of +unused Windows-specific code has been removed. Visual Studio 2013 +or later is now required.

    • +
    +
  • +
+

Release 1.18

+
    +
  • Administrator experience:

    +
      +
    • Remove support for single-DES encryption types.

    • +
    • Change the replay cache format to be more efficient and robust. +Replay cache filenames using the new format end with .rcache2 +by default.

    • +
    • setuid programs will automatically ignore environment variables +that normally affect krb5 API functions, even if the caller does +not use krb5_init_secure_context().

    • +
    • Add an enforce_ok_as_delegate krb5.conf relation to disable +credential forwarding during GSSAPI authentication unless the KDC +sets the ok-as-delegate bit in the service ticket.

    • +
    +
  • +
  • Developer experience:

    +
      +
    • Implement krb5_cc_remove_cred() for all credential cache types.

    • +
    • Add the krb5_pac_get_client_info() API to get the client account +name from a PAC.

    • +
    +
  • +
  • Protocol evolution:

    +
      +
    • Add KDC support for S4U2Self requests where the user is identified +by X.509 certificate. (Requires support for certificate lookup +from a third-party KDB module.)

    • +
    • Remove support for an old (“draft 9”) variant of PKINIT.

    • +
    • Add support for Microsoft NegoEx. (Requires one or more +third-party GSS modules implementing NegoEx mechanisms.)

    • +
    +
  • +
  • User experience:

    +
      +
    • Add support for dns_canonicalize_hostname=fallback, causing +host-based principal names to be tried first without DNS +canonicalization, and again with DNS canonicalization if the +un-canonicalized server is not found.

    • +
    • Expand single-component hostnames in hhost-based principal names +when DNS canonicalization is not used, adding the system’s first +DNS search path as a suffix. Add a qualify_shortname +krb5.conf relation to override this suffix or disable expansion.

    • +
    +
  • +
  • Code quality:

    +
      +
    • The libkrb5 serialization code (used to export and import krb5 GSS +security contexts) has been simplified and made type-safe.

    • +
    • The libkrb5 code for creating KRB-PRIV, KRB-SAFE, and KRB-CRED +messages has been revised to conform to current coding practices.

    • +
    • The test suite has been modified to work with macOS System +Integrity Protection enabled.

    • +
    • The test suite incorporates soft-pkcs11 so that PKINIT PKCS11 +support can always be tested.

    • +
    +
  • +
+

Release 1.19

+
    +
  • Administrator experience:

    +
      +
    • When a client keytab is present, the GSSAPI krb5 mech will refresh +credentials even if the current credentials were acquired +manually.

    • +
    • It is now harder to accidentally delete the K/M entry from a KDB.

    • +
    +
  • +
  • Developer experience:

    +
      +
    • gss_acquire_cred_from() now supports the “password” and “verify” +options, allowing credentials to be acquired via password and +verified using a keytab key.

    • +
    • When an application accepts a GSS security context, the new +GSS_C_CHANNEL_BOUND_FLAG will be set if the initiator and acceptor +both provided matching channel bindings.

    • +
    • Added the GSS_KRB5_NT_X509_CERT name type, allowing S4U2Self +requests to identify the desired client principal by certificate.

    • +
    • PKINIT certauth modules can now cause the hw-authent flag to be +set in issued tickets.

    • +
    • The krb5_init_creds_step() API will now issue the same password +expiration warnings as krb5_get_init_creds_password().

    • +
    +
  • +
  • Protocol evolution:

    +
      +
    • Added client and KDC support for Microsoft’s Resource-Based +Constrained Delegation, which allows cross-realm S4U2Proxy +requests. A third-party database module is required for KDC +support.

    • +
    • kadmin/admin is now the preferred server principal name for kadmin +connections, and the host-based form is no longer created by +default. The client will still try the host-based form as a +fallback.

    • +
    • Added client and server support for Microsoft’s +KERB_AP_OPTIONS_CBT extension, which causes channel bindings to be +required for the initiator if the acceptor provided them. The +client will send this option if the client_aware_gss_bindings +profile option is set.

    • +
    +
  • +
+

User experience:

+
+
    +
  • The default setting of dns_canonicalize_realm is now “fallback”. +Hostnames provided from applications will be tried in principal +names as given (possibly with shortname qualification), falling +back to the canonicalized name.

  • +
  • kinit will now issue a warning if the des3-cbc-sha1 encryption +type is used in the reply. This encryption type will be +deprecated and removed in future releases.

  • +
  • Added kvno flags –out-cache, –no-store, and –cached-only +(inspired by Heimdal’s kgetcred).

  • +
+
+

Release 1.20

+
    +
  • Administrator experience:

    +
      +
    • Added a “disable_pac” realm relation to suppress adding PAC +authdata to tickets, for realms which do not need to support S4U +requests.

    • +
    • Most credential cache types will use atomic replacement when a +cache is reinitialized using kinit or refreshed from the client +keytab.

    • +
    • kprop can now propagate databases with a dump size larger than +4GB, if both the client and server are upgraded.

    • +
    • kprop can now work over NATs that change the destination IP +address, if the client is upgraded.

    • +
    +
  • +
  • Developer experience:

    +
      +
    • Updated the KDB interface. The sign_authdata() method is replaced +with the issue_pac() method, allowing KDB modules to add logon +info and other buffers to the PAC issued by the KDC.

    • +
    • Host-based initiator names are better supported in the GSS krb5 +mechanism.

    • +
    +
  • +
  • Protocol evolution:

    +
      +
    • Replaced AD-SIGNEDPATH authdata with minimal PACs.

    • +
    • To avoid spurious replay errors, password change requests will not +be attempted over UDP until the attempt over TCP fails.

    • +
    • PKINIT will sign its CMS messages with SHA-256 instead of SHA-1.

    • +
    +
  • +
  • Code quality:

    +
      +
    • Updated all code using OpenSSL to be compatible with OpenSSL 3.

    • +
    • Reorganized the libk5crypto build system to allow the OpenSSL +back-end to pull in material from the builtin back-end depending +on the OpenSSL version.

    • +
    • Simplified the PRNG logic to always use the platform PRNG.

    • +
    • Converted the remaining Tcl tests to Python.

    • +
    +
  • +
+

Release 1.21

+
    +
  • User experience:

    +
      +
    • Added a credential cache type providing compatibility with the +macOS 11 native credential cache.

    • +
    +
  • +
  • Developer experience:

    +
      +
    • libkadm5 will use the provided krb5_context object to read +configuration values, instead of creating its own.

    • +
    • Added an interface to retrieve the ticket session key from a GSS +context.

    • +
    +
  • +
  • Protocol evolution:

    +
      +
    • The KDC will no longer issue tickets with RC4 or triple-DES +session keys unless explicitly configured with the new allow_rc4 +or allow_des3 variables respectively.

    • +
    • The KDC will assume that all services can handle aes256-sha1 +session keys unless the service principal has a session_enctypes +string attribute.

    • +
    • Support for PAC full KDC checksums has been added to mitigate an +S4U2Proxy privilege escalation attack.

    • +
    • The PKINIT client will advertise a more modern set of supported +CMS algorithms.

    • +
    +
  • +
  • Code quality:

    +
      +
    • Removed unused code in libkrb5, libkrb5support, and the PKINIT +module.

    • +
    • Modernized the KDC code for processing TGS requests, the code for +encrypting and decrypting key data, the PAC handling code, and the +GSS library packet parsing and composition code.

    • +
    • Improved the test framework’s detection of memory errors in daemon +processes when used with asan.

    • +
    +
  • +
+

Pre-authentication mechanisms

+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/mitK5license.html b/krb5-1.21.3/doc/html/mitK5license.html new file mode 100644 index 00000000..43f82902 --- /dev/null +++ b/krb5-1.21.3/doc/html/mitK5license.html @@ -0,0 +1,1301 @@ + + + + + + + + + MIT Kerberos License information — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

MIT Kerberos License information

+
+
+

Copyright © 1985-2024 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.

+

Downloading of this software may constitute an export of cryptographic +software from the United States of America that is subject to the +United States Export Administration Regulations (EAR), 15 CFR 730-774. +Additional laws or regulations may apply. It is the responsibility of +the person or entity contemplating export to comply with all +applicable export laws and regulations, including obtaining any +required license from the U.S. government.

+

The U.S. government prohibits export of encryption source code to +certain countries and individuals, including, but not limited to, the +countries of Cuba, Iran, North Korea, Sudan, Syria, and residents and +nationals of those countries.

+

Documentation components of this software distribution are licensed +under a Creative Commons Attribution-ShareAlike 3.0 Unported License. +(https://creativecommons.org/licenses/by-sa/3.0/)

+

Individual source code files are copyright MIT, Cygnus Support, +Novell, OpenVision Technologies, Oracle, Red Hat, Sun Microsystems, +FundsXpress, and others.

+

Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, +and Zephyr are trademarks of the Massachusetts Institute of Technology +(MIT). No commercial use of these trademarks may be made without +prior written permission of MIT.

+

“Commercial use” means use of a name in a product or other for-profit +manner. It does NOT prevent a commercial firm from referring to the +MIT trademarks in order to convey information (although in doing so, +recognition of their trademark status should be given).

+
+

The following copyright and permission notice applies to the +OpenVision Kerberos Administration system located in +kadmin/create, kadmin/dbutil, kadmin/passwd, +kadmin/server, lib/kadm5, and portions of +lib/rpc:

+
+

Copyright, OpenVision Technologies, Inc., 1993-1996, All Rights Reserved

+

WARNING: Retrieving the OpenVision Kerberos Administration system source +code, as described below, indicates your acceptance of the following +terms. If you do not agree to the following terms, do not retrieve the +OpenVision Kerberos administration system.

+

You may freely use and distribute the Source Code and Object Code +compiled from it, with or without modification, but this Source Code is +provided to you “AS IS” EXCLUSIVE OF ANY WARRANTY, INCLUDING, WITHOUT +LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A +PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER EXPRESS OR IMPLIED. +IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY FOR ANY LOST PROFITS, +LOSS OF DATA OR COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR +FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS +AGREEMENT, INCLUDING, WITHOUT LIMITATION, THOSE RESULTING FROM THE USE +OF THE SOURCE CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR +ANY OTHER REASON.

+

OpenVision retains all copyrights in the donated Source Code. OpenVision +also retains copyright to derivative works of the Source Code, whether +created by OpenVision or by a third party. The OpenVision copyright +notice must be preserved if derivative works are made based on the +donated Source Code.

+

OpenVision Technologies, Inc. has donated this Kerberos Administration +system to MIT for inclusion in the standard Kerberos 5 distribution. +This donation underscores our commitment to continuing Kerberos +technology development and our gratitude for the valuable work which has +been performed by MIT and the Kerberos community.

+
+
+
+

Portions contributed by Matt Crawford crawdad@fnal.gov were work +performed at Fermi National Accelerator Laboratory, which is operated +by Universities Research Association, Inc., under contract +DE-AC02-76CHO3000 with the U.S. Department of Energy.

+
+
+

Portions of src/lib/crypto have the following copyright:

+
+

Copyright © 1998 by the FundsXpress, INC.

+

All rights reserved.

+
+

Export of this software from the United States of America may require +a specific license from the United States Government. It is the +responsibility of any person or organization contemplating export to +obtain such a license before exporting.

+
+

WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +distribute this software and its documentation for any purpose and +without fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation, and that +the name of FundsXpress. not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. FundsXpress makes no representations about the suitability of +this software for any purpose. It is provided “as is” without express +or implied warranty.

+

THIS SOFTWARE IS PROVIDED “AS IS” AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

+
+
+

The implementation of the AES encryption algorithm in +src/lib/crypto/builtin/aes has the following copyright:

+
+
+
Copyright © 1998-2013, Brian Gladman, Worcester, UK. All
+
rights reserved.
+
+

The redistribution and use of this software (with or without +changes) is allowed without the payment of fees or royalties +provided that:

+
+

source code distributions include the above copyright notice, +this list of conditions and the following disclaimer;

+

binary distributions include the above copyright notice, this +list of conditions and the following disclaimer in their +documentation.

+
+

This software is provided ‘as is’ with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose.

+
+
+

Portions contributed by Red Hat, including the pre-authentication +plug-in framework and the NSS crypto implementation, contain the +following copyright:

+
+
+
Copyright © 2006 Red Hat, Inc.
+
Portions copyright © 2006 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.

  • +
  • Neither the name of Red Hat, Inc., 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 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.

+
+
+

The bundled verto source code is subject to the following license:

+
+

Copyright 2011 Red Hat, Inc.

+

Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation files +(the “Software”), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, +and to permit persons to whom the Software is furnished to do so, +subject to the following conditions:

+

The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software.

+

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.

+
+
+

The MS-KKDCP client implementation has the following copyright:

+
+

Copyright 2013,2014 Red Hat, Inc.

+

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. +
  3. 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.

  4. +
+
+

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.

+
+
+

The implementations of GSSAPI mechglue in GSSAPI-SPNEGO in +src/lib/gssapi, including the following files:

+
lib/gssapi/generic/gssapi_err_generic.et
+lib/gssapi/mechglue/g_accept_sec_context.c
+lib/gssapi/mechglue/g_acquire_cred.c
+lib/gssapi/mechglue/g_canon_name.c
+lib/gssapi/mechglue/g_compare_name.c
+lib/gssapi/mechglue/g_context_time.c
+lib/gssapi/mechglue/g_delete_sec_context.c
+lib/gssapi/mechglue/g_dsp_name.c
+lib/gssapi/mechglue/g_dsp_status.c
+lib/gssapi/mechglue/g_dup_name.c
+lib/gssapi/mechglue/g_exp_sec_context.c
+lib/gssapi/mechglue/g_export_name.c
+lib/gssapi/mechglue/g_glue.c
+lib/gssapi/mechglue/g_imp_name.c
+lib/gssapi/mechglue/g_imp_sec_context.c
+lib/gssapi/mechglue/g_init_sec_context.c
+lib/gssapi/mechglue/g_initialize.c
+lib/gssapi/mechglue/g_inquire_context.c
+lib/gssapi/mechglue/g_inquire_cred.c
+lib/gssapi/mechglue/g_inquire_names.c
+lib/gssapi/mechglue/g_process_context.c
+lib/gssapi/mechglue/g_rel_buffer.c
+lib/gssapi/mechglue/g_rel_cred.c
+lib/gssapi/mechglue/g_rel_name.c
+lib/gssapi/mechglue/g_rel_oid_set.c
+lib/gssapi/mechglue/g_seal.c
+lib/gssapi/mechglue/g_sign.c
+lib/gssapi/mechglue/g_store_cred.c
+lib/gssapi/mechglue/g_unseal.c
+lib/gssapi/mechglue/g_userok.c
+lib/gssapi/mechglue/g_utils.c
+lib/gssapi/mechglue/g_verify.c
+lib/gssapi/mechglue/gssd_pname_to_uid.c
+lib/gssapi/mechglue/mglueP.h
+lib/gssapi/mechglue/oid_ops.c
+lib/gssapi/spnego/gssapiP_spnego.h
+lib/gssapi/spnego/spnego_mech.c
+
+
+

and the initial implementation of incremental propagation, including +the following new or changed files:

+
include/iprop_hdr.h
+kadmin/server/ipropd_svc.c
+lib/kdb/iprop.x
+lib/kdb/kdb_convert.c
+lib/kdb/kdb_log.c
+lib/kdb/kdb_log.h
+lib/krb5/error_tables/kdb5_err.et
+kprop/kpropd_rpc.c
+kprop/kproplog.c
+
+
+

are subject to the following license:

+
+

Copyright © 2004 Sun Microsystems, Inc.

+

Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +“Software”), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions:

+

The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software.

+

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+
+
+

Kerberos V5 includes documentation and software developed at the +University of California at Berkeley, which includes this copyright +notice:

+
+
+
Copyright © 1983 Regents of the University of California.
+
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. +
  3. 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.

  4. +
  5. Neither the name of the University nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission.

  6. +
+

THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.

+
+
+

Portions contributed by Novell, Inc., including the LDAP database +backend, are subject to the following license:

+
+
+
Copyright © 2004-2005, Novell, Inc.
+
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.

  • +
  • The copyright holder’s name is not 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.

+
+
+

Portions funded by Sandia National Laboratory +and developed by the University of Michigan’s +Center for Information Technology Integration, +including the PKINIT implementation, are subject +to the following license:

+
+
+
COPYRIGHT © 2006-2007
+
THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+
ALL RIGHTS RESERVED
+
+

Permission is granted to use, copy, create derivative works +and redistribute this software and such derivative works +for any purpose, so long as the name of The University of +Michigan is not used in any advertising or publicity +pertaining to the use of distribution of this software +without specific, written prior authorization. If the +above copyright notice or any other identification of the +University of Michigan is included in any copy of any +portion of this software, then the disclaimer below must +also be included.

+

THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION +FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY +PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF +MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING +WITHOUT LIMITATION THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE +REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE +FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR +CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING +OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN +IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES.

+
+
+

The pkcs11.h file included in the PKINIT code has the +following license:

+
+
+
Copyright 2006 g10 Code GmbH
+
Copyright 2006 Andreas Jellinghaus
+
+

This file is free software; as a special exception the author gives +unlimited permission to copy and/or distribute it, with or without +modifications, as long as this notice is preserved.

+

This file is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY, to the extent permitted by law; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE.

+
+
+

Portions contributed by Apple Inc. are subject to the following license:

+
+

Copyright 2004-2008 Apple Inc. All Rights Reserved.

+
+

Export of this software from the United States of America may require +a specific license from the United States Government. It is the +responsibility of any person or organization contemplating export to +obtain such a license before exporting.

+
+

WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +distribute this software and its documentation for any purpose and +without fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation, and that +the name of Apple Inc. not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. Apple Inc. makes no representations about the suitability of +this software for any purpose. It is provided “as is” without express +or implied warranty.

+

THIS SOFTWARE IS PROVIDED “AS IS” AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

+
+
+

The implementations of UTF-8 string handling in src/util/support and +src/lib/krb5/unicode are subject to the following copyright and +permission notice:

+
+
+
The OpenLDAP Public License
+
Version 2.8, 17 August 2003
+
+

Redistribution and use of this software and associated documentation +(“Software”), with or without modification, are permitted provided +that the following conditions are met:

+
    +
  1. Redistributions in source form must retain copyright statements +and notices,

  2. +
  3. Redistributions in binary form must reproduce applicable copyright +statements and notices, this list of conditions, and the following +disclaimer in the documentation and/or other materials provided +with the distribution, and

  4. +
  5. Redistributions must contain a verbatim copy of this document.

  6. +
+

The OpenLDAP Foundation may revise this license from time to time. +Each revision is distinguished by a version number. You may use +this Software under terms of this license revision or under the +terms of any subsequent revision of the license.

+

THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS +CONTRIBUTORS “AS IS” AND ANY EXPRESSED 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 OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S) +OR OWNER(S) OF THE SOFTWARE 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.

+

The names of the authors and copyright holders must not be used in +advertising or otherwise to promote the sale, use or other dealing +in this Software without specific, written prior permission. Title +to copyright in this Software shall at all times remain with copyright +holders.

+

OpenLDAP is a registered trademark of the OpenLDAP Foundation.

+

Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, +California, USA. All Rights Reserved. Permission to copy and +distribute verbatim copies of this document is granted.

+
+
+

Marked test programs in src/lib/krb5/krb have the following copyright:

+
+
+
Copyright © 2006 Kungliga Tekniska Högskola
+
(Royal Institute of Technology, Stockholm, Sweden).
+
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. +
  3. 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.

  4. +
  5. Neither the name of KTH nor the names of its contributors may be +used to endorse or promote products derived from this software without +specific prior written permission.

  6. +
+

THIS SOFTWARE IS PROVIDED BY KTH AND ITS 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 KTH OR ITS 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.

+
+
+

The KCM Mach RPC definition file used on macOS has the following copyright:

+
+
+
Copyright © 2009 Kungliga Tekniska Högskola
+
(Royal Institute of Technology, Stockholm, Sweden).
+
All rights reserved.
+
+

Portions Copyright © 2009 Apple Inc. 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. +
  3. 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.

  4. +
  5. 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.

  6. +
+

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.

+
+
+

Portions of the RPC implementation in src/lib/rpc and src/include/gssrpc +have the following copyright and permission notice:

+
+

Copyright © 2010, Oracle America, Inc.

+

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. +
  3. 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.

  4. +
  5. Neither the name of the “Oracle America, Inc.” nor the names of +its contributors may be used to endorse or promote products +derived from this software without specific prior written permission.

  6. +
+

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.

+
+
+
+

Copyright © 2006,2007,2009 +NTT (Nippon Telegraph and Telephone Corporation). 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 as +the first lines of this file unmodified.

  2. +
  3. 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.

  4. +
+

THIS SOFTWARE IS PROVIDED BY NTT “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 NTT 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.

+
+
+
+

Copyright 2000 by Carnegie Mellon University

+

All Rights Reserved

+

Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Carnegie Mellon +University not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission.

+

CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR +ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

+
+
+
+

Copyright © 2002 Naval Research Laboratory (NRL/CCS)

+

Permission to use, copy, modify and distribute this software and its +documentation is hereby granted, provided that both the copyright +notice and this permission notice appear in all copies of the software, +derivative works or modified versions, and any portions thereof.

+

NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS “AS IS” CONDITION AND +DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER +RESULTING FROM THE USE OF THIS SOFTWARE.

+
+
+
+

Copyright © 2022 United States Government as represented by the +Secretary of the Navy. 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.

+
+
+
+

Copyright © 1991, 1992, 1994 by Cygnus Support.

+

Permission to use, copy, modify, and +distribute this software and its documentation for any purpose and +without fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation. +Cygnus Support makes no representations about the suitability of +this software for any purpose. It is provided “as is” without express +or implied warranty.

+
+
+
+

Copyright © 2006 Secure Endpoints Inc.

+

Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the “Software”), to deal in the Software without +restriction, including without limitation the rights to use, copy, +modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions:

+

The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software.

+

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.

+
+
+
+

Copyright © 1994 by the University of Southern California

+
+

EXPORT OF THIS SOFTWARE from the United States of America may +require a specific license from the United States Government. +It is the responsibility of any person or organization contemplating +export to obtain such a license before exporting.

+
+

WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute +this software and its documentation in source and binary forms is +hereby granted, provided that any documentation or other materials +related to such distribution or use acknowledge that the software +was developed by the University of Southern California.

+

DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED “AS IS”. The +University of Southern California MAKES NO REPRESENTATIONS OR +WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not +limitation, the University of Southern California MAKES NO +REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY +PARTICULAR PURPOSE. The University of Southern +California shall not be held liable for any liability nor for any +direct, indirect, or consequential damages with respect to any +claim by the user or distributor of the ksu software.

+
+
+
+
+
Copyright © 1995
+
The President and Fellows of Harvard University
+
+

This code is derived from software contributed to Harvard by +Jeremy Rassen.

+

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. +
  3. 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.

  4. +
  5. All advertising materials mentioning features or use of this software +must display the following acknowledgement:

    +
    +

    This product includes software developed by the University of +California, Berkeley and its contributors.

    +
    +
  6. +
  7. Neither the name of the University nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission.

  8. +
+

THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.

+
+
+
+
+
Copyright © 2008 by the Massachusetts Institute of Technology.
+
Copyright 1995 by Richard P. Basch. All Rights Reserved.
+
Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved.
+
+
+

Export of this software from the United States of America may +require a specific license from the United States Government. +It is the responsibility of any person or organization contemplating +export to obtain such a license before exporting.

+
+

WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +distribute this software and its documentation for any purpose and +without fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation, and that +the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used +in advertising or publicity pertaining to distribution of the software +without specific, written prior permission. Richard P. Basch, +Lehman Brothers and M.I.T. make no representations about the suitability +of this software for any purpose. It is provided “as is” without +express or implied warranty.

+
+
+

The following notice applies to src/lib/krb5/krb/strptime.c and +src/include/k5-queue.h.

+
+
+
Copyright © 1997, 1998 The NetBSD Foundation, Inc.
+
All rights reserved.
+
+

This code was contributed to The NetBSD Foundation by Klaus Klein.

+

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. +
  3. 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.

  4. +
  5. All advertising materials mentioning features or use of this software +must display the following acknowledgement:

    +
    +

    This product includes software developed by the NetBSD +Foundation, Inc. and its contributors.

    +
    +
  6. +
  7. Neither the name of The NetBSD Foundation nor the names of its +contributors may be used to endorse or promote products derived +from this software without specific prior written permission.

  8. +
+

THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.

+
+
+

The following notice applies to Unicode library files in +src/lib/krb5/unicode:

+
+
+
Copyright 1997, 1998, 1999 Computing Research Labs,
+
New Mexico State University
+
+

Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the “Software”), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions:

+

The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software.

+

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT +OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+
+
+

The following notice applies to src/util/support/strlcpy.c:

+
+

Copyright © 1998 Todd C. Miller Todd.Miller@courtesan.com

+

Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies.

+

THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

+
+
+

The following notice applies to src/util/profile/argv_parse.c and +src/util/profile/argv_parse.h:

+
+

Copyright 1999 by Theodore Ts’o.

+

Permission to use, copy, modify, and distribute this software for +any purpose with or without fee is hereby granted, provided that +the above copyright notice and this permission notice appear in all +copies. THE SOFTWARE IS PROVIDED “AS IS” AND THEODORE TS’O (THE +AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER +RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (Isn’t +it sick that the U.S. culture of lawsuit-happy lawyers requires +this kind of disclaimer?)

+
+
+

The following notice applies to portiions of src/lib/rpc and +src/include/gssrpc:

+
+

Copyright © 2000 The Regents of the University of Michigan. +All rights reserved.

+

Copyright © 2000 Dug Song dugsong@UMICH.EDU. +All rights reserved, all wrongs reversed.

+

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. +
  3. 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.

  4. +
  5. Neither the name of the University nor the names of its +contributors may be used to endorse or promote products derived +from this software without specific prior written permission.

  6. +
+

THIS SOFTWARE IS PROVIDED “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 REGENTS 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.

+
+
+

Implementations of the MD4 algorithm are subject to the following +notice:

+
+

Copyright © 1990, RSA Data Security, Inc. All rights reserved.

+

License to copy and use this software is granted provided that +it is identified as the “RSA Data Security, Inc. MD4 Message +Digest Algorithm” in all material mentioning or referencing this +software or this function.

+

License is also granted to make and use derivative works +provided that such works are identified as “derived from the RSA +Data Security, Inc. MD4 Message Digest Algorithm” in all +material mentioning or referencing the derived work.

+

RSA Data Security, Inc. makes no representations concerning +either the merchantability of this software or the suitability +of this software for any particular purpose. It is provided “as +is” without express or implied warranty of any kind.

+

These notices must be retained in any copies of any part of this +documentation and/or software.

+
+
+

Implementations of the MD5 algorithm are subject to the following +notice:

+
+

Copyright © 1990, RSA Data Security, Inc. All rights reserved.

+

License to copy and use this software is granted provided that +it is identified as the “RSA Data Security, Inc. MD5 Message- +Digest Algorithm” in all material mentioning or referencing this +software or this function.

+

License is also granted to make and use derivative works +provided that such works are identified as “derived from the RSA +Data Security, Inc. MD5 Message-Digest Algorithm” in all +material mentioning or referencing the derived work.

+

RSA Data Security, Inc. makes no representations concerning +either the merchantability of this software or the suitability +of this software for any particular purpose. It is provided “as +is” without express or implied warranty of any kind.

+

These notices must be retained in any copies of any part of this +documentation and/or software.

+
+
+

The following notice applies to src/lib/crypto/crypto_tests/t_mddriver.c:

+
+

Copyright © 1990-2, RSA Data Security, Inc. Created 1990. All +rights reserved.

+

RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided “as is” +without express or implied warranty of any kind.

+

These notices must be retained in any copies of any part of this +documentation and/or software.

+
+
+

Portions of src/lib/krb5 are subject to the following notice:

+
+
+
Copyright © 1994 CyberSAFE Corporation.
+
Copyright 1990,1991,2007,2008 by the Massachusetts +Institute of Technology.
+
All Rights Reserved.
+
+
+

Export of this software from the United States of America may +require a specific license from the United States Government. +It is the responsibility of any person or organization contemplating +export to obtain such a license before exporting.

+
+

WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +distribute this software and its documentation for any purpose and +without fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation, and that +the name of M.I.T. not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. Furthermore if you modify this software you must label +your software as modified software and not distribute it in such a +fashion that it might be confused with the original M.I.T. software. +Neither M.I.T., the Open Computing Security Group, nor +CyberSAFE Corporation make any representations about the suitability of +this software for any purpose. It is provided “as is” without express +or implied warranty.

+
+
+

Portions contributed by PADL Software are subject to the following +license:

+
+

Copyright (c) 2011, PADL Software Pty Ltd. +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. +
  3. 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.

  4. +
  5. Neither the name of PADL Software nor the names of its contributors +may be used to endorse or promote products derived from this software +without specific prior written permission.

  6. +
+

THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE 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 PADL SOFTWARE 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.

+
+
+

The bundled libev source code is subject to the following license:

+
+

All files in libev are Copyright (C)2007,2008,2009 Marc Alexander Lehmann.

+

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 +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.

+

Alternatively, the contents of this package may be used under the terms +of the GNU General Public License (“GPL”) version 2 or any later version, +in which case the provisions of the GPL are applicable instead of the +above. If you wish to allow the use of your version of this package only +under the terms of the GPL and not to allow others to use your version of +this file under the BSD license, indicate your decision by deleting the +provisions above and replace them with the notice and other provisions +required by the GPL in this and the other files of this package. If you do +not delete the provisions above, a recipient may use your version of this +file under either the BSD or the GPL.

+
+
+

Files copied from the Intel AESNI Sample Library are subject to the +following license:

+
+

Copyright © 2010, Intel Corporation +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 Intel Corporation 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 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.

+
+
+

The following notice applies to +src/ccapi/common/win/OldCC/autolock.hxx:

+
+

Copyright (C) 1998 by Danilo Almeida. 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.

+
+
+

The following notice applies to portions of +src/plugins/preauth/spake/edwards25519.c and +src/plugins/preauth/spake/edwards25519_tables.h:

+

The MIT License (MIT)

+

Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file).

+

Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions:

+

The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software.

+

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE.

+
+

The following notice applies to portions of +src/plugins/preauth/spake/edwards25519.c:

+

Copyright (c) 2015-2016, Google Inc.

+

Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies.

+

THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/objects.inv b/krb5-1.21.3/doc/html/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..002ef306660d6b5817a87c1274c59000222c0c21 GIT binary patch literal 49033 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
h|auh;-_VDoWjgoW0+}I*s4TDUIp? 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 literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/doc/html/plugindev/ccselect.html b/krb5-1.21.3/doc/html/plugindev/ccselect.html new file mode 100644 index 00000000..bd694cbb --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/ccselect.html @@ -0,0 +1,160 @@ + + + + + + + + + Credential cache selection interface (ccselect) — MIT Kerberos Documentation + + + + + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+

Credential cache selection interface (ccselect)

+

The ccselect interface allows modules to control how credential caches +are chosen when a GSSAPI client contacts a service. For a detailed +description of the ccselect interface, see the header file +<krb5/ccselect_plugin.h>.

+

The primary ccselect method is choose, which accepts a server +principal as input and returns a ccache and/or principal name as +output. A module can use the krb5_cccol APIs to iterate over the +cache collection in order to find an appropriate ccache to use.

+

A module can create and destroy per-library-context state objects by +implementing the init and fini methods. State objects have +the type krb5_ccselect_moddata, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object.

+

A module can have one of two priorities, “authoritative” or +“heuristic”. Results from authoritative modules, if any are +available, will take priority over results from heuristic modules. A +module communicates its priority as a result of the init method.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/certauth.html b/krb5-1.21.3/doc/html/plugindev/certauth.html new file mode 100644 index 00000000..881f7489 --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/certauth.html @@ -0,0 +1,170 @@ + + + + + + + + + PKINIT certificate authorization interface (certauth) — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

PKINIT certificate authorization interface (certauth)

+

The certauth interface was first introduced in release 1.16. It +allows customization of the X.509 certificate attribute requirements +placed on certificates used by PKINIT enabled clients. For a detailed +description of the certauth interface, see the header file +<krb5/certauth_plugin.h>

+

A certauth module implements the authorize method to determine +whether a client’s certificate is authorized to authenticate a client +principal. authorize receives the DER-encoded certificate, the +requested client principal, and a pointer to the client’s +krb5_db_entry (for modules that link against libkdb5). The method +must decode the certificate and inspect its attributes to determine if +it should authorize PKINIT authentication. It returns the +authorization status and optionally outputs a list of authentication +indicator strings to be added to the ticket.

+

Beginning in release 1.19, the authorize method can request that the +hardware authentication bit be set in the ticket by returning +KRB5_CERTAUTH_HWAUTH. Beginning in release 1.20, the authorize +method can return KRB5_CERTAUTH_HWAUTH_PASS to request that the +hardware authentication bit be set in the ticket but otherwise defer +authorization to another certauth module. A module must use its own +internal or library-provided ASN.1 certificate decoder.

+

A module can optionally create and destroy module data with the +init and fini methods. Module data objects last for the +lifetime of the KDC process.

+

If a module allocates and returns a list of authentication indicators +from authorize, it must also implement the free_ind method +to free the list.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/clpreauth.html b/krb5-1.21.3/doc/html/plugindev/clpreauth.html new file mode 100644 index 00000000..cd008ab9 --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/clpreauth.html @@ -0,0 +1,187 @@ + + + + + + + + + Client preauthentication interface (clpreauth) — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Client preauthentication interface (clpreauth)

+

During an initial ticket request, a KDC may ask a client to prove its +knowledge of the password before issuing an encrypted ticket, or to +use credentials other than a password. This process is called +preauthentication, and is described in RFC 4120 and RFC 6113. +The clpreauth interface allows the addition of client support for +preauthentication mechanisms beyond those included in the core MIT +krb5 code base. For a detailed description of the clpreauth +interface, see the header file <krb5/clpreauth_plugin.h> (or +<krb5/preauth_plugin.h> before release 1.12).

+

A clpreauth module is generally responsible for:

+
    +
  • Supplying a list of preauth type numbers used by the module in the +pa_type_list field of the vtable structure.

  • +
  • Indicating what kind of preauthentication mechanism it implements, +with the flags method. In the most common case, this method +just returns PA_REAL, indicating that it implements a normal +preauthentication type.

  • +
  • Examining the padata information included in a PREAUTH_REQUIRED or +MORE_PREAUTH_DATA_REQUIRED error and producing padata values for the +next AS request. This is done with the process method.

  • +
  • Examining the padata information included in a successful ticket +reply, possibly verifying the KDC identity and computing a reply +key. This is also done with the process method.

  • +
  • For preauthentication types which support it, recovering from errors +by examining the error data from the KDC and producing a padata +value for another AS request. This is done with the tryagain +method.

  • +
  • Receiving option information (supplied by kinit -X or by an +application), with the gic_opts method.

  • +
+

A clpreauth module can create and destroy per-library-context and +per-request state objects by implementing the init, fini, +request_init, and request_fini methods. Per-context state +objects have the type krb5_clpreauth_moddata, and per-request state +objects have the type krb5_clpreauth_modreq. These are abstract +pointer types; a module should typically cast these to internal +types for the state objects.

+

The process and tryagain methods have access to a callback +function and handle (called a “rock”) which can be used to get +additional information about the current request, including the +expected enctype of the AS reply, the FAST armor key, and the client +long-term key (prompting for the user password if necessary). A +callback can also be used to replace the AS reply key if the +preauthentication mechanism computes one.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/general.html b/krb5-1.21.3/doc/html/plugindev/general.html new file mode 100644 index 00000000..35c1ce70 --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/general.html @@ -0,0 +1,242 @@ + + + + + + + + + General plugin concepts — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

General plugin concepts

+

A krb5 dynamic plugin module is a Unix shared object or Windows DLL. +Typically, the source code for a dynamic plugin module should live in +its own project with a build system using automake and libtool, or +tools with similar functionality.

+

A plugin module must define a specific symbol name, which depends on +the pluggable interface and module name. For most pluggable +interfaces, the exported symbol is a function named +INTERFACE_MODULE_initvt, where INTERFACE is the name of the +pluggable interface and MODULE is the name of the module. For these +interfaces, it is possible for one shared object or DLL to implement +multiple plugin modules, either for the same pluggable interface or +for different ones. For example, a shared object could implement both +KDC and client preauthentication mechanisms, by exporting functions +named kdcpreauth_mymech_initvt and clpreauth_mymech_initvt.

+

A plugin module implementation should include the header file +<krb5/INTERFACE_plugin.h>, where INTERFACE is the name of the +pluggable interface. For instance, a ccselect plugin module +implementation should use #include <krb5/ccselect_plugin.h>.

+

initvt functions have the following prototype:

+
krb5_error_code interface_modname_initvt(krb5_context context,
+                                         int maj_ver, int min_ver,
+                                         krb5_plugin_vtable vtable);
+
+
+

and should do the following:

+
    +
  1. Check that the supplied maj_ver argument is supported by the +module. If it is not supported, the function should return +KRB5_PLUGIN_VER_NOTSUPP.

  2. +
  3. Cast the supplied vtable pointer to the structure type +corresponding to the major version, as documented in the pluggable +interface header file.

  4. +
  5. Fill in the structure fields with pointers to method functions and +static data, stopping at the field indicated by the supplied minor +version. Fields for unimplemented optional methods can be left +alone; it is not necessary to initialize them to NULL.

  6. +
+

In most cases, the context argument will not be used. The initvt +function should not allocate memory; think of it as a glorified +structure initializer. Each pluggable interface defines methods for +allocating and freeing module state if doing so is necessary for the +interface.

+

Pluggable interfaces typically include a name field in the vtable +structure, which should be filled in with a pointer to a string +literal containing the module name.

+

Here is an example of what an initvt function might look like for a +fictional pluggable interface named fences, for a module named +“wicker”:

+
krb5_error_code
+fences_wicker_initvt(krb5_context context, int maj_ver,
+                     int min_ver, krb5_plugin_vtable vtable)
+{
+    krb5_ccselect_vtable vt;
+
+    if (maj_ver == 1) {
+        krb5_fences_vtable vt = (krb5_fences_vtable)vtable;
+        vt->name = "wicker";
+        vt->slats = wicker_slats;
+        vt->braces = wicker_braces;
+    } else if (maj_ver == 2) {
+        krb5_fences_vtable_v2 vt = (krb5_fences_vtable_v2)vtable;
+        vt->name = "wicker";
+        vt->material = wicker_material;
+        vt->construction = wicker_construction;
+        if (min_ver < 2)
+            return 0;
+        vt->footing = wicker_footing;
+        if (min_ver < 3)
+            return 0;
+        vt->appearance = wicker_appearance;
+    } else {
+        return KRB5_PLUGIN_VER_NOTSUPP;
+    }
+    return 0;
+}
+
+
+
+

Logging from KDC and kadmind plugin modules

+

Plugin modules for the KDC or kadmind daemons can write to the +configured logging outputs (see [logging]) by calling the +com_err function. The first argument (whoami) is ignored. If +the second argument (code) is zero, the formatted message is logged +at informational severity; otherwise, the formatted message is logged +at error severity and includes the error message for the supplied +code. Here are examples:

+
com_err("", 0, "Client message contains %d items", nitems);
+com_err("", retval, "while decoding client message");
+
+
+

(The behavior described above is new in release 1.17. In prior +releases, the whoami argument is included for some logging output +types, the logged message does not include the usual header for some +output types, and the severity for syslog outputs is configured as +part of the logging specification, defaulting to error severity.)

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/gssapi.html b/krb5-1.21.3/doc/html/plugindev/gssapi.html new file mode 100644 index 00000000..95db08fb --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/gssapi.html @@ -0,0 +1,259 @@ + + + + + + + + + GSSAPI mechanism interface — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

GSSAPI mechanism interface

+

The GSSAPI library in MIT krb5 can load mechanism modules to augment +the set of built-in mechanisms.

+

A mechanism module is a Unix shared object or Windows DLL, built +separately from the krb5 tree. Modules are loaded according to the +GSS mechanism config files described in GSSAPI mechanism modules.

+

For the most part, a GSSAPI mechanism module exports the same +functions as would a GSSAPI implementation itself, with the same +function signatures. The mechanism selection layer within the GSSAPI +library (called the “mechglue”) will dispatch calls from the +application to the module if the module’s mechanism is requested. If +a module does not wish to implement a GSSAPI extension, it can simply +refrain from exporting it, and the mechglue will fail gracefully if +the application calls that function.

+

The mechglue does not invoke a module’s gss_add_cred, +gss_add_cred_from, gss_add_cred_impersonate_name, or +gss_add_cred_with_password function. A mechanism only needs to +implement the “acquire” variants of those functions.

+

A module does not need to coordinate its minor status codes with those +of other mechanisms. If the mechglue detects conflicts, it will map +the mechanism’s status codes onto unique values, and then map them +back again when gss_display_status is called.

+
+

NegoEx modules

+

Some Windows GSSAPI mechanisms can only be negotiated via a Microsoft +extension to SPNEGO called NegoEx. Beginning with release 1.18, +mechanism modules can support NegoEx as follows:

+
    +
  • Implement the gssspi_query_meta_data(), gssspi_exchange_meta_data(), +and gssspi_query_mechanism_info() SPIs declared in +<gssapi/gssapi_ext.h>.

  • +
  • Implement gss_inquire_sec_context_by_oid() and answer the +GSS_C_INQ_NEGOEX_KEY and GSS_C_INQ_NEGOEX_VERIFY_KEY OIDs +to provide the checksum keys for outgoing and incoming checksums, +respectively. The answer must be in two buffers: the first buffer +contains the key contents, and the second buffer contains the key +encryption type as a four-byte little-endian integer.

  • +
+

By default, NegoEx mechanisms will not be directly negotiated via +SPNEGO. If direct SPNEGO negotiation is required for +interoperability, implement gss_inquire_attrs_for_mech() and assert +the GSS_C_MA_NEGOEX_AND_SPNEGO attribute (along with any applicable +RFC 5587 attributes).

+
+
+

Interposer modules

+

The mechglue also supports a kind of loadable module, called an +interposer module, which intercepts calls to existing mechanisms +rather than implementing a new mechanism.

+

An interposer module must export the symbol gss_mech_interposer +with the following signature:

+
gss_OID_set gss_mech_interposer(gss_OID mech_type);
+
+
+

This function is invoked with the OID of the interposer mechanism as +specified in the mechanism config file, and returns a set of mechanism +OIDs to be interposed. The returned OID set must have been created +using the mechglue’s gss_create_empty_oid_set and +gss_add_oid_set_member functions.

+

An interposer module must use the prefix gssi_ for the GSSAPI +functions it exports, instead of the prefix gss_. In most cases, +unexported gssi_ functions will result in failure from their +corresponding gss_ calls.

+

An interposer module can link against the GSSAPI library in order to +make calls to the original mechanism. To do so, it must specify a +special mechanism OID which is the concatention of the interposer’s +own OID byte string and the original mechanism’s OID byte string.

+

Functions that do not accept a mechanism argument directly require no +special handling, with the following exceptions:

+

Since gss_accept_sec_context does not accept a mechanism argument, +an interposer mechanism must, in order to invoke the original +mechanism’s function, acquire a credential for the concatenated OID +and pass that as the verifier_cred_handle parameter.

+

Since gss_import_name, gss_import_cred, and +gss_import_sec_context do not accept mechanism parameters, the SPI +has been extended to include variants which do. This allows the +interposer module to know which mechanism should be used to interpret +the token. These functions have the following signatures:

+
OM_uint32 gssi_import_sec_context_by_mech(OM_uint32 *minor_status,
+    gss_OID desired_mech, gss_buffer_t interprocess_token,
+    gss_ctx_id_t *context_handle);
+
+OM_uint32 gssi_import_name_by_mech(OM_uint32 *minor_status,
+    gss_OID mech_type, gss_buffer_t input_name_buffer,
+    gss_OID input_name_type, gss_name_t output_name);
+
+OM_uint32 gssi_import_cred_by_mech(OM_uint32 *minor_status,
+    gss_OID mech_type, gss_buffer_t token,
+    gss_cred_id_t *cred_handle);
+
+
+

To re-enter the original mechanism when importing tokens for the above +functions, the interposer module must wrap the mechanism token in the +mechglue’s format, using the concatenated OID (except in +gss_import_name). The mechglue token formats are:

+
    +
  • For gss_import_sec_context, a four-byte OID length in big-endian +order, followed by the concatenated OID, followed by the mechanism +token.

  • +
  • For gss_import_name, the bytes 04 01, followed by a two-byte OID +length in big-endian order, followed by the mechanism OID, followed +by a four-byte token length in big-endian order, followed by the +mechanism token. Unlike most uses of OIDs in the API, the mechanism +OID encoding must include the DER tag and length for an object +identifier (06 followed by the DER length of the OID byte string), +and this prefix must be included in the two-byte OID length. +input_name_type must also be set to GSS_C_NT_EXPORT_NAME.

  • +
  • For gss_import_cred, a four-byte OID length in big-endian order, +followed by the concatenated OID, followed by a four-byte token +length in big-endian order, followed by the mechanism token. This +sequence may be repeated multiple times.

  • +
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/hostrealm.html b/krb5-1.21.3/doc/html/plugindev/hostrealm.html new file mode 100644 index 00000000..d7d1840b --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/hostrealm.html @@ -0,0 +1,170 @@ + + + + + + + + + Host-to-realm interface (hostrealm) — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Host-to-realm interface (hostrealm)

+

The host-to-realm interface was first introduced in release 1.12. It +allows modules to control the local mapping of hostnames to realm +names as well as the default realm. For a detailed description of the +hostrealm interface, see the header file +<krb5/hostrealm_plugin.h>.

+

Although the mapping methods in the hostrealm interface return a list +of one or more realms, only the first realm in the list is currently +used by callers. Callers may begin using later responses in the +future.

+

Any mapping method may return KRB5_PLUGIN_NO_HANDLE to defer +processing to a later module.

+

A module can create and destroy per-library-context state objects +using the init and fini methods. If the module does not need +any state, it does not need to implement these methods.

+

The optional host_realm method allows a module to determine +authoritative realm mappings for a hostname. The first authoritative +mapping is used in preference to KDC referrals when getting service +credentials.

+

The optional fallback_realm method allows a module to determine +fallback mappings for a hostname. The first fallback mapping is tried +if there is no authoritative mapping for a realm, and KDC referrals +failed to produce a successful result.

+

The optional default_realm method allows a module to determine the +local default realm.

+

If a module implements any of the above methods, it must also +implement free_list to ensure that memory is allocated and +deallocated consistently.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/index.html b/krb5-1.21.3/doc/html/plugindev/index.html new file mode 100644 index 00000000..b10153cb --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/index.html @@ -0,0 +1,185 @@ + + + + + + + + + For plugin module developers — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+ + +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/internal.html b/krb5-1.21.3/doc/html/plugindev/internal.html new file mode 100644 index 00000000..c6dfca91 --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/internal.html @@ -0,0 +1,171 @@ + + + + + + + + + Internal pluggable interfaces — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Internal pluggable interfaces

+

Following are brief discussions of pluggable interfaces which have not +yet been made public. These interfaces are functional, but the +interfaces are likely to change in incompatible ways from release to +release. In some cases, it may be necessary to copy header files from +the krb5 source tree to use an internal interface. Use these with +care, and expect to need to update your modules for each new release +of MIT krb5.

+
+

Kerberos database interface (KDB)

+

A KDB module implements a database back end for KDC principal and +policy information, and can also control many aspects of KDC behavior. +For a full description of the interface, see the header file +<kdb.h>.

+

The KDB pluggable interface is often referred to as the DAL (Database +Access Layer).

+
+
+

Authorization data interface (authdata)

+

The authdata interface allows a module to provide (from the KDC) or +consume (in application servers) authorization data of types beyond +those handled by the core MIT krb5 code base. The interface is +defined in the header file <krb5/authdata_plugin.h>, which is not +installed by the build.

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/kadm5_auth.html b/krb5-1.21.3/doc/html/plugindev/kadm5_auth.html new file mode 100644 index 00000000..da95cd89 --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/kadm5_auth.html @@ -0,0 +1,169 @@ + + + + + + + + + kadmin authorization interface (kadm5_auth) — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kadmin authorization interface (kadm5_auth)

+

The kadm5_auth interface (new in release 1.16) allows modules to +determine whether a client principal is authorized to perform an +operation in the kadmin protocol, and to apply restrictions to +principal operations. For a detailed description of the kadm5_auth +interface, see the header file <krb5/kadm5_auth_plugin.h>.

+

A module can create and destroy per-process state objects by +implementing the init and fini methods. State objects have +the type kadm5_auth_modinfo, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object.

+

The kadm5_auth interface has one method for each kadmin operation, +with parameters specific to the operation. Each method can return +either 0 to authorize access, KRB5_PLUGIN_NO_HANDLE to defer the +decision to other modules, or another error (canonically EPERM) to +authoritatively deny access. Access is granted if at least one module +grants access and no module authoritatively denies access.

+

The addprinc and modprinc methods can also impose restrictions +on the principal operation by returning a struct +kadm5_auth_restrictions object. The module should also implement +the free_restrictions method if it dynamically allocates +restrictions objects for principal operations.

+

kadm5_auth modules can optionally inspect principal or policy objects. +To do this, the module must also include <kadm5/admin.h> to gain +access to the structure definitions for those objects. As the kadmin +interface is explicitly not as stable as other public interfaces, +modules which do this may not retain compatibility across releases.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/kadm5_hook.html b/krb5-1.21.3/doc/html/plugindev/kadm5_hook.html new file mode 100644 index 00000000..bcba2445 --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/kadm5_hook.html @@ -0,0 +1,162 @@ + + + + + + + + + KADM5 hook interface (kadm5_hook) — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

KADM5 hook interface (kadm5_hook)

+

The kadm5_hook interface allows modules to perform actions when +changes are made to the Kerberos database through kadmin. +For a detailed description of the kadm5_hook interface, see the header +file <krb5/kadm5_hook_plugin.h>.

+

The kadm5_hook interface has five primary methods: chpass, +create, modify, remove, and rename. (The rename +method was introduced in release 1.14.) Each of these methods is +called twice when the corresponding administrative action takes place, +once before the action is committed and once afterwards. A module can +prevent the action from taking place by returning an error code during +the pre-commit stage.

+

A module can create and destroy per-process state objects by +implementing the init and fini methods. State objects have +the type kadm5_hook_modinfo, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object.

+

Because the kadm5_hook interface is tied closely to the kadmin +interface (which is explicitly unstable), it may not remain as stable +across versions as other public pluggable interfaces.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/kdcpolicy.html b/krb5-1.21.3/doc/html/plugindev/kdcpolicy.html new file mode 100644 index 00000000..5e93921f --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/kdcpolicy.html @@ -0,0 +1,160 @@ + + + + + + + + + KDC policy interface (kdcpolicy) — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

KDC policy interface (kdcpolicy)

+

The kdcpolicy interface was first introduced in release 1.16. It +allows modules to veto otherwise valid AS and TGS requests or restrict +the lifetime and renew time of the resulting ticket. For a detailed +description of the kdcpolicy interface, see the header file +<krb5/kdcpolicy_plugin.h>.

+

The optional check_as and check_tgs functions allow the module +to perform access control. Additionally, a module can create and +destroy module data with the init and fini methods. Module +data objects last for the lifetime of the KDC process, and are +provided to all other methods. The data has the type +krb5_kdcpolicy_moddata, which should be cast to the appropriate +internal type.

+

kdcpolicy modules can optionally inspect principal entries. To do +this, the module must also include <kdb.h> to gain access to the +principal entry structure definition. As the KDB interface is +explicitly not as stable as other public interfaces, modules which do +this may not retain compatibility across releases.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/kdcpreauth.html b/krb5-1.21.3/doc/html/plugindev/kdcpreauth.html new file mode 100644 index 00000000..294aedc9 --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/kdcpreauth.html @@ -0,0 +1,207 @@ + + + + + + + + + KDC preauthentication interface (kdcpreauth) — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

KDC preauthentication interface (kdcpreauth)

+

The kdcpreauth interface allows the addition of KDC support for +preauthentication mechanisms beyond those included in the core MIT +krb5 code base. For a detailed description of the kdcpreauth +interface, see the header file <krb5/kdcpreauth_plugin.h> (or +<krb5/preauth_plugin.h> before release 1.12).

+

A kdcpreauth module is generally responsible for:

+
    +
  • Supplying a list of preauth type numbers used by the module in the +pa_type_list field of the vtable structure.

  • +
  • Indicating what kind of preauthentication mechanism it implements, +with the flags method. If the mechanism computes a new reply +key, it must specify the PA_REPLACES_KEY flag. If the mechanism +is generally only used with hardware tokens, the PA_HARDWARE +flag allows the mechanism to work with principals which have the +requires_hwauth flag set.

  • +
  • Producing a padata value to be sent with a preauth_required error, +with the edata method.

  • +
  • Examining a padata value sent by a client and verifying that it +proves knowledge of the appropriate client credential information. +This is done with the verify method.

  • +
  • Producing a padata response value for the client, and possibly +computing a reply key. This is done with the return_padata +method.

  • +
+

A module can create and destroy per-KDC state objects by implementing +the init and fini methods. Per-KDC state objects have the +type krb5_kdcpreauth_moddata, which is an abstract pointer types. A +module should typically cast this to an internal type for the state +object.

+

A module can create a per-request state object by returning one in the +verify method, receiving it in the return_padata method, and +destroying it in the free_modreq method. Note that these state +objects only apply to the processing of a single AS request packet, +not to an entire authentication exchange (since an authentication +exchange may remain unfinished by the client or may involve multiple +different KDC hosts). Per-request state objects have the type +krb5_kdcpreauth_modreq, which is an abstract pointer type.

+

The edata, verify, and return_padata methods have access +to a callback function and handle (called a “rock”) which can be used +to get additional information about the current request, including the +maximum allowable clock skew, the client’s long-term keys, the +DER-encoded request body, the FAST armor key, string attributes on the +client’s database entry, and the client’s database entry itself. The +verify method can assert one or more authentication indicators to +be included in the issued ticket using the add_auth_indicator +callback (new in release 1.14).

+

A module can generate state information to be included with the next +client request using the set_cookie callback (new in release +1.14). On the next request, the module can read this state +information using the get_cookie callback. Cookie information is +encrypted, timestamped, and transmitted to the client in a +PA-FX-COOKIE pa-data item. Older clients may not support cookies +and therefore may not transmit the cookie in the next request; in this +case, get_cookie will not yield the saved information.

+

If a module implements a mechanism which requires multiple round +trips, its verify method can respond with the code +KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED and a list of pa-data in +the e_data parameter to be processed by the client.

+

The edata and verify methods can be implemented +asynchronously. Because of this, they do not return values directly +to the caller, but must instead invoke responder functions with their +results. A synchronous implementation can invoke the responder +function immediately. An asynchronous implementation can use the +callback to get an event context for use with the libverto API.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/localauth.html b/krb5-1.21.3/doc/html/plugindev/localauth.html new file mode 100644 index 00000000..07321c6b --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/localauth.html @@ -0,0 +1,176 @@ + + + + + + + + + Local authorization interface (localauth) — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Local authorization interface (localauth)

+

The localauth interface was first introduced in release 1.12. It +allows modules to control the relationship between Kerberos principals +and local system accounts. When an application calls +krb5_kuserok() or krb5_aname_to_localname(), localauth +modules are consulted to determine the result. For a detailed +description of the localauth interface, see the header file +<krb5/localauth_plugin.h>.

+

A module can create and destroy per-library-context state objects +using the init and fini methods. If the module does not need +any state, it does not need to implement these methods.

+

The optional userok method allows a module to control the behavior +of krb5_kuserok(). The module receives the authenticated name +and the local account name as inputs, and can return either 0 to +authorize access, KRB5_PLUGIN_NO_HANDLE to defer the decision to other +modules, or another error (canonically EPERM) to authoritatively deny +access. Access is granted if at least one module grants access and no +module authoritatively denies access.

+

The optional an2ln method can work in two different ways. If the +module sets an array of uppercase type names in an2ln_types, then +the module’s an2ln method will only be invoked by +krb5_aname_to_localname() if an auth_to_local value in +krb5.conf refers to one of the module’s types. In this +case, the type and residual arguments will give the type name and +residual string of the auth_to_local value.

+

If the module does not set an2ln_types but does implement +an2ln, the module’s an2ln method will be invoked for all +krb5_aname_to_localname() operations unless an earlier module +determines a mapping, with type and residual set to NULL. The +module can return KRB5_LNAME_NO_TRANS to defer mapping to later +modules.

+

If a module implements an2ln, it must also implement +free_string to ensure that memory is allocated and deallocated +consistently.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/locate.html b/krb5-1.21.3/doc/html/plugindev/locate.html new file mode 100644 index 00000000..c17cc6ee --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/locate.html @@ -0,0 +1,165 @@ + + + + + + + + + Server location interface (locate) — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Server location interface (locate)

+

The locate interface allows modules to control how KDCs and similar +services are located by clients. For a detailed description of the +ccselect interface, see the header file <krb5/locate_plugin.h>.

+

A locate module exports a structure object of type +krb5plugin_service_locate_ftable, with the name service_locator. +The structure contains a minor version and pointers to the module’s +methods.

+

The primary locate method is lookup, which accepts a service type, +realm name, desired socket type, and desired address family (which +will be AF_UNSPEC if no specific address family is desired). The +method should invoke the callback function once for each server +address it wants to return, passing a socket type (SOCK_STREAM for TCP +or SOCK_DGRAM for UDP) and socket address. The lookup method +should return 0 if it has authoritatively determined the server +addresses for the realm, KRB5_PLUGIN_NO_HANDLE if it wants to let +other location mechanisms determine the server addresses, or another +code if it experienced a failure which should abort the location +process.

+

A module can create and destroy per-library-context state objects by +implementing the init and fini methods. State objects have +the type void *, and should be cast to an internal type for the state +object.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/profile.html b/krb5-1.21.3/doc/html/plugindev/profile.html new file mode 100644 index 00000000..beef56c0 --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/profile.html @@ -0,0 +1,229 @@ + + + + + + + + + Configuration interface (profile) — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Configuration interface (profile)

+

The profile interface allows a module to control how krb5 +configuration information is obtained by the Kerberos library and +applications. For a detailed description of the profile interface, +see the header file <profile.h>.

+
+

Note

+

The profile interface does not follow the normal conventions +for MIT krb5 pluggable interfaces, because it is part of a +lower-level component of the krb5 library.

+
+

As with other types of plugin modules, a profile module is a Unix +shared object or Windows DLL, built separately from the krb5 tree. +The krb5 library will dynamically load and use a profile plugin module +if it reads a module directive at the beginning of krb5.conf, as +described in Configuration profile modules.

+

A profile module exports a function named profile_module_init +matching the signature of the profile_module_init_fn type. This +function accepts a residual string, which may be used to help locate +the configuration source. The function fills in a vtable and may also +create a per-profile state object. If the module uses state objects, +it should implement the copy and cleanup methods to manage +them.

+

A basic read-only profile module need only implement the +get_values and free_values methods. The get_values method +accepts a null-terminated list of C string names (e.g., an array +containing “libdefaults”, “clockskew”, and NULL for the clockskew +variable in the [libdefaults] section) and returns a +null-terminated list of values, which will be cleaned up with the +free_values method when the caller is done with them.

+

Iterable profile modules must also define the iterator_create, +iterator, iterator_free, and free_string methods. The +core krb5 code does not require profiles to be iterable, but some +applications may iterate over the krb5 profile object in order to +present configuration interfaces.

+

Writable profile modules must also define the writable, +modified, update_relation, rename_section, +add_relation, and flush methods. The core krb5 code does not +require profiles to be writable, but some applications may write to +the krb5 profile in order to present configuration interfaces.

+

The following is an example of a very basic read-only profile module +which returns a hardcoded value for the default_realm variable in +[libdefaults], and provides no other configuration information. +(For conciseness, the example omits code for checking the return +values of malloc and strdup.)

+
#include <stdlib.h>
+#include <string.h>
+#include <profile.h>
+
+static long
+get_values(void *cbdata, const char *const *names, char ***values)
+{
+    if (names[0] != NULL && strcmp(names[0], "libdefaults") == 0 &&
+        names[1] != NULL && strcmp(names[1], "default_realm") == 0) {
+        *values = malloc(2 * sizeof(char *));
+        (*values)[0] = strdup("ATHENA.MIT.EDU");
+        (*values)[1] = NULL;
+        return 0;
+    }
+    return PROF_NO_RELATION;
+}
+
+static void
+free_values(void *cbdata, char **values)
+{
+    char **v;
+
+    for (v = values; *v; v++)
+        free(*v);
+    free(values);
+}
+
+long
+profile_module_init(const char *residual, struct profile_vtable *vtable,
+                    void **cb_ret);
+
+long
+profile_module_init(const char *residual, struct profile_vtable *vtable,
+                    void **cb_ret)
+{
+    *cb_ret = NULL;
+    vtable->get_values = get_values;
+    vtable->free_values = free_values;
+    return 0;
+}
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/plugindev/pwqual.html b/krb5-1.21.3/doc/html/plugindev/pwqual.html new file mode 100644 index 00000000..0a8c20fb --- /dev/null +++ b/krb5-1.21.3/doc/html/plugindev/pwqual.html @@ -0,0 +1,161 @@ + + + + + + + + + Password quality interface (pwqual) — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Password quality interface (pwqual)

+

The pwqual interface allows modules to control what passwords are +allowed when a user changes passwords. For a detailed description of +the pwqual interface, see the header file <krb5/pwqual_plugin.h>.

+

The primary pwqual method is check, which receives a password as +input and returns success (0) or a KADM5_PASS_Q_ failure code +depending on whether the password is allowed. The check method +also receives the principal name and the name of the principal’s +password policy as input; although there is no stable interface for +the module to obtain the fields of the password policy, it can define +its own configuration or data store based on the policy name.

+

A module can create and destroy per-process state objects by +implementing the open and close methods. State objects have +the type krb5_pwqual_moddata, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object. The open method also receives the name of the realm’s +dictionary file (as configured by the dict_file variable in the +[realms] section of kdc.conf) if it wishes to use +it.

+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/resources.html b/krb5-1.21.3/doc/html/resources.html new file mode 100644 index 00000000..dc9875e2 --- /dev/null +++ b/krb5-1.21.3/doc/html/resources.html @@ -0,0 +1,180 @@ + + + + + + + + + Resources — MIT Kerberos Documentation + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Resources

+
+

Mailing lists

+
    +
  • kerberos@mit.edu is a community resource for discussion and +questions about MIT krb5 and other Kerberos implementations. To +subscribe to the list, please follow the instructions at +https://mailman.mit.edu/mailman/listinfo/kerberos.

  • +
  • krbdev@mit.edu is the primary list for developers of MIT Kerberos. +To subscribe to the list, please follow the instructions at +https://mailman.mit.edu/mailman/listinfo/krbdev.

  • +
  • krb5-bugs@mit.edu is notified when a ticket is created or updated. +This list helps track bugs and feature requests. +In addition, this list is used to track documentation criticism +and recommendations for improvements.

  • +
  • krbcore@mit.edu is a private list for the MIT krb5 core team. Send +mail to this list if you need to contact the core team.

  • +
  • krbcore-security@mit.edu is the point of contact for security problems +with MIT Kerberos. Please use PGP-encrypted mail to report possible +vulnerabilities to this list.

  • +
+
+
+

IRC channels

+

The IRC channel #kerberos on libera.chat is a community resource for +general Kerberos discussion and support.

+

The main IRC channel for MIT Kerberos development is #krbdev on +Libera Chat.

+

For more information about Libera Chat, see https://libera.chat/.

+
+
+

Archives

+ +
+
+

Wiki

+

The wiki at https://k5wiki.kerberos.org/ contains useful information +for developers working on the MIT Kerberos source code. Some of the +information on the wiki may be useful for advanced users or system +administrators.

+
+
+

Web pages

+ +
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/search.html b/krb5-1.21.3/doc/html/search.html new file mode 100644 index 00000000..c4cd9353 --- /dev/null +++ b/krb5-1.21.3/doc/html/search.html @@ -0,0 +1,144 @@ + + + + + + + + Search — MIT Kerberos Documentation + + + + + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/searchindex.js b/krb5-1.21.3/doc/html/searchindex.js new file mode 100644 index 00000000..867f9959 --- /dev/null +++ b/krb5-1.21.3/doc/html/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({docnames:["about","admin/admin_commands/index","admin/admin_commands/k5srvutil","admin/admin_commands/kadmin_local","admin/admin_commands/kadmind","admin/admin_commands/kdb5_ldap_util","admin/admin_commands/kdb5_util","admin/admin_commands/kprop","admin/admin_commands/kpropd","admin/admin_commands/kproplog","admin/admin_commands/krb5kdc","admin/admin_commands/ktutil","admin/admin_commands/sserver","admin/advanced/index","admin/advanced/retiring-des","admin/appl_servers","admin/auth_indicator","admin/backup_host","admin/conf_files/index","admin/conf_files/kadm5_acl","admin/conf_files/kdc_conf","admin/conf_files/krb5_conf","admin/conf_ldap","admin/database","admin/dbtypes","admin/dictionary","admin/enctypes","admin/env_variables","admin/host_config","admin/https","admin/index","admin/install","admin/install_appl_srv","admin/install_clients","admin/install_kdc","admin/lockout","admin/otp","admin/pkinit","admin/princ_dns","admin/realm_config","admin/spake","admin/troubleshoot","admin/various_envs","appdev/gssapi","appdev/h5l_mit_apidiff","appdev/index","appdev/init_creds","appdev/princ_handle","appdev/refs/api/index","appdev/refs/api/krb5_425_conv_principal","appdev/refs/api/krb5_524_conv_principal","appdev/refs/api/krb5_524_convert_creds","appdev/refs/api/krb5_address_compare","appdev/refs/api/krb5_address_order","appdev/refs/api/krb5_address_search","appdev/refs/api/krb5_allow_weak_crypto","appdev/refs/api/krb5_aname_to_localname","appdev/refs/api/krb5_anonymous_principal","appdev/refs/api/krb5_anonymous_realm","appdev/refs/api/krb5_appdefault_boolean","appdev/refs/api/krb5_appdefault_string","appdev/refs/api/krb5_auth_con_free","appdev/refs/api/krb5_auth_con_genaddrs","appdev/refs/api/krb5_auth_con_get_checksum_func","appdev/refs/api/krb5_auth_con_getaddrs","appdev/refs/api/krb5_auth_con_getauthenticator","appdev/refs/api/krb5_auth_con_getflags","appdev/refs/api/krb5_auth_con_getkey","appdev/refs/api/krb5_auth_con_getkey_k","appdev/refs/api/krb5_auth_con_getlocalseqnumber","appdev/refs/api/krb5_auth_con_getlocalsubkey","appdev/refs/api/krb5_auth_con_getrcache","appdev/refs/api/krb5_auth_con_getrecvsubkey","appdev/refs/api/krb5_auth_con_getrecvsubkey_k","appdev/refs/api/krb5_auth_con_getremoteseqnumber","appdev/refs/api/krb5_auth_con_getremotesubkey","appdev/refs/api/krb5_auth_con_getsendsubkey","appdev/refs/api/krb5_auth_con_getsendsubkey_k","appdev/refs/api/krb5_auth_con_init","appdev/refs/api/krb5_auth_con_initivector","appdev/refs/api/krb5_auth_con_set_checksum_func","appdev/refs/api/krb5_auth_con_set_req_cksumtype","appdev/refs/api/krb5_auth_con_setaddrs","appdev/refs/api/krb5_auth_con_setflags","appdev/refs/api/krb5_auth_con_setports","appdev/refs/api/krb5_auth_con_setrcache","appdev/refs/api/krb5_auth_con_setrecvsubkey","appdev/refs/api/krb5_auth_con_setrecvsubkey_k","appdev/refs/api/krb5_auth_con_setsendsubkey","appdev/refs/api/krb5_auth_con_setsendsubkey_k","appdev/refs/api/krb5_auth_con_setuseruserkey","appdev/refs/api/krb5_build_principal","appdev/refs/api/krb5_build_principal_alloc_va","appdev/refs/api/krb5_build_principal_ext","appdev/refs/api/krb5_build_principal_va","appdev/refs/api/krb5_c_block_size","appdev/refs/api/krb5_c_checksum_length","appdev/refs/api/krb5_c_crypto_length","appdev/refs/api/krb5_c_crypto_length_iov","appdev/refs/api/krb5_c_decrypt","appdev/refs/api/krb5_c_decrypt_iov","appdev/refs/api/krb5_c_derive_prfplus","appdev/refs/api/krb5_c_encrypt","appdev/refs/api/krb5_c_encrypt_iov","appdev/refs/api/krb5_c_encrypt_length","appdev/refs/api/krb5_c_enctype_compare","appdev/refs/api/krb5_c_free_state","appdev/refs/api/krb5_c_fx_cf2_simple","appdev/refs/api/krb5_c_init_state","appdev/refs/api/krb5_c_is_coll_proof_cksum","appdev/refs/api/krb5_c_is_keyed_cksum","appdev/refs/api/krb5_c_keyed_checksum_types","appdev/refs/api/krb5_c_keylengths","appdev/refs/api/krb5_c_make_checksum","appdev/refs/api/krb5_c_make_checksum_iov","appdev/refs/api/krb5_c_make_random_key","appdev/refs/api/krb5_c_padding_length","appdev/refs/api/krb5_c_prf","appdev/refs/api/krb5_c_prf_length","appdev/refs/api/krb5_c_prfplus","appdev/refs/api/krb5_c_random_add_entropy","appdev/refs/api/krb5_c_random_make_octets","appdev/refs/api/krb5_c_random_os_entropy","appdev/refs/api/krb5_c_random_seed","appdev/refs/api/krb5_c_random_to_key","appdev/refs/api/krb5_c_string_to_key","appdev/refs/api/krb5_c_string_to_key_with_params","appdev/refs/api/krb5_c_valid_cksumtype","appdev/refs/api/krb5_c_valid_enctype","appdev/refs/api/krb5_c_verify_checksum","appdev/refs/api/krb5_c_verify_checksum_iov","appdev/refs/api/krb5_calculate_checksum","appdev/refs/api/krb5_cc_cache_match","appdev/refs/api/krb5_cc_close","appdev/refs/api/krb5_cc_copy_creds","appdev/refs/api/krb5_cc_default","appdev/refs/api/krb5_cc_default_name","appdev/refs/api/krb5_cc_destroy","appdev/refs/api/krb5_cc_dup","appdev/refs/api/krb5_cc_end_seq_get","appdev/refs/api/krb5_cc_gen_new","appdev/refs/api/krb5_cc_get_config","appdev/refs/api/krb5_cc_get_flags","appdev/refs/api/krb5_cc_get_full_name","appdev/refs/api/krb5_cc_get_name","appdev/refs/api/krb5_cc_get_principal","appdev/refs/api/krb5_cc_get_type","appdev/refs/api/krb5_cc_initialize","appdev/refs/api/krb5_cc_move","appdev/refs/api/krb5_cc_new_unique","appdev/refs/api/krb5_cc_next_cred","appdev/refs/api/krb5_cc_remove_cred","appdev/refs/api/krb5_cc_resolve","appdev/refs/api/krb5_cc_retrieve_cred","appdev/refs/api/krb5_cc_select","appdev/refs/api/krb5_cc_set_config","appdev/refs/api/krb5_cc_set_default_name","appdev/refs/api/krb5_cc_set_flags","appdev/refs/api/krb5_cc_start_seq_get","appdev/refs/api/krb5_cc_store_cred","appdev/refs/api/krb5_cc_support_switch","appdev/refs/api/krb5_cc_switch","appdev/refs/api/krb5_cccol_cursor_free","appdev/refs/api/krb5_cccol_cursor_new","appdev/refs/api/krb5_cccol_cursor_next","appdev/refs/api/krb5_cccol_have_content","appdev/refs/api/krb5_change_password","appdev/refs/api/krb5_check_clockskew","appdev/refs/api/krb5_checksum_size","appdev/refs/api/krb5_chpw_message","appdev/refs/api/krb5_cksumtype_to_string","appdev/refs/api/krb5_clear_error_message","appdev/refs/api/krb5_copy_addresses","appdev/refs/api/krb5_copy_authdata","appdev/refs/api/krb5_copy_authenticator","appdev/refs/api/krb5_copy_checksum","appdev/refs/api/krb5_copy_context","appdev/refs/api/krb5_copy_creds","appdev/refs/api/krb5_copy_data","appdev/refs/api/krb5_copy_error_message","appdev/refs/api/krb5_copy_keyblock","appdev/refs/api/krb5_copy_keyblock_contents","appdev/refs/api/krb5_copy_principal","appdev/refs/api/krb5_copy_ticket","appdev/refs/api/krb5_decode_authdata_container","appdev/refs/api/krb5_decode_ticket","appdev/refs/api/krb5_decrypt","appdev/refs/api/krb5_deltat_to_string","appdev/refs/api/krb5_eblock_enctype","appdev/refs/api/krb5_encode_authdata_container","appdev/refs/api/krb5_encrypt","appdev/refs/api/krb5_encrypt_size","appdev/refs/api/krb5_enctype_to_name","appdev/refs/api/krb5_enctype_to_string","appdev/refs/api/krb5_expand_hostname","appdev/refs/api/krb5_find_authdata","appdev/refs/api/krb5_finish_key","appdev/refs/api/krb5_finish_random_key","appdev/refs/api/krb5_free_addresses","appdev/refs/api/krb5_free_ap_rep_enc_part","appdev/refs/api/krb5_free_authdata","appdev/refs/api/krb5_free_authenticator","appdev/refs/api/krb5_free_checksum","appdev/refs/api/krb5_free_checksum_contents","appdev/refs/api/krb5_free_cksumtypes","appdev/refs/api/krb5_free_context","appdev/refs/api/krb5_free_cred_contents","appdev/refs/api/krb5_free_creds","appdev/refs/api/krb5_free_data","appdev/refs/api/krb5_free_data_contents","appdev/refs/api/krb5_free_default_realm","appdev/refs/api/krb5_free_enctypes","appdev/refs/api/krb5_free_error","appdev/refs/api/krb5_free_error_message","appdev/refs/api/krb5_free_host_realm","appdev/refs/api/krb5_free_keyblock","appdev/refs/api/krb5_free_keyblock_contents","appdev/refs/api/krb5_free_keytab_entry_contents","appdev/refs/api/krb5_free_principal","appdev/refs/api/krb5_free_string","appdev/refs/api/krb5_free_tgt_creds","appdev/refs/api/krb5_free_ticket","appdev/refs/api/krb5_free_unparsed_name","appdev/refs/api/krb5_fwd_tgt_creds","appdev/refs/api/krb5_get_credentials","appdev/refs/api/krb5_get_credentials_renew","appdev/refs/api/krb5_get_credentials_validate","appdev/refs/api/krb5_get_default_realm","appdev/refs/api/krb5_get_error_message","appdev/refs/api/krb5_get_etype_info","appdev/refs/api/krb5_get_fallback_host_realm","appdev/refs/api/krb5_get_host_realm","appdev/refs/api/krb5_get_in_tkt_with_keytab","appdev/refs/api/krb5_get_in_tkt_with_password","appdev/refs/api/krb5_get_in_tkt_with_skey","appdev/refs/api/krb5_get_init_creds_keytab","appdev/refs/api/krb5_get_init_creds_opt_alloc","appdev/refs/api/krb5_get_init_creds_opt_free","appdev/refs/api/krb5_get_init_creds_opt_get_fast_flags","appdev/refs/api/krb5_get_init_creds_opt_init","appdev/refs/api/krb5_get_init_creds_opt_set_address_list","appdev/refs/api/krb5_get_init_creds_opt_set_anonymous","appdev/refs/api/krb5_get_init_creds_opt_set_canonicalize","appdev/refs/api/krb5_get_init_creds_opt_set_change_password_prompt","appdev/refs/api/krb5_get_init_creds_opt_set_etype_list","appdev/refs/api/krb5_get_init_creds_opt_set_expire_callback","appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache","appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache_name","appdev/refs/api/krb5_get_init_creds_opt_set_fast_flags","appdev/refs/api/krb5_get_init_creds_opt_set_forwardable","appdev/refs/api/krb5_get_init_creds_opt_set_in_ccache","appdev/refs/api/krb5_get_init_creds_opt_set_out_ccache","appdev/refs/api/krb5_get_init_creds_opt_set_pa","appdev/refs/api/krb5_get_init_creds_opt_set_pac_request","appdev/refs/api/krb5_get_init_creds_opt_set_preauth_list","appdev/refs/api/krb5_get_init_creds_opt_set_proxiable","appdev/refs/api/krb5_get_init_creds_opt_set_renew_life","appdev/refs/api/krb5_get_init_creds_opt_set_responder","appdev/refs/api/krb5_get_init_creds_opt_set_salt","appdev/refs/api/krb5_get_init_creds_opt_set_tkt_life","appdev/refs/api/krb5_get_init_creds_password","appdev/refs/api/krb5_get_permitted_enctypes","appdev/refs/api/krb5_get_profile","appdev/refs/api/krb5_get_prompt_types","appdev/refs/api/krb5_get_renewed_creds","appdev/refs/api/krb5_get_server_rcache","appdev/refs/api/krb5_get_time_offsets","appdev/refs/api/krb5_get_validated_creds","appdev/refs/api/krb5_init_context","appdev/refs/api/krb5_init_context_profile","appdev/refs/api/krb5_init_creds_free","appdev/refs/api/krb5_init_creds_get","appdev/refs/api/krb5_init_creds_get_creds","appdev/refs/api/krb5_init_creds_get_error","appdev/refs/api/krb5_init_creds_get_times","appdev/refs/api/krb5_init_creds_init","appdev/refs/api/krb5_init_creds_set_keytab","appdev/refs/api/krb5_init_creds_set_password","appdev/refs/api/krb5_init_creds_set_service","appdev/refs/api/krb5_init_creds_step","appdev/refs/api/krb5_init_keyblock","appdev/refs/api/krb5_init_random_key","appdev/refs/api/krb5_init_secure_context","appdev/refs/api/krb5_is_config_principal","appdev/refs/api/krb5_is_referral_realm","appdev/refs/api/krb5_is_thread_safe","appdev/refs/api/krb5_k_create_key","appdev/refs/api/krb5_k_decrypt","appdev/refs/api/krb5_k_decrypt_iov","appdev/refs/api/krb5_k_encrypt","appdev/refs/api/krb5_k_encrypt_iov","appdev/refs/api/krb5_k_free_key","appdev/refs/api/krb5_k_key_enctype","appdev/refs/api/krb5_k_key_keyblock","appdev/refs/api/krb5_k_make_checksum","appdev/refs/api/krb5_k_make_checksum_iov","appdev/refs/api/krb5_k_prf","appdev/refs/api/krb5_k_reference_key","appdev/refs/api/krb5_k_verify_checksum","appdev/refs/api/krb5_k_verify_checksum_iov","appdev/refs/api/krb5_kdc_sign_ticket","appdev/refs/api/krb5_kdc_verify_ticket","appdev/refs/api/krb5_kt_add_entry","appdev/refs/api/krb5_kt_client_default","appdev/refs/api/krb5_kt_close","appdev/refs/api/krb5_kt_default","appdev/refs/api/krb5_kt_default_name","appdev/refs/api/krb5_kt_dup","appdev/refs/api/krb5_kt_end_seq_get","appdev/refs/api/krb5_kt_free_entry","appdev/refs/api/krb5_kt_get_entry","appdev/refs/api/krb5_kt_get_name","appdev/refs/api/krb5_kt_get_type","appdev/refs/api/krb5_kt_have_content","appdev/refs/api/krb5_kt_next_entry","appdev/refs/api/krb5_kt_read_service_key","appdev/refs/api/krb5_kt_remove_entry","appdev/refs/api/krb5_kt_resolve","appdev/refs/api/krb5_kt_start_seq_get","appdev/refs/api/krb5_kuserok","appdev/refs/api/krb5_make_authdata_kdc_issued","appdev/refs/api/krb5_marshal_credentials","appdev/refs/api/krb5_merge_authdata","appdev/refs/api/krb5_mk_1cred","appdev/refs/api/krb5_mk_error","appdev/refs/api/krb5_mk_ncred","appdev/refs/api/krb5_mk_priv","appdev/refs/api/krb5_mk_rep","appdev/refs/api/krb5_mk_rep_dce","appdev/refs/api/krb5_mk_req","appdev/refs/api/krb5_mk_req_extended","appdev/refs/api/krb5_mk_safe","appdev/refs/api/krb5_os_localaddr","appdev/refs/api/krb5_pac_add_buffer","appdev/refs/api/krb5_pac_free","appdev/refs/api/krb5_pac_get_buffer","appdev/refs/api/krb5_pac_get_client_info","appdev/refs/api/krb5_pac_get_types","appdev/refs/api/krb5_pac_init","appdev/refs/api/krb5_pac_parse","appdev/refs/api/krb5_pac_sign","appdev/refs/api/krb5_pac_sign_ext","appdev/refs/api/krb5_pac_verify","appdev/refs/api/krb5_pac_verify_ext","appdev/refs/api/krb5_parse_name","appdev/refs/api/krb5_parse_name_flags","appdev/refs/api/krb5_prepend_error_message","appdev/refs/api/krb5_principal2salt","appdev/refs/api/krb5_principal_compare","appdev/refs/api/krb5_principal_compare_any_realm","appdev/refs/api/krb5_principal_compare_flags","appdev/refs/api/krb5_process_key","appdev/refs/api/krb5_prompter_posix","appdev/refs/api/krb5_random_key","appdev/refs/api/krb5_rd_cred","appdev/refs/api/krb5_rd_error","appdev/refs/api/krb5_rd_priv","appdev/refs/api/krb5_rd_rep","appdev/refs/api/krb5_rd_rep_dce","appdev/refs/api/krb5_rd_req","appdev/refs/api/krb5_rd_safe","appdev/refs/api/krb5_read_password","appdev/refs/api/krb5_realm_compare","appdev/refs/api/krb5_recvauth","appdev/refs/api/krb5_recvauth_version","appdev/refs/api/krb5_responder_get_challenge","appdev/refs/api/krb5_responder_list_questions","appdev/refs/api/krb5_responder_otp_challenge_free","appdev/refs/api/krb5_responder_otp_get_challenge","appdev/refs/api/krb5_responder_otp_set_answer","appdev/refs/api/krb5_responder_pkinit_challenge_free","appdev/refs/api/krb5_responder_pkinit_get_challenge","appdev/refs/api/krb5_responder_pkinit_set_answer","appdev/refs/api/krb5_responder_set_answer","appdev/refs/api/krb5_salttype_to_string","appdev/refs/api/krb5_sendauth","appdev/refs/api/krb5_server_decrypt_ticket_keytab","appdev/refs/api/krb5_set_default_realm","appdev/refs/api/krb5_set_default_tgs_enctypes","appdev/refs/api/krb5_set_error_message","appdev/refs/api/krb5_set_kdc_recv_hook","appdev/refs/api/krb5_set_kdc_send_hook","appdev/refs/api/krb5_set_password","appdev/refs/api/krb5_set_password_using_ccache","appdev/refs/api/krb5_set_principal_realm","appdev/refs/api/krb5_set_real_time","appdev/refs/api/krb5_set_trace_callback","appdev/refs/api/krb5_set_trace_filename","appdev/refs/api/krb5_sname_match","appdev/refs/api/krb5_sname_to_principal","appdev/refs/api/krb5_string_to_cksumtype","appdev/refs/api/krb5_string_to_deltat","appdev/refs/api/krb5_string_to_enctype","appdev/refs/api/krb5_string_to_key","appdev/refs/api/krb5_string_to_salttype","appdev/refs/api/krb5_string_to_timestamp","appdev/refs/api/krb5_timeofday","appdev/refs/api/krb5_timestamp_to_sfstring","appdev/refs/api/krb5_timestamp_to_string","appdev/refs/api/krb5_tkt_creds_free","appdev/refs/api/krb5_tkt_creds_get","appdev/refs/api/krb5_tkt_creds_get_creds","appdev/refs/api/krb5_tkt_creds_get_times","appdev/refs/api/krb5_tkt_creds_init","appdev/refs/api/krb5_tkt_creds_step","appdev/refs/api/krb5_unmarshal_credentials","appdev/refs/api/krb5_unparse_name","appdev/refs/api/krb5_unparse_name_ext","appdev/refs/api/krb5_unparse_name_flags","appdev/refs/api/krb5_unparse_name_flags_ext","appdev/refs/api/krb5_us_timeofday","appdev/refs/api/krb5_use_enctype","appdev/refs/api/krb5_verify_authdata_kdc_issued","appdev/refs/api/krb5_verify_checksum","appdev/refs/api/krb5_verify_init_creds","appdev/refs/api/krb5_verify_init_creds_opt_init","appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail","appdev/refs/api/krb5_vprepend_error_message","appdev/refs/api/krb5_vset_error_message","appdev/refs/api/krb5_vwrap_error_message","appdev/refs/api/krb5_wrap_error_message","appdev/refs/index","appdev/refs/macros/ADDRTYPE_ADDRPORT","appdev/refs/macros/ADDRTYPE_CHAOS","appdev/refs/macros/ADDRTYPE_DDP","appdev/refs/macros/ADDRTYPE_INET","appdev/refs/macros/ADDRTYPE_INET6","appdev/refs/macros/ADDRTYPE_IPPORT","appdev/refs/macros/ADDRTYPE_ISO","appdev/refs/macros/ADDRTYPE_IS_LOCAL","appdev/refs/macros/ADDRTYPE_NETBIOS","appdev/refs/macros/ADDRTYPE_XNS","appdev/refs/macros/AD_TYPE_EXTERNAL","appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK","appdev/refs/macros/AD_TYPE_REGISTERED","appdev/refs/macros/AD_TYPE_RESERVED","appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION","appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED","appdev/refs/macros/AP_OPTS_RESERVED","appdev/refs/macros/AP_OPTS_USE_SESSION_KEY","appdev/refs/macros/AP_OPTS_USE_SUBKEY","appdev/refs/macros/AP_OPTS_WIRE_MASK","appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128","appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256","appdev/refs/macros/CKSUMTYPE_CRC32","appdev/refs/macros/CKSUMTYPE_DESCBC","appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR","appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128","appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256","appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3","appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128","appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256","appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR","appdev/refs/macros/CKSUMTYPE_NIST_SHA","appdev/refs/macros/CKSUMTYPE_RSA_MD4","appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES","appdev/refs/macros/CKSUMTYPE_RSA_MD5","appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES","appdev/refs/macros/CKSUMTYPE_SHA1","appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96","appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128","appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96","appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192","appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC","appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP","appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC","appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC","appdev/refs/macros/ENCTYPE_DES3_CBC_ENV","appdev/refs/macros/ENCTYPE_DES3_CBC_RAW","appdev/refs/macros/ENCTYPE_DES3_CBC_SHA","appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1","appdev/refs/macros/ENCTYPE_DES_CBC_CRC","appdev/refs/macros/ENCTYPE_DES_CBC_MD4","appdev/refs/macros/ENCTYPE_DES_CBC_MD5","appdev/refs/macros/ENCTYPE_DES_CBC_RAW","appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1","appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS","appdev/refs/macros/ENCTYPE_MD5_RSA_CMS","appdev/refs/macros/ENCTYPE_NULL","appdev/refs/macros/ENCTYPE_RC2_CBC_ENV","appdev/refs/macros/ENCTYPE_RSA_ENV","appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV","appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS","appdev/refs/macros/ENCTYPE_UNKNOWN","appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE","appdev/refs/macros/KDC_OPT_CANONICALIZE","appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT","appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK","appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY","appdev/refs/macros/KDC_OPT_FORWARDABLE","appdev/refs/macros/KDC_OPT_FORWARDED","appdev/refs/macros/KDC_OPT_POSTDATED","appdev/refs/macros/KDC_OPT_PROXIABLE","appdev/refs/macros/KDC_OPT_PROXY","appdev/refs/macros/KDC_OPT_RENEW","appdev/refs/macros/KDC_OPT_RENEWABLE","appdev/refs/macros/KDC_OPT_RENEWABLE_OK","appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS","appdev/refs/macros/KDC_OPT_VALIDATE","appdev/refs/macros/KDC_TKT_COMMON_MASK","appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE","appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR","appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR","appdev/refs/macros/KRB5_AP_REP","appdev/refs/macros/KRB5_AP_REQ","appdev/refs/macros/KRB5_AS_REP","appdev/refs/macros/KRB5_AS_REQ","appdev/refs/macros/KRB5_AUTHDATA_AND_OR","appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS","appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR","appdev/refs/macros/KRB5_AUTHDATA_CAMMAC","appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION","appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR","appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT","appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS","appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED","appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC","appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE","appdev/refs/macros/KRB5_AUTHDATA_SESAME","appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET","appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC","appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE","appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME","appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR","appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR","appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR","appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR","appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL","appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE","appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME","appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY","appdev/refs/macros/KRB5_CRED","appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM","appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA","appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY","appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER","appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING","appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY","appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM","appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER","appdev/refs/macros/KRB5_CYBERSAFE_SECUREID","appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS","appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP","appdev/refs/macros/KRB5_ERROR","appdev/refs/macros/KRB5_FAST_REQUIRED","appdev/refs/macros/KRB5_GC_CACHED","appdev/refs/macros/KRB5_GC_CANONICALIZE","appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION","appdev/refs/macros/KRB5_GC_FORWARDABLE","appdev/refs/macros/KRB5_GC_NO_STORE","appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK","appdev/refs/macros/KRB5_GC_USER_USER","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE","appdev/refs/macros/KRB5_INIT_CONTEXT_KDC","appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE","appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE","appdev/refs/macros/KRB5_INT16_MAX","appdev/refs/macros/KRB5_INT16_MIN","appdev/refs/macros/KRB5_INT32_MAX","appdev/refs/macros/KRB5_INT32_MIN","appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE","appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM","appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE","appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH","appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM","appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT","appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART","appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH","appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM","appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART","appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ","appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS","appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC","appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT","appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC","appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC","appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED","appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP","appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM","appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC","appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG","appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV","appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED","appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET","appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART","appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM","appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART","appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM","appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS","appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE","appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST","appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX","appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY","appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST","appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM","appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID","appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE","appdev/refs/macros/KRB5_KEYUSAGE_SPAKE","appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY","appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY","appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY","appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY","appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH","appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM","appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED","appdev/refs/macros/KRB5_KPASSWD_AUTHERROR","appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION","appdev/refs/macros/KRB5_KPASSWD_HARDERROR","appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED","appdev/refs/macros/KRB5_KPASSWD_MALFORMED","appdev/refs/macros/KRB5_KPASSWD_SOFTERROR","appdev/refs/macros/KRB5_KPASSWD_SUCCESS","appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME","appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL","appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL","appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ","appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT","appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED","appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME","appdev/refs/macros/KRB5_LRQ_NONE","appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME","appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL","appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL","appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ","appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT","appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED","appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME","appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL","appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID","appdev/refs/macros/KRB5_NT_MS_PRINCIPAL","appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID","appdev/refs/macros/KRB5_NT_PRINCIPAL","appdev/refs/macros/KRB5_NT_SMTP_NAME","appdev/refs/macros/KRB5_NT_SRV_HST","appdev/refs/macros/KRB5_NT_SRV_INST","appdev/refs/macros/KRB5_NT_SRV_XHST","appdev/refs/macros/KRB5_NT_UID","appdev/refs/macros/KRB5_NT_UNKNOWN","appdev/refs/macros/KRB5_NT_WELLKNOWN","appdev/refs/macros/KRB5_NT_X500_PRINCIPAL","appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO","appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS","appdev/refs/macros/KRB5_PAC_CLIENT_INFO","appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO","appdev/refs/macros/KRB5_PAC_DELEGATION_INFO","appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS","appdev/refs/macros/KRB5_PAC_DEVICE_INFO","appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM","appdev/refs/macros/KRB5_PAC_LOGON_INFO","appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM","appdev/refs/macros/KRB5_PAC_REQUESTOR","appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM","appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM","appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO","appdev/refs/macros/KRB5_PADATA_AFS3_SALT","appdev/refs/macros/KRB5_PADATA_AP_REQ","appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM","appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS","appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE","appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID","appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP","appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME","appdev/refs/macros/KRB5_PADATA_ETYPE_INFO","appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2","appdev/refs/macros/KRB5_PADATA_FOR_USER","appdev/refs/macros/KRB5_PADATA_FX_COOKIE","appdev/refs/macros/KRB5_PADATA_FX_ERROR","appdev/refs/macros/KRB5_PADATA_FX_FAST","appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA","appdev/refs/macros/KRB5_PADATA_NONE","appdev/refs/macros/KRB5_PADATA_OSF_DCE","appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE","appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE","appdev/refs/macros/KRB5_PADATA_OTP_REQUEST","appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS","appdev/refs/macros/KRB5_PADATA_PAC_REQUEST","appdev/refs/macros/KRB5_PADATA_PKINIT_KX","appdev/refs/macros/KRB5_PADATA_PK_AS_REP","appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD","appdev/refs/macros/KRB5_PADATA_PK_AS_REQ","appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD","appdev/refs/macros/KRB5_PADATA_PW_SALT","appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2","appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY","appdev/refs/macros/KRB5_PADATA_REFERRAL","appdev/refs/macros/KRB5_PADATA_S4U_X509_USER","appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE","appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2","appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT","appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE","appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2","appdev/refs/macros/KRB5_PADATA_SESAME","appdev/refs/macros/KRB5_PADATA_SPAKE","appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO","appdev/refs/macros/KRB5_PADATA_TGS_REQ","appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO","appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD","appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE","appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM","appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8","appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE","appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM","appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM","appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM","appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM","appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY","appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM","appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT","appdev/refs/macros/KRB5_PRIV","appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD","appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN","appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD","appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH","appdev/refs/macros/KRB5_PVNO","appdev/refs/macros/KRB5_REALM_BRANCH_CHAR","appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS","appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION","appdev/refs/macros/KRB5_REFERRAL_REALM","appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN","appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN","appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP","appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN","appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC","appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL","appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL","appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW","appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY","appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED","appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP","appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD","appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT","appdev/refs/macros/KRB5_SAFE","appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD","appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD","appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY","appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT","appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA","appdev/refs/macros/KRB5_TC_MATCH_FLAGS","appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT","appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY","appdev/refs/macros/KRB5_TC_MATCH_KTYPE","appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY","appdev/refs/macros/KRB5_TC_MATCH_TIMES","appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT","appdev/refs/macros/KRB5_TC_NOTICKET","appdev/refs/macros/KRB5_TC_OPENCLOSE","appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES","appdev/refs/macros/KRB5_TGS_NAME","appdev/refs/macros/KRB5_TGS_NAME_SIZE","appdev/refs/macros/KRB5_TGS_REP","appdev/refs/macros/KRB5_TGS_REQ","appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE","appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL","appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR","appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK","appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY","appdev/refs/macros/MAX_KEYTAB_NAME_LEN","appdev/refs/macros/MSEC_DIRBIT","appdev/refs/macros/MSEC_VAL_MASK","appdev/refs/macros/SALT_TYPE_AFS_LENGTH","appdev/refs/macros/SALT_TYPE_NO_LENGTH","appdev/refs/macros/THREEPARAMOPEN","appdev/refs/macros/TKT_FLG_ANONYMOUS","appdev/refs/macros/TKT_FLG_ENC_PA_REP","appdev/refs/macros/TKT_FLG_FORWARDABLE","appdev/refs/macros/TKT_FLG_FORWARDED","appdev/refs/macros/TKT_FLG_HW_AUTH","appdev/refs/macros/TKT_FLG_INITIAL","appdev/refs/macros/TKT_FLG_INVALID","appdev/refs/macros/TKT_FLG_MAY_POSTDATE","appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE","appdev/refs/macros/TKT_FLG_POSTDATED","appdev/refs/macros/TKT_FLG_PRE_AUTH","appdev/refs/macros/TKT_FLG_PROXIABLE","appdev/refs/macros/TKT_FLG_PROXY","appdev/refs/macros/TKT_FLG_RENEWABLE","appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED","appdev/refs/macros/VALID_INT_BITS","appdev/refs/macros/VALID_UINT_BITS","appdev/refs/macros/index","appdev/refs/macros/krb524_convert_creds_kdc","appdev/refs/macros/krb524_init_ets","appdev/refs/macros/krb5_const","appdev/refs/macros/krb5_princ_component","appdev/refs/macros/krb5_princ_name","appdev/refs/macros/krb5_princ_realm","appdev/refs/macros/krb5_princ_set_realm","appdev/refs/macros/krb5_princ_set_realm_data","appdev/refs/macros/krb5_princ_set_realm_length","appdev/refs/macros/krb5_princ_size","appdev/refs/macros/krb5_princ_type","appdev/refs/macros/krb5_roundup","appdev/refs/macros/krb5_x","appdev/refs/macros/krb5_xc","appdev/refs/types/index","appdev/refs/types/krb5_address","appdev/refs/types/krb5_addrtype","appdev/refs/types/krb5_ap_rep","appdev/refs/types/krb5_ap_rep_enc_part","appdev/refs/types/krb5_ap_req","appdev/refs/types/krb5_auth_context","appdev/refs/types/krb5_authdata","appdev/refs/types/krb5_authdatatype","appdev/refs/types/krb5_authenticator","appdev/refs/types/krb5_boolean","appdev/refs/types/krb5_cc_cursor","appdev/refs/types/krb5_ccache","appdev/refs/types/krb5_cccol_cursor","appdev/refs/types/krb5_checksum","appdev/refs/types/krb5_cksumtype","appdev/refs/types/krb5_const_pointer","appdev/refs/types/krb5_const_principal","appdev/refs/types/krb5_context","appdev/refs/types/krb5_cred","appdev/refs/types/krb5_cred_enc_part","appdev/refs/types/krb5_cred_info","appdev/refs/types/krb5_creds","appdev/refs/types/krb5_crypto_iov","appdev/refs/types/krb5_cryptotype","appdev/refs/types/krb5_data","appdev/refs/types/krb5_deltat","appdev/refs/types/krb5_enc_data","appdev/refs/types/krb5_enc_kdc_rep_part","appdev/refs/types/krb5_enc_tkt_part","appdev/refs/types/krb5_encrypt_block","appdev/refs/types/krb5_enctype","appdev/refs/types/krb5_error","appdev/refs/types/krb5_error_code","appdev/refs/types/krb5_expire_callback_func","appdev/refs/types/krb5_flags","appdev/refs/types/krb5_get_init_creds_opt","appdev/refs/types/krb5_gic_opt_pa_data","appdev/refs/types/krb5_init_creds_context","appdev/refs/types/krb5_int16","appdev/refs/types/krb5_int32","appdev/refs/types/krb5_kdc_rep","appdev/refs/types/krb5_kdc_req","appdev/refs/types/krb5_key","appdev/refs/types/krb5_keyblock","appdev/refs/types/krb5_keytab","appdev/refs/types/krb5_keytab_entry","appdev/refs/types/krb5_keyusage","appdev/refs/types/krb5_kt_cursor","appdev/refs/types/krb5_kvno","appdev/refs/types/krb5_last_req_entry","appdev/refs/types/krb5_magic","appdev/refs/types/krb5_mk_req_checksum_func","appdev/refs/types/krb5_msgtype","appdev/refs/types/krb5_octet","appdev/refs/types/krb5_pa_data","appdev/refs/types/krb5_pa_pac_req","appdev/refs/types/krb5_pa_server_referral_data","appdev/refs/types/krb5_pa_svr_referral_data","appdev/refs/types/krb5_pac","appdev/refs/types/krb5_pointer","appdev/refs/types/krb5_post_recv_fn","appdev/refs/types/krb5_pre_send_fn","appdev/refs/types/krb5_preauthtype","appdev/refs/types/krb5_principal","appdev/refs/types/krb5_principal_data","appdev/refs/types/krb5_prompt","appdev/refs/types/krb5_prompt_type","appdev/refs/types/krb5_prompter_fct","appdev/refs/types/krb5_pwd_data","appdev/refs/types/krb5_rcache","appdev/refs/types/krb5_replay_data","appdev/refs/types/krb5_responder_context","appdev/refs/types/krb5_responder_fn","appdev/refs/types/krb5_responder_otp_challenge","appdev/refs/types/krb5_responder_otp_tokeninfo","appdev/refs/types/krb5_responder_pkinit_challenge","appdev/refs/types/krb5_responder_pkinit_identity","appdev/refs/types/krb5_response","appdev/refs/types/krb5_ticket","appdev/refs/types/krb5_ticket_times","appdev/refs/types/krb5_timestamp","appdev/refs/types/krb5_tkt_authent","appdev/refs/types/krb5_tkt_creds_context","appdev/refs/types/krb5_trace_callback","appdev/refs/types/krb5_trace_info","appdev/refs/types/krb5_transited","appdev/refs/types/krb5_typed_data","appdev/refs/types/krb5_ui_2","appdev/refs/types/krb5_ui_4","appdev/refs/types/krb5_verify_init_creds_opt","appdev/refs/types/passwd_phrase_element","appdev/y2038","basic/ccache_def","basic/date_format","basic/index","basic/keytab_def","basic/rcache_def","basic/stash_file_def","build/directory_org","build/doing_build","build/index","build/options2configure","build/osconf","build_this","copyright","formats/ccache_file_format","formats/cookie","formats/freshness_token","formats/index","formats/keytab_file_format","formats/rcache_file_format","index","mitK5defaults","mitK5features","mitK5license","plugindev/ccselect","plugindev/certauth","plugindev/clpreauth","plugindev/general","plugindev/gssapi","plugindev/hostrealm","plugindev/index","plugindev/internal","plugindev/kadm5_auth","plugindev/kadm5_hook","plugindev/kdcpolicy","plugindev/kdcpreauth","plugindev/localauth","plugindev/locate","plugindev/profile","plugindev/pwqual","resources","user/index","user/pwd_mgmt","user/tkt_mgmt","user/user_commands/index","user/user_commands/kdestroy","user/user_commands/kinit","user/user_commands/klist","user/user_commands/kpasswd","user/user_commands/krb5-config","user/user_commands/ksu","user/user_commands/kswitch","user/user_commands/kvno","user/user_commands/sclient","user/user_config/index","user/user_config/k5identity","user/user_config/k5login","user/user_config/kerberos"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,sphinx:56},filenames:["about.rst","admin/admin_commands/index.rst","admin/admin_commands/k5srvutil.rst","admin/admin_commands/kadmin_local.rst","admin/admin_commands/kadmind.rst","admin/admin_commands/kdb5_ldap_util.rst","admin/admin_commands/kdb5_util.rst","admin/admin_commands/kprop.rst","admin/admin_commands/kpropd.rst","admin/admin_commands/kproplog.rst","admin/admin_commands/krb5kdc.rst","admin/admin_commands/ktutil.rst","admin/admin_commands/sserver.rst","admin/advanced/index.rst","admin/advanced/retiring-des.rst","admin/appl_servers.rst","admin/auth_indicator.rst","admin/backup_host.rst","admin/conf_files/index.rst","admin/conf_files/kadm5_acl.rst","admin/conf_files/kdc_conf.rst","admin/conf_files/krb5_conf.rst","admin/conf_ldap.rst","admin/database.rst","admin/dbtypes.rst","admin/dictionary.rst","admin/enctypes.rst","admin/env_variables.rst","admin/host_config.rst","admin/https.rst","admin/index.rst","admin/install.rst","admin/install_appl_srv.rst","admin/install_clients.rst","admin/install_kdc.rst","admin/lockout.rst","admin/otp.rst","admin/pkinit.rst","admin/princ_dns.rst","admin/realm_config.rst","admin/spake.rst","admin/troubleshoot.rst","admin/various_envs.rst","appdev/gssapi.rst","appdev/h5l_mit_apidiff.rst","appdev/index.rst","appdev/init_creds.rst","appdev/princ_handle.rst","appdev/refs/api/index.rst","appdev/refs/api/krb5_425_conv_principal.rst","appdev/refs/api/krb5_524_conv_principal.rst","appdev/refs/api/krb5_524_convert_creds.rst","appdev/refs/api/krb5_address_compare.rst","appdev/refs/api/krb5_address_order.rst","appdev/refs/api/krb5_address_search.rst","appdev/refs/api/krb5_allow_weak_crypto.rst","appdev/refs/api/krb5_aname_to_localname.rst","appdev/refs/api/krb5_anonymous_principal.rst","appdev/refs/api/krb5_anonymous_realm.rst","appdev/refs/api/krb5_appdefault_boolean.rst","appdev/refs/api/krb5_appdefault_string.rst","appdev/refs/api/krb5_auth_con_free.rst","appdev/refs/api/krb5_auth_con_genaddrs.rst","appdev/refs/api/krb5_auth_con_get_checksum_func.rst","appdev/refs/api/krb5_auth_con_getaddrs.rst","appdev/refs/api/krb5_auth_con_getauthenticator.rst","appdev/refs/api/krb5_auth_con_getflags.rst","appdev/refs/api/krb5_auth_con_getkey.rst","appdev/refs/api/krb5_auth_con_getkey_k.rst","appdev/refs/api/krb5_auth_con_getlocalseqnumber.rst","appdev/refs/api/krb5_auth_con_getlocalsubkey.rst","appdev/refs/api/krb5_auth_con_getrcache.rst","appdev/refs/api/krb5_auth_con_getrecvsubkey.rst","appdev/refs/api/krb5_auth_con_getrecvsubkey_k.rst","appdev/refs/api/krb5_auth_con_getremoteseqnumber.rst","appdev/refs/api/krb5_auth_con_getremotesubkey.rst","appdev/refs/api/krb5_auth_con_getsendsubkey.rst","appdev/refs/api/krb5_auth_con_getsendsubkey_k.rst","appdev/refs/api/krb5_auth_con_init.rst","appdev/refs/api/krb5_auth_con_initivector.rst","appdev/refs/api/krb5_auth_con_set_checksum_func.rst","appdev/refs/api/krb5_auth_con_set_req_cksumtype.rst","appdev/refs/api/krb5_auth_con_setaddrs.rst","appdev/refs/api/krb5_auth_con_setflags.rst","appdev/refs/api/krb5_auth_con_setports.rst","appdev/refs/api/krb5_auth_con_setrcache.rst","appdev/refs/api/krb5_auth_con_setrecvsubkey.rst","appdev/refs/api/krb5_auth_con_setrecvsubkey_k.rst","appdev/refs/api/krb5_auth_con_setsendsubkey.rst","appdev/refs/api/krb5_auth_con_setsendsubkey_k.rst","appdev/refs/api/krb5_auth_con_setuseruserkey.rst","appdev/refs/api/krb5_build_principal.rst","appdev/refs/api/krb5_build_principal_alloc_va.rst","appdev/refs/api/krb5_build_principal_ext.rst","appdev/refs/api/krb5_build_principal_va.rst","appdev/refs/api/krb5_c_block_size.rst","appdev/refs/api/krb5_c_checksum_length.rst","appdev/refs/api/krb5_c_crypto_length.rst","appdev/refs/api/krb5_c_crypto_length_iov.rst","appdev/refs/api/krb5_c_decrypt.rst","appdev/refs/api/krb5_c_decrypt_iov.rst","appdev/refs/api/krb5_c_derive_prfplus.rst","appdev/refs/api/krb5_c_encrypt.rst","appdev/refs/api/krb5_c_encrypt_iov.rst","appdev/refs/api/krb5_c_encrypt_length.rst","appdev/refs/api/krb5_c_enctype_compare.rst","appdev/refs/api/krb5_c_free_state.rst","appdev/refs/api/krb5_c_fx_cf2_simple.rst","appdev/refs/api/krb5_c_init_state.rst","appdev/refs/api/krb5_c_is_coll_proof_cksum.rst","appdev/refs/api/krb5_c_is_keyed_cksum.rst","appdev/refs/api/krb5_c_keyed_checksum_types.rst","appdev/refs/api/krb5_c_keylengths.rst","appdev/refs/api/krb5_c_make_checksum.rst","appdev/refs/api/krb5_c_make_checksum_iov.rst","appdev/refs/api/krb5_c_make_random_key.rst","appdev/refs/api/krb5_c_padding_length.rst","appdev/refs/api/krb5_c_prf.rst","appdev/refs/api/krb5_c_prf_length.rst","appdev/refs/api/krb5_c_prfplus.rst","appdev/refs/api/krb5_c_random_add_entropy.rst","appdev/refs/api/krb5_c_random_make_octets.rst","appdev/refs/api/krb5_c_random_os_entropy.rst","appdev/refs/api/krb5_c_random_seed.rst","appdev/refs/api/krb5_c_random_to_key.rst","appdev/refs/api/krb5_c_string_to_key.rst","appdev/refs/api/krb5_c_string_to_key_with_params.rst","appdev/refs/api/krb5_c_valid_cksumtype.rst","appdev/refs/api/krb5_c_valid_enctype.rst","appdev/refs/api/krb5_c_verify_checksum.rst","appdev/refs/api/krb5_c_verify_checksum_iov.rst","appdev/refs/api/krb5_calculate_checksum.rst","appdev/refs/api/krb5_cc_cache_match.rst","appdev/refs/api/krb5_cc_close.rst","appdev/refs/api/krb5_cc_copy_creds.rst","appdev/refs/api/krb5_cc_default.rst","appdev/refs/api/krb5_cc_default_name.rst","appdev/refs/api/krb5_cc_destroy.rst","appdev/refs/api/krb5_cc_dup.rst","appdev/refs/api/krb5_cc_end_seq_get.rst","appdev/refs/api/krb5_cc_gen_new.rst","appdev/refs/api/krb5_cc_get_config.rst","appdev/refs/api/krb5_cc_get_flags.rst","appdev/refs/api/krb5_cc_get_full_name.rst","appdev/refs/api/krb5_cc_get_name.rst","appdev/refs/api/krb5_cc_get_principal.rst","appdev/refs/api/krb5_cc_get_type.rst","appdev/refs/api/krb5_cc_initialize.rst","appdev/refs/api/krb5_cc_move.rst","appdev/refs/api/krb5_cc_new_unique.rst","appdev/refs/api/krb5_cc_next_cred.rst","appdev/refs/api/krb5_cc_remove_cred.rst","appdev/refs/api/krb5_cc_resolve.rst","appdev/refs/api/krb5_cc_retrieve_cred.rst","appdev/refs/api/krb5_cc_select.rst","appdev/refs/api/krb5_cc_set_config.rst","appdev/refs/api/krb5_cc_set_default_name.rst","appdev/refs/api/krb5_cc_set_flags.rst","appdev/refs/api/krb5_cc_start_seq_get.rst","appdev/refs/api/krb5_cc_store_cred.rst","appdev/refs/api/krb5_cc_support_switch.rst","appdev/refs/api/krb5_cc_switch.rst","appdev/refs/api/krb5_cccol_cursor_free.rst","appdev/refs/api/krb5_cccol_cursor_new.rst","appdev/refs/api/krb5_cccol_cursor_next.rst","appdev/refs/api/krb5_cccol_have_content.rst","appdev/refs/api/krb5_change_password.rst","appdev/refs/api/krb5_check_clockskew.rst","appdev/refs/api/krb5_checksum_size.rst","appdev/refs/api/krb5_chpw_message.rst","appdev/refs/api/krb5_cksumtype_to_string.rst","appdev/refs/api/krb5_clear_error_message.rst","appdev/refs/api/krb5_copy_addresses.rst","appdev/refs/api/krb5_copy_authdata.rst","appdev/refs/api/krb5_copy_authenticator.rst","appdev/refs/api/krb5_copy_checksum.rst","appdev/refs/api/krb5_copy_context.rst","appdev/refs/api/krb5_copy_creds.rst","appdev/refs/api/krb5_copy_data.rst","appdev/refs/api/krb5_copy_error_message.rst","appdev/refs/api/krb5_copy_keyblock.rst","appdev/refs/api/krb5_copy_keyblock_contents.rst","appdev/refs/api/krb5_copy_principal.rst","appdev/refs/api/krb5_copy_ticket.rst","appdev/refs/api/krb5_decode_authdata_container.rst","appdev/refs/api/krb5_decode_ticket.rst","appdev/refs/api/krb5_decrypt.rst","appdev/refs/api/krb5_deltat_to_string.rst","appdev/refs/api/krb5_eblock_enctype.rst","appdev/refs/api/krb5_encode_authdata_container.rst","appdev/refs/api/krb5_encrypt.rst","appdev/refs/api/krb5_encrypt_size.rst","appdev/refs/api/krb5_enctype_to_name.rst","appdev/refs/api/krb5_enctype_to_string.rst","appdev/refs/api/krb5_expand_hostname.rst","appdev/refs/api/krb5_find_authdata.rst","appdev/refs/api/krb5_finish_key.rst","appdev/refs/api/krb5_finish_random_key.rst","appdev/refs/api/krb5_free_addresses.rst","appdev/refs/api/krb5_free_ap_rep_enc_part.rst","appdev/refs/api/krb5_free_authdata.rst","appdev/refs/api/krb5_free_authenticator.rst","appdev/refs/api/krb5_free_checksum.rst","appdev/refs/api/krb5_free_checksum_contents.rst","appdev/refs/api/krb5_free_cksumtypes.rst","appdev/refs/api/krb5_free_context.rst","appdev/refs/api/krb5_free_cred_contents.rst","appdev/refs/api/krb5_free_creds.rst","appdev/refs/api/krb5_free_data.rst","appdev/refs/api/krb5_free_data_contents.rst","appdev/refs/api/krb5_free_default_realm.rst","appdev/refs/api/krb5_free_enctypes.rst","appdev/refs/api/krb5_free_error.rst","appdev/refs/api/krb5_free_error_message.rst","appdev/refs/api/krb5_free_host_realm.rst","appdev/refs/api/krb5_free_keyblock.rst","appdev/refs/api/krb5_free_keyblock_contents.rst","appdev/refs/api/krb5_free_keytab_entry_contents.rst","appdev/refs/api/krb5_free_principal.rst","appdev/refs/api/krb5_free_string.rst","appdev/refs/api/krb5_free_tgt_creds.rst","appdev/refs/api/krb5_free_ticket.rst","appdev/refs/api/krb5_free_unparsed_name.rst","appdev/refs/api/krb5_fwd_tgt_creds.rst","appdev/refs/api/krb5_get_credentials.rst","appdev/refs/api/krb5_get_credentials_renew.rst","appdev/refs/api/krb5_get_credentials_validate.rst","appdev/refs/api/krb5_get_default_realm.rst","appdev/refs/api/krb5_get_error_message.rst","appdev/refs/api/krb5_get_etype_info.rst","appdev/refs/api/krb5_get_fallback_host_realm.rst","appdev/refs/api/krb5_get_host_realm.rst","appdev/refs/api/krb5_get_in_tkt_with_keytab.rst","appdev/refs/api/krb5_get_in_tkt_with_password.rst","appdev/refs/api/krb5_get_in_tkt_with_skey.rst","appdev/refs/api/krb5_get_init_creds_keytab.rst","appdev/refs/api/krb5_get_init_creds_opt_alloc.rst","appdev/refs/api/krb5_get_init_creds_opt_free.rst","appdev/refs/api/krb5_get_init_creds_opt_get_fast_flags.rst","appdev/refs/api/krb5_get_init_creds_opt_init.rst","appdev/refs/api/krb5_get_init_creds_opt_set_address_list.rst","appdev/refs/api/krb5_get_init_creds_opt_set_anonymous.rst","appdev/refs/api/krb5_get_init_creds_opt_set_canonicalize.rst","appdev/refs/api/krb5_get_init_creds_opt_set_change_password_prompt.rst","appdev/refs/api/krb5_get_init_creds_opt_set_etype_list.rst","appdev/refs/api/krb5_get_init_creds_opt_set_expire_callback.rst","appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache.rst","appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache_name.rst","appdev/refs/api/krb5_get_init_creds_opt_set_fast_flags.rst","appdev/refs/api/krb5_get_init_creds_opt_set_forwardable.rst","appdev/refs/api/krb5_get_init_creds_opt_set_in_ccache.rst","appdev/refs/api/krb5_get_init_creds_opt_set_out_ccache.rst","appdev/refs/api/krb5_get_init_creds_opt_set_pa.rst","appdev/refs/api/krb5_get_init_creds_opt_set_pac_request.rst","appdev/refs/api/krb5_get_init_creds_opt_set_preauth_list.rst","appdev/refs/api/krb5_get_init_creds_opt_set_proxiable.rst","appdev/refs/api/krb5_get_init_creds_opt_set_renew_life.rst","appdev/refs/api/krb5_get_init_creds_opt_set_responder.rst","appdev/refs/api/krb5_get_init_creds_opt_set_salt.rst","appdev/refs/api/krb5_get_init_creds_opt_set_tkt_life.rst","appdev/refs/api/krb5_get_init_creds_password.rst","appdev/refs/api/krb5_get_permitted_enctypes.rst","appdev/refs/api/krb5_get_profile.rst","appdev/refs/api/krb5_get_prompt_types.rst","appdev/refs/api/krb5_get_renewed_creds.rst","appdev/refs/api/krb5_get_server_rcache.rst","appdev/refs/api/krb5_get_time_offsets.rst","appdev/refs/api/krb5_get_validated_creds.rst","appdev/refs/api/krb5_init_context.rst","appdev/refs/api/krb5_init_context_profile.rst","appdev/refs/api/krb5_init_creds_free.rst","appdev/refs/api/krb5_init_creds_get.rst","appdev/refs/api/krb5_init_creds_get_creds.rst","appdev/refs/api/krb5_init_creds_get_error.rst","appdev/refs/api/krb5_init_creds_get_times.rst","appdev/refs/api/krb5_init_creds_init.rst","appdev/refs/api/krb5_init_creds_set_keytab.rst","appdev/refs/api/krb5_init_creds_set_password.rst","appdev/refs/api/krb5_init_creds_set_service.rst","appdev/refs/api/krb5_init_creds_step.rst","appdev/refs/api/krb5_init_keyblock.rst","appdev/refs/api/krb5_init_random_key.rst","appdev/refs/api/krb5_init_secure_context.rst","appdev/refs/api/krb5_is_config_principal.rst","appdev/refs/api/krb5_is_referral_realm.rst","appdev/refs/api/krb5_is_thread_safe.rst","appdev/refs/api/krb5_k_create_key.rst","appdev/refs/api/krb5_k_decrypt.rst","appdev/refs/api/krb5_k_decrypt_iov.rst","appdev/refs/api/krb5_k_encrypt.rst","appdev/refs/api/krb5_k_encrypt_iov.rst","appdev/refs/api/krb5_k_free_key.rst","appdev/refs/api/krb5_k_key_enctype.rst","appdev/refs/api/krb5_k_key_keyblock.rst","appdev/refs/api/krb5_k_make_checksum.rst","appdev/refs/api/krb5_k_make_checksum_iov.rst","appdev/refs/api/krb5_k_prf.rst","appdev/refs/api/krb5_k_reference_key.rst","appdev/refs/api/krb5_k_verify_checksum.rst","appdev/refs/api/krb5_k_verify_checksum_iov.rst","appdev/refs/api/krb5_kdc_sign_ticket.rst","appdev/refs/api/krb5_kdc_verify_ticket.rst","appdev/refs/api/krb5_kt_add_entry.rst","appdev/refs/api/krb5_kt_client_default.rst","appdev/refs/api/krb5_kt_close.rst","appdev/refs/api/krb5_kt_default.rst","appdev/refs/api/krb5_kt_default_name.rst","appdev/refs/api/krb5_kt_dup.rst","appdev/refs/api/krb5_kt_end_seq_get.rst","appdev/refs/api/krb5_kt_free_entry.rst","appdev/refs/api/krb5_kt_get_entry.rst","appdev/refs/api/krb5_kt_get_name.rst","appdev/refs/api/krb5_kt_get_type.rst","appdev/refs/api/krb5_kt_have_content.rst","appdev/refs/api/krb5_kt_next_entry.rst","appdev/refs/api/krb5_kt_read_service_key.rst","appdev/refs/api/krb5_kt_remove_entry.rst","appdev/refs/api/krb5_kt_resolve.rst","appdev/refs/api/krb5_kt_start_seq_get.rst","appdev/refs/api/krb5_kuserok.rst","appdev/refs/api/krb5_make_authdata_kdc_issued.rst","appdev/refs/api/krb5_marshal_credentials.rst","appdev/refs/api/krb5_merge_authdata.rst","appdev/refs/api/krb5_mk_1cred.rst","appdev/refs/api/krb5_mk_error.rst","appdev/refs/api/krb5_mk_ncred.rst","appdev/refs/api/krb5_mk_priv.rst","appdev/refs/api/krb5_mk_rep.rst","appdev/refs/api/krb5_mk_rep_dce.rst","appdev/refs/api/krb5_mk_req.rst","appdev/refs/api/krb5_mk_req_extended.rst","appdev/refs/api/krb5_mk_safe.rst","appdev/refs/api/krb5_os_localaddr.rst","appdev/refs/api/krb5_pac_add_buffer.rst","appdev/refs/api/krb5_pac_free.rst","appdev/refs/api/krb5_pac_get_buffer.rst","appdev/refs/api/krb5_pac_get_client_info.rst","appdev/refs/api/krb5_pac_get_types.rst","appdev/refs/api/krb5_pac_init.rst","appdev/refs/api/krb5_pac_parse.rst","appdev/refs/api/krb5_pac_sign.rst","appdev/refs/api/krb5_pac_sign_ext.rst","appdev/refs/api/krb5_pac_verify.rst","appdev/refs/api/krb5_pac_verify_ext.rst","appdev/refs/api/krb5_parse_name.rst","appdev/refs/api/krb5_parse_name_flags.rst","appdev/refs/api/krb5_prepend_error_message.rst","appdev/refs/api/krb5_principal2salt.rst","appdev/refs/api/krb5_principal_compare.rst","appdev/refs/api/krb5_principal_compare_any_realm.rst","appdev/refs/api/krb5_principal_compare_flags.rst","appdev/refs/api/krb5_process_key.rst","appdev/refs/api/krb5_prompter_posix.rst","appdev/refs/api/krb5_random_key.rst","appdev/refs/api/krb5_rd_cred.rst","appdev/refs/api/krb5_rd_error.rst","appdev/refs/api/krb5_rd_priv.rst","appdev/refs/api/krb5_rd_rep.rst","appdev/refs/api/krb5_rd_rep_dce.rst","appdev/refs/api/krb5_rd_req.rst","appdev/refs/api/krb5_rd_safe.rst","appdev/refs/api/krb5_read_password.rst","appdev/refs/api/krb5_realm_compare.rst","appdev/refs/api/krb5_recvauth.rst","appdev/refs/api/krb5_recvauth_version.rst","appdev/refs/api/krb5_responder_get_challenge.rst","appdev/refs/api/krb5_responder_list_questions.rst","appdev/refs/api/krb5_responder_otp_challenge_free.rst","appdev/refs/api/krb5_responder_otp_get_challenge.rst","appdev/refs/api/krb5_responder_otp_set_answer.rst","appdev/refs/api/krb5_responder_pkinit_challenge_free.rst","appdev/refs/api/krb5_responder_pkinit_get_challenge.rst","appdev/refs/api/krb5_responder_pkinit_set_answer.rst","appdev/refs/api/krb5_responder_set_answer.rst","appdev/refs/api/krb5_salttype_to_string.rst","appdev/refs/api/krb5_sendauth.rst","appdev/refs/api/krb5_server_decrypt_ticket_keytab.rst","appdev/refs/api/krb5_set_default_realm.rst","appdev/refs/api/krb5_set_default_tgs_enctypes.rst","appdev/refs/api/krb5_set_error_message.rst","appdev/refs/api/krb5_set_kdc_recv_hook.rst","appdev/refs/api/krb5_set_kdc_send_hook.rst","appdev/refs/api/krb5_set_password.rst","appdev/refs/api/krb5_set_password_using_ccache.rst","appdev/refs/api/krb5_set_principal_realm.rst","appdev/refs/api/krb5_set_real_time.rst","appdev/refs/api/krb5_set_trace_callback.rst","appdev/refs/api/krb5_set_trace_filename.rst","appdev/refs/api/krb5_sname_match.rst","appdev/refs/api/krb5_sname_to_principal.rst","appdev/refs/api/krb5_string_to_cksumtype.rst","appdev/refs/api/krb5_string_to_deltat.rst","appdev/refs/api/krb5_string_to_enctype.rst","appdev/refs/api/krb5_string_to_key.rst","appdev/refs/api/krb5_string_to_salttype.rst","appdev/refs/api/krb5_string_to_timestamp.rst","appdev/refs/api/krb5_timeofday.rst","appdev/refs/api/krb5_timestamp_to_sfstring.rst","appdev/refs/api/krb5_timestamp_to_string.rst","appdev/refs/api/krb5_tkt_creds_free.rst","appdev/refs/api/krb5_tkt_creds_get.rst","appdev/refs/api/krb5_tkt_creds_get_creds.rst","appdev/refs/api/krb5_tkt_creds_get_times.rst","appdev/refs/api/krb5_tkt_creds_init.rst","appdev/refs/api/krb5_tkt_creds_step.rst","appdev/refs/api/krb5_unmarshal_credentials.rst","appdev/refs/api/krb5_unparse_name.rst","appdev/refs/api/krb5_unparse_name_ext.rst","appdev/refs/api/krb5_unparse_name_flags.rst","appdev/refs/api/krb5_unparse_name_flags_ext.rst","appdev/refs/api/krb5_us_timeofday.rst","appdev/refs/api/krb5_use_enctype.rst","appdev/refs/api/krb5_verify_authdata_kdc_issued.rst","appdev/refs/api/krb5_verify_checksum.rst","appdev/refs/api/krb5_verify_init_creds.rst","appdev/refs/api/krb5_verify_init_creds_opt_init.rst","appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail.rst","appdev/refs/api/krb5_vprepend_error_message.rst","appdev/refs/api/krb5_vset_error_message.rst","appdev/refs/api/krb5_vwrap_error_message.rst","appdev/refs/api/krb5_wrap_error_message.rst","appdev/refs/index.rst","appdev/refs/macros/ADDRTYPE_ADDRPORT.rst","appdev/refs/macros/ADDRTYPE_CHAOS.rst","appdev/refs/macros/ADDRTYPE_DDP.rst","appdev/refs/macros/ADDRTYPE_INET.rst","appdev/refs/macros/ADDRTYPE_INET6.rst","appdev/refs/macros/ADDRTYPE_IPPORT.rst","appdev/refs/macros/ADDRTYPE_ISO.rst","appdev/refs/macros/ADDRTYPE_IS_LOCAL.rst","appdev/refs/macros/ADDRTYPE_NETBIOS.rst","appdev/refs/macros/ADDRTYPE_XNS.rst","appdev/refs/macros/AD_TYPE_EXTERNAL.rst","appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK.rst","appdev/refs/macros/AD_TYPE_REGISTERED.rst","appdev/refs/macros/AD_TYPE_RESERVED.rst","appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION.rst","appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED.rst","appdev/refs/macros/AP_OPTS_RESERVED.rst","appdev/refs/macros/AP_OPTS_USE_SESSION_KEY.rst","appdev/refs/macros/AP_OPTS_USE_SUBKEY.rst","appdev/refs/macros/AP_OPTS_WIRE_MASK.rst","appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128.rst","appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256.rst","appdev/refs/macros/CKSUMTYPE_CRC32.rst","appdev/refs/macros/CKSUMTYPE_DESCBC.rst","appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR.rst","appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128.rst","appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256.rst","appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3.rst","appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128.rst","appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256.rst","appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR.rst","appdev/refs/macros/CKSUMTYPE_NIST_SHA.rst","appdev/refs/macros/CKSUMTYPE_RSA_MD4.rst","appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES.rst","appdev/refs/macros/CKSUMTYPE_RSA_MD5.rst","appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES.rst","appdev/refs/macros/CKSUMTYPE_SHA1.rst","appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96.rst","appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128.rst","appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96.rst","appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192.rst","appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC.rst","appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP.rst","appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC.rst","appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC.rst","appdev/refs/macros/ENCTYPE_DES3_CBC_ENV.rst","appdev/refs/macros/ENCTYPE_DES3_CBC_RAW.rst","appdev/refs/macros/ENCTYPE_DES3_CBC_SHA.rst","appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1.rst","appdev/refs/macros/ENCTYPE_DES_CBC_CRC.rst","appdev/refs/macros/ENCTYPE_DES_CBC_MD4.rst","appdev/refs/macros/ENCTYPE_DES_CBC_MD5.rst","appdev/refs/macros/ENCTYPE_DES_CBC_RAW.rst","appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1.rst","appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS.rst","appdev/refs/macros/ENCTYPE_MD5_RSA_CMS.rst","appdev/refs/macros/ENCTYPE_NULL.rst","appdev/refs/macros/ENCTYPE_RC2_CBC_ENV.rst","appdev/refs/macros/ENCTYPE_RSA_ENV.rst","appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV.rst","appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS.rst","appdev/refs/macros/ENCTYPE_UNKNOWN.rst","appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE.rst","appdev/refs/macros/KDC_OPT_CANONICALIZE.rst","appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT.rst","appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK.rst","appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY.rst","appdev/refs/macros/KDC_OPT_FORWARDABLE.rst","appdev/refs/macros/KDC_OPT_FORWARDED.rst","appdev/refs/macros/KDC_OPT_POSTDATED.rst","appdev/refs/macros/KDC_OPT_PROXIABLE.rst","appdev/refs/macros/KDC_OPT_PROXY.rst","appdev/refs/macros/KDC_OPT_RENEW.rst","appdev/refs/macros/KDC_OPT_RENEWABLE.rst","appdev/refs/macros/KDC_OPT_RENEWABLE_OK.rst","appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS.rst","appdev/refs/macros/KDC_OPT_VALIDATE.rst","appdev/refs/macros/KDC_TKT_COMMON_MASK.rst","appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE.rst","appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR.rst","appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR.rst","appdev/refs/macros/KRB5_AP_REP.rst","appdev/refs/macros/KRB5_AP_REQ.rst","appdev/refs/macros/KRB5_AS_REP.rst","appdev/refs/macros/KRB5_AS_REQ.rst","appdev/refs/macros/KRB5_AUTHDATA_AND_OR.rst","appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS.rst","appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR.rst","appdev/refs/macros/KRB5_AUTHDATA_CAMMAC.rst","appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION.rst","appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR.rst","appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT.rst","appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS.rst","appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED.rst","appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC.rst","appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE.rst","appdev/refs/macros/KRB5_AUTHDATA_SESAME.rst","appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET.rst","appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC.rst","appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE.rst","appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME.rst","appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR.rst","appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR.rst","appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR.rst","appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR.rst","appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL.rst","appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE.rst","appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME.rst","appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY.rst","appdev/refs/macros/KRB5_CRED.rst","appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM.rst","appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA.rst","appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY.rst","appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER.rst","appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING.rst","appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY.rst","appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM.rst","appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER.rst","appdev/refs/macros/KRB5_CYBERSAFE_SECUREID.rst","appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS.rst","appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP.rst","appdev/refs/macros/KRB5_ERROR.rst","appdev/refs/macros/KRB5_FAST_REQUIRED.rst","appdev/refs/macros/KRB5_GC_CACHED.rst","appdev/refs/macros/KRB5_GC_CANONICALIZE.rst","appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION.rst","appdev/refs/macros/KRB5_GC_FORWARDABLE.rst","appdev/refs/macros/KRB5_GC_NO_STORE.rst","appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK.rst","appdev/refs/macros/KRB5_GC_USER_USER.rst","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST.rst","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS.rst","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE.rst","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT.rst","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST.rst","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE.rst","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST.rst","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE.rst","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE.rst","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT.rst","appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE.rst","appdev/refs/macros/KRB5_INIT_CONTEXT_KDC.rst","appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE.rst","appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE.rst","appdev/refs/macros/KRB5_INT16_MAX.rst","appdev/refs/macros/KRB5_INT16_MIN.rst","appdev/refs/macros/KRB5_INT32_MAX.rst","appdev/refs/macros/KRB5_INT32_MIN.rst","appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE.rst","appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM.rst","appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE.rst","appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH.rst","appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM.rst","appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT.rst","appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART.rst","appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH.rst","appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM.rst","appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART.rst","appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ.rst","appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS.rst","appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC.rst","appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT.rst","appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC.rst","appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC.rst","appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED.rst","appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP.rst","appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM.rst","appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC.rst","appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG.rst","appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV.rst","appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED.rst","appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET.rst","appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART.rst","appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM.rst","appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART.rst","appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM.rst","appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS.rst","appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE.rst","appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST.rst","appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX.rst","appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY.rst","appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST.rst","appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM.rst","appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID.rst","appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE.rst","appdev/refs/macros/KRB5_KEYUSAGE_SPAKE.rst","appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY.rst","appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY.rst","appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY.rst","appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY.rst","appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH.rst","appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM.rst","appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED.rst","appdev/refs/macros/KRB5_KPASSWD_AUTHERROR.rst","appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION.rst","appdev/refs/macros/KRB5_KPASSWD_HARDERROR.rst","appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED.rst","appdev/refs/macros/KRB5_KPASSWD_MALFORMED.rst","appdev/refs/macros/KRB5_KPASSWD_SOFTERROR.rst","appdev/refs/macros/KRB5_KPASSWD_SUCCESS.rst","appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME.rst","appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL.rst","appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL.rst","appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ.rst","appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT.rst","appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED.rst","appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME.rst","appdev/refs/macros/KRB5_LRQ_NONE.rst","appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME.rst","appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL.rst","appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL.rst","appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ.rst","appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT.rst","appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED.rst","appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME.rst","appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL.rst","appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID.rst","appdev/refs/macros/KRB5_NT_MS_PRINCIPAL.rst","appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID.rst","appdev/refs/macros/KRB5_NT_PRINCIPAL.rst","appdev/refs/macros/KRB5_NT_SMTP_NAME.rst","appdev/refs/macros/KRB5_NT_SRV_HST.rst","appdev/refs/macros/KRB5_NT_SRV_INST.rst","appdev/refs/macros/KRB5_NT_SRV_XHST.rst","appdev/refs/macros/KRB5_NT_UID.rst","appdev/refs/macros/KRB5_NT_UNKNOWN.rst","appdev/refs/macros/KRB5_NT_WELLKNOWN.rst","appdev/refs/macros/KRB5_NT_X500_PRINCIPAL.rst","appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO.rst","appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS.rst","appdev/refs/macros/KRB5_PAC_CLIENT_INFO.rst","appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO.rst","appdev/refs/macros/KRB5_PAC_DELEGATION_INFO.rst","appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS.rst","appdev/refs/macros/KRB5_PAC_DEVICE_INFO.rst","appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM.rst","appdev/refs/macros/KRB5_PAC_LOGON_INFO.rst","appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM.rst","appdev/refs/macros/KRB5_PAC_REQUESTOR.rst","appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM.rst","appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM.rst","appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO.rst","appdev/refs/macros/KRB5_PADATA_AFS3_SALT.rst","appdev/refs/macros/KRB5_PADATA_AP_REQ.rst","appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM.rst","appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS.rst","appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE.rst","appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID.rst","appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP.rst","appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME.rst","appdev/refs/macros/KRB5_PADATA_ETYPE_INFO.rst","appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2.rst","appdev/refs/macros/KRB5_PADATA_FOR_USER.rst","appdev/refs/macros/KRB5_PADATA_FX_COOKIE.rst","appdev/refs/macros/KRB5_PADATA_FX_ERROR.rst","appdev/refs/macros/KRB5_PADATA_FX_FAST.rst","appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA.rst","appdev/refs/macros/KRB5_PADATA_NONE.rst","appdev/refs/macros/KRB5_PADATA_OSF_DCE.rst","appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE.rst","appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE.rst","appdev/refs/macros/KRB5_PADATA_OTP_REQUEST.rst","appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS.rst","appdev/refs/macros/KRB5_PADATA_PAC_REQUEST.rst","appdev/refs/macros/KRB5_PADATA_PKINIT_KX.rst","appdev/refs/macros/KRB5_PADATA_PK_AS_REP.rst","appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD.rst","appdev/refs/macros/KRB5_PADATA_PK_AS_REQ.rst","appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD.rst","appdev/refs/macros/KRB5_PADATA_PW_SALT.rst","appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2.rst","appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY.rst","appdev/refs/macros/KRB5_PADATA_REFERRAL.rst","appdev/refs/macros/KRB5_PADATA_S4U_X509_USER.rst","appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE.rst","appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2.rst","appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT.rst","appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE.rst","appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2.rst","appdev/refs/macros/KRB5_PADATA_SESAME.rst","appdev/refs/macros/KRB5_PADATA_SPAKE.rst","appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO.rst","appdev/refs/macros/KRB5_PADATA_TGS_REQ.rst","appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO.rst","appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD.rst","appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE.rst","appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM.rst","appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8.rst","appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE.rst","appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM.rst","appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM.rst","appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM.rst","appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM.rst","appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY.rst","appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM.rst","appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT.rst","appdev/refs/macros/KRB5_PRIV.rst","appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD.rst","appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN.rst","appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD.rst","appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH.rst","appdev/refs/macros/KRB5_PVNO.rst","appdev/refs/macros/KRB5_REALM_BRANCH_CHAR.rst","appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS.rst","appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION.rst","appdev/refs/macros/KRB5_REFERRAL_REALM.rst","appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN.rst","appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN.rst","appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP.rst","appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN.rst","appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC.rst","appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL.rst","appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL.rst","appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW.rst","appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY.rst","appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED.rst","appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP.rst","appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD.rst","appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT.rst","appdev/refs/macros/KRB5_SAFE.rst","appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD.rst","appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD.rst","appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY.rst","appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT.rst","appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA.rst","appdev/refs/macros/KRB5_TC_MATCH_FLAGS.rst","appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT.rst","appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY.rst","appdev/refs/macros/KRB5_TC_MATCH_KTYPE.rst","appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY.rst","appdev/refs/macros/KRB5_TC_MATCH_TIMES.rst","appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT.rst","appdev/refs/macros/KRB5_TC_NOTICKET.rst","appdev/refs/macros/KRB5_TC_OPENCLOSE.rst","appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES.rst","appdev/refs/macros/KRB5_TGS_NAME.rst","appdev/refs/macros/KRB5_TGS_NAME_SIZE.rst","appdev/refs/macros/KRB5_TGS_REP.rst","appdev/refs/macros/KRB5_TGS_REQ.rst","appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE.rst","appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL.rst","appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR.rst","appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK.rst","appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY.rst","appdev/refs/macros/MAX_KEYTAB_NAME_LEN.rst","appdev/refs/macros/MSEC_DIRBIT.rst","appdev/refs/macros/MSEC_VAL_MASK.rst","appdev/refs/macros/SALT_TYPE_AFS_LENGTH.rst","appdev/refs/macros/SALT_TYPE_NO_LENGTH.rst","appdev/refs/macros/THREEPARAMOPEN.rst","appdev/refs/macros/TKT_FLG_ANONYMOUS.rst","appdev/refs/macros/TKT_FLG_ENC_PA_REP.rst","appdev/refs/macros/TKT_FLG_FORWARDABLE.rst","appdev/refs/macros/TKT_FLG_FORWARDED.rst","appdev/refs/macros/TKT_FLG_HW_AUTH.rst","appdev/refs/macros/TKT_FLG_INITIAL.rst","appdev/refs/macros/TKT_FLG_INVALID.rst","appdev/refs/macros/TKT_FLG_MAY_POSTDATE.rst","appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE.rst","appdev/refs/macros/TKT_FLG_POSTDATED.rst","appdev/refs/macros/TKT_FLG_PRE_AUTH.rst","appdev/refs/macros/TKT_FLG_PROXIABLE.rst","appdev/refs/macros/TKT_FLG_PROXY.rst","appdev/refs/macros/TKT_FLG_RENEWABLE.rst","appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED.rst","appdev/refs/macros/VALID_INT_BITS.rst","appdev/refs/macros/VALID_UINT_BITS.rst","appdev/refs/macros/index.rst","appdev/refs/macros/krb524_convert_creds_kdc.rst","appdev/refs/macros/krb524_init_ets.rst","appdev/refs/macros/krb5_const.rst","appdev/refs/macros/krb5_princ_component.rst","appdev/refs/macros/krb5_princ_name.rst","appdev/refs/macros/krb5_princ_realm.rst","appdev/refs/macros/krb5_princ_set_realm.rst","appdev/refs/macros/krb5_princ_set_realm_data.rst","appdev/refs/macros/krb5_princ_set_realm_length.rst","appdev/refs/macros/krb5_princ_size.rst","appdev/refs/macros/krb5_princ_type.rst","appdev/refs/macros/krb5_roundup.rst","appdev/refs/macros/krb5_x.rst","appdev/refs/macros/krb5_xc.rst","appdev/refs/types/index.rst","appdev/refs/types/krb5_address.rst","appdev/refs/types/krb5_addrtype.rst","appdev/refs/types/krb5_ap_rep.rst","appdev/refs/types/krb5_ap_rep_enc_part.rst","appdev/refs/types/krb5_ap_req.rst","appdev/refs/types/krb5_auth_context.rst","appdev/refs/types/krb5_authdata.rst","appdev/refs/types/krb5_authdatatype.rst","appdev/refs/types/krb5_authenticator.rst","appdev/refs/types/krb5_boolean.rst","appdev/refs/types/krb5_cc_cursor.rst","appdev/refs/types/krb5_ccache.rst","appdev/refs/types/krb5_cccol_cursor.rst","appdev/refs/types/krb5_checksum.rst","appdev/refs/types/krb5_cksumtype.rst","appdev/refs/types/krb5_const_pointer.rst","appdev/refs/types/krb5_const_principal.rst","appdev/refs/types/krb5_context.rst","appdev/refs/types/krb5_cred.rst","appdev/refs/types/krb5_cred_enc_part.rst","appdev/refs/types/krb5_cred_info.rst","appdev/refs/types/krb5_creds.rst","appdev/refs/types/krb5_crypto_iov.rst","appdev/refs/types/krb5_cryptotype.rst","appdev/refs/types/krb5_data.rst","appdev/refs/types/krb5_deltat.rst","appdev/refs/types/krb5_enc_data.rst","appdev/refs/types/krb5_enc_kdc_rep_part.rst","appdev/refs/types/krb5_enc_tkt_part.rst","appdev/refs/types/krb5_encrypt_block.rst","appdev/refs/types/krb5_enctype.rst","appdev/refs/types/krb5_error.rst","appdev/refs/types/krb5_error_code.rst","appdev/refs/types/krb5_expire_callback_func.rst","appdev/refs/types/krb5_flags.rst","appdev/refs/types/krb5_get_init_creds_opt.rst","appdev/refs/types/krb5_gic_opt_pa_data.rst","appdev/refs/types/krb5_init_creds_context.rst","appdev/refs/types/krb5_int16.rst","appdev/refs/types/krb5_int32.rst","appdev/refs/types/krb5_kdc_rep.rst","appdev/refs/types/krb5_kdc_req.rst","appdev/refs/types/krb5_key.rst","appdev/refs/types/krb5_keyblock.rst","appdev/refs/types/krb5_keytab.rst","appdev/refs/types/krb5_keytab_entry.rst","appdev/refs/types/krb5_keyusage.rst","appdev/refs/types/krb5_kt_cursor.rst","appdev/refs/types/krb5_kvno.rst","appdev/refs/types/krb5_last_req_entry.rst","appdev/refs/types/krb5_magic.rst","appdev/refs/types/krb5_mk_req_checksum_func.rst","appdev/refs/types/krb5_msgtype.rst","appdev/refs/types/krb5_octet.rst","appdev/refs/types/krb5_pa_data.rst","appdev/refs/types/krb5_pa_pac_req.rst","appdev/refs/types/krb5_pa_server_referral_data.rst","appdev/refs/types/krb5_pa_svr_referral_data.rst","appdev/refs/types/krb5_pac.rst","appdev/refs/types/krb5_pointer.rst","appdev/refs/types/krb5_post_recv_fn.rst","appdev/refs/types/krb5_pre_send_fn.rst","appdev/refs/types/krb5_preauthtype.rst","appdev/refs/types/krb5_principal.rst","appdev/refs/types/krb5_principal_data.rst","appdev/refs/types/krb5_prompt.rst","appdev/refs/types/krb5_prompt_type.rst","appdev/refs/types/krb5_prompter_fct.rst","appdev/refs/types/krb5_pwd_data.rst","appdev/refs/types/krb5_rcache.rst","appdev/refs/types/krb5_replay_data.rst","appdev/refs/types/krb5_responder_context.rst","appdev/refs/types/krb5_responder_fn.rst","appdev/refs/types/krb5_responder_otp_challenge.rst","appdev/refs/types/krb5_responder_otp_tokeninfo.rst","appdev/refs/types/krb5_responder_pkinit_challenge.rst","appdev/refs/types/krb5_responder_pkinit_identity.rst","appdev/refs/types/krb5_response.rst","appdev/refs/types/krb5_ticket.rst","appdev/refs/types/krb5_ticket_times.rst","appdev/refs/types/krb5_timestamp.rst","appdev/refs/types/krb5_tkt_authent.rst","appdev/refs/types/krb5_tkt_creds_context.rst","appdev/refs/types/krb5_trace_callback.rst","appdev/refs/types/krb5_trace_info.rst","appdev/refs/types/krb5_transited.rst","appdev/refs/types/krb5_typed_data.rst","appdev/refs/types/krb5_ui_2.rst","appdev/refs/types/krb5_ui_4.rst","appdev/refs/types/krb5_verify_init_creds_opt.rst","appdev/refs/types/passwd_phrase_element.rst","appdev/y2038.rst","basic/ccache_def.rst","basic/date_format.rst","basic/index.rst","basic/keytab_def.rst","basic/rcache_def.rst","basic/stash_file_def.rst","build/directory_org.rst","build/doing_build.rst","build/index.rst","build/options2configure.rst","build/osconf.rst","build_this.rst","copyright.rst","formats/ccache_file_format.rst","formats/cookie.rst","formats/freshness_token.rst","formats/index.rst","formats/keytab_file_format.rst","formats/rcache_file_format.rst","index.rst","mitK5defaults.rst","mitK5features.rst","mitK5license.rst","plugindev/ccselect.rst","plugindev/certauth.rst","plugindev/clpreauth.rst","plugindev/general.rst","plugindev/gssapi.rst","plugindev/hostrealm.rst","plugindev/index.rst","plugindev/internal.rst","plugindev/kadm5_auth.rst","plugindev/kadm5_hook.rst","plugindev/kdcpolicy.rst","plugindev/kdcpreauth.rst","plugindev/localauth.rst","plugindev/locate.rst","plugindev/profile.rst","plugindev/pwqual.rst","resources.rst","user/index.rst","user/pwd_mgmt.rst","user/tkt_mgmt.rst","user/user_commands/index.rst","user/user_commands/kdestroy.rst","user/user_commands/kinit.rst","user/user_commands/klist.rst","user/user_commands/kpasswd.rst","user/user_commands/krb5-config.rst","user/user_commands/ksu.rst","user/user_commands/kswitch.rst","user/user_commands/kvno.rst","user/user_commands/sclient.rst","user/user_config/index.rst","user/user_config/k5identity.rst","user/user_config/k5login.rst","user/user_config/kerberos.rst"],objects:{"":[[49,0,1,"c.krb5_425_conv_principal","krb5_425_conv_principal"],[50,0,1,"c.krb5_524_conv_principal","krb5_524_conv_principal"],[51,0,1,"c.krb5_524_convert_creds","krb5_524_convert_creds"],[805,2,1,"c.krb5_address","krb5_address"],[52,0,1,"c.krb5_address_compare","krb5_address_compare"],[53,0,1,"c.krb5_address_order","krb5_address_order"],[54,0,1,"c.krb5_address_search","krb5_address_search"],[806,2,1,"c.krb5_addrtype","krb5_addrtype"],[55,0,1,"c.krb5_allow_weak_crypto","krb5_allow_weak_crypto"],[56,0,1,"c.krb5_aname_to_localname","krb5_aname_to_localname"],[57,0,1,"c.krb5_anonymous_principal","krb5_anonymous_principal"],[58,0,1,"c.krb5_anonymous_realm","krb5_anonymous_realm"],[807,2,1,"c.krb5_ap_rep","krb5_ap_rep"],[808,2,1,"c.krb5_ap_rep_enc_part","krb5_ap_rep_enc_part"],[809,2,1,"c.krb5_ap_req","krb5_ap_req"],[59,0,1,"c.krb5_appdefault_boolean","krb5_appdefault_boolean"],[60,0,1,"c.krb5_appdefault_string","krb5_appdefault_string"],[61,0,1,"c.krb5_auth_con_free","krb5_auth_con_free"],[62,0,1,"c.krb5_auth_con_genaddrs","krb5_auth_con_genaddrs"],[63,0,1,"c.krb5_auth_con_get_checksum_func","krb5_auth_con_get_checksum_func"],[64,0,1,"c.krb5_auth_con_getaddrs","krb5_auth_con_getaddrs"],[65,0,1,"c.krb5_auth_con_getauthenticator","krb5_auth_con_getauthenticator"],[66,0,1,"c.krb5_auth_con_getflags","krb5_auth_con_getflags"],[67,0,1,"c.krb5_auth_con_getkey","krb5_auth_con_getkey"],[68,0,1,"c.krb5_auth_con_getkey_k","krb5_auth_con_getkey_k"],[69,0,1,"c.krb5_auth_con_getlocalseqnumber","krb5_auth_con_getlocalseqnumber"],[70,0,1,"c.krb5_auth_con_getlocalsubkey","krb5_auth_con_getlocalsubkey"],[71,0,1,"c.krb5_auth_con_getrcache","krb5_auth_con_getrcache"],[72,0,1,"c.krb5_auth_con_getrecvsubkey","krb5_auth_con_getrecvsubkey"],[73,0,1,"c.krb5_auth_con_getrecvsubkey_k","krb5_auth_con_getrecvsubkey_k"],[74,0,1,"c.krb5_auth_con_getremoteseqnumber","krb5_auth_con_getremoteseqnumber"],[75,0,1,"c.krb5_auth_con_getremotesubkey","krb5_auth_con_getremotesubkey"],[76,0,1,"c.krb5_auth_con_getsendsubkey","krb5_auth_con_getsendsubkey"],[77,0,1,"c.krb5_auth_con_getsendsubkey_k","krb5_auth_con_getsendsubkey_k"],[78,0,1,"c.krb5_auth_con_init","krb5_auth_con_init"],[79,0,1,"c.krb5_auth_con_initivector","krb5_auth_con_initivector"],[80,0,1,"c.krb5_auth_con_set_checksum_func","krb5_auth_con_set_checksum_func"],[81,0,1,"c.krb5_auth_con_set_req_cksumtype","krb5_auth_con_set_req_cksumtype"],[82,0,1,"c.krb5_auth_con_setaddrs","krb5_auth_con_setaddrs"],[83,0,1,"c.krb5_auth_con_setflags","krb5_auth_con_setflags"],[84,0,1,"c.krb5_auth_con_setports","krb5_auth_con_setports"],[85,0,1,"c.krb5_auth_con_setrcache","krb5_auth_con_setrcache"],[86,0,1,"c.krb5_auth_con_setrecvsubkey","krb5_auth_con_setrecvsubkey"],[87,0,1,"c.krb5_auth_con_setrecvsubkey_k","krb5_auth_con_setrecvsubkey_k"],[88,0,1,"c.krb5_auth_con_setsendsubkey","krb5_auth_con_setsendsubkey"],[89,0,1,"c.krb5_auth_con_setsendsubkey_k","krb5_auth_con_setsendsubkey_k"],[90,0,1,"c.krb5_auth_con_setuseruserkey","krb5_auth_con_setuseruserkey"],[810,2,1,"c.krb5_auth_context","krb5_auth_context"],[811,2,1,"c.krb5_authdata","krb5_authdata"],[812,2,1,"c.krb5_authdatatype","krb5_authdatatype"],[813,2,1,"c.krb5_authenticator","krb5_authenticator"],[814,2,1,"c.krb5_boolean","krb5_boolean"],[91,0,1,"c.krb5_build_principal","krb5_build_principal"],[92,0,1,"c.krb5_build_principal_alloc_va","krb5_build_principal_alloc_va"],[93,0,1,"c.krb5_build_principal_ext","krb5_build_principal_ext"],[94,0,1,"c.krb5_build_principal_va","krb5_build_principal_va"],[95,0,1,"c.krb5_c_block_size","krb5_c_block_size"],[96,0,1,"c.krb5_c_checksum_length","krb5_c_checksum_length"],[97,0,1,"c.krb5_c_crypto_length","krb5_c_crypto_length"],[98,0,1,"c.krb5_c_crypto_length_iov","krb5_c_crypto_length_iov"],[99,0,1,"c.krb5_c_decrypt","krb5_c_decrypt"],[100,0,1,"c.krb5_c_decrypt_iov","krb5_c_decrypt_iov"],[101,0,1,"c.krb5_c_derive_prfplus","krb5_c_derive_prfplus"],[102,0,1,"c.krb5_c_encrypt","krb5_c_encrypt"],[103,0,1,"c.krb5_c_encrypt_iov","krb5_c_encrypt_iov"],[104,0,1,"c.krb5_c_encrypt_length","krb5_c_encrypt_length"],[105,0,1,"c.krb5_c_enctype_compare","krb5_c_enctype_compare"],[106,0,1,"c.krb5_c_free_state","krb5_c_free_state"],[107,0,1,"c.krb5_c_fx_cf2_simple","krb5_c_fx_cf2_simple"],[108,0,1,"c.krb5_c_init_state","krb5_c_init_state"],[109,0,1,"c.krb5_c_is_coll_proof_cksum","krb5_c_is_coll_proof_cksum"],[110,0,1,"c.krb5_c_is_keyed_cksum","krb5_c_is_keyed_cksum"],[111,0,1,"c.krb5_c_keyed_checksum_types","krb5_c_keyed_checksum_types"],[112,0,1,"c.krb5_c_keylengths","krb5_c_keylengths"],[113,0,1,"c.krb5_c_make_checksum","krb5_c_make_checksum"],[114,0,1,"c.krb5_c_make_checksum_iov","krb5_c_make_checksum_iov"],[115,0,1,"c.krb5_c_make_random_key","krb5_c_make_random_key"],[116,0,1,"c.krb5_c_padding_length","krb5_c_padding_length"],[117,0,1,"c.krb5_c_prf","krb5_c_prf"],[118,0,1,"c.krb5_c_prf_length","krb5_c_prf_length"],[119,0,1,"c.krb5_c_prfplus","krb5_c_prfplus"],[120,0,1,"c.krb5_c_random_add_entropy","krb5_c_random_add_entropy"],[121,0,1,"c.krb5_c_random_make_octets","krb5_c_random_make_octets"],[122,0,1,"c.krb5_c_random_os_entropy","krb5_c_random_os_entropy"],[123,0,1,"c.krb5_c_random_seed","krb5_c_random_seed"],[124,0,1,"c.krb5_c_random_to_key","krb5_c_random_to_key"],[125,0,1,"c.krb5_c_string_to_key","krb5_c_string_to_key"],[126,0,1,"c.krb5_c_string_to_key_with_params","krb5_c_string_to_key_with_params"],[127,0,1,"c.krb5_c_valid_cksumtype","krb5_c_valid_cksumtype"],[128,0,1,"c.krb5_c_valid_enctype","krb5_c_valid_enctype"],[129,0,1,"c.krb5_c_verify_checksum","krb5_c_verify_checksum"],[130,0,1,"c.krb5_c_verify_checksum_iov","krb5_c_verify_checksum_iov"],[131,0,1,"c.krb5_calculate_checksum","krb5_calculate_checksum"],[132,0,1,"c.krb5_cc_cache_match","krb5_cc_cache_match"],[133,0,1,"c.krb5_cc_close","krb5_cc_close"],[134,0,1,"c.krb5_cc_copy_creds","krb5_cc_copy_creds"],[815,2,1,"c.krb5_cc_cursor","krb5_cc_cursor"],[135,0,1,"c.krb5_cc_default","krb5_cc_default"],[136,0,1,"c.krb5_cc_default_name","krb5_cc_default_name"],[137,0,1,"c.krb5_cc_destroy","krb5_cc_destroy"],[138,0,1,"c.krb5_cc_dup","krb5_cc_dup"],[139,0,1,"c.krb5_cc_end_seq_get","krb5_cc_end_seq_get"],[140,0,1,"c.krb5_cc_gen_new","krb5_cc_gen_new"],[141,0,1,"c.krb5_cc_get_config","krb5_cc_get_config"],[142,0,1,"c.krb5_cc_get_flags","krb5_cc_get_flags"],[143,0,1,"c.krb5_cc_get_full_name","krb5_cc_get_full_name"],[144,0,1,"c.krb5_cc_get_name","krb5_cc_get_name"],[145,0,1,"c.krb5_cc_get_principal","krb5_cc_get_principal"],[146,0,1,"c.krb5_cc_get_type","krb5_cc_get_type"],[147,0,1,"c.krb5_cc_initialize","krb5_cc_initialize"],[148,0,1,"c.krb5_cc_move","krb5_cc_move"],[149,0,1,"c.krb5_cc_new_unique","krb5_cc_new_unique"],[150,0,1,"c.krb5_cc_next_cred","krb5_cc_next_cred"],[151,0,1,"c.krb5_cc_remove_cred","krb5_cc_remove_cred"],[152,0,1,"c.krb5_cc_resolve","krb5_cc_resolve"],[153,0,1,"c.krb5_cc_retrieve_cred","krb5_cc_retrieve_cred"],[154,0,1,"c.krb5_cc_select","krb5_cc_select"],[155,0,1,"c.krb5_cc_set_config","krb5_cc_set_config"],[156,0,1,"c.krb5_cc_set_default_name","krb5_cc_set_default_name"],[157,0,1,"c.krb5_cc_set_flags","krb5_cc_set_flags"],[158,0,1,"c.krb5_cc_start_seq_get","krb5_cc_start_seq_get"],[159,0,1,"c.krb5_cc_store_cred","krb5_cc_store_cred"],[160,0,1,"c.krb5_cc_support_switch","krb5_cc_support_switch"],[161,0,1,"c.krb5_cc_switch","krb5_cc_switch"],[816,2,1,"c.krb5_ccache","krb5_ccache"],[817,2,1,"c.krb5_cccol_cursor","krb5_cccol_cursor"],[162,0,1,"c.krb5_cccol_cursor_free","krb5_cccol_cursor_free"],[163,0,1,"c.krb5_cccol_cursor_new","krb5_cccol_cursor_new"],[164,0,1,"c.krb5_cccol_cursor_next","krb5_cccol_cursor_next"],[165,0,1,"c.krb5_cccol_have_content","krb5_cccol_have_content"],[166,0,1,"c.krb5_change_password","krb5_change_password"],[167,0,1,"c.krb5_check_clockskew","krb5_check_clockskew"],[818,2,1,"c.krb5_checksum","krb5_checksum"],[168,0,1,"c.krb5_checksum_size","krb5_checksum_size"],[169,0,1,"c.krb5_chpw_message","krb5_chpw_message"],[819,2,1,"c.krb5_cksumtype","krb5_cksumtype"],[170,0,1,"c.krb5_cksumtype_to_string","krb5_cksumtype_to_string"],[171,0,1,"c.krb5_clear_error_message","krb5_clear_error_message"],[820,2,1,"c.krb5_const_pointer","krb5_const_pointer"],[821,2,1,"c.krb5_const_principal","krb5_const_principal"],[822,2,1,"c.krb5_context","krb5_context"],[172,0,1,"c.krb5_copy_addresses","krb5_copy_addresses"],[173,0,1,"c.krb5_copy_authdata","krb5_copy_authdata"],[174,0,1,"c.krb5_copy_authenticator","krb5_copy_authenticator"],[175,0,1,"c.krb5_copy_checksum","krb5_copy_checksum"],[176,0,1,"c.krb5_copy_context","krb5_copy_context"],[177,0,1,"c.krb5_copy_creds","krb5_copy_creds"],[178,0,1,"c.krb5_copy_data","krb5_copy_data"],[179,0,1,"c.krb5_copy_error_message","krb5_copy_error_message"],[180,0,1,"c.krb5_copy_keyblock","krb5_copy_keyblock"],[181,0,1,"c.krb5_copy_keyblock_contents","krb5_copy_keyblock_contents"],[182,0,1,"c.krb5_copy_principal","krb5_copy_principal"],[183,0,1,"c.krb5_copy_ticket","krb5_copy_ticket"],[823,2,1,"c.krb5_cred","krb5_cred"],[824,2,1,"c.krb5_cred_enc_part","krb5_cred_enc_part"],[825,2,1,"c.krb5_cred_info","krb5_cred_info"],[826,2,1,"c.krb5_creds","krb5_creds"],[827,2,1,"c.krb5_crypto_iov","krb5_crypto_iov"],[828,2,1,"c.krb5_cryptotype","krb5_cryptotype"],[829,2,1,"c.krb5_data","krb5_data"],[184,0,1,"c.krb5_decode_authdata_container","krb5_decode_authdata_container"],[185,0,1,"c.krb5_decode_ticket","krb5_decode_ticket"],[186,0,1,"c.krb5_decrypt","krb5_decrypt"],[830,2,1,"c.krb5_deltat","krb5_deltat"],[187,0,1,"c.krb5_deltat_to_string","krb5_deltat_to_string"],[188,0,1,"c.krb5_eblock_enctype","krb5_eblock_enctype"],[831,2,1,"c.krb5_enc_data","krb5_enc_data"],[832,2,1,"c.krb5_enc_kdc_rep_part","krb5_enc_kdc_rep_part"],[833,2,1,"c.krb5_enc_tkt_part","krb5_enc_tkt_part"],[189,0,1,"c.krb5_encode_authdata_container","krb5_encode_authdata_container"],[190,0,1,"c.krb5_encrypt","krb5_encrypt"],[834,2,1,"c.krb5_encrypt_block","krb5_encrypt_block"],[191,0,1,"c.krb5_encrypt_size","krb5_encrypt_size"],[835,2,1,"c.krb5_enctype","krb5_enctype"],[192,0,1,"c.krb5_enctype_to_name","krb5_enctype_to_name"],[193,0,1,"c.krb5_enctype_to_string","krb5_enctype_to_string"],[836,2,1,"c.krb5_error","krb5_error"],[837,2,1,"c.krb5_error_code","krb5_error_code"],[194,0,1,"c.krb5_expand_hostname","krb5_expand_hostname"],[838,2,1,"c.krb5_expire_callback_func","krb5_expire_callback_func"],[195,0,1,"c.krb5_find_authdata","krb5_find_authdata"],[196,0,1,"c.krb5_finish_key","krb5_finish_key"],[197,0,1,"c.krb5_finish_random_key","krb5_finish_random_key"],[839,2,1,"c.krb5_flags","krb5_flags"],[198,0,1,"c.krb5_free_addresses","krb5_free_addresses"],[199,0,1,"c.krb5_free_ap_rep_enc_part","krb5_free_ap_rep_enc_part"],[200,0,1,"c.krb5_free_authdata","krb5_free_authdata"],[201,0,1,"c.krb5_free_authenticator","krb5_free_authenticator"],[202,0,1,"c.krb5_free_checksum","krb5_free_checksum"],[203,0,1,"c.krb5_free_checksum_contents","krb5_free_checksum_contents"],[204,0,1,"c.krb5_free_cksumtypes","krb5_free_cksumtypes"],[205,0,1,"c.krb5_free_context","krb5_free_context"],[206,0,1,"c.krb5_free_cred_contents","krb5_free_cred_contents"],[207,0,1,"c.krb5_free_creds","krb5_free_creds"],[208,0,1,"c.krb5_free_data","krb5_free_data"],[209,0,1,"c.krb5_free_data_contents","krb5_free_data_contents"],[210,0,1,"c.krb5_free_default_realm","krb5_free_default_realm"],[211,0,1,"c.krb5_free_enctypes","krb5_free_enctypes"],[212,0,1,"c.krb5_free_error","krb5_free_error"],[213,0,1,"c.krb5_free_error_message","krb5_free_error_message"],[214,0,1,"c.krb5_free_host_realm","krb5_free_host_realm"],[215,0,1,"c.krb5_free_keyblock","krb5_free_keyblock"],[216,0,1,"c.krb5_free_keyblock_contents","krb5_free_keyblock_contents"],[217,0,1,"c.krb5_free_keytab_entry_contents","krb5_free_keytab_entry_contents"],[218,0,1,"c.krb5_free_principal","krb5_free_principal"],[219,0,1,"c.krb5_free_string","krb5_free_string"],[220,0,1,"c.krb5_free_tgt_creds","krb5_free_tgt_creds"],[221,0,1,"c.krb5_free_ticket","krb5_free_ticket"],[222,0,1,"c.krb5_free_unparsed_name","krb5_free_unparsed_name"],[223,0,1,"c.krb5_fwd_tgt_creds","krb5_fwd_tgt_creds"],[224,0,1,"c.krb5_get_credentials","krb5_get_credentials"],[225,0,1,"c.krb5_get_credentials_renew","krb5_get_credentials_renew"],[226,0,1,"c.krb5_get_credentials_validate","krb5_get_credentials_validate"],[227,0,1,"c.krb5_get_default_realm","krb5_get_default_realm"],[228,0,1,"c.krb5_get_error_message","krb5_get_error_message"],[229,0,1,"c.krb5_get_etype_info","krb5_get_etype_info"],[230,0,1,"c.krb5_get_fallback_host_realm","krb5_get_fallback_host_realm"],[231,0,1,"c.krb5_get_host_realm","krb5_get_host_realm"],[232,0,1,"c.krb5_get_in_tkt_with_keytab","krb5_get_in_tkt_with_keytab"],[233,0,1,"c.krb5_get_in_tkt_with_password","krb5_get_in_tkt_with_password"],[234,0,1,"c.krb5_get_in_tkt_with_skey","krb5_get_in_tkt_with_skey"],[235,0,1,"c.krb5_get_init_creds_keytab","krb5_get_init_creds_keytab"],[840,2,1,"c.krb5_get_init_creds_opt","krb5_get_init_creds_opt"],[236,0,1,"c.krb5_get_init_creds_opt_alloc","krb5_get_init_creds_opt_alloc"],[237,0,1,"c.krb5_get_init_creds_opt_free","krb5_get_init_creds_opt_free"],[238,0,1,"c.krb5_get_init_creds_opt_get_fast_flags","krb5_get_init_creds_opt_get_fast_flags"],[239,0,1,"c.krb5_get_init_creds_opt_init","krb5_get_init_creds_opt_init"],[240,0,1,"c.krb5_get_init_creds_opt_set_address_list","krb5_get_init_creds_opt_set_address_list"],[241,0,1,"c.krb5_get_init_creds_opt_set_anonymous","krb5_get_init_creds_opt_set_anonymous"],[242,0,1,"c.krb5_get_init_creds_opt_set_canonicalize","krb5_get_init_creds_opt_set_canonicalize"],[243,0,1,"c.krb5_get_init_creds_opt_set_change_password_prompt","krb5_get_init_creds_opt_set_change_password_prompt"],[244,0,1,"c.krb5_get_init_creds_opt_set_etype_list","krb5_get_init_creds_opt_set_etype_list"],[245,0,1,"c.krb5_get_init_creds_opt_set_expire_callback","krb5_get_init_creds_opt_set_expire_callback"],[246,0,1,"c.krb5_get_init_creds_opt_set_fast_ccache","krb5_get_init_creds_opt_set_fast_ccache"],[247,0,1,"c.krb5_get_init_creds_opt_set_fast_ccache_name","krb5_get_init_creds_opt_set_fast_ccache_name"],[248,0,1,"c.krb5_get_init_creds_opt_set_fast_flags","krb5_get_init_creds_opt_set_fast_flags"],[249,0,1,"c.krb5_get_init_creds_opt_set_forwardable","krb5_get_init_creds_opt_set_forwardable"],[250,0,1,"c.krb5_get_init_creds_opt_set_in_ccache","krb5_get_init_creds_opt_set_in_ccache"],[251,0,1,"c.krb5_get_init_creds_opt_set_out_ccache","krb5_get_init_creds_opt_set_out_ccache"],[252,0,1,"c.krb5_get_init_creds_opt_set_pa","krb5_get_init_creds_opt_set_pa"],[253,0,1,"c.krb5_get_init_creds_opt_set_pac_request","krb5_get_init_creds_opt_set_pac_request"],[254,0,1,"c.krb5_get_init_creds_opt_set_preauth_list","krb5_get_init_creds_opt_set_preauth_list"],[255,0,1,"c.krb5_get_init_creds_opt_set_proxiable","krb5_get_init_creds_opt_set_proxiable"],[256,0,1,"c.krb5_get_init_creds_opt_set_renew_life","krb5_get_init_creds_opt_set_renew_life"],[257,0,1,"c.krb5_get_init_creds_opt_set_responder","krb5_get_init_creds_opt_set_responder"],[258,0,1,"c.krb5_get_init_creds_opt_set_salt","krb5_get_init_creds_opt_set_salt"],[259,0,1,"c.krb5_get_init_creds_opt_set_tkt_life","krb5_get_init_creds_opt_set_tkt_life"],[260,0,1,"c.krb5_get_init_creds_password","krb5_get_init_creds_password"],[261,0,1,"c.krb5_get_permitted_enctypes","krb5_get_permitted_enctypes"],[262,0,1,"c.krb5_get_profile","krb5_get_profile"],[263,0,1,"c.krb5_get_prompt_types","krb5_get_prompt_types"],[264,0,1,"c.krb5_get_renewed_creds","krb5_get_renewed_creds"],[265,0,1,"c.krb5_get_server_rcache","krb5_get_server_rcache"],[266,0,1,"c.krb5_get_time_offsets","krb5_get_time_offsets"],[267,0,1,"c.krb5_get_validated_creds","krb5_get_validated_creds"],[841,2,1,"c.krb5_gic_opt_pa_data","krb5_gic_opt_pa_data"],[268,0,1,"c.krb5_init_context","krb5_init_context"],[269,0,1,"c.krb5_init_context_profile","krb5_init_context_profile"],[842,2,1,"c.krb5_init_creds_context","krb5_init_creds_context"],[270,0,1,"c.krb5_init_creds_free","krb5_init_creds_free"],[271,0,1,"c.krb5_init_creds_get","krb5_init_creds_get"],[272,0,1,"c.krb5_init_creds_get_creds","krb5_init_creds_get_creds"],[273,0,1,"c.krb5_init_creds_get_error","krb5_init_creds_get_error"],[274,0,1,"c.krb5_init_creds_get_times","krb5_init_creds_get_times"],[275,0,1,"c.krb5_init_creds_init","krb5_init_creds_init"],[276,0,1,"c.krb5_init_creds_set_keytab","krb5_init_creds_set_keytab"],[277,0,1,"c.krb5_init_creds_set_password","krb5_init_creds_set_password"],[278,0,1,"c.krb5_init_creds_set_service","krb5_init_creds_set_service"],[279,0,1,"c.krb5_init_creds_step","krb5_init_creds_step"],[280,0,1,"c.krb5_init_keyblock","krb5_init_keyblock"],[281,0,1,"c.krb5_init_random_key","krb5_init_random_key"],[282,0,1,"c.krb5_init_secure_context","krb5_init_secure_context"],[843,2,1,"c.krb5_int16","krb5_int16"],[844,2,1,"c.krb5_int32","krb5_int32"],[283,0,1,"c.krb5_is_config_principal","krb5_is_config_principal"],[284,0,1,"c.krb5_is_referral_realm","krb5_is_referral_realm"],[285,0,1,"c.krb5_is_thread_safe","krb5_is_thread_safe"],[286,0,1,"c.krb5_k_create_key","krb5_k_create_key"],[287,0,1,"c.krb5_k_decrypt","krb5_k_decrypt"],[288,0,1,"c.krb5_k_decrypt_iov","krb5_k_decrypt_iov"],[289,0,1,"c.krb5_k_encrypt","krb5_k_encrypt"],[290,0,1,"c.krb5_k_encrypt_iov","krb5_k_encrypt_iov"],[291,0,1,"c.krb5_k_free_key","krb5_k_free_key"],[292,0,1,"c.krb5_k_key_enctype","krb5_k_key_enctype"],[293,0,1,"c.krb5_k_key_keyblock","krb5_k_key_keyblock"],[294,0,1,"c.krb5_k_make_checksum","krb5_k_make_checksum"],[295,0,1,"c.krb5_k_make_checksum_iov","krb5_k_make_checksum_iov"],[296,0,1,"c.krb5_k_prf","krb5_k_prf"],[297,0,1,"c.krb5_k_reference_key","krb5_k_reference_key"],[298,0,1,"c.krb5_k_verify_checksum","krb5_k_verify_checksum"],[299,0,1,"c.krb5_k_verify_checksum_iov","krb5_k_verify_checksum_iov"],[845,2,1,"c.krb5_kdc_rep","krb5_kdc_rep"],[846,2,1,"c.krb5_kdc_req","krb5_kdc_req"],[300,0,1,"c.krb5_kdc_sign_ticket","krb5_kdc_sign_ticket"],[301,0,1,"c.krb5_kdc_verify_ticket","krb5_kdc_verify_ticket"],[847,2,1,"c.krb5_key","krb5_key"],[848,2,1,"c.krb5_keyblock","krb5_keyblock"],[849,2,1,"c.krb5_keytab","krb5_keytab"],[850,2,1,"c.krb5_keytab_entry","krb5_keytab_entry"],[851,2,1,"c.krb5_keyusage","krb5_keyusage"],[302,0,1,"c.krb5_kt_add_entry","krb5_kt_add_entry"],[303,0,1,"c.krb5_kt_client_default","krb5_kt_client_default"],[304,0,1,"c.krb5_kt_close","krb5_kt_close"],[852,2,1,"c.krb5_kt_cursor","krb5_kt_cursor"],[305,0,1,"c.krb5_kt_default","krb5_kt_default"],[306,0,1,"c.krb5_kt_default_name","krb5_kt_default_name"],[307,0,1,"c.krb5_kt_dup","krb5_kt_dup"],[308,0,1,"c.krb5_kt_end_seq_get","krb5_kt_end_seq_get"],[309,0,1,"c.krb5_kt_free_entry","krb5_kt_free_entry"],[310,0,1,"c.krb5_kt_get_entry","krb5_kt_get_entry"],[311,0,1,"c.krb5_kt_get_name","krb5_kt_get_name"],[312,0,1,"c.krb5_kt_get_type","krb5_kt_get_type"],[313,0,1,"c.krb5_kt_have_content","krb5_kt_have_content"],[314,0,1,"c.krb5_kt_next_entry","krb5_kt_next_entry"],[315,0,1,"c.krb5_kt_read_service_key","krb5_kt_read_service_key"],[316,0,1,"c.krb5_kt_remove_entry","krb5_kt_remove_entry"],[317,0,1,"c.krb5_kt_resolve","krb5_kt_resolve"],[318,0,1,"c.krb5_kt_start_seq_get","krb5_kt_start_seq_get"],[319,0,1,"c.krb5_kuserok","krb5_kuserok"],[853,2,1,"c.krb5_kvno","krb5_kvno"],[854,2,1,"c.krb5_last_req_entry","krb5_last_req_entry"],[855,2,1,"c.krb5_magic","krb5_magic"],[320,0,1,"c.krb5_make_authdata_kdc_issued","krb5_make_authdata_kdc_issued"],[321,0,1,"c.krb5_marshal_credentials","krb5_marshal_credentials"],[322,0,1,"c.krb5_merge_authdata","krb5_merge_authdata"],[323,0,1,"c.krb5_mk_1cred","krb5_mk_1cred"],[324,0,1,"c.krb5_mk_error","krb5_mk_error"],[325,0,1,"c.krb5_mk_ncred","krb5_mk_ncred"],[326,0,1,"c.krb5_mk_priv","krb5_mk_priv"],[327,0,1,"c.krb5_mk_rep","krb5_mk_rep"],[328,0,1,"c.krb5_mk_rep_dce","krb5_mk_rep_dce"],[329,0,1,"c.krb5_mk_req","krb5_mk_req"],[856,2,1,"c.krb5_mk_req_checksum_func","krb5_mk_req_checksum_func"],[330,0,1,"c.krb5_mk_req_extended","krb5_mk_req_extended"],[331,0,1,"c.krb5_mk_safe","krb5_mk_safe"],[857,2,1,"c.krb5_msgtype","krb5_msgtype"],[858,2,1,"c.krb5_octet","krb5_octet"],[332,0,1,"c.krb5_os_localaddr","krb5_os_localaddr"],[859,2,1,"c.krb5_pa_data","krb5_pa_data"],[860,2,1,"c.krb5_pa_pac_req","krb5_pa_pac_req"],[861,2,1,"c.krb5_pa_server_referral_data","krb5_pa_server_referral_data"],[862,2,1,"c.krb5_pa_svr_referral_data","krb5_pa_svr_referral_data"],[863,2,1,"c.krb5_pac","krb5_pac"],[333,0,1,"c.krb5_pac_add_buffer","krb5_pac_add_buffer"],[334,0,1,"c.krb5_pac_free","krb5_pac_free"],[335,0,1,"c.krb5_pac_get_buffer","krb5_pac_get_buffer"],[336,0,1,"c.krb5_pac_get_client_info","krb5_pac_get_client_info"],[337,0,1,"c.krb5_pac_get_types","krb5_pac_get_types"],[338,0,1,"c.krb5_pac_init","krb5_pac_init"],[339,0,1,"c.krb5_pac_parse","krb5_pac_parse"],[340,0,1,"c.krb5_pac_sign","krb5_pac_sign"],[341,0,1,"c.krb5_pac_sign_ext","krb5_pac_sign_ext"],[342,0,1,"c.krb5_pac_verify","krb5_pac_verify"],[343,0,1,"c.krb5_pac_verify_ext","krb5_pac_verify_ext"],[344,0,1,"c.krb5_parse_name","krb5_parse_name"],[345,0,1,"c.krb5_parse_name_flags","krb5_parse_name_flags"],[864,2,1,"c.krb5_pointer","krb5_pointer"],[865,2,1,"c.krb5_post_recv_fn","krb5_post_recv_fn"],[866,2,1,"c.krb5_pre_send_fn","krb5_pre_send_fn"],[867,2,1,"c.krb5_preauthtype","krb5_preauthtype"],[346,0,1,"c.krb5_prepend_error_message","krb5_prepend_error_message"],[868,2,1,"c.krb5_principal","krb5_principal"],[347,0,1,"c.krb5_principal2salt","krb5_principal2salt"],[348,0,1,"c.krb5_principal_compare","krb5_principal_compare"],[349,0,1,"c.krb5_principal_compare_any_realm","krb5_principal_compare_any_realm"],[350,0,1,"c.krb5_principal_compare_flags","krb5_principal_compare_flags"],[869,2,1,"c.krb5_principal_data","krb5_principal_data"],[351,0,1,"c.krb5_process_key","krb5_process_key"],[870,2,1,"c.krb5_prompt","krb5_prompt"],[871,2,1,"c.krb5_prompt_type","krb5_prompt_type"],[872,2,1,"c.krb5_prompter_fct","krb5_prompter_fct"],[352,0,1,"c.krb5_prompter_posix","krb5_prompter_posix"],[873,2,1,"c.krb5_pwd_data","krb5_pwd_data"],[353,0,1,"c.krb5_random_key","krb5_random_key"],[874,2,1,"c.krb5_rcache","krb5_rcache"],[354,0,1,"c.krb5_rd_cred","krb5_rd_cred"],[355,0,1,"c.krb5_rd_error","krb5_rd_error"],[356,0,1,"c.krb5_rd_priv","krb5_rd_priv"],[357,0,1,"c.krb5_rd_rep","krb5_rd_rep"],[358,0,1,"c.krb5_rd_rep_dce","krb5_rd_rep_dce"],[359,0,1,"c.krb5_rd_req","krb5_rd_req"],[360,0,1,"c.krb5_rd_safe","krb5_rd_safe"],[361,0,1,"c.krb5_read_password","krb5_read_password"],[362,0,1,"c.krb5_realm_compare","krb5_realm_compare"],[363,0,1,"c.krb5_recvauth","krb5_recvauth"],[364,0,1,"c.krb5_recvauth_version","krb5_recvauth_version"],[875,2,1,"c.krb5_replay_data","krb5_replay_data"],[876,2,1,"c.krb5_responder_context","krb5_responder_context"],[877,2,1,"c.krb5_responder_fn","krb5_responder_fn"],[365,0,1,"c.krb5_responder_get_challenge","krb5_responder_get_challenge"],[366,0,1,"c.krb5_responder_list_questions","krb5_responder_list_questions"],[878,2,1,"c.krb5_responder_otp_challenge","krb5_responder_otp_challenge"],[367,0,1,"c.krb5_responder_otp_challenge_free","krb5_responder_otp_challenge_free"],[368,0,1,"c.krb5_responder_otp_get_challenge","krb5_responder_otp_get_challenge"],[369,0,1,"c.krb5_responder_otp_set_answer","krb5_responder_otp_set_answer"],[879,2,1,"c.krb5_responder_otp_tokeninfo","krb5_responder_otp_tokeninfo"],[880,2,1,"c.krb5_responder_pkinit_challenge","krb5_responder_pkinit_challenge"],[370,0,1,"c.krb5_responder_pkinit_challenge_free","krb5_responder_pkinit_challenge_free"],[371,0,1,"c.krb5_responder_pkinit_get_challenge","krb5_responder_pkinit_get_challenge"],[881,2,1,"c.krb5_responder_pkinit_identity","krb5_responder_pkinit_identity"],[372,0,1,"c.krb5_responder_pkinit_set_answer","krb5_responder_pkinit_set_answer"],[373,0,1,"c.krb5_responder_set_answer","krb5_responder_set_answer"],[882,2,1,"c.krb5_response","krb5_response"],[374,0,1,"c.krb5_salttype_to_string","krb5_salttype_to_string"],[375,0,1,"c.krb5_sendauth","krb5_sendauth"],[376,0,1,"c.krb5_server_decrypt_ticket_keytab","krb5_server_decrypt_ticket_keytab"],[377,0,1,"c.krb5_set_default_realm","krb5_set_default_realm"],[378,0,1,"c.krb5_set_default_tgs_enctypes","krb5_set_default_tgs_enctypes"],[379,0,1,"c.krb5_set_error_message","krb5_set_error_message"],[380,0,1,"c.krb5_set_kdc_recv_hook","krb5_set_kdc_recv_hook"],[381,0,1,"c.krb5_set_kdc_send_hook","krb5_set_kdc_send_hook"],[382,0,1,"c.krb5_set_password","krb5_set_password"],[383,0,1,"c.krb5_set_password_using_ccache","krb5_set_password_using_ccache"],[384,0,1,"c.krb5_set_principal_realm","krb5_set_principal_realm"],[385,0,1,"c.krb5_set_real_time","krb5_set_real_time"],[386,0,1,"c.krb5_set_trace_callback","krb5_set_trace_callback"],[387,0,1,"c.krb5_set_trace_filename","krb5_set_trace_filename"],[388,0,1,"c.krb5_sname_match","krb5_sname_match"],[389,0,1,"c.krb5_sname_to_principal","krb5_sname_to_principal"],[390,0,1,"c.krb5_string_to_cksumtype","krb5_string_to_cksumtype"],[391,0,1,"c.krb5_string_to_deltat","krb5_string_to_deltat"],[392,0,1,"c.krb5_string_to_enctype","krb5_string_to_enctype"],[393,0,1,"c.krb5_string_to_key","krb5_string_to_key"],[394,0,1,"c.krb5_string_to_salttype","krb5_string_to_salttype"],[395,0,1,"c.krb5_string_to_timestamp","krb5_string_to_timestamp"],[883,2,1,"c.krb5_ticket","krb5_ticket"],[884,2,1,"c.krb5_ticket_times","krb5_ticket_times"],[396,0,1,"c.krb5_timeofday","krb5_timeofday"],[885,2,1,"c.krb5_timestamp","krb5_timestamp"],[397,0,1,"c.krb5_timestamp_to_sfstring","krb5_timestamp_to_sfstring"],[398,0,1,"c.krb5_timestamp_to_string","krb5_timestamp_to_string"],[886,2,1,"c.krb5_tkt_authent","krb5_tkt_authent"],[887,2,1,"c.krb5_tkt_creds_context","krb5_tkt_creds_context"],[399,0,1,"c.krb5_tkt_creds_free","krb5_tkt_creds_free"],[400,0,1,"c.krb5_tkt_creds_get","krb5_tkt_creds_get"],[401,0,1,"c.krb5_tkt_creds_get_creds","krb5_tkt_creds_get_creds"],[402,0,1,"c.krb5_tkt_creds_get_times","krb5_tkt_creds_get_times"],[403,0,1,"c.krb5_tkt_creds_init","krb5_tkt_creds_init"],[404,0,1,"c.krb5_tkt_creds_step","krb5_tkt_creds_step"],[888,2,1,"c.krb5_trace_callback","krb5_trace_callback"],[889,2,1,"c.krb5_trace_info","krb5_trace_info"],[890,2,1,"c.krb5_transited","krb5_transited"],[891,2,1,"c.krb5_typed_data","krb5_typed_data"],[892,2,1,"c.krb5_ui_2","krb5_ui_2"],[893,2,1,"c.krb5_ui_4","krb5_ui_4"],[405,0,1,"c.krb5_unmarshal_credentials","krb5_unmarshal_credentials"],[406,0,1,"c.krb5_unparse_name","krb5_unparse_name"],[407,0,1,"c.krb5_unparse_name_ext","krb5_unparse_name_ext"],[408,0,1,"c.krb5_unparse_name_flags","krb5_unparse_name_flags"],[409,0,1,"c.krb5_unparse_name_flags_ext","krb5_unparse_name_flags_ext"],[410,0,1,"c.krb5_us_timeofday","krb5_us_timeofday"],[411,0,1,"c.krb5_use_enctype","krb5_use_enctype"],[412,0,1,"c.krb5_verify_authdata_kdc_issued","krb5_verify_authdata_kdc_issued"],[413,0,1,"c.krb5_verify_checksum","krb5_verify_checksum"],[414,0,1,"c.krb5_verify_init_creds","krb5_verify_init_creds"],[894,2,1,"c.krb5_verify_init_creds_opt","krb5_verify_init_creds_opt"],[415,0,1,"c.krb5_verify_init_creds_opt_init","krb5_verify_init_creds_opt_init"],[416,0,1,"c.krb5_verify_init_creds_opt_set_ap_req_nofail","krb5_verify_init_creds_opt_set_ap_req_nofail"],[417,0,1,"c.krb5_vprepend_error_message","krb5_vprepend_error_message"],[418,0,1,"c.krb5_vset_error_message","krb5_vset_error_message"],[419,0,1,"c.krb5_vwrap_error_message","krb5_vwrap_error_message"],[420,0,1,"c.krb5_wrap_error_message","krb5_wrap_error_message"],[895,2,1,"c.passwd_phrase_element","passwd_phrase_element"],[422,4,1,"","ADDRTYPE_ADDRPORT"],[423,4,1,"","ADDRTYPE_CHAOS"],[424,4,1,"","ADDRTYPE_DDP"],[425,4,1,"","ADDRTYPE_INET"],[426,4,1,"","ADDRTYPE_INET6"],[427,4,1,"","ADDRTYPE_IPPORT"],[428,4,1,"","ADDRTYPE_ISO"],[429,4,1,"","ADDRTYPE_IS_LOCAL"],[430,4,1,"","ADDRTYPE_NETBIOS"],[431,4,1,"","ADDRTYPE_XNS"],[432,4,1,"","AD_TYPE_EXTERNAL"],[433,4,1,"","AD_TYPE_FIELD_TYPE_MASK"],[434,4,1,"","AD_TYPE_REGISTERED"],[435,4,1,"","AD_TYPE_RESERVED"],[436,4,1,"","AP_OPTS_ETYPE_NEGOTIATION"],[437,4,1,"","AP_OPTS_MUTUAL_REQUIRED"],[438,4,1,"","AP_OPTS_RESERVED"],[439,4,1,"","AP_OPTS_USE_SESSION_KEY"],[440,4,1,"","AP_OPTS_USE_SUBKEY"],[441,4,1,"","AP_OPTS_WIRE_MASK"],[442,4,1,"","CKSUMTYPE_CMAC_CAMELLIA128"],[443,4,1,"","CKSUMTYPE_CMAC_CAMELLIA256"],[444,4,1,"","CKSUMTYPE_CRC32"],[445,4,1,"","CKSUMTYPE_DESCBC"],[446,4,1,"","CKSUMTYPE_HMAC_MD5_ARCFOUR"],[447,4,1,"","CKSUMTYPE_HMAC_SHA1_96_AES128"],[448,4,1,"","CKSUMTYPE_HMAC_SHA1_96_AES256"],[449,4,1,"","CKSUMTYPE_HMAC_SHA1_DES3"],[450,4,1,"","CKSUMTYPE_HMAC_SHA256_128_AES128"],[451,4,1,"","CKSUMTYPE_HMAC_SHA384_192_AES256"],[452,4,1,"","CKSUMTYPE_MD5_HMAC_ARCFOUR"],[453,4,1,"","CKSUMTYPE_NIST_SHA"],[454,4,1,"","CKSUMTYPE_RSA_MD4"],[455,4,1,"","CKSUMTYPE_RSA_MD4_DES"],[456,4,1,"","CKSUMTYPE_RSA_MD5"],[457,4,1,"","CKSUMTYPE_RSA_MD5_DES"],[458,4,1,"","CKSUMTYPE_SHA1"],[459,4,1,"","ENCTYPE_AES128_CTS_HMAC_SHA1_96"],[460,4,1,"","ENCTYPE_AES128_CTS_HMAC_SHA256_128"],[461,4,1,"","ENCTYPE_AES256_CTS_HMAC_SHA1_96"],[462,4,1,"","ENCTYPE_AES256_CTS_HMAC_SHA384_192"],[463,4,1,"","ENCTYPE_ARCFOUR_HMAC"],[464,4,1,"","ENCTYPE_ARCFOUR_HMAC_EXP"],[465,4,1,"","ENCTYPE_CAMELLIA128_CTS_CMAC"],[466,4,1,"","ENCTYPE_CAMELLIA256_CTS_CMAC"],[467,4,1,"","ENCTYPE_DES3_CBC_ENV"],[468,4,1,"","ENCTYPE_DES3_CBC_RAW"],[469,4,1,"","ENCTYPE_DES3_CBC_SHA"],[470,4,1,"","ENCTYPE_DES3_CBC_SHA1"],[471,4,1,"","ENCTYPE_DES_CBC_CRC"],[472,4,1,"","ENCTYPE_DES_CBC_MD4"],[473,4,1,"","ENCTYPE_DES_CBC_MD5"],[474,4,1,"","ENCTYPE_DES_CBC_RAW"],[475,4,1,"","ENCTYPE_DES_HMAC_SHA1"],[476,4,1,"","ENCTYPE_DSA_SHA1_CMS"],[477,4,1,"","ENCTYPE_MD5_RSA_CMS"],[478,4,1,"","ENCTYPE_NULL"],[479,4,1,"","ENCTYPE_RC2_CBC_ENV"],[480,4,1,"","ENCTYPE_RSA_ENV"],[481,4,1,"","ENCTYPE_RSA_ES_OAEP_ENV"],[482,4,1,"","ENCTYPE_SHA1_RSA_CMS"],[483,4,1,"","ENCTYPE_UNKNOWN"],[484,4,1,"","KDC_OPT_ALLOW_POSTDATE"],[485,4,1,"","KDC_OPT_CANONICALIZE"],[486,4,1,"","KDC_OPT_CNAME_IN_ADDL_TKT"],[487,4,1,"","KDC_OPT_DISABLE_TRANSITED_CHECK"],[488,4,1,"","KDC_OPT_ENC_TKT_IN_SKEY"],[489,4,1,"","KDC_OPT_FORWARDABLE"],[490,4,1,"","KDC_OPT_FORWARDED"],[491,4,1,"","KDC_OPT_POSTDATED"],[492,4,1,"","KDC_OPT_PROXIABLE"],[493,4,1,"","KDC_OPT_PROXY"],[494,4,1,"","KDC_OPT_RENEW"],[495,4,1,"","KDC_OPT_RENEWABLE"],[496,4,1,"","KDC_OPT_RENEWABLE_OK"],[497,4,1,"","KDC_OPT_REQUEST_ANONYMOUS"],[498,4,1,"","KDC_OPT_VALIDATE"],[499,4,1,"","KDC_TKT_COMMON_MASK"],[500,4,1,"","KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE"],[501,4,1,"","KRB5_ANONYMOUS_PRINCSTR"],[502,4,1,"","KRB5_ANONYMOUS_REALMSTR"],[503,4,1,"","KRB5_AP_REP"],[504,4,1,"","KRB5_AP_REQ"],[505,4,1,"","KRB5_AS_REP"],[506,4,1,"","KRB5_AS_REQ"],[507,4,1,"","KRB5_AUTHDATA_AND_OR"],[508,4,1,"","KRB5_AUTHDATA_AP_OPTIONS"],[509,4,1,"","KRB5_AUTHDATA_AUTH_INDICATOR"],[510,4,1,"","KRB5_AUTHDATA_CAMMAC"],[511,4,1,"","KRB5_AUTHDATA_ETYPE_NEGOTIATION"],[512,4,1,"","KRB5_AUTHDATA_FX_ARMOR"],[513,4,1,"","KRB5_AUTHDATA_IF_RELEVANT"],[514,4,1,"","KRB5_AUTHDATA_INITIAL_VERIFIED_CAS"],[515,4,1,"","KRB5_AUTHDATA_KDC_ISSUED"],[516,4,1,"","KRB5_AUTHDATA_MANDATORY_FOR_KDC"],[517,4,1,"","KRB5_AUTHDATA_OSF_DCE"],[518,4,1,"","KRB5_AUTHDATA_SESAME"],[519,4,1,"","KRB5_AUTHDATA_SIGNTICKET"],[520,4,1,"","KRB5_AUTHDATA_WIN2K_PAC"],[521,4,1,"","KRB5_AUTH_CONTEXT_DO_SEQUENCE"],[522,4,1,"","KRB5_AUTH_CONTEXT_DO_TIME"],[523,4,1,"","KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR"],[524,4,1,"","KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR"],[525,4,1,"","KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR"],[526,4,1,"","KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR"],[527,4,1,"","KRB5_AUTH_CONTEXT_PERMIT_ALL"],[528,4,1,"","KRB5_AUTH_CONTEXT_RET_SEQUENCE"],[529,4,1,"","KRB5_AUTH_CONTEXT_RET_TIME"],[530,4,1,"","KRB5_AUTH_CONTEXT_USE_SUBKEY"],[531,4,1,"","KRB5_CRED"],[532,4,1,"","KRB5_CRYPTO_TYPE_CHECKSUM"],[533,4,1,"","KRB5_CRYPTO_TYPE_DATA"],[534,4,1,"","KRB5_CRYPTO_TYPE_EMPTY"],[535,4,1,"","KRB5_CRYPTO_TYPE_HEADER"],[536,4,1,"","KRB5_CRYPTO_TYPE_PADDING"],[537,4,1,"","KRB5_CRYPTO_TYPE_SIGN_ONLY"],[538,4,1,"","KRB5_CRYPTO_TYPE_STREAM"],[539,4,1,"","KRB5_CRYPTO_TYPE_TRAILER"],[540,4,1,"","KRB5_CYBERSAFE_SECUREID"],[541,4,1,"","KRB5_DOMAIN_X500_COMPRESS"],[542,4,1,"","KRB5_ENCPADATA_REQ_ENC_PA_REP"],[543,4,1,"","KRB5_ERROR"],[544,4,1,"","KRB5_FAST_REQUIRED"],[545,4,1,"","KRB5_GC_CACHED"],[546,4,1,"","KRB5_GC_CANONICALIZE"],[547,4,1,"","KRB5_GC_CONSTRAINED_DELEGATION"],[548,4,1,"","KRB5_GC_FORWARDABLE"],[549,4,1,"","KRB5_GC_NO_STORE"],[550,4,1,"","KRB5_GC_NO_TRANSIT_CHECK"],[551,4,1,"","KRB5_GC_USER_USER"],[552,4,1,"","KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST"],[553,4,1,"","KRB5_GET_INIT_CREDS_OPT_ANONYMOUS"],[554,4,1,"","KRB5_GET_INIT_CREDS_OPT_CANONICALIZE"],[555,4,1,"","KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT"],[556,4,1,"","KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST"],[557,4,1,"","KRB5_GET_INIT_CREDS_OPT_FORWARDABLE"],[558,4,1,"","KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST"],[559,4,1,"","KRB5_GET_INIT_CREDS_OPT_PROXIABLE"],[560,4,1,"","KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE"],[561,4,1,"","KRB5_GET_INIT_CREDS_OPT_SALT"],[562,4,1,"","KRB5_GET_INIT_CREDS_OPT_TKT_LIFE"],[563,4,1,"","KRB5_INIT_CONTEXT_KDC"],[564,4,1,"","KRB5_INIT_CONTEXT_SECURE"],[565,4,1,"","KRB5_INIT_CREDS_STEP_FLAG_CONTINUE"],[566,4,1,"","KRB5_INT16_MAX"],[567,4,1,"","KRB5_INT16_MIN"],[568,4,1,"","KRB5_INT32_MAX"],[569,4,1,"","KRB5_INT32_MIN"],[570,4,1,"","KRB5_KEYUSAGE_AD_ITE"],[571,4,1,"","KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM"],[572,4,1,"","KRB5_KEYUSAGE_AD_MTE"],[573,4,1,"","KRB5_KEYUSAGE_AD_SIGNEDPATH"],[574,4,1,"","KRB5_KEYUSAGE_APP_DATA_CKSUM"],[575,4,1,"","KRB5_KEYUSAGE_APP_DATA_ENCRYPT"],[576,4,1,"","KRB5_KEYUSAGE_AP_REP_ENCPART"],[577,4,1,"","KRB5_KEYUSAGE_AP_REQ_AUTH"],[578,4,1,"","KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM"],[579,4,1,"","KRB5_KEYUSAGE_AS_REP_ENCPART"],[580,4,1,"","KRB5_KEYUSAGE_AS_REQ"],[581,4,1,"","KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS"],[582,4,1,"","KRB5_KEYUSAGE_CAMMAC"],[583,4,1,"","KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT"],[584,4,1,"","KRB5_KEYUSAGE_ENC_CHALLENGE_KDC"],[585,4,1,"","KRB5_KEYUSAGE_FAST_ENC"],[586,4,1,"","KRB5_KEYUSAGE_FAST_FINISHED"],[587,4,1,"","KRB5_KEYUSAGE_FAST_REP"],[588,4,1,"","KRB5_KEYUSAGE_FAST_REQ_CHKSUM"],[589,4,1,"","KRB5_KEYUSAGE_GSS_TOK_MIC"],[590,4,1,"","KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG"],[591,4,1,"","KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV"],[592,4,1,"","KRB5_KEYUSAGE_IAKERB_FINISHED"],[593,4,1,"","KRB5_KEYUSAGE_KDC_REP_TICKET"],[594,4,1,"","KRB5_KEYUSAGE_KRB_CRED_ENCPART"],[595,4,1,"","KRB5_KEYUSAGE_KRB_ERROR_CKSUM"],[596,4,1,"","KRB5_KEYUSAGE_KRB_PRIV_ENCPART"],[597,4,1,"","KRB5_KEYUSAGE_KRB_SAFE_CKSUM"],[598,4,1,"","KRB5_KEYUSAGE_PA_AS_FRESHNESS"],[599,4,1,"","KRB5_KEYUSAGE_PA_FX_COOKIE"],[600,4,1,"","KRB5_KEYUSAGE_PA_OTP_REQUEST"],[601,4,1,"","KRB5_KEYUSAGE_PA_PKINIT_KX"],[602,4,1,"","KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY"],[603,4,1,"","KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST"],[604,4,1,"","KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM"],[605,4,1,"","KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID"],[606,4,1,"","KRB5_KEYUSAGE_PA_SAM_RESPONSE"],[607,4,1,"","KRB5_KEYUSAGE_SPAKE"],[608,4,1,"","KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY"],[609,4,1,"","KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY"],[610,4,1,"","KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY"],[611,4,1,"","KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY"],[612,4,1,"","KRB5_KEYUSAGE_TGS_REQ_AUTH"],[613,4,1,"","KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM"],[614,4,1,"","KRB5_KPASSWD_ACCESSDENIED"],[615,4,1,"","KRB5_KPASSWD_AUTHERROR"],[616,4,1,"","KRB5_KPASSWD_BAD_VERSION"],[617,4,1,"","KRB5_KPASSWD_HARDERROR"],[618,4,1,"","KRB5_KPASSWD_INITIAL_FLAG_NEEDED"],[619,4,1,"","KRB5_KPASSWD_MALFORMED"],[620,4,1,"","KRB5_KPASSWD_SOFTERROR"],[621,4,1,"","KRB5_KPASSWD_SUCCESS"],[622,4,1,"","KRB5_LRQ_ALL_ACCT_EXPTIME"],[623,4,1,"","KRB5_LRQ_ALL_LAST_INITIAL"],[624,4,1,"","KRB5_LRQ_ALL_LAST_RENEWAL"],[625,4,1,"","KRB5_LRQ_ALL_LAST_REQ"],[626,4,1,"","KRB5_LRQ_ALL_LAST_TGT"],[627,4,1,"","KRB5_LRQ_ALL_LAST_TGT_ISSUED"],[628,4,1,"","KRB5_LRQ_ALL_PW_EXPTIME"],[629,4,1,"","KRB5_LRQ_NONE"],[630,4,1,"","KRB5_LRQ_ONE_ACCT_EXPTIME"],[631,4,1,"","KRB5_LRQ_ONE_LAST_INITIAL"],[632,4,1,"","KRB5_LRQ_ONE_LAST_RENEWAL"],[633,4,1,"","KRB5_LRQ_ONE_LAST_REQ"],[634,4,1,"","KRB5_LRQ_ONE_LAST_TGT"],[635,4,1,"","KRB5_LRQ_ONE_LAST_TGT_ISSUED"],[636,4,1,"","KRB5_LRQ_ONE_PW_EXPTIME"],[637,4,1,"","KRB5_NT_ENTERPRISE_PRINCIPAL"],[638,4,1,"","KRB5_NT_ENT_PRINCIPAL_AND_ID"],[639,4,1,"","KRB5_NT_MS_PRINCIPAL"],[640,4,1,"","KRB5_NT_MS_PRINCIPAL_AND_ID"],[641,4,1,"","KRB5_NT_PRINCIPAL"],[642,4,1,"","KRB5_NT_SMTP_NAME"],[643,4,1,"","KRB5_NT_SRV_HST"],[644,4,1,"","KRB5_NT_SRV_INST"],[645,4,1,"","KRB5_NT_SRV_XHST"],[646,4,1,"","KRB5_NT_UID"],[647,4,1,"","KRB5_NT_UNKNOWN"],[648,4,1,"","KRB5_NT_WELLKNOWN"],[649,4,1,"","KRB5_NT_X500_PRINCIPAL"],[650,4,1,"","KRB5_PAC_ATTRIBUTES_INFO"],[651,4,1,"","KRB5_PAC_CLIENT_CLAIMS"],[652,4,1,"","KRB5_PAC_CLIENT_INFO"],[653,4,1,"","KRB5_PAC_CREDENTIALS_INFO"],[654,4,1,"","KRB5_PAC_DELEGATION_INFO"],[655,4,1,"","KRB5_PAC_DEVICE_CLAIMS"],[656,4,1,"","KRB5_PAC_DEVICE_INFO"],[657,4,1,"","KRB5_PAC_FULL_CHECKSUM"],[658,4,1,"","KRB5_PAC_LOGON_INFO"],[659,4,1,"","KRB5_PAC_PRIVSVR_CHECKSUM"],[660,4,1,"","KRB5_PAC_REQUESTOR"],[661,4,1,"","KRB5_PAC_SERVER_CHECKSUM"],[662,4,1,"","KRB5_PAC_TICKET_CHECKSUM"],[663,4,1,"","KRB5_PAC_UPN_DNS_INFO"],[664,4,1,"","KRB5_PADATA_AFS3_SALT"],[665,4,1,"","KRB5_PADATA_AP_REQ"],[666,4,1,"","KRB5_PADATA_AS_CHECKSUM"],[667,4,1,"","KRB5_PADATA_AS_FRESHNESS"],[668,4,1,"","KRB5_PADATA_ENCRYPTED_CHALLENGE"],[669,4,1,"","KRB5_PADATA_ENC_SANDIA_SECURID"],[670,4,1,"","KRB5_PADATA_ENC_TIMESTAMP"],[671,4,1,"","KRB5_PADATA_ENC_UNIX_TIME"],[672,4,1,"","KRB5_PADATA_ETYPE_INFO"],[673,4,1,"","KRB5_PADATA_ETYPE_INFO2"],[674,4,1,"","KRB5_PADATA_FOR_USER"],[675,4,1,"","KRB5_PADATA_FX_COOKIE"],[676,4,1,"","KRB5_PADATA_FX_ERROR"],[677,4,1,"","KRB5_PADATA_FX_FAST"],[678,4,1,"","KRB5_PADATA_GET_FROM_TYPED_DATA"],[679,4,1,"","KRB5_PADATA_NONE"],[680,4,1,"","KRB5_PADATA_OSF_DCE"],[681,4,1,"","KRB5_PADATA_OTP_CHALLENGE"],[682,4,1,"","KRB5_PADATA_OTP_PIN_CHANGE"],[683,4,1,"","KRB5_PADATA_OTP_REQUEST"],[684,4,1,"","KRB5_PADATA_PAC_OPTIONS"],[685,4,1,"","KRB5_PADATA_PAC_REQUEST"],[686,4,1,"","KRB5_PADATA_PKINIT_KX"],[687,4,1,"","KRB5_PADATA_PK_AS_REP"],[688,4,1,"","KRB5_PADATA_PK_AS_REP_OLD"],[689,4,1,"","KRB5_PADATA_PK_AS_REQ"],[690,4,1,"","KRB5_PADATA_PK_AS_REQ_OLD"],[691,4,1,"","KRB5_PADATA_PW_SALT"],[692,4,1,"","KRB5_PADATA_REDHAT_IDP_OAUTH2"],[693,4,1,"","KRB5_PADATA_REDHAT_PASSKEY"],[694,4,1,"","KRB5_PADATA_REFERRAL"],[695,4,1,"","KRB5_PADATA_S4U_X509_USER"],[696,4,1,"","KRB5_PADATA_SAM_CHALLENGE"],[697,4,1,"","KRB5_PADATA_SAM_CHALLENGE_2"],[698,4,1,"","KRB5_PADATA_SAM_REDIRECT"],[699,4,1,"","KRB5_PADATA_SAM_RESPONSE"],[700,4,1,"","KRB5_PADATA_SAM_RESPONSE_2"],[701,4,1,"","KRB5_PADATA_SESAME"],[702,4,1,"","KRB5_PADATA_SPAKE"],[703,4,1,"","KRB5_PADATA_SVR_REFERRAL_INFO"],[704,4,1,"","KRB5_PADATA_TGS_REQ"],[705,4,1,"","KRB5_PADATA_USE_SPECIFIED_KVNO"],[706,4,1,"","KRB5_PRINCIPAL_COMPARE_CASEFOLD"],[707,4,1,"","KRB5_PRINCIPAL_COMPARE_ENTERPRISE"],[708,4,1,"","KRB5_PRINCIPAL_COMPARE_IGNORE_REALM"],[709,4,1,"","KRB5_PRINCIPAL_COMPARE_UTF8"],[710,4,1,"","KRB5_PRINCIPAL_PARSE_ENTERPRISE"],[711,4,1,"","KRB5_PRINCIPAL_PARSE_IGNORE_REALM"],[712,4,1,"","KRB5_PRINCIPAL_PARSE_NO_DEF_REALM"],[713,4,1,"","KRB5_PRINCIPAL_PARSE_NO_REALM"],[714,4,1,"","KRB5_PRINCIPAL_PARSE_REQUIRE_REALM"],[715,4,1,"","KRB5_PRINCIPAL_UNPARSE_DISPLAY"],[716,4,1,"","KRB5_PRINCIPAL_UNPARSE_NO_REALM"],[717,4,1,"","KRB5_PRINCIPAL_UNPARSE_SHORT"],[718,4,1,"","KRB5_PRIV"],[719,4,1,"","KRB5_PROMPT_TYPE_NEW_PASSWORD"],[720,4,1,"","KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN"],[721,4,1,"","KRB5_PROMPT_TYPE_PASSWORD"],[722,4,1,"","KRB5_PROMPT_TYPE_PREAUTH"],[723,4,1,"","KRB5_PVNO"],[724,4,1,"","KRB5_REALM_BRANCH_CHAR"],[725,4,1,"","KRB5_RECVAUTH_BADAUTHVERS"],[726,4,1,"","KRB5_RECVAUTH_SKIP_VERSION"],[727,4,1,"","KRB5_REFERRAL_REALM"],[728,4,1,"","KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN"],[729,4,1,"","KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN"],[730,4,1,"","KRB5_RESPONDER_OTP_FLAGS_NEXTOTP"],[731,4,1,"","KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN"],[732,4,1,"","KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC"],[733,4,1,"","KRB5_RESPONDER_OTP_FORMAT_DECIMAL"],[734,4,1,"","KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL"],[735,4,1,"","KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW"],[736,4,1,"","KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY"],[737,4,1,"","KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED"],[738,4,1,"","KRB5_RESPONDER_QUESTION_OTP"],[739,4,1,"","KRB5_RESPONDER_QUESTION_PASSWORD"],[740,4,1,"","KRB5_RESPONDER_QUESTION_PKINIT"],[741,4,1,"","KRB5_SAFE"],[742,4,1,"","KRB5_SAM_MUST_PK_ENCRYPT_SAD"],[743,4,1,"","KRB5_SAM_SEND_ENCRYPTED_SAD"],[744,4,1,"","KRB5_SAM_USE_SAD_AS_KEY"],[745,4,1,"","KRB5_TC_MATCH_2ND_TKT"],[746,4,1,"","KRB5_TC_MATCH_AUTHDATA"],[747,4,1,"","KRB5_TC_MATCH_FLAGS"],[748,4,1,"","KRB5_TC_MATCH_FLAGS_EXACT"],[749,4,1,"","KRB5_TC_MATCH_IS_SKEY"],[750,4,1,"","KRB5_TC_MATCH_KTYPE"],[751,4,1,"","KRB5_TC_MATCH_SRV_NAMEONLY"],[752,4,1,"","KRB5_TC_MATCH_TIMES"],[753,4,1,"","KRB5_TC_MATCH_TIMES_EXACT"],[754,4,1,"","KRB5_TC_NOTICKET"],[755,4,1,"","KRB5_TC_OPENCLOSE"],[756,4,1,"","KRB5_TC_SUPPORTED_KTYPES"],[757,4,1,"","KRB5_TGS_NAME"],[758,4,1,"","KRB5_TGS_NAME_SIZE"],[759,4,1,"","KRB5_TGS_REP"],[760,4,1,"","KRB5_TGS_REQ"],[761,4,1,"","KRB5_TKT_CREDS_STEP_FLAG_CONTINUE"],[762,4,1,"","KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL"],[763,4,1,"","KRB5_WELLKNOWN_NAMESTR"],[764,4,1,"","LR_TYPE_INTERPRETATION_MASK"],[765,4,1,"","LR_TYPE_THIS_SERVER_ONLY"],[766,4,1,"","MAX_KEYTAB_NAME_LEN"],[767,4,1,"","MSEC_DIRBIT"],[768,4,1,"","MSEC_VAL_MASK"],[769,4,1,"","SALT_TYPE_AFS_LENGTH"],[770,4,1,"","SALT_TYPE_NO_LENGTH"],[771,4,1,"","THREEPARAMOPEN"],[772,4,1,"","TKT_FLG_ANONYMOUS"],[773,4,1,"","TKT_FLG_ENC_PA_REP"],[774,4,1,"","TKT_FLG_FORWARDABLE"],[775,4,1,"","TKT_FLG_FORWARDED"],[776,4,1,"","TKT_FLG_HW_AUTH"],[777,4,1,"","TKT_FLG_INITIAL"],[778,4,1,"","TKT_FLG_INVALID"],[779,4,1,"","TKT_FLG_MAY_POSTDATE"],[780,4,1,"","TKT_FLG_OK_AS_DELEGATE"],[781,4,1,"","TKT_FLG_POSTDATED"],[782,4,1,"","TKT_FLG_PRE_AUTH"],[783,4,1,"","TKT_FLG_PROXIABLE"],[784,4,1,"","TKT_FLG_PROXY"],[785,4,1,"","TKT_FLG_RENEWABLE"],[786,4,1,"","TKT_FLG_TRANSIT_POLICY_CHECKED"],[787,4,1,"","VALID_INT_BITS"],[788,4,1,"","VALID_UINT_BITS"],[790,4,1,"","krb524_convert_creds_kdc"],[791,4,1,"","krb524_init_ets"],[792,4,1,"","krb5_const"],[793,4,1,"","krb5_princ_component"],[794,4,1,"","krb5_princ_name"],[795,4,1,"","krb5_princ_realm"],[796,4,1,"","krb5_princ_set_realm"],[797,4,1,"","krb5_princ_set_realm_data"],[798,4,1,"","krb5_princ_set_realm_length"],[799,4,1,"","krb5_princ_size"],[800,4,1,"","krb5_princ_type"],[801,4,1,"","krb5_roundup"],[802,4,1,"","krb5_x"],[803,4,1,"","krb5_xc"]],krb5_425_conv_principal:[[49,1,1,"c.krb5_425_conv_principal","context"],[49,1,1,"c.krb5_425_conv_principal","instance"],[49,1,1,"c.krb5_425_conv_principal","name"],[49,1,1,"c.krb5_425_conv_principal","princ"],[49,1,1,"c.krb5_425_conv_principal","realm"]],krb5_524_conv_principal:[[50,1,1,"c.krb5_524_conv_principal","context"],[50,1,1,"c.krb5_524_conv_principal","inst"],[50,1,1,"c.krb5_524_conv_principal","name"],[50,1,1,"c.krb5_524_conv_principal","princ"],[50,1,1,"c.krb5_524_conv_principal","realm"]],krb5_524_convert_creds:[[51,1,1,"c.krb5_524_convert_creds","context"],[51,1,1,"c.krb5_524_convert_creds","v4creds"],[51,1,1,"c.krb5_524_convert_creds","v5creds"]],krb5_address:[[805,3,1,"c.krb5_address.addrtype","addrtype"],[805,3,1,"c.krb5_address.contents","contents"],[805,3,1,"c.krb5_address.length","length"],[805,3,1,"c.krb5_address.magic","magic"]],krb5_address_compare:[[52,1,1,"c.krb5_address_compare","addr1"],[52,1,1,"c.krb5_address_compare","addr2"],[52,1,1,"c.krb5_address_compare","context"]],krb5_address_order:[[53,1,1,"c.krb5_address_order","addr1"],[53,1,1,"c.krb5_address_order","addr2"],[53,1,1,"c.krb5_address_order","context"]],krb5_address_search:[[54,1,1,"c.krb5_address_search","addr"],[54,1,1,"c.krb5_address_search","addrlist"],[54,1,1,"c.krb5_address_search","context"]],krb5_allow_weak_crypto:[[55,1,1,"c.krb5_allow_weak_crypto","context"],[55,1,1,"c.krb5_allow_weak_crypto","enable"]],krb5_aname_to_localname:[[56,1,1,"c.krb5_aname_to_localname","aname"],[56,1,1,"c.krb5_aname_to_localname","context"],[56,1,1,"c.krb5_aname_to_localname","lname"],[56,1,1,"c.krb5_aname_to_localname","lnsize_in"]],krb5_anonymous_principal:[[57,1,1,"c.krb5_anonymous_principal","None"]],krb5_anonymous_realm:[[58,1,1,"c.krb5_anonymous_realm","None"]],krb5_ap_rep:[[807,3,1,"c.krb5_ap_rep.enc_part","enc_part"],[807,3,1,"c.krb5_ap_rep.magic","magic"]],krb5_ap_rep_enc_part:[[808,3,1,"c.krb5_ap_rep_enc_part.ctime","ctime"],[808,3,1,"c.krb5_ap_rep_enc_part.cusec","cusec"],[808,3,1,"c.krb5_ap_rep_enc_part.magic","magic"],[808,3,1,"c.krb5_ap_rep_enc_part.seq_number","seq_number"],[808,3,1,"c.krb5_ap_rep_enc_part.subkey","subkey"]],krb5_ap_req:[[809,3,1,"c.krb5_ap_req.ap_options","ap_options"],[809,3,1,"c.krb5_ap_req.authenticator","authenticator"],[809,3,1,"c.krb5_ap_req.magic","magic"],[809,3,1,"c.krb5_ap_req.ticket","ticket"]],krb5_appdefault_boolean:[[59,1,1,"c.krb5_appdefault_boolean","appname"],[59,1,1,"c.krb5_appdefault_boolean","context"],[59,1,1,"c.krb5_appdefault_boolean","default_value"],[59,1,1,"c.krb5_appdefault_boolean","option"],[59,1,1,"c.krb5_appdefault_boolean","realm"],[59,1,1,"c.krb5_appdefault_boolean","ret_value"]],krb5_appdefault_string:[[60,1,1,"c.krb5_appdefault_string","appname"],[60,1,1,"c.krb5_appdefault_string","context"],[60,1,1,"c.krb5_appdefault_string","default_value"],[60,1,1,"c.krb5_appdefault_string","option"],[60,1,1,"c.krb5_appdefault_string","realm"],[60,1,1,"c.krb5_appdefault_string","ret_value"]],krb5_auth_con_free:[[61,1,1,"c.krb5_auth_con_free","auth_context"],[61,1,1,"c.krb5_auth_con_free","context"]],krb5_auth_con_genaddrs:[[62,1,1,"c.krb5_auth_con_genaddrs","auth_context"],[62,1,1,"c.krb5_auth_con_genaddrs","context"],[62,1,1,"c.krb5_auth_con_genaddrs","flags"],[62,1,1,"c.krb5_auth_con_genaddrs","infd"]],krb5_auth_con_get_checksum_func:[[63,1,1,"c.krb5_auth_con_get_checksum_func","auth_context"],[63,1,1,"c.krb5_auth_con_get_checksum_func","context"],[63,1,1,"c.krb5_auth_con_get_checksum_func","data"],[63,1,1,"c.krb5_auth_con_get_checksum_func","func"]],krb5_auth_con_getaddrs:[[64,1,1,"c.krb5_auth_con_getaddrs","auth_context"],[64,1,1,"c.krb5_auth_con_getaddrs","context"],[64,1,1,"c.krb5_auth_con_getaddrs","local_addr"],[64,1,1,"c.krb5_auth_con_getaddrs","remote_addr"]],krb5_auth_con_getauthenticator:[[65,1,1,"c.krb5_auth_con_getauthenticator","auth_context"],[65,1,1,"c.krb5_auth_con_getauthenticator","authenticator"],[65,1,1,"c.krb5_auth_con_getauthenticator","context"]],krb5_auth_con_getflags:[[66,1,1,"c.krb5_auth_con_getflags","auth_context"],[66,1,1,"c.krb5_auth_con_getflags","context"],[66,1,1,"c.krb5_auth_con_getflags","flags"]],krb5_auth_con_getkey:[[67,1,1,"c.krb5_auth_con_getkey","auth_context"],[67,1,1,"c.krb5_auth_con_getkey","context"],[67,1,1,"c.krb5_auth_con_getkey","keyblock"]],krb5_auth_con_getkey_k:[[68,1,1,"c.krb5_auth_con_getkey_k","auth_context"],[68,1,1,"c.krb5_auth_con_getkey_k","context"],[68,1,1,"c.krb5_auth_con_getkey_k","key"]],krb5_auth_con_getlocalseqnumber:[[69,1,1,"c.krb5_auth_con_getlocalseqnumber","auth_context"],[69,1,1,"c.krb5_auth_con_getlocalseqnumber","context"],[69,1,1,"c.krb5_auth_con_getlocalseqnumber","seqnumber"]],krb5_auth_con_getlocalsubkey:[[70,1,1,"c.krb5_auth_con_getlocalsubkey","auth_context"],[70,1,1,"c.krb5_auth_con_getlocalsubkey","context"],[70,1,1,"c.krb5_auth_con_getlocalsubkey","keyblock"]],krb5_auth_con_getrcache:[[71,1,1,"c.krb5_auth_con_getrcache","auth_context"],[71,1,1,"c.krb5_auth_con_getrcache","context"],[71,1,1,"c.krb5_auth_con_getrcache","rcache"]],krb5_auth_con_getrecvsubkey:[[72,1,1,"c.krb5_auth_con_getrecvsubkey","ac"],[72,1,1,"c.krb5_auth_con_getrecvsubkey","ctx"],[72,1,1,"c.krb5_auth_con_getrecvsubkey","keyblock"]],krb5_auth_con_getrecvsubkey_k:[[73,1,1,"c.krb5_auth_con_getrecvsubkey_k","ac"],[73,1,1,"c.krb5_auth_con_getrecvsubkey_k","ctx"],[73,1,1,"c.krb5_auth_con_getrecvsubkey_k","key"]],krb5_auth_con_getremoteseqnumber:[[74,1,1,"c.krb5_auth_con_getremoteseqnumber","auth_context"],[74,1,1,"c.krb5_auth_con_getremoteseqnumber","context"],[74,1,1,"c.krb5_auth_con_getremoteseqnumber","seqnumber"]],krb5_auth_con_getremotesubkey:[[75,1,1,"c.krb5_auth_con_getremotesubkey","auth_context"],[75,1,1,"c.krb5_auth_con_getremotesubkey","context"],[75,1,1,"c.krb5_auth_con_getremotesubkey","keyblock"]],krb5_auth_con_getsendsubkey:[[76,1,1,"c.krb5_auth_con_getsendsubkey","ac"],[76,1,1,"c.krb5_auth_con_getsendsubkey","ctx"],[76,1,1,"c.krb5_auth_con_getsendsubkey","keyblock"]],krb5_auth_con_getsendsubkey_k:[[77,1,1,"c.krb5_auth_con_getsendsubkey_k","ac"],[77,1,1,"c.krb5_auth_con_getsendsubkey_k","ctx"],[77,1,1,"c.krb5_auth_con_getsendsubkey_k","key"]],krb5_auth_con_init:[[78,1,1,"c.krb5_auth_con_init","auth_context"],[78,1,1,"c.krb5_auth_con_init","context"]],krb5_auth_con_initivector:[[79,1,1,"c.krb5_auth_con_initivector","auth_context"],[79,1,1,"c.krb5_auth_con_initivector","context"]],krb5_auth_con_set_checksum_func:[[80,1,1,"c.krb5_auth_con_set_checksum_func","auth_context"],[80,1,1,"c.krb5_auth_con_set_checksum_func","context"],[80,1,1,"c.krb5_auth_con_set_checksum_func","data"],[80,1,1,"c.krb5_auth_con_set_checksum_func","func"]],krb5_auth_con_set_req_cksumtype:[[81,1,1,"c.krb5_auth_con_set_req_cksumtype","auth_context"],[81,1,1,"c.krb5_auth_con_set_req_cksumtype","cksumtype"],[81,1,1,"c.krb5_auth_con_set_req_cksumtype","context"]],krb5_auth_con_setaddrs:[[82,1,1,"c.krb5_auth_con_setaddrs","auth_context"],[82,1,1,"c.krb5_auth_con_setaddrs","context"],[82,1,1,"c.krb5_auth_con_setaddrs","local_addr"],[82,1,1,"c.krb5_auth_con_setaddrs","remote_addr"]],krb5_auth_con_setflags:[[83,1,1,"c.krb5_auth_con_setflags","auth_context"],[83,1,1,"c.krb5_auth_con_setflags","context"],[83,1,1,"c.krb5_auth_con_setflags","flags"]],krb5_auth_con_setports:[[84,1,1,"c.krb5_auth_con_setports","auth_context"],[84,1,1,"c.krb5_auth_con_setports","context"],[84,1,1,"c.krb5_auth_con_setports","local_port"],[84,1,1,"c.krb5_auth_con_setports","remote_port"]],krb5_auth_con_setrcache:[[85,1,1,"c.krb5_auth_con_setrcache","auth_context"],[85,1,1,"c.krb5_auth_con_setrcache","context"],[85,1,1,"c.krb5_auth_con_setrcache","rcache"]],krb5_auth_con_setrecvsubkey:[[86,1,1,"c.krb5_auth_con_setrecvsubkey","ac"],[86,1,1,"c.krb5_auth_con_setrecvsubkey","ctx"],[86,1,1,"c.krb5_auth_con_setrecvsubkey","keyblock"]],krb5_auth_con_setrecvsubkey_k:[[87,1,1,"c.krb5_auth_con_setrecvsubkey_k","ac"],[87,1,1,"c.krb5_auth_con_setrecvsubkey_k","ctx"],[87,1,1,"c.krb5_auth_con_setrecvsubkey_k","key"]],krb5_auth_con_setsendsubkey:[[88,1,1,"c.krb5_auth_con_setsendsubkey","ac"],[88,1,1,"c.krb5_auth_con_setsendsubkey","ctx"],[88,1,1,"c.krb5_auth_con_setsendsubkey","keyblock"]],krb5_auth_con_setsendsubkey_k:[[89,1,1,"c.krb5_auth_con_setsendsubkey_k","ac"],[89,1,1,"c.krb5_auth_con_setsendsubkey_k","ctx"],[89,1,1,"c.krb5_auth_con_setsendsubkey_k","key"]],krb5_auth_con_setuseruserkey:[[90,1,1,"c.krb5_auth_con_setuseruserkey","auth_context"],[90,1,1,"c.krb5_auth_con_setuseruserkey","context"],[90,1,1,"c.krb5_auth_con_setuseruserkey","keyblock"]],krb5_authdata:[[811,3,1,"c.krb5_authdata.ad_type","ad_type"],[811,3,1,"c.krb5_authdata.contents","contents"],[811,3,1,"c.krb5_authdata.length","length"],[811,3,1,"c.krb5_authdata.magic","magic"]],krb5_authenticator:[[813,3,1,"c.krb5_authenticator.authorization_data","authorization_data"],[813,3,1,"c.krb5_authenticator.checksum","checksum"],[813,3,1,"c.krb5_authenticator.client","client"],[813,3,1,"c.krb5_authenticator.ctime","ctime"],[813,3,1,"c.krb5_authenticator.cusec","cusec"],[813,3,1,"c.krb5_authenticator.magic","magic"],[813,3,1,"c.krb5_authenticator.seq_number","seq_number"],[813,3,1,"c.krb5_authenticator.subkey","subkey"]],krb5_build_principal:[[91,1,1,"c.krb5_build_principal","context"],[91,1,1,"c.krb5_build_principal","princ"],[91,1,1,"c.krb5_build_principal","realm"],[91,1,1,"c.krb5_build_principal","rlen"]],krb5_build_principal_alloc_va:[[92,1,1,"c.krb5_build_principal_alloc_va","ap"],[92,1,1,"c.krb5_build_principal_alloc_va","context"],[92,1,1,"c.krb5_build_principal_alloc_va","princ"],[92,1,1,"c.krb5_build_principal_alloc_va","realm"],[92,1,1,"c.krb5_build_principal_alloc_va","rlen"]],krb5_build_principal_ext:[[93,1,1,"c.krb5_build_principal_ext","context"],[93,1,1,"c.krb5_build_principal_ext","princ"],[93,1,1,"c.krb5_build_principal_ext","realm"],[93,1,1,"c.krb5_build_principal_ext","rlen"]],krb5_build_principal_va:[[94,1,1,"c.krb5_build_principal_va","ap"],[94,1,1,"c.krb5_build_principal_va","context"],[94,1,1,"c.krb5_build_principal_va","princ"],[94,1,1,"c.krb5_build_principal_va","realm"],[94,1,1,"c.krb5_build_principal_va","rlen"]],krb5_c_block_size:[[95,1,1,"c.krb5_c_block_size","blocksize"],[95,1,1,"c.krb5_c_block_size","context"],[95,1,1,"c.krb5_c_block_size","enctype"]],krb5_c_checksum_length:[[96,1,1,"c.krb5_c_checksum_length","cksumtype"],[96,1,1,"c.krb5_c_checksum_length","context"],[96,1,1,"c.krb5_c_checksum_length","length"]],krb5_c_crypto_length:[[97,1,1,"c.krb5_c_crypto_length","context"],[97,1,1,"c.krb5_c_crypto_length","enctype"],[97,1,1,"c.krb5_c_crypto_length","size"],[97,1,1,"c.krb5_c_crypto_length","type"]],krb5_c_crypto_length_iov:[[98,1,1,"c.krb5_c_crypto_length_iov","context"],[98,1,1,"c.krb5_c_crypto_length_iov","data"],[98,1,1,"c.krb5_c_crypto_length_iov","enctype"],[98,1,1,"c.krb5_c_crypto_length_iov","num_data"]],krb5_c_decrypt:[[99,1,1,"c.krb5_c_decrypt","cipher_state"],[99,1,1,"c.krb5_c_decrypt","context"],[99,1,1,"c.krb5_c_decrypt","input"],[99,1,1,"c.krb5_c_decrypt","key"],[99,1,1,"c.krb5_c_decrypt","output"],[99,1,1,"c.krb5_c_decrypt","usage"]],krb5_c_decrypt_iov:[[100,1,1,"c.krb5_c_decrypt_iov","cipher_state"],[100,1,1,"c.krb5_c_decrypt_iov","context"],[100,1,1,"c.krb5_c_decrypt_iov","data"],[100,1,1,"c.krb5_c_decrypt_iov","keyblock"],[100,1,1,"c.krb5_c_decrypt_iov","num_data"],[100,1,1,"c.krb5_c_decrypt_iov","usage"]],krb5_c_derive_prfplus:[[101,1,1,"c.krb5_c_derive_prfplus","context"],[101,1,1,"c.krb5_c_derive_prfplus","enctype"],[101,1,1,"c.krb5_c_derive_prfplus","input"],[101,1,1,"c.krb5_c_derive_prfplus","k"],[101,1,1,"c.krb5_c_derive_prfplus","out"]],krb5_c_encrypt:[[102,1,1,"c.krb5_c_encrypt","cipher_state"],[102,1,1,"c.krb5_c_encrypt","context"],[102,1,1,"c.krb5_c_encrypt","input"],[102,1,1,"c.krb5_c_encrypt","key"],[102,1,1,"c.krb5_c_encrypt","output"],[102,1,1,"c.krb5_c_encrypt","usage"]],krb5_c_encrypt_iov:[[103,1,1,"c.krb5_c_encrypt_iov","cipher_state"],[103,1,1,"c.krb5_c_encrypt_iov","context"],[103,1,1,"c.krb5_c_encrypt_iov","data"],[103,1,1,"c.krb5_c_encrypt_iov","keyblock"],[103,1,1,"c.krb5_c_encrypt_iov","num_data"],[103,1,1,"c.krb5_c_encrypt_iov","usage"]],krb5_c_encrypt_length:[[104,1,1,"c.krb5_c_encrypt_length","context"],[104,1,1,"c.krb5_c_encrypt_length","enctype"],[104,1,1,"c.krb5_c_encrypt_length","inputlen"],[104,1,1,"c.krb5_c_encrypt_length","length"]],krb5_c_enctype_compare:[[105,1,1,"c.krb5_c_enctype_compare","context"],[105,1,1,"c.krb5_c_enctype_compare","e1"],[105,1,1,"c.krb5_c_enctype_compare","e2"],[105,1,1,"c.krb5_c_enctype_compare","similar"]],krb5_c_free_state:[[106,1,1,"c.krb5_c_free_state","context"],[106,1,1,"c.krb5_c_free_state","key"],[106,1,1,"c.krb5_c_free_state","state"]],krb5_c_fx_cf2_simple:[[107,1,1,"c.krb5_c_fx_cf2_simple","context"],[107,1,1,"c.krb5_c_fx_cf2_simple","k1"],[107,1,1,"c.krb5_c_fx_cf2_simple","k2"],[107,1,1,"c.krb5_c_fx_cf2_simple","out"],[107,1,1,"c.krb5_c_fx_cf2_simple","pepper1"],[107,1,1,"c.krb5_c_fx_cf2_simple","pepper2"]],krb5_c_init_state:[[108,1,1,"c.krb5_c_init_state","context"],[108,1,1,"c.krb5_c_init_state","key"],[108,1,1,"c.krb5_c_init_state","new_state"],[108,1,1,"c.krb5_c_init_state","usage"]],krb5_c_is_coll_proof_cksum:[[109,1,1,"c.krb5_c_is_coll_proof_cksum","ctype"]],krb5_c_is_keyed_cksum:[[110,1,1,"c.krb5_c_is_keyed_cksum","ctype"]],krb5_c_keyed_checksum_types:[[111,1,1,"c.krb5_c_keyed_checksum_types","cksumtypes"],[111,1,1,"c.krb5_c_keyed_checksum_types","context"],[111,1,1,"c.krb5_c_keyed_checksum_types","count"],[111,1,1,"c.krb5_c_keyed_checksum_types","enctype"]],krb5_c_keylengths:[[112,1,1,"c.krb5_c_keylengths","context"],[112,1,1,"c.krb5_c_keylengths","enctype"],[112,1,1,"c.krb5_c_keylengths","keybytes"],[112,1,1,"c.krb5_c_keylengths","keylength"]],krb5_c_make_checksum:[[113,1,1,"c.krb5_c_make_checksum","cksum"],[113,1,1,"c.krb5_c_make_checksum","cksumtype"],[113,1,1,"c.krb5_c_make_checksum","context"],[113,1,1,"c.krb5_c_make_checksum","input"],[113,1,1,"c.krb5_c_make_checksum","key"],[113,1,1,"c.krb5_c_make_checksum","usage"]],krb5_c_make_checksum_iov:[[114,1,1,"c.krb5_c_make_checksum_iov","cksumtype"],[114,1,1,"c.krb5_c_make_checksum_iov","context"],[114,1,1,"c.krb5_c_make_checksum_iov","data"],[114,1,1,"c.krb5_c_make_checksum_iov","key"],[114,1,1,"c.krb5_c_make_checksum_iov","num_data"],[114,1,1,"c.krb5_c_make_checksum_iov","usage"]],krb5_c_make_random_key:[[115,1,1,"c.krb5_c_make_random_key","context"],[115,1,1,"c.krb5_c_make_random_key","enctype"],[115,1,1,"c.krb5_c_make_random_key","k5_random_key"]],krb5_c_padding_length:[[116,1,1,"c.krb5_c_padding_length","context"],[116,1,1,"c.krb5_c_padding_length","data_length"],[116,1,1,"c.krb5_c_padding_length","enctype"],[116,1,1,"c.krb5_c_padding_length","size"]],krb5_c_prf:[[117,1,1,"c.krb5_c_prf","context"],[117,1,1,"c.krb5_c_prf","input"],[117,1,1,"c.krb5_c_prf","keyblock"],[117,1,1,"c.krb5_c_prf","output"]],krb5_c_prf_length:[[118,1,1,"c.krb5_c_prf_length","context"],[118,1,1,"c.krb5_c_prf_length","enctype"],[118,1,1,"c.krb5_c_prf_length","len"]],krb5_c_prfplus:[[119,1,1,"c.krb5_c_prfplus","context"],[119,1,1,"c.krb5_c_prfplus","input"],[119,1,1,"c.krb5_c_prfplus","k"],[119,1,1,"c.krb5_c_prfplus","output"]],krb5_c_random_add_entropy:[[120,1,1,"c.krb5_c_random_add_entropy","context"],[120,1,1,"c.krb5_c_random_add_entropy","data"],[120,1,1,"c.krb5_c_random_add_entropy","randsource"]],krb5_c_random_make_octets:[[121,1,1,"c.krb5_c_random_make_octets","context"],[121,1,1,"c.krb5_c_random_make_octets","data"]],krb5_c_random_os_entropy:[[122,1,1,"c.krb5_c_random_os_entropy","context"],[122,1,1,"c.krb5_c_random_os_entropy","strong"],[122,1,1,"c.krb5_c_random_os_entropy","success"]],krb5_c_random_seed:[[123,1,1,"c.krb5_c_random_seed","context"],[123,1,1,"c.krb5_c_random_seed","data"]],krb5_c_random_to_key:[[124,1,1,"c.krb5_c_random_to_key","context"],[124,1,1,"c.krb5_c_random_to_key","enctype"],[124,1,1,"c.krb5_c_random_to_key","k5_random_key"],[124,1,1,"c.krb5_c_random_to_key","random_data"]],krb5_c_string_to_key:[[125,1,1,"c.krb5_c_string_to_key","context"],[125,1,1,"c.krb5_c_string_to_key","enctype"],[125,1,1,"c.krb5_c_string_to_key","key"],[125,1,1,"c.krb5_c_string_to_key","salt"],[125,1,1,"c.krb5_c_string_to_key","string"]],krb5_c_string_to_key_with_params:[[126,1,1,"c.krb5_c_string_to_key_with_params","context"],[126,1,1,"c.krb5_c_string_to_key_with_params","enctype"],[126,1,1,"c.krb5_c_string_to_key_with_params","key"],[126,1,1,"c.krb5_c_string_to_key_with_params","params"],[126,1,1,"c.krb5_c_string_to_key_with_params","salt"],[126,1,1,"c.krb5_c_string_to_key_with_params","string"]],krb5_c_valid_cksumtype:[[127,1,1,"c.krb5_c_valid_cksumtype","ctype"]],krb5_c_valid_enctype:[[128,1,1,"c.krb5_c_valid_enctype","ktype"]],krb5_c_verify_checksum:[[129,1,1,"c.krb5_c_verify_checksum","cksum"],[129,1,1,"c.krb5_c_verify_checksum","context"],[129,1,1,"c.krb5_c_verify_checksum","data"],[129,1,1,"c.krb5_c_verify_checksum","key"],[129,1,1,"c.krb5_c_verify_checksum","usage"],[129,1,1,"c.krb5_c_verify_checksum","valid"]],krb5_c_verify_checksum_iov:[[130,1,1,"c.krb5_c_verify_checksum_iov","cksumtype"],[130,1,1,"c.krb5_c_verify_checksum_iov","context"],[130,1,1,"c.krb5_c_verify_checksum_iov","data"],[130,1,1,"c.krb5_c_verify_checksum_iov","key"],[130,1,1,"c.krb5_c_verify_checksum_iov","num_data"],[130,1,1,"c.krb5_c_verify_checksum_iov","usage"],[130,1,1,"c.krb5_c_verify_checksum_iov","valid"]],krb5_calculate_checksum:[[131,1,1,"c.krb5_calculate_checksum","context"],[131,1,1,"c.krb5_calculate_checksum","ctype"],[131,1,1,"c.krb5_calculate_checksum","in"],[131,1,1,"c.krb5_calculate_checksum","in_length"],[131,1,1,"c.krb5_calculate_checksum","outcksum"],[131,1,1,"c.krb5_calculate_checksum","seed"],[131,1,1,"c.krb5_calculate_checksum","seed_length"]],krb5_cc_cache_match:[[132,1,1,"c.krb5_cc_cache_match","cache_out"],[132,1,1,"c.krb5_cc_cache_match","client"],[132,1,1,"c.krb5_cc_cache_match","context"]],krb5_cc_close:[[133,1,1,"c.krb5_cc_close","cache"],[133,1,1,"c.krb5_cc_close","context"]],krb5_cc_copy_creds:[[134,1,1,"c.krb5_cc_copy_creds","context"],[134,1,1,"c.krb5_cc_copy_creds","incc"],[134,1,1,"c.krb5_cc_copy_creds","outcc"]],krb5_cc_default:[[135,1,1,"c.krb5_cc_default","ccache"],[135,1,1,"c.krb5_cc_default","context"]],krb5_cc_default_name:[[136,1,1,"c.krb5_cc_default_name","context"]],krb5_cc_destroy:[[137,1,1,"c.krb5_cc_destroy","cache"],[137,1,1,"c.krb5_cc_destroy","context"]],krb5_cc_dup:[[138,1,1,"c.krb5_cc_dup","context"],[138,1,1,"c.krb5_cc_dup","in"],[138,1,1,"c.krb5_cc_dup","out"]],krb5_cc_end_seq_get:[[139,1,1,"c.krb5_cc_end_seq_get","cache"],[139,1,1,"c.krb5_cc_end_seq_get","context"],[139,1,1,"c.krb5_cc_end_seq_get","cursor"]],krb5_cc_gen_new:[[140,1,1,"c.krb5_cc_gen_new","cache"],[140,1,1,"c.krb5_cc_gen_new","context"]],krb5_cc_get_config:[[141,1,1,"c.krb5_cc_get_config","context"],[141,1,1,"c.krb5_cc_get_config","data"],[141,1,1,"c.krb5_cc_get_config","id"],[141,1,1,"c.krb5_cc_get_config","key"],[141,1,1,"c.krb5_cc_get_config","principal"]],krb5_cc_get_flags:[[142,1,1,"c.krb5_cc_get_flags","cache"],[142,1,1,"c.krb5_cc_get_flags","context"],[142,1,1,"c.krb5_cc_get_flags","flags"]],krb5_cc_get_full_name:[[143,1,1,"c.krb5_cc_get_full_name","cache"],[143,1,1,"c.krb5_cc_get_full_name","context"],[143,1,1,"c.krb5_cc_get_full_name","fullname_out"]],krb5_cc_get_name:[[144,1,1,"c.krb5_cc_get_name","cache"],[144,1,1,"c.krb5_cc_get_name","context"]],krb5_cc_get_principal:[[145,1,1,"c.krb5_cc_get_principal","cache"],[145,1,1,"c.krb5_cc_get_principal","context"],[145,1,1,"c.krb5_cc_get_principal","principal"]],krb5_cc_get_type:[[146,1,1,"c.krb5_cc_get_type","cache"],[146,1,1,"c.krb5_cc_get_type","context"]],krb5_cc_initialize:[[147,1,1,"c.krb5_cc_initialize","cache"],[147,1,1,"c.krb5_cc_initialize","context"],[147,1,1,"c.krb5_cc_initialize","principal"]],krb5_cc_move:[[148,1,1,"c.krb5_cc_move","context"],[148,1,1,"c.krb5_cc_move","dst"],[148,1,1,"c.krb5_cc_move","src"]],krb5_cc_new_unique:[[149,1,1,"c.krb5_cc_new_unique","context"],[149,1,1,"c.krb5_cc_new_unique","hint"],[149,1,1,"c.krb5_cc_new_unique","id"],[149,1,1,"c.krb5_cc_new_unique","type"]],krb5_cc_next_cred:[[150,1,1,"c.krb5_cc_next_cred","cache"],[150,1,1,"c.krb5_cc_next_cred","context"],[150,1,1,"c.krb5_cc_next_cred","creds"],[150,1,1,"c.krb5_cc_next_cred","cursor"]],krb5_cc_remove_cred:[[151,1,1,"c.krb5_cc_remove_cred","cache"],[151,1,1,"c.krb5_cc_remove_cred","context"],[151,1,1,"c.krb5_cc_remove_cred","creds"],[151,1,1,"c.krb5_cc_remove_cred","flags"]],krb5_cc_resolve:[[152,1,1,"c.krb5_cc_resolve","cache"],[152,1,1,"c.krb5_cc_resolve","context"],[152,1,1,"c.krb5_cc_resolve","name"]],krb5_cc_retrieve_cred:[[153,1,1,"c.krb5_cc_retrieve_cred","cache"],[153,1,1,"c.krb5_cc_retrieve_cred","context"],[153,1,1,"c.krb5_cc_retrieve_cred","creds"],[153,1,1,"c.krb5_cc_retrieve_cred","flags"],[153,1,1,"c.krb5_cc_retrieve_cred","mcreds"]],krb5_cc_select:[[154,1,1,"c.krb5_cc_select","cache_out"],[154,1,1,"c.krb5_cc_select","context"],[154,1,1,"c.krb5_cc_select","princ_out"],[154,1,1,"c.krb5_cc_select","server"]],krb5_cc_set_config:[[155,1,1,"c.krb5_cc_set_config","context"],[155,1,1,"c.krb5_cc_set_config","data"],[155,1,1,"c.krb5_cc_set_config","id"],[155,1,1,"c.krb5_cc_set_config","key"],[155,1,1,"c.krb5_cc_set_config","principal"]],krb5_cc_set_default_name:[[156,1,1,"c.krb5_cc_set_default_name","context"],[156,1,1,"c.krb5_cc_set_default_name","name"]],krb5_cc_set_flags:[[157,1,1,"c.krb5_cc_set_flags","cache"],[157,1,1,"c.krb5_cc_set_flags","context"],[157,1,1,"c.krb5_cc_set_flags","flags"]],krb5_cc_start_seq_get:[[158,1,1,"c.krb5_cc_start_seq_get","cache"],[158,1,1,"c.krb5_cc_start_seq_get","context"],[158,1,1,"c.krb5_cc_start_seq_get","cursor"]],krb5_cc_store_cred:[[159,1,1,"c.krb5_cc_store_cred","cache"],[159,1,1,"c.krb5_cc_store_cred","context"],[159,1,1,"c.krb5_cc_store_cred","creds"]],krb5_cc_support_switch:[[160,1,1,"c.krb5_cc_support_switch","context"],[160,1,1,"c.krb5_cc_support_switch","type"]],krb5_cc_switch:[[161,1,1,"c.krb5_cc_switch","cache"],[161,1,1,"c.krb5_cc_switch","context"]],krb5_cccol_cursor_free:[[162,1,1,"c.krb5_cccol_cursor_free","context"],[162,1,1,"c.krb5_cccol_cursor_free","cursor"]],krb5_cccol_cursor_new:[[163,1,1,"c.krb5_cccol_cursor_new","context"],[163,1,1,"c.krb5_cccol_cursor_new","cursor"]],krb5_cccol_cursor_next:[[164,1,1,"c.krb5_cccol_cursor_next","ccache"],[164,1,1,"c.krb5_cccol_cursor_next","context"],[164,1,1,"c.krb5_cccol_cursor_next","cursor"]],krb5_cccol_have_content:[[165,1,1,"c.krb5_cccol_have_content","context"]],krb5_change_password:[[166,1,1,"c.krb5_change_password","context"],[166,1,1,"c.krb5_change_password","creds"],[166,1,1,"c.krb5_change_password","newpw"],[166,1,1,"c.krb5_change_password","result_code"],[166,1,1,"c.krb5_change_password","result_code_string"],[166,1,1,"c.krb5_change_password","result_string"]],krb5_check_clockskew:[[167,1,1,"c.krb5_check_clockskew","context"],[167,1,1,"c.krb5_check_clockskew","date"]],krb5_checksum:[[818,3,1,"c.krb5_checksum.checksum_type","checksum_type"],[818,3,1,"c.krb5_checksum.contents","contents"],[818,3,1,"c.krb5_checksum.length","length"],[818,3,1,"c.krb5_checksum.magic","magic"]],krb5_checksum_size:[[168,1,1,"c.krb5_checksum_size","context"],[168,1,1,"c.krb5_checksum_size","ctype"]],krb5_chpw_message:[[169,1,1,"c.krb5_chpw_message","context"],[169,1,1,"c.krb5_chpw_message","message_out"],[169,1,1,"c.krb5_chpw_message","server_string"]],krb5_cksumtype_to_string:[[170,1,1,"c.krb5_cksumtype_to_string","buffer"],[170,1,1,"c.krb5_cksumtype_to_string","buflen"],[170,1,1,"c.krb5_cksumtype_to_string","cksumtype"]],krb5_clear_error_message:[[171,1,1,"c.krb5_clear_error_message","ctx"]],krb5_const_principal:[[821,3,1,"c.krb5_const_principal.data","data"],[821,3,1,"c.krb5_const_principal.length","length"],[821,3,1,"c.krb5_const_principal.magic","magic"],[821,3,1,"c.krb5_const_principal.realm","realm"],[821,3,1,"c.krb5_const_principal.type","type"]],krb5_copy_addresses:[[172,1,1,"c.krb5_copy_addresses","context"],[172,1,1,"c.krb5_copy_addresses","inaddr"],[172,1,1,"c.krb5_copy_addresses","outaddr"]],krb5_copy_authdata:[[173,1,1,"c.krb5_copy_authdata","context"],[173,1,1,"c.krb5_copy_authdata","in_authdat"],[173,1,1,"c.krb5_copy_authdata","out"]],krb5_copy_authenticator:[[174,1,1,"c.krb5_copy_authenticator","authfrom"],[174,1,1,"c.krb5_copy_authenticator","authto"],[174,1,1,"c.krb5_copy_authenticator","context"]],krb5_copy_checksum:[[175,1,1,"c.krb5_copy_checksum","ckfrom"],[175,1,1,"c.krb5_copy_checksum","ckto"],[175,1,1,"c.krb5_copy_checksum","context"]],krb5_copy_context:[[176,1,1,"c.krb5_copy_context","ctx"],[176,1,1,"c.krb5_copy_context","nctx_out"]],krb5_copy_creds:[[177,1,1,"c.krb5_copy_creds","context"],[177,1,1,"c.krb5_copy_creds","incred"],[177,1,1,"c.krb5_copy_creds","outcred"]],krb5_copy_data:[[178,1,1,"c.krb5_copy_data","context"],[178,1,1,"c.krb5_copy_data","indata"],[178,1,1,"c.krb5_copy_data","outdata"]],krb5_copy_error_message:[[179,1,1,"c.krb5_copy_error_message","dest_ctx"],[179,1,1,"c.krb5_copy_error_message","src_ctx"]],krb5_copy_keyblock:[[180,1,1,"c.krb5_copy_keyblock","context"],[180,1,1,"c.krb5_copy_keyblock","from"],[180,1,1,"c.krb5_copy_keyblock","to"]],krb5_copy_keyblock_contents:[[181,1,1,"c.krb5_copy_keyblock_contents","context"],[181,1,1,"c.krb5_copy_keyblock_contents","from"],[181,1,1,"c.krb5_copy_keyblock_contents","to"]],krb5_copy_principal:[[182,1,1,"c.krb5_copy_principal","context"],[182,1,1,"c.krb5_copy_principal","inprinc"],[182,1,1,"c.krb5_copy_principal","outprinc"]],krb5_copy_ticket:[[183,1,1,"c.krb5_copy_ticket","context"],[183,1,1,"c.krb5_copy_ticket","from"],[183,1,1,"c.krb5_copy_ticket","pto"]],krb5_cred:[[823,3,1,"c.krb5_cred.enc_part","enc_part"],[823,3,1,"c.krb5_cred.enc_part2","enc_part2"],[823,3,1,"c.krb5_cred.magic","magic"],[823,3,1,"c.krb5_cred.tickets","tickets"]],krb5_cred_enc_part:[[824,3,1,"c.krb5_cred_enc_part.magic","magic"],[824,3,1,"c.krb5_cred_enc_part.nonce","nonce"],[824,3,1,"c.krb5_cred_enc_part.r_address","r_address"],[824,3,1,"c.krb5_cred_enc_part.s_address","s_address"],[824,3,1,"c.krb5_cred_enc_part.ticket_info","ticket_info"],[824,3,1,"c.krb5_cred_enc_part.timestamp","timestamp"],[824,3,1,"c.krb5_cred_enc_part.usec","usec"]],krb5_cred_info:[[825,3,1,"c.krb5_cred_info.caddrs","caddrs"],[825,3,1,"c.krb5_cred_info.client","client"],[825,3,1,"c.krb5_cred_info.flags","flags"],[825,3,1,"c.krb5_cred_info.magic","magic"],[825,3,1,"c.krb5_cred_info.server","server"],[825,3,1,"c.krb5_cred_info.session","session"],[825,3,1,"c.krb5_cred_info.times","times"]],krb5_creds:[[826,3,1,"c.krb5_creds.addresses","addresses"],[826,3,1,"c.krb5_creds.authdata","authdata"],[826,3,1,"c.krb5_creds.client","client"],[826,3,1,"c.krb5_creds.is_skey","is_skey"],[826,3,1,"c.krb5_creds.keyblock","keyblock"],[826,3,1,"c.krb5_creds.magic","magic"],[826,3,1,"c.krb5_creds.second_ticket","second_ticket"],[826,3,1,"c.krb5_creds.server","server"],[826,3,1,"c.krb5_creds.ticket","ticket"],[826,3,1,"c.krb5_creds.ticket_flags","ticket_flags"],[826,3,1,"c.krb5_creds.times","times"]],krb5_crypto_iov:[[827,3,1,"c.krb5_crypto_iov.data","data"],[827,3,1,"c.krb5_crypto_iov.flags","flags"]],krb5_data:[[829,3,1,"c.krb5_data.data","data"],[829,3,1,"c.krb5_data.length","length"],[829,3,1,"c.krb5_data.magic","magic"]],krb5_decode_authdata_container:[[184,1,1,"c.krb5_decode_authdata_container","authdata"],[184,1,1,"c.krb5_decode_authdata_container","container"],[184,1,1,"c.krb5_decode_authdata_container","context"],[184,1,1,"c.krb5_decode_authdata_container","type"]],krb5_decode_ticket:[[185,1,1,"c.krb5_decode_ticket","code"],[185,1,1,"c.krb5_decode_ticket","rep"]],krb5_decrypt:[[186,1,1,"c.krb5_decrypt","context"],[186,1,1,"c.krb5_decrypt","eblock"],[186,1,1,"c.krb5_decrypt","inptr"],[186,1,1,"c.krb5_decrypt","ivec"],[186,1,1,"c.krb5_decrypt","outptr"],[186,1,1,"c.krb5_decrypt","size"]],krb5_deltat_to_string:[[187,1,1,"c.krb5_deltat_to_string","buffer"],[187,1,1,"c.krb5_deltat_to_string","buflen"],[187,1,1,"c.krb5_deltat_to_string","deltat"]],krb5_eblock_enctype:[[188,1,1,"c.krb5_eblock_enctype","context"],[188,1,1,"c.krb5_eblock_enctype","eblock"]],krb5_enc_data:[[831,3,1,"c.krb5_enc_data.ciphertext","ciphertext"],[831,3,1,"c.krb5_enc_data.enctype","enctype"],[831,3,1,"c.krb5_enc_data.kvno","kvno"],[831,3,1,"c.krb5_enc_data.magic","magic"]],krb5_enc_kdc_rep_part:[[832,3,1,"c.krb5_enc_kdc_rep_part.caddrs","caddrs"],[832,3,1,"c.krb5_enc_kdc_rep_part.enc_padata","enc_padata"],[832,3,1,"c.krb5_enc_kdc_rep_part.flags","flags"],[832,3,1,"c.krb5_enc_kdc_rep_part.key_exp","key_exp"],[832,3,1,"c.krb5_enc_kdc_rep_part.last_req","last_req"],[832,3,1,"c.krb5_enc_kdc_rep_part.magic","magic"],[832,3,1,"c.krb5_enc_kdc_rep_part.msg_type","msg_type"],[832,3,1,"c.krb5_enc_kdc_rep_part.nonce","nonce"],[832,3,1,"c.krb5_enc_kdc_rep_part.server","server"],[832,3,1,"c.krb5_enc_kdc_rep_part.session","session"],[832,3,1,"c.krb5_enc_kdc_rep_part.times","times"]],krb5_enc_tkt_part:[[833,3,1,"c.krb5_enc_tkt_part.authorization_data","authorization_data"],[833,3,1,"c.krb5_enc_tkt_part.caddrs","caddrs"],[833,3,1,"c.krb5_enc_tkt_part.client","client"],[833,3,1,"c.krb5_enc_tkt_part.flags","flags"],[833,3,1,"c.krb5_enc_tkt_part.magic","magic"],[833,3,1,"c.krb5_enc_tkt_part.session","session"],[833,3,1,"c.krb5_enc_tkt_part.times","times"],[833,3,1,"c.krb5_enc_tkt_part.transited","transited"]],krb5_encode_authdata_container:[[189,1,1,"c.krb5_encode_authdata_container","authdata"],[189,1,1,"c.krb5_encode_authdata_container","container"],[189,1,1,"c.krb5_encode_authdata_container","context"],[189,1,1,"c.krb5_encode_authdata_container","type"]],krb5_encrypt:[[190,1,1,"c.krb5_encrypt","context"],[190,1,1,"c.krb5_encrypt","eblock"],[190,1,1,"c.krb5_encrypt","inptr"],[190,1,1,"c.krb5_encrypt","ivec"],[190,1,1,"c.krb5_encrypt","outptr"],[190,1,1,"c.krb5_encrypt","size"]],krb5_encrypt_block:[[834,3,1,"c.krb5_encrypt_block.crypto_entry","crypto_entry"],[834,3,1,"c.krb5_encrypt_block.key","key"],[834,3,1,"c.krb5_encrypt_block.magic","magic"]],krb5_encrypt_size:[[191,1,1,"c.krb5_encrypt_size","crypto"],[191,1,1,"c.krb5_encrypt_size","length"]],krb5_enctype_to_name:[[192,1,1,"c.krb5_enctype_to_name","buffer"],[192,1,1,"c.krb5_enctype_to_name","buflen"],[192,1,1,"c.krb5_enctype_to_name","enctype"],[192,1,1,"c.krb5_enctype_to_name","shortest"]],krb5_enctype_to_string:[[193,1,1,"c.krb5_enctype_to_string","buffer"],[193,1,1,"c.krb5_enctype_to_string","buflen"],[193,1,1,"c.krb5_enctype_to_string","enctype"]],krb5_error:[[836,3,1,"c.krb5_error.client","client"],[836,3,1,"c.krb5_error.ctime","ctime"],[836,3,1,"c.krb5_error.cusec","cusec"],[836,3,1,"c.krb5_error.e_data","e_data"],[836,3,1,"c.krb5_error.error","error"],[836,3,1,"c.krb5_error.magic","magic"],[836,3,1,"c.krb5_error.server","server"],[836,3,1,"c.krb5_error.stime","stime"],[836,3,1,"c.krb5_error.susec","susec"],[836,3,1,"c.krb5_error.text","text"]],krb5_expand_hostname:[[194,1,1,"c.krb5_expand_hostname","canonhost_out"],[194,1,1,"c.krb5_expand_hostname","context"],[194,1,1,"c.krb5_expand_hostname","host"]],krb5_find_authdata:[[195,1,1,"c.krb5_find_authdata","ad_type"],[195,1,1,"c.krb5_find_authdata","ap_req_authdata"],[195,1,1,"c.krb5_find_authdata","context"],[195,1,1,"c.krb5_find_authdata","results"],[195,1,1,"c.krb5_find_authdata","ticket_authdata"]],krb5_finish_key:[[196,1,1,"c.krb5_finish_key","context"],[196,1,1,"c.krb5_finish_key","eblock"]],krb5_finish_random_key:[[197,1,1,"c.krb5_finish_random_key","context"],[197,1,1,"c.krb5_finish_random_key","eblock"],[197,1,1,"c.krb5_finish_random_key","ptr"]],krb5_free_addresses:[[198,1,1,"c.krb5_free_addresses","context"],[198,1,1,"c.krb5_free_addresses","val"]],krb5_free_ap_rep_enc_part:[[199,1,1,"c.krb5_free_ap_rep_enc_part","context"],[199,1,1,"c.krb5_free_ap_rep_enc_part","val"]],krb5_free_authdata:[[200,1,1,"c.krb5_free_authdata","context"],[200,1,1,"c.krb5_free_authdata","val"]],krb5_free_authenticator:[[201,1,1,"c.krb5_free_authenticator","context"],[201,1,1,"c.krb5_free_authenticator","val"]],krb5_free_checksum:[[202,1,1,"c.krb5_free_checksum","context"],[202,1,1,"c.krb5_free_checksum","val"]],krb5_free_checksum_contents:[[203,1,1,"c.krb5_free_checksum_contents","context"],[203,1,1,"c.krb5_free_checksum_contents","val"]],krb5_free_cksumtypes:[[204,1,1,"c.krb5_free_cksumtypes","context"],[204,1,1,"c.krb5_free_cksumtypes","val"]],krb5_free_context:[[205,1,1,"c.krb5_free_context","context"]],krb5_free_cred_contents:[[206,1,1,"c.krb5_free_cred_contents","context"],[206,1,1,"c.krb5_free_cred_contents","val"]],krb5_free_creds:[[207,1,1,"c.krb5_free_creds","context"],[207,1,1,"c.krb5_free_creds","val"]],krb5_free_data:[[208,1,1,"c.krb5_free_data","context"],[208,1,1,"c.krb5_free_data","val"]],krb5_free_data_contents:[[209,1,1,"c.krb5_free_data_contents","context"],[209,1,1,"c.krb5_free_data_contents","val"]],krb5_free_default_realm:[[210,1,1,"c.krb5_free_default_realm","context"],[210,1,1,"c.krb5_free_default_realm","lrealm"]],krb5_free_enctypes:[[211,1,1,"c.krb5_free_enctypes","context"],[211,1,1,"c.krb5_free_enctypes","val"]],krb5_free_error:[[212,1,1,"c.krb5_free_error","context"],[212,1,1,"c.krb5_free_error","val"]],krb5_free_error_message:[[213,1,1,"c.krb5_free_error_message","ctx"],[213,1,1,"c.krb5_free_error_message","msg"]],krb5_free_host_realm:[[214,1,1,"c.krb5_free_host_realm","context"],[214,1,1,"c.krb5_free_host_realm","realmlist"]],krb5_free_keyblock:[[215,1,1,"c.krb5_free_keyblock","context"],[215,1,1,"c.krb5_free_keyblock","val"]],krb5_free_keyblock_contents:[[216,1,1,"c.krb5_free_keyblock_contents","context"],[216,1,1,"c.krb5_free_keyblock_contents","key"]],krb5_free_keytab_entry_contents:[[217,1,1,"c.krb5_free_keytab_entry_contents","context"],[217,1,1,"c.krb5_free_keytab_entry_contents","entry"]],krb5_free_principal:[[218,1,1,"c.krb5_free_principal","context"],[218,1,1,"c.krb5_free_principal","val"]],krb5_free_string:[[219,1,1,"c.krb5_free_string","context"],[219,1,1,"c.krb5_free_string","val"]],krb5_free_tgt_creds:[[220,1,1,"c.krb5_free_tgt_creds","context"],[220,1,1,"c.krb5_free_tgt_creds","tgts"]],krb5_free_ticket:[[221,1,1,"c.krb5_free_ticket","context"],[221,1,1,"c.krb5_free_ticket","val"]],krb5_free_unparsed_name:[[222,1,1,"c.krb5_free_unparsed_name","context"],[222,1,1,"c.krb5_free_unparsed_name","val"]],krb5_fwd_tgt_creds:[[223,1,1,"c.krb5_fwd_tgt_creds","auth_context"],[223,1,1,"c.krb5_fwd_tgt_creds","cc"],[223,1,1,"c.krb5_fwd_tgt_creds","client"],[223,1,1,"c.krb5_fwd_tgt_creds","context"],[223,1,1,"c.krb5_fwd_tgt_creds","forwardable"],[223,1,1,"c.krb5_fwd_tgt_creds","outbuf"],[223,1,1,"c.krb5_fwd_tgt_creds","rhost"],[223,1,1,"c.krb5_fwd_tgt_creds","server"]],krb5_get_credentials:[[224,1,1,"c.krb5_get_credentials","ccache"],[224,1,1,"c.krb5_get_credentials","context"],[224,1,1,"c.krb5_get_credentials","in_creds"],[224,1,1,"c.krb5_get_credentials","options"],[224,1,1,"c.krb5_get_credentials","out_creds"]],krb5_get_credentials_renew:[[225,1,1,"c.krb5_get_credentials_renew","ccache"],[225,1,1,"c.krb5_get_credentials_renew","context"],[225,1,1,"c.krb5_get_credentials_renew","in_creds"],[225,1,1,"c.krb5_get_credentials_renew","options"],[225,1,1,"c.krb5_get_credentials_renew","out_creds"]],krb5_get_credentials_validate:[[226,1,1,"c.krb5_get_credentials_validate","ccache"],[226,1,1,"c.krb5_get_credentials_validate","context"],[226,1,1,"c.krb5_get_credentials_validate","in_creds"],[226,1,1,"c.krb5_get_credentials_validate","options"],[226,1,1,"c.krb5_get_credentials_validate","out_creds"]],krb5_get_default_realm:[[227,1,1,"c.krb5_get_default_realm","context"],[227,1,1,"c.krb5_get_default_realm","lrealm"]],krb5_get_error_message:[[228,1,1,"c.krb5_get_error_message","code"],[228,1,1,"c.krb5_get_error_message","ctx"]],krb5_get_etype_info:[[229,1,1,"c.krb5_get_etype_info","context"],[229,1,1,"c.krb5_get_etype_info","enctype_out"],[229,1,1,"c.krb5_get_etype_info","opt"],[229,1,1,"c.krb5_get_etype_info","principal"],[229,1,1,"c.krb5_get_etype_info","s2kparams_out"],[229,1,1,"c.krb5_get_etype_info","salt_out"]],krb5_get_fallback_host_realm:[[230,1,1,"c.krb5_get_fallback_host_realm","context"],[230,1,1,"c.krb5_get_fallback_host_realm","hdata"],[230,1,1,"c.krb5_get_fallback_host_realm","realmsp"]],krb5_get_host_realm:[[231,1,1,"c.krb5_get_host_realm","context"],[231,1,1,"c.krb5_get_host_realm","host"],[231,1,1,"c.krb5_get_host_realm","realmsp"]],krb5_get_in_tkt_with_keytab:[[232,1,1,"c.krb5_get_in_tkt_with_keytab","addrs"],[232,1,1,"c.krb5_get_in_tkt_with_keytab","arg_keytab"],[232,1,1,"c.krb5_get_in_tkt_with_keytab","ccache"],[232,1,1,"c.krb5_get_in_tkt_with_keytab","context"],[232,1,1,"c.krb5_get_in_tkt_with_keytab","creds"],[232,1,1,"c.krb5_get_in_tkt_with_keytab","ktypes"],[232,1,1,"c.krb5_get_in_tkt_with_keytab","options"],[232,1,1,"c.krb5_get_in_tkt_with_keytab","pre_auth_types"],[232,1,1,"c.krb5_get_in_tkt_with_keytab","ret_as_reply"]],krb5_get_in_tkt_with_password:[[233,1,1,"c.krb5_get_in_tkt_with_password","addrs"],[233,1,1,"c.krb5_get_in_tkt_with_password","ccache"],[233,1,1,"c.krb5_get_in_tkt_with_password","context"],[233,1,1,"c.krb5_get_in_tkt_with_password","creds"],[233,1,1,"c.krb5_get_in_tkt_with_password","ktypes"],[233,1,1,"c.krb5_get_in_tkt_with_password","options"],[233,1,1,"c.krb5_get_in_tkt_with_password","password"],[233,1,1,"c.krb5_get_in_tkt_with_password","pre_auth_types"],[233,1,1,"c.krb5_get_in_tkt_with_password","ret_as_reply"]],krb5_get_in_tkt_with_skey:[[234,1,1,"c.krb5_get_in_tkt_with_skey","addrs"],[234,1,1,"c.krb5_get_in_tkt_with_skey","ccache"],[234,1,1,"c.krb5_get_in_tkt_with_skey","context"],[234,1,1,"c.krb5_get_in_tkt_with_skey","creds"],[234,1,1,"c.krb5_get_in_tkt_with_skey","key"],[234,1,1,"c.krb5_get_in_tkt_with_skey","ktypes"],[234,1,1,"c.krb5_get_in_tkt_with_skey","options"],[234,1,1,"c.krb5_get_in_tkt_with_skey","pre_auth_types"],[234,1,1,"c.krb5_get_in_tkt_with_skey","ret_as_reply"]],krb5_get_init_creds_keytab:[[235,1,1,"c.krb5_get_init_creds_keytab","arg_keytab"],[235,1,1,"c.krb5_get_init_creds_keytab","client"],[235,1,1,"c.krb5_get_init_creds_keytab","context"],[235,1,1,"c.krb5_get_init_creds_keytab","creds"],[235,1,1,"c.krb5_get_init_creds_keytab","in_tkt_service"],[235,1,1,"c.krb5_get_init_creds_keytab","k5_gic_options"],[235,1,1,"c.krb5_get_init_creds_keytab","start_time"]],krb5_get_init_creds_opt:[[840,3,1,"c.krb5_get_init_creds_opt.address_list","address_list"],[840,3,1,"c.krb5_get_init_creds_opt.etype_list","etype_list"],[840,3,1,"c.krb5_get_init_creds_opt.etype_list_length","etype_list_length"],[840,3,1,"c.krb5_get_init_creds_opt.flags","flags"],[840,3,1,"c.krb5_get_init_creds_opt.forwardable","forwardable"],[840,3,1,"c.krb5_get_init_creds_opt.preauth_list","preauth_list"],[840,3,1,"c.krb5_get_init_creds_opt.preauth_list_length","preauth_list_length"],[840,3,1,"c.krb5_get_init_creds_opt.proxiable","proxiable"],[840,3,1,"c.krb5_get_init_creds_opt.renew_life","renew_life"],[840,3,1,"c.krb5_get_init_creds_opt.salt","salt"],[840,3,1,"c.krb5_get_init_creds_opt.tkt_life","tkt_life"]],krb5_get_init_creds_opt_alloc:[[236,1,1,"c.krb5_get_init_creds_opt_alloc","context"],[236,1,1,"c.krb5_get_init_creds_opt_alloc","opt"]],krb5_get_init_creds_opt_free:[[237,1,1,"c.krb5_get_init_creds_opt_free","context"],[237,1,1,"c.krb5_get_init_creds_opt_free","opt"]],krb5_get_init_creds_opt_get_fast_flags:[[238,1,1,"c.krb5_get_init_creds_opt_get_fast_flags","context"],[238,1,1,"c.krb5_get_init_creds_opt_get_fast_flags","opt"],[238,1,1,"c.krb5_get_init_creds_opt_get_fast_flags","out_flags"]],krb5_get_init_creds_opt_init:[[239,1,1,"c.krb5_get_init_creds_opt_init","opt"]],krb5_get_init_creds_opt_set_address_list:[[240,1,1,"c.krb5_get_init_creds_opt_set_address_list","addresses"],[240,1,1,"c.krb5_get_init_creds_opt_set_address_list","opt"]],krb5_get_init_creds_opt_set_anonymous:[[241,1,1,"c.krb5_get_init_creds_opt_set_anonymous","anonymous"],[241,1,1,"c.krb5_get_init_creds_opt_set_anonymous","opt"]],krb5_get_init_creds_opt_set_canonicalize:[[242,1,1,"c.krb5_get_init_creds_opt_set_canonicalize","canonicalize"],[242,1,1,"c.krb5_get_init_creds_opt_set_canonicalize","opt"]],krb5_get_init_creds_opt_set_change_password_prompt:[[243,1,1,"c.krb5_get_init_creds_opt_set_change_password_prompt","opt"],[243,1,1,"c.krb5_get_init_creds_opt_set_change_password_prompt","prompt"]],krb5_get_init_creds_opt_set_etype_list:[[244,1,1,"c.krb5_get_init_creds_opt_set_etype_list","etype_list"],[244,1,1,"c.krb5_get_init_creds_opt_set_etype_list","etype_list_length"],[244,1,1,"c.krb5_get_init_creds_opt_set_etype_list","opt"]],krb5_get_init_creds_opt_set_expire_callback:[[245,1,1,"c.krb5_get_init_creds_opt_set_expire_callback","cb"],[245,1,1,"c.krb5_get_init_creds_opt_set_expire_callback","context"],[245,1,1,"c.krb5_get_init_creds_opt_set_expire_callback","data"],[245,1,1,"c.krb5_get_init_creds_opt_set_expire_callback","opt"]],krb5_get_init_creds_opt_set_fast_ccache:[[246,1,1,"c.krb5_get_init_creds_opt_set_fast_ccache","ccache"],[246,1,1,"c.krb5_get_init_creds_opt_set_fast_ccache","context"],[246,1,1,"c.krb5_get_init_creds_opt_set_fast_ccache","opt"]],krb5_get_init_creds_opt_set_fast_ccache_name:[[247,1,1,"c.krb5_get_init_creds_opt_set_fast_ccache_name","context"],[247,1,1,"c.krb5_get_init_creds_opt_set_fast_ccache_name","fast_ccache_name"],[247,1,1,"c.krb5_get_init_creds_opt_set_fast_ccache_name","opt"]],krb5_get_init_creds_opt_set_fast_flags:[[248,1,1,"c.krb5_get_init_creds_opt_set_fast_flags","context"],[248,1,1,"c.krb5_get_init_creds_opt_set_fast_flags","flags"],[248,1,1,"c.krb5_get_init_creds_opt_set_fast_flags","opt"]],krb5_get_init_creds_opt_set_forwardable:[[249,1,1,"c.krb5_get_init_creds_opt_set_forwardable","forwardable"],[249,1,1,"c.krb5_get_init_creds_opt_set_forwardable","opt"]],krb5_get_init_creds_opt_set_in_ccache:[[250,1,1,"c.krb5_get_init_creds_opt_set_in_ccache","ccache"],[250,1,1,"c.krb5_get_init_creds_opt_set_in_ccache","context"],[250,1,1,"c.krb5_get_init_creds_opt_set_in_ccache","opt"]],krb5_get_init_creds_opt_set_out_ccache:[[251,1,1,"c.krb5_get_init_creds_opt_set_out_ccache","ccache"],[251,1,1,"c.krb5_get_init_creds_opt_set_out_ccache","context"],[251,1,1,"c.krb5_get_init_creds_opt_set_out_ccache","opt"]],krb5_get_init_creds_opt_set_pa:[[252,1,1,"c.krb5_get_init_creds_opt_set_pa","attr"],[252,1,1,"c.krb5_get_init_creds_opt_set_pa","context"],[252,1,1,"c.krb5_get_init_creds_opt_set_pa","opt"],[252,1,1,"c.krb5_get_init_creds_opt_set_pa","value"]],krb5_get_init_creds_opt_set_pac_request:[[253,1,1,"c.krb5_get_init_creds_opt_set_pac_request","context"],[253,1,1,"c.krb5_get_init_creds_opt_set_pac_request","opt"],[253,1,1,"c.krb5_get_init_creds_opt_set_pac_request","req_pac"]],krb5_get_init_creds_opt_set_preauth_list:[[254,1,1,"c.krb5_get_init_creds_opt_set_preauth_list","opt"],[254,1,1,"c.krb5_get_init_creds_opt_set_preauth_list","preauth_list"],[254,1,1,"c.krb5_get_init_creds_opt_set_preauth_list","preauth_list_length"]],krb5_get_init_creds_opt_set_proxiable:[[255,1,1,"c.krb5_get_init_creds_opt_set_proxiable","opt"],[255,1,1,"c.krb5_get_init_creds_opt_set_proxiable","proxiable"]],krb5_get_init_creds_opt_set_renew_life:[[256,1,1,"c.krb5_get_init_creds_opt_set_renew_life","opt"],[256,1,1,"c.krb5_get_init_creds_opt_set_renew_life","renew_life"]],krb5_get_init_creds_opt_set_responder:[[257,1,1,"c.krb5_get_init_creds_opt_set_responder","context"],[257,1,1,"c.krb5_get_init_creds_opt_set_responder","data"],[257,1,1,"c.krb5_get_init_creds_opt_set_responder","opt"],[257,1,1,"c.krb5_get_init_creds_opt_set_responder","responder"]],krb5_get_init_creds_opt_set_salt:[[258,1,1,"c.krb5_get_init_creds_opt_set_salt","opt"],[258,1,1,"c.krb5_get_init_creds_opt_set_salt","salt"]],krb5_get_init_creds_opt_set_tkt_life:[[259,1,1,"c.krb5_get_init_creds_opt_set_tkt_life","opt"],[259,1,1,"c.krb5_get_init_creds_opt_set_tkt_life","tkt_life"]],krb5_get_init_creds_password:[[260,1,1,"c.krb5_get_init_creds_password","client"],[260,1,1,"c.krb5_get_init_creds_password","context"],[260,1,1,"c.krb5_get_init_creds_password","creds"],[260,1,1,"c.krb5_get_init_creds_password","data"],[260,1,1,"c.krb5_get_init_creds_password","in_tkt_service"],[260,1,1,"c.krb5_get_init_creds_password","k5_gic_options"],[260,1,1,"c.krb5_get_init_creds_password","password"],[260,1,1,"c.krb5_get_init_creds_password","prompter"],[260,1,1,"c.krb5_get_init_creds_password","start_time"]],krb5_get_permitted_enctypes:[[261,1,1,"c.krb5_get_permitted_enctypes","context"],[261,1,1,"c.krb5_get_permitted_enctypes","ktypes"]],krb5_get_profile:[[262,1,1,"c.krb5_get_profile","context"],[262,1,1,"c.krb5_get_profile","profile"]],krb5_get_prompt_types:[[263,1,1,"c.krb5_get_prompt_types","context"]],krb5_get_renewed_creds:[[264,1,1,"c.krb5_get_renewed_creds","ccache"],[264,1,1,"c.krb5_get_renewed_creds","client"],[264,1,1,"c.krb5_get_renewed_creds","context"],[264,1,1,"c.krb5_get_renewed_creds","creds"],[264,1,1,"c.krb5_get_renewed_creds","in_tkt_service"]],krb5_get_server_rcache:[[265,1,1,"c.krb5_get_server_rcache","context"],[265,1,1,"c.krb5_get_server_rcache","piece"],[265,1,1,"c.krb5_get_server_rcache","rcptr"]],krb5_get_time_offsets:[[266,1,1,"c.krb5_get_time_offsets","context"],[266,1,1,"c.krb5_get_time_offsets","microseconds"],[266,1,1,"c.krb5_get_time_offsets","seconds"]],krb5_get_validated_creds:[[267,1,1,"c.krb5_get_validated_creds","ccache"],[267,1,1,"c.krb5_get_validated_creds","client"],[267,1,1,"c.krb5_get_validated_creds","context"],[267,1,1,"c.krb5_get_validated_creds","creds"],[267,1,1,"c.krb5_get_validated_creds","in_tkt_service"]],krb5_gic_opt_pa_data:[[841,3,1,"c.krb5_gic_opt_pa_data.attr","attr"],[841,3,1,"c.krb5_gic_opt_pa_data.value","value"]],krb5_init_context:[[268,1,1,"c.krb5_init_context","context"]],krb5_init_context_profile:[[269,1,1,"c.krb5_init_context_profile","context"],[269,1,1,"c.krb5_init_context_profile","flags"],[269,1,1,"c.krb5_init_context_profile","profile"]],krb5_init_creds_free:[[270,1,1,"c.krb5_init_creds_free","context"],[270,1,1,"c.krb5_init_creds_free","ctx"]],krb5_init_creds_get:[[271,1,1,"c.krb5_init_creds_get","context"],[271,1,1,"c.krb5_init_creds_get","ctx"]],krb5_init_creds_get_creds:[[272,1,1,"c.krb5_init_creds_get_creds","context"],[272,1,1,"c.krb5_init_creds_get_creds","creds"],[272,1,1,"c.krb5_init_creds_get_creds","ctx"]],krb5_init_creds_get_error:[[273,1,1,"c.krb5_init_creds_get_error","context"],[273,1,1,"c.krb5_init_creds_get_error","ctx"],[273,1,1,"c.krb5_init_creds_get_error","error"]],krb5_init_creds_get_times:[[274,1,1,"c.krb5_init_creds_get_times","context"],[274,1,1,"c.krb5_init_creds_get_times","ctx"],[274,1,1,"c.krb5_init_creds_get_times","times"]],krb5_init_creds_init:[[275,1,1,"c.krb5_init_creds_init","client"],[275,1,1,"c.krb5_init_creds_init","context"],[275,1,1,"c.krb5_init_creds_init","ctx"],[275,1,1,"c.krb5_init_creds_init","data"],[275,1,1,"c.krb5_init_creds_init","options"],[275,1,1,"c.krb5_init_creds_init","prompter"],[275,1,1,"c.krb5_init_creds_init","start_time"]],krb5_init_creds_set_keytab:[[276,1,1,"c.krb5_init_creds_set_keytab","context"],[276,1,1,"c.krb5_init_creds_set_keytab","ctx"],[276,1,1,"c.krb5_init_creds_set_keytab","keytab"]],krb5_init_creds_set_password:[[277,1,1,"c.krb5_init_creds_set_password","context"],[277,1,1,"c.krb5_init_creds_set_password","ctx"],[277,1,1,"c.krb5_init_creds_set_password","password"]],krb5_init_creds_set_service:[[278,1,1,"c.krb5_init_creds_set_service","context"],[278,1,1,"c.krb5_init_creds_set_service","ctx"],[278,1,1,"c.krb5_init_creds_set_service","service"]],krb5_init_creds_step:[[279,1,1,"c.krb5_init_creds_step","context"],[279,1,1,"c.krb5_init_creds_step","ctx"],[279,1,1,"c.krb5_init_creds_step","flags"],[279,1,1,"c.krb5_init_creds_step","in"],[279,1,1,"c.krb5_init_creds_step","out"],[279,1,1,"c.krb5_init_creds_step","realm"]],krb5_init_keyblock:[[280,1,1,"c.krb5_init_keyblock","context"],[280,1,1,"c.krb5_init_keyblock","enctype"],[280,1,1,"c.krb5_init_keyblock","length"],[280,1,1,"c.krb5_init_keyblock","out"]],krb5_init_random_key:[[281,1,1,"c.krb5_init_random_key","context"],[281,1,1,"c.krb5_init_random_key","eblock"],[281,1,1,"c.krb5_init_random_key","keyblock"],[281,1,1,"c.krb5_init_random_key","ptr"]],krb5_init_secure_context:[[282,1,1,"c.krb5_init_secure_context","context"]],krb5_is_config_principal:[[283,1,1,"c.krb5_is_config_principal","context"],[283,1,1,"c.krb5_is_config_principal","principal"]],krb5_is_referral_realm:[[284,1,1,"c.krb5_is_referral_realm","r"]],krb5_is_thread_safe:[[285,1,1,"c.krb5_is_thread_safe","None"]],krb5_k_create_key:[[286,1,1,"c.krb5_k_create_key","context"],[286,1,1,"c.krb5_k_create_key","key_data"],[286,1,1,"c.krb5_k_create_key","out"]],krb5_k_decrypt:[[287,1,1,"c.krb5_k_decrypt","cipher_state"],[287,1,1,"c.krb5_k_decrypt","context"],[287,1,1,"c.krb5_k_decrypt","input"],[287,1,1,"c.krb5_k_decrypt","key"],[287,1,1,"c.krb5_k_decrypt","output"],[287,1,1,"c.krb5_k_decrypt","usage"]],krb5_k_decrypt_iov:[[288,1,1,"c.krb5_k_decrypt_iov","cipher_state"],[288,1,1,"c.krb5_k_decrypt_iov","context"],[288,1,1,"c.krb5_k_decrypt_iov","data"],[288,1,1,"c.krb5_k_decrypt_iov","key"],[288,1,1,"c.krb5_k_decrypt_iov","num_data"],[288,1,1,"c.krb5_k_decrypt_iov","usage"]],krb5_k_encrypt:[[289,1,1,"c.krb5_k_encrypt","cipher_state"],[289,1,1,"c.krb5_k_encrypt","context"],[289,1,1,"c.krb5_k_encrypt","input"],[289,1,1,"c.krb5_k_encrypt","key"],[289,1,1,"c.krb5_k_encrypt","output"],[289,1,1,"c.krb5_k_encrypt","usage"]],krb5_k_encrypt_iov:[[290,1,1,"c.krb5_k_encrypt_iov","cipher_state"],[290,1,1,"c.krb5_k_encrypt_iov","context"],[290,1,1,"c.krb5_k_encrypt_iov","data"],[290,1,1,"c.krb5_k_encrypt_iov","key"],[290,1,1,"c.krb5_k_encrypt_iov","num_data"],[290,1,1,"c.krb5_k_encrypt_iov","usage"]],krb5_k_free_key:[[291,1,1,"c.krb5_k_free_key","context"],[291,1,1,"c.krb5_k_free_key","key"]],krb5_k_key_enctype:[[292,1,1,"c.krb5_k_key_enctype","context"],[292,1,1,"c.krb5_k_key_enctype","key"]],krb5_k_key_keyblock:[[293,1,1,"c.krb5_k_key_keyblock","context"],[293,1,1,"c.krb5_k_key_keyblock","key"],[293,1,1,"c.krb5_k_key_keyblock","key_data"]],krb5_k_make_checksum:[[294,1,1,"c.krb5_k_make_checksum","cksum"],[294,1,1,"c.krb5_k_make_checksum","cksumtype"],[294,1,1,"c.krb5_k_make_checksum","context"],[294,1,1,"c.krb5_k_make_checksum","input"],[294,1,1,"c.krb5_k_make_checksum","key"],[294,1,1,"c.krb5_k_make_checksum","usage"]],krb5_k_make_checksum_iov:[[295,1,1,"c.krb5_k_make_checksum_iov","cksumtype"],[295,1,1,"c.krb5_k_make_checksum_iov","context"],[295,1,1,"c.krb5_k_make_checksum_iov","data"],[295,1,1,"c.krb5_k_make_checksum_iov","key"],[295,1,1,"c.krb5_k_make_checksum_iov","num_data"],[295,1,1,"c.krb5_k_make_checksum_iov","usage"]],krb5_k_prf:[[296,1,1,"c.krb5_k_prf","context"],[296,1,1,"c.krb5_k_prf","input"],[296,1,1,"c.krb5_k_prf","key"],[296,1,1,"c.krb5_k_prf","output"]],krb5_k_reference_key:[[297,1,1,"c.krb5_k_reference_key","context"],[297,1,1,"c.krb5_k_reference_key","key"]],krb5_k_verify_checksum:[[298,1,1,"c.krb5_k_verify_checksum","cksum"],[298,1,1,"c.krb5_k_verify_checksum","context"],[298,1,1,"c.krb5_k_verify_checksum","data"],[298,1,1,"c.krb5_k_verify_checksum","key"],[298,1,1,"c.krb5_k_verify_checksum","usage"],[298,1,1,"c.krb5_k_verify_checksum","valid"]],krb5_k_verify_checksum_iov:[[299,1,1,"c.krb5_k_verify_checksum_iov","cksumtype"],[299,1,1,"c.krb5_k_verify_checksum_iov","context"],[299,1,1,"c.krb5_k_verify_checksum_iov","data"],[299,1,1,"c.krb5_k_verify_checksum_iov","key"],[299,1,1,"c.krb5_k_verify_checksum_iov","num_data"],[299,1,1,"c.krb5_k_verify_checksum_iov","usage"],[299,1,1,"c.krb5_k_verify_checksum_iov","valid"]],krb5_kdc_rep:[[845,3,1,"c.krb5_kdc_rep.client","client"],[845,3,1,"c.krb5_kdc_rep.enc_part","enc_part"],[845,3,1,"c.krb5_kdc_rep.enc_part2","enc_part2"],[845,3,1,"c.krb5_kdc_rep.magic","magic"],[845,3,1,"c.krb5_kdc_rep.msg_type","msg_type"],[845,3,1,"c.krb5_kdc_rep.padata","padata"],[845,3,1,"c.krb5_kdc_rep.ticket","ticket"]],krb5_kdc_req:[[846,3,1,"c.krb5_kdc_req.addresses","addresses"],[846,3,1,"c.krb5_kdc_req.authorization_data","authorization_data"],[846,3,1,"c.krb5_kdc_req.client","client"],[846,3,1,"c.krb5_kdc_req.from","from"],[846,3,1,"c.krb5_kdc_req.kdc_options","kdc_options"],[846,3,1,"c.krb5_kdc_req.ktype","ktype"],[846,3,1,"c.krb5_kdc_req.magic","magic"],[846,3,1,"c.krb5_kdc_req.msg_type","msg_type"],[846,3,1,"c.krb5_kdc_req.nktypes","nktypes"],[846,3,1,"c.krb5_kdc_req.nonce","nonce"],[846,3,1,"c.krb5_kdc_req.padata","padata"],[846,3,1,"c.krb5_kdc_req.rtime","rtime"],[846,3,1,"c.krb5_kdc_req.second_ticket","second_ticket"],[846,3,1,"c.krb5_kdc_req.server","server"],[846,3,1,"c.krb5_kdc_req.till","till"],[846,3,1,"c.krb5_kdc_req.unenc_authdata","unenc_authdata"]],krb5_kdc_sign_ticket:[[300,1,1,"c.krb5_kdc_sign_ticket","client_princ"],[300,1,1,"c.krb5_kdc_sign_ticket","context"],[300,1,1,"c.krb5_kdc_sign_ticket","enc_tkt"],[300,1,1,"c.krb5_kdc_sign_ticket","pac"],[300,1,1,"c.krb5_kdc_sign_ticket","privsvr"],[300,1,1,"c.krb5_kdc_sign_ticket","server"],[300,1,1,"c.krb5_kdc_sign_ticket","server_princ"],[300,1,1,"c.krb5_kdc_sign_ticket","with_realm"]],krb5_kdc_verify_ticket:[[301,1,1,"c.krb5_kdc_verify_ticket","context"],[301,1,1,"c.krb5_kdc_verify_ticket","enc_tkt"],[301,1,1,"c.krb5_kdc_verify_ticket","pac_out"],[301,1,1,"c.krb5_kdc_verify_ticket","privsvr"],[301,1,1,"c.krb5_kdc_verify_ticket","server"],[301,1,1,"c.krb5_kdc_verify_ticket","server_princ"]],krb5_keyblock:[[848,3,1,"c.krb5_keyblock.contents","contents"],[848,3,1,"c.krb5_keyblock.enctype","enctype"],[848,3,1,"c.krb5_keyblock.length","length"],[848,3,1,"c.krb5_keyblock.magic","magic"]],krb5_keytab_entry:[[850,3,1,"c.krb5_keytab_entry.key","key"],[850,3,1,"c.krb5_keytab_entry.magic","magic"],[850,3,1,"c.krb5_keytab_entry.principal","principal"],[850,3,1,"c.krb5_keytab_entry.timestamp","timestamp"],[850,3,1,"c.krb5_keytab_entry.vno","vno"]],krb5_kt_add_entry:[[302,1,1,"c.krb5_kt_add_entry","context"],[302,1,1,"c.krb5_kt_add_entry","entry"],[302,1,1,"c.krb5_kt_add_entry","id"]],krb5_kt_client_default:[[303,1,1,"c.krb5_kt_client_default","context"],[303,1,1,"c.krb5_kt_client_default","keytab_out"]],krb5_kt_close:[[304,1,1,"c.krb5_kt_close","context"],[304,1,1,"c.krb5_kt_close","keytab"]],krb5_kt_default:[[305,1,1,"c.krb5_kt_default","context"],[305,1,1,"c.krb5_kt_default","id"]],krb5_kt_default_name:[[306,1,1,"c.krb5_kt_default_name","context"],[306,1,1,"c.krb5_kt_default_name","name"],[306,1,1,"c.krb5_kt_default_name","name_size"]],krb5_kt_dup:[[307,1,1,"c.krb5_kt_dup","context"],[307,1,1,"c.krb5_kt_dup","in"],[307,1,1,"c.krb5_kt_dup","out"]],krb5_kt_end_seq_get:[[308,1,1,"c.krb5_kt_end_seq_get","context"],[308,1,1,"c.krb5_kt_end_seq_get","cursor"],[308,1,1,"c.krb5_kt_end_seq_get","keytab"]],krb5_kt_free_entry:[[309,1,1,"c.krb5_kt_free_entry","context"],[309,1,1,"c.krb5_kt_free_entry","entry"]],krb5_kt_get_entry:[[310,1,1,"c.krb5_kt_get_entry","context"],[310,1,1,"c.krb5_kt_get_entry","enctype"],[310,1,1,"c.krb5_kt_get_entry","entry"],[310,1,1,"c.krb5_kt_get_entry","keytab"],[310,1,1,"c.krb5_kt_get_entry","principal"],[310,1,1,"c.krb5_kt_get_entry","vno"]],krb5_kt_get_name:[[311,1,1,"c.krb5_kt_get_name","context"],[311,1,1,"c.krb5_kt_get_name","keytab"],[311,1,1,"c.krb5_kt_get_name","name"],[311,1,1,"c.krb5_kt_get_name","namelen"]],krb5_kt_get_type:[[312,1,1,"c.krb5_kt_get_type","context"],[312,1,1,"c.krb5_kt_get_type","keytab"]],krb5_kt_have_content:[[313,1,1,"c.krb5_kt_have_content","context"],[313,1,1,"c.krb5_kt_have_content","keytab"]],krb5_kt_next_entry:[[314,1,1,"c.krb5_kt_next_entry","context"],[314,1,1,"c.krb5_kt_next_entry","cursor"],[314,1,1,"c.krb5_kt_next_entry","entry"],[314,1,1,"c.krb5_kt_next_entry","keytab"]],krb5_kt_read_service_key:[[315,1,1,"c.krb5_kt_read_service_key","context"],[315,1,1,"c.krb5_kt_read_service_key","enctype"],[315,1,1,"c.krb5_kt_read_service_key","key"],[315,1,1,"c.krb5_kt_read_service_key","keyprocarg"],[315,1,1,"c.krb5_kt_read_service_key","principal"],[315,1,1,"c.krb5_kt_read_service_key","vno"]],krb5_kt_remove_entry:[[316,1,1,"c.krb5_kt_remove_entry","context"],[316,1,1,"c.krb5_kt_remove_entry","entry"],[316,1,1,"c.krb5_kt_remove_entry","id"]],krb5_kt_resolve:[[317,1,1,"c.krb5_kt_resolve","context"],[317,1,1,"c.krb5_kt_resolve","ktid"],[317,1,1,"c.krb5_kt_resolve","name"]],krb5_kt_start_seq_get:[[318,1,1,"c.krb5_kt_start_seq_get","context"],[318,1,1,"c.krb5_kt_start_seq_get","cursor"],[318,1,1,"c.krb5_kt_start_seq_get","keytab"]],krb5_kuserok:[[319,1,1,"c.krb5_kuserok","context"],[319,1,1,"c.krb5_kuserok","luser"],[319,1,1,"c.krb5_kuserok","principal"]],krb5_last_req_entry:[[854,3,1,"c.krb5_last_req_entry.lr_type","lr_type"],[854,3,1,"c.krb5_last_req_entry.magic","magic"],[854,3,1,"c.krb5_last_req_entry.value","value"]],krb5_make_authdata_kdc_issued:[[320,1,1,"c.krb5_make_authdata_kdc_issued","ad_kdcissued"],[320,1,1,"c.krb5_make_authdata_kdc_issued","authdata"],[320,1,1,"c.krb5_make_authdata_kdc_issued","context"],[320,1,1,"c.krb5_make_authdata_kdc_issued","issuer"],[320,1,1,"c.krb5_make_authdata_kdc_issued","key"]],krb5_marshal_credentials:[[321,1,1,"c.krb5_marshal_credentials","context"],[321,1,1,"c.krb5_marshal_credentials","data_out"],[321,1,1,"c.krb5_marshal_credentials","in_creds"]],krb5_merge_authdata:[[322,1,1,"c.krb5_merge_authdata","context"],[322,1,1,"c.krb5_merge_authdata","inauthdat1"],[322,1,1,"c.krb5_merge_authdata","inauthdat2"],[322,1,1,"c.krb5_merge_authdata","outauthdat"]],krb5_mk_1cred:[[323,1,1,"c.krb5_mk_1cred","auth_context"],[323,1,1,"c.krb5_mk_1cred","context"],[323,1,1,"c.krb5_mk_1cred","creds"],[323,1,1,"c.krb5_mk_1cred","der_out"],[323,1,1,"c.krb5_mk_1cred","rdata_out"]],krb5_mk_error:[[324,1,1,"c.krb5_mk_error","context"],[324,1,1,"c.krb5_mk_error","dec_err"],[324,1,1,"c.krb5_mk_error","enc_err"]],krb5_mk_ncred:[[325,1,1,"c.krb5_mk_ncred","auth_context"],[325,1,1,"c.krb5_mk_ncred","context"],[325,1,1,"c.krb5_mk_ncred","creds"],[325,1,1,"c.krb5_mk_ncred","der_out"],[325,1,1,"c.krb5_mk_ncred","rdata_out"]],krb5_mk_priv:[[326,1,1,"c.krb5_mk_priv","auth_context"],[326,1,1,"c.krb5_mk_priv","context"],[326,1,1,"c.krb5_mk_priv","der_out"],[326,1,1,"c.krb5_mk_priv","rdata_out"],[326,1,1,"c.krb5_mk_priv","userdata"]],krb5_mk_rep:[[327,1,1,"c.krb5_mk_rep","auth_context"],[327,1,1,"c.krb5_mk_rep","context"],[327,1,1,"c.krb5_mk_rep","outbuf"]],krb5_mk_rep_dce:[[328,1,1,"c.krb5_mk_rep_dce","auth_context"],[328,1,1,"c.krb5_mk_rep_dce","context"],[328,1,1,"c.krb5_mk_rep_dce","outbuf"]],krb5_mk_req:[[329,1,1,"c.krb5_mk_req","ap_req_options"],[329,1,1,"c.krb5_mk_req","auth_context"],[329,1,1,"c.krb5_mk_req","ccache"],[329,1,1,"c.krb5_mk_req","context"],[329,1,1,"c.krb5_mk_req","hostname"],[329,1,1,"c.krb5_mk_req","in_data"],[329,1,1,"c.krb5_mk_req","outbuf"],[329,1,1,"c.krb5_mk_req","service"]],krb5_mk_req_extended:[[330,1,1,"c.krb5_mk_req_extended","ap_req_options"],[330,1,1,"c.krb5_mk_req_extended","auth_context"],[330,1,1,"c.krb5_mk_req_extended","context"],[330,1,1,"c.krb5_mk_req_extended","in_creds"],[330,1,1,"c.krb5_mk_req_extended","in_data"],[330,1,1,"c.krb5_mk_req_extended","outbuf"]],krb5_mk_safe:[[331,1,1,"c.krb5_mk_safe","auth_context"],[331,1,1,"c.krb5_mk_safe","context"],[331,1,1,"c.krb5_mk_safe","der_out"],[331,1,1,"c.krb5_mk_safe","rdata_out"],[331,1,1,"c.krb5_mk_safe","userdata"]],krb5_os_localaddr:[[332,1,1,"c.krb5_os_localaddr","addr"],[332,1,1,"c.krb5_os_localaddr","context"]],krb5_pa_data:[[859,3,1,"c.krb5_pa_data.contents","contents"],[859,3,1,"c.krb5_pa_data.length","length"],[859,3,1,"c.krb5_pa_data.magic","magic"],[859,3,1,"c.krb5_pa_data.pa_type","pa_type"]],krb5_pa_pac_req:[[860,3,1,"c.krb5_pa_pac_req.include_pac","include_pac"]],krb5_pa_server_referral_data:[[861,3,1,"c.krb5_pa_server_referral_data.referral_valid_until","referral_valid_until"],[861,3,1,"c.krb5_pa_server_referral_data.referred_realm","referred_realm"],[861,3,1,"c.krb5_pa_server_referral_data.rep_cksum","rep_cksum"],[861,3,1,"c.krb5_pa_server_referral_data.requested_principal_name","requested_principal_name"],[861,3,1,"c.krb5_pa_server_referral_data.true_principal_name","true_principal_name"]],krb5_pa_svr_referral_data:[[862,3,1,"c.krb5_pa_svr_referral_data.principal","principal"]],krb5_pac_add_buffer:[[333,1,1,"c.krb5_pac_add_buffer","context"],[333,1,1,"c.krb5_pac_add_buffer","data"],[333,1,1,"c.krb5_pac_add_buffer","pac"],[333,1,1,"c.krb5_pac_add_buffer","type"]],krb5_pac_free:[[334,1,1,"c.krb5_pac_free","context"],[334,1,1,"c.krb5_pac_free","pac"]],krb5_pac_get_buffer:[[335,1,1,"c.krb5_pac_get_buffer","context"],[335,1,1,"c.krb5_pac_get_buffer","data"],[335,1,1,"c.krb5_pac_get_buffer","pac"],[335,1,1,"c.krb5_pac_get_buffer","type"]],krb5_pac_get_client_info:[[336,1,1,"c.krb5_pac_get_client_info","authtime_out"],[336,1,1,"c.krb5_pac_get_client_info","context"],[336,1,1,"c.krb5_pac_get_client_info","pac"],[336,1,1,"c.krb5_pac_get_client_info","princname_out"]],krb5_pac_get_types:[[337,1,1,"c.krb5_pac_get_types","context"],[337,1,1,"c.krb5_pac_get_types","len"],[337,1,1,"c.krb5_pac_get_types","pac"],[337,1,1,"c.krb5_pac_get_types","types"]],krb5_pac_init:[[338,1,1,"c.krb5_pac_init","context"],[338,1,1,"c.krb5_pac_init","pac"]],krb5_pac_parse:[[339,1,1,"c.krb5_pac_parse","context"],[339,1,1,"c.krb5_pac_parse","len"],[339,1,1,"c.krb5_pac_parse","pac"],[339,1,1,"c.krb5_pac_parse","ptr"]],krb5_pac_sign:[[340,1,1,"c.krb5_pac_sign","authtime"],[340,1,1,"c.krb5_pac_sign","context"],[340,1,1,"c.krb5_pac_sign","data"],[340,1,1,"c.krb5_pac_sign","pac"],[340,1,1,"c.krb5_pac_sign","principal"],[340,1,1,"c.krb5_pac_sign","privsvr_key"],[340,1,1,"c.krb5_pac_sign","server_key"]],krb5_pac_sign_ext:[[341,1,1,"c.krb5_pac_sign_ext","authtime"],[341,1,1,"c.krb5_pac_sign_ext","context"],[341,1,1,"c.krb5_pac_sign_ext","data"],[341,1,1,"c.krb5_pac_sign_ext","pac"],[341,1,1,"c.krb5_pac_sign_ext","principal"],[341,1,1,"c.krb5_pac_sign_ext","privsvr_key"],[341,1,1,"c.krb5_pac_sign_ext","server_key"],[341,1,1,"c.krb5_pac_sign_ext","with_realm"]],krb5_pac_verify:[[342,1,1,"c.krb5_pac_verify","authtime"],[342,1,1,"c.krb5_pac_verify","context"],[342,1,1,"c.krb5_pac_verify","pac"],[342,1,1,"c.krb5_pac_verify","principal"],[342,1,1,"c.krb5_pac_verify","privsvr"],[342,1,1,"c.krb5_pac_verify","server"]],krb5_pac_verify_ext:[[343,1,1,"c.krb5_pac_verify_ext","authtime"],[343,1,1,"c.krb5_pac_verify_ext","context"],[343,1,1,"c.krb5_pac_verify_ext","pac"],[343,1,1,"c.krb5_pac_verify_ext","principal"],[343,1,1,"c.krb5_pac_verify_ext","privsvr"],[343,1,1,"c.krb5_pac_verify_ext","server"],[343,1,1,"c.krb5_pac_verify_ext","with_realm"]],krb5_parse_name:[[344,1,1,"c.krb5_parse_name","context"],[344,1,1,"c.krb5_parse_name","name"],[344,1,1,"c.krb5_parse_name","principal_out"]],krb5_parse_name_flags:[[345,1,1,"c.krb5_parse_name_flags","context"],[345,1,1,"c.krb5_parse_name_flags","flags"],[345,1,1,"c.krb5_parse_name_flags","name"],[345,1,1,"c.krb5_parse_name_flags","principal_out"]],krb5_prepend_error_message:[[346,1,1,"c.krb5_prepend_error_message","code"],[346,1,1,"c.krb5_prepend_error_message","ctx"],[346,1,1,"c.krb5_prepend_error_message","fmt"]],krb5_principal2salt:[[347,1,1,"c.krb5_principal2salt","context"],[347,1,1,"c.krb5_principal2salt","pr"],[347,1,1,"c.krb5_principal2salt","ret"]],krb5_principal:[[868,3,1,"c.krb5_principal.data","data"],[868,3,1,"c.krb5_principal.length","length"],[868,3,1,"c.krb5_principal.magic","magic"],[868,3,1,"c.krb5_principal.realm","realm"],[868,3,1,"c.krb5_principal.type","type"]],krb5_principal_compare:[[348,1,1,"c.krb5_principal_compare","context"],[348,1,1,"c.krb5_principal_compare","princ1"],[348,1,1,"c.krb5_principal_compare","princ2"]],krb5_principal_compare_any_realm:[[349,1,1,"c.krb5_principal_compare_any_realm","context"],[349,1,1,"c.krb5_principal_compare_any_realm","princ1"],[349,1,1,"c.krb5_principal_compare_any_realm","princ2"]],krb5_principal_compare_flags:[[350,1,1,"c.krb5_principal_compare_flags","context"],[350,1,1,"c.krb5_principal_compare_flags","flags"],[350,1,1,"c.krb5_principal_compare_flags","princ1"],[350,1,1,"c.krb5_principal_compare_flags","princ2"]],krb5_principal_data:[[869,3,1,"c.krb5_principal_data.data","data"],[869,3,1,"c.krb5_principal_data.length","length"],[869,3,1,"c.krb5_principal_data.magic","magic"],[869,3,1,"c.krb5_principal_data.realm","realm"],[869,3,1,"c.krb5_principal_data.type","type"]],krb5_process_key:[[351,1,1,"c.krb5_process_key","context"],[351,1,1,"c.krb5_process_key","eblock"],[351,1,1,"c.krb5_process_key","key"]],krb5_prompt:[[870,3,1,"c.krb5_prompt.hidden","hidden"],[870,3,1,"c.krb5_prompt.prompt","prompt"],[870,3,1,"c.krb5_prompt.reply","reply"]],krb5_prompter_posix:[[352,1,1,"c.krb5_prompter_posix","banner"],[352,1,1,"c.krb5_prompter_posix","context"],[352,1,1,"c.krb5_prompter_posix","data"],[352,1,1,"c.krb5_prompter_posix","name"],[352,1,1,"c.krb5_prompter_posix","num_prompts"],[352,1,1,"c.krb5_prompter_posix","prompts"]],krb5_pwd_data:[[873,3,1,"c.krb5_pwd_data.element","element"],[873,3,1,"c.krb5_pwd_data.magic","magic"],[873,3,1,"c.krb5_pwd_data.sequence_count","sequence_count"]],krb5_random_key:[[353,1,1,"c.krb5_random_key","context"],[353,1,1,"c.krb5_random_key","eblock"],[353,1,1,"c.krb5_random_key","keyblock"],[353,1,1,"c.krb5_random_key","ptr"]],krb5_rd_cred:[[354,1,1,"c.krb5_rd_cred","auth_context"],[354,1,1,"c.krb5_rd_cred","context"],[354,1,1,"c.krb5_rd_cred","creddata"],[354,1,1,"c.krb5_rd_cred","creds_out"],[354,1,1,"c.krb5_rd_cred","rdata_out"]],krb5_rd_error:[[355,1,1,"c.krb5_rd_error","context"],[355,1,1,"c.krb5_rd_error","dec_error"],[355,1,1,"c.krb5_rd_error","enc_errbuf"]],krb5_rd_priv:[[356,1,1,"c.krb5_rd_priv","auth_context"],[356,1,1,"c.krb5_rd_priv","context"],[356,1,1,"c.krb5_rd_priv","inbuf"],[356,1,1,"c.krb5_rd_priv","rdata_out"],[356,1,1,"c.krb5_rd_priv","userdata_out"]],krb5_rd_rep:[[357,1,1,"c.krb5_rd_rep","auth_context"],[357,1,1,"c.krb5_rd_rep","context"],[357,1,1,"c.krb5_rd_rep","inbuf"],[357,1,1,"c.krb5_rd_rep","repl"]],krb5_rd_rep_dce:[[358,1,1,"c.krb5_rd_rep_dce","auth_context"],[358,1,1,"c.krb5_rd_rep_dce","context"],[358,1,1,"c.krb5_rd_rep_dce","inbuf"],[358,1,1,"c.krb5_rd_rep_dce","nonce"]],krb5_rd_req:[[359,1,1,"c.krb5_rd_req","ap_req_options"],[359,1,1,"c.krb5_rd_req","auth_context"],[359,1,1,"c.krb5_rd_req","context"],[359,1,1,"c.krb5_rd_req","inbuf"],[359,1,1,"c.krb5_rd_req","keytab"],[359,1,1,"c.krb5_rd_req","server"],[359,1,1,"c.krb5_rd_req","ticket"]],krb5_rd_safe:[[360,1,1,"c.krb5_rd_safe","auth_context"],[360,1,1,"c.krb5_rd_safe","context"],[360,1,1,"c.krb5_rd_safe","inbuf"],[360,1,1,"c.krb5_rd_safe","rdata_out"],[360,1,1,"c.krb5_rd_safe","userdata_out"]],krb5_read_password:[[361,1,1,"c.krb5_read_password","context"],[361,1,1,"c.krb5_read_password","prompt"],[361,1,1,"c.krb5_read_password","prompt2"],[361,1,1,"c.krb5_read_password","return_pwd"],[361,1,1,"c.krb5_read_password","size_return"]],krb5_realm_compare:[[362,1,1,"c.krb5_realm_compare","context"],[362,1,1,"c.krb5_realm_compare","princ1"],[362,1,1,"c.krb5_realm_compare","princ2"]],krb5_recvauth:[[363,1,1,"c.krb5_recvauth","appl_version"],[363,1,1,"c.krb5_recvauth","auth_context"],[363,1,1,"c.krb5_recvauth","context"],[363,1,1,"c.krb5_recvauth","fd"],[363,1,1,"c.krb5_recvauth","flags"],[363,1,1,"c.krb5_recvauth","keytab"],[363,1,1,"c.krb5_recvauth","server"],[363,1,1,"c.krb5_recvauth","ticket"]],krb5_recvauth_version:[[364,1,1,"c.krb5_recvauth_version","auth_context"],[364,1,1,"c.krb5_recvauth_version","context"],[364,1,1,"c.krb5_recvauth_version","fd"],[364,1,1,"c.krb5_recvauth_version","flags"],[364,1,1,"c.krb5_recvauth_version","keytab"],[364,1,1,"c.krb5_recvauth_version","server"],[364,1,1,"c.krb5_recvauth_version","ticket"],[364,1,1,"c.krb5_recvauth_version","version"]],krb5_replay_data:[[875,3,1,"c.krb5_replay_data.seq","seq"],[875,3,1,"c.krb5_replay_data.timestamp","timestamp"],[875,3,1,"c.krb5_replay_data.usec","usec"]],krb5_responder_get_challenge:[[365,1,1,"c.krb5_responder_get_challenge","ctx"],[365,1,1,"c.krb5_responder_get_challenge","question"],[365,1,1,"c.krb5_responder_get_challenge","rctx"]],krb5_responder_list_questions:[[366,1,1,"c.krb5_responder_list_questions","ctx"],[366,1,1,"c.krb5_responder_list_questions","rctx"]],krb5_responder_otp_challenge:[[878,3,1,"c.krb5_responder_otp_challenge.service","service"],[878,3,1,"c.krb5_responder_otp_challenge.tokeninfo","tokeninfo"]],krb5_responder_otp_challenge_free:[[367,1,1,"c.krb5_responder_otp_challenge_free","chl"],[367,1,1,"c.krb5_responder_otp_challenge_free","ctx"],[367,1,1,"c.krb5_responder_otp_challenge_free","rctx"]],krb5_responder_otp_get_challenge:[[368,1,1,"c.krb5_responder_otp_get_challenge","chl"],[368,1,1,"c.krb5_responder_otp_get_challenge","ctx"],[368,1,1,"c.krb5_responder_otp_get_challenge","rctx"]],krb5_responder_otp_set_answer:[[369,1,1,"c.krb5_responder_otp_set_answer","ctx"],[369,1,1,"c.krb5_responder_otp_set_answer","pin"],[369,1,1,"c.krb5_responder_otp_set_answer","rctx"],[369,1,1,"c.krb5_responder_otp_set_answer","ti"],[369,1,1,"c.krb5_responder_otp_set_answer","value"]],krb5_responder_otp_tokeninfo:[[879,3,1,"c.krb5_responder_otp_tokeninfo.alg_id","alg_id"],[879,3,1,"c.krb5_responder_otp_tokeninfo.challenge","challenge"],[879,3,1,"c.krb5_responder_otp_tokeninfo.flags","flags"],[879,3,1,"c.krb5_responder_otp_tokeninfo.format","format"],[879,3,1,"c.krb5_responder_otp_tokeninfo.length","length"],[879,3,1,"c.krb5_responder_otp_tokeninfo.token_id","token_id"],[879,3,1,"c.krb5_responder_otp_tokeninfo.vendor","vendor"]],krb5_responder_pkinit_challenge:[[880,3,1,"c.krb5_responder_pkinit_challenge.identities","identities"]],krb5_responder_pkinit_challenge_free:[[370,1,1,"c.krb5_responder_pkinit_challenge_free","chl"],[370,1,1,"c.krb5_responder_pkinit_challenge_free","ctx"],[370,1,1,"c.krb5_responder_pkinit_challenge_free","rctx"]],krb5_responder_pkinit_get_challenge:[[371,1,1,"c.krb5_responder_pkinit_get_challenge","chl_out"],[371,1,1,"c.krb5_responder_pkinit_get_challenge","ctx"],[371,1,1,"c.krb5_responder_pkinit_get_challenge","rctx"]],krb5_responder_pkinit_identity:[[881,3,1,"c.krb5_responder_pkinit_identity.identity","identity"],[881,3,1,"c.krb5_responder_pkinit_identity.token_flags","token_flags"]],krb5_responder_pkinit_set_answer:[[372,1,1,"c.krb5_responder_pkinit_set_answer","ctx"],[372,1,1,"c.krb5_responder_pkinit_set_answer","identity"],[372,1,1,"c.krb5_responder_pkinit_set_answer","pin"],[372,1,1,"c.krb5_responder_pkinit_set_answer","rctx"]],krb5_responder_set_answer:[[373,1,1,"c.krb5_responder_set_answer","answer"],[373,1,1,"c.krb5_responder_set_answer","ctx"],[373,1,1,"c.krb5_responder_set_answer","question"],[373,1,1,"c.krb5_responder_set_answer","rctx"]],krb5_response:[[882,3,1,"c.krb5_response.expected_nonce","expected_nonce"],[882,3,1,"c.krb5_response.magic","magic"],[882,3,1,"c.krb5_response.message_type","message_type"],[882,3,1,"c.krb5_response.request_time","request_time"],[882,3,1,"c.krb5_response.response","response"]],krb5_salttype_to_string:[[374,1,1,"c.krb5_salttype_to_string","buffer"],[374,1,1,"c.krb5_salttype_to_string","buflen"],[374,1,1,"c.krb5_salttype_to_string","salttype"]],krb5_sendauth:[[375,1,1,"c.krb5_sendauth","ap_req_options"],[375,1,1,"c.krb5_sendauth","appl_version"],[375,1,1,"c.krb5_sendauth","auth_context"],[375,1,1,"c.krb5_sendauth","ccache"],[375,1,1,"c.krb5_sendauth","client"],[375,1,1,"c.krb5_sendauth","context"],[375,1,1,"c.krb5_sendauth","error"],[375,1,1,"c.krb5_sendauth","fd"],[375,1,1,"c.krb5_sendauth","in_creds"],[375,1,1,"c.krb5_sendauth","in_data"],[375,1,1,"c.krb5_sendauth","out_creds"],[375,1,1,"c.krb5_sendauth","rep_result"],[375,1,1,"c.krb5_sendauth","server"]],krb5_server_decrypt_ticket_keytab:[[376,1,1,"c.krb5_server_decrypt_ticket_keytab","context"],[376,1,1,"c.krb5_server_decrypt_ticket_keytab","kt"],[376,1,1,"c.krb5_server_decrypt_ticket_keytab","ticket"]],krb5_set_default_realm:[[377,1,1,"c.krb5_set_default_realm","context"],[377,1,1,"c.krb5_set_default_realm","lrealm"]],krb5_set_default_tgs_enctypes:[[378,1,1,"c.krb5_set_default_tgs_enctypes","context"],[378,1,1,"c.krb5_set_default_tgs_enctypes","etypes"]],krb5_set_error_message:[[379,1,1,"c.krb5_set_error_message","code"],[379,1,1,"c.krb5_set_error_message","ctx"],[379,1,1,"c.krb5_set_error_message","fmt"]],krb5_set_kdc_recv_hook:[[380,1,1,"c.krb5_set_kdc_recv_hook","context"],[380,1,1,"c.krb5_set_kdc_recv_hook","data"],[380,1,1,"c.krb5_set_kdc_recv_hook","recv_hook"]],krb5_set_kdc_send_hook:[[381,1,1,"c.krb5_set_kdc_send_hook","context"],[381,1,1,"c.krb5_set_kdc_send_hook","data"],[381,1,1,"c.krb5_set_kdc_send_hook","send_hook"]],krb5_set_password:[[382,1,1,"c.krb5_set_password","change_password_for"],[382,1,1,"c.krb5_set_password","context"],[382,1,1,"c.krb5_set_password","creds"],[382,1,1,"c.krb5_set_password","newpw"],[382,1,1,"c.krb5_set_password","result_code"],[382,1,1,"c.krb5_set_password","result_code_string"],[382,1,1,"c.krb5_set_password","result_string"]],krb5_set_password_using_ccache:[[383,1,1,"c.krb5_set_password_using_ccache","ccache"],[383,1,1,"c.krb5_set_password_using_ccache","change_password_for"],[383,1,1,"c.krb5_set_password_using_ccache","context"],[383,1,1,"c.krb5_set_password_using_ccache","newpw"],[383,1,1,"c.krb5_set_password_using_ccache","result_code"],[383,1,1,"c.krb5_set_password_using_ccache","result_code_string"],[383,1,1,"c.krb5_set_password_using_ccache","result_string"]],krb5_set_principal_realm:[[384,1,1,"c.krb5_set_principal_realm","context"],[384,1,1,"c.krb5_set_principal_realm","principal"],[384,1,1,"c.krb5_set_principal_realm","realm"]],krb5_set_real_time:[[385,1,1,"c.krb5_set_real_time","context"],[385,1,1,"c.krb5_set_real_time","microseconds"],[385,1,1,"c.krb5_set_real_time","seconds"]],krb5_set_trace_callback:[[386,1,1,"c.krb5_set_trace_callback","cb_data"],[386,1,1,"c.krb5_set_trace_callback","context"],[386,1,1,"c.krb5_set_trace_callback","fn"]],krb5_set_trace_filename:[[387,1,1,"c.krb5_set_trace_filename","context"],[387,1,1,"c.krb5_set_trace_filename","filename"]],krb5_sname_match:[[388,1,1,"c.krb5_sname_match","context"],[388,1,1,"c.krb5_sname_match","matching"],[388,1,1,"c.krb5_sname_match","princ"]],krb5_sname_to_principal:[[389,1,1,"c.krb5_sname_to_principal","context"],[389,1,1,"c.krb5_sname_to_principal","hostname"],[389,1,1,"c.krb5_sname_to_principal","ret_princ"],[389,1,1,"c.krb5_sname_to_principal","sname"],[389,1,1,"c.krb5_sname_to_principal","type"]],krb5_string_to_cksumtype:[[390,1,1,"c.krb5_string_to_cksumtype","cksumtypep"],[390,1,1,"c.krb5_string_to_cksumtype","string"]],krb5_string_to_deltat:[[391,1,1,"c.krb5_string_to_deltat","deltatp"],[391,1,1,"c.krb5_string_to_deltat","string"]],krb5_string_to_enctype:[[392,1,1,"c.krb5_string_to_enctype","enctypep"],[392,1,1,"c.krb5_string_to_enctype","string"]],krb5_string_to_key:[[393,1,1,"c.krb5_string_to_key","context"],[393,1,1,"c.krb5_string_to_key","data"],[393,1,1,"c.krb5_string_to_key","eblock"],[393,1,1,"c.krb5_string_to_key","keyblock"],[393,1,1,"c.krb5_string_to_key","salt"]],krb5_string_to_salttype:[[394,1,1,"c.krb5_string_to_salttype","salttypep"],[394,1,1,"c.krb5_string_to_salttype","string"]],krb5_string_to_timestamp:[[395,1,1,"c.krb5_string_to_timestamp","string"],[395,1,1,"c.krb5_string_to_timestamp","timestampp"]],krb5_ticket:[[883,3,1,"c.krb5_ticket.enc_part","enc_part"],[883,3,1,"c.krb5_ticket.enc_part2","enc_part2"],[883,3,1,"c.krb5_ticket.magic","magic"],[883,3,1,"c.krb5_ticket.server","server"]],krb5_ticket_times:[[884,3,1,"c.krb5_ticket_times.authtime","authtime"],[884,3,1,"c.krb5_ticket_times.endtime","endtime"],[884,3,1,"c.krb5_ticket_times.renew_till","renew_till"],[884,3,1,"c.krb5_ticket_times.starttime","starttime"]],krb5_timeofday:[[396,1,1,"c.krb5_timeofday","context"],[396,1,1,"c.krb5_timeofday","timeret"]],krb5_timestamp_to_sfstring:[[397,1,1,"c.krb5_timestamp_to_sfstring","buffer"],[397,1,1,"c.krb5_timestamp_to_sfstring","buflen"],[397,1,1,"c.krb5_timestamp_to_sfstring","pad"],[397,1,1,"c.krb5_timestamp_to_sfstring","timestamp"]],krb5_timestamp_to_string:[[398,1,1,"c.krb5_timestamp_to_string","buffer"],[398,1,1,"c.krb5_timestamp_to_string","buflen"],[398,1,1,"c.krb5_timestamp_to_string","timestamp"]],krb5_tkt_authent:[[886,3,1,"c.krb5_tkt_authent.ap_options","ap_options"],[886,3,1,"c.krb5_tkt_authent.authenticator","authenticator"],[886,3,1,"c.krb5_tkt_authent.magic","magic"],[886,3,1,"c.krb5_tkt_authent.ticket","ticket"]],krb5_tkt_creds_free:[[399,1,1,"c.krb5_tkt_creds_free","context"],[399,1,1,"c.krb5_tkt_creds_free","ctx"]],krb5_tkt_creds_get:[[400,1,1,"c.krb5_tkt_creds_get","context"],[400,1,1,"c.krb5_tkt_creds_get","ctx"]],krb5_tkt_creds_get_creds:[[401,1,1,"c.krb5_tkt_creds_get_creds","context"],[401,1,1,"c.krb5_tkt_creds_get_creds","creds"],[401,1,1,"c.krb5_tkt_creds_get_creds","ctx"]],krb5_tkt_creds_get_times:[[402,1,1,"c.krb5_tkt_creds_get_times","context"],[402,1,1,"c.krb5_tkt_creds_get_times","ctx"],[402,1,1,"c.krb5_tkt_creds_get_times","times"]],krb5_tkt_creds_init:[[403,1,1,"c.krb5_tkt_creds_init","ccache"],[403,1,1,"c.krb5_tkt_creds_init","context"],[403,1,1,"c.krb5_tkt_creds_init","creds"],[403,1,1,"c.krb5_tkt_creds_init","ctx"],[403,1,1,"c.krb5_tkt_creds_init","options"]],krb5_tkt_creds_step:[[404,1,1,"c.krb5_tkt_creds_step","context"],[404,1,1,"c.krb5_tkt_creds_step","ctx"],[404,1,1,"c.krb5_tkt_creds_step","flags"],[404,1,1,"c.krb5_tkt_creds_step","in"],[404,1,1,"c.krb5_tkt_creds_step","out"],[404,1,1,"c.krb5_tkt_creds_step","realm"]],krb5_trace_info:[[889,3,1,"c.krb5_trace_info.message","message"]],krb5_transited:[[890,3,1,"c.krb5_transited.magic","magic"],[890,3,1,"c.krb5_transited.tr_contents","tr_contents"],[890,3,1,"c.krb5_transited.tr_type","tr_type"]],krb5_typed_data:[[891,3,1,"c.krb5_typed_data.data","data"],[891,3,1,"c.krb5_typed_data.length","length"],[891,3,1,"c.krb5_typed_data.magic","magic"],[891,3,1,"c.krb5_typed_data.type","type"]],krb5_unmarshal_credentials:[[405,1,1,"c.krb5_unmarshal_credentials","context"],[405,1,1,"c.krb5_unmarshal_credentials","creds_out"],[405,1,1,"c.krb5_unmarshal_credentials","data"]],krb5_unparse_name:[[406,1,1,"c.krb5_unparse_name","context"],[406,1,1,"c.krb5_unparse_name","name"],[406,1,1,"c.krb5_unparse_name","principal"]],krb5_unparse_name_ext:[[407,1,1,"c.krb5_unparse_name_ext","context"],[407,1,1,"c.krb5_unparse_name_ext","name"],[407,1,1,"c.krb5_unparse_name_ext","principal"],[407,1,1,"c.krb5_unparse_name_ext","size"]],krb5_unparse_name_flags:[[408,1,1,"c.krb5_unparse_name_flags","context"],[408,1,1,"c.krb5_unparse_name_flags","flags"],[408,1,1,"c.krb5_unparse_name_flags","name"],[408,1,1,"c.krb5_unparse_name_flags","principal"]],krb5_unparse_name_flags_ext:[[409,1,1,"c.krb5_unparse_name_flags_ext","context"],[409,1,1,"c.krb5_unparse_name_flags_ext","flags"],[409,1,1,"c.krb5_unparse_name_flags_ext","name"],[409,1,1,"c.krb5_unparse_name_flags_ext","principal"],[409,1,1,"c.krb5_unparse_name_flags_ext","size"]],krb5_us_timeofday:[[410,1,1,"c.krb5_us_timeofday","context"],[410,1,1,"c.krb5_us_timeofday","microseconds"],[410,1,1,"c.krb5_us_timeofday","seconds"]],krb5_use_enctype:[[411,1,1,"c.krb5_use_enctype","context"],[411,1,1,"c.krb5_use_enctype","eblock"],[411,1,1,"c.krb5_use_enctype","enctype"]],krb5_verify_authdata_kdc_issued:[[412,1,1,"c.krb5_verify_authdata_kdc_issued","ad_kdcissued"],[412,1,1,"c.krb5_verify_authdata_kdc_issued","authdata"],[412,1,1,"c.krb5_verify_authdata_kdc_issued","context"],[412,1,1,"c.krb5_verify_authdata_kdc_issued","issuer"],[412,1,1,"c.krb5_verify_authdata_kdc_issued","key"]],krb5_verify_checksum:[[413,1,1,"c.krb5_verify_checksum","cksum"],[413,1,1,"c.krb5_verify_checksum","context"],[413,1,1,"c.krb5_verify_checksum","ctype"],[413,1,1,"c.krb5_verify_checksum","in"],[413,1,1,"c.krb5_verify_checksum","in_length"],[413,1,1,"c.krb5_verify_checksum","seed"],[413,1,1,"c.krb5_verify_checksum","seed_length"]],krb5_verify_init_creds:[[414,1,1,"c.krb5_verify_init_creds","ccache"],[414,1,1,"c.krb5_verify_init_creds","context"],[414,1,1,"c.krb5_verify_init_creds","creds"],[414,1,1,"c.krb5_verify_init_creds","keytab"],[414,1,1,"c.krb5_verify_init_creds","options"],[414,1,1,"c.krb5_verify_init_creds","server"]],krb5_verify_init_creds_opt:[[894,3,1,"c.krb5_verify_init_creds_opt.ap_req_nofail","ap_req_nofail"],[894,3,1,"c.krb5_verify_init_creds_opt.flags","flags"]],krb5_verify_init_creds_opt_init:[[415,1,1,"c.krb5_verify_init_creds_opt_init","k5_vic_options"]],krb5_verify_init_creds_opt_set_ap_req_nofail:[[416,1,1,"c.krb5_verify_init_creds_opt_set_ap_req_nofail","ap_req_nofail"],[416,1,1,"c.krb5_verify_init_creds_opt_set_ap_req_nofail","k5_vic_options"]],krb5_vprepend_error_message:[[417,1,1,"c.krb5_vprepend_error_message","args"],[417,1,1,"c.krb5_vprepend_error_message","code"],[417,1,1,"c.krb5_vprepend_error_message","ctx"],[417,1,1,"c.krb5_vprepend_error_message","fmt"]],krb5_vset_error_message:[[418,1,1,"c.krb5_vset_error_message","args"],[418,1,1,"c.krb5_vset_error_message","code"],[418,1,1,"c.krb5_vset_error_message","ctx"],[418,1,1,"c.krb5_vset_error_message","fmt"]],krb5_vwrap_error_message:[[419,1,1,"c.krb5_vwrap_error_message","args"],[419,1,1,"c.krb5_vwrap_error_message","code"],[419,1,1,"c.krb5_vwrap_error_message","ctx"],[419,1,1,"c.krb5_vwrap_error_message","fmt"],[419,1,1,"c.krb5_vwrap_error_message","old_code"]],krb5_wrap_error_message:[[420,1,1,"c.krb5_wrap_error_message","code"],[420,1,1,"c.krb5_wrap_error_message","ctx"],[420,1,1,"c.krb5_wrap_error_message","fmt"],[420,1,1,"c.krb5_wrap_error_message","old_code"]],passwd_phrase_element:[[895,3,1,"c.passwd_phrase_element.magic","magic"],[895,3,1,"c.passwd_phrase_element.passwd","passwd"],[895,3,1,"c.passwd_phrase_element.phrase","phrase"]]},objnames:{"0":["c","function","C function"],"1":["c","functionParam","C function parameter"],"2":["c","type","C type"],"3":["c","member","C member"],"4":["py","data","Python data"]},objtypes:{"0":"c:function","1":"c:functionParam","2":"c:type","3":"c:member","4":"py:data"},terms:{"0":[3,5,6,14,15,20,21,23,28,35,37,39,41,43,46,49,50,53,55,56,61,62,63,64,65,66,67,68,69,71,72,73,74,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,95,96,97,98,99,100,102,103,104,105,106,107,108,111,112,113,114,115,116,117,118,119,121,124,125,126,129,130,132,133,134,135,137,139,141,142,145,147,148,149,150,152,153,154,155,156,157,158,159,161,162,163,164,165,166,167,169,170,172,173,174,175,176,177,178,180,181,182,183,184,185,187,189,192,193,214,217,223,224,227,229,231,235,236,238,245,248,260,261,262,264,265,266,267,268,271,272,273,274,275,276,277,278,279,280,282,286,287,288,289,290,294,295,296,298,299,300,301,302,303,304,305,306,308,310,311,313,314,315,316,317,318,321,322,323,324,325,326,327,328,329,330,331,332,333,335,336,337,338,339,342,344,345,347,352,354,355,356,357,358,359,360,361,363,364,374,375,376,377,378,382,383,384,385,389,390,391,392,394,395,396,397,398,400,401,402,403,404,405,406,407,408,409,410,414,534,621,629,647,679,733,735,791,803,837,908,910,914,915,918,919,923,928,932,933,934,935,943,946,948],"00":[3,5,23,898],"01":[5,23,42,898,924],"02":[34,918],"03":[14,35,939],"04":[924,939],"0400":898,"05":939,"05pm":898,"06":[924,939],"07":[898,939],"08":[898,939],"0h":[20,34,898],"0m":[20,34,898],"0s":[20,34,898],"0x0000":478,"0x00000001":[440,498,522,523,752,755],"0x00000002":[436,494,525,529,749,754],"0x00000004":[521,524,747],"0x00000008":[488,526,528,753],"0x00000010":[21,496,527,748],"0x00000020":[487,530,746],"0x00000040":751,"0x00000080":745,"0x00000100":750,"0x00000200":756,"0x00008000":[497,772],"0x0001":[444,471,544,562,726,729,762],"0x00010000":[485,773],"0x0002":[425,454,472,560,725,728],"0x00020000":486,"0x0003":[455,473],"0x0004":[445,474,557,730],"0x00040000":780,"0x0005":[423,469],"0x0006":[431,468],"0x0007":[428,456],"0x0008":[457,475,559,731],"0x00080000":786,"0x0009":[453,476],"0x000a":477,"0x000b":482,"0x000c":[449,479],"0x000d":480,"0x000e":[458,481],"0x000f":[447,467],"0x0010":[424,448,470,556],"0x00100000":776,"0x0011":[442,459],"0x0012":[443,461],"0x0013":[450,460],"0x0014":[430,451,462],"0x0017":463,"0x0018":[426,464],"0x0019":465,"0x001a":466,"0x0020":552,"0x00200000":782,"0x0040":558,"0x00400000":777,"0x0080":561,"0x00800000":[495,785],"0x0100":[422,555],"0x01000000":778,"0x0101":427,"0x01ff":483,"0x0200":554,"0x02000000":[491,781],"0x0400":553,"0x04000000":[484,779],"0x08000000":[493,784],"0x1":[564,565,713,717,721,761],"0x10":712,"0x10000000":[492,783],"0x1fff":433,"0x2":[563,714,716,719],"0x2000":434,"0x20000000":[437,490,742,775],"0x3":720,"0x4":[710,715,722],"0x4000":432,"0x40000000":[439,489,743,774],"0x54800000":499,"0x7fff":[764,768],"0x8":711,"0x8000":[429,435,765,767],"0x80000000":[438,744],"0xfffffff0":441,"1":[0,3,4,5,6,8,11,14,15,16,19,20,21,23,24,25,26,28,33,34,35,37,38,39,40,41,42,43,44,46,48,87,89,91,93,119,132,143,154,155,160,165,166,167,169,192,194,195,203,209,211,219,229,245,246,247,250,253,257,265,286,300,301,303,307,313,336,343,344,365,366,367,368,369,370,371,372,373,380,381,386,387,397,399,400,401,402,403,404,513,535,541,551,567,569,581,619,626,634,641,658,665,681,708,734,735,736,737,801,802,896,897,898,901,905,906,908,910,912,914,915,918,921,922,923,924,925,928,929,930,931,932,934,942,943,945,946,948,951,952,953],"10":[3,5,14,15,21,23,35,38,39,42,43,44,132,143,154,155,160,167,195,219,342,506,578,637,652,664,897,898,901,918],"1000":[20,23],"1022":915,"1023":915,"1024":[21,43],"10d":898,"11":[0,6,8,14,15,20,21,23,26,41,43,165,169,250,257,303,313,365,366,367,368,369,373,505,577,648,654,672,740,910,918,939],"1100":766,"114687":915,"12":[3,14,21,23,34,35,37,41,43,211,307,370,371,372,576,663,696,760,897,898,915,918,922,925,931,932,939,946],"1234":46,"127":15,"128":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],"129":[511,640,674],"12h":[20,34],"13":[3,4,20,23,39,43,596,651,699,759,897,918],"130":[638,695],"13135":12,"132":666,"133":675,"1332348778":41,"136":677,"137":[452,676],"138":[446,668],"14":[3,14,16,20,21,23,504,594,656,690,898,911,914,918,929,931],"140":918,"141":681,"141231235900":898,"142":683,"143":508,"144":682,"147":686,"149":542,"15":[6,14,20,21,26,39,43,194,253,380,381,503,597,655,688,915,918,919],"150":667,"151":[702,911],"152":692,"153":693,"15552000":3,"16":[3,19,20,21,37,43,548,575,662,689,896,910,914,915,918,921,928,930,939],"16383":915,"16384":915,"167":684,"17":[3,14,20,21,24,25,26,37,40,43,229,343,574,650,687,912,918,919,923],"18":[14,21,26,38,43,265,336,595,660,901,915,918,924,939,953],"180":[3,35],"1812":20,"19":[14,20,21,26,43,203,209,571,657,673,918,921,939,948],"192":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],"1964":911,"1970":[23,896],"1983":919,"1985":[909,919,953],"1986":953,"1989":953,"1990":[905,919],"1991":919,"1992":919,"1993":919,"1994":919,"1995":919,"1996":[3,919,953],"1997":919,"1998":919,"1999":919,"1foo":21,"2":[3,5,6,14,15,19,21,23,26,34,35,37,39,43,166,320,412,533,545,593,600,617,623,631,644,653,670,683,707,732,737,908,910,911,914,915,918,919,923,934,946,953],"20":[9,20,39,43,91,93,300,301,344,572,703,705,741,898,918,921,939],"2000":[26,637,639,703,919],"200000":898,"2001":10,"2002":[10,919,953],"2003":919,"2004":[9,919],"2005":919,"2006":919,"2007":919,"2008":919,"2009":919,"2010":919,"2011":[919,953],"2012":[35,898],"20120727203000":898,"2013":[918,919],"2014":[898,918,919],"20141231235900":898,"2015":[898,919],"2016":919,"2018":953,"2022":919,"2024":[909,919],"2037":37,"2038":[45,885,918],"2047":915,"2048":[20,21,37,915],"21":[21,26,570,573,698,718,918,939],"2106":[885,896,918],"2147483647":[568,898],"22":[531,589,678,898,939],"2253":21,"23":[9,39,590,898,939],"24":[20,46,591,939],"25":[604,694,939],"2500":[20,23],"255":918,"256":[14,20,21,40,915,918],"26":[23,603,605],"27":[602,606,898],"2743":43,"2744":43,"2782":39,"29":939,"2m":20,"3":[3,6,14,19,20,21,23,26,32,36,37,43,44,166,417,418,419,467,537,579,615,627,635,643,682,691,898,906,910,915,918,919,923,946],"30":[35,39,543,697,898,939,942],"300":[21,23],"30m":898,"31":[14,700,898,939],"3187":34,"3189":34,"32":[10,12,14,24,550,896,910,914],"3244":[382,383,918],"33":35,"35":34,"36":898,"3600":898,"365":37,"3650":37,"37":9,"384":[20,21,40],"3961":[458,664,911,912,915],"3962":[447,448,459,461],"3de":14,"3h":939,"3h30m":939,"4":[6,9,14,19,20,21,23,34,37,39,43,166,321,405,515,536,546,600,610,620,624,632,638,640,645,681,682,683,706,908,910,914,915,918],"40":[35,39],"4096":[20,21,915],"4120":[320,412,540,664,669,670,671,672,673,678,680,691,698,701,705,901,918,922],"42":[9,592],"424":9,"44":601,"4402":119,"45":600,"4537":511,"4556":[20,21,687,689,918],"4557":42,"464":[15,20,21,39,917],"47":[3,34],"4757":[43,446,463,464],"48":939,"49":939,"49151":915,"49152":915,"4gb":918,"5":[0,3,6,10,12,14,19,20,21,23,31,34,36,37,43,119,320,412,507,539,611,614,625,633,646,671,723,898,903,908,910,911,914,918,919,941,942,943,945,946,947,949,953],"50":588,"509":[20,21,37,43,918,921,948],"51":585,"512":[24,519],"513":[599,911],"514":[598,912],"52":[34,587,939],"521":[21,40],"5280":43,"53":586,"5351":918,"54":583,"5480":21,"55":584,"5587":[918,924],"5588":918,"56":[14,580],"5801":918,"5896":918,"59":[14,898],"5h30m":942,"5m":20,"6":[3,6,9,15,19,37,39,320,342,412,532,613,616,628,636,649,661,669,758],"60":[5,35,46,898,905],"604800":3,"6112":[686,918],"6113":[48,668,675,676,677,910,911,918,922],"64":[500,517,547,582,885,896],"65":[518,607],"65535":[566,918],"6560":[600,681,682,683,738,918],"6649":14,"6680":[43,918],"6803":[442,443,465,466,918],"6806":[43,542,910,918],"6820":703,"7":[3,6,23,26,33,39,41,43,247,538,612,618,622,630,642,659,701,897,918],"70":905,"71":512,"730":919,"749":[15,20,34,39,917],"753241234":3,"754":[8,15,34,41,917,953],"7546":43,"7553":39,"76cho3000":919,"774":919,"7748":21,"785900000":3,"785926535":3,"786100034":3,"7d":[20,34],"8":[3,5,6,8,12,23,26,35,43,46,247,350,365,373,516,549,608,680,709,898,910,914,918,919,942],"8009":[450,451,460,462],"8070":[667,912],"816":42,"823276":41,"823381":41,"85":906,"86400":3,"86528":42,"88":[10,15,20,34,37,39,917],"89":39,"8h30":898,"9":[14,19,20,21,26,35,41,87,89,192,245,246,386,387,399,400,401,402,403,404,514,540,609,905,918],"9138":41,"96":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],"97":509,"9899":905,"9h":19,"abstract":[920,922,928,929,931,935],"boolean":[6,20,23,36,48,55,870,894],"break":[32,902],"byte":[20,43,46,48,99,104,287,311,910,911,912,914,915,924],"case":[2,3,6,11,14,19,20,21,23,24,28,38,39,43,46,195,245,280,325,330,350,359,375,389,416,706,897,898,900,919,922,923,924,927,931,932,944,946,951,953],"char":[43,46,49,50,56,59,60,91,92,93,94,107,136,141,143,144,146,149,152,155,156,160,166,169,170,187,192,193,194,210,213,214,219,222,223,227,228,230,231,233,235,247,252,260,264,267,277,278,306,311,312,317,319,329,336,344,345,346,352,361,363,365,366,369,372,373,374,375,377,379,382,383,384,387,389,390,391,392,394,395,397,398,406,407,408,409,417,418,419,420,803,829,841,870,872,878,879,881,889,934],"class":[3,23,944],"const":[43,49,52,53,54,58,59,60,91,92,93,94,99,100,101,102,103,106,107,108,113,114,117,119,120,125,126,129,130,136,141,144,146,149,152,155,156,160,166,169,172,173,174,175,177,178,180,181,183,184,185,188,189,194,195,197,213,214,223,228,231,232,233,234,235,247,252,260,264,265,267,277,278,281,284,286,287,288,289,290,294,298,299,300,301,312,317,319,320,322,324,326,329,331,333,336,339,340,341,342,343,344,345,346,351,352,353,355,356,357,358,359,360,361,365,366,369,372,373,376,377,378,379,382,383,384,387,389,393,405,412,413,417,418,419,420,792,820,821,865,866,872,888,889,934],"default":[2,3,4,5,6,7,8,10,11,12,15,19,20,21,22,23,24,26,29,30,32,33,34,35,37,38,39,40,41,43,44,46,48,59,60,78,132,147,148,154,223,229,243,253,265,269,275,278,315,317,345,359,375,383,414,712,898,905,906,907,908,910,918,923,924,925,939,941,942,943,945,946,947,948,952,953],"do":[3,6,14,15,20,21,22,23,26,28,29,32,33,34,37,38,39,40,41,43,46,223,267,349,408,549,905,906,908,918,919,923,924,928,930,931,938,939,942,946,948,953],"export":[20,34,918,919,923,924,933,934],"final":[19,21,112,158,904,911,915],"function":[3,6,14,25,29,34,35,43,46,48,49,50,55,57,58,59,60,61,62,67,68,69,71,72,73,74,76,77,78,81,82,84,85,86,87,88,89,92,93,99,100,101,102,103,104,105,107,113,114,116,117,119,124,125,126,129,130,133,136,137,139,148,150,151,153,156,157,158,159,167,169,171,172,173,174,175,177,178,180,181,182,183,192,194,195,198,199,200,201,202,203,205,206,207,208,209,212,215,216,221,228,235,236,241,245,246,252,254,258,260,261,262,264,265,266,267,271,272,275,276,277,278,279,287,288,289,290,294,295,296,298,299,301,308,310,320,323,324,325,326,327,329,330,331,333,334,342,343,345,352,355,356,357,358,359,360,361,368,371,373,376,378,382,383,385,387,389,396,400,401,403,404,407,408,410,412,414,416,417,419,856,865,866,870,872,877,903,904,918,919,922,923,924,927,930,931,933,934],"goto":46,"h\u00f6gskola":919,"import":[5,6,14,15,17,19,21,23,34,35,918,924,938],"int":[43,51,53,56,59,62,91,92,93,94,97,111,116,120,122,166,223,241,242,243,244,249,254,255,279,306,311,345,350,352,361,382,383,404,407,408,409,416,805,811,814,818,829,840,846,848,853,857,859,870,872,873,891,894,923],"long":[3,14,15,23,25,26,37,38,39,41,43,99,287,365,366,739,766,897,900,918,919,922,931,934,948],"new":[2,3,6,14,20,21,23,24,26,34,35,37,41,43,48,87,89,129,132,138,143,154,160,163,165,166,167,169,172,173,174,175,176,177,178,180,182,183,192,194,195,211,219,229,235,243,245,246,250,253,257,260,262,269,275,280,298,300,301,303,307,313,327,330,336,338,343,344,345,359,365,366,367,368,369,370,371,372,373,380,381,382,383,386,387,399,400,401,402,403,404,407,719,720,897,901,915,918,919,923,924,927,928,931,938,939,942,944,953],"null":[19,20,21,43,44,46,48,54,64,92,99,100,102,103,107,113,129,136,141,154,155,156,164,173,195,198,200,203,209,220,223,224,228,230,231,235,240,260,264,267,269,273,275,287,288,289,290,294,298,300,301,315,322,323,325,326,329,330,331,332,336,342,343,344,354,356,359,360,361,363,364,365,366,369,372,375,377,380,381,382,383,386,388,389,397,407,408,409,412,414,793,918,923,932,934,953],"public":[21,40,919,927,928,929,930],"return":[3,9,12,20,21,22,38,43,46,48,50,52,54,56,57,59,60,69,74,91,92,93,100,103,109,110,119,127,128,133,135,137,141,142,144,145,146,147,148,149,151,152,153,154,155,156,159,161,169,176,189,192,214,223,224,227,228,229,231,235,260,262,263,264,267,268,271,279,282,283,284,288,290,301,302,303,305,306,308,310,311,314,315,316,317,318,320,323,325,330,344,345,352,355,361,365,366,368,371,375,377,378,380,382,383,384,386,388,389,396,398,400,404,406,407,408,409,410,412,414,416,731,865,866,906,918,920,921,922,923,924,925,928,929,931,932,933,934,935,942,946],"short":[14,19,21,41,306,900],"static":[46,923,934],"switch":[14,28,31,43,48,161,897],"true":[9,14,20,21,22,23,24,25,26,33,35,36,37,38,40,41,43,52,54,105,109,110,127,128,160,192,245,283,284,285,300,319,343,348,349,350,362,388,416,813,826,860,952],"try":[21,25,32,35,38,39,41,43,906,918,938,946],"var":[5,8,20,21,23,34,37,901,906,907,917,953],"void":[43,46,57,58,59,60,63,80,171,179,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,215,216,218,219,220,221,222,237,239,240,241,242,243,244,245,249,254,255,256,257,258,259,260,270,275,285,291,297,334,339,346,352,367,370,379,380,381,386,399,415,416,417,418,419,420,820,838,856,864,865,866,872,877,888,933,934],"while":[3,12,14,15,16,20,21,23,24,34,35,43,46,897,904,923,938,939,946,953],A:[3,6,8,15,16,19,21,23,24,25,26,28,32,34,35,36,37,38,43,46,169,229,342,344,366,368,371,388,740,850,876,889,897,900,901,910,911,914,915,917,918,919,920,921,922,923,924,925,927,928,929,931,932,933,934,935,939,941,942,943,953],AND:919,AS:[10,21,23,25,26,253,505,666,918,919,922,930,931],As:[3,14,16,17,26,34,35,37,39,43,46,908,928,930,934,942],At:[14,23,33,34,165,910],BE:919,BUT:919,BY:919,Be:14,But:901,By:[5,6,21,23,24,28,32,34,37,40,78,253,906,918,919,924,939,942,943,946],FOR:919,For:[3,10,14,16,17,18,19,20,21,22,23,24,26,28,32,33,34,35,36,37,38,39,43,46,99,100,103,142,287,288,290,738,896,897,901,904,905,906,910,911,915,916,917,918,920,921,922,923,924,925,927,928,929,930,931,932,933,934,935,936,938,939,942,945,946,951,953],IF:[195,300,919],IN:[826,919],IS:919,IT:919,ITS:[42,919],If:[0,2,3,4,5,6,8,9,10,11,14,15,16,17,19,20,21,22,23,24,25,26,28,29,32,33,34,35,36,37,38,39,40,41,43,44,46,54,56,99,100,101,102,103,113,129,152,154,156,158,159,161,169,192,223,224,229,230,231,235,245,250,251,253,260,264,267,269,279,280,287,288,289,290,294,298,300,301,310,315,317,325,326,327,330,331,336,342,343,344,345,352,356,359,360,361,375,377,382,383,386,388,397,404,407,414,416,731,865,866,877,897,898,901,902,904,905,906,908,910,911,918,919,921,923,924,925,931,932,934,938,939,941,942,943,944,946,947,948,951,953],In:[2,3,4,6,8,14,17,20,21,22,23,24,26,28,29,32,34,35,37,38,39,43,247,359,375,389,897,904,905,906,911,918,922,923,924,927,932,936,939,943,946,952,953],Is:14,It:[3,5,8,9,10,12,14,20,21,23,24,34,35,36,39,46,55,124,203,209,243,245,280,382,383,739,876,897,901,910,918,919,921,925,930,932,938,949,953],Its:[20,21,910],NO:919,NOT:[5,34,919],No:[3,12,21,34,151,325,919,939,953],Not:[20,21,44,51,151,614,897],OF:[911,919],ON:919,ONE:5,OR:[740,919],ORed:151,Of:[17,35],On:[15,20,21,23,34,37,41,43,100,103,144,271,279,288,290,330,359,361,400,404,407,408,409,901,904,917,918,931,939,942],One:[3,20,23,34,36,38,43,342,897,898,938,939,952],SUCH:919,Such:[14,37,39,46],THAT:919,THE:919,TO:919,That:[21,904],The:[0,3,4,5,6,7,8,9,10,11,12,15,19,20,21,22,23,24,25,26,28,29,31,33,34,35,37,38,39,40,41,43,46,53,62,69,71,74,78,80,91,93,99,100,102,103,113,117,119,121,125,126,129,135,136,138,144,146,148,153,165,166,173,176,189,198,200,217,220,224,228,229,245,248,252,262,268,274,282,286,287,288,289,290,294,296,298,300,305,307,312,315,320,321,322,325,326,331,333,344,345,346,354,356,359,360,365,366,367,368,369,370,371,372,373,376,380,381,382,383,389,398,402,403,405,406,407,408,412,414,420,618,730,738,740,745,746,749,750,752,756,807,813,827,837,850,865,866,870,876,883,896,897,898,900,901,902,903,904,905,906,907,908,910,911,912,914,915,917,918,919,920,921,922,923,924,925,927,928,929,930,931,932,933,934,935,936,938,939,941,942,944,946,948,950,951,952,953],Then:[3,6,17,24,34,942],There:[20,21,23,34,35,897,904,906,907,910,914,939],These:[14,16,20,21,23,26,34,35,37,39,43,733,904,910,918,919,922,924,927,951,953],To:[3,14,15,16,19,20,21,23,24,25,28,29,34,35,36,37,38,39,40,41,43,46,344,896,904,908,914,918,924,928,930,936,938,939,946],WILL:919,WITH:919,With:[0,3,6,22,23,39,952],_:42,_kerbero:39,_kpasswd:39,_krb5_address:805,_krb5_ap_rep:[807,808],_krb5_ap_rep_enc_part:808,_krb5_ap_req:809,_krb5_auth_context:810,_krb5_authdata:811,_krb5_authent:813,_krb5_ccach:816,_krb5_cccol_cursor:817,_krb5_checksum:818,_krb5_context:[135,156,822],_krb5_cred:[823,826],_krb5_cred_enc_part:824,_krb5_cred_info:825,_krb5_crypto_iov:827,_krb5_data:829,_krb5_enc_data:831,_krb5_enc_kdc_rep_part:832,_krb5_enc_tkt_part:833,_krb5_encrypt_block:834,_krb5_error:836,_krb5_get_init_cr:840,_krb5_get_init_creds_opt:840,_krb5_gic_opt_pa_data:841,_krb5_init_creds_context:842,_krb5_kdc_rep:845,_krb5_kdc_req:846,_krb5_keyblock:848,_krb5_kt:849,_krb5_last_req_entri:854,_krb5_pa_data:859,_krb5_pa_pac_req:860,_krb5_pa_server_referral_data:861,_krb5_pa_svr_referral_data:862,_krb5_prompt:870,_krb5_pwd_data:873,_krb5_responder_otp_challeng:878,_krb5_responder_otp_tokeninfo:879,_krb5_responder_pkinit_challeng:880,_krb5_responder_pkinit_ident:881,_krb5_respons:882,_krb5_ticket:883,_krb5_ticket_tim:884,_krb5_tkt_authent:886,_krb5_tkt_creds_context:887,_krb5_trace_info:889,_krb5_transit:890,_krb5_typed_data:891,_krb5_verify_init_creds_opt:894,_passwd_phrase_el:895,_profile_t:[262,269],_tcp:39,_udp:39,abbrevi:[904,943],abc:[906,953],abi:885,abil:[14,368,371,952],abl:[15,16,19,20,21,23,25,29,34,35,39,897,902,938,939,946],abort:[802,803,933],about:[0,14,19,20,22,23,26,31,39,41,43,46,251,901,904,906,908,918,919,922,931,936,939,942,953],abov:[6,14,19,21,22,23,25,26,32,34,37,41,43,46,901,906,910,919,923,924,925,939,946],absenc:[20,46],absent:942,absolut:[20,21,896,900,904],ac02:919,ac:[72,73,76,77,86,87,88,89],acceler:919,accept:[3,4,8,14,15,16,20,21,26,34,38,39,41,151,389,898,900,904,918,919,920,924,933,934,939,942],acceptor:[8,918,943],acceptor_cred_handl:43,access:[3,4,8,9,14,17,18,19,20,21,22,23,24,25,26,28,29,32,33,34,35,37,39,43,46,897,902,904,912,915,918,922,927,928,930,931,932,937,939,945,946,951,952],accident:918,accommod:[46,901],accomplish:[23,26],accord:[3,19,21,36,38,43,154,167,910,911,917,924,946,948],account:[20,21,24,25,28,30,48,56,245,336,897,918,932,937,942,946,950,952],account_expir:[245,838],acknowledg:919,acl:[3,4,8,18,20,21,22,23,31,917],acl_fil:[4,8,19,20,34],acquir:[3,6,8,43,48,245,274,402,548,910,918,924,948],acquisit:[43,403],across:[17,20,21,34,43,928,929,930,938],act:[10,19,21,26,901,918],action:[4,6,14,901,919,929],activ:[3,6,8,14,21,23,25,37,40,169,941],actor:19,actual:[6,14,23,26,35,46,98,99,100,102,103,113,129,287,288,289,290,294,298,901,939],actual_mech:43,ad:[3,6,8,17,20,21,23,24,25,26,32,34,38,40,41,48,195,300,302,740,897,910,918,921,948],ad_kdcissu:[320,412],ad_typ:[195,811,910],ad_type_extern:789,ad_type_field_type_mask:789,ad_type_regist:789,ad_type_reserv:789,add:[3,6,9,11,12,14,15,19,20,21,22,23,31,33,36,38,48,300,343,712,898,918,939],add_auth_ind:[918,931],add_mkei:[14,23],add_polici:23,add_princip:[5,14,23,25,37],add_rel:934,addent:[11,918],addit:[3,18,19,20,21,22,26,29,34,37,38,39,40,43,46,48,301,363,364,414,836,897,901,904,906,908,909,918,919,922,931,936,942,946,953],addition:[10,21,36,930,939],addpol:[3,23,35],addprinc:[3,23,34,37,898,928],addr1:[52,53],addr2:[52,53],addr:[54,232,233,234,332,825,826,832],address1:910,address2:910,address:[0,15,20,21,23,24,30,33,38,39,44,48,260,325,326,331,356,359,360,523,524,525,526,805,824,826,833,846,906,910,918,933,939,942,943],address_list:840,addresssanit:918,addrlist:54,addrtyp:[429,805,910],addrtype_addrport:789,addrtype_chao:789,addrtype_ddp:789,addrtype_inet6:789,addrtype_inet:789,addrtype_ipport:789,addrtype_is_loc:789,addrtype_iso:789,addrtype_netbio:789,addrtype_xn:789,adjust:[14,29,33,34,37,48,100,103,288,290,410],adm:[20,22,39],admcil:19,admcilsp:19,admin:[3,4,5,8,14,15,16,19,21,22,23,26,32,34,897,906,917,918,928,946,953],admin_serv:[3,8,20,21,34,39],adminhost:3,administ:[4,15,34],administr:[0,2,3,4,5,6,11,14,15,16,18,19,20,21,22,24,25,26,31,32,35,36,38,897,903,916,917,918,919,929,936,938,942,952,953],adminjohndoefoo:21,adtyp:811,advanc:[14,30,150,314,918,936],advantag:[14,21,26,32],advertis:[21,918,919],advic:31,advis:[14,919],ae:[3,14,15,20,25,906,918,919],aead:48,aes128:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],aes256:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],aesni:[906,919],af:14,af_unspec:933,affect:[4,19,20,21,26,28,40,126,133,229,918,942,953],afford:32,afs3:14,after:[2,3,4,6,10,12,14,21,23,24,25,33,34,35,37,80,98,136,228,272,380,401,885,896,897,902,904,910,911,914,915,918,938,939,946,953],afterward:[23,929],again:[14,28,33,34,720,901,918,924,938,939],against:[2,14,20,21,25,28,34,39,40,46,48,129,298,342,356,359,360,363,412,901,906,918,921,924,945,951],agent:20,agre:919,agreement:919,aklog:55,al:3,alexand:919,alg_id:879,algid:738,algorithm:[14,26,126,915,918,919,946],alia:[3,11,43,48,144,146,312,365,366],alias:[3,11,15,22,38,39,918],alic:[11,23,28,951,952],all:[0,2,3,6,9,14,15,17,18,19,20,21,23,24,25,26,28,29,32,33,34,35,37,38,43,46,48,153,163,164,282,342,359,414,747,748,753,817,827,897,898,901,904,905,909,910,915,918,919,930,932,939,941,943,944,945,946,948,951,953],alloc:[43,46,48,61,78,93,98,99,100,102,103,107,115,117,119,121,124,148,280,287,288,289,290,296,355,357,407,827,870,921,923,925,928,932],allow:[2,3,4,5,6,8,10,12,14,15,16,17,18,19,20,21,23,24,26,28,29,32,33,34,35,36,37,38,40,41,43,46,48,111,252,279,359,404,407,898,900,902,904,906,908,911,918,919,920,921,922,924,925,926,927,928,929,930,931,932,933,934,935,938,939,942,945,952],allow_des3:[21,26,918],allow_dup_skei:3,allow_forward:[3,5],allow_postd:[3,5],allow_proxi:3,allow_rc4:[21,26,918],allow_renew:3,allow_svr:[3,23,25,35,40],allow_tgs_req:3,allow_tix:3,allow_weak_crypto:[14,21,26,41,48],allowedkeysalt:3,almeida:919,alon:[34,923],along:[0,36,827,897,906,924],alongsid:34,alphabet:898,alphanumer:21,alreadi:[6,14,22,34,36,43,124,333,897,904,906,908,942,946,948],also:[15,17,18,22,23,24,25,26,28,29,32,33,34,35,37,38,39,40,43,46,126,342,403,896,897,900,906,908,910,918,919,921,922,924,925,927,928,930,932,934,935,939],alter:[14,37],altern:[8,15,20,21,22,24,28,34,37,43,500,904,906,917,918,919,942],although:[39,900,919,925,935,938,939],altogeth:20,alwai:[14,15,20,21,23,24,39,44,51,55,61,63,66,68,71,80,83,139,142,155,365,716,910,914,918],am:898,america:919,among:46,amount:[20,21,35,39,102,119,121,289,361,905],an2ln:[21,932],an2ln_typ:932,an:[0,2,3,4,5,6,8,9,11,12,14,15,16,19,20,21,22,23,24,25,26,28,29,32,33,34,35,36,37,38,39,40,41,43,46,48,55,56,61,93,99,101,119,126,144,146,154,229,235,236,241,243,247,260,263,265,276,277,279,287,300,301,312,315,320,326,327,330,331,342,355,356,360,365,366,373,375,388,394,404,407,412,414,722,735,736,738,813,821,827,837,868,869,877,896,900,901,904,905,906,910,911,912,915,917,918,919,920,922,923,924,927,928,929,931,932,933,934,935,938,939,942,944,946,948,953],analog:15,anam:[56,946],anchor:[20,21,942],andrea:919,andrew:5,ani:[0,3,6,8,9,10,14,15,16,17,19,20,21,23,24,25,26,28,32,34,36,37,38,39,40,41,43,46,48,56,137,147,153,154,156,224,260,268,275,278,279,310,315,359,363,364,404,414,740,837,897,901,902,910,911,915,918,919,920,924,925,932,938,939,942,943,946,952],ank:3,anl:21,annot:[16,23,36,918],anonym:[3,20,25,28,43,48,501,502,918,939,942,943],anoth:[15,17,21,24,32,41,48,101,171,826,897,901,906,910,921,922,928,932,933,939,953],ansi:905,answer:[21,46,48,366,731,738,740,876,924],anticip:[33,39],anyon:[938,952],anyth:[21,37],anywai:[20,39,46,330],anywher:[938,953],ap:[92,94,195,199,327,328,329,330,357,358,359,503,807],ap_opt:[329,330,375,809,886],ap_opts_etype_negoti:789,ap_opts_mutual_requir:[330,359,375,789],ap_opts_reserv:789,ap_opts_use_session_kei:[330,789],ap_opts_use_subkei:[330,789],ap_opts_wire_mask:789,ap_req_authdata:195,ap_req_nofail:[416,894],ap_req_opt:[329,330,359,375],api:[0,14,41,43,45,98,100,103,186,188,190,191,196,197,245,250,251,262,281,288,290,351,353,411,740,827,847,897,903,906,918,920,924,931],appdata:[21,901],appdefault:48,appear:[14,20,21,24,34,37,39,41,46,910,919,923],append:[3,20,23,38,387,900,906,915],appl:[903,919],appl_vers:[363,375],appli:[3,10,14,18,19,20,21,23,24,35,41,43,171,919,928,931,939,942,946,950],applic:[0,12,16,18,20,21,28,30,31,37,43,46,48,59,60,156,250,329,330,331,363,375,504,528,529,718,741,896,897,900,901,903,906,916,918,919,922,924,927,932,934,938,939,945,949,952],appnam:[59,60],approach:43,appropri:[6,14,21,23,24,28,29,34,37,39,43,46,154,373,398,920,930,931,942,943,946],approxim:[905,918],apputil:903,aprepencpart:807,ar:[0,2,3,4,5,6,9,10,11,12,14,15,16,17,18,19,20,21,22,23,24,25,26,28,29,33,34,35,36,37,38,39,40,43,46,52,53,66,78,80,83,92,100,103,105,107,153,154,164,166,217,224,229,230,231,241,245,248,252,269,279,280,288,290,325,330,342,345,348,349,350,359,361,362,366,375,381,382,383,404,408,414,731,827,837,847,885,897,898,900,901,903,904,906,908,910,911,912,914,915,917,918,919,920,922,923,924,927,929,930,932,933,935,939,941,942,944,945,946,948,951,953],arbitrari:[3,43],arcfour:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],architectur:[904,906],archiv:[42,905],area:[34,46],arg:[3,417,418,419,802,803,906,946],arg_keytab:[232,235],argument:[3,4,6,8,10,14,20,44,46,48,63,80,91,93,245,257,260,263,275,325,326,331,352,354,356,360,386,417,418,419,889,906,918,923,924,932,946,948],argv_pars:919,ari:946,aris:919,armor:[20,37,48,229,922,931,942],armor_ccach:942,around:[23,906],arrai:[3,36,43,46,48,100,103,111,173,240,244,254,288,290,322,332,352,354,821,825,827,832,833,846,868,869,932,934],arrang:23,arriv:901,asan:[906,918],asc:905,ascii:[6,23,39,910],ask:[6,37,39,46,48,738,739,740,922,938,939,942,946],asn:[48,911,912,921],aspect:[15,28,927],assert:[20,43,910,918,924,931],assign:[3,19,20,34,39,48,82,84,946],associ:[3,4,9,19,20,21,23,35,38,43,537,897,901,910,919,953],assum:[14,21,26,34,36,39,43,44,107,124,155,905,918,939,942,953],assumpt:26,asynchron:[403,931],athena:[3,5,14,15,19,20,21,23,24,28,32,34,906,919,934,938,939,953],athent:260,atom:918,attach:918,attack:[2,14,21,23,29,30,32,35,40,46,325,326,331,901,918,942],attempt:[0,3,6,20,21,24,29,35,39,43,243,250,414,910,918,946],attr:[252,841],attribut:[3,5,6,9,16,19,20,21,22,23,24,26,36,37,48,253,650,841,918,919,921,924,931,942,946],audit:918,aug:3,augment:924,august:919,auth:[16,20,39,43,48,61,329,330,359,363,364,375,504,811,825,833],auth_context:[61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,90,223,323,325,326,327,328,329,330,331,354,356,357,358,359,360,363,364,375],auth_gssapi:3,auth_to_loc:[21,28,932],auth_to_local_nam:[21,28],authdata1:910,authdata2:910,authdata:[184,189,224,320,322,412,826,910,918,926,942,943],authdata_plugin:927,authdatum:412,authent:[3,5,6,10,12,14,15,20,21,22,24,25,26,29,30,32,34,35,36,37,38,39,40,43,44,46,48,61,62,63,64,66,67,68,69,71,72,73,74,76,77,79,80,81,82,83,84,85,86,87,88,89,90,166,201,223,224,250,322,323,325,326,327,328,329,330,331,336,342,354,356,357,358,359,360,375,437,500,506,615,738,807,809,813,859,876,886,897,900,901,902,903,910,911,915,918,919,921,931,932,939,942,943,949,953],authfrom:174,author:[3,19,20,21,48,153,224,253,300,614,746,826,863,918,919,926,941],authoriaz:813,authorit:[19,21,154,920,925,928,932,933],authoritykeyidentifi:37,authorization_data:[813,833,846],authtim:[340,341,342,343,884,910],authtime_out:336,authto:174,authz:846,auto:918,autoconf:903,autodoc:908,autohead:904,autolock:919,autom:[904,918],automak:923,automat:[3,4,6,8,15,17,23,34,897,900,902,904,915,918,939,941,946],autoreconf:904,avail:[3,6,11,12,14,20,21,23,29,34,38,43,46,56,170,187,192,193,227,252,306,310,315,361,368,371,374,398,416,563,823,845,883,897,904,915,920,926,941,943,947,953],avoid:[3,14,19,24,38,46,245,906,918,939],awai:[14,41,938,939],awar:910,awk:6,b7:6,b:[344,918],back:[19,20,23,24,30,39,40,897,906,911,918,924,927],backend:[14,906,918,919],background:[4,8,10,34],backslash:344,backspac:344,backup:[23,30,32,39,902],backward:[8,20,21,24,26,34,948],bad:[34,135,156],balanc:[14,38,39],banner:[46,352,872],bar:[6,21],basch:919,base:[0,3,20,21,22,23,24,25,26,34,37,38,39,43,46,49,59,60,62,91,93,98,117,296,344,388,897,901,908,917,918,919,922,927,931,935,939,942,951],basi:[14,18,23,39],basic:934,basicconstraint:37,baz:21,bb463167:42,becaus:[6,17,19,20,21,23,24,25,35,37,38,39,41,43,46,251,342,897,904,906,910,914,929,931,934,938,942,952],becom:[0,6,14,17,21,23,34,39,136,235,260,275,897,918,938,942,946],beeblebrox:34,been:[6,12,14,20,21,23,26,35,124,897,901,915,918,919,924,927,939,943,950,953],beep:[939,941],befor:[2,3,4,5,6,14,15,20,21,22,23,26,35,37,39,41,44,98,100,103,155,288,290,381,389,827,870,898,901,902,904,919,922,929,931,939,942],beforehand:43,began:14,begin:[4,6,15,21,23,28,36,43,91,93,99,100,102,103,203,209,287,288,289,290,344,403,910,921,924,925,934,951],behalf:948,behav:[3,43,407,416,896,906],behavior:[3,14,20,21,28,39,46,228,414,416,918,923,926,927,932,941,945,950],behind:[14,28],being:[3,14,20,21,23,29,39,44,46,245,372,740,901,908,951],belong:[33,161],below:[6,20,21,23,28,36,43,740,903,919,946],benefit:39,berkelei:[906,919],besid:[15,21],best:[14,25,34,38],beta:6,better:[23,24,847,918],between:[3,9,20,21,23,25,26,29,34,35,41,45,136,158,385,885,897,918,932,939,941,942],beyond:[915,922,927,931,953],big:[910,911,912,914,924],biggest:14,bin:[34,904,906,908,917,946],binari:[21,32,906,919],bind:[3,5,20,21,22,39,918,945],bind_dn:3,binddn:3,bindir:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],bindpwd:3,bison:906,bit:[14,20,24,37,46,66,83,142,153,157,359,885,896,910,914,918,921,946],bitwis:[151,740],bjaspan:3,blank:951,bleep:[3,11,939,952,953],block:[14,20,24,48,99,100,102,103,287,288,289,290,918],blocksiz:95,bob:[946,952],bodi:[846,931],book:15,boot:[34,902],bootstrap:21,borrow:939,boston:39,both:[3,12,21,22,23,24,26,28,29,36,37,39,40,43,159,245,251,904,918,919,923,946],bourn:34,box:36,brace:[21,923],bracket:[20,21,28],breviti:911,brian:919,bridg:918,brief:[32,903,927],broken:[14,906],brother:919,brute:[14,23,35],bsd:[918,919],btree:6,buffer:[3,23,43,48,56,98,99,119,170,187,192,193,279,287,300,301,306,331,336,339,374,397,398,404,407,409,538,827,918,924],buflen:[170,187,192,193,374,397,398],bug:[0,23,42,903,904,936],build:[34,39,41,48,49,136,897,903,906,916,917,918,923,927,945],built:[21,24,28,46,48,378,897,904,906,918,924,934,939,945],builtin:[906,918,919],bundl:[21,919],bunni:39,busi:919,byacc:906,c89:905,c:[3,6,19,21,22,23,48,107,228,365,807,813,832,846,883,897,905,906,919,934,941,942,943,946,947,948],ca:[20,21,29,37],cacert:[29,37],cach:[3,14,15,21,23,28,43,44,48,78,138,140,223,224,229,247,264,267,323,325,326,329,331,356,359,360,375,403,414,522,545,549,755,899,903,906,907,913,917,918,926,939,941,942,943,945,946,947,948,951,953],cache_nam:[3,941,942,943],cache_out:[132,154],cacheconf:910,cachenam:[897,947],cachetyp:918,cacreateseri:37,caddr:[825,832,833],cakei:37,california:919,call:[14,16,20,21,23,24,28,34,43,46,91,93,100,103,113,120,122,123,125,126,136,156,158,176,228,245,251,261,268,275,279,282,288,290,294,301,308,317,323,380,381,404,827,870,877,896,897,903,904,918,922,923,924,929,931,932,938,946],callback:[48,260,275,352,380,381,387,856,870,872,876,918,922,931,933],caller:[43,46,71,85,99,100,102,103,117,119,121,136,144,146,245,252,269,279,287,288,289,290,296,301,312,314,330,361,365,366,404,414,827,896,918,925,931,934],camellia128:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],camellia256:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],camellia:[20,918],can:[0,2,3,4,5,6,8,9,10,11,14,15,16,17,18,19,20,21,22,23,24,25,26,28,29,32,33,34,35,36,37,38,39,40,41,43,46,50,56,136,138,154,224,254,271,301,307,331,342,344,366,386,389,400,403,414,416,737,865,866,876,884,896,897,898,900,901,904,905,906,908,910,911,918,920,921,922,923,924,925,927,928,929,930,931,932,933,935,938,939,942,946,950,953],candid:[915,946],cannot:[3,23,24,25,35,37,43,46,91,93,135,151,260,344,414,885,910,939,942,943,948],canon:[4,15,22,23,38,39,192,300,928,932],canonhost_out:194,canonic:[15,21,22,33,43,48,301,389,546,918,942,948],capabl:[32,918,938],capac:25,capath:20,card:[3,20,21,918],care:[3,14,19,28,43,927],carefulli:37,carnegi:919,carri:[3,25,953],cartoon:34,casio:14,cast:[885,896,920,922,923,928,929,930,931,933,935],cat:6,categori:25,caus:[3,4,6,14,20,21,24,25,26,34,35,37,38,39,40,43,48,245,247,388,736,897,901,906,918,919,943,947],caution:3,cb:245,cb_data:[386,888],cb_ret:934,cbc:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],cbdata:934,cbrown:953,cc246071:918,cc246091:918,cc:[223,906,919,945],ccach:[3,23,41,43,48,132,135,164,224,225,226,232,233,234,246,250,251,264,267,321,329,375,383,403,405,414,817,906,917,920,944,948],ccache_typ:21,ccachenam:906,ccapi:[903,919],ccselect:[28,918,923,926,933],ccselect_plugin:[920,923],cd:[42,904,908],ceas:[0,6],cell:14,center:[10,903,919,953],central:0,cert:[16,21,37],cert_fil:948,certain:[23,32,236,906,919,948,953],certauth:[918,926],certauth_plugin:921,certid:21,certif:[3,20,21,29,40,43,48,253,695,912,918,926,948,953],certifi:21,certlabel:21,cf2:48,cflag:[906,945],cfr:919,chain:[20,21,918],challeng:[20,21,40,46,48,366,367,368,370,371,697,700,738,739,876,879,911,918],chang:[2,3,6,9,14,15,19,20,21,22,24,25,26,28,33,34,37,39,46,48,78,136,158,245,260,382,383,620,719,896,904,908,910,917,918,919,927,929,935,937,944,946,952],change_password:[23,26],change_password_for:[382,383],changeov:34,changepw:[3,14,23,26,166,245,300,301,382],channel:[14,21,36,43,46,325,918,946],charact:[3,19,20,21,23,34,38,39,344,397,408,715,944],charg:919,chat:936,check:[12,20,21,23,26,28,34,37,43,48,59,60,153,283,356,359,360,550,904,906,908,914,923,934,935,939,943,946],check_a:930,check_tg:930,checkout:908,checksum:[3,43,48,104,175,202,203,300,301,329,330,331,333,342,343,532,539,657,659,661,662,666,813,856,912,915,918,924],checksum_typ:818,cheetah:908,chiefli:23,chl:[46,367,368,370],chl_out:371,choic:[21,38,43,46,250,942],choos:[14,22,25,34,38,39,43,902,920,938,942,951],chosen:[16,21,22,26,43,46,229,905,911,917,918,920,951],chpass:[3,929],chrand:3,chunk:[114,295],ci:19,cipher:[14,26,48,99,100,102,103,287,288,289,290],cipher_st:[99,100,102,103,287,288,289,290],ciphertext:[25,99,100,102,103,104,287,288,289,290,807,831,911,915],circular:23,circumst:[20,37],citi:919,ckf_:740,ckfrom:175,cksum:[113,129,294,298,413],cksumtyp:[81,96,111,113,114,130,170,294,295,299],cksumtype_cmac_camellia128:789,cksumtype_cmac_camellia256:789,cksumtype_crc32:789,cksumtype_descbc:789,cksumtype_hmac_md5_arcfour:789,cksumtype_hmac_sha1_96_aes128:789,cksumtype_hmac_sha1_96_aes256:789,cksumtype_hmac_sha1_des3:789,cksumtype_hmac_sha256_128_aes128:789,cksumtype_hmac_sha384_192_aes256:789,cksumtype_md5_hmac_arcfour:789,cksumtype_nist_sha:789,cksumtype_rsa_md4:789,cksumtype_rsa_md4_d:789,cksumtype_rsa_md5:789,cksumtype_rsa_md5_d:789,cksumtype_sha1:789,cksumtypep:390,ckto:175,claim:[651,655,919],clang:918,clarifi:37,clariti:946,clean:[23,268,269,386,908,918,934],cleanli:918,cleanup:[46,934],clear:[3,6,11,15,36,46,48,136,156,377],clearpolici:[3,19],cleartext:[808,824,832],click:34,client1:37,client2:37,client:[3,12,14,16,18,20,21,22,23,25,26,28,31,32,34,35,36,38,39,40,41,43,46,48,145,154,223,224,235,241,242,258,260,264,267,275,276,277,330,333,359,363,403,651,652,740,807,808,813,825,826,833,836,845,846,897,901,903,906,910,911,912,917,918,919,920,921,923,926,928,931,933,939,942,943,945,946,948,951,953],client_aware_channel_bind:21,client_aware_gss_bind:918,client_cert:37,client_kei:918,client_keytab:43,client_princ:[46,300],clientauth:21,clientkei:37,clifford:953,clock:[21,34,48,267,356,360,898,931,942],clockskew:[15,21,359,915,934,942],close:[21,32,48,71,85,132,137,138,148,164,167,265,301,307,755,915,929,935],clpreauth:[28,926],clpreauth_mymech_initvt:923,clpreauth_plugin:922,cm:[467,476,477,479,480,481,482,918],cmac:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],cmd_path:946,cn:[5,20,22,37],cname:[33,34,38,39],code:[0,20,21,23,41,43,46,48,49,50,56,62,64,65,67,69,72,73,74,76,77,78,79,81,82,84,85,86,87,88,89,90,91,92,93,95,96,97,98,99,100,102,103,104,105,106,107,108,111,112,113,114,115,117,118,119,121,124,125,126,129,130,133,134,135,141,142,145,147,148,149,150,151,152,153,154,155,156,157,158,159,161,162,163,164,166,169,170,171,172,173,174,175,176,177,178,180,181,182,183,184,185,187,189,192,193,214,217,223,224,227,229,231,235,251,260,261,262,264,265,266,267,268,271,272,273,274,275,276,277,278,279,280,282,287,288,289,290,294,295,296,298,299,300,301,302,303,305,306,308,310,311,314,315,316,317,318,321,322,323,324,325,326,327,328,329,330,331,332,333,335,337,338,339,342,344,345,347,352,354,355,356,357,358,359,360,361,363,364,374,375,376,377,378,382,383,384,385,389,396,397,398,400,401,402,403,404,405,406,407,408,409,410,414,730,836,837,865,885,896,903,905,906,918,919,922,923,924,927,929,931,933,934,935,936],coerc:915,coexist:19,collect:[21,43,48,132,154,728,729,903,918,920,941,942,943,947,951,953],collis:[48,901],colon:[5,20,21,28,39,152,344,346,420,953],column:6,com:[3,6,9,11,16,20,21,22,23,28,35,37,38,39,41,42,911,912,918,919,938,939,951,952,953],com_err:[837,906,918,923],combin:[3,8,20,23,26,43,48,254,911,943],come:[21,46,359,904,905,938],comma:[3,6,10,20,21],command:[4,8,9,10,14,15,20,21,22,23,24,26,29,32,34,35,37,41,898,900,903,904,905,906,918,937,938,939,941,944,946,948,953],command_opt:[5,6],commenc:34,comment:[0,15,21],commerci:[21,37,919],commit:[9,919,929],common:[21,23,25,34,43,906,919,922,938,952],common_appdata:21,commonconfig:21,commonli:[8,41],commun:[0,21,23,25,29,34,37,43,865,897,903,919,920,936],compani:939,companion:36,compar:[47,48,129,298,911],comparison:21,compat:[8,20,21,36,43,904,906,918,928,930,948],compil:[0,904,905,906,907,918,919,945,946],compile_et:906,complet:[5,6,14,20,21,23,39,43,45,158,272,274,359,375,401,402,738,903,906,907],complex:918,compli:919,complic:[37,906],compon:[19,21,28,37,38,43,46,48,92,93,223,344,345,350,388,645,708,710,763,910,914,918,919,934,939,951],component1:[910,914],component2:[910,914],compos:37,composit:918,compress:905,compromis:[14,17,21,32,897,902],comput:[14,20,21,29,43,44,46,48,91,117,129,229,296,298,912,919,922,931,938,939],concaten:[731,911,924],concatent:924,concept:[916,926],concern:[25,35,919,939],concis:934,concret:908,concurr:[20,24],condit:[37,154,301,918,919,946],conduct:29,conf:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],conf_keyfil:5,conf_req_flag:43,conf_stat:43,confidenti:[26,43,918],config:[20,21,23,141,155,269,378,903,906,917,918,924,937,940],configur:[3,4,5,9,14,16,17,19,20,21,23,24,25,30,31,38,41,43,46,48,50,78,154,167,194,251,261,269,388,414,416,563,564,898,901,903,904,905,907,908,918,923,926,935,939,942,943,946,950,952,953],confirm:[2,3,5,6,23,130,299,918,948],conflict:[15,28,359,924],conform:[21,905,918,944],confound:104,confus:919,confusingli:46,confvalid:903,conjunct:948,connect:[3,4,5,8,12,20,23,32,34,38,43,48,897,901,918,919,939],consequ:14,consequenti:919,consid:[0,14,21,24,33,39,41,342,901,906,910],consider:[39,45],consist:[21,39,344,900,905,910,911,918,925,932],consol:20,consolid:0,consortium:[936,953],constant:[46,57,58,727,733,821],constitut:919,constrain:[3,333,547,654,918,948],constraint:[919,951],construct:[0,43,46,277,279,329,404,865,866,918,923,948],consult:[21,932],consum:[24,896,927],contact:[3,7,8,14,20,21,23,29,39,260,897,920,936,949],contain:[3,4,5,6,8,9,15,19,20,21,22,23,24,28,29,33,34,37,38,39,41,43,46,48,54,67,72,76,152,154,169,172,173,183,184,195,231,245,247,276,279,300,301,320,330,336,342,344,355,356,357,360,363,365,375,404,414,847,876,889,897,898,900,901,903,904,905,906,907,908,910,911,914,915,919,923,924,933,934,936,938,939,941,942,946,947,948,951,952,953],container_dn:3,container_reference_dn:5,containerdn:3,containerref:5,contempl:919,content:[0,6,9,11,12,14,23,27,34,37,43,44,46,48,82,84,124,133,137,147,148,174,175,177,178,180,182,183,198,199,200,201,202,207,208,212,215,221,280,333,334,805,811,818,827,848,859,890,897,910,912,914,919,924,942,943],context:[21,41,43,44,46,48,49,50,51,52,53,54,55,56,59,60,61,66,70,75,83,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,172,173,174,175,176,177,178,180,181,182,183,184,186,188,189,190,194,195,196,197,198,199,200,201,202,203,204,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,245,246,247,248,250,251,252,253,257,260,261,264,265,267,276,277,278,279,280,281,283,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,367,368,369,370,371,372,375,376,378,379,380,381,382,383,384,385,386,387,388,389,393,404,405,406,407,408,409,410,411,412,413,414,417,418,419,420,564,793,794,795,796,797,798,799,800,838,865,866,872,876,888,918,920,922,923,925,931,932,933],context_handl:[43,924],contigu:43,continu:[2,6,17,34,911,918,919,946],contract:919,contrari:[43,46],contribut:[101,107,119,916,919,953],contributor:[909,919],control:[4,14,15,18,19,20,21,22,26,28,34,36,37,38,41,43,46,243,279,404,414,906,907,918,920,925,926,927,930,932,933,934,935,950],convei:[14,23,39,43,837,863,918,919],conveni:[46,323,368,371,904],convent:[39,406,934],convention:953,convers:[21,911],convert:[14,21,38,43,48,169,258,389,918,951],cooki:[599,913,918,931],coordin:924,copi:[15,17,23,26,29,32,34,37,41,43,48,86,88,269,272,342,401,902,910,919,927,934,939,946],copyright:[903,905,919,953],core:[922,927,931,934,936],corpor:[919,953],correct:[4,10,14,21,23,33,34,41,124,735,897,906,918,919],correctli:[12,43,865,866,896,918,938],correspond:[6,19,21,37,39,43,44,46,56,152,245,263,342,884,908,911,918,923,924,929,953],corrupt:[6,17,918],cost:[23,29,906,919],could:[0,14,16,17,21,25,28,33,34,35,39,901,918,923,938,939,946],couldn:12,count:[3,6,43,48,87,89,111,286,910,914],counter:[3,35],countermeasur:32,counterpart:[19,33],countri:919,cours:17,courtesan:919,cover:33,cpp:906,cppflag:906,cppopt:906,cpu:40,cpw:[3,14],crash:[17,21,34],crawdad:919,crawford:919,crc:[14,26],creat:[3,4,7,12,14,15,19,20,21,22,23,24,26,28,31,32,35,43,47,48,67,72,76,93,113,114,125,126,135,138,172,173,174,175,176,177,178,180,182,183,205,236,262,265,271,294,295,307,308,324,331,345,359,363,364,375,387,400,414,710,897,898,900,904,908,911,915,918,919,920,921,922,924,925,926,928,929,930,931,932,933,934,935,936,938,939,942],create_polici:23,creation:[14,21,23,37,911],creativ:919,creativecommon:919,cred:[46,48,150,151,153,159,166,232,233,234,235,260,264,267,272,275,321,382,401,403,405,414,531,918,946],cred_handl:[43,924],cred_stor:43,cred_usag:43,cred_usage_stor:43,creddata:354,credenti:[3,8,12,16,20,21,23,28,33,35,37,45,48,138,166,177,206,207,223,224,229,321,329,333,354,375,402,405,440,549,618,653,747,823,824,825,826,877,896,899,900,901,903,906,913,918,922,924,925,926,931,939,941,942,943,945,946,947,948,951,953],credentials_cach:3,creds_out:[354,405],criteria:[37,897],critic:[46,936],crl:[20,21],cron:[17,20,34,39],cross:[3,20,21,342,343,359,906,910,918],crt:[20,21],crypto:[14,121,191,903,906,918,919],crypto_entri:834,crypto_test:919,cryptograph:[14,43,918,919],cryptographi:[14,40],cryptosystem:14,csv:[6,918],ct:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],ctime:[808,813,836],ctx:[43,72,73,76,77,86,87,88,89,171,176,213,228,270,271,272,273,274,275,276,277,278,279,346,365,366,367,368,369,370,371,372,373,379,399,400,401,402,403,404,417,418,419,420,877],ctype:[109,110,127,131,168,413],cuba:919,cultur:919,current:[2,3,6,8,9,11,14,20,21,22,23,28,39,48,136,179,330,346,356,360,382,440,742,889,897,900,906,910,915,918,922,925,926,931,939,944,951,953],curri:15,curs:906,cursor:[48,139,150,158,163,164,314,318,815,817],curv:[21,40],cusec:[808,813,836],custom:[21,908,917,918,921],cut:39,cve:918,cybersaf:[540,919],cycl:918,cygnu:[664,919],d:[3,5,6,7,8,10,19,28,898,906,918,923,939,943,953],daemon:[8,19,20,21,23,31,36,37,38,897,902,918,923,953],daffodil:[15,939],dai:[3,5,21,23,37,48,396,898,939,953],daili:14,daisi:39,dal:927,damag:[897,919],danger:[17,946],danilo:919,dash:21,data:[3,6,9,14,20,21,22,23,24,26,32,43,44,46,48,63,79,80,98,113,114,117,119,120,121,123,129,130,141,151,153,155,169,178,203,208,212,224,245,253,257,258,260,262,275,294,295,296,298,299,300,323,326,329,330,331,333,335,340,341,352,354,356,359,360,368,371,375,376,380,381,382,383,386,388,393,405,467,479,480,481,537,538,678,722,746,793,794,797,811,813,821,823,826,827,829,832,833,836,838,845,846,856,859,863,865,866,868,869,872,875,877,886,891,897,901,902,906,910,911,912,914,918,919,921,922,923,926,930,931,935,943],data_length:116,data_out:321,data_set:43,databas:[2,4,5,6,7,8,9,10,12,15,18,19,20,21,22,26,28,30,31,32,35,37,43,900,902,903,906,907,917,918,919,926,929,931,942,945,946,953],database_modul:[20,24],database_nam:[20,23,34],datadir:906,datarootdir:906,datatyp:45,date:[3,6,8,20,21,23,26,37,167,224,398,832,899,918],datebas:4,david:[15,938,939,953],db2:[3,6,20,23,35,903,917,918],db3:906,db:[24,35,906],db_185:906,db_arg:[3,4,6,8,10],db_header:906,db_lib:906,db_librari:[20,22,24],db_module_dir:20,db_princ_arg:3,dbadmin:19,dbdefault:5,dbmatch:21,dbmodul:[3,22,23,24,35],dbname:[3,6,10],dbutil:919,dc:[20,22],dce:[43,48,641,680,918],dcmd_path:946,dd:898,de:[13,20,26,41,467,918,919],deactiv:20,deal:[897,919],dealloc:[92,925,932],debian:[31,918],debug:[3,7,8,9,20,28,905],dec:[34,35,898],dec_err:324,dec_error:355,decid:[34,39,245,939],decim:[6,43,910,953],decis:[30,919,928,932,953],declar:[43,924],decod:[21,46,48,159,184,359,910,921,923],decompos:538,decreas:[21,900],decrement:48,decrypt:[3,35,43,48,79,354,364,827,883,901,918,946,948],dedic:34,default_ccache_nam:[21,136,897,953],default_client_keytab_nam:[15,21,900],default_cr:43,default_domain:21,default_kdb_fil:907,default_kdc_enctyp:907,default_keytab_nam:[21,900,907],default_principal_expir:[20,898],default_principal_flag:[19,20,918],default_profile_path:907,default_rcache_nam:[21,901],default_realm:[21,28,33,34,925,934],default_tgs_enctyp:[21,26],default_tkt_enctyp:[21,26],default_valu:[59,60],defccnam:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],defcktnam:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],defeat:40,defens:25,defer:[43,921,925,928,932],defin:[3,12,20,21,33,34,39,43,101,119,228,740,901,906,910,911,923,927,934,935,946],definit:[10,16,20,903,919,928,930],defktnam:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],del_polici:3,delai:[24,39,906,918,942],deleg:[3,20,21,333,547,654,910,918,939,943,948],delegated_cred_handl:43,delent:11,delet:[2,3,5,6,11,19,21,23,151,901,918,919,938,941,946,953],delete_polici:23,delete_princip:23,delimit:[21,311],delold:[2,14,26],delpol:3,delprinc:[3,23],delstr:3,delta:[20,48],deltat:187,deltatp:391,demand:414,demonstr:[12,14],deni:[3,19,25,28,35,928,932,946],denial:21,denot:[6,19,898,911],depart:919,depend:[25,33,39,43,46,126,365,373,740,876,905,906,917,918,923,935,938,939],deploi:[36,37,38,904],deploy:[14,24,37],deprec:[14,20,26,70,75,94,120,122,123,131,168,186,188,190,191,196,197,225,226,232,233,234,239,281,309,340,341,351,353,393,411,413,918],der:[911,921,924,931],der_out:[323,325,326,331],deriv:[3,6,14,20,25,48,99,100,102,103,113,129,287,288,289,290,294,298,911,915,918,919,944],des3:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],descend:[897,901],describ:[0,3,14,16,21,23,24,25,28,32,34,37,43,375,406,827,836,837,896,910,919,922,923,924,926,934,939,946],descript:[32,39,43,836,903,917,918,920,921,922,925,927,928,929,930,931,932,933,934,935],descriptor:[62,363,364,375],deseri:48,design:[28,34,46,315,897,901,953],desir:[14,15,23,28,43,119,121,250,251,329,906,918,933,946],desired_mech:[43,924],desired_nam:43,desired_object:43,desktop:46,dest_ctx:179,destdir:904,destin:[32,904,918],destroi:[23,43,48,136,147,148,386,414,897,918,920,921,922,925,928,929,930,931,932,933,935,937,941,942],destroy_polici:23,detach:8,detail:[10,14,15,22,24,26,28,33,34,36,262,738,897,903,905,918,920,921,922,925,928,929,930,931,932,933,934,935,946],detect:[6,8,14,323,325,326,331,356,360,901,906,918,924],determin:[3,4,5,6,8,20,21,23,24,28,34,43,48,62,102,105,117,136,154,230,231,261,289,359,385,389,416,889,897,900,901,904,906,911,914,918,921,925,928,932,933,939,953],dev:[20,21,41,953],develop:[0,904,916,918,919,936,953],devic:[3,20,21,46,655,656],devicenam:20,dfl:[21,901,953],dget_tgt_via_passwd:946,di:19,dict:[3,21],dict_fil:[4,20,935],dictat:23,dictionari:[20,21,23,29,30,34,35,40,918,935,942],did:[23,34,223,267,342,939],didn:[12,28],differ:[3,6,12,21,25,26,28,33,34,37,38,39,43,45,48,107,119,159,265,375,385,865,901,904,906,923,931,932,938,939,942,946,953],diffi:[20,21,942],difficult:35,difficulti:38,digest:[20,919],digit:[898,953],digitalsignatur:[21,37],dir:[20,21,37,897,906,917,942,953],direct:[21,22,23,28,41,48,919,924,934,953],directli:[3,18,20,21,23,29,34,43,46,375,618,924,931,942,947],directori:[3,5,12,20,21,22,28,33,34,37,169,342,897,901,905,907,908,917,918,938,946,950,951,952,953],dirnam:[21,897],dirpath:897,disabl:[3,14,20,21,23,24,26,28,34,37,38,39,41,380,381,386,550,901,904,906,918,926,942,950,953],disable_encrypted_timestamp:[21,25,40],disable_fresh:[37,942],disable_last_success:[20,22,35],disable_lockout:[20,22,35],disable_pac:[20,918],disallow:19,disallow_forward:5,disallow_svr:23,disassoci:[4,10],disast:39,disclaim:919,disclosur:[19,918],discoveri:[25,33,34,918],discuss:[34,901,919,927,936],disjoint:0,disk:[4,5,6,15,17,24,32,34,46,897,902,905],dispatch:924,displai:[2,3,5,9,11,23,37,42,46,245,730,900,910,918,919,942,943,949],display:169,disrupt:14,dist:905,distclean:904,distinct:23,distinguish:[5,21,919],distribut:[10,903,904,905,906,907,918,919,939,953],distributor:919,divid:915,dll:[28,923,924,934],dn:[3,5,20,21,22,25,30,33,34,35,39,44,333,663,906,918],dns_canonicalize_hostnam:[21,38,918],dns_canonicalize_realm:918,dns_lookup_kdc:21,dns_lookup_realm:[21,39],dns_uri_lookup:[21,39],dnsname:21,doc:[22,42,908],document:[5,20,21,29,33,34,43,896,904,906,915,918,919,923,936],doe:[3,6,8,10,14,20,21,22,23,24,25,26,34,37,38,39,40,43,46,56,119,144,152,160,301,311,313,345,375,389,397,414,897,900,904,906,911,918,919,923,924,925,932,934,938,939,946],doesn:[2,6,23,161,897,938],domain:[12,15,20,21,33,34,36,37,38,39,918,939],domain_realm:[28,33,39,951],don:[12,712,715,897,904,906,938,946,953],donat:[23,919],done:[8,22,23,32,34,39,897,906,922,931,934,946,953],dot:38,doubl:898,down:39,download:[8,919],downstream:[23,918],downtim:14,doxygen:[0,908],dprinc_look_ahead:946,dr:14,draft:[694,697,700,918],drift:15,drop:918,dry:6,dsa:476,dst:148,due:[14,19,23,41],dug:919,dugsong:919,dump:[4,7,8,17,20,24,34,917,918],dump_fil:4,dumpfil:[6,23,906],dumptyp:6,dup:20,duplic:[48,826,901],durabl:[20,24],durat:[3,20,21,884,942,946],dure:[3,4,8,17,20,21,23,26,34,35,40,43,352,380,414,719,910,911,918,922,929,939,946],dynam:[21,923,926,928,934],e19253:42,e1:105,e2:105,e2big:119,e:[2,3,6,9,11,14,19,20,21,22,23,33,34,37,38,39,46,870,897,902,904,905,906,911,912,934,938,942,943,946,948,953],e_data:[836,931],each:[2,3,6,8,10,15,19,20,21,23,24,25,26,28,33,35,37,39,43,44,46,252,263,265,352,755,897,900,902,904,910,911,915,918,919,923,927,928,929,933,938,939,942,943,946,948,951,952],ear:919,earli:14,earlier:[20,23,26,34,224,932],earliest:[6,153,915],eas:36,easi:[14,17,25,35,939],easier:[0,14,918],easili:[14,34,904,918],eavesdrop:43,eavesdropp:901,ebaa:42,eblock:[186,188,190,196,197,281,351,353,393,411],echo:[352,361],edata:931,edit:[2,11,12,31,906,907,938],editor:0,edt:3,edu:[0,3,5,12,14,15,19,20,21,23,24,28,32,34,42,918,919,934,936,938,939,946],educ:33,edwards25519:[21,40,919],edwards25519_t:919,effect:[14,19,20,21,23,37,39,731,897,901],effici:918,effort:25,eight:33,einval:[260,373,390,392,394,395],either:[15,20,21,22,23,25,26,34,35,36,37,41,43,44,195,245,253,274,325,326,327,331,402,403,407,731,866,897,904,915,919,923,928,932,939,946,952],eku:[20,21],elaps:3,element:[43,46,48,189,320,412,827,873,911],elements_stor:43,elimin:[14,40],ellipt:40,els:[34,923,938,939,946],elsewher:17,emac:906,email:[0,642,938],emailprotect:21,embed:678,empti:[3,6,19,20,21,23,36,43,46,48,93,229,231,279,345,388,389,404,414,901,906,910,942],en:[42,918],enabl:[3,4,8,14,15,20,21,22,23,24,25,28,34,36,37,39,40,41,43,55,78,897,905,906,918,921,926,946,953],enable_onli:[21,28],enc:[3,6,20,199,301,826,918],enc_err:324,enc_errbuf:355,enc_padata:832,enc_part2:[376,823,845,883],enc_part:[807,823,845,883],enc_tkt:[300,301],encdata:911,enckdcreppart:832,enckrbcredpart:825,enclos:[20,21,898],encod:[21,43,46,48,189,300,323,325,355,541,883,890,910,911,921,924,931],encompass:43,encount:[21,34,943],encourag:21,encrypt:[2,3,6,14,15,17,21,23,25,29,30,32,34,36,40,43,46,48,79,95,98,99,100,112,113,114,116,124,125,126,129,130,153,229,280,287,288,294,295,298,299,310,315,325,326,357,359,394,480,481,539,599,671,750,808,809,823,825,826,827,832,833,845,846,883,900,901,902,903,907,911,912,918,919,922,924,931,936,943,948,953],encrypted_challeng:21,encrypted_challenge_ind:[20,918],encrypted_timestamp:21,enctyp:[6,11,14,20,21,23,48,95,97,98,99,101,104,107,111,112,116,118,125,126,192,193,211,224,280,287,310,315,378,411,831,833,846,848,910,914,917,918,922,948],enctype_aes128_cts_hmac_sha1_96:[447,789],enctype_aes128_cts_hmac_sha256_128:789,enctype_aes256_cts_hmac_sha1_96:[448,789],enctype_aes256_cts_hmac_sha384_192:789,enctype_arcfour_hmac:789,enctype_arcfour_hmac_exp:789,enctype_camellia128_cts_cmac:789,enctype_camellia256_cts_cmac:789,enctype_des3_cbc_env:789,enctype_des3_cbc_raw:789,enctype_des3_cbc_sha1:789,enctype_des3_cbc_sha:789,enctype_des_cbc_crc:789,enctype_des_cbc_md4:789,enctype_des_cbc_md5:789,enctype_des_cbc_raw:789,enctype_des_hmac_sha1:789,enctype_dsa_sha1_cm:789,enctype_md5_rsa_cm:789,enctype_nul:[101,229,789],enctype_out:229,enctype_rc2_cbc_env:789,enctype_rsa_env:789,enctype_rsa_es_oaep_env:789,enctype_sha1_rsa_cm:789,enctype_unknown:789,enctypep:392,end:[6,20,21,23,24,30,33,34,39,92,93,164,332,825,833,846,884,906,910,914,915,918,927,946,953],endian:[910,911,912,914,924],endors:919,endpoint:[62,919],endtim:[224,884,910],energi:919,enforc:21,enforce_ok_as_deleg:[21,918],engin:39,enoent:336,enomem:[119,223,231,302,323,325],enough:[3,23,26,99,102,167,287,289,766],ensur:[14,15,17,20,23,24,25,26,34,37,46,171,865,866,925,932,939],enter:[3,5,10,14,23,34,37,325,326,331,361,924,938,939],enterpris:[38,43,345,710,918,942,948],entir:[3,14,20,39,538,910,931],entiti:[43,919],entri:[3,8,9,11,12,14,15,19,20,21,22,23,24,26,32,34,35,37,38,39,40,41,43,46,48,153,173,195,198,200,220,245,309,315,320,322,325,326,331,337,352,359,414,832,850,854,897,900,902,911,912,915,918,930,931,939,943,946],entropi:918,enumer:[14,26],env:[21,37,41,953],envelop:[467,479,480,481],environ:[14,15,20,21,23,24,26,28,30,34,35,37,38,41,43,56,136,268,269,282,386,387,897,900,901,904,917,918],envvar:21,eperm:[928,932],epoch:[48,885],eq:22,equal:[15,24,914,918,946],equip:953,equival:[20,36,166,382,383,918],erang:336,err_fmt:[21,918],erron:41,error:[3,20,21,24,34,37,39,43,48,49,50,56,62,64,65,67,69,72,73,74,76,77,78,79,81,82,84,85,86,87,88,89,90,91,92,93,95,96,97,98,99,100,102,103,104,105,106,107,108,111,112,113,114,115,117,118,119,121,124,125,126,129,130,133,134,135,137,141,142,145,147,148,149,150,151,152,153,154,155,156,157,158,159,161,162,163,164,166,169,170,172,173,174,175,176,177,178,180,181,182,183,184,185,187,189,192,193,214,217,223,224,227,229,231,235,236,238,243,248,260,261,262,264,265,266,267,268,271,272,274,275,276,277,278,279,280,282,287,288,289,290,294,295,296,298,299,300,301,302,303,305,306,308,310,311,314,315,316,317,318,321,322,323,324,325,326,327,328,329,330,331,332,333,335,337,338,339,342,344,345,347,352,354,356,357,358,359,360,361,363,364,374,375,376,377,378,382,383,384,385,389,396,397,398,400,401,402,403,404,405,406,407,408,409,410,414,543,615,617,713,714,836,837,865,901,903,906,918,922,923,928,929,931,932,939,948],error_t:919,es:[21,942],escal:918,escap:715,especi:[15,26,34,38,918],essenti:20,est:[35,898],establish:[37,43,901],et:[903,906,919],etc:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],etyp:[6,229,378,672,918,948],etype_list:[244,840],etype_list_length:[244,840],euid:[21,901,917],evalu:21,even:[14,20,21,23,25,28,34,38,39,43,245,388,896,898,901,918,919,942,946],event:[39,48,918,919,931],eventu:[26,39],everi:[20,21,23,32,34,48,318,897],evid:43,evolut:918,exact:[22,905],exactli:[21,34,153,407,748,749,753,911,946],examin:[21,37,922,931],exampl:[3,5,6,9,14,15,16,20,21,22,23,24,26,28,32,34,35,37,38,39,41,43,56,100,103,288,290,897,898,901,904,905,918,919,923,934,938,939,942,946,953],exce:[896,898],except:[3,19,21,23,37,39,43,329,918,919,924,946],excess:904,exchang:[34,40,48,224,247,279,363,375,437,877,911,931],exclud:[6,17,32,918],exclus:[3,915,919,942,946],exec:[906,945,946],execprefix:906,execut:[3,6,22,34,46,380,905,906,945],exemplari:919,exhaust:32,exist:[0,2,3,5,6,14,15,20,21,22,23,26,28,32,34,35,43,46,48,137,147,155,329,330,359,363,364,375,407,414,897,902,910,918,924,942,944,946],exit:[3,10,11,897,918,939,943,948],exp:[3,20,21,26,37],expand:[21,915,918],expans:[906,918],expdat:3,expect:[14,21,34,41,267,301,342,343,730,908,922,927,939],expected_nonc:882,expens:[20,25,35],experi:[0,14,39,918],experienc:[0,933],experiment:918,expir:[2,3,6,15,19,20,21,23,26,33,37,43,46,48,224,243,260,832,884,897,898,901,910,918,939,942,943,946,953],expiri:[14,245,918],explain:34,explicit:[14,19,21,22,24,28,39,919],explicitli:[3,14,19,23,28,34,44,253,906,918,928,929,930,939],expos:[3,6,14,46,848,942,946],express:[3,21,898,919],extend:[20,21,37,48,420,889,924,953],extendedkeyusag:37,extens:[37,39,247,908,918,924],extent:919,extern:[20,22,43,910],extfil:37,extra:[19,39,40,766,905],extra_address:21,extract:[3,15,19,34,229,900,918],extrem:3,eytab:3,f:[2,4,5,6,7,8,11,14,22,33,34,908,918,939,942,943,946,948],facil:[4,15,20,43,918],facilit:918,factor:[21,911],fail:[2,3,6,14,15,20,21,23,24,35,38,39,43,46,228,260,279,342,354,404,865,904,906,918,924,925,939,941,946],fail_count:6,failov:39,failur:[3,6,14,24,35,46,119,129,130,159,260,298,299,310,407,408,409,918,919,924,933,935],failurecountinterv:[3,35],failuretim:3,fake:[21,46],fall:[39,40,897,918],fallback:[3,20,21,38,40,46,918,925],fallback_realm:925,fals:[14,20,21,23,26,28,33,36,37,38,39,43,52,54,105,109,110,127,128,160,192,245,283,284,285,319,348,349,350,362,388,416,952],famili:[20,186,188,190,191,196,197,250,251,281,351,353,411,933],famou:34,far:37,fashion:[26,29,919,946],fast:[20,21,25,36,37,48,229,544,599,910,918,922,931],fast_avail:910,fast_ccache_nam:247,faster:[25,39,897,904],fatal:154,fd:[363,364,375],fdii:939,feasibl:34,featur:[24,29,368,371,916,919,936],feb:9,februari:896,fee:919,feedback:0,fellow:919,fenc:923,fences_wicker_initvt:923,fermi:919,fetch:[4,5,6,10,11,21,23,71,141,414,918],few:[906,938,953],ff:939,fiat:919,fiction:923,fictiti:939,field:[3,6,20,21,35,36,37,39,44,46,48,153,256,310,330,331,343,352,356,357,359,360,412,749,753,889,910,911,914,915,918,922,923,931,935,939,951],file2:[901,915,953],file:[3,4,5,6,7,9,10,11,12,14,15,16,17,19,22,23,24,28,29,30,31,37,38,39,41,46,48,50,152,262,269,317,321,363,364,375,378,405,755,897,898,899,900,901,903,904,905,906,907,908,916,917,918,919,920,921,922,923,924,925,927,928,929,930,931,932,933,934,935,937,938,939,946,951,952,953],filenam:[2,3,5,6,7,8,15,20,21,28,34,36,37,41,43,387,897,901,918,953],filesystem:[20,23,34,37,915,917],fill:[46,48,50,56,119,121,134,150,152,224,230,231,303,306,311,327,347,357,358,390,391,394,396,397,914,915,923,934],filter:[20,21],find:[12,21,23,38,39,43,48,50,910,915,918,920,938,939,942,946],fine:[39,43],fini:[920,921,922,925,928,929,930,931,932,933],finish:48,fip:918,fire:39,firewal:[29,39,41],firm:919,first:[3,6,9,12,16,19,20,21,22,23,26,28,34,37,38,39,43,44,52,53,93,105,136,228,258,279,300,322,348,349,350,361,362,386,404,763,827,900,901,906,908,910,911,912,914,915,918,919,921,923,924,925,930,932,939,944,946,951,953],fit:[311,919],five:[3,21,34,898,901,929,944],fix:[6,915,918],flag:[2,3,5,6,11,14,19,20,21,22,23,25,26,28,33,35,39,40,43,46,48,55,62,69,74,78,151,153,192,269,279,325,326,327,331,343,352,354,356,359,360,363,364,404,728,729,730,731,735,736,737,738,740,747,748,825,826,827,832,833,840,879,894,897,906,918,922,931,939,941,942,943,945,946],flag_rsa_protocol:942,flagnam:19,flat:897,flavor:3,flexibl:[21,38],flip:14,flush:934,fmt:[346,379,417,418,419,420],fn:386,fnal:919,folder:21,follow:[2,3,6,10,14,15,19,20,21,22,23,24,25,26,28,29,34,35,36,37,38,39,43,62,228,245,248,263,333,344,345,352,359,361,389,408,897,898,900,901,903,904,906,907,910,911,912,914,918,919,923,924,927,934,936,938,939,942,943,945,946,950,951,952,953],foo:[3,6,21,23],foobar:[39,906,952],fool:25,foot:923,for_us:948,forbid:3,forbidden:21,forc:[3,5,8,9,11,14,19,20,21,23,25,26,35,39,40,136],foreground:[4,8],forev:3,forget:[5,34,156],fork:[10,34,946],form:[0,3,15,20,21,24,25,28,29,34,39,43,152,317,325,326,331,373,389,642,876,897,902,911,918,919,942,951,953],format:[0,3,6,19,20,21,36,39,43,48,321,346,405,406,417,419,420,733,738,740,879,889,897,899,900,901,906,908,912,916,918,923,924,946,948,953],former:388,formul:21,forth:21,forward:[3,15,20,21,23,33,34,36,38,43,48,354,531,548,840,918,939,942,943,946,953],found:[7,10,12,20,21,23,34,39,59,60,151,153,154,195,301,315,359,906,915,918,938,939,946,947,953],foundat:919,four:[21,24,35,40,910,911,912,915,924,946],fqdn:29,fraction:25,frame:910,framework:[43,918,919],fred:28,free:[46,47,48,49,65,67,72,76,91,93,111,115,141,143,145,150,153,169,172,173,174,175,177,178,180,181,182,183,194,195,224,227,229,236,261,272,275,280,286,310,315,317,321,322,324,325,326,327,328,329,330,331,332,335,338,339,344,345,354,355,356,357,359,360,363,375,389,401,403,405,406,408,919,921,923,934],free_ind:921,free_list:925,free_modreq:931,free_restrict:928,free_str:[932,934],free_valu:934,freed:[44,57,58,61,78,85,106,136,144,146,198,199,200,201,202,204,207,208,210,211,212,215,216,217,218,219,221,222,228,262,312,334,365,366,368,371,865,866],freeli:919,frequent:[14,33,38,39,885,938],fresh:[0,15,17,20,43,598,913,918,942,946],fri:9,friend:939,friendli:918,friendlier:918,from:[0,2,3,4,5,6,7,8,9,10,11,17,19,20,21,22,23,24,25,28,29,32,34,35,37,38,39,41,43,44,46,48,49,93,99,100,101,102,103,113,119,121,129,148,166,169,180,181,183,195,241,245,250,258,269,287,288,289,290,294,298,322,327,330,342,346,352,356,357,358,359,360,375,376,378,380,382,383,414,420,440,832,845,846,897,900,901,904,905,906,910,911,915,916,918,919,920,921,922,924,926,927,929,934,936,938,939,942,944,946,948,951,953],from_mast:[8,917],front:[20,344],fsanit:906,ftp:[32,34],fubar:[21,953],fulfil:946,full:[4,8,9,14,20,23,39,48,331,657,906,918,927,938,946],fulli:[3,15,19,21,23,29,32,34,35,46,942,953],fullname_out:143,fulvio:42,func:[63,80],fund:919,fundsxpress:919,furnish:919,further:[10,34,901,952],furthermor:[14,245,919],futur:[21,23,26,37,43,156,228,889,918,925],fx:[48,911,918,931],g10:919,g:[3,6,19,21,22,33,34,37,39,46,870,897,902,904,905,906,911,912,934,938,946,953],g_accept_sec_context:919,g_acquire_cr:919,g_canon_nam:919,g_compare_nam:919,g_context_tim:919,g_delete_sec_context:919,g_dsp_name:919,g_dsp_statu:919,g_dup_nam:919,g_exp_sec_context:919,g_export_nam:919,g_glue:919,g_imp_nam:919,g_imp_sec_context:919,g_init_sec_context:919,g_initi:919,g_inquire_context:919,g_inquire_cr:919,g_inquire_nam:919,g_process_context:919,g_rel_buff:919,g_rel_cr:919,g_rel_nam:919,g_rel_oid_set:919,g_seal:919,g_sign:919,g_store_cr:919,g_unseal:919,g_userok:919,g_util:919,g_verifi:919,gain:[14,25,34,928,930,939],gcc:906,gen_sym:946,gener:[2,9,12,14,15,17,19,20,21,23,25,26,32,35,41,43,48,113,125,126,260,283,294,327,330,342,440,523,524,525,526,824,841,856,897,901,903,904,905,906,908,910,918,919,922,926,931,936,939,946,951],generalizedtim:911,generalstr:37,generic_trusted_ca:[20,21],gennadi:946,genrsa:37,german:918,get:[3,12,14,16,19,20,21,32,33,35,38,39,48,59,60,163,236,254,258,275,906,918,922,925,931,938,939,942,946,953],get_cooki:[918,931],get_cr:46,get_princip:23,get_tgt_via_passwd:946,get_valu:934,getaddrinfo:38,getdat:[3,5,6,19],gethostnam:[38,43],getnameinfo:38,getopt:903,getpol:3,getprinc:[3,6,14,26,35,918],getpwuid:3,getrandom:918,getstr:3,getusershel:946,gic_opt:922,give:[6,14,23,28,38,904,910,911,919,932,938,939],given:[2,3,5,6,8,10,14,20,21,23,28,36,38,39,41,43,46,48,49,59,60,124,135,317,329,389,866,906,910,915,918,919,943],gladman:919,glob:[3,6],global:[5,19,20,21,22,141,155,918],glorifi:923,glossolalia:14,glue:903,gmbh:919,gmt:898,gnu:[904,906,918,919],go:[20,24,939,946],goal:46,good:[12,15,23,34,919,938,939,953],googl:919,gotten:939,gov:[21,919],govern:[23,919,944],gpg:905,gpl:919,grace:942,gracefulli:924,grain:43,grammar:[910,914],grant:[3,14,19,20,21,23,26,28,34,35,37,39,43,46,48,224,235,260,264,267,760,897,910,918,919,928,932,937,939,942,946,952],gratitud:919,great:[19,153,267,752],greater:53,greg:953,groff:0,group:[20,21,40,911,919],grow:901,gs2:918,gss:[28,903,910,917,918,924,953],gss_:924,gss_accept_sec_context:[43,918,924],gss_acquire_cr:[43,918],gss_acquire_cred_from:[43,918],gss_acquire_cred_impersonate_nam:43,gss_acquire_cred_with_password:918,gss_add_cr:924,gss_add_cred_from:924,gss_add_cred_impersonate_nam:924,gss_add_cred_with_password:924,gss_add_oid_set_memb:924,gss_buffer_desc:43,gss_buffer_set_t:43,gss_buffer_t:[43,924],gss_c_accept:43,gss_c_both:43,gss_c_buffer_flag_alloc:43,gss_c_buffer_type_data:43,gss_c_buffer_type_head:43,gss_c_buffer_type_mic_token:43,gss_c_buffer_type_pad:43,gss_c_buffer_type_sign_onli:43,gss_c_buffer_type_stream:43,gss_c_buffer_type_trail:43,gss_c_channel_bound_flag:918,gss_c_dce_styl:43,gss_c_deleg_policy_flag:918,gss_c_inq_negoex_kei:924,gss_c_inq_negoex_verify_kei:924,gss_c_ma_negoex_and_spnego:924,gss_c_no_credenti:43,gss_c_no_nam:43,gss_c_nt_anonym:43,gss_c_nt_export_nam:[43,924],gss_c_nt_hostbased_servic:43,gss_c_nt_machine_uid_nam:43,gss_c_nt_string_uid_nam:43,gss_c_nt_user_nam:43,gss_c_null_oid:43,gss_c_qop_default:43,gss_c_sec_context_sasl_ssf:918,gss_const_key_value_set_t:43,gss_create_empty_oid_set:924,gss_cred_id_t:[43,924],gss_cred_usage_t:43,gss_ctx_id_t:[43,924],gss_display_statu:924,gss_error:43,gss_export_cr:43,gss_export_nam:43,gss_get_mic_iov:43,gss_get_mic_iov_length:43,gss_get_name_attribut:43,gss_import_cr:[43,924],gss_import_nam:[43,924],gss_import_sec_context:924,gss_init_sec_context:43,gss_inquire_attrs_for_mech:924,gss_inquire_cr:43,gss_inquire_cred_by_oid:[43,918],gss_inquire_nam:43,gss_inquire_sec_context_by_oid:[918,924],gss_iov:918,gss_iov_buffer_desc:43,gss_iov_buffer_desc_struct:43,gss_iov_buffer_flag_alloc:43,gss_iov_buffer_t:43,gss_iov_buffer_type_data:43,gss_iov_buffer_type_head:43,gss_iov_buffer_type_mic_token:43,gss_iov_buffer_type_pad:43,gss_iov_buffer_type_sign_onli:43,gss_iov_buffer_type_stream:43,gss_iov_buffer_type_trail:43,gss_key_value_element_desc:43,gss_key_value_element_struct:43,gss_key_value_set_desc:43,gss_key_value_set_struct:43,gss_krb5_cred_no_ci_flags_x:918,gss_krb5_get_cred_imperson:[43,918],gss_krb5_nt_enterprise_nam:[43,918],gss_krb5_nt_principal_nam:43,gss_krb5_nt_x509_cert:[43,918],gss_mech_config:[28,917,953],gss_mech_interpos:924,gss_name_t:[43,924],gss_oid:[43,924],gss_oid_set:[43,924],gss_qop_t:43,gss_release_iov_buff:43,gss_s_cred_unavail:43,gss_s_duplicate_el:43,gss_s_unavail:43,gss_store_cr:918,gss_store_cred_into:43,gss_unwrap_aead:43,gss_unwrap_iov:43,gss_verify_mic_iov:43,gss_wrap_aead:43,gss_wrap_iov:43,gss_wrap_iov_length:43,gss_wrapex:918,gssapi:[15,16,20,21,45,896,897,900,901,903,918,919,920,926,945,953],gssapi_err_gener:919,gssapi_ext:[43,924],gssapi_krb5:43,gssapiauthent:28,gssapip_spnego:919,gssapistrictacceptorcheck:38,gssapiv2:43,gssd_pname_to_uid:919,gssi_:924,gssi_import_cred_by_mech:924,gssi_import_name_by_mech:924,gssi_import_sec_context_by_mech:924,gssrpc:919,gssspi_exchange_meta_data:924,gssspi_query_mechanism_info:924,gssspi_query_meta_data:924,guarante:14,guard:901,guess:[21,34,918],guest:[3,21],guid:[15,30,32,926],gz:905,h5l:[21,44],h:[5,6,9,22,43,262,898,906,919,920,921,922,923,924,925,927,928,929,930,931,932,933,934,935,939,943],ha:[0,3,5,6,12,14,15,17,19,20,21,23,24,25,26,27,28,34,35,37,38,39,43,46,78,124,260,263,279,356,360,388,404,739,897,901,904,905,906,910,914,915,918,919,924,928,929,930,933,938,939,943,946,951],had:[6,28,34,37,938,939,952],haddl:85,hand:[14,34],handi:34,handl:[3,6,14,19,36,43,48,71,132,135,137,139,141,142,143,144,145,146,147,149,150,151,152,153,154,155,157,158,159,161,164,223,224,235,246,250,251,265,276,300,302,303,305,308,310,311,312,313,314,316,318,335,336,342,343,359,403,414,918,919,922,924,927,931],handle_error:43,handle_out_of_space_error:43,happen:[3,17,20,34,39,41,939],happi:919,hard:[20,23],hardcod:[897,900,934],harder:918,hardwar:[3,20,34,46,921,931,939,943],harm:901,harvard:919,harwood:953,hash:[6,21,37,901,911,915,918],hat:[692,693,919,953],have:[0,2,3,6,8,12,14,15,17,19,20,21,23,24,25,26,28,32,33,34,35,37,38,39,43,46,101,153,230,274,402,897,901,904,905,908,910,911,914,915,918,919,920,922,923,924,927,928,929,931,933,935,938,939,942,946,950,952,953],have_getusershel:946,haven:[906,953],hdata:230,he:[19,23,938,939,952],head:21,header:[6,21,43,48,535,538,809,906,920,921,922,923,925,927,928,929,930,931,932,933,934,935],headernam:906,heim_org:21,heimdal:[42,43,45,897,918],held:[919,943],hellman:[20,21,942],help:[21,23,37,901,906,918,934,936,939,945,953],helpdesk:14,henc:12,her:[39,939,952],here:[0,15,19,20,21,23,28,35,41,43,46,898,906,923,938,939],hereaft:919,herebi:919,hesiod:[21,906,919],heurist:[21,154,230,920,946,951],hexadecim:[6,918],hh:898,hhmmss:898,hhost:918,hi:[19,23,939,946,952],hidden:[46,352,870],hide:[3,942],hierarch:[4,21,918],hierarchi:23,high:[14,16,24],higher:[43,897,908,918],highest:[3,6,14,21,310,315,414],highli:[905,918],himself:939,hin:905,hint:[3,20,149],hist_kvno:6,histor:[28,33,896],histori:[6,26,906,918],hit:[48,946],hmac:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],hold:[3,43,78,170,187,192,193,397,398,897],holder:919,hole:[32,34,39,914],home:[5,21,28,938,946,950,951,952],honor:[41,939],hook:[48,865,866,918,926],hope:919,hopefulli:35,host01:953,host:[3,4,7,8,12,14,15,16,20,21,23,24,25,26,29,30,31,33,36,37,38,39,43,46,48,194,223,230,329,331,388,389,414,643,645,901,904,906,918,926,931,938,939,942,943,946,950,951,952,953],host_based_servic:[20,39],host_realm:925,hostaccount:28,hostnam:[3,12,15,20,21,23,26,33,34,37,38,41,43,48,329,388,389,906,918,925,948,951,953],hostrealm:[28,918,926],hostrealm_plugin:925,hotp:3,hour:[5,19,20,23,33,898,938,939,946,953],houston:39,how:[14,20,21,23,26,28,32,34,37,39,43,224,416,905,906,916,920,926,933,934,938,942],howev:[3,6,14,17,20,21,23,25,32,33,35,37,39,904,919,939,953],html:[0,22,42,905,908,918],html_subst:908,htmlsrc:908,http:[21,22,25,30,38,39,42,904,905,908,918,919,936],http_anchor:[21,29],hudson:953,human:[169,898,918],hundr:24,hw:918,hwauth:20,hxx:919,i:[2,19,34,38,793,904,906,919,939,942,943,948,953],iakerb:918,icr:43,id:[8,20,21,141,149,155,302,305,316,646,897,938,946,953],idea:38,ideal:[15,23,34,46,904],ident:[3,15,20,22,43,48,361,740,880,881,897,918,922,938,939,942,944],identif:[918,919],identifi:[4,10,21,28,43,166,265,315,317,733,826,832,847,918,919,924,948],idp:692,iec:905,ietf:918,ignor:[3,19,20,21,26,28,43,48,235,260,264,267,269,278,282,342,345,350,359,388,534,708,711,865,901,904,906,910,918,923,951,953],ignore_acceptor_hostnam:[21,38,43],illinoi:42,illumin:953,imap:[38,906,951],immedi:[6,14,21,23,39,918,931],impact:35,impend:46,imperson:918,impl:906,implement:[0,14,20,21,23,24,28,29,36,38,40,43,44,46,51,113,119,151,294,382,383,897,904,906,910,912,914,918,919,920,921,922,923,924,925,927,928,929,931,932,933,934,935,936,939,946,953],impli:[8,919],implicit:20,impos:928,imposs:[23,35],improv:[0,14,20,21,35,918,936],in_authdat:173,in_cr:[224,225,226,321,330,375],in_data:[329,330,375],in_length:[131,413],in_tkt_servic:[235,260,264,267],inaccess:39,inaccur:21,inaddr:172,inadequ:41,inauthdat1:322,inauthdat2:322,inbuf:[356,357,358,359,360],inc:[919,939,953],incc:134,incident:919,includ:[6,9,15,16,19,20,21,23,24,26,32,33,34,37,38,39,43,48,99,104,144,287,311,325,326,330,331,343,344,359,407,685,813,826,833,846,860,896,897,901,903,906,907,908,910,911,914,918,919,922,923,924,928,930,931,934,938,942,946,953],include_pac:860,includedir:[21,906],inclus:919,incom:[20,38,924],incompat:[904,906,927],incomplet:21,inconsist:24,incorpor:[0,20,24,918],incorrect:[35,39,735,736,938,939],incorrectli:939,incr:177,increas:[20,24,40,100,103,288,290,926],increment:[4,8,9,14,19,20,24,31,35,39,48,87,89,325,326,331,915,918,919],indata:178,inde:939,independ:[21,26,138,163,245,307,906],index:[6,22,29,42,369,905,915],indic:[3,6,14,19,20,21,23,26,28,30,36,37,39,41,43,46,154,245,327,728,729,730,731,735,736,737,738,837,897,898,900,901,910,911,912,914,915,918,919,921,922,923,931,939,942,953],indirect:919,individu:[9,20,919,939,953],inetd:[8,12,34,41],infd:62,infer:[91,93,344],influenc:38,info2:918,info:[20,34,229,652,654,663,672,826,832,888,918],inform:[3,4,6,7,9,11,20,22,23,26,28,33,34,38,39,41,43,46,48,169,185,229,250,251,282,325,327,333,342,364,386,387,416,651,653,655,656,658,740,824,825,863,870,875,889,897,905,906,909,910,911,914,918,922,923,926,927,931,934,936,942,953],infrastructur:[21,40,903,904,918],infrequ:918,inherit:[938,946],ini:21,init:[4,10,920,921,922,925,928,929,930,931,932,933],init_cr:46,initi:[3,5,12,14,15,21,22,23,25,26,34,35,38,40,45,48,99,102,115,124,229,269,287,289,336,401,506,877,884,897,900,906,910,918,919,922,923,938,939,942,943,945,946,948,953],initiator_cred_handl:43,inittab:34,initvt:923,inject:25,inop:14,inout:[98,99,100,102,103,114,287,288,289,290,295,329,330,359,361,363,364,375,407],inprinc:182,inptr:[186,190],input:[23,43,48,49,99,100,102,103,107,113,117,119,124,144,194,195,224,287,288,289,290,294,296,352,375,376,403,920,932,935,948],input_assoc_buff:43,input_ccach:942,input_cred_handl:43,input_message_buff:43,input_name_buff:924,input_name_typ:924,input_payload_buff:43,inputlen:104,inquir:[3,19],inquiri:19,ins:32,insecur:[14,32,39,43,230],insensit:[39,350,706,898],insert:[25,825,832],insid:[15,26,195,911,918],insist:946,inspect:[16,380,381,865,866,921,928,930],inspir:918,inst:50,instal:[12,14,15,17,21,28,30,32,39,902,905,908,927,941,945],instanc:[19,21,23,28,33,35,43,49,50,643,644,901,910,918,923,953],instead:[3,4,6,8,14,20,21,23,24,34,37,38,46,239,246,278,309,340,341,342,344,417,419,866,906,918,919,924,931,941,943,946,952],institut:[909,919,953],instruct:[22,23,34,37,43,906,936],insuffici:[223,231,302,323,325,906],int16_t:843,int32_t:844,int_max:787,integ:[3,20,21,23,36,37,896,910,911,914,924],integr:[26,33,43,46,326,331,356,360,903,905,917,918,919,939],intel:919,intend:[3,10,23,41,43,46,352,946],interact:[2,3,21,23,39,368,906],intercept:[28,924],interest:[21,35,901,907],interfac:[3,11,14,19,20,23,28,34,46,897,901,903,906,918,923,926],interface_modname_initvt:923,interface_module_initvt:923,interface_plugin:923,interfer:904,intermedi:[20,21,23,43,224,910,911,918,939],intern:[24,36,41,107,731,847,920,921,922,926,928,929,930,931,933,935,953],internet:38,interoper:[37,382,383,897,924],interpos:[28,926],interpret:[3,36,43,46,152,245,924,942,946,948],interprocess_token:924,interrupt:[14,260,919],intersect:26,interv:[3,8,23,34,35,896,898],interven:23,intervent:[14,26],introduc:[3,20,21,921,925,929,930,932],intrud:939,invalid:[14,21,23,50,136,139,156,260,301,315,336,939,942,943],invers:914,investig:906,invis:25,invoc:[6,41,43],invok:[4,8,9,11,12,21,23,24,46,80,136,245,386,924,931,932,933,942,944,946],involv:[21,931],iov:[48,100,103,288,290,827,918],iov_count:43,ip:[15,20,39,918],iprop:[4,8,20,918,919],iprop_en:[4,8,20,23],iprop_hdr:919,iprop_listen:20,iprop_logfil:[20,23],iprop_master_ulogs:[20,23],iprop_port:[20,23],iprop_replica_pol:[8,20,23],iprop_resync_timeout:[20,23],iprop_slave_pol:20,iprop_ulogs:20,ipropd_svc:919,ipv4:38,ipv6:[21,38,918],iran:919,is_last_req:[245,838],is_skei:[153,749,826,910],isi:946,isn:[20,23,333,901,904,919],iso:905,isol:39,issu:[2,3,14,20,21,23,26,29,32,35,36,37,39,43,46,320,412,884,906,918,922,931,939,942],issuanc:3,issue_pac:918,issuer:[21,37,320,412],issueraltnam:37,item:[253,731,923,931],iter:[3,20,23,24,48,164,359,817,920,934],iterator_cr:934,iterator_fre:934,its:[3,4,8,10,14,15,17,20,21,23,24,26,28,29,32,33,34,35,37,38,39,40,41,43,46,48,87,89,92,107,117,203,209,228,269,296,301,356,359,360,381,412,898,909,910,918,919,920,921,922,923,924,931,935,941,942,943,951],itself:[3,4,8,10,14,15,20,21,28,43,46,198,199,200,201,202,203,206,207,208,209,212,215,216,221,334,736,826,897,900,902,924,931,939],ivec:[186,190],jan:23,januari:[896,898],jellinghau:919,jennif:[3,938,939,953],jeremi:919,jimi:12,job:[8,17,34,39],joeadmin:[19,23,32,952],joeuser:953,johndo:21,jqpublic:946,json:[3,36,46,368,371,738,740,910],jul:898,juli:898,just:[6,14,15,20,21,33,34,43,326,641,897,904,907,922,939,946,952],k1:107,k2:107,k5:[20,34,917,919],k5_gic_opt:[235,260],k5_random_kei:[115,124],k5_vic_opt:[415,416],k5ident:[21,28,937,950],k5login:[21,28,937,938,946,950],k5login_authorit:[21,28,952],k5login_directori:[21,28],k5srvutil:[1,14,26,900],k5user:946,k5wiki:[904,918,936],k:[2,3,4,5,6,10,11,14,15,20,23,26,34,101,119,900,911,918,942,943,946,948],kadm5:[3,4,6,18,20,21,23,24,34,903,917,918,919,926,928],kadm5_auth:[19,918,926],kadm5_auth_modinfo:928,kadm5_auth_plugin:928,kadm5_auth_restrict:928,kadm5_hook:[918,926],kadm5_hook_modinfo:929,kadm5_hook_plugin:929,kadm5_pass_q_:935,kadm:945,kadmin:[1,2,4,5,6,8,10,11,12,14,15,16,19,20,21,22,23,24,25,26,32,34,35,37,39,40,166,245,300,301,382,897,898,900,903,918,919,926,929,944,945,953],kadmind:[1,3,5,9,19,20,21,22,23,24,26,28,34,39,902,918,926,944,953],kadmind_listen:20,kadmind_port:[4,20,34],kaduk:14,kbd5_util:23,kbuild:903,kc:0,kcm:[21,321,405,897,918,919,953],kcm_mach_servic:21,kcm_socket:21,kd:20,kdb5_err:919,kdb5_ldap_util:[1,3,4,10,20,22,23,24],kdb5_util:[1,4,7,8,10,11,14,20,22,23,24,26,34,898,903,917,918,953],kdb5_util_path:4,kdb5_util_prog:8,kdb:[4,22,23,24,35,903,918,919,926,930,942,945],kdb_convert:919,kdb_log:919,kdc1:39,kdc2:39,kdc:[3,4,5,6,8,9,10,11,15,16,17,18,19,21,22,23,24,25,26,29,31,32,33,36,40,43,46,48,101,107,119,166,224,230,235,241,245,247,258,260,269,300,301,333,342,343,414,544,546,563,657,659,738,832,845,846,865,866,884,897,900,902,903,906,907,910,912,913,918,921,922,925,926,927,933,935,939,942,948,953],kdc_cert:37,kdc_default_opt:21,kdc_err_more_preauth_data_requir:918,kdc_listen:[20,34],kdc_max_dgram_reply_s:20,kdc_opt_allow_postd:789,kdc_opt_canonic:789,kdc_opt_cname_in_addl_tkt:789,kdc_opt_disable_transited_check:789,kdc_opt_enc_tkt_in_skei:789,kdc_opt_forward:789,kdc_opt_postd:789,kdc_opt_proxi:789,kdc_opt_renew:789,kdc_opt_renewable_ok:[21,789],kdc_opt_request_anonym:789,kdc_opt_valid:789,kdc_option:846,kdc_port:20,kdc_princ_nam:37,kdc_princip:37,kdc_principal_seq:37,kdc_tcp_listen:[20,34,37],kdc_tcp_listen_backlog:20,kdc_tcp_port:20,kdc_timesync:21,kdc_tkt_common_mask:789,kdcdefault:[10,34,37,40],kdcissu:48,kdckei:37,kdclist:34,kdcpolici:[918,926],kdcpolicy_plugin:930,kdcpreauth:[918,926],kdcpreauth_mymech_initvt:923,kdcpreauth_plugin:931,kdcproxi:29,kdestroi:[33,897,918,937,940,942,943,947,948,953],keep:[3,9,15,23,35,901,904,905,938],keepkvno:3,keepold:[3,14,23,918],kei:[2,3,5,6,9,10,11,12,15,16,19,20,21,25,28,32,34,36,37,38,40,41,43,46,48,73,77,87,89,100,103,105,106,108,113,114,117,119,129,130,141,153,155,181,216,224,229,234,258,276,277,280,292,293,300,301,307,308,313,320,325,330,342,343,351,354,359,363,364,412,414,439,440,671,740,750,756,813,825,826,832,833,834,847,848,850,900,901,902,903,906,907,910,911,912,917,918,922,924,931,939,942,943,948,953],kept:[3,17,20,23,32],kerb_ap_options_cbt:918,kerber:[14,33,34,946],kerbero:[2,3,4,5,6,7,8,9,10,11,12,14,18,19,20,21,24,25,26,27,28,30,31,32,33,36,37,38,42,43,45,46,47,48,56,62,64,65,67,69,72,73,74,76,77,78,79,81,82,84,85,86,87,88,89,90,91,92,93,95,96,97,98,99,100,102,103,104,105,106,107,108,111,112,113,114,115,117,118,121,124,125,126,129,130,133,134,135,141,142,145,147,148,149,150,151,152,153,155,156,157,158,159,161,162,163,164,169,170,172,173,174,175,176,177,178,180,181,182,183,184,185,187,189,192,193,214,217,223,224,227,229,235,236,238,248,260,261,262,264,265,266,267,268,271,272,273,274,275,276,277,278,279,280,282,287,288,289,290,294,295,296,298,299,300,301,302,303,305,306,308,310,311,314,315,316,317,318,321,322,323,324,325,326,327,328,329,330,331,332,333,335,337,338,339,342,344,345,347,352,354,355,356,357,358,359,360,361,363,364,374,375,376,377,378,382,383,384,385,389,396,397,398,400,401,402,403,404,405,406,407,408,409,410,414,897,898,901,902,903,904,906,907,909,910,926,929,932,934,936,937,938,941,942,943,944,945,946,947,948,949,950,951,952],kerberos_db:8,kerboro:18,kern:20,kernel:[897,903,918],key_data:[286,293],key_exp:832,key_stash_fil:[6,20,34],keyagr:37,keyblock:[48,70,75,90,101,107,115,117,215,216,224,280,281,331,353,359,393,826,910],keyboard:[4,6,10,48],keybyt:112,keydata:6,keyencipher:[21,37],keyexchang:107,keyfil:[6,20,22],keyfilenam:21,keyid:37,keyindex:6,keyinfo:[6,26],keylength:112,keylist:[11,15],keyprocarg:315,keyr:[897,906,918,953],keysalt:[2,3,917],keyspac:14,keytab:[2,3,7,8,11,12,14,17,21,23,26,28,31,41,43,46,48,304,310,311,312,314,317,318,359,363,364,416,897,899,901,902,906,907,910,913,917,918,942,943,945,946,948,953],keytab_fil:[8,942],keytab_nam:943,keytab_out:303,keytabl:850,keytabnam:906,keytyp:10,keyusag:37,keyutil:906,keyword:[21,898],kfw:918,kgetcr:918,kile:684,kill:34,kind:[38,43,105,897,919,922,924,931],kinit:[3,12,15,16,21,22,28,29,33,34,35,37,41,46,897,898,918,922,937,940,941,943,946,947,948,949,953],kiprop:[4,8,23],kkdcp:[29,39,918,919],klau:919,kldap:[20,22],klein:919,klist:[14,15,33,897,900,937,940,941,942,946,947,953],klmdb:20,know:[21,33,35,37,901,906,924,939],knowledg:[0,14,17,414,922,931],known:[6,20,23,26,38,43,46,48,152,231,317,647,648,907,918,951],korea:919,kp:[20,21],kpasswd:[3,4,14,15,20,21,23,29,33,918,937,938,940,953],kpasswd_listen:20,kpasswd_port:20,kpasswd_serv:[21,29,39],kpclientauth:20,kpkdc:21,kprop:[1,4,6,8,15,23,24,34,35,903,917,918,919,953],kprop_path:4,kprop_port:[4,917,953],kpropd:[1,4,7,9,23,34,41,903,917,918],kpropd_rpc:919,kproplog:[1,8,919],kpserverauth:[21,37],krb4:918,krb524:21,krb524_convert_creds_kdc:789,krb524_init_et:789,krb524_krb4_disabl:51,krb5:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,40,41,42,43,44,45,46,47,49,50,51,52,53,54,55,56,57,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,206,207,208,209,210,211,212,213,214,215,216,217,218,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,270,271,272,273,274,275,276,277,278,279,280,281,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,790,791,792,793,794,795,796,797,798,799,800,801,802,803,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,946,947,948,949,950,951,952,953],krb5_425_conv_princip:48,krb5_524_conv_princip:48,krb5_524_convert_cr:[48,790],krb5_address:[52,53,54,64,82,84,172,198,232,233,234,240,332,804,824,825,826,832,833,840,846],krb5_address_compar:48,krb5_address_ord:48,krb5_address_search:48,krb5_addrtyp:[804,805],krb5_allow_weak_crypto:48,krb5_altauth_att_challenge_respons:789,krb5_aname_to_localnam:[48,918,932],krb5_anonymous_princip:48,krb5_anonymous_princstr:[57,789],krb5_anonymous_realm:48,krb5_anonymous_realmstr:[58,789],krb5_ap_rep:[789,804],krb5_ap_rep_enc_part:[48,357,375,804],krb5_ap_req:[789,804],krb5_appdefault_boolean:[48,60],krb5_appdefault_str:[48,59],krb5_as_rep:[789,845],krb5_as_req:[789,846],krb5_auth_con_fre:[48,78],krb5_auth_con_genaddr:[48,82,84],krb5_auth_con_get_checksum_func:48,krb5_auth_con_getaddr:[44,48],krb5_auth_con_getauthent:48,krb5_auth_con_getflag:48,krb5_auth_con_getkei:48,krb5_auth_con_getkey_k:48,krb5_auth_con_getlocalseqnumb:48,krb5_auth_con_getlocalsubkei:48,krb5_auth_con_getrcach:48,krb5_auth_con_getrecvsubkei:[48,75],krb5_auth_con_getrecvsubkey_k:48,krb5_auth_con_getremoteseqnumb:48,krb5_auth_con_getremotesubkei:48,krb5_auth_con_getsendsubkei:[48,70],krb5_auth_con_getsendsubkey_k:48,krb5_auth_con_init:[48,61],krb5_auth_con_initivector:48,krb5_auth_con_set_checksum_func:48,krb5_auth_con_set_req_cksumtyp:48,krb5_auth_con_setaddr:[44,48],krb5_auth_con_setflag:[48,78],krb5_auth_con_setport:[44,48],krb5_auth_con_setrcach:48,krb5_auth_con_setrecvsubkei:[44,48],krb5_auth_con_setrecvsubkey_k:48,krb5_auth_con_setsendsubkei:[44,48],krb5_auth_con_setsendsubkey_k:48,krb5_auth_con_setuseruserkei:[48,359],krb5_auth_context:[48,62,63,64,65,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,84,85,86,87,88,89,90,223,323,325,326,327,328,329,330,331,354,356,357,358,359,360,363,364,375,804,856],krb5_auth_context_do_sequ:[66,69,74,83,325,326,327,331,356,360,789],krb5_auth_context_do_tim:[66,78,83,325,326,331,356,360,789],krb5_auth_context_generate_local_addr:[62,789],krb5_auth_context_generate_local_full_addr:[62,789],krb5_auth_context_generate_remote_addr:[62,789],krb5_auth_context_generate_remote_full_addr:[62,789],krb5_auth_context_permit_al:789,krb5_auth_context_ret_sequ:[66,83,325,326,327,331,354,356,360,789],krb5_auth_context_ret_tim:[66,83,325,326,331,354,356,360,789],krb5_auth_context_use_subkei:789,krb5_authdata:[173,184,189,195,200,320,322,412,804,813,826,833,846],krb5_authdata_and_or:789,krb5_authdata_ap_opt:789,krb5_authdata_auth_ind:789,krb5_authdata_cammac:789,krb5_authdata_etype_negoti:789,krb5_authdata_fx_armor:789,krb5_authdata_if_relev:789,krb5_authdata_initial_verified_ca:789,krb5_authdata_kdc_issu:789,krb5_authdata_mandatory_for_kdc:789,krb5_authdata_osf_dc:789,krb5_authdata_sesam:789,krb5_authdata_signticket:789,krb5_authdata_win2k_pac:789,krb5_authdatatyp:[184,189,195,804,811],krb5_authent:[48,65,804,886],krb5_bad_enctyp:[116,286],krb5_boolean:[52,54,55,105,109,110,127,128,129,130,160,192,253,283,284,285,298,299,300,319,341,343,348,349,350,362,388,804,826,838,860],krb5_build_princip:[46,47,48,92],krb5_build_principal_alloc_va:[47,48,91,94],krb5_build_principal_ext:[47,48],krb5_build_principal_va:48,krb5_c_:[186,188,190,191,196,197,281,351,353,411],krb5_c_block_siz:48,krb5_c_checksum_length:[48,168],krb5_c_crypto_length:48,krb5_c_crypto_length_iov:48,krb5_c_decrypt:[48,287],krb5_c_decrypt_iov:[48,103,288],krb5_c_derive_prfplu:[48,918],krb5_c_encrypt:48,krb5_c_encrypt_iov:[48,290],krb5_c_encrypt_length:[48,102,289],krb5_c_enctype_compar:48,krb5_c_free_stat:48,krb5_c_fx_cf2_simpl:48,krb5_c_init_st:48,krb5_c_is_coll_proof_cksum:48,krb5_c_is_keyed_cksum:48,krb5_c_keyed_checksum_typ:48,krb5_c_keylength:[48,124],krb5_c_make_checksum:[48,131,294],krb5_c_make_checksum_iov:[48,130,295],krb5_c_make_random_kei:48,krb5_c_padding_length:48,krb5_c_prf:[48,119,296],krb5_c_prf_length:[48,117],krb5_c_prfplu:[48,918],krb5_c_random_add_entropi:48,krb5_c_random_make_octet:48,krb5_c_random_os_entropi:48,krb5_c_random_se:48,krb5_c_random_to_kei:48,krb5_c_string_to_kei:[48,126,393],krb5_c_string_to_key_with_param:48,krb5_c_valid_cksumtyp:48,krb5_c_valid_enctyp:48,krb5_c_verify_checksum:[48,113,294,298,413],krb5_c_verify_checksum_iov:[48,114,299],krb5_calculate_checksum:48,krb5_cc_badnam:223,krb5_cc_cache_match:48,krb5_cc_close:[48,132,154,164],krb5_cc_copy_cr:48,krb5_cc_cursor:[139,150,158,804],krb5_cc_default:48,krb5_cc_default_nam:[48,135,156],krb5_cc_destroi:48,krb5_cc_dup:48,krb5_cc_end_seq_get:[48,158],krb5_cc_gen_new:48,krb5_cc_get_config:48,krb5_cc_get_flag:48,krb5_cc_get_full_nam:48,krb5_cc_get_nam:48,krb5_cc_get_princip:[47,48],krb5_cc_get_typ:48,krb5_cc_initi:[48,145],krb5_cc_move:48,krb5_cc_new_uniqu:48,krb5_cc_next_cr:[48,139,158],krb5_cc_nosupp:151,krb5_cc_notfound:[132,154,165],krb5_cc_remove_cr:[48,918],krb5_cc_resolv:[48,144],krb5_cc_retrieve_cr:[48,151],krb5_cc_select:48,krb5_cc_set_config:[44,48,283],krb5_cc_set_default_nam:[48,136],krb5_cc_set_flag:48,krb5_cc_start_seq_get:[48,139,150],krb5_cc_store_cr:48,krb5_cc_support_switch:48,krb5_cc_switch:48,krb5_ccach:[132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,157,158,159,161,164,223,224,225,226,232,233,234,246,250,251,264,267,329,375,383,403,414,804],krb5_ccache_conf_data:910,krb5_cccol:920,krb5_cccol_cursor:[162,163,164,804],krb5_cccol_cursor_fre:[48,163,164],krb5_cccol_cursor_new:[48,162,164],krb5_cccol_cursor_next:[48,162,163],krb5_cccol_have_cont:48,krb5_cccol_last_change_tim:44,krb5_ccselect_moddata:920,krb5_ccselect_vt:923,krb5_certauth_hwauth:921,krb5_certauth_hwauth_pass:921,krb5_change_password:[48,169],krb5_check_clockskew:48,krb5_checksum:[48,113,129,131,294,298,413,804,813,861],krb5_checksum_s:48,krb5_chpw_fail:260,krb5_chpw_messag:48,krb5_chpw_pwdnull:260,krb5_cksumtyp:[81,96,109,110,111,113,114,127,130,131,168,170,204,294,295,299,390,413,804,818],krb5_cksumtype_to_str:48,krb5_clear_error_messag:48,krb5_client_ktnam:[15,900,917,953],krb5_clpreauth_moddata:922,krb5_clpreauth_modreq:922,krb5_config:[21,34,917,918,953],krb5_config_cantopen:50,krb5_config_notenufspac:[56,306],krb5_const:789,krb5_const_point:[131,186,190,413,804],krb5_const_princip:[50,56,57,141,155,182,283,300,301,310,320,340,341,342,343,347,348,349,350,359,362,388,406,407,408,409,804],krb5_context:[46,48,49,50,51,52,53,54,55,56,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,171,172,173,174,175,177,178,179,180,181,182,183,184,186,188,189,190,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,245,246,247,248,250,251,252,253,257,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,375,376,377,379,380,381,382,383,384,386,387,388,389,393,396,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,417,418,419,420,804,838,856,865,866,872,877,888,918,923],krb5_copy_address:48,krb5_copy_authdata:48,krb5_copy_authent:48,krb5_copy_checksum:48,krb5_copy_context:48,krb5_copy_cr:48,krb5_copy_data:[48,865,866],krb5_copy_error_messag:48,krb5_copy_keyblock:48,krb5_copy_keyblock_cont:48,krb5_copy_princip:[47,48],krb5_copy_ticket:48,krb5_cred:[46,48,51,150,151,153,159,166,220,224,225,226,232,233,234,235,260,264,267,272,323,325,330,354,375,382,401,403,414,789,804],krb5_cred_enc_part:[804,823],krb5_cred_info:[804,824],krb5_crypto_iov:[98,100,103,114,130,288,290,295,299,804],krb5_crypto_typ:[97,827],krb5_crypto_type_checksum:[114,130,295,299,789],krb5_crypto_type_data:[114,130,295,299,789],krb5_crypto_type_empti:789,krb5_crypto_type_head:789,krb5_crypto_type_pad:789,krb5_crypto_type_sign_onli:[98,114,130,295,299,789],krb5_crypto_type_stream:789,krb5_crypto_type_trail:789,krb5_cryptotyp:[97,804,827],krb5_cybersafe_secureid:789,krb5_data:[48,58,59,60,99,100,101,102,103,106,108,113,117,119,120,121,123,124,125,126,129,141,155,166,169,185,223,229,230,258,265,279,284,287,288,289,290,294,296,298,321,323,324,325,326,327,328,329,330,331,333,335,340,341,347,354,355,356,357,358,359,360,364,375,382,383,393,404,405,804,821,826,827,831,836,840,856,861,865,866,868,869,870,882,890,895],krb5_db_entri:921,krb5_decode_authdata_contain:[48,189],krb5_decode_ticket:48,krb5_decrypt:48,krb5_deltat:[187,235,256,259,260,275,391,804,840],krb5_deltat_badformat:391,krb5_deltat_to_str:48,krb5_domain_x500_compress:789,krb5_eblock_enctyp:48,krb5_enc_data:[99,102,287,289,804,807,809,823,845,846,883],krb5_enc_kdc_rep_part:[804,845],krb5_enc_tkt_part:[300,301,804,883],krb5_encode_authdata_contain:[48,184],krb5_encpadata_req_enc_pa_rep:789,krb5_encrypt:48,krb5_encrypt_block:[186,188,190,196,197,281,351,353,393,411,804],krb5_encrypt_s:48,krb5_enctyp:[95,97,98,101,104,105,111,112,115,116,118,124,125,126,128,188,191,192,193,211,229,232,233,234,244,261,280,292,310,315,378,392,411,804,831,834,840,846,848],krb5_enctype_to_nam:48,krb5_enctype_to_str:48,krb5_end_seq_get:150,krb5_error:[212,273,324,355,375,789,804],krb5_error_cod:[46,49,50,55,56,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,129,130,131,132,133,134,135,137,138,139,140,141,142,143,145,147,148,149,150,151,152,153,154,155,156,157,158,159,161,162,163,164,165,166,167,169,170,172,173,174,175,176,177,178,180,181,182,183,184,185,186,187,189,190,192,193,194,195,196,197,214,217,223,224,225,226,227,228,229,230,231,232,233,234,235,236,238,245,246,247,248,250,251,252,253,257,260,261,262,264,265,266,267,268,269,271,272,273,274,275,276,277,278,279,280,281,282,286,287,288,289,290,293,294,295,296,298,299,300,301,302,303,304,305,306,307,308,309,310,311,313,314,315,316,317,318,320,321,322,323,324,325,326,327,328,329,330,331,332,333,335,336,337,338,339,340,341,342,343,344,345,346,347,351,352,353,354,355,356,357,358,359,360,361,363,364,368,369,371,372,373,374,375,376,377,378,379,382,383,384,385,386,387,389,390,391,392,393,394,395,396,397,398,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,417,418,419,420,804,855,856,865,866,872,877,923],krb5_euid:901,krb5_expand_hostnam:48,krb5_expire_callback_func:[245,804],krb5_fast_requir:[248,789],krb5_fcc_intern:135,krb5_fences_vt:923,krb5_fences_vtable_v2:923,krb5_find_authdata:48,krb5_finish_kei:48,krb5_finish_random_kei:48,krb5_flag:[142,151,153,157,224,225,226,232,233,234,238,248,269,329,330,359,375,403,804,809,825,826,832,833,840,846,879,886,894],krb5_free_address:[48,172,332],krb5_free_ap_rep_enc_part:[48,357,375],krb5_free_authdata:[48,173,195,322],krb5_free_authent:[48,65,174],krb5_free_checksum:[48,175],krb5_free_checksum_cont:[48,113,294],krb5_free_cksumtyp:[48,111],krb5_free_context:[48,136,176,268,282],krb5_free_cr:[48,177,224,375,405],krb5_free_cred_cont:[46,48,150,153,272,401],krb5_free_data:[48,178,321],krb5_free_data_cont:[48,141,229,324,325,326,327,328,329,330,331,335,356,360],krb5_free_default_realm:[48,227],krb5_free_enctyp:[48,261],krb5_free_error:[48,355,375],krb5_free_error_messag:[48,228],krb5_free_host_realm:[48,230,231],krb5_free_keyblock:[48,67,72,76,180,280,315],krb5_free_keyblock_cont:[48,115,125,126,181],krb5_free_keytab_entry_cont:[48,309,310],krb5_free_princip:[46,47,48,49,91,92,93,145,154,182,344,345,389],krb5_free_str:[48,143,169,194],krb5_free_tgt_cr:[48,354],krb5_free_ticket:[48,183,359,363],krb5_free_unparsed_nam:[48,406,408],krb5_fwd_tgt_cred:48,krb5_gc:403,krb5_gc_cach:[224,789],krb5_gc_canonic:789,krb5_gc_constrained_deleg:789,krb5_gc_forward:789,krb5_gc_no_stor:789,krb5_gc_no_transit_check:789,krb5_gc_user_us:[224,789],krb5_generate_seq_numb:327,krb5_get_credenti:[48,375,380,381,403],krb5_get_credentials_renew:48,krb5_get_credentials_valid:48,krb5_get_default_realm:48,krb5_get_error_messag:[48,837],krb5_get_etype_info:[48,918],krb5_get_fallback_host_realm:48,krb5_get_host_realm:[48,389],krb5_get_in_tkt_with_keytab:48,krb5_get_in_tkt_with_password:48,krb5_get_in_tkt_with_skei:48,krb5_get_init_cr:[234,250,251],krb5_get_init_creds_keytab:[48,232],krb5_get_init_creds_opt:[46,229,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,275,804],krb5_get_init_creds_opt_address_list:789,krb5_get_init_creds_opt_alloc:[46,48,237,239],krb5_get_init_creds_opt_anonym:789,krb5_get_init_creds_opt_canonic:789,krb5_get_init_creds_opt_chg_pwd_prmpt:789,krb5_get_init_creds_opt_etype_list:789,krb5_get_init_creds_opt_forward:789,krb5_get_init_creds_opt_fre:[46,48,236],krb5_get_init_creds_opt_get_fast_flag:48,krb5_get_init_creds_opt_init:48,krb5_get_init_creds_opt_preauth_list:789,krb5_get_init_creds_opt_proxi:789,krb5_get_init_creds_opt_renew_lif:789,krb5_get_init_creds_opt_salt:789,krb5_get_init_creds_opt_set_address_list:48,krb5_get_init_creds_opt_set_anonym:[46,48],krb5_get_init_creds_opt_set_canonic:48,krb5_get_init_creds_opt_set_change_password_prompt:48,krb5_get_init_creds_opt_set_etype_list:[48,229],krb5_get_init_creds_opt_set_expire_callback:48,krb5_get_init_creds_opt_set_fast_ccach:48,krb5_get_init_creds_opt_set_fast_ccache_nam:[48,229,246],krb5_get_init_creds_opt_set_fast_flag:[48,247],krb5_get_init_creds_opt_set_forward:48,krb5_get_init_creds_opt_set_in_ccach:48,krb5_get_init_creds_opt_set_out_ccach:48,krb5_get_init_creds_opt_set_pa:[48,254],krb5_get_init_creds_opt_set_pac_request:48,krb5_get_init_creds_opt_set_preauth_list:48,krb5_get_init_creds_opt_set_proxi:48,krb5_get_init_creds_opt_set_renew_lif:48,krb5_get_init_creds_opt_set_respond:[46,48],krb5_get_init_creds_opt_set_salt:[48,254],krb5_get_init_creds_opt_set_tkt_lif:[46,48],krb5_get_init_creds_opt_tkt_lif:789,krb5_get_init_creds_password:[46,48,233,243,245,352,918],krb5_get_permitted_enctyp:48,krb5_get_profil:48,krb5_get_prompt_typ:[46,48],krb5_get_renewed_cr:[48,225],krb5_get_server_rcach:48,krb5_get_time_offset:48,krb5_get_validated_cr:[48,226],krb5_gic_opt_pa_data:804,krb5_init_context:[48,205],krb5_init_context_kdc:[269,789],krb5_init_context_profil:48,krb5_init_context_secur:[269,789],krb5_init_creds_context:[270,271,272,273,274,275,276,277,278,279,804],krb5_init_creds_fre:[48,275],krb5_init_creds_get:[48,272,274,275],krb5_init_creds_get_cr:[48,271],krb5_init_creds_get_error:48,krb5_init_creds_get_tim:48,krb5_init_creds_init:[48,270,271,279,352],krb5_init_creds_set_keytab:48,krb5_init_creds_set_password:48,krb5_init_creds_set_servic:48,krb5_init_creds_step:[48,272,274,275,918],krb5_init_creds_step_flag_continu:[279,789],krb5_init_keyblock:48,krb5_init_random_kei:48,krb5_init_secure_context:[48,205,268,918],krb5_int16:804,krb5_int16_max:[567,789],krb5_int16_min:789,krb5_int32:[66,69,74,83,266,363,364,374,385,389,394,410,804,806,808,812,813,819,821,824,828,830,832,835,836,837,839,846,851,854,867,868,869,871,875,879,881,882,885,891],krb5_int32_max:[569,789],krb5_int32_min:789,krb5_invalid_princip:50,krb5_is_config_princip:[47,48],krb5_is_referral_realm:48,krb5_is_thread_saf:48,krb5_k:847,krb5_k_create_kei:48,krb5_k_decrypt:48,krb5_k_decrypt_iov:[48,290],krb5_k_encrypt:48,krb5_k_encrypt_iov:[48,288],krb5_k_free_kei:[48,68,73,77,286],krb5_k_key_enctyp:48,krb5_k_key_keyblock:48,krb5_k_make_checksum:[48,113],krb5_k_make_checksum_iov:[48,114,299],krb5_k_prf:48,krb5_k_reference_kei:48,krb5_k_verify_checksum:[48,129],krb5_k_verify_checksum_iov:[48,130,295],krb5_kdc_profil:[10,20,34,917,918,953],krb5_kdc_rep:[232,233,234,804],krb5_kdc_req:804,krb5_kdc_sign_ticket:[48,340,341],krb5_kdc_unreach:260,krb5_kdc_verify_ticket:48,krb5_kdcpolicy_moddata:930,krb5_kdcpreauth_moddata:931,krb5_kdcpreauth_modreq:931,krb5_kdcrep_modifi:267,krb5_kdcrep_skew:267,krb5_kei:[48,68,73,77,87,89,287,288,289,290,291,294,295,296,297,298,299,804],krb5_key_st:847,krb5_keyblock:[48,67,70,72,75,76,86,88,90,99,100,101,102,103,106,107,108,113,114,115,117,119,124,125,126,129,130,180,181,234,281,286,293,300,301,315,320,340,341,342,343,351,353,393,412,804,808,813,825,826,832,833,834,850],krb5_keytab:[232,235,276,302,303,304,305,307,308,310,311,312,313,314,316,317,318,359,363,364,376,414,804],krb5_keytab_entri:[217,302,309,310,314,316,804],krb5_keytab_entry_st:850,krb5_keyusag:[99,100,102,103,108,113,114,129,130,287,288,289,290,294,295,298,299,804],krb5_keyusage_ad_it:789,krb5_keyusage_ad_kdcissued_cksum:789,krb5_keyusage_ad_mt:789,krb5_keyusage_ad_signedpath:789,krb5_keyusage_ap_rep_encpart:789,krb5_keyusage_ap_req_auth:789,krb5_keyusage_ap_req_auth_cksum:789,krb5_keyusage_app_data_cksum:789,krb5_keyusage_app_data_encrypt:789,krb5_keyusage_as_rep_encpart:789,krb5_keyusage_as_req:789,krb5_keyusage_as_req_pa_enc_t:789,krb5_keyusage_cammac:789,krb5_keyusage_enc_challenge_cli:789,krb5_keyusage_enc_challenge_kdc:789,krb5_keyusage_fast_enc:789,krb5_keyusage_fast_finish:789,krb5_keyusage_fast_rep:789,krb5_keyusage_fast_req_chksum:789,krb5_keyusage_gss_tok_m:789,krb5_keyusage_gss_tok_wrap_integ:789,krb5_keyusage_gss_tok_wrap_priv:789,krb5_keyusage_iakerb_finish:789,krb5_keyusage_kdc_rep_ticket:789,krb5_keyusage_krb_cred_encpart:789,krb5_keyusage_krb_error_cksum:789,krb5_keyusage_krb_priv_encpart:789,krb5_keyusage_krb_safe_cksum:789,krb5_keyusage_pa_as_fresh:789,krb5_keyusage_pa_fx_cooki:789,krb5_keyusage_pa_otp_request:789,krb5_keyusage_pa_pkinit_kx:789,krb5_keyusage_pa_s4u_x509_user_repli:789,krb5_keyusage_pa_s4u_x509_user_request:789,krb5_keyusage_pa_sam_challenge_cksum:789,krb5_keyusage_pa_sam_challenge_trackid:789,krb5_keyusage_pa_sam_respons:789,krb5_keyusage_spak:789,krb5_keyusage_tgs_rep_encpart_sesskei:789,krb5_keyusage_tgs_rep_encpart_subkei:789,krb5_keyusage_tgs_req_ad_sesskei:789,krb5_keyusage_tgs_req_ad_subkei:789,krb5_keyusage_tgs_req_auth:789,krb5_keyusage_tgs_req_auth_cksum:789,krb5_kpasswd_accessdeni:789,krb5_kpasswd_autherror:[166,789],krb5_kpasswd_bad_vers:789,krb5_kpasswd_harderror:[166,789],krb5_kpasswd_initial_flag_need:789,krb5_kpasswd_malform:[166,789],krb5_kpasswd_softerror:[166,789],krb5_kpasswd_success:[166,382,789],krb5_kt_add_entri:48,krb5_kt_client_default:48,krb5_kt_close:[48,317],krb5_kt_cursor:[308,314,318,804],krb5_kt_default:48,krb5_kt_default_nam:48,krb5_kt_dup:48,krb5_kt_end:314,krb5_kt_end_seq_get:[48,318],krb5_kt_free_entri:[48,314],krb5_kt_get_entri:48,krb5_kt_get_nam:48,krb5_kt_get_typ:48,krb5_kt_have_cont:48,krb5_kt_name_toolong:311,krb5_kt_next_entri:48,krb5_kt_notfound:313,krb5_kt_nowrit:[302,316],krb5_kt_read_service_kei:48,krb5_kt_remove_entri:48,krb5_kt_resolv:48,krb5_kt_start_seq_get:[48,308],krb5_ktname:[43,900,917,953],krb5_kuserok:[47,48,918,932],krb5_kvno:[310,315,804,831,850],krb5_last_req_entri:[804,832],krb5_libos_badpwdmatch:[260,361],krb5_libos_pwdintr:260,krb5_lname_no_tran:932,krb5_lname_notran:56,krb5_lrq_all_acct_exptim:789,krb5_lrq_all_last_initi:789,krb5_lrq_all_last_renew:789,krb5_lrq_all_last_req:789,krb5_lrq_all_last_tgt:789,krb5_lrq_all_last_tgt_issu:789,krb5_lrq_all_pw_exptim:789,krb5_lrq_none:789,krb5_lrq_one_acct_exptim:789,krb5_lrq_one_last_initi:789,krb5_lrq_one_last_renew:789,krb5_lrq_one_last_req:789,krb5_lrq_one_last_tgt:789,krb5_lrq_one_last_tgt_issu:789,krb5_lrq_one_pw_exptim:789,krb5_magic:[804,805,807,808,809,811,813,818,821,823,824,825,826,829,831,832,833,834,836,845,846,848,850,854,859,868,869,873,882,883,886,890,891,895],krb5_make_authdata_kdc_issu:48,krb5_marshal_credenti:48,krb5_merge_authdata:48,krb5_mk_1cred:48,krb5_mk_error:48,krb5_mk_ncred:[48,323],krb5_mk_priv:[48,79],krb5_mk_rep:48,krb5_mk_rep_dc:48,krb5_mk_req:[48,80,81,330],krb5_mk_req_checksum_func:[63,80,804],krb5_mk_req_extend:[48,329],krb5_mk_safe:[48,326],krb5_msgtype:[503,504,505,506,531,543,718,741,759,760,804,832,845,846],krb5_no_2nd_tkt:267,krb5_no_tkt_suppli:[223,267],krb5_nt_ent_principal_and_id:789,krb5_nt_enterprise_princip:789,krb5_nt_ms_princip:789,krb5_nt_ms_principal_and_id:789,krb5_nt_princip:[91,93,344,789],krb5_nt_smtp_name:789,krb5_nt_srv_hst:[223,389,789],krb5_nt_srv_inst:[91,93,344,789],krb5_nt_srv_xhst:789,krb5_nt_uid:789,krb5_nt_unknown:[389,789],krb5_nt_wellknown:[91,93,344,789],krb5_nt_x500_princip:789,krb5_octet:[804,805,811,818,848,859,882,890,891],krb5_os_localaddr:48,krb5_pa_data:[804,832,845,846],krb5_pa_pac_req:804,krb5_pa_server_referral_data:804,krb5_pa_svr_referral_data:804,krb5_pac:[300,301,333,334,335,336,337,338,339,340,341,342,343,804],krb5_pac_add_buff:48,krb5_pac_attributes_info:789,krb5_pac_client_claim:789,krb5_pac_client_info:[333,789],krb5_pac_credentials_info:[333,789],krb5_pac_data:863,krb5_pac_delegation_info:[333,789],krb5_pac_device_claim:789,krb5_pac_device_info:789,krb5_pac_fre:[48,338,339],krb5_pac_full_checksum:789,krb5_pac_get_buff:48,krb5_pac_get_client_info:[48,918],krb5_pac_get_typ:48,krb5_pac_init:48,krb5_pac_logon_info:[333,789],krb5_pac_pars:48,krb5_pac_privsvr_checksum:[333,789],krb5_pac_requestor:789,krb5_pac_server_checksum:[333,789],krb5_pac_sign:48,krb5_pac_sign_ext:48,krb5_pac_ticket_checksum:789,krb5_pac_upn_dns_info:[333,789],krb5_pac_verifi:[48,343],krb5_pac_verify_ext:[48,301],krb5_padata_afs3_salt:789,krb5_padata_ap_req:[704,789],krb5_padata_as_checksum:789,krb5_padata_as_fresh:789,krb5_padata_enc_sandia_securid:789,krb5_padata_enc_timestamp:789,krb5_padata_enc_unix_tim:789,krb5_padata_encrypted_challeng:789,krb5_padata_etype_info2:789,krb5_padata_etype_info:789,krb5_padata_for_us:789,krb5_padata_fx_cooki:789,krb5_padata_fx_error:789,krb5_padata_fx_fast:789,krb5_padata_get_from_typed_data:789,krb5_padata_non:789,krb5_padata_osf_dc:789,krb5_padata_otp_challeng:789,krb5_padata_otp_pin_chang:789,krb5_padata_otp_request:789,krb5_padata_pac_opt:789,krb5_padata_pac_request:789,krb5_padata_pk_as_rep:789,krb5_padata_pk_as_rep_old:789,krb5_padata_pk_as_req:789,krb5_padata_pk_as_req_old:789,krb5_padata_pkinit_kx:789,krb5_padata_pw_salt:789,krb5_padata_redhat_idp_oauth2:789,krb5_padata_redhat_passkei:789,krb5_padata_referr:789,krb5_padata_s4u_x509_us:789,krb5_padata_sam_challeng:789,krb5_padata_sam_challenge_2:789,krb5_padata_sam_redirect:789,krb5_padata_sam_respons:789,krb5_padata_sam_response_2:789,krb5_padata_sesam:789,krb5_padata_spak:789,krb5_padata_svr_referral_info:789,krb5_padata_tgs_req:789,krb5_padata_use_specified_kvno:789,krb5_parse_nam:[46,47,48,345,406],krb5_parse_name_flag:[47,48],krb5_plugin_no_handl:[925,928,932,933],krb5_plugin_ver_notsupp:923,krb5_plugin_vt:923,krb5_pointer:[186,190,197,281,315,353,363,364,375,804,815,852],krb5_post_recv_fn:[380,804],krb5_pre_send_fn:[381,804],krb5_preauth_fail:260,krb5_preauthtyp:[232,233,234,254,804,840,859],krb5_prepend_error_messag:[48,417,918],krb5_princ_compon:789,krb5_princ_nam:789,krb5_princ_nomatch:[223,267],krb5_princ_realm:789,krb5_princ_set_realm:789,krb5_princ_set_realm_data:789,krb5_princ_set_realm_length:789,krb5_princ_siz:[789,793],krb5_princ_typ:789,krb5_princip:[46,47,48,49,91,92,93,94,132,145,147,154,182,218,223,229,235,260,264,267,275,315,319,363,364,375,382,383,384,389,412,414,804,813,825,826,832,833,836,845,846,850,861,862,883],krb5_principal2salt:48,krb5_principal_compar:[47,48,349,350,388],krb5_principal_compare_any_realm:[47,48],krb5_principal_compare_casefold:[350,789],krb5_principal_compare_enterpris:[350,789],krb5_principal_compare_flag:[47,48],krb5_principal_compare_ignore_realm:[350,789],krb5_principal_compare_utf8:[350,789],krb5_principal_data:[47,804,821,868],krb5_principal_parse_enterpris:[345,789],krb5_principal_parse_ignore_realm:[345,789],krb5_principal_parse_no_def_realm:789,krb5_principal_parse_no_realm:[345,789],krb5_principal_parse_require_realm:[345,789],krb5_principal_unparse_displai:[408,789],krb5_principal_unparse_no_realm:[408,789],krb5_principal_unparse_short:[408,789],krb5_priv:789,krb5_process_kei:48,krb5_prog_etype_nosupp:378,krb5_prompt:[352,804,872],krb5_prompt_typ:[263,804],krb5_prompt_type_new_password:[263,789],krb5_prompt_type_new_password_again:[263,789],krb5_prompt_type_password:[263,789],krb5_prompt_type_preauth:[263,789],krb5_prompter_fct:[260,275,804],krb5_prompter_posix:[46,48],krb5_prop:[15,34,41],krb5_pvno:789,krb5_pwd_data:804,krb5_pwqual_moddata:935,krb5_random_kei:48,krb5_rc_close:265,krb5_rc_requir:[323,325],krb5_rc_st:874,krb5_rcach:[71,85,265,804],krb5_rd_cred:[48,325],krb5_rd_error:48,krb5_rd_priv:[48,79,875],krb5_rd_rep:48,krb5_rd_rep_dc:48,krb5_rd_req:48,krb5_rd_safe:[48,875],krb5_read_error:48,krb5_read_password:48,krb5_realm_branch_char:789,krb5_realm_cant_resolv:260,krb5_realm_compar:[47,48],krb5_recvauth:[48,364,375],krb5_recvauth_badauthv:789,krb5_recvauth_skip_vers:789,krb5_recvauth_vers:48,krb5_referral_realm:[48,789],krb5_replay_data:[323,325,326,331,354,356,360,804],krb5_responder_context:[46,365,366,367,368,369,370,371,372,373,804,877],krb5_responder_context_st:876,krb5_responder_fn:[257,804,876],krb5_responder_get_challeng:[46,48,366,876],krb5_responder_list_quest:[46,48,876],krb5_responder_otp_challeng:[46,367,368,804],krb5_responder_otp_challenge_fre:[46,48,368],krb5_responder_otp_flags_collect_pin:[731,789],krb5_responder_otp_flags_collect_token:789,krb5_responder_otp_flags_nextotp:789,krb5_responder_otp_flags_separate_pin:789,krb5_responder_otp_format_alphanumer:789,krb5_responder_otp_format_decim:789,krb5_responder_otp_format_hexadecim:789,krb5_responder_otp_get_challeng:[46,48],krb5_responder_otp_set_answ:[46,48],krb5_responder_otp_tokeninfo:[804,878],krb5_responder_pkinit_challeng:[46,370,371,804],krb5_responder_pkinit_challenge_fre:[48,371],krb5_responder_pkinit_flags_token_:740,krb5_responder_pkinit_flags_token_user_pin_count_low:789,krb5_responder_pkinit_flags_token_user_pin_final_tri:789,krb5_responder_pkinit_flags_token_user_pin_lock:789,krb5_responder_pkinit_get_challeng:[46,48],krb5_responder_pkinit_ident:[804,880],krb5_responder_pkinit_set_answ:[46,48],krb5_responder_question_otp:[46,48,789],krb5_responder_question_password:[46,789],krb5_responder_question_pkinit:[46,48,789],krb5_responder_set_answ:[46,48,366,876],krb5_respons:804,krb5_roundup:789,krb5_safe:789,krb5_salttype_to_str:48,krb5_sam_must_pk_encrypt_sad:789,krb5_sam_send_encrypted_sad:789,krb5_sam_use_sad_as_kei:789,krb5_sendauth:[48,363],krb5_server_decrypt_ticket_keytab:48,krb5_set_default_realm:[44,48],krb5_set_default_tgs_enctyp:[48,261],krb5_set_error_messag:48,krb5_set_kdc_recv_hook:48,krb5_set_kdc_send_hook:48,krb5_set_password:[47,48,169],krb5_set_password_using_ccach:[47,48],krb5_set_principal_realm:[47,48],krb5_set_real_tim:48,krb5_set_trace_callback:48,krb5_set_trace_filenam:48,krb5_sname_match:[47,48,359],krb5_sname_to_princip:[47,48],krb5_string_to_cksumtyp:48,krb5_string_to_deltat:48,krb5_string_to_enctyp:48,krb5_string_to_kei:48,krb5_string_to_salttyp:48,krb5_string_to_timestamp:48,krb5_tc_match_2nd_tkt:[153,789],krb5_tc_match_authdata:[153,789],krb5_tc_match_flag:[153,789],krb5_tc_match_flags_exact:[153,789],krb5_tc_match_is_skei:[153,789],krb5_tc_match_ktyp:[153,789],krb5_tc_match_srv_nameonli:[153,789],krb5_tc_match_tim:[153,789],krb5_tc_match_times_exact:[153,789],krb5_tc_noticket:789,krb5_tc_openclos:789,krb5_tc_supported_ktyp:[153,789],krb5_tgs_name:789,krb5_tgs_name_s:789,krb5_tgs_rep:789,krb5_tgs_req:[789,846],krb5_ticket:[48,185,221,359,363,364,376,804,809,823,845,846,886],krb5_ticket_tim:[274,402,804,825,826,832,833],krb5_timeofdai:48,krb5_timestamp:[45,167,266,336,340,341,342,343,385,395,396,397,398,410,804,808,813,824,832,836,838,846,850,854,861,875,882,884],krb5_timestamp_to_sfstr:48,krb5_timestamp_to_str:48,krb5_tkt_authent:804,krb5_tkt_creds_context:[399,400,401,402,403,404,804],krb5_tkt_creds_fre:[48,403],krb5_tkt_creds_get:[48,401,402,403],krb5_tkt_creds_get_cr:[48,400],krb5_tkt_creds_get_tim:48,krb5_tkt_creds_init:[48,400],krb5_tkt_creds_step:[48,401,402,403],krb5_tkt_creds_step_flag_continu:[404,789],krb5_trace:[41,386,387,953],krb5_trace_callback:[386,804,889],krb5_trace_info:[386,804,888],krb5_trace_nosupp:[386,387],krb5_transit:[804,833],krb5_typed_data:804,krb5_ui_2:804,krb5_ui_4:[333,335,337,358,804,808,813,836,875],krb5_unmarshal_credenti:48,krb5_unparse_nam:[47,48,407,408],krb5_unparse_name_ext:48,krb5_unparse_name_flag:[47,48],krb5_unparse_name_flags_ext:48,krb5_us_timeofdai:48,krb5_use_enctyp:48,krb5_verify_authdata_kdc_issu:48,krb5_verify_checksum:48,krb5_verify_init_cr:[46,48,416],krb5_verify_init_creds_opt:[46,414,415,416,804],krb5_verify_init_creds_opt_ap_req_nofail:789,krb5_verify_init_creds_opt_init:[46,48,414],krb5_verify_init_creds_opt_set_ap_req_nofail:[46,48,414],krb5_vprepend_error_messag:48,krb5_vset_error_messag:48,krb5_vwrap_error_messag:48,krb5_wellknown_namestr:789,krb5_wrap_error_messag:[48,419,918],krb5_x:789,krb5_xc:789,krb5cc_1984:946,krb5cc_320:939,krb5cc_:[917,946,953],krb5cc_p11795:939,krb5cc_ttypa:939,krb5ccname:[15,136,897,941,942,943,946,953],krb5kdc:[0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],krb5kdc_err_key_exp:260,krb5kdc_err_more_preauth_data_requir:931,krb5krb_ap_err_skew:167,krb5krb_err_response_too_big:[279,404],krb5lib:34,krb5plugin_service_locate_ft:933,krb5rcachedir:[901,917,953],krb5rcachenam:[901,953],krb5rcachetyp:[901,953],krb5srv:39,krb:[48,918,919],krb_ap_rep:48,krb_ap_req:48,krb_error:[48,375],krbadmin:[20,22],krbcanonicalnam:22,krbcontain:[20,22],krbcore:936,krbdev:936,krbprincipalnam:22,krbtest:[16,23,35,41,911,912,951],krbtgt:[3,19,26,37,41,43,278,301,644,757,910,911,912,918,939,948],ksu:[919,937,940,953],ksu_opt:946,kswitch:[897,937,940,953],kt:376,ktadd:[14,15,23,32,34,900],kth:919,ktid:317,ktrem:3,ktremov:15,ktutil:[1,2,900,903,918],ktype:[128,232,233,234,261,846],ku:21,kungliga:919,kv5m_context:[135,156],kv:[5,6],kvno:[3,6,11,14,15,16,23,26,29,32,34,41,310,414,831,883,911,918,937,940],l:[11,19,897,898,906,939,942,943,945,946],lab:[5,919],label:[21,919],laboratori:919,lack:[37,378,918],lag:946,larg:[20,23,24,34,36,39,46,100,103,119,288,290,904,918],larger:[24,32,37,896,914,918],largest:35,last:[3,6,9,20,23,24,35,44,48,173,198,200,220,245,314,322,386,735,854,897,898,921,930],last_fail:6,last_req:832,last_success:6,lastpwd:6,latenc:24,later:[3,19,20,21,23,26,33,37,38,39,41,43,136,247,740,896,911,914,918,919,925,932],latest:[34,224,884,904,918,939],latter:[388,897],launchpad:42,law:919,lawsuit:919,lawyer:919,layer:[918,924,927],layout:[43,917],lcom_err:945,lcurs:906,ld:906,ldap:[3,4,5,6,10,20,22,35,38,906,918,919],ldap_conns_per_serv:20,ldap_kadmind_dn:[5,20,22],ldap_kadmind_sasl_authcid:[5,20],ldap_kadmind_sasl_authzid:20,ldap_kadmind_sasl_mech:20,ldap_kadmind_sasl_realm:20,ldap_kdc_dn:[5,20,22],ldap_kdc_sasl_authcid:[5,20],ldap_kdc_sasl_authzid:20,ldap_kdc_sasl_mech:[20,22],ldap_kdc_sasl_realm:20,ldap_kerberos_container_dn:[20,22],ldap_serv:[20,22],ldap_service_password_fil:[20,22],ldapadd:22,ldapi:[20,22,24],ldapsasl_nocanon:38,ldapuri:[3,5],ldb:906,ldflag:906,ldif:22,ldname:906,ldopt:906,lead:[20,946],learn:15,least:[15,23,32,34,39,99,102,153,165,287,289,407,735,752,914,928,932],leav:[3,14,24,28,32,33],left:[20,21,280,912,923],leg:918,legaci:[26,46,885],legal:[280,946],legitim:[25,46,901,946],lehman:919,lehmann:919,len:[12,118,337,339],length:[3,20,33,43,46,48,91,92,99,100,102,103,116,117,119,124,191,203,209,244,254,260,280,284,287,288,289,290,311,336,339,361,397,738,798,799,805,811,818,821,829,848,859,868,869,879,891,910,911,914,915,924,944],lengthi:918,less:[3,20,25,53,897,904,914,915,918],let:[99,287,933,952],letter:[34,39,939],level:[3,5,10,25,37,39,43,904,908,934],liabil:919,liabl:919,lib:[37,904,906,917,919,945],libdefault:[15,20,26,28,33,34,38,39,40,41,43,44,897,900,901,934],libdir:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],libedit:906,libera:936,libev:919,libk5crypto:918,libkadm5:918,libkdb5:921,libkdb_ldap:22,libkeyutil:906,libkrb5:[21,28,43,896,918],libkrb5support:918,libpam:42,librari:[3,18,20,21,24,26,29,38,41,43,46,48,49,50,52,53,54,55,56,59,60,61,62,63,64,65,66,67,68,69,71,72,73,74,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,95,96,97,98,99,100,101,102,103,104,105,106,107,108,111,112,113,114,115,116,117,118,119,121,124,125,126,129,130,132,133,134,135,136,137,138,139,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,169,171,172,173,174,175,176,177,178,179,180,181,182,183,184,189,194,195,198,199,200,201,202,203,204,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,227,228,229,230,231,235,236,237,238,245,246,247,248,250,251,252,253,257,260,261,262,263,264,265,266,267,270,271,272,273,274,275,276,277,278,279,280,283,286,287,288,289,290,294,295,296,298,299,300,301,302,303,304,305,306,307,308,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,342,343,344,345,346,347,348,349,350,352,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,396,399,400,401,402,403,404,405,406,407,408,409,410,412,414,417,418,419,420,865,866,896,897,903,904,906,917,918,919,920,921,922,924,925,926,932,933,934,945,953],libtool:923,libverto:[906,931],licens:[905,906,909,918],life:[3,5,19,23,942],lifetim:[3,6,14,21,23,48,153,365,366,752,826,832,897,918,921,930,939,942,946,953],lightn:918,lightweight:903,like:[3,6,8,12,14,15,19,21,23,32,33,34,37,38,39,41,43,192,897,901,902,904,906,908,923,927,939],likewis:946,limit:[20,23,24,25,34,39,919,946,953],line:[0,3,8,10,12,15,19,20,21,23,28,34,35,37,352,905,906,918,919,938,946,948,951,952,953],link:[0,30,34,901,904,905,906,908,921,924,945],linkdn:3,linker:906,linux:[897,906,918],list:[0,2,3,4,6,10,14,15,19,21,23,26,28,32,34,36,39,40,43,46,48,93,153,164,184,189,195,214,230,231,320,378,412,417,418,419,833,876,897,906,907,917,919,921,922,925,931,934,938,939,943,946,951,952],list_mkei:23,list_polici:23,list_princip:23,listen:[4,8,10,20,34,39,918],listinfo:936,listpol:3,listprinc:3,liter:923,littl:924,live:[6,15,923],lk5crypto:945,lkrb5:945,ll:34,lmdb:[20,23,24,906,918],lname:[56,946],lndir:[903,905],lnsize_in:56,lnsl:906,load:[8,14,17,20,24,34,38,40,906,924,934],load_dump:6,loadabl:[20,21,924],loader:906,local0:20,local7:20,local:[3,5,8,12,14,15,20,21,22,23,28,32,34,36,39,43,46,48,62,64,80,230,231,325,326,327,329,331,344,356,359,360,389,398,408,523,524,717,898,901,902,903,906,908,910,911,912,917,918,925,926,938,939,942,943,945,946,948,953],local_addr:[44,64,82],local_appdata:21,local_port:84,local_realm:946,localauth:[918,926],localauth_plugin:932,localedir:906,localfr:28,localhost:15,localhostnam:43,localstatedir:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],locat:[4,7,8,10,15,19,20,21,22,24,25,29,34,39,41,43,48,897,901,906,907,915,917,918,919,926,934,939,941,942,943,945,946,947,948,953],locate_plugin:933,lock:[6,20,23,24,34,35,736,737,915,918,939],lockdown_kei:[3,19,918],lockit:3,lockout:[3,20,24,25,30],lockout_polici:35,lockoutdur:[3,35],lockouttim:3,log:[8,9,23,24,26,28,33,34,37,39,46,48,737,897,918,926,938,939,941,946,952,953],log_:20,log_daemon:20,logic:[39,918],login:[20,21,33,38,41,46,939,946,953],logon:[20,333,658,918],logout:[939,941],longer:[11,19,23,25,33,39,43,49,65,67,68,72,73,76,77,78,91,92,93,111,113,115,120,122,123,125,126,132,141,143,145,150,153,154,163,164,169,172,173,174,175,176,177,178,180,181,182,183,194,195,224,227,229,230,231,236,261,265,268,272,275,280,282,286,294,310,315,317,318,321,322,324,325,326,327,328,329,330,331,332,335,338,339,344,345,354,355,356,357,359,360,363,375,389,401,403,405,406,408,906,918,939,942],look:[0,8,12,15,20,21,23,28,37,38,39,43,389,904,906,923,939,942,946],lookasid:906,lookup:[21,22,33,38,39,194,815,906,918,933],lose:6,loss:[23,919],lost:[17,904,919],lot:39,lower:[3,19,21,43,230,934,944,951],lowercas:[23,38,901],lowest:21,lpr:20,lr:[3,11,854],lr_type:854,lr_type_interpretation_mask:789,lr_type_this_server_onli:789,lrealm:[210,227,377],ls:946,lsocket:906,lss:906,ltd:919,luke:39,luser:319,lxml:908,m:[3,4,5,6,10,14,19,20,21,23,26,34,39,898,918,919,939],mac:903,mach:[21,919],machin:[4,8,12,14,15,17,18,21,31,32,34,37,38,39,897,902,906,938,939,952,953],maco:[21,342,897,903,918,919],macro:[97,99,100,102,103,108,113,114,130,184,189,287,288,289,290,294,295,299,329,330,375,403,421,827,889,946],made:[8,21,23,34,41,136,253,269,378,897,918,919,927,929,947,953],magic:[135,156,805,807,808,809,811,813,818,821,823,824,825,826,829,831,832,833,834,836,845,846,848,850,854,859,868,869,873,882,883,886,890,891,895],mai:[3,6,8,10,11,14,15,19,20,21,22,23,24,25,26,28,33,34,35,36,37,38,39,40,41,43,46,99,107,126,158,195,224,228,229,241,245,258,262,287,330,359,375,380,381,388,389,414,731,847,865,877,889,898,901,904,906,907,910,911,914,915,918,919,922,924,925,927,928,929,930,931,934,936,938,939,941,942,946,951,953],mail:[20,897,939,946,951],mailbox:901,mailman:936,main:[368,371,936],maintain:[0,9,15,20,23,904,906,953],mainten:[3,6,23],maj_ver:923,major:[43,905,923],make:[0,3,6,12,14,15,17,20,21,22,23,25,26,28,32,33,34,35,37,39,41,43,48,112,236,241,250,301,368,371,403,896,904,905,906,908,910,918,919,924,938,942,947],makedepend:903,makefil:[904,906,908],malform:[166,223,619,910],malici:[3,46],malloc:934,man:[0,3,21,901,906,918],manag:[5,19,23,33,918,934,937,953],mandatori:[23,113,114,129,130,294,295,298,299,912],mandir:906,mani:[3,17,21,28,35,39,41,927,939,953],manipul:[22,23,45,827,900],manner:[5,919],manual:[0,6,10,15,23,33,34,904,906,918],manual_test:904,map:[21,28,33,34,43,906,918,924,925,932,946,951],mapsiz:[20,24],marc:919,mark:[3,6,20,21,34,342,919],marker:[910,918],markup:[0,908],marshal:[910,911,918],masachusett:953,mask:[66,83,142,153,157],masquerad:[17,938,939],massachusett:[909,919],master:[3,4,5,6,10,20,26,34,35,39,41,902,907,917,918],master_kdc:[21,39],master_key_nam:[5,6,20],master_key_typ:[5,6,14,20,34],match:[0,2,3,6,15,19,20,21,28,29,33,37,38,43,48,59,60,119,151,153,195,223,224,267,301,310,359,363,375,403,745,746,747,748,749,750,751,753,756,846,897,901,915,917,918,934,948,951,953],materi:[14,46,918,919,923],matt:919,matter:[17,21],max_keytab_name_len:789,max_lif:[6,20,34],max_read:[20,24],max_renew_lif:6,max_renewable_lif:[20,34],max_renewable_ticket_lif:5,max_ticket_lif:5,maxfailur:[3,35],maximum:[3,5,6,10,14,15,20,21,23,24,33,39,46,311,361,896,931,939,942],maxlif:[3,19,23],maxnumb:3,maxpathlen:766,maxrenewlif:[3,5,19,23],maxtktlif:[5,23],mcred:153,md4:[26,919],md5:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],mdb:24,me:41,mean:[3,12,14,20,21,23,33,34,37,46,902,907,919,939,946,953],meaning:3,meant:939,measur:[25,896],mech:[28,917,918,953],mech_typ:924,mechan:[3,16,20,21,22,23,36,37,39,40,43,46,154,250,692,693,901,910,911,917,918,922,923,926,931,933,942,953],mechglu:[919,924],media:[5,21],medvinski:946,meet:951,megabyt:[20,24,905],mellon:919,member:20,membership:46,memori:[15,41,43,48,93,142,223,231,302,323,325,326,331,356,357,360,414,827,897,900,906,918,923,925,932],memset:46,mention:[20,22,919],merchant:919,merg:[18,20,48,919],messag:[3,8,20,21,24,34,41,48,78,363,375,381,531,538,718,741,807,832,836,845,846,865,866,883,889,901,903,911,918,919,923,938,939,945,946,948,953],message_out:169,message_typ:882,met:[919,946],metadata:6,method:[21,25,39,230,910,918,920,921,922,923,925,928,929,930,931,932,933,934,935,942],mexico:919,mgluep:919,mic:[532,918],mic_token:43,michigan:919,microsecond:[266,385,410,808,824,875,910],microsoft:[20,21,26,29,42,43,382,452,918,924],microsystem:919,middl:901,might:[14,17,23,28,29,34,35,38,39,43,904,906,910,919,923,938,953],migrat:[14,23,41,918],miller:[919,953],min:[3,19,898],min_ver:923,minclass:3,minim:[6,14,23,24,918],minimum:[3,20,23,33],minlength:3,minlif:3,minor:[14,43,905,918,923,924,933],minor_statu:[43,924],minu:[20,915],minut:[5,20,21,23,898,901,938,939,953],mismatch:[43,260,342,938],miss:[267,908],mission:946,mistak:938,mistakenli:171,mit1:911,mit:[3,5,12,14,15,17,19,20,21,24,28,30,31,32,34,38,39,41,43,45,46,896,897,903,905,906,908,909,910,911,912,922,924,926,927,931,934,936,938,939,942,953],mitig:[23,25,46,901,918],mitiys4k5:34,mix:939,mk_cmd:906,mk_req:856,mkdir:904,mkei:[3,6],mkey_convert:6,mkey_fil:6,mkeynam:[5,6,10],mkeytyp:[5,6],mkeyvno:[5,6],mkvno:6,mm:898,modbi:6,mode:[3,6,8,14,20,41,467,479,730,906,918,942,946],modern:[14,15,23,38,918],modestli:40,modif:[6,9,19,21,34,919],modifi:[3,6,9,18,19,23,25,28,34,40,43,100,103,114,136,144,146,158,288,290,295,312,365,366,866,906,918,919,929,934,942],modify_polici:23,modify_princip:[23,26],modnam:[21,28],modpol:3,modprinc:[3,23,35,37,40,928],modtim:6,modul:[3,4,6,20,21,23,35,252,268,906,908,916,917,918,920,921,922,925,927,928,929,930,931,932,933,934,935,942,953],module_nam:21,modulenam:21,modulepath:21,modulo:915,moira:919,mon:[3,35],monitor:25,month:[898,918],more:[6,14,15,19,20,21,22,23,25,29,32,34,35,37,38,39,41,43,46,262,279,344,404,565,738,740,761,889,897,900,901,903,906,907,911,918,925,931,936,938,953],more_preauth_data_requir:922,morn:33,most:[2,6,17,20,21,23,24,25,26,28,33,34,37,39,40,41,43,48,154,897,900,901,903,918,922,923,924,939,941,953],mostli:906,move:[20,27,34,48],ms:[20,29,39,48,383,684,918,919],msdn:918,msec_dirbit:789,msec_val_mask:789,msg:213,msg_type:[832,845,846],mslsa:897,mssclogin:21,much:[14,25,38,153,938],multi:[35,37,918],multihom:21,multipl:[3,10,14,16,20,21,22,23,24,28,34,35,36,37,39,43,46,847,897,901,904,918,923,924,931,942,951,953],multipli:35,multithread:48,muse:919,must:[2,3,7,8,11,14,15,19,20,21,22,23,24,26,28,29,32,33,34,35,36,37,39,43,46,57,58,69,74,78,99,100,102,103,113,117,119,121,125,126,136,146,152,153,158,173,176,195,198,200,220,224,228,241,247,268,270,271,274,275,279,282,287,288,289,290,294,296,312,314,317,322,326,331,345,359,368,371,373,375,402,407,728,729,731,738,740,742,745,746,747,748,749,750,751,752,753,756,827,847,870,897,904,905,906,910,911,912,914,915,918,919,921,923,924,925,928,930,931,932,934,938,939,944,946,948,953],mutabl:847,mutex:847,mutual:[34,330,375,437,503,807,942,946],my:16,my_cach:946,my_proxi:21,my_respond:46,mydir:897,mydomain:20,mymodul:28,mypreauth:28,myrealm:46,myremotetokentyp:20,n:[3,6,10,21,28,37,344,898,942,943,946],name:[2,3,4,5,6,8,10,12,14,15,16,19,20,21,22,23,24,28,29,30,32,33,34,36,37,40,46,48,49,50,59,60,141,147,153,155,159,214,222,223,227,230,235,246,247,252,260,264,267,278,300,301,310,315,317,319,320,329,333,336,342,343,350,352,359,362,365,377,382,384,406,407,408,409,412,414,501,638,640,641,642,643,647,652,663,740,751,813,833,862,872,876,883,898,900,905,908,910,911,914,917,918,919,920,923,925,932,933,934,935,939,941,942,943,944,945,946,948,953],name_s:306,name_str:37,name_typ:37,namelen:311,nat:[21,23,918],nation:919,nativ:[33,368,371,896,906,910,914,917,918],natur:38,naval:919,navi:919,ncsa:42,nctx_out:176,ndnhnmn:898,nearli:3,necessari:[3,14,21,22,23,24,33,34,37,39,43,120,122,123,260,343,387,407,922,923,927,938,939],necessarili:14,need:[4,6,12,14,15,19,20,21,23,32,33,34,35,37,38,39,40,41,43,46,49,64,65,67,68,72,73,76,77,78,91,92,93,99,100,102,103,111,113,115,125,126,132,141,143,145,150,153,154,163,164,169,172,173,174,175,176,177,178,180,181,182,183,194,195,224,227,229,230,231,236,258,261,265,268,272,275,279,280,282,286,287,288,289,290,294,310,315,317,318,321,322,323,324,325,326,327,328,329,330,331,332,335,336,338,339,344,345,354,355,356,357,359,360,363,364,375,389,401,403,404,405,406,408,565,739,740,761,897,898,903,904,905,906,908,911,918,924,925,927,932,934,936,938,939,942,945],needchang:[3,5],neg:[28,885,914],neglig:919,negoex:[918,926],negoti:[910,918,924],neither:[3,325,919,942,943,946],nersc:21,net:[21,42],netbio:54,netbsd:[918,919],netlib:906,netlogon:452,network:[3,15,17,21,23,25,29,32,34,38,39,40,43,46,260,375,523,524,525,526,903,906,938,939,952,953],neuman:953,never:[3,14,15,17,19,20,23,24,35,100,103,228,288,290,915,938,939],new_message_out:866,new_mkey_fil:6,new_princip:3,new_reply_out:[865,866],new_stat:108,newer:[6,14,20,23,906],newest:23,newli:[3,6,26,37,107,113,125,126,176,294,329,330,359,363,364,375,897,904,918],newlin:[344,352],newprinc:3,newpw:[166,382,383],next:[3,6,17,23,34,35,48,99,100,102,103,287,288,289,290,730,904,910,911,915,918,922,931,939,946],nf:[38,938],nii:946,nippon:919,nist:[21,40],nitem:923,nktype:846,nl:918,nlgilman:12,no_auth_data_requir:3,no_host_referr:[20,39],noaddress:21,nofail:46,nofork:4,nokei:[3,23,37],non:[2,3,14,19,21,23,26,33,37,43,44,99,100,102,103,113,129,130,155,224,241,245,250,269,287,288,289,290,294,298,299,300,315,330,342,359,375,382,383,388,865,910,914,918,942,945,946],nonc:[358,824,832,846,918],none:[3,20,21,22,26,36,37,57,58,132,273,285,304,369,372,901,911,946,953],nonexist:[23,918],noninfring:919,nonrepudi:37,nonzero:[21,224,948],noout:37,nopw:3,nor:[919,943,946],norandkei:3,norealm:[14,20],normal:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],north:919,nosync:[20,24],notabl:23,note:[3,5,6,14,20,21,23,26,32,34,154,241,245,898,904,931,939,942,946,952,953],noth:[8,901],notic:[17,24,919],notifi:936,novel:919,now:[8,14,34,37,39,235,260,275,730,918,939],nowait:[8,12,34],nrl:919,nss:919,nt:[638,640],nt_wellknown:763,ntlm:918,ntt:919,num:9,num_data:[98,100,103,114,130,288,290,295,299],num_prompt:[352,872],number:[2,3,4,5,6,8,9,10,11,12,14,19,20,21,23,24,35,36,37,39,46,48,66,78,80,83,100,103,112,135,156,288,290,310,315,325,326,327,331,337,352,356,358,359,360,521,528,723,738,740,808,827,846,850,875,885,896,898,900,904,906,908,910,911,912,914,918,919,922,931,943,944,945,946,948],numer:[6,34,166,382,383,898,918,943],numwork:10,o:[3,5,6,898,905,906,919,939,943],object:[3,5,6,20,21,22,23,24,25,28,35,36,43,48,262,269,740,904,906,910,918,919,920,921,922,923,924,925,928,929,930,931,932,933,934,935],observ:[25,29,35],obtain:[2,3,15,16,17,20,21,23,25,26,33,34,37,43,46,48,80,135,230,258,271,274,329,330,359,375,402,403,414,440,618,837,897,900,906,915,918,919,934,935,937,938,942,946,948],obvious:32,occasion:34,occur:[3,6,9,78,342,386,918],occurr:171,octet:48,odd:939,oeap:481,off:[15,21,24,25,28,33,35,39,352,361],offer:[21,24,40,906],offlin:[14,25,942],offset:[10,48,410,910,915],often:[20,22,23,28,33,38,39,900,927,953],oid:[28,43,918,924],oid_op:919,ok:[5,20,21,23,24,34,918],ok_as_deleg:3,ok_to_auth_as_deleg:3,okai:[3,939,943],old:[2,3,6,14,20,21,23,34,37,243,346,420,918,938],old_cod:[419,420],old_princip:3,oldcc:919,older:[14,23,918,931],oldest_kvno_to_keep:3,om_uint32:[43,924],omit:[11,22,28,39,408,716,717,910,914,934],onc:[3,6,14,15,21,23,34,43,46,78,361,735,897,901,904,929,933,938,953],one:[2,3,5,6,9,15,16,17,19,20,21,23,24,25,26,28,32,34,35,36,37,38,39,40,41,43,46,48,153,165,243,263,264,270,271,275,279,330,333,344,356,360,389,740,897,898,900,901,904,906,907,908,910,911,915,918,920,922,923,925,928,931,932,938,939,942,944,946,947],ones:[21,25,34,904,923,939],onli:[3,4,6,8,9,10,14,15,18,19,20,21,22,23,26,28,32,33,34,35,38,39,41,43,46,48,54,114,153,224,228,241,245,295,325,361,365,366,545,731,751,862,889,896,897,902,904,906,910,915,918,919,924,925,931,932,934,938,939,942,946,948,951,953],onlin:[14,25],onlyrealm:[14,20],onto:[17,21,32,34,906,924,939],opaqu:[48,286,847,918],open:[6,21,24,46,48,50,305,315,317,342,387,755,771,901,915,918,919,935,942],openldap:[3,5,23,24,30,906,919],openldap_ldapconf:20,opensc:917,openssh:[28,38],openssl:[21,37,906,918],openvis:[3,919],oper:[2,3,5,9,10,14,15,19,20,21,22,24,26,28,33,34,35,37,41,43,48,62,119,121,136,156,158,382,383,386,755,837,847,897,903,904,905,906,911,915,917,918,919,928,932,942,946,953],oppos:37,opt:[46,229,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,945],optim:906,optimist:[20,40,48,254],option1:21,option2:21,option:[2,11,12,15,19,22,23,24,28,29,34,35,36,37,39,43,48,59,60,224,225,226,229,232,233,234,235,253,260,269,275,325,326,329,330,331,344,375,403,414,416,546,738,808,809,813,824,825,832,836,840,841,846,884,900,905,918,921,922,923,925,928,930,932,939,953],oracl:[42,919],order:[3,4,6,14,16,17,19,20,21,22,23,32,33,34,35,37,38,43,46,48,245,738,897,900,901,905,906,910,914,919,920,924,934,953],ordinari:[14,904,918,953],ordinarili:[2,15,245],org:[5,21,22,42,904,905,908,918,919,936,952,953],organ:[905,919],orig_hostnam:194,origin:[3,14,21,23,39,43,46,906,919,924],os:[20,34,48,904,917,918],osconf:905,osf:680,other:[3,4,6,10,14,15,19,20,21,23,24,26,28,34,35,37,38,39,43,46,154,279,310,359,404,644,740,837,896,897,900,903,904,905,906,910,911,914,918,919,922,924,928,929,930,932,933,934,936,938,939,944,946,951,952],othernam:37,otherrealm:21,otherwis:[3,6,14,20,21,23,29,33,34,36,37,39,43,49,52,54,62,64,65,67,69,72,73,74,76,77,78,79,81,82,84,85,86,87,88,89,90,95,96,97,98,99,100,102,103,104,105,106,107,108,110,111,112,113,114,115,116,117,118,121,124,125,126,129,130,134,142,150,153,157,158,162,163,164,166,170,172,173,174,175,177,178,180,181,182,183,184,185,187,189,192,193,195,217,224,235,236,238,248,260,261,264,265,266,267,271,272,273,274,275,276,277,278,279,280,283,284,285,286,287,288,289,290,294,295,296,298,299,300,301,319,321,322,324,325,326,327,328,329,330,331,332,333,335,337,338,339,342,345,347,348,349,350,354,355,356,357,358,359,360,361,362,363,364,374,375,376,385,388,390,391,392,394,395,397,398,400,401,402,403,404,405,414,897,906,911,919,921,923,930,939,942,943,944,946],otp:[3,16,25,30,46,368,696,698,699,722,738,917,918],ou:[5,22],our:[20,36,903,904,919],out:[3,8,12,21,23,24,33,35,36,37,41,43,49,50,56,59,60,63,64,65,66,67,68,69,71,72,73,74,76,77,78,89,91,92,93,95,96,97,99,101,102,104,105,107,108,111,112,113,115,116,117,118,119,121,124,125,126,129,130,132,134,135,138,141,142,143,145,149,150,152,153,154,158,163,164,166,169,170,172,173,174,175,176,177,178,180,181,182,183,184,185,187,189,192,193,194,195,223,224,227,229,230,231,235,236,238,251,260,261,262,264,265,266,267,268,269,272,273,274,275,279,280,282,286,287,289,294,296,298,299,301,303,305,306,307,308,310,311,314,315,317,318,320,321,322,323,324,325,326,327,328,329,330,331,332,335,336,337,338,339,344,345,347,354,355,356,357,358,359,360,361,363,364,368,371,374,375,382,383,389,390,391,392,394,395,396,397,398,401,402,403,404,405,406,408,409,410,412,532,533,535,536,539,897,906,918,919,938,941,948],out_cr:[224,225,226,375],out_flag:238,outaddr:172,outag:[20,39],outauthdat:322,outbuf:[223,327,328,329,330],outcc:134,outcksum:131,outcr:177,outdata:178,outfil:6,outgo:[15,924],outlin:[0,29],outprinc:182,outptr:[186,190],output:[3,6,9,15,20,23,26,34,41,43,48,99,100,101,102,103,107,117,119,166,181,224,279,287,288,289,290,296,352,359,361,364,404,866,875,897,908,918,920,921,923,942,943,945,948,953],output_cr:43,output_cred_handl:43,output_message_buff:43,output_nam:924,output_payload_buff:43,outputinto:102,outreach:14,outsid:[15,897,953],ov:3,over:[0,10,14,15,20,21,23,24,28,32,34,36,38,39,43,46,48,107,113,114,117,155,164,294,295,296,300,301,325,363,375,817,918,920,926,934,938,939],overrid:[3,6,10,14,20,21,26,36,48,378,380,381,386,387,865,906,914,918,942],overridden:[2,10,11,19,21,901,918],overview:903,overwrit:[6,23,384,941],overwrite_cr:43,overwritten:[20,827],own:[0,3,15,20,21,23,24,25,34,38,381,918,921,923,924,935,938,939,946,952],owner:919,ownership:901,p27:42,p:[3,4,5,6,7,8,10,11,12,14,19,21,23,40,897,918,919,939,941,942,943,946,947,948],pa:[253,911,912,931],pa_as_fresh:912,pa_config_data:910,pa_hardwar:931,pa_real:922,pa_replaces_kei:931,pa_typ:[859,910],pa_type_list:[922,931],pac:[3,20,48,340,341,650,660,685,860,863,918,942],pac_client_info:[300,301,336,343],pac_out:301,pac_privsvr_enctyp:3,packag:[29,34,904,919],packet:[20,25,36,330,918,931],pad:[43,48,99,100,103,104,287,288,290,536,915],padata:[845,846,922,931],padl:919,page:[0,3,21,23,905,906,918],pair:[6,20,21,26,841],pam:33,parallel:[10,39,904,918],param:[49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420],paramet:[5,6,10,20,28,35,36,43,46,48,169,229,323,325,343,906,907,910,917,918,924,928,931,946],parent:[21,39,897,917],pars:[3,28,43,45,46,48,235,260,264,267,278,356,360,368,371,903,910,918],part:[14,21,23,26,32,41,199,264,267,278,283,301,344,359,384,823,833,845,883,897,902,910,911,915,919,923,924,934,946,953],parti:[28,36,43,918,919,953],partial:[14,19,23,46,915],particip:[21,34],particular:[2,11,14,16,17,19,20,21,37,43,46,317,904,906,919,938,939],particularli:[14,17,25,39,938,945],partit:39,pass:[14,20,21,28,36,43,99,100,102,103,228,250,270,271,275,279,280,282,287,288,289,290,325,368,371,380,381,382,386,387,889,906,924,933,942,946],passcod:669,passiv:25,passkei:693,passwd:[5,33,895,919,946],passwd_phrase_el:[804,873],password:[3,4,5,6,9,10,11,14,15,16,17,19,20,21,22,23,24,25,26,28,29,32,33,34,35,36,37,39,40,43,48,233,245,258,618,620,719,720,721,739,740,897,902,917,918,922,926,937,939,944,946,952,953],password_changing_servic:3,password_expir:[245,838],past:[3,936],pasword:25,patch:23,path:[4,5,8,20,21,22,25,28,29,34,39,359,904,906,908,918,946,953],pathnam:[4,8,21,23,24,28,29,37,900,904,907,953],pattern:[6,21,28,951],payment:919,pdf:0,pem:[16,21,29,37,948],peopl:20,pepper1:107,pepper2:107,pepper:48,per:[3,6,9,10,14,18,20,21,23,26,28,36,39,43,46,897,920,922,925,928,929,931,932,933,934,935],perfect:901,perform:[3,4,5,6,12,14,19,20,21,22,24,25,26,34,37,38,39,43,46,62,91,250,254,258,359,363,375,382,383,386,416,437,847,897,918,919,928,929,930,939],perhap:[3,14,20,23,24],period:[6,8,14,17,20,21,23,24,35,939,942],permiss:[3,18,19,20,23,34,43,137,147,159,897,918,919,939],permit:[3,19,20,21,26,36,48,194,251,356,360,917,918,919,942,952],permitted_enctyp:[21,26],persist:[21,897],person:[17,34,919,938,939],pertain:[10,919],pgp:[905,936],phase:946,phrase:895,physic:[32,39],pick:[20,25,37,904],pid:[4,8,10,918],pid_fil:[4,8,10],piec:[35,265],pin:[369,372,728,731,735,736,737,738,870],pipermail:936,pkc:[21,740],pkcs11:[21,906,917,918,919],pkcs11_modnam:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],pkcs12:21,pkinit:[3,16,23,25,30,40,41,107,649,687,688,689,690,740,906,913,918,919,926,942],pkinit_allow_upn:[20,21],pkinit_anchor:[3,20,21,37,942],pkinit_cert_match:[3,21,37,918],pkinit_dh_min_bit:[20,21],pkinit_eku:21,pkinit_eku_check:[20,21,37],pkinit_ident:[20,21,37],pkinit_ind:[16,20],pkinit_kdc_hostnam:[21,37],pkinit_pool:[20,21],pkinit_require_crl_check:[20,21],pkinit_require_fresh:[20,37],pkinit_revok:[20,21],pkinit_san:21,place:[2,8,14,15,21,26,28,32,33,37,39,43,44,46,48,107,117,229,264,267,279,296,301,336,364,376,404,827,866,906,908,915,921,929,941,946,952],placehold:[903,905],plain:911,plaintext:[116,533],plan:23,platform:[24,885,896,897,904,905,906,918],pleas:[0,15,20,738,936],plu:[20,939,946],plug:919,pluggabl:[21,28,918,923,926,929,934],plugin:[3,20,22,903,906,916,917,918,919,934],plugin_base_dir:21,pm:898,pnl:21,po:903,point:[3,14,15,21,23,32,34,43,330,407,414,827,897,902,906,918,936],pointer:[24,43,44,46,91,135,136,173,198,200,203,209,213,217,220,230,231,256,262,263,322,323,330,332,357,365,366,386,395,407,825,827,832,872,883,920,921,922,923,928,929,931,933,935],pol:[3,19],polici:[3,4,5,6,16,19,20,21,24,25,34,35,169,359,918,926,927,928,935,939,943,944],policy_nam:5,poll:[4,8,20,23,918],pool:14,pop:32,popul:[14,24,44,148,915],popular:34,port:[3,4,7,8,10,12,15,20,21,23,34,36,41,44,48,62,331,524,526,917,953],portabl:897,portiion:919,portion:[21,36,153,266,317,385,410,751,808,813,824,836,875,919],portmapp:23,portnum:10,pose:14,posit:[6,19,28,35,885,914],posix:[6,885,896,911,912,915],possess:[37,939],possibl:[3,5,6,14,15,17,20,21,22,24,25,26,32,34,35,37,38,39,43,46,48,93,166,224,740,900,901,906,918,919,922,923,931,936,939,951],post:[48,897,936],postdat:[3,19,20,267,939,942,943],potenti:[14,32,34,46,902],power:[20,24,25,39,918],pp:898,pr:[347,903],practic:[14,21,46,99,287,918],pre:[0,16,20,22,43,48,91,260,329,330,359,363,364,375,380,859,908,911,918,919,929,942],pre_auth_typ:[232,233,234],preauth:[20,672,841,910,918,919,922,931],preauth_list:[254,840],preauth_list_length:[254,840],preauth_plugin:[922,931],preauth_requir:[922,931],preauthent:[3,16,20,21,23,25,28,30,37,41,46,48,250,722,832,845,846,859,876,910,918,923,926,939,942,943],prebuilt:904,preced:[10,14,21,39,914,946,953],precis:33,precomput:48,predefin:39,prefer:[3,21,38,43,236,900,901,918,925],preferred_preauth_typ:21,prefix:[20,39,48,344,904,906,918,924,945,946],preiniti:[117,119,121,296],prepar:[48,79,318,403],prepend:[39,346,420,906],preprocessor:906,prerequisit:908,preselect:942,presenc:[21,910],present:[8,14,16,20,21,22,23,28,34,36,37,43,46,165,245,301,325,333,336,345,354,365,366,373,388,618,711,713,714,884,900,901,910,914,915,918,934,939,943,948,953],preserv:[6,919],presid:919,pressvr:14,presum:901,prevent:[2,3,19,20,21,25,26,29,40,330,521,522,901,918,919,929,938,942],previou:[0,3,21,23,34,37,42,44,156,250,261,279,384,404,419,420,910],previous:[3,6,23,43,48,904,918],prf:[48,118,911,918],primari:[3,4,7,8,9,14,17,20,21,23,24,31,35,38,39,41,43,48,145,897,918,920,929,933,935,936,941,942,947,951,953],primarili:[24,55,949],primary_kdc:21,princ1:[37,348,349,350,362],princ2:[37,348,349,350,362],princ:[3,6,21,49,50,91,92,93,94,388,793,794,795,796,797,798,799,800,911],princ_flag:6,princ_lockout:6,princ_look_ahead:946,princ_meta:6,princ_nam:[37,941],princ_out:154,princ_stringattr:6,princ_tktpolici:6,princip:[2,3,4,5,6,7,8,9,10,11,12,14,16,17,19,20,21,22,24,25,26,28,29,30,31,32,33,36,37,40,41,43,45,46,48,78,141,147,148,153,155,159,166,223,229,235,242,260,264,267,275,300,301,310,315,320,329,333,340,341,342,343,359,363,364,375,403,406,407,408,409,412,414,501,641,648,663,707,709,751,763,825,826,832,836,845,846,850,862,897,898,900,901,907,911,912,914,917,918,920,921,927,928,930,931,932,935,938,939,942,943,944,946,947,948,951,952,953],principal_databas:8,principal_nam:37,principal_out:[344,345],principal_seq:37,principalnam:918,principl:710,princnam:[25,35,40,46,897],princname_out:336,print:[3,6,7,8,361,918,945,946,948],printabl:[365,373],prior:[6,8,14,20,21,23,39,41,43,136,265,919,923],priorit:39,prioriti:[14,20,39,230,897,901,920],priv:[48,918],privat:[21,37,718,906,911,912,918,936],privileg:[3,19,34,43,48,253,918,938,952,953],privsvr:[300,301,342,343],privsvr_kei:[340,341],prng:[121,918],probabl:[6,12,14,34,904],problem:[14,23,330,901,918,936],proce:946,procedur:[6,26,32,34,903,904],proceed:23,process:[3,4,6,8,9,10,14,15,20,21,23,24,25,34,38,43,46,48,136,154,169,355,414,897,900,901,918,921,922,925,928,929,930,931,933,935,942,953],procur:[37,919],produc:[6,21,46,104,124,905,915,922,925,931,943,945],product:[34,919],prof_no_rel:934,profil:[15,18,20,21,48,136,388,897,900,901,903,907,918,919,926],profile_module_init:934,profile_module_init_fn:934,profile_releas:262,profile_vt:934,profit:919,program:[2,3,4,6,8,12,15,20,21,23,26,28,30,32,33,34,37,38,39,41,43,46,56,268,378,901,903,904,905,908,910,917,918,919,939,945,946,953],programm:945,programmat:46,progress:[14,20],prohibit:[3,919],project:[0,701,906,918,919,923,953],promot:[14,919],prompt2:361,prompt:[2,3,5,6,23,34,46,48,260,361,719,720,721,722,870,872,902,918,922,938,939,944,946],prompter:[245,260,263,275,352,870,872,877],prone:918,proof:[48,939],propag:[4,6,7,8,14,17,19,20,21,24,31,35,903,918,919,938],proper:[12,23,37,359,904],properli:[29,34,37,41,896,906],properti:[21,937],propog:8,proponli:[4,23],proprietari:36,protect:[6,15,25,26,32,35,37,40,43,78,247,326,331,740,847,901,918],protocol:[2,3,14,21,23,29,39,43,48,247,301,321,405,674,695,723,832,836,845,846,901,903,916,918,928,939,942,948,953],prototyp:[903,923],prove:[46,912,922,931],provid:[0,3,4,10,15,21,22,23,24,26,28,29,32,34,37,38,39,41,43,46,98,229,359,372,414,896,897,904,906,918,919,921,924,927,930,934,938,946,953],provis:919,proxi:[20,21,25,30,36,39,43,918,939,943],proxiabl:[3,20,21,48,840,939,942,943,946],proxy_imperson:910,pseudo:[48,903],pto:183,ptr:[38,43,197,281,339,353,802,803,832,833,883],pty:[903,919],publish:[38,919],pull:918,punctuat:[3,21,34,944],purg:[3,6,14,918],purge_mkei:23,purgekei:[14,23,37],purpos:[10,15,21,23,26,28,34,906,919,942,949],put:[4,10,34,344,808],pw:[3,918],pw_expir:6,pwchang:20,pwd:904,pwexpdat:3,pwexpir:[3,19,26],pwqual:[28,918,926],pwqual_plugin:935,pwservic:20,py:908,python:[29,908,918],q:[3,11,14,37,941,946,948],qop_req:43,qop_stat:43,qualif:[21,918],qualifi:[3,15,19,21,23,953],qualify_shortnam:[21,38,918],qualiti:[21,28,918,926,937],queri:[3,21,39,43,46,918],question:[0,20,39,48,368,371,738,739,740,876,877,936],queue:[20,919],quietli:941,quit:[6,32],quot:[3,6,344,406,408,898],quux:21,r13:6,r18:6,r:[3,4,5,6,7,8,9,10,14,21,28,34,284,939,942,943,946,953],r_address:824,rabbit:39,radiu:[20,36,918],randkei:[3,14,23,26,34,37,918],random:[3,6,14,20,21,23,25,34,48,911,915,918],random_data:124,randomli:[2,26],randsourc:120,rang:942,rapidli:15,rare:[24,37,898,900],rassen:919,rather:[3,4,5,6,10,15,20,21,23,32,38,39,56,279,404,897,904,911,924,942],raw:[20,904],rc2:479,rc4:[20,26,918],rc:34,rcach:[43,71,85,265,323,325,901],rcache2:[901,918],rcmd:21,rcommand:643,rcptr:265,rctmpdir:907,rctx:[46,365,366,367,368,369,370,371,372,373,877],rdata_out:[323,325,326,331,354,356,360],rdn:[21,33,38,43],re:[3,5,6,14,23,34,41,730,901,924,938,953],reach:[20,21,24,164,314,915],react:243,read:[3,5,6,9,11,20,21,22,23,34,35,37,46,48,250,260,262,318,352,371,414,906,914,918,931,934,938,943,953],readabl:[15,21,32,169,898,900,902,918],reader:[21,24],readi:[6,34],readlin:906,readm:[903,905],real:[21,350,385,707,946],realiti:0,realloc:44,realm1:10,realm2:10,realm3:10,realm:[3,4,5,6,7,8,10,12,14,15,16,19,22,24,25,26,29,30,33,34,36,37,38,40,43,44,46,48,49,50,59,60,91,92,93,94,153,214,230,235,251,260,264,267,278,279,284,300,342,344,345,350,359,388,389,403,404,408,502,708,711,712,713,714,716,717,727,795,796,797,798,813,821,825,833,836,845,846,862,865,866,868,869,883,897,906,907,910,911,912,914,917,918,926,933,935,938,939,942,946,951,952,953],realm_try_domain:21,realmlist:214,realmnam:[37,46],realmsp:[230,231],reason:[14,17,21,24,28,33,39,342,896,910,919,938,939,946],reboot:[20,34,902],rebuild:[906,908],receiv:[3,4,8,9,14,20,21,37,39,41,43,48,223,245,273,325,326,330,331,354,356,360,363,374,375,876,921,922,931,932,935,939,953],recent:[2,6,17,20,25,26,37,48,901,912,918,939],recipi:[824,919],recogn:[3,20,21,37,41,942,951],recognit:[918,919],recommend:[5,6,15,17,20,21,23,32,34,39,40,43,904,905,906,936,939,941],recomput:136,reconf:903,record:[6,10,21,33,34,38,39,901,911,914,915,918],recov:[6,918,922],recurs:[6,24,918],recv_hook:380,recvauth:[363,375],red:[692,693,919,953],redhat:918,redirect:[21,34],redistribut:919,reduc:[14,21,33,100,103,288,290,906],redwood:919,ref:5,refcount:918,refer:[3,5,15,19,20,22,23,39,43,45,48,87,89,138,286,307,862,918,919,927,932,946],referenc:[22,910,919],referr:[20,21,39,230,231,343,389,694,703,727,910,918,925,939],referral_valid_until:861,referred_realm:861,reflect:[23,34,100,103,136,158,262,288,290,325,326,331,356,360,911,912],reforward:939,refrain:924,refresh:[15,43,910,918],refresh_tim:910,refus:[12,14,34],regard:919,regardless:[6,19,21,43],regener:908,regent:919,regexp:21,region:[43,114,130,295,299,827],regist:[4,21,23,28,39,919,926,953],registr:21,regress:904,regul:919,regular:[14,21,34,37,43,946],regularli:[17,39],reiniti:[148,918],reject:[12,15,16,20,21,34,166,620,939],reject_bad_transit:20,rekei:14,rel:[20,21,48,898,904,910,946],relai:10,relat:[4,6,20,21,22,28,29,35,37,39,169,826,918,919],relationship:[21,932],releas:[0,3,4,6,8,14,15,16,19,20,21,23,24,25,26,33,35,37,38,39,40,41,43,46,48,68,73,77,82,84,91,93,113,125,126,154,163,176,203,209,214,230,231,265,268,282,294,314,318,344,896,897,901,911,912,914,915,918,921,922,923,924,925,927,928,929,930,931,932,942,948,953],relev:[34,38,78,195,300,911],reli:[15,34],reliabl:24,relianc:21,relinquish:85,remain:[3,4,6,14,20,43,44,245,645,896,897,914,915,918,919,929,931,946],rememb:[34,37,910],remot:[3,4,7,15,20,23,33,38,43,48,62,64,169,223,325,326,331,356,359,360,382,383,525,526,903,918,938,939,946,952,953],remote_addr:[44,64,82,359],remote_port:84,remotehost:949,remov:[2,3,6,20,23,26,28,37,38,48,155,904,918,929,938],renam:[3,906,918,929],rename_sect:934,render:[14,904],renew:[3,5,6,20,21,23,48,846,884,918,930,939,942,943,946,953],renew_lif:[256,840],renew_lifetim:21,renew_til:[825,833,884,910],renewable_lif:942,renprinc:3,reorgan:918,rep:[185,199,327,328,357,358,807,832,845,860],rep_cksum:861,rep_result:375,repeat:[6,20,21,34,847,910,924],repl:357,replac:[3,5,21,23,28,34,70,75,94,186,188,190,191,196,197,225,226,232,233,234,281,351,353,411,906,914,918,919,922,942],replai:[21,43,48,78,323,325,326,331,354,356,359,360,521,522,875,897,899,907,913,917,918,953],repli:[12,26,46,107,245,258,267,279,352,357,358,380,381,404,730,845,865,866,870,911,918,922,931,942],replic:[8,34],replica:[4,6,7,8,9,14,15,17,20,21,23,31,32,35,41,903,918],replica_datatran:[7,34,917],replica_datatrans_hostnam:23,replica_dumpfil:8,replica_host:7,replicahostnam:8,reply_out:866,report:[6,38,903,918,936,942,948],repositori:908,repres:[3,21,34,43,158,885,896,900,911,919],represent:[21,43,48,344,345,398,407,408,813,832,845,846,883,896,910,914,919],representaton:807,reproduc:919,req:[21,26,37,245,329,330,359,504,846],req_pac:253,request:[3,4,6,8,9,10,14,15,16,19,20,21,22,23,24,25,28,33,35,36,37,38,40,43,46,48,153,166,195,223,224,229,235,241,253,260,267,276,277,330,359,378,403,503,505,506,619,674,695,752,759,760,807,809,832,846,854,898,900,901,910,911,912,918,921,922,924,930,931,936,939,942,946,948,953],request_fini:922,request_init:922,request_tim:882,requested_principal_nam:861,requestor:660,requir:[3,4,6,8,9,12,14,15,16,20,21,22,23,24,25,26,28,32,34,35,36,37,38,39,40,43,46,48,98,112,116,117,236,241,247,248,301,323,325,326,331,354,356,360,544,738,862,877,896,897,904,905,906,908,911,918,919,921,924,931,934,939,944,952,953],require_auth:[3,16,918],requires_hwauth:[3,931],requires_pre_auth:23,requires_preauth:[3,5,14,23,25,35,37,40],requires_pwchang:5,requisit:908,research:919,resembl:740,reserv:[909,919],reset:[3,9,35,46,157,386,918],resid:[15,39,46,902,919,951,952],residu:[21,39,152,317,897,901,932,934,953],resiz:407,resolut:[15,33,38,43,230,918,946],resolv:[15,33,48,260,317,897,906,918,943,946],resourc:[43,46,904,916,918],respect:[3,11,34,82,84,224,344,898,918,919,924,938],respond:[4,48,367,368,369,370,371,372,731,738,739,740,876,877,918,931],respons:[3,4,37,40,46,85,166,229,245,279,357,404,503,505,543,565,739,759,761,807,846,882,918,919,922,925,931,942,949,953],rest:[28,906],restart:[12,14,19,20,23,24,34,37,41],restor:[6,23,918],restrict:[3,5,14,19,21,23,48,224,919,928,930,942,946],restrict_anonymous_to_tgt:[20,37],restructuredtext:0,resubmit:942,result:[0,14,15,21,23,37,39,40,41,43,46,48,99,102,107,117,124,144,156,158,189,195,228,287,289,296,320,375,376,403,405,406,407,420,906,910,911,915,918,919,920,924,925,930,931,932,939,946,948],result_cod:[166,382,383],result_code_str:[166,382,383],result_str:[166,169,382,383],resum:23,resync:[4,9,23,918],resynchron:9,ret:[46,347],ret_as_repli:[232,233,234],ret_princ:389,ret_valu:[59,60],retain:[2,3,14,20,23,919,928,930,952],retir:[13,23,918],retransmit:906,retri:[20,36,38,39],retriev:[3,6,23,24,41,43,44,46,48,158,271,310,366,375,400,403,876,918,919,948],return_padata:931,return_pwd:361,retval:[49,50,51,53,55,56,61,62,63,64,65,66,67,68,69,71,72,73,74,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,95,96,97,98,99,100,102,103,104,105,106,107,108,111,112,113,114,115,116,117,118,121,124,125,126,129,130,132,133,134,135,137,139,141,142,145,147,148,149,150,151,152,153,155,156,157,158,159,160,161,162,163,164,165,166,167,169,170,172,173,174,175,176,177,178,180,181,182,183,184,185,187,189,192,193,214,217,223,224,227,229,231,235,236,238,248,260,261,262,264,265,266,267,268,271,272,273,274,275,276,277,278,279,280,282,285,286,287,288,289,290,294,295,296,298,299,300,301,302,303,304,305,306,308,310,311,313,314,315,316,317,318,319,321,322,323,324,325,326,327,328,329,330,331,332,333,335,336,337,338,339,342,344,345,347,348,349,350,352,354,355,356,357,358,359,360,361,362,363,364,373,374,375,376,377,378,382,383,384,385,387,389,390,391,392,394,395,396,397,398,400,401,402,403,404,405,406,407,408,409,410,414,923],reus:23,rev:[6,24],revers:[6,15,21,33,43,919,943],review:905,revis:[918,919],revoc:[20,21],revok:[20,21,35],rfc4120:29,rfc:[14,20,21,39,43,48,320,382,383,412,442,443,446,447,448,450,451,458,459,460,461,462,463,464,465,466,511,540,542,600,664,667,668,669,670,671,672,673,675,676,677,678,680,681,682,683,686,687,689,691,698,701,703,705,738,901,910,911,912,915,918,922,924],rhost:223,ricciardi:42,richard:919,ride:20,right:[5,19,20,100,103,288,290,827,909,915,919],risk:[14,23,26,30,46],rkt:11,rlen:[91,92,93,94],rlogin:946,rm:37,rnd:38,roam:21,robbi:953,robin:15,robust:918,rock:[922,931],roll:23,rollback:14,rollov:[6,23],root:[8,12,14,15,17,19,20,21,32,34,902,906,938,946,951,952,953],rotat:[26,38],round:[40,918,931],rout:34,routin:[21,870],royal:919,royalti:919,rpath:[904,906,945],rpc:[20,21,23,43,48,616,903,918,919],rpcbind:23,rsa:[37,477,480,481,482,919,942],rst:908,rtime:846,rule:[3,19,21,23,28,38,39,43,154,946,948,951,952],run:[3,4,6,8,9,10,12,14,15,20,21,23,24,26,28,32,33,34,37,39,41,897,904,905,906,908,917,918,941,943,946,953],runstatedir:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],runtim:917,s2kparam:48,s2kparams_out:229,s4u2proxi:[20,43,910,918],s4u2self:[20,43,343,918,948],s4u:918,s4uself:20,s:[2,3,4,5,6,7,8,10,11,12,14,15,17,19,20,21,22,23,25,26,28,29,32,33,34,35,37,38,39,41,43,46,48,50,113,192,203,209,230,231,245,263,279,294,300,363,366,375,378,398,404,740,807,826,827,832,836,876,897,898,902,904,906,910,911,917,918,919,921,924,931,932,933,935,938,939,941,942,943,944,946,948,949,950,951,952,953],s_address:824,sa:919,safe:[28,48,741,896,918],safer:938,safest:939,sai:901,sake:946,sale:919,salt:[2,3,6,11,20,23,25,48,125,126,393,840,918],salt_out:229,salt_type_afs_length:789,salt_type_no_length:789,salttyp:[6,20,26,374],salttypep:394,sam:[696,698,699,918],samba:[28,918],same:[3,4,5,10,12,19,20,21,23,24,28,36,39,43,52,53,91,101,105,107,136,138,151,155,171,180,228,250,270,271,275,279,307,348,349,350,362,388,847,897,901,906,918,923,924,938,942,946,948],sampl:[12,15,22,34,903,919,938,939,946,949],san:[20,21,918],sandia:919,sasl:[3,5,20,22,38,43,918],sasl_authcid:3,sasl_authzid:3,sasl_mech:3,sasl_nocanon:38,sasl_realm:3,satisfactori:25,save:[37,40,66,83,528,529,911,918,931],sbin:[8,12,34,906,917],sbindir:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],sc:20,scalar:911,scenario:[14,918],schedul:[14,23],schema:[22,24],scheme:39,sclient:[12,937,940],sclogin:20,scope:5,screen:939,screensav:939,script:[3,4,10,34,903,904,906,918],search:[5,20,21,38,48,151,153,195,224,315,897,904,915,918,941,947],search_scop:5,searchscop:5,sec:[48,813,836,898],second:[3,10,20,21,23,28,36,37,39,43,44,52,53,105,153,223,228,266,267,322,348,349,350,361,362,385,386,388,410,745,808,824,826,846,875,885,896,898,901,910,911,914,915,923,924,939,942,946,953],second_ticket:[826,846,910],secondari:34,secret:[3,20,21,36,43,46,850,938],secretari:919,section:[3,10,19,22,23,28,33,34,35,37,39,41,43,48,119,320,412,600,681,682,683,901,904,905,910,911,915,918,934,935,946,951],sector:6,secur:[3,7,14,15,20,21,23,25,30,31,34,37,39,41,43,46,250,325,564,902,903,918,919,936,939,953],securecooki:911,securid:[669,918],sed:906,see:[14,15,17,22,23,24,26,28,32,34,35,36,39,43,46,97,99,100,102,103,108,113,114,130,131,168,184,189,229,262,287,288,289,290,294,295,299,320,329,330,359,375,393,403,412,413,414,600,738,827,897,898,901,902,903,904,906,908,909,910,918,919,920,921,922,923,925,926,927,928,929,930,931,932,933,934,935,936,938,939],seed:[131,331,413,915],seed_length:[131,413],seen:901,segment:39,select:[6,14,21,23,28,43,46,48,117,296,359,369,897,906,918,924,926,942,946,951],self:21,sell:919,semant:46,semfiajf42:20,send:[0,4,15,20,21,23,25,26,32,34,41,48,229,245,325,363,375,380,901,903,906,918,936,938,942,953],send_hook:381,sendauth:[12,34,48],sender:[325,326,331,356,360,824],sensit:250,sent:[6,20,25,36,37,41,43,325,375,381,866,901,904,911,918,931,939],sentenc:34,separ:[0,3,5,6,10,16,19,20,21,22,23,24,25,28,39,50,301,344,346,420,731,905,906,911,918,924,934,938,953],seq:875,seq_numb:[808,813],seqnumb:[69,74],sequenc:[25,37,48,66,78,80,83,325,326,327,331,356,358,359,360,521,528,808,813,875,902,910,911,914,924],sequence_count:873,sequenti:[48,314,815],seri:[48,915],serial:[9,43,48,405,918],serv:[4,10,21,23,918],server1:5,server:[2,3,4,5,6,7,8,9,10,12,16,18,20,21,22,23,24,25,28,29,30,31,34,36,37,38,39,43,46,48,159,166,223,224,264,267,300,301,333,342,343,359,375,382,383,414,504,617,661,730,760,807,825,826,832,836,846,883,897,900,901,903,907,910,917,918,919,920,926,927,939,945,946,948,949,951],server_kei:[340,341],server_port:12,server_princ:[300,301],server_str:169,serverauth:21,servic:[2,3,5,8,10,12,15,16,19,20,21,22,23,24,28,29,31,32,33,34,43,48,166,224,235,245,260,264,267,301,329,330,363,382,414,643,644,645,738,878,897,901,903,910,918,919,920,925,933,939,942,948,951,953],service1:948,service2:948,service_loc:933,service_nam:942,service_passwd:5,sesam:[46,701],session:[3,14,15,21,23,33,34,43,46,48,224,320,325,330,354,412,439,440,813,825,826,832,833,897,901,918,939,943,948,953],session_enctyp:[3,23,918],set:[0,3,4,5,6,14,15,16,18,19,20,21,22,23,24,25,26,28,29,31,32,33,34,35,37,38,39,40,41,43,44,46,48,62,68,69,73,74,77,78,98,102,145,153,154,161,164,203,209,224,229,253,279,280,286,289,301,305,317,325,326,331,352,354,356,359,360,361,369,373,377,387,404,407,408,409,420,546,731,747,865,866,876,897,898,901,906,918,921,924,931,932,938,939,941,942,943,946,952,953],set_cooki:[918,931],set_str:[23,26,36,37],setstr:[3,16],setuid:[41,918,953],setup:[23,34,904,918],sever:[3,15,16,20,21,23,24,37,39,897,903,906,910,923,953],sf:[5,6,911],sfu:684,sh:34,sha1:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],sha256:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],sha2:[3,20,918],sha384:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],sha:[14,20,918],shall:919,share:[0,14,21,23,28,46,330,906,923,924,934,938],sharealik:919,sharp:19,she:[939,952],shell:[3,5,23,34,41,918,938,939,945,951],shorter:21,shortest:192,shortli:[33,938],shortnam:[21,918],should:[0,2,3,4,5,6,10,12,14,15,17,20,21,22,23,24,25,26,28,29,32,33,34,37,38,39,43,46,71,85,144,152,223,245,249,255,269,279,308,317,325,327,330,342,359,361,365,366,404,740,860,865,866,885,896,897,898,902,904,906,910,912,918,919,920,921,922,923,924,928,929,930,931,933,934,935,938,939,942,946,948,953],show:[2,6,20,41,870,897,908,917,939,943],shown:[20,21,897],shrubberi:42,shutdown:24,sick:919,sid:[21,638,639,660],side:[23,43,363,375,901],sighup:[10,41],sign1:43,sign2:43,sign:[3,19,20,21,32,37,41,43,48,896,905,912,914,918,942,953],sign_authdata:918,sign_onli:43,signal:10,signatur:[48,412,476,477,482,905,924,934],signedpath:[3,20,918],signific:[25,35],silent:943,similar:[6,21,22,26,29,43,92,105,113,114,126,129,130,246,294,295,296,298,299,326,329,343,345,349,364,407,408,417,419,918,923,933,939,946],similarli:[15,344,740,939],simpl:[5,12,17,23,107,421,897,901],simplest:[28,43,897,904],simpli:[28,36,37,40,43,46,739,904,924,938,939],simplifi:[251,918],simul:946,simultan:847,sinc:[3,12,14,17,21,22,23,37,48,330,735,885,896,910,924,931,952,953],singl:[0,3,14,15,20,21,24,26,28,32,34,37,39,40,43,46,48,189,320,345,409,710,897,906,918,931,946],siphash:915,site:[15,23,34,39,918,939,942,952],situat:[14,20,24,28,39,948],size:[9,20,21,23,24,37,41,48,97,98,100,103,114,116,130,186,190,288,290,295,299,361,407,409,827,906,914,915,918],size_return:361,size_t:[95,96,98,100,103,104,112,114,116,118,130,131,168,170,186,187,190,191,192,193,280,288,290,295,299,337,339,369,374,397,398,413],sizeof:[43,46,934],skei:[20,826],skew:[48,267,356,360,931,942],skip:[22,23,37,414,416],slack:39,slash:[344,953],slat:923,slightli:906,slot:[11,21,300,915],slotid:21,slower:[14,24],sm:19,small:56,smaller:[21,914],smard:21,smart:[20,21,918],smtp:642,sname:[389,948],sni:918,so:[2,3,5,14,19,20,21,22,23,24,28,29,33,34,35,37,39,43,85,93,136,144,228,386,885,897,904,910,917,918,919,923,924,938,939,941,942,953],sock_dgram:933,sock_stream:933,socket:[20,21,36,48,375,917,933],soft:918,softwar:[14,15,21,24,25,28,42,46,906,919,936],solari:[31,904,906,918],solaris9ab:42,sole:[21,28],solut:34,some:[2,3,6,14,20,21,23,24,28,29,31,34,37,38,39,41,46,48,99,151,154,287,389,766,897,898,901,903,904,905,906,907,915,917,918,923,924,927,934,936,938,939,942,951,953],someon:[17,21,34,938,939],someprinc:23,someth:[12,14,20,38,901],sometim:[23,25,38,942],somewhat:[37,901],song:919,sophist:46,sort:38,sourc:[0,10,22,23,28,34,39,42,43,904,905,906,916,919,923,927,934,936,946],source_cache_nam:946,source_us:946,southern:919,space:[3,16,20,24,37,38,56,99,102,117,119,121,287,289,296,306,346,361,407,420,898,905],spake:[20,21,25,30,918,919],spake_preauth_group:[20,21,40],spake_preauth_ind:20,spake_preauth_kdc_challeng:[20,40],sparc:918,spars:915,spawn:4,special:[20,23,28,35,43,408,648,715,897,918,919,924,942],specif:[3,4,6,8,10,14,18,19,20,21,24,26,34,39,43,48,49,56,155,301,315,317,363,364,410,740,897,898,900,906,908,915,918,919,923,928,933,939],specifi:[3,4,5,6,7,8,9,10,11,14,15,16,18,19,20,22,23,28,29,34,36,37,39,43,46,48,92,93,99,100,102,103,113,125,129,224,227,229,235,260,264,267,287,288,289,290,294,298,310,315,318,325,326,331,344,345,356,359,360,375,383,414,752,897,901,906,911,912,918,924,931,939,941,942,943,944,945,946,947,948,953],speed:[22,25],sphinx:908,sphinx_arg:908,spi:924,split:[3,39,918],spnego:[918,919,924],spnego_mech:919,spoof:[21,25,39],sprecif:905,spuriou:918,sqlite3:6,sqlite:6,squar:[20,21,28],src:[22,148,904,906,908,919],src_ctx:179,src_name:43,srcdir:908,srv:[21,33,34,39,918],srvtab:11,ss:[898,903,906],ss_lib:906,sscope:5,sserver:[1,949],ssh:[15,33,939,952,953],sshd:21,sshing:953,ssl:[29,37],sspi:918,stabl:[918,928,929,930,935],stage:[14,911,929],stai:3,stale:[0,21,26],stamp:[6,9],stand:34,standalon:[8,41,918],standard:[3,6,9,14,20,37,41,43,900,918,919,945],start:[0,3,4,6,8,10,14,15,19,20,21,23,24,26,31,37,41,48,825,833,846,884,897,902,904,912,918,939,946],start_realm:910,start_tim:[235,260,275,942],starttim:[884,910],startup:[34,918],stash:[3,5,10,14,20,22,23,34,41,899,917],stash_fil:6,stashfilenam:[5,6],stashsrvpw:[3,20,22],state:[6,9,14,20,34,46,48,78,99,100,102,103,287,288,289,290,847,911,917,918,919,920,922,923,925,928,929,931,932,933,934,935],statement:919,statu:[3,837,918,919,921,924,943,946,948],stderr:[20,953],stdin:352,stdlib:934,stdout:[41,352],stduser:23,step:[6,14,22,23,34,37,946],steve:953,still:[3,4,6,10,14,20,21,23,32,33,34,35,39,148,269,918,942,946,948],stime:836,stockholm:919,stolen:939,stop:[4,10,24,923],storag:[46,48,57,58,82,84,159,170,187,192,193,280,361,374,398,897],store:[2,3,4,5,6,8,14,15,17,20,21,22,23,24,26,34,37,46,48,80,99,100,102,103,224,235,250,287,288,289,290,325,326,330,331,356,359,360,361,407,414,549,731,840,897,900,901,904,907,910,915,918,935,939,942,943,946,948],str:43,strategi:35,strcmp:934,strdup:934,stream:[8,12,20,34,36,43],strength:918,strengthen:14,strict:919,strictli:34,string2kei:14,string:[3,5,6,16,19,20,21,23,25,26,28,34,36,37,39,43,46,48,101,166,169,192,228,229,258,264,267,278,336,346,365,373,379,382,383,417,418,419,420,738,739,740,821,826,837,868,869,889,897,898,901,906,918,919,921,923,924,931,932,934,942,946],strip_realm:[20,36],strlcpy:919,strlen:[43,46],strong:[16,122],stronger:[14,16,21,26],strongest:26,strptime:919,struct:[43,48,51,262,269,805,807,808,809,810,811,813,816,817,818,822,823,824,825,826,827,829,831,832,833,834,836,840,841,842,845,846,847,848,849,850,854,859,860,861,862,863,869,870,873,874,875,876,878,879,880,881,882,883,884,886,887,889,890,891,894,895,928,934],structur:[43,46,47,48,92,100,103,135,156,169,173,182,212,221,237,240,241,242,243,244,245,249,252,253,254,255,257,258,259,269,275,280,282,288,290,322,324,334,345,355,356,365,368,371,375,389,414,416,421,538,805,811,823,826,827,836,863,883,890,896,922,923,928,930,931,933],studio:918,style:[3,21,39,417,418,419,638,640],su:946,sub:[5,21,903],subcommand:14,subdirectori:[21,28,903,908,917],subdomain:[21,39,951],subject:[0,20,21,23,37,919],subjectalternativenam:21,subjectaltnam:37,subjectkeyidentifi:37,subkei:[48,80,325,354,359,808,813],sublicens:919,submit:[26,43],subprocess:10,subregion:43,subschema:22,subscrib:936,subsect:[16,20,21,22,24,25,28,29,35,37,40],subsequ:[9,10,14,24,136,275,279,404,919],subsess:[26,330,440],subset:[39,903],substanti:919,substhtml:908,substitut:[21,34,37,919],subsystem:906,subtag:21,subtre:[3,5,20,22],subtree_dn_list:5,succe:[20,21,34,43,46,414],succeed:[12,34],success:[3,6,8,20,24,25,35,46,49,50,56,62,64,65,67,69,72,73,74,76,77,78,79,81,82,84,85,86,87,88,89,90,91,92,93,95,96,97,98,99,100,102,103,104,105,106,107,108,111,112,113,114,115,116,117,118,119,121,122,124,125,126,129,130,132,133,134,135,137,141,142,144,145,147,148,149,150,152,153,155,156,157,158,159,161,162,163,164,166,167,169,170,172,173,174,175,176,177,178,180,181,182,183,184,185,187,189,192,193,214,217,223,224,227,229,231,235,236,238,248,260,261,262,264,265,266,267,268,271,272,273,274,275,276,277,278,279,280,282,286,287,288,289,290,294,295,296,298,299,300,301,302,303,305,306,308,310,311,314,315,316,317,318,321,322,323,324,325,326,327,328,329,330,331,332,333,335,336,337,338,339,342,344,345,347,352,354,355,356,357,358,359,360,361,363,364,374,375,376,377,378,382,383,384,385,389,390,391,392,394,395,396,397,398,400,401,402,403,404,405,406,407,408,409,410,414,416,621,837,901,922,925,935,946,948],successfulli:[3,6,12,35,43,46,245,301,416,865,866],sudan:919,sudden:20,suffici:[3,5,14,24,906],suffix:[21,28,38,43,906,918,953],suggest:[0,245],suit:[34,903,904,918],suitabl:[6,904,906,918,919,939],summar:943,summari:[8,9],sun:919,suncc:906,sunw_dbprop_en:23,sunw_dbprop_master_ulogs:23,sunw_dbprop_slave_pol:23,sunwaadm:42,supersed:[10,14],supervisor:10,supplement:20,suppli:[3,11,43,46,48,223,245,258,262,267,276,277,278,331,342,372,373,386,735,736,876,906,922,923,931],support:[3,4,6,8,10,11,20,21,22,23,24,25,26,37,39,40,43,46,48,153,161,247,253,378,386,387,544,756,897,899,903,904,905,906,910,911,915,918,919,922,923,924,931,936,942],supported_enctyp:[14,20,26,34,918],suppos:[939,952],suppress:[3,6,20,906,918,941,946,948],sure:[3,5,12,14,15,22,23,26,33,41,938,939,942],surpris:14,surround:28,surviv:[20,897],susec:836,swap:[34,39],sweden:919,symbol:[6,344,901,904,905,908,917,923,924],symmetri:20,synchron:[9,14,15,21,24,34,41,48,271,403,730,918,931],syntact:21,syntax:[20,21,37,918],synthes:[381,865],synthet:[380,910],syria:919,sysadv6:42,sysconfdir:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953],syslog:[20,21,34,923],system:[3,6,14,15,19,20,21,24,29,32,33,34,35,36,37,38,41,43,46,48,56,136,147,169,282,382,383,385,396,694,697,700,876,897,902,903,904,905,918,919,923,932,936,938,939,941,942,952,953],systest:3,t:[2,3,6,10,11,12,14,15,20,21,23,28,34,37,44,50,161,333,344,712,715,737,897,901,904,906,919,938,939,942,943,946,953],t_mddriver:919,tab:[3,6,344,918],tabdump:[26,918],tabl:[3,6,23,48,276,307,308,313,359,363,414,850,900,903,905,906,908,915,917,918,943],tabular:[6,918],tag:[20,21,34,910,915,924],tail:34,take:[10,14,19,20,21,23,25,26,28,32,39,41,43,46,91,124,126,325,376,731,827,898,915,918,920,929,938,939,946],taken:[6,14,39,245,901,915],talk:901,tamper:43,tape:32,tar:[904,905],target:[19,21,34,43,897,910,918],target_nam:43,target_princip:19,target_principal_nam:946,target_us:946,target_user_login_nam:946,task:[14,46,91],tcl:918,tcp:[8,10,12,15,20,21,23,29,34,37,39,279,404,918,933],team:936,teardown:904,technet:42,techniqu:[40,46],technolog:[909,919,953],tekniska:919,telegraph:919,telephon:919,tell:[4,10,938,939,945],telnet:[21,643,946],temp:21,templat:903,temporari:[3,21,34,37,900,901,917,918,953],temporarili:3,ten:[33,939],tend:15,term:[3,14,23,25,26,37,41,739,897,900,918,919,922,931,948],termin:[4,10,48,173,195,220,230,231,240,261,325,352,354,361,366,407,903,934,946],ters:3,test1:[3,898],test2:[3,898],test3:[3,898],test4:898,test:[3,9,10,12,14,21,37,48,903,906,908,918,919,942,949],test_html:908,testdir:41,testus:3,texinfo:0,text:[6,23,28,36,37,46,169,365,827,836,870,911,945],tg:[3,20,21,25,26,35,48,224,300,403,759,860,910,918,930],tgt:[3,14,20,23,26,37,46,48,220,342,343,910,911,918,939,946],th:21,than:[3,4,5,6,10,12,14,15,19,20,21,23,24,25,26,28,32,35,37,38,39,43,53,56,230,279,375,404,897,901,904,911,914,915,918,922,924,938,942],thei:[3,6,9,14,15,20,21,28,33,34,37,38,39,41,43,46,229,325,375,731,847,896,897,900,904,906,910,918,931,938,939,950,953],them:[3,14,15,20,22,23,24,25,29,32,34,37,39,41,46,82,84,253,330,344,403,731,897,904,906,918,919,923,924,934,939,941,953],themselv:6,theodor:919,theori:919,therebi:952,therefor:[22,23,25,39,910,931],thereof:919,thi:[0,2,3,4,5,6,8,9,10,11,12,14,15,17,19,20,21,22,23,24,25,26,27,28,32,33,34,35,36,37,38,39,40,41,43,46,48,49,50,55,57,58,59,60,61,62,67,68,69,71,72,73,74,76,77,78,81,82,84,85,86,87,88,89,92,93,98,99,100,101,102,103,104,105,107,113,114,116,117,119,120,122,123,124,125,126,129,130,133,136,137,139,141,144,148,150,151,153,156,157,158,159,167,169,171,172,173,174,175,177,178,180,181,182,183,192,194,195,198,199,200,201,202,203,205,206,207,208,209,212,215,216,221,228,235,236,241,243,245,246,252,253,254,258,260,261,262,264,265,266,267,270,271,272,275,276,277,278,279,287,288,289,290,294,295,296,298,299,301,308,317,320,323,324,325,326,327,329,330,331,333,334,342,343,345,352,355,356,357,358,359,360,361,363,364,368,371,373,375,376,378,380,382,383,385,386,387,389,396,400,401,403,404,407,408,410,412,414,416,417,419,728,729,730,731,735,736,737,739,832,850,884,885,896,897,901,902,903,904,905,906,910,911,915,916,917,918,919,920,922,924,926,928,929,930,931,932,934,935,936,938,939,941,942,943,945,946,948,952,953],think:[38,923,938],third:[21,28,36,37,910,918,919,953],thorough:39,those:[3,6,14,19,21,23,25,26,34,39,43,46,906,908,914,918,919,922,924,927,928,931,948,952,953],though:[14,904,939],thousand:24,thread:[24,847,897,906,918],threadsaf:285,three:[14,24,26,35,39,40,375,910,918,939,953],threeparamopen:789,through:[15,16,20,21,23,24,28,29,33,34,35,39,46,230,282,386,387,416,910,915,918,929,938,939],throughput:[20,24],thu:[23,901,906,946],ti:[369,929],ticket:[2,3,5,6,12,14,15,16,19,20,21,22,26,28,33,34,35,36,37,38,39,41,43,46,48,153,159,183,195,223,229,235,247,260,264,267,322,330,333,342,359,363,364,375,545,548,551,652,662,745,760,809,813,823,825,826,832,833,845,846,883,884,886,897,898,910,918,921,922,930,931,936,937,938,941,942,943,946,948,949,952,953],ticket_authdata:195,ticket_flag:[5,826,910],ticket_info:824,ticket_lifetim:[21,33],tightli:[14,28,32,902],till:846,time:[0,2,3,5,6,9,10,14,15,19,20,21,22,23,24,26,28,34,35,36,37,39,41,43,44,48,136,158,224,228,235,245,260,275,356,359,360,398,735,752,753,808,824,825,826,832,833,846,850,884,896,897,899,901,902,906,907,910,911,915,917,918,919,924,930,938,939,942,943,946,953],time_offset:10,time_rec:[43,918],time_req:43,time_t:[6,885,896],timeofdai:410,timeout:[14,20,36],timeret:396,timestamp:[6,11,14,21,25,37,40,48,66,83,325,326,331,336,342,343,356,360,396,522,529,671,824,850,854,875,885,896,900,901,910,911,912,914,915,918,931,943],timestampp:395,titl:[903,919],tkt:826,tkt_flg_anonym:789,tkt_flg_enc_pa_rep:789,tkt_flg_forward:789,tkt_flg_hw_auth:789,tkt_flg_initi:789,tkt_flg_invalid:789,tkt_flg_may_postd:789,tkt_flg_ok_as_deleg:789,tkt_flg_postdat:789,tkt_flg_pre_auth:789,tkt_flg_proxi:789,tkt_flg_proxiabl:789,tkt_flg_renew:789,tkt_flg_transit_policy_check:789,tkt_life:[259,840],tktpolici:[3,5,23],tl:[9,22,29],tlyu:3,tmp:[3,21,34,901,907,917,939,946,953],tmpbuild:904,tmpdir:[901,953],tmppolici:5,tn:42,todd:919,todo:938,togeth:15,token:[16,20,21,46,368,598,729,730,731,733,736,737,913,918,924,931,942],token_flag:881,token_id:879,token_len:43,tokenid:738,tokeninfo:[369,738,878],toler:21,tom:3,tomorrow:23,too:[3,23,56,100,103,119,267,288,290,306],tool:[6,23,903,905,918,923],toolkit:903,top:[10,39,897,904,905,908],top_srcdir:908,topic:[0,30,34],topolog:4,tort:919,tortiou:919,total:[20,25,915,942,946],toward:[0,23],tr_content:890,tr_type:890,trace:[48,889,918,953],trace_log:41,track:[3,6,9,35,901,936],trademark:919,tradit:[6,35],traffic:29,trail:[20,38,946],trailer:[43,48,538],transact:[24,953],transcript:911,transfer:[4,23,37],transform:906,transit:[20,21,24,359,541,550,674,695,833,890,939,942,943,948],transitori:14,translat:[21,56,918],transmiss:17,transmit:[23,43,279,404,918,931],transpar:953,transport:[23,39,279,404],travers:6,treat:[3,21,36,38,43,54,342,350,709,885,910,942,948],treatment:39,tree:[0,22,23,24,34,905,906,908,924,927,934],tri:[20,21,25,44,359,414,918,925],trigger:901,trillium:[15,32,939],trim:[99,287],trip:[40,918,931],tripl:[14,20,26,918],trivial:[25,918],troubl:42,troubleshoot:[30,34],true_principal_nam:861,truncat:[915,939],trust:[20,21,29,37,43,268,942],tryagain:922,ts:919,tt:898,tty04:20,tty:5,tune:[22,39],tupl:3,turn:[8,21,24,33,35,40,352,361,906,946],twice:[3,24,34,910,929,938,944],two:[3,18,20,21,23,24,26,28,34,35,37,38,48,53,361,898,910,911,914,918,920,924,932,939,942,946],txt:[6,34,39],type:[2,3,5,6,10,15,16,21,23,25,28,30,32,34,38,39,46,48,91,93,95,98,99,100,102,103,104,112,113,114,115,116,124,125,126,129,130,151,152,153,161,163,184,189,195,223,224,229,280,287,288,289,290,294,295,298,299,310,311,315,317,331,333,335,344,389,421,500,541,647,678,750,756,800,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,900,904,907,910,911,912,914,915,918,920,922,923,924,927,928,929,930,931,932,933,934,935,938,939,942,943,946,948,952,953],typedef:[43,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895],typic:[4,15,20,21,26,33,38,39,43,46,98,253,908,917,920,922,923,928,929,931,935,942,948],u1:[904,905],u2u:948,u:[919,948],ubuntu:[42,918],uc:918,ucb:946,udp:[10,15,20,21,29,39,279,404,918,933],udp_preference_limit:21,uid:[21,43,897,901,917,946,952,953],uid_t:43,uidnumb:897,uint16_t:892,uint32_t:[885,893,896],uint8_t:858,uint_max:[769,770,788],uk:919,ulog:[20,23],umich:919,un:[904,918],unabl:[17,21,23],unalloc:280,unam:28,unambigu:245,unansw:877,unauthent:32,unavail:[23,34,39],unchang:[3,14,946],unclean:24,uncommon:901,uncondition:[228,906],unconfigur:[39,908],undefin:946,under:[3,5,6,10,20,21,22,38,155,159,901,904,915,918,919],underli:43,underneath:22,underscor:[21,919],understand:46,undertaken:0,unenc_authdata:846,unencapsul:918,unencrypt:[32,356,813,823,845,846],unescap:6,unexport:924,unfinish:931,unicod:919,unifi:0,unimpl:923,unimport:910,uninterrupt:14,uniqu:[3,43,48,265,414,644,646,897,924],unit:[898,919,939],univers:919,unix:[6,15,20,21,28,31,36,43,923,924,934],unkei:46,unknown:[12,38,41,616,910,948],unless:[2,3,6,11,14,19,20,21,26,28,32,34,43,315,386,414,416,901,902,918,932,946,950],unlik:[14,23,40,897,901,918,924,939],unlimit:919,unlink:6,unlock:[23,35,918],unlockit:[3,20,23,24],unmodifi:[919,946],unnecessari:23,unpack:905,unpars:[43,48,407,409],unpleas:14,unport:919,unprint:3,unqualifi:33,unquot:6,unrecogn:906,unrestrict:[32,902],unser:43,unset:[43,48,171,953],unsign:[91,92,93,94,97,111,116,120,279,311,361,404,407,409,805,811,814,818,829,848,853,857,859,891,896],unspecifi:[21,953],unstabl:929,unsuccess:37,unsupport:[37,906],unswapp:897,untest:906,until:[3,6,14,21,23,43,896,897,901,906,915,918,939],untrust:[43,953],unus:[149,265,352,375,918],unusu:[28,37],unwrap:[43,48],up:[4,8,10,20,21,22,23,28,31,32,33,34,37,38,39,43,46,98,269,386,387,389,896,902,906,918,934,938,942],updat:[2,4,6,8,9,14,20,21,22,24,26,34,35,99,100,102,103,224,287,288,289,290,697,700,906,911,918,927,936],update_princ_encrypt:[14,23],update_rel:934,upgrad:[21,23,26,34,39,918],upn:[20,21,350,637,639,707,918],upon:[6,8,946],upper:[3,19,39,944],uppercas:[21,932,953],upstream:[23,906,918],upstreamhostnam:23,uri:[3,5,20,21,33,34,39,918],url:[20,24,29,39],us:[0,2,3,4,5,6,7,8,9,10,11,12,14,16,18,19,20,21,22,23,24,25,26,28,29,33,34,35,36,37,38,39,40,41,42,43,45,46,49,55,56,65,66,67,68,69,72,73,74,76,77,78,81,83,98,100,103,105,111,113,115,117,121,125,129,132,141,143,144,145,150,153,156,163,164,169,172,173,174,175,177,178,180,181,182,183,195,223,224,227,228,229,230,231,236,239,241,246,247,248,250,254,258,261,267,268,272,275,277,279,280,286,288,290,294,298,300,309,310,315,317,318,321,322,324,325,326,327,328,329,331,332,335,338,339,340,341,344,345,352,354,355,356,357,359,360,363,366,375,378,389,401,403,404,405,406,407,408,414,416,439,447,448,563,564,598,599,618,740,825,837,847,856,865,866,870,876,884,885,900,901,902,903,905,908,910,911,912,914,915,917,918,919,920,921,922,923,924,925,927,931,932,934,935,936,938,939,941,942,943,944,945,946,948,949,950,951,952,953],usa:919,usabl:48,usag:[20,21,37,43,99,100,102,103,108,113,114,129,130,287,288,289,290,294,295,298,299,847,896,911,912,945,946],usc:946,use_mkei:[14,23],usec:[813,824,836,875],useless:14,user:[0,3,5,6,8,14,15,16,19,20,21,22,23,25,26,33,34,35,36,37,38,39,41,43,48,56,90,136,169,224,227,326,330,331,333,361,551,641,663,730,737,870,897,898,901,903,904,906,908,916,917,918,919,922,935,936,938,939,941,942,944,946,948,951,952,953],user_dn:5,userconfig:21,userdata:[326,331],userdata_out:[356,360],userid:[21,906],usernam:[3,12,21,34,36,37,43,319,674,939,942],userok:932,userpolici:5,userprincipalnam:20,usr:[5,8,12,20,21,34,906,908,917,945,946],usual:[3,10,12,20,21,23,25,35,37,39,46,99,287,897,900,906,910,923,939,948,953],utc:23,utf:[46,350,365,373,709,918,919],util:[22,34,39,47,904,906,919,941,953],uucp:20,v4:[11,14,21,48],v4_instance_convert:21,v4_realm:21,v4cred:51,v5:[3,7,11,21,32,39,48,903,904,906,916,919,939],v5cred:51,v:[6,9,42,934,942,943],va_list:[48,92,94],vagu:906,val:[198,199,200,201,202,203,204,206,207,208,209,211,212,215,218,219,221,222],valid:[20,21,23,39,43,48,66,83,109,124,129,153,160,224,235,248,260,269,275,298,301,330,333,342,343,345,350,359,365,366,408,414,884,897,898,903,910,914,918,930,939,942,948,952,953],valid_int_bit:789,valid_uint_bit:789,valu:[3,5,6,10,14,16,19,20,21,22,23,24,25,26,28,33,34,36,37,38,39,43,46,48,66,83,117,125,126,136,151,153,156,166,224,245,248,252,263,265,269,296,301,333,368,369,371,375,386,388,397,722,728,729,731,733,738,740,796,797,798,837,841,854,865,866,885,896,897,898,900,901,906,907,908,910,911,912,914,915,918,922,924,931,932,934,939,941,942,943,945,946,951,953],valuabl:[46,919],vaniti:38,vararg:91,vari:[15,33,905,917,941,942],variabl:[2,3,4,5,6,7,8,9,10,11,12,15,16,19,20,21,24,25,28,30,34,35,37,38,39,40,41,43,48,93,136,141,155,269,282,386,387,897,900,901,907,918,934,935,941,942,943,944,946,947,948,949],variad:[91,417,419],variant:[23,906,918,924],varieti:26,variou:[14,30,43,359,903,907,918,939],vendor:[738,879,945],verbatim:919,verbos:[3,6,23,904,918,942],veri:[14,20,21,23,934],verif:[20,21,34,43,46,48,414,897,937,939],verifi:[5,20,21,23,34,37,43,48,241,356,357,358,359,360,361,901,905,918,922,931,938,939,946],verifier_cred_handl:924,verify_ap_req_nofail:21,versa:[37,918],version:[0,2,3,5,6,9,10,14,20,23,24,26,29,38,42,43,44,48,155,228,247,310,315,363,375,616,723,821,823,845,850,883,896,900,904,905,906,908,910,912,914,915,918,919,923,929,933,943,945,946,948,949,953],verto:[906,919],vesion:[321,405],veto:930,via:[0,3,6,8,20,21,34,35,46,48,274,386,402,826,918,924,926,946,952],vice:[37,918],view:[8,23,34,937],view_polici:23,viola:15,virtual:[15,21],visibl:[14,23,25,918],visit:939,vista:[26,918],visual:918,vnder:14,vno:[3,14,310,315,850],volum:918,vopt:46,vpath:[904,905],vprintf:[417,418,419],vt:923,vtabl:[922,923,931,934],vulner:[14,23,32,46,918,936],w:[3,5,10,24,481],wa:[0,3,6,8,12,14,17,20,21,23,24,26,39,41,43,44,48,155,205,245,273,314,342,359,735,900,910,911,918,919,921,925,929,930,932,938,939,942,945,946,953],wai:[21,23,28,39,43,46,126,236,250,375,896,897,898,900,906,908,918,919,927,932,938,939,951],wait:[8,20,23,39],wake:15,walk:[6,938],want:[3,23,28,34,545,551,904,933,938,939,946],warn:[3,23,26,245,908,918,919],warranti:919,wasn:44,we:[0,22,23,28,32,34,43,904,905,906,918],weak:[14,20,21,26,41],web:[34,897,918],week:5,weight:39,well:[14,21,23,34,38,43,46,343,648,903,906,918,925],wellknown:[37,46,502,763],went:939,were:[14,15,21,34,43,414,618,897,918,919,939],wg:918,what:[6,14,19,20,21,26,38,43,901,922,923,931,935,938,939,945],whatev:39,whatsoev:919,when:[3,4,6,8,9,10,12,14,15,16,17,20,21,22,23,26,28,29,33,34,36,37,38,39,40,41,43,46,49,65,67,68,72,73,76,77,78,79,85,91,92,93,111,113,115,125,126,132,136,141,143,145,150,153,154,163,164,169,172,173,174,175,176,177,178,180,181,182,183,194,195,224,227,228,229,230,231,235,236,250,254,258,260,261,265,268,272,275,280,282,286,294,310,315,317,318,321,322,324,325,326,327,328,329,330,331,332,335,338,339,344,345,352,354,355,356,357,359,360,361,363,375,389,401,403,405,406,408,738,739,740,897,900,906,908,910,915,917,918,920,924,925,929,932,934,935,936,938,939,941,942,943,945,946,948,951,953],whenev:46,where:[3,4,6,7,8,14,15,17,20,21,23,25,28,39,43,46,317,389,896,897,900,901,904,905,906,911,918,923,939,942,946,953],whether:[4,6,8,10,14,20,21,26,28,35,36,43,46,48,105,223,241,242,243,245,249,253,255,319,407,905,911,918,919,921,928,935,939,946],which:[3,4,5,6,7,8,9,10,11,12,14,15,19,20,21,22,23,24,25,26,28,29,33,34,35,36,37,38,39,40,41,43,46,126,173,195,229,230,245,250,280,310,330,359,366,368,371,372,884,885,896,897,900,901,903,904,905,906,907,910,911,912,914,915,917,918,919,920,922,923,924,927,928,929,930,931,933,934,935,939,942,945,946,948,951,952,953],whichev:15,whitespac:[3,20,21],who:[0,5,16,20,25,34,37,938,939],whoami:923,whole:[23,37,141,155,342],whom:[919,938],whose:[3,5,10,17,19,21,34,38,40,43,46,132,217,229,910,914,939,952],wicker:923,wicker_appear:923,wicker_brac:923,wicker_construct:923,wicker_foot:923,wicker_materi:923,wicker_slat:923,wide:[21,29,36],wiki:[42,904,918],wild:3,wildcard:[19,20,918,951],willi:14,willing:[20,21,26],win:919,winbind:28,winbind_krb5_loc:28,window:[21,26,28,29,42,301,382,383,637,639,685,703,897,901,903,915,918,923,924,934,939],wish:[16,21,34,39,43,250,904,905,906,907,919,924,935,938,939,953],with_realm:[300,341,343],within:[3,15,20,21,24,34,35,39,43,48,132,154,252,261,356,360,365,373,386,847,897,912,918,919,924,942,951,953],without:[3,14,19,20,21,23,24,28,32,34,35,36,37,43,133,368,371,538,866,897,901,904,906,915,918,919,938,939,946,953],wkt:11,wl:945,won:[21,37,939],worcest:919,word:[21,34,939],work:[2,3,4,6,21,23,34,35,36,39,40,43,897,906,918,919,931,932,936,938,939,953],workdai:33,worker:[10,24],workflow:14,workstat:46,worri:[22,904,953],wors:21,worst:14,worth:32,would:[5,6,14,16,17,20,21,23,25,28,32,34,37,38,39,40,43,46,902,918,924,938,939,945,952,953],wrap:[23,48,300,320,924],wrapper:[889,911,912],wrfile:[14,23],writabl:[15,34,316,934],write:[0,6,8,10,11,20,21,22,23,24,28,34,35,251,352,387,897,915,918,923,934,953],writeabl:302,writer:0,written:[3,4,155,850,900,915,919],wrong:[35,37,919,939,946],wsgi:29,www:[22,42,908,918],x11r6:904,x509:[37,918,942],x509_anchor:[21,942],x509_proxi:21,x509_proxy_ca:21,x509_user_ident:[16,21,942],x86:[906,918],x86_64:[906,918],x:[3,4,6,8,10,16,19,20,21,23,37,43,771,791,801,910,918,919,921,922,942,948],xconsortium:904,xf:905,xml:908,xore:[21,359],xp:918,xst:3,xvm:14,xyz:953,y:[22,771,801,906],yacc:906,ye:[3,5,23,906,942],year:[23,45,898,918],yet:[6,21,23,26,34,37,38,897,906,927,939],yflag:906,yield:931,you:[0,3,5,12,15,16,17,20,21,22,23,24,28,32,33,34,35,37,39,40,41,737,898,902,904,905,906,907,908,919,936,938,939,941,946,953],your:[0,12,17,20,21,26,32,33,34,37,39,904,905,906,919,927,937,939,941,950,953],your_princnam:37,your_realmnam:37,yourdir:34,yourself:[939,953],yu:3,yy:898,yymmddhhmmss:898,yyyi:898,yyyymmddhhmmss:898,z:[771,898,946],zanarotti:46,zephyr:[14,919],zero:[3,21,24,39,43,44,48,129,130,203,241,245,260,261,284,298,299,310,740,742,865,910,911,914,915,918,923],zone:[14,39,898],zonetest:14},titles:["Contributing to the MIT Kerberos Documentation","Administration programs","k5srvutil","kadmin","kadmind","kdb5_ldap_util","kdb5_util","kprop","kpropd","kproplog","krb5kdc","ktutil","sserver","Advanced topics","Retiring DES","Application servers","Authentication indicators","Backups of secure hosts","Configuration Files","kadm5.acl","kdc.conf","krb5.conf","Configuring Kerberos with OpenLDAP back-end","Database administration","Database types","Addressing dictionary attack risks","Encryption types","Environment variables","Host configuration","HTTPS proxy configuration","For administrators","Installation guide","UNIX Application Servers","Installing and configuring UNIX client machines","Installing KDCs","Account lockout","OTP Preauthentication","PKINIT configuration","Principal names and DNS","Realm configuration decisions","SPAKE Preauthentication","Troubleshooting","Various links","Developing with GSSAPI","Differences between Heimdal and MIT Kerberos API","For application developers","Initial credentials","Principal manipulation and parsing","krb5 API","krb5_425_conv_principal - Convert a Kerberos V4 principal to a Kerberos V5 principal.","krb5_524_conv_principal - Convert a Kerberos V5 principal to a Kerberos V4 principal.","krb5_524_convert_creds - Convert a Kerberos V5 credentials to a Kerberos V4 credentials.","krb5_address_compare - Compare two Kerberos addresses.","krb5_address_order - Return an ordering of the specified addresses.","krb5_address_search - Search a list of addresses for a specified address.","krb5_allow_weak_crypto - Allow the application to override the profile\u2019s allow_weak_crypto setting.","krb5_aname_to_localname - Convert a principal name to a local name.","krb5_anonymous_principal - Build an anonymous principal.","krb5_anonymous_realm - Return an anonymous realm data.","krb5_appdefault_boolean - Retrieve a boolean value from the appdefaults section of krb5.conf.","krb5_appdefault_string - Retrieve a string value from the appdefaults section of krb5.conf.","krb5_auth_con_free - Free a krb5_auth_context structure.","krb5_auth_con_genaddrs - Generate auth context addresses from a connected socket.","krb5_auth_con_get_checksum_func - Get the checksum callback from an auth context.","krb5_auth_con_getaddrs - Retrieve address fields from an auth context.","krb5_auth_con_getauthenticator - Retrieve the authenticator from an auth context.","krb5_auth_con_getflags - Retrieve flags from a krb5_auth_context structure.","krb5_auth_con_getkey - Retrieve the session key from an auth context as a keyblock.","krb5_auth_con_getkey_k - Retrieve the session key from an auth context.","krb5_auth_con_getlocalseqnumber - Retrieve the local sequence number from an auth context.","krb5_auth_con_getlocalsubkey","krb5_auth_con_getrcache - Retrieve the replay cache from an auth context.","krb5_auth_con_getrecvsubkey - Retrieve the receiving subkey from an auth context as a keyblock.","krb5_auth_con_getrecvsubkey_k - Retrieve the receiving subkey from an auth context as a keyblock.","krb5_auth_con_getremoteseqnumber - Retrieve the remote sequence number from an auth context.","krb5_auth_con_getremotesubkey","krb5_auth_con_getsendsubkey - Retrieve the send subkey from an auth context as a keyblock.","krb5_auth_con_getsendsubkey_k - Retrieve the send subkey from an auth context.","krb5_auth_con_init - Create and initialize an authentication context.","krb5_auth_con_initivector - Cause an auth context to use cipher state.","krb5_auth_con_set_checksum_func - Set a checksum callback in an auth context.","krb5_auth_con_set_req_cksumtype - Set checksum type in an an auth context.","krb5_auth_con_setaddrs - Set the local and remote addresses in an auth context.","krb5_auth_con_setflags - Set a flags field in a krb5_auth_context structure.","krb5_auth_con_setports - Set local and remote port fields in an auth context.","krb5_auth_con_setrcache - Set the replay cache in an auth context.","krb5_auth_con_setrecvsubkey - Set the receiving subkey in an auth context with a keyblock.","krb5_auth_con_setrecvsubkey_k - Set the receiving subkey in an auth context.","krb5_auth_con_setsendsubkey - Set the send subkey in an auth context with a keyblock.","krb5_auth_con_setsendsubkey_k - Set the send subkey in an auth context.","krb5_auth_con_setuseruserkey - Set the session key in an auth context.","krb5_build_principal - Build a principal name using null-terminated strings.","krb5_build_principal_alloc_va - Build a principal name, using a precomputed variable argument list.","krb5_build_principal_ext - Build a principal name using length-counted strings.","krb5_build_principal_va","krb5_c_block_size - Return cipher block size.","krb5_c_checksum_length - Return the length of checksums for a checksum type.","krb5_c_crypto_length - Return a length of a message field specific to the encryption type.","krb5_c_crypto_length_iov - Fill in lengths for header, trailer and padding in a IOV array.","krb5_c_decrypt - Decrypt data using a key (operates on keyblock).","krb5_c_decrypt_iov - Decrypt data in place supporting AEAD (operates on keyblock).","krb5_c_derive_prfplus - Derive a key using some input data (via RFC 6113 PRF+).","krb5_c_encrypt - Encrypt data using a key (operates on keyblock).","krb5_c_encrypt_iov - Encrypt data in place supporting AEAD (operates on keyblock).","krb5_c_encrypt_length - Compute encrypted data length.","krb5_c_enctype_compare - Compare two encryption types.","krb5_c_free_state - Free a cipher state previously allocated by krb5_c_init_state().","krb5_c_fx_cf2_simple - Compute the KRB-FX-CF2 combination of two keys and pepper strings.","krb5_c_init_state - Initialize a new cipher state.","krb5_c_is_coll_proof_cksum - Test whether a checksum type is collision-proof.","krb5_c_is_keyed_cksum - Test whether a checksum type is keyed.","krb5_c_keyed_checksum_types - Return a list of keyed checksum types usable with an encryption type.","krb5_c_keylengths - Return length of the specified key in bytes.","krb5_c_make_checksum - Compute a checksum (operates on keyblock).","krb5_c_make_checksum_iov - Fill in a checksum element in IOV array (operates on keyblock)","krb5_c_make_random_key - Generate an enctype-specific random encryption key.","krb5_c_padding_length - Return a number of padding octets.","krb5_c_prf - Generate enctype-specific pseudo-random bytes.","krb5_c_prf_length - Get the output length of pseudo-random functions for an encryption type.","krb5_c_prfplus - Generate pseudo-random bytes using RFC 6113 PRF+.","krb5_c_random_add_entropy","krb5_c_random_make_octets - Generate pseudo-random bytes.","krb5_c_random_os_entropy","krb5_c_random_seed","krb5_c_random_to_key - Generate an enctype-specific key from random data.","krb5_c_string_to_key - Convert a string (such a password) to a key.","krb5_c_string_to_key_with_params - Convert a string (such as a password) to a key with additional parameters.","krb5_c_valid_cksumtype - Verify that specified checksum type is a valid Kerberos checksum type.","krb5_c_valid_enctype - Verify that a specified encryption type is a valid Kerberos encryption type.","krb5_c_verify_checksum - Verify a checksum (operates on keyblock).","krb5_c_verify_checksum_iov - Validate a checksum element in IOV array (operates on keyblock).","krb5_calculate_checksum","krb5_cc_cache_match - Find a credential cache with a specified client principal.","krb5_cc_close - Close a credential cache handle.","krb5_cc_copy_creds - Copy a credential cache.","krb5_cc_default - Resolve the default credential cache name.","krb5_cc_default_name - Return the name of the default credential cache.","krb5_cc_destroy - Destroy a credential cache.","krb5_cc_dup - Duplicate ccache handle.","krb5_cc_end_seq_get - Finish a series of sequential processing credential cache entries.","krb5_cc_gen_new","krb5_cc_get_config - Get a configuration value from a credential cache.","krb5_cc_get_flags - Retrieve flags from a credential cache structure.","krb5_cc_get_full_name - Retrieve the full name of a credential cache.","krb5_cc_get_name - Retrieve the name, but not type of a credential cache.","krb5_cc_get_principal - Get the default principal of a credential cache.","krb5_cc_get_type - Retrieve the type of a credential cache.","krb5_cc_initialize - Initialize a credential cache.","krb5_cc_move - Move a credential cache.","krb5_cc_new_unique - Create a new credential cache of the specified type with a unique name.","krb5_cc_next_cred - Retrieve the next entry from the credential cache.","krb5_cc_remove_cred - Remove credentials from a credential cache.","krb5_cc_resolve - Resolve a credential cache name.","krb5_cc_retrieve_cred - Retrieve a specified credentials from a credential cache.","krb5_cc_select - Select a credential cache to use with a server principal.","krb5_cc_set_config - Store a configuration value in a credential cache.","krb5_cc_set_default_name - Set the default credential cache name.","krb5_cc_set_flags - Set options flags on a credential cache.","krb5_cc_start_seq_get - Prepare to sequentially read every credential in a credential cache.","krb5_cc_store_cred - Store credentials in a credential cache.","krb5_cc_support_switch - Determine whether a credential cache type supports switching.","krb5_cc_switch - Make a credential cache the primary cache for its collection.","krb5_cccol_cursor_free - Free a credential cache collection cursor.","krb5_cccol_cursor_new - Prepare to iterate over the collection of known credential caches.","krb5_cccol_cursor_next - Get the next credential cache in the collection.","krb5_cccol_have_content - Check if the credential cache collection contains any initialized caches.","krb5_change_password - Change a password for an existing Kerberos account.","krb5_check_clockskew - Check if a timestamp is within the allowed clock skew of the current time.","krb5_checksum_size","krb5_chpw_message - Get a result message for changing or setting a password.","krb5_cksumtype_to_string - Convert a checksum type to a string.","krb5_clear_error_message - Clear the extended error message in a context.","krb5_copy_addresses - Copy an array of addresses.","krb5_copy_authdata - Copy an authorization data list.","krb5_copy_authenticator - Copy a krb5_authenticator structure.","krb5_copy_checksum - Copy a krb5_checksum structure.","krb5_copy_context - Copy a krb5_context structure.","krb5_copy_creds - Copy a krb5_creds structure.","krb5_copy_data - Copy a krb5_data object.","krb5_copy_error_message - Copy the most recent extended error message from one context to another.","krb5_copy_keyblock - Copy a keyblock.","krb5_copy_keyblock_contents - Copy the contents of a keyblock.","krb5_copy_principal - Copy a principal.","krb5_copy_ticket - Copy a krb5_ticket structure.","krb5_decode_authdata_container - Unwrap authorization data.","krb5_decode_ticket - Decode an ASN.1-formatted ticket.","krb5_decrypt","krb5_deltat_to_string - Convert a relative time value to a string.","krb5_eblock_enctype","krb5_encode_authdata_container - Wrap authorization data in a container.","krb5_encrypt","krb5_encrypt_size","krb5_enctype_to_name - Convert an encryption type to a name or alias.","krb5_enctype_to_string - Convert an encryption type to a string.","krb5_expand_hostname - Canonicalize a hostname, possibly using name service.","krb5_find_authdata - Find authorization data elements.","krb5_finish_key","krb5_finish_random_key","krb5_free_addresses - Free the data stored in array of addresses.","krb5_free_ap_rep_enc_part - Free a krb5_ap_rep_enc_part structure.","krb5_free_authdata - Free the storage assigned to array of authentication data.","krb5_free_authenticator - Free a krb5_authenticator structure.","krb5_free_checksum - Free a krb5_checksum structure.","krb5_free_checksum_contents - Free the contents of a krb5_checksum structure.","krb5_free_cksumtypes - Free an array of checksum types.","krb5_free_context - Free a krb5 library context.","krb5_free_cred_contents - Free the contents of a krb5_creds structure.","krb5_free_creds - Free a krb5_creds structure.","krb5_free_data - Free a krb5_data structure.","krb5_free_data_contents - Free the contents of a krb5_data structure and zero the data field.","krb5_free_default_realm - Free a default realm string returned by krb5_get_default_realm().","krb5_free_enctypes - Free an array of encryption types.","krb5_free_error - Free an error allocated by krb5_read_error() or krb5_sendauth().","krb5_free_error_message - Free an error message generated by krb5_get_error_message().","krb5_free_host_realm - Free the memory allocated by krb5_get_host_realm().","krb5_free_keyblock - Free a krb5_keyblock structure.","krb5_free_keyblock_contents - Free the contents of a krb5_keyblock structure.","krb5_free_keytab_entry_contents - Free the contents of a key table entry.","krb5_free_principal - Free the storage assigned to a principal.","krb5_free_string - Free a string allocated by a krb5 function.","krb5_free_tgt_creds - Free an array of credential structures.","krb5_free_ticket - Free a ticket.","krb5_free_unparsed_name - Free a string representation of a principal.","krb5_fwd_tgt_creds - Get a forwarded TGT and format a KRB-CRED message.","krb5_get_credentials - Get an additional ticket.","krb5_get_credentials_renew","krb5_get_credentials_validate","krb5_get_default_realm - Retrieve the default realm.","krb5_get_error_message - Get the (possibly extended) error message for a code.","krb5_get_etype_info - Retrieve enctype, salt and s2kparams from KDC.","krb5_get_fallback_host_realm","krb5_get_host_realm - Get the Kerberos realm names for a host.","krb5_get_in_tkt_with_keytab","krb5_get_in_tkt_with_password","krb5_get_in_tkt_with_skey","krb5_get_init_creds_keytab - Get initial credentials using a key table.","krb5_get_init_creds_opt_alloc - Allocate a new initial credential options structure.","krb5_get_init_creds_opt_free - Free initial credential options.","krb5_get_init_creds_opt_get_fast_flags - Retrieve FAST flags from initial credential options.","krb5_get_init_creds_opt_init","krb5_get_init_creds_opt_set_address_list - Set address restrictions in initial credential options.","krb5_get_init_creds_opt_set_anonymous - Set or unset the anonymous flag in initial credential options.","krb5_get_init_creds_opt_set_canonicalize - Set or unset the canonicalize flag in initial credential options.","krb5_get_init_creds_opt_set_change_password_prompt - Set or unset change-password-prompt flag in initial credential options.","krb5_get_init_creds_opt_set_etype_list - Set allowable encryption types in initial credential options.","krb5_get_init_creds_opt_set_expire_callback - Set an expiration callback in initial credential options.","krb5_get_init_creds_opt_set_fast_ccache - Set FAST armor cache in initial credential options.","krb5_get_init_creds_opt_set_fast_ccache_name - Set location of FAST armor ccache in initial credential options.","krb5_get_init_creds_opt_set_fast_flags - Set FAST flags in initial credential options.","krb5_get_init_creds_opt_set_forwardable - Set or unset the forwardable flag in initial credential options.","krb5_get_init_creds_opt_set_in_ccache - Set an input credential cache in initial credential options.","krb5_get_init_creds_opt_set_out_ccache - Set an output credential cache in initial credential options.","krb5_get_init_creds_opt_set_pa - Supply options for preauthentication in initial credential options.","krb5_get_init_creds_opt_set_pac_request - Ask the KDC to include or not include a PAC in the ticket.","krb5_get_init_creds_opt_set_preauth_list - Set preauthentication types in initial credential options.","krb5_get_init_creds_opt_set_proxiable - Set or unset the proxiable flag in initial credential options.","krb5_get_init_creds_opt_set_renew_life - Set the ticket renewal lifetime in initial credential options.","krb5_get_init_creds_opt_set_responder - Set the responder function in initial credential options.","krb5_get_init_creds_opt_set_salt - Set salt for optimistic preauthentication in initial credential options.","krb5_get_init_creds_opt_set_tkt_life - Set the ticket lifetime in initial credential options.","krb5_get_init_creds_password - Get initial credentials using a password.","krb5_get_permitted_enctypes - Return a list of encryption types permitted for session keys.","krb5_get_profile - Retrieve configuration profile from the context.","krb5_get_prompt_types - Get prompt types array from a context.","krb5_get_renewed_creds - Get renewed credential from KDC using an existing credential.","krb5_get_server_rcache - Generate a replay cache object for server use and open it.","krb5_get_time_offsets - Return the time offsets from the os context.","krb5_get_validated_creds - Get validated credentials from the KDC.","krb5_init_context - Create a krb5 library context.","krb5_init_context_profile - Create a krb5 library context using a specified profile.","krb5_init_creds_free - Free an initial credentials context.","krb5_init_creds_get - Acquire credentials using an initial credentials context.","krb5_init_creds_get_creds - Retrieve acquired credentials from an initial credentials context.","krb5_init_creds_get_error - Get the last error from KDC from an initial credentials context.","krb5_init_creds_get_times - Retrieve ticket times from an initial credentials context.","krb5_init_creds_init - Create a context for acquiring initial credentials.","krb5_init_creds_set_keytab - Specify a keytab to use for acquiring initial credentials.","krb5_init_creds_set_password - Set a password for acquiring initial credentials.","krb5_init_creds_set_service - Specify a service principal for acquiring initial credentials.","krb5_init_creds_step - Get the next KDC request for acquiring initial credentials.","krb5_init_keyblock - Initialize an empty krb5_keyblock .","krb5_init_random_key","krb5_init_secure_context - Create a krb5 library context using only configuration files.","krb5_is_config_principal - Test whether a principal is a configuration principal.","krb5_is_referral_realm - Check for a match with KRB5_REFERRAL_REALM.","krb5_is_thread_safe - Test whether the Kerberos library was built with multithread support.","krb5_k_create_key - Create a krb5_key from the enctype and key data in a keyblock.","krb5_k_decrypt - Decrypt data using a key (operates on opaque key).","krb5_k_decrypt_iov - Decrypt data in place supporting AEAD (operates on opaque key).","krb5_k_encrypt - Encrypt data using a key (operates on opaque key).","krb5_k_encrypt_iov - Encrypt data in place supporting AEAD (operates on opaque key).","krb5_k_free_key - Decrement the reference count on a key and free it if it hits zero.","krb5_k_key_enctype - Retrieve the enctype of a krb5_key structure.","krb5_k_key_keyblock - Retrieve a copy of the keyblock from a krb5_key structure.","krb5_k_make_checksum - Compute a checksum (operates on opaque key).","krb5_k_make_checksum_iov - Fill in a checksum element in IOV array (operates on opaque key)","krb5_k_prf - Generate enctype-specific pseudo-random bytes (operates on opaque key).","krb5_k_reference_key - Increment the reference count on a key.","krb5_k_verify_checksum - Verify a checksum (operates on opaque key).","krb5_k_verify_checksum_iov - Validate a checksum element in IOV array (operates on opaque key).","krb5_kdc_sign_ticket - Sign a PAC, possibly including a ticket signature.","krb5_kdc_verify_ticket - Verify a PAC, possibly including ticket signature.","krb5_kt_add_entry - Add a new entry to a key table.","krb5_kt_client_default - Resolve the default client key table.","krb5_kt_close - Close a key table handle.","krb5_kt_default - Resolve the default key table.","krb5_kt_default_name - Get the default key table name.","krb5_kt_dup - Duplicate keytab handle.","krb5_kt_end_seq_get - Release a keytab cursor.","krb5_kt_free_entry","krb5_kt_get_entry - Get an entry from a key table.","krb5_kt_get_name - Get a key table name.","krb5_kt_get_type - Return the type of a key table.","krb5_kt_have_content - Check if a keytab exists and contains entries.","krb5_kt_next_entry - Retrieve the next entry from the key table.","krb5_kt_read_service_key - Retrieve a service key from a key table.","krb5_kt_remove_entry - Remove an entry from a key table.","krb5_kt_resolve - Get a handle for a key table.","krb5_kt_start_seq_get - Start a sequential retrieval of key table entries.","krb5_kuserok - Determine if a principal is authorized to log in as a local user.","krb5_make_authdata_kdc_issued - Encode and sign AD-KDCIssued authorization data.","krb5_marshal_credentials - Serialize a krb5_creds object.","krb5_merge_authdata - Merge two authorization data lists into a new list.","krb5_mk_1cred - Format a KRB-CRED message for a single set of credentials.","krb5_mk_error - Format and encode a KRB_ERROR message.","krb5_mk_ncred - Format a KRB-CRED message for an array of credentials.","krb5_mk_priv - Format a KRB-PRIV message.","krb5_mk_rep - Format and encrypt a KRB_AP_REP message.","krb5_mk_rep_dce - Format and encrypt a KRB_AP_REP message for DCE RPC.","krb5_mk_req - Create a KRB_AP_REQ message.","krb5_mk_req_extended - Create a KRB_AP_REQ message using supplied credentials.","krb5_mk_safe - Format a KRB-SAFE message.","krb5_os_localaddr - Return all interface addresses for this host.","krb5_pac_add_buffer - Add a buffer to a PAC handle.","krb5_pac_free - Free a PAC handle.","krb5_pac_get_buffer - Retrieve a buffer value from a PAC.","krb5_pac_get_client_info - Read client information from a PAC.","krb5_pac_get_types - Return an array of buffer types in a PAC handle.","krb5_pac_init - Create an empty Privilege Attribute Certificate (PAC) handle.","krb5_pac_parse - Unparse an encoded PAC into a new handle.","krb5_pac_sign","krb5_pac_sign_ext","krb5_pac_verify - Verify a PAC.","krb5_pac_verify_ext - Verify a PAC, possibly from a specified realm.","krb5_parse_name - Convert a string principal name to a krb5_principal structure.","krb5_parse_name_flags - Convert a string principal name to a krb5_principal with flags.","krb5_prepend_error_message - Add a prefix to the message for an error code.","krb5_principal2salt - Convert a principal name into the default salt for that principal.","krb5_principal_compare - Compare two principals.","krb5_principal_compare_any_realm - Compare two principals ignoring realm components.","krb5_principal_compare_flags - Compare two principals with additional flags.","krb5_process_key","krb5_prompter_posix - Prompt user for password.","krb5_random_key","krb5_rd_cred - Read and validate a KRB-CRED message.","krb5_rd_error - Decode a KRB-ERROR message.","krb5_rd_priv - Process a KRB-PRIV message.","krb5_rd_rep - Parse and decrypt a KRB_AP_REP message.","krb5_rd_rep_dce - Parse and decrypt a KRB_AP_REP message for DCE RPC.","krb5_rd_req - Parse and decrypt a KRB_AP_REQ message.","krb5_rd_safe - Process KRB-SAFE message.","krb5_read_password - Read a password from keyboard input.","krb5_realm_compare - Compare the realms of two principals.","krb5_recvauth - Server function for sendauth protocol.","krb5_recvauth_version - Server function for sendauth protocol with version parameter.","krb5_responder_get_challenge - Retrieve the challenge data for a given question in the responder context.","krb5_responder_list_questions - List the question names contained in the responder context.","krb5_responder_otp_challenge_free - Free the value returned by krb5_responder_otp_get_challenge().","krb5_responder_otp_get_challenge - Decode the KRB5_RESPONDER_QUESTION_OTP to a C struct.","krb5_responder_otp_set_answer - Answer the KRB5_RESPONDER_QUESTION_OTP question.","krb5_responder_pkinit_challenge_free - Free the value returned by krb5_responder_pkinit_get_challenge().","krb5_responder_pkinit_get_challenge - Decode the KRB5_RESPONDER_QUESTION_PKINIT to a C struct.","krb5_responder_pkinit_set_answer - Answer the KRB5_RESPONDER_QUESTION_PKINIT question for one identity.","krb5_responder_set_answer - Answer a named question in the responder context.","krb5_salttype_to_string - Convert a salt type to a string.","krb5_sendauth - Client function for sendauth protocol.","krb5_server_decrypt_ticket_keytab - Decrypt a ticket using the specified key table.","krb5_set_default_realm - Override the default realm for the specified context.","krb5_set_default_tgs_enctypes - Set default TGS encryption types in a krb5_context structure.","krb5_set_error_message - Set an extended error message for an error code.","krb5_set_kdc_recv_hook - Set a KDC post-receive hook function.","krb5_set_kdc_send_hook - Set a KDC pre-send hook function.","krb5_set_password - Set a password for a principal using specified credentials.","krb5_set_password_using_ccache - Set a password for a principal using cached credentials.","krb5_set_principal_realm - Set the realm field of a principal.","krb5_set_real_time - Set time offset field in a krb5_context structure.","krb5_set_trace_callback - Specify a callback function for trace events.","krb5_set_trace_filename - Specify a file name for directing trace events.","krb5_sname_match - Test whether a principal matches a matching principal.","krb5_sname_to_principal - Generate a full principal name from a service name.","krb5_string_to_cksumtype - Convert a string to a checksum type.","krb5_string_to_deltat - Convert a string to a delta time value.","krb5_string_to_enctype - Convert a string to an encryption type.","krb5_string_to_key","krb5_string_to_salttype - Convert a string to a salt type.","krb5_string_to_timestamp - Convert a string to a timestamp.","krb5_timeofday - Retrieve the current time with context specific time offset adjustment.","krb5_timestamp_to_sfstring - Convert a timestamp to a string, with optional output padding.","krb5_timestamp_to_string - Convert a timestamp to a string.","krb5_tkt_creds_free - Free a TGS request context.","krb5_tkt_creds_get - Synchronously obtain credentials using a TGS request context.","krb5_tkt_creds_get_creds - Retrieve acquired credentials from a TGS request context.","krb5_tkt_creds_get_times - Retrieve ticket times from a TGS request context.","krb5_tkt_creds_init - Create a context to get credentials from a KDC\u2019s Ticket Granting Service.","krb5_tkt_creds_step - Get the next KDC request in a TGS exchange.","krb5_unmarshal_credentials - Deserialize a krb5_creds object.","krb5_unparse_name - Convert a krb5_principal structure to a string representation.","krb5_unparse_name_ext - Convert krb5_principal structure to string and length.","krb5_unparse_name_flags - Convert krb5_principal structure to a string with flags.","krb5_unparse_name_flags_ext - Convert krb5_principal structure to string format with flags.","krb5_us_timeofday - Retrieve the system time of day, in sec and ms, since the epoch.","krb5_use_enctype","krb5_verify_authdata_kdc_issued - Unwrap and verify AD-KDCIssued authorization data.","krb5_verify_checksum","krb5_verify_init_creds - Verify initial credentials against a keytab.","krb5_verify_init_creds_opt_init - Initialize a credential verification options structure.","krb5_verify_init_creds_opt_set_ap_req_nofail - Set whether credential verification is required.","krb5_vprepend_error_message - Add a prefix to the message for an error code using a va_list.","krb5_vset_error_message - Set an extended error message for an error code using a va_list.","krb5_vwrap_error_message - Add a prefix to a different error code\u2019s message using a va_list.","krb5_wrap_error_message - Add a prefix to a different error code\u2019s message.","Complete reference - API and datatypes","ADDRTYPE_ADDRPORT","ADDRTYPE_CHAOS","ADDRTYPE_DDP","ADDRTYPE_INET","ADDRTYPE_INET6","ADDRTYPE_IPPORT","ADDRTYPE_ISO","ADDRTYPE_IS_LOCAL","ADDRTYPE_NETBIOS","ADDRTYPE_XNS","AD_TYPE_EXTERNAL","AD_TYPE_FIELD_TYPE_MASK","AD_TYPE_REGISTERED","AD_TYPE_RESERVED","AP_OPTS_ETYPE_NEGOTIATION","AP_OPTS_MUTUAL_REQUIRED","AP_OPTS_RESERVED","AP_OPTS_USE_SESSION_KEY","AP_OPTS_USE_SUBKEY","AP_OPTS_WIRE_MASK","CKSUMTYPE_CMAC_CAMELLIA128","CKSUMTYPE_CMAC_CAMELLIA256","CKSUMTYPE_CRC32","CKSUMTYPE_DESCBC","CKSUMTYPE_HMAC_MD5_ARCFOUR","CKSUMTYPE_HMAC_SHA1_96_AES128","CKSUMTYPE_HMAC_SHA1_96_AES256","CKSUMTYPE_HMAC_SHA1_DES3","CKSUMTYPE_HMAC_SHA256_128_AES128","CKSUMTYPE_HMAC_SHA384_192_AES256","CKSUMTYPE_MD5_HMAC_ARCFOUR","CKSUMTYPE_NIST_SHA","CKSUMTYPE_RSA_MD4","CKSUMTYPE_RSA_MD4_DES","CKSUMTYPE_RSA_MD5","CKSUMTYPE_RSA_MD5_DES","CKSUMTYPE_SHA1","ENCTYPE_AES128_CTS_HMAC_SHA1_96","ENCTYPE_AES128_CTS_HMAC_SHA256_128","ENCTYPE_AES256_CTS_HMAC_SHA1_96","ENCTYPE_AES256_CTS_HMAC_SHA384_192","ENCTYPE_ARCFOUR_HMAC","ENCTYPE_ARCFOUR_HMAC_EXP","ENCTYPE_CAMELLIA128_CTS_CMAC","ENCTYPE_CAMELLIA256_CTS_CMAC","ENCTYPE_DES3_CBC_ENV","ENCTYPE_DES3_CBC_RAW","ENCTYPE_DES3_CBC_SHA","ENCTYPE_DES3_CBC_SHA1","ENCTYPE_DES_CBC_CRC","ENCTYPE_DES_CBC_MD4","ENCTYPE_DES_CBC_MD5","ENCTYPE_DES_CBC_RAW","ENCTYPE_DES_HMAC_SHA1","ENCTYPE_DSA_SHA1_CMS","ENCTYPE_MD5_RSA_CMS","ENCTYPE_NULL","ENCTYPE_RC2_CBC_ENV","ENCTYPE_RSA_ENV","ENCTYPE_RSA_ES_OAEP_ENV","ENCTYPE_SHA1_RSA_CMS","ENCTYPE_UNKNOWN","KDC_OPT_ALLOW_POSTDATE","KDC_OPT_CANONICALIZE","KDC_OPT_CNAME_IN_ADDL_TKT","KDC_OPT_DISABLE_TRANSITED_CHECK","KDC_OPT_ENC_TKT_IN_SKEY","KDC_OPT_FORWARDABLE","KDC_OPT_FORWARDED","KDC_OPT_POSTDATED","KDC_OPT_PROXIABLE","KDC_OPT_PROXY","KDC_OPT_RENEW","KDC_OPT_RENEWABLE","KDC_OPT_RENEWABLE_OK","KDC_OPT_REQUEST_ANONYMOUS","KDC_OPT_VALIDATE","KDC_TKT_COMMON_MASK","KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE","KRB5_ANONYMOUS_PRINCSTR","KRB5_ANONYMOUS_REALMSTR","KRB5_AP_REP","KRB5_AP_REQ","KRB5_AS_REP","KRB5_AS_REQ","KRB5_AUTHDATA_AND_OR","KRB5_AUTHDATA_AP_OPTIONS","KRB5_AUTHDATA_AUTH_INDICATOR","KRB5_AUTHDATA_CAMMAC","KRB5_AUTHDATA_ETYPE_NEGOTIATION","KRB5_AUTHDATA_FX_ARMOR","KRB5_AUTHDATA_IF_RELEVANT","KRB5_AUTHDATA_INITIAL_VERIFIED_CAS","KRB5_AUTHDATA_KDC_ISSUED","KRB5_AUTHDATA_MANDATORY_FOR_KDC","KRB5_AUTHDATA_OSF_DCE","KRB5_AUTHDATA_SESAME","KRB5_AUTHDATA_SIGNTICKET","KRB5_AUTHDATA_WIN2K_PAC","KRB5_AUTH_CONTEXT_DO_SEQUENCE","KRB5_AUTH_CONTEXT_DO_TIME","KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR","KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR","KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR","KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR","KRB5_AUTH_CONTEXT_PERMIT_ALL","KRB5_AUTH_CONTEXT_RET_SEQUENCE","KRB5_AUTH_CONTEXT_RET_TIME","KRB5_AUTH_CONTEXT_USE_SUBKEY","KRB5_CRED","KRB5_CRYPTO_TYPE_CHECKSUM","KRB5_CRYPTO_TYPE_DATA","KRB5_CRYPTO_TYPE_EMPTY","KRB5_CRYPTO_TYPE_HEADER","KRB5_CRYPTO_TYPE_PADDING","KRB5_CRYPTO_TYPE_SIGN_ONLY","KRB5_CRYPTO_TYPE_STREAM","KRB5_CRYPTO_TYPE_TRAILER","KRB5_CYBERSAFE_SECUREID","KRB5_DOMAIN_X500_COMPRESS","KRB5_ENCPADATA_REQ_ENC_PA_REP","KRB5_ERROR","KRB5_FAST_REQUIRED","KRB5_GC_CACHED","KRB5_GC_CANONICALIZE","KRB5_GC_CONSTRAINED_DELEGATION","KRB5_GC_FORWARDABLE","KRB5_GC_NO_STORE","KRB5_GC_NO_TRANSIT_CHECK","KRB5_GC_USER_USER","KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST","KRB5_GET_INIT_CREDS_OPT_ANONYMOUS","KRB5_GET_INIT_CREDS_OPT_CANONICALIZE","KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT","KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST","KRB5_GET_INIT_CREDS_OPT_FORWARDABLE","KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST","KRB5_GET_INIT_CREDS_OPT_PROXIABLE","KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE","KRB5_GET_INIT_CREDS_OPT_SALT","KRB5_GET_INIT_CREDS_OPT_TKT_LIFE","KRB5_INIT_CONTEXT_KDC","KRB5_INIT_CONTEXT_SECURE","KRB5_INIT_CREDS_STEP_FLAG_CONTINUE","KRB5_INT16_MAX","KRB5_INT16_MIN","KRB5_INT32_MAX","KRB5_INT32_MIN","KRB5_KEYUSAGE_AD_ITE","KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM","KRB5_KEYUSAGE_AD_MTE","KRB5_KEYUSAGE_AD_SIGNEDPATH","KRB5_KEYUSAGE_APP_DATA_CKSUM","KRB5_KEYUSAGE_APP_DATA_ENCRYPT","KRB5_KEYUSAGE_AP_REP_ENCPART","KRB5_KEYUSAGE_AP_REQ_AUTH","KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM","KRB5_KEYUSAGE_AS_REP_ENCPART","KRB5_KEYUSAGE_AS_REQ","KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS","KRB5_KEYUSAGE_CAMMAC","KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT","KRB5_KEYUSAGE_ENC_CHALLENGE_KDC","KRB5_KEYUSAGE_FAST_ENC","KRB5_KEYUSAGE_FAST_FINISHED","KRB5_KEYUSAGE_FAST_REP","KRB5_KEYUSAGE_FAST_REQ_CHKSUM","KRB5_KEYUSAGE_GSS_TOK_MIC","KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG","KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV","KRB5_KEYUSAGE_IAKERB_FINISHED","KRB5_KEYUSAGE_KDC_REP_TICKET","KRB5_KEYUSAGE_KRB_CRED_ENCPART","KRB5_KEYUSAGE_KRB_ERROR_CKSUM","KRB5_KEYUSAGE_KRB_PRIV_ENCPART","KRB5_KEYUSAGE_KRB_SAFE_CKSUM","KRB5_KEYUSAGE_PA_AS_FRESHNESS","KRB5_KEYUSAGE_PA_FX_COOKIE","KRB5_KEYUSAGE_PA_OTP_REQUEST","KRB5_KEYUSAGE_PA_PKINIT_KX","KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY","KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST","KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM","KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID","KRB5_KEYUSAGE_PA_SAM_RESPONSE","KRB5_KEYUSAGE_SPAKE","KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY","KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY","KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY","KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY","KRB5_KEYUSAGE_TGS_REQ_AUTH","KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM","KRB5_KPASSWD_ACCESSDENIED","KRB5_KPASSWD_AUTHERROR","KRB5_KPASSWD_BAD_VERSION","KRB5_KPASSWD_HARDERROR","KRB5_KPASSWD_INITIAL_FLAG_NEEDED","KRB5_KPASSWD_MALFORMED","KRB5_KPASSWD_SOFTERROR","KRB5_KPASSWD_SUCCESS","KRB5_LRQ_ALL_ACCT_EXPTIME","KRB5_LRQ_ALL_LAST_INITIAL","KRB5_LRQ_ALL_LAST_RENEWAL","KRB5_LRQ_ALL_LAST_REQ","KRB5_LRQ_ALL_LAST_TGT","KRB5_LRQ_ALL_LAST_TGT_ISSUED","KRB5_LRQ_ALL_PW_EXPTIME","KRB5_LRQ_NONE","KRB5_LRQ_ONE_ACCT_EXPTIME","KRB5_LRQ_ONE_LAST_INITIAL","KRB5_LRQ_ONE_LAST_RENEWAL","KRB5_LRQ_ONE_LAST_REQ","KRB5_LRQ_ONE_LAST_TGT","KRB5_LRQ_ONE_LAST_TGT_ISSUED","KRB5_LRQ_ONE_PW_EXPTIME","KRB5_NT_ENTERPRISE_PRINCIPAL","KRB5_NT_ENT_PRINCIPAL_AND_ID","KRB5_NT_MS_PRINCIPAL","KRB5_NT_MS_PRINCIPAL_AND_ID","KRB5_NT_PRINCIPAL","KRB5_NT_SMTP_NAME","KRB5_NT_SRV_HST","KRB5_NT_SRV_INST","KRB5_NT_SRV_XHST","KRB5_NT_UID","KRB5_NT_UNKNOWN","KRB5_NT_WELLKNOWN","KRB5_NT_X500_PRINCIPAL","KRB5_PAC_ATTRIBUTES_INFO","KRB5_PAC_CLIENT_CLAIMS","KRB5_PAC_CLIENT_INFO","KRB5_PAC_CREDENTIALS_INFO","KRB5_PAC_DELEGATION_INFO","KRB5_PAC_DEVICE_CLAIMS","KRB5_PAC_DEVICE_INFO","KRB5_PAC_FULL_CHECKSUM","KRB5_PAC_LOGON_INFO","KRB5_PAC_PRIVSVR_CHECKSUM","KRB5_PAC_REQUESTOR","KRB5_PAC_SERVER_CHECKSUM","KRB5_PAC_TICKET_CHECKSUM","KRB5_PAC_UPN_DNS_INFO","KRB5_PADATA_AFS3_SALT","KRB5_PADATA_AP_REQ","KRB5_PADATA_AS_CHECKSUM","KRB5_PADATA_AS_FRESHNESS","KRB5_PADATA_ENCRYPTED_CHALLENGE","KRB5_PADATA_ENC_SANDIA_SECURID","KRB5_PADATA_ENC_TIMESTAMP","KRB5_PADATA_ENC_UNIX_TIME","KRB5_PADATA_ETYPE_INFO","KRB5_PADATA_ETYPE_INFO2","KRB5_PADATA_FOR_USER","KRB5_PADATA_FX_COOKIE","KRB5_PADATA_FX_ERROR","KRB5_PADATA_FX_FAST","KRB5_PADATA_GET_FROM_TYPED_DATA","KRB5_PADATA_NONE","KRB5_PADATA_OSF_DCE","KRB5_PADATA_OTP_CHALLENGE","KRB5_PADATA_OTP_PIN_CHANGE","KRB5_PADATA_OTP_REQUEST","KRB5_PADATA_PAC_OPTIONS","KRB5_PADATA_PAC_REQUEST","KRB5_PADATA_PKINIT_KX","KRB5_PADATA_PK_AS_REP","KRB5_PADATA_PK_AS_REP_OLD","KRB5_PADATA_PK_AS_REQ","KRB5_PADATA_PK_AS_REQ_OLD","KRB5_PADATA_PW_SALT","KRB5_PADATA_REDHAT_IDP_OAUTH2","KRB5_PADATA_REDHAT_PASSKEY","KRB5_PADATA_REFERRAL","KRB5_PADATA_S4U_X509_USER","KRB5_PADATA_SAM_CHALLENGE","KRB5_PADATA_SAM_CHALLENGE_2","KRB5_PADATA_SAM_REDIRECT","KRB5_PADATA_SAM_RESPONSE","KRB5_PADATA_SAM_RESPONSE_2","KRB5_PADATA_SESAME","KRB5_PADATA_SPAKE","KRB5_PADATA_SVR_REFERRAL_INFO","KRB5_PADATA_TGS_REQ","KRB5_PADATA_USE_SPECIFIED_KVNO","KRB5_PRINCIPAL_COMPARE_CASEFOLD","KRB5_PRINCIPAL_COMPARE_ENTERPRISE","KRB5_PRINCIPAL_COMPARE_IGNORE_REALM","KRB5_PRINCIPAL_COMPARE_UTF8","KRB5_PRINCIPAL_PARSE_ENTERPRISE","KRB5_PRINCIPAL_PARSE_IGNORE_REALM","KRB5_PRINCIPAL_PARSE_NO_DEF_REALM","KRB5_PRINCIPAL_PARSE_NO_REALM","KRB5_PRINCIPAL_PARSE_REQUIRE_REALM","KRB5_PRINCIPAL_UNPARSE_DISPLAY","KRB5_PRINCIPAL_UNPARSE_NO_REALM","KRB5_PRINCIPAL_UNPARSE_SHORT","KRB5_PRIV","KRB5_PROMPT_TYPE_NEW_PASSWORD","KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN","KRB5_PROMPT_TYPE_PASSWORD","KRB5_PROMPT_TYPE_PREAUTH","KRB5_PVNO","KRB5_REALM_BRANCH_CHAR","KRB5_RECVAUTH_BADAUTHVERS","KRB5_RECVAUTH_SKIP_VERSION","KRB5_REFERRAL_REALM","KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN","KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN","KRB5_RESPONDER_OTP_FLAGS_NEXTOTP","KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN","KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC","KRB5_RESPONDER_OTP_FORMAT_DECIMAL","KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL","KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW","KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY","KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED","KRB5_RESPONDER_QUESTION_OTP","KRB5_RESPONDER_QUESTION_PASSWORD","KRB5_RESPONDER_QUESTION_PKINIT","KRB5_SAFE","KRB5_SAM_MUST_PK_ENCRYPT_SAD","KRB5_SAM_SEND_ENCRYPTED_SAD","KRB5_SAM_USE_SAD_AS_KEY","KRB5_TC_MATCH_2ND_TKT","KRB5_TC_MATCH_AUTHDATA","KRB5_TC_MATCH_FLAGS","KRB5_TC_MATCH_FLAGS_EXACT","KRB5_TC_MATCH_IS_SKEY","KRB5_TC_MATCH_KTYPE","KRB5_TC_MATCH_SRV_NAMEONLY","KRB5_TC_MATCH_TIMES","KRB5_TC_MATCH_TIMES_EXACT","KRB5_TC_NOTICKET","KRB5_TC_OPENCLOSE","KRB5_TC_SUPPORTED_KTYPES","KRB5_TGS_NAME","KRB5_TGS_NAME_SIZE","KRB5_TGS_REP","KRB5_TGS_REQ","KRB5_TKT_CREDS_STEP_FLAG_CONTINUE","KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL","KRB5_WELLKNOWN_NAMESTR","LR_TYPE_INTERPRETATION_MASK","LR_TYPE_THIS_SERVER_ONLY","MAX_KEYTAB_NAME_LEN","MSEC_DIRBIT","MSEC_VAL_MASK","SALT_TYPE_AFS_LENGTH","SALT_TYPE_NO_LENGTH","THREEPARAMOPEN","TKT_FLG_ANONYMOUS","TKT_FLG_ENC_PA_REP","TKT_FLG_FORWARDABLE","TKT_FLG_FORWARDED","TKT_FLG_HW_AUTH","TKT_FLG_INITIAL","TKT_FLG_INVALID","TKT_FLG_MAY_POSTDATE","TKT_FLG_OK_AS_DELEGATE","TKT_FLG_POSTDATED","TKT_FLG_PRE_AUTH","TKT_FLG_PROXIABLE","TKT_FLG_PROXY","TKT_FLG_RENEWABLE","TKT_FLG_TRANSIT_POLICY_CHECKED","VALID_INT_BITS","VALID_UINT_BITS","krb5 simple macros","krb524_convert_creds_kdc","krb524_init_ets","krb5_const","krb5_princ_component","krb5_princ_name","krb5_princ_realm","krb5_princ_set_realm","krb5_princ_set_realm_data","krb5_princ_set_realm_length","krb5_princ_size","krb5_princ_type","krb5_roundup","krb5_x","krb5_xc","krb5 types and structures","krb5_address","krb5_addrtype","krb5_ap_rep","krb5_ap_rep_enc_part","krb5_ap_req","krb5_auth_context","krb5_authdata","krb5_authdatatype","krb5_authenticator","krb5_boolean","krb5_cc_cursor","krb5_ccache","krb5_cccol_cursor","krb5_checksum","krb5_cksumtype","krb5_const_pointer","krb5_const_principal","krb5_context","krb5_cred","krb5_cred_enc_part","krb5_cred_info","krb5_creds","krb5_crypto_iov","krb5_cryptotype","krb5_data","krb5_deltat","krb5_enc_data","krb5_enc_kdc_rep_part","krb5_enc_tkt_part","krb5_encrypt_block","krb5_enctype","krb5_error","krb5_error_code","krb5_expire_callback_func","krb5_flags","krb5_get_init_creds_opt","krb5_gic_opt_pa_data","krb5_init_creds_context","krb5_int16","krb5_int32","krb5_kdc_rep","krb5_kdc_req","krb5_key","krb5_keyblock","krb5_keytab","krb5_keytab_entry","krb5_keyusage","krb5_kt_cursor","krb5_kvno","krb5_last_req_entry","krb5_magic","krb5_mk_req_checksum_func","krb5_msgtype","krb5_octet","krb5_pa_data","krb5_pa_pac_req","krb5_pa_server_referral_data","krb5_pa_svr_referral_data","krb5_pac","krb5_pointer","krb5_post_recv_fn","krb5_pre_send_fn","krb5_preauthtype","krb5_principal","krb5_principal_data","krb5_prompt","krb5_prompt_type","krb5_prompter_fct","krb5_pwd_data","krb5_rcache","krb5_replay_data","krb5_responder_context","krb5_responder_fn","krb5_responder_otp_challenge","krb5_responder_otp_tokeninfo","krb5_responder_pkinit_challenge","krb5_responder_pkinit_identity","krb5_response","krb5_ticket","krb5_ticket_times","krb5_timestamp","krb5_tkt_authent","krb5_tkt_creds_context","krb5_trace_callback","krb5_trace_info","krb5_transited","krb5_typed_data","krb5_ui_2","krb5_ui_4","krb5_verify_init_creds_opt","passwd_phrase_element","Year 2038 considerations for uses of krb5_timestamp","Credential cache","Supported date and time formats","Kerberos V5 concepts","keytab","replay cache","stash file","Organization of the source directory","Doing the build","Building Kerberos V5","Options to configure","osconf.hin","How to build this documentation from the source","Copyright","Credential cache file format","KDC cookie format","PKINIT freshness tokens","Protocols and file formats","Keytab file format","Replay cache file format","MIT Kerberos Documentation (1.21.3)","MIT Kerberos defaults","MIT Kerberos features","MIT Kerberos License information","Credential cache selection interface (ccselect)","PKINIT certificate authorization interface (certauth)","Client preauthentication interface (clpreauth)","General plugin concepts","GSSAPI mechanism interface","Host-to-realm interface (hostrealm)","For plugin module developers","Internal pluggable interfaces","kadmin authorization interface (kadm5_auth)","KADM5 hook interface (kadm5_hook)","KDC policy interface (kdcpolicy)","KDC preauthentication interface (kdcpreauth)","Local authorization interface (localauth)","Server location interface (locate)","Configuration interface (profile)","Password quality interface (pwqual)","Resources","For users","Password management","Ticket management","User commands","kdestroy","kinit","klist","kpasswd","krb5-config","ksu","kswitch","kvno","sclient","User config files",".k5identity",".k5login","kerberos"],titleterms:{"0":911,"1":[185,911,916],"2038":896,"21":916,"3":916,"6113":[101,119],"boolean":59,"byte":[112,117,119,121,296],"default":[14,28,36,135,136,145,156,210,227,303,305,306,347,377,378,897,900,901,917],"do":904,"export":43,"function":[118,219,257,363,364,375,380,381,386],"import":43,"new":[108,149,236,302,322,339,946],"null":91,"public":[48,789,804],"return":[53,58,95,96,97,111,112,116,136,210,261,266,312,332,337,367,370],"switch":[34,160],"while":41,A:946,For:[30,45,926,937],No:41,OF:946,One:46,THE:946,The:[14,32,36],abbrevi:898,about:32,absolut:898,acceptor:43,access:938,account:[35,166,938],acl:[19,34],acquir:[15,271,272,275,276,277,278,279,401],ad:[14,15,320,412],ad_type_extern:432,ad_type_field_type_mask:433,ad_type_regist:434,ad_type_reserv:435,add:[34,302,333,346,417,419,420],add_entri:11,add_mkei:6,add_polici:3,add_princip:3,addit:[31,126,224,350],address:[25,52,53,54,62,64,82,172,198,240,332],addrtype_addrport:422,addrtype_chao:423,addrtype_ddp:424,addrtype_inet6:426,addrtype_inet:425,addrtype_ipport:427,addrtype_is_loc:429,addrtype_iso:428,addrtype_netbio:430,addrtype_xn:431,adjust:396,admin:[39,41],administr:[1,23,30,34],advanc:13,advic:[32,38],aead:[43,100,103,288,290],against:414,alia:192,all:332,alloc:[106,212,214,219,236],allow:[55,167,244],allow_weak_crypto:55,also:[2,3,4,5,6,7,8,9,10,11,12,19,20,21,941,942,943,944,945,946,947,948,949,951,952,953],alter:897,an:[53,57,58,63,64,65,67,68,69,71,72,73,74,76,77,78,79,80,81,82,84,85,86,87,88,89,90,111,115,118,124,166,172,173,185,192,193,204,211,212,213,220,224,245,250,251,264,270,271,272,273,274,280,310,316,325,337,338,339,346,379,392,417,418,908],ani:165,anonym:[37,46,57,58,241],anoth:179,answer:[369,372,373],ap_opts_etype_negoti:436,ap_opts_mutual_requir:437,ap_opts_reserv:438,ap_opts_use_session_kei:439,ap_opts_use_subkei:440,ap_opts_wire_mask:441,api:[44,48,421,908],appdefault:[21,59,60],applic:[14,15,32,38,45,55],archiv:936,argument:92,ark:6,armor:[246,247],arrai:[98,114,130,172,198,200,204,211,220,263,295,299,325,337],ask:253,asn:185,assign:[200,218],attack:25,attribut:[43,338],auth:[62,63,64,65,67,68,69,71,72,73,74,76,77,79,80,81,82,84,85,86,87,88,89,90],authdata:927,authent:[16,23,41,65,78,200,946],author:[28,37,173,184,189,195,319,320,322,412,921,927,928,932,946,953],autoconf:904,awai:26,back:[17,22],background:[0,901],backup:17,behavior:[19,38],berkelei:24,between:44,binari:904,block:95,buffer:[333,335,337],bug:953,build:[57,91,92,93,904,905,908],built:285,c:[368,371],cach:[71,85,132,133,134,135,136,137,139,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,246,250,251,265,383,897,901,910,915,920],call:48,callback:[46,63,80,245,386],cannot:41,canonic:[38,194,242],capath:21,caus:79,ccach:[138,247,897],ccselect:[21,920],cert:41,certauth:[21,921],certif:[37,41,338,921],cf2:107,chain:41,challeng:365,chang:[23,166,169,243,938],change_password:3,channel:936,check:[165,167,284,313],checksum:[63,80,81,96,109,110,111,113,114,127,129,130,170,204,294,295,298,299,390],choos:26,cipher:[79,95,106,108],cksumtype_cmac_camellia128:442,cksumtype_cmac_camellia256:443,cksumtype_crc32:444,cksumtype_descbc:445,cksumtype_hmac_md5_arcfour:446,cksumtype_hmac_sha1_96_aes128:447,cksumtype_hmac_sha1_96_aes256:448,cksumtype_hmac_sha1_des3:449,cksumtype_hmac_sha256_128_aes128:450,cksumtype_hmac_sha384_192_aes256:451,cksumtype_md5_hmac_arcfour:452,cksumtype_nist_sha:453,cksumtype_rsa_md4:454,cksumtype_rsa_md4_d:455,cksumtype_rsa_md5:456,cksumtype_rsa_md5_d:457,cksumtype_sha1:458,clean:904,clear:171,clear_list:11,client:[15,29,33,37,132,303,336,375,900,922],clock:[15,167],close:[133,304],clpreauth:[21,922],code:[228,346,379,417,418,419,420],collect:[161,162,163,164,165,897],collis:109,combin:107,command:[3,5,6,11,940],common:12,commonli:906,compar:[52,105,348,349,350,362],compat:26,complet:421,compon:349,comput:[104,107,113,294],concept:[899,923],conf:[20,21,34,59,60],config:[945,950],configur:[15,18,22,26,28,29,33,34,35,36,37,39,141,155,262,282,283,906,910,934],connect:[41,62],consider:[36,896],constrain:43,contain:[165,189,313,366],content:[18,31,181,203,206,209,216,217,905,926],context:[62,63,64,65,67,68,69,71,72,73,74,76,77,78,79,80,81,82,84,85,86,87,88,89,90,171,179,205,262,263,266,268,269,270,271,272,273,274,275,282,365,366,373,377,396,399,400,401,402,403,946],contribut:0,conveni:48,convert:[49,50,51,56,125,126,170,187,192,193,344,345,347,374,390,391,392,394,395,397,398,406,407,408,409],cooki:911,copi:[134,172,173,174,175,176,177,178,179,180,181,182,183,293],copyright:909,correct:15,count:[93,291,297],creat:[5,6,34,37,41,78,149,268,269,275,282,286,329,330,338,403,946],create_polici:5,cred:[223,323,325,354],credenti:[15,41,43,46,51,132,133,134,135,136,137,139,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,220,235,236,237,238,240,241,242,243,244,245,246,247,248,249,250,251,252,254,255,256,257,258,259,260,264,267,270,271,272,273,274,275,276,277,278,279,323,325,330,382,383,400,401,403,414,415,416,897,910,920],cross:23,current:[167,396],cursor:[162,308],daemon:34,dai:410,data:[58,99,100,101,102,103,104,124,173,184,189,195,198,200,209,286,287,288,289,290,320,322,365,412,927],databas:[3,14,17,23,24,34,39,927],datatyp:421,date:898,db2:24,dbdefault:20,dbmodul:20,dce:[328,358],de:14,decis:39,declar:[805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881,882,883,884,885,886,887,888,889,890,891,892,893,894,895],decod:[185,355,368,371],decrement:291,decrypt:[99,100,287,288,357,358,359,376],defin:36,del_str:3,deleg:43,delete_entri:11,delete_polici:3,delete_princip:3,delta:391,deprec:[48,789],deriv:101,descript:[2,3,4,5,6,7,8,9,10,11,12,19,941,942,943,944,945,946,947,948,949,951,952,953],deseri:405,destroi:[5,6,137,939],destroy_polici:5,determin:[160,319],develop:[43,45,926],dictionari:25,differ:[23,44,419,420],direct:387,directli:48,directori:[903,904,906],discoveri:39,dn:[15,38],document:[0,898,908,916],domain_realm:21,dump:[6,23],duplic:[138,307],durat:898,dure:41,each:34,edit:34,effect:946,element:[114,130,195,295,299],empti:[280,338],encod:[320,324,339],encrypt:[20,26,41,97,102,103,104,105,111,115,118,128,192,193,211,244,261,289,290,327,328,378,392],enctyp:[26,115,117,124,229,286,292,296],enctype_aes128_cts_hmac_sha1_96:459,enctype_aes128_cts_hmac_sha256_128:460,enctype_aes256_cts_hmac_sha1_96:461,enctype_aes256_cts_hmac_sha384_192:462,enctype_arcfour_hmac:463,enctype_arcfour_hmac_exp:464,enctype_camellia128_cts_cmac:465,enctype_camellia256_cts_cmac:466,enctype_des3_cbc_env:467,enctype_des3_cbc_raw:468,enctype_des3_cbc_sha1:470,enctype_des3_cbc_sha:469,enctype_des_cbc_crc:471,enctype_des_cbc_md4:472,enctype_des_cbc_md5:473,enctype_des_cbc_raw:474,enctype_des_hmac_sha1:475,enctype_dsa_sha1_cm:476,enctype_md5_rsa_cm:477,enctype_nul:478,enctype_rc2_cbc_env:479,enctype_rsa_env:480,enctype_rsa_es_oaep_env:481,enctype_sha1_rsa_cm:482,enctype_unknown:483,end:22,entri:[139,150,217,302,310,313,314,316,318,910,914],environ:[2,3,4,5,6,7,8,9,10,11,12,27,906,941,942,943,944,946,947,948,949,953],epoch:410,error:[12,41,171,179,212,213,228,273,346,355,379,417,418,419,420],etc:38,event:[386,387],everi:158,exampl:[10,11,19,46,906,945,951,952],exchang:[41,404],execut:946,exist:[166,264,313],expans:21,expir:[41,245],extend:[171,179,228,379,418],extens:43,fact:918,fail:[34,41],fast:[238,246,247,248],featur:[906,918],field:[64,83,84,97,209,384,385],file:[8,18,20,21,32,33,34,282,387,902,910,913,914,915,941,942,943,947,948,950],fill:[98,114,295],find:[132,195],fine:906,finish:139,firewal:15,flag:[66,83,142,157,238,241,242,243,248,249,255,345,350,408,409],format:[185,223,323,324,325,326,327,328,331,409,898,910,911,913,914,915],forward:[223,249],free:[61,106,162,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,237,270,291,334,367,370,399],frequent:[41,48],fresh:[37,912],from:[14,15,26,59,60,62,63,64,65,66,67,68,69,71,72,73,74,76,77,124,141,142,150,151,153,179,229,238,262,263,264,266,267,272,273,274,286,293,310,314,315,316,335,336,343,361,389,401,402,403,908,923],full:[143,389],fx:107,gener:[37,62,115,117,119,121,124,213,265,296,389,917,923],get:[15,41,46,63,118,141,145,164,169,223,224,228,231,235,260,263,264,267,273,279,306,310,311,317,403,404],get_init_cr:46,get_polici:3,get_princip:3,get_str:3,getdat:898,given:365,grant:[403,938],gssapi:[28,43,924],guid:31,ha:41,handl:[133,138,304,307,317,333,334,337,338,339],header:[98,910],heimdal:44,hin:907,histori:[3,14,23,953],hit:291,hook:[380,381,929],host:[17,28,32,34,41,231,332,925],hostnam:[39,194],hostrealm:[21,925],how:908,http:29,ident:[21,372],ignor:349,includ:[253,300,301],increment:[23,34,297],indic:16,inform:[15,21,336,901,919],initi:[41,43,46,78,108,147,165,235,236,237,238,240,241,242,243,244,245,246,247,248,249,250,251,252,254,255,256,257,258,259,260,270,271,272,273,274,275,276,277,278,279,280,414,415],input:[101,250,361],instal:[31,33,34,904,906,946],instanc:36,instruct:946,interact:46,interfac:[21,48,332,920,921,922,924,925,927,928,929,930,931,932,933,934,935],intern:[804,927],interoper:918,interpos:924,iov:[43,98,114,130,295,299],irc:936,iter:163,its:161,k5ident:951,k5login:952,k5srvutil:2,kadm5:[19,929],kadm5_auth:[21,928],kadm5_hook:[21,929],kadmin:[3,928],kadmind:[4,923],kdb5_ldap_util:5,kdb5_util:6,kdb:927,kdc:[14,20,28,34,35,37,39,41,229,253,264,267,273,279,380,381,403,404,911,917,923,930,931],kdc_opt_allow_postd:484,kdc_opt_canonic:485,kdc_opt_cname_in_addl_tkt:486,kdc_opt_disable_transited_check:487,kdc_opt_enc_tkt_in_skei:488,kdc_opt_forward:[489,490],kdc_opt_postd:491,kdc_opt_proxi:[492,493],kdc_opt_renew:[494,495],kdc_opt_renewable_ok:496,kdc_opt_request_anonym:497,kdc_opt_valid:498,kdc_tkt_common_mask:499,kdcdefault:20,kdcissu:[320,412],kdcpolici:930,kdcpreauth:[21,931],kdestroi:[939,941],kei:[14,23,26,67,68,90,99,101,102,107,110,111,112,115,124,125,126,217,235,261,286,287,288,289,290,291,294,295,296,297,298,299,302,303,304,305,306,310,311,312,314,315,316,317,318,376,914],kerbero:[0,15,17,22,23,34,39,44,49,50,51,52,127,128,166,231,285,899,905,916,917,918,919,927,939,953],keyblock:[67,72,73,76,86,88,99,100,102,103,113,114,129,130,180,181,286,293],keyboard:361,keysalt:20,keytab:[15,32,34,38,276,307,308,313,414,900,914],kinit:[939,942],kldap:24,klist:[939,943],klmdb:24,known:163,kpasswd:944,kprop:[7,41],kpropd:8,kproplog:9,krb524_convert_creds_kdc:790,krb524_init_et:791,krb5:[21,34,48,59,60,205,219,268,269,282,789,804,945],krb5_425_conv_princip:49,krb5_524_conv_princip:50,krb5_524_convert_cr:51,krb5_address:805,krb5_address_compar:52,krb5_address_ord:53,krb5_address_search:54,krb5_addrtyp:806,krb5_allow_weak_crypto:55,krb5_altauth_att_challenge_respons:500,krb5_aname_to_localnam:56,krb5_anonymous_princip:57,krb5_anonymous_princstr:501,krb5_anonymous_realm:58,krb5_anonymous_realmstr:502,krb5_ap_rep:[503,807],krb5_ap_rep_enc_part:[199,808],krb5_ap_req:[504,809],krb5_appdefault_boolean:59,krb5_appdefault_str:60,krb5_as_rep:505,krb5_as_req:506,krb5_auth_con_fre:61,krb5_auth_con_genaddr:62,krb5_auth_con_get_checksum_func:63,krb5_auth_con_getaddr:64,krb5_auth_con_getauthent:65,krb5_auth_con_getflag:66,krb5_auth_con_getkei:67,krb5_auth_con_getkey_k:68,krb5_auth_con_getlocalseqnumb:69,krb5_auth_con_getlocalsubkei:70,krb5_auth_con_getrcach:71,krb5_auth_con_getrecvsubkei:72,krb5_auth_con_getrecvsubkey_k:73,krb5_auth_con_getremoteseqnumb:74,krb5_auth_con_getremotesubkei:75,krb5_auth_con_getsendsubkei:76,krb5_auth_con_getsendsubkey_k:77,krb5_auth_con_init:78,krb5_auth_con_initivector:79,krb5_auth_con_set_checksum_func:80,krb5_auth_con_set_req_cksumtyp:81,krb5_auth_con_setaddr:82,krb5_auth_con_setflag:83,krb5_auth_con_setport:84,krb5_auth_con_setrcach:85,krb5_auth_con_setrecvsubkei:86,krb5_auth_con_setrecvsubkey_k:87,krb5_auth_con_setsendsubkei:88,krb5_auth_con_setsendsubkey_k:89,krb5_auth_con_setuseruserkei:90,krb5_auth_context:[61,66,83,810],krb5_auth_context_do_sequ:521,krb5_auth_context_do_tim:522,krb5_auth_context_generate_local_addr:523,krb5_auth_context_generate_local_full_addr:524,krb5_auth_context_generate_remote_addr:525,krb5_auth_context_generate_remote_full_addr:526,krb5_auth_context_permit_al:527,krb5_auth_context_ret_sequ:528,krb5_auth_context_ret_tim:529,krb5_auth_context_use_subkei:530,krb5_authdata:811,krb5_authdata_and_or:507,krb5_authdata_ap_opt:508,krb5_authdata_auth_ind:509,krb5_authdata_cammac:510,krb5_authdata_etype_negoti:511,krb5_authdata_fx_armor:512,krb5_authdata_if_relev:513,krb5_authdata_initial_verified_ca:514,krb5_authdata_kdc_issu:515,krb5_authdata_mandatory_for_kdc:516,krb5_authdata_osf_dc:517,krb5_authdata_sesam:518,krb5_authdata_signticket:519,krb5_authdata_win2k_pac:520,krb5_authdatatyp:812,krb5_authent:[174,201,813],krb5_boolean:814,krb5_build_princip:91,krb5_build_principal_alloc_va:92,krb5_build_principal_ext:93,krb5_build_principal_va:94,krb5_c_block_siz:95,krb5_c_checksum_length:96,krb5_c_crypto_length:97,krb5_c_crypto_length_iov:98,krb5_c_decrypt:99,krb5_c_decrypt_iov:100,krb5_c_derive_prfplu:101,krb5_c_encrypt:102,krb5_c_encrypt_iov:103,krb5_c_encrypt_length:104,krb5_c_enctype_compar:105,krb5_c_free_stat:106,krb5_c_fx_cf2_simpl:107,krb5_c_init_st:[106,108],krb5_c_is_coll_proof_cksum:109,krb5_c_is_keyed_cksum:110,krb5_c_keyed_checksum_typ:111,krb5_c_keylength:112,krb5_c_make_checksum:113,krb5_c_make_checksum_iov:114,krb5_c_make_random_kei:115,krb5_c_padding_length:116,krb5_c_prf:117,krb5_c_prf_length:118,krb5_c_prfplu:119,krb5_c_random_add_entropi:120,krb5_c_random_make_octet:121,krb5_c_random_os_entropi:122,krb5_c_random_se:123,krb5_c_random_to_kei:124,krb5_c_string_to_kei:125,krb5_c_string_to_key_with_param:126,krb5_c_valid_cksumtyp:127,krb5_c_valid_enctyp:128,krb5_c_verify_checksum:129,krb5_c_verify_checksum_iov:130,krb5_calculate_checksum:131,krb5_cc_cache_match:132,krb5_cc_close:133,krb5_cc_copy_cr:134,krb5_cc_cursor:815,krb5_cc_default:135,krb5_cc_default_nam:136,krb5_cc_destroi:137,krb5_cc_dup:138,krb5_cc_end_seq_get:139,krb5_cc_gen_new:140,krb5_cc_get_config:141,krb5_cc_get_flag:142,krb5_cc_get_full_nam:143,krb5_cc_get_nam:144,krb5_cc_get_princip:145,krb5_cc_get_typ:146,krb5_cc_initi:147,krb5_cc_move:148,krb5_cc_new_uniqu:149,krb5_cc_next_cr:150,krb5_cc_remove_cr:151,krb5_cc_resolv:152,krb5_cc_retrieve_cr:153,krb5_cc_select:154,krb5_cc_set_config:155,krb5_cc_set_default_nam:156,krb5_cc_set_flag:157,krb5_cc_start_seq_get:158,krb5_cc_store_cr:159,krb5_cc_support_switch:160,krb5_cc_switch:161,krb5_ccach:816,krb5_cccol_cursor:817,krb5_cccol_cursor_fre:162,krb5_cccol_cursor_new:163,krb5_cccol_cursor_next:164,krb5_cccol_have_cont:165,krb5_change_password:166,krb5_check_clockskew:167,krb5_checksum:[175,202,203,818],krb5_checksum_s:168,krb5_chpw_messag:169,krb5_cksumtyp:819,krb5_cksumtype_to_str:170,krb5_clear_error_messag:171,krb5_const:792,krb5_const_point:820,krb5_const_princip:821,krb5_context:[176,378,385,822],krb5_copy_address:172,krb5_copy_authdata:173,krb5_copy_authent:174,krb5_copy_checksum:175,krb5_copy_context:176,krb5_copy_cr:177,krb5_copy_data:178,krb5_copy_error_messag:179,krb5_copy_keyblock:180,krb5_copy_keyblock_cont:181,krb5_copy_princip:182,krb5_copy_ticket:183,krb5_cred:[177,206,207,321,405,531,823,826],krb5_cred_enc_part:824,krb5_cred_info:825,krb5_crypto_iov:827,krb5_crypto_type_checksum:532,krb5_crypto_type_data:533,krb5_crypto_type_empti:534,krb5_crypto_type_head:535,krb5_crypto_type_pad:536,krb5_crypto_type_sign_onli:537,krb5_crypto_type_stream:538,krb5_crypto_type_trail:539,krb5_cryptotyp:828,krb5_cybersafe_secureid:540,krb5_data:[178,208,209,829],krb5_decode_authdata_contain:184,krb5_decode_ticket:185,krb5_decrypt:186,krb5_deltat:830,krb5_deltat_to_str:187,krb5_domain_x500_compress:541,krb5_eblock_enctyp:188,krb5_enc_data:831,krb5_enc_kdc_rep_part:832,krb5_enc_tkt_part:833,krb5_encode_authdata_contain:189,krb5_encpadata_req_enc_pa_rep:542,krb5_encrypt:190,krb5_encrypt_block:834,krb5_encrypt_s:191,krb5_enctyp:835,krb5_enctype_to_nam:192,krb5_enctype_to_str:193,krb5_error:[543,836],krb5_error_cod:837,krb5_expand_hostnam:194,krb5_expire_callback_func:838,krb5_fast_requir:544,krb5_find_authdata:195,krb5_finish_kei:196,krb5_finish_random_kei:197,krb5_flag:839,krb5_free_address:198,krb5_free_ap_rep_enc_part:199,krb5_free_authdata:200,krb5_free_authent:201,krb5_free_checksum:202,krb5_free_checksum_cont:203,krb5_free_cksumtyp:204,krb5_free_context:205,krb5_free_cr:207,krb5_free_cred_cont:206,krb5_free_data:208,krb5_free_data_cont:209,krb5_free_default_realm:210,krb5_free_enctyp:211,krb5_free_error:212,krb5_free_error_messag:213,krb5_free_host_realm:214,krb5_free_keyblock:215,krb5_free_keyblock_cont:216,krb5_free_keytab_entry_cont:217,krb5_free_princip:218,krb5_free_str:219,krb5_free_tgt_cr:220,krb5_free_ticket:221,krb5_free_unparsed_nam:222,krb5_fwd_tgt_cred:223,krb5_gc_cach:545,krb5_gc_canonic:546,krb5_gc_constrained_deleg:547,krb5_gc_forward:548,krb5_gc_no_stor:549,krb5_gc_no_transit_check:550,krb5_gc_user_us:551,krb5_get_credenti:224,krb5_get_credentials_renew:225,krb5_get_credentials_valid:226,krb5_get_default_realm:[210,227],krb5_get_error_messag:[213,228],krb5_get_etype_info:229,krb5_get_fallback_host_realm:230,krb5_get_host_realm:[214,231],krb5_get_in_tkt_with_keytab:232,krb5_get_in_tkt_with_password:233,krb5_get_in_tkt_with_skei:234,krb5_get_init_creds_keytab:235,krb5_get_init_creds_opt:840,krb5_get_init_creds_opt_address_list:552,krb5_get_init_creds_opt_alloc:236,krb5_get_init_creds_opt_anonym:553,krb5_get_init_creds_opt_canonic:554,krb5_get_init_creds_opt_chg_pwd_prmpt:555,krb5_get_init_creds_opt_etype_list:556,krb5_get_init_creds_opt_forward:557,krb5_get_init_creds_opt_fre:237,krb5_get_init_creds_opt_get_fast_flag:238,krb5_get_init_creds_opt_init:239,krb5_get_init_creds_opt_preauth_list:558,krb5_get_init_creds_opt_proxi:559,krb5_get_init_creds_opt_renew_lif:560,krb5_get_init_creds_opt_salt:561,krb5_get_init_creds_opt_set_address_list:240,krb5_get_init_creds_opt_set_anonym:241,krb5_get_init_creds_opt_set_canonic:242,krb5_get_init_creds_opt_set_change_password_prompt:243,krb5_get_init_creds_opt_set_etype_list:244,krb5_get_init_creds_opt_set_expire_callback:245,krb5_get_init_creds_opt_set_fast_ccach:246,krb5_get_init_creds_opt_set_fast_ccache_nam:247,krb5_get_init_creds_opt_set_fast_flag:248,krb5_get_init_creds_opt_set_forward:249,krb5_get_init_creds_opt_set_in_ccach:250,krb5_get_init_creds_opt_set_out_ccach:251,krb5_get_init_creds_opt_set_pa:252,krb5_get_init_creds_opt_set_pac_request:253,krb5_get_init_creds_opt_set_preauth_list:254,krb5_get_init_creds_opt_set_proxi:255,krb5_get_init_creds_opt_set_renew_lif:256,krb5_get_init_creds_opt_set_respond:257,krb5_get_init_creds_opt_set_salt:258,krb5_get_init_creds_opt_set_tkt_lif:259,krb5_get_init_creds_opt_tkt_lif:562,krb5_get_init_creds_password:260,krb5_get_permitted_enctyp:261,krb5_get_profil:262,krb5_get_prompt_typ:263,krb5_get_renewed_cr:264,krb5_get_server_rcach:265,krb5_get_time_offset:266,krb5_get_validated_cr:267,krb5_gic_opt_pa_data:841,krb5_init_context:268,krb5_init_context_kdc:563,krb5_init_context_profil:269,krb5_init_context_secur:564,krb5_init_creds_context:842,krb5_init_creds_fre:270,krb5_init_creds_get:271,krb5_init_creds_get_cr:272,krb5_init_creds_get_error:273,krb5_init_creds_get_tim:274,krb5_init_creds_init:275,krb5_init_creds_set_keytab:276,krb5_init_creds_set_password:277,krb5_init_creds_set_servic:278,krb5_init_creds_step:279,krb5_init_creds_step_flag_continu:565,krb5_init_keyblock:280,krb5_init_random_kei:281,krb5_init_secure_context:282,krb5_int16:843,krb5_int16_max:566,krb5_int16_min:567,krb5_int32:844,krb5_int32_max:568,krb5_int32_min:569,krb5_is_config_princip:283,krb5_is_referral_realm:284,krb5_is_thread_saf:285,krb5_k_create_kei:286,krb5_k_decrypt:287,krb5_k_decrypt_iov:288,krb5_k_encrypt:289,krb5_k_encrypt_iov:290,krb5_k_free_kei:291,krb5_k_key_enctyp:292,krb5_k_key_keyblock:293,krb5_k_make_checksum:294,krb5_k_make_checksum_iov:295,krb5_k_prf:296,krb5_k_reference_kei:297,krb5_k_verify_checksum:298,krb5_k_verify_checksum_iov:299,krb5_kdc_rep:845,krb5_kdc_req:846,krb5_kdc_sign_ticket:300,krb5_kdc_verify_ticket:301,krb5_kei:[286,292,293,847],krb5_keyblock:[215,216,280,848],krb5_keytab:849,krb5_keytab_entri:850,krb5_keyusag:851,krb5_keyusage_ad_it:570,krb5_keyusage_ad_kdcissued_cksum:571,krb5_keyusage_ad_mt:572,krb5_keyusage_ad_signedpath:573,krb5_keyusage_ap_rep_encpart:576,krb5_keyusage_ap_req_auth:577,krb5_keyusage_ap_req_auth_cksum:578,krb5_keyusage_app_data_cksum:574,krb5_keyusage_app_data_encrypt:575,krb5_keyusage_as_rep_encpart:579,krb5_keyusage_as_req:580,krb5_keyusage_as_req_pa_enc_t:581,krb5_keyusage_cammac:582,krb5_keyusage_enc_challenge_cli:583,krb5_keyusage_enc_challenge_kdc:584,krb5_keyusage_fast_enc:585,krb5_keyusage_fast_finish:586,krb5_keyusage_fast_rep:587,krb5_keyusage_fast_req_chksum:588,krb5_keyusage_gss_tok_m:589,krb5_keyusage_gss_tok_wrap_integ:590,krb5_keyusage_gss_tok_wrap_priv:591,krb5_keyusage_iakerb_finish:592,krb5_keyusage_kdc_rep_ticket:593,krb5_keyusage_krb_cred_encpart:594,krb5_keyusage_krb_error_cksum:595,krb5_keyusage_krb_priv_encpart:596,krb5_keyusage_krb_safe_cksum:597,krb5_keyusage_pa_as_fresh:598,krb5_keyusage_pa_fx_cooki:599,krb5_keyusage_pa_otp_request:600,krb5_keyusage_pa_pkinit_kx:601,krb5_keyusage_pa_s4u_x509_user_repli:602,krb5_keyusage_pa_s4u_x509_user_request:603,krb5_keyusage_pa_sam_challenge_cksum:604,krb5_keyusage_pa_sam_challenge_trackid:605,krb5_keyusage_pa_sam_respons:606,krb5_keyusage_spak:607,krb5_keyusage_tgs_rep_encpart_sesskei:608,krb5_keyusage_tgs_rep_encpart_subkei:609,krb5_keyusage_tgs_req_ad_sesskei:610,krb5_keyusage_tgs_req_ad_subkei:611,krb5_keyusage_tgs_req_auth:612,krb5_keyusage_tgs_req_auth_cksum:613,krb5_kpasswd_accessdeni:614,krb5_kpasswd_autherror:615,krb5_kpasswd_bad_vers:616,krb5_kpasswd_harderror:617,krb5_kpasswd_initial_flag_need:618,krb5_kpasswd_malform:619,krb5_kpasswd_softerror:620,krb5_kpasswd_success:621,krb5_kt_add_entri:302,krb5_kt_client_default:303,krb5_kt_close:304,krb5_kt_cursor:852,krb5_kt_default:305,krb5_kt_default_nam:306,krb5_kt_dup:307,krb5_kt_end_seq_get:308,krb5_kt_free_entri:309,krb5_kt_get_entri:310,krb5_kt_get_nam:311,krb5_kt_get_typ:312,krb5_kt_have_cont:313,krb5_kt_next_entri:314,krb5_kt_read_service_kei:315,krb5_kt_remove_entri:316,krb5_kt_resolv:317,krb5_kt_start_seq_get:318,krb5_kuserok:319,krb5_kvno:853,krb5_last_req_entri:854,krb5_lrq_all_acct_exptim:622,krb5_lrq_all_last_initi:623,krb5_lrq_all_last_renew:624,krb5_lrq_all_last_req:625,krb5_lrq_all_last_tgt:626,krb5_lrq_all_last_tgt_issu:627,krb5_lrq_all_pw_exptim:628,krb5_lrq_none:629,krb5_lrq_one_acct_exptim:630,krb5_lrq_one_last_initi:631,krb5_lrq_one_last_renew:632,krb5_lrq_one_last_req:633,krb5_lrq_one_last_tgt:634,krb5_lrq_one_last_tgt_issu:635,krb5_lrq_one_pw_exptim:636,krb5_magic:855,krb5_make_authdata_kdc_issu:320,krb5_marshal_credenti:321,krb5_merge_authdata:322,krb5_mk_1cred:323,krb5_mk_error:324,krb5_mk_ncred:325,krb5_mk_priv:326,krb5_mk_rep:327,krb5_mk_rep_dc:328,krb5_mk_req:329,krb5_mk_req_checksum_func:856,krb5_mk_req_extend:330,krb5_mk_safe:331,krb5_msgtype:857,krb5_nt_ent_principal_and_id:638,krb5_nt_enterprise_princip:637,krb5_nt_ms_princip:639,krb5_nt_ms_principal_and_id:640,krb5_nt_princip:641,krb5_nt_smtp_name:642,krb5_nt_srv_hst:643,krb5_nt_srv_inst:644,krb5_nt_srv_xhst:645,krb5_nt_uid:646,krb5_nt_unknown:647,krb5_nt_wellknown:648,krb5_nt_x500_princip:649,krb5_octet:858,krb5_os_localaddr:332,krb5_pa_data:859,krb5_pa_pac_req:860,krb5_pa_server_referral_data:861,krb5_pa_svr_referral_data:862,krb5_pac:863,krb5_pac_add_buff:333,krb5_pac_attributes_info:650,krb5_pac_client_claim:651,krb5_pac_client_info:652,krb5_pac_credentials_info:653,krb5_pac_delegation_info:654,krb5_pac_device_claim:655,krb5_pac_device_info:656,krb5_pac_fre:334,krb5_pac_full_checksum:657,krb5_pac_get_buff:335,krb5_pac_get_client_info:336,krb5_pac_get_typ:337,krb5_pac_init:338,krb5_pac_logon_info:658,krb5_pac_pars:339,krb5_pac_privsvr_checksum:659,krb5_pac_requestor:660,krb5_pac_server_checksum:661,krb5_pac_sign:340,krb5_pac_sign_ext:341,krb5_pac_ticket_checksum:662,krb5_pac_upn_dns_info:663,krb5_pac_verifi:342,krb5_pac_verify_ext:343,krb5_padata_afs3_salt:664,krb5_padata_ap_req:665,krb5_padata_as_checksum:666,krb5_padata_as_fresh:667,krb5_padata_enc_sandia_securid:669,krb5_padata_enc_timestamp:670,krb5_padata_enc_unix_tim:671,krb5_padata_encrypted_challeng:668,krb5_padata_etype_info2:673,krb5_padata_etype_info:672,krb5_padata_for_us:674,krb5_padata_fx_cooki:675,krb5_padata_fx_error:676,krb5_padata_fx_fast:677,krb5_padata_get_from_typed_data:678,krb5_padata_non:679,krb5_padata_osf_dc:680,krb5_padata_otp_challeng:681,krb5_padata_otp_pin_chang:682,krb5_padata_otp_request:683,krb5_padata_pac_opt:684,krb5_padata_pac_request:685,krb5_padata_pk_as_rep:687,krb5_padata_pk_as_rep_old:688,krb5_padata_pk_as_req:689,krb5_padata_pk_as_req_old:690,krb5_padata_pkinit_kx:686,krb5_padata_pw_salt:691,krb5_padata_redhat_idp_oauth2:692,krb5_padata_redhat_passkei:693,krb5_padata_referr:694,krb5_padata_s4u_x509_us:695,krb5_padata_sam_challeng:696,krb5_padata_sam_challenge_2:697,krb5_padata_sam_redirect:698,krb5_padata_sam_respons:699,krb5_padata_sam_response_2:700,krb5_padata_sesam:701,krb5_padata_spak:702,krb5_padata_svr_referral_info:703,krb5_padata_tgs_req:704,krb5_padata_use_specified_kvno:705,krb5_parse_nam:344,krb5_parse_name_flag:345,krb5_pointer:864,krb5_post_recv_fn:865,krb5_pre_send_fn:866,krb5_preauthtyp:867,krb5_prepend_error_messag:346,krb5_princ_compon:793,krb5_princ_nam:794,krb5_princ_realm:795,krb5_princ_set_realm:796,krb5_princ_set_realm_data:797,krb5_princ_set_realm_length:798,krb5_princ_siz:799,krb5_princ_typ:800,krb5_princip:[344,345,406,407,408,409,868],krb5_principal2salt:347,krb5_principal_compar:348,krb5_principal_compare_any_realm:349,krb5_principal_compare_casefold:706,krb5_principal_compare_enterpris:707,krb5_principal_compare_flag:350,krb5_principal_compare_ignore_realm:708,krb5_principal_compare_utf8:709,krb5_principal_data:869,krb5_principal_parse_enterpris:710,krb5_principal_parse_ignore_realm:711,krb5_principal_parse_no_def_realm:712,krb5_principal_parse_no_realm:713,krb5_principal_parse_require_realm:714,krb5_principal_unparse_displai:715,krb5_principal_unparse_no_realm:716,krb5_principal_unparse_short:717,krb5_priv:718,krb5_process_kei:351,krb5_prompt:870,krb5_prompt_typ:871,krb5_prompt_type_new_password:719,krb5_prompt_type_new_password_again:720,krb5_prompt_type_password:721,krb5_prompt_type_preauth:722,krb5_prompter_fct:872,krb5_prompter_posix:352,krb5_pvno:723,krb5_pwd_data:873,krb5_random_kei:353,krb5_rcach:874,krb5_rd_cred:354,krb5_rd_error:355,krb5_rd_priv:356,krb5_rd_rep:357,krb5_rd_rep_dc:358,krb5_rd_req:359,krb5_rd_safe:360,krb5_read_error:212,krb5_read_password:361,krb5_realm_branch_char:724,krb5_realm_compar:362,krb5_recvauth:363,krb5_recvauth_badauthv:725,krb5_recvauth_skip_vers:726,krb5_recvauth_vers:364,krb5_referral_realm:[284,727],krb5_replay_data:875,krb5_responder_context:876,krb5_responder_fn:877,krb5_responder_get_challeng:365,krb5_responder_list_quest:366,krb5_responder_otp_challeng:878,krb5_responder_otp_challenge_fre:367,krb5_responder_otp_flags_collect_pin:728,krb5_responder_otp_flags_collect_token:729,krb5_responder_otp_flags_nextotp:730,krb5_responder_otp_flags_separate_pin:731,krb5_responder_otp_format_alphanumer:732,krb5_responder_otp_format_decim:733,krb5_responder_otp_format_hexadecim:734,krb5_responder_otp_get_challeng:[367,368],krb5_responder_otp_set_answ:369,krb5_responder_otp_tokeninfo:879,krb5_responder_pkinit_challeng:880,krb5_responder_pkinit_challenge_fre:370,krb5_responder_pkinit_flags_token_user_pin_count_low:735,krb5_responder_pkinit_flags_token_user_pin_final_tri:736,krb5_responder_pkinit_flags_token_user_pin_lock:737,krb5_responder_pkinit_get_challeng:[370,371],krb5_responder_pkinit_ident:881,krb5_responder_pkinit_set_answ:372,krb5_responder_question_otp:[368,369,738],krb5_responder_question_password:739,krb5_responder_question_pkinit:[371,372,740],krb5_responder_set_answ:373,krb5_respons:882,krb5_roundup:801,krb5_safe:741,krb5_salttype_to_str:374,krb5_sam_must_pk_encrypt_sad:742,krb5_sam_send_encrypted_sad:743,krb5_sam_use_sad_as_kei:744,krb5_sendauth:[212,375],krb5_server_decrypt_ticket_keytab:376,krb5_set_default_realm:377,krb5_set_default_tgs_enctyp:378,krb5_set_error_messag:379,krb5_set_kdc_recv_hook:380,krb5_set_kdc_send_hook:381,krb5_set_password:382,krb5_set_password_using_ccach:383,krb5_set_principal_realm:384,krb5_set_real_tim:385,krb5_set_trace_callback:386,krb5_set_trace_filenam:387,krb5_sname_match:388,krb5_sname_to_princip:389,krb5_string_to_cksumtyp:390,krb5_string_to_deltat:391,krb5_string_to_enctyp:392,krb5_string_to_kei:393,krb5_string_to_salttyp:394,krb5_string_to_timestamp:395,krb5_tc_match_2nd_tkt:745,krb5_tc_match_authdata:746,krb5_tc_match_flag:747,krb5_tc_match_flags_exact:748,krb5_tc_match_is_skei:749,krb5_tc_match_ktyp:750,krb5_tc_match_srv_nameonli:751,krb5_tc_match_tim:752,krb5_tc_match_times_exact:753,krb5_tc_noticket:754,krb5_tc_openclos:755,krb5_tc_supported_ktyp:756,krb5_tgs_name:757,krb5_tgs_name_s:758,krb5_tgs_rep:759,krb5_tgs_req:760,krb5_ticket:[183,883],krb5_ticket_tim:884,krb5_timeofdai:396,krb5_timestamp:[885,896],krb5_timestamp_to_sfstr:397,krb5_timestamp_to_str:398,krb5_tkt_authent:886,krb5_tkt_creds_context:887,krb5_tkt_creds_fre:399,krb5_tkt_creds_get:400,krb5_tkt_creds_get_cr:401,krb5_tkt_creds_get_tim:402,krb5_tkt_creds_init:403,krb5_tkt_creds_step:404,krb5_tkt_creds_step_flag_continu:761,krb5_trace_callback:888,krb5_trace_info:889,krb5_transit:890,krb5_typed_data:891,krb5_ui_2:892,krb5_ui_4:893,krb5_unmarshal_credenti:405,krb5_unparse_nam:406,krb5_unparse_name_ext:407,krb5_unparse_name_flag:408,krb5_unparse_name_flags_ext:409,krb5_us_timeofdai:410,krb5_use_enctyp:411,krb5_verify_authdata_kdc_issu:412,krb5_verify_checksum:413,krb5_verify_init_cr:414,krb5_verify_init_creds_opt:894,krb5_verify_init_creds_opt_ap_req_nofail:762,krb5_verify_init_creds_opt_init:415,krb5_verify_init_creds_opt_set_ap_req_nofail:416,krb5_vprepend_error_messag:417,krb5_vset_error_messag:418,krb5_vwrap_error_messag:419,krb5_wellknown_namestr:763,krb5_wrap_error_messag:420,krb5_x:802,krb5_xc:803,krb5kdc:10,krb:[107,223,323,325,326,331,354,355,356,360],krb_ap_rep:[327,328,357,358],krb_ap_req:[329,330,359],krb_error:324,krbtgt:[14,23],ksu:946,kswitch:947,ktadd:3,ktremov:3,ktutil:11,kvno:948,last:273,ldap:[23,24],ldapsearch:38,legaci:[14,48],length:[93,96,97,98,104,112,118,407],lib:903,libdefault:21,librari:[205,268,269,282,285],licens:919,lifetim:[256,259],lightn:24,like:917,line:[5,6],link:42,list:[5,11,20,41,54,92,111,173,261,322,366,918,936],list_mkei:6,list_polici:[3,5],list_princip:3,list_request:[3,11],lndir:904,load:[6,23],local:[56,69,82,84,319,932],localauth:[21,932],locat:[28,247,933],lock:3,lockout:35,log:[20,41,319,923],login:28,lr_type_interpretation_mask:764,lr_type_this_server_onli:765,machin:33,macro:789,mail:936,make:161,man:908,manag:[938,939],manipul:47,map:[24,39],master:[14,23],match:[284,388],max_keytab_name_len:766,mechan:[28,924],member:[805,807,808,809,811,813,818,821,823,824,825,826,827,829,831,832,833,834,836,840,841,845,846,848,850,854,859,860,861,862,868,869,870,873,875,878,879,880,881,882,883,884,886,889,890,891,894,895],memori:[24,214],merg:322,messag:[12,43,97,169,171,179,213,223,228,323,324,325,326,327,328,329,330,331,346,354,355,356,357,358,359,360,379,417,418,419,420],mic:43,migrat:26,mismatch:38,mit:[0,23,44,916,917,918,919],modifi:5,modify_polici:[3,5],modify_princip:3,modul:[19,24,28,923,924,926],most:[179,906],move:148,ms:410,msec_dirbit:767,msec_val_mask:768,multithread:285,name:[38,39,43,56,91,92,93,135,136,143,144,149,152,156,192,194,231,306,311,344,345,347,366,373,387,389,897,901,906],negoex:924,next:[150,164,279,314,404],note:941,number:[69,74,116],object:[178,265,321,405],obtain:[400,905,939],octet:116,offset:[266,385,396],older:26,one:[179,372],onli:282,onto:39,opaqu:[287,288,289,290,294,295,296,298,299],open:265,openldap:[22,38],oper:[23,99,100,102,103,113,114,129,130,287,288,289,290,294,295,296,298,299],optimist:258,option:[3,4,5,6,7,8,9,10,20,21,46,157,236,237,238,240,241,242,243,244,245,246,247,248,249,250,251,252,254,255,256,257,258,259,397,415,906,941,942,943,944,945,946,947,948],order:53,organ:903,os:[266,908],osconf:907,other:36,otp:[20,36],output:[118,251,397],over:163,overrid:[38,55,377],overview:23,pac:[253,300,301,333,334,335,336,337,338,339,342,343],packag:[906,908],pad:[98,116,397],page:[908,936],paramet:[21,126,364],pars:[47,357,358,359],passwd_phrase_el:895,password:[46,125,126,166,169,243,260,277,352,361,382,383,935,938],path:917,pepper:107,perform:35,permit:261,pin:46,pkinit:[20,21,37,46,912,921],place:[100,103,288,290],pluggabl:927,plugin:[21,28,923,926],polici:[23,930],port:[39,84],possibl:[194,228,300,301,343],post:380,pre:381,preauthent:[36,40,252,254,258,922,931],precomput:92,prefix:[346,417,419,420],prepar:[158,163],prerequisit:905,previous:106,prf:[101,119],primari:[34,161],princip:[15,23,34,35,38,47,49,50,56,57,91,92,93,132,145,154,182,218,222,278,283,319,344,345,347,348,349,350,362,382,383,384,388,389,910],priv:[326,356],privileg:[23,338],procedur:14,process:[139,356,360],profil:[28,55,262,269,934],program:[1,906],prompt:[243,263,352],prompter:46,proof:109,propag:[23,34,39,917],properti:939,protocol:[363,364,375,913],provis:38,proxi:29,proxiabl:255,pseudo:[117,118,119,121,296],purge_mkei:6,purgekei:3,pwqual:[21,935],qualiti:[935,938],question:[46,365,366,369,372,373],quick:918,quit:[3,11],random:[115,117,118,119,121,124,296],rare:48,read:[158,336,354,361],read_kt:11,realm:[20,21,23,28,39,58,210,227,231,343,349,362,377,384,925],receiv:[72,73,86,87,380],recent:179,refer:[31,291,297,421,908],refus:41,reject:41,rel:187,releas:[308,908],remot:[74,82,84],remov:[14,15,151,316],rename_princip:3,renew:[256,264],replai:[71,85,265,901,915],replic:35,replica:[34,39,917],represent:[222,406],request:[26,279,399,400,401,402,404],requir:[416,946],resolv:[135,152,303,305],resourc:936,respond:[46,257,365,366,373],restrict:[240,953],result:169,retir:14,retriev:[59,60,64,65,66,67,68,69,71,72,73,74,76,77,142,143,144,146,150,153,227,229,238,262,272,274,292,293,314,315,318,335,365,396,401,402,410],revers:38,rfc:[101,119],risk:25,rout:41,rpc:[328,358],s2kparam:229,s4u:43,s:[55,403,419,420],safe:[331,360],salt:[229,258,347,374,394],salt_type_afs_length:769,salt_type_no_length:770,sampl:[20,21],sclient:949,search:54,sec:410,section:[20,21,59,60],secur:[17,32,38,911,946],see:[2,3,4,5,6,7,8,9,10,11,12,19,20,21,941,942,943,944,945,946,947,948,949,951,952,953],seen:41,select:[26,154,920],send:[76,77,88,89,381],sendauth:[41,363,364,375],separ:904,sequenc:[69,74],sequenti:[139,158,318],seri:139,serial:321,server:[14,15,32,41,154,265,363,364,933],servic:[14,26,38,39,194,278,315,389,403],session:[26,67,68,90,261],set:[55,80,81,82,83,84,85,86,87,88,89,90,156,157,169,240,241,242,243,244,245,246,247,248,249,250,251,254,255,256,257,258,259,277,323,378,379,380,381,382,383,384,385,416,418],set_str:3,setup:35,shell:[38,946],should:48,side:946,sign:[300,320],signatur:[300,301],simpl:[789,908],sinc:410,singl:[323,904],site:908,size:95,skew:[15,167],socket:62,softwar:905,some:[32,101],sourc:[903,908],spake:[40,911],specif:[38,97,115,117,124,296,396],specifi:[21,53,54,112,127,128,132,149,153,269,276,278,343,376,377,382,386,387],sserver:12,ssh:38,start:[34,318],stash:[6,902],stashsrvpw:5,state:[35,79,106,108],storag:[200,218],store:[43,155,159,198],string:[60,91,93,107,125,126,170,187,193,210,219,222,344,345,374,390,391,392,394,395,397,398,406,407,408,409],strong:14,struct:[368,371],structur:[20,21,61,66,83,142,174,175,176,177,183,199,201,202,203,206,207,208,209,215,216,220,236,292,293,344,378,385,406,407,408,409,415,804],subkei:[72,73,76,77,86,87,88,89],sun:23,suppli:[252,330],support:[14,41,100,103,160,285,288,290,898],synchron:400,synopsi:[2,3,4,5,6,7,8,9,10,11,12,941,942,943,944,945,946,947,948,949],syntax:19,system:[410,906,917],tabdump:6,tabl:[217,235,302,303,304,305,306,310,311,312,314,315,316,317,318,376],tarbal:908,target:946,termin:91,test:[35,109,110,283,285,388,904],tg:[378,399,400,401,402,404],tgt:223,thi:[332,898,908],threeparamopen:771,ticket:[23,185,221,224,253,256,259,274,300,301,376,402,403,939],time:[46,167,187,266,274,385,391,396,402,410,898],timestamp:[167,395,397,398],tkt_flg_anonym:772,tkt_flg_enc_pa_rep:773,tkt_flg_forward:[774,775],tkt_flg_hw_auth:776,tkt_flg_initi:777,tkt_flg_invalid:778,tkt_flg_may_postd:779,tkt_flg_ok_as_deleg:780,tkt_flg_postdat:781,tkt_flg_pre_auth:782,tkt_flg_proxi:784,tkt_flg_proxiabl:783,tkt_flg_renew:785,tkt_flg_transit_policy_check:786,token:[36,37,43,912],tool:897,topic:13,trace:[41,386,387],trailer:98,tree:904,trivial:911,troubleshoot:[41,42],tune:906,tutori:42,two:[52,105,107,322,348,349,350,362],type:[14,20,24,26,36,41,43,81,96,97,105,109,110,111,118,127,128,144,146,149,160,170,192,193,204,211,244,254,261,263,312,337,374,378,390,392,394,804,897,901,906],uniqu:149,unix:[32,33,917],unlock:3,unpars:339,unset:[241,242,243,249,255],unwrap:[184,412],up:[17,904],updat:[23,908],update_princ_encrypt:6,upgrad:14,us:[15,48,79,91,92,93,99,101,102,119,154,194,235,260,264,265,269,271,276,282,287,289,330,376,382,383,400,417,418,419,896,897,898,904,906],usabl:111,usag:14,use_mkei:6,user:[46,319,352,937,940,950],util:903,v4:[49,50,51],v5:[15,49,50,51,899,905],va_list:[417,418,419],valid:[127,128,130,267,299,354],valid_int_bit:787,valid_uint_bit:788,valu:[59,60,141,155,187,335,367,370,391],variabl:[26,27,92,906,953],variou:42,verif:[41,415,416,938],verifi:[46,127,128,129,298,301,342,343,412,414],version:[364,911],via:101,view:[5,939],view_polici:5,wa:285,web:[908,936],whether:[109,110,160,283,285,388,416],whitepap:42,wiki:936,within:[167,904],without:908,work:15,wrap:[43,189],write_kt:11,year:896,your:[15,938],zero:[209,291]}}) \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/index.html b/krb5-1.21.3/doc/html/user/index.html new file mode 100644 index 00000000..5a053fde --- /dev/null +++ b/krb5-1.21.3/doc/html/user/index.html @@ -0,0 +1,167 @@ + + + + + + + + + For users — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/pwd_mgmt.html b/krb5-1.21.3/doc/html/user/pwd_mgmt.html new file mode 100644 index 00000000..ccb2a404 --- /dev/null +++ b/krb5-1.21.3/doc/html/user/pwd_mgmt.html @@ -0,0 +1,229 @@ + + + + + + + + + Password management — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Password management

+

Your password is the only way Kerberos has of verifying your identity. +If someone finds out your password, that person can masquerade as +you—send email that comes from you, read, edit, or delete your files, +or log into other hosts as you—and no one will be able to tell the +difference. For this reason, it is important that you choose a good +password, and keep it secret. If you need to give access to your +account to someone else, you can do so through Kerberos (see +Granting access to your account). You should never tell your password to anyone, +including your system administrator, for any reason. You should +change your password frequently, particularly any time you think +someone may have found out what it is.

+
+

Changing your password

+

To change your Kerberos password, use the kpasswd command. +It will ask you for your old password (to prevent someone else from +walking up to your computer when you’re not there and changing your +password), and then prompt you for the new one twice. (The reason you +have to type it twice is to make sure you have typed it correctly.) +For example, user david would do the following:

+
shell% kpasswd
+Password for david:    <- Type your old password.
+Enter new password:    <- Type your new password.
+Enter it again:  <- Type the new password again.
+Password changed.
+shell%
+
+
+

If david typed the incorrect old password, he would get the +following message:

+
shell% kpasswd
+Password for david:  <- Type the incorrect old password.
+kpasswd: Password incorrect while getting initial ticket
+shell%
+
+
+

If you make a mistake and don’t type the new password the same way +twice, kpasswd will ask you to try again:

+
shell% kpasswd
+Password for david:  <- Type the old password.
+Enter new password:  <- Type the new password.
+Enter it again: <- Type a different new password.
+kpasswd: Password mismatch while reading password
+shell%
+
+
+

Once you change your password, it takes some time for the change to +propagate through the system. Depending on how your system is set up, +this might be anywhere from a few minutes to an hour or more. If you +need to get new Kerberos tickets shortly after changing your password, +try the new password. If the new password doesn’t work, try again +using the old one.

+
+
+

Granting access to your account

+

If you need to give someone access to log into your account, you can +do so through Kerberos, without telling the person your password. +Simply create a file called .k5login in your home directory. +This file should contain the Kerberos principal of each person to whom +you wish to give access. Each principal must be on a separate line. +Here is a sample .k5login file:

+
jennifer@ATHENA.MIT.EDU
+david@EXAMPLE.COM
+
+
+

This file would allow the users jennifer and david to use your +user ID, provided that they had Kerberos tickets in their respective +realms. If you will be logging into other hosts across a network, you +will want to include your own Kerberos principal in your .k5login file +on each of these hosts.

+

Using a .k5login file is much safer than giving out your password, +because:

+
    +
  • You can take access away any time simply by removing the principal +from your .k5login file.

  • +
  • Although the user has full access to your account on one particular +host (or set of hosts if your .k5login file is shared, e.g., over +NFS), that user does not inherit your network privileges.

  • +
  • Kerberos keeps a log of who obtains tickets, so a system +administrator could find out, if necessary, who was capable of using +your user ID at a particular time.

  • +
+

One common application is to have a .k5login file in root’s home +directory, giving root access to that machine to the Kerberos +principals listed. This allows system administrators to allow users +to become root locally, or to log in remotely as root, without their +having to give out the root password, and without anyone having to +type the root password over the network.

+
+
+

Password quality verification

+

TODO

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/tkt_mgmt.html b/krb5-1.21.3/doc/html/user/tkt_mgmt.html new file mode 100644 index 00000000..18939ed7 --- /dev/null +++ b/krb5-1.21.3/doc/html/user/tkt_mgmt.html @@ -0,0 +1,449 @@ + + + + + + + + + Ticket management — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

Ticket management

+

On many systems, Kerberos is built into the login program, and you get +tickets automatically when you log in. Other programs, such as ssh, +can forward copies of your tickets to a remote host. Most of these +programs also automatically destroy your tickets when they exit. +However, MIT recommends that you explicitly destroy your Kerberos +tickets when you are through with them, just to be sure. One way to +help ensure that this happens is to add the kdestroy command +to your .logout file. Additionally, if you are going to be away from +your machine and are concerned about an intruder using your +permissions, it is safest to either destroy all copies of your +tickets, or use a screensaver that locks the screen.

+
+

Kerberos ticket properties

+

There are various properties that Kerberos tickets can have:

+

If a ticket is forwardable, then the KDC can issue a new ticket +(with a different network address, if necessary) based on the +forwardable ticket. This allows for authentication forwarding without +requiring a password to be typed in again. For example, if a user +with a forwardable TGT logs into a remote system, the KDC could issue +a new TGT for that user with the network address of the remote system, +allowing authentication on that host to work as though the user were +logged in locally.

+

When the KDC creates a new ticket based on a forwardable ticket, it +sets the forwarded flag on that new ticket. Any tickets that are +created based on a ticket with the forwarded flag set will also have +their forwarded flags set.

+

A proxiable ticket is similar to a forwardable ticket in that it +allows a service to take on the identity of the client. Unlike a +forwardable ticket, however, a proxiable ticket is only issued for +specific services. In other words, a ticket-granting ticket cannot be +issued based on a ticket that is proxiable but not forwardable.

+

A proxy ticket is one that was issued based on a proxiable ticket.

+

A postdated ticket is issued with the invalid flag set. After the +starting time listed on the ticket, it can be presented to the KDC to +obtain valid tickets.

+

Ticket-granting tickets with the postdateable flag set can be used +to obtain postdated service tickets.

+

Renewable tickets can be used to obtain new session keys without +the user entering their password again. A renewable ticket has two +expiration times. The first is the time at which this particular +ticket expires. The second is the latest possible expiration time for +any ticket issued based on this renewable ticket.

+

A ticket with the initial flag set was issued based on the +authentication protocol, and not on a ticket-granting ticket. +Application servers that wish to ensure that the user’s key has been +recently presented for verification could specify that this flag must +be set to accept the ticket.

+

An invalid ticket must be rejected by application servers. +Postdated tickets are usually issued with this flag set, and must be +validated by the KDC before they can be used.

+

A preauthenticated ticket is one that was only issued after the +client requesting the ticket had authenticated itself to the KDC.

+

The hardware authentication flag is set on a ticket which required +the use of hardware for authentication. The hardware is expected to +be possessed only by the client which requested the tickets.

+

If a ticket has the transit policy checked flag set, then the KDC +that issued this ticket implements the transited-realm check policy +and checked the transited-realms list on the ticket. The +transited-realms list contains a list of all intermediate realms +between the realm of the KDC that issued the first ticket and that of +the one that issued the current ticket. If this flag is not set, then +the application server must check the transited realms itself or else +reject the ticket.

+

The okay as delegate flag indicates that the server specified in +the ticket is suitable as a delegate as determined by the policy of +that realm. Some client applications may use this flag to decide +whether to forward tickets to a remote host, although many +applications do not honor it.

+

An anonymous ticket is one in which the named principal is a +generic principal for that realm; it does not actually specify the +individual that will be using the ticket. This ticket is meant only +to securely distribute a session key.

+
+
+

Obtaining tickets with kinit

+

If your site has integrated Kerberos V5 with the login system, you +will get Kerberos tickets automatically when you log in. Otherwise, +you may need to explicitly obtain your Kerberos tickets, using the +kinit program. Similarly, if your Kerberos tickets expire, +use the kinit program to obtain new ones.

+

To use the kinit program, simply type kinit and then type your +password at the prompt. For example, Jennifer (whose username is +jennifer) works for Bleep, Inc. (a fictitious company with the +domain name mit.edu and the Kerberos realm ATHENA.MIT.EDU). She would +type:

+
shell% kinit
+Password for jennifer@ATHENA.MIT.EDU: <-- [Type jennifer's password here.]
+shell%
+
+
+

If you type your password incorrectly, kinit will give you the +following error message:

+
shell% kinit
+Password for jennifer@ATHENA.MIT.EDU: <-- [Type the wrong password here.]
+kinit: Password incorrect
+shell%
+
+
+

and you won’t get Kerberos tickets.

+

By default, kinit assumes you want tickets for your own username in +your default realm. Suppose Jennifer’s friend David is visiting, and +he wants to borrow a window to check his mail. David needs to get +tickets for himself in his own realm, EXAMPLE.COM. He would type:

+
shell% kinit david@EXAMPLE.COM
+Password for david@EXAMPLE.COM: <-- [Type david's password here.]
+shell%
+
+
+

David would then have tickets which he could use to log onto his own +machine. Note that he typed his password locally on Jennifer’s +machine, but it never went over the network. Kerberos on the local +host performed the authentication to the KDC in the other realm.

+

If you want to be able to forward your tickets to another host, you +need to request forwardable tickets. You do this by specifying the +-f option:

+
shell% kinit -f
+Password for jennifer@ATHENA.MIT.EDU: <-- [Type your password here.]
+shell%
+
+
+

Note that kinit does not tell you that it obtained forwardable +tickets; you can verify this using the klist command (see +Viewing tickets with klist).

+

Normally, your tickets are good for your system’s default ticket +lifetime, which is ten hours on many systems. You can specify a +different ticket lifetime with the -l option. Add the letter +s to the value for seconds, m for minutes, h for hours, or +d for days. For example, to obtain forwardable tickets for +david@EXAMPLE.COM that would be good for three hours, you would +type:

+
shell% kinit -f -l 3h david@EXAMPLE.COM
+Password for david@EXAMPLE.COM: <-- [Type david's password here.]
+shell%
+
+
+
+

Note

+

You cannot mix units; specifying a lifetime of 3h30m would +result in an error. Note also that most systems specify a +maximum ticket lifetime. If you request a longer ticket +lifetime, it will be automatically truncated to the maximum +lifetime.

+
+
+
+

Viewing tickets with klist

+

The klist command shows your tickets. When you first obtain +tickets, you will have only the ticket-granting ticket. The listing +would look like this:

+
shell% klist
+Ticket cache: /tmp/krb5cc_ttypa
+Default principal: jennifer@ATHENA.MIT.EDU
+
+Valid starting     Expires            Service principal
+06/07/04 19:49:21  06/08/04 05:49:19  krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU
+shell%
+
+
+

The ticket cache is the location of your ticket file. In the above +example, this file is named /tmp/krb5cc_ttypa. The default +principal is your Kerberos principal.

+

The “valid starting” and “expires” fields describe the period of time +during which the ticket is valid. The “service principal” describes +each ticket. The ticket-granting ticket has a first component +krbtgt, and a second component which is the realm name.

+

Now, if jennifer connected to the machine daffodil.mit.edu, +and then typed “klist” again, she would have gotten the following +result:

+
shell% klist
+Ticket cache: /tmp/krb5cc_ttypa
+Default principal: jennifer@ATHENA.MIT.EDU
+
+Valid starting     Expires            Service principal
+06/07/04 19:49:21  06/08/04 05:49:19  krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU
+06/07/04 20:22:30  06/08/04 05:49:19  host/daffodil.mit.edu@ATHENA.MIT.EDU
+shell%
+
+
+

Here’s what happened: when jennifer used ssh to connect to the +host daffodil.mit.edu, the ssh program presented her +ticket-granting ticket to the KDC and requested a host ticket for the +host daffodil.mit.edu. The KDC sent the host ticket, which ssh +then presented to the host daffodil.mit.edu, and she was allowed +to log in without typing her password.

+

Suppose your Kerberos tickets allow you to log into a host in another +domain, such as trillium.example.com, which is also in another +Kerberos realm, EXAMPLE.COM. If you ssh to this host, you will +receive a ticket-granting ticket for the realm EXAMPLE.COM, plus +the new host ticket for trillium.example.com. klist will now +show:

+
shell% klist
+Ticket cache: /tmp/krb5cc_ttypa
+Default principal: jennifer@ATHENA.MIT.EDU
+
+Valid starting     Expires            Service principal
+06/07/04 19:49:21  06/08/04 05:49:19  krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU
+06/07/04 20:22:30  06/08/04 05:49:19  host/daffodil.mit.edu@ATHENA.MIT.EDU
+06/07/04 20:24:18  06/08/04 05:49:19  krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU
+06/07/04 20:24:18  06/08/04 05:49:19  host/trillium.example.com@EXAMPLE.COM
+shell%
+
+
+

Depending on your host’s and realm’s configuration, you may also see a +ticket with the service principal host/trillium.example.com@. If +so, this means that your host did not know what realm +trillium.example.com is in, so it asked the ATHENA.MIT.EDU KDC for +a referral. The next time you connect to trillium.example.com, +the odd-looking entry will be used to avoid needing to ask for a +referral again.

+

You can use the -f option to view the flags that apply to your +tickets. The flags are:

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

F

Forwardable

f

forwarded

P

Proxiable

p

proxy

D

postDateable

d

postdated

R

Renewable

I

Initial

i

invalid

H

Hardware authenticated

A

preAuthenticated

T

Transit policy checked

O

Okay as delegate

a

anonymous

+

Here is a sample listing. In this example, the user jennifer +obtained her initial tickets (I), which are forwardable (F) +and postdated (d) but not yet validated (i):

+
shell% klist -f
+Ticket cache: /tmp/krb5cc_320
+Default principal: jennifer@ATHENA.MIT.EDU
+
+Valid starting      Expires             Service principal
+31/07/05 19:06:25  31/07/05 19:16:25  krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU
+        Flags: FdiI
+shell%
+
+
+

In the following example, the user david’s tickets were forwarded +(f) to this host from another host. The tickets are reforwardable +(F):

+
shell% klist -f
+Ticket cache: /tmp/krb5cc_p11795
+Default principal: david@EXAMPLE.COM
+
+Valid starting     Expires            Service principal
+07/31/05 11:52:29  07/31/05 21:11:23  krbtgt/EXAMPLE.COM@EXAMPLE.COM
+        Flags: Ff
+07/31/05 12:03:48  07/31/05 21:11:23  host/trillium.example.com@EXAMPLE.COM
+        Flags: Ff
+shell%
+
+
+
+
+

Destroying tickets with kdestroy

+

Your Kerberos tickets are proof that you are indeed yourself, and +tickets could be stolen if someone gains access to a computer where +they are stored. If this happens, the person who has them can +masquerade as you until they expire. For this reason, you should +destroy your Kerberos tickets when you are away from your computer.

+

Destroying your tickets is easy. Simply type kdestroy:

+
shell% kdestroy
+shell%
+
+
+

If kdestroy fails to destroy your tickets, it will beep and +give an error message. For example, if kdestroy can’t find any +tickets to destroy, it will give the following message:

+
shell% kdestroy
+kdestroy: No credentials cache file found while destroying cache
+shell%
+
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_commands/index.html b/krb5-1.21.3/doc/html/user/user_commands/index.html new file mode 100644 index 00000000..0448a826 --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_commands/index.html @@ -0,0 +1,156 @@ + + + + + + + + + User commands — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ + + + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_commands/kdestroy.html b/krb5-1.21.3/doc/html/user/user_commands/kdestroy.html new file mode 100644 index 00000000..1cb0c518 --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_commands/kdestroy.html @@ -0,0 +1,212 @@ + + + + + + + + + kdestroy — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kdestroy

+
+

SYNOPSIS

+

kdestroy +[-A] +[-q] +[-c cache_name] +[-p princ_name]

+
+
+

DESCRIPTION

+

The kdestroy utility destroys the user’s active Kerberos authorization +tickets by overwriting and deleting the credentials cache that +contains them. If the credentials cache is not specified, the default +credentials cache is destroyed.

+
+
+

OPTIONS

+
+
-A

Destroys all caches in the collection, if a cache collection is +available. May be used with the -c option to specify the +collection to be destroyed.

+
+
-q

Run quietly. Normally kdestroy beeps if it fails to destroy the +user’s tickets. The -q flag suppresses this behavior.

+
+
-c cache_name

Use cache_name as the credentials (ticket) cache name and +location; if this option is not used, the default cache name and +location are used.

+

The default credentials cache may vary between systems. If the +KRB5CCNAME environment variable is set, its value is used to +name the default ticket cache.

+
+
-p princ_name

If a cache collection is available, destroy the cache for +princ_name instead of the primary cache. May be used with the +-c option to specify the collection to be searched.

+
+
+
+
+

NOTE

+

Most installations recommend that you place the kdestroy command in +your .logout file, so that your tickets are destroyed automatically +when you log out.

+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

FILES

+
+
DEFCCNAME

Default location of Kerberos 5 credentials cache

+
+
+
+
+

SEE ALSO

+

kinit, klist, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_commands/kinit.html b/krb5-1.21.3/doc/html/user/user_commands/kinit.html new file mode 100644 index 00000000..89910d0c --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_commands/kinit.html @@ -0,0 +1,341 @@ + + + + + + + + + kinit — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kinit

+
+

SYNOPSIS

+

kinit +[-V] +[-l lifetime] +[-s start_time] +[-r renewable_life] +[-p | -P] +[-f | -F] +[-a] +[-A] +[-C] +[-E] +[-v] +[-R] +[-k [-i | -t keytab_file]] +[-c cache_name] +[-n] +[-S service_name] +[-I input_ccache] +[-T armor_ccache] +[-X attribute[=value]] +[–request-pac | –no-request-pac] +[principal]

+
+
+

DESCRIPTION

+

kinit obtains and caches an initial ticket-granting ticket for +principal. If principal is absent, kinit chooses an appropriate +principal name based on existing credential cache contents or the +local username of the user invoking kinit. Some options modify the +choice of principal name.

+
+
+

OPTIONS

+
+
-V

display verbose output.

+
+
-l lifetime

(Time duration string.) Requests a ticket with the lifetime +lifetime.

+

For example, kinit -l 5:30 or kinit -l 5h30m.

+

If the -l option is not specified, the default ticket lifetime +(configured by each site) is used. Specifying a ticket lifetime +longer than the maximum ticket lifetime (configured by each site) +will not override the configured maximum ticket lifetime.

+
+
-s start_time

(Time duration string.) Requests a postdated ticket. Postdated +tickets are issued with the invalid flag set, and need to be +resubmitted to the KDC for validation before use.

+

start_time specifies the duration of the delay before the ticket +can become valid.

+
+
-r renewable_life

(Time duration string.) Requests renewable tickets, with a total +lifetime of renewable_life.

+
+
-f

requests forwardable tickets.

+
+
-F

requests non-forwardable tickets.

+
+
-p

requests proxiable tickets.

+
+
-P

requests non-proxiable tickets.

+
+
-a

requests tickets restricted to the host’s local address[es].

+
+
-A

requests tickets not restricted by address.

+
+
-C

requests canonicalization of the principal name, and allows the +KDC to reply with a different client principal from the one +requested.

+
+
-E

treats the principal name as an enterprise name.

+
+
-v

requests that the ticket-granting ticket in the cache (with the +invalid flag set) be passed to the KDC for validation. If the +ticket is within its requested time range, the cache is replaced +with the validated ticket.

+
+
-R

requests renewal of the ticket-granting ticket. Note that an +expired ticket cannot be renewed, even if the ticket is still +within its renewable life.

+

Note that renewable tickets that have expired as reported by +klist may sometimes be renewed using this option, +because the KDC applies a grace period to account for client-KDC +clock skew. See krb5.conf clockskew setting.

+
+
-k [-i | -t keytab_file]

requests a ticket, obtained from a key in the local host’s keytab. +The location of the keytab may be specified with the -t +keytab_file option, or with the -i option to specify the use +of the default client keytab; otherwise the default keytab will be +used. By default, a host ticket for the local host is requested, +but any principal may be specified. On a KDC, the special keytab +location KDB: can be used to indicate that kinit should open +the KDC database and look up the key directly. This permits an +administrator to obtain tickets as any principal that supports +authentication based on the key.

+
+
-n

Requests anonymous processing. Two types of anonymous principals +are supported.

+

For fully anonymous Kerberos, configure pkinit on the KDC and +configure pkinit_anchors in the client’s krb5.conf. +Then use the -n option with a principal of the form @REALM +(an empty principal name followed by the at-sign and a realm +name). If permitted by the KDC, an anonymous ticket will be +returned.

+

A second form of anonymous tickets is supported; these +realm-exposed tickets hide the identity of the client but not the +client’s realm. For this mode, use kinit -n with a normal +principal name. If supported by the KDC, the principal (but not +realm) will be replaced by the anonymous principal.

+

As of release 1.8, the MIT Kerberos KDC only supports fully +anonymous operation.

+
+
+

-I input_ccache

+
+

Specifies the name of a credentials cache that already contains a +ticket. When obtaining that ticket, if information about how that +ticket was obtained was also stored to the cache, that information +will be used to affect how new credentials are obtained, including +preselecting the same methods of authenticating to the KDC.

+
+
+
-T armor_ccache

Specifies the name of a credentials cache that already contains a +ticket. If supported by the KDC, this cache will be used to armor +the request, preventing offline dictionary attacks and allowing +the use of additional preauthentication mechanisms. Armoring also +makes sure that the response from the KDC is not modified in +transit.

+
+
-c cache_name

use cache_name as the Kerberos 5 credentials (ticket) cache +location. If this option is not used, the default cache location +is used.

+

The default cache location may vary between systems. If the +KRB5CCNAME environment variable is set, its value is used to +locate the default cache. If a principal name is specified and +the type of the default cache supports a collection (such as the +DIR type), an existing cache containing credentials for the +principal is selected or a new one is created and becomes the new +primary cache. Otherwise, any existing contents of the default +cache are destroyed by kinit.

+
+
-S service_name

specify an alternate service name to use when getting initial +tickets.

+
+
-X attribute[=value]

specify a pre-authentication attribute and value to be +interpreted by pre-authentication modules. The acceptable +attribute and value values vary from module to module. This +option may be specified multiple times to specify multiple +attributes. If no value is specified, it is assumed to be “yes”.

+

The following attributes are recognized by the PKINIT +pre-authentication mechanism:

+
+
X509_user_identity=value

specify where to find user’s X509 identity information

+
+
X509_anchors=value

specify where to find trusted X509 anchor information

+
+
flag_RSA_PROTOCOL[=yes]

specify use of RSA, rather than the default Diffie-Hellman +protocol

+
+
disable_freshness[=yes]

disable sending freshness tokens (for testing purposes only)

+
+
+
+
–request-pac | –no-request-pac

mutually exclusive. If –request-pac is set, ask the KDC to +include a PAC in authdata; if –no-request-pac is set, ask the +KDC not to include a PAC; if neither are set, the KDC will follow +its default, which is typically is to include a PAC if doing so is +supported.

+
+
+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

FILES

+
+
DEFCCNAME

default location of Kerberos 5 credentials cache

+
+
DEFKTNAME

default location for the local host’s keytab.

+
+
+
+
+

SEE ALSO

+

klist, kdestroy, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_commands/klist.html b/krb5-1.21.3/doc/html/user/user_commands/klist.html new file mode 100644 index 00000000..699b3712 --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_commands/klist.html @@ -0,0 +1,254 @@ + + + + + + + + + klist — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

klist

+
+

SYNOPSIS

+

klist +[-e] +[[-c] [-l] [-A] [-f] [-s] [-a [-n]]] +[-C] +[-k [-i] [-t] [-K]] +[-V] +[-d] +[cache_name|keytab_name]

+
+
+

DESCRIPTION

+

klist lists the Kerberos principal and Kerberos tickets held in a +credentials cache, or the keys held in a keytab file.

+
+
+

OPTIONS

+
+
-e

Displays the encryption types of the session key and the ticket +for each credential in the credential cache, or each key in the +keytab file.

+
+
-l

If a cache collection is available, displays a table summarizing +the caches present in the collection.

+
+
-A

If a cache collection is available, displays the contents of all +of the caches in the collection.

+
+
-c

List tickets held in a credentials cache. This is the default if +neither -c nor -k is specified.

+
+
-f

Shows the flags present in the credentials, using the following +abbreviations:

+
F    Forwardable
+f    forwarded
+P    Proxiable
+p    proxy
+D    postDateable
+d    postdated
+R    Renewable
+I    Initial
+i    invalid
+H    Hardware authenticated
+A    preAuthenticated
+T    Transit policy checked
+O    Okay as delegate
+a    anonymous
+
+
+
+
-s

Causes klist to run silently (produce no output). klist will exit +with status 1 if the credentials cache cannot be read or is +expired, and with status 0 otherwise.

+
+
-a

Display list of addresses in credentials.

+
+
-n

Show numeric addresses instead of reverse-resolving addresses.

+
+
-C

List configuration data that has been stored in the credentials +cache when klist encounters it. By default, configuration data +is not listed.

+
+
-k

List keys held in a keytab file.

+
+
-i

In combination with -k, defaults to using the default client +keytab instead of the default acceptor keytab, if no name is +given.

+
+
-t

Display the time entry timestamps for each keytab entry in the +keytab file.

+
+
-K

Display the value of the encryption key in each keytab entry in +the keytab file.

+
+
-d

Display the authdata types (if any) for each entry.

+
+
-V

Display the Kerberos version number and exit.

+
+
+

If cache_name or keytab_name is not specified, klist will display +the credentials in the default credentials cache or keytab file as +appropriate. If the KRB5CCNAME environment variable is set, its +value is used to locate the default ticket cache.

+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

FILES

+
+
DEFCCNAME

Default location of Kerberos 5 credentials cache

+
+
DEFKTNAME

Default location for the local host’s keytab file.

+
+
+
+
+

SEE ALSO

+

kinit, kdestroy, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_commands/kpasswd.html b/krb5-1.21.3/doc/html/user/user_commands/kpasswd.html new file mode 100644 index 00000000..e3799af3 --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_commands/kpasswd.html @@ -0,0 +1,184 @@ + + + + + + + + + kpasswd — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kpasswd

+
+

SYNOPSIS

+

kpasswd [principal]

+
+
+

DESCRIPTION

+

The kpasswd command is used to change a Kerberos principal’s password. +kpasswd first prompts for the current Kerberos password, then prompts +the user twice for the new password, and the password is changed.

+

If the principal is governed by a policy that specifies the length +and/or number of character classes required in the new password, the +new password must conform to the policy. (The five character classes +are lower case, upper case, numbers, punctuation, and all other +characters.)

+
+
+

OPTIONS

+
+
principal

Change the password for the Kerberos principal principal. +Otherwise, kpasswd uses the principal name from an existing ccache +if there is one; if not, the principal is derived from the +identity of the user invoking the kpasswd command.

+
+
+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

kadmin, kadmind, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_commands/krb5-config.html b/krb5-1.21.3/doc/html/user/user_commands/krb5-config.html new file mode 100644 index 00000000..db556ad8 --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_commands/krb5-config.html @@ -0,0 +1,229 @@ + + + + + + + + + krb5-config — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

krb5-config

+
+

SYNOPSIS

+

krb5-config +[--help | --all | --version | --vendor | --prefix | --exec-prefix | --defccname | --defktname | --defcktname | --cflags | --libs [libraries]]

+
+
+

DESCRIPTION

+

krb5-config tells the application programmer what flags to use to compile +and link programs against the installed Kerberos libraries.

+
+
+

OPTIONS

+
+
--help

prints a usage message. This is the default behavior when no options +are specified.

+
+
--all

prints the version, vendor, prefix, and exec-prefix.

+
+
--version

prints the version number of the Kerberos installation.

+
+
--vendor

prints the name of the vendor of the Kerberos installation.

+
+
--prefix

prints the prefix for which the Kerberos installation was built.

+
+
--exec-prefix

prints the prefix for executables for which the Kerberos installation +was built.

+
+
--defccname

prints the built-in default credentials cache location.

+
+
--defktname

prints the built-in default keytab location.

+
+
--defcktname

prints the built-in default client (initiator) keytab location.

+
+
--cflags

prints the compilation flags used to build the Kerberos installation.

+
+
--libs [library]

prints the compiler options needed to link against library. +Allowed values for library are:

+ ++++ + + + + + + + + + + + + + + + + + +

krb5

Kerberos 5 applications (default)

gssapi

GSSAPI applications with Kerberos 5 bindings

kadm-client

Kadmin client

kadm-server

Kadmin server

kdb

Applications that access the Kerberos database

+
+
+
+
+

EXAMPLES

+

krb5-config is particularly useful for compiling against a Kerberos +installation that was installed in a non-standard location. For example, +a Kerberos installation that is installed in /opt/krb5/ but uses +libraries in /usr/local/lib/ for text localization would produce +the following output:

+
shell% krb5-config --libs krb5
+-L/opt/krb5/lib -Wl,-rpath -Wl,/opt/krb5/lib -L/usr/local/lib -lkrb5 -lk5crypto -lcom_err
+
+
+
+
+

SEE ALSO

+

kerberos, cc(1)

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_commands/ksu.html b/krb5-1.21.3/doc/html/user/user_commands/ksu.html new file mode 100644 index 00000000..34d5033f --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_commands/ksu.html @@ -0,0 +1,516 @@ + + + + + + + + + ksu — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

ksu

+
+

SYNOPSIS

+

ksu +[ target_user ] +[ -n target_principal_name ] +[ -c source_cache_name ] +[ -k ] +[ -r time ] +[ -p | -P] +[ -f | -F] +[ -l lifetime ] +[ -z | Z ] +[ -q ] +[ -e command [ args … ] ] [ -a [ args … ] ]

+
+
+

REQUIREMENTS

+

Must have Kerberos version 5 installed to compile ksu. Must have a +Kerberos version 5 server running to use ksu.

+
+
+

DESCRIPTION

+

ksu is a Kerberized version of the su program that has two missions: +one is to securely change the real and effective user ID to that of +the target user, and the other is to create a new security context.

+
+

Note

+

For the sake of clarity, all references to and attributes of +the user invoking the program will start with “source” +(e.g., “source user”, “source cache”, etc.).

+

Likewise, all references to and attributes of the target +account will start with “target”.

+
+
+
+

AUTHENTICATION

+

To fulfill the first mission, ksu operates in two phases: +authentication and authorization. Resolving the target principal name +is the first step in authentication. The user can either specify his +principal name with the -n option (e.g., -n jqpublic@USC.EDU) +or a default principal name will be assigned using a heuristic +described in the OPTIONS section (see -n option). The target user +name must be the first argument to ksu; if not specified root is the +default. If . is specified then the target user will be the +source user (e.g., ksu .). If the source user is root or the +target user is the source user, no authentication or authorization +takes place. Otherwise, ksu looks for an appropriate Kerberos ticket +in the source cache.

+

The ticket can either be for the end-server or a ticket granting +ticket (TGT) for the target principal’s realm. If the ticket for the +end-server is already in the cache, it’s decrypted and verified. If +it’s not in the cache but the TGT is, the TGT is used to obtain the +ticket for the end-server. The end-server ticket is then verified. +If neither ticket is in the cache, but ksu is compiled with the +GET_TGT_VIA_PASSWD define, the user will be prompted for a +Kerberos password which will then be used to get a TGT. If the user +is logged in remotely and does not have a secure channel, the password +may be exposed. If neither ticket is in the cache and +GET_TGT_VIA_PASSWD is not defined, authentication fails.

+
+
+

AUTHORIZATION

+

This section describes authorization of the source user when ksu is +invoked without the -e option. For a description of the -e +option, see the OPTIONS section.

+

Upon successful authentication, ksu checks whether the target +principal is authorized to access the target account. In the target +user’s home directory, ksu attempts to access two authorization files: +.k5login and .k5users. In the .k5login file each line +contains the name of a principal that is authorized to access the +account.

+

For example:

+
jqpublic@USC.EDU
+jqpublic/secure@USC.EDU
+jqpublic/admin@USC.EDU
+
+
+

The format of .k5users is the same, except the principal name may be +followed by a list of commands that the principal is authorized to +execute (see the -e option in the OPTIONS section for details).

+

Thus if the target principal name is found in the .k5login file the +source user is authorized to access the target account. Otherwise ksu +looks in the .k5users file. If the target principal name is found +without any trailing commands or followed only by * then the +source user is authorized. If either .k5login or .k5users exist but +an appropriate entry for the target principal does not exist then +access is denied. If neither file exists then the principal will be +granted access to the account according to the aname->lname mapping +rules. Otherwise, authorization fails.

+
+
+

EXECUTION OF THE TARGET SHELL

+

Upon successful authentication and authorization, ksu proceeds in a +similar fashion to su. The environment is unmodified with the +exception of USER, HOME and SHELL variables. If the target user is +not root, USER gets set to the target user name. Otherwise USER +remains unchanged. Both HOME and SHELL are set to the target login’s +default values. In addition, the environment variable KRB5CCNAME +gets set to the name of the target cache. The real and effective user +ID are changed to that of the target user. The target user’s shell is +then invoked (the shell name is specified in the password file). Upon +termination of the shell, ksu deletes the target cache (unless ksu is +invoked with the -k option). This is implemented by first doing a +fork and then an exec, instead of just exec, as done by su.

+
+
+

CREATING A NEW SECURITY CONTEXT

+

ksu can be used to create a new security context for the target +program (either the target shell, or command specified via the -e +option). The target program inherits a set of credentials from the +source user. By default, this set includes all of the credentials in +the source cache plus any additional credentials obtained during +authentication. The source user is able to limit the credentials in +this set by using -z or -Z option. -z restricts the copy +of tickets from the source cache to the target cache to only the +tickets where client == the target principal name. The -Z option +provides the target user with a fresh target cache (no creds in the +cache). Note that for security reasons, when the source user is root +and target user is non-root, -z option is the default mode of +operation.

+

While no authentication takes place if the source user is root or is +the same as the target user, additional tickets can still be obtained +for the target cache. If -n is specified and no credentials can +be copied to the target cache, the source user is prompted for a +Kerberos password (unless -Z specified or GET_TGT_VIA_PASSWD +is undefined). If successful, a TGT is obtained from the Kerberos +server and stored in the target cache. Otherwise, if a password is +not provided (user hit return) ksu continues in a normal mode of +operation (the target cache will not contain the desired TGT). If the +wrong password is typed in, ksu fails.

+
+

Note

+

During authentication, only the tickets that could be +obtained without providing a password are cached in the +source cache.

+
+
+
+

OPTIONS

+
+
-n target_principal_name

Specify a Kerberos target principal name. Used in authentication +and authorization phases of ksu.

+

If ksu is invoked without -n, a default principal name is +assigned via the following heuristic:

+
    +
  • Case 1: source user is non-root.

    +

    If the target user is the source user the default principal name +is set to the default principal of the source cache. If the +cache does not exist then the default principal name is set to +target_user@local_realm. If the source and target users are +different and neither ~target_user/.k5users nor +~target_user/.k5login exist then the default principal name +is target_user_login_name@local_realm. Otherwise, starting +with the first principal listed below, ksu checks if the +principal is authorized to access the target account and whether +there is a legitimate ticket for that principal in the source +cache. If both conditions are met that principal becomes the +default target principal, otherwise go to the next principal.

    +
      +
    1. default principal of the source cache

    2. +
    3. target_user@local_realm

    4. +
    5. source_user@local_realm

    6. +
    +

    If a-c fails try any principal for which there is a ticket in +the source cache and that is authorized to access the target +account. If that fails select the first principal that is +authorized to access the target account from the above list. If +none are authorized and ksu is configured with +PRINC_LOOK_AHEAD turned on, select the default principal as +follows:

    +

    For each candidate in the above list, select an authorized +principal that has the same realm name and first part of the +principal name equal to the prefix of the candidate. For +example if candidate a) is jqpublic@ISI.EDU and +jqpublic/secure@ISI.EDU is authorized to access the target +account then the default principal is set to +jqpublic/secure@ISI.EDU.

    +
  • +
  • Case 2: source user is root.

    +

    If the target user is non-root then the default principal name +is target_user@local_realm. Else, if the source cache +exists the default principal name is set to the default +principal of the source cache. If the source cache does not +exist, default principal name is set to root\@local_realm.

    +
  • +
+
+
+

-c source_cache_name

+
+

Specify source cache name (e.g., -c FILE:/tmp/my_cache). If +-c option is not used then the name is obtained from +KRB5CCNAME environment variable. If KRB5CCNAME is not +defined the source cache name is set to krb5cc_<source uid>. +The target cache name is automatically set to krb5cc_<target +uid>.(gen_sym()), where gen_sym generates a new number such that +the resulting cache does not already exist. For example:

+
krb5cc_1984.2
+
+
+
+
+
-k

Do not delete the target cache upon termination of the target +shell or a command (-e command). Without -k, ksu deletes +the target cache.

+
+
-z

Restrict the copy of tickets from the source cache to the target +cache to only the tickets where client == the target principal +name. Use the -n option if you want the tickets for other then +the default principal. Note that the -z option is mutually +exclusive with the -Z option.

+
+
-Z

Don’t copy any tickets from the source cache to the target cache. +Just create a fresh target cache, where the default principal name +of the cache is initialized to the target principal name. Note +that the -Z option is mutually exclusive with the -z +option.

+
+
-q

Suppress the printing of status messages.

+
+
+

Ticket granting ticket options:

+
+
-l lifetime -r time -p -P -f -F

The ticket granting ticket options only apply to the case where +there are no appropriate tickets in the cache to authenticate the +source user. In this case if ksu is configured to prompt users +for a Kerberos password (GET_TGT_VIA_PASSWD is defined), the +ticket granting ticket options that are specified will be used +when getting a ticket granting ticket from the Kerberos server.

+
+
-l lifetime

(Time duration string.) Specifies the lifetime to be requested +for the ticket; if this option is not specified, the default ticket +lifetime (12 hours) is used instead.

+
+
-r time

(Time duration string.) Specifies that the renewable option +should be requested for the ticket, and specifies the desired +total lifetime of the ticket.

+
+
-p

specifies that the proxiable option should be requested for +the ticket.

+
+
-P

specifies that the proxiable option should not be requested +for the ticket, even if the default configuration is to ask for +proxiable tickets.

+
+
-f

option specifies that the forwardable option should be +requested for the ticket.

+
+
-F

option specifies that the forwardable option should not be +requested for the ticket, even if the default configuration is to +ask for forwardable tickets.

+
+
-e command [args …]

ksu proceeds exactly the same as if it was invoked without the +-e option, except instead of executing the target shell, ksu +executes the specified command. Example of usage:

+
ksu bob -e ls -lag
+
+
+

The authorization algorithm for -e is as follows:

+

If the source user is root or source user == target user, no +authorization takes place and the command is executed. If source +user id != 0, and ~target_user/.k5users file does not exist, +authorization fails. Otherwise, ~target_user/.k5users file +must have an appropriate entry for target principal to get +authorized.

+

The .k5users file format:

+

A single principal entry on each line that may be followed by a +list of commands that the principal is authorized to execute. A +principal name followed by a * means that the user is +authorized to execute any command. Thus, in the following +example:

+
jqpublic@USC.EDU ls mail /local/kerberos/klist
+jqpublic/secure@USC.EDU *
+jqpublic/admin@USC.EDU
+
+
+

jqpublic@USC.EDU is only authorized to execute ls, +mail and klist commands. jqpublic/secure@USC.EDU is +authorized to execute any command. jqpublic/admin@USC.EDU is +not authorized to execute any command. Note, that +jqpublic/admin@USC.EDU is authorized to execute the target +shell (regular ksu, without the -e option) but +jqpublic@USC.EDU is not.

+

The commands listed after the principal name must be either a full +path names or just the program name. In the second case, +CMD_PATH specifying the location of authorized programs must +be defined at the compilation time of ksu. Which command gets +executed?

+

If the source user is root or the target user is the source user +or the user is authorized to execute any command (* entry) +then command can be either a full or a relative path leading to +the target program. Otherwise, the user must specify either a +full path or just the program name.

+
+
-a args

Specify arguments to be passed to the target shell. Note that all +flags and parameters following -a will be passed to the shell, +thus all options intended for ksu must precede -a.

+

The -a option can be used to simulate the -e option if +used as follows:

+
-a -c [command [arguments]].
+
+
+

-c is interpreted by the c-shell to execute the command.

+
+
+
+
+

INSTALLATION INSTRUCTIONS

+

ksu can be compiled with the following four flags:

+
+
GET_TGT_VIA_PASSWD

In case no appropriate tickets are found in the source cache, the +user will be prompted for a Kerberos password. The password is +then used to get a ticket granting ticket from the Kerberos +server. The danger of configuring ksu with this macro is if the +source user is logged in remotely and does not have a secure +channel, the password may get exposed.

+
+
PRINC_LOOK_AHEAD

During the resolution of the default principal name, +PRINC_LOOK_AHEAD enables ksu to find principal names in +the .k5users file as described in the OPTIONS section +(see -n option).

+
+
CMD_PATH

Specifies a list of directories containing programs that users are +authorized to execute (via .k5users file).

+
+
HAVE_GETUSERSHELL

If the source user is non-root, ksu insists that the target user’s +shell to be invoked is a “legal shell”. getusershell(3) is +called to obtain the names of “legal shells”. Note that the +target user’s shell is obtained from the passwd file.

+
+
+

Sample configuration:

+
KSU_OPTS = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/bin /usr/ucb /local/bin"
+
+
+

ksu should be owned by root and have the set user id bit turned on.

+

ksu attempts to get a ticket for the end server just as Kerberized +telnet and rlogin. Thus, there must be an entry for the server in the +Kerberos database (e.g., host/nii.isi.edu@ISI.EDU). The keytab +file must be in an appropriate location.

+
+
+

SIDE EFFECTS

+

ksu deletes all expired tickets from the source cache.

+
+
+

AUTHOR OF KSU

+

GENNADY (ARI) MEDVINSKY

+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

kerberos, kinit

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_commands/kswitch.html b/krb5-1.21.3/doc/html/user/user_commands/kswitch.html new file mode 100644 index 00000000..808bceea --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_commands/kswitch.html @@ -0,0 +1,189 @@ + + + + + + + + + kswitch — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kswitch

+
+

SYNOPSIS

+

kswitch +{-c cachename|-p principal}

+
+
+

DESCRIPTION

+

kswitch makes the specified credential cache the primary cache for the +collection, if a cache collection is available.

+
+
+

OPTIONS

+
+
-c cachename

Directly specifies the credential cache to be made primary.

+
+
-p principal

Causes the cache collection to be searched for a cache containing +credentials for principal. If one is found, that collection is +made primary.

+
+
+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

FILES

+
+
DEFCCNAME

Default location of Kerberos 5 credentials cache

+
+
+
+
+

SEE ALSO

+

kinit, kdestroy, klist, +kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_commands/kvno.html b/krb5-1.21.3/doc/html/user/user_commands/kvno.html new file mode 100644 index 00000000..18c4079f --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_commands/kvno.html @@ -0,0 +1,247 @@ + + + + + + + + + kvno — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kvno

+
+

SYNOPSIS

+

kvno +[-c ccache] +[-e etype] +[-k keytab] +[-q] +[-u | -S sname] +[-P] +[–cached-only] +[–no-store] +[–out-cache cache] +[[{-F cert_file | {-I | -U} for_user} [-P]] | –u2u ccache] +service1 service2

+
+
+

DESCRIPTION

+

kvno acquires a service ticket for the specified Kerberos principals +and prints out the key version numbers of each.

+
+
+

OPTIONS

+
+
-c ccache

Specifies the name of a credentials cache to use (if not the +default)

+
+
-e etype

Specifies the enctype which will be requested for the session key +of all the services named on the command line. This is useful in +certain backward compatibility situations.

+
+
-k keytab

Decrypt the acquired tickets using keytab to confirm their +validity.

+
+
-q

Suppress printing output when successful. If a service ticket +cannot be obtained, an error message will still be printed and +kvno will exit with nonzero status.

+
+
-u

Use the unknown name type in requested service principal names. +This option Cannot be used with -S.

+
+
-P

Specifies that the service1 service2 … arguments are to be +treated as services for which credentials should be acquired using +constrained delegation. This option is only valid when used in +conjunction with protocol transition.

+
+
-S sname

Specifies that the service1 service2 … arguments are +interpreted as hostnames, and the service principals are to be +constructed from those hostnames and the service name sname. +The service hostnames will be canonicalized according to the usual +rules for constructing service principals.

+
+
-I for_user

Specifies that protocol transition (S4U2Self) is to be used to +acquire a ticket on behalf of for_user. If constrained +delegation is not requested, the service name must match the +credentials cache client principal.

+
+
-U for_user

Same as -I, but treats for_user as an enterprise name.

+
+
-F cert_file

Specifies that protocol transition is to be used, identifying the +client principal with the X.509 certificate in cert_file. The +certificate file must be in PEM format.

+
+
–cached-only

Only retrieve credentials already present in the cache, not from +the KDC. (Added in release 1.19.)

+
+
–no-store

Do not store retrieved credentials in the cache. If +–out-cache is also specified, credentials will still be +stored into the output credential cache. (Added in release 1.19.)

+
+
–out-cache ccache

Initialize ccache and store all retrieved credentials into it. +Do not store acquired credentials in the input cache. (Added in +release 1.19.)

+
+
–u2u ccache

Requests a user-to-user ticket. ccache must contain a local +krbtgt ticket for the server principal. The reported version +number will typically be 0, as the resulting ticket is not +encrypted in the server’s long-term key.

+
+
+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

FILES

+
+
DEFCCNAME

Default location of the credentials cache

+
+
+
+
+

SEE ALSO

+

kinit, kdestroy, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_commands/sclient.html b/krb5-1.21.3/doc/html/user/user_commands/sclient.html new file mode 100644 index 00000000..1f5ff902 --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_commands/sclient.html @@ -0,0 +1,169 @@ + + + + + + + + + sclient — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

sclient

+
+

SYNOPSIS

+

sclient remotehost

+
+
+

DESCRIPTION

+

sclient is a sample application, primarily useful for testing +purposes. It contacts a sample server sserver and +authenticates to it using Kerberos version 5 tickets, then displays +the server’s response.

+
+
+

ENVIRONMENT

+

See kerberos for a description of Kerberos environment +variables.

+
+
+

SEE ALSO

+

kinit, sserver, kerberos

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_config/index.html b/krb5-1.21.3/doc/html/user/user_config/index.html new file mode 100644 index 00000000..4154d2de --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_config/index.html @@ -0,0 +1,147 @@ + + + + + + + + + User config files — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

User config files

+

The following files in your home directory can be used to control the +behavior of Kerberos as it applies to your account (unless they have +been disabled by your host’s configuration):

+ +
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_config/k5identity.html b/krb5-1.21.3/doc/html/user/user_config/k5identity.html new file mode 100644 index 00000000..e4ebf6b1 --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_config/k5identity.html @@ -0,0 +1,195 @@ + + + + + + + + + .k5identity — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

.k5identity

+
+

DESCRIPTION

+

The .k5identity file, which resides in a user’s home directory, +contains a list of rules for selecting a client principals based on +the server being accessed. These rules are used to choose a +credential cache within the cache collection when possible.

+

Blank lines and lines beginning with # are ignored. Each line has +the form:

+
+

principal field=value

+
+

If the server principal meets all of the field constraints, then +principal is chosen as the client principal. The following fields are +recognized:

+
+
realm

If the realm of the server principal is known, it is matched +against value, which may be a pattern using shell wildcards. +For host-based server principals, the realm will generally only be +known if there is a [domain_realm] section in +krb5.conf with a mapping for the hostname.

+
+
service

If the server principal is a host-based principal, its service +component is matched against value, which may be a pattern using +shell wildcards.

+
+
host

If the server principal is a host-based principal, its hostname +component is converted to lower case and matched against value, +which may be a pattern using shell wildcards.

+

If the server principal matches the constraints of multiple lines +in the .k5identity file, the principal from the first matching +line is used. If no line matches, credentials will be selected +some other way, such as the realm heuristic or the current primary +cache.

+
+
+
+
+

EXAMPLE

+

The following example .k5identity file selects the client principal +alice@KRBTEST.COM if the server principal is within that realm, +the principal alice/root@EXAMPLE.COM if the server host is within +a servers subdomain, and the principal alice/mail@EXAMPLE.COM when +accessing the IMAP service on mail.example.com:

+
alice@KRBTEST.COM       realm=KRBTEST.COM
+alice/root@EXAMPLE.COM  host=*.servers.example.com
+alice/mail@EXAMPLE.COM  host=mail.example.com service=imap
+
+
+
+
+

SEE ALSO

+

kerberos(1), krb5.conf

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_config/k5login.html b/krb5-1.21.3/doc/html/user/user_config/k5login.html new file mode 100644 index 00000000..97afc40c --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_config/k5login.html @@ -0,0 +1,186 @@ + + + + + + + + + .k5login — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

.k5login

+
+

DESCRIPTION

+

The .k5login file, which resides in a user’s home directory, contains +a list of the Kerberos principals. Anyone with valid tickets for a +principal in the file is allowed host access with the UID of the user +in whose home directory the file resides. One common use is to place +a .k5login file in root’s home directory, thereby granting system +administrators remote root access to the host via Kerberos.

+
+
+

EXAMPLES

+

Suppose the user alice had a .k5login file in her home directory +containing just the following line:

+
bob@FOOBAR.ORG
+
+
+

This would allow bob to use Kerberos network applications, such as +ssh(1), to access alice’s account, using bob’s Kerberos +tickets. In a default configuration (with k5login_authoritative set +to true in krb5.conf), this .k5login file would not let +alice use those network applications to access her account, since +she is not listed! With no .k5login file, or with k5login_authoritative +set to false, a default rule would permit the principal alice in the +machine’s default realm to access the alice account.

+

Let us further suppose that alice is a system administrator. +Alice and the other system administrators would have their principals +in root’s .k5login file on each host:

+
alice@BLEEP.COM
+
+joeadmin/root@BLEEP.COM
+
+
+

This would allow either system administrator to log in to these hosts +using their Kerberos tickets instead of having to type the root +password. Note that because bob retains the Kerberos tickets for +his own principal, bob@FOOBAR.ORG, he would not have any of the +privileges that require alice’s tickets, such as root access to +any of the site’s hosts, or the ability to change alice’s +password.

+
+
+

SEE ALSO

+

kerberos(1)

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/html/user/user_config/kerberos.html b/krb5-1.21.3/doc/html/user/user_config/kerberos.html new file mode 100644 index 00000000..fcc718c8 --- /dev/null +++ b/krb5-1.21.3/doc/html/user/user_config/kerberos.html @@ -0,0 +1,303 @@ + + + + + + + + + kerberos — MIT Kerberos Documentation + + + + + + + + + + + + + + +
+
+ + +

MIT Kerberos Documentation

+ +
+ + Contents | + previous | + next | + index | + Search | + feedback +
+
+
+ +
+
+
+ +
+
+
+ +
+

kerberos

+
+

DESCRIPTION

+

The Kerberos system authenticates individual users in a network +environment. After authenticating yourself to Kerberos, you can use +Kerberos-enabled programs without having to present passwords or +certificates to those programs.

+

If you receive the following response from kinit:

+

kinit: Client not found in Kerberos database while getting initial +credentials

+

you haven’t been registered as a Kerberos user. See your system +administrator.

+

A Kerberos name usually contains three parts. The first is the +primary, which is usually a user’s or service’s name. The second +is the instance, which in the case of a user is usually null. +Some users may have privileged instances, however, such as root or +admin. In the case of a service, the instance is the fully +qualified name of the machine on which it runs; i.e. there can be an +ssh service running on the machine ABC (ssh/ABC@REALM), which is +different from the ssh service running on the machine XYZ +(ssh/XYZ@REALM). The third part of a Kerberos name is the realm. +The realm corresponds to the Kerberos service providing authentication +for the principal. Realms are conventionally all-uppercase, and often +match the end of hostnames in the realm (for instance, host01.example.com +might be in realm EXAMPLE.COM).

+

When writing a Kerberos name, the principal name is separated from the +instance (if not null) by a slash, and the realm (if not the local +realm) follows, preceded by an “@” sign. The following are examples +of valid Kerberos names:

+
david
+jennifer/admin
+joeuser@BLEEP.COM
+cbrown/root@FUBAR.ORG
+
+
+

When you authenticate yourself with Kerberos you get an initial +Kerberos ticket. (A Kerberos ticket is an encrypted protocol +message that provides authentication.) Kerberos uses this ticket for +network utilities such as ssh. The ticket transactions are done +transparently, so you don’t have to worry about their management.

+

Note, however, that tickets expire. Administrators may configure more +privileged tickets, such as those with service or instance of root +or admin, to expire in a few minutes, while tickets that carry +more ordinary privileges may be good for several hours or a day. If +your login session extends beyond the time limit, you will have to +re-authenticate yourself to Kerberos to get new tickets using the +kinit command.

+

Some tickets are renewable beyond their initial lifetime. This +means that kinit -R can extend their lifetime without requiring +you to re-authenticate.

+

If you wish to delete your local tickets, use the kdestroy +command.

+

Kerberos tickets can be forwarded. In order to forward tickets, you +must request forwardable tickets when you kinit. Once you have +forwardable tickets, most Kerberos programs have a command line option +to forward them to the remote host. This can be useful for, e.g., +running kinit on your local machine and then sshing into another to do +work. Note that this should not be done on untrusted machines since +they will then have your tickets.

+
+
+

ENVIRONMENT VARIABLES

+

Several environment variables affect the operation of Kerberos-enabled +programs. These include:

+
+
KRB5CCNAME

Default name for the credentials cache file, in the form +TYPE:residual. The type of the default cache may determine +the availability of a cache collection. FILE is not a +collection type; KEYRING, DIR, and KCM are.

+

If not set, the value of default_ccache_name from +configuration files (see KRB5_CONFIG) will be used. If that +is also not set, the default type is FILE, and the +residual is the path /tmp/krb5cc_*uid*, where uid is the +decimal user ID of the user.

+
+
KRB5_KTNAME

Specifies the location of the default keytab file, in the form +TYPE:residual. If no type is present, the FILE type is +assumed and residual is the pathname of the keytab file. If +unset, DEFKTNAME will be used.

+
+
KRB5_CONFIG

Specifies the location of the Kerberos configuration file. The +default is SYSCONFDIR/krb5.conf. Multiple filenames can +be specified, separated by a colon; all files which are present +will be read.

+
+
KRB5_KDC_PROFILE

Specifies the location of the KDC configuration file, which +contains additional configuration directives for the Key +Distribution Center daemon and associated programs. The default +is LOCALSTATEDIR/krb5kdc/kdc.conf.

+
+
KRB5RCACHENAME

(New in release 1.18) Specifies the location of the default replay +cache, in the form type:residual. The file2 type with a +pathname residual specifies a replay cache file in the version-2 +format in the specified location. The none type (residual is +ignored) disables the replay cache. The dfl type (residual is +ignored) indicates the default, which uses a file2 replay cache in +a temporary directory. The default is dfl:.

+
+
KRB5RCACHETYPE

Specifies the type of the default replay cache, if +KRB5RCACHENAME is unspecified. No residual can be specified, +so none and dfl are the only useful types.

+
+
KRB5RCACHEDIR

Specifies the directory used by the dfl replay cache type. +The default is the value of the TMPDIR environment variable, +or /var/tmp if TMPDIR is not set.

+
+
KRB5_TRACE

Specifies a filename to write trace log output to. Trace logs can +help illuminate decisions made internally by the Kerberos +libraries. For example, env KRB5_TRACE=/dev/stderr kinit +would send tracing information for kinit to +/dev/stderr. The default is not to write trace log output +anywhere.

+
+
KRB5_CLIENT_KTNAME

Default client keytab file name. If unset, DEFCKTNAME will be +used).

+
+
KPROP_PORT

kprop port to use. Defaults to 754.

+
+
GSS_MECH_CONFIG

Specifies a filename containing GSSAPI mechanism module +configuration. The default is to read SYSCONFDIR/gss/mech +and files with a .conf suffix within the directory +SYSCONFDIR/gss/mech.d.

+
+
+

Most environment variables are disabled for certain programs, such as +login system programs and setuid programs, which are designed to be +secure when run within an untrusted process environment.

+
+
+

SEE ALSO

+

kdestroy, kinit, klist, +kswitch, kpasswd, ksu, +krb5.conf, kdc.conf, kadmin, +kadmind, kdb5_util, krb5kdc

+
+
+

BUGS

+
+
+

AUTHORS

+
+
Steve Miller, MIT Project Athena/Digital Equipment Corporation
+
Clifford Neuman, MIT Project Athena
+
Greg Hudson, MIT Kerberos Consortium
+
Robbie Harwood, Red Hat, Inc.
+
+
+
+

HISTORY

+

The MIT Kerberos 5 implementation was developed at MIT, with +contributions from many outside parties. It is currently maintained +by the MIT Kerberos Consortium.

+
+
+

RESTRICTIONS

+

Copyright 1985, 1986, 1989-1996, 2002, 2011, 2018 Masachusetts +Institute of Technology

+
+
+ + +
+
+
+
+
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/krb5-1.21.3/doc/index.rst b/krb5-1.21.3/doc/index.rst new file mode 100644 index 00000000..543a9d1b --- /dev/null +++ b/krb5-1.21.3/doc/index.rst @@ -0,0 +1,18 @@ +MIT Kerberos Documentation (|release|) +====================================== + + +.. toctree:: + :maxdepth: 1 + + user/index.rst + admin/index.rst + appdev/index.rst + plugindev/index.rst + build/index.rst + basic/index.rst + formats/index.rst + mitK5features.rst + build_this.rst + about.rst + resources diff --git a/krb5-1.21.3/doc/iprop-notes.txt b/krb5-1.21.3/doc/iprop-notes.txt new file mode 100644 index 00000000..b620773d --- /dev/null +++ b/krb5-1.21.3/doc/iprop-notes.txt @@ -0,0 +1,140 @@ +Some (intentional) changes from Sun's submission are noted in the +install guide. + +Bugs or issues: + +The "full resync" part of the protocol involves the primary side +firing off a normal kprop (and going back to servicing requests), and +the replica side stopping all the incremental propagation stuff and +waiting for the kprop. If the connection from the primary never comes +in for some reason, the replica side just blocks forever, and never +resumes incremental propagation. + +The protocol does not currently pass policy database changes; this was +an intentional decision on Sun's part. The policy database is only +relevant to the primary KDC, and is usually fairly static (aside from +refcount updates), but not propagating it does mean that a replica +maintained via iprop can't simply be promoted to a primary in disaster +recovery or other cases without doing a full propagation or restoring +a database from backups. + +Shawn had a good suggestion after I started the integration work, and +which I haven't had a chance to implement: Make the update-log code +fit in as a sort of pseudo-database layer via the DAL, being called +through the standard DAL methods, and doing its work around calls +through to the real database back end again through the DAL methods. +So for example, creating a "iprop+db2" database would create an update +log and the real db2 database; storing a principal entry would update +the update log as well; etc. At least initially, we wouldn't treat it +as a differently-named database; the installation of the hooks would +be done by explicitly checking if iprop is enabled, etc. + +The "iprop role" is assumed to be either primary or replica. The +primary writes a log, and the replica fetches it. But what about a +cascade propagation model where A sends to B which sends to C, perhaps +because A's bandwidth is highly limited, or B and C are co-located? +In such a case, B would want to operate in both modes. Granted, with +iprop the bandwidth issues should be less important, but there may +still be reasons one may wish to run in such a configuration. + +The propagation of changes does not happen in real time. It's not a +"push" protocol; the replicas poll periodically for changes. Perhaps +a future revision of the protocol could address that. + +kadmin/cli/kadmin.c call to kadm5_init_iprop - is this needed in +client-side program? Should it be done in libkadm5srv instead as part +of the existing kadm5_init* so that database-accessing applications +that don't get updated at the source level will automatically start +changing the update log as needed? + +Locking: Currently DAL exports the DB locking interface to the caller; +we want to slip the iprop code in between -- run it plus the DB update +operation with the DB lock held, whether or not the caller grabbed the +lock. (Does the caller always grab the lock before making changes?) +Currently we're using a file lock on the update log itself; this will +be independent of whether the DB back end implements locking (which +may be a good thing or a bad thing, depending). + +Various logging calls with odd format strings like "" should be +fixed. + +Why are different principal names used, when incremental propagation +requires that normal kprop (which uses host principals) be possible +anyways? + +Why is this tied to kadmind, aside from (a) wanting to prevent other +db changes, which locking protocols should deal with anyways, (b) +existing acl code, (c) existing server process? + +The incremental propagation protocol requires an ACL entry on the +primary, listing the replica. Since the full-resync part uses normal +kprop, the replica also has to have an ACL entry for the primary. If +this is missing, I suspect the behavior will be that every two +minutes, the primary side will (at the prompting of the replica) dump +out the database and attempt a full propagation. + +Possible optimizations: If an existing dump file has a recent enough +serial number, just send it, without dumping again? Use just one dump +file instead of one per replica? + +Requiring normal kprop means the replica still can't be behind a NAT +or firewall without special configuration. The incremental parts can +work in such a configuration, so long as outgoing TCP connections are +allowed. + +Still limited to IPv4 because of limitations in MIT's version of the +RPC code. (This could be fixed for kprop, if IPv6 sites want to do +full propagation only. Doing incremental propagation over IPv6 will +take work on the RPC library, and probably introduce +backwards-incompatible ABI changes.) + +Overflow checks for ulogentries times block size? + +If file can't be made the size indicated by ulogentries, should we +truncate or error out? If we error out, this could blow out when +resizing the log because of a too-large log entry. + +The kprop invocation doesn't specify a realm name, so it'll only work +for the default realm. No clean way to specify a port number, either. +Would it be overkill to come up with a way to configure host+port for +kpropd on the primary? Preferably in a way that'd support cascading +propagations. + +The kadmind process, when it needs to run kprop, extracts the replica +host name from the client principal name. It assumes that the +principal name will be of the form foo/hostname@REALM, and looks +specifically for the "/" and "@" to chop up the string form of the +name. If looking up that name won't give a working IPv4 address for +the replica, kprop will fail (and kpropd will keep waiting, +incremental updates will stop, etc). + +Mapping between file offsets and structure addresses, we should be +careful about alignment. We're probably okay on current platforms, +but if we break log-format compatibility with Sun at some point, use +the chance to make the kdb_ent_header_t offsets be more strictly +aligned in the file. (16 or 32 bytes?) + +Not thread safe! The kdb5.c code will get a lock on the update log +file while making changes, but the lock is per-process. Currently +there are no processes I know of that use multiple threads and change +the database. (There's the Novell patch to make the KDC +multithreaded, but the kdc-kdb-update option doesn't currently +compile.) + +Logging in kpropd is poor to useless. If there are any problems, run +it in debug mode ("-d"). You'll still lose all output from the +invocation of kdb5_util dump and kprop run out of kadmind. + +Other man page updates needed: Anything with new -x options. + +Comments from lha: + +Verify both client and server are demanding privacy from RPC. + +Authorization code in check_iprop_rpcsec_auth is weird. Check realm +checking, is it trusting the client realm length? + +What will happen if my realm is named "A" and I can get a cross realm +(though multihop) to ATHENA.MIT.EDU's iprop server? + +Why is the ACL not applied before we get to the functions themselves? diff --git a/krb5-1.21.3/doc/kadm5-errmsg.txt b/krb5-1.21.3/doc/kadm5-errmsg.txt new file mode 100644 index 00000000..76404bca --- /dev/null +++ b/krb5-1.21.3/doc/kadm5-errmsg.txt @@ -0,0 +1,59 @@ +Proposed approach for passing more detailed error messages across the +kadm5 API: + +We've already got too many init functions and too many options. +Multiplying the number of init functions isn't feasible. + +Create an (opaque to application) init-options type, create/destroy +functions for it, set-creds/set-keytab/set-password functions, and a +kadm5-init-with-options function. (Optional: Reimplement the current +init functions as wrappers around these.) + +Add a set-context function which saves away in the init-options object +a krb5_context to be used in the new server handle instead of creating +a new one. (Destroying a server handle with such a "borrowed" krb5 +context should probably not destroy the context.) Calls within the +library should store any error messages in the context contained in +the server handle. Error messages produced during initialization +should also be stored in this context. + +The caller of these functions can use krb5_get_error_message to +extract the text of the error message from the supplied context. + +Unless we determine it's safe, we should probably assert (for now) +that each server handle must have a different context. (That's aside +from the thread safety issues.) + +These contexts should have been created with kadm5_init_krb5_context, +which will decide whether to look at the KDC config file depending on +whether you're using the client-side or server-side version of the +library. (Same as for kadmin vs kadmin.local.) + +Notes: + + * The existing API must continue to work, without changes. There is + external code we need to continue to support. + + * We considered a variant where the application could retrieve the + error message from the server handle using a new + kadm5_get_error_message function. However, the initialization code + is one likely place where the errors would occur (can't + authenticate, etc), and in that case, there is no server handle + from which to extract the context. + + A function to retrieve the library-created krb5_context from the + server handle would have the same problem. + + Using a separate approach to deal with errors at initialization + time, in combination with the above, might work. But we still wind + up either creating the init-with-options interface or adding + error-message-return variants of multiple existing init functions. + +To do: + + * Write up specifics (including function names -- the names used here + aren't meant to be definitive) and discuss on krbdev. + + * Implement library part. + + * Change kadmin and kdc to use it. diff --git a/krb5-1.21.3/doc/kadm5/adb-unit-test.tex b/krb5-1.21.3/doc/kadm5/adb-unit-test.tex new file mode 100644 index 00000000..0595c672 --- /dev/null +++ b/krb5-1.21.3/doc/kadm5/adb-unit-test.tex @@ -0,0 +1,135 @@ +% This document is included for historical purposes only, and does not +% apply to krb5 today. + +\documentstyle[times,fullpage]{article} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Make _ actually generate an _, and allow line-breaking after it. +\let\underscore=\_ +\catcode`_=13 +\def_{\underscore\penalty75\relax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newcommand{\test}[1]{\begin{description} +\setlength{\itemsep}{0pt} +#1 +\end{description} + +} + +\newcommand{\numtest}[2]{\begin{description} +\setlength{\itemsep}{0pt} +\Number{#1} +#2 +\end{description} + +} + +\newcommand{\Number}[1]{\item[Number:] #1} +\newcommand{\Reason}[1]{\item[Reason:] #1} +%\newcommand{\Call}[1]{\item[Call:] #1} +\newcommand{\Expected}[1]{\item[Expected:] #1} +\newcommand{\Conditions}[1]{\item[Conditions:] #1} +\newcommand{\Priority}[1]{\item[Priority:] #1} +\newcommand{\Status}[1]{\item[Status:] #1} +%\newcommand{\Number}[1]{} +%\newcommand{\Reason}[1]{} +\newcommand{\Call}[1]{} +%\newcommand{\Expected}[1]{} +%\newcommand{\Conditions}[1]{} +%\newcommand{\Priority}[1]{} + +\title{OpenV*Secure Admin Database API\\ +Unit Test Description} +\author{Jonathan I. Kamens} + +\begin{document} + +\maketitle + +%\tableofcontents + +\section{Introduction} + +The following is a description of a black-box unit test of the +OpenV*Secure Admin Database API (osa_adb). Each API function is +listed, followed by the tests that should be performed on it. + +The tests described here are based on the ``OV*Secure Admin Server +Implementation Design'' revision 1.14. + +\section{osa_adb_get_lock and osa_adb_release_lock} + +\numtest{1}{ +\Reason{A shared lock can be acquired.} +\Status{Implemented} +} + +\numtest{2}{ +\Reason{An exclusive lock can be acquired and released.} +\Status{Implemented} +} + +\numtest{3}{ +\Reason{A permanent lock can be acquired and released.} +\Status{Implemented} +} + +\numtest{4}{ +\Reason{Attempting to release a lock when none is held fails with +NOTLOCKED.} +\Status{Implemented} +} + +\numtest{5}{ +\Reason{Two processes can both acquire a shared lock.} +\Status{Implemented} +} + +\numtest{6}{ +\Reason{An attempt to acquire a shared lock while another process holds an +exclusive lock fails with CANTLOCK_DB.} +\Status{Implemented} +} + +\numtest{7}{ +\Reason{An attempt to acquire an exclusive lock while another process holds a +shared lock fails with CANTLOCK_DB.} +\Status{Implemented} +} + +\numtest{8}{ +\Reason{An attempt to open the database while a process holds a +permanent lock fails with NO_LOCKFILE.} +\Status{Implemented} +} + +\numtest{9}{ +\Reason{An attempt to acquire an exclusive lock while a process holds a +permanent lock fails with NO_LOCKFILE.} +\Status{Implemented} +} + +\numtest{10}{ +\Reason{Acquiring a permanent lock deletes the lockfile.} +\Status{Implemented} +} + +\numtest{11}{ +\Reason{Releasing a permanent lock re-creates the lockfile.} +\Status{Implemented} +} + +\numtest{12}{ +\Reason{A process can perform a get operation while another process holds a +shared lock.} +\Status{Implemented} +} + +\numtest{13}{ +\Reason{A process that is running and has opened the adb principal database +can retrieve a principal created after the open occurred.} +\Status{Implemented, but not working} +} + +\end{document} diff --git a/krb5-1.21.3/doc/kadm5/api-funcspec.tex b/krb5-1.21.3/doc/kadm5/api-funcspec.tex new file mode 100644 index 00000000..b633cef1 --- /dev/null +++ b/krb5-1.21.3/doc/kadm5/api-funcspec.tex @@ -0,0 +1,2015 @@ +% This document is included for historical purposes only, and does not +% apply to krb5 today. + +\documentstyle[12pt,fullpage]{article} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Make _ actually generate an _, and allow line-breaking after it. +\let\underscore=\_ +\catcode`_=13 +\def_{\underscore\penalty75\relax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\setlength{\parskip}{.7\baselineskip} +\setlength{\parindent}{0pt} + +\def\v#1{\verb+#1+} + +\title{Kerberos Administration System \\ + KADM5 API Functional Specifications} +\author{Barry Jaspan} + +\begin{document} + +\sloppy +\maketitle + +{\setlength{\parskip}{0pt}\tableofcontents} + +\section{Introduction} + +This document describes the Admin API that can be used to maintain +principals and policies. It describes the data structures used for +each function and the interpretation of each data type field, the +semantics of each API function, and the possible return codes. + +The Admin API is intended to be used by remote clients using an RPC +interface. It is implemented by the admin server running on the +Kerberos master server. It is also possible for a program running on +the Kerberos master server to use the Admin API directly, without +going through the admin server. + +\section{Versions of the API} + +The versions of this API and a brief description of the changes for +each are: + +\begin{description} +\item[KADM5_API_VERSION_1] The initial version of this API, written by +OpenVision Technologies and donated to MIT for including in the public +release. Originally called OVSEC_KADM_API_VERSION_1. Most everything +has been renamed in one way or another, including functions, header +files, and data structures. Where possible, the old OVSEC_KADM names +have been left behind for compatibility with version 1, and +KADM5_API_VERSION_1 is compatible with OVSEC_KADM_API_VERSION_1 at +compile-, link-, and run-time. + +The OVSEC_KADM name compatibility will not be extended to new +functionality in future versions because no existing OVSEC_KADM +clients will use that functionality; new clients should be written to +the KADM5 API. + +\item[KADM5_API_VERSION_2] This version contains the initial changes +necessary to make the OpenVision administration system work with the +mid-1996 MIT version of Kerberos 5. Changes include +\begin{enumerate} +\item The kadm5_init functions now take a structure of parameters +instead of just a realm name, allowing the calling program to specify +non-default values for various configuration options. See section +\ref{sec:configparams} for details. + +\item The KADM5 API has been extended to support new features of the +Kerberos database, including multiple encryption and salt types per +principal. See section \ref{sec:keys} for details. + +\item kadm5_get_principal now allows a principal's keys to be +retrieved {\it by local clients only}. This is necessary in order for +the kadm5 API to provide the primary Kerberos database interface. + +\item The KADM5 authorization system has been completely changed. + +\item The functions kadm5_flush, kadm5_get_principals, and +kadm5_get_policies have been added. + +\item The KADM5 API now obeys a caller-allocates rather than +callee-allocates system. kadm5_get_principal and kadm5_get_policy are +affected. +\end{enumerate} +\end{description} + +\section{Policies and Password Quality} + +The Admin API Password Quality mechanism provides the following +controls. Note that two strings are defined to be ``significantly +different'' if they differ by at least one character. The compare is not +case sensitive. + +\begin{itemize} +\item A minimum length can be required; a password with +fewer than the specified number of characters will not be accepted. + +\item A minimum number of character classes can be required; a +password that does not contain at least one character from at least +the specified number of character classes will not be accepted. The +character classes are defined by islower(), isupper(), isdigit(), +ispunct(), and other. + +\item Passwords can be required to be different from +previous passwords; a password that generates the same encryption key +as any of the principal's specified previous number of passwords will +not be accepted. This comparison is performed on the encryption keys +generated from the passwords, not on the passwords themselves. + +\item A single ``forbidden password'' dictionary can be specified for all +users; a password that is not significantly different from every word +in the dictionary will not be accepted. +\end{itemize} + +\section{Data Structures} + +This section describes the data structures used by the Admin API. +They are defined in $<$kadm5/admin.h$>$. + +\subsection{Principals, kadm5_principal_ent_t} +\label{sec:principal-structure} + +A Kerberos principal entry is represented by a kadm5_principal_ent_t. +It contains a subset of the information stored in the master Kerberos +database as well as the additional information maintained by the admin +system. In the current version, the only additional information is +the principal's policy and the aux_attributes flags. + +The principal may or may not have a policy enforced on it. If the +POLICY bit (see section \ref{sec:masks}) is set in aux_attributes, the +policy field names the principal's policy. If the POLICY bit is not +set in aux_attributes, no policy is enforced on the principal and the +value of the policy field is undefined. + +\begin{figure}[htbp] +\begin{verbatim} +typedef struct _kadm5_principal_ent_t { + krb5_principal principal; + + krb5_timestamp princ_expire_time; + krb5_timestamp last_pwd_change; + krb5_timestamp pw_expiration; + krb5_deltat max_life; + krb5_principal mod_name; + krb5_timestamp mod_date; + krb5_flags attributes; + krb5_kvno kvno; + krb5_kvno mkvno; + + char * policy; + u_int32 aux_attributes; + + krb5_deltat max_renewable_life; + krb5_timestamp last_success; + krb5_timestamp last_failed; + krb5_kvno fail_auth_count; + krb5_int16 n_key_data; + krb5_int16 n_tl_data; + krb5_tl_data *tl_data; + krb5_key_data *key_data; +} kadm5_principal_ent_rec, *kadm5_principal_ent_t; +\end{verbatim} +\caption{Definition of kadm5_principal_ent_t.} +\label{fig:princ-t} +\end{figure} + +The fields of an kadm5_principal_ent_t are interpreted as +follows. + +\begin{description} +\item[principal] The name of the principal; must conform to Kerberos +naming specifications. + +\item[princ_expire_time] The expire time of the principal as a Kerberos +timestamp. No Kerberos tickets will be issued for a principal after +its expire time. + +\item[last_pwd_change] The time this principal's password was last +changed, as a Kerberos timestamp. + +\item[pw_expiration] The expire time of the user's current password, as a +Kerberos timestamp. No application service tickets will be issued for the +principal once the password expire time has passed. Note that the user can +only obtain tickets for services that have the PW_CHANGE_SERVICE bit set in +the attributes field. + +\item[max_life] The maximum lifetime of any Kerberos ticket issued to +this principal. + +\item[attributes] A bitfield of attributes for use by the KDC. The +symbols and constant values are defined below; their interpretation +appears in the libkdb functional specification. + +\begin{tabular}{clr} +{\bf Name} & {\bf Value} \\ +KRB5_KDB_DISALLOW_POSTDATED & 0x00000001 \\ +KRB5_KDB_DISALLOW_FORWARDABLE & 0x00000002 \\ +KRB5_KDB_DISALLOW_TGT_BASED & 0x00000004 \\ +KRB5_KDB_DISALLOW_RENEWABLE & 0x00000008 \\ +KRB5_KDB_DISALLOW_PROXIABLE & 0x00000010 \\ +KRB5_KDB_DISALLOW_DUP_SKEY & 0x00000020 \\ +KRB5_KDB_DISALLOW_ALL_TIX & 0x00000040 \\ +KRB5_KDB_REQUIRES_PRE_AUTH & 0x00000080 \\ +KRB5_KDB_REQUIRES_HW_AUTH & 0x00000100 \\ +KRB5_KDB_REQUIRES_PWCHANGE & 0x00000200 \\ +KRB5_KDB_DISALLOW_SVR & 0x00001000 \\ +KRB5_KDB_PWCHANGE_SERVICE & 0x00002000 \\ +KRB5_KDB_SUPPORT_DESMD5 & 0x00004000 \\ +KRB5_KDB_NEW_PRINC & 0x00008000 +\end{tabular} + +\item[mod_name] The name of the Kerberos principal that most recently +modified this principal. + +\item[mod_date] The time this principal was last modified, as a Kerberos +timestamp. + +\item[kvno] The version of the principal's current key. + +\item[mkvno] The version of the Kerberos Master Key in effect when +this principal's key was last changed. In KADM5_API_VERSION_2, this +field is always zero. + +\item[policy] If the POLICY bit is set in aux_attributes, the name +of the policy controlling this principal. + +\item[aux_attributes] A bitfield of flags for use by the +administration system. Currently, the only valid flag is POLICY, and +it indicates whether or not the principal has a policy enforced on it. + +\item[max_renewable_life] The maximum renewable lifetime of any +Kerberos ticket issued to or for this principal. This field only +exists in KADM5_API_VERSION_2. + +\item[last_success] The KDC time of the last successful AS_REQ. This +is only updated if KRBCONF_KDC_MODIFIES_KDB is defined during +compilation of the KDC. This field only exists in +KADM5_API_VERSION_2. + +\item[last_failed] The KDC time of the last failed AS_REQ. This is +only updated if KRBCONF_KDC_MODIFIES_KDB is defined during compilation +of the KDC. This field only exists in KADM5_API_VERSION_2. + +\item[fail_auth_count] The number of consecutive failed AS_REQs. When +this number reaches KRB5_MAX_FAIL_COUNT, the KRB5_KDC_DISALLOW_ALL_TIX +is set on the principal. This is only updated if +KRBCONF_KDC_MODIFIES_KDB is defined during compilation. This field +only exists in KADM5_API_VERSION_2. + +\item[n_tl_data] The number of elements in the \v{tl_data} linked +list. This field only exists in KADM5_API_VERSION_2. + +\item[n_key_data] The number of elements in the \v{key_data} +array. This field only exists in KADM5_API_VERSION_2. + +\item[tl_data] A linked list of tagged data. This list is a mechanism +by which programs can store extended information in a principal entry, +without having to modify the database API. Each element is of type +krb5_tl_data: +\begin{verbatim} +typedef struct _krb5_tl_data { + struct _krb5_tl_data* tl_data_next; + krb5_int16 tl_data_type; + krb5_int16 tl_data_length; + krb5_octet * tl_data_contents; +} krb5_tl_data; +\end{verbatim} +% +The KADM5 API only allows elements whose tl_data_type is greater than +or equal to 256. Values less than 256 are reserved for internal use +by the KADM5 or kdb system. They are filtered out of the list +returned by kadm5_get_principal, and generate an error if given to +kadm5_modify_principal. + +The libkdb library defines the tagged data types +KRB5_TL_LAST_PWD_CHANGE, KRB5_TL_MOD_PRINC, and KRB5_TL_KADM_DATA, all +with values less than 256, which store the last password modification +time, time and modifier of last principal modification, and +administration system data. All of these entries are expected by the +administration system and parsed out into fields of the +kadm5_principal_ent_rec structure; as described above, they are not +included in the tl_data list. + +Tagged data elements with types greater than 256 are handled without +interpretation by KADM5. Note that an application that calls +kadm5_modify_principal with the KADM5_TL_DATA mask bit set is +responsible for providing the {\it complete} tl_data list, which it +necessarily must obtain from kadm5_get_principal. It is {\it never} +possible for an application to construct a complete tl_data list from +scratch. + +\item[key_data] An array of the principal's keys. The keys contained +in this array are encrypted in the Kerberos master key. See section +\ref{sec:keys} for a discussion of the krb5_key_data structure. +\end{description} + +\subsection{Policies, kadm5_policy_ent_t} +\label{sec:policy-fields} + +If the POLICY bit is set in aux_attributes, the \v{policy} name field +in the kadm5_principal_ent_t structure refers to a password policy +entry defined in a \v{kadm5_policy_ent_t}. + +\begin{verbatim} +typedef struct _kadm5_policy_ent_t { + char *policy; + + u_int32 pw_min_life; + u_int32 pw_max_life; + u_int32 pw_min_length; + u_int32 pw_min_classes; + u_int32 pw_history_num; + u_int32 policy_refcnt; +} kadm5_policy_ent_rec, *kadm5_policy_ent_t; +\end{verbatim} + +The fields of an kadm5_policy_ent_t are interpreted as follows. +Note that a policy's values only apply to a principal using that +policy. + +\begin{description} +\item[policy] The name of this policy, as a NULL-terminated string. +The ASCII characters between 32 (space) and 126 (tilde), inclusive, +are legal. + +\item[pw_min_life] The minimum password lifetime, in seconds. +A principal cannot change its password before pw_min_life seconds have +passed since last_pwd_change. + +\item[pw_max_life] The default duration, in seconds, used to compute +pw_expiration when a principal's password is changed. + +\item[pw_min_length] The minimum password length, in characters. A +principal cannot set its password to anything with fewer than this +number of characters. This value must be greater than zero. + +\item[pw_min_classes] The minimum number of character classes in the +password. This value can only be 1, 2, 3, 4, or 5. A principal cannot +set its password to anything with fewer than this number of character +classes in it. + +\item[pw_history_num] The number of past passwords that are +stored for the principal; the minimum value is 1 and the maximum value +is 10. A principal cannot set its password to any of its previous +pw_history_num passwords. The first ``previous'' password is the +current password; thus, a principal with a policy can never reset its +password to its current value. + +\item[policy_refcnt] The number of principals currently using this policy. +A policy cannot be deleted unless this number is zero. +\end{description} + +\subsection{Configuration parameters} +\label{sec:configparams} + +The KADM5 API acquires configuration information from the Kerberos +configuration file (\$KRB5_CONFIG or DEFAULT_PROFILE_PATH) and from +the KDC configuration file (\$KRB5_KDC_CONFIG or DEFAULT_KDC_PROFILE). +In KADM5_API_VERSION_2, some of the configuration parameters used by +the KADM5 API can be controlled by the caller by providing a +kadm5_config_params structure to kadm5_init: +% +\begin{verbatim} +typedef struct _kadm5_config_params { + u_int32 mask; + + /* Client and server fields */ + char *realm; + char *profile; + int kadmind_port; + + /* client fields */ + char *admin_server; + + /* server fields */ + char *dbname; + char *admin_dbname; + char *admin_lockfile; + char *acl_file; + char *dict_file; + char *admin_keytab; + + /* server library (database) fields */ + int mkey_from_kbd; + char *stash_file; + char *mkey_name; + krb5_enctype enctype; + krb5_deltat max_life; + krb5_deltat max_rlife; + krb5_timestamp expiration; + krb5_flags flags; + krb5_key_salt_tuple *keysalts; + krb5_int32 num_keysalts; +} kadm5_config_params; +\end{verbatim} +% +The following list describes each of the fields of the structure, +along with the profile relation it overrides, its mask value, its +default value, and whether it is valid on the client, server, or both, +or neither. +\begin{description} +\item[mask] No variable. No mask value. A bitfield specifying which +fields of the structure contain valid information. A caller sets this +mask before calling kadm5_init_*, indicating which parameters are +specified. The mask values are defined in $<$kadm5/admin.h$>$ and are +all prefixed with KADM5_CONFIG_; the prefix is not included in the +descriptions below. + +\item[realm] No variable. REALM. Client and server. The realm to +which these parameters apply, and the realm for which additional +parameters are to be acquired, if any. If this field is not specified +in the mask, the default local realm is used. + +\item[profile] Variable: profile (server only). PROFILE. Client and +server. The Kerberos profile to use. On the client, the default is +the value of the KRB5_CONFIG environment variable, or +DEFAULT_PROFILE_PATH if that is not set. On the server, the value of +the ``profile'' variable of the KDC configuration file will be used as +the first default if it exists; otherwise, the default is the value of +the KRB5_KDC_PROFILE environment variable or DEFAULT_KDC_PROFILE. + +\item[kadmind_port] Variable: kadmind_port. KADMIND_PORT. Client and +server. The port number the kadmind server listens on. The client +uses this field to determine where to connect, and the server to +determine where to listen. The default is 749, which has been +assigned by IANA. + +\item[admin_server] Variable: admin_server. ADMIN_SERVER. Client. +The host name of the admin server to which to connect. There is no +default. If the value of this field contains a colon (:), the text +following the colon is treated as an integer and assigned to the +kadmind_port field, overriding any value of the kadmind_port variable. + +\item[dbname] Variable: dbname. DBNAME. Server. The Kerberos +database name to use; the Kerberos database stores principal +information. The default is DEFAULT_KDB_FILE. + +\item[admin_dbname] Variable: admin_database_name. ADBNAME. +Neither. If the dbname field is set, this field is set to the value +of dbname followed by ``.kadm5''. + +\item[admin_lockfile] Variable: admin_database_lockfile. +ADB_LOCKFILE. Neither. If the admin_dbname field is set, this field +is set to the value of admin_dbname followed by ``.lock''. + +\item[acl_file] Variable: acl_file. ACL_FILE. Server. The admin +server's ACL file. The default is DEFAULT_KADM5_ACL_FILE. + +\item[dict_file] Variable: admin_dict_file. DICT_FILE. Server. The +admin server's dictionary file of passwords to disallow. No default. + +\item[admin_keytab] Variable: admin_keytab. ADMIN_KEYTAB. Server. +The keytab file containing the kadmin/admin and kadmin/changepw +entries for the server to use. The default is the value of the +KRB5_KTNAME environment variable, if defined, else +DEFAULT_KADM5_KEYTAB. + +\item[mkey_from_keyboard] No variable. MKEY_FROM_KEYBOARD. Server. +If non-zero, prompt for the master password via the tty instead of +using the stash file. If this mask bit is not set, or is set and the +value is zero, the stash file is used. + +\item[stash_file] Variable: key_stash_file. STASH_FILE. Server. The +file name containing the master key stash file. No default; libkdb +will work with a NULL value. + +\item[mkey_name] Variable: master_key_name. MKEY_NAME. Server. The +name of the master principal for the realm. No default; lbkdb will +work with a NULL value. + +\item[enctype] Variable: master_key_type. ENCTYPE. Server. The +encryption type of the master principal. The default is +DEFAULT_KDC_ENCTYPE. + +\item[max_life] Variable: max_life. MAX_LIFE. Maximum lifetime for +all tickets issued to the principal. The default is 28800, which is 8 +hours. + +\item[max_rlife, expiration, flags] Variables: max_renewable_life, +default_principal_expiration, default_principal_flags. MAX_LIFE, +MAX_RLIFE, EXPIRATION, FLAGS. Server. Default values for new +principals. All default to 0. + +\item[keysalts, num_keysalts] Variable: supported_enctypes. ENCTYPES. +Server. The list of supported encryption type/salt type tuples; both +fields must be assigned if ENCTYPES is set. The default is a list +containing one enctype, DES-CBC-CRC with normal salt. +\end{description} + +\subsection{Principal keys} +\label{sec:keys} + +In KADM5_API_VERSION_1, all principals had a single key. The +encryption method was always DES, and the salt type was determined +outside the API (by command-line options to the administration +server). + +In KADM5_API_VERSION_2, principals can have multiple keys, each with +its own encryption type and salt. Each time a principal's key is +changed with kadm5_create_principal, kadm5_chpass_principal or +kadm5_randkey_principal, existing key entries are removed and a key +entry for each encryption and salt type tuple specified in the +configuration parameters is added. There is no provision for +specifying encryption and salt type information on a per-principal +basis; in a future version, this will probably be part of the admin +policy. There is also presently no provision for keeping multiple key +versions for a single principal active in the database. + +A single key is represented by a krb5_key_data: +% +\begin{verbatim} +typedef struct _krb5_key_data { + krb5_int16 key_data_ver; /* Version */ + krb5_int16 key_data_kvno; /* Key Version */ + krb5_int16 key_data_type[2]; /* Array of types */ + krb5_int16 key_data_length[2]; /* Array of lengths */ + krb5_octet * key_data_contents[2]; /* Array of pointers */ +} krb5_key_data; +\end{verbatim} +% +\begin{description} +\item[key_data_ver] The version number of the structure. Versions 1 +and 2 are currently defined. If key_data_ver is 1 then the key is +either a random key (not requiring a salt) or the salt is the normal +v5 salt which is the same as the realm and therefore doesn't need to +be saved in the database. + +\item[key_data_kvno] The key version number of this key. + +\item[key_data_type] The first element is the enctype of this key. In +a version 2 structure, the second element is the salttype of this key. +The legal encryption types are defined in $<$krb5.h$>$. The legal +salt types are defined in $<$k5-int.h$>$. + +\item[key_data_length] The first element is length this key. In a +version 2 structure, the second element is length of the salt for this +key. + +\item[key_data_contents] The first element is the content of this key. +In a version 2 structure, the second element is the contents of the +salt for this key. +\end{description} + +\subsection{Field masks} +\label{sec:masks} + +The API functions for creating, retrieving, and modifying principals +and policies allow for a relevant subset of the fields of the +kadm5_principal_ent_t and kadm5_policy_ent_t to be specified or +changed. The chosen fields are determined by a bitmask that is passed +to the relevant function. Each API function has different rules for +which mask values can be specified, and can specify whether a given +mask value is mandatory, optional, or forbidden. Mandatory fields +must be present and forbidden fields must not be present or an error +is generated. When creating a principal or policy, optional fields +have a default value if they are not specified. When modifying a +principal or policy, optional fields are unchanged if they are not +specified. When retrieving a principal, optional fields are simply +not provided if they are not specified; not specifying undeeded fields +for retrieval may improve efficiency. The values for forbidden fields +are defined in the function semantics. + +The masks for principals are in table \ref{tab:princ-bits} and the +masks for policies are in table \ref{tab:policy-bits}. They are +defined in $<$kadm5/admin.h$>$. The KADM5_ prefix has been removed +from the Name fields. In the Create and Modify fields, M means +mandatory, F means forbidden, and O means optional. Create fields +that are optional specify the default value. The notation ``K/M +value'' means that the field inherits its value from the corresponding +field in the Kerberos master principal, for KADM5_API_VERSION_1, and +from the configuration parameters for KADM5_API_VERSION_2. + +All masks for principals are optional for retrevial, {\it except} that +the KEY_DATA mask is illegal when specified by a remote client; for +details, see the function semantics for kadm5_get_principal. + +Note that the POLICY and POLICY_CLR bits are special. When POLICY is +set, the policy is assigned to the principal. When POLICY_CLR is +specified, the policy is unassigned to the principal and as a result +no policy controls the principal. + +For convenience, the mask KADM5_PRINCIPAL_NORMAL_MASK contains all of +the principal masks {\it except} KADM5_KEY_DATA and KADM5_TL_DATA, and +the mask KADM5_POLICY_NORMAL_MASK contains all of the policy masks. + +\begin{table}[htbp] +\begin{tabular}{@{}lclll} +{\bf Name} & {\bf Value} & {\bf Fields Affected} & {\bf Create} & + {\bf Modify} \\ +PRINCIPAL & 0x000001 & principal & M & F \\ +PRINC_EXPIRE_TIME & 0x000002 & princ_expire_time & O, K/M value & O \\ +PW_EXPIRATION & 0x000004 & pw_expiration & O, now+pw_max_life & O \\ +LAST_PWD_CHANGE & 0x000008 & last_pwd_change & F & F \\ +ATTRIBUTES & 0x000010 & attributes & O, 0 & O \\ +MAX_LIFE & 0x000020 & max_life & O, K/M value & O \\ +MOD_TIME & 0x000040 & mod_date & F & F \\ +MOD_NAME & 0x000080 & mod_name & F & F \\ +KVNO & 0x000100 & kvno & O, 1 & O \\ +MKVNO & 0x000200 & mkvno & F & F \\ +AUX_ATTRIBUTES & 0x000400 & aux_attributes & F & F \\ +POLICY & 0x000800 & policy & O, none & O \\ +POLICY_CLR & 0x001000 & policy & F & O \\ +MAX_RLIFE & 0x002000 & max_renewable_life & O, K/M value & O \\ +LAST_SUCCESS & 0x004000 & last_success & F & F \\ +LAST_FAILED & 0x008000 & last_failed & F & F \\ +FAIL_AUTH_COUNT & 0x010000 & fail_auth_count & F & O \\ +KEY_DATA & 0x020000 & n_key_data, key_data & F & F \\ +TL_DATA & 0x040000 & n_tl_data, tl_data & O, 0, NULL & O +\end{tabular} +\caption{Mask bits for creating, retrieving, and modifying principals.} +\label{tab:princ-bits} +\end{table} + +\begin{table}[htbp] +\begin{tabular}{@{}lclll} +Name & Value & Field Affected & Create & Modify \\ +POLICY & same & policy & M & F \\ +PW_MAX_LIFE & 0x004000 & pw_max_life & O, 0 (infinite) & O \\ +PW_MIN_LIFE & 0x008000 & pw_min_life & O, 0 & O \\ +PW_MIN_LENGTH & 0x010000 & pw_min_length & O, 1 & O \\ +PW_MIN_CLASSES & 0x020000 & pw_min_classes & O, 1 & O \\ +PW_HISTORY_NUM & 0x040000 & pw_history_num & O, 0 & O \\ +REF_COUNT & 0x080000 & pw_refcnt & F & F +\end{tabular} +\caption{Mask bits for creating/modifying policies.} +\label{tab:policy-bits} +\end{table} + +\section{Constants, Header Files, Libraries} + +$<$kadm5/admin.h$>$ includes a number of required header files, +including RPC, Kerberos 5, com_err, and admin com_err +defines. It contains prototypes for all kadm5 routines mentioned +below, as well as all Admin API data structures, type definitions and +defines mentioned in this document. + +Before \v{\#include}ing $<$kadm5/admin.h$>$, the programmer can +specify the API version number that the program will use by +\v{\#define}ing USE_KADM5_API_VERSION; for example, define that symbol +to be 1 to use KADM5_API_VERSION_1. This will ensure that the correct +functional prototypes and data structures are defined. If no version +symbol is defined, the most recent version supported by the header +files will be used. + +Some of the defines and their values contained in $<$kadm5/admin.h$>$ +include the following, whose KADM5_ prefixes have been removed. +Symbols that do not exist in KADM5_API_VERSION_2 do not have a KADM5_ +prefix, but instead retain only with OVSEC_KADM_ prefix for +compatibility. +\begin{description} +\item[admin service principal] ADMIN_SERVICE (``kadmin/admin'') +\item[admin history key] HIST_PRINCIPAL (``kadmin/history'') +\item[change password principal] CHANGEPW_SERVICE (``kadmin/changepw'') +\item[server acl file path] ACLFILE (``/krb5/ovsec_adm.acl''). In +KADM5_API_VERSION 2, this is controlled by configuration parameters. +\item[dictionary] WORDFILE (``/krb5/kadmind.dict''). In +KADM5_API_VERSION 2, this is controlled by configuration parameters. +\end{description} + +KADM5 errors are described in $<$kadm5/kadm_err.h$>$, which +is included by $<$kadm5/admin.h$>$. + +The locations of the admin policy and principal databases, as well as +defines and type definitions for the databases, are defined in +$<$kadm5/adb.h$>$. Some of the defines in that file are: +\begin{description} +\item[admin policy database] POLICY_DB (``/krb5/kadm5_policy.db''). In +KADM5_API_VERSION 2, this is controlled by configuration parameters. +\item[admin principal database] PRINCIPAL_DB +(``/krb5/ovsec_principal.db''). In KADM5_API_VERSION 2, this is +controlled by configuration parameters. +\end{description} + +Client applications will link against libkadm5clnt.a and server +programs against libkadm5srv.a. Client applications must also link +against: libgssapi_krb5.a, libkrb5.a, libcrypto.a, libgssrpc.a, +libcom_err.a, and libdyn.a. Server applications must also link +against: libkdb5.a, libkrb5.a, libcrypto.a, libgssrpc.a, libcom_err.a, +and libdyn.a. + +\section{Error Codes} + +The error codes that can be returned by admin functions are listed +below. Error codes indicated with a ``*'' can be returned by every +admin function and always have the same meaning; these codes are +omitted from the list presented with each function. + +The admin system guarantees that a function that returns an error code +has no other side effect. + +The Admin system will use \v{com_err} for error codes. Note that this +means \v{com_err} codes may be returned from functions that the admin +routines call (e.g. the kerberos library). Callers should not expect +that only KADM5 errors will be returned. The Admin system error code +table name will be ``ovk'', and the offsets will be the same as the +order presented here. As mentioned above, the error table include file +will be $<$kadm5/kadm_err.h$>$. + +Note that these error codes are also used as protocol error code +constants and therefore must not change between product releases. +Additional codes should be added at the end of the list, not in the +middle. The integer value of KADM5_FAILURE is 43787520; the +remaining values are assigned in sequentially increasing order. + +\begin{description} +\item[* KADM5_FAILURE] Operation failed for unspecified reason +\item[* KADM5_AUTH_GET] Operation requires ``get'' privilege +\item[* KADM5_AUTH_ADD] Operation requires ``add'' privilege +\item[* KADM5_AUTH_MODIFY] Operation requires ``modify'' privilege +\item[* KADM5_AUTH_DELETE] Operation requires ``delete'' privilege +\item[* KADM5_AUTH_INSUFFICIENT] Insufficient authorization for +operation +\item[* KADM5_BAD_DB] Database inconsistency detected +\item[KADM5_DUP] Principal or policy already exists +\item[KADM5_RPC_ERROR] Communication failure with server +\item[KADM5_NO_SRV] No administration server found for realm +\item[KADM5_BAD_HIST_KEY] Password history principal key version +mismatch +\item[KADM5_NOT_INIT] Connection to server not initialized +\item[KADM5_UNK_PRINC] Principal does not exist +\item[KADM5_UNK_POLICY] Policy does not exist +\item[KADM5_BAD_MASK] Invalid field mask for operation +\item[KADM5_BAD_CLASS] Invalid number of character classes +\item[KADM5_BAD_LENGTH] Invalid password length +\item[KADM5_BAD_POLICY] Illegal policy name +\item[KADM5_BAD_PRINCIPAL] Illegal principal name. +\item[KADM5_BAD_AUX_ATTR] Invalid auxiliary attributes +\item[KADM5_BAD_HISTORY] Invalid password history count +\item[KADM5_BAD_MIN_PASS_LIFE] Password minimum life is greater +then password maximum life +\item[KADM5_PASS_Q_TOOSHORT] Password is too short +\item[KADM5_PASS_Q_CLASS] Password does not contain enough +character classes +\item[KADM5_PASS_Q_DICT] Password is in the password dictionary +\item[KADM5_PASS_REUSE] Cannot reuse password +\item[KADM5_PASS_TOOSOON] Current password's minimum life has not +expired +\item[KADM5_POLICY_REF] Policy is in use +\item[KADM5_INIT] Connection to server already initialized +\item[KADM5_BAD_PASSWORD] Incorrect password +\item[KADM5_PROTECT_PRINCIPAL] Cannot change protected principal +\item[* KADM5_BAD_SERVER_HANDLE] Programmer error! Bad Admin server handle +\item[* KADM5_BAD_STRUCT_VERSION] Programmer error! Bad API structure version +\item[* KADM5_OLD_STRUCT_VERSION] API structure version specified by application is no longer supported (to fix, recompile application against current Admin API header files and libraries) +\item[* KADM5_NEW_STRUCT_VERSION] API structure version specified by application is unknown to libraries (to fix, obtain current Admin API header files and libraries and recompile application) +\item[* KADM5_BAD_API_VERSION] Programmer error! Bad API version +\item[* KADM5_OLD_LIB_API_VERSION] API version specified by application is no longer supported by libraries (to fix, update application to adhere to current API version and recompile) +\item[* KADM5_OLD_SERVER_API_VERSION] API version specified by application is no longer supported by server (to fix, update application to adhere to current API version and recompile) +\item[* KADM5_NEW_LIB_API_VERSION] API version specified by application is unknown to libraries (to fix, obtain current Admin API header files and libraries and recompile application) +\item[* KADM5_NEW_SERVER_API_VERSION] API version specified by +application is unknown to server (to fix, obtain and install newest +Admin Server) +\item[KADM5_SECURE_PRINC_MISSING] Database error! Required principal missing +\item[KADM5_NO_RENAME_SALT] The salt type of the specified principal +does not support renaming +\item[KADM5_BAD_CLIENT_PARAMS] Illegal configuration parameter for +remote KADM5 client +\item[KADM5_BAD_SERVER_PARAMS] Illegal configuration parameter for +local KADM5 client. +\item[KADM5_AUTH_LIST] Operation requires ``list'' privilege +\item[KADM5_AUTH_CHANGEPW] Operation requires ``change-password'' privilege +\item[KADM5_BAD_TL_TYPE] Programmer error! Illegal tagged data list +element type +\item[KADM5_MISSING_CONF_PARAMS] Required parameters in kdc.conf missing +\item[KADM5_BAD_SERVER_NAME] Bad krb5 admin server hostname +\item[KADM5_AUTH_SETKEY] Operation requires ``set-key'' privilege +\item[KADM5_SETKEY_DUP_ENCTYPES] Multiple values for single or folded enctype +\end{description} + +\section{Authentication and Authorization} +\label{sec:auth} + +Two Kerberos principals exist for use in communicating with the Admin +system: kadmin/admin and kadmin/changepw. Both principals +have the KRB5_KDB_DISALLOW_TGT_BASED bit set in their attributes so +that service tickets for them can only be acquired via a +password-based (AS_REQ) request. Additionally, kadmin/changepw +has the KRB5_KDB_PWCHANGE_SERVICE bit set so that a principal with an +expired password can still obtain a service ticket for it. + +The Admin system accepts requests that are authenticated to either +service principal, but the sets of operations that can be performed by +a request authenticated to each service are different. In particular, +only the functions chpass_principal, randkey_principal, get_principal, +and get_policy can be performed by a request authenticated to the +kadmin/changepw service, and they can only be performed when the +target principal of the operation is the same as the authenticated +client principal; the function semantics descriptions below give the +precise details. This means that administrative operations can only +be performed when authenticated to the kadmin/admin service. The +reason for this distinction is that tickets for kadmin/changepw can be +acquired with an expired password, and the KADM system does not want +to allow an administrator with an expired password to perform +administrative operations on arbitrary principals. + +Each Admin API operation authenticated to the kadmin/admin service +requires a specific authorization to run. This version uses a simple +named privilege system with the following names and meanings: + +\begin{description} +\item[Get] Able to examine the attributes (NOT key data) of principals +and policies. +\item[Add] Able to add principals and policies. +\item[Modify] Able to modify attributes of existing principals and +policies; this does not include changing passwords. +\item[Delete] Able to remove principals and policies. +\item[List] Able to retrieve a list of principals and policies. +\item[Changepw] Able to change the password of principals. +\item[Setkey] Able to set principal keys directly. +\end{description} + +Privileges are specified via an external configuration file on the +Kerberos master server. + +Table \ref{tab:func-overview} summarizes the authorization +requirements of each function. Additionally, each API function +description identifies the privilege required to perform it. The +Authorization checks only happen if you are using the RPC mechanism. +If you are using the server-side API functions locally on the admin +server, the only authorization check is if you can access the +approporiate local files. + +\section{Functions} + +\subsection{Overview} + +The functions provided by the Admin API, and the authorization they +require, are listed in the table \ref{tab:func-overview}. The +``kadm5_'' prefix has been removed from each function name. + +The function semantics in the following sections omit details that are +the same for every function. + +\begin{itemize} +\item The effects of every function are atomic. + +\item Every function performs an authorization check and returns +the appropriate KADM5_AUTH_* error code if the caller does not +have the required privilege. No other information or error code is +ever returned to an unauthorized user. + +\item Every function checks its arguments for NULL pointers or other +obviously invalid values, and returns EINVAL if any are detected. + +\item Any function that performs a policy check uses the policy named +in the principal's policy field. If the POLICY bit is not set in the +principal's aux_attributes field, however, the principal has no +policy, so the policy check is not performed. + +\item Unless otherwise specified, all functions return KADM5_OK. +\end{itemize} + +\begin{table}[htbp] +\caption{Summary of functions and required authorization.} +\label{tab:func-overview} +\begin{tabular}{@{}llp{3.24in}} +\\ +{\bf Function Name} & {\bf Authorization} & {\bf Operation} \\ + +init & none & Open a connection with the kadm5 library. OBSOLETE +but still provided---use init_with_password instead. \\ +init_with_password & none & Open a connection with the kadm5 +library using a password to obtain initial credentials. \\ +init_with_skey & none & Open a connection with the kadm5 library +using the keytab entry to obtain initial credentials. \\ +destroy & none & Close the connection with the kadm5 library. \\ +flush & none & Flush all database changes to disk; no-op when called +remotely. \\ +create_principal & add & Create a new principal. \\ +delete_principal & delete & Delete a principal. \\ +modify_principal & modify & Modify the attributes of an existing + principal (not password). \\ +rename_principal & add and delete & Rename a principal. \\ +get_principal & get\footnotemark & Retrieve a principal. \\ +get_principals & list & Retrieve some or all principal names. \\ +chpass_principal & changepw\footnotemark[\thefootnote] & + Change a principal's password. \\ +chpass_principal_util & changepw\footnotemark[\thefootnote] & Utility wrapper around chpass_principal. \\ +randkey_principal & changepw\footnotemark[\thefootnote] & + Randomize a principal's key. \\ +setkey_principal & setkey & Explicitly set a principal's keys. \\ +decrypt_key & none & Decrypt a principal key. \\ +create_policy & add & Create a new policy. \\ +delete_policy & delete & Delete a policy. \\ +modify_policy & modify & Modify the attributes of a policy. \\ +get_policy & get & Retrieve a policy. \\ +get_policies & list & Retrieve some or all policy names. \\ +free_principal_ent & none & Free the memory associated with an + kadm5_principal_ent_t. \\ +free_policy_ent & none & Free the memory associated with an + kadm5_policy_ent_t. \\ +get_privs & none & Return the caller's admin server privileges. +\end{tabular} +\end{table} +\footnotetext[\thefootnote]{These functions also allow a principal to +perform the operation on itself; see the function's semantics for +details.} + +\subsection{kadm5_init_*} + +In KADM5_API_VERSION 1: + +\begin{verbatim} +kadm5_ret_t kadm5_init_with_password(char *client_name, char *pass, + char *service_name, char *realm, + unsigned long struct_version, + unsigned long api_version, + void **server_handle) + +kadm5_ret_t kadm5_init_with_skey(char *client_name, char *keytab, + char *service_name, char *realm, + unsigned long struct_version, + unsigned long api_version, + void **server_handle) + +kadm5_ret_t kadm5_init(char *client_name, char *pass, + char *service_name, char *realm, + unsigned long struct_version, + unsigned long api_version, + void **server_handle) +\end{verbatim} + +In KADM5_API_VERSION 2: + +\begin{verbatim} +kadm5_ret_t kadm5_init_with_password(char *client_name, char *pass, + char *service_name, + kadm5_config_params *realm_params, + unsigned long struct_version, + unsigned long api_version, + void **server_handle) + +kadm5_ret_t kadm5_init_with_skey(char *client_name, char *keytab, + char *service_name, + kadm5_config_params *realm_params, + unsigned long struct_version, + unsigned long api_version, + void **server_handle) + +kadm5_ret_t kadm5_init(char *client_name, char *pass, + char *service_name, + kadm5_config_params *realm_params, + unsigned long struct_version, + unsigned long api_version, + void **server_handle) + +kadm5_ret_t kadm5_init_with_creds(char *client_name, + krb5_ccache ccache, + char *service_name, + kadm5_config_params *params, + krb5_ui_4 struct_version, + krb5_ui_4 api_version, + void **server_handle) +\end{verbatim} + +AUTHORIZATION REQUIRED: none + +NOTE: kadm5_init is an obsolete function provided for backwards +compatibility. It is identical to kadm5_init_with_password. + +These three functions open a connection to the kadm5 library and +initialize any necessary state information. They behave differently +when called from local and remote clients. + +In KADM5_API_VERSION_2, these functions take a kadm5_config_params +structure instead of a realm name as an argument. The semantics are +similar: if a NULL pointer is passed for the realm_params argument, +the default realm and default parameters for that realm, as specified +in the krb5 configuration file (e.g. /etc/krb5.conf) are used. If a +realm_params structure is provided, the fields that are set override +the default values. If a parameter is specified to the local or +remote libraries that does not apply to that side, an error code +(KADM5_BAD_CLIENT_PARAMS or KADM5_BAD_SERVER_PARAMS) is returned. See +section \ref{sec:configparams} for a discussion of configuration +parameters. + +For remote clients, the semantics are: + +\begin{enumerate} +\item Initializes all the com_err error tables used by the Admin +system. + +\item Acquires configuration parameters. In KADM5_API_VERSION_1, all +the defaults specified in the configuration file are used, according +to the realm. In KADM5_API_VERSION_2, the values in params_in are +merged with the default values. If an illegal mask value is +specified, KADM5_BAD_CLIENT_PARAMS is returned. + +\item Acquires a Kerberos ticket for the specified service. + +\begin{enumerate} +\item The ticket's client is client_name, which can be any valid +Kerberos principal. If client_name does not include a realm, the +default realm of the local host is used +\item The ticket's service is service_name@realm. service_name must +be one of the constants KADM5_ADMIN_SERVICE or +KADM5_CHANGEPW_SERVICE. +\item If realm is NULL, client_name's realm is used. + +\item For init_with_password, an initial ticket is acquired and +decoded with the password pass, which must be client_name's password. +If pass is NULL or an empty string, the user is prompted (via the tty) +for a password. + +\item For init_with_skey, an initial ticket is acquired and decoded +with client_name's key obtained from the specified keytab. If keytab +is NULL or an empty string the default keytab is used. + +\item For init_with_creds, ccache must be an open credential cache +that already has a ticket for the specified client and server. +Alternatively, if a site chooses to disable the DISALLOW_TGT_BASED +flag on the admin and changepw principals, the ccache can contain a +ticket-granting ticket for client_name. +\end{enumerate} + +\item Creates a GSS-API authenticated connection to the Admin server, +using the just-acquired Kerberos ticket. + +\item Verifies that the struct_version and api_version specified by +the caller are valid and known to the library. + +\item Sends the specified api_version to the server. + +\item Upon successful completion, fills in server_handle with a handle +for this connection, to be used in all subsequent API calls. +\end{enumerate} + +The caller should always specify KADM5_STRUCT_VERSION for the +struct_version argument, a valid and supported API version constant +for the api_version argument (currently, KADM5_API_VERSION_1 or +KADM5_API_VERSION_2), and a valid pointer in which the server handle +will be stored. + +If any kadm5_init_* is invoked locally its semantics are: + +\begin{enumerate} +\item Initializes all the com_err error tables used by the Admin +system. + +\item Acquires configuration parameters. In KADM5_API_VERSION_1, all +the defaults specified in the configuration file are used, according +to the realm. In KADM5_API_VERSION_2, the values in params_in are +merged with the default values. If an illegal mask value is +specified, KADM5_BAD_SERVER_PARAMS is returned. + +\item Initializes direct access to the KDC database. In +KADM5_API_VERISON_1, if pass (or keytab) is NULL or an empty string, +reads the master password from the stash file; otherwise, the non-NULL +password is ignored and the user is prompted for it via the tty. In +KADM5_API_VERSION_2, if the MKEY_FROM_KEYBOARD parameter mask is set +and the value is non-zero, reads the master password from the user via +the tty; otherwise, the master key is read from the stash file. +Calling init_with_skey or init_with_creds with the MKEY_FROM_KEYBOARD +mask set with a non-zero field is illegal, and calling them without +the mask set is exactly like calling init_with_password. + +\item Initializes the dictionary (if present) for dictionary checks. + +\item Parses client_name as a Kerberos principal. client_name should +usually be specified as the name of the program. + +\item Verifies that the struct_version and api_version specified by +the caller are valid. + +\item Fills in server_handle with a handle containing all state +information (version numbers and client name) for this ``connection.'' +\end{enumerate} +The service_name argument is not used. + +RETURN CODES: + +\begin{description} +\item[KADM5_NO_SRV] No Admin server can be found for the +specified realm. + +\item[KADM5_RPC_ERROR] The RPC connection to the server cannot be +initiated. + +\item[KADM5_BAD_PASSWORD] Incorrect password. + +\item[KADM5_SECURE_PRINC_MISSING] The principal +KADM5_ADMIN_SERVICE or KADM5_CHANGEPW_SERVICE does not +exist. This is a special-case replacement return code for ``Server +not found in database'' for these required principals. + +\item[KADM5_BAD_CLIENT_PARAMS] A field in the parameters mask was +specified to the remote client library that is not legal for remote +clients. + +\item[KADM5_BAD_SERVER_PARAMS] A field in the parameters mask was +specified to the local client library that is not legal for local +clients. +\end{description} + +\subsection{kadm5_flush} + +\begin{verbatim} +kadm5_ret_t kadm5_flush(void *server_handle) +\end{verbatim} + +AUTHORIZATION REQUIRED: none + +Flush all changes to the Kerberos databases, leaving the connection to +the Admin API open. This function behaves differently when called by +local and remote clients. + +For local clients, the function closes and reopens the Kerberos +database with krb5_db_fini() and krb5_db_init(). +Although it is unlikely, either of these functions +could return errors; in that case, this function calls +kadm5_destroy and returns the error code. Therefore, if +kadm5_flush does not return KADM5_OK, the connection to the +Admin server has been terminated and, in principle, the databases +might be corrupt. + +For remote clients, the function is a no-op. + +\subsection{kadm5_destroy} + +\begin{verbatim} +kadm5_ret_t kadm5_destroy(void *server_handle) +\end{verbatim} + +AUTHORIZATION REQUIRED: none + +Close the connection to the Admin server and releases all related +resources. This function behaves differently when called by local and +remote clients. + +For remote clients, the semantics are: + +\begin{enumerate} +\item Destroy the temporary credential cache created by +kadm5_init. + +\item Tear down the GSS-API context negotiated with the server. + +\item Close the RPC connection. + +\item Free storage space associated with server_handle, after erasing +its magic number so it won't be mistaken for a valid handle by the +library later. +\end{enumerate} + +For local clients, this function just frees the storage space +associated with server_handle after erasing its magic number. + +RETURN CODES: + +\subsection{kadm5_create_principal} + +\begin{verbatim} +kadm5_ret_t +kadm5_create_principal(void *server_handle, + kadm5_principal_ent_t princ, u_int32 mask, + char *pw); +\end{verbatim} + +AUTHORIZATION REQUIRED: add + +\begin{enumerate} + +\item Return KADM5_BAD_MASK if the mask is invalid. +\item If the named principal exists, return KADM5_DUP. +\item If the POLICY bit is set and the named policy does not exist, +return KADM5_UNK_POLICY. +\item If KADM5_POLICY bit is set in aux_attributes check to see if +the password does not meets quality standards, return the appropriate +KADM5_PASS_Q_* error code if it fails. +\item Store the principal, set the key; see section \ref{sec:keys}. +\item If the POLICY bit is set, increment the named policy's reference +count by one. + +\item Set the pw_expiration field. +\begin{enumerate} +\item If the POLICY bit is set in mask, then if pw_max_life is non-zero, +set pw_expiration to now + pw_maxlife, otherwise set pw_max_life to +never. +\item If the PW_EXPIRATION bit is set in mask, set pw_expiration to +the requested value, overriding the value set above. +\end{enumerate} +NOTE: This is a change from the original semantics, in which policy +expiration was enforced even on administrators. The old semantics are +not preserved, even for version 1 callers, because this is a +server-specific policy decision; besides, the new semantics are less +restrictive, so all previous callers should continue to function +properly. + +\item Set mod_date to now and set mod_name to caller. +\item Set last_pwd_change to now. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_BAD_MASK] The field mask is invalid for a create +operation. +\item[KADM5_DUP] Principal already exists. +\item[KADM5_UNK_POLICY] Policy named in entry does not exist. +\item[KADM5_PASS_Q_*] Specified password does not meet policy +standards. +\end{description} + +\subsection{kadm5_delete_principal} + +\begin{verbatim} +kadm5_ret_t +kadm5_delete_principal(void *server_handle, krb5_principal princ); +\end{verbatim} + +AUTHORIZATION REQUIRED: delete + +\begin{enumerate} +\item Return KADM5_UNK_PRINC if the principal does not exist. +\item If the POLICY bit is set in aux_attributes, decrement the named +policy's reference count by one. +\item Delete principal. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Principal does not exist. +\end{description} + +\subsection{kadm5_modify_principal} + +\begin{verbatim} +kadm5_ret_t +kadm5_modify_principal(void *server_handle, + kadm5_principal_ent_t princ, u_int32 mask); +\end{verbatim} + +Modify the attributes of the principal named in +kadm5_principal_ent_t. This does not allow the principal to be +renamed or for its password to be changed. + +AUTHORIZATION REQUIRED: modify + +Although a principal's pw_expiration is usually computed based on its +policy and the time at which it changes its password, this function +also allows it to be specified explicitly. This allows an +administrator, for example, to create a principal and assign it to a +policy with a pw_max_life of one month, but to declare that the new +principal must change its password away from its initial value +sometime within the first week. + +\begin{enumerate} +\item Return KADM5_UNK_PRINC if the principal does not exist. +\item Return KADM5_BAD_MASK if the mask is invalid. +\item If POLICY bit is set but the new policy does not exist, return +KADM5_UNK_POLICY. +\item If either the POLICY or POLICY_CLR bits are set, update the +corresponding bits in aux_attributes. + +\item Update policy reference counts. +\begin{enumerate} +\item If the POLICY bit is set, then increment policy count on new +policy. +\item If the POLICY or POLICY_CLR bit is set, and the POLICY bit in +aux_attributes is set, decrement policy count on old policy. +\end{enumerate} + +\item Set pw_expiration appropriately. pw_expiration can change if: +the POLICY bit is set in mask, so the principal is changing to a +policy (either from another policy or no policy); the POLICY_CLR bit +is set in mask, so the principal is changing to no policy; or +PW_EXPIRATION is set. +\begin{enumerate} +\item If the POLICY bit is set in mask, set pw_expiration to +last_pwd_change + pw_max_life if pw_max_life is non-zero, otherwise +set pw_expiration to never. +\item If the POLICY_CLR biti s set in mask, set pw_expiration to +never. +\item If PW_EXPIRATION is set, set pw_expiration to the requested +value, overriding the value from the previous two cases. NOTE: This +is a change from the original semantics, in which policy expiration +was enforced even on administrators. The old semantics are not +preserved, even for version 1 callers, because this is a +server-specific policy decision; besides, the new semantics are less +restrictive, so all previous callers should continue to function +properly. +\end{enumerate} + +% Here is the previous, and confusing, text of pw_expiration semantics: +%\begin{enumerate} +%\item If the POLICY bit is not set in aux_attributes, then +%\begin{enumerate} +%\item if the PW_EXPIRATION bit is set, set pw_expiration to the given +%value, else +%\item set pw_expiration to never. +%\end{enumerate} +%\item Otherwise, if the PW_EXPIRATION bit is set, set pw_expiration to +%the sooner of the given value and last_pwd_change + pw_max_life. +%\item Otherwise, set pw_expiration to last_pwd_change + pw_max_life. +%\end{enumerate} + +\item Update the remaining fields specified in the mask. +\item Update mod_name field to caller and mod_date to now. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Entry does not exist. +\item[KADM5_BAD_MASK] The mask is not valid for a modify +operation. +\item[KADM5_UNK_POLICY] The POLICY bit is set but the new +policy does not exist. +\item[KADM5_BAD_TL_TYPE] The KADM5_TL_DATA bit is set in mask, and the +given tl_data list contains an element whose type is less than 256. +\end{description} + +\subsection{kadm5_rename_principal} + +\begin{verbatim} +kadm5_ret_t +kadm5_rename_principal(void *server_handle, krb5_principal source, + krb5_principal target); +\end{verbatim} + +AUTHORIZATION REQUIRED: add and delete + +\begin{enumerate} +\item Check to see if source principal exists, if not return +KADM5_UNK_PRINC error. +\item Check to see if target exists, if so return KADM5_DUP error. +\item Create the new principal named target, then delete the old +principal named source. All of target's fields will be the same as +source's fields, except that mod_name and mod_date will be updated to +reflect the current caller and time. +\end{enumerate} + +Note that since the principal name may have been used as the salt for +the principal's key, renaming the principal may render the principal's +current password useless; with the new salt, the key generated by +string-to-key on the password will suddenly be different. Therefore, +an application that renames a principal must also require the user to +specify a new password for the principal (and administrators should +notify the affected party). + +Note also that, by the same argument, renaming a principal will +invalidate that principal's password history information; since the +salt will be different, a user will be able to select a previous +password without error. + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Source principal does not exist. +\item[KADM5_DUP] Target principal already exist. +\end{description} + +\subsection{kadm5_chpass_principal} + +\begin{verbatim} +kadm5_ret_t +kadm5_chpass_principal(void *server_handle, krb5_principal princ, + char *pw); +\end{verbatim} + +AUTHORIZATION REQUIRED: changepw, or the calling principal being the +same as the princ argument. If the request is authenticated to the +kadmin/changepw service, the changepw privilege is disregarded. + +Change a principal's password. See section \ref{sec:keys} for a +description of how the keys are determined. + +This function enforces password policy and dictionary checks. If the new +password specified is in the password dictionary, and the policy bit is set +KADM5_PASS_DICT is returned. If the principal's POLICY bit is set in +aux_attributes, compliance with each of the named policy fields is verified +and an appropriate error code is returned if verification fails. + +Note that the policy checks are only be performed if the POLICY bit is +set in the principal's aux_attributes field. + +\begin{enumerate} +\item Make sure principal exists, if not return KADM5_UNK_PRINC error. +\item If caller does not have modify privilege, (now - last_pwd_change) $<$ +pw_min_life, and the KRB5_KDB_REQUIRES_PWCHANGE bit is not set in the +principal's attributes, return KADM5_PASS_TOOSOON. +\item If the principal your are trying to change is kadmin/history +return KADM5_PROTECT_PRINCIPAL. +\item If the password does not meet the quality +standards, return the appropriate KADM5_PASS_Q_* error code. +\item Convert password to key; see section \ref{sec:keys}. +\item If the new key is in the principal's password history, return +KADM5_PASS_REUSE. +\item Store old key in history. +\item Update principal to have new key. +\item Increment principal's key version number by one. +\item If the POLICY bit is set, set pw_expiration to now + +max_pw_life. If the POLICY bit is not set, set pw_expiration to +never. +\item If the KRB5_KDB_REQUIRES_PWCHANGE bit is set in the principal's +attributes, clear it. +\item Update last_pwd_change and mod_date to now, update mod_name to +caller. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Principal does not exist. +\item[KADM5_PASS_Q_*] Requested password does not meet quality +standards. +\item[KADM5_PASS_REUSE] Requested password is in user's +password history. +\item[KADM5_PASS_TOOSOON] Current password has not reached minimum life +\item[KADM5_PROTECT_PRINCIPAL] Cannot change the password of a special principal +\end{description} + + +\subsection{kadm5_chpass_principal_util} + +\begin{verbatim} +kadm5_ret_t +kadm5_chpass_principal_util(void *server_handle, krb5_principal princ, + char *new_pw, char **pw_ret, + char *msg_ret); +\end{verbatim} + +AUTHORIZATION REQUIRED: changepw, or the calling principal being the +same as the princ argument. If the request is authenticated to the +kadmin/changepw service, the changepw privilege is disregarded. + +This function is a wrapper around kadm5_chpass_principal. It can +read a new password from a user, change a principal's password, and +return detailed error messages. msg_ret should point to a char buffer +in the caller's space of sufficient length for the error messages +described below. 1024 bytes is recommended. It will also return the +new password to the caller if pw_ret is non-NULL. + +\begin{enumerate} +\item If new_pw is NULL, this routine will prompt the user for the new +password (using the strings specified by KADM5_PW_FIRST_PROMPT and +KADM5_PW_SECOND_PROMPT) and read (without echoing) the password input. +Since it is likely that this will simply call krb5_read_password only +terminal-based applications will make use of the password reading +functionality. If the passwords don't match the string ``New passwords do +not match - password not changed.'' will be copied into msg_ret, and the +error code KRB5_LIBOS_BADPWDMATCH will be returned. For other errors that +occur while reading the new password, copy the string ``$ +occurred while trying to read new password.'' followed by a blank line and +the string specified by CHPASS_UTIL_PASSWORD_NOT_CHANGED into msg_ret and +return the error code returned by krb5_read_password. + +\item If pw_ret is non-NULL, and the password was prompted, set *pw_ret to +point to a static buffer containing the password. If pw_ret is non-NULL +and the password was supplied, set *pw_ret to the supplied password. + +\item Call kadm5_chpass_principal with princ, and new_pw. + +\item If successful copy the string specified by CHPASS_UTIL_PASSWORD_CHANGED +into msg_ret and return zero. + +\item For a policy related failure copy the appropriate message (from below) +followed by a newline and ``Password not changed.'' into msg_ret +filling in the parameters from the principal's policy information. If +the policy information cannot be obtained copy the generic message if +one is specified below. Return the error code from +kadm5_chpass_principal. + +Detailed messages: +\begin{description} + +\item[PASS_Q_TOO_SHORT] +New password is too short. Please choose a +password which is more than $<$pw-min-len$>$ characters. + +\item[PASS_Q_TOO_SHORT - generic] +New password is too short. Please choose a longer password. + +\item[PASS_REUSE] +New password was used previously. Please choose a +different password. + +\item[PASS_Q_CLASS] +New password does not have enough character classes. Classes include +lower class letters, upper case letters, digits, punctuation and all +other characters. Please choose a password with at least +$<$min-classes$>$ character classes. + +\item[PASS_Q_CLASS - generic] +New password does not have enough character classes. Classes include +lower class letters, upper case letters, digits, punctuation and all +other characters. + +\item[PASS_Q_DICT] +New password was found in a dictionary of possible passwords and +therefore may be easily guessed. Please choose another password. See +the kpasswd man page for help in choosing a good password. + +\item[PASS_TOOSOON] +Password cannot be changed because it was changed too recently. Please +wait until $<$last-pw-change+pw-min-life$>$ before you change it. If you +need to change your password before then, contact your system +security administrator. + +\item[PASS_TOOSOON - generic] +Password cannot be changed because it was changed too recently. If you +need to change your now please contact your system security +administrator. +\end{description} + +\item For other errors copy the string ``$<$com_err message$>$ +occurred while trying to change password.'' following by a blank line +and ``Password not changed.'' into msg_ret. Return the error code +returned by kadm5_chpass_principal. +\end{enumerate} + + +RETURN CODES: + +\begin{description} +\item[KRB5_LIBOS_BADPWDMATCH] Typed new passwords did not match. +\item[KADM5_UNK_PRINC] Principal does not exist. +\item[KADM5_PASS_Q_*] Requested password does not meet quality +standards. +\item[KADM5_PASS_REUSE] Requested password is in user's +password history. +\item[KADM5_PASS_TOOSOON] Current password has not reached minimum +life. +\end{description} + +\subsection{kadm5_randkey_principal} + +In KADM5_API_VERSION_1: + +\begin{verbatim} +kadm5_ret_t +kadm5_randkey_principal(void *server_handle, krb5_principal princ, + krb5_keyblock **new_key) +\end{verbatim} + +In KADM5_API_VERSION_2: + +\begin{verbatim} +kadm5_ret_t +kadm5_randkey_principal(void *server_handle, krb5_principal princ, + krb5_keyblock **new_keys, int *n_keys) +\end{verbatim} + +AUTHORIZATION REQUIRED: changepw, or the calling principal being the +same as the princ argument. If the request is authenticated to the +kadmin/changepw service, the changepw privilege is disregarded. + +Generate and assign a new random key to the named principal, and +return the generated key in allocated storage. In +KADM5_API_VERSION_2, multiple keys may be generated and returned as an +array, and n_new_keys is filled in with the number of keys generated. +See section \ref{sec:keys} for a description of how the keys are +chosen. In KADM5_API_VERSION_1, the caller must free the returned +krb5_keyblock * with krb5_free_keyblock. In KADM5_API_VERSION_2, the +caller must free each returned keyblock with krb5_free_keyblock. + +If the principal's POLICY bit is set in aux_attributes and the caller does +not have modify privilege , compliance with the password minimum life +specified by the policy is verified and an appropriate error code is returned +if verification fails. + +\begin{enumerate} +\item If the principal does not exist, return KADM5_UNK_PRINC. +\item If caller does not have modify privilege, (now - last_pwd_change) $<$ +pw_min_life, and the KRB5_KDB_REQUIRES_PWCHANGE bit is not set in the +principal's attributes, return KADM5_PASS_TOOSOON. +\item If the principal you are trying to change is kadmin/history return +KADM5_PROTECT_PRINCIPAL. +\item Store old key in history. +\item Update principal to have new key. +\item Increment principal's key version number by one. +\item If the POLICY bit in aux_attributes is set, set pw_expiration to +now + max_pw_life. +\item If the KRB5_KDC_REQUIRES_PWCHANGE bit is set in the principal's +attributes, clear it. +\item Update last_pwd_change and mod_date to now, update mod_name to +caller. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Principal does not exist. +\item[KADM5_PASS_TOOSOON] The minimum lifetime for the current +key has not expired. +\item[KADM5_PROTECT_PRINCIPAL] Cannot change the password of a special +principal +\end{description} + +This function can also be used as part of a sequence to create a new +principal with a random key. The steps to perform the operation +securely are + +\begin{enumerate} +\item Create the principal with kadm5_create_principal with a +random password string and with the KRB5_KDB_DISALLOW_ALL_TIX bit set +in the attributes field. + +\item Randomize the principal's key with kadm5_randkey_principal. + +\item Call kadm5_modify_principal to reset the +KRB5_KDB_DISALLOW_ALL_TIX bit in the attributes field. +\end{enumerate} + +The three steps are necessary to ensure secure creation. Since an +attacker might be able to guess the initial password assigned by the +client program, the principal must be disabled until the key can be +truly randomized. + +\subsection{kadm5_setkey_principal} + +\begin{verbatim} +kadm5_ret_t +kadm5_setkey_principal(void *server_handle, krb5_principal princ, + krb5_keyblock *new_keys, int n_keys) +\end{verbatim} + +AUTHORIZATION REQUIRED: setkey. This function does not allow the use +of regular changepw authorization because it bypasses the password +policy mechanism. + +This function only exists in KADM5_API_VERSION_2. + +Explicitly sets the specified principal's keys to the n_keys keys in +the new_keys array. The keys in new_keys should not be encrypted in +the Kerberos master key; this function will perform that operation +itself (the keys will be protected during transmission from the +calling client to the kadmind server by the AUTH_GSSAPI RPC layer). +This function completely bypasses the principal's password policy, if +set. + +\begin{enumerate} +\item If the principal does not exist, return KADM5_UNK_PRINC. +\item If the principal you are trying to change is kadmin/history return +KADM5_PROTECT_PRINCIPAL. +\item If new_keys contains more than one key of any ENCTYPE_DES_CBC_* +type that is folded, return KADM5_SETKEY_DUP_ENCTYPES. +\item Store old key in history. +\item Update principal to have new key. +\item Increment principal's key version number by one. +\item If the POLICY bit in aux_attributes is set, set pw_expiration to +now + max_pw_life. +\item If the KRB5_KDC_REQUIRES_PWCHANGE bit is set in the principal's +attributes, clear it. +\item Update last_pwd_change and mod_date to now, update mod_name to +caller. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Principal does not exist. +\item[KADM5_PROTECT_PRINCIPAL] Cannot change the password of a special +principal +\end{description} + +This function can also be used as part of a sequence to create a new +principal with an explicitly key. The steps to perform the operation +securely are + +\begin{enumerate} +\item Create the principal with kadm5_create_principal with a +random password string and with the KRB5_KDB_DISALLOW_ALL_TIX bit set +in the attributes field. + +\item Set the principal's key with kadm5_setkey_principal. + +\item Call kadm5_modify_principal to reset the +KRB5_KDB_DISALLOW_ALL_TIX bit in the attributes field. +\end{enumerate} + +The three steps are necessary to ensure secure creation. Since an +attacker might be able to guess the initial password assigned by the +client program, the principal must be disabled until the key can be +truly randomized. + +\subsection{kadm5_get_principal} + +In KADM5_API_VERSION_1: + +\begin{verbatim} +kadm5_ret_t +kadm5_get_principal(void *server_handle, krb5_principal princ, + kadm5_principal_ent_t *ent); +\end{verbatim} + +In KADM5_API_VERSION_2: + +\begin{verbatim} +kadm5_ret_t +kadm5_get_principal(void *server_handle, krb5_principal princ, + kadm5_principal_ent_t ent, u_int32 mask); +\end{verbatim} + +AUTHORIZATION REQUIRED: get, or the calling principal being the same +as the princ argument. If the request is authenticated to the +kadmin/changepw service, the get privilege is disregarded. + +In KADM5_API_VERSION_1, return all of the principal's attributes in +allocated memory; if an error is returned entry is set to NULL. In +KADM5_API_VERSION_2, fill in the fields of the principal structure +specified in the mask; memory for the structure is not allocated. +Typically, a caller will specify the mask KADM5_PRINCIPAL_NORMAL_MASK, +which includes all the fields {\it except} key_data and tl_data to +improve time and memory efficiency. A caller that wants key_data and +tl_data can bitwise-OR those masks onto NORMAL_MASK. Note that even +if KADM5_TL_DATA is specified, this function will not return internal +tl_data elements whose type is less than 256. + +The caller must free the returned entry with kadm5_free_principal_ent. + +The function behaves differently for local and remote clients. For +remote clients, the KEY_DATA mask is illegal and results in a +KADM5_BAD_MASK error. + +RETURN CODES: + +\begin{description} +\item[KADM5_UNK_PRINC] Principal does not exist. +\item[KADM5_BAD_MASK] The mask is not valid for a get operation. + +\end{description} + +\subsection{kadm5_decyrpt_key} + +\begin{verbatim} +kadm5_ret_t kadm5_decrypt_key(void *server_handle, + kadm5_principal_ent_t entry, krb5_int32 + ktype, krb5_int32 stype, krb5_int32 + kvno, krb5_keyblock *keyblock, + krb5_keysalt *keysalt, int *kvnop) +\end{verbatim} + +AUTHORIZATION REQUIRED: none, local function + +Searches a principal's key_data array to find a key with the specified +enctype, salt type, and kvno, and decrypts the key into keyblock and +keysalt if found. entry must have been returned by +kadm5_get_principal with at least the KADM5_KEY_DATA mask set. +Returns ENOENT if the key cannot be found, EINVAL if the key_data +array is empty (as it always is in an RPC client). + +If ktype or stype is -1, it is ignored for the search. If kvno is -1, +ktype and stype are ignored and the key with the max kvno is returned. +If kvno is 0, only the key with the max kvno is returned and only if +it matches the ktype and stype; otherwise, ENOENT is returned. + +\subsection{kadm5_get_principals} + +\begin{verbatim} +kadm5_ret_t +kadm5_get_principals(void *server_handle, char *exp, + char ***princs, int *count) +\end{verbatim} + +Retrieves the list of principal names. + +AUTHORIZATION REQUIRED: list + +If \v{exp} is NULL, all principal names are retrieved; otherwise, +principal names that match the expression exp are retrieved. +\v{princs} is filled in with a pointer to a NULL-terminated array of +strings, and \v{count} is filled in with the number of principal names +in the array. \v{princs} must be freed with a call to +\v{kadm5_free_name_list}. + +All characters in the expression match themselves except ``?'' which +matches any single character, ``*'' which matches any number of +consecutive characters, and ``[chars]'' which matches any single +character of ``chars''. Any character which follows a ``$\backslash$'' +matches itself exactly, and a ``$\backslash$'' cannot be the last +character in the string. + +\subsection{kadm5_create_policy} + +\begin{verbatim} +kadm5_ret_t +kadm5_create_policy(void *server_handle, + kadm5_policy_ent_t policy, u_int32 mask); +\end{verbatim} + +Create a new policy. + +AUTHORIZATION REQUIRED: add + +\begin{enumerate} +\item Check to see if mask is valid, if not return KADM5_BAD_MASK error. +\item Return KADM5_BAD_POLICY if the policy name contains illegal +characters. + +\item Check to see if the policy already exists, if so return +KADM5_DUP error. +\item If the PW_MIN_CLASSES bit is set and pw_min_classes is not 1, 2, +3, 4, or 5, return KADM5_BAD_CLASS. +\item Create a new policy setting the appropriate fields determined +by the mask. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_DUP] Policy already exists +\item[KADM5_BAD_MASK] The mask is not valid for a create +operation. +\item[KADM5_BAD_CLASS] The specified number of character classes +is invalid. +\item[KADM5_BAD_POLICY] The policy name contains illegal characters. +\end{description} + +\subsection{kadm5_delete_policy} + +\begin{verbatim} +kadm5_ret_t +kadm5_delete_policy(void *server_handle, char *policy); +\end{verbatim} + +Deletes a policy. + +AUTHORIZATION REQUIRED: delete + +\begin{enumerate} +\item Return KADM5_BAD_POLICY if the policy name contains illegal +characters. +\item Return KADM5_UNK_POLICY if the named policy does not exist. +\item Return KADM5_POLICY_REF if the named policy's refcnt is not 0. +\item Delete policy. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_BAD_POLICY] The policy name contains illegal characters. +\item[KADM5_UNK_POLICY] Policy does not exist. +\item[KADM5_POLICY_REF] Policy is being referenced. +\end{description} + +\subsection{kadm5_modify_policy} + +\begin{verbatim} +kadm5_ret_t +kadm5_modify_policy(void *server_handle, + kadm5_policy_ent_t policy, u_int32 mask); +\end{verbatim} + +Modify an existing policy. Note that modifying a policy has no affect +on a principal using the policy until the next time the principal's +password is changed. + +AUTHORIZATION REQUIRED: modify + +\begin{enumerate} +\item Return KADM5_BAD_POLICY if the policy name contains illegal +characters. +\item Check to see if mask is legal, if not return KADM5_BAD_MASK error. +\item Check to see if policy exists, if not return +KADM5_UNK_POLICY error. +\item If the PW_MIN_CLASSES bit is set and pw_min_classes is not 1, 2, +3, 4, or 5, return KADM5_BAD_CLASS. +\item Update the fields specified in the mask. +\end{enumerate} + +RETURN CODES: + +\begin{description} +\item[KADM5_BAD_POLICY] The policy name contains illegal characters. +\item[KADM5_UNK_POLICY] Policy not found. +\item[KADM5_BAD_MASK] The mask is not valid for a modify +operation. +\item[KADM5_BAD_CLASS] The specified number of character classes +is invalid. +\end{description} + +\subsection{kadm5_get_policy} + +In KADM5_API_VERSION_1: + +\begin{verbatim} +kadm5_ret_t +kadm5_get_policy(void *server_handle, char *policy, kadm5_policy_ent_t *ent); +\end{verbatim} + +In KADM5_API_VERSION_2: + +\begin{verbatim} +kadm5_ret_t +kadm5_get_policy(void *server_handle, char *policy, kadm5_policy_ent_t ent); +\end{verbatim} + +AUTHORIZATION REQUIRED: get, or the calling principal's policy being +the same as the policy argument. If the request is authenticated to +the kadmin/changepw service, the get privilege is disregarded. + +In KADM5_API_VERSION_1, return the policy's attributes in allocated +memory; if an error is returned entry is set to NULL. In +KADM5_API_VERSION_2, fill in fields of the policy structure allocated +by the caller. The caller must free the returned entry with +kadm5_free_policy_ent + +RETURN CODES: + +\begin{description} +\item[KADM5_BAD_POLICY] The policy name contains illegal characters. +\item[KADM5_UNK_POLICY] Policy not found. +\end{description} + +\subsection{kadm5_get_policies} + +\begin{verbatim} +kadm5_ret_t +kadm5_get_policies(void *server_handle, char *exp, + char ***pols, int *count) +\end{verbatim} + +Retrieves the list of principal names. + +AUTHORIZATION REQUIRED: list + +If \v{exp} is NULL, all principal names are retrieved; otherwise, +principal names that match the expression exp are retrieved. \v{pols} +is filled in with a pointer to a NULL-terminated array of strings, and +\v{count} is filled in with the number of principal names in the +array. \v{pols} must be freed with a call to +\v{kadm5_free_name_list}. + +All characters in the expression match themselves except ``?'' which +matches any single character, ``*'' which matches any number of +consecutive characters, and ``[chars]'' which matches any single +character of ``chars''. Any character which follows a ``$\backslash$'' +matches itself exactly, and a ``$\backslash$'' cannot be the last +character in the string. + +\subsection{kadm5_free_principal_ent, _policy_ent} + +\begin{verbatim} +void kadm5_free_principal_ent(void *server_handle, + kadm5_principal_ent_t princ); +\end{verbatim} + +In KADM5_API_VERSION_1, free the structure and contents allocated by a +call to kadm5_get_principal. In KADM5_API_VERSION_2, free the +contents allocated by a call to kadm5_get_principal. + +AUTHORIZATION REQUIRED: none (local operation) + +\begin{verbatim} +void kadm5_free_policy_ent(kadm5_policy_ent_t policy); +\end{verbatim} + +Free memory that was allocated by a call to kadm5_get_policy. If +the argument is NULL, the function returns successfully. + +AUTHORIZATION REQUIRED: none (local operation) + +\subsection{kadm5_free_name_list} + +\begin{verbatim} +void kadm5_free_name_list(void *server_handle, + char **names, int *count); +\end{verbatim} + +Free the memory that was allocated by kadm5_get_principals or +kadm5_get_policies. names and count must be a matched pair of +values returned from one of those two functions. + +\subsection{kadm5_free_key_data} + +\begin{verbatim} +void kadm5_free_key_data(void *server_handle, + krb5_int16 *n_key_data, krb5_key_data *key_data) +\end{verbatim} + +Free the memory that was allocated by kadm5_randkey_principal. +n_key_data and key_data must be a matched pair of values returned from +that function. + +\subsection{kadm5_get_privs} + +\begin{verbatim} +kadm5_ret_t +kadm5_get_privs(void *server_handle, u_int32 *privs); +\end{verbatim} + +Return the caller's admin server privileges in the integer pointed to +by the argument. The Admin API does not define any way for a +principal's privileges to be set. Note that this function will +probably be removed or drastically changed in future versions of this +system. + +The returned value is a bitmask indicating the caller's privileges: + +\begin{tabular}{llr} +{\bf Privilege} & {\bf Symbol} & {\bf Value} \\ +Get & KADM5_PRIV_GET & 0x01 \\ +Add & KADM5_PRIV_ADD & 0x02 \\ +Modify & KADM5_PRIV_MODIFY & 0x04 \\ +Delete & KADM5_PRIV_DELETE & 0x08 \\ +List & KADM5_PRIV_LIST & 0x10 \\ +Changepw & KADM5_PRIV_CPW & 0x20 +\end{tabular} + +There is no guarantee that a caller will have a privilege indicated by +this function for any length of time or for any particular target; +applications using this function must still be prepared to handle all +possible KADM5_AUTH_* error codes. + +In the initial MIT Kerberos version of the admin server, permissions +depend both on the caller and the target; this function returns a +bitmask representing all privileges the caller can possibly have for +any possible target. + +\end{document} diff --git a/krb5-1.21.3/doc/kadm5/api-server-design.tex b/krb5-1.21.3/doc/kadm5/api-server-design.tex new file mode 100644 index 00000000..2cf0fe84 --- /dev/null +++ b/krb5-1.21.3/doc/kadm5/api-server-design.tex @@ -0,0 +1,1054 @@ +% This document is included for historical purposes only, and does not +% apply to krb5 today. + +\documentstyle[12pt,fullpage]{article} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Make _ actually generate an _, and allow line-breaking after it. +\let\underscore=\_ +\catcode`_=13 +\def_{\underscore\penalty75\relax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\setlength{\parskip}{.7\baselineskip} +\setlength{\parindent}{0pt} + +\def\v#1{\verb+#1+} +\def\k#1{K$_#1$} + +\title{KADM5 Library and Server \\ Implementation Design} +\author{Barry Jaspan} + +\begin{document} + +\sloppy +\maketitle + +{\setlength{\parskip}{0pt}\tableofcontents} + +\section{Overview} + +The KADM5 administration system is designed around the KADM5 API. The +``server-side'' library libkadm5srv.a implements the KADM5 API by +operating directly on the underlying KDC and admin databases. The +``client-side'' library libkadm5clnt.a implements the KADM5 API via an +RPC mechanism. The administration server kadmind accepts RPC requests +from the client-side library and translates them into calls to the +server-side library, performing authentication, authorization, and +logging along the way. + +The two libraries, libkadm5clnt.a and libkadm5srv.a, export the +identical kadm5 interface; for example, both contain definitions for +kadm5_get_principal, and all other kadm5 functions. In most cases, +the client library function just marshalls arguments and results into +and out of an RPC call, whereas the server library function performs +the actual operation on the database file. kadm5_init_*, however, are +substantially different even though they export the same interface: on +the client, they establish the RPC connection and GSS-API context, +whereas on the server side the open the database files, read in the +password dictionary, and the like. Also, the kadm5_free functions +operate on local process memory in both libraries. + +The admin server is implemented as a nearly-stateless transaction +server, where each admin API function represents a single transaction. +No per-client or per-connection information is stored; only local +database handles are maintained between requests. The RPC mechanism +provides access to remote callers' authentication credentials for +authorization purposes. + +The admin API is exported via an RPC interface that hides all details +about network encoding, authentication, and encryption of data on the +wire. The RPC mechanism does, however, allow the server to access the +underlying authentication credentials for authorization purposes. + +The admin system maintains two databases: +% +\begin{itemize} +\item The master Kerberos (KDC) database is used to store all the +information that the Kerberos server understands, thus allowing the +greatest functionality with no modifications to a standard KDC. + +\item The KDC database also stores kadm5-specific per-principal +information in each principal's krb5_tl_data list. In a prior +version, this data was stored in a separate admin principal database; +thus, when this document refers to ``the admin principal database,'' +it now refers to the appropriate krb5_tl_data entries in the KDC +database. + +\item The policy database stores kadm5 policy information. +\end{itemize} + +The per-principal information stored in the admin principal database +consists of the principal's policy name and an array of the +principal's previous keys. The old keys are stored encrypted in the +key of the special principal ``kadmin/history'' that is created by the +server library when it is first needed. Since a change in +kadmin/history's key renders every principal's key history array +useless, it can only be changed using the ovsec_adm_edit utility; that +program will reencrypt every principal's key history in the new +key.\footnote{ovsec_adm_edit has not yet been implemented, and there +are currently no plans to implement it; thus, the history cannot +currently be changed.} The server library refuses all requests to +change kadmin/history's key. + +\section{API Handles} + +Each call to kadm5_init_* on the client or server creates a new API +handle. The handles encapsulate the API and structure versions +specified by kadm5_init_*'s caller and all other internal data needed +by the library. A process can have multiple open API handles +simultaneously by calling kadm5_init_* multiple times, and call can +specify a different version, client or service principal, and so +forth. + +Each kadm5 function verifies the handle it is given with the +CHECK_HANDLE or _KADM5_CHECK_HANDLE macros. The CHECK_HANDLE macro +differs for the client and server library because the handle types +used by those libraries differ, so it is defined in both +$<$client_internal.h$>$ and $<$server_internal.h$>$ in the library +source directory. In each header file, CHECK_HANDLE first calls +GENERIC_CHECK_HANDLE, defined in $<$admin_internal.h$>$, which +verifies the magic number, API version, and structure version that is +contained in both client and server handles. CHECK_HANDLE then calls +either CLIENT_CHECK_HANDLE or SERVER_CHECK_HANDLE respectively to +verify the client- or server-library specific handle fields. + +The CHECK_HANDLE macro is useful because it inlines the handle check +instead of requiring a separate function call. However, using +CHECK_HANDLE means that a source file cannot be compiled once and +included into both the client and server library, because CHECK_HANDLE +is always either specific to either the client or server library, not +both. There are a number of functions that can be implemented with +the same code in both the client and server libraries, however, +including all of the kadm5_free functions and +kadm5_chpass_principal_util. The _KADM5_CHECK_HANDLE macro solves +this problem; instead of inlining the handle check, it calls the +function _kadm5_check_handle which is defined separately in both the +client and server library, in client_init.c and server_init.c. +Since these two files are only compiled once and put in a single +library, they simply verify the handle they are passed with +CHECK_HANDLE and return the result. + +\section{API Versioning} + +The KADM5 system was designed by OpenVision to support multiple +versions of the KADM5 API. MIT has not adopted this level of support, +and considers the KADM5 C API to be unstable from release to release. +This section describes the original design intent; bear in mind that +only the most recent API is supported by current MIT krb5 releases, +and that the API version does not necessarily change with API changes +unless there is a need to do so for wire compatibility. + +Historically, three versions of the KADM5 API have existed: +KADM5_API_VERSION_1 through KADM5_API_VERSION_3. The first version +was equivalent to the initial OpenVision API, +OVSEC_KADM_API_VERSION_1; the second was created during the initial +integration of the OpenVision system into the MIT release; and the +third was created for MIT krb5 1.8 to add lockout fields to policy +entries. MIT dropped wire compatibility support for version 1 in MIT +krb5 1.8 (as version 1 was never used in shipped MIT code), but +retains wire compatibility support for version 2. + +Implementing a versioned API in C via with both local and RPC access +presents a number of design issues, some of them quite subtle. The +contexts in which versioning considerations must be made include: + +\begin{enumerate} +\item Typedefs, function declarations, and defined constants depend on +the API version a client is written to and must be correct at compile +time. + +\item Each function in the server library must behave according to the +API version specified by the caller at runtime to kadm5_init_*. + +\item The XDR functions used by the RPC layer to transmit function +arguments and results must encode data structures correctly depending +on the API version specified by the client at runtime. + +\item Each function in the client library must behave according to the +API version specified by the caller at runtime to kadm5_init_*. + +\item The RPC server (kadmind) must accept calls from a client using +any supported API version, and must then invoke the function in the +server library corresponding to the RPC with the API version indicated +by the client caller. + +\item When a first API function is invoked that needs to call a second +function in the API on its own behalf, and that second API function's +behavior depends on the API version specified, the first API function +must either be prepared to call the second API function at whatever +version its caller specifies or have a means of always calling the +second API function at a pre-determined version. +\end{enumerate} + +The following functions describe how each context is handled. + +\subsection{Designing for future compatibility} + +Any code whose behavior depends on the API version should be written +so as to be compatible with future, currently unknown API versions on +the grounds that any particular piece of API behavior will most +likely not change between versions. For example, in the current +system, the code is not written as ``if this is VERSION_1, do X, else +if this is VERSION_2, do Y''; instead, it is written as ``if this is +VERSION_1, do X; else, do Y.'' The former will require additional +work when VERSION_3 is defined, even if ``do Y'' is still the correct +action, whereas the latter will work without modification in that +case. + +\subsection{Header file declarations} + +Typedefs, defined constants and macros, and function declarations may +change between versions. A client is always written to a single, +specific API version, and thus expects the header files to define +everything according to that API. Failure of a header file to define +values correctly will result in either compiler warnings (e.g. if the +pointer type of a function argument changes) or fatal errors (e.g. if +the number of arguments to a function changes, or the fields of a +structure change). For example, in VERSION_1, kadm5_get_policy took a +pointer to a pointer to a structure, and in VERSION_2 it takes a +pointer to a structure; that would generate a warning if not correct. +In VERSION_1, kadm5_randkey_principal accepted three arguments but in +VERSION_2 accepts four; that would generate a fatal error. + +The header file defines everything correctly based on the value of the +USE_KADM5_API_VERSION constant. The constant can be assigned to an +integer corresponding to any supported API version, and defaults to +the newest version. The header files then simply use an \#ifdef to +include the right definitions: +% +\begin{verbatim} +#if USE_KADM5_API_VERSION == 1 +kadm5_ret_t kadm5_get_principal(void *server_handle, + krb5_principal principal, + kadm5_principal_ent_t *ent); +#else +kadm5_ret_t kadm5_get_principal(void *server_handle, + krb5_principal principal, + kadm5_principal_ent_t ent, + long mask); +#endif +\end{verbatim} + +\subsection{Server library functions} + +Server library functions must know how many and what type of arguments +to expect, and must operate on those arguments correctly, based on the +API version with which they are invoked. The API version is contained +in the handle that is always passed as their first argument, generated +by kadm5_init_* (to which the client specified the API version to use +at run-time). + +In general, it is probably unsafe for a compiled function in a library +to re-interpret the number and type of defined arguments at run-time +since the calling conventions may not allow it; for example, a +function whose first argument was a short in one version and a pointer +in the next might fail if it simply typed-casted the argument. In +that case, the function would have to written to take variable +arguments (i.e. use $<$stdarg.h$>$) and extract them from the stack +based on the API version. Alternatively, a separate function for each +API version could be defined, and $<$kadm5/admin.h$>$ could be written +to \v{\#define} the exported function name based on the value of +USE_KADM5_API_VERSION. + +In the current system, it turns out, that isn't necessary, and future +implementors should take try to ensure that no version has semantics +that will cause such problems in the future. All the functions in +KADM5 that have different arguments or results between VERSION_1 and +VERSION_2 do so simply by type-casting their arguments to the +appropriate version and then have separate code paths to handle each +one correctly. kadm5_get_principal, in svr_principal.c, is a good +example. In VERSION_1, it took the address of a pointer to a +kadm5_principal_ent_t to fill in with a pointer to allocated memory; +in VERSION_2, it takes a pointer to a structure to fill in, and a mask +of which fields in that structure should be filled in. Also, the +contents of the kadm5_principal_ent_t changed slightly between the two +versions. kadm5_get_principal handles versioning as follows +(following along in the source code will be helpful): + +\begin{enumerate} +\item If VERSION_1, it saves away its entry argument (address of a +pointer to a structure) and resets its value to contain the address of +a locally stack-allocated entry structure; this allows most of the +function to written once, in terms of VERSION_2 semantics. If +VERSION_1, it also resets its mask argument to be +KADM5_PRINCIPAL_NORMAL_MASK, because that is the equivalent to +VERSION_1 behavior, which was to return all the fields of the +structure. + +\item The bulk of the function is implemented as expected for +VERSION_2. + +\item The new fields in the VERSION_2 entry structure are assigned +inside a block that is only execute if the caller specified +VERSION_2. This saves a little time for a VERSION_1 caller. + +\item After the entry structure is filled, the function checks again +if it was called as VERSION_1. If so, it allocates a new +kadm5_principal_ent_t_v1 structure (which is conveniently defined in +the header file) with malloc, copies the appropriate values from the +entry structure into the VERSION_1 entry structure, and then writes +the address of the newly allocated memory into address specified by +the original entry argument which it had previously saved away. +\end{enumerate} + +There is another complication involved in a function re-interpreting +the number of arguments it receives at compile time---it cannot assign +any value to an argument for which the client did not pass a value. +For example, a VERSION_1 client only passes three arguments to +kadm5_get_principal. If the implementation of kadm5_get_principal +notices that the caller is VERSION_1 and therefore assigns its fourth +argument, mask, to a value that mimics the VERSION_1 behavior, it may +inadvertently overwrite data on its caller's stack. This problem can +be avoided simply by using a true local variable in such cases, +instead of treating an unpassed argument as a local variable. + +\subsection{XDR functions} + +The XDR functions used to encode function arguments and results must +know how to encode the data for any API version. This is important +both so that all the data gets correctly transmitted and so that +protocol compatibility between clients or servers using the new +library but an old API version is maintained; specific, new kadmind +servers should support old kadm5 clients. + +The signature of all XDR functions is strictly defined: they take the +address of an XDR function and the address of the data object to be +encoded or decoded. It is thus impossible to provide the API version +of the data object as an additional argument to an XDR function. +There are two other means to convey the information, storing the API +version to use as a field in the data object itself and creating +separate XDR functions to handle each different version of the data +object, and both of them are used in KADM5. + +In the client library, each kadm5 function collects its arguments into +a single structure to be passed by the RPC; similarly, it expects all +of the results to come back as a single structure from the RPC that it +will then decode back into its constituent pieces (these are the +standard ONC RPC semantics). In order to pass versioning information +to the XDR functions, each function argument and result datatype has a +filed to store the API version. For example, consider +kadm5_get_principal's structures: +% +\begin{verbatim} +struct gprinc_arg { + krb5_ui_4 api_version; + krb5_principal princ; + long mask; +}; +typedef struct gprinc_arg gprinc_arg; +bool_t xdr_gprinc_arg(); + +struct gprinc_ret { + krb5_ui_4 api_version; + kadm5_ret_t code; + kadm5_principal_ent_rec rec; +}; +typedef struct gprinc_ret gprinc_ret; +bool_t xdr_gprinc_ret(); +\end{verbatim} +% +kadm5_get_principal (in client_principal.c) assigns the api_version +field of the gprinc_arg to the version specified by its caller, +assigns the princ field based on its arguments, and assigns the mask +field from its argument if the caller specified VERSION_2. It then +calls the RPC function clnt_call, specifying the XDR functions +xdr_gprinc_arg and xdr_gprinc_ret to handle the arguments and results. + +xdr_gprinc_arg is invoked with a pointer to the gprinc_arg structure +just described. It first encodes the api_version field; this allows +the server to know what to expect. It then encodes the krb5_principal +structure and, if api_version is VERSION_2, the mask. If api_version +is not VERSION_2, it does not encode {\it anything} in place of the +mask, because an old VERSION_1 server will not expect any other data +to arrive on the wire there. + +The server performs the kadm5_get_principal call and returns its +results in an XDR encoded gprinc_ret structure. clnt_call, which has +been blocking until the results arrived, invokes xdr_gprinc_ret with a +pointer to the encoded data for it to decode. xdr_gprinc_ret first +decodes the api_version field, and then the code field since that is +present in all versions to date. The kadm5_principal_ent_rec presents +a problem, however. The structure does not itself contain an +api_version field, but the structure is different between the two +versions. Thus, a single XDR function cannot decode both versions of +the structure because it will have no way to decide which version to +expect. The solution is to have two functions, +kadm5_principal_ent_rec_v1 and kadm5_principal_ent_rec, which always +decode according to VERSION_1 or VERSION_2, respectively. gprinc_ret +knows which one to invoke because it has the api_version field +returned by the server (which is always the same as that specified by +the client in the gpring_arg). + +In hindsight, it probably would have been better to encode the API +version of all structures directly in a version field in the structure +itself; then multiple XDR functions for a single data type wouldn't be +necessary, and the data objects would stand complete on their own. +This can be added in a future API version if desired. + +\subsection{Client library functions} + +Just as with server library functions, client library functions must +be able to interpret their arguments and provide result according to +the API version specified by the caller. Again, kadm5_get_principal +(in client_principal.c) is a good example. The gprinc_ret structure +that it gets back from clnt_call contains a kadm5_principal_ent_rec or +a kadm5_principal_ent_rec_v1 (the logic is simplified somewhat because +the VERSION_2 structure only has new fields added on the end). If +kadm5_get_principal was invoked with VERSION_2, that structure should +be copied into the pointer provided as the entry argument; if it was +invoked with VERSION_1, however, the structure should be copied into +allocated memory whose address is then written into the pointer +provided by the entry argument. Client library functions make this +determination based on the API version specified in the provided +handle, just like server library functions do. + +\subsection{Admin server stubs} + +When an RPC call arrives at the server, the RPC layer authenticates +the call using the GSS-API, decodes the arguments into their +single-structure form (ie: a gprinc_arg) and dispatches the call to a +stub function in the server (in server_stubs.c). The stub function +first checks the caller's authorization to invoke the function and, if +authorized, calls the kadm5 function corresponding to the RPC function +with the arguments specified in the single-structure argument. + +Once again, kadm5_get_principal is a good example for the issues +involved. The contents of the gprinc_arg given to the stub +(get_principal_1) depends on the API version the caller on the client +side specified; that version is available to the server in the +api_version field of the gprinc_arg. When the server calls +kadm5_get_principal in the server library, it must give that function +an API handle that contains the API version requested by the client; +otherwise the function semantics might not be correct. One +possibility would be for the server to call kadm5_init for each client +request, specifying the client's API version number and thus generating +an API handle with the correct version, but that would be +prohibitively inefficient. Instead, the server dips down in the +server library's internal abstraction barrier, using the function +new_server_handle to cons up a server handle based on the server's own +global_server_handle but using the API version specified by the +client. The server then passes the newly generated handle to +kadm5_get_principal, ensuring the right behavior, and creates the +gprinc_ret structure in a manner similar to that described above. + +Although new_server_handle solves the problem of providing the server +with an API handle containing the right API version number, it does +not solve another problem: that a single source file, server_stubs.c, +needs to be able to invoke functions with arguments appropriate for +multiple API versions. If the client specifies VERSION_1, for +example, the server must invoke kadm5_get_principal with three +arguments, but if the client specifies VERSION_2 the server must +invoke kadm5_get_principal with four arguments. The compiler will not +allow this inconsistency. The server defines wrapper functions in a +separate source file that match the old version, and the separate +source file is compiled with USE_KADM5_API_VERSION set to the old +version; see kadm5_get_principal_v1 in server_glue_v1.c. The server +then calls the correct variant of kadm5_get_principal_* based on the +API version and puts the return values into the gprinc_ret in a manner +similar to that described above. + +Neither of these solutions are necessarily correct. new_server_handle +violates the server library's abstraction barrier and is at best a +kludge; the server library should probably export a function to +provide this behavior without violating the abstraction; +alternatively, the librar should be modified so that having the server +call kadm5_init for each client RPC request would not be too +inefficient. The glue functions in server_glue_v1.c really are not +necessary, because the server stubs could always just pass dummy +arguments for the extra arguments; after all, the glue functions pass +{\it nothing} for the extra arguments, so they just end up as stack +garbage anyway. + +Another alternative to the new_server_handle problem is to have the +server always invoke server library functions at a single API version, +and then have the stubs take care of converting the function arguments +and results back into the form expected by the caller. In general, +however, this might require the stubs to duplicate substantial logic +already present in the server library and further violate the server +library's abstraction barrier. + +\subsection{KADM5 self-reference} + +Some kadm5 functions call other kadm5 functions ``on their own +behalf'' to perform functionality that is necessary but that does not +directly affect what the client sees. For example, +kadm5_chpass_principal has to enforce password policies; thus, it +needs to call kadm5_get_principal and, if the principal has a policy, +kadm5_get_policy and kadm5_modify_principal in the process of changing +a principal's password. This leads to a complication: what API handle +should kadm5_chpass_principal pass to the other kadm5 functions it +calls? + +The ``obvious,'' but wrong, answer is that it should pass the handle +it was given by its caller. The caller may provide an API handle +specifying any valid API version. Although the semantics of +kadm5_chpass_principal did not change between VERSION_1 and VERSION_2, +the declarations of both kadm5_get_principal and kadm5_get_policy +did. Thus, to use the caller's API handle, kadm5_chpass_principal +will have to have a separate code path for each API version, even +though it itself did not change between versions, and duplicate a lot +of logic found elsewhere in the library. + +Instead, each API handle contains a ``local-use handle,'' or lhandle, +that kadm5 functions should use to call other kadm5 functions. For +example, the client-side library's handle structure is: +% +\begin{verbatim} +typedef struct _kadm5_server_handle_t { + krb5_ui_4 magic_number; + krb5_ui_4 struct_version; + krb5_ui_4 api_version; + char * cache_name; + int destroy_cache; + CLIENT * clnt; + krb5_context context; + kadm5_config_params params; + struct _kadm5_server_handle_t *lhandle; +} kadm5_server_handle_rec, *kadm5_server_handle_t; +\end{verbatim} +% +The lhandle field is allocated automatically when the handle is +created. All of the fields of the API handle that are accessed +outside kadm5_init are also duplicated in the lhandle; however, the +api_version field of the lhandle is always set to a {\it constant} +value, regardless of the API version specified by the caller to +kadm5_init. In the current implementation, the lhandle's api_version +is always VERSION_2. + +By passing the caller's handle's lhandle to recursively called kadm5 +functions, a kadm5 function is assured of invoking the second kadm5 +function with a known API version. Additionally, the lhandle's +lhandle field points back to the lhandle, in case kadm5 functions call +themselves more than one level deep; handle$->$lhandle always points +to the same lhandle, no matter how many times the indirection is +performed. + +This scheme might break down if a kadm5 function has to call another +kadm5 function to perform operations that they client will see and for +its own benefit, since the semantics of the recursively-called kadm5 +function may depend on the API version specified and the client may be +depending on a particular version's behavior. Future implementors +should avoid creating a situation in which this is possible. + +\section{Server Main} + +The admin server starts by trapping all fatal signals and directing +them to a cleanup-and-exit function. It then creates and exports the +RPC interface and enters its main loop. + +The main loop dispatches all incoming requests to the RPC mechanism. +In a previous version, after 15 seconds of inactivity, the server +closed all open databases; each database was be automatically reopened +by the API function implementations as necessary. That behavior +existed to protect against loss of written data before the process +exited. The current database libraries write all changes out to disk +immediately, however, so this behavior is no longer required or +performed. + +\section{Remote Procedure Calls} + +The RPC for the Admin system will be based on ONC RPC. ONC RPC is +used because it is a well-known, portable RPC mechanism. The +underlying external data representation (xdr) mechanisms for wire +encapsulation are well-known and extensible. Authentication to the +admin server and encryption of all RPC functional arguments and +results are be handled via the AUTH_GSSAPI authentication flavor of +ONC RPC. + +\section{Database Record Types} +\label{sec:db-types} + +\subsection{Admin Principal, osa_princ_ent_t} + +The admin principal database stores records of the type +osa_princ_ent_t (declared in $<$kadm5/adb.h$>$), which is the +subset of the kadm5_principal_ent_t structure that is not stored +in the Kerberos database plus the necessary bookkeeping information. +The records are keyed by the ASCII representation of the principal's +name, including the trailing NULL. + +\begin{verbatim} +typedef struct _osa_pw_hist_t { + int n_key_data; + krb5_key_data *key_data; +} osa_pw_hist_ent, *osa_pw_hist_t; + +typedef struct _osa_princ_ent_t { + char * policy; + u_int32 aux_attributes; + + unsigned int old_key_len; + unsigned int old_key_next; + krb5_kvno admin_history_kvno; + osa_pw_hist_ent *old_keys; + + + u_int32 num_old_keys; + u_int32 next_old_key; + krb5_kvno admin_history_kvno; + osa_pw_hist_ent *old_keys; +} osa_princ_ent_rec, *osa_princ_ent_t; +\end{verbatim} + +The fields that are different from kadm5_principal_ent_t are: + +\begin{description} +\item[num_old_keys] The number of previous keys in the old_keys array. +This value must be 0 $\le$ num_old_keys $<$ pw_history_num. + +\item[old_key_next] The index into old_keys where the next key should +be inserted. This value must be 0 $\le$ old_key_next $\le$ +num_old_keys. + +\item[admin_history_kvno] The key version number of the kadmin/history +principal's key used to encrypt the values in old_keys. If the server +library finds that kadmin/history's kvno is different from the value +in this field, it returns KADM5_BAD_HIST_KEY. + +\item[old_keys] The array of the principal's previous passwords, each +encrypted in the kadmin/history key. There are num_old_keys +elements. Each ``password'' in the array is itself an array of +n_key_data krb5_key_data structures, one for each keysalt type the +password was encoded in. +\end{description} + +\subsection{Policy, osa_policy_ent_t} + +The policy database stores records of the type osa_policy_ent_t +(declared in $<$kadm5/adb.h$>$) , which is all of +kadm5_policy_ent_t plus necessary bookkeeping information. The +records are keyed by the policy name. + +\begin{verbatim} +typedef struct _osa_policy_ent_t { + char *policy; + + u_int32 pw_min_life; + u_int32 pw_max_life; + u_int32 pw_min_length; + u_int32 pw_min_classes; + u_int32 pw_history_num; + + u_int32 refcnt; +} osa_policy_ent_rec, *osa_policy_ent_t; +\end{verbatim} + +\subsection{Kerberos, krb5_db_entry} + +The Kerberos database stores records of type krb5_db_entry, which is +defined in the $<$k5-int.h$>$ header file. The semantics of each +field are defined in the libkdb functional specification. + +\section{Database Access Methods} + +\subsection{Principal and Policy Databases} + +This section describes the database abstraction used for the admin +policy database; the admin principal database used to be treated in +the same manner but is now handled more directly as krb5_tl_data; +thus, nothing in this section applies to it any more. Since both +databases export equivalent functionality, the API is only described +once. The character T is used to represent both ``princ'' and +``policy''. The location of the principal database is defined by the +configuration parameters given to any of the kadm5_init functions in +the server library. + +Note that this is {\it only} a database abstraction. All functional +intelligence, such as maintaining policy reference counts or sanity +checking, must be implemented above this layer. + +Prototypes for the osa functions are supplied in +$<$kadm5/adb.h$>$. The routines are defined in libkadm5srv.a. They +require linking with the Berkely DB library. + +\subsubsection{Error codes} + +The database routines use com_err for error codes. The error code +table name is ``adb'' and the offsets are the same as the order +presented here. The error table header file is +$<$kadm5/adb_err.h$>$. Callers of the OSA routines should first call +init_adb_err_tbl() to initialize the database table. + +\begin{description} +\item[OSA_ADB_OK] Operation successful. +\item[OSA_ADB_FAILURE] General failure. +\item[OSA_ADB_DUP] Operation would create a duplicate database entry. +\item[OSA_ADB_NOENT] Named entry not in database. +\item[OSA_ADB_BAD_PRINC] The krb5_principal structure is invalid. +\item[OSA_ADB_BAD_POLICY] The specified policy name is invalid. +\item[OSA_ADB_XDR_FAILURE] The principal or policy structure cannot be +encoded for storage. +\item[OSA_ADB_BADLOCKMODE] Bad lock mode specified. +\item[OSA_ADB_CANTLOCK_DB] Cannot lock database, presumably because it +is already locked. +\item[OSA_ADB_NOTLOCKED] Internal error, database not locked when +unlock is called. +\item[OSA_ADB_NOLOCKFILE] KADM5 administration database lock file missing. +\end{description} + +Database functions can also return system errors. Unless otherwise +specified, database functions return OSA_ADB_OK. + +\subsubsection{Locking} + +All of the osa_adb functions except open and close lock and unlock the +database to prevent concurrency collisions. The overall locking +algorithm is as follows: + +\begin{enumerate} +\item osa_adb_open_T calls osa_adb_init_db to allocate the osa_adb_T_t +structure and open the locking file for further use. + +\item Each osa_adb functions locks the locking file and opens the +appropriate database with osa_adb_open_and_lock, performs its action, +and then closes the database and unlocks the locking file with +osa_adb_close_and_unlock. + +\item osa_adb_close_T calls osa_adb_fini_db to close the locking file +and deallocate the db structure. +\end{enumerate} + +Functions which modify the database acquire an exclusive lock, others +acquire a shared lock. osa_adb_iter_T acquires an exclusive lock for +safety but as stated below consequences of modifying the database in +the iteration function are undefined. + +\subsubsection{Function descriptions} + +\begin{verbatim} +osa_adb_ret_t osa_adb_create_T_db(kadm5_config_params *params) +\end{verbatim} +% +Create the database and lockfile specified in params. The database +must not already exist, or EEXIST is returned. The lock file is only +created after the database file has been created successfully. + +\begin{verbatim} +osa_adb_ret_t osa_adb_rename_T_db(kadm5_config_params *fromparams, + kadm5_config_params *toparams) +\end{verbatim} +% +Rename the database named by fromparams to that named by toparams. +The fromparams database must already exist; the toparams database may +exist or not. When the function returns, the database named by +fromparams no longer exists, and toparams has been overwritten with +fromparams. This function acquires a permanent lock on both databases +for the duration of its operation, so a failure is likely to leave the +databases unusable. + +\begin{verbatim} +osa_adb_ret_t osa_adb_destroy_policy_db(kadm5_config_params *params) +\end{verbatim} +% +Destroy the database named by params. The database file and lock file +are deleted. + +\begin{verbatim} +osa_adb_ret_t +osa_adb_open_T(osa_adb_T_t *db, char *filename); +\end{verbatim} +% +Open the database named filename. Returns OSA_ADB_NOLOCKFILE if the +database does not exist or if the lock file is missing. The database +is not actually opened in the operating-system file sense until a lock +is acquire. + +\begin{verbatim} +osa_adb_ret_t +osa_adb_close_T(osa_adb_T_t db); +\end{verbatim} +% +Release all shared or exclusive locks (on BOTH databases, since they +use the same lock file) and close the database. + +It is an error to exit while a permanent lock is held; +OSA_ADB_NOLOCKFILE is returned in this case. + +\begin{verbatim} +osa_adb_ret_t osa_adb_get_lock(osa_adb_T_t db, int mode) +\end{verbatim} + +Acquire a lock on the administration databases; note that both +databases are locked simultaneously by a single call. The mode +argument can be OSA_ADB_SHARED, OSA_ADB_EXCLUSIVE, or +OSA_ADB_PERMANENT. The first two and the third are really disjoint +locking semantics and should not be interleaved. + +Shared and exclusive locks have the usual semantics, and a program can +upgrade a shared lock to an exclusive lock by calling the function +again. A reference count of open locks is maintained by this function +and osa_adb_release_lock so the functions can be called multiple +times; the actual lock is not released until the final +osa_adb_release_lock. Note, however, that once a lock is upgraded +from shared to exclusive, or from exclusive to permanent, it is not +downgraded again until released completely. In other words, +get_lock(SHARED), get_lock(EXCLUSIVE), release_lock() leaves the +process with an exclusive lock with a reference count of one. An +attempt to get a shared or exclusive lock that conflicts with another +process results in the OSA_ADB_CANLOCK_DB error code. + +This function and osa_adb_release_lock are called automatically as +needed by all other osa_adb functions to acquire shared and exclusive +locks and so are not normally needed. They can be used explicitly by +a program that wants to perform multiple osa_adb functions within the +context of a single lock. + +Acquiring an OSA_ADB_PERMANENT lock is different. A permanent lock +consists of first acquiring an exclusive lock and then {\it deleting +the lock file}. Any subsequent attempt to acquire a lock by a +different process will fail with OSA_ADB_NOLOCKFILE instead of +OSA_ADB_CANTLOCK_DB (attempts in the same process will ``succeed'' +because only the reference count gets incremented). The lock file is +recreated by osa_adb_release_lock when the last pending lock is released. + +The purpose of a permanent lock is to absolutely ensure that the +database remain locked during non-atomic operations. If the locking +process dies while holding a permanent lock, all subsequent osa_adb +operations will fail, even through a system reboot. This is useful, +for example, for ovsec_adm_import which creates both new database +files in a temporary location and renames them into place. If both +renames do not fully complete the database will probably be +inconsistent and everything should stop working until an administrator +can clean it up. + +\begin{verbatim} +osa_adb_ret_t osa_adb_release_lock(osa_adb_T_t db) +\end{verbatim} + +Releases a shared, exclusive, or permanent lock acquired with +osa_adb_get_lock, or just decrements the reference count if multiple +locks are held. When a permanent lock is released, the lock file is +re-created. + +All of a process' shared or exclusive database locks are released when +the process terminates. A permanent lock is {\it not} released when +the process exits (although the exclusive lock it begins with +obviously is). + +\begin{verbatim} +osa_adb_ret_t +osa_adb_create_T(osa_adb_T_t db, osa_T_ent_t entry); +\end{verbatim} +% +Adds the entry to the database. All fields are defined. Returns +OSA_ADB_DUP if it already exists. + +\begin{verbatim} +osa_adb_ret_t +osa_adb_destroy_T(osa_adb_T_t db, osa_T_t name); +\end{verbatim} + +Removes the named entry from the database. Returns OSA_ADB_NOENT if +it does not exist. + +\begin{verbatim} +osa_adb_ret_t +osa_adb_get_T(osa_adb_T_t db, osa_T_t name, + osa_princ_ent_t *entry); +\end{verbatim} + +Looks up the named entry in the db, and returns it in *entry in +allocated storage that must be freed with osa_adb_free_T. Returns +OSA_ADB_NOENT if name does not exist, OSA_ADB_MEM if memory cannot be +allocated. + +\begin{verbatim} +osa_adb_ret_t +osadb_adb_put_T(osa_adb_T_t db, osa_T_ent_t entry); +\end{verbatim} + +Modifies the existing entry named in entry. All fields must be filled +in. Returns OSA_DB_NOENT if the named entry does not exist. Note +that this cannot be used to rename an entry; rename is implemented by +deleting the old name and creating the new one (NOT ATOMIC!). + +\begin{verbatim} +void osa_adb_free_T(osa_T_ent_t); +\end{verbatim} + +Frees the memory associated with an osa_T_ent_t allocated by +osa_adb_get_T. + +\begin{verbatim} +typedef osa_adb_ret_t (*osa_adb_iter_T_func)(void *data, + osa_T_ent_t entry); + +osa_adb_ret_t osa_adb_iter_T(osa_adb_T_t db, osa_adb_iter_T_func func, + void *data); +\end{verbatim} + +Iterates over every entry in the database. For each entry ent in the +database db, the function (*func)(data, ent) is called. If func +returns an error code, osa_adb_iter_T returns an error code. If all +invocations of func return OSA_ADB_OK, osa_adb_iter_T returns +OSA_ADB_OK. The function func is permitted to access the database, +but the consequences of modifying the database during the iteration +are undefined. + +\subsection{Kerberos Database} + +Kerberos uses the libkdb interface to store krb5_db_entry records. It +can be accessed and modified in parallel with the Kerberos server, +using functions that are defined inside the KDC and the libkdb.a. The +libkdb interface is defined in the libkdb functional specifications. + +\subsubsection{Initialization and Key Access} + +Keys stored in the Kerberos database are encrypted in the Kerberos +master key. The admin server will therefore have to acquire the key +before it can perform any key-changing operations, and will have to +decrypt and encrypt the keys retrieved from and placed into the +database via krb5_db_get_principal and _put_principal. This section +describes the internal admin server API that will be used to perform +these functions. + +\begin{verbatim} +krb5_principal master_princ; +krb5_encrypt_block master_encblock; +krb5_keyblock master_keyblock; + +void kdc_init_master() +\end{verbatim} + +kdc_init_master opens the database and acquires the master key. It +also sets the global variables master_princ, master_encblock, and +master_keyblock: + +\begin{itemize} +\item master_princ is set to the name of the Kerberos master principal +(\v{K/M@REALM}). + +\item master_encblock is something I have no idea about. + +\item master_keyblock is the Kerberos master key +\end{itemize} + +\begin{verbatim} +krb5_error_code kdb_get_entry_and_key(krb5_principal principal, + krb5_db_entry *entry, + krb5_keyblock *key) +\end{verbatim} + +kdb_get_entry_and_key retrieves the named principal's entry from the +database in entry, and decrypts its key into key. The caller must +free entry with krb5_dbm_db_free_principal and free key-$>$contents with +free.\footnote{The caller should also \v{memset(key-$>$contents, 0, +key-$>$length)}. There should be a function krb5_free_keyblock_contents +for this, but there is not.} + +\begin{verbatim} +krb5_error_code kdb_put_entry_pw(krb5_db_entry *entry, char *pw) +\end{verbatim} + +kdb_put_entry_pw stores entry in the database. All the entry values +must already be set; this function does not change any of them except +the key. pw, the NULL-terminated password string, is converted to a +key using string-to-key with the salt type specified in +entry-$>$salt_type.\footnote{The salt_type should be set based on the +command line arguments to the kadmin server (see the ``Command Line'' +section of the functional specification).} + +\section{Admin Principal and Policy Database Implementation} + +The admin principal and policy databases will each be stored in a +single hash table, implemented by the Berkeley 4.4BSD db library. +Each record will consist of an entire osa_T_ent_t. The key into the +hash table is the entry name (for principals, the ASCII representation +of the name). The value is the T entry structure. Since the key and +data must be self-contained, with no pointers, the Sun xdr mechanisms +will be used to marshal and unmarshal data in the database. + +The server in the first release will be single-threaded in that a +request will run to completion (or error) before the next will run, +but multiple connections will be allowed simultaneously. + +\section{ACLs, acl_check} + +The ACL mechanism described in the ``Authorization ACLs'' section of +the functional specifications will be implemented by the acl_check +function. + +\begin{verbatim} +enum access_t { + ACCESS_DENIED = 0, + ACCESS_OK = 1, +}; + +enum access_t acl_check(krb5_principal princ, char *priv); +\end{verbatim} + +The priv argument must be one of ``get'', ``add'', ``delete'', or +``modify''. acl_check returns 1 if the principal princ has the named +privilege, 0 if it does not. + +\section{Function Details} + +This section discusses specific design issues for Admin API functions +that are not addressed by the functional specifications. + +\subsection{kadm5_create_principal} + +If the named principal exists in either the Kerberos or admin +principal database, but not both, return KADM5_BAD_DB. + +The principal's initial key is not stored in the key history array at +creation time. + +\subsection{kadm5_delete_principal} + +If the named principal exists in either the Kerberos or admin +principal database, but not both, return KADM5_BAD_DB. + +\subsection{kadm5_modify_principal} + +If the named principal exists in either the Kerberos or admin +principal database, but not both, return KADM5_BAD_DB. + +If pw_history_num changes and the new value $n$ is smaller than the +current value of num_old_keys, old_keys should end up with the $n$ +most recent keys; these are found by counting backwards $n$ elements +in old_keys from old_key_next. old_key_nexts should then be reset to +0, the oldest of the saved keys, and num_old_keys set to $n$, the +new actual number of old keys in the array. + +\subsection{kadm5_chpass_principal, randkey_principal} + +The algorithm for determining whether a password is in the principal's +key history is complicated by the use of the kadmin/history \k{h} +encrypting key. + +\begin{enumerate} +\item For kadm5_chpass_principal, convert the password to a key +using string-to-key and the salt method specified by the command line +arguments. + +\item If the POLICY bit is set and pw_history_num is not zero, check +if the new key is in the history. +\begin{enumerate} +\item Retrieve the principal's current key and decrypt it with \k{M}. +If it is the same as the new key, return KADM5_PASS_REUSE. +\item Retrieve the kadmin/history key \k{h} and decrypt it with \k{M}. +\item Encrypt the principal's new key in \k{h}. +\item If the principal's new key encrypted in \k{h} is in old_keys, +return KADM5_PASS_REUSE. +\item Encrypt the principal's current key in \k{h} and store it in +old_keys. +\item Erase the memory containing \k{h}. +\end{enumerate} + +\item Encrypt the principal's new key in \k{M} and store it in the +database. +\item Erase the memory containing \k{M}. +\end{enumerate} + +To store the an encrypted key in old_keys, insert it as the +old_key_next element of old_keys, and increment old_key_next by one +modulo pw_history_num. + +\subsection{kadm5_get_principal} + +If the named principal exists in either the Kerberos or admin +principal database, but not both, return KADM5_BAD_DB. + +\end{document} diff --git a/krb5-1.21.3/doc/kadm5/fullpage.sty b/krb5-1.21.3/doc/kadm5/fullpage.sty new file mode 100644 index 00000000..d5a2bf5b --- /dev/null +++ b/krb5-1.21.3/doc/kadm5/fullpage.sty @@ -0,0 +1,9 @@ +\marginparwidth 0pt +\oddsidemargin 0pt +\evensidemargin 0pt +\marginparsep 0pt + +\topmargin 0pt + +\textwidth 6.5in +\textheight 8.5 in diff --git a/krb5-1.21.3/doc/mitK5defaults.rst b/krb5-1.21.3/doc/mitK5defaults.rst new file mode 100644 index 00000000..aea7af3d --- /dev/null +++ b/krb5-1.21.3/doc/mitK5defaults.rst @@ -0,0 +1,79 @@ +.. _mitK5defaults: + +MIT Kerberos defaults +===================== + +General defaults +---------------- + +========================================== ============================= ==================== +Description Default Environment +========================================== ============================= ==================== +:ref:`keytab_definition` file |keytab| **KRB5_KTNAME** +Client :ref:`keytab_definition` file |ckeytab| **KRB5_CLIENT_KTNAME** +Kerberos config file :ref:`krb5.conf(5)` |krb5conf|\ ``:``\ **KRB5_CONFIG** + |sysconfdir|\ ``/krb5.conf`` +KDC config file :ref:`kdc.conf(5)` |kdcdir|\ ``/kdc.conf`` **KRB5_KDC_PROFILE** +GSS mechanism config file |sysconfdir|\ ``/gss/mech`` **GSS_MECH_CONFIG** +KDC database path (DB2) |kdcdir|\ ``/principal`` +Master key :ref:`stash_definition` |kdcdir|\ ``/.k5.``\ *realm* +Admin server ACL file :ref:`kadm5.acl(5)` |kdcdir|\ ``/kadm5.acl`` +OTP socket directory |kdcrundir| +Plugin base directory |libdir|\ ``/krb5/plugins`` +:ref:`rcache_definition` directory ``/var/tmp`` **KRB5RCACHEDIR** +Master key default enctype |defmkey| +Default :ref:`keysalt list` |defkeysalts| +Permitted enctypes |defetypes| +KDC default port 88 +Admin server port 749 +Password change port 464 +========================================== ============================= ==================== + + +Replica KDC propagation defaults +-------------------------------- + +This table shows defaults used by the :ref:`kprop(8)` and +:ref:`kpropd(8)` programs. + +========================== ================================ =========== +Description Default Environment +========================== ================================ =========== +kprop database dump file |kdcdir|\ ``/replica_datatrans`` +kpropd temporary dump file |kdcdir|\ ``/from_master`` +kdb5_util location |sbindir|\ ``/kdb5_util`` +kprop location |sbindir|\ ``/kprop`` +kpropd ACL file |kdcdir|\ ``/kpropd.acl`` +kprop port 754 KPROP_PORT +========================== ================================ =========== + + +.. _paths: + +Default paths for Unix-like systems +----------------------------------- + +On Unix-like systems, some paths used by MIT krb5 depend on parameters +chosen at build time. For a custom build, these paths default to +subdirectories of ``/usr/local``. When MIT krb5 is integrated into an +operating system, the paths are generally chosen to match the +operating system's filesystem layout. + +========================== ============== =========================== =========================== +Description Symbolic name Custom build path Typical OS path +========================== ============== =========================== =========================== +User programs BINDIR ``/usr/local/bin`` ``/usr/bin`` +Libraries and plugins LIBDIR ``/usr/local/lib`` ``/usr/lib`` +Parent of KDC state dir LOCALSTATEDIR ``/usr/local/var`` ``/var`` +Parent of KDC runtime dir RUNSTATEDIR ``/usr/local/var/run`` ``/run`` +Administrative programs SBINDIR ``/usr/local/sbin`` ``/usr/sbin`` +Alternate krb5.conf dir SYSCONFDIR ``/usr/local/etc`` ``/etc`` +Default ccache name DEFCCNAME ``FILE:/tmp/krb5cc_%{uid}`` ``FILE:/tmp/krb5cc_%{uid}`` +Default keytab name DEFKTNAME ``FILE:/etc/krb5.keytab`` ``FILE:/etc/krb5.keytab`` +Default PKCS11 module PKCS11_MODNAME ``opensc-pkcs11.so`` ``opensc-pkcs11.so`` +========================== ============== =========================== =========================== + +The default client keytab name (DEFCKTNAME) typically defaults to +``FILE:/usr/local/var/krb5/user/%{euid}/client.keytab`` for a custom +build. A native build will typically use a path which will vary +according to the operating system's layout of ``/var``. diff --git a/krb5-1.21.3/doc/mitK5features.rst b/krb5-1.21.3/doc/mitK5features.rst new file mode 100644 index 00000000..10effcf1 --- /dev/null +++ b/krb5-1.21.3/doc/mitK5features.rst @@ -0,0 +1,699 @@ +.. highlight:: rst + +.. toctree:: + :hidden: + + mitK5license.rst + +.. _mitK5features: + +MIT Kerberos features +===================== + +https://web.mit.edu/kerberos + + +Quick facts +----------- + +License - :ref:`mitK5license` + +Releases: + - Latest stable: https://web.mit.edu/kerberos/krb5-1.20/ + - Supported: https://web.mit.edu/kerberos/krb5-1.19/ + - Release cycle: approximately 12 months + +Supported platforms \/ OS distributions: + - Windows (KfW 4.0): Windows 7, Vista, XP + - Solaris: SPARC, x86_64/x86 + - GNU/Linux: Debian x86_64/x86, Ubuntu x86_64/x86, RedHat x86_64/x86 + - BSD: NetBSD x86_64/x86 + +Crypto backends: + - builtin - MIT Kerberos native crypto library + - OpenSSL (1.0\+) - https://www.openssl.org + +Database backends: LDAP, DB2, LMDB + +krb4 support: Kerberos 5 release < 1.8 + +DES support: Kerberos 5 release < 1.18 (See :ref:`retiring-des`) + +Interoperability +---------------- + +`Microsoft` + +Starting from release 1.7: + +* Follow client principal referrals in the client library when + obtaining initial tickets. + +* KDC can issue realm referrals for service principals based on domain names. + +* Extensions supporting DCE RPC, including three-leg GSS context setup + and unencapsulated GSS tokens inside SPNEGO. + +* Microsoft GSS_WrapEX, implemented using the gss_iov API, which is + similar to the equivalent SSPI functionality. This is needed to + support some instances of DCE RPC. + +* NTLM recognition support in GSS-API, to facilitate dropping in an + NTLM implementation for improved compatibility with older releases + of Microsoft Windows. + +* KDC support for principal aliases, if the back end supports them. + Currently, only the LDAP back end supports aliases. + +* Support Microsoft set/change password (:rfc:`3244`) protocol in + kadmind. + +* Implement client and KDC support for GSS_C_DELEG_POLICY_FLAG, which + allows a GSS application to request credential delegation only if + permitted by KDC policy. + + +Starting from release 1.8: + +* Microsoft Services for User (S4U) compatibility + + +`Heimdal` + +* Support for KCM credential cache starting from release 1.13 + +Feature list +------------ + +For more information on the specific project see https://k5wiki.kerberos.org/wiki/Projects + +Release 1.7 + - Credentials delegation :rfc:`5896` + - Cross-realm authentication and referrals :rfc:`6806` + - Master key migration + - PKINIT :rfc:`4556` :ref:`pkinit` + +Release 1.8 + - Anonymous PKINIT :rfc:`6112` :ref:`anonymous_pkinit` + - Constrained delegation + - IAKERB https://tools.ietf.org/html/draft-ietf-krb-wg-iakerb-02 + - Heimdal bridge plugin for KDC backend + - GSS-API S4U extensions https://msdn.microsoft.com/en-us/library/cc246071 + - GSS-API naming extensions :rfc:`6680` + - GSS-API extensions for storing delegated credentials :rfc:`5588` + +Release 1.9 + - Advance warning on password expiry + - Camellia encryption (CTS-CMAC mode) :rfc:`6803` + - KDC support for SecurID preauthentication + - kadmin over IPv6 + - Trace logging :ref:`trace_logging` + - GSSAPI/KRB5 multi-realm support + - Plugin to test password quality :ref:`pwqual_plugin` + - Plugin to synchronize password changes :ref:`kadm5_hook_plugin` + - Parallel KDC + - GSS-API extensions for SASL GS2 bridge :rfc:`5801` :rfc:`5587` + - Purging old keys + - Naming extensions for delegation chain + - Password expiration API + - Windows client support (build-only) + - IPv6 support in iprop + +Release 1.10 + - Plugin interface for configuration :ref:`profile_plugin` + - Credentials for multiple identities :ref:`ccselect_plugin` + +Release 1.11 + - Client support for FAST OTP :rfc:`6560` + - GSS-API extensions for credential locations + - Responder mechanism + +Release 1.12 + - Plugin to control krb5_aname_to_localname and krb5_kuserok behavior :ref:`localauth_plugin` + - Plugin to control hostname-to-realm mappings and the default realm :ref:`hostrealm_plugin` + - GSSAPI extensions for constructing MIC tokens using IOV lists :ref:`gssapi_mic_token` + - Principal may refer to nonexistent policies `Policy Refcount project `_ + - Support for having no long-term keys for a principal `Principals Without Keys project `_ + - Collection support to the KEYRING credential cache type on Linux :ref:`ccache_definition` + - FAST OTP preauthentication module for the KDC which uses RADIUS to validate OTP token values :ref:`otp_preauth` + - Experimental Audit plugin for KDC processing `Audit project `_ + +Release 1.13 + + - Add support for accessing KDCs via an HTTPS proxy server using + the `MS-KKDCP + `_ + protocol. + - Add support for `hierarchical incremental propagation + `_, + where replicas can act as intermediates between an upstream primary + and other downstream replicas. + - Add support for configuring GSS mechanisms using + ``/etc/gss/mech.d/*.conf`` files in addition to + ``/etc/gss/mech``. + - Add support to the LDAP KDB module for `binding to the LDAP + server using SASL + `_. + - The KDC listens for TCP connections by default. + - Fix a minor key disclosure vulnerability where using the + "keepold" option to the kadmin randkey operation could return the + old keys. `[CVE-2014-5351] + `_ + - Add client support for the Kerberos Cache Manager protocol. If + the host is running a Heimdal kcm daemon, caches served by the + daemon can be accessed with the KCM: cache type. + - When built on macOS 10.7 and higher, use "KCM:" as the default + cachetype, unless overridden by command-line options or + krb5-config values. + - Add support for doing unlocked database dumps for the DB2 KDC + back end, which would allow the KDC and kadmind to continue + accessing the database during lengthy database dumps. + +Release 1.14 + + * Administrator experience + + - Add a new kdb5_util tabdump command to provide reporting-friendly + tabular dump formats (tab-separated or CSV) for the KDC database. + Unlike the normal dump format, each output table has a fixed number + of fields. Some tables include human-readable forms of data that + are opaque in ordinary dump files. This format is also suitable for + importing into relational databases for complex queries. + - Add support to kadmin and kadmin.local for specifying a single + command line following any global options, where the command + arguments are split by the shell--for example, "kadmin getprinc + principalname". Commands issued this way do not prompt for + confirmation or display warning messages, and exit with non-zero + status if the operation fails. + - Accept the same principal flag names in kadmin as we do for the + default_principal_flags kdc.conf variable, and vice versa. Also + accept flag specifiers in the form that kadmin prints, as well as + hexadecimal numbers. + - Remove the triple-DES and RC4 encryption types from the default + value of supported_enctypes, which determines the default key and + salt types for new password-derived keys. By default, keys will + only created only for AES128 and AES256. This mitigates some types + of password guessing attacks. + - Add support for directory names in the KRB5_CONFIG and + KRB5_KDC_PROFILE environment variables. + - Add support for authentication indicators, which are ticket + annotations to indicate the strength of the initial authentication. + Add support for the "require_auth" string attribute, which can be + set on server principal entries to require an indicator when + authenticating to the server. + - Add support for key version numbers larger than 255 in keytab files, + and for version numbers up to 65535 in KDC databases. + - Transmit only one ETYPE-INFO and/or ETYPE-INFO2 entry from the KDC + during pre-authentication, corresponding to the client's most + preferred encryption type. + - Add support for server name identification (SNI) when proxying KDC + requests over HTTPS. + - Add support for the err_fmt profile parameter, which can be used to + generate custom-formatted error messages. + + * Developer experience: + + - Change gss_acquire_cred_with_password() to acquire credentials into + a private memory credential cache. Applications can use + gss_store_cred() to make the resulting credentials visible to other + processes. + - Change gss_acquire_cred() and SPNEGO not to acquire credentials for + IAKERB or for non-standard variants of the krb5 mechanism OID unless + explicitly requested. (SPNEGO will still accept the Microsoft + variant of the krb5 mechanism OID during negotiation.) + - Change gss_accept_sec_context() not to accept tokens for IAKERB or + for non-standard variants of the krb5 mechanism OID unless an + acceptor credential is acquired for those mechanisms. + - Change gss_acquire_cred() to immediately resolve credentials if the + time_rec parameter is not NULL, so that a correct expiration time + can be returned. Normally credential resolution is delayed until + the target name is known. + - Add krb5_prepend_error_message() and krb5_wrap_error_message() APIs, + which can be used by plugin modules or applications to add prefixes + to existing detailed error messages. + - Add krb5_c_prfplus() and krb5_c_derive_prfplus() APIs, which + implement the RFC 6113 PRF+ operation and key derivation using PRF+. + - Add support for pre-authentication mechanisms which use multiple + round trips, using the the KDC_ERR_MORE_PREAUTH_DATA_REQUIRED error + code. Add get_cookie() and set_cookie() callbacks to the kdcpreauth + interface; these callbacks can be used to save marshalled state + information in an encrypted cookie for the next request. + - Add a client_key() callback to the kdcpreauth interface to retrieve + the chosen client key, corresponding to the ETYPE-INFO2 entry sent + by the KDC. + - Add an add_auth_indicator() callback to the kdcpreauth interface, + allowing pre-authentication modules to assert authentication + indicators. + - Add support for the GSS_KRB5_CRED_NO_CI_FLAGS_X cred option to + suppress sending the confidentiality and integrity flags in GSS + initiator tokens unless they are requested by the caller. These + flags control the negotiated SASL security layer for the Microsoft + GSS-SPNEGO SASL mechanism. + - Make the FILE credential cache implementation less prone to + corruption issues in multi-threaded programs, especially on + platforms with support for open file description locks. + + * Performance: + + - On replica KDCs, poll the primary KDC immediately after + processing a full resync, and do not require two full resyncs + after the primary KDC's log file is reset. + +Release 1.15 + +* Administrator experience: + + - Add support to kadmin for remote extraction of current keys + without changing them (requires a special kadmin permission that + is excluded from the wildcard permission), with the exception of + highly protected keys. + + - Add a lockdown_keys principal attribute to prevent retrieval of + the principal's keys (old or new) via the kadmin protocol. In + newly created databases, this attribute is set on the krbtgt and + kadmin principals. + + - Restore recursive dump capability for DB2 back end, so sites can + more easily recover from database corruption resulting from power + failure events. + + - Add DNS auto-discovery of KDC and kpasswd servers from URI + records, in addition to SRV records. URI records can convey TCP + and UDP servers and primary KDC status in a single DNS lookup, and + can also point to HTTPS proxy servers. + + - Add support for password history to the LDAP back end. + + - Add support for principal renaming to the LDAP back end. + + - Use the getrandom system call on supported Linux kernels to avoid + blocking problems when getting entropy from the operating system. + +* Code quality: + + - Clean up numerous compilation warnings. + + - Remove various infrequently built modules, including some preauth + modules that were not built by default. + +* Developer experience: + + - Add support for building with OpenSSL 1.1. + + - Use SHA-256 instead of MD5 for (non-cryptographic) hashing of + authenticators in the replay cache. This helps sites that must + build with FIPS 140 conformant libraries that lack MD5. + +* Protocol evolution: + + - Add support for the AES-SHA2 enctypes, which allows sites to + conform to Suite B crypto requirements. + +Release 1.16 + +* Administrator experience: + + - The KDC can match PKINIT client certificates against the + "pkinit_cert_match" string attribute on the client principal + entry, using the same syntax as the existing "pkinit_cert_match" + profile option. + + - The ktutil addent command supports the "-k 0" option to ignore the + key version, and the "-s" option to use a non-default salt string. + + - kpropd supports a --pid-file option to write a pid file at + startup, when it is run in standalone mode. + + - The "encrypted_challenge_indicator" realm option can be used to + attach an authentication indicator to tickets obtained using FAST + encrypted challenge pre-authentication. + + - Localization support can be disabled at build time with the + --disable-nls configure option. + +* Developer experience: + + - The kdcpolicy pluggable interface allows modules control whether + tickets are issued by the KDC. + + - The kadm5_auth pluggable interface allows modules to control + whether kadmind grants access to a kadmin request. + + - The certauth pluggable interface allows modules to control which + PKINIT client certificates can authenticate to which client + principals. + + - KDB modules can use the client and KDC interface IP addresses to + determine whether to allow an AS request. + + - GSS applications can query the bit strength of a krb5 GSS context + using the GSS_C_SEC_CONTEXT_SASL_SSF OID with + gss_inquire_sec_context_by_oid(). + + - GSS applications can query the impersonator name of a krb5 GSS + credential using the GSS_KRB5_GET_CRED_IMPERSONATOR OID with + gss_inquire_cred_by_oid(). + + - kdcpreauth modules can query the KDC for the canonicalized + requested client principal name, or match a principal name against + the requested client principal name with canonicalization. + +* Protocol evolution: + + - The client library will continue to try pre-authentication + mechanisms after most failure conditions. + + - The KDC will issue trivially renewable tickets (where the + renewable lifetime is equal to or less than the ticket lifetime) + if requested by the client, to be friendlier to scripts. + + - The client library will use a random nonce for TGS requests + instead of the current system time. + + - For the RC4 string-to-key or PAC operations, UTF-16 is supported + (previously only UCS-2 was supported). + + - When matching PKINIT client certificates, UPN SANs will be matched + correctly as UPNs, with canonicalization. + +* User experience: + + - Dates after the year 2038 are accepted (provided that the platform + time facilities support them), through the year 2106. + + - Automatic credential cache selection based on the client realm + will take into account the fallback realm and the service + hostname. + + - Referral and alternate cross-realm TGTs will not be cached, + avoiding some scenarios where they can be added to the credential + cache multiple times. + + - A German translation has been added. + +* Code quality: + + - The build is warning-clean under clang with the configured warning + options. + + - The automated test suite runs cleanly under AddressSanitizer. + +Release 1.17 + +* Administrator experience: + + - A new Kerberos database module using the Lightning Memory-Mapped + Database library (LMDB) has been added. The LMDB KDB module + should be more performant and more robust than the DB2 module, and + may become the default module for new databases in a future + release. + + - "kdb5_util dump" will no longer dump policy entries when specific + principal names are requested. + +* Developer experience: + + - The new krb5_get_etype_info() API can be used to retrieve enctype, + salt, and string-to-key parameters from the KDC for a client + principal. + + - The new GSS_KRB5_NT_ENTERPRISE_NAME name type allows enterprise + principal names to be used with GSS-API functions. + + - KDC and kadmind modules which call com_err() will now write to the + log file in a format more consistent with other log messages. + + - Programs which use large numbers of memory credential caches + should perform better. + +* Protocol evolution: + + - The SPAKE pre-authentication mechanism is now supported. This + mechanism protects against password dictionary attacks without + requiring any additional infrastructure such as certificates. + SPAKE is enabled by default on clients, but must be manually + enabled on the KDC for this release. + + - PKINIT freshness tokens are now supported. Freshness tokens can + protect against scenarios where an attacker uses temporary access + to a smart card to generate authentication requests for the + future. + + - Password change operations now prefer TCP over UDP, to avoid + spurious error messages about replays when a response packet is + dropped. + + - The KDC now supports cross-realm S4U2Self requests when used with + a third-party KDB module such as Samba's. The client code for + cross-realm S4U2Self requests is also now more robust. + +* User experience: + + - The new ktutil addent -f flag can be used to fetch salt + information from the KDC for password-based keys. + + - The new kdestroy -p option can be used to destroy a credential + cache within a collection by client principal name. + + - The Kerberos man page has been restored, and documents the + environment variables that affect programs using the Kerberos + library. + +* Code quality: + + - Python test scripts now use Python 3. + + - Python test scripts now display markers in verbose output, making + it easier to find where a failure occurred within the scripts. + + - The Windows build system has been simplified and updated to work + with more recent versions of Visual Studio. A large volume of + unused Windows-specific code has been removed. Visual Studio 2013 + or later is now required. + +Release 1.18 + +* Administrator experience: + + - Remove support for single-DES encryption types. + + - Change the replay cache format to be more efficient and robust. + Replay cache filenames using the new format end with ``.rcache2`` + by default. + + - setuid programs will automatically ignore environment variables + that normally affect krb5 API functions, even if the caller does + not use krb5_init_secure_context(). + + - Add an ``enforce_ok_as_delegate`` krb5.conf relation to disable + credential forwarding during GSSAPI authentication unless the KDC + sets the ok-as-delegate bit in the service ticket. + +* Developer experience: + + - Implement krb5_cc_remove_cred() for all credential cache types. + + - Add the krb5_pac_get_client_info() API to get the client account + name from a PAC. + +* Protocol evolution: + + - Add KDC support for S4U2Self requests where the user is identified + by X.509 certificate. (Requires support for certificate lookup + from a third-party KDB module.) + + - Remove support for an old ("draft 9") variant of PKINIT. + + - Add support for Microsoft NegoEx. (Requires one or more + third-party GSS modules implementing NegoEx mechanisms.) + +* User experience: + + - Add support for ``dns_canonicalize_hostname=fallback``, causing + host-based principal names to be tried first without DNS + canonicalization, and again with DNS canonicalization if the + un-canonicalized server is not found. + + - Expand single-component hostnames in hhost-based principal names + when DNS canonicalization is not used, adding the system's first + DNS search path as a suffix. Add a ``qualify_shortname`` + krb5.conf relation to override this suffix or disable expansion. + +* Code quality: + + - The libkrb5 serialization code (used to export and import krb5 GSS + security contexts) has been simplified and made type-safe. + + - The libkrb5 code for creating KRB-PRIV, KRB-SAFE, and KRB-CRED + messages has been revised to conform to current coding practices. + + - The test suite has been modified to work with macOS System + Integrity Protection enabled. + + - The test suite incorporates soft-pkcs11 so that PKINIT PKCS11 + support can always be tested. + +Release 1.19 + +* Administrator experience: + + - When a client keytab is present, the GSSAPI krb5 mech will refresh + credentials even if the current credentials were acquired + manually. + + - It is now harder to accidentally delete the K/M entry from a KDB. + +* Developer experience: + + - gss_acquire_cred_from() now supports the "password" and "verify" + options, allowing credentials to be acquired via password and + verified using a keytab key. + + - When an application accepts a GSS security context, the new + GSS_C_CHANNEL_BOUND_FLAG will be set if the initiator and acceptor + both provided matching channel bindings. + + - Added the GSS_KRB5_NT_X509_CERT name type, allowing S4U2Self + requests to identify the desired client principal by certificate. + + - PKINIT certauth modules can now cause the hw-authent flag to be + set in issued tickets. + + - The krb5_init_creds_step() API will now issue the same password + expiration warnings as krb5_get_init_creds_password(). + +* Protocol evolution: + + - Added client and KDC support for Microsoft's Resource-Based + Constrained Delegation, which allows cross-realm S4U2Proxy + requests. A third-party database module is required for KDC + support. + + - kadmin/admin is now the preferred server principal name for kadmin + connections, and the host-based form is no longer created by + default. The client will still try the host-based form as a + fallback. + + - Added client and server support for Microsoft's + KERB_AP_OPTIONS_CBT extension, which causes channel bindings to be + required for the initiator if the acceptor provided them. The + client will send this option if the client_aware_gss_bindings + profile option is set. + +User experience: + + - The default setting of dns_canonicalize_realm is now "fallback". + Hostnames provided from applications will be tried in principal + names as given (possibly with shortname qualification), falling + back to the canonicalized name. + + - kinit will now issue a warning if the des3-cbc-sha1 encryption + type is used in the reply. This encryption type will be + deprecated and removed in future releases. + + - Added kvno flags --out-cache, --no-store, and --cached-only + (inspired by Heimdal's kgetcred). + +Release 1.20 + +* Administrator experience: + + - Added a "disable_pac" realm relation to suppress adding PAC + authdata to tickets, for realms which do not need to support S4U + requests. + + - Most credential cache types will use atomic replacement when a + cache is reinitialized using kinit or refreshed from the client + keytab. + + - kprop can now propagate databases with a dump size larger than + 4GB, if both the client and server are upgraded. + + - kprop can now work over NATs that change the destination IP + address, if the client is upgraded. + +* Developer experience: + + - Updated the KDB interface. The sign_authdata() method is replaced + with the issue_pac() method, allowing KDB modules to add logon + info and other buffers to the PAC issued by the KDC. + + - Host-based initiator names are better supported in the GSS krb5 + mechanism. + +* Protocol evolution: + + - Replaced AD-SIGNEDPATH authdata with minimal PACs. + + - To avoid spurious replay errors, password change requests will not + be attempted over UDP until the attempt over TCP fails. + + - PKINIT will sign its CMS messages with SHA-256 instead of SHA-1. + +* Code quality: + + - Updated all code using OpenSSL to be compatible with OpenSSL 3. + + - Reorganized the libk5crypto build system to allow the OpenSSL + back-end to pull in material from the builtin back-end depending + on the OpenSSL version. + + - Simplified the PRNG logic to always use the platform PRNG. + + - Converted the remaining Tcl tests to Python. + +Release 1.21 + +* User experience: + + - Added a credential cache type providing compatibility with the + macOS 11 native credential cache. + +* Developer experience: + + - libkadm5 will use the provided krb5_context object to read + configuration values, instead of creating its own. + + - Added an interface to retrieve the ticket session key from a GSS + context. + +* Protocol evolution: + + - The KDC will no longer issue tickets with RC4 or triple-DES + session keys unless explicitly configured with the new allow_rc4 + or allow_des3 variables respectively. + + - The KDC will assume that all services can handle aes256-sha1 + session keys unless the service principal has a session_enctypes + string attribute. + + - Support for PAC full KDC checksums has been added to mitigate an + S4U2Proxy privilege escalation attack. + + - The PKINIT client will advertise a more modern set of supported + CMS algorithms. + +* Code quality: + + - Removed unused code in libkrb5, libkrb5support, and the PKINIT + module. + + - Modernized the KDC code for processing TGS requests, the code for + encrypting and decrypting key data, the PAC handling code, and the + GSS library packet parsing and composition code. + + - Improved the test framework's detection of memory errors in daemon + processes when used with asan. + +`Pre-authentication mechanisms` + +- PW-SALT :rfc:`4120#section-5.2.7.3` +- ENC-TIMESTAMP :rfc:`4120#section-5.2.7.2` +- SAM-2 +- FAST negotiation framework (release 1.8) :rfc:`6113` +- PKINIT with FAST on client (release 1.10) :rfc:`6113` +- PKINIT :rfc:`4556` +- FX-COOKIE :rfc:`6113#section-5.2` +- S4U-X509-USER (release 1.8) https://msdn.microsoft.com/en-us/library/cc246091 +- OTP (release 1.12) :ref:`otp_preauth` +- SPAKE (release 1.17) :ref:`spake` diff --git a/krb5-1.21.3/doc/mitK5license.rst b/krb5-1.21.3/doc/mitK5license.rst new file mode 100644 index 00000000..e23edbfb --- /dev/null +++ b/krb5-1.21.3/doc/mitK5license.rst @@ -0,0 +1,11 @@ +.. _mitK5license: + +MIT Kerberos License information +================================ + +.. toctree:: + :hidden: + + copyright.rst + +.. include:: notice.rst diff --git a/krb5-1.21.3/doc/notice.rst b/krb5-1.21.3/doc/notice.rst new file mode 100644 index 00000000..498e287d --- /dev/null +++ b/krb5-1.21.3/doc/notice.rst @@ -0,0 +1,1271 @@ +Copyright |copy| 1985-2024 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. + +Downloading of this software may constitute an export of cryptographic +software from the United States of America that is subject to the +United States Export Administration Regulations (EAR), 15 CFR 730-774. +Additional laws or regulations may apply. It is the responsibility of +the person or entity contemplating export to comply with all +applicable export laws and regulations, including obtaining any +required license from the U.S. government. + +The U.S. government prohibits export of encryption source code to +certain countries and individuals, including, but not limited to, the +countries of Cuba, Iran, North Korea, Sudan, Syria, and residents and +nationals of those countries. + +Documentation components of this software distribution are licensed +under a Creative Commons Attribution-ShareAlike 3.0 Unported License. +(https://creativecommons.org/licenses/by-sa/3.0/) + +Individual source code files are copyright MIT, Cygnus Support, +Novell, OpenVision Technologies, Oracle, Red Hat, Sun Microsystems, +FundsXpress, and others. + +Project Athena, Athena, Athena MUSE, Discuss, Hesiod, Kerberos, Moira, +and Zephyr are trademarks of the Massachusetts Institute of Technology +(MIT). No commercial use of these trademarks may be made without +prior written permission of MIT. + +"Commercial use" means use of a name in a product or other for-profit +manner. It does NOT prevent a commercial firm from referring to the +MIT trademarks in order to convey information (although in doing so, +recognition of their trademark status should be given). + +------------------- + +The following copyright and permission notice applies to the +OpenVision Kerberos Administration system located in +``kadmin/create``, ``kadmin/dbutil``, ``kadmin/passwd``, +``kadmin/server``, ``lib/kadm5``, and portions of +``lib/rpc``: + + Copyright, OpenVision Technologies, Inc., 1993-1996, All Rights Reserved + + WARNING: Retrieving the OpenVision Kerberos Administration system source + code, as described below, indicates your acceptance of the following + terms. If you do not agree to the following terms, do not retrieve the + OpenVision Kerberos administration system. + + You may freely use and distribute the Source Code and Object Code + compiled from it, with or without modification, but this Source Code is + provided to you "AS IS" EXCLUSIVE OF ANY WARRANTY, INCLUDING, WITHOUT + LIMITATION, ANY WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A + PARTICULAR PURPOSE, OR ANY OTHER WARRANTY, WHETHER EXPRESS OR IMPLIED. + IN NO EVENT WILL OPENVISION HAVE ANY LIABILITY FOR ANY LOST PROFITS, + LOSS OF DATA OR COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR + FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS + AGREEMENT, INCLUDING, WITHOUT LIMITATION, THOSE RESULTING FROM THE USE + OF THE SOURCE CODE, OR THE FAILURE OF THE SOURCE CODE TO PERFORM, OR FOR + ANY OTHER REASON. + + OpenVision retains all copyrights in the donated Source Code. OpenVision + also retains copyright to derivative works of the Source Code, whether + created by OpenVision or by a third party. The OpenVision copyright + notice must be preserved if derivative works are made based on the + donated Source Code. + + OpenVision Technologies, Inc. has donated this Kerberos Administration + system to MIT for inclusion in the standard Kerberos 5 distribution. + This donation underscores our commitment to continuing Kerberos + technology development and our gratitude for the valuable work which has + been performed by MIT and the Kerberos community. + +------------------- + + Portions contributed by Matt Crawford ``crawdad@fnal.gov`` were work + performed at Fermi National Accelerator Laboratory, which is operated + by Universities Research Association, Inc., under contract + DE-AC02-76CHO3000 with the U.S. Department of Energy. + +------------------- + +Portions of ``src/lib/crypto`` have the following copyright: + + Copyright |copy| 1998 by the FundsXpress, INC. + + All rights reserved. + + Export of this software from the United States of America may require + a specific license from the United States Government. It is the + responsibility of any person or organization contemplating export to + obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of FundsXpress. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. FundsXpress makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + + THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +------------------- + +The implementation of the AES encryption algorithm in +``src/lib/crypto/builtin/aes`` has the following copyright: + + | Copyright |copy| 1998-2013, Brian Gladman, Worcester, UK. All + | rights reserved. + + The redistribution and use of this software (with or without + changes) is allowed without the payment of fees or royalties + provided that: + + source code distributions include the above copyright notice, + this list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this + list of conditions and the following disclaimer in their + documentation. + + This software is provided 'as is' with no explicit or implied warranties + in respect of its operation, including, but not limited to, correctness + and fitness for purpose. + +------------------- + +Portions contributed by Red Hat, including the pre-authentication +plug-in framework and the NSS crypto implementation, contain the +following copyright: + + | Copyright |copy| 2006 Red Hat, Inc. + | Portions copyright |copy| 2006 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. + * Neither the name of Red Hat, Inc., 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 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. + +------------------- + +The bundled verto source code is subject to the following license: + + Copyright 2011 Red Hat, Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation files + (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, + and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +------------------- + +The MS-KKDCP client implementation has the following copyright: + + Copyright 2013,2014 Red Hat, Inc. + + 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. + + 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. + +------------------- + +The implementations of GSSAPI mechglue in GSSAPI-SPNEGO in +``src/lib/gssapi``, including the following files: + +.. parsed-literal:: + + lib/gssapi/generic/gssapi_err_generic.et + lib/gssapi/mechglue/g_accept_sec_context.c + lib/gssapi/mechglue/g_acquire_cred.c + lib/gssapi/mechglue/g_canon_name.c + lib/gssapi/mechglue/g_compare_name.c + lib/gssapi/mechglue/g_context_time.c + lib/gssapi/mechglue/g_delete_sec_context.c + lib/gssapi/mechglue/g_dsp_name.c + lib/gssapi/mechglue/g_dsp_status.c + lib/gssapi/mechglue/g_dup_name.c + lib/gssapi/mechglue/g_exp_sec_context.c + lib/gssapi/mechglue/g_export_name.c + lib/gssapi/mechglue/g_glue.c + lib/gssapi/mechglue/g_imp_name.c + lib/gssapi/mechglue/g_imp_sec_context.c + lib/gssapi/mechglue/g_init_sec_context.c + lib/gssapi/mechglue/g_initialize.c + lib/gssapi/mechglue/g_inquire_context.c + lib/gssapi/mechglue/g_inquire_cred.c + lib/gssapi/mechglue/g_inquire_names.c + lib/gssapi/mechglue/g_process_context.c + lib/gssapi/mechglue/g_rel_buffer.c + lib/gssapi/mechglue/g_rel_cred.c + lib/gssapi/mechglue/g_rel_name.c + lib/gssapi/mechglue/g_rel_oid_set.c + lib/gssapi/mechglue/g_seal.c + lib/gssapi/mechglue/g_sign.c + lib/gssapi/mechglue/g_store_cred.c + lib/gssapi/mechglue/g_unseal.c + lib/gssapi/mechglue/g_userok.c + lib/gssapi/mechglue/g_utils.c + lib/gssapi/mechglue/g_verify.c + lib/gssapi/mechglue/gssd_pname_to_uid.c + lib/gssapi/mechglue/mglueP.h + lib/gssapi/mechglue/oid_ops.c + lib/gssapi/spnego/gssapiP_spnego.h + lib/gssapi/spnego/spnego_mech.c + +and the initial implementation of incremental propagation, including +the following new or changed files: + +.. parsed-literal:: + + include/iprop_hdr.h + kadmin/server/ipropd_svc.c + lib/kdb/iprop.x + lib/kdb/kdb_convert.c + lib/kdb/kdb_log.c + lib/kdb/kdb_log.h + lib/krb5/error_tables/kdb5_err.et + kprop/kpropd_rpc.c + kprop/kproplog.c + +are subject to the following license: + + Copyright |copy| 2004 Sun Microsystems, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +------------------- + +Kerberos V5 includes documentation and software developed at the +University of California at Berkeley, which includes this copyright +notice: + + | Copyright |copy| 1983 Regents of the University of California. + | 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 University 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 REGENTS 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 REGENTS 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. + +------------------- + +Portions contributed by Novell, Inc., including the LDAP database +backend, are subject to the following license: + + | Copyright |copy| 2004-2005, Novell, Inc. + | 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. + * The copyright holder's name is not 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. + +------------------- + +Portions funded by Sandia National Laboratory +and developed by the University of Michigan's +Center for Information Technology Integration, +including the PKINIT implementation, are subject +to the following license: + + | COPYRIGHT |copy| 2006-2007 + | THE REGENTS OF THE UNIVERSITY OF MICHIGAN + | ALL RIGHTS RESERVED + + Permission is granted to use, copy, create derivative works + and redistribute this software and such derivative works + for any purpose, so long as the name of The University of + Michigan is not used in any advertising or publicity + pertaining to the use of distribution of this software + without specific, written prior authorization. If the + above copyright notice or any other identification of the + University of Michigan is included in any copy of any + portion of this software, then the disclaimer below must + also be included. + + THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + SUCH DAMAGES. + +------------------- + +The pkcs11.h file included in the PKINIT code has the +following license: + + | Copyright 2006 g10 Code GmbH + | Copyright 2006 Andreas Jellinghaus + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. + +------------------- + +Portions contributed by Apple Inc. are subject to the following license: + + Copyright 2004-2008 Apple Inc. All Rights Reserved. + + Export of this software from the United States of America may require + a specific license from the United States Government. It is the + responsibility of any person or organization contemplating export to + obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of Apple Inc. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Apple Inc. makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + + THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +------------------- + +The implementations of UTF-8 string handling in src/util/support and +src/lib/krb5/unicode are subject to the following copyright and +permission notice: + + | The OpenLDAP Public License + | Version 2.8, 17 August 2003 + + Redistribution and use of this software and associated documentation + ("Software"), with or without modification, are permitted provided + that the following conditions are met: + + 1. Redistributions in source form must retain copyright statements + and notices, + 2. Redistributions in binary form must reproduce applicable copyright + statements and notices, this list of conditions, and the following + disclaimer in the documentation and/or other materials provided + with the distribution, and + 3. Redistributions must contain a verbatim copy of this document. + + The OpenLDAP Foundation may revise this license from time to time. + Each revision is distinguished by a version number. You may use + this Software under terms of this license revision or under the + terms of any subsequent revision of the license. + + THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS + CONTRIBUTORS "AS IS" AND ANY EXPRESSED 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 OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S) + OR OWNER(S) OF THE SOFTWARE 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. + + The names of the authors and copyright holders must not be used in + advertising or otherwise to promote the sale, use or other dealing + in this Software without specific, written prior permission. Title + to copyright in this Software shall at all times remain with copyright + holders. + + OpenLDAP is a registered trademark of the OpenLDAP Foundation. + + Copyright 1999-2003 The OpenLDAP Foundation, Redwood City, + California, USA. All Rights Reserved. Permission to copy and + distribute verbatim copies of this document is granted. + +------------------- + +Marked test programs in src/lib/krb5/krb have the following copyright: + + | Copyright |copy| 2006 Kungliga Tekniska Högskola + | (Royal Institute of Technology, Stockholm, Sweden). + | 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 KTH 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 KTH AND ITS 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 KTH OR ITS 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. + +------------------- + +The KCM Mach RPC definition file used on macOS has the following copyright: + + | Copyright |copy| 2009 Kungliga Tekniska Högskola + | (Royal Institute of Technology, Stockholm, Sweden). + | All rights reserved. + + Portions Copyright |copy| 2009 Apple Inc. 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. + +------------------- + +Portions of the RPC implementation in src/lib/rpc and src/include/gssrpc +have the following copyright and permission notice: + + Copyright |copy| 2010, Oracle America, Inc. + + 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 "Oracle America, Inc." 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 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. + +------------------- + + Copyright |copy| 2006,2007,2009 + NTT (Nippon Telegraph and Telephone Corporation). 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 as + the first lines of this file unmodified. + 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. + + THIS SOFTWARE IS PROVIDED BY NTT "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 NTT 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. + +------------------- + + Copyright 2000 by Carnegie Mellon University + + All Rights Reserved + + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose and without fee is hereby granted, + provided that the above copyright notice appear in all copies and that + both that copyright notice and this permission notice appear in + supporting documentation, and that the name of Carnegie Mellon + University not be used in advertising or publicity pertaining to + distribution of the software without specific, written prior + permission. + + CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR + ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +------------------- + + Copyright |copy| 2002 Naval Research Laboratory (NRL/CCS) + + Permission to use, copy, modify and distribute this software and its + documentation is hereby granted, provided that both the copyright + notice and this permission notice appear in all copies of the software, + derivative works or modified versions, and any portions thereof. + + NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND + DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER + RESULTING FROM THE USE OF THIS SOFTWARE. + +------------------- + + Copyright |copy| 2022 United States Government as represented by the + Secretary of the Navy. 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. + +------------------- + + Copyright |copy| 1991, 1992, 1994 by Cygnus Support. + + Permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation. + Cygnus Support makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + +------------------- + + Copyright |copy| 2006 Secure Endpoints Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + +------------------- + + Copyright |copy| 1994 by the University of Southern California + + EXPORT OF THIS SOFTWARE from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute + this software and its documentation in source and binary forms is + hereby granted, provided that any documentation or other materials + related to such distribution or use acknowledge that the software + was developed by the University of Southern California. + + DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The + University of Southern California MAKES NO REPRESENTATIONS OR + WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + limitation, the University of Southern California MAKES NO + REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY + PARTICULAR PURPOSE. The University of Southern + California shall not be held liable for any liability nor for any + direct, indirect, or consequential damages with respect to any + claim by the user or distributor of the ksu software. + +------------------- + + | Copyright |copy| 1995 + | The President and Fellows of Harvard University + + This code is derived from software contributed to Harvard by + Jeremy Rassen. + + 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. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + + This product includes software developed by the University of + California, Berkeley and its contributors. + + 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + +------------------- + + | Copyright |copy| 2008 by the Massachusetts Institute of Technology. + | Copyright 1995 by Richard P. Basch. All Rights Reserved. + | Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used + in advertising or publicity pertaining to distribution of the software + without specific, written prior permission. Richard P. Basch, + Lehman Brothers and M.I.T. make no representations about the suitability + of this software for any purpose. It is provided "as is" without + express or implied warranty. + +------------------- + +The following notice applies to ``src/lib/krb5/krb/strptime.c`` and +``src/include/k5-queue.h``. + + | Copyright |copy| 1997, 1998 The NetBSD Foundation, Inc. + | All rights reserved. + + This code was contributed to The NetBSD Foundation by Klaus Klein. + + 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. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + + This product includes software developed by the NetBSD + Foundation, Inc. and its contributors. + + 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + +------------------- + +The following notice applies to Unicode library files in +``src/lib/krb5/unicode``: + + | Copyright 1997, 1998, 1999 Computing Research Labs, + | New Mexico State University + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT + OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +------------------- + +The following notice applies to ``src/util/support/strlcpy.c``: + + Copyright |copy| 1998 Todd C. Miller ``Todd.Miller@courtesan.com`` + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +------------------- + +The following notice applies to ``src/util/profile/argv_parse.c`` and +``src/util/profile/argv_parse.h``: + + Copyright 1999 by Theodore Ts'o. + + Permission to use, copy, modify, and distribute this software for + any purpose with or without fee is hereby granted, provided that + the above copyright notice and this permission notice appear in all + copies. THE SOFTWARE IS PROVIDED "AS IS" AND THEODORE TS'O (THE + AUTHOR) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. (Isn't + it sick that the U.S. culture of lawsuit-happy lawyers requires + this kind of disclaimer?) + +------------------- + +The following notice applies to portiions of ``src/lib/rpc`` and +``src/include/gssrpc``: + + Copyright |copy| 2000 The Regents of the University of Michigan. + All rights reserved. + + Copyright |copy| 2000 Dug Song ``dugsong@UMICH.EDU``. + All rights reserved, all wrongs reversed. + + 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 University 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 "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 REGENTS 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. + +------------------- + +Implementations of the MD4 algorithm are subject to the following +notice: + + Copyright |copy| 1990, RSA Data Security, Inc. All rights reserved. + + License to copy and use this software is granted provided that + it is identified as the "RSA Data Security, Inc. MD4 Message + Digest Algorithm" in all material mentioning or referencing this + software or this function. + + License is also granted to make and use derivative works + provided that such works are identified as "derived from the RSA + Data Security, Inc. MD4 Message Digest Algorithm" in all + material mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning + either the merchantability of this software or the suitability + of this software for any particular purpose. It is provided "as + is" without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +------------------- + +Implementations of the MD5 algorithm are subject to the following +notice: + + Copyright |copy| 1990, RSA Data Security, Inc. All rights reserved. + + License to copy and use this software is granted provided that + it is identified as the "RSA Data Security, Inc. MD5 Message- + Digest Algorithm" in all material mentioning or referencing this + software or this function. + + License is also granted to make and use derivative works + provided that such works are identified as "derived from the RSA + Data Security, Inc. MD5 Message-Digest Algorithm" in all + material mentioning or referencing the derived work. + + RSA Data Security, Inc. makes no representations concerning + either the merchantability of this software or the suitability + of this software for any particular purpose. It is provided "as + is" without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +------------------- + +The following notice applies to ``src/lib/crypto/crypto_tests/t_mddriver.c``: + + Copyright |copy| 1990-2, RSA Data Security, Inc. Created 1990. All + rights reserved. + + RSA Data Security, Inc. makes no representations concerning either + the merchantability of this software or the suitability of this + software for any particular purpose. It is provided "as is" + without express or implied warranty of any kind. + + These notices must be retained in any copies of any part of this + documentation and/or software. + +------------------- + +Portions of ``src/lib/krb5`` are subject to the following notice: + + | Copyright |copy| 1994 CyberSAFE Corporation. + | Copyright 1990,1991,2007,2008 by the Massachusetts + Institute of Technology. + | All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Furthermore if you modify this software you must label + your software as modified software and not distribute it in such a + fashion that it might be confused with the original M.I.T. software. + Neither M.I.T., the Open Computing Security Group, nor + CyberSAFE Corporation make any representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + +------------------- + +Portions contributed by PADL Software are subject to the following +license: + + Copyright (c) 2011, PADL Software Pty Ltd. + 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + +------------------- + +The bundled libev source code is subject to the following license: + + All files in libev are Copyright (C)2007,2008,2009 Marc Alexander Lehmann. + + 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 + 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. + + Alternatively, the contents of this package may be used under the terms + of the GNU General Public License ("GPL") version 2 or any later version, + in which case the provisions of the GPL are applicable instead of the + above. If you wish to allow the use of your version of this package only + under the terms of the GPL and not to allow others to use your version of + this file under the BSD license, indicate your decision by deleting the + provisions above and replace them with the notice and other provisions + required by the GPL in this and the other files of this package. If you do + not delete the provisions above, a recipient may use your version of this + file under either the BSD or the GPL. + +------------------- + +Files copied from the Intel AESNI Sample Library are subject to the +following license: + + Copyright |copy| 2010, Intel Corporation + 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 Intel Corporation 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 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. + +------------------- + +The following notice applies to +``src/ccapi/common/win/OldCC/autolock.hxx``: + + Copyright (C) 1998 by Danilo Almeida. 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. + +------------------- + +The following notice applies to portions of +``src/plugins/preauth/spake/edwards25519.c`` and +``src/plugins/preauth/spake/edwards25519_tables.h``: + +The MIT License (MIT) + +Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file). + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. + +------------------- + +The following notice applies to portions of +``src/plugins/preauth/spake/edwards25519.c``: + +Copyright (c) 2015-2016, Google Inc. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/krb5-1.21.3/doc/pdf/GMakefile b/krb5-1.21.3/doc/pdf/GMakefile new file mode 100644 index 00000000..e4653f23 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/GMakefile @@ -0,0 +1,64 @@ +# Makefile for Sphinx LaTeX output + +ALLDOCS = $(basename $(wildcard *.tex)) +ALLPDF = $(addsuffix .pdf,$(ALLDOCS)) +ALLDVI = $(addsuffix .dvi,$(ALLDOCS)) +ALLXDV = +ALLPS = $(addsuffix .ps,$(ALLDOCS)) + +# Prefix for archive names +ARCHIVEPREFIX = +# Additional LaTeX options (passed via variables in latexmkrc/latexmkjarc file) +export LATEXOPTS ?= +# Additional latexmk options +LATEXMKOPTS ?= +# format: pdf or dvi (used only by archive targets) +FMT = pdf + +LATEX = latexmk -dvi +PDFLATEX = latexmk -pdf -dvi- -ps- + + +%.dvi: %.tex FORCE_MAKE + $(LATEX) $(LATEXMKOPTS) '$<' + +%.ps: %.dvi + dvips '$<' + +%.pdf: %.tex FORCE_MAKE + $(PDFLATEX) $(LATEXMKOPTS) '$<' + +all: $(ALLPDF) + +all-dvi: $(ALLDVI) + +all-ps: $(ALLPS) + +all-pdf: $(ALLPDF) + +zip: all-$(FMT) + mkdir $(ARCHIVEPREFIX)docs-$(FMT) + cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT) + zip -q -r -9 $(ARCHIVEPREFIX)docs-$(FMT).zip $(ARCHIVEPREFIX)docs-$(FMT) + rm -r $(ARCHIVEPREFIX)docs-$(FMT) + +tar: all-$(FMT) + mkdir $(ARCHIVEPREFIX)docs-$(FMT) + cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT) + tar cf $(ARCHIVEPREFIX)docs-$(FMT).tar $(ARCHIVEPREFIX)docs-$(FMT) + rm -r $(ARCHIVEPREFIX)docs-$(FMT) + +gz: tar + gzip -9 < $(ARCHIVEPREFIX)docs-$(FMT).tar > $(ARCHIVEPREFIX)docs-$(FMT).tar.gz + +bz2: tar + bzip2 -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar + +xz: tar + xz -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar + +clean: + rm -f *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ps *.tar *.tar.gz *.tar.bz2 *.tar.xz $(ALLPDF) $(ALLDVI) $(ALLXDV) *.fls *.fdb_latexmk + +.PHONY: all all-pdf all-dvi all-ps clean zip tar gz bz2 xz +.PHONY: FORCE_MAKE \ No newline at end of file diff --git a/krb5-1.21.3/doc/pdf/LICRcyr2utf8.xdy b/krb5-1.21.3/doc/pdf/LICRcyr2utf8.xdy new file mode 100644 index 00000000..a9ca1c82 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/LICRcyr2utf8.xdy @@ -0,0 +1,101 @@ +;; -*- coding: utf-8; mode: Lisp; -*- +;; style file for xindy +;; filename: LICRcyr2utf8.xdy +;; description: style file for xindy which maps back LaTeX Internal +;; Character Representation of Cyrillic to utf-8 +;; usage: for use with pdflatex produced .idx files. +;; Contributed by the Sphinx team, July 2018. +(merge-rule "\IeC {\'\CYRG }" "Ѓ" :string) +(merge-rule "\IeC {\'\CYRK }" "Ќ" :string) +(merge-rule "\IeC {\'\cyrg }" "ѓ" :string) +(merge-rule "\IeC {\'\cyrk }" "ќ" :string) +(merge-rule "\IeC {\CYRA }" "А" :string) +(merge-rule "\IeC {\CYRB }" "Б" :string) +(merge-rule "\IeC {\CYRC }" "Ц" :string) +(merge-rule "\IeC {\CYRCH }" "Ч" :string) +(merge-rule "\IeC {\CYRD }" "Д" :string) +(merge-rule "\IeC {\CYRDJE }" "Ђ" :string) +(merge-rule "\IeC {\CYRDZE }" "Ѕ" :string) +(merge-rule "\IeC {\CYRDZHE }" "Џ" :string) +(merge-rule "\IeC {\CYRE }" "Е" :string) +(merge-rule "\IeC {\CYREREV }" "Э" :string) +(merge-rule "\IeC {\CYRERY }" "Ы" :string) +(merge-rule "\IeC {\CYRF }" "Ф" :string) +(merge-rule "\IeC {\CYRG }" "Г" :string) +(merge-rule "\IeC {\CYRGUP }" "Ґ" :string) +(merge-rule "\IeC {\CYRH }" "Х" :string) +(merge-rule "\IeC {\CYRHRDSN }" "Ъ" :string) +(merge-rule "\IeC {\CYRI }" "И" :string) +(merge-rule "\IeC {\CYRIE }" "Є" :string) +(merge-rule "\IeC {\CYRII }" "І" :string) +(merge-rule "\IeC {\CYRISHRT }" "Й" :string) +(merge-rule "\IeC {\CYRJE }" "Ј" :string) +(merge-rule "\IeC {\CYRK }" "К" :string) +(merge-rule "\IeC {\CYRL }" "Л" :string) +(merge-rule "\IeC {\CYRLJE }" "Љ" :string) +(merge-rule "\IeC {\CYRM }" "М" :string) +(merge-rule "\IeC {\CYRN }" "Н" :string) +(merge-rule "\IeC {\CYRNJE }" "Њ" :string) +(merge-rule "\IeC {\CYRO }" "О" :string) +(merge-rule "\IeC {\CYRP }" "П" :string) +(merge-rule "\IeC {\CYRR }" "Р" :string) +(merge-rule "\IeC {\CYRS }" "С" :string) +(merge-rule "\IeC {\CYRSFTSN }" "Ь" :string) +(merge-rule "\IeC {\CYRSH }" "Ш" :string) +(merge-rule "\IeC {\CYRSHCH }" "Щ" :string) +(merge-rule "\IeC {\CYRT }" "Т" :string) +(merge-rule "\IeC {\CYRTSHE }" "Ћ" :string) +(merge-rule "\IeC {\CYRU }" "У" :string) +(merge-rule "\IeC {\CYRUSHRT }" "Ў" :string) +(merge-rule "\IeC {\CYRV }" "В" :string) +(merge-rule "\IeC {\CYRYA }" "Я" :string) +(merge-rule "\IeC {\CYRYI }" "Ї" :string) +(merge-rule "\IeC {\CYRYO }" "Ё" :string) +(merge-rule "\IeC {\CYRYU }" "Ю" :string) +(merge-rule "\IeC {\CYRZ }" "З" :string) +(merge-rule "\IeC {\CYRZH }" "Ж" :string) +(merge-rule "\IeC {\cyra }" "а" :string) +(merge-rule "\IeC {\cyrb }" "б" :string) +(merge-rule "\IeC {\cyrc }" "ц" :string) +(merge-rule "\IeC {\cyrch }" "ч" :string) +(merge-rule "\IeC {\cyrd }" "д" :string) +(merge-rule "\IeC {\cyrdje }" "ђ" :string) +(merge-rule "\IeC {\cyrdze }" "ѕ" :string) +(merge-rule "\IeC {\cyrdzhe }" "џ" :string) +(merge-rule "\IeC {\cyre }" "е" :string) +(merge-rule "\IeC {\cyrerev }" "э" :string) +(merge-rule "\IeC {\cyrery }" "ы" :string) +(merge-rule "\IeC {\cyrf }" "ф" :string) +(merge-rule "\IeC {\cyrg }" "г" :string) +(merge-rule "\IeC {\cyrgup }" "ґ" :string) +(merge-rule "\IeC {\cyrh }" "х" :string) +(merge-rule "\IeC {\cyrhrdsn }" "ъ" :string) +(merge-rule "\IeC {\cyri }" "и" :string) +(merge-rule "\IeC {\cyrie }" "є" :string) +(merge-rule "\IeC {\cyrii }" "і" :string) +(merge-rule "\IeC {\cyrishrt }" "й" :string) +(merge-rule "\IeC {\cyrje }" "ј" :string) +(merge-rule "\IeC {\cyrk }" "к" :string) +(merge-rule "\IeC {\cyrl }" "л" :string) +(merge-rule "\IeC {\cyrlje }" "љ" :string) +(merge-rule "\IeC {\cyrm }" "м" :string) +(merge-rule "\IeC {\cyrn }" "н" :string) +(merge-rule "\IeC {\cyrnje }" "њ" :string) +(merge-rule "\IeC {\cyro }" "о" :string) +(merge-rule "\IeC {\cyrp }" "п" :string) +(merge-rule "\IeC {\cyrr }" "р" :string) +(merge-rule "\IeC {\cyrs }" "с" :string) +(merge-rule "\IeC {\cyrsftsn }" "ь" :string) +(merge-rule "\IeC {\cyrsh }" "ш" :string) +(merge-rule "\IeC {\cyrshch }" "щ" :string) +(merge-rule "\IeC {\cyrt }" "т" :string) +(merge-rule "\IeC {\cyrtshe }" "ћ" :string) +(merge-rule "\IeC {\cyru }" "у" :string) +(merge-rule "\IeC {\cyrushrt }" "ў" :string) +(merge-rule "\IeC {\cyrv }" "в" :string) +(merge-rule "\IeC {\cyrya }" "я" :string) +(merge-rule "\IeC {\cyryi }" "ї" :string) +(merge-rule "\IeC {\cyryo }" "ё" :string) +(merge-rule "\IeC {\cyryu }" "ю" :string) +(merge-rule "\IeC {\cyrz }" "з" :string) +(merge-rule "\IeC {\cyrzh }" "ж" :string) diff --git a/krb5-1.21.3/doc/pdf/LICRlatin2utf8.xdy b/krb5-1.21.3/doc/pdf/LICRlatin2utf8.xdy new file mode 100644 index 00000000..1d768259 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/LICRlatin2utf8.xdy @@ -0,0 +1,239 @@ +;; style file for xindy +;; filename: LICRlatin2utf8.xdy +;; description: style file for xindy which maps back LaTeX Internal +;; Character Representation of letters (as arising in .idx index +;; file) to UTF-8 encoding for correct sorting by xindy. +;; usage: for use with the pdflatex engine, +;; *not* for use with xelatex or lualatex. +;; +;; This is based upon xindy's distributed file tex/inputenc/utf8.xdy. +;; The modifications include: +;; +;; - Updates for compatibility with current LaTeX macro encoding. +;; +;; - Systematic usage of the \IeC {...} mark-up, because mark-up in +;; tex/inputenc/utf8.xdy was using it on seemingly random basis, and +;; Sphinx coercing of xindy usability for both Latin and Cyrillic scripts +;; with pdflatex requires its systematic presence here. +;; +;; - Support for some extra letters: Ÿ, Ŋ, ŋ, Œ, œ, IJ, ij, ȷ and ẞ. +;; +;; Indeed Sphinx needs to support for pdflatex engine all Unicode letters +;; available in TeX T1 font encoding. The above letters are found in +;; that encoding but not in the Latin1, 2, 3 charsets which are those +;; covered by original tex/inputenc/utf8.xdy. +;; +;; - There is a problem that ȷ is not supported out-of-the box by LaTeX +;; with inputenc, one must add explicitly +;; \DeclareUnicodeCharacter{0237}{\j} +;; to preamble of LaTeX document. However this character is not supported +;; by the TeX "times" font used by default by Sphinx for pdflatex engine. +;; +;; **Update**: since LaTeX 2018/12/01, the \j as well as \SS, \k{} and +;; \.{} need no extra user declaration anymore. +;; +;; - ẞ needs \DeclareUnicodeCharacter{1E9E}{\SS} (but ß needs no extra set-up). +;; +;; - U+02DB (˛) and U+02D9 (˙) are also not supported by inputenc +;; out of the box and require +;; \DeclareUnicodeCharacter{02DB}{\k{}} +;; \DeclareUnicodeCharacter{02D9}{\.{}} +;; to be added to preamble. +;; +;; - U+0127 ħ and U+0126 Ħ are absent from TeX T1+TS1 font encodings. +;; +;; - Characters Ŋ and ŋ are not supported by TeX font "times" used by +;; default by Sphinx for pdflatex engine but they are supported by +;; some TeX fonts, in particular by the default LaTeX font for T1 +;; encoding. +;; +;; - " and ~ must be escaped as ~" and resp. ~~ in xindy merge rules. +;; +;; Contributed by the Sphinx team, July 2018. +;; +;; See sphinx.xdy for superior figures, as they are escaped by LaTeX writer. +(merge-rule "\IeC {\textonesuperior }" "¹" :string) +(merge-rule "\IeC {\texttwosuperior }" "²" :string) +(merge-rule "\IeC {\textthreesuperior }" "³" :string) +(merge-rule "\IeC {\'a}" "á" :string) +(merge-rule "\IeC {\'A}" "Á" :string) +(merge-rule "\IeC {\`a}" "à" :string) +(merge-rule "\IeC {\`A}" "À" :string) +(merge-rule "\IeC {\^a}" "â" :string) +(merge-rule "\IeC {\^A}" "Â" :string) +(merge-rule "\IeC {\~"a}" "ä" :string) +(merge-rule "\IeC {\~"A}" "Ä" :string) +(merge-rule "\IeC {\~~a}" "ã" :string) +(merge-rule "\IeC {\~~A}" "Ã" :string) +(merge-rule "\IeC {\c c}" "ç" :string) +(merge-rule "\IeC {\c C}" "Ç" :string) +(merge-rule "\IeC {\'c}" "ć" :string) +(merge-rule "\IeC {\'C}" "Ć" :string) +(merge-rule "\IeC {\^c}" "ĉ" :string) +(merge-rule "\IeC {\^C}" "Ĉ" :string) +(merge-rule "\IeC {\.c}" "ċ" :string) +(merge-rule "\IeC {\.C}" "Ċ" :string) +(merge-rule "\IeC {\c s}" "ş" :string) +(merge-rule "\IeC {\c S}" "Ş" :string) +(merge-rule "\IeC {\c t}" "ţ" :string) +(merge-rule "\IeC {\c T}" "Ţ" :string) +(merge-rule "\IeC {\-}" "­" :string); soft hyphen +(merge-rule "\IeC {\textdiv }" "÷" :string) +(merge-rule "\IeC {\'e}" "é" :string) +(merge-rule "\IeC {\'E}" "É" :string) +(merge-rule "\IeC {\`e}" "è" :string) +(merge-rule "\IeC {\`E}" "È" :string) +(merge-rule "\IeC {\^e}" "ê" :string) +(merge-rule "\IeC {\^E}" "Ê" :string) +(merge-rule "\IeC {\~"e}" "ë" :string) +(merge-rule "\IeC {\~"E}" "Ë" :string) +(merge-rule "\IeC {\^g}" "ĝ" :string) +(merge-rule "\IeC {\^G}" "Ĝ" :string) +(merge-rule "\IeC {\.g}" "ġ" :string) +(merge-rule "\IeC {\.G}" "Ġ" :string) +(merge-rule "\IeC {\^h}" "ĥ" :string) +(merge-rule "\IeC {\^H}" "Ĥ" :string) +(merge-rule "\IeC {\H o}" "ő" :string) +(merge-rule "\IeC {\H O}" "Ő" :string) +(merge-rule "\IeC {\textacutedbl }" "˝" :string) +(merge-rule "\IeC {\H u}" "ű" :string) +(merge-rule "\IeC {\H U}" "Ű" :string) +(merge-rule "\IeC {\ae }" "æ" :string) +(merge-rule "\IeC {\AE }" "Æ" :string) +(merge-rule "\IeC {\textcopyright }" "©" :string) +(merge-rule "\IeC {\c \ }" "¸" :string) +(merge-rule "\IeC {\dh }" "ð" :string) +(merge-rule "\IeC {\DH }" "Ð" :string) +(merge-rule "\IeC {\dj }" "đ" :string) +(merge-rule "\IeC {\DJ }" "Đ" :string) +(merge-rule "\IeC {\guillemotleft }" "«" :string) +(merge-rule "\IeC {\guillemotright }" "»" :string) +(merge-rule "\IeC {\'\i }" "í" :string) +(merge-rule "\IeC {\`\i }" "ì" :string) +(merge-rule "\IeC {\^\i }" "î" :string) +(merge-rule "\IeC {\~"\i }" "ï" :string) +(merge-rule "\IeC {\i }" "ı" :string) +(merge-rule "\IeC {\^\j }" "ĵ" :string) +(merge-rule "\IeC {\k {}}" "˛" :string) +(merge-rule "\IeC {\l }" "ł" :string) +(merge-rule "\IeC {\L }" "Ł" :string) +(merge-rule "\IeC {\nobreakspace }" " " :string) +(merge-rule "\IeC {\o }" "ø" :string) +(merge-rule "\IeC {\O }" "Ø" :string) +(merge-rule "\IeC {\textsterling }" "£" :string) +(merge-rule "\IeC {\textparagraph }" "¶" :string) +(merge-rule "\IeC {\ss }" "ß" :string) +(merge-rule "\IeC {\textsection }" "§" :string) +(merge-rule "\IeC {\textbrokenbar }" "¦" :string) +(merge-rule "\IeC {\textcent }" "¢" :string) +(merge-rule "\IeC {\textcurrency }" "¤" :string) +(merge-rule "\IeC {\textdegree }" "°" :string) +(merge-rule "\IeC {\textexclamdown }" "¡" :string) +(merge-rule "\IeC {\texthbar }" "ħ" :string) +(merge-rule "\IeC {\textHbar }" "Ħ" :string) +(merge-rule "\IeC {\textonehalf }" "½" :string) +(merge-rule "\IeC {\textonequarter }" "¼" :string) +(merge-rule "\IeC {\textordfeminine }" "ª" :string) +(merge-rule "\IeC {\textordmasculine }" "º" :string) +(merge-rule "\IeC {\textperiodcentered }" "·" :string) +(merge-rule "\IeC {\textquestiondown }" "¿" :string) +(merge-rule "\IeC {\textregistered }" "®" :string) +(merge-rule "\IeC {\textthreequarters }" "¾" :string) +(merge-rule "\IeC {\textyen }" "¥" :string) +(merge-rule "\IeC {\th }" "þ" :string) +(merge-rule "\IeC {\TH }" "Þ" :string) +(merge-rule "\IeC {\'I}" "Í" :string) +(merge-rule "\IeC {\`I}" "Ì" :string) +(merge-rule "\IeC {\^I}" "Î" :string) +(merge-rule "\IeC {\~"I}" "Ï" :string) +(merge-rule "\IeC {\.I}" "İ" :string) +(merge-rule "\IeC {\^J}" "Ĵ" :string) +(merge-rule "\IeC {\k a}" "ą" :string) +(merge-rule "\IeC {\k A}" "Ą" :string) +(merge-rule "\IeC {\k e}" "ę" :string) +(merge-rule "\IeC {\k E}" "Ę" :string) +(merge-rule "\IeC {\'l}" "ĺ" :string) +(merge-rule "\IeC {\'L}" "Ĺ" :string) +(merge-rule "\IeC {\textlnot }" "¬" :string) +(merge-rule "\IeC {\textmu }" "µ" :string) +(merge-rule "\IeC {\'n}" "ń" :string) +(merge-rule "\IeC {\'N}" "Ń" :string) +(merge-rule "\IeC {\~~n}" "ñ" :string) +(merge-rule "\IeC {\~~N}" "Ñ" :string) +(merge-rule "\IeC {\'o}" "ó" :string) +(merge-rule "\IeC {\'O}" "Ó" :string) +(merge-rule "\IeC {\`o}" "ò" :string) +(merge-rule "\IeC {\`O}" "Ò" :string) +(merge-rule "\IeC {\^o}" "ô" :string) +(merge-rule "\IeC {\^O}" "Ô" :string) +(merge-rule "\IeC {\~"o}" "ö" :string) +(merge-rule "\IeC {\~"O}" "Ö" :string) +(merge-rule "\IeC {\~~o}" "õ" :string) +(merge-rule "\IeC {\~~O}" "Õ" :string) +(merge-rule "\IeC {\textpm }" "±" :string) +(merge-rule "\IeC {\r a}" "å" :string) +(merge-rule "\IeC {\r A}" "Å" :string) +(merge-rule "\IeC {\'r}" "ŕ" :string) +(merge-rule "\IeC {\'R}" "Ŕ" :string) +(merge-rule "\IeC {\r u}" "ů" :string) +(merge-rule "\IeC {\r U}" "Ů" :string) +(merge-rule "\IeC {\'s}" "ś" :string) +(merge-rule "\IeC {\'S}" "Ś" :string) +(merge-rule "\IeC {\^s}" "ŝ" :string) +(merge-rule "\IeC {\^S}" "Ŝ" :string) +(merge-rule "\IeC {\textasciidieresis }" "¨" :string) +(merge-rule "\IeC {\textasciimacron }" "¯" :string) +(merge-rule "\IeC {\.{}}" "˙" :string) +(merge-rule "\IeC {\textasciiacute }" "´" :string) +(merge-rule "\IeC {\texttimes }" "×" :string) +(merge-rule "\IeC {\u a}" "ă" :string) +(merge-rule "\IeC {\u A}" "Ă" :string) +(merge-rule "\IeC {\u g}" "ğ" :string) +(merge-rule "\IeC {\u G}" "Ğ" :string) +(merge-rule "\IeC {\textasciibreve }" "˘" :string) +(merge-rule "\IeC {\'u}" "ú" :string) +(merge-rule "\IeC {\'U}" "Ú" :string) +(merge-rule "\IeC {\`u}" "ù" :string) +(merge-rule "\IeC {\`U}" "Ù" :string) +(merge-rule "\IeC {\^u}" "û" :string) +(merge-rule "\IeC {\^U}" "Û" :string) +(merge-rule "\IeC {\~"u}" "ü" :string) +(merge-rule "\IeC {\~"U}" "Ü" :string) +(merge-rule "\IeC {\u u}" "ŭ" :string) +(merge-rule "\IeC {\u U}" "Ŭ" :string) +(merge-rule "\IeC {\v c}" "č" :string) +(merge-rule "\IeC {\v C}" "Č" :string) +(merge-rule "\IeC {\v d}" "ď" :string) +(merge-rule "\IeC {\v D}" "Ď" :string) +(merge-rule "\IeC {\v e}" "ě" :string) +(merge-rule "\IeC {\v E}" "Ě" :string) +(merge-rule "\IeC {\v l}" "ľ" :string) +(merge-rule "\IeC {\v L}" "Ľ" :string) +(merge-rule "\IeC {\v n}" "ň" :string) +(merge-rule "\IeC {\v N}" "Ň" :string) +(merge-rule "\IeC {\v r}" "ř" :string) +(merge-rule "\IeC {\v R}" "Ř" :string) +(merge-rule "\IeC {\v s}" "š" :string) +(merge-rule "\IeC {\v S}" "Š" :string) +(merge-rule "\IeC {\textasciicaron }" "ˇ" :string) +(merge-rule "\IeC {\v t}" "ť" :string) +(merge-rule "\IeC {\v T}" "Ť" :string) +(merge-rule "\IeC {\v z}" "ž" :string) +(merge-rule "\IeC {\v Z}" "Ž" :string) +(merge-rule "\IeC {\'y}" "ý" :string) +(merge-rule "\IeC {\'Y}" "Ý" :string) +(merge-rule "\IeC {\~"y}" "ÿ" :string) +(merge-rule "\IeC {\'z}" "ź" :string) +(merge-rule "\IeC {\'Z}" "Ź" :string) +(merge-rule "\IeC {\.z}" "ż" :string) +(merge-rule "\IeC {\.Z}" "Ż" :string) +;; letters not in Latin1, 2, 3 but available in TeX T1 font encoding +(merge-rule "\IeC {\~"Y}" "Ÿ" :string) +(merge-rule "\IeC {\NG }" "Ŋ" :string) +(merge-rule "\IeC {\ng }" "ŋ" :string) +(merge-rule "\IeC {\OE }" "Œ" :string) +(merge-rule "\IeC {\oe }" "œ" :string) +(merge-rule "\IeC {\IJ }" "IJ" :string) +(merge-rule "\IeC {\ij }" "ij" :string) +(merge-rule "\IeC {\j }" "ȷ" :string) +(merge-rule "\IeC {\SS }" "ẞ" :string) diff --git a/krb5-1.21.3/doc/pdf/LatinRules.xdy b/krb5-1.21.3/doc/pdf/LatinRules.xdy new file mode 100644 index 00000000..99f14a2e --- /dev/null +++ b/krb5-1.21.3/doc/pdf/LatinRules.xdy @@ -0,0 +1,607 @@ +;; style file for xindy +;; filename: LatinRules.xdy +;; +;; It is based upon xindy's files lang/general/utf8.xdy and +;; lang/general/utf8-lang.xdy which implement +;; "a general sorting order for Western European languages" +;; +;; The aim for Sphinx is to be able to index in a Cyrillic document +;; also terms using the Latin alphabets, inclusive of letters +;; with diacritics. To this effect the xindy rules from lang/general +;; got manually re-coded to avoid collisions with the encoding +;; done by xindy for sorting words in Cyrillic languages, which was +;; observed not to use bytes with octal encoding 0o266 or higher. +;; +;; So here we use only 0o266 or higher bytes. +;; (Ŋ, ŋ, IJ, and ij are absent from +;; lang/general/utf8.xdy and not included here) +;; Contributed by the Sphinx team, 2018. + +(define-letter-group "A" :prefixes ("")) +(define-letter-group "B" :after "A" :prefixes ("")) +(define-letter-group "C" :after "B" :prefixes ("")) +(define-letter-group "D" :after "C" :prefixes ("")) +(define-letter-group "E" :after "D" :prefixes ("")) +(define-letter-group "F" :after "E" :prefixes ("")) +(define-letter-group "G" :after "F" :prefixes ("")) +(define-letter-group "H" :after "G" :prefixes ("")) +(define-letter-group "I" :after "H" :prefixes ("")) +(define-letter-group "J" :after "I" :prefixes ("")) +(define-letter-group "K" :after "J" :prefixes ("")) +(define-letter-group "L" :after "K" :prefixes ("")) +(define-letter-group "M" :after "L" :prefixes ("")) +(define-letter-group "N" :after "M" :prefixes ("")) +(define-letter-group "O" :after "N" :prefixes ("")) +(define-letter-group "P" :after "O" :prefixes ("")) +(define-letter-group "Q" :after "P" :prefixes ("")) +(define-letter-group "R" :after "Q" :prefixes ("")) +(define-letter-group "S" :after "R" :prefixes ("")) +(define-letter-group "T" :after "S" :prefixes ("")) +(define-letter-group "U" :after "T" :prefixes ("")) +(define-letter-group "V" :after "U" :prefixes ("")) +(define-letter-group "W" :after "V" :prefixes ("")) +(define-letter-group "X" :after "W" :prefixes ("")) +(define-letter-group "Y" :after "X" :prefixes ("")) +(define-letter-group "Z" :after "Y" :prefixes ("")) + +(define-rule-set "sphinx-xy-alphabetize" + + :rules (("À" "" :string) + ("Ă" "" :string) + ("â" "" :string) + ("Ä" "" :string) + ("à" "" :string) + ("Å" "" :string) + ("Ã" "" :string) + ("Á" "" :string) + ("á" "" :string) + ("ã" "" :string) + ("Â" "" :string) + ("ă" "" :string) + ("å" "" :string) + ("ą" "" :string) + ("ä" "" :string) + ("Ą" "" :string) + ("æ" "" :string) + ("Æ" "" :string) + ("ć" "" :string) + ("ĉ" "" :string) + ("ç" "" :string) + ("Č" "" :string) + ("č" "" :string) + ("Ĉ" "" :string) + ("Ç" "" :string) + ("Ć" "" :string) + ("ď" "" :string) + ("Đ" "" :string) + ("Ď" "" :string) + ("đ" "" :string) + ("ê" "" :string) + ("Ę" "" :string) + ("Ě" "" :string) + ("ë" "" :string) + ("ě" "" :string) + ("é" "" :string) + ("È" "" :string) + ("Ë" "" :string) + ("É" "" :string) + ("è" "" :string) + ("Ê" "" :string) + ("ę" "" :string) + ("ĝ" "" :string) + ("ğ" "" :string) + ("Ğ" "" :string) + ("Ĝ" "" :string) + ("ĥ" "" :string) + ("Ĥ" "" :string) + ("Ï" "" :string) + ("Í" "" :string) + ("ï" "" :string) + ("Î" "" :string) + ("î" "" :string) + ("ı" "" :string) + ("İ" "" :string) + ("í" "" :string) + ("Ì" "" :string) + ("ì" "" :string) + ("Ĵ" "" :string) + ("ĵ" "" :string) + ("ł" "" :string) + ("Ł" "" :string) + ("ľ" "" :string) + ("Ľ" "" :string) + ("ń" "" :string) + ("Ń" "" :string) + ("ñ" "" :string) + ("ň" "" :string) + ("Ñ" "" :string) + ("Ň" "" :string) + ("Õ" "" :string) + ("Ő" "" :string) + ("ó" "" :string) + ("ö" "" :string) + ("ô" "" :string) + ("ő" "" :string) + ("Ø" "" :string) + ("Ö" "" :string) + ("õ" "" :string) + ("Ô" "" :string) + ("ø" "" :string) + ("Ó" "" :string) + ("Ò" "" :string) + ("ò" "" :string) + ("œ" "ĺ" :string) + ("Œ" "ĺ" :string) + ("Ř" "" :string) + ("ř" "" :string) + ("Ŕ" "" :string) + ("ŕ" "" :string) + ("ŝ" "" :string) + ("Ś" "" :string) + ("ș" "" :string) + ("ş" "" :string) + ("Ŝ" "" :string) + ("ś" "" :string) + ("Ș" "" :string) + ("š" "" :string) + ("Ş" "" :string) + ("Š" "" :string) + ("ß" "" :string) + ("Ț" "" :string) + ("Ť" "" :string) + ("ț" "" :string) + ("ť" "" :string) + ("û" "" :string) + ("ŭ" "" :string) + ("ů" "" :string) + ("ű" "" :string) + ("ù" "" :string) + ("Ŭ" "" :string) + ("Ù" "" :string) + ("Ű" "" :string) + ("Ü" "" :string) + ("Ů" "" :string) + ("ú" "" :string) + ("Ú" "" :string) + ("Û" "" :string) + ("ü" "" :string) + ("ÿ" "" :string) + ("Ý" "" :string) + ("Ÿ" "" :string) + ("ý" "" :string) + ("Ż" "" :string) + ("Ž" "" :string) + ("Ź" "" :string) + ("ž" "" :string) + ("ż" "" :string) + ("ź" "" :string) + ("a" "" :string) + ("A" "" :string) + ("b" "" :string) + ("B" "" :string) + ("c" "" :string) + ("C" "" :string) + ("d" "" :string) + ("D" "" :string) + ("e" "" :string) + ("E" "" :string) + ("F" "" :string) + ("f" "" :string) + ("G" "" :string) + ("g" "" :string) + ("H" "" :string) + ("h" "" :string) + ("i" "" :string) + ("I" "" :string) + ("J" "" :string) + ("j" "" :string) + ("K" "" :string) + ("k" "" :string) + ("L" "" :string) + ("l" "" :string) + ("M" "" :string) + ("m" "" :string) + ("n" "" :string) + ("N" "" :string) + ("O" "" :string) + ("o" "" :string) + ("p" "" :string) + ("P" "" :string) + ("Q" "" :string) + ("q" "" :string) + ("r" "" :string) + ("R" "" :string) + ("S" "" :string) + ("s" "" :string) + ("t" "" :string) + ("T" "" :string) + ("u" "" :string) + ("U" "" :string) + ("v" "" :string) + ("V" "" :string) + ("W" "" :string) + ("w" "" :string) + ("x" "" :string) + ("X" "" :string) + ("Y" "" :string) + ("y" "" :string) + ("z" "" :string) + ("Z" "" :string) + )) + +(define-rule-set "sphinx-xy-resolve-diacritics" + + :rules (("Ĥ" "" :string) + ("ó" "" :string) + ("ľ" "" :string) + ("Ř" "" :string) + ("ĝ" "" :string) + ("ď" "" :string) + ("Ě" "" :string) + ("ĥ" "" :string) + ("Č" "" :string) + ("Ĵ" "" :string) + ("ě" "" :string) + ("ž" "" :string) + ("Ď" "" :string) + ("ř" "" :string) + ("Ž" "" :string) + ("ı" "" :string) + ("Ť" "" :string) + ("á" "" :string) + ("č" "" :string) + ("Á" "" :string) + ("ň" "" :string) + ("Š" "" :string) + ("Ň" "" :string) + ("ĵ" "" :string) + ("ť" "" :string) + ("Ó" "" :string) + ("ý" "" :string) + ("Ĝ" "" :string) + ("Ú" "" :string) + ("Ľ" "" :string) + ("š" "" :string) + ("Ý" "" :string) + ("ú" "" :string) + ("Ś" "" :string) + ("ć" "" :string) + ("Ł" "" :string) + ("ł" "" :string) + ("ń" "" :string) + ("À" "" :string) + ("Ź" "" :string) + ("à" "" :string) + ("Ń" "" :string) + ("Đ" "" :string) + ("ÿ" "" :string) + ("ś" "" :string) + ("Ğ" "" :string) + ("ğ" "" :string) + ("Ù" "" :string) + ("İ" "" :string) + ("đ" "" :string) + ("ù" "" :string) + ("Ț" "" :string) + ("é" "" :string) + ("ŕ" "" :string) + ("Ć" "" :string) + ("ț" "" :string) + ("ò" "" :string) + ("ź" "" :string) + ("Ò" "" :string) + ("Ÿ" "" :string) + ("Ŕ" "" :string) + ("É" "" :string) + ("ĉ" "" :string) + ("ô" "" :string) + ("Í" "" :string) + ("ŝ" "" :string) + ("Ż" "" :string) + ("Ă" "" :string) + ("Ŝ" "" :string) + ("ñ" "" :string) + ("ŭ" "" :string) + ("í" "" :string) + ("È" "" :string) + ("Ô" "" :string) + ("Ŭ" "" :string) + ("ż" "" :string) + ("Ñ" "" :string) + ("è" "" :string) + ("Ĉ" "" :string) + ("ă" "" :string) + ("â" "" :string) + ("û" "" :string) + ("ê" "" :string) + ("Õ" "" :string) + ("õ" "" :string) + ("ș" "" :string) + ("ç" "" :string) + ("Â" "" :string) + ("Ê" "" :string) + ("Û" "" :string) + ("Ç" "" :string) + ("ì" "" :string) + ("Ì" "" :string) + ("Ș" "" :string) + ("ö" "" :string) + ("Ö" "" :string) + ("ş" "" :string) + ("ů" "" :string) + ("ë" "" :string) + ("ã" "" :string) + ("î" "" :string) + ("Î" "" :string) + ("Ã" "" :string) + ("Ş" "" :string) + ("Ů" "" :string) + ("Ë" "" :string) + ("ï" "" :string) + ("Ő" "" :string) + ("Ï" "" :string) + ("Ę" "" :string) + ("ő" "" :string) + ("Ü" "" :string) + ("Å" "" :string) + ("ü" "" :string) + ("ę" "" :string) + ("å" "" :string) + ("Ä" "" :string) + ("ű" "" :string) + ("Ø" "" :string) + ("ø" "" :string) + ("Ű" "" :string) + ("ä" "" :string) + ("Ą" "" :string) + ("ą" "" :string) + ("œ" "" :string) + ("ß" "" :string) + ("Æ" "" :string) + ("Œ" "" :string) + ("æ" "" :string) + ("e" "" :string) + ("t" "" :string) + ("L" "" :string) + ("Y" "" :string) + ("J" "" :string) + ("a" "" :string) + ("p" "" :string) + ("u" "" :string) + ("j" "" :string) + ("b" "" :string) + ("G" "" :string) + ("U" "" :string) + ("F" "" :string) + ("H" "" :string) + ("i" "" :string) + ("z" "" :string) + ("c" "" :string) + ("l" "" :string) + ("A" "" :string) + ("Q" "" :string) + ("w" "" :string) + ("D" "" :string) + ("R" "" :string) + ("d" "" :string) + ("s" "" :string) + ("r" "" :string) + ("k" "" :string) + ("v" "" :string) + ("m" "" :string) + ("P" "" :string) + ("y" "" :string) + ("K" "" :string) + ("q" "" :string) + ("S" "" :string) + ("I" "" :string) + ("C" "" :string) + ("M" "" :string) + ("Z" "" :string) + ("T" "" :string) + ("W" "" :string) + ("B" "" :string) + ("h" "" :string) + ("x" "" :string) + ("X" "" :string) + ("f" "" :string) + ("E" "" :string) + ("V" "" :string) + ("N" "" :string) + ("O" "" :string) + ("o" "" :string) + ("g" "" :string) + ("n" "" :string) + )) + +(define-rule-set "sphinx-xy-resolve-case" + + :rules (("Ú" "8" :string) + ("Ÿ" "8" :string) + ("Ç" "8" :string) + ("Ĉ" "8" :string) + ("Ŕ" "8" :string) + ("Ľ" "8" :string) + ("Ů" "8" :string) + ("Ý" "8" :string) + ("É" "8" :string) + ("Ë" "8" :string) + ("Ș" "8" :string) + ("Ì" "8" :string) + ("Ê" "8" :string) + ("Ň" "8" :string) + ("Ą" "8" :string) + ("Š" "8" :string) + ("Û" "8" :string) + ("Ş" "8" :string) + ("Ć" "8" :string) + ("Ò" "8" :string) + ("Ĝ" "8" :string) + ("Ñ" "8" :string) + ("Ó" "8" :string) + ("Î" "8" :string) + ("Á" "8" :string) + ("Ã" "8" :string) + ("Ț" "8" :string) + ("Å" "8" :string) + ("Ğ" "8" :string) + ("Ü" "8" :string) + ("È" "8" :string) + ("Ô" "8" :string) + ("İ" "8" :string) + ("Ű" "8" :string) + ("Ù" "8" :string) + ("Ŭ" "8" :string) + ("Â" "8" :string) + ("Ť" "8" :string) + ("Ń" "8" :string) + ("Ď" "8" :string) + ("Ź" "8" :string) + ("Ž" "8" :string) + ("Đ" "8" :string) + ("Ŝ" "8" :string) + ("Č" "8" :string) + ("Ĵ" "8" :string) + ("Ö" "8" :string) + ("Ø" "8" :string) + ("Ż" "8" :string) + ("Ł" "8" :string) + ("Ă" "8" :string) + ("Ě" "8" :string) + ("Ő" "8" :string) + ("Õ" "8" :string) + ("Ę" "8" :string) + ("Ï" "8" :string) + ("À" "8" :string) + ("Ĥ" "8" :string) + ("Ä" "8" :string) + ("Ś" "8" :string) + ("Ř" "8" :string) + ("Í" "8" :string) + ("Œ" "89" :string) + ("Æ" "89" :string) + ("ì" "9" :string) + ("è" "9" :string) + ("ą" "9" :string) + ("š" "9" :string) + ("ú" "9" :string) + ("å" "9" :string) + ("ă" "9" :string) + ("ę" "9" :string) + ("ü" "9" :string) + ("ź" "9" :string) + ("ò" "9" :string) + ("ť" "9" :string) + ("ț" "9" :string) + ("ĵ" "9" :string) + ("ŕ" "9" :string) + ("ż" "9" :string) + ("ä" "9" :string) + ("ý" "9" :string) + ("ù" "9" :string) + ("á" "9" :string) + ("é" "9" :string) + ("č" "9" :string) + ("ň" "9" :string) + ("ś" "9" :string) + ("ø" "9" :string) + ("í" "9" :string) + ("đ" "9" :string) + ("ı" "9" :string) + ("ğ" "9" :string) + ("î" "9" :string) + ("ã" "9" :string) + ("à" "9" :string) + ("ř" "9" :string) + ("ő" "9" :string) + ("ů" "9" :string) + ("ș" "9" :string) + ("ÿ" "9" :string) + ("ë" "9" :string) + ("ŭ" "9" :string) + ("ç" "9" :string) + ("ű" "9" :string) + ("ñ" "9" :string) + ("õ" "9" :string) + ("ě" "9" :string) + ("ş" "9" :string) + ("ž" "9" :string) + ("ĝ" "9" :string) + ("ŝ" "9" :string) + ("ń" "9" :string) + ("û" "9" :string) + ("ł" "9" :string) + ("ď" "9" :string) + ("ĥ" "9" :string) + ("ê" "9" :string) + ("ô" "9" :string) + ("ĉ" "9" :string) + ("â" "9" :string) + ("ć" "9" :string) + ("ï" "9" :string) + ("ö" "9" :string) + ("ľ" "9" :string) + ("ó" "9" :string) + ("æ" "99" :string) + ("ß" "99" :string) + ("œ" "99" :string) + ("N" "8" :string) + ("V" "8" :string) + ("O" "8" :string) + ("X" "8" :string) + ("E" "8" :string) + ("P" "8" :string) + ("K" "8" :string) + ("T" "8" :string) + ("Z" "8" :string) + ("M" "8" :string) + ("C" "8" :string) + ("I" "8" :string) + ("S" "8" :string) + ("B" "8" :string) + ("W" "8" :string) + ("D" "8" :string) + ("R" "8" :string) + ("H" "8" :string) + ("F" "8" :string) + ("Q" "8" :string) + ("A" "8" :string) + ("G" "8" :string) + ("U" "8" :string) + ("J" "8" :string) + ("Y" "8" :string) + ("L" "8" :string) + ("o" "9" :string) + ("n" "9" :string) + ("g" "9" :string) + ("x" "9" :string) + ("f" "9" :string) + ("y" "9" :string) + ("q" "9" :string) + ("h" "9" :string) + ("w" "9" :string) + ("s" "9" :string) + ("d" "9" :string) + ("v" "9" :string) + ("k" "9" :string) + ("r" "9" :string) + ("m" "9" :string) + ("z" "9" :string) + ("c" "9" :string) + ("i" "9" :string) + ("l" "9" :string) + ("b" "9" :string) + ("j" "9" :string) + ("a" "9" :string) + ("p" "9" :string) + ("u" "9" :string) + ("t" "9" :string) + ("e" "9" :string) + )) + +(use-rule-set :run 0 + :rule-set ("sphinx-xy-alphabetize")) +(use-rule-set :run 1 + :rule-set ("sphinx-xy-resolve-diacritics")) +(use-rule-set :run 2 + :rule-set ("sphinx-xy-resolve-case")) diff --git a/krb5-1.21.3/doc/pdf/admin.pdf b/krb5-1.21.3/doc/pdf/admin.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bf21d4e21c889f72b3e7c460021d1735aea4a3b0 GIT binary patch literal 648892 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 %N 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�>;);1vbHO8Xn4x+r=-4N@HI`b= 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%0A&V0T(slH_RE0ZP?j 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�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

tOH`cgWT6jgQ%p7Fkr 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

;s9=@E6!|G9w+}=lRi@L?0qr~1yp&ab& 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 z

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

=YdImYwICMrQg@dr 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 GRR06+Vfh*W literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/doc/pdf/admin.tex b/krb5-1.21.3/doc/pdf/admin.tex new file mode 100644 index 00000000..8a67a6d0 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/admin.tex @@ -0,0 +1,12287 @@ +%% Generated by Sphinx. +\def\sphinxdocclass{report} +\documentclass[letterpaper,10pt,english]{sphinxmanual} +\ifdefined\pdfpxdimen + \let\sphinxpxdimen\pdfpxdimen\else\newdimen\sphinxpxdimen +\fi \sphinxpxdimen=.75bp\relax +\ifdefined\pdfimageresolution + \pdfimageresolution= \numexpr \dimexpr1in\relax/\sphinxpxdimen\relax +\fi +%% let collapsible pdf bookmarks panel have high depth per default +\PassOptionsToPackage{bookmarksdepth=5}{hyperref} + +\PassOptionsToPackage{warn}{textcomp} +\usepackage[utf8]{inputenc} +\ifdefined\DeclareUnicodeCharacter +% support both utf8 and utf8x syntaxes + \ifdefined\DeclareUnicodeCharacterAsOptional + \def\sphinxDUC#1{\DeclareUnicodeCharacter{"#1}} + \else + \let\sphinxDUC\DeclareUnicodeCharacter + \fi + \sphinxDUC{00A0}{\nobreakspace} + \sphinxDUC{2500}{\sphinxunichar{2500}} + \sphinxDUC{2502}{\sphinxunichar{2502}} + \sphinxDUC{2514}{\sphinxunichar{2514}} + \sphinxDUC{251C}{\sphinxunichar{251C}} + \sphinxDUC{2572}{\textbackslash} +\fi +\usepackage{cmap} +\usepackage[T1]{fontenc} +\usepackage{amsmath,amssymb,amstext} +\usepackage{babel} + + + +\usepackage{tgtermes} +\usepackage{tgheros} +\renewcommand{\ttdefault}{txtt} + + + +\usepackage[Bjarne]{fncychap} +\usepackage{sphinx} + +\fvset{fontsize=auto} +\usepackage{geometry} + + +% Include hyperref last. +\usepackage{hyperref} +% Fix anchor placement for figures with captions. +\usepackage{hypcap}% it must be loaded after hyperref. +% Set up styles of URL: it should be placed after hyperref. +\urlstyle{same} + + +\usepackage{sphinxmessages} +\setcounter{tocdepth}{0} + + + +\title{Kerberos Administration Guide} +\date{ } +\release{1.21.3} +\author{MIT} +\newcommand{\sphinxlogo}{\vbox{}} +\renewcommand{\releasename}{Release} +\makeindex +\begin{document} + +\pagestyle{empty} +\sphinxmaketitle +\pagestyle{plain} +\sphinxtableofcontents +\pagestyle{normal} +\phantomsection\label{\detokenize{admin/index::doc}} + + + +\chapter{Installation guide} +\label{\detokenize{admin/install:installation-guide}}\label{\detokenize{admin/install::doc}} + +\section{Contents} +\label{\detokenize{admin/install:contents}} + +\subsection{Installing KDCs} +\label{\detokenize{admin/install_kdc:installing-kdcs}}\label{\detokenize{admin/install_kdc::doc}} +\sphinxAtStartPar +When setting up Kerberos in a production environment, it is best to +have multiple replica KDCs alongside with a primary KDC to ensure the +continued availability of the Kerberized services. Each KDC contains +a copy of the Kerberos database. The primary KDC contains the +writable copy of the realm database, which it replicates to the +replica KDCs at regular intervals. All database changes (such as +password changes) are made on the primary KDC. Replica KDCs provide +Kerberos ticket\sphinxhyphen{}granting services, but not database administration, +when the primary KDC is unavailable. MIT recommends that you install +all of your KDCs to be able to function as either the primary or one +of the replicas. This will enable you to easily switch your primary +KDC with one of the replicas if necessary (see +{\hyperref[\detokenize{admin/install_kdc:switch-primary-replica}]{\sphinxcrossref{\DUrole{std,std-ref}{Switching primary and replica KDCs}}}}). This installation procedure is based +on that recommendation. + +\begin{sphinxadmonition}{warning}{Warning:}\begin{itemize} +\item {} +\sphinxAtStartPar +The Kerberos system relies on the availability of correct time +information. Ensure that the primary and all replica KDCs have +properly synchronized clocks. + +\item {} +\sphinxAtStartPar +It is best to install and run KDCs on secured and dedicated +hardware with limited access. If your KDC is also a file +server, FTP server, Web server, or even just a client machine, +someone who obtained root access through a security hole in any +of those areas could potentially gain access to the Kerberos +database. + +\end{itemize} +\end{sphinxadmonition} + + +\subsubsection{Install and configure the primary KDC} +\label{\detokenize{admin/install_kdc:install-and-configure-the-primary-kdc}} +\sphinxAtStartPar +Install Kerberos either from the OS\sphinxhyphen{}provided packages or from the +source (See \DUrole{xref,std,std-ref}{do\_build}). + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +For the purpose of this document we will use the following +names: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kerberos}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{o}{\PYGZhy{}} \PYG{n}{primary} \PYG{n}{KDC} +\PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{o}{\PYGZhy{}} \PYG{n}{replica} \PYG{n}{KDC} +\PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{\PYGZhy{}} \PYG{n}{realm} \PYG{n}{name} +\PYG{o}{.}\PYG{n}{k5}\PYG{o}{.}\PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{\PYGZhy{}} \PYG{n}{stash} \PYG{n}{file} +\PYG{n}{admin}\PYG{o}{/}\PYG{n}{admin} \PYG{o}{\PYGZhy{}} \PYG{n}{admin} \PYG{n}{principal} +\end{sphinxVerbatim} + +\sphinxAtStartPar +See {\hyperref[\detokenize{mitK5defaults:mitk5defaults}]{\sphinxcrossref{\DUrole{std,std-ref}{MIT Kerberos defaults}}}} for the default names and locations +of the relevant to this topic files. Adjust the names and +paths to your system environment. +\end{sphinxadmonition} + + +\subsubsection{Edit KDC configuration files} +\label{\detokenize{admin/install_kdc:edit-kdc-configuration-files}} +\sphinxAtStartPar +Modify the configuration files, {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} and +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}, to reflect the correct information (such as +domain\sphinxhyphen{}realm mappings and Kerberos servers names) for your realm. +(See {\hyperref[\detokenize{mitK5defaults:mitk5defaults}]{\sphinxcrossref{\DUrole{std,std-ref}{MIT Kerberos defaults}}}} for the recommended default locations for +these files). + +\sphinxAtStartPar +Most of the tags in the configuration have default values that will +work well for most sites. There are some tags in the +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} file whose values must be specified, and this +section will explain those. + +\sphinxAtStartPar +If the locations for these configuration files differs from the +default ones, set \sphinxstylestrong{KRB5\_CONFIG} and \sphinxstylestrong{KRB5\_KDC\_PROFILE} environment +variables to point to the krb5.conf and kdc.conf respectively. For +example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{export} \PYG{n}{KRB5\PYGZus{}CONFIG}\PYG{o}{=}\PYG{o}{/}\PYG{n}{yourdir}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{conf} +\PYG{n}{export} \PYG{n}{KRB5\PYGZus{}KDC\PYGZus{}PROFILE}\PYG{o}{=}\PYG{o}{/}\PYG{n}{yourdir}\PYG{o}{/}\PYG{n}{kdc}\PYG{o}{.}\PYG{n}{conf} +\end{sphinxVerbatim} + + +\paragraph{krb5.conf} +\label{\detokenize{admin/install_kdc:krb5-conf}} +\sphinxAtStartPar +If you are not using DNS TXT records (see {\hyperref[\detokenize{admin/realm_config:mapping-hostnames}]{\sphinxcrossref{\DUrole{std,std-ref}{Mapping hostnames onto Kerberos realms}}}}), +you must specify the \sphinxstylestrong{default\_realm} in the {\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}} +section. If you are not using DNS URI or SRV records (see +{\hyperref[\detokenize{admin/realm_config:kdc-hostnames}]{\sphinxcrossref{\DUrole{std,std-ref}{Hostnames for KDCs}}}} and {\hyperref[\detokenize{admin/realm_config:kdc-discovery}]{\sphinxcrossref{\DUrole{std,std-ref}{KDC Discovery}}}}), you must include the +\sphinxstylestrong{kdc} tag for each \sphinxstyleemphasis{realm} in the {\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} section. To +communicate with the kadmin server in each realm, the \sphinxstylestrong{admin\_server} +tag must be set in the +{\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} section. + +\sphinxAtStartPar +An example krb5.conf file: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{libdefaults}\PYG{p}{]} + \PYG{n}{default\PYGZus{}realm} \PYG{o}{=} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} + +\PYG{p}{[}\PYG{n}{realms}\PYG{p}{]} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{kdc} \PYG{o}{=} \PYG{n}{kerberos}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{n}{kdc} \PYG{o}{=} \PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{n}{admin\PYGZus{}server} \PYG{o}{=} \PYG{n}{kerberos}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + + +\paragraph{kdc.conf} +\label{\detokenize{admin/install_kdc:kdc-conf}} +\sphinxAtStartPar +The kdc.conf file can be used to control the listening ports of the +KDC and kadmind, as well as realm\sphinxhyphen{}specific defaults, the database type +and location, and logging. + +\sphinxAtStartPar +An example kdc.conf file: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{kdcdefaults}\PYG{p}{]} + \PYG{n}{kdc\PYGZus{}listen} \PYG{o}{=} \PYG{l+m+mi}{88} + \PYG{n}{kdc\PYGZus{}tcp\PYGZus{}listen} \PYG{o}{=} \PYG{l+m+mi}{88} + +\PYG{p}{[}\PYG{n}{realms}\PYG{p}{]} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{kadmind\PYGZus{}port} \PYG{o}{=} \PYG{l+m+mi}{749} + \PYG{n}{max\PYGZus{}life} \PYG{o}{=} \PYG{l+m+mi}{12}\PYG{n}{h} \PYG{l+m+mi}{0}\PYG{n}{m} \PYG{l+m+mi}{0}\PYG{n}{s} + \PYG{n}{max\PYGZus{}renewable\PYGZus{}life} \PYG{o}{=} \PYG{l+m+mi}{7}\PYG{n}{d} \PYG{l+m+mi}{0}\PYG{n}{h} \PYG{l+m+mi}{0}\PYG{n}{m} \PYG{l+m+mi}{0}\PYG{n}{s} + \PYG{n}{master\PYGZus{}key\PYGZus{}type} \PYG{o}{=} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts} + \PYG{n}{supported\PYGZus{}enctypes} \PYG{o}{=} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{p}{:}\PYG{n}{normal} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{p}{:}\PYG{n}{normal} + \PYG{c+c1}{\PYGZsh{} If the default location does not suit your setup,} + \PYG{c+c1}{\PYGZsh{} explicitly configure the following values:} + \PYG{c+c1}{\PYGZsh{} database\PYGZus{}name = /var/krb5kdc/principal} + \PYG{c+c1}{\PYGZsh{} key\PYGZus{}stash\PYGZus{}file = /var/krb5kdc/.k5.ATHENA.MIT.EDU} + \PYG{c+c1}{\PYGZsh{} acl\PYGZus{}file = /var/krb5kdc/kadm5.acl} + \PYG{p}{\PYGZcb{}} + +\PYG{p}{[}\PYG{n}{logging}\PYG{p}{]} + \PYG{c+c1}{\PYGZsh{} By default, the KDC and kadmind will log output using} + \PYG{c+c1}{\PYGZsh{} syslog. You can instead send log output to files like this:} + \PYG{n}{kdc} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{var}\PYG{o}{/}\PYG{n}{log}\PYG{o}{/}\PYG{n}{krb5kdc}\PYG{o}{.}\PYG{n}{log} + \PYG{n}{admin\PYGZus{}server} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{var}\PYG{o}{/}\PYG{n}{log}\PYG{o}{/}\PYG{n}{kadmin}\PYG{o}{.}\PYG{n}{log} + \PYG{n}{default} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{var}\PYG{o}{/}\PYG{n}{log}\PYG{o}{/}\PYG{n}{krb5lib}\PYG{o}{.}\PYG{n}{log} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Replace \sphinxcode{\sphinxupquote{ATHENA.MIT.EDU}} and \sphinxcode{\sphinxupquote{kerberos.mit.edu}} with the name of +your Kerberos realm and server respectively. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +You have to have write permission on the target directories +(these directories must exist) used by \sphinxstylestrong{database\_name}, +\sphinxstylestrong{key\_stash\_file}, and \sphinxstylestrong{acl\_file}. +\end{sphinxadmonition} + + +\subsubsection{Create the KDC database} +\label{\detokenize{admin/install_kdc:create-the-kdc-database}}\label{\detokenize{admin/install_kdc:create-db}} +\sphinxAtStartPar +You will use the {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} command on the primary KDC to +create the Kerberos database and the optional \DUrole{xref,std,std-ref}{stash\_definition}. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +If you choose not to install a stash file, the KDC will +prompt you for the master key each time it starts up. This +means that the KDC will not be able to start automatically, +such as after a system reboot. +\end{sphinxadmonition} + +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} will prompt you for the master password for the +Kerberos database. This password can be any string. A good password +is one you can remember, but that no one else can guess. Examples of +bad passwords are words that can be found in a dictionary, any common +or popular name, especially a famous person (or cartoon character), +your username in any form (e.g., forward, backward, repeated twice, +etc.), and any of the sample passwords that appear in this manual. +One example of a password which might be good if it did not appear in +this manual is “MITiys4K5!”, which represents the sentence “MIT is +your source for Kerberos 5!” (It’s the first letter of each word, +substituting the numeral “4” for the word “for”, and includes the +punctuation mark at the end.) + +\sphinxAtStartPar +The following is an example of how to create a Kerberos database and +stash file on the primary KDC, using the {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} command. +Replace \sphinxcode{\sphinxupquote{ATHENA.MIT.EDU}} with the name of your Kerberos realm: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kdb5\PYGZus{}util} \PYG{n}{create} \PYG{o}{\PYGZhy{}}\PYG{n}{r} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{\PYGZhy{}}\PYG{n}{s} + +\PYG{n}{Initializing} \PYG{n}{database} \PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{/usr/local/var/krb5kdc/principal}\PYG{l+s+s1}{\PYGZsq{}} \PYG{k}{for} \PYG{n}{realm} \PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{ATHENA.MIT.EDU}\PYG{l+s+s1}{\PYGZsq{}}\PYG{p}{,} +\PYG{n}{master} \PYG{n}{key} \PYG{n}{name} \PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{K/M@ATHENA.MIT.EDU}\PYG{l+s+s1}{\PYGZsq{}} +\PYG{n}{You} \PYG{n}{will} \PYG{n}{be} \PYG{n}{prompted} \PYG{k}{for} \PYG{n}{the} \PYG{n}{database} \PYG{n}{Master} \PYG{n}{Password}\PYG{o}{.} +\PYG{n}{It} \PYG{o+ow}{is} \PYG{n}{important} \PYG{n}{that} \PYG{n}{you} \PYG{n}{NOT} \PYG{n}{FORGET} \PYG{n}{this} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Enter} \PYG{n}{KDC} \PYG{n}{database} \PYG{n}{master} \PYG{n}{key}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{=} \PYG{n}{Type} \PYG{n}{the} \PYG{n}{master} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Re}\PYG{o}{\PYGZhy{}}\PYG{n}{enter} \PYG{n}{KDC} \PYG{n}{database} \PYG{n}{master} \PYG{n}{key} \PYG{n}{to} \PYG{n}{verify}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{=} \PYG{n}{Type} \PYG{n}{it} \PYG{n}{again}\PYG{o}{.} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +This will create five files in {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}} (or at the locations specified +in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}): +\begin{itemize} +\item {} +\sphinxAtStartPar +two Kerberos database files, \sphinxcode{\sphinxupquote{principal}}, and \sphinxcode{\sphinxupquote{principal.ok}} + +\item {} +\sphinxAtStartPar +the Kerberos administrative database file, \sphinxcode{\sphinxupquote{principal.kadm5}} + +\item {} +\sphinxAtStartPar +the administrative database lock file, \sphinxcode{\sphinxupquote{principal.kadm5.lock}} + +\item {} +\sphinxAtStartPar +the stash file, in this example \sphinxcode{\sphinxupquote{.k5.ATHENA.MIT.EDU}}. If you do +not want a stash file, run the above command without the \sphinxstylestrong{\sphinxhyphen{}s} +option. + +\end{itemize} + +\sphinxAtStartPar +For more information on administrating Kerberos database see +{\hyperref[\detokenize{admin/database:db-operations}]{\sphinxcrossref{\DUrole{std,std-ref}{Operations on the Kerberos database}}}}. + + +\subsubsection{Add administrators to the ACL file} +\label{\detokenize{admin/install_kdc:add-administrators-to-the-acl-file}}\label{\detokenize{admin/install_kdc:admin-acl}} +\sphinxAtStartPar +Next, you need create an Access Control List (ACL) file and put the +Kerberos principal of at least one of the administrators into it. +This file is used by the {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} daemon to control which +principals may view and make privileged modifications to the Kerberos +database files. The ACL filename is determined by the \sphinxstylestrong{acl\_file} +variable in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}; the default is {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/kadm5.acl}}. + +\sphinxAtStartPar +For more information on Kerberos ACL file see {\hyperref[\detokenize{admin/conf_files/kadm5_acl:kadm5-acl-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kadm5.acl}}}}. + + +\subsubsection{Add administrators to the Kerberos database} +\label{\detokenize{admin/install_kdc:add-administrators-to-the-kerberos-database}}\label{\detokenize{admin/install_kdc:addadmin-kdb}} +\sphinxAtStartPar +Next you need to add administrative principals (i.e., principals who +are allowed to administer Kerberos database) to the Kerberos database. +You \sphinxstyleemphasis{must} add at least one principal now to allow communication +between the Kerberos administration daemon kadmind and the kadmin +program over the network for further administration. To do this, use +the kadmin.local utility on the primary KDC. kadmin.local is designed +to be run on the primary KDC host without using Kerberos +authentication to an admin server; instead, it must have read and +write access to the Kerberos database on the local filesystem. + +\sphinxAtStartPar +The administrative principals you create should be the ones you added +to the ACL file (see {\hyperref[\detokenize{admin/install_kdc:admin-acl}]{\sphinxcrossref{\DUrole{std,std-ref}{Add administrators to the ACL file}}}}). + +\sphinxAtStartPar +In the following example, the administrative principal \sphinxcode{\sphinxupquote{admin/admin}} +is created: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kadmin}\PYG{o}{.}\PYG{n}{local} + +\PYG{n}{kadmin}\PYG{o}{.}\PYG{n}{local}\PYG{p}{:} \PYG{n}{addprinc} \PYG{n}{admin}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} + +\PYG{n}{No} \PYG{n}{policy} \PYG{n}{specified} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{admin/admin@ATHENA.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{;} +\PYG{n}{assigning} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{default}\PYG{l+s+s2}{\PYGZdq{}}\PYG{o}{.} +\PYG{n}{Enter} \PYG{n}{password} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{admin}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{=} \PYG{n}{Enter} \PYG{n}{a} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Re}\PYG{o}{\PYGZhy{}}\PYG{n}{enter} \PYG{n}{password} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{admin}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{=} \PYG{n}{Type} \PYG{n}{it} \PYG{n}{again}\PYG{o}{.} +\PYG{n}{Principal} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{admin/admin@ATHENA.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{created}\PYG{o}{.} +\PYG{n}{kadmin}\PYG{o}{.}\PYG{n}{local}\PYG{p}{:} +\end{sphinxVerbatim} + + +\subsubsection{Start the Kerberos daemons on the primary KDC} +\label{\detokenize{admin/install_kdc:start-the-kerberos-daemons-on-the-primary-kdc}}\label{\detokenize{admin/install_kdc:start-kdc-daemons}} +\sphinxAtStartPar +At this point, you are ready to start the Kerberos KDC +({\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}}) and administrative daemons on the primary KDC. To +do so, type: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{krb5kdc} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kadmind} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Each server daemon will fork and run in the background. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +Assuming you want these daemons to start up automatically at +boot time, you can add them to the KDC’s \sphinxcode{\sphinxupquote{/etc/rc}} or +\sphinxcode{\sphinxupquote{/etc/inittab}} file. You need to have a +\DUrole{xref,std,std-ref}{stash\_definition} in order to do this. +\end{sphinxadmonition} + +\sphinxAtStartPar +You can verify that they started properly by checking for their +startup messages in the logging locations you defined in +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} (see {\hyperref[\detokenize{admin/conf_files/kdc_conf:logging}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}logging{]}}}}}). For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{tail} \PYG{o}{/}\PYG{n}{var}\PYG{o}{/}\PYG{n}{log}\PYG{o}{/}\PYG{n}{krb5kdc}\PYG{o}{.}\PYG{n}{log} +\PYG{n}{Dec} \PYG{l+m+mi}{02} \PYG{l+m+mi}{12}\PYG{p}{:}\PYG{l+m+mi}{35}\PYG{p}{:}\PYG{l+m+mi}{47} \PYG{n}{beeblebrox} \PYG{n}{krb5kdc}\PYG{p}{[}\PYG{l+m+mi}{3187}\PYG{p}{]}\PYG{p}{(}\PYG{n}{info}\PYG{p}{)}\PYG{p}{:} \PYG{n}{commencing} \PYG{n}{operation} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{tail} \PYG{o}{/}\PYG{n}{var}\PYG{o}{/}\PYG{n}{log}\PYG{o}{/}\PYG{n}{kadmin}\PYG{o}{.}\PYG{n}{log} +\PYG{n}{Dec} \PYG{l+m+mi}{02} \PYG{l+m+mi}{12}\PYG{p}{:}\PYG{l+m+mi}{35}\PYG{p}{:}\PYG{l+m+mi}{52} \PYG{n}{beeblebrox} \PYG{n}{kadmind}\PYG{p}{[}\PYG{l+m+mi}{3189}\PYG{p}{]}\PYG{p}{(}\PYG{n}{info}\PYG{p}{)}\PYG{p}{:} \PYG{n}{starting} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Any errors the daemons encounter while starting will also be listed in +the logging output. + +\sphinxAtStartPar +As an additional verification, check if \DUrole{xref,std,std-ref}{kinit(1)} succeeds +against the principals that you have created on the previous step +({\hyperref[\detokenize{admin/install_kdc:addadmin-kdb}]{\sphinxcrossref{\DUrole{std,std-ref}{Add administrators to the Kerberos database}}}}). Run: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kinit} \PYG{n}{admin}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\end{sphinxVerbatim} + + +\subsubsection{Install the replica KDCs} +\label{\detokenize{admin/install_kdc:install-the-replica-kdcs}} +\sphinxAtStartPar +You are now ready to start configuring the replica KDCs. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +Assuming you are setting the KDCs up so that you can easily +switch the primary KDC with one of the replicas, you should +perform each of these steps on the primary KDC as well as +the replica KDCs, unless these instructions specify +otherwise. +\end{sphinxadmonition} + + +\paragraph{Create host keytabs for replica KDCs} +\label{\detokenize{admin/install_kdc:create-host-keytabs-for-replica-kdcs}}\label{\detokenize{admin/install_kdc:replica-host-key}} +\sphinxAtStartPar +Each KDC needs a \sphinxcode{\sphinxupquote{host}} key in the Kerberos database. These keys +are used for mutual authentication when propagating the database dump +file from the primary KDC to the secondary KDC servers. + +\sphinxAtStartPar +On the primary KDC, connect to administrative interface and create the +host principal for each of the KDCs’ \sphinxcode{\sphinxupquote{host}} services. For example, +if the primary KDC were called \sphinxcode{\sphinxupquote{kerberos.mit.edu}}, and you had a +replica KDC named \sphinxcode{\sphinxupquote{kerberos\sphinxhyphen{}1.mit.edu}}, you would type the +following: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kadmin} +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{addprinc} \PYG{o}{\PYGZhy{}}\PYG{n}{randkey} \PYG{n}{host}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} +\PYG{n}{No} \PYG{n}{policy} \PYG{n}{specified} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{host/kerberos.mit.edu@ATHENA.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{;} \PYG{n}{assigning} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{default}\PYG{l+s+s2}{\PYGZdq{}} +\PYG{n}{Principal} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{host/kerberos.mit.edu@ATHENA.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{created}\PYG{o}{.} + +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{addprinc} \PYG{o}{\PYGZhy{}}\PYG{n}{randkey} \PYG{n}{host}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} +\PYG{n}{No} \PYG{n}{policy} \PYG{n}{specified} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{host/kerberos\PYGZhy{}1.mit.edu@ATHENA.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{;} \PYG{n}{assigning} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{default}\PYG{l+s+s2}{\PYGZdq{}} +\PYG{n}{Principal} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{host/kerberos\PYGZhy{}1.mit.edu@ATHENA.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{created}\PYG{o}{.} +\end{sphinxVerbatim} + +\sphinxAtStartPar +It is not strictly necessary to have the primary KDC server in the +Kerberos database, but it can be handy if you want to be able to swap +the primary KDC with one of the replicas. + +\sphinxAtStartPar +Next, extract \sphinxcode{\sphinxupquote{host}} random keys for all participating KDCs and +store them in each host’s default keytab file. Ideally, you should +extract each keytab locally on its own KDC. If this is not feasible, +you should use an encrypted session to send them across the network. +To extract a keytab directly on a replica KDC called +\sphinxcode{\sphinxupquote{kerberos\sphinxhyphen{}1.mit.edu}}, you would execute the following command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{ktadd} \PYG{n}{host}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{2}\PYG{p}{,} \PYG{n}{encryption} + \PYG{n+nb}{type} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{2}\PYG{p}{,} \PYG{n}{encryption} + \PYG{n+nb}{type} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{2}\PYG{p}{,} \PYG{n}{encryption} + \PYG{n+nb}{type} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha384}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{192} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{2}\PYG{p}{,} \PYG{n}{encryption} + \PYG{n+nb}{type} \PYG{n}{arcfour}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If you are instead extracting a keytab for the replica KDC called +\sphinxcode{\sphinxupquote{kerberos\sphinxhyphen{}1.mit.edu}} on the primary KDC, you should use a dedicated +temporary keytab file for that machine’s keytab: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{ktadd} \PYG{o}{\PYGZhy{}}\PYG{n}{k} \PYG{o}{/}\PYG{n}{tmp}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{keytab} \PYG{n}{host}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{2}\PYG{p}{,} \PYG{n}{encryption} + \PYG{n+nb}{type} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{2}\PYG{p}{,} \PYG{n}{encryption} + \PYG{n+nb}{type} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The file \sphinxcode{\sphinxupquote{/tmp/kerberos\sphinxhyphen{}1.keytab}} can then be installed as +\sphinxcode{\sphinxupquote{/etc/krb5.keytab}} on the host \sphinxcode{\sphinxupquote{kerberos\sphinxhyphen{}1.mit.edu}}. + + +\paragraph{Configure replica KDCs} +\label{\detokenize{admin/install_kdc:configure-replica-kdcs}} +\sphinxAtStartPar +Database propagation copies the contents of the primary’s database, +but does not propagate configuration files, stash files, or the kadm5 +ACL file. The following files must be copied by hand to each replica +(see {\hyperref[\detokenize{mitK5defaults:mitk5defaults}]{\sphinxcrossref{\DUrole{std,std-ref}{MIT Kerberos defaults}}}} for the default locations for these files): +\begin{itemize} +\item {} +\sphinxAtStartPar +krb5.conf + +\item {} +\sphinxAtStartPar +kdc.conf + +\item {} +\sphinxAtStartPar +kadm5.acl + +\item {} +\sphinxAtStartPar +master key stash file + +\end{itemize} + +\sphinxAtStartPar +Move the copied files into their appropriate directories, exactly as +on the primary KDC. kadm5.acl is only needed to allow a replica to +swap with the primary KDC. + +\sphinxAtStartPar +The database is propagated from the primary KDC to the replica KDCs +via the {\hyperref[\detokenize{admin/admin_commands/kpropd:kpropd-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kpropd}}}} daemon. You must explicitly specify the +principals which are allowed to provide Kerberos dump updates on the +replica machine with a new database. Create a file named kpropd.acl +in the KDC state directory containing the \sphinxcode{\sphinxupquote{host}} principals for each +of the KDCs: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{host}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{n}{host}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\end{sphinxVerbatim} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +If you expect that the primary and replica KDCs will be +switched at some point of time, list the host principals +from all participating KDC servers in kpropd.acl files on +all of the KDCs. Otherwise, you only need to list the +primary KDC’s host principal in the kpropd.acl files of the +replica KDCs. +\end{sphinxadmonition} + +\sphinxAtStartPar +Then, add the following line to \sphinxcode{\sphinxupquote{/etc/inetd.conf}} on each KDC +(adjust the path to kpropd): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{krb5\PYGZus{}prop} \PYG{n}{stream} \PYG{n}{tcp} \PYG{n}{nowait} \PYG{n}{root} \PYG{o}{/}\PYG{n}{usr}\PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{sbin}\PYG{o}{/}\PYG{n}{kpropd} \PYG{n}{kpropd} +\end{sphinxVerbatim} + +\sphinxAtStartPar +You also need to add the following line to \sphinxcode{\sphinxupquote{/etc/services}} on each +KDC, if it is not already present (assuming that the default port is +used): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{krb5\PYGZus{}prop} \PYG{l+m+mi}{754}\PYG{o}{/}\PYG{n}{tcp} \PYG{c+c1}{\PYGZsh{} Kerberos replica propagation} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Restart inetd daemon. + +\sphinxAtStartPar +Alternatively, start {\hyperref[\detokenize{admin/admin_commands/kpropd:kpropd-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kpropd}}}} as a stand\sphinxhyphen{}alone daemon. This is +required when incremental propagation is enabled. + +\sphinxAtStartPar +Now that the replica KDC is able to accept database propagation, +you’ll need to propagate the database from the primary server. + +\sphinxAtStartPar +NOTE: Do not start the replica KDC yet; you still do not have a copy +of the primary’s database. + + +\paragraph{Propagate the database to each replica KDC} +\label{\detokenize{admin/install_kdc:propagate-the-database-to-each-replica-kdc}}\label{\detokenize{admin/install_kdc:kprop-to-replicas}} +\sphinxAtStartPar +First, create a dump file of the database on the primary KDC, as +follows: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kdb5\PYGZus{}util} \PYG{n}{dump} \PYG{o}{/}\PYG{n}{usr}\PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{var}\PYG{o}{/}\PYG{n}{krb5kdc}\PYG{o}{/}\PYG{n}{replica\PYGZus{}datatrans} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Then, manually propagate the database to each replica KDC, as in the +following example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kprop} \PYG{o}{\PYGZhy{}}\PYG{n}{f} \PYG{o}{/}\PYG{n}{usr}\PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{var}\PYG{o}{/}\PYG{n}{krb5kdc}\PYG{o}{/}\PYG{n}{replica\PYGZus{}datatrans} \PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + +\PYG{n}{Database} \PYG{n}{propagation} \PYG{n}{to} \PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{p}{:} \PYG{n}{SUCCEEDED} +\end{sphinxVerbatim} + +\sphinxAtStartPar +You will need a script to dump and propagate the database. The +following is an example of a Bourne shell script that will do this. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +Remember that you need to replace \sphinxcode{\sphinxupquote{/usr/local/var/krb5kdc}} +with the name of the KDC state directory. +\end{sphinxadmonition} + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZsh{}!/bin/sh + +kdclist = \PYGZdq{}kerberos\PYGZhy{}1.mit.edu kerberos\PYGZhy{}2.mit.edu\PYGZdq{} + +kdb5\PYGZus{}util dump /usr/local/var/krb5kdc/replica\PYGZus{}datatrans + +for kdc in \PYGZdl{}kdclist +do + kprop \PYGZhy{}f /usr/local/var/krb5kdc/replica\PYGZus{}datatrans \PYGZdl{}kdc +done +\end{sphinxVerbatim} + +\sphinxAtStartPar +You will need to set up a cron job to run this script at the intervals +you decided on earlier (see {\hyperref[\detokenize{admin/realm_config:db-prop}]{\sphinxcrossref{\DUrole{std,std-ref}{Database propagation}}}}). + +\sphinxAtStartPar +Now that the replica KDC has a copy of the Kerberos database, you can +start the krb5kdc daemon: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{krb5kdc} +\end{sphinxVerbatim} + +\sphinxAtStartPar +As with the primary KDC, you will probably want to add this command to +the KDCs’ \sphinxcode{\sphinxupquote{/etc/rc}} or \sphinxcode{\sphinxupquote{/etc/inittab}} files, so they will start +the krb5kdc daemon automatically at boot time. + + +\subparagraph{Propagation failed?} +\label{\detokenize{admin/install_kdc:propagation-failed}} +\sphinxAtStartPar +You may encounter the following error messages. For a more detailed +discussion on possible causes and solutions click on the error link +to be redirected to {\hyperref[\detokenize{admin/troubleshoot:troubleshoot}]{\sphinxcrossref{\DUrole{std,std-ref}{Troubleshooting}}}} section. +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/troubleshoot:kprop-no-route}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop: No route to host while connecting to server}}}} + +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/troubleshoot:kprop-con-refused}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop: Connection refused while connecting to server}}}} + +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/troubleshoot:kprop-sendauth-exchange}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop: Server rejected authentication (during sendauth exchange) while authenticating to server}}}} + +\end{enumerate} + + +\subsubsection{Add Kerberos principals to the database} +\label{\detokenize{admin/install_kdc:add-kerberos-principals-to-the-database}} +\sphinxAtStartPar +Once your KDCs are set up and running, you are ready to use +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} to load principals for your users, hosts, and other +services into the Kerberos database. This procedure is described +fully in {\hyperref[\detokenize{admin/database:principals}]{\sphinxcrossref{\DUrole{std,std-ref}{Principals}}}}. + +\sphinxAtStartPar +You may occasionally want to use one of your replica KDCs as the +primary. This might happen if you are upgrading the primary KDC, or +if your primary KDC has a disk crash. See the following section for +the instructions. + + +\subsubsection{Switching primary and replica KDCs} +\label{\detokenize{admin/install_kdc:switching-primary-and-replica-kdcs}}\label{\detokenize{admin/install_kdc:switch-primary-replica}} +\sphinxAtStartPar +You may occasionally want to use one of your replica KDCs as the +primary. This might happen if you are upgrading the primary KDC, or +if your primary KDC has a disk crash. + +\sphinxAtStartPar +Assuming you have configured all of your KDCs to be able to function +as either the primary KDC or a replica KDC (as this document +recommends), all you need to do to make the changeover is: + +\sphinxAtStartPar +If the primary KDC is still running, do the following on the \sphinxstyleemphasis{old} +primary KDC: +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +Kill the kadmind process. + +\item {} +\sphinxAtStartPar +Disable the cron job that propagates the database. + +\item {} +\sphinxAtStartPar +Run your database propagation script manually, to ensure that the +replicas all have the latest copy of the database (see +{\hyperref[\detokenize{admin/install_kdc:kprop-to-replicas}]{\sphinxcrossref{\DUrole{std,std-ref}{Propagate the database to each replica KDC}}}}). + +\end{enumerate} + +\sphinxAtStartPar +On the \sphinxstyleemphasis{new} primary KDC: +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +Start the {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} daemon (see {\hyperref[\detokenize{admin/install_kdc:start-kdc-daemons}]{\sphinxcrossref{\DUrole{std,std-ref}{Start the Kerberos daemons on the primary KDC}}}}). + +\item {} +\sphinxAtStartPar +Set up the cron job to propagate the database (see +{\hyperref[\detokenize{admin/install_kdc:kprop-to-replicas}]{\sphinxcrossref{\DUrole{std,std-ref}{Propagate the database to each replica KDC}}}}). + +\item {} +\sphinxAtStartPar +Switch the CNAMEs of the old and new primary KDCs. If you can’t do +this, you’ll need to change the {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} file on every +client machine in your Kerberos realm. + +\end{enumerate} + + +\subsubsection{Incremental database propagation} +\label{\detokenize{admin/install_kdc:incremental-database-propagation}} +\sphinxAtStartPar +If you expect your Kerberos database to become large, you may wish to +set up incremental propagation to replica KDCs. See +{\hyperref[\detokenize{admin/database:incr-db-prop}]{\sphinxcrossref{\DUrole{std,std-ref}{Incremental database propagation}}}} for details. + + +\subsection{Installing and configuring UNIX client machines} +\label{\detokenize{admin/install_clients:installing-and-configuring-unix-client-machines}}\label{\detokenize{admin/install_clients::doc}} +\sphinxAtStartPar +The Kerberized client programs include \DUrole{xref,std,std-ref}{kinit(1)}, +\DUrole{xref,std,std-ref}{klist(1)}, \DUrole{xref,std,std-ref}{kdestroy(1)}, and \DUrole{xref,std,std-ref}{kpasswd(1)}. All of +these programs are in the directory {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{BINDIR}}}}. + +\sphinxAtStartPar +You can often integrate Kerberos with the login system on client +machines, typically through the use of PAM. The details vary by +operating system, and should be covered in your operating system’s +documentation. If you do this, you will need to make sure your users +know to use their Kerberos passwords when they log in. + +\sphinxAtStartPar +You will also need to educate your users to use the ticket management +programs kinit, klist, and kdestroy. If you do not have Kerberos +password changing integrated into the native password program (again, +typically through PAM), you will need to educate users to use kpasswd +in place of its non\sphinxhyphen{}Kerberos counterparts passwd. + + +\subsubsection{Client machine configuration files} +\label{\detokenize{admin/install_clients:client-machine-configuration-files}} +\sphinxAtStartPar +Each machine running Kerberos should have a {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} file. +At a minimum, it should define a \sphinxstylestrong{default\_realm} setting in +{\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}}. If you are not using DNS SRV records +({\hyperref[\detokenize{admin/realm_config:kdc-hostnames}]{\sphinxcrossref{\DUrole{std,std-ref}{Hostnames for KDCs}}}}) or URI records ({\hyperref[\detokenize{admin/realm_config:kdc-discovery}]{\sphinxcrossref{\DUrole{std,std-ref}{KDC Discovery}}}}), it must +also contain a {\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} section containing information for your +realm’s KDCs. + +\sphinxAtStartPar +Consider setting \sphinxstylestrong{rdns} to false in order to reduce your dependence +on precisely correct DNS information for service hostnames. Turning +this flag off means that service hostnames will be canonicalized +through forward name resolution (which adds your domain name to +unqualified hostnames, and resolves CNAME records in DNS), but not +through reverse address lookup. The default value of this flag is +true for historical reasons only. + +\sphinxAtStartPar +If you anticipate users frequently logging into remote hosts +(e.g., using ssh) using forwardable credentials, consider setting +\sphinxstylestrong{forwardable} to true so that users obtain forwardable tickets by +default. Otherwise users will need to use \sphinxcode{\sphinxupquote{kinit \sphinxhyphen{}f}} to get +forwardable tickets. + +\sphinxAtStartPar +Consider adjusting the \sphinxstylestrong{ticket\_lifetime} setting to match the likely +length of sessions for your users. For instance, if most of your +users will be logging in for an eight\sphinxhyphen{}hour workday, you could set the +default to ten hours so that tickets obtained in the morning expire +shortly after the end of the workday. Users can still manually +request longer tickets when necessary, up to the maximum allowed by +each user’s principal record on the KDC. + +\sphinxAtStartPar +If a client host may access services in different realms, it may be +useful to define a {\hyperref[\detokenize{admin/conf_files/krb5_conf:domain-realm}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}domain\_realm{]}}}}} mapping so that clients know +which hosts belong to which realms. However, if your clients and KDC +are running release 1.7 or later, it is also reasonable to leave this +section out on client machines and just define it in the KDC’s +krb5.conf. + + +\subsection{UNIX Application Servers} +\label{\detokenize{admin/install_appl_srv:unix-application-servers}}\label{\detokenize{admin/install_appl_srv::doc}} +\sphinxAtStartPar +An application server is a host that provides one or more services +over the network. Application servers can be “secure” or “insecure.” +A “secure” host is set up to require authentication from every client +connecting to it. An “insecure” host will still provide Kerberos +authentication, but will also allow unauthenticated clients to +connect. + +\sphinxAtStartPar +If you have Kerberos V5 installed on all of your client machines, MIT +recommends that you make your hosts secure, to take advantage of the +security that Kerberos authentication affords. However, if you have +some clients that do not have Kerberos V5 installed, you can run an +insecure server, and still take advantage of Kerberos V5’s single +sign\sphinxhyphen{}on capability. + + +\subsubsection{The keytab file} +\label{\detokenize{admin/install_appl_srv:the-keytab-file}}\label{\detokenize{admin/install_appl_srv:keytab-file}} +\sphinxAtStartPar +All Kerberos server machines need a keytab file to authenticate to the +KDC. By default on UNIX\sphinxhyphen{}like systems this file is named {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{DEFKTNAME}}}}. +The keytab file is an local copy of the host’s key. The keytab file +is a potential point of entry for a break\sphinxhyphen{}in, and if compromised, +would allow unrestricted access to its host. The keytab file should +be readable only by root, and should exist only on the machine’s local +disk. The file should not be part of any backup of the machine, +unless access to the backup data is secured as tightly as access to +the machine’s root password. + +\sphinxAtStartPar +In order to generate a keytab for a host, the host must have a +principal in the Kerberos database. The procedure for adding hosts to +the database is described fully in {\hyperref[\detokenize{admin/database:principals}]{\sphinxcrossref{\DUrole{std,std-ref}{Principals}}}}. (See +{\hyperref[\detokenize{admin/install_kdc:replica-host-key}]{\sphinxcrossref{\DUrole{std,std-ref}{Create host keytabs for replica KDCs}}}} for a brief description.) The keytab is +generated by running {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} and issuing the {\hyperref[\detokenize{admin/admin_commands/kadmin_local:ktadd}]{\sphinxcrossref{\DUrole{std,std-ref}{ktadd}}}} +command. + +\sphinxAtStartPar +For example, to generate a keytab file to allow the host +\sphinxcode{\sphinxupquote{trillium.mit.edu}} to authenticate for the services host, ftp, and +pop, the administrator \sphinxcode{\sphinxupquote{joeadmin}} would issue the command (on +\sphinxcode{\sphinxupquote{trillium.mit.edu}}): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{trillium}\PYG{o}{\PYGZpc{}} \PYG{n}{kadmin} +\PYG{n}{Authenticating} \PYG{k}{as} \PYG{n}{principal} \PYG{n}{root}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Password} \PYG{k}{for} \PYG{n}{root}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{p}{:} +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{ktadd} \PYG{n}{host}\PYG{o}{/}\PYG{n}{trillium}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{n}{ftp}\PYG{o}{/}\PYG{n}{trillium}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{n}{pop}\PYG{o}{/}\PYG{n}{trillium}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{trillium}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{3}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha384}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{192} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{ftp}\PYG{o}{/}\PYG{n}{trillium}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{3}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha384}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{192} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{pop}\PYG{o}{/}\PYG{n}{trillium}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{3}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha384}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{192} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{quit} +\PYG{n}{trillium}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If you generate the keytab file on another host, you need to get a +copy of the keytab file onto the destination host (\sphinxcode{\sphinxupquote{trillium}}, in +the above example) without sending it unencrypted over the network. + + +\subsubsection{Some advice about secure hosts} +\label{\detokenize{admin/install_appl_srv:some-advice-about-secure-hosts}} +\sphinxAtStartPar +Kerberos V5 can protect your host from certain types of break\sphinxhyphen{}ins, but +it is possible to install Kerberos V5 and still leave your host +vulnerable to attack. Obviously an installation guide is not the +place to try to include an exhaustive list of countermeasures for +every possible attack, but it is worth noting some of the larger holes +and how to close them. + +\sphinxAtStartPar +We recommend that backups of secure machines exclude the keytab file +({\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{DEFKTNAME}}}}). If this is not possible, the backups should at least be +done locally, rather than over a network, and the backup tapes should +be physically secured. + +\sphinxAtStartPar +The keytab file and any programs run by root, including the Kerberos +V5 binaries, should be kept on local disk. The keytab file should be +readable only by root. + + +\section{Additional references} +\label{\detokenize{admin/install:additional-references}}\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +Debian: \sphinxhref{http://techpubs.spinlocksolutions.com/dklar/kerberos.html}{Setting up MIT Kerberos 5} + +\item {} +\sphinxAtStartPar +Solaris: \sphinxhref{https://docs.oracle.com/cd/E19253-01/816-4557/6maosrjv2/index.html}{Configuring the Kerberos Service} + +\end{enumerate} + + +\chapter{Configuration Files} +\label{\detokenize{admin/conf_files/index:configuration-files}}\label{\detokenize{admin/conf_files/index::doc}} +\sphinxAtStartPar +Kerberos uses configuration files to allow administrators to specify +settings on a per\sphinxhyphen{}machine basis. {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} applies to all +applications using the Kerboros library, on clients and servers. +For KDC\sphinxhyphen{}specific applications, additional settings can be specified in +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}; the two files are merged into a configuration profile +used by applications accessing the KDC database directly. {\hyperref[\detokenize{admin/conf_files/kadm5_acl:kadm5-acl-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kadm5.acl}}}} +is also only used on the KDC, it controls permissions for modifying the +KDC database. + + +\section{Contents} +\label{\detokenize{admin/conf_files/index:contents}} + +\subsection{krb5.conf} +\label{\detokenize{admin/conf_files/krb5_conf:krb5-conf}}\label{\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}}\label{\detokenize{admin/conf_files/krb5_conf::doc}} +\sphinxAtStartPar +The krb5.conf file contains Kerberos configuration information, +including the locations of KDCs and admin servers for the Kerberos +realms of interest, defaults for the current realm and for Kerberos +applications, and mappings of hostnames onto Kerberos realms. +Normally, you should install your krb5.conf file in the directory +\sphinxcode{\sphinxupquote{/etc}}. You can override the default location by setting the +environment variable \sphinxstylestrong{KRB5\_CONFIG}. Multiple colon\sphinxhyphen{}separated +filenames may be specified in \sphinxstylestrong{KRB5\_CONFIG}; all files which are +present will be read. Starting in release 1.14, directory names can +also be specified in \sphinxstylestrong{KRB5\_CONFIG}; all files within the directory +whose names consist solely of alphanumeric characters, dashes, or +underscores will be read. + + +\subsubsection{Structure} +\label{\detokenize{admin/conf_files/krb5_conf:structure}} +\sphinxAtStartPar +The krb5.conf file is set up in the style of a Windows INI file. +Lines beginning with ‘\#’ or ‘;’ (possibly after initial whitespace) +are ignored as comments. Sections are headed by the section name, in +square brackets. Each section may contain zero or more relations, of +the form: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{foo} \PYG{o}{=} \PYG{n}{bar} +\end{sphinxVerbatim} + +\sphinxAtStartPar +or: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{fubar} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{foo} \PYG{o}{=} \PYG{n}{bar} + \PYG{n}{baz} \PYG{o}{=} \PYG{n}{quux} +\PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Placing a ‘*’ after the closing bracket of a section name indicates +that the section is \sphinxstyleemphasis{final}, meaning that if the same section appears +within a later file specified in \sphinxstylestrong{KRB5\_CONFIG}, it will be ignored. +A subsection can be marked as final by placing a ‘*’ after either the +tag name or the closing brace. + +\sphinxAtStartPar +The krb5.conf file can include other files using either of the +following directives at the beginning of a line: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{include} \PYG{n}{FILENAME} +\PYG{n}{includedir} \PYG{n}{DIRNAME} +\end{sphinxVerbatim} + +\sphinxAtStartPar +\sphinxstyleemphasis{FILENAME} or \sphinxstyleemphasis{DIRNAME} should be an absolute path. The named file or +directory must exist and be readable. Including a directory includes +all files within the directory whose names consist solely of +alphanumeric characters, dashes, or underscores. Starting in release +1.15, files with names ending in “.conf” are also included, unless the +name begins with “.”. Included profile files are syntactically +independent of their parents, so each included file must begin with a +section header. Starting in release 1.17, files are read in +alphanumeric order; in previous releases, they may be read in any +order. + +\sphinxAtStartPar +The krb5.conf file can specify that configuration should be obtained +from a loadable module, rather than the file itself, using the +following directive at the beginning of a line before any section +headers: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{module} \PYG{n}{MODULEPATH}\PYG{p}{:}\PYG{n}{RESIDUAL} +\end{sphinxVerbatim} + +\sphinxAtStartPar +\sphinxstyleemphasis{MODULEPATH} may be relative to the library path of the krb5 +installation, or it may be an absolute path. \sphinxstyleemphasis{RESIDUAL} is provided +to the module at initialization time. If krb5.conf uses a module +directive, {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} should also use one if it exists. + + +\subsubsection{Sections} +\label{\detokenize{admin/conf_files/krb5_conf:sections}} +\sphinxAtStartPar +The krb5.conf file may contain the following sections: + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}} +& +\sphinxAtStartPar +Settings used by the Kerberos V5 library +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} +& +\sphinxAtStartPar +Realm\sphinxhyphen{}specific contact information and settings +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/krb5_conf:domain-realm}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}domain\_realm{]}}}}} +& +\sphinxAtStartPar +Maps server hostnames to Kerberos realms +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/krb5_conf:capaths}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}capaths{]}}}}} +& +\sphinxAtStartPar +Authentication paths for non\sphinxhyphen{}hierarchical cross\sphinxhyphen{}realm +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/krb5_conf:appdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}appdefaults{]}}}}} +& +\sphinxAtStartPar +Settings used by some Kerberos V5 applications +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/krb5_conf:plugins}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}plugins{]}}}}} +& +\sphinxAtStartPar +Controls plugin module registration +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + +\sphinxAtStartPar +Additionally, krb5.conf may include any of the relations described in +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}, but it is not a recommended practice. + + +\paragraph{{[}libdefaults{]}} +\label{\detokenize{admin/conf_files/krb5_conf:libdefaults}}\label{\detokenize{admin/conf_files/krb5_conf:id1}} +\sphinxAtStartPar +The libdefaults section may contain any of the following relations: +\begin{description} +\item[{\sphinxstylestrong{allow\_des3}}] \leavevmode +\sphinxAtStartPar +Permit the KDC to issue tickets with des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1 session keys. +In future releases, this flag will allow des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1 to be used +at all. The default value for this tag is false. (Added in +release 1.21.) + +\item[{\sphinxstylestrong{allow\_rc4}}] \leavevmode +\sphinxAtStartPar +Permit the KDC to issue tickets with arcfour\sphinxhyphen{}hmac session keys. +In future releases, this flag will allow arcfour\sphinxhyphen{}hmac to be used +at all. The default value for this tag is false. (Added in +release 1.21.) + +\item[{\sphinxstylestrong{allow\_weak\_crypto}}] \leavevmode +\sphinxAtStartPar +If this flag is set to false, then weak encryption types (as noted +in {\hyperref[\detokenize{admin/conf_files/kdc_conf:encryption-types}]{\sphinxcrossref{\DUrole{std,std-ref}{Encryption types}}}} in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}) will be filtered +out of the lists \sphinxstylestrong{default\_tgs\_enctypes}, +\sphinxstylestrong{default\_tkt\_enctypes}, and \sphinxstylestrong{permitted\_enctypes}. The default +value for this tag is false. + +\item[{\sphinxstylestrong{canonicalize}}] \leavevmode +\sphinxAtStartPar +If this flag is set to true, initial ticket requests to the KDC +will request canonicalization of the client principal name, and +answers with different client principals than the requested +principal will be accepted. The default value is false. + +\item[{\sphinxstylestrong{ccache\_type}}] \leavevmode +\sphinxAtStartPar +This parameter determines the format of credential cache types +created by \DUrole{xref,std,std-ref}{kinit(1)} or other programs. The default value +is 4, which represents the most current format. Smaller values +can be used for compatibility with very old implementations of +Kerberos which interact with credential caches on the same host. + +\item[{\sphinxstylestrong{clockskew}}] \leavevmode +\sphinxAtStartPar +Sets the maximum allowable amount of clockskew in seconds that the +library will tolerate before assuming that a Kerberos message is +invalid. The default value is 300 seconds, or five minutes. + +\sphinxAtStartPar +The clockskew setting is also used when evaluating ticket start +and expiration times. For example, tickets that have reached +their expiration time can still be used (and renewed if they are +renewable tickets) if they have been expired for a shorter +duration than the \sphinxstylestrong{clockskew} setting. + +\item[{\sphinxstylestrong{default\_ccache\_name}}] \leavevmode +\sphinxAtStartPar +This relation specifies the name of the default credential cache. +The default is {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{DEFCCNAME}}}}. This relation is subject to parameter +expansion (see below). New in release 1.11. + +\item[{\sphinxstylestrong{default\_client\_keytab\_name}}] \leavevmode +\sphinxAtStartPar +This relation specifies the name of the default keytab for +obtaining client credentials. The default is {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{DEFCKTNAME}}}}. This +relation is subject to parameter expansion (see below). +New in release 1.11. + +\item[{\sphinxstylestrong{default\_keytab\_name}}] \leavevmode +\sphinxAtStartPar +This relation specifies the default keytab name to be used by +application servers such as sshd. The default is {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{DEFKTNAME}}}}. This +relation is subject to parameter expansion (see below). + +\item[{\sphinxstylestrong{default\_rcache\_name}}] \leavevmode +\sphinxAtStartPar +This relation specifies the name of the default replay cache. +The default is \sphinxcode{\sphinxupquote{dfl:}}. This relation is subject to parameter +expansion (see below). New in release 1.18. + +\item[{\sphinxstylestrong{default\_realm}}] \leavevmode +\sphinxAtStartPar +Identifies the default Kerberos realm for the client. Set its +value to your Kerberos realm. If this value is not set, then a +realm must be specified with every Kerberos principal when +invoking programs such as \DUrole{xref,std,std-ref}{kinit(1)}. + +\item[{\sphinxstylestrong{default\_tgs\_enctypes}}] \leavevmode +\sphinxAtStartPar +Identifies the supported list of session key encryption types that +the client should request when making a TGS\sphinxhyphen{}REQ, in order of +preference from highest to lowest. The list may be delimited with +commas or whitespace. See {\hyperref[\detokenize{admin/conf_files/kdc_conf:encryption-types}]{\sphinxcrossref{\DUrole{std,std-ref}{Encryption types}}}} in +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} for a list of the accepted values for this tag. +Starting in release 1.18, the default value is the value of +\sphinxstylestrong{permitted\_enctypes}. For previous releases or if +\sphinxstylestrong{permitted\_enctypes} is not set, the default value is +\sphinxcode{\sphinxupquote{aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96 aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96 aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha384\sphinxhyphen{}192 aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha256\sphinxhyphen{}128 des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1 arcfour\sphinxhyphen{}hmac\sphinxhyphen{}md5 camellia256\sphinxhyphen{}cts\sphinxhyphen{}cmac camellia128\sphinxhyphen{}cts\sphinxhyphen{}cmac}}. + +\sphinxAtStartPar +Do not set this unless required for specific backward +compatibility purposes; stale values of this setting can prevent +clients from taking advantage of new stronger enctypes when the +libraries are upgraded. + +\item[{\sphinxstylestrong{default\_tkt\_enctypes}}] \leavevmode +\sphinxAtStartPar +Identifies the supported list of session key encryption types that +the client should request when making an AS\sphinxhyphen{}REQ, in order of +preference from highest to lowest. The format is the same as for +default\_tgs\_enctypes. Starting in release 1.18, the default +value is the value of \sphinxstylestrong{permitted\_enctypes}. For previous +releases or if \sphinxstylestrong{permitted\_enctypes} is not set, the default +value is \sphinxcode{\sphinxupquote{aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96 aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96 aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha384\sphinxhyphen{}192 aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha256\sphinxhyphen{}128 des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1 arcfour\sphinxhyphen{}hmac\sphinxhyphen{}md5 camellia256\sphinxhyphen{}cts\sphinxhyphen{}cmac camellia128\sphinxhyphen{}cts\sphinxhyphen{}cmac}}. + +\sphinxAtStartPar +Do not set this unless required for specific backward +compatibility purposes; stale values of this setting can prevent +clients from taking advantage of new stronger enctypes when the +libraries are upgraded. + +\item[{\sphinxstylestrong{dns\_canonicalize\_hostname}}] \leavevmode +\sphinxAtStartPar +Indicate whether name lookups will be used to canonicalize +hostnames for use in service principal names. Setting this flag +to false can improve security by reducing reliance on DNS, but +means that short hostnames will not be canonicalized to +fully\sphinxhyphen{}qualified hostnames. If this option is set to \sphinxcode{\sphinxupquote{fallback}} (new +in release 1.18), DNS canonicalization will only be performed the +server hostname is not found with the original name when +requesting credentials. The default value is true. + +\item[{\sphinxstylestrong{dns\_lookup\_kdc}}] \leavevmode +\sphinxAtStartPar +Indicate whether DNS SRV records should be used to locate the KDCs +and other servers for a realm, if they are not listed in the +krb5.conf information for the realm. (Note that the admin\_server +entry must be in the krb5.conf realm information in order to +contact kadmind, because the DNS implementation for kadmin is +incomplete.) + +\sphinxAtStartPar +Enabling this option does open up a type of denial\sphinxhyphen{}of\sphinxhyphen{}service +attack, if someone spoofs the DNS records and redirects you to +another server. However, it’s no worse than a denial of service, +because that fake KDC will be unable to decode anything you send +it (besides the initial ticket request, which has no encrypted +data), and anything the fake KDC sends will not be trusted without +verification using some secret that it won’t know. + +\item[{\sphinxstylestrong{dns\_uri\_lookup}}] \leavevmode +\sphinxAtStartPar +Indicate whether DNS URI records should be used to locate the KDCs +and other servers for a realm, if they are not listed in the +krb5.conf information for the realm. SRV records are used as a +fallback if no URI records were found. The default value is true. +New in release 1.15. + +\item[{\sphinxstylestrong{enforce\_ok\_as\_delegate}}] \leavevmode +\sphinxAtStartPar +If this flag to true, GSSAPI credential delegation will be +disabled when the \sphinxcode{\sphinxupquote{ok\sphinxhyphen{}as\sphinxhyphen{}delegate}} flag is not set in the +service ticket. If this flag is false, the \sphinxcode{\sphinxupquote{ok\sphinxhyphen{}as\sphinxhyphen{}delegate}} +ticket flag is only enforced when an application specifically +requests enforcement. The default value is false. + +\item[{\sphinxstylestrong{err\_fmt}}] \leavevmode +\sphinxAtStartPar +This relation allows for custom error message formatting. If a +value is set, error messages will be formatted by substituting a +normal error message for \%M and an error code for \%C in the value. + +\item[{\sphinxstylestrong{extra\_addresses}}] \leavevmode +\sphinxAtStartPar +This allows a computer to use multiple local addresses, in order +to allow Kerberos to work in a network that uses NATs while still +using address\sphinxhyphen{}restricted tickets. The addresses should be in a +comma\sphinxhyphen{}separated list. This option has no effect if +\sphinxstylestrong{noaddresses} is true. + +\item[{\sphinxstylestrong{forwardable}}] \leavevmode +\sphinxAtStartPar +If this flag is true, initial tickets will be forwardable by +default, if allowed by the KDC. The default value is false. + +\item[{\sphinxstylestrong{ignore\_acceptor\_hostname}}] \leavevmode +\sphinxAtStartPar +When accepting GSSAPI or krb5 security contexts for host\sphinxhyphen{}based +service principals, ignore any hostname passed by the calling +application, and allow clients to authenticate to any service +principal in the keytab matching the service name and realm name +(if given). This option can improve the administrative +flexibility of server applications on multihomed hosts, but could +compromise the security of virtual hosting environments. The +default value is false. New in release 1.10. + +\item[{\sphinxstylestrong{k5login\_authoritative}}] \leavevmode +\sphinxAtStartPar +If this flag is true, principals must be listed in a local user’s +k5login file to be granted login access, if a \DUrole{xref,std,std-ref}{.k5login(5)} +file exists. If this flag is false, a principal may still be +granted login access through other mechanisms even if a k5login +file exists but does not list the principal. The default value is +true. + +\item[{\sphinxstylestrong{k5login\_directory}}] \leavevmode +\sphinxAtStartPar +If set, the library will look for a local user’s k5login file +within the named directory, with a filename corresponding to the +local username. If not set, the library will look for k5login +files in the user’s home directory, with the filename .k5login. +For security reasons, .k5login files must be owned by +the local user or by root. + +\item[{\sphinxstylestrong{kcm\_mach\_service}}] \leavevmode +\sphinxAtStartPar +On macOS only, determines the name of the bootstrap service used to +contact the KCM daemon for the KCM credential cache type. If the +value is \sphinxcode{\sphinxupquote{\sphinxhyphen{}}}, Mach RPC will not be used to contact the KCM +daemon. The default value is \sphinxcode{\sphinxupquote{org.h5l.kcm}}. + +\item[{\sphinxstylestrong{kcm\_socket}}] \leavevmode +\sphinxAtStartPar +Determines the path to the Unix domain socket used to access the +KCM daemon for the KCM credential cache type. If the value is +\sphinxcode{\sphinxupquote{\sphinxhyphen{}}}, Unix domain sockets will not be used to contact the KCM +daemon. The default value is +\sphinxcode{\sphinxupquote{/var/run/.heim\_org.h5l.kcm\sphinxhyphen{}socket}}. + +\item[{\sphinxstylestrong{kdc\_default\_options}}] \leavevmode +\sphinxAtStartPar +Default KDC options (Xored for multiple values) when requesting +initial tickets. By default it is set to 0x00000010 +(KDC\_OPT\_RENEWABLE\_OK). + +\item[{\sphinxstylestrong{kdc\_timesync}}] \leavevmode +\sphinxAtStartPar +Accepted values for this relation are 1 or 0. If it is nonzero, +client machines will compute the difference between their time and +the time returned by the KDC in the timestamps in the tickets and +use this value to correct for an inaccurate system clock when +requesting service tickets or authenticating to services. This +corrective factor is only used by the Kerberos library; it is not +used to change the system clock. The default value is 1. + +\item[{\sphinxstylestrong{noaddresses}}] \leavevmode +\sphinxAtStartPar +If this flag is true, requests for initial tickets will not be +made with address restrictions set, allowing the tickets to be +used across NATs. The default value is true. + +\item[{\sphinxstylestrong{permitted\_enctypes}}] \leavevmode +\sphinxAtStartPar +Identifies the encryption types that servers will permit for +session keys and for ticket and authenticator encryption, ordered +by preference from highest to lowest. Starting in release 1.18, +this tag also acts as the default value for +\sphinxstylestrong{default\_tgs\_enctypes} and \sphinxstylestrong{default\_tkt\_enctypes}. The +default value for this tag is \sphinxcode{\sphinxupquote{aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96 aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96 aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha384\sphinxhyphen{}192 aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha256\sphinxhyphen{}128 des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1 arcfour\sphinxhyphen{}hmac\sphinxhyphen{}md5 camellia256\sphinxhyphen{}cts\sphinxhyphen{}cmac camellia128\sphinxhyphen{}cts\sphinxhyphen{}cmac}}. + +\item[{\sphinxstylestrong{plugin\_base\_dir}}] \leavevmode +\sphinxAtStartPar +If set, determines the base directory where krb5 plugins are +located. The default value is the \sphinxcode{\sphinxupquote{krb5/plugins}} subdirectory +of the krb5 library directory. This relation is subject to +parameter expansion (see below) in release 1.17 and later. + +\item[{\sphinxstylestrong{preferred\_preauth\_types}}] \leavevmode +\sphinxAtStartPar +This allows you to set the preferred preauthentication types which +the client will attempt before others which may be advertised by a +KDC. The default value for this setting is “17, 16, 15, 14”, +which forces libkrb5 to attempt to use PKINIT if it is supported. + +\item[{\sphinxstylestrong{proxiable}}] \leavevmode +\sphinxAtStartPar +If this flag is true, initial tickets will be proxiable by +default, if allowed by the KDC. The default value is false. + +\item[{\sphinxstylestrong{qualify\_shortname}}] \leavevmode +\sphinxAtStartPar +If this string is set, it determines the domain suffix for +single\sphinxhyphen{}component hostnames when DNS canonicalization is not used +(either because \sphinxstylestrong{dns\_canonicalize\_hostname} is false or because +forward canonicalization failed). The default value is the first +search domain of the system’s DNS configuration. To disable +qualification of shortnames, set this relation to the empty string +with \sphinxcode{\sphinxupquote{qualify\_shortname = ""}}. (New in release 1.18.) + +\item[{\sphinxstylestrong{rdns}}] \leavevmode +\sphinxAtStartPar +If this flag is true, reverse name lookup will be used in addition +to forward name lookup to canonicalizing hostnames for use in +service principal names. If \sphinxstylestrong{dns\_canonicalize\_hostname} is set +to false, this flag has no effect. The default value is true. + +\item[{\sphinxstylestrong{realm\_try\_domains}}] \leavevmode +\sphinxAtStartPar +Indicate whether a host’s domain components should be used to +determine the Kerberos realm of the host. The value of this +variable is an integer: \sphinxhyphen{}1 means not to search, 0 means to try the +host’s domain itself, 1 means to also try the domain’s immediate +parent, and so forth. The library’s usual mechanism for locating +Kerberos realms is used to determine whether a domain is a valid +realm, which may involve consulting DNS if \sphinxstylestrong{dns\_lookup\_kdc} is +set. The default is not to search domain components. + +\item[{\sphinxstylestrong{renew\_lifetime}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} string.) Sets the default renewable lifetime +for initial ticket requests. The default value is 0. + +\item[{\sphinxstylestrong{spake\_preauth\_groups}}] \leavevmode +\sphinxAtStartPar +A whitespace or comma\sphinxhyphen{}separated list of words which specifies the +groups allowed for SPAKE preauthentication. The possible values +are: + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +edwards25519 +& +\sphinxAtStartPar +Edwards25519 curve (\index{RFC@\spxentry{RFC}!RFC 7748@\spxentry{RFC 7748}}\sphinxhref{https://tools.ietf.org/html/rfc7748.html}{\sphinxstylestrong{RFC 7748}}) +\\ +\hline +\sphinxAtStartPar +P\sphinxhyphen{}256 +& +\sphinxAtStartPar +NIST P\sphinxhyphen{}256 curve (\index{RFC@\spxentry{RFC}!RFC 5480@\spxentry{RFC 5480}}\sphinxhref{https://tools.ietf.org/html/rfc5480.html}{\sphinxstylestrong{RFC 5480}}) +\\ +\hline +\sphinxAtStartPar +P\sphinxhyphen{}384 +& +\sphinxAtStartPar +NIST P\sphinxhyphen{}384 curve (\index{RFC@\spxentry{RFC}!RFC 5480@\spxentry{RFC 5480}}\sphinxhref{https://tools.ietf.org/html/rfc5480.html}{\sphinxstylestrong{RFC 5480}}) +\\ +\hline +\sphinxAtStartPar +P\sphinxhyphen{}521 +& +\sphinxAtStartPar +NIST P\sphinxhyphen{}521 curve (\index{RFC@\spxentry{RFC}!RFC 5480@\spxentry{RFC 5480}}\sphinxhref{https://tools.ietf.org/html/rfc5480.html}{\sphinxstylestrong{RFC 5480}}) +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + +\sphinxAtStartPar +The default value for the client is \sphinxcode{\sphinxupquote{edwards25519}}. The default +value for the KDC is empty. New in release 1.17. + +\item[{\sphinxstylestrong{ticket\_lifetime}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} string.) Sets the default lifetime for initial +ticket requests. The default value is 1 day. + +\item[{\sphinxstylestrong{udp\_preference\_limit}}] \leavevmode +\sphinxAtStartPar +When sending a message to the KDC, the library will try using TCP +before UDP if the size of the message is above +\sphinxstylestrong{udp\_preference\_limit}. If the message is smaller than +\sphinxstylestrong{udp\_preference\_limit}, then UDP will be tried before TCP. +Regardless of the size, both protocols will be tried if the first +attempt fails. + +\item[{\sphinxstylestrong{verify\_ap\_req\_nofail}}] \leavevmode +\sphinxAtStartPar +If this flag is true, then an attempt to verify initial +credentials will fail if the client machine does not have a +keytab. The default value is false. + +\item[{\sphinxstylestrong{client\_aware\_channel\_bindings}}] \leavevmode +\sphinxAtStartPar +If this flag is true, then all application protocol authentication +requests will be flagged to indicate that the application supports +channel bindings when operating over a secure channel. The +default value is false. + +\end{description} + + +\paragraph{{[}realms{]}} +\label{\detokenize{admin/conf_files/krb5_conf:realms}}\label{\detokenize{admin/conf_files/krb5_conf:id2}} +\sphinxAtStartPar +Each tag in the {[}realms{]} section of the file is the name of a Kerberos +realm. The value of the tag is a subsection with relations that +define the properties of that particular realm. For each realm, the +following tags may be specified in the realm’s subsection: +\begin{description} +\item[{\sphinxstylestrong{admin\_server}}] \leavevmode +\sphinxAtStartPar +Identifies the host where the administration server is running. +Typically, this is the primary Kerberos server. This tag must be +given a value in order to communicate with the {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} +server for the realm. + +\item[{\sphinxstylestrong{auth\_to\_local}}] \leavevmode +\sphinxAtStartPar +This tag allows you to set a general rule for mapping principal +names to local user names. It will be used if there is not an +explicit mapping for the principal name that is being +translated. The possible values are: +\begin{description} +\item[{\sphinxstylestrong{RULE:}\sphinxstyleemphasis{exp}}] \leavevmode +\sphinxAtStartPar +The local name will be formulated from \sphinxstyleemphasis{exp}. + +\sphinxAtStartPar +The format for \sphinxstyleemphasis{exp} is \sphinxstylestrong{{[}}\sphinxstyleemphasis{n}\sphinxstylestrong{:}\sphinxstyleemphasis{string}\sphinxstylestrong{{]}(}\sphinxstyleemphasis{regexp}\sphinxstylestrong{)s/}\sphinxstyleemphasis{pattern}\sphinxstylestrong{/}\sphinxstyleemphasis{replacement}\sphinxstylestrong{/g}. +The integer \sphinxstyleemphasis{n} indicates how many components the target +principal should have. If this matches, then a string will be +formed from \sphinxstyleemphasis{string}, substituting the realm of the principal +for \sphinxcode{\sphinxupquote{\$0}} and the \sphinxstyleemphasis{n}’th component of the principal for +\sphinxcode{\sphinxupquote{\$n}} (e.g., if the principal was \sphinxcode{\sphinxupquote{johndoe/admin}} then +\sphinxcode{\sphinxupquote{{[}2:\$2\$1foo{]}}} would result in the string +\sphinxcode{\sphinxupquote{adminjohndoefoo}}). If this string matches \sphinxstyleemphasis{regexp}, then +the \sphinxcode{\sphinxupquote{s//{[}g{]}}} substitution command will be run over the +string. The optional \sphinxstylestrong{g} will cause the substitution to be +global over the \sphinxstyleemphasis{string}, instead of replacing only the first +match in the \sphinxstyleemphasis{string}. + +\item[{\sphinxstylestrong{DEFAULT}}] \leavevmode +\sphinxAtStartPar +The principal name will be used as the local user name. If +the principal has more than one component or is not in the +default realm, this rule is not applicable and the conversion +will fail. + +\end{description} + +\sphinxAtStartPar +For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +[realms] + ATHENA.MIT.EDU = \PYGZob{} + auth\PYGZus{}to\PYGZus{}local = RULE:[2:\PYGZdl{}1](johndoe)s/\PYGZca{}.*\PYGZdl{}/guest/ + auth\PYGZus{}to\PYGZus{}local = RULE:[2:\PYGZdl{}1;\PYGZdl{}2](\PYGZca{}.*;admin\PYGZdl{})s/;admin\PYGZdl{}// + auth\PYGZus{}to\PYGZus{}local = RULE:[2:\PYGZdl{}2](\PYGZca{}.*;root)s/\PYGZca{}.*\PYGZdl{}/root/ + auth\PYGZus{}to\PYGZus{}local = DEFAULT + \PYGZcb{} +\end{sphinxVerbatim} + +\sphinxAtStartPar +would result in any principal without \sphinxcode{\sphinxupquote{root}} or \sphinxcode{\sphinxupquote{admin}} as the +second component to be translated with the default rule. A +principal with a second component of \sphinxcode{\sphinxupquote{admin}} will become its +first component. \sphinxcode{\sphinxupquote{root}} will be used as the local name for any +principal with a second component of \sphinxcode{\sphinxupquote{root}}. The exception to +these two rules are any principals \sphinxcode{\sphinxupquote{johndoe/*}}, which will +always get the local name \sphinxcode{\sphinxupquote{guest}}. + +\item[{\sphinxstylestrong{auth\_to\_local\_names}}] \leavevmode +\sphinxAtStartPar +This subsection allows you to set explicit mappings from principal +names to local user names. The tag is the mapping name, and the +value is the corresponding local user name. + +\item[{\sphinxstylestrong{default\_domain}}] \leavevmode +\sphinxAtStartPar +This tag specifies the domain used to expand hostnames when +translating Kerberos 4 service principals to Kerberos 5 principals +(for example, when converting \sphinxcode{\sphinxupquote{rcmd.hostname}} to +\sphinxcode{\sphinxupquote{host/hostname.domain}}). + +\item[{\sphinxstylestrong{disable\_encrypted\_timestamp}}] \leavevmode +\sphinxAtStartPar +If this flag is true, the client will not perform encrypted +timestamp preauthentication if requested by the KDC. Setting this +flag can help to prevent dictionary attacks by active attackers, +if the realm’s KDCs support SPAKE preauthentication or if initial +authentication always uses another mechanism or always uses FAST. +This flag persists across client referrals during initial +authentication. This flag does not prevent the KDC from offering +encrypted timestamp. New in release 1.17. + +\item[{\sphinxstylestrong{http\_anchors}}] \leavevmode +\sphinxAtStartPar +When KDCs and kpasswd servers are accessed through HTTPS proxies, this tag +can be used to specify the location of the CA certificate which should be +trusted to issue the certificate for a proxy server. If left unspecified, +the system\sphinxhyphen{}wide default set of CA certificates is used. + +\sphinxAtStartPar +The syntax for values is similar to that of values for the +\sphinxstylestrong{pkinit\_anchors} tag: + +\sphinxAtStartPar +\sphinxstylestrong{FILE:} \sphinxstyleemphasis{filename} + +\sphinxAtStartPar +\sphinxstyleemphasis{filename} is assumed to be the name of an OpenSSL\sphinxhyphen{}style ca\sphinxhyphen{}bundle file. + +\sphinxAtStartPar +\sphinxstylestrong{DIR:} \sphinxstyleemphasis{dirname} + +\sphinxAtStartPar +\sphinxstyleemphasis{dirname} is assumed to be an directory which contains CA certificates. +All files in the directory will be examined; if they contain certificates +(in PEM format), they will be used. + +\sphinxAtStartPar +\sphinxstylestrong{ENV:} \sphinxstyleemphasis{envvar} + +\sphinxAtStartPar +\sphinxstyleemphasis{envvar} specifies the name of an environment variable which has been set +to a value conforming to one of the previous values. For example, +\sphinxcode{\sphinxupquote{ENV:X509\_PROXY\_CA}}, where environment variable \sphinxcode{\sphinxupquote{X509\_PROXY\_CA}} has +been set to \sphinxcode{\sphinxupquote{FILE:/tmp/my\_proxy.pem}}. + +\item[{\sphinxstylestrong{kdc}}] \leavevmode +\sphinxAtStartPar +The name or address of a host running a KDC for that realm. An +optional port number, separated from the hostname by a colon, may +be included. If the name or address contains colons (for example, +if it is an IPv6 address), enclose it in square brackets to +distinguish the colon from a port separator. For your computer to +be able to communicate with the KDC for each realm, this tag must +be given a value in each realm subsection in the configuration +file, or there must be DNS SRV records specifying the KDCs. + +\item[{\sphinxstylestrong{kpasswd\_server}}] \leavevmode +\sphinxAtStartPar +Points to the server where all the password changes are performed. +If there is no such entry, DNS will be queried (unless forbidden +by \sphinxstylestrong{dns\_lookup\_kdc}). Finally, port 464 on the \sphinxstylestrong{admin\_server} +host will be tried. + +\item[{\sphinxstylestrong{master\_kdc}}] \leavevmode +\sphinxAtStartPar +The name for \sphinxstylestrong{primary\_kdc} prior to release 1.19. Its value is +used as a fallback if \sphinxstylestrong{primary\_kdc} is not specified. + +\item[{\sphinxstylestrong{primary\_kdc}}] \leavevmode +\sphinxAtStartPar +Identifies the primary KDC(s). Currently, this tag is used in only +one case: If an attempt to get credentials fails because of an +invalid password, the client software will attempt to contact the +primary KDC, in case the user’s password has just been changed, and +the updated database has not been propagated to the replica +servers yet. New in release 1.19. + +\item[{\sphinxstylestrong{v4\_instance\_convert}}] \leavevmode +\sphinxAtStartPar +This subsection allows the administrator to configure exceptions +to the \sphinxstylestrong{default\_domain} mapping rule. It contains V4 instances +(the tag name) which should be translated to some specific +hostname (the tag value) as the second component in a Kerberos V5 +principal name. + +\item[{\sphinxstylestrong{v4\_realm}}] \leavevmode +\sphinxAtStartPar +This relation is used by the krb524 library routines when +converting a V5 principal name to a V4 principal name. It is used +when the V4 realm name and the V5 realm name are not the same, but +still share the same principal names and passwords. The tag value +is the Kerberos V4 realm name. + +\end{description} + + +\paragraph{{[}domain\_realm{]}} +\label{\detokenize{admin/conf_files/krb5_conf:domain-realm}}\label{\detokenize{admin/conf_files/krb5_conf:id3}} +\sphinxAtStartPar +The {[}domain\_realm{]} section provides a translation from hostnames to +Kerberos realms. Each tag is a domain name, providing the mapping for +that domain and all subdomains. If the tag begins with a period +(\sphinxcode{\sphinxupquote{.}}) then it applies only to subdomains. The Kerberos realm may be +identified either in the {\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{realms}}} section or using DNS SRV records. +Tag names should be in lower case. For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{domain\PYGZus{}realm}\PYG{p}{]} + \PYG{n}{crash}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{o}{=} \PYG{n}{TEST}\PYG{o}{.}\PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} + \PYG{o}{.}\PYG{n}{dev}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{o}{=} \PYG{n}{TEST}\PYG{o}{.}\PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} + \PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{o}{=} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\end{sphinxVerbatim} + +\sphinxAtStartPar +maps the host with the name \sphinxcode{\sphinxupquote{crash.mit.edu}} into the +\sphinxcode{\sphinxupquote{TEST.ATHENA.MIT.EDU}} realm. The second entry maps all hosts under the +domain \sphinxcode{\sphinxupquote{dev.mit.edu}} into the \sphinxcode{\sphinxupquote{TEST.ATHENA.MIT.EDU}} realm, but not +the host with the name \sphinxcode{\sphinxupquote{dev.mit.edu}}. That host is matched +by the third entry, which maps the host \sphinxcode{\sphinxupquote{mit.edu}} and all hosts +under the domain \sphinxcode{\sphinxupquote{mit.edu}} that do not match a preceding rule +into the realm \sphinxcode{\sphinxupquote{ATHENA.MIT.EDU}}. + +\sphinxAtStartPar +If no translation entry applies to a hostname used for a service +principal for a service ticket request, the library will try to get a +referral to the appropriate realm from the client realm’s KDC. If +that does not succeed, the host’s realm is considered to be the +hostname’s domain portion converted to uppercase, unless the +\sphinxstylestrong{realm\_try\_domains} setting in {[}libdefaults{]} causes a different +parent domain to be used. + + +\paragraph{{[}capaths{]}} +\label{\detokenize{admin/conf_files/krb5_conf:capaths}}\label{\detokenize{admin/conf_files/krb5_conf:id4}} +\sphinxAtStartPar +In order to perform direct (non\sphinxhyphen{}hierarchical) cross\sphinxhyphen{}realm +authentication, configuration is needed to determine the +authentication paths between realms. + +\sphinxAtStartPar +A client will use this section to find the authentication path between +its realm and the realm of the server. The server will use this +section to verify the authentication path used by the client, by +checking the transited field of the received ticket. + +\sphinxAtStartPar +There is a tag for each participating client realm, and each tag has +subtags for each of the server realms. The value of the subtags is an +intermediate realm which may participate in the cross\sphinxhyphen{}realm +authentication. The subtags may be repeated if there is more then one +intermediate realm. A value of “.” means that the two realms share +keys directly, and no intermediate realms should be allowed to +participate. + +\sphinxAtStartPar +Only those entries which will be needed on the client or the server +need to be present. A client needs a tag for its local realm with +subtags for all the realms of servers it will need to authenticate to. +A server needs a tag for each realm of the clients it will serve, with +a subtag of the server realm. + +\sphinxAtStartPar +For example, \sphinxcode{\sphinxupquote{ANL.GOV}}, \sphinxcode{\sphinxupquote{PNL.GOV}}, and \sphinxcode{\sphinxupquote{NERSC.GOV}} all wish to +use the \sphinxcode{\sphinxupquote{ES.NET}} realm as an intermediate realm. ANL has a sub +realm of \sphinxcode{\sphinxupquote{TEST.ANL.GOV}} which will authenticate with \sphinxcode{\sphinxupquote{NERSC.GOV}} +but not \sphinxcode{\sphinxupquote{PNL.GOV}}. The {[}capaths{]} section for \sphinxcode{\sphinxupquote{ANL.GOV}} systems +would look like this: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{capaths}\PYG{p}{]} + \PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{TEST}\PYG{o}{.}\PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{o}{.} + \PYG{n}{PNL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} + \PYG{n}{NERSC}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} + \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} \PYG{o}{=} \PYG{o}{.} + \PYG{p}{\PYGZcb{}} + \PYG{n}{TEST}\PYG{o}{.}\PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{o}{.} + \PYG{p}{\PYGZcb{}} + \PYG{n}{PNL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} + \PYG{p}{\PYGZcb{}} + \PYG{n}{NERSC}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} + \PYG{p}{\PYGZcb{}} + \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{o}{.} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The {[}capaths{]} section of the configuration file used on \sphinxcode{\sphinxupquote{NERSC.GOV}} +systems would look like this: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{capaths}\PYG{p}{]} + \PYG{n}{NERSC}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} + \PYG{n}{TEST}\PYG{o}{.}\PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} + \PYG{n}{TEST}\PYG{o}{.}\PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} + \PYG{n}{PNL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} + \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} \PYG{o}{=} \PYG{o}{.} + \PYG{p}{\PYGZcb{}} + \PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{NERSC}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} + \PYG{p}{\PYGZcb{}} + \PYG{n}{PNL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{NERSC}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} + \PYG{p}{\PYGZcb{}} + \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{NERSC}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{o}{.} + \PYG{p}{\PYGZcb{}} + \PYG{n}{TEST}\PYG{o}{.}\PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{NERSC}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{n}{ANL}\PYG{o}{.}\PYG{n}{GOV} + \PYG{n}{NERSC}\PYG{o}{.}\PYG{n}{GOV} \PYG{o}{=} \PYG{n}{ES}\PYG{o}{.}\PYG{n}{NET} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +When a subtag is used more than once within a tag, clients will use +the order of values to determine the path. The order of values is not +important to servers. + + +\paragraph{{[}appdefaults{]}} +\label{\detokenize{admin/conf_files/krb5_conf:appdefaults}}\label{\detokenize{admin/conf_files/krb5_conf:id5}} +\sphinxAtStartPar +Each tag in the {[}appdefaults{]} section names a Kerberos V5 application +or an option that is used by some Kerberos V5 application{[}s{]}. The +value of the tag defines the default behaviors for that application. + +\sphinxAtStartPar +For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{appdefaults}\PYG{p}{]} + \PYG{n}{telnet} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{option1} \PYG{o}{=} \PYG{n}{false} + \PYG{p}{\PYGZcb{}} + \PYG{p}{\PYGZcb{}} + \PYG{n}{telnet} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{option1} \PYG{o}{=} \PYG{n}{true} + \PYG{n}{option2} \PYG{o}{=} \PYG{n}{true} + \PYG{p}{\PYGZcb{}} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{option2} \PYG{o}{=} \PYG{n}{false} + \PYG{p}{\PYGZcb{}} + \PYG{n}{option2} \PYG{o}{=} \PYG{n}{true} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The above four ways of specifying the value of an option are shown in +order of decreasing precedence. In this example, if telnet is running +in the realm EXAMPLE.COM, it should, by default, have option1 and +option2 set to true. However, a telnet program in the realm +\sphinxcode{\sphinxupquote{ATHENA.MIT.EDU}} should have \sphinxcode{\sphinxupquote{option1}} set to false and +\sphinxcode{\sphinxupquote{option2}} set to true. Any other programs in ATHENA.MIT.EDU should +have \sphinxcode{\sphinxupquote{option2}} set to false by default. Any programs running in +other realms should have \sphinxcode{\sphinxupquote{option2}} set to true. + +\sphinxAtStartPar +The list of specifiable options for each application may be found in +that application’s man pages. The application defaults specified here +are overridden by those specified in the {\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{realms}}} section. + + +\paragraph{{[}plugins{]}} +\label{\detokenize{admin/conf_files/krb5_conf:plugins}}\label{\detokenize{admin/conf_files/krb5_conf:id6}}\begin{itemize} +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/krb5_conf:pwqual}]{\sphinxcrossref{pwqual}}} interface + +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/krb5_conf:kadm5-hook}]{\sphinxcrossref{kadm5\_hook}}} interface + +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/krb5_conf:clpreauth}]{\sphinxcrossref{clpreauth}}} and {\hyperref[\detokenize{admin/conf_files/krb5_conf:kdcpreauth}]{\sphinxcrossref{kdcpreauth}}} interfaces + +\end{itemize} + +\sphinxAtStartPar +Tags in the {[}plugins{]} section can be used to register dynamic plugin +modules and to turn modules on and off. Not every krb5 pluggable +interface uses the {[}plugins{]} section; the ones that do are documented +here. + +\sphinxAtStartPar +New in release 1.9. + +\sphinxAtStartPar +Each pluggable interface corresponds to a subsection of {[}plugins{]}. +All subsections support the same tags: +\begin{description} +\item[{\sphinxstylestrong{disable}}] \leavevmode +\sphinxAtStartPar +This tag may have multiple values. If there are values for this +tag, then the named modules will be disabled for the pluggable +interface. + +\item[{\sphinxstylestrong{enable\_only}}] \leavevmode +\sphinxAtStartPar +This tag may have multiple values. If there are values for this +tag, then only the named modules will be enabled for the pluggable +interface. + +\item[{\sphinxstylestrong{module}}] \leavevmode +\sphinxAtStartPar +This tag may have multiple values. Each value is a string of the +form \sphinxcode{\sphinxupquote{modulename:pathname}}, which causes the shared object +located at \sphinxstyleemphasis{pathname} to be registered as a dynamic module named +\sphinxstyleemphasis{modulename} for the pluggable interface. If \sphinxstyleemphasis{pathname} is not an +absolute path, it will be treated as relative to the +\sphinxstylestrong{plugin\_base\_dir} value from {\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}}. + +\end{description} + +\sphinxAtStartPar +For pluggable interfaces where module order matters, modules +registered with a \sphinxstylestrong{module} tag normally come first, in the order +they are registered, followed by built\sphinxhyphen{}in modules in the order they +are documented below. If \sphinxstylestrong{enable\_only} tags are used, then the +order of those tags overrides the normal module order. + +\sphinxAtStartPar +The following subsections are currently supported within the {[}plugins{]} +section: + + +\subparagraph{ccselect interface} +\label{\detokenize{admin/conf_files/krb5_conf:ccselect-interface}}\label{\detokenize{admin/conf_files/krb5_conf:ccselect}} +\sphinxAtStartPar +The ccselect subsection controls modules for credential cache +selection within a cache collection. In addition to any registered +dynamic modules, the following built\sphinxhyphen{}in modules exist (and may be +disabled with the disable tag): +\begin{description} +\item[{\sphinxstylestrong{k5identity}}] \leavevmode +\sphinxAtStartPar +Uses a .k5identity file in the user’s home directory to select a +client principal + +\item[{\sphinxstylestrong{realm}}] \leavevmode +\sphinxAtStartPar +Uses the service realm to guess an appropriate cache from the +collection + +\item[{\sphinxstylestrong{hostname}}] \leavevmode +\sphinxAtStartPar +If the service principal is host\sphinxhyphen{}based, uses the service hostname +to guess an appropriate cache from the collection + +\end{description} + + +\subparagraph{pwqual interface} +\label{\detokenize{admin/conf_files/krb5_conf:pwqual-interface}}\label{\detokenize{admin/conf_files/krb5_conf:pwqual}} +\sphinxAtStartPar +The pwqual subsection controls modules for the password quality +interface, which is used to reject weak passwords when passwords are +changed. The following built\sphinxhyphen{}in modules exist for this interface: +\begin{description} +\item[{\sphinxstylestrong{dict}}] \leavevmode +\sphinxAtStartPar +Checks against the realm dictionary file + +\item[{\sphinxstylestrong{empty}}] \leavevmode +\sphinxAtStartPar +Rejects empty passwords + +\item[{\sphinxstylestrong{hesiod}}] \leavevmode +\sphinxAtStartPar +Checks against user information stored in Hesiod (only if Kerberos +was built with Hesiod support) + +\item[{\sphinxstylestrong{princ}}] \leavevmode +\sphinxAtStartPar +Checks against components of the principal name + +\end{description} + + +\subparagraph{kadm5\_hook interface} +\label{\detokenize{admin/conf_files/krb5_conf:kadm5-hook-interface}}\label{\detokenize{admin/conf_files/krb5_conf:kadm5-hook}} +\sphinxAtStartPar +The kadm5\_hook interface provides plugins with information on +principal creation, modification, password changes and deletion. This +interface can be used to write a plugin to synchronize MIT Kerberos +with another database such as Active Directory. No plugins are built +in for this interface. + + +\subparagraph{kadm5\_auth interface} +\label{\detokenize{admin/conf_files/krb5_conf:kadm5-auth-interface}}\label{\detokenize{admin/conf_files/krb5_conf:kadm5-auth}} +\sphinxAtStartPar +The kadm5\_auth section (introduced in release 1.16) controls modules +for the kadmin authorization interface, which determines whether a +client principal is allowed to perform a kadmin operation. The +following built\sphinxhyphen{}in modules exist for this interface: +\begin{description} +\item[{\sphinxstylestrong{acl}}] \leavevmode +\sphinxAtStartPar +This module reads the {\hyperref[\detokenize{admin/conf_files/kadm5_acl:kadm5-acl-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kadm5.acl}}}} file, and authorizes +operations which are allowed according to the rules in the file. + +\item[{\sphinxstylestrong{self}}] \leavevmode +\sphinxAtStartPar +This module authorizes self\sphinxhyphen{}service operations including password +changes, creation of new random keys, fetching the client’s +principal record or string attributes, and fetching the policy +record associated with the client principal. + +\end{description} + + +\subparagraph{clpreauth and kdcpreauth interfaces} +\label{\detokenize{admin/conf_files/krb5_conf:clpreauth-and-kdcpreauth-interfaces}}\label{\detokenize{admin/conf_files/krb5_conf:kdcpreauth}}\label{\detokenize{admin/conf_files/krb5_conf:clpreauth}} +\sphinxAtStartPar +The clpreauth and kdcpreauth interfaces allow plugin modules to +provide client and KDC preauthentication mechanisms. The following +built\sphinxhyphen{}in modules exist for these interfaces: +\begin{description} +\item[{\sphinxstylestrong{pkinit}}] \leavevmode +\sphinxAtStartPar +This module implements the PKINIT preauthentication mechanism. + +\item[{\sphinxstylestrong{encrypted\_challenge}}] \leavevmode +\sphinxAtStartPar +This module implements the encrypted challenge FAST factor. + +\item[{\sphinxstylestrong{encrypted\_timestamp}}] \leavevmode +\sphinxAtStartPar +This module implements the encrypted timestamp mechanism. + +\end{description} + + +\subparagraph{hostrealm interface} +\label{\detokenize{admin/conf_files/krb5_conf:hostrealm-interface}}\label{\detokenize{admin/conf_files/krb5_conf:hostrealm}} +\sphinxAtStartPar +The hostrealm section (introduced in release 1.12) controls modules +for the host\sphinxhyphen{}to\sphinxhyphen{}realm interface, which affects the local mapping of +hostnames to realm names and the choice of default realm. The following +built\sphinxhyphen{}in modules exist for this interface: +\begin{description} +\item[{\sphinxstylestrong{profile}}] \leavevmode +\sphinxAtStartPar +This module consults the {[}domain\_realm{]} section of the profile for +authoritative host\sphinxhyphen{}to\sphinxhyphen{}realm mappings, and the \sphinxstylestrong{default\_realm} +variable for the default realm. + +\item[{\sphinxstylestrong{dns}}] \leavevmode +\sphinxAtStartPar +This module looks for DNS records for fallback host\sphinxhyphen{}to\sphinxhyphen{}realm +mappings and the default realm. It only operates if the +\sphinxstylestrong{dns\_lookup\_realm} variable is set to true. + +\item[{\sphinxstylestrong{domain}}] \leavevmode +\sphinxAtStartPar +This module applies heuristics for fallback host\sphinxhyphen{}to\sphinxhyphen{}realm +mappings. It implements the \sphinxstylestrong{realm\_try\_domains} variable, and +uses the uppercased parent domain of the hostname if that does not +produce a result. + +\end{description} + + +\subparagraph{localauth interface} +\label{\detokenize{admin/conf_files/krb5_conf:localauth-interface}}\label{\detokenize{admin/conf_files/krb5_conf:localauth}} +\sphinxAtStartPar +The localauth section (introduced in release 1.12) controls modules +for the local authorization interface, which affects the relationship +between Kerberos principals and local system accounts. The following +built\sphinxhyphen{}in modules exist for this interface: +\begin{description} +\item[{\sphinxstylestrong{default}}] \leavevmode +\sphinxAtStartPar +This module implements the \sphinxstylestrong{DEFAULT} type for \sphinxstylestrong{auth\_to\_local} +values. + +\item[{\sphinxstylestrong{rule}}] \leavevmode +\sphinxAtStartPar +This module implements the \sphinxstylestrong{RULE} type for \sphinxstylestrong{auth\_to\_local} +values. + +\item[{\sphinxstylestrong{names}}] \leavevmode +\sphinxAtStartPar +This module looks for an \sphinxstylestrong{auth\_to\_local\_names} mapping for the +principal name. + +\item[{\sphinxstylestrong{auth\_to\_local}}] \leavevmode +\sphinxAtStartPar +This module processes \sphinxstylestrong{auth\_to\_local} values in the default +realm’s section, and applies the default method if no +\sphinxstylestrong{auth\_to\_local} values exist. + +\item[{\sphinxstylestrong{k5login}}] \leavevmode +\sphinxAtStartPar +This module authorizes a principal to a local account according to +the account’s \DUrole{xref,std,std-ref}{.k5login(5)} file. + +\item[{\sphinxstylestrong{an2ln}}] \leavevmode +\sphinxAtStartPar +This module authorizes a principal to a local account if the +principal name maps to the local account name. + +\end{description} + + +\subparagraph{certauth interface} +\label{\detokenize{admin/conf_files/krb5_conf:certauth-interface}}\label{\detokenize{admin/conf_files/krb5_conf:certauth}} +\sphinxAtStartPar +The certauth section (introduced in release 1.16) controls modules for +the certificate authorization interface, which determines whether a +certificate is allowed to preauthenticate a user via PKINIT. The +following built\sphinxhyphen{}in modules exist for this interface: +\begin{description} +\item[{\sphinxstylestrong{pkinit\_san}}] \leavevmode +\sphinxAtStartPar +This module authorizes the certificate if it contains a PKINIT +Subject Alternative Name for the requested client principal, or a +Microsoft UPN SAN matching the principal if \sphinxstylestrong{pkinit\_allow\_upn} +is set to true for the realm. + +\item[{\sphinxstylestrong{pkinit\_eku}}] \leavevmode +\sphinxAtStartPar +This module rejects the certificate if it does not contain an +Extended Key Usage attribute consistent with the +\sphinxstylestrong{pkinit\_eku\_checking} value for the realm. + +\item[{\sphinxstylestrong{dbmatch}}] \leavevmode +\sphinxAtStartPar +This module authorizes or rejects the certificate according to +whether it matches the \sphinxstylestrong{pkinit\_cert\_match} string attribute on +the client principal, if that attribute is present. + +\end{description} + + +\subsubsection{PKINIT options} +\label{\detokenize{admin/conf_files/krb5_conf:pkinit-options}} +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The following are PKINIT\sphinxhyphen{}specific options. These values may +be specified in {[}libdefaults{]} as global defaults, or within +a realm\sphinxhyphen{}specific subsection of {[}libdefaults{]}, or may be +specified as realm\sphinxhyphen{}specific values in the {[}realms{]} section. +A realm\sphinxhyphen{}specific value overrides, not adds to, a generic +{[}libdefaults{]} specification. The search order is: +\end{sphinxadmonition} +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +realm\sphinxhyphen{}specific subsection of {[}libdefaults{]}: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{libdefaults}\PYG{p}{]} + \PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{pkinit\PYGZus{}anchors} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{usr}\PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com}\PYG{o}{.}\PYG{n}{crt} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\item {} +\sphinxAtStartPar +realm\sphinxhyphen{}specific value in the {[}realms{]} section: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{realms}\PYG{p}{]} + \PYG{n}{OTHERREALM}\PYG{o}{.}\PYG{n}{ORG} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{pkinit\PYGZus{}anchors} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{usr}\PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{otherrealm}\PYG{o}{.}\PYG{n}{org}\PYG{o}{.}\PYG{n}{crt} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\item {} +\sphinxAtStartPar +generic value in the {[}libdefaults{]} section: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{libdefaults}\PYG{p}{]} + \PYG{n}{pkinit\PYGZus{}anchors} \PYG{o}{=} \PYG{n}{DIR}\PYG{p}{:}\PYG{o}{/}\PYG{n}{usr}\PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{generic\PYGZus{}trusted\PYGZus{}cas}\PYG{o}{/} +\end{sphinxVerbatim} + +\end{enumerate} + + +\paragraph{Specifying PKINIT identity information} +\label{\detokenize{admin/conf_files/krb5_conf:specifying-pkinit-identity-information}}\label{\detokenize{admin/conf_files/krb5_conf:pkinit-identity}} +\sphinxAtStartPar +The syntax for specifying Public Key identity, trust, and revocation +information for PKINIT is as follows: +\begin{description} +\item[{\sphinxstylestrong{FILE:}\sphinxstyleemphasis{filename}{[}\sphinxstylestrong{,}\sphinxstyleemphasis{keyfilename}{]}}] \leavevmode +\sphinxAtStartPar +This option has context\sphinxhyphen{}specific behavior. + +\sphinxAtStartPar +In \sphinxstylestrong{pkinit\_identity} or \sphinxstylestrong{pkinit\_identities}, \sphinxstyleemphasis{filename} +specifies the name of a PEM\sphinxhyphen{}format file containing the user’s +certificate. If \sphinxstyleemphasis{keyfilename} is not specified, the user’s +private key is expected to be in \sphinxstyleemphasis{filename} as well. Otherwise, +\sphinxstyleemphasis{keyfilename} is the name of the file containing the private key. + +\sphinxAtStartPar +In \sphinxstylestrong{pkinit\_anchors} or \sphinxstylestrong{pkinit\_pool}, \sphinxstyleemphasis{filename} is assumed to +be the name of an OpenSSL\sphinxhyphen{}style ca\sphinxhyphen{}bundle file. + +\item[{\sphinxstylestrong{DIR:}\sphinxstyleemphasis{dirname}}] \leavevmode +\sphinxAtStartPar +This option has context\sphinxhyphen{}specific behavior. + +\sphinxAtStartPar +In \sphinxstylestrong{pkinit\_identity} or \sphinxstylestrong{pkinit\_identities}, \sphinxstyleemphasis{dirname} +specifies a directory with files named \sphinxcode{\sphinxupquote{*.crt}} and \sphinxcode{\sphinxupquote{*.key}} +where the first part of the file name is the same for matching +pairs of certificate and private key files. When a file with a +name ending with \sphinxcode{\sphinxupquote{.crt}} is found, a matching file ending with +\sphinxcode{\sphinxupquote{.key}} is assumed to contain the private key. If no such file +is found, then the certificate in the \sphinxcode{\sphinxupquote{.crt}} is not used. + +\sphinxAtStartPar +In \sphinxstylestrong{pkinit\_anchors} or \sphinxstylestrong{pkinit\_pool}, \sphinxstyleemphasis{dirname} is assumed to +be an OpenSSL\sphinxhyphen{}style hashed CA directory where each CA cert is +stored in a file named \sphinxcode{\sphinxupquote{hash\sphinxhyphen{}of\sphinxhyphen{}ca\sphinxhyphen{}cert.\#}}. This infrastructure +is encouraged, but all files in the directory will be examined and +if they contain certificates (in PEM format), they will be used. + +\sphinxAtStartPar +In \sphinxstylestrong{pkinit\_revoke}, \sphinxstyleemphasis{dirname} is assumed to be an OpenSSL\sphinxhyphen{}style +hashed CA directory where each revocation list is stored in a file +named \sphinxcode{\sphinxupquote{hash\sphinxhyphen{}of\sphinxhyphen{}ca\sphinxhyphen{}cert.r\#}}. This infrastructure is encouraged, +but all files in the directory will be examined and if they +contain a revocation list (in PEM format), they will be used. + +\item[{\sphinxstylestrong{PKCS12:}\sphinxstyleemphasis{filename}}] \leavevmode +\sphinxAtStartPar +\sphinxstyleemphasis{filename} is the name of a PKCS \#12 format file, containing the +user’s certificate and private key. + +\item[{\sphinxstylestrong{PKCS11:}{[}\sphinxstylestrong{module\_name=}{]}\sphinxstyleemphasis{modname}{[}\sphinxstylestrong{:slotid=}\sphinxstyleemphasis{slot\sphinxhyphen{}id}{]}{[}\sphinxstylestrong{:token=}\sphinxstyleemphasis{token\sphinxhyphen{}label}{]}{[}\sphinxstylestrong{:certid=}\sphinxstyleemphasis{cert\sphinxhyphen{}id}{]}{[}\sphinxstylestrong{:certlabel=}\sphinxstyleemphasis{cert\sphinxhyphen{}label}{]}}] \leavevmode +\sphinxAtStartPar +All keyword/values are optional. \sphinxstyleemphasis{modname} specifies the location +of a library implementing PKCS \#11. If a value is encountered +with no keyword, it is assumed to be the \sphinxstyleemphasis{modname}. If no +module\sphinxhyphen{}name is specified, the default is {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{PKCS11\_MODNAME}}}}. +\sphinxcode{\sphinxupquote{slotid=}} and/or \sphinxcode{\sphinxupquote{token=}} may be specified to force the use of +a particular smard card reader or token if there is more than one +available. \sphinxcode{\sphinxupquote{certid=}} and/or \sphinxcode{\sphinxupquote{certlabel=}} may be specified to +force the selection of a particular certificate on the device. +See the \sphinxstylestrong{pkinit\_cert\_match} configuration option for more ways +to select a particular certificate to use for PKINIT. + +\item[{\sphinxstylestrong{ENV:}\sphinxstyleemphasis{envvar}}] \leavevmode +\sphinxAtStartPar +\sphinxstyleemphasis{envvar} specifies the name of an environment variable which has +been set to a value conforming to one of the previous values. For +example, \sphinxcode{\sphinxupquote{ENV:X509\_PROXY}}, where environment variable +\sphinxcode{\sphinxupquote{X509\_PROXY}} has been set to \sphinxcode{\sphinxupquote{FILE:/tmp/my\_proxy.pem}}. + +\end{description} + + +\paragraph{PKINIT krb5.conf options} +\label{\detokenize{admin/conf_files/krb5_conf:pkinit-krb5-conf-options}}\begin{description} +\item[{\sphinxstylestrong{pkinit\_anchors}}] \leavevmode +\sphinxAtStartPar +Specifies the location of trusted anchor (root) certificates which +the client trusts to sign KDC certificates. This option may be +specified multiple times. These values from the config file are +not used if the user specifies X509\_anchors on the command line. + +\item[{\sphinxstylestrong{pkinit\_cert\_match}}] \leavevmode +\sphinxAtStartPar +Specifies matching rules that the client certificate must match +before it is used to attempt PKINIT authentication. If a user has +multiple certificates available (on a smart card, or via other +media), there must be exactly one certificate chosen before +attempting PKINIT authentication. This option may be specified +multiple times. All the available certificates are checked +against each rule in order until there is a match of exactly one +certificate. + +\sphinxAtStartPar +The Subject and Issuer comparison strings are the \index{RFC@\spxentry{RFC}!RFC 2253@\spxentry{RFC 2253}}\sphinxhref{https://tools.ietf.org/html/rfc2253.html}{\sphinxstylestrong{RFC 2253}} +string representations from the certificate Subject DN and Issuer +DN values. + +\sphinxAtStartPar +The syntax of the matching rules is: +\begin{quote} + +\sphinxAtStartPar +{[}\sphinxstyleemphasis{relation\sphinxhyphen{}operator}{]}\sphinxstyleemphasis{component\sphinxhyphen{}rule} … +\end{quote} + +\sphinxAtStartPar +where: +\begin{description} +\item[{\sphinxstyleemphasis{relation\sphinxhyphen{}operator}}] \leavevmode +\sphinxAtStartPar +can be either \sphinxcode{\sphinxupquote{\&\&}}, meaning all component rules must match, +or \sphinxcode{\sphinxupquote{||}}, meaning only one component rule must match. The +default is \sphinxcode{\sphinxupquote{\&\&}}. + +\item[{\sphinxstyleemphasis{component\sphinxhyphen{}rule}}] \leavevmode +\sphinxAtStartPar +can be one of the following. Note that there is no +punctuation or whitespace between component rules. +\begin{quote} + +\begin{DUlineblock}{0em} +\item[] \sphinxstylestrong{\textless{}SUBJECT\textgreater{}}\sphinxstyleemphasis{regular\sphinxhyphen{}expression} +\item[] \sphinxstylestrong{\textless{}ISSUER\textgreater{}}\sphinxstyleemphasis{regular\sphinxhyphen{}expression} +\item[] \sphinxstylestrong{\textless{}SAN\textgreater{}}\sphinxstyleemphasis{regular\sphinxhyphen{}expression} +\item[] \sphinxstylestrong{\textless{}EKU\textgreater{}}\sphinxstyleemphasis{extended\sphinxhyphen{}key\sphinxhyphen{}usage\sphinxhyphen{}list} +\item[] \sphinxstylestrong{\textless{}KU\textgreater{}}\sphinxstyleemphasis{key\sphinxhyphen{}usage\sphinxhyphen{}list} +\end{DUlineblock} +\end{quote} + +\sphinxAtStartPar +\sphinxstyleemphasis{extended\sphinxhyphen{}key\sphinxhyphen{}usage\sphinxhyphen{}list} is a comma\sphinxhyphen{}separated list of +required Extended Key Usage values. All values in the list +must be present in the certificate. Extended Key Usage values +can be: +\begin{itemize} +\item {} +\sphinxAtStartPar +pkinit + +\item {} +\sphinxAtStartPar +msScLogin + +\item {} +\sphinxAtStartPar +clientAuth + +\item {} +\sphinxAtStartPar +emailProtection + +\end{itemize} + +\sphinxAtStartPar +\sphinxstyleemphasis{key\sphinxhyphen{}usage\sphinxhyphen{}list} is a comma\sphinxhyphen{}separated list of required Key +Usage values. All values in the list must be present in the +certificate. Key Usage values can be: +\begin{itemize} +\item {} +\sphinxAtStartPar +digitalSignature + +\item {} +\sphinxAtStartPar +keyEncipherment + +\end{itemize} + +\end{description} + +\sphinxAtStartPar +Examples: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{pkinit\PYGZus{}cert\PYGZus{}match} \PYG{o}{=} \PYG{o}{|}\PYG{o}{|}\PYG{o}{\PYGZlt{}}\PYG{n}{SUBJECT}\PYG{o}{\PYGZgt{}}\PYG{o}{.}\PYG{o}{*}\PYG{n}{DoE}\PYG{o}{.}\PYG{o}{*}\PYG{o}{\PYGZlt{}}\PYG{n}{SAN}\PYG{o}{\PYGZgt{}}\PYG{o}{.}\PYG{o}{*}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM} +\PYG{n}{pkinit\PYGZus{}cert\PYGZus{}match} \PYG{o}{=} \PYG{o}{\PYGZam{}}\PYG{o}{\PYGZam{}}\PYG{o}{\PYGZlt{}}\PYG{n}{EKU}\PYG{o}{\PYGZgt{}}\PYG{n}{msScLogin}\PYG{p}{,}\PYG{n}{clientAuth}\PYG{o}{\PYGZlt{}}\PYG{n}{ISSUER}\PYG{o}{\PYGZgt{}}\PYG{o}{.}\PYG{o}{*}\PYG{n}{DoE}\PYG{o}{.}\PYG{o}{*} +\PYG{n}{pkinit\PYGZus{}cert\PYGZus{}match} \PYG{o}{=} \PYG{o}{\PYGZlt{}}\PYG{n}{EKU}\PYG{o}{\PYGZgt{}}\PYG{n}{msScLogin}\PYG{p}{,}\PYG{n}{clientAuth}\PYG{o}{\PYGZlt{}}\PYG{n}{KU}\PYG{o}{\PYGZgt{}}\PYG{n}{digitalSignature} +\end{sphinxVerbatim} + +\item[{\sphinxstylestrong{pkinit\_eku\_checking}}] \leavevmode +\sphinxAtStartPar +This option specifies what Extended Key Usage value the KDC +certificate presented to the client must contain. (Note that if +the KDC certificate has the pkinit SubjectAlternativeName encoded +as the Kerberos TGS name, EKU checking is not necessary since the +issuing CA has certified this as a KDC certificate.) The values +recognized in the krb5.conf file are: +\begin{description} +\item[{\sphinxstylestrong{kpKDC}}] \leavevmode +\sphinxAtStartPar +This is the default value and specifies that the KDC must have +the id\sphinxhyphen{}pkinit\sphinxhyphen{}KPKdc EKU as defined in \index{RFC@\spxentry{RFC}!RFC 4556@\spxentry{RFC 4556}}\sphinxhref{https://tools.ietf.org/html/rfc4556.html}{\sphinxstylestrong{RFC 4556}}. + +\item[{\sphinxstylestrong{kpServerAuth}}] \leavevmode +\sphinxAtStartPar +If \sphinxstylestrong{kpServerAuth} is specified, a KDC certificate with the +id\sphinxhyphen{}kp\sphinxhyphen{}serverAuth EKU will be accepted. This key usage value +is used in most commercially issued server certificates. + +\item[{\sphinxstylestrong{none}}] \leavevmode +\sphinxAtStartPar +If \sphinxstylestrong{none} is specified, then the KDC certificate will not be +checked to verify it has an acceptable EKU. The use of this +option is not recommended. + +\end{description} + +\item[{\sphinxstylestrong{pkinit\_dh\_min\_bits}}] \leavevmode +\sphinxAtStartPar +Specifies the size of the Diffie\sphinxhyphen{}Hellman key the client will +attempt to use. The acceptable values are 1024, 2048, and 4096. +The default is 2048. + +\item[{\sphinxstylestrong{pkinit\_identities}}] \leavevmode +\sphinxAtStartPar +Specifies the location(s) to be used to find the user’s X.509 +identity information. If this option is specified multiple times, +each value is attempted in order until certificates are found. +Note that these values are not used if the user specifies +\sphinxstylestrong{X509\_user\_identity} on the command line. + +\item[{\sphinxstylestrong{pkinit\_kdc\_hostname}}] \leavevmode +\sphinxAtStartPar +The presence of this option indicates that the client is willing +to accept a KDC certificate with a dNSName SAN (Subject +Alternative Name) rather than requiring the id\sphinxhyphen{}pkinit\sphinxhyphen{}san as +defined in \index{RFC@\spxentry{RFC}!RFC 4556@\spxentry{RFC 4556}}\sphinxhref{https://tools.ietf.org/html/rfc4556.html}{\sphinxstylestrong{RFC 4556}}. This option may be specified multiple +times. Its value should contain the acceptable hostname for the +KDC (as contained in its certificate). + +\item[{\sphinxstylestrong{pkinit\_pool}}] \leavevmode +\sphinxAtStartPar +Specifies the location of intermediate certificates which may be +used by the client to complete the trust chain between a KDC +certificate and a trusted anchor. This option may be specified +multiple times. + +\item[{\sphinxstylestrong{pkinit\_require\_crl\_checking}}] \leavevmode +\sphinxAtStartPar +The default certificate verification process will always check the +available revocation information to see if a certificate has been +revoked. If a match is found for the certificate in a CRL, +verification fails. If the certificate being verified is not +listed in a CRL, or there is no CRL present for its issuing CA, +and \sphinxstylestrong{pkinit\_require\_crl\_checking} is false, then verification +succeeds. + +\sphinxAtStartPar +However, if \sphinxstylestrong{pkinit\_require\_crl\_checking} is true and there is +no CRL information available for the issuing CA, then verification +fails. + +\sphinxAtStartPar +\sphinxstylestrong{pkinit\_require\_crl\_checking} should be set to true if the +policy is such that up\sphinxhyphen{}to\sphinxhyphen{}date CRLs must be present for every CA. + +\item[{\sphinxstylestrong{pkinit\_revoke}}] \leavevmode +\sphinxAtStartPar +Specifies the location of Certificate Revocation List (CRL) +information to be used by the client when verifying the validity +of the KDC certificate presented. This option may be specified +multiple times. + +\end{description} + + +\subsubsection{Parameter expansion} +\label{\detokenize{admin/conf_files/krb5_conf:parameter-expansion}}\label{\detokenize{admin/conf_files/krb5_conf:id7}} +\sphinxAtStartPar +Starting with release 1.11, several variables, such as +\sphinxstylestrong{default\_keytab\_name}, allow parameters to be expanded. +Valid parameters are: +\begin{quote} + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\%\{TEMP\} +& +\sphinxAtStartPar +Temporary directory +\\ +\hline +\sphinxAtStartPar +\%\{uid\} +& +\sphinxAtStartPar +Unix real UID or Windows SID +\\ +\hline +\sphinxAtStartPar +\%\{euid\} +& +\sphinxAtStartPar +Unix effective user ID or Windows SID +\\ +\hline +\sphinxAtStartPar +\%\{USERID\} +& +\sphinxAtStartPar +Same as \%\{uid\} +\\ +\hline +\sphinxAtStartPar +\%\{null\} +& +\sphinxAtStartPar +Empty string +\\ +\hline +\sphinxAtStartPar +\%\{LIBDIR\} +& +\sphinxAtStartPar +Installation library directory +\\ +\hline +\sphinxAtStartPar +\%\{BINDIR\} +& +\sphinxAtStartPar +Installation binary directory +\\ +\hline +\sphinxAtStartPar +\%\{SBINDIR\} +& +\sphinxAtStartPar +Installation admin binary directory +\\ +\hline +\sphinxAtStartPar +\%\{username\} +& +\sphinxAtStartPar +(Unix) Username of effective user ID +\\ +\hline +\sphinxAtStartPar +\%\{APPDATA\} +& +\sphinxAtStartPar +(Windows) Roaming application data for current user +\\ +\hline +\sphinxAtStartPar +\%\{COMMON\_APPDATA\} +& +\sphinxAtStartPar +(Windows) Application data for all users +\\ +\hline +\sphinxAtStartPar +\%\{LOCAL\_APPDATA\} +& +\sphinxAtStartPar +(Windows) Local application data for current user +\\ +\hline +\sphinxAtStartPar +\%\{SYSTEM\} +& +\sphinxAtStartPar +(Windows) Windows system folder +\\ +\hline +\sphinxAtStartPar +\%\{WINDOWS\} +& +\sphinxAtStartPar +(Windows) Windows folder +\\ +\hline +\sphinxAtStartPar +\%\{USERCONFIG\} +& +\sphinxAtStartPar +(Windows) Per\sphinxhyphen{}user MIT krb5 config file directory +\\ +\hline +\sphinxAtStartPar +\%\{COMMONCONFIG\} +& +\sphinxAtStartPar +(Windows) Common MIT krb5 config file directory +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} +\end{quote} + + +\subsubsection{Sample krb5.conf file} +\label{\detokenize{admin/conf_files/krb5_conf:sample-krb5-conf-file}} +\sphinxAtStartPar +Here is an example of a generic krb5.conf file: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{libdefaults}\PYG{p}{]} + \PYG{n}{default\PYGZus{}realm} \PYG{o}{=} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} + \PYG{n}{dns\PYGZus{}lookup\PYGZus{}kdc} \PYG{o}{=} \PYG{n}{true} + \PYG{n}{dns\PYGZus{}lookup\PYGZus{}realm} \PYG{o}{=} \PYG{n}{false} + +\PYG{p}{[}\PYG{n}{realms}\PYG{p}{]} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{kdc} \PYG{o}{=} \PYG{n}{kerberos}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{n}{kdc} \PYG{o}{=} \PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{n}{kdc} \PYG{o}{=} \PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{2.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{n}{admin\PYGZus{}server} \PYG{o}{=} \PYG{n}{kerberos}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{n}{primary\PYGZus{}kdc} \PYG{o}{=} \PYG{n}{kerberos}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{p}{\PYGZcb{}} + \PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{kdc} \PYG{o}{=} \PYG{n}{kerberos}\PYG{o}{.}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com} + \PYG{n}{kdc} \PYG{o}{=} \PYG{n}{kerberos}\PYG{o}{\PYGZhy{}}\PYG{l+m+mf}{1.}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com} + \PYG{n}{admin\PYGZus{}server} \PYG{o}{=} \PYG{n}{kerberos}\PYG{o}{.}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com} + \PYG{p}{\PYGZcb{}} + +\PYG{p}{[}\PYG{n}{domain\PYGZus{}realm}\PYG{p}{]} + \PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{o}{=} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} + +\PYG{p}{[}\PYG{n}{capaths}\PYG{p}{]} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM} \PYG{o}{=} \PYG{o}{.} + \PYG{p}{\PYGZcb{}} + \PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{o}{.} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + + +\subsubsection{FILES} +\label{\detokenize{admin/conf_files/krb5_conf:files}} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/etc/krb5.conf}} + + +\subsubsection{SEE ALSO} +\label{\detokenize{admin/conf_files/krb5_conf:see-also}} +\sphinxAtStartPar +syslog(3) + + +\subsection{kdc.conf} +\label{\detokenize{admin/conf_files/kdc_conf:kdc-conf}}\label{\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}}\label{\detokenize{admin/conf_files/kdc_conf::doc}} +\sphinxAtStartPar +The kdc.conf file supplements {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} for programs which +are typically only used on a KDC, such as the {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} and +{\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} daemons and the {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} program. +Relations documented here may also be specified in krb5.conf; for the +KDC programs mentioned, krb5.conf and kdc.conf will be merged into a +single configuration profile. + +\sphinxAtStartPar +Normally, the kdc.conf file is found in the KDC state directory, +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}. You can override the default location by setting the +environment variable \sphinxstylestrong{KRB5\_KDC\_PROFILE}. + +\sphinxAtStartPar +Please note that you need to restart the KDC daemon for any configuration +changes to take effect. + + +\subsubsection{Structure} +\label{\detokenize{admin/conf_files/kdc_conf:structure}} +\sphinxAtStartPar +The kdc.conf file is set up in the same format as the +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} file. + + +\subsubsection{Sections} +\label{\detokenize{admin/conf_files/kdc_conf:sections}} +\sphinxAtStartPar +The kdc.conf file may contain the following sections: + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdcdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}kdcdefaults{]}}}}} +& +\sphinxAtStartPar +Default values for KDC behavior +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} +& +\sphinxAtStartPar +Realm\sphinxhyphen{}specific database configuration and settings +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/kdc_conf:dbdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}dbdefaults{]}}}}} +& +\sphinxAtStartPar +Default database settings +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/kdc_conf:dbmodules}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}dbmodules{]}}}}} +& +\sphinxAtStartPar +Per\sphinxhyphen{}database settings +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/kdc_conf:logging}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}logging{]}}}}} +& +\sphinxAtStartPar +Controls how Kerberos daemons perform logging +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\paragraph{{[}kdcdefaults{]}} +\label{\detokenize{admin/conf_files/kdc_conf:kdcdefaults}}\label{\detokenize{admin/conf_files/kdc_conf:id1}} +\sphinxAtStartPar +Some relations in the {[}kdcdefaults{]} section specify default values for +realm variables, to be used if the {[}realms{]} subsection does not +contain a relation for the tag. See the {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} section for +the definitions of these relations. +\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstylestrong{host\_based\_services} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{kdc\_listen} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{kdc\_ports} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{kdc\_tcp\_listen} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{kdc\_tcp\_ports} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{no\_host\_referral} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{restrict\_anonymous\_to\_tgt} + +\end{itemize} + +\sphinxAtStartPar +The following {[}kdcdefaults{]} variables have no per\sphinxhyphen{}realm equivalent: +\begin{description} +\item[{\sphinxstylestrong{kdc\_max\_dgram\_reply\_size}}] \leavevmode +\sphinxAtStartPar +Specifies the maximum packet size that can be sent over UDP. The +default value is 4096 bytes. + +\item[{\sphinxstylestrong{kdc\_tcp\_listen\_backlog}}] \leavevmode +\sphinxAtStartPar +(Integer.) Set the size of the listen queue length for the KDC +daemon. The value may be limited by OS settings. The default +value is 5. + +\item[{\sphinxstylestrong{spake\_preauth\_kdc\_challenge}}] \leavevmode +\sphinxAtStartPar +(String.) Specifies the group for a SPAKE optimistic challenge. +See the \sphinxstylestrong{spake\_preauth\_groups} variable in {\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}} +for possible values. The default is not to issue an optimistic +challenge. (New in release 1.17.) + +\end{description} + + +\paragraph{{[}realms{]}} +\label{\detokenize{admin/conf_files/kdc_conf:realms}}\label{\detokenize{admin/conf_files/kdc_conf:kdc-realms}} +\sphinxAtStartPar +Each tag in the {[}realms{]} section is the name of a Kerberos realm. The +value of the tag is a subsection where the relations define KDC +parameters for that particular realm. The following example shows how +to define one parameter for the ATHENA.MIT.EDU realm: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{realms}\PYG{p}{]} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{max\PYGZus{}renewable\PYGZus{}life} \PYG{o}{=} \PYG{l+m+mi}{7}\PYG{n}{d} \PYG{l+m+mi}{0}\PYG{n}{h} \PYG{l+m+mi}{0}\PYG{n}{m} \PYG{l+m+mi}{0}\PYG{n}{s} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The following tags may be specified in a {[}realms{]} subsection: +\begin{description} +\item[{\sphinxstylestrong{acl\_file}}] \leavevmode +\sphinxAtStartPar +(String.) Location of the access control list file that +{\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} uses to determine which principals are allowed +which permissions on the Kerberos database. To operate without an +ACL file, set this relation to the empty string with \sphinxcode{\sphinxupquote{acl\_file = +""}}. The default value is {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/kadm5.acl}}. For more +information on Kerberos ACL file see {\hyperref[\detokenize{admin/conf_files/kadm5_acl:kadm5-acl-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kadm5.acl}}}}. + +\item[{\sphinxstylestrong{database\_module}}] \leavevmode +\sphinxAtStartPar +(String.) This relation indicates the name of the configuration +section under {\hyperref[\detokenize{admin/conf_files/kdc_conf:dbmodules}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}dbmodules{]}}}}} for database\sphinxhyphen{}specific parameters +used by the loadable database library. The default value is the +realm name. If this configuration section does not exist, default +values will be used for all database parameters. + +\item[{\sphinxstylestrong{database\_name}}] \leavevmode +\sphinxAtStartPar +(String, deprecated.) This relation specifies the location of the +Kerberos database for this realm, if the DB2 module is being used +and the {\hyperref[\detokenize{admin/conf_files/kdc_conf:dbmodules}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}dbmodules{]}}}}} configuration section does not specify a +database name. The default value is {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/principal}}. + +\item[{\sphinxstylestrong{default\_principal\_expiration}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{abstime} string.) Specifies the default expiration date of +principals created in this realm. The default value is 0, which +means no expiration date. + +\item[{\sphinxstylestrong{default\_principal\_flags}}] \leavevmode +\sphinxAtStartPar +(Flag string.) Specifies the default attributes of principals +created in this realm. The format for this string is a +comma\sphinxhyphen{}separated list of flags, with ‘+’ before each flag that +should be enabled and ‘\sphinxhyphen{}’ before each flag that should be +disabled. The \sphinxstylestrong{postdateable}, \sphinxstylestrong{forwardable}, \sphinxstylestrong{tgt\sphinxhyphen{}based}, +\sphinxstylestrong{renewable}, \sphinxstylestrong{proxiable}, \sphinxstylestrong{dup\sphinxhyphen{}skey}, \sphinxstylestrong{allow\sphinxhyphen{}tickets}, and +\sphinxstylestrong{service} flags default to enabled. + +\sphinxAtStartPar +There are a number of possible flags: +\begin{description} +\item[{\sphinxstylestrong{allow\sphinxhyphen{}tickets}}] \leavevmode +\sphinxAtStartPar +Enabling this flag means that the KDC will issue tickets for +this principal. Disabling this flag essentially deactivates +the principal within this realm. + +\item[{\sphinxstylestrong{dup\sphinxhyphen{}skey}}] \leavevmode +\sphinxAtStartPar +Enabling this flag allows the KDC to issue user\sphinxhyphen{}to\sphinxhyphen{}user +service tickets for this principal. + +\item[{\sphinxstylestrong{forwardable}}] \leavevmode +\sphinxAtStartPar +Enabling this flag allows the principal to obtain forwardable +tickets. + +\item[{\sphinxstylestrong{hwauth}}] \leavevmode +\sphinxAtStartPar +If this flag is enabled, then the principal is required to +preauthenticate using a hardware device before receiving any +tickets. + +\item[{\sphinxstylestrong{no\sphinxhyphen{}auth\sphinxhyphen{}data\sphinxhyphen{}required}}] \leavevmode +\sphinxAtStartPar +Enabling this flag prevents PAC or AD\sphinxhyphen{}SIGNEDPATH data from +being added to service tickets for the principal. + +\item[{\sphinxstylestrong{ok\sphinxhyphen{}as\sphinxhyphen{}delegate}}] \leavevmode +\sphinxAtStartPar +If this flag is enabled, it hints the client that credentials +can and should be delegated when authenticating to the +service. + +\item[{\sphinxstylestrong{ok\sphinxhyphen{}to\sphinxhyphen{}auth\sphinxhyphen{}as\sphinxhyphen{}delegate}}] \leavevmode +\sphinxAtStartPar +Enabling this flag allows the principal to use S4USelf tickets. + +\item[{\sphinxstylestrong{postdateable}}] \leavevmode +\sphinxAtStartPar +Enabling this flag allows the principal to obtain postdateable +tickets. + +\item[{\sphinxstylestrong{preauth}}] \leavevmode +\sphinxAtStartPar +If this flag is enabled on a client principal, then that +principal is required to preauthenticate to the KDC before +receiving any tickets. On a service principal, enabling this +flag means that service tickets for this principal will only +be issued to clients with a TGT that has the preauthenticated +bit set. + +\item[{\sphinxstylestrong{proxiable}}] \leavevmode +\sphinxAtStartPar +Enabling this flag allows the principal to obtain proxy +tickets. + +\item[{\sphinxstylestrong{pwchange}}] \leavevmode +\sphinxAtStartPar +Enabling this flag forces a password change for this +principal. + +\item[{\sphinxstylestrong{pwservice}}] \leavevmode +\sphinxAtStartPar +If this flag is enabled, it marks this principal as a password +change service. This should only be used in special cases, +for example, if a user’s password has expired, then the user +has to get tickets for that principal without going through +the normal password authentication in order to be able to +change the password. + +\item[{\sphinxstylestrong{renewable}}] \leavevmode +\sphinxAtStartPar +Enabling this flag allows the principal to obtain renewable +tickets. + +\item[{\sphinxstylestrong{service}}] \leavevmode +\sphinxAtStartPar +Enabling this flag allows the the KDC to issue service tickets +for this principal. In release 1.17 and later, user\sphinxhyphen{}to\sphinxhyphen{}user +service tickets are still allowed if the \sphinxstylestrong{dup\sphinxhyphen{}skey} flag is +set. + +\item[{\sphinxstylestrong{tgt\sphinxhyphen{}based}}] \leavevmode +\sphinxAtStartPar +Enabling this flag allows a principal to obtain tickets based +on a ticket\sphinxhyphen{}granting\sphinxhyphen{}ticket, rather than repeating the +authentication process that was used to obtain the TGT. + +\end{description} + +\item[{\sphinxstylestrong{dict\_file}}] \leavevmode +\sphinxAtStartPar +(String.) Location of the dictionary file containing strings that +are not allowed as passwords. The file should contain one string +per line, with no additional whitespace. If none is specified or +if there is no policy assigned to the principal, no dictionary +checks of passwords will be performed. + +\item[{\sphinxstylestrong{disable\_pac}}] \leavevmode +\sphinxAtStartPar +(Boolean value.) If true, the KDC will not issue PACs for this +realm, and S4U2Self and S4U2Proxy operations will be disabled. +The default is false, which will permit the KDC to issue PACs. +New in release 1.20. + +\item[{\sphinxstylestrong{encrypted\_challenge\_indicator}}] \leavevmode +\sphinxAtStartPar +(String.) Specifies the authentication indicator value that the KDC +asserts into tickets obtained using FAST encrypted challenge +pre\sphinxhyphen{}authentication. New in 1.16. + +\item[{\sphinxstylestrong{host\_based\_services}}] \leavevmode +\sphinxAtStartPar +(Whitespace\sphinxhyphen{} or comma\sphinxhyphen{}separated list.) Lists services which will +get host\sphinxhyphen{}based referral processing even if the server principal is +not marked as host\sphinxhyphen{}based by the client. + +\item[{\sphinxstylestrong{iprop\_enable}}] \leavevmode +\sphinxAtStartPar +(Boolean value.) Specifies whether incremental database +propagation is enabled. The default value is false. + +\item[{\sphinxstylestrong{iprop\_ulogsize}}] \leavevmode +\sphinxAtStartPar +(Integer.) Specifies the maximum number of log entries to be +retained for incremental propagation. The default value is 1000. +Prior to release 1.11, the maximum value was 2500. New in release +1.19. + +\item[{\sphinxstylestrong{iprop\_master\_ulogsize}}] \leavevmode +\sphinxAtStartPar +The name for \sphinxstylestrong{iprop\_ulogsize} prior to release 1.19. Its value is +used as a fallback if \sphinxstylestrong{iprop\_ulogsize} is not specified. + +\item[{\sphinxstylestrong{iprop\_replica\_poll}}] \leavevmode +\sphinxAtStartPar +(Delta time string.) Specifies how often the replica KDC polls +for new updates from the primary. The default value is \sphinxcode{\sphinxupquote{2m}} +(that is, two minutes). New in release 1.17. + +\item[{\sphinxstylestrong{iprop\_slave\_poll}}] \leavevmode +\sphinxAtStartPar +(Delta time string.) The name for \sphinxstylestrong{iprop\_replica\_poll} prior to +release 1.17. Its value is used as a fallback if +\sphinxstylestrong{iprop\_replica\_poll} is not specified. + +\item[{\sphinxstylestrong{iprop\_listen}}] \leavevmode +\sphinxAtStartPar +(Whitespace\sphinxhyphen{} or comma\sphinxhyphen{}separated list.) Specifies the iprop RPC +listening addresses and/or ports for the {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} daemon. +Each entry may be an interface address, a port number, or an +address and port number separated by a colon. If the address +contains colons, enclose it in square brackets. If no address is +specified, the wildcard address is used. If kadmind fails to bind +to any of the specified addresses, it will fail to start. The +default (when \sphinxstylestrong{iprop\_enable} is true) is to bind to the wildcard +address at the port specified in \sphinxstylestrong{iprop\_port}. New in release +1.15. + +\item[{\sphinxstylestrong{iprop\_port}}] \leavevmode +\sphinxAtStartPar +(Port number.) Specifies the port number to be used for +incremental propagation. When \sphinxstylestrong{iprop\_enable} is true, this +relation is required in the replica KDC configuration file, and +this relation or \sphinxstylestrong{iprop\_listen} is required in the primary +configuration file, as there is no default port number. Port +numbers specified in \sphinxstylestrong{iprop\_listen} entries will override this +port number for the {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} daemon. + +\item[{\sphinxstylestrong{iprop\_resync\_timeout}}] \leavevmode +\sphinxAtStartPar +(Delta time string.) Specifies the amount of time to wait for a +full propagation to complete. This is optional in configuration +files, and is used by replica KDCs only. The default value is 5 +minutes (\sphinxcode{\sphinxupquote{5m}}). New in release 1.11. + +\item[{\sphinxstylestrong{iprop\_logfile}}] \leavevmode +\sphinxAtStartPar +(File name.) Specifies where the update log file for the realm +database is to be stored. The default is to use the +\sphinxstylestrong{database\_name} entry from the realms section of the krb5 config +file, with \sphinxcode{\sphinxupquote{.ulog}} appended. (NOTE: If \sphinxstylestrong{database\_name} isn’t +specified in the realms section, perhaps because the LDAP database +back end is being used, or the file name is specified in the +{[}dbmodules{]} section, then the hard\sphinxhyphen{}coded default for +\sphinxstylestrong{database\_name} is used. Determination of the \sphinxstylestrong{iprop\_logfile} +default value will not use values from the {[}dbmodules{]} section.) + +\item[{\sphinxstylestrong{kadmind\_listen}}] \leavevmode +\sphinxAtStartPar +(Whitespace\sphinxhyphen{} or comma\sphinxhyphen{}separated list.) Specifies the kadmin RPC +listening addresses and/or ports for the {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} daemon. +Each entry may be an interface address, a port number, or an +address and port number separated by a colon. If the address +contains colons, enclose it in square brackets. If no address is +specified, the wildcard address is used. If kadmind fails to bind +to any of the specified addresses, it will fail to start. The +default is to bind to the wildcard address at the port specified +in \sphinxstylestrong{kadmind\_port}, or the standard kadmin port (749). New in +release 1.15. + +\item[{\sphinxstylestrong{kadmind\_port}}] \leavevmode +\sphinxAtStartPar +(Port number.) Specifies the port on which the {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} +daemon is to listen for this realm. Port numbers specified in +\sphinxstylestrong{kadmind\_listen} entries will override this port number. The +assigned port for kadmind is 749, which is used by default. + +\item[{\sphinxstylestrong{key\_stash\_file}}] \leavevmode +\sphinxAtStartPar +(String.) Specifies the location where the master key has been +stored (via kdb5\_util stash). The default is {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/.k5.REALM}}, where \sphinxstyleemphasis{REALM} is the Kerberos realm. + +\item[{\sphinxstylestrong{kdc\_listen}}] \leavevmode +\sphinxAtStartPar +(Whitespace\sphinxhyphen{} or comma\sphinxhyphen{}separated list.) Specifies the UDP +listening addresses and/or ports for the {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} daemon. +Each entry may be an interface address, a port number, or an +address and port number separated by a colon. If the address +contains colons, enclose it in square brackets. If no address is +specified, the wildcard address is used. If no port is specified, +the standard port (88) is used. If the KDC daemon fails to bind +to any of the specified addresses, it will fail to start. The +default is to bind to the wildcard address on the standard port. +New in release 1.15. + +\item[{\sphinxstylestrong{kdc\_ports}}] \leavevmode +\sphinxAtStartPar +(Whitespace\sphinxhyphen{} or comma\sphinxhyphen{}separated list, deprecated.) Prior to +release 1.15, this relation lists the ports for the +{\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} daemon to listen on for UDP requests. In +release 1.15 and later, it has the same meaning as \sphinxstylestrong{kdc\_listen} +if that relation is not defined. + +\item[{\sphinxstylestrong{kdc\_tcp\_listen}}] \leavevmode +\sphinxAtStartPar +(Whitespace\sphinxhyphen{} or comma\sphinxhyphen{}separated list.) Specifies the TCP +listening addresses and/or ports for the {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} daemon. +Each entry may be an interface address, a port number, or an +address and port number separated by a colon. If the address +contains colons, enclose it in square brackets. If no address is +specified, the wildcard address is used. If no port is specified, +the standard port (88) is used. To disable listening on TCP, set +this relation to the empty string with \sphinxcode{\sphinxupquote{kdc\_tcp\_listen = ""}}. +If the KDC daemon fails to bind to any of the specified addresses, +it will fail to start. The default is to bind to the wildcard +address on the standard port. New in release 1.15. + +\item[{\sphinxstylestrong{kdc\_tcp\_ports}}] \leavevmode +\sphinxAtStartPar +(Whitespace\sphinxhyphen{} or comma\sphinxhyphen{}separated list, deprecated.) Prior to +release 1.15, this relation lists the ports for the +{\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} daemon to listen on for UDP requests. In +release 1.15 and later, it has the same meaning as +\sphinxstylestrong{kdc\_tcp\_listen} if that relation is not defined. + +\item[{\sphinxstylestrong{kpasswd\_listen}}] \leavevmode +\sphinxAtStartPar +(Comma\sphinxhyphen{}separated list.) Specifies the kpasswd listening addresses +and/or ports for the {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} daemon. Each entry may be +an interface address, a port number, or an address and port number +separated by a colon. If the address contains colons, enclose it +in square brackets. If no address is specified, the wildcard +address is used. If kadmind fails to bind to any of the specified +addresses, it will fail to start. The default is to bind to the +wildcard address at the port specified in \sphinxstylestrong{kpasswd\_port}, or the +standard kpasswd port (464). New in release 1.15. + +\item[{\sphinxstylestrong{kpasswd\_port}}] \leavevmode +\sphinxAtStartPar +(Port number.) Specifies the port on which the {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} +daemon is to listen for password change requests for this realm. +Port numbers specified in \sphinxstylestrong{kpasswd\_listen} entries will override +this port number. The assigned port for password change requests +is 464, which is used by default. + +\item[{\sphinxstylestrong{master\_key\_name}}] \leavevmode +\sphinxAtStartPar +(String.) Specifies the name of the principal associated with the +master key. The default is \sphinxcode{\sphinxupquote{K/M}}. + +\item[{\sphinxstylestrong{master\_key\_type}}] \leavevmode +\sphinxAtStartPar +(Key type string.) Specifies the master key’s key type. The +default value for this is \sphinxcode{\sphinxupquote{aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96}}. For a list of all possible +values, see {\hyperref[\detokenize{admin/conf_files/kdc_conf:encryption-types}]{\sphinxcrossref{\DUrole{std,std-ref}{Encryption types}}}}. + +\item[{\sphinxstylestrong{max\_life}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} string.) Specifies the maximum time period for +which a ticket may be valid in this realm. The default value is +24 hours. + +\item[{\sphinxstylestrong{max\_renewable\_life}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} string.) Specifies the maximum time period +during which a valid ticket may be renewed in this realm. +The default value is 0. + +\item[{\sphinxstylestrong{no\_host\_referral}}] \leavevmode +\sphinxAtStartPar +(Whitespace\sphinxhyphen{} or comma\sphinxhyphen{}separated list.) Lists services to block +from getting host\sphinxhyphen{}based referral processing, even if the client +marks the server principal as host\sphinxhyphen{}based or the service is also +listed in \sphinxstylestrong{host\_based\_services}. \sphinxcode{\sphinxupquote{no\_host\_referral = *}} will +disable referral processing altogether. + +\item[{\sphinxstylestrong{reject\_bad\_transit}}] \leavevmode +\sphinxAtStartPar +(Boolean value.) If set to true, the KDC will check the list of +transited realms for cross\sphinxhyphen{}realm tickets against the transit path +computed from the realm names and the capaths section of its +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} file; if the path in the ticket to be issued +contains any realms not in the computed path, the ticket will not +be issued, and an error will be returned to the client instead. +If this value is set to false, such tickets will be issued +anyways, and it will be left up to the application server to +validate the realm transit path. + +\sphinxAtStartPar +If the disable\sphinxhyphen{}transited\sphinxhyphen{}check flag is set in the incoming +request, this check is not performed at all. Having the +\sphinxstylestrong{reject\_bad\_transit} option will cause such ticket requests to +be rejected always. + +\sphinxAtStartPar +This transit path checking and config file option currently apply +only to TGS requests. + +\sphinxAtStartPar +The default value is true. + +\item[{\sphinxstylestrong{restrict\_anonymous\_to\_tgt}}] \leavevmode +\sphinxAtStartPar +(Boolean value.) If set to true, the KDC will reject ticket +requests from anonymous principals to service principals other +than the realm’s ticket\sphinxhyphen{}granting service. This option allows +anonymous PKINIT to be enabled for use as FAST armor tickets +without allowing anonymous authentication to services. The +default value is false. New in release 1.9. + +\item[{\sphinxstylestrong{spake\_preauth\_indicator}}] \leavevmode +\sphinxAtStartPar +(String.) Specifies an authentication indicator value that the +KDC asserts into tickets obtained using SPAKE pre\sphinxhyphen{}authentication. +The default is not to add any indicators. This option may be +specified multiple times. New in release 1.17. + +\item[{\sphinxstylestrong{supported\_enctypes}}] \leavevmode +\sphinxAtStartPar +(List of \sphinxstyleemphasis{key}:\sphinxstyleemphasis{salt} strings.) Specifies the default key/salt +combinations of principals for this realm. Any principals created +through {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} will have keys of these types. The +default value for this tag is \sphinxcode{\sphinxupquote{aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96:normal aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96:normal}}. For lists of +possible values, see {\hyperref[\detokenize{admin/conf_files/kdc_conf:keysalt-lists}]{\sphinxcrossref{\DUrole{std,std-ref}{Keysalt lists}}}}. + +\end{description} + + +\paragraph{{[}dbdefaults{]}} +\label{\detokenize{admin/conf_files/kdc_conf:dbdefaults}}\label{\detokenize{admin/conf_files/kdc_conf:id2}} +\sphinxAtStartPar +The {[}dbdefaults{]} section specifies default values for some database +parameters, to be used if the {[}dbmodules{]} subsection does not contain +a relation for the tag. See the {\hyperref[\detokenize{admin/conf_files/kdc_conf:dbmodules}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}dbmodules{]}}}}} section for the +definitions of these relations. +\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ldap\_kerberos\_container\_dn} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ldap\_kdc\_dn} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ldap\_kdc\_sasl\_authcid} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ldap\_kdc\_sasl\_authzid} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ldap\_kdc\_sasl\_mech} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ldap\_kdc\_sasl\_realm} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ldap\_kadmind\_dn} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ldap\_kadmind\_sasl\_authcid} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ldap\_kadmind\_sasl\_authzid} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ldap\_kadmind\_sasl\_mech} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ldap\_kadmind\_sasl\_realm} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ldap\_service\_password\_file} + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ldap\_conns\_per\_server} + +\end{itemize} + + +\paragraph{{[}dbmodules{]}} +\label{\detokenize{admin/conf_files/kdc_conf:dbmodules}}\label{\detokenize{admin/conf_files/kdc_conf:id3}} +\sphinxAtStartPar +The {[}dbmodules{]} section contains parameters used by the KDC database +library and database modules. Each tag in the {[}dbmodules{]} section is +the name of a Kerberos realm or a section name specified by a realm’s +\sphinxstylestrong{database\_module} parameter. The following example shows how to +define one database parameter for the ATHENA.MIT.EDU realm: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{dbmodules}\PYG{p}{]} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{disable\PYGZus{}last\PYGZus{}success} \PYG{o}{=} \PYG{n}{true} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The following tags may be specified in a {[}dbmodules{]} subsection: +\begin{description} +\item[{\sphinxstylestrong{database\_name}}] \leavevmode +\sphinxAtStartPar +This DB2\sphinxhyphen{}specific tag indicates the location of the database in +the filesystem. The default is {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/principal}}. + +\item[{\sphinxstylestrong{db\_library}}] \leavevmode +\sphinxAtStartPar +This tag indicates the name of the loadable database module. The +value should be \sphinxcode{\sphinxupquote{db2}} for the DB2 module, \sphinxcode{\sphinxupquote{klmdb}} for the LMDB +module, or \sphinxcode{\sphinxupquote{kldap}} for the LDAP module. + +\item[{\sphinxstylestrong{disable\_last\_success}}] \leavevmode +\sphinxAtStartPar +If set to \sphinxcode{\sphinxupquote{true}}, suppresses KDC updates to the “Last successful +authentication” field of principal entries requiring +preauthentication. Setting this flag may improve performance. +(Principal entries which do not require preauthentication never +update the “Last successful authentication” field.). First +introduced in release 1.9. + +\item[{\sphinxstylestrong{disable\_lockout}}] \leavevmode +\sphinxAtStartPar +If set to \sphinxcode{\sphinxupquote{true}}, suppresses KDC updates to the “Last failed +authentication” and “Failed password attempts” fields of principal +entries requiring preauthentication. Setting this flag may +improve performance, but also disables account lockout. First +introduced in release 1.9. + +\item[{\sphinxstylestrong{ldap\_conns\_per\_server}}] \leavevmode +\sphinxAtStartPar +This LDAP\sphinxhyphen{}specific tag indicates the number of connections to be +maintained per LDAP server. + +\item[{\sphinxstylestrong{ldap\_kdc\_dn} and \sphinxstylestrong{ldap\_kadmind\_dn}}] \leavevmode +\sphinxAtStartPar +These LDAP\sphinxhyphen{}specific tags indicate the default DN for binding to +the LDAP server. The {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} daemon uses +\sphinxstylestrong{ldap\_kdc\_dn}, while the {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} daemon and other +administrative programs use \sphinxstylestrong{ldap\_kadmind\_dn}. The kadmind DN +must have the rights to read and write the Kerberos data in the +LDAP database. The KDC DN must have the same rights, unless +\sphinxstylestrong{disable\_lockout} and \sphinxstylestrong{disable\_last\_success} are true, in +which case it only needs to have rights to read the Kerberos data. +These tags are ignored if a SASL mechanism is set with +\sphinxstylestrong{ldap\_kdc\_sasl\_mech} or \sphinxstylestrong{ldap\_kadmind\_sasl\_mech}. + +\item[{\sphinxstylestrong{ldap\_kdc\_sasl\_mech} and \sphinxstylestrong{ldap\_kadmind\_sasl\_mech}}] \leavevmode +\sphinxAtStartPar +These LDAP\sphinxhyphen{}specific tags specify the SASL mechanism (such as +\sphinxcode{\sphinxupquote{EXTERNAL}}) to use when binding to the LDAP server. New in +release 1.13. + +\item[{\sphinxstylestrong{ldap\_kdc\_sasl\_authcid} and \sphinxstylestrong{ldap\_kadmind\_sasl\_authcid}}] \leavevmode +\sphinxAtStartPar +These LDAP\sphinxhyphen{}specific tags specify the SASL authentication identity +to use when binding to the LDAP server. Not all SASL mechanisms +require an authentication identity. If the SASL mechanism +requires a secret (such as the password for \sphinxcode{\sphinxupquote{DIGEST\sphinxhyphen{}MD5}}), these +tags also determine the name within the +\sphinxstylestrong{ldap\_service\_password\_file} where the secret is stashed. New +in release 1.13. + +\item[{\sphinxstylestrong{ldap\_kdc\_sasl\_authzid} and \sphinxstylestrong{ldap\_kadmind\_sasl\_authzid}}] \leavevmode +\sphinxAtStartPar +These LDAP\sphinxhyphen{}specific tags specify the SASL authorization identity +to use when binding to the LDAP server. In most circumstances +they do not need to be specified. New in release 1.13. + +\item[{\sphinxstylestrong{ldap\_kdc\_sasl\_realm} and \sphinxstylestrong{ldap\_kadmind\_sasl\_realm}}] \leavevmode +\sphinxAtStartPar +These LDAP\sphinxhyphen{}specific tags specify the SASL realm to use when +binding to the LDAP server. In most circumstances they do not +need to be set. New in release 1.13. + +\item[{\sphinxstylestrong{ldap\_kerberos\_container\_dn}}] \leavevmode +\sphinxAtStartPar +This LDAP\sphinxhyphen{}specific tag indicates the DN of the container object +where the realm objects will be located. + +\item[{\sphinxstylestrong{ldap\_servers}}] \leavevmode +\sphinxAtStartPar +This LDAP\sphinxhyphen{}specific tag indicates the list of LDAP servers that the +Kerberos servers can connect to. The list of LDAP servers is +whitespace\sphinxhyphen{}separated. The LDAP server is specified by a LDAP URI. +It is recommended to use \sphinxcode{\sphinxupquote{ldapi:}} or \sphinxcode{\sphinxupquote{ldaps:}} URLs to connect +to the LDAP server. + +\item[{\sphinxstylestrong{ldap\_service\_password\_file}}] \leavevmode +\sphinxAtStartPar +This LDAP\sphinxhyphen{}specific tag indicates the file containing the stashed +passwords (created by \sphinxcode{\sphinxupquote{kdb5\_ldap\_util stashsrvpw}}) for the +\sphinxstylestrong{ldap\_kdc\_dn} and \sphinxstylestrong{ldap\_kadmind\_dn} objects, or for the +\sphinxstylestrong{ldap\_kdc\_sasl\_authcid} or \sphinxstylestrong{ldap\_kadmind\_sasl\_authcid} names +for SASL authentication. This file must be kept secure. + +\item[{\sphinxstylestrong{mapsize}}] \leavevmode +\sphinxAtStartPar +This LMDB\sphinxhyphen{}specific tag indicates the maximum size of the two +database environments in megabytes. The default value is 128. +Increase this value to address “Environment mapsize limit reached” +errors. New in release 1.17. + +\item[{\sphinxstylestrong{max\_readers}}] \leavevmode +\sphinxAtStartPar +This LMDB\sphinxhyphen{}specific tag indicates the maximum number of concurrent +reading processes for the databases. The default value is 128. +New in release 1.17. + +\item[{\sphinxstylestrong{nosync}}] \leavevmode +\sphinxAtStartPar +This LMDB\sphinxhyphen{}specific tag can be set to improve the throughput of +kadmind and other administrative agents, at the expense of +durability (recent database changes may not survive a power outage +or other sudden reboot). It does not affect the throughput of the +KDC. The default value is false. New in release 1.17. + +\item[{\sphinxstylestrong{unlockiter}}] \leavevmode +\sphinxAtStartPar +If set to \sphinxcode{\sphinxupquote{true}}, this DB2\sphinxhyphen{}specific tag causes iteration +operations to release the database lock while processing each +principal. Setting this flag to \sphinxcode{\sphinxupquote{true}} can prevent extended +blocking of KDC or kadmin operations when dumps of large databases +are in progress. First introduced in release 1.13. + +\end{description} + +\sphinxAtStartPar +The following tag may be specified directly in the {[}dbmodules{]} +section to control where database modules are loaded from: +\begin{description} +\item[{\sphinxstylestrong{db\_module\_dir}}] \leavevmode +\sphinxAtStartPar +This tag controls where the plugin system looks for database +modules. The value should be an absolute path. + +\end{description} + + +\paragraph{{[}logging{]}} +\label{\detokenize{admin/conf_files/kdc_conf:logging}}\label{\detokenize{admin/conf_files/kdc_conf:id4}} +\sphinxAtStartPar +The {[}logging{]} section indicates how {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} and +{\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} perform logging. It may contain the following +relations: +\begin{description} +\item[{\sphinxstylestrong{admin\_server}}] \leavevmode +\sphinxAtStartPar +Specifies how {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} performs logging. + +\item[{\sphinxstylestrong{kdc}}] \leavevmode +\sphinxAtStartPar +Specifies how {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} performs logging. + +\item[{\sphinxstylestrong{default}}] \leavevmode +\sphinxAtStartPar +Specifies how either daemon performs logging in the absence of +relations specific to the daemon. + +\item[{\sphinxstylestrong{debug}}] \leavevmode +\sphinxAtStartPar +(Boolean value.) Specifies whether debugging messages are +included in log outputs other than SYSLOG. Debugging messages are +always included in the system log output because syslog performs +its own priority filtering. The default value is false. New in +release 1.15. + +\end{description} + +\sphinxAtStartPar +Logging specifications may have the following forms: +\begin{description} +\item[{\sphinxstylestrong{FILE=}\sphinxstyleemphasis{filename} or \sphinxstylestrong{FILE:}\sphinxstyleemphasis{filename}}] \leavevmode +\sphinxAtStartPar +This value causes the daemon’s logging messages to go to the +\sphinxstyleemphasis{filename}. If the \sphinxcode{\sphinxupquote{=}} form is used, the file is overwritten. +If the \sphinxcode{\sphinxupquote{:}} form is used, the file is appended to. + +\item[{\sphinxstylestrong{STDERR}}] \leavevmode +\sphinxAtStartPar +This value causes the daemon’s logging messages to go to its +standard error stream. + +\item[{\sphinxstylestrong{CONSOLE}}] \leavevmode +\sphinxAtStartPar +This value causes the daemon’s logging messages to go to the +console, if the system supports it. + +\item[{\sphinxstylestrong{DEVICE=}\sphinxstyleemphasis{\textless{}devicename\textgreater{}}}] \leavevmode +\sphinxAtStartPar +This causes the daemon’s logging messages to go to the specified +device. + +\item[{\sphinxstylestrong{SYSLOG}{[}\sphinxstylestrong{:}\sphinxstyleemphasis{severity}{[}\sphinxstylestrong{:}\sphinxstyleemphasis{facility}{]}{]}}] \leavevmode +\sphinxAtStartPar +This causes the daemon’s logging messages to go to the system log. + +\sphinxAtStartPar +For backward compatibility, a severity argument may be specified, +and must be specified in order to specify a facility. This +argument will be ignored. + +\sphinxAtStartPar +The facility argument specifies the facility under which the +messages are logged. This may be any of the following facilities +supported by the syslog(3) call minus the LOG\_ prefix: \sphinxstylestrong{KERN}, +\sphinxstylestrong{USER}, \sphinxstylestrong{MAIL}, \sphinxstylestrong{DAEMON}, \sphinxstylestrong{AUTH}, \sphinxstylestrong{LPR}, \sphinxstylestrong{NEWS}, +\sphinxstylestrong{UUCP}, \sphinxstylestrong{CRON}, and \sphinxstylestrong{LOCAL0} through \sphinxstylestrong{LOCAL7}. If no +facility is specified, the default is \sphinxstylestrong{AUTH}. + +\end{description} + +\sphinxAtStartPar +In the following example, the logging messages from the KDC will go to +the console and to the system log under the facility LOG\_DAEMON, and +the logging messages from the administrative server will be appended +to the file \sphinxcode{\sphinxupquote{/var/adm/kadmin.log}} and sent to the device +\sphinxcode{\sphinxupquote{/dev/tty04}}. + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{logging}\PYG{p}{]} + \PYG{n}{kdc} \PYG{o}{=} \PYG{n}{CONSOLE} + \PYG{n}{kdc} \PYG{o}{=} \PYG{n}{SYSLOG}\PYG{p}{:}\PYG{n}{INFO}\PYG{p}{:}\PYG{n}{DAEMON} + \PYG{n}{admin\PYGZus{}server} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{var}\PYG{o}{/}\PYG{n}{adm}\PYG{o}{/}\PYG{n}{kadmin}\PYG{o}{.}\PYG{n}{log} + \PYG{n}{admin\PYGZus{}server} \PYG{o}{=} \PYG{n}{DEVICE}\PYG{o}{=}\PYG{o}{/}\PYG{n}{dev}\PYG{o}{/}\PYG{n}{tty04} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If no logging specification is given, the default is to use syslog. +To disable logging entirely, specify \sphinxcode{\sphinxupquote{default = DEVICE=/dev/null}}. + + +\paragraph{{[}otp{]}} +\label{\detokenize{admin/conf_files/kdc_conf:otp}}\label{\detokenize{admin/conf_files/kdc_conf:id5}} +\sphinxAtStartPar +Each subsection of {[}otp{]} is the name of an OTP token type. The tags +within the subsection define the configuration required to forward a +One Time Password request to a RADIUS server. + +\sphinxAtStartPar +For each token type, the following tags may be specified: +\begin{description} +\item[{\sphinxstylestrong{server}}] \leavevmode +\sphinxAtStartPar +This is the server to send the RADIUS request to. It can be a +hostname with optional port, an ip address with optional port, or +a Unix domain socket address. The default is +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/\textless{}name\textgreater{}.socket}}. + +\item[{\sphinxstylestrong{secret}}] \leavevmode +\sphinxAtStartPar +This tag indicates a filename (which may be relative to {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}) +containing the secret used to encrypt the RADIUS packets. The +secret should appear in the first line of the file by itself; +leading and trailing whitespace on the line will be removed. If +the value of \sphinxstylestrong{server} is a Unix domain socket address, this tag +is optional, and an empty secret will be used if it is not +specified. Otherwise, this tag is required. + +\item[{\sphinxstylestrong{timeout}}] \leavevmode +\sphinxAtStartPar +An integer which specifies the time in seconds during which the +KDC should attempt to contact the RADIUS server. This tag is the +total time across all retries and should be less than the time +which an OTP value remains valid for. The default is 5 seconds. + +\item[{\sphinxstylestrong{retries}}] \leavevmode +\sphinxAtStartPar +This tag specifies the number of retries to make to the RADIUS +server. The default is 3 retries (4 tries). + +\item[{\sphinxstylestrong{strip\_realm}}] \leavevmode +\sphinxAtStartPar +If this tag is \sphinxcode{\sphinxupquote{true}}, the principal without the realm will be +passed to the RADIUS server. Otherwise, the realm will be +included. The default value is \sphinxcode{\sphinxupquote{true}}. + +\item[{\sphinxstylestrong{indicator}}] \leavevmode +\sphinxAtStartPar +This tag specifies an authentication indicator to be included in +the ticket if this token type is used to authenticate. This +option may be specified multiple times. (New in release 1.14.) + +\end{description} + +\sphinxAtStartPar +In the following example, requests are sent to a remote server via UDP: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +[otp] + MyRemoteTokenType = \PYGZob{} + server = radius.mydomain.com:1812 + secret = SEmfiajf42\PYGZdl{} + timeout = 15 + retries = 5 + strip\PYGZus{}realm = true + \PYGZcb{} +\end{sphinxVerbatim} + +\sphinxAtStartPar +An implicit default token type named \sphinxcode{\sphinxupquote{DEFAULT}} is defined for when +the per\sphinxhyphen{}principal configuration does not specify a token type. Its +configuration is shown below. You may override this token type to +something applicable for your situation: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{otp}\PYG{p}{]} + \PYG{n}{DEFAULT} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{strip\PYGZus{}realm} \PYG{o}{=} \PYG{n}{false} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + + +\subsubsection{PKINIT options} +\label{\detokenize{admin/conf_files/kdc_conf:pkinit-options}} +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The following are pkinit\sphinxhyphen{}specific options. These values may +be specified in {[}kdcdefaults{]} as global defaults, or within +a realm\sphinxhyphen{}specific subsection of {[}realms{]}. Also note that a +realm\sphinxhyphen{}specific value over\sphinxhyphen{}rides, does not add to, a generic +{[}kdcdefaults{]} specification. The search order is: +\end{sphinxadmonition} +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +realm\sphinxhyphen{}specific subsection of {[}realms{]}: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{realms}\PYG{p}{]} + \PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{pkinit\PYGZus{}anchors} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{usr}\PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com}\PYG{o}{.}\PYG{n}{crt} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\item {} +\sphinxAtStartPar +generic value in the {[}kdcdefaults{]} section: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{kdcdefaults}\PYG{p}{]} + \PYG{n}{pkinit\PYGZus{}anchors} \PYG{o}{=} \PYG{n}{DIR}\PYG{p}{:}\PYG{o}{/}\PYG{n}{usr}\PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{generic\PYGZus{}trusted\PYGZus{}cas}\PYG{o}{/} +\end{sphinxVerbatim} + +\end{enumerate} + +\sphinxAtStartPar +For information about the syntax of some of these options, see +{\hyperref[\detokenize{admin/conf_files/krb5_conf:pkinit-identity}]{\sphinxcrossref{\DUrole{std,std-ref}{Specifying PKINIT identity information}}}} in +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}. +\begin{description} +\item[{\sphinxstylestrong{pkinit\_anchors}}] \leavevmode +\sphinxAtStartPar +Specifies the location of trusted anchor (root) certificates which +the KDC trusts to sign client certificates. This option is +required if pkinit is to be supported by the KDC. This option may +be specified multiple times. + +\item[{\sphinxstylestrong{pkinit\_dh\_min\_bits}}] \leavevmode +\sphinxAtStartPar +Specifies the minimum number of bits the KDC is willing to accept +for a client’s Diffie\sphinxhyphen{}Hellman key. The default is 2048. + +\item[{\sphinxstylestrong{pkinit\_allow\_upn}}] \leavevmode +\sphinxAtStartPar +Specifies that the KDC is willing to accept client certificates +with the Microsoft UserPrincipalName (UPN) Subject Alternative +Name (SAN). This means the KDC accepts the binding of the UPN in +the certificate to the Kerberos principal name. The default value +is false. + +\sphinxAtStartPar +Without this option, the KDC will only accept certificates with +the id\sphinxhyphen{}pkinit\sphinxhyphen{}san as defined in \index{RFC@\spxentry{RFC}!RFC 4556@\spxentry{RFC 4556}}\sphinxhref{https://tools.ietf.org/html/rfc4556.html}{\sphinxstylestrong{RFC 4556}}. There is currently +no option to disable SAN checking in the KDC. + +\item[{\sphinxstylestrong{pkinit\_eku\_checking}}] \leavevmode +\sphinxAtStartPar +This option specifies what Extended Key Usage (EKU) values the KDC +is willing to accept in client certificates. The values +recognized in the kdc.conf file are: +\begin{description} +\item[{\sphinxstylestrong{kpClientAuth}}] \leavevmode +\sphinxAtStartPar +This is the default value and specifies that client +certificates must have the id\sphinxhyphen{}pkinit\sphinxhyphen{}KPClientAuth EKU as +defined in \index{RFC@\spxentry{RFC}!RFC 4556@\spxentry{RFC 4556}}\sphinxhref{https://tools.ietf.org/html/rfc4556.html}{\sphinxstylestrong{RFC 4556}}. + +\item[{\sphinxstylestrong{scLogin}}] \leavevmode +\sphinxAtStartPar +If scLogin is specified, client certificates with the +Microsoft Smart Card Login EKU (id\sphinxhyphen{}ms\sphinxhyphen{}kp\sphinxhyphen{}sc\sphinxhyphen{}logon) will be +accepted. + +\item[{\sphinxstylestrong{none}}] \leavevmode +\sphinxAtStartPar +If none is specified, then client certificates will not be +checked to verify they have an acceptable EKU. The use of +this option is not recommended. + +\end{description} + +\item[{\sphinxstylestrong{pkinit\_identity}}] \leavevmode +\sphinxAtStartPar +Specifies the location of the KDC’s X.509 identity information. +This option is required if pkinit is to be supported by the KDC. + +\item[{\sphinxstylestrong{pkinit\_indicator}}] \leavevmode +\sphinxAtStartPar +Specifies an authentication indicator to include in the ticket if +pkinit is used to authenticate. This option may be specified +multiple times. (New in release 1.14.) + +\item[{\sphinxstylestrong{pkinit\_pool}}] \leavevmode +\sphinxAtStartPar +Specifies the location of intermediate certificates which may be +used by the KDC to complete the trust chain between a client’s +certificate and a trusted anchor. This option may be specified +multiple times. + +\item[{\sphinxstylestrong{pkinit\_revoke}}] \leavevmode +\sphinxAtStartPar +Specifies the location of Certificate Revocation List (CRL) +information to be used by the KDC when verifying the validity of +client certificates. This option may be specified multiple times. + +\item[{\sphinxstylestrong{pkinit\_require\_crl\_checking}}] \leavevmode +\sphinxAtStartPar +The default certificate verification process will always check the +available revocation information to see if a certificate has been +revoked. If a match is found for the certificate in a CRL, +verification fails. If the certificate being verified is not +listed in a CRL, or there is no CRL present for its issuing CA, +and \sphinxstylestrong{pkinit\_require\_crl\_checking} is false, then verification +succeeds. + +\sphinxAtStartPar +However, if \sphinxstylestrong{pkinit\_require\_crl\_checking} is true and there is +no CRL information available for the issuing CA, then verification +fails. + +\sphinxAtStartPar +\sphinxstylestrong{pkinit\_require\_crl\_checking} should be set to true if the +policy is such that up\sphinxhyphen{}to\sphinxhyphen{}date CRLs must be present for every CA. + +\item[{\sphinxstylestrong{pkinit\_require\_freshness}}] \leavevmode +\sphinxAtStartPar +Specifies whether to require clients to include a freshness token +in PKINIT requests. The default value is false. (New in release +1.17.) + +\end{description} + + +\subsubsection{Encryption types} +\label{\detokenize{admin/conf_files/kdc_conf:encryption-types}}\label{\detokenize{admin/conf_files/kdc_conf:id6}} +\sphinxAtStartPar +Any tag in the configuration files which requires a list of encryption +types can be set to some combination of the following strings. +Encryption types marked as “weak” and “deprecated” are available for +compatibility but not recommended for use. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +des3\sphinxhyphen{}cbc\sphinxhyphen{}raw +& +\sphinxAtStartPar +Triple DES cbc mode raw (weak) +\\ +\hline +\sphinxAtStartPar +des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1 des3\sphinxhyphen{}hmac\sphinxhyphen{}sha1 des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1\sphinxhyphen{}kd +& +\sphinxAtStartPar +Triple DES cbc mode with HMAC/sha1 (deprecated) +\\ +\hline +\sphinxAtStartPar +aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96 aes256\sphinxhyphen{}cts aes256\sphinxhyphen{}sha1 +& +\sphinxAtStartPar +AES\sphinxhyphen{}256 CTS mode with 96\sphinxhyphen{}bit SHA\sphinxhyphen{}1 HMAC +\\ +\hline +\sphinxAtStartPar +aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96 aes128\sphinxhyphen{}cts aes128\sphinxhyphen{}sha1 +& +\sphinxAtStartPar +AES\sphinxhyphen{}128 CTS mode with 96\sphinxhyphen{}bit SHA\sphinxhyphen{}1 HMAC +\\ +\hline +\sphinxAtStartPar +aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha384\sphinxhyphen{}192 aes256\sphinxhyphen{}sha2 +& +\sphinxAtStartPar +AES\sphinxhyphen{}256 CTS mode with 192\sphinxhyphen{}bit SHA\sphinxhyphen{}384 HMAC +\\ +\hline +\sphinxAtStartPar +aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha256\sphinxhyphen{}128 aes128\sphinxhyphen{}sha2 +& +\sphinxAtStartPar +AES\sphinxhyphen{}128 CTS mode with 128\sphinxhyphen{}bit SHA\sphinxhyphen{}256 HMAC +\\ +\hline +\sphinxAtStartPar +arcfour\sphinxhyphen{}hmac rc4\sphinxhyphen{}hmac arcfour\sphinxhyphen{}hmac\sphinxhyphen{}md5 +& +\sphinxAtStartPar +RC4 with HMAC/MD5 (deprecated) +\\ +\hline +\sphinxAtStartPar +arcfour\sphinxhyphen{}hmac\sphinxhyphen{}exp rc4\sphinxhyphen{}hmac\sphinxhyphen{}exp arcfour\sphinxhyphen{}hmac\sphinxhyphen{}md5\sphinxhyphen{}exp +& +\sphinxAtStartPar +Exportable RC4 with HMAC/MD5 (weak) +\\ +\hline +\sphinxAtStartPar +camellia256\sphinxhyphen{}cts\sphinxhyphen{}cmac camellia256\sphinxhyphen{}cts +& +\sphinxAtStartPar +Camellia\sphinxhyphen{}256 CTS mode with CMAC +\\ +\hline +\sphinxAtStartPar +camellia128\sphinxhyphen{}cts\sphinxhyphen{}cmac camellia128\sphinxhyphen{}cts +& +\sphinxAtStartPar +Camellia\sphinxhyphen{}128 CTS mode with CMAC +\\ +\hline +\sphinxAtStartPar +des3 +& +\sphinxAtStartPar +The triple DES family: des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1 +\\ +\hline +\sphinxAtStartPar +aes +& +\sphinxAtStartPar +The AES family: aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96, aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96, aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha384\sphinxhyphen{}192, and aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha256\sphinxhyphen{}128 +\\ +\hline +\sphinxAtStartPar +rc4 +& +\sphinxAtStartPar +The RC4 family: arcfour\sphinxhyphen{}hmac +\\ +\hline +\sphinxAtStartPar +camellia +& +\sphinxAtStartPar +The Camellia family: camellia256\sphinxhyphen{}cts\sphinxhyphen{}cmac and camellia128\sphinxhyphen{}cts\sphinxhyphen{}cmac +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + +\sphinxAtStartPar +The string \sphinxstylestrong{DEFAULT} can be used to refer to the default set of +types for the variable in question. Types or families can be removed +from the current list by prefixing them with a minus sign (“\sphinxhyphen{}“). +Types or families can be prefixed with a plus sign (“+”) for symmetry; +it has the same meaning as just listing the type or family. For +example, “\sphinxcode{\sphinxupquote{DEFAULT \sphinxhyphen{}rc4}}” would be the default set of encryption +types with RC4 types removed, and “\sphinxcode{\sphinxupquote{des3 DEFAULT}}” would be the +default set of encryption types with triple DES types moved to the +front. + +\sphinxAtStartPar +While \sphinxstylestrong{aes128\sphinxhyphen{}cts} and \sphinxstylestrong{aes256\sphinxhyphen{}cts} are supported for all Kerberos +operations, they are not supported by very old versions of our GSSAPI +implementation (krb5\sphinxhyphen{}1.3.1 and earlier). Services running versions of +krb5 without AES support must not be given keys of these encryption +types in the KDC database. + +\sphinxAtStartPar +The \sphinxstylestrong{aes128\sphinxhyphen{}sha2} and \sphinxstylestrong{aes256\sphinxhyphen{}sha2} encryption types are new in +release 1.15. Services running versions of krb5 without support for +these newer encryption types must not be given keys of these +encryption types in the KDC database. + + +\subsubsection{Keysalt lists} +\label{\detokenize{admin/conf_files/kdc_conf:keysalt-lists}}\label{\detokenize{admin/conf_files/kdc_conf:id7}} +\sphinxAtStartPar +Kerberos keys for users are usually derived from passwords. Kerberos +commands and configuration parameters that affect generation of keys +take lists of enctype\sphinxhyphen{}salttype (“keysalt”) pairs, known as \sphinxstyleemphasis{keysalt +lists}. Each keysalt pair is an enctype name followed by a salttype +name, in the format \sphinxstyleemphasis{enc}:\sphinxstyleemphasis{salt}. Individual keysalt list members are +separated by comma (“,”) characters or space characters. For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin} \PYG{o}{\PYGZhy{}}\PYG{n}{e} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{p}{:}\PYG{n}{normal}\PYG{p}{,}\PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{p}{:}\PYG{n}{normal} +\end{sphinxVerbatim} + +\sphinxAtStartPar +would start up kadmin so that by default it would generate +password\sphinxhyphen{}derived keys for the \sphinxstylestrong{aes256\sphinxhyphen{}cts} and \sphinxstylestrong{aes128\sphinxhyphen{}cts} +encryption types, using a \sphinxstylestrong{normal} salt. + +\sphinxAtStartPar +To ensure that people who happen to pick the same password do not have +the same key, Kerberos 5 incorporates more information into the key +using something called a salt. The supported salt types are as +follows: + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +normal +& +\sphinxAtStartPar +default for Kerberos Version 5 +\\ +\hline +\sphinxAtStartPar +norealm +& +\sphinxAtStartPar +same as the default, without using realm information +\\ +\hline +\sphinxAtStartPar +onlyrealm +& +\sphinxAtStartPar +uses only realm information as the salt +\\ +\hline +\sphinxAtStartPar +special +& +\sphinxAtStartPar +generate a random salt +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{Sample kdc.conf File} +\label{\detokenize{admin/conf_files/kdc_conf:sample-kdc-conf-file}} +\sphinxAtStartPar +Here’s an example of a kdc.conf file: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{kdcdefaults}\PYG{p}{]} + \PYG{n}{kdc\PYGZus{}listen} \PYG{o}{=} \PYG{l+m+mi}{88} + \PYG{n}{kdc\PYGZus{}tcp\PYGZus{}listen} \PYG{o}{=} \PYG{l+m+mi}{88} +\PYG{p}{[}\PYG{n}{realms}\PYG{p}{]} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{kadmind\PYGZus{}port} \PYG{o}{=} \PYG{l+m+mi}{749} + \PYG{n}{max\PYGZus{}life} \PYG{o}{=} \PYG{l+m+mi}{12}\PYG{n}{h} \PYG{l+m+mi}{0}\PYG{n}{m} \PYG{l+m+mi}{0}\PYG{n}{s} + \PYG{n}{max\PYGZus{}renewable\PYGZus{}life} \PYG{o}{=} \PYG{l+m+mi}{7}\PYG{n}{d} \PYG{l+m+mi}{0}\PYG{n}{h} \PYG{l+m+mi}{0}\PYG{n}{m} \PYG{l+m+mi}{0}\PYG{n}{s} + \PYG{n}{master\PYGZus{}key\PYGZus{}type} \PYG{o}{=} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} + \PYG{n}{supported\PYGZus{}enctypes} \PYG{o}{=} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96}\PYG{p}{:}\PYG{n}{normal} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96}\PYG{p}{:}\PYG{n}{normal} + \PYG{n}{database\PYGZus{}module} \PYG{o}{=} \PYG{n}{openldap\PYGZus{}ldapconf} + \PYG{p}{\PYGZcb{}} + +\PYG{p}{[}\PYG{n}{logging}\PYG{p}{]} + \PYG{n}{kdc} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{usr}\PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{var}\PYG{o}{/}\PYG{n}{krb5kdc}\PYG{o}{/}\PYG{n}{kdc}\PYG{o}{.}\PYG{n}{log} + \PYG{n}{admin\PYGZus{}server} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{usr}\PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{var}\PYG{o}{/}\PYG{n}{krb5kdc}\PYG{o}{/}\PYG{n}{kadmin}\PYG{o}{.}\PYG{n}{log} + +\PYG{p}{[}\PYG{n}{dbdefaults}\PYG{p}{]} + \PYG{n}{ldap\PYGZus{}kerberos\PYGZus{}container\PYGZus{}dn} \PYG{o}{=} \PYG{n}{cn}\PYG{o}{=}\PYG{n}{krbcontainer}\PYG{p}{,}\PYG{n}{dc}\PYG{o}{=}\PYG{n}{mit}\PYG{p}{,}\PYG{n}{dc}\PYG{o}{=}\PYG{n}{edu} + +\PYG{p}{[}\PYG{n}{dbmodules}\PYG{p}{]} + \PYG{n}{openldap\PYGZus{}ldapconf} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{db\PYGZus{}library} \PYG{o}{=} \PYG{n}{kldap} + \PYG{n}{disable\PYGZus{}last\PYGZus{}success} \PYG{o}{=} \PYG{n}{true} + \PYG{n}{ldap\PYGZus{}kdc\PYGZus{}dn} \PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=krbadmin,dc=mit,dc=edu}\PYG{l+s+s2}{\PYGZdq{}} + \PYG{c+c1}{\PYGZsh{} this object needs to have read rights on} + \PYG{c+c1}{\PYGZsh{} the realm container and principal subtrees} + \PYG{n}{ldap\PYGZus{}kadmind\PYGZus{}dn} \PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=krbadmin,dc=mit,dc=edu}\PYG{l+s+s2}{\PYGZdq{}} + \PYG{c+c1}{\PYGZsh{} this object needs to have read and write rights on} + \PYG{c+c1}{\PYGZsh{} the realm container and principal subtrees} + \PYG{n}{ldap\PYGZus{}service\PYGZus{}password\PYGZus{}file} \PYG{o}{=} \PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{/}\PYG{n}{service}\PYG{o}{.}\PYG{n}{keyfile} + \PYG{n}{ldap\PYGZus{}servers} \PYG{o}{=} \PYG{n}{ldaps}\PYG{p}{:}\PYG{o}{/}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{n}{ldap\PYGZus{}conns\PYGZus{}per\PYGZus{}server} \PYG{o}{=} \PYG{l+m+mi}{5} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + + +\subsubsection{FILES} +\label{\detokenize{admin/conf_files/kdc_conf:files}} +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/kdc.conf}} + + +\subsubsection{SEE ALSO} +\label{\detokenize{admin/conf_files/kdc_conf:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}, {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}}, {\hyperref[\detokenize{admin/conf_files/kadm5_acl:kadm5-acl-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kadm5.acl}}}} + + +\subsection{kadm5.acl} +\label{\detokenize{admin/conf_files/kadm5_acl:kadm5-acl}}\label{\detokenize{admin/conf_files/kadm5_acl:kadm5-acl-5}}\label{\detokenize{admin/conf_files/kadm5_acl::doc}} + +\subsubsection{DESCRIPTION} +\label{\detokenize{admin/conf_files/kadm5_acl:description}} +\sphinxAtStartPar +The Kerberos {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} daemon uses an Access Control List +(ACL) file to manage access rights to the Kerberos database. +For operations that affect principals, the ACL file also controls +which principals can operate on which other principals. + +\sphinxAtStartPar +The default location of the Kerberos ACL file is +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/kadm5.acl}} unless this is overridden by the \sphinxstyleemphasis{acl\_file} +variable in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. + + +\subsubsection{SYNTAX} +\label{\detokenize{admin/conf_files/kadm5_acl:syntax}} +\sphinxAtStartPar +Empty lines and lines starting with the sharp sign (\sphinxcode{\sphinxupquote{\#}}) are +ignored. Lines containing ACL entries have the format: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{principal} \PYG{n}{permissions} \PYG{p}{[}\PYG{n}{target\PYGZus{}principal} \PYG{p}{[}\PYG{n}{restrictions}\PYG{p}{]} \PYG{p}{]} +\end{sphinxVerbatim} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +Line order in the ACL file is important. The first matching entry +will control access for an actor principal on a target principal. +\end{sphinxadmonition} +\begin{description} +\item[{\sphinxstyleemphasis{principal}}] \leavevmode +\sphinxAtStartPar +(Partially or fully qualified Kerberos principal name.) Specifies +the principal whose permissions are to be set. + +\sphinxAtStartPar +Each component of the name may be wildcarded using the \sphinxcode{\sphinxupquote{*}} +character. + +\item[{\sphinxstyleemphasis{permissions}}] \leavevmode +\sphinxAtStartPar +Specifies what operations may or may not be performed by a +\sphinxstyleemphasis{principal} matching a particular entry. This is a string of one or +more of the following list of characters or their upper\sphinxhyphen{}case +counterparts. If the character is \sphinxstyleemphasis{upper\sphinxhyphen{}case}, then the operation +is disallowed. If the character is \sphinxstyleemphasis{lower\sphinxhyphen{}case}, then the operation +is permitted. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +a +& +\sphinxAtStartPar +{[}Dis{]}allows the addition of principals or policies +\\ +\hline +\sphinxAtStartPar +c +& +\sphinxAtStartPar +{[}Dis{]}allows the changing of passwords for principals +\\ +\hline +\sphinxAtStartPar +d +& +\sphinxAtStartPar +{[}Dis{]}allows the deletion of principals or policies +\\ +\hline +\sphinxAtStartPar +e +& +\sphinxAtStartPar +{[}Dis{]}allows the extraction of principal keys +\\ +\hline +\sphinxAtStartPar +i +& +\sphinxAtStartPar +{[}Dis{]}allows inquiries about principals or policies +\\ +\hline +\sphinxAtStartPar +l +& +\sphinxAtStartPar +{[}Dis{]}allows the listing of all principals or policies +\\ +\hline +\sphinxAtStartPar +m +& +\sphinxAtStartPar +{[}Dis{]}allows the modification of principals or policies +\\ +\hline +\sphinxAtStartPar +p +& +\sphinxAtStartPar +{[}Dis{]}allows the propagation of the principal database (used in {\hyperref[\detokenize{admin/database:incr-db-prop}]{\sphinxcrossref{\DUrole{std,std-ref}{Incremental database propagation}}}}) +\\ +\hline +\sphinxAtStartPar +s +& +\sphinxAtStartPar +{[}Dis{]}allows the explicit setting of the key for a principal +\\ +\hline +\sphinxAtStartPar +x +& +\sphinxAtStartPar +Short for admcilsp. All privileges (except \sphinxcode{\sphinxupquote{e}}) +\\ +\hline +\sphinxAtStartPar +* +& +\sphinxAtStartPar +Same as x. +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + +\end{description} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The \sphinxcode{\sphinxupquote{extract}} privilege is not included in the wildcard +privilege; it must be explicitly assigned. This privilege +allows the user to extract keys from the database, and must be +handled with great care to avoid disclosure of important keys +like those of the kadmin/* or krbtgt/* principals. The +\sphinxstylestrong{lockdown\_keys} principal attribute can be used to prevent +key extraction from specific principals regardless of the +granted privilege. +\end{sphinxadmonition} +\begin{description} +\item[{\sphinxstyleemphasis{target\_principal}}] \leavevmode +\sphinxAtStartPar +(Optional. Partially or fully qualified Kerberos principal name.) +Specifies the principal on which \sphinxstyleemphasis{permissions} may be applied. +Each component of the name may be wildcarded using the \sphinxcode{\sphinxupquote{*}} +character. + +\sphinxAtStartPar +\sphinxstyleemphasis{target\_principal} can also include back\sphinxhyphen{}references to \sphinxstyleemphasis{principal}, +in which \sphinxcode{\sphinxupquote{*number}} matches the corresponding wildcard in +\sphinxstyleemphasis{principal}. + +\item[{\sphinxstyleemphasis{restrictions}}] \leavevmode +\sphinxAtStartPar +(Optional) A string of flags. Allowed restrictions are: +\begin{quote} +\begin{description} +\item[{\{+|\sphinxhyphen{}\}\sphinxstyleemphasis{flagname}}] \leavevmode +\sphinxAtStartPar +flag is forced to the indicated value. The permissible flags +are the same as those for the \sphinxstylestrong{default\_principal\_flags} +variable in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. + +\item[{\sphinxstyleemphasis{\sphinxhyphen{}clearpolicy}}] \leavevmode +\sphinxAtStartPar +policy is forced to be empty. + +\item[{\sphinxstyleemphasis{\sphinxhyphen{}policy pol}}] \leavevmode +\sphinxAtStartPar +policy is forced to be \sphinxstyleemphasis{pol}. + +\item[{\sphinxhyphen{}\{\sphinxstyleemphasis{expire, pwexpire, maxlife, maxrenewlife}\} \sphinxstyleemphasis{time}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{getdate} string) associated value will be forced to +MIN(\sphinxstyleemphasis{time}, requested value). + +\end{description} +\end{quote} + +\sphinxAtStartPar +The above flags act as restrictions on any add or modify operation +which is allowed due to that ACL line. + +\end{description} + +\begin{sphinxadmonition}{warning}{Warning:} +\sphinxAtStartPar +If the kadmind ACL file is modified, the kadmind daemon needs to be +restarted for changes to take effect. +\end{sphinxadmonition} + + +\subsubsection{EXAMPLE} +\label{\detokenize{admin/conf_files/kadm5_acl:example}} +\sphinxAtStartPar +Here is an example of a kadm5.acl file: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{o}{*}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{*} \PYG{c+c1}{\PYGZsh{} line 1} +\PYG{n}{joeadmin}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{n}{ADMCIL} \PYG{c+c1}{\PYGZsh{} line 2} +\PYG{n}{joeadmin}\PYG{o}{/}\PYG{o}{*}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{n}{i} \PYG{o}{*}\PYG{o}{/}\PYG{n}{root}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{c+c1}{\PYGZsh{} line 3} +\PYG{o}{*}\PYG{o}{/}\PYG{n}{root}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{n}{ci} \PYG{o}{*}\PYG{l+m+mi}{1}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{c+c1}{\PYGZsh{} line 4} +\PYG{o}{*}\PYG{o}{/}\PYG{n}{root}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{n}{l} \PYG{o}{*} \PYG{c+c1}{\PYGZsh{} line 5} +\PYG{n}{sms}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{n}{x} \PYG{o}{*} \PYG{o}{\PYGZhy{}}\PYG{n}{maxlife} \PYG{l+m+mi}{9}\PYG{n}{h} \PYG{o}{\PYGZhy{}}\PYG{n}{postdateable} \PYG{c+c1}{\PYGZsh{} line 6} +\end{sphinxVerbatim} + +\sphinxAtStartPar +(line 1) Any principal in the \sphinxcode{\sphinxupquote{ATHENA.MIT.EDU}} realm with an +\sphinxcode{\sphinxupquote{admin}} instance has all administrative privileges except extracting +keys. + +\sphinxAtStartPar +(lines 1\sphinxhyphen{}3) The user \sphinxcode{\sphinxupquote{joeadmin}} has all permissions except +extracting keys with his \sphinxcode{\sphinxupquote{admin}} instance, +\sphinxcode{\sphinxupquote{joeadmin/admin@ATHENA.MIT.EDU}} (matches line 1). He has no +permissions at all with his null instance, \sphinxcode{\sphinxupquote{joeadmin@ATHENA.MIT.EDU}} +(matches line 2). His \sphinxcode{\sphinxupquote{root}} and other non\sphinxhyphen{}\sphinxcode{\sphinxupquote{admin}}, non\sphinxhyphen{}null +instances (e.g., \sphinxcode{\sphinxupquote{extra}} or \sphinxcode{\sphinxupquote{dbadmin}}) have inquire permissions +with any principal that has the instance \sphinxcode{\sphinxupquote{root}} (matches line 3). + +\sphinxAtStartPar +(line 4) Any \sphinxcode{\sphinxupquote{root}} principal in \sphinxcode{\sphinxupquote{ATHENA.MIT.EDU}} can inquire +or change the password of their null instance, but not any other +null instance. (Here, \sphinxcode{\sphinxupquote{*1}} denotes a back\sphinxhyphen{}reference to the +component matching the first wildcard in the actor principal.) + +\sphinxAtStartPar +(line 5) Any \sphinxcode{\sphinxupquote{root}} principal in \sphinxcode{\sphinxupquote{ATHENA.MIT.EDU}} can generate +the list of principals in the database, and the list of policies +in the database. This line is separate from line 4, because list +permission can only be granted globally, not to specific target +principals. + +\sphinxAtStartPar +(line 6) Finally, the Service Management System principal +\sphinxcode{\sphinxupquote{sms@ATHENA.MIT.EDU}} has all permissions except extracting keys, but +any principal that it creates or modifies will not be able to get +postdateable tickets or tickets with a life of longer than 9 hours. + + +\subsubsection{MODULE BEHAVIOR} +\label{\detokenize{admin/conf_files/kadm5_acl:module-behavior}} +\sphinxAtStartPar +The ACL file can coexist with other authorization modules in release +1.16 and later, as configured in the {\hyperref[\detokenize{admin/conf_files/krb5_conf:kadm5-auth}]{\sphinxcrossref{\DUrole{std,std-ref}{kadm5\_auth interface}}}} section of +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}. The ACL file will positively authorize +operations according to the rules above, but will never +authoritatively deny an operation, so other modules can authorize +operations in addition to those authorized by the ACL file. + +\sphinxAtStartPar +To operate without an ACL file, set the \sphinxstyleemphasis{acl\_file} variable in +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} to the empty string with \sphinxcode{\sphinxupquote{acl\_file = ""}}. + + +\subsubsection{SEE ALSO} +\label{\detokenize{admin/conf_files/kadm5_acl:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}, {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} + + +\chapter{Realm configuration decisions} +\label{\detokenize{admin/realm_config:realm-configuration-decisions}}\label{\detokenize{admin/realm_config::doc}} +\sphinxAtStartPar +Before installing Kerberos V5, it is necessary to consider the +following issues: +\begin{itemize} +\item {} +\sphinxAtStartPar +The name of your Kerberos realm (or the name of each realm, if you +need more than one). + +\item {} +\sphinxAtStartPar +How you will assign your hostnames to Kerberos realms. + +\item {} +\sphinxAtStartPar +Which ports your KDC and and kadmind services will use, if they will +not be using the default ports. + +\item {} +\sphinxAtStartPar +How many replica KDCs you need and where they should be located. + +\item {} +\sphinxAtStartPar +The hostnames of your primary and replica KDCs. + +\item {} +\sphinxAtStartPar +How frequently you will propagate the database from the primary KDC +to the replica KDCs. + +\end{itemize} + + +\section{Realm name} +\label{\detokenize{admin/realm_config:realm-name}} +\sphinxAtStartPar +Although your Kerberos realm can be any ASCII string, convention is to +make it the same as your domain name, in upper\sphinxhyphen{}case letters. + +\sphinxAtStartPar +For example, hosts in the domain \sphinxcode{\sphinxupquote{example.com}} would be in the +Kerberos realm: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If you need multiple Kerberos realms, MIT recommends that you use +descriptive names which end with your domain name, such as: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{BOSTON}\PYG{o}{.}\PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM} +\PYG{n}{HOUSTON}\PYG{o}{.}\PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM} +\end{sphinxVerbatim} + + +\section{Mapping hostnames onto Kerberos realms} +\label{\detokenize{admin/realm_config:mapping-hostnames-onto-kerberos-realms}}\label{\detokenize{admin/realm_config:mapping-hostnames}} +\sphinxAtStartPar +Mapping hostnames onto Kerberos realms is done in one of three ways. + +\sphinxAtStartPar +The first mechanism works through a set of rules in the +{\hyperref[\detokenize{admin/conf_files/krb5_conf:domain-realm}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}domain\_realm{]}}}}} section of {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}. You can specify +mappings for an entire domain or on a per\sphinxhyphen{}hostname basis. Typically +you would do this by specifying the mappings for a given domain or +subdomain and listing the exceptions. + +\sphinxAtStartPar +The second mechanism is to use KDC host\sphinxhyphen{}based service referrals. With +this method, the KDC’s krb5.conf has a full {[}domain\_realm{]} mapping for +hosts, but the clients do not, or have mappings for only a subset of +the hosts they might contact. When a client needs to contact a server +host for which it has no mapping, it will ask the client realm’s KDC +for the service ticket, and will receive a referral to the appropriate +service realm. + +\sphinxAtStartPar +To use referrals, clients must be running MIT krb5 1.6 or later, and +the KDC must be running MIT krb5 1.7 or later. The +\sphinxstylestrong{host\_based\_services} and \sphinxstylestrong{no\_host\_referral} variables in the +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} section of {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} can be used to +fine\sphinxhyphen{}tune referral behavior on the KDC. + +\sphinxAtStartPar +It is also possible for clients to use DNS TXT records, if +\sphinxstylestrong{dns\_lookup\_realm} is enabled in {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}. Such lookups +are disabled by default because DNS is an insecure protocol and security +holes could result if DNS records are spoofed. If enabled, the client +will try to look up a TXT record formed by prepending the prefix +\sphinxcode{\sphinxupquote{\_kerberos}} to the hostname in question. If that record is not +found, the client will attempt a lookup by prepending \sphinxcode{\sphinxupquote{\_kerberos}} to the +host’s domain name, then its parent domain, up to the top\sphinxhyphen{}level domain. +For the hostname \sphinxcode{\sphinxupquote{boston.engineering.example.com}}, the names looked up +would be: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{\PYGZus{}kerberos}\PYG{o}{.}\PYG{n}{boston}\PYG{o}{.}\PYG{n}{engineering}\PYG{o}{.}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com} +\PYG{n}{\PYGZus{}kerberos}\PYG{o}{.}\PYG{n}{engineering}\PYG{o}{.}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com} +\PYG{n}{\PYGZus{}kerberos}\PYG{o}{.}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com} +\PYG{n}{\PYGZus{}kerberos}\PYG{o}{.}\PYG{n}{com} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The value of the first TXT record found is taken as the realm name. + +\sphinxAtStartPar +Even if you do not choose to use this mechanism within your site, +you may wish to set it up anyway, for use when interacting with other sites. + + +\section{Ports for the KDC and admin services} +\label{\detokenize{admin/realm_config:ports-for-the-kdc-and-admin-services}} +\sphinxAtStartPar +The default ports used by Kerberos are port 88 for the KDC and port +749 for the admin server. You can, however, choose to run on other +ports, as long as they are specified in each host’s +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} files or in DNS SRV records, and the +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} file on each KDC. For a more thorough treatment of +port numbers used by the Kerberos V5 programs, refer to the +{\hyperref[\detokenize{admin/appl_servers:conf-firewall}]{\sphinxcrossref{\DUrole{std,std-ref}{Configuring your firewall to work with Kerberos V5}}}}. + + +\section{Replica KDCs} +\label{\detokenize{admin/realm_config:replica-kdcs}} +\sphinxAtStartPar +Replica KDCs provide an additional source of Kerberos ticket\sphinxhyphen{}granting +services in the event of inaccessibility of the primary KDC. The +number of replica KDCs you need and the decision of where to place them, +both physically and logically, depends on the specifics of your +network. + +\sphinxAtStartPar +Kerberos authentication requires that each client be able to contact a +KDC. Therefore, you need to anticipate any likely reason a KDC might +be unavailable and have a replica KDC to take up the slack. + +\sphinxAtStartPar +Some considerations include: +\begin{itemize} +\item {} +\sphinxAtStartPar +Have at least one replica KDC as a backup, for when the primary KDC +is down, is being upgraded, or is otherwise unavailable. + +\item {} +\sphinxAtStartPar +If your network is split such that a network outage is likely to +cause a network partition (some segment or segments of the network +to become cut off or isolated from other segments), have a replica +KDC accessible to each segment. + +\item {} +\sphinxAtStartPar +If possible, have at least one replica KDC in a different building +from the primary, in case of power outages, fires, or other +localized disasters. + +\end{itemize} + + +\section{Hostnames for KDCs} +\label{\detokenize{admin/realm_config:hostnames-for-kdcs}}\label{\detokenize{admin/realm_config:kdc-hostnames}} +\sphinxAtStartPar +MIT recommends that your KDCs have a predefined set of CNAME records +(DNS hostname aliases), such as \sphinxcode{\sphinxupquote{kerberos}} for the primary KDC and +\sphinxcode{\sphinxupquote{kerberos\sphinxhyphen{}1}}, \sphinxcode{\sphinxupquote{kerberos\sphinxhyphen{}2}}, … for the replica KDCs. This way, +if you need to swap a machine, you only need to change a DNS entry, +rather than having to change hostnames. + +\sphinxAtStartPar +As of MIT krb5 1.4, clients can locate a realm’s KDCs through DNS +using SRV records (\index{RFC@\spxentry{RFC}!RFC 2782@\spxentry{RFC 2782}}\sphinxhref{https://tools.ietf.org/html/rfc2782.html}{\sphinxstylestrong{RFC 2782}}), assuming the Kerberos realm name is +also a DNS domain name. These records indicate the hostname and port +number to contact for that service, optionally with weighting and +prioritization. The domain name used in the SRV record name is the +realm name. Several different Kerberos\sphinxhyphen{}related service names are +used: +\begin{description} +\item[{\_kerberos.\_udp}] \leavevmode +\sphinxAtStartPar +This is for contacting any KDC by UDP. This entry will be used +the most often. Normally you should list port 88 on each of your +KDCs. + +\item[{\_kerberos.\_tcp}] \leavevmode +\sphinxAtStartPar +This is for contacting any KDC by TCP. Normally you should use +port 88. This entry should be omitted if the KDC does not listen +on TCP ports, as was the default prior to release 1.13. + +\item[{\_kerberos\sphinxhyphen{}master.\_udp}] \leavevmode +\sphinxAtStartPar +This entry should refer to those KDCs, if any, that will +immediately see password changes to the Kerberos database. If a +user is logging in and the password appears to be incorrect, the +client will retry with the primary KDC before failing with an +“incorrect password” error given. + +\sphinxAtStartPar +If you have only one KDC, or for whatever reason there is no +accessible KDC that would get database changes faster than the +others, you do not need to define this entry. + +\item[{\_kerberos\sphinxhyphen{}adm.\_tcp}] \leavevmode +\sphinxAtStartPar +This should list port 749 on your primary KDC. Support for it is +not complete at this time, but it will eventually be used by the +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} program and related utilities. For now, you will +also need the \sphinxstylestrong{admin\_server} variable in {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}. + +\item[{\_kerberos\sphinxhyphen{}master.\_tcp}] \leavevmode +\sphinxAtStartPar +The corresponding TCP port for \_kerberos\sphinxhyphen{}master.\_udp, assuming the +primary KDC listens on a TCP port. + +\item[{\_kpasswd.\_udp}] \leavevmode +\sphinxAtStartPar +This entry should list port 464 on your primary KDC. It is used +when a user changes her password. If this entry is not defined +but a \_kerberos\sphinxhyphen{}adm.\_tcp entry is defined, the client will use the +\_kerberos\sphinxhyphen{}adm.\_tcp entry with the port number changed to 464. + +\item[{\_kpasswd.\_tcp}] \leavevmode +\sphinxAtStartPar +The corresponding TCP port for \_kpasswd.\_udp. + +\end{description} + +\sphinxAtStartPar +The DNS SRV specification requires that the hostnames listed be the +canonical names, not aliases. So, for example, you might include the +following records in your (BIND\sphinxhyphen{}style) zone file: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{}ORIGIN foobar.com. +\PYGZus{}kerberos TXT \PYGZdq{}FOOBAR.COM\PYGZdq{} +kerberos CNAME daisy +kerberos\PYGZhy{}1 CNAME use\PYGZhy{}the\PYGZhy{}force\PYGZhy{}luke +kerberos\PYGZhy{}2 CNAME bunny\PYGZhy{}rabbit +\PYGZus{}kerberos.\PYGZus{}udp SRV 0 0 88 daisy + SRV 0 0 88 use\PYGZhy{}the\PYGZhy{}force\PYGZhy{}luke + SRV 0 0 88 bunny\PYGZhy{}rabbit +\PYGZus{}kerberos\PYGZhy{}master.\PYGZus{}udp SRV 0 0 88 daisy +\PYGZus{}kerberos\PYGZhy{}adm.\PYGZus{}tcp SRV 0 0 749 daisy +\PYGZus{}kpasswd.\PYGZus{}udp SRV 0 0 464 daisy +\end{sphinxVerbatim} + +\sphinxAtStartPar +Clients can also be configured with the explicit location of services +using the \sphinxstylestrong{kdc}, \sphinxstylestrong{master\_kdc}, \sphinxstylestrong{admin\_server}, and +\sphinxstylestrong{kpasswd\_server} variables in the {\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} section of +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}. Even if some clients will be configured with +explicit server locations, providing SRV records will still benefit +unconfigured clients, and be useful for other sites. + + +\section{KDC Discovery} +\label{\detokenize{admin/realm_config:kdc-discovery}}\label{\detokenize{admin/realm_config:id1}} +\sphinxAtStartPar +As of MIT krb5 1.15, clients can also locate KDCs in DNS through URI +records (\index{RFC@\spxentry{RFC}!RFC 7553@\spxentry{RFC 7553}}\sphinxhref{https://tools.ietf.org/html/rfc7553.html}{\sphinxstylestrong{RFC 7553}}). Limitations with the SRV record format may +result in extra DNS queries in situations where a client must failover +to other transport types, or find a primary server. The URI record +can convey more information about a realm’s KDCs with a single query. + +\sphinxAtStartPar +The client performs a query for the following URI records: +\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{\_kerberos.REALM}} for finding KDCs. + +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{\_kerberos\sphinxhyphen{}adm.REALM}} for finding kadmin services. + +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{\_kpasswd.REALM}} for finding password services. + +\end{itemize} + +\sphinxAtStartPar +The URI record includes a priority, weight, and a URI string that +consists of case\sphinxhyphen{}insensitive colon separated fields, in the form +\sphinxcode{\sphinxupquote{scheme:{[}flags{]}:transport:residual}}. +\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstyleemphasis{scheme} defines the registered URI type. It should always be +\sphinxcode{\sphinxupquote{krb5srv}}. + +\item {} +\sphinxAtStartPar +\sphinxstyleemphasis{flags} contains zero or more flag characters. Currently the only +valid flag is \sphinxcode{\sphinxupquote{m}}, which indicates that the record is for a +primary server. + +\item {} +\sphinxAtStartPar +\sphinxstyleemphasis{transport} defines the transport type of the residual URL or +address. Accepted values are \sphinxcode{\sphinxupquote{tcp}}, \sphinxcode{\sphinxupquote{udp}}, or \sphinxcode{\sphinxupquote{kkdcp}} for the +MS\sphinxhyphen{}KKDCP type. + +\item {} +\sphinxAtStartPar +\sphinxstyleemphasis{residual} contains the hostname, IP address, or URL to be +contacted using the specified transport, with an optional port +extension. The MS\sphinxhyphen{}KKDCP transport type uses a HTTPS URL, and can +include a port and/or path extension. + +\end{itemize} + +\sphinxAtStartPar +An example of URI records in a zone file: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{\PYGZus{}kerberos}\PYG{o}{.}\PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM} \PYG{n}{URI} \PYG{l+m+mi}{10} \PYG{l+m+mi}{1} \PYG{n}{krb5srv}\PYG{p}{:}\PYG{n}{m}\PYG{p}{:}\PYG{n}{tcp}\PYG{p}{:}\PYG{n}{kdc1}\PYG{o}{.}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com} + \PYG{n}{URI} \PYG{l+m+mi}{20} \PYG{l+m+mi}{1} \PYG{n}{krb5srv}\PYG{p}{:}\PYG{n}{m}\PYG{p}{:}\PYG{n}{udp}\PYG{p}{:}\PYG{n}{kdc2}\PYG{o}{.}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com}\PYG{p}{:}\PYG{l+m+mi}{89} + \PYG{n}{URI} \PYG{l+m+mi}{40} \PYG{l+m+mi}{1} \PYG{n}{krb5srv}\PYG{p}{:}\PYG{p}{:}\PYG{n}{udp}\PYG{p}{:}\PYG{l+m+mf}{10.10}\PYG{l+m+mf}{.0}\PYG{l+m+mf}{.23} + \PYG{n}{URI} \PYG{l+m+mi}{30} \PYG{l+m+mi}{1} \PYG{n}{krb5srv}\PYG{p}{:}\PYG{p}{:}\PYG{n}{kkdcp}\PYG{p}{:}\PYG{n}{https}\PYG{p}{:}\PYG{o}{/}\PYG{o}{/}\PYG{n}{proxy}\PYG{p}{:}\PYG{l+m+mi}{89}\PYG{o}{/}\PYG{n}{auth} +\end{sphinxVerbatim} + +\sphinxAtStartPar +URI lookups are enabled by default, and can be disabled by setting +\sphinxstylestrong{dns\_uri\_lookup} in the {\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}} section of +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} to False. When enabled, URI lookups take +precedence over SRV lookups, falling back to SRV lookups if no URI +records are found. + + +\section{Database propagation} +\label{\detokenize{admin/realm_config:database-propagation}}\label{\detokenize{admin/realm_config:db-prop}} +\sphinxAtStartPar +The Kerberos database resides on the primary KDC, and must be +propagated regularly (usually by a cron job) to the replica KDCs. In +deciding how frequently the propagation should happen, you will need +to balance the amount of time the propagation takes against the +maximum reasonable amount of time a user should have to wait for a +password change to take effect. + +\sphinxAtStartPar +If the propagation time is longer than this maximum reasonable time +(e.g., you have a particularly large database, you have a lot of +replicas, or you experience frequent network delays), you may wish to +cut down on your propagation delay by performing the propagation in +parallel. To do this, have the primary KDC propagate the database to +one set of replicas, and then have each of these replicas propagate +the database to additional replicas. + +\sphinxAtStartPar +See also {\hyperref[\detokenize{admin/database:incr-db-prop}]{\sphinxcrossref{\DUrole{std,std-ref}{Incremental database propagation}}}} + + +\chapter{Database administration} +\label{\detokenize{admin/database:database-administration}}\label{\detokenize{admin/database::doc}} +\sphinxAtStartPar +A Kerberos database contains all of a realm’s Kerberos principals, +their passwords, and other administrative information about each +principal. For the most part, you will use the {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} +program to manipulate the Kerberos database as a whole, and the +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} program to make changes to the entries in the +database. (One notable exception is that users will use the +\DUrole{xref,std,std-ref}{kpasswd(1)} program to change their own passwords.) The kadmin +program has its own command\sphinxhyphen{}line interface, to which you type the +database administrating commands. + +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} provides a means to create, delete, load, or dump +a Kerberos database. It also contains commands to roll over the +database master key, and to stash a copy of the key so that the +{\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} and {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} daemons can use the database +without manual input. + +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} provides for the maintenance of Kerberos principals, +password policies, and service key tables (keytabs). Normally it +operates as a network client using Kerberos authentication to +communicate with {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}}, but there is also a variant, named +kadmin.local, which directly accesses the Kerberos database on the +local filesystem (or through LDAP). kadmin.local is necessary to set +up enough of the database to be able to use the remote version. + +\sphinxAtStartPar +kadmin can authenticate to the admin server using the service +principal \sphinxcode{\sphinxupquote{kadmin/admin}} or \sphinxcode{\sphinxupquote{kadmin/HOST}} (where \sphinxstyleemphasis{HOST} is the +hostname of the admin server). If the credentials cache contains a +ticket for either service principal and the \sphinxstylestrong{\sphinxhyphen{}c} ccache option is +specified, that ticket is used to authenticate to KADM5. Otherwise, +the \sphinxstylestrong{\sphinxhyphen{}p} and \sphinxstylestrong{\sphinxhyphen{}k} options are used to specify the client Kerberos +principal name used to authenticate. Once kadmin has determined the +principal name, it requests a \sphinxcode{\sphinxupquote{kadmin/admin}} Kerberos service ticket +from the KDC, and uses that service ticket to authenticate to KADM5. + +\sphinxAtStartPar +See {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} for the available kadmin and kadmin.local +commands and options. + + +\section{Principals} +\label{\detokenize{admin/database:principals}}\label{\detokenize{admin/database:id1}} +\sphinxAtStartPar +Each entry in the Kerberos database contains a Kerberos principal and +the attributes and policies associated with that principal. + +\sphinxAtStartPar +To add a principal to the database, use the {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} +\sphinxstylestrong{add\_principal} command. User principals should usually be created +with the \sphinxcode{\sphinxupquote{+requires\_preauth \sphinxhyphen{}allow\_svr}} options to help mitigate +dictionary attacks (see {\hyperref[\detokenize{admin/dictionary:dictionary}]{\sphinxcrossref{\DUrole{std,std-ref}{Addressing dictionary attack risks}}}}): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{addprinc} \PYG{o}{+}\PYG{n}{requires\PYGZus{}preauth} \PYG{o}{\PYGZhy{}}\PYG{n}{allow\PYGZus{}svr} \PYG{n}{alice} +\PYG{n}{Enter} \PYG{n}{password} \PYG{k}{for} \PYG{n}{principal} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{alice@KRBTEST.COM}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{:} +\PYG{n}{Re}\PYG{o}{\PYGZhy{}}\PYG{n}{enter} \PYG{n}{password} \PYG{k}{for} \PYG{n}{principal} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{alice@KRBTEST.COM}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{:} +\end{sphinxVerbatim} + +\sphinxAtStartPar +User principals which will authenticate with {\hyperref[\detokenize{admin/pkinit:pkinit}]{\sphinxcrossref{\DUrole{std,std-ref}{PKINIT configuration}}}} should +instead by created with the \sphinxcode{\sphinxupquote{\sphinxhyphen{}nokey}} option: +\begin{quote} + +\sphinxAtStartPar +kadmin: addprinc \sphinxhyphen{}nokey alice +\end{quote} + +\sphinxAtStartPar +Service principals can be created with the \sphinxcode{\sphinxupquote{\sphinxhyphen{}nokey}} option; +long\sphinxhyphen{}term keys will be added when a keytab is generated: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{addprinc} \PYG{o}{\PYGZhy{}}\PYG{n}{nokey} \PYG{n}{host}\PYG{o}{/}\PYG{n}{foo}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{ktadd} \PYG{o}{\PYGZhy{}}\PYG{n}{k} \PYG{n}{foo}\PYG{o}{.}\PYG{n}{keytab} \PYG{n}{host}\PYG{o}{/}\PYG{n}{foo}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{foo}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{1}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{WRFILE}\PYG{p}{:}\PYG{n}{foo}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{foo}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{1}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{WRFILE}\PYG{p}{:}\PYG{n}{foo}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\end{sphinxVerbatim} + +\sphinxAtStartPar +To modify attributes of an existing principal, use the kadmin +\sphinxstylestrong{modify\_principal} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{modprinc} \PYG{o}{\PYGZhy{}}\PYG{n}{expire} \PYG{n}{tomorrow} \PYG{n}{alice} +\PYG{n}{Principal} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{alice@KRBTEST.COM}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{modified}\PYG{o}{.} +\end{sphinxVerbatim} + +\sphinxAtStartPar +To delete a principal, use the kadmin \sphinxstylestrong{delete\_principal} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +kadmin: delprinc alice +Are you sure you want to delete the principal \PYGZdq{}alice@KRBTEST.COM\PYGZdq{}? (yes/no): yes +Principal \PYGZdq{}alice@KRBTEST.COM\PYGZdq{} deleted. +Make sure that you have removed this principal from all ACLs before reusing. +\end{sphinxVerbatim} + +\sphinxAtStartPar +To change a principal’s password, use the kadmin \sphinxstylestrong{change\_password} +command. Password changes made through kadmin are subject to the same +password policies as would apply to password changes made through +\DUrole{xref,std,std-ref}{kpasswd(1)}. + +\sphinxAtStartPar +To view the attributes of a principal, use the kadmin\textasciigrave{} +\sphinxstylestrong{get\_principal} command. + +\sphinxAtStartPar +To generate a listing of principals, use the kadmin +\sphinxstylestrong{list\_principals} command. + + +\section{Policies} +\label{\detokenize{admin/database:policies}}\label{\detokenize{admin/database:id2}} +\sphinxAtStartPar +A policy is a set of rules governing passwords. Policies can dictate +minimum and maximum password lifetimes, minimum number of characters +and character classes a password must contain, and the number of old +passwords kept in the database. + +\sphinxAtStartPar +To add a new policy, use the {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} \sphinxstylestrong{add\_policy} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{addpol} \PYG{o}{\PYGZhy{}}\PYG{n}{maxlife} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{1 year}\PYG{l+s+s2}{\PYGZdq{}} \PYG{o}{\PYGZhy{}}\PYG{n}{history} \PYG{l+m+mi}{3} \PYG{n}{stduser} +\end{sphinxVerbatim} + +\sphinxAtStartPar +To modify attributes of a principal, use the kadmin \sphinxstylestrong{modify\_policy} +command. To delete a policy, use the kadmin \sphinxstylestrong{delete\_policy} +command. + +\sphinxAtStartPar +To associate a policy with a principal, use the kadmin +\sphinxstylestrong{modify\_principal} command with the \sphinxstylestrong{\sphinxhyphen{}policy} option: +\begin{quote} + +\sphinxAtStartPar +kadmin: modprinc \sphinxhyphen{}policy stduser alice +Principal “\sphinxhref{mailto:alice@KRBTEST.COM}{alice@KRBTEST.COM}” modified. +\end{quote} + +\sphinxAtStartPar +A principal entry may be associated with a nonexistent policy, either +because the policy did not exist at the time of associated or was +deleted afterwards. kadmin will warn when associated a principal with +a nonexistent policy, and will annotate the policy name with “{[}does +not exist{]}” in the \sphinxstylestrong{get\_principal} output. + + +\subsection{Updating the history key} +\label{\detokenize{admin/database:updating-the-history-key}}\label{\detokenize{admin/database:updating-history-key}} +\sphinxAtStartPar +If a policy specifies a number of old keys kept of two or more, the +stored old keys are encrypted in a history key, which is found in the +key data of the \sphinxcode{\sphinxupquote{kadmin/history}} principal. + +\sphinxAtStartPar +Currently there is no support for proper rollover of the history key, +but you can change the history key (for example, to use a better +encryption type) at the cost of invalidating currently stored old +keys. To change the history key, run: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{change\PYGZus{}password} \PYG{o}{\PYGZhy{}}\PYG{n}{randkey} \PYG{n}{kadmin}\PYG{o}{/}\PYG{n}{history} +\end{sphinxVerbatim} + +\sphinxAtStartPar +This command will fail if you specify the \sphinxstylestrong{\sphinxhyphen{}keepold} flag. Only one +new history key will be created, even if you specify multiple key/salt +combinations. + +\sphinxAtStartPar +In the future, we plan to migrate towards encrypting old keys in the +master key instead of the history key, and implementing proper +rollover support for stored old keys. + + +\section{Privileges} +\label{\detokenize{admin/database:privileges}}\label{\detokenize{admin/database:id3}} +\sphinxAtStartPar +Administrative privileges for the Kerberos database are stored in the +file {\hyperref[\detokenize{admin/conf_files/kadm5_acl:kadm5-acl-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kadm5.acl}}}}. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +A common use of an admin instance is so you can grant +separate permissions (such as administrator access to the +Kerberos database) to a separate Kerberos principal. For +example, the user \sphinxcode{\sphinxupquote{joeadmin}} might have a principal for +his administrative use, called \sphinxcode{\sphinxupquote{joeadmin/admin}}. This +way, \sphinxcode{\sphinxupquote{joeadmin}} would obtain \sphinxcode{\sphinxupquote{joeadmin/admin}} tickets +only when he actually needs to use those permissions. +\end{sphinxadmonition} + + +\section{Operations on the Kerberos database} +\label{\detokenize{admin/database:operations-on-the-kerberos-database}}\label{\detokenize{admin/database:db-operations}} +\sphinxAtStartPar +The {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} command is the primary tool for administrating +the Kerberos database when using the DB2 or LMDB modules (see +{\hyperref[\detokenize{admin/dbtypes:dbtypes}]{\sphinxcrossref{\DUrole{std,std-ref}{Database types}}}}). Creating a database is described in +{\hyperref[\detokenize{admin/install_kdc:create-db}]{\sphinxcrossref{\DUrole{std,std-ref}{Create the KDC database}}}}. + +\sphinxAtStartPar +To create a stash file using the master password (because the database +was not created with one using the \sphinxcode{\sphinxupquote{create \sphinxhyphen{}s}} flag, or after +restoring from a backup which did not contain the stash file), use the +kdb5\_util \sphinxstylestrong{stash} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}util stash +kdb5\PYGZus{}util: Cannot find/read stored master key while reading master key +kdb5\PYGZus{}util: Warning: proceeding without master key +Enter KDC database master key: \PYGZlt{}= Type the KDC database master password. +\end{sphinxVerbatim} + +\sphinxAtStartPar +To destroy a database, use the kdb5\_util destroy command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}util destroy +Deleting KDC database stored in \PYGZsq{}/var/krb5kdc/principal\PYGZsq{}, are you sure? +(type \PYGZsq{}yes\PYGZsq{} to confirm)? yes +OK, deleting database \PYGZsq{}/var/krb5kdc/principal\PYGZsq{}... +** Database \PYGZsq{}/var/krb5kdc/principal\PYGZsq{} destroyed. +\end{sphinxVerbatim} + + +\subsection{Dumping and loading a Kerberos database} +\label{\detokenize{admin/database:dumping-and-loading-a-kerberos-database}}\label{\detokenize{admin/database:restore-from-dump}} +\sphinxAtStartPar +To dump a Kerberos database into a text file for backup or transfer +purposes, use the {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} \sphinxstylestrong{dump} command on one of the +KDCs: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}util dump dumpfile + +\PYGZdl{} kbd5\PYGZus{}util dump \PYGZhy{}verbose dumpfile +kadmin/admin@ATHENA.MIT.EDU +krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU +kadmin/history@ATHENA.MIT.EDU +K/M@ATHENA.MIT.EDU +kadmin/changepw@ATHENA.MIT.EDU +\end{sphinxVerbatim} + +\sphinxAtStartPar +You may specify which principals to dump, using full principal names +including realm: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}util dump \PYGZhy{}verbose someprincs K/M@ATHENA.MIT.EDU kadmin/admin@ATHENA.MIT.EDU +kadmin/admin@ATHENA.MIT.EDU +K/M@ATHENA.MIT.EDU +\end{sphinxVerbatim} + +\sphinxAtStartPar +To restore a Kerberos database dump from a file, use the +{\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} \sphinxstylestrong{load} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}util load dumpfile +\end{sphinxVerbatim} + +\sphinxAtStartPar +To update an existing database with a partial dump file containing +only some principals, use the \sphinxcode{\sphinxupquote{\sphinxhyphen{}update}} flag: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}util load \PYGZhy{}update someprincs +\end{sphinxVerbatim} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +If the database file exists, and the \sphinxstyleemphasis{\sphinxhyphen{}update} flag was not +given, \sphinxstyleemphasis{kdb5\_util} will overwrite the existing database. +\end{sphinxadmonition} + + +\subsection{Updating the master key} +\label{\detokenize{admin/database:updating-the-master-key}}\label{\detokenize{admin/database:updating-master-key}} +\sphinxAtStartPar +Starting with release 1.7, {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} allows the master key +to be changed using a rollover process, with minimal loss of +availability. To roll over the master key, follow these steps: +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +On the primary KDC, run \sphinxcode{\sphinxupquote{kdb5\_util list\_mkeys}} to view the +current master key version number (KVNO). If you have never rolled +over the master key before, this will likely be version 1: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}util list\PYGZus{}mkeys +Master keys for Principal: K/M@KRBTEST.COM +KVNO: 1, Enctype: aes256\PYGZhy{}cts\PYGZhy{}hmac\PYGZhy{}sha384\PYGZhy{}192, Active on: Thu Jan 01 00:00:00 UTC 1970 * +\end{sphinxVerbatim} + +\item {} +\sphinxAtStartPar +On the primary KDC, run \sphinxcode{\sphinxupquote{kdb5\_util use\_mkey 1}} to ensure that a +master key activation list is present in the database. This step +is unnecessary in release 1.11.4 or later, or if the database was +initially created with release 1.7 or later. + +\item {} +\sphinxAtStartPar +On the primary KDC, run \sphinxcode{\sphinxupquote{kdb5\_util add\_mkey \sphinxhyphen{}s}} to create a new +master key and write it to the stash file. Enter a secure password +when prompted. If this is the first time you are changing the +master key, the new key will have version 2. The new master key +will not be used until you make it active. + +\item {} +\sphinxAtStartPar +Propagate the database to all replica KDCs, either manually or by +waiting until the next scheduled propagation. If you do not have +any replica KDCs, you can skip this and the next step. + +\item {} +\sphinxAtStartPar +On each replica KDC, run \sphinxcode{\sphinxupquote{kdb5\_util list\_mkeys}} to verify that +the new master key is present, and then \sphinxcode{\sphinxupquote{kdb5\_util stash}} to +write the new master key to the replica KDC’s stash file. + +\item {} +\sphinxAtStartPar +On the primary KDC, run \sphinxcode{\sphinxupquote{kdb5\_util use\_mkey 2}} to begin using the +new master key. Replace \sphinxcode{\sphinxupquote{2}} with the version of the new master +key, as appropriate. You can optionally specify a date for the new +master key to become active; by default, it will become active +immediately. Prior to release 1.12, {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} must be +restarted for this change to take full effect. + +\item {} +\sphinxAtStartPar +On the primary KDC, run \sphinxcode{\sphinxupquote{kdb5\_util update\_princ\_encryption}}. +This command will iterate over the database and re\sphinxhyphen{}encrypt all keys +in the new master key. If the database is large and uses DB2, the +primary KDC will become unavailable while this command runs, but +clients should fail over to replica KDCs (if any are present) +during this time period. In release 1.13 and later, you can +instead run \sphinxcode{\sphinxupquote{kdb5\_util \sphinxhyphen{}x unlockiter update\_princ\_encryption}} to +use unlocked iteration; this variant will take longer, but will +keep the database available to the KDC and kadmind while it runs. + +\item {} +\sphinxAtStartPar +Wait until the above changes have propagated to all replica KDCs +and until all running KDC and kadmind processes have serviced +requests using updated principal entries. + +\item {} +\sphinxAtStartPar +On the primary KDC, run \sphinxcode{\sphinxupquote{kdb5\_util purge\_mkeys}} to clean up the +old master key. + +\end{enumerate} + + +\section{Operations on the LDAP database} +\label{\detokenize{admin/database:operations-on-the-ldap-database}}\label{\detokenize{admin/database:ops-on-ldap}} +\sphinxAtStartPar +The {\hyperref[\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_ldap\_util}}}} command is the primary tool for +administrating the Kerberos database when using the LDAP module. +Creating an LDAP Kerberos database is describe in {\hyperref[\detokenize{admin/conf_ldap:conf-ldap}]{\sphinxcrossref{\DUrole{std,std-ref}{Configuring Kerberos with OpenLDAP back\sphinxhyphen{}end}}}}. + +\sphinxAtStartPar +To view a list of realms in the LDAP database, use the kdb5\_ldap\_util +\sphinxstylestrong{list} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}ldap\PYGZus{}util list +KRBTEST.COM +\end{sphinxVerbatim} + +\sphinxAtStartPar +To modify the attributes of a realm, use the kdb5\_ldap\_util \sphinxstylestrong{modify} +command. For example, to change the default realm’s maximum ticket +life: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}ldap\PYGZus{}util modify \PYGZhy{}maxtktlife \PYGZdq{}10 hours\PYGZdq{} +\end{sphinxVerbatim} + +\sphinxAtStartPar +To display the attributes of a realm, use the kdb5\_ldap\_util \sphinxstylestrong{view} +command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}ldap\PYGZus{}util view + Realm Name: KRBTEST.COM + Maximum Ticket Life: 0 days 00:10:00 +\end{sphinxVerbatim} + +\sphinxAtStartPar +To remove a realm from the LDAP database, destroying its contents, use +the kdb5\_ldap\_util \sphinxstylestrong{destroy} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}ldap\PYGZus{}util destroy +Deleting KDC database of \PYGZsq{}KRBTEST.COM\PYGZsq{}, are you sure? +(type \PYGZsq{}yes\PYGZsq{} to confirm)? yes +OK, deleting database of \PYGZsq{}KRBTEST.COM\PYGZsq{}... +** Database of \PYGZsq{}KRBTEST.COM\PYGZsq{} destroyed. +\end{sphinxVerbatim} + + +\subsection{Ticket Policy operations} +\label{\detokenize{admin/database:ticket-policy-operations}} +\sphinxAtStartPar +Unlike the DB2 and LMDB modules, the LDAP module supports ticket +policy objects, which can be associated with principals to restrict +maximum ticket lifetimes and set mandatory principal flags. Ticket +policy objects are distinct from the password policies described +earlier on this page, and are chiefly managed through kdb5\_ldap\_util +rather than kadmin. To create a new ticket policy, use the +kdb5\_ldap\_util \sphinxstylestrong{create\_policy} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}ldap\PYGZus{}util create\PYGZus{}policy \PYGZhy{}maxrenewlife \PYGZdq{}2 days\PYGZdq{} users +\end{sphinxVerbatim} + +\sphinxAtStartPar +To associate a ticket policy with a principal, use the +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} \sphinxstylestrong{modify\_principal} (or \sphinxstylestrong{add\_principal}) command +with the \sphinxstylestrong{\sphinxhyphen{}x tktpolicy=}\sphinxstyleemphasis{policy} option: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kadmin.local modprinc \PYGZhy{}x tktpolicy=users alice +\end{sphinxVerbatim} + +\sphinxAtStartPar +To remove a ticket policy reference from a principal, use the same +command with an empty \sphinxstyleemphasis{policy}: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kadmin.local modprinc \PYGZhy{}x tktpolicy= alice +\end{sphinxVerbatim} + +\sphinxAtStartPar +To list the existing ticket policy objects, use the kdb5\_ldap\_util +\sphinxstylestrong{list\_policy} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}ldap\PYGZus{}util list\PYGZus{}policy +users +\end{sphinxVerbatim} + +\sphinxAtStartPar +To modify the attributes of a ticket policy object, use the +kdb5\_ldap\_util \sphinxstylestrong{modify\_policy} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}ldap\PYGZus{}util modify\PYGZus{}policy \PYGZhy{}allow\PYGZus{}svr +requires\PYGZus{}preauth users +\end{sphinxVerbatim} + +\sphinxAtStartPar +To view the attributes of a ticket policy object, use the +kdb5\_ldap\_util \sphinxstylestrong{view\_policy} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}ldap\PYGZus{}util view\PYGZus{}policy users + Ticket policy: users + Maximum renewable life: 2 days 00:00:00 + Ticket flags: REQUIRES\PYGZus{}PRE\PYGZus{}AUTH DISALLOW\PYGZus{}SVR +\end{sphinxVerbatim} + +\sphinxAtStartPar +To destroy an ticket policy object, use the kdb5\_ldap\_util +\sphinxstylestrong{destroy\_policy} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}ldap\PYGZus{}util destroy\PYGZus{}policy users +This will delete the policy object \PYGZsq{}users\PYGZsq{}, are you sure? +(type \PYGZsq{}yes\PYGZsq{} to confirm)? yes +** policy object \PYGZsq{}users\PYGZsq{} deleted. +\end{sphinxVerbatim} + + +\section{Cross\sphinxhyphen{}realm authentication} +\label{\detokenize{admin/database:cross-realm-authentication}}\label{\detokenize{admin/database:xrealm-authn}} +\sphinxAtStartPar +In order for a KDC in one realm to authenticate Kerberos users in a +different realm, it must share a key with the KDC in the other realm. +In both databases, there must be krbtgt service principals for both realms. +For example, if you need to do cross\sphinxhyphen{}realm authentication between the realms +\sphinxcode{\sphinxupquote{ATHENA.MIT.EDU}} and \sphinxcode{\sphinxupquote{EXAMPLE.COM}}, you would need to add the +principals \sphinxcode{\sphinxupquote{krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU}} and +\sphinxcode{\sphinxupquote{krbtgt/ATHENA.MIT.EDU@EXAMPLE.COM}} to both databases. +These principals must all have the same passwords, key version +numbers, and encryption types; this may require explicitly setting +the key version number with the \sphinxstylestrong{\sphinxhyphen{}kvno} option. + +\sphinxAtStartPar +In the ATHENA.MIT.EDU and EXAMPLE.COM cross\sphinxhyphen{}realm case, the administrators +would run the following commands on the KDCs in both realms: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}}\PYG{p}{:} \PYG{n}{kadmin}\PYG{o}{.}\PYG{n}{local} \PYG{o}{\PYGZhy{}}\PYG{n}{e} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{aes256\PYGZhy{}cts:normal}\PYG{l+s+s2}{\PYGZdq{}} +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{addprinc} \PYG{o}{\PYGZhy{}}\PYG{n}{requires\PYGZus{}preauth} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM} +\PYG{n}{Enter} \PYG{n}{password} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM}\PYG{p}{:} +\PYG{n}{Re}\PYG{o}{\PYGZhy{}}\PYG{n}{enter} \PYG{n}{password} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM}\PYG{p}{:} +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{addprinc} \PYG{o}{\PYGZhy{}}\PYG{n}{requires\PYGZus{}preauth} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{n}{Enter} \PYG{n}{password} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{p}{:} +\PYG{n}{Enter} \PYG{n}{password} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{p}{:} +\PYG{n}{kadmin}\PYG{p}{:} +\end{sphinxVerbatim} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +Even if most principals in a realm are generally created +with the \sphinxstylestrong{requires\_preauth} flag enabled, this flag is not +desirable on cross\sphinxhyphen{}realm authentication keys because doing +so makes it impossible to disable preauthentication on a +service\sphinxhyphen{}by\sphinxhyphen{}service basis. Disabling it as in the example +above is recommended. +\end{sphinxadmonition} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +It is very important that these principals have good +passwords. MIT recommends that TGT principal passwords be +at least 26 characters of random ASCII text. +\end{sphinxadmonition} + + +\section{Changing the krbtgt key} +\label{\detokenize{admin/database:changing-the-krbtgt-key}}\label{\detokenize{admin/database:changing-krbtgt-key}} +\sphinxAtStartPar +A Kerberos Ticket Granting Ticket (TGT) is a service ticket for the +principal \sphinxcode{\sphinxupquote{krbtgt/REALM}}. The key for this principal is created +when the Kerberos database is initialized and need not be changed. +However, it will only have the encryption types supported by the KDC +at the time of the initial database creation. To allow use of newer +encryption types for the TGT, this key has to be changed. + +\sphinxAtStartPar +Changing this key using the normal {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} +\sphinxstylestrong{change\_password} command would invalidate any previously issued +TGTs. Therefore, when changing this key, normally one should use the +\sphinxstylestrong{\sphinxhyphen{}keepold} flag to change\_password to retain the previous key in the +database as well as the new key. For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{change\PYGZus{}password} \PYG{o}{\PYGZhy{}}\PYG{n}{randkey} \PYG{o}{\PYGZhy{}}\PYG{n}{keepold} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\end{sphinxVerbatim} + +\begin{sphinxadmonition}{warning}{Warning:} +\sphinxAtStartPar +After issuing this command, the old key is still valid +and is still vulnerable to (for instance) brute force +attacks. To completely retire an old key or encryption +type, run the kadmin \sphinxstylestrong{purgekeys} command to delete keys +with older kvnos, ideally first making sure that all +tickets issued with the old keys have expired. +\end{sphinxadmonition} + +\sphinxAtStartPar +Only the first krbtgt key of the newest key version is used to encrypt +ticket\sphinxhyphen{}granting tickets. However, the set of encryption types present +in the krbtgt keys is used by default to determine the session key +types supported by the krbtgt service (see +{\hyperref[\detokenize{admin/enctypes:session-key-selection}]{\sphinxcrossref{\DUrole{std,std-ref}{Session key selection}}}}). Because non\sphinxhyphen{}MIT Kerberos clients +sometimes send a limited set of encryption types when making AS +requests, it can be important for the krbtgt service to support +multiple encryption types. This can be accomplished by giving the +krbtgt principal multiple keys, which is usually as simple as not +specifying any \sphinxstylestrong{\sphinxhyphen{}e} option when changing the krbtgt key, or by +setting the \sphinxstylestrong{session\_enctypes} string attribute on the krbtgt +principal (see {\hyperref[\detokenize{admin/admin_commands/kadmin_local:set-string}]{\sphinxcrossref{\DUrole{std,std-ref}{set\_string}}}}). + +\sphinxAtStartPar +Due to a bug in releases 1.8 through 1.13, renewed and forwarded +tickets may not work if the original ticket was obtained prior to a +krbtgt key change and the modified ticket is obtained afterwards. +Upgrading the KDC to release 1.14 or later will correct this bug. + + +\section{Incremental database propagation} +\label{\detokenize{admin/database:incremental-database-propagation}}\label{\detokenize{admin/database:incr-db-prop}} + +\subsection{Overview} +\label{\detokenize{admin/database:overview}} +\sphinxAtStartPar +At some very large sites, dumping and transmitting the database can +take more time than is desirable for changes to propagate from the +primary KDC to the replica KDCs. The incremental propagation support +added in the 1.7 release is intended to address this. + +\sphinxAtStartPar +With incremental propagation enabled, all programs on the primary KDC +that change the database also write information about the changes to +an “update log” file, maintained as a circular buffer of a certain +size. A process on each replica KDC connects to a service on the +primary KDC (currently implemented in the {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} server) and +periodically requests the changes that have been made since the last +check. By default, this check is done every two minutes. + +\sphinxAtStartPar +Incremental propagation uses the following entries in the per\sphinxhyphen{}realm +data in the KDC config file (See {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}): + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|T|} +\hline + +\sphinxAtStartPar +iprop\_enable +& +\sphinxAtStartPar +\sphinxstyleemphasis{boolean} +& +\sphinxAtStartPar +If \sphinxstyleemphasis{true}, then incremental propagation is enabled, and (as noted below) normal kprop propagation is disabled. The default is \sphinxstyleemphasis{false}. +\\ +\hline +\sphinxAtStartPar +iprop\_master\_ulogsize +& +\sphinxAtStartPar +\sphinxstyleemphasis{integer} +& +\sphinxAtStartPar +Indicates the number of entries that should be retained in the update log. The default is 1000; the maximum number is 2500. +\\ +\hline +\sphinxAtStartPar +iprop\_replica\_poll +& +\sphinxAtStartPar +\sphinxstyleemphasis{time interval} +& +\sphinxAtStartPar +Indicates how often the replica should poll the primary KDC for changes to the database. The default is two minutes. +\\ +\hline +\sphinxAtStartPar +iprop\_port +& +\sphinxAtStartPar +\sphinxstyleemphasis{integer} +& +\sphinxAtStartPar +Specifies the port number to be used for incremental propagation. This is required in both primary and replica configuration files. +\\ +\hline +\sphinxAtStartPar +iprop\_resync\_timeout +& +\sphinxAtStartPar +\sphinxstyleemphasis{integer} +& +\sphinxAtStartPar +Specifies the number of seconds to wait for a full propagation to complete. This is optional on replica configurations. Defaults to 300 seconds (5 minutes). +\\ +\hline +\sphinxAtStartPar +iprop\_logfile +& +\sphinxAtStartPar +\sphinxstyleemphasis{file name} +& +\sphinxAtStartPar +Specifies where the update log file for the realm database is to be stored. The default is to use the \sphinxstyleemphasis{database\_name} entry from the realms section of the config file {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}, with \sphinxstyleemphasis{.ulog} appended. (NOTE: If database\_name isn’t specified in the realms section, perhaps because the LDAP database back end is being used, or the file name is specified in the \sphinxstyleemphasis{dbmodules} section, then the hard\sphinxhyphen{}coded default for \sphinxstyleemphasis{database\_name} is used. Determination of the \sphinxstyleemphasis{iprop\_logfile} default value will not use values from the \sphinxstyleemphasis{dbmodules} section.) +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + +\sphinxAtStartPar +Both primary and replica sides must have a principal named +\sphinxcode{\sphinxupquote{kiprop/hostname}} (where \sphinxstyleemphasis{hostname} is the lowercase, +fully\sphinxhyphen{}qualified, canonical name for the host) registered in the +Kerberos database, and have keys for that principal stored in the +default keytab file ({\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{DEFKTNAME}}}}). The \sphinxcode{\sphinxupquote{kiprop/hostname}} principal may +have been created automatically for the primary KDC, but it must +always be created for replica KDCs. + +\sphinxAtStartPar +On the primary KDC side, the \sphinxcode{\sphinxupquote{kiprop/hostname}} principal must be +listed in the kadmind ACL file {\hyperref[\detokenize{admin/conf_files/kadm5_acl:kadm5-acl-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kadm5.acl}}}}, and given the +\sphinxstylestrong{p} privilege (see {\hyperref[\detokenize{admin/database:privileges}]{\sphinxcrossref{\DUrole{std,std-ref}{Privileges}}}}). + +\sphinxAtStartPar +On the replica KDC side, {\hyperref[\detokenize{admin/admin_commands/kpropd:kpropd-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kpropd}}}} should be run. When +incremental propagation is enabled, it will connect to the kadmind on +the primary KDC and start requesting updates. + +\sphinxAtStartPar +The normal kprop mechanism is disabled by the incremental propagation +support. However, if the replica has been unable to fetch changes +from the primary KDC for too long (network problems, perhaps), the log +on the primary may wrap around and overwrite some of the updates that +the replica has not yet retrieved. In this case, the replica will +instruct the primary KDC to dump the current database out to a file +and invoke a one\sphinxhyphen{}time kprop propagation, with special options to also +convey the point in the update log at which the replica should resume +fetching incremental updates. Thus, all the keytab and ACL setup +previously described for kprop propagation is still needed. + +\sphinxAtStartPar +If an environment has a large number of replicas, it may be desirable +to arrange them in a hierarchy instead of having the primary serve +updates to every replica. To do this, run \sphinxcode{\sphinxupquote{kadmind \sphinxhyphen{}proponly}} on +each intermediate replica, and \sphinxcode{\sphinxupquote{kpropd \sphinxhyphen{}A upstreamhostname}} on +downstream replicas to direct each one to the appropriate upstream +replica. + +\sphinxAtStartPar +There are several known restrictions in the current implementation: +\begin{itemize} +\item {} +\sphinxAtStartPar +The incremental update protocol does not transport changes to policy +objects. Any policy changes on the primary will result in full +resyncs to all replicas. + +\item {} +\sphinxAtStartPar +The replica’s KDB module must support locking; it cannot be using the +LDAP KDB module. + +\item {} +\sphinxAtStartPar +The primary and replica must be able to initiate TCP connections in +both directions, without an intervening NAT. + +\end{itemize} + + +\subsection{Sun/MIT incremental propagation differences} +\label{\detokenize{admin/database:sun-mit-incremental-propagation-differences}} +\sphinxAtStartPar +Sun donated the original code for supporting incremental database +propagation to MIT. Some changes have been made in the MIT source +tree that will be visible to administrators. (These notes are based +on Sun’s patches. Changes to Sun’s implementation since then may not +be reflected here.) + +\sphinxAtStartPar +The Sun config file support looks for \sphinxcode{\sphinxupquote{sunw\_dbprop\_enable}}, +\sphinxcode{\sphinxupquote{sunw\_dbprop\_master\_ulogsize}}, and \sphinxcode{\sphinxupquote{sunw\_dbprop\_slave\_poll}}. + +\sphinxAtStartPar +The incremental propagation service is implemented as an ONC RPC +service. In the Sun implementation, the service is registered with +rpcbind (also known as portmapper) and the client looks up the port +number to contact. In the MIT implementation, where interaction with +some modern versions of rpcbind doesn’t always work well, the port +number must be specified in the config file on both the primary and +replica sides. + +\sphinxAtStartPar +The Sun implementation hard\sphinxhyphen{}codes pathnames in \sphinxcode{\sphinxupquote{/var/krb5}} for the +update log and the per\sphinxhyphen{}replica kprop dump files. In the MIT +implementation, the pathname for the update log is specified in the +config file, and the per\sphinxhyphen{}replica dump files are stored in +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/replica\_datatrans\_hostname}}. + + +\chapter{Database types} +\label{\detokenize{admin/dbtypes:database-types}}\label{\detokenize{admin/dbtypes:dbtypes}}\label{\detokenize{admin/dbtypes::doc}} +\sphinxAtStartPar +A Kerberos database can be implemented with one of three built\sphinxhyphen{}in +database providers, called KDB modules. Software which incorporates +the MIT krb5 KDC may also provide its own KDB module. The following +subsections describe the three built\sphinxhyphen{}in KDB modules and the +configuration specific to them. + +\sphinxAtStartPar +The database type can be configured with the \sphinxstylestrong{db\_library} variable +in the {\hyperref[\detokenize{admin/conf_files/kdc_conf:dbmodules}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}dbmodules{]}}}}} subsection for the realm. For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{dbmodules}\PYG{p}{]} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{db\PYGZus{}library} \PYG{o}{=} \PYG{n}{db2} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If the \sphinxcode{\sphinxupquote{ATHENA.MIT.EDU}} realm subsection contains a +\sphinxstylestrong{database\_module} setting, then the subsection within +\sphinxcode{\sphinxupquote{{[}dbmodules{]}}} should use that name instead of \sphinxcode{\sphinxupquote{ATHENA.MIT.EDU}}. + +\sphinxAtStartPar +To transition from one database type to another, stop the +{\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} service, use \sphinxcode{\sphinxupquote{kdb5\_util dump}} to create a dump +file, change the \sphinxstylestrong{db\_library} value and set any appropriate +configuration for the new database type, and use \sphinxcode{\sphinxupquote{kdb5\_util load}} to +create and populate the new database. If the new database type is +LDAP, create the new database using \sphinxcode{\sphinxupquote{kdb5\_ldap\_util}} and populate it +from the dump file using \sphinxcode{\sphinxupquote{kdb5\_util load \sphinxhyphen{}update}}. Then restart the +{\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} and {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} services. + + +\section{Berkeley database module (db2)} +\label{\detokenize{admin/dbtypes:berkeley-database-module-db2}} +\sphinxAtStartPar +The default KDB module is \sphinxcode{\sphinxupquote{db2}}, which uses a version of the +Berkeley DB library. It creates four files based on the database +pathname. If the pathname ends with \sphinxcode{\sphinxupquote{principal}} then the four files +are: +\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{principal}}, containing principal entry data + +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{principal.ok}}, a lock file for the principal database + +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{principal.kadm5}}, containing policy object data + +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{principal.kadm5.lock}}, a lock file for the policy database + +\end{itemize} + +\sphinxAtStartPar +For large databases, the {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} \sphinxstylestrong{dump} command (perhaps +invoked by {\hyperref[\detokenize{admin/admin_commands/kprop:kprop-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop}}}} or by {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} for incremental +propagation) may cause {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} to stop for a noticeable +period of time while it iterates over the database. This delay can be +avoided by disabling account lockout features so that the KDC does not +perform database writes (see {\hyperref[\detokenize{admin/lockout:disable-lockout}]{\sphinxcrossref{\DUrole{std,std-ref}{KDC performance and account lockout}}}}). Alternatively, +a slower form of iteration can be enabled by setting the +\sphinxstylestrong{unlockiter} variable to \sphinxcode{\sphinxupquote{true}}. For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{dbmodules}\PYG{p}{]} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{db\PYGZus{}library} \PYG{o}{=} \PYG{n}{db2} + \PYG{n}{unlockiter} \PYG{o}{=} \PYG{n}{true} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +In rare cases, a power failure or other unclean system shutdown may +cause inconsistencies in the internal pointers within a database file, +such that \sphinxcode{\sphinxupquote{kdb5\_util dump}} cannot retrieve all principal entries in +the database. In this situation, it may be possible to retrieve all +of the principal data by running \sphinxcode{\sphinxupquote{kdb5\_util dump \sphinxhyphen{}recurse}} to +iterate over the database using the tree pointers instead of the +iteration pointers. Running \sphinxcode{\sphinxupquote{kdb5\_util dump \sphinxhyphen{}rev}} to iterate over +the database backwards may also retrieve some of the data which is not +retrieved by a normal dump operation. + + +\section{Lightning Memory\sphinxhyphen{}Mapped Database module (klmdb)} +\label{\detokenize{admin/dbtypes:lightning-memory-mapped-database-module-klmdb}} +\sphinxAtStartPar +The klmdb module was added in release 1.17. It uses the LMDB library, +and may offer better performance and reliability than the db2 module. +It creates four files based on the database pathname. If the pathname +ends with \sphinxcode{\sphinxupquote{principal}}, then the four files are: +\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{principal.mdb}}, containing policy object data and most principal +entry data + +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{principal.mdb\sphinxhyphen{}lock}}, a lock file for the primary database + +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{principal.lockout.mdb}}, containing the account lockout attributes +(last successful authentication time, last failed authentication +time, and number of failed attempts) for each principal entry + +\item {} +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{principal.lockout.mdb\sphinxhyphen{}lock}}, a lock file for the lockout database + +\end{itemize} + +\sphinxAtStartPar +Separating out the lockout attributes ensures that the KDC will never +block on an administrative operation such as a database dump or load. +It also allows the KDC to operate without write access to the primary +database. If both account lockout features are disabled (see +{\hyperref[\detokenize{admin/lockout:disable-lockout}]{\sphinxcrossref{\DUrole{std,std-ref}{KDC performance and account lockout}}}}), the lockout database files will be created +but will not subsequently be opened, and the account lockout +attributes will always have zero values. + +\sphinxAtStartPar +Because LMDB creates a memory map to the database files, it requires a +configured memory map size which also determines the maximum size of +the database. This size is applied equally to the two databases, so +twice the configured size will be consumed in the process address +space; this is primarily a limitation on 32\sphinxhyphen{}bit platforms. The +default value of 128 megabytes should be sufficient for several +hundred thousand principal entries. If the limit is reached, kadmin +operations will fail and the error message “Environment mapsize limit +reached” will appear in the kadmind log file. In this case, the +\sphinxstylestrong{mapsize} variable can be used to increase the map size. The +following example sets the map size to 512 megabytes: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{dbmodules}\PYG{p}{]} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{db\PYGZus{}library} \PYG{o}{=} \PYG{n}{klmdb} + \PYG{n}{mapsize} \PYG{o}{=} \PYG{l+m+mi}{512} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +LMDB has a configurable maximum number of readers. The default value +of 128 should be sufficient for most deployments. If you are going to +use a large number of KDC worker processes, it may be necessary to set +the \sphinxstylestrong{max\_readers} variable to a larger number. + +\sphinxAtStartPar +By default, LMDB synchronizes database files to disk after each write +transaction to ensure durability in the case of an unclean system +shutdown. The klmdb module always turns synchronization off for the +lockout database to ensure reasonable KDC performance, but leaves it +on for the primary database. If high throughput for administrative +operations (including password changes) is required, the \sphinxstylestrong{nosync} +variable can be set to “true” to disable synchronization for the +primary database. + +\sphinxAtStartPar +The klmdb module does not support explicit locking with the +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} \sphinxstylestrong{lock} command. + + +\section{LDAP module (kldap)} +\label{\detokenize{admin/dbtypes:ldap-module-kldap}} +\sphinxAtStartPar +The kldap module stores principal and policy data using an LDAP +server. To use it you must configure an LDAP server to use the +Kerberos schema. See {\hyperref[\detokenize{admin/conf_ldap:conf-ldap}]{\sphinxcrossref{\DUrole{std,std-ref}{Configuring Kerberos with OpenLDAP back\sphinxhyphen{}end}}}} for details. + +\sphinxAtStartPar +Because {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} is single\sphinxhyphen{}threaded, latency in LDAP database +accesses may limit KDC operation throughput. If the LDAP server is +located on the same server host as the KDC and accessed through an +\sphinxcode{\sphinxupquote{ldapi://}} URL, latency should be minimal. If this is not possible, +consider starting multiple KDC worker processes with the +{\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} \sphinxstylestrong{\sphinxhyphen{}w} option to enable concurrent processing of KDC +requests. + +\sphinxAtStartPar +The kldap module does not support explicit locking with the +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} \sphinxstylestrong{lock} command. + + +\chapter{Account lockout} +\label{\detokenize{admin/lockout:account-lockout}}\label{\detokenize{admin/lockout:lockout}}\label{\detokenize{admin/lockout::doc}} +\sphinxAtStartPar +As of release 1.8, the KDC can be configured to lock out principals +after a number of failed authentication attempts within a period of +time. Account lockout can make it more difficult to attack a +principal’s password by brute force, but also makes it easy for an +attacker to deny access to a principal. + + +\section{Configuring account lockout} +\label{\detokenize{admin/lockout:configuring-account-lockout}} +\sphinxAtStartPar +Account lockout only works for principals with the +\sphinxstylestrong{+requires\_preauth} flag set. Without this flag, the KDC cannot +know whether or not a client successfully decrypted the ticket it +issued. It is also important to set the \sphinxstylestrong{\sphinxhyphen{}allow\_svr} flag on a +principal to protect its password from an off\sphinxhyphen{}line dictionary attack +through a TGS request. You can set these flags on a principal with +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} as follows: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{modprinc} \PYG{o}{+}\PYG{n}{requires\PYGZus{}preauth} \PYG{o}{\PYGZhy{}}\PYG{n}{allow\PYGZus{}svr} \PYG{n}{PRINCNAME} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Account lockout parameters are configured via {\hyperref[\detokenize{admin/database:policies}]{\sphinxcrossref{\DUrole{std,std-ref}{policy objects}}}}. There may be an existing policy associated with user +principals (such as the “default” policy), or you may need to create a +new one and associate it with each user principal. + +\sphinxAtStartPar +The policy parameters related to account lockout are: +\begin{itemize} +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:policy-maxfailure}]{\sphinxcrossref{\DUrole{std,std-ref}{maxfailure}}}}: the number of failed attempts +before the principal is locked out + +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:policy-failurecountinterval}]{\sphinxcrossref{\DUrole{std,std-ref}{failurecountinterval}}}}: the +allowable interval between failed attempts + +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:policy-lockoutduration}]{\sphinxcrossref{\DUrole{std,std-ref}{lockoutduration}}}}: the amount of time +a principal is locked out for + +\end{itemize} + +\sphinxAtStartPar +Here is an example of setting these parameters on a new policy and +associating it with a principal: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{addpol} \PYG{o}{\PYGZhy{}}\PYG{n}{maxfailure} \PYG{l+m+mi}{10} \PYG{o}{\PYGZhy{}}\PYG{n}{failurecountinterval} \PYG{l+m+mi}{180} + \PYG{o}{\PYGZhy{}}\PYG{n}{lockoutduration} \PYG{l+m+mi}{60} \PYG{n}{lockout\PYGZus{}policy} +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{modprinc} \PYG{o}{\PYGZhy{}}\PYG{n}{policy} \PYG{n}{lockout\PYGZus{}policy} \PYG{n}{PRINCNAME} +\end{sphinxVerbatim} + + +\section{Testing account lockout} +\label{\detokenize{admin/lockout:testing-account-lockout}} +\sphinxAtStartPar +To test that account lockout is working, try authenticating as the +principal (hopefully not one that might be in use) multiple times with +the wrong password. For instance, if \sphinxstylestrong{maxfailure} is set to 2, you +might see: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kinit user +Password for user@KRBTEST.COM: +kinit: Password incorrect while getting initial credentials +\PYGZdl{} kinit user +Password for user@KRBTEST.COM: +kinit: Password incorrect while getting initial credentials +\PYGZdl{} kinit user +kinit: Client\PYGZsq{}s credentials have been revoked while getting initial credentials +\end{sphinxVerbatim} + + +\section{Account lockout principal state} +\label{\detokenize{admin/lockout:account-lockout-principal-state}} +\sphinxAtStartPar +A principal entry keeps three pieces of state related to account +lockout: +\begin{itemize} +\item {} +\sphinxAtStartPar +The time of last successful authentication + +\item {} +\sphinxAtStartPar +The time of last failed authentication + +\item {} +\sphinxAtStartPar +A counter of failed attempts + +\end{itemize} + +\sphinxAtStartPar +The time of last successful authentication is not actually needed for +the account lockout system to function, but may be of administrative +interest. These fields can be observed with the \sphinxstylestrong{getprinc} kadmin +command. For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{getprinc} \PYG{n}{user} +\PYG{n}{Principal}\PYG{p}{:} \PYG{n}{user}\PYG{n+nd}{@KRBTEST}\PYG{o}{.}\PYG{n}{COM} +\PYG{o}{.}\PYG{o}{.}\PYG{o}{.} +\PYG{n}{Last} \PYG{n}{successful} \PYG{n}{authentication}\PYG{p}{:} \PYG{p}{[}\PYG{n}{never}\PYG{p}{]} +\PYG{n}{Last} \PYG{n}{failed} \PYG{n}{authentication}\PYG{p}{:} \PYG{n}{Mon} \PYG{n}{Dec} \PYG{l+m+mi}{03} \PYG{l+m+mi}{12}\PYG{p}{:}\PYG{l+m+mi}{30}\PYG{p}{:}\PYG{l+m+mi}{33} \PYG{n}{EST} \PYG{l+m+mi}{2012} +\PYG{n}{Failed} \PYG{n}{password} \PYG{n}{attempts}\PYG{p}{:} \PYG{l+m+mi}{2} +\PYG{o}{.}\PYG{o}{.}\PYG{o}{.} +\end{sphinxVerbatim} + +\sphinxAtStartPar +A principal which has been locked out can be administratively unlocked +with the \sphinxstylestrong{\sphinxhyphen{}unlock} option to the \sphinxstylestrong{modprinc} kadmin command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{modprinc} \PYG{o}{\PYGZhy{}}\PYG{n}{unlock} \PYG{n}{PRINCNAME} +\end{sphinxVerbatim} + +\sphinxAtStartPar +This command will reset the number of failed attempts to 0. + + +\section{KDC replication and account lockout} +\label{\detokenize{admin/lockout:kdc-replication-and-account-lockout}} +\sphinxAtStartPar +The account lockout state of a principal is not replicated by either +traditional {\hyperref[\detokenize{admin/admin_commands/kprop:kprop-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop}}}} or incremental propagation. Because of +this, the number of attempts an attacker can make within a time period +is multiplied by the number of KDCs. For instance, if the +\sphinxstylestrong{maxfailure} parameter on a policy is 10 and there are four KDCs in +the environment (a primary and three replicas), an attacker could make +as many as 40 attempts before the principal is locked out on all four +KDCs. + +\sphinxAtStartPar +An administrative unlock is propagated from the primary to the replica +KDCs during the next propagation. Propagation of an administrative +unlock will cause the counter of failed attempts on each replica to +reset to 1 on the next failure. + +\sphinxAtStartPar +If a KDC environment uses a replication strategy other than kprop or +incremental propagation, such as the LDAP KDB module with multi\sphinxhyphen{}master +LDAP replication, then account lockout state may be replicated between +KDCs and the concerns of this section may not apply. + + +\section{KDC performance and account lockout} +\label{\detokenize{admin/lockout:kdc-performance-and-account-lockout}}\label{\detokenize{admin/lockout:disable-lockout}} +\sphinxAtStartPar +In order to fully track account lockout state, the KDC must write to +the the database on each successful and failed authentication. +Writing to the database is generally more expensive than reading from +it, so these writes may have a significant impact on KDC performance. +As of release 1.9, it is possible to turn off account lockout state +tracking in order to improve performance, by setting the +\sphinxstylestrong{disable\_last\_success} and \sphinxstylestrong{disable\_lockout} variables in the +database module subsection of {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{dbmodules}\PYG{p}{]} + \PYG{n}{DB} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{disable\PYGZus{}last\PYGZus{}success} \PYG{o}{=} \PYG{n}{true} + \PYG{n}{disable\PYGZus{}lockout} \PYG{o}{=} \PYG{n}{true} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Of the two variables, setting \sphinxstylestrong{disable\_last\_success} will usually +have the largest positive impact on performance, and will still allow +account lockout policies to operate. However, it will make it +impossible to observe the last successful authentication time with +kadmin. + + +\section{KDC setup and account lockout} +\label{\detokenize{admin/lockout:kdc-setup-and-account-lockout}} +\sphinxAtStartPar +To update the account lockout state on principals, the KDC must be +able to write to the principal database. For the DB2 module, no +special setup is required. For the LDAP module, the KDC DN must be +granted write access to the principal objects. If the KDC DN has only +read access, account lockout will not function. + + +\chapter{Configuring Kerberos with OpenLDAP back\sphinxhyphen{}end} +\label{\detokenize{admin/conf_ldap:configuring-kerberos-with-openldap-back-end}}\label{\detokenize{admin/conf_ldap:conf-ldap}}\label{\detokenize{admin/conf_ldap::doc}}\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +Make sure the LDAP server is using local authentication +(\sphinxcode{\sphinxupquote{ldapi://}}) or TLS (\sphinxcode{\sphinxupquote{ldaps}}). See +\sphinxurl{https://www.openldap.org/doc/admin/tls.html} for instructions on +configuring TLS support in OpenLDAP. + +\item {} +\sphinxAtStartPar +Add the Kerberos schema file to the LDAP Server using the OpenLDAP +LDIF file from the krb5 source directory +(\sphinxcode{\sphinxupquote{src/plugins/kdb/ldap/libkdb\_ldap/kerberos.openldap.ldif}}). +The following example uses local authentication: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{ldapadd} \PYG{o}{\PYGZhy{}}\PYG{n}{Y} \PYG{n}{EXTERNAL} \PYG{o}{\PYGZhy{}}\PYG{n}{H} \PYG{n}{ldapi}\PYG{p}{:}\PYG{o}{/}\PYG{o}{/}\PYG{o}{/} \PYG{o}{\PYGZhy{}}\PYG{n}{f} \PYG{o}{/}\PYG{n}{path}\PYG{o}{/}\PYG{n}{to}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{.}\PYG{n}{openldap}\PYG{o}{.}\PYG{n}{ldif} +\end{sphinxVerbatim} + +\item {} +\sphinxAtStartPar +Choose DNs for the {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} and {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} servers +to bind to the LDAP server, and create them if necessary. Specify +these DNs with the \sphinxstylestrong{ldap\_kdc\_dn} and \sphinxstylestrong{ldap\_kadmind\_dn} +directives in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. The kadmind DN will also be +used for administrative commands such as {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}}. + +\sphinxAtStartPar +Alternatively, you may configure krb5kdc and kadmind to use SASL +authentication to access the LDAP server; see the {\hyperref[\detokenize{admin/conf_files/kdc_conf:dbmodules}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}dbmodules{]}}}}} +relations \sphinxstylestrong{ldap\_kdc\_sasl\_mech} and similar. + +\item {} +\sphinxAtStartPar +Specify a location for the LDAP service password file by setting +\sphinxstylestrong{ldap\_service\_password\_file}. Use \sphinxcode{\sphinxupquote{kdb5\_ldap\_util stashsrvpw}} +to stash passwords for the KDC and kadmind DNs chosen above. For +example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kdb5\PYGZus{}ldap\PYGZus{}util} \PYG{n}{stashsrvpw} \PYG{o}{\PYGZhy{}}\PYG{n}{f} \PYG{o}{/}\PYG{n}{path}\PYG{o}{/}\PYG{n}{to}\PYG{o}{/}\PYG{n}{service}\PYG{o}{.}\PYG{n}{keyfile} \PYG{n}{cn}\PYG{o}{=}\PYG{n}{krbadmin}\PYG{p}{,}\PYG{n}{dc}\PYG{o}{=}\PYG{n}{example}\PYG{p}{,}\PYG{n}{dc}\PYG{o}{=}\PYG{n}{com} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Skip this step if you are using SASL authentication and the +mechanism does not require a password. + +\item {} +\sphinxAtStartPar +Choose a DN for the global Kerberos container entry (but do not +create the entry at this time). Specify this DN with the +\sphinxstylestrong{ldap\_kerberos\_container\_dn} directive in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. +Realm container entries will be created underneath this DN. +Principal entries may exist either underneath the realm container +(the default) or in separate trees referenced from the realm +container. + +\item {} +\sphinxAtStartPar +Configure the LDAP server ACLs to enable the KDC and kadmin server +DNs to read and write the Kerberos data. If +\sphinxstylestrong{disable\_last\_success} and \sphinxstylestrong{disable\_lockout} are both set to +true in the {\hyperref[\detokenize{admin/conf_files/kdc_conf:dbmodules}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}dbmodules{]}}}}} subsection for the realm, then the +KDC DN only requires read access to the Kerberos data. + +\sphinxAtStartPar +Sample access control information: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{access} \PYG{n}{to} \PYG{n}{dn}\PYG{o}{.}\PYG{n}{base}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZdq{}} + \PYG{n}{by} \PYG{o}{*} \PYG{n}{read} + +\PYG{n}{access} \PYG{n}{to} \PYG{n}{dn}\PYG{o}{.}\PYG{n}{base}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=Subschema}\PYG{l+s+s2}{\PYGZdq{}} + \PYG{n}{by} \PYG{o}{*} \PYG{n}{read} + +\PYG{c+c1}{\PYGZsh{} Provide access to the realm container.} +\PYG{n}{access} \PYG{n}{to} \PYG{n}{dn}\PYG{o}{.}\PYG{n}{subtree}\PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=EXAMPLE.COM,cn=krbcontainer,dc=example,dc=com}\PYG{l+s+s2}{\PYGZdq{}} + \PYG{n}{by} \PYG{n}{dn}\PYG{o}{.}\PYG{n}{exact}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=kdc\PYGZhy{}service,dc=example,dc=com}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{write} + \PYG{n}{by} \PYG{n}{dn}\PYG{o}{.}\PYG{n}{exact}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=adm\PYGZhy{}service,dc=example,dc=com}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{write} + \PYG{n}{by} \PYG{o}{*} \PYG{n}{none} + +\PYG{c+c1}{\PYGZsh{} Provide access to principals, if not underneath the realm container.} +\PYG{n}{access} \PYG{n}{to} \PYG{n}{dn}\PYG{o}{.}\PYG{n}{subtree}\PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{ou=users,dc=example,dc=com}\PYG{l+s+s2}{\PYGZdq{}} + \PYG{n}{by} \PYG{n}{dn}\PYG{o}{.}\PYG{n}{exact}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=kdc\PYGZhy{}service,dc=example,dc=com}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{write} + \PYG{n}{by} \PYG{n}{dn}\PYG{o}{.}\PYG{n}{exact}\PYG{o}{=}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=adm\PYGZhy{}service,dc=example,dc=com}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{write} + \PYG{n}{by} \PYG{o}{*} \PYG{n}{none} + +\PYG{n}{access} \PYG{n}{to} \PYG{o}{*} + \PYG{n}{by} \PYG{o}{*} \PYG{n}{read} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If the locations of the container and principals or the DNs of the +service objects for a realm are changed then this information +should be updated. + +\item {} +\sphinxAtStartPar +In {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}, make sure the following relations are set +in the {\hyperref[\detokenize{admin/conf_files/kdc_conf:dbmodules}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}dbmodules{]}}}}} subsection for the realm: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +db\PYGZus{}library (set to ``kldap``) +ldap\PYGZus{}kerberos\PYGZus{}container\PYGZus{}dn +ldap\PYGZus{}kdc\PYGZus{}dn +ldap\PYGZus{}kadmind\PYGZus{}dn +ldap\PYGZus{}service\PYGZus{}password\PYGZus{}file +ldap\PYGZus{}servers +\end{sphinxVerbatim} + +\item {} +\sphinxAtStartPar +Create the realm using {\hyperref[\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_ldap\_util}}}}: +\begin{quote} + +\sphinxAtStartPar +kdb5\_ldap\_util create \sphinxhyphen{}subtrees ou=users,dc=example,dc=com \sphinxhyphen{}s +\end{quote} + +\sphinxAtStartPar +Use the \sphinxstylestrong{\sphinxhyphen{}subtrees} option if the principals are to exist in a +separate subtree from the realm container. Before executing the +command, make sure that the subtree mentioned above +\sphinxcode{\sphinxupquote{(ou=users,dc=example,dc=com)}} exists. If the principals will +exist underneath the realm container, omit the \sphinxstylestrong{\sphinxhyphen{}subtrees} option +and do not worry about creating the principal subtree. + +\sphinxAtStartPar +For more information, refer to the section {\hyperref[\detokenize{admin/database:ops-on-ldap}]{\sphinxcrossref{\DUrole{std,std-ref}{Operations on the LDAP database}}}}. + +\sphinxAtStartPar +The realm object is created under the +\sphinxstylestrong{ldap\_kerberos\_container\_dn} specified in the configuration +file. This operation will also create the Kerberos container, if +not present already. This container can be used to store +information related to multiple realms. + +\item {} +\sphinxAtStartPar +Add an \sphinxcode{\sphinxupquote{eq}} index for \sphinxcode{\sphinxupquote{krbPrincipalName}} to speed up principal +lookup operations. See +\sphinxurl{https://www.openldap.org/doc/admin/tuning.html\#Indexes} for +details. + +\end{enumerate} + +\sphinxAtStartPar +With the LDAP back end it is possible to provide aliases for principal +entries. Currently we provide no administrative utilities for +creating aliases, so it must be done by direct manipulation of the +LDAP entries. + +\sphinxAtStartPar +An entry with aliases contains multiple values of the +\sphinxstyleemphasis{krbPrincipalName} attribute. Since LDAP attribute values are not +ordered, it is necessary to specify which principal name is canonical, +by using the \sphinxstyleemphasis{krbCanonicalName} attribute. Therefore, to create +aliases for an entry, first set the \sphinxstyleemphasis{krbCanonicalName} attribute of +the entry to the canonical principal name (which should be identical +to the pre\sphinxhyphen{}existing \sphinxstyleemphasis{krbPrincipalName} value), and then add additional +\sphinxstyleemphasis{krbPrincipalName} attributes for the aliases. + +\sphinxAtStartPar +Principal aliases are only returned by the KDC when the client +requests canonicalization. Canonicalization is normally requested for +service principals; for client principals, an explicit flag is often +required (e.g., \sphinxcode{\sphinxupquote{kinit \sphinxhyphen{}C}}) and canonicalization is only performed +for initial ticket requests. + + +\chapter{Application servers} +\label{\detokenize{admin/appl_servers:application-servers}}\label{\detokenize{admin/appl_servers::doc}} +\sphinxAtStartPar +If you need to install the Kerberos V5 programs on an application +server, please refer to the Kerberos V5 Installation Guide. Once you +have installed the software, you need to add that host to the Kerberos +database (see {\hyperref[\detokenize{admin/database:principals}]{\sphinxcrossref{\DUrole{std,std-ref}{Principals}}}}), and generate a keytab for that host, +that contains the host’s key. You also need to make sure the host’s +clock is within your maximum clock skew of the KDCs. + + +\section{Keytabs} +\label{\detokenize{admin/appl_servers:keytabs}} +\sphinxAtStartPar +A keytab is a host’s copy of its own keylist, which is analogous to a +user’s password. An application server that needs to authenticate +itself to the KDC has to have a keytab that contains its own principal +and key. Just as it is important for users to protect their +passwords, it is equally important for hosts to protect their keytabs. +You should always store keytab files on local disk, and make them +readable only by root, and you should never send a keytab file over a +network in the clear. Ideally, you should run the {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} +command to extract a keytab on the host on which the keytab is to +reside. + + +\subsection{Adding principals to keytabs} +\label{\detokenize{admin/appl_servers:adding-principals-to-keytabs}}\label{\detokenize{admin/appl_servers:add-princ-kt}} +\sphinxAtStartPar +To generate a keytab, or to add a principal to an existing keytab, use +the \sphinxstylestrong{ktadd} command from kadmin. Here is a sample session, using +configuration files that enable only AES encryption: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{ktadd} \PYG{n}{host}\PYG{o}{/}\PYG{n}{daffodil}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{daffodil}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{2}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{daffodil}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{2}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab} +\end{sphinxVerbatim} + + +\subsection{Removing principals from keytabs} +\label{\detokenize{admin/appl_servers:removing-principals-from-keytabs}} +\sphinxAtStartPar +To remove a principal from an existing keytab, use the kadmin +\sphinxstylestrong{ktremove} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{ktremove} \PYG{n}{host}\PYG{o}{/}\PYG{n}{daffodil}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{daffodil}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{2} \PYG{n}{removed} \PYG{k+kn}{from} \PYG{n+nn}{keytab} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{daffodil}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{2} \PYG{n}{removed} \PYG{k+kn}{from} \PYG{n+nn}{keytab} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\end{sphinxVerbatim} + + +\subsection{Using a keytab to acquire client credentials} +\label{\detokenize{admin/appl_servers:using-a-keytab-to-acquire-client-credentials}} +\sphinxAtStartPar +While keytabs are ordinarily used to accept credentials from clients, +they can also be used to acquire initial credentials, allowing one +service to authenticate to another. + +\sphinxAtStartPar +To manually obtain credentials using a keytab, use the \DUrole{xref,std,std-ref}{kinit(1)} +\sphinxstylestrong{\sphinxhyphen{}k} option, together with the \sphinxstylestrong{\sphinxhyphen{}t} option if the keytab is not in +the default location. + +\sphinxAtStartPar +Beginning with release 1.11, GSSAPI applications can be configured to +automatically obtain initial credentials from a keytab as needed. The +recommended configuration is as follows: +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +Create a keytab containing a single entry for the desired client +identity. + +\item {} +\sphinxAtStartPar +Place the keytab in a location readable by the service, and set the +\sphinxstylestrong{KRB5\_CLIENT\_KTNAME} environment variable to its filename. +Alternatively, use the \sphinxstylestrong{default\_client\_keytab\_name} profile +variable in {\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}}, or use the default location of +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{DEFCKTNAME}}}}. + +\item {} +\sphinxAtStartPar +Set \sphinxstylestrong{KRB5CCNAME} to a filename writable by the service, which +will not be used for any other purpose. Do not manually obtain +credentials at this location. (Another credential cache type +besides \sphinxstylestrong{FILE} can be used if desired, as long the cache will not +conflict with another use. A \sphinxstylestrong{MEMORY} cache can be used if the +service runs as a long\sphinxhyphen{}lived process. See \DUrole{xref,std,std-ref}{ccache\_definition} +for details.) + +\item {} +\sphinxAtStartPar +Start the service. When it authenticates using GSSAPI, it will +automatically obtain credentials from the client keytab into the +specified credential cache, and refresh them before they expire. + +\end{enumerate} + + +\section{Clock Skew} +\label{\detokenize{admin/appl_servers:clock-skew}} +\sphinxAtStartPar +A Kerberos application server host must keep its clock synchronized or +it will reject authentication requests from clients. Modern operating +systems typically provide a facility to maintain the correct time; +make sure it is enabled. This is especially important on virtual +machines, where clocks tend to drift more rapidly than normal machine +clocks. + +\sphinxAtStartPar +The default allowable clock skew is controlled by the \sphinxstylestrong{clockskew} +variable in {\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}}. + + +\section{Getting DNS information correct} +\label{\detokenize{admin/appl_servers:getting-dns-information-correct}} +\sphinxAtStartPar +Several aspects of Kerberos rely on name service. When a hostname is +used to name a service, clients may canonicalize the hostname using +forward and possibly reverse name resolution. The result of this +canonicalization must match the principal entry in the host’s keytab, +or authentication will fail. To work with all client canonicalization +configurations, each host’s canonical name must be the fully\sphinxhyphen{}qualified +host name (including the domain), and each host’s IP address must +reverse\sphinxhyphen{}resolve to the canonical name. + +\sphinxAtStartPar +Configuration of hostnames varies by operating system. On the +application server itself, canonicalization will typically use the +\sphinxcode{\sphinxupquote{/etc/hosts}} file rather than the DNS. Ensure that the line for the +server’s hostname is in the following form: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{IP} \PYG{n}{address} \PYG{n}{fully}\PYG{o}{\PYGZhy{}}\PYG{n}{qualified} \PYG{n}{hostname} \PYG{n}{aliases} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Here is a sample \sphinxcode{\sphinxupquote{/etc/hosts}} file: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{c+c1}{\PYGZsh{} this is a comment} +\PYG{l+m+mf}{127.0}\PYG{l+m+mf}{.0}\PYG{l+m+mf}{.1} \PYG{n}{localhost} \PYG{n}{localhost}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} +\PYG{l+m+mf}{10.0}\PYG{l+m+mf}{.0}\PYG{l+m+mf}{.6} \PYG{n}{daffodil}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{n}{daffodil} \PYG{n}{trillium} \PYG{n}{wake}\PYG{o}{\PYGZhy{}}\PYG{n}{robin} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The output of \sphinxcode{\sphinxupquote{klist \sphinxhyphen{}k}} for this example host should look like: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{viola}\PYG{c+c1}{\PYGZsh{} klist \PYGZhy{}k} +\PYG{n}{Keytab} \PYG{n}{name}\PYG{p}{:} \PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab} +\PYG{n}{KVNO} \PYG{n}{Principal} +\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}} \PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}} + \PYG{l+m+mi}{2} \PYG{n}{host}\PYG{o}{/}\PYG{n}{daffodil}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If you were to ssh to this host with a fresh credentials cache (ticket +file), and then \DUrole{xref,std,std-ref}{klist(1)}, the output should list a service +principal of \sphinxcode{\sphinxupquote{host/daffodil.mit.edu@ATHENA.MIT.EDU}}. + + +\section{Configuring your firewall to work with Kerberos V5} +\label{\detokenize{admin/appl_servers:configuring-your-firewall-to-work-with-kerberos-v5}}\label{\detokenize{admin/appl_servers:conf-firewall}} +\sphinxAtStartPar +If you need off\sphinxhyphen{}site users to be able to get Kerberos tickets in your +realm, they must be able to get to your KDC. This requires either +that you have a replica KDC outside your firewall, or that you +configure your firewall to allow UDP requests into at least one of +your KDCs, on whichever port the KDC is running. (The default is port +88; other ports may be specified in the KDC’s {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} +file.) Similarly, if you need off\sphinxhyphen{}site users to be able to change +their passwords in your realm, they must be able to get to your +Kerberos admin server on the kpasswd port (which defaults to 464). If +you need off\sphinxhyphen{}site users to be able to administer your Kerberos realm, +they must be able to get to your Kerberos admin server on the +administrative port (which defaults to 749). + +\sphinxAtStartPar +If your on\sphinxhyphen{}site users inside your firewall will need to get to KDCs in +other realms, you will also need to configure your firewall to allow +outgoing TCP and UDP requests to port 88, and to port 464 to allow +password changes. If your on\sphinxhyphen{}site users inside your firewall will +need to get to Kerberos admin servers in other realms, you will also +need to allow outgoing TCP and UDP requests to port 749. + +\sphinxAtStartPar +If any of your KDCs are outside your firewall, you will need to allow +kprop requests to get through to the remote KDC. {\hyperref[\detokenize{admin/admin_commands/kprop:kprop-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop}}}} uses +the \sphinxcode{\sphinxupquote{krb5\_prop}} service on port 754 (tcp). + +\sphinxAtStartPar +The book \sphinxstyleemphasis{UNIX System Security}, by David Curry, is a good starting +point for learning to configure firewalls. + + +\chapter{Host configuration} +\label{\detokenize{admin/host_config:host-configuration}}\label{\detokenize{admin/host_config::doc}} +\sphinxAtStartPar +All hosts running Kerberos software, whether they are clients, +application servers, or KDCs, can be configured using +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}. Here we describe some of the behavior changes +you might want to make. + + +\section{Default realm} +\label{\detokenize{admin/host_config:default-realm}} +\sphinxAtStartPar +In the {\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}} section, the \sphinxstylestrong{default\_realm} realm +relation sets the default Kerberos realm. For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{libdefaults}\PYG{p}{]} + \PYG{n}{default\PYGZus{}realm} \PYG{o}{=} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The default realm affects Kerberos behavior in the following ways: +\begin{itemize} +\item {} +\sphinxAtStartPar +When a principal name is parsed from text, the default realm is used +if no \sphinxcode{\sphinxupquote{@REALM}} component is specified. + +\item {} +\sphinxAtStartPar +The default realm affects login authorization as described below. + +\item {} +\sphinxAtStartPar +For programs which operate on a Kerberos database, the default realm +is used to determine which database to operate on, unless the \sphinxstylestrong{\sphinxhyphen{}r} +parameter is given to specify a realm. + +\item {} +\sphinxAtStartPar +A server program may use the default realm when looking up its key +in a {\hyperref[\detokenize{admin/install_appl_srv:keytab-file}]{\sphinxcrossref{\DUrole{std,std-ref}{keytab file}}}}, if its realm is not +determined by {\hyperref[\detokenize{admin/conf_files/krb5_conf:domain-realm}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}domain\_realm{]}}}}} configuration or by the server +program itself. + +\item {} +\sphinxAtStartPar +If \DUrole{xref,std,std-ref}{kinit(1)} is passed the \sphinxstylestrong{\sphinxhyphen{}n} flag, it requests anonymous +tickets from the default realm. + +\end{itemize} + +\sphinxAtStartPar +In some situations, these uses of the default realm might conflict. +For example, it might be desirable for principal name parsing to use +one realm by default, but for login authorization to use a second +realm. In this situation, the first realm can be configured as the +default realm, and \sphinxstylestrong{auth\_to\_local} relations can be used as +described below to use the second realm for login authorization. + + +\section{Login authorization} +\label{\detokenize{admin/host_config:login-authorization}}\label{\detokenize{admin/host_config:id1}} +\sphinxAtStartPar +If a host runs a Kerberos\sphinxhyphen{}enabled login service such as OpenSSH with +GSSAPIAuthentication enabled, login authorization rules determine +whether a Kerberos principal is allowed to access a local account. + +\sphinxAtStartPar +By default, a Kerberos principal is allowed access to an account if +its realm matches the default realm and its name matches the account +name. (For historical reasons, access is also granted by default if +the name has two components and the second component matches the +default realm; for instance, \sphinxcode{\sphinxupquote{alice/ATHENA.MIT.EDU@ATHENA.MIT.EDU}} +is granted access to the \sphinxcode{\sphinxupquote{alice}} account if \sphinxcode{\sphinxupquote{ATHENA.MIT.EDU}} is +the default realm.) + +\sphinxAtStartPar +The simplest way to control local access is using \DUrole{xref,std,std-ref}{.k5login(5)} +files. To use these, place a \sphinxcode{\sphinxupquote{.k5login}} file in the home directory +of each account listing the principal names which should have login +access to that account. If it is not desirable to use \sphinxcode{\sphinxupquote{.k5login}} +files located in account home directories, the \sphinxstylestrong{k5login\_directory} +relation in the {\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}} section can specify a directory +containing one file per account uname. + +\sphinxAtStartPar +By default, if a \sphinxcode{\sphinxupquote{.k5login}} file is present, it controls +authorization both positively and negatively\textendash{}any principal name +contained in the file is granted access and any other principal name +is denied access, even if it would have had access if the \sphinxcode{\sphinxupquote{.k5login}} +file didn’t exist. The \sphinxstylestrong{k5login\_authoritative} relation in the +{\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}} section can be set to false to make \sphinxcode{\sphinxupquote{.k5login}} +files provide positive authorization only. + +\sphinxAtStartPar +The \sphinxstylestrong{auth\_to\_local} relation in the {\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} section for the +default realm can specify pattern\sphinxhyphen{}matching rules to control login +authorization. For example, the following configuration allows access +to principals from a different realm than the default realm: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +[realms] + DEFAULT.REALM = \PYGZob{} + \PYGZsh{} Allow access to principals from OTHER.REALM. + \PYGZsh{} + \PYGZsh{} [1:\PYGZdl{}1@\PYGZdl{}0] matches single\PYGZhy{}component principal names and creates + \PYGZsh{} a selection string containing the principal name and realm. + \PYGZsh{} + \PYGZsh{} (.*@OTHER\PYGZbs{}.REALM) matches against the selection string, so that + \PYGZsh{} only principals in OTHER.REALM are matched. + \PYGZsh{} + \PYGZsh{} s/@OTHER\PYGZbs{}.REALM\PYGZdl{}// removes the realm name, leaving behind the + \PYGZsh{} principal name as the account name. + auth\PYGZus{}to\PYGZus{}local = RULE:[1:\PYGZdl{}1@\PYGZdl{}0](.*@OTHER\PYGZbs{}.REALM)s/@OTHER\PYGZbs{}.REALM\PYGZdl{}// + + \PYGZsh{} Also allow principals from the default realm. Omit this line + \PYGZsh{} to only allow access to principals in OTHER.REALM. + auth\PYGZus{}to\PYGZus{}local = DEFAULT + \PYGZcb{} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The \sphinxstylestrong{auth\_to\_local\_names} subsection of the {\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} section +for the default realm can specify explicit mappings from principal +names to local accounts. The key used in this subsection is the +principal name without realm, so it is only safe to use in a Kerberos +environment with a single realm or a tightly controlled set of realms. +An example use of \sphinxstylestrong{auth\_to\_local\_names} might be: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{realms}\PYG{p}{]} + \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{auth\PYGZus{}to\PYGZus{}local\PYGZus{}names} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{c+c1}{\PYGZsh{} Careful, these match principals in any realm!} + \PYG{n}{host}\PYG{o}{/}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com} \PYG{o}{=} \PYG{n}{hostaccount} + \PYG{n}{fred} \PYG{o}{=} \PYG{n}{localfred} + \PYG{p}{\PYGZcb{}} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Local authorization behavior can also be modified using plugin +modules; see \DUrole{xref,std,std-ref}{hostrealm\_plugin} for details. + + +\section{Plugin module configuration} +\label{\detokenize{admin/host_config:plugin-module-configuration}}\label{\detokenize{admin/host_config:plugin-config}} +\sphinxAtStartPar +Many aspects of Kerberos behavior, such as client preauthentication +and KDC service location, can be modified through the use of plugin +modules. For most of these behaviors, you can use the {\hyperref[\detokenize{admin/conf_files/krb5_conf:plugins}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}plugins{]}}}}} +section of krb5.conf to register third\sphinxhyphen{}party modules, and to switch +off registered or built\sphinxhyphen{}in modules. + +\sphinxAtStartPar +A plugin module takes the form of a Unix shared object +(\sphinxcode{\sphinxupquote{modname.so}}) or Windows DLL (\sphinxcode{\sphinxupquote{modname.dll}}). If you have +installed a third\sphinxhyphen{}party plugin module and want to register it, you do +so using the \sphinxstylestrong{module} relation in the appropriate subsection of the +{[}plugins{]} section. The value for \sphinxstylestrong{module} must give the module name +and the path to the module, separated by a colon. The module name +will often be the same as the shared object’s name, but in unusual +cases (such as a shared object which implements multiple modules for +the same interface) it might not be. For example, to register a +client preauthentication module named \sphinxcode{\sphinxupquote{mypreauth}} installed at +\sphinxcode{\sphinxupquote{/path/to/mypreauth.so}}, you could write: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{plugins}\PYG{p}{]} + \PYG{n}{clpreauth} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{module} \PYG{o}{=} \PYG{n}{mypreauth}\PYG{p}{:}\PYG{o}{/}\PYG{n}{path}\PYG{o}{/}\PYG{n}{to}\PYG{o}{/}\PYG{n}{mypreauth}\PYG{o}{.}\PYG{n}{so} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Many of the pluggable behaviors in MIT krb5 contain built\sphinxhyphen{}in modules +which can be switched off. You can disable a built\sphinxhyphen{}in module (or one +you have registered) using the \sphinxstylestrong{disable} directive in the +appropriate subsection of the {[}plugins{]} section. For example, to +disable the use of .k5identity files to select credential caches, you +could write: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{plugins}\PYG{p}{]} + \PYG{n}{ccselect} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{disable} \PYG{o}{=} \PYG{n}{k5identity} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If you want to disable multiple modules, specify the \sphinxstylestrong{disable} +directive multiple times, giving one module to disable each time. + +\sphinxAtStartPar +Alternatively, you can explicitly specify which modules you want to be +enabled for that behavior using the \sphinxstylestrong{enable\_only} directive. For +example, to make {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} check password quality using only a +module you have registered, and no other mechanism, you could write: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{plugins}\PYG{p}{]} + \PYG{n}{pwqual} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{module} \PYG{o}{=} \PYG{n}{mymodule}\PYG{p}{:}\PYG{o}{/}\PYG{n}{path}\PYG{o}{/}\PYG{n}{to}\PYG{o}{/}\PYG{n}{mymodule}\PYG{o}{.}\PYG{n}{so} + \PYG{n}{enable\PYGZus{}only} \PYG{o}{=} \PYG{n}{mymodule} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Again, if you want to specify multiple modules, specify the +\sphinxstylestrong{enable\_only} directive multiple times, giving one module to enable +each time. + +\sphinxAtStartPar +Some Kerberos interfaces use different mechanisms to register plugin +modules. + + +\subsection{KDC location modules} +\label{\detokenize{admin/host_config:kdc-location-modules}} +\sphinxAtStartPar +For historical reasons, modules to control how KDC servers are located +are registered simply by placing the shared object or DLL into the +“libkrb5” subdirectory of the krb5 plugin directory, which defaults to +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LIBDIR}}}}\sphinxcode{\sphinxupquote{/krb5/plugins}}. For example, Samba’s winbind krb5 +locator plugin would be registered by placing its shared object in +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LIBDIR}}}}\sphinxcode{\sphinxupquote{/krb5/plugins/libkrb5/winbind\_krb5\_locator.so}}. + + +\subsection{GSSAPI mechanism modules} +\label{\detokenize{admin/host_config:gssapi-mechanism-modules}}\label{\detokenize{admin/host_config:gssapi-plugin-config}} +\sphinxAtStartPar +GSSAPI mechanism modules are registered using the file +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{SYSCONFDIR}}}}\sphinxcode{\sphinxupquote{/gss/mech}} or configuration files in the +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{SYSCONFDIR}}}}\sphinxcode{\sphinxupquote{/gss/mech.d}} directory with a \sphinxcode{\sphinxupquote{.conf}} +suffix. Each line in these files has the form: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{name} \PYG{n}{oid} \PYG{n}{pathname} \PYG{p}{[}\PYG{n}{options}\PYG{p}{]} \PYG{o}{\PYGZlt{}}\PYG{n+nb}{type}\PYG{o}{\PYGZgt{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Only the name, oid, and pathname are required. \sphinxstyleemphasis{name} is the +mechanism name, which may be used for debugging or logging purposes. +\sphinxstyleemphasis{oid} is the object identifier of the GSSAPI mechanism to be +registered. \sphinxstyleemphasis{pathname} is a path to the module shared object or DLL. +\sphinxstyleemphasis{options} (if present) are options provided to the plugin module, +surrounded in square brackets. \sphinxstyleemphasis{type} (if present) can be used to +indicate a special type of module. Currently the only special module +type is “interposer”, for a module designed to intercept calls to +other mechanisms. + +\sphinxAtStartPar +If the environment variable \sphinxstylestrong{GSS\_MECH\_CONFIG} is set, its value is +used as the sole mechanism configuration filename. + + +\subsection{Configuration profile modules} +\label{\detokenize{admin/host_config:configuration-profile-modules}}\label{\detokenize{admin/host_config:profile-plugin-config}} +\sphinxAtStartPar +A configuration profile module replaces the information source for +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} itself. To use a profile module, begin krb5.conf +with the line: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{module} \PYG{n}{PATHNAME}\PYG{p}{:}\PYG{n}{STRING} +\end{sphinxVerbatim} + +\sphinxAtStartPar +where \sphinxstyleemphasis{PATHNAME} is a path to the module shared object or DLL, and +\sphinxstyleemphasis{STRING} is a string to provide to the module. The module will then +take over, and the rest of krb5.conf will be ignored. + + +\chapter{Backups of secure hosts} +\label{\detokenize{admin/backup_host:backups-of-secure-hosts}}\label{\detokenize{admin/backup_host::doc}} +\sphinxAtStartPar +When you back up a secure host, you should exclude the host’s keytab +file from the backup. If someone obtained a copy of the keytab from a +backup, that person could make any host masquerade as the host whose +keytab was compromised. In many configurations, knowledge of the +host’s keytab also allows root access to the host. This could be +particularly dangerous if the compromised keytab was from one of your +KDCs. If the machine has a disk crash and the keytab file is lost, it +is easy to generate another keytab file. (See {\hyperref[\detokenize{admin/appl_servers:add-princ-kt}]{\sphinxcrossref{\DUrole{std,std-ref}{Adding principals to keytabs}}}}.) +If you are unable to exclude particular files from backups, you should +ensure that the backups are kept as secure as the host’s root +password. + + +\section{Backing up the Kerberos database} +\label{\detokenize{admin/backup_host:backing-up-the-kerberos-database}} +\sphinxAtStartPar +As with any file, it is possible that your Kerberos database could +become corrupted. If this happens on one of the replica KDCs, you +might never notice, since the next automatic propagation of the +database would install a fresh copy. However, if it happens to the +primary KDC, the corrupted database would be propagated to all of the +replicas during the next propagation. For this reason, MIT recommends +that you back up your Kerberos database regularly. Because the primary +KDC is continuously dumping the database to a file in order to +propagate it to the replica KDCs, it is a simple matter to have a cron +job periodically copy the dump file to a secure machine elsewhere on +your network. (Of course, it is important to make the host where +these backups are stored as secure as your KDCs, and to encrypt its +transmission across your network.) Then if your database becomes +corrupted, you can load the most recent dump onto the primary KDC. +(See {\hyperref[\detokenize{admin/database:restore-from-dump}]{\sphinxcrossref{\DUrole{std,std-ref}{Dumping and loading a Kerberos database}}}}.) + + +\chapter{PKINIT configuration} +\label{\detokenize{admin/pkinit:pkinit-configuration}}\label{\detokenize{admin/pkinit:pkinit}}\label{\detokenize{admin/pkinit::doc}} +\sphinxAtStartPar +PKINIT is a preauthentication mechanism for Kerberos 5 which uses +X.509 certificates to authenticate the KDC to clients and vice versa. +PKINIT can also be used to enable anonymity support, allowing clients +to communicate securely with the KDC or with application servers +without authenticating as a particular client principal. + + +\section{Creating certificates} +\label{\detokenize{admin/pkinit:creating-certificates}} +\sphinxAtStartPar +PKINIT requires an X.509 certificate for the KDC and one for each +client principal which will authenticate using PKINIT. For anonymous +PKINIT, a KDC certificate is required, but client certificates are +not. A commercially issued server certificate can be used for the KDC +certificate, but generally cannot be used for client certificates. + +\sphinxAtStartPar +The instruction in this section describe how to establish a +certificate authority and create standard PKINIT certificates. Skip +this section if you are using a commercially issued server certificate +as the KDC certificate for anonymous PKINIT, or if you are configuring +a client to use an Active Directory KDC. + + +\subsection{Generating a certificate authority certificate} +\label{\detokenize{admin/pkinit:generating-a-certificate-authority-certificate}} +\sphinxAtStartPar +You can establish a new certificate authority (CA) for use with a +PKINIT deployment with the commands: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{openssl} \PYG{n}{genrsa} \PYG{o}{\PYGZhy{}}\PYG{n}{out} \PYG{n}{cakey}\PYG{o}{.}\PYG{n}{pem} \PYG{l+m+mi}{2048} +\PYG{n}{openssl} \PYG{n}{req} \PYG{o}{\PYGZhy{}}\PYG{n}{key} \PYG{n}{cakey}\PYG{o}{.}\PYG{n}{pem} \PYG{o}{\PYGZhy{}}\PYG{n}{new} \PYG{o}{\PYGZhy{}}\PYG{n}{x509} \PYG{o}{\PYGZhy{}}\PYG{n}{out} \PYG{n}{cacert}\PYG{o}{.}\PYG{n}{pem} \PYG{o}{\PYGZhy{}}\PYG{n}{days} \PYG{l+m+mi}{3650} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The second command will ask for the values of several certificate +fields. These fields can be set to any values. You can adjust the +expiration time of the CA certificate by changing the number after +\sphinxcode{\sphinxupquote{\sphinxhyphen{}days}}. Since the CA certificate must be deployed to client +machines each time it changes, it should normally have an expiration +time far in the future; however, expiration times after 2037 may cause +interoperability issues in rare circumstances. + +\sphinxAtStartPar +The result of these commands will be two files, cakey.pem and +cacert.pem. cakey.pem will contain a 2048\sphinxhyphen{}bit RSA private key, which +must be carefully protected. cacert.pem will contain the CA +certificate, which must be placed in the filesystems of the KDC and +each client host. cakey.pem will be required to create KDC and client +certificates. + + +\subsection{Generating a KDC certificate} +\label{\detokenize{admin/pkinit:generating-a-kdc-certificate}} +\sphinxAtStartPar +A KDC certificate for use with PKINIT is required to have some unusual +fields, which makes generating them with OpenSSL somewhat complicated. +First, you will need a file containing the following: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +[kdc\PYGZus{}cert] +basicConstraints=CA:FALSE +keyUsage=nonRepudiation,digitalSignature,keyEncipherment,keyAgreement +extendedKeyUsage=1.3.6.1.5.2.3.5 +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer +issuerAltName=issuer:copy +subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:kdc\PYGZus{}princ\PYGZus{}name + +[kdc\PYGZus{}princ\PYGZus{}name] +realm=EXP:0,GeneralString:\PYGZdl{}\PYGZob{}ENV::REALM\PYGZcb{} +principal\PYGZus{}name=EXP:1,SEQUENCE:kdc\PYGZus{}principal\PYGZus{}seq + +[kdc\PYGZus{}principal\PYGZus{}seq] +name\PYGZus{}type=EXP:0,INTEGER:2 +name\PYGZus{}string=EXP:1,SEQUENCE:kdc\PYGZus{}principals + +[kdc\PYGZus{}principals] +princ1=GeneralString:krbtgt +princ2=GeneralString:\PYGZdl{}\PYGZob{}ENV::REALM\PYGZcb{} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If the above contents are placed in extensions.kdc, you can generate +and sign a KDC certificate with the following commands: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{openssl} \PYG{n}{genrsa} \PYG{o}{\PYGZhy{}}\PYG{n}{out} \PYG{n}{kdckey}\PYG{o}{.}\PYG{n}{pem} \PYG{l+m+mi}{2048} +\PYG{n}{openssl} \PYG{n}{req} \PYG{o}{\PYGZhy{}}\PYG{n}{new} \PYG{o}{\PYGZhy{}}\PYG{n}{out} \PYG{n}{kdc}\PYG{o}{.}\PYG{n}{req} \PYG{o}{\PYGZhy{}}\PYG{n}{key} \PYG{n}{kdckey}\PYG{o}{.}\PYG{n}{pem} +\PYG{n}{env} \PYG{n}{REALM}\PYG{o}{=}\PYG{n}{YOUR\PYGZus{}REALMNAME} \PYG{n}{openssl} \PYG{n}{x509} \PYG{o}{\PYGZhy{}}\PYG{n}{req} \PYG{o}{\PYGZhy{}}\PYG{o+ow}{in} \PYG{n}{kdc}\PYG{o}{.}\PYG{n}{req} \PYGZbs{} + \PYG{o}{\PYGZhy{}}\PYG{n}{CAkey} \PYG{n}{cakey}\PYG{o}{.}\PYG{n}{pem} \PYG{o}{\PYGZhy{}}\PYG{n}{CA} \PYG{n}{cacert}\PYG{o}{.}\PYG{n}{pem} \PYG{o}{\PYGZhy{}}\PYG{n}{out} \PYG{n}{kdc}\PYG{o}{.}\PYG{n}{pem} \PYG{o}{\PYGZhy{}}\PYG{n}{days} \PYG{l+m+mi}{365} \PYGZbs{} + \PYG{o}{\PYGZhy{}}\PYG{n}{extfile} \PYG{n}{extensions}\PYG{o}{.}\PYG{n}{kdc} \PYG{o}{\PYGZhy{}}\PYG{n}{extensions} \PYG{n}{kdc\PYGZus{}cert} \PYG{o}{\PYGZhy{}}\PYG{n}{CAcreateserial} +\PYG{n}{rm} \PYG{n}{kdc}\PYG{o}{.}\PYG{n}{req} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The second command will ask for the values of certificate fields, +which can be set to any values. In the third command, substitute your +KDC’s realm name for YOUR\_REALMNAME. You can adjust the certificate’s +expiration date by changing the number after \sphinxcode{\sphinxupquote{\sphinxhyphen{}days}}. Remember to +create a new KDC certificate before the old one expires. + +\sphinxAtStartPar +The result of this operation will be in two files, kdckey.pem and +kdc.pem. Both files must be placed in the KDC’s filesystem. +kdckey.pem, which contains the KDC’s private key, must be carefully +protected. + +\sphinxAtStartPar +If you examine the KDC certificate with \sphinxcode{\sphinxupquote{openssl x509 \sphinxhyphen{}in kdc.pem +\sphinxhyphen{}text \sphinxhyphen{}noout}}, OpenSSL will not know how to display the KDC principal +name in the Subject Alternative Name extension, so it will appear as +\sphinxcode{\sphinxupquote{othername:\textless{}unsupported\textgreater{}}}. This is normal and does not mean +anything is wrong with the KDC certificate. + + +\subsection{Generating client certificates} +\label{\detokenize{admin/pkinit:generating-client-certificates}} +\sphinxAtStartPar +PKINIT client certificates also must have some unusual certificate +fields. To generate a client certificate with OpenSSL for a +single\sphinxhyphen{}component principal name, you will need an extensions file +(different from the KDC extensions file above) containing: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +[client\PYGZus{}cert] +basicConstraints=CA:FALSE +keyUsage=digitalSignature,keyEncipherment,keyAgreement +extendedKeyUsage=1.3.6.1.5.2.3.4 +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer +issuerAltName=issuer:copy +subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:princ\PYGZus{}name + +[princ\PYGZus{}name] +realm=EXP:0,GeneralString:\PYGZdl{}\PYGZob{}ENV::REALM\PYGZcb{} +principal\PYGZus{}name=EXP:1,SEQUENCE:principal\PYGZus{}seq + +[principal\PYGZus{}seq] +name\PYGZus{}type=EXP:0,INTEGER:1 +name\PYGZus{}string=EXP:1,SEQUENCE:principals + +[principals] +princ1=GeneralString:\PYGZdl{}\PYGZob{}ENV::CLIENT\PYGZcb{} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If the above contents are placed in extensions.client, you can +generate and sign a client certificate with the following commands: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{openssl} \PYG{n}{genrsa} \PYG{o}{\PYGZhy{}}\PYG{n}{out} \PYG{n}{clientkey}\PYG{o}{.}\PYG{n}{pem} \PYG{l+m+mi}{2048} +\PYG{n}{openssl} \PYG{n}{req} \PYG{o}{\PYGZhy{}}\PYG{n}{new} \PYG{o}{\PYGZhy{}}\PYG{n}{key} \PYG{n}{clientkey}\PYG{o}{.}\PYG{n}{pem} \PYG{o}{\PYGZhy{}}\PYG{n}{out} \PYG{n}{client}\PYG{o}{.}\PYG{n}{req} +\PYG{n}{env} \PYG{n}{REALM}\PYG{o}{=}\PYG{n}{YOUR\PYGZus{}REALMNAME} \PYG{n}{CLIENT}\PYG{o}{=}\PYG{n}{YOUR\PYGZus{}PRINCNAME} \PYG{n}{openssl} \PYG{n}{x509} \PYGZbs{} + \PYG{o}{\PYGZhy{}}\PYG{n}{CAkey} \PYG{n}{cakey}\PYG{o}{.}\PYG{n}{pem} \PYG{o}{\PYGZhy{}}\PYG{n}{CA} \PYG{n}{cacert}\PYG{o}{.}\PYG{n}{pem} \PYG{o}{\PYGZhy{}}\PYG{n}{req} \PYG{o}{\PYGZhy{}}\PYG{o+ow}{in} \PYG{n}{client}\PYG{o}{.}\PYG{n}{req} \PYGZbs{} + \PYG{o}{\PYGZhy{}}\PYG{n}{extensions} \PYG{n}{client\PYGZus{}cert} \PYG{o}{\PYGZhy{}}\PYG{n}{extfile} \PYG{n}{extensions}\PYG{o}{.}\PYG{n}{client} \PYGZbs{} + \PYG{o}{\PYGZhy{}}\PYG{n}{days} \PYG{l+m+mi}{365} \PYG{o}{\PYGZhy{}}\PYG{n}{out} \PYG{n}{client}\PYG{o}{.}\PYG{n}{pem} +\PYG{n}{rm} \PYG{n}{client}\PYG{o}{.}\PYG{n}{req} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Normally, the first two commands should be run on the client host, and +the resulting client.req file transferred to the certificate authority +host for the third command. As in the previous steps, the second +command will ask for the values of certificate fields, which can be +set to any values. In the third command, substitute your realm’s name +for YOUR\_REALMNAME and the client’s principal name (without realm) for +YOUR\_PRINCNAME. You can adjust the certificate’s expiration date by +changing the number after \sphinxcode{\sphinxupquote{\sphinxhyphen{}days}}. + +\sphinxAtStartPar +The result of this operation will be two files, clientkey.pem and +client.pem. Both files must be present on the client’s host; +clientkey.pem, which contains the client’s private key, must be +protected from access by others. + +\sphinxAtStartPar +As in the KDC certificate, OpenSSL will display the client principal +name as \sphinxcode{\sphinxupquote{othername:\textless{}unsupported\textgreater{}}} in the Subject Alternative Name +extension of a PKINIT client certificate. + +\sphinxAtStartPar +If the client principal name contains more than one component +(e.g. \sphinxcode{\sphinxupquote{host/example.com@REALM}}), the \sphinxcode{\sphinxupquote{{[}principals{]}}} section of +\sphinxcode{\sphinxupquote{extensions.client}} must be altered to contain multiple entries. +(Simply setting \sphinxcode{\sphinxupquote{CLIENT}} to \sphinxcode{\sphinxupquote{host/example.com}} would generate a +certificate for \sphinxcode{\sphinxupquote{host\textbackslash{}/example.com@REALM}} which would not match the +multi\sphinxhyphen{}component principal name.) For a two\sphinxhyphen{}component principal, the +section should read: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +[principals] +princ1=GeneralString:\PYGZdl{}\PYGZob{}ENV::CLIENT1\PYGZcb{} +princ2=GeneralString:\PYGZdl{}\PYGZob{}ENV::CLIENT2\PYGZcb{} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The environment variables \sphinxcode{\sphinxupquote{CLIENT1}} and \sphinxcode{\sphinxupquote{CLIENT2}} must then be set +to the first and second components when running \sphinxcode{\sphinxupquote{openssl x509}}. + + +\section{Configuring the KDC} +\label{\detokenize{admin/pkinit:configuring-the-kdc}} +\sphinxAtStartPar +The KDC must have filesystem access to the KDC certificate (kdc.pem) +and the KDC private key (kdckey.pem). Configure the following +relation in the KDC’s {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} file, either in the +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdcdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}kdcdefaults{]}}}}} section or in a {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} subsection (with +appropriate pathnames): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{pkinit\PYGZus{}identity} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{var}\PYG{o}{/}\PYG{n}{lib}\PYG{o}{/}\PYG{n}{krb5kdc}\PYG{o}{/}\PYG{n}{kdc}\PYG{o}{.}\PYG{n}{pem}\PYG{p}{,}\PYG{o}{/}\PYG{n}{var}\PYG{o}{/}\PYG{n}{lib}\PYG{o}{/}\PYG{n}{krb5kdc}\PYG{o}{/}\PYG{n}{kdckey}\PYG{o}{.}\PYG{n}{pem} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If any clients will authenticate using regular (as opposed to +anonymous) PKINIT, the KDC must also have filesystem access to the CA +certificate (cacert.pem), and the following configuration (with the +appropriate pathname): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{pkinit\PYGZus{}anchors} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{var}\PYG{o}{/}\PYG{n}{lib}\PYG{o}{/}\PYG{n}{krb5kdc}\PYG{o}{/}\PYG{n}{cacert}\PYG{o}{.}\PYG{n}{pem} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Because of the larger size of requests and responses using PKINIT, you +may also need to allow TCP access to the KDC: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kdc\PYGZus{}tcp\PYGZus{}listen} \PYG{o}{=} \PYG{l+m+mi}{88} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Restart the {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} daemon to pick up the configuration +changes. + +\sphinxAtStartPar +The principal entry for each PKINIT\sphinxhyphen{}using client must be configured to +require preauthentication. Ensure this with the command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin} \PYG{o}{\PYGZhy{}}\PYG{n}{q} \PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{modprinc +requires\PYGZus{}preauth YOUR\PYGZus{}PRINCNAME}\PYG{l+s+s1}{\PYGZsq{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Starting with release 1.12, it is possible to remove the long\sphinxhyphen{}term +keys of a principal entry, which can save some space in the database +and help to clarify some PKINIT\sphinxhyphen{}related error conditions by not asking +for a password: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin} \PYG{o}{\PYGZhy{}}\PYG{n}{q} \PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{purgekeys \PYGZhy{}all YOUR\PYGZus{}PRINCNAME}\PYG{l+s+s1}{\PYGZsq{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +These principal options can also be specified at principal creation +time as follows: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin} \PYG{o}{\PYGZhy{}}\PYG{n}{q} \PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{add\PYGZus{}principal +requires\PYGZus{}preauth \PYGZhy{}nokey YOUR\PYGZus{}PRINCNAME}\PYG{l+s+s1}{\PYGZsq{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +By default, the KDC requires PKINIT client certificates to have the +standard Extended Key Usage and Subject Alternative Name attributes +for PKINIT. Starting in release 1.16, it is possible to authorize +client certificates based on the subject or other criteria instead of +the standard PKINIT Subject Alternative Name, by setting the +\sphinxstylestrong{pkinit\_cert\_match} string attribute on each client principal entry. +For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin} \PYG{n}{set\PYGZus{}string} \PYG{n}{user}\PYG{n+nd}{@REALM} \PYG{n}{pkinit\PYGZus{}cert\PYGZus{}match} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZlt{}SUBJECT\PYGZgt{}CN=user@REALM\PYGZdl{}}\PYG{l+s+s2}{\PYGZdq{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The \sphinxstylestrong{pkinit\_cert\_match} string attribute follows the syntax used by +the {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} \sphinxstylestrong{pkinit\_cert\_match} relation. To allow the +use of non\sphinxhyphen{}PKINIT client certificates, it will also be necessary to +disable key usage checking using the \sphinxstylestrong{pkinit\_eku\_checking} relation; +for example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{kdcdefaults}\PYG{p}{]} + \PYG{n}{pkinit\PYGZus{}eku\PYGZus{}checking} \PYG{o}{=} \PYG{n}{none} +\end{sphinxVerbatim} + + +\section{Configuring the clients} +\label{\detokenize{admin/pkinit:configuring-the-clients}} +\sphinxAtStartPar +Client hosts must be configured to trust the issuing authority for the +KDC certificate. For a newly established certificate authority, the +client host must have filesystem access to the CA certificate +(cacert.pem) and the following relation in {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} in the +appropriate {\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} subsection (with appropriate pathnames): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{pkinit\PYGZus{}anchors} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{/}\PYG{n}{cacert}\PYG{o}{.}\PYG{n}{pem} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If the KDC certificate is a commercially issued server certificate, +the issuing certificate is most likely included in a system directory. +You can specify it by filename as above, or specify the whole +directory like so: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{pkinit\PYGZus{}anchors} \PYG{o}{=} \PYG{n}{DIR}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{ssl}\PYG{o}{/}\PYG{n}{certs} +\end{sphinxVerbatim} + +\sphinxAtStartPar +A commercially issued server certificate will usually not have the +standard PKINIT principal name or Extended Key Usage extensions, so +the following additional configuration is required: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{pkinit\PYGZus{}eku\PYGZus{}checking} \PYG{o}{=} \PYG{n}{kpServerAuth} +\PYG{n}{pkinit\PYGZus{}kdc\PYGZus{}hostname} \PYG{o}{=} \PYG{n}{hostname}\PYG{o}{.}\PYG{n}{of}\PYG{o}{.}\PYG{n}{kdc}\PYG{o}{.}\PYG{n}{certificate} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Multiple \sphinxstylestrong{pkinit\_kdc\_hostname} relations can be configured to +recognize multiple KDC certificates. If the KDC is an Active +Directory domain controller, setting \sphinxstylestrong{pkinit\_kdc\_hostname} is +necessary, but it should not be necessary to set +\sphinxstylestrong{pkinit\_eku\_checking}. + +\sphinxAtStartPar +To perform regular (as opposed to anonymous) PKINIT authentication, a +client host must have filesystem access to a client certificate +(client.pem), and the corresponding private key (clientkey.pem). +Configure the following relations in the client host’s +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} file in the appropriate {\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} subsection +(with appropriate pathnames): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{pkinit\PYGZus{}identities} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{/}\PYG{n}{client}\PYG{o}{.}\PYG{n}{pem}\PYG{p}{,}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{/}\PYG{n}{clientkey}\PYG{o}{.}\PYG{n}{pem} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If the KDC and client are properly configured, it should now be +possible to run \sphinxcode{\sphinxupquote{kinit username}} without entering a password. + + +\section{Anonymous PKINIT} +\label{\detokenize{admin/pkinit:anonymous-pkinit}}\label{\detokenize{admin/pkinit:id1}} +\sphinxAtStartPar +Anonymity support in Kerberos allows a client to obtain a ticket +without authenticating as any particular principal. Such a ticket can +be used as a FAST armor ticket, or to securely communicate with an +application server anonymously. + +\sphinxAtStartPar +To configure anonymity support, you must generate or otherwise procure +a KDC certificate and configure the KDC host, but you do not need to +generate any client certificates. On the KDC, you must set the +\sphinxstylestrong{pkinit\_identity} variable to provide the KDC certificate, but do +not need to set the \sphinxstylestrong{pkinit\_anchors} variable or store the issuing +certificate if you won’t have any client certificates to verify. On +client hosts, you must set the \sphinxstylestrong{pkinit\_anchors} variable (and +possibly \sphinxstylestrong{pkinit\_kdc\_hostname} and \sphinxstylestrong{pkinit\_eku\_checking}) in order +to trust the issuing authority for the KDC certificate, but do not +need to set the \sphinxstylestrong{pkinit\_identities} variable. + +\sphinxAtStartPar +Anonymity support is not enabled by default. To enable it, you must +create the principal \sphinxcode{\sphinxupquote{WELLKNOWN/ANONYMOUS}} using the command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin} \PYG{o}{\PYGZhy{}}\PYG{n}{q} \PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{addprinc \PYGZhy{}randkey WELLKNOWN/ANONYMOUS}\PYG{l+s+s1}{\PYGZsq{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Some Kerberos deployments include application servers which lack +proper access control, and grant some level of access to any user who +can authenticate. In such an environment, enabling anonymity support +on the KDC would present a security issue. If you need to enable +anonymity support for TGTs (for use as FAST armor tickets) without +enabling anonymous authentication to application servers, you can set +the variable \sphinxstylestrong{restrict\_anonymous\_to\_tgt} to \sphinxcode{\sphinxupquote{true}} in the +appropriate {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} subsection of the KDC’s +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} file. + +\sphinxAtStartPar +To obtain anonymous credentials on a client, run \sphinxcode{\sphinxupquote{kinit \sphinxhyphen{}n}}, or +\sphinxcode{\sphinxupquote{kinit \sphinxhyphen{}n @REALMNAME}} to specify a realm. The resulting tickets +will have the client name \sphinxcode{\sphinxupquote{WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS}}. + + +\section{Freshness tokens} +\label{\detokenize{admin/pkinit:freshness-tokens}} +\sphinxAtStartPar +Freshness tokens can ensure that the client has recently had access to +its certificate private key. If freshness tokens are not required by +the KDC, a client program with temporary possession of the private key +can compose requests for future timestamps and use them later. + +\sphinxAtStartPar +In release 1.17 and later, freshness tokens are supported by the +client and are sent by the KDC when the client indicates support for +them. Because not all clients support freshness tokens yet, they are +not required by default. To check if freshness tokens are supported +by a realm’s clients, look in the KDC logs for the lines: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{PKINIT}\PYG{p}{:} \PYG{n}{freshness} \PYG{n}{token} \PYG{n}{received} \PYG{k+kn}{from} \PYG{o}{\PYGZlt{}}\PYG{n}{client} \PYG{n}{principal}\PYG{o}{\PYGZgt{}} +\PYG{n}{PKINIT}\PYG{p}{:} \PYG{n}{no} \PYG{n}{freshness} \PYG{n}{token} \PYG{n}{received} \PYG{k+kn}{from} \PYG{o}{\PYGZlt{}}\PYG{n}{client} \PYG{n}{principal}\PYG{o}{\PYGZgt{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +To require freshness tokens for all clients in a realm (except for +clients authenticating anonymously), set the +\sphinxstylestrong{pkinit\_require\_freshness} variable to \sphinxcode{\sphinxupquote{true}} in the appropriate +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} subsection of the KDC’s {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} file. To +test that this option is in effect, run \sphinxcode{\sphinxupquote{kinit \sphinxhyphen{}X disable\_freshness}} +and verify that authentication is unsuccessful. + + +\chapter{OTP Preauthentication} +\label{\detokenize{admin/otp:otp-preauthentication}}\label{\detokenize{admin/otp:otp-preauth}}\label{\detokenize{admin/otp::doc}} +\sphinxAtStartPar +OTP is a preauthentication mechanism for Kerberos 5 which uses One +Time Passwords (OTP) to authenticate the client to the KDC. The OTP +is passed to the KDC over an encrypted FAST channel in clear\sphinxhyphen{}text. +The KDC uses the password along with per\sphinxhyphen{}user configuration to proxy +the request to a third\sphinxhyphen{}party RADIUS system. This enables +out\sphinxhyphen{}of\sphinxhyphen{}the\sphinxhyphen{}box compatibility with a large number of already widely +deployed proprietary systems. + +\sphinxAtStartPar +Additionally, our implementation of the OTP system allows for the +passing of RADIUS requests over a UNIX domain stream socket. This +permits the use of a local companion daemon which can handle the +details of authentication. + + +\section{Defining token types} +\label{\detokenize{admin/otp:defining-token-types}} +\sphinxAtStartPar +Token types are defined in either {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} or +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} according to the following format: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{otp}\PYG{p}{]} + \PYG{o}{\PYGZlt{}}\PYG{n}{name}\PYG{o}{\PYGZgt{}} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{server} \PYG{o}{=} \PYG{o}{\PYGZlt{}}\PYG{n}{host}\PYG{p}{:}\PYG{n}{port} \PYG{o+ow}{or} \PYG{n}{filename}\PYG{o}{\PYGZgt{}} \PYG{p}{(}\PYG{n}{default}\PYG{p}{:} \PYG{n}{see} \PYG{n}{below}\PYG{p}{)} + \PYG{n}{secret} \PYG{o}{=} \PYG{o}{\PYGZlt{}}\PYG{n}{filename}\PYG{o}{\PYGZgt{}} + \PYG{n}{timeout} \PYG{o}{=} \PYG{o}{\PYGZlt{}}\PYG{n}{integer}\PYG{o}{\PYGZgt{}} \PYG{p}{(}\PYG{n}{default}\PYG{p}{:} \PYG{l+m+mi}{5} \PYG{p}{[}\PYG{n}{seconds}\PYG{p}{]}\PYG{p}{)} + \PYG{n}{retries} \PYG{o}{=} \PYG{o}{\PYGZlt{}}\PYG{n}{integer}\PYG{o}{\PYGZgt{}} \PYG{p}{(}\PYG{n}{default}\PYG{p}{:} \PYG{l+m+mi}{3}\PYG{p}{)} + \PYG{n}{strip\PYGZus{}realm} \PYG{o}{=} \PYG{o}{\PYGZlt{}}\PYG{n}{boolean}\PYG{o}{\PYGZgt{}} \PYG{p}{(}\PYG{n}{default}\PYG{p}{:} \PYG{n}{true}\PYG{p}{)} + \PYG{n}{indicator} \PYG{o}{=} \PYG{o}{\PYGZlt{}}\PYG{n}{string}\PYG{o}{\PYGZgt{}} \PYG{p}{(}\PYG{n}{default}\PYG{p}{:} \PYG{n}{none}\PYG{p}{)} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If the server field begins with ‘/’, it will be interpreted as a UNIX +socket. Otherwise, it is assumed to be in the format host:port. When +a UNIX domain socket is specified, the secret field is optional and an +empty secret is used by default. If the server field is not +specified, it defaults to {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{RUNSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/\textless{}name\textgreater{}.socket}}. + +\sphinxAtStartPar +When forwarding the request over RADIUS, by default the principal is +used in the User\sphinxhyphen{}Name attribute of the RADIUS packet. The strip\_realm +parameter controls whether the principal is forwarded with or without +the realm portion. + +\sphinxAtStartPar +If an indicator field is present, tickets issued using this token type +will be annotated with the specified authentication indicator (see +{\hyperref[\detokenize{admin/auth_indicator:auth-indicator}]{\sphinxcrossref{\DUrole{std,std-ref}{Authentication indicators}}}}). This key may be specified multiple times to +add multiple indicators. + + +\section{The default token type} +\label{\detokenize{admin/otp:the-default-token-type}} +\sphinxAtStartPar +A default token type is used internally when no token type is specified for a +given user. It is defined as follows: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{otp}\PYG{p}{]} + \PYG{n}{DEFAULT} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{strip\PYGZus{}realm} \PYG{o}{=} \PYG{n}{false} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The administrator may override the internal \sphinxcode{\sphinxupquote{DEFAULT}} token type +simply by defining a configuration with the same name. + + +\section{Token instance configuration} +\label{\detokenize{admin/otp:token-instance-configuration}} +\sphinxAtStartPar +To enable OTP for a client principal, the administrator must define +the \sphinxstylestrong{otp} string attribute for that principal. (See +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:set-string}]{\sphinxcrossref{\DUrole{std,std-ref}{set\_string}}}}.) The \sphinxstylestrong{otp} user string is a JSON string of the +format: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +[\PYGZob{} + \PYGZdq{}type\PYGZdq{}: \PYG{n+nt}{\PYGZlt{}string}\PYG{n+nt}{\PYGZgt{}}, + \PYGZdq{}username\PYGZdq{}: \PYG{n+nt}{\PYGZlt{}string}\PYG{n+nt}{\PYGZgt{}}, + \PYGZdq{}indicators\PYGZdq{}: [\PYG{n+nt}{\PYGZlt{}string}\PYG{n+nt}{\PYGZgt{}}, ...] + \PYGZcb{}, ...] +\end{sphinxVerbatim} + +\sphinxAtStartPar +This is an array of token objects. Both fields of token objects are +optional. The \sphinxstylestrong{type} field names the token type of this token; if +not specified, it defaults to \sphinxcode{\sphinxupquote{DEFAULT}}. The \sphinxstylestrong{username} field +specifies the value to be sent in the User\sphinxhyphen{}Name RADIUS attribute. If +not specified, the principal name is sent, with or without realm as +defined in the token type. The \sphinxstylestrong{indicators} field specifies a list +of authentication indicators to annotate tickets with, overriding any +indicators specified in the token type. + +\sphinxAtStartPar +For ease of configuration, an empty array (\sphinxcode{\sphinxupquote{{[}{]}}}) is treated as +equivalent to one DEFAULT token (\sphinxcode{\sphinxupquote{{[}\{\}{]}}}). + + +\section{Other considerations} +\label{\detokenize{admin/otp:other-considerations}}\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +FAST is required for OTP to work. + +\end{enumerate} + + +\chapter{SPAKE Preauthentication} +\label{\detokenize{admin/spake:spake-preauthentication}}\label{\detokenize{admin/spake:spake}}\label{\detokenize{admin/spake::doc}} +\sphinxAtStartPar +SPAKE preauthentication (added in release 1.17) uses public key +cryptography techniques to protect against {\hyperref[\detokenize{admin/dictionary:dictionary}]{\sphinxcrossref{\DUrole{std,std-ref}{password dictionary +attacks}}}}. Unlike {\hyperref[\detokenize{admin/pkinit:pkinit}]{\sphinxcrossref{\DUrole{std,std-ref}{PKINIT}}}}, it does not +require any additional infrastructure such as certificates; it simply +needs to be turned on. Using SPAKE preauthentication may modestly +increase the CPU and network load on the KDC. + +\sphinxAtStartPar +SPAKE preauthentication can use one of four elliptic curve groups for +its password\sphinxhyphen{}authenticated key exchange. The recommended group is +\sphinxcode{\sphinxupquote{edwards25519}}; three NIST curves (\sphinxcode{\sphinxupquote{P\sphinxhyphen{}256}}, \sphinxcode{\sphinxupquote{P\sphinxhyphen{}384}}, and +\sphinxcode{\sphinxupquote{P\sphinxhyphen{}521}}) are also supported. + +\sphinxAtStartPar +By default, SPAKE with the \sphinxcode{\sphinxupquote{edwards25519}} group is enabled on +clients, but the KDC does not offer SPAKE by default. To turn it on, +set the \sphinxstylestrong{spake\_preauth\_groups} variable in {\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}} to a +list of allowed groups. This variable affects both the client and the +KDC. Simply setting it to \sphinxcode{\sphinxupquote{edwards25519}} is recommended: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{libdefaults}\PYG{p}{]} + \PYG{n}{spake\PYGZus{}preauth\PYGZus{}groups} \PYG{o}{=} \PYG{n}{edwards25519} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Set the \sphinxstylestrong{+requires\_preauth} and \sphinxstylestrong{\sphinxhyphen{}allow\_svr} flags on client +principal entries, as you would for any preauthentication mechanism: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{modprinc} \PYG{o}{+}\PYG{n}{requires\PYGZus{}preauth} \PYG{o}{\PYGZhy{}}\PYG{n}{allow\PYGZus{}svr} \PYG{n}{PRINCNAME} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Clients which do not implement SPAKE preauthentication will fall back +to encrypted timestamp. + +\sphinxAtStartPar +An active attacker can force a fallback to encrypted timestamp by +modifying the initial KDC response, defeating the protection against +dictionary attacks. To prevent this fallback on clients which do +implement SPAKE preauthentication, set the +\sphinxstylestrong{disable\_encrypted\_timestamp} variable to \sphinxcode{\sphinxupquote{true}} in the +{\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} subsection for realms whose KDCs offer SPAKE +preauthentication. + +\sphinxAtStartPar +By default, SPAKE preauthentication requires an extra network round +trip to the KDC during initial authentication. If most of the clients +in a realm support SPAKE, this extra round trip can be eliminated +using an optimistic challenge, by setting the +\sphinxstylestrong{spake\_preauth\_kdc\_challenge} variable in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdcdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}kdcdefaults{]}}}}} to a +single group name: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{kdcdefaults}\PYG{p}{]} + \PYG{n}{spake\PYGZus{}preauth\PYGZus{}kdc\PYGZus{}challenge} \PYG{o}{=} \PYG{n}{edwards25519} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Using optimistic challenge will cause the KDC to do extra work for +initial authentication requests that do not result in SPAKE +preauthentication, but will save work when SPAKE preauthentication is +used. + + +\chapter{Addressing dictionary attack risks} +\label{\detokenize{admin/dictionary:addressing-dictionary-attack-risks}}\label{\detokenize{admin/dictionary:dictionary}}\label{\detokenize{admin/dictionary::doc}} +\sphinxAtStartPar +Kerberos initial authentication is normally secured using the client +principal’s long\sphinxhyphen{}term key, which for users is generally derived from a +password. Using a pasword\sphinxhyphen{}derived long\sphinxhyphen{}term key carries the risk of a +dictionary attack, where an attacker tries a sequence of possible +passwords, possibly requiring much less effort than would be required +to try all possible values of the key. Even if {\hyperref[\detokenize{admin/database:policies}]{\sphinxcrossref{\DUrole{std,std-ref}{password policy +objects}}}} are used to force users not to pick trivial +passwords, dictionary attacks can sometimes be successful against a +significant fraction of the users in a realm. Dictionary attacks are +not a concern for principals using random keys. + +\sphinxAtStartPar +A dictionary attack may be online or offline. An online dictionary +attack is performed by trying each password in a separate request to +the KDC, and is therefore visible to the KDC and also limited in speed +by the KDC’s processing power and the network capacity between the +client and the KDC. Online dictionary attacks can be mitigated using +{\hyperref[\detokenize{admin/lockout:lockout}]{\sphinxcrossref{\DUrole{std,std-ref}{account lockout}}}}. This measure is not totally +satisfactory, as it makes it easy for an attacker to deny access to a +client principal. + +\sphinxAtStartPar +An offline dictionary attack is performed by obtaining a ciphertext +generated using the password\sphinxhyphen{}derived key, and trying each password +against the ciphertext. This category of attack is invisible to the +KDC and can be performed much faster than an online attack. The +attack will generally take much longer with more recent encryption +types (particularly the ones based on AES), because those encryption +types use a much more expensive string\sphinxhyphen{}to\sphinxhyphen{}key function. However, the +best defense is to deny the attacker access to a useful ciphertext. +The required defensive measures depend on the attacker’s level of +network access. + +\sphinxAtStartPar +An off\sphinxhyphen{}path attacker has no access to packets sent between legitimate +users and the KDC. An off\sphinxhyphen{}path attacker could gain access to an +attackable ciphertext either by making an AS request for a client +principal which does not have the \sphinxstylestrong{+requires\_preauth} flag, or by +making a TGS request (after authenticating as a different user) for a +server principal which does not have the \sphinxstylestrong{\sphinxhyphen{}allow\_svr} flag. To +address off\sphinxhyphen{}path attackers, a KDC administrator should set those flags +on principals with password\sphinxhyphen{}derived keys: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{add\PYGZus{}principal} \PYG{o}{+}\PYG{n}{requires\PYGZus{}preauth} \PYG{o}{\PYGZhy{}}\PYG{n}{allow\PYGZus{}svr} \PYG{n}{princname} +\end{sphinxVerbatim} + +\sphinxAtStartPar +An attacker with passive network access (one who can monitor packets +sent between legitimate users and the KDC, but cannot change them or +insert their own packets) can gain access to an attackable ciphertext +by observing an authentication by a user using the most common form of +preauthentication, encrypted timestamp. Any of the following methods +can prevent dictionary attacks by attackers with passive network +access: +\begin{itemize} +\item {} +\sphinxAtStartPar +Enabling {\hyperref[\detokenize{admin/spake:spake}]{\sphinxcrossref{\DUrole{std,std-ref}{SPAKE preauthentication}}}} (added in release +1.17) on the KDC, and ensuring that all clients are able to support +it. + +\item {} +\sphinxAtStartPar +Using an {\hyperref[\detokenize{admin/https:https}]{\sphinxcrossref{\DUrole{std,std-ref}{HTTPS proxy}}}} for communication with the KDC, +if the attacker cannot monitor communication between the proxy +server and the KDC. + +\item {} +\sphinxAtStartPar +Using FAST, protecting the initial authentication with either a +random key (such as a host key) or with {\hyperref[\detokenize{admin/pkinit:anonymous-pkinit}]{\sphinxcrossref{\DUrole{std,std-ref}{anonymous PKINIT}}}}. + +\end{itemize} + +\sphinxAtStartPar +An attacker with active network access (one who can inject or modify +packets sent between legitimate users and the KDC) can try to fool the +client software into sending an attackable ciphertext using an +encryption type and salt string of the attacker’s choosing. Any of the +following methods can prevent dictionary attacks by active attackers: +\begin{itemize} +\item {} +\sphinxAtStartPar +Enabling SPAKE preauthentication and setting the +\sphinxstylestrong{disable\_encrypted\_timestamp} variable to \sphinxcode{\sphinxupquote{true}} in the +{\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} subsection of the client configuration. + +\item {} +\sphinxAtStartPar +Using an HTTPS proxy as described above, configured in the client’s +krb5.conf realm configuration. If {\hyperref[\detokenize{admin/realm_config:kdc-discovery}]{\sphinxcrossref{\DUrole{std,std-ref}{KDC discovery}}}} is used to locate a proxy server, an active +attacker may be able to use DNS spoofing to cause the client to use +a different HTTPS server or to not use HTTPS. + +\item {} +\sphinxAtStartPar +Using FAST as described above. + +\end{itemize} + +\sphinxAtStartPar +If {\hyperref[\detokenize{admin/pkinit:pkinit}]{\sphinxcrossref{\DUrole{std,std-ref}{PKINIT}}}} or {\hyperref[\detokenize{admin/otp:otp-preauth}]{\sphinxcrossref{\DUrole{std,std-ref}{OTP}}}} are used for +initial authentication, the principal’s long\sphinxhyphen{}term keys are not used +and dictionary attacks are usually not a concern. + + +\chapter{Principal names and DNS} +\label{\detokenize{admin/princ_dns:principal-names-and-dns}}\label{\detokenize{admin/princ_dns::doc}} +\sphinxAtStartPar +Kerberos clients can do DNS lookups to canonicalize service principal +names. This can cause difficulties when setting up Kerberos +application servers, especially when the client’s name for the service +is different from what the service thinks its name is. + + +\section{Service principal names} +\label{\detokenize{admin/princ_dns:service-principal-names}} +\sphinxAtStartPar +A frequently used kind of principal name is the host\sphinxhyphen{}based service +principal name. This kind of principal name has two components: a +service name and a hostname. For example, \sphinxcode{\sphinxupquote{imap/imap.example.com}} +is the principal name of the “imap” service on the host +“imap.example.com”. Other possible service names for the first +component include “host” (remote login services such as ssh), “HTTP”, +and “nfs” (Network File System). + +\sphinxAtStartPar +Service administrators often publish well\sphinxhyphen{}known hostname aliases that +they would prefer users to use instead of the canonical name of the +service host. This gives service administrators more flexibility in +deploying services. For example, a shell login server might be named +“long\sphinxhyphen{}vanity\sphinxhyphen{}hostname.example.com”, but users will naturally prefer to +type something like “login.example.com”. Hostname aliases also allow +for administrators to set up load balancing for some sorts of services +based on rotating \sphinxcode{\sphinxupquote{CNAME}} records in DNS. + + +\section{Service principal canonicalization} +\label{\detokenize{admin/princ_dns:service-principal-canonicalization}} +\sphinxAtStartPar +In the MIT krb5 client library, canonicalization of host\sphinxhyphen{}based service +principals is controlled by the \sphinxstylestrong{dns\_canonicalize\_hostname}, +\sphinxstylestrong{rnds}, and \sphinxstylestrong{qualify\_shortname} variables in {\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}}. + +\sphinxAtStartPar +If \sphinxstylestrong{dns\_canonicalize\_hostname} is set to \sphinxcode{\sphinxupquote{true}} (the default +value), the client performs forward resolution by looking up the IPv4 +and/or IPv6 addresses of the hostname using \sphinxcode{\sphinxupquote{getaddrinfo()}}. This +process will typically add a domain suffix to the hostname if needed, +and follow CNAME records in the DNS. If \sphinxstylestrong{rdns} is also set to +\sphinxcode{\sphinxupquote{true}} (the default), the client will then perform a reverse lookup +of the first returned Internet address using \sphinxcode{\sphinxupquote{getnameinfo()}}, +finding the name associated with the PTR record. + +\sphinxAtStartPar +If \sphinxstylestrong{dns\_canonicalize\_hostname} is set to \sphinxcode{\sphinxupquote{false}}, the hostname is +not canonicalized using DNS. If the hostname has only one component +(i.e. it contains no “.” characters), the host’s primary DNS search +domain will be appended, if there is one. The \sphinxstylestrong{qualify\_shortname} +variable can be used to override or disable this suffix. + +\sphinxAtStartPar +If \sphinxstylestrong{dns\_canonicalize\_hostname} is set to \sphinxcode{\sphinxupquote{fallback}} (added in +release 1.18), the hostname is initially treated according to the +rules for \sphinxcode{\sphinxupquote{dns\_canonicalize\_hostname=false}}. If a ticket request +fails because the service principal is unknown, the hostname will be +canonicalized according to the rules for +\sphinxcode{\sphinxupquote{dns\_canonicalize\_hostname=true}} and the request will be retried. + +\sphinxAtStartPar +In all cases, the hostname is converted to lowercase, and any trailing +dot is removed. + + +\section{Reverse DNS mismatches} +\label{\detokenize{admin/princ_dns:reverse-dns-mismatches}} +\sphinxAtStartPar +Sometimes, an enterprise will have control over its forward DNS but +not its reverse DNS. The reverse DNS is sometimes under the control +of the Internet service provider of the enterprise, and the enterprise +may not have much influence in setting up reverse DNS records for its +address space. If there are difficulties with getting forward and +reverse DNS to match, it is best to set \sphinxcode{\sphinxupquote{rdns = false}} on client +machines. + + +\section{Overriding application behavior} +\label{\detokenize{admin/princ_dns:overriding-application-behavior}} +\sphinxAtStartPar +Applications can choose to use a default hostname component in their +service principal name when accepting authentication, which avoids +some sorts of hostname mismatches. Because not all relevant +applications do this yet, using the {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} setting: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{libdefaults}\PYG{p}{]} + \PYG{n}{ignore\PYGZus{}acceptor\PYGZus{}hostname} \PYG{o}{=} \PYG{n}{true} +\end{sphinxVerbatim} + +\sphinxAtStartPar +will allow the Kerberos library to override the application’s choice +of service principal hostname and will allow a server program to +accept incoming authentications using any key in its keytab that +matches the service name and realm name (if given). This setting +defaults to “false” and is available in releases krb5\sphinxhyphen{}1.10 and later. + + +\section{Provisioning keytabs} +\label{\detokenize{admin/princ_dns:provisioning-keytabs}} +\sphinxAtStartPar +One service principal entry that should be in the keytab is a +principal whose hostname component is the canonical hostname that +\sphinxcode{\sphinxupquote{getaddrinfo()}} reports for all known aliases for the host. If the +reverse DNS information does not match this canonical hostname, an +additional service principal entry should be in the keytab for this +different hostname. + + +\section{Specific application advice} +\label{\detokenize{admin/princ_dns:specific-application-advice}} + +\subsection{Secure shell (ssh)} +\label{\detokenize{admin/princ_dns:secure-shell-ssh}} +\sphinxAtStartPar +Setting \sphinxcode{\sphinxupquote{GSSAPIStrictAcceptorCheck = no}} in the configuration file +of modern versions of the openssh daemon will allow the daemon to try +any key in its keytab when accepting a connection, rather than looking +for the keytab entry that matches the host’s own idea of its name +(typically the name that \sphinxcode{\sphinxupquote{gethostname()}} returns). This requires +krb5\sphinxhyphen{}1.10 or later. + + +\subsection{OpenLDAP (ldapsearch, etc.)} +\label{\detokenize{admin/princ_dns:openldap-ldapsearch-etc}} +\sphinxAtStartPar +OpenLDAP’s SASL implementation performs reverse DNS lookup in order to +canonicalize service principal names, even if \sphinxstylestrong{rdns} is set to +\sphinxcode{\sphinxupquote{false}} in the Kerberos configuration. To disable this behavior, +add \sphinxcode{\sphinxupquote{SASL\_NOCANON on}} to \sphinxcode{\sphinxupquote{ldap.conf}}, or set the +\sphinxcode{\sphinxupquote{LDAPSASL\_NOCANON}} environment variable. + + +\chapter{Encryption types} +\label{\detokenize{admin/enctypes:encryption-types}}\label{\detokenize{admin/enctypes:enctypes}}\label{\detokenize{admin/enctypes::doc}} +\sphinxAtStartPar +Kerberos can use a variety of cipher algorithms to protect data. A +Kerberos \sphinxstylestrong{encryption type} (also known as an \sphinxstylestrong{enctype}) is a +specific combination of a cipher algorithm with an integrity algorithm +to provide both confidentiality and integrity to data. + + +\section{Enctypes in requests} +\label{\detokenize{admin/enctypes:enctypes-in-requests}} +\sphinxAtStartPar +Clients make two types of requests (KDC\sphinxhyphen{}REQ) to the KDC: AS\sphinxhyphen{}REQs and +TGS\sphinxhyphen{}REQs. The client uses the AS\sphinxhyphen{}REQ to obtain initial tickets +(typically a Ticket\sphinxhyphen{}Granting Ticket (TGT)), and uses the TGS\sphinxhyphen{}REQ to +obtain service tickets. + +\sphinxAtStartPar +The KDC uses three different keys when issuing a ticket to a client: +\begin{itemize} +\item {} +\sphinxAtStartPar +The long\sphinxhyphen{}term key of the service: the KDC uses this to encrypt the +actual service ticket. The KDC only uses the first long\sphinxhyphen{}term key in +the most recent kvno for this purpose. + +\item {} +\sphinxAtStartPar +The session key: the KDC randomly chooses this key and places one +copy inside the ticket and the other copy inside the encrypted part +of the reply. + +\item {} +\sphinxAtStartPar +The reply\sphinxhyphen{}encrypting key: the KDC uses this to encrypt the reply it +sends to the client. For AS replies, this is a long\sphinxhyphen{}term key of the +client principal. For TGS replies, this is either the session key of the +authenticating ticket, or a subsession key. + +\end{itemize} + +\sphinxAtStartPar +Each of these keys is of a specific enctype. + +\sphinxAtStartPar +Each request type allows the client to submit a list of enctypes that +it is willing to accept. For the AS\sphinxhyphen{}REQ, this list affects both the +session key selection and the reply\sphinxhyphen{}encrypting key selection. For the +TGS\sphinxhyphen{}REQ, this list only affects the session key selection. + + +\section{Session key selection} +\label{\detokenize{admin/enctypes:session-key-selection}}\label{\detokenize{admin/enctypes:id1}} +\sphinxAtStartPar +The KDC chooses the session key enctype by taking the intersection of +its \sphinxstylestrong{permitted\_enctypes} list, the list of long\sphinxhyphen{}term keys for the +most recent kvno of the service, and the client’s requested list of +enctypes. Starting in krb5\sphinxhyphen{}1.21, all services are assumed to support +aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96; also, des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1 and arcfour\sphinxhyphen{}hmac session +keys will not be issued by default. + +\sphinxAtStartPar +Starting in krb5\sphinxhyphen{}1.11, it is possible to set a string attribute on a +service principal to control what session key enctypes the KDC may +issue for service tickets for that principal, overriding the service’s +long\sphinxhyphen{}term keys and the assumption of aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96 support. +See {\hyperref[\detokenize{admin/admin_commands/kadmin_local:set-string}]{\sphinxcrossref{\DUrole{std,std-ref}{set\_string}}}} in {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} for details. + + +\section{Choosing enctypes for a service} +\label{\detokenize{admin/enctypes:choosing-enctypes-for-a-service}} +\sphinxAtStartPar +Generally, a service should have a key of the strongest +enctype that both it and the KDC support. If the KDC is running a +release earlier than krb5\sphinxhyphen{}1.11, it is also useful to generate an +additional key for each enctype that the service can support. The KDC +will only use the first key in the list of long\sphinxhyphen{}term keys for encrypting +the service ticket, but the additional long\sphinxhyphen{}term keys indicate the +other enctypes that the service supports. + +\sphinxAtStartPar +As noted above, starting with release krb5\sphinxhyphen{}1.11, there are additional +configuration settings that control session key enctype selection +independently of the set of long\sphinxhyphen{}term keys that the KDC has stored for +a service principal. + + +\section{Configuration variables} +\label{\detokenize{admin/enctypes:configuration-variables}} +\sphinxAtStartPar +The following \sphinxcode{\sphinxupquote{{[}libdefaults{]}}} settings in {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} will +affect how enctypes are chosen. +\begin{description} +\item[{\sphinxstylestrong{allow\_weak\_crypto}}] \leavevmode +\sphinxAtStartPar +defaults to \sphinxstyleemphasis{false} starting with krb5\sphinxhyphen{}1.8. When \sphinxstyleemphasis{false}, removes +weak enctypes from \sphinxstylestrong{permitted\_enctypes}, +\sphinxstylestrong{default\_tkt\_enctypes}, and \sphinxstylestrong{default\_tgs\_enctypes}. Do not +set this to \sphinxstyleemphasis{true} unless the use of weak enctypes is an +acceptable risk for your environment and the weak enctypes are +required for backward compatibility. + +\item[{\sphinxstylestrong{allow\_des3}}] \leavevmode +\sphinxAtStartPar +was added in release 1.21 and defaults to \sphinxstyleemphasis{false}. Unless this +flag is set to \sphinxstyleemphasis{true}, the KDC will not issue tickets with +des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1 session keys. In a future release, this flag will +control whether des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1 is permitted in similar fashion to +weak enctypes. + +\item[{\sphinxstylestrong{allow\_rc4}}] \leavevmode +\sphinxAtStartPar +was added in release 1.21 and defaults to \sphinxstyleemphasis{false}. Unless this +flag is set to \sphinxstyleemphasis{true}, the KDC will not issue tickets with +arcfour\sphinxhyphen{}hmac session keys. In a future release, this flag will +control whether arcfour\sphinxhyphen{}hmac is permitted in similar fashion to +weak enctypes. + +\item[{\sphinxstylestrong{permitted\_enctypes}}] \leavevmode +\sphinxAtStartPar +controls the set of enctypes that a service will permit for +session keys and for ticket and authenticator encryption. The KDC +and other programs that access the Kerberos database will ignore +keys of non\sphinxhyphen{}permitted enctypes. Starting in release 1.18, this +setting also acts as the default for \sphinxstylestrong{default\_tkt\_enctypes} and +\sphinxstylestrong{default\_tgs\_enctypes}. + +\item[{\sphinxstylestrong{default\_tkt\_enctypes}}] \leavevmode +\sphinxAtStartPar +controls the default set of enctypes that the Kerberos client +library requests when making an AS\sphinxhyphen{}REQ. Do not set this unless +required for specific backward compatibility purposes; stale +values of this setting can prevent clients from taking advantage +of new stronger enctypes when the libraries are upgraded. + +\item[{\sphinxstylestrong{default\_tgs\_enctypes}}] \leavevmode +\sphinxAtStartPar +controls the default set of enctypes that the Kerberos client +library requests when making a TGS\sphinxhyphen{}REQ. Do not set this unless +required for specific backward compatibility purposes; stale +values of this setting can prevent clients from taking advantage +of new stronger enctypes when the libraries are upgraded. + +\end{description} + +\sphinxAtStartPar +The following per\sphinxhyphen{}realm setting in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} affects the +generation of long\sphinxhyphen{}term keys. +\begin{description} +\item[{\sphinxstylestrong{supported\_enctypes}}] \leavevmode +\sphinxAtStartPar +controls the default set of enctype\sphinxhyphen{}salttype pairs that {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} +will use for generating long\sphinxhyphen{}term keys, either randomly or from +passwords + +\end{description} + + +\section{Enctype compatibility} +\label{\detokenize{admin/enctypes:enctype-compatibility}} +\sphinxAtStartPar +See {\hyperref[\detokenize{admin/conf_files/kdc_conf:encryption-types}]{\sphinxcrossref{\DUrole{std,std-ref}{Encryption types}}}} for additional information about enctypes. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|T|T|} +\hline +\sphinxstyletheadfamily +\sphinxAtStartPar +enctype +&\sphinxstyletheadfamily +\sphinxAtStartPar +weak? +&\sphinxstyletheadfamily +\sphinxAtStartPar +krb5 +&\sphinxstyletheadfamily +\sphinxAtStartPar +Windows +\\ +\hline +\sphinxAtStartPar +des\sphinxhyphen{}cbc\sphinxhyphen{}crc +& +\sphinxAtStartPar +weak +& +\sphinxAtStartPar +\textless{}1.18 +& +\sphinxAtStartPar +\textgreater{}=2000 +\\ +\hline +\sphinxAtStartPar +des\sphinxhyphen{}cbc\sphinxhyphen{}md4 +& +\sphinxAtStartPar +weak +& +\sphinxAtStartPar +\textless{}1.18 +& +\sphinxAtStartPar +? +\\ +\hline +\sphinxAtStartPar +des\sphinxhyphen{}cbc\sphinxhyphen{}md5 +& +\sphinxAtStartPar +weak +& +\sphinxAtStartPar +\textless{}1.18 +& +\sphinxAtStartPar +\textgreater{}=2000 +\\ +\hline +\sphinxAtStartPar +des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1 +& +\sphinxAtStartPar +deprecated +& +\sphinxAtStartPar +\textgreater{}=1.1 +& +\sphinxAtStartPar +none +\\ +\hline +\sphinxAtStartPar +arcfour\sphinxhyphen{}hmac +& +\sphinxAtStartPar +deprecated +& +\sphinxAtStartPar +\textgreater{}=1.3 +& +\sphinxAtStartPar +\textgreater{}=2000 +\\ +\hline +\sphinxAtStartPar +arcfour\sphinxhyphen{}hmac\sphinxhyphen{}exp +& +\sphinxAtStartPar +weak +& +\sphinxAtStartPar +\textgreater{}=1.3 +& +\sphinxAtStartPar +\textgreater{}=2000 +\\ +\hline +\sphinxAtStartPar +aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96 +&& +\sphinxAtStartPar +\textgreater{}=1.3 +& +\sphinxAtStartPar +\textgreater{}=Vista +\\ +\hline +\sphinxAtStartPar +aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96 +&& +\sphinxAtStartPar +\textgreater{}=1.3 +& +\sphinxAtStartPar +\textgreater{}=Vista +\\ +\hline +\sphinxAtStartPar +aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha256\sphinxhyphen{}128 +&& +\sphinxAtStartPar +\textgreater{}=1.15 +& +\sphinxAtStartPar +none +\\ +\hline +\sphinxAtStartPar +aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha384\sphinxhyphen{}192 +&& +\sphinxAtStartPar +\textgreater{}=1.15 +& +\sphinxAtStartPar +none +\\ +\hline +\sphinxAtStartPar +camellia128\sphinxhyphen{}cts\sphinxhyphen{}cmac +&& +\sphinxAtStartPar +\textgreater{}=1.9 +& +\sphinxAtStartPar +none +\\ +\hline +\sphinxAtStartPar +camellia256\sphinxhyphen{}cts\sphinxhyphen{}cmac +&& +\sphinxAtStartPar +\textgreater{}=1.9 +& +\sphinxAtStartPar +none +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + +\sphinxAtStartPar +krb5 releases 1.18 and later do not support single\sphinxhyphen{}DES. krb5 releases +1.8 and later disable the single\sphinxhyphen{}DES enctypes by default. Microsoft +Windows releases Windows 7 and later disable single\sphinxhyphen{}DES enctypes by +default. + +\sphinxAtStartPar +krb5 releases 1.17 and later flag deprecated encryption types +(including \sphinxcode{\sphinxupquote{des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1}} and \sphinxcode{\sphinxupquote{arcfour\sphinxhyphen{}hmac}}) in KDC logs and +kadmin output. krb5 release 1.19 issues a warning during initial +authentication if \sphinxcode{\sphinxupquote{des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1}} is used. Future releases will +disable \sphinxcode{\sphinxupquote{des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1}} by default and eventually remove support for +it. + + +\section{Migrating away from older encryption types} +\label{\detokenize{admin/enctypes:migrating-away-from-older-encryption-types}} +\sphinxAtStartPar +Administrator intervention may be required to migrate a realm away +from legacy encryption types, especially if the realm was created +using krb5 release 1.2 or earlier. This migration should be performed +before upgrading to krb5 versions which disable or remove support for +legacy encryption types. + +\sphinxAtStartPar +If there is a \sphinxstylestrong{supported\_enctypes} setting in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} on +the KDC, make sure that it does not include weak or deprecated +encryption types. This will ensure that newly created keys do not use +those encryption types by default. + +\sphinxAtStartPar +Check the \sphinxcode{\sphinxupquote{krbtgt/REALM}} principal using the {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} +\sphinxstylestrong{getprinc} command. If it lists a weak or deprecated encryption +type as the first key, it must be migrated using the procedure in +{\hyperref[\detokenize{admin/database:changing-krbtgt-key}]{\sphinxcrossref{\DUrole{std,std-ref}{Changing the krbtgt key}}}}. + +\sphinxAtStartPar +Check the \sphinxcode{\sphinxupquote{kadmin/history}} principal, which should have only one key +entry. If it uses a weak or deprecated encryption type, it should be +upgraded following the notes in {\hyperref[\detokenize{admin/database:updating-history-key}]{\sphinxcrossref{\DUrole{std,std-ref}{Updating the history key}}}}. + +\sphinxAtStartPar +Check the other kadmin principals: kadmin/changepw, kadmin/admin, and +any kadmin/hostname principals that may exist. These principals can +be upgraded with \sphinxstylestrong{change\_password \sphinxhyphen{}randkey} in kadmin. + +\sphinxAtStartPar +Check the \sphinxcode{\sphinxupquote{K/M}} entry. If it uses a weak or deprecated encryption +type, it should be upgraded following the procedure in +{\hyperref[\detokenize{admin/database:updating-master-key}]{\sphinxcrossref{\DUrole{std,std-ref}{Updating the master key}}}}. + +\sphinxAtStartPar +User and service principals using legacy encryption types can be +enumerated with the {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} \sphinxstylestrong{tabdump keyinfo} command. + +\sphinxAtStartPar +Service principals can be migrated with a keytab rotation on the +service host, which can be accomplished using the {\hyperref[\detokenize{admin/admin_commands/k5srvutil:k5srvutil-1}]{\sphinxcrossref{\DUrole{std,std-ref}{k5srvutil}}}} +\sphinxstylestrong{change} and \sphinxstylestrong{delold} commands. Allow enough time for existing +tickets to expire between the change and delold operations. + +\sphinxAtStartPar +User principals with password\sphinxhyphen{}based keys can be migrated with a +password change. The realm administrator can set a password +expiration date using the {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} \sphinxstylestrong{modify\_principal +\sphinxhyphen{}pwexpire} command to force a password change. + +\sphinxAtStartPar +If a legacy encryption type has not yet been disabled by default in +the version of krb5 running on the KDC, it can be disabled +administratively with the \sphinxstylestrong{permitted\_enctypes} variable. For +example, setting \sphinxstylestrong{permitted\_enctypes} to \sphinxcode{\sphinxupquote{DEFAULT \sphinxhyphen{}des3 \sphinxhyphen{}rc4}} will +cause any database keys of the triple\sphinxhyphen{}DES and RC4 encryption types to +be ignored. + + +\chapter{HTTPS proxy configuration} +\label{\detokenize{admin/https:https-proxy-configuration}}\label{\detokenize{admin/https:https}}\label{\detokenize{admin/https::doc}} +\sphinxAtStartPar +In addition to being able to use UDP or TCP to communicate directly +with a KDC as is outlined in RFC4120, and with kpasswd services in a +similar fashion, the client libraries can attempt to use an HTTPS +proxy server to communicate with a KDC or kpasswd service, using the +protocol outlined in {[}MS\sphinxhyphen{}KKDCP{]}. + +\sphinxAtStartPar +Communicating with a KDC through an HTTPS proxy allows clients to +contact servers when network firewalls might otherwise prevent them +from doing so. The use of TLS also encrypts all traffic between the +clients and the KDC, preventing observers from conducting password +dictionary attacks or from observing the client and server principals +being authenticated, at additional computational cost to both clients +and servers. + +\sphinxAtStartPar +An HTTPS proxy server is provided as a feature in some versions of +Microsoft Windows Server, and a WSGI implementation named \sphinxtitleref{kdcproxy} +is available in the python package index. + + +\section{Configuring the clients} +\label{\detokenize{admin/https:configuring-the-clients}} +\sphinxAtStartPar +To use an HTTPS proxy, a client host must trust the CA which issued +that proxy’s SSL certificate. If that CA’s certificate is not in the +system\sphinxhyphen{}wide default set of trusted certificates, configure the +following relation in the client host’s {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} file in +the appropriate {\hyperref[\detokenize{admin/conf_files/krb5_conf:realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} subsection: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{http\PYGZus{}anchors} \PYG{o}{=} \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{/}\PYG{n}{cacert}\PYG{o}{.}\PYG{n}{pem} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Adjust the pathname to match the path of the file which contains a +copy of the CA’s certificate. The \sphinxtitleref{http\_anchors} option is documented +more fully in {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}. + +\sphinxAtStartPar +Configure the client to access the KDC and kpasswd service by +specifying their locations in its {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} file in the form +of HTTPS URLs for the proxy server: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kdc} \PYG{o}{=} \PYG{n}{https}\PYG{p}{:}\PYG{o}{/}\PYG{o}{/}\PYG{n}{server}\PYG{o}{.}\PYG{n}{fqdn}\PYG{o}{/}\PYG{n}{KdcProxy} +\PYG{n}{kpasswd\PYGZus{}server} \PYG{o}{=} \PYG{n}{https}\PYG{p}{:}\PYG{o}{/}\PYG{o}{/}\PYG{n}{server}\PYG{o}{.}\PYG{n}{fqdn}\PYG{o}{/}\PYG{n}{KdcProxy} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If the proxy and client are properly configured, client commands such +as \sphinxcode{\sphinxupquote{kinit}}, \sphinxcode{\sphinxupquote{kvno}}, and \sphinxcode{\sphinxupquote{kpasswd}} should all function normally. + + +\chapter{Authentication indicators} +\label{\detokenize{admin/auth_indicator:authentication-indicators}}\label{\detokenize{admin/auth_indicator:auth-indicator}}\label{\detokenize{admin/auth_indicator::doc}} +\sphinxAtStartPar +As of release 1.14, the KDC can be configured to annotate tickets if +the client authenticated using a stronger preauthentication mechanism +such as {\hyperref[\detokenize{admin/pkinit:pkinit}]{\sphinxcrossref{\DUrole{std,std-ref}{PKINIT}}}} or {\hyperref[\detokenize{admin/otp:otp-preauth}]{\sphinxcrossref{\DUrole{std,std-ref}{OTP}}}}. These +annotations are called “authentication indicators.” Service +principals can be configured to require particular authentication +indicators in order to authenticate to that service. An +authentication indicator value can be any string chosen by the KDC +administrator; there are no pre\sphinxhyphen{}set values. + +\sphinxAtStartPar +To use authentication indicators with PKINIT or OTP, first configure +the KDC to include an indicator when that preauthentication mechanism +is used. For PKINIT, use the \sphinxstylestrong{pkinit\_indicator} variable in +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. For OTP, use the \sphinxstylestrong{indicator} variable in the +token type definition, or specify the indicators in the \sphinxstylestrong{otp} user +string as described in {\hyperref[\detokenize{admin/otp:otp-preauth}]{\sphinxcrossref{\DUrole{std,std-ref}{OTP Preauthentication}}}}. + +\sphinxAtStartPar +To require an indicator to be present in order to authenticate to a +service principal, set the \sphinxstylestrong{require\_auth} string attribute on the +principal to the indicator value to be required. If you wish to allow +one of several indicators to be accepted, you can specify multiple +indicator values separated by spaces. + +\sphinxAtStartPar +For example, a realm could be configured to set the authentication +indicator value “strong” when PKINIT is used to authenticate, using a +setting in the {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-realms}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}realms{]}}}}} subsection: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{pkinit\PYGZus{}indicator} \PYG{o}{=} \PYG{n}{strong} +\end{sphinxVerbatim} + +\sphinxAtStartPar +A service principal could be configured to require the “strong” +authentication indicator value: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kadmin setstr host/high.value.server require\PYGZus{}auth strong +Password for user/admin@KRBTEST.COM: +\end{sphinxVerbatim} + +\sphinxAtStartPar +A user who authenticates with PKINIT would be able to obtain a ticket +for the service principal: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kinit \PYGZhy{}X X509\PYGZus{}user\PYGZus{}identity=FILE:/my/cert.pem,/my/key.pem user +\PYGZdl{} kvno host/high.value.server +host/high.value.server@KRBTEST.COM: kvno = 1 +\end{sphinxVerbatim} + +\sphinxAtStartPar +but a user who authenticates with a password would not: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kinit user +Password for user@KRBTEST.COM: +\PYGZdl{} kvno host/high.value.server +kvno: KDC policy rejects request while getting credentials for + host/high.value.server@KRBTEST.COM +\end{sphinxVerbatim} + +\sphinxAtStartPar +GSSAPI server applications can inspect authentication indicators +through the \DUrole{xref,std,std-ref}{auth\sphinxhyphen{}indicators} name +attribute. + + +\chapter{Administration programs} +\label{\detokenize{admin/admin_commands/index:administration-programs}}\label{\detokenize{admin/admin_commands/index::doc}} + +\section{kadmin} +\label{\detokenize{admin/admin_commands/kadmin_local:kadmin}}\label{\detokenize{admin/admin_commands/kadmin_local:kadmin-1}}\label{\detokenize{admin/admin_commands/kadmin_local::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{admin/admin_commands/kadmin_local:synopsis}}\phantomsection\label{\detokenize{admin/admin_commands/kadmin_local:kadmin-synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{kadmin} +{[}\sphinxstylestrong{\sphinxhyphen{}O}|\sphinxstylestrong{\sphinxhyphen{}N}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{principal}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}q} \sphinxstyleemphasis{query}{]} +{[}{[}\sphinxstylestrong{\sphinxhyphen{}c} \sphinxstyleemphasis{cache\_name}{]}|{[}\sphinxstylestrong{\sphinxhyphen{}k} {[}\sphinxstylestrong{\sphinxhyphen{}t} \sphinxstyleemphasis{keytab}{]}{]}|\sphinxstylestrong{\sphinxhyphen{}n}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}w} \sphinxstyleemphasis{password}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}s} \sphinxstyleemphasis{admin\_server}{[}:\sphinxstyleemphasis{port}{]}{]} +{[}command args…{]} + +\sphinxAtStartPar +\sphinxstylestrong{kadmin.local} +{[}\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{principal}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}q} \sphinxstyleemphasis{query}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}d} \sphinxstyleemphasis{dbname}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{enc}:\sphinxstyleemphasis{salt} …{]} +{[}\sphinxstylestrong{\sphinxhyphen{}m}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}x} \sphinxstyleemphasis{db\_args}{]} +{[}command args…{]} + + +\subsection{DESCRIPTION} +\label{\detokenize{admin/admin_commands/kadmin_local:description}} +\sphinxAtStartPar +kadmin and kadmin.local are command\sphinxhyphen{}line interfaces to the Kerberos V5 +administration system. They provide nearly identical functionalities; +the difference is that kadmin.local directly accesses the KDC +database, while kadmin performs operations using {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}}. +Except as explicitly noted otherwise, this man page will use “kadmin” +to refer to both versions. kadmin provides for the maintenance of +Kerberos principals, password policies, and service key tables +(keytabs). + +\sphinxAtStartPar +The remote kadmin client uses Kerberos to authenticate to kadmind +using the service principal \sphinxcode{\sphinxupquote{kadmin/admin}} or \sphinxcode{\sphinxupquote{kadmin/ADMINHOST}} +(where \sphinxstyleemphasis{ADMINHOST} is the fully\sphinxhyphen{}qualified hostname of the admin +server). If the credentials cache contains a ticket for one of these +principals, and the \sphinxstylestrong{\sphinxhyphen{}c} credentials\_cache option is specified, that +ticket is used to authenticate to kadmind. Otherwise, the \sphinxstylestrong{\sphinxhyphen{}p} and +\sphinxstylestrong{\sphinxhyphen{}k} options are used to specify the client Kerberos principal name +used to authenticate. Once kadmin has determined the principal name, +it requests a service ticket from the KDC, and uses that service +ticket to authenticate to kadmind. + +\sphinxAtStartPar +Since kadmin.local directly accesses the KDC database, it usually must +be run directly on the primary KDC with sufficient permissions to read +the KDC database. If the KDC database uses the LDAP database module, +kadmin.local can be run on any host which can access the LDAP server. + + +\subsection{OPTIONS} +\label{\detokenize{admin/admin_commands/kadmin_local:options}}\phantomsection\label{\detokenize{admin/admin_commands/kadmin_local:kadmin-options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm}}] \leavevmode +\sphinxAtStartPar +Use \sphinxstyleemphasis{realm} as the default database realm. + +\item[{\sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{principal}}] \leavevmode +\sphinxAtStartPar +Use \sphinxstyleemphasis{principal} to authenticate. Otherwise, kadmin will append +\sphinxcode{\sphinxupquote{/admin}} to the primary principal name of the default ccache, +the value of the \sphinxstylestrong{USER} environment variable, or the username as +obtained with getpwuid, in order of preference. + +\item[{\sphinxstylestrong{\sphinxhyphen{}k}}] \leavevmode +\sphinxAtStartPar +Use a keytab to decrypt the KDC response instead of prompting for +a password. In this case, the default principal will be +\sphinxcode{\sphinxupquote{host/hostname}}. If there is no keytab specified with the +\sphinxstylestrong{\sphinxhyphen{}t} option, then the default keytab will be used. + +\item[{\sphinxstylestrong{\sphinxhyphen{}t} \sphinxstyleemphasis{keytab}}] \leavevmode +\sphinxAtStartPar +Use \sphinxstyleemphasis{keytab} to decrypt the KDC response. This can only be used +with the \sphinxstylestrong{\sphinxhyphen{}k} option. + +\item[{\sphinxstylestrong{\sphinxhyphen{}n}}] \leavevmode +\sphinxAtStartPar +Requests anonymous processing. Two types of anonymous principals +are supported. For fully anonymous Kerberos, configure PKINIT on +the KDC and configure \sphinxstylestrong{pkinit\_anchors} in the client’s +{\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}. Then use the \sphinxstylestrong{\sphinxhyphen{}n} option with a principal +of the form \sphinxcode{\sphinxupquote{@REALM}} (an empty principal name followed by the +at\sphinxhyphen{}sign and a realm name). If permitted by the KDC, an anonymous +ticket will be returned. A second form of anonymous tickets is +supported; these realm\sphinxhyphen{}exposed tickets hide the identity of the +client but not the client’s realm. For this mode, use \sphinxcode{\sphinxupquote{kinit +\sphinxhyphen{}n}} with a normal principal name. If supported by the KDC, the +principal (but not realm) will be replaced by the anonymous +principal. As of release 1.8, the MIT Kerberos KDC only supports +fully anonymous operation. + +\item[{\sphinxstylestrong{\sphinxhyphen{}c} \sphinxstyleemphasis{credentials\_cache}}] \leavevmode +\sphinxAtStartPar +Use \sphinxstyleemphasis{credentials\_cache} as the credentials cache. The cache +should contain a service ticket for the \sphinxcode{\sphinxupquote{kadmin/admin}} or +\sphinxcode{\sphinxupquote{kadmin/ADMINHOST}} (where \sphinxstyleemphasis{ADMINHOST} is the fully\sphinxhyphen{}qualified +hostname of the admin server) service; it can be acquired with the +\DUrole{xref,std,std-ref}{kinit(1)} program. If this option is not specified, kadmin +requests a new service ticket from the KDC, and stores it in its +own temporary ccache. + +\item[{\sphinxstylestrong{\sphinxhyphen{}w} \sphinxstyleemphasis{password}}] \leavevmode +\sphinxAtStartPar +Use \sphinxstyleemphasis{password} instead of prompting for one. Use this option with +care, as it may expose the password to other users on the system +via the process list. + +\item[{\sphinxstylestrong{\sphinxhyphen{}q} \sphinxstyleemphasis{query}}] \leavevmode +\sphinxAtStartPar +Perform the specified query and then exit. + +\item[{\sphinxstylestrong{\sphinxhyphen{}d} \sphinxstyleemphasis{dbname}}] \leavevmode +\sphinxAtStartPar +Specifies the name of the KDC database. This option does not +apply to the LDAP database module. + +\item[{\sphinxstylestrong{\sphinxhyphen{}s} \sphinxstyleemphasis{admin\_server}{[}:\sphinxstyleemphasis{port}{]}}] \leavevmode +\sphinxAtStartPar +Specifies the admin server which kadmin should contact. + +\item[{\sphinxstylestrong{\sphinxhyphen{}m}}] \leavevmode +\sphinxAtStartPar +If using kadmin.local, prompt for the database master password +instead of reading it from a stash file. + +\item[{\sphinxstylestrong{\sphinxhyphen{}e} “\sphinxstyleemphasis{enc}:\sphinxstyleemphasis{salt} …”}] \leavevmode +\sphinxAtStartPar +Sets the keysalt list to be used for any new keys created. See +{\hyperref[\detokenize{admin/conf_files/kdc_conf:keysalt-lists}]{\sphinxcrossref{\DUrole{std,std-ref}{Keysalt lists}}}} in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} for a list of possible +values. + +\item[{\sphinxstylestrong{\sphinxhyphen{}O}}] \leavevmode +\sphinxAtStartPar +Force use of old AUTH\_GSSAPI authentication flavor. + +\item[{\sphinxstylestrong{\sphinxhyphen{}N}}] \leavevmode +\sphinxAtStartPar +Prevent fallback to AUTH\_GSSAPI authentication flavor. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x} \sphinxstyleemphasis{db\_args}}] \leavevmode +\sphinxAtStartPar +Specifies the database specific arguments. See the next section +for supported options. + +\end{description} + +\sphinxAtStartPar +Starting with release 1.14, if any command\sphinxhyphen{}line arguments remain after +the options, they will be treated as a single query to be executed. +This mode of operation is intended for scripts and behaves differently +from the interactive mode in several respects: +\begin{itemize} +\item {} +\sphinxAtStartPar +Query arguments are split by the shell, not by kadmin. + +\item {} +\sphinxAtStartPar +Informational and warning messages are suppressed. Error messages +and query output (e.g. for \sphinxstylestrong{get\_principal}) will still be +displayed. + +\item {} +\sphinxAtStartPar +Confirmation prompts are disabled (as if \sphinxstylestrong{\sphinxhyphen{}force} was given). +Password prompts will still be issued as required. + +\item {} +\sphinxAtStartPar +The exit status will be non\sphinxhyphen{}zero if the query fails. + +\end{itemize} + +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}q} option does not carry these behavior differences; the query +will be processed as if it was entered interactively. The \sphinxstylestrong{\sphinxhyphen{}q} +option cannot be used in combination with a query in the remaining +arguments. + + +\subsection{DATABASE OPTIONS} +\label{\detokenize{admin/admin_commands/kadmin_local:database-options}}\label{\detokenize{admin/admin_commands/kadmin_local:dboptions}} +\sphinxAtStartPar +Database options can be used to override database\sphinxhyphen{}specific defaults. +Supported options for the DB2 module are: +\begin{quote} +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}x dbname=}*filename*}] \leavevmode +\sphinxAtStartPar +Specifies the base filename of the DB2 database. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x lockiter}}] \leavevmode +\sphinxAtStartPar +Make iteration operations hold the lock for the duration of +the entire operation, rather than temporarily releasing the +lock while handling each principal. This is the default +behavior, but this option exists to allow command line +override of a {[}dbmodules{]} setting. First introduced in +release 1.13. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x unlockiter}}] \leavevmode +\sphinxAtStartPar +Make iteration operations unlock the database for each +principal, instead of holding the lock for the duration of the +entire operation. First introduced in release 1.13. + +\end{description} +\end{quote} + +\sphinxAtStartPar +Supported options for the LDAP module are: +\begin{quote} +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}x host=}\sphinxstyleemphasis{ldapuri}}] \leavevmode +\sphinxAtStartPar +Specifies the LDAP server to connect to by a LDAP URI. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x binddn=}\sphinxstyleemphasis{bind\_dn}}] \leavevmode +\sphinxAtStartPar +Specifies the DN used to bind to the LDAP server. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x bindpwd=}\sphinxstyleemphasis{password}}] \leavevmode +\sphinxAtStartPar +Specifies the password or SASL secret used to bind to the LDAP +server. Using this option may expose the password to other +users on the system via the process list; to avoid this, +instead stash the password using the \sphinxstylestrong{stashsrvpw} command of +{\hyperref[\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_ldap\_util}}}}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x sasl\_mech=}\sphinxstyleemphasis{mechanism}}] \leavevmode +\sphinxAtStartPar +Specifies the SASL mechanism used to bind to the LDAP server. +The bind DN is ignored if a SASL mechanism is used. New in +release 1.13. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x sasl\_authcid=}\sphinxstyleemphasis{name}}] \leavevmode +\sphinxAtStartPar +Specifies the authentication name used when binding to the +LDAP server with a SASL mechanism, if the mechanism requires +one. New in release 1.13. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x sasl\_authzid=}\sphinxstyleemphasis{name}}] \leavevmode +\sphinxAtStartPar +Specifies the authorization name used when binding to the LDAP +server with a SASL mechanism. New in release 1.13. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x sasl\_realm=}\sphinxstyleemphasis{realm}}] \leavevmode +\sphinxAtStartPar +Specifies the realm used when binding to the LDAP server with +a SASL mechanism, if the mechanism uses one. New in release +1.13. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x debug=}\sphinxstyleemphasis{level}}] \leavevmode +\sphinxAtStartPar +sets the OpenLDAP client library debug level. \sphinxstyleemphasis{level} is an +integer to be interpreted by the library. Debugging messages +are printed to standard error. New in release 1.12. + +\end{description} +\end{quote} + + +\subsection{COMMANDS} +\label{\detokenize{admin/admin_commands/kadmin_local:commands}} +\sphinxAtStartPar +When using the remote client, available commands may be restricted +according to the privileges specified in the {\hyperref[\detokenize{admin/conf_files/kadm5_acl:kadm5-acl-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kadm5.acl}}}} file +on the admin server. + + +\subsubsection{add\_principal} +\label{\detokenize{admin/admin_commands/kadmin_local:add-principal}}\label{\detokenize{admin/admin_commands/kadmin_local:id1}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{add\_principal} {[}\sphinxstyleemphasis{options}{]} \sphinxstyleemphasis{newprinc} +\end{quote} + +\sphinxAtStartPar +Creates the principal \sphinxstyleemphasis{newprinc}, prompting twice for a password. If +no password policy is specified with the \sphinxstylestrong{\sphinxhyphen{}policy} option, and the +policy named \sphinxcode{\sphinxupquote{default}} is assigned to the principal if it exists. +However, creating a policy named \sphinxcode{\sphinxupquote{default}} will not automatically +assign this policy to previously existing principals. This policy +assignment can be suppressed with the \sphinxstylestrong{\sphinxhyphen{}clearpolicy} option. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{add} privilege. + +\sphinxAtStartPar +Aliases: \sphinxstylestrong{addprinc}, \sphinxstylestrong{ank} + +\sphinxAtStartPar +Options: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}expire} \sphinxstyleemphasis{expdate}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{getdate} string) The expiration date of the principal. + +\item[{\sphinxstylestrong{\sphinxhyphen{}pwexpire} \sphinxstyleemphasis{pwexpdate}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{getdate} string) The password expiration date. + +\item[{\sphinxstylestrong{\sphinxhyphen{}maxlife} \sphinxstyleemphasis{maxlife}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} or \DUrole{xref,std,std-ref}{getdate} string) The maximum ticket life +for the principal. + +\item[{\sphinxstylestrong{\sphinxhyphen{}maxrenewlife} \sphinxstyleemphasis{maxrenewlife}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} or \DUrole{xref,std,std-ref}{getdate} string) The maximum renewable +life of tickets for the principal. + +\item[{\sphinxstylestrong{\sphinxhyphen{}kvno} \sphinxstyleemphasis{kvno}}] \leavevmode +\sphinxAtStartPar +The initial key version number. + +\item[{\sphinxstylestrong{\sphinxhyphen{}policy} \sphinxstyleemphasis{policy}}] \leavevmode +\sphinxAtStartPar +The password policy used by this principal. If not specified, the +policy \sphinxcode{\sphinxupquote{default}} is used if it exists (unless \sphinxstylestrong{\sphinxhyphen{}clearpolicy} +is specified). + +\item[{\sphinxstylestrong{\sphinxhyphen{}clearpolicy}}] \leavevmode +\sphinxAtStartPar +Prevents any policy from being assigned when \sphinxstylestrong{\sphinxhyphen{}policy} is not +specified. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{allow\_postdated}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{\sphinxhyphen{}allow\_postdated} prohibits this principal from obtaining +postdated tickets. \sphinxstylestrong{+allow\_postdated} clears this flag. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{allow\_forwardable}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{\sphinxhyphen{}allow\_forwardable} prohibits this principal from obtaining +forwardable tickets. \sphinxstylestrong{+allow\_forwardable} clears this flag. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{allow\_renewable}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{\sphinxhyphen{}allow\_renewable} prohibits this principal from obtaining +renewable tickets. \sphinxstylestrong{+allow\_renewable} clears this flag. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{allow\_proxiable}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{\sphinxhyphen{}allow\_proxiable} prohibits this principal from obtaining +proxiable tickets. \sphinxstylestrong{+allow\_proxiable} clears this flag. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{allow\_dup\_skey}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{\sphinxhyphen{}allow\_dup\_skey} disables user\sphinxhyphen{}to\sphinxhyphen{}user authentication for this +principal by prohibiting others from obtaining a service ticket +encrypted in this principal’s TGT session key. +\sphinxstylestrong{+allow\_dup\_skey} clears this flag. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{requires\_preauth}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{+requires\_preauth} requires this principal to preauthenticate +before being allowed to kinit. \sphinxstylestrong{\sphinxhyphen{}requires\_preauth} clears this +flag. When \sphinxstylestrong{+requires\_preauth} is set on a service principal, +the KDC will only issue service tickets for that service principal +if the client’s initial authentication was performed using +preauthentication. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{requires\_hwauth}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{+requires\_hwauth} requires this principal to preauthenticate +using a hardware device before being allowed to kinit. +\sphinxstylestrong{\sphinxhyphen{}requires\_hwauth} clears this flag. When \sphinxstylestrong{+requires\_hwauth} is +set on a service principal, the KDC will only issue service tickets +for that service principal if the client’s initial authentication was +performed using a hardware device to preauthenticate. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{ok\_as\_delegate}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{+ok\_as\_delegate} sets the \sphinxstylestrong{okay as delegate} flag on tickets +issued with this principal as the service. Clients may use this +flag as a hint that credentials should be delegated when +authenticating to the service. \sphinxstylestrong{\sphinxhyphen{}ok\_as\_delegate} clears this +flag. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{allow\_svr}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{\sphinxhyphen{}allow\_svr} prohibits the issuance of service tickets for this +principal. In release 1.17 and later, user\sphinxhyphen{}to\sphinxhyphen{}user service +tickets are still allowed unless the \sphinxstylestrong{\sphinxhyphen{}allow\_dup\_skey} flag is +also set. \sphinxstylestrong{+allow\_svr} clears this flag. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{allow\_tgs\_req}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{\sphinxhyphen{}allow\_tgs\_req} specifies that a Ticket\sphinxhyphen{}Granting Service (TGS) +request for a service ticket for this principal is not permitted. +\sphinxstylestrong{+allow\_tgs\_req} clears this flag. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{allow\_tix}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{\sphinxhyphen{}allow\_tix} forbids the issuance of any tickets for this +principal. \sphinxstylestrong{+allow\_tix} clears this flag. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{needchange}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{+needchange} forces a password change on the next initial +authentication to this principal. \sphinxstylestrong{\sphinxhyphen{}needchange} clears this +flag. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{password\_changing\_service}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{+password\_changing\_service} marks this principal as a password +change service principal. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{ok\_to\_auth\_as\_delegate}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{+ok\_to\_auth\_as\_delegate} allows this principal to acquire +forwardable tickets to itself from arbitrary users, for use with +constrained delegation. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{no\_auth\_data\_required}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{+no\_auth\_data\_required} prevents PAC or AD\sphinxhyphen{}SIGNEDPATH data from +being added to service tickets for the principal. + +\item[{\{\sphinxhyphen{}|+\}\sphinxstylestrong{lockdown\_keys}}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{+lockdown\_keys} prevents keys for this principal from leaving +the KDC via kadmind. The chpass and extract operations are denied +for a principal with this attribute. The chrand operation is +allowed, but will not return the new keys. The delete and rename +operations are also denied if this attribute is set, in order to +prevent a malicious administrator from replacing principals like +krbtgt/* or kadmin/* with new principals without the attribute. +This attribute can be set via the network protocol, but can only +be removed using kadmin.local. + +\item[{\sphinxstylestrong{\sphinxhyphen{}randkey}}] \leavevmode +\sphinxAtStartPar +Sets the key of the principal to a random value. + +\item[{\sphinxstylestrong{\sphinxhyphen{}nokey}}] \leavevmode +\sphinxAtStartPar +Causes the principal to be created with no key. New in release +1.12. + +\item[{\sphinxstylestrong{\sphinxhyphen{}pw} \sphinxstyleemphasis{password}}] \leavevmode +\sphinxAtStartPar +Sets the password of the principal to the specified string and +does not prompt for a password. Note: using this option in a +shell script may expose the password to other users on the system +via the process list. + +\item[{\sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{enc}:\sphinxstyleemphasis{salt},…}] \leavevmode +\sphinxAtStartPar +Uses the specified keysalt list for setting the keys of the +principal. See {\hyperref[\detokenize{admin/conf_files/kdc_conf:keysalt-lists}]{\sphinxcrossref{\DUrole{std,std-ref}{Keysalt lists}}}} in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} for a +list of possible values. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x} \sphinxstyleemphasis{db\_princ\_args}}] \leavevmode +\sphinxAtStartPar +Indicates database\sphinxhyphen{}specific options. The options for the LDAP +database module are: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}x dn=}\sphinxstyleemphasis{dn}}] \leavevmode +\sphinxAtStartPar +Specifies the LDAP object that will contain the Kerberos +principal being created. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x linkdn=}\sphinxstyleemphasis{dn}}] \leavevmode +\sphinxAtStartPar +Specifies the LDAP object to which the newly created Kerberos +principal object will point. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x containerdn=}\sphinxstyleemphasis{container\_dn}}] \leavevmode +\sphinxAtStartPar +Specifies the container object under which the Kerberos +principal is to be created. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x tktpolicy=}\sphinxstyleemphasis{policy}}] \leavevmode +\sphinxAtStartPar +Associates a ticket policy to the Kerberos principal. + +\end{description} + +\begin{sphinxadmonition}{note}{Note:}\begin{itemize} +\item {} +\sphinxAtStartPar +The \sphinxstylestrong{containerdn} and \sphinxstylestrong{linkdn} options cannot be +specified with the \sphinxstylestrong{dn} option. + +\item {} +\sphinxAtStartPar +If the \sphinxstyleemphasis{dn} or \sphinxstyleemphasis{containerdn} options are not specified while +adding the principal, the principals are created under the +principal container configured in the realm or the realm +container. + +\item {} +\sphinxAtStartPar +\sphinxstyleemphasis{dn} and \sphinxstyleemphasis{containerdn} should be within the subtrees or +principal container configured in the realm. + +\end{itemize} +\end{sphinxadmonition} + +\end{description} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{addprinc} \PYG{n}{jennifer} +\PYG{n}{No} \PYG{n}{policy} \PYG{n}{specified} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{jennifer@ATHENA.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{;} +\PYG{n}{defaulting} \PYG{n}{to} \PYG{n}{no} \PYG{n}{policy}\PYG{o}{.} +\PYG{n}{Enter} \PYG{n}{password} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{jennifer}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{p}{:} +\PYG{n}{Re}\PYG{o}{\PYGZhy{}}\PYG{n}{enter} \PYG{n}{password} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{jennifer}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{p}{:} +\PYG{n}{Principal} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{jennifer@ATHENA.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{created}\PYG{o}{.} +\PYG{n}{kadmin}\PYG{p}{:} +\end{sphinxVerbatim} + + +\subsubsection{modify\_principal} +\label{\detokenize{admin/admin_commands/kadmin_local:modify-principal}}\label{\detokenize{admin/admin_commands/kadmin_local:id2}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{modify\_principal} {[}\sphinxstyleemphasis{options}{]} \sphinxstyleemphasis{principal} +\end{quote} + +\sphinxAtStartPar +Modifies the specified principal, changing the fields as specified. +The options to \sphinxstylestrong{add\_principal} also apply to this command, except +for the \sphinxstylestrong{\sphinxhyphen{}randkey}, \sphinxstylestrong{\sphinxhyphen{}pw}, and \sphinxstylestrong{\sphinxhyphen{}e} options. In addition, the +option \sphinxstylestrong{\sphinxhyphen{}clearpolicy} will clear the current policy of a principal. + +\sphinxAtStartPar +This command requires the \sphinxstyleemphasis{modify} privilege. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{modprinc} + +\sphinxAtStartPar +Options (in addition to the \sphinxstylestrong{addprinc} options): +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}unlock}}] \leavevmode +\sphinxAtStartPar +Unlocks a locked principal (one which has received too many failed +authentication attempts without enough time between them according +to its password policy) so that it can successfully authenticate. + +\end{description} + + +\subsubsection{rename\_principal} +\label{\detokenize{admin/admin_commands/kadmin_local:rename-principal}}\label{\detokenize{admin/admin_commands/kadmin_local:id3}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{rename\_principal} {[}\sphinxstylestrong{\sphinxhyphen{}force}{]} \sphinxstyleemphasis{old\_principal} \sphinxstyleemphasis{new\_principal} +\end{quote} + +\sphinxAtStartPar +Renames the specified \sphinxstyleemphasis{old\_principal} to \sphinxstyleemphasis{new\_principal}. This +command prompts for confirmation, unless the \sphinxstylestrong{\sphinxhyphen{}force} option is +given. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{add} and \sphinxstylestrong{delete} privileges. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{renprinc} + + +\subsubsection{delete\_principal} +\label{\detokenize{admin/admin_commands/kadmin_local:delete-principal}}\label{\detokenize{admin/admin_commands/kadmin_local:id4}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{delete\_principal} {[}\sphinxstylestrong{\sphinxhyphen{}force}{]} \sphinxstyleemphasis{principal} +\end{quote} + +\sphinxAtStartPar +Deletes the specified \sphinxstyleemphasis{principal} from the database. This command +prompts for deletion, unless the \sphinxstylestrong{\sphinxhyphen{}force} option is given. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{delete} privilege. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{delprinc} + + +\subsubsection{change\_password} +\label{\detokenize{admin/admin_commands/kadmin_local:change-password}}\label{\detokenize{admin/admin_commands/kadmin_local:id5}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{change\_password} {[}\sphinxstyleemphasis{options}{]} \sphinxstyleemphasis{principal} +\end{quote} + +\sphinxAtStartPar +Changes the password of \sphinxstyleemphasis{principal}. Prompts for a new password if +neither \sphinxstylestrong{\sphinxhyphen{}randkey} or \sphinxstylestrong{\sphinxhyphen{}pw} is specified. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{changepw} privilege, or that the +principal running the program is the same as the principal being +changed. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{cpw} + +\sphinxAtStartPar +The following options are available: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}randkey}}] \leavevmode +\sphinxAtStartPar +Sets the key of the principal to a random value. + +\item[{\sphinxstylestrong{\sphinxhyphen{}pw} \sphinxstyleemphasis{password}}] \leavevmode +\sphinxAtStartPar +Set the password to the specified string. Using this option in a +script may expose the password to other users on the system via +the process list. + +\item[{\sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{enc}:\sphinxstyleemphasis{salt},…}] \leavevmode +\sphinxAtStartPar +Uses the specified keysalt list for setting the keys of the +principal. See {\hyperref[\detokenize{admin/conf_files/kdc_conf:keysalt-lists}]{\sphinxcrossref{\DUrole{std,std-ref}{Keysalt lists}}}} in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} for a +list of possible values. + +\item[{\sphinxstylestrong{\sphinxhyphen{}keepold}}] \leavevmode +\sphinxAtStartPar +Keeps the existing keys in the database. This flag is usually not +necessary except perhaps for \sphinxcode{\sphinxupquote{krbtgt}} principals. + +\end{description} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{cpw} \PYG{n}{systest} +\PYG{n}{Enter} \PYG{n}{password} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{systest}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM}\PYG{p}{:} +\PYG{n}{Re}\PYG{o}{\PYGZhy{}}\PYG{n}{enter} \PYG{n}{password} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{systest}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM}\PYG{p}{:} +\PYG{n}{Password} \PYG{k}{for} \PYG{n}{systest}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM} \PYG{n}{changed}\PYG{o}{.} +\PYG{n}{kadmin}\PYG{p}{:} +\end{sphinxVerbatim} + + +\subsubsection{purgekeys} +\label{\detokenize{admin/admin_commands/kadmin_local:purgekeys}}\label{\detokenize{admin/admin_commands/kadmin_local:id6}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{purgekeys} {[}\sphinxstylestrong{\sphinxhyphen{}all}|\sphinxstylestrong{\sphinxhyphen{}keepkvno} \sphinxstyleemphasis{oldest\_kvno\_to\_keep}{]} \sphinxstyleemphasis{principal} +\end{quote} + +\sphinxAtStartPar +Purges previously retained old keys (e.g., from \sphinxstylestrong{change\_password +\sphinxhyphen{}keepold}) from \sphinxstyleemphasis{principal}. If \sphinxstylestrong{\sphinxhyphen{}keepkvno} is specified, then +only purges keys with kvnos lower than \sphinxstyleemphasis{oldest\_kvno\_to\_keep}. If +\sphinxstylestrong{\sphinxhyphen{}all} is specified, then all keys are purged. The \sphinxstylestrong{\sphinxhyphen{}all} option +is new in release 1.12. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{modify} privilege. + + +\subsubsection{get\_principal} +\label{\detokenize{admin/admin_commands/kadmin_local:get-principal}}\label{\detokenize{admin/admin_commands/kadmin_local:id7}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{get\_principal} {[}\sphinxstylestrong{\sphinxhyphen{}terse}{]} \sphinxstyleemphasis{principal} +\end{quote} + +\sphinxAtStartPar +Gets the attributes of principal. With the \sphinxstylestrong{\sphinxhyphen{}terse} option, outputs +fields as quoted tab\sphinxhyphen{}separated strings. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{inquire} privilege, or that the principal +running the the program to be the same as the one being listed. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{getprinc} + +\sphinxAtStartPar +Examples: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{getprinc} \PYG{n}{tlyu}\PYG{o}{/}\PYG{n}{admin} +\PYG{n}{Principal}\PYG{p}{:} \PYG{n}{tlyu}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM} +\PYG{n}{Expiration} \PYG{n}{date}\PYG{p}{:} \PYG{p}{[}\PYG{n}{never}\PYG{p}{]} +\PYG{n}{Last} \PYG{n}{password} \PYG{n}{change}\PYG{p}{:} \PYG{n}{Mon} \PYG{n}{Aug} \PYG{l+m+mi}{12} \PYG{l+m+mi}{14}\PYG{p}{:}\PYG{l+m+mi}{16}\PYG{p}{:}\PYG{l+m+mi}{47} \PYG{n}{EDT} \PYG{l+m+mi}{1996} +\PYG{n}{Password} \PYG{n}{expiration} \PYG{n}{date}\PYG{p}{:} \PYG{p}{[}\PYG{n}{never}\PYG{p}{]} +\PYG{n}{Maximum} \PYG{n}{ticket} \PYG{n}{life}\PYG{p}{:} \PYG{l+m+mi}{0} \PYG{n}{days} \PYG{l+m+mi}{10}\PYG{p}{:}\PYG{l+m+mi}{00}\PYG{p}{:}\PYG{l+m+mi}{00} +\PYG{n}{Maximum} \PYG{n}{renewable} \PYG{n}{life}\PYG{p}{:} \PYG{l+m+mi}{7} \PYG{n}{days} \PYG{l+m+mi}{00}\PYG{p}{:}\PYG{l+m+mi}{00}\PYG{p}{:}\PYG{l+m+mi}{00} +\PYG{n}{Last} \PYG{n}{modified}\PYG{p}{:} \PYG{n}{Mon} \PYG{n}{Aug} \PYG{l+m+mi}{12} \PYG{l+m+mi}{14}\PYG{p}{:}\PYG{l+m+mi}{16}\PYG{p}{:}\PYG{l+m+mi}{47} \PYG{n}{EDT} \PYG{l+m+mi}{1996} \PYG{p}{(}\PYG{n}{bjaspan}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM}\PYG{p}{)} +\PYG{n}{Last} \PYG{n}{successful} \PYG{n}{authentication}\PYG{p}{:} \PYG{p}{[}\PYG{n}{never}\PYG{p}{]} +\PYG{n}{Last} \PYG{n}{failed} \PYG{n}{authentication}\PYG{p}{:} \PYG{p}{[}\PYG{n}{never}\PYG{p}{]} +\PYG{n}{Failed} \PYG{n}{password} \PYG{n}{attempts}\PYG{p}{:} \PYG{l+m+mi}{0} +\PYG{n}{Number} \PYG{n}{of} \PYG{n}{keys}\PYG{p}{:} \PYG{l+m+mi}{1} +\PYG{n}{Key}\PYG{p}{:} \PYG{n}{vno} \PYG{l+m+mi}{1}\PYG{p}{,} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha384}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{192} +\PYG{n}{MKey}\PYG{p}{:} \PYG{n}{vno} \PYG{l+m+mi}{1} +\PYG{n}{Attributes}\PYG{p}{:} +\PYG{n}{Policy}\PYG{p}{:} \PYG{p}{[}\PYG{n}{none}\PYG{p}{]} + +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{getprinc} \PYG{o}{\PYGZhy{}}\PYG{n}{terse} \PYG{n}{systest} +\PYG{n}{systest}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM} \PYG{l+m+mi}{3} \PYG{l+m+mi}{86400} \PYG{l+m+mi}{604800} \PYG{l+m+mi}{1} +\PYG{l+m+mi}{785926535} \PYG{l+m+mi}{753241234} \PYG{l+m+mi}{785900000} +\PYG{n}{tlyu}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM} \PYG{l+m+mi}{786100034} \PYG{l+m+mi}{0} \PYG{l+m+mi}{0} +\PYG{n}{kadmin}\PYG{p}{:} +\end{sphinxVerbatim} + + +\subsubsection{list\_principals} +\label{\detokenize{admin/admin_commands/kadmin_local:list-principals}}\label{\detokenize{admin/admin_commands/kadmin_local:id8}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{list\_principals} {[}\sphinxstyleemphasis{expression}{]} +\end{quote} + +\sphinxAtStartPar +Retrieves all or some principal names. \sphinxstyleemphasis{expression} is a shell\sphinxhyphen{}style +glob expression that can contain the wild\sphinxhyphen{}card characters \sphinxcode{\sphinxupquote{?}}, +\sphinxcode{\sphinxupquote{*}}, and \sphinxcode{\sphinxupquote{{[}{]}}}. All principal names matching the expression are +printed. If no expression is provided, all principal names are +printed. If the expression does not contain an \sphinxcode{\sphinxupquote{@}} character, an +\sphinxcode{\sphinxupquote{@}} character followed by the local realm is appended to the +expression. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{list} privilege. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{listprincs}, \sphinxstylestrong{get\_principals}, \sphinxstylestrong{getprincs} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{listprincs} \PYG{n}{test}\PYG{o}{*} +\PYG{n}{test3}\PYG{n+nd}{@SECURE}\PYG{o}{\PYGZhy{}}\PYG{n}{TEST}\PYG{o}{.}\PYG{n}{OV}\PYG{o}{.}\PYG{n}{COM} +\PYG{n}{test2}\PYG{n+nd}{@SECURE}\PYG{o}{\PYGZhy{}}\PYG{n}{TEST}\PYG{o}{.}\PYG{n}{OV}\PYG{o}{.}\PYG{n}{COM} +\PYG{n}{test1}\PYG{n+nd}{@SECURE}\PYG{o}{\PYGZhy{}}\PYG{n}{TEST}\PYG{o}{.}\PYG{n}{OV}\PYG{o}{.}\PYG{n}{COM} +\PYG{n}{testuser}\PYG{n+nd}{@SECURE}\PYG{o}{\PYGZhy{}}\PYG{n}{TEST}\PYG{o}{.}\PYG{n}{OV}\PYG{o}{.}\PYG{n}{COM} +\PYG{n}{kadmin}\PYG{p}{:} +\end{sphinxVerbatim} + + +\subsubsection{get\_strings} +\label{\detokenize{admin/admin_commands/kadmin_local:get-strings}}\label{\detokenize{admin/admin_commands/kadmin_local:id9}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{get\_strings} \sphinxstyleemphasis{principal} +\end{quote} + +\sphinxAtStartPar +Displays string attributes on \sphinxstyleemphasis{principal}. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{inquire} privilege. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{getstrs} + + +\subsubsection{set\_string} +\label{\detokenize{admin/admin_commands/kadmin_local:set-string}}\label{\detokenize{admin/admin_commands/kadmin_local:id10}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{set\_string} \sphinxstyleemphasis{principal} \sphinxstyleemphasis{name} \sphinxstyleemphasis{value} +\end{quote} + +\sphinxAtStartPar +Sets a string attribute on \sphinxstyleemphasis{principal}. String attributes are used to +supply per\sphinxhyphen{}principal configuration to the KDC and some KDC plugin +modules. The following string attribute names are recognized by the +KDC: +\begin{description} +\item[{\sphinxstylestrong{require\_auth}}] \leavevmode +\sphinxAtStartPar +Specifies an authentication indicator which is required to +authenticate to the principal as a service. Multiple indicators +can be specified, separated by spaces; in this case any of the +specified indicators will be accepted. (New in release 1.14.) + +\item[{\sphinxstylestrong{session\_enctypes}}] \leavevmode +\sphinxAtStartPar +Specifies the encryption types supported for session keys when the +principal is authenticated to as a server. See +{\hyperref[\detokenize{admin/conf_files/kdc_conf:encryption-types}]{\sphinxcrossref{\DUrole{std,std-ref}{Encryption types}}}} in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} for a list of the +accepted values. + +\item[{\sphinxstylestrong{otp}}] \leavevmode +\sphinxAtStartPar +Enables One Time Passwords (OTP) preauthentication for a client +\sphinxstyleemphasis{principal}. The \sphinxstyleemphasis{value} is a JSON string representing an array +of objects, each having optional \sphinxcode{\sphinxupquote{type}} and \sphinxcode{\sphinxupquote{username}} fields. + +\item[{\sphinxstylestrong{pkinit\_cert\_match}}] \leavevmode +\sphinxAtStartPar +Specifies a matching expression that defines the certificate +attributes required for the client certificate used by the +principal during PKINIT authentication. The matching expression +is in the same format as those used by the \sphinxstylestrong{pkinit\_cert\_match} +option in {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}. (New in release 1.16.) + +\item[{\sphinxstylestrong{pac\_privsvr\_enctype}}] \leavevmode +\sphinxAtStartPar +Forces the encryption type of the PAC KDC checksum buffers to the +specified encryption type for tickets issued to this server, by +deriving a key from the local krbtgt key if it is of a different +encryption type. It may be necessary to set this value to +“aes256\sphinxhyphen{}sha1” on the cross\sphinxhyphen{}realm krbtgt entry for an Active +Directory realm when using aes\sphinxhyphen{}sha2 keys on the local krbtgt +entry. + +\end{description} + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{modify} privilege. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{setstr} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{set\PYGZus{}string} \PYG{n}{host}\PYG{o}{/}\PYG{n}{foo}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{n}{session\PYGZus{}enctypes} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts} +\PYG{n}{set\PYGZus{}string} \PYG{n}{user}\PYG{n+nd}{@FOO}\PYG{o}{.}\PYG{n}{COM} \PYG{n}{otp} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{[}\PYG{l+s+s2}{\PYGZob{}}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{type}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{:}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{hotp}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{,}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{username}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{:}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{al}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZcb{}]}\PYG{l+s+s2}{\PYGZdq{}} +\end{sphinxVerbatim} + + +\subsubsection{del\_string} +\label{\detokenize{admin/admin_commands/kadmin_local:del-string}}\label{\detokenize{admin/admin_commands/kadmin_local:id11}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{del\_string} \sphinxstyleemphasis{principal} \sphinxstyleemphasis{key} +\end{quote} + +\sphinxAtStartPar +Deletes a string attribute from \sphinxstyleemphasis{principal}. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{delete} privilege. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{delstr} + + +\subsubsection{add\_policy} +\label{\detokenize{admin/admin_commands/kadmin_local:add-policy}}\label{\detokenize{admin/admin_commands/kadmin_local:id12}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{add\_policy} {[}\sphinxstyleemphasis{options}{]} \sphinxstyleemphasis{policy} +\end{quote} + +\sphinxAtStartPar +Adds a password policy named \sphinxstyleemphasis{policy} to the database. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{add} privilege. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{addpol} + +\sphinxAtStartPar +The following options are available: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}maxlife} \sphinxstyleemphasis{time}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} or \DUrole{xref,std,std-ref}{getdate} string) Sets the maximum +lifetime of a password. + +\item[{\sphinxstylestrong{\sphinxhyphen{}minlife} \sphinxstyleemphasis{time}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} or \DUrole{xref,std,std-ref}{getdate} string) Sets the minimum +lifetime of a password. + +\item[{\sphinxstylestrong{\sphinxhyphen{}minlength} \sphinxstyleemphasis{length}}] \leavevmode +\sphinxAtStartPar +Sets the minimum length of a password. + +\item[{\sphinxstylestrong{\sphinxhyphen{}minclasses} \sphinxstyleemphasis{number}}] \leavevmode +\sphinxAtStartPar +Sets the minimum number of character classes required in a +password. The five character classes are lower case, upper case, +numbers, punctuation, and whitespace/unprintable characters. + +\item[{\sphinxstylestrong{\sphinxhyphen{}history} \sphinxstyleemphasis{number}}] \leavevmode +\sphinxAtStartPar +Sets the number of past keys kept for a principal. This option is +not supported with the LDAP KDC database module. + +\end{description} +\phantomsection\label{\detokenize{admin/admin_commands/kadmin_local:policy-maxfailure}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}maxfailure} \sphinxstyleemphasis{maxnumber}}] \leavevmode +\sphinxAtStartPar +Sets the number of authentication failures before the principal is +locked. Authentication failures are only tracked for principals +which require preauthentication. The counter of failed attempts +resets to 0 after a successful attempt to authenticate. A +\sphinxstyleemphasis{maxnumber} value of 0 (the default) disables lockout. + +\end{description} +\phantomsection\label{\detokenize{admin/admin_commands/kadmin_local:policy-failurecountinterval}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}failurecountinterval} \sphinxstyleemphasis{failuretime}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} or \DUrole{xref,std,std-ref}{getdate} string) Sets the allowable time +between authentication failures. If an authentication failure +happens after \sphinxstyleemphasis{failuretime} has elapsed since the previous +failure, the number of authentication failures is reset to 1. A +\sphinxstyleemphasis{failuretime} value of 0 (the default) means forever. + +\end{description} +\phantomsection\label{\detokenize{admin/admin_commands/kadmin_local:policy-lockoutduration}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}lockoutduration} \sphinxstyleemphasis{lockouttime}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} or \DUrole{xref,std,std-ref}{getdate} string) Sets the duration for +which the principal is locked from authenticating if too many +authentication failures occur without the specified failure count +interval elapsing. A duration of 0 (the default) means the +principal remains locked out until it is administratively unlocked +with \sphinxcode{\sphinxupquote{modprinc \sphinxhyphen{}unlock}}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}allowedkeysalts}}] \leavevmode +\sphinxAtStartPar +Specifies the key/salt tuples supported for long\sphinxhyphen{}term keys when +setting or changing a principal’s password/keys. See +{\hyperref[\detokenize{admin/conf_files/kdc_conf:keysalt-lists}]{\sphinxcrossref{\DUrole{std,std-ref}{Keysalt lists}}}} in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} for a list of the +accepted values, but note that key/salt tuples must be separated +with commas (‘,’) only. To clear the allowed key/salt policy use +a value of ‘\sphinxhyphen{}‘. + +\end{description} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{add\PYGZus{}policy} \PYG{o}{\PYGZhy{}}\PYG{n}{maxlife} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{2 days}\PYG{l+s+s2}{\PYGZdq{}} \PYG{o}{\PYGZhy{}}\PYG{n}{minlength} \PYG{l+m+mi}{5} \PYG{n}{guests} +\PYG{n}{kadmin}\PYG{p}{:} +\end{sphinxVerbatim} + + +\subsubsection{modify\_policy} +\label{\detokenize{admin/admin_commands/kadmin_local:modify-policy}}\label{\detokenize{admin/admin_commands/kadmin_local:id13}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{modify\_policy} {[}\sphinxstyleemphasis{options}{]} \sphinxstyleemphasis{policy} +\end{quote} + +\sphinxAtStartPar +Modifies the password policy named \sphinxstyleemphasis{policy}. Options are as described +for \sphinxstylestrong{add\_policy}. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{modify} privilege. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{modpol} + + +\subsubsection{delete\_policy} +\label{\detokenize{admin/admin_commands/kadmin_local:delete-policy}}\label{\detokenize{admin/admin_commands/kadmin_local:id14}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{delete\_policy} {[}\sphinxstylestrong{\sphinxhyphen{}force}{]} \sphinxstyleemphasis{policy} +\end{quote} + +\sphinxAtStartPar +Deletes the password policy named \sphinxstyleemphasis{policy}. Prompts for confirmation +before deletion. The command will fail if the policy is in use by any +principals. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{delete} privilege. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{delpol} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +kadmin: del\PYGZus{}policy guests +Are you sure you want to delete the policy \PYGZdq{}guests\PYGZdq{}? +(yes/no): yes +kadmin: +\end{sphinxVerbatim} + + +\subsubsection{get\_policy} +\label{\detokenize{admin/admin_commands/kadmin_local:get-policy}}\label{\detokenize{admin/admin_commands/kadmin_local:id15}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{get\_policy} {[} \sphinxstylestrong{\sphinxhyphen{}terse} {]} \sphinxstyleemphasis{policy} +\end{quote} + +\sphinxAtStartPar +Displays the values of the password policy named \sphinxstyleemphasis{policy}. With the +\sphinxstylestrong{\sphinxhyphen{}terse} flag, outputs the fields as quoted strings separated by +tabs. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{inquire} privilege. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{getpol} + +\sphinxAtStartPar +Examples: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{get\PYGZus{}policy} \PYG{n}{admin} +\PYG{n}{Policy}\PYG{p}{:} \PYG{n}{admin} +\PYG{n}{Maximum} \PYG{n}{password} \PYG{n}{life}\PYG{p}{:} \PYG{l+m+mi}{180} \PYG{n}{days} \PYG{l+m+mi}{00}\PYG{p}{:}\PYG{l+m+mi}{00}\PYG{p}{:}\PYG{l+m+mi}{00} +\PYG{n}{Minimum} \PYG{n}{password} \PYG{n}{life}\PYG{p}{:} \PYG{l+m+mi}{00}\PYG{p}{:}\PYG{l+m+mi}{00}\PYG{p}{:}\PYG{l+m+mi}{00} +\PYG{n}{Minimum} \PYG{n}{password} \PYG{n}{length}\PYG{p}{:} \PYG{l+m+mi}{6} +\PYG{n}{Minimum} \PYG{n}{number} \PYG{n}{of} \PYG{n}{password} \PYG{n}{character} \PYG{n}{classes}\PYG{p}{:} \PYG{l+m+mi}{2} +\PYG{n}{Number} \PYG{n}{of} \PYG{n}{old} \PYG{n}{keys} \PYG{n}{kept}\PYG{p}{:} \PYG{l+m+mi}{5} +\PYG{n}{Reference} \PYG{n}{count}\PYG{p}{:} \PYG{l+m+mi}{17} + +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{get\PYGZus{}policy} \PYG{o}{\PYGZhy{}}\PYG{n}{terse} \PYG{n}{admin} +\PYG{n}{admin} \PYG{l+m+mi}{15552000} \PYG{l+m+mi}{0} \PYG{l+m+mi}{6} \PYG{l+m+mi}{2} \PYG{l+m+mi}{5} \PYG{l+m+mi}{17} +\PYG{n}{kadmin}\PYG{p}{:} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The “Reference count” is the number of principals using that policy. +With the LDAP KDC database module, the reference count field is not +meaningful. + + +\subsubsection{list\_policies} +\label{\detokenize{admin/admin_commands/kadmin_local:list-policies}}\label{\detokenize{admin/admin_commands/kadmin_local:id16}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{list\_policies} {[}\sphinxstyleemphasis{expression}{]} +\end{quote} + +\sphinxAtStartPar +Retrieves all or some policy names. \sphinxstyleemphasis{expression} is a shell\sphinxhyphen{}style +glob expression that can contain the wild\sphinxhyphen{}card characters \sphinxcode{\sphinxupquote{?}}, +\sphinxcode{\sphinxupquote{*}}, and \sphinxcode{\sphinxupquote{{[}{]}}}. All policy names matching the expression are +printed. If no expression is provided, all existing policy names are +printed. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{list} privilege. + +\sphinxAtStartPar +Aliases: \sphinxstylestrong{listpols}, \sphinxstylestrong{get\_policies}, \sphinxstylestrong{getpols}. + +\sphinxAtStartPar +Examples: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{listpols} +\PYG{n}{test}\PYG{o}{\PYGZhy{}}\PYG{n}{pol} +\PYG{n+nb}{dict}\PYG{o}{\PYGZhy{}}\PYG{n}{only} +\PYG{n}{once}\PYG{o}{\PYGZhy{}}\PYG{n}{a}\PYG{o}{\PYGZhy{}}\PYG{n+nb}{min} +\PYG{n}{test}\PYG{o}{\PYGZhy{}}\PYG{n}{pol}\PYG{o}{\PYGZhy{}}\PYG{n}{nopw} + +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{listpols} \PYG{n}{t}\PYG{o}{*} +\PYG{n}{test}\PYG{o}{\PYGZhy{}}\PYG{n}{pol} +\PYG{n}{test}\PYG{o}{\PYGZhy{}}\PYG{n}{pol}\PYG{o}{\PYGZhy{}}\PYG{n}{nopw} +\PYG{n}{kadmin}\PYG{p}{:} +\end{sphinxVerbatim} + + +\subsubsection{ktadd} +\label{\detokenize{admin/admin_commands/kadmin_local:ktadd}}\label{\detokenize{admin/admin_commands/kadmin_local:id17}}\begin{quote} + +\begin{DUlineblock}{0em} +\item[] \sphinxstylestrong{ktadd} {[}options{]} \sphinxstyleemphasis{principal} +\item[] \sphinxstylestrong{ktadd} {[}options{]} \sphinxstylestrong{\sphinxhyphen{}glob} \sphinxstyleemphasis{princ\sphinxhyphen{}exp} +\end{DUlineblock} +\end{quote} + +\sphinxAtStartPar +Adds a \sphinxstyleemphasis{principal}, or all principals matching \sphinxstyleemphasis{princ\sphinxhyphen{}exp}, to a +keytab file. Each principal’s keys are randomized in the process. +The rules for \sphinxstyleemphasis{princ\sphinxhyphen{}exp} are described in the \sphinxstylestrong{list\_principals} +command. + +\sphinxAtStartPar +This command requires the \sphinxstylestrong{inquire} and \sphinxstylestrong{changepw} privileges. +With the \sphinxstylestrong{\sphinxhyphen{}glob} form, it also requires the \sphinxstylestrong{list} privilege. + +\sphinxAtStartPar +The options are: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}k{[}eytab{]}} \sphinxstyleemphasis{keytab}}] \leavevmode +\sphinxAtStartPar +Use \sphinxstyleemphasis{keytab} as the keytab file. Otherwise, the default keytab is +used. + +\item[{\sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{enc}:\sphinxstyleemphasis{salt},…}] \leavevmode +\sphinxAtStartPar +Uses the specified keysalt list for setting the new keys of the +principal. See {\hyperref[\detokenize{admin/conf_files/kdc_conf:keysalt-lists}]{\sphinxcrossref{\DUrole{std,std-ref}{Keysalt lists}}}} in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} for a +list of possible values. + +\item[{\sphinxstylestrong{\sphinxhyphen{}q}}] \leavevmode +\sphinxAtStartPar +Display less verbose information. + +\item[{\sphinxstylestrong{\sphinxhyphen{}norandkey}}] \leavevmode +\sphinxAtStartPar +Do not randomize the keys. The keys and their version numbers stay +unchanged. This option cannot be specified in combination with the +\sphinxstylestrong{\sphinxhyphen{}e} option. + +\end{description} + +\sphinxAtStartPar +An entry for each of the principal’s unique encryption types is added, +ignoring multiple keys with the same encryption type but different +salt types. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{xst} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{ktadd} \PYG{o}{\PYGZhy{}}\PYG{n}{k} \PYG{o}{/}\PYG{n}{tmp}\PYG{o}{/}\PYG{n}{foo}\PYG{o}{\PYGZhy{}}\PYG{n}{new}\PYG{o}{\PYGZhy{}}\PYG{n}{keytab} \PYG{n}{host}\PYG{o}{/}\PYG{n}{foo}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{foo}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{3}\PYG{p}{,} + \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} + \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{tmp}\PYG{o}{/}\PYG{n}{foo}\PYG{o}{\PYGZhy{}}\PYG{n}{new}\PYG{o}{\PYGZhy{}}\PYG{n}{keytab} +\PYG{n}{kadmin}\PYG{p}{:} +\end{sphinxVerbatim} + + +\subsubsection{ktremove} +\label{\detokenize{admin/admin_commands/kadmin_local:ktremove}}\label{\detokenize{admin/admin_commands/kadmin_local:id18}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{ktremove} {[}options{]} \sphinxstyleemphasis{principal} {[}\sphinxstyleemphasis{kvno} | \sphinxstyleemphasis{all} | \sphinxstyleemphasis{old}{]} +\end{quote} + +\sphinxAtStartPar +Removes entries for the specified \sphinxstyleemphasis{principal} from a keytab. Requires +no permissions, since this does not require database access. + +\sphinxAtStartPar +If the string “all” is specified, all entries for that principal are +removed; if the string “old” is specified, all entries for that +principal except those with the highest kvno are removed. Otherwise, +the value specified is parsed as an integer, and all entries whose +kvno match that integer are removed. + +\sphinxAtStartPar +The options are: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}k{[}eytab{]}} \sphinxstyleemphasis{keytab}}] \leavevmode +\sphinxAtStartPar +Use \sphinxstyleemphasis{keytab} as the keytab file. Otherwise, the default keytab is +used. + +\item[{\sphinxstylestrong{\sphinxhyphen{}q}}] \leavevmode +\sphinxAtStartPar +Display less verbose information. + +\end{description} + +\sphinxAtStartPar +Alias: \sphinxstylestrong{ktrem} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kadmin}\PYG{p}{:} \PYG{n}{ktremove} \PYG{n}{kadmin}\PYG{o}{/}\PYG{n}{admin} \PYG{n+nb}{all} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{kadmin}\PYG{o}{/}\PYG{n}{admin} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{3} \PYG{n}{removed} \PYG{k+kn}{from} \PYG{n+nn}{keytab} + \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab} +\PYG{n}{kadmin}\PYG{p}{:} +\end{sphinxVerbatim} + + +\subsubsection{lock} +\label{\detokenize{admin/admin_commands/kadmin_local:lock}} +\sphinxAtStartPar +Lock database exclusively. Use with extreme caution! This command +only works with the DB2 KDC database module. + + +\subsubsection{unlock} +\label{\detokenize{admin/admin_commands/kadmin_local:unlock}} +\sphinxAtStartPar +Release the exclusive database lock. + + +\subsubsection{list\_requests} +\label{\detokenize{admin/admin_commands/kadmin_local:list-requests}} +\sphinxAtStartPar +Lists available for kadmin requests. + +\sphinxAtStartPar +Aliases: \sphinxstylestrong{lr}, \sphinxstylestrong{?} + + +\subsubsection{quit} +\label{\detokenize{admin/admin_commands/kadmin_local:quit}} +\sphinxAtStartPar +Exit program. If the database was locked, the lock is released. + +\sphinxAtStartPar +Aliases: \sphinxstylestrong{exit}, \sphinxstylestrong{q} + + +\subsection{HISTORY} +\label{\detokenize{admin/admin_commands/kadmin_local:history}} +\sphinxAtStartPar +The kadmin program was originally written by Tom Yu at MIT, as an +interface to the OpenVision Kerberos administration program. + + +\subsection{ENVIRONMENT} +\label{\detokenize{admin/admin_commands/kadmin_local:environment}} +\sphinxAtStartPar +See \DUrole{xref,std,std-ref}{kerberos(7)} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{admin/admin_commands/kadmin_local:see-also}} +\sphinxAtStartPar +\DUrole{xref,std,std-ref}{kpasswd(1)}, {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}}, \DUrole{xref,std,std-ref}{kerberos(7)} + + +\section{kadmind} +\label{\detokenize{admin/admin_commands/kadmind:kadmind}}\label{\detokenize{admin/admin_commands/kadmind:kadmind-8}}\label{\detokenize{admin/admin_commands/kadmind::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{admin/admin_commands/kadmind:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{kadmind} +{[}\sphinxstylestrong{\sphinxhyphen{}x} \sphinxstyleemphasis{db\_args}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}m}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}nofork}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}proponly}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}port} \sphinxstyleemphasis{port\sphinxhyphen{}number}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}P} \sphinxstyleemphasis{pid\_file}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{kdb5\_util\_path}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}K} \sphinxstyleemphasis{kprop\_path}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}k} \sphinxstyleemphasis{kprop\_port}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}F} \sphinxstyleemphasis{dump\_file}{]} + + +\subsection{DESCRIPTION} +\label{\detokenize{admin/admin_commands/kadmind:description}} +\sphinxAtStartPar +kadmind starts the Kerberos administration server. kadmind typically +runs on the primary Kerberos server, which stores the KDC database. +If the KDC database uses the LDAP module, the administration server +and the KDC server need not run on the same machine. kadmind accepts +remote requests from programs such as {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} and +\DUrole{xref,std,std-ref}{kpasswd(1)} to administer the information in these database. + +\sphinxAtStartPar +kadmind requires a number of configuration files to be set up in order +for it to work: +\begin{description} +\item[{{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}}] \leavevmode +\sphinxAtStartPar +The KDC configuration file contains configuration information for +the KDC and admin servers. kadmind uses settings in this file to +locate the Kerberos database, and is also affected by the +\sphinxstylestrong{acl\_file}, \sphinxstylestrong{dict\_file}, \sphinxstylestrong{kadmind\_port}, and iprop\sphinxhyphen{}related +settings. + +\item[{{\hyperref[\detokenize{admin/conf_files/kadm5_acl:kadm5-acl-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kadm5.acl}}}}}] \leavevmode +\sphinxAtStartPar +kadmind’s ACL (access control list) tells it which principals are +allowed to perform administration actions. The pathname to the +ACL file can be specified with the \sphinxstylestrong{acl\_file} {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} +variable; by default, it is {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/kadm5.acl}}. + +\end{description} + +\sphinxAtStartPar +After the server begins running, it puts itself in the background and +disassociates itself from its controlling terminal. + +\sphinxAtStartPar +kadmind can be configured for incremental database propagation. +Incremental propagation allows replica KDC servers to receive +principal and policy updates incrementally instead of receiving full +dumps of the database. This facility can be enabled in the +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} file with the \sphinxstylestrong{iprop\_enable} option. Incremental +propagation requires the principal \sphinxcode{\sphinxupquote{kiprop/PRIMARY\textbackslash{}@REALM}} (where +PRIMARY is the primary KDC’s canonical host name, and REALM the realm +name). In release 1.13, this principal is automatically created and +registered into the datebase. + + +\subsection{OPTIONS} +\label{\detokenize{admin/admin_commands/kadmind:options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm}}] \leavevmode +\sphinxAtStartPar +specifies the realm that kadmind will serve; if it is not +specified, the default realm of the host is used. + +\item[{\sphinxstylestrong{\sphinxhyphen{}m}}] \leavevmode +\sphinxAtStartPar +causes the master database password to be fetched from the +keyboard (before the server puts itself in the background, if not +invoked with the \sphinxstylestrong{\sphinxhyphen{}nofork} option) rather than from a file on +disk. + +\item[{\sphinxstylestrong{\sphinxhyphen{}nofork}}] \leavevmode +\sphinxAtStartPar +causes the server to remain in the foreground and remain +associated to the terminal. + +\item[{\sphinxstylestrong{\sphinxhyphen{}proponly}}] \leavevmode +\sphinxAtStartPar +causes the server to only listen and respond to Kerberos replica +incremental propagation polling requests. This option can be used +to set up a hierarchical propagation topology where a replica KDC +provides incremental updates to other Kerberos replicas. + +\item[{\sphinxstylestrong{\sphinxhyphen{}port} \sphinxstyleemphasis{port\sphinxhyphen{}number}}] \leavevmode +\sphinxAtStartPar +specifies the port on which the administration server listens for +connections. The default port is determined by the +\sphinxstylestrong{kadmind\_port} configuration variable in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}P} \sphinxstyleemphasis{pid\_file}}] \leavevmode +\sphinxAtStartPar +specifies the file to which the PID of kadmind process should be +written after it starts up. This file can be used to identify +whether kadmind is still running and to allow init scripts to stop +the correct process. + +\item[{\sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{kdb5\_util\_path}}] \leavevmode +\sphinxAtStartPar +specifies the path to the kdb5\_util command to use when dumping the +KDB in response to full resync requests when iprop is enabled. + +\item[{\sphinxstylestrong{\sphinxhyphen{}K} \sphinxstyleemphasis{kprop\_path}}] \leavevmode +\sphinxAtStartPar +specifies the path to the kprop command to use to send full dumps +to replicas in response to full resync requests. + +\item[{\sphinxstylestrong{\sphinxhyphen{}k} \sphinxstyleemphasis{kprop\_port}}] \leavevmode +\sphinxAtStartPar +specifies the port by which the kprop process that is spawned by +kadmind connects to the replica kpropd, in order to transfer the +dump file during an iprop full resync request. + +\item[{\sphinxstylestrong{\sphinxhyphen{}F} \sphinxstyleemphasis{dump\_file}}] \leavevmode +\sphinxAtStartPar +specifies the file path to be used for dumping the KDB in response +to full resync requests when iprop is enabled. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x} \sphinxstyleemphasis{db\_args}}] \leavevmode +\sphinxAtStartPar +specifies database\sphinxhyphen{}specific arguments. See {\hyperref[\detokenize{admin/admin_commands/kadmin_local:dboptions}]{\sphinxcrossref{\DUrole{std,std-ref}{Database Options}}}} in {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} for supported arguments. + +\end{description} + + +\subsection{ENVIRONMENT} +\label{\detokenize{admin/admin_commands/kadmind:environment}} +\sphinxAtStartPar +See \DUrole{xref,std,std-ref}{kerberos(7)} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{admin/admin_commands/kadmind:see-also}} +\sphinxAtStartPar +\DUrole{xref,std,std-ref}{kpasswd(1)}, {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}}, {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}}, +{\hyperref[\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_ldap\_util}}}}, {\hyperref[\detokenize{admin/conf_files/kadm5_acl:kadm5-acl-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kadm5.acl}}}}, \DUrole{xref,std,std-ref}{kerberos(7)} + + +\section{kdb5\_util} +\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util}}\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}}\label{\detokenize{admin/admin_commands/kdb5_util::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{admin/admin_commands/kdb5_util:synopsis}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{kdb5\_util} +{[}\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}d} \sphinxstyleemphasis{dbname}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}k} \sphinxstyleemphasis{mkeytype}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}kv} \sphinxstyleemphasis{mkeyVNO}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}M} \sphinxstyleemphasis{mkeyname}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}m}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}sf} \sphinxstyleemphasis{stashfilename}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}P} \sphinxstyleemphasis{password}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}x} \sphinxstyleemphasis{db\_args}{]} +\sphinxstyleemphasis{command} {[}\sphinxstyleemphasis{command\_options}{]} + + +\subsection{DESCRIPTION} +\label{\detokenize{admin/admin_commands/kdb5_util:description}}\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-synopsis-end}} +\sphinxAtStartPar +kdb5\_util allows an administrator to perform maintenance procedures on +the KDC database. Databases can be created, destroyed, and dumped to +or loaded from ASCII files. kdb5\_util can create a Kerberos master +key stash file or perform live rollover of the master key. + +\sphinxAtStartPar +When kdb5\_util is run, it attempts to acquire the master key and open +the database. However, execution continues regardless of whether or +not kdb5\_util successfully opens the database, because the database +may not exist yet or the stash file may be corrupt. + +\sphinxAtStartPar +Note that some KDC database modules may not support all kdb5\_util +commands. + + +\subsection{COMMAND\sphinxhyphen{}LINE OPTIONS} +\label{\detokenize{admin/admin_commands/kdb5_util:command-line-options}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm}}] \leavevmode +\sphinxAtStartPar +specifies the Kerberos realm of the database. + +\item[{\sphinxstylestrong{\sphinxhyphen{}d} \sphinxstyleemphasis{dbname}}] \leavevmode +\sphinxAtStartPar +specifies the name under which the principal database is stored; +by default the database is that listed in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. The +password policy database and lock files are also derived from this +value. + +\item[{\sphinxstylestrong{\sphinxhyphen{}k} \sphinxstyleemphasis{mkeytype}}] \leavevmode +\sphinxAtStartPar +specifies the key type of the master key in the database. The +default is given by the \sphinxstylestrong{master\_key\_type} variable in +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}kv} \sphinxstyleemphasis{mkeyVNO}}] \leavevmode +\sphinxAtStartPar +Specifies the version number of the master key in the database; +the default is 1. Note that 0 is not allowed. + +\item[{\sphinxstylestrong{\sphinxhyphen{}M} \sphinxstyleemphasis{mkeyname}}] \leavevmode +\sphinxAtStartPar +principal name for the master key in the database. If not +specified, the name is determined by the \sphinxstylestrong{master\_key\_name} +variable in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}m}}] \leavevmode +\sphinxAtStartPar +specifies that the master database password should be read from +the keyboard rather than fetched from a file on disk. + +\item[{\sphinxstylestrong{\sphinxhyphen{}sf} \sphinxstyleemphasis{stash\_file}}] \leavevmode +\sphinxAtStartPar +specifies the stash filename of the master database password. If +not specified, the filename is determined by the +\sphinxstylestrong{key\_stash\_file} variable in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}P} \sphinxstyleemphasis{password}}] \leavevmode +\sphinxAtStartPar +specifies the master database password. Using this option may +expose the password to other users on the system via the process +list. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x} \sphinxstyleemphasis{db\_args}}] \leavevmode +\sphinxAtStartPar +specifies database\sphinxhyphen{}specific options. See {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} for +supported options. + +\end{description} + + +\subsection{COMMANDS} +\label{\detokenize{admin/admin_commands/kdb5_util:commands}}\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-options-end}} + +\subsubsection{create} +\label{\detokenize{admin/admin_commands/kdb5_util:create}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-create}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{create} {[}\sphinxstylestrong{\sphinxhyphen{}s}{]} +\end{quote} + +\sphinxAtStartPar +Creates a new database. If the \sphinxstylestrong{\sphinxhyphen{}s} option is specified, the stash +file is also created. This command fails if the database already +exists. If the command is successful, the database is opened just as +if it had already existed when the program was first run. + + +\subsubsection{destroy} +\label{\detokenize{admin/admin_commands/kdb5_util:destroy}}\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-create-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-destroy}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{destroy} {[}\sphinxstylestrong{\sphinxhyphen{}f}{]} +\end{quote} + +\sphinxAtStartPar +Destroys the database, first overwriting the disk sectors and then +unlinking the files, after prompting the user for confirmation. With +the \sphinxstylestrong{\sphinxhyphen{}f} argument, does not prompt the user. + + +\subsubsection{stash} +\label{\detokenize{admin/admin_commands/kdb5_util:stash}}\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-destroy-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-stash}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{stash} {[}\sphinxstylestrong{\sphinxhyphen{}f} \sphinxstyleemphasis{keyfile}{]} +\end{quote} + +\sphinxAtStartPar +Stores the master principal’s keys in a stash file. The \sphinxstylestrong{\sphinxhyphen{}f} +argument can be used to override the \sphinxstyleemphasis{keyfile} specified in +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. + + +\subsubsection{dump} +\label{\detokenize{admin/admin_commands/kdb5_util:dump}}\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-stash-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-dump}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{dump} {[}\sphinxstylestrong{\sphinxhyphen{}b7}|\sphinxstylestrong{\sphinxhyphen{}r13}|\sphinxstylestrong{\sphinxhyphen{}r18}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}verbose}{]} {[}\sphinxstylestrong{\sphinxhyphen{}mkey\_convert}{]} {[}\sphinxstylestrong{\sphinxhyphen{}new\_mkey\_file} +\sphinxstyleemphasis{mkey\_file}{]} {[}\sphinxstylestrong{\sphinxhyphen{}rev}{]} {[}\sphinxstylestrong{\sphinxhyphen{}recurse}{]} {[}\sphinxstyleemphasis{filename} +{[}\sphinxstyleemphasis{principals}…{]}{]} +\end{quote} + +\sphinxAtStartPar +Dumps the current Kerberos and KADM5 database into an ASCII file. By +default, the database is dumped in current format, “kdb5\_util +load\_dump version 7”. If filename is not specified, or is the string +“\sphinxhyphen{}”, the dump is sent to standard output. Options: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}b7}}] \leavevmode +\sphinxAtStartPar +causes the dump to be in the Kerberos 5 Beta 7 format (“kdb5\_util +load\_dump version 4”). This was the dump format produced on +releases prior to 1.2.2. + +\item[{\sphinxstylestrong{\sphinxhyphen{}r13}}] \leavevmode +\sphinxAtStartPar +causes the dump to be in the Kerberos 5 1.3 format (“kdb5\_util +load\_dump version 5”). This was the dump format produced on +releases prior to 1.8. + +\item[{\sphinxstylestrong{\sphinxhyphen{}r18}}] \leavevmode +\sphinxAtStartPar +causes the dump to be in the Kerberos 5 1.8 format (“kdb5\_util +load\_dump version 6”). This was the dump format produced on +releases prior to 1.11. + +\item[{\sphinxstylestrong{\sphinxhyphen{}verbose}}] \leavevmode +\sphinxAtStartPar +causes the name of each principal and policy to be printed as it +is dumped. + +\item[{\sphinxstylestrong{\sphinxhyphen{}mkey\_convert}}] \leavevmode +\sphinxAtStartPar +prompts for a new master key. This new master key will be used to +re\sphinxhyphen{}encrypt principal key data in the dumpfile. The principal keys +themselves will not be changed. + +\item[{\sphinxstylestrong{\sphinxhyphen{}new\_mkey\_file} \sphinxstyleemphasis{mkey\_file}}] \leavevmode +\sphinxAtStartPar +the filename of a stash file. The master key in this stash file +will be used to re\sphinxhyphen{}encrypt the key data in the dumpfile. The key +data in the database will not be changed. + +\item[{\sphinxstylestrong{\sphinxhyphen{}rev}}] \leavevmode +\sphinxAtStartPar +dumps in reverse order. This may recover principals that do not +dump normally, in cases where database corruption has occurred. + +\item[{\sphinxstylestrong{\sphinxhyphen{}recurse}}] \leavevmode +\sphinxAtStartPar +causes the dump to walk the database recursively (btree only). +This may recover principals that do not dump normally, in cases +where database corruption has occurred. In cases of such +corruption, this option will probably retrieve more principals +than the \sphinxstylestrong{\sphinxhyphen{}rev} option will. + +\sphinxAtStartPar +\DUrole{versionmodified,changed}{Changed in version 1.15: }Release 1.15 restored the functionality of the \sphinxstylestrong{\sphinxhyphen{}recurse} +option. + +\sphinxAtStartPar +\DUrole{versionmodified,changed}{Changed in version 1.5: }The \sphinxstylestrong{\sphinxhyphen{}recurse} option ceased working until release 1.15, +doing a normal dump instead of a recursive traversal. + +\end{description} + + +\subsubsection{load} +\label{\detokenize{admin/admin_commands/kdb5_util:load}}\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-dump-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-load}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{load} {[}\sphinxstylestrong{\sphinxhyphen{}b7}|\sphinxstylestrong{\sphinxhyphen{}r13}|\sphinxstylestrong{\sphinxhyphen{}r18}{]} {[}\sphinxstylestrong{\sphinxhyphen{}hash}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}verbose}{]} {[}\sphinxstylestrong{\sphinxhyphen{}update}{]} \sphinxstyleemphasis{filename} +\end{quote} + +\sphinxAtStartPar +Loads a database dump from the named file into the named database. If +no option is given to determine the format of the dump file, the +format is detected automatically and handled as appropriate. Unless +the \sphinxstylestrong{\sphinxhyphen{}update} option is given, \sphinxstylestrong{load} creates a new database +containing only the data in the dump file, overwriting the contents of +any previously existing database. Note that when using the LDAP KDC +database module, the \sphinxstylestrong{\sphinxhyphen{}update} flag is required. + +\sphinxAtStartPar +Options: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}b7}}] \leavevmode +\sphinxAtStartPar +requires the database to be in the Kerberos 5 Beta 7 format +(“kdb5\_util load\_dump version 4”). This was the dump format +produced on releases prior to 1.2.2. + +\item[{\sphinxstylestrong{\sphinxhyphen{}r13}}] \leavevmode +\sphinxAtStartPar +requires the database to be in Kerberos 5 1.3 format (“kdb5\_util +load\_dump version 5”). This was the dump format produced on +releases prior to 1.8. + +\item[{\sphinxstylestrong{\sphinxhyphen{}r18}}] \leavevmode +\sphinxAtStartPar +requires the database to be in Kerberos 5 1.8 format (“kdb5\_util +load\_dump version 6”). This was the dump format produced on +releases prior to 1.11. + +\item[{\sphinxstylestrong{\sphinxhyphen{}hash}}] \leavevmode +\sphinxAtStartPar +stores the database in hash format, if using the DB2 database +type. If this option is not specified, the database will be +stored in btree format. This option is not recommended, as +databases stored in hash format are known to corrupt data and lose +principals. + +\item[{\sphinxstylestrong{\sphinxhyphen{}verbose}}] \leavevmode +\sphinxAtStartPar +causes the name of each principal and policy to be printed as it +is dumped. + +\item[{\sphinxstylestrong{\sphinxhyphen{}update}}] \leavevmode +\sphinxAtStartPar +records from the dump file are added to or updated in the existing +database. Otherwise, a new database is created containing only +what is in the dump file and the old one destroyed upon successful +completion. + +\end{description} + + +\subsubsection{ark} +\label{\detokenize{admin/admin_commands/kdb5_util:ark}}\label{\detokenize{admin/admin_commands/kdb5_util:kdb5-util-load-end}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{ark} {[}\sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{enc}:\sphinxstyleemphasis{salt},…{]} \sphinxstyleemphasis{principal} +\end{quote} + +\sphinxAtStartPar +Adds new random keys to \sphinxstyleemphasis{principal} at the next available key version +number. Keys for the current highest key version number will be +preserved. The \sphinxstylestrong{\sphinxhyphen{}e} option specifies the list of encryption and +salt types to be used for the new keys. + + +\subsubsection{add\_mkey} +\label{\detokenize{admin/admin_commands/kdb5_util:add-mkey}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{add\_mkey} {[}\sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{etype}{]} {[}\sphinxstylestrong{\sphinxhyphen{}s}{]} +\end{quote} + +\sphinxAtStartPar +Adds a new master key to the master key principal, but does not mark +it as active. Existing master keys will remain. The \sphinxstylestrong{\sphinxhyphen{}e} option +specifies the encryption type of the new master key; see +{\hyperref[\detokenize{admin/conf_files/kdc_conf:encryption-types}]{\sphinxcrossref{\DUrole{std,std-ref}{Encryption types}}}} in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} for a list of possible +values. The \sphinxstylestrong{\sphinxhyphen{}s} option stashes the new master key in the stash +file, which will be created if it doesn’t already exist. + +\sphinxAtStartPar +After a new master key is added, it should be propagated to replica +servers via a manual or periodic invocation of {\hyperref[\detokenize{admin/admin_commands/kprop:kprop-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop}}}}. Then, +the stash files on the replica servers should be updated with the +kdb5\_util \sphinxstylestrong{stash} command. Once those steps are complete, the key +is ready to be marked active with the kdb5\_util \sphinxstylestrong{use\_mkey} command. + + +\subsubsection{use\_mkey} +\label{\detokenize{admin/admin_commands/kdb5_util:use-mkey}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{use\_mkey} \sphinxstyleemphasis{mkeyVNO} {[}\sphinxstyleemphasis{time}{]} +\end{quote} + +\sphinxAtStartPar +Sets the activation time of the master key specified by \sphinxstyleemphasis{mkeyVNO}. +Once a master key becomes active, it will be used to encrypt newly +created principal keys. If no \sphinxstyleemphasis{time} argument is given, the current +time is used, causing the specified master key version to become +active immediately. The format for \sphinxstyleemphasis{time} is \DUrole{xref,std,std-ref}{getdate} string. + +\sphinxAtStartPar +After a new master key becomes active, the kdb5\_util +\sphinxstylestrong{update\_princ\_encryption} command can be used to update all +principal keys to be encrypted in the new master key. + + +\subsubsection{list\_mkeys} +\label{\detokenize{admin/admin_commands/kdb5_util:list-mkeys}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{list\_mkeys} +\end{quote} + +\sphinxAtStartPar +List all master keys, from most recent to earliest, in the master key +principal. The output will show the kvno, enctype, and salt type for +each mkey, similar to the output of {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} \sphinxstylestrong{getprinc}. A +\sphinxcode{\sphinxupquote{*}} following an mkey denotes the currently active master key. + + +\subsubsection{purge\_mkeys} +\label{\detokenize{admin/admin_commands/kdb5_util:purge-mkeys}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{purge\_mkeys} {[}\sphinxstylestrong{\sphinxhyphen{}f}{]} {[}\sphinxstylestrong{\sphinxhyphen{}n}{]} {[}\sphinxstylestrong{\sphinxhyphen{}v}{]} +\end{quote} + +\sphinxAtStartPar +Delete master keys from the master key principal that are not used to +protect any principals. This command can be used to remove old master +keys all principal keys are protected by a newer master key. +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}f}}] \leavevmode +\sphinxAtStartPar +does not prompt for confirmation. + +\item[{\sphinxstylestrong{\sphinxhyphen{}n}}] \leavevmode +\sphinxAtStartPar +performs a dry run, showing master keys that would be purged, but +not actually purging any keys. + +\item[{\sphinxstylestrong{\sphinxhyphen{}v}}] \leavevmode +\sphinxAtStartPar +gives more verbose output. + +\end{description} + + +\subsubsection{update\_princ\_encryption} +\label{\detokenize{admin/admin_commands/kdb5_util:update-princ-encryption}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{update\_princ\_encryption} {[}\sphinxstylestrong{\sphinxhyphen{}f}{]} {[}\sphinxstylestrong{\sphinxhyphen{}n}{]} {[}\sphinxstylestrong{\sphinxhyphen{}v}{]} +{[}\sphinxstyleemphasis{princ\sphinxhyphen{}pattern}{]} +\end{quote} + +\sphinxAtStartPar +Update all principal records (or only those matching the +\sphinxstyleemphasis{princ\sphinxhyphen{}pattern} glob pattern) to re\sphinxhyphen{}encrypt the key data using the +active database master key, if they are encrypted using a different +version, and give a count at the end of the number of principals +updated. If the \sphinxstylestrong{\sphinxhyphen{}f} option is not given, ask for confirmation +before starting to make changes. The \sphinxstylestrong{\sphinxhyphen{}v} option causes each +principal processed to be listed, with an indication as to whether it +needed updating or not. The \sphinxstylestrong{\sphinxhyphen{}n} option performs a dry run, only +showing the actions which would have been taken. + + +\subsubsection{tabdump} +\label{\detokenize{admin/admin_commands/kdb5_util:tabdump}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{tabdump} {[}\sphinxstylestrong{\sphinxhyphen{}H}{]} {[}\sphinxstylestrong{\sphinxhyphen{}c}{]} {[}\sphinxstylestrong{\sphinxhyphen{}e}{]} {[}\sphinxstylestrong{\sphinxhyphen{}n}{]} {[}\sphinxstylestrong{\sphinxhyphen{}o} \sphinxstyleemphasis{outfile}{]} +\sphinxstyleemphasis{dumptype} +\end{quote} + +\sphinxAtStartPar +Dump selected fields of the database in a tabular format suitable for +reporting (e.g., using traditional Unix text processing tools) or +importing into relational databases. The data format is tab\sphinxhyphen{}separated +(default), or optionally comma\sphinxhyphen{}separated (CSV), with a fixed number of +columns. The output begins with a header line containing field names, +unless suppression is requested using the \sphinxstylestrong{\sphinxhyphen{}H} option. + +\sphinxAtStartPar +The \sphinxstyleemphasis{dumptype} parameter specifies the name of an output table (see +below). + +\sphinxAtStartPar +Options: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}H}}] \leavevmode +\sphinxAtStartPar +suppress writing the field names in a header line + +\item[{\sphinxstylestrong{\sphinxhyphen{}c}}] \leavevmode +\sphinxAtStartPar +use comma separated values (CSV) format, with minimal quoting, +instead of the default tab\sphinxhyphen{}separated (unquoted, unescaped) format + +\item[{\sphinxstylestrong{\sphinxhyphen{}e}}] \leavevmode +\sphinxAtStartPar +write empty hexadecimal string fields as empty fields instead of +as “\sphinxhyphen{}1”. + +\item[{\sphinxstylestrong{\sphinxhyphen{}n}}] \leavevmode +\sphinxAtStartPar +produce numeric output for fields that normally have symbolic +output, such as enctypes and flag names. Also requests output of +time stamps as decimal POSIX time\_t values. + +\item[{\sphinxstylestrong{\sphinxhyphen{}o} \sphinxstyleemphasis{outfile}}] \leavevmode +\sphinxAtStartPar +write the dump to the specified output file instead of to standard +output + +\end{description} + +\sphinxAtStartPar +Dump types: +\begin{description} +\item[{\sphinxstylestrong{keydata}}] \leavevmode +\sphinxAtStartPar +principal encryption key information, including actual key data +(which is still encrypted in the master key) +\begin{description} +\item[{\sphinxstylestrong{name}}] \leavevmode +\sphinxAtStartPar +principal name + +\item[{\sphinxstylestrong{keyindex}}] \leavevmode +\sphinxAtStartPar +index of this key in the principal’s key list + +\item[{\sphinxstylestrong{kvno}}] \leavevmode +\sphinxAtStartPar +key version number + +\item[{\sphinxstylestrong{enctype}}] \leavevmode +\sphinxAtStartPar +encryption type + +\item[{\sphinxstylestrong{key}}] \leavevmode +\sphinxAtStartPar +key data as a hexadecimal string + +\item[{\sphinxstylestrong{salttype}}] \leavevmode +\sphinxAtStartPar +salt type + +\item[{\sphinxstylestrong{salt}}] \leavevmode +\sphinxAtStartPar +salt data as a hexadecimal string + +\end{description} + +\item[{\sphinxstylestrong{keyinfo}}] \leavevmode +\sphinxAtStartPar +principal encryption key information (as in \sphinxstylestrong{keydata} above), +excluding actual key data + +\item[{\sphinxstylestrong{princ\_flags}}] \leavevmode +\sphinxAtStartPar +principal boolean attributes. Flag names print as hexadecimal +numbers if the \sphinxstylestrong{\sphinxhyphen{}n} option is specified, and all flag positions +are printed regardless of whether or not they are set. If \sphinxstylestrong{\sphinxhyphen{}n} +is not specified, print all known flag names for each principal, +but only print hexadecimal flag names if the corresponding flag is +set. +\begin{description} +\item[{\sphinxstylestrong{name}}] \leavevmode +\sphinxAtStartPar +principal name + +\item[{\sphinxstylestrong{flag}}] \leavevmode +\sphinxAtStartPar +flag name + +\item[{\sphinxstylestrong{value}}] \leavevmode +\sphinxAtStartPar +boolean value (0 for clear, or 1 for set) + +\end{description} + +\item[{\sphinxstylestrong{princ\_lockout}}] \leavevmode +\sphinxAtStartPar +state information used for tracking repeated password failures +\begin{description} +\item[{\sphinxstylestrong{name}}] \leavevmode +\sphinxAtStartPar +principal name + +\item[{\sphinxstylestrong{last\_success}}] \leavevmode +\sphinxAtStartPar +time stamp of most recent successful authentication + +\item[{\sphinxstylestrong{last\_failed}}] \leavevmode +\sphinxAtStartPar +time stamp of most recent failed authentication + +\item[{\sphinxstylestrong{fail\_count}}] \leavevmode +\sphinxAtStartPar +count of failed attempts + +\end{description} + +\item[{\sphinxstylestrong{princ\_meta}}] \leavevmode +\sphinxAtStartPar +principal metadata +\begin{description} +\item[{\sphinxstylestrong{name}}] \leavevmode +\sphinxAtStartPar +principal name + +\item[{\sphinxstylestrong{modby}}] \leavevmode +\sphinxAtStartPar +name of last principal to modify this principal + +\item[{\sphinxstylestrong{modtime}}] \leavevmode +\sphinxAtStartPar +timestamp of last modification + +\item[{\sphinxstylestrong{lastpwd}}] \leavevmode +\sphinxAtStartPar +timestamp of last password change + +\item[{\sphinxstylestrong{policy}}] \leavevmode +\sphinxAtStartPar +policy object name + +\item[{\sphinxstylestrong{mkvno}}] \leavevmode +\sphinxAtStartPar +key version number of the master key that encrypts this +principal’s key data + +\item[{\sphinxstylestrong{hist\_kvno}}] \leavevmode +\sphinxAtStartPar +key version number of the history key that encrypts the key +history data for this principal + +\end{description} + +\item[{\sphinxstylestrong{princ\_stringattrs}}] \leavevmode +\sphinxAtStartPar +string attributes (key/value pairs) +\begin{description} +\item[{\sphinxstylestrong{name}}] \leavevmode +\sphinxAtStartPar +principal name + +\item[{\sphinxstylestrong{key}}] \leavevmode +\sphinxAtStartPar +attribute name + +\item[{\sphinxstylestrong{value}}] \leavevmode +\sphinxAtStartPar +attribute value + +\end{description} + +\item[{\sphinxstylestrong{princ\_tktpolicy}}] \leavevmode +\sphinxAtStartPar +per\sphinxhyphen{}principal ticket policy data, including maximum ticket +lifetimes +\begin{description} +\item[{\sphinxstylestrong{name}}] \leavevmode +\sphinxAtStartPar +principal name + +\item[{\sphinxstylestrong{expiration}}] \leavevmode +\sphinxAtStartPar +principal expiration date + +\item[{\sphinxstylestrong{pw\_expiration}}] \leavevmode +\sphinxAtStartPar +password expiration date + +\item[{\sphinxstylestrong{max\_life}}] \leavevmode +\sphinxAtStartPar +maximum ticket lifetime + +\item[{\sphinxstylestrong{max\_renew\_life}}] \leavevmode +\sphinxAtStartPar +maximum renewable ticket lifetime + +\end{description} + +\end{description} + +\sphinxAtStartPar +Examples: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYGZdl{} kdb5\PYGZus{}util tabdump \PYGZhy{}o keyinfo.txt keyinfo +\PYGZdl{} cat keyinfo.txt +name keyindex kvno enctype salttype salt +K/M@EXAMPLE.COM 0 1 aes256\PYGZhy{}cts\PYGZhy{}hmac\PYGZhy{}sha384\PYGZhy{}192 normal \PYGZhy{}1 +foo@EXAMPLE.COM 0 1 aes128\PYGZhy{}cts\PYGZhy{}hmac\PYGZhy{}sha1\PYGZhy{}96 normal \PYGZhy{}1 +bar@EXAMPLE.COM 0 1 aes128\PYGZhy{}cts\PYGZhy{}hmac\PYGZhy{}sha1\PYGZhy{}96 normal \PYGZhy{}1 +\PYGZdl{} sqlite3 +sqlite\PYGZgt{} .mode tabs +sqlite\PYGZgt{} .import keyinfo.txt keyinfo +sqlite\PYGZgt{} select * from keyinfo where enctype like \PYGZsq{}aes256\PYGZhy{}\PYGZpc{}\PYGZsq{}; +K/M@EXAMPLE.COM 1 1 aes256\PYGZhy{}cts\PYGZhy{}hmac\PYGZhy{}sha384\PYGZhy{}192 normal \PYGZhy{}1 +sqlite\PYGZgt{} .quit +\PYGZdl{} awk \PYGZhy{}F\PYGZsq{}\PYGZbs{}t\PYGZsq{} \PYGZsq{}\PYGZdl{}4 \PYGZti{} /aes256\PYGZhy{}/ \PYGZob{} print \PYGZcb{}\PYGZsq{} keyinfo.txt +K/M@EXAMPLE.COM 1 1 aes256\PYGZhy{}cts\PYGZhy{}hmac\PYGZhy{}sha384\PYGZhy{}192 normal \PYGZhy{}1 +\end{sphinxVerbatim} + + +\subsection{ENVIRONMENT} +\label{\detokenize{admin/admin_commands/kdb5_util:environment}} +\sphinxAtStartPar +See \DUrole{xref,std,std-ref}{kerberos(7)} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{admin/admin_commands/kdb5_util:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}}, \DUrole{xref,std,std-ref}{kerberos(7)} + + +\section{kdb5\_ldap\_util} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-8}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:synopsis}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{kdb5\_ldap\_util} +{[}\sphinxstylestrong{\sphinxhyphen{}D} \sphinxstyleemphasis{user\_dn} {[}\sphinxstylestrong{\sphinxhyphen{}w} \sphinxstyleemphasis{passwd}{]}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}H} \sphinxstyleemphasis{ldapuri}{]} +\sphinxstylestrong{command} +{[}\sphinxstyleemphasis{command\_options}{]} + + +\subsection{DESCRIPTION} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:description}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-synopsis-end}} +\sphinxAtStartPar +kdb5\_ldap\_util allows an administrator to manage realms, Kerberos +services and ticket policies. + + +\subsection{COMMAND\sphinxhyphen{}LINE OPTIONS} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:command-line-options}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm}}] \leavevmode +\sphinxAtStartPar +Specifies the realm to be operated on. + +\item[{\sphinxstylestrong{\sphinxhyphen{}D} \sphinxstyleemphasis{user\_dn}}] \leavevmode +\sphinxAtStartPar +Specifies the Distinguished Name (DN) of the user who has +sufficient rights to perform the operation on the LDAP server. + +\item[{\sphinxstylestrong{\sphinxhyphen{}w} \sphinxstyleemphasis{passwd}}] \leavevmode +\sphinxAtStartPar +Specifies the password of \sphinxstyleemphasis{user\_dn}. This option is not +recommended. + +\item[{\sphinxstylestrong{\sphinxhyphen{}H} \sphinxstyleemphasis{ldapuri}}] \leavevmode +\sphinxAtStartPar +Specifies the URI of the LDAP server. + +\end{description} + +\sphinxAtStartPar +By default, kdb5\_ldap\_util operates on the default realm (as specified +in {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}) and connects and authenticates to the LDAP +server in the same manner as :ref:kadmind(8)\textasciigrave{} would given the +parameters in {\hyperref[\detokenize{admin/conf_files/kdc_conf:dbdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}dbdefaults{]}}}}} in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. + + +\subsection{COMMANDS} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:commands}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-options-end}} + +\subsubsection{create} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:create}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-create}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{create} +{[}\sphinxstylestrong{\sphinxhyphen{}subtrees} \sphinxstyleemphasis{subtree\_dn\_list}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}sscope} \sphinxstyleemphasis{search\_scope}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}containerref} \sphinxstyleemphasis{container\_reference\_dn}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}k} \sphinxstyleemphasis{mkeytype}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}kv} \sphinxstyleemphasis{mkeyVNO}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}M} \sphinxstyleemphasis{mkeyname}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}m|\sphinxhyphen{}P} \sphinxstyleemphasis{password}|\sphinxstylestrong{\sphinxhyphen{}sf} \sphinxstyleemphasis{stashfilename}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}s}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}maxtktlife} \sphinxstyleemphasis{max\_ticket\_life}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}maxrenewlife} \sphinxstyleemphasis{max\_renewable\_ticket\_life}{]} +{[}\sphinxstyleemphasis{ticket\_flags}{]} +\end{quote} + +\sphinxAtStartPar +Creates realm in directory. Options: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}subtrees} \sphinxstyleemphasis{subtree\_dn\_list}}] \leavevmode +\sphinxAtStartPar +Specifies the list of subtrees containing the principals of a +realm. The list contains the DNs of the subtree objects separated +by colon (\sphinxcode{\sphinxupquote{:}}). + +\item[{\sphinxstylestrong{\sphinxhyphen{}sscope} \sphinxstyleemphasis{search\_scope}}] \leavevmode +\sphinxAtStartPar +Specifies the scope for searching the principals under the +subtree. The possible values are 1 or one (one level), 2 or sub +(subtrees). + +\item[{\sphinxstylestrong{\sphinxhyphen{}containerref} \sphinxstyleemphasis{container\_reference\_dn}}] \leavevmode +\sphinxAtStartPar +Specifies the DN of the container object in which the principals +of a realm will be created. If the container reference is not +configured for a realm, the principals will be created in the +realm container. + +\item[{\sphinxstylestrong{\sphinxhyphen{}k} \sphinxstyleemphasis{mkeytype}}] \leavevmode +\sphinxAtStartPar +Specifies the key type of the master key in the database. The +default is given by the \sphinxstylestrong{master\_key\_type} variable in +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}kv} \sphinxstyleemphasis{mkeyVNO}}] \leavevmode +\sphinxAtStartPar +Specifies the version number of the master key in the database; +the default is 1. Note that 0 is not allowed. + +\item[{\sphinxstylestrong{\sphinxhyphen{}M} \sphinxstyleemphasis{mkeyname}}] \leavevmode +\sphinxAtStartPar +Specifies the principal name for the master key in the database. +If not specified, the name is determined by the +\sphinxstylestrong{master\_key\_name} variable in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}m}}] \leavevmode +\sphinxAtStartPar +Specifies that the master database password should be read from +the TTY rather than fetched from a file on the disk. + +\item[{\sphinxstylestrong{\sphinxhyphen{}P} \sphinxstyleemphasis{password}}] \leavevmode +\sphinxAtStartPar +Specifies the master database password. This option is not +recommended. + +\item[{\sphinxstylestrong{\sphinxhyphen{}sf} \sphinxstyleemphasis{stashfilename}}] \leavevmode +\sphinxAtStartPar +Specifies the stash file of the master database password. + +\item[{\sphinxstylestrong{\sphinxhyphen{}s}}] \leavevmode +\sphinxAtStartPar +Specifies that the stash file is to be created. + +\item[{\sphinxstylestrong{\sphinxhyphen{}maxtktlife} \sphinxstyleemphasis{max\_ticket\_life}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{getdate} string) Specifies maximum ticket life for +principals in this realm. + +\item[{\sphinxstylestrong{\sphinxhyphen{}maxrenewlife} \sphinxstyleemphasis{max\_renewable\_ticket\_life}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{getdate} string) Specifies maximum renewable life of +tickets for principals in this realm. + +\item[{\sphinxstyleemphasis{ticket\_flags}}] \leavevmode +\sphinxAtStartPar +Specifies global ticket flags for the realm. Allowable flags are +documented in the description of the \sphinxstylestrong{add\_principal} command in +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}}. + +\end{description} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kdb5\PYGZus{}ldap\PYGZus{}util} \PYG{o}{\PYGZhy{}}\PYG{n}{D} \PYG{n}{cn}\PYG{o}{=}\PYG{n}{admin}\PYG{p}{,}\PYG{n}{o}\PYG{o}{=}\PYG{n}{org} \PYG{o}{\PYGZhy{}}\PYG{n}{H} \PYG{n}{ldaps}\PYG{p}{:}\PYG{o}{/}\PYG{o}{/}\PYG{n}{ldap}\PYG{o}{\PYGZhy{}}\PYG{n}{server1}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{o}{\PYGZhy{}}\PYG{n}{r} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{n}{create} \PYG{o}{\PYGZhy{}}\PYG{n}{subtrees} \PYG{n}{o}\PYG{o}{=}\PYG{n}{org} \PYG{o}{\PYGZhy{}}\PYG{n}{sscope} \PYG{n}{SUB} +\PYG{n}{Password} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=admin,o=org}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{:} +\PYG{n}{Initializing} \PYG{n}{database} \PYG{k}{for} \PYG{n}{realm} \PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{ATHENA.MIT.EDU}\PYG{l+s+s1}{\PYGZsq{}} +\PYG{n}{You} \PYG{n}{will} \PYG{n}{be} \PYG{n}{prompted} \PYG{k}{for} \PYG{n}{the} \PYG{n}{database} \PYG{n}{Master} \PYG{n}{Password}\PYG{o}{.} +\PYG{n}{It} \PYG{o+ow}{is} \PYG{n}{important} \PYG{n}{that} \PYG{n}{you} \PYG{n}{NOT} \PYG{n}{FORGET} \PYG{n}{this} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Enter} \PYG{n}{KDC} \PYG{n}{database} \PYG{n}{master} \PYG{n}{key}\PYG{p}{:} +\PYG{n}{Re}\PYG{o}{\PYGZhy{}}\PYG{n}{enter} \PYG{n}{KDC} \PYG{n}{database} \PYG{n}{master} \PYG{n}{key} \PYG{n}{to} \PYG{n}{verify}\PYG{p}{:} +\end{sphinxVerbatim} + + +\subsubsection{modify} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:modify}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-create-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-modify}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{modify} +{[}\sphinxstylestrong{\sphinxhyphen{}subtrees} \sphinxstyleemphasis{subtree\_dn\_list}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}sscope} \sphinxstyleemphasis{search\_scope}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}containerref} \sphinxstyleemphasis{container\_reference\_dn}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}maxtktlife} \sphinxstyleemphasis{max\_ticket\_life}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}maxrenewlife} \sphinxstyleemphasis{max\_renewable\_ticket\_life}{]} +{[}\sphinxstyleemphasis{ticket\_flags}{]} +\end{quote} + +\sphinxAtStartPar +Modifies the attributes of a realm. Options: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}subtrees} \sphinxstyleemphasis{subtree\_dn\_list}}] \leavevmode +\sphinxAtStartPar +Specifies the list of subtrees containing the principals of a +realm. The list contains the DNs of the subtree objects separated +by colon (\sphinxcode{\sphinxupquote{:}}). This list replaces the existing list. + +\item[{\sphinxstylestrong{\sphinxhyphen{}sscope} \sphinxstyleemphasis{search\_scope}}] \leavevmode +\sphinxAtStartPar +Specifies the scope for searching the principals under the +subtrees. The possible values are 1 or one (one level), 2 or sub +(subtrees). + +\item[{\sphinxstylestrong{\sphinxhyphen{}containerref} \sphinxstyleemphasis{container\_reference\_dn} Specifies the DN of the}] \leavevmode +\sphinxAtStartPar +container object in which the principals of a realm will be +created. + +\item[{\sphinxstylestrong{\sphinxhyphen{}maxtktlife} \sphinxstyleemphasis{max\_ticket\_life}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{getdate} string) Specifies maximum ticket life for +principals in this realm. + +\item[{\sphinxstylestrong{\sphinxhyphen{}maxrenewlife} \sphinxstyleemphasis{max\_renewable\_ticket\_life}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{getdate} string) Specifies maximum renewable life of +tickets for principals in this realm. + +\item[{\sphinxstyleemphasis{ticket\_flags}}] \leavevmode +\sphinxAtStartPar +Specifies global ticket flags for the realm. Allowable flags are +documented in the description of the \sphinxstylestrong{add\_principal} command in +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}}. + +\end{description} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kdb5\PYGZus{}ldap\PYGZus{}util} \PYG{o}{\PYGZhy{}}\PYG{n}{r} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{\PYGZhy{}}\PYG{n}{D} \PYG{n}{cn}\PYG{o}{=}\PYG{n}{admin}\PYG{p}{,}\PYG{n}{o}\PYG{o}{=}\PYG{n}{org} \PYG{o}{\PYGZhy{}}\PYG{n}{H} + \PYG{n}{ldaps}\PYG{p}{:}\PYG{o}{/}\PYG{o}{/}\PYG{n}{ldap}\PYG{o}{\PYGZhy{}}\PYG{n}{server1}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{n}{modify} \PYG{o}{+}\PYG{n}{requires\PYGZus{}preauth} +\PYG{n}{Password} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=admin,o=org}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{:} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + + +\subsubsection{view} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:view}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-modify-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-view}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{view} +\end{quote} + +\sphinxAtStartPar +Displays the attributes of a realm. + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kdb5\PYGZus{}ldap\PYGZus{}util} \PYG{o}{\PYGZhy{}}\PYG{n}{D} \PYG{n}{cn}\PYG{o}{=}\PYG{n}{admin}\PYG{p}{,}\PYG{n}{o}\PYG{o}{=}\PYG{n}{org} \PYG{o}{\PYGZhy{}}\PYG{n}{H} \PYG{n}{ldaps}\PYG{p}{:}\PYG{o}{/}\PYG{o}{/}\PYG{n}{ldap}\PYG{o}{\PYGZhy{}}\PYG{n}{server1}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{o}{\PYGZhy{}}\PYG{n}{r} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{n}{view} +\PYG{n}{Password} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=admin,o=org}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{:} +\PYG{n}{Realm} \PYG{n}{Name}\PYG{p}{:} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{n}{Subtree}\PYG{p}{:} \PYG{n}{ou}\PYG{o}{=}\PYG{n}{users}\PYG{p}{,}\PYG{n}{o}\PYG{o}{=}\PYG{n}{org} +\PYG{n}{Subtree}\PYG{p}{:} \PYG{n}{ou}\PYG{o}{=}\PYG{n}{servers}\PYG{p}{,}\PYG{n}{o}\PYG{o}{=}\PYG{n}{org} +\PYG{n}{SearchScope}\PYG{p}{:} \PYG{n}{ONE} +\PYG{n}{Maximum} \PYG{n}{ticket} \PYG{n}{life}\PYG{p}{:} \PYG{l+m+mi}{0} \PYG{n}{days} \PYG{l+m+mi}{01}\PYG{p}{:}\PYG{l+m+mi}{00}\PYG{p}{:}\PYG{l+m+mi}{00} +\PYG{n}{Maximum} \PYG{n}{renewable} \PYG{n}{life}\PYG{p}{:} \PYG{l+m+mi}{0} \PYG{n}{days} \PYG{l+m+mi}{10}\PYG{p}{:}\PYG{l+m+mi}{00}\PYG{p}{:}\PYG{l+m+mi}{00} +\PYG{n}{Ticket} \PYG{n}{flags}\PYG{p}{:} \PYG{n}{DISALLOW\PYGZus{}FORWARDABLE} \PYG{n}{REQUIRES\PYGZus{}PWCHANGE} +\end{sphinxVerbatim} + + +\subsubsection{destroy} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:destroy}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-view-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-destroy}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{destroy} {[}\sphinxstylestrong{\sphinxhyphen{}f}{]} +\end{quote} + +\sphinxAtStartPar +Destroys an existing realm. Options: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}f}}] \leavevmode +\sphinxAtStartPar +If specified, will not prompt the user for confirmation. + +\end{description} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +shell\PYGZpc{} kdb5\PYGZus{}ldap\PYGZus{}util \PYGZhy{}r ATHENA.MIT.EDU \PYGZhy{}D cn=admin,o=org \PYGZhy{}H + ldaps://ldap\PYGZhy{}server1.mit.edu destroy +Password for \PYGZdq{}cn=admin,o=org\PYGZdq{}: +Deleting KDC database of \PYGZsq{}ATHENA.MIT.EDU\PYGZsq{}, are you sure? +(type \PYGZsq{}yes\PYGZsq{} to confirm)? yes +OK, deleting database of \PYGZsq{}ATHENA.MIT.EDU\PYGZsq{}... +shell\PYGZpc{} +\end{sphinxVerbatim} + + +\subsubsection{list} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:list}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-destroy-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-list}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{list} +\end{quote} + +\sphinxAtStartPar +Lists the names of realms under the container. + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kdb5\PYGZus{}ldap\PYGZus{}util} \PYG{o}{\PYGZhy{}}\PYG{n}{D} \PYG{n}{cn}\PYG{o}{=}\PYG{n}{admin}\PYG{p}{,}\PYG{n}{o}\PYG{o}{=}\PYG{n}{org} \PYG{o}{\PYGZhy{}}\PYG{n}{H} + \PYG{n}{ldaps}\PYG{p}{:}\PYG{o}{/}\PYG{o}{/}\PYG{n}{ldap}\PYG{o}{\PYGZhy{}}\PYG{n}{server1}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{n+nb}{list} +\PYG{n}{Password} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=admin,o=org}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{:} +\PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{n}{OPENLDAP}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{n}{MEDIA}\PYG{o}{\PYGZhy{}}\PYG{n}{LAB}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + + +\subsubsection{stashsrvpw} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:stashsrvpw}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-list-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-stashsrvpw}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{stashsrvpw} +{[}\sphinxstylestrong{\sphinxhyphen{}f} \sphinxstyleemphasis{filename}{]} +\sphinxstyleemphasis{name} +\end{quote} + +\sphinxAtStartPar +Allows an administrator to store the password for service object in a +file so that KDC and Administration server can use it to authenticate +to the LDAP server. Options: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}f} \sphinxstyleemphasis{filename}}] \leavevmode +\sphinxAtStartPar +Specifies the complete path of the service password file. By +default, \sphinxcode{\sphinxupquote{/usr/local/var/service\_passwd}} is used. + +\item[{\sphinxstyleemphasis{name}}] \leavevmode +\sphinxAtStartPar +Specifies the name of the object whose password is to be stored. +If {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}} or {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} are configured for +simple binding, this should be the distinguished name it will +use as given by the \sphinxstylestrong{ldap\_kdc\_dn} or \sphinxstylestrong{ldap\_kadmind\_dn} +variable in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. If the KDC or kadmind is +configured for SASL binding, this should be the authentication +name it will use as given by the \sphinxstylestrong{ldap\_kdc\_sasl\_authcid} or +\sphinxstylestrong{ldap\_kadmind\_sasl\_authcid} variable. + +\end{description} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kdb5\PYGZus{}ldap\PYGZus{}util} \PYG{n}{stashsrvpw} \PYG{o}{\PYGZhy{}}\PYG{n}{f} \PYG{o}{/}\PYG{n}{home}\PYG{o}{/}\PYG{n}{andrew}\PYG{o}{/}\PYG{n}{conf\PYGZus{}keyfile} + \PYG{n}{cn}\PYG{o}{=}\PYG{n}{service}\PYG{o}{\PYGZhy{}}\PYG{n}{kdc}\PYG{p}{,}\PYG{n}{o}\PYG{o}{=}\PYG{n}{org} +\PYG{n}{Password} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=service\PYGZhy{}kdc,o=org}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{:} +\PYG{n}{Re}\PYG{o}{\PYGZhy{}}\PYG{n}{enter} \PYG{n}{password} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=service\PYGZhy{}kdc,o=org}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{:} +\end{sphinxVerbatim} + + +\subsubsection{create\_policy} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:create-policy}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-stashsrvpw-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-create-policy}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{create\_policy} +{[}\sphinxstylestrong{\sphinxhyphen{}maxtktlife} \sphinxstyleemphasis{max\_ticket\_life}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}maxrenewlife} \sphinxstyleemphasis{max\_renewable\_ticket\_life}{]} +{[}\sphinxstyleemphasis{ticket\_flags}{]} +\sphinxstyleemphasis{policy\_name} +\end{quote} + +\sphinxAtStartPar +Creates a ticket policy in the directory. Options: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}maxtktlife} \sphinxstyleemphasis{max\_ticket\_life}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{getdate} string) Specifies maximum ticket life for +principals. + +\item[{\sphinxstylestrong{\sphinxhyphen{}maxrenewlife} \sphinxstyleemphasis{max\_renewable\_ticket\_life}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{getdate} string) Specifies maximum renewable life of +tickets for principals. + +\item[{\sphinxstyleemphasis{ticket\_flags}}] \leavevmode +\sphinxAtStartPar +Specifies the ticket flags. If this option is not specified, by +default, no restriction will be set by the policy. Allowable +flags are documented in the description of the \sphinxstylestrong{add\_principal} +command in {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}}. + +\item[{\sphinxstyleemphasis{policy\_name}}] \leavevmode +\sphinxAtStartPar +Specifies the name of the ticket policy. + +\end{description} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kdb5\PYGZus{}ldap\PYGZus{}util} \PYG{o}{\PYGZhy{}}\PYG{n}{D} \PYG{n}{cn}\PYG{o}{=}\PYG{n}{admin}\PYG{p}{,}\PYG{n}{o}\PYG{o}{=}\PYG{n}{org} \PYG{o}{\PYGZhy{}}\PYG{n}{H} \PYG{n}{ldaps}\PYG{p}{:}\PYG{o}{/}\PYG{o}{/}\PYG{n}{ldap}\PYG{o}{\PYGZhy{}}\PYG{n}{server1}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{o}{\PYGZhy{}}\PYG{n}{r} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{n}{create\PYGZus{}policy} \PYG{o}{\PYGZhy{}}\PYG{n}{maxtktlife} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{1 day}\PYG{l+s+s2}{\PYGZdq{}} + \PYG{o}{\PYGZhy{}}\PYG{n}{maxrenewlife} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{1 week}\PYG{l+s+s2}{\PYGZdq{}} \PYG{o}{\PYGZhy{}}\PYG{n}{allow\PYGZus{}postdated} \PYG{o}{+}\PYG{n}{needchange} + \PYG{o}{\PYGZhy{}}\PYG{n}{allow\PYGZus{}forwardable} \PYG{n}{tktpolicy} +\PYG{n}{Password} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=admin,o=org}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{:} +\end{sphinxVerbatim} + + +\subsubsection{modify\_policy} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:modify-policy}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-create-policy-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-modify-policy}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{modify\_policy} +{[}\sphinxstylestrong{\sphinxhyphen{}maxtktlife} \sphinxstyleemphasis{max\_ticket\_life}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}maxrenewlife} \sphinxstyleemphasis{max\_renewable\_ticket\_life}{]} +{[}\sphinxstyleemphasis{ticket\_flags}{]} +\sphinxstyleemphasis{policy\_name} +\end{quote} + +\sphinxAtStartPar +Modifies the attributes of a ticket policy. Options are same as for +\sphinxstylestrong{create\_policy}. + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kdb5\PYGZus{}ldap\PYGZus{}util} \PYG{o}{\PYGZhy{}}\PYG{n}{D} \PYG{n}{cn}\PYG{o}{=}\PYG{n}{admin}\PYG{p}{,}\PYG{n}{o}\PYG{o}{=}\PYG{n}{org} \PYG{o}{\PYGZhy{}}\PYG{n}{H} + \PYG{n}{ldaps}\PYG{p}{:}\PYG{o}{/}\PYG{o}{/}\PYG{n}{ldap}\PYG{o}{\PYGZhy{}}\PYG{n}{server1}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} \PYG{o}{\PYGZhy{}}\PYG{n}{r} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{n}{modify\PYGZus{}policy} + \PYG{o}{\PYGZhy{}}\PYG{n}{maxtktlife} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{60 minutes}\PYG{l+s+s2}{\PYGZdq{}} \PYG{o}{\PYGZhy{}}\PYG{n}{maxrenewlife} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{10 hours}\PYG{l+s+s2}{\PYGZdq{}} + \PYG{o}{+}\PYG{n}{allow\PYGZus{}postdated} \PYG{o}{\PYGZhy{}}\PYG{n}{requires\PYGZus{}preauth} \PYG{n}{tktpolicy} +\PYG{n}{Password} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=admin,o=org}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{:} +\end{sphinxVerbatim} + + +\subsubsection{view\_policy} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:view-policy}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-modify-policy-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-view-policy}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{view\_policy} +\sphinxstyleemphasis{policy\_name} +\end{quote} + +\sphinxAtStartPar +Displays the attributes of the named ticket policy. + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kdb5\PYGZus{}ldap\PYGZus{}util} \PYG{o}{\PYGZhy{}}\PYG{n}{D} \PYG{n}{cn}\PYG{o}{=}\PYG{n}{admin}\PYG{p}{,}\PYG{n}{o}\PYG{o}{=}\PYG{n}{org} \PYG{o}{\PYGZhy{}}\PYG{n}{H} \PYG{n}{ldaps}\PYG{p}{:}\PYG{o}{/}\PYG{o}{/}\PYG{n}{ldap}\PYG{o}{\PYGZhy{}}\PYG{n}{server1}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{o}{\PYGZhy{}}\PYG{n}{r} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{n}{view\PYGZus{}policy} \PYG{n}{tktpolicy} +\PYG{n}{Password} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=admin,o=org}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{:} +\PYG{n}{Ticket} \PYG{n}{policy}\PYG{p}{:} \PYG{n}{tktpolicy} +\PYG{n}{Maximum} \PYG{n}{ticket} \PYG{n}{life}\PYG{p}{:} \PYG{l+m+mi}{0} \PYG{n}{days} \PYG{l+m+mi}{01}\PYG{p}{:}\PYG{l+m+mi}{00}\PYG{p}{:}\PYG{l+m+mi}{00} +\PYG{n}{Maximum} \PYG{n}{renewable} \PYG{n}{life}\PYG{p}{:} \PYG{l+m+mi}{0} \PYG{n}{days} \PYG{l+m+mi}{10}\PYG{p}{:}\PYG{l+m+mi}{00}\PYG{p}{:}\PYG{l+m+mi}{00} +\PYG{n}{Ticket} \PYG{n}{flags}\PYG{p}{:} \PYG{n}{DISALLOW\PYGZus{}FORWARDABLE} \PYG{n}{REQUIRES\PYGZus{}PWCHANGE} +\end{sphinxVerbatim} + + +\subsubsection{destroy\_policy} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:destroy-policy}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-view-policy-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-destroy-policy}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{destroy\_policy} +{[}\sphinxstylestrong{\sphinxhyphen{}force}{]} +\sphinxstyleemphasis{policy\_name} +\end{quote} + +\sphinxAtStartPar +Destroys an existing ticket policy. Options: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}force}}] \leavevmode +\sphinxAtStartPar +Forces the deletion of the policy object. If not specified, the +user will be prompted for confirmation before deleting the policy. + +\item[{\sphinxstyleemphasis{policy\_name}}] \leavevmode +\sphinxAtStartPar +Specifies the name of the ticket policy. + +\end{description} + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +kdb5\PYGZus{}ldap\PYGZus{}util \PYGZhy{}D cn=admin,o=org \PYGZhy{}H ldaps://ldap\PYGZhy{}server1.mit.edu + \PYGZhy{}r ATHENA.MIT.EDU destroy\PYGZus{}policy tktpolicy +Password for \PYGZdq{}cn=admin,o=org\PYGZdq{}: +This will delete the policy object \PYGZsq{}tktpolicy\PYGZsq{}, are you sure? +(type \PYGZsq{}yes\PYGZsq{} to confirm)? yes +** policy object \PYGZsq{}tktpolicy\PYGZsq{} deleted. +\end{sphinxVerbatim} + + +\subsubsection{list\_policy} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:list-policy}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-destroy-policy-end}}\phantomsection\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-list-policy}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{list\_policy} +\end{quote} + +\sphinxAtStartPar +Lists ticket policies. + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kdb5\PYGZus{}ldap\PYGZus{}util} \PYG{o}{\PYGZhy{}}\PYG{n}{D} \PYG{n}{cn}\PYG{o}{=}\PYG{n}{admin}\PYG{p}{,}\PYG{n}{o}\PYG{o}{=}\PYG{n}{org} \PYG{o}{\PYGZhy{}}\PYG{n}{H} \PYG{n}{ldaps}\PYG{p}{:}\PYG{o}{/}\PYG{o}{/}\PYG{n}{ldap}\PYG{o}{\PYGZhy{}}\PYG{n}{server1}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu} + \PYG{o}{\PYGZhy{}}\PYG{n}{r} \PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{n}{list\PYGZus{}policy} +\PYG{n}{Password} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{cn=admin,o=org}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{:} +\PYG{n}{tktpolicy} +\PYG{n}{tmppolicy} +\PYG{n}{userpolicy} +\end{sphinxVerbatim} + + +\subsection{ENVIRONMENT} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:environment}}\label{\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-list-policy-end}} +\sphinxAtStartPar +See \DUrole{xref,std,std-ref}{kerberos(7)} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{admin/admin_commands/kdb5_ldap_util:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}}, \DUrole{xref,std,std-ref}{kerberos(7)} + + +\section{krb5kdc} +\label{\detokenize{admin/admin_commands/krb5kdc:krb5kdc}}\label{\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}}\label{\detokenize{admin/admin_commands/krb5kdc::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{admin/admin_commands/krb5kdc:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{krb5kdc} +{[}\sphinxstylestrong{\sphinxhyphen{}x} \sphinxstyleemphasis{db\_args}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}d} \sphinxstyleemphasis{dbname}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}k} \sphinxstyleemphasis{keytype}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}M} \sphinxstyleemphasis{mkeyname}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{portnum}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}m}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}n}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}w} \sphinxstyleemphasis{numworkers}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}P} \sphinxstyleemphasis{pid\_file}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}T} \sphinxstyleemphasis{time\_offset}{]} + + +\subsection{DESCRIPTION} +\label{\detokenize{admin/admin_commands/krb5kdc:description}} +\sphinxAtStartPar +krb5kdc is the Kerberos version 5 Authentication Service and Key +Distribution Center (AS/KDC). + + +\subsection{OPTIONS} +\label{\detokenize{admin/admin_commands/krb5kdc:options}} +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm} option specifies the realm for which the server +should provide service. This option may be specified multiple times +to serve multiple realms. If no \sphinxstylestrong{\sphinxhyphen{}r} option is given, the default +realm (as specified in {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}) will be served. + +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}d} \sphinxstyleemphasis{dbname} option specifies the name under which the +principal database can be found. This option does not apply to the +LDAP database. + +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}k} \sphinxstyleemphasis{keytype} option specifies the key type of the master key +to be entered manually as a password when \sphinxstylestrong{\sphinxhyphen{}m} is given; the default +is \sphinxcode{\sphinxupquote{aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96}}. + +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}M} \sphinxstyleemphasis{mkeyname} option specifies the principal name for the +master key in the database (usually \sphinxcode{\sphinxupquote{K/M}} in the KDC’s realm). + +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}m} option specifies that the master database password should +be fetched from the keyboard rather than from a stash file. + +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}n} option specifies that the KDC does not put itself in the +background and does not disassociate itself from the terminal. + +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}P} \sphinxstyleemphasis{pid\_file} option tells the KDC to write its PID into +\sphinxstyleemphasis{pid\_file} after it starts up. This can be used to identify whether +the KDC is still running and to allow init scripts to stop the correct +process. + +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{portnum} option specifies the default UDP and TCP port +numbers which the KDC should listen on for Kerberos version 5 +requests, as a comma\sphinxhyphen{}separated list. This value overrides the port +numbers specified in the {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdcdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}kdcdefaults{]}}}}} section of +{\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}, but may be overridden by realm\sphinxhyphen{}specific values. +If no value is given from any source, the default port is 88. + +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}w} \sphinxstyleemphasis{numworkers} option tells the KDC to fork \sphinxstyleemphasis{numworkers} +processes to listen to the KDC ports and process requests in parallel. +The top level KDC process (whose pid is recorded in the pid file if +the \sphinxstylestrong{\sphinxhyphen{}P} option is also given) acts as a supervisor. The supervisor +will relay SIGHUP signals to the worker subprocesses, and will +terminate the worker subprocess if the it is itself terminated or if +any other worker process exits. + +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}x} \sphinxstyleemphasis{db\_args} option specifies database\sphinxhyphen{}specific arguments. +See {\hyperref[\detokenize{admin/admin_commands/kadmin_local:dboptions}]{\sphinxcrossref{\DUrole{std,std-ref}{Database Options}}}} in {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} for +supported arguments. + +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}T} \sphinxstyleemphasis{offset} option specifies a time offset, in seconds, which +the KDC will operate under. It is intended only for testing purposes. + + +\subsection{EXAMPLE} +\label{\detokenize{admin/admin_commands/krb5kdc:example}} +\sphinxAtStartPar +The KDC may service requests for multiple realms (maximum 32 realms). +The realms are listed on the command line. Per\sphinxhyphen{}realm options that can +be specified on the command line pertain for each realm that follows +it and are superseded by subsequent definitions of the same option. + +\sphinxAtStartPar +For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{krb5kdc} \PYG{o}{\PYGZhy{}}\PYG{n}{p} \PYG{l+m+mi}{2001} \PYG{o}{\PYGZhy{}}\PYG{n}{r} \PYG{n}{REALM1} \PYG{o}{\PYGZhy{}}\PYG{n}{p} \PYG{l+m+mi}{2002} \PYG{o}{\PYGZhy{}}\PYG{n}{r} \PYG{n}{REALM2} \PYG{o}{\PYGZhy{}}\PYG{n}{r} \PYG{n}{REALM3} +\end{sphinxVerbatim} + +\sphinxAtStartPar +specifies that the KDC listen on port 2001 for REALM1 and on port 2002 +for REALM2 and REALM3. Additionally, per\sphinxhyphen{}realm parameters may be +specified in the {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} file. The location of this file +may be specified by the \sphinxstylestrong{KRB5\_KDC\_PROFILE} environment variable. +Per\sphinxhyphen{}realm parameters specified in this file take precedence over +options specified on the command line. See the {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} +description for further details. + + +\subsection{ENVIRONMENT} +\label{\detokenize{admin/admin_commands/krb5kdc:environment}} +\sphinxAtStartPar +See \DUrole{xref,std,std-ref}{kerberos(7)} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{admin/admin_commands/krb5kdc:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}}, {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}, {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}, +{\hyperref[\detokenize{admin/admin_commands/kdb5_ldap_util:kdb5-ldap-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_ldap\_util}}}}, \DUrole{xref,std,std-ref}{kerberos(7)} + + +\section{kprop} +\label{\detokenize{admin/admin_commands/kprop:kprop}}\label{\detokenize{admin/admin_commands/kprop:kprop-8}}\label{\detokenize{admin/admin_commands/kprop::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{admin/admin_commands/kprop:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{kprop} +{[}\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}f} \sphinxstyleemphasis{file}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}d}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}P} \sphinxstyleemphasis{port}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}s} \sphinxstyleemphasis{keytab}{]} +\sphinxstyleemphasis{replica\_host} + + +\subsection{DESCRIPTION} +\label{\detokenize{admin/admin_commands/kprop:description}} +\sphinxAtStartPar +kprop is used to securely propagate a Kerberos V5 database dump file +from the primary Kerberos server to a replica Kerberos server, which is +specified by \sphinxstyleemphasis{replica\_host}. The dump file must be created by +{\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}}. + + +\subsection{OPTIONS} +\label{\detokenize{admin/admin_commands/kprop:options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm}}] \leavevmode +\sphinxAtStartPar +Specifies the realm of the primary server. + +\item[{\sphinxstylestrong{\sphinxhyphen{}f} \sphinxstyleemphasis{file}}] \leavevmode +\sphinxAtStartPar +Specifies the filename where the dumped principal database file is +to be found; by default the dumped database file is normally +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/replica\_datatrans}}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}P} \sphinxstyleemphasis{port}}] \leavevmode +\sphinxAtStartPar +Specifies the port to use to contact the {\hyperref[\detokenize{admin/admin_commands/kpropd:kpropd-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kpropd}}}} server +on the remote host. + +\item[{\sphinxstylestrong{\sphinxhyphen{}d}}] \leavevmode +\sphinxAtStartPar +Prints debugging information. + +\item[{\sphinxstylestrong{\sphinxhyphen{}s} \sphinxstyleemphasis{keytab}}] \leavevmode +\sphinxAtStartPar +Specifies the location of the keytab file. + +\end{description} + + +\subsection{ENVIRONMENT} +\label{\detokenize{admin/admin_commands/kprop:environment}} +\sphinxAtStartPar +See \DUrole{xref,std,std-ref}{kerberos(7)} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{admin/admin_commands/kprop:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kpropd:kpropd-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kpropd}}}}, {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}}, {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}}, +\DUrole{xref,std,std-ref}{kerberos(7)} + + +\section{kpropd} +\label{\detokenize{admin/admin_commands/kpropd:kpropd}}\label{\detokenize{admin/admin_commands/kpropd:kpropd-8}}\label{\detokenize{admin/admin_commands/kpropd::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{admin/admin_commands/kpropd:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{kpropd} +{[}\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}A} \sphinxstyleemphasis{admin\_server}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}a} \sphinxstyleemphasis{acl\_file}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}f} \sphinxstyleemphasis{replica\_dumpfile}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}F} \sphinxstyleemphasis{principal\_database}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{kdb5\_util\_prog}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}P} \sphinxstyleemphasis{port}{]} +{[}\sphinxstylestrong{\textendash{}pid\sphinxhyphen{}file}=\sphinxstyleemphasis{pid\_file}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}D}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}d}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}s} \sphinxstyleemphasis{keytab\_file}{]} + + +\subsection{DESCRIPTION} +\label{\detokenize{admin/admin_commands/kpropd:description}} +\sphinxAtStartPar +The \sphinxstyleemphasis{kpropd} command runs on the replica KDC server. It listens for +update requests made by the {\hyperref[\detokenize{admin/admin_commands/kprop:kprop-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop}}}} program. If incremental +propagation is enabled, it periodically requests incremental updates +from the primary KDC. + +\sphinxAtStartPar +When the replica receives a kprop request from the primary, kpropd +accepts the dumped KDC database and places it in a file, and then runs +{\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} to load the dumped database into the active +database which is used by {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}}. This allows the primary +Kerberos server to use {\hyperref[\detokenize{admin/admin_commands/kprop:kprop-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop}}}} to propagate its database to +the replica servers. Upon a successful download of the KDC database +file, the replica Kerberos server will have an up\sphinxhyphen{}to\sphinxhyphen{}date KDC +database. + +\sphinxAtStartPar +Where incremental propagation is not used, kpropd is commonly invoked +out of inetd(8) as a nowait service. This is done by adding a line to +the \sphinxcode{\sphinxupquote{/etc/inetd.conf}} file which looks like this: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kprop} \PYG{n}{stream} \PYG{n}{tcp} \PYG{n}{nowait} \PYG{n}{root} \PYG{o}{/}\PYG{n}{usr}\PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{sbin}\PYG{o}{/}\PYG{n}{kpropd} \PYG{n}{kpropd} +\end{sphinxVerbatim} + +\sphinxAtStartPar +kpropd can also run as a standalone daemon, backgrounding itself and +waiting for connections on port 754 (or the port specified with the +\sphinxstylestrong{\sphinxhyphen{}P} option if given). Standalone mode is required for incremental +propagation. Starting in release 1.11, kpropd automatically detects +whether it was run from inetd and runs in standalone mode if it is +not. Prior to release 1.11, the \sphinxstylestrong{\sphinxhyphen{}S} option is required to run +kpropd in standalone mode; this option is now accepted for backward +compatibility but does nothing. + +\sphinxAtStartPar +Incremental propagation may be enabled with the \sphinxstylestrong{iprop\_enable} +variable in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}}. If incremental propagation is +enabled, the replica periodically polls the primary KDC for updates, at +an interval determined by the \sphinxstylestrong{iprop\_replica\_poll} variable. If the +replica receives updates, kpropd updates its log file with any updates +from the primary. {\hyperref[\detokenize{admin/admin_commands/kproplog:kproplog-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kproplog}}}} can be used to view a summary of +the update entry log on the replica KDC. If incremental propagation +is enabled, the principal \sphinxcode{\sphinxupquote{kiprop/replicahostname@REALM}} (where +\sphinxstyleemphasis{replicahostname} is the name of the replica KDC host, and \sphinxstyleemphasis{REALM} is +the name of the Kerberos realm) must be present in the replica’s +keytab file. + +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kproplog:kproplog-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kproplog}}}} can be used to force full replication when iprop is +enabled. + + +\subsection{OPTIONS} +\label{\detokenize{admin/admin_commands/kpropd:options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{realm}}] \leavevmode +\sphinxAtStartPar +Specifies the realm of the primary server. + +\item[{\sphinxstylestrong{\sphinxhyphen{}A} \sphinxstyleemphasis{admin\_server}}] \leavevmode +\sphinxAtStartPar +Specifies the server to be contacted for incremental updates; by +default, the primary admin server is contacted. + +\item[{\sphinxstylestrong{\sphinxhyphen{}f} \sphinxstyleemphasis{file}}] \leavevmode +\sphinxAtStartPar +Specifies the filename where the dumped principal database file is +to be stored; by default the dumped database file is {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/from\_master}}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}F} \sphinxstyleemphasis{kerberos\_db}}] \leavevmode +\sphinxAtStartPar +Path to the Kerberos database file, if not the default. + +\item[{\sphinxstylestrong{\sphinxhyphen{}p}}] \leavevmode +\sphinxAtStartPar +Allows the user to specify the pathname to the {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}} +program; by default the pathname used is {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{SBINDIR}}}}\sphinxcode{\sphinxupquote{/kdb5\_util}}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}D}}] \leavevmode +\sphinxAtStartPar +In this mode, kpropd will not detach itself from the current job +and run in the background. Instead, it will run in the +foreground. + +\item[{\sphinxstylestrong{\sphinxhyphen{}d}}] \leavevmode +\sphinxAtStartPar +Turn on debug mode. kpropd will print out debugging messages +during the database propogation and will run in the foreground +(implies \sphinxstylestrong{\sphinxhyphen{}D}). + +\item[{\sphinxstylestrong{\sphinxhyphen{}P}}] \leavevmode +\sphinxAtStartPar +Allow for an alternate port number for kpropd to listen on. This +is only useful in combination with the \sphinxstylestrong{\sphinxhyphen{}S} option. + +\item[{\sphinxstylestrong{\sphinxhyphen{}a} \sphinxstyleemphasis{acl\_file}}] \leavevmode +\sphinxAtStartPar +Allows the user to specify the path to the kpropd.acl file; by +default the path used is {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/kpropd.acl}}. + +\item[{\sphinxstylestrong{\textendash{}pid\sphinxhyphen{}file}=\sphinxstyleemphasis{pid\_file}}] \leavevmode +\sphinxAtStartPar +In standalone mode, write the process ID of the daemon into +\sphinxstyleemphasis{pid\_file}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}s} \sphinxstyleemphasis{keytab\_file}}] \leavevmode +\sphinxAtStartPar +Path to a keytab to use for acquiring acceptor credentials. + +\item[{\sphinxstylestrong{\sphinxhyphen{}x} \sphinxstyleemphasis{db\_args}}] \leavevmode +\sphinxAtStartPar +Database\sphinxhyphen{}specific arguments. See {\hyperref[\detokenize{admin/admin_commands/kadmin_local:dboptions}]{\sphinxcrossref{\DUrole{std,std-ref}{Database Options}}}} in {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} for supported arguments. + +\end{description} + + +\subsection{FILES} +\label{\detokenize{admin/admin_commands/kpropd:files}}\begin{description} +\item[{kpropd.acl}] \leavevmode +\sphinxAtStartPar +Access file for kpropd; the default location is +\sphinxcode{\sphinxupquote{/usr/local/var/krb5kdc/kpropd.acl}}. Each entry is a line +containing the principal of a host from which the local machine +will allow Kerberos database propagation via {\hyperref[\detokenize{admin/admin_commands/kprop:kprop-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop}}}}. + +\end{description} + + +\subsection{ENVIRONMENT} +\label{\detokenize{admin/admin_commands/kpropd:environment}} +\sphinxAtStartPar +See \DUrole{xref,std,std-ref}{kerberos(7)} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{admin/admin_commands/kpropd:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kprop:kprop-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop}}}}, {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}}, {\hyperref[\detokenize{admin/admin_commands/krb5kdc:krb5kdc-8}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5kdc}}}}, +\DUrole{xref,std,std-ref}{kerberos(7)}, inetd(8) + + +\section{kproplog} +\label{\detokenize{admin/admin_commands/kproplog:kproplog}}\label{\detokenize{admin/admin_commands/kproplog:kproplog-8}}\label{\detokenize{admin/admin_commands/kproplog::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{admin/admin_commands/kproplog:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{kproplog} {[}\sphinxstylestrong{\sphinxhyphen{}h}{]} {[}\sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{num}{]} {[}\sphinxhyphen{}v{]} +\sphinxstylestrong{kproplog} {[}\sphinxhyphen{}R{]} + + +\subsection{DESCRIPTION} +\label{\detokenize{admin/admin_commands/kproplog:description}} +\sphinxAtStartPar +The kproplog command displays the contents of the KDC database update +log to standard output. It can be used to keep track of incremental +updates to the principal database. The update log file contains the +update log maintained by the {\hyperref[\detokenize{admin/admin_commands/kadmind:kadmind-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmind}}}} process on the primary +KDC server and the {\hyperref[\detokenize{admin/admin_commands/kpropd:kpropd-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kpropd}}}} process on the replica KDC +servers. When updates occur, they are logged to this file. +Subsequently any KDC replica configured for incremental updates will +request the current data from the primary KDC and update their log +file with any updates returned. + +\sphinxAtStartPar +The kproplog command requires read access to the update log file. It +will display update entries only for the KDC it runs on. + +\sphinxAtStartPar +If no options are specified, kproplog displays a summary of the update +log. If invoked on the primary, kproplog also displays all of the +update entries. If invoked on a replica KDC server, kproplog displays +only a summary of the updates, which includes the serial number of the +last update received and the associated time stamp of the last update. + + +\subsection{OPTIONS} +\label{\detokenize{admin/admin_commands/kproplog:options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}R}}] \leavevmode +\sphinxAtStartPar +Reset the update log. This forces full resynchronization. If +used on a replica then that replica will request a full resync. +If used on the primary then all replicas will request full +resyncs. + +\item[{\sphinxstylestrong{\sphinxhyphen{}h}}] \leavevmode +\sphinxAtStartPar +Display a summary of the update log. This information includes +the database version number, state of the database, the number of +updates in the log, the time stamp of the first and last update, +and the version number of the first and last update entry. + +\item[{\sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{num}}] \leavevmode +\sphinxAtStartPar +Display the last \sphinxstyleemphasis{num} update entries in the log. This is useful +when debugging synchronization between KDC servers. + +\item[{\sphinxstylestrong{\sphinxhyphen{}v}}] \leavevmode +\sphinxAtStartPar +Display individual attributes per update. An example of the +output generated for one entry: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{Update} \PYG{n}{Entry} + \PYG{n}{Update} \PYG{n}{serial} \PYG{c+c1}{\PYGZsh{} : 4} + \PYG{n}{Update} \PYG{n}{operation} \PYG{p}{:} \PYG{n}{Add} + \PYG{n}{Update} \PYG{n}{principal} \PYG{p}{:} \PYG{n}{test}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM} + \PYG{n}{Update} \PYG{n}{size} \PYG{p}{:} \PYG{l+m+mi}{424} + \PYG{n}{Update} \PYG{n}{committed} \PYG{p}{:} \PYG{k+kc}{True} + \PYG{n}{Update} \PYG{n}{time} \PYG{n}{stamp} \PYG{p}{:} \PYG{n}{Fri} \PYG{n}{Feb} \PYG{l+m+mi}{20} \PYG{l+m+mi}{23}\PYG{p}{:}\PYG{l+m+mi}{37}\PYG{p}{:}\PYG{l+m+mi}{42} \PYG{l+m+mi}{2004} + \PYG{n}{Attributes} \PYG{n}{changed} \PYG{p}{:} \PYG{l+m+mi}{6} + \PYG{n}{Principal} + \PYG{n}{Key} \PYG{n}{data} + \PYG{n}{Password} \PYG{n}{last} \PYG{n}{changed} + \PYG{n}{Modifying} \PYG{n}{principal} + \PYG{n}{Modification} \PYG{n}{time} + \PYG{n}{TL} \PYG{n}{data} +\end{sphinxVerbatim} + +\end{description} + + +\subsection{ENVIRONMENT} +\label{\detokenize{admin/admin_commands/kproplog:environment}} +\sphinxAtStartPar +See \DUrole{xref,std,std-ref}{kerberos(7)} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{admin/admin_commands/kproplog:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kpropd:kpropd-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kpropd}}}}, \DUrole{xref,std,std-ref}{kerberos(7)} + + +\section{ktutil} +\label{\detokenize{admin/admin_commands/ktutil:ktutil}}\label{\detokenize{admin/admin_commands/ktutil:ktutil-1}}\label{\detokenize{admin/admin_commands/ktutil::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{admin/admin_commands/ktutil:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{ktutil} + + +\subsection{DESCRIPTION} +\label{\detokenize{admin/admin_commands/ktutil:description}} +\sphinxAtStartPar +The ktutil command invokes a command interface from which an +administrator can read, write, or edit entries in a keytab. (Kerberos +V4 srvtab files are no longer supported.) + + +\subsection{COMMANDS} +\label{\detokenize{admin/admin_commands/ktutil:commands}} + +\subsubsection{list} +\label{\detokenize{admin/admin_commands/ktutil:list}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{list} {[}\sphinxstylestrong{\sphinxhyphen{}t}{]} {[}\sphinxstylestrong{\sphinxhyphen{}k}{]} {[}\sphinxstylestrong{\sphinxhyphen{}e}{]} +\end{quote} + +\sphinxAtStartPar +Displays the current keylist. If \sphinxstylestrong{\sphinxhyphen{}t}, \sphinxstylestrong{\sphinxhyphen{}k}, and/or \sphinxstylestrong{\sphinxhyphen{}e} are +specified, also display the timestamp, key contents, or enctype +(respectively). + +\sphinxAtStartPar +Alias: \sphinxstylestrong{l} + + +\subsubsection{read\_kt} +\label{\detokenize{admin/admin_commands/ktutil:read-kt}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{read\_kt} \sphinxstyleemphasis{keytab} +\end{quote} + +\sphinxAtStartPar +Read the Kerberos V5 keytab file \sphinxstyleemphasis{keytab} into the current keylist. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{rkt} + + +\subsubsection{write\_kt} +\label{\detokenize{admin/admin_commands/ktutil:write-kt}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{write\_kt} \sphinxstyleemphasis{keytab} +\end{quote} + +\sphinxAtStartPar +Write the current keylist into the Kerberos V5 keytab file \sphinxstyleemphasis{keytab}. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{wkt} + + +\subsubsection{clear\_list} +\label{\detokenize{admin/admin_commands/ktutil:clear-list}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{clear\_list} +\end{quote} + +\sphinxAtStartPar +Clear the current keylist. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{clear} + + +\subsubsection{delete\_entry} +\label{\detokenize{admin/admin_commands/ktutil:delete-entry}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{delete\_entry} \sphinxstyleemphasis{slot} +\end{quote} + +\sphinxAtStartPar +Delete the entry in slot number \sphinxstyleemphasis{slot} from the current keylist. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{delent} + + +\subsubsection{add\_entry} +\label{\detokenize{admin/admin_commands/ktutil:add-entry}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{add\_entry} \{\sphinxstylestrong{\sphinxhyphen{}key}|\sphinxstylestrong{\sphinxhyphen{}password}\} \sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{principal} +\sphinxstylestrong{\sphinxhyphen{}k} \sphinxstyleemphasis{kvno} {[}\sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{enctype}{]} {[}\sphinxstylestrong{\sphinxhyphen{}f}|\sphinxstylestrong{\sphinxhyphen{}s} \sphinxstyleemphasis{salt}{]} +\end{quote} + +\sphinxAtStartPar +Add \sphinxstyleemphasis{principal} to keylist using key or password. If the \sphinxstylestrong{\sphinxhyphen{}f} flag +is specified, salt information will be fetched from the KDC; in this +case the \sphinxstylestrong{\sphinxhyphen{}e} flag may be omitted, or it may be supplied to force a +particular enctype. If the \sphinxstylestrong{\sphinxhyphen{}f} flag is not specified, the \sphinxstylestrong{\sphinxhyphen{}e} +flag must be specified, and the default salt will be used unless +overridden with the \sphinxstylestrong{\sphinxhyphen{}s} option. + +\sphinxAtStartPar +Alias: \sphinxstylestrong{addent} + + +\subsubsection{list\_requests} +\label{\detokenize{admin/admin_commands/ktutil:list-requests}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{list\_requests} +\end{quote} + +\sphinxAtStartPar +Displays a listing of available commands. + +\sphinxAtStartPar +Aliases: \sphinxstylestrong{lr}, \sphinxstylestrong{?} + + +\subsubsection{quit} +\label{\detokenize{admin/admin_commands/ktutil:quit}}\begin{quote} + +\sphinxAtStartPar +\sphinxstylestrong{quit} +\end{quote} + +\sphinxAtStartPar +Quits ktutil. + +\sphinxAtStartPar +Aliases: \sphinxstylestrong{exit}, \sphinxstylestrong{q} + + +\subsection{EXAMPLE} +\label{\detokenize{admin/admin_commands/ktutil:example}}\begin{quote} + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{ktutil}\PYG{p}{:} \PYG{n}{add\PYGZus{}entry} \PYG{o}{\PYGZhy{}}\PYG{n}{password} \PYG{o}{\PYGZhy{}}\PYG{n}{p} \PYG{n}{alice}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM} \PYG{o}{\PYGZhy{}}\PYG{n}{k} \PYG{l+m+mi}{1} \PYG{o}{\PYGZhy{}}\PYG{n}{e} + \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} +\PYG{n}{Password} \PYG{k}{for} \PYG{n}{alice}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM}\PYG{p}{:} +\PYG{n}{ktutil}\PYG{p}{:} \PYG{n}{add\PYGZus{}entry} \PYG{o}{\PYGZhy{}}\PYG{n}{password} \PYG{o}{\PYGZhy{}}\PYG{n}{p} \PYG{n}{alice}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM} \PYG{o}{\PYGZhy{}}\PYG{n}{k} \PYG{l+m+mi}{1} \PYG{o}{\PYGZhy{}}\PYG{n}{e} + \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} +\PYG{n}{Password} \PYG{k}{for} \PYG{n}{alice}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM}\PYG{p}{:} +\PYG{n}{ktutil}\PYG{p}{:} \PYG{n}{write\PYGZus{}kt} \PYG{n}{alice}\PYG{o}{.}\PYG{n}{keytab} +\PYG{n}{ktutil}\PYG{p}{:} +\end{sphinxVerbatim} +\end{quote} + + +\subsection{ENVIRONMENT} +\label{\detokenize{admin/admin_commands/ktutil:environment}} +\sphinxAtStartPar +See \DUrole{xref,std,std-ref}{kerberos(7)} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{admin/admin_commands/ktutil:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}}, {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}}, \DUrole{xref,std,std-ref}{kerberos(7)} + + +\section{k5srvutil} +\label{\detokenize{admin/admin_commands/k5srvutil:k5srvutil}}\label{\detokenize{admin/admin_commands/k5srvutil:k5srvutil-1}}\label{\detokenize{admin/admin_commands/k5srvutil::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{admin/admin_commands/k5srvutil:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{k5srvutil} \sphinxstyleemphasis{operation} +{[}\sphinxstylestrong{\sphinxhyphen{}i}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}f} \sphinxstyleemphasis{filename}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{keysalts}{]} + + +\subsection{DESCRIPTION} +\label{\detokenize{admin/admin_commands/k5srvutil:description}} +\sphinxAtStartPar +k5srvutil allows an administrator to list keys currently in +a keytab, to obtain new keys for a principal currently in a keytab, +or to delete non\sphinxhyphen{}current keys from a keytab. + +\sphinxAtStartPar +\sphinxstyleemphasis{operation} must be one of the following: +\begin{description} +\item[{\sphinxstylestrong{list}}] \leavevmode +\sphinxAtStartPar +Lists the keys in a keytab, showing version number and principal +name. + +\item[{\sphinxstylestrong{change}}] \leavevmode +\sphinxAtStartPar +Uses the kadmin protocol to update the keys in the Kerberos +database to new randomly\sphinxhyphen{}generated keys, and updates the keys in +the keytab to match. If a key’s version number doesn’t match the +version number stored in the Kerberos server’s database, then the +operation will fail. If the \sphinxstylestrong{\sphinxhyphen{}i} flag is given, k5srvutil will +prompt for confirmation before changing each key. If the \sphinxstylestrong{\sphinxhyphen{}k} +option is given, the old and new keys will be displayed. +Ordinarily, keys will be generated with the default encryption +types and key salts. This can be overridden with the \sphinxstylestrong{\sphinxhyphen{}e} +option. Old keys are retained in the keytab so that existing +tickets continue to work, but \sphinxstylestrong{delold} should be used after +such tickets expire, to prevent attacks against the old keys. + +\item[{\sphinxstylestrong{delold}}] \leavevmode +\sphinxAtStartPar +Deletes keys that are not the most recent version from the keytab. +This operation should be used some time after a change operation +to remove old keys, after existing tickets issued for the service +have expired. If the \sphinxstylestrong{\sphinxhyphen{}i} flag is given, then k5srvutil will +prompt for confirmation for each principal. + +\item[{\sphinxstylestrong{delete}}] \leavevmode +\sphinxAtStartPar +Deletes particular keys in the keytab, interactively prompting for +each key. + +\end{description} + +\sphinxAtStartPar +In all cases, the default keytab is used unless this is overridden by +the \sphinxstylestrong{\sphinxhyphen{}f} option. + +\sphinxAtStartPar +k5srvutil uses the {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} program to edit the keytab in +place. + + +\subsection{ENVIRONMENT} +\label{\detokenize{admin/admin_commands/k5srvutil:environment}} +\sphinxAtStartPar +See \DUrole{xref,std,std-ref}{kerberos(7)} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{admin/admin_commands/k5srvutil:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}}, {\hyperref[\detokenize{admin/admin_commands/ktutil:ktutil-1}]{\sphinxcrossref{\DUrole{std,std-ref}{ktutil}}}}, \DUrole{xref,std,std-ref}{kerberos(7)} + + +\section{sserver} +\label{\detokenize{admin/admin_commands/sserver:sserver}}\label{\detokenize{admin/admin_commands/sserver:sserver-8}}\label{\detokenize{admin/admin_commands/sserver::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{admin/admin_commands/sserver:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{sserver} +{[} \sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{port} {]} +{[} \sphinxstylestrong{\sphinxhyphen{}S} \sphinxstyleemphasis{keytab} {]} +{[} \sphinxstyleemphasis{server\_port} {]} + + +\subsection{DESCRIPTION} +\label{\detokenize{admin/admin_commands/sserver:description}} +\sphinxAtStartPar +sserver and \DUrole{xref,std,std-ref}{sclient(1)} are a simple demonstration client/server +application. When sclient connects to sserver, it performs a Kerberos +authentication, and then sserver returns to sclient the Kerberos +principal which was used for the Kerberos authentication. It makes a +good test that Kerberos has been successfully installed on a machine. + +\sphinxAtStartPar +The service name used by sserver and sclient is sample. Hence, +sserver will require that there be a keytab entry for the service +\sphinxcode{\sphinxupquote{sample/hostname.domain.name@REALM.NAME}}. This keytab is generated +using the {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} program. The keytab file is usually +installed as {\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{DEFKTNAME}}}}. + +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}S} option allows for a different keytab than the default. + +\sphinxAtStartPar +sserver is normally invoked out of inetd(8), using a line in +\sphinxcode{\sphinxupquote{/etc/inetd.conf}} that looks like this: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{sample} \PYG{n}{stream} \PYG{n}{tcp} \PYG{n}{nowait} \PYG{n}{root} \PYG{o}{/}\PYG{n}{usr}\PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{sbin}\PYG{o}{/}\PYG{n}{sserver} \PYG{n}{sserver} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Since \sphinxcode{\sphinxupquote{sample}} is normally not a port defined in \sphinxcode{\sphinxupquote{/etc/services}}, +you will usually have to add a line to \sphinxcode{\sphinxupquote{/etc/services}} which looks +like this: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{sample} \PYG{l+m+mi}{13135}\PYG{o}{/}\PYG{n}{tcp} +\end{sphinxVerbatim} + +\sphinxAtStartPar +When using sclient, you will first have to have an entry in the +Kerberos database, by using {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}}, and then you have to get +Kerberos tickets, by using \DUrole{xref,std,std-ref}{kinit(1)}. Also, if you are running +the sclient program on a different host than the sserver it will be +connecting to, be sure that both hosts have an entry in /etc/services +for the sample tcp port, and that the same port number is in both +files. + +\sphinxAtStartPar +When you run sclient you should see something like this: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{sendauth} \PYG{n}{succeeded}\PYG{p}{,} \PYG{n}{reply} \PYG{o+ow}{is}\PYG{p}{:} +\PYG{n}{reply} \PYG{n+nb}{len} \PYG{l+m+mi}{32}\PYG{p}{,} \PYG{n}{contents}\PYG{p}{:} +\PYG{n}{You} \PYG{n}{are} \PYG{n}{nlgilman}\PYG{n+nd}{@JIMI}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\end{sphinxVerbatim} + + +\subsection{COMMON ERROR MESSAGES} +\label{\detokenize{admin/admin_commands/sserver:common-error-messages}}\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{)}% +\item {} +\sphinxAtStartPar +kinit returns the error: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{kinit}\PYG{p}{:} \PYG{n}{Client} \PYG{o+ow}{not} \PYG{n}{found} \PYG{o+ow}{in} \PYG{n}{Kerberos} \PYG{n}{database} \PYG{k}{while} \PYG{n}{getting} + \PYG{n}{initial} \PYG{n}{credentials} +\end{sphinxVerbatim} + +\sphinxAtStartPar +This means that you didn’t create an entry for your username in the +Kerberos database. + +\item {} +\sphinxAtStartPar +sclient returns the error: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{unknown} \PYG{n}{service} \PYG{n}{sample}\PYG{o}{/}\PYG{n}{tcp}\PYG{p}{;} \PYG{n}{check} \PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{services} +\end{sphinxVerbatim} + +\sphinxAtStartPar +This means that you don’t have an entry in /etc/services for the +sample tcp port. + +\item {} +\sphinxAtStartPar +sclient returns the error: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{connect}\PYG{p}{:} \PYG{n}{Connection} \PYG{n}{refused} +\end{sphinxVerbatim} + +\sphinxAtStartPar +This probably means you didn’t edit /etc/inetd.conf correctly, or +you didn’t restart inetd after editing inetd.conf. + +\item {} +\sphinxAtStartPar +sclient returns the error: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{sclient}\PYG{p}{:} \PYG{n}{Server} \PYG{o+ow}{not} \PYG{n}{found} \PYG{o+ow}{in} \PYG{n}{Kerberos} \PYG{n}{database} \PYG{k}{while} \PYG{n}{using} + \PYG{n}{sendauth} +\end{sphinxVerbatim} + +\sphinxAtStartPar +This means that the \sphinxcode{\sphinxupquote{sample/hostname@LOCAL.REALM}} service was not +defined in the Kerberos database; it should be created using +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}}, and a keytab file needs to be generated to make +the key for that service principal available for sclient. + +\item {} +\sphinxAtStartPar +sclient returns the error: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{sendauth} \PYG{n}{rejected}\PYG{p}{,} \PYG{n}{error} \PYG{n}{reply} \PYG{o+ow}{is}\PYG{p}{:} + \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{No such file or directory}\PYG{l+s+s2}{\PYGZdq{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +This probably means sserver couldn’t find the keytab file. It was +probably not installed in the proper directory. + +\end{enumerate} + + +\subsection{ENVIRONMENT} +\label{\detokenize{admin/admin_commands/sserver:environment}} +\sphinxAtStartPar +See \DUrole{xref,std,std-ref}{kerberos(7)} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{admin/admin_commands/sserver:see-also}} +\sphinxAtStartPar +\DUrole{xref,std,std-ref}{sclient(1)}, \DUrole{xref,std,std-ref}{kerberos(7)}, services(5), inetd(8) + + +\chapter{MIT Kerberos defaults} +\label{\detokenize{mitK5defaults:mit-kerberos-defaults}}\label{\detokenize{mitK5defaults:mitk5defaults}}\label{\detokenize{mitK5defaults::doc}} + +\section{General defaults} +\label{\detokenize{mitK5defaults:general-defaults}} + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|T|} +\hline +\sphinxstyletheadfamily +\sphinxAtStartPar +Description +&\sphinxstyletheadfamily +\sphinxAtStartPar +Default +&\sphinxstyletheadfamily +\sphinxAtStartPar +Environment +\\ +\hline +\sphinxAtStartPar +\DUrole{xref,std,std-ref}{keytab\_definition} file +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{DEFKTNAME}}}} +& +\sphinxAtStartPar +\sphinxstylestrong{KRB5\_KTNAME} +\\ +\hline +\sphinxAtStartPar +Client \DUrole{xref,std,std-ref}{keytab\_definition} file +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{DEFCKTNAME}}}} +& +\sphinxAtStartPar +\sphinxstylestrong{KRB5\_CLIENT\_KTNAME} +\\ +\hline +\sphinxAtStartPar +Kerberos config file {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/etc/krb5.conf}}\sphinxcode{\sphinxupquote{:}}{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{SYSCONFDIR}}}}\sphinxcode{\sphinxupquote{/krb5.conf}} +& +\sphinxAtStartPar +\sphinxstylestrong{KRB5\_CONFIG} +\\ +\hline +\sphinxAtStartPar +KDC config file {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/kdc.conf}} +& +\sphinxAtStartPar +\sphinxstylestrong{KRB5\_KDC\_PROFILE} +\\ +\hline +\sphinxAtStartPar +GSS mechanism config file +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{SYSCONFDIR}}}}\sphinxcode{\sphinxupquote{/gss/mech}} +& +\sphinxAtStartPar +\sphinxstylestrong{GSS\_MECH\_CONFIG} +\\ +\hline +\sphinxAtStartPar +KDC database path (DB2) +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/principal}} +&\\ +\hline +\sphinxAtStartPar +Master key \DUrole{xref,std,std-ref}{stash\_definition} +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/.k5.}}\sphinxstyleemphasis{realm} +&\\ +\hline +\sphinxAtStartPar +Admin server ACL file {\hyperref[\detokenize{admin/conf_files/kadm5_acl:kadm5-acl-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kadm5.acl}}}} +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/kadm5.acl}} +&\\ +\hline +\sphinxAtStartPar +OTP socket directory +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{RUNSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}} +&\\ +\hline +\sphinxAtStartPar +Plugin base directory +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LIBDIR}}}}\sphinxcode{\sphinxupquote{/krb5/plugins}} +&\\ +\hline +\sphinxAtStartPar +\DUrole{xref,std,std-ref}{rcache\_definition} directory +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/var/tmp}} +& +\sphinxAtStartPar +\sphinxstylestrong{KRB5RCACHEDIR} +\\ +\hline +\sphinxAtStartPar +Master key default enctype +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96}} +&\\ +\hline +\sphinxAtStartPar +Default {\hyperref[\detokenize{admin/conf_files/kdc_conf:keysalt-lists}]{\sphinxcrossref{\DUrole{std,std-ref}{keysalt list}}}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96:normal aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96:normal}} +&\\ +\hline +\sphinxAtStartPar +Permitted enctypes +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96 aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96 aes256\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha384\sphinxhyphen{}192 aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha256\sphinxhyphen{}128 des3\sphinxhyphen{}cbc\sphinxhyphen{}sha1 arcfour\sphinxhyphen{}hmac\sphinxhyphen{}md5 camellia256\sphinxhyphen{}cts\sphinxhyphen{}cmac camellia128\sphinxhyphen{}cts\sphinxhyphen{}cmac}} +&\\ +\hline +\sphinxAtStartPar +KDC default port +& +\sphinxAtStartPar +88 +&\\ +\hline +\sphinxAtStartPar +Admin server port +& +\sphinxAtStartPar +749 +&\\ +\hline +\sphinxAtStartPar +Password change port +& +\sphinxAtStartPar +464 +&\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\section{Replica KDC propagation defaults} +\label{\detokenize{mitK5defaults:replica-kdc-propagation-defaults}} +\sphinxAtStartPar +This table shows defaults used by the {\hyperref[\detokenize{admin/admin_commands/kprop:kprop-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop}}}} and +{\hyperref[\detokenize{admin/admin_commands/kpropd:kpropd-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kpropd}}}} programs. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|T|} +\hline +\sphinxstyletheadfamily +\sphinxAtStartPar +Description +&\sphinxstyletheadfamily +\sphinxAtStartPar +Default +&\sphinxstyletheadfamily +\sphinxAtStartPar +Environment +\\ +\hline +\sphinxAtStartPar +kprop database dump file +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/replica\_datatrans}} +&\\ +\hline +\sphinxAtStartPar +kpropd temporary dump file +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/from\_master}} +&\\ +\hline +\sphinxAtStartPar +kdb5\_util location +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{SBINDIR}}}}\sphinxcode{\sphinxupquote{/kdb5\_util}} +&\\ +\hline +\sphinxAtStartPar +kprop location +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{SBINDIR}}}}\sphinxcode{\sphinxupquote{/kprop}} +&\\ +\hline +\sphinxAtStartPar +kpropd ACL file +& +\sphinxAtStartPar +{\hyperref[\detokenize{mitK5defaults:paths}]{\sphinxcrossref{\DUrole{std,std-ref}{LOCALSTATEDIR}}}}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/kpropd.acl}} +&\\ +\hline +\sphinxAtStartPar +kprop port +& +\sphinxAtStartPar +754 +& +\sphinxAtStartPar +KPROP\_PORT +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\section{Default paths for Unix\sphinxhyphen{}like systems} +\label{\detokenize{mitK5defaults:default-paths-for-unix-like-systems}}\label{\detokenize{mitK5defaults:paths}} +\sphinxAtStartPar +On Unix\sphinxhyphen{}like systems, some paths used by MIT krb5 depend on parameters +chosen at build time. For a custom build, these paths default to +subdirectories of \sphinxcode{\sphinxupquote{/usr/local}}. When MIT krb5 is integrated into an +operating system, the paths are generally chosen to match the +operating system’s filesystem layout. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|T|T|} +\hline +\sphinxstyletheadfamily +\sphinxAtStartPar +Description +&\sphinxstyletheadfamily +\sphinxAtStartPar +Symbolic name +&\sphinxstyletheadfamily +\sphinxAtStartPar +Custom build path +&\sphinxstyletheadfamily +\sphinxAtStartPar +Typical OS path +\\ +\hline +\sphinxAtStartPar +User programs +& +\sphinxAtStartPar +BINDIR +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/usr/local/bin}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/usr/bin}} +\\ +\hline +\sphinxAtStartPar +Libraries and plugins +& +\sphinxAtStartPar +LIBDIR +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/usr/local/lib}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/usr/lib}} +\\ +\hline +\sphinxAtStartPar +Parent of KDC state dir +& +\sphinxAtStartPar +LOCALSTATEDIR +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/usr/local/var}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/var}} +\\ +\hline +\sphinxAtStartPar +Parent of KDC runtime dir +& +\sphinxAtStartPar +RUNSTATEDIR +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/usr/local/var/run}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/run}} +\\ +\hline +\sphinxAtStartPar +Administrative programs +& +\sphinxAtStartPar +SBINDIR +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/usr/local/sbin}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/usr/sbin}} +\\ +\hline +\sphinxAtStartPar +Alternate krb5.conf dir +& +\sphinxAtStartPar +SYSCONFDIR +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/usr/local/etc}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{/etc}} +\\ +\hline +\sphinxAtStartPar +Default ccache name +& +\sphinxAtStartPar +DEFCCNAME +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{FILE:/tmp/krb5cc\_\%\{uid\}}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{FILE:/tmp/krb5cc\_\%\{uid\}}} +\\ +\hline +\sphinxAtStartPar +Default keytab name +& +\sphinxAtStartPar +DEFKTNAME +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{FILE:/etc/krb5.keytab}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{FILE:/etc/krb5.keytab}} +\\ +\hline +\sphinxAtStartPar +Default PKCS11 module +& +\sphinxAtStartPar +PKCS11\_MODNAME +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{opensc\sphinxhyphen{}pkcs11.so}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{opensc\sphinxhyphen{}pkcs11.so}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + +\sphinxAtStartPar +The default client keytab name (DEFCKTNAME) typically defaults to +\sphinxcode{\sphinxupquote{FILE:/usr/local/var/krb5/user/\%\{euid\}/client.keytab}} for a custom +build. A native build will typically use a path which will vary +according to the operating system’s layout of \sphinxcode{\sphinxupquote{/var}}. + + +\chapter{Environment variables} +\label{\detokenize{admin/env_variables:environment-variables}}\label{\detokenize{admin/env_variables::doc}} +\sphinxAtStartPar +This content has moved to \DUrole{xref,std,std-ref}{kerberos(7)}. + + +\chapter{Troubleshooting} +\label{\detokenize{admin/troubleshoot:troubleshooting}}\label{\detokenize{admin/troubleshoot:troubleshoot}}\label{\detokenize{admin/troubleshoot::doc}} + +\section{Trace logging} +\label{\detokenize{admin/troubleshoot:trace-logging}}\label{\detokenize{admin/troubleshoot:id1}} +\sphinxAtStartPar +Most programs using MIT krb5 1.9 or later can be made to provide +information about internal krb5 library operations using trace +logging. To enable this, set the \sphinxstylestrong{KRB5\_TRACE} environment variable +to a filename before running the program. On many operating systems, +the filename \sphinxcode{\sphinxupquote{/dev/stdout}} can be used to send trace logging output +to standard output. + +\sphinxAtStartPar +Some programs do not honor \sphinxstylestrong{KRB5\_TRACE}, either because they use +secure library contexts (this generally applies to setuid programs and +parts of the login system) or because they take direct control of the +trace logging system using the API. + +\sphinxAtStartPar +Here is a short example showing trace logging output for an invocation +of the \DUrole{xref,std,std-ref}{kvno(1)} command: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{env} \PYG{n}{KRB5\PYGZus{}TRACE}\PYG{o}{=}\PYG{o}{/}\PYG{n}{dev}\PYG{o}{/}\PYG{n}{stdout} \PYG{n}{kvno} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{KRBTEST}\PYG{o}{.}\PYG{n}{COM} +\PYG{p}{[}\PYG{l+m+mi}{9138}\PYG{p}{]} \PYG{l+m+mf}{1332348778.823276}\PYG{p}{:} \PYG{n}{Getting} \PYG{n}{credentials} \PYG{n}{user}\PYG{n+nd}{@KRBTEST}\PYG{o}{.}\PYG{n}{COM} \PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZgt{}} + \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{KRBTEST}\PYG{o}{.}\PYG{n}{COM}\PYG{n+nd}{@KRBTEST}\PYG{o}{.}\PYG{n}{COM} \PYG{n}{using} \PYG{n}{ccache} + \PYG{n}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{me}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{/}\PYG{n}{build}\PYG{o}{/}\PYG{n}{testdir}\PYG{o}{/}\PYG{n}{ccache} +\PYG{p}{[}\PYG{l+m+mi}{9138}\PYG{p}{]} \PYG{l+m+mf}{1332348778.823381}\PYG{p}{:} \PYG{n}{Retrieving} \PYG{n}{user}\PYG{n+nd}{@KRBTEST}\PYG{o}{.}\PYG{n}{COM} \PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZgt{}} + \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{KRBTEST}\PYG{o}{.}\PYG{n}{COM}\PYG{n+nd}{@KRBTEST}\PYG{o}{.}\PYG{n}{COM} \PYG{k+kn}{from} + \PYG{n+nn}{FILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{me}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{/}\PYG{n}{build}\PYG{o}{/}\PYG{n}{testdir}\PYG{o}{/}\PYG{n}{ccache} \PYG{k}{with} \PYG{n}{result}\PYG{p}{:} \PYG{l+m+mi}{0}\PYG{o}{/}\PYG{n}{Unknown} \PYG{n}{code} \PYG{l+m+mi}{0} +\PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{KRBTEST}\PYG{o}{.}\PYG{n}{COM}\PYG{n+nd}{@KRBTEST}\PYG{o}{.}\PYG{n}{COM}\PYG{p}{:} \PYG{n}{kvno} \PYG{o}{=} \PYG{l+m+mi}{1} +\end{sphinxVerbatim} + + +\section{List of errors} +\label{\detokenize{admin/troubleshoot:list-of-errors}} + +\subsection{Frequently seen errors} +\label{\detokenize{admin/troubleshoot:frequently-seen-errors}}\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/troubleshoot:init-creds-etype-nosupp}]{\sphinxcrossref{\DUrole{std,std-ref}{KDC has no support for encryption type while getting initial credentials}}}} + +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/troubleshoot:cert-chain-etype-nosupp}]{\sphinxcrossref{\DUrole{std,std-ref}{credential verification failed: KDC has no support for encryption type}}}} + +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/troubleshoot:err-cert-chain-cert-expired}]{\sphinxcrossref{\DUrole{std,std-ref}{Cannot create cert chain: certificate has expired}}}} + +\end{enumerate} + + +\subsection{Errors seen by admins} +\label{\detokenize{admin/troubleshoot:errors-seen-by-admins}}\phantomsection\label{\detokenize{admin/troubleshoot:prop-failed-start}}\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/troubleshoot:kprop-no-route}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop: No route to host while connecting to server}}}} + +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/troubleshoot:kprop-con-refused}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop: Connection refused while connecting to server}}}} + +\item {} +\sphinxAtStartPar +{\hyperref[\detokenize{admin/troubleshoot:kprop-sendauth-exchange}]{\sphinxcrossref{\DUrole{std,std-ref}{kprop: Server rejected authentication (during sendauth exchange) while authenticating to server}}}} + +\end{enumerate} +\phantomsection\label{\detokenize{admin/troubleshoot:prop-failed-end}} + +\bigskip\hrule\bigskip + + + +\subsubsection{KDC has no support for encryption type while getting initial credentials} +\label{\detokenize{admin/troubleshoot:kdc-has-no-support-for-encryption-type-while-getting-initial-credentials}}\label{\detokenize{admin/troubleshoot:init-creds-etype-nosupp}} + +\subsubsection{credential verification failed: KDC has no support for encryption type} +\label{\detokenize{admin/troubleshoot:credential-verification-failed-kdc-has-no-support-for-encryption-type}}\label{\detokenize{admin/troubleshoot:cert-chain-etype-nosupp}} +\sphinxAtStartPar +This most commonly happens when trying to use a principal with only +DES keys, in a release (MIT krb5 1.7 or later) which disables DES by +default. DES encryption is considered weak due to its inadequate key +size. If you cannot migrate away from its use, you can re\sphinxhyphen{}enable DES +by adding \sphinxcode{\sphinxupquote{allow\_weak\_crypto = true}} to the {\hyperref[\detokenize{admin/conf_files/krb5_conf:libdefaults}]{\sphinxcrossref{\DUrole{std,std-ref}{{[}libdefaults{]}}}}} +section of {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}}. + + +\subsubsection{Cannot create cert chain: certificate has expired} +\label{\detokenize{admin/troubleshoot:cannot-create-cert-chain-certificate-has-expired}}\label{\detokenize{admin/troubleshoot:err-cert-chain-cert-expired}} +\sphinxAtStartPar +This error message indicates that PKINIT authentication failed because +the client certificate, KDC certificate, or one of the certificates in +the signing chain above them has expired. + +\sphinxAtStartPar +If the KDC certificate has expired, this message appears in the KDC +log file, and the client will receive a “Preauthentication failed” +error. (Prior to release 1.11, the KDC log file message erroneously +appears as “Out of memory”. Prior to release 1.12, the client will +receive a “Generic error”.) + +\sphinxAtStartPar +If the client or a signing certificate has expired, this message may +appear in {\hyperref[\detokenize{admin/troubleshoot:trace-logging}]{\sphinxcrossref{trace\_logging}}} output from \DUrole{xref,std,std-ref}{kinit(1)} or, starting in +release 1.12, as an error message from kinit or another program which +gets initial tickets. The error message is more likely to appear +properly on the client if the principal entry has no long\sphinxhyphen{}term keys. + + +\subsubsection{kprop: No route to host while connecting to server} +\label{\detokenize{admin/troubleshoot:kprop-no-route-to-host-while-connecting-to-server}}\label{\detokenize{admin/troubleshoot:kprop-no-route}} +\sphinxAtStartPar +Make sure that the hostname of the replica KDC (as given to kprop) is +correct, and that any firewalls between the primary and the replica +allow a connection on port 754. + + +\subsubsection{kprop: Connection refused while connecting to server} +\label{\detokenize{admin/troubleshoot:kprop-connection-refused-while-connecting-to-server}}\label{\detokenize{admin/troubleshoot:kprop-con-refused}} +\sphinxAtStartPar +If the replica KDC is intended to run kpropd out of inetd, make sure +that inetd is configured to accept krb5\_prop connections. inetd may +need to be restarted or sent a SIGHUP to recognize the new +configuration. If the replica is intended to run kpropd in standalone +mode, make sure that it is running. + + +\subsubsection{kprop: Server rejected authentication (during sendauth exchange) while authenticating to server} +\label{\detokenize{admin/troubleshoot:kprop-server-rejected-authentication-during-sendauth-exchange-while-authenticating-to-server}}\label{\detokenize{admin/troubleshoot:kprop-sendauth-exchange}} +\sphinxAtStartPar +Make sure that: +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +The time is synchronized between the primary and replica KDCs. + +\item {} +\sphinxAtStartPar +The master stash file was copied from the primary to the expected +location on the replica. + +\item {} +\sphinxAtStartPar +The replica has a keytab file in the default location containing a +\sphinxcode{\sphinxupquote{host}} principal for the replica’s hostname. + +\end{enumerate} + + +\chapter{Advanced topics} +\label{\detokenize{admin/advanced/index:advanced-topics}}\label{\detokenize{admin/advanced/index::doc}} + +\section{Retiring DES} +\label{\detokenize{admin/advanced/retiring-des:retiring-des}}\label{\detokenize{admin/advanced/retiring-des:id1}}\label{\detokenize{admin/advanced/retiring-des::doc}} +\sphinxAtStartPar +Version 5 of the Kerberos protocol was originally implemented using +the Data Encryption Standard (DES) as a block cipher for encryption. +While it was considered secure at the time, advancements in computational +ability have rendered DES vulnerable to brute force attacks on its 56\sphinxhyphen{}bit +keyspace. As such, it is now considered insecure and should not be +used (\index{RFC@\spxentry{RFC}!RFC 6649@\spxentry{RFC 6649}}\sphinxhref{https://tools.ietf.org/html/rfc6649.html}{\sphinxstylestrong{RFC 6649}}). + + +\subsection{History} +\label{\detokenize{admin/advanced/retiring-des:history}} +\sphinxAtStartPar +DES was used in the original Kerberos implementation, and was the +only cryptosystem in krb5 1.0. Partial support for triple\sphinxhyphen{}DES (3DES) was +added in version 1.1, with full support following in version 1.2. +The Advanced Encryption Standard (AES), which supersedes DES, gained +partial support in version 1.3.0 of krb5 and full support in version 1.3.2. +However, deployments of krb5 using Kerberos databases created with older +versions of krb5 will not necessarily start using strong crypto for +ordinary operation without administrator intervention. + +\sphinxAtStartPar +MIT krb5 began flagging deprecated encryption types with release 1.17, +and removed DES (single\sphinxhyphen{}DES) support in release 1.18. As a +consequence, a release prior to 1.18 is required to perform these +migrations. + + +\subsection{Types of keys} +\label{\detokenize{admin/advanced/retiring-des:types-of-keys}}\begin{itemize} +\item {} +\sphinxAtStartPar +The database master key: This key is not exposed to user requests, +but is used to encrypt other key material stored in the kerberos +database. The database master key is currently stored as \sphinxcode{\sphinxupquote{K/M}} +by default. + +\item {} +\sphinxAtStartPar +Password\sphinxhyphen{}derived keys: User principals frequently have keys +derived from a password. When a new password is set, the KDC +uses various string2key functions to generate keys in the database +for that principal. + +\item {} +\sphinxAtStartPar +Keytab keys: Application server principals generally use random +keys which are not derived from a password. When the database +entry is created, the KDC generates random keys of various enctypes +to enter in the database, which are conveyed to the application server +and stored in a keytab. + +\item {} +\sphinxAtStartPar +Session keys: These are short\sphinxhyphen{}term keys generated by the KDC while +processing client requests, with an enctype selected by the KDC. + +\end{itemize} + +\sphinxAtStartPar +For details on the various enctypes and how enctypes are selected by the KDC +for session keys and client/server long\sphinxhyphen{}term keys, see {\hyperref[\detokenize{admin/enctypes:enctypes}]{\sphinxcrossref{\DUrole{std,std-ref}{Encryption types}}}}. +When using the {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} interface to generate new long\sphinxhyphen{}term keys, +the \sphinxstylestrong{\sphinxhyphen{}e} argument can be used to force a particular set of enctypes, +overriding the KDC default values. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +When the KDC is selecting a session key, it has no knowledge about the +kerberos installation on the server which will receive the service ticket, +only what keys are in the database for the service principal. +In order to allow uninterrupted operation to +clients while migrating away from DES, care must be taken to ensure that +kerberos installations on application server machines are configured to +support newer encryption types before keys of those new encryption types +are created in the Kerberos database for those server principals. +\end{sphinxadmonition} + + +\subsection{Upgrade procedure} +\label{\detokenize{admin/advanced/retiring-des:upgrade-procedure}} +\sphinxAtStartPar +This procedure assumes that the KDC software has already been upgraded +to a modern version of krb5 that supports non\sphinxhyphen{}DES keys, so that the +only remaining task is to update the actual keys used to service requests. +The realm used for demonstrating this procedure, ZONE.MIT.EDU, +is an example of the worst\sphinxhyphen{}case scenario, where all keys in the realm +are DES. The realm was initially created with a very old version of krb5, +and \sphinxstylestrong{supported\_enctypes} in {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} was set to a value +appropriate when the KDC was installed, but was not updated as the KDC +was upgraded: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{realms}\PYG{p}{]} + \PYG{n}{ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{p}{[}\PYG{o}{.}\PYG{o}{.}\PYG{o}{.}\PYG{p}{]} + \PYG{n}{master\PYGZus{}key\PYGZus{}type} \PYG{o}{=} \PYG{n}{des}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{crc} + \PYG{n}{supported\PYGZus{}enctypes} \PYG{o}{=} \PYG{n}{des}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{crc}\PYG{p}{:}\PYG{n}{normal} \PYG{n}{des}\PYG{p}{:}\PYG{n}{normal} \PYG{n}{des}\PYG{p}{:}\PYG{n}{v4} \PYG{n}{des}\PYG{p}{:}\PYG{n}{norealm} \PYG{n}{des}\PYG{p}{:}\PYG{n}{onlyrealm} \PYG{n}{des}\PYG{p}{:}\PYG{n}{afs3} + \PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +This resulted in the keys for all principals in the realm being forced +to DES\sphinxhyphen{}only, unless specifically requested using {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}}. + +\sphinxAtStartPar +Before starting the upgrade, all KDCs were running krb5 1.11, +and the database entries for some “high\sphinxhyphen{}value” principals were: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} kadmin.local \PYGZhy{}r ZONE.MIT.EDU \PYGZhy{}q \PYGZsq{}getprinc krbtgt/ZONE.MIT.EDU\PYGZsq{}} +\PYG{p}{[}\PYG{o}{.}\PYG{o}{.}\PYG{o}{.}\PYG{p}{]} +\PYG{n}{Number} \PYG{n}{of} \PYG{n}{keys}\PYG{p}{:} \PYG{l+m+mi}{1} +\PYG{n}{Key}\PYG{p}{:} \PYG{n}{vno} \PYG{l+m+mi}{1}\PYG{p}{,} \PYG{n}{des}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{crc}\PYG{p}{:}\PYG{n}{v4} +\PYG{p}{[}\PYG{o}{.}\PYG{o}{.}\PYG{o}{.}\PYG{p}{]} +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} kadmin.local \PYGZhy{}r ZONE.MIT.EDU \PYGZhy{}q \PYGZsq{}getprinc kadmin/admin\PYGZsq{}} +\PYG{p}{[}\PYG{o}{.}\PYG{o}{.}\PYG{o}{.}\PYG{p}{]} +\PYG{n}{Number} \PYG{n}{of} \PYG{n}{keys}\PYG{p}{:} \PYG{l+m+mi}{1} +\PYG{n}{Key}\PYG{p}{:} \PYG{n}{vno} \PYG{l+m+mi}{15}\PYG{p}{,} \PYG{n}{des}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{crc} +\PYG{p}{[}\PYG{o}{.}\PYG{o}{.}\PYG{o}{.}\PYG{p}{]} +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} kadmin.local \PYGZhy{}r ZONE.MIT.EDU \PYGZhy{}q \PYGZsq{}getprinc kadmin/changepw\PYGZsq{}} +\PYG{p}{[}\PYG{o}{.}\PYG{o}{.}\PYG{o}{.}\PYG{p}{]} +\PYG{n}{Number} \PYG{n}{of} \PYG{n}{keys}\PYG{p}{:} \PYG{l+m+mi}{1} +\PYG{n}{Key}\PYG{p}{:} \PYG{n}{vno} \PYG{l+m+mi}{14}\PYG{p}{,} \PYG{n}{des}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{crc} +\PYG{p}{[}\PYG{o}{.}\PYG{o}{.}\PYG{o}{.}\PYG{p}{]} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The \sphinxcode{\sphinxupquote{krbtgt/REALM}} key appears to have never been changed since creation +(its kvno is 1), and all three database entries have only a des\sphinxhyphen{}cbc\sphinxhyphen{}crc key. + + +\subsubsection{The krbtgt key and KDC keys} +\label{\detokenize{admin/advanced/retiring-des:the-krbtgt-key-and-kdc-keys}} +\sphinxAtStartPar +Perhaps the biggest single\sphinxhyphen{}step improvement in the security of the cell +is gained by strengthening the key of the ticket\sphinxhyphen{}granting service principal, +\sphinxcode{\sphinxupquote{krbtgt/REALM}}—if this principal’s key is compromised, so is the +entire realm. Since the server that will handle service tickets +for this principal is the KDC itself, it is easy to guarantee that it +will be configured to support any encryption types which might be +selected. However, the default KDC behavior when creating new keys is to +remove the old keys, which would invalidate all existing tickets issued +against that principal, rendering the TGTs cached by clients useless. +Instead, a new key can be created with the old key retained, so that +existing tickets will still function until their scheduled expiry +(see {\hyperref[\detokenize{admin/database:changing-krbtgt-key}]{\sphinxcrossref{\DUrole{std,std-ref}{Changing the krbtgt key}}}}). + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} enctypes=aes256\PYGZhy{}cts\PYGZhy{}hmac\PYGZhy{}sha1\PYGZhy{}96:normal,\PYGZbs{}} +\PYG{o}{\PYGZgt{}} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96}\PYG{p}{:}\PYG{n}{normal}\PYG{p}{,}\PYG{n}{des3}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{p}{:}\PYG{n}{normal}\PYG{p}{,}\PYG{n}{des}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{crc}\PYG{p}{:}\PYG{n}{normal} +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} kadmin.local \PYGZhy{}r ZONE.MIT.EDU \PYGZhy{}q \PYGZdq{}cpw \PYGZhy{}e \PYGZdl{}\PYGZob{}enctypes\PYGZcb{} \PYGZhy{}randkey \PYGZbs{}} +\PYG{o}{\PYGZgt{}} \PYG{o}{\PYGZhy{}}\PYG{n}{keepold} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{l+s+s2}{\PYGZdq{}} +\PYG{n}{Authenticating} \PYG{k}{as} \PYG{n}{principal} \PYG{n}{root}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Key} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{krbtgt/ZONE.MIT.EDU@ZONE.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{randomized}\PYG{o}{.} +\end{sphinxVerbatim} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The new \sphinxcode{\sphinxupquote{krbtgt@REALM}} key should be propagated to replica KDCs +immediately so that TGTs issued by the primary KDC can be used to +issue service tickets on replica KDCs. Replica KDCs will refuse +requests using the new TGT kvno until the new krbtgt entry has +been propagated to them. +\end{sphinxadmonition} + +\sphinxAtStartPar +It is necessary to explicitly specify the enctypes for the new database +entry, since \sphinxstylestrong{supported\_enctypes} has not been changed. Leaving +\sphinxstylestrong{supported\_enctypes} unchanged makes a potential rollback operation +easier, since all new keys of new enctypes are the result of explicit +administrator action and can be easily enumerated. +Upgrading the krbtgt key should have minimal user\sphinxhyphen{}visible disruption other +than that described in the note above, since only clients which list the +new enctypes as supported will use them, per the procedure +in {\hyperref[\detokenize{admin/enctypes:session-key-selection}]{\sphinxcrossref{\DUrole{std,std-ref}{Session key selection}}}}. +Once the krbtgt key is updated, the session and ticket keys for user +TGTs will be strong keys, but subsequent requests +for service tickets will still get DES keys until the service principals +have new keys generated. Application service +remains uninterrupted due to the key\sphinxhyphen{}selection procedure on the KDC. + +\sphinxAtStartPar +After the change, the database entry is now: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} kadmin.local \PYGZhy{}r ZONE.MIT.EDU \PYGZhy{}q \PYGZsq{}getprinc krbtgt/ZONE.MIT.EDU\PYGZsq{}} +\PYG{p}{[}\PYG{o}{.}\PYG{o}{.}\PYG{o}{.}\PYG{p}{]} +\PYG{n}{Number} \PYG{n}{of} \PYG{n}{keys}\PYG{p}{:} \PYG{l+m+mi}{5} +\PYG{n}{Key}\PYG{p}{:} \PYG{n}{vno} \PYG{l+m+mi}{2}\PYG{p}{,} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} +\PYG{n}{Key}\PYG{p}{:} \PYG{n}{vno} \PYG{l+m+mi}{2}\PYG{p}{,} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} +\PYG{n}{Key}\PYG{p}{:} \PYG{n}{vno} \PYG{l+m+mi}{2}\PYG{p}{,} \PYG{n}{des3}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1} +\PYG{n}{Key}\PYG{p}{:} \PYG{n}{vno} \PYG{l+m+mi}{2}\PYG{p}{,} \PYG{n}{des}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{crc} +\PYG{n}{Key}\PYG{p}{:} \PYG{n}{vno} \PYG{l+m+mi}{1}\PYG{p}{,} \PYG{n}{des}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{crc}\PYG{p}{:}\PYG{n}{v4} +\PYG{p}{[}\PYG{o}{.}\PYG{o}{.}\PYG{o}{.}\PYG{p}{]} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Since the expected disruptions from rekeying the krbtgt principal are +minor, after a short testing period, it is +appropriate to rekey the other high\sphinxhyphen{}value principals, \sphinxcode{\sphinxupquote{kadmin/admin@REALM}} +and \sphinxcode{\sphinxupquote{kadmin/changepw@REALM}}. These are the service principals used for +changing user passwords and updating application keytabs. The kadmin +and password\sphinxhyphen{}changing services are regular kerberized services, so the +session\sphinxhyphen{}key\sphinxhyphen{}selection algorithm described in {\hyperref[\detokenize{admin/enctypes:session-key-selection}]{\sphinxcrossref{\DUrole{std,std-ref}{Session key selection}}}} +applies. It is particularly important to have strong session keys for +these services, since user passwords and new long\sphinxhyphen{}term keys are conveyed +over the encrypted channel. + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} enctypes=aes256\PYGZhy{}cts\PYGZhy{}hmac\PYGZhy{}sha1\PYGZhy{}96:normal,\PYGZbs{}} +\PYG{o}{\PYGZgt{}} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96}\PYG{p}{:}\PYG{n}{normal}\PYG{p}{,}\PYG{n}{des3}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{p}{:}\PYG{n}{normal} +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} kadmin.local \PYGZhy{}r ZONE.MIT.EDU \PYGZhy{}q \PYGZdq{}cpw \PYGZhy{}e \PYGZdl{}\PYGZob{}enctypes\PYGZcb{} \PYGZhy{}randkey \PYGZbs{}} +\PYG{o}{\PYGZgt{}} \PYG{n}{kadmin}\PYG{o}{/}\PYG{n}{admin}\PYG{l+s+s2}{\PYGZdq{}} +\PYG{n}{Authenticating} \PYG{k}{as} \PYG{n}{principal} \PYG{n}{root}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Key} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{kadmin/admin@ZONE.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{randomized}\PYG{o}{.} +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} kadmin.local \PYGZhy{}r ZONE.MIT.EDU \PYGZhy{}q \PYGZdq{}cpw \PYGZhy{}e \PYGZdl{}\PYGZob{}enctypes\PYGZcb{} \PYGZhy{}randkey \PYGZbs{}} +\PYG{o}{\PYGZgt{}} \PYG{n}{kadmin}\PYG{o}{/}\PYG{n}{changepw}\PYG{l+s+s2}{\PYGZdq{}} +\PYG{n}{Authenticating} \PYG{k}{as} \PYG{n}{principal} \PYG{n}{root}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Key} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{kadmin/changepw@ZONE.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{randomized}\PYG{o}{.} +\end{sphinxVerbatim} + +\sphinxAtStartPar +It is not necessary to retain a single\sphinxhyphen{}DES key for these services, since +password changes are not part of normal daily workflow, and disruption +from a client failure is likely to be minimal. Furthermore, if a kerberos +client experiences failure changing a user password or keytab key, +this indicates that that client will become inoperative once services +are rekeyed to non\sphinxhyphen{}DES enctypes. Such problems can be detected early +at this stage, giving more time for corrective action. + + +\subsubsection{Adding strong keys to application servers} +\label{\detokenize{admin/advanced/retiring-des:adding-strong-keys-to-application-servers}} +\sphinxAtStartPar +Before switching the default enctypes for new keys over to strong enctypes, +it may be desired to test upgrading a handful of services with the +new configuration before flipping the switch for the defaults. This +still requires using the \sphinxstylestrong{\sphinxhyphen{}e} argument in {\hyperref[\detokenize{admin/admin_commands/kadmin_local:kadmin-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kadmin}}}} to get non\sphinxhyphen{}default +enctypes: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} enctypes=aes256\PYGZhy{}cts\PYGZhy{}hmac\PYGZhy{}sha1\PYGZhy{}96:normal,\PYGZbs{}} +\PYG{o}{\PYGZgt{}} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96}\PYG{p}{:}\PYG{n}{normal}\PYG{p}{,}\PYG{n}{des3}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{p}{:}\PYG{n}{normal}\PYG{p}{,}\PYG{n}{des}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{crc}\PYG{p}{:}\PYG{n}{normal} +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} kadmin \PYGZhy{}r ZONE.MIT.EDU \PYGZhy{}p zephyr/zephyr@ZONE.MIT.EDU \PYGZhy{}k \PYGZhy{}t \PYGZbs{}} +\PYG{o}{\PYGZgt{}} \PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab} \PYG{o}{\PYGZhy{}}\PYG{n}{q} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{ktadd \PYGZhy{}e \PYGZdl{}}\PYG{l+s+si}{\PYGZob{}enctypes\PYGZcb{}}\PYG{l+s+s2}{ }\PYG{l+s+se}{\PYGZbs{}} +\PYG{l+s+s2}{\PYGZgt{} \PYGZhy{}k /etc/zephyr/krb5.keytab zephyr/zephyr@ZONE.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}} +\PYG{n}{Authenticating} \PYG{k}{as} \PYG{n}{principal} \PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{zephyr}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{keytab} \PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{zephyr}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{4}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{WRFILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{zephyr}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{4}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{WRFILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{zephyr}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{4}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{des3}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{WRFILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{zephyr}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{4}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{des}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{crc} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{WRFILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Be sure to remove the old keys from the application keytab, per best +practice. + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} k5srvutil \PYGZhy{}f /etc/zephyr/krb5.keytab delold} +\PYG{n}{Authenticating} \PYG{k}{as} \PYG{n}{principal} \PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{zephyr}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{keytab} \PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{zephyr}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{3} \PYG{n}{removed} \PYG{k+kn}{from} \PYG{n+nn}{keytab} \PYG{n}{WRFILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{zephyr}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\end{sphinxVerbatim} + + +\subsubsection{Adding strong keys by default} +\label{\detokenize{admin/advanced/retiring-des:adding-strong-keys-by-default}} +\sphinxAtStartPar +Once the high\sphinxhyphen{}visibility services have been rekeyed, it is probably +appropriate to change {\hyperref[\detokenize{admin/conf_files/kdc_conf:kdc-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{kdc.conf}}}} to generate keys with the new +encryption types by default. This enables server administrators to generate +new enctypes with the \sphinxstylestrong{change} subcommand of {\hyperref[\detokenize{admin/admin_commands/k5srvutil:k5srvutil-1}]{\sphinxcrossref{\DUrole{std,std-ref}{k5srvutil}}}}, +and causes user password +changes to add new encryption types for their entries. It will probably +be necessary to implement administrative controls to cause all user +principal keys to be updated in a reasonable period of time, whether +by forcing password changes or a password synchronization service that +has access to the current password and can add the new keys. + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{realms}\PYG{p}{]} + \PYG{n}{ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{supported\PYGZus{}enctypes} \PYG{o}{=} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96}\PYG{p}{:}\PYG{n}{normal} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96}\PYG{p}{:}\PYG{n}{normal} \PYG{n}{des3}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{p}{:}\PYG{n}{normal} \PYG{n}{des3}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{p}{:}\PYG{n}{normal} \PYG{n}{des}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{crc}\PYG{p}{:}\PYG{n}{normal} +\end{sphinxVerbatim} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The krb5kdc process must be restarted for these changes to take effect. +\end{sphinxadmonition} + +\sphinxAtStartPar +At this point, all service administrators can update their services and the +servers behind them to take advantage of strong cryptography. +If necessary, the server’s krb5 installation should be configured and/or +upgraded to a version supporting non\sphinxhyphen{}DES keys. See {\hyperref[\detokenize{admin/enctypes:enctypes}]{\sphinxcrossref{\DUrole{std,std-ref}{Encryption types}}}} for +krb5 version and configuration settings. +Only when the service is configured to accept non\sphinxhyphen{}DES keys should +the key version number be incremented and new keys generated +(\sphinxcode{\sphinxupquote{k5srvutil change \&\& k5srvutil delold}}). + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{root}\PYG{n+nd}{@dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{p}{:}\PYG{o}{\PYGZti{}}\PYG{c+c1}{\PYGZsh{} k5srvutil change} +\PYG{n}{Authenticating} \PYG{k}{as} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{o}{.}\PYG{n}{xvm}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{keytab} \PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{o}{.}\PYG{n}{xvm}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{3}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{AES}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{256} \PYG{n}{CTS} \PYG{n}{mode} \PYG{k}{with} \PYG{l+m+mi}{96}\PYG{o}{\PYGZhy{}}\PYG{n}{bit} \PYG{n}{SHA}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{1} \PYG{n}{HMAC} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{WRFILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{o}{.}\PYG{n}{xvm}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{3}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{AES}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{128} \PYG{n}{CTS} \PYG{n}{mode} \PYG{k}{with} \PYG{l+m+mi}{96}\PYG{o}{\PYGZhy{}}\PYG{n}{bit} \PYG{n}{SHA}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{1} \PYG{n}{HMAC} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{WRFILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{o}{.}\PYG{n}{xvm}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{3}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{Triple} \PYG{n}{DES} \PYG{n}{cbc} \PYG{n}{mode} \PYG{k}{with} \PYG{n}{HMAC}\PYG{o}{/}\PYG{n}{sha1} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{WRFILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{o}{.}\PYG{n}{xvm}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{3}\PYG{p}{,} \PYG{n}{encryption} \PYG{n+nb}{type} \PYG{n}{DES} \PYG{n}{cbc} \PYG{n}{mode} \PYG{k}{with} \PYG{n}{CRC}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{32} \PYG{n}{added} \PYG{n}{to} \PYG{n}{keytab} \PYG{n}{WRFILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{root}\PYG{n+nd}{@dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{p}{:}\PYG{o}{\PYGZti{}}\PYG{c+c1}{\PYGZsh{} klist \PYGZhy{}e \PYGZhy{}k \PYGZhy{}t /etc/krb5.keytab} +\PYG{n}{Keytab} \PYG{n}{name}\PYG{p}{:} \PYG{n}{WRFILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab} +\PYG{n}{KVNO} \PYG{n}{Timestamp} \PYG{n}{Principal} +\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}} \PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}} \PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}} + \PYG{l+m+mi}{2} \PYG{l+m+mi}{10}\PYG{o}{/}\PYG{l+m+mi}{10}\PYG{o}{/}\PYG{l+m+mi}{12} \PYG{l+m+mi}{17}\PYG{p}{:}\PYG{l+m+mi}{03}\PYG{p}{:}\PYG{l+m+mi}{59} \PYG{n}{host}\PYG{o}{/}\PYG{n}{dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{o}{.}\PYG{n}{xvm}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{p}{(}\PYG{n}{DES} \PYG{n}{cbc} \PYG{n}{mode} \PYG{k}{with} \PYG{n}{CRC}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{32}\PYG{p}{)} + \PYG{l+m+mi}{3} \PYG{l+m+mi}{12}\PYG{o}{/}\PYG{l+m+mi}{12}\PYG{o}{/}\PYG{l+m+mi}{12} \PYG{l+m+mi}{15}\PYG{p}{:}\PYG{l+m+mi}{31}\PYG{p}{:}\PYG{l+m+mi}{19} \PYG{n}{host}\PYG{o}{/}\PYG{n}{dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{o}{.}\PYG{n}{xvm}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{p}{(}\PYG{n}{AES}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{256} \PYG{n}{CTS} \PYG{n}{mode} \PYG{k}{with} \PYG{l+m+mi}{96}\PYG{o}{\PYGZhy{}}\PYG{n}{bit} \PYG{n}{SHA}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{1} \PYG{n}{HMAC}\PYG{p}{)} + \PYG{l+m+mi}{3} \PYG{l+m+mi}{12}\PYG{o}{/}\PYG{l+m+mi}{12}\PYG{o}{/}\PYG{l+m+mi}{12} \PYG{l+m+mi}{15}\PYG{p}{:}\PYG{l+m+mi}{31}\PYG{p}{:}\PYG{l+m+mi}{19} \PYG{n}{host}\PYG{o}{/}\PYG{n}{dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{o}{.}\PYG{n}{xvm}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{p}{(}\PYG{n}{AES}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{128} \PYG{n}{CTS} \PYG{n}{mode} \PYG{k}{with} \PYG{l+m+mi}{96}\PYG{o}{\PYGZhy{}}\PYG{n}{bit} \PYG{n}{SHA}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{1} \PYG{n}{HMAC}\PYG{p}{)} + \PYG{l+m+mi}{3} \PYG{l+m+mi}{12}\PYG{o}{/}\PYG{l+m+mi}{12}\PYG{o}{/}\PYG{l+m+mi}{12} \PYG{l+m+mi}{15}\PYG{p}{:}\PYG{l+m+mi}{31}\PYG{p}{:}\PYG{l+m+mi}{19} \PYG{n}{host}\PYG{o}{/}\PYG{n}{dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{o}{.}\PYG{n}{xvm}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{p}{(}\PYG{n}{Triple} \PYG{n}{DES} \PYG{n}{cbc} \PYG{n}{mode} \PYG{k}{with} \PYG{n}{HMAC}\PYG{o}{/}\PYG{n}{sha1}\PYG{p}{)} + \PYG{l+m+mi}{3} \PYG{l+m+mi}{12}\PYG{o}{/}\PYG{l+m+mi}{12}\PYG{o}{/}\PYG{l+m+mi}{12} \PYG{l+m+mi}{15}\PYG{p}{:}\PYG{l+m+mi}{31}\PYG{p}{:}\PYG{l+m+mi}{19} \PYG{n}{host}\PYG{o}{/}\PYG{n}{dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{o}{.}\PYG{n}{xvm}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{p}{(}\PYG{n}{DES} \PYG{n}{cbc} \PYG{n}{mode} \PYG{k}{with} \PYG{n}{CRC}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{32}\PYG{p}{)} +\PYG{n}{root}\PYG{n+nd}{@dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{p}{:}\PYG{o}{\PYGZti{}}\PYG{c+c1}{\PYGZsh{} k5srvutil delold} +\PYG{n}{Authenticating} \PYG{k}{as} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{o}{.}\PYG{n}{xvm}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{keytab} \PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\PYG{n}{Entry} \PYG{k}{for} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{dr}\PYG{o}{\PYGZhy{}}\PYG{n}{willy}\PYG{o}{.}\PYG{n}{xvm}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{kvno} \PYG{l+m+mi}{2} \PYG{n}{removed} \PYG{k+kn}{from} \PYG{n+nn}{keytab} \PYG{n}{WRFILE}\PYG{p}{:}\PYG{o}{/}\PYG{n}{etc}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{.}\PYG{n}{keytab}\PYG{o}{.} +\end{sphinxVerbatim} + +\sphinxAtStartPar +When a single service principal is shared by multiple backend servers in +a load\sphinxhyphen{}balanced environment, it may be necessary to schedule downtime +or adjust the population in the load\sphinxhyphen{}balanced pool in order to propagate +the updated keytab to all hosts in the pool with minimal service interruption. + + +\subsubsection{Removing DES keys from usage} +\label{\detokenize{admin/advanced/retiring-des:removing-des-keys-from-usage}} +\sphinxAtStartPar +This situation remains something of a testing or transitory state, +as new DES keys are still being generated, and will be used if requested +by a client. To make more progress removing DES from the realm, the KDC +should be configured to not generate such keys by default. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +An attacker posing as a client can implement a brute force attack against +a DES key for any principal, if that key is in the current (highest\sphinxhyphen{}kvno) +key list. This attack is only possible if \sphinxstylestrong{allow\_weak\_crypto = true} +is enabled on the KDC. Setting the \sphinxstylestrong{+requires\_preauth} flag on a +principal forces this attack to be an online attack, much slower than +the offline attack otherwise available to the attacker. However, setting +this flag on a service principal is not always advisable; see the entry in +{\hyperref[\detokenize{admin/admin_commands/kadmin_local:add-principal}]{\sphinxcrossref{\DUrole{std,std-ref}{add\_principal}}}} for details. +\end{sphinxadmonition} + +\sphinxAtStartPar +The following KDC configuration will not generate DES keys by default: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{realms}\PYG{p}{]} + \PYG{n}{ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{=} \PYG{p}{\PYGZob{}} + \PYG{n}{supported\PYGZus{}enctypes} \PYG{o}{=} \PYG{n}{aes256}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96}\PYG{p}{:}\PYG{n}{normal} \PYG{n}{aes128}\PYG{o}{\PYGZhy{}}\PYG{n}{cts}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{o}{\PYGZhy{}}\PYG{l+m+mi}{96}\PYG{p}{:}\PYG{n}{normal} \PYG{n}{des3}\PYG{o}{\PYGZhy{}}\PYG{n}{cbc}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{p}{:}\PYG{n}{normal} \PYG{n}{des3}\PYG{o}{\PYGZhy{}}\PYG{n}{hmac}\PYG{o}{\PYGZhy{}}\PYG{n}{sha1}\PYG{p}{:}\PYG{n}{normal} +\end{sphinxVerbatim} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +As before, the KDC process must be restarted for this change to take +effect. It is best practice to update kdc.conf on all KDCs, not just the +primary, to avoid unpleasant surprises should the primary fail and a +replica need to be promoted. +\end{sphinxadmonition} + +\sphinxAtStartPar +It is now appropriate to remove the legacy single\sphinxhyphen{}DES key from the +\sphinxcode{\sphinxupquote{krbtgt/REALM}} entry: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} kadmin.local \PYGZhy{}r ZONE.MIT.EDU \PYGZhy{}q \PYGZdq{}cpw \PYGZhy{}randkey \PYGZhy{}keepold \PYGZbs{}} +\PYG{o}{\PYGZgt{}} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{l+s+s2}{\PYGZdq{}} +\PYG{n}{Authenticating} \PYG{k}{as} \PYG{n}{principal} \PYG{n}{host}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Key} \PYG{k}{for} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{krbtgt/ZONE.MIT.EDU@ZONE.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{randomized}\PYG{o}{.} +\end{sphinxVerbatim} + +\sphinxAtStartPar +After the maximum ticket lifetime has passed, the old database entry +should be removed. + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{[}\PYG{n}{root}\PYG{n+nd}{@casio} \PYG{n}{krb5kdc}\PYG{p}{]}\PYG{c+c1}{\PYGZsh{} kadmin.local \PYGZhy{}r ZONE.MIT.EDU \PYGZhy{}q \PYGZsq{}purgekeys krbtgt/ZONE.MIT.EDU\PYGZsq{}} +\PYG{n}{Authenticating} \PYG{k}{as} \PYG{n}{principal} \PYG{n}{root}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@ZONE}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} \PYG{k}{with} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Old} \PYG{n}{keys} \PYG{k}{for} \PYG{n}{principal} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{krbtgt/ZONE.MIT.EDU@ZONE.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}} \PYG{n}{purged}\PYG{o}{.} +\end{sphinxVerbatim} + +\sphinxAtStartPar +After the KDC is restarted with the new \sphinxstylestrong{supported\_enctypes}, +all user password changes and application keytab updates will not +generate DES keys by default. + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +contents\PYGZhy{}vnder\PYGZhy{}pressvre:\PYGZti{}\PYGZgt{} kpasswd zonetest@ZONE.MIT.EDU +Password for zonetest@ZONE.MIT.EDU: [enter old password] +Enter new password: [enter new password] +Enter it again: [enter new password] +Password changed. +contents\PYGZhy{}vnder\PYGZhy{}pressvre:\PYGZti{}\PYGZgt{} kadmin \PYGZhy{}r ZONE.MIT.EDU \PYGZhy{}q \PYGZsq{}getprinc zonetest\PYGZsq{} +[...] +Number of keys: 3 +Key: vno 9, aes256\PYGZhy{}cts\PYGZhy{}hmac\PYGZhy{}sha1\PYGZhy{}96 +Key: vno 9, aes128\PYGZhy{}cts\PYGZhy{}hmac\PYGZhy{}sha1\PYGZhy{}96 +Key: vno 9, des3\PYGZhy{}cbc\PYGZhy{}sha1 +[...] + +[kaduk@glossolalia \PYGZti{}]\PYGZdl{} kadmin \PYGZhy{}p kaduk@ZONE.MIT.EDU \PYGZhy{}r ZONE.MIT.EDU \PYGZhy{}k \PYGZbs{} +\PYGZgt{} \PYGZhy{}t kaduk\PYGZhy{}zone.keytab \PYGZhy{}q \PYGZsq{}ktadd \PYGZhy{}k kaduk\PYGZhy{}zone.keytab kaduk@ZONE.MIT.EDU\PYGZsq{} +Authenticating as principal kaduk@ZONE.MIT.EDU with keytab kaduk\PYGZhy{}zone.keytab. +Entry for principal kaduk@ZONE.MIT.EDU with kvno 3, encryption type aes256\PYGZhy{}cts\PYGZhy{}hmac\PYGZhy{}sha1\PYGZhy{}96 added to keytab WRFILE:kaduk\PYGZhy{}zone.keytab. +Entry for principal kaduk@ZONE.MIT.EDU with kvno 3, encryption type aes128\PYGZhy{}cts\PYGZhy{}hmac\PYGZhy{}sha1\PYGZhy{}96 added to keytab WRFILE:kaduk\PYGZhy{}zone.keytab. +Entry for principal kaduk@ZONE.MIT.EDU with kvno 3, encryption type des3\PYGZhy{}cbc\PYGZhy{}sha1 added to keytab WRFILE:kaduk\PYGZhy{}zone.keytab. +\end{sphinxVerbatim} + +\sphinxAtStartPar +Once all principals have been re\sphinxhyphen{}keyed, DES support can be disabled on the +KDC (\sphinxstylestrong{allow\_weak\_crypto = false}), and client machines can remove +\sphinxstylestrong{allow\_weak\_crypto = true} from their {\hyperref[\detokenize{admin/conf_files/krb5_conf:krb5-conf-5}]{\sphinxcrossref{\DUrole{std,std-ref}{krb5.conf}}}} configuration +files, completing the migration. \sphinxstylestrong{allow\_weak\_crypto} takes precedence over +all places where DES enctypes could be explicitly configured. DES keys will +not be used, even if they are present, when \sphinxstylestrong{allow\_weak\_crypto = false}. + + +\subsubsection{Support for legacy services} +\label{\detokenize{admin/advanced/retiring-des:support-for-legacy-services}} +\sphinxAtStartPar +If there remain legacy services which do not support non\sphinxhyphen{}DES enctypes +(such as older versions of AFS), \sphinxstylestrong{allow\_weak\_crypto} must remain +enabled on the KDC. Client machines need not have this setting, +though—applications which require DES can use API calls to allow +weak crypto on a per\sphinxhyphen{}request basis, overriding the system krb5.conf. +However, having \sphinxstylestrong{allow\_weak\_crypto} set on the KDC means that any +principals which have a DES key in the database could still use those +keys. To minimize the use of DES in the realm and restrict it to just +legacy services which require DES, it is necessary to remove all other +DES keys. The realm has been configured such that at password and +keytab change, no DES keys will be generated by default. The task +then reduces to requiring user password changes and having server +administrators update their service keytabs. Administrative outreach +will be necessary, and if the desire to eliminate DES is sufficiently +strong, the KDC administrators may choose to randkey any principals +which have not been rekeyed after some timeout period, forcing the +user to contact the helpdesk for access. + + +\subsection{The Database Master Key} +\label{\detokenize{admin/advanced/retiring-des:the-database-master-key}} +\sphinxAtStartPar +This procedure does not alter \sphinxcode{\sphinxupquote{K/M@REALM}}, the key used to encrypt key +material in the Kerberos database. (This is the key stored in the stash file +on the KDC if stash files are used.) However, the security risk of +a single\sphinxhyphen{}DES key for \sphinxcode{\sphinxupquote{K/M}} is minimal, given that access to material +encrypted in \sphinxcode{\sphinxupquote{K/M}} (the Kerberos database) is generally tightly controlled. +If an attacker can gain access to the encrypted database, they likely +have access to the stash file as well, rendering the weak cryptography +broken by non\sphinxhyphen{}cryptographic means. As such, upgrading \sphinxcode{\sphinxupquote{K/M}} to a stronger +encryption type is unlikely to be a high\sphinxhyphen{}priority task. + +\sphinxAtStartPar +Is is possible to upgrade the master key used for the database, if +desired. Using {\hyperref[\detokenize{admin/admin_commands/kdb5_util:kdb5-util-8}]{\sphinxcrossref{\DUrole{std,std-ref}{kdb5\_util}}}}’s \sphinxstylestrong{add\_mkey}, \sphinxstylestrong{use\_mkey}, and +\sphinxstylestrong{update\_princ\_encryption} commands, a new master key can be added +and activated for use on new key material, and the existing entries +converted to the new master key. + + +\chapter{Various links} +\label{\detokenize{admin/various_envs:various-links}}\label{\detokenize{admin/various_envs::doc}} + +\section{Whitepapers} +\label{\detokenize{admin/various_envs:whitepapers}}\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +\sphinxurl{https://kerberos.org/software/whitepapers.html} + +\end{enumerate} + + +\section{Tutorials} +\label{\detokenize{admin/various_envs:tutorials}}\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +Fulvio Ricciardi \textless{}\sphinxurl{https://www.kerberos.org/software/tutorial.html}\textgreater{}\_ + +\end{enumerate} + + +\section{Troubleshooting} +\label{\detokenize{admin/various_envs:troubleshooting}}\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +\sphinxurl{https://wiki.ncsa.illinois.edu/display/ITS/Windows+Kerberos+Troubleshooting} + +\item {} +\sphinxAtStartPar +\sphinxurl{https://www.shrubbery.net/solaris9ab/SUNWaadm/SYSADV6/p27.html} + +\item {} +\sphinxAtStartPar +\sphinxurl{https://docs.oracle.com/cd/E19253-01/816-4557/trouble-1/index.html} + +\item {} +\sphinxAtStartPar +\sphinxurl{https://docs.microsoft.com/en-us/previous-versions/tn-archive/bb463167(v=technet.10})\#EBAA + +\item {} +\sphinxAtStartPar +\sphinxurl{https://bugs.launchpad.net/ubuntu/+source/libpam-heimdal/+bug/86528} + +\end{enumerate} + + + +\renewcommand{\indexname}{Index} +\printindex +\end{document} \ No newline at end of file diff --git a/krb5-1.21.3/doc/pdf/appdev.pdf b/krb5-1.21.3/doc/pdf/appdev.pdf new file mode 100644 index 0000000000000000000000000000000000000000..781b33037f20b8f5f08b371d3860ad11bf11c8df GIT binary patch literal 829074 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

  • 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
      j?Au;ltWM(W6 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�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

      -OU^?7pl?WNyB3E~i=#z?m(rn988w?pnve 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 eLY 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≧FL$FrUipY$p<;&BDS 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

      On`}T^w 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�?H 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 z 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 z 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 KR8?L5-M9dILV%C} literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/doc/pdf/basic.tex b/krb5-1.21.3/doc/pdf/basic.tex new file mode 100644 index 00000000..898bc40f --- /dev/null +++ b/krb5-1.21.3/doc/pdf/basic.tex @@ -0,0 +1,918 @@ +%% Generated by Sphinx. +\def\sphinxdocclass{report} +\documentclass[letterpaper,10pt,english]{sphinxmanual} +\ifdefined\pdfpxdimen + \let\sphinxpxdimen\pdfpxdimen\else\newdimen\sphinxpxdimen +\fi \sphinxpxdimen=.75bp\relax +\ifdefined\pdfimageresolution + \pdfimageresolution= \numexpr \dimexpr1in\relax/\sphinxpxdimen\relax +\fi +%% let collapsible pdf bookmarks panel have high depth per default +\PassOptionsToPackage{bookmarksdepth=5}{hyperref} + +\PassOptionsToPackage{warn}{textcomp} +\usepackage[utf8]{inputenc} +\ifdefined\DeclareUnicodeCharacter +% support both utf8 and utf8x syntaxes + \ifdefined\DeclareUnicodeCharacterAsOptional + \def\sphinxDUC#1{\DeclareUnicodeCharacter{"#1}} + \else + \let\sphinxDUC\DeclareUnicodeCharacter + \fi + \sphinxDUC{00A0}{\nobreakspace} + \sphinxDUC{2500}{\sphinxunichar{2500}} + \sphinxDUC{2502}{\sphinxunichar{2502}} + \sphinxDUC{2514}{\sphinxunichar{2514}} + \sphinxDUC{251C}{\sphinxunichar{251C}} + \sphinxDUC{2572}{\textbackslash} +\fi +\usepackage{cmap} +\usepackage[T1]{fontenc} +\usepackage{amsmath,amssymb,amstext} +\usepackage{babel} + + + +\usepackage{tgtermes} +\usepackage{tgheros} +\renewcommand{\ttdefault}{txtt} + + + +\usepackage[Bjarne]{fncychap} +\usepackage{sphinx} + +\fvset{fontsize=auto} +\usepackage{geometry} + + +% Include hyperref last. +\usepackage{hyperref} +% Fix anchor placement for figures with captions. +\usepackage{hypcap}% it must be loaded after hyperref. +% Set up styles of URL: it should be placed after hyperref. +\urlstyle{same} + + +\usepackage{sphinxmessages} +\setcounter{tocdepth}{0} + + + +\title{Kerberos Concepts} +\date{ } +\release{1.21.3} +\author{MIT} +\newcommand{\sphinxlogo}{\vbox{}} +\renewcommand{\releasename}{Release} +\makeindex +\begin{document} + +\pagestyle{empty} +\sphinxmaketitle +\pagestyle{plain} +\sphinxtableofcontents +\pagestyle{normal} +\phantomsection\label{\detokenize{basic/index::doc}} + + + +\chapter{Credential cache} +\label{\detokenize{basic/ccache_def:credential-cache}}\label{\detokenize{basic/ccache_def:ccache-definition}}\label{\detokenize{basic/ccache_def::doc}} +\sphinxAtStartPar +A credential cache (or “ccache”) holds Kerberos credentials while they +remain valid and, generally, while the user’s session lasts, so that +authenticating to a service multiple times (e.g., connecting to a web +or mail server more than once) doesn’t require contacting the KDC +every time. + +\sphinxAtStartPar +A credential cache usually contains one initial ticket which is +obtained using a password or another form of identity verification. +If this ticket is a ticket\sphinxhyphen{}granting ticket, it can be used to obtain +additional credentials without the password. Because the credential +cache does not store the password, less long\sphinxhyphen{}term damage can be done +to the user’s account if the machine is compromised. + +\sphinxAtStartPar +A credentials cache stores a default client principal name, set when +the cache is created. This is the name shown at the top of the +\DUrole{xref,std,std-ref}{klist(1)} \sphinxstyleemphasis{\sphinxhyphen{}A} output. + +\sphinxAtStartPar +Each normal cache entry includes a service principal name, a client +principal name (which, in some ccache types, need not be the same as +the default), lifetime information, and flags, along with the +credential itself. There are also other entries, indicated by special +names, that store additional information. + + +\section{ccache types} +\label{\detokenize{basic/ccache_def:ccache-types}} +\sphinxAtStartPar +The credential cache interface, like the {\hyperref[\detokenize{basic/keytab_def:keytab-definition}]{\sphinxcrossref{\DUrole{std,std-ref}{keytab}}}} and +{\hyperref[\detokenize{basic/rcache_def:rcache-definition}]{\sphinxcrossref{\DUrole{std,std-ref}{replay cache}}}} interfaces, uses \sphinxtitleref{TYPE:value} strings to +indicate the type of credential cache and any associated cache naming +data to use. + +\sphinxAtStartPar +There are several kinds of credentials cache supported in the MIT +Kerberos library. Not all are supported on every platform. In most +cases, it should be correct to use the default type built into the +library. +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +\sphinxstylestrong{API} is only implemented on Windows. It communicates with a +server process that holds the credentials in memory for the user, +rather than writing them to disk. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{DIR} points to the storage location of the collection of the +credential caches in \sphinxstyleemphasis{FILE:} format. It is most useful when dealing +with multiple Kerberos realms and KDCs. For release 1.10 the +directory must already exist. In post\sphinxhyphen{}1.10 releases the +requirement is for parent directory to exist and the current +process must have permissions to create the directory if it does +not exist. See {\hyperref[\detokenize{basic/ccache_def:col-ccache}]{\sphinxcrossref{\DUrole{std,std-ref}{Collections of caches}}}} for details. New in release 1.10. +The following residual forms are supported: +\begin{itemize} +\item {} +\sphinxAtStartPar +DIR:dirname + +\item {} +\sphinxAtStartPar +DIR::dirpath/filename \sphinxhyphen{} a single cache within the directory + +\end{itemize} + +\sphinxAtStartPar +Switching to a ccache of the latter type causes it to become the +primary for the directory. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{FILE} caches are the simplest and most portable. A simple flat +file format is used to store one credential after another. This is +the default ccache type if no type is specified in a ccache name. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{KCM} caches work by contacting a daemon process called \sphinxcode{\sphinxupquote{kcm}} +to perform cache operations. If the cache name is just \sphinxcode{\sphinxupquote{KCM:}}, +the default cache as determined by the KCM daemon will be used. +Newly created caches must generally be named \sphinxcode{\sphinxupquote{KCM:uid:name}}, +where \sphinxstyleemphasis{uid} is the effective user ID of the running process. + +\sphinxAtStartPar +KCM client support is new in release 1.13. A KCM daemon has not +yet been implemented in MIT krb5, but the client will interoperate +with the KCM daemon implemented by Heimdal. macOS 10.7 and higher +provides a KCM daemon as part of the operating system, and the +\sphinxstylestrong{KCM} cache type is used as the default cache on that platform in +a default build. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{KEYRING} is Linux\sphinxhyphen{}specific, and uses the kernel keyring support +to store credential data in unswappable kernel memory where only +the current user should be able to access it. The following +residual forms are supported: +\begin{itemize} +\item {} +\sphinxAtStartPar +KEYRING:name + +\item {} +\sphinxAtStartPar +KEYRING:process:name \sphinxhyphen{} process keyring + +\item {} +\sphinxAtStartPar +KEYRING:thread:name \sphinxhyphen{} thread keyring + +\end{itemize} + +\sphinxAtStartPar +Starting with release 1.12 the \sphinxstyleemphasis{KEYRING} type supports collections. +The following new residual forms were added: +\begin{itemize} +\item {} +\sphinxAtStartPar +KEYRING:session:name \sphinxhyphen{} session keyring + +\item {} +\sphinxAtStartPar +KEYRING:user:name \sphinxhyphen{} user keyring + +\item {} +\sphinxAtStartPar +KEYRING:persistent:uidnumber \sphinxhyphen{} persistent per\sphinxhyphen{}UID collection. +Unlike the user keyring, this collection survives after the user +logs out, until the cache credentials expire. This type of +ccache requires support from the kernel; otherwise, it will fall +back to the user keyring. + +\end{itemize} + +\sphinxAtStartPar +See {\hyperref[\detokenize{basic/ccache_def:col-ccache}]{\sphinxcrossref{\DUrole{std,std-ref}{Collections of caches}}}} for details. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{MEMORY} caches are for storage of credentials that don’t need to +be made available outside of the current process. For example, a +memory ccache is used by \DUrole{xref,std,std-ref}{kadmin(1)} to store the +administrative ticket used to contact the admin server. Memory +ccaches are faster than file ccaches and are automatically +destroyed when the process exits. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{MSLSA} is a Windows\sphinxhyphen{}specific cache type that accesses the +Windows credential store. + +\end{enumerate} + + +\section{Collections of caches} +\label{\detokenize{basic/ccache_def:collections-of-caches}}\label{\detokenize{basic/ccache_def:col-ccache}} +\sphinxAtStartPar +Some credential cache types can support collections of multiple +caches. One of the caches in the collection is designated as the +\sphinxstyleemphasis{primary} and will be used when the collection is resolved as a cache. +When a collection\sphinxhyphen{}enabled cache type is the default cache for a +process, applications can search the specified collection for a +specific client principal, and GSSAPI applications will automatically +select between the caches in the collection based on criteria such as +the target service realm. + +\sphinxAtStartPar +Credential cache collections are new in release 1.10, with support +from the \sphinxstylestrong{DIR} and \sphinxstylestrong{API} ccache types. Starting in release 1.12, +collections are also supported by the \sphinxstylestrong{KEYRING} ccache type. +Collections are supported by the \sphinxstylestrong{KCM} ccache type in release 1.13. + + +\subsection{Tool alterations to use cache collection} +\label{\detokenize{basic/ccache_def:tool-alterations-to-use-cache-collection}}\begin{itemize} +\item {} +\sphinxAtStartPar +\DUrole{xref,std,std-ref}{kdestroy(1)} \sphinxstyleemphasis{\sphinxhyphen{}A} will destroy all caches in the collection. + +\item {} +\sphinxAtStartPar +If the default cache type supports switching, \DUrole{xref,std,std-ref}{kinit(1)} +\sphinxstyleemphasis{princname} will search the collection for a matching cache and +store credentials there, or will store credentials in a new unique +cache of the default type if no existing cache for the principal +exists. Either way, kinit will switch to the selected cache. + +\item {} +\sphinxAtStartPar +\DUrole{xref,std,std-ref}{klist(1)} \sphinxstyleemphasis{\sphinxhyphen{}l} will list the caches in the collection. + +\item {} +\sphinxAtStartPar +\DUrole{xref,std,std-ref}{klist(1)} \sphinxstyleemphasis{\sphinxhyphen{}A} will show the content of all caches in the +collection. + +\item {} +\sphinxAtStartPar +\DUrole{xref,std,std-ref}{kswitch(1)} \sphinxstyleemphasis{\sphinxhyphen{}p princname} will search the collection for a +matching cache and switch to it. + +\item {} +\sphinxAtStartPar +\DUrole{xref,std,std-ref}{kswitch(1)} \sphinxstyleemphasis{\sphinxhyphen{}c cachename} will switch to a specified cache. + +\end{itemize} + + +\section{Default ccache name} +\label{\detokenize{basic/ccache_def:default-ccache-name}} +\sphinxAtStartPar +The default credential cache name is determined by the following, in +descending order of priority: +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +The \sphinxstylestrong{KRB5CCNAME} environment variable. For example, +\sphinxcode{\sphinxupquote{KRB5CCNAME=DIR:/mydir/}}. + +\item {} +\sphinxAtStartPar +The \sphinxstylestrong{default\_ccache\_name} profile variable in \DUrole{xref,std,std-ref}{libdefaults}. + +\item {} +\sphinxAtStartPar +The hardcoded default, \DUrole{xref,std,std-ref}{DEFCCNAME}. + +\end{enumerate} + + +\chapter{keytab} +\label{\detokenize{basic/keytab_def:keytab}}\label{\detokenize{basic/keytab_def:keytab-definition}}\label{\detokenize{basic/keytab_def::doc}} +\sphinxAtStartPar +A keytab (short for “key table”) stores long\sphinxhyphen{}term keys for one or more +principals. Keytabs are normally represented by files in a standard +format, although in rare cases they can be represented in other ways. +Keytabs are used most often to allow server applications to accept +authentications from clients, but can also be used to obtain initial +credentials for client applications. + +\sphinxAtStartPar +Keytabs are named using the format \sphinxstyleemphasis{type}\sphinxcode{\sphinxupquote{:}}\sphinxstyleemphasis{value}. Usually +\sphinxstyleemphasis{type} is \sphinxcode{\sphinxupquote{FILE}} and \sphinxstyleemphasis{value} is the absolute pathname of the file. +The other possible value for \sphinxstyleemphasis{type} is \sphinxcode{\sphinxupquote{MEMORY}}, which indicates a +temporary keytab stored in the memory of the current process. + +\sphinxAtStartPar +A keytab contains one or more entries, where each entry consists of a +timestamp (indicating when the entry was written to the keytab), a +principal name, a key version number, an encryption type, and the +encryption key itself. + +\sphinxAtStartPar +A keytab can be displayed using the \DUrole{xref,std,std-ref}{klist(1)} command with the +\sphinxcode{\sphinxupquote{\sphinxhyphen{}k}} option. Keytabs can be created or appended to by extracting +keys from the KDC database using the \DUrole{xref,std,std-ref}{kadmin(1)} \DUrole{xref,std,std-ref}{ktadd} +command. Keytabs can be manipulated using the \DUrole{xref,std,std-ref}{ktutil(1)} and +\DUrole{xref,std,std-ref}{k5srvutil(1)} commands. + + +\section{Default keytab} +\label{\detokenize{basic/keytab_def:default-keytab}} +\sphinxAtStartPar +The default keytab is used by server applications if the application +does not request a specific keytab. The name of the default keytab is +determined by the following, in decreasing order of preference: +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +The \sphinxstylestrong{KRB5\_KTNAME} environment variable. + +\item {} +\sphinxAtStartPar +The \sphinxstylestrong{default\_keytab\_name} profile variable in \DUrole{xref,std,std-ref}{libdefaults}. + +\item {} +\sphinxAtStartPar +The hardcoded default, \DUrole{xref,std,std-ref}{DEFKTNAME}. + +\end{enumerate} + + +\section{Default client keytab} +\label{\detokenize{basic/keytab_def:default-client-keytab}} +\sphinxAtStartPar +The default client keytab is used, if it is present and readable, to +automatically obtain initial credentials for GSSAPI client +applications. The principal name of the first entry in the client +keytab is used by default when obtaining initial credentials. The +name of the default client keytab is determined by the following, in +decreasing order of preference: +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +The \sphinxstylestrong{KRB5\_CLIENT\_KTNAME} environment variable. + +\item {} +\sphinxAtStartPar +The \sphinxstylestrong{default\_client\_keytab\_name} profile variable in +\DUrole{xref,std,std-ref}{libdefaults}. + +\item {} +\sphinxAtStartPar +The hardcoded default, \DUrole{xref,std,std-ref}{DEFCKTNAME}. + +\end{enumerate} + + +\chapter{replay cache} +\label{\detokenize{basic/rcache_def:replay-cache}}\label{\detokenize{basic/rcache_def:rcache-definition}}\label{\detokenize{basic/rcache_def::doc}} +\sphinxAtStartPar +A replay cache (or “rcache”) keeps track of all authenticators +recently presented to a service. If a duplicate authentication +request is detected in the replay cache, an error message is sent to +the application program. + +\sphinxAtStartPar +The replay cache interface, like the credential cache and +{\hyperref[\detokenize{basic/keytab_def:keytab-definition}]{\sphinxcrossref{\DUrole{std,std-ref}{keytab}}}} interfaces, uses \sphinxtitleref{type:residual} strings to +indicate the type of replay cache and any associated cache naming +data to use. + + +\section{Background information} +\label{\detokenize{basic/rcache_def:background-information}} +\sphinxAtStartPar +Some Kerberos or GSSAPI services use a simple authentication mechanism +where a message is sent containing an authenticator, which establishes +the encryption key that the client will use for talking to the +service. But nothing about that prevents an eavesdropper from +recording the messages sent by the client, establishing a new +connection, and re\sphinxhyphen{}sending or “replaying” the same messages; the +replayed authenticator will establish the same encryption key for the +new session, and the following messages will be decrypted and +processed. The attacker may not know what the messages say, and can’t +generate new messages under the same encryption key, but in some +instances it may be harmful to the user (or helpful to the attacker) +to cause the server to see the same messages again a second time. For +example, if the legitimate client sends “delete first message in +mailbox”, a replay from an attacker may delete another, different +“first” message. (Protocol design to guard against such problems has +been discussed in \index{RFC@\spxentry{RFC}!RFC 4120\#section\sphinxhyphen{}10@\spxentry{RFC 4120\#section\sphinxhyphen{}10}}\sphinxhref{https://tools.ietf.org/html/rfc4120.html\#section-10}{\sphinxstylestrong{RFC 4120\#section\sphinxhyphen{}10}}.) + +\sphinxAtStartPar +Even if one protocol uses further protection to verify that the client +side of the connection actually knows the encryption keys (and thus is +presumably a legitimate user), if another service uses the same +service principal name, it may be possible to record an authenticator +used with the first protocol and “replay” it against the second. + +\sphinxAtStartPar +The replay cache mitigates these attacks somewhat, by keeping track of +authenticators that have been seen until their five\sphinxhyphen{}minute window +expires. Different authenticators generated by multiple connections +from the same legitimate client will generally have different +timestamps, and thus will not be considered the same. + +\sphinxAtStartPar +This mechanism isn’t perfect. If a message is sent to one application +server but a man\sphinxhyphen{}in\sphinxhyphen{}the\sphinxhyphen{}middle attacker can prevent it from actually +arriving at that server, the attacker could then use the authenticator +(once!) against a different service on the same host. This could be a +problem if the message from the client included something more than +authentication in the first message that could be useful to the +attacker (which is uncommon; in most protocols the server has to +indicate a successful authentication before the client sends +additional messages), or if the simple act of presenting the +authenticator triggers some interesting action in the service being +attacked. + + +\section{Replay cache types} +\label{\detokenize{basic/rcache_def:replay-cache-types}} +\sphinxAtStartPar +Unlike the credential cache and keytab interfaces, replay cache types +are in lowercase. The following types are defined: +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +\sphinxstylestrong{none} disables the replay cache. The residual value is ignored. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{file2} (new in release 1.18) uses a hash\sphinxhyphen{}based format to store +replay records. The file may grow to accommodate hash collisions. +The residual value is the filename. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{dfl} is the default type if no environment variable or +configuration specifies a different type. It stores replay data in +a file2 replay cache with a filename based on the effective uid. +The residual value is ignored. + +\end{enumerate} + +\sphinxAtStartPar +For the dfl type, the location of the replay cache file is determined +as follows: +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +The directory is taken from the \sphinxstylestrong{KRB5RCACHEDIR} environment +variable, or the \sphinxstylestrong{TMPDIR} environment variable, or a temporary +directory determined at configuration time such as \sphinxcode{\sphinxupquote{/var/tmp}}, in +descending order of preference. + +\item {} +\sphinxAtStartPar +The filename is \sphinxcode{\sphinxupquote{krb5\_EUID.rcache2}} where EUID is the effective +uid of the process. + +\item {} +\sphinxAtStartPar +The file is opened without following symbolic links, and ownership +of the file is verified to match the effective uid. + +\end{enumerate} + +\sphinxAtStartPar +On Windows, the directory for the dfl type is the local appdata +directory, unless overridden by the \sphinxstylestrong{KRB5RCACHEDIR} environment +variable. The filename on Windows is \sphinxcode{\sphinxupquote{krb5.rcache2}}, and the file +is opened normally. + + +\section{Default replay cache name} +\label{\detokenize{basic/rcache_def:default-replay-cache-name}} +\sphinxAtStartPar +The default replay cache name is determined by the following, in +descending order of priority: +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +The \sphinxstylestrong{KRB5RCACHENAME} environment variable (new in release 1.18). + +\item {} +\sphinxAtStartPar +The \sphinxstylestrong{KRB5RCACHETYPE} environment variable. If this variable is +set, the residual value is empty. + +\item {} +\sphinxAtStartPar +The \sphinxstylestrong{default\_rcache\_name} profile variable in \DUrole{xref,std,std-ref}{libdefaults} +(new in release 1.18). + +\item {} +\sphinxAtStartPar +If none of the above are set, the default replay cache name is +\sphinxcode{\sphinxupquote{dfl:}}. + +\end{enumerate} + + +\chapter{stash file} +\label{\detokenize{basic/stash_file_def:stash-file}}\label{\detokenize{basic/stash_file_def:stash-definition}}\label{\detokenize{basic/stash_file_def::doc}} +\sphinxAtStartPar +The stash file is a local copy of the master key that resides in +encrypted form on the KDC’s local disk. The stash file is used to +authenticate the KDC to itself automatically before starting the +\DUrole{xref,std,std-ref}{kadmind(8)} and \DUrole{xref,std,std-ref}{krb5kdc(8)} daemons (e.g., as part of the +machine’s boot sequence). The stash file, like the keytab file (see +\DUrole{xref,std,std-ref}{keytab\_file}) is a potential point\sphinxhyphen{}of\sphinxhyphen{}entry for a break\sphinxhyphen{}in, and +if compromised, would allow unrestricted access to the Kerberos +database. If you choose to install a stash file, it should be +readable only by root, and should exist only on the KDC’s local disk. +The file should not be part of any backup of the machine, unless +access to the backup data is secured as tightly as access to the +master password itself. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +If you choose not to install a stash file, the KDC will prompt you for the master key each time it starts up. +This means that the KDC will not be able to start automatically, such as after a system reboot. +\end{sphinxadmonition} + + +\chapter{Supported date and time formats} +\label{\detokenize{basic/date_format:supported-date-and-time-formats}}\label{\detokenize{basic/date_format:datetime}}\label{\detokenize{basic/date_format::doc}} + +\section{Time duration} +\label{\detokenize{basic/date_format:time-duration}}\label{\detokenize{basic/date_format:duration}} +\sphinxAtStartPar +This format is used to express a time duration in the Kerberos +configuration files and user commands. The allowed formats are: +\begin{quote} + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|T|} +\hline + +\sphinxAtStartPar +Format +& +\sphinxAtStartPar +Example +& +\sphinxAtStartPar +Value +\\ +\hline +\sphinxAtStartPar +h:m{[}:s{]} +& +\sphinxAtStartPar +36:00 +& +\sphinxAtStartPar +36 hours +\\ +\hline +\sphinxAtStartPar +NdNhNmNs +& +\sphinxAtStartPar +8h30s +& +\sphinxAtStartPar +8 hours 30 seconds +\\ +\hline +\sphinxAtStartPar +N (number of seconds) +& +\sphinxAtStartPar +3600 +& +\sphinxAtStartPar +1 hour +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} +\end{quote} + +\sphinxAtStartPar +Here \sphinxstyleemphasis{N} denotes a number, \sphinxstyleemphasis{d} \sphinxhyphen{} days, \sphinxstyleemphasis{h} \sphinxhyphen{} hours, \sphinxstyleemphasis{m} \sphinxhyphen{} minutes, +\sphinxstyleemphasis{s} \sphinxhyphen{} seconds. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The time interval should not exceed 2147483647 seconds. +\end{sphinxadmonition} + +\sphinxAtStartPar +Examples: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{Request} \PYG{n}{a} \PYG{n}{ticket} \PYG{n}{valid} \PYG{k}{for} \PYG{n}{one} \PYG{n}{hour}\PYG{p}{,} \PYG{n}{five} \PYG{n}{hours}\PYG{p}{,} \PYG{l+m+mi}{30} \PYG{n}{minutes} +\PYG{o+ow}{and} \PYG{l+m+mi}{10} \PYG{n}{days} \PYG{n}{respectively}\PYG{p}{:} + + \PYG{n}{kinit} \PYG{o}{\PYGZhy{}}\PYG{n}{l} \PYG{l+m+mi}{3600} + \PYG{n}{kinit} \PYG{o}{\PYGZhy{}}\PYG{n}{l} \PYG{l+m+mi}{5}\PYG{p}{:}\PYG{l+m+mi}{00} + \PYG{n}{kinit} \PYG{o}{\PYGZhy{}}\PYG{n}{l} \PYG{l+m+mi}{30}\PYG{n}{m} + \PYG{n}{kinit} \PYG{o}{\PYGZhy{}}\PYG{n}{l} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{10d 0h 0m 0s}\PYG{l+s+s2}{\PYGZdq{}} +\end{sphinxVerbatim} + + +\section{getdate time} +\label{\detokenize{basic/date_format:getdate-time}}\label{\detokenize{basic/date_format:getdate}} +\sphinxAtStartPar +Some of the kadmin and kdb5\_util commands take a date\sphinxhyphen{}time in a +human\sphinxhyphen{}readable format. Some of the acceptable date\sphinxhyphen{}time +strings are: +\begin{quote} + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|T|} +\hline +\sphinxstyletheadfamily &\sphinxstyletheadfamily +\sphinxAtStartPar +Format +&\sphinxstyletheadfamily +\sphinxAtStartPar +Example +\\ +\hline\sphinxmultirow{3}{4}{% +\begin{varwidth}[t]{\sphinxcolwidth{1}{3}} +\sphinxAtStartPar +Date +\par +\vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% +}% +& +\sphinxAtStartPar +mm/dd/yy +& +\sphinxAtStartPar +07/27/12 +\\ +\cline{2-3}\sphinxtablestrut{4}& +\sphinxAtStartPar +month dd, yyyy +& +\sphinxAtStartPar +Jul 27, 2012 +\\ +\cline{2-3}\sphinxtablestrut{4}& +\sphinxAtStartPar +yyyy\sphinxhyphen{}mm\sphinxhyphen{}dd +& +\sphinxAtStartPar +2012\sphinxhyphen{}07\sphinxhyphen{}27 +\\ +\hline\sphinxmultirow{2}{11}{% +\begin{varwidth}[t]{\sphinxcolwidth{1}{3}} +\sphinxAtStartPar +Absolute +time +\par +\vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% +}% +& +\sphinxAtStartPar +HH:mm{[}:ss{]}pp +& +\sphinxAtStartPar +08:30 PM +\\ +\cline{2-3}\sphinxtablestrut{11}& +\sphinxAtStartPar +hh:mm{[}:ss{]} +& +\sphinxAtStartPar +20:30 +\\ +\hline +\sphinxAtStartPar +Relative +time +& +\sphinxAtStartPar +N tt +& +\sphinxAtStartPar +30 sec +\\ +\hline\sphinxmultirow{2}{19}{% +\begin{varwidth}[t]{\sphinxcolwidth{1}{3}} +\sphinxAtStartPar +Time zone +\par +\vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% +}% +& +\sphinxAtStartPar +Z +& +\sphinxAtStartPar +EST +\\ +\cline{2-3}\sphinxtablestrut{19}& +\sphinxAtStartPar +z +& +\sphinxAtStartPar +\sphinxhyphen{}0400 +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} +\end{quote} + +\sphinxAtStartPar +(See {\hyperref[\detokenize{basic/date_format:abbreviation}]{\sphinxcrossref{\DUrole{std,std-ref}{Abbreviations used in this document}}}}.) + +\sphinxAtStartPar +Examples: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{Create} \PYG{n}{a} \PYG{n}{principal} \PYG{n}{that} \PYG{n}{expires} \PYG{n}{on} \PYG{n}{the} \PYG{n}{date} \PYG{n}{indicated}\PYG{p}{:} + \PYG{n}{addprinc} \PYG{n}{test1} \PYG{o}{\PYGZhy{}}\PYG{n}{expire} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{3/27/12 10:00:07 EST}\PYG{l+s+s2}{\PYGZdq{}} + \PYG{n}{addprinc} \PYG{n}{test2} \PYG{o}{\PYGZhy{}}\PYG{n}{expire} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{January 23, 2015 10:05pm}\PYG{l+s+s2}{\PYGZdq{}} + \PYG{n}{addprinc} \PYG{n}{test3} \PYG{o}{\PYGZhy{}}\PYG{n}{expire} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{22:00 GMT}\PYG{l+s+s2}{\PYGZdq{}} +\PYG{n}{Add} \PYG{n}{a} \PYG{n}{principal} \PYG{n}{that} \PYG{n}{will} \PYG{n}{expire} \PYG{o+ow}{in} \PYG{l+m+mi}{30} \PYG{n}{minutes}\PYG{p}{:} + \PYG{n}{addprinc} \PYG{n}{test4} \PYG{o}{\PYGZhy{}}\PYG{n}{expire} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{30 minutes}\PYG{l+s+s2}{\PYGZdq{}} +\end{sphinxVerbatim} + + +\section{Absolute time} +\label{\detokenize{basic/date_format:absolute-time}}\label{\detokenize{basic/date_format:abstime}} +\sphinxAtStartPar +This rarely used date\sphinxhyphen{}time format can be noted in one of the +following ways: +\begin{quote} + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|T|} +\hline +\sphinxstyletheadfamily +\sphinxAtStartPar +Format +&\sphinxstyletheadfamily +\sphinxAtStartPar +Example +&\sphinxstyletheadfamily +\sphinxAtStartPar +Value +\\ +\hline +\sphinxAtStartPar +yyyymmddhhmmss +& +\sphinxAtStartPar +20141231235900 +&\sphinxmultirow{5}{6}{% +\begin{varwidth}[t]{\sphinxcolwidth{1}{3}} +\sphinxAtStartPar +One minute +before 2015 +\par +\vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% +}% +\\ +\cline{1-2} +\sphinxAtStartPar +yyyy.mm.dd.hh.mm.ss +& +\sphinxAtStartPar +2014.12.31.23.59.00 +&\sphinxtablestrut{6}\\ +\cline{1-2} +\sphinxAtStartPar +yymmddhhmmss +& +\sphinxAtStartPar +141231235900 +&\sphinxtablestrut{6}\\ +\cline{1-2} +\sphinxAtStartPar +yy.mm.dd.hh.mm.ss +& +\sphinxAtStartPar +14.12.31.23.59.00 +&\sphinxtablestrut{6}\\ +\cline{1-2} +\sphinxAtStartPar +dd\sphinxhyphen{}month\sphinxhyphen{}yyyy:hh:mm:ss +& +\sphinxAtStartPar +31\sphinxhyphen{}Dec\sphinxhyphen{}2014:23:59:00 +&\sphinxtablestrut{6}\\ +\hline +\sphinxAtStartPar +hh:mm:ss +& +\sphinxAtStartPar +20:00:00 +&\sphinxmultirow{2}{17}{% +\begin{varwidth}[t]{\sphinxcolwidth{1}{3}} +\sphinxAtStartPar +8 o’clock in +the evening +\par +\vskip-\baselineskip\vbox{\hbox{\strut}}\end{varwidth}% +}% +\\ +\cline{1-2} +\sphinxAtStartPar +hhmmss +& +\sphinxAtStartPar +200000 +&\sphinxtablestrut{17}\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} +\end{quote} + +\sphinxAtStartPar +(See {\hyperref[\detokenize{basic/date_format:abbreviation}]{\sphinxcrossref{\DUrole{std,std-ref}{Abbreviations used in this document}}}}.) + +\sphinxAtStartPar +Example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{Set} \PYG{n}{the} \PYG{n}{default} \PYG{n}{expiration} \PYG{n}{date} \PYG{n}{to} \PYG{n}{July} \PYG{l+m+mi}{27}\PYG{p}{,} \PYG{l+m+mi}{2012} \PYG{n}{at} \PYG{l+m+mi}{20}\PYG{p}{:}\PYG{l+m+mi}{30} +\PYG{n}{default\PYGZus{}principal\PYGZus{}expiration} \PYG{o}{=} \PYG{l+m+mi}{20120727203000} +\end{sphinxVerbatim} + + +\subsection{Abbreviations used in this document} +\label{\detokenize{basic/date_format:abbreviations-used-in-this-document}}\label{\detokenize{basic/date_format:abbreviation}} +\begin{DUlineblock}{0em} +\item[] \sphinxstyleemphasis{month} : locale’s month name or its abbreviation; +\item[] \sphinxstyleemphasis{dd} : day of month (01\sphinxhyphen{}31); +\item[] \sphinxstyleemphasis{HH} : hours (00\sphinxhyphen{}12); +\item[] \sphinxstyleemphasis{hh} : hours (00\sphinxhyphen{}23); +\item[] \sphinxstyleemphasis{mm} : in time \sphinxhyphen{} minutes (00\sphinxhyphen{}59); in date \sphinxhyphen{} month (01\sphinxhyphen{}12); +\item[] \sphinxstyleemphasis{N} : number; +\item[] \sphinxstyleemphasis{pp} : AM or PM; +\item[] \sphinxstyleemphasis{ss} : seconds (00\sphinxhyphen{}60); +\item[] \sphinxstyleemphasis{tt} : time units (hours, minutes, min, seconds, sec); +\item[] \sphinxstyleemphasis{yyyy} : year; +\item[] \sphinxstyleemphasis{yy} : last two digits of the year; +\item[] \sphinxstyleemphasis{Z} : alphabetic time zone abbreviation; +\item[] \sphinxstyleemphasis{z} : numeric time zone; +\end{DUlineblock} + +\begin{sphinxadmonition}{note}{Note:}\begin{itemize} +\item {} +\sphinxAtStartPar +If the date specification contains spaces, you may need to +enclose it in double quotes; + +\item {} +\sphinxAtStartPar +All keywords are case\sphinxhyphen{}insensitive. + +\end{itemize} +\end{sphinxadmonition} + + + +\renewcommand{\indexname}{Index} +\printindex +\end{document} \ No newline at end of file diff --git a/krb5-1.21.3/doc/pdf/build.pdf b/krb5-1.21.3/doc/pdf/build.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d3ae23d9e6894aff8f96f772b71f1915b935b9ae GIT binary patch literal 203594 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�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 z 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 0) { + print("mendex exited with error code $? (ignored)\n"); + } + if (!-e $destination) { + # create an empty .ind file if nothing + open(FH, ">" . $destination); + close(FH); + } + return 0; +} +add_cus_dep( "glo", "gls", 0, "makeglo" ); +sub makeglo { + return system( "mendex -J -f -s gglo.ist -o '$_[0].gls' '$_[0].glo'" ); +} \ No newline at end of file diff --git a/krb5-1.21.3/doc/pdf/latexmkrc b/krb5-1.21.3/doc/pdf/latexmkrc new file mode 100644 index 00000000..bba17fa6 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/latexmkrc @@ -0,0 +1,9 @@ +$latex = 'latex ' . $ENV{'LATEXOPTS'} . ' %O %S'; +$pdflatex = 'pdflatex ' . $ENV{'LATEXOPTS'} . ' %O %S'; +$lualatex = 'lualatex ' . $ENV{'LATEXOPTS'} . ' %O %S'; +$xelatex = 'xelatex --no-pdf ' . $ENV{'LATEXOPTS'} . ' %O %S'; +$makeindex = 'makeindex -s python.ist %O -o %D %S'; +add_cus_dep( "glo", "gls", 0, "makeglo" ); +sub makeglo { + return system( "makeindex -s gglo.ist -o '$_[0].gls' '$_[0].glo'" ); +} \ No newline at end of file diff --git a/krb5-1.21.3/doc/pdf/make.bat b/krb5-1.21.3/doc/pdf/make.bat new file mode 100644 index 00000000..94bda213 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/make.bat @@ -0,0 +1,31 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +pushd %~dp0 + +set PDFLATEX=latexmk -pdf -dvi- -ps- + +set "LATEXOPTS= " + +if "%1" == "" goto all-pdf + +if "%1" == "all-pdf" ( + :all-pdf + for %%i in (*.tex) do ( + %PDFLATEX% %LATEXMKOPTS% %%i + ) + goto end +) + +if "%1" == "all-pdf-ja" ( + goto all-pdf +) + +if "%1" == "clean" ( + del /q /s *.dvi *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ps *.tar *.tar.gz *.tar.bz2 *.tar.xz *.fls *.fdb_latexmk + goto end +) + +:end +popd \ No newline at end of file diff --git a/krb5-1.21.3/doc/pdf/plugindev.pdf b/krb5-1.21.3/doc/pdf/plugindev.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1715cb2eb793b6b1affa2204a059b697c0057fe5 GIT binary patch literal 199462 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�#N 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 b*}&1+{rmk6#lXSN!omtgLLwq33iW>gjajw0 literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/doc/pdf/plugindev.tex b/krb5-1.21.3/doc/pdf/plugindev.tex new file mode 100644 index 00000000..0bb2bc52 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/plugindev.tex @@ -0,0 +1,1020 @@ +%% Generated by Sphinx. +\def\sphinxdocclass{report} +\documentclass[letterpaper,10pt,english]{sphinxmanual} +\ifdefined\pdfpxdimen + \let\sphinxpxdimen\pdfpxdimen\else\newdimen\sphinxpxdimen +\fi \sphinxpxdimen=.75bp\relax +\ifdefined\pdfimageresolution + \pdfimageresolution= \numexpr \dimexpr1in\relax/\sphinxpxdimen\relax +\fi +%% let collapsible pdf bookmarks panel have high depth per default +\PassOptionsToPackage{bookmarksdepth=5}{hyperref} + +\PassOptionsToPackage{warn}{textcomp} +\usepackage[utf8]{inputenc} +\ifdefined\DeclareUnicodeCharacter +% support both utf8 and utf8x syntaxes + \ifdefined\DeclareUnicodeCharacterAsOptional + \def\sphinxDUC#1{\DeclareUnicodeCharacter{"#1}} + \else + \let\sphinxDUC\DeclareUnicodeCharacter + \fi + \sphinxDUC{00A0}{\nobreakspace} + \sphinxDUC{2500}{\sphinxunichar{2500}} + \sphinxDUC{2502}{\sphinxunichar{2502}} + \sphinxDUC{2514}{\sphinxunichar{2514}} + \sphinxDUC{251C}{\sphinxunichar{251C}} + \sphinxDUC{2572}{\textbackslash} +\fi +\usepackage{cmap} +\usepackage[T1]{fontenc} +\usepackage{amsmath,amssymb,amstext} +\usepackage{babel} + + + +\usepackage{tgtermes} +\usepackage{tgheros} +\renewcommand{\ttdefault}{txtt} + + + +\usepackage[Bjarne]{fncychap} +\usepackage{sphinx} + +\fvset{fontsize=auto} +\usepackage{geometry} + + +% Include hyperref last. +\usepackage{hyperref} +% Fix anchor placement for figures with captions. +\usepackage{hypcap}% it must be loaded after hyperref. +% Set up styles of URL: it should be placed after hyperref. +\urlstyle{same} + + +\usepackage{sphinxmessages} +\setcounter{tocdepth}{1} + + + +\title{Kerberos Plugin Module Developer Guide} +\date{ } +\release{1.21.3} +\author{MIT} +\newcommand{\sphinxlogo}{\vbox{}} +\renewcommand{\releasename}{Release} +\makeindex +\begin{document} + +\pagestyle{empty} +\sphinxmaketitle +\pagestyle{plain} +\sphinxtableofcontents +\pagestyle{normal} +\phantomsection\label{\detokenize{plugindev/index::doc}} + + +\sphinxAtStartPar +Kerberos plugin modules allow increased control over MIT krb5 library +and server behavior. This guide describes how to create dynamic +plugin modules and the currently available pluggable interfaces. + +\sphinxAtStartPar +See \DUrole{xref,std,std-ref}{plugin\_config} for information on how to register dynamic +plugin modules and how to enable and disable modules via +\DUrole{xref,std,std-ref}{krb5.conf(5)}. + + +\chapter{Contents} +\label{\detokenize{plugindev/index:contents}} + +\section{General plugin concepts} +\label{\detokenize{plugindev/general:general-plugin-concepts}}\label{\detokenize{plugindev/general::doc}} +\sphinxAtStartPar +A krb5 dynamic plugin module is a Unix shared object or Windows DLL. +Typically, the source code for a dynamic plugin module should live in +its own project with a build system using \sphinxhref{https://www.gnu.org/software/automake/}{automake} and \sphinxhref{https://www.gnu.org/software/libtool/}{libtool}, or +tools with similar functionality. + +\sphinxAtStartPar +A plugin module must define a specific symbol name, which depends on +the pluggable interface and module name. For most pluggable +interfaces, the exported symbol is a function named +\sphinxcode{\sphinxupquote{INTERFACE\_MODULE\_initvt}}, where \sphinxstyleemphasis{INTERFACE} is the name of the +pluggable interface and \sphinxstyleemphasis{MODULE} is the name of the module. For these +interfaces, it is possible for one shared object or DLL to implement +multiple plugin modules, either for the same pluggable interface or +for different ones. For example, a shared object could implement both +KDC and client preauthentication mechanisms, by exporting functions +named \sphinxcode{\sphinxupquote{kdcpreauth\_mymech\_initvt}} and \sphinxcode{\sphinxupquote{clpreauth\_mymech\_initvt}}. + +\sphinxAtStartPar +A plugin module implementation should include the header file +\sphinxcode{\sphinxupquote{\textless{}krb5/INTERFACE\_plugin.h\textgreater{}}}, where \sphinxstyleemphasis{INTERFACE} is the name of the +pluggable interface. For instance, a ccselect plugin module +implementation should use \sphinxcode{\sphinxupquote{\#include \textless{}krb5/ccselect\_plugin.h\textgreater{}}}. + +\sphinxAtStartPar +initvt functions have the following prototype: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{krb5\PYGZus{}error\PYGZus{}code} \PYG{n}{interface\PYGZus{}modname\PYGZus{}initvt}\PYG{p}{(}\PYG{n}{krb5\PYGZus{}context} \PYG{n}{context}\PYG{p}{,} + \PYG{n+nb}{int} \PYG{n}{maj\PYGZus{}ver}\PYG{p}{,} \PYG{n+nb}{int} \PYG{n}{min\PYGZus{}ver}\PYG{p}{,} + \PYG{n}{krb5\PYGZus{}plugin\PYGZus{}vtable} \PYG{n}{vtable}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +and should do the following: +\begin{enumerate} +\sphinxsetlistlabels{\arabic}{enumi}{enumii}{}{.}% +\item {} +\sphinxAtStartPar +Check that the supplied maj\_ver argument is supported by the +module. If it is not supported, the function should return +KRB5\_PLUGIN\_VER\_NOTSUPP. + +\item {} +\sphinxAtStartPar +Cast the supplied vtable pointer to the structure type +corresponding to the major version, as documented in the pluggable +interface header file. + +\item {} +\sphinxAtStartPar +Fill in the structure fields with pointers to method functions and +static data, stopping at the field indicated by the supplied minor +version. Fields for unimplemented optional methods can be left +alone; it is not necessary to initialize them to NULL. + +\end{enumerate} + +\sphinxAtStartPar +In most cases, the context argument will not be used. The initvt +function should not allocate memory; think of it as a glorified +structure initializer. Each pluggable interface defines methods for +allocating and freeing module state if doing so is necessary for the +interface. + +\sphinxAtStartPar +Pluggable interfaces typically include a \sphinxstylestrong{name} field in the vtable +structure, which should be filled in with a pointer to a string +literal containing the module name. + +\sphinxAtStartPar +Here is an example of what an initvt function might look like for a +fictional pluggable interface named fences, for a module named +“wicker”: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{krb5\PYGZus{}error\PYGZus{}code} +\PYG{n}{fences\PYGZus{}wicker\PYGZus{}initvt}\PYG{p}{(}\PYG{n}{krb5\PYGZus{}context} \PYG{n}{context}\PYG{p}{,} \PYG{n+nb}{int} \PYG{n}{maj\PYGZus{}ver}\PYG{p}{,} + \PYG{n+nb}{int} \PYG{n}{min\PYGZus{}ver}\PYG{p}{,} \PYG{n}{krb5\PYGZus{}plugin\PYGZus{}vtable} \PYG{n}{vtable}\PYG{p}{)} +\PYG{p}{\PYGZob{}} + \PYG{n}{krb5\PYGZus{}ccselect\PYGZus{}vtable} \PYG{n}{vt}\PYG{p}{;} + + \PYG{k}{if} \PYG{p}{(}\PYG{n}{maj\PYGZus{}ver} \PYG{o}{==} \PYG{l+m+mi}{1}\PYG{p}{)} \PYG{p}{\PYGZob{}} + \PYG{n}{krb5\PYGZus{}fences\PYGZus{}vtable} \PYG{n}{vt} \PYG{o}{=} \PYG{p}{(}\PYG{n}{krb5\PYGZus{}fences\PYGZus{}vtable}\PYG{p}{)}\PYG{n}{vtable}\PYG{p}{;} + \PYG{n}{vt}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZgt{}}\PYG{n}{name} \PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{wicker}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{;} + \PYG{n}{vt}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZgt{}}\PYG{n}{slats} \PYG{o}{=} \PYG{n}{wicker\PYGZus{}slats}\PYG{p}{;} + \PYG{n}{vt}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZgt{}}\PYG{n}{braces} \PYG{o}{=} \PYG{n}{wicker\PYGZus{}braces}\PYG{p}{;} + \PYG{p}{\PYGZcb{}} \PYG{k}{else} \PYG{k}{if} \PYG{p}{(}\PYG{n}{maj\PYGZus{}ver} \PYG{o}{==} \PYG{l+m+mi}{2}\PYG{p}{)} \PYG{p}{\PYGZob{}} + \PYG{n}{krb5\PYGZus{}fences\PYGZus{}vtable\PYGZus{}v2} \PYG{n}{vt} \PYG{o}{=} \PYG{p}{(}\PYG{n}{krb5\PYGZus{}fences\PYGZus{}vtable\PYGZus{}v2}\PYG{p}{)}\PYG{n}{vtable}\PYG{p}{;} + \PYG{n}{vt}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZgt{}}\PYG{n}{name} \PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{wicker}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{;} + \PYG{n}{vt}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZgt{}}\PYG{n}{material} \PYG{o}{=} \PYG{n}{wicker\PYGZus{}material}\PYG{p}{;} + \PYG{n}{vt}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZgt{}}\PYG{n}{construction} \PYG{o}{=} \PYG{n}{wicker\PYGZus{}construction}\PYG{p}{;} + \PYG{k}{if} \PYG{p}{(}\PYG{n}{min\PYGZus{}ver} \PYG{o}{\PYGZlt{}} \PYG{l+m+mi}{2}\PYG{p}{)} + \PYG{k}{return} \PYG{l+m+mi}{0}\PYG{p}{;} + \PYG{n}{vt}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZgt{}}\PYG{n}{footing} \PYG{o}{=} \PYG{n}{wicker\PYGZus{}footing}\PYG{p}{;} + \PYG{k}{if} \PYG{p}{(}\PYG{n}{min\PYGZus{}ver} \PYG{o}{\PYGZlt{}} \PYG{l+m+mi}{3}\PYG{p}{)} + \PYG{k}{return} \PYG{l+m+mi}{0}\PYG{p}{;} + \PYG{n}{vt}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZgt{}}\PYG{n}{appearance} \PYG{o}{=} \PYG{n}{wicker\PYGZus{}appearance}\PYG{p}{;} + \PYG{p}{\PYGZcb{}} \PYG{k}{else} \PYG{p}{\PYGZob{}} + \PYG{k}{return} \PYG{n}{KRB5\PYGZus{}PLUGIN\PYGZus{}VER\PYGZus{}NOTSUPP}\PYG{p}{;} + \PYG{p}{\PYGZcb{}} + \PYG{k}{return} \PYG{l+m+mi}{0}\PYG{p}{;} +\PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + + +\subsection{Logging from KDC and kadmind plugin modules} +\label{\detokenize{plugindev/general:logging-from-kdc-and-kadmind-plugin-modules}} +\sphinxAtStartPar +Plugin modules for the KDC or kadmind daemons can write to the +configured logging outputs (see \DUrole{xref,std,std-ref}{logging}) by calling the +\sphinxstylestrong{com\_err} function. The first argument (\sphinxstyleemphasis{whoami}) is ignored. If +the second argument (\sphinxstyleemphasis{code}) is zero, the formatted message is logged +at informational severity; otherwise, the formatted message is logged +at error severity and includes the error message for the supplied +code. Here are examples: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{com\PYGZus{}err}\PYG{p}{(}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{,} \PYG{l+m+mi}{0}\PYG{p}{,} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{Client message contains }\PYG{l+s+si}{\PYGZpc{}d}\PYG{l+s+s2}{ items}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{,} \PYG{n}{nitems}\PYG{p}{)}\PYG{p}{;} +\PYG{n}{com\PYGZus{}err}\PYG{p}{(}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{,} \PYG{n}{retval}\PYG{p}{,} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{while decoding client message}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +(The behavior described above is new in release 1.17. In prior +releases, the \sphinxstyleemphasis{whoami} argument is included for some logging output +types, the logged message does not include the usual header for some +output types, and the severity for syslog outputs is configured as +part of the logging specification, defaulting to error severity.) + + +\section{Client preauthentication interface (clpreauth)} +\label{\detokenize{plugindev/clpreauth:client-preauthentication-interface-clpreauth}}\label{\detokenize{plugindev/clpreauth::doc}} +\sphinxAtStartPar +During an initial ticket request, a KDC may ask a client to prove its +knowledge of the password before issuing an encrypted ticket, or to +use credentials other than a password. This process is called +preauthentication, and is described in \index{RFC@\spxentry{RFC}!RFC 4120@\spxentry{RFC 4120}}\sphinxhref{https://tools.ietf.org/html/rfc4120.html}{\sphinxstylestrong{RFC 4120}} and \index{RFC@\spxentry{RFC}!RFC 6113@\spxentry{RFC 6113}}\sphinxhref{https://tools.ietf.org/html/rfc6113.html}{\sphinxstylestrong{RFC 6113}}. +The clpreauth interface allows the addition of client support for +preauthentication mechanisms beyond those included in the core MIT +krb5 code base. For a detailed description of the clpreauth +interface, see the header file \sphinxcode{\sphinxupquote{\textless{}krb5/clpreauth\_plugin.h\textgreater{}}} (or +\sphinxcode{\sphinxupquote{\textless{}krb5/preauth\_plugin.h\textgreater{}}} before release 1.12). + +\sphinxAtStartPar +A clpreauth module is generally responsible for: +\begin{itemize} +\item {} +\sphinxAtStartPar +Supplying a list of preauth type numbers used by the module in the +\sphinxstylestrong{pa\_type\_list} field of the vtable structure. + +\item {} +\sphinxAtStartPar +Indicating what kind of preauthentication mechanism it implements, +with the \sphinxstylestrong{flags} method. In the most common case, this method +just returns \sphinxcode{\sphinxupquote{PA\_REAL}}, indicating that it implements a normal +preauthentication type. + +\item {} +\sphinxAtStartPar +Examining the padata information included in a PREAUTH\_REQUIRED or +MORE\_PREAUTH\_DATA\_REQUIRED error and producing padata values for the +next AS request. This is done with the \sphinxstylestrong{process} method. + +\item {} +\sphinxAtStartPar +Examining the padata information included in a successful ticket +reply, possibly verifying the KDC identity and computing a reply +key. This is also done with the \sphinxstylestrong{process} method. + +\item {} +\sphinxAtStartPar +For preauthentication types which support it, recovering from errors +by examining the error data from the KDC and producing a padata +value for another AS request. This is done with the \sphinxstylestrong{tryagain} +method. + +\item {} +\sphinxAtStartPar +Receiving option information (supplied by \sphinxcode{\sphinxupquote{kinit \sphinxhyphen{}X}} or by an +application), with the \sphinxstylestrong{gic\_opts} method. + +\end{itemize} + +\sphinxAtStartPar +A clpreauth module can create and destroy per\sphinxhyphen{}library\sphinxhyphen{}context and +per\sphinxhyphen{}request state objects by implementing the \sphinxstylestrong{init}, \sphinxstylestrong{fini}, +\sphinxstylestrong{request\_init}, and \sphinxstylestrong{request\_fini} methods. Per\sphinxhyphen{}context state +objects have the type krb5\_clpreauth\_moddata, and per\sphinxhyphen{}request state +objects have the type krb5\_clpreauth\_modreq. These are abstract +pointer types; a module should typically cast these to internal +types for the state objects. + +\sphinxAtStartPar +The \sphinxstylestrong{process} and \sphinxstylestrong{tryagain} methods have access to a callback +function and handle (called a “rock”) which can be used to get +additional information about the current request, including the +expected enctype of the AS reply, the FAST armor key, and the client +long\sphinxhyphen{}term key (prompting for the user password if necessary). A +callback can also be used to replace the AS reply key if the +preauthentication mechanism computes one. + + +\section{KDC preauthentication interface (kdcpreauth)} +\label{\detokenize{plugindev/kdcpreauth:kdc-preauthentication-interface-kdcpreauth}}\label{\detokenize{plugindev/kdcpreauth::doc}} +\sphinxAtStartPar +The kdcpreauth interface allows the addition of KDC support for +preauthentication mechanisms beyond those included in the core MIT +krb5 code base. For a detailed description of the kdcpreauth +interface, see the header file \sphinxcode{\sphinxupquote{\textless{}krb5/kdcpreauth\_plugin.h\textgreater{}}} (or +\sphinxcode{\sphinxupquote{\textless{}krb5/preauth\_plugin.h\textgreater{}}} before release 1.12). + +\sphinxAtStartPar +A kdcpreauth module is generally responsible for: +\begin{itemize} +\item {} +\sphinxAtStartPar +Supplying a list of preauth type numbers used by the module in the +\sphinxstylestrong{pa\_type\_list} field of the vtable structure. + +\item {} +\sphinxAtStartPar +Indicating what kind of preauthentication mechanism it implements, +with the \sphinxstylestrong{flags} method. If the mechanism computes a new reply +key, it must specify the \sphinxcode{\sphinxupquote{PA\_REPLACES\_KEY}} flag. If the mechanism +is generally only used with hardware tokens, the \sphinxcode{\sphinxupquote{PA\_HARDWARE}} +flag allows the mechanism to work with principals which have the +\sphinxstylestrong{requires\_hwauth} flag set. + +\item {} +\sphinxAtStartPar +Producing a padata value to be sent with a preauth\_required error, +with the \sphinxstylestrong{edata} method. + +\item {} +\sphinxAtStartPar +Examining a padata value sent by a client and verifying that it +proves knowledge of the appropriate client credential information. +This is done with the \sphinxstylestrong{verify} method. + +\item {} +\sphinxAtStartPar +Producing a padata response value for the client, and possibly +computing a reply key. This is done with the \sphinxstylestrong{return\_padata} +method. + +\end{itemize} + +\sphinxAtStartPar +A module can create and destroy per\sphinxhyphen{}KDC state objects by implementing +the \sphinxstylestrong{init} and \sphinxstylestrong{fini} methods. Per\sphinxhyphen{}KDC state objects have the +type krb5\_kdcpreauth\_moddata, which is an abstract pointer types. A +module should typically cast this to an internal type for the state +object. + +\sphinxAtStartPar +A module can create a per\sphinxhyphen{}request state object by returning one in the +\sphinxstylestrong{verify} method, receiving it in the \sphinxstylestrong{return\_padata} method, and +destroying it in the \sphinxstylestrong{free\_modreq} method. Note that these state +objects only apply to the processing of a single AS request packet, +not to an entire authentication exchange (since an authentication +exchange may remain unfinished by the client or may involve multiple +different KDC hosts). Per\sphinxhyphen{}request state objects have the type +krb5\_kdcpreauth\_modreq, which is an abstract pointer type. + +\sphinxAtStartPar +The \sphinxstylestrong{edata}, \sphinxstylestrong{verify}, and \sphinxstylestrong{return\_padata} methods have access +to a callback function and handle (called a “rock”) which can be used +to get additional information about the current request, including the +maximum allowable clock skew, the client’s long\sphinxhyphen{}term keys, the +DER\sphinxhyphen{}encoded request body, the FAST armor key, string attributes on the +client’s database entry, and the client’s database entry itself. The +\sphinxstylestrong{verify} method can assert one or more authentication indicators to +be included in the issued ticket using the \sphinxcode{\sphinxupquote{add\_auth\_indicator}} +callback (new in release 1.14). + +\sphinxAtStartPar +A module can generate state information to be included with the next +client request using the \sphinxcode{\sphinxupquote{set\_cookie}} callback (new in release +1.14). On the next request, the module can read this state +information using the \sphinxcode{\sphinxupquote{get\_cookie}} callback. Cookie information is +encrypted, timestamped, and transmitted to the client in a +\sphinxcode{\sphinxupquote{PA\sphinxhyphen{}FX\sphinxhyphen{}COOKIE}} pa\sphinxhyphen{}data item. Older clients may not support cookies +and therefore may not transmit the cookie in the next request; in this +case, \sphinxcode{\sphinxupquote{get\_cookie}} will not yield the saved information. + +\sphinxAtStartPar +If a module implements a mechanism which requires multiple round +trips, its \sphinxstylestrong{verify} method can respond with the code +\sphinxcode{\sphinxupquote{KRB5KDC\_ERR\_MORE\_PREAUTH\_DATA\_REQUIRED}} and a list of pa\sphinxhyphen{}data in +the \sphinxstyleemphasis{e\_data} parameter to be processed by the client. + +\sphinxAtStartPar +The \sphinxstylestrong{edata} and \sphinxstylestrong{verify} methods can be implemented +asynchronously. Because of this, they do not return values directly +to the caller, but must instead invoke responder functions with their +results. A synchronous implementation can invoke the responder +function immediately. An asynchronous implementation can use the +callback to get an event context for use with the \sphinxhref{https://fedorahosted.org/libverto/}{libverto} API. + + +\section{Credential cache selection interface (ccselect)} +\label{\detokenize{plugindev/ccselect:credential-cache-selection-interface-ccselect}}\label{\detokenize{plugindev/ccselect:ccselect-plugin}}\label{\detokenize{plugindev/ccselect::doc}} +\sphinxAtStartPar +The ccselect interface allows modules to control how credential caches +are chosen when a GSSAPI client contacts a service. For a detailed +description of the ccselect interface, see the header file +\sphinxcode{\sphinxupquote{\textless{}krb5/ccselect\_plugin.h\textgreater{}}}. + +\sphinxAtStartPar +The primary ccselect method is \sphinxstylestrong{choose}, which accepts a server +principal as input and returns a ccache and/or principal name as +output. A module can use the krb5\_cccol APIs to iterate over the +cache collection in order to find an appropriate ccache to use. + +\sphinxAtStartPar +A module can create and destroy per\sphinxhyphen{}library\sphinxhyphen{}context state objects by +implementing the \sphinxstylestrong{init} and \sphinxstylestrong{fini} methods. State objects have +the type krb5\_ccselect\_moddata, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object. + +\sphinxAtStartPar +A module can have one of two priorities, “authoritative” or +“heuristic”. Results from authoritative modules, if any are +available, will take priority over results from heuristic modules. A +module communicates its priority as a result of the \sphinxstylestrong{init} method. + + +\section{Password quality interface (pwqual)} +\label{\detokenize{plugindev/pwqual:password-quality-interface-pwqual}}\label{\detokenize{plugindev/pwqual:pwqual-plugin}}\label{\detokenize{plugindev/pwqual::doc}} +\sphinxAtStartPar +The pwqual interface allows modules to control what passwords are +allowed when a user changes passwords. For a detailed description of +the pwqual interface, see the header file \sphinxcode{\sphinxupquote{\textless{}krb5/pwqual\_plugin.h\textgreater{}}}. + +\sphinxAtStartPar +The primary pwqual method is \sphinxstylestrong{check}, which receives a password as +input and returns success (0) or a \sphinxcode{\sphinxupquote{KADM5\_PASS\_Q\_}} failure code +depending on whether the password is allowed. The \sphinxstylestrong{check} method +also receives the principal name and the name of the principal’s +password policy as input; although there is no stable interface for +the module to obtain the fields of the password policy, it can define +its own configuration or data store based on the policy name. + +\sphinxAtStartPar +A module can create and destroy per\sphinxhyphen{}process state objects by +implementing the \sphinxstylestrong{open} and \sphinxstylestrong{close} methods. State objects have +the type krb5\_pwqual\_moddata, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object. The \sphinxstylestrong{open} method also receives the name of the realm’s +dictionary file (as configured by the \sphinxstylestrong{dict\_file} variable in the +\DUrole{xref,std,std-ref}{kdc\_realms} section of \DUrole{xref,std,std-ref}{kdc.conf(5)}) if it wishes to use +it. + + +\section{KADM5 hook interface (kadm5\_hook)} +\label{\detokenize{plugindev/kadm5_hook:kadm5-hook-interface-kadm5-hook}}\label{\detokenize{plugindev/kadm5_hook:kadm5-hook-plugin}}\label{\detokenize{plugindev/kadm5_hook::doc}} +\sphinxAtStartPar +The kadm5\_hook interface allows modules to perform actions when +changes are made to the Kerberos database through \DUrole{xref,std,std-ref}{kadmin(1)}. +For a detailed description of the kadm5\_hook interface, see the header +file \sphinxcode{\sphinxupquote{\textless{}krb5/kadm5\_hook\_plugin.h\textgreater{}}}. + +\sphinxAtStartPar +The kadm5\_hook interface has five primary methods: \sphinxstylestrong{chpass}, +\sphinxstylestrong{create}, \sphinxstylestrong{modify}, \sphinxstylestrong{remove}, and \sphinxstylestrong{rename}. (The \sphinxstylestrong{rename} +method was introduced in release 1.14.) Each of these methods is +called twice when the corresponding administrative action takes place, +once before the action is committed and once afterwards. A module can +prevent the action from taking place by returning an error code during +the pre\sphinxhyphen{}commit stage. + +\sphinxAtStartPar +A module can create and destroy per\sphinxhyphen{}process state objects by +implementing the \sphinxstylestrong{init} and \sphinxstylestrong{fini} methods. State objects have +the type kadm5\_hook\_modinfo, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object. + +\sphinxAtStartPar +Because the kadm5\_hook interface is tied closely to the kadmin +interface (which is explicitly unstable), it may not remain as stable +across versions as other public pluggable interfaces. + + +\section{kadmin authorization interface (kadm5\_auth)} +\label{\detokenize{plugindev/kadm5_auth:kadmin-authorization-interface-kadm5-auth}}\label{\detokenize{plugindev/kadm5_auth:kadm5-auth-plugin}}\label{\detokenize{plugindev/kadm5_auth::doc}} +\sphinxAtStartPar +The kadm5\_auth interface (new in release 1.16) allows modules to +determine whether a client principal is authorized to perform an +operation in the kadmin protocol, and to apply restrictions to +principal operations. For a detailed description of the kadm5\_auth +interface, see the header file \sphinxcode{\sphinxupquote{\textless{}krb5/kadm5\_auth\_plugin.h\textgreater{}}}. + +\sphinxAtStartPar +A module can create and destroy per\sphinxhyphen{}process state objects by +implementing the \sphinxstylestrong{init} and \sphinxstylestrong{fini} methods. State objects have +the type kadm5\_auth\_modinfo, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object. + +\sphinxAtStartPar +The kadm5\_auth interface has one method for each kadmin operation, +with parameters specific to the operation. Each method can return +either 0 to authorize access, KRB5\_PLUGIN\_NO\_HANDLE to defer the +decision to other modules, or another error (canonically EPERM) to +authoritatively deny access. Access is granted if at least one module +grants access and no module authoritatively denies access. + +\sphinxAtStartPar +The \sphinxstylestrong{addprinc} and \sphinxstylestrong{modprinc} methods can also impose restrictions +on the principal operation by returning a \sphinxcode{\sphinxupquote{struct +kadm5\_auth\_restrictions}} object. The module should also implement +the \sphinxstylestrong{free\_restrictions} method if it dynamically allocates +restrictions objects for principal operations. + +\sphinxAtStartPar +kadm5\_auth modules can optionally inspect principal or policy objects. +To do this, the module must also include \sphinxcode{\sphinxupquote{\textless{}kadm5/admin.h\textgreater{}}} to gain +access to the structure definitions for those objects. As the kadmin +interface is explicitly not as stable as other public interfaces, +modules which do this may not retain compatibility across releases. + + +\section{Host\sphinxhyphen{}to\sphinxhyphen{}realm interface (hostrealm)} +\label{\detokenize{plugindev/hostrealm:host-to-realm-interface-hostrealm}}\label{\detokenize{plugindev/hostrealm:hostrealm-plugin}}\label{\detokenize{plugindev/hostrealm::doc}} +\sphinxAtStartPar +The host\sphinxhyphen{}to\sphinxhyphen{}realm interface was first introduced in release 1.12. It +allows modules to control the local mapping of hostnames to realm +names as well as the default realm. For a detailed description of the +hostrealm interface, see the header file +\sphinxcode{\sphinxupquote{\textless{}krb5/hostrealm\_plugin.h\textgreater{}}}. + +\sphinxAtStartPar +Although the mapping methods in the hostrealm interface return a list +of one or more realms, only the first realm in the list is currently +used by callers. Callers may begin using later responses in the +future. + +\sphinxAtStartPar +Any mapping method may return KRB5\_PLUGIN\_NO\_HANDLE to defer +processing to a later module. + +\sphinxAtStartPar +A module can create and destroy per\sphinxhyphen{}library\sphinxhyphen{}context state objects +using the \sphinxstylestrong{init} and \sphinxstylestrong{fini} methods. If the module does not need +any state, it does not need to implement these methods. + +\sphinxAtStartPar +The optional \sphinxstylestrong{host\_realm} method allows a module to determine +authoritative realm mappings for a hostname. The first authoritative +mapping is used in preference to KDC referrals when getting service +credentials. + +\sphinxAtStartPar +The optional \sphinxstylestrong{fallback\_realm} method allows a module to determine +fallback mappings for a hostname. The first fallback mapping is tried +if there is no authoritative mapping for a realm, and KDC referrals +failed to produce a successful result. + +\sphinxAtStartPar +The optional \sphinxstylestrong{default\_realm} method allows a module to determine the +local default realm. + +\sphinxAtStartPar +If a module implements any of the above methods, it must also +implement \sphinxstylestrong{free\_list} to ensure that memory is allocated and +deallocated consistently. + + +\section{Local authorization interface (localauth)} +\label{\detokenize{plugindev/localauth:local-authorization-interface-localauth}}\label{\detokenize{plugindev/localauth:localauth-plugin}}\label{\detokenize{plugindev/localauth::doc}} +\sphinxAtStartPar +The localauth interface was first introduced in release 1.12. It +allows modules to control the relationship between Kerberos principals +and local system accounts. When an application calls +\sphinxcode{\sphinxupquote{krb5\_kuserok()}} or \sphinxcode{\sphinxupquote{krb5\_aname\_to\_localname()}}, localauth +modules are consulted to determine the result. For a detailed +description of the localauth interface, see the header file +\sphinxcode{\sphinxupquote{\textless{}krb5/localauth\_plugin.h\textgreater{}}}. + +\sphinxAtStartPar +A module can create and destroy per\sphinxhyphen{}library\sphinxhyphen{}context state objects +using the \sphinxstylestrong{init} and \sphinxstylestrong{fini} methods. If the module does not need +any state, it does not need to implement these methods. + +\sphinxAtStartPar +The optional \sphinxstylestrong{userok} method allows a module to control the behavior +of \sphinxcode{\sphinxupquote{krb5\_kuserok()}}. The module receives the authenticated name +and the local account name as inputs, and can return either 0 to +authorize access, KRB5\_PLUGIN\_NO\_HANDLE to defer the decision to other +modules, or another error (canonically EPERM) to authoritatively deny +access. Access is granted if at least one module grants access and no +module authoritatively denies access. + +\sphinxAtStartPar +The optional \sphinxstylestrong{an2ln} method can work in two different ways. If the +module sets an array of uppercase type names in \sphinxstylestrong{an2ln\_types}, then +the module’s \sphinxstylestrong{an2ln} method will only be invoked by +\sphinxcode{\sphinxupquote{krb5\_aname\_to\_localname()}} if an \sphinxstylestrong{auth\_to\_local} value in +\DUrole{xref,std,std-ref}{krb5.conf(5)} refers to one of the module’s types. In this +case, the \sphinxstyleemphasis{type} and \sphinxstyleemphasis{residual} arguments will give the type name and +residual string of the \sphinxstylestrong{auth\_to\_local} value. + +\sphinxAtStartPar +If the module does not set \sphinxstylestrong{an2ln\_types} but does implement +\sphinxstylestrong{an2ln}, the module’s \sphinxstylestrong{an2ln} method will be invoked for all +\sphinxcode{\sphinxupquote{krb5\_aname\_to\_localname()}} operations unless an earlier module +determines a mapping, with \sphinxstyleemphasis{type} and \sphinxstyleemphasis{residual} set to NULL. The +module can return KRB5\_LNAME\_NO\_TRANS to defer mapping to later +modules. + +\sphinxAtStartPar +If a module implements \sphinxstylestrong{an2ln}, it must also implement +\sphinxstylestrong{free\_string} to ensure that memory is allocated and deallocated +consistently. + + +\section{Server location interface (locate)} +\label{\detokenize{plugindev/locate:server-location-interface-locate}}\label{\detokenize{plugindev/locate::doc}} +\sphinxAtStartPar +The locate interface allows modules to control how KDCs and similar +services are located by clients. For a detailed description of the +ccselect interface, see the header file \sphinxcode{\sphinxupquote{\textless{}krb5/locate\_plugin.h\textgreater{}}}. + +\sphinxAtStartPar +A locate module exports a structure object of type +krb5plugin\_service\_locate\_ftable, with the name \sphinxcode{\sphinxupquote{service\_locator}}. +The structure contains a minor version and pointers to the module’s +methods. + +\sphinxAtStartPar +The primary locate method is \sphinxstylestrong{lookup}, which accepts a service type, +realm name, desired socket type, and desired address family (which +will be AF\_UNSPEC if no specific address family is desired). The +method should invoke the callback function once for each server +address it wants to return, passing a socket type (SOCK\_STREAM for TCP +or SOCK\_DGRAM for UDP) and socket address. The \sphinxstylestrong{lookup} method +should return 0 if it has authoritatively determined the server +addresses for the realm, KRB5\_PLUGIN\_NO\_HANDLE if it wants to let +other location mechanisms determine the server addresses, or another +code if it experienced a failure which should abort the location +process. + +\sphinxAtStartPar +A module can create and destroy per\sphinxhyphen{}library\sphinxhyphen{}context state objects by +implementing the \sphinxstylestrong{init} and \sphinxstylestrong{fini} methods. State objects have +the type void *, and should be cast to an internal type for the state +object. + + +\section{Configuration interface (profile)} +\label{\detokenize{plugindev/profile:configuration-interface-profile}}\label{\detokenize{plugindev/profile:profile-plugin}}\label{\detokenize{plugindev/profile::doc}} +\sphinxAtStartPar +The profile interface allows a module to control how krb5 +configuration information is obtained by the Kerberos library and +applications. For a detailed description of the profile interface, +see the header file \sphinxcode{\sphinxupquote{\textless{}profile.h\textgreater{}}}. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The profile interface does not follow the normal conventions +for MIT krb5 pluggable interfaces, because it is part of a +lower\sphinxhyphen{}level component of the krb5 library. +\end{sphinxadmonition} + +\sphinxAtStartPar +As with other types of plugin modules, a profile module is a Unix +shared object or Windows DLL, built separately from the krb5 tree. +The krb5 library will dynamically load and use a profile plugin module +if it reads a \sphinxcode{\sphinxupquote{module}} directive at the beginning of krb5.conf, as +described in \DUrole{xref,std,std-ref}{profile\_plugin\_config}. + +\sphinxAtStartPar +A profile module exports a function named \sphinxcode{\sphinxupquote{profile\_module\_init}} +matching the signature of the profile\_module\_init\_fn type. This +function accepts a residual string, which may be used to help locate +the configuration source. The function fills in a vtable and may also +create a per\sphinxhyphen{}profile state object. If the module uses state objects, +it should implement the \sphinxstylestrong{copy} and \sphinxstylestrong{cleanup} methods to manage +them. + +\sphinxAtStartPar +A basic read\sphinxhyphen{}only profile module need only implement the +\sphinxstylestrong{get\_values} and \sphinxstylestrong{free\_values} methods. The \sphinxstylestrong{get\_values} method +accepts a null\sphinxhyphen{}terminated list of C string names (e.g., an array +containing “libdefaults”, “clockskew”, and NULL for the \sphinxstylestrong{clockskew} +variable in the \DUrole{xref,std,std-ref}{libdefaults} section) and returns a +null\sphinxhyphen{}terminated list of values, which will be cleaned up with the +\sphinxstylestrong{free\_values} method when the caller is done with them. + +\sphinxAtStartPar +Iterable profile modules must also define the \sphinxstylestrong{iterator\_create}, +\sphinxstylestrong{iterator}, \sphinxstylestrong{iterator\_free}, and \sphinxstylestrong{free\_string} methods. The +core krb5 code does not require profiles to be iterable, but some +applications may iterate over the krb5 profile object in order to +present configuration interfaces. + +\sphinxAtStartPar +Writable profile modules must also define the \sphinxstylestrong{writable}, +\sphinxstylestrong{modified}, \sphinxstylestrong{update\_relation}, \sphinxstylestrong{rename\_section}, +\sphinxstylestrong{add\_relation}, and \sphinxstylestrong{flush} methods. The core krb5 code does not +require profiles to be writable, but some applications may write to +the krb5 profile in order to present configuration interfaces. + +\sphinxAtStartPar +The following is an example of a very basic read\sphinxhyphen{}only profile module +which returns a hardcoded value for the \sphinxstylestrong{default\_realm} variable in +\DUrole{xref,std,std-ref}{libdefaults}, and provides no other configuration information. +(For conciseness, the example omits code for checking the return +values of malloc and strdup.) + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{c+c1}{\PYGZsh{}include \PYGZlt{}stdlib.h\PYGZgt{}} +\PYG{c+c1}{\PYGZsh{}include \PYGZlt{}string.h\PYGZgt{}} +\PYG{c+c1}{\PYGZsh{}include \PYGZlt{}profile.h\PYGZgt{}} + +\PYG{n}{static} \PYG{n}{long} +\PYG{n}{get\PYGZus{}values}\PYG{p}{(}\PYG{n}{void} \PYG{o}{*}\PYG{n}{cbdata}\PYG{p}{,} \PYG{n}{const} \PYG{n}{char} \PYG{o}{*}\PYG{n}{const} \PYG{o}{*}\PYG{n}{names}\PYG{p}{,} \PYG{n}{char} \PYG{o}{*}\PYG{o}{*}\PYG{o}{*}\PYG{n}{values}\PYG{p}{)} +\PYG{p}{\PYGZob{}} + \PYG{k}{if} \PYG{p}{(}\PYG{n}{names}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]} \PYG{o}{!=} \PYG{n}{NULL} \PYG{o}{\PYGZam{}}\PYG{o}{\PYGZam{}} \PYG{n}{strcmp}\PYG{p}{(}\PYG{n}{names}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{p}{,} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{libdefaults}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{)} \PYG{o}{==} \PYG{l+m+mi}{0} \PYG{o}{\PYGZam{}}\PYG{o}{\PYGZam{}} + \PYG{n}{names}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]} \PYG{o}{!=} \PYG{n}{NULL} \PYG{o}{\PYGZam{}}\PYG{o}{\PYGZam{}} \PYG{n}{strcmp}\PYG{p}{(}\PYG{n}{names}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{p}{,} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{default\PYGZus{}realm}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{)} \PYG{o}{==} \PYG{l+m+mi}{0}\PYG{p}{)} \PYG{p}{\PYGZob{}} + \PYG{o}{*}\PYG{n}{values} \PYG{o}{=} \PYG{n}{malloc}\PYG{p}{(}\PYG{l+m+mi}{2} \PYG{o}{*} \PYG{n}{sizeof}\PYG{p}{(}\PYG{n}{char} \PYG{o}{*}\PYG{p}{)}\PYG{p}{)}\PYG{p}{;} + \PYG{p}{(}\PYG{o}{*}\PYG{n}{values}\PYG{p}{)}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]} \PYG{o}{=} \PYG{n}{strdup}\PYG{p}{(}\PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{ATHENA.MIT.EDU}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{)}\PYG{p}{;} + \PYG{p}{(}\PYG{o}{*}\PYG{n}{values}\PYG{p}{)}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]} \PYG{o}{=} \PYG{n}{NULL}\PYG{p}{;} + \PYG{k}{return} \PYG{l+m+mi}{0}\PYG{p}{;} + \PYG{p}{\PYGZcb{}} + \PYG{k}{return} \PYG{n}{PROF\PYGZus{}NO\PYGZus{}RELATION}\PYG{p}{;} +\PYG{p}{\PYGZcb{}} + +\PYG{n}{static} \PYG{n}{void} +\PYG{n}{free\PYGZus{}values}\PYG{p}{(}\PYG{n}{void} \PYG{o}{*}\PYG{n}{cbdata}\PYG{p}{,} \PYG{n}{char} \PYG{o}{*}\PYG{o}{*}\PYG{n}{values}\PYG{p}{)} +\PYG{p}{\PYGZob{}} + \PYG{n}{char} \PYG{o}{*}\PYG{o}{*}\PYG{n}{v}\PYG{p}{;} + + \PYG{k}{for} \PYG{p}{(}\PYG{n}{v} \PYG{o}{=} \PYG{n}{values}\PYG{p}{;} \PYG{o}{*}\PYG{n}{v}\PYG{p}{;} \PYG{n}{v}\PYG{o}{+}\PYG{o}{+}\PYG{p}{)} + \PYG{n}{free}\PYG{p}{(}\PYG{o}{*}\PYG{n}{v}\PYG{p}{)}\PYG{p}{;} + \PYG{n}{free}\PYG{p}{(}\PYG{n}{values}\PYG{p}{)}\PYG{p}{;} +\PYG{p}{\PYGZcb{}} + +\PYG{n}{long} +\PYG{n}{profile\PYGZus{}module\PYGZus{}init}\PYG{p}{(}\PYG{n}{const} \PYG{n}{char} \PYG{o}{*}\PYG{n}{residual}\PYG{p}{,} \PYG{n}{struct} \PYG{n}{profile\PYGZus{}vtable} \PYG{o}{*}\PYG{n}{vtable}\PYG{p}{,} + \PYG{n}{void} \PYG{o}{*}\PYG{o}{*}\PYG{n}{cb\PYGZus{}ret}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{long} +\PYG{n}{profile\PYGZus{}module\PYGZus{}init}\PYG{p}{(}\PYG{n}{const} \PYG{n}{char} \PYG{o}{*}\PYG{n}{residual}\PYG{p}{,} \PYG{n}{struct} \PYG{n}{profile\PYGZus{}vtable} \PYG{o}{*}\PYG{n}{vtable}\PYG{p}{,} + \PYG{n}{void} \PYG{o}{*}\PYG{o}{*}\PYG{n}{cb\PYGZus{}ret}\PYG{p}{)} +\PYG{p}{\PYGZob{}} + \PYG{o}{*}\PYG{n}{cb\PYGZus{}ret} \PYG{o}{=} \PYG{n}{NULL}\PYG{p}{;} + \PYG{n}{vtable}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZgt{}}\PYG{n}{get\PYGZus{}values} \PYG{o}{=} \PYG{n}{get\PYGZus{}values}\PYG{p}{;} + \PYG{n}{vtable}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZgt{}}\PYG{n}{free\PYGZus{}values} \PYG{o}{=} \PYG{n}{free\PYGZus{}values}\PYG{p}{;} + \PYG{k}{return} \PYG{l+m+mi}{0}\PYG{p}{;} +\PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + + +\section{GSSAPI mechanism interface} +\label{\detokenize{plugindev/gssapi:gssapi-mechanism-interface}}\label{\detokenize{plugindev/gssapi::doc}} +\sphinxAtStartPar +The GSSAPI library in MIT krb5 can load mechanism modules to augment +the set of built\sphinxhyphen{}in mechanisms. + +\sphinxAtStartPar +A mechanism module is a Unix shared object or Windows DLL, built +separately from the krb5 tree. Modules are loaded according to the +GSS mechanism config files described in \DUrole{xref,std,std-ref}{gssapi\_plugin\_config}. + +\sphinxAtStartPar +For the most part, a GSSAPI mechanism module exports the same +functions as would a GSSAPI implementation itself, with the same +function signatures. The mechanism selection layer within the GSSAPI +library (called the “mechglue”) will dispatch calls from the +application to the module if the module’s mechanism is requested. If +a module does not wish to implement a GSSAPI extension, it can simply +refrain from exporting it, and the mechglue will fail gracefully if +the application calls that function. + +\sphinxAtStartPar +The mechglue does not invoke a module’s \sphinxstylestrong{gss\_add\_cred}, +\sphinxstylestrong{gss\_add\_cred\_from}, \sphinxstylestrong{gss\_add\_cred\_impersonate\_name}, or +\sphinxstylestrong{gss\_add\_cred\_with\_password} function. A mechanism only needs to +implement the “acquire” variants of those functions. + +\sphinxAtStartPar +A module does not need to coordinate its minor status codes with those +of other mechanisms. If the mechglue detects conflicts, it will map +the mechanism’s status codes onto unique values, and then map them +back again when \sphinxstylestrong{gss\_display\_status} is called. + + +\subsection{NegoEx modules} +\label{\detokenize{plugindev/gssapi:negoex-modules}} +\sphinxAtStartPar +Some Windows GSSAPI mechanisms can only be negotiated via a Microsoft +extension to SPNEGO called NegoEx. Beginning with release 1.18, +mechanism modules can support NegoEx as follows: +\begin{itemize} +\item {} +\sphinxAtStartPar +Implement the gssspi\_query\_meta\_data(), gssspi\_exchange\_meta\_data(), +and gssspi\_query\_mechanism\_info() SPIs declared in +\sphinxcode{\sphinxupquote{\textless{}gssapi/gssapi\_ext.h\textgreater{}}}. + +\item {} +\sphinxAtStartPar +Implement gss\_inquire\_sec\_context\_by\_oid() and answer the +\sphinxstylestrong{GSS\_C\_INQ\_NEGOEX\_KEY} and \sphinxstylestrong{GSS\_C\_INQ\_NEGOEX\_VERIFY\_KEY} OIDs +to provide the checksum keys for outgoing and incoming checksums, +respectively. The answer must be in two buffers: the first buffer +contains the key contents, and the second buffer contains the key +encryption type as a four\sphinxhyphen{}byte little\sphinxhyphen{}endian integer. + +\end{itemize} + +\sphinxAtStartPar +By default, NegoEx mechanisms will not be directly negotiated via +SPNEGO. If direct SPNEGO negotiation is required for +interoperability, implement gss\_inquire\_attrs\_for\_mech() and assert +the GSS\_C\_MA\_NEGOEX\_AND\_SPNEGO attribute (along with any applicable +RFC 5587 attributes). + + +\subsection{Interposer modules} +\label{\detokenize{plugindev/gssapi:interposer-modules}} +\sphinxAtStartPar +The mechglue also supports a kind of loadable module, called an +interposer module, which intercepts calls to existing mechanisms +rather than implementing a new mechanism. + +\sphinxAtStartPar +An interposer module must export the symbol \sphinxstylestrong{gss\_mech\_interposer} +with the following signature: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{gss\PYGZus{}OID\PYGZus{}set} \PYG{n}{gss\PYGZus{}mech\PYGZus{}interposer}\PYG{p}{(}\PYG{n}{gss\PYGZus{}OID} \PYG{n}{mech\PYGZus{}type}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +This function is invoked with the OID of the interposer mechanism as +specified in the mechanism config file, and returns a set of mechanism +OIDs to be interposed. The returned OID set must have been created +using the mechglue’s gss\_create\_empty\_oid\_set and +gss\_add\_oid\_set\_member functions. + +\sphinxAtStartPar +An interposer module must use the prefix \sphinxcode{\sphinxupquote{gssi\_}} for the GSSAPI +functions it exports, instead of the prefix \sphinxcode{\sphinxupquote{gss\_}}. In most cases, +unexported \sphinxcode{\sphinxupquote{gssi\_}} functions will result in failure from their +corresponding \sphinxcode{\sphinxupquote{gss\_}} calls. + +\sphinxAtStartPar +An interposer module can link against the GSSAPI library in order to +make calls to the original mechanism. To do so, it must specify a +special mechanism OID which is the concatention of the interposer’s +own OID byte string and the original mechanism’s OID byte string. + +\sphinxAtStartPar +Functions that do not accept a mechanism argument directly require no +special handling, with the following exceptions: + +\sphinxAtStartPar +Since \sphinxstylestrong{gss\_accept\_sec\_context} does not accept a mechanism argument, +an interposer mechanism must, in order to invoke the original +mechanism’s function, acquire a credential for the concatenated OID +and pass that as the \sphinxstyleemphasis{verifier\_cred\_handle} parameter. + +\sphinxAtStartPar +Since \sphinxstylestrong{gss\_import\_name}, \sphinxstylestrong{gss\_import\_cred}, and +\sphinxstylestrong{gss\_import\_sec\_context} do not accept mechanism parameters, the SPI +has been extended to include variants which do. This allows the +interposer module to know which mechanism should be used to interpret +the token. These functions have the following signatures: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gssi\PYGZus{}import\PYGZus{}sec\PYGZus{}context\PYGZus{}by\PYGZus{}mech}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}OID} \PYG{n}{desired\PYGZus{}mech}\PYG{p}{,} \PYG{n}{gss\PYGZus{}buffer\PYGZus{}t} \PYG{n}{interprocess\PYGZus{}token}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}ctx\PYGZus{}id\PYGZus{}t} \PYG{o}{*}\PYG{n}{context\PYGZus{}handle}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gssi\PYGZus{}import\PYGZus{}name\PYGZus{}by\PYGZus{}mech}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}OID} \PYG{n}{mech\PYGZus{}type}\PYG{p}{,} \PYG{n}{gss\PYGZus{}buffer\PYGZus{}t} \PYG{n}{input\PYGZus{}name\PYGZus{}buffer}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}OID} \PYG{n}{input\PYGZus{}name\PYGZus{}type}\PYG{p}{,} \PYG{n}{gss\PYGZus{}name\PYGZus{}t} \PYG{n}{output\PYGZus{}name}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gssi\PYGZus{}import\PYGZus{}cred\PYGZus{}by\PYGZus{}mech}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}OID} \PYG{n}{mech\PYGZus{}type}\PYG{p}{,} \PYG{n}{gss\PYGZus{}buffer\PYGZus{}t} \PYG{n}{token}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}cred\PYGZus{}id\PYGZus{}t} \PYG{o}{*}\PYG{n}{cred\PYGZus{}handle}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +To re\sphinxhyphen{}enter the original mechanism when importing tokens for the above +functions, the interposer module must wrap the mechanism token in the +mechglue’s format, using the concatenated OID (except in +\sphinxstylestrong{gss\_import\_name}). The mechglue token formats are: +\begin{itemize} +\item {} +\sphinxAtStartPar +For \sphinxstylestrong{gss\_import\_sec\_context}, a four\sphinxhyphen{}byte OID length in big\sphinxhyphen{}endian +order, followed by the concatenated OID, followed by the mechanism +token. + +\item {} +\sphinxAtStartPar +For \sphinxstylestrong{gss\_import\_name}, the bytes 04 01, followed by a two\sphinxhyphen{}byte OID +length in big\sphinxhyphen{}endian order, followed by the mechanism OID, followed +by a four\sphinxhyphen{}byte token length in big\sphinxhyphen{}endian order, followed by the +mechanism token. Unlike most uses of OIDs in the API, the mechanism +OID encoding must include the DER tag and length for an object +identifier (06 followed by the DER length of the OID byte string), +and this prefix must be included in the two\sphinxhyphen{}byte OID length. +input\_name\_type must also be set to GSS\_C\_NT\_EXPORT\_NAME. + +\item {} +\sphinxAtStartPar +For \sphinxstylestrong{gss\_import\_cred}, a four\sphinxhyphen{}byte OID length in big\sphinxhyphen{}endian order, +followed by the concatenated OID, followed by a four\sphinxhyphen{}byte token +length in big\sphinxhyphen{}endian order, followed by the mechanism token. This +sequence may be repeated multiple times. + +\end{itemize} + + +\section{Internal pluggable interfaces} +\label{\detokenize{plugindev/internal:internal-pluggable-interfaces}}\label{\detokenize{plugindev/internal::doc}} +\sphinxAtStartPar +Following are brief discussions of pluggable interfaces which have not +yet been made public. These interfaces are functional, but the +interfaces are likely to change in incompatible ways from release to +release. In some cases, it may be necessary to copy header files from +the krb5 source tree to use an internal interface. Use these with +care, and expect to need to update your modules for each new release +of MIT krb5. + + +\subsection{Kerberos database interface (KDB)} +\label{\detokenize{plugindev/internal:kerberos-database-interface-kdb}} +\sphinxAtStartPar +A KDB module implements a database back end for KDC principal and +policy information, and can also control many aspects of KDC behavior. +For a full description of the interface, see the header file +\sphinxcode{\sphinxupquote{\textless{}kdb.h\textgreater{}}}. + +\sphinxAtStartPar +The KDB pluggable interface is often referred to as the DAL (Database +Access Layer). + + +\subsection{Authorization data interface (authdata)} +\label{\detokenize{plugindev/internal:authorization-data-interface-authdata}} +\sphinxAtStartPar +The authdata interface allows a module to provide (from the KDC) or +consume (in application servers) authorization data of types beyond +those handled by the core MIT krb5 code base. The interface is +defined in the header file \sphinxcode{\sphinxupquote{\textless{}krb5/authdata\_plugin.h\textgreater{}}}, which is not +installed by the build. + + +\section{PKINIT certificate authorization interface (certauth)} +\label{\detokenize{plugindev/certauth:pkinit-certificate-authorization-interface-certauth}}\label{\detokenize{plugindev/certauth:certauth-plugin}}\label{\detokenize{plugindev/certauth::doc}} +\sphinxAtStartPar +The certauth interface was first introduced in release 1.16. It +allows customization of the X.509 certificate attribute requirements +placed on certificates used by PKINIT enabled clients. For a detailed +description of the certauth interface, see the header file +\sphinxcode{\sphinxupquote{\textless{}krb5/certauth\_plugin.h\textgreater{}}} + +\sphinxAtStartPar +A certauth module implements the \sphinxstylestrong{authorize} method to determine +whether a client’s certificate is authorized to authenticate a client +principal. \sphinxstylestrong{authorize} receives the DER\sphinxhyphen{}encoded certificate, the +requested client principal, and a pointer to the client’s +krb5\_db\_entry (for modules that link against libkdb5). The method +must decode the certificate and inspect its attributes to determine if +it should authorize PKINIT authentication. It returns the +authorization status and optionally outputs a list of authentication +indicator strings to be added to the ticket. + +\sphinxAtStartPar +Beginning in release 1.19, the authorize method can request that the +hardware authentication bit be set in the ticket by returning +\sphinxstylestrong{KRB5\_CERTAUTH\_HWAUTH}. Beginning in release 1.20, the authorize +method can return \sphinxstylestrong{KRB5\_CERTAUTH\_HWAUTH\_PASS} to request that the +hardware authentication bit be set in the ticket but otherwise defer +authorization to another certauth module. A module must use its own +internal or library\sphinxhyphen{}provided ASN.1 certificate decoder. + +\sphinxAtStartPar +A module can optionally create and destroy module data with the +\sphinxstylestrong{init} and \sphinxstylestrong{fini} methods. Module data objects last for the +lifetime of the KDC process. + +\sphinxAtStartPar +If a module allocates and returns a list of authentication indicators +from \sphinxstylestrong{authorize}, it must also implement the \sphinxstylestrong{free\_ind} method +to free the list. + + +\section{KDC policy interface (kdcpolicy)} +\label{\detokenize{plugindev/kdcpolicy:kdc-policy-interface-kdcpolicy}}\label{\detokenize{plugindev/kdcpolicy:kdcpolicy-plugin}}\label{\detokenize{plugindev/kdcpolicy::doc}} +\sphinxAtStartPar +The kdcpolicy interface was first introduced in release 1.16. It +allows modules to veto otherwise valid AS and TGS requests or restrict +the lifetime and renew time of the resulting ticket. For a detailed +description of the kdcpolicy interface, see the header file +\sphinxcode{\sphinxupquote{\textless{}krb5/kdcpolicy\_plugin.h\textgreater{}}}. + +\sphinxAtStartPar +The optional \sphinxstylestrong{check\_as} and \sphinxstylestrong{check\_tgs} functions allow the module +to perform access control. Additionally, a module can create and +destroy module data with the \sphinxstylestrong{init} and \sphinxstylestrong{fini} methods. Module +data objects last for the lifetime of the KDC process, and are +provided to all other methods. The data has the type +krb5\_kdcpolicy\_moddata, which should be cast to the appropriate +internal type. + +\sphinxAtStartPar +kdcpolicy modules can optionally inspect principal entries. To do +this, the module must also include \sphinxcode{\sphinxupquote{\textless{}kdb.h\textgreater{}}} to gain access to the +principal entry structure definition. As the KDB interface is +explicitly not as stable as other public interfaces, modules which do +this may not retain compatibility across releases. + + + +\renewcommand{\indexname}{Index} +\printindex +\end{document} \ No newline at end of file diff --git a/krb5-1.21.3/doc/pdf/python.ist b/krb5-1.21.3/doc/pdf/python.ist new file mode 100644 index 00000000..70536a66 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/python.ist @@ -0,0 +1,16 @@ +line_max 100 +headings_flag 1 +heading_prefix " \\bigletter " + +preamble "\\begin{sphinxtheindex} +\\let\\bigletter\\sphinxstyleindexlettergroup +\\let\\spxpagem \\sphinxstyleindexpagemain +\\let\\spxentry \\sphinxstyleindexentry +\\let\\spxextra \\sphinxstyleindexextra + +" + +postamble "\n\n\\end{sphinxtheindex}\n" + +symhead_positive "{\\sphinxsymbolsname}" +numhead_positive "{\\sphinxnumbersname}" diff --git a/krb5-1.21.3/doc/pdf/sphinx.sty b/krb5-1.21.3/doc/pdf/sphinx.sty new file mode 100644 index 00000000..4d42199a --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinx.sty @@ -0,0 +1,351 @@ +% +% sphinx.sty +% +% Adapted from the old python.sty, mostly written by Fred Drake, +% by Georg Brandl. +% + +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesPackage{sphinx}[2021/01/27 v4.0.0 LaTeX package (Sphinx markup)] + +% provides \ltx@ifundefined +% (many packages load ltxcmds: graphicx does for pdftex and lualatex but +% not xelatex, and anyhow kvoptions does, but it may be needed in future to +% use \sphinxdeprecationwarning earlier, and it needs \ltx@ifundefined) +\RequirePackage{ltxcmds} + +%% for deprecation warnings +\newcommand\sphinxdeprecationwarning[4]{% #1 the deprecated macro or name, +% #2 = when deprecated, #3 = when removed, #4 = additional info + \edef\spx@tempa{\detokenize{#1}}% + \ltx@ifundefined{sphinx_depr_\spx@tempa}{% + \global\expandafter\let\csname sphinx_depr_\spx@tempa\endcsname\spx@tempa + \expandafter\AtEndDocument\expandafter{\expandafter\let\expandafter + \sphinxdeprecatedmacro\csname sphinx_depr_\spx@tempa\endcsname + \PackageWarningNoLine{sphinx}{^^J**** SPHINX DEPRECATION WARNING:^^J + \sphinxdeprecatedmacro^^J + \@spaces- is deprecated at Sphinx #2^^J + \@spaces- and removed at Sphinx #3.^^J + #4^^J****}}% + }{% warning already emitted (at end of latex log), don't repeat + }} + + +%% OPTION HANDLING +% + +% We first handle options then load packages, but we need \definecolor from +% xcolor/color. + +% FIXME: we should \RequirePackage{xcolor} always now +% The xcolor package draws better fcolorboxes around verbatim code +\IfFileExists{xcolor.sty}{ + \RequirePackage{xcolor} +}{ + \RequirePackage{color} +} + +% Handle options via "kvoptions" (later loaded by hyperref anyhow) +\RequirePackage{kvoptions} +\SetupKeyvalOptions{prefix=spx@opt@} % use \spx@opt@ prefix + +% Sphinx legacy text layout: 1in margins on all four sides +\ifx\@jsc@uplatextrue\@undefined +\DeclareStringOption[1in]{hmargin} +\DeclareStringOption[1in]{vmargin} +\DeclareStringOption[.5in]{marginpar} +\else +% Japanese standard document classes handle \mag in a special way +\DeclareStringOption[\inv@mag in]{hmargin} +\DeclareStringOption[\inv@mag in]{vmargin} +\DeclareStringOption[.5\dimexpr\inv@mag in\relax]{marginpar} +\fi + +\DeclareStringOption[0]{maxlistdepth}% \newcommand*\spx@opt@maxlistdepth{0} +\DeclareStringOption[-1]{numfigreset} +\DeclareBoolOption[false]{nonumfigreset} +\DeclareBoolOption[false]{mathnumfig} +\define@key{sphinx}{bookmarksdepth}{\AtBeginDocument{\hypersetup{bookmarksdepth=#1}}} +\AtBeginDocument{\define@key{sphinx}{bookmarksdepth}{\hypersetup{bookmarksdepth=#1}}} +% \DeclareBoolOption[false]{usespart}% not used +% dimensions, we declare the \dimen registers here. +\newdimen\sphinxverbatimsep +\newdimen\sphinxverbatimborder +\newdimen\sphinxshadowsep +\newdimen\sphinxshadowsize +\newdimen\sphinxshadowrule +% \DeclareStringOption is not convenient for the handling of these dimensions +% because we want to assign the values to the corresponding registers. Even if +% we added the code to the key handler it would be too late for the initial +% set-up and we would need to do initial assignments explicitly. We end up +% using \define@key directly. +% verbatim +\sphinxverbatimsep=\fboxsep + \define@key{sphinx}{verbatimsep}{\sphinxverbatimsep\dimexpr #1\relax} +\sphinxverbatimborder=\fboxrule + \define@key{sphinx}{verbatimborder}{\sphinxverbatimborder\dimexpr #1\relax} +% topic boxes +\sphinxshadowsep =5pt + \define@key{sphinx}{shadowsep}{\sphinxshadowsep\dimexpr #1\relax} +\sphinxshadowsize=4pt + \define@key{sphinx}{shadowsize}{\sphinxshadowsize\dimexpr #1\relax} +\sphinxshadowrule=\fboxrule + \define@key{sphinx}{shadowrule}{\sphinxshadowrule\dimexpr #1\relax} +% verbatim +\DeclareBoolOption[true]{verbatimwithframe} +\DeclareBoolOption[true]{verbatimwrapslines} +\DeclareBoolOption[false]{verbatimforcewraps} +\DeclareStringOption[3]{verbatimmaxoverfull} +\DeclareStringOption[100]{verbatimmaxunderfull} +\DeclareBoolOption[true]{verbatimhintsturnover} +\DeclareBoolOption[true]{inlineliteralwraps} +\DeclareStringOption[t]{literalblockcappos} +\DeclareStringOption[r]{verbatimcontinuedalign} +\DeclareStringOption[r]{verbatimcontinuesalign} +% parsed literal +\DeclareBoolOption[true]{parsedliteralwraps} +% \textvisiblespace for compatibility with fontspec+XeTeX/LuaTeX +\DeclareStringOption[\textcolor{red}{\textvisiblespace}]{verbatimvisiblespace} +\DeclareStringOption % must use braces to hide the brackets + [{\makebox[2\fontcharwd\font`\x][r]{\textcolor{red}{\tiny$\m@th\hookrightarrow$}}}]% + {verbatimcontinued} +% notices/admonitions +% the dimensions for notices/admonitions are kept as macros and assigned to +% \spx@notice@border at time of use, hence \DeclareStringOption is ok for this +\newdimen\spx@notice@border +\DeclareStringOption[0.5pt]{noteborder} +\DeclareStringOption[0.5pt]{hintborder} +\DeclareStringOption[0.5pt]{importantborder} +\DeclareStringOption[0.5pt]{tipborder} +\DeclareStringOption[1pt]{warningborder} +\DeclareStringOption[1pt]{cautionborder} +\DeclareStringOption[1pt]{attentionborder} +\DeclareStringOption[1pt]{dangerborder} +\DeclareStringOption[1pt]{errorborder} +% footnotes +\DeclareStringOption[\mbox{ }]{AtStartFootnote} +% we need a public macro name for direct use in latex file +\newcommand*{\sphinxAtStartFootnote}{\spx@opt@AtStartFootnote} +% no such need for this one, as it is used inside other macros +\DeclareStringOption[\leavevmode\unskip]{BeforeFootnote} +% some font styling. +\DeclareStringOption[\sffamily\bfseries]{HeaderFamily} +% colours +% same problems as for dimensions: we want the key handler to use \definecolor. +% first, some colours with no prefix, for backwards compatibility +\newcommand*{\sphinxDeclareColorOption}[2]{% + \definecolor{#1}#2% + \define@key{sphinx}{#1}{\definecolor{#1}##1}% +}% +\sphinxDeclareColorOption{TitleColor}{{rgb}{0.126,0.263,0.361}} +\sphinxDeclareColorOption{InnerLinkColor}{{rgb}{0.208,0.374,0.486}} +\sphinxDeclareColorOption{OuterLinkColor}{{rgb}{0.216,0.439,0.388}} +\sphinxDeclareColorOption{VerbatimColor}{{rgb}{1,1,1}} +\sphinxDeclareColorOption{VerbatimBorderColor}{{rgb}{0,0,0}} +% now the colours defined with "sphinx" prefix in their names +\newcommand*{\sphinxDeclareSphinxColorOption}[2]{% + % set the initial default + \definecolor{sphinx#1}#2% + % set the key handler. The "value" ##1 must be acceptable by \definecolor. + \define@key{sphinx}{#1}{\definecolor{sphinx#1}##1}% +}% +% Default color chosen to be as in minted.sty LaTeX package! +\sphinxDeclareSphinxColorOption{VerbatimHighlightColor}{{rgb}{0.878,1,1}} +% admonition boxes, "light" style +\sphinxDeclareSphinxColorOption{noteBorderColor}{{rgb}{0,0,0}} +\sphinxDeclareSphinxColorOption{hintBorderColor}{{rgb}{0,0,0}} +\sphinxDeclareSphinxColorOption{importantBorderColor}{{rgb}{0,0,0}} +\sphinxDeclareSphinxColorOption{tipBorderColor}{{rgb}{0,0,0}} +% admonition boxes, "heavy" style +\sphinxDeclareSphinxColorOption{warningBorderColor}{{rgb}{0,0,0}} +\sphinxDeclareSphinxColorOption{cautionBorderColor}{{rgb}{0,0,0}} +\sphinxDeclareSphinxColorOption{attentionBorderColor}{{rgb}{0,0,0}} +\sphinxDeclareSphinxColorOption{dangerBorderColor}{{rgb}{0,0,0}} +\sphinxDeclareSphinxColorOption{errorBorderColor}{{rgb}{0,0,0}} +\sphinxDeclareSphinxColorOption{warningBgColor}{{rgb}{1,1,1}} +\sphinxDeclareSphinxColorOption{cautionBgColor}{{rgb}{1,1,1}} +\sphinxDeclareSphinxColorOption{attentionBgColor}{{rgb}{1,1,1}} +\sphinxDeclareSphinxColorOption{dangerBgColor}{{rgb}{1,1,1}} +\sphinxDeclareSphinxColorOption{errorBgColor}{{rgb}{1,1,1}} + +\DeclareDefaultOption{\@unknownoptionerror} +\ProcessKeyvalOptions* +% don't allow use of maxlistdepth via \sphinxsetup. +\DisableKeyvalOption{sphinx}{maxlistdepth} +\DisableKeyvalOption{sphinx}{numfigreset} +\DisableKeyvalOption{sphinx}{nonumfigreset} +\DisableKeyvalOption{sphinx}{mathnumfig} +% FIXME: this is unrelated to an option, move this elsewhere +% To allow hyphenation of first word in narrow contexts; no option, +% customization to be done via 'preamble' key +\newcommand*\sphinxAtStartPar{\leavevmode\nobreak\hskip\z@skip} +% No need for the \hspace{0pt} trick (\hskip\z@skip) with luatex +\ifdefined\directlua\let\sphinxAtStartPar\@empty\fi +% user interface: options can be changed midway in a document! +\newcommand\sphinxsetup[1]{\setkeys{sphinx}{#1}} + + +%% MISCELLANEOUS CONTEXT +% +% flag to be set in a framed environment +% (defined here as currently needed by three sphinxlatex....sty files and +% even if not needed if such files are replaced, the definition does no harm) +\newif\ifspx@inframed +% +% \spx@ifcaptionpackage (defined at begin document) +% is needed currently in macros from: +% sphinxlatexliterals.sty (sphinxVerbatim) +% sphinxlatextables.sty (for some macros used in the table templates) +% +% \sphinxcaption is mark-up injected by the tabular and tabulary templates +% it is defined in sphinxlatextables.sty +% +% store the original \caption macro for usage with figures inside longtable +% and tabulary cells. Make sure we get the final \caption in presence of +% caption package, whether the latter was loaded before or after sphinx. +\AtBeginDocument{% + \let\spx@originalcaption\caption + \@ifpackageloaded{caption} + {\let\spx@ifcaptionpackage\@firstoftwo + \caption@AtBeginDocument*{\let\spx@originalcaption\caption}% +% in presence of caption package, drop our own \sphinxcaption whose aim was to +% ensure same width of caption to all kinds of tables (tabular(y), longtable), +% because caption package has its own width (or margin) option + \def\sphinxcaption{\caption}% + }% + {\let\spx@ifcaptionpackage\@secondoftwo}% +} + +%% PASS OPTIONS +% +% pass options to hyperref; it must not have been loaded already +\input{sphinxoptionshyperref.sty} +% pass options to geometry; it must not have been loaded already +\input{sphinxoptionsgeometry.sty} + + +%% COLOR (general) +% +% FIXME: these two should be deprecated +% +% FIXME: \normalcolor should be used and \py@NormalColor never defined +\def\py@NormalColor{\color{black}} +% FIXME: \color{TitleColor} should be used directly and \py@TitleColor +% should never get defined. +\def\py@TitleColor{\color{TitleColor}} + + +%% PACKAGES +% +% as will be indicated below, secondary style files load some more packages +% +% For \text macro (sphinx.util.texescape) +% also for usage of \firstchoice@true(false) in sphinxlatexgraphics.sty +\RequirePackage{amstext} +% It was passed "warn" option from latex template in case it is already loaded +% via some other package before \usepackage{sphinx} in preamble +\RequirePackage{textcomp} +% For the H specifier. Do not \restylefloat{figure}, it breaks Sphinx code +% for allowing figures in tables. +\RequirePackage{float} +% For floating figures in the text. Better to load after float. +\RequirePackage{wrapfig} +% Provides \captionof, used once by latex writer (\captionof{figure}) +\RequirePackage{capt-of} +% Support hlist directive +\RequirePackage{multicol} + + +%% GRAPHICS +% +% It will always be needed, so let's load it here +\RequirePackage{graphicx} +\input{sphinxlatexgraphics.sty} + + +%% FRAMED ENVIRONMENTS +% +\input{sphinxlatexadmonitions.sty} +\input{sphinxlatexliterals.sty} +\input{sphinxlatexshadowbox.sty} + + +%% CONTAINERS +% +\input{sphinxlatexcontainers.sty} + + +%% PYGMENTS +% stylesheet for highlighting with pygments +\RequirePackage{sphinxhighlight} + + +%% TABLES +% +\input{sphinxlatextables.sty} + + +%% NUMBERING OF FIGURES, TABLES, AND LITERAL BLOCKS +% +\input{sphinxlatexnumfig.sty} + + +%% LISTS +% +\input{sphinxlatexlists.sty} + + +%% FOOTNOTES +% +% Support scopes for footnote numbering +\newcounter{sphinxscope} +\newcommand{\sphinxstepscope}{\stepcounter{sphinxscope}} +% Explicitly numbered footnotes may be referred to, and for this to be +% clickable we need to have only one target. So we will step this at each +% explicit footnote and let \thesphinxscope take it into account +\newcounter{sphinxexplicit} +\newcommand{\sphinxstepexplicit}{\stepcounter{sphinxexplicit}} +% Some babel/polyglossia languages fiddle with \@arabic, so let's be extra +% cautious and redefine \thesphinxscope with \number not \@arabic. +% Memo: we expect some subtle redefinition of \thesphinxscope to be a part of page +% scoping for footnotes, when we shall implement it. +\renewcommand{\thesphinxscope}{\number\value{sphinxscope}.\number\value{sphinxexplicit}} +\newcommand\sphinxthefootnotemark[2]{% + % this is used to make reference to an explicitly numbered footnote not on same page + % #1=label of footnote text, #2=page number where footnote text was printed + \ifdefined\pagename + \pagename\space#2, % <- space + \else + p. #2, % <- space + \fi #1% no space +} +% support large numbered footnotes in minipage; but this is now obsolete +% from systematic use of savenotes environment around minipages +\def\thempfootnote{\arabic{mpfootnote}} +% This package is needed to support hyperlinked footnotes in tables and +% framed contents, and to allow code-blocks in footnotes. +\RequirePackage{sphinxpackagefootnote} + + +%% INDEX, BIBLIOGRAPHY, APPENDIX, TABLE OF CONTENTS +% +\input{sphinxlatexindbibtoc.sty} + + +%% STYLING +% +\input{sphinxlatexstylepage.sty} +\input{sphinxlatexstyleheadings.sty} +\input{sphinxlatexstyletext.sty} + + +%% MODULE RELEASE DATA AND OBJECT DESCRIPTIONS +% +\input{sphinxlatexobjects.sty} + + +% FIXME: this line should be dropped, as "9" is default anyhow. +\ifdefined\pdfcompresslevel\pdfcompresslevel = 9 \fi + + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinx.xdy b/krb5-1.21.3/doc/pdf/sphinx.xdy new file mode 100644 index 00000000..0dcf1133 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinx.xdy @@ -0,0 +1,230 @@ +;;; -*- mode: lisp; coding: utf-8; -*- + +;; Unfortunately xindy is out-of-the-box hyperref-incompatible. This +;; configuration is a workaround, which requires to pass option +;; hyperindex=false to hyperref. +;; textit and emph not currently used, spxpagem replaces former textbf +(define-attributes (("textbf" "textit" "emph" "spxpagem" "default"))) +(markup-locref :open "\textbf{\hyperpage{" :close "}}" :attr "textbf") +(markup-locref :open "\textit{\hyperpage{" :close "}}" :attr "textit") +(markup-locref :open "\emph{\hyperpage{" :close "}}" :attr "emph") +(markup-locref :open "\spxpagem{\hyperpage{" :close "}}" :attr "spxpagem") +(markup-locref :open "\hyperpage{" :close "}" :attr "default") + +(require "numeric-sort.xdy") + +;; xindy base module latex.xdy loads tex.xdy and the latter instructs +;; xindy to ignore **all** TeX macros in .idx entries, except those +;; explicitly described in merge rule. But when after applying all +;; merge rules an empty string results, xindy raises an error: + +;; ERROR: CHAR: index 0 should be less than the length of the string + +;; For example when using pdflatex with utf-8 characters the index +;; file will contain \IeC macros and they will get ignored except if +;; suitable merge rules are loaded early. The texindy script coming +;; with xindy provides this, but only for Latin scripts. The texindy +;; man page says to use rather xelatex or lualatex in case of Cyrillic +;; scripts. + +;; Sphinx contributes LICRcyr2utf8.xdy to provide support for Cyrillic +;; scripts for the pdflatex engine. + +;; Another issue caused by xindy ignoring all TeX macros except those +;; explicitly declared reveals itself when attempting to index ">>>", +;; as the ">" is converted to "\textgreater{}" by Sphinx's LaTeX +;; escaping. + +;; To fix this, Sphinx does **not** use texindy, and does not even +;; load the xindy latex.xdy base module. + +;(require "latex.xdy") + +;; Rather it incorporates some suitable extracts from latex.xdy and +;; tex.xdy with additional Sphinx contributed rules. + +;; But, this means for pdflatex and Latin scripts that the xindy file +;; tex/inputenc/uf8.xdy is not usable because it refers to the macro +;; \IeC only sporadically, and as tex.xdy is not loaded, a rule such as +;; (merge-rule "\'e" "é" :string) +;; does not work, it must be +;; (merge-rule "\IeC {\'e}" "é" :string) +;; So Sphinx contributes LICRlatin2utf8.xdy to mitigate that problem. + +;;;;;;;; extracts from tex.xdy (discarding most original comments): + +;;; +;;; TeX conventions +;;; + +;; Discard leading and trailing white space. Collapse multiple white +;; space characters to blank. + +(merge-rule "^ +" "" :eregexp) +(merge-rule " +$" "" :eregexp) +(merge-rule " +" " " :eregexp) + +;; Handle TeX markup + +(merge-rule "\\([{}$%&#])" "\1" :eregexp) + +;;;;;;;; end of extracts from xindy's tex.xdy + +;;;;;;;; extracts from latex.xdy: + +;; Standard location classes: arabic and roman numbers, and alphabets. + +(define-location-class "arabic-page-numbers" ("arabic-numbers")) +(define-location-class "roman-page-numbers" ("roman-numbers-lowercase")) +(define-location-class "Roman-page-numbers" ("roman-numbers-uppercase")) +(define-location-class "alpha-page-numbers" ("alpha")) +(define-location-class "Alpha-page-numbers" ("ALPHA")) + +;; Output Markup + +(markup-letter-group-list :sep "~n~n \indexspace~n") + +(markup-indexentry :open "~n \item " :depth 0) +(markup-indexentry :open "~n \subitem " :depth 1) +(markup-indexentry :open "~n \subsubitem " :depth 2) + +(markup-locclass-list :open ", " :sep ", ") +(markup-locref-list :sep ", ") + +;;;;;;;; end of extracts from latex.xdy + +;; The LaTeX \index command turns \ into normal character so the TeX macros +;; written to .idx files are not followed by a blank. This is different +;; from non-ascii letters which end up (with pdflatex) as \IeC macros in .idx +;; file, with a blank space after \IeC + +;; Details of the syntax are explained at +;; http://xindy.sourceforge.net/doc/manual-3.html +;; In absence of :string, "xindy uses an auto-detection mechanism to decide, +;; if the pattern is a regular expression or not". But it is not obvious to +;; guess, for example "\\_" is not detected as RE but "\\P\{\}" is, so for +;; being sure we apply the :string switch everywhere and do not use \\ etc... + +;; Go back from sphinx.util.texescape TeX macros to UTF-8 + +(merge-rule "\sphinxleftcurlybrace{}" "{" :string) +(merge-rule "\sphinxrightcurlybrace{}" "}" :string) +(merge-rule "\_" "_" :string) +(merge-rule "{[}" "[" :string) +(merge-rule "{]}" "]" :string) +(merge-rule "\textbackslash{}" "\" :string) ; " for Emacs syntax highlighting +(merge-rule "\textasciitilde{}" "~~" :string); the ~~ escape is needed here +(merge-rule "\textasciicircum{}" "^" :string) +(merge-rule "\sphinxhyphen{}" "-" :string) +(merge-rule "\textquotesingle{}" "'" :string) +(merge-rule "\textasciigrave{}" "`" :string) +(merge-rule "\textless{}" "<" :string) +(merge-rule "\textgreater{}" ">" :string) +(merge-rule "\P{}" "¶" :string) +(merge-rule "\S{}" "§" :string) +(merge-rule "\texteuro{}" "€" :string) +(merge-rule "\(\infty\)" "∞" :string) +(merge-rule "\(\pm\)" "±" :string) +(merge-rule "\(\rightarrow\)" "→" :string) +(merge-rule "\(\checkmark\)" "✓" :string) +(merge-rule "\textendash{}" "–" :string) +(merge-rule "\textbar{}" "|" :string) +(merge-rule "\(\sp{\text{0}}\)" "⁰" :string) +(merge-rule "\(\sp{\text{1}}\)" "¹" :string) +(merge-rule "\(\sp{\text{2}}\)" "²" :string) +(merge-rule "\(\sp{\text{3}}\)" "³" :string) +(merge-rule "\(\sp{\text{4}}\)" "⁴" :string) +(merge-rule "\(\sp{\text{5}}\)" "⁵" :string) +(merge-rule "\(\sp{\text{6}}\)" "⁶" :string) +(merge-rule "\(\sp{\text{7}}\)" "⁷" :string) +(merge-rule "\(\sp{\text{8}}\)" "⁸" :string) +(merge-rule "\(\sp{\text{9}}\)" "⁹" :string) +(merge-rule "\(\sb{\text{0}}\)" "₀" :string) +(merge-rule "\(\sb{\text{1}}\)" "₁" :string) +(merge-rule "\(\sb{\text{2}}\)" "₂" :string) +(merge-rule "\(\sb{\text{3}}\)" "₃" :string) +(merge-rule "\(\sb{\text{4}}\)" "₄" :string) +(merge-rule "\(\sb{\text{5}}\)" "₅" :string) +(merge-rule "\(\sb{\text{6}}\)" "₆" :string) +(merge-rule "\(\sb{\text{7}}\)" "₇" :string) +(merge-rule "\(\sb{\text{8}}\)" "₈" :string) +(merge-rule "\(\sb{\text{9}}\)" "₉" :string) +(merge-rule "\IeC {\textalpha }" "α" :string) +(merge-rule "\IeC {\textbeta }" "β" :string) +(merge-rule "\IeC {\textgamma }" "γ" :string) +(merge-rule "\IeC {\textdelta }" "δ" :string) +(merge-rule "\IeC {\textepsilon }" "ε" :string) +(merge-rule "\IeC {\textzeta }" "ζ" :string) +(merge-rule "\IeC {\texteta }" "η" :string) +(merge-rule "\IeC {\texttheta }" "θ" :string) +(merge-rule "\IeC {\textiota }" "ι" :string) +(merge-rule "\IeC {\textkappa }" "κ" :string) +(merge-rule "\IeC {\textlambda }" "λ" :string) +(merge-rule "\IeC {\textmu }" "μ" :string) +(merge-rule "\IeC {\textnu }" "ν" :string) +(merge-rule "\IeC {\textxi }" "ξ" :string) +(merge-rule "\IeC {\textomicron }" "ο" :string) +(merge-rule "\IeC {\textpi }" "π" :string) +(merge-rule "\IeC {\textrho }" "ρ" :string) +(merge-rule "\IeC {\textsigma }" "σ" :string) +(merge-rule "\IeC {\texttau }" "τ" :string) +(merge-rule "\IeC {\textupsilon }" "υ" :string) +(merge-rule "\IeC {\textphi }" "φ" :string) +(merge-rule "\IeC {\textchi }" "χ" :string) +(merge-rule "\IeC {\textpsi }" "ψ" :string) +(merge-rule "\IeC {\textomega }" "ω" :string) +(merge-rule "\IeC {\textAlpha }" "Α" :string) +(merge-rule "\IeC {\textBeta }" "Β" :string) +(merge-rule "\IeC {\textGamma }" "Γ" :string) +(merge-rule "\IeC {\textDelta }" "Δ" :string) +(merge-rule "\IeC {\textEpsilon }" "Ε" :string) +(merge-rule "\IeC {\textZeta }" "Ζ" :string) +(merge-rule "\IeC {\textEta }" "Η" :string) +(merge-rule "\IeC {\textTheta }" "Θ" :string) +(merge-rule "\IeC {\textIota }" "Ι" :string) +(merge-rule "\IeC {\textKappa }" "Κ" :string) +(merge-rule "\IeC {\textLambda }" "Λ" :string) +(merge-rule "\IeC {\textMu }" "Μ" :string) +(merge-rule "\IeC {\textNu }" "Ν" :string) +(merge-rule "\IeC {\textTheta }" "Θ" :string) +(merge-rule "\IeC {\textIota }" "Ι" :string) +(merge-rule "\IeC {\textKappa }" "Κ" :string) +(merge-rule "\IeC {\textLambda }" "Λ" :string) +(merge-rule "\IeC {\textMu }" "Μ" :string) +(merge-rule "\IeC {\textNu }" "Ν" :string) +(merge-rule "\IeC {\textXi }" "Ξ" :string) +(merge-rule "\IeC {\textOmicron }" "Ο" :string) +(merge-rule "\IeC {\textPi }" "Π" :string) +(merge-rule "\IeC {\textRho }" "Ρ" :string) +(merge-rule "\IeC {\textSigma }" "Σ" :string) +(merge-rule "\IeC {\textTau }" "Τ" :string) +(merge-rule "\IeC {\textUpsilon }" "Υ" :string) +(merge-rule "\IeC {\textPhi }" "Φ" :string) +(merge-rule "\IeC {\textChi }" "Χ" :string) +(merge-rule "\IeC {\textPsi }" "Ψ" :string) +(merge-rule "\IeC {\textOmega }" "Ω" :string) +(merge-rule "\IeC {\textohm }" "Ω" :string) + +;; This xindy module provides some basic support for "see" +(require "makeindex.xdy") + +;; This creates one-letter headings and works fine with utf-8 letters. +;; For Cyrillic with pdflatex works thanks to LICRcyr2utf8.xdy +(require "latin-lettergroups.xdy") + +;; currently we don't (know how to easily) separate "Numbers" from +;; "Symbols" with xindy as is the case with makeindex. +(markup-index :open "\begin{sphinxtheindex} +\let\lettergroup\sphinxstyleindexlettergroup +\let\lettergroupDefault\sphinxstyleindexlettergroupDefault +\let\spxpagem\sphinxstyleindexpagemain +\let\spxentry\sphinxstyleindexentry +\let\spxextra\sphinxstyleindexextra + +" + :close " + +\end{sphinxtheindex} +" + :tree) + diff --git a/krb5-1.21.3/doc/pdf/sphinxhighlight.sty b/krb5-1.21.3/doc/pdf/sphinxhighlight.sty new file mode 100644 index 00000000..83b523cb --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxhighlight.sty @@ -0,0 +1,106 @@ +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesPackage{sphinxhighlight}[2016/05/29 stylesheet for highlighting with pygments] +% Its contents depend on pygments_style configuration variable. + + +\makeatletter +\def\PYG@reset{\let\PYG@it=\relax \let\PYG@bf=\relax% + \let\PYG@ul=\relax \let\PYG@tc=\relax% + \let\PYG@bc=\relax \let\PYG@ff=\relax} +\def\PYG@tok#1{\csname PYG@tok@#1\endcsname} +\def\PYG@toks#1+{\ifx\relax#1\empty\else% + \PYG@tok{#1}\expandafter\PYG@toks\fi} +\def\PYG@do#1{\PYG@bc{\PYG@tc{\PYG@ul{% + \PYG@it{\PYG@bf{\PYG@ff{#1}}}}}}} +\def\PYG#1#2{\PYG@reset\PYG@toks#1+\relax+\PYG@do{#2}} + +\@namedef{PYG@tok@w}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.73,0.73}{##1}}} +\@namedef{PYG@tok@c}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}} +\@namedef{PYG@tok@cp}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@cs}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}\def\PYG@bc##1{{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}} +\@namedef{PYG@tok@k}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@kp}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@kt}{\def\PYG@tc##1{\textcolor[rgb]{0.56,0.13,0.00}{##1}}} +\@namedef{PYG@tok@o}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}} +\@namedef{PYG@tok@ow}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@nb}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@nf}{\def\PYG@tc##1{\textcolor[rgb]{0.02,0.16,0.49}{##1}}} +\@namedef{PYG@tok@nc}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.05,0.52,0.71}{##1}}} +\@namedef{PYG@tok@nn}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.05,0.52,0.71}{##1}}} +\@namedef{PYG@tok@ne}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@nv}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}} +\@namedef{PYG@tok@no}{\def\PYG@tc##1{\textcolor[rgb]{0.38,0.68,0.84}{##1}}} +\@namedef{PYG@tok@nl}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.13,0.44}{##1}}} +\@namedef{PYG@tok@ni}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.84,0.33,0.22}{##1}}} +\@namedef{PYG@tok@na}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@nt}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.02,0.16,0.45}{##1}}} +\@namedef{PYG@tok@nd}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.33,0.33,0.33}{##1}}} +\@namedef{PYG@tok@s}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@sd}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@si}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.44,0.63,0.82}{##1}}} +\@namedef{PYG@tok@se}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@sr}{\def\PYG@tc##1{\textcolor[rgb]{0.14,0.33,0.53}{##1}}} +\@namedef{PYG@tok@ss}{\def\PYG@tc##1{\textcolor[rgb]{0.32,0.47,0.09}{##1}}} +\@namedef{PYG@tok@sx}{\def\PYG@tc##1{\textcolor[rgb]{0.78,0.36,0.04}{##1}}} +\@namedef{PYG@tok@m}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@gh}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.50}{##1}}} +\@namedef{PYG@tok@gu}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.50,0.00,0.50}{##1}}} +\@namedef{PYG@tok@gd}{\def\PYG@tc##1{\textcolor[rgb]{0.63,0.00,0.00}{##1}}} +\@namedef{PYG@tok@gi}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.63,0.00}{##1}}} +\@namedef{PYG@tok@gr}{\def\PYG@tc##1{\textcolor[rgb]{1.00,0.00,0.00}{##1}}} +\@namedef{PYG@tok@ge}{\let\PYG@it=\textit} +\@namedef{PYG@tok@gs}{\let\PYG@bf=\textbf} +\@namedef{PYG@tok@gp}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.78,0.36,0.04}{##1}}} +\@namedef{PYG@tok@go}{\def\PYG@tc##1{\textcolor[rgb]{0.20,0.20,0.20}{##1}}} +\@namedef{PYG@tok@gt}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.27,0.87}{##1}}} +\@namedef{PYG@tok@err}{\def\PYG@bc##1{{\setlength{\fboxsep}{\string -\fboxrule}\fcolorbox[rgb]{1.00,0.00,0.00}{1,1,1}{\strut ##1}}}} +\@namedef{PYG@tok@kc}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@kd}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@kn}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@kr}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@bp}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@fm}{\def\PYG@tc##1{\textcolor[rgb]{0.02,0.16,0.49}{##1}}} +\@namedef{PYG@tok@vc}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}} +\@namedef{PYG@tok@vg}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}} +\@namedef{PYG@tok@vi}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}} +\@namedef{PYG@tok@vm}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}} +\@namedef{PYG@tok@sa}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@sb}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@sc}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@dl}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@s2}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@sh}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@s1}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@mb}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@mf}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@mh}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@mi}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@il}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@mo}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@ch}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}} +\@namedef{PYG@tok@cm}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}} +\@namedef{PYG@tok@cpf}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}} +\@namedef{PYG@tok@c1}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}} + +\def\PYGZbs{\char`\\} +\def\PYGZus{\char`\_} +\def\PYGZob{\char`\{} +\def\PYGZcb{\char`\}} +\def\PYGZca{\char`\^} +\def\PYGZam{\char`\&} +\def\PYGZlt{\char`\<} +\def\PYGZgt{\char`\>} +\def\PYGZsh{\char`\#} +\def\PYGZpc{\char`\%} +\def\PYGZdl{\char`\$} +\def\PYGZhy{\char`\-} +\def\PYGZsq{\char`\'} +\def\PYGZdq{\char`\"} +\def\PYGZti{\char`\~} +% for compatibility with earlier versions +\def\PYGZat{@} +\def\PYGZlb{[} +\def\PYGZrb{]} +\makeatother + +\renewcommand\PYGZsq{\textquotesingle} diff --git a/krb5-1.21.3/doc/pdf/sphinxhowto.cls b/krb5-1.21.3/doc/pdf/sphinxhowto.cls new file mode 100644 index 00000000..951cf810 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxhowto.cls @@ -0,0 +1,102 @@ +% +% sphinxhowto.cls for Sphinx (https://www.sphinx-doc.org/) +% + +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesClass{sphinxhowto}[2019/12/01 v2.3.0 Document class (Sphinx howto)] + +% 'oneside' option overriding the 'twoside' default +\newif\if@oneside +\DeclareOption{oneside}{\@onesidetrue} +% Pass remaining document options to the parent class. +\DeclareOption*{\PassOptionsToClass{\CurrentOption}{\sphinxdocclass}} +\ProcessOptions\relax + +% Default to two-side document +\if@oneside +% nothing to do (oneside is the default) +\else +\PassOptionsToClass{twoside}{\sphinxdocclass} +\fi + +\LoadClass{\sphinxdocclass} + +% Set some sane defaults for section numbering depth and TOC depth. You can +% reset these counters in your preamble. +% +\setcounter{secnumdepth}{2} +\setcounter{tocdepth}{2}% i.e. section and subsection + +% Adapt \and command to the flushright context of \sphinxmaketitle, to +% avoid ragged line endings if author names do not fit all on one single line +\DeclareRobustCommand{\and}{% + \end{tabular}\kern-\tabcolsep + \allowbreak + \hskip\dimexpr1em+\tabcolsep\@plus.17fil\begin{tabular}[t]{c}% +}% +% If it is desired that each author name be on its own line, use in preamble: +%\DeclareRobustCommand{\and}{% +% \end{tabular}\kern-\tabcolsep\\\begin{tabular}[t]{c}% +%}% +% Change the title page to look a bit better, and fit in with the fncychap +% ``Bjarne'' style a bit better. +% +\newcommand{\sphinxmaketitle}{% + \noindent\rule{\textwidth}{1pt}\par + \begingroup % for PDF information dictionary + \def\endgraf{ }\def\and{\& }% + \pdfstringdefDisableCommands{\def\\{, }}% overwrite hyperref setup + \hypersetup{pdfauthor={\@author}, pdftitle={\@title}}% + \endgroup + \begin{flushright} + \sphinxlogo + \py@HeaderFamily + {\Huge \@title }\par + {\itshape\large \py@release \releaseinfo}\par + \vspace{25pt} + {\Large + \begin{tabular}[t]{c} + \@author + \end{tabular}\kern-\tabcolsep}\par + \vspace{25pt} + \@date \par + \py@authoraddress \par + \end{flushright} + \@thanks + \setcounter{footnote}{0} + \let\thanks\relax\let\maketitle\relax + %\gdef\@thanks{}\gdef\@author{}\gdef\@title{} +} + +\newcommand{\sphinxtableofcontents}{% + \begingroup + \parskip \z@skip + \sphinxtableofcontentshook + \tableofcontents + \endgroup + \noindent\rule{\textwidth}{1pt}\par + \vspace{12pt}% +} +\newcommand\sphinxtableofcontentshook{} +\pagenumbering{arabic} + +% Fix the bibliography environment to add an entry to the Table of +% Contents. +% For an article document class this environment is a section, +% so no page break before it. +% +\newenvironment{sphinxthebibliography}[1]{% + % \phantomsection % not needed here since TeXLive 2010's hyperref + \begin{thebibliography}{#1}% + \addcontentsline{toc}{section}{\ifdefined\refname\refname\else\ifdefined\bibname\bibname\fi\fi}}{\end{thebibliography}} + + +% Same for the indices. +% The memoir class already does this, so we don't duplicate it in that case. +% +\@ifclassloaded{memoir} + {\newenvironment{sphinxtheindex}{\begin{theindex}}{\end{theindex}}} + {\newenvironment{sphinxtheindex}{% + \phantomsection % needed because no chapter, section, ... is created by theindex + \begin{theindex}% + \addcontentsline{toc}{section}{\indexname}}{\end{theindex}}} diff --git a/krb5-1.21.3/doc/pdf/sphinxlatexadmonitions.sty b/krb5-1.21.3/doc/pdf/sphinxlatexadmonitions.sty new file mode 100644 index 00000000..1e418c8c --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxlatexadmonitions.sty @@ -0,0 +1,148 @@ +%% NOTICES AND ADMONITIONS +% +% change this info string if making any custom modification +\ProvidesFile{sphinxlatexadmonitions.sty}[2021/01/27 admonitions] + +% Provides support for this output mark-up from Sphinx latex writer: +% +% - sphinxadmonition (environment) +% This is a dispatch supporting +% +% - note, hint, important, tip (via sphinxlightbox) +% - warning, caution, attention, danger, error (via sphinxheavybox) +% +% Each sphinx environment can be redefined by user. +% The defaults are customizable via various colour and dimension +% settings, cf sphinx docs (latex customization). +% +% Requires: +\RequirePackage{framed}% used by sphinxheavybox +% +% Dependencies (they do not need to be defined at time of loading): +% - of course the various colour and dimension options handled via sphinx.sty +% - \sphinxstrong (for sphinxlightbox and sphinxheavybox) +% - dimension register \spx@image@maxheight from sphinxlatexgraphics.sty +% - \savenotes/\spewnotes from sphinxpackagefootnote (for sphinxheavybox) + +% Provides: (also in sphinxlatexliterals.sty) +\providecommand*\sphinxvspacefixafterfrenchlists{% + \ifvmode\ifdim\lastskip<\z@ \vskip\parskip\fi\else\par\fi +} + +% Some are quite plain +% the spx@notice@bordercolor etc are set in the sphinxadmonition environment +\newenvironment{sphinxlightbox}{% + \par + \noindent{\color{spx@notice@bordercolor}% + \rule{\linewidth}{\spx@notice@border}}\par\nobreak + {\parskip\z@skip\noindent}% + } + {% + % counteract previous possible negative skip (French lists!): + % (we can't cancel that any earlier \vskip introduced a potential pagebreak) + \sphinxvspacefixafterfrenchlists + \nobreak\vbox{\noindent\kern\@totalleftmargin + {\color{spx@notice@bordercolor}% + \rule[\dimexpr.4\baselineskip-\spx@notice@border\relax] + {\linewidth}{\spx@notice@border}}\hss}\allowbreak + }% end of sphinxlightbox environment definition +% may be renewenvironment'd by user for complete customization +\newenvironment{sphinxnote}[1] + {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}} +\newenvironment{sphinxhint}[1] + {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}} +\newenvironment{sphinximportant}[1] + {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}} +\newenvironment{sphinxtip}[1] + {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}} +% or just use the package options +% these are needed for common handling by notice environment of lightbox +% and heavybox but they are currently not used by lightbox environment +% and there is consequently no corresponding package option +\definecolor{sphinxnoteBgColor}{rgb}{1,1,1} +\definecolor{sphinxhintBgColor}{rgb}{1,1,1} +\definecolor{sphinximportantBgColor}{rgb}{1,1,1} +\definecolor{sphinxtipBgColor}{rgb}{1,1,1} + +% Others get more distinction +% Code adapted from framed.sty's "snugshade" environment. +% Nesting works (inner frames do not allow page breaks). +\newenvironment{sphinxheavybox}{\par + \setlength{\FrameRule}{\spx@notice@border}% + \setlength{\FrameSep}{\dimexpr.6\baselineskip-\FrameRule\relax} + \advance\spx@image@maxheight + -\dimexpr2\FrameRule + +2\FrameSep + +\baselineskip\relax % will happen again if nested, needed indeed! + % configure framed.sty's parameters to obtain same vertical spacing + % as for "light" boxes. We need for this to manually insert parskip glue and + % revert a skip done by framed before the frame. + \ltx@ifundefined{OuterFrameSep}{}{\OuterFrameSep\z@skip}% + \vspace{\FrameHeightAdjust} + % copied/adapted from framed.sty's snugshade + \def\FrameCommand##1{\hskip\@totalleftmargin + \fboxsep\FrameSep \fboxrule\FrameRule + \fcolorbox{spx@notice@bordercolor}{spx@notice@bgcolor}{##1}% + \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth}% + \savenotes + % use a minipage if we are already inside a framed environment + \ifspx@inframed + \noindent\begin{minipage}{\linewidth} + \else + % handle case where notice is first thing in a list item (or is quoted) + \if@inlabel + \noindent\par\vspace{-\baselineskip} + \else + \vspace{\parskip} + \fi + \fi + \MakeFramed {\spx@inframedtrue + \advance\hsize-\width \@totalleftmargin\z@ \linewidth\hsize + % minipage initialization copied from LaTeX source code. + \@pboxswfalse + \let\@listdepth\@mplistdepth \@mplistdepth\z@ + \@minipagerestore + \@setminipage }% + } + {% + \par\unskip + \@minipagefalse + \endMakeFramed + \ifspx@inframed\end{minipage}\fi + % set footnotes at bottom of page + \spewnotes + % arrange for similar spacing below frame as for "light" boxes. + \vskip .4\baselineskip + }% end of sphinxheavybox environment definition +% may be renewenvironment'd by user for complete customization +\newenvironment{sphinxwarning}[1] + {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}} +\newenvironment{sphinxcaution}[1] + {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}} +\newenvironment{sphinxattention}[1] + {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}} +\newenvironment{sphinxdanger}[1] + {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}} +\newenvironment{sphinxerror}[1] + {\begin{sphinxheavybox}\sphinxstrong{#1} }{\end{sphinxheavybox}} +% or just use package options + +% the \colorlet of xcolor (if at all loaded) is overkill for our use case +\newcommand{\sphinxcolorlet}[2] + {\expandafter\let\csname\@backslashchar color@#1\expandafter\endcsname + \csname\@backslashchar color@#2\endcsname } + +% the main dispatch for all types of notices +\newenvironment{sphinxadmonition}[2]{% #1=type, #2=heading + % can't use #1 directly in definition of end part + \def\spx@noticetype {#1}% + % set parameters of heavybox/lightbox + \sphinxcolorlet{spx@notice@bordercolor}{sphinx#1BorderColor}% + \sphinxcolorlet{spx@notice@bgcolor}{sphinx#1BgColor}% + \spx@notice@border \dimexpr\csname spx@opt@#1border\endcsname\relax + % start specific environment, passing the heading as argument + \begin{sphinx#1}{#2}} + % workaround some LaTeX "feature" of \end command + {\edef\spx@temp{\noexpand\end{sphinx\spx@noticetype}}\spx@temp} + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxlatexcontainers.sty b/krb5-1.21.3/doc/pdf/sphinxlatexcontainers.sty new file mode 100644 index 00000000..93b2c8c0 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxlatexcontainers.sty @@ -0,0 +1,22 @@ +%% CONTAINER DIRECTIVES +% +% change this info string if making any custom modification +\ProvidesFile{sphinxlatexcontainers.sty}[2021/05/03 containers] + +% The purpose of this file is to provide a dummy environment sphinxclass which +% will be inserted for each class in each container directive. The class name +% will be passed as the argument to the environment. +% +% For a class foo, the user can define customised handling of that class by +% defining the sphinxclassfoo LaTeX environment. + +\newenvironment{sphinxuseclass}[1]{% + \def\sphinxClassFunctionName{sphinxclass#1}% + \ltx@ifundefined{\sphinxClassFunctionName}% + {}% undefined so do nothing + {\expandafter\begin\expandafter{\sphinxClassFunctionName}}% +}{% + \ltx@ifundefined{\sphinxClassFunctionName}% + {}% we did nothing so we keep doing nothing + {\expandafter\end\expandafter{\sphinxClassFunctionName}}% +}% diff --git a/krb5-1.21.3/doc/pdf/sphinxlatexgraphics.sty b/krb5-1.21.3/doc/pdf/sphinxlatexgraphics.sty new file mode 100644 index 00000000..fd0aae63 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxlatexgraphics.sty @@ -0,0 +1,122 @@ +%% GRAPHICS +% +% change this info string if making any custom modification +\ProvidesFile{sphinxlatexgraphics.sty}[2021/01/27 graphics] + +% Provides support for this output mark-up from Sphinx latex writer: +% +% - macros: +% +% - \sphinxfigcaption +% - \sphinxincludegraphics +% +% - environments: +% +% - sphinxfigure-in-table +% +% May change: +% +% - \sphinxcaption (at begin document) +% +% Also provides: +% +% - \sphinxsafeincludegraphics (default of \sphinxincludegraphics since 2.0) +% - \spx@image@maxheight dimension (used by sphinxlatexadmonitions.sty) +% - \spx@image@box scratch box register (also used by sphinxlatexliterals.sty) +% +% Requires: +% \RequirePackage{graphicx}% done in sphinx.sty +\RequirePackage{amstext}% needed for \firstchoice@true(false) + +% \sphinxincludegraphics resizes images larger than the TeX \linewidth (which +% is adjusted in indented environments), or taller than a certain maximal +% height (usually \textheight and this is reduced in the environments which use +% framed.sty to avoid infinite loop if image too tall). +% +% In case height or width options are present the rescaling is done +% (since 2.0), in a way keeping the width:height ratio either native from +% image or from the width and height options if both were present. +% +\newdimen\spx@image@maxheight +\AtBeginDocument{\spx@image@maxheight\textheight} + +% box scratch register +\newbox\spx@image@box +\newcommand*{\sphinxsafeincludegraphics}[2][]{% + % #1 contains possibly width=, height=, but no scale= since 1.8.4 + \setbox\spx@image@box\hbox{\includegraphics[#1,draft]{#2}}% + \in@false % use some handy boolean flag + \ifdim \wd\spx@image@box>\linewidth + \in@true % flag to remember to adjust options and set box dimensions + % compute height which results from rescaling width to \linewidth + % and keep current aspect ratio. multiply-divide in \numexpr uses + % temporarily doubled precision, hence no overflow. (of course we + % assume \ht is not a few sp's below \maxdimen...(about 16384pt). + \edef\spx@image@rescaledheight % with sp units + {\the\numexpr\ht\spx@image@box + *\linewidth/\wd\spx@image@box sp}% + \ifdim\spx@image@rescaledheight>\spx@image@maxheight + % the rescaled height will be too big, so it is height which decides + % the rescaling factor + \def\spx@image@requiredheight{\spx@image@maxheight}% dimen register + \edef\spx@image@requiredwidth % with sp units + {\the\numexpr\wd\spx@image@box + *\spx@image@maxheight/\ht\spx@image@box sp}% + % TODO: decide if this commented-out block could be needed due to + % rounding in numexpr operations going up + % \ifdim\spx@image@requiredwidth>\linewidth + % \def\spx@image@requiredwidth{\linewidth}% dimen register + % \fi + \else + \def\spx@image@requiredwidth{\linewidth}% dimen register + \let\spx@image@requiredheight\spx@image@rescaledheight% sp units + \fi + \else + % width is ok, let's check height + \ifdim\ht\spx@image@box>\spx@image@maxheight + \in@true + \edef\spx@image@requiredwidth % with sp units + {\the\numexpr\wd\spx@image@box + *\spx@image@maxheight/\ht\spx@image@box sp}% + \def\spx@image@requiredheight{\spx@image@maxheight}% dimen register + \fi + \fi % end of check of width and height + \ifin@ + \setbox\spx@image@box + \hbox{\includegraphics + [%#1,% contained only width and/or height and overruled anyhow + width=\spx@image@requiredwidth,height=\spx@image@requiredheight]% + {#2}}% + % \includegraphics does not set box dimensions to the exactly + % requested ones, see https://github.com/latex3/latex2e/issues/112 + \wd\spx@image@box\spx@image@requiredwidth + \ht\spx@image@box\spx@image@requiredheight + \leavevmode\box\spx@image@box + \else + % here we do not modify the options, no need to adjust width and height + % on output, they will be computed exactly as with "draft" option + \setbox\spx@image@box\box\voidb@x % clear memory + \includegraphics[#1]{#2}% + \fi +}% +% Use the "safe" one by default (2.0) +\def\sphinxincludegraphics{\sphinxsafeincludegraphics} + + +%% FIGURE IN TABLE +% +\newenvironment{sphinxfigure-in-table}[1][\linewidth]{% + \def\@captype{figure}% + \sphinxsetvskipsforfigintablecaption + \begin{minipage}{#1}% +}{\end{minipage}} +% tabulary expands twice contents, we need to prevent double counter stepping +\newcommand*\sphinxfigcaption + {\ifx\equation$%$% this is trick to identify tabulary first pass + \firstchoice@false\else\firstchoice@true\fi + \spx@originalcaption } +\newcommand*\sphinxsetvskipsforfigintablecaption + {\abovecaptionskip\smallskipamount + \belowcaptionskip\smallskipamount} + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxlatexindbibtoc.sty b/krb5-1.21.3/doc/pdf/sphinxlatexindbibtoc.sty new file mode 100644 index 00000000..79e30a1f --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxlatexindbibtoc.sty @@ -0,0 +1,69 @@ +%% INDEX, BIBLIOGRAPHY, APPENDIX, TABLE OF CONTENTS +% +% change this info string if making any custom modification +\ProvidesFile{sphinxlatexindbibtoc.sty}[2021/01/27 index, bib., toc] + +% Provides support for this output mark-up from Sphinx latex writer: +% +% - environments: (backup defaults or get redefined) +% +% - sphinxtheindex (direct mark-up or via python.ist or sphinx.xdy) +% - sphinxthebibliography +% +% - macros: (defines defaults) +% +% - \sphinxmaketitle +% - \sphinxtableofcontents +% - \sphinxnonalphabeticalgroupname +% - \sphinxsymbolsname +% - \sphinxnumbersname +% - \sphinxcite +% +% Requires: +\RequirePackage{makeidx} + +% fix the double index and bibliography on the table of contents +% in jsclasses (Japanese standard document classes) +\ifx\@jsc@uplatextrue\@undefined\else + \renewenvironment{sphinxtheindex} + {\cleardoublepage\phantomsection + \begin{theindex}} + {\end{theindex}} + + \renewenvironment{sphinxthebibliography}[1] + {\cleardoublepage% \phantomsection % not needed here since TeXLive 2010's hyperref + \begin{thebibliography}{#1}} + {\end{thebibliography}} +\fi + +% disable \@chappos in Appendix in pTeX +\ifx\kanjiskip\@undefined\else + \let\py@OldAppendix=\appendix + \renewcommand{\appendix}{ + \py@OldAppendix + \gdef\@chappos{} + } +\fi + +% make commands known to non-Sphinx document classes +\providecommand*{\sphinxmaketitle}{\maketitle} +\providecommand*{\sphinxtableofcontents}{\tableofcontents} +\ltx@ifundefined{sphinxthebibliography} + {\newenvironment + {sphinxthebibliography}{\begin{thebibliography}}{\end{thebibliography}}% + } + {}% else clause of \ltx@ifundefined +\ltx@ifundefined{sphinxtheindex} + {\newenvironment{sphinxtheindex}{\begin{theindex}}{\end{theindex}}}% + {}% else clause of \ltx@ifundefined + +% for usage with xindy: this string gets internationalized in preamble +\newcommand*{\sphinxnonalphabeticalgroupname}{} +% redefined in preamble, headings for makeindex produced index +\newcommand*{\sphinxsymbolsname}{} +\newcommand*{\sphinxnumbersname}{} + +\protected\def\sphinxcite{\cite} + + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxlatexlists.sty b/krb5-1.21.3/doc/pdf/sphinxlatexlists.sty new file mode 100644 index 00000000..ed7521cf --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxlatexlists.sty @@ -0,0 +1,97 @@ +%% ALPHANUMERIC LIST ITEMS +% +% change this info string if making any custom modification +\ProvidesFile{sphinxlatexlists.sty}[2021/01/27 lists] + +% Provides support for this output mark-up from Sphinx latex writer: +% - \sphinxsetlistlabels + +% Dependencies: the \spx@opt@maxlistdepth from sphinx.sty + +\newcommand\sphinxsetlistlabels[5] +{% #1 = style, #2 = enum, #3 = enumnext, #4 = prefix, #5 = suffix + % #2 and #3 are counters used by enumerate environment e.g. enumi, enumii. + % #1 is a macro such as \arabic or \alph + % prefix and suffix are strings (by default empty and a dot). + \@namedef{the#2}{#1{#2}}% + \@namedef{label#2}{#4\@nameuse{the#2}#5}% + \@namedef{p@#3}{\@nameuse{p@#2}#4\@nameuse{the#2}#5}% +}% + + +%% MAXLISTDEPTH +% +% remove LaTeX's cap on nesting depth if 'maxlistdepth' key used. +% This is a hack, which works with the standard classes: it assumes \@toodeep +% is always used in "true" branches: "\if ... \@toodeep \else .. \fi." + +% will force use the "false" branch (if there is one) +\def\spx@toodeep@hack{\fi\iffalse} + +% do nothing if 'maxlistdepth' key not used or if package enumitem loaded. +\ifnum\spx@opt@maxlistdepth=\z@\expandafter\@gobbletwo\fi +\AtBeginDocument{% +\@ifpackageloaded{enumitem}{\remove@to@nnil}{}% + \let\spx@toodeepORI\@toodeep + \def\@toodeep{% + \ifnum\@listdepth<\spx@opt@maxlistdepth\relax + \expandafter\spx@toodeep@hack + \else + \expandafter\spx@toodeepORI + \fi}% +% define all missing \@list... macros + \count@\@ne + \loop + \ltx@ifundefined{@list\romannumeral\the\count@} + {\iffalse}{\iftrue\advance\count@\@ne}% + \repeat + \loop + \ifnum\count@>\spx@opt@maxlistdepth\relax\else + \expandafter\let + \csname @list\romannumeral\the\count@\expandafter\endcsname + \csname @list\romannumeral\the\numexpr\count@-\@ne\endcsname + % workaround 2.6--3.2d babel-french issue (fixed in 3.2e; no change needed) + \ltx@ifundefined{leftmargin\romannumeral\the\count@} + {\expandafter\let + \csname leftmargin\romannumeral\the\count@\expandafter\endcsname + \csname leftmargin\romannumeral\the\numexpr\count@-\@ne\endcsname}{}% + \advance\count@\@ne + \repeat +% define all missing enum... counters and \labelenum... macros and \p@enum.. + \count@\@ne + \loop + \ltx@ifundefined{c@enum\romannumeral\the\count@} + {\iffalse}{\iftrue\advance\count@\@ne}% + \repeat + \loop + \ifnum\count@>\spx@opt@maxlistdepth\relax\else + \newcounter{enum\romannumeral\the\count@}% + \expandafter\def + \csname labelenum\romannumeral\the\count@\expandafter\endcsname + \expandafter + {\csname theenum\romannumeral\the\numexpr\count@\endcsname.}% + \expandafter\def + \csname p@enum\romannumeral\the\count@\expandafter\endcsname + \expandafter + {\csname p@enum\romannumeral\the\numexpr\count@-\@ne\expandafter + \endcsname\csname theenum\romannumeral\the\numexpr\count@-\@ne\endcsname.}% + \advance\count@\@ne + \repeat +% define all missing labelitem... macros + \count@\@ne + \loop + \ltx@ifundefined{labelitem\romannumeral\the\count@} + {\iffalse}{\iftrue\advance\count@\@ne}% + \repeat + \loop + \ifnum\count@>\spx@opt@maxlistdepth\relax\else + \expandafter\let + \csname labelitem\romannumeral\the\count@\expandafter\endcsname + \csname labelitem\romannumeral\the\numexpr\count@-\@ne\endcsname + \advance\count@\@ne + \repeat + \PackageInfo{sphinx}{maximal list depth extended to \spx@opt@maxlistdepth}% +\@gobble\@nnil +} + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxlatexliterals.sty b/krb5-1.21.3/doc/pdf/sphinxlatexliterals.sty new file mode 100644 index 00000000..d2ba89ea --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxlatexliterals.sty @@ -0,0 +1,795 @@ +%% LITERAL BLOCKS +% +% change this info string if making any custom modification +\ProvidesFile{sphinxlatexliterals.sty}[2021/01/27 code-blocks and parsed literals] + +% Provides support for this output mark-up from Sphinx latex writer: +% +% - macros: +% - \sphinxLiteralBlockLabel +% - \sphinxSetupCaptionForVerbatim +% - \sphinxSetupCodeBlockInFootnote +% - \sphinxhref +% - \sphinxnolinkurl +% - \sphinxresetverbatimhllines +% - \sphinxunactivateextrasandspace +% - \sphinxupquote +% - \sphinxurl +% +% - environments: +% - sphinxVerbatim +% - sphinxVerbatimintable +% - sphinxalltt +% +% Dependency: +% +% - hyperref (for \phantomsection and \capstart) (loaded later) +% +% Executes \RequirePackage for: +% +% - framed +% - fancyvrb +% - alltt +% - upquote +% - needspace + +% also in sphinxlatexadmonitions.sty: +% This is a workaround to a "feature" of French lists, when literal block +% follows immediately; usable generally (does only \par then), a priori... +\providecommand*\sphinxvspacefixafterfrenchlists{% + \ifvmode\ifdim\lastskip<\z@ \vskip\parskip\fi\else\par\fi +} + +% For framing allowing pagebreaks +\RequirePackage{framed} +% For source code +% MEMO: fancyvrb is used mainly to +% 1- control horizontal and vertical spacing +% 2- optional line numbering +% 3- optional line emphasizing +% 4- while still allowing expansion of Pygments latex mark-up +% Other aspects such as framing, caption handling, codeline wrapping are +% added on top of it. We should stop using fancyvrb and implement +% 1, 2, 3, 4 by own Sphinx fully native Verbatim. This would allow to solve +% limitations with wrapped long code line not allowing page break. +\RequirePackage{fancyvrb} +% For parsed-literal blocks. +\RequirePackage{alltt} +% Display "real" single quotes in literal blocks. +\RequirePackage{upquote} +% Skip to next page if not enough space at bottom +\RequirePackage{needspace} + +% Based on use of "fancyvrb.sty"'s Verbatim. +% - with framing allowing page breaks ("framed.sty") +% - with breaking of long lines (exploits Pygments mark-up), +% - with possibly of a top caption, non-separable by pagebreak. +% - and usable inside tables or footnotes ("sphinxpackagefootnote.sty"). + +% for emphasizing lines +\define@key{FV}{hllines}{\def\sphinx@verbatim@checkifhl##1{\in@{, ##1,}{#1}}} +% sphinxVerbatim must be usable by third party without requiring hllines set-up +\def\sphinxresetverbatimhllines{\def\sphinx@verbatim@checkifhl##1{\in@false}} +\sphinxresetverbatimhllines + +% Prior to Sphinx 1.5, \Verbatim and \endVerbatim were modified by Sphinx. +% The aliases defined here are used in sphinxVerbatim environment and can +% serve as hook-points with no need to modify \Verbatim itself. +\let\OriginalVerbatim \Verbatim +\let\endOriginalVerbatim\endVerbatim + +% for captions of literal blocks +% at start of caption title +\newcommand*{\fnum@literalblock}{\literalblockname\nobreakspace\theliteralblock} +% this will be overwritten in document preamble by Babel translation +\newcommand*{\literalblockname}{Listing } +% file extension needed for \caption's good functioning, the file is created +% only if a \listof{literalblock}{foo} command is encountered, which is +% analogous to \listoffigures, but for the code listings (foo = chosen title.) +\newcommand*{\ext@literalblock}{lol} + +% if forced use of minipage encapsulation is needed (e.g. table cells) +\newif\ifsphinxverbatimwithminipage \sphinxverbatimwithminipagefalse + +% Framing macro for use with framed.sty's \FrameCommand +% - it obeys current indentation, +% - frame is \fboxsep separated from the contents, +% - the contents use the full available text width, +% - #1 = color of frame, #2 = color of background, +% - #3 = above frame, #4 = below frame, #5 = within frame, +% - #3 and #4 must be already typeset boxes; they must issue \normalcolor +% or similar, else, they are under scope of color #1 +\long\def\spx@fcolorbox #1#2#3#4#5{% + \hskip\@totalleftmargin + \hskip-\fboxsep\hskip-\fboxrule + % use of \color@b@x here is compatible with both xcolor.sty and color.sty + \color@b@x {\color{#1}\spx@CustomFBox{#3}{#4}}{\color{#2}}{#5}% + \hskip-\fboxsep\hskip-\fboxrule + \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth +}% +% #1 = for material above frame, such as a caption or a "continued" hint +% #2 = for material below frame, such as a caption or "continues on next page" +% #3 = actual contents, which will be typeset with a background color +\long\def\spx@CustomFBox#1#2#3{% + \begingroup + \setbox\@tempboxa\hbox{{#3}}% inner braces to avoid color leaks + \vbox{#1% above frame + % draw frame border _latest_ to avoid pdf viewer issue + \kern\fboxrule + \hbox{\kern\fboxrule + \copy\@tempboxa + \kern-\wd\@tempboxa\kern-\fboxrule + \vrule\@width\fboxrule + \kern\wd\@tempboxa + \vrule\@width\fboxrule}% + \kern-\dimexpr\ht\@tempboxa+\dp\@tempboxa+\fboxrule\relax + \hrule\@height\fboxrule + \kern\dimexpr\ht\@tempboxa+\dp\@tempboxa\relax + \hrule\@height\fboxrule + #2% below frame + }% + \endgroup +}% +\def\spx@fcolorbox@put@c#1{% hide width from framed.sty measuring + \moveright\dimexpr\fboxrule+.5\wd\@tempboxa\hb@xt@\z@{\hss#1\hss}% +}% +\def\spx@fcolorbox@put@r#1{% right align with contents, width hidden + \moveright\dimexpr\fboxrule+\wd\@tempboxa-\fboxsep\hb@xt@\z@{\hss#1}% +}% +\def\spx@fcolorbox@put@l#1{% left align with contents, width hidden + \moveright\dimexpr\fboxrule+\fboxsep\hb@xt@\z@{#1\hss}% +}% +% +\def\sphinxVerbatim@Continued + {\csname spx@fcolorbox@put@\spx@opt@verbatimcontinuedalign\endcsname + {\normalcolor\sphinxstylecodecontinued\literalblockcontinuedname}}% +\def\sphinxVerbatim@Continues + {\csname spx@fcolorbox@put@\spx@opt@verbatimcontinuesalign\endcsname + {\normalcolor\sphinxstylecodecontinues\literalblockcontinuesname}}% +\def\sphinxVerbatim@Title + {\spx@fcolorbox@put@c{\unhcopy\sphinxVerbatim@TitleBox}}% +\let\sphinxVerbatim@Before\@empty +\let\sphinxVerbatim@After\@empty +% Defaults are redefined in document preamble according to language +\newcommand*\literalblockcontinuedname{continued from previous page}% +\newcommand*\literalblockcontinuesname{continues on next page}% +% +\def\spx@verbatimfcolorbox{\spx@fcolorbox{VerbatimBorderColor}{VerbatimColor}}% +\def\sphinxVerbatim@FrameCommand + {\spx@verbatimfcolorbox\sphinxVerbatim@Before\sphinxVerbatim@After}% +\def\sphinxVerbatim@FirstFrameCommand + {\spx@verbatimfcolorbox\sphinxVerbatim@Before\sphinxVerbatim@Continues}% +\def\sphinxVerbatim@MidFrameCommand + {\spx@verbatimfcolorbox\sphinxVerbatim@Continued\sphinxVerbatim@Continues}% +\def\sphinxVerbatim@LastFrameCommand + {\spx@verbatimfcolorbox\sphinxVerbatim@Continued\sphinxVerbatim@After}% + +% For linebreaks inside Verbatim environment from package fancyvrb. +\newbox\sphinxcontinuationbox +\newbox\sphinxvisiblespacebox +\newcommand*\sphinxafterbreak {\copy\sphinxcontinuationbox} + +% Take advantage of the already applied Pygments mark-up to insert +% potential linebreaks for TeX processing. +% {, <, #, %, $, ' and ": go to next line. +% _, }, ^, &, >, -, ~, and \: stay at end of broken line. +% Use of \textquotesingle for straight quote. +% FIXME: convert this to package options ? +\newcommand*\sphinxbreaksbeforelist {% + \do\PYGZob\{\do\PYGZlt\<\do\PYGZsh\#\do\PYGZpc\%% {, <, #, %, + \do\PYGZdl\$\do\PYGZdq\"% $, " + \def\PYGZsq + {\discretionary{}{\sphinxafterbreak\textquotesingle}{\textquotesingle}}% ' +} +\newcommand*\sphinxbreaksafterlist {% + \do\PYGZus\_\do\PYGZcb\}\do\PYGZca\^\do\PYGZam\&% _, }, ^, &, + \do\PYGZgt\>\do\PYGZhy\-\do\PYGZti\~% >, -, ~ + \do\PYGZbs\\% \ +} +\newcommand*\sphinxbreaksatspecials {% + \def\do##1##2% + {\def##1{\discretionary{}{\sphinxafterbreak\char`##2}{\char`##2}}}% + \sphinxbreaksbeforelist + \def\do##1##2% + {\def##1{\discretionary{\char`##2}{\sphinxafterbreak}{\char`##2}}}% + \sphinxbreaksafterlist +} + +\def\sphinx@verbatim@nolig@list {\do \`}% +% Some characters . , ; ? ! / are neither pygmentized nor "tex-escaped". +% This macro makes them "active" and they will insert potential linebreaks. +% Not compatible with math mode (cf \sphinxunactivateextras). +\newcommand*\sphinxbreaksbeforeactivelist {}% none +\newcommand*\sphinxbreaksafteractivelist {\do\.\do\,\do\;\do\?\do\!\do\/} +\newcommand*\sphinxbreaksviaactive {% + \def\do##1{\lccode`\~`##1% + \lowercase{\def~}{\discretionary{}{\sphinxafterbreak\char`##1}{\char`##1}}% + \catcode`##1\active}% + \sphinxbreaksbeforeactivelist + \def\do##1{\lccode`\~`##1% + \lowercase{\def~}{\discretionary{\char`##1}{\sphinxafterbreak}{\char`##1}}% + \catcode`##1\active}% + \sphinxbreaksafteractivelist + \lccode`\~`\~ +} + +% If the linebreak is at a space, the latter will be displayed as visible +% space at end of first line, and a continuation symbol starts next line. +\def\spx@verbatim@space {% + \nobreak\hskip\z@skip + \discretionary{\copy\sphinxvisiblespacebox}{\sphinxafterbreak} + {\kern\fontdimen2\font}% +}% + +% if the available space on page is less than \literalblockneedspace, insert pagebreak +\newcommand{\sphinxliteralblockneedspace}{5\baselineskip} +\newcommand{\sphinxliteralblockwithoutcaptionneedspace}{1.5\baselineskip} +% The title (caption) is specified from outside as macro \sphinxVerbatimTitle. +% \sphinxVerbatimTitle is reset to empty after each use of Verbatim. +\newcommand*\sphinxVerbatimTitle {} +% This box to typeset the caption before framed.sty multiple passes for framing. +\newbox\sphinxVerbatim@TitleBox +% This box to measure contents if nested as inner \MakeFramed requires then +% minipage encapsulation but too long contents then break outer \MakeFramed +\newbox\sphinxVerbatim@ContentsBox +% Holder macro for labels of literal blocks. Set-up by LaTeX writer. +\newcommand*\sphinxLiteralBlockLabel {} +\newcommand*\sphinxSetupCaptionForVerbatim [1] +{% + \sphinxvspacefixafterfrenchlists + \needspace{\sphinxliteralblockneedspace}% +% insert a \label via \sphinxLiteralBlockLabel +% reset to normal the color for the literal block caption + \def\sphinxVerbatimTitle + {\py@NormalColor\sphinxcaption{\sphinxLiteralBlockLabel #1}}% +} +\newcommand*\sphinxSetupCodeBlockInFootnote {% + \fvset{fontsize=\footnotesize}\let\caption\sphinxfigcaption + \sphinxverbatimwithminipagetrue % reduces vertical spaces + % we counteract (this is in a group) the \@normalsize from \caption + \let\normalsize\footnotesize\let\@parboxrestore\relax + \def\spx@abovecaptionskip{\sphinxverbatimsmallskipamount}% +} +\newcommand*{\sphinxverbatimsmallskipamount}{\smallskipamount} +% serves to implement line highlighting and line wrapping +\newcommand\sphinxFancyVerbFormatLine[1]{% + \expandafter\sphinx@verbatim@checkifhl\expandafter{\the\FV@CodeLineNo}% + \ifin@ + \sphinxVerbatimHighlightLine{#1}% + \else + \sphinxVerbatimFormatLine{#1}% + \fi +}% +\newcommand\sphinxVerbatimHighlightLine[1]{% + \edef\sphinxrestorefboxsep{\fboxsep\the\fboxsep\relax}% + \fboxsep0pt\relax % cf LaTeX bug graphics/4524 + \colorbox{sphinxVerbatimHighlightColor}% + {\sphinxrestorefboxsep\sphinxVerbatimFormatLine{#1}}% + % no need to restore \fboxsep here, as this ends up in a \hbox from fancyvrb +}% +% \sphinxVerbatimFormatLine will be set locally to one of those two: +\newcommand\sphinxVerbatimFormatLineWrap{% + \hsize\linewidth + \ifspx@opt@verbatimforcewraps + \expandafter\spx@verb@FormatLineForceWrap + \else\expandafter\spx@verb@FormatLineWrap + \fi +}% +\newcommand\sphinxVerbatimFormatLineNoWrap[1]{\hb@xt@\linewidth{\strut #1\hss}}% +\long\def\spx@verb@FormatLineWrap#1{% + \vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ + \doublehyphendemerits\z@\finalhyphendemerits\z@ + \strut #1\strut}% +}% +% +% The normal line wrapping allows breaks at spaces and ascii non +% letters, non digits. The \raggedright above means there will be +% an overfilled line only if some non-breakable "word" was +% encountered, which is longer than a line (it is moved always to +% be on its own on a new line). +% +% The "forced" line wrapping will parse the tokens to add potential +% breakpoints at each character. As some strings are highlighted, +% we have to apply the highlighting character per character, which +% requires to manipulate the output of the Pygments LaTeXFormatter. +% +% Doing this at latex level is complicated. The contents should +% be as expected: i.e. some active characters from +% \sphinxbreaksviaactive, some Pygments character escapes such as +% \PYGZdl{}, and the highlighting \PYG macro with always 2 +% arguments. No other macros should be there, except perhaps +% zero-parameter macros. In particular: +% - the texcomments Pygments option must be set to False +% +% With pdflatex, Unicode input gives multi-bytes characters +% where the first byte is active. We support the "utf8" macros +% only. "utf8x" is not supported. +% +% The highlighting macro \PYG will be applied character per +% character. Highlighting via a colored background gives thus a +% chain of small colored boxes which may cause some artefact in +% some pdf viewers. Can't do anything here if we do want the line +% break to be possible. +% +% First a measurement step is done of what would the standard line +% wrapping give (i.e line breaks only at spaces and non-letter, +% non-digit ascii characters), cf TeX by Topic for the basic +% dissecting technique: TeX unfortunately when building a vertical +% box does not store in an accessible way what was the maximal +% line-width during paragraph building. +% +% Avoid LaTeX 2021 alteration of \@@par which potentially could break our +% measurement step (typically if the para/after hook is configured to use +% \vspace). Of course, breakage could happen only from user or package +% adding things to basic Sphinx latex. And perhaps spring LaTeX 2021 will +% provide a non-hooked \@@par, but this should work anyway and can't be +% beaten for speed. +\ltx@ifundefined{tex_par:D} +% We could use \@ifl@t@r\fmtversion{2020/02/02}{use \tex_par:D}{use \@@par}. + {\let\spx@par\@@par}% \@@par is then expected to be TeX's original \par + {\expandafter\let\expandafter\spx@par\csname tex_par:D\endcsname} +% More hesitation for avoiding the at-start-of-par hooks for our +% measurement : 1. with old LaTeX, we can not avoid hooks from everyhook +% or similar packages, 2. and perhaps the hooks add stuff which we should +% actually measure. Ideally, hooks are for inserting things in margin +% which do not change spacing. Most everything else in fact should not be +% executed in our scratch box for measurement, such as counter stepping. +\ltx@ifundefined{tex_everypar:D} + {\let\spx@everypar\everypar} + {\expandafter\let\expandafter\spx@everypar\csname tex_everypar:D\endcsname} +% +% If the max width exceeds the linewidth by more than verbatimmaxoverfull +% character widths, or if the min width plus verbatimmaxunderfull character +% widths is inferior to linewidth, then we apply the "force wrapping" with +% potential line break at each character, else we don't. +\long\def\spx@verb@FormatLineForceWrap#1{% + % \spx@image@box is a scratch box register that we can use here + \global\let\spx@verb@maxwidth\z@ + \global\let\spx@verb@minwidth\linewidth + \setbox\spx@image@box + \vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ + \doublehyphendemerits\z@\finalhyphendemerits\z@ + \spx@everypar{}\noindent\strut #1\strut\spx@par + \spx@verb@getwidths}% + \ifdim\spx@verb@maxwidth> + \dimexpr\linewidth+\spx@opt@verbatimmaxoverfull\fontcharwd\font`X \relax + \spx@verb@FormatLineWrap{\spx@verb@wrapPYG #1\spx@verb@wrapPYG}% + \else + \ifdim\spx@verb@minwidth< + \dimexpr\linewidth-\spx@opt@verbatimmaxunderfull\fontcharwd\font`X \relax + \spx@verb@FormatLineWrap{\spx@verb@wrapPYG #1\spx@verb@wrapPYG}% + \else + \spx@verb@FormatLineWrap{#1}% + \fi\fi +}% +% auxiliary paragraph dissector to get max and min widths +% but minwidth must not take into account the last line +\newbox\spx@scratchbox +\def\spx@verb@getwidths {% + \unskip\unpenalty + \setbox\spx@scratchbox\lastbox + \ifvoid\spx@scratchbox + \else + \setbox\spx@scratchbox\hbox{\unhbox\spx@scratchbox}% + \ifdim\spx@verb@maxwidth<\wd\spx@scratchbox + \xdef\spx@verb@maxwidth{\number\wd\spx@scratchbox sp}% + \fi + \expandafter\spx@verb@getwidths@loop + \fi +}% +\def\spx@verb@getwidths@loop {% + \unskip\unpenalty + \setbox\spx@scratchbox\lastbox + \ifvoid\spx@scratchbox + \else + \setbox\spx@scratchbox\hbox{\unhbox\spx@scratchbox}% + \ifdim\spx@verb@maxwidth<\wd\spx@scratchbox + \xdef\spx@verb@maxwidth{\number\wd\spx@scratchbox sp}% + \fi + \ifdim\spx@verb@minwidth>\wd\spx@scratchbox + \xdef\spx@verb@minwidth{\number\wd\spx@scratchbox sp}% + \fi + \expandafter\spx@verb@getwidths@loop + \fi +}% +% auxiliary macros to implement "cut long line even in middle of word" +\catcode`Z=3 % safe delimiter +\def\spx@verb@wrapPYG{% + \futurelet\spx@nexttoken\spx@verb@wrapPYG@i +}% +\def\spx@verb@wrapPYG@i{% + \ifx\spx@nexttoken\spx@verb@wrapPYG\let\next=\@gobble\else + \ifx\spx@nexttoken\PYG\let\next=\spx@verb@wrapPYG@PYG@onebyone\else + \discretionary{}{\sphinxafterbreak}{}% + \let\next\spx@verb@wrapPYG@ii + \fi\fi + \next +}% +% Let's recognize active characters. We don't support utf8x only utf8. +% And here #1 should not have picked up (non empty) braced contents +\long\def\spx@verb@wrapPYG@ii#1{% + \ifcat\noexpand~\noexpand#1\relax% active character + \expandafter\spx@verb@wrapPYG@active + \else % non-active character, control sequence such as \PYGZdl, or empty + \expandafter\spx@verb@wrapPYG@one + \fi {#1}% +}% +\long\def\spx@verb@wrapPYG@active#1{% +% Let's hope expansion of active character does not really require arguments, +% as we certainly don't want to go into expanding upfront token stream anyway. + \expandafter\spx@verb@wrapPYG@iii#1{}{}{}{}{}{}{}{}{}Z#1% +}% +\long\def\spx@verb@wrapPYG@iii#1#2Z{% + \ifx\UTFviii@four@octets#1\let\next=\spx@verb@wrapPYG@four\else + \ifx\UTFviii@three@octets#1\let\next=\spx@verb@wrapPYG@three\else + \ifx\UTFviii@two@octets#1\let\next=\spx@verb@wrapPYG@two\else + \let\next=\spx@verb@wrapPYG@one + \fi\fi\fi + \next +}% +\long\def\spx@verb@wrapPYG@one #1{#1\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}% +\long\def\spx@verb@wrapPYG@two #1#2{#1#2\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}% +\long\def\spx@verb@wrapPYG@three #1#2#3{#1#2#3\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}% +\long\def\spx@verb@wrapPYG@four #1#2#3#4{#1#2#3#4\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}% +% Replace \PYG by itself applied one character at a time! This way breakpoints +% can be inserted. +\def\spx@verb@wrapPYG@PYG@onebyone#1#2#3{% #1 = \PYG, #2 = highlight spec, #3 = tokens + \def\spx@verb@wrapPYG@PYG@spec{{#2}}% + \futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i#3Z% +}% +\def\spx@verb@wrapPYG@PYG@i{% + \ifx\spx@nexttokenZ\let\next=\spx@verb@wrapPYG@PYG@done\else + \discretionary{}{\sphinxafterbreak}{}% + \let\next\spx@verb@wrapPYG@PYG@ii + \fi + \next +}% +\def\spx@verb@wrapPYG@PYG@doneZ{\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}% +\long\def\spx@verb@wrapPYG@PYG@ii#1{% + \ifcat\noexpand~\noexpand#1\relax% active character + \expandafter\spx@verb@wrapPYG@PYG@active + \else % non-active character, control sequence such as \PYGZdl, or empty + \expandafter\spx@verb@wrapPYG@PYG@one + \fi {#1}% +}% +\long\def\spx@verb@wrapPYG@PYG@active#1{% +% Let's hope expansion of active character does not really require arguments, +% as we certainly don't want to go into expanding upfront token stream anyway. + \expandafter\spx@verb@wrapPYG@PYG@iii#1{}{}{}{}{}{}{}{}{}Z#1% +}% +\long\def\spx@verb@wrapPYG@PYG@iii#1#2Z{% + \ifx\UTFviii@four@octets#1\let\next=\spx@verb@wrapPYG@PYG@four\else + \ifx\UTFviii@three@octets#1\let\next=\spx@verb@wrapPYG@PYG@three\else + \ifx\UTFviii@two@octets#1\let\next=\spx@verb@wrapPYG@PYG@two\else + \let\next=\spx@verb@wrapPYG@PYG@one + \fi\fi\fi + \next +}% +\long\def\spx@verb@wrapPYG@PYG@one#1{% + \expandafter\PYG\spx@verb@wrapPYG@PYG@spec{#1}% + \futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i +}% +\long\def\spx@verb@wrapPYG@PYG@two#1#2{% + \expandafter\PYG\spx@verb@wrapPYG@PYG@spec{#1#2}% + \futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i +}% +\long\def\spx@verb@wrapPYG@PYG@three#1#2#3{% + \expandafter\PYG\spx@verb@wrapPYG@PYG@spec{#1#2#3}% + \futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i +}% +\long\def\spx@verb@wrapPYG@PYG@four#1#2#3#4{% + \expandafter\PYG\spx@verb@wrapPYG@PYG@spec{#1#2#3#4}% + \futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i +}% +\catcode`Z 11 % +% +\g@addto@macro\FV@SetupFont{% + \sbox\sphinxcontinuationbox {\spx@opt@verbatimcontinued}% + \sbox\sphinxvisiblespacebox {\spx@opt@verbatimvisiblespace}% +}% +\newenvironment{sphinxVerbatim}{% + % first, let's check if there is a caption + \ifx\sphinxVerbatimTitle\empty + \sphinxvspacefixafterfrenchlists + \parskip\z@skip + \vskip\sphinxverbatimsmallskipamount + % there was no caption. Check if nevertheless a label was set. + \ifx\sphinxLiteralBlockLabel\empty\else + % we require some space to be sure hyperlink target from \phantomsection + % will not be separated from upcoming verbatim by a page break + \needspace{\sphinxliteralblockwithoutcaptionneedspace}% + \phantomsection\sphinxLiteralBlockLabel + \fi + \else + \parskip\z@skip + \if t\spx@opt@literalblockcappos + \vskip\spx@abovecaptionskip + \def\sphinxVerbatim@Before + {\sphinxVerbatim@Title\nointerlineskip + \kern\dimexpr-\dp\strutbox+\sphinxbelowcaptionspace + % if no frame (code-blocks inside table cells), remove + % the "verbatimsep" whitespace from the top (better visually) + \ifspx@opt@verbatimwithframe\else-\sphinxverbatimsep\fi + % caption package adds \abovecaptionskip vspace, remove it + \spx@ifcaptionpackage{-\abovecaptionskip}{}\relax}% + \else + \vskip\sphinxverbatimsmallskipamount + \def\sphinxVerbatim@After + {\nointerlineskip\kern\dimexpr\dp\strutbox + \ifspx@opt@verbatimwithframe\else-\sphinxverbatimsep\fi + \spx@ifcaptionpackage{-\abovecaptionskip}{}\relax + \sphinxVerbatim@Title}% + \fi + \def\@captype{literalblock}% + \capstart + % \sphinxVerbatimTitle must reset color + \setbox\sphinxVerbatim@TitleBox + \hbox{\begin{minipage}{\linewidth}% + % caption package may detect wrongly if top or bottom, so we help it + \spx@ifcaptionpackage + {\caption@setposition{\spx@opt@literalblockcappos}}{}% + \sphinxVerbatimTitle + \end{minipage}}% + \fi + \global\let\sphinxLiteralBlockLabel\empty + \global\let\sphinxVerbatimTitle\empty + \fboxsep\sphinxverbatimsep \fboxrule\sphinxverbatimborder + \ifspx@opt@verbatimwithframe\else\fboxrule\z@\fi + \let\FrameCommand \sphinxVerbatim@FrameCommand + \let\FirstFrameCommand\sphinxVerbatim@FirstFrameCommand + \let\MidFrameCommand \sphinxVerbatim@MidFrameCommand + \let\LastFrameCommand \sphinxVerbatim@LastFrameCommand + \ifspx@opt@verbatimhintsturnover\else + \let\sphinxVerbatim@Continued\@empty + \let\sphinxVerbatim@Continues\@empty + \fi + \ifspx@opt@verbatimwrapslines + % fancyvrb's Verbatim puts each input line in (unbreakable) horizontal boxes. + % This customization wraps each line from the input in a \vtop, thus + % allowing it to wrap and display on two or more lines in the latex output. + % - The codeline counter will be increased only once. + % - The wrapped material will not break across pages, it is impossible + % to achieve this without extensive rewrite of fancyvrb. + % - The (not used in sphinx) obeytabs option to Verbatim is + % broken by this change (showtabs and tabspace work). + \let\sphinxVerbatimFormatLine\sphinxVerbatimFormatLineWrap + \let\FV@Space\spx@verbatim@space + % Allow breaks at special characters using \PYG... macros. + \sphinxbreaksatspecials + % Breaks at punctuation characters . , ; ? ! and / (needs catcode activation) + \fvset{codes*=\sphinxbreaksviaactive}% + \else % end of conditional code for wrapping long code lines + \let\sphinxVerbatimFormatLine\sphinxVerbatimFormatLineNoWrap + \fi + \let\FancyVerbFormatLine\sphinxFancyVerbFormatLine + \VerbatimEnvironment + % workaround to fancyvrb's check of current list depth + \def\@toodeep {\advance\@listdepth\@ne}% + % The list environment is needed to control perfectly the vertical space. + % Note: \OuterFrameSep used by framed.sty is later set to \topsep hence 0pt. + % - if caption: distance from last text baseline to caption baseline is + % A+(B-F)+\ht\strutbox, A = \abovecaptionskip (default 10pt), B = + % \baselineskip, F is the framed.sty \FrameHeightAdjust macro, default 6pt. + % Formula valid for F < 10pt. + % - distance of baseline of caption to top of frame is like for tables: + % \sphinxbelowcaptionspace (=0.5\baselineskip) + % - if no caption: distance of last text baseline to code frame is S+(B-F), + % with S = \sphinxverbatimtopskip (=\smallskip) + % - and distance from bottom of frame to next text baseline is + % \baselineskip+\parskip. + % The \trivlist is used to avoid possible "too deeply nested" error. + \itemsep \z@skip + \topsep \z@skip + \partopsep \z@skip + % trivlist will set \parsep to \parskip (which itself is set to zero above) + % \leftmargin will be set to zero by trivlist + \rightmargin\z@ + \parindent \z@% becomes \itemindent. Default zero, but perhaps overwritten. + \trivlist\item\relax + \ifspx@inframed\setbox\sphinxVerbatim@ContentsBox\vbox\bgroup + \@setminipage\hsize\linewidth + % use bulk of minipage paragraph shape restores (this is needed + % in indented contexts, at least for some) + \textwidth\hsize \columnwidth\hsize \@totalleftmargin\z@ + \leftskip\z@skip \rightskip\z@skip \@rightskip\z@skip + \else + \ifsphinxverbatimwithminipage\noindent\begin{minipage}{\linewidth}\fi + \MakeFramed {% adapted over from framed.sty's snugshade environment + \advance\hsize-\width\@totalleftmargin\z@\linewidth\hsize\@setminipage + }% + \fi + % For grid placement from \strut's in \FancyVerbFormatLine + \lineskip\z@skip + % active comma should not be overwritten by \@noligs + \ifspx@opt@verbatimwrapslines + \let\verbatim@nolig@list \sphinx@verbatim@nolig@list + \fi + % will fetch its optional arguments if any + \OriginalVerbatim +} +{% + \endOriginalVerbatim + \ifspx@inframed + \egroup % finish \sphinxVerbatim@ContentsBox vbox + \nobreak % update page totals + \ifdim\dimexpr\ht\sphinxVerbatim@ContentsBox+ + \dp\sphinxVerbatim@ContentsBox+ + \ht\sphinxVerbatim@TitleBox+ + \dp\sphinxVerbatim@TitleBox+ + 2\fboxsep+2\fboxrule+ + % try to account for external frame parameters + \FrameSep+\FrameRule+ + % Usage here of 2 baseline distances is empirical. + % In border case where code-block fits barely in remaining space, + % it gets framed and looks good but the outer frame may continue + % on top of next page and give (if no contents after code-block) + % an empty framed line, as testing showed. + 2\baselineskip+ + % now add all to accumulated page totals and compare to \pagegoal + \pagetotal+\pagedepth>\pagegoal + % long contents: do not \MakeFramed. Do make a caption (either before or + % after) if title exists. Continuation hints across pagebreaks dropped. + % FIXME? a bottom caption may end up isolated at top of next page + % (no problem with a top caption, which is default) + \spx@opt@verbatimwithframefalse + \def\sphinxVerbatim@Title{\noindent\box\sphinxVerbatim@TitleBox\par}% + \sphinxVerbatim@Before + \noindent\unvbox\sphinxVerbatim@ContentsBox\par + \sphinxVerbatim@After + \else + % short enough contents: use \MakeFramed. As it is nested, this requires + % minipage encapsulation. + \noindent\begin{minipage}{\linewidth}% + \MakeFramed {% Use it now with the fetched contents + \advance\hsize-\width\@totalleftmargin\z@\linewidth\hsize\@setminipage + }% + \unvbox\sphinxVerbatim@ContentsBox + % some of this may be superfluous: + \par\unskip\@minipagefalse\endMakeFramed + \end{minipage}% + \fi + \else % non-nested \MakeFramed + \par\unskip\@minipagefalse\endMakeFramed % from framed.sty snugshade + \ifsphinxverbatimwithminipage\end{minipage}\fi + \fi + \endtrivlist +} +\newenvironment {sphinxVerbatimNoFrame} + {\spx@opt@verbatimwithframefalse + \VerbatimEnvironment + \begin{sphinxVerbatim}} + {\end{sphinxVerbatim}} +\newenvironment {sphinxVerbatimintable} + {% don't use a frame if in a table cell + \spx@opt@verbatimwithframefalse + \sphinxverbatimwithminipagetrue + % the literal block caption uses \sphinxcaption which is wrapper of \caption, + % but \caption must be modified because longtable redefines it to work only + % for the own table caption, and tabulary has multiple passes + \let\caption\sphinxfigcaption + % reduce above caption skip + \def\spx@abovecaptionskip{\sphinxverbatimsmallskipamount}% + \VerbatimEnvironment + \begin{sphinxVerbatim}} + {\end{sphinxVerbatim}} + + +%% PARSED LITERALS +% allow long lines to wrap like they do in code-blocks + +% this should be kept in sync with definitions in sphinx.util.texescape +\newcommand*\sphinxbreaksattexescapedchars{% + \def\do##1##2% put potential break point before character + {\def##1{\discretionary{}{\sphinxafterbreak\char`##2}{\char`##2}}}% + \do\{\{\do\textless\<\do\#\#\do\%\%\do\$\$% {, <, #, %, $ + \def\do##1##2% put potential break point after character + {\def##1{\discretionary{\char`##2}{\sphinxafterbreak}{\char`##2}}}% + \do\_\_\do\}\}\do\textasciicircum\^\do\&\&% _, }, ^, &, + \do\textgreater\>\do\textasciitilde\~% >, ~ + \do\textbackslash\\% \ +} +\newcommand*\sphinxbreaksviaactiveinparsedliteral{% + \sphinxbreaksviaactive % by default handles . , ; ? ! / + \lccode`\~`\~ % + % update \dospecials as it is used by \url + % but deactivation will already have been done hence this is unneeded: + % \expandafter\def\expandafter\dospecials\expandafter{\dospecials + % \sphinxbreaksbeforeactivelist\sphinxbreaksafteractivelist\do\-}% +} +\newcommand*\sphinxbreaksatspaceinparsedliteral{% + \lccode`~32 \lowercase{\let~}\spx@verbatim@space\lccode`\~`\~ +} +\newcommand*{\sphinxunactivateextras}{\let\do\@makeother + \sphinxbreaksbeforeactivelist\sphinxbreaksafteractivelist}% +% the \catcode13=5\relax (deactivate end of input lines) is left to callers +\newcommand*{\sphinxunactivateextrasandspace}{\catcode32=10\relax + \sphinxunactivateextras}% +% now for the modified alltt environment +\newenvironment{sphinxalltt} +{% at start of next line to workaround Emacs/AUCTeX issue with this file +\begin{alltt}% + \ifspx@opt@parsedliteralwraps + \sbox\sphinxcontinuationbox {\spx@opt@verbatimcontinued}% + \sbox\sphinxvisiblespacebox {\spx@opt@verbatimvisiblespace}% + \sphinxbreaksattexescapedchars + \sphinxbreaksviaactiveinparsedliteral + \sphinxbreaksatspaceinparsedliteral +% alltt takes care of the ' as derivative ("prime") in math mode + \everymath\expandafter{\the\everymath\sphinxunactivateextrasandspace + \catcode`\<=12\catcode`\>=12\catcode`\^=7\catcode`\_=8 }% +% not sure if displayed math (align,...) can end up in parsed-literal, anyway + \everydisplay\expandafter{\the\everydisplay + \catcode13=5 \sphinxunactivateextrasandspace + \catcode`\<=12\catcode`\>=12\catcode`\^=7\catcode`\_=8 }% + \fi } +{\end{alltt}} + + +%% INLINE MARK-UP +% + +% Protect \href's first argument in contexts such as sphinxalltt (or +% \sphinxcode). Sphinx uses \#, \%, \& ... always inside \sphinxhref. +\protected\def\sphinxhref#1#2{{% + \sphinxunactivateextrasandspace % never do \scantokens with active space! +% for the \endlinechar business, https://github.com/latex3/latex2e/issues/286 + \endlinechar\m@ne\everyeof{{\endlinechar13 #2}}% keep catcode regime for #2 + \scantokens{\href{#1}}% normalise it for #1 during \href expansion +}} +% Same for \url. And also \nolinkurl for coherence. +\protected\def\sphinxurl#1{{% + \sphinxunactivateextrasandspace\everyeof{}% (<- precaution for \scantokens) + \endlinechar\m@ne\scantokens{\url{#1}}% +}} +\protected\def\sphinxnolinkurl#1{{% + \sphinxunactivateextrasandspace\everyeof{}% + \endlinechar\m@ne\scantokens{\nolinkurl{#1}}% +}} + +% \sphinxupquote +% to obtain straight quotes we execute \@noligs as patched by upquote, and +% \scantokens is needed in cases where it would be too late for the macro to +% first set catcodes and then fetch its argument. We also make the contents +% breakable at non-escaped . , ; ? ! / using \sphinxbreaksviaactive, +% and also at \ character (which is escaped to \textbackslash{}). +\protected\def\sphinxtextbackslashbreakbefore + {\discretionary{}{\sphinxafterbreak\sphinx@textbackslash}{\sphinx@textbackslash}} +\protected\def\sphinxtextbackslashbreakafter + {\discretionary{\sphinx@textbackslash}{\sphinxafterbreak}{\sphinx@textbackslash}} +\let\sphinxtextbackslash\sphinxtextbackslashbreakafter +% the macro must be protected if it ends up used in moving arguments, +% in 'alltt' \@noligs is done already, and the \scantokens must be avoided. +\protected\def\sphinxupquote#1{{\def\@tempa{alltt}% + \ifx\@tempa\@currenvir\else + \ifspx@opt@inlineliteralwraps + % break at . , ; ? ! / + \sphinxbreaksviaactive + % break also at \ + \setbox8=\hbox{\textbackslash}% + \def\sphinx@textbackslash{\copy8}% + \let\textbackslash\sphinxtextbackslash + % by default, no continuation symbol on next line but may be added + \let\sphinxafterbreak\sphinxafterbreakofinlineliteral + % do not overwrite the comma set-up + \let\verbatim@nolig@list\sphinx@literal@nolig@list + \fi + % fix a space-gobbling issue due to LaTeX's original \do@noligs +% TODO: using \@noligs as patched by upquote.sty is now unneeded because +% either ` and ' are escaped (non-unicode engines) or they don't build +% ligatures (unicode engines). Thus remove this and unify handling of `, <, >, +% ' and - with the characters . , ; ? ! / as handled via +% \sphinxbreaksviaactive. +% Hence \sphinx@do@noligs will be removed, or rather replaced with code +% inserting discretionaries, as they allow a continuation symbol on start of +% next line to achieve common design with code-blocks. + \let\do@noligs\sphinx@do@noligs + \@noligs\endlinechar\m@ne\everyeof{}% (<- in case inside \sphinxhref) + \expandafter\scantokens + \fi {{#1}}}}% extra brace pair to fix end-space gobbling issue... +\def\sphinx@do@noligs #1{\catcode`#1\active\begingroup\lccode`\~`#1\relax + \lowercase{\endgroup\def~{\leavevmode\kern\z@\char`#1 }}} +\def\sphinx@literal@nolig@list {\do\`\do\<\do\>\do\'\do\-}% +\let\sphinxafterbreakofinlineliteral\empty + + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxlatexnumfig.sty b/krb5-1.21.3/doc/pdf/sphinxlatexnumfig.sty new file mode 100644 index 00000000..6d729610 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxlatexnumfig.sty @@ -0,0 +1,122 @@ +%% NUMBERING OF FIGURES, TABLES, AND LITERAL BLOCKS +% +% change this info string if making any custom modification +\ProvidesFile{sphinxlatexnumfig.sty}[2021/01/27 numbering] + +% Requires: remreset (old LaTeX only) +% relates to numfig and numfig_secnum_depth configuration variables + +% LaTeX 2018-04-01 and later provides \@removefromreset +\ltx@ifundefined{@removefromreset} + {\RequirePackage{remreset}} + {}% avoid warning +% Everything is delayed to \begin{document} to allow hyperref patches into +% \newcounter to solve duplicate label problems for internal hyperlinks to +% code listings (literalblock counter). User or extension re-definitions of +% \theliteralblock, et al., thus have also to be delayed. (changed at 3.5.0) +\AtBeginDocument{% +\ltx@ifundefined{c@chapter} + {\newcounter{literalblock}}% + {\newcounter{literalblock}[chapter]% + \def\theliteralblock{\ifnum\c@chapter>\z@\arabic{chapter}.\fi + \arabic{literalblock}}% + }% +\ifspx@opt@nonumfigreset + \ltx@ifundefined{c@chapter}{}{% + \@removefromreset{figure}{chapter}% + \@removefromreset{table}{chapter}% + \@removefromreset{literalblock}{chapter}% + \ifspx@opt@mathnumfig + \@removefromreset{equation}{chapter}% + \fi + }% + \def\thefigure{\arabic{figure}}% + \def\thetable {\arabic{table}}% + \def\theliteralblock{\arabic{literalblock}}% + \ifspx@opt@mathnumfig + \def\theequation{\arabic{equation}}% + \fi +\else +\let\spx@preAthefigure\@empty +\let\spx@preBthefigure\@empty +% \ifspx@opt@usespart % <-- LaTeX writer could pass such a 'usespart' boolean +% % as sphinx.sty package option +% If document uses \part, (triggered in Sphinx by latex_toplevel_sectioning) +% LaTeX core per default does not reset chapter or section +% counters at each part. +% But if we modify this, we need to redefine \thechapter, \thesection to +% include the part number and this will cause problems in table of contents +% because of too wide numbering. Simplest is to do nothing. +% \fi +\ifnum\spx@opt@numfigreset>0 + \ltx@ifundefined{c@chapter} + {} + {\g@addto@macro\spx@preAthefigure{\ifnum\c@chapter>\z@\arabic{chapter}.}% + \g@addto@macro\spx@preBthefigure{\fi}}% +\fi +\ifnum\spx@opt@numfigreset>1 + \@addtoreset{figure}{section}% + \@addtoreset{table}{section}% + \@addtoreset{literalblock}{section}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{section}% + \fi% + \g@addto@macro\spx@preAthefigure{\ifnum\c@section>\z@\arabic{section}.}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\ifnum\spx@opt@numfigreset>2 + \@addtoreset{figure}{subsection}% + \@addtoreset{table}{subsection}% + \@addtoreset{literalblock}{subsection}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{subsection}% + \fi% + \g@addto@macro\spx@preAthefigure{\ifnum\c@subsection>\z@\arabic{subsection}.}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\ifnum\spx@opt@numfigreset>3 + \@addtoreset{figure}{subsubsection}% + \@addtoreset{table}{subsubsection}% + \@addtoreset{literalblock}{subsubsection}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{subsubsection}% + \fi% + \g@addto@macro\spx@preAthefigure{\ifnum\c@subsubsection>\z@\arabic{subsubsection}.}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\ifnum\spx@opt@numfigreset>4 + \@addtoreset{figure}{paragraph}% + \@addtoreset{table}{paragraph}% + \@addtoreset{literalblock}{paragraph}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{paragraph}% + \fi% + \g@addto@macro\spx@preAthefigure{\ifnum\c@subparagraph>\z@\arabic{subparagraph}.}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\ifnum\spx@opt@numfigreset>5 + \@addtoreset{figure}{subparagraph}% + \@addtoreset{table}{subparagraph}% + \@addtoreset{literalblock}{subparagraph}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{subparagraph}% + \fi% + \g@addto@macro\spx@preAthefigure{\ifnum\c@subsubparagraph>\z@\arabic{subsubparagraph}.}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\expandafter\g@addto@macro +\expandafter\spx@preAthefigure\expandafter{\spx@preBthefigure}% +\let\thefigure\spx@preAthefigure +\let\thetable\spx@preAthefigure +\let\theliteralblock\spx@preAthefigure +\g@addto@macro\thefigure{\arabic{figure}}% +\g@addto@macro\thetable{\arabic{table}}% +\g@addto@macro\theliteralblock{\arabic{literalblock}}% + \ifspx@opt@mathnumfig + \let\theequation\spx@preAthefigure + \g@addto@macro\theequation{\arabic{equation}}% + \fi +\fi +}% end of big \AtBeginDocument + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxlatexobjects.sty b/krb5-1.21.3/doc/pdf/sphinxlatexobjects.sty new file mode 100644 index 00000000..e00881e5 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxlatexobjects.sty @@ -0,0 +1,200 @@ +%% MODULE RELEASE DATA AND OBJECT DESCRIPTIONS +% +% change this info string if making any custom modification +\ProvidesFile{sphinxlatexobjects.sty}[2021/01/27 documentation environments] + +% Provides support for this output mark-up from Sphinx latex writer: +% +% - environments +% +% - fulllineitems +% - productionlist +% - optionlist +% - DUlineblock (also "lineblock") +% +% - macros +% +% - \DUrole +% - various legacy support macros related to author and release +% data of documented objects and modules. + +% \moduleauthor{name}{email} +\newcommand{\moduleauthor}[2]{} + +% \sectionauthor{name}{email} +\newcommand{\sectionauthor}[2]{} + +% Allow the release number to be specified independently of the +% \date{}. This allows the date to reflect the document's date and +% release to specify the release that is documented. +% +\newcommand{\py@release}{\releasename\space\version} +\newcommand{\version}{}% part of \py@release, used by title page and headers +% \releaseinfo is used on titlepage (sphinxmanual.cls, sphinxhowto.cls) +\newcommand{\releaseinfo}{} +\newcommand{\setreleaseinfo}[1]{\renewcommand{\releaseinfo}{#1}} +% this is inserted via template and #1=release config variable +\newcommand{\release}[1]{\renewcommand{\version}{#1}} +% this is defined by template to 'releasename' latex_elements key +\newcommand{\releasename}{} +% Fix issue in case release and releasename deliberately left blank +\newcommand{\sphinxheadercomma}{, }% used in fancyhdr header definition +\newcommand{\sphinxifemptyorblank}[1]{% +% test after one expansion of macro #1 if contents is empty or spaces + \if&\expandafter\@firstofone\detokenize\expandafter{#1}&% + \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}% +\AtBeginDocument {% + \sphinxifemptyorblank{\releasename} + {\sphinxifemptyorblank{\version}{\let\sphinxheadercomma\empty}{}} + {}% +}% + +% Allow specification of the author's address separately from the +% author's name. This can be used to format them differently, which +% is a good thing. +% +\newcommand{\py@authoraddress}{} +\newcommand{\authoraddress}[1]{\renewcommand{\py@authoraddress}{#1}} + +% {fulllineitems} is the main environment for object descriptions. +% +% With 4.0.0 \pysigline (and \pysiglinewithargsret), used in a fulllineitems +% environment the #1 will already be of the width which is computed here, i.e. +% the available width on line, so the \makebox becomes a bit superfluous +\newcommand{\py@itemnewline}[1]{% macro used as \makelabel in fulllineitems +% Memo: this presupposes \itemindent is 0pt + \kern\labelsep % because \@labels core latex box does \hskip-\labelsep + \makebox[\dimexpr\linewidth+\labelwidth\relax][l]{#1}% + \kern-\labelsep % because at end of \@labels box there is \hskip\labelsep +} + +\newenvironment{fulllineitems}{% + \begin{list}{}{\labelwidth \leftmargin + \rightmargin \z@ \topsep -\parskip \partopsep \parskip + \itemsep -\parsep + \let\makelabel=\py@itemnewline}% +}{\end{list}} + +% Signatures, possibly multi-line +% +\newlength{\py@argswidth} +\newcommand{\py@sigparams}[2]{% + % The \py@argswidth has been computed in \pysiglinewithargsret to make this + % occupy full available width on line. + \parbox[t]{\py@argswidth}{\raggedright #1\sphinxcode{)}#2\strut}% + % final strut is to help get correct vertical separation in case of multi-line + % box with the item contents. +} +\newcommand{\pysigline}[1]{% +% the \py@argswidth is available we use it despite its name (no "args" here) +% the \relax\relax is because \py@argswidth is a "skip" variable and the first +% \relax only ends its "dimen" part + \py@argswidth=\dimexpr\linewidth+\labelwidth\relax\relax + \item[{\parbox[t]{\py@argswidth}{\raggedright #1\strut}}] +% contrarily to \pysiglinewithargsret, we do not do this: +% \leavevmode\par\nobreak\vskip-\parskip\prevdepth\dp\strutbox +% which would give exact vertical spacing if item parbox is multi-line, +% as it affects negatively more common situation of \pysigline +% used twice or more in a row for labels sharing common description, +% due to bad interaction with the \phantomsection in the mark-up +} +\newcommand{\pysiglinewithargsret}[3]{% + \settowidth{\py@argswidth}{#1\sphinxcode{(}}% + \py@argswidth=\dimexpr\linewidth+\labelwidth-\py@argswidth\relax\relax + \item[{#1\sphinxcode{(}\py@sigparams{#2}{#3}}] +% this strange incantation is because at its root LaTeX in fact did not +% imagine a multi-line label, it is always wrapped in a horizontal box at core +% LaTeX level and we have to find tricks to get correct interline distances. + \leavevmode\par\nobreak\vskip-\parskip\prevdepth\dp\strutbox} +\newcommand{\pysigstartmultiline}{% + \def\pysigstartmultiline{\vskip\smallskipamount\parskip\z@skip\itemsep\z@skip}% + \edef\pysigstopmultiline + {\noexpand\leavevmode\parskip\the\parskip\relax\itemsep\the\itemsep\relax}% + \parskip\z@skip\itemsep\z@skip +} + +% Production lists +% +\newenvironment{productionlist}{% +% \def\sphinxoptional##1{{\Large[}##1{\Large]}} + \def\production##1##2{\\\sphinxcode{\sphinxupquote{##1}}&::=&\sphinxcode{\sphinxupquote{##2}}}% + \def\productioncont##1{\\& &\sphinxcode{\sphinxupquote{##1}}}% + \parindent=2em + \indent + \setlength{\LTpre}{0pt}% + \setlength{\LTpost}{0pt}% + \begin{longtable}[l]{lcl} +}{% + \end{longtable} +} + +% Definition lists; requested by AMK for HOWTO documents. Probably useful +% elsewhere as well, so keep in in the general style support. +% +\newenvironment{definitions}{% + \begin{description}% + \def\term##1{\item[{##1}]\mbox{}\\*[0mm]}% +}{% + \end{description}% +} + +%% FROM DOCTUTILS LATEX WRITER +% +% The following is stuff copied from docutils' latex writer. +% +\newcommand{\optionlistlabel}[1]{\normalfont\bfseries #1 \hfill}% \bf deprecated +\newenvironment{optionlist}[1] +{\begin{list}{} + {\setlength{\labelwidth}{#1} + \setlength{\rightmargin}{1cm} + \setlength{\leftmargin}{\rightmargin} + \addtolength{\leftmargin}{\labelwidth} + \addtolength{\leftmargin}{\labelsep} + \renewcommand{\makelabel}{\optionlistlabel}} +}{\end{list}} + +\newlength{\lineblockindentation} +\setlength{\lineblockindentation}{2.5em} +\newenvironment{lineblock}[1] +{\begin{list}{} + {\setlength{\partopsep}{\parskip} + \addtolength{\partopsep}{\baselineskip} + \topsep0pt\itemsep0.15\baselineskip\parsep0pt + \leftmargin#1\relax} + \raggedright} +{\end{list}} + +% From docutils.writers.latex2e +% inline markup (custom roles) +% \DUrole{#1}{#2} tries \DUrole#1{#2} +\providecommand*{\DUrole}[2]{% + \ifcsname DUrole\detokenize{#1}\endcsname + \csname DUrole\detokenize{#1}\endcsname{#2}% + \else% backwards compatibility: try \docutilsrole#1{#2} + \ifcsname docutilsrole\detokenize{#1}\endcsname + \csname docutilsrole\detokenize{#1}\endcsname{#2}% + \else + #2% + \fi + \fi +} + +\providecommand*{\DUprovidelength}[2]{% + \ifdefined#1\else\newlength{#1}\setlength{#1}{#2}\fi +} + +\DUprovidelength{\DUlineblockindent}{2.5em} +\ifdefined\DUlineblock\else + \newenvironment{DUlineblock}[1]{% + \list{}{\setlength{\partopsep}{\parskip} + \addtolength{\partopsep}{\baselineskip} + \setlength{\topsep}{0pt} + \setlength{\itemsep}{0.15\baselineskip} + \setlength{\parsep}{0pt} + \setlength{\leftmargin}{#1}} + \raggedright + } + {\endlist} +\fi + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxlatexshadowbox.sty b/krb5-1.21.3/doc/pdf/sphinxlatexshadowbox.sty new file mode 100644 index 00000000..8d6c7866 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxlatexshadowbox.sty @@ -0,0 +1,100 @@ +%% TOPIC AND CONTENTS BOXES +% +% change this info string if making any custom modification +\ProvidesFile{sphinxlatexshadowbox.sty}[2021/01/27 sphinxShadowBox] + +% Provides support for this output mark-up from Sphinx latex writer: +% +% - sphinxShadowBox (environment) +% +% Dependencies (they do not need to be defined at time of loading): +% +% - of course the various colour and dimension options handled via sphinx.sty +% - dimension register \spx@image@maxheight from sphinxlatexgraphics.sty +% - \savenotes/\spewnotes from sphinxpackagefootnote +% - \ifspx@inframed defined in sphinx.sty +% +% Requires: +\RequirePackage{framed} + +% Again based on use of "framed.sty", this allows breakable framed boxes. +\long\def\spx@ShadowFBox#1{% + \leavevmode\begingroup + % first we frame the box #1 + \setbox\@tempboxa + \hbox{\vrule\@width\sphinxshadowrule + \vbox{\hrule\@height\sphinxshadowrule + \kern\sphinxshadowsep + \hbox{\kern\sphinxshadowsep #1\kern\sphinxshadowsep}% + \kern\sphinxshadowsep + \hrule\@height\sphinxshadowrule}% + \vrule\@width\sphinxshadowrule}% + % Now we add the shadow, like \shadowbox from fancybox.sty would do + \dimen@\dimexpr.5\sphinxshadowrule+\sphinxshadowsize\relax + \hbox{\vbox{\offinterlineskip + \hbox{\copy\@tempboxa\kern-.5\sphinxshadowrule + % add shadow on right side + \lower\sphinxshadowsize + \hbox{\vrule\@height\ht\@tempboxa \@width\dimen@}% + }% + \kern-\dimen@ % shift back vertically to bottom of frame + % and add shadow at bottom + \moveright\sphinxshadowsize + \vbox{\hrule\@width\wd\@tempboxa \@height\dimen@}% + }% + % move left by the size of right shadow so shadow adds no width + \kern-\sphinxshadowsize + }% + \endgroup +} + +% use framed.sty to allow page breaks in frame+shadow +% works well inside Lists and Quote-like environments +% produced by ``topic'' directive (or local contents) +% could nest if LaTeX writer authorized it +\newenvironment{sphinxShadowBox} + {\def\FrameCommand {\spx@ShadowFBox }% + \advance\spx@image@maxheight + -\dimexpr2\sphinxshadowrule + +2\sphinxshadowsep + +\sphinxshadowsize + +\baselineskip\relax + % configure framed.sty not to add extra vertical spacing + \ltx@ifundefined{OuterFrameSep}{}{\OuterFrameSep\z@skip}% + % the \trivlist will add the vertical spacing on top and bottom which is + % typical of center environment as used in Sphinx <= 1.4.1 + % the \noindent has the effet of an extra blank line on top, to + % imitate closely the layout from Sphinx <= 1.4.1; the \FrameHeightAdjust + % will put top part of frame on this baseline. + \def\FrameHeightAdjust {\baselineskip}% + % use package footnote to handle footnotes + \savenotes + \trivlist\item\noindent + % use a minipage if we are already inside a framed environment + \ifspx@inframed\begin{minipage}{\linewidth}\fi + \MakeFramed {\spx@inframedtrue + % framed.sty puts into "\width" the added width (=2shadowsep+2shadowrule) + % adjust \hsize to what the contents must use + \advance\hsize-\width + % adjust LaTeX parameters to behave properly in indented/quoted contexts + \FrameRestore + % typeset the contents as in a minipage (Sphinx <= 1.4.1 used a minipage and + % itemize/enumerate are therein typeset more tightly, we want to keep + % that). We copy-paste from LaTeX source code but don't do a real minipage. + \@pboxswfalse + \let\@listdepth\@mplistdepth \@mplistdepth\z@ + \@minipagerestore + \@setminipage + }% + }% + {% insert the "endminipage" code + \par\unskip + \@minipagefalse + \endMakeFramed + \ifspx@inframed\end{minipage}\fi + \endtrivlist + % output the stored footnotes + \spewnotes + } + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxlatexstyleheadings.sty b/krb5-1.21.3/doc/pdf/sphinxlatexstyleheadings.sty new file mode 100644 index 00000000..fa9be82b --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxlatexstyleheadings.sty @@ -0,0 +1,83 @@ +%% TITLES +% +% change this info string if making any custom modification +\ProvidesFile{sphinxlatexstyleheadings.sty}[2021/01/27 headings] + +\RequirePackage[nobottomtitles*]{titlesec} +\@ifpackagelater{titlesec}{2016/03/15}% + {\@ifpackagelater{titlesec}{2016/03/21}% + {}% + {\newif\ifsphinx@ttlpatch@ok + \IfFileExists{etoolbox.sty}{% + \RequirePackage{etoolbox}% + \patchcmd{\ttlh@hang}{\parindent\z@}{\parindent\z@\leavevmode}% + {\sphinx@ttlpatch@oktrue}{}% + \ifsphinx@ttlpatch@ok + \patchcmd{\ttlh@hang}{\noindent}{}{}{\sphinx@ttlpatch@okfalse}% + \fi + }{}% + \ifsphinx@ttlpatch@ok + \typeout{^^J Package Sphinx Info: ^^J + **** titlesec 2.10.1 successfully patched for bugfix ****^^J}% + \else + \AtEndDocument{\PackageWarningNoLine{sphinx}{^^J% +******** titlesec 2.10.1 has a bug, (section numbers disappear) ......|^^J% +******** and Sphinx could not patch it, perhaps because your local ...|^^J% +******** copy is already fixed without a changed release date. .......|^^J% +******** If not, you must update titlesec! ...........................|}}% + \fi + }% + }{} + +% Augment the sectioning commands used to get our own font family in place, +% and reset some internal data items (\titleformat from titlesec package) +\titleformat{\section}{\Large\py@HeaderFamily}% + {\py@TitleColor\thesection}{0.5em}{\py@TitleColor} +\titleformat{\subsection}{\large\py@HeaderFamily}% + {\py@TitleColor\thesubsection}{0.5em}{\py@TitleColor} +\titleformat{\subsubsection}{\py@HeaderFamily}% + {\py@TitleColor\thesubsubsection}{0.5em}{\py@TitleColor} +% By default paragraphs (and subsubsections) will not be numbered because +% sphinxmanual.cls and sphinxhowto.cls set secnumdepth to 2 +\titleformat{\paragraph}{\py@HeaderFamily}% + {\py@TitleColor\theparagraph}{0.5em}{\py@TitleColor} +\titleformat{\subparagraph}{\py@HeaderFamily}% + {\py@TitleColor\thesubparagraph}{0.5em}{\py@TitleColor} + + +% Since Sphinx 1.5, users should use HeaderFamily key to 'sphinxsetup' rather +% than defining their own \py@HeaderFamily command (which is still possible). +% Memo: \py@HeaderFamily is also used by \maketitle as defined in +% sphinxmanual.cls/sphinxhowto.cls +\newcommand{\py@HeaderFamily}{\spx@opt@HeaderFamily} + +% This sets up the fancy chapter headings that make the documents look +% at least a little better than the usual LaTeX output. +\@ifpackagewith{fncychap}{Bjarne}{ + \ChNameVar {\raggedleft\normalsize \py@HeaderFamily} + \ChNumVar {\raggedleft\Large \py@HeaderFamily} + \ChTitleVar{\raggedleft\Large \py@HeaderFamily} + % This creates (numbered) chapter heads without the leading \vspace*{}: + \def\@makechapterhead#1{% + {\parindent \z@ \raggedright \normalfont + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter + \DOCH + \fi + \fi + \interlinepenalty\@M + \if@mainmatter + \DOTI{#1}% + \else% + \DOTIS{#1}% + \fi + }} +}{}% <-- "false" clause of \@ifpackagewith + +% fix fncychap's bug which uses prematurely the \textwidth value +\@ifpackagewith{fncychap}{Bjornstrup} + {\AtBeginDocument{\mylen\textwidth\advance\mylen-2\myhi}}% + {}% <-- "false" clause of \@ifpackagewith + + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxlatexstylepage.sty b/krb5-1.21.3/doc/pdf/sphinxlatexstylepage.sty new file mode 100644 index 00000000..4066129b --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxlatexstylepage.sty @@ -0,0 +1,79 @@ +%% PAGE STYLING +% +% change this info string if making any custom modification +\ProvidesFile{sphinxlatexstylepage.sty}[2021/01/27 page styling] + +% Separate paragraphs by space by default. +\IfFileExists{parskip-2001-04-09.sty}% since September 2018 TeXLive update +% new parskip.sty, but let it rollback to old one. +% hopefully TeX installation not broken and LaTeX kernel not too old + {\RequirePackage{parskip}[=v1]} +% standard one from 1989. Admittedly \section of article/book gives possibly +% anomalous spacing, but we can't require September 2018 release for some time. + {\RequirePackage{parskip}} + +% Style parameters and macros used by most documents here +\raggedbottom +\sloppy +\hbadness = 5000 % don't print trivial gripes + +% Require package fancyhdr except under memoir class +\@ifclassloaded{memoir}{}{\RequirePackage{fancyhdr}} +% Use \pagestyle{normal} as the primary pagestyle for text. +% Redefine the 'normal' header/footer style when using "fancyhdr" package: +\@ifpackageloaded{fancyhdr}{% + \ltx@ifundefined{c@chapter} + {% no \chapter, "howto" (non-Japanese) docclass + \fancypagestyle{plain}{ + \fancyhf{} + \fancyfoot[C]{{\py@HeaderFamily\thepage}} + \renewcommand{\headrulewidth}{0pt} + \renewcommand{\footrulewidth}{0pt} + } + % Same as 'plain', this way we can use it in template + % FIXME: shouldn't this have a running header with Name and Release like 'manual'? + \fancypagestyle{normal}{ + \fancyhf{} + \fancyfoot[C]{{\py@HeaderFamily\thepage}} + \renewcommand{\headrulewidth}{0pt} + \renewcommand{\footrulewidth}{0pt} + } + }% + {% classes with \chapter command + \fancypagestyle{normal}{ + \fancyhf{} + \fancyfoot[RO]{{\py@HeaderFamily\thepage}} + \fancyfoot[LO]{{\py@HeaderFamily\nouppercase{\rightmark}}} + \fancyhead[RO]{{\py@HeaderFamily \@title\sphinxheadercomma\py@release}} + \if@twoside + \fancyfoot[LE]{{\py@HeaderFamily\thepage}} + \fancyfoot[RE]{{\py@HeaderFamily\nouppercase{\leftmark}}} + \fancyhead[LE]{{\py@HeaderFamily \@title\sphinxheadercomma\py@release}} + \fi + \renewcommand{\headrulewidth}{0.4pt} + \renewcommand{\footrulewidth}{0.4pt} + % define chaptermark with \@chappos when \@chappos is available for Japanese + \ltx@ifundefined{@chappos}{} + {\def\chaptermark##1{\markboth{\@chapapp\space\thechapter\space\@chappos\space ##1}{}}} + } + % Update the plain style so we get the page number & footer line, + % but not a chapter or section title. This is to keep the first + % page of a chapter `clean.' + \fancypagestyle{plain}{ + \fancyhf{} + \fancyfoot[RO]{{\py@HeaderFamily\thepage}} + \if@twoside\fancyfoot[LE]{{\py@HeaderFamily\thepage}}\fi + \renewcommand{\headrulewidth}{0pt} + \renewcommand{\footrulewidth}{0.4pt} + } + } + } + {% no fancyhdr: memoir class + % Provide default for 'normal' style simply as an alias of 'plain' style + % This way we can use \pagestyle{normal} in LaTeX template + \def\ps@normal{\ps@plain} + % Users of memoir class are invited to redefine 'normal' style in preamble + } + + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxlatexstyletext.sty b/krb5-1.21.3/doc/pdf/sphinxlatexstyletext.sty new file mode 100644 index 00000000..ab50aed5 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxlatexstyletext.sty @@ -0,0 +1,126 @@ +%% TEXT STYLING +% +% change this info string if making any custom modification +\ProvidesFile{sphinxlatexstyletext.sty}[2021/01/27 text styling] + +% Basically everything here consists of macros which are part of the latex +% markup produced by the Sphinx latex writer + +% Some custom font markup commands. +\protected\def\sphinxstrong#1{\textbf{#1}} +\protected\def\sphinxcode#1{\texttt{#1}} +\protected\def\sphinxbfcode#1{\textbf{\sphinxcode{#1}}} +\protected\def\sphinxemail#1{\textsf{#1}} +\protected\def\sphinxtablecontinued#1{\textsf{#1}} +\protected\def\sphinxtitleref#1{\emph{#1}} +\protected\def\sphinxmenuselection#1{\emph{#1}} +\protected\def\sphinxguilabel#1{\emph{#1}} +\protected\def\sphinxkeyboard#1{\sphinxcode{#1}} +\protected\def\sphinxaccelerator#1{\underline{#1}} +\protected\def\sphinxcrossref#1{\emph{#1}} +\protected\def\sphinxtermref#1{\emph{#1}} +% \optional is used for ``[, arg]``, i.e. desc_optional nodes. +\long\protected\def\sphinxoptional#1{% + {\textnormal{\Large[}}{#1}\hspace{0.5mm}{\textnormal{\Large]}}} + +% additional customizable styling +\def\sphinxstyleindexentry #1{\texttt{#1}} +\def\sphinxstyleindexextra #1{ (\emph{#1})} +\def\sphinxstyleindexpageref #1{, \pageref{#1}} +\def\sphinxstyleindexpagemain#1{\textbf{#1}} +\def\spxentry{\@backslashchar spxentry}% let to \sphinxstyleindexentry in index +\def\spxextra{\@backslashchar spxextra}% let to \sphinxstyleindexextra in index +\def\sphinxstyleindexlettergroup #1% + {{\Large\sffamily#1}\nopagebreak\vspace{1mm}} +\def\sphinxstyleindexlettergroupDefault #1% + {{\Large\sffamily\sphinxnonalphabeticalgroupname}\nopagebreak\vspace{1mm}} +\protected\def\sphinxstyletopictitle #1{\textbf{#1}\par\medskip} +\let\sphinxstylesidebartitle\sphinxstyletopictitle +\protected\def\sphinxstyleothertitle #1{\textbf{#1}} +\protected\def\sphinxstylesidebarsubtitle #1{~\\\textbf{#1} \smallskip} +% \text.. commands do not allow multiple paragraphs +\protected\def\sphinxstyletheadfamily {\sffamily} +\protected\def\sphinxstyleemphasis #1{\emph{#1}} +\protected\def\sphinxstyleliteralemphasis#1{\emph{\sphinxcode{#1}}} +\protected\def\sphinxstylestrong #1{\textbf{#1}} +\protected\def\sphinxstyleliteralstrong#1{\sphinxbfcode{#1}} +\protected\def\sphinxstyleabbreviation #1{\textsc{#1}} +\protected\def\sphinxstyleliteralintitle#1{\sphinxcode{#1}} +\newcommand*\sphinxstylecodecontinued[1]{\footnotesize(#1)}% +\newcommand*\sphinxstylecodecontinues[1]{\footnotesize(#1)}% +% figure legend comes after caption and may contain arbitrary body elements +\newenvironment{sphinxlegend}{\par\small}{\par} +% reduce hyperref "Token not allowed in a PDF string" warnings on PDF builds +\AtBeginDocument{\pdfstringdefDisableCommands{% +% all "protected" macros possibly ending up in section titles should be here +% TODO: examine if \sphinxhref, \sphinxurl, \sphinnolinkurl should be handled + \let\sphinxstyleemphasis \@firstofone + \let\sphinxstyleliteralemphasis \@firstofone + \let\sphinxstylestrong \@firstofone + \let\sphinxstyleliteralstrong \@firstofone + \let\sphinxstyleabbreviation \@firstofone + \let\sphinxstyleliteralintitle \@firstofone + \let\sphinxupquote \@firstofone + \let\sphinxstrong \@firstofone + \let\sphinxcode \@firstofone + \let\sphinxbfcode \@firstofone + \let\sphinxemail \@firstofone + \let\sphinxcrossref \@firstofone + \let\sphinxtermref \@firstofone + \let\sphinxhyphen\sphinxhyphenforbookmarks +}} + +% Special characters +% +% This definition prevents en-dash and em-dash TeX ligatures. +% +% It inserts a potential breakpoint after the hyphen. This is to keep in sync +% with behavior in code-blocks, parsed and inline literals. For a breakpoint +% before the hyphen use \leavevmode\kern\z@- (within \makeatletter/\makeatother) +\protected\def\sphinxhyphen#1{-\kern\z@} +% The {} from texescape mark-up is kept, else -- gives en-dash in PDF bookmark +\def\sphinxhyphenforbookmarks{-} + +% For curly braces inside \index macro +\def\sphinxleftcurlybrace{\{} +\def\sphinxrightcurlybrace{\}} + +% Declare Unicode characters used by linux tree command to pdflatex utf8/utf8x +\def\spx@bd#1#2{% + \leavevmode + \begingroup + \ifx\spx@bd@height \@undefined\def\spx@bd@height{\baselineskip}\fi + \ifx\spx@bd@width \@undefined\setbox0\hbox{0}\def\spx@bd@width{\wd0 }\fi + \ifx\spx@bd@thickness\@undefined\def\spx@bd@thickness{.6\p@}\fi + \ifx\spx@bd@lower \@undefined\def\spx@bd@lower{\dp\strutbox}\fi + \lower\spx@bd@lower#1{#2}% + \endgroup +}% +\@namedef{sphinx@u2500}% BOX DRAWINGS LIGHT HORIZONTAL + {\spx@bd{\vbox to\spx@bd@height} + {\vss\hrule\@height\spx@bd@thickness + \@width\spx@bd@width\vss}}% +\@namedef{sphinx@u2502}% BOX DRAWINGS LIGHT VERTICAL + {\spx@bd{\hb@xt@\spx@bd@width} + {\hss\vrule\@height\spx@bd@height + \@width \spx@bd@thickness\hss}}% +\@namedef{sphinx@u2514}% BOX DRAWINGS LIGHT UP AND RIGHT + {\spx@bd{\hb@xt@\spx@bd@width} + {\hss\raise.5\spx@bd@height + \hb@xt@\z@{\hss\vrule\@height.5\spx@bd@height + \@width \spx@bd@thickness\hss}% + \vbox to\spx@bd@height{\vss\hrule\@height\spx@bd@thickness + \@width.5\spx@bd@width\vss}}}% +\@namedef{sphinx@u251C}% BOX DRAWINGS LIGHT VERTICAL AND RIGHT + {\spx@bd{\hb@xt@\spx@bd@width} + {\hss + \hb@xt@\z@{\hss\vrule\@height\spx@bd@height + \@width \spx@bd@thickness\hss}% + \vbox to\spx@bd@height{\vss\hrule\@height\spx@bd@thickness + \@width.5\spx@bd@width\vss}}}% +\protected\def\sphinxunichar#1{\@nameuse{sphinx@u#1}}% + +% Tell TeX about pathological hyphenation cases: +\hyphenation{Base-HTTP-Re-quest-Hand-ler} + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxlatextables.sty b/krb5-1.21.3/doc/pdf/sphinxlatextables.sty new file mode 100644 index 00000000..c3c1d6ad --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxlatextables.sty @@ -0,0 +1,481 @@ +%% TABLES (WITH SUPPORT FOR MERGED CELLS OF GENERAL CONTENTS) +% +% change this info string if making any custom modification +\ProvidesFile{sphinxlatextables.sty}[2021/01/27 tables]% + +% Provides support for this output mark-up from Sphinx latex writer +% and table templates: +% +% - the tabulary and longtable environments from the eponymous packages +% - the varwidth environment +% - the >{} etc mark-up possible in tabularcolumns is from array package +% which is loaded by longtable and tabulary +% - \X, \Y, T column types; others (L, C, R, J) are from tabulary package +% - \sphinxaftertopcaption +% - \sphinxatlongtableend +% - \sphinxatlongtablestart +% - \sphinxattableend +% - \sphinxattablestart +% - \sphinxcapstartof +% - \sphinxcolwidth +% - \sphinxlongtablecapskipadjust +% - \sphinxmultirow +% - \sphinxstartmulticolumn +% - \sphinxstopmulticolumn +% - \sphinxtablestrut +% - \sphinxthecaptionisattop +% - \sphinxthelongtablecaptionisattop +% +% Executes \RequirePackage for: +% +% - tabulary +% - longtable +% - varwidth +% +% Extends tabulary and longtable via patches and custom macros to support +% merged cells possibly containing code-blocks in complex tables + +\RequirePackage{tabulary} +% tabulary has a bug with its re-definition of \multicolumn in its first pass +% which is not \long. But now Sphinx does not use LaTeX's \multicolumn but its +% own macro. Hence we don't even need to patch tabulary. See +% sphinxpackagemulticell.sty +% X or S (Sphinx) may have meanings if some table package is loaded hence +% \X was chosen to avoid possibility of conflict +\newcolumntype{\X}[2]{p{\dimexpr + (\linewidth-\arrayrulewidth)*#1/#2-\tw@\tabcolsep-\arrayrulewidth\relax}} +\newcolumntype{\Y}[1]{p{\dimexpr + #1\dimexpr\linewidth-\arrayrulewidth\relax-\tw@\tabcolsep-\arrayrulewidth\relax}} +% using here T (for Tabulary) feels less of a problem than the X could be +\newcolumntype{T}{J}% +% For tables allowing pagebreaks +\RequirePackage{longtable} +% User interface to set-up whitespace before and after tables: +\newcommand*\sphinxtablepre {0pt}% +\newcommand*\sphinxtablepost{\medskipamount}% +% Space from caption baseline to top of table or frame of literal-block +\newcommand*\sphinxbelowcaptionspace{.5\sphinxbaselineskip}% +% as one can not use \baselineskip from inside longtable (it is zero there) +% we need \sphinxbaselineskip, which defaults to \baselineskip +\def\sphinxbaselineskip{\baselineskip}% +% The following is to ensure that, whether tabular(y) or longtable: +% - if a caption is on top of table: +% a) the space between its last baseline and the top rule of table is +% exactly \sphinxbelowcaptionspace +% b) the space from last baseline of previous text to first baseline of +% caption is exactly \parskip+\baselineskip+ height of a strut. +% c) the caption text will wrap at width \LTcapwidth (4in) +% - make sure this works also if "caption" package is loaded by user +% (with its width or margin option taking place of \LTcapwidth role) +% TODO: obtain same for caption of literal block: a) & c) DONE, b) TO BE DONE +% +% To modify space below such top caption, adjust \sphinxbelowcaptionspace +% To add or remove space above such top caption, adjust \sphinxtablepre: +% notice that \abovecaptionskip, \belowcaptionskip, \LTpre are **ignored** +% A. Table with longtable +\def\sphinxatlongtablestart + {\par + \vskip\parskip + \vskip\dimexpr\sphinxtablepre\relax % adjust vertical position + \vbox{}% get correct baseline from above + \LTpre\z@skip\LTpost\z@skip % set to zero longtable's own skips + \edef\sphinxbaselineskip{\dimexpr\the\dimexpr\baselineskip\relax\relax}% + }% +% Compatibility with caption package +\def\sphinxthelongtablecaptionisattop{% + \spx@ifcaptionpackage{\noalign{\vskip-\belowcaptionskip}}{}% +}% +% Achieves exactly \sphinxbelowcaptionspace below longtable caption +\def\sphinxlongtablecapskipadjust + {\dimexpr-\dp\strutbox + -\spx@ifcaptionpackage{\abovecaptionskip}{\sphinxbaselineskip}% + +\sphinxbelowcaptionspace\relax}% +\def\sphinxatlongtableend{\@nobreakfalse % latex3/latex2e#173 + \prevdepth\z@\vskip\sphinxtablepost\relax}% +% B. Table with tabular or tabulary +\def\sphinxattablestart{\par\vskip\dimexpr\sphinxtablepre\relax}% +\let\sphinxattableend\sphinxatlongtableend +% This is used by tabular and tabulary templates +\newcommand*\sphinxcapstartof[1]{% + \vskip\parskip + \vbox{}% force baselineskip for good positioning by capstart of hyperanchor + % hyperref puts the anchor 6pt above this baseline; in case of caption + % this baseline will be \ht\strutbox above first baseline of caption + \def\@captype{#1}% + \capstart +% move back vertically, as tabular (or its caption) will compensate + \vskip-\baselineskip\vskip-\parskip +}% +\def\sphinxthecaptionisattop{% locate it after \sphinxcapstartof + \spx@ifcaptionpackage + {\caption@setposition{t}% + \vskip\baselineskip\vskip\parskip % undo those from \sphinxcapstartof + \vskip-\belowcaptionskip % anticipate caption package skip + % caption package uses a \vbox, not a \vtop, so "single line" case + % gives different result from "multi-line" without this: + \nointerlineskip + }% + {}% +}% +\def\sphinxthecaptionisatbottom{% (not finalized; for template usage) + \spx@ifcaptionpackage{\caption@setposition{b}}{}% +}% +% The aim of \sphinxcaption is to apply to tabular(y) the maximal width +% of caption as done by longtable +\def\sphinxtablecapwidth{\LTcapwidth}% +\newcommand\sphinxcaption{\@dblarg\spx@caption}% +\long\def\spx@caption[#1]#2{% + \noindent\hb@xt@\linewidth{\hss + \vtop{\@tempdima\dimexpr\sphinxtablecapwidth\relax +% don't exceed linewidth for the caption width + \ifdim\@tempdima>\linewidth\hsize\linewidth\else\hsize\@tempdima\fi +% longtable ignores \abovecaptionskip/\belowcaptionskip, so do the same here + \abovecaptionskip\sphinxabovecaptionskip % \z@skip + \belowcaptionskip\sphinxbelowcaptionskip % \z@skip + \caption[{#1}]% + {\strut\ignorespaces#2\ifhmode\unskip\@finalstrut\strutbox\fi}% + }\hss}% + \par\prevdepth\dp\strutbox +}% +\def\sphinxabovecaptionskip{\z@skip}% Do not use! Flagged for removal +\def\sphinxbelowcaptionskip{\z@skip}% Do not use! Flagged for removal +% This wrapper of \abovecaptionskip is used in sphinxVerbatim for top +% caption, and with another value in sphinxVerbatimintable +% TODO: To unify space above caption of a code-block with the one above +% caption of a table/longtable, \abovecaptionskip must not be used +% This auxiliary will get renamed and receive a different meaning +% in future. +\def\spx@abovecaptionskip{\abovecaptionskip}% +% Achieve \sphinxbelowcaptionspace below a caption located above a tabular +% or a tabulary +\newcommand\sphinxaftertopcaption +{% + \spx@ifcaptionpackage + {\par\prevdepth\dp\strutbox\nobreak\vskip-\abovecaptionskip}{\nobreak}% + \vskip\dimexpr\sphinxbelowcaptionspace\relax + \vskip-\baselineskip\vskip-\parskip +}% +% varwidth is crucial for our handling of general contents in merged cells +\RequirePackage{varwidth} +% but addition of a compatibility patch with hyperref is needed +% (tested with varwidth v 0.92 Mar 2009) +\AtBeginDocument {% + \let\@@vwid@Hy@raisedlink\Hy@raisedlink + \long\def\@vwid@Hy@raisedlink#1{\@vwid@wrap{\@@vwid@Hy@raisedlink{#1}}}% + \edef\@vwid@setup{% + \let\noexpand\Hy@raisedlink\noexpand\@vwid@Hy@raisedlink % HYPERREF ! + \unexpanded\expandafter{\@vwid@setup}}% +}% + +%%%%%%%%%%%%%%%%%%%%% +% --- MULTICOLUMN --- +% standard LaTeX's \multicolumn +% 1. does not allow verbatim contents, +% 2. interacts very poorly with tabulary. +% +% It is needed to write own macros for Sphinx: to allow code-blocks in merged +% cells rendered by tabular/longtable, and to allow multi-column cells with +% paragraphs to be taken into account sanely by tabulary algorithm for column +% widths. +% +% This requires quite a bit of hacking. First, in Sphinx, the multi-column +% contents will *always* be wrapped in a varwidth environment. The issue +% becomes to pass it the correct target width. We must trick tabulary into +% believing the multicolumn is simply separate columns, else tabulary does not +% incorporate the contents in its algorithm. But then we must clear the +% vertical rules... +% +% configuration of tabulary +\setlength{\tymin}{3\fontcharwd\font`0 }% minimal width of "squeezed" columns +\setlength{\tymax}{10000pt}% allow enough room for paragraphs to "compete" +% we need access to tabulary's final computed width. \@tempdima is too volatile +% to hope it has kept tabulary's value when \sphinxcolwidth needs it. +\newdimen\sphinx@TY@tablewidth +\def\tabulary{% + \def\TY@final{\sphinx@TY@tablewidth\@tempdima\tabular}% + \let\endTY@final\endtabular + \TY@tabular}% +% next hack is needed only if user has set latex_use_latex_multicolumn to True: +% it fixes tabulary's bug with \multicolumn defined "short" in first pass. (if +% upstream tabulary adds a \long, our extra one causes no harm) +\def\sphinx@tempa #1\def\multicolumn#2#3#4#5#6#7#8#9\sphinx@tempa + {\def\TY@tab{#1\long\def\multicolumn####1####2####3{\multispan####1\relax}#9}}% +\expandafter\sphinx@tempa\TY@tab\sphinx@tempa +% +% TN. 1: as \omit is never executed, Sphinx multicolumn does not need to worry +% like standard multicolumn about |l| vs l|. On the other hand it assumes +% columns are separated by a | ... (if not it will add extraneous +% \arrayrulewidth space for each column separation in its estimate of available +% width). +% +% TN. 1b: as Sphinx multicolumn uses neither \omit nor \span, it can not +% (easily) get rid of extra macros from >{...} or <{...} between columns. At +% least, it has been made compatible with colortbl's \columncolor. +% +% TN. 2: tabulary's second pass is handled like tabular/longtable's single +% pass, with the difference that we hacked \TY@final to set in +% \sphinx@TY@tablewidth the final target width as computed by tabulary. This is +% needed only to handle columns with a "horizontal" specifier: "p" type columns +% (inclusive of tabulary's LJRC) holds the target column width in the +% \linewidth dimension. +% +% TN. 3: use of \begin{sphinxmulticolumn}...\end{sphinxmulticolumn} mark-up +% would need some hacking around the fact that groups can not span across table +% cells (the code does inserts & tokens, see TN1b). It was decided to keep it +% simple with \sphinxstartmulticolumn...\sphinxstopmulticolumn. +% +% MEMO about nesting: if sphinxmulticolumn is encountered in a nested tabular +% inside a tabulary it will think to be at top level in the tabulary. But +% Sphinx generates no nested tables, and if some LaTeX macro uses internally a +% tabular this will not have a \sphinxstartmulticolumn within it! +% +\def\sphinxstartmulticolumn{% + \ifx\equation$% $ tabulary's first pass + \expandafter\sphinx@TYI@start@multicolumn + \else % either not tabulary or tabulary's second pass + \expandafter\sphinx@start@multicolumn + \fi +}% +\def\sphinxstopmulticolumn{% + \ifx\equation$% $ tabulary's first pass + \expandafter\sphinx@TYI@stop@multicolumn + \else % either not tabulary or tabulary's second pass + \ignorespaces + \fi +}% +\def\sphinx@TYI@start@multicolumn#1{% + % use \gdef always to avoid stack space build up + \gdef\sphinx@tempa{#1}\begingroup\setbox\z@\hbox\bgroup +}% +\def\sphinx@TYI@stop@multicolumn{\egroup % varwidth was used with \tymax + \xdef\sphinx@tempb{\the\dimexpr\wd\z@/\sphinx@tempa}% per column width + \endgroup + \expandafter\sphinx@TYI@multispan\expandafter{\sphinx@tempa}% +}% +\def\sphinx@TYI@multispan #1{% + \kern\sphinx@tempb\ignorespaces % the per column occupied width + \ifnum#1>\@ne % repeat, taking into account subtleties of TeX's & ... + \expandafter\sphinx@TYI@multispan@next\expandafter{\the\numexpr#1-\@ne\expandafter}% + \fi +}% +\def\sphinx@TYI@multispan@next{&\relax\sphinx@TYI@multispan}% +% +% Now the branch handling either the second pass of tabulary or the single pass +% of tabular/longtable. This is the delicate part where we gather the +% dimensions from the p columns either set-up by tabulary or by user p column +% or Sphinx \X, \Y columns. The difficulty is that to get the said width, the +% template must be inserted (other hacks would be horribly complicated except +% if we rewrote crucial parts of LaTeX's \@array !) and we can not do +% \omit\span like standard \multicolumn's easy approach. Thus we must cancel +% the \vrule separators. Also, perhaps the column specifier is of the l, c, r +% type, then we attempt an ad hoc rescue to give varwidth a reasonable target +% width. +\def\sphinx@start@multicolumn#1{% + \gdef\sphinx@multiwidth{0pt}\gdef\sphinx@tempa{#1}\sphinx@multispan{#1}% +}% +\def\sphinx@multispan #1{% + \ifnum#1=\@ne\expandafter\sphinx@multispan@end + \else\expandafter\sphinx@multispan@next + \fi {#1}% +}% +\def\sphinx@multispan@next #1{% + % trick to recognize L, C, R, J or p, m, b type columns + \ifdim\baselineskip>\z@ + \gdef\sphinx@tempb{\linewidth}% + \else + % if in an l, r, c type column, try and hope for the best + \xdef\sphinx@tempb{\the\dimexpr(\ifx\TY@final\@undefined\linewidth\else + \sphinx@TY@tablewidth\fi-\arrayrulewidth)/\sphinx@tempa + -\tw@\tabcolsep-\arrayrulewidth\relax}% + \fi + \noindent\kern\sphinx@tempb\relax + \xdef\sphinx@multiwidth + {\the\dimexpr\sphinx@multiwidth+\sphinx@tempb+\tw@\tabcolsep+\arrayrulewidth}% + % hack the \vline and the colortbl macros + \sphinx@hack@vline\sphinx@hack@CT&\relax + % repeat + \expandafter\sphinx@multispan\expandafter{\the\numexpr#1-\@ne}% +}% +% packages like colortbl add group levels, we need to "climb back up" to be +% able to hack the \vline and also the colortbl inserted tokens. This creates +% empty space whether or not the columns were | separated: +\def\sphinx@hack@vline{\ifnum\currentgrouptype=6\relax + \kern\arrayrulewidth\arrayrulewidth\z@\else\aftergroup\sphinx@hack@vline\fi}% +\def\sphinx@hack@CT{\ifnum\currentgrouptype=6\relax + \let\CT@setup\sphinx@CT@setup\else\aftergroup\sphinx@hack@CT\fi}% +% It turns out \CT@row@color is not expanded contrarily to \CT@column@color +% during LaTeX+colortbl preamble preparation, hence it would be possible for +% \sphinx@CT@setup to discard only the column color and choose to obey or not +% row color and cell color. It would even be possible to propagate cell color +% to row color for the duration of the Sphinx multicolumn... the (provisional?) +% choice has been made to cancel the colortbl colours for the multicolumn +% duration. +\def\sphinx@CT@setup #1\endgroup{\endgroup}% hack to remove colour commands +\def\sphinx@multispan@end#1{% + % first, trace back our steps horizontally + \noindent\kern-\dimexpr\sphinx@multiwidth\relax + % and now we set the final computed width for the varwidth environment + \ifdim\baselineskip>\z@ + \xdef\sphinx@multiwidth{\the\dimexpr\sphinx@multiwidth+\linewidth}% + \else + \xdef\sphinx@multiwidth{\the\dimexpr\sphinx@multiwidth+ + (\ifx\TY@final\@undefined\linewidth\else + \sphinx@TY@tablewidth\fi-\arrayrulewidth)/\sphinx@tempa + -\tw@\tabcolsep-\arrayrulewidth\relax}% + \fi + % we need to remove colour set-up also for last cell of the multi-column + \aftergroup\sphinx@hack@CT +}% +\newcommand*\sphinxcolwidth[2]{% + % this dimension will always be used for varwidth, and serves as maximum + % width when cells are merged either via multirow or multicolumn or both, + % as always their contents is wrapped in varwidth environment. + \ifnum#1>\@ne % multi-column (and possibly also multi-row) + % we wrote our own multicolumn code especially to handle that (and allow + % verbatim contents) + \ifx\equation$%$ + \tymax % first pass of tabulary (cf MEMO above regarding nesting) + \else % the \@gobble thing is for compatibility with standard \multicolumn + \sphinx@multiwidth\@gobble{#1/#2}% + \fi + \else % single column multirow + \ifx\TY@final\@undefined % not a tabulary. + \ifdim\baselineskip>\z@ + % in a p{..} type column, \linewidth is the target box width + \linewidth + \else + % l, c, r columns. Do our best. + \dimexpr(\linewidth-\arrayrulewidth)/#2- + \tw@\tabcolsep-\arrayrulewidth\relax + \fi + \else % in tabulary + \ifx\equation$%$% first pass + \tymax % it is set to a big value so that paragraphs can express themselves + \else + % second pass. + \ifdim\baselineskip>\z@ + \linewidth % in a L, R, C, J column or a p, \X, \Y ... + \else + % we have hacked \TY@final to put in \sphinx@TY@tablewidth the table width + \dimexpr(\sphinx@TY@tablewidth-\arrayrulewidth)/#2- + \tw@\tabcolsep-\arrayrulewidth\relax + \fi + \fi + \fi + \fi +}% +% fallback default in case user has set latex_use_latex_multicolumn to True: +% \sphinxcolwidth will use this only inside LaTeX's standard \multicolumn +\def\sphinx@multiwidth #1#2{\dimexpr % #1 to gobble the \@gobble (!) + (\ifx\TY@final\@undefined\linewidth\else\sphinx@TY@tablewidth\fi + -\arrayrulewidth)*#2-\tw@\tabcolsep-\arrayrulewidth\relax}% + +%%%%%%%%%%%%%%%%%% +% --- MULTIROW --- +% standard \multirow +% 1. does not allow verbatim contents, +% 2. does not allow blank lines in its argument, +% 3. its * specifier means to typeset "horizontally" which is very +% bad for paragraph content. 2016 version has = specifier but it +% must be used with p type columns only, else results are bad, +% 4. it requires manual intervention if the contents is too long to fit +% in the asked-for number of rows. +% 5. colour panels (either from \rowcolor or \columncolor) will hide +% the bottom part of multirow text, hence manual tuning is needed +% to put the multirow insertion at the _bottom_. +% +% The Sphinx solution consists in always having contents wrapped +% in a varwidth environment so that it makes sense to estimate how many +% lines it will occupy, and then ensure by insertion of suitable struts +% that the table rows have the needed height. The needed mark-up is done +% by LaTeX writer, which has its own id for the merged cells. +% +% The colour issue is solved by clearing colour panels in all cells, +% whether or not the multirow is single-column or multi-column. +% +% In passing we obtain baseline alignements across rows (only if +% \arraystretch is 1, as LaTeX's does not obey \arraystretch in "p" +% multi-line contents, only first and last line...) +% +% TODO: examine the situation with \arraystretch > 1. The \extrarowheight +% is hopeless for multirow anyhow, it makes baseline alignment strictly +% impossible. +\newcommand\sphinxmultirow[2]{\begingroup + % #1 = nb of spanned rows, #2 = Sphinx id of "cell", #3 = contents + % but let's fetch #3 in a way allowing verbatim contents ! + \def\sphinx@nbofrows{#1}\def\sphinx@cellid{#2}% + \afterassignment\sphinx@multirow\let\next= +}% +\def\sphinx@multirow {% + \setbox\z@\hbox\bgroup\aftergroup\sphinx@@multirow\strut +}% +\def\sphinx@@multirow {% + % The contents, which is a varwidth environment, has been captured in + % \box0 (a \hbox). + % We have with \sphinx@cellid an assigned unique id. The goal is to give + % about the same height to all the involved rows. + % For this Sphinx will insert a \sphinxtablestrut{cell_id} mark-up + % in LaTeX file and the expansion of the latter will do the suitable thing. + \dimen@\dp\z@ + \dimen\tw@\ht\@arstrutbox + \advance\dimen@\dimen\tw@ + \advance\dimen\tw@\dp\@arstrutbox + \count@=\dimen@ % type conversion dim -> int + \count\tw@=\dimen\tw@ + \divide\count@\count\tw@ % TeX division truncates + \advance\dimen@-\count@\dimen\tw@ + % 1300sp is about 0.02pt. For comparison a rule default width is 0.4pt. + % (note that if \count@ holds 0, surely \dimen@>1300sp) + \ifdim\dimen@>1300sp \advance\count@\@ne \fi + % now \count@ holds the count L of needed "lines" + % and \sphinx@nbofrows holds the number N of rows + % we have L >= 1 and N >= 1 + % if L is a multiple of N, ... clear what to do ! + % else write L = qN + r, 1 <= r < N and we will + % arrange for each row to have enough space for: + % q+1 "lines" in each of the first r rows + % q "lines" in each of the (N-r) bottom rows + % for a total of (q+1) * r + q * (N-r) = q * N + r = L + % It is possible that q == 0. + \count\tw@\count@ + % the TeX division truncates + \divide\count\tw@\sphinx@nbofrows\relax + \count4\count\tw@ % q + \multiply\count\tw@\sphinx@nbofrows\relax + \advance\count@-\count\tw@ % r + \expandafter\xdef\csname sphinx@tablestrut_\sphinx@cellid\endcsname + {\noexpand\sphinx@tablestrut{\the\count4}{\the\count@}{\sphinx@cellid}}% + \dp\z@\z@ + % this will use the real height if it is >\ht\@arstrutbox + \sphinxtablestrut{\sphinx@cellid}\box\z@ + \endgroup % group was opened in \sphinxmultirow +}% +\newcommand*\sphinxtablestrut[1]{% + % #1 is a "cell_id", i.e. the id of a merged group of table cells + \csname sphinx@tablestrut_#1\endcsname +}% +% LaTeX typesets the table row by row, hence each execution can do +% an update for the next row. +\newcommand*\sphinx@tablestrut[3]{\begingroup + % #1 = q, #2 = (initially) r, #3 = cell_id, q+1 lines in first r rows + % if #2 = 0, create space for max(q,1) table lines + % if #2 > 0, create space for q+1 lines and decrement #2 + \leavevmode + \count@#1\relax + \ifnum#2=\z@ + \ifnum\count@=\z@\count@\@ne\fi + \else + % next row will be with a #2 decremented by one + \expandafter\xdef\csname sphinx@tablestrut_#3\endcsname + {\noexpand\sphinx@tablestrut{#1}{\the\numexpr#2-\@ne}{#3}}% + \advance\count@\@ne + \fi + \vrule\@height\ht\@arstrutbox + \@depth\dimexpr\count@\ht\@arstrutbox+\count@\dp\@arstrutbox-\ht\@arstrutbox\relax + \@width\z@ + \endgroup + % we need this to avoid colour panels hiding bottom parts of multirow text + \sphinx@hack@CT +}% + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxmanual.cls b/krb5-1.21.3/doc/pdf/sphinxmanual.cls new file mode 100644 index 00000000..2e4b30d9 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxmanual.cls @@ -0,0 +1,128 @@ +% +% sphinxmanual.cls for Sphinx (https://www.sphinx-doc.org/) +% + +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesClass{sphinxmanual}[2019/12/01 v2.3.0 Document class (Sphinx manual)] + +% chapters starting at odd pages (overridden by 'openany' document option) +\PassOptionsToClass{openright}{\sphinxdocclass} + +% 'oneside' option overriding the 'twoside' default +\newif\if@oneside +\DeclareOption{oneside}{\@onesidetrue} +% Pass remaining document options to the parent class. +\DeclareOption*{\PassOptionsToClass{\CurrentOption}{\sphinxdocclass}} +\ProcessOptions\relax + +% Defaults two-side document +\if@oneside +% nothing to do (oneside is the default) +\else +\PassOptionsToClass{twoside}{\sphinxdocclass} +\fi + +\LoadClass{\sphinxdocclass} + +% Set some sane defaults for section numbering depth and TOC depth. You can +% reset these counters in your preamble. +% +\setcounter{secnumdepth}{2} +\setcounter{tocdepth}{1} + +% Adapt \and command to the flushright context of \sphinxmaketitle, to +% avoid ragged line endings if author names do not fit all on one single line +\DeclareRobustCommand{\and}{% + \end{tabular}\kern-\tabcolsep + \allowbreak + \hskip\dimexpr1em+\tabcolsep\@plus.17fil\begin{tabular}[t]{c}% +}% +% If it is desired that each author name be on its own line, use in preamble: +%\DeclareRobustCommand{\and}{% +% \end{tabular}\kern-\tabcolsep\\\begin{tabular}[t]{c}% +%}% +% Change the title page to look a bit better, and fit in with the fncychap +% ``Bjarne'' style a bit better. +% +\newcommand{\sphinxmaketitle}{% + \let\sphinxrestorepageanchorsetting\relax + \ifHy@pageanchor\def\sphinxrestorepageanchorsetting{\Hy@pageanchortrue}\fi + \hypersetup{pageanchor=false}% avoid duplicate destination warnings + \begin{titlepage}% + \let\footnotesize\small + \let\footnoterule\relax + \noindent\rule{\textwidth}{1pt}\par + \begingroup % for PDF information dictionary + \def\endgraf{ }\def\and{\& }% + \pdfstringdefDisableCommands{\def\\{, }}% overwrite hyperref setup + \hypersetup{pdfauthor={\@author}, pdftitle={\@title}}% + \endgroup + \begin{flushright}% + \sphinxlogo + \py@HeaderFamily + {\Huge \@title \par} + {\itshape\LARGE \py@release\releaseinfo \par} + \vfill + {\LARGE + \begin{tabular}[t]{c} + \@author + \end{tabular}\kern-\tabcolsep + \par} + \vfill\vfill + {\large + \@date \par + \vfill + \py@authoraddress \par + }% + \end{flushright}%\par + \@thanks + \end{titlepage}% + \setcounter{footnote}{0}% + \let\thanks\relax\let\maketitle\relax + %\gdef\@thanks{}\gdef\@author{}\gdef\@title{} + \clearpage + \ifdefined\sphinxbackoftitlepage\sphinxbackoftitlepage\fi + \if@openright\cleardoublepage\else\clearpage\fi + \sphinxrestorepageanchorsetting +} + +\newcommand{\sphinxtableofcontents}{% + \pagenumbering{roman}% + \begingroup + \parskip \z@skip + \sphinxtableofcontentshook + \tableofcontents + \endgroup + % before resetting page counter, let's do the right thing. + \if@openright\cleardoublepage\else\clearpage\fi + \pagenumbering{arabic}% +} + +% This is needed to get the width of the section # area wide enough in the +% library reference. Doing it here keeps it the same for all the manuals. +% +\newcommand{\sphinxtableofcontentshook}{% + \renewcommand*\l@section{\@dottedtocline{1}{1.5em}{2.6em}}% + \renewcommand*\l@subsection{\@dottedtocline{2}{4.1em}{3.5em}}% +} + +% Fix the bibliography environment to add an entry to the Table of +% Contents. +% For a report document class this environment is a chapter. +% +\newenvironment{sphinxthebibliography}[1]{% + \if@openright\cleardoublepage\else\clearpage\fi + % \phantomsection % not needed here since TeXLive 2010's hyperref + \begin{thebibliography}{#1}% + \addcontentsline{toc}{chapter}{\bibname}}{\end{thebibliography}} + +% Same for the indices. +% The memoir class already does this, so we don't duplicate it in that case. +% +\@ifclassloaded{memoir} + {\newenvironment{sphinxtheindex}{\begin{theindex}}{\end{theindex}}} + {\newenvironment{sphinxtheindex}{% + \if@openright\cleardoublepage\else\clearpage\fi + \phantomsection % needed as no chapter, section, ... created + \begin{theindex}% + \addcontentsline{toc}{chapter}{\indexname}}{\end{theindex}}} diff --git a/krb5-1.21.3/doc/pdf/sphinxmessages.sty b/krb5-1.21.3/doc/pdf/sphinxmessages.sty new file mode 100644 index 00000000..68ebffa8 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxmessages.sty @@ -0,0 +1,21 @@ +% +% sphinxmessages.sty +% +% message resources for Sphinx +% +\ProvidesPackage{sphinxmessages}[2019/01/04 v2.0 Localized LaTeX macros (Sphinx team)] + +\renewcommand{\literalblockcontinuedname}{continued from previous page} +\renewcommand{\literalblockcontinuesname}{continues on next page} +\renewcommand{\sphinxnonalphabeticalgroupname}{Non\sphinxhyphen{}alphabetical} +\renewcommand{\sphinxsymbolsname}{Symbols} +\renewcommand{\sphinxnumbersname}{Numbers} +\def\pageautorefname{page} + +\addto\captionsenglish{\renewcommand{\figurename}{Fig.\@{} }} +\def\fnum@figure{\figurename\thefigure{}} + +\addto\captionsenglish{\renewcommand{\tablename}{Table }} +\def\fnum@table{\tablename\thetable{}} + +\addto\captionsenglish{\renewcommand{\literalblockname}{Listing}} \ No newline at end of file diff --git a/krb5-1.21.3/doc/pdf/sphinxoptionsgeometry.sty b/krb5-1.21.3/doc/pdf/sphinxoptionsgeometry.sty new file mode 100644 index 00000000..af5a804d --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxoptionsgeometry.sty @@ -0,0 +1,54 @@ +%% OPTIONS FOR GEOMETRY +% +% change this info string if making any custom modification +\ProvidesFile{sphinxoptionsgeometry.sty}[2021/01/27 geometry] + +% geometry +\ifx\kanjiskip\@undefined + \PassOptionsToPackage{% + hmargin={\unexpanded{\spx@opt@hmargin}},% + vmargin={\unexpanded{\spx@opt@vmargin}},% + marginpar=\unexpanded{\spx@opt@marginpar}} + {geometry} +\else + % set text width for Japanese documents to be integer multiple of 1zw + % and text height to be integer multiple of \baselineskip + % the execution is delayed to \sphinxsetup then geometry.sty + \normalsize\normalfont + \newcommand*\sphinxtextwidthja[1]{% + \if@twocolumn\tw@\fi + \dimexpr + \numexpr\dimexpr\paperwidth-\tw@\dimexpr#1\relax\relax/ + \dimexpr\if@twocolumn\tw@\else\@ne\fi zw\relax + zw\relax}% + \newcommand*\sphinxmarginparwidthja[1]{% + \dimexpr\numexpr\dimexpr#1\relax/\dimexpr1zw\relax zw\relax}% + \newcommand*\sphinxtextlinesja[1]{% + \numexpr\@ne+\dimexpr\paperheight-\topskip-\tw@\dimexpr#1\relax\relax/ + \baselineskip\relax}% + \ifx\@jsc@uplatextrue\@undefined\else + % the way we found in order for the papersize special written by + % geometry in the dvi file to be correct in case of jsbook class + \ifnum\mag=\@m\else % do nothing special if nomag class option or 10pt + \PassOptionsToPackage{truedimen}{geometry}% + \fi + \fi + \PassOptionsToPackage{% + hmarginratio={1:1},% + textwidth=\unexpanded{\sphinxtextwidthja{\spx@opt@hmargin}},% + vmarginratio={1:1},% + lines=\unexpanded{\sphinxtextlinesja{\spx@opt@vmargin}},% + marginpar=\unexpanded{\sphinxmarginparwidthja{\spx@opt@marginpar}},% + footskip=2\baselineskip,% + }{geometry}% + \AtBeginDocument + {% update a dimension used by the jsclasses + \ifx\@jsc@uplatextrue\@undefined\else\fullwidth\textwidth\fi + % for some reason, jreport normalizes all dimensions with \@settopoint + \@ifclassloaded{jreport} + {\@settopoint\textwidth\@settopoint\textheight\@settopoint\marginparwidth} + {}% <-- "false" clause of \@ifclassloaded + }% +\fi + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxoptionshyperref.sty b/krb5-1.21.3/doc/pdf/sphinxoptionshyperref.sty new file mode 100644 index 00000000..b88f108d --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxoptionshyperref.sty @@ -0,0 +1,35 @@ +%% Bookmarks and hyperlinks +% +% change this info string if making any custom modification +\ProvidesFile{sphinxoptionshyperref.sty}[2021/01/27 hyperref] + +% to make pdf with correct encoded bookmarks in Japanese +% this should precede the hyperref package +\ifx\kanjiskip\@undefined +% for non-Japanese: make sure bookmarks are ok also with lualatex + \PassOptionsToPackage{pdfencoding=unicode}{hyperref} +\else + \RequirePackage{atbegshi} + \ifx\ucs\@undefined + \ifnum 42146=\euc"A4A2 + \AtBeginShipoutFirst{\special{pdf:tounicode EUC-UCS2}} + \else + \AtBeginShipoutFirst{\special{pdf:tounicode 90ms-RKSJ-UCS2}} + \fi + \else + \AtBeginShipoutFirst{\special{pdf:tounicode UTF8-UCS2}} + \fi +\fi + +\ifx\@jsc@uplatextrue\@undefined\else + \PassOptionsToPackage{setpagesize=false}{hyperref} +\fi + +% These options can be overridden inside 'hyperref' key +% or by later use of \hypersetup. +\PassOptionsToPackage{colorlinks,breaklinks,% + linkcolor=InnerLinkColor,filecolor=OuterLinkColor,% + menucolor=OuterLinkColor,urlcolor=OuterLinkColor,% + citecolor=InnerLinkColor}{hyperref} + +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxpackagecyrillic.sty b/krb5-1.21.3/doc/pdf/sphinxpackagecyrillic.sty new file mode 100644 index 00000000..9aa62fc2 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxpackagecyrillic.sty @@ -0,0 +1,55 @@ +%% CYRILLIC IN NON-CYRILLIC DOCUMENTS (pdflatex only) +% +% refs: https://tex.stackexchange.com/q/460271/ +\ProvidesPackage{sphinxpackagecyrillic}% + [2018/11/21 v2.0 support for Cyrillic in non-Cyrillic documents] +\RequirePackage{kvoptions} +\SetupKeyvalOptions{prefix=spx@cyropt@} % use \spx@cyropt@ prefix +\DeclareBoolOption[false]{Xtwo} +\DeclareBoolOption[false]{TtwoA} +\DeclareDefaultOption{\@unknownoptionerror} +\ProcessLocalKeyvalOptions* % ignore class options + +\ifspx@cyropt@Xtwo +% original code by tex.sx user egreg (updated 2019/10/28): +% https://tex.stackexchange.com/a/460325/ +% 159 Cyrillic glyphs as available in X2 TeX 8bit font encoding +% This assumes inputenc loaded with utf8 option, or LaTeX release +% as recent as 2018/04/01 which does it automatically. + \@tfor\next:=% + {Ё}{Ђ}{Є}{Ѕ}{І}{Ј}{Љ}{Њ}{Ћ}{Ў}{Џ}{А}{Б}{В}{Г}{Д}{Е}{Ж}{З}{И}{Й}% + {К}{Л}{М}{Н}{О}{П}{Р}{С}{Т}{У}{Ф}{Х}{Ц}{Ч}{Ш}{Щ}{Ъ}{Ы}{Ь}{Э}{Ю}% + {Я}{а}{б}{в}{г}{д}{е}{ж}{з}{и}{й}{к}{л}{м}{н}{о}{п}{р}{с}{т}{у}% + {ф}{х}{ц}{ч}{ш}{щ}{ъ}{ы}{ь}{э}{ю}{я}{ё}{ђ}{є}{ѕ}{і}{ј}{љ}{њ}{ћ}% + {ў}{џ}{Ѣ}{ѣ}{Ѫ}{ѫ}{Ѵ}{ѵ}{Ґ}{ґ}{Ғ}{ғ}{Ҕ}{ҕ}{Җ}{җ}{Ҙ}{ҙ}{Қ}{қ}{Ҝ}{ҝ}% + {Ҟ}{ҟ}{Ҡ}{ҡ}{Ң}{ң}{Ҥ}{ҥ}{Ҧ}{ҧ}{Ҩ}{ҩ}{Ҫ}{ҫ}{Ҭ}{ҭ}{Ү}{ү}{Ұ}{ұ}{Ҳ}{ҳ}% + {Ҵ}{ҵ}{Ҷ}{ҷ}{Ҹ}{ҹ}{Һ}{һ}{Ҽ}{ҽ}{Ҿ}{ҿ}{Ӏ}{Ӄ}{ӄ}{Ӆ}{ӆ}{Ӈ}{ӈ}{Ӌ}{ӌ}% + {Ӎ}{ӎ}{Ӕ}{ӕ}{Ә}{ә}{Ӡ}{ӡ}{Ө}{ө}\do + {% + \begingroup\def\IeC{\protect\DeclareTextSymbolDefault}% + \protected@edef\@temp{\endgroup + \@ifl@t@r{\fmtversion}{2019/10/01}{\csname u8:\next\endcsname}{\next}}% + \@temp{X2}% + }% +\else +\ifspx@cyropt@TtwoA +% original code by tex.sx user jfbu: +% https://tex.stackexchange.com/a/460305/ +% 63*2+1=127 Cyrillic glyphs as found in T2A 8bit TeX font-encoding + \@tfor\@tempa:=% + {ae}{a}{b}{chrdsc}{chvcrs}{ch}{c}{dje}{dze}{dzhe}{d}{erev}{ery}{e}% + {f}{ghcrs}{gup}{g}{hdsc}{hrdsn}{h}{ie}{ii}{ishrt}{i}{je}% + {kbeak}{kdsc}{kvcrs}{k}{lje}{l}{m}{ndsc}{ng}{nje}{n}{otld}{o}{p}{r}% + {schwa}{sdsc}{sftsn}{shch}{shha}{sh}{s}{tshe}{t}{ushrt}{u}{v}% + {ya}{yhcrs}{yi}{yo}{yu}{y}{zdsc}{zhdsc}{zh}{z}\do + {% + \expandafter\DeclareTextSymbolDefault\expandafter + {\csname cyr\@tempa\endcsname}{T2A}% + \expandafter\uppercase\expandafter{\expandafter + \def\expandafter\@tempa\expandafter{\@tempa}}% + \expandafter\DeclareTextSymbolDefault\expandafter + {\csname CYR\@tempa\endcsname}{T2A}% + }% + \DeclareTextSymbolDefault{\CYRpalochka}{T2A}% +\fi\fi +\endinput diff --git a/krb5-1.21.3/doc/pdf/sphinxpackagefootnote.sty b/krb5-1.21.3/doc/pdf/sphinxpackagefootnote.sty new file mode 100644 index 00000000..a6071cf1 --- /dev/null +++ b/krb5-1.21.3/doc/pdf/sphinxpackagefootnote.sty @@ -0,0 +1,396 @@ +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{sphinxpackagefootnote}% + [2021/02/04 v1.1d footnotehyper adapted to sphinx (Sphinx team)] +% Provides support for this output mark-up from Sphinx latex writer: +% - footnote environment +% - savenotes environment (table templates) +% - \sphinxfootnotemark +% +%% +%% Package: sphinxpackagefootnote +%% Version: based on footnotehyper.sty 2021/02/04 v1.1d +%% as available at https://www.ctan.org/pkg/footnotehyper +%% License: the one applying to Sphinx +%% +%% Refer to the PDF documentation at https://www.ctan.org/pkg/footnotehyper for +%% the code comments. +%% +%% Differences: +%% 1. a partial tabulary compatibility layer added (enough for Sphinx mark-up), +%% 2. use of \spx@opt@BeforeFootnote from sphinx.sty, +%% 3. use of \sphinxunactivateextrasandspace from sphinx.sty, +%% 4. macro definition \sphinxfootnotemark, +%% 5. macro definition \sphinxlongtablepatch +%% 6. replaced some \undefined by \@undefined +\newif\iffootnotehyperparse\footnotehyperparsetrue +\DeclareOption*{\PackageWarning{sphinxpackagefootnote}{Option `\CurrentOption' is unknown}}% +\ProcessOptions\relax +\newbox\FNH@notes +\newtoks\FNH@toks % 1.1c +\newdimen\FNH@width +\let\FNH@colwidth\columnwidth +\newif\ifFNH@savingnotes +\AtBeginDocument {% + \let\FNH@latex@footnote \footnote + \let\FNH@latex@footnotetext\footnotetext + \let\FNH@H@@footnotetext \@footnotetext + \let\FNH@H@@mpfootnotetext \@mpfootnotetext + \newenvironment{savenotes} + {\FNH@savenotes\ignorespaces}{\FNH@spewnotes\ignorespacesafterend}% + \let\spewnotes \FNH@spewnotes + \let\footnote \FNH@footnote + \let\footnotetext \FNH@footnotetext + \let\endfootnote \FNH@endfntext + \let\endfootnotetext\FNH@endfntext + \@ifpackageloaded{hyperref} + {\ifHy@hyperfootnotes + \let\FNH@H@@footnotetext\H@@footnotetext + \let\FNH@H@@mpfootnotetext\H@@mpfootnotetext + \else + \let\FNH@hyper@fntext\FNH@nohyp@fntext + \fi}% + {\let\FNH@hyper@fntext\FNH@nohyp@fntext}% +}% +\def\FNH@hyper@fntext{\FNH@fntext\FNH@hyper@fntext@i}% +\def\FNH@nohyp@fntext{\FNH@fntext\FNH@nohyp@fntext@i}% +\def\FNH@fntext #1{% + \ifx\ifmeasuring@\@undefined + \expandafter\@secondoftwo\else\expandafter\@firstofone\fi +% these two lines modified for Sphinx (tabulary compatibility): + {\ifmeasuring@\expandafter\@gobbletwo\else\expandafter\@firstofone\fi}% + {\ifx\equation$\expandafter\@gobbletwo\fi #1}%$ +}% +\long\def\FNH@hyper@fntext@i#1{% + \global\setbox\FNH@notes\vbox + {\unvbox\FNH@notes + \FNH@startnote + \@makefntext + {\rule\z@\footnotesep\ignorespaces + \ifHy@nesting\expandafter\ltx@firstoftwo + \else\expandafter\ltx@secondoftwo + \fi + {\expandafter\hyper@@anchor\expandafter{\Hy@footnote@currentHref}{#1}}% + {\Hy@raisedlink + {\expandafter\hyper@@anchor\expandafter{\Hy@footnote@currentHref}% + {\relax}}% + \let\@currentHref\Hy@footnote@currentHref + \let\@currentlabelname\@empty + #1}% + \@finalstrut\strutbox + }% + \FNH@endnote + }% +}% +\long\def\FNH@nohyp@fntext@i#1{% + \global\setbox\FNH@notes\vbox + {\unvbox\FNH@notes + \FNH@startnote + \@makefntext{\rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}% + \FNH@endnote + }% +}% +\def\FNH@startnote{% + \hsize\FNH@colwidth + \interlinepenalty\interfootnotelinepenalty + \reset@font\footnotesize + \floatingpenalty\@MM + \@parboxrestore + \protected@edef\@currentlabel{\csname p@\@mpfn\endcsname\@thefnmark}% + \color@begingroup +}% +\def\FNH@endnote{\color@endgroup}% +\def\FNH@savenotes{% + \begingroup + \ifFNH@savingnotes\else + \FNH@savingnotestrue + \let\@footnotetext \FNH@hyper@fntext + \let\@mpfootnotetext \FNH@hyper@fntext + \let\H@@mpfootnotetext\FNH@nohyp@fntext + \FNH@width\columnwidth + \let\FNH@colwidth\FNH@width + \global\setbox\FNH@notes\box\voidb@x + \let\FNH@thempfn\thempfn + \let\FNH@mpfn\@mpfn + \ifx\@minipagerestore\relax\let\@minipagerestore\@empty\fi + \expandafter\def\expandafter\@minipagerestore\expandafter{% + \@minipagerestore + \let\thempfn\FNH@thempfn + \let\@mpfn\FNH@mpfn + }% + \fi +}% +\def\FNH@spewnotes {% + \if@endpe\ifx\par\@@par\FNH@toks{}\else + \FNH@toks\expandafter{\expandafter + \def\expandafter\par\expandafter{\par}\@endpetrue}% + \expandafter\expandafter\expandafter + \FNH@toks + \expandafter\expandafter\expandafter + {\expandafter\the\expandafter\FNH@toks + \expandafter\def\expandafter\@par\expandafter{\@par}}% + \expandafter\expandafter\expandafter + \FNH@toks + \expandafter\expandafter\expandafter + {\expandafter\the\expandafter\FNH@toks + \expandafter\everypar\expandafter{\the\everypar}}\fi + \else\FNH@toks{}\fi + \expandafter + \endgroup\the\FNH@toks + \ifFNH@savingnotes\else + \ifvoid\FNH@notes\else + \begingroup + \let\@makefntext\@empty + \let\@finalstrut\@gobble + \let\rule\@gobbletwo + \ifx\@footnotetext\@mpfootnotetext + \expandafter\FNH@H@@mpfootnotetext + \else + \expandafter\FNH@H@@footnotetext + \fi{\unvbox\FNH@notes}% + \endgroup + \fi + \fi +}% +\def\FNH@footnote@envname {footnote}% +\def\FNH@footnotetext@envname{footnotetext}% +\def\FNH@footnote{% +% this line added for Sphinx: + \spx@opt@BeforeFootnote + \ifx\@currenvir\FNH@footnote@envname + \expandafter\FNH@footnoteenv + \else + \expandafter\FNH@latex@footnote + \fi +}% +\def\FNH@footnoteenv{% +% this line added for Sphinx (footnotes in parsed literal blocks): + \catcode13=5 \sphinxunactivateextrasandspace + \@ifnextchar[% + \FNH@footnoteenv@i %] + {\stepcounter\@mpfn + \protected@xdef\@thefnmark{\thempfn}% + \@footnotemark + \def\FNH@endfntext@fntext{\@footnotetext}% + \FNH@startfntext}% +}% +\def\FNH@footnoteenv@i[#1]{% + \begingroup + \csname c@\@mpfn\endcsname #1\relax + \unrestored@protected@xdef\@thefnmark{\thempfn}% + \endgroup + \@footnotemark + \def\FNH@endfntext@fntext{\@footnotetext}% + \FNH@startfntext +}% +\def\FNH@footnotetext{% + \ifx\@currenvir\FNH@footnotetext@envname + \expandafter\FNH@footnotetextenv + \else + \expandafter\FNH@latex@footnotetext + \fi +}% +\def\FNH@footnotetextenv{% + \@ifnextchar[% + \FNH@footnotetextenv@i %] + {\protected@xdef\@thefnmark{\thempfn}% + \def\FNH@endfntext@fntext{\@footnotetext}% + \FNH@startfntext}% +}% +\def\FNH@footnotetextenv@i[#1]{% + \begingroup + \csname c@\@mpfn\endcsname #1\relax + \unrestored@protected@xdef\@thefnmark{\thempfn}% + \endgroup + \ifFNH@savingnotes + \def\FNH@endfntext@fntext{\FNH@nohyp@fntext}% + \else + \def\FNH@endfntext@fntext{\FNH@H@@footnotetext}% + \fi + \FNH@startfntext +}% +\def\FNH@startfntext{% + \setbox\z@\vbox\bgroup + \FNH@startnote + \FNH@prefntext + \rule\z@\footnotesep\ignorespaces +}% +\def\FNH@endfntext {% + \@finalstrut\strutbox + \FNH@postfntext + \FNH@endnote + \egroup + \begingroup + \let\@makefntext\@empty\let\@finalstrut\@gobble\let\rule\@gobbletwo + \FNH@endfntext@fntext {\unvbox\z@}% + \endgroup +}% +\let\FNH@prefntext\@empty +\let\FNH@postfntext\@empty +\AtBeginDocument{\iffootnotehyperparse\expandafter\FNH@check\fi}% +\def\FNH@safeif#1{% + \iftrue\csname if#1\endcsname\csname fi\endcsname\expandafter\@firstoftwo + \else\csname fi\endcsname\expandafter\@secondoftwo + \fi +}% +\def\FNH@check{% + \ifx\@makefntextFB\@undefined\expandafter\FNH@check@ + \else\expandafter\FNH@frenchb@ + \fi +}% +\def\FNH@frenchb@{% + \def\FNH@prefntext{% + \localleftbox{}% + \let\FBeverypar@save\FBeverypar@quote + \let\FBeverypar@quote\relax + \FNH@safeif{FB@koma}% + {\FNH@safeif{FBFrenchFootnotes}% + {\ifx\footnote\thanks + \let\@@makefnmark\@@makefnmarkTH + \@makefntextTH{} % space as in french.ldf + \else + \let\@@makefnmark\@@makefnmarkFB + \@makefntextFB{} % space as in french.ldf + \fi + }{\let\@@makefnmark\@@makefnmarkORI + \@makefntextORI{}% no space as in french.ldf + }% + }% + {\FNH@safeif{FBFrenchFootnotes}% + {\@makefntextFB{}}% + {\@makefntextORI{}}% + }% + }% + \def\FNH@postfntext{% + \let\FBeverypar@quote\FBeverypar@save + \localleftbox{\FBeveryline@quote}% + }% +}% +\def\FNH@check@{% + \expandafter\FNH@check@a\@makefntext{1.2!3?4,}% + \FNH@@@1.2!3?4,\FNH@@@\relax +}% +\long\def\FNH@check@a #11.2!3?4,#2\FNH@@@#3{% + \ifx\relax#3\expandafter\FNH@checkagain@ + \else + \def\FNH@prefntext{#1}\def\FNH@postfntext{#2}% + \expandafter\FNH@check@b + \fi +}% +\def\FNH@checkagain@{% + \expandafter\FNH@checkagain@a + \detokenize\expandafter{\@makefntext{1.2!3?4,}}\relax\FNH@@@ +}% +\edef\FNH@temp{\noexpand\FNH@checkagain@a ##1\string{1.2!3?4,\string}}% +\expandafter\def\FNH@temp#2#3\FNH@@@{% + \ifx\relax#2% + \def\FNH@prefntext{\@makefntext{}}% + \else\FNH@bad@makefntext@alert + \fi +}% +\def\FNH@check@b #1\relax{% + \expandafter\expandafter\expandafter\FNH@check@c + \expandafter\meaning\expandafter\FNH@prefntext + \meaning\FNH@postfntext1.2!3?4,\FNH@check@c\relax +}% +\def\FNH@check@c #11.2!3?4,#2#3\relax{% + \ifx\FNH@check@c#2\else\FNH@bad@makefntext@alert\fi +}% +% slight reformulation for Sphinx +\def\FNH@bad@makefntext@alert{% + \PackageWarningNoLine{sphinxpackagefootnote}% + {Footnotes will be sub-optimal, sorry. This is due to the document class or^^J + some package modifying macro \string\@makefntext.^^J + You can try to report this incompatibility at^^J + https://github.com/sphinx-doc/sphinx with this info:}% + \typeout{\meaning\@makefntext}% + \let\FNH@prefntext\@empty\let\FNH@postfntext\@empty +}% +% this macro from original footnote.sty is not used anymore by Sphinx +% but for simplicity sake let's just keep it as is +\def\makesavenoteenv{\@ifnextchar[\FNH@msne@ii\FNH@msne@i}%] +\def\FNH@msne@i #1{% + \expandafter\let\csname FNH$#1\expandafter\endcsname %$ + \csname #1\endcsname + \expandafter\let\csname endFNH$#1\expandafter\endcsname %$ + \csname end#1\endcsname + \FNH@msne@ii[#1]{FNH$#1}%$ +}% +\def\FNH@msne@ii[#1]#2{% + \expandafter\edef\csname#1\endcsname{% + \noexpand\savenotes + \expandafter\noexpand\csname#2\endcsname + }% + \expandafter\edef\csname end#1\endcsname{% + \expandafter\noexpand\csname end#2\endcsname + \noexpand\expandafter + \noexpand\spewnotes + \noexpand\if@endpe\noexpand\@endpetrue\noexpand\fi + }% +}% +% +% some extras for Sphinx : +% \sphinxfootnotemark: usable in section titles and silently removed from TOCs. +\def\sphinxfootnotemark [#1]% + {\ifx\thepage\relax\else\sphinxfootref{#1}\fi}% +% \sphinxfootref: +% - \spx@opt@BeforeFootnote is from BeforeFootnote sphinxsetup option +% - \ref: +% the latex.py writer inserts a \phantomsection\label{.} +% whenever +% - the footnote was explicitly numbered in sources, +% - or it was in restrained context and is rendered using footnotetext +% +% These are the two types of footnotes that \sphinxfootnotemark must +% handle. But for explicitly numbered footnotes the same number +% can be found in document. So a secondary part in is updated +% at each novel such footnote to know what is the target from then on +% for \sphinxfootnotemark and already encountered [1], or [2],... +% +% LaTeX package varioref is not supported by hyperref (from its doc: "There +% are too many problems with varioref. Nobody has time to sort them out. +% Therefore this package is now unsupported.") So we will simply use our own +% macros to access the page number of footnote text and decide whether to print +% it. \pagename is internationalized by latex-babel. +\def\spx@thefnmark#1#2{% + % #1=label for reference, #2=page where footnote was printed + \ifx\spx@tempa\spx@tempb + % same page + #1% + \else + \sphinxthefootnotemark{#1}{#2}% + \fi +}% +\def\sphinxfootref@get #1#2#3#4#5\relax{% + \def\sphinxfootref@label{#1}% + \def\sphinxfootref@page {#2}% + \def\sphinxfootref@Href {#4}% +}% +\protected\def\sphinxfootref#1{% #1 always explicit number in Sphinx usage + \spx@opt@BeforeFootnote + \ltx@ifundefined{r@\thesphinxscope.#1}% + {\gdef\@thefnmark{?}\H@@footnotemark}% + {\expandafter\expandafter\expandafter\sphinxfootref@get + \csname r@\thesphinxscope.#1\endcsname\relax + \edef\spx@tempa{\thepage}\edef\spx@tempb{\sphinxfootref@page}% + \protected@xdef\@thefnmark{\spx@thefnmark{\sphinxfootref@label}{\sphinxfootref@page}}% + \let\spx@@makefnmark\@makefnmark + \def\@makefnmark{% + \hyper@linkstart{link}{\sphinxfootref@Href}% + \spx@@makefnmark + \hyper@linkend + }% + \H@@footnotemark + \let\@makefnmark\spx@@makefnmark + }% +}% +\AtBeginDocument{% + % let hyperref less complain + \pdfstringdefDisableCommands{\def\sphinxfootnotemark [#1]{}}% + % to obtain hyperlinked footnotes in longtable environment we must replace + % hyperref's patch of longtable's patch of \@footnotetext by our own + \let\LT@p@ftntext\FNH@hyper@fntext + % this *requires* longtable to be used always wrapped in savenotes environment +}% +\endinput +%% +%% End of file `sphinxpackagefootnote.sty'. diff --git a/krb5-1.21.3/doc/pdf/user.pdf b/krb5-1.21.3/doc/pdf/user.pdf new file mode 100644 index 0000000000000000000000000000000000000000..397b0864ca064c6a909322e3ce2d7ce7c4d6b6dc GIT binary patch literal 254843 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%0A;tG!r!_f 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�(H%k_q=|h#R%DS~8Q9vxYX`?Kw7+Q@hTJ}m|!3l)L z@l+yH8&XRp0+<)0v-BDM9>i{OR};&T7siCBfZ7|-f+o=LwF_`oj`fE(7w3_dO(S{8FLUb!Crj-PiCiWh#o+qX4_jz+L5|1SA^}N<2aC)aT6wZl!zB^ z15=Y5OW5WccKWWf*>q=SFxGfFgHBpfKT~(s_5>f{oU_&C>eKa z;++Hw;a`=`C33leWB2G8O$-r}lsx%sp^`^DfzH?2ERve5Gpr!wufioypOrx%r*JAC zMhOUZE$ABtr|B2H$FsS=Y1D)}(O$|geO;yM+{!vdYvYcnzM_%tpj}o-W(jSp5>%nc zD4o`MSSdIr(ULgtWSn=trdff)rd<)5_nH28JIT)#^NM3ts9>RHi8duMLsabjcdV~>j5Um=`ykW})3J_K) z?{Y3|K%Fjn?|KssWwoFp`3ac|bf=@hTe&OhbMs`x1v0cDDU@>~qi{hI9(y8mMffX-+>{T1V*=ba z#ZU@zxVgYd{84PSZ;xh%n$-b0Mq$_Y;;q(V&@q4D|7La5OJm+a|c8$VA*Dr)ej%@pck01T9Q+Ch3Kb{ zEW%ws@Lcsw92n#bdBhWpN4&1^lJUdv3PgG5K~|(n61BVwK#>qBpODi$NhrJft~Sbp zmFNrfJyr)kmb zFWj%c28msKapmN`I0Pu;Hnl5GgsiBZmj>nykLZ8Fc6 ze{i^-(hlD$30^C+(dxoh9R5X~u4C69DJt}2Q*Zr1nHL0x7wcEtu;M=?PiZrfH8a|2 zi=i=1P+uwO9sOHI{91aYAWAvmQ`muOgUp&s9NcB#!QiGTBrCK$hJfM4+_I8xqHa!M z3HtJVvRI^t588v6(`ZX$qlN72=A>hIbnMVhw8ThZwrN4h-W6d}5uiM9=U8=QGfNs6 zMz-JU!g7}r7Eaww>l0o3C{JrSD7FFa7ZQZHj#_Jt&}Mbz#14k3=%6FhTz)eBEE-|C z>KGJz+q?=GBm5W2I{+Ld)7EbQ{P3x`TeY(q zEab3^U?i(RFt=_s%26MNG*->^p`l@X-G%f_(XO*?GR##Z11#_s@a6MiiJ;&hM?nndjoRH|`X+lML_L1il-2hyr7LMC zVGP+vh~i&q3)%^qKnV_Bt#D>x8rhQfuJWI({430kTtj!(kSt~rgye@R* z14ETAv}Iz~UEUhe$UW)pMOf4Bp9Eh^*Gi5VA$uqHY%7poemxN|dhnhuZumR0i}xy` zam$dKfZ7O=JEqS?V?fIjLeuSb$IqiiHyLbEe(=fM-85ZqJA3%P~)#}+t4UK-Gcc~#laJ`5Qg ziM;p2poJ~;RdfRnE!k5i9dxjNYjVh(>g=EEgrr^d3>#*E2e>BTAN8GZ#4vgQ?hHF1 zm!rM$*dM+EucqY~^0NAsDj7`ijB7O6-k5OfhrgI8du;B3)7lhQg|yXMR(hdS$agzT zD~}T}JoV~R&`?GOSj^f}%0~oY1w-5Pv-_qoAryRDYG9HIGFH1zS$&5GOd|OjYS@#L zs|M&kbAcX7ohxEL6?yz*7`vt+xyw_3sd@^E46BPox*Gf4!p`|8*b)t8 zUe>k&$s&{Q_k;{audG^mIFRLT**ONcE<>^$M)>T;JGGJ5%hR-+s6?1XM7GcSf(eN)>G+ z6!=cpU1AuQ!5M5^8Y+ zI5{~?)XovgMXJQ=BY*3)n+yZuSeFx{;F&z0$AYJLDLy1WTeYh+7OOfO3^y0_K~{ga zy)u!lG<|(Uf9@KAbp$8H4$W;n=X4YX(oBKyeo=z#w%&uNdir>V+01%WJa?T1Fnh4l(ir=A@f|*W#)!4W;b)KJItSPKm|3wEraV z;q1E7dk!{Ooyv|+dy`Tg5OVw^G{}NZaa=?JaeT;n(Q(8uNN)4IkyoPxMW`E3^pKB~ z&`$6WZ7efHkJAJv=Y#pU2;a*NX%hrh{fZ2|4N_V@8w6i#&S(G)s{R zB@G|#0%N%)=Ed5e@}5JkX7zWuN2@?59)ekshcaAeWOg@U(Id=-w`-TL>7lsC;iu9d z$4_W?pcsMgiMtU_*-$YYc&bDikBM|po<2emdu-YE4Z@Ij9hMs`+I3@~dAIG6-zMYz zoOCi^OI}=NboPE=ol0AqQGCDW6XDC^exS8G#AqN8Ok&WzKCEeUQ%z9I@8yu*Oc2FQ zB1B?)X6?*W6AErLmpRz7Y3_pri;b>J`#RGr(XeNqs$3(J9tbCIa7r6S`c0|kl96#K zDiue>LTwN|+7{g31@H-2-wKkI3W|Z&TrQe5r!{Np{`fI}tLCb>zykG)&g3)$tuseV&=P-kYdNAVqGap_M_?sJ zaC1z;@nlQ_TBJ$+3GOdl+|fw1SY){KI(k1GWobzk+vaJOp^(DI1i3X3nU9c~dtavB^;} z>ZKH1$JC2|bOww@Hga5!`zw*opZrJ1_F_*B4LeX5Si|Hh9&sWeTK5CzcZ{XpA#dWV zE_7KsB`=0B*?xHx3O#ZA!Qi6p>@J~-^t}o{%=!Bw`ZxQ6siSNP)z9&N3l6j!ragX( z_-Xo;{8a8Ttrwm!DzbMN-)3KtXtc;JgfjJOJ%nhSw9Ka`+00dfy-^}bN4--iU)Ntw z@Awu?_##DwR5HQxT&dZKSDGRV9@?9fcY0f^#`w&ZLnLDfGdEI~tBf$-vD&f-B$PZc zAcJZFB7z6JWu52CMt}1`1kUNi_>P#vDw(~Rb$9oXjDgH6f`>G5y`)uIVX zA=j&t1N*b8o=ZdR#0j)=bCj|kEfW$LtecSNN#LG5*s3O`$?-`FgBWpIfmDYt$a#T?xv&0$;aeOl0OgEI*Q6veo)9D=q?s2_Dyw< zMG>4zyPq>Hz98S%-5I~S5YP+r52~-meB#WL#+l8&6v=tKv!qd|z`Cn#JtJLU^Mb=1 zCsP!1Xde}+C3MH1m%lpC;whF-Ys5SxV$k5VlL{BQIw8fgS<7VP<2r9Dz0WdyqO}3fHXKgIgMk8--af;i! z{a&RGZf@|`Xq$xY_K??TGzgotZOFS9mtWoFA6Z@%-5(FX612GX??n|MUi+pGfPN$78g(sE@1Vvw6;A;fJA<;JZAGb82x?Fc<_H%l^z^G>43_^et@Ll=xUzG zM(DFlv)ldSc;c{*h%WYzjx7y!&R@7eLBEkJ|Ms8z0A;vm0OY*l`f85ezRy~O^NM|{3IGXI5f@Sw zOECXX)Y+wNjO1VWucgJMwe>lavn!xGfB^Tfsj1&ZDpL!1nFf#mzLA#{SiG8-OI(Ejf04WqV`LmL3QIm6V#A*l)HD9v&VHnhjkI4BQMF zOib&12gEW}H4g_T%LX8CXPRGYSC7=Skq!9IFlzFs9-uE927#FgR0Zj6ZIOR(586=( zY7yz+@0SQH75wPfzxQy>?4F;!tI<*I_Z!~t|Jb~>@>6T&P3V2S<4(XV8dGbbgCVT# zfN{x>2t@K1)%=WOEn=+f1ls&81K9%t2?Tt5c}5=-EYU^(G%khQxsg30MM7CVI?fmD zLsjhil{?#iBlj*%?YG|iq#X35OwX?#(T_PwN;(2?8Bu%9E@EzE20pf9b^L1w5dUci z;N@qY?}>r~3IE5z^&>0u?e{n9CuQrWMQ9K(IX0&{F1LQf53Z)Z>wf?u4u5rO|xXVET9h)=oE|Fn~6Hu z*@1++!2g~KF)L7qTpgUf82`)Bx3PEdu=n|IE9O@AX1}WpFmrQcRJXTsasx_>{m*`o z3I31G0_X~00sx&rN7>Yp@i*mP2jRDw`L`KV4L=`82S{tyTKQWsfKf+YUR+X@_P-3_UmL~kO&!dv>@7eO&H*rX zb~g5cX97(Y3p+c&hZ%HM%z&PMjUIrJ!QR0YcsQ{vcKWqx2sHVwe4cK?>+Q$y!cC~Z{{^9%G5myg~e>i{yyZz}mDB54I zGA^bL&i_;iDuMeyASerue{>8K)bk$@#On1A2+Gj=PlljK-azNS75w`Zr1bm2{@25b z>Cc_?KW}k=VO3XW2OFTKl^N(=_#a#3jX_iEsmla<(lCSUpr8N!rvGmQ6n`F)|L_(O zaq#q^X9t}|dR8{(-_ynZyJ=j0|K@A@_shp$PdU&;|1bXi*arZCom6sd&G>7G42yyrkOJ; z496aqfpP5Z!Pw7jKNL97q%vi~=+5R3Ks1*I&tp`4H^321;_R-0^Q+@06@T=Wn7NrE zN*^aYCqZ!X=k|s0lf9p1Qy=++lc%_6^WLV;Lg&D3Z`z!Kt|(+|dYD)5Z|CaYv;;`a z-1wm)f^~vIB$?8g1(0ojkrJeEl7-f2SC_`4vcDxI-r{DEoKM8H;7M}@=()H{4Sj;R z{9+cHsd(w|W?F@!fj6#r1ao=H*D}bbFa{jip_Iuelb3Y!4_Z(V%rwAAK2ocF-l^~u2r9QK8OQ`y?pjEWqk4{ zU~Q~2@R+axr;9P>!pvpkQ{Ssvh&rxaVuHk6M=R8P~fcG`RZ0gjY6!$27wo7 z(5gK!2cgp`cV=EW>BW0SaYMzI+Wd~!%l;J>yfU}Zrytz}0+3n)QJQ$BpJ|47SbhpRZaL(gHj!soeh?Vr zNbOzx(NA_45qph;VbZ8ha?gHhksjOYjpr_?bki?Ljlo%+n{4u`{+7kvbJyBAW;r z{O>m$LU&Zsy3oH^A2<_E{hEwhuS8O_GGcfIK0_k$I&?T9dV`1a%eVWxw3CIb9w$_D z35X4$t;L96rg#iSU|NTN!s?)!&!AK_$bHSj9YWT;JscJ4)0h?Dftf4J@2hD7jW~QBX3|C2mOlyzVBq2L>&OmK_|2;*TP;cA z&pKos!!k997+6qFup~ZwO?xL!hp@Tq=;JpYsc!?d5k)cryEc4LZ29t1xhCtkBCc0M zloS{iU@W6DI<3`|gOv=e0v3@>k)$>u8m5+VXEqOGb7^(!@9DG68ON_JmU^cO&zFsj zM5>2X6MKNu`BO0o8Z7W5-*9!ku@i0WP#}e8LTU5zWao%;+EY9fzTbtJuW*F92VlbE zN19@;vOA}$lxOxfLc>>7+`0II&J*6OLdP{^PeR-GJT%JZdV3)u23ixES*qv2CT&`U zpRL@f%9U)-Ph#B-)WVMi z2WlR4b@i~aY<=oMJ8`?T_!4RK?()i1juU1ug)NUb^+IOkhw})R&&bj69a+Y5Wc)xt zUOu0#w2Z?S_crM^yJ09M7oldSadA01wZtm!t}2m}%vtzjuu4eewhyFiPH)&y zsRz|$l?0CAdKZmKs(W(oiwJHL$$y~Omr#gwbBjtUXik2gYQI1=j``j`Q*iu)?#GYU zMJW+0XHX73aUqy55Uxn^iu*2ku-MlI0m98?K5!5J)?_H+|auKNRlT;Qrqz%Q$!BVqK#-_Dz zI0Nj?y7P$Jk=XGNO8bV>Uoa|Y)MKq68dlL)`j1^sbJiYmb{PB2Qb}+x zG|XTw&aooxo{e{P5GvW~5j_0tAR)hJM~IVwyCnSl65Xwd3d5k(FD6B(T8j%2$XiP$ zNiV|iHP_bqoL;WY0&}>2{sHFA<{7TkubSJ}CgL&b7oyO)2vs?!_NqgYDVx1$lfbqI z)xHREa-%7{c*L7Wyg62a89jmOc=(cqJ|9P>M1T7nZiv1l>=8VqP=}9och6^`eAx=; zQ@i2O-OnffLQsaN*U=m(i2SG16iD}ZHi-oTJYOQNNKO)C5tQ?MRLQ(;E)uNm-nb6@ z#wK}sDZlaw8)qqk+ZVm8Go!0GE$$+yudUi1^j}Wkh_P=cW#&#jznJK{ND1jfAHC^X zYE9^|sW^!*(tmFPScr1a*@7_?VKB5x;CT)bUm%i9H)4MBK4^Sb&=hJOjgjM`niR-j zGZmvN;&@jvS`qujz}3c0+G!xXHOP{J6yihe&nEO~`i)cb5K!F}bxjef8?TuOZ9 zpYGqv_gB=kxnjj8|G}rsqBLbm%}d`xZiMJ}op7DZ5mo)o;F!jkBHaI$tZ#9eu68^( ztTaKUwo&Cl=s}zp!EpD^g6;#dBGAYZ?hw(>*``P^kPJ5;A|-@C%#qRt$KFvCSp)G z_0>shLd&OKny})*PMK+KzH$@+tu(@>6c6_$#dfcPt=UJ3@}*|?_cUaRMPaf1g9}lR zt6(n%3k+SdsFjrN7`%Psqgh{*0*KLLv3BsMSrMDORRr|2q;pUu$IUS@3IrVeBgY3D z#ydWU>~AM&Gh=t>qp>-+mR{n9qX7yMgpQJZWL}3~uJJzo* z*>OH9AyeRdxo|l=3q~EIWi(2Sc^sZgH<3Pp4{1hUzgv@bYYSuKqnO;6_-MiKrBx$& zYP-nuaC%!m44%ho!3+rxz6Y1<9ni!-*~m&`l4XUmttv-1*7HcK_z1qQNz$k4##Owc zCvn!N^Y#H&9&RnmBCWl(!f0X22Eg+Sw9h%?6zAwo|WyCw^YT}Em<-&gM+Q>l z?G>gNvi$T_$|fFG6kx_j?Zpn*lva70=)A2Xusq6pl#Jv&LU&d8VK1v`TeYe&8@9P>`|ZnHxE6spEbl z?`NBW<tH`X zXZci0c_4 z3BJNKQ6%9~z|)o6bQ4Sx>nUu%P_i)XcwnUqY{97K4W@W} zmj74(FBg*IHwH*9)DU<%D%+-(L(JqfN(2O5efdZAhj3mkQa**_o<_La@CK0TmCU|m z{3d3s$6enOw!Vio*$`QR?_@Gx8$US=y&lCu*bFuf5+~IU*)hvx$vnH6cl^3?MKaIg z|M3fY9jyqVG~EGX!ZTIyqjQ^@P@=R|!PN|S$V z&2>`n44FM#h^O80omHaIL&(Rzn?n6WeuDF|?SZuTw<6ncXF#<<2Gi{;$3v1+2) zb|(e#Cb7RG5VE*?vnun6T&VZFF>OVQ4EW7F5$~uFW;iJfC|Bv1P-G_xOFOo7ysUX@ z2oNbu%73o|R<(Pt4m4fe;RVds&GeZ%sYc~g#!Q+-u%`0W>}L6upDu^Nox4ZoQ6B5C z_$(_s4zn!h0_4ue1*=2^wjuE8BaCZ(Pqi?*QP%7n6?)KvJ~fslEW9tXhaq*X%SGo@ zyLY32UH2Gi)GH{upLJiwm;2=T%}%`gz(;6me=AWeosvtx2U}3lul8ci{@%}lQ;eaYN|v<166GV6@;v z_N$=K2`#EbX3hwV&JV^-raLEt=Ix9~)=p+y4U|Xr`wZ8J(|frm!u~>Hal6jDIQk(~ zUD|F7&9;UtgV}Qv(StO#hxN1nrp(Mr!z!b!)|B zo>44{HFd z*Ui-e>oJs!nV!sm2ErPfU|CpUBNs%w`Ui!)hMzr6tzqosx3LPuZE+{Zv;@RD4Sitx zYouGy1vfSF6x5?_1tWtq-q$ltD*AqB+o;84pNc<`ozi|e<}Zfk^}*z0i`;Q}J84cK zZo3f>St5<kGM^+bPUVmSP|*iln|YVonL$*{XiI`T{Pi&MS+9MAe? zylAGFwEMLp6A5*@Tx?jMdg0c}7QN2a{se zq73+qoDd^b(E5_Gd(1K89q~BB=!dnKdY$4k>|STWMMwc1aGWs1h+RYDRFEsLd@Tdp zkO!WS?E~pfas>+y_mVgtVI6|2h>|>-p93t-5Z5REY$z>ZZR1U$q~y>e z!j*)o_p|x2N8>P@xWL;2;CK^Rcjoew1gL?3RoE`K)T2>afOKj!8YEsAG${5w82`EX zpuiDBEQ(6-x_!Y2qAx8~P;tAhyc(g_OO=(=zNt5S4L=Nu6-v5pZL+V;(yQ7c=@4DS znsw5%TnrsS*DM;1YW=j`tSeXcyHGaU~M{%Ls`W5 zJoUZQv6r-8WCf~oSSemEj-xS-0viyw6_)M&4`_H6s)4f9-G+OSHYbR4R2nRcdUO@# z$?q~Km+FSo9_Gxoi4scqrnw}WTFF8Nmd~27o~uyVlVUDkUg<`PI;U2D##i#D%rmQ^ zbJjWIArdbRY^mH;CfjJE(a^xDIyNOV+8JH0*;nQ(S*e;>jxyFc=X@x&Xn-u%L$*a@ zBwQ$Qi~&x_H^IglrLQM{nGp)|glTUjS#%G!+waEzB}8@WvxG6Vr%~p>q8;^7qZr6} zCk~5(-}(hz8V2WO(>LnwV*tZ0H_YRFzHDZvuHK1=Q~5U*7-M(Ub5wK9*iLY2NjM;P zV+Zv7DU>ilc z7+TN#TsG1$*`bPvR>{DKt*9Q~;NnM@nJN19ncnmqhj5Z~waKLwM<70twRGOFLn{FJ zVUAwM$!mrpgQ)JZlJmqL4vnn2{doDn3oNUuh$+SWs5%j{vE|}T@7dG%;&M=t>wECp z;rezoY{h2rd(q7oaqO)lhy?-i7NYsf2@EMZsTWL*4z6#t(}7H5-%L@T2=A?K3QN}@ z`K^&G^M=T=LR#gpEMts;<=vMWceO|^esp}f(XZlG;a8TQyZ03aj>GV8#_`{eqg;*+ zlPDyd!5AM=NoQ1LT&^iV(OL+ka>y22aQ2nr^TumUnt}_f|A3VJSR+Ry{_VC4c_uta z`{kJnFvBQ;Ovm`4X~Lk$&{yVydw7=CrUE+&cM18yw;8KLfEKtE!7_kCB5RKM$nqG; z`Iv$Bsn-^Ll1Abdji}-~SMu6HdHpe_;~iAw<1(dj3Ac^K;plrelINLV25%%oNQ-hR zaUmZ0i70w1ICr9E3^7`*N!{r7z4aOy#;x;H`sos%y2YI}TL_m1ibz#iWHTOUGlA$3 z$Uy2tmJ95%SHI}Bo$g_NAn8E)9;B+QhC`ztsz6&%qRsyJNd^=FUO@GXx4(?Oj!+60 zM%G)xB}(2T91_~Q$cIF(LJw;I45u2Y9WQ&lyv(Gg6otM@zmzQXMCBDOTW0W=l;c;he8zC>K%MHnJlOGqjd`*4C0=S-I8ckN+uNAta31bv&zD{#2q3Z~ zh7VF4iz60pqF`vr!k4WjU76Y3-&JuQFc<-G9F_%eZi~|@#Dw?>g&X_(=!@0TT3F0u ze+lx!nTLXx1_D6S4~lr-2J9Gj+3E+LV2gDUn$@FER8=omp=u!!B3Nq z|LfDn*LQ{$wDB8y3v|Ff|L~xxavturcprb*oG8WO82nZo;U~vVWO&&wR5^d0ubP+O zr2Mc+qX+RM2v&;3Z9lv*Y(E#ZYV2i(lQ7LB{jw?dUXDhn8J)ZIKAJ>afqN%Sxw*pM zq*mYkeNtdp^#g7k!%0DN1YJyy35K@7g2SnuL2itoHhNE60ePkomqJsk!oV9%v-DG}?f#)RDc@MJb!<*$GdA8%Mb+9Hkbl%(0zh-fA42 zx3w(UedZ5?n|tF&qxBPo-8k@;#hwj~mD2FqOX{scY#z7D=B+Go97sS$UjkeOF;bb> z?R4>F%(6eP`Awh0KC+tE27I_Sn2yycQJN2qDW_p^9osMnmR-gt#=1pJbx> zk2lwysy3xBuMF20a1idWY`i2S^of+GQj_y$Y?0{)+dhd5q=C;En@zjjqu8oj7+SyZ zZQ2Yt`4nWhd$ThvCuKe&AU$eHgA*({JV<4lm4(I+T~8Ow1}HC%lREQNtKTe;nNzu> z!F)g0nN(l&D&Hu4G-oAHsV+fk9TN3T(I@g9YseCeXEWmrV*En3y|G)1uOV?9cbd8V zE|0ZjYYKicu5aEffE0G;0!Ni7wic_9 zcp``Yw=A824uu90UY9of$ZbNT-3J5b2tF}x==V4w6TMBVYJNY^g5M`XHM~zhh9Yk2 z(g2@op7H9W*aIeFTHUUz&rs1+RxhvcVrh32dzQBtu}F;(i8VHtY{ssr+*HrCjb?-M za5f(A`BK)ewA>}CB&I;ia>6OaGceSJTM-9e$D>xyap5erpZKKeRYlrZ4NUQHPm)gM zF!Jj{Kps8eTz&eAoI2&s-~sSAB0X9_prS<&UCS*s=Il$ve?H%)K{(&}s1;)-cY8~( zh=V_Bl`W3#@98P&R3BEM`(oGarevyA{BFFzK?uaQg6Rpt2N$Pmh>rrXg zbUEE4uG-9Wa9VX!ZkhMnHwN5G5|a!$!!UO2Ug1xV)ZcPz#S#ieKQQk`N$|@hXIiXE z{5<`JE?9NWI`>JtjB48D@{d27pgVfIc9ShIsna>nlUA;uX@>WB;J zg~aXcPTDbncFZcRcvet-794z`K`a=Dxi#wrpGP!)5YlA$Cv&8JE?~<+pH48g*09Fo z^!JxTWNBrkS#gQaWSBGWw+Znokc=#7*m4;pQ?^>mA%g8|KX^)nOqq|uwLn30eK}YU zY+i@f?~5T2XihhKshfj(Jl(HA6IoVIKF?bq&X6AFLJ;ZyM6>5=VV$qdCPqH%%6i+rKHSDMR)zN;_#c*hVXe;8Eta6}H$X_Twc%pjGnD~AF`J-BnHklJE z5tZ7`$%jTYR<7BXr1yJvH}%6n80O2bGD4?($a;?F8RWKrt|jCP23J+h5sWADaktk} zE?AL6RGXfwrtPa3`0xa{ckol*p(e-j@Ck~Q%KE~q?Ha0 zRe6lr1|%11OqbyFBh>H3z~`ethNkLjBl_nzX>?-|Z6%OUieVkCK|*`ajoTvjcgpGA z`wn=yY7@IeR&`&rs||+SNdo2C{drm?(wKz2zQqdPl1eSXY~id++j?F6YIL@UM=Z&4 zex4O4D+ppovcDMY=l%w)W;#O5jq^(W$aZh!X*}+&nP7|<_Mv;@!==;U&B!~a>ZM5* z-v+cDgRcipk-eepg$Hl#+J=bG3TYE!_si{3Ib;(pH68j!7ic?ph5Yntn$|@`b>tT6 zn+9Fsm{pAB>4&7=2umt9Q-kAsbMGV4b925XX}o@YWyIMZwD=e<)BAxHu_>KvDG0|} z&_7IDo`RAqE5N5R?Njd)RMjAXO9W~TTG(d|sa{5TSz15g8F`LuSmi8yD2?BBO^m1*Jgl8z-Qx0OPfy}qF zbtrto`;_%RGThIAF-lc*aV%dxd@#f}RZ(-}4#c>SmA-Q_yI|`HG$O5p>a>aCE#Sk4 z#WJW;jUZ{~4fKfvT-lZiXMSrjCG%1sMt^mP@e^fz$-@48A--A5C$SALN-20aMKiwu zj67jo+1zwbOJn%S!-FvZg}-X30%oWkZ$w60&mAI{64?;z8U0I1A&UPe)(|uEYcXC& zIgGCza+#YHfJs+{G##d@H9#1ie&h0a~bsoPP8{$qePGC$n?n3Ju5)5 z_-ZC%{{h%*A(pH(X?KJH&FgKUj{=SNrRBDQjj~&X7HDuXABk_mO;;@-e!%HOvlLtC2!QpgN1%diQ@)MCI%Co`O zSvvc1qkDSneRp@C@*)~JeSrs|Hq)GX1W%qBA|b!L_x)gd=0E%Sio0H1C~Kmzlvth*^*!+Hl4+w% zPZ~y$K!V<$9}DjU1jRN8O76)!)A+e4F3||ZXne0w_nD^o%=<7um^zCCeZmX7e;kwj z+_EUs-nNLUXIQh>9RJQLMHS-_k0L$aca%U2NGUm`LxB(RDySv9WBinc`(FHlhO?>S zyN3)D*qbnwGMB~A0++%~j7~Rs<>!UT)aX%TTFz}RTBwGrwux$74ZRY~+?EfbO*JVS z2ozPed3|DJ{NWT&;Cc}7>$3YRnn-^64}fRYf5Y4T~)p z>t^dX2#cX9y*J9iXWx7)jy2*216q@5W^r%;S-gEyk4 z7s1P7wWevG2kIBRlADPONiq}8ZIgU}zyOM`;6&3puD45DoE(E)>vck2&bGyZW8Kp1 z1Tuy{!Jz+6O?-u01=Z zfR#$OqHMB%`eC#BE$IvrP~TjuQnuVjFxVrOQ!2kXn#7JfW$2QiS)+6H0V9R^2|LkE zQ-)~zYYZ@ZWW(cG$mcfU3Y|Naq+;PMrfZ{i%v_D{+4=0QfVz1mTLa~W2XCw~aJxF6 zmPCGE=hfTx`BQRE#hTdnIBGmAS1-#l3n3{lRC1U@Eb^5(x6J-ifF?OZdD%)L#sHb3 zh3SCPug&a3rt?Z%sqX;yQQZq;$SOr?lhX7tCi7@qxHab%eAymb^J{EKLDpKwuk*$L zw8?eVGtzb9=d573hP4-Ue=IpaY3BCVtVE9f%1x&_gdzx5A=ME3#|*-8t5Ryck(guVywIp*B9hOLr6z?;k) z^BXhQxn1x8&c@nKug3L!rRS02eXnA_rXfIUgUylKdH{&Q*j8V)nsl7zk6t#$qkJS5 zhn}9b9*2p>lBHa&z+TN&-Ht|}i&Ks+j|89Iaf!d5NIG3cQk5h*PND~+TvMuFjDrRo z{X*FMRzv9`=JyVUB`BOku`t+2^UL$pyc*_b(lA=G;&4XYO2Wbo3{k%X{=Va1#lDkY zI=7y)FfY|95i@r_v5MffWr%W_bIB`kcPNB2Ie8IdEq!QUm%y$}t@6OT zgkL*u?7KfSbhH~sT!9CaB{rV0r`JT6!v+LtC=rj;3}&laDjTw{W*^TpyA)D5pZl$e zF2QzE#VlyVtvr5JL#|qxVp6cV-5;*)1RQCoJ%||IQ z$P|m~<^=SV(kBWMvlez9`<@Fq(Pq-YaYGdEpHv@={q)N)c!ST=$3CiDAt!4Nd)4!GfI*E6?{+j=;{pz#dKx0m&ygF~XgF13?3FSnce#nP5wXr-t9xm-7 zIQG36vY`QFDKLjbaHc~Uf6oYHG4z)>*fLW=L?)dM>6I5%iK6Ln6&_D4*7M7GAF8`V z3w8BPq00Vy3(c$_9|c;rVvgC$U1ARU#mkXCrKu+vxpUCILRqA>W}dQ|t^ck3#{5<_bE9AboT*Mv) zPfsDuW4*Wa-GRBUf#J#-tfVlvG7@!`p%D3U4FsVStg2UFC;F!AXTRjkru@U5BUuU9^-hR+Tl~3x-U0w2p63Wj={< zKxsdE%She^b3U@2njLC=*bIzusUJ^a;w##kvCQ5x2_lqZj7c7F@h?TrHbtYG=_!U8 z9FN_jtaKzl?=uLCdzW>`3@24>F*ZVhcKO?(*R@Wt7$k`gIsuL`)Z#SB#t0ned1yaB zN}F+aQ?XDlbw&!#&6t(y70eBod69iuYUT{2H|GhqnnR0}Xt!X-y`*;s4z4>NdO&%1 z`Xl(M#UbQcEuhi~|JWgfMd4u!^jEybQQD$+@YMf?B~1Pt?BZ47b7essFLC>>ke~Mc zvW=YcqkF{~HZ0W`X>&3%4*!<0N&^Z*RCHPJS88>P=vw7X{{Yz)tW!^tM+F1)mGP)T z72}@?b7jqj6)Jw7lY*7y40a zzar49{d*3De+1Xi5DV3lf{Z7ULJWiNyZ6X?MPY()Doj+UderKv@?z+v)kVZR+ zEURSFsMA-{+6f~~5-K{`UXN5ugyWX6QXoJWgtq(MK0ZEqK?#S42BF{+3@$hNBg&xp zbiLoVLbal#vEEg$=M~C>M^L~!-Os`ikzZXfs{a(Ve8XAbdAbYu)q{iG8G;&$iv-Sw z?{Rx6(#){Fl+Y#p1s!zB^I!Cp>$iwx_lcC5rYC11-(IqbR$!s9R}Px+j@Q}_&eJ&5 z1t)k<)M`B zmUW))F%!*mBXhl#YoyWWlt!J&V zFVuy;j>LL(ynEk+&L3wzgaoVO@1JD_De5;PirQ!>`Z?fNm;K=Iz~w`2TczO^C@aDg zjECH<==F4darBeTjK`b6`sXU@Am_v#Iup%7P-+;KP`>pf8e35$ntLS?MC{>yKXJ3W_ZgTIOCL*&lQmZL4hTN8^RA|mFHXC`dC|^>+;iRdStY#4l2GJ3dPI_LE$5?P4N^vljHPxM>U|ACUx5B#OXO$uvg!-hBj!-7S zfeEhw?yqlp(zBm4tu3nHFu(JM<-k+9qp+Fy%yE;P{N$U}Kxkd``Jj63+dW3CAS4Udc-+Nn zd74c-F4)v7D^6nFOI}9`rrx78Y;GOI{wLB)pKMMR&Ds#Z`$44jx0n;!JHKjG0#yoI zwvzWGHObmWx_p{F7W@$Ijy~6J4x@g614spuIfYx;6mXc$oE2R>-OCBVGen=o>-jiw zDex%8?DQ|=DgD`pU&olY(o=muU{&lYqKIRpo5YN6f6c2&W<5A2*h;>4Wu5#07gtb+ zzHeEIQEfOQ{DEC~sd%(4MmOOsTY(?f2|U)g>%NLc_Gjz6f{mw_TyS0V{9D(Q0RZ)_dOXo&e980_3TIl(@09~nr>T!rrBCI?u*r)>+=ji&dXpPKul;6Dnr9Y; zdq&bF4*MX2h}+mNMS8jN-7>M*?&Peq=A+1X)%JRo6favImL44zD+I1*TTX|XyM5KB z`fmkojM5kH#k4djdl|70Ej-2<$1qoRh)o2iu&`GOkTW?>-ZAScwckeK)ZhQ?l+LLN9n)uiI73M=xsE+Zr=Uh*;ay*+T6Q)ZO6XV^T;i^@#BK2z_g z<>_7kng-7FzW$C%*Z@P0qv6-YOyj86{OgG%(l}Y}<2MiDH5%D9(g%idj$6!13@7~! z2S>JMnJ-$?W5&b`=ZDl5YWeax5-1WqJYzYU%Mgq z%s1YySgRDTvs<4*Tb&v`KJTe@QF_`$AW%5_JBD_be__X-zZgPrre_%ac)9yij!|?~ z_{VEoT(&^8@ZCeV6+AiPj_oTZi=;x8A7etQI&-g?wX&k-)kPbGe->Pt@gO;BoZFE? zolv7uUL?d1xCF>y2Z7L?*f_)!e2jH|`UI;<>-q-C(!4W<@^va-WU=hS-R(U=aGZym z;l8A%Ew{T&K-UwoTo{M98{UrSL^<^j2|`%0&o3Nw`Qt$C{uQiIBn|1%Mk)b^%3hMv zPpe9RiLZ%CZdDNq-jz8G=Q+w&rGEPqgN#Ea@26~*r}K}mSeQQ>qx^b4{}!zBlZ<{!p-%;_4?9T6MHgk_2 z*Fp`ew{03>qf2NJURp;LQl;PYRdKb?!G-4b^{nuOvKCA~4{sIryWh(k zRJSSlc+-|?s)DPO6q<5a;2&&YpFL}cDe-6s!ql*WMIerP=@%-*#bzJ!l6hXiqJpQT z;>L&~n_!F==Rho>N3TE*j____1T<4CXiC<4ryZ!Nwd@SUHXnb5hhHvQ(3A0g)b%oA ze2+L*0#k2jcJzI`GY4f=f$*})IDv7Qzl*j0TyGhM{~^xkbO*0G5RWJBhqo4_Dcj6o zx*1^DVHmpJTkYsQ;^{exxxaF+(8Z9oV^?gOHa}Xj+NwoaI_HQC5jh3MS zCtJjDvi%N2sYKMRv`!n`$_AFrO-Vf|s>?5TH#o0Sf+}G`#39~gGRNbpA$j!!dyX5W zD<{_DLtLRPMZsDaN8e{cMLL_@8E%56Py*jsemyY?Ccf^z)zcq0Td+q6y3k)zJ5B_@ z357{O!eg-bc}2+d7y)Jid+pBzAmvfy;O-uNe2nMaif1MuFvw{PO#>849&bgftL31w^~$L)G7@9@FiPdQG_Wj!<5nF{}%6Fp^Sfu!|WtZ0X(jRDlex#bmhs3ulGOtZo0I2T1u}-N^WO*JW8( z@zKz21Ef-0(?PUJx~r|jJIKqEJ+IXnHbYCb5`HD6`JLkA#X@r)%IjCs?UURT-XU_f>aw=0HB6xd)#J4|{D=HG(C=w^() zLy#^_8*be;pSEq=wr$(qZDY4>W4CSFwr$(){@;J_MV!GIoMBdE)SxmWGwRB`*SeQu zRZx_QI;($VgFmE{ysRQ8+f<#*V<-ntj(KyqRS-`TnJY{5bunqFe*Mo`7$T9U9($}y za6w8(>^GV#>GUUAL7{7WB(e&|3qDG)FI<>Tr{yMaeZ@6yZJo!|YiwBbBxJ0W9Ioz$ zn-;G0hN_Voa_pjl!#AAi#+X44R(h$*CX#!4GJa)Y^4bxvQg<2W>_?(=Hbw*DPIwen~us<=NU zu0s){5VlHNI3jW?jS)3zPnk9GG}R~qugs`rR^dCmt5VjK8OfkC^a=jRMwBBza(uZ2`Xgem{ zvaEAMF4}jK^7F3}3>mA&V0b8T7Y7Kbt+KDFdeZ%m?T^Rhlw(q=+{lc&R{9JWypUi3 z`=@;l45qJX_8d+PPqUT#-Pr=N<}~JuGVf~(Grq1Y9@dP6rKAXq7g)&rpOhHW#J;ie zLnJrUT&*IIvt;)AfV~Qa^{ZmQH&}863nYV~^>w*lDV7v~aBzxq4v7H2bXP&^s+L%u z0!`2*e3evlV%D{aful%PdgDJ9U6X0Rp5LC+zl57X6;gg;lPM}K;cUHV&%9n?dZ-cH zAT-MZRRsvI)o#1-|0baGTF<7heGr|ivtT$pDQs`KDo?8W6ZQ^Rd3p&jqc))E6h;vx z$-`lK3P$%*V2Jh{x-0ME;{$m109Mnj;~}$q%N^vYALQ zDr*6RXh~NJ&)^N6v}szEF@qI z5(d4!Uk@9tNG6me?@?E0_Pe{LB+OETTI=FMnx*b$R;Bsl8yxhSzXMeA1={}Azc*sb zv$R-gYU%hSFm)u^jzJ)6`Ih3gBlByK@JAe!yP@J|r1C4x`0H_ENy<4%*hXQw`h2~X zT93qWHU6QVK=(%a7jEJDv8+X_m4a>r<=t$Lt}EwaT6Z#{gV*H&%hrRnzF4%LA<5;` z7zXe9+JSVozskv3N%sC}Dw#nh%Nv|Mav^*lxTE>OBS=BjbDclF1$|KD))31AMkM}Y zt`!J&0S4Nt3kk|eI>H0=(rGE*0X{o~((KOlRmpX5_v^((izO8Ky2a|TKBF@y*p!X! zq{RXP@nA^(Qt*9L$7K|*0cobadvLwMB>qU3Q<4h04Sd+GM$mu}dWRil9s70~4M^(0 zm>Uo{TaM9s-`#?J=8pw2TYY#t3$0xcc2;5S=S7|lmGsjr<&fiJvqObV(}bA?|6I}W z;#5Z)IwlyR^he9qo*;MIi&>Pkhg$}=sGe;q47!mMve1KMZEkW#R<(6Tt*`zJiTNL# zqW*-NlSrBqIy{|Z5u8 zIveGNYbwJezc_z+KSTUM=l4(`yU8LmxR^Ay3|)fDa*~m*s8(cn#?HC%ik7w6uaRmKajHyB981IHKlknEB09=#d}7w4zab%kNkB0 z0j!AxB-G)rgt*;03@BEs8+M=muXWf2hxem~L!_k;&_iIWT*XdR3Lz%lXfjE#ae#w0 zkk?9@Sq|cVW53sf|)+D5~>h7xt#Q6-ApOp@^J3K)!{lvgCjZ3dQNQ*qmk z3@7TOnw{Q)orik|rK?(ZvP`?#B>yF$ytzgwtbLsD!h0?y>nw73)q}kNTig#p1dd?I zm$p!CNHia!&vz6^pby*LGoUiidvjzctjHS|hzc1Tc_joC=oj^5cZhX7Q~A8AveE52 zvZJj|&T%J@t$rCJ|G~=pEU2g}CVx;>Z-NxfO^+}~LJG`*%6Gq=yXuujDDn!8l)hz{ ze9@PA;vERvfJ~Zxj1GmY8b2l{pA8hhtB=*)aQgOUxxh z8FJS|T4CsfL%E3Ss%s0{v+d?-NE>nKv^t^kp%-UYkBg8a3qSGC^g1Mxl+?bI|Bjt} z3KwRlo-ve_)dJ47dA6h3brz{S6|P(@huPh6tB^jzB6mXqU~Zxl2A_ifCX2*%O8!@$RlbE! zEy|y?ti~!HpX^S!*I79}_vXq!TA=7zddCcZ;tD!D8snrVC%(iHd-&oYe(h)%0V_mE zg&h08!t%dYfQv~I4yRu0<>e+gFlFO*YQD92+_`72v=dO$Ht!0o7s+cl*T~)zR>rOy zpH|j%hM-?s=6{8;Dmh7FPt9>QvHTox$h(sx4(#Wk{H72m@v=#ByGUenqgw#Q4P(*7 zSs`ztFwJ|siuP5LLTOJN6e3&~19QH#M@Ljt_2La@QJO9BHRG3YR9?;PX5CPw1yj#3 zqoJD}adJxwtq_lS$pt_+l1WU6(`^93Q%&!vb{C60E>n(stM-G1uxzur~z}Z#PgLpUIJ!KRDgrZ5o*q<3J>SF$o4Q;tYT{rhCo=^R`&dwJh`QyKl;(T~$ z;&oykdDYZF`EShnk01$Ty>MxKoO45gBXLW81u)8V`0R$ISuXGRw%s}M6o=-{hh=oD&#do_s`hmJ)n!DwZmUBA zZ#2QUS*uU(^=7;r_~Kq0v&egHqy{bxIqvY`%3&~Te)Rp7PS5Jn+ey#oP_)^;g=Z86d<9H* z7{4_iDK4rM`JJo$5VxvL-~@xnCzvw6Sh=qqnvl2$9X8aU@*6^=1}FH&gxzu6;QxK! z{1LP{D-v%Idy-F%%Q)IaZWDqX$-vPoN08V@2zemV#q2o0ilHp~as#EI0W>y)`OjMa zkFMw*6Uu^G;~gV&g6QdxNmM_J{&n*$TPP1~N|l1={~v82TR~Zb}C@E#=T~7 zt0-&0GwD_uDE!Bz=tpB%ny2`G_|9cm{Esd^DguS=EE#zQZ4^Op_4zqxjG1^ibVUaZ zU=dd_{VKDg0VG+3C~M|OEj!FbqrJNFhccDLK%+$#qve%J3UE9av4x(4q`N+{QCxX} z-!xAl(K}Wa%W@3Zt26&)fE^+l0*M^AE_2BhA#&pHTF+?66AHD#T#@;8SQsydbK#Xz zeHnVv*UVM!=QjTDoR5a}gXr1}yu1JrZ!0pBcjYIf5DX&XkD9#L>%x(Ixawzc(s)(p z_h-Jye^(I+j3jjUp(O9ihVj0d>0hJZVZ$+&QYzfTTnxr!$Rj4aY)GYq=tn@3Qbc{TgGk|@pL4C&<)VR+Ppj(FT)%5HHZygC2#T@X0{uex_;B0tBbM9eW;u0s>_^{J?+>xNwb9$k`Le4BA z3aYu=L{bX?p|($bxuWc{_}B<&f?9{FAFfW)JT;s@S`c08)!_T?Hp&l}Zs)ZrKL!Ix zG9IWGn*Yl>t~?FPY5lFIaD@N)1J*_{Xfz$mw=Z7P$4^g!r?V;<|2{sECm#n5a@X}uEWdd=r8-t>5cE>3P6KF* ziRjykjA@YFx-W_-#9YSq z7F=6Z#;kqz11}Ehrx|Ud4RIt4+^vl7&@x^`o`ZA_zWkAwtxRPIvH^P9q`E02FCOLV z^%865HN`ycJ#J0VJh3%D58u8kHsiChcY{O*?vvy&Y@qf=@fM6sX05Mup_ZY0+jGS<}}su*Bz#g!&=j$w(@c7E`nTP&9UG3 zP#3G1>aK$N_L7|##A`yy+tQ6?`iyXM+%Ox&BcbfU5`;YgmhqX zLTA2tU{4<&YX6I)E?0ga0*MKC;N$9Y++65vd^pp!^C zv`=prcP>&sWT%RP`|rizcJASEMRNWBmMiwB7CQHg9h-|`X#eEahMSBR^g%XzL4l1n zBPEMhsmFA!9`!%g{XsTnnEE#?PG3$#sJHNGr|P%3tOYI@2IHK6Nzmi%I5q=w{D)kF zBBd_K(!R1$tr2A7k2e%y%-#&oL~^bb{3xQPy@Ek)N!&JZwJ@dCK{zFfkE0FTDCzJl zfyJZXG_soIvii2!FJKpbEh7~aIqnlKs`+%T7?y=Z`XN@$O;i1SK=@dkkb4}#Ba&P6->Q=(HD2F8FYM}1k zpHc+Gpqd5jL)`%#Yfd^YB$-Jje%)|ui1B~%Dp!IuHY>5zD&)9!+n|cz>#7cvjhY%q zZSN~q`j5=rJQcaeN=5a;>#>45cKr=v@WS0(*(>2H7-Mj4K>yN8<)Q#^Gq~o@lIig- zco8~7M5+*FuD1xZ?2nC3)6=8E|6nk+Ly^j-7IQ-fiM{3X^RxgtDkGd8Updx@CM@PBT2Hu+-Jzi>leOxBr#ahuLOQ4^1pCS>(v()s)g(}iMHgmo8SaL(# z`ogkduVA0TCal(~a+{w}B65IeI?8^+xshOt6#J*}&5LE|8#uF3sKiN$c{1f&jy>Hl zk@Ol;;Q?*u^i&FGXJj$D#$H6OX@Q6A&ea5;@ocC%rP)c;Ttj=P^avzSdeaT|ZI)Nb zS+7z*Pl2Km;mqP)usMBtYb^00R^#b6{W~h&)7;_eGU+HF2wNW*sMzAuyu_>Fyp)rb z+L4c(OXZ;n#l2?hgZPbi+(8B7wtwhTSc-Ky{iz$|gwSn7XG^=Snq?;gSx#-fiPHQS zI&EAXA>q#H2oJ_Q?v<%X!0+#i;B4{fTlZ**Q18$1*QCCGPM)1OH7_&QIG2y7ss6q& zPltk35&Do-$0Al>B=C$+q&k~ zG=*9-(OL>*SE?+hhsdCWJ9bZt#Nm57j((KkHF0Wf7r2EA?SN_zvuN}^=X3LFTS5Ye z#7HhhsBiYWY8H5iW@MS7AQh5?{;b5gpagWGiE{2X=?~u6Cb!^CQFS&}De$SHWhUtN1W|oB7D}Uh z#o$duC$I%zf-FHVm=c9!axX&13u0%4SHLOfS@sf>`-?f~;ka*~sR7OoCfiL{1v#gG zc2``GR6bBamLlEBZ6I3JJ7$`{7OfG{*w{B#BR@A<=1LS%_%lW&bUJE}t@gfOvXyI?$A_B{=o4m=l_ZEN*pAsBu(|4K%Ya zihN`I@eMEa(N%=rpd_HW_Gp$UT4Ry`tq?#yhs5wH7Mtx;kIIH2ckC1pp|GD*CLP}_ z%?#Pn7`WVs6{b#6{CDfXaW=Qkux`Wd!`7&%imKIjgW3U;M1+O4Q&i4M3#DtYF!~e# z{4Y@VLwR>&W~~#!{bw&K&OQ%RhNO+!IbhTcZQ`?&d%nyiEdQpiXFq48?1q z5HWivLm#4y9)V8|0{!NOfA<#;lES|{lDxHu_ARFBM4E3b*!@ID0-79?G_PBg^LM|q%vM;(d z2*6mK=f)Xk)=IL`BMxobuG#X|84`&$fIn+MzsR7F00FlP-5RE@(n_MB zw&K}#XNh>A-TcYLOGYlr8vAJ7uoIeTmO^VChhuz@C@w((IKhIZib2eijx9`Mg}W9p zb)MRVJD?M^8K?_vxGFZve@DnbR0#s$jA)=aU^6KMd+Qs^^e1gX{M1&U3 z5ugLKcSeP~L9Bqsje+c=tDN~}8QrPMbudIo*zS3`CYsFW{p-aX`>rweP0Ha#)JAH6 zMC1E)$f3nVU6;>_KDVoe!a*H@HQSbU#=3^&=?aegOb-3$OhyNx)Mb>xdP~2@ERKMv z`8#J!D@V47kn=(LoOX+QV-25u!yT;D05kWn>>+_dz z89ucMg92=OrrhB8;Q_TEd=7K3ECj!ysz(i>psQUdGBra)p9~UFG>Q?a>|}tH|MAzZ z^xhTjn9JXu;*V|47)AYFgzI~H(-1#enY`~6;N&%%P2^CEIC#VzRxs>3x7E70*@UM? ziATBAdV%H*yswvkI^+!zcDss~kf-ZwgQ~0zm>J7z`fre)mpXrNx}-+XrTRiDGn7jZ z0chZ&Ao1;W>}6QkCdTQq?ZuiOJA-~B8W3-;8?p(coF=#0;F!Jg5#)&Q%r=AVCYx&u z29@o$wUPo|&zb=M6t`J{t(sdSe6U$kN$F{)@{f^W4$eweY3Ft*jlo7M<{0(VBmJxZ z8Q*l=PfSG{d=zFug@&V|^$0>TM4ezlGPn!}v|=3fs-8!eZ4&aOK6h5wbgKFBzX)TKc3U7 z#ts@Qx_dUp9tFvAq=_=*3noWZLbc6OdBj0cN;{g0Cn#ta4eJO&83WO(2Waj3PaHi( zk}n6Kh5U4^`OPtFd`ii*lu4%)@5C6`i%irigc-lkBXO97PSV1MgjG%gTh7Z=YE>!x z@dar4$5F$+h|CS2PV@=kQ0u}JeH|Aliz&aoqkAE-(fSMuD?bltLBKRGg<4s*F`FHp zr@b?%D2K1zb{Lj*jGg40vw%_`FQHw})y%3B_rcho>FjURk3K984k{u53p4Lo!u`;N zLq+E7f@M8L2Z)Y(p+VZMQnL6Fw(JR8W^l|?X8Q!^l`=Yae*C`*8{APa!y<@&_?tHt zaMC!TGy}NjA0WvWS3)RAIft%chYE}2xV~eX9b$I0Dirh!hN_IXT&UgT9Sg%0+*7AM zppW*nF{{jfSd$ttDuEn|-YjzuMjZ`+0>I)}BI40+>AC9owsvA$>$Xg^Z%C<76g1uByV-bblXNMhddi!%po5{BvT7Dx`pc0k{; zwc36xYz+6~t%}b$p`a_xyL5Vd=yslPjuTCL!cOW@JuBSwc&M<6TR$Su=Y^5CMc6UA zF!h}&*NVWZzl|x9IHy8{^A{0oAmf@io>$s`_(ZqxKANB9= zz0vj+5+RWwm1^uH=tH-}gQN&z^0EnQy?yt-UHRA4j}?nl?iShuQw#Tna&HSd&?cr5 zIvqM0_r6$W8i<+^l}E>f+4z@gmxcr^GaE{rJZh6kRMGyGU!SpFLg z>`m&mfcY1888uvp*VZuRx<9F34%MjLN<3-Ax!?AOr&RgM@-=&BPJ0a@=38(@fb2vh z@Lz>ou^LrNB^v4T&M!tkuOOIyf9bR0=Lc#s27rY7gpaonaA*%2uYTu&%}04%gjpHYF?>Ll{&skSkk+!L==dzY^xlpXr6H zPy26?Bd7&s9slttiyj1JEw@qT+sH|Yrk1po1$<$Qk?X$7O? z$(ZISB;I<=EnBGmouU4O$t2*_C#p%>bS4S9KUF^xzP@@V2DxR)-R7`HMZ*k9SYiSW zTi_?p;0>NRFOf>HvREGbG1%DleZm9D4~#(cciM9X4KldBWvJW_hXTyCQ>h5lLFnquJN|bNU&y?W%BYsG zwqXIZQUC%v$81tR5Ji5mnZm!2_-`mjykaGux5BEj`v6SqlxG?JNtK&)f~SpW%UF?# z)k&#ikz7;T>HaSbt-;m92xwK`D)%hs1K+FL^COaVnnZ%t#X>kEap{xRti;Pp)oUPa zxNXv7#)dBDlrJ8FG)jYUPl;xQMcWq+ilT>?MkmM04w&(T%N#>bFvItctV#a z;@|@PfI}9Ak$4uu&RGZX9aXv}R+iNy=&K|v=dw zoE^A9k?G=C{fTB28sB1K93n4+`p9aVb#7*$3y1g!o`sqs_xd&1ML}Y^z$QNiOXY+V z4cL6W35?{HPB1t%m&88=52${!x(e)%Qf%6;zWAd_70qL!oRVQXyZ@3ky6oamq*$N`E7VkAS+4Rpv?LFnf;7q1?*#O0d^ueRXj3jx|ov zyLz-C>|!Z`(5gPHJo{??u}QGY{>v{L=%2hcp&5jbK)Mim7Rdv3E;Xj~kK@(mzfAap zlsu z={eq6`CTnm&={OzC?06_W76Xl4B!}X`Fq${(uJ|PEPG2EKi!Slri%rZkKlnogYey} z|BS0E5EwFJPNlEjkM?^UWTx5qE91izTBOpGxIHR>oCorj!-8dd>3U=Eun)ReDrEob- zyf0b`>Xc;OQSf4(a+3oUdm^!5`ulD`L~&oe*4;t306FCI0lnd z|3t1I8wD%h^*0PR88R&MUJ>!UT#VWTv~ zT@z6wV~ng@CM{HgpO*0DZE&iyglM*r&&Li_zD)(DAY>v^9~pO$!IUY#0@QR!oFV45 znbl24owid-?dfmEa76!KYRyJ}SYP;dwYxorPsu<3YzoNdB!_lugw< z^cFJ294FY-<@*5W0G|tk-+*`7Q#3NR)4*nUd6-oWw?CWHc_k}=0^y;9&L#Yy{)2if zHKBr0cGvcDpBeC6K}9zJv9Ls4^EgoK&enw%wGFac1-JgsEh9Cx$VPCA<`iuYGzcYi z;%=^N{5@KKYIxA6Yf0=bVl{$g$=^{Q;4b@b$33Dgqu&^_(J%W@I}3R&A2C*-Z>zWA z;rZtn!{d@oNsa{8BuMS0*=Q=>srZQ?5c!Q)6_sAN##7N{Zm|a0?EvpN6A3qfZ*m?p zH{9NweRKBefWT6odz%C0?tlf(t7^Y#m#6<<@00$CO_^s z{kuJFnTfO~cU!YM0;A7i`@-0MDirc4gSngp^9 z{vt^eG6}w@ukZnyE~=lM!z8W2kD?WJOie+cHc+Q=%}IZ`L_>o}01Q~+9@cPzO)EQV z*?>93;VRVrzqrigz`_JHBBfHy5l241xhG?A4whi3Rn1UgTf%0_$T`+4`3?;tqniPJ z=i+MGLr9~}NoVEr^A$=}*ycRb+^=70WXmmG^G#Z8`Q$94vs=kUxtMsB;3jkk{$l4K zmY|i*M<5U{Qtjj%P-{!2p{PobM(0YW38(75zmAR_J3DG$Gb_O8AX1yx;mHtv#2~f~ zGEcS*`J%Ro}sZXm;sVVatNQvY$hyTU$huA;c&9g%6bI~~aYw6lpuX^b+?Oodh zsHD3v3wG=U!>u+`E7gFT5txipp%dhwEFxVS6?#bp?_JHCN%DT8bcn_X7ao}ZZSskr zWDioz-MgXkM89V?l2$%p7ki?98#{Gr^LF91qjw|=ONr!1!$IB#v!PK2eCW0))moM3 zit}XpKbWHX?_iKS3?58Oje&mmz0i>W3l%o)swT%0L2<)l+3kD>X5!J1Pso0Ao=~PV z1&D`xJJ2{%KmIRUjj8mx1Mzi-&d+q1a;4-PhpQU7bg-Sr2DKfD2Gn;27DPZ>$ zrS~SS-xL8DX9zLLPK%IL*dTF}-};0&y&<$}i6Us)Db;sgiH5jco)?|A;W8 z;kooi^Ra$y<)0b7aoJ6({ZnX>7(+hhWSO|rvmR1X6-yK|ThanHdJ&c>Y_~)r?Nghr z%W|a_92U-Z=1IVd4h(ctpv5{|EH6d0|Wg7~<%GvYiOwgs$uFzOA`Yftgg-2;TArtqF^-Y z8sY=pY80(sACVA;dQC|Oe|)pLtzIPLD5<4-5QKUN^|jY1Be1t>pC@hvHxU{}$PV8Y z*p6INF0DfAqdFtW@T$w8_J;5M>?pw`;;ZTpi&hdWFK~=wkb2CF{EvW7b5xu%I$j53 zLIO&$^9)v;IEKiQ7CGkiy?^Zp=F59tw@X=I5Ji7hs z_n*`CBficv-7Sw)7r%Y%G-hPZu2@n+-(h>;ZiNnxEUwWS>u0%M_foOADxIDne`CLi z6z*WZf7e)-t!NX6-4}>4m}sC}p4u-djV)Mzid@+A=xua4OGms&jYs|ZuA|bR9CG4{ zGB-_YlN;^4{1+(eFaJg+KHuRZ-P1H7`yK%o^qYV}{2V~hG|1u{J(D4;z~82s)CLNw zh;EOIN%l~vZ@ge-zaNhn2WdUMn*`7E$qz*`jtpw3F#+6_SUD|{*ZcF4XYwYoqt}g$ z1~)zhmT>k#0=n9YNfh2o_r91_y6o!}Uadcq*_1{1wQCbYpOG8|azxG`O6?5x4VeGU z-8i9jhqeCPk|&HIk=(NB!)_94S5-rM+!HsII@k&f`IiYDy{wz(p3PWq46uWaS2VYU zSGef-g*$nz&Db6$9LSw-^|q6-$j7Nnvh-#)+W(9kn|m2>yq+t!02{>R1Gii|6;@z1 z*73AWdHSi(1s}wWpacT@P3unJcTEf0@6gCb9b;>$`M>doa+OBVz?jQr!Iaqz}L;eEJSTSN8 z1f6bXwlkvh+_zHdJSScP0Xf(0C2BW$!lWpygGe!5HU!gfxJyoAL8`mBy~I?yB)?NA z<(Jks{p?1#E?O9Mj%a#cS_oG+;l4F^$kCb*B^dr4_$@b1Y6WiD!WPuXay|9h z6KLEIaEdOr`>4cdkxXCT*R^`K-YrK66G>ajv@yHzv(8D|c?v@Q(mVW#S;`NPoFs1q zCxC{}%2m+;bLvvDQK};NoET0UgK?E@q#T#Y5T)hUT`f2ZXTWvfqHDLG+tGTwgj1kP z1$LoVvWGS&A$;4|MjW$j@^SsQF`5-I2nBO8HAs2{5vDQ{58*Y9W=q3gLf(+lo}qX< z^i`3tQYe#M?z!b{;YFdGFD>vU*LM(Q5~%!mc|lmHqDJOWYIpOZ$}Xp`i3HLJ;%aA| z6nOncb2oenL7ipq`(j5i=-!_oD0hTCV3&=gQ}B_%G~Dcx+25;;ySC>fUU`gL0#xUf zOXp-AOWQq=a7K1S^XO48F$>&hv>S8{g82#DKR37RqP=n2FndeX#(++K7lmz?;`I;;(1Y~;N)oN z6w^n@U3Ug$xBX?h$f=48kcdtY53(z{$b)^eie-X;XFB;Zd>c*e#KhFoK;4_36=4vb zY0B)+e8GX$Qr!5ndo+9F<}?|65YQfeyab1)e-Ek(*A1~bJH@afCu3h= zkIL8lwAlY6{}p4e7u(Bi)L_k@*nwVzNa9IA&{7^MPE|b}%{p3{>u159Rx6vDNTA(? z2H#|^QfPwXE8D)#<><$dS(n3ArFn-pwki6kTF(H&Sl)OjfoqucE4~S%=?mOs-^Dx1 zu2-)f35^KOBD7uHl7xpv9sKNczJ9Xbc^-YHBHp%oP!2#4snUfdym%lET1Kud4DUYD zMM~JHY^@h)hFU|v*ZvRz2I@ngvPpE`rA?VjK)0LO+&0pW8v+_EkT1QXg;RB!;sVU7 zFZ|z}w5jN|Jb;QxQx$wQ!Jlh?Sq{>pQ>ljqL3GyknRUGbhgmB~;@ zC6%IvB`SLzEtKfiG6P2&J=F!o7N43NMj{D+WC`kQjMUu7p5g?dt&<6)iItJDj!a24 zj4LE)A;Y8Nl+O~5(RXYMtjO%-=e`eRXl8yQln*8uXe$(ZE3Fbx4=D(I1gH8~_n*zu zGQc0$jEBMk!X$sO6Wi3r-U{}gF9&jCPz+H_xcQ7+Fb03B4F15{8m$5>No^8L;w2h4mAVShM@SL8d^_PA`zDtsGsT z{}dYOlIT)X3Ylj5k11#$h@!4Jc5|-^NBh29%_% zES$pjs3excoIcTMVCnn1ezxr3^N{EOFySDv~VXKn+(j`tKYfFDxH zZ`;AX(NLkD(v*cnmBf{W)nfMfbm05}Gk5OaSUKA{zmZ~M!lJrD2frmhB6ADaM^75v zKX1&w3=PH2D2Jcs{;;+?G(R(EzAC4`u^<1v+aF5jcN%;T45XXqqc?2S^krrv;@m(c zC;dls;J?7SY=n@3guI}P`W{2(zt6$r=*IMG^7%V{=U+4fa`uE_=4oc;82~@G@X~!5 z&_aIul^r-kFAvnvYkG?~mV9+v6bxic9~@et?rJFA@8#nDxq)VR2dFZ4Un^xS#Y-ICh!d)xeJayMEW-uCsWb!-Sx*CQ}> zTdFy*qB=D*a+1@AGLTn;)ap|k-pLG-0#j^GTz2r7thJGwCxbUypyj~6LmoGNheI_2TLvAGU96|f>t=pe%~ z_X!zPiZb`yt%s*4xRd*<`lS%kHvrDq%+lyH8Ye;u)Y*+nu6L8{Bv*2F?xuL1;{Ut#6 zW0FCBrT}C4)Ao)SQ=C*(%rmCCzOX)YaBKZd_v_7ptm9&X6cG6L(4pWX&&c%KPk84R zXi`99tTQs>UEt5{w1cr3tg|zSqswnGNO$SIfM##n6QTuBQeyWt*N#OME-sKl>Z^(=jPq|LGO%oPi`&dCIgmGo#jSvu_}d~a zuPzYz9>M%>I8LAGm%|XKA@jS#69p#uqQ4+I5Xu=rJX)XWi^JH5y^Z-hA{$P?_!mJu zUZ3eb;ux^u$LWE)vifhpZB^AT@UGtG7fwUhV#7D2PpR1};+y>B55b+U!Ki=Vt8dN^ zFc+}w%zs^3b$@dHi>>_iIOWORVt=8sk8^S^1@?G&TK$jqb7Dsg?)=rY-e-BgZRi<) zJFk8_cz*{fW@6pc3FTxKUp3D=0{1+xKz6EUMesbUa;ger~z8JnNHb4Xk-Q%GL2C8zP4falt zLidabBD(GYmeTkmhYg59+70!Ju;qu1Fu=c0fKT-;nYp!{IEf7%L!)sHQ$snv&-6$IOqdF&Y#~*hbm^ld^^( z4tr?x;1g>}?9MSHjXgulkzLk`s=;}%>?(bLLV*`wriirr#(OV}T-s$db--8Z>HSe>yxU!C z%@_0SMeFLYt7>N=*BoE!=h5N!hPC1o?_!GXrjd`($^z75u0Ub-=sb$agp+*RE+MIc z&5vOF_gIBoUZMrD?3@=YUCk-(Xnhk^=o#>BD4eh6E*L<+F#)C{M{nxbv3{Sx+fSP{ zjbxkXfK@DYVq>6bp7&(vw$yHYF!yGB8A;)o;!6{UQmOK%Z7})|3&Q2M%(*(4L+DCM zwB|WC?X^n+eliMrbA^T|OXHC|q)~zCJ62YKk_n?rxi+8=*>9%v#n|mn^*_F%iDrTw zp`PI?p+WwQq}DeT1`_6~skN&H_Pt|`QA8cS`@r@rrh#LKBu_{s79pFc15-y?%r^KQ zuXKF^M-#pwSN@#CJ3O|a7H3YUcxnEKjRQ7u#3azqcBi;L~-qA)i z!JODKZsTH3-PhSS*Oe2CkvACUe<$sN25(wAnwNaCt90nGowJh&juRc*F0D`i(yG{g z9gy_eN;P*&vz5%`J_Z%BPs)>QM%C z6oNbh(B7)?Sz_YIYD2sajF>B+she|qd1?h#LQRXQ+0>oZN5R5T5|0FvWUb4w#r19E za4TfSOf7b<89&B(r4l3Rcy;V%zypt5+%$^=5np6 zY#}dZtg(!(az9_!Ozle;(N|V_Z?w~i41k`=J!YCH<@L27?ztzM1@QCnxh_CHM8#UsX?f;v6ET^-2##n^ghvmQ5Y-}(~;C}t7j2;#JU;=mQ_)CG!- zWrL1I%vLy^ZkOA=aC=y4y;&0jlzJKRx_(eB13oiBSW=UnFQ|;M`pJj%;A!jPvJNz@ zwMdwcd?_UNALa5nDvemA>0x6`hIGAJ#<86qrj959p}^jkv0PcEptVW{)cBjN1zyh* z`dZsoL%?g@Nl-GJSUM5Rp{f0@xP<92OL|fSX#Dp#RPQ{WOR@B+AwzPAi{8&kJRX|| zTL4%8X@Dt_ozda8WFXun!ky!l_{=@Wsr#X$wYP2fXq*R4cgMso6 zETXGN>C3}_ngZN4*KOI{sg(~WUtzndv=2ZYH2hce?VA1@yIEl`booK}c8{9N4GFt(N=_ZYI9=rCCcb7M*s`#wHMY0MiMQQ#t84cos^_Y@*w@@Ga=dH z@K&$cjTe}8)13Q+{B8i+NP&GkH#EZ!kG$*O51-kVf+rl&)=Jd+v0wcE0ZKr%zo$|p zlbVBoO6jYxQ9%y<7Vb(!>GRXYIlO{$Bf&*N4O|ZjA>D52X+z>fB99UXx&Vhp$P1P) zXWEA91q5KT_+BVFVx*2j^F3cbkJNY8C01~D&o+DKke?f3^10K*ZNH%R8tn(Fn&>u!$+@ekh7Y&|x#;IJ~Sz8{2 zDuN?TL8hFfemmz+d8(F*R-tD@MMXYafT||24z31=BFQXurhi9)UK0M>i%}w_l{x8K zt89eJN#BY+8w6YFyeYm#Bx0*Ah7-SyG;ZPtmdiuGHJZmsZB1)BUm$n?gxAbO%OG#0 ziCgV@o3zsaoc~l-BvezD?N>q0ydeyak8K^F+ zvf@D5W-aw)46XRILV_#F4EAbwzMH_@zAZGmeNWKPbpl@kb#VF$lUUa(wS<#0|5*mV z$V^xoXl`#LvMg9=O-BN*=M2_cCV$Xp83cs8-$-qrBA*%rga5&4$Nq`mZs{Wg>qPS_ zKgL!hLqdpu1h2!@ITk%KUGbMvz(>kbmtgK!KTBck!+2nKU2_=>m>k@fLu!uwedCeK zz@&;kdYg~2IP7rd-)odxBBdtEK3xB_1jawQbyz7*Ha@w}i4T@Ok0<8P3ma+>EIjpS zERY$sj#Gww>rrSTVVlP;%lLIInw$X3WWo=ZceFmjS)Ufdjvc~NT*2^S?_iDvD3NX{TGckn>!sEg9&Fonl+ zb!5xxisK@%pCi^;!&A2XoMMuIZ388uJQk;FlR0?Rfy$1^@7zY_4UZvY3+;VC_RDU< zx3#rTv+TSR!m+x&OHigPnw~NgRN2=a=!hn)U(u z?ouDwr>wGzSO8HIrXS10<^zJ9*`+#0p#a;uOz7)wURtKKn5dR;kGN zt+GiKH#$8nw6Q)X%inlsUP8{PYSd-h+yd70$C}prtE426XX+IX+2_$|&i0xg?VSGp z(E*5HtO^EpHmJODs)u3G#tnF~j&So)d9;u9N~#2t1Z?;awgQgD&nVcZpB@}UFm#*; z@3P8Im`#bzA4Jt|}54f|y?T0DJ@9W!~G zqSNSUN--qzg{&q4JxZJ*jdfS#)ouIQH#6v*W1j- zW_s>rCdd4f@W&eWBKS<&1jOE)G4%|_IYxKiL0up-CH*7h*;rDI{G$g+# zrLHF~@BA3bRxHV`BMNSw|ssrVPW7 zY<71&YUS!4_P$x@X8bpMt_V2a3KeODad>tM1U*u|c1Jy?Pbo5|Bfz@1qR$<0rjjMN zb0i!UR>%sBx4Ala)Y2;G9TLpzEr7l;gAnuyi3h`LV2A0r!WOv z)^I3Eb^FqZ#-8rMH*QYdFa^=hSU5YKg$d#t$+e^{{vTTUo(Zk-u^&3sZ8A=p3e->8 zv*0zBY>X}X#!zzOjn%p~c%L|#3Rc`Ig%1rY2#L?4g1$0&=E7&^&x5w|n53#t{ljqw zgI+GOXSf|GKo%^)Oy`8d!M+eaiRV4RUMqIvT)DB^EcXwFvgwM>n=7h8RDNhR4j=2+SZkihatm-Q7aJq(D9RuUYkaW zbQ7Xd;|dn$E5oY)Z!6SW9Ba&VRXHxbRsMn%2MPJ>l6)rWQ2c+-rIsVH@)wTqLVmZs`KVhlD3L^7*K6>!kDb*smNt@p!^$clht;KL zz`Uk~;R<1{6<2F=7wrG(6$n9H5NAtD-X5al{X_k=&2HY3+O~`jMcE@;Dh_3ONG&KX zSJ@4G!Lj*RHCg1oDgAiT$!nk6tY*11&1zDfXG4skJ;-d1zeKk?)DTfK!A+oT9u~&Y z>-?riRZ!1|zqbc5D1NY`7N9s(c>?4wPPy2yU zgdJxpP3pv|0K1{F4f#x2C|Y7a0W3zYy|RMOH6C1{hM7Oz@@r2~n)i1=;od6B8>}zO%fKHgyYuov^nQW^DqNu zaa`p3X8pWzxS3-kZSbpXWO^ExjfDwA;u20`Z%_Njc}V%~;{MID!K8t(7V@$|We!8D zczv0ek6h{_RfW-Tk6*n%Sxq@@}Z;qbuPI>sKcms{YOV0lfIU2>7=BV z;k3N()67qIWm)m_2>!FMi=0XcO!a8VR*`KcVirJ7vPFdwj>^C(9UmPUPkN50gWflr zAMhEw$y(jleJzp>xcBNP#`l=LuraBcukj zQtv}mccJBiTtvM$iy0kyLc^T{!*`bXLFf%ONaFgna7Le0AN26z-WZg<>iyBMd_Bao zdgktx%v+_?tMtpY>rCEMN*QzRLlj)21JG4}a2Syq+_s3O{rhENC- zv@TEmL@tKW-qSam-;E@Lq$SHp`Gd`*8#TG}2k?jw*i63gggZ3b$6-W^-K(s_k}Yvm zj}D%YnIu0%Z3$6G_w^0AaUtdndQ1>HwoAh{hZboQV^587iFzEjD`D;LG6Es&zIBUu zx-tdF)@+%ncLy@*`P%aB6t0>IYr|z5Noq@qqh`^*I+*AiPyecvCt7+5?XWKiB+#7b zKTo1UKjK|1k%oBqKF9Nh+%*AaB6cI~6ygrLwh5IFBWo4IBs3P) z<*IOSEMSP90h=}AZpdx@;9_z+vvDuVlwo((a;Ml~BBc9cZS_rA!q1>3;QZ2!_FQ}j z(l3_+1;C1H4yM&xUR9zO9yI&6(OfC~x*=^;8H@=X-FuoxzTB<6Lhi`_!x$U`TDOF53*DdsLa7mRt7jv@yTUy#(Dt8w3;Gpx9sN6WWFp%H535%mBGwv6_es(pkvWiRbdOV-NMlK+++l8 zin@%gSvxKhu|r&BlUs?f0Y^$Ezm*-PB)i5DT|R+hi05rMH{P%(`zM(XnpaGGjxV6& zZrLM}4W_u;$t^=H-o-z%hBt=uO0NsZ>jaHD^vNoZHc|RTX$~h@`FKvHwshA=CU?Bd zhj4?#lY)S~ye`>K{?0ny^n798mA#Bo8D~v4CY4gu{l4W!BlIGLa^zb$M`~p1;4SM} zFP&$@7l1fM5hs}tSQuYN%9p=^^BvvzBlifH>wE5dJg?Uvq_^-WWpHDs2fF^ox1)b` z!Zg~_nFVuFQRc3)P#R`PkmamG$b1|Kh@k9W5n=c#f&~6)!8>Ji_+z-aqf!IEgHSf( zPl6BDBDBpq%;Ahtz>SWTQ)%19yvTSGHF<^0Lhq=v=>X~;*^RH`hyt4{zaN(1!~3ms zF12)t04}PHF$36**-u?6P3^9MfGLZLBRRrkw9m9ZY)<-k0Yoy7wUy_JfsuMwG|`SJ zvw*lbCRhk3l~%7LjIkkcj6vV+KDEIOG8o+-#>saRqT~DX9zUoRR|d%Cf&qo!#vv~~ ze$gWj3+V*=s(MWZPjok|+BPeGy{K$SQ+xlj-xjfW((^yW3k`{~0pMUYZ&^-2)H$&?x zaGAQAfY}G)%MpPNWMd)DrWzgtR!i>aT!qSnPN4d(?er5v-D(gwS>Gxc{Pw5L_6fyo z8D!5wBNM7nLLKX&GO`&7IeOyio(2P84E_NUu)hUy7O|rGnU z{~7~QiaFgvdaSUX#|3lWCqKVk)dWAjz|p0*n5$Cylb6@PNP1EuSpm5qn-KUDrMeYM z&x{2;ZI1>oGh0d-?vBsm_Me{#JL8-Q3ZGKQjF7{5s?>}z6zz_<$G-8bw`0lKbuH7n z)19-;DkiVG@UWG9z4D!&7XGc=&I|+H^mFGnSk;DJ%anB5c%H_V3<`9O@7#Vf;LP@E zIZ?R`_hX9FXQqm3W=XQKNS}&Xa`R$u>@xu8$2*vB(dUu6H_-e~l>8KZx;h19Bog1S z3EAO@L_b^GeRR(;D{Wk#FRL(@TUeZY{39g09q7_9sqh8Z;TH8z9xCu(Fu zaopj$hP@l8;;o@nl~-?pUOvw13CXRUDr2jrv&S|hofC^&`1r#e;jXe3`J6wOL4Aqf zVc2MH45%bz|L1YPyfuZ5td19-{Ppv3&a3QLO7<0M-r_zkblbDBo+i%psGy~Sura&` zKo27tk1-?Mi0J39ynOF`h#147|3_CSz0|(vU z{=B~78k*mR>`@sq{=Ks!55uCe2W}j%{4y8G1)53nrJmKS^_xyoPSpur{`O2WU}>f0 zt2QL8-^l*`uD4*D1u5Xd21#$?>nv5MfIh+`u+S=nF6z_m7p(f4zI(+)$Oh3g`@ur$ z1^SA@Q1G??SZm3*AlCrf+{lNBHVc)G-rAUBjT0I<{$Zcr%f#Qow)mxpE2A=BM4ym` zgZx{^K$j5bWp)E45%sNRefWr{4o0KoQ32PW^N$39X%%+|CSZR_jxFOC5|eVTlp9<=3ZUZ?}|o|*mgYh3!zS3#AvoIhn(CKwM@$gsU zQC79|*o{2PZj&2&*2M{)rh!IBuj1Uzp`dm|+z6NRTZ^vadQM22ITu7xS=_M#c2&Gl z+@r&j9&m|A6Vr0s!_I&36?2T_p-k&cBS9(8YNy_T_gyWODWF>{>zOUl<1f?XJH^WO zlF^4L@LXlKRxEvEmRr1A0amAb()d&u|2B7em7U48gpo?%yCd^6Qn*qE)(PEET#+Yc z)836$^r0v4cq?%_3oTOmYBdxqomutY&D{&0WF>g8V5M0<^8X4QVR9v_1?hjB!6uyh zsKq%X9)+2C|4LV*hs{6WSsbk+62w0>co<-vET;fj3i&Oe#8V-wKxtD^8a1L~R~8}+ z^)&wDhf>K8=_0(G`)D_aTw_dEAC_e;Tf`rD=uFw*r=>1TWgTql{Oc8w+cET-M|*JY zNOOklWiWfP!Ure>o4EGN55|G66{NYc2)*Q7L}+<4OCbr?oxJ?i4A6S!TmItVB$SX1(9zq9ro_xKz}ce zi<<+2ViZWz$6(5HJj8DMS;|c6=;8RsZ?=m@;=KO;kX?+*rIiG2QpX|u)(ZM%;qfycb6`=jE+zlXkm@S zF(wQ5E{hm}8Z|de4xnlZLAsSftl7Me_x>bG>tTZQ9cG_74trJ()aat1MS5jD8yUz? zfO%Bxhx-5&msJ#GUYQeHfe$Q+n+-BsL3t?46B__Go36QUYz69pBnfKEN{6FVDVGjt z>+T%qed{WTG5*x_@MW#a>c!5eDD75B{gmbm7?ssE+J)5_ovApBG4f*8Dw8oa;xWuh zZvJdv6nBc1Z-HD5%_2g9pF=$-YJX;)IcXRQAT!;IPZO&X)=b^#bqoxT%{^2$(8>L> zE_KkCbCI{1Fap>#e`P@qK(vIa)hG>Vx$q?a2*h!FW{HhoBsC_z7kxn$#Ii(Y>T*+) zwHDPY-Jh{>_9h7!mnmTAb!d5U0PaS5)YDm~ZcXVxu4@=aAJ&Ykv!qe={%G-G+i%E7 zQ<*ko2(=-z1}9IXlP~7i47CUjdaPZGlBOq+MgA}n`f`Kid9jeNvB)^RRE0%5HH48w zHNX$1L_!rApVe*lRTimYCg!4xEsnn;KHa*qJDls7RL#Zxh7iJ0$IZunu{M|MN?4g6 zXN(lTZ4glJX+zX|jO&xsBn##OU%R@gczRC4^YVnRoRqZQfPut<_0C0(Vn=}Y5clxI4|zA9c2aebtsm~^@q*Q~ zhuh+T>w#^nzJY?8G=z~Nn#?-x`Fm@?hh=5#`!oz~xND5cAe=X?`jtHtevcTD;RNp| zG=l;w#r@~{I7RR~-bA~hiGtLrYsQ(JS$fV~M@5nweTRCKspdhq^VUck5(9{wor>>a=g5#`t z+<+)*Z`C)4|LS`XFMuzZ$^)4!MixKCo+R8ReQ=}6T<0G%@K$^(X7@3twxjqvYZmu@s#CXAUrm6Bd7qMeANS_ph8QpTY+r~h($bb=0XR$tw!4^Gpa!$l&WwTs-!tY^gXK9YIUNX zJoe~JTIZ0Rho8LF8DBgM=+>c^M7PaU#WN3Fq(@@=b5Q5Lpq+nPsm_#qv&dsH^l>gA@OI$~1q>y^>g;kCtN^4l_4=MucnPbnZ> zVgIz$g$MJ@?b>fA>m_u(r2ey+l)26akIp0PB^{J1`Ag8$&(chXrcU%kgYHM*1{}8! zN?@yhzvLb!x7kk0b2u_VX*vS1Y{>P;*{82aIquLWmh0^cftELwARzv!p2-W={n#s2 z_jvYrrNMO18%VOUOjhm9>;RsyM!2`pLeg(ZBz~OV#3R4iPN(#051Km)Mw=~kf9Hd# zXVI#LH;&>Uyo9j4Ha|&Xc;0l6F82Ftk|Q1FxuL^+4-&nD|J`8jHSU>I*#xEX23=;6 z6>s}jCr8Txr)bG_C~7$(u%J3Z?fh;$4N-e!AYtkV>(a^an->!?ZHyTRb~b+ z?IxlXSZU-!pRbq;E*+DadBFHD!L)SpcE0r&o(Ozzb)|%K7?+L0 zKRNx-a%Y-czxBb74HLIkp#A!w{%%99-(6I5x-M;XO>Iyp!yoWKvdA%OSOB}Cg zHnjzD{xS|K&6AI`Dt1HtBRg8eE_MR8Tye7&_+vdEVoWZd^$X0adusrjR@+@-Fp(@z zK~iib6V?iBJsW~c7W@WAzH(QS26xVJdIA8CthkaFp#9Wh1W54UT3v-=V2EfIpq|?P zwHb0=0deFfXT{rA6;B!U;HRX=SmB;++Bc)EesrBt7P%(sJ>PorqK|#UXOiVZMU$o9 zNFTxwvOaDc_%nL=2%fwh7#z%4O4eIGBZ%kWz)vwXAdI;z(^a^7LriBW5wO%rI<`UT zb?N9F-t^mTQcPPMY4-_CM=U!SKZfnZwb7(#$&`q?!$96;u1VBRB$cHtQ}7h&x}HY5 z8aCC1JYAtFhDvxLk}O)wh0}JmaAulI&uMSAhyqx8M*Fo+z+E9-(_GzQI5bMShN1TY7B5 z0NdA)ndv$zzIa%9DO^4-XQ~57Tzwf!w(Ws=eZNH$-pC7QA2Oe1{9yIT-`tbF*n@AX z2v5Is%(vP&XSOZYLr39p78gR(4H@qedg0)=4T(xwUFrm*xQ{v!di<>Y#ix>_Tlca< zdoZrrARE%2lu76Eu7xjX9L#4;mMa11nuUJg0l`9-Dt6aJS6bV6x$Ca|*@_4 zltWyfpj@ODGEdMeUhZB+Nz%ntE;YBDc)dzVkVq%P?-STW)yT4#Fsd9{Vni|@B`~VV zd~DF2N4y0z>k_-jiovR55xvGAhnq^S@t7K^xY~MJ;N6+=A;Go5UwG-~W)i~(%~83? zRJzL+ly#~;|Aad^Fuw>P{ew+4*7#GPy zsEd7$X`R&!bITl0MZesfV*IibU-jjTqBweO2`|YXDJ#+THx^N$}xgE~~|7IiZeR!PMK~q)(C_UU3-tIMJL5 zTaxkD8%`#{@!%!E$lnL>H#xnWpopDzD>MP^G9snZsVA{7-^r4{Y)bg=VDb z3ncZIQTZ*aQok{pkV)>T6odHXO@+cx*YKW52plQuQ_8e-o;{eD4540X4RK}Y-*d=| z4X+qNO8q)np zN;=SnQ(`nW6~e1Ps_B8(5OF$kXuz_Ae!=^b!W)Y!q;*zi0h6z%C~I;rwnPxO$p{ z+QI3A>9IQSyS0Zi#{QA-mT`q45}aurA0vj1NiFU68|TEd``(V7RhzgghGUY$3&AD< z{tOhIPHzr(S+W5@`&EfC-UDtgh@gYotjH+O7Y+woT#fg2{&6kz| z>AHAuxNENZN{%@8I;($M8=WQha^2;3xIvXRTGj;`#mU`PI`W!Ghzfxz4N2DHnz;8-DX!=W~HnK~B>CGIbzk1J4Y>PX6v6#_Q2Pn^H zpfVnvbF#Qw!YQFH-Ha8yw!F?v-GiwSG&%7xi5Im+AuGX{Pmp0P-*RFx2JKxt9+br* z`+_K(C)UXI_cJ6Fua)TIl8-xRgpbXN*^E_=esmf$(4hp=mI=^3@WHa`KY9Z@PN3aG z9m(2h|;{I!u=ucAVkcV?p?>9Ter08}A7xigAm3QJtt~4{$tzvVc2|;i%AtuZ3 zP2^4TGZ*@B{6{!Q&HKizdlg?!iI-elBABl1ORav7q!gaIX^V{`?ZgxYNw#gw%AJ>= zO2t*32dlEs4jUo}(QSYWo*b2Pv0X^iDSS^W19ydL9d)By%kSm^4zz8*=_#vF@?;bK zsy05_HvkiPBHF?d1=-c+Wle3iTQ|3p=K^kxDZKBXXu9swJ#3_d96l(gdGjTqY`I)4 z56hPjj;v*GT~g;zqom%p&6r&C6h(zE74oKyiP_*_;M>6E5y2++kFOEggqHWbS$gU9 zC8mEjds?MaFRFqh+E#D>DR7@mIKsS6rEV{BPihb~of|gdvp`e3nM=tmf`fj8{Cwq5 z)Nfp=JJ*vLqVc^H;Xx}V2MnA|ci{eone2W(-2GSIe~;G7muk=bEIr%Yy^v4wA2J4uT#2=>D{7v1qWLgNL6`A z{`;^v<_%?)RmefJ#_Zjee_wgG*NFw75?O}*-L;U-@~HOK)&X8pM$yNwPd z6^LxpiAIp%zOWpRtu8Ye*CfvGF~rPVN{FYd%&;t>`3!FGxV1;Ti^9~w4tW|fcQ2XF z>3B?jOwqY=^RAWRVh?uHvlm|;l&xxVj2i+D4D~D`qYRYk)}IlVubj1Z-!1CLvX&mv zm$TO+;k;xw&*b|W9DKq(WNVgQ)_B8ABVtT>iY$cb*q(n0m=_xQi4j4k-Oc%l_%|0) zV@U*>?Dq!wEyfWJC=8`5YeksxI+b zSi7cPUZS`-jQ4V@mYOffl6osP^hwp_4#}boppe@d=0RaVX6R^St!X&b_wk|Wg{t(i za8ljrjVyb-AoSsEce9#Wd*1ax(0xN`&MKK2h52}W`o(z%zq{AuXQIits^s*Wqvw_U ztG8`WMrYn}1=-gDHf15e$$RIGgVe7`_lFXEQ&A&lMR*0-j(VRF{gK zo=#jmc?J>5#-|Uzg($ObXrDQ-E^i9%2pRm;ECR(9hB)N6i*SfuK8A>sjTg%yn!|*0 zmS9=B5xa@YN+FW)-uetaZ@Kp*Kti@mYrL?G)3nqZ+`cfu_Pt}v6PTNXj6U+J}^M-NdLt$^%-AV4rd2^8O7;WKO8@kt0 zGxR`cx3E7jvo29e?8=oLr9aHs?S2iC`WhIskMP`rDcnomzbQq{1yyPAQtn=&5?m{r zYDgB6RW)Ei&c=Fds^jK7F~6b=2&L&RU5bG@AYg~S@txia4&5o37Rxdcx;8=WnIJ!2 zG_$P+OrZK9W4_6%c(js^@6=3$Jbi9xWnz}XFElV<`6X*oDdgW;5_EOriN*7{7Dnd? z9};-6j%B{8jT6Evo+-P^7*ui-`MnrXY&Zg2Dn9e_3R8MIN_veS#>ep-7_}CjR&S;@ zjo3Z@Q%+n9iSWjdnA3Vb2Hi3?c~=TZX{Hd((Pz*>#;$~Y>HDCD|E9nyQgRs?Zd1hn z$PbC#RD*8x94T_`5(kJrr<c<(mL$xIXo2Zek(M7j;d&T8A()Hl*UM8^ z3>^}vH<)l11C((q2*)vVjKfX#_(miHHuURnc$?9ZzjvWhJ~FClpf2S`ol?2FIv2dzjPltiOe@nKlhLDna-Jf9w0_15o!Rh)S6r}| zO;Y=bn8sLhLJ~Qh54K_rDK7X}!3V-a=WRT4{DQ0<>Fh(AgW2H<)h7)9@S!UY*o?spbX^kCRqb}*m7 zLFHV~1$pdUt<6C}Zg~jOS7`6=4^lsCv1QL1?gh1vzu;dp9=Le8GfM^sL8Os4BX!%O z%=_;t7H^EdIQM8zT$oWv+_sTrI$^S*efdh#{@J>cpkaZXR)3Mhl{Y~6{>q7AZ67gO z)(j_Eqt7e~)9KeG25rFC#&-R|eK)MDpAhAO0jc&^yFA#^dD1#zLFUBYmM%*V7cIiIuGTkYUTpO*T5 z#bMCr=Sw=x^#0zAKC%NN&>bS#E}D%0+saUwD*RBvBC~OS@DXSNfo|#hxH-_%*YhMDkJ*3MQgh+t~~P--i9+ z+b6%|gs*9tO;G@R=#+)9V!CH7%HKi%m!Gv~>k}U#BF{x=?oFhhQa_Ol_Fn!-_|_qf zt6@karbK{fOT1oAi8fn9WFW37i(MJsKFcRJKhsw4<82xNgZ%J4@UksIQ1+hoS4OSX zqdA7K>Rd*3R$y32S8+?c^|lX%Njd`SolIU7aapFjgJH3TQ<Sx8aW@tZQOyKeh*kYmg;mU!{yZ3ncDim+A!;uvAkgiR`gt!YnY`xmq1 zTQk|dhOQeBgu0svbl68*USt&tkLS|oQPF!;CTgS+3HkM0Y74q4ccJ9WG)W^Ntoy+2 z&*c@RKTm;C@&T;&iKR z0%K_F3q7&&D8isOjEQXpp?|r9%dkyFX*g~?LEus0*r^-P8w5YXXsqZIo!g22Zs2s^Fs{eg*I+^^)=I2tsRJ3N7|)qZNEuQc%T5 z0`FHia08ab#p1>T#O#h}HyEwzA(Jmk@Uj5U%c>^SO`!$E9GZ~0IqPnsAQF+C)R}rS-fOT5HEjc{RDCD6AH3U zz$H2OOzHH^aBo7NhC6t^P90h0Lq$;yDQA4}HUw;qWvTGU*Ts9z6FFxeDkGiNC_mTK zPq*U$VDPUV%2yQzO$;hy!O)gN3+th!P#*7^q1$*Bi-ZnY_UFkWa|Ob* z59<5;<;-KD*)U%}j4yTzn3(OQyqTL524ulT*2Pz3FYvCnAu4pPu1qzNt%rI^ntS}7 zvq7gMK@Oh@{&WC7($~hGFFb-6Sj}Ea<)KaLzs5C((&7}4|F+~q`-IZscmate(5awn zpgOM+<$?Y+vq~>oaT&m1FrpF6YN^@q`&x$nSb0P62O#A-#O0_|^-jw)`X}8l&wZi* zLrlm26T=Za?#DV_*f)XJp6W|x1K@~$&^NKVI2{uYo+UXslqw!>O~$tsQivXvrE8?S z?Vw0_vjlQJ(6&tMGjpEWhwW%4iKrJi%qMLAxFU0#cL_<}tqrKd8Kp2jH5Y3w{7;vX zibd`HPn{h+KNzCA>>w#4Lqm}nns%S_N}%?v+6?9$f&kd^oEGXI1P6N)n_JogaengV z5YFI&9BBIx*GJ_(>$?=T<5}WPsxjRGQ``BRm#?34uwcxq*w>4SdR{p3Q`&--enfHNu=BdEe90Y>Y{zc2;~KmXIzbSzetIo_ zO?#g_Rq>xjW2G;L>xy`Ip8liji7D@8Umaa37{0Jbp2f;wkA6!XK$!PxtarSz(SSo) z`t<&??D7~481&7H-$1nRixB!)suwrtQ|Y(W2|2B5z8VWd7^Ma_St)ek&f-8xAF5$I z1t~kKnz^n1#$j(^>2`#QUb~!clw)W) z&k%Jix*b2?gcs|R9>fC54S_m4p7q*hbAuPR;2Rt>ed$`x1Q zXclBKlJ=`iLS?1GS)WzmG^$G6{~brS>QntaI=Y`c`|!ZtFkX7qQar-e&w}M(9L0zC zn&4oA7`gX|o(d__huwym02&;0zu%Qk6Oj^fc#$+xjy)}l*snfbxx9Pfk6yQ=K*n>{ zB@x^J@Q9;^%Xgq)wJHBmkYUlC8vZKALJPiu>h@|10}f|Fz+j+~VnSS+KrUE$QQSqL zSB)%2i9;s0sHFQ_3p}ZO-zFrqDJWV7>*`^<6F^n6Q!>QzugNf;zz(Z)Yd&fbn+|-g zkyV|>rL(%VRv28Lh!yT_7xG#hi+!Xo(R8FNP_l2lHWOW&(sUcuqz|wQslXK4Aw>J& z2rk$Zv%HQDP#?YQ**qT!Q&=Rk4HYNOT z=#u2ZM`sttr*oJ4Aq|GewkkjyEh6K+3N}wl$^K-(gKG)KbU}LL1IArcuytE!Vkjfx zkwc3zV2IIbV^K?K?zmV@YRHKF{@zD}ra7kCk?)UQR^#dmwax(o0RURiF?WElZuU9> zF1iJ3NqZO58k0lhgK;XZ!tm<@nl?<2Do~Lmi6tXTlQ;X~vl0MN19D+b@?sB$8?e;pzyNwD{j+5PYddznAoZ zgrLO{Xu6sPeXGE?Qk7W~KsmtwTuITbnQCXN2^82pg`5VckrYdmJ&D#iX8f4h$}+imGlVJ>y~}*k znLQrDxH0<3vs!SFz2UQfN*#&ct_OHLmrex2kv=1vQsvs%VqPj`yVmi7hEJW->7V#u zG6K7_ON)WoFJnj?&inKxPS}tQ7ujH!HY$j(>+^*{tsAi}95};EXlb2j<_o3b2!Z3%nNK&Te)&m_(`NErH2AE<7nQ& zrnuGLbQ@T2!E39YnF;Pv&)MCjZbP&_;&&+KK)$lB)l^Fctw`F{<9EXIb;{8?kVG71 zJ{w(W!PUa5-wu`qQquk>=TZ~nw~5@xHj56P&KF|<)v_}t+cBFJ3AUYWotOhz=io-- zk%I8>(f8E_TS99b>9ewtMgxIUACeZJKqCFtWBu1Z7$MC=0EVW$KJt9LZxZS|)p3}t z6$G4_(CCx#T`N8_a&VY_M z4MFSbh4*Q;IeXpwi=V}05K0o}ZqO7>o5&9TYAR`>+1OHS`_sopdKGK(bdl)>mMR4* zJe}b63O&^LcsWr0imin*XxBehZ~nfCM>UGnU(O)pgWo;;b;L6Y z+!1jAY!}rYm_K13r@u%pM9bPOufeU(A!h)7+T^Wx&+ql!tCSK_v?yXf(dHplTfCxd zm}<&taZcidF?ICk(nsp0zZ>jR-2t8ayfB%o%TWpp#i7qtoi5idcz?-Tb0;8<#~k`j zCftQr1+UARqyr8rK<2A-0xX8*PB=RN8~F=f>??Dc5Sur!eu`#}Xwes@4rm+K#%~?b zk}T{C4F8xtAX=eFou(m#L?Y0sOABWPh&HMeX?GrXL`p{qz9`^bK57N~BgU=v3MLs2 zy5V}1MRh>*5Tjr+(L3pz;ysWs&Oy_hAkIe29FYGfbDofyq_vB+J~$`zWha<$%7?JP z4kt-K3r(7f>QF0F8kNv=r(`W&FnascoUQ*I$E|~liF(&4vt5Rq_k=j>b)?b`u@n-~ z0VT z-x3i9$G}{!C6v_nE?>9cGe9dQdEy#jY>QF5oDX;g*~my|%&GQyL*I!QKP zlpu8F=Ca;95}EL!=Cm|``&~J;QGrTZhT@qpq1wMtVI@QUUhJwGG9XyeN#ZuoL)~3p zBYzHLl)pBk7uX1zpzO`fK+bx^mlfE(3TOk^u}*bT#ni-v4=({~Lp2WoGz$Kk4MP0> z^|kHX&lZ!L;%Ce;pdH@c2=y+wv|Gc0DH-uk@epxE8cFZbFd}zU`WwO(4!BI31fG(o z-;)#E65vph3KL-gHrC-#J#)Da4r_#q zFVHlCX+yW)q&$6$5^*iMb|T{BPJCrIbON4mlar+Q-N=RIkB7Zu1?Ww`BYX!zAnB!* z?U7U)N9eS$B=I1l^m0Si3FPw{x8?7bFH2U+l5s#W6zDQC^_VEADJQGl0Nuuv6FWVD zX_8}H>i1JRsDx#HT^$nQWOf)vCn6DL$E5!}Eh1IrpV_hBJHu{F^mDo_?MOE3S7r?g z<&?2yEa*i&821^#0%O(JG)NscU}h)LeE%6XJ#1KrDZ)}(0X1yQ%U$3M=!0G~I?-u_ z{xB<*Rl5h}y+7KNN*k=%{k3h|wr$(CZQHhO+qP}nwtdgP zn2A~3%`7XUqN1Xrc5mjBc--Z?SZ3%@AMa6dDYhf%rBfOaD|LMiy(#@4zD){IqDQ36 zRkDR4Bkx|RV!k^<3xUX87~~`O0#nQoZ+AiR6^`uh;bdq3^%R`qdY32!t-wlhh@!b= zGA(@;Zl{h@@YJDmywZUrn>mMFitytN5KV zGXN@+r7@#|_S63UwSkM!3Kqyw?2Q@jplxccK;*Wi6c0{i#3+cwKa{>)ZNV-vNJ_TM zBQKkPOEGszC?uh5UgOP*P|)>UtJKo-O_HlrYd!eiQ;cd;cmygj7UB@zu!_Dl?+T%q z^Ww`G@Kb|E!w=ZeV#sM zylIy1AYN!DI`!v4`KO;$d7dc?9|VJ{21~~#c2Pf#VWA3&Xe33aBPiL<;DBIn_e70Q zZG$Ww^fXE6|hwSw`G%tR%&!)jIuxSac*POPaw5 zY!V769+UfY94M6g-}yNCQ!9q;n$CFVNG(8!!?$GA=(CpbiM8pUg)^!3wVqY&G4|m| zy~g{Q-gPQI*+?&)>rigYJBgK1F-OVLpUE;l_N2W&^Fl9l3$XOuyL1k#cg251ZI2@( z?EZ7W1=KD;(9&=BKV~`P(z0Da6m}L43Q_wTjx=H2M2NAZ*)(^0EAASk=82cX3}SXd zQmZkzCkw3~gkFU|Q>(;zXug~LS$zk|5?Wbn(XN@pd!mzaY^e9<%J)g(P$?B83|089 z-ZvC%UTB(iz-KjKz(cvFtl1i$;Q*`APWAAYnAPYF-Xn6ApyjFT)Gi+1XU6#5#6CCW zjz!0SO!v=0DXe{gmrz_6{2IigK=B(t;=1lf#5j9xB;Nx1@|kUZa1<&}!fuDXvLC)^ z>m)9xkQSlrY3Auu4Qt7E$7OihSSaD1Dxo5*5NIkrRBZJ;hp7seKj%bT#yIw(gTX_Y z!LU;)*|HU&*vAC$!{D4X$bii#LX|n{4DwhRd;O1UWhH=%kHH{Vx0Q8Fzzpj2%0MhG z)?XQGijDLJD5xaf9JKV5=|5|*!}7wa6<&=*qg+zq5=)RiEe~n64+4K*bV4Ou^(qu~ z6DDSbR0R4=p2d)Uk+fGKR_7?&S%MiDovT(}m}y{HgDC7mln(LV(2GjtZX>@)di0Et zq-NoR6|NWQTNT0Xi+w2k<1!yz4kAJHmYS^^i;^3{-g?Lil?~yK0*T0izC9OQ% zwO7LkVTVc`Ua0gg!OjgViDa(&?}}1Q2a1>ccagqvitupt4e(GEd7yW;|JdwpSc!cv zy=C|~{pI7y9qmE|1yBF|q1K@x1U45GWPjlW(Nd9DG9uT2c`d zu`?t`dV2ma14$RB6nh-mcRzBH?)e(co9f(YyFsPA1Lv+7@u8&f)Dkv}(Gh{|0f)=w zndmDaHm7$gRSBGO7S!>y_G1>zE(xJ4k9(q*>a{_K>?_~WKeM`H<@Zph^DfQ7S4kdN zH*JC4+Qe7W?kbXDOY@#^ccz?4*hF=c>?$B@T7KA)VP9el;ihgeQ| za0Imcr-SXUZ|ahtlGRfI5jY*NM&^bF5Pzyq+uTCD!V186S*2N-1zjCrla*ghOiA39-@l`!BC4W; zY90jo{y%$Ax~BT~jMnNhLcRq|aJMv0jRrn4%XW4)KkeV7q@a+JR44>KMQJq!2!JIM zpz(je~DnR|P_F==#A0y9wiv=OX zK<_y)!^?{x$M(i*awl0r!siZrKsAZEW^AJnzE zwSFgsv?Qbz#4mlzec+qxKm&d+S7~%m;z>5w1Jv>Qeo)x>IAQdGz%D;>tN)$+OKAPa zh6aER9?br^chR6Js2-&8*MdC#Nrhx;fnp+KD#8IlVFFXpryi*7%VqD<^l9?tXZ#+w zsF4-;S6E$MSqW}W-{KG~ol{Z75u8_5QH6!h|B?p%_)k;*N5>hTe{g2xM9ot2PqpKl ztjn)W2pd>pY<_oaZuzJWY;Ab~=K4ph?{7oWX}o{SUuVG23;4Hc@f9ASxQ#XT@2}^} z-bpWja@|lcw*7s1{V0DUoPG2!e+G{=E`i^r=gAZER5qVbA}~ z!T!7%DuH2n)&0Fa{%Mv1eW&pK{Jk0grM5l*YnE@eXKMZJ)byP=)|SS@ke!;Fzy&*h z(j~0c360}6GU1!`&D4p3{l~w(>2rxMU~6*%4jcfu?Ni|wNBE0kEiUL22U2H2VJ=xF zM*n+b{%uj6T);LqI5G#paL4tph>EH}gTyi(W^eBR%4wgLsLrjEr|3y0{R zm|3|~3sdl&fq-N4SGi6*{~y>B3!h;Soz~ z`)KfcXMTg$Iq)@^#H;+E@G;T_T49bm%q~8|(!cZ$``jM=x*PszT7f!$jd=LZ{Eq*a z_0Iy0jX*aH`}t6Xgirqjw&4R$@x8{a|Hx=+^$@|r_9A{UJyoOl@Pk3`+rY#v0{)^W zf2;z6LMYZh-E@2-vUj9!{)i5O<3ptzdn$(TatTOUzKfvYD^pqfh#Yvwf=wX0xRU;2!*- zfzZDCivO@dXu++>#<>H2&55~+IcNK-o}fAa2mErJ`^duI(vX2Y?6WrhoWwiceXV}I zuHAo2KIu5PidX%Tb8!^a@9!-68$p0@tbaLTxBFHBcK*)6*oGn2N1xnG;Y0Pm_`+gx za1j68*7c6gEpPsP8<`TMIK2S;7yvvRyn03P8~(Zgfn)_~|5Ec28@>JaboFC+OOOti zA7H`4FP}hynrA;*Ov6cR^Cxzof8LtqznyVEE?xRxKkx5rCtq~c2bcdEfiBn8`FjVy z8-yp28$Wnp*74PVT*I*+-|pl@|G@d5zEq#WTH4vim%=i#g24Kx2gZJ_%pSfmy>0va z)-(Tn%)YNQ|9Q;*VEuL00Q&RG<#S99vc-4sm)m#>xmWZpk3}%LWBR5JL3$hLdDtP5g*(HD5c^+I~l0!fgmqTe5o`dI&o~$nNBF@HK9`hO~pRJH9m1 zIkZZnW6ibQW{;3JTcl}=*HdZU=PYWn^qJOBdr^r-8p`l&@|ycaY0ISTUZ;Eawnkqu z{oI<d9=kWv+`2;pB?JX4PT@ri2j`UILg_hdCJ)xNEuXlKaQ%>zP1pZj&HGg7zSzlPq|%UVi2t30q^n3S3# zc(K9$xwh{#!`&9`A8~gW{^o?%fw~;IY*Ca@_AXcI+{xlKIM|nDfm-prBE-@UYab#> z;4cqexG}fpLEf{5&?)NQFc>U`OX&~GX1|Iv>PAwOcpw7;n})6O6_G>q#i?tZ$E&YV zSv!GNKfKP#hcF!(H#X; zeyUr-ylCBPMr2Fr+PK6UR}B*F;5#YDsyp*E#7Y1Fo0tyt$Y=Mh`S~sh3f$9 zuyU$Y#4bI4E*|opSwQo?sG}ad;}Z}#+0k$7*|{raBgVasS%N!PHoOdKL5a1jsS6!2 zM~mzQ`*pfVg9%@5^A}_~5)!nhbYCG+FPEzUW^e(dNxThQmNF(#o8`kw92o+Nd zF@jIAUOqYmvZ}eM`jkqPY{aPrf_pu99QVC-rL@&sv=g!?O|1jrF?7la@6&5^u_Eq3 z;ay8ZsDRo+pfn=Wvk|u`_Fn5L?_~qmnW{Aa6=YCWJn*8kt)HXzR^kOJ;=-nO3q=s! zvxR*UICB`~7-$NGn)Dkn@zW{8uxAiN(oR* zYy#C4m4*-OZJCLDf;V|7ZF@~ldCZ9MIoi3wXD~Mhl;KKlqPYDE+}Fe^;x8O7Wx1Rt zP&xmYYEPhSnWZq>cDY%gb422f@@DV~M@&KcG&#gbQ}0)nM-zM8-3r{frb~cAvIdx- zq1t`ipTHkjf34aEHCFet_$ZCXU8>OsjKf&dpl$=*oYcMuaXU?)p=m5MTGpM|7tL@Q zoY0>yV>_(1e6wVZ+NBb{(y;?SR(#QW(|a?$2L;ZG3@Z>moPx}dCAxSL7g>w#=Vyq} zqDzQ=j8+@SHCTSjX$`ye>vbv3ctcO4?#}{b9j8=}*T4sS>*bjm&*-I0g`uqJS z=H{;5NukDnfJJht^+26zMl2LGr;qL3^l+x43ph|=SF9R{ATKuJ8lA#qmq+$xGt6&k zx8TLxxP{SB`M8cOsXM6LRZ7@pI(6Bz}8-3j(N}dr~@envPl#}3c3O2Y(G9MT; zs*dEi1z7Mshn=f%mxwN*z{JR1e-y?A(XH{^Hql;elNAaB<(L+i!S15NDYhB0zADAX zBL%A|Cx<(a(K@FUO9iZGDA<@G2@Qe@?=n4c6jry1O|jIWMQ&>I`TW8&om@(V zU_MPIF0x{9Ca2JN4+8oF1vE7a*n82z46YlX4-a_(|v8-RR4A z&Vg8d0mW2?a{^x2YZl&(z*Fgs7YfO=O6}NZNFr=`X+-$k3=vR|Mu~@FLtPni5Bs*B z>cj})4*qi?tH3E#U9EF%Ui`i>KzTDR;mmC!E{cyq?4MY|Pp`lUkA~7c0WOlol{Opd z(o&Cd?OA|>*MYSR9c7#jmr>s5qvQyJ&+esLQqb#6=B z;|-KvV6Js+vlrq01(x^Wk!T84@jk0Zqh6Hq>xX6|h*_atski0qI4 zx%9gEEBuVY#yI+oO2c|)n9N8xeveHvT>@?L=cKoQ@`YpN4{6F~^P2q(tq&IMS;%%5 z7)x=)-4*kk-kGf*DHZq#k39w5!KP2_^?cr3{9>T%1>>a}0#o6vz7z3Yy7vL`ZBwAFQBpD9S~T;k zwD`OkfhjcMdIda=vUwCT@F7q2CyW+jgSnYCCan@KJ6bUB z8=6l%OyqrRIo%sW$E4u*q^|&BzI(@BO7jS8#oa$saS{zd@SF_y>;s4k zr=l>LcatMEADd+eMQ)j2poj@=1$?J*>}xcZ+f>F2?`NOTnNmRaD_9`ZiN+_Q#^A9n zHN82Nozd@Yk89|2J~kk@M$fd2$tAiSG5O?ShlP%0-mp~~>%o{T$&8J{4OG9@UI>kL z2Jp-rG4h8c5fWv0`Mo0HsMZ2u{}m7ZF^CJXnx6%!7$;vFu^UP3Tr^PeocK)^%G0Sr z*qy%I*~n$5-(|rT@!{DL2^9uyhg{?e;gUndlzLl}`5_P87AIA`COKcUKD!*ToQpwf zZCfJs^p8a$3c@bSsXfwzOR6Lm@T?AR&#`>He@h556~9^z*3*pnUayi=kKo@J{eD+G zu6Zyt7dh)68BseGH(Ba61&`4{rH#JGJUud-w2q0Mlzv`!1X7e6s87-4eOfSvwF+lv z=?_Qb6&kJ>lpO8#W+llavuU~mK64yd&5cS8 z-NRB%NKvU)ZQtwltY&7}pDkEA?0=wXo|r#axE5Ro1cgahyKC*PA0BzwF8ySgfz1Dv zHfOxCXc4L$qoR2#X$E;M(A}GlR)Sx8PY92I#mK>)peEnAwelEXtS`!3j4h;i&^q|c zalWr5?AnCVT9v}fk}AJ}EfjiG4Z&gw`YchB^IAh#We~54?iUmKQ)W+P#2bDOTS8Yk z;4?f)wFK;&218Fb zY#Ki#@zFckcJa%eP5IOH;#F;LV;SNQzYqzYSG?RQpby6e-M&5_2zpS0g_xhLZ-RlH zXNaB@`&!ToU|2adHdv@9dVJ;3XTGUHb$2W07AYKl>Pc#_)JY@6{@lr{k)fBKud}a$ zL5U$aefqr`gwOVV((0$y$2n3eCTutT&Y1g`8=Y};KX>1K0d*$oHcZ@ZKH!5XoSbgN zBCx8w#$*b`T7{zd09;9Qhxgw8B5G|tjTt^V5oC`|;%Gk5LxioI?x5w+RL`kv9;*h2 zG-AJwc4aLqcmYO-H|xEMGPLVYwzpcrt<>pBfKhmE=tos@6Lk|b&`Gvl@QcB zg|4JP(m-q@?3pL`^r8=9?CcNvGWVpOY38c88aDB!{h|1HKQ6Lq-i_9)W;YzWL`4^ zhdrnA4S94@RDIY}lWtEO`d<@~Js3F&n+g>>Ux-5)v)@yfCNn-PO8$IV74QZWyD(e0i#yt(&uw5lDZ5m*Ckw!MZ@i+ z6rI*N(zCeX<_Yw6H!1?#%L{5lid&#{J*j*pGfydZkrZ%rPJ|GZoUU{ly?1dX8;>2;$;UMhjXbj|d0lA?ftx_RQKeyN8==D$LRgGpc8V zg-$r(bb-8P%$Nl3RXXuYi>FPn%69-@)mg-~}Yb>NDwl#}Aufa-A#WKL(xQJTJgERp#2ZjQl zW%tcT#e(8neWc&F!JbyTYX;AB2*hJ52ay7fM#~_aTYCr;(czmH@y850!9r4@UJ5jv zZW|9D`GIqNh2&@lPuDaKnZEJ%AZpgbhis(HQCJjqOiax}sWNBP^f`s1hfGQWO5_2c zEV&w^AaBZTBV>n^B>hG&RD2JV6Vsur30Tr*_&h6_0xE77+(u?#W#zu zO&+;->F?X1g`-i*Z#y{xddryV`i8;ET={s7re<{57iek4NH9}ons!SGBGG2bvqKFh zGtFpM`<6J)CmXM!9ilu7;=4+P0BzU}z)XAHhT(U6qH{*vd@x1RPH0noi^O=yQX?`& zq*`{h1PhopU-$_Nm4n!mL5eJCj!BC=#vIyDkH4$%n$YLQP6~?OY+Y( zbeF=)Tz4G@u#tl8=o{A_h+HM~V7jUQS&`U=|3iyFv;<*h15wEGCT&MKq?r1&QH!{7 zgr~$fS@lTjC2n;Wk7UbS>Eg$RZ|#K~L0$Mbe$D>~Ase~)&=QDehM;*aGF|lwpWV{; zq=0VIv2#?C8TWeLDBeVp-_7~{h~(QPP{bxX??GIa=^Jc4@Ps6gyt1%DL(Rk_5a$~( zPQUd+^z_-HWZsxl2Flp(k~A8ZnAPI=cnFy&`}ooAQKS!9b}U-#ihC{6S$ec@*Aef& zPTL8>tqbEG$?DSUyWhs@Wp-CR1Yiu@IW2{phpDSmKPtNgu@#eeN%h*c96em4AYk zHP2j^tI-F`9JtwVup~eTONFf{d-$XE)G}i>c0$8h3HO3{v?FoQQ73@Je?I_spwP`8 zx@DX@D5E^VDu@*OuuDCu-VH1|YfK9S{Kx4{=MR!)i_+0?)R&M&uL#sEhF($6Ec1c; ziQF+Pl{{ulK@^Kk&V$+=j&0Uj&DN5%aU1r8%=21eT+kTu9yfqL;9eGyaroiA?!@7r zt)A&j&Z)CMYw#$nZ|KXvrZkS>&Ok)7+Tbz3huq31%dcf_kjtu?HR?=BGs1c^vW_aZ zJBV!E^a?`kZf}jFFDtAhD(l$W1YrT4wmlu(>@;8fqDsscuA_{E#VBSm6;1aSx=oQ< znK(_l3?OGqoLQ;^1)p{@*{)MiYrMv2S#*O$3*T(%%Le;Z7uEe@_;?*<6cC>m?Z{}C zX7OX&UNE|#u^#sBVx6(ND?u@$(Z2BqO80cmt!IZ)FepY=>UwP+#%s)8!4I-vIi5Sb z@SNZ?Dv~7qwe1LVmg5eTSN+L8Bb$g(dC|Pok#QGR_&3CV{g? zx4_ct^RIQGOy;QTLaYuY(h8olCdx5hLL)CHF;J&nD5POB(#x&{sy936n9)1uxJx&YxUAbZxG-i^!^!5flDtERd4>LDSZ)XFdf2a0jLlP~@5Y;gqHhcFL zU`VoG4j-$UPv)zxXq%oyWn0x)m-VV?cWLdlc+w1Gh-zb5 zpXp|`69)H3ZFrF(u@=VQZj4Oy&bmHJTf^P|n=;wBT-OGF3`YkwIblyj`tTWn?>b)wo_QO{F4agZ)bndAp}O_6zQgpS)y0&9jA?WO!9r8X+i@ZaE!4_j(s4dk z#$(Kzx`cOt$Hf`4`YQ7s@BHmhQIly2n)u~OhXH%hsj9QLi`eBBaUZ)=iQN64b+5I| z;DP;VRNVZ+6kbf`ZcL;}Z_%BpSl`dvhlum~KIdEKaBKf#m89_j50hE3+kZ)IUZj)Z zolQ#a>>SPzlw@I{?5AnPA)9alJec0Zjnzd=-P7M+{F>)x3tyE0^6b=u+k)!H#a3SYJudHwn*jE0RZR5FMkqjhU~h$H9$aazTxn>)>8>GD zI)|yTfWn2Wq+Zd&%Ck)I);w?GJ-{V}--(NZ!%$H5WPu3nQO0PtHguZ*YU2V1w>$6D z7v{sA|7dC)Vu7wMOy)6VWK>l180kGoWX&IT)WHKGdWW^Gt`Odv*Sj^6(KLxzxXzB@ zlYKzldeXlZY)tb`)FHcdHQjI`?TelDz!yTH@HUoEyeo*g?6r zddks!D`I)Jw?UO6^cJPpPbuN;BCE|4P{GFhO0S{Yduw{hA9%z#Q;%t+yo%uCTT$3+ z_!(M0>;@|bYOG!!+L;gsL3$q;Dsx5Pop%l|Z{$7!P1|X`ls}Mi?HV*I@h~`o52E18 zXRP3GY2kV<4}B~ls&a9r^t;K>hu*BNeO7y{CzyZ{XQF%v3Kk zwPjPbw6|Z+dd*|6ef^h!U5uQGHdj?TGA+=QU)V|4?7`7Q_%*sG-c?)1Qs<+r#rEoD zK4rX^yNYaNCOBhiWgsoqu3^DD>qg)E zFwmynEMAWYr&#ozlQn8*M~vPlq;4yS631cRtC4cdyB5W9A^K2N6*(l1lvw^Hf&esd z3#YH;g>RdaLCV@JWYi47O5r`~6+Jn5_pUngUh8Dq#wnTrJhKaZg~f(OCl9;w$Xnfv zJ6idw|C+rb$M3qxRB%r?%FsG4sZR6j+^EZE3;*7K{yc zjPWwdS%Zw_h}d``vzX)}%(%+DN7=r4WUO%R9bYb?*sXphnOVUtr?bUmMtU3jZUuXi z(geNe)fbhARCUH4SaLp6vlhSLAb*WW3u9Lv9~|g2StE`hDGxtxdZ|pA@=!y=%W*yc znuC73{^J$2L6l_LCbK~m|9X|7$eUItTVnd5!jI6ne_lN9)wHPQpsCR+Rz6P|Xp@CfstD=7Z8B7gxcR-Lr=q zL|{qYN+0nl`(mCP)Z_^klMiUqTw%>+L?t{(PY8VJll>P00Ok5n#Sd{|tI2Tdf^)-J z5DfED#yce9Q=E9!<2E2p>7EVqX@q_oE0(-qlboq@%W|qsy}*i#@f-UlsFZTNiY-r?t8JjiM2J%tH4WDFfUYwDEIcfZBnHs6&$RpY~AWRiXoD7BVt3BD@U=Xa-_d zP!*qh8uR{v9&3Re%eJfKU1-vohZbNqEm2kMfEY6WP(VZg!vkCf+b(V}Nn*_h&t+UX zzhKhs2bE-H>8fae$t!Q%VH24B4p*>A=7S0L%tYn8<SPaO&;f&8^c{-dM5oyG89YIhoR;whLu+wYl|8{4o|(?X)kMe^bvTu>PJN=17lKj+;(`vHpe+>3p`3 z@aXH7@lKJmU2DG5Y0c8YAtn3=JFIC6GND1y66Pa`=@3p#WSW6SBB@C7_w)ErG8gpn zmCo>2WNnRi3Zd&4FkkE!QUUC%_1aq$o_?0U3%Y~ac;kx znBx*9|8VxcFvmY-0=vqy4Qm(L3$Pse+kQN=0BymK4H%{fm_hY~rCRa(tkQKM)AFk! zUx?YoRx60jbFRjxSyGwK=*c~zOa;`lSk$sSXW+^`cqf`4^pnV?Ue7$`3La%_ZLJnZ zgz$}WNHF->LZu7dp3i-p-y@Y9Z|+jn$*y`;Qb$C+C@EX9PqC9zvRv zW-~{#9Vu6_!@y1Oi@?Z5N-Kosqh-pa8LF7O}vGCL zF3a`>f}3b7+zc@pXK*vqz$vmUHP-WwrXe*eZ{|=M4Uy;XP3AFkWxy2qfp(8Io-&!3 zbV8YwxZo;;HF@=v^`LGR(|Z)F9Lh0BVdyCDP#jevkon9tY%eORvW3DSZ z&mWda8{Lsi4_EG8O*>NOW<5pXVhJd84Jp#GX_J4yB}*g0m)=bNOIu~$YcS`m|Jl=&XSC>!cj?vwzfdLUPH8MHjAA?JoVgy{vMFi*lw%4;z^Z=C0=Q;;MSkgK}2?A50* z$vRj|0N2u_<(#cN%?N}3F)oea^2JyltF#G!wX$w;hNO*`7=xXQ%3?lW`sm|YaxhM% zCCt0I%5@PG-PrAQx8u=W%kt|C4zg~aGu-X_tUcscX4I|c>1K7J#@Q` z(LVXpX6|uSHYJftL8+KR(<08tE|6$Paj1^3VtGNxFNGoUIY?>lm=YwVJ`ATbow3Y7 z)D@fWqX=@fCb_rs;*{!H63|yPp(29O25T%SmIM$*cs993Z`n zvH1N9(^g~aJ+7cGXwxe5*>P=Tig^PZaj%;%PxoHsi#4AdPl~p;(dmNGM2B&tH2{Se zz<$n(MU`XHly1fLvggZ722Gr8S+-GHf%~kXYgZZB&h|#-M(8EK>rW;9Ubd?j55}KZ zc=R8WazqoNeh`|s6lpaCO_Q*PBN&t%xlvG*~mQD&55IXfRo?3OpUu z(ujB-W7b+VNf660L@hYc5HC49FVGE`0o!;RQPPs2mhTy(sKcx3=ddj^Q>vVDs~+CS zKsZz3mH-M>bDT~%8>-2UmgPCTMQ>iVocV{I?=g(nBgawHsSAu(|An<`!ybXr>#-rW z#jdnVzXUE`2*YA5uobuM{i@gxB+`{tZl>HsIMh9HYMgTD;uEDo?8K^SSbRn^X0aYN zYxe7_rx;6?g*aB@*#YPxTA^v&AI)`HL}pO!6hAn-gc=3pQ4~UG%Ai6^OD8h0d)jrF z3WYhA5_Yq6Lcr2=MQB)Rl`<5m2Ihde^i|=e3?{C(r-J+QZoxrah_E{{b|^;l)H1td ziU7RoYML+ZCajln+?^bfb9@B$0B_+j>EOTJo!b(NY4D#VE0j)F{AZ#!;vqh*FUDa>@B224!DC zd_vYF*}2E$`+R7d+q5Hp<6^#m{HXdI#reyVcj-Vw_jN`^gzQ(rx=diOU{+b9Ogzs; z-1S}3Pvw=2mLk}+P(>`VZbzf7P1H4`d->Soj=;S#xI*W>Y+i7xth_w0V+dT5Wn9Un z#S#$gB-4VZd;W-YI*1@~9$?hP`Itlv{T#3$)C#S6HqL`PiL03Hb&1)!`Rb;5XL*@Y zPmUpfvnp;2Vj-L7$H)DeJtw_aYr1vWz5ukeE&TeArDal?K;cv|PTdA3kasuhGB+gE zXGr5=`S;F9`7VoCTyrXV=zz!hpHTTKc})P59o#I89H9cwTTNOzliN1Yu>?f)ifUE5z?p%v1Bu$(H*?{W+!T$EAen9aPJcKkuLYBm$WjvmaAOfo3(4V zju(^OLxcn1&0^p+%g0WB!YkG~B?+*)ib%Wib+A;xznT>$sSsl-g|2iwOJP{?f@I@H ztC!?B_v~R5Hd8l!#zBYK)jZ_+&C$RC(DPEpHi6dVN8P9ZQx)e#s6C@F?CIfCdsf>- z4qwI%-(!y`o*K7iYfVPN#Z|)+Y@D;zZjpq8T}z_3(Acq&+p`H7RZpLaVXMe;5)S0@ zJMf~M(CJc{^4#X(Xw1&PBe&-1uUvhj0_vI>MsFqALmX2=E9OsL3Ufb4`d-Jic?uLy zuIKxe?{5v$_6C!c0tWjcdF4O`ALjnk&C2nw!V@kfM}z8R;_G<@2YP80&&q2rPA0ce zf41v(B#|AXc&Wv}-?`btr-YOk%gm}9iZJM#E1qTv)QKW24L$G89;yDWsgNWuNHKU> z2q2hk4h=>n1|sZ-H5(f5jN}<#jsp_g;}Ju*l#b7!?cRM_lEBF49uf?aBSx!`cDbLV z=?{j9-OHAwOjqk^m>c){bKXKzXH2~)xvDOU4U_!Zt4brucmtHRJDva$!BEzXH3wo=f>%Yf+Bk4!%I=Lef@maK; z2=kUD0XHyroiYQvUaFd}io`YAhP65<_>EPctguehRay>VLUdV`HNmjBn#21}uI3&J z0ymL~wd&1sFPs4NCZX1~&EHHCqG<+IjSz+4I0<})ANk*_iODc;0a3Bkc0xgK0!piT z#sl0U=RB9Z;hsyWVj|eH@1QS%(G!3m63k_3A5aXVFm$>G?Yhgca@6OgnV#$-IWHvE zT{E`BR#xXE_tm9#(90tlE)>S3C&?YD1K6nE0kT-s*Oa^l>~qkWwg|7!nJmQ_GV@_Y z)dKiHM2rVivP%&7e4i-cJc%dLc+K5Q5PMZl&4dWT>(Uy?Dak63{uAFkelqtF%v2~9}EeL`Ojoq67c7`R(-|yje)wIZj z72>*oAwmTrYa=cAfN&V^^PGCDRp(!CmaGpu!cgSzkd-fj#$V+a)zUd1#l}TiRu(D* z<=;Usi~L5pVThWd&c#(2D4Fy1;|M~TM%M6aR35#>Vz1sej(EsNM27cvcU(?fH7;ME z-Bh=3EFAdOr_USQw>LYvaAk?>eu#z_bMDo(LMqK}Q|h82rp^Jn@@%RHS$;6CqUvpE zPONK!T0MxuXfaE_XOfCsR)nRN%CLmCDQh6^as32kblO|iF`YGl7PZ&fR9_8Eccx5` zU~RsR4qy*VhCn0c&|BxsuD0>!e#iW{Ud7e1kkZ0ic6{W^Y1^Zq_#Ut{kcQ6q#n`8g z0q+79CU46>d@J#E}j>mK!o0@Z@}21dHzLKc#Pca6VVRmyv0$R)3vBKr`uW~xMTb5IkC+KTapfj*v1d< z(c28#yg?2n$6Luv$5*{BJ^%&s)DC&A<=i_cIVWc9~BZP*j77|OFJ(*7%i zEUvVU1$hBps?0%;T{?`g;J6*)V4D%FN9-wRDr`tZf^A+#rML-7H&Y50s{M?Y;+_v| z+%OVPtD5}E=f1naQya9f_ompR2zzcTgC+!P^et(a;MTY|A2qd6umey6J zmGX&lK~6aD=v~hR4jSz2ODO+&E?sqXONCT-jsi=jE7+b@**PKa_F-Mt(JY0FjSy#W z-d)OX49V>a#i^(<5i@k23sF5k6ZcC$c^(|((6-I}8T9HT_^MU*%o`0*yh~N^GJtE4 zq$t#1B?0NwBvp*7_o!p=H1JR)%1L{|+@M_>J_iyZA`Q1;BGS=aFZ>rZ3^;LzG;b-& za5=0e2`1O^RXC{v3*&QR8~PA)8`ahuNQl^ce zD(gc$bXpr1 zEg(l@=*#)GK@npXR*k*6CoG4*zJ#5LmkILDL#Z5wiSS`al>2o#H^ zv*yH&x1S9Qe>dae6gQ)GMpTa8pVjyyU93n&o&~LefXBgf*I{FHT94AOh~Vl+SV)Y+ zYB7}ozXOe_n3}Kdrz#ZOW$Ip8({HyfjBj+mYq4Kmz_GzePCmoO$GMa>+G#P$^^vU1 zSy^x%7}NWKa#sqmWp8z+6CCiHlGyblZLa$oZ5a)95V@3}*VilCa52rYa<9d{gZC{F z&KGmvz2&{ixTCZq=t&pR)M{C_+gyH%i=pkZaqp~AWj;??j7(<@+ol% zT(UfC-c8WDIp zCO~PhM~g0AJ+OLTtItwyNhI_>Tw_|&n?4I2?m%G)o8CrW8h`a&eOk{BG^~@@>WW(% z>Ucj8>522rLqN#GEyW2?tl%idfYesw!0yWe7YlBBBd#E(Bcq=5jlgJppF(olBHeNq zQx*~5uE!4lOU8TjX7&i;0-3n0m7T4tjj7C8tEJ^`n%xDp)s82P>ekcKq6yf}H zP-zpYMY2(I z=DF&>Tqs!$DfF*?LWS_nw}0FDfS=l5$IPm3Qn6s$m9_=EVJbaCgHravf#I)ZLv60a6dYCv z@$|Haay$Es)ya)RJ3>Y%Ge%ALyzj8AWy#+eG~UBexSCd(a9)Wq>+=wio+Tay)Q&j2 zq)21BBi$i|L_EbDw*)--V3cEB&eus)YdmVE$OTV}b*|z~+R(CQls_RUR6hv$pp{*O zcNwj9;)mZl+LtVX3JM7+!d>GLoB?^>pl4{gHHWvEJeP&%85>O6+l&hhL^LPi+lkO# z?MJ%u`)9$B5S(7jNW;l$u)R(%Ww?O3XRu1esPbd2^HdWn*$$4pdaOI zeBe%V1J3uML%W-fuzRUCebX25u==Q#L>PlqQ*E59kd31|7TS%OH-k*`tQGkpfdr_S zc7zwNL8~&->vvi%$HZoanI-cBpCyCAdb(zh%I6!J&B^k|EU8)5e^_f_D`)y1tK9bd z=B_;?OSUxtwmNz^MW+91JbW)}jmDdi{V#1aMhoHeLB8nQ3E-piThk*KhD&{u5p zhV$AR@LZr>kWlsj`vdAGRO*w+ySUQw46H)l^fV};fyb86ce{rJ62g3%+$!RUMFv!+ zMvF*_CgYE6BDeii^b`v}!c)~NsVuTBY5ZR~HCUTV?EmKZ4?ht41;Uw7bki{hvp+q} zR5NyC@GRQW8l7Lp1MabeN|KOPl?DR+Mf!=d2WSxBMa+Vfn!Vzse9EIiLJc7x{6VjFfhDR(aTQ+uF<890M}PyMrCO0 zO|CjT{Q7&s-YRNHV-(GyU;ArFZ>UW*=j8^4xh4ri)-a@)4GwicgdgJsrPjln_Pd8_ zB|;w&5>(q$;5ruY`J0JTjZy_xBZExuq{-SGmWl@$SJ>WR|KzvRnQ>}dCt%`A!9hZF zf5o*;%QgvRtVV9|;UL=dvaq91PWD@E`8b)Ew55~wo-W;71yUt6_w4TzOjS@wTEQaf>H=)F#eDpCfK3RTt&Mo zph9jH>u^Wn&|T^fb<#!2I%p_|l^%<*AK6^LRDv6bMN%6#ms>V^2kfrHbK0$LaVQwE z89FudwBa3>6OBl9%`|?Z3@IzTSA%7O-c?0? z-F-x)JDf-Fwty2n$(A6Ynd*`zNs8zm2pE&}GRiYZv zfG8n#;l^-O`!|V%H_|2W+gL^}7w_p*(H;7h-@edYWZB%Ap(ryVVvwK1oenj|wHD2F zW_MwoYaR}M@JSq)Ws3#Tw290fH&sR5L9y8QG9F}w49W;g)!}QD9S92 zeWx4pTKSH7Mt29*p+kl>gztlEZ5P#&+1guO{K8sJNgGVjW1fM zQn34UM?+X_>1D6YYSIx2RK2GGUowkeZc?&%#U4*$zgtI>EosQ>J8AL;1lM3)kHzf$-?9RyTUn8@z6^1@%{HQzo391h9lA zFu@mG(XS?yA$^&@aN(a$`PTXh=%V~c!_$HpiDGkO()e<+>-VJZjVI9i`Q$xHRs$zM3ZG{^^Xph~Y9-|f zhwe6YEZ$ApyM#Cf+fVB~KJnI(HE3(fGmYm%?Y(OZ{#I~bf$u@&>rv!M5$MJ9lM2j6 zRtj2}lCApCkMV4KwjKiHL`mqk#@h-My#N{6+RP63X$H>DT0%p9m*+b6L<{AknUw@r zmjIP^L0E&&?S#}HDvB84RGR$gB|^V_Lc**U^~VgWp2bvHzp!37cvm}w%h}CrqaMOW z^CHupoC@*elD&b6Xu3$0NNhDvHRX~I)fMrj8pd|I%?L%40Q%tzIeGC(Od;m=i-x6| z3;g&OOZigc%Oc%Lq{3N=pp>vKW9Zt zE(RRw$8u}GU`#qwsd9auO+Hu!@A_-thH?K3EZBNs4OS@P>6O@`(l5Gj>U&4#w4MGv ziI$2A_o3LB%bBO2u+Q|}g|cZKuxzFY>po?iOX-TaC!LG1GftN%5?cy%5-QbKelQIA zs_aBWRW=eCtm*xQs1Z*Xd6bWIYE`HaPIp1a1rEiCrpp3J5+t%}+YqgQI|u)+wcjCx zKIvd@qtzuZmIXuX>5Il0`>_1%G13r6@|}vJUGQ7~{f$<1V45V;c1^dG>IcA2hWwUo z0iBK`g1yvx(fj(*8X9(asjgVNx>U|<80UcD_?PD=udqMx4gEiConvz) z4AZS+XW~pav2EM7ZQHhO?%1|Hv5kps?bzq8Q}uj%|G@gVR$pD!y}lW`YQcI2zU$`Nez0hK|W=5al#x_|Al6_4V!N}O; zDfTK}@-p(G2`LY#JYHBLE}egW`daM835tMqnn&)2%fK@IJ+D*=B8(68VQh9|ERX@s zMShhRCH16%)Ew^R{i_hO(c*)?ccT&cDGp(#uy-Z=!A$u;iZ&?9CytfE(a3H|3iJ!b z;%A{~QetsYM6NieHh(QPIF6xfA|t4i5r`P*tEqjI!g*CQ0x(;m7jnf-@S^pLG}*22 zCC+1nBm@d>onsf*a&>WwXrXSDEDsSkJ>uw~)vM;+CnM#B``!n-X(dhQGhDAKnSYi+&#BjLmVy7gLxE>|`ArHSNWP&x!Yup&+44H886~kFG@5TY zyScY&533dciQebIZU|>QZb>yTng>j+9nykORPKuz<^&4vmMu!XmDVKjaMz7!CGPQf zb_$g#_5{9m_uNd~8`h83g9Nz@bHkV2JfvJhjqVa_Z`2xoSexU}*iLeELVM$2NBlhj zm*2V2uYdL<-snWk?aL)UEWP3&Cu-(bm4BMuY&^7}7=#U9b^QAkpJ4tI59IRPfhTVh zA@&dvw}E_Gcu{BYN_zQjJpt=+n(O?duvNaH(V%fntCb_nJ%URLWD;P>Y)R(C3^A<6 z{>>!jVq`4;Yr8cp3o-==$2Pf;kctAXIWwXV>AVhV*&@D>j(&+`fC`nVr-av=ouW9g z0cHakf+`_c7smeUaI+0aipDaFkJOD^)7>%`wu{zNhBvh4d(nS(XIb?YV zp+C2&V-S44T$7_p%0!_y+%6LG1uN4{C|xmJ9zot=zum01>LB$g7lEDrQ#%o=f^Jt? z88b{(8bHF^AOQ;~?=6s3NAu!C#BaA;eB4f3<@fi#?Xe@a>sfLoG9Z=eQdyE@?Ji#_TF@-&wiBwHa_FB7@qoP#rW_!{7nJCj{364>=vP|;_#c;l@_x4Sd{-PoHi zf@cgnT;$jTBh3>Yt~ps+`kAT;XRssfY-ofDd?EcBks!pj=D9;kJP_{t)4Ec>{X8jk zNfcq?K>qXLuXST;jIbQtprV0*p-(Msa-$6#Mh7W~aOf;4T*OR|Q2|DwkuuB5y+BOo z&~_Syz~a*J$I%LjTbI^|S)#2@G4KGcFrjsA&iAb?vP9IYRwlD>GWh7OXcG1M?dQI= zt#EPaNS>E^eOgPTVKIApq?)X!OeAGxPW|GuOe5UN;qlVFvRZk;<-%O`6`5t0KUtkb z>^B)@ubOcQwi7-AcEg}2aBga6VQn6%EhVk#8u+6LV=D&2E*EtluVvgx;P`dQqFLA3 za}{-_dlQS^<#<2cNA-43XdZXrzeYTJFZh!*SJB86^n+ok!oL{i>f37`{lkQ-m*kJv zD4R%jE0ieb)~xN{_+6-RTiR#mu4Xy=q}3xrLH58Lbh>2$q&vV6gX3BblsfVy*H4Z_QWlQOQIlHLTyNi=mqYB`!bN z5d3lC&R3`7o{n@~v)Aw-UbUHBp3a{;FxxWqldaX%_sa79x~yS3u&Z`f=BRp%NHK+i z9xB^{zXc;G((1eJ&`E*0)%g<6Ax$KTkR*_&rmSf}{(R#ew=;&AR%7)B43JKfwuSzK ze~%;t6w$OGO6>+8QGVr7bji!C88hBjU)cLdk7VRw2l@!`jdWFnsiB3s!U)>>^6j&5 zJ~2=lM1FxlX{?jV-sf>H#+ol4nYZkR=utZ=;!4){E?NUOqSW$tHISMUCx2+komW6b zA{tB;5yAqX-VoEq@^s1!8gTxC&#A+yYWtKp;t+CR9HJef9OE=l{5h3OTWG;x(w%<3 zn!%XiMd0Obd{GfZzkIfVS``GPLyn(ep+a#A18z<1)iTZTw$7LHPTL602B-fZBu{!t ze>@vq?^C+tV@hX=r0MiuIioT9cyc6I{uG0N{xcn%XIPzV@gfP5;sC;%M$zm;d`rKo z+iqfeGFo96{kHiQ{^d28=7^H4kdK_C2m0F@fsc4&&^iU3-C*Zv+A4}S+WuQi(%%{ZEI?=Lw-bM6y%JdWJ$N0rArEhN5;=D?qJI?s2@P!7Fxhw?| z3s$>Aq+RdBu*|l366iFq&O?aLE>C5Iq-4yi)j6`P&Z@`%cqn2hJJC9Hrff6)U)9*K%jmqQP)UwAWAgzd|yp(LZYNrbRM5Y94MaiMSTE=)bLww z@;R8B1F!zc8plc$t!gZTGVMkccj3wmCgmmqg2A|qm>eHwv2;j`-%fNvIK zEqgs5EL(;@_qOQ67X#~YNciw!&x}F4ki_>Z&FXj^%Q$dTuGBJt=C{1qyCuWT#);i^ z#WyEERn3p3P|Z*G-WUjO=i25 zhlhmrqrf7z!V3^oY7__o*ASL3R(5r98%uj{V7R+t<~S$`sTzWX8e987GWIkU?A9M1 zrwn3m7LN@z9*R9p%hZN+I`LK>y8d1l*wLQjZ|FZJj&UCV(G-zqR&3>_##?a|iF=@K zrg2y*?*3P?2P5_N&al_kzZ@sCa@Fgj%R!TL_1onI0DFq8BZ|`?4jwHdOe|3EE0bar z!(D%_^3k{4c_ZEeUTb;h&!}E*hr@BAud!f5L{_NbsrV9sX1IhZGh?}`&WH}hcP|Ll zFIGC%cc|{pIR~-~agZZ5f-Ixb56*NLFHLXQ;M)S07HI_LhV1}#naKZ}&Gq-#hIX5= z?C$pcZ+&KGAhyYBK%dMVj`xf+3tUg05Fh?fO}ydG-vBmX?!)`dWUmU;tW2;17^gtB zjU0uer120}gO^f#6udmsNe54Ti;eQ5yDd5(V|IKqI^h{J!h>;JZ5uUR?mR5h1$1j4 z?(Cg$&dChFCuimFbOA`*8toJu9nl3`J<^HL_B?F5_C-g|K_$mZD z0K#5UU(C20a#w3n*`HTp|CeI9y*_hu@2Okyk@ zVb0sKL|T^<5Sj+*)t3>bZr|rI{yQ612ZO|M3CSxR#LaypJ-6u@+MnJv?p2Cspwi`Oi2Kapg-ovvi5bvmrUgoS+8TA9418#>X#bb5We>xot z6Yz8ej0kKWn_+NdB(ORZT&H{tLJd!!gE7>hq}4uYPgucm>3(Ys4k=q284axqoLfXs zVpspn=x7xOP78+4Np#I>MO|tg?{|XH(My0lJx19?ze}`0aP0El;M0*)#GyN+hofuy zb$_bbN987fw$oVo*SV#T#@FI`Z);Ir@Li3}MfPtv5(+ZB?lmXX2m4h!$!Q(Q{-RXl zz%eGqP5Wl^d3JWXvA<4fQfkCWw8%)2p>6xOL=uFPY6#=Xg!S|mMvjhrFMS(R)qKeP zzL@m|LPv|^I+mUh>O42_v+pgOM4`?#x?^<|$)MSO^fI`&vn(I$-?!EC$w-3o#z|C& zm4}@4o{3wz%KDa^LyxAbx@KioUI@;9&&XeR^o>UJ+=~uGbKg~X*2&@dwv6K?8Z;)P z^~_-xkn!ktP!gcSd!;!vZ4l2RTh-iS#7jZxo`vSA?eS>IJq_mL`;UBNbMj{&t@aon zCEQ(IO8bTgEo~|FXiR=>pT!J;Ac$t5Rb3vHs2~YIDx^MIw;u z@^FxgxvQ1`{pAQI13XB^B&xMtOy5qrySugq!#mKXKfM5NY^wW-fXpB&4dc2klkZDJ z?>h|XX$rAF{AOgpBrlj3JSv<#ByuZQ6FLlSx9RvlHj3W9R<|s&Y7!i^ep;y{78#F> z3E%;y&ewm!7tgUohp2gXVAOlV1s6LTL*=1?oi%*16w(#Oo$RSX*Im!f)-I5o>21dQ zRnmJjA8L@IHY)QbAZHl{^}?gSRAhI#UeyHt2 zzB$DPGx>rwTTRHPj?LrLP_}oQ@qd?r#zdhHRzq}qGR_unDE2*QJTRY^iCwI0n%4+@ z_vfN!MQhOEa0DlK+vwAF%!TFCnN7%Z5xiOLQfK=sM%1825TYA{iXZs%H+2UA{7DWu z%hX7H6|>Xe7ys7GP0cyI2J{rd5BqB^yIrA*5%|;;FmLY;etr#y>noBh$rXAuZgWJe z3abHa_{i6Qlx<^+7~~<#-@cZ$y*+A=SN1b@(=}zfsUo}OV~GntS`VZ+n|s$lES&^ zWi|7zV-OAX;L|XGrE|iiuI>O>K~E>Ptm({v?e=vnv!7=3R)L?i>L|e7?j;#eM_>@J zoa%(Ti8|ETk<8bS%=JsUz&ay3p&$#hC?GM*A9c4UPus>;T|iU z<8#QaO5+$un1o0;rEby?v_oA1l1iadNab7#sZgUdh~Q1l%y{W@8$~6Td3039?74$# zAX=8$FwiJK^IrY@V)P39<4StaUNu=|I=N7qhsssSN;|z^c~{B}(Hd>GG6(V%TULV} z#Fh+niPJ?^{sVsG9c6l!Kr$az&eLUwCs3Q|r86%(mV%kAP{J*zTS`~2dQ-zs6oj7k zHrPuFSlmpSw$1*S8X&zEyDG`7X%xxpkSmXVk03J3j7E2C#o?x{mbJiofqj@$uXhQ} zvO1oPI+VUz#lY|Mnqxn`RIV-E0wF42IK=YguVGYDIQd)2DmgSld1LSn6+by2B|k-r z9j^8ej@pHt1Do2tGKKcsyFFt463|UCnQ`6QPR+uVx&_o;r<7s{Ka%mfiy>R@M<6~p zlPsi6e*oKE+uE+TGSWJM#ZbMdln!cn-|8kt@X%)M6lJC|xcdkdKgr^FmF?kQ4rPq% zEE3BF|64$7W--#c1;r_Jw_Y5!ti=w92(q+N9A);i1mP!TmO%<7gy(Mw6TNuf{sx2$ zxPJ@rYvHw=v;7!Jz*zNv4gu=kc+ z_PXu;72t~3Qgv`)cAca52di`7_$<-#UbC_Gn|n3C_JVJb%3R2bfP`1`>#}Ogx6YjU6U^H&a8RYYZlegKvA$fw-4H_G{gLwIE+g3f2uPO^mmBxf_~ zeb`W9kDlc|ROE9Z5F~zQW+tT{iviJ%3Mo5PSjsSG{@d&B;gcIKxJwonv?aO2SaXdRnNs#V(pas1QwxEzf=TD?`1Qf)LT8Xh%ZTc2YL^Rx=i@4ztU;iD{A#OEB&P>@)T;qryoL21T))O7s z4PvH#IP9-6m@Fj7Lni=!@BjO@di%S$wk?C7nVUMoy}hpe#LLuyfSX1K_*xDpD^zT- zk@<`YlQk9vQnU0?cczb=fGl7(<_Rwpw7vkUP%G8JDqt*6`fM^95PteNY&vzbf4S3t%eyJxS=$pfBK)R_)zXCM0;uu7n<;sYb8^W+INiv)S4?mBU z>MeL_O=3ea*8I$zaCgGMo3G-HIN<*oQU*FedeMk5Oo&|kGLTUk!x&hlCwAWJNvG%- zBdz{|<8}K5{}ptN;Ygb*^z{SgIe{NCH*w*bWvJ*9{$Tv@k~ol-%#0mJAm?*7hv{<> z=o{Cl8rH|I7R%!nQLZv>U5rW4gvw06&~;U9lk!sU}(9Z-t^( za$23u{KEcrj+^JM=BsRDyy>F#6VNWI0BG65;F$LQF3{Olv%;y)FR&}SiAm^IeNpFb zeL|dE$6Ns|Ls0r4;Pk+wAj46Fj*rdU64@jkRdJ;B3d%fKY7paJBWwzwOarIztMBN+ z5Sc#66sRh7?%MDY^DxgdlSdCoTbDNWwnWx$WaH_1hk^hT zLaf*!Np*2c&;Sy*bYJ!(BYWD1g7^H1JmbZjm^cr&kS7(64a z+A%I)v7)%}QMA#yPE<(K_=gA)81YI{zdra|75kYg$?zcgy2gZ(J0&YBW1I>gJ=wS$+IspM3vBMKiRke6N%6qp#ze`~uXhp2qe(d$3BsQo&yi%4vhuyx}kAGuV& zQV1-!>DMpYt`ZN+TiTE^pZX9#4-P-8*6A6k7-m{u>%o+3%NK5$uh4ugZZ~oNwT4+F z3KA0P-;%#ldL1bHR&K)Xa}~C+XuAt{G4FT+^Kgd6_6A%J&WNlpz^~<*hmad?sC(cL zp@q43IcFtk&%a$V8z4&H{mzUnl_X+)&Xx0H6RlUP4J0A{w#KMht1p-T4G9AC7B(u6`l=zOSeA`q#8ua?lxJ270rUtaIa*!>h5lP$7k2ot7B7%@#uhZi5S6i%?U|s{@M&h77u0EsvN2C%zNBT@qnY zdhq%|?ga!c<-n5U6@J;O*49$Lquh;hXNlN`wN=dDUJ@N&^Nfx(n$SM*dL(`&A}Zb| zf8Ff4=JEzavVf%C1I5Pi29F^rUGWZ40Zg!##tsSSg!H5{@wIHcEo?g24xlmJMy4Xz zcVHXzBi;<{mHVEPy+^@NM>wQ(%8N`cCW%h* zVF1MKhimd(uMN(uItTXE?SAVRMFZn-ReW(nNVYa<1CuUQ_O`h7rQjfKWF?Qg)d*(j z(4|3OuVfo43bem1ca-IK5-bBXAU65WI;@im@&%xYJMb7A+yJpz94yOVu+AYh*&z}#8iZbAl0-Odx%kpT%q(_glHhWJ?MY*FkD2M}45g2v0Zzx5 zwNf0Pc(a);yeS33~4nPz=-e1@Ia%TO<+cQm7;abaPf@Z63&R`_P@;_#x zhGDEJONtG@(IeVilIl$HwoFkY+fh7DQVYLd7rN#~aKs{{t1EI7*{Lly(DgjyCvwuY z)C1pZTgI|U+=NcS%%BpUHSHG8Rb_ZB6j6nSnB_Gch-c1_KY?h`86#vy8q=9TIu4MM%yQPGTPixPg0;IgNj>y~bdoI9LMz)%kAw)I zeTM%Ib_qsK8||~LL{d}>4FBB`KzTBH6N!_+fac9*Tnm(vGr_dlTXcE=Asvv6b^2iR zB4B}ws(9kTlEoT3bd>$K|F zckuk@1;j4u#y){^Ar-l`zb}pxu1|K`6$O5^E0*kPE;v7+(vP<$!hi?Ew-`UwU12qe zt%Av*(S~5t{bCt0Bl93Wkf(PC`!ekV9pYE*t|3JOA((7ukk!OH5Z--tW`48&5$i1- z^k>kd4Vz$~d6_*$cl;uHlgFV&KWQoC`(Wx^-EdBRNeX-mR>A$_>!Sr>4ny4|gWWs5 zfRB3+YR@4!KFw5bvb9*us(K>`Bc;arIvrHYL*ZvEZ>@OsQueei{O(`$#c(KjCN09I z*FTqcj~IW22LD;BwgHKqKK?|7`{&6gVyW#I=rDVgwrp%%-;-H2IGk+mg3J> zAZ{{bB>RtB`qZarg{>I>!i!R76oXprmPtgYJ)kI?w%-feEn;R~7g!WQ3cs{2;X>J} zJc|G^QG_PC>5t;th`+Z>A2pZc@B#=58FxK&H7dsoUbxKS;!A*j{VbDI<2B?)zS&6W_kg-}xV~KGk0+dsS)fjD6 zqxWnnlKA<6?`@1@g$$}{EJ4cxk+I$5wOY;3CeqCTw3oUnrC(%n;^vS7c%KW9V?I_U zUVLB6@z|-41JkoDB)<5{iS_LohQ-2&!*$%@5)#H4ssn%e7~-#`@6%8;jCEH zL}%|jD#KBjf%C$fbf2`_?tT-Ndq>8q@`j?>4sUQnRD}gaS;NhEK{giUA?@^}94M0E zSQy-x$@|w9n5}EqpKEcr)iTVM0H?;!c0)AfNCS7~q>K~p^`g4gKwUcVS)PLtkHEJe zRsAq!gLC7>{VB*|n|b}VmV=Iw4icm6ikX3z^25izxRe;_;{|0m)#$4N64z)l3(CO%d^h{|RY!d(T^n9O{EY zDz2ybE&Q&wDm&1LSnjRKimjUmc8v?I@EbkN2m_YdeBT|kl#H$Zyj1A?Y>X|a=bS6; zCM$X%HVC&vy@}FYRgX093N=&K}G91oHZse zw`&u-2ul7E=a6^?^*%R*Y@fL|8RTo4RW>@ldgvCaBbyO0!l|4xOI$gfpXd<@|lFOORF=s?Kzif~N5BHG7Jottn0>@Xo z-P|0$5_AKs*B=~#_yZZ9kqEp;dokme3R&8)vjWQ1o!ieNV=y9l@)r@noTZv2xu@3l zZ8Jtn@5QHN4d}O^m{lZt3)G51rsy}Gnx!MN`P4Q!`BZBISXR&y^V-6DiN3!!6T;^N z;OH;@CuE|g;(wyvxRRBHeSM|Yj76k8>g zDiXj=%q1?Q-rGH`D;W%h8h%B&@O!r2cq#k@Cj(Vl8{lLbe=)uCoA8<0?5d)(uGh}>+YH{kJ{df zlY!ytYs0&ebbruT-mY)wft{apatB1K9RVdO^Jk>;*MDX=^%219IC}l3Qv6=TptT6X zK-esWn0TlKj#`m;=!{4Z$=fO1C(dXvNh{FT<4cS_wV8&tr17FE>zB2I`ByC4R@G2y<5y^VQ_}vg@odS*9($sX^aIG1 zTDFki)bFk5cYJe6bcS7ophfe^1+zB>jdKRw9OsC^+D31NLa6_sl{&b`5=9bW{S&|( ziLWw~d=J6!;>$wAaQ;MA7K98g^>WC}AH2#kYWs@1R0jOzN5!vPt`6pg$&E1L9+)aX zOS>$PRc7(UwUq>+bW)DTnJe=85=v@3`c1gj_GEt^?rfvTK0f4GQj0=Xgl*^79Xx+@ zw)dLu&N$C6+1;K#6khA1bB{Vl)=5p9aG>cDz zA#d&JbI1wCx_QYO!;>(6>2y5xXq6$EOnC()7GPwNUc^K0NG93<-5>7r0v>n5Uv6x( zlM>2C*f)HO19hw)V|@va(!$>vcD40L36?DU(OAS=iMme2huq35!f0eN1k6tOIVj|E zE^Q?~!H)S&kuL-AnV45}#{3-Ti+6}7rMG4zu=E)QnjNLJYoL8`Za4kvtr8Kk?FfY3JReU%hvvROcJ_ z14*ieOpp%I%SFY&a}8bK) zAF@nT{n>UNJeFu9@h9z`qEz?TGM41xf)Xu7w&O##gIKLvo{r8v#u=8|FQ|?~ELak-KdadaCh+o3b{Z;pjRWuGb7jSLV z!}FNyk3-n?a3C6JlI0(egJjQ$Ho*p$0}tz(y@_Vc30W5T>*`>Yw4n6nC2+QSeL}O3 zTk2f&)OoN!T5R`MrQ(e6Z9Fk*^_*YDhodU6#&6+I8iA<; z_ddwos0<{22;$9Az754TSCt{KI&$vbK>m|EvHMAmL!e{jZ836e4K%=yK7411#j~d4 z+Hb#C*&xwyvH#|^e+8|96E>w|h1yJf6+lVTqrg;Bl~of1b1>NElxdb+=YpIYEyAwf z2wEjVLV#9aAVXsW1+KG~ojxu;#R)7Uh`etm->@0^5yJ-WQJQG!1^uNNI||BHM3xQj z+Kh4^i!yBjW)~^(-F*OxJ`-|r4+s<}X*FM~slsjT4x0He!A=yMT;~am4@zF2 z9gF)T40RyeuKY)v(xOg{l!aeO zvPN5V67KQ^4;Y^UHCDXW>FX!Rz=Fcxm=3sjX&)P9=_(8MEAcwAXk*TcuwF|K&qqVc zb*j0cwfu3m?_dwxwlBv)ED3EMN9)s5VIPfIXUhN0ZC2Sb^gz79BgXoAi%m{*c(O+r z!sJ+%q9)6&E7Mb-Tw?jx(umxLL$l4VDM%t{~_Z(&=nJe1quE4KLXv) zVtg>bN3Il9u5zeU)GA@XKXHLyH|JfuU$~n~L#Obl`6@k3N4!4Ade@O0;|l(RMUHJ50neGr}~A1|8O^O1E(7`pxlTRzg#RQl|pqiFE=+q2z7T_q;TJ{a@r0D(0Dn z!mW)kcPY6AA63l*1K(E5E}oL$`5*JyG@l*^{QQ773#9uy>Zq2Z-N!SnelEK@gmK9x zh-iO3D&Va(h1)}x=Dv)O+72xuq`?8?bB3%Ud|m?BjqpQh+6NZ;>iSS^MI`yCpZ|Uc_BfLzKM zWBR7CNh-^bEtDLYH8PueAoR^LL4dRDfqf}L2QLe8`~cUh9u~=WUh)A*ncyo*I<8|; zRW%A+ocWrLV~xQzM6jTEPA3Gk@=!s`XF>=bY)H;1zZzY2&cHrk3dcF%wsSZ=D1sQ~ zZVF;+8;!{c^RWK2`1DsBaQ6FV1?74WpG&7m6;yUW{3nJNvMLZ&tq|#z*E!#|-xiqI zY!HBwxaZ1$syoJ${_uOyMI;T$Y+DxWp#B_$+PWFX)4UAUsy->mmoeO84Dxf!DPrNw8#q%Q`W3`FvUpp8Yzz{GF|L9G47D{ zn~-vz#4?gD51n1?JLk|lH``4+SDU91vgDJJS4=XFe|C>uJ=wCZ3s9a#qY6Gq1m8{J zw*bCRH8xd5A)Z;f(VbX3BUZBQ_K$0?kkiKt*WcJ&=SleK`FG#L)cljba!?Y#@2S$0 zoy<3>Y|+m0U}(X=X*88smk?rH_%y2bXB&Cz$eh ziY)V|JN#~oph2+AbAl!rH{b!Q)=GkV*U5)J(wagsy_)Df44?c#*ZSv7G=U*GrW8ME zL4RqBb|v>mgO%@(sX6>GM59v&oQe$qExzz|g~3kLDx?ECm88syt^4Ntlu7EeH#X8# zP*2nh&3lkvpr>C6Q=-)!#cG$bJ3t``((ndko3Dpi#WxWWb1grUurBI#o-=oplhYeP zUJX>IIi6!IaTm))wfb75iO3r-H|QJ`_-cXnlIK!PH%R(u0lJU_H^;!*`oe3SK)SF8 zjZ(E|%XPiYA85(pCzMHX9QM2FSTUN4Qty@aJ5KI5hoTU9I;|Hcvd=lD#7pgz#C0@E-cDFLfzbt1=G%g3oZ&-tB$f{QW} zK8{d6C>Fe(R^MZv(vx7bdB8lP8@c;tZCk7FZt;a5gOh!er@Vg<7>|eH!2!vRn*?>T z?*_)CZ^#H5|9qP(J=(0?lp?4QJnsl7cThi6l7Uz8b%Z?{ve^U&t+Gb=R&qy>)yHI@ zHzIVbF+3R!XHkE$v!clXwF)HF|M~Y!O1ykPCz5U(OHtX{np4g7dp-}Yz8>Xd=k%!E zX36PQ5)mOQ!06V{Q}9LFQw3$v2coRrbhkK&tW>gFRSX;l)GD}P0&HQSbk`tP z+_{BmBR9@|=Vbb6Iz9UqxghIe#hB(eU-C{LfT(!_A5$G&AEV34ZLwnkY!lBAVJ1qs zRRQT~Y=UucQunbbDg#i<@LyvB3zKyhb7~OS{Et?H_3Lm`zpK!{VTH?)&g|~_eM3ab z)BH!&_pUcjby6n&499*g+9;>|W`D>`!#~E#lAsx$BX%mZ=aOw`cBJe9kwr1E&{C)& ztjoNRWXcpsR=RgRkp{*rm_lK+s|{K>H3{twj)D{<|8_7#?o_r-CCiPI>VGDmNykjhDz1b14P%I{0Y!%gHQ!?Mp^oq`v?0-mB>Xh^uCKE@qTdbq?OUTALbR_97u&OHsQ7FC3K{TDi%)7-> zHh7#;vnER^Ud)d5izg_CB?C$L`Ji{xscfhi2O6co?AhC~q=I+f+h#}x+%uhEY#d$neTaBe5 z+MB?Ui@bMk?=eAJSAvFfS2hk>_Od^mBjo^e6;~xwrKaotD? z>kmyPKjX)h#GrrAq7pwXfqAO4M7au%E!pF@_E7@|?s4f5vqSZ8be2EZ)1dD7!MYyj z$R4q6lsDCs;G$!@tjF>9<3KVPvT@VANS$0bcHU1z7Z8T>4=h9-jaT$fz)5@INNyjYlV)s7I))qj+CJCzwXP-2e?;WU774yS|4Q^ z?dQA7zglz*yK(J||FxU?Rp;s(%IKepu^HOPUb`yX867+GjN^*Yd(@j^Ceb%l?wUyk z#h*LTCoFsSQSOfYMqo=6bi>2U|5u#Rmpq%WER;hFabp?&OMK!|leXT4KN%HJbJx8x zcOH1Ty=h*Lv>lqpjKIvXq=fz>0>B>6UqzJ!-%n_pG6FilieRk97X&=qurnKCc9-P0 ze2pB4B3VM?81Y>pn(Z<8YL3AB3$yO)WR(qLRue5Lb+U4H70=~(Z*qlunNB7V5Dur6 zEx7QE##Jwn-d5wVZbTAvH$b-NW^ezo2-*YmEq8syTKgA}5+p5b4u@qG#_7cl3pGND z>OrGdaw~&;8?KNG(?LYIX+jGlKcscJbE}hydNl0E?9>vk)+)SNjEdEF21A0K>cvG& zpLT(TQnjk_q6QoZJ*k|j>Tlr2vD>W%EnXQxIo*_3!Me>;RD^D!I_3pnIUmozPTYbK zv*X{RZkKyD9#?ejx=$Dzv96{o4_#Qnm4p&uP6C-nbEjsZj^7Zz{Ye0?Fxp^6(jn@x z0FS;Mc}?e+Os6ESV3kow*y8wG#eC`hqHkW6L5(IZqlOZAc#f5=Aho%NfJ=n7_ToSNet&C2ayMGLrgI z=VK=S2?Kwqh1kqi0kUU*+NYhEAUkj* z@&zC-x|5nac1_{D9AwV7Ut<=+#h}72^4Mf$ro)FZw=HLWeKnP2sv@D={cNbl5TbAh)bVY32qy)uPP5_D18GpKitaDfUa6^h zPPFrEnkam_mDdXcp2VPiz}$G@@h(JWB5Scpn|bM|c-%+#IMxAYFXr}Vb)AERfe37j zYDBW{;rHAxtBUcgORgQsxW@QwjBWY9>~5ixNaW_3`H0UjvcD$cut{;bv<`Ag6`2k? zSpR%Z#IAK*GKU00J1ZvUF7?|Ed1bHyM`F7}!@m$Ud3sx>-Nzipu}xO9uP{zt zn8064^huB%|2_n%#HLW0OK(g}1@1}BrdqB+9!*7zHiMEl!fl~RzX^v;G@5w3FQiks zh)r(RY<3t(G@$DdS?b{wC}Bc2#j1i0MvCbCdZWLfwh19e#NPbnEhQfqXZX1l!9MPZ z#VkD?b6k5n-$|ST*Dq-1 zy*3cxILv-IXEN#zfCUw0&_F#*d_k@8Gs-|t4Cd?nO0pABr5}zJxWJ0{3E1HHGAc!h zzK0tvX(AEMsXTfyszA&@^!xo+u;k1{IG?-*tXwN7a7-(IE8H_|@C!Si|4pvUH-C0p zrA01nimDw6w^p3?iqXnPzd>gcplbm6M$a9Cn)RBCRDtlmxmXL%%O>I-K(OGC)Al$&Lcgd zYF`*qS!ycL%U1f&nTYS4Lgu%pksJpN1jqjAX;q-SJPoT=Sp1JAkfr=;L+SMmA|$TK4!RLgZi>WkUESfkTAEyY)Iyo~QBtuzJ22 zoO}gt%H*2uq6`)9x>^}m*BoK4Jv9)GY5rINPRpVIA#c39-mFFt3hebF z&P@2xVJZw+g!T6ixUivhY0y~H;j{keblVWt&#vps2qK1sLUt zAZj+3k-Jkr7tk${0PfzulIE?+if-Bow9logoP|MPOq=w`T%Fb$RLGWf$=7E^jK6loVs~= z9b2OtsJ)vzFA%$^I=aX)B0$&wh+@J?TM4cfbaqCO=UCJ48LU{BdpTC3fXy331F!|U z#fQ6hdU=(<_s+|FeiO8SC1`1?o?!u(!&}`{0ByJ%WNG}M5dVAP&Z|eY#HgLQU5;T~|f%WcNk<5;@C`dwLKpfB5 zk{c{?hD~{p-nX{;vChm*>b4?yc&h*ux53k?!lV$&NKv~8tnfWOE&j(UxFqlNbI+o$ z3`H)td!DunSjRD#|Mf&BnOkH1W6ZhTq$ynq@hqK-xcWQJr|`1lI~Hr-e&pjt!_?lE zz2H>YpRN^BWRN<#qecb5FXbWtdZPop;NG=YX?dR}qz1JGLm$LPdH3#=`2WRI7a_R1PNCs zn=#sZ-U?-IWOHhpWkh9TZ)9Z(K0XR_baG{3Z3=kW%=&dy+*{HH3ga%p9U8ab?(Q1ggEj7ry9Jlv z1b0GkcMI3*tq)vl+icI{s;pe9#UXA(1aGzCgK zI=C{iF|+amG=MrXUM@flpo={a#3bixVrOjzU}t7!RfA^?0)GI=Ihb3U{5DsT(h$?oRh436`JD{_ z8^9gBr}ghh|BDU{m<-@=Hegc=7f1U)8vy96TwR^`Sy((gJeV!rK(5S=E|$zrcJ#kD z(6F)wb8vLA1%TgOfOfz?DRy%(2N%W_OyrM)-z5epTAP7$3H(C}2>hc|5>u9wmQvSX z0%wcqcfy(esy(x-r|TasYEoj7N>cwz{X0NwJ0R#!y?*;L2N&7e4#W)J>@R^mxZ>c5 zz?-`Mhc&n`uD=7e`zsaz2nYl_`rq_eEWlBNSpKyX#PXX7leCJm29u(kgp{(n)SoCF zUH*39>Sp=d_WzaP|4E&d3FuGAimIxL0DBW_2XNP!IGBOsb2V{w0|6-h$iOe4ImKT| z2LdGATwH!rQ~I~c|RmRSN_0jvO^Gx#{0 zS+V@y_RnGXEoS>I24}?2$H~zNU}0hh0{U570KsoaJ|Gi!aGScg0sVabsrbJLiH!$f zZf)iYKKkIPg7n9`oP&iUfbTCcIFf&>{?&wZe|JqN?!O{*0U}EF?OQ`vK1lfVl1$gpX|GqfDDpuD2(t%sv%+>)20s*+W z|EPfAB>q?2;DY{+8o(m1qM@KH$M`>+@y}8z2Qx==YX?hkw{rtbTwF}NkXXST#?HkB z@L>a=8*`xNpB4nLFgrN9f=vKUZmxd63yk!;O}P00EKqWU-D z0I;b4jW_`;8h;~h0E^b&2<%h$KZuV9z+&<@;svmn{*AyZ&HjUar;5e=9}pZ3@E?#J zz+&+?WCz?g%*^R;HQ3h41UzT$fEKQQOWFP< z{p+ayM+^?q3Fu<&_>a7?ftkAe1A=LR{sF-jf7^3`-MU)20RN5#JTzHcJskgG04DDC zcgeus{@k=6Ge?(yascPU{T~p_(c>S*0&nB>2maqiSN(mF{27d_e|P@Bo*MpObypWh zTcEbJIr!P@A4`->TwSa^^;yAFjSVaZ|NQ%t;s4oy`tO1K4{LF8M^7InPH+!1vGagW z3&-zYtURoK|HszsugmVwLf=Qi-P`8KDR)(lyf$-EuoDRpgDFV!Pn9K5X(OKigB4r zVeqAGJs;Mic%H2p+rd4ZT9ITg8Y(CFpxHvXmWf6~pk8Px z7q>*Gncw6je!4U`e@68LioWhJM7t+Z?Z%u9x-VKsO=0+}yYO*4Ob3z*KJA)`M|+PN zhxAe}v4^WQVcBMgUVug@g?eZoV8b>dYhi{X*!fytg?YvirNm}Tzr;eHAJg+2#fkcf zOSgS_bH3tiCy4#s@&4kqeFd&Hdcp54KR?c#IH&*7y-s%$kED7Qd!?Y@7KVNU?~_!T zE?l_pyYDFeNNW@()kZO`R>r#yR&d{n(cW_)T4VAvp(>Rt8s)4+FEUgi&d}kX@J>bd zs0j4&)*vz+N;;{3mlQY^<}uZF(RJU84F&P?@)q7uTjy#z$zS_rx!uxh-PRP73Y>&JgkEEZJ%*ihwBdP{H3)&FAiRT$Y>SeG8W-pLDuy33?KV)$};#dWEYQNP#e%=U7BiT(v zh@wZ4uN&us--hZVCC@B$*2^0Gb;pXwNgUXerN~2Hs_eWYtyq0ow$jh4&jO#`KK4Xq8a^^X$P6y%B2;mWg`0&a z6!1Mv9jzedZY+Hwnpn-V)1dO1iT1`+fkKZSNH!^Cwt)!WMTt+S|3q~Brk1>q9AEy2yydy_a>PRv)VBZA%(Y%^A*io zW%R?ok2ynmDhjsZXh`YUje0JPOd){-7%Yk%W1f9mxv{}3haS0-Rvsl@o%I5F09@}^ zm#v?Exk2*?O4XM#%Shsr4W#zmMxXeKq#Qt;zJ2UnZnB(J8q29tsTZ0)OMSAah=P%} zgIm*eIL9VC{%w?MoAe5S+{JHd@>vx=qtn(uQW_-dI>Pal*9?LH{`HWt28c%yqX?iX zYqaEf0WN*oGNBlE9+dE8cDFt&?0(~R&nR@*^a%YV`Yp|zy*tj-=h?>iXlzvJs+_0K zM|*;1$9~&4U-s^^JOGX15Qx!{-A|1vKU40zRA6JKxC)XiKQZO^HMFUYn3saiPro(u zU_InHWY%kD!G0S3J}Nz>U>WN;Ww)Ll_fD2Q^@G=*z6f5Ihkatq`o_}mcM%pX4*pqA ziRbJ^mN(ndDTu`{kybATF*uIWeJoIsfnQX6;R%f^y9q`z(N__C7?LgJ(aV<~G6=`7{qoZ)MrBhGnSruXUBxJ>tLJ0LI-vt*cO*INgnjNlvYB*v z{9lOZFPjX;&Gho(T@cd%l@@;{gggxq{FGFh1vN2p4+ z&UfgTlA3xbb9c|{vglhs1<@4uSV8jFj$9p4w%>t(*BH$t7Z~|G{EZw*Vy(+g|Ti{Y#qY;L2+h6*+1a zgYtA7b$_Uvu4TWCEw-+OUI%DV|t4mlUgAtcY0}WROoxM~A znYMxQIJ zE4!^sFKo)LC}#~tgf+YyYEj5X|J_vr)As>B`m^`L9VEDRc<(4fru>}QJ!se5@StAf z{Pdogqc~Sbybh5L_9}fnJO>15!u*eSNAuCf-*9{4@f&UPK%#Erv~u3GloEKT{Gf7k z)i4?Dsq}cvRLnCt(%uQB=P=#sL^k|bsLr+`s@gM>Jo^~0teQlLjFDBrKk?B8n`uXu z#o3`7D$mLHs58>_^cIhX9~on4nfEC{HZ-WD_VP(o^AN=QPEM4Y2cf%RbWNz$;M>-(R(#2X}y(KO7zI~pY`|OeQPw54Czx$KT|d%Kr|mu43CpOWwN?FTI4_;UQ+jh*p`X+` zN)7WGxTcYG0G+^7m^V0;z?qPM$P<8@B-{gTd7cP8*)QnRB|o)Gt=EY=xCX7J2*>v~ z*SI}i>y{p3@k^w^L1$QH>tg_W?0cQoZiX@Cx=2S*mhKjWg zwlEw)HICc%qp$rauKRH0=4SMdNAmU@gZs7Sh7@H#*+Wc8~;xB+4`WkfFfd8+D!>dnh_IE z5l_w;>I;Un*7r7C(o}uKR;5+h0l89#ira;2oQ?(&vsQu(T8 zq#)1sRZNXdIp0Q81$8_%30HA6eP0(a`<7~=?j1VtqxuE|&M(M62XPd+DIFTlWq{A3 zKJ%F702#Ix_W0P_)qR<5wue`Qj|&xqA9X8OTz6;_as5zmQ#`*f*_;T0UaeYc>vLR| z>m6kIP+jN^%6p1Y-EF)moavl~2QHW2K3PZwIb!sBC1(=9CypThpDD^cU~`L&)O)^keHponSH-0wLe_T1cZXqV=+AiM{?cwh)3({9-MVdh41; zYu$84v?f(zIEb&tk-@vvk^O=GnXb_d!PAu#GZtr;aEb$^!COt(FhefujZEM4QEn=K zS99n$$}le}V!*7S4b}OuX)r7X;{(nMab^1SQ4b68?RHM$BDu~^Sfgi^i|Mb>_v3fr z;<@sCDU&8Vj3z=}0&=W%TWiX80Zz?!4Pg?oRDMt#BGDql(O-A+B!WmF%VqSIUmc@O zDsO4HM}CkI<7N&%X5Ya~2ut z&Mc7XC6lxGzkA#lyDEGDIC2v1SQm1F?5U+-(HM_Z^=wpXRI z6({?8f=9JBl@sf6IVKYAQRUb~`3)f`=TqcI^(RaWW+edM789em9x zjo1`r5KFE=%k`;J)gcnyODf7BVl_x6P(gJf#c%&>RW{zIx=d=E;B0B)p$Z5bqa>EX zn|e{ReUxY4ajp-1P>$%db#lj-eS}BZ1dpAn&6H-lv_FC#l52bV>qBV_#+MXdtUda0 z&U*A`4d2lT;RuC)*dSbFFGL7u;s5mfc&$ zGwFGAcaTiDdjsb)1y&T^DX~>AWl(2onCBSpof4*Rg9zD`Ux>;VJ-yObOl853CvvbE zm%v}+8DkMM`JRD@6I4rx$k!ha)10`ai7bu=+SBZ80uH^^u0+(R`cdX}&@ZSLNw@2y zwqK=x%-B6D8OigCCg(59rxy?{W?jjhyuC~fz76LTzQvGR7r4BJw92%YFyJOt%?b4%}p6H^-d%G z4_jnuEmPzq--cQv%kBuIy0IrO#8#0m*RF#ULt%MB-??;2x%`LpKK#!w+|vtCX!u2` z)M$Rt`rBJQYV5PRj^_pAkv+06L%bI+vDNW6yaDLi2pLS9UyA|n=OzF+h4DM$zIbw} z+0_CrQ!_VS*CotO`t~zV=yo{St1Y48A1!?j%HOT?Ag2^NATo;pbU^mTzMqe^nAfA) z4eg)?Ow!Fyy4(wAkueStRt5~ zRm;xbg*NX%mnt#@|vu@}t4oqe9@xXu2KzM5es|Axc_^1V_3d1GbRs zW*+)ogmd@izHm?Pk!qKF ziy>(5tVU=S$r%!tHb}2X=&eWN+X_72BsuvJxAHtX$3D__pP-CA&9P6yk5cTPj|Qk6 zHPp#ca2~yrbxK&5NVJ++F&!aPhHpJIj|(o4n1tmV3p)fXlouy;V2Zi)TL-@zS1l)I zD4*)`a<3=Lep51#e9oxyr-*_gXUqB?HuFtBI{Yg|ipeg0;Xwf9S;?lHfp2!IHPr=` zIeamJ0e7N1yXJsY;(cKk4rP{AT;1I?5n6)?8s^uZ!5{X>jQDs+_mHH&as4{rZi0l% zAm-Fp2wtnB#ue|V$H0sZIMc{dW{OsoR7d7O)Yg2qE)>e~Y=3`O=Lgz9lOM8ia=M^) zu-{OtjV)qTATq0VL9n%RKznO|Kv5|_&RZgju6baR1o;H;FJ&nBdZZ!CfSV*-YK+a$ zt)-AudZyX$^6j!ef`M46d^=+9QDEn8sf zB^=mBj+KkQli4gLhs)!>XLRron+r?|QOXV?~CB>mV-VnOtS?t8zi{r=zld8J8anXXDqsx{HCi1q`Tt7|fm# zMW3V~O`CZH$A8u-%IjvYH7RNN1>j@vtG45Bg>`wo@7Dvc>gDH!*N&&D#i~ZkZ2KJ+ zaQ{G52^<|m%ziNLXD&Dm3Y44@bm?WD#mbmDFI`)Uoc<|5C140tTf)zle{7SOcn}{x zsS3deW|(lQ!b1`F(}@;h*v*zYhEeB%lWD@)w+#aj zroLhqUnm^Cb0M7s`JhU)lG?I?`AD*B5*9T2Ifpq~;UIV)muU!P;VtW+k6Nw0rwj*0 z+=NTgVeGh!RD~7IGx4DM?oWFH?`odX!@a5^wJ(i?LE$Q&>s#A6_G>C3J=TVdH(eUh z!CRFqi7a1=WtIAJ`yw%<6>?4@8~=b#FZQrk>@*vy7`C~kx7b1e1&CF~?x2b{e@=jd zb3!F-Iq;A9$dayFyY0-wXgkG6s?#0pH?|%zj#GU`POXPP$^5jiaHnef42yKWdR=Z< zq>}MeU%=bE`VnO-m_f$GJRKrepZ<~Ki0@2@;U!6qElCI4s}%hUNEikFHd9hIR%dN7 zJ>ZMR+B}yP&{ANxaltBObjyiD<#wq-`qt+T>G(>IVcQ`k#xilPwk;4&m`khDYPzn9 z3l?Up-AX?Hz>JY%;SGqI#%>o{OCr%-|A!gkFf@s(q4iqhO{H{=U5j|m+cT2wx3!fQ zdXTLN&%yi~hddgriuVe#l{vpg&A#WBLZ-X+XR1Mveb5YRU0(j43>eCCpbSqbaXcLG zkqauBTt9i%vR@RIFN|BH(~_>PnK5fVk1kvpk+e}Wu4eap=rufHIEo<%*=pD(v)rdw z5;Q*Q@kC1_;Zrk@-mPe0Jh9g|%p1MPf?J(K5p9~&7B510^uSSW_H$H|#Z8;kJjI8c z-Pw*rBXk&cx1$Ra%2zqggUnQBv7Zl>Ztt;u{T9||v2zt(MYt(>kpt^P=*%fp(NEm5 zj>dZV-G0o2f-n)&u%k~l3+9q`#_0%!G!6$yk{OxMmsn)yHY3&OTPTM!$e8_!QDeNFN2#pS$)By@^$sitW9puk-np2i{Orlq zyIQPnegOXPKv{}=CuTsjXsrSe8alDtWuov-;e>bP!CV6=yv*W3iF{L2|iDjA3t}R4Kz>2zwXS< z!}#=Jd!p1dam2>lu|{CgeDmq!WC& zSE-M3u9L3~8fFIb{1&Q+#GKaj7`J1XYV|Heu7bXPGPiIGk;xK;xP(xufQhO97~eu$ zKpdie?g!@g95ov6x_($hzGvY^-KsBN zy4Bcu%gn)nalP?`rSZe`Jqkyq2b?3#{U*+%u4QEU58|mtD>;@E8%!p33XYjrgg9P5 zLq9XJuV_Z-W6Pw_2(n-NYb2i^d2Ee8P8SR* zwgS$uux74>U;Fe6qtR~Ue=^5$RP5XWe{ySZwtC94d=!IZSPFu({KT{ezjdi++? z`UJNV3e?y5!IGclFqUdZZhCoeR!3Q9 zfO}qmMtkG=BBlo5stebXJoBsmIap)w*HGU@-R8_U1%U+zT5R}%_pY)8UxB5_99_M0 z?$(>u@XYWv1D*YAilS9!jXY*)cvpG<9>aZnL20AH`9TQf*EhWHmsmEH3}t&kLv&0X zf$%ODM(JbKiLgFjc`555*5sCZsMy{XtEF_K0wNn>8?R`NbMr>Tb&eoybS&Q7awG>l zmN_x&@16O6E^7A?9*jlGLOc^H5#bCI`aVK)NRmX+`u!JEGeXrWDBuSLa$i zWuwp;QpG@m21EsovwYJC6ReAjW>a&onK@U5m9?9xS5wHiYgLYTbAx6%Uvav5Y$Ol{oD%Ckhfkm?Y*A>^aioWF4w5FFGs^)83MLO7gqlY5AF#RJRE=-OffM_+_l&ybEkU|_jGqG&E zZ)iF22{y;%GeM z{GI0FcOU$ROfvq`4|Jiu^QOR2gbpG8m2l4A%!|zE za(KwyK7dNs*!zJmbKvVcOdp%DWOP-+Bq=S)lY2203xbR`9--Q*GKXJI)UC{#8-_Y* z7s6}xT#h-6**ni#4SQU3J+z5qk_E`raf{B$<%erbUW)-U#KygOBe~IscB4<38(f=^ zNZC_pvZCdOX69)hZqsJB-b0D?7)WNv?n~%{TqVg~#_|)D*r#;5gM!2HckzZCq8xL)Me6pE?5_VlyX)V;J_6aQN|S6n~% z`Dj#?dBZeVht-)D`c%XoG5H{9v6K&lNCD+Ut#qdJU(?Bw(whFeVlr5o1+NU)b$D$ItYl@SpP*n%*5=$@O zvCA7dUSJt+miqDsnMqJ}nL0h|V>e;4e|9;2mly&laak7HZ%#lO)Du@4xwRA>UGn!o z%0hLrL4(ChH64E9p!7rBc7L>Oozlc%VfaLMsb;aI^2G{oGNbUN!oX(E$rTG*GwoSz zN!T^P5(C9(geM)~5fO7|u&mdo7CWFdxqsBftz&j|QIx8EqR+@bAR23}A^w<5i<*E^ zjiK=#t>ugzDcrb9ZymE^yyg05-=1_ni`bxRfJSFk&`D=ypO}K}rN=Y-Bc^sf>Hrl3 z@WitNFz2xteVXRGrK~#4X{rz#KZ?-TheO#&BUVRetT<72Fyr_Y`!4dfFGR-loKZg|@TW1%jf5(heW%NWFlcnk%Pk%jm3X5X5! z_FJUTAI3fiZ=q65w4-BwfA4Bc?va(}KD*oRAX7SMR9~I;ojQ2{KMz`zH`%71>ocvL zRq!%Q$KX1@93X=@|-n1Fj-Pe|R}wd@NfZMe8Y5`uHP10|(~Cp1eOJI+~ny)j|ugXS3-WXJflr{!xmAoa_BGoP*Rh?FeO_l%(1*;& zgN|&>K1G)z$!VwiwD!zyd%Wqtj$~jgCw*)UCgdTC!t7ZhpLoQL4|}FHTtmvS+!;M# z>3>Wtv(Mckbj8=|e8Y!}6PDbBhv6@3y$S2%V9`1Ovdxwxs1|(1wLw!ppk?m8%52^? z;GRG|AQF`MIA$`Y(c;t$zMj-ww}*EeCMq=9V3us??!U9oBJ9gbo@AO(>6{HrNuXk( zeH#ujpT_!lc*xS^t)=4SE$`D+hQWNL`Xqi)dDcV^QmH0HzJh@(SY7$)CT5jCzewRXZmBg+QN6;Btay zrZs%{YGvxRwrs`s(t)0f85JiRd4_c)ahM4u;z%sXZB8tcqAj>-Uw4~arN150MoM%Q>gyHqn;~jS+TMvj28x#Hi5)o=Ic7p zO^e4{k(E?`9Su`mTAP@E_*^|NqsaT`q~TJNC6Omvcn(F0AQV7Ik_C=jGk_y;sR@)va-7*Y8PW5z(u zT5YTYOp2Q5221Ytnw&!uR8?$OL zt}nbBSY03oBa!Ja1@%D`v`h0=xX?BnJCle$DvVzV^6zVse|`*|&@?{@d7LqLBkQiD zoQP`9_(@02*hTQ>Qpx>Js3}Q@VnfDN&btJQ$-ir>5`Gmiu-G68$8&YM3|Za1v%6h; zRo>4N#xa#l@?6Vhpk$P+Yes+0ci!_&ZQiTR;8Y6DsIJfJekde`%Qv?4ifPPR!C5m{ zA7?gvxzEQ+n>?xCyHR=Pc?|iZ)fMaZbq_j)O8Kw21y>5~HX@F#Z#+G@Q`Ma(@Eg8L z17lV2w}efOW>H0+2~H?ot`k=SyAY`Q4zQ~So72=S*!l+}k*L?UISRyCA& zUQN_cB^8i-3%3^Nr3-jF#q;&-R_u+)QUj>*0trl<1lfr$<1iP|9bDCQojdyyL?`bo z(e9;%M7)rcU^rOary_mWM#d zJ>hmQBFu#$xzs^LMK^BkP9jb5a~9cm`vCZjJpf7BFX~pxp)AOra6ymmJ-qfsKDRh8 z6zQwG4?1|?TkzcA1Lo6O72a$<7a^9lqGBxm)PF=jXe6ac1@8K{=o&(-#dnN1>^=KT zJrvR+h0a6XtUd3pv2hLzLCTX1UJD4T@qcFPI1>Nh(NftRZR#ubY;`Q~NO2CE_C0v% zV7R|tOba8^saUx2Tt{*xIi8uOw zRisO-ZpQ-#7bR>M0-qCOMfT~V9=$1HP}81S?Yp#RN%D!?i}GSvR%1kF^=ShJopJlQ z6E^5JHqW;Xq)qn9`kX19Xru-*I&wXF4LR^ZKZ%6o6zm=%coa^e8tJqys!_FWvqc-! z-(8+X>c>&oAOmjlLS|2~bCw-#;BR8qT<#|XuMg~|+*~#G%QDl1LIfeXxIdP@#S+>L zvulPfZZ>vS<83087b->>BfVMnJNGKKY^!${4_2q^_N5e4rvDJWv68HupW1C}HHC-< zBP59MjL&+GgDV!exw+I??zV*wZD6i-I4~q!qMPM57A_y!^UURHSgbDSr8UFueAB&; z?Gk%$agr-RKxK@-)|BS4-hv}}%NeNcM3_p^8|hPWuHp1#X3$Ja61~=txbRp~VpXT3 zCu9s~#ZGbVQ+w{R!twcvV%6}1_515gniYQ`feO`paVC#>#GnQo7gVi8D zEBjB+q`T+N`$42~SnlMjBuHQov*23Qc+!40g^1sYdQ~8ZDW+qxEi51>N!)Ar+ zP7fLsFjpcgk{q(NOy8;P^MBok==J@&8A#AEj9SbQH#iKh-BVJUsMe1#ZuT%BOB*g& z5DfoOR^6qJ0EnCMjDl~m7~-g@eI2?25;&r6o9XS@I+!j~#ucw2cNFPPc2mnSY!waI zL`6ZNd<-UuL}7oQN-5qmTQ;`?o1aajJ@k#MP z6^6i+oKY@~71Tp+B;|ml%n)(?C=kjddADa8s)(%sS^xGD+j?rwhrUbYNhW`1im37dQ}$M|_y^rD zC9Lpkk66SKCrld-KK>!=3@)%b>7Fc*>^P~H((7$Z7+8U;Whwv9Wzu#iD$1v z&GQ?~U|hp~p14w(u|~$|f6B14jt$0M;oLuHqzVA>km2l|oAc84th6SbbDna;QTHW`e*S$><<}O2L6-_2>64n?!j{H0 z@(Ve-SRd5>kAH&cNg4IrcoFA^m|P5n{mg;`os0D8;1~H-T2Gr@^DeJj3qe)w*{(OY z)<_*30*#zy5UqCpSr*5Q%O&|Bu0QCo37N9GHhmA9Rf0Y9u1yA zhciCLX4R(Yx5AZ+Csy4>v*k%?x4Um>UIoCqS1*`VBSeD<3BXk=b72_<-J4gtR zn`B%wxySUJEdJVMUE-dN$so4Tm-{~VT}=~Ka=E9aE~fEV)K8s5pWJ}i=KFf98@<8D zFq1J`up)d!aDj2YiLmvGtr?!$6qp7nS8vCspFK79IP*AuImDszFGM7c-mEOBW+&aq}aHCw$3~{0RiBBNMF8 zXrBH!c$5lqK#YE+Idc_47`VrPC#l5^$q{V4C^wnEW+1sHVuu;f(2Y4IA9^k6G-qw$aoJ{vrdXe$bdp=cbA+NZFF zj<8<1Ke%EA{_$nlh4tq}uW`psto(L>By>v_fPt|=2>PR92b<`9f@?x#V<7Ly+c6-Y z>14c**-_SGrCEDIi!^*nb2`w^3_f7|i z=XzP^28A{4tV0fKA%E2Hy)a*7{yVIfPsO-CW>ApCyUcmq-B=l@S82y7=gdLTTnATU zgIZu)T!+==m;83%en1+UC;IpY3hcZc9l|X5&!}GFr4UK56bMO{MHR~vh%B<^2FK9B znS171#+zuRvxh9u*lguxBuMWv8CZr#1P1e4aE7bGkz<3DfNICyx_f;T^1QFIAR6rL zwuzV)tuGHc3{MXCbzv?)g-^4A=wLZ_Ewfd@G*2k0ZtQH9(8^V}ocDFYdTIY`{`jj1 zL8fOqCDg*_FpJTCB;*jNgT^eEP)m2n!6`!^5}yQ8IK`ndp<&0pKNYA1DWoRCr4Ey*Y4?jF_bvSg8|z}gcu4UXVgE& zZu7e5mDlm<%%Gt>UVo6hw%fO@NX$6w@^`)XrAxJusF2JWvfAw@iAnQGr@gvqqjl*7 z$T*RXBjS#eq9Tvtx|s6o^{)WW!M&xkoWlI#0v(AH>9(@C5ObU`dG z5;Z@VJ8rRSpwICEOG%(0Fq@2xyRxBZ-#y_zm<2ar9z!%7s-B5&?;8+*Tlofp1gQu} zKi_5P{-$OZE8LG54CFr+5@;k@fK;bqF5onmo)amqpu%Nd6>na9ONl{RE>#J2Hw4!= zq<*MhaN{J9ztW)rid$u?f*}-XHi3(bK3D`D5Ja-wC|#04Iy&A>4hhqW`5c~`)1M3FyMs816Y$GWMqE4*DBnjbMHz!NDLao3PMmpuoq_L4s z<4k|i8?3NQ@ASyKJ=e1-4YYxYZQQWdhO;<(lTFy3_&AtZl|KYWcPlY&VW=PXyQE`vMz4$^V!XPm}NL`{pggGQ-A^$8#Ofvt>TQBo*?{g zIbW)^KrT@V-R_{i&-zExm~(5#TBlBP7TH}oo`dW?88ap#61%(0&3?DU>EGpDH7%(< zX1H3hF4z;Tv@(#nBCPWiIB@UX)x~lQpHYkYV$hsSuYHo*1Ch|GasQTGi<^%jnt}A{ zuoT9j01y(j(mS3kVzY9d=w}j?xiZ~i^uw2uLaHh-yq=hB35vf!)JB@Ivgk(^unV0# zbvDD7TSK=Db=xk`I9+&|D*sunXywsHW_uh?GMJjyQ*bjFgh@br^;CVJoL-Y8ek>7x z8-`5TP9zvFR77e~RQW)@=-YKD$F@DEiBM9Ch&=!$0k=j7Q;tQCCmgb$uqnN{elh^w zC^QDS&3w})8n&o#ZEwKiYwKvN2V6{A-hAU5w~HpSUzm<9kxk&@yWNS8X5Id%WLfku zU_l<(`v?)@WSDt2-;s;o!OPz*a2`Pb!7xv}qo?*ZM~`}9#L?U~?Aw-^E-XMbI}|f} zG)H7U)4_ZplY$Sc)~;0M{7?)~zCEb(GLXg2xc$MS)F7Op)cVvK!$UF_kyf#h^&m$X zL;<6KfS+;<+>2&LRKTjyHuYVi>?l(7@{1F=Kp*s!-XkG9mGAN4W(m) zpOl>yUItalQUHJ@*oz))tTM{gQJy3Jbm|Xqs>_#!2N)*`v<{XB{fe<}_-k2I)l_^O z%~R|AyQgZ#q5Al@_Jf@xr7Q(GP23?wP3{&K(`5{PNi-74BY_2AXMrV zZ04<7`-G7)`s?!V*G1NA*on_iLZt1NHt+DOy)zTeUwJWmd*us*@B~i`Ma15RLs<1D z_a>wX^rRhYRg9)i!y%&4#6rU&9ij24`!EBOXcQIo`-Acuyb()Z?OiS1(Uo+ziYB7! zz816&lZgP@(_d4aiChH!?#}@Xd;Vde=7E#!k~9amm@RB}m#VnkT18fc@QtJGaWRR< zb%wW#!0#{AVLvsUh=Zn3^Bey)bsMbM9_L{4N6LF+fdyUX)IRc@$n8}eTPjv=2S`-0 z?au1i^SC8gD%`)QuwKv?>`8{YGZ2KYxuRmby$~y$AjYHc_vV!Kzs_u1!)jU*l1{)5 zo54m-Ng@%Qj0|zYdRIA=w!^ia-kv7mm1vJ>pIE`$c{ZUZ{44d42+_Xmdpr~MK6(Y? zjj8qYehD`>9h9L1)DRT=4;kL5m+e}1;#m+oO{ey%I%cS~a4u1oSUPHa;J(7zkG^Vq zqq3)x#NT4Ivp*Oa$NTOSp^HXf8NRs7R59MpMq@SEtZantP7s_*gHq$VJ}6OrHUg}O zV4Dn0%NF1bqo0{8MWn?8xoyvq!GXG}Q(<~fvPNDY$|HphH6}j%geu-UC)2EWXKMgv z)0PtRqg(9(up`DZ z7ZiD~FPgZ!*-%0|-Fnz6x^H=9Gg4nH0+rNJDYxVGReLo&sK3?8z6op#EJRyOdi5Cf zk88|H$3nesGe{wm{p-kn?e`~=;$-|NPr0IBk>?TyQSqV)Pg_INs+@7<>CyXSG%}Mg zz^MZX#5|&yF1>D$QuU~NJY9Hs(|4*dhN9G8@z$;*6R!RgKMh_M)JjB+4>aqJS~nc& zRhDBeNqJxhdB-2)sg$Gj@Xw+m4JdQ`FgH^OYkibG@Lh`FOZ^_6NMKKiPaUOlFCrIx zW){1M{n^zq)lkaS2nuD4&d_<;quxfm`2!XsFOJ=iZp$vKX%r3ADwU?Xs~%a3r>?@M z-t0dn@qP=At!Lqv_DXGoSIxl*K1F-``%NQek7?&%E-~@1=cF1MZou=8bv&WKiQn`b zLjaYiC}y4i;}_?E1Y%miJO^)Z;_>3DkTF}ICrFJN+N{M%AlC|}`#gnJ zjuJ|0Ye)Vv8r{s^Kd zPLMQH-ke$#wB(>JLOUjY2elqH#za9K1DxgH;Iv%lmi}CaBHjcAYAs`{597(lh20;Z zT@nB0M!vugDNxYfqcG0?B*rEp6DFVAzW)P@b4)I(h~keFjUeZ!pReTD z#I0Hf(FhpSN#e?98UWB1A=9>tVg@e~$@DZ_)gEJ|L#ts6xz&i7e_rm+T1nicb9AsY z+zkz$4>;@!UJhY!4^?c7a=~5T0ux`p%*EgUpT$)#3U+j_Djr|30p~R_)d79F&opO8C*I zLR*HFtm6v^4qd_c{Y~-_G!oOnlAezeV$Bdiakia1@->{$mCs4ET0R_lIfx=AjlI!! zGXbCcT?^@lykwkFFto=5^$ws6ifxelWHAD_h`#I~CX*QYbDKv+6G^m2Z)uECwoj4U z060{68b40502DE;BFBf_Ge0OyG~^398XpzJ+%0z|xad=F1ha|`j_q^VQ9SigK%&nx9NR~5Re<{mt$hb z3S+xBGH8`fekg#%%{gM;hi?g)PnAtzmjnT<*SE)o(~m0f*9C&&ZE?`UzptH%L6rgw zR{h+dW6~bAAR~y!1WY&AYBejRSvlxb+SZ7?HLk_hpMeyI37|>aSUl0L$WdQZ=vv-O z<>uB#`7C)Ac#T_JQL21?XI^K?5boGQBU5-gl|sGGSB>|MvI^V^JS44gNA$VCvE~r! zrj6^}qstWN-f&V&kdGmG6I(+t4*sG7GG4Gm80y*oh1WPj)+A4@h zCCsRA617vC8H%u3$upg~uf@*_1cW0JJt8UaO}7Mf#pI>uTg-28VNSv`?lA!E;zKx4 zT@;Q(Iji3tJEFUVGflAsFUvK>Ou_;iE<2LD%XHwwA~i>Os)FG8nRq63T6>$&cdOLl zSh>koTj1Ta%oh0j^D?Tue05KdMd|WSjn$J=wqoCe;;v-YO!JP<<7dccfhI13{ZF|s z+68RN5PoqIeTmhhvn6fB()F&L@-7GH0Thc!RJTF?Ir^88doWU}tyOqCU+7i&H$CKD=o`&O6 zzquO`wzHoZ!k4}mJEPrzw1J##P)03h`V_!SUQhNgV`q@^OM2z}i~8A(mI|t#^WI4V znb{&}jGm-qCAX=jmmb042;#u|ajlaE52)MGAr}1ERc+g}5f_KENWZ^!o+oJ;X5|Ax zm#2^m9l{*MZLR{UYbTy8-)J;6ZR$kVI_E_0kJz+od~2qu>)`;xe2in+N`EcA%aR{P z&qTf;?hxb-no!JkZJz0tS@S=(f5Z@S{)n6Ev=YcYzh3kMuheD#`!x?}0tg~i0HiYm zne|AL9cV`K%XLi(R2G8{vvZDoYC98NnGWS43@Jvn)!aeq5?(5B7uLmdDrwx2Wl4nA zt=ex!U`qO{M6<-n3+?J>kQHCNa8e2M=tXB5X+r~Z4oOv6A0$oRrKher;MYIdxaRc@ zjP>h^w5=at_C(fO8WMmO6nG0tVAQL@ciA)w~;Ep0bosFs`rZIkj4XN%8 zUc^7SSd^%a(rToxm}u>>0dG^RIH8#jg&xIoi@p(T6?Y5gv7RyiS8dL$g5&bfp{#_8 z*nkds(xL7jAw8AC73=fwOZCrYh{_F`9o|dyelzQ`d2U~z$aszeOXZjp|GDQseU?en zU`cgprTf$ZLpX<1d9w#5TgE=prJu=Cf-4dA1P!?CHIrLdt7xy9)Q0oF*jeZnq>uXQ zmfED_2`Qz-XPu9f~`mT+|3g%}o7n6ue)Z)tZ2wsf_GmO#)E?#^Mz%Ga5ft@+{( z1mL1&JR+Poj@{Z%MxiTdTK0zk|7?yZa@5sjI`e|}GUG}#eV?vLXcS$9*4=`2VyaM* zUV?|3x(20!?28#gE=``B6&iVj?={MMdg+M9jK<`2Q!sO>=)`{i>|6|I62Qp4qZ)Zz zp4`u^b)=^`cluMFNpMg^*f&wsODc6)dXz>&M>^!yR@cW%Nz%KleK!M(58tP@Xyd$D zh=Gw$*Pag*$e+|Fh62L~)U|^dR5$lI^V0uV)_>OIL&B6~s@!bEyRe?f9AyfAV;!{Ory$|8IrdoTj<{zY(Nh*H5 z*?SFAj1UrDw@4;mc!RUWgLF~yGpl*y(!7aK;c|wS5*o17!jS1Z?{Sfr@s#yv^O<7q zpB>E&Ki*M6QJF;A=nC$65TJyn?vGNJmyO5K)miAr=E)(wvd)-_M1yr1*d*ccz(gct zi3 zig$b9kjR2}~QNiYG&`3g(8aV~}-#$@OwC%2Iy_8pIJZ=LXFV+$U0gAUuxI<~! z>{oIC296_S;^Rvz&uJSPA4?jcU|*YenTdJ8kxMrpN`I}Gx_QC4xEs5?mr_t|RIhZ3 z43W*X6&85UN^JSYmo-!_pK_{Wb_IRbx~{)NuuRvs7vtX6UJ0qk0#y-&C6Lp zU$pJ(=NDNPdXTIv*SpJ$?cPb@l&e|LS8!N1tfTCi?l_b(i4|T=FtJ3ihsd#l)MkdR!Nq-$#v)k>Tz? z?Ho>Et6}(%nS`eV?Prz1xVmMh{|*%Fdn8>^?tNb>c5*>4YC|Or^ynx2!uP+b{_GuN zaVn%0+NDO)r0eUxkTVh$|L_F1l3jx{-&hRt*0Yt?o?!q-fHlngfUb@)JT#Oa{)1+I zDOSNJ#6t3^8#cac{lK(@@ox?NO_x@gT?B;qMeJU_pp-GswL>6C?Bru3=gQXwS3_2U zIqevOwvUYsLIof`e|Y}bAk1N-1DuLy=G!NUO&s%k_+x|w6Nq&63iIbV09$E*%R~3H zA51fW?eHm}lJHECYas0JH>`9^i$rVYxZI_4IJ}6tvwzjOTtA%pnGPSi5DX*qKMyFh z|25)qjytyt zH0bjPnNOJf1$T-Rv!AvqN8^Ywi2;9reCv$ZB$yMH48cUbz2H+9As%T&s|TTf3=_#I z_EK?pl@o&`u%DhIPtg0FyQ$*1DndaBa>+RP7?9WUiQ9ZOJKC)_j2w3uA!V}hP@GYr z97A%Fek#AZjR7DE_(hCCd@jm@l7 zMTOfB*@nAaZJ}%KJAnwS%uNZU$Tk(GWvkDcy*`m`7t=l-z||?+#;NS?AvK0Po&jgE|J=S8)rp3J@o;p(gxME*~ABiTaxn)(Y51O6)SwU<-% zce{7mY!8>p5A!^bgO=M2ODU709y^H7Atuc2aEN~@%+`Iey|7V1o9;>N+ErtvenAlW z+>|)-jB!ZWE+zK8grP(-BaG?rMJjlM&Ws>7F6lh1;YodC{A8&DA(@ENaZb#;RGwD6 zk}i$W)v0{EVui0#C&t1g?z4KyMJ!pHJET1HPVt?m!R=x|7CMu^Zd9r=izw*sj$ zlWHc?O6LBgUA|j>m?jiWBxN_Zr@}s`0}G$drE&bR>}A=G4J8c}<(E-aJdedI4Vn?g zDgQ;bcZl6z8pfGQ2$s-&O9tql1@xUdFfhjC0QwZeW=4dBxhd++5hA|mk zO>E9ns@-x?b}@y;`Wkaem*21Gz?tN2(6$;eMZm7%5KX*SJKHp(cQFB9>u!2?G(9Oo z;IBoF4ErskaT0v0KmNOEtNQ8}fjf-SbNBXRRHF_nY`N$nUKQh*%%W1=&$jACET(e%k|ov8;y zcyBwDj|b+{fE++&=%k6^&BnGkPks|4C8BoA< z(!BoTbfN-k%{-uS%1~K6;S5k7B&`B#)IeA&dHsgLy0FmpeBOjXt!~gG6d~Bd^|H%D z`fZRK?l4cn;EU4EhB6-)d^~gvJu1sjD1)iyHuIBI*<&@7TaN%?fbs-P2@{YHUV0vY zxQJQzL^kj>-z2*2nu;%Wb-j~h|0YY|Gu|`GP@~WPo#iiAAmpm8=F(0KEEa8`plY&< z$;k96%JkE?uBlDB!-+rvb$Ymm;nA`cP;|y^o4r+vH)aJ`XtJQG=Q?6YkrTW z#*zsdb!#4LU(M`^Mjp@b7DdFKdZ{Y3bRd7|*CwIopyv-mjYlu-6(n_DvhEY?f15rV z_hqSU|62rH)RD;F9*?j)YY<0U2}{xw5KxVp(I-@LkqCu*Z4$(jY!pODTBh>W9FW1F z4idpm-=s_l*_vY>k1=(&afR}QeD(PJn;_x4K+32=0vhq*jIjwur3}Ar`S_OY5#y77 z#g!0yZ*ZmwNsl9}%@g>|#es$pOLT69XBxHLGUi4j9)BmV-ZZUAjhncB&X;S*>}0>}L(5*$Fje~3L`1_i*u8o_e5VBBdcRRb z34P%$Lv%C2A;61-_NjKU%T2+ZR9{@?;mue3A#2_HkmOrAcrIQeMS51Os(y;SrxgwW z^U4&u@n`LdfxeUfmZ>&`pZD&B(@~~A{UmNIfiXR>@E|N==9WJ0b5cOM;MT$fPn`uB zt=09U{3O2@w_UB{u4xrl0f5h;hpLRk*6rq8?43(SL-^)n1VO*uld&fUhFYpXz9S+>&94|UE;_zGe0)VepZS-L zOJ6=odO!T&1g^|#m-T~YGI>u zZ5!S$Z=unSs=?Tq@rv>j$fn?%b09j>!=s*v22hk zmQ$=@tCZlMSkCWy{#h_4iY2F9bmi#50&T9Vl~@>13^q)pLfsDF!bl;!u=X>}1qIJd z_)B<#umIJ&nxz?$gik46)K&<*5oX%6YV^*ea?i?a(2+G6^bja#I`u9s@+4QJ&RKSq zns`PvE%JmPFGN)8m)J&}E?e}lx@Ylgy~ZxD8yFgM`;?#*p_0nwZ?*q(E8nu_=_Rom^*z^|NbV z>U5DEzA(%ImY!yvE5Gl8UbODCGF8TkmJVqUyk!QnrzNy}YM9PU4~FGGpoSW~qviX6 zxn~fb_FfRNUn)$FZ!)e{dNoHb;lv%KGr1GRX0x05`(YoR&1RTiXlM=k3D?!5?TEDz z+?hT66l^Rxe3>J-U?52_sZGhcTvwM3hb&4SfO~05fhc&L=vLnaR0D=P*+SReF)mZs z>)P`Rl$~uI63JID5(F z)v?3;V+x2@B3lQ5Pxl2u=da0s; zMJ?f_nowbIgDuwQRZtO}gfLW`KLQp>v#>HC(#M?|Sv6~SLYXk07NH*2upcuGh~7I= z99n{nxX5Yo`(WIh@TJZS-N0Y7&l-(0afz<3OfxNADbEX~!VGRGHDSna-lS<*qLGME5vxj$!|Ku~^1bWV?$;pQNxRSdGJ>f@(+vXjj zcGjoiVk-y#9^k@i$?+}OrOegQMfi7-S##G_samuBf%%1Qpknymr9ecraoz-ahx{nx zO=sQRdP8juTa%A_i-yOUdmoTkVYHq+(q5fhB>(5hW5rV+{wf7$*|qjMD?)#$zgu#Q z3d)t&PZc0@w9H6x^I}u7h!PVneOMR2ZaU=!BPAbSi@&{h6UWr$ASI7YEu+@s_-*ly zWqg4B-5TrB^)ZzQ_GLuUgu>S7h_*xNGMNb-;9gkAYVpQMJym=wy3|>k?8^RRMt3tazXC7^;j)1 zDR2vAxW-O81a|aja5?~OTZpl0hTDgaH?85#mizW4Q{2fU(h#y*qhz5yuh{nau$vGc z4)Zr-h$>sJm2|I*#itQ)F*UEOId5Y8m8=IKQ>7Yi6^*i-vExj0XM7(qo9M3W2eQoT ziP<%YFThYg>6LJ|q07~6o)6KUrBf6qo>u-{Dm4KOY!ev^t43?j3ie_~y=YEBo6_pm zW|iG9u|*l&@LQy~6HrqBABJBt{*6=BjCZJKMGoDt7&AqCm7O%*Bn3|ROTpq;cwl5u z)WVqF(|7!Zb?4$AkLm2#K3)#n_PP~pqpVevc|B>-U1e;DIF;4qd|CGaN%2XPAJ$&v zZMo(Qae`??6KlkHd5h&R%}3UmevG_9S9hsO`o9dw5%{%GDqJ{J1r{tjIo;RfOg}(a zLtPe5P+s<$(e8 zC${c3w-0MkLqEpttynTJd#Fr5JK!m`zc_=LV zUCnaNO1kFGHb!sXzBarZWQ^F59NuvHVe_l3?sj9t3TiT?Zr@A!gOe(T!>gekU$`~h zbb)7DgtHYj>@|z)z0s}liw=j4A0u1o1=)Wysm!!A0heAM2cR6t&3!kY2Zt;D;ZpPw zEq2%OrL}G~)zif!lB&N}@Ua9Psz9?`yROr!46)e!AS{$SoQn-N74#WHb!ys@-t@s=O|FD!ay`u~MR&%nUM{9pJyBLNdTBkO;= z|B0e!W?^Fdza;wq4-~ymk_Y>e4f<$^@vc{ia)(DKz74f*{ z`lw34UxGa+ycLTPCTbN z3?4`V5EZa{cpfqy{Fr3GxrlJHy*LJ5$gug~owx}A5ix8+QYv6jKLCszsmViJ1R}>( zV?rDH)Ug@JKdC=HfRch@VbUKE1S%FhJD!#tru#__&?lM+&7b_Mk+_S;_tQI`ovsmr zKo%_pU@Q@W8tfXLAb#eE+m3ky<0KYj$Pf3*?~C3IW#ji(M4eE9cJm$9JBS>9JX7!nG;7i`aAXH3sj3I-@bsEA%1xf=cAR2~2U1m-7g z_5cg&CRD)F1MtDGGrGYYCEL4w(vMBz=AJs=%JA(rh+uns@lyx>1XRrM&i}wpl)w+u z_=lB%A>3~^fP1&Ml)%PueCh1rn8|PVP;UkrgB>kkpdEnm0SW*nEa-hP2oNIUD1aZr zp9p^kp8q4EGbMFE|NaQ2Zx9iBkqUBUr`7QAaUYf{>I`*eDT&=F5U1Lvb+_4X1w-?V6%W?+=ff8?(|W>@*;9^TgaX zHkiejjIM7#x6ZX)?Uum=LETQM}!1+(_3ls?HGkn%F7CS1V?a&JP3&kDv$xdfNN9pI$;L;%Hq zMclwUl8)B*3k}_HR6EZb#%d~N_9I?){EbR8zD8EbCSwJILUm;x)U{mo$6>9-AG3+g z$1go+-J02HRFVUd1NZk-F>@!e$t*5WzH3ZlJ09(|BI2X$jlp!vk?{62Ovu~Krt0cF zoU5Qy8J(b+*YDsy#!ItYsa#fR!dB--=AHq6Z$pLvm+Xs52 zty*h53}+lbFp9zOmI8iHL~dGX91l{vU1zfMja1&z)OJ^_5T(z1F1FZ0Zf9;=CHYPH zmZpqZN9nB4^t^ft=$(#SvM!L9_}L3t;3Z6}OIYnqbRL$;DL;M|GnzH7rs<{r$hEzd zs*W;~F_uNP_4?b6m4!v$Mzo(WSm)TF@yP%zu(0Jq(?F<((_;7Xa8u9txJ?4i){1F> z2|^^0!>FPnx$0;>`!_(|;V$;{CQ4luE@{F(&V2xMg*vY4wt2y3B$Ss&Fn0z5HHLT5 zd9S|_oqm|TEo!AR>vnaBJNUGq6@TbjNvk=AX^dst-uyA!`R>x>NSmRl8ort5;F&(w zEGy{uvcLAQtXsN#C)TgEzO=bD=RivmmM=tQg90C&Ud_Lw^)x4K394qHe8rd5v2qfWI3lk%GoN8sCn`wzEK*}n_fM12 zTo)f?BGY~oHQ3e!Jy^8^D-VQi=A#^DE*;fCB$7hf&MF1tcXI_0Py-F6aF_vN1S51! z49e@&0SX(Tuyhdip;Zi%4asJV^m#>eUVNG{PA!`8oTf@eH`r^f7>zzpMk0eO3)<*E zT1=3dA4h_LF@##%R29~KWT+eAW==dd8_>$Fm`@+f8>qMKwEpltJ-`8RM_3qdoL9EC zQUh9|?a4g)Z>La5h#IIy@rAowj3L@sc#_Y$d}%pZ+fw%Ya(0* z%nGV(*pn=Rdb;-2Le-V&cubEzNvgVW*0wbI=%!fTg6!{oQUQw=dyoATg=@$2i|PWY zbmQSaIct?pPW@blE3o8E`?AO}VyvTJq0>3SoN7b#j&=Ax9&0N|KYfe-uu_nATeNI+ zT2NatGv%1ljRy?R7XV@s_;ZQ5P89^>2rnsZ+D_9g+l#UZsGcRqxmE;0q zxht&~}uzQ> z8k$RB!ucS*xW@+xV_lhS6o0SwN^_~D-sYYky1L4^pzWNw$YQrfdD#-F4#8OBgFOW} z#?F`|ViQ_L6qcEKFxCU4ERhM0py3PgJ%OxCTKRW@BRe51mtP?4JuWJ)T7C z4VN2QJ=IcZ2TCli?nK7A;JpB7e0^EPP2_pnrxFFoWeZovSoBg-k8lhy!@D09G!m+tV1*;ZD_6!8|#NGuNhGdPW7*lpW%1# zj2;Ia;E@d_;tsvqVu*5W>IEwCJUgu{-PvgUTrhp596Ai*siw#1>AQij?=r25OZ0)f zoz56nr_BxpF3DD6KT@VgUA%B$&QE55iM*%&ohJEqbqh4n4&4uC&gbW30Y2jc_f%d2 zN-kI&PVQDoP1LTTTy0eLdVO+}EVh2vX@Qw06>V@fS!5G0YPqA zPT!M1Et)E)XNDuZNkdD%pbEMfwKoxQT2t6!1HQ9}6E{N@@$9S5plU4&?>;_B^f`D7 zrfb)|SO`QC2dV>-O0&3ekBg1|Bie7_nW7uoMs|~1hbAiZ&fkW2RVId$q<5JNlo81)2Zdp1JGJ6jh+(+4LIz^hnnwS?wT155VW_)XHP;=*S&+Fg_#x7@aF=?_? z!S|vceLhODTP=no{@QboD2Bfrosw@AODZGv>IQQhEPrDFu+Vr#D~Cf`nyk))bX#;Plu=!p#_KT;W0sBwI2L^d@KU(h zndK$RwSlb5b=tL(g0m+G`geWFaS1K*yq2jk^2@OdsZsw_)WY}vq78p?-UH{Z3(`RE@Fr&U(VOwV_`iVw)-jA;4OPHOO$$H$JnU6rCcJ^JN~C^x6b z*69|bKA9zog=-H+uEABR--sDgVnP&3lYuO>f8zGPl0`Ib21ampye%rBM(-Tt3CW#RR)tP9dpga*)gWWv*6jr8(`|Xht2S%kf7x-_M2GS? zfAf8ZuzXCOh_xbiin_2h@~S7LdYNksC@tLaCQ*vTv&S9^mQjzi4lwU016|zu-Z6lO zj(1u|HMBJn9@`>e)w&cp`3Nd=6Z2s}b@O=)*O+WaB$; zl5O#peH`3Y4Nu?|69ALRBoKZ6{5Wo2!h5MLHNT@99j(PFWQd?%wv1Bsh+}Phl~dNl zlB8Ic4EHc$PN+|&l(l&B82x2xA->3D-a=zf@atabQ*+Tlis{7gx{=8}LkTvKkpG2F zX&A4$nWfYw$@zX!j?=j3vt<=>79_$WBfEnPB*i0_<%Nd5c`HX67xl}W$(Mgn((4d8 z1%pjMUql%epKvGRqSn8eV&n(B;KBQ*{nI;+NW<7|M5~>V3apJ%ou2e?j(BYNBD}^L z4obEqO>VzQ3!fY#pQKeM7ADgg^)J7cva!@GrO(UOdL0-wf~>&WMLuB?tLUQ)omMdA)m=w_mXk1I!Sd_O1JjCkgYeej}Yn z7y0D*Xh_1HmlS<<`TzWnGfbYMleCG(f1`SOj`xi zH3yMq>}v8yb6TrARfGDbgj(+(oevK%Nf9cAm;K|w4Dbs{!4y~)Y%|8z8va{k-@aW2 zw@Q<0R@XIi$l)$5Lq@9)c+Rg?-2Y80V*FpUB1U?8hX1NVj0EhgEdQ_jpIQ+I8w>0I zw^ropqQ11b!Ac-59u_<_x4peUqO$-)-zP5wLlTqk?B*uP2DGpM0U-_{F777fbGUPA zy>;4MdzOPcY{g?`PO;3aK|)PnN}v%AoSc#rBLo3({NyhPxMhuF-rTG>LqLE6 z;}8!fC?E(ROY16&=Sm9)2M6%ab0t_0&tj6E5!+Y=J$KOt3XTr%AC;FE1|AaytPjW< z1~kR5st?ZmvU`t;Lrn-E+tYiDRvY`f+!2tiqyGm041-JjaPx7O8_ zlHUu#f4{ElCl1RTzV-3z7vn6jPjy8eAc%1c=*sf9R}++c4$hi(U*7~A$o`84sBP_+1V0?w?_|V3A)sqLkp2Awp#RJazZ^3h02$0ZP!~I(zWNOwKsrM105#!^d9T^fC^Ynk))U(SaJ>{SkuN~!5-}1$y%Zmj06^yyUw9sHAMIy2 zJK&XLTsU+e?QeKH;1yIH#7ON^xc*fg9%8i4J7WKu%72Py{67FjYF@(hyfI=Rhl}3A z+yJgMVjxDVzQXjbIsYkqgy~;a|FifN9w}G@=vN?HyPm!tGRUB8YzF8lE<5b94Fk#% ztaFW*6)_d=s`48da>Vc@Tp!Pr-$@IdD?jSF2xUc!$t)cMqy<>xXMgfLZtJ~{>OKxA zwfdbe99`4^t|16_*$?UPou;Afw+Lj7!?^7Ycz_%qIv|J9b*>lV&G#}#JHXYiz0a}D z+d1Ia6w>vRc*KrnX!#u;JUwFBNH~4x;-6UcZ2=_p)Bw+2zpmlMsTqXxQ|~|C=f|&J z%Ie3zmTmp(UoXpTIt5O(e)Br*yEOP=`U}Bf02Zg*Rj&?LA9EMyk1cw=XKDB11+V^{ zfJ9c!7C%~Sz(DBd?%+58<>IY8$c_^*LlEXClN$EOx8OIMf}I*jJoa8UeIG}$tH(%x z6nE}0zSCHiu6Jph~%f`w#|99eR0K5aRInN4Jyq1mTqL6BIjh6CYtk?v<|= zkGgymA7SL;J^jzrGwj&A-GpDA8VkW1VCC`o+br?D*X~aU$L~m{yjeJnIJz}p%g>@P zCPb$d9vF@_PCeDY{pag0UD0o6F9``Do^Ewly&Gt2BD;ryE0DG}?{6cMn@ea6=Ev$M zq!-9f6it8qDKy9fKt|E@H2+jckhNvdMr|dDZhMn$G_TIjJR(-nD*6C)N!Ijzqi;wy zDckuU3rht7=IrX1ny2ld=vU~{pehFV!P;p5l0Wa($se-r*@~iHQt-{Y6ne}^z6~~;mQB@l}dX8#w3qjtcgIZ z78Sn(;w~@^#SXZziaRVT&f)b6K^&CzDD~}1V6b_Qk}(^jY=IeEKaq@R1x`M+A#ZYa zCzY~Ye=rBfz>B# zl8MzRagc{Ax#cYn?EF8JeN&L8QIKUX{z%zN^jw4WV4Y`6$NY?X5U(agvAy6I|*)OIk*L)l-@wSS=S_q}j( zcr2{D&+_I5Hkv!Qhls&q94G$%-yBDk6ITlK>t3%ao3Ozkw{Ca;03_ckGL`9d zBrLxzz2=@;kJJ#z+!(3PwD(W`j>WfA7ZX|0WjJqcY=jhQcbRcNwIvm(6nsqBwO%<$ z&AW|Hus{NfOMCwr_tN*{X4w1te4mA8prhubJvE(Yq;KwVE5s@>QD=-E&tb~Sxz=s; z>~z1rEoX@|Q>a5h?vP=ztW(P^wlHzm8jpbsjU|xM0v0>CAA>k%u0$b8otGA|nf!y= zm&22YQSjqldZ5Fdf2P5v{vV>S7lWm8N2|epn^Pa61^i0ozEp>LO}%nb=X%d^D zvctQ4j(cKV0ckDVZFcjncBSZH_lq-9ZwE~Zc%_?N%PICqOr(4Kauyrw(Lva#=zUgR zqIu@hSfNzL16vKQg~Z6)wa^P}s-MePTQ zmaruC50?>giGK=#u3Ex=eY{OHOA96gN)SL9s1_%2JSrt^-I0$EttM(<#NO@Ao54+x z{*+lf@203nM_aY7haQv~Zf^+U$d9crnspIC5Y*Fvz0h%SkS8*HqD$(^tPA8Ny5?2E zr?m?BmGAQ9lbw>aDgswE2~gCpy1kd~h;th@yQayg;=O@MBCyr5y1>-cBq>x-EqEA* zb5(3s`NSHI+mFoLBgFYrr}&Igf1E+BEgdfVVjz1&2JRqrc(!%Sy7@xvwMfFzgEd$# zV43VPIQoX4=>>(*>PT)0bVOaJ{`7DH?%KaNEw`b5ab8bXz1O*YizjjB%}Tm-1$2{n3`_&i`1 z($Vph!kzQS@^+XGhxo=_(L{|{TCKNy)ATF(C*3G|_`2hI5)u6oV7aguTv;!yPT%T) zIUe%R@W=r;f38n9Czv-bhitqsXfc+{f@^g}hkSn1NE?nupItVKyH6PVdB)^9TAm$R zkG*40is$35B4hX?fC)_>kW>CoN9e|IhKWIwEsIUw0g5?1v6K%m4UvFkdgDO}f5k{( zNHK`tf*0)G3vb6*P{_jyMK2t&H>=Jvv4SAJUs-a z<#g&*`gj>UsqZcFN_$#@bKv5s?S?a-JZlj{@; z*jm2-NwaH}{asfbwn+98yjJHIPr@&AED9<{x0sXAp2j_o{D4%5-xh+-*3!8@gH{!x z-t>sCes%W(P92-Yljh_hIZ6PvLXM`@Hi9umXh|5#4r>obiFkdV0WLp@sybwGkCztm zF~>DANNgm6=7xtZ8{N(=BeK^y&{&fta6aaNUj-x4esM`QOW#1HlJn7EN9Kusizf@M zPVCUSys{7tiTiD*f#_QZZK6H#VP-?kHwa z=N~qLb-+#jU;@@!UbR zC)0e+pnt~m{rq!>Mr&Wh-U_ySUCS2vFEYv)*kLsAec&Pz>iW}#wPiBb$C{2$Cm@V& zx#5nsvrHLBC$Tz`;DoPYQwK3GM1(z)5rV|-;7I6c_u0eUD_DI=oL)Sh zeWePPS_MC*veaPy=O;y49@`eZ%>nO-Y+qKmd%=%nXfaQu^z?BbwaY(Mi`pAY#XX_+ zLitCQaXb|<@4q#x7WP557`Fe_mXs21)g6L0qEHjU3q>~T{H;7NX#@6@o=m}x4m~`9 zxS|1R9L#?W_)s*soBSIK?NEabQGg)<_cZ6wFwqW|PinKUZi4s+JHrliqVjb!K8a9< zjR!Il74b0N7#tss{ot1+7M}m6e8>*QI_u~xA8f=#GlYMc7+!QT78TTn%Y#0RL#D=- z<_t)CGX@0F2-Th(BUTl+T|Sd+nSzlVg|eUce$SRMpixiy)(EM^jUbJ0J{P?fh0C+<>p#l$=yUKtghgGzLs} zn_@HH$m_;HJC3nZ)VZ}iHOGRM(wS8A{BANF8P2$Xvvz^JkjMt^_3hJ;%Uoh4cS8K4 z*)?szPOW@Kx7N&8PhbJdS-+t63`aOk7e6!NH9P(f5z5;g*Dbgo@3u{}YgAfD71uK6 z3i{*=%_DmSwiK0md>6Nn3S+}Og7osQ!qTk*1&C&JcJaG!Vtf(}qBz>L3NLp>#BhWm zltt5D#OCG2-kdEXe)dGCK?5fRx3l2&bWEmnxpg-AyS%%(j77mMwJFf5$$*+Q(0mY4 zcNMwZUhlCiVP3o0WR4a-xlJ}^l7SmUJI4W#+U_7ZSGBzy)5x*y>upCw#APbFFqGFp zk!qHh z^8G;rLVI7edgRi)s$*?WF(Nz{4-j@JFS+Xr#y4Kl)e0ssL(!ly@}<9b!aawz*sEoo zcPJsqHXbNWyC&#Eds5=1)!(|ht{8}+5S&LHu-4&qY4+n@ZT`K2$G)j{ldG6; z-5(5KlO@Hek|rtThK1|KAucZACaoUm^t9qW+cw4|lrl8Ut89Bn+=CUd>FMXIY%4c% z&`f=_7w)q6dV={&`do?w5FXkz`*p6&W^9ettZBXMv9!BUA$Lc&AMlgYxn`^f8}w+f zQ32&{87@U{guYbT=1=)ep=>STr1;nZJXlKT%*#b}`_3}a{;x&%hCS4?wYv`;HZrqU zzf4OrNgo2_hX^?9@F-b&*A-P%UCdX68e(O+sjDsM$^%IKL@6GJ1mT6x;$t|4Y2{oWZ{^!Jw}I3hWZ9)G4^hRj3jTfTD0EN_AY?SP|ucGCx_5;pz! z-G;N7n8(dPl{5AiyOEBwt*CYLOwdx=6ip&=Xmm zPfpwVx>Wg3H&^>Qeg^kUcb;fnjAzAk^lG=8 z@^Tq74-uqj5mGlYe2*U2hxN$^NRkM!C8!dQ;O3zHzRQ?0q2_j9sV~4Bu16nU=r-!e zW8)3}+jS9v0&q8^u&-*d+C;N*B6DM~0nvRK%F0r-7}+WZaB54X&t9v&#TmMDkS>G#y|DjvUV(3IB`RG z@1-oBLAq2sDn%cu^6ug?7Ro@5o*wj!8JDZ4igF0fJ-&T=nw)BGm+x*+pcP24z|P=% zlgHoRS|56%V{C^Bd{nykyBC~#4obb*m(G`!be7h$6SjCOw(5)e1QVAQ*?5;Cf0;lo zh%rLkiHUiNqLn8qWzEbXKgS{5OS3aLOC(lN78pj&u6sQ=NM3V)0D-GK88E%EN!YE~ z0Pse4w{pGb$TuF-HxkYt;=0@**kHUCbY2H3amF)B&9zg26DwNn^A302T2>KrB^`zv zCKgps&(eiiSvsAim_B_ZZCxZSE-%$AL&l)cHbjWu$2Mtwz;<4W zq;&CV1#Mzx;SDlWpch`3>lZxn2a(h!+)#p`nNLhHd8EbnbF4RSfA85P- z`qrQOmY8B3V66g|Pmx2Th}`6V)p_)Xz>!TM9Yh z@7diKth1kd#|Z$=KL91l#{BZIKI1T2-KU!f2bWBM47Sm@18(U4Bcde3ys~mL4^BPH73(Ckqfp?rnppq<$~OHGP8bl#6hpYsOo?dQyV@)w$ms$zzs zNBb;>&vOjn9Cjm71Fx*Si^N-rqRgPRq<2S33?&N>bQ9?8Y2lspvmQZM+ZS4uSxV^s z!+EL1l054Yp6YL$(d<3+hkNH~wQ+D6BIKl#>048L)=C{wVjxatFS)-!x>AXIjH;mt zA?ylsb>R*OKQ;0nTVr^;wW2e`@Oq@<6A{ktNGW(V!Aj%FhiD7-Q1{=C{wY1GlVsZB zIhG+#?nnjWM>PzDm|2BOX2Yy+8E!ySRa>9%b)MnX%_+1LO?SP0PnKOgf-*k9`;g>k z%Pm+c-`8_S?puc)sya2&f@9x2o8f%u{5#G`x4_-jLK}jbb!aB*-n~NK!h0^iza-DO zV@Xpzy}xuo;TMhV;SYh5P7odaN-`bNEQY~5kQew_zr5bb_+Q{1oP^ku!OdSVWtqMB zvC~{qN`4z#b=b7uf=@B_oqk1ITg2L$-eRE|opuKldJJi;{E*~$UrcHnImmvJK11&h zd2LBg`bKQCf53x6`#hfxpZ_%6t=&~w$e~b@#r`m@1uMOL-T*5jeM60rM4E#+y=~j` zR+yrOKP}_pLfFBQV2+EhBh@nRKE;&_z?fLLuPc}mtg5KDW(Gh`q$@f(9U^d$E44HR z(OB7eYr)Rt|w}85IwC*dE-GD;7vkDKZ4tII8wHxA#(}h+q=GsA6>^C6)bO8Rs1Q z_IEBrJ{9v_8E#)8z8z0C^rQeP(3+Zm&{K!vSGxnfGV2D2@hW4vcSfy%HoIres1N*o~01Jd5@?7jeR(NbLQVUyBhs2vXe8E^Hm`OB3rgwoWB9ARl^Q-YhNup)y~0h5RsF(M=H zx~vwD8xIXefRup$A7;UVa*E6IEA)0$U4}w?4tY1scP1y0G}QCn77SXuq+ACyOsc<- z85A@}*vN^QAL&gMOhkI!%36>&r?MXTPQj0?`Y;UIH+ITe^}{|%t)iV`r_J8!;4>+H zV5)#9giW2;ZK2uXN&|P4DTSr0W8+(-Tz_ z_?kOP!My*R*Xm|EF*em|XIE30F;f(FKq3JW2*}kzJOj5X7ud9;+|uJ+uW)#>c?MX8 z!IqaYh1#hY$F?m|4xiO{w-V<@qH$dhBNz^KupQ2pCNvH8F6gw3yTD-@og?mK%vi{v zWl^nyn81t0dB<7S4`%cTYS4Mi(d%aiBAAAGeXuSh(w!<+H;=zaZhd6*6cE0rb25&b zR$Vnf#y?l`>dj&6-!w006=t`m#Sv>Z=JS4=^3!Hh341T{7JI7LiU#iwy%a}wAO$f# zRvgfj5d$JuflWUdpaTOG~W3f*U+uQq_r6mP0JMS^Q6?7 zDSfrlSQDOB_I^FmQL;&q`<-rRc6Rq2`KUd?K6$tcUa?}ju~b~YENv=ub*3s%d|T}* zWUU`LETgP6ADxmM4!pdI-^3V93qPWe9&|*If8#T7Ijy%vd5Q_l=1I-Msil>&fLlgZ z`NVzKVB(N>bCv}3rI-h+n!0k729Z$nTO@=xI#!so3$B_eArzDw!P8V}P#|wLshact zfm3%Co8h$0iqelN7-`J2tw<2)9hr@f;W!XBt6nzCLK=TIQko{>Q zZL(O?;9=GwN9<+Qkx;OtXQuRLl_eslMezy7LDvd zA1uvUJCh)s)@Fx|j5j+#dT_4@rCg->8*P-AI5N~ux!!NJGQL>wbR!?>1KeVlOq)e7 zInnkLjGc>Co5%%TFg3-fe>$-BfyHmbVV70pLrQy*(x_sd=){it%jL44Aeku0Oj3=q z{`s(_L{#1j5r&j5eVo0HU5@}L(5%W;yKBmYV$KGW{-cE7+dTKB!v}TY2LnyzB^KEy zE<7#%i0>~)Mre0tKzu7HVOn;9*N?u7{>~n3{qty**nCX!J>?n)7dvt=fnCxXY!9{@ z{{U-fE0vL&Hqf#?oFnz81Y^m(RLr{PnVjXQU+A5ZW>wL4;C58w+F>w#(x;9M_f?3# zmE1KQ;piB!wigeoc=F7mA28K5O2eFRaY1JDn50kpu|8C>OlvoESRoX zQR0=UYm6k9P0u%0iM<(#-MPdi<`8=;Q(vRj~VFha1qlC zmif|(VGTVd0({lQ;BAXj?vyeoZ}GksIjGvBH^fNtf-abRX%YL}MYrh9pacZe$rr`q@*#%n^ZQtUgz=ti9rw)FbTt^^&u<7{4cBtatS4wvtU6KwQGu^K$cY zc5ZgcA$Sa%J}}O;HbzjpqDJN35QS2WgGQDH3`eC@)bMEeHVAVZ$8Ay(qoNw;65yeN zuw9UFj~1dYt(bGqG!2iN_jK^HDTNPVYCaK$hGfNT)ez2FM0D?my$LURMy_8W?=qms zK*FQ5y-l(*cP`>$VJY*P5y_vE42av$ifZ?4&4QoV9i`+Y%HSgey#BnZyWCEy^2|*W-;vo3I)5;5sOzM^DTE7j7V=*9dmz9cO3EOS%LJu4Puc~rT>e(g)ygw zmq&cbmm+R$X}HGTipemM(Q2hzW>w;ccu$d0LVL}kqqS3st*UG7Ias<|trME%n&k!mW(p-87hq}5I zjP`o=sBUKO_jL<)BGeT!z1(1GR;o|BwK4@FxW5s2VqBpT&vfgS4Y#cHBXHsdUS~>i{qLMIs~Q6A`^?w4B^- zRm5u;!jk&4SFtBK@YVP!^vFT{!Cn*%88T)CBkm~- zL4!Q?*(TM8n-5ii-fPd8JP~@eXqJ3UDpIK5j6gr>!KODuM;hFBP5C6$MIxOUiyn-x z8@9!`d=Dlo2ETt{za3f2Lq^kPI>skDYPBYuTd>_3^^(*}MS+u7`4ljbH9Lvew$}&8 zf+^{S*}s5Y2yxSOlQ{wMkuUDQ6W$hAuQDK0^ zi=-AgDJ+z@WPqwft=BV9dMO1B1VdB*9V6mGA4QC>9ER`^RR)7bJ2 zW?S?hxX>%YcWgUW*9;joMkN?&Cqn^M&3RE@v_`)alST1!n~6tH%)80^*QO4RJBXZm z^Utotm7KU+2NUNqxsLoEeu_b8o)WsfKQUCX@Y_YQB~(h(bo{Y<^Lbu-Zum(!W2{Gp z<1vvT{q6x8#o?-x;#Wmi_#W5~q5~zyQf(Q;Z0T{9VClKB@&a?R_=WHGt{lao*DUr- zPP&KmIyX`El_G>3$GTg_LFzXm)?sMrh?q-S!1_idHiit{UFMmz?4L)bbSZCY+PL_% z*AQw!epSpk1Mydf{5Q_718B9w7WIQbP5%3rh@r*ZOa!Z5>9dgRDZ7-9&7q9RMHN+* z_i739We{%L^8`8L#7|LCUZIGA=ii=BsUj3l7K1KqkYBI(M!KPO3nWJMmppC)O#;}# zcDAH?X$lL?#|hG(7`OY#UK294(4v& z9YXGT1MVyiSrp9e=8UquW@BQFI|kOdf%TzgY(X(LHqWekL+oCdj+w|q16BgwgaN;F zt4B_Iok>P>V&QRY-$b`mk8A9RK6@l`X;l->BE4=&MVAx#i-T=P!If6PU0~(cxSpc0 zWJaFOFlJ-ZCbG8p9`aDwKppR?M(9{{k21Uziim)gSt-Z;=Zfn|dBfv|u*_9_-9tk9 zbLVZp=^~K|)m_<@e)M2evEcxignYd-uG5K63vNCDf(Vbv6Oc}n1YOp-c;JG(^ zT>%^Tpz!NcUd=$B)Y>Cg=nW_|@ydL?Jw`m&es0fq`%rBASB%X>Sy;LV&~U*RUc#`xZfaFfUMH;`S8 z_PIm6f}b*YVk4BTg@_W<65MJXo`yNA!g<7GGY(^U`_?*(^6WH)2G}2I891cjlkJmt zW08w9aR2z^GN+w@9H#KkhEAl9CB`)}dh}SM9ENB1&77?G1Xr$$DHePMwhFWG>ud(O z>ooJKi}6r%Dz`>1{;&D;2+*?4PN4Xf$bDyGVOrM9O-_!6&Y%Gmn& zwVv44nIvReeH+2eb=Cf>o@Ccsaty6KY`UxwB+^PFU;$X-JX^U zI>vn|S9i_4k?qgK@=w`<4)Ppl+YE~4kHRhz4cIJ>+;g8g$0eQ#rdocOFT}q#Q=;*z zKXiuGd6|w<6WNUDo#nD0)2QZZWz_e~9-L2F&@CJc%2Lh2{{&4Ywo{YVBsP!nXGdRl zqO^x+p-ZsDvT;1rj`Cx4QbgXw&o(zF={6!(lgi3IIeS5l7bwSoZcn-x2aDVxUXLq< z?K95{v$`M`VuJ>_8E3WmBETPEvgdJJ1#z~2vCP+W~>`)V&=w;8qN&1<9fy1#2q_)RVH-_6{8a6H}I-1iUSv-f6 zRG1np-J6V_vqcgdpeP()9#+U7vpy|(0rcZIke|l$Sj0vc)V&`TiVwYj7^=FBsS?Iq zBfmEs?uMR5O*sx+Eq;536uf^^*Zfo#;L}f#R^V^VCw02_FasG9;4sqk-^QLSc#HP2 zdjmDeYvDW3*->CpxJ048ez{EA5yh`pswmD|8FEf{|Gi05>n16&@3$neFT~{9LV9uo zBZrz-J|RsT36#8i1tOWmsnky`@SyWxVJ$el|NSvwrEl@yVbWOs8%!EIE7Sjlq_HzG z|DTWlj7Vc-VrBiGBGQypU?5gpq{rnXT_$I#=UJDS>l7&@YA7fb7*?3~6jfa4BxPvE zr)HfbXe62y8CVwBS?1aQ0psMwX+R#T{G)&9=^ybZ_tRqnt}k3Ol@&dQ%6@_ONaVE zO63XqUJ_=^vlfOj^Z>pk1$+2A0XK0=I)*F#6H+wt(vuVl^}aXCas&|KGJZ>4C{KnT zLg+XU9|^L2J>R+;@#4QH+fPVOON~ze)EF6=lq6`Vq^gdX6c|4}N}!fQp)&Ye)hLQp zfACh;rlslqTq=~8*Ho;GPt_X&jU+ab0tF5%d?hX&NZT`jkhaUy!i!H$QA3u~_=6LU zvFi5_2IFfhCg5P*B4VX5^eC$_Vpo9zy&j?(v;k0XFpI^xX94@_uCr$ zgrSCJ)_+T1Eu@g9qow*8ip=2wG6*puH~E{3o3)vUHRJN6`OEk+wMvH8%h%dInQqm` zGxhp=&?g6(D9$xKwM<7(K4*WBZxX0jpd>h<8L_zd%eKn8)4f_$^Kv`R36&B2lw~LD zgt0fc|M|?Q6utvm?)%G|fmel&RF4YS_5L(78hA?%Ht|3%+$dZr2iN;jy8IP?|L8KC z`n9e0#WV5HELbzpVD~d}u~^Cz_w?FpdI`6@?4j;R**Ka%PhR0EdI4c}?$Iwpb1LPp zXJl8VBVWn%)J3$);a7vrg!ZpAt)~f!EQ+uZ1wX8r}r#`Z`U{v-p*Il9Q1m+~~Ivt}de1$t zM_H0ByYSwrbFy(wF6teBYOXFqvdG`M$mDD&ErC0_Rkzh&?rP_}gRL>HCCte@C3tL; zRF{zmoQ5r(+s#|wkH|&T0aK&5Vk;A>a?;^!#zyy$4S(!q-|57n$S!HW^)A(3@Uq{< z{2Bpeif-cD?=$jYYMi5SkG|vH)7dsUulASMLeYg_+^TvDPbS@^?G`5=5GLa%9429W zVtL4s;4@tvirPTp8+}5(z~ZgR!`2G4uOs(e{1vaRBCi9xYPjkxicpE9(;Zi!w^2mN z@Kwv-Y3N>z zrmmh)GLKrbG(@cf!mnbyl9o@D^J?0Vbsb0;hpl{+j=P%W{@hnJdQKB|F0@=TnX4X8UAGAZ*wt3h{RGGY{CU-}cS>qLKEBGlpKqT~S*;xma=+PhJQa1wvTd|cigV+0-%Ku* zI<8UJ1=o00WzQo#BevDszFk-U#vNVXSIisf$dDN7SvedZ^?ucGm-XKN4ft{d%C}Aj z$-gQ}${oq1w3tmX{C<=OOV>-my)3yPXFT{}5wK8LG3nr0WajZ=O5pLz7k$%Z6Khka z8}%Obmm?a;P1yx~BIk4b(cyvIs+asu-zl}4gQEkOpKZKO(y&2gx$UWe~)SGzv#v1nD4A#z*E$F0@?X4oN0MJk`N$aet%ioKsp*f#ww zEEx~{(tY2ds~7@yz&vg`l8EQ!cVUbH(S5K8EH;usf?UoE@yXKY5PJKF$C zU#Q1eO6sSg^h6iv%$mfKa;5`ZbfzZhTouwtovaaB_nf_Mqil=@ix;3ktf+P+(td*H zWZ^1R)JI3Y7SvH_=u8F9#$crV4E1D6=x?CA$a5O?$em3_BO9nTLugC*8^wS&qfOMx z8@|y*4jSnRu0UlnQn3rWt25k%aua4knI`vfg z-3!)Ro^)fr>42x;k~Gad6f@c4)g5ht?j%l^fgNlY>s7Ttbk0S7PxBSIcik1|uvwE7 zQ&1l0p&_dcqYbSrk!?&Iv###P4!&Q9=9&5-|7y%lJ5E}4oqeC~*-HR&FFSp!T z>%R*D_Wv3J>Mca|QKMK8BQnO73Zs7)1R(4g&g0IHD&MepP z)xxGCfC zY%3f-3f)}pdIixmb@?Z6N&t=4RmH4EhJNtITQq{dxC;I`s3fduSFWU6aIJOyUklfh2l(k z(XgBcFkD!k%&Wtb81X-suL{XzC9u%SFawK(V1WiR?Pu6%IAJHGFMz|Jcyvx9WxX`& zr9bH~!|=rZW{U`CQwZjyf2lFDV0+vzmPO5q>dg$?ZHqe$Q;-|p<_``9zu#c?xX#(E zaYN#gb-SBg9g|@_gaBE+*(hK1p+@eA_MIdXvS`}SSxBo0hug`D1r&CJZ-YZxg1;1t zna4AJ?IKt7lHe=xWucfEY50X_x_*@Ak2d&1-&P$r5>B0pwR3K(Wej#EI$+BAK>;z} z(ilDXMulB2y#5H7^UUk_iJNP_a`wk=BWgU&o&6J3_vTIR*ZaxhSNUIqf|dP0FM=q0 z*qad0%NbfKIom+d%Mvg$FhJ3ZS~xm66L2!H|DV#EfSLJ!z5#NrrD3-zj^w*qyLSi! zX0VHn0E2LvEx{y#BS$v~-!QedF{Vf~&OHA80jyXr7MEl)8J(d6gHFE*8os%xsEsAl z8u^Ge8#$M@4_h!zocyn&|NWieKcDh5j8LCdz3f0ebzixkw&UwYI(#A)c{ZFl9)n99I9fv zt(B+XK;I@n1}$DIhS+|KD-#ULQZ;Tzb$rH4Hq{xVdJ^e1GELQyvP0QF8V+9S0(fG6 zY0JBM@WA-ka2eB__+QX;Ir2+~Or@an!Bd=N^M$L>b^84^t8I25D7PSx(Dz^<0vf0d zdvi8~LjCP&Wt4%*C%-Bol@jofPy(?Jvi3{}Kv4rk6P17CNgESV4`}!41T9013l#M? z#wQvFYJ@CpBvL30et>C$^et#SVO~I!cxIxD7bf(l5RF+1u?~cVLP7u_M-+uIicCRN zMJ}8C1N^rX7BMsgR)RX+z^~@5JEm@Srq_rUaMupj`LOnKImBU+F{!a5#bzc$867N^ z-kw)Myg2h>bkQfT7>wxgc_!8b?p-o)VeO+zxZYmc`(pMj81-KnZ5Vav^w&c1@auqv zjGgImks?k1W_4X0nDDQrdW}M{aDm~_4-ktmr|xWYv1bc+@C`x_R0;KNw}1FQGnnaK z^D}j&$;7nI8EBFh#EhDzIhVGj$bDu&#&x;+o%RYuT0}5mDI3LPg<)*u!3;#QVxW={ zjdqL3=vSAH-d&b|SKg>BqG?zM>4`CH-g#XgcRn9yQPbvaXUUpjTriAK8~~V2y8h_b z(#NLN1Fd<0Ec#xJ?-Go0LXX5R!N8Fl{Kz!|Q&IJhusi*Efm2O+oW=J33B(M?HYoY+ zC`Ip_`q9Q94Y2pWO?^&>>nv*RZy6*DOVQiY{+iBrF{;OkmAYKP58BW0VPn~0-}A+x zkc1c4fmvt-nr#-Fa}$bl_Ve$)@V0?^gEDp8`=L0l=H5+Dm`m&oQ! zaGGG}QNE_2=-5&OLqJi!sQuY=d-&^~Elgz9nK-^LQEQ9)pTHxqsM5!~KSk1#>F~}=%bmcn#Kq9uJi`&5=*?fUC7ippF=UM#uk><-| zC{Sg_=CAwM+@roSJ#Gs+C*Z2vS+L*fd6qh6%0g~Mid>q`P5M~#-lSCfBr{>uaXW^m zX}MGPsG#~d#*7BZGCV6gxh{Xm^eoa5?6Oc~~qxcQ!4c@u8f0S-1*jLTO9NEI^Uk0~PRxhftib&aen7p!41V zny}9FHwW5N=&6{QB_PKtJ&brSl@daij9@K+ItgTz3(r8T$F1iB|KZeG;^|X%Rj99^;X2kRV{N9)ZOmy)qcyv z!hqM&wSZ|cH%F~9rO)tt`TQY$d0xsYlUL_H_wWg<%{wTHsb@=e_DScNBeu4N1O0q# zIW4I{CC>XTadr*f?Q%Z$H5~2w0uxyeShFFl#w(ntlEnkr& zy+=7-)5h^4JR)^f44b%X$OQ(~`h7$FRRiSCogtuPr?3t*A9b(T zoDVLzX|l&C=q%xr)K=HF+$`15a6G7KNIgkch-jsxu&Q2*ivh=rR8~q4ULicnUD#Ju zHQbhO7aFyyxnl%)6#vyq70ZpvX?u)~#qg@j!fdo8bgCWh%aI2?yRce5HX_S4(R`hN zD0Mi+s`eepHW`ufBhOCTHdX0S*hN$Z-$fnvZHABq&uduF>h^uITN(B)$Z%K@5hHU7 zmWnZ_jb8Z-=@P}nG*+YJomxXcq*_dwXjOFFM`)-mvpU$Y73C_D49E;=gmQo4g>!8x zUo&+_as3I01L3rQ*8DLER~T6f7&@`AxqcgH-eH@uKF)X=zPRq2@bZ zJ^JKuc5=OIYWpun?%~X(n%#@9A8=CO{^q{b-w*kcwWP}L%dr`uaVrwKWor0iQR^uSFGIn zehutbv|gh-jquiEvFqV6rl+Sut^-hLVJ7&aZ=aR=_-5!%t`jqB>#eh9!^tu09`3j@P>=)*fy#JN5nQd)NP=C?T#+ z6@}wQ)X{AIV(;pH7XN(#epkZRt^o8TEu-L^0l%h;;FOiXOR9f4Wx(A)v@Zm1RD}45 zH~VK7+Dp#Us1}-6>)uyZeGfjK!sD;5aZ{X}4g>Zc(V$oFp_2=WM0}g=FIAlO>)SOs zRyX@f2Q1e&BDecnF+E2IIk|J;#quJLi{IL+E*`@L2ab)|XdO6tG3jR1?~e^R4Di){ z#ilv#68^DVYGCle~+>B_gTsrwN)B)vbs=R#KyTB8}m4@p!yldWkcD z2Tz7f*>?T)zhlqyQSGe>(H89syC_k5kRW%#^y#n{7lTMN7(WJxTzm zQ)5@O{ETx-;*e+#w2pIOjw?O%#I#&sS4;b7JzC`?p>+qH@_b2o#Xeq z=)1JnTjWm+3z;R~bMM^6vNc7=WWpLTYsE}of^{TY7hV!FJTnoU!PYI-ca;q;PIGOF z=yc0g8`Y~pbwZ1m{JgzM_}v28r_Y$XGMn%@G4fH}Sp5v` z_x$W9mraV!iWQf3I4)6tQZ1S%`FI7}Z{=GaJ6K8MPEZZrt? zv$_FXyI7z?pjZl)7%;(;=wELMpdzj!>MP7F8jyMt!BGhy3&BxW6*LJMTO7953FE1YhyX0py)K#+~Fz%FEeGHH>nSFN7Qh5E~txd$%Hb9$`G7E{CA zp2F5YPxgD+#B4fJISSVT`)UkZzcdNPd0m4U!P7#qu?TAbv1c-7`K4DMzQP2df|9-m ztgddRQR_5A)`9j6V-=LNzmiyki}wBe?YDq50AI7rnMpgXXfa}}NX}Q8blXL>DDmptGnEW3Qo|ZX*==E(XdNwCdf}2u4Qv|0 z@Bwlz)Ivtf7_BeK_QF>9VkG&V*{|bRUg8vRd6h0`bn0eMsQe-W7W@0EpiMqSK@%ez zNwlAz>ES&6c`%C3`>)Ly8|!~&aQuHXV;rpiw;5yPHg|M5TRqir^Im-Llol^8vX@?TMVUBt z?Gv~2Ust*nnEuP&$`E;P=t)s^5()Pi+7+OAI}Q9B3H$u|7% zN^wNW&OKx#gm#3VOu?||sQW@vIR?n_++-w=46=N?g<*_J_R0oRT0@}G%xcfgPU6Y$#K`M+^%JvzQ9(i1N%dT9xM?;Es;_rhv)J9+!Xk!S%#IUPosLQGdgQXHj)&9*#yQJ6#!MwFAiJSv0l&0BsG$Kh6;R_s|x{ zKCX@lSa6n11z8(^gHbJP!!+iDq8x23hdOHPZF!d+EVR1H@F3Ml zv1e5Lz9b#Ud=95RcVt6`6C9GgpP|_s)kl&w*J#n~cTdyot#N<8ZXdUOzAo+J^7Q=L z{n~xL7B4r`zzaQIUpGg4yY@N^n*BZpYkPqY_UA9xt=o^!_m8+H_-?&}CO2t*ULKu; z4L0N7!0YckpTicrB=#tF+HRkJ|6gEl9FT^=FoaokN44HjwZ5vOZhuC7Jl4hCYmz&% zRc(hny*tr;=%y?$&r#;ihNmljpP9@oA*T`JTAs@yKP_b^5=2go zCPkw;(!ut(xF#v|g`hsX*#vcxAf$z;et`+CTzw}Jm2?H^+Hw15ktD9v@3aY|&qQS! zXs-l4DygfKuSC*bk_Rb|i0(wahNCoLUrPFVHACrCjHGbJW73zZx>>ZB!uBDlD-DA@ z+AEQOh&=t>ZrW+mdF@OVH!db|+&_m57h)qCrhk}XuQ_9*5lXWQr&%l>GXSSeEb+oI z7K(@CTIGxymePeIEamq&Quq2Rq#M#nY_s(!)boZS!f9ml%RJE?O|9W{^NL{J@{jwd zrT0|7e)aTI{yV>9iL6-?UI4(8#8Ns5Yj!6ROe#iVDV>Zp*N779sv|g5BBoSbGHZOn z6v?KfAj7F@aFfe>B=rNXH|;WT;pNwRWc*Ia_eZCG-)r!KJ;Y&dqRT`=acR}PPrm_# z>mwZXZM80xtsQ8z`gb(z(31qsf83Q&{Z@4c%uC6MGRH{L;^dA3CMoq8u?`|d>#;I>7VE(~)kRFAgWbS`>d&0UoDk8TUU!LvRYqe(saPli1xbmLR=7j08eK5lNdFt}P(D0NxmDS;!5T1FBCtnOm`qDyWP->&F8 zkdoEvy;2E|{z=+X2eoiVP~gZ@(dt+W6?2C`h{Zi|uOhw95&G*IY1H8{9E(^rwX7lwJNfL4Ex~5BA+Uf3(~UVXSrM2!fZkH3ncjkXGAIAZWB}VkH*!JtF=i~A4`}}qPm#b|%jl5Qy=1`0L=YZT_-}kS! zUSLf-K=z`&t+qJ@Ut#gGbagcO)$sLDd#5er2>2YTPVAGJx&Yqio&5HGtoO?6w5w^< zZvw=8oZRJ)xQe9tTG;8?LTJlxe2Fgi?ui`M0sA20rg;exs8KWu2Y#nK3I;lx<5Q4Ar%i|7Y6 zg`of#0s#TRZQ~duTC7nJ(hMWM&4K^`aFq}z3Gsr!y~qqI@t@Sr5)Dy8VkIQ(pIMrO zrAtTW{~P^Hhm+{yB!ny>1PLKR;GS_|6k<5T2m(JCOT;t8{<+}AZiA1L z86+@Cybv85ON@ZPor&?sX|V*lk+>f}fMi;<9iBl18`)VR00auaATXvF00CG)0n{D< z*dxZd(g^_d#D zi<<@`VWuckv;_i#MnVxV%-^CcHW2&nLS_=dVy_Tz0+9)~BZiUj(GYNC44y%v6Y*f? zU+ciYkT8@40s&cDOWrFji~_=-|8aZjUk85(@gd%SF2o}M^S>{|n*zwc?%+zaREF4b zxC2!j9Xnz;jX;#tPG^Xt8wEP?;!?5e1ue5p86VfwEk|WL4YIaCq?BZA7e`T$(nU29 z$4M?FW%YmvJO8?9q?dQ{S@>k=fXLZBLHAJUkcnaJEB8KS{r*<-`KPM!+vx>+doN6G z4?3K1L3y9Ew7q=gd)L@pFh8Puh?Xg^)$?vravN9MUe%U2VB@|_jM2+>(I#|Pfh_IZ z3@u&2!R8jbav8f>o1P<^x!PV&m6b?7$A%J33m>sJWQWnThOlZR39Qjo{vZocH_1) zT*EPb-?at%G52q&OJAf2QW?2IWAcsupi4D%fz0cDK?Z*WK?9=N33oe7T7q{ZukPz< zK<^*?g3?cS=A3iF^T~xvLqZ;UiT) zMtrp+RNF`Psw=0n8k%L-;wyDb zQRB9B8*ZOQ>h(jaS(+XoJLEOB-UvrX6}Iq2CRrVTNe%O{j+gZPeGDfTPP&PTg_o4# zvqA*tr$6oj1jgfm`1bHveK@OUP(>Pk1|PRS}gin)}n0)`}Qel{*fv z(A`zoK(z+hgLGWuHf`R{M+<5S)Qou(Qncb|7T(c!L;q-RpgaL;UV0hoYeUDq1Ci$H zf~3L`2SFMi8r6U|#$b4e`ZwdyTc@8^8L2-Ds;ZGLb#C#pp`R@T_0DQR;gG(s$G)w+ zsh@P)k>&iM#`%NO0Z3aUW$e)t?#nMludOQqz%KrhAwKsU} zeCG)vCA{ShvUPc8>Ql@+W|U5b{`!Da=DDGE)ffX3&NuA)Z>%$D%?ZEu#uns8Xl+8! z_x_i!7I5U7A)oS-wym!%)f|60zDi#I%lD|^Rmi163^$%SeCh-it6lMnhaAywZdv#A za&6oC+i#JtSLvd`ocgcP>mAAFuU;`fhUi|na(CjSXpY(CM!Wx!`Ke(dJ8zEbygq-u zlxbeZ8hM?ZuUPK!pK{2*@BjIE5F9lp%00#Q7O0DouBo=k1$OJ$DECBjgpIC_Na{`uE6O$i ze+S#d+exH2xvOC#CIy?$ z;IwgI_^v!1KMSh%c=kMp$$^EfDER>atWWQv85j1DA_&pAd++GWT zjzGZ&0rFfg=gug>x<`_ii<7?VHz*1lm){nJ@_^NA!3kSNrL9u=XIwb}_~otuk!JC7 zyh{B69%tlYg136S)Tpdgj(2KMdK|aKg>q|_t>dTblhdIvn@&E&1AloJe1^i@CK!MvHX=Iw#!nnQiv#*2NQNwaS4W9ficQ z(?h-~Z22CYJ@_Z=G_1;E-Ls*KKLqNX27VHR*ZcQVHUb&^1tgpMr$FWD0k9~A{iL3a zF~M(6!v?43RsTSY;cxyx1f}G0ehAF)ygy9@PiYbpT>2`wP|}(@(;w?1sP1`{$=|HH zSl2yMKfgyY@vhQ1i?1Z41^)%qu$HlHN}*wk&jo%@(~)K4;$U0*=`=`LVxt$jO#DnZ zWvTzH_P(l5cFkpJ?6f)n-C3^je*f*${Ltw?y6?}51y+g*semkXd*S@Xgy(xhjWwSt z>0CeU9p)4jI=Bcb?sFAzja+2H_Y|^ON^E9vKssA~`M1bWQTLWboAKqhK&vKxb4%UN z$J+YDfq8a*ZKDhHkU-|uq?GhlOGG0-0)PL-F3kvM0CA3!LALcZ}>Ku4Q=B<9_O_vd3cQ7I;&K&r7iTaM;Gf31unHdWhJA+QOp->nObv`>YBSyArC@`J$yN|(4<-&K}eIqo| zOjG}gR&RcXJe)S7mpIV6*hiVcfJ^IL9Zw}KrO(abNbV2Lz32IcLLIH1Q*Y6IHV=DL zlmoLi=M7lA1?=e28Wz^nDh1#-1*er1#g%G(b0362>Vr%to20IdPYhJeEgHD6sm~@p z=L=MNHugK@HVcDqJj=nSeJaQ)O+>ka-2}?(lqqnTinCmIj~^(2JBL-o)yidBq&%C|-QXy)Rvu6Ue2d{hiN)gD7+N z)cvEz3aqyA?yWZ$w?%v?za+EH!T;JZTZ0MZk?wRKg%*u8@PSthI*d2{3UTJpry^C*2yFOrT3dp{ z?Xlh1Go;JIYbSMv#7AtA;6mU{tIUz&h2%NDxkowadEqbdF}MY!kR z^QK;ZcBCl0bJA>vpby<}Ka}IqS6rx9u&0JVR;_e{TyiRT2;p5pM0#dK9+LHB-Ye*= y8G+VBlgkbF-|J2OKBl*{e|BzT*}tbsIs+feI3b>tfDmYeg*h5zXlQ@L0rY@ literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/doc/pdf/user.tex b/krb5-1.21.3/doc/pdf/user.tex new file mode 100644 index 00000000..38d9d91b --- /dev/null +++ b/krb5-1.21.3/doc/pdf/user.tex @@ -0,0 +1,2456 @@ +%% Generated by Sphinx. +\def\sphinxdocclass{report} +\documentclass[letterpaper,10pt,english]{sphinxmanual} +\ifdefined\pdfpxdimen + \let\sphinxpxdimen\pdfpxdimen\else\newdimen\sphinxpxdimen +\fi \sphinxpxdimen=.75bp\relax +\ifdefined\pdfimageresolution + \pdfimageresolution= \numexpr \dimexpr1in\relax/\sphinxpxdimen\relax +\fi +%% let collapsible pdf bookmarks panel have high depth per default +\PassOptionsToPackage{bookmarksdepth=5}{hyperref} + +\PassOptionsToPackage{warn}{textcomp} +\usepackage[utf8]{inputenc} +\ifdefined\DeclareUnicodeCharacter +% support both utf8 and utf8x syntaxes + \ifdefined\DeclareUnicodeCharacterAsOptional + \def\sphinxDUC#1{\DeclareUnicodeCharacter{"#1}} + \else + \let\sphinxDUC\DeclareUnicodeCharacter + \fi + \sphinxDUC{00A0}{\nobreakspace} + \sphinxDUC{2500}{\sphinxunichar{2500}} + \sphinxDUC{2502}{\sphinxunichar{2502}} + \sphinxDUC{2514}{\sphinxunichar{2514}} + \sphinxDUC{251C}{\sphinxunichar{251C}} + \sphinxDUC{2572}{\textbackslash} +\fi +\usepackage{cmap} +\usepackage[T1]{fontenc} +\usepackage{amsmath,amssymb,amstext} +\usepackage{babel} + + + +\usepackage{tgtermes} +\usepackage{tgheros} +\renewcommand{\ttdefault}{txtt} + + + +\usepackage[Bjarne]{fncychap} +\usepackage{sphinx} + +\fvset{fontsize=auto} +\usepackage{geometry} + + +% Include hyperref last. +\usepackage{hyperref} +% Fix anchor placement for figures with captions. +\usepackage{hypcap}% it must be loaded after hyperref. +% Set up styles of URL: it should be placed after hyperref. +\urlstyle{same} + + +\usepackage{sphinxmessages} +\setcounter{tocdepth}{1} + + + +\title{Kerberos User Guide} +\date{ } +\release{1.21.3} +\author{MIT} +\newcommand{\sphinxlogo}{\vbox{}} +\renewcommand{\releasename}{Release} +\makeindex +\begin{document} + +\pagestyle{empty} +\sphinxmaketitle +\pagestyle{plain} +\sphinxtableofcontents +\pagestyle{normal} +\phantomsection\label{\detokenize{user/index::doc}} + + + +\chapter{Password management} +\label{\detokenize{user/pwd_mgmt:password-management}}\label{\detokenize{user/pwd_mgmt::doc}} +\sphinxAtStartPar +Your password is the only way Kerberos has of verifying your identity. +If someone finds out your password, that person can masquerade as +you—send email that comes from you, read, edit, or delete your files, +or log into other hosts as you—and no one will be able to tell the +difference. For this reason, it is important that you choose a good +password, and keep it secret. If you need to give access to your +account to someone else, you can do so through Kerberos (see +{\hyperref[\detokenize{user/pwd_mgmt:grant-access}]{\sphinxcrossref{\DUrole{std,std-ref}{Granting access to your account}}}}). You should never tell your password to anyone, +including your system administrator, for any reason. You should +change your password frequently, particularly any time you think +someone may have found out what it is. + + +\section{Changing your password} +\label{\detokenize{user/pwd_mgmt:changing-your-password}} +\sphinxAtStartPar +To change your Kerberos password, use the {\hyperref[\detokenize{user/user_commands/kpasswd:kpasswd-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kpasswd}}}} command. +It will ask you for your old password (to prevent someone else from +walking up to your computer when you’re not there and changing your +password), and then prompt you for the new one twice. (The reason you +have to type it twice is to make sure you have typed it correctly.) +For example, user \sphinxcode{\sphinxupquote{david}} would do the following: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kpasswd} +\PYG{n}{Password} \PYG{k}{for} \PYG{n}{david}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{\PYGZhy{}} \PYG{n}{Type} \PYG{n}{your} \PYG{n}{old} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Enter} \PYG{n}{new} \PYG{n}{password}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{\PYGZhy{}} \PYG{n}{Type} \PYG{n}{your} \PYG{n}{new} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Enter} \PYG{n}{it} \PYG{n}{again}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{\PYGZhy{}} \PYG{n}{Type} \PYG{n}{the} \PYG{n}{new} \PYG{n}{password} \PYG{n}{again}\PYG{o}{.} +\PYG{n}{Password} \PYG{n}{changed}\PYG{o}{.} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If \sphinxcode{\sphinxupquote{david}} typed the incorrect old password, he would get the +following message: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kpasswd} +\PYG{n}{Password} \PYG{k}{for} \PYG{n}{david}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{\PYGZhy{}} \PYG{n}{Type} \PYG{n}{the} \PYG{n}{incorrect} \PYG{n}{old} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{kpasswd}\PYG{p}{:} \PYG{n}{Password} \PYG{n}{incorrect} \PYG{k}{while} \PYG{n}{getting} \PYG{n}{initial} \PYG{n}{ticket} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If you make a mistake and don’t type the new password the same way +twice, kpasswd will ask you to try again: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kpasswd} +\PYG{n}{Password} \PYG{k}{for} \PYG{n}{david}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{\PYGZhy{}} \PYG{n}{Type} \PYG{n}{the} \PYG{n}{old} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Enter} \PYG{n}{new} \PYG{n}{password}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{\PYGZhy{}} \PYG{n}{Type} \PYG{n}{the} \PYG{n}{new} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{Enter} \PYG{n}{it} \PYG{n}{again}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{\PYGZhy{}} \PYG{n}{Type} \PYG{n}{a} \PYG{n}{different} \PYG{n}{new} \PYG{n}{password}\PYG{o}{.} +\PYG{n}{kpasswd}\PYG{p}{:} \PYG{n}{Password} \PYG{n}{mismatch} \PYG{k}{while} \PYG{n}{reading} \PYG{n}{password} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Once you change your password, it takes some time for the change to +propagate through the system. Depending on how your system is set up, +this might be anywhere from a few minutes to an hour or more. If you +need to get new Kerberos tickets shortly after changing your password, +try the new password. If the new password doesn’t work, try again +using the old one. + + +\section{Granting access to your account} +\label{\detokenize{user/pwd_mgmt:granting-access-to-your-account}}\label{\detokenize{user/pwd_mgmt:grant-access}} +\sphinxAtStartPar +If you need to give someone access to log into your account, you can +do so through Kerberos, without telling the person your password. +Simply create a file called {\hyperref[\detokenize{user/user_config/k5login:k5login-5}]{\sphinxcrossref{\DUrole{std,std-ref}{.k5login}}}} in your home directory. +This file should contain the Kerberos principal of each person to whom +you wish to give access. Each principal must be on a separate line. +Here is a sample .k5login file: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{jennifer}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{n}{david}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM} +\end{sphinxVerbatim} + +\sphinxAtStartPar +This file would allow the users \sphinxcode{\sphinxupquote{jennifer}} and \sphinxcode{\sphinxupquote{david}} to use your +user ID, provided that they had Kerberos tickets in their respective +realms. If you will be logging into other hosts across a network, you +will want to include your own Kerberos principal in your .k5login file +on each of these hosts. + +\sphinxAtStartPar +Using a .k5login file is much safer than giving out your password, +because: +\begin{itemize} +\item {} +\sphinxAtStartPar +You can take access away any time simply by removing the principal +from your .k5login file. + +\item {} +\sphinxAtStartPar +Although the user has full access to your account on one particular +host (or set of hosts if your .k5login file is shared, e.g., over +NFS), that user does not inherit your network privileges. + +\item {} +\sphinxAtStartPar +Kerberos keeps a log of who obtains tickets, so a system +administrator could find out, if necessary, who was capable of using +your user ID at a particular time. + +\end{itemize} + +\sphinxAtStartPar +One common application is to have a .k5login file in root’s home +directory, giving root access to that machine to the Kerberos +principals listed. This allows system administrators to allow users +to become root locally, or to log in remotely as root, without their +having to give out the root password, and without anyone having to +type the root password over the network. + + +\section{Password quality verification} +\label{\detokenize{user/pwd_mgmt:password-quality-verification}} +\sphinxAtStartPar +TODO + + +\chapter{Ticket management} +\label{\detokenize{user/tkt_mgmt:ticket-management}}\label{\detokenize{user/tkt_mgmt::doc}} +\sphinxAtStartPar +On many systems, Kerberos is built into the login program, and you get +tickets automatically when you log in. Other programs, such as ssh, +can forward copies of your tickets to a remote host. Most of these +programs also automatically destroy your tickets when they exit. +However, MIT recommends that you explicitly destroy your Kerberos +tickets when you are through with them, just to be sure. One way to +help ensure that this happens is to add the {\hyperref[\detokenize{user/user_commands/kdestroy:kdestroy-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kdestroy}}}} command +to your .logout file. Additionally, if you are going to be away from +your machine and are concerned about an intruder using your +permissions, it is safest to either destroy all copies of your +tickets, or use a screensaver that locks the screen. + + +\section{Kerberos ticket properties} +\label{\detokenize{user/tkt_mgmt:kerberos-ticket-properties}} +\sphinxAtStartPar +There are various properties that Kerberos tickets can have: + +\sphinxAtStartPar +If a ticket is \sphinxstylestrong{forwardable}, then the KDC can issue a new ticket +(with a different network address, if necessary) based on the +forwardable ticket. This allows for authentication forwarding without +requiring a password to be typed in again. For example, if a user +with a forwardable TGT logs into a remote system, the KDC could issue +a new TGT for that user with the network address of the remote system, +allowing authentication on that host to work as though the user were +logged in locally. + +\sphinxAtStartPar +When the KDC creates a new ticket based on a forwardable ticket, it +sets the \sphinxstylestrong{forwarded} flag on that new ticket. Any tickets that are +created based on a ticket with the forwarded flag set will also have +their forwarded flags set. + +\sphinxAtStartPar +A \sphinxstylestrong{proxiable} ticket is similar to a forwardable ticket in that it +allows a service to take on the identity of the client. Unlike a +forwardable ticket, however, a proxiable ticket is only issued for +specific services. In other words, a ticket\sphinxhyphen{}granting ticket cannot be +issued based on a ticket that is proxiable but not forwardable. + +\sphinxAtStartPar +A \sphinxstylestrong{proxy} ticket is one that was issued based on a proxiable ticket. + +\sphinxAtStartPar +A \sphinxstylestrong{postdated} ticket is issued with the invalid flag set. After the +starting time listed on the ticket, it can be presented to the KDC to +obtain valid tickets. + +\sphinxAtStartPar +Ticket\sphinxhyphen{}granting tickets with the \sphinxstylestrong{postdateable} flag set can be used +to obtain postdated service tickets. + +\sphinxAtStartPar +\sphinxstylestrong{Renewable} tickets can be used to obtain new session keys without +the user entering their password again. A renewable ticket has two +expiration times. The first is the time at which this particular +ticket expires. The second is the latest possible expiration time for +any ticket issued based on this renewable ticket. + +\sphinxAtStartPar +A ticket with the \sphinxstylestrong{initial flag} set was issued based on the +authentication protocol, and not on a ticket\sphinxhyphen{}granting ticket. +Application servers that wish to ensure that the user’s key has been +recently presented for verification could specify that this flag must +be set to accept the ticket. + +\sphinxAtStartPar +An \sphinxstylestrong{invalid} ticket must be rejected by application servers. +Postdated tickets are usually issued with this flag set, and must be +validated by the KDC before they can be used. + +\sphinxAtStartPar +A \sphinxstylestrong{preauthenticated} ticket is one that was only issued after the +client requesting the ticket had authenticated itself to the KDC. + +\sphinxAtStartPar +The \sphinxstylestrong{hardware authentication} flag is set on a ticket which required +the use of hardware for authentication. The hardware is expected to +be possessed only by the client which requested the tickets. + +\sphinxAtStartPar +If a ticket has the \sphinxstylestrong{transit policy} checked flag set, then the KDC +that issued this ticket implements the transited\sphinxhyphen{}realm check policy +and checked the transited\sphinxhyphen{}realms list on the ticket. The +transited\sphinxhyphen{}realms list contains a list of all intermediate realms +between the realm of the KDC that issued the first ticket and that of +the one that issued the current ticket. If this flag is not set, then +the application server must check the transited realms itself or else +reject the ticket. + +\sphinxAtStartPar +The \sphinxstylestrong{okay as delegate} flag indicates that the server specified in +the ticket is suitable as a delegate as determined by the policy of +that realm. Some client applications may use this flag to decide +whether to forward tickets to a remote host, although many +applications do not honor it. + +\sphinxAtStartPar +An \sphinxstylestrong{anonymous} ticket is one in which the named principal is a +generic principal for that realm; it does not actually specify the +individual that will be using the ticket. This ticket is meant only +to securely distribute a session key. + + +\section{Obtaining tickets with kinit} +\label{\detokenize{user/tkt_mgmt:obtaining-tickets-with-kinit}}\label{\detokenize{user/tkt_mgmt:obtain-tkt}} +\sphinxAtStartPar +If your site has integrated Kerberos V5 with the login system, you +will get Kerberos tickets automatically when you log in. Otherwise, +you may need to explicitly obtain your Kerberos tickets, using the +{\hyperref[\detokenize{user/user_commands/kinit:kinit-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kinit}}}} program. Similarly, if your Kerberos tickets expire, +use the kinit program to obtain new ones. + +\sphinxAtStartPar +To use the kinit program, simply type \sphinxcode{\sphinxupquote{kinit}} and then type your +password at the prompt. For example, Jennifer (whose username is +\sphinxcode{\sphinxupquote{jennifer}}) works for Bleep, Inc. (a fictitious company with the +domain name mit.edu and the Kerberos realm ATHENA.MIT.EDU). She would +type: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kinit} +\PYG{n}{Password} \PYG{k}{for} \PYG{n}{jennifer}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}} \PYG{p}{[}\PYG{n}{Type} \PYG{n}{jennifer}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{s password here.]} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If you type your password incorrectly, kinit will give you the +following error message: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kinit} +\PYG{n}{Password} \PYG{k}{for} \PYG{n}{jennifer}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}} \PYG{p}{[}\PYG{n}{Type} \PYG{n}{the} \PYG{n}{wrong} \PYG{n}{password} \PYG{n}{here}\PYG{o}{.}\PYG{p}{]} +\PYG{n}{kinit}\PYG{p}{:} \PYG{n}{Password} \PYG{n}{incorrect} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +and you won’t get Kerberos tickets. + +\sphinxAtStartPar +By default, kinit assumes you want tickets for your own username in +your default realm. Suppose Jennifer’s friend David is visiting, and +he wants to borrow a window to check his mail. David needs to get +tickets for himself in his own realm, EXAMPLE.COM. He would type: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kinit} \PYG{n}{david}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM} +\PYG{n}{Password} \PYG{k}{for} \PYG{n}{david}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}} \PYG{p}{[}\PYG{n}{Type} \PYG{n}{david}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{s password here.]} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +David would then have tickets which he could use to log onto his own +machine. Note that he typed his password locally on Jennifer’s +machine, but it never went over the network. Kerberos on the local +host performed the authentication to the KDC in the other realm. + +\sphinxAtStartPar +If you want to be able to forward your tickets to another host, you +need to request forwardable tickets. You do this by specifying the +\sphinxstylestrong{\sphinxhyphen{}f} option: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kinit} \PYG{o}{\PYGZhy{}}\PYG{n}{f} +\PYG{n}{Password} \PYG{k}{for} \PYG{n}{jennifer}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}} \PYG{p}{[}\PYG{n}{Type} \PYG{n}{your} \PYG{n}{password} \PYG{n}{here}\PYG{o}{.}\PYG{p}{]} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Note that kinit does not tell you that it obtained forwardable +tickets; you can verify this using the {\hyperref[\detokenize{user/user_commands/klist:klist-1}]{\sphinxcrossref{\DUrole{std,std-ref}{klist}}}} command (see +{\hyperref[\detokenize{user/tkt_mgmt:view-tkt}]{\sphinxcrossref{\DUrole{std,std-ref}{Viewing tickets with klist}}}}). + +\sphinxAtStartPar +Normally, your tickets are good for your system’s default ticket +lifetime, which is ten hours on many systems. You can specify a +different ticket lifetime with the \sphinxstylestrong{\sphinxhyphen{}l} option. Add the letter +\sphinxstylestrong{s} to the value for seconds, \sphinxstylestrong{m} for minutes, \sphinxstylestrong{h} for hours, or +\sphinxstylestrong{d} for days. For example, to obtain forwardable tickets for +\sphinxcode{\sphinxupquote{david@EXAMPLE.COM}} that would be good for three hours, you would +type: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kinit} \PYG{o}{\PYGZhy{}}\PYG{n}{f} \PYG{o}{\PYGZhy{}}\PYG{n}{l} \PYG{l+m+mi}{3}\PYG{n}{h} \PYG{n}{david}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM} +\PYG{n}{Password} \PYG{k}{for} \PYG{n}{david}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM}\PYG{p}{:} \PYG{o}{\PYGZlt{}}\PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}} \PYG{p}{[}\PYG{n}{Type} \PYG{n}{david}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{s password here.]} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +You cannot mix units; specifying a lifetime of 3h30m would +result in an error. Note also that most systems specify a +maximum ticket lifetime. If you request a longer ticket +lifetime, it will be automatically truncated to the maximum +lifetime. +\end{sphinxadmonition} + + +\section{Viewing tickets with klist} +\label{\detokenize{user/tkt_mgmt:viewing-tickets-with-klist}}\label{\detokenize{user/tkt_mgmt:view-tkt}} +\sphinxAtStartPar +The {\hyperref[\detokenize{user/user_commands/klist:klist-1}]{\sphinxcrossref{\DUrole{std,std-ref}{klist}}}} command shows your tickets. When you first obtain +tickets, you will have only the ticket\sphinxhyphen{}granting ticket. The listing +would look like this: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{klist} +\PYG{n}{Ticket} \PYG{n}{cache}\PYG{p}{:} \PYG{o}{/}\PYG{n}{tmp}\PYG{o}{/}\PYG{n}{krb5cc\PYGZus{}ttypa} +\PYG{n}{Default} \PYG{n}{principal}\PYG{p}{:} \PYG{n}{jennifer}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} + +\PYG{n}{Valid} \PYG{n}{starting} \PYG{n}{Expires} \PYG{n}{Service} \PYG{n}{principal} +\PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{07}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{19}\PYG{p}{:}\PYG{l+m+mi}{49}\PYG{p}{:}\PYG{l+m+mi}{21} \PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{08}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{05}\PYG{p}{:}\PYG{l+m+mi}{49}\PYG{p}{:}\PYG{l+m+mi}{19} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The ticket cache is the location of your ticket file. In the above +example, this file is named \sphinxcode{\sphinxupquote{/tmp/krb5cc\_ttypa}}. The default +principal is your Kerberos principal. + +\sphinxAtStartPar +The “valid starting” and “expires” fields describe the period of time +during which the ticket is valid. The “service principal” describes +each ticket. The ticket\sphinxhyphen{}granting ticket has a first component +\sphinxcode{\sphinxupquote{krbtgt}}, and a second component which is the realm name. + +\sphinxAtStartPar +Now, if \sphinxcode{\sphinxupquote{jennifer}} connected to the machine \sphinxcode{\sphinxupquote{daffodil.mit.edu}}, +and then typed “klist” again, she would have gotten the following +result: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{klist} +\PYG{n}{Ticket} \PYG{n}{cache}\PYG{p}{:} \PYG{o}{/}\PYG{n}{tmp}\PYG{o}{/}\PYG{n}{krb5cc\PYGZus{}ttypa} +\PYG{n}{Default} \PYG{n}{principal}\PYG{p}{:} \PYG{n}{jennifer}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} + +\PYG{n}{Valid} \PYG{n}{starting} \PYG{n}{Expires} \PYG{n}{Service} \PYG{n}{principal} +\PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{07}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{19}\PYG{p}{:}\PYG{l+m+mi}{49}\PYG{p}{:}\PYG{l+m+mi}{21} \PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{08}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{05}\PYG{p}{:}\PYG{l+m+mi}{49}\PYG{p}{:}\PYG{l+m+mi}{19} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{07}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{20}\PYG{p}{:}\PYG{l+m+mi}{22}\PYG{p}{:}\PYG{l+m+mi}{30} \PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{08}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{05}\PYG{p}{:}\PYG{l+m+mi}{49}\PYG{p}{:}\PYG{l+m+mi}{19} \PYG{n}{host}\PYG{o}{/}\PYG{n}{daffodil}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Here’s what happened: when \sphinxcode{\sphinxupquote{jennifer}} used ssh to connect to the +host \sphinxcode{\sphinxupquote{daffodil.mit.edu}}, the ssh program presented her +ticket\sphinxhyphen{}granting ticket to the KDC and requested a host ticket for the +host \sphinxcode{\sphinxupquote{daffodil.mit.edu}}. The KDC sent the host ticket, which ssh +then presented to the host \sphinxcode{\sphinxupquote{daffodil.mit.edu}}, and she was allowed +to log in without typing her password. + +\sphinxAtStartPar +Suppose your Kerberos tickets allow you to log into a host in another +domain, such as \sphinxcode{\sphinxupquote{trillium.example.com}}, which is also in another +Kerberos realm, \sphinxcode{\sphinxupquote{EXAMPLE.COM}}. If you ssh to this host, you will +receive a ticket\sphinxhyphen{}granting ticket for the realm \sphinxcode{\sphinxupquote{EXAMPLE.COM}}, plus +the new host ticket for \sphinxcode{\sphinxupquote{trillium.example.com}}. klist will now +show: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{klist} +\PYG{n}{Ticket} \PYG{n}{cache}\PYG{p}{:} \PYG{o}{/}\PYG{n}{tmp}\PYG{o}{/}\PYG{n}{krb5cc\PYGZus{}ttypa} +\PYG{n}{Default} \PYG{n}{principal}\PYG{p}{:} \PYG{n}{jennifer}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} + +\PYG{n}{Valid} \PYG{n}{starting} \PYG{n}{Expires} \PYG{n}{Service} \PYG{n}{principal} +\PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{07}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{19}\PYG{p}{:}\PYG{l+m+mi}{49}\PYG{p}{:}\PYG{l+m+mi}{21} \PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{08}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{05}\PYG{p}{:}\PYG{l+m+mi}{49}\PYG{p}{:}\PYG{l+m+mi}{19} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{07}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{20}\PYG{p}{:}\PYG{l+m+mi}{22}\PYG{p}{:}\PYG{l+m+mi}{30} \PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{08}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{05}\PYG{p}{:}\PYG{l+m+mi}{49}\PYG{p}{:}\PYG{l+m+mi}{19} \PYG{n}{host}\PYG{o}{/}\PYG{n}{daffodil}\PYG{o}{.}\PYG{n}{mit}\PYG{o}{.}\PYG{n}{edu}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{07}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{20}\PYG{p}{:}\PYG{l+m+mi}{24}\PYG{p}{:}\PYG{l+m+mi}{18} \PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{08}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{05}\PYG{p}{:}\PYG{l+m+mi}{49}\PYG{p}{:}\PYG{l+m+mi}{19} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} +\PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{07}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{20}\PYG{p}{:}\PYG{l+m+mi}{24}\PYG{p}{:}\PYG{l+m+mi}{18} \PYG{l+m+mi}{06}\PYG{o}{/}\PYG{l+m+mi}{08}\PYG{o}{/}\PYG{l+m+mi}{04} \PYG{l+m+mi}{05}\PYG{p}{:}\PYG{l+m+mi}{49}\PYG{p}{:}\PYG{l+m+mi}{19} \PYG{n}{host}\PYG{o}{/}\PYG{n}{trillium}\PYG{o}{.}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Depending on your host’s and realm’s configuration, you may also see a +ticket with the service principal \sphinxcode{\sphinxupquote{host/trillium.example.com@}}. If +so, this means that your host did not know what realm +trillium.example.com is in, so it asked the \sphinxcode{\sphinxupquote{ATHENA.MIT.EDU}} KDC for +a referral. The next time you connect to \sphinxcode{\sphinxupquote{trillium.example.com}}, +the odd\sphinxhyphen{}looking entry will be used to avoid needing to ask for a +referral again. + +\sphinxAtStartPar +You can use the \sphinxstylestrong{\sphinxhyphen{}f} option to view the flags that apply to your +tickets. The flags are: + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +F +& +\sphinxAtStartPar +Forwardable +\\ +\hline +\sphinxAtStartPar +f +& +\sphinxAtStartPar +forwarded +\\ +\hline +\sphinxAtStartPar +P +& +\sphinxAtStartPar +Proxiable +\\ +\hline +\sphinxAtStartPar +p +& +\sphinxAtStartPar +proxy +\\ +\hline +\sphinxAtStartPar +D +& +\sphinxAtStartPar +postDateable +\\ +\hline +\sphinxAtStartPar +d +& +\sphinxAtStartPar +postdated +\\ +\hline +\sphinxAtStartPar +R +& +\sphinxAtStartPar +Renewable +\\ +\hline +\sphinxAtStartPar +I +& +\sphinxAtStartPar +Initial +\\ +\hline +\sphinxAtStartPar +i +& +\sphinxAtStartPar +invalid +\\ +\hline +\sphinxAtStartPar +H +& +\sphinxAtStartPar +Hardware authenticated +\\ +\hline +\sphinxAtStartPar +A +& +\sphinxAtStartPar +preAuthenticated +\\ +\hline +\sphinxAtStartPar +T +& +\sphinxAtStartPar +Transit policy checked +\\ +\hline +\sphinxAtStartPar +O +& +\sphinxAtStartPar +Okay as delegate +\\ +\hline +\sphinxAtStartPar +a +& +\sphinxAtStartPar +anonymous +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + +\sphinxAtStartPar +Here is a sample listing. In this example, the user \sphinxstyleemphasis{jennifer} +obtained her initial tickets (\sphinxstylestrong{I}), which are forwardable (\sphinxstylestrong{F}) +and postdated (\sphinxstylestrong{d}) but not yet validated (\sphinxstylestrong{i}): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{klist} \PYG{o}{\PYGZhy{}}\PYG{n}{f} +\PYG{n}{Ticket} \PYG{n}{cache}\PYG{p}{:} \PYG{o}{/}\PYG{n}{tmp}\PYG{o}{/}\PYG{n}{krb5cc\PYGZus{}320} +\PYG{n}{Default} \PYG{n}{principal}\PYG{p}{:} \PYG{n}{jennifer}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} + +\PYG{n}{Valid} \PYG{n}{starting} \PYG{n}{Expires} \PYG{n}{Service} \PYG{n}{principal} +\PYG{l+m+mi}{31}\PYG{o}{/}\PYG{l+m+mi}{07}\PYG{o}{/}\PYG{l+m+mi}{05} \PYG{l+m+mi}{19}\PYG{p}{:}\PYG{l+m+mi}{06}\PYG{p}{:}\PYG{l+m+mi}{25} \PYG{l+m+mi}{31}\PYG{o}{/}\PYG{l+m+mi}{07}\PYG{o}{/}\PYG{l+m+mi}{05} \PYG{l+m+mi}{19}\PYG{p}{:}\PYG{l+m+mi}{16}\PYG{p}{:}\PYG{l+m+mi}{25} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU}\PYG{n+nd}{@ATHENA}\PYG{o}{.}\PYG{n}{MIT}\PYG{o}{.}\PYG{n}{EDU} + \PYG{n}{Flags}\PYG{p}{:} \PYG{n}{FdiI} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +In the following example, the user \sphinxstyleemphasis{david}’s tickets were forwarded +(\sphinxstylestrong{f}) to this host from another host. The tickets are reforwardable +(\sphinxstylestrong{F}): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{klist} \PYG{o}{\PYGZhy{}}\PYG{n}{f} +\PYG{n}{Ticket} \PYG{n}{cache}\PYG{p}{:} \PYG{o}{/}\PYG{n}{tmp}\PYG{o}{/}\PYG{n}{krb5cc\PYGZus{}p11795} +\PYG{n}{Default} \PYG{n}{principal}\PYG{p}{:} \PYG{n}{david}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM} + +\PYG{n}{Valid} \PYG{n}{starting} \PYG{n}{Expires} \PYG{n}{Service} \PYG{n}{principal} +\PYG{l+m+mi}{07}\PYG{o}{/}\PYG{l+m+mi}{31}\PYG{o}{/}\PYG{l+m+mi}{05} \PYG{l+m+mi}{11}\PYG{p}{:}\PYG{l+m+mi}{52}\PYG{p}{:}\PYG{l+m+mi}{29} \PYG{l+m+mi}{07}\PYG{o}{/}\PYG{l+m+mi}{31}\PYG{o}{/}\PYG{l+m+mi}{05} \PYG{l+m+mi}{21}\PYG{p}{:}\PYG{l+m+mi}{11}\PYG{p}{:}\PYG{l+m+mi}{23} \PYG{n}{krbtgt}\PYG{o}{/}\PYG{n}{EXAMPLE}\PYG{o}{.}\PYG{n}{COM}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM} + \PYG{n}{Flags}\PYG{p}{:} \PYG{n}{Ff} +\PYG{l+m+mi}{07}\PYG{o}{/}\PYG{l+m+mi}{31}\PYG{o}{/}\PYG{l+m+mi}{05} \PYG{l+m+mi}{12}\PYG{p}{:}\PYG{l+m+mi}{03}\PYG{p}{:}\PYG{l+m+mi}{48} \PYG{l+m+mi}{07}\PYG{o}{/}\PYG{l+m+mi}{31}\PYG{o}{/}\PYG{l+m+mi}{05} \PYG{l+m+mi}{21}\PYG{p}{:}\PYG{l+m+mi}{11}\PYG{p}{:}\PYG{l+m+mi}{23} \PYG{n}{host}\PYG{o}{/}\PYG{n}{trillium}\PYG{o}{.}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM} + \PYG{n}{Flags}\PYG{p}{:} \PYG{n}{Ff} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + + +\section{Destroying tickets with kdestroy} +\label{\detokenize{user/tkt_mgmt:destroying-tickets-with-kdestroy}} +\sphinxAtStartPar +Your Kerberos tickets are proof that you are indeed yourself, and +tickets could be stolen if someone gains access to a computer where +they are stored. If this happens, the person who has them can +masquerade as you until they expire. For this reason, you should +destroy your Kerberos tickets when you are away from your computer. + +\sphinxAtStartPar +Destroying your tickets is easy. Simply type kdestroy: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kdestroy} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If {\hyperref[\detokenize{user/user_commands/kdestroy:kdestroy-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kdestroy}}}} fails to destroy your tickets, it will beep and +give an error message. For example, if kdestroy can’t find any +tickets to destroy, it will give the following message: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{kdestroy} +\PYG{n}{kdestroy}\PYG{p}{:} \PYG{n}{No} \PYG{n}{credentials} \PYG{n}{cache} \PYG{n}{file} \PYG{n}{found} \PYG{k}{while} \PYG{n}{destroying} \PYG{n}{cache} +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} +\end{sphinxVerbatim} + + +\chapter{User config files} +\label{\detokenize{user/user_config/index:user-config-files}}\label{\detokenize{user/user_config/index::doc}} +\sphinxAtStartPar +The following files in your home directory can be used to control the +behavior of Kerberos as it applies to your account (unless they have +been disabled by your host’s configuration): + + +\section{kerberos} +\label{\detokenize{user/user_config/kerberos:kerberos}}\label{\detokenize{user/user_config/kerberos:kerberos-7}}\label{\detokenize{user/user_config/kerberos::doc}} + +\subsection{DESCRIPTION} +\label{\detokenize{user/user_config/kerberos:description}} +\sphinxAtStartPar +The Kerberos system authenticates individual users in a network +environment. After authenticating yourself to Kerberos, you can use +Kerberos\sphinxhyphen{}enabled programs without having to present passwords or +certificates to those programs. + +\sphinxAtStartPar +If you receive the following response from {\hyperref[\detokenize{user/user_commands/kinit:kinit-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kinit}}}}: + +\sphinxAtStartPar +kinit: Client not found in Kerberos database while getting initial +credentials + +\sphinxAtStartPar +you haven’t been registered as a Kerberos user. See your system +administrator. + +\sphinxAtStartPar +A Kerberos name usually contains three parts. The first is the +\sphinxstylestrong{primary}, which is usually a user’s or service’s name. The second +is the \sphinxstylestrong{instance}, which in the case of a user is usually null. +Some users may have privileged instances, however, such as \sphinxcode{\sphinxupquote{root}} or +\sphinxcode{\sphinxupquote{admin}}. In the case of a service, the instance is the fully +qualified name of the machine on which it runs; i.e. there can be an +ssh service running on the machine ABC (\sphinxhref{mailto:ssh/ABC@REALM}{ssh/ABC@REALM}), which is +different from the ssh service running on the machine XYZ +(\sphinxhref{mailto:ssh/XYZ@REALM}{ssh/XYZ@REALM}). The third part of a Kerberos name is the \sphinxstylestrong{realm}. +The realm corresponds to the Kerberos service providing authentication +for the principal. Realms are conventionally all\sphinxhyphen{}uppercase, and often +match the end of hostnames in the realm (for instance, host01.example.com +might be in realm EXAMPLE.COM). + +\sphinxAtStartPar +When writing a Kerberos name, the principal name is separated from the +instance (if not null) by a slash, and the realm (if not the local +realm) follows, preceded by an “@” sign. The following are examples +of valid Kerberos names: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{david} +\PYG{n}{jennifer}\PYG{o}{/}\PYG{n}{admin} +\PYG{n}{joeuser}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM} +\PYG{n}{cbrown}\PYG{o}{/}\PYG{n}{root}\PYG{n+nd}{@FUBAR}\PYG{o}{.}\PYG{n}{ORG} +\end{sphinxVerbatim} + +\sphinxAtStartPar +When you authenticate yourself with Kerberos you get an initial +Kerberos \sphinxstylestrong{ticket}. (A Kerberos ticket is an encrypted protocol +message that provides authentication.) Kerberos uses this ticket for +network utilities such as ssh. The ticket transactions are done +transparently, so you don’t have to worry about their management. + +\sphinxAtStartPar +Note, however, that tickets expire. Administrators may configure more +privileged tickets, such as those with service or instance of \sphinxcode{\sphinxupquote{root}} +or \sphinxcode{\sphinxupquote{admin}}, to expire in a few minutes, while tickets that carry +more ordinary privileges may be good for several hours or a day. If +your login session extends beyond the time limit, you will have to +re\sphinxhyphen{}authenticate yourself to Kerberos to get new tickets using the +{\hyperref[\detokenize{user/user_commands/kinit:kinit-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kinit}}}} command. + +\sphinxAtStartPar +Some tickets are \sphinxstylestrong{renewable} beyond their initial lifetime. This +means that \sphinxcode{\sphinxupquote{kinit \sphinxhyphen{}R}} can extend their lifetime without requiring +you to re\sphinxhyphen{}authenticate. + +\sphinxAtStartPar +If you wish to delete your local tickets, use the {\hyperref[\detokenize{user/user_commands/kdestroy:kdestroy-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kdestroy}}}} +command. + +\sphinxAtStartPar +Kerberos tickets can be forwarded. In order to forward tickets, you +must request \sphinxstylestrong{forwardable} tickets when you kinit. Once you have +forwardable tickets, most Kerberos programs have a command line option +to forward them to the remote host. This can be useful for, e.g., +running kinit on your local machine and then sshing into another to do +work. Note that this should not be done on untrusted machines since +they will then have your tickets. + + +\subsection{ENVIRONMENT VARIABLES} +\label{\detokenize{user/user_config/kerberos:environment-variables}} +\sphinxAtStartPar +Several environment variables affect the operation of Kerberos\sphinxhyphen{}enabled +programs. These include: +\begin{description} +\item[{\sphinxstylestrong{KRB5CCNAME}}] \leavevmode +\sphinxAtStartPar +Default name for the credentials cache file, in the form +\sphinxstyleemphasis{TYPE}:\sphinxstyleemphasis{residual}. The type of the default cache may determine +the availability of a cache collection. \sphinxcode{\sphinxupquote{FILE}} is not a +collection type; \sphinxcode{\sphinxupquote{KEYRING}}, \sphinxcode{\sphinxupquote{DIR}}, and \sphinxcode{\sphinxupquote{KCM}} are. + +\sphinxAtStartPar +If not set, the value of \sphinxstylestrong{default\_ccache\_name} from +configuration files (see \sphinxstylestrong{KRB5\_CONFIG}) will be used. If that +is also not set, the default \sphinxstyleemphasis{type} is \sphinxcode{\sphinxupquote{FILE}}, and the +\sphinxstyleemphasis{residual} is the path /tmp/krb5cc\_*uid*, where \sphinxstyleemphasis{uid} is the +decimal user ID of the user. + +\item[{\sphinxstylestrong{KRB5\_KTNAME}}] \leavevmode +\sphinxAtStartPar +Specifies the location of the default keytab file, in the form +\sphinxstyleemphasis{TYPE}:\sphinxstyleemphasis{residual}. If no \sphinxstyleemphasis{type} is present, the \sphinxstylestrong{FILE} type is +assumed and \sphinxstyleemphasis{residual} is the pathname of the keytab file. If +unset, \DUrole{xref,std,std-ref}{DEFKTNAME} will be used. + +\item[{\sphinxstylestrong{KRB5\_CONFIG}}] \leavevmode +\sphinxAtStartPar +Specifies the location of the Kerberos configuration file. The +default is \DUrole{xref,std,std-ref}{SYSCONFDIR}\sphinxcode{\sphinxupquote{/krb5.conf}}. Multiple filenames can +be specified, separated by a colon; all files which are present +will be read. + +\item[{\sphinxstylestrong{KRB5\_KDC\_PROFILE}}] \leavevmode +\sphinxAtStartPar +Specifies the location of the KDC configuration file, which +contains additional configuration directives for the Key +Distribution Center daemon and associated programs. The default +is \DUrole{xref,std,std-ref}{LOCALSTATEDIR}\sphinxcode{\sphinxupquote{/krb5kdc}}\sphinxcode{\sphinxupquote{/kdc.conf}}. + +\item[{\sphinxstylestrong{KRB5RCACHENAME}}] \leavevmode +\sphinxAtStartPar +(New in release 1.18) Specifies the location of the default replay +cache, in the form \sphinxstyleemphasis{type}:\sphinxstyleemphasis{residual}. The \sphinxcode{\sphinxupquote{file2}} type with a +pathname residual specifies a replay cache file in the version\sphinxhyphen{}2 +format in the specified location. The \sphinxcode{\sphinxupquote{none}} type (residual is +ignored) disables the replay cache. The \sphinxcode{\sphinxupquote{dfl}} type (residual is +ignored) indicates the default, which uses a file2 replay cache in +a temporary directory. The default is \sphinxcode{\sphinxupquote{dfl:}}. + +\item[{\sphinxstylestrong{KRB5RCACHETYPE}}] \leavevmode +\sphinxAtStartPar +Specifies the type of the default replay cache, if +\sphinxstylestrong{KRB5RCACHENAME} is unspecified. No residual can be specified, +so \sphinxcode{\sphinxupquote{none}} and \sphinxcode{\sphinxupquote{dfl}} are the only useful types. + +\item[{\sphinxstylestrong{KRB5RCACHEDIR}}] \leavevmode +\sphinxAtStartPar +Specifies the directory used by the \sphinxcode{\sphinxupquote{dfl}} replay cache type. +The default is the value of the \sphinxstylestrong{TMPDIR} environment variable, +or \sphinxcode{\sphinxupquote{/var/tmp}} if \sphinxstylestrong{TMPDIR} is not set. + +\item[{\sphinxstylestrong{KRB5\_TRACE}}] \leavevmode +\sphinxAtStartPar +Specifies a filename to write trace log output to. Trace logs can +help illuminate decisions made internally by the Kerberos +libraries. For example, \sphinxcode{\sphinxupquote{env KRB5\_TRACE=/dev/stderr kinit}} +would send tracing information for {\hyperref[\detokenize{user/user_commands/kinit:kinit-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kinit}}}} to +\sphinxcode{\sphinxupquote{/dev/stderr}}. The default is not to write trace log output +anywhere. + +\item[{\sphinxstylestrong{KRB5\_CLIENT\_KTNAME}}] \leavevmode +\sphinxAtStartPar +Default client keytab file name. If unset, \DUrole{xref,std,std-ref}{DEFCKTNAME} will be +used). + +\item[{\sphinxstylestrong{KPROP\_PORT}}] \leavevmode +\sphinxAtStartPar +\DUrole{xref,std,std-ref}{kprop(8)} port to use. Defaults to 754. + +\item[{\sphinxstylestrong{GSS\_MECH\_CONFIG}}] \leavevmode +\sphinxAtStartPar +Specifies a filename containing GSSAPI mechanism module +configuration. The default is to read \DUrole{xref,std,std-ref}{SYSCONFDIR}\sphinxcode{\sphinxupquote{/gss/mech}} +and files with a \sphinxcode{\sphinxupquote{.conf}} suffix within the directory +\DUrole{xref,std,std-ref}{SYSCONFDIR}\sphinxcode{\sphinxupquote{/gss/mech.d}}. + +\end{description} + +\sphinxAtStartPar +Most environment variables are disabled for certain programs, such as +login system programs and setuid programs, which are designed to be +secure when run within an untrusted process environment. + + +\subsection{SEE ALSO} +\label{\detokenize{user/user_config/kerberos:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{user/user_commands/kdestroy:kdestroy-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kdestroy}}}}, {\hyperref[\detokenize{user/user_commands/kinit:kinit-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kinit}}}}, {\hyperref[\detokenize{user/user_commands/klist:klist-1}]{\sphinxcrossref{\DUrole{std,std-ref}{klist}}}}, +{\hyperref[\detokenize{user/user_commands/kswitch:kswitch-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kswitch}}}}, {\hyperref[\detokenize{user/user_commands/kpasswd:kpasswd-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kpasswd}}}}, {\hyperref[\detokenize{user/user_commands/ksu:ksu-1}]{\sphinxcrossref{\DUrole{std,std-ref}{ksu}}}}, +\DUrole{xref,std,std-ref}{krb5.conf(5)}, \DUrole{xref,std,std-ref}{kdc.conf(5)}, \DUrole{xref,std,std-ref}{kadmin(1)}, +\DUrole{xref,std,std-ref}{kadmind(8)}, \DUrole{xref,std,std-ref}{kdb5\_util(8)}, \DUrole{xref,std,std-ref}{krb5kdc(8)} + + +\subsection{BUGS} +\label{\detokenize{user/user_config/kerberos:bugs}} + +\subsection{AUTHORS} +\label{\detokenize{user/user_config/kerberos:authors}} +\begin{DUlineblock}{0em} +\item[] Steve Miller, MIT Project Athena/Digital Equipment Corporation +\item[] Clifford Neuman, MIT Project Athena +\item[] Greg Hudson, MIT Kerberos Consortium +\item[] Robbie Harwood, Red Hat, Inc. +\end{DUlineblock} + + +\subsection{HISTORY} +\label{\detokenize{user/user_config/kerberos:history}} +\sphinxAtStartPar +The MIT Kerberos 5 implementation was developed at MIT, with +contributions from many outside parties. It is currently maintained +by the MIT Kerberos Consortium. + + +\subsection{RESTRICTIONS} +\label{\detokenize{user/user_config/kerberos:restrictions}} +\sphinxAtStartPar +Copyright 1985, 1986, 1989\sphinxhyphen{}1996, 2002, 2011, 2018 Masachusetts +Institute of Technology + + +\section{.k5login} +\label{\detokenize{user/user_config/k5login:k5login}}\label{\detokenize{user/user_config/k5login:k5login-5}}\label{\detokenize{user/user_config/k5login::doc}} + +\subsection{DESCRIPTION} +\label{\detokenize{user/user_config/k5login:description}} +\sphinxAtStartPar +The .k5login file, which resides in a user’s home directory, contains +a list of the Kerberos principals. Anyone with valid tickets for a +principal in the file is allowed host access with the UID of the user +in whose home directory the file resides. One common use is to place +a .k5login file in root’s home directory, thereby granting system +administrators remote root access to the host via Kerberos. + + +\subsection{EXAMPLES} +\label{\detokenize{user/user_config/k5login:examples}} +\sphinxAtStartPar +Suppose the user \sphinxcode{\sphinxupquote{alice}} had a .k5login file in her home directory +containing just the following line: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{bob}\PYG{n+nd}{@FOOBAR}\PYG{o}{.}\PYG{n}{ORG} +\end{sphinxVerbatim} + +\sphinxAtStartPar +This would allow \sphinxcode{\sphinxupquote{bob}} to use Kerberos network applications, such as +ssh(1), to access \sphinxcode{\sphinxupquote{alice}}’s account, using \sphinxcode{\sphinxupquote{bob}}’s Kerberos +tickets. In a default configuration (with \sphinxstylestrong{k5login\_authoritative} set +to true in \DUrole{xref,std,std-ref}{krb5.conf(5)}), this .k5login file would not let +\sphinxcode{\sphinxupquote{alice}} use those network applications to access her account, since +she is not listed! With no .k5login file, or with \sphinxstylestrong{k5login\_authoritative} +set to false, a default rule would permit the principal \sphinxcode{\sphinxupquote{alice}} in the +machine’s default realm to access the \sphinxcode{\sphinxupquote{alice}} account. + +\sphinxAtStartPar +Let us further suppose that \sphinxcode{\sphinxupquote{alice}} is a system administrator. +Alice and the other system administrators would have their principals +in root’s .k5login file on each host: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{alice}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM} + +\PYG{n}{joeadmin}\PYG{o}{/}\PYG{n}{root}\PYG{n+nd}{@BLEEP}\PYG{o}{.}\PYG{n}{COM} +\end{sphinxVerbatim} + +\sphinxAtStartPar +This would allow either system administrator to log in to these hosts +using their Kerberos tickets instead of having to type the root +password. Note that because \sphinxcode{\sphinxupquote{bob}} retains the Kerberos tickets for +his own principal, \sphinxcode{\sphinxupquote{bob@FOOBAR.ORG}}, he would not have any of the +privileges that require \sphinxcode{\sphinxupquote{alice}}’s tickets, such as root access to +any of the site’s hosts, or the ability to change \sphinxcode{\sphinxupquote{alice}}’s +password. + + +\subsection{SEE ALSO} +\label{\detokenize{user/user_config/k5login:see-also}} +\sphinxAtStartPar +kerberos(1) + + +\section{.k5identity} +\label{\detokenize{user/user_config/k5identity:k5identity}}\label{\detokenize{user/user_config/k5identity:k5identity-5}}\label{\detokenize{user/user_config/k5identity::doc}} + +\subsection{DESCRIPTION} +\label{\detokenize{user/user_config/k5identity:description}} +\sphinxAtStartPar +The .k5identity file, which resides in a user’s home directory, +contains a list of rules for selecting a client principals based on +the server being accessed. These rules are used to choose a +credential cache within the cache collection when possible. + +\sphinxAtStartPar +Blank lines and lines beginning with \sphinxcode{\sphinxupquote{\#}} are ignored. Each line has +the form: +\begin{quote} + +\sphinxAtStartPar +\sphinxstyleemphasis{principal} \sphinxstyleemphasis{field}=\sphinxstyleemphasis{value} … +\end{quote} + +\sphinxAtStartPar +If the server principal meets all of the field constraints, then +principal is chosen as the client principal. The following fields are +recognized: +\begin{description} +\item[{\sphinxstylestrong{realm}}] \leavevmode +\sphinxAtStartPar +If the realm of the server principal is known, it is matched +against \sphinxstyleemphasis{value}, which may be a pattern using shell wildcards. +For host\sphinxhyphen{}based server principals, the realm will generally only be +known if there is a \DUrole{xref,std,std-ref}{domain\_realm} section in +\DUrole{xref,std,std-ref}{krb5.conf(5)} with a mapping for the hostname. + +\item[{\sphinxstylestrong{service}}] \leavevmode +\sphinxAtStartPar +If the server principal is a host\sphinxhyphen{}based principal, its service +component is matched against \sphinxstyleemphasis{value}, which may be a pattern using +shell wildcards. + +\item[{\sphinxstylestrong{host}}] \leavevmode +\sphinxAtStartPar +If the server principal is a host\sphinxhyphen{}based principal, its hostname +component is converted to lower case and matched against \sphinxstyleemphasis{value}, +which may be a pattern using shell wildcards. + +\sphinxAtStartPar +If the server principal matches the constraints of multiple lines +in the .k5identity file, the principal from the first matching +line is used. If no line matches, credentials will be selected +some other way, such as the realm heuristic or the current primary +cache. + +\end{description} + + +\subsection{EXAMPLE} +\label{\detokenize{user/user_config/k5identity:example}} +\sphinxAtStartPar +The following example .k5identity file selects the client principal +\sphinxcode{\sphinxupquote{alice@KRBTEST.COM}} if the server principal is within that realm, +the principal \sphinxcode{\sphinxupquote{alice/root@EXAMPLE.COM}} if the server host is within +a servers subdomain, and the principal \sphinxcode{\sphinxupquote{alice/mail@EXAMPLE.COM}} when +accessing the IMAP service on \sphinxcode{\sphinxupquote{mail.example.com}}: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{alice}\PYG{n+nd}{@KRBTEST}\PYG{o}{.}\PYG{n}{COM} \PYG{n}{realm}\PYG{o}{=}\PYG{n}{KRBTEST}\PYG{o}{.}\PYG{n}{COM} +\PYG{n}{alice}\PYG{o}{/}\PYG{n}{root}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM} \PYG{n}{host}\PYG{o}{=}\PYG{o}{*}\PYG{o}{.}\PYG{n}{servers}\PYG{o}{.}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com} +\PYG{n}{alice}\PYG{o}{/}\PYG{n}{mail}\PYG{n+nd}{@EXAMPLE}\PYG{o}{.}\PYG{n}{COM} \PYG{n}{host}\PYG{o}{=}\PYG{n}{mail}\PYG{o}{.}\PYG{n}{example}\PYG{o}{.}\PYG{n}{com} \PYG{n}{service}\PYG{o}{=}\PYG{n}{imap} +\end{sphinxVerbatim} + + +\subsection{SEE ALSO} +\label{\detokenize{user/user_config/k5identity:see-also}} +\sphinxAtStartPar +kerberos(1), \DUrole{xref,std,std-ref}{krb5.conf(5)} + + +\chapter{User commands} +\label{\detokenize{user/user_commands/index:user-commands}}\label{\detokenize{user/user_commands/index:id1}}\label{\detokenize{user/user_commands/index::doc}} + +\section{kdestroy} +\label{\detokenize{user/user_commands/kdestroy:kdestroy}}\label{\detokenize{user/user_commands/kdestroy:kdestroy-1}}\label{\detokenize{user/user_commands/kdestroy::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{user/user_commands/kdestroy:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{kdestroy} +{[}\sphinxstylestrong{\sphinxhyphen{}A}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}q}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}c} \sphinxstyleemphasis{cache\_name}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{princ\_name}{]} + + +\subsection{DESCRIPTION} +\label{\detokenize{user/user_commands/kdestroy:description}} +\sphinxAtStartPar +The kdestroy utility destroys the user’s active Kerberos authorization +tickets by overwriting and deleting the credentials cache that +contains them. If the credentials cache is not specified, the default +credentials cache is destroyed. + + +\subsection{OPTIONS} +\label{\detokenize{user/user_commands/kdestroy:options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}A}}] \leavevmode +\sphinxAtStartPar +Destroys all caches in the collection, if a cache collection is +available. May be used with the \sphinxstylestrong{\sphinxhyphen{}c} option to specify the +collection to be destroyed. + +\item[{\sphinxstylestrong{\sphinxhyphen{}q}}] \leavevmode +\sphinxAtStartPar +Run quietly. Normally kdestroy beeps if it fails to destroy the +user’s tickets. The \sphinxstylestrong{\sphinxhyphen{}q} flag suppresses this behavior. + +\item[{\sphinxstylestrong{\sphinxhyphen{}c} \sphinxstyleemphasis{cache\_name}}] \leavevmode +\sphinxAtStartPar +Use \sphinxstyleemphasis{cache\_name} as the credentials (ticket) cache name and +location; if this option is not used, the default cache name and +location are used. + +\sphinxAtStartPar +The default credentials cache may vary between systems. If the +\sphinxstylestrong{KRB5CCNAME} environment variable is set, its value is used to +name the default ticket cache. + +\item[{\sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{princ\_name}}] \leavevmode +\sphinxAtStartPar +If a cache collection is available, destroy the cache for +\sphinxstyleemphasis{princ\_name} instead of the primary cache. May be used with the +\sphinxstylestrong{\sphinxhyphen{}c} option to specify the collection to be searched. + +\end{description} + + +\subsection{NOTE} +\label{\detokenize{user/user_commands/kdestroy:note}} +\sphinxAtStartPar +Most installations recommend that you place the kdestroy command in +your .logout file, so that your tickets are destroyed automatically +when you log out. + + +\subsection{ENVIRONMENT} +\label{\detokenize{user/user_commands/kdestroy:environment}} +\sphinxAtStartPar +See {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} for a description of Kerberos environment +variables. + + +\subsection{FILES} +\label{\detokenize{user/user_commands/kdestroy:files}}\begin{description} +\item[{\DUrole{xref,std,std-ref}{DEFCCNAME}}] \leavevmode +\sphinxAtStartPar +Default location of Kerberos 5 credentials cache + +\end{description} + + +\subsection{SEE ALSO} +\label{\detokenize{user/user_commands/kdestroy:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{user/user_commands/kinit:kinit-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kinit}}}}, {\hyperref[\detokenize{user/user_commands/klist:klist-1}]{\sphinxcrossref{\DUrole{std,std-ref}{klist}}}}, {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} + + +\section{kinit} +\label{\detokenize{user/user_commands/kinit:kinit}}\label{\detokenize{user/user_commands/kinit:kinit-1}}\label{\detokenize{user/user_commands/kinit::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{user/user_commands/kinit:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{kinit} +{[}\sphinxstylestrong{\sphinxhyphen{}V}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}l} \sphinxstyleemphasis{lifetime}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}s} \sphinxstyleemphasis{start\_time}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{renewable\_life}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}p} | \sphinxhyphen{}\sphinxstylestrong{P}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}f} | \sphinxhyphen{}\sphinxstylestrong{F}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}a}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}A}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}C}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}E}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}v}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}R}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}k} {[}\sphinxstylestrong{\sphinxhyphen{}i} | \sphinxhyphen{}\sphinxstylestrong{t} \sphinxstyleemphasis{keytab\_file}{]}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}c} \sphinxstyleemphasis{cache\_name}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}n}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}S} \sphinxstyleemphasis{service\_name}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}I} \sphinxstyleemphasis{input\_ccache}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}T} \sphinxstyleemphasis{armor\_ccache}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}X} \sphinxstyleemphasis{attribute}{[}=\sphinxstyleemphasis{value}{]}{]} +{[}\sphinxstylestrong{\textendash{}request\sphinxhyphen{}pac} | \sphinxstylestrong{\textendash{}no\sphinxhyphen{}request\sphinxhyphen{}pac}{]} +{[}\sphinxstyleemphasis{principal}{]} + + +\subsection{DESCRIPTION} +\label{\detokenize{user/user_commands/kinit:description}} +\sphinxAtStartPar +kinit obtains and caches an initial ticket\sphinxhyphen{}granting ticket for +\sphinxstyleemphasis{principal}. If \sphinxstyleemphasis{principal} is absent, kinit chooses an appropriate +principal name based on existing credential cache contents or the +local username of the user invoking kinit. Some options modify the +choice of principal name. + + +\subsection{OPTIONS} +\label{\detokenize{user/user_commands/kinit:options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}V}}] \leavevmode +\sphinxAtStartPar +display verbose output. + +\item[{\sphinxstylestrong{\sphinxhyphen{}l} \sphinxstyleemphasis{lifetime}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} string.) Requests a ticket with the lifetime +\sphinxstyleemphasis{lifetime}. + +\sphinxAtStartPar +For example, \sphinxcode{\sphinxupquote{kinit \sphinxhyphen{}l 5:30}} or \sphinxcode{\sphinxupquote{kinit \sphinxhyphen{}l 5h30m}}. + +\sphinxAtStartPar +If the \sphinxstylestrong{\sphinxhyphen{}l} option is not specified, the default ticket lifetime +(configured by each site) is used. Specifying a ticket lifetime +longer than the maximum ticket lifetime (configured by each site) +will not override the configured maximum ticket lifetime. + +\item[{\sphinxstylestrong{\sphinxhyphen{}s} \sphinxstyleemphasis{start\_time}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} string.) Requests a postdated ticket. Postdated +tickets are issued with the \sphinxstylestrong{invalid} flag set, and need to be +resubmitted to the KDC for validation before use. + +\sphinxAtStartPar +\sphinxstyleemphasis{start\_time} specifies the duration of the delay before the ticket +can become valid. + +\item[{\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{renewable\_life}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} string.) Requests renewable tickets, with a total +lifetime of \sphinxstyleemphasis{renewable\_life}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}f}}] \leavevmode +\sphinxAtStartPar +requests forwardable tickets. + +\item[{\sphinxstylestrong{\sphinxhyphen{}F}}] \leavevmode +\sphinxAtStartPar +requests non\sphinxhyphen{}forwardable tickets. + +\item[{\sphinxstylestrong{\sphinxhyphen{}p}}] \leavevmode +\sphinxAtStartPar +requests proxiable tickets. + +\item[{\sphinxstylestrong{\sphinxhyphen{}P}}] \leavevmode +\sphinxAtStartPar +requests non\sphinxhyphen{}proxiable tickets. + +\item[{\sphinxstylestrong{\sphinxhyphen{}a}}] \leavevmode +\sphinxAtStartPar +requests tickets restricted to the host’s local address{[}es{]}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}A}}] \leavevmode +\sphinxAtStartPar +requests tickets not restricted by address. + +\item[{\sphinxstylestrong{\sphinxhyphen{}C}}] \leavevmode +\sphinxAtStartPar +requests canonicalization of the principal name, and allows the +KDC to reply with a different client principal from the one +requested. + +\item[{\sphinxstylestrong{\sphinxhyphen{}E}}] \leavevmode +\sphinxAtStartPar +treats the principal name as an enterprise name. + +\item[{\sphinxstylestrong{\sphinxhyphen{}v}}] \leavevmode +\sphinxAtStartPar +requests that the ticket\sphinxhyphen{}granting ticket in the cache (with the +\sphinxstylestrong{invalid} flag set) be passed to the KDC for validation. If the +ticket is within its requested time range, the cache is replaced +with the validated ticket. + +\item[{\sphinxstylestrong{\sphinxhyphen{}R}}] \leavevmode +\sphinxAtStartPar +requests renewal of the ticket\sphinxhyphen{}granting ticket. Note that an +expired ticket cannot be renewed, even if the ticket is still +within its renewable life. + +\sphinxAtStartPar +Note that renewable tickets that have expired as reported by +{\hyperref[\detokenize{user/user_commands/klist:klist-1}]{\sphinxcrossref{\DUrole{std,std-ref}{klist}}}} may sometimes be renewed using this option, +because the KDC applies a grace period to account for client\sphinxhyphen{}KDC +clock skew. See \DUrole{xref,std,std-ref}{krb5.conf(5)} \sphinxstylestrong{clockskew} setting. + +\item[{\sphinxstylestrong{\sphinxhyphen{}k} {[}\sphinxstylestrong{\sphinxhyphen{}i} | \sphinxstylestrong{\sphinxhyphen{}t} \sphinxstyleemphasis{keytab\_file}{]}}] \leavevmode +\sphinxAtStartPar +requests a ticket, obtained from a key in the local host’s keytab. +The location of the keytab may be specified with the \sphinxstylestrong{\sphinxhyphen{}t} +\sphinxstyleemphasis{keytab\_file} option, or with the \sphinxstylestrong{\sphinxhyphen{}i} option to specify the use +of the default client keytab; otherwise the default keytab will be +used. By default, a host ticket for the local host is requested, +but any principal may be specified. On a KDC, the special keytab +location \sphinxcode{\sphinxupquote{KDB:}} can be used to indicate that kinit should open +the KDC database and look up the key directly. This permits an +administrator to obtain tickets as any principal that supports +authentication based on the key. + +\item[{\sphinxstylestrong{\sphinxhyphen{}n}}] \leavevmode +\sphinxAtStartPar +Requests anonymous processing. Two types of anonymous principals +are supported. + +\sphinxAtStartPar +For fully anonymous Kerberos, configure pkinit on the KDC and +configure \sphinxstylestrong{pkinit\_anchors} in the client’s \DUrole{xref,std,std-ref}{krb5.conf(5)}. +Then use the \sphinxstylestrong{\sphinxhyphen{}n} option with a principal of the form \sphinxcode{\sphinxupquote{@REALM}} +(an empty principal name followed by the at\sphinxhyphen{}sign and a realm +name). If permitted by the KDC, an anonymous ticket will be +returned. + +\sphinxAtStartPar +A second form of anonymous tickets is supported; these +realm\sphinxhyphen{}exposed tickets hide the identity of the client but not the +client’s realm. For this mode, use \sphinxcode{\sphinxupquote{kinit \sphinxhyphen{}n}} with a normal +principal name. If supported by the KDC, the principal (but not +realm) will be replaced by the anonymous principal. + +\sphinxAtStartPar +As of release 1.8, the MIT Kerberos KDC only supports fully +anonymous operation. + +\end{description} + +\sphinxAtStartPar +\sphinxstylestrong{\sphinxhyphen{}I} \sphinxstyleemphasis{input\_ccache} +\begin{quote} + +\sphinxAtStartPar +Specifies the name of a credentials cache that already contains a +ticket. When obtaining that ticket, if information about how that +ticket was obtained was also stored to the cache, that information +will be used to affect how new credentials are obtained, including +preselecting the same methods of authenticating to the KDC. +\end{quote} +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}T} \sphinxstyleemphasis{armor\_ccache}}] \leavevmode +\sphinxAtStartPar +Specifies the name of a credentials cache that already contains a +ticket. If supported by the KDC, this cache will be used to armor +the request, preventing offline dictionary attacks and allowing +the use of additional preauthentication mechanisms. Armoring also +makes sure that the response from the KDC is not modified in +transit. + +\item[{\sphinxstylestrong{\sphinxhyphen{}c} \sphinxstyleemphasis{cache\_name}}] \leavevmode +\sphinxAtStartPar +use \sphinxstyleemphasis{cache\_name} as the Kerberos 5 credentials (ticket) cache +location. If this option is not used, the default cache location +is used. + +\sphinxAtStartPar +The default cache location may vary between systems. If the +\sphinxstylestrong{KRB5CCNAME} environment variable is set, its value is used to +locate the default cache. If a principal name is specified and +the type of the default cache supports a collection (such as the +DIR type), an existing cache containing credentials for the +principal is selected or a new one is created and becomes the new +primary cache. Otherwise, any existing contents of the default +cache are destroyed by kinit. + +\item[{\sphinxstylestrong{\sphinxhyphen{}S} \sphinxstyleemphasis{service\_name}}] \leavevmode +\sphinxAtStartPar +specify an alternate service name to use when getting initial +tickets. + +\item[{\sphinxstylestrong{\sphinxhyphen{}X} \sphinxstyleemphasis{attribute}{[}=\sphinxstyleemphasis{value}{]}}] \leavevmode +\sphinxAtStartPar +specify a pre\sphinxhyphen{}authentication \sphinxstyleemphasis{attribute} and \sphinxstyleemphasis{value} to be +interpreted by pre\sphinxhyphen{}authentication modules. The acceptable +attribute and value values vary from module to module. This +option may be specified multiple times to specify multiple +attributes. If no value is specified, it is assumed to be “yes”. + +\sphinxAtStartPar +The following attributes are recognized by the PKINIT +pre\sphinxhyphen{}authentication mechanism: +\begin{description} +\item[{\sphinxstylestrong{X509\_user\_identity}=\sphinxstyleemphasis{value}}] \leavevmode +\sphinxAtStartPar +specify where to find user’s X509 identity information + +\item[{\sphinxstylestrong{X509\_anchors}=\sphinxstyleemphasis{value}}] \leavevmode +\sphinxAtStartPar +specify where to find trusted X509 anchor information + +\item[{\sphinxstylestrong{flag\_RSA\_PROTOCOL}{[}\sphinxstylestrong{=yes}{]}}] \leavevmode +\sphinxAtStartPar +specify use of RSA, rather than the default Diffie\sphinxhyphen{}Hellman +protocol + +\item[{\sphinxstylestrong{disable\_freshness}{[}\sphinxstylestrong{=yes}{]}}] \leavevmode +\sphinxAtStartPar +disable sending freshness tokens (for testing purposes only) + +\end{description} + +\item[{\sphinxstylestrong{\textendash{}request\sphinxhyphen{}pac} | \sphinxstylestrong{\textendash{}no\sphinxhyphen{}request\sphinxhyphen{}pac}}] \leavevmode +\sphinxAtStartPar +mutually exclusive. If \sphinxstylestrong{\textendash{}request\sphinxhyphen{}pac} is set, ask the KDC to +include a PAC in authdata; if \sphinxstylestrong{\textendash{}no\sphinxhyphen{}request\sphinxhyphen{}pac} is set, ask the +KDC not to include a PAC; if neither are set, the KDC will follow +its default, which is typically is to include a PAC if doing so is +supported. + +\end{description} + + +\subsection{ENVIRONMENT} +\label{\detokenize{user/user_commands/kinit:environment}} +\sphinxAtStartPar +See {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} for a description of Kerberos environment +variables. + + +\subsection{FILES} +\label{\detokenize{user/user_commands/kinit:files}}\begin{description} +\item[{\DUrole{xref,std,std-ref}{DEFCCNAME}}] \leavevmode +\sphinxAtStartPar +default location of Kerberos 5 credentials cache + +\item[{\DUrole{xref,std,std-ref}{DEFKTNAME}}] \leavevmode +\sphinxAtStartPar +default location for the local host’s keytab. + +\end{description} + + +\subsection{SEE ALSO} +\label{\detokenize{user/user_commands/kinit:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{user/user_commands/klist:klist-1}]{\sphinxcrossref{\DUrole{std,std-ref}{klist}}}}, {\hyperref[\detokenize{user/user_commands/kdestroy:kdestroy-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kdestroy}}}}, {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} + + +\section{klist} +\label{\detokenize{user/user_commands/klist:klist}}\label{\detokenize{user/user_commands/klist:klist-1}}\label{\detokenize{user/user_commands/klist::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{user/user_commands/klist:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{klist} +{[}\sphinxstylestrong{\sphinxhyphen{}e}{]} +{[}{[}\sphinxstylestrong{\sphinxhyphen{}c}{]} {[}\sphinxstylestrong{\sphinxhyphen{}l}{]} {[}\sphinxstylestrong{\sphinxhyphen{}A}{]} {[}\sphinxstylestrong{\sphinxhyphen{}f}{]} {[}\sphinxstylestrong{\sphinxhyphen{}s}{]} {[}\sphinxstylestrong{\sphinxhyphen{}a} {[}\sphinxstylestrong{\sphinxhyphen{}n}{]}{]}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}C}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}k} {[}\sphinxstylestrong{\sphinxhyphen{}i}{]} {[}\sphinxstylestrong{\sphinxhyphen{}t}{]} {[}\sphinxstylestrong{\sphinxhyphen{}K}{]}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}V}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}d}{]} +{[}\sphinxstyleemphasis{cache\_name}|\sphinxstyleemphasis{keytab\_name}{]} + + +\subsection{DESCRIPTION} +\label{\detokenize{user/user_commands/klist:description}} +\sphinxAtStartPar +klist lists the Kerberos principal and Kerberos tickets held in a +credentials cache, or the keys held in a keytab file. + + +\subsection{OPTIONS} +\label{\detokenize{user/user_commands/klist:options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}e}}] \leavevmode +\sphinxAtStartPar +Displays the encryption types of the session key and the ticket +for each credential in the credential cache, or each key in the +keytab file. + +\item[{\sphinxstylestrong{\sphinxhyphen{}l}}] \leavevmode +\sphinxAtStartPar +If a cache collection is available, displays a table summarizing +the caches present in the collection. + +\item[{\sphinxstylestrong{\sphinxhyphen{}A}}] \leavevmode +\sphinxAtStartPar +If a cache collection is available, displays the contents of all +of the caches in the collection. + +\item[{\sphinxstylestrong{\sphinxhyphen{}c}}] \leavevmode +\sphinxAtStartPar +List tickets held in a credentials cache. This is the default if +neither \sphinxstylestrong{\sphinxhyphen{}c} nor \sphinxstylestrong{\sphinxhyphen{}k} is specified. + +\item[{\sphinxstylestrong{\sphinxhyphen{}f}}] \leavevmode +\sphinxAtStartPar +Shows the flags present in the credentials, using the following +abbreviations: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{F} \PYG{n}{Forwardable} +\PYG{n}{f} \PYG{n}{forwarded} +\PYG{n}{P} \PYG{n}{Proxiable} +\PYG{n}{p} \PYG{n}{proxy} +\PYG{n}{D} \PYG{n}{postDateable} +\PYG{n}{d} \PYG{n}{postdated} +\PYG{n}{R} \PYG{n}{Renewable} +\PYG{n}{I} \PYG{n}{Initial} +\PYG{n}{i} \PYG{n}{invalid} +\PYG{n}{H} \PYG{n}{Hardware} \PYG{n}{authenticated} +\PYG{n}{A} \PYG{n}{preAuthenticated} +\PYG{n}{T} \PYG{n}{Transit} \PYG{n}{policy} \PYG{n}{checked} +\PYG{n}{O} \PYG{n}{Okay} \PYG{k}{as} \PYG{n}{delegate} +\PYG{n}{a} \PYG{n}{anonymous} +\end{sphinxVerbatim} + +\item[{\sphinxstylestrong{\sphinxhyphen{}s}}] \leavevmode +\sphinxAtStartPar +Causes klist to run silently (produce no output). klist will exit +with status 1 if the credentials cache cannot be read or is +expired, and with status 0 otherwise. + +\item[{\sphinxstylestrong{\sphinxhyphen{}a}}] \leavevmode +\sphinxAtStartPar +Display list of addresses in credentials. + +\item[{\sphinxstylestrong{\sphinxhyphen{}n}}] \leavevmode +\sphinxAtStartPar +Show numeric addresses instead of reverse\sphinxhyphen{}resolving addresses. + +\item[{\sphinxstylestrong{\sphinxhyphen{}C}}] \leavevmode +\sphinxAtStartPar +List configuration data that has been stored in the credentials +cache when klist encounters it. By default, configuration data +is not listed. + +\item[{\sphinxstylestrong{\sphinxhyphen{}k}}] \leavevmode +\sphinxAtStartPar +List keys held in a keytab file. + +\item[{\sphinxstylestrong{\sphinxhyphen{}i}}] \leavevmode +\sphinxAtStartPar +In combination with \sphinxstylestrong{\sphinxhyphen{}k}, defaults to using the default client +keytab instead of the default acceptor keytab, if no name is +given. + +\item[{\sphinxstylestrong{\sphinxhyphen{}t}}] \leavevmode +\sphinxAtStartPar +Display the time entry timestamps for each keytab entry in the +keytab file. + +\item[{\sphinxstylestrong{\sphinxhyphen{}K}}] \leavevmode +\sphinxAtStartPar +Display the value of the encryption key in each keytab entry in +the keytab file. + +\item[{\sphinxstylestrong{\sphinxhyphen{}d}}] \leavevmode +\sphinxAtStartPar +Display the authdata types (if any) for each entry. + +\item[{\sphinxstylestrong{\sphinxhyphen{}V}}] \leavevmode +\sphinxAtStartPar +Display the Kerberos version number and exit. + +\end{description} + +\sphinxAtStartPar +If \sphinxstyleemphasis{cache\_name} or \sphinxstyleemphasis{keytab\_name} is not specified, klist will display +the credentials in the default credentials cache or keytab file as +appropriate. If the \sphinxstylestrong{KRB5CCNAME} environment variable is set, its +value is used to locate the default ticket cache. + + +\subsection{ENVIRONMENT} +\label{\detokenize{user/user_commands/klist:environment}} +\sphinxAtStartPar +See {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} for a description of Kerberos environment +variables. + + +\subsection{FILES} +\label{\detokenize{user/user_commands/klist:files}}\begin{description} +\item[{\DUrole{xref,std,std-ref}{DEFCCNAME}}] \leavevmode +\sphinxAtStartPar +Default location of Kerberos 5 credentials cache + +\item[{\DUrole{xref,std,std-ref}{DEFKTNAME}}] \leavevmode +\sphinxAtStartPar +Default location for the local host’s keytab file. + +\end{description} + + +\subsection{SEE ALSO} +\label{\detokenize{user/user_commands/klist:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{user/user_commands/kinit:kinit-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kinit}}}}, {\hyperref[\detokenize{user/user_commands/kdestroy:kdestroy-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kdestroy}}}}, {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} + + +\section{kpasswd} +\label{\detokenize{user/user_commands/kpasswd:kpasswd}}\label{\detokenize{user/user_commands/kpasswd:kpasswd-1}}\label{\detokenize{user/user_commands/kpasswd::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{user/user_commands/kpasswd:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{kpasswd} {[}\sphinxstyleemphasis{principal}{]} + + +\subsection{DESCRIPTION} +\label{\detokenize{user/user_commands/kpasswd:description}} +\sphinxAtStartPar +The kpasswd command is used to change a Kerberos principal’s password. +kpasswd first prompts for the current Kerberos password, then prompts +the user twice for the new password, and the password is changed. + +\sphinxAtStartPar +If the principal is governed by a policy that specifies the length +and/or number of character classes required in the new password, the +new password must conform to the policy. (The five character classes +are lower case, upper case, numbers, punctuation, and all other +characters.) + + +\subsection{OPTIONS} +\label{\detokenize{user/user_commands/kpasswd:options}}\begin{description} +\item[{\sphinxstyleemphasis{principal}}] \leavevmode +\sphinxAtStartPar +Change the password for the Kerberos principal principal. +Otherwise, kpasswd uses the principal name from an existing ccache +if there is one; if not, the principal is derived from the +identity of the user invoking the kpasswd command. + +\end{description} + + +\subsection{ENVIRONMENT} +\label{\detokenize{user/user_commands/kpasswd:environment}} +\sphinxAtStartPar +See {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{user/user_commands/kpasswd:see-also}} +\sphinxAtStartPar +\DUrole{xref,std,std-ref}{kadmin(1)}, \DUrole{xref,std,std-ref}{kadmind(8)}, {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} + + +\section{krb5\sphinxhyphen{}config} +\label{\detokenize{user/user_commands/krb5-config:krb5-config}}\label{\detokenize{user/user_commands/krb5-config:krb5-config-1}}\label{\detokenize{user/user_commands/krb5-config::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{user/user_commands/krb5-config:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{krb5\sphinxhyphen{}config} +{[}\sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}help} | \sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}all} | \sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}version} | \sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}vendor} | \sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}prefix} | \sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}exec\sphinxhyphen{}prefix} | \sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}defccname} | \sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}defktname} | \sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}defcktname} | \sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}cflags} | \sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}libs} {[}\sphinxstyleemphasis{libraries}{]}{]} + + +\subsection{DESCRIPTION} +\label{\detokenize{user/user_commands/krb5-config:description}} +\sphinxAtStartPar +krb5\sphinxhyphen{}config tells the application programmer what flags to use to compile +and link programs against the installed Kerberos libraries. + + +\subsection{OPTIONS} +\label{\detokenize{user/user_commands/krb5-config:options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}help}}] \leavevmode +\sphinxAtStartPar +prints a usage message. This is the default behavior when no options +are specified. + +\item[{\sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}all}}] \leavevmode +\sphinxAtStartPar +prints the version, vendor, prefix, and exec\sphinxhyphen{}prefix. + +\item[{\sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}version}}] \leavevmode +\sphinxAtStartPar +prints the version number of the Kerberos installation. + +\item[{\sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}vendor}}] \leavevmode +\sphinxAtStartPar +prints the name of the vendor of the Kerberos installation. + +\item[{\sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}prefix}}] \leavevmode +\sphinxAtStartPar +prints the prefix for which the Kerberos installation was built. + +\item[{\sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}exec\sphinxhyphen{}prefix}}] \leavevmode +\sphinxAtStartPar +prints the prefix for executables for which the Kerberos installation +was built. + +\item[{\sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}defccname}}] \leavevmode +\sphinxAtStartPar +prints the built\sphinxhyphen{}in default credentials cache location. + +\item[{\sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}defktname}}] \leavevmode +\sphinxAtStartPar +prints the built\sphinxhyphen{}in default keytab location. + +\item[{\sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}defcktname}}] \leavevmode +\sphinxAtStartPar +prints the built\sphinxhyphen{}in default client (initiator) keytab location. + +\item[{\sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}cflags}}] \leavevmode +\sphinxAtStartPar +prints the compilation flags used to build the Kerberos installation. + +\item[{\sphinxstylestrong{\sphinxhyphen{}}\sphinxstylestrong{\sphinxhyphen{}libs} {[}\sphinxstyleemphasis{library}{]}}] \leavevmode +\sphinxAtStartPar +prints the compiler options needed to link against \sphinxstyleemphasis{library}. +Allowed values for \sphinxstyleemphasis{library} are: + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +krb5 +& +\sphinxAtStartPar +Kerberos 5 applications (default) +\\ +\hline +\sphinxAtStartPar +gssapi +& +\sphinxAtStartPar +GSSAPI applications with Kerberos 5 bindings +\\ +\hline +\sphinxAtStartPar +kadm\sphinxhyphen{}client +& +\sphinxAtStartPar +Kadmin client +\\ +\hline +\sphinxAtStartPar +kadm\sphinxhyphen{}server +& +\sphinxAtStartPar +Kadmin server +\\ +\hline +\sphinxAtStartPar +kdb +& +\sphinxAtStartPar +Applications that access the Kerberos database +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + +\end{description} + + +\subsection{EXAMPLES} +\label{\detokenize{user/user_commands/krb5-config:examples}} +\sphinxAtStartPar +krb5\sphinxhyphen{}config is particularly useful for compiling against a Kerberos +installation that was installed in a non\sphinxhyphen{}standard location. For example, +a Kerberos installation that is installed in \sphinxcode{\sphinxupquote{/opt/krb5/}} but uses +libraries in \sphinxcode{\sphinxupquote{/usr/local/lib/}} for text localization would produce +the following output: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{shell}\PYG{o}{\PYGZpc{}} \PYG{n}{krb5}\PYG{o}{\PYGZhy{}}\PYG{n}{config} \PYG{o}{\PYGZhy{}}\PYG{o}{\PYGZhy{}}\PYG{n}{libs} \PYG{n}{krb5} +\PYG{o}{\PYGZhy{}}\PYG{n}{L}\PYG{o}{/}\PYG{n}{opt}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{/}\PYG{n}{lib} \PYG{o}{\PYGZhy{}}\PYG{n}{Wl}\PYG{p}{,}\PYG{o}{\PYGZhy{}}\PYG{n}{rpath} \PYG{o}{\PYGZhy{}}\PYG{n}{Wl}\PYG{p}{,}\PYG{o}{/}\PYG{n}{opt}\PYG{o}{/}\PYG{n}{krb5}\PYG{o}{/}\PYG{n}{lib} \PYG{o}{\PYGZhy{}}\PYG{n}{L}\PYG{o}{/}\PYG{n}{usr}\PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{lib} \PYG{o}{\PYGZhy{}}\PYG{n}{lkrb5} \PYG{o}{\PYGZhy{}}\PYG{n}{lk5crypto} \PYG{o}{\PYGZhy{}}\PYG{n}{lcom\PYGZus{}err} +\end{sphinxVerbatim} + + +\subsection{SEE ALSO} +\label{\detokenize{user/user_commands/krb5-config:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}}, cc(1) + + +\section{ksu} +\label{\detokenize{user/user_commands/ksu:ksu}}\label{\detokenize{user/user_commands/ksu:ksu-1}}\label{\detokenize{user/user_commands/ksu::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{user/user_commands/ksu:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{ksu} +{[} \sphinxstyleemphasis{target\_user} {]} +{[} \sphinxstylestrong{\sphinxhyphen{}n} \sphinxstyleemphasis{target\_principal\_name} {]} +{[} \sphinxstylestrong{\sphinxhyphen{}c} \sphinxstyleemphasis{source\_cache\_name} {]} +{[} \sphinxstylestrong{\sphinxhyphen{}k} {]} +{[} \sphinxstylestrong{\sphinxhyphen{}r} time {]} +{[} \sphinxstylestrong{\sphinxhyphen{}p} | \sphinxstylestrong{\sphinxhyphen{}P}{]} +{[} \sphinxstylestrong{\sphinxhyphen{}f} | \sphinxstylestrong{\sphinxhyphen{}F}{]} +{[} \sphinxstylestrong{\sphinxhyphen{}l} \sphinxstyleemphasis{lifetime} {]} +{[} \sphinxstylestrong{\sphinxhyphen{}z | Z} {]} +{[} \sphinxstylestrong{\sphinxhyphen{}q} {]} +{[} \sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{command} {[} args … {]} {]} {[} \sphinxstylestrong{\sphinxhyphen{}a} {[} args … {]} {]} + + +\subsection{REQUIREMENTS} +\label{\detokenize{user/user_commands/ksu:requirements}} +\sphinxAtStartPar +Must have Kerberos version 5 installed to compile ksu. Must have a +Kerberos version 5 server running to use ksu. + + +\subsection{DESCRIPTION} +\label{\detokenize{user/user_commands/ksu:description}} +\sphinxAtStartPar +ksu is a Kerberized version of the su program that has two missions: +one is to securely change the real and effective user ID to that of +the target user, and the other is to create a new security context. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +For the sake of clarity, all references to and attributes of +the user invoking the program will start with “source” +(e.g., “source user”, “source cache”, etc.). + +\sphinxAtStartPar +Likewise, all references to and attributes of the target +account will start with “target”. +\end{sphinxadmonition} + + +\subsection{AUTHENTICATION} +\label{\detokenize{user/user_commands/ksu:authentication}} +\sphinxAtStartPar +To fulfill the first mission, ksu operates in two phases: +authentication and authorization. Resolving the target principal name +is the first step in authentication. The user can either specify his +principal name with the \sphinxstylestrong{\sphinxhyphen{}n} option (e.g., \sphinxcode{\sphinxupquote{\sphinxhyphen{}n jqpublic@USC.EDU}}) +or a default principal name will be assigned using a heuristic +described in the OPTIONS section (see \sphinxstylestrong{\sphinxhyphen{}n} option). The target user +name must be the first argument to ksu; if not specified root is the +default. If \sphinxcode{\sphinxupquote{.}} is specified then the target user will be the +source user (e.g., \sphinxcode{\sphinxupquote{ksu .}}). If the source user is root or the +target user is the source user, no authentication or authorization +takes place. Otherwise, ksu looks for an appropriate Kerberos ticket +in the source cache. + +\sphinxAtStartPar +The ticket can either be for the end\sphinxhyphen{}server or a ticket granting +ticket (TGT) for the target principal’s realm. If the ticket for the +end\sphinxhyphen{}server is already in the cache, it’s decrypted and verified. If +it’s not in the cache but the TGT is, the TGT is used to obtain the +ticket for the end\sphinxhyphen{}server. The end\sphinxhyphen{}server ticket is then verified. +If neither ticket is in the cache, but ksu is compiled with the +\sphinxstylestrong{GET\_TGT\_VIA\_PASSWD} define, the user will be prompted for a +Kerberos password which will then be used to get a TGT. If the user +is logged in remotely and does not have a secure channel, the password +may be exposed. If neither ticket is in the cache and +\sphinxstylestrong{GET\_TGT\_VIA\_PASSWD} is not defined, authentication fails. + + +\subsection{AUTHORIZATION} +\label{\detokenize{user/user_commands/ksu:authorization}} +\sphinxAtStartPar +This section describes authorization of the source user when ksu is +invoked without the \sphinxstylestrong{\sphinxhyphen{}e} option. For a description of the \sphinxstylestrong{\sphinxhyphen{}e} +option, see the OPTIONS section. + +\sphinxAtStartPar +Upon successful authentication, ksu checks whether the target +principal is authorized to access the target account. In the target +user’s home directory, ksu attempts to access two authorization files: +{\hyperref[\detokenize{user/user_config/k5login:k5login-5}]{\sphinxcrossref{\DUrole{std,std-ref}{.k5login}}}} and .k5users. In the .k5login file each line +contains the name of a principal that is authorized to access the +account. + +\sphinxAtStartPar +For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{jqpublic}\PYG{n+nd}{@USC}\PYG{o}{.}\PYG{n}{EDU} +\PYG{n}{jqpublic}\PYG{o}{/}\PYG{n}{secure}\PYG{n+nd}{@USC}\PYG{o}{.}\PYG{n}{EDU} +\PYG{n}{jqpublic}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@USC}\PYG{o}{.}\PYG{n}{EDU} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The format of .k5users is the same, except the principal name may be +followed by a list of commands that the principal is authorized to +execute (see the \sphinxstylestrong{\sphinxhyphen{}e} option in the OPTIONS section for details). + +\sphinxAtStartPar +Thus if the target principal name is found in the .k5login file the +source user is authorized to access the target account. Otherwise ksu +looks in the .k5users file. If the target principal name is found +without any trailing commands or followed only by \sphinxcode{\sphinxupquote{*}} then the +source user is authorized. If either .k5login or .k5users exist but +an appropriate entry for the target principal does not exist then +access is denied. If neither file exists then the principal will be +granted access to the account according to the aname\sphinxhyphen{}\textgreater{}lname mapping +rules. Otherwise, authorization fails. + + +\subsection{EXECUTION OF THE TARGET SHELL} +\label{\detokenize{user/user_commands/ksu:execution-of-the-target-shell}} +\sphinxAtStartPar +Upon successful authentication and authorization, ksu proceeds in a +similar fashion to su. The environment is unmodified with the +exception of USER, HOME and SHELL variables. If the target user is +not root, USER gets set to the target user name. Otherwise USER +remains unchanged. Both HOME and SHELL are set to the target login’s +default values. In addition, the environment variable \sphinxstylestrong{KRB5CCNAME} +gets set to the name of the target cache. The real and effective user +ID are changed to that of the target user. The target user’s shell is +then invoked (the shell name is specified in the password file). Upon +termination of the shell, ksu deletes the target cache (unless ksu is +invoked with the \sphinxstylestrong{\sphinxhyphen{}k} option). This is implemented by first doing a +fork and then an exec, instead of just exec, as done by su. + + +\subsection{CREATING A NEW SECURITY CONTEXT} +\label{\detokenize{user/user_commands/ksu:creating-a-new-security-context}} +\sphinxAtStartPar +ksu can be used to create a new security context for the target +program (either the target shell, or command specified via the \sphinxstylestrong{\sphinxhyphen{}e} +option). The target program inherits a set of credentials from the +source user. By default, this set includes all of the credentials in +the source cache plus any additional credentials obtained during +authentication. The source user is able to limit the credentials in +this set by using \sphinxstylestrong{\sphinxhyphen{}z} or \sphinxstylestrong{\sphinxhyphen{}Z} option. \sphinxstylestrong{\sphinxhyphen{}z} restricts the copy +of tickets from the source cache to the target cache to only the +tickets where client == the target principal name. The \sphinxstylestrong{\sphinxhyphen{}Z} option +provides the target user with a fresh target cache (no creds in the +cache). Note that for security reasons, when the source user is root +and target user is non\sphinxhyphen{}root, \sphinxstylestrong{\sphinxhyphen{}z} option is the default mode of +operation. + +\sphinxAtStartPar +While no authentication takes place if the source user is root or is +the same as the target user, additional tickets can still be obtained +for the target cache. If \sphinxstylestrong{\sphinxhyphen{}n} is specified and no credentials can +be copied to the target cache, the source user is prompted for a +Kerberos password (unless \sphinxstylestrong{\sphinxhyphen{}Z} specified or \sphinxstylestrong{GET\_TGT\_VIA\_PASSWD} +is undefined). If successful, a TGT is obtained from the Kerberos +server and stored in the target cache. Otherwise, if a password is +not provided (user hit return) ksu continues in a normal mode of +operation (the target cache will not contain the desired TGT). If the +wrong password is typed in, ksu fails. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +During authentication, only the tickets that could be +obtained without providing a password are cached in the +source cache. +\end{sphinxadmonition} + + +\subsection{OPTIONS} +\label{\detokenize{user/user_commands/ksu:options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}n} \sphinxstyleemphasis{target\_principal\_name}}] \leavevmode +\sphinxAtStartPar +Specify a Kerberos target principal name. Used in authentication +and authorization phases of ksu. + +\sphinxAtStartPar +If ksu is invoked without \sphinxstylestrong{\sphinxhyphen{}n}, a default principal name is +assigned via the following heuristic: +\begin{itemize} +\item {} +\sphinxAtStartPar +Case 1: source user is non\sphinxhyphen{}root. + +\sphinxAtStartPar +If the target user is the source user the default principal name +is set to the default principal of the source cache. If the +cache does not exist then the default principal name is set to +\sphinxcode{\sphinxupquote{target\_user@local\_realm}}. If the source and target users are +different and neither \sphinxcode{\sphinxupquote{\textasciitilde{}target\_user/.k5users}} nor +\sphinxcode{\sphinxupquote{\textasciitilde{}target\_user/.k5login}} exist then the default principal name +is \sphinxcode{\sphinxupquote{target\_user\_login\_name@local\_realm}}. Otherwise, starting +with the first principal listed below, ksu checks if the +principal is authorized to access the target account and whether +there is a legitimate ticket for that principal in the source +cache. If both conditions are met that principal becomes the +default target principal, otherwise go to the next principal. +\begin{enumerate} +\sphinxsetlistlabels{\alph}{enumi}{enumii}{}{)}% +\item {} +\sphinxAtStartPar +default principal of the source cache + +\item {} +\sphinxAtStartPar +target\_user@local\_realm + +\item {} +\sphinxAtStartPar +source\_user@local\_realm + +\end{enumerate} + +\sphinxAtStartPar +If a\sphinxhyphen{}c fails try any principal for which there is a ticket in +the source cache and that is authorized to access the target +account. If that fails select the first principal that is +authorized to access the target account from the above list. If +none are authorized and ksu is configured with +\sphinxstylestrong{PRINC\_LOOK\_AHEAD} turned on, select the default principal as +follows: + +\sphinxAtStartPar +For each candidate in the above list, select an authorized +principal that has the same realm name and first part of the +principal name equal to the prefix of the candidate. For +example if candidate a) is \sphinxcode{\sphinxupquote{jqpublic@ISI.EDU}} and +\sphinxcode{\sphinxupquote{jqpublic/secure@ISI.EDU}} is authorized to access the target +account then the default principal is set to +\sphinxcode{\sphinxupquote{jqpublic/secure@ISI.EDU}}. + +\item {} +\sphinxAtStartPar +Case 2: source user is root. + +\sphinxAtStartPar +If the target user is non\sphinxhyphen{}root then the default principal name +is \sphinxcode{\sphinxupquote{target\_user@local\_realm}}. Else, if the source cache +exists the default principal name is set to the default +principal of the source cache. If the source cache does not +exist, default principal name is set to \sphinxcode{\sphinxupquote{root\textbackslash{}@local\_realm}}. + +\end{itemize} + +\end{description} + +\sphinxAtStartPar +\sphinxstylestrong{\sphinxhyphen{}c} \sphinxstyleemphasis{source\_cache\_name} +\begin{quote} + +\sphinxAtStartPar +Specify source cache name (e.g., \sphinxcode{\sphinxupquote{\sphinxhyphen{}c FILE:/tmp/my\_cache}}). If +\sphinxstylestrong{\sphinxhyphen{}c} option is not used then the name is obtained from +\sphinxstylestrong{KRB5CCNAME} environment variable. If \sphinxstylestrong{KRB5CCNAME} is not +defined the source cache name is set to \sphinxcode{\sphinxupquote{krb5cc\_\textless{}source uid\textgreater{}}}. +The target cache name is automatically set to \sphinxcode{\sphinxupquote{krb5cc\_\textless{}target +uid\textgreater{}.(gen\_sym())}}, where gen\_sym generates a new number such that +the resulting cache does not already exist. For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{krb5cc\PYGZus{}1984}\PYG{l+m+mf}{.2} +\end{sphinxVerbatim} +\end{quote} +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}k}}] \leavevmode +\sphinxAtStartPar +Do not delete the target cache upon termination of the target +shell or a command (\sphinxstylestrong{\sphinxhyphen{}e} command). Without \sphinxstylestrong{\sphinxhyphen{}k}, ksu deletes +the target cache. + +\item[{\sphinxstylestrong{\sphinxhyphen{}z}}] \leavevmode +\sphinxAtStartPar +Restrict the copy of tickets from the source cache to the target +cache to only the tickets where client == the target principal +name. Use the \sphinxstylestrong{\sphinxhyphen{}n} option if you want the tickets for other then +the default principal. Note that the \sphinxstylestrong{\sphinxhyphen{}z} option is mutually +exclusive with the \sphinxstylestrong{\sphinxhyphen{}Z} option. + +\item[{\sphinxstylestrong{\sphinxhyphen{}Z}}] \leavevmode +\sphinxAtStartPar +Don’t copy any tickets from the source cache to the target cache. +Just create a fresh target cache, where the default principal name +of the cache is initialized to the target principal name. Note +that the \sphinxstylestrong{\sphinxhyphen{}Z} option is mutually exclusive with the \sphinxstylestrong{\sphinxhyphen{}z} +option. + +\item[{\sphinxstylestrong{\sphinxhyphen{}q}}] \leavevmode +\sphinxAtStartPar +Suppress the printing of status messages. + +\end{description} + +\sphinxAtStartPar +Ticket granting ticket options: +\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}l} \sphinxstyleemphasis{lifetime} \sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{time} \sphinxstylestrong{\sphinxhyphen{}p} \sphinxstylestrong{\sphinxhyphen{}P} \sphinxstylestrong{\sphinxhyphen{}f} \sphinxstylestrong{\sphinxhyphen{}F}}] \leavevmode +\sphinxAtStartPar +The ticket granting ticket options only apply to the case where +there are no appropriate tickets in the cache to authenticate the +source user. In this case if ksu is configured to prompt users +for a Kerberos password (\sphinxstylestrong{GET\_TGT\_VIA\_PASSWD} is defined), the +ticket granting ticket options that are specified will be used +when getting a ticket granting ticket from the Kerberos server. + +\item[{\sphinxstylestrong{\sphinxhyphen{}l} \sphinxstyleemphasis{lifetime}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} string.) Specifies the lifetime to be requested +for the ticket; if this option is not specified, the default ticket +lifetime (12 hours) is used instead. + +\item[{\sphinxstylestrong{\sphinxhyphen{}r} \sphinxstyleemphasis{time}}] \leavevmode +\sphinxAtStartPar +(\DUrole{xref,std,std-ref}{duration} string.) Specifies that the \sphinxstylestrong{renewable} option +should be requested for the ticket, and specifies the desired +total lifetime of the ticket. + +\item[{\sphinxstylestrong{\sphinxhyphen{}p}}] \leavevmode +\sphinxAtStartPar +specifies that the \sphinxstylestrong{proxiable} option should be requested for +the ticket. + +\item[{\sphinxstylestrong{\sphinxhyphen{}P}}] \leavevmode +\sphinxAtStartPar +specifies that the \sphinxstylestrong{proxiable} option should not be requested +for the ticket, even if the default configuration is to ask for +proxiable tickets. + +\item[{\sphinxstylestrong{\sphinxhyphen{}f}}] \leavevmode +\sphinxAtStartPar +option specifies that the \sphinxstylestrong{forwardable} option should be +requested for the ticket. + +\item[{\sphinxstylestrong{\sphinxhyphen{}F}}] \leavevmode +\sphinxAtStartPar +option specifies that the \sphinxstylestrong{forwardable} option should not be +requested for the ticket, even if the default configuration is to +ask for forwardable tickets. + +\item[{\sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{command} {[}\sphinxstyleemphasis{args} …{]}}] \leavevmode +\sphinxAtStartPar +ksu proceeds exactly the same as if it was invoked without the +\sphinxstylestrong{\sphinxhyphen{}e} option, except instead of executing the target shell, ksu +executes the specified command. Example of usage: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{ksu} \PYG{n}{bob} \PYG{o}{\PYGZhy{}}\PYG{n}{e} \PYG{n}{ls} \PYG{o}{\PYGZhy{}}\PYG{n}{lag} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The authorization algorithm for \sphinxstylestrong{\sphinxhyphen{}e} is as follows: + +\sphinxAtStartPar +If the source user is root or source user == target user, no +authorization takes place and the command is executed. If source +user id != 0, and \sphinxcode{\sphinxupquote{\textasciitilde{}target\_user/.k5users}} file does not exist, +authorization fails. Otherwise, \sphinxcode{\sphinxupquote{\textasciitilde{}target\_user/.k5users}} file +must have an appropriate entry for target principal to get +authorized. + +\sphinxAtStartPar +The .k5users file format: + +\sphinxAtStartPar +A single principal entry on each line that may be followed by a +list of commands that the principal is authorized to execute. A +principal name followed by a \sphinxcode{\sphinxupquote{*}} means that the user is +authorized to execute any command. Thus, in the following +example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{jqpublic}\PYG{n+nd}{@USC}\PYG{o}{.}\PYG{n}{EDU} \PYG{n}{ls} \PYG{n}{mail} \PYG{o}{/}\PYG{n}{local}\PYG{o}{/}\PYG{n}{kerberos}\PYG{o}{/}\PYG{n}{klist} +\PYG{n}{jqpublic}\PYG{o}{/}\PYG{n}{secure}\PYG{n+nd}{@USC}\PYG{o}{.}\PYG{n}{EDU} \PYG{o}{*} +\PYG{n}{jqpublic}\PYG{o}{/}\PYG{n}{admin}\PYG{n+nd}{@USC}\PYG{o}{.}\PYG{n}{EDU} +\end{sphinxVerbatim} + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{jqpublic@USC.EDU}} is only authorized to execute \sphinxcode{\sphinxupquote{ls}}, +\sphinxcode{\sphinxupquote{mail}} and \sphinxcode{\sphinxupquote{klist}} commands. \sphinxcode{\sphinxupquote{jqpublic/secure@USC.EDU}} is +authorized to execute any command. \sphinxcode{\sphinxupquote{jqpublic/admin@USC.EDU}} is +not authorized to execute any command. Note, that +\sphinxcode{\sphinxupquote{jqpublic/admin@USC.EDU}} is authorized to execute the target +shell (regular ksu, without the \sphinxstylestrong{\sphinxhyphen{}e} option) but +\sphinxcode{\sphinxupquote{jqpublic@USC.EDU}} is not. + +\sphinxAtStartPar +The commands listed after the principal name must be either a full +path names or just the program name. In the second case, +\sphinxstylestrong{CMD\_PATH} specifying the location of authorized programs must +be defined at the compilation time of ksu. Which command gets +executed? + +\sphinxAtStartPar +If the source user is root or the target user is the source user +or the user is authorized to execute any command (\sphinxcode{\sphinxupquote{*}} entry) +then command can be either a full or a relative path leading to +the target program. Otherwise, the user must specify either a +full path or just the program name. + +\item[{\sphinxstylestrong{\sphinxhyphen{}a} \sphinxstyleemphasis{args}}] \leavevmode +\sphinxAtStartPar +Specify arguments to be passed to the target shell. Note that all +flags and parameters following \sphinxhyphen{}a will be passed to the shell, +thus all options intended for ksu must precede \sphinxstylestrong{\sphinxhyphen{}a}. + +\sphinxAtStartPar +The \sphinxstylestrong{\sphinxhyphen{}a} option can be used to simulate the \sphinxstylestrong{\sphinxhyphen{}e} option if +used as follows: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{o}{\PYGZhy{}}\PYG{n}{a} \PYG{o}{\PYGZhy{}}\PYG{n}{c} \PYG{p}{[}\PYG{n}{command} \PYG{p}{[}\PYG{n}{arguments}\PYG{p}{]}\PYG{p}{]}\PYG{o}{.} +\end{sphinxVerbatim} + +\sphinxAtStartPar +\sphinxstylestrong{\sphinxhyphen{}c} is interpreted by the c\sphinxhyphen{}shell to execute the command. + +\end{description} + + +\subsection{INSTALLATION INSTRUCTIONS} +\label{\detokenize{user/user_commands/ksu:installation-instructions}} +\sphinxAtStartPar +ksu can be compiled with the following four flags: +\begin{description} +\item[{\sphinxstylestrong{GET\_TGT\_VIA\_PASSWD}}] \leavevmode +\sphinxAtStartPar +In case no appropriate tickets are found in the source cache, the +user will be prompted for a Kerberos password. The password is +then used to get a ticket granting ticket from the Kerberos +server. The danger of configuring ksu with this macro is if the +source user is logged in remotely and does not have a secure +channel, the password may get exposed. + +\item[{\sphinxstylestrong{PRINC\_LOOK\_AHEAD}}] \leavevmode +\sphinxAtStartPar +During the resolution of the default principal name, +\sphinxstylestrong{PRINC\_LOOK\_AHEAD} enables ksu to find principal names in +the .k5users file as described in the OPTIONS section +(see \sphinxstylestrong{\sphinxhyphen{}n} option). + +\item[{\sphinxstylestrong{CMD\_PATH}}] \leavevmode +\sphinxAtStartPar +Specifies a list of directories containing programs that users are +authorized to execute (via .k5users file). + +\item[{\sphinxstylestrong{HAVE\_GETUSERSHELL}}] \leavevmode +\sphinxAtStartPar +If the source user is non\sphinxhyphen{}root, ksu insists that the target user’s +shell to be invoked is a “legal shell”. \sphinxstyleemphasis{getusershell(3)} is +called to obtain the names of “legal shells”. Note that the +target user’s shell is obtained from the passwd file. + +\end{description} + +\sphinxAtStartPar +Sample configuration: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{KSU\PYGZus{}OPTS} \PYG{o}{=} \PYG{o}{\PYGZhy{}}\PYG{n}{DGET\PYGZus{}TGT\PYGZus{}VIA\PYGZus{}PASSWD} \PYG{o}{\PYGZhy{}}\PYG{n}{DPRINC\PYGZus{}LOOK\PYGZus{}AHEAD} \PYG{o}{\PYGZhy{}}\PYG{n}{DCMD\PYGZus{}PATH}\PYG{o}{=}\PYG{l+s+s1}{\PYGZsq{}}\PYG{l+s+s1}{\PYGZdq{}}\PYG{l+s+s1}{/bin /usr/ucb /local/bin}\PYG{l+s+s1}{\PYGZdq{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +ksu should be owned by root and have the set user id bit turned on. + +\sphinxAtStartPar +ksu attempts to get a ticket for the end server just as Kerberized +telnet and rlogin. Thus, there must be an entry for the server in the +Kerberos database (e.g., \sphinxcode{\sphinxupquote{host/nii.isi.edu@ISI.EDU}}). The keytab +file must be in an appropriate location. + + +\subsection{SIDE EFFECTS} +\label{\detokenize{user/user_commands/ksu:side-effects}} +\sphinxAtStartPar +ksu deletes all expired tickets from the source cache. + + +\subsection{AUTHOR OF KSU} +\label{\detokenize{user/user_commands/ksu:author-of-ksu}} +\sphinxAtStartPar +GENNADY (ARI) MEDVINSKY + + +\subsection{ENVIRONMENT} +\label{\detokenize{user/user_commands/ksu:environment}} +\sphinxAtStartPar +See {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{user/user_commands/ksu:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}}, {\hyperref[\detokenize{user/user_commands/kinit:kinit-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kinit}}}} + + +\section{kswitch} +\label{\detokenize{user/user_commands/kswitch:kswitch}}\label{\detokenize{user/user_commands/kswitch:kswitch-1}}\label{\detokenize{user/user_commands/kswitch::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{user/user_commands/kswitch:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{kswitch} +\{\sphinxstylestrong{\sphinxhyphen{}c} \sphinxstyleemphasis{cachename}|\sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{principal}\} + + +\subsection{DESCRIPTION} +\label{\detokenize{user/user_commands/kswitch:description}} +\sphinxAtStartPar +kswitch makes the specified credential cache the primary cache for the +collection, if a cache collection is available. + + +\subsection{OPTIONS} +\label{\detokenize{user/user_commands/kswitch:options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}c} \sphinxstyleemphasis{cachename}}] \leavevmode +\sphinxAtStartPar +Directly specifies the credential cache to be made primary. + +\item[{\sphinxstylestrong{\sphinxhyphen{}p} \sphinxstyleemphasis{principal}}] \leavevmode +\sphinxAtStartPar +Causes the cache collection to be searched for a cache containing +credentials for \sphinxstyleemphasis{principal}. If one is found, that collection is +made primary. + +\end{description} + + +\subsection{ENVIRONMENT} +\label{\detokenize{user/user_commands/kswitch:environment}} +\sphinxAtStartPar +See {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} for a description of Kerberos environment +variables. + + +\subsection{FILES} +\label{\detokenize{user/user_commands/kswitch:files}}\begin{description} +\item[{\DUrole{xref,std,std-ref}{DEFCCNAME}}] \leavevmode +\sphinxAtStartPar +Default location of Kerberos 5 credentials cache + +\end{description} + + +\subsection{SEE ALSO} +\label{\detokenize{user/user_commands/kswitch:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{user/user_commands/kinit:kinit-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kinit}}}}, {\hyperref[\detokenize{user/user_commands/kdestroy:kdestroy-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kdestroy}}}}, {\hyperref[\detokenize{user/user_commands/klist:klist-1}]{\sphinxcrossref{\DUrole{std,std-ref}{klist}}}}, +{\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} + + +\section{kvno} +\label{\detokenize{user/user_commands/kvno:kvno}}\label{\detokenize{user/user_commands/kvno:kvno-1}}\label{\detokenize{user/user_commands/kvno::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{user/user_commands/kvno:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{kvno} +{[}\sphinxstylestrong{\sphinxhyphen{}c} \sphinxstyleemphasis{ccache}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{etype}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}k} \sphinxstyleemphasis{keytab}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}q}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}u} | \sphinxstylestrong{\sphinxhyphen{}S} \sphinxstyleemphasis{sname}{]} +{[}\sphinxstylestrong{\sphinxhyphen{}P}{]} +{[}\sphinxstylestrong{\textendash{}cached\sphinxhyphen{}only}{]} +{[}\sphinxstylestrong{\textendash{}no\sphinxhyphen{}store}{]} +{[}\sphinxstylestrong{\textendash{}out\sphinxhyphen{}cache} \sphinxstyleemphasis{cache}{]} +{[}{[}\{\sphinxstylestrong{\sphinxhyphen{}F} \sphinxstyleemphasis{cert\_file} | \{\sphinxstylestrong{\sphinxhyphen{}I} | \sphinxstylestrong{\sphinxhyphen{}U}\} \sphinxstyleemphasis{for\_user}\} {[}\sphinxstylestrong{\sphinxhyphen{}P}{]}{]} | \sphinxstylestrong{\textendash{}u2u} \sphinxstyleemphasis{ccache}{]} +\sphinxstyleemphasis{service1 service2} … + + +\subsection{DESCRIPTION} +\label{\detokenize{user/user_commands/kvno:description}} +\sphinxAtStartPar +kvno acquires a service ticket for the specified Kerberos principals +and prints out the key version numbers of each. + + +\subsection{OPTIONS} +\label{\detokenize{user/user_commands/kvno:options}}\begin{description} +\item[{\sphinxstylestrong{\sphinxhyphen{}c} \sphinxstyleemphasis{ccache}}] \leavevmode +\sphinxAtStartPar +Specifies the name of a credentials cache to use (if not the +default) + +\item[{\sphinxstylestrong{\sphinxhyphen{}e} \sphinxstyleemphasis{etype}}] \leavevmode +\sphinxAtStartPar +Specifies the enctype which will be requested for the session key +of all the services named on the command line. This is useful in +certain backward compatibility situations. + +\item[{\sphinxstylestrong{\sphinxhyphen{}k} \sphinxstyleemphasis{keytab}}] \leavevmode +\sphinxAtStartPar +Decrypt the acquired tickets using \sphinxstyleemphasis{keytab} to confirm their +validity. + +\item[{\sphinxstylestrong{\sphinxhyphen{}q}}] \leavevmode +\sphinxAtStartPar +Suppress printing output when successful. If a service ticket +cannot be obtained, an error message will still be printed and +kvno will exit with nonzero status. + +\item[{\sphinxstylestrong{\sphinxhyphen{}u}}] \leavevmode +\sphinxAtStartPar +Use the unknown name type in requested service principal names. +This option Cannot be used with \sphinxstyleemphasis{\sphinxhyphen{}S}. + +\item[{\sphinxstylestrong{\sphinxhyphen{}P}}] \leavevmode +\sphinxAtStartPar +Specifies that the \sphinxstyleemphasis{service1 service2} … arguments are to be +treated as services for which credentials should be acquired using +constrained delegation. This option is only valid when used in +conjunction with protocol transition. + +\item[{\sphinxstylestrong{\sphinxhyphen{}S} \sphinxstyleemphasis{sname}}] \leavevmode +\sphinxAtStartPar +Specifies that the \sphinxstyleemphasis{service1 service2} … arguments are +interpreted as hostnames, and the service principals are to be +constructed from those hostnames and the service name \sphinxstyleemphasis{sname}. +The service hostnames will be canonicalized according to the usual +rules for constructing service principals. + +\item[{\sphinxstylestrong{\sphinxhyphen{}I} \sphinxstyleemphasis{for\_user}}] \leavevmode +\sphinxAtStartPar +Specifies that protocol transition (S4U2Self) is to be used to +acquire a ticket on behalf of \sphinxstyleemphasis{for\_user}. If constrained +delegation is not requested, the service name must match the +credentials cache client principal. + +\item[{\sphinxstylestrong{\sphinxhyphen{}U} \sphinxstyleemphasis{for\_user}}] \leavevmode +\sphinxAtStartPar +Same as \sphinxhyphen{}I, but treats \sphinxstyleemphasis{for\_user} as an enterprise name. + +\item[{\sphinxstylestrong{\sphinxhyphen{}F} \sphinxstyleemphasis{cert\_file}}] \leavevmode +\sphinxAtStartPar +Specifies that protocol transition is to be used, identifying the +client principal with the X.509 certificate in \sphinxstyleemphasis{cert\_file}. The +certificate file must be in PEM format. + +\item[{\sphinxstylestrong{\textendash{}cached\sphinxhyphen{}only}}] \leavevmode +\sphinxAtStartPar +Only retrieve credentials already present in the cache, not from +the KDC. (Added in release 1.19.) + +\item[{\sphinxstylestrong{\textendash{}no\sphinxhyphen{}store}}] \leavevmode +\sphinxAtStartPar +Do not store retrieved credentials in the cache. If +\sphinxstylestrong{\textendash{}out\sphinxhyphen{}cache} is also specified, credentials will still be +stored into the output credential cache. (Added in release 1.19.) + +\item[{\sphinxstylestrong{\textendash{}out\sphinxhyphen{}cache} \sphinxstyleemphasis{ccache}}] \leavevmode +\sphinxAtStartPar +Initialize \sphinxstyleemphasis{ccache} and store all retrieved credentials into it. +Do not store acquired credentials in the input cache. (Added in +release 1.19.) + +\item[{\sphinxstylestrong{\textendash{}u2u} \sphinxstyleemphasis{ccache}}] \leavevmode +\sphinxAtStartPar +Requests a user\sphinxhyphen{}to\sphinxhyphen{}user ticket. \sphinxstyleemphasis{ccache} must contain a local +krbtgt ticket for the server principal. The reported version +number will typically be 0, as the resulting ticket is not +encrypted in the server’s long\sphinxhyphen{}term key. + +\end{description} + + +\subsection{ENVIRONMENT} +\label{\detokenize{user/user_commands/kvno:environment}} +\sphinxAtStartPar +See {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} for a description of Kerberos environment +variables. + + +\subsection{FILES} +\label{\detokenize{user/user_commands/kvno:files}}\begin{description} +\item[{\DUrole{xref,std,std-ref}{DEFCCNAME}}] \leavevmode +\sphinxAtStartPar +Default location of the credentials cache + +\end{description} + + +\subsection{SEE ALSO} +\label{\detokenize{user/user_commands/kvno:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{user/user_commands/kinit:kinit-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kinit}}}}, {\hyperref[\detokenize{user/user_commands/kdestroy:kdestroy-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kdestroy}}}}, {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} + + +\section{sclient} +\label{\detokenize{user/user_commands/sclient:sclient}}\label{\detokenize{user/user_commands/sclient:sclient-1}}\label{\detokenize{user/user_commands/sclient::doc}} + +\subsection{SYNOPSIS} +\label{\detokenize{user/user_commands/sclient:synopsis}} +\sphinxAtStartPar +\sphinxstylestrong{sclient} \sphinxstyleemphasis{remotehost} + + +\subsection{DESCRIPTION} +\label{\detokenize{user/user_commands/sclient:description}} +\sphinxAtStartPar +sclient is a sample application, primarily useful for testing +purposes. It contacts a sample server \DUrole{xref,std,std-ref}{sserver(8)} and +authenticates to it using Kerberos version 5 tickets, then displays +the server’s response. + + +\subsection{ENVIRONMENT} +\label{\detokenize{user/user_commands/sclient:environment}} +\sphinxAtStartPar +See {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} for a description of Kerberos environment +variables. + + +\subsection{SEE ALSO} +\label{\detokenize{user/user_commands/sclient:see-also}} +\sphinxAtStartPar +{\hyperref[\detokenize{user/user_commands/kinit:kinit-1}]{\sphinxcrossref{\DUrole{std,std-ref}{kinit}}}}, \DUrole{xref,std,std-ref}{sserver(8)}, {\hyperref[\detokenize{user/user_config/kerberos:kerberos-7}]{\sphinxcrossref{\DUrole{std,std-ref}{kerberos}}}} + + + +\renewcommand{\indexname}{Index} +\printindex +\end{document} \ No newline at end of file diff --git a/krb5-1.21.3/doc/plugindev/ccselect.rst b/krb5-1.21.3/doc/plugindev/ccselect.rst new file mode 100644 index 00000000..1253fe6b --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/ccselect.rst @@ -0,0 +1,28 @@ +.. _ccselect_plugin: + +Credential cache selection interface (ccselect) +=============================================== + +The ccselect interface allows modules to control how credential caches +are chosen when a GSSAPI client contacts a service. For a detailed +description of the ccselect interface, see the header file +````. + +The primary ccselect method is **choose**, which accepts a server +principal as input and returns a ccache and/or principal name as +output. A module can use the krb5_cccol APIs to iterate over the +cache collection in order to find an appropriate ccache to use. + +.. TODO: add reference to the admin guide for ccaches and cache + collections when we have appropriate sections. + +A module can create and destroy per-library-context state objects by +implementing the **init** and **fini** methods. State objects have +the type krb5_ccselect_moddata, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object. + +A module can have one of two priorities, "authoritative" or +"heuristic". Results from authoritative modules, if any are +available, will take priority over results from heuristic modules. A +module communicates its priority as a result of the **init** method. diff --git a/krb5-1.21.3/doc/plugindev/certauth.rst b/krb5-1.21.3/doc/plugindev/certauth.rst new file mode 100644 index 00000000..3740c5f7 --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/certauth.rst @@ -0,0 +1,36 @@ +.. _certauth_plugin: + +PKINIT certificate authorization interface (certauth) +===================================================== + +The certauth interface was first introduced in release 1.16. It +allows customization of the X.509 certificate attribute requirements +placed on certificates used by PKINIT enabled clients. For a detailed +description of the certauth interface, see the header file +```` + +A certauth module implements the **authorize** method to determine +whether a client's certificate is authorized to authenticate a client +principal. **authorize** receives the DER-encoded certificate, the +requested client principal, and a pointer to the client's +krb5_db_entry (for modules that link against libkdb5). The method +must decode the certificate and inspect its attributes to determine if +it should authorize PKINIT authentication. It returns the +authorization status and optionally outputs a list of authentication +indicator strings to be added to the ticket. + +Beginning in release 1.19, the authorize method can request that the +hardware authentication bit be set in the ticket by returning +**KRB5_CERTAUTH_HWAUTH**. Beginning in release 1.20, the authorize +method can return **KRB5_CERTAUTH_HWAUTH_PASS** to request that the +hardware authentication bit be set in the ticket but otherwise defer +authorization to another certauth module. A module must use its own +internal or library-provided ASN.1 certificate decoder. + +A module can optionally create and destroy module data with the +**init** and **fini** methods. Module data objects last for the +lifetime of the KDC process. + +If a module allocates and returns a list of authentication indicators +from **authorize**, it must also implement the **free_ind** method +to free the list. diff --git a/krb5-1.21.3/doc/plugindev/clpreauth.rst b/krb5-1.21.3/doc/plugindev/clpreauth.rst new file mode 100644 index 00000000..38aa52e8 --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/clpreauth.rst @@ -0,0 +1,54 @@ +Client preauthentication interface (clpreauth) +============================================== + +During an initial ticket request, a KDC may ask a client to prove its +knowledge of the password before issuing an encrypted ticket, or to +use credentials other than a password. This process is called +preauthentication, and is described in :rfc:`4120` and :rfc:`6113`. +The clpreauth interface allows the addition of client support for +preauthentication mechanisms beyond those included in the core MIT +krb5 code base. For a detailed description of the clpreauth +interface, see the header file ```` (or +```` before release 1.12). + +A clpreauth module is generally responsible for: + +* Supplying a list of preauth type numbers used by the module in the + **pa_type_list** field of the vtable structure. + +* Indicating what kind of preauthentication mechanism it implements, + with the **flags** method. In the most common case, this method + just returns ``PA_REAL``, indicating that it implements a normal + preauthentication type. + +* Examining the padata information included in a PREAUTH_REQUIRED or + MORE_PREAUTH_DATA_REQUIRED error and producing padata values for the + next AS request. This is done with the **process** method. + +* Examining the padata information included in a successful ticket + reply, possibly verifying the KDC identity and computing a reply + key. This is also done with the **process** method. + +* For preauthentication types which support it, recovering from errors + by examining the error data from the KDC and producing a padata + value for another AS request. This is done with the **tryagain** + method. + +* Receiving option information (supplied by ``kinit -X`` or by an + application), with the **gic_opts** method. + +A clpreauth module can create and destroy per-library-context and +per-request state objects by implementing the **init**, **fini**, +**request_init**, and **request_fini** methods. Per-context state +objects have the type krb5_clpreauth_moddata, and per-request state +objects have the type krb5_clpreauth_modreq. These are abstract +pointer types; a module should typically cast these to internal +types for the state objects. + +The **process** and **tryagain** methods have access to a callback +function and handle (called a "rock") which can be used to get +additional information about the current request, including the +expected enctype of the AS reply, the FAST armor key, and the client +long-term key (prompting for the user password if necessary). A +callback can also be used to replace the AS reply key if the +preauthentication mechanism computes one. diff --git a/krb5-1.21.3/doc/plugindev/general.rst b/krb5-1.21.3/doc/plugindev/general.rst new file mode 100644 index 00000000..fba9bf6e --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/general.rst @@ -0,0 +1,118 @@ +General plugin concepts +======================= + +A krb5 dynamic plugin module is a Unix shared object or Windows DLL. +Typically, the source code for a dynamic plugin module should live in +its own project with a build system using automake_ and libtool_, or +tools with similar functionality. + +A plugin module must define a specific symbol name, which depends on +the pluggable interface and module name. For most pluggable +interfaces, the exported symbol is a function named +``INTERFACE_MODULE_initvt``, where *INTERFACE* is the name of the +pluggable interface and *MODULE* is the name of the module. For these +interfaces, it is possible for one shared object or DLL to implement +multiple plugin modules, either for the same pluggable interface or +for different ones. For example, a shared object could implement both +KDC and client preauthentication mechanisms, by exporting functions +named ``kdcpreauth_mymech_initvt`` and ``clpreauth_mymech_initvt``. + +.. note: The profile, locate, and GSSAPI mechglue pluggable interfaces + follow different conventions. See the documentation for + those interfaces for details. The remainder of this section + applies to pluggable interfaces which use the standard + conventions. + +A plugin module implementation should include the header file +````, where *INTERFACE* is the name of the +pluggable interface. For instance, a ccselect plugin module +implementation should use ``#include ``. + +.. note: clpreauth and kdcpreauth module implementations should + include . + +initvt functions have the following prototype:: + + krb5_error_code interface_modname_initvt(krb5_context context, + int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +and should do the following: + +1. Check that the supplied maj_ver argument is supported by the + module. If it is not supported, the function should return + KRB5_PLUGIN_VER_NOTSUPP. + +2. Cast the supplied vtable pointer to the structure type + corresponding to the major version, as documented in the pluggable + interface header file. + +3. Fill in the structure fields with pointers to method functions and + static data, stopping at the field indicated by the supplied minor + version. Fields for unimplemented optional methods can be left + alone; it is not necessary to initialize them to NULL. + +In most cases, the context argument will not be used. The initvt +function should not allocate memory; think of it as a glorified +structure initializer. Each pluggable interface defines methods for +allocating and freeing module state if doing so is necessary for the +interface. + +Pluggable interfaces typically include a **name** field in the vtable +structure, which should be filled in with a pointer to a string +literal containing the module name. + +Here is an example of what an initvt function might look like for a +fictional pluggable interface named fences, for a module named +"wicker":: + + krb5_error_code + fences_wicker_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) + { + krb5_ccselect_vtable vt; + + if (maj_ver == 1) { + krb5_fences_vtable vt = (krb5_fences_vtable)vtable; + vt->name = "wicker"; + vt->slats = wicker_slats; + vt->braces = wicker_braces; + } else if (maj_ver == 2) { + krb5_fences_vtable_v2 vt = (krb5_fences_vtable_v2)vtable; + vt->name = "wicker"; + vt->material = wicker_material; + vt->construction = wicker_construction; + if (min_ver < 2) + return 0; + vt->footing = wicker_footing; + if (min_ver < 3) + return 0; + vt->appearance = wicker_appearance; + } else { + return KRB5_PLUGIN_VER_NOTSUPP; + } + return 0; + } + +Logging from KDC and kadmind plugin modules +------------------------------------------- + +Plugin modules for the KDC or kadmind daemons can write to the +configured logging outputs (see :ref:`logging`) by calling the +**com_err** function. The first argument (*whoami*) is ignored. If +the second argument (*code*) is zero, the formatted message is logged +at informational severity; otherwise, the formatted message is logged +at error severity and includes the error message for the supplied +code. Here are examples:: + + com_err("", 0, "Client message contains %d items", nitems); + com_err("", retval, "while decoding client message"); + +(The behavior described above is new in release 1.17. In prior +releases, the *whoami* argument is included for some logging output +types, the logged message does not include the usual header for some +output types, and the severity for syslog outputs is configured as +part of the logging specification, defaulting to error severity.) + +.. _automake: https://www.gnu.org/software/automake/ +.. _libtool: https://www.gnu.org/software/libtool/ diff --git a/krb5-1.21.3/doc/plugindev/gssapi.rst b/krb5-1.21.3/doc/plugindev/gssapi.rst new file mode 100644 index 00000000..0918d151 --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/gssapi.rst @@ -0,0 +1,134 @@ +GSSAPI mechanism interface +========================== + +The GSSAPI library in MIT krb5 can load mechanism modules to augment +the set of built-in mechanisms. + +.. note: The GSSAPI loadable mechanism interface does not follow the + normal conventions for MIT krb5 pluggable interfaces. + +A mechanism module is a Unix shared object or Windows DLL, built +separately from the krb5 tree. Modules are loaded according to the +GSS mechanism config files described in :ref:`gssapi_plugin_config`. + +For the most part, a GSSAPI mechanism module exports the same +functions as would a GSSAPI implementation itself, with the same +function signatures. The mechanism selection layer within the GSSAPI +library (called the "mechglue") will dispatch calls from the +application to the module if the module's mechanism is requested. If +a module does not wish to implement a GSSAPI extension, it can simply +refrain from exporting it, and the mechglue will fail gracefully if +the application calls that function. + +The mechglue does not invoke a module's **gss_add_cred**, +**gss_add_cred_from**, **gss_add_cred_impersonate_name**, or +**gss_add_cred_with_password** function. A mechanism only needs to +implement the "acquire" variants of those functions. + +A module does not need to coordinate its minor status codes with those +of other mechanisms. If the mechglue detects conflicts, it will map +the mechanism's status codes onto unique values, and then map them +back again when **gss_display_status** is called. + + +NegoEx modules +-------------- + +Some Windows GSSAPI mechanisms can only be negotiated via a Microsoft +extension to SPNEGO called NegoEx. Beginning with release 1.18, +mechanism modules can support NegoEx as follows: + +* Implement the gssspi_query_meta_data(), gssspi_exchange_meta_data(), + and gssspi_query_mechanism_info() SPIs declared in + ````. + +* Implement gss_inquire_sec_context_by_oid() and answer the + **GSS_C_INQ_NEGOEX_KEY** and **GSS_C_INQ_NEGOEX_VERIFY_KEY** OIDs + to provide the checksum keys for outgoing and incoming checksums, + respectively. The answer must be in two buffers: the first buffer + contains the key contents, and the second buffer contains the key + encryption type as a four-byte little-endian integer. + +By default, NegoEx mechanisms will not be directly negotiated via +SPNEGO. If direct SPNEGO negotiation is required for +interoperability, implement gss_inquire_attrs_for_mech() and assert +the GSS_C_MA_NEGOEX_AND_SPNEGO attribute (along with any applicable +RFC 5587 attributes). + + +Interposer modules +------------------ + +The mechglue also supports a kind of loadable module, called an +interposer module, which intercepts calls to existing mechanisms +rather than implementing a new mechanism. + +An interposer module must export the symbol **gss_mech_interposer** +with the following signature:: + + gss_OID_set gss_mech_interposer(gss_OID mech_type); + +This function is invoked with the OID of the interposer mechanism as +specified in the mechanism config file, and returns a set of mechanism +OIDs to be interposed. The returned OID set must have been created +using the mechglue's gss_create_empty_oid_set and +gss_add_oid_set_member functions. + +An interposer module must use the prefix ``gssi_`` for the GSSAPI +functions it exports, instead of the prefix ``gss_``. In most cases, +unexported ``gssi_`` functions will result in failure from their +corresponding ``gss_`` calls. + +An interposer module can link against the GSSAPI library in order to +make calls to the original mechanism. To do so, it must specify a +special mechanism OID which is the concatention of the interposer's +own OID byte string and the original mechanism's OID byte string. + +Functions that do not accept a mechanism argument directly require no +special handling, with the following exceptions: + +Since **gss_accept_sec_context** does not accept a mechanism argument, +an interposer mechanism must, in order to invoke the original +mechanism's function, acquire a credential for the concatenated OID +and pass that as the *verifier_cred_handle* parameter. + +Since **gss_import_name**, **gss_import_cred**, and +**gss_import_sec_context** do not accept mechanism parameters, the SPI +has been extended to include variants which do. This allows the +interposer module to know which mechanism should be used to interpret +the token. These functions have the following signatures:: + + OM_uint32 gssi_import_sec_context_by_mech(OM_uint32 *minor_status, + gss_OID desired_mech, gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle); + + OM_uint32 gssi_import_name_by_mech(OM_uint32 *minor_status, + gss_OID mech_type, gss_buffer_t input_name_buffer, + gss_OID input_name_type, gss_name_t output_name); + + OM_uint32 gssi_import_cred_by_mech(OM_uint32 *minor_status, + gss_OID mech_type, gss_buffer_t token, + gss_cred_id_t *cred_handle); + +To re-enter the original mechanism when importing tokens for the above +functions, the interposer module must wrap the mechanism token in the +mechglue's format, using the concatenated OID (except in +**gss_import_name**). The mechglue token formats are: + +* For **gss_import_sec_context**, a four-byte OID length in big-endian + order, followed by the concatenated OID, followed by the mechanism + token. + +* For **gss_import_name**, the bytes 04 01, followed by a two-byte OID + length in big-endian order, followed by the mechanism OID, followed + by a four-byte token length in big-endian order, followed by the + mechanism token. Unlike most uses of OIDs in the API, the mechanism + OID encoding must include the DER tag and length for an object + identifier (06 followed by the DER length of the OID byte string), + and this prefix must be included in the two-byte OID length. + input_name_type must also be set to GSS_C_NT_EXPORT_NAME. + +* For **gss_import_cred**, a four-byte OID length in big-endian order, + followed by the concatenated OID, followed by a four-byte token + length in big-endian order, followed by the mechanism token. This + sequence may be repeated multiple times. diff --git a/krb5-1.21.3/doc/plugindev/hostrealm.rst b/krb5-1.21.3/doc/plugindev/hostrealm.rst new file mode 100644 index 00000000..4d488ef7 --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/hostrealm.rst @@ -0,0 +1,39 @@ +.. _hostrealm_plugin: + +Host-to-realm interface (hostrealm) +=================================== + +The host-to-realm interface was first introduced in release 1.12. It +allows modules to control the local mapping of hostnames to realm +names as well as the default realm. For a detailed description of the +hostrealm interface, see the header file +````. + +Although the mapping methods in the hostrealm interface return a list +of one or more realms, only the first realm in the list is currently +used by callers. Callers may begin using later responses in the +future. + +Any mapping method may return KRB5_PLUGIN_NO_HANDLE to defer +processing to a later module. + +A module can create and destroy per-library-context state objects +using the **init** and **fini** methods. If the module does not need +any state, it does not need to implement these methods. + +The optional **host_realm** method allows a module to determine +authoritative realm mappings for a hostname. The first authoritative +mapping is used in preference to KDC referrals when getting service +credentials. + +The optional **fallback_realm** method allows a module to determine +fallback mappings for a hostname. The first fallback mapping is tried +if there is no authoritative mapping for a realm, and KDC referrals +failed to produce a successful result. + +The optional **default_realm** method allows a module to determine the +local default realm. + +If a module implements any of the above methods, it must also +implement **free_list** to ensure that memory is allocated and +deallocated consistently. diff --git a/krb5-1.21.3/doc/plugindev/index.rst b/krb5-1.21.3/doc/plugindev/index.rst new file mode 100644 index 00000000..5e783463 --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/index.rst @@ -0,0 +1,38 @@ +For plugin module developers +============================ + +Kerberos plugin modules allow increased control over MIT krb5 library +and server behavior. This guide describes how to create dynamic +plugin modules and the currently available pluggable interfaces. + +See :ref:`plugin_config` for information on how to register dynamic +plugin modules and how to enable and disable modules via +:ref:`krb5.conf(5)`. + +.. TODO: update the above reference when we have a free-form section + in the admin guide about plugin configuration + + +Contents +-------- + +.. toctree:: + :maxdepth: 2 + + general.rst + clpreauth.rst + kdcpreauth.rst + ccselect.rst + pwqual.rst + kadm5_hook.rst + kadm5_auth.rst + hostrealm.rst + localauth.rst + locate.rst + profile.rst + gssapi.rst + internal.rst + certauth.rst + kdcpolicy.rst + +.. TODO: GSSAPI mechanism plugins diff --git a/krb5-1.21.3/doc/plugindev/internal.rst b/krb5-1.21.3/doc/plugindev/internal.rst new file mode 100644 index 00000000..99e30bb7 --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/internal.rst @@ -0,0 +1,32 @@ +Internal pluggable interfaces +============================= + +Following are brief discussions of pluggable interfaces which have not +yet been made public. These interfaces are functional, but the +interfaces are likely to change in incompatible ways from release to +release. In some cases, it may be necessary to copy header files from +the krb5 source tree to use an internal interface. Use these with +care, and expect to need to update your modules for each new release +of MIT krb5. + + +Kerberos database interface (KDB) +--------------------------------- + +A KDB module implements a database back end for KDC principal and +policy information, and can also control many aspects of KDC behavior. +For a full description of the interface, see the header file +````. + +The KDB pluggable interface is often referred to as the DAL (Database +Access Layer). + + +Authorization data interface (authdata) +--------------------------------------- + +The authdata interface allows a module to provide (from the KDC) or +consume (in application servers) authorization data of types beyond +those handled by the core MIT krb5 code base. The interface is +defined in the header file ````, which is not +installed by the build. diff --git a/krb5-1.21.3/doc/plugindev/kadm5_auth.rst b/krb5-1.21.3/doc/plugindev/kadm5_auth.rst new file mode 100644 index 00000000..b4839617 --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/kadm5_auth.rst @@ -0,0 +1,35 @@ +.. _kadm5_auth_plugin: + +kadmin authorization interface (kadm5_auth) +=========================================== + +The kadm5_auth interface (new in release 1.16) allows modules to +determine whether a client principal is authorized to perform an +operation in the kadmin protocol, and to apply restrictions to +principal operations. For a detailed description of the kadm5_auth +interface, see the header file ````. + +A module can create and destroy per-process state objects by +implementing the **init** and **fini** methods. State objects have +the type kadm5_auth_modinfo, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object. + +The kadm5_auth interface has one method for each kadmin operation, +with parameters specific to the operation. Each method can return +either 0 to authorize access, KRB5_PLUGIN_NO_HANDLE to defer the +decision to other modules, or another error (canonically EPERM) to +authoritatively deny access. Access is granted if at least one module +grants access and no module authoritatively denies access. + +The **addprinc** and **modprinc** methods can also impose restrictions +on the principal operation by returning a ``struct +kadm5_auth_restrictions`` object. The module should also implement +the **free_restrictions** method if it dynamically allocates +restrictions objects for principal operations. + +kadm5_auth modules can optionally inspect principal or policy objects. +To do this, the module must also include ```` to gain +access to the structure definitions for those objects. As the kadmin +interface is explicitly not as stable as other public interfaces, +modules which do this may not retain compatibility across releases. diff --git a/krb5-1.21.3/doc/plugindev/kadm5_hook.rst b/krb5-1.21.3/doc/plugindev/kadm5_hook.rst new file mode 100644 index 00000000..ece3eacf --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/kadm5_hook.rst @@ -0,0 +1,27 @@ +.. _kadm5_hook_plugin: + +KADM5 hook interface (kadm5_hook) +================================= + +The kadm5_hook interface allows modules to perform actions when +changes are made to the Kerberos database through :ref:`kadmin(1)`. +For a detailed description of the kadm5_hook interface, see the header +file ````. + +The kadm5_hook interface has five primary methods: **chpass**, +**create**, **modify**, **remove**, and **rename**. (The **rename** +method was introduced in release 1.14.) Each of these methods is +called twice when the corresponding administrative action takes place, +once before the action is committed and once afterwards. A module can +prevent the action from taking place by returning an error code during +the pre-commit stage. + +A module can create and destroy per-process state objects by +implementing the **init** and **fini** methods. State objects have +the type kadm5_hook_modinfo, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object. + +Because the kadm5_hook interface is tied closely to the kadmin +interface (which is explicitly unstable), it may not remain as stable +across versions as other public pluggable interfaces. diff --git a/krb5-1.21.3/doc/plugindev/kdcpolicy.rst b/krb5-1.21.3/doc/plugindev/kdcpolicy.rst new file mode 100644 index 00000000..74f21f08 --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/kdcpolicy.rst @@ -0,0 +1,24 @@ +.. _kdcpolicy_plugin: + +KDC policy interface (kdcpolicy) +================================ + +The kdcpolicy interface was first introduced in release 1.16. It +allows modules to veto otherwise valid AS and TGS requests or restrict +the lifetime and renew time of the resulting ticket. For a detailed +description of the kdcpolicy interface, see the header file +````. + +The optional **check_as** and **check_tgs** functions allow the module +to perform access control. Additionally, a module can create and +destroy module data with the **init** and **fini** methods. Module +data objects last for the lifetime of the KDC process, and are +provided to all other methods. The data has the type +krb5_kdcpolicy_moddata, which should be cast to the appropriate +internal type. + +kdcpolicy modules can optionally inspect principal entries. To do +this, the module must also include ```` to gain access to the +principal entry structure definition. As the KDB interface is +explicitly not as stable as other public interfaces, modules which do +this may not retain compatibility across releases. diff --git a/krb5-1.21.3/doc/plugindev/kdcpreauth.rst b/krb5-1.21.3/doc/plugindev/kdcpreauth.rst new file mode 100644 index 00000000..ab7f3a90 --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/kdcpreauth.rst @@ -0,0 +1,79 @@ +KDC preauthentication interface (kdcpreauth) +============================================ + +The kdcpreauth interface allows the addition of KDC support for +preauthentication mechanisms beyond those included in the core MIT +krb5 code base. For a detailed description of the kdcpreauth +interface, see the header file ```` (or +```` before release 1.12). + +A kdcpreauth module is generally responsible for: + +* Supplying a list of preauth type numbers used by the module in the + **pa_type_list** field of the vtable structure. + +* Indicating what kind of preauthentication mechanism it implements, + with the **flags** method. If the mechanism computes a new reply + key, it must specify the ``PA_REPLACES_KEY`` flag. If the mechanism + is generally only used with hardware tokens, the ``PA_HARDWARE`` + flag allows the mechanism to work with principals which have the + **requires_hwauth** flag set. + +* Producing a padata value to be sent with a preauth_required error, + with the **edata** method. + +* Examining a padata value sent by a client and verifying that it + proves knowledge of the appropriate client credential information. + This is done with the **verify** method. + +* Producing a padata response value for the client, and possibly + computing a reply key. This is done with the **return_padata** + method. + +A module can create and destroy per-KDC state objects by implementing +the **init** and **fini** methods. Per-KDC state objects have the +type krb5_kdcpreauth_moddata, which is an abstract pointer types. A +module should typically cast this to an internal type for the state +object. + +A module can create a per-request state object by returning one in the +**verify** method, receiving it in the **return_padata** method, and +destroying it in the **free_modreq** method. Note that these state +objects only apply to the processing of a single AS request packet, +not to an entire authentication exchange (since an authentication +exchange may remain unfinished by the client or may involve multiple +different KDC hosts). Per-request state objects have the type +krb5_kdcpreauth_modreq, which is an abstract pointer type. + +The **edata**, **verify**, and **return_padata** methods have access +to a callback function and handle (called a "rock") which can be used +to get additional information about the current request, including the +maximum allowable clock skew, the client's long-term keys, the +DER-encoded request body, the FAST armor key, string attributes on the +client's database entry, and the client's database entry itself. The +**verify** method can assert one or more authentication indicators to +be included in the issued ticket using the ``add_auth_indicator`` +callback (new in release 1.14). + +A module can generate state information to be included with the next +client request using the ``set_cookie`` callback (new in release +1.14). On the next request, the module can read this state +information using the ``get_cookie`` callback. Cookie information is +encrypted, timestamped, and transmitted to the client in a +``PA-FX-COOKIE`` pa-data item. Older clients may not support cookies +and therefore may not transmit the cookie in the next request; in this +case, ``get_cookie`` will not yield the saved information. + +If a module implements a mechanism which requires multiple round +trips, its **verify** method can respond with the code +``KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED`` and a list of pa-data in +the *e_data* parameter to be processed by the client. + +The **edata** and **verify** methods can be implemented +asynchronously. Because of this, they do not return values directly +to the caller, but must instead invoke responder functions with their +results. A synchronous implementation can invoke the responder +function immediately. An asynchronous implementation can use the +callback to get an event context for use with the libverto_ API. + +.. _libverto: https://fedorahosted.org/libverto/ diff --git a/krb5-1.21.3/doc/plugindev/localauth.rst b/krb5-1.21.3/doc/plugindev/localauth.rst new file mode 100644 index 00000000..6f396a9c --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/localauth.rst @@ -0,0 +1,43 @@ +.. _localauth_plugin: + +Local authorization interface (localauth) +========================================= + +The localauth interface was first introduced in release 1.12. It +allows modules to control the relationship between Kerberos principals +and local system accounts. When an application calls +:c:func:`krb5_kuserok` or :c:func:`krb5_aname_to_localname`, localauth +modules are consulted to determine the result. For a detailed +description of the localauth interface, see the header file +````. + +A module can create and destroy per-library-context state objects +using the **init** and **fini** methods. If the module does not need +any state, it does not need to implement these methods. + +The optional **userok** method allows a module to control the behavior +of :c:func:`krb5_kuserok`. The module receives the authenticated name +and the local account name as inputs, and can return either 0 to +authorize access, KRB5_PLUGIN_NO_HANDLE to defer the decision to other +modules, or another error (canonically EPERM) to authoritatively deny +access. Access is granted if at least one module grants access and no +module authoritatively denies access. + +The optional **an2ln** method can work in two different ways. If the +module sets an array of uppercase type names in **an2ln_types**, then +the module's **an2ln** method will only be invoked by +:c:func:`krb5_aname_to_localname` if an **auth_to_local** value in +:ref:`krb5.conf(5)` refers to one of the module's types. In this +case, the *type* and *residual* arguments will give the type name and +residual string of the **auth_to_local** value. + +If the module does not set **an2ln_types** but does implement +**an2ln**, the module's **an2ln** method will be invoked for all +:c:func:`krb5_aname_to_localname` operations unless an earlier module +determines a mapping, with *type* and *residual* set to NULL. The +module can return KRB5_LNAME_NO_TRANS to defer mapping to later +modules. + +If a module implements **an2ln**, it must also implement +**free_string** to ensure that memory is allocated and deallocated +consistently. diff --git a/krb5-1.21.3/doc/plugindev/locate.rst b/krb5-1.21.3/doc/plugindev/locate.rst new file mode 100644 index 00000000..fca6a4da --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/locate.rst @@ -0,0 +1,32 @@ +Server location interface (locate) +================================== + +The locate interface allows modules to control how KDCs and similar +services are located by clients. For a detailed description of the +ccselect interface, see the header file ````. + +.. note: The locate interface does not follow the normal conventions + for MIT krb5 pluggable interfaces, because it was made public + before those conventions were established. + +A locate module exports a structure object of type +krb5plugin_service_locate_ftable, with the name ``service_locator``. +The structure contains a minor version and pointers to the module's +methods. + +The primary locate method is **lookup**, which accepts a service type, +realm name, desired socket type, and desired address family (which +will be AF_UNSPEC if no specific address family is desired). The +method should invoke the callback function once for each server +address it wants to return, passing a socket type (SOCK_STREAM for TCP +or SOCK_DGRAM for UDP) and socket address. The **lookup** method +should return 0 if it has authoritatively determined the server +addresses for the realm, KRB5_PLUGIN_NO_HANDLE if it wants to let +other location mechanisms determine the server addresses, or another +code if it experienced a failure which should abort the location +process. + +A module can create and destroy per-library-context state objects by +implementing the **init** and **fini** methods. State objects have +the type void \*, and should be cast to an internal type for the state +object. diff --git a/krb5-1.21.3/doc/plugindev/profile.rst b/krb5-1.21.3/doc/plugindev/profile.rst new file mode 100644 index 00000000..209c0644 --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/profile.rst @@ -0,0 +1,96 @@ +.. _profile_plugin: + +Configuration interface (profile) +================================= + +The profile interface allows a module to control how krb5 +configuration information is obtained by the Kerberos library and +applications. For a detailed description of the profile interface, +see the header file ````. + +.. note:: + + The profile interface does not follow the normal conventions + for MIT krb5 pluggable interfaces, because it is part of a + lower-level component of the krb5 library. + +As with other types of plugin modules, a profile module is a Unix +shared object or Windows DLL, built separately from the krb5 tree. +The krb5 library will dynamically load and use a profile plugin module +if it reads a ``module`` directive at the beginning of krb5.conf, as +described in :ref:`profile_plugin_config`. + +A profile module exports a function named ``profile_module_init`` +matching the signature of the profile_module_init_fn type. This +function accepts a residual string, which may be used to help locate +the configuration source. The function fills in a vtable and may also +create a per-profile state object. If the module uses state objects, +it should implement the **copy** and **cleanup** methods to manage +them. + +A basic read-only profile module need only implement the +**get_values** and **free_values** methods. The **get_values** method +accepts a null-terminated list of C string names (e.g., an array +containing "libdefaults", "clockskew", and NULL for the **clockskew** +variable in the :ref:`libdefaults` section) and returns a +null-terminated list of values, which will be cleaned up with the +**free_values** method when the caller is done with them. + +Iterable profile modules must also define the **iterator_create**, +**iterator**, **iterator_free**, and **free_string** methods. The +core krb5 code does not require profiles to be iterable, but some +applications may iterate over the krb5 profile object in order to +present configuration interfaces. + +Writable profile modules must also define the **writable**, +**modified**, **update_relation**, **rename_section**, +**add_relation**, and **flush** methods. The core krb5 code does not +require profiles to be writable, but some applications may write to +the krb5 profile in order to present configuration interfaces. + +The following is an example of a very basic read-only profile module +which returns a hardcoded value for the **default_realm** variable in +:ref:`libdefaults`, and provides no other configuration information. +(For conciseness, the example omits code for checking the return +values of malloc and strdup.) :: + + #include + #include + #include + + static long + get_values(void *cbdata, const char *const *names, char ***values) + { + if (names[0] != NULL && strcmp(names[0], "libdefaults") == 0 && + names[1] != NULL && strcmp(names[1], "default_realm") == 0) { + *values = malloc(2 * sizeof(char *)); + (*values)[0] = strdup("ATHENA.MIT.EDU"); + (*values)[1] = NULL; + return 0; + } + return PROF_NO_RELATION; + } + + static void + free_values(void *cbdata, char **values) + { + char **v; + + for (v = values; *v; v++) + free(*v); + free(values); + } + + long + profile_module_init(const char *residual, struct profile_vtable *vtable, + void **cb_ret); + + long + profile_module_init(const char *residual, struct profile_vtable *vtable, + void **cb_ret) + { + *cb_ret = NULL; + vtable->get_values = get_values; + vtable->free_values = free_values; + return 0; + } diff --git a/krb5-1.21.3/doc/plugindev/pwqual.rst b/krb5-1.21.3/doc/plugindev/pwqual.rst new file mode 100644 index 00000000..523b95c5 --- /dev/null +++ b/krb5-1.21.3/doc/plugindev/pwqual.rst @@ -0,0 +1,25 @@ +.. _pwqual_plugin: + +Password quality interface (pwqual) +=================================== + +The pwqual interface allows modules to control what passwords are +allowed when a user changes passwords. For a detailed description of +the pwqual interface, see the header file ````. + +The primary pwqual method is **check**, which receives a password as +input and returns success (0) or a ``KADM5_PASS_Q_`` failure code +depending on whether the password is allowed. The **check** method +also receives the principal name and the name of the principal's +password policy as input; although there is no stable interface for +the module to obtain the fields of the password policy, it can define +its own configuration or data store based on the policy name. + +A module can create and destroy per-process state objects by +implementing the **open** and **close** methods. State objects have +the type krb5_pwqual_moddata, which is an abstract pointer type. A +module should typically cast this to an internal type for the state +object. The **open** method also receives the name of the realm's +dictionary file (as configured by the **dict_file** variable in the +:ref:`kdc_realms` section of :ref:`kdc.conf(5)`) if it wishes to use +it. diff --git a/krb5-1.21.3/doc/resources.rst b/krb5-1.21.3/doc/resources.rst new file mode 100644 index 00000000..2ac2791c --- /dev/null +++ b/krb5-1.21.3/doc/resources.rst @@ -0,0 +1,60 @@ +Resources +========= + +Mailing lists +------------- + +* kerberos@mit.edu is a community resource for discussion and + questions about MIT krb5 and other Kerberos implementations. To + subscribe to the list, please follow the instructions at + https://mailman.mit.edu/mailman/listinfo/kerberos. +* krbdev@mit.edu is the primary list for developers of MIT Kerberos. + To subscribe to the list, please follow the instructions at + https://mailman.mit.edu/mailman/listinfo/krbdev. +* krb5-bugs@mit.edu is notified when a ticket is created or updated. + This list helps track bugs and feature requests. + In addition, this list is used to track documentation criticism + and recommendations for improvements. +* krbcore@mit.edu is a private list for the MIT krb5 core team. Send + mail to this list if you need to contact the core team. +* krbcore-security@mit.edu is the point of contact for security problems + with MIT Kerberos. Please use PGP-encrypted mail to report possible + vulnerabilities to this list. + + +IRC channels +------------ + +The IRC channel `#kerberos` on libera.chat is a community resource for +general Kerberos discussion and support. + +The main IRC channel for MIT Kerberos development is `#krbdev` on +Libera Chat. + +For more information about Libera Chat, see https://libera.chat/. + + +Archives +-------- + +* The archive https://mailman.mit.edu/pipermail/kerberos/ contains + past postings from the `kerberos@mit.edu` list. + +* The https://mailman.mit.edu/pipermail/krbdev/ contains past postings + from the `krbdev@mit.edu` list. + + +Wiki +---- + +The wiki at https://k5wiki.kerberos.org/ contains useful information +for developers working on the MIT Kerberos source code. Some of the +information on the wiki may be useful for advanced users or system +administrators. + +Web pages +--------- + +* https://web.mit.edu/kerberos/ is the MIT Kerberos software web page. + +* https://kerberos.org/ is the MIT Kerberos Consortium web page. diff --git a/krb5-1.21.3/doc/rpc/design.tex b/krb5-1.21.3/doc/rpc/design.tex new file mode 100644 index 00000000..801034b0 --- /dev/null +++ b/krb5-1.21.3/doc/rpc/design.tex @@ -0,0 +1,1037 @@ +\documentstyle[fullpage,12pt]{article} + +\title{GSS-API Extensions to Sun RPC} +\date{Draft---\today} +\author{Barry Jaspan} + +\setlength{\parskip}{.7\baselineskip} +\setlength{\parindent}{0pt} + +\makeatletter +\newcount\savecnt\savecnt=0 +\def\saveenum#1{\global\savecnt=\csname c@enum#1\endcsname} +\def\restoreenum#1{\csname c@enum#1\endcsname=\savecnt} +\makeatother + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Make _ actually generate an _, and allow line-breaking after it. +\let\underscore=\_ +\catcode`_=13 +\def_{\underscore\penalty75\relax} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\begin{document} + + +{\setlength{\parskip}{0pt}\maketitle\tableofcontents} + +\section{Introduction} + +This document describes the integration of GSS-API authentication and +security with Sun RPC. + +\section{Requirements} + +The requirements of the GSS-API authentication system for Sun RPC are: + +\begin{enumerate} +\item It must provide mutual authentication between RPC clients and +servers. + +\item It must provide for integrity checking and encryption of all +procedure arguments and results passed over the network. +\saveenum{i} +\end{enumerate} + +The following features are desired, but not mandatory: + +\begin{enumerate} +\restoreenum{i} +\item It should provide for integrity checking and encryption of all +``header information'' that specifies the program and procedure being +called. + +\item It should obey the Sun RPC protocol so that clients using +it can interoperate with existing servers. In this case, +``interoperate'' means that existing servers will return an error code +indicating that they do not understand the authentication flavor, but +not that they do not understand the request at all. + +\item It should require minimal or no changes to the standard Sun RPC +programming paradigm for either clients or servers so that existing +code can use it with little or no effort. + +\item It should operate correctly with all the standard Sun RPC +transport mechansims (e.g. UDP and TCP). +\saveenum{i} +\end{enumerate} + +\section{Functional Specification} + +This section describes the programmer's interface to the GSS-API +authentication flavor. Knowledge of standard Sun RPC programming is +assumed. + +\subsection{Client Side} + +A RPC client can select the GSS-API authentication flavor in the same +way it can select any other authentication flavor, by setting the +cl_auth field of the CLIENT structure to the appropriate value: + +\begin{verbatim} + clnt = clnt_create(server_host, PROG_NUM, PROG_VERS, protocol); + clnt->cl_auth = auth_gssapi_create(clnt, ...); +\end{verbatim} + +There are two functions that create GSS-API authentication flavor +structures for the cl_auth field, auth_gssapi_create and +auth_gssapi_create_default. + +\begin{verbatim} +AUTH *auth_gssapi_create(CLIENT *clnt, + OM_uint32 *major_status, + OM_uint32 *minor_status, + gss_cred_id_t claimant_cred_handle, + gss_name_t target_name, + gss_OID mech_type, + int req_flags, + int time_req, + gss_OID *actual_mech_type, + int *ret_flags, + OM_uint32 *time_rec); +\end{verbatim} + +auth_gssapi_create creates a GSS-API authentication structure and +provides most of the flexibility of gss_init_sec_context. The +arguments have the same interpretation as those of +gss_init_sec_context with the same name, except: + +\begin{description} +\item[clnt] The CLIENT structure returned by client_create or one of +its relatives. It is not modified. +\end{description} + +auth_gssapi_create calls gss_init_sec_context as needed, passing each +generated token to and processing each token returned from the RPC +server specified by the RPC handle clnt. On return, if major_status +is GSS_S_COMPLETE, the context has been established, the returned AUTH +structure is valid, and all of the arguments filled in by +gss_init_sec_context have the correct values. If major_status is not +GSS_S_COMPLETE then it and minor_status contain error codes that can +be passed to gss_display_status and the returned value is NULL. + +\begin{verbatim} +AUTH *auth_gssapi_create_default(CLIENT *clnt, char *service_name); +\end{verbatim} + +auth_gssapi_create_default is a shorthand for auth_gssapi_create that +attempts to create a context that provides procedure call and result +integrity, using the default credentials and GSS-API mechanism. +service_name is parsed as a GSS-API ``service'' name and used as the +target name. The other arguments to auth_gssapi_create are as follows: + +\begin{verbatim} +auth_gssapi_create(clnt, + &dummy, + &dummy, + GSS_C_NO_CREDENTIAL, + target_name, + GSS_C_NULL_OID, + GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG, + 0, + NULL, + NULL, + NULL); +\end{verbatim} + +Note that if the underlying default mechanism does not support data +integrity (e.g. the trust mechanism), this function will fail. + +The GSS-API major and minor status codes can be interpreted with +auth_gssapi_display_status: + +\begin{verbatim} +void auth_gssapi_display_status(char *msg, OM_uint32 major, + OM_uint32 minor); +\end{verbatim} + +All of the error messages associated with the major and minor status +are displated on the standard error output, preceeded by the message +``GSS-API authentication error $<$msg$>$:''. + +\subsection{Server Side} + +\subsubsection{Service Name Registration} + +An application server must register the service name(s) that it will +use for GSS-API connections before any AUTH_GSSAPI requests will +succeed. + +\begin{verbatim} +typedef struct _auth_gssapi_name { + char *name; + gss_OID type; +} auth_gssapi_name; + +bool_t _svcauth_gssapi_set_names(auth_gssapi_name *names, int num); +\end{verbatim} + +names is an array of name specifications, each of which consists of a +null-terminated ASCII representation of a name and the GSS-API name +type that should be used to import it with gss_import_name. The +name type ``gss_nt_service_name'' is recommended. + +\subsubsection{Calling Client and Service Identification} + +Each application server's dispatch function is passed two arguments, +the transport mechanism (transp) and the RPC service request (rqstp). +If the service request's credential flavor (rq_cred.oa_flavor) is +AUTH_GSSAPI (300001)\footnote{The value 4 was originally used, but +300001 has been officially assigned by the IETF.}, then the call has +been authenticated. The rq_clntcred field of transp contains the +gss_name_t of the authenticated caller and can be passed to +gss_display_name to obtain a string represtation or gss_compare_name +to compare it with other names. The rq_svccred field of transp +contains the GSS-API context established with the caller and can be +passed to gss_inquire_context. + +\subsubsection{Error Logging} + +An application server can register a function to be called when a +failure occurs during GSS-API context establishment with +_svcauth_set_log_badauth_func. + +\begin{verbatim} +typedef void (*auth_gssapi_log_badauth_func)(OM_uint32 major, + OM_uint32 minor, + struct sockaddr_in *raddr, + caddr_t data); + +void _svcauth_set_log_badauth_func(auth_gssapi_log_badauth_func func, + caddr_t data); +\end{verbatim} + +The function func is called each time gss_accept_sec_context fails. +The major and minor arguments indicate the GSS-API major and minor +status codes returned. The raddr field contains the INET socket that +the request came from, and the data field contains the data argument +of _svcauth_gssapi_set_log_badauth_func. + +An application server can register a function to be called when an RPC +request with an invalid verifier arrives with +_svcauth_set_log_badverf_func. + +\begin{verbatim} +typedef void (*auth_gssapi_log_badverf_func)(gss_name_t client, + gss_name_t server, + struct svc_req *rqst, + struct rpc_msg *msg, + caddr_t data); + +void _svcauth_set_log_badverf_func(auth_gssapi_log_badverf_func func, + caddr_t data); +\end{verbatim} + +The function specified in func is called each time an invalid verifier +is received. The client and server fields identify the (falsely +claimed) originating client and the server it originally authenticated +to. The raddr and addrlen fields contain the INET socket that the +request (claims to have) come from, and data contains the data +argument of _svcauth_set_log_badverf_func. + +\section{Modifications to Sun RPC} + +The Sun RPC extensible authentication mechanism is designed to allow +different authentication systems to be integrated into Sun RPC easily. +Unfortunately, it has two drawbacks. First, the existing system has a +number of non-general design properties that are intended specifically +for Sun's Secure RPC, and second, the existing system has no concept +of or ability to perform authentication-flavor-specific operations on +function arguments and results passed over the wire. The first +problem merely makes the system confusing, since a number of features +touted as ``general'' do not make any sense for arbitrary +authentication systems. The second problem is more substantial, and +can only be corrected by modifications to Sun RPC internals. + +The following sections describe the necessary modifications to Sun +RPC. + +\subsection{Client Side Authentication, AUTH Structure} + +The AUTH structure (figure \ref{fig:auth}) encapsulates the data and +function pointers for an authentication flavor instance. It has been +changed in two ways. + +\begin{figure}[htbp] +\begin{verbatim} +typedef struct { + struct opaque_auth ah_cred; + struct opaque_auth ah_verf; + union des_block ah_key; + struct auth_ops { + void (*ah_nextverf)(); + int (*ah_marshal)(); /* nextverf & serialize */ + int (*ah_validate)(); /* validate varifier */ + int (*ah_refresh)(); /* refresh credentials */ + int (*ah_wrap)(); /* encode data for wire */ + int (*ah_unwrap)(); /* decode data from wire */ + void (*ah_destroy)(); /* destroy this structure */ + } *ah_ops; + caddr_t ah_private; +} AUTH; +\end{verbatim} +\caption{The AUTH structure, with the new function pointers ah_wrap +and ah_unwrap.} +\label{fig:auth} +\end{figure} + +First, the new functions ah_wrap and ah_unwrap prepare function +arguments and results for transmission over the wire. The +authentication mechanism can use them to sign, encrypt, or perform any +other operation on the data. Their prototype is: + +\begin{verbatim} +bool_t ah_wrap(AUTH *auth, XDR *out_xdrs, xdrproc_t func, caddr_t ptr); +bool_t ah_unwrap(AUTH *auth, XDR *in_xdrs, xdrproc_t func, caddr_t ptr); +\end{verbatim} + +ah_wrap encodes function arguments for transmission. func and ptr are +the XDR procedure and pointer that serialize the arguments, and +out_xdrs is the xdr stream that the encoded arguments should be +written to. ah_unwrap decodes function arguments received from the +network. Its arguments are the converse of those to ah_wrap. + +It is the responsibility of RPC transport mechanisms to call an +authorization flavor's ah_wrap and ah_unwrap functions when function +arguments or results would normally be written to or read from the +wire. Authorization flavors that do not need to perform any encoding +or decoding can use the provided function authany_wrap for ah_wrap +and ah_unwrap; it consists of the single statement ``return +(*func)(out_xdrs, ptr)'' (or in_xdrs, as appropriate). + +Second, the function ah_refresh has been changed to take the RPC error +message that resulted in its being called as an argument. This is +necessary since the contents of the error message may dictate how +ah_refresh should go about correcting the authentication failure. + +\subsection{Client Side Transport Mechanisms} + +Each client side transport mechanism must be modified to call the +ah_wrap and ah_unwrap functions from the cl_auth field of the CLIENT +structure during the call and reply process. The modification is +fairly simple. For example, the UDP transport mechanism used to +encode procedure calls like this: + +\begin{verbatim} + if ((! XDR_PUTLONG(xdrs, (long *)&proc)) || + (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || + (! (*xargs)(xdrs, argsp))) + return (cu->cu_error.re_status = RPC_CANTENCODEARGS); +\end{verbatim} + +The last function call in the conditional serializes the arguments +onto the xdr stream. This must be replaced with a call to the +appropriate ah_wrap function: + +\begin{verbatim} + if ((! XDR_PUTLONG(xdrs, (long *)&proc)) || + (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || + (! AUTH_WRAP(cl->cl_auth, xdrs, xargs, argsp))) + return (cu->cu_error.re_status = RPC_CANTENCODEARGS); +\end{verbatim} + +AUTH_WRAP is a macro that takes the four arguments for an ah_wrap +function and extracts and calls the function pointer from the cl_auth +structure with the specified arguments. + +Similarly, the transport mechanism must unwrap procedure results. +Again, the UDP mechanism will be instructive. It used to deserialize +function results like this: + +\begin{verbatim} + reply_msg.acpted_rply.ar_results.where = resultsp; + reply_msg.acpted_rply.ar_results.proc = xresults; + + ok = xdr_replymsg(&reply_xdrs, &reply_msg); +\end{verbatim} + +The problem here is that xdr_replymsg deserializes an entire reply +message, including the results. Since xresults and resultsp are the +function and pointer to decode the results, they will be automatically +deserialized {\it without} ah_unwrap being invoked. The simplest +solution (which is also the normal method used by the TCP mechanism) +is to arrange to deserialize the function results explicitly: + +\begin{verbatim} + reply_msg.acpted_rply.ar_results.where = NULL; + reply_msg.acpted_rply.ar_results.proc = xdr_void; + + if ((! xdr_replymsg(&reply_xdrs, &reply_msg)) || + (! AUTH_UNWRAP(cl->cl_auth, reply_xdrs, xresults, + resultsp))) { + return (cu->cu_error.re_status = RPC_CANTENCODEARGS); + } +\end{verbatim} + +Since xdr_void does not read any data from the XDR stream, the +function results are still available when AUTH_UNWRAP is called. Note +that AUTH_UNWRAP should only be called on {\it successful} calls; if +the reply message status is not RPC_SUCCESS there are no arguments to +read. + +Currently, the UDP and TCP transport mechanisms has been +converted.\footnote{The ``raw'' mechanism, for direct connections, has +not been.} + +\subsection{Service Side Authentication, SVCAUTH and XPRT} + +Standard Sun RPC service-side authentication consists of a single +function per authentication flavor; there is no concept of an AUTH +structure containing function pointers and private data as with the +client side. Previously, nothing else was necessary, because each +flavor only did a single thing (authenticated individual calls in a +stateless manner). More functions and state are now required, +however; they are stored in the SVCAUTH structure, see figure +\ref{fig:svcauth}. + +\begin{figure}[htbp] +\begin{verbatim} +typedef struct { + struct svc_auth_ops { + int (*svc_ah_wrap)(); + int (*svc_ah_unwrap)(); + } *svc_ah_ops; + caddr_t svc_ah_private; +} SVCAUTH; +\end{verbatim} +\caption{The new SVCAUTH structure.} +\label{fig:svcauth} +\end{figure} + +There is one SVCAUTH structure per authentication flavor (there is a +default, svc_auth_any, for existing authentication flavors that do not +need the extra functionality). The svc_ah_wrap and svc_ah_unwrap +perform the same logical function as their client-side counterparts. + +Just as with the client side, it is the responsibility of the +transport mechanism to call the svc_ah_wrap and svc_ah_unwrap +functions associated with the authentication flavor associated with +each RPC call at the appropriate time. Unfortunately, the transport +mechanism code does not have access to the RPC call structure +containing the authenticator flavor because the RPC call structure +itself is not passed as an argument to the necessary functions. The +present solution is to add another argument to the transport mechanism +structure, xp_auth, that stores the SVCAUTH of the {\it current} call +on that mechanism; see figure \ref{fig:xprt}. xp_auth is initialized +to svc_auth_any so that existing authentication mechanisms that do not +set the field will still operate correctly. \footnote{This is not an +great solution, because it forces each transport mechanism to be +single threaded. The correct solution is to store the SVCAUTH +associated with each RPC call in the RPC call structure; however, +doing so would require changing a lot of code to pass around the RPC +call structure that currently does not do so. Since other parts of +Sun RPC use the XPRT structure in a non-reentrant way, the present +solution does not make the situation any +worse.}$^{\mbox{,}}$\footnote{A somewhat irrelevant side effect of +adding SVCAUTH to XPRT is that the standard include file +$<$rpc/rpc.h$>$ had to be changed to include $<$rpc/svc_auth$>$ before +$<$rpc/svc.h$>$, whereas they used to be in the opposite order.} + +\begin{figure}[htbp] +\begin{verbatim} +typedef struct { + int xp_sock; + u_short xp_port; /* associated port number */ + struct xp_ops { + bool_t (*xp_recv)(); /* receive incomming requests */ + enum xprt_stat (*xp_stat)(); /* get transport status */ + bool_t (*xp_getargs)(); /* get arguments */ + bool_t (*xp_reply)(); /* send reply */ + bool_t (*xp_freeargs)();/* free mem allocated for args */ + void (*xp_destroy)(); /* destroy this struct */ + } *xp_ops; + int xp_addrlen; /* length of remote address */ + struct sockaddr_in xp_raddr; /* remote address */ + struct opaque_auth xp_verf; /* raw response verifier */ + SVCAUTH *xp_auth; /* auth flavor of current req */ + caddr_t xp_p1; /* private */ + caddr_t xp_p2; /* private */ +} SVCXPRT; +\end{verbatim} +\caption{The modified XPRT structure, with the xp_auth field.} +\label{fig:xprt} +\end{figure} + +Finally, with the modified XPRT structure carrying around the +authentication flavor structure, the functions that serialize and +deserialize function arguments and results must be modified to use the +svc_ah_wrap and svc_ah_unwrap functions. Each service-side transport +mechanism has getargs and reply functions that must be modified to use +the SVCAUTH_UNWRAP and SVCAUTH_WRAP macros, respectively, in a manner +completely parallel to the client side. + +\subsection{Authenticated Service Identification, svc_req} + +Sun RPC provides the authenticated credentials of a client to the +application server via rq_clntcred (``cooked credentials'') field of +the service request (svc_req) structure. In many authentication +systems, services are also named entities, and there is no reason that +an RPC should be restricted to accepting connections as a single +authenticated service name. However, access control decisions may be +based on the service name a client authenticated to, so that +information must be available to the application server. + +Figure \ref{fig:svc-req} shows the modified service request structure +that contains a single new field, rq_svccred. Like rq_clntcred, the +authentication flavor is responsible for setting rq_svccred to the +``cooked'' service credentials associated with a given RPC call. +Authentication flavors that do not have the concept of service names +can of course leave this field blank. + +\begin{figure}[htbp] +\begin{verbatim} +struct svc_req { + u_long rq_prog; /* service program number */ + u_long rq_vers; /* service protocol version */ + u_long rq_proc; /* the desired procedure */ + struct opaque_auth rq_cred; /* raw creds from the wire */ + caddr_t rq_clntcred; /* read only cooked client cred */ + caddr_t rq_svccred; /* read only cooked svc cred */ + SVCXPRT *rq_xprt; /* associated transport */ +}; +\end{verbatim} +\caption{The modified svc_req structure, with the rq_svccred field.} +\label{fig:svc-req} +\end{figure} + + + +\subsection{Authentication Negotiation, no_dispatch} + +In order to avoid having to transmit a full set of authentication +information with every call, the service-side authentication mechanism +must save state between calls. Establishing that state may require +multiple messages between the client-side and service-side +authentication mechanisms. The client-side authentication mechanism +can make arbitrary RPC calls to the server simply by requiring the +programmer to specify the CLIENT structure to the authentication +flavor initialization routine. The service side, however, is more +complex. In the normal course of events, an RPC call comes in, is +authenticated, and is then dispatched to the appropriate procedure. +For client- and service-side authentication flavors to communicate +independent of the server implemented above the RPC layer, the +service-side flavor must be able to send a reply to the client +directly and {\it prevent} the call from being dispatched. + +This is implemented by a simple modification to the _authenticate +routine, which dispatches each RPC call to the appropriate +authentication flavor; see figure \ref{fig:authenticate}. It takes an +additional argument, no_dispatch, that instructs the mechanism not to +dispatch the RPC call to the specified procedure. + +\begin{figure}[htbp] +\begin{verbatim} + why=_authenticate(&r, &msg, &no_dispatch); + if (why != AUTH_OK) { + svcerr_auth(xprt, why); + goto call_done; + } else if (no_dispatch) { + goto call_done; + } +\end{verbatim} +\caption{A call to the modified _authenticate.} +\label{fig:authenticate} +\end{figure} + +If _authenticate sets no_dispatch to true, the call is considered +finished and no procedure dispatch takes place. Presumably, an +authentication flavor that sets no_dispatch to true also replies to +the RPC call with svc_sendreply. Authentication flavors that do not +modify no_dispatch implicitly leave it set to false, so the normal +dispatch takes place. + +\subsection{Affected Files} + +Table \ref{tab:modfiles} lists the files that were +affected for each of the modifications described in previous sections. + +\begin{table}[htbp] +\centering +\caption{Files modified for each change to Sun RPC.} +\label{tab:modfiles} +\begin{tabular}{ll} +AUTH structure & auth.h \\ + & auth_none.c \\ + & auth_exit.c \\ + & auth_any.c \\ +Client Transport Mechanisms & clnt_udp.c \\ + & clnt_tcp.c \\ +SVCAUTH and XPRT structures & rpc.h \\ + & svc.h \\ + & svc_auth.h \\ + & svc.c \\ + & svc_auth.c \\ + & svc_auth_any.c \\ + & svc_auth_unix.c \\ +Server Transport Mechanisms & svc_udp.c \\ + & svc_tcp.c +\end{tabular} +\end{table} + +\section{GSS-API Authentication Flavor} + +The following sections describe the implementation of the GSS-API +authentication flavor for Sun RPC. + +\subsection{Authentication Algorithms} +\label{sec:algorithms} + +\subsubsection{Context Initiation} + +The client creates a GSS-API context with the server each time it +calls auth_gssapi_create. The context is created using the standard +gss_init_sec_context and gss_accept_sec_context function calls. The +generated tokens are passed between the client and server as arguments +and results of normal RPC calls. + +The client side, in auth_gssapi_create, performs the following steps +to initiate a context: + +\begin{enumerate} +\item\label{item:process-token} The client calls gss_init_sec_context. +On the first such call, no input token is provided; on subsequent +calls, the token received from the server is provided. + +\item If gss_init_sec_context produces an output token: + +\begin{enumerate} +\item The client transmits the token to the server, identifying itself +with client_handle if it has already been received (see next step). +The return value from the server will contain a client_handle and one +or both of a token and a signed initial sequence number. + +\item If this is the first response from the server, the client_handle +is stored for subsequent calls. Otherwise, the client_handle should be +the same as returned on the previous call. + +\item If the response contains a signed initian sequence number but +the context is not yet established, then the response also contains a +token that will established the context. The signed initial sequence +number is stored. + +\item If the response contains a token, step \ref{item:process-token} +repeated. +\end{enumerate} + +\item The signed initial sequence number is verified using the +established context. +\end{enumerate} + +The server side, in _svcauth_gssapi, performs the following steps to +initiate a context: + +\begin{enumerate} +\item If a call arrives with no client_handle, a new client_handle is +allocated and stored in the database. Otherwise, the client's +previous state is is looked up in the database. + +\item The received token is passed to gss_accept_sec_context. If an +output token is generated, it is returned to the client. Note that +since the application server may have registered multiple service +names and there is no way to determine {\it a priori} which service a +token is for, _svcauth_gssapi calls gss_accept_sec_context once for +each registered credential until one of them succeeds. The code +assumes that GSS_S_FAILURE is the only error that can result from a +credential mismatch, so any other error terminates the loop +immediately. + +\item If the context is established, the server signs an initial +sequence number and returns it to the client. +\end{enumerate} + +Note that these algorithms require context establishment to be +synchronous. If gss_init_sec_context returns GSS_S_COMPLETE upon +processing a token, it will either produce a token or not. If it +does, then gss_accept_sec_context will return GSS_S_COMPLETE when that +token is processed; if it does not, then gss_accept_sec_context +already returned GSS_S_COMPLETE (and presumably returned the token +that caused gss_init_sec_context to return GSS_S_COMPLETE when +processed). The reverse is also true. + +\subsubsection{RPC Calls} + +After the GSS-API context is established, both the server and the +client possess a client handle and a corresponding sequence number. +Each call from the client contains the client handle as the +``credential'' so that the server can identify which context to apply +to the call. + +Each client call and server response includes a ``verifier'' that +contains the sealed current sequence number.\footnote{In a future +version, the verifier will also contain a signature block for the call +header, including the procedure number called.} The sequence number +prevents replay attacks\footnote{Although some GSS-API mechanisms +provide replay detection themselves, not all of them do; explicitly +including the sequence number in the RPC therefore provides better +end-to-end security}, but by itself it does not prevent splicing +attacks. + +Each procedure argument and result block consists of the current +sequence number and the actual serialized argument string, all sealed +with gss_seal. Combining the sequence number with the argument/result +data prevents splicing attacks. + +The sequence number is incremented by one for each RPC call and by one +for each response. The client and server will both reject messages +that do not contain the expected sequence number. Packets +retransmitted by the client should use the {\it same} sequence number +as the original packet, since even if the server receives multiple +copies only one will be honored. + +\subsection{RPC Call Credential Structure} + +Every message transmitted from the client to the server has a +credentials (cb_cred) field of the type auth_gssapi_creds: + +\begin{verbatim} +typedef struct _auth_gssapi_creds { + bool_t auth_msg; + gss_buffer_desc client_handle; +}; +\end{verbatim} + +The auth_msg field indicates whether the message is intended for the +authentication mechanism for the actual server. Any message whose +auth_msg field is true is processed by the authentication mechanism; +any message whose auth_msg is false is passed to the application +server's dispatch function if authentication succeeds. All messages +must have an auth_msg of true until the context is established, since +authentication cannot succeed until it is. + +The client_handle field contains the client handle obtained from the +first call to the server. On the first call, this field is empty. + +\subsection{GSS-API Authentication Flavor Procedures} + +The GSS-API authentication flavor uses standard RPC calls over the +client handle it is provided for the interactions described in +\ref{sec:algorithms}. All of the following procedures require the +auth_msg field in the credentials to be true; otherwise, the +server-side authentication flavor will simply attempt to authenticate +the caller and pass the call to the application server. The +server-side authentication flavor uses the no_dispatch variable to +indicate that it has handled the call. + +\subsubsection{AUTH_GSSAPI_INIT, AUTH_GSSAPI_CONTINUE_INIT} + +Context initiation is performed via AUTH_GSSAPI_INIT and +AUTH_GSSAPI_CONTINUE_INIT. The former is used to transfer the first +token generated by gss_init_sec_context, when no client handle is +included in the credentials; the latter is used on subsequent calls, +when a client handle is included. + +Both procedures take an argument of type auth_gssapi_init_arg and +return results of the type auth_gssapi_init_res. + +\begin{verbatim} +typedef struct _auth_gssapi_init_arg { + u_long version; + gss_buffer_desc token; +} auth_gssapi_init_arg; +\end{verbatim} + +\begin{description} +\item[version] Three versions are presently defined. + +\begin{description} +\item[1] The original version, as described in this document + +\item[2] In earlier versions of Secure there was a bug in the GSS-API +library that affected the contents of accept_sec_context output +tokens. A client specifies version 2 to indicate that it expects the +correct (fixed) behavior. If the server indicates AUTH_BADCRED or +AUTH_FAILED it does not understand this version, so the client should +fall back to version 1. + +\item[3] Version three indicates that channel bindings are in use. +The client must specify channel bindings with the version, and the +server will as well. If the server indicates AUTH_BADCRED or +AUTH_FAILED it does not understand this version, so the client should +fall back to version 2 (and cease specifying channel bindings). + +\item[4] The previous versions all used the old GSS-API krb5 mechanism +oid; this version uses the new one specified in the RFC. +\end{description} + +\item[token] The token field contains the token generated by +gss_init_sec_context. +\end{description} + +\begin{verbatim} +typedef struct _auth_gssapi_init_res { + u_long version; + gss_buffer_desc client_handle; + gss_buffer_desc token; + OM_uint32 gss_major, gss_minor; + gss_buffer_desc signed_isn; +} auth_gssapi_init_res; +\end{verbatim} + +\begin{description} +\item[version] There are two versions currently defined. +\begin{description} +\item[1] The original version, as described in this document. This is +the response version for {\it both} versions 1 and 2. The Secure 1.1 +server will always return this version. + +\item[3] Version three indicates that the server specified channel +bindings in response to a call arg version number of three. The +server must not specify this version unless the client does. +\end{description} + +\item[client_handle] The client_handle field contains the client +handle that the client must use in the credentials field in all +subsequent RPC calls. In response to AUTH_GSSAPI_CONTINUE_INIT, it is +the same client handle that arrived in the credentials. + +\item[gss_major, gss_minor] The GSS-API error codes that resulted from +processing the auth_gssapi_init_arg. If gss_major is GSS_S_COMPLETE, +the argument token was processed successfully. Otherwise, gss_major +and gss_minor contain the relevant major and minor status codes, and +the context currently being negotiated is no longer valid. + +\item[token] In any response that the client is expecting another +token (i.e.: gss_init_sec_context last returned GSS_S_CONTINUE), the +token field contains the output token from gss_accept_sec_context. If +the client is not expecting a token and this field is not empty, an +error has occurred. + +\item[signed_isn] If the client is not expecting another token (i.e.: +the previous call to gss_init_sec_context yielded a token and returned +GSS_S_COMPLETE) or the supplied token completes the context, the +signed_isn field contains the signed initial sequence number. The +server expects the first RPC call to have a sequence number one +greater than the initial sequence number (so that the signed_isn block +cannot be replayed). If the client is expecting another token and the +signed_isn field is not empty, an error has occurred. +\end{description} + +\subsubsection{AUTH_GSSAPI_DESTROY} + +Context tear-down is performed via AUTH_GSSAPI_DESTROY. This +procedure takes no arguments and returns no results; it merely informs +the server that the client wishes to destroy the established context. + +When a client wishes to tear down an established context between +itself and a server, auth_gssapi_destroy first calls the +AUTH_GSSAPI_DESTROY procedure. The server authenticates the message +and immediately sends a ``success'' response with no results. The +client and server then both independently call gss_delete_sec_context +and discard the context-destruction token that is generated. + +No RPC error checking is performed by either the client or the server. +The client waits a brief time for a success response from the server, +but if none arrives it destroys the context anyway since presumably +the user is waiting for the application to exit. The server similar +ignores any RPC errors since it knows that the client will ignore any +errors that are reported. + +\subsection{RPC Call Authentication Implementation} + +Once the context has been established, all subsequent RPC calls are +authenticated via the verifier described in section +\ref{sec:algorithms}. + +auth_gssapi_marshall, invoked via AUTH_MARSHALL while the RPC call is +being created on the client side, serializes the client_handle +obtained during context initiation {\it in plaintext} as the +credentials and serializes the current sequence number, sealed with +gss_seal, as the verifier. + +auth_gssapi_wrap, invoked next via AUTH_WRAP, serializes a sealed +token containing both the sequence number of the current call and the +serialized arguments. + +_svcauth_gssapi, invoked on the server side by _authenticate, uses the +client_handle contained in the credentials to look up the correct +context and verifies the sequence number provided in the verifier; if +the sequence number is not correct, it declares a potential replay +attack.\footnote{Retransmitted packets will appear as replay attacks, +of course.} The response verifier is set to the serialized sealed +incremented sequence number. + +svc_auth_gssapi_unwrap, invoked when either the application server or +_svcauth_gssapi (in response to an AUTH_GSSAPI authentication flavor +message) attempts to read its arguments, deserialzes and unseals the +block containing the current sequence number and serialized arguments. +If the sequence number is incorrect, it declares a splicing attack; +otherwise, it unserializes the arguments into the original structure. + +svc_auth_gssapi_wrap, invoked when either the application server or +_svcauth_gssapi attempts to write its response, performs the same +operation as auth_gssapi_wrap. + +auth_gssapi_validate, invoked by the client-side RPC mechanism when +an RPC_SUCCESS response is received, verifies that the returned sequence +number is one greater than the previous value sent by +auth_gssapi_marshall. + +Finally, auth_gssapi_unwrap, invoked by the client-side RPC mechanism +after auth_gssapi_validate succeeds, performs the same operation as +svc_auth_gssapi_unwrap. + +If an RPC request generates an error message (a status of other than +RPC_SUCCESS), auth_gssapi_refresh is called. If the error status is +AUTH_REJECTEDVERF, then the server rejected the sequence number as +invalid or replayed. The client guesses that, on some previous call, +the server received a message but the server's response did not make +it back to the client; this could happen if the packet got lost or if +the server was being debugged and the client timed out waiting for it. +As a result, the server is expected a higher sequence number than the +client sent. auth_gssapi_refresh increments the sequence number and +returns true so that the call will be tried again. The transport +mechanism will only call auth_gssapi_refresh twice for each RPC +request, so if some other error occurred an infinite loop will not +result; however, it is unlikely the the client and server will be able +to resynchronize after such an event. + +\subsection{Client State Information} + +The client-side GSS-API authentication flavor maintains an +auth_gssapi_data structure for each authentication instance: + +\begin{verbatim} +struct auth_gssapi_data { + bool_t established; + CLIENT *clnt; + gss_ctx_id_t context; + gss_buffer_desc client_handle; + u_long seq_num; + int def_cred; + + /* pre-serialized ah_cred */ + u_char cred_buf[MAX_AUTH_BYTES]; + u_long cred_len; +}; +\end{verbatim} + +The established field indicates whether the authentication context +between the client and server has been established. It is set to true +when gss_init_sec_context returns GSS_S_COM\-PLETE. When this field is +false, the auth_gssapi functions marshall, validate, wrap, and unwrap +mimic the ``no authentication'' flavor since there is no context with +which to perform authentication functions.\footnote{This field is +necessary because, when auth_gssapi_create calls clnt_call to make an +RPC call, it has to have set the client's authentication flavor to +AUTH_GSSAPI; otherwise, the service-side RPC mechanism will not know +to dispatch the call to _svcauth_gssapi. However, with the client's +authentication flavor set, all of the authentication flavor's +functions will be automatically invoked, even though they are not +ready to operate.} + +The clnt field contains the RPC client structure that can be used to +communicate with the GSS-API authentication flavor on the server. + +The context field contains the context structure created by +gss_init_sec_context. + +The client_handle field contains the client handle used on all RPC +calls except the first one; the handle is obtained as the result of +the first call. + +The sequence_number field contains the sequence number that will be +used when transmitting RPC calls to the server and verifying the +server's responses after the context is initialized. + +The def_cred field is true if gss_init_sec_context created a default +credential, in which case the authentication mechanism is responsible +for releasing the default credential that gets automatically +allocated. + +The cred_buf and cred_len fields contain the pre-serialized +credentials structure used in each call. This provides a small +performance enhancement since the credentials structure does not +change very often; the same pre-serialized version can be used on +virtually every call. + +\subsection{Server State Information} +\label{sec:server-state} + +The server-side GSS-API authentication flavor maintains an +svcauth_gssapi_data structure for each established or partially +established context: + +\begin{verbatim} +typedef struct _svc_auth_gssapi_data { + bool_t established; + gss_ctx_id_t context; + gss_name_t client_name, server_name; + gss_cred_id_t server_creds; + + u_long expiration; + u_long seq_num; + u_long key; + + SVCAUTH svcauth; +} svc_auth_gssapi_data; +\end{verbatim} + +The established field indicates whether the context is fully +established. + +The context field contains the context created by +gss_accept_sec_context. + +The client_name field contains the client's authenticated name, as +returned by gss_accept_sec_context. _svcauth_gssapi sets the ``cooked +credentials'' field of the RPC call structure to this value after the +call is authenticated; the application server can use it to perform +authorization. + +The server_name field contains the service name that the client +established a context with. This is useful if the application server +registered more than one service name with the library; it allows the +server to determine which service the client chose. + +The server_creds field contains the service credentials that the +client established a context with. It is used to avoid having to scan +through the server_creds_list multiple times in the case that context +establishment requires more than one round-trip to the server. + +The expiration field contains the expiration time of the context, as a +Unix timestamp. If a context has no expiration (time_rec is +GSS_C_INDEFINITE), the expiration time is set to 24 hours in the +future. When the structure is created, before the context is +established, the expiration time is initialized to small duration +(currently 5 minutes) so that partially created and abandoned contexts +will be expired quickly. + +The seq_num field is the current sequence number for the client. + +The key field is the client's key into the hash table (see below). +The client_handle field sent to the client is the key treated as an +arbitrary four-byte string. + +The svcauth field is a kludge that allows the svc_auth_gssapi +functions to access the per-client data structure while processing a +call. One SVCAUTH structure is allocated for each client structure, +and the svc_ah_private field is set to the corresponding client. The +client's svcauth field is then set to the new SVCAUTH structure, so +that client_data->svcauth->svc_ah_private == client_data. As each +request is processed, the transport mechanism's xp_auth field is set +to the client's svcauth field; thus, the server-side functions that +dispatch to server-side authentication flavors can access an +appropriate SVCAUTH structure, and the server-side authentication +function that is called can determine the appropriate per-client +structure from the SVCAUTH structure. + +The per-client structures are all stored both in a BSD 4.4 db library +hash table and b-tree. The hash table maps client handles (key +fields) the client structures, and is used to look up client +structures based on the client_handle field of a call's credentials +structure. The b-tree stores the client structures as keys, sorted by +their expiration time. Each time _svcauth_gssapi is activated, it +traverses the tree and destroys all client structures that have +expired. + +\end{document} diff --git a/krb5-1.21.3/doc/thread-safe.txt b/krb5-1.21.3/doc/thread-safe.txt new file mode 100644 index 00000000..d6c8c6ea --- /dev/null +++ b/krb5-1.21.3/doc/thread-safe.txt @@ -0,0 +1,241 @@ +[May be out of date. Last significant update: Jan 2005.] + +In general, it's assumed that the library initialization function (if +initialization isn't delayed) and the library finalization function +are run in some thread-safe fashion, with no other parts of the +library in question in use. (If dlopen or dlsym in one thread starts +running the initializer, and then dlopen/dlsym in another thread +returns and lets you start accessing functions or data in the library +before the initializer is finished, that really seems like a +dlopen/dlsym bug.) + +It's also assumed that if library A depends on library B, then library +B's initializer runs first, and its finalizer last, whether loading +dynamically at run time or at process startup/exit. (It appears that +AIX 4.3.3 may violate this, at least when we use gcc's +constructor/destructor attributes in shared libraries.) + +Support for freeing the heap storage allocated by a library has NOT, +in general, been written. There are hooks, but often they ignore some +of the library's local storage, mutexes, etc. + +If shared library finalization code doesn't get run at all at dlclose +time, or if we can't use it because the execution order is wrong, then +you'll get memory leaks. Deal with it. + +Several debugging variables that are not part of our official API are +not protected by mutexes. In general, the only way to set them is by +changing the sources and recompiling, which obviously has no run-time +thread safety issues, or by stopping the process under a debugger, +which we blithely assert is "safe enough". + +Debug code that we don't normally enable may be less thread safe than +might be desired. For example, multiple printf calls may be made, +with the assumption that the output will not be intermixed with output +from some other thread. Offhand, I'm not aware of any cases where +debugging code is "really" unsafe, as in likely to crash the program +or produce insecure results. + +Various libraries may call assert() and abort(). This should only be +for "can't happen" cases, and indicate programming errors. In some +cases, the compiler may be able to infer that the "can't happen" cases +really can't happen, and drop the calls, but in many cases, this is +not possible. + +There are cases (e.g., in the com_err library) where errors arising +when dealing with other errors are handled by calling abort, for lack +of anything better. We should probably clean those up someday. + +Various libraries call getenv(). This is perfectly safe, as long as +nothing is calling setenv or putenv or what have you, while multiple +threads are executing. Of course, that severely curtails the ability +to control our libraries through that "interface". + +Various libraries call the ctype functions/macros (isupper, etc). It +is assumed that the program does not call setlocale, or does so only +while the program is still single-threaded or while calls into the +Kerberos libraries are not in progress. + +The Windows thread safety support is unfinished. + +I'm assuming that structure fields that are never written to (e.g., +after a structure has been initialized and *then* made possibly +visible to multiple threads) are safe to read from one thread while +another field is being updated by another thread. If that's not the +case, some more work is needed (and I'd like details on why it's not +safe). + +---------------- + +libcom_err + +Issues: + +The callback hook support (set_com_err_hook, reset_com_err_hook, and +calls to com_err and com_err_va) uses a mutex to protect the handle on +the hook function. As a side effect of this, if a callback function +is registered which pops up a window and waits for the users' +acknowledgement, then other errors cannot be reported by other threads +until after the acknowledgement. This could be fixed with +multiple-reader-one-writer type locks, but that's a bit more +complicated. + +The string returned by error_message may be per-thread storage. It +can be passed off between threads, but it shouldn't be in use by any +thread by the time the originating thread calls error_message again. + +Error tables must no longer be in use (including pointers returned by +error_message) when the library containing them is unloaded. + +Temporary: A flag variable has been created in error_message.c which +is used to try to catch cases where remove_error_table is called after +the library finalization function. This generally indicates +out-of-order execution of the library finalization functions. The +handling of this flag is not thread-safe, but if the finalization +function is called, other threads should in theory be finished with +this library anyways. + +Statics: error_message.c, com_err.c, covered above. + +---------------- + +libprofile (and its use in libkrb5) + +Does no checks to see if it's opened multiple instances of the same +file under different names. Does not guard against trying to open a +file while another thread or process is in the process of replacing +it, or two threads trying to update a file at the same time. The +former should be pretty safe on UNIX with atomic rename, but on +Windows there's a race condition; there's a window (so to speak) where +the filename does not correspond to an actual file. + +Statics: prof_file.c, a list of opened config files and their parse +trees, and a mutex to protect it. + +---------------- + +libk5crypto + +Uses ctype macros; what happens if the locale is changed in a +multi-threaded program? + +Debug var in pbkdf2.c. + +Statics: pbkdf2.c: debug variable. + +Statics: crypto_libinit.c: library initializer aux data. + +---------------- + +libkrb5 + +(TBD) + +Uses: ctype macros + +Uses: getaddrinfo, getnameinfo. According to current specifications, +getaddrinfo should be thread-safe; some implementations are not, and +we're not attempting to figure out which ones. NetBSD 1.6, for +example, had an unsafe implementation. + +Uses: res_ninit, res_nsearch. If these aren't available, the non-'n' +versions will be used, and they are sometimes not thread-safe. + +Uses: mkstemp, mktemp -- Are these, or our uses of them, likely to be +thread-safe? + +Uses: sigaction + +The use of sigaction is in the code prompting for a password; we try +to catch the keyboard interrupt character being used and turn it into +an error return from that function. THIS IS NOT THREAD-SAFE. + +Uses: tcgetattr, tcsetattr. This is also in the password-prompting +code. These are fine as long as no other threads are accessing the +same terminal at the same time. + +Uses: fopen. This is thread-safe, actually, but a multi-threaded +server is likely to be using lots of file descriptors. On 32-bit +Solaris platforms, fopen will not work if the next available file +descriptor number is 256 or higher. This can cause the keytab code to +fail. + +Statics: prompter.c: interrupt flag + +Statics: ccdefops.c: default operations table pointer + +Statics: ktdefname.c: variable to override default keytab name, NO +LOCKING. DON'T TOUCH THESE VARIABLES, at least in threaded programs. + +Statics: conv_creds.c: debug variable + +Statics: sendto_kdc.c: debug variable, in export list for KDC + +Statics: parse.c: default realm cache, changed to not cache + +Statics: krb5_libinit.c: lib init aux data + +Statics: osconfig.c: various internal variables, probably should be const + +Statics: init_ctx.c: "brand" string; not written. + +Statics: cc_memory.c: list of caches, with mutex. + +Statics: c_ustime.c: last timestamp, to implement "microseconds must +always increment" + +Statics: ktbase.c, ccbase.c, rc_base.c: type registries and mutexes. + +---------------- + +libgssapi_krb5 + +(TBD) + +Uses: ctype macros + +Statics: acquire_cred.c: name of keytab to use, and mutex. + +Statics: gssapi_krb5.c: + +Statics: init_sec_context.c: + +Statics: set_ccache.c: + +Statics: gssapi_generic.c: OID definitions, non-const by +specification. We probably could make them const anyways. + +The keytab name saved away by krb5_gss_register_acceptor_identity is +global and protected by a mutex; the ccache name stored by +gss_krb5_ccache_name is per-thread. This inconsistency is due to the +anticipated usage patterns. + +The old ccache name returned by gss_krb5_ccache_name if the last +parameter is not a null pointer is also stored per-thread, and will be +discarded at the next call to that routine from the same thread, or at +thread termination. + +Needs work: check various objects for thread safety + +---------------- + +libgssrpc + +New version is in place. Ignore it for now? + +---------------- + +libkadm5* +libkdb5 + +Skip these for now. We may want the KDC libraries to be thread-safe +eventually, so the KDC can take better advantage of hyperthreaded or +multiprocessor systems. + +---------------- + +libapputils +libss + +Used by single-threaded programs only (but see above re KDC). Don't +bother for now. diff --git a/krb5-1.21.3/doc/threads.txt b/krb5-1.21.3/doc/threads.txt new file mode 100644 index 00000000..956fb9ed --- /dev/null +++ b/krb5-1.21.3/doc/threads.txt @@ -0,0 +1,101 @@ +Thread safety in the MIT Kerberos libraries + +The return value from krb5_cc_default_name is a handle on internal +storage from the krb5_context. It is valid only until +krb5_cc_set_default_name or krb5_free_context is called. If +krb5_cc_set_default_name may be called, the calling code must ensure +that the storage returned by krb5_cc_default_name is no longer in use +by that time. + +Any use of krb5_context must be confined to one thread at a time by +the application code. + +Uses of credentials caches, replay caches, and keytabs may happen in +multiple threads simultaneously as long as none of them destroys the +object while other threads may still be using it. (Any internal data +modification in those objects will be protected by mutexes or other +means, within the krb5 library.) + +The simple, exposed data structures in krb5.h like krb5_principal are +not protected; they should not be used in one thread while another +thread might be modifying them. (TO DO: Build a list of which calls +keep references to supplied data or return references to +otherwise-referenced data, as opposed to everything making copies.) + + + +[ This part is a little outdated already. ] + + // Between these two, we should be able to do pure compile-time + // and pure run-time initialization. + // POSIX: partial initializer is PTHREAD_MUTEX_INITIALIZER, + // finish does nothing + // Windows: partial initializer is zero/empty, + // finish does the actual work and runs at load time + // debug: partial initializer sets one magic value, + // finish verifies, sets a new magic value + k5_mutex_t foo_mutex = K5_MUTEX_PARTIAL_INITIALIZER; + int k5_mutex_finish_init(k5_mutex_t *); + // for dynamic allocation + int k5_mutex_init(k5_mutex_t *); + // Must work for both kinds of allocation, even if it means adding + // a flag. + int k5_mutex_destroy(k5_mutex_t *); + // + // Per library, one function to finish the static mutex + // initialization. + // + // A second function called at various possible "first" entry + // points which either calls pthread_once on the first function + // (POSIX), or checks some flag set by the first function (Windows, + // debug support), and possibly returns an error. + // + // A third function for library termination calls mutex_destroy on + // each mutex for the library. + // + // + int k5_mutex_lock(k5_mutex_t *); + int k5_mutex_unlock(k5_mutex_t *); + // Optional (always defined, but need not do anything): + void k5_mutex_assert_locked(k5_mutex_t *); + void k5_mutex_assert_unlocked(k5_mutex_t *); + + + k5_key_t key; + int k5_key_create(k5_key_t *, void (*destructor)(void *)); + void *k5_getspecific(k5_key_t); + int k5_setspecific(k5_key_t, const void *); + ... stuff to signal library termination ... + +This is **NOT** an exported interface, and is subject to change. + +On many platforms with weak reference support, we can declare certain +symbols to be weak, and test the addresses before calling them. The +references generally will be non-null if the application pulls in the +pthread support. Sometimes stubs are present in the C library for +some of these routines, and sometimes they're not functional; if so, +we need to figure out which ones, and check for the presence of some +*other* routines. + +AIX 4.3.3 doesn't support weak references. However, it looks like +calling dlsym(NULL) causes the pthread library to get loaded, so we're +going to just go ahead and link against it anyways. + +On Tru64 we also link against the thread library always. + + +For now, the basic model is: + + If weak references are supported, use them. + Else, assume support is present; if that means explicitly pulling in + the thread library, so be it. + + + +The locking described above may not be sufficient, at least for good +performance. At some point we may want to switch to read/write locks, +so multiple threads can grovel over a data structure at once as long +as they don't change it. + + +See also notes in src/include/k5-thread.h. diff --git a/krb5-1.21.3/doc/tools/README b/krb5-1.21.3/doc/tools/README new file mode 100644 index 00000000..4bed11b0 --- /dev/null +++ b/krb5-1.21.3/doc/tools/README @@ -0,0 +1,62 @@ +How to deploy the Doxygen output in Sphinx project. +==================================================== + +The text below is meant to give the instructions on how to incorporate MIT Kerberos API reference documentation into Sphinx document hierarchy. The Sphinx API documentation can be constructed with (Part B) or without (Part A) the bridge to the original Doxygen HTML output. + +Pre-requisites: +- python 2.5+ with Cheetah, lxml and xml extension modules installed; +- For part B only: + - Sphinx "doxylink" extension; + - Doxygen HTML output + + +Part A: Transforming Doxygen XML output into reStructuredText (rst) without the bridge to Doxygen HTML output. + +1. Delete lines containing text "Doxygen reference" from the template files func_document.tmpl and type_document.tmpl; + +2. In the Doxygen configuration file set GENERATE_XML to YES. Generate Doxygen XML output; + +3. Suppose the Doxygen XML output is located in doxy_xml_dir and the desired output directory is rst_dir. + Run: + python doxy.py -i doxy_xml_dir -o rst_dir -t func + This will result in the storing of the API function documentation files in rst format in the rst_dir. The file names are constructed based on the function name. For example, the file for krb5_build_principal() will be krb5_build_principal.rst + + Run: + python doxy.py -i doxy_xml_dir -o rst_dir -t typedef + It is similar to the API function conversion, but for data types. The result will be stored under rst_dir/types directory + + Alternatively, running + python doxy.py -i doxy_xml_dir -o rst_dir + or + python doxy.py -i doxy_xml_dir -o rst_dir -t all + converts Doxygen XML output into reStructuredText format files both for API functions and data types; + +4. In appdev/index.rst add the following section to point to the API references: + + .. toctree:: + :maxdepth: 1 + + refs/index.rst + +5. Copy the content of rst_dir into appdev/refs/api/ directory and rst_dir/types into appdev/refs/types directory; + +6. Rebuild Sphinx source: + sphinx-build source_dir build_dir + + + + +Part B: Bridge to Doxygen HTML output. + +1. Transform Doxygen XML output into reStructuredText. + In src/Doxygen configuration file request generation of the tag file and XML output: + GENERATE_TAGFILE = krb5doxy.tag + GENERATE_XML = YES + +2. Modify Sphinx conf.py file to point to the "doxylink" extension and Doxygen tag file: + extensions = ['sphinx.ext.autodoc', 'sphinxcontrib.doxylink'] + doxylink = { ' krb5doxy' : ('/tmp/krb5doxy.tag, ' doxy_html_dir ') } + + where doxy_html_dir is the location of the Doxygen HTML output + +3. Continue with steps 3 - 6 of Part A. diff --git a/krb5-1.21.3/doc/tools/define_document.tmpl b/krb5-1.21.3/doc/tools/define_document.tmpl new file mode 100644 index 00000000..8e74dc30 --- /dev/null +++ b/krb5-1.21.3/doc/tools/define_document.tmpl @@ -0,0 +1,27 @@ +.. highlight:: c + +.. $composite.macro_reference($composite.name): + +#set $title = $composite.name +$title +#echo ''.join(['=']*len($title)) # + +.. +.. data:: $composite.name +.. + +#if $composite.short_description is not None and len($composite.short_description) +$composite.short_description +#end if + +$composite.long_description + +#if $composite.name_signature is not None and len($composite.name_signature) +#echo ''.join(['=']*(len($composite.name_signature)+4)) + '== ======================' # +``$composite.name_signature`` ``$composite.initializer`` +#echo ''.join(['=']*(len($composite.name_signature)+4)) + '== ======================' # +#else +#echo ''.join(['=']*(len($composite.name)+4)) + '=== ======================' # +``$composite.name`` ``$composite.initializer`` +#echo ''.join(['=']*(len($composite.name)+4)) + '=== ======================' # +#end if diff --git a/krb5-1.21.3/doc/tools/docmodel.py b/krb5-1.21.3/doc/tools/docmodel.py new file mode 100644 index 00000000..e5d4d11b --- /dev/null +++ b/krb5-1.21.3/doc/tools/docmodel.py @@ -0,0 +1,251 @@ +''' + Copyright 2011 by the Massachusetts + Institute of Technology. All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Furthermore if you modify this software you must label + your software as modified software and not distribute it in such a + fashion that it might be confused with the original M.I.T. software. + M.I.T. makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. +''' +import re + +from Cheetah.Template import Template + +class Attribute(object): + def __init__(self, **argkw): + self.definition = argkw.get('definition') + self.name = argkw.get('name') + self.type = argkw.get('type') + self.typeId = argkw.get('typeId') + self.short_description = argkw.get('short_description') + self.long_description = argkw.get('long_description') + self.version = argkw.get('version') + + def __repr__(self): + result = list() + for (attr,value) in self.__dict__.iteritems(): + result.append('%s=%s' % (attr,value)) + return 'Attribute: %s' % ','.join(result) + + +class CompositeType(): + def __init__(self, **argkw): + self.category = 'composite' + self.definition = argkw.get('definition') + self.name = argkw.get('name') + self.name_signature = argkw.get('name_signature') + self.Id = argkw.get('Id') + self.initializer = argkw.get('initializer') + self.active = argkw.get('active', False) + self.version = argkw.get('version') + self.return_type = argkw.get('return_type') + self.short_description = argkw.get('short_description') + self.long_description = argkw.get('long_description') + self.friends = argkw.get('friends') + self.type = argkw.get('type') + self.attributes = self._setAttributes(argkw.get('attributes')) + + def __repr__(self): + result = list() + for (attr,value) in self.__dict__.iteritems(): + if attr == 'attributes': + if value is not None: + attributes = ['%s' % a for a in value] + value = '\n %s' % '\n '.join(attributes) + + result.append('%s: %s' % (attr,value)) + result = '\n'.join(result) + + return result + + def _setAttributes(self, attributes): + result = None + if attributes is not None: + result = list() + for a in attributes: + result.append(Attribute(**a)) + + return result + + def struct_reference(self, name): + result = re.sub(r'_', '-', name) + result = '_%s-struct' % result + + return result + + def macro_reference(self, name): + result = re.sub(r'_', '-', name) + result = '_%s-data' % result + + return result + +class Parameter(object): + def __init__(self, **argkw): + self.seqno = argkw.get('seqno') + self.name = argkw.get('name') + self.direction = argkw.get('direction') + self.type = argkw.get('type') + self.typeId = argkw.get('typeId') + self.description = argkw.get('description') + self.version = argkw.get('version') + + def __repr__(self): + content = (self.name,self.direction,self.seqno,self.type,self.typeId,self.description) + return 'Parameter: name=%s,direction=%s,seqno=%s,type=%s,typeId=%s,descr=%s' % content + +class Function(object): + def __init__(self, **argkw): + self.category = 'function' + self.name = argkw.get('name') + self.Id = argkw.get('Id') + self.active = argkw.get('active', False) + self.version = argkw.get('version') + self.parameters = self._setParameters(argkw.get('parameters')) + self.return_type = argkw.get('return_type') + self.return_description = argkw.get('return_description') + self.retval_description = argkw.get('retval_description') + self.warn_description = argkw.get('warn_description') + self.sa_description = argkw.get('sa_description') + self.notes_description = argkw.get('notes_description') + self.version_num = argkw.get('version_num') + self.short_description = argkw.get('short_description') + self.long_description = argkw.get('long_description') + self.deprecated_description = argkw.get('deprecated_description') + self.friends = argkw.get('friends') + + def _setParameters(self, parameters): + result = None + if parameters is not None: + result = list() + for p in parameters: + result.append(Parameter(**p)) + + return result + + def getObjectRow(self): + result = [str(self.Id), + self.name, + self.category] + + return ','.join(result) + + def getObjectDescriptionRow(self): + result = [self.Id, + self.active, + self.version, + self.short_description, + self.long_description] + + return ','.join(result) + + def getParameterRows(self): + result = list() + for p in self.parameters: + p_row = [self.Id, + p.name, + p.seqno, + p.type, + p.typeId, + p.description, + p.version] + result.append(','.join(p_row)) + + return '\n'.join(result) + + def __repr__(self): + lines = list() + lines.append('Category: %s' % self.category) + lines.append('Function name: %s' % self.name) + lines.append('Function Id: %s' % self.Id) + parameters = [' %s' % p for p in self.parameters] + lines.append('Parameters:\n%s' % '\n'.join(parameters)) + lines.append('Function return type: %s' % self.return_type) + lines.append('Function return type description:\n%s' % self.return_description) + lines.append('Function retval description:\n%s' % self.retval_description) + lines.append('Function short description:\n%s' % self.short_description) + lines.append('Function long description:\n%s' % self.long_description) + lines.append('Warning description:\n%s' % self.warn_description) + lines.append('See also description:\n%s' % self.sa_description) + lines.append('NOTE description:\n%s' % self.notes_description) + lines.append('Version introduced:\n%s' % self.version_num) + lines.append('Deprecated description:\n%s' % self.deprecated_description) + result = '\n'.join(lines) + + return result + + +class DocModel(object): + def __init__(self, **argkw): + if len(argkw): + self.name = argkw['name'] + if argkw['category'] == 'function': + self.category = 'function' + self.function = Function(**argkw) + elif argkw['category'] == 'composite': + self.category = 'composite' + self.composite = CompositeType(**argkw) + + def __repr__(self): + obj = getattr(self,self.category) + return str(obj) + + def signature(self): + param_list = list() + for p in self.function.parameters: + if p.type is "... " : + param_list.append('%s %s' % (p.type,' ')) + else: + param_list.append('%s %s' % (p.type, p.name)) + param_list = ', '.join(param_list) + result = '%s %s(%s)' % (self.function.return_type, + self.function.name, param_list) + + return result + + def save(self, path, template_path): + f = open(template_path, 'r') + t = Template(f.read(),self) + out = open(path, 'w') + out.write(str(t)) + out.close() + f.close() + + +class DocModelTest(DocModel): + def __init__(self): + doc_path = '../docutil/example.yml' + argkw = yaml.load(open(doc_path,'r')) + super(DocModelTest,self).__init__(**argkw) + + def run_tests(self): + self.test_save() + + def test_print(self): + print('testing') + print(self) + + + def test_save(self): + template_path = '../docutil/function2edit.html' + + path = '/var/tsitkova/Sources/v10/trunk/documentation/test_doc.html' + + self.save(path, template_path) + +if __name__ == '__main__': + tester = DocModelTest() + tester.run_tests() diff --git a/krb5-1.21.3/doc/tools/doxy.py b/krb5-1.21.3/doc/tools/doxy.py new file mode 100644 index 00000000..c82f88eb --- /dev/null +++ b/krb5-1.21.3/doc/tools/doxy.py @@ -0,0 +1,64 @@ +''' + Copyright 2011 by the Massachusetts + Institute of Technology. All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Furthermore if you modify this software you must label + your software as modified software and not distribute it in such a + fashion that it might be confused with the original M.I.T. software. + M.I.T. makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. +''' +import sys +import os +import re +from optparse import OptionParser + + +from doxybuilder_types import * +from doxybuilder_funcs import * + + +def processOptions(): + usage = "\n\t\t%prog -t type -i in_dir -o out_dir" + description = "Description:\n\tProcess doxygen output for c-types and/or functions" + parser = OptionParser(usage=usage, description=description) + + parser.add_option("-t", "--type", type="string", dest="action_type", help="process typedef and/or function. Possible choices: typedef, func, all. Default: all.", default="all") + parser.add_option("-i", "--in", type="string", dest="in_dir", help="input directory") + parser.add_option("-o", "--out", type="string", dest= "out_dir", help="output directory. Note: The subdirectory ./types will be created for typedef") + + (options, args) = parser.parse_args() + action = options.action_type + in_dir = options.in_dir + out_dir = options.out_dir + + + if in_dir is None or out_dir is None: + parser.error("Input and output directories are required") + + if action == "all" or action == "typedef": + builder = DoxyBuilderTypes(in_dir, out_dir) + builder.run_all() + + if action == "all" or action == "func" or action == "function": + builder = DoxyBuilderFuncs(in_dir, out_dir) + builder.run_all() + + +if __name__ == '__main__': + parser = processOptions() + + diff --git a/krb5-1.21.3/doc/tools/doxybuilder_funcs.py b/krb5-1.21.3/doc/tools/doxybuilder_funcs.py new file mode 100644 index 00000000..9a11977a --- /dev/null +++ b/krb5-1.21.3/doc/tools/doxybuilder_funcs.py @@ -0,0 +1,594 @@ +''' + Copyright 2011 by the Massachusetts + Institute of Technology. All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Furthermore if you modify this software you must label + your software as modified software and not distribute it in such a + fashion that it might be confused with the original M.I.T. software. + M.I.T. makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. +''' +import sys +import re + +from collections import defaultdict +from xml.sax import make_parser +from xml.sax.handler import ContentHandler +from docmodel import * + +exclude_funcs = ['krb5_free_octet_data'] + +class DocNode(object): + """ + Represents the structure of xml node. + """ + def __init__(self, name): + """ + @param node: name - the name of a node. + @param attributes: a dictionary populated with attributes of a node + @param children: a dictionary with lists of children nodes. Nodes + in lists are ordered as they appear in a document. + @param content: a content of xml node represented as a list of + tuples [(type,value)] with type = ['char'|'element']. + If type is 'char' then the value is a character string otherwise + it is a reference to a child node. + """ + self.name = name + self.content = list() + self.attributes = dict() + self.children = defaultdict(list) + + def walk(self, decorators, sub_ws, stack=[]): + result = list() + decorator = decorators.get(self.name, decorators['default']) + stack.append(decorators['default']) + decorators['default'] = decorator + + for (obj_type,obj) in self.content: + if obj_type == 'char': + if obj != '': + result.append(obj) + else: + partial = obj.walk(decorators,1, stack) + if partial is not None: + result.append(' %s ' % partial) + decorators['default'] = stack.pop() + result = decorator(self, ''.join(result)) + if result is not None: + if sub_ws == 1: + result = re.sub(r'[ ]+', r' ', result) + else: + result = result.strip() + + return result + + def getContent(self): + decorators = {'default': lambda node,value: value} + result = self.walk(decorators, 1) + if len(result) == 0: + result = None + + return result + + def __repr__(self): + result = ['Content: %s' % self.content] + + for (key,value) in self.attributes.iteritems(): + result.append('Attr: %s = %s' % (key,value)) + for (key,value) in self.children.iteritems(): + result.append('Child: %s,%i' % (key,len(value))) + + return '\n'.join(result) + +class DoxyContenHandler(ContentHandler): + def __init__(self, builder): + self.builder = builder + self.counters = defaultdict(int) + self._nodes = None + self._current = None + + def startDocument(self): + pass + + def endDocument(self): + import sys + + def startElement(self, name, attrs): + if name == self.builder.toplevel: + self._nodes = [] + + if name == 'memberdef': + kind = attrs.get('kind') + if kind is None: + raise ValueError('Kind is not defined') + self.counters[kind] += 1 + + if self._nodes is None: + return + + node = DocNode(name) + for (key,value) in attrs.items(): + node.attributes[key] = value + if self._current is not None: + self._current.children[name].append(node) + self._nodes.append(self._current) + self._current = node + + def characters(self, content): + + if self._current is not None: + self._current.content.append(('char',content.strip())) + + def endElement(self, name): + if name == self.builder.toplevel: + assert(len(self._nodes) == 0) + self._nodes = None + self.builder.document.append(self._current) + self._current = None + else: + if self._nodes is not None: + node = self._current + self._current = self._nodes.pop() + self._current.content.append(('element',node)) + + +class XML2AST(object): + """ + Translates XML document into Abstract Syntax Tree like representation + The content of document is stored in self.document + """ + def __init__(self, xmlpath, toplevel='doxygen'): + self.document = list() + self.toplevel = toplevel + self.parser = make_parser() + handler = DoxyContenHandler(self) + self.parser.setContentHandler(handler) + filename = 'krb5_8hin.xml' + filepath = '%s/%s' % (xmlpath,filename) + self.parser.parse(open(filepath,'r')) + + +class DoxyFuncs(XML2AST): + def __init__(self, path): + super(DoxyFuncs, self).__init__(path,toplevel='memberdef') + self.objects = list() + + def run(self): + for node in self.document: + self.process(node) + + def process(self, node): + node_type = node.attributes['kind'] + if node_type == 'function': + data = self._process_function_node(node) + else: + return + + if 'name' in data and data['name'] in exclude_funcs: + return + self.objects.append(DocModel(**data)) + + def save(self, templates, target_dir): + for obj in self.objects: + template_path = templates[obj.category] + outpath = '%s/%s.rst' % (target_dir,obj.name) + obj.save(outpath, template_path) + + + def _process_function_node(self, node): + f_name = node.children['name'][0].getContent() + f_Id = node.attributes['id'] + f_ret_type = self._process_type_node(node.children['type'][0]) + f_brief = node.children['briefdescription'][0].getContent() + f_detailed = node.children['detaileddescription'][0] + detailed_description = self._process_description_node(f_detailed) + return_value_description = self._process_return_value_description(f_detailed) + retval_description = self._process_retval_description(f_detailed) + warning_description = self._process_warning_description(f_detailed) + seealso_description = self._process_seealso_description(f_detailed) + notes_description = self._process_notes_description(f_detailed) + f_version = self._process_version_description(f_detailed) + deprecated_description = self._process_deprecated_description(f_detailed) + param_description_map = self.process_parameter_description(f_detailed) + f_definition = node.children['definition'][0].getContent() + f_argsstring = node.children['argsstring'][0].getContent() + + function_descr = {'category': 'function', + 'name': f_name, + 'Id': f_Id, + 'return_type': f_ret_type[1], + 'return_description': return_value_description, + 'retval_description': retval_description, + 'sa_description': seealso_description, + 'warn_description': warning_description, + 'notes_description': notes_description, + 'short_description': f_brief, + 'version_num': f_version, + 'long_description': detailed_description, + 'deprecated_description': deprecated_description, + 'parameters': list()} + + parameters = function_descr['parameters'] + for (i,p) in enumerate(node.children['param']): + type_node = p.children['type'][0] + p_type = self._process_type_node(type_node) + if p_type[1].find('...') > -1 : + p_name = '' + else: + p_name = None + p_name_node = p.children.get('declname') + if p_name_node is not None: + p_name = p_name_node[0].getContent() + (p_direction,p_descr) = param_description_map.get(p_name,(None,None)) + + param_descr = {'seqno': i, + 'name': p_name, + 'direction': p_direction, + 'type': p_type[1], + 'typeId': p_type[0], + 'description': p_descr} + parameters.append(param_descr) + result = Function(**function_descr) + print(result, file=self.tmp) + + return function_descr + + def _process_type_node(self, type_node): + """ + Type node has form + type_string + for build in types and + + + 'type_name' + + postfix (ex. *, **m, etc.) + + for user defined types. + """ + type_ref_node = type_node.children.get('ref') + if type_ref_node is not None: + p_type_id = type_ref_node[0].attributes['refid'] + else: + p_type_id = None + p_type = type_node.getContent() + # remove some macros + p_type = re.sub('KRB5_ATTR_DEPRECATED', '', p_type) + p_type = re.sub('KRB5_CALLCONV_C', '', p_type) + p_type = re.sub('KRB5_CALLCONV_WRONG', '', p_type) + p_type = re.sub('KRB5_CALLCONV', '', p_type) + p_type = p_type.strip() + + return (p_type_id, p_type) + + def _process_description_node(self, node): + """ + Description node is comprised of ... sections + """ + para = node.children.get('para') + result = list() + if para is not None: + decorators = {'default': self.paragraph_content_decorator} + for e in para: + result.append(str(e.walk(decorators, 1))) + result.append('\n') + result = '\n'.join(result) + + return result + + def return_value_description_decorator(self, node, value): + if node.name == 'simplesect': + if node.attributes['kind'] == 'return': + cont = set() + cont = node.getContent() + return value + else: + return None + + def paragraph_content_decorator(self, node, value): + if node.name == 'para': + return value + '\n' + elif node.name == 'simplesect': + if node.attributes['kind'] == 'return': + return None + elif node.name == 'ref': + if value.find('()') >= 0: + # functions + return ':c:func:' + '`' + value + '`' + else: + # macro's + return ':data:' + '`' + value + '`' + elif node.name == 'emphasis': + return '*' + value + '*' + elif node.name == 'itemizedlist': + return '\n' + value + elif node.name == 'listitem': + return '\n\t - ' + value + '\n' + elif node.name == 'computeroutput': + return '**' + value + '**' + else: + return None + + def parameter_name_decorator(self, node, value): + if node.name == 'parametername': + direction = node.attributes.get('direction') + if direction is not None: + value = '%s:%s' % (value,direction) + return value + + elif node.name == 'parameterdescription': + return None + else: + return value + + def parameter_description_decorator(self, node, value): + if node.name == 'parameterdescription': + return value + elif node.name == 'parametername': + return None + else: + return value + + def process_parameter_description(self, node): + """ + Parameter descriptions reside inside detailed description section. + """ + para = node.children.get('para') + result = dict() + if para is not None: + for e in para: + + param_list = e.children.get('parameterlist') + if param_list is None: + continue + param_items = param_list[0].children.get('parameteritem') + if param_items is None: + continue + for it in param_items: + decorators = {'default': self.parameter_name_decorator} + direction = None + name = it.walk(decorators,0).split(':') + if len(name) == 2: + direction = name[1] + + decorators = {'default': self.parameter_description_decorator, + 'para': self.paragraph_content_decorator} + description = it.walk(decorators, 0) + result[name[0]] = (direction,description) + return result + + + def _process_return_value_description(self, node): + result = None + ret = list() + + para = node.children.get('para') + if para is not None: + for p in para: + simplesect_list = p.children.get('simplesect') + if simplesect_list is None: + continue + for it in simplesect_list: + decorators = {'default': self.return_value_description_decorator, + 'para': self.parameter_name_decorator} + result = it.walk(decorators, 1) + if result is not None: + ret.append(result) + return ret + + + def _process_retval_description(self, node): + """ + retval descriptions reside inside detailed description section. + """ + para = node.children.get('para') + + result = None + ret = list() + if para is not None: + + for e in para: + param_list = e.children.get('parameterlist') + if param_list is None: + continue + for p in param_list: + kind = p.attributes['kind'] + if kind == 'retval': + + param_items = p.children.get('parameteritem') + if param_items is None: + continue + + + for it in param_items: + param_descr = it.children.get('parameterdescription') + if param_descr is not None: + val = param_descr[0].children.get('para') + + if val is not None: + val_descr = val[0].getContent() + + else: + val_descr ='' + + decorators = {'default': self.parameter_name_decorator} + + name = it.walk(decorators, 1).split(':') + + val = name[0] + result = " %s %s" % (val, val_descr) + ret.append (result) + return ret + + def return_warning_decorator(self, node, value): + if node.name == 'simplesect': + if node.attributes['kind'] == 'warning': + return value + else: + return None + + def _process_warning_description(self, node): + result = None + para = node.children.get('para') + if para is not None: + for p in para: + simplesect_list = p.children.get('simplesect') + if simplesect_list is None: + continue + for it in simplesect_list: + decorators = {'default': self.return_warning_decorator, + 'para': self.paragraph_content_decorator} + result = it.walk(decorators, 1) + # Assuming that only one Warning per function + if result is not None: + return result + return result + + def return_seealso_decorator(self, node, value): + if node.name == 'simplesect': + if node.attributes['kind'] == 'see': + return value + else: + return None + + def _process_seealso_description(self, node): + result = None + para = node.children.get('para') + if para is not None: + for p in para: + simplesect_list = p.children.get('simplesect') + if simplesect_list is None: + continue + for it in simplesect_list: + decorators = {'default': self.return_seealso_decorator, + 'para': self.paragraph_content_decorator} + result = it.walk(decorators, 1) + return result + + def return_version_decorator(self, node, value): + if node.name == 'simplesect': + if node.attributes['kind'] == 'version': + return value + else: + return None + + def _process_version_description(self, node): + result = None + para = node.children.get('para') + if para is not None: + for p in para: + simplesect_list = p.children.get('simplesect') + if simplesect_list is None: + continue + for it in simplesect_list: + decorators = {'default': self.return_version_decorator, + 'para': self.paragraph_content_decorator} + result = it.walk(decorators, 1) + if result is not None: + return result + return result + + def return_notes_decorator(self, node, value): + if node.name == 'simplesect': + if node.attributes['kind'] == 'note': + # We indent notes with an extra tab. Do it for all paragraphs. + return value.replace("\n ", "\n\n\t "); + else: + return None + + def _process_notes_description(self, node): + result = None + para = node.children.get('para') + if para is not None: + for p in para: + simplesect_list = p.children.get('simplesect') + if simplesect_list is None: + continue + for it in simplesect_list: + decorators = {'default': self.return_notes_decorator, + 'para': self.paragraph_content_decorator} + result = it.walk(decorators, 1) + if result is not None: + return result + return result + + def return_deprecated_decorator(self, node, value): + if node.name == 'xrefsect': + if node.attributes['id'].find('deprecated_') > -1: + xreftitle = node.children.get('xreftitle') + if xreftitle[0] is not None: + xrefdescr = node.children.get('xrefdescription') + deprecated_descr = "DEPRECATED %s" % xrefdescr[0].getContent() + return deprecated_descr + else: + return None + + def _process_deprecated_description(self, node): + result = None + para = node.children.get('para') + if para is not None: + for p in para: + xrefsect_list = p.children.get('xrefsect') + if xrefsect_list is None: + continue + for it in xrefsect_list: + decorators = {'default': self.return_deprecated_decorator, + 'para': self.paragraph_content_decorator} + result = it.walk(decorators, 1) + if result is not None: + return result + return result + + def break_into_lines(self, value, linelen=82): + breaks = range(0,len(value),linelen) + [len(value)] + result = list() + for (start,end) in zip(breaks[:-1],breaks[1:]): + result.append(value[start:end]) + result = '\n'.join(result) + + return result + + def _save(self, table, path = None): + if path is None: + f = sys.stdout + else: + f = open(path, 'w') + for l in table: + f.write('%s\n' % ','.join(l)) + if path is not None: + f.close() + + + +class DoxyBuilderFuncs(DoxyFuncs): + def __init__(self, xmlpath, rstpath): + super(DoxyBuilderFuncs,self).__init__(xmlpath) + self.target_dir = rstpath + outfile = '%s/%s' % (self.target_dir, 'out.txt') + self.tmp = open(outfile, 'w') + + def run_all(self): + self.run() + templates = {'function': 'func_document.tmpl'} + self.save(templates, self.target_dir) + + def test_run(self): + self.run() + +if __name__ == '__main__': + builder = DoxyBuilderFuncs(xmlpath, rstpath) + builder.run_all() + diff --git a/krb5-1.21.3/doc/tools/doxybuilder_types.py b/krb5-1.21.3/doc/tools/doxybuilder_types.py new file mode 100644 index 00000000..6fa2f02a --- /dev/null +++ b/krb5-1.21.3/doc/tools/doxybuilder_types.py @@ -0,0 +1,382 @@ +''' + Copyright 2011 by the Massachusetts + Institute of Technology. All Rights Reserved. + + Export of this software from the United States of America may + require a specific license from the United States Government. + It is the responsibility of any person or organization contemplating + export to obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of M.I.T. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. Furthermore if you modify this software you must label + your software as modified software and not distribute it in such a + fashion that it might be confused with the original M.I.T. software. + M.I.T. makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. +''' + +import sys +import os +import re +import textwrap + +from lxml import etree + +from docmodel import * + +exclude_types = [ 'TRUE', 'FALSE', 'KRB5_ATTR_DEPRECATED', + 'KRB5_CALLCONV', 'KRB5_CALLCONV_C', 'KRB5_CALLCONV_WRONG', + 'KRB5_GENERAL__', 'KRB5_KEYUSAGE_PA_REFERRAL', + 'KRB5_OLD_CRYPTO', + 'KRB5INT_BEGIN_DECLS', 'KRB5INT_END_DECLS', + 'krb5_cc_ops', 'krb5_octet_data' ] + +class DoxyTypes(object): + def __init__(self, xmlpath): + self.xmlpath = xmlpath + + def run_compound(self, filename, include=None): + path = '%s/%s' % (self.xmlpath,filename) + tree = etree.parse(path) + root = tree.getroot() + + brief_node = root.xpath('./compounddef/briefdescription')[0] + brief_description = self._get_brief_description(brief_node) + details_node = root.xpath('./compounddef/detaileddescription')[0] + detailed_description = self._get_detailed_description(details_node) + + fields = list() + for node in root.iterfind(".//memberdef[@kind]"): + data = {} + kind = node.attrib['kind'] + if include is None or kind in include: + if kind == 'variable': + data = self._process_variable_node(node) + else: + pass + fields.append(data) + + result = {'brief_description': brief_description, + 'detailed_description': detailed_description, + 'attributes': fields} + + return result + + + + def run(self, filename, include=None): + """ + Parses xml file generated by doxygen. + + @param filename: doxygen xml file name + @param include: members sections to include, in None -- include all + """ + path = '%s/%s' % (self.xmlpath,filename) + tree = etree.parse(path) + root = tree.getroot() + result = list() + for node in root.iterfind(".//memberdef[@kind]"): + data = {} + kind = node.attrib['kind'] + if include is None or kind in include: + if kind == 'typedef': + data = self._process_typedef_node(node) + elif kind == 'variable': + data = self._process_variable_node(node) + elif kind == 'define': + data = self._process_define_node(node) + if 'name' in data and data['name'] in exclude_types: + continue + result.append(data) + return result + + + def _process_typedef_node(self, node): + t_name = node.xpath('./name/text()')[0] + + t_Id = node.attrib['id'] + t_definition = node.xpath('./definition/text()')[0] + t_type = self._process_type_node(node.xpath("./type")[0]) + brief_node = node.xpath('./briefdescription')[0] + t_brief = self._get_brief_description(brief_node) + details_node = node.xpath('./detaileddescription')[0] + t_detailed = self._get_detailed_description(details_node) + # remove macros + t_definition = re.sub('KRB5_CALLCONV_C', '', t_definition) + t_definition = re.sub('KRB5_CALLCONV', '', t_definition) + t_definition = re.sub(r'\*', '\\*', t_definition) + # handle fp + if t_type[1].find('(') >= 0: + t_type = (t_type[0],None) + + typedef_descr = {'category': 'composite', + 'definition': t_definition, + 'name': t_name, + 'Id': t_Id, + 'initializer': '', + 'type': t_type[1], + 'short_description': t_brief, + 'long_description': t_detailed, + 'attributes': list() + } + if t_type[0] is not None : + filename = '%s.xml' % t_type[0] + path = '%s/%s' % (self.xmlpath,filename) + if not os.path.exists(path): + # nothing can be done + return typedef_descr + + compound_info = self.run_compound(filename) + if compound_info is not None: + brief_description = compound_info.get('brief_description') + if brief_description is not None and len(brief_description): + # override brief description + typedef_descr['short_description'] = brief_description + detailed_description = compound_info.get('detailed_description') + if detailed_description is not None and len(detailed_description): + # check if this is not a duplicate + if detailed_description.find(t_detailed) < 0: + typedef_descr['long_description'] = '%s\n%s' % \ + (detailed_description, + typedef_descr['long_description']) + typedef_descr['attributes'] = compound_info['attributes'] + return typedef_descr + + def _process_variable_node(self, node): + v_name = node.xpath('./name/text()')[0] + v_Id = node.attrib['id'] + v_definition = node.xpath('./definition/text()')[0] + v_type = self._process_type_node(node.xpath("./type")[0]) + brief_node = node.xpath('./briefdescription')[0] + v_brief = self._get_brief_description(brief_node) + details_node = node.xpath('./detaileddescription')[0] + detailed_description = self._get_detailed_description(details_node) + # remove macros + v_definition = re.sub('KRB5_CALLCONV_C', '', v_definition) + v_definition = re.sub('KRB5_CALLCONV', '', v_definition) + v_definition = re.sub(r'\*', '\\*', v_definition) + + variable_descr = {'category': 'variable', + 'definition': v_definition, + 'name': v_name, + 'Id': v_Id, + 'initializer': '', + 'type': v_type[1], + 'short_description': v_brief, + 'long_description': detailed_description, + 'attributes': list() + } + + return variable_descr + + def _process_define_node(self, node): + d_name = node.xpath('./name/text()')[0] + d_initializer = '' + d_type = '' + d_signature = '' + + # Process param/defname node + if len(node.xpath('./param/defname')) > 0: + prm_str = '' + prm_list = list() + for p in node.xpath("./param"): + x = self._process_paragraph_content(p) + if x is not None and len(x): + prm_list.append(x) + if prm_list is not None: + prm_str = prm_str.join(prm_list) + d_signature = " %s (%s) " % (d_name , prm_str) + d_signature = re.sub(r', \)', ')', d_signature).strip() + + if len(node.xpath('./initializer')) > 0: + len_ref = len(node.xpath('./initializer/ref')) + if len(node.xpath('./initializer/ref')) > 0: + d_type = self._process_type_node(node.xpath("./initializer/ref")[0]) + if len(d_type) > 0: + len_text = len(node.xpath('./initializer/text()')) + if len_text == 0 and d_type[1]: + d_initializer = d_type[1] + if len_text > 0 and len(node.xpath('./initializer/text()')[0]) > 0: + d_initializer = node.xpath('./initializer/text()')[0] + d_type[1] + if len_text > 1: + if node.xpath('./initializer/text()')[1] is not None: + d_initializer = d_initializer + node.xpath('./initializer/text()')[1] + else: + d_initializer = node.xpath('./initializer/text()')[0] + d_Id = node.attrib['id'] + brief_node = node.xpath('./briefdescription')[0] + d_brief = self._get_brief_description(brief_node) + details_node = node.xpath('./detaileddescription')[0] + detailed_description = self._get_detailed_description(details_node) + # Condense multiline macros, stripping leading whitespace. + d_initializer = re.sub(" *\\\\\n *", " ", d_initializer) + + define_descr = {'category': 'composite', + 'definition': '', + 'name': d_name, + 'name_signature': d_signature, + 'Id': d_Id, + 'initializer': d_initializer, + 'type': '', + 'short_description': d_brief, + 'long_description': detailed_description, + 'attributes': list() + } + + return define_descr + + + def _get_brief_description(self, node): + result = list() + for p in node.xpath("./para"): + x = self._process_paragraph_content(p) + if x is not None and len(x): + result.append(x) + result = '\n'.join(result) + + return result + + + def _get_detailed_description(self, node): + """ + Description node is comprised of ... sections. + There are few types of these sections: + a) Content section + b) Return value section -- skip + c) Parameter list section -- skip + @param node: detailed description node + """ + result = list() + for p in node.xpath("./para"): + if len(p.xpath("./simplesect[@kind='return']")): + continue + elif len(p.xpath("./parameterlist[@kind='param']")): + continue + else: + x = self._process_paragraph_content(p) + result.append(x) + result = '\n'.join(result) + + return result + + def _process_paragraph_content(self, node): + + def add_text(l, s): + # Add a space if it wouldn't be at the start or end of a line. + if l and not l[-1].endswith('\n') and not s.startswith('\n'): + l.append(' ') + l.append(s) + + result = list() + content = node.xpath(".//text()") + for e in content: + if e.is_tail or node is e.getparent(): + add_text(result, e.strip()) + elif e.getparent().tag == 'ref': + if e.strip().find('(') > 0: + add_text(result, ':c:func:`%s`' % e.strip()) + elif e.isupper(): + add_text(result, ':c:data:`%s`' % e.strip()) + else: + add_text(result, ':c:type:`%s`' % e.strip()) + elif e.getparent().tag == 'emphasis': + add_text(result, '*%s*' % e.strip()) + elif e.getparent().tag == 'computeroutput': + add_text(result, '*%s*' % e.strip()) + elif e.getparent().tag == 'defname': + add_text(result, '%s, ' % e.strip()) + elif e.getparent().tag == 'verbatim': + add_text(result, '\n::\n\n') + add_text(result, textwrap.indent(e, ' ', lambda x: True)) + add_text(result, '\n') + + result = ''.join(result) + + return result + + def _process_type_node(self, node): + """ + Type node has form + type_string + for build in types and + + + 'type_name' + + postfix (ex. *, **m, etc.) + + for user defined types. + """ + p_id = node.xpath("./ref/@refid") + if len(p_id) == 1: + p_id = p_id[0] + elif len(p_id) == 0: + p_id = None + p_type = ' '.join(node.xpath(".//text()")) + + # remove macros + p_type = re.sub('KRB5_CALLCONV_C', ' ', p_type) + p_type = re.sub('KRB5_CALLCONV', ' ', p_type) + + return (p_id,p_type) + + def save(self, obj, templates, target_dir): + template_path = templates[obj.category] + outpath = '%s/%s.rst' % (target_dir,obj.name) + obj.save(outpath, template_path) + + + +class DoxyBuilderTypes(DoxyTypes): + def __init__(self, xmlpath, rstpath): + self.templates = { 'composite': 'type_document.tmpl'} + self.target_dir = rstpath + + super(DoxyBuilderTypes,self).__init__(xmlpath) + + def run_all(self): + self.process_typedef_nodes() + self.process_define_nodes() + + def test_run(self): + filename = 'krb5_8hin.xml' + self.run(filename) + + def process_variable_nodes(self): + filename = 'struct__krb5__octet__data.xml' + result = self.run(filename, include=['variable']) + + def process_typedef_nodes(self): + # run parser for typedefs + filename = 'krb5_8hin.xml' + result = self.run(filename, include=['typedef']) + target_dir = '%s/types' % (self.target_dir) + if not os.path.exists(target_dir): + os.makedirs(target_dir, 0o755) + for t in result: + obj = DocModel(**t) + self.save(obj, self.templates, target_dir) + + def process_define_nodes(self): + # run parser for define's + filename = 'krb5_8hin.xml' + result = self.run(filename, include=['define']) + target_dir = '%s/macros' % (self.target_dir) + if not os.path.exists(target_dir): + os.makedirs(target_dir, 0o755) + for t in result: + obj = DocModel(**t) + tmpl = {'composite': 'define_document.tmpl'} + self.save(obj, tmpl, target_dir) + +if __name__ == '__main__': + + builder = DoxyBuilderTypes( xml_inpath, rst_outpath) + builder.run_all() diff --git a/krb5-1.21.3/doc/tools/func_document.tmpl b/krb5-1.21.3/doc/tools/func_document.tmpl new file mode 100644 index 00000000..104930b6 --- /dev/null +++ b/krb5-1.21.3/doc/tools/func_document.tmpl @@ -0,0 +1,102 @@ +#if $function.short_description is not None + #set $title = $function.name + ' - ' + $function.short_description +#else + #set $title = $function.name +#end if +$title +#echo ''.join(['=']*len($title)) # + +.. + +.. c:function:: $signature + +.. + + +:param: + +#for $param in $function.parameters: + #if $param.name == '' + #continue + #end if + #if $param.direction is not None + #set name_description = '**[%s]** **%s**' % ($param.direction, $param.name) + #else + #set name_description = '**%s**' % $param.name + #end if + #if $param.description is not None + #set $description= ' - ' + $param.description + #else + #set $description='' + #end if + $name_description$description + +#end for + +.. + +#if len($function.retval_description) > 0 + +:retval: +#for $retval in $function.retval_description: + - $retval +#end for +#end if + +#if len($function.return_description) > 0 + +:return: +#for $retval in $function.return_description: + - $retval +#end for +#end if + +.. + +#if $function.deprecated_description is not None + +$function.deprecated_description +#end if + + + + +#if $function.long_description is not None + + +$function.long_description + +#end if + + +.. + +#if $function.sa_description is not None +.. seealso:: + $function.sa_description +#end if + + +#if $function.warn_description is not None or $function.notes_description is not None + + +#if $function.warn_description is not None +.. warning:: + + $function.warn_description +#end if + +#if $function.notes_description is not None +.. note:: + + $function.notes_description +#end if + +#end if + +#if $function.version_num is not None +.. note:: + + $function.version_num +#end if + diff --git a/krb5-1.21.3/doc/tools/type_document.tmpl b/krb5-1.21.3/doc/tools/type_document.tmpl new file mode 100644 index 00000000..11aafb81 --- /dev/null +++ b/krb5-1.21.3/doc/tools/type_document.tmpl @@ -0,0 +1,43 @@ +.. highlight:: c + +.. $composite.struct_reference($composite.name): + +#set $title = $composite.name +$title +#echo ''.join(['=']*len($title)) # + +.. +.. c:type:: $composite.name +.. + +#if $composite.short_description is not None and len($composite.short_description) +$composite.short_description +#end if + +$composite.long_description + +Declaration +------------ + +$composite.definition + +#if $composite.Id is not None +#if len($composite.attributes) + +Members +--------- + +#end if + +#for $attr in $composite.attributes: +#if $attr.name is not None +.. c:member:: $attr.type $composite.name.$attr.name + + $attr.short_description +#if $attr.long_description is not None + $attr.long_description +#end if + +#end if +#end for +#end if diff --git a/krb5-1.21.3/doc/user/index.rst b/krb5-1.21.3/doc/user/index.rst new file mode 100644 index 00000000..233c3ef5 --- /dev/null +++ b/krb5-1.21.3/doc/user/index.rst @@ -0,0 +1,10 @@ +For users +========= + +.. toctree:: + :maxdepth: 2 + + pwd_mgmt.rst + tkt_mgmt.rst + user_config/index.rst + user_commands/index.rst diff --git a/krb5-1.21.3/doc/user/pwd_mgmt.rst b/krb5-1.21.3/doc/user/pwd_mgmt.rst new file mode 100644 index 00000000..ed7d459f --- /dev/null +++ b/krb5-1.21.3/doc/user/pwd_mgmt.rst @@ -0,0 +1,106 @@ +Password management +=================== + +Your password is the only way Kerberos has of verifying your identity. +If someone finds out your password, that person can masquerade as +you---send email that comes from you, read, edit, or delete your files, +or log into other hosts as you---and no one will be able to tell the +difference. For this reason, it is important that you choose a good +password, and keep it secret. If you need to give access to your +account to someone else, you can do so through Kerberos (see +:ref:`grant_access`). You should never tell your password to anyone, +including your system administrator, for any reason. You should +change your password frequently, particularly any time you think +someone may have found out what it is. + + +Changing your password +---------------------- + +To change your Kerberos password, use the :ref:`kpasswd(1)` command. +It will ask you for your old password (to prevent someone else from +walking up to your computer when you're not there and changing your +password), and then prompt you for the new one twice. (The reason you +have to type it twice is to make sure you have typed it correctly.) +For example, user ``david`` would do the following:: + + shell% kpasswd + Password for david: <- Type your old password. + Enter new password: <- Type your new password. + Enter it again: <- Type the new password again. + Password changed. + shell% + +If ``david`` typed the incorrect old password, he would get the +following message:: + + shell% kpasswd + Password for david: <- Type the incorrect old password. + kpasswd: Password incorrect while getting initial ticket + shell% + +If you make a mistake and don't type the new password the same way +twice, kpasswd will ask you to try again:: + + shell% kpasswd + Password for david: <- Type the old password. + Enter new password: <- Type the new password. + Enter it again: <- Type a different new password. + kpasswd: Password mismatch while reading password + shell% + +Once you change your password, it takes some time for the change to +propagate through the system. Depending on how your system is set up, +this might be anywhere from a few minutes to an hour or more. If you +need to get new Kerberos tickets shortly after changing your password, +try the new password. If the new password doesn't work, try again +using the old one. + + +.. _grant_access: + +Granting access to your account +------------------------------- + +If you need to give someone access to log into your account, you can +do so through Kerberos, without telling the person your password. +Simply create a file called :ref:`.k5login(5)` in your home directory. +This file should contain the Kerberos principal of each person to whom +you wish to give access. Each principal must be on a separate line. +Here is a sample .k5login file:: + + jennifer@ATHENA.MIT.EDU + david@EXAMPLE.COM + +This file would allow the users ``jennifer`` and ``david`` to use your +user ID, provided that they had Kerberos tickets in their respective +realms. If you will be logging into other hosts across a network, you +will want to include your own Kerberos principal in your .k5login file +on each of these hosts. + +Using a .k5login file is much safer than giving out your password, +because: + +* You can take access away any time simply by removing the principal + from your .k5login file. + +* Although the user has full access to your account on one particular + host (or set of hosts if your .k5login file is shared, e.g., over + NFS), that user does not inherit your network privileges. + +* Kerberos keeps a log of who obtains tickets, so a system + administrator could find out, if necessary, who was capable of using + your user ID at a particular time. + +One common application is to have a .k5login file in root's home +directory, giving root access to that machine to the Kerberos +principals listed. This allows system administrators to allow users +to become root locally, or to log in remotely as root, without their +having to give out the root password, and without anyone having to +type the root password over the network. + + +Password quality verification +----------------------------- + +TODO diff --git a/krb5-1.21.3/doc/user/tkt_mgmt.rst b/krb5-1.21.3/doc/user/tkt_mgmt.rst new file mode 100644 index 00000000..9ec7f1e7 --- /dev/null +++ b/krb5-1.21.3/doc/user/tkt_mgmt.rst @@ -0,0 +1,314 @@ +Ticket management +================= + +On many systems, Kerberos is built into the login program, and you get +tickets automatically when you log in. Other programs, such as ssh, +can forward copies of your tickets to a remote host. Most of these +programs also automatically destroy your tickets when they exit. +However, MIT recommends that you explicitly destroy your Kerberos +tickets when you are through with them, just to be sure. One way to +help ensure that this happens is to add the :ref:`kdestroy(1)` command +to your .logout file. Additionally, if you are going to be away from +your machine and are concerned about an intruder using your +permissions, it is safest to either destroy all copies of your +tickets, or use a screensaver that locks the screen. + + +Kerberos ticket properties +-------------------------- + +There are various properties that Kerberos tickets can have: + +If a ticket is **forwardable**, then the KDC can issue a new ticket +(with a different network address, if necessary) based on the +forwardable ticket. This allows for authentication forwarding without +requiring a password to be typed in again. For example, if a user +with a forwardable TGT logs into a remote system, the KDC could issue +a new TGT for that user with the network address of the remote system, +allowing authentication on that host to work as though the user were +logged in locally. + +When the KDC creates a new ticket based on a forwardable ticket, it +sets the **forwarded** flag on that new ticket. Any tickets that are +created based on a ticket with the forwarded flag set will also have +their forwarded flags set. + +A **proxiable** ticket is similar to a forwardable ticket in that it +allows a service to take on the identity of the client. Unlike a +forwardable ticket, however, a proxiable ticket is only issued for +specific services. In other words, a ticket-granting ticket cannot be +issued based on a ticket that is proxiable but not forwardable. + +A **proxy** ticket is one that was issued based on a proxiable ticket. + +A **postdated** ticket is issued with the invalid flag set. After the +starting time listed on the ticket, it can be presented to the KDC to +obtain valid tickets. + +Ticket-granting tickets with the **postdateable** flag set can be used +to obtain postdated service tickets. + +**Renewable** tickets can be used to obtain new session keys without +the user entering their password again. A renewable ticket has two +expiration times. The first is the time at which this particular +ticket expires. The second is the latest possible expiration time for +any ticket issued based on this renewable ticket. + +A ticket with the **initial flag** set was issued based on the +authentication protocol, and not on a ticket-granting ticket. +Application servers that wish to ensure that the user's key has been +recently presented for verification could specify that this flag must +be set to accept the ticket. + +An **invalid** ticket must be rejected by application servers. +Postdated tickets are usually issued with this flag set, and must be +validated by the KDC before they can be used. + +A **preauthenticated** ticket is one that was only issued after the +client requesting the ticket had authenticated itself to the KDC. + +The **hardware authentication** flag is set on a ticket which required +the use of hardware for authentication. The hardware is expected to +be possessed only by the client which requested the tickets. + +If a ticket has the **transit policy** checked flag set, then the KDC +that issued this ticket implements the transited-realm check policy +and checked the transited-realms list on the ticket. The +transited-realms list contains a list of all intermediate realms +between the realm of the KDC that issued the first ticket and that of +the one that issued the current ticket. If this flag is not set, then +the application server must check the transited realms itself or else +reject the ticket. + +The **okay as delegate** flag indicates that the server specified in +the ticket is suitable as a delegate as determined by the policy of +that realm. Some client applications may use this flag to decide +whether to forward tickets to a remote host, although many +applications do not honor it. + +An **anonymous** ticket is one in which the named principal is a +generic principal for that realm; it does not actually specify the +individual that will be using the ticket. This ticket is meant only +to securely distribute a session key. + + +.. _obtain_tkt: + +Obtaining tickets with kinit +---------------------------- + +If your site has integrated Kerberos V5 with the login system, you +will get Kerberos tickets automatically when you log in. Otherwise, +you may need to explicitly obtain your Kerberos tickets, using the +:ref:`kinit(1)` program. Similarly, if your Kerberos tickets expire, +use the kinit program to obtain new ones. + +To use the kinit program, simply type ``kinit`` and then type your +password at the prompt. For example, Jennifer (whose username is +``jennifer``) works for Bleep, Inc. (a fictitious company with the +domain name mit.edu and the Kerberos realm ATHENA.MIT.EDU). She would +type:: + + shell% kinit + Password for jennifer@ATHENA.MIT.EDU: <-- [Type jennifer's password here.] + shell% + +If you type your password incorrectly, kinit will give you the +following error message:: + + shell% kinit + Password for jennifer@ATHENA.MIT.EDU: <-- [Type the wrong password here.] + kinit: Password incorrect + shell% + +and you won't get Kerberos tickets. + +By default, kinit assumes you want tickets for your own username in +your default realm. Suppose Jennifer's friend David is visiting, and +he wants to borrow a window to check his mail. David needs to get +tickets for himself in his own realm, EXAMPLE.COM. He would type:: + + shell% kinit david@EXAMPLE.COM + Password for david@EXAMPLE.COM: <-- [Type david's password here.] + shell% + +David would then have tickets which he could use to log onto his own +machine. Note that he typed his password locally on Jennifer's +machine, but it never went over the network. Kerberos on the local +host performed the authentication to the KDC in the other realm. + +If you want to be able to forward your tickets to another host, you +need to request forwardable tickets. You do this by specifying the +**-f** option:: + + shell% kinit -f + Password for jennifer@ATHENA.MIT.EDU: <-- [Type your password here.] + shell% + +Note that kinit does not tell you that it obtained forwardable +tickets; you can verify this using the :ref:`klist(1)` command (see +:ref:`view_tkt`). + +Normally, your tickets are good for your system's default ticket +lifetime, which is ten hours on many systems. You can specify a +different ticket lifetime with the **-l** option. Add the letter +**s** to the value for seconds, **m** for minutes, **h** for hours, or +**d** for days. For example, to obtain forwardable tickets for +``david@EXAMPLE.COM`` that would be good for three hours, you would +type:: + + shell% kinit -f -l 3h david@EXAMPLE.COM + Password for david@EXAMPLE.COM: <-- [Type david's password here.] + shell% + +.. note:: + + You cannot mix units; specifying a lifetime of 3h30m would + result in an error. Note also that most systems specify a + maximum ticket lifetime. If you request a longer ticket + lifetime, it will be automatically truncated to the maximum + lifetime. + + +.. _view_tkt: + +Viewing tickets with klist +-------------------------- + +The :ref:`klist(1)` command shows your tickets. When you first obtain +tickets, you will have only the ticket-granting ticket. The listing +would look like this:: + + shell% klist + Ticket cache: /tmp/krb5cc_ttypa + Default principal: jennifer@ATHENA.MIT.EDU + + Valid starting Expires Service principal + 06/07/04 19:49:21 06/08/04 05:49:19 krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU + shell% + +The ticket cache is the location of your ticket file. In the above +example, this file is named ``/tmp/krb5cc_ttypa``. The default +principal is your Kerberos principal. + +The "valid starting" and "expires" fields describe the period of time +during which the ticket is valid. The "service principal" describes +each ticket. The ticket-granting ticket has a first component +``krbtgt``, and a second component which is the realm name. + +Now, if ``jennifer`` connected to the machine ``daffodil.mit.edu``, +and then typed "klist" again, she would have gotten the following +result:: + + shell% klist + Ticket cache: /tmp/krb5cc_ttypa + Default principal: jennifer@ATHENA.MIT.EDU + + Valid starting Expires Service principal + 06/07/04 19:49:21 06/08/04 05:49:19 krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU + 06/07/04 20:22:30 06/08/04 05:49:19 host/daffodil.mit.edu@ATHENA.MIT.EDU + shell% + +Here's what happened: when ``jennifer`` used ssh to connect to the +host ``daffodil.mit.edu``, the ssh program presented her +ticket-granting ticket to the KDC and requested a host ticket for the +host ``daffodil.mit.edu``. The KDC sent the host ticket, which ssh +then presented to the host ``daffodil.mit.edu``, and she was allowed +to log in without typing her password. + +Suppose your Kerberos tickets allow you to log into a host in another +domain, such as ``trillium.example.com``, which is also in another +Kerberos realm, ``EXAMPLE.COM``. If you ssh to this host, you will +receive a ticket-granting ticket for the realm ``EXAMPLE.COM``, plus +the new host ticket for ``trillium.example.com``. klist will now +show:: + + shell% klist + Ticket cache: /tmp/krb5cc_ttypa + Default principal: jennifer@ATHENA.MIT.EDU + + Valid starting Expires Service principal + 06/07/04 19:49:21 06/08/04 05:49:19 krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU + 06/07/04 20:22:30 06/08/04 05:49:19 host/daffodil.mit.edu@ATHENA.MIT.EDU + 06/07/04 20:24:18 06/08/04 05:49:19 krbtgt/EXAMPLE.COM@ATHENA.MIT.EDU + 06/07/04 20:24:18 06/08/04 05:49:19 host/trillium.example.com@EXAMPLE.COM + shell% + +Depending on your host's and realm's configuration, you may also see a +ticket with the service principal ``host/trillium.example.com@``. If +so, this means that your host did not know what realm +trillium.example.com is in, so it asked the ``ATHENA.MIT.EDU`` KDC for +a referral. The next time you connect to ``trillium.example.com``, +the odd-looking entry will be used to avoid needing to ask for a +referral again. + +You can use the **-f** option to view the flags that apply to your +tickets. The flags are: + +===== ========================= + F Forwardable + f forwarded + P Proxiable + p proxy + D postDateable + d postdated + R Renewable + I Initial + i invalid + H Hardware authenticated + A preAuthenticated + T Transit policy checked + O Okay as delegate + a anonymous +===== ========================= + +Here is a sample listing. In this example, the user *jennifer* +obtained her initial tickets (**I**), which are forwardable (**F**) +and postdated (**d**) but not yet validated (**i**):: + + shell% klist -f + Ticket cache: /tmp/krb5cc_320 + Default principal: jennifer@ATHENA.MIT.EDU + + Valid starting Expires Service principal + 31/07/05 19:06:25 31/07/05 19:16:25 krbtgt/ATHENA.MIT.EDU@ATHENA.MIT.EDU + Flags: FdiI + shell% + +In the following example, the user *david*'s tickets were forwarded +(**f**) to this host from another host. The tickets are reforwardable +(**F**):: + + shell% klist -f + Ticket cache: /tmp/krb5cc_p11795 + Default principal: david@EXAMPLE.COM + + Valid starting Expires Service principal + 07/31/05 11:52:29 07/31/05 21:11:23 krbtgt/EXAMPLE.COM@EXAMPLE.COM + Flags: Ff + 07/31/05 12:03:48 07/31/05 21:11:23 host/trillium.example.com@EXAMPLE.COM + Flags: Ff + shell% + + +Destroying tickets with kdestroy +-------------------------------- + +Your Kerberos tickets are proof that you are indeed yourself, and +tickets could be stolen if someone gains access to a computer where +they are stored. If this happens, the person who has them can +masquerade as you until they expire. For this reason, you should +destroy your Kerberos tickets when you are away from your computer. + +Destroying your tickets is easy. Simply type kdestroy:: + + shell% kdestroy + shell% + +If :ref:`kdestroy(1)` fails to destroy your tickets, it will beep and +give an error message. For example, if kdestroy can't find any +tickets to destroy, it will give the following message:: + + shell% kdestroy + kdestroy: No credentials cache file found while destroying cache + shell% diff --git a/krb5-1.21.3/doc/user/user_commands/index.rst b/krb5-1.21.3/doc/user/user_commands/index.rst new file mode 100644 index 00000000..7ce86a14 --- /dev/null +++ b/krb5-1.21.3/doc/user/user_commands/index.rst @@ -0,0 +1,17 @@ +.. _user_commands: + +User commands +============= + +.. toctree:: + :maxdepth: 1 + + kdestroy.rst + kinit.rst + klist.rst + kpasswd.rst + krb5-config.rst + ksu.rst + kswitch.rst + kvno.rst + sclient.rst diff --git a/krb5-1.21.3/doc/user/user_commands/kdestroy.rst b/krb5-1.21.3/doc/user/user_commands/kdestroy.rst new file mode 100644 index 00000000..b15846f9 --- /dev/null +++ b/krb5-1.21.3/doc/user/user_commands/kdestroy.rst @@ -0,0 +1,77 @@ +.. _kdestroy(1): + +kdestroy +======== + +SYNOPSIS +-------- + +**kdestroy** +[**-A**] +[**-q**] +[**-c** *cache_name*] +[**-p** *princ_name*] + + +DESCRIPTION +----------- + +The kdestroy utility destroys the user's active Kerberos authorization +tickets by overwriting and deleting the credentials cache that +contains them. If the credentials cache is not specified, the default +credentials cache is destroyed. + + +OPTIONS +------- + +**-A** + Destroys all caches in the collection, if a cache collection is + available. May be used with the **-c** option to specify the + collection to be destroyed. + +**-q** + Run quietly. Normally kdestroy beeps if it fails to destroy the + user's tickets. The **-q** flag suppresses this behavior. + +**-c** *cache_name* + Use *cache_name* as the credentials (ticket) cache name and + location; if this option is not used, the default cache name and + location are used. + + The default credentials cache may vary between systems. If the + **KRB5CCNAME** environment variable is set, its value is used to + name the default ticket cache. + +**-p** *princ_name* + If a cache collection is available, destroy the cache for + *princ_name* instead of the primary cache. May be used with the + **-c** option to specify the collection to be searched. + + +NOTE +---- + +Most installations recommend that you place the kdestroy command in +your .logout file, so that your tickets are destroyed automatically +when you log out. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +FILES +----- + +|ccache| + Default location of Kerberos 5 credentials cache + + +SEE ALSO +-------- + +:ref:`kinit(1)`, :ref:`klist(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/user/user_commands/kinit.rst b/krb5-1.21.3/doc/user/user_commands/kinit.rst new file mode 100644 index 00000000..5b105e35 --- /dev/null +++ b/krb5-1.21.3/doc/user/user_commands/kinit.rst @@ -0,0 +1,230 @@ +.. _kinit(1): + +kinit +===== + +SYNOPSIS +-------- + +**kinit** +[**-V**] +[**-l** *lifetime*] +[**-s** *start_time*] +[**-r** *renewable_life*] +[**-p** | -**P**] +[**-f** | -**F**] +[**-a**] +[**-A**] +[**-C**] +[**-E**] +[**-v**] +[**-R**] +[**-k** [**-i** | -**t** *keytab_file*]] +[**-c** *cache_name*] +[**-n**] +[**-S** *service_name*] +[**-I** *input_ccache*] +[**-T** *armor_ccache*] +[**-X** *attribute*\ [=\ *value*]] +[**--request-pac** | **--no-request-pac**] +[*principal*] + + +DESCRIPTION +----------- + +kinit obtains and caches an initial ticket-granting ticket for +*principal*. If *principal* is absent, kinit chooses an appropriate +principal name based on existing credential cache contents or the +local username of the user invoking kinit. Some options modify the +choice of principal name. + + +OPTIONS +------- + +**-V** + display verbose output. + +**-l** *lifetime* + (:ref:`duration` string.) Requests a ticket with the lifetime + *lifetime*. + + For example, ``kinit -l 5:30`` or ``kinit -l 5h30m``. + + If the **-l** option is not specified, the default ticket lifetime + (configured by each site) is used. Specifying a ticket lifetime + longer than the maximum ticket lifetime (configured by each site) + will not override the configured maximum ticket lifetime. + +**-s** *start_time* + (:ref:`duration` string.) Requests a postdated ticket. Postdated + tickets are issued with the **invalid** flag set, and need to be + resubmitted to the KDC for validation before use. + + *start_time* specifies the duration of the delay before the ticket + can become valid. + +**-r** *renewable_life* + (:ref:`duration` string.) Requests renewable tickets, with a total + lifetime of *renewable_life*. + +**-f** + requests forwardable tickets. + +**-F** + requests non-forwardable tickets. + +**-p** + requests proxiable tickets. + +**-P** + requests non-proxiable tickets. + +**-a** + requests tickets restricted to the host's local address[es]. + +**-A** + requests tickets not restricted by address. + +**-C** + requests canonicalization of the principal name, and allows the + KDC to reply with a different client principal from the one + requested. + +**-E** + treats the principal name as an enterprise name. + +**-v** + requests that the ticket-granting ticket in the cache (with the + **invalid** flag set) be passed to the KDC for validation. If the + ticket is within its requested time range, the cache is replaced + with the validated ticket. + +**-R** + requests renewal of the ticket-granting ticket. Note that an + expired ticket cannot be renewed, even if the ticket is still + within its renewable life. + + Note that renewable tickets that have expired as reported by + :ref:`klist(1)` may sometimes be renewed using this option, + because the KDC applies a grace period to account for client-KDC + clock skew. See :ref:`krb5.conf(5)` **clockskew** setting. + +**-k** [**-i** | **-t** *keytab_file*] + requests a ticket, obtained from a key in the local host's keytab. + The location of the keytab may be specified with the **-t** + *keytab_file* option, or with the **-i** option to specify the use + of the default client keytab; otherwise the default keytab will be + used. By default, a host ticket for the local host is requested, + but any principal may be specified. On a KDC, the special keytab + location ``KDB:`` can be used to indicate that kinit should open + the KDC database and look up the key directly. This permits an + administrator to obtain tickets as any principal that supports + authentication based on the key. + +**-n** + Requests anonymous processing. Two types of anonymous principals + are supported. + + For fully anonymous Kerberos, configure pkinit on the KDC and + configure **pkinit_anchors** in the client's :ref:`krb5.conf(5)`. + Then use the **-n** option with a principal of the form ``@REALM`` + (an empty principal name followed by the at-sign and a realm + name). If permitted by the KDC, an anonymous ticket will be + returned. + + A second form of anonymous tickets is supported; these + realm-exposed tickets hide the identity of the client but not the + client's realm. For this mode, use ``kinit -n`` with a normal + principal name. If supported by the KDC, the principal (but not + realm) will be replaced by the anonymous principal. + + As of release 1.8, the MIT Kerberos KDC only supports fully + anonymous operation. + +**-I** *input_ccache* + + Specifies the name of a credentials cache that already contains a + ticket. When obtaining that ticket, if information about how that + ticket was obtained was also stored to the cache, that information + will be used to affect how new credentials are obtained, including + preselecting the same methods of authenticating to the KDC. + +**-T** *armor_ccache* + Specifies the name of a credentials cache that already contains a + ticket. If supported by the KDC, this cache will be used to armor + the request, preventing offline dictionary attacks and allowing + the use of additional preauthentication mechanisms. Armoring also + makes sure that the response from the KDC is not modified in + transit. + +**-c** *cache_name* + use *cache_name* as the Kerberos 5 credentials (ticket) cache + location. If this option is not used, the default cache location + is used. + + The default cache location may vary between systems. If the + **KRB5CCNAME** environment variable is set, its value is used to + locate the default cache. If a principal name is specified and + the type of the default cache supports a collection (such as the + DIR type), an existing cache containing credentials for the + principal is selected or a new one is created and becomes the new + primary cache. Otherwise, any existing contents of the default + cache are destroyed by kinit. + +**-S** *service_name* + specify an alternate service name to use when getting initial + tickets. + +**-X** *attribute*\ [=\ *value*] + specify a pre-authentication *attribute* and *value* to be + interpreted by pre-authentication modules. The acceptable + attribute and value values vary from module to module. This + option may be specified multiple times to specify multiple + attributes. If no value is specified, it is assumed to be "yes". + + The following attributes are recognized by the PKINIT + pre-authentication mechanism: + + **X509_user_identity**\ =\ *value* + specify where to find user's X509 identity information + + **X509_anchors**\ =\ *value* + specify where to find trusted X509 anchor information + + **flag_RSA_PROTOCOL**\ [**=yes**] + specify use of RSA, rather than the default Diffie-Hellman + protocol + + **disable_freshness**\ [**=yes**] + disable sending freshness tokens (for testing purposes only) + +**--request-pac** | **--no-request-pac** + mutually exclusive. If **--request-pac** is set, ask the KDC to + include a PAC in authdata; if **--no-request-pac** is set, ask the + KDC not to include a PAC; if neither are set, the KDC will follow + its default, which is typically is to include a PAC if doing so is + supported. + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +FILES +----- + +|ccache| + default location of Kerberos 5 credentials cache + +|keytab| + default location for the local host's keytab. + + +SEE ALSO +-------- + +:ref:`klist(1)`, :ref:`kdestroy(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/user/user_commands/klist.rst b/krb5-1.21.3/doc/user/user_commands/klist.rst new file mode 100644 index 00000000..eb556450 --- /dev/null +++ b/krb5-1.21.3/doc/user/user_commands/klist.rst @@ -0,0 +1,129 @@ +.. _klist(1): + +klist +===== + +SYNOPSIS +-------- + +**klist** +[**-e**] +[[**-c**] [**-l**] [**-A**] [**-f**] [**-s**] [**-a** [**-n**]]] +[**-C**] +[**-k** [**-i**] [**-t**] [**-K**]] +[**-V**] +[**-d**] +[*cache_name*\|\ *keytab_name*] + + +DESCRIPTION +----------- + +klist lists the Kerberos principal and Kerberos tickets held in a +credentials cache, or the keys held in a keytab file. + + +OPTIONS +------- + +**-e** + Displays the encryption types of the session key and the ticket + for each credential in the credential cache, or each key in the + keytab file. + +**-l** + If a cache collection is available, displays a table summarizing + the caches present in the collection. + +**-A** + If a cache collection is available, displays the contents of all + of the caches in the collection. + +**-c** + List tickets held in a credentials cache. This is the default if + neither **-c** nor **-k** is specified. + +**-f** + Shows the flags present in the credentials, using the following + abbreviations:: + + F Forwardable + f forwarded + P Proxiable + p proxy + D postDateable + d postdated + R Renewable + I Initial + i invalid + H Hardware authenticated + A preAuthenticated + T Transit policy checked + O Okay as delegate + a anonymous + +**-s** + Causes klist to run silently (produce no output). klist will exit + with status 1 if the credentials cache cannot be read or is + expired, and with status 0 otherwise. + +**-a** + Display list of addresses in credentials. + +**-n** + Show numeric addresses instead of reverse-resolving addresses. + +**-C** + List configuration data that has been stored in the credentials + cache when klist encounters it. By default, configuration data + is not listed. + +**-k** + List keys held in a keytab file. + +**-i** + In combination with **-k**, defaults to using the default client + keytab instead of the default acceptor keytab, if no name is + given. + +**-t** + Display the time entry timestamps for each keytab entry in the + keytab file. + +**-K** + Display the value of the encryption key in each keytab entry in + the keytab file. + +**-d** + Display the authdata types (if any) for each entry. + +**-V** + Display the Kerberos version number and exit. + +If *cache_name* or *keytab_name* is not specified, klist will display +the credentials in the default credentials cache or keytab file as +appropriate. If the **KRB5CCNAME** environment variable is set, its +value is used to locate the default ticket cache. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +FILES +----- + +|ccache| + Default location of Kerberos 5 credentials cache + +|keytab| + Default location for the local host's keytab file. + + +SEE ALSO +-------- + +:ref:`kinit(1)`, :ref:`kdestroy(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/user/user_commands/kpasswd.rst b/krb5-1.21.3/doc/user/user_commands/kpasswd.rst new file mode 100644 index 00000000..0583bbd0 --- /dev/null +++ b/krb5-1.21.3/doc/user/user_commands/kpasswd.rst @@ -0,0 +1,46 @@ +.. _kpasswd(1): + +kpasswd +======= + +SYNOPSIS +-------- + +**kpasswd** [*principal*] + + +DESCRIPTION +----------- + +The kpasswd command is used to change a Kerberos principal's password. +kpasswd first prompts for the current Kerberos password, then prompts +the user twice for the new password, and the password is changed. + +If the principal is governed by a policy that specifies the length +and/or number of character classes required in the new password, the +new password must conform to the policy. (The five character classes +are lower case, upper case, numbers, punctuation, and all other +characters.) + + +OPTIONS +------- + +*principal* + Change the password for the Kerberos principal principal. + Otherwise, kpasswd uses the principal name from an existing ccache + if there is one; if not, the principal is derived from the + identity of the user invoking the kpasswd command. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kadmin(1)`, :ref:`kadmind(8)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/user/user_commands/krb5-config.rst b/krb5-1.21.3/doc/user/user_commands/krb5-config.rst new file mode 100644 index 00000000..2c09141a --- /dev/null +++ b/krb5-1.21.3/doc/user/user_commands/krb5-config.rst @@ -0,0 +1,83 @@ +.. _krb5-config(1): + +krb5-config +=========== + +SYNOPSIS +-------- + +**krb5-config** +[**-**\ **-help** | **-**\ **-all** | **-**\ **-version** | **-**\ **-vendor** | **-**\ **-prefix** | **-**\ **-exec-prefix** | **-**\ **-defccname** | **-**\ **-defktname** | **-**\ **-defcktname** | **-**\ **-cflags** | **-**\ **-libs** [*libraries*]] + + +DESCRIPTION +----------- + +krb5-config tells the application programmer what flags to use to compile +and link programs against the installed Kerberos libraries. + + +OPTIONS +------- + +**-**\ **-help** + prints a usage message. This is the default behavior when no options + are specified. + +**-**\ **-all** + prints the version, vendor, prefix, and exec-prefix. + +**-**\ **-version** + prints the version number of the Kerberos installation. + +**-**\ **-vendor** + prints the name of the vendor of the Kerberos installation. + +**-**\ **-prefix** + prints the prefix for which the Kerberos installation was built. + +**-**\ **-exec-prefix** + prints the prefix for executables for which the Kerberos installation + was built. + +**-**\ **-defccname** + prints the built-in default credentials cache location. + +**-**\ **-defktname** + prints the built-in default keytab location. + +**-**\ **-defcktname** + prints the built-in default client (initiator) keytab location. + +**-**\ **-cflags** + prints the compilation flags used to build the Kerberos installation. + +**-**\ **-libs** [*library*] + prints the compiler options needed to link against *library*. + Allowed values for *library* are: + + ============ =============================================== + krb5 Kerberos 5 applications (default) + gssapi GSSAPI applications with Kerberos 5 bindings + kadm-client Kadmin client + kadm-server Kadmin server + kdb Applications that access the Kerberos database + ============ =============================================== + +EXAMPLES +-------- + +krb5-config is particularly useful for compiling against a Kerberos +installation that was installed in a non-standard location. For example, +a Kerberos installation that is installed in ``/opt/krb5/`` but uses +libraries in ``/usr/local/lib/`` for text localization would produce +the following output:: + + shell% krb5-config --libs krb5 + -L/opt/krb5/lib -Wl,-rpath -Wl,/opt/krb5/lib -L/usr/local/lib -lkrb5 -lk5crypto -lcom_err + + +SEE ALSO +-------- + +:ref:`kerberos(7)`, cc(1) diff --git a/krb5-1.21.3/doc/user/user_commands/ksu.rst b/krb5-1.21.3/doc/user/user_commands/ksu.rst new file mode 100644 index 00000000..93373822 --- /dev/null +++ b/krb5-1.21.3/doc/user/user_commands/ksu.rst @@ -0,0 +1,411 @@ +.. _ksu(1): + +ksu +=== + +SYNOPSIS +-------- + +**ksu** +[ *target_user* ] +[ **-n** *target_principal_name* ] +[ **-c** *source_cache_name* ] +[ **-k** ] +[ **-r** time ] +[ **-p** | **-P**] +[ **-f** | **-F**] +[ **-l** *lifetime* ] +[ **-z | Z** ] +[ **-q** ] +[ **-e** *command* [ args ... ] ] [ **-a** [ args ... ] ] + + +REQUIREMENTS +------------ + +Must have Kerberos version 5 installed to compile ksu. Must have a +Kerberos version 5 server running to use ksu. + + +DESCRIPTION +----------- + +ksu is a Kerberized version of the su program that has two missions: +one is to securely change the real and effective user ID to that of +the target user, and the other is to create a new security context. + +.. note:: + + For the sake of clarity, all references to and attributes of + the user invoking the program will start with "source" + (e.g., "source user", "source cache", etc.). + + Likewise, all references to and attributes of the target + account will start with "target". + +AUTHENTICATION +-------------- + +To fulfill the first mission, ksu operates in two phases: +authentication and authorization. Resolving the target principal name +is the first step in authentication. The user can either specify his +principal name with the **-n** option (e.g., ``-n jqpublic@USC.EDU``) +or a default principal name will be assigned using a heuristic +described in the OPTIONS section (see **-n** option). The target user +name must be the first argument to ksu; if not specified root is the +default. If ``.`` is specified then the target user will be the +source user (e.g., ``ksu .``). If the source user is root or the +target user is the source user, no authentication or authorization +takes place. Otherwise, ksu looks for an appropriate Kerberos ticket +in the source cache. + +The ticket can either be for the end-server or a ticket granting +ticket (TGT) for the target principal's realm. If the ticket for the +end-server is already in the cache, it's decrypted and verified. If +it's not in the cache but the TGT is, the TGT is used to obtain the +ticket for the end-server. The end-server ticket is then verified. +If neither ticket is in the cache, but ksu is compiled with the +**GET_TGT_VIA_PASSWD** define, the user will be prompted for a +Kerberos password which will then be used to get a TGT. If the user +is logged in remotely and does not have a secure channel, the password +may be exposed. If neither ticket is in the cache and +**GET_TGT_VIA_PASSWD** is not defined, authentication fails. + + +AUTHORIZATION +------------- + +This section describes authorization of the source user when ksu is +invoked without the **-e** option. For a description of the **-e** +option, see the OPTIONS section. + +Upon successful authentication, ksu checks whether the target +principal is authorized to access the target account. In the target +user's home directory, ksu attempts to access two authorization files: +:ref:`.k5login(5)` and .k5users. In the .k5login file each line +contains the name of a principal that is authorized to access the +account. + +For example:: + + jqpublic@USC.EDU + jqpublic/secure@USC.EDU + jqpublic/admin@USC.EDU + +The format of .k5users is the same, except the principal name may be +followed by a list of commands that the principal is authorized to +execute (see the **-e** option in the OPTIONS section for details). + +Thus if the target principal name is found in the .k5login file the +source user is authorized to access the target account. Otherwise ksu +looks in the .k5users file. If the target principal name is found +without any trailing commands or followed only by ``*`` then the +source user is authorized. If either .k5login or .k5users exist but +an appropriate entry for the target principal does not exist then +access is denied. If neither file exists then the principal will be +granted access to the account according to the aname->lname mapping +rules. Otherwise, authorization fails. + + +EXECUTION OF THE TARGET SHELL +----------------------------- + +Upon successful authentication and authorization, ksu proceeds in a +similar fashion to su. The environment is unmodified with the +exception of USER, HOME and SHELL variables. If the target user is +not root, USER gets set to the target user name. Otherwise USER +remains unchanged. Both HOME and SHELL are set to the target login's +default values. In addition, the environment variable **KRB5CCNAME** +gets set to the name of the target cache. The real and effective user +ID are changed to that of the target user. The target user's shell is +then invoked (the shell name is specified in the password file). Upon +termination of the shell, ksu deletes the target cache (unless ksu is +invoked with the **-k** option). This is implemented by first doing a +fork and then an exec, instead of just exec, as done by su. + + +CREATING A NEW SECURITY CONTEXT +------------------------------- + +ksu can be used to create a new security context for the target +program (either the target shell, or command specified via the **-e** +option). The target program inherits a set of credentials from the +source user. By default, this set includes all of the credentials in +the source cache plus any additional credentials obtained during +authentication. The source user is able to limit the credentials in +this set by using **-z** or **-Z** option. **-z** restricts the copy +of tickets from the source cache to the target cache to only the +tickets where client == the target principal name. The **-Z** option +provides the target user with a fresh target cache (no creds in the +cache). Note that for security reasons, when the source user is root +and target user is non-root, **-z** option is the default mode of +operation. + +While no authentication takes place if the source user is root or is +the same as the target user, additional tickets can still be obtained +for the target cache. If **-n** is specified and no credentials can +be copied to the target cache, the source user is prompted for a +Kerberos password (unless **-Z** specified or **GET_TGT_VIA_PASSWD** +is undefined). If successful, a TGT is obtained from the Kerberos +server and stored in the target cache. Otherwise, if a password is +not provided (user hit return) ksu continues in a normal mode of +operation (the target cache will not contain the desired TGT). If the +wrong password is typed in, ksu fails. + +.. note:: + + During authentication, only the tickets that could be + obtained without providing a password are cached in the + source cache. + + +OPTIONS +------- + +**-n** *target_principal_name* + Specify a Kerberos target principal name. Used in authentication + and authorization phases of ksu. + + If ksu is invoked without **-n**, a default principal name is + assigned via the following heuristic: + + * Case 1: source user is non-root. + + If the target user is the source user the default principal name + is set to the default principal of the source cache. If the + cache does not exist then the default principal name is set to + ``target_user@local_realm``. If the source and target users are + different and neither ``~target_user/.k5users`` nor + ``~target_user/.k5login`` exist then the default principal name + is ``target_user_login_name@local_realm``. Otherwise, starting + with the first principal listed below, ksu checks if the + principal is authorized to access the target account and whether + there is a legitimate ticket for that principal in the source + cache. If both conditions are met that principal becomes the + default target principal, otherwise go to the next principal. + + a) default principal of the source cache + b) target_user\@local_realm + c) source_user\@local_realm + + If a-c fails try any principal for which there is a ticket in + the source cache and that is authorized to access the target + account. If that fails select the first principal that is + authorized to access the target account from the above list. If + none are authorized and ksu is configured with + **PRINC_LOOK_AHEAD** turned on, select the default principal as + follows: + + For each candidate in the above list, select an authorized + principal that has the same realm name and first part of the + principal name equal to the prefix of the candidate. For + example if candidate a) is ``jqpublic@ISI.EDU`` and + ``jqpublic/secure@ISI.EDU`` is authorized to access the target + account then the default principal is set to + ``jqpublic/secure@ISI.EDU``. + + * Case 2: source user is root. + + If the target user is non-root then the default principal name + is ``target_user@local_realm``. Else, if the source cache + exists the default principal name is set to the default + principal of the source cache. If the source cache does not + exist, default principal name is set to ``root\@local_realm``. + +**-c** *source_cache_name* + + Specify source cache name (e.g., ``-c FILE:/tmp/my_cache``). If + **-c** option is not used then the name is obtained from + **KRB5CCNAME** environment variable. If **KRB5CCNAME** is not + defined the source cache name is set to ``krb5cc_``. + The target cache name is automatically set to ``krb5cc_.(gen_sym())``, where gen_sym generates a new number such that + the resulting cache does not already exist. For example:: + + krb5cc_1984.2 + +**-k** + Do not delete the target cache upon termination of the target + shell or a command (**-e** command). Without **-k**, ksu deletes + the target cache. + +**-z** + Restrict the copy of tickets from the source cache to the target + cache to only the tickets where client == the target principal + name. Use the **-n** option if you want the tickets for other then + the default principal. Note that the **-z** option is mutually + exclusive with the **-Z** option. + +**-Z** + Don't copy any tickets from the source cache to the target cache. + Just create a fresh target cache, where the default principal name + of the cache is initialized to the target principal name. Note + that the **-Z** option is mutually exclusive with the **-z** + option. + +**-q** + Suppress the printing of status messages. + +Ticket granting ticket options: + +**-l** *lifetime* **-r** *time* **-p** **-P** **-f** **-F** + The ticket granting ticket options only apply to the case where + there are no appropriate tickets in the cache to authenticate the + source user. In this case if ksu is configured to prompt users + for a Kerberos password (**GET_TGT_VIA_PASSWD** is defined), the + ticket granting ticket options that are specified will be used + when getting a ticket granting ticket from the Kerberos server. + +**-l** *lifetime* + (:ref:`duration` string.) Specifies the lifetime to be requested + for the ticket; if this option is not specified, the default ticket + lifetime (12 hours) is used instead. + +**-r** *time* + (:ref:`duration` string.) Specifies that the **renewable** option + should be requested for the ticket, and specifies the desired + total lifetime of the ticket. + +**-p** + specifies that the **proxiable** option should be requested for + the ticket. + +**-P** + specifies that the **proxiable** option should not be requested + for the ticket, even if the default configuration is to ask for + proxiable tickets. + +**-f** + option specifies that the **forwardable** option should be + requested for the ticket. + +**-F** + option specifies that the **forwardable** option should not be + requested for the ticket, even if the default configuration is to + ask for forwardable tickets. + +**-e** *command* [*args* ...] + ksu proceeds exactly the same as if it was invoked without the + **-e** option, except instead of executing the target shell, ksu + executes the specified command. Example of usage:: + + ksu bob -e ls -lag + + The authorization algorithm for **-e** is as follows: + + If the source user is root or source user == target user, no + authorization takes place and the command is executed. If source + user id != 0, and ``~target_user/.k5users`` file does not exist, + authorization fails. Otherwise, ``~target_user/.k5users`` file + must have an appropriate entry for target principal to get + authorized. + + The .k5users file format: + + A single principal entry on each line that may be followed by a + list of commands that the principal is authorized to execute. A + principal name followed by a ``*`` means that the user is + authorized to execute any command. Thus, in the following + example:: + + jqpublic@USC.EDU ls mail /local/kerberos/klist + jqpublic/secure@USC.EDU * + jqpublic/admin@USC.EDU + + ``jqpublic@USC.EDU`` is only authorized to execute ``ls``, + ``mail`` and ``klist`` commands. ``jqpublic/secure@USC.EDU`` is + authorized to execute any command. ``jqpublic/admin@USC.EDU`` is + not authorized to execute any command. Note, that + ``jqpublic/admin@USC.EDU`` is authorized to execute the target + shell (regular ksu, without the **-e** option) but + ``jqpublic@USC.EDU`` is not. + + The commands listed after the principal name must be either a full + path names or just the program name. In the second case, + **CMD_PATH** specifying the location of authorized programs must + be defined at the compilation time of ksu. Which command gets + executed? + + If the source user is root or the target user is the source user + or the user is authorized to execute any command (``*`` entry) + then command can be either a full or a relative path leading to + the target program. Otherwise, the user must specify either a + full path or just the program name. + +**-a** *args* + Specify arguments to be passed to the target shell. Note that all + flags and parameters following -a will be passed to the shell, + thus all options intended for ksu must precede **-a**. + + The **-a** option can be used to simulate the **-e** option if + used as follows:: + + -a -c [command [arguments]]. + + **-c** is interpreted by the c-shell to execute the command. + + +INSTALLATION INSTRUCTIONS +------------------------- + +ksu can be compiled with the following four flags: + +**GET_TGT_VIA_PASSWD** + In case no appropriate tickets are found in the source cache, the + user will be prompted for a Kerberos password. The password is + then used to get a ticket granting ticket from the Kerberos + server. The danger of configuring ksu with this macro is if the + source user is logged in remotely and does not have a secure + channel, the password may get exposed. + +**PRINC_LOOK_AHEAD** + During the resolution of the default principal name, + **PRINC_LOOK_AHEAD** enables ksu to find principal names in + the .k5users file as described in the OPTIONS section + (see **-n** option). + +**CMD_PATH** + Specifies a list of directories containing programs that users are + authorized to execute (via .k5users file). + +**HAVE_GETUSERSHELL** + If the source user is non-root, ksu insists that the target user's + shell to be invoked is a "legal shell". *getusershell(3)* is + called to obtain the names of "legal shells". Note that the + target user's shell is obtained from the passwd file. + +Sample configuration:: + + KSU_OPTS = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/bin /usr/ucb /local/bin" + +ksu should be owned by root and have the set user id bit turned on. + +ksu attempts to get a ticket for the end server just as Kerberized +telnet and rlogin. Thus, there must be an entry for the server in the +Kerberos database (e.g., ``host/nii.isi.edu@ISI.EDU``). The keytab +file must be in an appropriate location. + + +SIDE EFFECTS +------------ + +ksu deletes all expired tickets from the source cache. + + +AUTHOR OF KSU +------------- + +GENNADY (ARI) MEDVINSKY + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kerberos(7)`, :ref:`kinit(1)` diff --git a/krb5-1.21.3/doc/user/user_commands/kswitch.rst b/krb5-1.21.3/doc/user/user_commands/kswitch.rst new file mode 100644 index 00000000..010332e6 --- /dev/null +++ b/krb5-1.21.3/doc/user/user_commands/kswitch.rst @@ -0,0 +1,50 @@ +.. _kswitch(1): + +kswitch +======= + +SYNOPSIS +-------- + +**kswitch** +{**-c** *cachename*\|\ **-p** *principal*} + + +DESCRIPTION +----------- + +kswitch makes the specified credential cache the primary cache for the +collection, if a cache collection is available. + + +OPTIONS +------- + +**-c** *cachename* + Directly specifies the credential cache to be made primary. + +**-p** *principal* + Causes the cache collection to be searched for a cache containing + credentials for *principal*. If one is found, that collection is + made primary. + + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +FILES +----- + +|ccache| + Default location of Kerberos 5 credentials cache + + +SEE ALSO +-------- + +:ref:`kinit(1)`, :ref:`kdestroy(1)`, :ref:`klist(1)`, +:ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/user/user_commands/kvno.rst b/krb5-1.21.3/doc/user/user_commands/kvno.rst new file mode 100644 index 00000000..970fbb47 --- /dev/null +++ b/krb5-1.21.3/doc/user/user_commands/kvno.rst @@ -0,0 +1,119 @@ +.. _kvno(1): + +kvno +==== + +SYNOPSIS +-------- + +**kvno** +[**-c** *ccache*] +[**-e** *etype*] +[**-k** *keytab*] +[**-q**] +[**-u** | **-S** *sname*] +[**-P**] +[**--cached-only**] +[**--no-store**] +[**--out-cache** *cache*] +[[{**-F** *cert_file* | {**-I** | **-U**} *for_user*} [**-P**]] | **--u2u** *ccache*] +*service1 service2* ... + + +DESCRIPTION +----------- + +kvno acquires a service ticket for the specified Kerberos principals +and prints out the key version numbers of each. + + +OPTIONS +------- + +**-c** *ccache* + Specifies the name of a credentials cache to use (if not the + default) + +**-e** *etype* + Specifies the enctype which will be requested for the session key + of all the services named on the command line. This is useful in + certain backward compatibility situations. + +**-k** *keytab* + Decrypt the acquired tickets using *keytab* to confirm their + validity. + +**-q** + Suppress printing output when successful. If a service ticket + cannot be obtained, an error message will still be printed and + kvno will exit with nonzero status. + +**-u** + Use the unknown name type in requested service principal names. + This option Cannot be used with *-S*. + +**-P** + Specifies that the *service1 service2* ... arguments are to be + treated as services for which credentials should be acquired using + constrained delegation. This option is only valid when used in + conjunction with protocol transition. + +**-S** *sname* + Specifies that the *service1 service2* ... arguments are + interpreted as hostnames, and the service principals are to be + constructed from those hostnames and the service name *sname*. + The service hostnames will be canonicalized according to the usual + rules for constructing service principals. + +**-I** *for_user* + Specifies that protocol transition (S4U2Self) is to be used to + acquire a ticket on behalf of *for_user*. If constrained + delegation is not requested, the service name must match the + credentials cache client principal. + +**-U** *for_user* + Same as -I, but treats *for_user* as an enterprise name. + +**-F** *cert_file* + Specifies that protocol transition is to be used, identifying the + client principal with the X.509 certificate in *cert_file*. The + certificate file must be in PEM format. + +**--cached-only** + Only retrieve credentials already present in the cache, not from + the KDC. (Added in release 1.19.) + +**--no-store** + Do not store retrieved credentials in the cache. If + **--out-cache** is also specified, credentials will still be + stored into the output credential cache. (Added in release 1.19.) + +**--out-cache** *ccache* + Initialize *ccache* and store all retrieved credentials into it. + Do not store acquired credentials in the input cache. (Added in + release 1.19.) + +**--u2u** *ccache* + Requests a user-to-user ticket. *ccache* must contain a local + krbtgt ticket for the server principal. The reported version + number will typically be 0, as the resulting ticket is not + encrypted in the server's long-term key. + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +FILES +----- + +|ccache| + Default location of the credentials cache + + +SEE ALSO +-------- + +:ref:`kinit(1)`, :ref:`kdestroy(1)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/user/user_commands/sclient.rst b/krb5-1.21.3/doc/user/user_commands/sclient.rst new file mode 100644 index 00000000..1e3d38f8 --- /dev/null +++ b/krb5-1.21.3/doc/user/user_commands/sclient.rst @@ -0,0 +1,30 @@ +.. _sclient(1): + +sclient +======= + +SYNOPSIS +-------- + +**sclient** *remotehost* + + +DESCRIPTION +----------- + +sclient is a sample application, primarily useful for testing +purposes. It contacts a sample server :ref:`sserver(8)` and +authenticates to it using Kerberos version 5 tickets, then displays +the server's response. + +ENVIRONMENT +----------- + +See :ref:`kerberos(7)` for a description of Kerberos environment +variables. + + +SEE ALSO +-------- + +:ref:`kinit(1)`, :ref:`sserver(8)`, :ref:`kerberos(7)` diff --git a/krb5-1.21.3/doc/user/user_config/index.rst b/krb5-1.21.3/doc/user/user_config/index.rst new file mode 100644 index 00000000..ad0dc1a7 --- /dev/null +++ b/krb5-1.21.3/doc/user/user_config/index.rst @@ -0,0 +1,13 @@ +User config files +================= + +The following files in your home directory can be used to control the +behavior of Kerberos as it applies to your account (unless they have +been disabled by your host's configuration): + +.. toctree:: + :maxdepth: 1 + + kerberos.rst + k5login.rst + k5identity.rst diff --git a/krb5-1.21.3/doc/user/user_config/k5identity.rst b/krb5-1.21.3/doc/user/user_config/k5identity.rst new file mode 100644 index 00000000..cf5d95e5 --- /dev/null +++ b/krb5-1.21.3/doc/user/user_config/k5identity.rst @@ -0,0 +1,64 @@ +.. _.k5identity(5): + +.k5identity +=========== + +DESCRIPTION +----------- + +The .k5identity file, which resides in a user's home directory, +contains a list of rules for selecting a client principals based on +the server being accessed. These rules are used to choose a +credential cache within the cache collection when possible. + +Blank lines and lines beginning with ``#`` are ignored. Each line has +the form: + + *principal* *field*\=\ *value* ... + +If the server principal meets all of the field constraints, then +principal is chosen as the client principal. The following fields are +recognized: + +**realm** + If the realm of the server principal is known, it is matched + against *value*, which may be a pattern using shell wildcards. + For host-based server principals, the realm will generally only be + known if there is a :ref:`domain_realm` section in + :ref:`krb5.conf(5)` with a mapping for the hostname. + +**service** + If the server principal is a host-based principal, its service + component is matched against *value*, which may be a pattern using + shell wildcards. + +**host** + If the server principal is a host-based principal, its hostname + component is converted to lower case and matched against *value*, + which may be a pattern using shell wildcards. + + If the server principal matches the constraints of multiple lines + in the .k5identity file, the principal from the first matching + line is used. If no line matches, credentials will be selected + some other way, such as the realm heuristic or the current primary + cache. + + +EXAMPLE +------- + +The following example .k5identity file selects the client principal +``alice@KRBTEST.COM`` if the server principal is within that realm, +the principal ``alice/root@EXAMPLE.COM`` if the server host is within +a servers subdomain, and the principal ``alice/mail@EXAMPLE.COM`` when +accessing the IMAP service on ``mail.example.com``:: + + alice@KRBTEST.COM realm=KRBTEST.COM + alice/root@EXAMPLE.COM host=*.servers.example.com + alice/mail@EXAMPLE.COM host=mail.example.com service=imap + + +SEE ALSO +-------- + +kerberos(1), :ref:`krb5.conf(5)` diff --git a/krb5-1.21.3/doc/user/user_config/k5login.rst b/krb5-1.21.3/doc/user/user_config/k5login.rst new file mode 100644 index 00000000..8a9753da --- /dev/null +++ b/krb5-1.21.3/doc/user/user_config/k5login.rst @@ -0,0 +1,54 @@ +.. _.k5login(5): + +.k5login +======== + +DESCRIPTION +----------- + +The .k5login file, which resides in a user's home directory, contains +a list of the Kerberos principals. Anyone with valid tickets for a +principal in the file is allowed host access with the UID of the user +in whose home directory the file resides. One common use is to place +a .k5login file in root's home directory, thereby granting system +administrators remote root access to the host via Kerberos. + + +EXAMPLES +-------- + +Suppose the user ``alice`` had a .k5login file in her home directory +containing just the following line:: + + bob@FOOBAR.ORG + +This would allow ``bob`` to use Kerberos network applications, such as +ssh(1), to access ``alice``'s account, using ``bob``'s Kerberos +tickets. In a default configuration (with **k5login_authoritative** set +to true in :ref:`krb5.conf(5)`), this .k5login file would not let +``alice`` use those network applications to access her account, since +she is not listed! With no .k5login file, or with **k5login_authoritative** +set to false, a default rule would permit the principal ``alice`` in the +machine's default realm to access the ``alice`` account. + +Let us further suppose that ``alice`` is a system administrator. +Alice and the other system administrators would have their principals +in root's .k5login file on each host:: + + alice@BLEEP.COM + + joeadmin/root@BLEEP.COM + +This would allow either system administrator to log in to these hosts +using their Kerberos tickets instead of having to type the root +password. Note that because ``bob`` retains the Kerberos tickets for +his own principal, ``bob@FOOBAR.ORG``, he would not have any of the +privileges that require ``alice``'s tickets, such as root access to +any of the site's hosts, or the ability to change ``alice``'s +password. + + +SEE ALSO +-------- + +kerberos(1) diff --git a/krb5-1.21.3/doc/user/user_config/kerberos.rst b/krb5-1.21.3/doc/user/user_config/kerberos.rst new file mode 100644 index 00000000..1830447a --- /dev/null +++ b/krb5-1.21.3/doc/user/user_config/kerberos.rst @@ -0,0 +1,185 @@ +.. _kerberos(7): + +kerberos +======== + +DESCRIPTION +----------- + +The Kerberos system authenticates individual users in a network +environment. After authenticating yourself to Kerberos, you can use +Kerberos-enabled programs without having to present passwords or +certificates to those programs. + +If you receive the following response from :ref:`kinit(1)`: + +kinit: Client not found in Kerberos database while getting initial +credentials + +you haven't been registered as a Kerberos user. See your system +administrator. + +A Kerberos name usually contains three parts. The first is the +**primary**, which is usually a user's or service's name. The second +is the **instance**, which in the case of a user is usually null. +Some users may have privileged instances, however, such as ``root`` or +``admin``. In the case of a service, the instance is the fully +qualified name of the machine on which it runs; i.e. there can be an +ssh service running on the machine ABC (ssh/ABC@REALM), which is +different from the ssh service running on the machine XYZ +(ssh/XYZ@REALM). The third part of a Kerberos name is the **realm**. +The realm corresponds to the Kerberos service providing authentication +for the principal. Realms are conventionally all-uppercase, and often +match the end of hostnames in the realm (for instance, host01.example.com +might be in realm EXAMPLE.COM). + +When writing a Kerberos name, the principal name is separated from the +instance (if not null) by a slash, and the realm (if not the local +realm) follows, preceded by an "@" sign. The following are examples +of valid Kerberos names:: + + david + jennifer/admin + joeuser@BLEEP.COM + cbrown/root@FUBAR.ORG + +When you authenticate yourself with Kerberos you get an initial +Kerberos **ticket**. (A Kerberos ticket is an encrypted protocol +message that provides authentication.) Kerberos uses this ticket for +network utilities such as ssh. The ticket transactions are done +transparently, so you don't have to worry about their management. + +Note, however, that tickets expire. Administrators may configure more +privileged tickets, such as those with service or instance of ``root`` +or ``admin``, to expire in a few minutes, while tickets that carry +more ordinary privileges may be good for several hours or a day. If +your login session extends beyond the time limit, you will have to +re-authenticate yourself to Kerberos to get new tickets using the +:ref:`kinit(1)` command. + +Some tickets are **renewable** beyond their initial lifetime. This +means that ``kinit -R`` can extend their lifetime without requiring +you to re-authenticate. + +If you wish to delete your local tickets, use the :ref:`kdestroy(1)` +command. + +Kerberos tickets can be forwarded. In order to forward tickets, you +must request **forwardable** tickets when you kinit. Once you have +forwardable tickets, most Kerberos programs have a command line option +to forward them to the remote host. This can be useful for, e.g., +running kinit on your local machine and then sshing into another to do +work. Note that this should not be done on untrusted machines since +they will then have your tickets. + +ENVIRONMENT VARIABLES +--------------------- + +Several environment variables affect the operation of Kerberos-enabled +programs. These include: + +**KRB5CCNAME** + Default name for the credentials cache file, in the form + *TYPE*:*residual*. The type of the default cache may determine + the availability of a cache collection. ``FILE`` is not a + collection type; ``KEYRING``, ``DIR``, and ``KCM`` are. + + If not set, the value of **default_ccache_name** from + configuration files (see **KRB5_CONFIG**) will be used. If that + is also not set, the default *type* is ``FILE``, and the + *residual* is the path /tmp/krb5cc_*uid*, where *uid* is the + decimal user ID of the user. + +**KRB5_KTNAME** + Specifies the location of the default keytab file, in the form + *TYPE*:*residual*. If no *type* is present, the **FILE** type is + assumed and *residual* is the pathname of the keytab file. If + unset, |keytab| will be used. + +**KRB5_CONFIG** + Specifies the location of the Kerberos configuration file. The + default is |sysconfdir|\ ``/krb5.conf``. Multiple filenames can + be specified, separated by a colon; all files which are present + will be read. + +**KRB5_KDC_PROFILE** + Specifies the location of the KDC configuration file, which + contains additional configuration directives for the Key + Distribution Center daemon and associated programs. The default + is |kdcdir|\ ``/kdc.conf``. + +**KRB5RCACHENAME** + (New in release 1.18) Specifies the location of the default replay + cache, in the form *type*:*residual*. The ``file2`` type with a + pathname residual specifies a replay cache file in the version-2 + format in the specified location. The ``none`` type (residual is + ignored) disables the replay cache. The ``dfl`` type (residual is + ignored) indicates the default, which uses a file2 replay cache in + a temporary directory. The default is ``dfl:``. + +**KRB5RCACHETYPE** + Specifies the type of the default replay cache, if + **KRB5RCACHENAME** is unspecified. No residual can be specified, + so ``none`` and ``dfl`` are the only useful types. + +**KRB5RCACHEDIR** + Specifies the directory used by the ``dfl`` replay cache type. + The default is the value of the **TMPDIR** environment variable, + or ``/var/tmp`` if **TMPDIR** is not set. + +**KRB5_TRACE** + Specifies a filename to write trace log output to. Trace logs can + help illuminate decisions made internally by the Kerberos + libraries. For example, ``env KRB5_TRACE=/dev/stderr kinit`` + would send tracing information for :ref:`kinit(1)` to + ``/dev/stderr``. The default is not to write trace log output + anywhere. + +**KRB5_CLIENT_KTNAME** + Default client keytab file name. If unset, |ckeytab| will be + used). + +**KPROP_PORT** + :ref:`kprop(8)` port to use. Defaults to 754. + +**GSS_MECH_CONFIG** + Specifies a filename containing GSSAPI mechanism module + configuration. The default is to read |sysconfdir|\ ``/gss/mech`` + and files with a ``.conf`` suffix within the directory + |sysconfdir|\ ``/gss/mech.d``. + +Most environment variables are disabled for certain programs, such as +login system programs and setuid programs, which are designed to be +secure when run within an untrusted process environment. + +SEE ALSO +-------- + +:ref:`kdestroy(1)`, :ref:`kinit(1)`, :ref:`klist(1)`, +:ref:`kswitch(1)`, :ref:`kpasswd(1)`, :ref:`ksu(1)`, +:ref:`krb5.conf(5)`, :ref:`kdc.conf(5)`, :ref:`kadmin(1)`, +:ref:`kadmind(8)`, :ref:`kdb5_util(8)`, :ref:`krb5kdc(8)` + +BUGS +---- + +AUTHORS +------- + +| Steve Miller, MIT Project Athena/Digital Equipment Corporation +| Clifford Neuman, MIT Project Athena +| Greg Hudson, MIT Kerberos Consortium +| Robbie Harwood, Red Hat, Inc. + +HISTORY +------- + +The MIT Kerberos 5 implementation was developed at MIT, with +contributions from many outside parties. It is currently maintained +by the MIT Kerberos Consortium. + +RESTRICTIONS +------------ + +Copyright 1985, 1986, 1989-1996, 2002, 2011, 2018 Masachusetts +Institute of Technology diff --git a/krb5-1.21.3/src/Makefile.in b/krb5-1.21.3/src/Makefile.in new file mode 100644 index 00000000..8f14e9bf --- /dev/null +++ b/krb5-1.21.3/src/Makefile.in @@ -0,0 +1,693 @@ +datadir=@datadir@ + +mydir=. +# Don't build sample by default, and definitely don't install them +# for production use: +# plugins/locate/python +# plugins/preauth/wpse +# plugins/preauth/cksum_body +SUBDIRS=util include lib \ + @sam2_plugin@ \ + plugins/audit \ + plugins/audit/test \ + @audit_plugin@ \ + plugins/kadm5_hook/test \ + plugins/kadm5_auth/test \ + plugins/gssapi/negoextest \ + plugins/hostrealm/test \ + plugins/localauth/test \ + plugins/pwqual/test \ + plugins/authdata/greet_server \ + plugins/authdata/greet_client \ + plugins/certauth/test \ + plugins/kdb/db2 \ + @ldap_plugin_dir@ \ + @lmdb_plugin_dir@ \ + plugins/kdb/test \ + plugins/kdcpolicy/test \ + plugins/preauth/otp \ + plugins/preauth/pkinit \ + plugins/preauth/spake \ + plugins/preauth/test \ + plugins/tls/k5tls \ + kdc kadmin kprop clients appl tests \ + config-files build-tools man doc @po@ +WINSUBDIRS=include util lib ccapi windows clients appl plugins\preauth\spake +BUILDTOP=$(REL). + +SRCS = +HDRS = + +# Why aren't these flags showing up in Windows builds? +##DOS##CPPFLAGS=$(CPPFLAGS) -D_X86_=1 -DWIN32 -D_WIN32 -W3 -D_WINNT + +# Lots of things will start to depend on the thread support, which +# needs autoconf.h, but building "all" in include requires that util/et +# have been built first. Until we can untangle this, let's just check +# that autoconf.h is up to date before going into any of the subdirectories. +all-prerecurse generate-files-mac-prerecurse: update-autoconf-h +update-autoconf-h: + (cd include && $(MAKE) autoconf.h osconf.h) + +##DOS##!if 0 +# This makefile doesn't use lib.in, but we still need shlib.conf here. +config.status: $(top_srcdir)/config/shlib.conf +##DOS##!endif + +all-windows: maybe-awk Makefile-windows + +world: + date + make $(MFLAGS) all + date + +INSTALLMKDIRS = $(KRB5ROOT) $(KRB5MANROOT) $(KRB5OTHERMKDIRS) \ + $(ADMIN_BINDIR) $(SERVER_BINDIR) $(CLIENT_BINDIR) \ + $(ADMIN_MANDIR) $(SERVER_MANDIR) $(CLIENT_MANDIR) \ + $(FILE_MANDIR) $(OVERVIEW_MANDIR) \ + $(ADMIN_CATDIR) $(SERVER_CATDIR) $(CLIENT_CATDIR) \ + $(FILE_CATDIR) $(OVERVIEW_CATDIR) \ + $(KRB5_LIBDIR) $(KRB5_INCDIR) \ + $(KRB5_DB_MODULE_DIR) $(KRB5_PA_MODULE_DIR) \ + $(KRB5_AD_MODULE_DIR) \ + $(KRB5_LIBKRB5_MODULE_DIR) $(KRB5_TLS_MODULE_DIR) \ + $(localstatedir) $(localstatedir)/krb5kdc \ + $(runstatedir) $(runstatedir)/krb5kdc \ + $(KRB5_INCSUBDIRS) $(datadir) $(EXAMPLEDIR) \ + $(PKGCONFIG_DIR) + +install-strip: + $(MAKE) install INSTALL_STRIP=-s + +install-recurse: install-mkdirs + +install-mkdirs: + @for i in $(INSTALLMKDIRS); do \ + $(srcdir)/config/mkinstalldirs $(DESTDIR)$$i; \ + done + +install-headers-mkdirs: + $(srcdir)/config/mkinstalldirs $(DESTDIR)$(KRB5_INCDIR) + $(srcdir)/config/mkinstalldirs $(DESTDIR)$(KRB5_INCDIR)/gssapi + $(srcdir)/config/mkinstalldirs $(DESTDIR)$(KRB5_INCDIR)/gssrpc +install-headers-prerecurse: install-headers-mkdirs + +clean-:: clean-windows +clean-unix:: + $(RM) *.o core skiptests + +# Microsoft Windows build process... +# + +config-windows: Makefile-windows +# @echo Making in include +# cd include +# $(MAKE) -$(MFLAGS) +# cd .. + +# +# We need outpre-dir explicitly in here because we may +# try to build wconfig on a config-windows. +# +##DOS##$(WCONFIG_EXE): outpre-dir wconfig.c +##DOS## $(CC) -Fe$@ -Fo$*.obj wconfig.c $(CCLINKOPTION) +##DOS## $(_VC_MANIFEST_EMBED_EXE) + +##DOS##MKFDEP=$(WCONFIG_EXE) config\win-pre.in config\win-post.in + +WINMAKEFILES=Makefile \ + appl\Makefile appl\gss-sample\Makefile \ + ccapi\Makefile \ + ccapi\lib\win\Makefile \ + ccapi\server\win\Makefile \ + ccapi\test\Makefile \ + clients\Makefile clients\kdestroy\Makefile \ + clients\kinit\Makefile clients\klist\Makefile \ + clients\kpasswd\Makefile clients\kvno\Makefile \ + clients\kcpytkt\Makefile clients\kdeltkt\Makefile \ + clients\kswitch\Makefile \ + include\Makefile \ + lib\Makefile lib\crypto\Makefile lib\crypto\krb\Makefile \ + lib\crypto\builtin\Makefile lib\crypto\builtin\aes\Makefile \ + lib\crypto\builtin\enc_provider\Makefile \ + lib\crypto\builtin\des\Makefile lib\crypto\builtin\md5\Makefile \ + lib\crypto\builtin\camellia\Makefile lib\crypto\builtin\md4\Makefile \ + lib\crypto\builtin\hash_provider\Makefile \ + lib\crypto\builtin\sha2\Makefile lib\crypto\builtin\sha1\Makefile \ + lib\crypto\crypto_tests\Makefile \ + lib\gssapi\Makefile lib\gssapi\generic\Makefile \ + lib\gssapi\krb5\Makefile lib\gssapi\mechglue\Makefile \ + lib\gssapi\spnego\Makefile \ + lib\krb5\Makefile \ + lib\krb5\asn.1\Makefile lib\krb5\ccache\Makefile \ + lib\krb5\ccache\ccapi\Makefile \ + lib\krb5\error_tables\Makefile \ + lib\krb5\keytab\Makefile \ + lib\krb5\krb\Makefile \ + lib\krb5\os\Makefile lib\krb5\posix\Makefile \ + lib\krb5\rcache\Makefile \ + lib\krb5\unicode\Makefile \ + util\Makefile \ + util\et\Makefile util\profile\Makefile util\profile\testmod\Makefile \ + util\support\Makefile \ + util\windows\Makefile \ + windows\Makefile windows\lib\Makefile windows\ms2mit\Makefile \ + windows\kfwlogon\Makefile windows\leashdll\Makefile \ + windows\leash\Makefile windows\leash\htmlhelp\Makefile \ + plugins\preauth\spake\Makefile + +##DOS##Makefile-windows: $(MKFDEP) $(WINMAKEFILES) + +##DOS##Makefile: Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##appl\Makefile: appl\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##appl\gss-sample\Makefile: appl\gss-sample\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##ccapi\Makefile: ccapi\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##ccapi\lib\win\Makefile: ccapi\lib\win\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##ccapi\server\win\Makefile: ccapi\server\win\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##ccapi\test\Makefile: ccapi\test\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##clients\Makefile: clients\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##clients\kdestroy\Makefile: clients\kdestroy\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##clients\kinit\Makefile: clients\kinit\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##clients\klist\Makefile: clients\klist\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##clients\kpasswd\Makefile: clients\kpasswd\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##clients\kswitch\Makefile: clients\kswitch\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##clients\kvno\Makefile: clients\kvno\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##clients\kcpytkt\Makefile: clients\kcpytkt\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##clients\kdeltkt\Makefile: clients\kdeltkt\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##include\Makefile: include\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\Makefile: lib\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\crypto\Makefile: lib\crypto\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\crypto\krb\Makefile: lib\crypto\krb\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\crypto\builtin\aes\Makefile: lib\crypto\builtin\aes\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\crypto\builtin\enc_provider\Makefile: lib\crypto\builtin\enc_provider\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\crypto\builtin\des\Makefile: lib\crypto\builtin\des\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\crypto\builtin\md5\Makefile: lib\crypto\builtin\md5\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\crypto\builtin\camellia\Makefile: lib\crypto\builtin\camellia\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\crypto\builtin\md4\Makefile: lib\crypto\builtin\md4\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\crypto\builtin\hash_provider\Makefile: lib\crypto\builtin\hash_provider\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\crypto\builtin\sha2\Makefile: lib\crypto\builtin\sha2\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\crypto\builtin\sha1\Makefile: lib\crypto\builtin\sha1\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\crypto\builtin\Makefile: lib\crypto\builtin\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\crypto\crypto_tests\Makefile: lib\crypto\crypto_tests\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\gssapi\Makefile: lib\gssapi\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\gssapi\generic\Makefile: lib\gssapi\generic\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\gssapi\mechglue\Makefile: lib\gssapi\mechglue\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\gssapi\spnego\Makefile: lib\gssapi\spnego\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\gssapi\krb5\Makefile: lib\gssapi\krb5\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\krb5\Makefile: lib\krb5\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\krb5\asn.1\Makefile: lib\krb5\asn.1\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\krb5\ccache\Makefile: lib\krb5\ccache\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\krb5\ccache\ccapi\Makefile: lib\krb5\ccache\ccapi\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\krb5\error_tables\Makefile: lib\krb5\error_tables\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\krb5\keytab\Makefile: $$@.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\krb5\krb\Makefile: lib\krb5\krb\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\krb5\os\Makefile: lib\krb5\os\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\krb5\posix\Makefile: lib\krb5\posix\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\krb5\rcache\Makefile: lib\krb5\rcache\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##lib\krb5\unicode\Makefile: lib\krb5\unicode\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##util\Makefile: util\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##util\et\Makefile: util\et\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##util\profile\Makefile: util\profile\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##util\profile\testmod\Makefile: util\profile\testmod\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##util\support\Makefile: util\support\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##util\windows\Makefile: util\windows\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##windows\Makefile: windows\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##windows\lib\Makefile: windows\lib\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##windows\ms2mit\Makefile: windows\ms2mit\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##windows\kfwlogon\Makefile: windows\kfwlogon\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##windows\leashdll\Makefile: windows\leashdll\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##windows\leash\Makefile: windows\leash\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##windows\leash\htmlhelp\Makefile: windows\leash\htmlhelp\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ +##DOS##plugins\preauth\spake\Makefile: plugins\preauth\spake\Makefile.in $(MKFDEP) +##DOS## $(WCONFIG) config < $@.in > $@ + +clean-windows:: Makefile-windows + +# +# Renames DOS 8.3 filenames back to their proper, longer names. +# +ren2long: + -sh config/ren2long + +# +# Helper for the windows build +# +TOPLEVEL=dummy + +# +# Building error tables requires awk. +# +AWK = awk +AH = util/et/et_h.awk +AC = util/et/et_c.awk +INC = include/ +ET = lib/krb5/error_tables/ +GG = lib/gssapi/generic/ +GK = lib/gssapi/krb5/ +PR = util/profile/ +CE = util/et/ +CCL = ccapi/lib/ + +ETOUT = \ + $(INC)asn1_err.h $(ET)asn1_err.c \ + $(INC)kdb5_err.h $(ET)kdb5_err.c \ + $(INC)krb5_err.h $(ET)krb5_err.c \ + $(INC)k5e1_err.h $(ET)k5e1_err.c \ + $(INC)kv5m_err.h $(ET)kv5m_err.c \ + $(INC)krb524_err.h $(ET)krb524_err.c \ + $(PR)prof_err.h $(PR)prof_err.c \ + $(GG)gssapi_err_generic.h $(GG)gssapi_err_generic.c \ + $(GK)gssapi_err_krb5.h $(GK)gssapi_err_krb5.c \ + $(CCL)ccapi_err.h $(CCL)ccapi_err.c + +HOUT = $(INC)krb5/krb5.h $(GG)gssapi.h $(PR)profile.h + +CLEANUP= Makefile $(ETOUT) $(HOUT) \ + include/profile.h include/osconf.h + + +dos-Makefile: + cat config/win-pre.in Makefile.in config/win-post.in | \ + sed -e "s/^##DOS##//" -e "s/^##DOS//" > Makefile.tmp + mv Makefile.tmp Makefile + +prep-windows: dos-Makefile awk-windows-mac + + +$(INC)asn1_err.h: $(AH) $(ET)asn1_err.et + $(AWK) -f $(AH) outfile=$@ $(ET)asn1_err.et +$(INC)kdb5_err.h: $(AH) $(ET)kdb5_err.et + $(AWK) -f $(AH) outfile=$@ $(ET)kdb5_err.et +$(INC)krb5_err.h: $(AH) $(ET)krb5_err.et + $(AWK) -f $(AH) outfile=$@ $(ET)krb5_err.et +$(INC)k5e1_err.h: $(AH) $(ET)k5e1_err.et + $(AWK) -f $(AH) outfile=$@ $(ET)k5e1_err.et +$(INC)kv5m_err.h: $(AH) $(ET)kv5m_err.et + $(AWK) -f $(AH) outfile=$@ $(ET)kv5m_err.et +$(INC)krb524_err.h: $(AH) $(ET)krb524_err.et + $(AWK) -f $(AH) outfile=$@ $(ET)krb524_err.et +$(PR)prof_err.h: $(AH) $(PR)prof_err.et + $(AWK) -f $(AH) outfile=$@ $(PR)prof_err.et +$(GG)gssapi_err_generic.h: $(AH) $(GG)gssapi_err_generic.et + $(AWK) -f $(AH) outfile=$@ $(GG)gssapi_err_generic.et +$(GK)gssapi_err_krb5.h: $(AH) $(GK)gssapi_err_krb5.et + $(AWK) -f $(AH) outfile=$@ $(GK)gssapi_err_krb5.et +$(CCL)ccapi_err.h: $(AH) $(CCL)ccapi_err.et + $(AWK) -f $(AH) outfile=$@ $(CCL)ccapi_err.et +$(CE)test1.h: $(AH) $(CE)test1.et + $(AWK) -f $(AH) outfile=$@ $(CE)test1.et +$(CE)test2.h: $(AH) $(CE)test2.et + $(AWK) -f $(AH) outfile=$@ $(CE)test2.et + +$(ET)asn1_err.c: $(AC) $(ET)asn1_err.et + $(AWK) -f $(AC) outfile=$@ $(ET)asn1_err.et +$(ET)kdb5_err.c: $(AC) $(ET)kdb5_err.et + $(AWK) -f $(AC) outfile=$@ $(ET)kdb5_err.et +$(ET)krb5_err.c: $(AC) $(ET)krb5_err.et + $(AWK) -f $(AC) outfile=$@ $(ET)krb5_err.et +$(ET)k5e1_err.c: $(AC) $(ET)k5e1_err.et + $(AWK) -f $(AC) outfile=$@ $(ET)k5e1_err.et +$(ET)kv5m_err.c: $(AC) $(ET)kv5m_err.et + $(AWK) -f $(AC) outfile=$@ $(ET)kv5m_err.et +$(ET)krb524_err.c: $(AC) $(ET)krb524_err.et + $(AWK) -f $(AC) outfile=$@ $(ET)krb524_err.et +$(PR)prof_err.c: $(AC) $(PR)prof_err.et + $(AWK) -f $(AC) outfile=$@ $(PR)prof_err.et +$(GG)gssapi_err_generic.c: $(AC) $(GG)gssapi_err_generic.et + $(AWK) -f $(AC) outfile=$@ $(GG)gssapi_err_generic.et +$(GK)gssapi_err_krb5.c: $(AC) $(GK)gssapi_err_krb5.et + $(AWK) -f $(AC) outfile=$@ $(GK)gssapi_err_krb5.et +$(CCL)ccapi_err.c: $(AC) $(CCL)ccapi_err.et + $(AWK) -f $(AC) outfile=$@ $(CCL)ccapi_err.et +$(CE)test1.c: $(AC) $(CE)test1.et + $(AWK) -f $(AC) outfile=$@ $(CE)test1.et +$(CE)test2.c: $(AC) $(CE)test2.et + $(AWK) -f $(AC) outfile=$@ $(CE)test2.et + +KRBHDEP = $(INC)krb5/krb5.hin $(INC)krb5_err.h $(INC)k5e1_err.h \ + $(INC)kdb5_err.h $(INC)kv5m_err.h $(INC)krb524_err.h $(INC)asn1_err.h + +$(INC)krb5/krb5.h: $(KRBHDEP) + rm -f $@ + cat $(KRBHDEP) > $@ +$(PR)profile.h: $(PR)profile.hin $(PR)prof_err.h + rm -f $@ + cat $(PR)profile.hin $(PR)prof_err.h > $@ +$(GG)gssapi.h: $(GG)gssapi.hin + rm -f $@ + cat $(GG)gssapi.hin > $@ + +awk-windows-mac: $(ETOUT) $(HOUT) + +# +# The maybe-awk target needs to happen after AWK is defined. +# + +##DOS##maybe-awk: +##DOS##!ifdef WHICH_CMD +##DOS##!if ![ $(WHICH_CMD) $(AWK) ] +##DOS##maybe-awk: awk-windows-mac +##DOS##!endif +##DOS##!endif + +clean-windows-mac: + rm -f $(CLEANUP) + +distclean-windows: + config\rm.bat $(CLEANUP:^/=^\) + config\rm.bat $(WINMAKEFILES) + config\rm.bat $(KBINDIR)\*.dll $(KBINDIR)\*.exe + @if exist $(KBINDIR)\nul rmdir $(KBINDIR) + +# Avoid using $(CP) here because the nul+ hack breaks implicit +# destination filenames. +install-windows: + @if "$(KRB_INSTALL_DIR)"=="" @echo KRB_INSTALL_DIR is not defined! Please define it. + @if "$(KRB_INSTALL_DIR)"=="" @dir /b \nul\nul + @if not exist "$(KRB_INSTALL_DIR)\$(NULL)" @echo The directory $(KRB_INSTALL_DIR) does not exist. Please create it. + @if not exist "$(KRB_INSTALL_DIR)\$(NULL)" @dir /b $(KRB_INSTALL_DIR)\nul + @if not exist "$(KRB_INSTALL_DIR)\include\$(NULL)" @mkdir "$(KRB_INSTALL_DIR)\include" + @if not exist "$(KRB_INSTALL_DIR)\include\krb5\$(NULL)" @mkdir "$(KRB_INSTALL_DIR)\include\krb5" + @if not exist "$(KRB_INSTALL_DIR)\include\gssapi\$(NULL)" @mkdir "$(KRB_INSTALL_DIR)\include\gssapi" + @if not exist "$(KRB_INSTALL_DIR)\lib\$(NULL)" @mkdir "$(KRB_INSTALL_DIR)\lib" + @if not exist "$(KRB_INSTALL_DIR)\bin\$(NULL)" @mkdir "$(KRB_INSTALL_DIR)\bin" + @if not exist "$(KRB_INSTALL_DIR)\bin\plugins\$(NULL)" @mkdir "$(KRB_INSTALL_DIR)\bin\plugins" + @if not exist "$(KRB_INSTALL_DIR)\bin\plugins\preauth\$(NULL)" @mkdir "$(KRB_INSTALL_DIR)\bin\plugins\preauth" + copy include\krb5.h "$(KRB_INSTALL_DIR)\include\." + copy include\krb5\krb5.h "$(KRB_INSTALL_DIR)\include\krb5\." + copy include\win-mac.h "$(KRB_INSTALL_DIR)\include\." + copy include\profile.h "$(KRB_INSTALL_DIR)\include\." + copy include\com_err.h "$(KRB_INSTALL_DIR)\include\." + copy include\gssapi\gssapi.h "$(KRB_INSTALL_DIR)\include\gssapi\." + copy include\gssapi\gssapi_alloc.h "$(KRB_INSTALL_DIR)\include\gssapi\." + copy include\gssapi\gssapi_krb5.h "$(KRB_INSTALL_DIR)\include\gssapi\." + copy include\gssapi\gssapi_ext.h "$(KRB_INSTALL_DIR)\include\gssapi\." + copy lib\$(OUTPRE)*.lib "$(KRB_INSTALL_DIR)\lib\." + copy lib\$(OUTPRE)*.dll "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) lib\$(OUTPRE)*.pdb "$(KRB_INSTALL_DIR)\bin\." + copy appl\gss-sample\$(OUTPRE)gss-server.exe "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) appl\gss-sample\$(OUTPRE)gss-server.pdb "$(KRB_INSTALL_DIR)\bin\." + copy appl\gss-sample\$(OUTPRE)gss-client.exe "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) appl\gss-sample\$(OUTPRE)gss-client.pdb "$(KRB_INSTALL_DIR)\bin\." + copy windows\ms2mit\$(OUTPRE)*.exe "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) windows\ms2mit\$(OUTPRE)*.pdb "$(KRB_INSTALL_DIR)\bin\." + copy windows\leashdll\$(OUTPRE)*.lib "$(KRB_INSTALL_DIR)\lib\." + copy windows\leashdll\$(OUTPRE)*.dll "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) windows\leashdll\$(OUTPRE)*.pdb "$(KRB_INSTALL_DIR)\bin\." +##DOS##!ifndef NO_LEASH + copy windows\leash\$(OUTPRE)*.exe "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) windows\leash\$(OUTPRE)*.pdb "$(KRB_INSTALL_DIR)\bin\." + copy windows\leash\$(OUTPRE)*.chm "$(KRB_INSTALL_DIR)\bin\." + copy windows\leash\htmlhelp\*.chm "$(KRB_INSTALL_DIR)\bin\." +##DOS##!endif + copy windows\kfwlogon\$(OUTPRE)*.lib "$(KRB_INSTALL_DIR)\lib\." + copy windows\kfwlogon\$(OUTPRE)*.exe "$(KRB_INSTALL_DIR)\bin\." + copy windows\kfwlogon\$(OUTPRE)*.dll "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) windows\kfwlogon\$(OUTPRE)*.pdb "$(KRB_INSTALL_DIR)\bin\." + copy ccapi\lib\win\srctmp\$(OUTPRE)$(CCLIB).dll "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) ccapi\lib\win\srctmp\$(OUTPRE)$(CCLIB).pdb "$(KRB_INSTALL_DIR)\bin\." + copy ccapi\lib\win\srctmp\$(CCLIB).lib "$(KRB_INSTALL_DIR)\lib\." + copy ccapi\server\win\srctmp\$(OUTPRE)ccapiserver.exe "$(KRB_INSTALL_DIR)\bin\." + copy clients\kvno\$(OUTPRE)kvno.exe "$(KRB_INSTALL_DIR)\bin\." + copy clients\klist\$(OUTPRE)klist.exe "$(KRB_INSTALL_DIR)\bin\." + copy clients\kinit\$(OUTPRE)kinit.exe "$(KRB_INSTALL_DIR)\bin\." + copy clients\kdestroy\$(OUTPRE)kdestroy.exe "$(KRB_INSTALL_DIR)\bin\." + copy clients\kcpytkt\$(OUTPRE)kcpytkt.exe "$(KRB_INSTALL_DIR)\bin\." + copy clients\kdeltkt\$(OUTPRE)kdeltkt.exe "$(KRB_INSTALL_DIR)\bin\." + copy clients\kpasswd\$(OUTPRE)kpasswd.exe "$(KRB_INSTALL_DIR)\bin\." + copy clients\kswitch\$(OUTPRE)kswitch.exe "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) ccapi\server\win\srctmp\$(OUTPRE)ccapiserver.pdb "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) clients\kvno\$(OUTPRE)kvno.pdb "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) clients\klist\$(OUTPRE)klist.pdb "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) clients\kinit\$(OUTPRE)kinit.pdb "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) clients\kdestroy\$(OUTPRE)kdestroy.pdb "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) clients\kcpytkt\$(OUTPRE)kcpytkt.pdb "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) clients\kdeltkt\$(OUTPRE)kdeltkt.pdb "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) clients\kpasswd\$(OUTPRE)kpasswd.pdb "$(KRB_INSTALL_DIR)\bin\." + $(INSTALLDBGSYMS) clients\kswitch\$(OUTPRE)kswitch.pdb "$(KRB_INSTALL_DIR)\bin\." + copy plugins\preauth\spake\$(OUTPRE)$(SPAKELIB).dll "$(KRB_INSTALL_DIR)\bin\plugins\preauth\." + $(INSTALLDBGSYMS) plugins\preauth\spake\$(OUTPRE)$(SPAKELIB).pdb "$(KRB_INSTALL_DIR)\bin\plugins\preauth\." + +check-prerecurse: runenv.py + $(RM) $(SKIPTESTS) + touch $(SKIPTESTS) + +check-unix: check-lmdb-$(HAVE_LMDB) + cat $(SKIPTESTS) + +MINPYTHON = @PYTHON_MINVERSION@ +check-pytests-no: check-postrecurse + @echo 'Skipped python test scripts: python $(MINPYTHON) required' >> \ + $(SKIPTESTS) + +check-cmocka-no: check-postrecurse + @echo 'Skipped cmocka tests: cmocka library or header not found' >> \ + $(SKIPTESTS) + +check-lmdb-yes: +check-lmdb-no: + @echo 'Skipped LMDB tests: LMDB KDB module not built' >> $(SKIPTESTS) + +# Create a test realm and spawn a shell in an environment pointing to it. +# If CROSSNUM is set, create that many fully connected test realms and +# point the shell at the first one. +testrealm: runenv.py + PYTHONPATH=$(top_srcdir)/util $(PYTHON) $(srcdir)/util/testrealm.py \ + $(CROSSNUM) + +# environment variable settings to propagate to Python-based tests + +pyrunenv.vals: Makefile + $(RUN_SETUP); \ + for i in $(RUN_VARS); do \ + eval echo 'env['\\\'$$i\\\''] = '\\\'\$$$$i\\\'; \ + done > $@ + echo "tls_impl = '$(TLS_IMPL)'" >> $@ + echo "have_sasl = '$(HAVE_SASL)'" >> $@ + echo "have_spake_openssl = '$(HAVE_SPAKE_OPENSSL)'" >> $@ + echo "have_lmdb = '$(HAVE_LMDB)'" >> $@ + echo "sizeof_time_t = $(SIZEOF_TIME_T)" >> $@ + +runenv.py: pyrunenv.vals + echo 'env = {}' > $@ + cat pyrunenv.vals >> $@ + +clean-unix:: + $(RM) runenv.py runenv.pyc pyrunenv.vals + $(RM) -r __pycache__ + +COV_BUILD= cov-build +COV_ANALYZE= cov-analyze +COV_COMMIT= cov-commit-defects --product "$(COV_PRODUCT)" --user "$(COV_USER)" --target "$(COV_TARGET)" --description "$(COV_DESC)" +COV_MAKE_LIB= cov-make-library + +COV_PRODUCT= krb5 +COV_USER= admin +COV_DATADIR= +COV_TARGET= $(host) +COV_DESC= + +# Set to, e.g., "--all" or "--security". +COV_ANALYSES= +# Temporary directory, might as well put it in the build tree. +COV_TEMPDIR= cov-temp +# Sources modeling some functions or macros confusing Prevent. +COV_MODELS=\ + $(top_srcdir)/util/coverity-models/threads.c + +# Depend on Makefiles to ensure that (in maintainer mode) the configure +# scripts won't get rerun under cov-build. +coverity prevent cov: Makefiles + $(COV_BUILD) --dir $(COV_TEMPDIR) $(MAKE) all + $(COV_ANALYZE) $(COV_ANALYSES) --dir $(COV_TEMPDIR) + if test "$(COV_DATADIR)" != ""; then \ + $(COV_COMMIT) --dir $(COV_TEMPDIR) --datadir $(COV_DATADIR); \ + else \ + echo "** Coverity Prevent analysis results not commit to Defect Manager"; \ + fi + +FIND = find +XARGS = xargs +EMACS = emacs + +INDENTDIRS = \ + appl \ + clients \ + include \ + kadmin \ + kdc \ + lib/apputils \ + lib/crypto \ + lib/gssapi \ + lib/kadm5 \ + lib/kdb \ + lib/krb5 \ + plugins \ + prototype \ + kprop \ + tests \ + util + +BSDFILES = \ + kadmin/server/ipropd_svc.c \ + kadmin/server/kadm_rpc_svc.c \ + lib/apputils/daemon.c \ + lib/kadm5/admin_xdr.h \ + lib/kadm5/clnt/client_rpc.c \ + lib/kadm5/kadm_rpc.h \ + lib/kadm5/kadm_rpc_xdr.c \ + lib/kadm5/srv/adb_xdr.c \ + lib/krb5/krb/strptime.c \ + kprop/kpropd_rpc.c \ + util/support/getopt.c \ + util/support/getopt_long.c \ + util/support/mkstemp.c \ + util/support/strlcpy.c + +OTHEREXCLUDES = \ + include/iprop.h \ + include/k5-platform.h \ + include/gssrpc \ + lib/apputils/dummy.c \ + lib/crypto/crypto_tests/camellia-test.c \ + lib/crypto/builtin/aes \ + lib/crypto/builtin/camellia \ + lib/crypto/builtin/sha2 \ + lib/gssapi/generic/gssapiP_generic.h \ + lib/gssapi/generic/gssapi_ext.h \ + lib/gssapi/krb5/gssapiP_krb5.h \ + lib/gssapi/mechglue \ + lib/gssapi/spnego \ + lib/krb5/krb/deltat.c \ + lib/krb5/unicode \ + plugins/kdb/db2/libdb2 \ + plugins/kdb/db2/pol_xdr.c \ + plugins/preauth/pkinit/pkcs11.h \ + plugins/preauth/pkinit/pkinit_accessor.h \ + plugins/preauth/pkinit/pkinit_crypto.h \ + plugins/preauth/pkinit/pkinit.h \ + plugins/preauth/pkinit/pkinit_crypto_openssl.h \ + tests/asn.1/ktest.h \ + tests/asn.1/ktest_equal.h \ + tests/asn.1/utility.h \ + tests/gss-threads/gss-misc.c \ + tests/gss-threads/gss-misc.h \ + tests/hammer/kdc5_hammer.c \ + util/et/com_err.h \ + util/profile/prof_int.h \ + util/profile/profile.hin \ + util/support/fnmatch.c \ + util/verto \ + util/k5ev + +EXCLUDES = `for i in $(BSDFILES) $(OTHEREXCLUDES); do echo $$i; done | $(AWK) '{ print "-path", $$1, "-o" }'` -path /dev/null + +FIND_REINDENT = cd $(top_srcdir) && \ + $(FIND) $(INDENTDIRS) \( $(EXCLUDES) \) -prune -o \ + \( -name '*.[ch]' -o -name '*.hin' -o -name '*.[ch].in' \) + +show-reindentfiles: + ($(FIND_REINDENT) -print) + +reindent: + ($(FIND_REINDENT) \ + -print0 | $(XARGS) -0 $(EMACS) -q -batch \ + -l util/krb5-c-style.el \ + -l util/krb5-batch-reindent.el) + +mark-cstyle: mark-cstyle-krb5 mark-cstyle-bsd + +mark-cstyle-krb5: + (cd $(top_srcdir) && \ + $(FIND) $(INDENTDIRS) \( $(EXCLUDES) \) -prune -o \ + -name '*.[ch]' \ + -print0 | $(XARGS) -0 $(PYTHON) util/krb5-mark-cstyle.py \ + --cstyle=krb5) + +mark-cstyle-bsd: + (cd $(top_srcdir) && $(FIND) $(BSDFILES) -print0 | $(XARGS) -0 \ + $(PYTHON) util/krb5-mark-cstyle.py --cstyle=bsd) + +check-copyright: + (cd $(top_srcdir) && \ + $(FIND) . \( -name '*.[ch]' -o -name '*.hin' \) -print0 | \ + $(XARGS) -0 $(PYTHON) util/krb5-check-copyright.py) + +tags: FORCE + (cd $(top_srcdir) && \ + $(FIND) . \( -name '*.[ch]' -o -name '*.hin' \) -print | \ + etags --lang=c - && \ + $(FIND) . -name '*.cpp' -print | etags --lang=c++ --append - && \ + $(FIND) . -name '*.y' -print | etags --lang=yacc --append -) +FORCE: +.PHONY: FORCE tags + +# Update versioned automatically-generated files. +regen: + $(MAKE) depend + (cd man && $(MAKE) man) + (cd po && $(MAKE) update-po) + (cd lib/krb5/krb && $(RM) deltat.c && $(MAKE) deltat.c) + +distclean-unix: + $(RM) $(top_srcdir)/TAGS diff --git a/krb5-1.21.3/src/aclocal.m4 b/krb5-1.21.3/src/aclocal.m4 new file mode 100644 index 00000000..3d66a876 --- /dev/null +++ b/krb5-1.21.3/src/aclocal.m4 @@ -0,0 +1,1460 @@ +AC_PREREQ(2.63) +AC_COPYRIGHT([Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 +Massachusetts Institute of Technology. +]) +dnl +define([K5_TOPDIR],[.])dnl +dnl +AC_DEFUN(V5_SET_TOPDIR,[dnl +ac_reltopdir="K5_TOPDIR" +if test ! -r "$srcdir/K5_TOPDIR/aclocal.m4"; then + AC_MSG_ERROR([Configure could not determine the relative topdir]) +fi +ac_topdir=$srcdir/$ac_reltopdir +ac_config_fragdir=$ac_reltopdir/config +# echo "Looking for $srcdir/$ac_config_fragdir" +AC_CONFIG_AUX_DIR(K5_TOPDIR/config) +])dnl +dnl +dnl Version info. +dnl +pushdef([x],esyscmd([sed -n 's/#define \([A-Z0-9_]*\)[ \t]*\(.*\)/\1=\2/p' < ]K5_TOPDIR/patchlevel.h)) +define([PL_KRB5_MAJOR_RELEASE],regexp(x,[KRB5_MAJOR_RELEASE=\(.*\)],[\1])) +ifelse(PL_KRB5_MAJOR_RELEASE,,[errprint([Can't determine KRB5_MAJOR_RELEASE value from patchlevel.h. +]) m4exit(1) dnl sometimes that does not work? +builtin(m4exit,1)]) +define([PL_KRB5_MINOR_RELEASE],regexp(x,[KRB5_MINOR_RELEASE=\(.*\)],[\1])) +ifelse(PL_KRB5_MINOR_RELEASE,,[errprint([Can't determine KRB5_MINOR_RELEASE value from patchlevel.h. +]) m4exit(1) dnl sometimes that does not work? +builtin(m4exit,1)]) +define([PL_KRB5_PATCHLEVEL],regexp(x,[KRB5_PATCHLEVEL=\(.*\)],[\1])) +ifelse(PL_KRB5_PATCHLEVEL,,[errprint([Can't determine KRB5_PATCHLEVEL value from patchlevel.h. +]) m4exit(1) dnl sometimes that does not work? +builtin(m4exit,1)]) +define([PL_KRB5_RELTAIL],regexp(x,[KRB5_RELTAIL="\(.*\)"],[\1])) +dnl RELTAIL is allowed to not be defined. +popdef([x]) +define([K5_VERSION],PL_KRB5_MAJOR_RELEASE.PL_KRB5_MINOR_RELEASE[]ifelse(PL_KRB5_PATCHLEVEL,0,,.PL_KRB5_PATCHLEVEL)ifelse(PL_KRB5_RELTAIL,,,-PL_KRB5_RELTAIL)) +define([K5_BUGADDR],krb5-bugs@mit.edu) +define([K5_AC_INIT],[AC_INIT(Kerberos 5, K5_VERSION, K5_BUGADDR, krb5) +AC_CONFIG_SRCDIR($1) +build_dynobj=no]) +dnl +dnl drop in standard rules for all configure files -- CONFIG_RULES +dnl +AC_DEFUN(CONFIG_RULES,[dnl +AC_REQUIRE([V5_SET_TOPDIR]) dnl +EXTRA_FILES="" +AC_SUBST(EXTRA_FILES) +dnl Consider using AC_USE_SYSTEM_EXTENSIONS when we require autoconf +dnl 2.59c or later, but be sure to test on Solaris first. +AC_DEFINE([_GNU_SOURCE], 1, [Define to enable extensions in glibc]) +AC_DEFINE([__STDC_WANT_LIB_EXT1__], 1, [Define to enable C11 extensions]) + +WITH_CC dnl +AC_REQUIRE_CPP +if test -z "$LD" ; then LD=$CC; fi +AC_ARG_VAR(LD,[linker command [CC]]) +AC_SUBST(LDFLAGS) dnl +KRB5_AC_CHOOSE_ET dnl +KRB5_AC_CHOOSE_SS dnl +KRB5_AC_CHOOSE_DB dnl +dnl allow stuff in tree to access deprecated stuff for now +dnl AC_DEFINE([KRB5_DEPRECATED], 1, [Define only if building in-tree]) +AC_C_CONST dnl +WITH_NETLIB dnl +WITH_HESIOD dnl +KRB5_AC_MAINTAINER_MODE dnl +AC_ARG_PROGRAM dnl +dnl +dnl This identifies the top of the source tree relative to the directory +dnl in which the configure file lives. +dnl +CONFIG_RELTOPDIR=$ac_reltopdir +AC_SUBST(CONFIG_RELTOPDIR) +lib_frag=$srcdir/$ac_config_fragdir/lib.in +AC_SUBST_FILE(lib_frag) +libobj_frag=$srcdir/$ac_config_fragdir/libobj.in +AC_SUBST_FILE(libobj_frag) +libnover_frag=$srcdir/$ac_config_fragdir/libnover.in +AC_SUBST_FILE(libnover_frag) +libpriv_frag=$srcdir/$ac_config_fragdir/libpriv.in +AC_SUBST_FILE(libpriv_frag) +libnodeps_frag=$srcdir/$ac_config_fragdir/libnodeps.in +AC_SUBST_FILE(libnodeps_frag) +dnl +KRB5_AC_PRAGMA_WEAK_REF +WITH_LDAP +KRB5_LIB_PARAMS +KRB5_AC_INITFINI +KRB5_AC_ENABLE_THREADS +KRB5_AC_FIND_DLOPEN +])dnl + +dnl Maintainer mode, akin to what automake provides, 'cept we don't +dnl want to use automake right now. +AC_DEFUN([KRB5_AC_MAINTAINER_MODE], +[AC_ARG_ENABLE([maintainer-mode], + [AS_HELP_STRING([--enable-maintainer-mode], + [enable rebuilding of source files, Makefiles, etc])], + [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=no]) +if test "$USE_MAINTAINER_MODE" = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' + AC_MSG_NOTICE(enabling maintainer mode) +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi +MAINT=$MAINTAINER_MODE_TRUE +AC_SUBST(MAINTAINER_MODE_TRUE) +AC_SUBST(MAINTAINER_MODE_FALSE) +AC_SUBST(MAINT) +]) + +dnl +AC_DEFUN([KRB5_AC_INITFINI],[ +dnl Do we want initialization at load time? +AC_ARG_ENABLE([delayed-initialization], + [AS_HELP_STRING([--disable-delayed-initialization], + [initialize library code when loaded @<:@delay until first use@:>@])], + [], [enable_delayed_initialization=yes]) +case "$enable_delayed_initialization" in + yes) + AC_DEFINE(DELAY_INITIALIZER,1,[Define if library initialization should be delayed until first use]) ;; + no) ;; + *) AC_MSG_ERROR(invalid option $enable_delayed_initialization for delayed-initialization) ;; +esac +dnl We always want finalization at unload time. +dnl +dnl Can we do things through gcc? +KRB5_AC_GCC_ATTRS +dnl How about with the linker? +if test -z "$use_linker_init_option" ; then + AC_MSG_ERROR(ran INITFINI before checking shlib.conf?) +fi +if test "$use_linker_init_option" = yes; then + AC_DEFINE(USE_LINKER_INIT_OPTION,1,[Define if link-time options for library initialization will be used]) +fi +if test "$use_linker_fini_option" = yes; then + AC_DEFINE(USE_LINKER_FINI_OPTION,1,[Define if link-time options for library finalization will be used]) +fi +]) + +dnl find dlopen +AC_DEFUN([KRB5_AC_FIND_DLOPEN],[ +old_LIBS="$LIBS" +DL_LIB= +AC_SEARCH_LIBS(dlopen, dl, [ +if test "$ac_cv_search_dlopen" != "none required"; then + DL_LIB=$ac_cv_search_dlopen +fi +LIBS="$old_LIBS" +AC_DEFINE(USE_DLOPEN,1,[Define if dlopen should be used])]) +AC_SUBST(DL_LIB) +]) + + +dnl Hack for now. +AC_DEFUN([KRB5_AC_ENABLE_THREADS],[ +AC_ARG_ENABLE([thread-support], + [AS_HELP_STRING([--disable-thread-support], + [don't enable thread support @<:@enabled@:>@])], + [], [enable_thread_support=yes]) +if test "$enable_thread_support" = yes ; then + AC_MSG_NOTICE(enabling thread support) + AC_DEFINE(ENABLE_THREADS,1,[Define if thread support enabled]) +fi +dnl Maybe this should be inside the conditional above? Doesn't cache.... +if test "$enable_thread_support" = yes; then + AX_PTHREAD(,[AC_MSG_ERROR([cannot determine options for enabling thread support; try --disable-thread-support])]) + AC_MSG_NOTICE(PTHREAD_CC = $PTHREAD_CC) + AC_MSG_NOTICE(PTHREAD_CFLAGS = $PTHREAD_CFLAGS) + AC_MSG_NOTICE(PTHREAD_LIBS = $PTHREAD_LIBS) + dnl Not really needed -- if pthread.h isn't found, ACX_PTHREAD will fail. + dnl AC_CHECK_HEADERS(pthread.h) + # AIX and Tru64 don't support weak references, and don't have + # stub versions of the pthread code in libc. + case "${host_os}" in + aix* | osf*) + # On these platforms, we'll always pull in the thread support. + LIBS="$LIBS $PTHREAD_LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + # We don't need to sometimes add the flags we've just folded in... + PTHREAD_LIBS= + PTHREAD_CFLAGS= + ;; + hpux*) + # These are the flags that "gcc -pthread" adds. But we don't + # want "-pthread" because that has link-time effects, and we + # don't exclude CFLAGS when linking. *sigh* + PTHREAD_CFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_C_SOURCE=199506L" + ;; + solaris2.[[1-9]]) + # On Solaris 10 with gcc 3.4.3, the autoconf archive macro doesn't + # get the right result. XXX What about Solaris 9 and earlier? + if test "$GCC" = yes ; then + PTHREAD_CFLAGS="-D_REENTRANT -pthreads" + fi + ;; + solaris*) + # On Solaris 10 with gcc 3.4.3, the autoconf archive macro doesn't + # get the right result. + if test "$GCC" = yes ; then + PTHREAD_CFLAGS="-D_REENTRANT -pthreads" + fi + # On Solaris 10, the thread support is always available in libc. + AC_DEFINE(NO_WEAK_PTHREADS,1,[Define if references to pthread routines should be non-weak.]) + ;; + esac + THREAD_SUPPORT=1 +else + PTHREAD_CC="$CC" + PTHREAD_CFLAGS="" + PTHREAD_LIBS="" + THREAD_SUPPORT=0 +fi +AC_SUBST(THREAD_SUPPORT) +dnl We want to know where these routines live, so on systems with weak +dnl reference support we can figure out whether or not the pthread library +dnl has been linked in. +dnl If we don't add any libraries for thread support, don't bother. +AC_CHECK_FUNCS(pthread_once pthread_rwlock_init) +old_CC="$CC" +test "$PTHREAD_CC" != "" && test "$ac_cv_c_compiler_gnu" = no && CC=$PTHREAD_CC +old_CFLAGS="$CFLAGS" +# On Solaris, -pthreads is added to CFLAGS, no extra explicit libraries. +CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +AC_SUBST(PTHREAD_CFLAGS) +old_LIBS="$LIBS" +LIBS="$PTHREAD_LIBS $LIBS" +AC_MSG_NOTICE(rechecking with PTHREAD_... options) +AC_CHECK_LIB(c, pthread_rwlock_init, + [AC_DEFINE(HAVE_PTHREAD_RWLOCK_INIT_IN_THREAD_LIB,1,[Define if pthread_rwlock_init is provided in the thread library.])]) +LIBS="$old_LIBS" +CC="$old_CC" +CFLAGS="$old_CFLAGS" +]) + +dnl This is somewhat gross and should go away when the build system +dnl is revamped. -- tlyu +dnl DECLARE_SYS_ERRLIST - check for sys_errlist in libc +dnl +AC_DEFUN([DECLARE_SYS_ERRLIST], +[AC_CACHE_CHECK([for sys_errlist declaration], krb5_cv_decl_sys_errlist, +[AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + ]], + [[1+sys_nerr;]])], + [krb5_cv_decl_sys_errlist=yes], [krb5_cv_decl_sys_errlist=no])]) +# assume sys_nerr won't be declared w/o being in libc +if test $krb5_cv_decl_sys_errlist = yes; then + AC_DEFINE(SYS_ERRLIST_DECLARED,1,[Define if sys_errlist is defined in errno.h]) + AC_DEFINE(HAVE_SYS_ERRLIST,1,[Define if sys_errlist in libc]) +else + # This means that sys_errlist is not declared in errno.h, but may still + # be in libc. + AC_CACHE_CHECK([for sys_errlist in libc], krb5_cv_var_sys_errlist, + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[extern int sys_nerr;]], + [[if (1+sys_nerr < 0) return 1;]])], + [krb5_cv_var_sys_errlist=yes], [krb5_cv_var_sys_errlist=no])]) + if test $krb5_cv_var_sys_errlist = yes; then + AC_DEFINE(HAVE_SYS_ERRLIST,1,[Define if sys_errlist in libc]) + # Do this cruft for backwards compatibility for now. + AC_DEFINE(NEED_SYS_ERRLIST,1,[Define if need to declare sys_errlist]) + else + AC_MSG_WARN([sys_errlist is neither in errno.h nor in libc]) + fi +fi]) + +dnl +dnl check for sigmask/sigprocmask -- CHECK_SIGPROCMASK +dnl +AC_DEFUN(CHECK_SIGPROCMASK,[ +AC_MSG_CHECKING([for use of sigprocmask]) +AC_CACHE_VAL(krb5_cv_func_sigprocmask_use, +[AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[sigprocmask(SIG_SETMASK, 0, 0);]])], + [krb5_cv_func_sigprocmask_use=yes], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[sigmask(1);]])], + [krb5_cv_func_sigprocmask_use=no], [krb5_cv_func_sigprocmask_use=yes])])]) +AC_MSG_RESULT($krb5_cv_func_sigprocmask_use) +if test $krb5_cv_func_sigprocmask_use = yes; then + AC_DEFINE(USE_SIGPROCMASK,1,[Define if sigprocmask should be used]) +fi +])dnl +dnl +dnl +dnl check for -- CHECK_DIRENT +dnl (may need to be more complex later) +dnl +AC_DEFUN(CHECK_DIRENT,[ +AC_CHECK_HEADER(dirent.h,AC_DEFINE(USE_DIRENT_H,1,[Define if you have dirent.h functionality]))])dnl +dnl +dnl check if union wait is defined, or if WAIT_USES_INT -- CHECK_WAIT_TYPE +dnl +AC_DEFUN(CHECK_WAIT_TYPE,[ +AC_MSG_CHECKING([if argument to wait is int *]) +AC_CACHE_VAL(krb5_cv_struct_wait, +dnl Test for prototype clash - if there is none - then assume int * works +[AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#include + #include + extern pid_t wait(int *);]])], + [krb5_cv_struct_wait=no], + dnl Else fallback on old stuff + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[union wait i; + #ifdef WEXITSTATUS + WEXITSTATUS (i); + #endif + ]])], + [krb5_cv_struct_wait=yes], [krb5_cv_struct_wait=no])])]) +AC_MSG_RESULT($krb5_cv_struct_wait) +if test $krb5_cv_struct_wait = no; then + AC_DEFINE(WAIT_USES_INT,1,[Define if wait takes int as a argument]) +fi +])dnl +dnl +dnl check for POSIX signal handling -- CHECK_SIGNALS +dnl +AC_DEFUN(CHECK_SIGNALS,[ +AC_CHECK_FUNC(sigprocmask, +AC_MSG_CHECKING(for sigset_t and POSIX_SIGNALS) +AC_CACHE_VAL(krb5_cv_type_sigset_t, +[AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[sigset_t x]])], + [krb5_cv_type_sigset_t=yes], [krb5_cv_type_sigset_t=no])]) +AC_MSG_RESULT($krb5_cv_type_sigset_t) +if test $krb5_cv_type_sigset_t = yes; then + AC_DEFINE(POSIX_SIGNALS,1,[Define if POSIX signal handling is used]) +fi +)])dnl +dnl +dnl check for POSIX setjmp/longjmp -- CHECK_SETJMP +dnl +AC_DEFUN(CHECK_SETJMP,[ +AC_CHECK_FUNC(sigsetjmp, +AC_MSG_CHECKING(for sigjmp_buf) +AC_CACHE_VAL(krb5_cv_struct_sigjmp_buf, +[AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[sigjmp_buf x]])], + [krb5_cv_struct_sigjmp_buf=yes], [krb5_cv_struct_sigjmp_buf=no])]) +AC_MSG_RESULT($krb5_cv_struct_sigjmp_buf) +if test $krb5_cv_struct_sigjmp_buf = yes; then + AC_DEFINE(POSIX_SETJMP,1,[Define if setjmp indicates POSIX interface]) +fi +)])dnl +dnl +dnl Check for IPv6 compile-time support. +dnl +AC_DEFUN(KRB5_AC_INET6,[ +AC_CHECK_HEADERS(sys/types.h sys/socket.h netinet/in.h netdb.h) +AC_CHECK_FUNCS(inet_ntop inet_pton getnameinfo) +dnl getaddrinfo test needs netdb.h, for proper compilation on alpha +dnl under OSF/1^H^H^H^H^HDigital^H^H^H^H^H^H^HTru64 UNIX, where it's +dnl a macro +AC_MSG_CHECKING(for getaddrinfo) +AC_CACHE_VAL(ac_cv_func_getaddrinfo, +[AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#ifdef HAVE_NETDB_H + #include + #endif + ]], + [[struct addrinfo *ai; + getaddrinfo("kerberos.mit.edu", "echo", 0, &ai);]])], + [ac_cv_func_getaddrinfo=yes], [ac_cv_func_getaddrinfo=no])]) +AC_MSG_RESULT($ac_cv_func_getaddrinfo) +if test $ac_cv_func_getaddrinfo = yes; then + AC_DEFINE(HAVE_GETADDRINFO,1,[Define if you have the getaddrinfo function]) +fi +dnl +AC_REQUIRE([KRB5_SOCKADDR_SA_LEN])dnl +AC_MSG_CHECKING(for IPv6 compile-time support without -DINET6) +AC_CACHE_VAL(krb5_cv_inet6,[ +if test "$ac_cv_func_inet_ntop" != "yes" ; then + krb5_cv_inet6=no +else + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#ifdef HAVE_SYS_TYPES_H + #include + #endif + #include + #include + #include + ]], + [[struct sockaddr_in6 in; + AF_INET6; + IN6_IS_ADDR_LINKLOCAL(&in.sin6_addr);]])], + [krb5_cv_inet6=yes], [krb5_cv_inet6=no]) +fi]) +AC_MSG_RESULT($krb5_cv_inet6) +if test "$krb5_cv_inet6" = no && test "$ac_cv_func_inet_ntop" = yes; then +AC_MSG_CHECKING(for IPv6 compile-time support with -DINET6) +AC_CACHE_VAL(krb5_cv_inet6_with_dinet6,[ +old_CC="$CC" +CC="$CC -DINET6" +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#ifdef HAVE_SYS_TYPES_H + #include + #endif + #include + #include + #include + ]], + [[struct sockaddr_in6 in; + AF_INET6; + IN6_IS_ADDR_LINKLOCAL (&in.sin6_addr);]])], + [krb5_cv_inet6_with_dinet6=yes], [krb5_cv_inet6_with_dinet6=no]) +CC="$old_CC"]) +AC_MSG_RESULT($krb5_cv_inet6_with_dinet6) +fi +if test $krb5_cv_inet6 = yes || test "$krb5_cv_inet6_with_dinet6" = yes; then + if test "$krb5_cv_inet6_with_dinet6" = yes; then + AC_DEFINE(INET6,1,[May need to be defined to enable IPv6 support, for example on IRIX]) + fi +fi +])dnl +dnl +AC_DEFUN(KRB5_AC_CHECK_FOR_CFLAGS,[ +AC_BEFORE([$0],[AC_PROG_CC]) +AC_BEFORE([$0],[AC_PROG_CXX]) +krb5_ac_cflags_set=${CFLAGS+set} +krb5_ac_cxxflags_set=${CXXFLAGS+set} +krb5_ac_warn_cflags_set=${WARN_CFLAGS+set} +krb5_ac_warn_cxxflags_set=${WARN_CXXFLAGS+set} +]) +dnl +AC_DEFUN(TRY_WARN_CC_FLAG_1,[dnl + cachevar=`echo "krb5_cv_cc_flag_$1" | sed -e s/=/_eq_/g -e s/-/_dash_/g -e s/[[^a-zA-Z0-9_]]/_/g` + AC_CACHE_CHECK([if C compiler supports $1], [$cachevar], + [# first try without, then with + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([], [1;])], + [old_cflags="$CFLAGS" + CFLAGS="$CFLAGS $cflags_warning_test_flags $1" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([], [1;])], + [eval $cachevar=yes], [eval $cachevar=no]) + CFLAGS="$old_cflags"], + [AC_MSG_ERROR(compiling simple test program with $CFLAGS failed)])]) + if eval test '"${'$cachevar'}"' = yes; then + WARN_CFLAGS="$WARN_CFLAGS $1" + fi + eval flag_supported='${'$cachevar'}' +])dnl +dnl +dnl Are additional flags needed to make unsupported warning options +dnl get reported as errors? +AC_DEFUN(CHECK_CC_WARNING_TEST_FLAGS,[dnl + cflags_warning_test_flags= + TRY_WARN_CC_FLAG_1(-Werror=unknown-warning-option) + if test $flag_supported = yes; then + cflags_warning_test_flags=-Werror=unknown-warning-option + fi +])dnl +dnl +AC_DEFUN(TRY_WARN_CC_FLAG,[dnl +AC_REQUIRE([CHECK_CC_WARNING_TEST_FLAGS])dnl +TRY_WARN_CC_FLAG_1($1)dnl +])dnl +dnl +AC_DEFUN(WITH_CC,[dnl +AC_REQUIRE([KRB5_AC_CHECK_FOR_CFLAGS])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_CXX])dnl +if test $ac_cv_c_compiler_gnu = yes ; then + HAVE_GCC=yes + else HAVE_GCC= +fi +AC_SUBST(HAVE_GCC) +AC_CACHE_CHECK([for GNU linker], krb5_cv_prog_gnu_ld, +[krb5_cv_prog_gnu_ld=no +if test "$GCC" = yes; then + if AC_TRY_COMMAND([$CC -Wl,-v 2>&1 dnl + | grep "GNU ld" > /dev/null]); then + krb5_cv_prog_gnu_ld=yes + fi +fi]) +AC_ARG_WITH([size-optimizations], +[ --with-size-optimizations enable a few optimizations to reduce code size + possibly at some run-time cost], +, +withval=no) +if test "$withval" = yes; then + AC_DEFINE(CONFIG_SMALL,1,[Define to reduce code size even if it means more cpu usage]) +fi +# -Wno-long-long, if needed, for k5-platform.h without inttypes.h etc. +extra_gcc_warn_opts="-Wall -Wcast-align -Wshadow" +# -Wmissing-prototypes +if test "$GCC" = yes ; then + # Putting this here means we get -Os after -O2, which works. + if test "$with_size_optimizations" = yes && test "x$krb5_ac_cflags_set" != xset; then + AC_MSG_NOTICE(adding -Os optimization option) + case "$CFLAGS" in + "-g -O2") CFLAGS="-g -Os" ;; + "-O2") CFLAGS="-Os" ;; + *) CFLAGS="$CFLAGS -Os" ;; + esac + fi + if test "x$krb5_ac_warn_cflags_set" = xset ; then + AC_MSG_NOTICE(not adding extra gcc warning flags because WARN_CFLAGS was set) + else + AC_MSG_NOTICE(adding extra warning flags for gcc) + WARN_CFLAGS="$WARN_CFLAGS $extra_gcc_warn_opts -Wmissing-prototypes" + if test "`uname -s`" = Darwin ; then + AC_MSG_NOTICE(skipping pedantic warnings on Darwin) + elif test "`uname -s`" = Linux ; then + AC_MSG_NOTICE(skipping pedantic warnings on Linux) + else + WARN_CFLAGS="$WARN_CFLAGS -pedantic" + fi + if test "$ac_cv_cxx_compiler_gnu" = yes; then + if test "x$krb5_ac_warn_cxxflags_set" = xset ; then + AC_MSG_NOTICE(not adding extra g++ warnings because WARN_CXXFLAGS was set) + else + AC_MSG_NOTICE(adding extra warning flags for g++) + WARN_CXXFLAGS="$WARN_CXXFLAGS $extra_gcc_warn_opts" + fi + fi + # Currently, G++ does not support -Wno-format-zero-length. + TRY_WARN_CC_FLAG(-Wno-format-zero-length) + # Other flags here may not be supported on some versions of + # gcc that people want to use. + for flag in overflow strict-overflow missing-format-attribute missing-prototypes return-type missing-braces parentheses switch unused-function unused-label unused-variable unused-value unknown-pragmas sign-compare newline-eof error=uninitialized no-maybe-uninitialized error=pointer-arith error=int-conversion error=incompatible-pointer-types error=discarded-qualifiers error=implicit-int ; do + TRY_WARN_CC_FLAG(-W$flag) + done + # old-style-definition? generates many, many warnings + # + # Warnings that we'd like to turn into errors on versions of gcc + # that support promoting only specific warnings to errors, but + # we'll take as warnings on older compilers. (If such a warning + # is added after the -Werror=foo feature, you can just put + # error=foo in the above list, and skip the test for the + # warning-only form.) At least in some versions, -Werror= doesn't + # seem to make the conditions actual errors, but still issues + # warnings; I guess we'll take what we can get. + # + # We're currently targeting C89+, not C99, so disallow some + # constructs. + for flag in declaration-after-statement ; do + TRY_WARN_CC_FLAG(-Werror=$flag) + if test "$flag_supported" = no; then + TRY_WARN_CC_FLAG(-W$flag) + fi + done + # We require function declarations now. + # + # In some compiler versions -- e.g., "gcc version 4.2.1 (Apple + # Inc. build 5664)" -- the -Werror- option works, but the -Werror= + # version doesn't cause implicitly declared functions to be + # flagged as errors. If neither works, -Wall implies + # -Wimplicit-function-declaration so don't bother. + TRY_WARN_CC_FLAG(-Werror-implicit-function-declaration) + if test "implicit-function-declaration_supported" = no; then + TRY_WARN_CC_FLAG(-Werror=implicit-function-declaration) + fi + # + fi + if test "`uname -s`" = Darwin ; then + # Someday this should be a feature test. + # One current (Jaguar = OS 10.2) problem: + # Archive library with foo.o undef sym X and bar.o common sym X, + # if foo.o is pulled in at link time, bar.o may not be, causing + # the linker to complain. + # Dynamic library problems too? + case "$CC $CFLAGS" in + *-fcommon*) ;; # why someone would do this, I don't know + *-fno-common*) ;; # okay, they're already doing the right thing + *) + AC_MSG_NOTICE(disabling the use of common storage on Darwin) + CFLAGS="$CFLAGS -fno-common" + ;; + esac + fi +else + if test "`uname -s`" = AIX ; then + # Using AIX but not GCC, assume native compiler. + # The native compiler appears not to give a nonzero exit + # status for certain classes of errors, like missing arguments + # in function calls. Let's try to fix that with -qhalt=e. + case "$CC $CFLAGS" in + *-qhalt=*) ;; + *) + CFLAGS="$CFLAGS -qhalt=e" + AC_MSG_NOTICE(adding -qhalt=e for better error reporting) + ;; + esac + # Also, the optimizer isn't turned on by default, which means + # the static inline functions get left in random object files, + # leading to references to pthread_mutex_lock from anything that + # includes k5-int.h whether it uses threads or not. + case "$CC $CFLAGS" in + *-O*) ;; + *) + CFLAGS="$CFLAGS -O" + AC_MSG_NOTICE(adding -O for inline thread-support function elimination) + ;; + esac + fi + if test "`uname -s`" = SunOS ; then + # Using Solaris but not GCC, assume Sunsoft compiler. + # We have some error-out-on-warning options available. + # Sunsoft 12 compiler defaults to -xc99=all, it appears, so "inline" + # works, but it also means that declaration-in-code warnings won't + # be issued. + # -v -fd -errwarn=E_DECLARATION_IN_CODE ... + if test "x$krb5_ac_warn_cflags_set" = xset ; then + AC_MSG_NOTICE(not adding extra warning flags because WARN_CFLAGS was set) + else + WARN_CFLAGS="-errtags=yes -errwarn=E_BAD_PTR_INT_COMBINATION,E_BAD_PTR_INT_COMB_ARG,E_PTR_TO_VOID_IN_ARITHMETIC,E_NO_IMPLICIT_DECL_ALLOWED,E_ATTRIBUTE_PARAM_UNDEFINED" + fi + if test "x$krb5_ac_warn_cxxflags_set" = xset ; then + AC_MSG_NOTICE(not adding extra warning flags because WARN_CXXFLAGS was set) + else + WARN_CXXFLAGS="-errtags=yes +w +w2 -xport64" + fi + fi +fi +AC_SUBST(WARN_CFLAGS) +AC_SUBST(WARN_CXXFLAGS) +])dnl +dnl +dnl K5_GEN_MAKEFILE([dir, [frags]]) +dnl +AC_DEFUN(K5_GEN_MAKEFILE,[dnl +ifelse($1, ,[_K5_GEN_MAKEFILE(.,$2)],[_K5_GEN_MAKEFILE($1,$2)]) +]) +dnl +dnl _K5_GEN_MAKEFILE(dir, [frags]) +dnl dir must be present in this case +dnl Note: Be careful in quoting. +dnl The m4_foreach_w generates the list of fragments to include +dnl or "" if $2 is empty +AC_DEFUN(_K5_GEN_MAKEFILE,[dnl +AC_CONFIG_FILES([$1/Makefile:$srcdir/]K5_TOPDIR[/config/pre.in:$1/Makefile.in:$1/deps:$srcdir/]K5_TOPDIR[/config/post.in]) +]) +dnl +dnl K5_GEN_FILE( ) +dnl +AC_DEFUN(K5_GEN_FILE,[AC_CONFIG_FILES($1)])dnl +dnl +dnl K5_AC_OUTPUT +dnl Note: Adds the variables to config.status for individual +dnl Makefile generation from config.status +AC_DEFUN(K5_AC_OUTPUT,[AC_OUTPUT])dnl +dnl +dnl V5_AC_OUTPUT_MAKEFILE +dnl +AC_DEFUN(V5_AC_OUTPUT_MAKEFILE, +[ifelse($1, , [_V5_AC_OUTPUT_MAKEFILE(.,$2)],[_V5_AC_OUTPUT_MAKEFILE($1,$2)])]) +dnl +define(_V5_AC_OUTPUT_MAKEFILE, +[ifelse($2, , ,AC_CONFIG_FILES($2)) +m4_foreach_w([DIR], [$1],dnl + [AC_CONFIG_FILES(DIR[/Makefile:$srcdir/]K5_TOPDIR[/config/pre.in:]DIR[/Makefile.in:]DIR[/deps:$srcdir/]K5_TOPDIR[/config/post.in])]) +K5_AC_OUTPUT])dnl +dnl +dnl +dnl KRB5_SOCKADDR_SA_LEN: define HAVE_SA_LEN if sockaddr contains the sa_len +dnl component +dnl +AC_DEFUN([KRB5_SOCKADDR_SA_LEN],[ dnl +AC_CHECK_MEMBER(struct sockaddr.sa_len, + AC_DEFINE(HAVE_SA_LEN,1,[Define if struct sockaddr contains sa_len]) +,,[#include +#include ])]) +dnl +dnl WITH_NETLIB +dnl +dnl +AC_DEFUN(WITH_NETLIB,[ +AC_ARG_WITH([netlib], + [AS_HELP_STRING([--with-netlib=LIBS], [use user defined resolver library])], +[ if test "$withval" = yes -o "$withval" = no ; then + AC_MSG_RESULT("netlib will link with C library resolver only") + else + LIBS="$LIBS $withval" + AC_MSG_RESULT("netlib will use \'$withval\'") + fi +],dnl +[AC_LIBRARY_NET] +)])dnl +dnl +dnl +AC_DEFUN(KRB5_AC_NEED_DAEMON, [ +KRB5_NEED_PROTO([#ifdef HAVE_UNISTD_H +#include +#endif],daemon,1)])dnl + +dnl +dnl KRB5_AC_NEED_LIBGEN --- check if libgen needs to be linked in for +dnl compile/step +dnl +dnl +AC_DEFUN(KRB5_AC_NEED_LIBGEN,[ +AC_REQUIRE([AC_PROG_CC])dnl +dnl +dnl regcomp is present but non-functional on Solaris 2.4 +dnl +AC_MSG_CHECKING(for working regcomp) +AC_CACHE_VAL(ac_cv_func_regcomp, +[AC_RUN_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + regex_t x; regmatch_t m;]], + [[return regcomp(&x,"pat.*",0) || regexec(&x,"pattern",1,&m,0);]])], + [ac_cv_func_regcomp=yes], [ac_cv_func_regcomp=no], + [AC_MSG_ERROR([Cannot test regcomp when cross compiling])])]) +AC_MSG_RESULT($ac_cv_func_regcomp) +test $ac_cv_func_regcomp = yes && AC_DEFINE(HAVE_REGCOMP,1,[Define if regcomp exists and functions]) +dnl +dnl Check for the compile and step functions - only if regcomp is not available +dnl +if test $ac_cv_func_regcomp = no; then + save_LIBS="$LIBS" + LIBS=-lgen +dnl this will fail if there's no compile/step in -lgen, or if there's +dnl no -lgen. This is fine. + AC_CHECK_FUNCS(compile step) + LIBS="$save_LIBS" +dnl +dnl Set GEN_LIB if necessary +dnl + AC_CHECK_LIB(gen, compile, GEN_LIB=-lgen, GEN_LIB=) + AC_SUBST(GEN_LIB) +fi +]) +dnl +dnl KRB5_AC_REGEX_FUNCS --- check for different regular expression +dnl support functions +dnl +AC_DEFUN(KRB5_AC_REGEX_FUNCS,[ +AC_CHECK_FUNCS(re_comp re_exec regexec) +AC_REQUIRE([KRB5_AC_NEED_LIBGEN])dnl +])dnl +dnl +dnl WITH_HESIOD +dnl +AC_DEFUN(WITH_HESIOD, +[AC_ARG_WITH(hesiod, + [AS_HELP_STRING([--with-hesiod[=path]], + [compile with hesiod support @<:@omitted@:>@])], + [hesiod=$with_hesiod], [with_hesiod=no]) +if test "$with_hesiod" != "no"; then + HESIOD_DEFS=-DHESIOD + AC_CHECK_LIB(resolv, res_send, res_lib=-lresolv) + if test "$hesiod" != "yes"; then + HESIOD_LIBS="-L${hesiod}/lib -lhesiod $res_lib" + else + HESIOD_LIBS="-lhesiod $res_lib" + fi +else + HESIOD_DEFS= + HESIOD_LIBS= +fi +AC_SUBST(HESIOD_DEFS) +AC_SUBST(HESIOD_LIBS)]) + + +dnl +dnl KRB5_BUILD_LIBRARY +dnl +dnl Pull in the necessary stuff to create the libraries. + +AC_DEFUN(KRB5_BUILD_LIBRARY, +[AC_REQUIRE([KRB5_LIB_AUX])dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_PROG_RANLIB])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +AC_CHECK_TOOL(AR, ar, false) +if test "$AR" = "false"; then + AC_MSG_ERROR([ar not found in PATH]) +fi +AC_CHECK_PROG(PERL, perl, perl, false) +if test "$ac_cv_prog_PERL" = "false"; then + AC_MSG_ERROR(Perl is now required for Kerberos builds.) +fi +AC_SUBST(LIBLIST) +AC_SUBST(LIBLINKS) +AC_SUBST(PLUGIN) +AC_SUBST(PLUGINLINK) +AC_SUBST(PLUGININST) +AC_SUBST(KDB5_PLUGIN_DEPLIBS) +AC_SUBST(KDB5_PLUGIN_LIBS) +AC_SUBST(MAKE_SHLIB_COMMAND) +AC_SUBST(SHLIB_RPATH_FLAGS) +AC_SUBST(SHLIB_EXPFLAGS) +AC_SUBST(SHLIB_EXPORT_FILE_DEP) +AC_SUBST(DYNOBJ_EXPDEPS) +AC_SUBST(DYNOBJ_EXPFLAGS) +AC_SUBST(INSTALL_SHLIB) +AC_SUBST(STLIBEXT) +AC_SUBST(SHLIBEXT) +AC_SUBST(SHLIBVEXT) +AC_SUBST(SHLIBSEXT) +AC_SUBST(DEPLIBEXT) +AC_SUBST(PFLIBEXT) +AC_SUBST(LIBINSTLIST) +AC_SUBST(DYNOBJEXT) +AC_SUBST(MAKE_DYNOBJ_COMMAND) +AC_SUBST(UNDEF_CHECK) +]) + +dnl +dnl KRB5_BUILD_LIBOBJS +dnl +dnl Pull in the necessary stuff to build library objects. + +AC_DEFUN(KRB5_BUILD_LIBOBJS, +[AC_REQUIRE([KRB5_LIB_AUX])dnl +AC_SUBST(OBJLISTS) +AC_SUBST(STOBJEXT) +AC_SUBST(SHOBJEXT) +AC_SUBST(PFOBJEXT) +AC_SUBST(PICFLAGS) +AC_SUBST(PROFFLAGS)]) + +dnl +dnl KRB5_BUILD_PROGRAM +dnl +dnl Set variables to build a program. + +AC_DEFUN(KRB5_BUILD_PROGRAM, +[AC_REQUIRE([KRB5_LIB_AUX])dnl +AC_REQUIRE([KRB5_AC_NEED_LIBGEN])dnl +AC_SUBST(CC_LINK) +AC_SUBST(CXX_LINK) +AC_SUBST(RPATH_FLAG) +AC_SUBST(PROG_RPATH_FLAGS) +AC_SUBST(DEPLIBEXT)]) + +dnl +dnl KRB5_RUN_FLAGS +dnl +dnl Set up environment for running dynamic executables out of build tree + +AC_DEFUN(KRB5_RUN_FLAGS, +[AC_REQUIRE([KRB5_LIB_AUX])dnl +KRB5_RUN_ENV="$RUN_ENV" +KRB5_RUN_VARS="$RUN_VARS" +AC_SUBST(KRB5_RUN_ENV) +AC_SUBST(KRB5_RUN_VARS)]) + +dnl +dnl KRB5_LIB_AUX +dnl +dnl Parse configure options related to library building. + +AC_DEFUN(KRB5_LIB_AUX, +[AC_REQUIRE([KRB5_LIB_PARAMS])dnl + +AC_ARG_ENABLE([static],,, [enable_static=no]) +AC_ARG_ENABLE([shared],,, [enable_shared=yes]) + +if test "x$enable_static" = "x$enable_shared"; then + AC_MSG_ERROR([--enable-static must be specified with --disable-shared]) +fi + +AC_ARG_ENABLE([rpath], + [AS_HELP_STRING([--disable-rpath],[suppress run path flags in link lines])], + [], [enable_rpath=yes]) + +if test "x$enable_rpath" != xyes ; then + # Unset the rpath flag values set by shlib.conf + SHLIB_RPATH_FLAGS= + RPATH_FLAG= + PROG_RPATH_FLAGS= +fi + +if test "$SHLIBEXT" = ".so-nobuild"; then + AC_MSG_ERROR([Shared libraries are not yet supported on this platform.]) +fi + +DEPLIBEXT=$SHLIBEXT + +if test "x$enable_static" = xyes; then + AC_MSG_NOTICE([using static libraries]) + LIBLIST='lib$(LIBBASE)$(STLIBEXT)' + LIBLINKS='$(TOPLIBD)/lib$(LIBBASE)$(STLIBEXT)' + PLUGIN='libkrb5_$(LIBBASE)$(STLIBEXT)' + PLUGINLINK='$(TOPLIBD)/libkrb5_$(LIBBASE)$(STLIBEXT)' + PLUGININST=install-static + OBJLISTS=OBJS.ST + LIBINSTLIST=install-static + DEPLIBEXT=$STLIBEXT + AC_DEFINE([STATIC_PLUGINS], 1, [Define for static plugin linkage]) + + KDB5_PLUGIN_DEPLIBS='$(TOPLIBD)/libkrb5_db2$(DEPLIBEXT)' + KDB5_PLUGIN_LIBS='-lkrb5_db2' + if test "x$OPENLDAP_PLUGIN" = xyes; then + KDB5_PLUGIN_DEBLIBS=$KDB5_PLUGIN_DEPLIBS' $(TOPLIBD)/libkrb5_ldap$(DEPLIBEXT) $(TOPLIBD)/libkdb_ldap$(DEPLIBEXT)' + KDB5_PLUGIN_LIBS=$KDB5_PLUGIN_LIBS' -lkrb5_kldap -lkdb_ldap $(LDAP_LIBS)' + fi + # kadm5srv_mit normally comes before kdb on the link line. Add it + # again after the KDB plugins, since they depend on it for XDR stuff. + KDB5_PLUGIN_DEPLIBS=$KDB5_PLUGIN_DEPLIBS' $(TOPLIBD)/libkadm5srv_mit$(DEPLIBEXT)' + KDB5_PLUGIN_LIBS=$KDB5_PLUGIN_LIBS' -lkadm5srv_mit' + + # avoid duplicate rules generation for AIX and such + SHLIBEXT=.so-nobuild + SHLIBVEXT=.so.v-nobuild + SHLIBSEXT=.so.s-nobuild +else + AC_MSG_NOTICE([using shared libraries]) + + # Clear some stuff in case of AIX, etc. + if test "$STLIBEXT" = "$SHLIBEXT" ; then + STLIBEXT=.a-nobuild + fi + case "$SHLIBSEXT" in + .so.s-nobuild) + LIBLIST='lib$(LIBBASE)$(SHLIBEXT)' + LIBLINKS='$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT)' + LIBINSTLIST="install-shared" + ;; + *) + LIBLIST='lib$(LIBBASE)$(SHLIBEXT) lib$(LIBBASE)$(SHLIBSEXT)' + LIBLINKS='$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBSEXT)' + LIBINSTLIST="install-shlib-soname" + ;; + esac + OBJLISTS="OBJS.SH" + PLUGIN='$(LIBBASE)$(DYNOBJEXT)' + PLUGINLINK='../$(PLUGIN)' + PLUGININST=install-plugin + KDB5_PLUGIN_DEPLIBS= + KDB5_PLUGIN_LIBS= +fi +CC_LINK="$CC_LINK_SHARED" +CXX_LINK="$CXX_LINK_SHARED" + +if test -z "$LIBLIST"; then + AC_MSG_ERROR([must enable one of shared or static libraries]) +fi + +# Check whether to build profiled libraries. +AC_ARG_ENABLE([profiled], +dnl [ --enable-profiled build profiled libraries @<:@disabled@:>@] +, +[if test "$enableval" = yes; then + AC_MSG_ERROR([Sorry, profiled libraries do not work in this release.]) +fi])]) + +dnl +dnl KRB5_LIB_PARAMS +dnl +dnl Determine parameters related to libraries, e.g. various extensions. + +AC_DEFUN(KRB5_LIB_PARAMS, +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +krb5_cv_host=$host +AC_SUBST(krb5_cv_host) +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([V5_SET_TOPDIR])dnl +. $ac_topdir/config/shlib.conf]) +dnl +dnl The following was written by jhawk@mit.edu +dnl +dnl AC_LIBRARY_NET: Id: net.m4,v 1.4 1997/10/25 20:49:53 jhawk Exp +dnl +dnl This test is for network applications that need socket() and +dnl gethostbyname() -ish functions. Under Solaris, those applications need to +dnl link with "-lsocket -lnsl". Under IRIX, they should *not* link with +dnl "-lsocket" because libsocket.a breaks a number of things (for instance: +dnl gethostbyname() under IRIX 5.2, and snoop sockets under most versions of +dnl IRIX). +dnl +dnl Unfortunately, many application developers are not aware of this, and +dnl mistakenly write tests that cause -lsocket to be used under IRIX. It is +dnl also easy to write tests that cause -lnsl to be used under operating +dnl systems where neither are necessary (or useful), such as SunOS 4.1.4, which +dnl uses -lnsl for TLI. +dnl +dnl This test exists so that every application developer does not test this in +dnl a different, and subtly broken fashion. +dnl +dnl It has been argued that this test should be broken up into two separate +dnl tests, one for the resolver libraries, and one for the libraries necessary +dnl for using Sockets API. Unfortunately, the two are carefully intertwined and +dnl allowing the autoconf user to use them independantly potentially results in +dnl unfortunate ordering dependencies -- as such, such component macros would +dnl have to carefully use indirection and be aware if the other components were +dnl executed. Since other autoconf macros do not go to this trouble, and almost +dnl no applications use sockets without the resolver, this complexity has not +dnl been implemented. +dnl +dnl The check for libresolv is in case you are attempting to link statically +dnl and happen to have a libresolv.a lying around (and no libnsl.a). +dnl +AC_DEFUN(AC_LIBRARY_NET, [ + # Most operating systems have gethostbyname() in the default searched + # libraries (i.e. libc): + AC_CHECK_FUNC(gethostbyname, , [ + # Some OSes (eg. Solaris) place it in libnsl: + AC_CHECK_LIB(nsl, gethostbyname, , [ + # Some strange OSes (SINIX) have it in libsocket: + AC_CHECK_LIB(socket, gethostbyname, , [ + # Unfortunately libsocket sometimes depends on libnsl. + # AC_CHECK_LIB's API is essentially broken so the following + # ugliness is necessary: + AC_CHECK_LIB(socket, gethostbyname, + LIBS="-lsocket -lnsl $LIBS", + [AC_CHECK_LIB(resolv, gethostbyname, + LIBS="-lresolv $LIBS" )], + -lnsl) + ]) + ]) + ]) + AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket, , + AC_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", , -lnsl))) + KRB5_AC_ENABLE_DNS + if test "$enable_dns" = yes ; then + # We assume that if libresolv exists we can link against it. + # This may get us a gethostby* that doesn't respect nsswitch. + AC_CHECK_LIB(resolv, main) + +_KRB5_AC_CHECK_RES_FUNCS(res_ninit res_nclose res_ndestroy res_nsearch dnl +ns_initparse ns_name_uncompress dn_skipname res_search) + if test $krb5_cv_func_res_nsearch = no \ + && test $krb5_cv_func_res_search = no; then + # Attempt to link with res_search(), in case it's not prototyped. + AC_CHECK_FUNC(res_search, + [AC_DEFINE(HAVE_RES_SEARCH, 1, + [Define to 1 if you have the `res_search' function])], + [AC_MSG_ERROR([cannot find res_nsearch or res_search])]) + fi + fi +]) +AC_DEFUN([_KRB5_AC_CHECK_RES_FUNCS], +[m4_foreach_w([AC_Func], [$1], + [AH_TEMPLATE(AS_TR_CPP(HAVE_[]AC_Func), + [Define to 1 if you have the `]AC_Func[' function.])])dnl +for krb5_func in $1; do +_KRB5_AC_CHECK_RES_FUNC($krb5_func) +done +]) +AC_DEFUN([_KRB5_AC_CHECK_RES_FUNC], [ +# Solaris 9 prototypes ns_name_uncompress() in arpa/nameser.h, but +# doesn't export it from libresolv.so, so we use extreme paranoia here +# and check both for the declaration and that we can link against the +# function. +AC_CACHE_CHECK([for $1], [krb5_cv_func_$1], +[AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + #include + #include + ]], + [[/* + * Use volatile, or else optimization can cause false positives. + */ + void (* volatile p)() = (void (*)())$1;]])], + [AS_VAR_SET(krb5_cv_func_$1, yes)], + [AS_VAR_SET(krb5_cv_func_$1, no)])]) +AS_IF([test AS_VAR_GET(krb5_cv_func_$1) = yes], + [AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$1]), 1, + [Define to 1 if you have the `$1' function])])[]dnl +]) +dnl +dnl +dnl KRB5_AC_ENABLE_DNS +dnl +AC_DEFUN(KRB5_AC_ENABLE_DNS, [ +enable_dns=yes + AC_ARG_ENABLE([dns-for-realm], +[ --enable-dns-for-realm enable DNS lookups of Kerberos realm names], , +[enable_dns_for_realm=no]) + if test "$enable_dns_for_realm" = yes; then + AC_DEFINE(KRB5_DNS_LOOKUP_REALM,1,[Define to enable DNS lookups of Kerberos realm names]) + fi + +AC_DEFINE(KRB5_DNS_LOOKUP, 1,[Define for DNS support of locating realms and KDCs]) + +]) +dnl +dnl +dnl Check if we need the prototype for a function - we give it a bogus +dnl prototype and if it complains - then a valid prototype exists on the +dnl system. +dnl +dnl KRB5_NEED_PROTO(includes, function, [bypass]) +dnl if $3 set, don't see if library defined. +dnl Useful for case where we will define in libkrb5 the function if need be +dnl but want to know if a prototype exists in either case on system. +dnl +AC_DEFUN([KRB5_NEED_PROTO], [ +ifelse([$3], ,[if test "x$ac_cv_func_$2" = xyes; then]) +AC_CACHE_CHECK([if $2 needs a prototype provided], krb5_cv_func_$2_noproto, +[AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[$1]], + [[#undef $2 + struct k5foo {int foo; } xx; + extern int $2 (struct k5foo*); + $2(&xx);]])], + [krb5_cv_func_$2_noproto=yes], [krb5_cv_func_$2_noproto=no])]) +if test $krb5_cv_func_$2_noproto = yes; then + AC_DEFINE([NEED_]translit($2, [a-z], [A-Z])[_PROTO], 1, dnl +[define if the system header files are missing prototype for $2()]) +fi +ifelse([$3], ,[fi]) +]) +dnl +dnl ============================================================= +dnl Internal function for testing for getpeername prototype +dnl +AC_DEFUN([KRB5_GETPEERNAME_ARGS],[ +AC_DEFINE([GETPEERNAME_ARG3_TYPE],GETSOCKNAME_ARG3_TYPE,[Type of getpeername second argument.]) +]) +dnl +dnl ============================================================= +dnl Internal function for testing for getsockname arguments +dnl +AC_DEFUN([TRY_GETSOCK_INT],[ +krb5_lib_var=`echo "$1 $2" | sed 'y% ./+-*%___p_p%'` +AC_MSG_CHECKING([if getsockname() takes arguments $1 and $2]) +AC_CACHE_VAL(krb5_cv_getsockname_proto_$krb5_lib_var, +[AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#include + #include + extern int getsockname(int, $1, $2);]])], + [eval "krb5_cv_getsockname_proto_$krb5_lib_var=yes"], + [eval "krb5_cv_getsockname_proto_$krb5_lib_var=no"])]) +if eval "test \"`echo '$krb5_cv_getsockname_proto_'$krb5_lib_var`\" = yes"; then + AC_MSG_RESULT(yes) + sock_set=yes; res1="$1"; res2="$2" +else + AC_MSG_RESULT(no) +fi +]) +dnl +dnl Determines the types of the second and third arguments to getsockname(). +dnl +AC_DEFUN([KRB5_GETSOCKNAME_ARGS],[ +sock_set=no +for sock_arg1 in "struct sockaddr *" "void *" +do + for sock_arg2 in "size_t *" "int *" "socklen_t *" + do + if test $sock_set = no; then + TRY_GETSOCK_INT($sock_arg1, $sock_arg2) + fi + done +done +if test "$sock_set" = no; then + AC_MSG_NOTICE(assuming struct sockaddr and socklen_t for getsockname args) + res1="struct sockaddr *" + res2="socklen_t *" +fi +res1=`echo "$res1" | tr -d '*' | sed -e 's/ *$//'` +res2=`echo "$res2" | tr -d '*' | sed -e 's/ *$//'` +AC_DEFINE_UNQUOTED([GETSOCKNAME_ARG3_TYPE],$res2,[Type of pointer target for argument 3 to getsockname]) +]) +dnl +dnl +AC_DEFUN([KRB5_AC_CHOOSE_ET],[ +AC_ARG_WITH([system-et], + [AS_HELP_STRING([--with-system-et], + [use system compile_et and -lcom_err @<:@default: build and install a local version@:>@])]) +AC_MSG_CHECKING(which version of com_err to use) +if test "x$with_system_et" = xyes ; then + # This will be changed to "intlsys" if textdomain support is present. + COM_ERR_VERSION=sys + AC_MSG_RESULT(system) +else + COM_ERR_VERSION=k5 + AC_MSG_RESULT(krb5) +fi +OLDLIBS="$LIBS" +COM_ERR_LIB=-lcom_err +if test $COM_ERR_VERSION = sys; then + PKG_CHECK_MODULES(COM_ERR, com_err, [have_com_err=yes], [have_com_err=no]) + if test "x$have_com_err = xyes"; then + COM_ERR_LIB="$COM_ERR_LIBS" + fi + LIBS="$LIBS $COM_ERR_LIB" + # check for various functions we need + AC_CHECK_LIB(com_err, add_error_table, :, AC_MSG_ERROR(cannot find add_error_table in com_err library)) + AC_CHECK_LIB(com_err, remove_error_table, :, AC_MSG_ERROR(cannot find remove_error_table in com_err library)) + # make sure compile_et provides "et_foo" name + cat >> conf$$e.et </dev/null 2>&1 ; then true ; else + AC_MSG_ERROR(execution failed) + fi + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include "conf$$e.h" + ]], + [[&et_foo_error_table;]])], + [], [AC_MSG_ERROR(cannot use et_foo_error_table)]) + # Anything else we need to test for? + rm -f conf$$e.c conf$$e.h + krb5_cv_compile_et_useful=yes + ]) + AC_CACHE_CHECK(whether compile_et supports --textdomain, + krb5_cv_compile_et_textdomain,[ + krb5_cv_compile_et_textdomain=no + if compile_et --textdomain=xyzw conf$$e.et >/dev/null 2>&1 ; then + if grep -q xyzw conf$$e.c; then + krb5_cv_compile_et_textdomain=yes + fi + fi + rm -f conf$$e.c conf$$e.h + ]) + if test "$krb5_cv_compile_et_textdomain" = yes; then + COM_ERR_VERSION=intlsys + fi + rm -f conf$$e.et +fi +AC_SUBST(COM_ERR_VERSION) +AC_SUBST(COM_ERR_LIB) +LIBS="$OLDLIBS" +if test "$COM_ERR_VERSION" = k5 -o "$COM_ERR_VERSION" = intlsys; then + AC_DEFINE(HAVE_COM_ERR_INTL,1, + [Define if com_err has compatible gettext support]) +fi +]) +AC_DEFUN([KRB5_AC_CHOOSE_SS],[ +AC_ARG_WITH(system-ss, + [AS_HELP_STRING([--with-system-ss], + [use system -lss and mk_cmds @<:@private version@:>@])]) +AC_ARG_VAR(SS_LIB,[system libraries for 'ss' package [-lss]]) +AC_MSG_CHECKING(which version of subsystem package to use) +if test "x$with_system_ss" = xyes ; then + SS_VERSION=sys + AC_MSG_RESULT(system) + # todo: check for various libraries we might need + # in the meantime... + test "x${SS_LIB+set}" = xset || SS_LIB=-lss + old_LIBS="$LIBS" + LIBS="$LIBS $SS_LIB" + AC_CACHE_CHECK(whether system ss package works, krb5_cv_system_ss_okay, + [AC_RUN_IFELSE( + [AC_LANG_SOURCE( + [[#include + int main(int argc, char *argv[]) { + if (argc == 42) { + int i, err; + i = ss_create_invocation("foo","foo","",0,&err); + ss_listen(i); + } + return 0; + }]])], + [krb5_cv_system_ss_okay=yes], [AC_MSG_ERROR(cannot run test program)], + [krb5_cv_system_ss_okay=assumed])]) + LIBS="$old_LIBS" + KRB5_NEED_PROTO([#include ],ss_execute_command,1) +else + SS_VERSION=k5 + AC_MSG_RESULT(krb5) +fi +AC_SUBST(SS_LIB) +AC_SUBST(SS_VERSION) +]) +dnl +AC_DEFUN([KRB5_AC_CHOOSE_DB],[ +AC_ARG_WITH(system-db, + [AS_HELP_STRING([--with-system-db], + [use system Berkeley db @<:@private version@:>@])]) +AC_ARG_VAR(DB_HEADER,[header file for system Berkeley db package [db.h]]) +AC_ARG_VAR(DB_LIB,[library for system Berkeley db package [-ldb]]) +if test "x$with_system_db" = xyes ; then + DB_VERSION=sys + # TODO: Do we have specific routines we should check for? + # How about known, easily recognizable bugs? + # We want to use bt_rseq in some cases, but no other version but + # ours has it right now. + # + # Okay, check the variables. + test "x${DB_HEADER+set}" = xset || DB_HEADER=db.h + test "x${DB_LIB+set}" = xset || DB_LIB=-ldb + # + if test "x${DB_HEADER}" = xdb.h ; then + DB_HEADER_VERSION=sys + else + DB_HEADER_VERSION=redirect + fi + KDB5_DB_LIB="$DB_LIB" +else + DB_VERSION=k5 + AC_DEFINE(HAVE_BT_RSEQ,1,[Define if bt_rseq is available, for recursive btree traversal.]) + DB_HEADER=db.h + DB_HEADER_VERSION=k5 + # libdb gets sucked into libkdb + KDB5_DB_LIB= + # needed for a couple of things that need libdb for its own sake + DB_LIB=-ldb +fi +AC_SUBST(DB_VERSION) +AC_SUBST(DB_HEADER) +AC_SUBST(DB_HEADER_VERSION) +AC_SUBST(DB_LIB) +AC_SUBST(KDB5_DB_LIB) +]) +dnl +dnl KRB5_AC_PRIOCNTL_HACK +dnl +dnl +AC_DEFUN([KRB5_AC_PRIOCNTL_HACK], +[AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_LANG_COMPILER_REQUIRE])dnl +AC_CACHE_CHECK([whether to use priocntl hack], [krb5_cv_priocntl_hack], +[case $krb5_cv_host in +*-*-solaris2.9*) + if test "$cross_compiling" = yes; then + krb5_cv_priocntl_hack=yes + else + # Solaris patch 117171-11 (sparc) or 117172-11 (x86) + # fixes the Solaris 9 bug where final pty output + # gets lost on close. + if showrev -p | $AWK 'BEGIN { e = 1 } +/Patch: 11717[[12]]/ { x = index[]([$]2, "-"); +if (substr[]([$]2, x + 1, length([$]2) - x) >= 11) +{ e = 0 } else { e = 1 } } +END { exit e; }'; then + krb5_cv_priocntl_hack=no + else + krb5_cv_priocntl_hack=yes + fi + fi + ;; +*) + krb5_cv_priocntl_hack=no + ;; +esac]) +if test "$krb5_cv_priocntl_hack" = yes; then + PRIOCNTL_HACK=1 +else + PRIOCNTL_HACK=0 +fi +AC_SUBST(PRIOCNTL_HACK)]) +dnl +dnl +dnl KRB5_AC_GCC_ATTRS +AC_DEFUN([KRB5_AC_GCC_ATTRS], +[AC_CACHE_CHECK([for constructor/destructor attribute support],krb5_cv_attr_constructor_destructor, +[rm -f conftest.1 conftest.2 +if test -r conftest.1 || test -r conftest.2 ; then + AC_MSG_ERROR(write error in local file system?) +fi +true > conftest.1 +true > conftest.2 +if test -r conftest.1 && test -r conftest.2 ; then true ; else + AC_MSG_ERROR(write error in local file system?) +fi +a=no +b=no +# blindly assume we have 'unlink' and unistd.h. +AC_RUN_IFELSE( + [AC_LANG_SOURCE( + [[#include + void foo1() __attribute__((constructor)); + void foo1() { unlink("conftest.1"); } + void foo2() __attribute__((destructor)); + void foo2() { unlink("conftest.2"); } + int main () { return 0; }]])], + [test -r conftest.1 || a=yes + test -r conftest.2 || b=yes], + [], [AC_MSG_ERROR(Cannot test for constructor/destructor support when cross compiling)]) +case $krb5_cv_host in +*-*-aix4.*) + # Under AIX 4.3.3, at least, shared library destructor functions + # appear to get executed in reverse link order (right to left), + # so that a library's destructor function may run after that of + # libraries it depends on, and may still have to access in the + # destructor. + # + # That counts as "not working", for me, but it's a much more + # complicated test case to set up. + b=no + ;; +esac +krb5_cv_attr_constructor_destructor="$a,$b" +]) +# Okay, krb5_cv_... should be set now. +case $krb5_cv_attr_constructor_destructor in + yes,*) + AC_DEFINE(CONSTRUCTOR_ATTR_WORKS,1,[Define if __attribute__((constructor)) works]) ;; +esac +case $krb5_cv_attr_constructor_destructor in + *,yes) + AC_DEFINE(DESTRUCTOR_ATTR_WORKS,1,[Define if __attribute__((destructor)) works]) ;; +esac +dnl End of attributes we care about right now. +]) +dnl +dnl +dnl KRB5_AC_PRAGMA_WEAK_REF +AC_DEFUN([KRB5_AC_PRAGMA_WEAK_REF], +[AC_CACHE_CHECK([whether pragma weak references are supported], +krb5_cv_pragma_weak_ref, +[AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#pragma weak flurbl + extern int flurbl(void);]], + [[if (&flurbl != 0) return flurbl();]])], + [krb5_cv_pragma_weak_ref=yes], [krb5_cv_pragma_weak_ref=no])]) +if test $krb5_cv_pragma_weak_ref = yes ; then + AC_DEFINE(HAVE_PRAGMA_WEAK_REF,1,[Define if #pragma weak references work]) +fi]) +dnl +dnl +m4_include(config/ac-archive/ax_pthread.m4) +m4_include(config/ac-archive/ax_recursive_eval.m4) +m4_include(config/pkg.m4) +dnl +dnl +dnl +dnl --with-ldap=value +dnl +AC_DEFUN(WITH_LDAP,[ +AC_ARG_WITH([ldap], +[AS_HELP_STRING([--with-ldap], [compile OpenLDAP database backend module])], +[case "$withval" in + OPENLDAP) with_ldap=yes ;; + yes | no) ;; + *) AC_MSG_ERROR(Invalid option value --with-ldap="$withval") ;; +esac], with_ldap=no)dnl + +if test "$with_ldap" = yes; then + AC_MSG_NOTICE(enabling OpenLDAP database backend module support) + OPENLDAP_PLUGIN=yes +fi +])dnl diff --git a/krb5-1.21.3/src/appl/Makefile.in b/krb5-1.21.3/src/appl/Makefile.in new file mode 100644 index 00000000..32fe175c --- /dev/null +++ b/krb5-1.21.3/src/appl/Makefile.in @@ -0,0 +1,5 @@ +mydir=appl +BUILDTOP=$(REL).. + +SUBDIRS= sample simple user_user gss-sample +WINSUBDIRS= gss-sample diff --git a/krb5-1.21.3/src/appl/deps b/krb5-1.21.3/src/appl/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/appl/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/appl/gss-sample/Makefile.in b/krb5-1.21.3/src/appl/gss-sample/Makefile.in new file mode 100644 index 00000000..35d808d0 --- /dev/null +++ b/krb5-1.21.3/src/appl/gss-sample/Makefile.in @@ -0,0 +1,50 @@ +mydir=appl$(S)gss-sample +BUILDTOP=$(REL)..$(S).. +DEFINES = -DUSE_AUTOCONF_H -DGSSAPI_V2 + +SRCS= $(srcdir)/gss-client.c $(srcdir)/gss-misc.c $(srcdir)/gss-server.c + +OBJS= gss-client.o gss-misc.o gss-server.o + +all-unix: gss-server gss-client + +##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc +##WIN32##RCFLAGS=$(CPPFLAGS) -I$(top_srcdir) -D_WIN32 -DRES_ONLY + +##WIN32##GSSCLIENT=$(OUTPRE)gss-client.exe +##WIN32##GSSSERVER=$(OUTPRE)gss-server.exe + +##WIN32##CLIENTRES=$(GSSCLIENT:.exe=.res) +##WIN32##SERVERRES=$(GSSSERVER:.exe=.res) + +##WIN32##$(CLIENTRES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DGSS_CLIENT_APP -fo $@ -r $** +##WIN32##$(SERVERRES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DGSS_SERVER_APP -fo $@ -r $** + + +##WIN32##all-windows: $(OUTPRE)gss-server.exe $(OUTPRE)gss-client.exe + +gss-server: gss-server.o gss-misc.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o gss-server gss-server.o gss-misc.o $(GSS_LIBS) $(KRB5_BASE_LIBS) + +gss-client: gss-client.o gss-misc.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o gss-client gss-client.o gss-misc.o $(GSS_LIBS) $(KRB5_BASE_LIBS) + +##WIN32##$(GSSSERVER): $(OUTPRE)gss-server.obj $(OUTPRE)gss-misc.obj $(GLIB) $(KLIB) $(SERVERRES) +##WIN32## link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib +##WIN32## $(_VC_MANIFEST_EMBED_EXE) + +##WIN32##$(GSSCLIENT): $(OUTPRE)gss-client.obj $(OUTPRE)gss-misc.obj $(GLIB) $(KLIB) $(CLIENTRES) +##WIN32## link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib +##WIN32## $(_VC_MANIFEST_EMBED_EXE) + +clean-unix:: + $(RM) gss-server gss-client + +check-pytests: + $(RUNPYTEST) $(srcdir)/t_gss_sample.py $(PYTESTFLAGS) + +install-unix: + $(INSTALL_PROGRAM) gss-client $(DESTDIR)$(CLIENT_BINDIR)/gss-client + $(INSTALL_PROGRAM) gss-server $(DESTDIR)$(SERVER_BINDIR)/gss-server diff --git a/krb5-1.21.3/src/appl/gss-sample/README b/krb5-1.21.3/src/appl/gss-sample/README new file mode 100644 index 00000000..c207aba8 --- /dev/null +++ b/krb5-1.21.3/src/appl/gss-sample/README @@ -0,0 +1,165 @@ +# Copyright 1993 by OpenVision Technologies, Inc. +# +# Permission to use, copy, modify, distribute, and sell this software +# and its documentation for any purpose is hereby granted without fee, +# provided that the above copyright notice appears in all copies and +# that both that copyright notice and this permission notice appear in +# supporting documentation, and that the name of OpenVision not be used +# in advertising or publicity pertaining to distribution of the software +# without specific, written prior permission. OpenVision makes no +# representations about the suitability of this software for any +# purpose. It is provided "as is" without express or implied warranty. +# +# OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +This directory contains a sample GSS-API client and server +application. In addition to serving as an example of GSS-API +programming, this application is also intended to be a tool for +testing the performance of GSS-API implementations. + +Each time the client is invoked, it performs one or more exchanges +with the server. Each exchange with the server consists primarily of +the following steps: + + 1. A TCP/IP connection is established. + + 2. (optional, on by default) The client and server establish a + GSS-API context, and the server prints the identify of the + client. + + / 3. The client sends a message to the server. The message may + / be plaintext, cryptographically "signed" but not encrypted, + | or encrypted (default). + | +0 or | 4. The server decrypts the message (if necessary), verifies +more | its signature (if there is one) and prints it. +times| + | 5. The server sends either a signature block (the default) or an + | empty token back to the client to acknowledge the message. + \ + \ 6. If the server sent a signature block, the client verifies + it and prints a message indicating that it was verified. + + 7. The client sends an empty block to the server to tell it + that the exchange is finished. + + 8. The client and server close the TCP/IP connection and + destroy the GSS-API context. + +The client also supports the -v1 flag which uses an older exchange +format compatible with previous releases of Kerberos and with samples +shipped in the Microsoft SDK. + +The server's command line usage is + + gss-server [-port port] [-verbose] [-once] [-inetd] [-export] + [-logfile file] service_name + +where service_name is a GSS-API service name of the form +"service@host" (or just "service", in which case the local host name +is used). The command-line options have the following meanings: + +-port The TCP port on which to accept connections. Default is 4444. + +-once Tells the server to exit after a single exchange, rather than + persisting. + +-inetd Tells the server that it is running out of inetd, so it should + interact with the client on stdin rather than binding to a + network port. Implies "-once". + +-export Tells the server to test the gss_export_sec_context function + after establishing a context with a client. + +-logfile + The file to which the server should append its output, rather + than sending it to stdout. + +The client's command line usage is + + gss-client [-port port] [-mech mechanism] [-d] [-f] [-q] + [-seq] [-noreplay] [-nomutual] [-dce] + [-ccount count] [-mcount count] [-na] [-nw] [-nx] [-nm] + host service_name msg + +where host is the host running the server, service_name is the service +name that the server will establish connections as (if you don't +specify the host name in the service name when running gss-server, and +it's running on a different machine from gss-client, make sure to +specify the server's host name in the service name you specify to +gss-client!) and msg is the message. The command-line options have +the following meanings: + +-port The TCP port to which to connect. Default is 4444. + +-mech The OID of the GSS-API mechanism to use. + +-d Tells the client to delegate credentials to the server. For + the Kerberos GSS-API mechanism, this means that a forwardable + TGT will be sent to the server, which will put it in its + credential cache (you must have acquired your tickets with + "kinit -f" for this to work). + +-seq Tells the client to enforce ordered message delivery via + sequencing. + +-noreplay Tells the client to disable the use of replay + detection. + +-dce Tells the client to request DCE-style authentication. + +-nomutual Tells the client to disable the use of mutual authentication. + +-f Tells the client that the "msg" argument is actually the name + of a file whose contents should be used as the message. + +-q Tells the client to be quiet, i.e., to only print error + messages. + +-ccount Specifies how many sessions the client should initiate with + the server (the "connection count"). + +-mcount Specifies how many times the message should be sent to the + server in each session (the "message count"). + +-na Tells the client not to do any authentication with the + server. Implies "-nw", "-nx" and "-nm". + +-nw Tells the client not to "wrap" messages. Implies "-nx". + +-nx Tells the client not to encrypt messages. + +-nm Tells the client not to ask the server to send back a + cryptographic checksum ("MIC"). + +To run the server on a host, you need to make sure that the principal +corresponding to service_name is in the default keytab on the server +host, and that the gss-server process can read the keytab. For +example, the service name "host@server" corresponds to the Kerberos +principal "host/server.domain.com@REALM". + +This sample application uses the following GSS-API functions: + + gss_accept_sec_context gss_inquire_names_for_mech + gss_acquire_cred gss_oid_to_str + gss_delete_sec_context gss_release_buffer + gss_display_name gss_release_cred + gss_display_status gss_release_name + gss_export_sec_context gss_release_oid + gss_get_mic gss_release_oid_set + gss_import_name gss_str_to_oid + gss_import_sec_context gss_unwrap + gss_init_sec_context gss_verify_mic + gss_inquire_context gss_wrap + +This application was originally written by Barry Jaspan of OpenVision +Technologies, Inc. It was updated significantly by Jonathan Kamens of +OpenVision Technologies, Inc. + +$Id$ diff --git a/krb5-1.21.3/src/appl/gss-sample/deps b/krb5-1.21.3/src/appl/gss-sample/deps new file mode 100644 index 00000000..8d306a05 --- /dev/null +++ b/krb5-1.21.3/src/appl/gss-sample/deps @@ -0,0 +1,16 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)gss-client.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/gssapi/gssapi_generic.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/port-sockets.h gss-client.c gss-misc.h +$(OUTPRE)gss-misc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \ + gss-misc.c gss-misc.h +$(OUTPRE)gss-server.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/gssapi/gssapi_generic.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/port-sockets.h gss-misc.h gss-server.c diff --git a/krb5-1.21.3/src/appl/gss-sample/gss-client.c b/krb5-1.21.3/src/appl/gss-sample/gss-client.c new file mode 100644 index 00000000..6e2aa336 --- /dev/null +++ b/krb5-1.21.3/src/appl/gss-sample/gss-client.c @@ -0,0 +1,921 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1994 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (C) 2003, 2004, 2005 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include "gss-misc.h" +#include "port-sockets.h" + +static int verbose = 1; +static int spnego = 0; +static gss_OID_desc gss_spnego_mechanism_oid_desc = +{6, (void *)"\x2b\x06\x01\x05\x05\x02"}; + +static void +usage() +{ + fprintf(stderr, "Usage: gss-client [-port port] [-mech mechanism] " + "[-spnego] [-d]\n"); + fprintf(stderr, " [-seq] [-noreplay] [-nomutual] [-user user] " + "[-pass pw]"); +#ifdef _WIN32 + fprintf(stderr, " [-threads num]"); +#endif + fprintf(stderr, "\n"); + fprintf(stderr, " [-f] [-q] [-ccount count] [-mcount count]\n"); + fprintf(stderr, " [-v1] [-na] [-nw] [-nx] [-nm] host service msg\n"); + exit(1); +} + +/* + * Function: connect_to_server + * + * Purpose: Opens a TCP connection to the name host and port. + * + * Arguments: + * + * host (r) the target host name + * port (r) the target port, in host byte order + * + * Returns: the established socket file descriptor, or -1 on failure + * + * Effects: + * + * The host name is resolved with gethostbyname(), and the socket is + * opened and connected. If an error occurs, an error message is + * displayed and -1 is returned. + */ +static int +connect_to_server(char *host, u_short port) +{ + struct sockaddr_in saddr; + struct hostent *hp; + int s; + +#ifdef _WIN32 + WSADATA wsadata; + int wsastartuperror = WSAStartup(0x202, &wsadata); + if (wsastartuperror) { + fprintf(stderr, "WSAStartup error: %x\n", wsastartuperror); + return -1; + } +#endif + + if ((hp = gethostbyname(host)) == NULL) { + fprintf(stderr, "Unknown host: %s\n", host); + return -1; + } + + saddr.sin_family = hp->h_addrtype; + memcpy(&saddr.sin_addr, hp->h_addr, sizeof(saddr.sin_addr)); + saddr.sin_port = htons(port); + + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("creating socket"); + return -1; + } + if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) { + perror("connecting to server"); + (void) closesocket(s); + return -1; + } + return s; +} + +/* + * Function: client_establish_context + * + * Purpose: establishes a GSS-API context with a specified service and + * returns the context handle + * + * Arguments: + * + * s (r) an established TCP connection to the service + * service_name(r) the ASCII service name of the service + * gss_flags (r) GSS-API delegation flag (if any) + * auth_flag (r) whether to actually do authentication + * v1_format (r) whether the v1 sample protocol should be used + * oid (r) OID of the mechanism to use + * context (w) the established GSS-API context + * ret_flags (w) the returned flags from init_sec_context + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * service_name is imported as a GSS-API name and a GSS-API context is + * established with the corresponding service; the service should be + * listening on the TCP connection s. The default GSS-API mechanism + * is used, and mutual authentication and replay detection are + * requested. + * + * If successful, the context handle is returned in context. If + * unsuccessful, the GSS-API error messages are displayed on stderr + * and -1 is returned. + */ +static int +client_establish_context(int s, char *service_name, OM_uint32 gss_flags, + int auth_flag, int v1_format, gss_OID oid, + char *username, char *password, + gss_ctx_id_t *gss_context, OM_uint32 *ret_flags) +{ + if (auth_flag) { + gss_buffer_desc send_tok, recv_tok, *token_ptr; + gss_name_t target_name; + OM_uint32 maj_stat, min_stat, init_sec_min_stat; + int token_flags; + gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; + gss_name_t gss_username = GSS_C_NO_NAME; + gss_OID_set_desc mechs, *mechsp = GSS_C_NO_OID_SET; + + if (spnego) { + mechs.elements = &gss_spnego_mechanism_oid_desc; + mechs.count = 1; + mechsp = &mechs; + } else if (oid != GSS_C_NO_OID) { + mechs.elements = oid; + mechs.count = 1; + mechsp = &mechs; + } else { + mechs.elements = NULL; + mechs.count = 0; + } + + if (username != NULL) { + send_tok.value = username; + send_tok.length = strlen(username); + + maj_stat = gss_import_name(&min_stat, &send_tok, + (gss_OID) gss_nt_user_name, + &gss_username); + if (maj_stat != GSS_S_COMPLETE) { + display_status("parsing client name", maj_stat, min_stat); + return -1; + } + } + + if (password != NULL) { + gss_buffer_desc pwbuf; + + pwbuf.value = password; + pwbuf.length = strlen(password); + + maj_stat = gss_acquire_cred_with_password(&min_stat, + gss_username, + &pwbuf, 0, + mechsp, GSS_C_INITIATE, + &cred, NULL, NULL); + } else if (gss_username != GSS_C_NO_NAME) { + maj_stat = gss_acquire_cred(&min_stat, + gss_username, 0, + mechsp, GSS_C_INITIATE, + &cred, NULL, NULL); + } else + maj_stat = GSS_S_COMPLETE; + if (maj_stat != GSS_S_COMPLETE) { + display_status("acquiring creds", maj_stat, min_stat); + gss_release_name(&min_stat, &gss_username); + return -1; + } + if (spnego && oid != GSS_C_NO_OID) { + gss_OID_set_desc neg_mechs; + + neg_mechs.elements = oid; + neg_mechs.count = 1; + + maj_stat = gss_set_neg_mechs(&min_stat, cred, &neg_mechs); + if (maj_stat != GSS_S_COMPLETE) { + display_status("setting neg mechs", maj_stat, min_stat); + gss_release_name(&min_stat, &gss_username); + gss_release_cred(&min_stat, &cred); + return -1; + } + } + gss_release_name(&min_stat, &gss_username); + + /* + * Import the name into target_name. Use send_tok to save + * local variable space. + */ + send_tok.value = service_name; + send_tok.length = strlen(service_name); + maj_stat = gss_import_name(&min_stat, &send_tok, + (gss_OID) gss_nt_service_name, + &target_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("parsing name", maj_stat, min_stat); + return -1; + } + + if (!v1_format) { + if (send_token(s, TOKEN_NOOP | TOKEN_CONTEXT_NEXT, empty_token) < + 0) { + (void) gss_release_name(&min_stat, &target_name); + return -1; + } + } + + /* + * Perform the context-establishement loop. + * + * On each pass through the loop, token_ptr points to the token + * to send to the server (or GSS_C_NO_BUFFER on the first pass). + * Every generated token is stored in send_tok which is then + * transmitted to the server; every received token is stored in + * recv_tok, which token_ptr is then set to, to be processed by + * the next call to gss_init_sec_context. + * + * GSS-API guarantees that send_tok's length will be non-zero + * if and only if the server is expecting another token from us, + * and that gss_init_sec_context returns GSS_S_CONTINUE_NEEDED if + * and only if the server has another token to send us. + */ + + token_ptr = GSS_C_NO_BUFFER; + *gss_context = GSS_C_NO_CONTEXT; + + do { + maj_stat = gss_init_sec_context(&init_sec_min_stat, + cred, gss_context, + target_name, mechs.elements, + gss_flags, 0, + NULL, /* channel bindings */ + token_ptr, NULL, /* mech type */ + &send_tok, ret_flags, + NULL); /* time_rec */ + + if (token_ptr != GSS_C_NO_BUFFER) + free(recv_tok.value); + + if (send_tok.length != 0) { + if (verbose) + printf("Sending init_sec_context token (size=%d)...", + (int) send_tok.length); + if (send_token(s, v1_format ? 0 : TOKEN_CONTEXT, &send_tok) < + 0) { + (void) gss_release_buffer(&min_stat, &send_tok); + (void) gss_release_name(&min_stat, &target_name); + return -1; + } + } + (void) gss_release_buffer(&min_stat, &send_tok); + + if (maj_stat != GSS_S_COMPLETE + && maj_stat != GSS_S_CONTINUE_NEEDED) { + display_status("initializing context", maj_stat, + init_sec_min_stat); + (void) gss_release_name(&min_stat, &target_name); + (void) gss_release_cred(&min_stat, &cred); + if (*gss_context != GSS_C_NO_CONTEXT) + gss_delete_sec_context(&min_stat, gss_context, + GSS_C_NO_BUFFER); + return -1; + } + + if (maj_stat == GSS_S_CONTINUE_NEEDED) { + if (verbose) + printf("continue needed..."); + if (recv_token(s, &token_flags, &recv_tok) < 0) { + (void) gss_release_name(&min_stat, &target_name); + return -1; + } + token_ptr = &recv_tok; + } + if (verbose) + printf("\n"); + } while (maj_stat == GSS_S_CONTINUE_NEEDED); + + (void) gss_release_cred(&min_stat, &cred); + (void) gss_release_name(&min_stat, &target_name); + } else { + if (send_token(s, TOKEN_NOOP, empty_token) < 0) + return -1; + } + + return 0; +} + +static void +read_file(file_name, in_buf) + char *file_name; + gss_buffer_t in_buf; +{ + int fd, count; + struct stat stat_buf; + + if ((fd = open(file_name, O_RDONLY, 0)) < 0) { + perror("open"); + fprintf(stderr, "Couldn't open file %s\n", file_name); + exit(1); + } + if (fstat(fd, &stat_buf) < 0) { + perror("fstat"); + exit(1); + } + in_buf->length = stat_buf.st_size; + + if (in_buf->length == 0) { + in_buf->value = NULL; + return; + } + + if ((in_buf->value = malloc(in_buf->length)) == 0) { + fprintf(stderr, "Couldn't allocate %d byte buffer for reading file\n", + (int) in_buf->length); + exit(1); + } + + /* this code used to check for incomplete reads, but you can't get + * an incomplete read on any file for which fstat() is meaningful */ + + count = read(fd, in_buf->value, in_buf->length); + if (count < 0) { + perror("read"); + exit(1); + } + if (count < (int)in_buf->length) + fprintf(stderr, "Warning, only read in %d bytes, expected %d\n", + count, (int) in_buf->length); +} + +/* + * Function: call_server + * + * Purpose: Call the "sign" service. + * + * Arguments: + * + * host (r) the host providing the service + * port (r) the port to connect to on host + * service_name (r) the GSS-API service name to authenticate to + * gss_flags (r) GSS-API delegation flag (if any) + * auth_flag (r) whether to do authentication + * wrap_flag (r) whether to do message wrapping at all + * encrypt_flag (r) whether to do encryption while wrapping + * mic_flag (r) whether to request a MIC from the server + * msg (r) the message to have "signed" + * use_file (r) whether to treat msg as an input file name + * mcount (r) the number of times to send the message + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * call_server opens a TCP connection to and establishes a + * GSS-API context with service_name over the connection. It then + * seals msg in a GSS-API token with gss_wrap, sends it to the server, + * reads back a GSS-API signature block for msg from the server, and + * verifies it with gss_verify. -1 is returned if any step fails, + * otherwise 0 is returned. */ +static int +call_server(host, port, oid, service_name, gss_flags, auth_flag, + wrap_flag, encrypt_flag, mic_flag, v1_format, msg, use_file, + mcount, username, password) + char *host; + u_short port; + gss_OID oid; + char *service_name; + OM_uint32 gss_flags; + int auth_flag, wrap_flag, encrypt_flag, mic_flag; + int v1_format; + char *msg; + int use_file; + int mcount; + char *username; + char *password; +{ + gss_ctx_id_t context = GSS_C_NO_CONTEXT; + gss_buffer_desc in_buf, out_buf; + int s, state; + OM_uint32 ret_flags; + OM_uint32 maj_stat, min_stat; + gss_name_t src_name, targ_name; + gss_buffer_desc sname, tname; + OM_uint32 lifetime; + gss_OID mechanism, name_type; + int is_local; + OM_uint32 context_flags; + int is_open; + gss_qop_t qop_state; + gss_OID_set mech_names; + gss_buffer_desc oid_name; + size_t i; + int token_flags; + + /* Open connection */ + if ((s = connect_to_server(host, port)) < 0) + return -1; + + /* Establish context */ + if (client_establish_context(s, service_name, gss_flags, auth_flag, + v1_format, oid, username, password, + &context, &ret_flags) < 0) { + (void) closesocket(s); + return -1; + } + + if (auth_flag && verbose) { + /* display the flags */ + display_ctx_flags(ret_flags); + + /* Get context information */ + maj_stat = gss_inquire_context(&min_stat, context, + &src_name, &targ_name, &lifetime, + &mechanism, &context_flags, + &is_local, &is_open); + if (maj_stat != GSS_S_COMPLETE) { + display_status("inquiring context", maj_stat, min_stat); + return -1; + } + + maj_stat = gss_display_name(&min_stat, src_name, &sname, &name_type); + if (maj_stat != GSS_S_COMPLETE) { + display_status("displaying source name", maj_stat, min_stat); + return -1; + } + maj_stat = gss_display_name(&min_stat, targ_name, &tname, + (gss_OID *) NULL); + if (maj_stat != GSS_S_COMPLETE) { + display_status("displaying target name", maj_stat, min_stat); + return -1; + } + printf("\"%.*s\" to \"%.*s\", lifetime %d, flags %x, %s, %s\n", + (int) sname.length, (char *) sname.value, + (int) tname.length, (char *) tname.value, lifetime, + context_flags, + (is_local) ? "locally initiated" : "remotely initiated", + (is_open) ? "open" : "closed"); + + (void) gss_release_name(&min_stat, &src_name); + (void) gss_release_name(&min_stat, &targ_name); + (void) gss_release_buffer(&min_stat, &sname); + (void) gss_release_buffer(&min_stat, &tname); + + maj_stat = gss_oid_to_str(&min_stat, name_type, &oid_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("converting oid->string", maj_stat, min_stat); + return -1; + } + printf("Name type of source name is %.*s.\n", + (int) oid_name.length, (char *) oid_name.value); + (void) gss_release_buffer(&min_stat, &oid_name); + + /* Now get the names supported by the mechanism */ + maj_stat = gss_inquire_names_for_mech(&min_stat, + mechanism, &mech_names); + if (maj_stat != GSS_S_COMPLETE) { + display_status("inquiring mech names", maj_stat, min_stat); + return -1; + } + + maj_stat = gss_oid_to_str(&min_stat, mechanism, &oid_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("converting oid->string", maj_stat, min_stat); + return -1; + } + printf("Mechanism %.*s supports %d names\n", + (int) oid_name.length, (char *) oid_name.value, + (int) mech_names->count); + (void) gss_release_buffer(&min_stat, &oid_name); + + for (i = 0; i < mech_names->count; i++) { + maj_stat = gss_oid_to_str(&min_stat, + &mech_names->elements[i], &oid_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("converting oid->string", maj_stat, min_stat); + return -1; + } + printf(" %d: %.*s\n", (int) i, + (int) oid_name.length, (char *) oid_name.value); + + (void) gss_release_buffer(&min_stat, &oid_name); + } + (void) gss_release_oid_set(&min_stat, &mech_names); + } + + if (use_file) { + read_file(msg, &in_buf); + } else { + /* Seal the message */ + in_buf.value = msg; + in_buf.length = strlen((char *)in_buf.value); + } + + for (i = 0; i < (size_t)mcount; i++) { + if (wrap_flag) { + maj_stat = + gss_wrap(&min_stat, context, encrypt_flag, GSS_C_QOP_DEFAULT, + &in_buf, &state, &out_buf); + if (maj_stat != GSS_S_COMPLETE) { + display_status("wrapping message", maj_stat, min_stat); + (void) closesocket(s); + (void) gss_delete_sec_context(&min_stat, &context, + GSS_C_NO_BUFFER); + return -1; + } else if (encrypt_flag && !state) { + fprintf(stderr, "Warning! Message not encrypted.\n"); + } + } else { + out_buf = in_buf; + } + + /* Send to server */ + if (send_token(s, (v1_format ? 0 + : (TOKEN_DATA | + (wrap_flag ? TOKEN_WRAPPED : 0) | + (encrypt_flag ? TOKEN_ENCRYPTED : 0) | + (mic_flag ? TOKEN_SEND_MIC : 0))), + &out_buf) < 0) { + (void) closesocket(s); + (void) gss_delete_sec_context(&min_stat, &context, + GSS_C_NO_BUFFER); + return -1; + } + if (out_buf.value != in_buf.value) + (void) gss_release_buffer(&min_stat, &out_buf); + + /* Read signature block into out_buf */ + if (recv_token(s, &token_flags, &out_buf) < 0) { + (void) closesocket(s); + (void) gss_delete_sec_context(&min_stat, &context, + GSS_C_NO_BUFFER); + return -1; + } + + if (mic_flag) { + /* Verify signature block */ + maj_stat = gss_verify_mic(&min_stat, context, &in_buf, + &out_buf, &qop_state); + if (maj_stat != GSS_S_COMPLETE) { + display_status("verifying signature", maj_stat, min_stat); + (void) closesocket(s); + (void) gss_delete_sec_context(&min_stat, &context, + GSS_C_NO_BUFFER); + return -1; + } + + if (verbose) + printf("Signature verified.\n"); + } else { + if (verbose) + printf("Response received.\n"); + } + + free(out_buf.value); + } + + if (use_file) + free(in_buf.value); + + /* Send NOOP */ + if (!v1_format) + (void) send_token(s, TOKEN_NOOP, empty_token); + + if (auth_flag) { + /* Delete context */ + maj_stat = gss_delete_sec_context(&min_stat, &context, &out_buf); + if (maj_stat != GSS_S_COMPLETE) { + display_status("deleting context", maj_stat, min_stat); + (void) closesocket(s); + (void) gss_delete_sec_context(&min_stat, &context, + GSS_C_NO_BUFFER); + return -1; + } + + (void) gss_release_buffer(&min_stat, &out_buf); + } + + (void) closesocket(s); + + return 0; +} + +static void +parse_oid(char *mechanism, gss_OID * oid) +{ + char *mechstr = 0; + gss_buffer_desc tok; + OM_uint32 maj_stat, min_stat; + size_t i, mechlen = strlen(mechanism); + + if (isdigit((int) mechanism[0])) { + mechstr = malloc(mechlen + 5); + if (!mechstr) { + fprintf(stderr, "Couldn't allocate mechanism scratch!\n"); + return; + } + mechstr[0] = '{'; + mechstr[1] = ' '; + for (i = 0; i < mechlen; i++) + mechstr[i + 2] = (mechanism[i] == '.') ? ' ' : mechanism[i]; + mechstr[mechlen + 2] = ' '; + mechstr[mechlen + 3] = ' '; + mechstr[mechlen + 4] = '\0'; + tok.value = mechstr; + } else + tok.value = mechanism; + tok.length = strlen(tok.value); + maj_stat = gss_str_to_oid(&min_stat, &tok, oid); + if (maj_stat != GSS_S_COMPLETE) { + display_status("str_to_oid", maj_stat, min_stat); + return; + } + if (mechstr) + free(mechstr); +} + +static int max_threads = 1; + +#ifdef _WIN32 +static thread_count = 0; +static HANDLE hMutex = NULL; +static HANDLE hEvent = NULL; + +void +InitHandles(void) +{ + hMutex = CreateMutex(NULL, FALSE, NULL); + hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); +} + +void +CleanupHandles(void) +{ + CloseHandle(hMutex); + CloseHandle(hEvent); +} + +BOOL +WaitAndIncrementThreadCounter(void) +{ + for (;;) { + if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) { + if (thread_count < max_threads) { + thread_count++; + ReleaseMutex(hMutex); + return TRUE; + } else { + ReleaseMutex(hMutex); + + if (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0) { + continue; + } else { + return FALSE; + } + } + } else { + return FALSE; + } + } +} + +BOOL +DecrementAndSignalThreadCounter(void) +{ + if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) { + if (thread_count == max_threads) + ResetEvent(hEvent); + thread_count--; + ReleaseMutex(hMutex); + return TRUE; + } else { + return FALSE; + } +} +#endif + +static char *service_name, *server_host, *msg; +static char *mechanism = 0; +static u_short port = 4444; +static int use_file = 0; +static OM_uint32 gss_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG; +static OM_uint32 min_stat; +static gss_OID oid = GSS_C_NULL_OID; +static int mcount = 1, ccount = 1; +static int auth_flag, wrap_flag, encrypt_flag, mic_flag, v1_format; +static char *username = NULL; +static char *password = NULL; + +static void +worker_bee(void *unused) +{ + if (call_server(server_host, port, oid, service_name, + gss_flags, auth_flag, wrap_flag, encrypt_flag, mic_flag, + v1_format, msg, use_file, mcount, username, password) < 0) + exit(1); + +#ifdef _WIN32 + if (max_threads > 1) + DecrementAndSignalThreadCounter(); +#endif +} + +int +main(argc, argv) + int argc; + char **argv; +{ + int i; + + display_file = stdout; + auth_flag = wrap_flag = encrypt_flag = mic_flag = 1; + v1_format = 0; + + /* Parse arguments. */ + argc--; + argv++; + while (argc) { + if (strcmp(*argv, "-port") == 0) { + argc--; + argv++; + if (!argc) + usage(); + port = atoi(*argv); + } else if (strcmp(*argv, "-mech") == 0) { + argc--; + argv++; + if (!argc) + usage(); + mechanism = *argv; + } else if (strcmp(*argv, "-user") == 0) { + argc--; + argv++; + if (!argc) + usage(); + username = *argv; + } else if (strcmp(*argv, "-pass") == 0) { + argc--; + argv++; + if (!argc) + usage(); + password = *argv; + } else if (strcmp(*argv, "-iakerb") == 0) { + mechanism = "{ 1 3 6 1 5 2 5 }"; + } else if (strcmp(*argv, "-spnego") == 0) { + spnego = 1; + } else if (strcmp(*argv, "-krb5") == 0) { + mechanism = "{ 1 2 840 113554 1 2 2 }"; +#ifdef _WIN32 + } else if (strcmp(*argv, "-threads") == 0) { + argc--; + argv++; + if (!argc) + usage(); + max_threads = atoi(*argv); +#endif + } else if (strcmp(*argv, "-dce") == 0) { + gss_flags |= GSS_C_DCE_STYLE; + } else if (strcmp(*argv, "-d") == 0) { + gss_flags |= GSS_C_DELEG_FLAG; + } else if (strcmp(*argv, "-seq") == 0) { + gss_flags |= GSS_C_SEQUENCE_FLAG; + } else if (strcmp(*argv, "-noreplay") == 0) { + gss_flags &= ~GSS_C_REPLAY_FLAG; + } else if (strcmp(*argv, "-nomutual") == 0) { + gss_flags &= ~GSS_C_MUTUAL_FLAG; + } else if (strcmp(*argv, "-f") == 0) { + use_file = 1; + } else if (strcmp(*argv, "-q") == 0) { + verbose = 0; + } else if (strcmp(*argv, "-ccount") == 0) { + argc--; + argv++; + if (!argc) + usage(); + ccount = atoi(*argv); + if (ccount <= 0) + usage(); + } else if (strcmp(*argv, "-mcount") == 0) { + argc--; + argv++; + if (!argc) + usage(); + mcount = atoi(*argv); + if (mcount < 0) + usage(); + } else if (strcmp(*argv, "-na") == 0) { + auth_flag = wrap_flag = encrypt_flag = mic_flag = 0; + } else if (strcmp(*argv, "-nw") == 0) { + wrap_flag = 0; + } else if (strcmp(*argv, "-nx") == 0) { + encrypt_flag = 0; + } else if (strcmp(*argv, "-nm") == 0) { + mic_flag = 0; + } else if (strcmp(*argv, "-v1") == 0) { + v1_format = 1; + } else + break; + argc--; + argv++; + } + if (argc != 3) + usage(); + +#ifdef _WIN32 + if (max_threads < 1) { + fprintf(stderr, "warning: there must be at least one thread\n"); + max_threads = 1; + } +#endif + + server_host = *argv++; + service_name = *argv++; + msg = *argv++; + + if (mechanism) + parse_oid(mechanism, &oid); + + if (max_threads == 1) { + for (i = 0; i < ccount; i++) { + worker_bee(0); + } + } else { +#ifdef _WIN32 + for (i = 0; i < ccount; i++) { + if (WaitAndIncrementThreadCounter()) { + uintptr_t handle = _beginthread(worker_bee, 0, (void *) 0); + if (handle == (uintptr_t) - 1) { + exit(1); + } + } else { + exit(1); + } + } +#else + /* boom */ + assert(max_threads == 1); +#endif + } + + if (oid != GSS_C_NULL_OID) + (void) gss_release_oid(&min_stat, &oid); + +#ifdef _WIN32 + CleanupHandles(); +#endif + + return 0; +} diff --git a/krb5-1.21.3/src/appl/gss-sample/gss-misc.c b/krb5-1.21.3/src/appl/gss-sample/gss-misc.c new file mode 100644 index 00000000..1d051edf --- /dev/null +++ b/krb5-1.21.3/src/appl/gss-sample/gss-misc.c @@ -0,0 +1,425 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1994 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (C) 2003, 2004 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include + +#include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#endif +#include + +#ifdef HAVE_UNISTD_H +#include +#endif +#include + +/* need struct timeval */ +#ifdef HAVE_SYS_TIME_H +#include +#else +#include +#endif + +#include +#include "gss-misc.h" + +#ifdef HAVE_STDLIB_H +#include +#else +extern char *malloc(); +#endif + +FILE *display_file; + +gss_buffer_desc empty_token_buf = { 0, (void *) "" }; +gss_buffer_t empty_token = &empty_token_buf; + +static void display_status_1(char *m, OM_uint32 code, int type); + +static int +write_all(int fildes, const void *data, unsigned int nbyte) +{ + int ret; + const char *ptr, *buf = data; + + for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) { + ret = send(fildes, ptr, nbyte, 0); + if (ret < 0) { + if (errno == EINTR) + continue; + return (ret); + } else if (ret == 0) { + return (ptr - buf); + } + } + + return (ptr - buf); +} + +static int +read_all(int fildes, void *data, unsigned int nbyte) +{ + int ret; + char *ptr, *buf = data; + fd_set rfds; + struct timeval tv; + + FD_ZERO(&rfds); + FD_SET(fildes, &rfds); + tv.tv_sec = 300; + tv.tv_usec = 0; + + for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) { + if (select(FD_SETSIZE, &rfds, NULL, NULL, &tv) <= 0 + || !FD_ISSET(fildes, &rfds)) + return (ptr - buf); + ret = recv(fildes, ptr, nbyte, 0); + if (ret < 0) { + if (errno == EINTR) + continue; + return (ret); + } else if (ret == 0) { + return (ptr - buf); + } + } + + return (ptr - buf); +} + +/* + * Function: send_token + * + * Purpose: Writes a token to a file descriptor. + * + * Arguments: + * + * s (r) an open file descriptor + * flags (r) the flags to write + * tok (r) the token to write + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * If the flags are non-null, send_token writes the token flags (a + * single byte, even though they're passed in in an integer). Next, + * the token length (as a network long) and then the token data are + * written to the file descriptor s. It returns 0 on success, and -1 + * if an error occurs or if it could not write all the data. + */ +int +send_token(s, flags, tok) + int s; + int flags; + gss_buffer_t tok; +{ + int ret; + unsigned char char_flags = (unsigned char) flags; + unsigned char lenbuf[4]; + + if (char_flags) { + ret = write_all(s, (char *) &char_flags, 1); + if (ret != 1) { + perror("sending token flags"); + return -1; + } + } + if (tok->length > 0xffffffffUL) + abort(); + lenbuf[0] = (tok->length >> 24) & 0xff; + lenbuf[1] = (tok->length >> 16) & 0xff; + lenbuf[2] = (tok->length >> 8) & 0xff; + lenbuf[3] = tok->length & 0xff; + + ret = write_all(s, lenbuf, 4); + if (ret < 0) { + perror("sending token length"); + return -1; + } else if (ret != 4) { + if (display_file) + fprintf(display_file, + "sending token length: %d of %d bytes written\n", ret, 4); + return -1; + } + + ret = write_all(s, tok->value, tok->length); + if (ret < 0) { + perror("sending token data"); + return -1; + } else if ((size_t)ret != tok->length) { + if (display_file) + fprintf(display_file, + "sending token data: %d of %d bytes written\n", + ret, (int) tok->length); + return -1; + } + + return 0; +} + +/* + * Function: recv_token + * + * Purpose: Reads a token from a file descriptor. + * + * Arguments: + * + * s (r) an open file descriptor + * flags (w) the read flags + * tok (w) the read token + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * recv_token reads the token flags (a single byte, even though + * they're stored into an integer, then reads the token length (as a + * network long), allocates memory to hold the data, and then reads + * the token data from the file descriptor s. It blocks to read the + * length and data, if necessary. On a successful return, the token + * should be freed with gss_release_buffer. It returns 0 on success, + * and -1 if an error occurs or if it could not read all the data. + */ +int +recv_token(s, flags, tok) + int s; + int *flags; + gss_buffer_t tok; +{ + int ret; + unsigned char char_flags; + unsigned char lenbuf[4]; + + ret = read_all(s, (char *) &char_flags, 1); + if (ret < 0) { + perror("reading token flags"); + return -1; + } else if (!ret) { + if (display_file) + fputs("reading token flags: 0 bytes read\n", display_file); + return -1; + } else { + *flags = (int) char_flags; + } + + if (char_flags == 0) { + lenbuf[0] = 0; + ret = read_all(s, &lenbuf[1], 3); + if (ret < 0) { + perror("reading token length"); + return -1; + } else if (ret != 3) { + if (display_file) + fprintf(display_file, + "reading token length: %d of %d bytes read\n", ret, 3); + return -1; + } + } else { + ret = read_all(s, lenbuf, 4); + if (ret < 0) { + perror("reading token length"); + return -1; + } else if (ret != 4) { + if (display_file) + fprintf(display_file, + "reading token length: %d of %d bytes read\n", ret, 4); + return -1; + } + } + + tok->length = ((lenbuf[0] << 24) + | (lenbuf[1] << 16) + | (lenbuf[2] << 8) + | lenbuf[3]); + tok->value = (char *) malloc(tok->length ? tok->length : 1); + if (tok->length && tok->value == NULL) { + if (display_file) + fprintf(display_file, "Out of memory allocating token data\n"); + return -1; + } + + ret = read_all(s, (char *) tok->value, tok->length); + if (ret < 0) { + perror("reading token data"); + free(tok->value); + return -1; + } else if ((size_t)ret != tok->length) { + fprintf(stderr, "sending token data: %d of %d bytes written\n", + ret, (int) tok->length); + free(tok->value); + return -1; + } + + return 0; +} + +static void +display_status_1(m, code, type) + char *m; + OM_uint32 code; + int type; +{ + OM_uint32 min_stat; + gss_buffer_desc msg; + OM_uint32 msg_ctx; + + msg_ctx = 0; + while (1) { + (void) gss_display_status(&min_stat, code, type, GSS_C_NULL_OID, + &msg_ctx, &msg); + if (display_file) + fprintf(display_file, "GSS-API error %s: %s\n", m, + (char *) msg.value); + (void) gss_release_buffer(&min_stat, &msg); + + if (!msg_ctx) + break; + } +} + +/* + * Function: display_status + * + * Purpose: displays GSS-API messages + * + * Arguments: + * + * msg a string to be displayed with the message + * maj_stat the GSS-API major status code + * min_stat the GSS-API minor status code + * + * Effects: + * + * The GSS-API messages associated with maj_stat and min_stat are + * displayed on stderr, each preceded by "GSS-API error : " and + * followed by a newline. + */ +void +display_status(msg, maj_stat, min_stat) + char *msg; + OM_uint32 maj_stat; + OM_uint32 min_stat; +{ + display_status_1(msg, maj_stat, GSS_C_GSS_CODE); + display_status_1(msg, min_stat, GSS_C_MECH_CODE); +} + +/* + * Function: display_ctx_flags + * + * Purpose: displays the flags returned by context initiation in + * a human-readable form + * + * Arguments: + * + * int ret_flags + * + * Effects: + * + * Strings corresponding to the context flags are printed on + * stdout, preceded by "context flag: " and followed by a newline + */ + +void +display_ctx_flags(flags) + OM_uint32 flags; +{ + if (flags & GSS_C_DELEG_FLAG) + fprintf(display_file, "context flag: GSS_C_DELEG_FLAG\n"); + if (flags & GSS_C_MUTUAL_FLAG) + fprintf(display_file, "context flag: GSS_C_MUTUAL_FLAG\n"); + if (flags & GSS_C_REPLAY_FLAG) + fprintf(display_file, "context flag: GSS_C_REPLAY_FLAG\n"); + if (flags & GSS_C_SEQUENCE_FLAG) + fprintf(display_file, "context flag: GSS_C_SEQUENCE_FLAG\n"); + if (flags & GSS_C_CONF_FLAG) + fprintf(display_file, "context flag: GSS_C_CONF_FLAG \n"); + if (flags & GSS_C_INTEG_FLAG) + fprintf(display_file, "context flag: GSS_C_INTEG_FLAG \n"); +} + +void +print_token(tok) + gss_buffer_t tok; +{ + unsigned int i; + unsigned char *p = tok->value; + + if (!display_file) + return; + for (i = 0; i < tok->length; i++, p++) { + fprintf(display_file, "%02x ", *p); + if ((i % 16) == 15) { + fprintf(display_file, "\n"); + } + } + fprintf(display_file, "\n"); + fflush(display_file); +} + +#ifdef _WIN32 +#include +#include + +int +gettimeofday(struct timeval *tv, void *ignore_tz) +{ + struct _timeb tb; + _tzset(); + _ftime(&tb); + if (tv) { + tv->tv_sec = tb.time; + tv->tv_usec = tb.millitm * 1000; + } + return 0; +} +#endif /* _WIN32 */ diff --git a/krb5-1.21.3/src/appl/gss-sample/gss-misc.h b/krb5-1.21.3/src/appl/gss-sample/gss-misc.h new file mode 100644 index 00000000..98bcc222 --- /dev/null +++ b/krb5-1.21.3/src/appl/gss-sample/gss-misc.h @@ -0,0 +1,56 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1994 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * $Id$ + */ + +#ifndef _GSSMISC_H_ +#define _GSSMISC_H_ + +#include +#include + +extern FILE *display_file; + +int send_token(int s, int flags, gss_buffer_t tok); +int recv_token(int s, int *flags, gss_buffer_t tok); +void display_status(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat); +void display_ctx_flags(OM_uint32 flags); +void print_token(gss_buffer_t tok); + +/* Token types */ +#define TOKEN_NOOP (1<<0) +#define TOKEN_CONTEXT (1<<1) +#define TOKEN_DATA (1<<2) +#define TOKEN_MIC (1<<3) + +/* Token flags */ +#define TOKEN_CONTEXT_NEXT (1<<4) +#define TOKEN_WRAPPED (1<<5) +#define TOKEN_ENCRYPTED (1<<6) +#define TOKEN_SEND_MIC (1<<7) + +extern gss_buffer_t empty_token; + +#endif diff --git a/krb5-1.21.3/src/appl/gss-sample/gss-server.c b/krb5-1.21.3/src/appl/gss-sample/gss-server.c new file mode 100644 index 00000000..9b6ce9ff --- /dev/null +++ b/krb5-1.21.3/src/appl/gss-sample/gss-server.c @@ -0,0 +1,912 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1994 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (C) 2004,2005 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#ifdef _WIN32 +#include +#include +#else +#include "port-sockets.h" +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +#include +#include +#include "gss-misc.h" + +#ifdef HAVE_STRING_H +#include +#else +#include +#endif + +static OM_uint32 +enumerateAttributes(OM_uint32 *minor, gss_name_t name, int noisy); +static OM_uint32 +showLocalIdentity(OM_uint32 *minor, gss_name_t name); + +static void +usage() +{ + fprintf(stderr, "Usage: gss-server [-port port] [-verbose] [-once]"); +#ifdef _WIN32 + fprintf(stderr, " [-threads num]"); +#endif + fprintf(stderr, "\n"); + fprintf(stderr, + " [-inetd] [-export] [-logfile file] [-keytab keytab]\n" + " service_name\n"); + exit(1); +} + +static FILE *logfile; + +int verbose = 0; + +/* + * Function: server_acquire_creds + * + * Purpose: imports a service name and acquires credentials for it + * + * Arguments: + * + * service_name (r) the ASCII service name + * mech (r) the desired mechanism (or GSS_C_NO_OID) + * server_creds (w) the GSS-API service credentials + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * The service name is imported with gss_import_name, and service + * credentials are acquired with gss_acquire_cred. If either operation + * fails, an error message is displayed and -1 is returned; otherwise, + * 0 is returned. If mech is given, credentials are acquired for the + * specified mechanism. + */ + +static int +server_acquire_creds(char *service_name, gss_OID mech, + gss_cred_id_t *server_creds) +{ + gss_buffer_desc name_buf; + gss_name_t server_name; + OM_uint32 maj_stat, min_stat; + gss_OID_set_desc mechlist; + gss_OID_set mechs = GSS_C_NO_OID_SET; + + name_buf.value = service_name; + name_buf.length = strlen(name_buf.value) + 1; + maj_stat = gss_import_name(&min_stat, &name_buf, + (gss_OID) gss_nt_service_name, &server_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("importing name", maj_stat, min_stat); + return -1; + } + + if (mech != GSS_C_NO_OID) { + mechlist.count = 1; + mechlist.elements = mech; + mechs = &mechlist; + } + maj_stat = gss_acquire_cred(&min_stat, server_name, 0, mechs, GSS_C_ACCEPT, + server_creds, NULL, NULL); + if (maj_stat != GSS_S_COMPLETE) { + display_status("acquiring credentials", maj_stat, min_stat); + return -1; + } + + (void) gss_release_name(&min_stat, &server_name); + + return 0; +} + +/* + * Function: server_establish_context + * + * Purpose: establishses a GSS-API context as a specified service with + * an incoming client, and returns the context handle and associated + * client name + * + * Arguments: + * + * s (r) an established TCP connection to the client + * service_creds (r) server credentials, from gss_acquire_cred + * context (w) the established GSS-API context + * client_name (w) the client's ASCII name + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * Any valid client request is accepted. If a context is established, + * its handle is returned in context and the client name is returned + * in client_name and 0 is returned. If unsuccessful, an error + * message is displayed and -1 is returned. + */ +static int +server_establish_context(int s, gss_cred_id_t server_creds, + gss_ctx_id_t *context, gss_buffer_t client_name, + OM_uint32 *ret_flags) +{ + gss_buffer_desc send_tok, recv_tok; + gss_name_t client; + gss_OID doid; + OM_uint32 maj_stat, min_stat, acc_sec_min_stat; + gss_buffer_desc oid_name; + int token_flags; + + if (recv_token(s, &token_flags, &recv_tok) < 0) + return -1; + + if (recv_tok.value) { + free(recv_tok.value); + recv_tok.value = NULL; + } + + if (!(token_flags & TOKEN_NOOP)) { + if (logfile) + fprintf(logfile, "Expected NOOP token, got %d token instead\n", + token_flags); + return -1; + } + + *context = GSS_C_NO_CONTEXT; + + if (token_flags & TOKEN_CONTEXT_NEXT) { + do { + if (recv_token(s, &token_flags, &recv_tok) < 0) + return -1; + + if (verbose && logfile) { + fprintf(logfile, "Received token (size=%d): \n", + (int) recv_tok.length); + print_token(&recv_tok); + } + + maj_stat = gss_accept_sec_context(&acc_sec_min_stat, context, + server_creds, &recv_tok, + GSS_C_NO_CHANNEL_BINDINGS, + &client, &doid, &send_tok, + ret_flags, + NULL, /* time_rec */ + NULL); /* del_cred_handle */ + + if (recv_tok.value) { + free(recv_tok.value); + recv_tok.value = NULL; + } + + if (send_tok.length != 0) { + if (verbose && logfile) { + fprintf(logfile, + "Sending accept_sec_context token (size=%d):\n", + (int) send_tok.length); + print_token(&send_tok); + } + if (send_token(s, TOKEN_CONTEXT, &send_tok) < 0) { + if (logfile) + fprintf(logfile, "failure sending token\n"); + return -1; + } + + (void) gss_release_buffer(&min_stat, &send_tok); + } + if (maj_stat != GSS_S_COMPLETE + && maj_stat != GSS_S_CONTINUE_NEEDED) { + display_status("accepting context", maj_stat, + acc_sec_min_stat); + if (*context != GSS_C_NO_CONTEXT) + gss_delete_sec_context(&min_stat, context, + GSS_C_NO_BUFFER); + return -1; + } + + if (verbose && logfile) { + if (maj_stat == GSS_S_CONTINUE_NEEDED) + fprintf(logfile, "continue needed...\n"); + else + fprintf(logfile, "\n"); + fflush(logfile); + } + } while (maj_stat == GSS_S_CONTINUE_NEEDED); + + /* display the flags */ + display_ctx_flags(*ret_flags); + + if (verbose && logfile) { + maj_stat = gss_oid_to_str(&min_stat, doid, &oid_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("converting oid->string", maj_stat, min_stat); + return -1; + } + fprintf(logfile, "Accepted connection using mechanism OID %.*s.\n", + (int) oid_name.length, (char *) oid_name.value); + (void) gss_release_buffer(&min_stat, &oid_name); + } + + maj_stat = gss_display_name(&min_stat, client, client_name, &doid); + if (maj_stat != GSS_S_COMPLETE) { + display_status("displaying name", maj_stat, min_stat); + return -1; + } + enumerateAttributes(&min_stat, client, TRUE); + showLocalIdentity(&min_stat, client); + maj_stat = gss_release_name(&min_stat, &client); + if (maj_stat != GSS_S_COMPLETE) { + display_status("releasing name", maj_stat, min_stat); + return -1; + } + } else { + client_name->length = *ret_flags = 0; + + if (logfile) + fprintf(logfile, "Accepted unauthenticated connection.\n"); + } + + return 0; +} + +/* + * Function: create_socket + * + * Purpose: Opens a listening TCP socket. + * + * Arguments: + * + * port (r) the port number on which to listen + * + * Returns: the listening socket file descriptor, or -1 on failure + * + * Effects: + * + * A listening socket on the specified port and created and returned. + * On error, an error message is displayed and -1 is returned. + */ +static int +create_socket(u_short port) +{ + struct sockaddr_in saddr; + int s; + int on = 1; + + saddr.sin_family = AF_INET; + saddr.sin_port = htons(port); + saddr.sin_addr.s_addr = INADDR_ANY; + + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("creating socket"); + return -1; + } + /* Let the socket be reused right away */ + (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); + if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) { + perror("binding socket"); + (void) closesocket(s); + return -1; + } + if (listen(s, 5) < 0) { + perror("listening on socket"); + (void) closesocket(s); + return -1; + } + return s; +} + +static float +timeval_subtract(struct timeval *tv1, struct timeval *tv2) +{ + return ((tv1->tv_sec - tv2->tv_sec) + + ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000); +} + +/* + * Yes, yes, this isn't the best place for doing this test. + * DO NOT REMOVE THIS UNTIL A BETTER TEST HAS BEEN WRITTEN, THOUGH. + * -TYT + */ +static int +test_import_export_context(gss_ctx_id_t *context) +{ + OM_uint32 min_stat, maj_stat; + gss_buffer_desc context_token, copied_token; + struct timeval tm1, tm2; + + /* + * Attempt to save and then restore the context. + */ + gettimeofday(&tm1, (struct timezone *) 0); + maj_stat = gss_export_sec_context(&min_stat, context, &context_token); + if (maj_stat != GSS_S_COMPLETE) { + display_status("exporting context", maj_stat, min_stat); + return 1; + } + gettimeofday(&tm2, (struct timezone *) 0); + if (verbose && logfile) + fprintf(logfile, "Exported context: %d bytes, %7.4f seconds\n", + (int) context_token.length, timeval_subtract(&tm2, &tm1)); + copied_token.length = context_token.length; + copied_token.value = malloc(context_token.length); + if (copied_token.value == 0) { + if (logfile) + fprintf(logfile, + "Couldn't allocate memory to copy context token.\n"); + return 1; + } + memcpy(copied_token.value, context_token.value, copied_token.length); + maj_stat = gss_import_sec_context(&min_stat, &copied_token, context); + if (maj_stat != GSS_S_COMPLETE) { + display_status("importing context", maj_stat, min_stat); + return 1; + } + free(copied_token.value); + gettimeofday(&tm1, (struct timezone *) 0); + if (verbose && logfile) + fprintf(logfile, "Importing context: %7.4f seconds\n", + timeval_subtract(&tm1, &tm2)); + (void) gss_release_buffer(&min_stat, &context_token); + return 0; +} + +/* + * Function: sign_server + * + * Purpose: Performs the "sign" service. + * + * Arguments: + * + * s (r) a TCP socket on which a connection has been + * accept()ed + * service_name (r) the ASCII name of the GSS-API service to + * establish a context as + * export (r) whether to test context exporting + * + * Returns: -1 on error + * + * Effects: + * + * sign_server establishes a context, and performs a single sign request. + * + * A sign request is a single GSS-API sealed token. The token is + * unsealed and a signature block, produced with gss_sign, is returned + * to the sender. The context is the destroyed and the connection + * closed. + * + * If any error occurs, -1 is returned. + */ +static int +sign_server(int s, gss_cred_id_t server_creds, int export) +{ + gss_buffer_desc client_name, recv_buf, unwrap_buf, mic_buf, *msg_buf, *send_buf; + gss_ctx_id_t context; + OM_uint32 maj_stat, min_stat; + int i, conf_state; + OM_uint32 ret_flags; + char *cp; + int token_flags; + int send_flags; + + /* Establish a context with the client */ + if (server_establish_context(s, server_creds, &context, + &client_name, &ret_flags) < 0) + return (-1); + + if (context == GSS_C_NO_CONTEXT) { + printf("Accepted unauthenticated connection.\n"); + } else { + printf("Accepted connection: \"%.*s\"\n", + (int) client_name.length, (char *) client_name.value); + (void) gss_release_buffer(&min_stat, &client_name); + + if (export) { + for (i = 0; i < 3; i++) + if (test_import_export_context(&context)) + return -1; + } + } + + do { + /* Receive the message token */ + if (recv_token(s, &token_flags, &recv_buf) < 0) + return (-1); + + if (token_flags & TOKEN_NOOP) { + if (logfile) + fprintf(logfile, "NOOP token\n"); + if (recv_buf.value) { + free(recv_buf.value); + recv_buf.value = 0; + } + break; + } + + if (verbose && logfile) { + fprintf(logfile, "Message token (flags=%d):\n", token_flags); + print_token(&recv_buf); + } + + if ((context == GSS_C_NO_CONTEXT) && + (token_flags & (TOKEN_WRAPPED | TOKEN_ENCRYPTED | TOKEN_SEND_MIC))) + { + if (logfile) + fprintf(logfile, + "Unauthenticated client requested authenticated services!\n"); + if (recv_buf.value) { + free(recv_buf.value); + recv_buf.value = 0; + } + return (-1); + } + + if (token_flags & TOKEN_WRAPPED) { + maj_stat = gss_unwrap(&min_stat, context, &recv_buf, &unwrap_buf, + &conf_state, (gss_qop_t *) NULL); + if (maj_stat != GSS_S_COMPLETE) { + display_status("unsealing message", maj_stat, min_stat); + if (recv_buf.value) { + free(recv_buf.value); + recv_buf.value = 0; + } + return (-1); + } else if (!conf_state && (token_flags & TOKEN_ENCRYPTED)) { + fprintf(stderr, "Warning! Message not encrypted.\n"); + } + + if (recv_buf.value) { + free(recv_buf.value); + recv_buf.value = 0; + } + msg_buf = &unwrap_buf; + } else { + unwrap_buf.value = NULL; + unwrap_buf.length = 0; + msg_buf = &recv_buf; + } + + if (logfile) { + fprintf(logfile, "Received message: "); + cp = msg_buf->value; + if ((isprint((int) cp[0]) || isspace((int) cp[0])) && + (isprint((int) cp[1]) || isspace((int) cp[1]))) { + fprintf(logfile, "\"%.*s\"\n", (int) msg_buf->length, + (char *) msg_buf->value); + } else { + fprintf(logfile, "\n"); + print_token(msg_buf); + } + } + + if (token_flags & TOKEN_SEND_MIC) { + /* Produce a signature block for the message */ + maj_stat = gss_get_mic(&min_stat, context, GSS_C_QOP_DEFAULT, + msg_buf, &mic_buf); + if (maj_stat != GSS_S_COMPLETE) { + display_status("signing message", maj_stat, min_stat); + return (-1); + } + send_flags = TOKEN_MIC; + send_buf = &mic_buf; + } else { + mic_buf.value = NULL; + mic_buf.length = 0; + send_flags = TOKEN_NOOP; + send_buf = empty_token; + } + if (recv_buf.value) { + free(recv_buf.value); + recv_buf.value = NULL; + } + if (unwrap_buf.value) { + gss_release_buffer(&min_stat, &unwrap_buf); + } + + /* Send the signature block or NOOP to the client */ + if (send_token(s, send_flags, send_buf) < 0) + return (-1); + + if (mic_buf.value) { + gss_release_buffer(&min_stat, &mic_buf); + } + } while (1 /* loop will break if NOOP received */ ); + + if (context != GSS_C_NO_CONTEXT) { + /* Delete context */ + maj_stat = gss_delete_sec_context(&min_stat, &context, NULL); + if (maj_stat != GSS_S_COMPLETE) { + display_status("deleting context", maj_stat, min_stat); + return (-1); + } + } + + if (logfile) + fflush(logfile); + + return (0); +} + +static int max_threads = 1; + +#ifdef _WIN32 +static thread_count = 0; +static HANDLE hMutex = NULL; +static HANDLE hEvent = NULL; + +void +InitHandles(void) +{ + hMutex = CreateMutex(NULL, FALSE, NULL); + hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); +} + +void +CleanupHandles(void) +{ + CloseHandle(hMutex); + CloseHandle(hEvent); +} + +BOOL +WaitAndIncrementThreadCounter(void) +{ + for (;;) { + if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) { + if (thread_count < max_threads) { + thread_count++; + ReleaseMutex(hMutex); + return TRUE; + } else { + ReleaseMutex(hMutex); + + if (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0) { + continue; + } else { + return FALSE; + } + } + } else { + return FALSE; + } + } +} + +BOOL +DecrementAndSignalThreadCounter(void) +{ + if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) { + if (thread_count == max_threads) + ResetEvent(hEvent); + thread_count--; + ReleaseMutex(hMutex); + return TRUE; + } else { + return FALSE; + } +} +#endif + +struct _work_plan +{ + int s; + gss_cred_id_t server_creds; + int export; +}; + +static void +worker_bee(void *param) +{ + struct _work_plan *work = (struct _work_plan *) param; + + /* this return value is not checked, because there's + * not really anything to do if it fails + */ + sign_server(work->s, work->server_creds, work->export); + closesocket(work->s); + free(work); + +#ifdef _WIN32 + if (max_threads > 1) + DecrementAndSignalThreadCounter(); +#endif +} + +int +main(int argc, char **argv) +{ + char *service_name; + gss_cred_id_t server_creds; + gss_OID mech = GSS_C_NO_OID; + OM_uint32 min_stat; + u_short port = 4444; + int once = 0; + int do_inetd = 0; + int export = 0; + + logfile = stdout; + display_file = stdout; + argc--; + argv++; + while (argc) { + if (strcmp(*argv, "-port") == 0) { + argc--; + argv++; + if (!argc) + usage(); + port = atoi(*argv); + } +#ifdef _WIN32 + else if (strcmp(*argv, "-threads") == 0) { + argc--; + argv++; + if (!argc) + usage(); + max_threads = atoi(*argv); + } +#endif + else if (strcmp(*argv, "-verbose") == 0) { + verbose = 1; + } else if (strcmp(*argv, "-once") == 0) { + once = 1; + } else if (strcmp(*argv, "-inetd") == 0) { + do_inetd = 1; + } else if (strcmp(*argv, "-export") == 0) { + export = 1; + } else if (strcmp(*argv, "-logfile") == 0) { + argc--; + argv++; + if (!argc) + usage(); + /* Gross hack, but it makes it unnecessary to add an + * extra argument to disable logging, and makes the code + * more efficient because it doesn't actually write data + * to /dev/null. */ + if (!strcmp(*argv, "/dev/null")) { + logfile = display_file = NULL; + } else { + logfile = fopen(*argv, "a"); + display_file = logfile; + if (!logfile) { + perror(*argv); + exit(1); + } + } + } else if (strcmp(*argv, "-keytab") == 0) { + argc--; + argv++; + if (!argc) + usage(); + if (krb5_gss_register_acceptor_identity(*argv)) { + fprintf(stderr, "failed to register keytab\n"); + exit(1); + } + } else if (strcmp(*argv, "-iakerb") == 0) { + mech = (gss_OID)gss_mech_iakerb; + } else + break; + argc--; + argv++; + } + if (argc != 1) + usage(); + + if ((*argv)[0] == '-') + usage(); + +#ifdef _WIN32 + if (max_threads < 1) { + fprintf(stderr, "warning: there must be at least one thread\n"); + max_threads = 1; + } + + if (max_threads > 1 && do_inetd) + fprintf(stderr, + "warning: one thread may be used in conjunction with inetd\n"); + + InitHandles(); +#endif + + service_name = *argv; + + if (server_acquire_creds(service_name, mech, &server_creds) < 0) + return -1; + + if (do_inetd) { + close(1); + close(2); + + sign_server(0, server_creds, export); + close(0); + } else { + int stmp; + + if ((stmp = create_socket(port)) >= 0) { + fprintf(stderr, "starting...\n"); + + do { + struct _work_plan *work = malloc(sizeof(struct _work_plan)); + + if (work == NULL) { + fprintf(stderr, "fatal error: out of memory"); + break; + } + + /* Accept a TCP connection */ + if ((work->s = accept(stmp, NULL, 0)) < 0) { + perror("accepting connection"); + free(work); + continue; + } + + work->server_creds = server_creds; + work->export = export; + + if (max_threads == 1) { + worker_bee((void *) work); + } +#ifdef _WIN32 + else { + if (WaitAndIncrementThreadCounter()) { + uintptr_t handle = + _beginthread(worker_bee, 0, (void *) work); + if (handle == (uintptr_t) - 1) { + closesocket(work->s); + free(work); + } + } else { + fprintf(stderr, + "fatal error incrementing thread counter"); + closesocket(work->s); + free(work); + break; + } + } +#endif + } while (!once); + + closesocket(stmp); + } + } + + (void) gss_release_cred(&min_stat, &server_creds); + +#ifdef _WIN32 + CleanupHandles(); +#endif + + return 0; +} + +static void +dumpAttribute(OM_uint32 *minor, + gss_name_t name, + gss_buffer_t attribute, + int noisy) +{ + OM_uint32 major, tmp; + gss_buffer_desc value; + gss_buffer_desc display_value; + int authenticated = 0; + int complete = 0; + int more = -1; + unsigned int i; + + while (more != 0) { + value.value = NULL; + display_value.value = NULL; + + major = gss_get_name_attribute(minor, name, attribute, &authenticated, + &complete, &value, &display_value, + &more); + if (GSS_ERROR(major)) { + display_status("gss_get_name_attribute", major, *minor); + break; + } + + printf("Attribute %.*s %s %s\n\n%.*s\n", + (int)attribute->length, (char *)attribute->value, + authenticated ? "Authenticated" : "", + complete ? "Complete" : "", + (int)display_value.length, (char *)display_value.value); + + if (noisy) { + for (i = 0; i < value.length; i++) { + if ((i % 32) == 0) + printf("\n"); + printf("%02x", ((char *)value.value)[i] & 0xFF); + } + printf("\n\n"); + } + + gss_release_buffer(&tmp, &value); + gss_release_buffer(&tmp, &display_value); + } +} + +static OM_uint32 +enumerateAttributes(OM_uint32 *minor, + gss_name_t name, + int noisy) +{ + OM_uint32 major, tmp; + int name_is_MN; + gss_OID mech = GSS_C_NO_OID; + gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET; + unsigned int i; + + major = gss_inquire_name(minor, name, &name_is_MN, &mech, &attrs); + if (GSS_ERROR(major)) { + display_status("gss_inquire_name", major, *minor); + return major; + } + + if (attrs != GSS_C_NO_BUFFER_SET) { + for (i = 0; i < attrs->count; i++) + dumpAttribute(minor, name, &attrs->elements[i], noisy); + } + + gss_release_oid(&tmp, &mech); + gss_release_buffer_set(&tmp, &attrs); + + return major; +} + +static OM_uint32 +showLocalIdentity(OM_uint32 *minor, gss_name_t name) +{ + OM_uint32 major; + gss_buffer_desc buf; + + major = gss_localname(minor, name, GSS_C_NO_OID, &buf); + if (major == GSS_S_COMPLETE) + printf("localname: %-*s\n", (int)buf.length, (char *)buf.value); + else if (major != GSS_S_UNAVAILABLE) + display_status("gss_localname", major, *minor); + gss_release_buffer(minor, &buf); + return major; +} diff --git a/krb5-1.21.3/src/appl/gss-sample/t_gss_sample.py b/krb5-1.21.3/src/appl/gss-sample/t_gss_sample.py new file mode 100755 index 00000000..36083591 --- /dev/null +++ b/krb5-1.21.3/src/appl/gss-sample/t_gss_sample.py @@ -0,0 +1,133 @@ +# Copyright (C) 2010 by the Massachusetts Institute of Technology. +# All rights reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +from k5test import * + +appdir = os.path.join(buildtop, 'appl', 'gss-sample') +gss_client = os.path.join(appdir, 'gss-client') +gss_server = os.path.join(appdir, 'gss-server') + +# Run a gss-server process and a gss-client process, with additional +# gss-client flags given by options and additional gss-server flags +# given by server_options. Return the output of gss-client. +def run_client_server(realm, options, server_options, **kwargs): + portstr = str(realm.server_port()) + server_args = [gss_server, '-export', '-port', portstr] + server_args += server_options + ['host'] + server = realm.start_server(server_args, 'starting...') + realm.run([gss_client, '-port', portstr] + options + + [hostname, 'host', 'testmsg'], **kwargs) + + seen1 = seen2 = False + while 'expected_code' not in kwargs and not (seen1 and seen2): + line = server.stdout.readline() + if line == '': + fail('gss-server process exited unexpectedly') + if line == 'Accepted connection: "user@KRBTEST.COM"\n': + seen1 = True + if line == 'Received message: "testmsg"\n': + seen2 = True + + stop_daemon(server) + +# Run a gss-server and gss-client process, and verify that gss-client +# displayed the expected output for a successful negotiation. +def server_client_test(realm, options, server_options): + run_client_server(realm, options, server_options, + expected_msg='Signature verified.') + +# Make up a filename to hold user's initial credentials. +def ccache_savefile(realm): + return os.path.join(realm.testdir, 'ccache.copy') + +# Move user's initial credentials into the save file. +def ccache_save(realm): + os.rename(realm.ccache, ccache_savefile(realm)) + +# Copy user's initial credentials from the save file into the ccache. +def ccache_restore(realm): + shutil.copyfile(ccache_savefile(realm), realm.ccache) + +# Perform a regular (TGS path) test of the server and client. +def tgs_test(realm, options, server_options=[]): + ccache_restore(realm) + server_client_test(realm, options, server_options) + realm.klist(realm.user_princ, realm.host_princ) + +# Perform a test of the server and client with initial credentials +# obtained through gss_acquire_cred_with_password(). +def pw_test(realm, options, server_options=[]): + if os.path.exists(realm.ccache): + os.remove(realm.ccache) + options = options + ['-user', realm.user_princ, '-pass', password('user')] + server_client_test(realm, options, server_options) + if os.path.exists(realm.ccache): + fail('gss_acquire_cred_with_password created ccache') + +# Perform a test using the wrong password, and make sure that failure +# occurs during the expected operation (gss_init_sec_context() for +# IAKERB, gss_aqcuire_cred_with_password() otherwise). +def wrong_pw_test(realm, options, server_options=[], iakerb=False): + options = options + ['-user', realm.user_princ, '-pass', 'wrongpw'] + failed_op = 'initializing context' if iakerb else 'acquiring creds' + msg = 'GSS-API error ' + failed_op + run_client_server(realm, options, server_options, expected_code=1, + expected_msg=msg) + +# Perform a test of the server and client with initial credentials +# obtained with the client keytab +def kt_test(realm, options, server_options=[]): + if os.path.exists(realm.ccache): + os.remove(realm.ccache) + server_client_test(realm, options, server_options) + realm.klist(realm.user_princ, realm.host_princ) + +for realm in multipass_realms(): + ccache_save(realm) + + mark('TGS') + tgs_test(realm, ['-krb5']) + tgs_test(realm, ['-spnego']) + tgs_test(realm, ['-iakerb'], ['-iakerb']) + # test default (i.e., krb5) mechanism with GSS_C_DCE_STYLE + tgs_test(realm, ['-dce']) + + mark('pw') + pw_test(realm, ['-krb5']) + pw_test(realm, ['-spnego']) + pw_test(realm, ['-iakerb'], ['-iakerb']) + pw_test(realm, ['-dce']) + + mark('wrong pw') + wrong_pw_test(realm, ['-krb5']) + wrong_pw_test(realm, ['-spnego']) + wrong_pw_test(realm, ['-iakerb'], ['-iakerb'], True) + wrong_pw_test(realm, ['-dce']) + + mark('client keytab') + realm.extract_keytab(realm.user_princ, realm.client_keytab) + kt_test(realm, ['-krb5']) + kt_test(realm, ['-spnego']) + kt_test(realm, ['-iakerb'], ['-iakerb']) + kt_test(realm, ['-dce']) + +success('GSS sample application') diff --git a/krb5-1.21.3/src/appl/sample/Makefile.in b/krb5-1.21.3/src/appl/sample/Makefile.in new file mode 100644 index 00000000..50caa864 --- /dev/null +++ b/krb5-1.21.3/src/appl/sample/Makefile.in @@ -0,0 +1,6 @@ +mydir=appl$(S)sample +SUBDIRS = sclient sserver +BUILDTOP=$(REL)..$(S).. + +check-pytests: + $(RUNPYTEST) $(srcdir)/t_sample.py $(PYTESTFLAGS) diff --git a/krb5-1.21.3/src/appl/sample/deps b/krb5-1.21.3/src/appl/sample/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/appl/sample/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/appl/sample/sample.h b/krb5-1.21.3/src/appl/sample/sample.h new file mode 100644 index 00000000..2fda2f43 --- /dev/null +++ b/krb5-1.21.3/src/appl/sample/sample.h @@ -0,0 +1,33 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* appl/sample/sample.h - Common declarations for sample client/server */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef KRB5_SAMPLE__ +#define KRB5_SAMPLE__ + +#define SAMPLE_SERVICE "sample" +#define SAMPLE_PORT "sample" +#define SAMPLE_VERSION "KRB5_sample_protocol_v1.0" + +#endif /* KRB5_SAMPLE__ */ diff --git a/krb5-1.21.3/src/appl/sample/sclient/Makefile.in b/krb5-1.21.3/src/appl/sample/sclient/Makefile.in new file mode 100644 index 00000000..b09cc090 --- /dev/null +++ b/krb5-1.21.3/src/appl/sample/sclient/Makefile.in @@ -0,0 +1,13 @@ +mydir=appl$(S)sample$(S)sclient +BUILDTOP=$(REL)..$(S)..$(S).. + +all: sclient + +sclient: sclient.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o sclient sclient.o $(KRB5_BASE_LIBS) + +clean: + $(RM) sclient.o sclient + +install: + $(INSTALL_PROGRAM) sclient ${DESTDIR}$(CLIENT_BINDIR)/sclient diff --git a/krb5-1.21.3/src/appl/sample/sclient/deps b/krb5-1.21.3/src/appl/sample/sclient/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/appl/sample/sclient/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/appl/sample/sclient/sclient.c b/krb5-1.21.3/src/appl/sample/sclient/sclient.c new file mode 100644 index 00000000..7ec8edd0 --- /dev/null +++ b/krb5-1.21.3/src/appl/sample/sclient/sclient.c @@ -0,0 +1,260 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* appl/sample/sclient/sclient.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * Sample Kerberos v5 client. + * + * Usage: sample_client hostname + */ + +#include "krb5.h" +#include "com_err.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include "fake-addrinfo.h" /* not everyone implements getaddrinfo yet */ + +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include + +#include "../sample.h" + +#ifndef GETSOCKNAME_ARG3_TYPE +#define GETSOCKNAME_ARG3_TYPE int +#endif + +static int +net_read(int fd, char *buf, int len) +{ + int cc, len2 = 0; + + do { + cc = SOCKET_READ((SOCKET)fd, buf, len); + if (cc < 0) { + if (SOCKET_ERRNO == SOCKET_EINTR) + continue; + + /* XXX this interface sucks! */ + errno = SOCKET_ERRNO; + + return(cc); /* errno is already set */ + } + else if (cc == 0) { + return(len2); + } else { + buf += cc; + len2 += cc; + len -= cc; + } + } while (len > 0); + return(len2); +} + +int +main(int argc, char *argv[]) +{ + struct addrinfo *ap, aihints, *apstart; + int aierr; + int sock; + krb5_context context; + krb5_data recv_data; + krb5_data cksum_data; + krb5_error_code retval; + krb5_ccache ccdef; + krb5_principal client, server; + krb5_error *err_ret; + krb5_ap_rep_enc_part *rep_ret; + krb5_auth_context auth_context = 0; + short xmitlen; + char *portstr; + char *service = SAMPLE_SERVICE; + + if (argc != 2 && argc != 3 && argc != 4) { + fprintf(stderr, "usage: %s [port] [service]\n",argv[0]); + exit(1); + } + + retval = krb5_init_context(&context); + if (retval) { + com_err(argv[0], retval, "while initializing krb5"); + exit(1); + } + + (void) signal(SIGPIPE, SIG_IGN); + + if (argc > 2) + portstr = argv[2]; + else + portstr = SAMPLE_PORT; + + memset(&aihints, 0, sizeof(aihints)); + aihints.ai_socktype = SOCK_STREAM; + aihints.ai_flags = AI_ADDRCONFIG; + aierr = getaddrinfo(argv[1], portstr, &aihints, &ap); + if (aierr) { + fprintf(stderr, "%s: error looking up host '%s' port '%s'/tcp: %s\n", + argv[0], argv[1], portstr, gai_strerror(aierr)); + exit(1); + } + if (ap == 0) { + /* Should never happen. */ + fprintf(stderr, "%s: error looking up host '%s' port '%s'/tcp: no addresses returned?\n", + argv[0], argv[1], portstr); + exit(1); + } + + if (argc > 3) { + service = argv[3]; + } + + retval = krb5_sname_to_principal(context, argv[1], service, + KRB5_NT_SRV_HST, &server); + if (retval) { + com_err(argv[0], retval, "while creating server name for host %s service %s", + argv[1], service); + exit(1); + } + + /* set up the address of the foreign socket for connect() */ + apstart = ap; /* For freeing later */ + for (sock = -1; ap && sock == -1; ap = ap->ai_next) { + char abuf[NI_MAXHOST], pbuf[NI_MAXSERV]; + char mbuf[NI_MAXHOST + NI_MAXSERV + 64]; + if (getnameinfo(ap->ai_addr, ap->ai_addrlen, abuf, sizeof(abuf), + pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) { + memset(abuf, 0, sizeof(abuf)); + memset(pbuf, 0, sizeof(pbuf)); + strncpy(abuf, "[error, cannot print address?]", + sizeof(abuf)-1); + strncpy(pbuf, "[?]", sizeof(pbuf)-1); + } + memset(mbuf, 0, sizeof(mbuf)); + strncpy(mbuf, "error contacting ", sizeof(mbuf)-1); + strncat(mbuf, abuf, sizeof(mbuf) - strlen(mbuf) - 1); + strncat(mbuf, " port ", sizeof(mbuf) - strlen(mbuf) - 1); + strncat(mbuf, pbuf, sizeof(mbuf) - strlen(mbuf) - 1); + sock = socket(ap->ai_family, SOCK_STREAM, 0); + if (sock < 0) { + fprintf(stderr, "%s: socket: %s\n", mbuf, strerror(errno)); + continue; + } + if (connect(sock, ap->ai_addr, ap->ai_addrlen) < 0) { + fprintf(stderr, "%s: connect: %s\n", mbuf, strerror(errno)); + close(sock); + sock = -1; + continue; + } + /* connected, yay! */ + } + if (sock == -1) + /* Already printed error message above. */ + exit(1); + printf("connected\n"); + + cksum_data.data = argv[1]; + cksum_data.length = strlen(argv[1]); + + retval = krb5_cc_default(context, &ccdef); + if (retval) { + com_err(argv[0], retval, "while getting default ccache"); + exit(1); + } + + retval = krb5_cc_get_principal(context, ccdef, &client); + if (retval) { + com_err(argv[0], retval, "while getting client principal name"); + exit(1); + } + retval = krb5_sendauth(context, &auth_context, (krb5_pointer) &sock, + SAMPLE_VERSION, client, server, + AP_OPTS_MUTUAL_REQUIRED, + &cksum_data, + 0, /* no creds, use ccache instead */ + ccdef, &err_ret, &rep_ret, NULL); + + krb5_free_principal(context, server); /* finished using it */ + krb5_free_principal(context, client); + krb5_cc_close(context, ccdef); + if (auth_context) krb5_auth_con_free(context, auth_context); + + if (retval && retval != KRB5_SENDAUTH_REJECTED) { + com_err(argv[0], retval, "while using sendauth"); + exit(1); + } + if (retval == KRB5_SENDAUTH_REJECTED) { + /* got an error */ + printf("sendauth rejected, error reply is:\n\t\"%*s\"\n", + err_ret->text.length, err_ret->text.data); + } else if (rep_ret) { + /* got a reply */ + krb5_free_ap_rep_enc_part(context, rep_ret); + + printf("sendauth succeeded, reply is:\n"); + if ((retval = net_read(sock, (char *)&xmitlen, + sizeof(xmitlen))) <= 0) { + if (retval == 0) + errno = ECONNABORTED; + com_err(argv[0], errno, "while reading data from server"); + exit(1); + } + recv_data.length = ntohs(xmitlen); + if (!(recv_data.data = (char *)malloc((size_t) recv_data.length + 1))) { + com_err(argv[0], ENOMEM, + "while allocating buffer to read from server"); + exit(1); + } + if ((retval = net_read(sock, (char *)recv_data.data, + recv_data.length)) <= 0) { + if (retval == 0) + errno = ECONNABORTED; + com_err(argv[0], errno, "while reading data from server"); + exit(1); + } + recv_data.data[recv_data.length] = '\0'; + printf("reply len %d, contents:\n%s\n", + recv_data.length,recv_data.data); + free(recv_data.data); + } else { + com_err(argv[0], 0, "no error or reply from sendauth!"); + exit(1); + } + freeaddrinfo(apstart); + krb5_free_context(context); + exit(0); +} diff --git a/krb5-1.21.3/src/appl/sample/sserver/Makefile.in b/krb5-1.21.3/src/appl/sample/sserver/Makefile.in new file mode 100644 index 00000000..c2e6d40a --- /dev/null +++ b/krb5-1.21.3/src/appl/sample/sserver/Makefile.in @@ -0,0 +1,13 @@ +mydir=appl$(S)sample$(S)sserver +BUILDTOP=$(REL)..$(S)..$(S).. + +all: sserver + +sserver: sserver.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o sserver sserver.o $(KRB5_BASE_LIBS) + +clean: + $(RM) sserver.o sserver + +install: + $(INSTALL_PROGRAM) sserver ${DESTDIR}$(SERVER_BINDIR)/sserver diff --git a/krb5-1.21.3/src/appl/sample/sserver/deps b/krb5-1.21.3/src/appl/sample/sserver/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/appl/sample/sserver/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/appl/sample/sserver/sserver.c b/krb5-1.21.3/src/appl/sample/sserver/sserver.c new file mode 100644 index 00000000..805ead73 --- /dev/null +++ b/krb5-1.21.3/src/appl/sample/sserver/sserver.c @@ -0,0 +1,246 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* appl/sample/sserver/sserver.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Sample Kerberos v5 server. + * + * sample_server: + * A sample Kerberos server, which reads an AP_REQ from a TCP socket, + * decodes it, and writes back the results (in ASCII) to the client. + * + * Usage: + * sample_server servername + * + * file descriptor 0 (zero) should be a socket connected to the requesting + * client (this will be correct if this server is started by inetd). + */ + +#include "k5-int.h" +#include "com_err.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "../sample.h" + +extern krb5_deltat krb5_clockskew; + +#ifndef GETPEERNAME_ARG3_TYPE +#define GETPEERNAME_ARG3_TYPE int +#endif + +static void +usage(char *name) +{ + fprintf(stderr, "usage: %s [-p port] [-s service] [-S keytab]\n", + name); +} + +int +main(int argc, char *argv[]) +{ + krb5_context context; + krb5_auth_context auth_context = NULL; + krb5_ticket * ticket; + struct sockaddr_in peername; + GETPEERNAME_ARG3_TYPE namelen = sizeof(peername); + int sock = -1; /* incoming connection fd */ + krb5_data recv_data; + short xmitlen; + krb5_error_code retval; + krb5_principal server; + char repbuf[BUFSIZ]; + char *cname; + char *service = SAMPLE_SERVICE; + short port = 0; /* If user specifies port */ + extern int opterr, optind; + extern char * optarg; + int ch; + krb5_keytab keytab = NULL; /* Allow specification on command line */ + char *progname; + int on = 1; + + progname = *argv; + + retval = krb5_init_context(&context); + if (retval) { + com_err(argv[0], retval, "while initializing krb5"); + exit(1); + } + + /* open a log connection */ + openlog("sserver", 0, LOG_DAEMON); + + /* + * Parse command line arguments + * + */ + opterr = 0; + while ((ch = getopt(argc, argv, "p:S:s:")) != -1) { + switch (ch) { + case 'p': + port = atoi(optarg); + break; + case 's': + service = optarg; + break; + case 'S': + if ((retval = krb5_kt_resolve(context, optarg, &keytab))) { + com_err(progname, retval, + "while resolving keytab file %s", optarg); + exit(2); + } + break; + + case '?': + default: + usage(progname); + exit(1); + break; + } + } + + argc -= optind; + argv += optind; + + /* Backwards compatibility, allow port to be specified at end */ + if (argc > 1) { + port = atoi(argv[1]); + } + + retval = krb5_sname_to_principal(context, NULL, service, + KRB5_NT_SRV_HST, &server); + if (retval) { + syslog(LOG_ERR, "while generating service name (%s): %s", + service, error_message(retval)); + exit(1); + } + + /* + * If user specified a port, then listen on that port; otherwise, + * assume we've been started out of inetd. + */ + + if (port) { + int acc; + struct sockaddr_in sockin; + + if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + syslog(LOG_ERR, "socket: %m"); + exit(3); + } + /* Let the socket be reused right away */ + (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, + sizeof(on)); + + sockin.sin_family = AF_INET; + sockin.sin_addr.s_addr = 0; + sockin.sin_port = htons(port); + if (bind(sock, (struct sockaddr *) &sockin, sizeof(sockin))) { + syslog(LOG_ERR, "bind: %m"); + exit(3); + } + if (listen(sock, 1) == -1) { + syslog(LOG_ERR, "listen: %m"); + exit(3); + } + + printf("starting...\n"); + fflush(stdout); + + if ((acc = accept(sock, (struct sockaddr *)&peername, &namelen)) == -1){ + syslog(LOG_ERR, "accept: %m"); + exit(3); + } + dup2(acc, 0); + close(sock); + sock = 0; + } else { + /* + * To verify authenticity, we need to know the address of the + * client. + */ + if (getpeername(0, (struct sockaddr *)&peername, &namelen) < 0) { + syslog(LOG_ERR, "getpeername: %m"); + exit(1); + } + sock = 0; + } + + retval = krb5_recvauth(context, &auth_context, (krb5_pointer)&sock, + SAMPLE_VERSION, server, + 0, /* no flags */ + keytab, /* default keytab is NULL */ + &ticket); + if (retval) { + syslog(LOG_ERR, "recvauth failed--%s", error_message(retval)); + exit(1); + } + + /* Get client name */ + repbuf[sizeof(repbuf) - 1] = '\0'; + retval = krb5_unparse_name(context, ticket->enc_part2->client, &cname); + if (retval){ + syslog(LOG_ERR, "unparse failed: %s", error_message(retval)); + strncpy(repbuf, "You are \n", sizeof(repbuf) - 1); + } else { + strncpy(repbuf, "You are ", sizeof(repbuf) - 1); + strncat(repbuf, cname, sizeof(repbuf) - 1 - strlen(repbuf)); + strncat(repbuf, "\n", sizeof(repbuf) - 1 - strlen(repbuf)); + free(cname); + } + xmitlen = htons(strlen(repbuf)); + recv_data.length = strlen(repbuf); + recv_data.data = repbuf; + if ((retval = krb5_net_write(context, 0, (char *)&xmitlen, + sizeof(xmitlen))) < 0) { + syslog(LOG_ERR, "%m: while writing len to client"); + exit(1); + } + if ((retval = krb5_net_write(context, 0, (char *)recv_data.data, + recv_data.length)) < 0) { + syslog(LOG_ERR, "%m: while writing data to client"); + exit(1); + } + + krb5_free_ticket(context, ticket); + if(keytab) + krb5_kt_close(context, keytab); + krb5_free_principal(context, server); + krb5_auth_con_free(context, auth_context); + krb5_free_context(context); + exit(0); +} diff --git a/krb5-1.21.3/src/appl/sample/t_sample.py b/krb5-1.21.3/src/appl/sample/t_sample.py new file mode 100644 index 00000000..1b75fa2f --- /dev/null +++ b/krb5-1.21.3/src/appl/sample/t_sample.py @@ -0,0 +1,22 @@ +from k5test import * + +sclient = os.path.join(buildtop, 'appl', 'sample', 'sclient', 'sclient') +sserver = os.path.join(buildtop, 'appl', 'sample', 'sserver', 'sserver') + +for realm in multipass_realms(create_host=False): + server_princ = 'sample/%s@%s' % (hostname, realm.realm) + realm.addprinc(server_princ) + realm.extract_keytab(server_princ, realm.keytab) + + portstr = str(realm.server_port()) + server = realm.start_server([sserver, '-p', portstr], 'starting...') + out = realm.run([sclient, hostname, portstr], + expected_msg='You are user@KRBTEST.COM') + await_daemon_exit(server) + + server = realm.start_in_inetd([sserver]) + out = realm.run([sclient, hostname, portstr], + expected_msg='You are user@KRBTEST.COM') + await_daemon_exit(server) + +success('sim_client/sim_server tests') diff --git a/krb5-1.21.3/src/appl/simple/Makefile.in b/krb5-1.21.3/src/appl/simple/Makefile.in new file mode 100644 index 00000000..5b9af1be --- /dev/null +++ b/krb5-1.21.3/src/appl/simple/Makefile.in @@ -0,0 +1,6 @@ +mydir=appl$(S)simple +SUBDIRS = client server +BUILDTOP=$(REL)..$(S).. + +check-pytests: + $(RUNPYTEST) $(srcdir)/t_simple.py $(PYTESTFLAGS) diff --git a/krb5-1.21.3/src/appl/simple/client/Makefile.in b/krb5-1.21.3/src/appl/simple/client/Makefile.in new file mode 100644 index 00000000..3859fcea --- /dev/null +++ b/krb5-1.21.3/src/appl/simple/client/Makefile.in @@ -0,0 +1,15 @@ +mydir=appl$(S)simple$(S)client +BUILDTOP=$(REL)..$(S)..$(S).. + +all: sim_client + +LOCALINCLUDES= -I$(srcdir)/.. + +sim_client: sim_client.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o sim_client sim_client.o $(KRB5_BASE_LIBS) + +install: + $(INSTALL_PROGRAM) sim_client $(DESTDIR)$(CLIENT_BINDIR)/sim_client + +clean: + $(RM) sim_client.o sim_client diff --git a/krb5-1.21.3/src/appl/simple/client/deps b/krb5-1.21.3/src/appl/simple/client/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/appl/simple/client/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/appl/simple/client/sim_client.c b/krb5-1.21.3/src/appl/simple/client/sim_client.c new file mode 100644 index 00000000..6f428337 --- /dev/null +++ b/krb5-1.21.3/src/appl/simple/client/sim_client.c @@ -0,0 +1,290 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* appl/simple/client/sim_client.c */ +/* + * Copyright 1989,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Simple UDP-based sample client program. For demonstration. + * This program performs no useful function. + */ + +#include +#include "com_err.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "simple.h" + +/* for old Unixes and friends ... */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#define MSG "hi there!" /* message text */ + +void usage (char *); + +void +usage(char *name) +{ + fprintf(stderr, "usage: %s [-p port] [-h host] [-m message] [-s service] [host]\n", name); +} + +int +main(int argc, char *argv[]) +{ + int sock, i; + socklen_t len; + int flags = 0; /* flags for sendto() */ + struct servent *serv; + struct hostent *host; +#ifdef BROKEN_STREAMS_SOCKETS + char my_hostname[MAXHOSTNAMELEN]; +#endif + struct sockaddr_in s_sock; /* server address */ + struct sockaddr_in c_sock; /* client address */ + extern int opterr, optind; + extern char * optarg; + int ch; + + short port = 0; + char *message = MSG; + char *hostname = 0; + char *service = SIMPLE_SERVICE; + char *progname = 0; + + krb5_error_code retval; + krb5_data packet, inbuf; + krb5_ccache ccdef; + krb5_address addr; + + krb5_context context; + krb5_auth_context auth_context = NULL; + + retval = krb5_init_context(&context); + if (retval) { + com_err(argv[0], retval, "while initializing krb5"); + exit(1); + } + + progname = argv[0]; + + /* + * Parse command line arguments + * + */ + opterr = 0; + while ((ch = getopt(argc, argv, "p:m:h:s:")) != -1) + switch (ch) { + case 'p': + port = atoi(optarg); + break; + case 'm': + message = optarg; + break; + case 'h': + hostname = optarg; + break; + case 's': + service = optarg; + break; + case '?': + default: + usage(progname); + exit(1); + break; + } + argc -= optind; + argv += optind; + if (argc > 0) { + if (hostname) + usage(progname); + hostname = argv[0]; + } + + if (hostname == 0) { + fprintf(stderr, "You must specify a hostname to contact.\n\n"); + usage(progname); + exit(1); + } + + /* Look up server host */ + if ((host = gethostbyname(hostname)) == (struct hostent *) 0) { + fprintf(stderr, "%s: unknown host\n", hostname); + exit(1); + } + + /* Set server's address */ + (void) memset(&s_sock, 0, sizeof(s_sock)); + + memcpy(&s_sock.sin_addr, host->h_addr, sizeof(s_sock.sin_addr)); +#ifdef DEBUG + printf("s_sock.sin_addr is %s\n", inet_ntoa(s_sock.sin_addr)); +#endif + s_sock.sin_family = AF_INET; + + if (port == 0) { + /* Look up service */ + if ((serv = getservbyname(SIMPLE_PORT, "udp")) == NULL) { + fprintf(stderr, "service unknown: %s/udp\n", SIMPLE_PORT); + exit(1); + } + s_sock.sin_port = serv->s_port; + } else { + s_sock.sin_port = htons(port); + } + + /* Open a socket */ + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + com_err(progname, errno, "opening datagram socket"); + exit(1); + } + + memset(&c_sock, 0, sizeof(c_sock)); + c_sock.sin_family = AF_INET; +#ifdef BROKEN_STREAMS_SOCKETS + if (gethostname(my_hostname, sizeof(my_hostname)) < 0) { + perror("gethostname"); + exit(1); + } + + if ((host = gethostbyname(my_hostname)) == (struct hostent *)0) { + fprintf(stderr, "%s: unknown host\n", hostname); + exit(1); + } + memcpy(&c_sock.sin_addr, host->h_addr, sizeof(c_sock.sin_addr)); +#endif + + + /* Bind it to set the address; kernel will fill in port # */ + if (bind(sock, (struct sockaddr *)&c_sock, sizeof(c_sock)) < 0) { + com_err(progname, errno, "while binding datagram socket"); + exit(1); + } + + /* PREPARE KRB_AP_REQ MESSAGE */ + + inbuf.data = hostname; + inbuf.length = strlen(hostname); + + /* Get credentials for server */ + if ((retval = krb5_cc_default(context, &ccdef))) { + com_err(progname, retval, "while getting default ccache"); + exit(1); + } + + retval = krb5_mk_req(context, &auth_context, AP_OPTS_USE_SUBKEY, service, + hostname, &inbuf, ccdef, &packet); + if (retval) { + com_err(progname, retval, "while preparing AP_REQ"); + exit(1); + } + printf("Got credentials for %s.\n", service); + + /* "connect" the datagram socket; this is necessary to get a local address + properly bound for getsockname() below. */ + + if (connect(sock, (struct sockaddr *)&s_sock, sizeof(s_sock)) == -1) { + com_err(progname, errno, "while connecting to server"); + exit(1); + } + /* Send authentication info to server */ + if ((i = send(sock, (char *)packet.data, (unsigned) packet.length, + flags)) < 0) + com_err(progname, errno, "while sending KRB_AP_REQ message"); + printf("Sent authentication data: %d bytes\n", i); + krb5_free_data_contents(context, &packet); + + /* PREPARE KRB_SAFE MESSAGE */ + + /* Get my address */ + memset(&c_sock, 0, sizeof(c_sock)); + len = sizeof(c_sock); + if (getsockname(sock, (struct sockaddr *)&c_sock, &len) < 0) { + com_err(progname, errno, "while getting socket name"); + exit(1); + } + + addr.addrtype = ADDRTYPE_IPPORT; + addr.length = sizeof(c_sock.sin_port); + addr.contents = (krb5_octet *)&c_sock.sin_port; + if ((retval = krb5_auth_con_setports(context, auth_context, + &addr, NULL))) { + com_err(progname, retval, "while setting local port\n"); + exit(1); + } + + addr.addrtype = ADDRTYPE_INET; + addr.length = sizeof(c_sock.sin_addr); + addr.contents = (krb5_octet *)&c_sock.sin_addr; + if ((retval = krb5_auth_con_setaddrs(context, auth_context, + &addr, NULL))) { + com_err(progname, retval, "while setting local addr\n"); + exit(1); + } + + /* Make the safe message */ + inbuf.data = message; + inbuf.length = strlen(message); + + if ((retval = krb5_mk_safe(context, auth_context, &inbuf, &packet, NULL))){ + com_err(progname, retval, "while making KRB_SAFE message"); + exit(1); + } + + /* Send it */ + if ((i = send(sock, (char *)packet.data, (unsigned) packet.length, + flags)) < 0) + com_err(progname, errno, "while sending SAFE message"); + printf("Sent checksummed message: %d bytes\n", i); + krb5_free_data_contents(context, &packet); + + /* PREPARE KRB_PRIV MESSAGE */ + + /* Make the encrypted message */ + if ((retval = krb5_mk_priv(context, auth_context, &inbuf, + &packet, NULL))) { + com_err(progname, retval, "while making KRB_PRIV message"); + exit(1); + } + + /* Send it */ + if ((i = send(sock, (char *)packet.data, (unsigned) packet.length, + flags)) < 0) + com_err(progname, errno, "while sending PRIV message"); + printf("Sent encrypted message: %d bytes\n", i); + krb5_free_data_contents(context, &packet); + + krb5_auth_con_free(context, auth_context); + krb5_free_context(context); + + exit(0); +} diff --git a/krb5-1.21.3/src/appl/simple/deps b/krb5-1.21.3/src/appl/simple/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/appl/simple/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/appl/simple/server/Makefile.in b/krb5-1.21.3/src/appl/simple/server/Makefile.in new file mode 100644 index 00000000..83f4fccc --- /dev/null +++ b/krb5-1.21.3/src/appl/simple/server/Makefile.in @@ -0,0 +1,15 @@ +mydir=appl$(S)simple$(S)server +BUILDTOP=$(REL)..$(S)..$(S).. + +LOCALINCLUDES= -I$(srcdir)/.. + +all: sim_server + +sim_server: sim_server.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o sim_server sim_server.o $(KRB5_BASE_LIBS) + +install: + $(INSTALL_PROGRAM) sim_server $(DESTDIR)$(SERVER_BINDIR)/sim_server + +clean: + $(RM) sim_server.o sim_server diff --git a/krb5-1.21.3/src/appl/simple/server/deps b/krb5-1.21.3/src/appl/simple/server/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/appl/simple/server/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/appl/simple/server/sim_server.c b/krb5-1.21.3/src/appl/simple/server/sim_server.c new file mode 100644 index 00000000..093ed55d --- /dev/null +++ b/krb5-1.21.3/src/appl/simple/server/sim_server.c @@ -0,0 +1,269 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* appl/simple/server/sim_server.c */ +/* + * Copyright 1989,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Usage: + * sample_server servername + * + * Simple UDP-based server application. For demonstration. + * This program performs no useful function. + */ + +#include "krb5.h" +#include "port-sockets.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "com_err.h" + +#include "simple.h" + +/* for old Unixes and friends ... */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#define PROGNAME argv[0] + +static void +usage(char *name) +{ + fprintf(stderr, "usage: %s [-p port] [-s service] [-S keytab]\n", name); +} + +int +main(int argc, char *argv[]) +{ + int sock, i; + socklen_t len; + int flags = 0; /* for recvfrom() */ + int on = 1; + struct servent *serv; + struct sockaddr_in s_sock; /* server's address */ + struct sockaddr_in c_sock; /* client's address */ + char *cp; + extern char * optarg; + int ch; + + short port = 0; /* If user specifies port */ + krb5_keytab keytab = NULL; /* Allow specification on command line */ + char *service = SIMPLE_SERVICE; + + krb5_error_code retval; + krb5_data packet, message; + unsigned char pktbuf[BUFSIZ]; + krb5_principal sprinc; + krb5_context context; + krb5_auth_context auth_context = NULL; + krb5_address addr; + krb5_ticket *ticket = NULL; + + retval = krb5_init_context(&context); + if (retval) { + com_err(argv[0], retval, "while initializing krb5"); + exit(1); + } + + /* + * Parse command line arguments + * + */ + while ((ch = getopt(argc, argv, "p:s:S:")) != -1) { + switch (ch) { + case 'p': + port = atoi(optarg); + break; + case 's': + service = optarg; + break; + case 'S': + if ((retval = krb5_kt_resolve(context, optarg, &keytab))) { + com_err(PROGNAME, retval, + "while resolving keytab file %s", optarg); + exit(2); + } + break; + + case '?': + default: + usage(PROGNAME); + exit(1); + break; + } + } + + if ((retval = krb5_sname_to_principal(context, NULL, service, + KRB5_NT_SRV_HST, &sprinc))) { + com_err(PROGNAME, retval, "while generating service name %s", service); + exit(1); + } + + /* Set up server address */ + memset(&s_sock, 0, sizeof(s_sock)); + s_sock.sin_family = AF_INET; + s_sock.sin_addr.s_addr = INADDR_ANY; + + if (port == 0) { + /* Look up service */ + if ((serv = getservbyname(SIMPLE_PORT, "udp")) == NULL) { + fprintf(stderr, "service unknown: %s/udp\n", SIMPLE_PORT); + exit(1); + } + s_sock.sin_port = serv->s_port; + } else { + s_sock.sin_port = htons(port); + } + + /* Open socket */ + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("opening datagram socket"); + exit(1); + } + + /* Let the socket be reused right away */ + (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, + sizeof(on)); + + /* Bind the socket */ + if (bind(sock, (struct sockaddr *)&s_sock, sizeof(s_sock))) { + perror("binding datagram socket"); + exit(1); + } + + printf("starting...\n"); + fflush(stdout); + +#ifdef DEBUG + printf("socket has port # %d\n", ntohs(s_sock.sin_port)); +#endif + + /* GET KRB_AP_REQ MESSAGE */ + + /* use "recvfrom" so we know client's address */ + len = sizeof(struct sockaddr_in); + if ((i = recvfrom(sock, (char *)pktbuf, sizeof(pktbuf), flags, + (struct sockaddr *)&c_sock, &len)) < 0) { + perror("receiving datagram"); + exit(1); + } + + printf("Received %d bytes\n", i); + packet.length = i; + packet.data = (krb5_pointer) pktbuf; + + /* Check authentication info */ + if ((retval = krb5_rd_req(context, &auth_context, &packet, + sprinc, keytab, NULL, &ticket))) { + com_err(PROGNAME, retval, "while reading request"); + exit(1); + } + if ((retval = krb5_unparse_name(context, ticket->enc_part2->client, + &cp))) { + com_err(PROGNAME, retval, "while unparsing client name"); + exit(1); + } + printf("Got authentication info from %s\n", cp); + free(cp); + + /* Set foreign_addr for rd_safe() and rd_priv() */ + addr.addrtype = ADDRTYPE_INET; + addr.length = sizeof(c_sock.sin_addr); + addr.contents = (krb5_octet *)&c_sock.sin_addr; + if ((retval = krb5_auth_con_setaddrs(context, auth_context, + NULL, &addr))) { + com_err(PROGNAME, retval, "while setting foreign addr"); + exit(1); + } + + addr.addrtype = ADDRTYPE_IPPORT; + addr.length = sizeof(c_sock.sin_port); + addr.contents = (krb5_octet *)&c_sock.sin_port; + if ((retval = krb5_auth_con_setports(context, auth_context, + NULL, &addr))) { + com_err(PROGNAME, retval, "while setting foreign port"); + exit(1); + } + + /* GET KRB_MK_SAFE MESSAGE */ + + /* use "recvfrom" so we know client's address */ + len = sizeof(struct sockaddr_in); + if ((i = recvfrom(sock, (char *)pktbuf, sizeof(pktbuf), flags, + (struct sockaddr *)&c_sock, &len)) < 0) { + perror("receiving datagram"); + exit(1); + } +#ifdef DEBUG + printf("&c_sock.sin_addr is %s\n", inet_ntoa(c_sock.sin_addr)); +#endif + printf("Received %d bytes\n", i); + + packet.length = i; + packet.data = (krb5_pointer) pktbuf; + + if ((retval = krb5_rd_safe(context, auth_context, &packet, + &message, NULL))) { + com_err(PROGNAME, retval, "while verifying SAFE message"); + exit(1); + } + printf("Safe message is: '%.*s'\n", (int) message.length, message.data); + + krb5_free_data_contents(context, &message); + + /* NOW GET ENCRYPTED MESSAGE */ + + /* use "recvfrom" so we know client's address */ + len = sizeof(struct sockaddr_in); + if ((i = recvfrom(sock, (char *)pktbuf, sizeof(pktbuf), flags, + (struct sockaddr *)&c_sock, &len)) < 0) { + perror("receiving datagram"); + exit(1); + } + printf("Received %d bytes\n", i); + + packet.length = i; + packet.data = (krb5_pointer) pktbuf; + + if ((retval = krb5_rd_priv(context, auth_context, &packet, + &message, NULL))) { + com_err(PROGNAME, retval, "while verifying PRIV message"); + exit(1); + } + printf("Decrypted message is: '%.*s'\n", (int) message.length, + message.data); + + krb5_auth_con_free(context, auth_context); + krb5_free_context(context); + + exit(0); +} diff --git a/krb5-1.21.3/src/appl/simple/simple.h b/krb5-1.21.3/src/appl/simple/simple.h new file mode 100644 index 00000000..2de17d33 --- /dev/null +++ b/krb5-1.21.3/src/appl/simple/simple.h @@ -0,0 +1,33 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* appl/simple/simple.h */ +/* + * Copyright 1988,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Common definitions for the simple UDP-based Kerberos-mediated + * server & client applications. + */ + +#define SIMPLE_SERVICE "sample" +#define SIMPLE_PORT "sample" diff --git a/krb5-1.21.3/src/appl/simple/t_simple.py b/krb5-1.21.3/src/appl/simple/t_simple.py new file mode 100644 index 00000000..b720732a --- /dev/null +++ b/krb5-1.21.3/src/appl/simple/t_simple.py @@ -0,0 +1,34 @@ +from k5test import * + +sim_client = os.path.join(buildtop, 'appl', 'simple', 'client', 'sim_client') +sim_server = os.path.join(buildtop, 'appl', 'simple', 'server', 'sim_server') + +for realm in multipass_realms(create_host=False): + server_princ = 'sample/%s@%s' % (hostname, realm.realm) + realm.addprinc(server_princ) + realm.extract_keytab(server_princ, realm.keytab) + + portstr = str(realm.server_port()) + server = realm.start_server([sim_server, '-p', portstr], 'starting...') + + out = realm.run([sim_client, '-p', portstr, hostname]) + if ('Sent checksummed message:' not in out or + 'Sent encrypted message:' not in out): + fail('Expected client messages not seen') + + # sim_server exits after one client execution, so we can read + # until it closes stdout. + seen1 = seen2 = seen3 = False + for line in server.stdout: + if line == 'Got authentication info from user@KRBTEST.COM\n': + seen1 = True + if line == "Safe message is: 'hi there!'\n": + seen2 = True + if line == "Decrypted message is: 'hi there!'\n": + seen3 = True + if not (seen1 and seen2 and seen3): + fail('Expected server messages not seen') + + await_daemon_exit(server) + +success('sim_client/sim_server tests') diff --git a/krb5-1.21.3/src/appl/user_user/Makefile.in b/krb5-1.21.3/src/appl/user_user/Makefile.in new file mode 100644 index 00000000..8b553f1b --- /dev/null +++ b/krb5-1.21.3/src/appl/user_user/Makefile.in @@ -0,0 +1,22 @@ +mydir=appl$(S)user_user +BUILDTOP=$(REL)..$(S).. +# If you remove the -DDEBUG, the test program needs a line changed +DEFINES = -DDEBUG + +all: uuclient uuserver + +check-pytests: uuclient uuserver + $(RUNPYTEST) $(srcdir)/t_user2user.py $(PYTESTFLAGS) + +uuclient: client.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o uuclient client.o $(KRB5_BASE_LIBS) + +uuserver: server.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o uuserver server.o $(KRB5_BASE_LIBS) + +install: + $(INSTALL_PROGRAM) uuclient $(DESTDIR)$(CLIENT_BINDIR)/uuclient + $(INSTALL_PROGRAM) uuserver $(DESTDIR)$(SERVER_BINDIR)/uuserver + +clean: + $(RM) client.o server.o uuclient uuserver diff --git a/krb5-1.21.3/src/appl/user_user/client.c b/krb5-1.21.3/src/appl/user_user/client.c new file mode 100644 index 00000000..9a05345c --- /dev/null +++ b/krb5-1.21.3/src/appl/user_user/client.c @@ -0,0 +1,283 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* appl/user_user/client.c - Other end of user-user client/server pair */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "com_err.h" + +#include +#include +#include +#include +#include + +int main (int argc, char *argv[]) +{ + int s; + int retval, i; + char *hname; /* full name of server */ + char **srealms; /* realm(s) of server */ + char *princ; /* principal in credentials cache */ + struct servent *serv; + struct hostent *host; + struct sockaddr_in serv_net_addr, cli_net_addr; + krb5_ccache cc; + krb5_creds creds, *new_creds; + krb5_data reply, msg, princ_data; + krb5_auth_context auth_context = NULL; + krb5_ticket * ticket = NULL; + krb5_context context; + unsigned short port; + + if (argc < 2 || argc > 4) { + fputs ("usage: uu-client [message [port]]\n", stderr); + exit(1); + } + + retval = krb5_init_context(&context); + if (retval) { + com_err(argv[0], retval, "while initializing krb5"); + exit(1); + } + + if (argc == 4) { + port = htons(atoi(argv[3])); + } + else if ((serv = getservbyname ("uu-sample", "tcp")) == NULL) + { + fputs ("uu-client: unknown service \"uu-sample/tcp\"\n", stderr); + exit(2); + } else { + port = serv->s_port; + } + + if ((host = gethostbyname (argv[1])) == NULL) { + fprintf (stderr, "uu-client: can't get address of host \"%s\".\n", + argv[1]); + exit(3); + } + + if (host->h_addrtype != AF_INET) { + fprintf (stderr, "uu-client: bad address type %d for \"%s\".\n", + host->h_addrtype, argv[1]); + exit(3); + } + + hname = strdup (host->h_name); + +#ifndef USE_STDOUT + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + com_err ("uu-client", errno, "creating socket"); + exit(4); + } else { + cli_net_addr.sin_family = AF_INET; + cli_net_addr.sin_port = 0; + cli_net_addr.sin_addr.s_addr = 0; + if (bind (s, (struct sockaddr *)&cli_net_addr, + sizeof (cli_net_addr)) < 0) { + com_err ("uu-client", errno, "binding socket"); + exit(4); + } + } + + serv_net_addr.sin_family = AF_INET; + serv_net_addr.sin_port = port; + + i = 0; + while (1) { + if (host->h_addr_list[i] == 0) { + fprintf (stderr, "uu-client: unable to connect to \"%s\"\n", hname); + exit(5); + } + + memcpy (&serv_net_addr.sin_addr, host->h_addr_list[i++], + sizeof(serv_net_addr.sin_addr)); + + if (connect(s, (struct sockaddr *)&serv_net_addr, + sizeof (serv_net_addr)) == 0) + break; + com_err ("uu-client", errno, "connecting to \"%s\" (%s).", + hname, inet_ntoa(serv_net_addr.sin_addr)); + } +#else + s = 1; +#endif + + retval = krb5_cc_default(context, &cc); + if (retval) { + com_err("uu-client", retval, "getting credentials cache"); + exit(6); + } + + memset (&creds, 0, sizeof(creds)); + + retval = krb5_cc_get_principal(context, cc, &creds.client); + if (retval) { + com_err("uu-client", retval, "getting principal name"); + exit(6); + } + + retval = krb5_unparse_name(context, creds.client, &princ); + if (retval) { + com_err("uu-client", retval, "printing principal name"); + exit(7); + } + else + fprintf(stderr, "uu-client: client principal is \"%s\".\n", princ); + + retval = krb5_get_host_realm(context, hname, &srealms); + if (retval) { + com_err("uu-client", retval, "getting realms for \"%s\"", hname); + exit(7); + } + + retval = + krb5_build_principal_ext(context, &creds.server, + krb5_princ_realm(context, + creds.client)->length, + krb5_princ_realm(context, + creds.client)->data, + 6, "krbtgt", + krb5_princ_realm(context, + creds.client)->length, + krb5_princ_realm(context, + creds.client)->data, + 0); + if (retval) { + com_err("uu-client", retval, "setting up tgt server name"); + exit(7); + } + + /* Get TGT from credentials cache */ + retval = krb5_get_credentials(context, KRB5_GC_CACHED, cc, + &creds, &new_creds); + if (retval) { + com_err("uu-client", retval, "getting TGT"); + exit(6); + } + + i = strlen(princ) + 1; + + fprintf(stderr, "uu-client: sending %d bytes\n", + new_creds->ticket.length + i); + princ_data.data = princ; + princ_data.length = i; /* include null terminator for + server's convenience */ + retval = krb5_write_message(context, (krb5_pointer) &s, &princ_data); + if (retval) { + com_err("uu-client", retval, "sending principal name to server"); + exit(8); + } + + free(princ); + + retval = krb5_write_message(context, (krb5_pointer) &s, + &new_creds->ticket); + if (retval) { + com_err("uu-client", retval, "sending ticket to server"); + exit(8); + } + + retval = krb5_read_message(context, (krb5_pointer) &s, &reply); + if (retval) { + com_err("uu-client", retval, "reading reply from server"); + exit(9); + } + + retval = krb5_auth_con_init(context, &auth_context); + if (retval) { + com_err("uu-client", retval, "initializing the auth_context"); + exit(9); + } + + retval = + krb5_auth_con_genaddrs(context, auth_context, s, + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR | + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR); + if (retval) { + com_err("uu-client", retval, "generating addrs for auth_context"); + exit(9); + } + + retval = krb5_auth_con_setflags(context, auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE); + if (retval) { + com_err("uu-client", retval, "initializing the auth_context flags"); + exit(9); + } + + retval = krb5_auth_con_setuseruserkey(context, auth_context, + &new_creds->keyblock); + if (retval) { + com_err("uu-client", retval, "setting useruserkey for authcontext"); + exit(9); + } + + /* read the ap_req to get the session key */ + retval = krb5_rd_req(context, &auth_context, &reply, creds.client, NULL, + NULL, &ticket); + krb5_free_data_contents(context, &reply); + if (retval) { + com_err("uu-client", retval, "reading AP_REQ from server"); + exit(9); + } + + retval = krb5_unparse_name(context, ticket->enc_part2->client, &princ); + if (retval) + com_err("uu-client", retval, "while unparsing client name"); + else { + printf("server is named \"%s\"\n", princ); + free(princ); + } + + retval = krb5_read_message(context, (krb5_pointer) &s, &reply); + if (retval) { + com_err("uu-client", retval, "reading reply from server"); + exit(9); + } + + retval = krb5_rd_safe(context, auth_context, &reply, &msg, NULL); + if (retval) { + com_err("uu-client", retval, "decoding reply from server"); + exit(10); + } + + printf ("uu-client: server says \"%s\".\n", msg.data); + +#ifndef USE_STDOUT + close(s); +#endif + krb5_free_ticket(context, ticket); + krb5_free_host_realm(context, srealms); + free(hname); + krb5_free_cred_contents(context, &creds); + krb5_free_creds(context, new_creds); + krb5_free_data_contents(context, &msg); + krb5_free_data_contents(context, &reply); + krb5_cc_close(context, cc); + krb5_auth_con_free(context, auth_context); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/appl/user_user/deps b/krb5-1.21.3/src/appl/user_user/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/appl/user_user/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/appl/user_user/server.c b/krb5-1.21.3/src/appl/user_user/server.c new file mode 100644 index 00000000..f2b5b614 --- /dev/null +++ b/krb5-1.21.3/src/appl/user_user/server.c @@ -0,0 +1,247 @@ + +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* appl/user_user/server.c - One end of user-user client-server pair */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "port-sockets.h" +#include "com_err.h" + +#include +#include +#include +#include +#include +#include +#include + +/* fd 0 is a tcp socket used to talk to the client */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + krb5_data pname_data, tkt_data; + int sock = 0; + socklen_t l; + int retval; + struct sockaddr_in l_inaddr, f_inaddr; /* local, foreign address */ + krb5_creds creds, *new_creds; + krb5_ccache cc; + krb5_data msgtext, msg; + krb5_context context; + krb5_auth_context auth_context = NULL; + +#ifndef DEBUG + freopen("/tmp/uu-server.log", "w", stderr); +#endif + + retval = krb5_init_context(&context); + if (retval) { + com_err(argv[0], retval, "while initializing krb5"); + exit(1); + } + +#ifdef DEBUG + { + int one = 1; + int acc; + struct servent *sp; + socklen_t namelen = sizeof(f_inaddr); + + if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + com_err("uu-server", errno, "creating socket"); + exit(3); + } + + l_inaddr.sin_family = AF_INET; + l_inaddr.sin_addr.s_addr = 0; + if (argc == 2) { + l_inaddr.sin_port = htons(atoi(argv[1])); + } else { + if (!(sp = getservbyname("uu-sample", "tcp"))) { + com_err("uu-server", 0, "can't find uu-sample/tcp service"); + exit(3); + } + l_inaddr.sin_port = sp->s_port; + } + + (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof (one)); + if (bind(sock, (struct sockaddr *)&l_inaddr, sizeof(l_inaddr))) { + com_err("uu-server", errno, "binding socket"); + exit(3); + } + if (listen(sock, 1) == -1) { + com_err("uu-server", errno, "listening"); + exit(3); + } + + printf("Server started\n"); + fflush(stdout); + + if ((acc = accept(sock, (struct sockaddr *)&f_inaddr, &namelen)) == -1) { + com_err("uu-server", errno, "accepting"); + exit(3); + } + dup2(acc, 0); + close(sock); + sock = 0; + } +#endif + + /* principal name must be sent null-terminated. */ + retval = krb5_read_message(context, (krb5_pointer) &sock, &pname_data); + if (retval || pname_data.length == 0 || + pname_data.data[pname_data.length - 1] != '\0') { + com_err ("uu-server", retval, "reading pname"); + return 2; + } + + retval = krb5_read_message(context, (krb5_pointer) &sock, &tkt_data); + if (retval) { + com_err ("uu-server", retval, "reading ticket data"); + return 2; + } + + retval = krb5_cc_default(context, &cc); + if (retval) { + com_err("uu-server", retval, "getting credentials cache"); + return 4; + } + + memset (&creds, 0, sizeof(creds)); + retval = krb5_cc_get_principal(context, cc, &creds.client); + if (retval) { + com_err("uu-client", retval, "getting principal name"); + return 6; + } + + /* client sends it already null-terminated. */ + printf ("uu-server: client principal is \"%s\".\n", pname_data.data); + + retval = krb5_parse_name(context, pname_data.data, &creds.server); + if (retval) { + com_err("uu-server", retval, "parsing client name"); + return 3; + } + + creds.second_ticket = tkt_data; + printf ("uu-server: client ticket is %d bytes.\n", + creds.second_ticket.length); + + retval = krb5_get_credentials(context, KRB5_GC_USER_USER, cc, + &creds, &new_creds); + if (retval) { + com_err("uu-server", retval, "getting user-user ticket"); + return 5; + } + +#ifndef DEBUG + l = sizeof(f_inaddr); + if (getpeername(0, (struct sockaddr *)&f_inaddr, &l) == -1) + { + com_err("uu-server", errno, "getting client address"); + return 6; + } +#endif + l = sizeof(l_inaddr); + if (getsockname(0, (struct sockaddr *)&l_inaddr, &l) == -1) + { + com_err("uu-server", errno, "getting local address"); + return 6; + } + + /* send a ticket/authenticator to the other side, so it can get the key + we're using for the krb_safe below. */ + + retval = krb5_auth_con_init(context, &auth_context); + if (retval) { + com_err("uu-server", retval, "making auth_context"); + return 8; + } + + retval = krb5_auth_con_setflags(context, auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE); + if (retval) { + com_err("uu-server", retval, "initializing the auth_context flags"); + return 8; + } + + retval = + krb5_auth_con_genaddrs(context, auth_context, sock, + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR | + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR); + if (retval) { + com_err("uu-server", retval, "generating addrs for auth_context"); + return 9; + } + +#if 1 + retval = krb5_mk_req_extended(context, &auth_context, + AP_OPTS_USE_SESSION_KEY, + NULL, new_creds, &msg); + if (retval) { + com_err("uu-server", retval, "making AP_REQ"); + return 8; + } + retval = krb5_write_message(context, (krb5_pointer) &sock, &msg); +#else + retval = krb5_sendauth(context, &auth_context, (krb5_pointer)&sock, "???", + 0, 0, + AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SESSION_KEY, + NULL, &creds, cc, NULL, NULL, NULL); +#endif + if (retval) + goto cl_short_wrt; + + free(msg.data); + + msgtext.length = 32; + msgtext.data = "Hello, other end of connection."; + + retval = krb5_mk_safe(context, auth_context, &msgtext, &msg, NULL); + if (retval) { + com_err("uu-server", retval, "encoding message to client"); + return 6; + } + + retval = krb5_write_message(context, (krb5_pointer) &sock, &msg); + if (retval) { + cl_short_wrt: + com_err("uu-server", retval, "writing message to client"); + return 7; + } + + + krb5_free_data_contents(context, &msg); + krb5_free_data_contents(context, &pname_data); + /* tkt_data freed with creds */ + krb5_free_cred_contents(context, &creds); + krb5_free_creds(context, new_creds); + krb5_cc_close(context, cc); + krb5_auth_con_free(context, auth_context); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/appl/user_user/t_user2user.py b/krb5-1.21.3/src/appl/user_user/t_user2user.py new file mode 100755 index 00000000..9c967596 --- /dev/null +++ b/krb5-1.21.3/src/appl/user_user/t_user2user.py @@ -0,0 +1,18 @@ +from k5test import * + +# If uuserver is not compiled under -DDEBUG, then set to 0 +debug_compiled=1 + +for realm in multipass_realms(): + if debug_compiled == 0: + server = realm.start_in_inetd(['./uuserver'], port=9999) + else: + server = realm.start_server(['./uuserver', '9999'], 'Server started') + + msg = 'uu-client: server says "Hello, other end of connection."' + realm.run(['./uuclient', hostname, 'testing message', '9999'], + expected_msg=msg) + + await_daemon_exit(server) + +success('User-2-user test programs') diff --git a/krb5-1.21.3/src/build-tools/Makefile.in b/krb5-1.21.3/src/build-tools/Makefile.in new file mode 100644 index 00000000..5dcae118 --- /dev/null +++ b/krb5-1.21.3/src/build-tools/Makefile.in @@ -0,0 +1,50 @@ +mydir=build-tools +BUILDTOP=$(REL).. + +PKGCONFIG_FILES = \ + kadm-client.pc \ + kadm-server.pc \ + kdb.pc \ + mit-krb5.pc \ + krb5.pc \ + mit-krb5-gssapi.pc \ + krb5-gssapi.pc \ + gssrpc.pc + +all-unix: krb5-config $(PKGCONFIG_FILES) + +krb5-config $(PKGCONFIG_FILES): $(BUILDTOP)/config.status + (cd $(BUILDTOP) && $(SHELL) config.status $(mydir)/$@) +krb5-config: $(srcdir)/krb5-config.in +kadm-client.pc: $(srcdir)/kadm-client.pc.in +kadm-server.pc: $(srcdir)/kadm-server.pc.in +kdb.pc: $(srcdir)/kdb.pc.in +mit-krb5.pc: $(srcdir)/mit-krb5.pc.in +krb5.pc: $(srcdir)/krb5.pc.in +mit-krb5-gssapi.pc: $(srcdir)/mit-krb5-gssapi.pc.in +krb5-gssapi.pc: $(srcdir)/krb5-gssapi.pc.in +gssrpc.pc: $(srcdir)/gssrpc.pc.in + +install-unix: + $(INSTALL_SCRIPT) krb5-config $(DESTDIR)$(CLIENT_BINDIR)/krb5-config + $(INSTALL_DATA) kadm-client.pc \ + $(DESTDIR)$(PKGCONFIG_DIR)/kadm-client.pc + $(INSTALL_DATA) kadm-server.pc \ + $(DESTDIR)$(PKGCONFIG_DIR)/kadm-server.pc + $(INSTALL_DATA) kdb.pc $(DESTDIR)$(PKGCONFIG_DIR)/kdb.pc + $(INSTALL_DATA) mit-krb5.pc $(DESTDIR)$(PKGCONFIG_DIR)/mit-krb5.pc + $(INSTALL_DATA) krb5.pc $(DESTDIR)$(PKGCONFIG_DIR)/krb5.pc + $(INSTALL_DATA) mit-krb5-gssapi.pc \ + $(DESTDIR)$(PKGCONFIG_DIR)/mit-krb5-gssapi.pc + $(INSTALL_DATA) krb5-gssapi.pc \ + $(DESTDIR)$(PKGCONFIG_DIR)/krb5-gssapi.pc + $(INSTALL_DATA) gssrpc.pc \ + $(DESTDIR)$(PKGCONFIG_DIR)/gssrpc.pc + +# Test to ensure that krb5-config does not spit out things like +# $(PURE) or $(LDFLAGS) in case someone changes config/shlib.conf +check-unix: krb5-config + $(SHELL) $(srcdir)/t_krbconf + +distclean-unix: + $(RM) $(PKGCONFIG_FILES) krb5-config diff --git a/krb5-1.21.3/src/build-tools/deps b/krb5-1.21.3/src/build-tools/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/build-tools/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/build-tools/gssrpc.pc.in b/krb5-1.21.3/src/build-tools/gssrpc.pc.in new file mode 100644 index 00000000..ca909217 --- /dev/null +++ b/krb5-1.21.3/src/build-tools/gssrpc.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +vendor=MIT + +Name: gssrpc +Description: GSSAPI RPC implementation +Version: @KRB5_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -lgssrpc +Requires.private: mit-krb5-gssapi diff --git a/krb5-1.21.3/src/build-tools/kadm-client.pc.in b/krb5-1.21.3/src/build-tools/kadm-client.pc.in new file mode 100644 index 00000000..c8d1cd12 --- /dev/null +++ b/krb5-1.21.3/src/build-tools/kadm-client.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: kadm-client +Description: Kerberos administration client library +Version: @KRB5_VERSION@ +Requires.private: mit-krb5-gssapi gssrpc +Cflags: -I${includedir} +Libs: -L${libdir} -lkadm5clnt_mit diff --git a/krb5-1.21.3/src/build-tools/kadm-server.pc.in b/krb5-1.21.3/src/build-tools/kadm-server.pc.in new file mode 100644 index 00000000..cd2f86c6 --- /dev/null +++ b/krb5-1.21.3/src/build-tools/kadm-server.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: kadm-server +Description: Kerberos administration server library +Version: @KRB5_VERSION@ +Requires.private: kdb mit-krb5-gssapi +Cflags: -I${includedir} +Libs: -L${libdir} -lkadm5srv_mit diff --git a/krb5-1.21.3/src/build-tools/kdb.pc.in b/krb5-1.21.3/src/build-tools/kdb.pc.in new file mode 100644 index 00000000..461a8d01 --- /dev/null +++ b/krb5-1.21.3/src/build-tools/kdb.pc.in @@ -0,0 +1,14 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +KDB5_DB_LIB=@KDB5_DB_LIB@ + +Name: kdb +Description: Kerberos database access libraries +Version: @KRB5_VERSION@ +Requires.private: mit-krb5-gssapi mit-krb5 gssrpc +Cflags: -I${includedir} +Libs: -L${libdir} -lkdb5 +Libs.private: ${KDB5_DB_LIB} diff --git a/krb5-1.21.3/src/build-tools/krb5-config.in b/krb5-1.21.3/src/build-tools/krb5-config.in new file mode 100755 index 00000000..8e6eb866 --- /dev/null +++ b/krb5-1.21.3/src/build-tools/krb5-config.in @@ -0,0 +1,262 @@ +#!/bin/sh + +# Copyright 2001, 2002, 2003 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. +# +# + +# Configurable parameters set by autoconf +version_string="Kerberos 5 release @KRB5_VERSION@" + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +includedir=@includedir@ +libdir=@libdir@ +CC_LINK='@CC_LINK@' +KDB5_DB_LIB=@KDB5_DB_LIB@ +RPATH_FLAG='@RPATH_FLAG@' +PROG_RPATH_FLAGS='@PROG_RPATH_FLAGS@' +PTHREAD_CFLAGS='@PTHREAD_CFLAGS@' +DL_LIB='@DL_LIB@' +DEFCCNAME='@DEFCCNAME@' +DEFKTNAME='@DEFKTNAME@' +DEFCKTNAME='@DEFCKTNAME@' + +LIBS='@LIBS@' +GEN_LIB=@GEN_LIB@ + +# Defaults for program +library=krb5 + +# Some constants +vendor_string="Massachusetts Institute of Technology" + +# Process arguments +# Yes, we are sloppy, library specifications can come before options +while test $# != 0; do + case $1 in + --all) + do_all=1 + ;; + --cflags) + do_cflags=1 + ;; + --defccname) + do_defccname=1 + ;; + --defcktname) + do_defcktname=1 + ;; + --defktname) + do_defktname=1 + ;; + --deps) # historically a no-op + ;; + --exec-prefix) + do_exec_prefix=1 + ;; + --help) + do_help=1 + ;; + --libs) + do_libs=1 + ;; + --prefix) + do_prefix=1 + ;; + --vendor) + do_vendor=1 + ;; + --version) + do_version=1 + ;; + krb5) + library=krb5 + ;; + gssapi) + library=gssapi + ;; + gssrpc) + library=gssrpc + ;; + kadm-client) + library=kadm_client + ;; + kadm-server) + library=kadm_server + ;; + kdb) + library=kdb + ;; + *) + echo "$0: Unknown option \`$1' -- use \`--help' for usage" + exit 1 + esac + shift +done + +# If required options - provide help +if test -z "$do_all" -a -z "$do_version" -a -z "$do_vendor" -a \ + -z "$do_prefix" -a -z "$do_vendor" -a -z "$do_exec_prefix" -a \ + -z "$do_defccname" -a -z "$do_defktname" -a -z "$do_defcktname" -a \ + -z "$do_cflags" -a -z "$do_libs"; then + do_help=1 +fi + + +if test -n "$do_help"; then + echo "Usage: $0 [OPTIONS] [LIBRARIES]" + echo "Options:" + echo " [--help] Help" + echo " [--all] Display version, vendor, and various values" + echo " [--version] Version information" + echo " [--vendor] Vendor information" + echo " [--prefix] Kerberos installed prefix" + echo " [--exec-prefix] Kerberos installed exec_prefix" + echo " [--defccname] Show built-in default ccache name" + echo " [--defktname] Show built-in default keytab name" + echo " [--defcktname] Show built-in default client keytab name" + echo " [--cflags] Compile time CFLAGS" + echo " [--libs] List libraries required to link [LIBRARIES]" + echo "Libraries:" + echo " krb5 Kerberos 5 application" + echo " gssapi GSSAPI application with Kerberos 5 bindings" + echo " gssrpc GSSAPI RPC application" + echo " kadm-client Kadmin client" + echo " kadm-server Kadmin server" + echo " kdb Application that accesses the kerberos database" + exit 0 +fi + +if test -n "$do_all"; then + all_exit= + do_version=1 + do_prefix=1 + do_exec_prefix=1 + do_vendor=1 + title_version="Version: " + title_prefix="Prefix: " + title_exec_prefix="Exec_prefix: " + title_vendor="Vendor: " +else + all_exit="exit 0" +fi + +if test -n "$do_version"; then + echo "$title_version$version_string" + $all_exit +fi + +if test -n "$do_vendor"; then + echo "$title_vendor$vendor_string" + $all_exit +fi + +if test -n "$do_prefix"; then + echo "$title_prefix$prefix" + $all_exit +fi + +if test -n "$do_exec_prefix"; then + echo "$title_exec_prefix$exec_prefix" + $all_exit +fi + +if test -n "$do_defccname"; then + echo "$DEFCCNAME" + $all_exit +fi + +if test -n "$do_defktname"; then + echo "$DEFKTNAME" + $all_exit +fi + +if test -n "$do_defcktname"; then + echo "$DEFCKTNAME" + $all_exit +fi + +if test -n "$do_cflags"; then + if test x"$includedir" != x"/usr/include" ; then + echo "-I${includedir}" + else + echo '' + fi +fi + + +if test -n "$do_libs"; then + # Assumes /usr/lib is the standard library directory everywhere... + if test "$libdir" = /usr/lib; then + libdirarg= + else + libdirarg="-L$libdir" + fi + # Ugly gross hack for our build tree + lib_flags=`echo $CC_LINK | sed -e 's/\$(CC)//' \ + -e 's/\$(PURE)//' \ + -e 's#\$(PROG_RPATH_FLAGS)#'"$PROG_RPATH_FLAGS"'#' \ + -e 's#\$(PROG_RPATH)#'$libdir'#' \ + -e 's#\$(PROG_LIBPATH)#'$libdirarg'#' \ + -e 's#\$(RPATH_FLAG)#'"$RPATH_FLAG"'#' \ + -e 's#\$(LDFLAGS)##' \ + -e 's#\$(PTHREAD_CFLAGS)#'"$PTHREAD_CFLAGS"'#' \ + -e 's#\$(CFLAGS)##'` + + if test $library = 'kdb'; then + lib_flags="$lib_flags -lkdb5 $KDB5_DB_LIB" + library=krb5 + fi + + if test $library = 'kadm_server'; then + lib_flags="$lib_flags -lkadm5srv_mit -lkdb5 $KDB5_DB_LIB" + library=gssrpc + fi + + if test $library = 'kadm_client'; then + lib_flags="$lib_flags -lkadm5clnt_mit" + library=gssrpc + fi + + if test $library = 'gssrpc'; then + lib_flags="$lib_flags -lgssrpc" + library=gssapi + fi + + if test $library = 'gssapi'; then + lib_flags="$lib_flags -lgssapi_krb5" + library=krb5 + fi + + if test $library = 'krb5'; then + lib_flags="$lib_flags -lkrb5 -lk5crypto @COM_ERR_LIB@" + fi + + # If we ever support a flag to generate output suitable for static + # linking, we would output "-lkrb5support $GEN_LIB $LIBS $DL_LIB" + # here. + + echo $lib_flags +fi + +exit 0 diff --git a/krb5-1.21.3/src/build-tools/krb5-gssapi.pc.in b/krb5-1.21.3/src/build-tools/krb5-gssapi.pc.in new file mode 100644 index 00000000..4e2d8324 --- /dev/null +++ b/krb5-1.21.3/src/build-tools/krb5-gssapi.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +vendor=MIT + +Name: krb5-gssapi +Description: Kerberos implementation of the GSSAPI +Version: @KRB5_VERSION@ +Requires: mit-krb5-gssapi diff --git a/krb5-1.21.3/src/build-tools/krb5.pc.in b/krb5-1.21.3/src/build-tools/krb5.pc.in new file mode 100644 index 00000000..5f810496 --- /dev/null +++ b/krb5-1.21.3/src/build-tools/krb5.pc.in @@ -0,0 +1,14 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ +vendor=MIT + +defccname=@DEFCCNAME@ +defktname=@DEFKTNAME@ +defcktname=@DEFCKTNAME@ + +Name: krb5 +Description: An implementation of Kerberos network authentication +Version: @KRB5_VERSION@ +Requires: mit-krb5 diff --git a/krb5-1.21.3/src/build-tools/mit-krb5-gssapi.pc.in b/krb5-1.21.3/src/build-tools/mit-krb5-gssapi.pc.in new file mode 100644 index 00000000..7b91b19f --- /dev/null +++ b/krb5-1.21.3/src/build-tools/mit-krb5-gssapi.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: mit-krb5-gssapi +Description: Kerberos implementation of the GSSAPI +Version: @KRB5_VERSION@ +Requires.private: mit-krb5 +Cflags: -I${includedir} +Libs: -L${libdir} -lgssapi_krb5 diff --git a/krb5-1.21.3/src/build-tools/mit-krb5.pc.in b/krb5-1.21.3/src/build-tools/mit-krb5.pc.in new file mode 100644 index 00000000..fdc55778 --- /dev/null +++ b/krb5-1.21.3/src/build-tools/mit-krb5.pc.in @@ -0,0 +1,15 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +defccname=@DEFCCNAME@ +defktname=@DEFKTNAME@ +defcktname=@DEFCKTNAME@ + +Name: mit-krb5 +Description: An implementation of Kerberos network authentication +Version: @KRB5_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -lkrb5 -lk5crypto @COM_ERR_LIB@ +Libs.private: -lkrb5support diff --git a/krb5-1.21.3/src/build-tools/t_krbconf b/krb5-1.21.3/src/build-tools/t_krbconf new file mode 100644 index 00000000..5a141f5f --- /dev/null +++ b/krb5-1.21.3/src/build-tools/t_krbconf @@ -0,0 +1,38 @@ +#!/bin/sh + +# Copyright 2003 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +echo "Testing if krb5-config outputs shell variables" +echo " Testing --libs argument" +if ./krb5-config --libs kdb | egrep -s '\$' > /dev/null; then + echo "Error './krb5-config --libs kdb' contains shell variables" + exit 1 +fi + +echo " Testing --cflags argument" +if ./krb5-config --cflags | egrep -s '\$' > /dev/null; then + echo "Error './krb5-config --cflags' contains shell variables" + exit 1 +fi +echo "krb5-config tests pass" +exit 0 diff --git a/krb5-1.21.3/src/ccapi/Makefile.in b/krb5-1.21.3/src/ccapi/Makefile.in new file mode 100644 index 00000000..3f80d87e --- /dev/null +++ b/krb5-1.21.3/src/ccapi/Makefile.in @@ -0,0 +1,5 @@ +mydir=ccapi +BUILDTOP=$(REL).. + +SUBDIRS= lib server test +WINSUBDIRS= lib\win server\win test diff --git a/krb5-1.21.3/src/ccapi/common/Makefile.in b/krb5-1.21.3/src/ccapi/common/Makefile.in new file mode 100644 index 00000000..b51cfe2b --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/Makefile.in @@ -0,0 +1,65 @@ +mydir=ccapi$(S)common +BUILDTOP=$(REL)..$(S).. +SUBDIRS=unix + +SRCS= \ + cci_array_internal.c \ + cci_cred_union.c \ + cci_debugging.c \ + cci_identifier.c \ + cci_message.c \ + cci_stream.c + +STLIBOBJS= \ + cci_array_internal.o \ + cci_cred_union.o \ + cci_debugging.o \ + cci_identifier.o \ + cci_message.o \ + cci_stream.o + +OBJS= \ + $(OUTPRE)cci_array_internal.$(OBJEXT) \ + $(OUTPRE)cci_cred_union.$(OBJEXT) \ + $(OUTPRE)cci_debugging.$(OBJEXT) \ + $(OUTPRE)cci_identifier.$(OBJEXT) \ + $(OUTPRE)cci_message.$(OBJEXT) \ + $(OUTPRE)cci_stream.$(OBJEXT) + +all-unix: all-libobjs +clean-unix:: clean-libobjs + +@libobj_frag@ + +# +++ Dependency line eater +++ +# +# Makefile dependencies follow. This must be the last section in +# the Makefile.in file +# +cci_array_internal.so cci_array_internal.po $(OUTPRE)cci_array_internal.$(OBJEXT): \ + $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + cci_array_internal.c cci_array_internal.h cci_common.h \ + cci_cred_union.h cci_debugging.h cci_identifier.h cci_message.h \ + cci_stream.h cci_types.h +cci_cred_union.so cci_cred_union.po $(OUTPRE)cci_cred_union.$(OBJEXT): \ + $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + cci_common.h cci_cred_union.c cci_cred_union.h cci_debugging.h \ + cci_identifier.h cci_message.h cci_stream.h cci_types.h +cci_debugging.so cci_debugging.po $(OUTPRE)cci_debugging.$(OBJEXT): \ + $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + cci_common.h cci_cred_union.h cci_debugging.c cci_debugging.h \ + cci_identifier.h cci_message.h cci_os_debugging.h cci_stream.h \ + cci_types.h +cci_identifier.so cci_identifier.po $(OUTPRE)cci_identifier.$(OBJEXT): \ + $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + cci_common.h cci_cred_union.h cci_debugging.h cci_identifier.c \ + cci_identifier.h cci_message.h cci_os_identifier.h \ + cci_stream.h cci_types.h +cci_message.so cci_message.po $(OUTPRE)cci_message.$(OBJEXT): \ + $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + cci_common.h cci_cred_union.h cci_debugging.h cci_identifier.h \ + cci_message.c cci_message.h cci_stream.h cci_types.h +cci_stream.so cci_stream.po $(OUTPRE)cci_stream.$(OBJEXT): \ + $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + cci_common.h cci_cred_union.h cci_debugging.h cci_identifier.h \ + cci_message.h cci_stream.c cci_stream.h cci_types.h diff --git a/krb5-1.21.3/src/ccapi/common/cci_array_internal.c b/krb5-1.21.3/src/ccapi/common/cci_array_internal.c new file mode 100644 index 00000000..7a205d72 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_array_internal.c @@ -0,0 +1,312 @@ +/* ccapi/common/cci_array_internal.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "cci_common.h" +#include "cci_array_internal.h" + +#ifdef WIN32 +#include "k5-platform.h" +#endif + +/* ------------------------------------------------------------------------ */ + +struct cci_array_d { + cci_array_object_t *objects; + cc_uint64 count; + cc_uint64 max_count; + + cci_array_object_release_t object_release; +}; + +struct cci_array_d cci_array_initializer = { NULL, 0, 0, NULL }; + +#define CCI_ARRAY_COUNT_INCREMENT 16 + +/* ------------------------------------------------------------------------ */ + +static cc_int32 cci_array_resize (cci_array_t io_array, + cc_uint64 in_new_count) +{ + cc_int32 err = ccNoError; + cc_uint64 new_max_count = 0; + + if (!io_array) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_uint64 old_max_count = io_array->max_count; + new_max_count = io_array->max_count; + + if (in_new_count > old_max_count) { + /* Expand the array */ + while (in_new_count > new_max_count) { + new_max_count += CCI_ARRAY_COUNT_INCREMENT; + } + + } else if ((in_new_count + CCI_ARRAY_COUNT_INCREMENT) < old_max_count) { + /* Shrink the array, but never drop below CC_ARRAY_COUNT_INCREMENT */ + while ((in_new_count + CCI_ARRAY_COUNT_INCREMENT) < new_max_count && + (new_max_count > CCI_ARRAY_COUNT_INCREMENT)) { + new_max_count -= CCI_ARRAY_COUNT_INCREMENT; + } + } + } + + if (!err && io_array->max_count != new_max_count) { + cci_array_object_t *objects = io_array->objects; + + if (!objects) { + objects = malloc (new_max_count * sizeof (*objects)); + } else { + objects = realloc (objects, new_max_count * sizeof (*objects)); + } + if (!objects) { err = cci_check_error (ccErrNoMem); } + + if (!err) { + io_array->objects = objects; + io_array->max_count = new_max_count; + } + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_array_new (cci_array_t *out_array, + cci_array_object_release_t in_array_object_release) +{ + cc_int32 err = ccNoError; + cci_array_t array = NULL; + + if (!out_array) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + array = malloc (sizeof (*array)); + if (array) { + *array = cci_array_initializer; + array->object_release = in_array_object_release; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + *out_array = array; + array = NULL; + } + + cci_array_release (array); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_array_release (cci_array_t io_array) +{ + cc_int32 err = ccNoError; + + if (!err && io_array) { + cc_uint64 i; + + if (io_array->object_release) { + for (i = 0; i < io_array->count; i++) { + io_array->object_release (io_array->objects[i]); + } + } + free (io_array->objects); + free (io_array); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_uint64 cci_array_count (cci_array_t in_array) +{ + return in_array ? in_array->count : 0; +} + +/* ------------------------------------------------------------------------ */ + +cci_array_object_t cci_array_object_at_index (cci_array_t io_array, + cc_uint64 in_position) +{ + if (io_array && in_position < io_array->count) { + return io_array->objects[in_position]; + } else { + if (!io_array) { + cci_debug_printf ("%s() got NULL array", __FUNCTION__); + } else { + cci_debug_printf ("%s() got bad index %lld (count = %lld)", __FUNCTION__, + in_position, io_array->count); + } + return NULL; + } +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_array_insert (cci_array_t io_array, + cci_array_object_t in_object, + cc_uint64 in_position) +{ + cc_int32 err = ccNoError; + + if (!io_array ) { err = cci_check_error (ccErrBadParam); } + if (!in_object) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + /* Don't try to insert past the end and don't overflow the array */ + if (in_position > io_array->count || io_array->count == UINT64_MAX) { + err = cci_check_error (ccErrBadParam); + } + } + + if (!err) { + err = cci_array_resize (io_array, io_array->count + 1); + } + + if (!err) { + cc_uint64 move_count = io_array->count - in_position; + + if (move_count > 0) { + memmove (&io_array->objects[in_position + 1], &io_array->objects[in_position], + move_count * sizeof (*io_array->objects)); + } + + io_array->objects[in_position] = in_object; + io_array->count++; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_array_remove (cci_array_t io_array, + cc_uint64 in_position) +{ + cc_int32 err = ccNoError; + + if (!io_array) { err = cci_check_error (ccErrBadParam); } + + if (!err && in_position >= io_array->count) { + err = cci_check_error (ccErrBadParam); + } + + if (!err) { + cc_uint64 move_count = io_array->count - in_position - 1; + cci_array_object_t object = io_array->objects[in_position]; + + if (move_count > 0) { + memmove (&io_array->objects[in_position], &io_array->objects[in_position + 1], + move_count * sizeof (*io_array->objects)); + } + io_array->count--; + + if (io_array->object_release) { io_array->object_release (object); } + + cci_array_resize (io_array, io_array->count); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_array_move (cci_array_t io_array, + cc_uint64 in_position, + cc_uint64 in_new_position, + cc_uint64 *out_real_new_position) +{ + cc_int32 err = ccNoError; + + if (!io_array ) { err = cci_check_error (ccErrBadParam); } + if (!out_real_new_position) { err = cci_check_error (ccErrBadParam); } + + if (!err && in_position >= io_array->count) { + err = cci_check_error (ccErrBadParam); + } + + if (!err && in_new_position > io_array->count) { + err = cci_check_error (ccErrBadParam); + } + if (!err) { + cc_uint64 move_from = 0; + cc_uint64 move_to = 0; + cc_uint64 move_count = 0; + cc_uint64 real_new_position = 0; + + if (in_position < in_new_position) { + /* shift right, making an empty space so the + * actual new position is one less in_new_position */ + move_from = in_position + 1; + move_to = in_position; + move_count = in_new_position - in_position - 1; + real_new_position = in_new_position - 1; + + } else if (in_position > in_new_position) { + /* shift left */ + move_from = in_new_position; + move_to = in_new_position + 1; + move_count = in_position - in_new_position; + real_new_position = in_new_position; + + } else { + real_new_position = in_new_position; + } + + if (move_count > 0) { + cci_array_object_t object = io_array->objects[in_position]; + + memmove (&io_array->objects[move_to], &io_array->objects[move_from], + move_count * sizeof (*io_array->objects)); + io_array->objects[real_new_position] = object; + } + + *out_real_new_position = real_new_position; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_array_push_front (cci_array_t io_array, + cc_uint64 in_position) +{ + cc_uint64 real_new_position = 0; + return cci_array_move (io_array, in_position, 0, &real_new_position); +} diff --git a/krb5-1.21.3/src/ccapi/common/cci_array_internal.h b/krb5-1.21.3/src/ccapi/common/cci_array_internal.h new file mode 100644 index 00000000..364de767 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_array_internal.h @@ -0,0 +1,65 @@ +/* ccapi/common/cci_array_internal.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCI_ARRAY_INTERNAL_H +#define CCI_ARRAY_INTERNAL_H + +#include "cci_types.h" + +struct cci_array_object_d; +typedef struct cci_array_object_d *cci_array_object_t; + +typedef cc_int32 (*cci_array_object_release_t) (cci_array_object_t); + +struct cci_array_d; +typedef struct cci_array_d *cci_array_t; + +cc_int32 cci_array_new (cci_array_t *out_array, + cci_array_object_release_t in_array_object_release); + +cc_int32 cci_array_release (cci_array_t io_array); + +cc_uint64 cci_array_count (cci_array_t in_array); + +cci_array_object_t cci_array_object_at_index (cci_array_t io_array, + cc_uint64 in_position); + +cc_int32 cci_array_insert (cci_array_t io_array, + cci_array_object_t in_object, + cc_uint64 in_position); + +cc_int32 cci_array_remove (cci_array_t io_array, + cc_uint64 in_position); + +cc_int32 cci_array_move (cci_array_t io_array, + cc_uint64 in_position, + cc_uint64 in_new_position, + cc_uint64 *out_real_new_position); + +cc_int32 cci_array_push_front (cci_array_t io_array, + cc_uint64 in_position); + + +#endif /* CCI_ARRAY_INTERNAL_H */ diff --git a/krb5-1.21.3/src/ccapi/common/cci_common.h b/krb5-1.21.3/src/ccapi/common/cci_common.h new file mode 100644 index 00000000..ec9d10b9 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_common.h @@ -0,0 +1,56 @@ +/* ccapi/common/cci_common.h */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCI_COMMON_H +#define CCI_COMMON_H + +#include + +#include +#include +#include +#include +#include +#include +#include + +#if TARGET_OS_MAC +#include +#define VECTOR_FUNCTIONS_INITIALIZER ,NULL +#else +#include "win-mac.h" +#define VECTOR_FUNCTIONS_INITIALIZER +#endif + +#define k_cci_context_initial_ccache_name "Initial default ccache" + +#include "cci_cred_union.h" +#include "cci_debugging.h" +#include "cci_identifier.h" +#include "cci_message.h" + +#include "k5-ipc_stream.h" + +#endif /* CCI_COMMON_H */ diff --git a/krb5-1.21.3/src/ccapi/common/cci_cred_union.c b/krb5-1.21.3/src/ccapi/common/cci_cred_union.c new file mode 100644 index 00000000..424a93da --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_cred_union.c @@ -0,0 +1,848 @@ +/* ccapi/common/cci_cred_union.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "cci_common.h" + +/* ------------------------------------------------------------------------ */ + +static cc_uint32 cci_cc_data_contents_release (cc_data *io_ccdata) +{ + cc_int32 err = ccNoError; + + if (!io_ccdata && io_ccdata->data) { err = ccErrBadParam; } + + if (!err) { + if (io_ccdata->length) { + memset (io_ccdata->data, 0, io_ccdata->length); + } + free (io_ccdata->data); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static cc_uint32 cci_cc_data_release (cc_data *io_ccdata) +{ + cc_int32 err = ccNoError; + + if (!io_ccdata) { err = ccErrBadParam; } + + if (!err) { + cci_cc_data_contents_release (io_ccdata); + free (io_ccdata); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static cc_uint32 cci_cc_data_read (cc_data *io_ccdata, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + cc_uint32 type = 0; + cc_uint32 length = 0; + char *data = NULL; + + if (!io_stream) { err = cci_check_error (ccErrBadParam); } + if (!io_ccdata) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (io_stream, &type); + } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (io_stream, &length); + } + + if (!err && length > 0) { + data = malloc (length); + if (!data) { err = cci_check_error (ccErrNoMem); } + + if (!err) { + err = krb5int_ipc_stream_read (io_stream, data, length); + } + } + + if (!err) { + io_ccdata->type = type; + io_ccdata->length = length; + io_ccdata->data = data; + data = NULL; + } + + free (data); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_uint32 cci_cc_data_write (cc_data *in_ccdata, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + + if (!io_stream) { err = cci_check_error (ccErrBadParam); } + if (!in_ccdata) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (io_stream, in_ccdata->type); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (io_stream, in_ccdata->length); + } + + if (!err && in_ccdata->length > 0) { + err = krb5int_ipc_stream_write (io_stream, in_ccdata->data, in_ccdata->length); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_uint32 cci_cc_data_array_release (cc_data **io_ccdata_array) +{ + cc_int32 err = ccNoError; + + if (!io_ccdata_array) { err = ccErrBadParam; } + + if (!err) { + cc_uint32 i; + + for (i = 0; io_ccdata_array && io_ccdata_array[i]; i++) { + cci_cc_data_release (io_ccdata_array[i]); + } + free (io_ccdata_array); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static cc_uint32 cci_cc_data_array_read (cc_data ***io_ccdata_array, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + cc_uint32 count = 0; + cc_data **array = NULL; + cc_uint32 i; + + if (!io_stream ) { err = cci_check_error (ccErrBadParam); } + if (!io_ccdata_array) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (io_stream, &count); + } + + if (!err && count > 0) { + array = malloc ((count + 1) * sizeof (*array)); + if (array) { + for (i = 0; i <= count; i++) { array[i] = NULL; } + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + for (i = 0; !err && i < count; i++) { + array[i] = malloc (sizeof (cc_data)); + if (!array[i]) { err = cci_check_error (ccErrNoMem); } + + if (!err) { + err = cci_cc_data_read (array[i], io_stream); + } + } + } + + if (!err) { + *io_ccdata_array = array; + array = NULL; + } + + cci_cc_data_array_release (array); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_uint32 cci_cc_data_array_write (cc_data **in_ccdata_array, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + cc_uint32 count = 0; + + if (!io_stream) { err = cci_check_error (ccErrBadParam); } + /* in_ccdata_array may be NULL */ + + if (!err) { + for (count = 0; in_ccdata_array && in_ccdata_array[count]; count++); + + err = krb5int_ipc_stream_write_uint32 (io_stream, count); + } + + if (!err) { + cc_uint32 i; + + for (i = 0; !err && i < count; i++) { + err = cci_cc_data_write (in_ccdata_array[i], io_stream); + } + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_credentials_v5_t cci_credentials_v5_initializer = { + NULL, + NULL, + { 0, 0, NULL }, + 0, 0, 0, 0, 0, 0, + NULL, + { 0, 0, NULL }, + { 0, 0, NULL }, + NULL +}; + +/* ------------------------------------------------------------------------ */ + +static cc_uint32 cci_credentials_v5_release (cc_credentials_v5_t *io_v5creds) +{ + cc_int32 err = ccNoError; + + if (!io_v5creds) { err = ccErrBadParam; } + + if (!err) { + free (io_v5creds->client); + free (io_v5creds->server); + cci_cc_data_contents_release (&io_v5creds->keyblock); + cci_cc_data_array_release (io_v5creds->addresses); + cci_cc_data_contents_release (&io_v5creds->ticket); + cci_cc_data_contents_release (&io_v5creds->second_ticket); + cci_cc_data_array_release (io_v5creds->authdata); + free (io_v5creds); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static cc_uint32 cci_credentials_v5_read (cc_credentials_v5_t **out_v5creds, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + cc_credentials_v5_t *v5creds = NULL; + + if (!io_stream ) { err = cci_check_error (ccErrBadParam); } + if (!out_v5creds) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + v5creds = malloc (sizeof (*v5creds)); + if (v5creds) { + *v5creds = cci_credentials_v5_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = krb5int_ipc_stream_read_string (io_stream, &v5creds->client); + } + + if (!err) { + err = krb5int_ipc_stream_read_string (io_stream, &v5creds->server); + } + + if (!err) { + err = cci_cc_data_read (&v5creds->keyblock, io_stream); + } + + if (!err) { + err = krb5int_ipc_stream_read_time (io_stream, &v5creds->authtime); + } + + if (!err) { + err = krb5int_ipc_stream_read_time (io_stream, &v5creds->starttime); + } + + if (!err) { + err = krb5int_ipc_stream_read_time (io_stream, &v5creds->endtime); + } + + if (!err) { + err = krb5int_ipc_stream_read_time (io_stream, &v5creds->renew_till); + } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (io_stream, &v5creds->is_skey); + } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (io_stream, &v5creds->ticket_flags); + } + + if (!err) { + err = cci_cc_data_array_read (&v5creds->addresses, io_stream); + } + + if (!err) { + err = cci_cc_data_read (&v5creds->ticket, io_stream); + } + + if (!err) { + err = cci_cc_data_read (&v5creds->second_ticket, io_stream); + } + + if (!err) { + err = cci_cc_data_array_read (&v5creds->authdata, io_stream); + } + + if (!err) { + *out_v5creds = v5creds; + v5creds = NULL; + } + + cci_credentials_v5_release (v5creds); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_uint32 cci_credentials_v5_write (cc_credentials_v5_t *in_v5creds, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + + if (!io_stream ) { err = cci_check_error (ccErrBadParam); } + if (!in_v5creds) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_write_string (io_stream, in_v5creds->client); + } + + if (!err) { + err = krb5int_ipc_stream_write_string (io_stream, in_v5creds->server); + } + + if (!err) { + err = cci_cc_data_write (&in_v5creds->keyblock, io_stream); + } + + if (!err) { + err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->authtime); + } + + if (!err) { + err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->starttime); + } + + if (!err) { + err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->endtime); + } + + if (!err) { + err = krb5int_ipc_stream_write_time (io_stream, in_v5creds->renew_till); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (io_stream, in_v5creds->is_skey); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (io_stream, in_v5creds->ticket_flags); + } + + if (!err) { + err = cci_cc_data_array_write (in_v5creds->addresses, io_stream); + } + + if (!err) { + err = cci_cc_data_write (&in_v5creds->ticket, io_stream); + } + + if (!err) { + err = cci_cc_data_write (&in_v5creds->second_ticket, io_stream); + } + + if (!err) { + err = cci_cc_data_array_write (in_v5creds->authdata, io_stream); + } + + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_uint32 cci_credentials_union_release (cc_credentials_union *io_cred_union) +{ + cc_int32 err = ccNoError; + + if (!io_cred_union) { err = ccErrBadParam; } + + if (!err) { + if (io_cred_union->version == cc_credentials_v5) { + cci_credentials_v5_release (io_cred_union->credentials.credentials_v5); + } + free (io_cred_union); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_uint32 cci_credentials_union_read (cc_credentials_union **out_credentials_union, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + cc_credentials_union *credentials_union = NULL; + + if (!io_stream ) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials_union) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + credentials_union = calloc (1, sizeof (*credentials_union)); + if (!credentials_union) { err = cci_check_error (ccErrNoMem); } + } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (io_stream, &credentials_union->version); + } + + if (!err) { + if (credentials_union->version == cc_credentials_v5) { + err = cci_credentials_v5_read (&credentials_union->credentials.credentials_v5, + io_stream); + + + } else { + err = ccErrBadCredentialsVersion; + } + } + + if (!err) { + *out_credentials_union = credentials_union; + credentials_union = NULL; + } + + if (credentials_union) { cci_credentials_union_release (credentials_union); } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint32 cci_credentials_union_write (const cc_credentials_union *in_credentials_union, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + + if (!io_stream ) { err = cci_check_error (ccErrBadParam); } + if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (io_stream, in_credentials_union->version); + } + + if (!err) { + if (in_credentials_union->version == cc_credentials_v5) { + err = cci_credentials_v5_write (in_credentials_union->credentials.credentials_v5, + io_stream); + + } else { + err = ccErrBadCredentialsVersion; + } + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#pragma mark -- CCAPI v2 Compat -- +#endif + +/* ------------------------------------------------------------------------ */ + +cc_credentials_v5_compat cci_credentials_v5_compat_initializer = { + NULL, + NULL, + { 0, 0, NULL }, + 0, 0, 0, 0, 0, 0, + NULL, + { 0, 0, NULL }, + { 0, 0, NULL }, + NULL +}; + +/* ------------------------------------------------------------------------ */ + +cc_uint32 cci_cred_union_release (cred_union *io_cred_union) +{ + cc_int32 err = ccNoError; + + if (!io_cred_union) { err = ccErrBadParam; } + + if (!err) { + if (io_cred_union->cred_type == CC_CRED_V5) { + free (io_cred_union->cred.pV5Cred->client); + free (io_cred_union->cred.pV5Cred->server); + cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->keyblock); + cci_cc_data_array_release (io_cred_union->cred.pV5Cred->addresses); + cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->ticket); + cci_cc_data_contents_release (&io_cred_union->cred.pV5Cred->second_ticket); + cci_cc_data_array_release (io_cred_union->cred.pV5Cred->authdata); + free (io_cred_union->cred.pV5Cred); + } + free (io_cred_union); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static cc_uint32 cci_cc_data_copy_contents (cc_data *io_ccdata, + cc_data *in_ccdata) +{ + cc_int32 err = ccNoError; + char *data = NULL; + + if (!io_ccdata) { err = cci_check_error (ccErrBadParam); } + if (!in_ccdata) { err = cci_check_error (ccErrBadParam); } + + if (!err && in_ccdata->length > 0) { + data = malloc (in_ccdata->length); + if (data) { + memcpy (data, in_ccdata->data, in_ccdata->length); + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + io_ccdata->type = in_ccdata->type; + io_ccdata->length = in_ccdata->length; + io_ccdata->data = data; + data = NULL; + } + + free (data); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_uint32 cci_cc_data_array_copy (cc_data ***io_ccdata_array, + cc_data **in_ccdata_array) +{ + cc_int32 err = ccNoError; + cc_uint32 count = 0; + cc_data **array = NULL; + cc_uint32 i; + + if (!io_ccdata_array) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + for (count = 0; in_ccdata_array && in_ccdata_array[count]; count++); + } + + if (!err && count > 0) { + array = malloc ((count + 1) * sizeof (*array)); + if (array) { + for (i = 0; i <= count; i++) { array[i] = NULL; } + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + for (i = 0; !err && i < count; i++) { + array[i] = malloc (sizeof (cc_data)); + if (!array[i]) { err = cci_check_error (ccErrNoMem); } + + if (!err) { + err = cci_cc_data_copy_contents (array[i], in_ccdata_array[i]); + } + } + } + + if (!err) { + *io_ccdata_array = array; + array = NULL; + } + + cci_cc_data_array_release (array); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint32 cci_credentials_union_to_cred_union (const cc_credentials_union *in_credentials_union, + cred_union **out_cred_union) +{ + cc_int32 err = ccNoError; + cred_union *compat_cred_union = NULL; + + if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); } + if (!out_cred_union ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + compat_cred_union = calloc (1, sizeof (*compat_cred_union)); + if (!compat_cred_union) { err = cci_check_error (ccErrNoMem); } + } + + if (!err) { + if (in_credentials_union->version == cc_credentials_v5) { + cc_credentials_v5_t *v5creds = in_credentials_union->credentials.credentials_v5; + cc_credentials_v5_compat *compat_v5creds = NULL; + + compat_v5creds = malloc (sizeof (*compat_v5creds)); + if (compat_v5creds) { + *compat_v5creds = cci_credentials_v5_compat_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + + if (!err) { + if (!v5creds->client) { + err = cci_check_error (ccErrBadParam); + } else { + compat_v5creds->client = strdup (v5creds->client); + if (!compat_v5creds->client) { err = cci_check_error (ccErrNoMem); } + } + } + + if (!err) { + if (!v5creds->server) { + err = cci_check_error (ccErrBadParam); + } else { + compat_v5creds->server = strdup (v5creds->server); + if (!compat_v5creds->server) { err = cci_check_error (ccErrNoMem); } + } + } + + if (!err) { + err = cci_cc_data_copy_contents (&compat_v5creds->keyblock, &v5creds->keyblock); + } + + if (!err) { + err = cci_cc_data_array_copy (&compat_v5creds->addresses, v5creds->addresses); + } + + if (!err) { + err = cci_cc_data_copy_contents (&compat_v5creds->ticket, &v5creds->ticket); + } + + if (!err) { + err = cci_cc_data_copy_contents (&compat_v5creds->second_ticket, &v5creds->second_ticket); + } + + if (!err) { + err = cci_cc_data_array_copy (&compat_v5creds->authdata, v5creds->authdata); + } + + if (!err) { + compat_cred_union->cred_type = CC_CRED_V5; + compat_cred_union->cred.pV5Cred = compat_v5creds; + + compat_v5creds->keyblock = v5creds->keyblock; + compat_v5creds->authtime = v5creds->authtime; + compat_v5creds->starttime = v5creds->starttime; + compat_v5creds->endtime = v5creds->endtime; + compat_v5creds->renew_till = v5creds->renew_till; + compat_v5creds->is_skey = v5creds->is_skey; + compat_v5creds->ticket_flags = v5creds->ticket_flags; + } + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + if (!err) { + *out_cred_union = compat_cred_union; + compat_cred_union = NULL; + } + + if (compat_cred_union) { cci_cred_union_release (compat_cred_union); } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint32 cci_cred_union_to_credentials_union (const cred_union *in_cred_union, + cc_credentials_union **out_credentials_union) +{ + cc_int32 err = ccNoError; + cc_credentials_union *creds_union = NULL; + + if (!in_cred_union ) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials_union) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + creds_union = calloc (1, sizeof (*creds_union)); + if (!creds_union) { err = cci_check_error (ccErrNoMem); } + } + + if (!err) { + if (in_cred_union->cred_type == CC_CRED_V5) { + cc_credentials_v5_compat *compat_v5creds = in_cred_union->cred.pV5Cred; + cc_credentials_v5_t *v5creds = NULL; + + if (!err) { + v5creds = malloc (sizeof (*v5creds)); + if (v5creds) { + *v5creds = cci_credentials_v5_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + if (!compat_v5creds->client) { + err = cci_check_error (ccErrBadParam); + } else { + v5creds->client = strdup (compat_v5creds->client); + if (!v5creds->client) { err = cci_check_error (ccErrNoMem); } + } + } + + if (!err) { + if (!compat_v5creds->server) { + err = cci_check_error (ccErrBadParam); + } else { + v5creds->server = strdup (compat_v5creds->server); + if (!v5creds->server) { err = cci_check_error (ccErrNoMem); } + } + } + + if (!err) { + err = cci_cc_data_copy_contents (&v5creds->keyblock, &compat_v5creds->keyblock); + } + + if (!err) { + err = cci_cc_data_array_copy (&v5creds->addresses, compat_v5creds->addresses); + } + + if (!err) { + err = cci_cc_data_copy_contents (&v5creds->ticket, &compat_v5creds->ticket); + } + + if (!err) { + err = cci_cc_data_copy_contents (&v5creds->second_ticket, &compat_v5creds->second_ticket); + } + + if (!err) { + err = cci_cc_data_array_copy (&v5creds->authdata, compat_v5creds->authdata); + } + + if (!err) { + creds_union->version = cc_credentials_v5; + creds_union->credentials.credentials_v5 = v5creds; + + v5creds->authtime = compat_v5creds->authtime; + v5creds->starttime = compat_v5creds->starttime; + v5creds->endtime = compat_v5creds->endtime; + v5creds->renew_till = compat_v5creds->renew_till; + v5creds->is_skey = compat_v5creds->is_skey; + v5creds->ticket_flags = compat_v5creds->ticket_flags; + } + + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + if (!err) { + *out_credentials_union = creds_union; + creds_union = NULL; + } + + if (creds_union) { cci_credentials_union_release (creds_union); } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint32 cci_cred_union_compare_to_credentials_union (const cred_union *in_cred_union_compat, + const cc_credentials_union *in_credentials_union, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + cc_uint32 equal = 0; + + if (!in_cred_union_compat) { err = cci_check_error (ccErrBadParam); } + if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + if (in_cred_union_compat->cred_type == CC_CRED_V5 && + in_credentials_union->version == cc_credentials_v5) { + cc_credentials_v5_compat *old_creds_v5 = in_cred_union_compat->cred.pV5Cred; + cc_credentials_v5_t *new_creds_v5 = in_credentials_union->credentials.credentials_v5; + + /* Really should use krb5_parse_name and krb5_principal_compare */ + if (old_creds_v5 && new_creds_v5 && + !strcmp (old_creds_v5->client, new_creds_v5->client) && + !strcmp (old_creds_v5->server, new_creds_v5->server) && + (old_creds_v5->starttime == new_creds_v5->starttime)) { + equal = 1; + } + } + } + + if (!err) { + *out_equal = equal; + } + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/common/cci_cred_union.h b/krb5-1.21.3/src/ccapi/common/cci_cred_union.h new file mode 100644 index 00000000..2e40476c --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_cred_union.h @@ -0,0 +1,52 @@ +/* ccapi/common/cci_cred_union.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCI_CRED_UNION_H +#define CCI_CRED_UNION_H + +#include "cci_types.h" +#include + +cc_uint32 cci_credentials_union_release (cc_credentials_union *io_credentials); + +cc_uint32 cci_credentials_union_read (cc_credentials_union **out_credentials_union, + k5_ipc_stream io_stream); + +cc_uint32 cci_credentials_union_write (const cc_credentials_union *in_credentials_union, + k5_ipc_stream io_stream); + +cc_uint32 cci_cred_union_release (cred_union *io_cred_union); + +cc_uint32 cci_credentials_union_to_cred_union (const cc_credentials_union *in_credentials_union, + cred_union **out_cred_union); + +cc_uint32 cci_cred_union_to_credentials_union (const cred_union *in_cred_union, + cc_credentials_union **out_credentials_union); + +cc_uint32 cci_cred_union_compare_to_credentials_union (const cred_union *in_cred_union_compat, + const cc_credentials_union *in_credentials_union, + cc_uint32 *out_equal); + +#endif /* CCI_CRED_UNION_H */ diff --git a/krb5-1.21.3/src/ccapi/common/cci_debugging.c b/krb5-1.21.3/src/ccapi/common/cci_debugging.c new file mode 100644 index 00000000..42d8a772 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_debugging.c @@ -0,0 +1,54 @@ +/* ccapi/common/cci_debugging.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "cci_common.h" +#include "cci_os_debugging.h" + +/* ------------------------------------------------------------------------ */ + +cc_int32 _cci_check_error (cc_int32 in_error, + const char *in_function, + const char *in_file, + int in_line) +{ + /* Do not log for flow control errors or when there is no error at all */ + if (in_error != ccNoError && in_error != ccIteratorEnd) { + cci_debug_printf ("%s() got %d at %s: %d", in_function, + in_error, in_file, in_line); + } + + return in_error; +} + +/* ------------------------------------------------------------------------ */ + +void cci_debug_printf (const char *in_format, ...) +{ + va_list args; + + va_start (args, in_format); + cci_os_debug_vprintf (in_format, args); + va_end (args); +} diff --git a/krb5-1.21.3/src/ccapi/common/cci_debugging.h b/krb5-1.21.3/src/ccapi/common/cci_debugging.h new file mode 100644 index 00000000..64413e23 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_debugging.h @@ -0,0 +1,43 @@ +/* ccapi/common/cci_debugging.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCI_DEBUGGING_H +#define CCI_DEBUGGING_H + +#include "cci_types.h" + +cc_int32 _cci_check_error (cc_int32 in_err, + const char *in_function, + const char *in_file, + int in_line); +#define cci_check_error(err) _cci_check_error(err, __FUNCTION__, __FILE__, __LINE__) + +void cci_debug_printf (const char *in_format, ...) +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +__attribute__ ((__format__ (__printf__, 1, 2))) +#endif +; + +#endif /* CCI_DEBUGGING_H */ diff --git a/krb5-1.21.3/src/ccapi/common/cci_identifier.c b/krb5-1.21.3/src/ccapi/common/cci_identifier.c new file mode 100644 index 00000000..a672c18f --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_identifier.c @@ -0,0 +1,290 @@ +/* ccapi/common/cci_identifier.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "cci_common.h" +#include "cci_os_identifier.h" + +struct cci_identifier_d { + cci_uuid_string_t server_id; + cci_uuid_string_t object_id; +}; + +struct cci_identifier_d cci_identifier_initializer = { NULL, NULL }; + +#define cci_uninitialized_server_id "NEEDS_SYNC" +#define cci_uninitialized_object_id "NEEDS_SYNC" + +struct cci_identifier_d cci_identifier_uninitialized_d = { + cci_uninitialized_server_id, + cci_uninitialized_object_id +}; +const cci_identifier_t cci_identifier_uninitialized = &cci_identifier_uninitialized_d; + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_identifier_new_uuid (cci_uuid_string_t *out_uuid_string) +{ + return cci_os_identifier_new_uuid (out_uuid_string); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 cci_identifier_alloc (cci_identifier_t *out_identifier, + cci_uuid_string_t in_server_id, + cci_uuid_string_t in_object_id) +{ + cc_int32 err = ccNoError; + cci_identifier_t identifier = NULL; + + if (!out_identifier) { err = cci_check_error (ccErrBadParam); } + if (!in_server_id ) { err = cci_check_error (ccErrBadParam); } + if (!in_object_id ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + identifier = malloc (sizeof (*identifier)); + if (identifier) { + *identifier = cci_identifier_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + identifier->server_id = strdup (in_server_id); + if (!identifier->server_id) { err = cci_check_error (ccErrNoMem); } + } + + if (!err) { + identifier->object_id = strdup (in_object_id); + if (!identifier->object_id) { err = cci_check_error (ccErrNoMem); } + } + + if (!err) { + *out_identifier = identifier; + identifier = NULL; /* take ownership */ + } + + cci_identifier_release (identifier); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_identifier_new (cci_identifier_t *out_identifier, + cci_uuid_string_t in_server_id) +{ + cc_int32 err = ccNoError; + cci_uuid_string_t object_id = NULL; + + if (!out_identifier) { err = cci_check_error (ccErrBadParam); } + if (!in_server_id ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_os_identifier_new_uuid (&object_id); + } + + if (!err) { + err = cci_identifier_alloc (out_identifier, in_server_id, object_id); + } + + if (object_id) { free (object_id); } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_identifier_copy (cci_identifier_t *out_identifier, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + + if (!out_identifier) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_alloc (out_identifier, + in_identifier->server_id, + in_identifier->object_id); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_identifier_release (cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + + /* Do not free the static "uninitialized" identifier */ + if (!err && in_identifier && in_identifier != cci_identifier_uninitialized) { + free (in_identifier->server_id); + free (in_identifier->object_id); + free (in_identifier); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_identifier_compare (cci_identifier_t in_identifier, + cci_identifier_t in_compare_to_identifier, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!in_compare_to_identifier) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_equal = (!strcmp (in_identifier->object_id, + in_compare_to_identifier->object_id) && + !strcmp (in_identifier->server_id, + in_compare_to_identifier->server_id)); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_identifier_is_for_server (cci_identifier_t in_identifier, + cci_uuid_string_t in_server_id, + cc_uint32 *out_is_for_server) +{ + cc_int32 err = ccNoError; + + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!in_server_id ) { err = cci_check_error (ccErrBadParam); } + if (!out_is_for_server) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_is_for_server = (!strcmp (in_identifier->server_id, in_server_id) || + !strcmp (in_identifier->server_id, cci_uninitialized_server_id)); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_identifier_compare_server_id (cci_identifier_t in_identifier, + cci_identifier_t in_compare_to_identifier, + cc_uint32 *out_equal_server_id) +{ + cc_int32 err = ccNoError; + + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!in_compare_to_identifier) { err = cci_check_error (ccErrBadParam); } + if (!out_equal_server_id ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_equal_server_id = (!strcmp (in_identifier->server_id, + in_compare_to_identifier->server_id)); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_identifier_is_initialized (cci_identifier_t in_identifier, + cc_uint32 *out_is_initialized) +{ + cc_int32 err = ccNoError; + + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_is_initialized) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_is_initialized = (strcmp (in_identifier->server_id, + cci_uninitialized_server_id) != 0); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_uint32 cci_identifier_read (cci_identifier_t *out_identifier, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + cci_uuid_string_t server_id = NULL; + cci_uuid_string_t object_id = NULL; + + if (!out_identifier) { err = cci_check_error (ccErrBadParam); } + if (!io_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_string (io_stream, &server_id); + } + + if (!err) { + err = krb5int_ipc_stream_read_string (io_stream, &object_id); + } + + if (!err) { + err = cci_identifier_alloc (out_identifier, server_id, object_id); + } + + krb5int_ipc_stream_free_string (server_id); + krb5int_ipc_stream_free_string (object_id); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint32 cci_identifier_write (cci_identifier_t in_identifier, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + if (!io_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_write_string (io_stream, in_identifier->server_id); + } + + if (!err) { + err = krb5int_ipc_stream_write_string (io_stream, in_identifier->object_id); + } + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/common/cci_identifier.h b/krb5-1.21.3/src/ccapi/common/cci_identifier.h new file mode 100644 index 00000000..d5e1da4f --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_identifier.h @@ -0,0 +1,64 @@ +/* ccapi/common/cci_identifier.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCI_IDENTIFIER_H +#define CCI_IDENTIFIER_H + +#include "cci_types.h" + +extern const cci_identifier_t cci_identifier_uninitialized; + +cc_int32 cci_identifier_new_uuid (cci_uuid_string_t *out_uuid_string); + +cc_int32 cci_identifier_new (cci_identifier_t *out_identifier, + cci_uuid_string_t in_server_id); + +cc_int32 cci_identifier_copy (cci_identifier_t *out_identifier, + cci_identifier_t in_handle); + +cc_int32 cci_identifier_release (cci_identifier_t in_identifier); + +cc_int32 cci_identifier_compare (cci_identifier_t in_identifier, + cci_identifier_t in_compare_to_identifier, + cc_uint32 *out_equal); + +cc_int32 cci_identifier_is_for_server (cci_identifier_t in_identifier, + cci_uuid_string_t in_server_id, + cc_uint32 *out_is_for_server); + +cc_int32 cci_identifier_compare_server_id (cci_identifier_t in_identifier, + cci_identifier_t in_compare_to_identifier, + cc_uint32 *out_equal_server_id); + +cc_int32 cci_identifier_is_initialized (cci_identifier_t in_identifier, + cc_uint32 *out_is_initialized); + +cc_uint32 cci_identifier_read (cci_identifier_t *out_identifier, + k5_ipc_stream io_stream); + +cc_uint32 cci_identifier_write (cci_identifier_t in_identifier, + k5_ipc_stream io_stream); + +#endif /* CCI_IDENTIFIER_H */ diff --git a/krb5-1.21.3/src/ccapi/common/cci_message.c b/krb5-1.21.3/src/ccapi/common/cci_message.c new file mode 100644 index 00000000..3f610759 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_message.c @@ -0,0 +1,213 @@ +/* ccapi/common/cci_message.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "cci_common.h" + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_message_invalid_object_err (enum cci_msg_id_t in_request_name) +{ + cc_int32 err = ccNoError; + + if (in_request_name > cci_context_first_msg_id && + in_request_name < cci_context_last_msg_id) { + err = ccErrInvalidContext; + + } else if (in_request_name > cci_ccache_first_msg_id && + in_request_name < cci_ccache_last_msg_id) { + err = ccErrInvalidCCache; + + } else if (in_request_name > cci_ccache_iterator_first_msg_id && + in_request_name < cci_ccache_iterator_last_msg_id) { + err = ccErrInvalidCCacheIterator; + + } else if (in_request_name > cci_credentials_iterator_first_msg_id && + in_request_name < cci_credentials_iterator_last_msg_id) { + err = ccErrInvalidCredentialsIterator; + + } else { + err = ccErrBadInternalMessage; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_message_new_request_header (k5_ipc_stream *out_request, + enum cci_msg_id_t in_request_name, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + k5_ipc_stream request = NULL; + + if (!out_request) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (request, in_request_name); + } + + if (!err) { + err = cci_identifier_write (in_identifier, request); + } + + if (!err) { + *out_request = request; + request = NULL; + } + + krb5int_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_message_read_request_header (k5_ipc_stream in_request, + enum cci_msg_id_t *out_request_name, + cci_identifier_t *out_identifier) +{ + cc_int32 err = ccNoError; + cc_uint32 request_name; + cci_identifier_t identifier = NULL; + + if (!in_request ) { err = cci_check_error (ccErrBadParam); } + if (!out_request_name) { err = cci_check_error (ccErrBadParam); } + if (!out_identifier ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (in_request, &request_name); + } + + if (!err) { + err = cci_identifier_read (&identifier, in_request); + } + + if (!err) { + *out_request_name = request_name; + *out_identifier = identifier; + identifier = NULL; /* take ownership */ + } + + cci_identifier_release (identifier); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_message_new_reply_header (k5_ipc_stream *out_reply, + cc_int32 in_error) +{ + cc_int32 err = ccNoError; + k5_ipc_stream reply = NULL; + + if (!out_reply) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&reply); + } + + if (!err) { + err = krb5int_ipc_stream_write_int32 (reply, in_error); + } + + if (!err) { + *out_reply = reply; + reply = NULL; + } + + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_message_read_reply_header (k5_ipc_stream in_reply, + cc_int32 *out_reply_error) +{ + cc_int32 err = ccNoError; + cc_int32 reply_err = 0; + + if (!in_reply ) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_error) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_int32 (in_reply, &reply_err); + } + + if (!err) { + *out_reply_error = reply_err; + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +uint32_t krb5int_ipc_stream_read_time (k5_ipc_stream io_stream, + cc_time_t *out_time) +{ + int32_t err = 0; + int64_t t = 0; + + if (!io_stream) { err = cci_check_error (ccErrBadParam); } + if (!out_time ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_int64 (io_stream, &t); + } + + if (!err) { + *out_time = t; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +uint32_t krb5int_ipc_stream_write_time (k5_ipc_stream io_stream, + cc_time_t in_time) +{ + int32_t err = 0; + + if (!io_stream) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_write_int64 (io_stream, in_time); + } + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/common/cci_message.h b/krb5-1.21.3/src/ccapi/common/cci_message.h new file mode 100644 index 00000000..6babb560 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_message.h @@ -0,0 +1,52 @@ +/* ccapi/common/cci_message.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCI_MESSAGE_H +#define CCI_MESSAGE_H + +#include "cci_types.h" + +cc_int32 cci_message_invalid_object_err (enum cci_msg_id_t in_request_name); + +cc_int32 cci_message_new_request_header (k5_ipc_stream *out_request, + enum cci_msg_id_t in_request_name, + cci_identifier_t in_identifier); + +cc_int32 cci_message_read_request_header (k5_ipc_stream in_request, + enum cci_msg_id_t *out_request_name, + cci_identifier_t *out_identifier); + +cc_int32 cci_message_new_reply_header (k5_ipc_stream *out_reply, + cc_int32 in_error); + +cc_int32 cci_message_read_reply_header (k5_ipc_stream in_reply, + cc_int32 *out_reply_error); + +uint32_t krb5int_ipc_stream_read_time (k5_ipc_stream io_stream, + cc_time_t *out_time); +uint32_t krb5int_ipc_stream_write_time (k5_ipc_stream io_stream, + cc_time_t in_time); + +#endif /* CCI_MESSAGE_H */ diff --git a/krb5-1.21.3/src/ccapi/common/cci_os_debugging.h b/krb5-1.21.3/src/ccapi/common/cci_os_debugging.h new file mode 100644 index 00000000..c99c79a9 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_os_debugging.h @@ -0,0 +1,34 @@ +/* ccapi/common/cci_os_debugging.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCI_OS_DEBUGGING_H +#define CCI_OS_DEBUGGING_H + +#include "cci_types.h" +#include + +void cci_os_debug_vprintf (const char *in_format, va_list in_args); + +#endif /* CCI_OS_DEBUGGING_H */ diff --git a/krb5-1.21.3/src/ccapi/common/cci_os_identifier.h b/krb5-1.21.3/src/ccapi/common/cci_os_identifier.h new file mode 100644 index 00000000..7ee67eb3 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_os_identifier.h @@ -0,0 +1,33 @@ +/* ccapi/common/cci_os_identifier.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCI_OS_IDENTIFIER_H +#define CCI_OS_IDENTIFIER_H + +#include "cci_types.h" + +cc_int32 cci_os_identifier_new_uuid (cci_uuid_string_t *out_uuid_string); + +#endif /* CCI_OS_IDENTIFIER_H */ diff --git a/krb5-1.21.3/src/ccapi/common/cci_types.h b/krb5-1.21.3/src/ccapi/common/cci_types.h new file mode 100644 index 00000000..87597d44 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/cci_types.h @@ -0,0 +1,102 @@ +/* ccapi/common/cci_types.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCI_TYPES_H +#define CCI_TYPES_H + +#include +#include + +typedef char *cci_uuid_string_t; + +struct cci_identifier_d; +typedef struct cci_identifier_d *cci_identifier_t; + +enum cci_msg_id_t { + /* cc_context_t */ + cci_context_first_msg_id, + + cci_context_unused_release_msg_id, /* Unused. Handle for old clients. */ + cci_context_sync_msg_id, + cci_context_get_change_time_msg_id, + cci_context_wait_for_change_msg_id, + cci_context_get_default_ccache_name_msg_id, + cci_context_open_ccache_msg_id, + cci_context_open_default_ccache_msg_id, + cci_context_create_ccache_msg_id, + cci_context_create_default_ccache_msg_id, + cci_context_create_new_ccache_msg_id, + cci_context_new_ccache_iterator_msg_id, + cci_context_lock_msg_id, + cci_context_unlock_msg_id, + + cci_context_last_msg_id, + + /* cc_ccache_t */ + cci_ccache_first_msg_id, + + cci_ccache_destroy_msg_id, + cci_ccache_set_default_msg_id, + cci_ccache_get_credentials_version_msg_id, + cci_ccache_get_name_msg_id, + cci_ccache_get_principal_msg_id, + cci_ccache_set_principal_msg_id, + cci_ccache_store_credentials_msg_id, + cci_ccache_remove_credentials_msg_id, + cci_ccache_new_credentials_iterator_msg_id, + cci_ccache_move_msg_id, + cci_ccache_lock_msg_id, + cci_ccache_unlock_msg_id, + cci_ccache_get_last_default_time_msg_id, + cci_ccache_get_change_time_msg_id, + cci_ccache_wait_for_change_msg_id, + cci_ccache_get_kdc_time_offset_msg_id, + cci_ccache_set_kdc_time_offset_msg_id, + cci_ccache_clear_kdc_time_offset_msg_id, + + cci_ccache_last_msg_id, + + /* cc_ccache_iterator_t */ + cci_ccache_iterator_first_msg_id, + + cci_ccache_iterator_release_msg_id, + cci_ccache_iterator_next_msg_id, + cci_ccache_iterator_clone_msg_id, + + cci_ccache_iterator_last_msg_id, + + /* cc_credentials_iterator_t */ + cci_credentials_iterator_first_msg_id, + + cci_credentials_iterator_release_msg_id, + cci_credentials_iterator_next_msg_id, + cci_credentials_iterator_clone_msg_id, + + cci_credentials_iterator_last_msg_id, + + cci_max_msg_id /* must be last! */ +}; + +#endif /* CCI_TYPES_H */ diff --git a/krb5-1.21.3/src/ccapi/common/unix/Makefile.in b/krb5-1.21.3/src/ccapi/common/unix/Makefile.in new file mode 100644 index 00000000..ecacabd6 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/unix/Makefile.in @@ -0,0 +1,13 @@ +mydir=ccapi$(S)common$(S)unix +BUILDTOP=$(REL)..$(S)..$(S).. + +STLIBOBJS= +OBJS= +SRCS= + +all-unix: all-libobjs +clean-unix:: clean-libobjs + +@libobj_frag@ + +# +++ Dependency line eater +++ diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/autolock.hxx b/krb5-1.21.3/src/ccapi/common/win/OldCC/autolock.hxx new file mode 100644 index 00000000..b88172d2 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/autolock.hxx @@ -0,0 +1,66 @@ +/* ccapi/common/win/OldCC/autolock.hxx */ +/* + * Copyright (C) 1998 by Danilo Almeida. 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. + */ + +#ifndef __AUTOLOCK_HXX__ +#define __AUTOLOCK_HXX__ + +#include + +class CcOsLock { + CRITICAL_SECTION cs; + bool valid; +public: + CcOsLock() {InitializeCriticalSection(&cs); valid = true; } + ~CcOsLock() {DeleteCriticalSection(&cs); valid = false;} + void lock() {if (valid) EnterCriticalSection(&cs);} + void unlock() {if (valid) LeaveCriticalSection(&cs);} + bool trylock() {return valid ? (TryEnterCriticalSection(&cs) ? true : false) + : false; } +}; + +class CcAutoLock { + CcOsLock& m_lock; +public: + static void Start(CcAutoLock*& a, CcOsLock& lock) { a = new CcAutoLock(lock); }; + static void Stop (CcAutoLock*& a) { delete a; a = 0; }; + CcAutoLock(CcOsLock& lock):m_lock(lock) { m_lock.lock(); } + ~CcAutoLock() { m_lock.unlock(); } +}; + +class CcAutoTryLock { + CcOsLock& m_lock; + bool m_locked; +public: + CcAutoTryLock(CcOsLock& lock):m_lock(lock) { m_locked = m_lock.trylock(); } + ~CcAutoTryLock() { if (m_locked) m_lock.unlock(); m_locked = false; } + bool IsLocked() const { return m_locked; } +}; + +#endif /* __AUTOLOCK_HXX */ diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/ccutil.cxx b/krb5-1.21.3/src/ccapi/common/win/OldCC/ccutil.cxx new file mode 100644 index 00000000..b6092316 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/ccutil.cxx @@ -0,0 +1,187 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include "init.hxx" +#include "secure.hxx" + +extern "C" { +#include "cci_debugging.h" + } + + +CcOsLock Init::s_lock; +DWORD Init::s_refcount = 0; +DWORD Init::s_error = ERROR_INVALID_HANDLE; +bool Init::s_init = false; +Init::InitInfo Init::s_info = { 0 }; +HINSTANCE Init::s_hRpcDll = 0; + +#define INIT "INIT: " + +static +void +ShowInfo( + Init::InitInfo& info + ); + +DWORD +Init::Info( + InitInfo& info + ) +{ + // This function will not do automatic initialization. + CcAutoLock AL(s_lock); + if (!s_init) { + memset(&info, 0, sizeof(info)); + return s_error ? s_error : ERROR_INVALID_HANDLE; + } else { + info = s_info; + return 0; + } +} + +DWORD +Init::Initialize() { + CcAutoLock AL(s_lock); + cci_debug_printf("%s s_init:%d", __FUNCTION__, s_init); + if (s_init) { + s_refcount++; + return 0; + } + SecureClient s; + DWORD status = 0; + OSVERSIONINFO osvi; + BOOL isSupportedVersion = FALSE; + memset(&s_info, 0, sizeof(s_info)); + memset(&osvi, 0, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + status = !GetVersionEx(&osvi); // Returns a boolean. Invert to 0 is OK. + + if (!status) { + switch(osvi.dwPlatformId) { + case VER_PLATFORM_WIN32_WINDOWS: + s_info.isNT = FALSE; + isSupportedVersion = TRUE; + break; + case VER_PLATFORM_WIN32_NT: + s_info.isNT = TRUE; + isSupportedVersion = TRUE; + break; + case VER_PLATFORM_WIN32s: + default: + s_info.isNT = FALSE; + break; + } + + if (!isSupportedVersion) { + cci_debug_printf("%s Trying to run on an unsupported version of Windows", __FUNCTION__); + status = 1; + } + } + + if (!status) {status = !s_info.isNT;} + + if (!status) {status = !(s_hRpcDll = LoadLibrary(TEXT("rpcrt4.dll")));} + + if (!status) { + s_info.fRpcBindingSetAuthInfoEx = (FP_RpcBindingSetAuthInfoEx) + GetProcAddress(s_hRpcDll, TEXT(FN_RpcBindingSetAuthInfoEx)); + if (!s_info.fRpcBindingSetAuthInfoEx) { + cci_debug_printf(" Running on NT but could not find RpcBindinSetAuthInfoEx"); + status = 1; + } + } + + if (!status) { + s_info.fRpcServerRegisterIfEx = (FP_RpcServerRegisterIfEx) + GetProcAddress(s_hRpcDll, TEXT(FN_RpcServerRegisterIfEx)); + if (!s_info.fRpcServerRegisterIfEx) { + cci_debug_printf(" Running on NT but could not find RpcServerRegisterIfEx"); + status = 1; + } + } + + if (!status) { + status = SecureClient::Attach(); + if (status) { + cci_debug_printf(" SecureClient::Attach() failed (%u)", status); + } + } + + if (status) { + memset(&s_info, 0, sizeof(s_info)); + if (s_hRpcDll) { + FreeLibrary(s_hRpcDll); + s_hRpcDll = 0; + } + cci_debug_printf(" Init::Attach() failed (%u)", status); + } else { + s_refcount++; + s_init = true; + ShowInfo(s_info); + } + s_error = status; + return status; +} + +DWORD +Init::Cleanup( + ) +{ + CcAutoLock AL(s_lock); + s_refcount--; + if (s_refcount) return 0; + if (!s_init) return 0; + DWORD error = 0; + if (s_hRpcDll) { + FreeLibrary(s_hRpcDll); + s_hRpcDll = 0; + } + error = SecureClient::Detach(); + memset(&s_info, 0, sizeof(s_info)); + s_init = false; + s_error = 0; + if (error) { + cci_debug_printf(" Init::Detach() had an error (%u)", error); + } + return error; +} + +static +void +ShowInfo( + Init::InitInfo& info + ) +{ + if (info.isNT) { + cci_debug_printf(" Running on Windows NT using secure mode"); + } else { + cci_debug_printf(" Running insecurely on non-NT Windows"); + } + return; +} diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/ccutil.def b/krb5-1.21.3/src/ccapi/common/win/OldCC/ccutil.def new file mode 100644 index 00000000..57113f09 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/ccutil.def @@ -0,0 +1,5 @@ +;LIBRARY COMERR32 +HEAPSIZE 8192 + +EXPORTS + \ No newline at end of file diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/ccutils.c b/krb5-1.21.3/src/ccapi/common/win/OldCC/ccutils.c new file mode 100644 index 00000000..403c67eb --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/ccutils.c @@ -0,0 +1,133 @@ +/* ccapi/common/win/OldCC/ccutils.c */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include + +#include "cci_debugging.h" +#include "util.h" + +BOOL isNT() { + OSVERSIONINFO osvi; + DWORD status = 0; + BOOL bSupportedVersion = FALSE; + BOOL bIsNT = FALSE; + + memset(&osvi, 0, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + status = !GetVersionEx(&osvi); // Returns a boolean. Invert to 0 is OK. + + if (!status) { + switch(osvi.dwPlatformId) { + case VER_PLATFORM_WIN32_WINDOWS: + bIsNT = FALSE; + bSupportedVersion = TRUE; + break; + case VER_PLATFORM_WIN32_NT: + bIsNT = TRUE; + bSupportedVersion = TRUE; + break; + case VER_PLATFORM_WIN32s: + default: + bIsNT = FALSE; + break; + } + + if (!bSupportedVersion) { + cci_debug_printf("%s Running on an unsupported version of Windows", __FUNCTION__); + status = 1; + } + } + + return (!status && bIsNT && bSupportedVersion); + } + +char* allocEventName(char* uuid_string, char* suffix) { + LPSTR event_name = NULL; + cc_int32 err = ccNoError; + + event_name = malloc(strlen(uuid_string) + strlen(suffix) + 3); + if (!event_name) err = cci_check_error(ccErrNoMem); + + if (!err) { + strcpy(event_name, uuid_string); + strcat(event_name, "_"); + strcat(event_name, suffix); + } + + return event_name; + } + +HANDLE createThreadEvent(char* uuid, char* suffix) { + LPSTR event_name = NULL; + HANDLE hEvent = NULL; + PSECURITY_ATTRIBUTES psa = 0; // Everything having to do with + SECURITY_ATTRIBUTES sa = { 0 }; // sa, psa, security is copied + DWORD status = 0; // from the previous implementation. + + psa = isNT() ? &sa : 0; + + if (isNT()) { + sa.nLength = sizeof(sa); + status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor); + cci_check_error(status); + } + + if (!status) { + event_name = allocEventName(uuid, suffix); + if (!event_name) status = cci_check_error(ccErrNoMem); + } + if (!status) { + hEvent = CreateEvent(psa, FALSE, FALSE, event_name); + if (!hEvent) status = cci_check_error(GetLastError()); + } + + if (!status) ResetEvent(hEvent); + + + if (event_name) free(event_name); + if (isNT()) free(sa.lpSecurityDescriptor); + + return hEvent; + } + +HANDLE openThreadEvent(char* uuid, char* suffix) { + LPSTR event_name = NULL; + HANDLE hEvent = NULL; + DWORD status = 0; + + event_name = allocEventName(uuid, suffix); + if (!event_name) status = cci_check_error(ccErrNoMem); + if (!status) { + hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name); + if (!hEvent) status = cci_check_error(GetLastError()); + } + + if (event_name) free(event_name); + + return hEvent; + } diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/ccutils.h b/krb5-1.21.3/src/ccapi/common/win/OldCC/ccutils.h new file mode 100644 index 00000000..9da3d87f --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/ccutils.h @@ -0,0 +1,45 @@ +/* ccapi/common/win/OldCC/ccutils.h */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __CCUTILS_H__ +#define __CCUTILS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define REPLY_SUFFIX (char*)"reply" +#define LISTEN_SUFFIX (char*)"listen" + +BOOL isNT(); +char* allocEventName (char* uuid, char* suffix); +HANDLE createThreadEvent(char* uuid, char* suffix); +HANDLE openThreadEvent (char* uuid, char* suffix); + +#ifdef __cplusplus +} +#endif + +#endif /* __CCUTILS_H__ */ diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/init.cxx b/krb5-1.21.3/src/ccapi/common/win/OldCC/init.cxx new file mode 100644 index 00000000..baa8e280 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/init.cxx @@ -0,0 +1,187 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include "init.hxx" +#include "secure.hxx" + +extern "C" { +#include "cci_debugging.h" + } + + +CcOsLock Init::s_lock; +DWORD Init::s_refcount = 0; +DWORD Init::s_error = ERROR_INVALID_HANDLE; +bool Init::s_init = false; +Init::InitInfo Init::s_info = { 0 }; +HINSTANCE Init::s_hRpcDll = 0; + +#define INIT "INIT: " + +static +void +ShowInfo( + Init::InitInfo& info + ); + +DWORD +Init::Info( + InitInfo& info + ) +{ + // This function will not do automatic initialization. + CcAutoLock AL(s_lock); + if (!s_init) { + memset(&info, 0, sizeof(info)); + return s_error ? s_error : ERROR_INVALID_HANDLE; + } else { + info = s_info; + return 0; + } +} + +DWORD +Init::Initialize() { + CcAutoLock AL(s_lock); +// cci_debug_printf("%s s_init:%d", __FUNCTION__, s_init); + if (s_init) { + s_refcount++; + return 0; + } + SecureClient s; + DWORD status = 0; + OSVERSIONINFO osvi; + BOOL isSupportedVersion = FALSE; + memset(&s_info, 0, sizeof(s_info)); + memset(&osvi, 0, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + status = !GetVersionEx(&osvi); // Returns a boolean. Invert to 0 is OK. + + if (!status) { + switch(osvi.dwPlatformId) { + case VER_PLATFORM_WIN32_WINDOWS: + s_info.isNT = FALSE; + isSupportedVersion = TRUE; + break; + case VER_PLATFORM_WIN32_NT: + s_info.isNT = TRUE; + isSupportedVersion = TRUE; + break; + case VER_PLATFORM_WIN32s: + default: + s_info.isNT = FALSE; + break; + } + + if (!isSupportedVersion) { + cci_debug_printf("%s Trying to run on an unsupported version of Windows", __FUNCTION__); + status = 1; + } + } + + if (!status) {status = !s_info.isNT;} + + if (!status) {status = !(s_hRpcDll = LoadLibrary(TEXT("rpcrt4.dll")));} + + if (!status) { + s_info.fRpcBindingSetAuthInfoEx = (FP_RpcBindingSetAuthInfoEx) + GetProcAddress(s_hRpcDll, TEXT(FN_RpcBindingSetAuthInfoEx)); + if (!s_info.fRpcBindingSetAuthInfoEx) { + cci_debug_printf(" Running on NT but could not find RpcBindinSetAuthInfoEx"); + status = 1; + } + } + + if (!status) { + s_info.fRpcServerRegisterIfEx = (FP_RpcServerRegisterIfEx) + GetProcAddress(s_hRpcDll, TEXT(FN_RpcServerRegisterIfEx)); + if (!s_info.fRpcServerRegisterIfEx) { + cci_debug_printf(" Running on NT but could not find RpcServerRegisterIfEx"); + status = 1; + } + } + + if (!status) { + status = SecureClient::Attach(); + if (status) { + cci_debug_printf(" SecureClient::Attach() failed (%u)", status); + } + } + + if (status) { + memset(&s_info, 0, sizeof(s_info)); + if (s_hRpcDll) { + FreeLibrary(s_hRpcDll); + s_hRpcDll = 0; + } + cci_debug_printf(" Init::Attach() failed (%u)", status); + } else { + s_refcount++; + s_init = true; + ShowInfo(s_info); + } + s_error = status; + return status; +} + +DWORD +Init::Cleanup( + ) +{ + CcAutoLock AL(s_lock); + s_refcount--; + if (s_refcount) return 0; + if (!s_init) return 0; + DWORD error = 0; + if (s_hRpcDll) { + FreeLibrary(s_hRpcDll); + s_hRpcDll = 0; + } + error = SecureClient::Detach(); + memset(&s_info, 0, sizeof(s_info)); + s_init = false; + s_error = 0; + if (error) { + cci_debug_printf(" Init::Detach() had an error (%u)", error); + } + return error; +} + +static +void +ShowInfo( + Init::InitInfo& info + ) +{ + if (info.isNT) { + cci_debug_printf(" Running on Windows NT using secure mode"); + } else { + cci_debug_printf(" Running insecurely on non-NT Windows"); + } + return; +} diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/init.hxx b/krb5-1.21.3/src/ccapi/common/win/OldCC/init.hxx new file mode 100644 index 00000000..9bac7f8f --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/init.hxx @@ -0,0 +1,102 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#pragma once +#include "autolock.hxx" +#include + +typedef RPC_STATUS (RPC_ENTRY *FP_RpcBindingSetAuthInfoExA)( + IN RPC_BINDING_HANDLE Binding, + IN unsigned char __RPC_FAR * ServerPrincName, + IN unsigned long AuthnLevel, + IN unsigned long AuthnSvc, + IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL + IN unsigned long AuthzSvc, + IN RPC_SECURITY_QOS *SecurityQos OPTIONAL + ); + +typedef RPC_STATUS (RPC_ENTRY *FP_RpcBindingSetAuthInfoExW)( + IN RPC_BINDING_HANDLE Binding, + IN unsigned short __RPC_FAR * ServerPrincName, + IN unsigned long AuthnLevel, + IN unsigned long AuthnSvc, + IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL + IN unsigned long AuthzSvc, OPTIONAL + IN RPC_SECURITY_QOS *SecurityQOS + ); + +typedef RPC_STATUS (RPC_ENTRY *FP_RpcServerRegisterIfEx)( + IN RPC_IF_HANDLE IfSpec, + IN UUID __RPC_FAR * MgrTypeUuid, + IN RPC_MGR_EPV __RPC_FAR * MgrEpv, + IN unsigned int Flags, + IN unsigned int MaxCalls, + IN RPC_IF_CALLBACK_FN __RPC_FAR *IfCallback + ); + +#ifdef UNICODE +#define FP_RpcBindingSetAuthInfoEx FP_RpcBindingSetAuthInfoExW +#define FN_RpcBindingSetAuthInfoEx "RpcBindingSetAuthInfoExW" +#else +#define FP_RpcBindingSetAuthInfoEx FP_RpcBindingSetAuthInfoExA +#define FN_RpcBindingSetAuthInfoEx "RpcBindingSetAuthInfoExA" +#endif + +#define FN_RpcServerRegisterIfEx "RpcServerRegisterIfEx" + +class Init +{ +public: + struct InitInfo { + BOOL isNT; + FP_RpcBindingSetAuthInfoEx fRpcBindingSetAuthInfoEx; + FP_RpcServerRegisterIfEx fRpcServerRegisterIfEx; + }; + + static DWORD Initialize(); + static DWORD Cleanup(); + static DWORD Info(InitInfo& info); + + static bool Initialized() { return s_init; } + +private: + static CcOsLock s_lock; + static DWORD s_refcount; + static DWORD s_error; + static bool s_init; + static InitInfo s_info; + static HINSTANCE s_hRpcDll; +}; + +#define INIT_INIT_EX(trap, error) \ +do \ +{ \ + if (!Init::Initialized()) \ + { \ + DWORD rc = Init::Initialize(); \ + if (rc) return (trap) ? (error) : rc; \ + } \ +} while(0) diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/name.h b/krb5-1.21.3/src/ccapi/common/win/OldCC/name.h new file mode 100644 index 00000000..66ca3a9f --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/name.h @@ -0,0 +1,34 @@ +/* ccapi/common/win/OldCC/name.h */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#pragma once + +#ifdef _WIN64 +#define CCAPI_MODULE "krbcc64" +#else +#define CCAPI_MODULE "krbcc32" +#endif +#define CCAPI_DLL CCAPI_MODULE ".dll" +#define CCAPI_EXE "ccapiserver.exe" \ No newline at end of file diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/opts.cxx b/krb5-1.21.3/src/ccapi/common/win/OldCC/opts.cxx new file mode 100644 index 00000000..c9776638 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/opts.cxx @@ -0,0 +1,149 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include +#include + +bool +ParseOpts::IsValidOpt( + char ch + ) +{ + return (m_ValidOpts[ch % 256] != 0); +} + +void +ParseOpts::PrintOpt( + char ch, + char* text + ) +{ + if (IsValidOpt(ch)) + fprintf(stderr, " -%c %s\n", ch, text); +} + +void +ParseOpts::UsageOpts( + char * program, + int code + ) +{ + fprintf(stderr, "Usage: %s [options]\n", program); + PrintOpt('k', "stop server"); +#ifdef CCAPI_TEST_OPTIONS + PrintOpt('s', "string"); + PrintOpt('e', "endpoint"); + PrintOpt('m', "maxcalls"); + PrintOpt('n', "mincalls"); + PrintOpt('f', "flag_wait_op"); + PrintOpt('u', "unprotected"); + PrintOpt('b', "use security callback"); +#endif + PrintOpt('c', "output debug info to console"); + exit(code); +} + +void +ParseOpts::SetValidOpts( + char* valid_opts + ) +{ + memset(m_ValidOpts, 0, sizeof(m_ValidOpts)); + char *p = valid_opts; + for (p = valid_opts; *p; p++) { + m_ValidOpts[*p % sizeof(m_ValidOpts)] = 1; + } +} + +void +ParseOpts::Parse( + Opts& opts, + int argc, + char **argv + ) +{ + int i; + for (i = 1; i < argc; i++) { + if ((*argv[i] == '-') || (*argv[i] == '/')) { + char ch = tolower(*(argv[i]+1)); + if (!IsValidOpt(ch)) + UsageOpts(argv[0]); + switch (ch) { + case 'k': + opts.bShutdown = TRUE; + break; +#ifdef CCAPI_TEST_OPTIONS + case 's': + opts.pszString = argv[++i]; + break; + case 'e': + opts.pszEndpoint = argv[++i]; + break; + case 'm': + opts.cMaxCalls = (unsigned int) atoi(argv[++i]); + break; + case 'n': + opts.cMinCalls = (unsigned int) atoi(argv[++i]); + break; + case 'f': + opts.fDontWait = (unsigned int) atoi(argv[++i]); + break; + case 'u': + opts.bDontProtect = TRUE; + break; + case 'b': + opts.bSecCallback = TRUE; + break; +#endif + case 'c': + opts.bConsole = TRUE; + break; + case 'h': + case '?': + default: + UsageOpts(argv[0]); + } + } + else + UsageOpts(argv[0]); + } + +} + +ParseOpts::ParseOpts(char* valid_opts) +{ + SetValidOpts(valid_opts); +} + +ParseOpts::ParseOpts() +{ +} + +ParseOpts::~ParseOpts() +{ +} diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/opts.hxx b/krb5-1.21.3/src/ccapi/common/win/OldCC/opts.hxx new file mode 100644 index 00000000..755ce4ae --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/opts.hxx @@ -0,0 +1,56 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#pragma once + +class ParseOpts +{ +public: + struct Opts { + char* pszString; + char* pszEndpoint; + unsigned int cMinCalls; + unsigned int cMaxCalls; + unsigned int fDontWait; + bool bDontProtect; + bool bShutdown; + bool bSecCallback; + bool bConsole; + }; + + ParseOpts(char* valid_opts); + ParseOpts(); + ~ParseOpts(); + void SetValidOpts(char* valid_opts); + void Parse(Opts& opts, int argc, char **argv); + +private: + bool IsValidOpt(char ch); + void PrintOpt(char ch, char* text); + void UsageOpts(char* program, int code = 0); + + char m_ValidOpts[256]; +}; diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/secure.cxx b/krb5-1.21.3/src/ccapi/common/win/OldCC/secure.cxx new file mode 100644 index 00000000..99ba08a2 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/secure.cxx @@ -0,0 +1,161 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include "secure.hxx" + +extern "C" { +#include "cci_debugging.h" + } + +CcOsLock SecureClient::s_lock; +DWORD SecureClient::s_refcount = 0; +DWORD SecureClient::s_error = 0; +HANDLE SecureClient::s_hToken = 0; + +#include "util.h" + +#define SC "SecureClient::" + +DWORD +SecureClient::Attach( + ) +{ + CcAutoLock AL(s_lock); + if (s_hToken) { + s_refcount++; + return 0; + } + if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, + &s_hToken)) { + s_refcount++; + s_error = 0; + } else { + s_hToken = 0; + s_error = GetLastError(); + } + return s_error; +} + +DWORD +SecureClient::Detach( + ) +{ + CcAutoLock AL(s_lock); + s_refcount--; + if (s_refcount) return 0; + if (!s_hToken) return 0; + DWORD error = 0; + if (!CloseHandle(s_hToken)) + error = GetLastError(); + s_hToken = 0; + s_error = 0; + return error; +} + +DWORD SecureClient::Token(HANDLE& hToken) { + // This function will not do automatic initialization. + CcAutoLock AL(s_lock); + hToken = 0; + if (!s_hToken) { + cci_debug_printf("%s no process token initialized (%u)", __FUNCTION__, s_error); + return s_error ? s_error : ERROR_INVALID_HANDLE; + } + else { + DWORD status = 0; + if (!DuplicateHandle(GetCurrentProcess(), s_hToken, + GetCurrentProcess(), &hToken, 0, FALSE, + DUPLICATE_SAME_ACCESS)) { + status = GetLastError(); + cci_debug_printf(" Could not duplicate handle (%u)", status); + } + return status; + } + } + +void +SecureClient::Start(SecureClient*& s) { + s = new SecureClient; +} + +void +SecureClient::Stop(SecureClient*& s) { + delete s; + s = 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +/* This constructor turns off impersonation. + * It is OK for OpenThreadToken to return an error -- that just means impersonation + * is off. + */ +SecureClient::SecureClient(): + m_Error(0), + m_hToken(0), + m_NeedRestore(false) { + + HANDLE hThread = GetCurrentThread(); + HANDLE hThDuplicate; + + int status = DuplicateHandle( GetCurrentProcess(), + hThread, + GetCurrentProcess(), + &hThDuplicate, + TOKEN_ALL_ACCESS, + FALSE, + 0); + if (!status) return; + + if (!OpenThreadToken(hThDuplicate, TOKEN_ALL_ACCESS, FALSE, &m_hToken)) { + m_Error = GetLastError(); + return; + } + if (SetThreadToken(&hThDuplicate, NULL)) { + m_NeedRestore = true; + } else { + m_Error = GetLastError(); + } + CloseHandle(hThDuplicate); + } + +SecureClient::~SecureClient() { + if (m_NeedRestore) { + HANDLE hThread = GetCurrentThread(); + if (!SetThreadToken(&hThread, m_hToken)) { + m_Error = cci_check_error(GetLastError()); + } + } + if (m_hToken) { + if (!CloseHandle(m_hToken)) { + m_Error = cci_check_error(GetLastError()); + } + } + } + +DWORD SecureClient::Error() { + return m_Error; + } \ No newline at end of file diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/secure.hxx b/krb5-1.21.3/src/ccapi/common/win/OldCC/secure.hxx new file mode 100644 index 00000000..1b2e7532 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/secure.hxx @@ -0,0 +1,54 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#pragma once + +#include +#include "autolock.hxx" + +class SecureClient +{ +public: + static DWORD Attach(); + static DWORD Detach(); + static DWORD Token(HANDLE& hToken); + static void Start(SecureClient*& s); + static void Stop(SecureClient*& s); + + SecureClient(); + ~SecureClient(); + DWORD Error(); + +private: + static CcOsLock s_lock; + static DWORD s_refcount; + static DWORD s_error; + static HANDLE s_hToken; + + DWORD m_Error; + HANDLE m_hToken; + bool m_NeedRestore; +}; diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/util.cxx b/krb5-1.21.3/src/ccapi/common/win/OldCC/util.cxx new file mode 100644 index 00000000..327f5f87 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/util.cxx @@ -0,0 +1,520 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include // for _snprintf +#include +#include + +extern "C" { +#include "cci_debugging.h" +#include "ccutils.h" + } + +#include "util.h" +#include "secure.hxx" + + +void* malloc_alloc_p(size_t size) { + return malloc(size); + } + +void free_alloc_p(void *pptr) { + void **real_pptr = (void**)pptr; + if (*real_pptr) { + free(*real_pptr); + *real_pptr = 0; + } + } + +extern "C" DWORD alloc_textual_sid( + PSID pSid, // binary Sid + LPSTR *pTextualSid // buffer for Textual representation of Sid + ) { + PSID_IDENTIFIER_AUTHORITY psia; + DWORD dwSubAuthorities; + DWORD dwSidRev = SID_REVISION; + DWORD dwCounter; + DWORD dwSidSize; + + *pTextualSid = 0; + + // + // test if Sid passed in is valid + // + if(!IsValidSid(pSid)) return ERROR_INVALID_PARAMETER; + + // obtain SidIdentifierAuthority + psia = GetSidIdentifierAuthority(pSid); + + // obtain sidsubauthority count + dwSubAuthorities =* GetSidSubAuthorityCount(pSid); + + // + // compute buffer length + // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL + // + dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR); + *pTextualSid = (LPSTR)malloc_alloc_p(dwSidSize); + if (!*pTextualSid) + return GetLastError(); + + LPSTR TextualSid = *pTextualSid; + + // + // prepare S-SID_REVISION- + // + wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev ); + + // + // prepare SidIdentifierAuthority + // + if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) + { + wsprintf(TextualSid + lstrlen(TextualSid), + TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"), + (USHORT)psia->Value[0], + (USHORT)psia->Value[1], + (USHORT)psia->Value[2], + (USHORT)psia->Value[3], + (USHORT)psia->Value[4], + (USHORT)psia->Value[5]); + } + else + { + wsprintf(TextualSid + lstrlen(TextualSid), TEXT("%lu"), + (ULONG)(psia->Value[5] ) + + (ULONG)(psia->Value[4] << 8) + + (ULONG)(psia->Value[3] << 16) + + (ULONG)(psia->Value[2] << 24) ); + } + + // + // loop through SidSubAuthorities + // + for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++) + { + wsprintf(TextualSid + lstrlen(TextualSid), TEXT("-%lu"), + *GetSidSubAuthority(pSid, dwCounter) ); + } + return 0; +} + +DWORD alloc_token_user(HANDLE hToken, PTOKEN_USER *pptu) { + DWORD status = 0; + DWORD size = 0; + *pptu = 0; + + GetTokenInformation(hToken, TokenUser, *pptu, 0, &size); + if (size == 0) status = GetLastError(); + + if (!status) { + if (!(*pptu = (PTOKEN_USER)malloc_alloc_p(size))) + status = GetLastError(); + } + + if (!status) { + if (!GetTokenInformation(hToken, TokenUser, *pptu, size, &size)) + status = GetLastError(); + } + + if (status && *pptu) { + free_alloc_p(pptu); + } + return status; + } + +DWORD +alloc_username( + PSID Sid, + LPSTR* pname, + LPSTR* pdomain = 0 + ) +{ + DWORD status = 0; + DWORD name_len = 0; + DWORD domain_len = 0; + SID_NAME_USE snu; + LPSTR name = 0; + LPSTR domain = 0; + + *pname = 0; + if (pdomain) *pdomain = 0; + + LookupAccountSidA(NULL, Sid, 0, &name_len, 0, &domain_len, &snu); + if ((name_len == 0) || (domain_len == 0)) status = GetLastError(); + + if (!status) { + if (!(name = (LPSTR)malloc_alloc_p(name_len))) status = GetLastError(); + } + + if (!status) { + if (!(domain = (LPSTR)malloc_alloc_p(domain_len))) status = GetLastError(); + } + + if (!status) { + if (!LookupAccountSidA(NULL, Sid, name, &name_len, domain, &domain_len, &snu)) status = GetLastError(); + } + + if (status) { + if (name) free_alloc_p(&name); + if (domain) free_alloc_p(&domain); + } + else { + if (pdomain) { + *pname = name; + *pdomain = domain; + } + else { + DWORD size = name_len + domain_len + 1; + *pname = (LPSTR)malloc_alloc_p(size); + if (!*pname) status = GetLastError(); + else _snprintf(*pname, size, "%s\\%s", name, domain); + } + } + return status; + } + +DWORD get_authentication_id(HANDLE hToken, LUID* pAuthId) { + TOKEN_STATISTICS ts; + DWORD len; + + if (!GetTokenInformation(hToken, TokenStatistics, &ts, sizeof(ts), &len)) + return GetLastError(); + *pAuthId = ts.AuthenticationId; + return 0; + } + +DWORD +alloc_name_9x( + LPSTR* pname, + LPSTR postfix + ) +{ + char prefix[] = "krbcc"; + DWORD len = (sizeof(prefix) - 1) + 1 + strlen(postfix) + 1; + + *pname = (LPSTR)malloc_alloc_p(len); + if (!*pname) return GetLastError(); + _snprintf(*pname, len, "%s.%s", prefix, postfix); + return 0; +} + +DWORD alloc_name_NT(LPSTR* pname, LPSTR postfix) { + DWORD status = 0; + HANDLE hToken = 0; + LUID auth_id; +#ifdef _DEBUG + PTOKEN_USER ptu = 0; + LPSTR name = 0; + LPSTR domain = 0; + LPSTR sid = 0; +#endif + char prefix[] = "krbcc"; + // Play it safe and say 3 characters are needed per 8 bits (byte). + // Note that 20 characters are needed for a 64-bit number in + // decimal (plus one for the string termination. + // and include room for sessionId. + char lid[3*sizeof(LUID)+1+5]; + DWORD sessionId; + DWORD len = 0; + + *pname = 0; + + status = SecureClient::Token(hToken); + + if (!status) { + status = get_authentication_id(hToken, &auth_id); + } + + if (!status) { + if (!ProcessIdToSessionId(GetCurrentProcessId(), &sessionId)) + sessionId = 0; + } + +#ifdef _DEBUG + if (!status) {status = alloc_token_user(hToken, &ptu);} + if (!status) {status = alloc_username(ptu->User.Sid, &name, &domain);} + if (!status) {status = alloc_textual_sid(ptu->User.Sid, &sid);} +#endif + + if (!status) { + _snprintf(lid, sizeof(lid), "%I64u.%u", auth_id, sessionId); + lid[sizeof(lid)-1] = 0; // be safe + + len = (sizeof(prefix) - 1) + 1 + strlen(lid) + 1 + strlen(postfix) + 1; + *pname = (LPSTR)malloc_alloc_p(len); + if (!*pname) status = GetLastError(); + } + + // + // We used to allocate a name of the form: + // "prefix.domain.name.sid.lid.postfix" (usually under 80 + // characters, depending on username). However, XP thought this + // was "invalid" (too long?) for some reason. + // + // Therefore, we now use "prefix.lid.postfix" + // and for Terminal server we use "prefix.lid.sessionId.postfix" + // + + if (!status) { + _snprintf(*pname, len, "%s.%s.%s", prefix, lid, postfix); + } + +#ifdef _DEBUG + if (sid) + free_alloc_p(&sid); + if (name) + free_alloc_p(&name); + if (domain) + free_alloc_p(&domain); + if (ptu) + free_alloc_p(&ptu); +#endif + if (hToken && hToken != INVALID_HANDLE_VALUE) + CloseHandle(hToken); + if (status && *pname) + free_alloc_p(pname); + return status; +} + +extern "C" DWORD alloc_name(LPSTR* pname, LPSTR postfix, BOOL isNT) { + return isNT ? alloc_name_NT(pname, postfix) : + alloc_name_9x(pname, postfix); + } + +extern "C" DWORD alloc_own_security_descriptor_NT(PSECURITY_DESCRIPTOR* ppsd) { + DWORD status = 0; + HANDLE hToken = 0; + PTOKEN_USER ptu = 0; + PSID pSid = 0; + PACL pAcl = 0; + DWORD size = 0; + SECURITY_DESCRIPTOR sd; + + *ppsd = 0; + + if (!status) {status = SecureClient::Token(hToken);} + + // Get SID: + if (!status) {status = alloc_token_user(hToken, &ptu);} + + if (!status) { + size = GetLengthSid(ptu->User.Sid); + pSid = (PSID) malloc_alloc_p(size); + if (!pSid) status = GetLastError(); + } + if (!status) { + if (!CopySid(size, pSid, ptu->User.Sid)) status = GetLastError(); + } + + if (!status) { + // Prepare ACL: + size = sizeof(ACL); + // Add an ACE: + size += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSid); + pAcl = (PACL) malloc_alloc_p(size); + if (!pAcl) status = GetLastError(); + } + + if (!status) { + if (!InitializeAcl(pAcl, size, ACL_REVISION)) status = GetLastError(); + } + + if (!status) { + if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pSid)) status = GetLastError(); + } + + if (!status) { + // Prepare SD itself: + if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) status = GetLastError(); + } + + if (!status) { + if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) status = GetLastError(); + } + + if (!status) { + if (!SetSecurityDescriptorOwner(&sd, pSid, FALSE)) status = GetLastError(); + } + + if (!status) { + if (!IsValidSecurityDescriptor(&sd)) status = ERROR_INVALID_PARAMETER; + } + + if (!status) { + // We now have a SD. Let's copy it. + { + // This should not succeed. Instead it should give us the size. + BOOL ok = MakeSelfRelativeSD(&sd, 0, &size); + } + if (size == 0) status = GetLastError(); + } + + if (!status) { + *ppsd = (PSECURITY_DESCRIPTOR) malloc_alloc_p(size); + if (!*ppsd) status = GetLastError(); + } + + if (!status) { + if (!MakeSelfRelativeSD(&sd, *ppsd, &size)) status = GetLastError(); + } + + if (ptu) free_alloc_p(&ptu); + if (pSid) free_alloc_p(&pSid); + if (pAcl) free_alloc_p(&pAcl); + if (hToken && hToken != INVALID_HANDLE_VALUE) CloseHandle(hToken); + if (status && *ppsd) free_alloc_p(ppsd); + return status; +} + +DWORD +alloc_module_file_name( + char* module, + char** pname + ) +{ + const DWORD max = 8192; + DWORD status = 0; + DWORD got = 0; + DWORD size = 512; // use low number to test... + HMODULE h = 0; + BOOL ok = FALSE; + char* name = 0; + + if (!pname) + return ERROR_INVALID_PARAMETER; + *pname = 0; + + h = GetModuleHandle(module); + + if (!h) return GetLastError(); + + // We assume size < max and size > 0 + while (!status && !ok) { + if (size > max) { + // XXX - Assert? + status = ERROR_INVALID_DATA; + continue; + } + if (name) free_alloc_p(&name); + name = (char*)malloc_alloc_p(size + 1); + if (!name) { + status = ERROR_NOT_ENOUGH_MEMORY; + continue; + } + name[size] = 0; + got = GetModuleFileName(h, name, size); + if (!got) { + status = GetLastError(); + // sanity check: + if (!status) { + // XXX - print nasty message...assert? + status = ERROR_INVALID_DATA; + } + continue; + } + // To know we're ok, we need to verify that what we got + // was bigger than GetModuleSize thought it got. + ok = got && (got < size) && !name[got]; + size *= 2; + } + if (status && name) + free_alloc_p(&name); + else + *pname = name; + return status; +} + +DWORD +alloc_module_dir_name( + char* module, + char** pname + ) +{ + DWORD status = alloc_module_file_name(module, pname); + if (!status) { + char* name = *pname; + char* p = name + strlen(name); + while ((p >= name) && (*p != '\\') && (*p != '/')) p--; + if (p < name) { + free_alloc_p(pname); + status = ERROR_INVALID_DATA; + } else { + *p = 0; + } + } + return status; +} + +DWORD +alloc_module_dir_name_with_file( + char* module, + char* file, + char** pname + ) +{ + DWORD status = alloc_module_dir_name(module, pname); + if (!status) { + char* name = *pname; + size_t name_size = strlen(name); + size_t size = name_size + 1 + strlen(file) + 1; + char* result = (char*)malloc_alloc_p(size); + if (!result) { + status = ERROR_NOT_ENOUGH_MEMORY; + free_alloc_p(pname); + } else { + strcpy(result, name); + result[name_size] = '\\'; + strcpy(result + name_size + 1, file); + free_alloc_p(pname); + *pname = result; + } + } + return status; +} + +DWORD alloc_cmdline_2_args(char* prog, + char* arg1, + char* arg2, + char** pname) { + DWORD status = 0; + size_t size = strlen(prog) + strlen(arg1) + strlen(arg2) + 4; + char* result = (char*)malloc_alloc_p(size); + if (!result) { + status = ERROR_NOT_ENOUGH_MEMORY; + } + else { + strcpy(result, prog); + strcat(result, " "); + strcat(result, arg1); + strcat(result, " "); + strcat(result, arg2); + *pname = result; + } + cci_debug_printf("%s made <%s>", __FUNCTION__, result); + return status; + } diff --git a/krb5-1.21.3/src/ccapi/common/win/OldCC/util.h b/krb5-1.21.3/src/ccapi/common/win/OldCC/util.h new file mode 100644 index 00000000..45e069a7 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/OldCC/util.h @@ -0,0 +1,85 @@ +/* ccapi/common/win/OldCC/util.h */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __UTIL_H__ +#define __UTIL_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +BOOL isNT(); + +void* +user_allocate( + size_t size + ); + +void +user_free( + void* ptr + ); + +void +free_alloc_p( + void* pptr + ); + +DWORD +alloc_name( + LPSTR* pname, + LPSTR postfix, + BOOL isNT + ); + +DWORD +alloc_own_security_descriptor_NT( + PSECURITY_DESCRIPTOR* ppsd + ); + +DWORD +alloc_module_dir_name( + char* module, + char** pname + ); + +DWORD +alloc_module_dir_name_with_file( + char* module, + char* file, + char** pname + ); + +DWORD alloc_cmdline_2_args( + char* prog, + char* arg1, + char* arg2, + char** pname); + +#ifdef __cplusplus +} +#endif + +#endif /* __UTIL_H__ */ diff --git a/krb5-1.21.3/src/ccapi/common/win/cci_os_debugging.c b/krb5-1.21.3/src/ccapi/common/win/cci_os_debugging.c new file mode 100644 index 00000000..597ac856 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/cci_os_debugging.c @@ -0,0 +1,40 @@ +/* ccapi/common/win/cci_os_debugging.c */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include + +#include "cci_os_debugging.h" +#include "win-utils.h" + +/* ------------------------------------------------------------------------ */ + +void cci_os_debug_vprintf (const char *in_format, va_list in_args) { +#ifdef DEBUG + printf ( "%s %ld ", timestamp(), GetCurrentThreadId() ); + vprintf ( in_format, in_args ); + printf ( "\n" ); +#endif + } diff --git a/krb5-1.21.3/src/ccapi/common/win/cci_os_identifier.c b/krb5-1.21.3/src/ccapi/common/win/cci_os_identifier.c new file mode 100644 index 00000000..4be2638b --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/cci_os_identifier.c @@ -0,0 +1,57 @@ +/* ccapi/common/win/cci_os_identifier.c */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "cci_common.h" +#include "cci_os_identifier.h" + +#include + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_os_identifier_new_uuid (cci_uuid_string_t *out_uuid_string) { + cc_int32 err = ccNoError; + UUID uuid; + char* uuidStringTemp; + + err = UuidCreate(&uuid); + + if (!err) { + err = UuidToString(&uuid, &uuidStringTemp); + } + + if (!err) { + *out_uuid_string = malloc(1+strlen(uuidStringTemp)); + + if (*out_uuid_string) { + strcpy(*out_uuid_string, uuidStringTemp); + } + + RpcStringFree(&uuidStringTemp); + } + + cci_debug_printf("cci_os_identifier_new_uuid returning %s", *out_uuid_string); + + return cci_check_error (err); + } \ No newline at end of file diff --git a/krb5-1.21.3/src/ccapi/common/win/ccs_reply.Acf b/krb5-1.21.3/src/ccapi/common/win/ccs_reply.Acf new file mode 100644 index 00000000..aea44d74 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/ccs_reply.Acf @@ -0,0 +1,31 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +[implicit_handle(handle_t ccs_reply_IfHandle)] + +interface ccs_reply { + [async] ccapi_listen(); + } diff --git a/krb5-1.21.3/src/ccapi/common/win/ccs_reply.Idl b/krb5-1.21.3/src/ccapi/common/win/ccs_reply.Idl new file mode 100644 index 00000000..73e81868 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/ccs_reply.Idl @@ -0,0 +1,60 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +[ uuid (6E3B5060-CA46-1067-B31A-00DD010662DA), + version(1.0), + pointer_default(unique) +] + +/* This interface sends a cci_stream via rpc. + */ + +interface ccs_reply { + const long HSIZE = 8; + +/* The reply from the server to a request from the client: */ +void ccs_rpc_request_reply( + [in] const long rpcmsg, /* Message type */ + [in, size_is(HSIZE)] const char tsphandle[], + [in, string] const char* uuid, + [in] const long srvStartTime, /* Server Start Time */ + [in] const long cbIn, /* Length of buffer */ + [in, size_is(cbIn)] const unsigned char chIn[], /* Data buffer */ + [out] long* status ); /* Return code */ + +void ccs_rpc_connect_reply( + [in] const long rpcmsg, /* Message type */ + [in, size_is(HSIZE)] const char tsphandle[], + [in, string] const char* uuid, + [in] const long srvStartTime, /* Server Start Time */ + [out] long* status ); /* Return code */ + +void ccapi_listen( + handle_t hBinding, + [in] const long rpcmsg, /* Message type */ + [out] long* status ); /* Return code */ + + } diff --git a/krb5-1.21.3/src/ccapi/common/win/ccs_request.Acf b/krb5-1.21.3/src/ccapi/common/win/ccs_request.Acf new file mode 100644 index 00000000..625bcce6 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/ccs_request.Acf @@ -0,0 +1,31 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +[implicit_handle(handle_t ccs_request_IfHandle)] +interface ccs_request +{ + +} diff --git a/krb5-1.21.3/src/ccapi/common/win/ccs_request.idl b/krb5-1.21.3/src/ccapi/common/win/ccs_request.idl new file mode 100644 index 00000000..cad5e444 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/ccs_request.idl @@ -0,0 +1,58 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +[ uuid (906B0CE0-C70B-1067-B317-00DD010662DA), + version(1.0), + pointer_default(unique) +] + +interface ccs_request { + +typedef char CC_CHAR; +typedef unsigned char CC_UCHAR; +typedef int CC_INT32; +typedef unsigned int CC_UINT32; + +const long HSIZE = 8; + +void ccs_rpc_request( + [in] const long rpcmsg, /* Message type */ + [in, size_is(HSIZE)] const char tsphandle[], + [in, string] const char* pszUUID, /* Requestor's UUID */ + [in] const long lenRequest, /* Length of buffer */ + [in, size_is(lenRequest)] const char* pszRequest, /* Data buffer */ + [in] const long serverStartTime,/* Which server session we're talking to */ + [out] long* status ); /* Return code */ + +void ccs_rpc_connect( + [in] const long rpcmsg, /* Message type */ + [in, size_is(HSIZE)] const char tsphandle[], + [in, string] const char* pszUUID, /* Requestor's UUID */ + [out] long* status ); /* Return code */ + +CC_UINT32 ccs_authenticate( + [in, string] const CC_CHAR* name ); +} diff --git a/krb5-1.21.3/src/ccapi/common/win/tls.c b/krb5-1.21.3/src/ccapi/common/win/tls.c new file mode 100644 index 00000000..6c13d5a9 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/tls.c @@ -0,0 +1,77 @@ +/* ccapi/common/win/tls.c */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "string.h" +#include +#include + +#include "tls.h" + +void tspdata_setUUID(struct tspdata* p, unsigned char __RPC_FAR* uuidString) { + strncpy(p->_uuid, uuidString, UUID_SIZE-1); + }; + +void tspdata_setListening (struct tspdata* p, BOOL b) {p->_listening = b;} + +void tspdata_setConnected (struct tspdata* p, BOOL b) {p->_CCAPI_Connected = b;} + +void tspdata_setReplyEvent(struct tspdata* p, HANDLE h) {p->_replyEvent = h;} + +void tspdata_setRpcAState (struct tspdata* p, RPC_ASYNC_STATE* rpcState) { + p->_rpcState = rpcState;} + +void tspdata_setSST (struct tspdata* p, time_t t) {p->_sst = t;} + +void tspdata_setStream (struct tspdata* p, k5_ipc_stream s) {p->_stream = s;} + +BOOL tspdata_getListening (const struct tspdata* p) {return p->_listening;} + +BOOL tspdata_getConnected (const struct tspdata* p) {return p->_CCAPI_Connected;} + +HANDLE tspdata_getReplyEvent(const struct tspdata* p) {return p->_replyEvent;} + +time_t tspdata_getSST (const struct tspdata* p) {return p->_sst;} + +k5_ipc_stream tspdata_getStream (const struct tspdata* p) {return p->_stream;} + +char* tspdata_getUUID (const struct tspdata* p) {return p->_uuid;} + +RPC_ASYNC_STATE* tspdata_getRpcAState (const struct tspdata* p) {return p->_rpcState;} + + +BOOL WINAPI GetTspData(DWORD dwTlsIndex, struct tspdata** pdw) { + struct tspdata* pData; // The stored memory pointer + + pData = (struct tspdata*)TlsGetValue(dwTlsIndex); + if (pData == NULL) { + pData = malloc(sizeof(*pData)); + if (pData == NULL) + return FALSE; + memset(pData, 0, sizeof(*pData)); + TlsSetValue(dwTlsIndex, pData); + } + (*pdw) = pData; + return TRUE; + } diff --git a/krb5-1.21.3/src/ccapi/common/win/tls.h b/krb5-1.21.3/src/ccapi/common/win/tls.h new file mode 100644 index 00000000..bd2bb9e1 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/tls.h @@ -0,0 +1,71 @@ +/* ccapi/common/win/tls.h */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Thread local storage for client threads. */ + +#ifndef _tls_h +#define _tls_h + +#include "windows.h" +#include "time.h" +#include "rpc.h" + +#include "k5-ipc_stream.h" + +#define UUID_SIZE 128 + +/* The client code can be run in any client thread. + The thread-specific data is defined here. + */ + +struct tspdata { + BOOL _listening; + BOOL _CCAPI_Connected; + RPC_ASYNC_STATE* _rpcState; + HANDLE _replyEvent; + time_t _sst; + k5_ipc_stream _stream; + char _uuid[UUID_SIZE]; + }; + +void tspdata_setListening (struct tspdata* p, BOOL b); +void tspdata_setConnected (struct tspdata* p, BOOL b); +void tspdata_setReplyEvent(struct tspdata* p, HANDLE h); +void tspdata_setRpcAState (struct tspdata* p, RPC_ASYNC_STATE* rpcState); +void tspdata_setSST (struct tspdata* p, time_t t); +void tspdata_setStream (struct tspdata* p, k5_ipc_stream s); +void tspdata_setUUID (struct tspdata* p, unsigned char __RPC_FAR* uuidString); +HANDLE tspdata_getReplyEvent(const struct tspdata* p); + +BOOL tspdata_getListening(const struct tspdata* p); +BOOL tspdata_getConnected(const struct tspdata* p); +RPC_ASYNC_STATE* tspdata_getRpcAState(const struct tspdata* p); +time_t tspdata_getSST (const struct tspdata* p); +k5_ipc_stream tspdata_getStream (const struct tspdata* p); +char* tspdata_getUUID (const struct tspdata* p); + +BOOL WINAPI GetTspData(DWORD tlsIndex, struct tspdata** pdw); + +#endif _tls_h diff --git a/krb5-1.21.3/src/ccapi/common/win/win-utils.c b/krb5-1.21.3/src/ccapi/common/win/win-utils.c new file mode 100644 index 00000000..b49cca85 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/win-utils.c @@ -0,0 +1,68 @@ +/* ccapi/common/win/win-utils.c */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include +#include "windows.h" +#include +#include + + +#include "win-utils.h" +#include "cci_debugging.h" + +#pragma warning (disable : 4996) + +#define UUID_SIZE 128 + +char* clientPrefix = "CCAPI_CLIENT_"; +char* serverPrefix = "CCS_LISTEN_"; +unsigned char* pszProtocolSequence = "ncalrpc"; + +#define MAX_TIMESTAMP 40 +char _ts[MAX_TIMESTAMP]; + +char* clientEndpoint(const char* UUID) { + char* _clientEndpoint = (char*)malloc(strlen(UUID) + strlen(clientPrefix) + 2); + strcpy(_clientEndpoint, clientPrefix); + strncat(_clientEndpoint, UUID, UUID_SIZE); +// cci_debug_printf("%s returning %s", __FUNCTION__, _clientEndpoint); + return _clientEndpoint; + } + +char* serverEndpoint(const char* user) { + char* _serverEndpoint = (char*)malloc(strlen(user) + strlen(serverPrefix) + 2); + strcpy(_serverEndpoint, serverPrefix); + strncat(_serverEndpoint, user, UUID_SIZE); + return _serverEndpoint; + } + +char* timestamp() { + SYSTEMTIME _stime; + GetSystemTime(&_stime); + GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &_stime, "HH:mm:ss", _ts, sizeof(_ts)-1); + return _ts; + } diff --git a/krb5-1.21.3/src/ccapi/common/win/win-utils.h b/krb5-1.21.3/src/ccapi/common/win/win-utils.h new file mode 100644 index 00000000..41cab24d --- /dev/null +++ b/krb5-1.21.3/src/ccapi/common/win/win-utils.h @@ -0,0 +1,55 @@ +/* ccapi/common/win/win-utils.h */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef _win_utils_h +#define _win_utils_h + +#ifndef TRUE +#define TRUE (1==1) +#endif + +#ifndef FALSE +#define FALSE (1==0) +#endif + +static enum ccapiMsgType { + CCMSG_INVALID = 0, + CCMSG_CONNECT, + CCMSG_REQUEST, + CCMSG_CONNECT_REPLY, + CCMSG_REQUEST_REPLY, + CCMSG_DISCONNECT, + CCMSG_LISTEN, + CCMSG_PING, + CCMSG_QUIT + }; + +char* clientEndpoint(const char* UUID); +char* serverEndpoint(const char* UUID); +extern unsigned char* pszProtocolSequence; + +char* timestamp(); + +#endif // _win_utils_h \ No newline at end of file diff --git a/krb5-1.21.3/src/ccapi/deps b/krb5-1.21.3/src/ccapi/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/ccapi/doc/CCAPI-Windows-Design.html b/krb5-1.21.3/src/ccapi/doc/CCAPI-Windows-Design.html new file mode 100644 index 00000000..dd32acba --- /dev/null +++ b/krb5-1.21.3/src/ccapi/doc/CCAPI-Windows-Design.html @@ -0,0 +1,148 @@ + + + + +Windows CCAPI RPC design + + + + +

      Proposed RPC design for Windows CCAPI clients and server

      +

      The proposal is for a single user; the solution is replicated for each user logged onto the PC.

      +

      Conventions & clarifications

      +

      "Client" and "server" refer to the CCAPI client and server.

      +

      The CCAPI client acts as both an RPC client and RPC server and the CCAPI server acts as both an RPC client and RPC server.

      +
        +
      • The RPC call from the CCAPI client to the CCAPI server is called the "request." In this mode, the CCAPI client is the RPC client and the CCAPI server is the RPC server.
      • +
      • The RPC call from the CCAPI server to the CCAPI client is called the "reply." In this mode, the CCAPI client is the RPC server and the CCAPI server is the RPC client.
      • +
      +

      The Windows username is referred to below as "<USER>."

      +

      The Windows Logon Security Identifier is referred to as "<LSID>."

      +

      <UUID> means a thread-specific UUID.

      +

      <SST> means server start time, a time_t.

      +

      A description of client and server authentication has not been added yet.

      +

      Design Requirements

      +
        +
      • The server's OS-independent code is single threaded, because it must operate on platforms that do not allow multiple threads.
      • +
      • The client and server must be able to maintain connections, where state is maintained between individual messages.
      • +
      • Individual messages must be handled in a single threaded server.
      • +
      • The server must be able to detect when a client dies, so that any connection state can be cleaned up.
      • +
      +

      Design

      +

      The server and each client create an RPC endpoint. The server's endpoint is CCS_<LSID> and the client's endpoint is CCAPI_<UUID>, where each client geta a UUID.

      +

      On Windows, the server's ccs_pipe_t type is a char* and is set to the client UUID.

      +

      How is the request handled in the server and the reply sent to the client?

      +

      One straightforward way is for the reply to be the returned data in the request RPC call (an [out] parameter). That is, data passed from the RPC server to the RPC client. The request handler calls ccs_server_handle_request. Eventually, the server code calls ccs_os_server_send_reply, which saves the reply somewhere. When the server eventually returns to the request handler, the handler returns the saved reply to the client.

      +

      But this doesn't work. If two clients A and B ask for the same lock, A will acquire the lock and B will have to wait. But if the single threaded server waits for B's lock, it will never handle A's unlock message. Therefore the server must return to B's request handler and not send a reply to B. So this method will not work.

      +

      Instead, there are listener and worker threads in Windows-specific code.

      +

      The client's cci_os_ipc function waits for ccs_reply. The client sends the request, including its UUID, from which the server can construct the endpoint on which to call ccs_reply.

      +

      The server's listener thread listens for RPC requests. The request handler puts each request/reply endpoint in a queue and returns to the client.

      +

      The server's worker thread removes items from the queue, calls ccs_server_handle_request. ccs_server_handle_request takes both the request data and the client UUID . Eventually ccs_os_server_send_reply is called, with the reply data and client UUID in the reply_pipe. ccs_os_server_send_reply calls ccs_reply on the client's endpoint, which sends the reply to the client.

      +

      Is there any security issue with the client listening for RPC calls from the server?

      +

      Connections

      +

      If the client wants state to be maintained on the server, the client creates a connection. When the connection is closed, the server cleans up any state associated with the connection.

      +

      Any given thread in an application process could want to create a connection. When cci_ipc_thread_init is called, the connection thread-local variables are initialized. New connections are created when cci_os_ipc() (via _cci_ipc_send) is called and no connection was previously established. Basically we lazily establish connections so the client doesn't talk to the server until it has to.

      +

      Detecting client exit

      +

      The server must be able to detect when clients disappear, so the server can free any resources that had been held for the client.

      +

      The Windows RPC API does not appear to provide a notification for an endpoint disappearing. It does provide a way to ask if an endpoint is listening. This is useful for polling, but we want a better performing solution than that.

      +

      The client has an isAlive function on its endpoint.

      +

      To detect the client disappearing without using polling, the server makes an asynchronous call to the isAlive function on the client's endpoint. The isAlive function never returns. When the client exits for any reason, its endpoint will be closed and the server's function call will return an error. The asynchronous call on the server means no additional threads are used.

      +

      Windows provides a number of notification methods to signal I/O completion. Among them are I/O completion ports and callback functions. I chose callback functions because they appear to consume fewer resources.

      +

      RPC Endpoint / Function summary

      +
        +
      • The server creates one CCS_<LSID> endpoint to listen for connection requests and client requests. + It has the functions +
          +
        • ccs_rpc_connect(msgtype, UUIDlen, <UUID>, status)
        • +
        • ccs_rpc_request(msgtype, UUIDlen, <UUID>, msglen, msg, SST, status) called by client. NB: The windows server sets the in_client_pipe to the in_reply_pipe.
          +
        • +
        +
      • +
      • Each client thread creates a CCAPI_<UUID> endpoint. It has the functions +
          +
        • isAlive [function never returns.]
        • +
        • ccs_rpc_request_reply(msgtype, SST, replylen, reply, status)
        • +
        • ccs_rpc_connect_reply(msgtype, SST, status
        • +
        +
      • +
      +

      Windows-specific implementation details

      +

      Client CCAPI library initialization:

      +

      This code runs when the CCAPI DLL is loaded.

      +
        +
      • ?
      • +
      +

      Client initialization:

      +

      This code runs when cci_os_ipc_thread_init is called:

      +
        +
      • Generate <UUID> and save in thread-specific storage. This serves as the client ID / ccs_pipe_t.
      • +
      • Create client endpoint.
      • +
      • Listen on client endpoint.
      • +
      • Create canonical server connection endpoint from the <LSID>, which the client and server should have in common.
      • +
      • Test if server is listening to the CCS_<LSID> endpoint. +
          +
        • If not, quit. (! Start it?)
        • +
        +
      • +
      • Call ccs_connect(<UUID>) on the CCS_<LSID> endpoint.
      • +
      • Save SST in thread-specific storage.
      • +
      +

      Server initialization:

      +

      [old]

      +
        +
      • Server is initialized by client starting a new process. There should be only one server process per Windows username.
      • +
      +

      [new]

      +
        +
      • Server is started by kfwlogon (as is done currently).
      • +
      • Capture server start time (SST).
      • +
      • Start listener thread, create listener endpoint, listen on CCS_<LSID> endpoint.
      • +
      +

      Establishing a connection:

      +
        +
      • Client calls ccs_connect(<UUID>) on server's CCS_<LSID> endpoint.
      • +
      • Client gets back and stores SST in thread-specific storage.
      • +
      • If new connection, server ... +
          +
        • adds connection to connection table
        • +
        • calls isAlive on CCAPI_<UUID>. +
            +
          • NB: isAlive never returns.
          • +
          +
        • +
        +
      • +
      +

      Client request:

      +

      The server's reply to the client's request is not synchronous.

      +
        +
      • Client calls ccs_rpc_request(msglen, msg, msgtype, UUIDlen, <UUID>, SST, status) on server's endpoint.
      • +
      • Server listen thread receives message, queues request.
      • +
      • Server worker thread dequeues request, processes, calls ccs_rpc_reply(replylen, reply, msgtype, status) on CCAPI_<UUID>.
      • +
      • Server checks SST. If server's SST is different, it means server has restarted since client created connection.
      • +
      • Client receives reply.
      • +
      +

      Detecting client exit

      +
        +
      • When connection created, client created an endpoint.
      • +
      • Server calls isAlive on client's endpoint.
      • +
      • When isAlive returns, the server's notification callback will be called. Call back routine queues a DISCONNECT pseudo-message. When the server's worker thread handles the DISCONNECT, it will release connection resources.
      • +
      +

      Detecting server exit

      +
        +
      • Client's call to ccs_rpc_request will return an error if the server has gone away.
      • +
      +

       

      +

      ------
      + Stop:
      +Start:

      + + diff --git a/krb5-1.21.3/src/ccapi/lib/Makefile.in b/krb5-1.21.3/src/ccapi/lib/Makefile.in new file mode 100644 index 00000000..241e28b0 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/Makefile.in @@ -0,0 +1,61 @@ +mydir=ccapi$(S)lib +BUILDTOP=$(REL)..$(S).. +SUBDIRS=unix +LOCALINCLUDES=-I$(srcdir)/../common -I. + +SHLIB_EXPDEPS= $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB) +SHLIB_EXPLIBS=$(COM_ERR_LIB) $(SUPPORT_LIB) +RELDIR=../ccapi/lib + +LIBBASE=krb5-ccapi +LIBMAJOR=1 +LIBMINOR=0 + +STOBJLISTS= \ + OBJS.ST \ + unix/OBJS.ST + +STLIBOBJS= \ + ccapi_ccache.o \ + ccapi_ccache_iterator.o \ + ccapi_context.o \ + ccapi_context_change_time.o \ + ccapi_credentials.o \ + ccapi_credentials_iterator.o \ + ccapi_err.o \ + ccapi_ipc.o \ + ccapi_string.o \ + ccapi_v2.o + +OBJS= \ + $(OUTPRE)ccapi_ccache.$(OUTPRE) \ + $(OUTPRE)ccapi_ccache_iterator.$(OUTPRE) \ + $(OUTPRE)ccapi_context.$(OUTPRE) \ + $(OUTPRE)ccapi_context_change_time.$(OUTPRE) \ + $(OUTPRE)ccapi_credentials.$(OUTPRE) \ + $(OUTPRE)ccapi_credentials_iterator.$(OUTPRE) \ + $(OUTPRE)ccapi_err.$(OUTPRE) \ + $(OUTPRE)ccapi_ipc.$(OUTPRE) \ + $(OUTPRE)ccapi_string.$(OUTPRE) \ + $(OUTPRE)ccapi_v2.$(OUTPRE) + +SRCS= \ + ccapi_ccache.c \ + ccapi_ccache_iterator.c \ + ccapi_context.c \ + ccapi_context_change_time.c \ + ccapi_credentials.c \ + ccapi_credentials_iterator.c \ + ccapi_err.c \ + ccapi_ipc.c \ + ccapi_string.c \ + ccapi_v2.c + +ccapi_err.c ccapi_err.h : ccapi_err.et + +all-unix: all-libobjs all-liblinks +clean-unix:: clean-libobjs clean-liblinks clean-libs + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi.exports b/krb5-1.21.3/src/ccapi/lib/ccapi.exports new file mode 100644 index 00000000..92c859bd --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi.exports @@ -0,0 +1 @@ +cc_initialize diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_ccache.c b/krb5-1.21.3/src/ccapi/lib/ccapi_ccache.c new file mode 100644 index 00000000..9e8ba36c --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_ccache.c @@ -0,0 +1,793 @@ +/* ccapi/lib/ccapi_ccache.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccapi_ccache.h" + +#include "ccapi_string.h" +#include "ccapi_credentials.h" +#include "ccapi_credentials_iterator.h" +#include "ccapi_ipc.h" + +/* ------------------------------------------------------------------------ */ + +typedef struct cci_ccache_d { + cc_ccache_f *functions; +#if TARGET_OS_MAC + cc_ccache_f *vector_functions; +#endif + cci_identifier_t identifier; + cc_time_t last_wait_for_change_time; + cc_uint32 compat_version; +} *cci_ccache_t; + +/* ------------------------------------------------------------------------ */ + +struct cci_ccache_d cci_ccache_initializer = { + NULL + VECTOR_FUNCTIONS_INITIALIZER, + NULL, + 0 +}; + +cc_ccache_f cci_ccache_f_initializer = { + ccapi_ccache_release, + ccapi_ccache_destroy, + ccapi_ccache_set_default, + ccapi_ccache_get_credentials_version, + ccapi_ccache_get_name, + ccapi_ccache_get_principal, + ccapi_ccache_set_principal, + ccapi_ccache_store_credentials, + ccapi_ccache_remove_credentials, + ccapi_ccache_new_credentials_iterator, + ccapi_ccache_move, + ccapi_ccache_lock, + ccapi_ccache_unlock, + ccapi_ccache_get_last_default_time, + ccapi_ccache_get_change_time, + ccapi_ccache_compare, + ccapi_ccache_get_kdc_time_offset, + ccapi_ccache_set_kdc_time_offset, + ccapi_ccache_clear_kdc_time_offset, + ccapi_ccache_wait_for_change +}; + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_new (cc_ccache_t *out_ccache, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = NULL; + + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + ccache = malloc (sizeof (*ccache)); + if (ccache) { + *ccache = cci_ccache_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + ccache->functions = malloc (sizeof (*ccache->functions)); + if (ccache->functions) { + *ccache->functions = cci_ccache_f_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = cci_identifier_copy (&ccache->identifier, in_identifier); + } + + if (!err) { + *out_ccache = (cc_ccache_t) ccache; + ccache = NULL; /* take ownership */ + } + + ccapi_ccache_release ((cc_ccache_t) ccache); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_write (cc_ccache_t in_ccache, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + + if (!in_ccache) { err = cci_check_error (ccErrBadParam); } + if (!in_stream) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (ccache->identifier, in_stream); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_release (cc_ccache_t io_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + + if (!io_ccache) { err = ccErrBadParam; } + + if (!err) { + cci_identifier_release (ccache->identifier); + + free ((char *) ccache->functions); + free (ccache); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_destroy (cc_ccache_t io_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_destroy_msg_id, + ccache->identifier, + NULL, + NULL); + } + + if (!err) { + err = ccapi_ccache_release (io_ccache); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_set_default (cc_ccache_t io_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_set_default_msg_id, + ccache->identifier, + NULL, + NULL); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_get_credentials_version (cc_ccache_t in_ccache, + cc_uint32 *out_credentials_version) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream reply = NULL; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials_version) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_get_credentials_version_msg_id, + ccache->identifier, + NULL, + &reply); + } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (reply, out_credentials_version); + } + + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_get_name (cc_ccache_t in_ccache, + cc_string_t *out_name) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream reply = NULL; + char *name = NULL; + + if (!in_ccache) { err = cci_check_error (ccErrBadParam); } + if (!out_name ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_get_name_msg_id, + ccache->identifier, + NULL, + &reply); + } + + if (!err) { + err = krb5int_ipc_stream_read_string (reply, &name); + } + + if (!err) { + err = cci_string_new (out_name, name); + } + + krb5int_ipc_stream_release (reply); + krb5int_ipc_stream_free_string (name); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_get_principal (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_string_t *out_principal) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + char *principal = NULL; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_principal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_get_principal_msg_id, + ccache->identifier, + request, + &reply); + } + + if (!err) { + err = krb5int_ipc_stream_read_string (reply, &principal); + } + + if (!err) { + err = cci_string_new (out_principal, principal); + } + + krb5int_ipc_stream_release (request); + krb5int_ipc_stream_release (reply); + krb5int_ipc_stream_free_string (principal); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_set_principal (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + const char *in_principal) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + k5_ipc_stream request = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_principal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version); + } + + if (!err) { + err = krb5int_ipc_stream_write_string (request, in_principal); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_set_principal_msg_id, + ccache->identifier, + request, + NULL); + } + + krb5int_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_store_credentials (cc_ccache_t io_ccache, + const cc_credentials_union *in_credentials_union) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + k5_ipc_stream request = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_credentials_union) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = cci_credentials_union_write (in_credentials_union, request); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_store_credentials_msg_id, + ccache->identifier, + request, + NULL); + } + + krb5int_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_remove_credentials (cc_ccache_t io_ccache, + cc_credentials_t in_credentials) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + k5_ipc_stream request = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_credentials) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = cci_credentials_write (in_credentials, request); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_remove_credentials_msg_id, + ccache->identifier, + request, + NULL); + } + + krb5int_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_new_credentials_iterator (cc_ccache_t in_ccache, + cc_credentials_iterator_t *out_credentials_iterator) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_new_credentials_iterator_msg_id, + ccache->identifier, + NULL, + &reply); + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_credentials_iterator_new (out_credentials_iterator, identifier); + } + + krb5int_ipc_stream_release (reply); + cci_identifier_release (identifier); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ +/* Note: message is sent as the destination to avoid extra work on the */ +/* server when deleting it the source ccache. */ + +cc_int32 ccapi_ccache_move (cc_ccache_t io_source_ccache, + cc_ccache_t io_destination_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_t source_ccache = (cci_ccache_t) io_source_ccache; + cci_ccache_t destination_ccache = (cci_ccache_t) io_destination_ccache; + k5_ipc_stream request = NULL; + + if (!io_source_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = cci_identifier_write (source_ccache->identifier, request); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_move_msg_id, + destination_ccache->identifier, + request, + NULL); + } + + krb5int_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_lock (cc_ccache_t io_ccache, + cc_uint32 in_lock_type, + cc_uint32 in_block) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + k5_ipc_stream request = NULL; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (request, in_lock_type); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (request, in_block); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_lock_msg_id, + ccache->identifier, + request, + NULL); + } + + krb5int_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_unlock (cc_ccache_t io_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_unlock_msg_id, + ccache->identifier, + NULL, + NULL); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_get_last_default_time (cc_ccache_t in_ccache, + cc_time_t *out_last_default_time) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream reply = NULL; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_last_default_time) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_get_last_default_time_msg_id, + ccache->identifier, + NULL, + &reply); + } + + if (!err) { + err = krb5int_ipc_stream_read_time (reply, out_last_default_time); + } + + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_get_change_time (cc_ccache_t in_ccache, + cc_time_t *out_change_time) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream reply = NULL; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_change_time) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_ccache_get_change_time_msg_id, + ccache->identifier, + NULL, + &reply); + } + + if (!err) { + err = krb5int_ipc_stream_read_time (reply, out_change_time); + } + + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_wait_for_change (cc_ccache_t in_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + + if (!in_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_time (request, ccache->last_wait_for_change_time); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_wait_for_change_msg_id, + ccache->identifier, + request, + &reply); + } + + if (!err) { + err = krb5int_ipc_stream_read_time (reply, &ccache->last_wait_for_change_time); + } + + krb5int_ipc_stream_release (request); + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_compare (cc_ccache_t in_ccache, + cc_ccache_t in_compare_to_ccache, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + cci_ccache_t compare_to_ccache = (cci_ccache_t) in_compare_to_ccache; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_compare_to_ccache) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_compare (ccache->identifier, + compare_to_ccache->identifier, + out_equal); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_get_kdc_time_offset (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_time_t *out_time_offset) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_time_offset) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_get_kdc_time_offset_msg_id, + ccache->identifier, + request, + &reply); + } + + if (!err) { + err = krb5int_ipc_stream_read_time (reply, out_time_offset); + } + + krb5int_ipc_stream_release (request); + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_set_kdc_time_offset (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + cc_time_t in_time_offset) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + k5_ipc_stream request = NULL; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version); + } + + if (!err) { + err = krb5int_ipc_stream_write_time (request, in_time_offset); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_set_kdc_time_offset_msg_id, + ccache->identifier, + request, + NULL); + } + + krb5int_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_clear_kdc_time_offset (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + k5_ipc_stream request = NULL; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (request, in_credentials_version); + } + + if (!err) { + err = cci_ipc_send (cci_ccache_clear_kdc_time_offset_msg_id, + ccache->identifier, + request, + NULL); + } + + krb5int_ipc_stream_release (request); + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_get_compat_version (cc_ccache_t in_ccache, + cc_uint32 *out_compat_version) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) in_ccache; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_compat_version) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_compat_version = ccache->compat_version; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_set_compat_version (cc_ccache_t io_ccache, + cc_uint32 in_compat_version) +{ + cc_int32 err = ccNoError; + cci_ccache_t ccache = (cci_ccache_t) io_ccache; + + if (!io_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + ccache->compat_version = in_compat_version; + } + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_ccache.h b/krb5-1.21.3/src/ccapi/lib/ccapi_ccache.h new file mode 100644 index 00000000..e6fc129a --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_ccache.h @@ -0,0 +1,105 @@ +/* ccapi/lib/ccapi_ccache.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCAPI_CCACHE_H +#define CCAPI_CCACHE_H + +#include "cci_common.h" + +cc_int32 cci_ccache_new (cc_ccache_t *out_ccache, + cci_identifier_t in_identifier); + +cc_int32 ccapi_ccache_release (cc_ccache_t io_ccache); + +cc_int32 cci_ccache_write (cc_ccache_t in_ccache, + k5_ipc_stream in_stream); + +cc_int32 ccapi_ccache_destroy (cc_ccache_t io_ccache); + +cc_int32 ccapi_ccache_set_default (cc_ccache_t io_ccache); + +cc_int32 ccapi_ccache_get_credentials_version (cc_ccache_t in_ccache, + cc_uint32 *out_credentials_version); + +cc_int32 ccapi_ccache_get_name (cc_ccache_t in_ccache, + cc_string_t *out_name); + +cc_int32 ccapi_ccache_get_principal (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_string_t *out_principal); + +cc_int32 ccapi_ccache_set_principal (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + const char *in_principal); + +cc_int32 ccapi_ccache_store_credentials (cc_ccache_t io_ccache, + const cc_credentials_union *in_credentials_union); + +cc_int32 ccapi_ccache_remove_credentials (cc_ccache_t io_ccache, + cc_credentials_t in_credentials); + +cc_int32 ccapi_ccache_new_credentials_iterator (cc_ccache_t in_ccache, + cc_credentials_iterator_t *out_credentials_iterator); + +cc_int32 ccapi_ccache_move (cc_ccache_t io_source_ccache, + cc_ccache_t io_destination_ccache); + +cc_int32 ccapi_ccache_lock (cc_ccache_t io_ccache, + cc_uint32 in_lock_type, + cc_uint32 in_block); + +cc_int32 ccapi_ccache_unlock (cc_ccache_t io_ccache); + +cc_int32 ccapi_ccache_get_last_default_time (cc_ccache_t in_ccache, + cc_time_t *out_last_default_time); + +cc_int32 ccapi_ccache_get_change_time (cc_ccache_t in_ccache, + cc_time_t *out_change_time); + +cc_int32 ccapi_ccache_wait_for_change (cc_ccache_t in_ccache); + +cc_int32 ccapi_ccache_compare (cc_ccache_t in_ccache, + cc_ccache_t in_compare_to_ccache, + cc_uint32 *out_equal); + +cc_int32 ccapi_ccache_get_kdc_time_offset (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_time_t *out_time_offset); + +cc_int32 ccapi_ccache_set_kdc_time_offset (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + cc_time_t in_time_offset); + +cc_int32 ccapi_ccache_clear_kdc_time_offset (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version); + +cc_int32 cci_ccache_get_compat_version (cc_ccache_t in_ccache, + cc_uint32 *out_compat_version); + +cc_int32 cci_ccache_set_compat_version (cc_ccache_t io_ccache, + cc_uint32 in_compat_version); + + +#endif /* CCAPI_CCACHE_H */ diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_ccache_iterator.c b/krb5-1.21.3/src/ccapi/lib/ccapi_ccache_iterator.c new file mode 100644 index 00000000..795610d9 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_ccache_iterator.c @@ -0,0 +1,291 @@ +/* ccapi/lib/ccapi_ccache_iterator.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccapi_ccache_iterator.h" +#include "ccapi_ccache.h" +#include "ccapi_ipc.h" + +/* ------------------------------------------------------------------------ */ + +typedef struct cci_ccache_iterator_d { + cc_ccache_iterator_f *functions; +#if TARGET_OS_MAC + cc_ccache_iterator_f *vector_functions; +#endif + cci_identifier_t identifier; + char *saved_ccache_name; +} *cci_ccache_iterator_t; + +/* ------------------------------------------------------------------------ */ + +struct cci_ccache_iterator_d cci_ccache_iterator_initializer = { + NULL + VECTOR_FUNCTIONS_INITIALIZER, + NULL, + NULL +}; + +cc_ccache_iterator_f cci_ccache_iterator_f_initializer = { + ccapi_ccache_iterator_release, + ccapi_ccache_iterator_next, + ccapi_ccache_iterator_clone +}; + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_iterator_new (cc_ccache_iterator_t *out_ccache_iterator, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = NULL; + + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + ccache_iterator = malloc (sizeof (*ccache_iterator)); + if (ccache_iterator) { + *ccache_iterator = cci_ccache_iterator_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + ccache_iterator->functions = malloc (sizeof (*ccache_iterator->functions)); + if (ccache_iterator->functions) { + *ccache_iterator->functions = cci_ccache_iterator_f_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = cci_identifier_copy (&ccache_iterator->identifier, in_identifier); + } + + if (!err) { + *out_ccache_iterator = (cc_ccache_iterator_t) ccache_iterator; + ccache_iterator = NULL; /* take ownership */ + } + + ccapi_ccache_iterator_release ((cc_ccache_iterator_t) ccache_iterator); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_iterator_write (cc_ccache_iterator_t in_ccache_iterator, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator; + + if (!in_ccache_iterator) { err = cci_check_error (ccErrBadParam); } + if (!in_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (ccache_iterator->identifier, in_stream); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_iterator_release (cc_ccache_iterator_t io_ccache_iterator) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) io_ccache_iterator; + + if (!io_ccache_iterator) { err = ccErrBadParam; } + + if (!err) { + cc_uint32 initialized = 0; + + err = cci_identifier_is_initialized (ccache_iterator->identifier, + &initialized); + + if (!err && initialized) { + err = cci_ipc_send (cci_ccache_iterator_release_msg_id, + ccache_iterator->identifier, + NULL, + NULL); + if (err) { + cci_debug_printf ("%s: cci_ipc_send failed with error %d", + __FUNCTION__, err); + err = ccNoError; + } + } + } + + if (!err) { + free ((char *) ccache_iterator->functions); + cci_identifier_release (ccache_iterator->identifier); + free (ccache_iterator->saved_ccache_name); + free (ccache_iterator); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_iterator_next (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_ccache_iterator) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_uint32 initialized = 0; + + err = cci_identifier_is_initialized (ccache_iterator->identifier, + &initialized); + + if (!err && !initialized) { + /* server doesn't actually exist. Pretend we're empty. */ + err = cci_check_error (ccIteratorEnd); + } + } + + if (!err) { + err = cci_ipc_send (cci_ccache_iterator_next_msg_id, + ccache_iterator->identifier, + NULL, + &reply); + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_ccache_new (out_ccache, identifier); + } + + krb5int_ipc_stream_release (reply); + cci_identifier_release (identifier); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_ccache_iterator_clone (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_iterator_t *out_ccache_iterator) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator; + k5_ipc_stream reply = NULL; + cc_uint32 initialized = 0; + cci_identifier_t identifier = NULL; + + if (!in_ccache_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_is_initialized (ccache_iterator->identifier, + &initialized); + } + + if (!err) { + if (initialized) { + err = cci_ipc_send (cci_ccache_iterator_next_msg_id, + ccache_iterator->identifier, + NULL, + &reply); + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + } else { + /* server doesn't actually exist. Make another dummy one. */ + identifier = cci_identifier_uninitialized; + } + } + + if (!err) { + err = cci_ccache_iterator_new (out_ccache_iterator, identifier); + } + + cci_identifier_release (identifier); + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_iterator_get_saved_ccache_name (cc_ccache_iterator_t in_ccache_iterator, + const char **out_saved_ccache_name) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) in_ccache_iterator; + + if (!in_ccache_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!out_saved_ccache_name) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_saved_ccache_name = ccache_iterator->saved_ccache_name; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ccache_iterator_set_saved_ccache_name (cc_ccache_iterator_t io_ccache_iterator, + const char *in_saved_ccache_name) +{ + cc_int32 err = ccNoError; + cci_ccache_iterator_t ccache_iterator = (cci_ccache_iterator_t) io_ccache_iterator; + char *new_saved_ccache_name = NULL; + + if (!io_ccache_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err && in_saved_ccache_name) { + new_saved_ccache_name = strdup (in_saved_ccache_name); + if (!new_saved_ccache_name) { err = ccErrNoMem; } + } + + if (!err) { + free (ccache_iterator->saved_ccache_name); + + ccache_iterator->saved_ccache_name = new_saved_ccache_name; + new_saved_ccache_name = NULL; /* take ownership */ + } + + free (new_saved_ccache_name); + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_ccache_iterator.h b/krb5-1.21.3/src/ccapi/lib/ccapi_ccache_iterator.h new file mode 100644 index 00000000..88947eaf --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_ccache_iterator.h @@ -0,0 +1,51 @@ +/* ccapi/lib/ccapi_ccache_iterator.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCAPI_CCACHE_ITERATOR_H +#define CCAPI_CCACHE_ITERATOR_H + +#include "cci_common.h" + +cc_int32 cci_ccache_iterator_new (cc_ccache_iterator_t *out_ccache_iterator, + cci_identifier_t in_identifier); + +cc_int32 cci_ccache_iterator_write (cc_ccache_iterator_t in_ccache_iterator, + k5_ipc_stream in_stream); + +cc_int32 ccapi_ccache_iterator_release (cc_ccache_iterator_t io_ccache_iterator); + +cc_int32 ccapi_ccache_iterator_next (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_t *out_ccache); + +cc_int32 ccapi_ccache_iterator_clone (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_iterator_t *out_ccache_iterator); + +cc_int32 cci_ccache_iterator_get_saved_ccache_name (cc_ccache_iterator_t in_ccache_iterator, + const char **out_saved_ccache_name); + +cc_int32 cci_ccache_iterator_set_saved_ccache_name (cc_ccache_iterator_t io_ccache_iterator, + const char *in_saved_ccache_name); + +#endif /* CCAPI_CCACHE_ITERATOR_H */ diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_context.c b/krb5-1.21.3/src/ccapi/lib/ccapi_context.c new file mode 100644 index 00000000..cf677fc5 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_context.c @@ -0,0 +1,831 @@ +/* ccapi/lib/ccapi_context.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccapi_context.h" + +#include "k5-platform.h" + +#include "ccapi_ccache.h" +#include "ccapi_ccache_iterator.h" +#include "ccapi_string.h" +#include "ccapi_ipc.h" +#include "ccapi_context_change_time.h" +#include "ccapi_err.h" + +#include + +typedef struct cci_context_d { + cc_context_f *functions; +#if TARGET_OS_MAC + cc_context_f *vector_functions; +#endif + cci_identifier_t identifier; + cc_uint32 synchronized; + cc_time_t last_wait_for_change_time; +} *cci_context_t; + +/* ------------------------------------------------------------------------ */ + +struct cci_context_d cci_context_initializer = { + NULL + VECTOR_FUNCTIONS_INITIALIZER, + NULL, + 0, + 0 +}; + +cc_context_f cci_context_f_initializer = { + ccapi_context_release, + ccapi_context_get_change_time, + ccapi_context_get_default_ccache_name, + ccapi_context_open_ccache, + ccapi_context_open_default_ccache, + ccapi_context_create_ccache, + ccapi_context_create_default_ccache, + ccapi_context_create_new_ccache, + ccapi_context_new_ccache_iterator, + ccapi_context_lock, + ccapi_context_unlock, + ccapi_context_compare, + ccapi_context_wait_for_change +}; + +static cc_int32 cci_context_sync (cci_context_t in_context, + cc_uint32 in_launch); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +MAKE_INIT_FUNCTION(cci_process_init); +MAKE_FINI_FUNCTION(cci_process_fini); + +/* ------------------------------------------------------------------------ */ + +static int cci_process_init (void) +{ + cc_int32 err = ccNoError; + + if (!err) { + err = cci_context_change_time_thread_init (); + } + + if (!err) { + err = cci_ipc_process_init (); + } + + if (!err) { + add_error_table (&et_CAPI_error_table); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +static void cci_process_fini (void) +{ + if (!INITIALIZER_RAN (cci_process_init) || PROGRAM_EXITING ()) { + return; + } + + remove_error_table(&et_CAPI_error_table); + cci_context_change_time_thread_fini (); +} + + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 cc_initialize (cc_context_t *out_context, + cc_int32 in_version, + cc_int32 *out_supported_version, + char const **out_vendor) +{ + cc_int32 err = ccNoError; + cci_context_t context = NULL; + static char *vendor_string = "MIT Kerberos CCAPI"; + + if (!out_context) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = CALL_INIT_FUNCTION (cci_process_init); + } + + if (!err) { + switch (in_version) { + case ccapi_version_2: + case ccapi_version_3: + case ccapi_version_4: + case ccapi_version_5: + case ccapi_version_6: + case ccapi_version_7: + break; + + default: + err = ccErrBadAPIVersion; + break; + } + } + + if (!err) { + context = malloc (sizeof (*context)); + if (context) { + *context = cci_context_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + context->functions = malloc (sizeof (*context->functions)); + if (context->functions) { + *context->functions = cci_context_f_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + context->identifier = cci_identifier_uninitialized; + + *out_context = (cc_context_t) context; + context = NULL; /* take ownership */ + + if (out_supported_version) { + *out_supported_version = ccapi_version_max; + } + + if (out_vendor) { + *out_vendor = vendor_string; + } + } + + ccapi_context_release ((cc_context_t) context); + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ +/* + * Currently does not need to talk to the server since the server must + * handle cleaning up resources from crashed clients anyway. + * + * NOTE: if server communication is ever added here, make sure that + * krb5_stdcc_shutdown calls an internal function which does not talk to the + * server. krb5_stdcc_shutdown is called from thread fini functions and may + * crash talking to the server depending on what order the OS calls the fini + * functions (ie: if the ipc layer fini function is called first). + */ + +cc_int32 ccapi_context_release (cc_context_t in_context) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + + if (!in_context) { err = ccErrBadParam; } + + if (!err) { + cci_identifier_release (context->identifier); + free (context->functions); + free (context); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_get_change_time (cc_context_t in_context, + cc_time_t *out_change_time) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream reply = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!out_change_time) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_context_sync (context, 0); + } + + if (!err) { + err = cci_ipc_send_no_launch (cci_context_get_change_time_msg_id, + context->identifier, + NULL, &reply); + } + + if (!err && krb5int_ipc_stream_size (reply) > 0) { + cc_time_t change_time = 0; + + /* got a response from the server */ + err = krb5int_ipc_stream_read_time (reply, &change_time); + + if (!err) { + err = cci_context_change_time_update (context->identifier, + change_time); + } + } + + if (!err) { + err = cci_context_change_time_get (out_change_time); + } + + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_wait_for_change (cc_context_t in_context) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_time (request, context->last_wait_for_change_time); + } + + if (!err) { + err = cci_context_sync (context, 1); + } + + if (!err) { + err = cci_ipc_send (cci_context_wait_for_change_msg_id, + context->identifier, + request, + &reply); + } + + if (!err) { + err = krb5int_ipc_stream_read_time (reply, &context->last_wait_for_change_time); + } + + krb5int_ipc_stream_release (request); + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_get_default_ccache_name (cc_context_t in_context, + cc_string_t *out_name) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream reply = NULL; + char *reply_name = NULL; + char *name = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!out_name ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_context_sync (context, 0); + } + + if (!err) { + err = cci_ipc_send_no_launch (cci_context_get_default_ccache_name_msg_id, + context->identifier, + NULL, + &reply); + } + + if (!err) { + if (krb5int_ipc_stream_size (reply) > 0) { + /* got a response from the server */ + err = krb5int_ipc_stream_read_string (reply, &reply_name); + + if (!err) { + name = reply_name; + } + } else { + name = k_cci_context_initial_ccache_name; + } + } + + if (!err) { + err = cci_string_new (out_name, name); + } + + krb5int_ipc_stream_release (reply); + krb5int_ipc_stream_free_string (reply_name); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_open_ccache (cc_context_t in_context, + const char *in_name, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_string (request, in_name); + } + + if (!err) { + err = cci_context_sync (context, 0); + } + + if (!err) { + err = cci_ipc_send_no_launch (cci_context_open_ccache_msg_id, + context->identifier, + request, + &reply); + } + + if (!err && !(krb5int_ipc_stream_size (reply) > 0)) { + err = ccErrCCacheNotFound; + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_ccache_new (out_ccache, identifier); + } + + cci_identifier_release (identifier); + krb5int_ipc_stream_release (reply); + krb5int_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_open_default_ccache (cc_context_t in_context, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_context_sync (context, 0); + } + + if (!err) { + err = cci_ipc_send_no_launch (cci_context_open_default_ccache_msg_id, + context->identifier, + NULL, + &reply); + } + + if (!err && !(krb5int_ipc_stream_size (reply) > 0)) { + err = ccErrCCacheNotFound; + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_ccache_new (out_ccache, identifier); + } + + cci_identifier_release (identifier); + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_create_ccache (cc_context_t in_context, + const char *in_name, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!in_principal) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_string (request, in_name); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (request, in_cred_vers); + } + + if (!err) { + err = krb5int_ipc_stream_write_string (request, in_principal); + } + + if (!err) { + err = cci_context_sync (context, 1); + } + + if (!err) { + err = cci_ipc_send (cci_context_create_ccache_msg_id, + context->identifier, + request, + &reply); + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_ccache_new (out_ccache, identifier); + } + + cci_identifier_release (identifier); + krb5int_ipc_stream_release (reply); + krb5int_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_create_default_ccache (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_principal) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (request, in_cred_vers); + } + + if (!err) { + err = krb5int_ipc_stream_write_string (request, in_principal); + } + + if (!err) { + err = cci_context_sync (context, 1); + } + + if (!err) { + err = cci_ipc_send (cci_context_create_default_ccache_msg_id, + context->identifier, + request, + &reply); + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_ccache_new (out_ccache, identifier); + } + + cci_identifier_release (identifier); + krb5int_ipc_stream_release (reply); + krb5int_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_create_new_ccache (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_principal) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (request, in_cred_vers); + } + + if (!err) { + err = krb5int_ipc_stream_write_string (request, in_principal); + } + + if (!err) { + err = cci_context_sync (context, 1); + } + + if (!err) { + err = cci_ipc_send (cci_context_create_new_ccache_msg_id, + context->identifier, + request, + &reply); + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_ccache_new (out_ccache, identifier); + } + + cci_identifier_release (identifier); + krb5int_ipc_stream_release (reply); + krb5int_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_new_ccache_iterator (cc_context_t in_context, + cc_ccache_iterator_t *out_iterator) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!out_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_context_sync (context, 0); + } + + if (!err) { + err = cci_ipc_send_no_launch (cci_context_new_ccache_iterator_msg_id, + context->identifier, + NULL, + &reply); + } + + if (!err) { + if (krb5int_ipc_stream_size (reply) > 0) { + err = cci_identifier_read (&identifier, reply); + } else { + identifier = cci_identifier_uninitialized; + } + } + + if (!err) { + err = cci_ccache_iterator_new (out_iterator, identifier); + } + + krb5int_ipc_stream_release (reply); + cci_identifier_release (identifier); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_lock (cc_context_t in_context, + cc_uint32 in_lock_type, + cc_uint32 in_block) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream request = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&request); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (request, in_lock_type); + } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (request, in_block); + } + + if (!err) { + err = cci_context_sync (context, 1); + } + + if (!err) { + err = cci_ipc_send (cci_context_lock_msg_id, + context->identifier, + request, + NULL); + } + + krb5int_ipc_stream_release (request); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_unlock (cc_context_t in_context) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_context_sync (context, 1); + } + + if (!err) { + err = cci_ipc_send (cci_context_unlock_msg_id, + context->identifier, + NULL, + NULL); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_context_compare (cc_context_t in_context, + cc_context_t in_compare_to_context, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + cci_context_t compare_to_context = (cci_context_t) in_compare_to_context; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_compare_to_context) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_context_sync (context, 0); + } + + if (!err) { + err = cci_context_sync (compare_to_context, 0); + } + + if (!err) { + /* If both contexts can't talk to the server, then + * we assume they are equivalent */ + err = cci_identifier_compare (context->identifier, + compare_to_context->identifier, + out_equal); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 cci_context_sync (cci_context_t in_context, + cc_uint32 in_launch) +{ + cc_int32 err = ccNoError; + cci_context_t context = (cci_context_t) in_context; + k5_ipc_stream reply = NULL; + cci_identifier_t new_identifier = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + /* Use the uninitialized identifier because we may be talking */ + /* to a different server which would reject our identifier and */ + /* the point of this message is to sync with the server's id */ + if (in_launch) { + err = cci_ipc_send (cci_context_sync_msg_id, + cci_identifier_uninitialized, + NULL, + &reply); + } else { + err = cci_ipc_send_no_launch (cci_context_sync_msg_id, + cci_identifier_uninitialized, + NULL, + &reply); + } + } + + if (!err) { + if (krb5int_ipc_stream_size (reply) > 0) { + err = cci_identifier_read (&new_identifier, reply); + } else { + new_identifier = cci_identifier_uninitialized; + } + } + + if (!err) { + cc_uint32 equal = 0; + + err = cci_identifier_compare (context->identifier, new_identifier, &equal); + + if (!err && !equal) { + if (context->identifier) { + cci_identifier_release (context->identifier); + } + context->identifier = new_identifier; + new_identifier = NULL; /* take ownership */ + } + } + + if (!err && context->synchronized) { + err = cci_context_change_time_sync (context->identifier); + } + + if (!err && !context->synchronized) { + /* Keep state about whether this is the first call to avoid always */ + /* modifying the global change time on the context's first ipc call. */ + context->synchronized = 1; + } + + cci_identifier_release (new_identifier); + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_context.h b/krb5-1.21.3/src/ccapi/lib/ccapi_context.h new file mode 100644 index 00000000..51b8982e --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_context.h @@ -0,0 +1,86 @@ +/* ccapi/lib/ccapi_context.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCAPI_CONTEXT_H +#define CCAPI_CONTEXT_H + +#include "cci_common.h" + +/* Used for freeing ccapi context in thread fini calls + * Does not tell the server you are exiting. */ +cc_int32 cci_context_destroy (cc_context_t in_context); + +cc_int32 ccapi_context_release (cc_context_t in_context); + +cc_int32 ccapi_context_get_change_time (cc_context_t in_context, + cc_time_t *out_time); + +cc_int32 ccapi_context_wait_for_change (cc_context_t in_context); + +cc_int32 ccapi_context_get_default_ccache_name (cc_context_t in_context, + cc_string_t *out_name); + +cc_int32 ccapi_context_open_ccache (cc_context_t in_context, + const char *in_name, + cc_ccache_t *out_ccache); + +cc_int32 ccapi_context_open_default_ccache (cc_context_t in_context, + cc_ccache_t *out_ccache); + +cc_int32 ccapi_context_create_ccache (cc_context_t in_context, + const char *in_name, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + +cc_int32 ccapi_context_create_default_ccache (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + +cc_int32 ccapi_context_create_new_ccache (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + +cc_int32 ccapi_context_new_ccache_iterator (cc_context_t in_context, + cc_ccache_iterator_t *out_iterator); + +cc_int32 ccapi_context_lock (cc_context_t in_context, + cc_uint32 in_lock_type, + cc_uint32 in_block); + +cc_int32 ccapi_context_unlock (cc_context_t in_context); + +cc_int32 ccapi_context_compare (cc_context_t in_context, + cc_context_t in_compare_to_context, + cc_uint32 *out_equal); + +#ifdef WIN32 +void cci_thread_init__auxinit(); +#endif + + +#endif /* CCAPI_CONTEXT_H */ diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_context_change_time.c b/krb5-1.21.3/src/ccapi/lib/ccapi_context_change_time.c new file mode 100644 index 00000000..ec6b955e --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_context_change_time.c @@ -0,0 +1,199 @@ +/* ccapi/lib/ccapi_context_change_time.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccapi_context_change_time.h" +#include "cci_common.h" + +#include "k5-thread.h" + +static cci_identifier_t g_change_time_identifer = NULL; +static cc_time_t g_change_time = 0; +static cc_time_t g_change_time_offset = 0; +static k5_mutex_t g_change_time_mutex = K5_MUTEX_PARTIAL_INITIALIZER; + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_context_change_time_thread_init (void) +{ + return k5_mutex_finish_init(&g_change_time_mutex); +} + +/* ------------------------------------------------------------------------ */ + +void cci_context_change_time_thread_fini (void) +{ + k5_mutex_destroy(&g_change_time_mutex); +} + +/* ------------------------------------------------------------------------ */ +/* WARNING! Mutex must be locked when calling this! */ + +static cc_int32 cci_context_change_time_update_identifier (cci_identifier_t in_new_identifier, + cc_uint32 *out_server_ids_match, + cc_uint32 *out_old_server_running, + cc_uint32 *out_new_server_running) +{ + cc_int32 err = ccNoError; + cc_uint32 server_ids_match = 0; + cc_uint32 old_server_running = 0; + cc_uint32 new_server_running = 0; + + if (!in_new_identifier) { err = cci_check_error (err); } + + if (!err && !g_change_time_identifer) { + g_change_time_identifer = cci_identifier_uninitialized; + } + + if (!err) { + err = cci_identifier_compare_server_id (g_change_time_identifer, + in_new_identifier, + &server_ids_match); + } + + if (!err && out_old_server_running) { + err = cci_identifier_is_initialized (g_change_time_identifer, &old_server_running); + } + + if (!err && out_new_server_running) { + err = cci_identifier_is_initialized (in_new_identifier, &new_server_running); + } + + if (!err && !server_ids_match) { + cci_identifier_t new_change_time_identifer = NULL; + + err = cci_identifier_copy (&new_change_time_identifer, in_new_identifier); + + if (!err) { + /* Save the new identifier */ + if (g_change_time_identifer) { + cci_identifier_release (g_change_time_identifer); + } + g_change_time_identifer = new_change_time_identifer; + } + } + + if (!err) { + if (out_server_ids_match ) { *out_server_ids_match = server_ids_match; } + if (out_old_server_running) { *out_old_server_running = old_server_running; } + if (out_new_server_running) { *out_new_server_running = new_server_running; } + } + + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_context_change_time_get (cc_time_t *out_change_time) +{ + cc_int32 err = ccNoError; + + k5_mutex_lock (&g_change_time_mutex); + + *out_change_time = g_change_time + g_change_time_offset; + k5_mutex_unlock (&g_change_time_mutex); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_context_change_time_update (cci_identifier_t in_identifier, + cc_time_t in_new_change_time) +{ + cc_int32 err = ccNoError; + k5_mutex_lock (&g_change_time_mutex); + + if (!in_identifier) { err = cci_check_error (err); } + + if (!err) { + if (g_change_time < in_new_change_time) { + /* Only update if it increases the time. May be a different server. */ + g_change_time = in_new_change_time; + cci_debug_printf ("%s: setting change time to %d", + __FUNCTION__, in_new_change_time); + } + } + + if (!err) { + err = cci_context_change_time_update_identifier (in_identifier, + NULL, NULL, NULL); + } + + k5_mutex_unlock (&g_change_time_mutex); + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_context_change_time_sync (cci_identifier_t in_new_identifier) +{ + cc_int32 err = ccNoError; + cc_uint32 server_ids_match = 0; + cc_uint32 server_was_running = 0; + cc_uint32 server_is_running = 0; + + k5_mutex_lock (&g_change_time_mutex); + + if (!in_new_identifier) { err = cci_check_error (err); } + + if (!err) { + err = cci_context_change_time_update_identifier (in_new_identifier, + &server_ids_match, + &server_was_running, + &server_is_running); + } + + if (!err && !server_ids_match) { + /* Increment the change time so callers re-read */ + g_change_time_offset++; + + /* If the server died, absorb the offset */ + if (server_was_running && !server_is_running) { + cc_time_t now = time (NULL); + + g_change_time += g_change_time_offset; + g_change_time_offset = 0; + + /* Make sure the change time increases, ideally with the current time */ + g_change_time = (g_change_time < now) ? now : g_change_time; + } + + cci_debug_printf ("%s noticed server changed (" + "server_was_running = %d; server_is_running = %d; " + "g_change_time = %d; g_change_time_offset = %d", + __FUNCTION__, server_was_running, server_is_running, + g_change_time, g_change_time_offset); + } + + k5_mutex_unlock (&g_change_time_mutex); + + return err; +} diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_context_change_time.h b/krb5-1.21.3/src/ccapi/lib/ccapi_context_change_time.h new file mode 100644 index 00000000..b1fa110e --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_context_change_time.h @@ -0,0 +1,41 @@ +/* ccapi/lib/ccapi_context_change_time.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCAPI_CONTEXT_CHANGE_TIME_H +#define CCAPI_CONTEXT_CHANGE_TIME_H + +#include "cci_common.h" + +cc_int32 cci_context_change_time_thread_init (void); +void cci_context_change_time_thread_fini (void); + +cc_int32 cci_context_change_time_get (cc_time_t *out_change_time); + +cc_int32 cci_context_change_time_update (cci_identifier_t in_identifier, + cc_time_t in_new_change_time); + +cc_int32 cci_context_change_time_sync (cci_identifier_t in_new_identifier); + +#endif /* CCAPI_CONTEXT_CHANGE_TIME_H */ diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_credentials.c b/krb5-1.21.3/src/ccapi/lib/ccapi_credentials.c new file mode 100644 index 00000000..cb175a31 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_credentials.c @@ -0,0 +1,165 @@ +/* ccapi/lib/ccapi_credentials.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccapi_credentials.h" + +#include "ccapi_string.h" + +/* ------------------------------------------------------------------------ */ + +typedef struct cci_credentials_d { + cc_credentials_union *data; + cc_credentials_f *functions; +#if TARGET_OS_MAC + cc_credentials_f *vector_functions; +#endif + cci_identifier_t identifier; +} *cci_credentials_t; + +/* ------------------------------------------------------------------------ */ + +struct cci_credentials_d cci_credentials_initializer = { + NULL, + NULL + VECTOR_FUNCTIONS_INITIALIZER, + NULL +}; + +cc_credentials_f cci_credentials_f_initializer = { + ccapi_credentials_release, + ccapi_credentials_compare +}; + +cc_credentials_union cci_credentials_union_initializer = { + 0, + { NULL } +}; + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_credentials_read (cc_credentials_t *out_credentials, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + cci_credentials_t credentials = NULL; + + if (!out_credentials) { err = cci_check_error (ccErrBadParam); } + if (!in_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + credentials = malloc (sizeof (*credentials)); + if (credentials) { + *credentials = cci_credentials_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + credentials->functions = malloc (sizeof (*credentials->functions)); + if (credentials->functions) { + *credentials->functions = cci_credentials_f_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = cci_identifier_read (&credentials->identifier, in_stream); + } + + if (!err) { + err = cci_credentials_union_read (&credentials->data, in_stream); + } + + if (!err) { + *out_credentials = (cc_credentials_t) credentials; + credentials = NULL; /* take ownership */ + } + + if (credentials) { ccapi_credentials_release ((cc_credentials_t) credentials); } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_credentials_write (cc_credentials_t in_credentials, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + cci_credentials_t credentials = (cci_credentials_t) in_credentials; + + if (!in_credentials) { err = cci_check_error (ccErrBadParam); } + if (!in_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (credentials->identifier, in_stream); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_credentials_compare (cc_credentials_t in_credentials, + cc_credentials_t in_compare_to_credentials, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + cci_credentials_t credentials = (cci_credentials_t) in_credentials; + cci_credentials_t compare_to_credentials = (cci_credentials_t) in_compare_to_credentials; + + if (!in_credentials ) { err = cci_check_error (ccErrBadParam); } + if (!in_compare_to_credentials) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_compare (credentials->identifier, + compare_to_credentials->identifier, + out_equal); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_credentials_release (cc_credentials_t io_credentials) +{ + cc_int32 err = ccNoError; + cci_credentials_t credentials = (cci_credentials_t) io_credentials; + + if (!io_credentials) { err = ccErrBadParam; } + + if (!err) { + cci_credentials_union_release (credentials->data); + free ((char *) credentials->functions); + cci_identifier_release (credentials->identifier); + free (credentials); + } + + return err; +} diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_credentials.h b/krb5-1.21.3/src/ccapi/lib/ccapi_credentials.h new file mode 100644 index 00000000..aea6a412 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_credentials.h @@ -0,0 +1,43 @@ +/* ccapi/lib/ccapi_credentials.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCAPI_CREDENTIALS_H +#define CCAPI_CREDENTIALS_H + +#include "cci_common.h" + +cc_int32 cci_credentials_read (cc_credentials_t *out_credentials, + k5_ipc_stream in_stream); + +cc_int32 cci_credentials_write (cc_credentials_t in_credentials, + k5_ipc_stream in_stream); + +cc_int32 ccapi_credentials_compare (cc_credentials_t in_credentials, + cc_credentials_t in_compare_to_credentials, + cc_uint32 *out_equal); + +cc_int32 ccapi_credentials_release (cc_credentials_t io_credentials); + +#endif /* CCAPI_CREDENTIALS_H */ diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_credentials_iterator.c b/krb5-1.21.3/src/ccapi/lib/ccapi_credentials_iterator.c new file mode 100644 index 00000000..f1efc7f8 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_credentials_iterator.c @@ -0,0 +1,246 @@ +/* ccapi/lib/ccapi_credentials_iterator.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccapi_credentials_iterator.h" +#include "ccapi_credentials.h" +#include "ccapi_ipc.h" + +/* ------------------------------------------------------------------------ */ + +typedef struct cci_credentials_iterator_d { + cc_credentials_iterator_f *functions; +#if TARGET_OS_MAC + cc_credentials_iterator_f *vector_functions; +#endif + cci_identifier_t identifier; + cc_uint32 compat_version; +} *cci_credentials_iterator_t; + +/* ------------------------------------------------------------------------ */ + +struct cci_credentials_iterator_d cci_credentials_iterator_initializer = { + NULL + VECTOR_FUNCTIONS_INITIALIZER, + NULL, + 0 +}; + +cc_credentials_iterator_f cci_credentials_iterator_f_initializer = { + ccapi_credentials_iterator_release, + ccapi_credentials_iterator_next, + ccapi_credentials_iterator_clone +}; + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_credentials_iterator_new (cc_credentials_iterator_t *out_credentials_iterator, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = NULL; + + if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + credentials_iterator = malloc (sizeof (*credentials_iterator)); + if (credentials_iterator) { + *credentials_iterator = cci_credentials_iterator_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + credentials_iterator->functions = malloc (sizeof (*credentials_iterator->functions)); + if (credentials_iterator->functions) { + *credentials_iterator->functions = cci_credentials_iterator_f_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = cci_identifier_copy (&credentials_iterator->identifier, in_identifier); + } + + if (!err) { + *out_credentials_iterator = (cc_credentials_iterator_t) credentials_iterator; + credentials_iterator = NULL; /* take ownership */ + } + + if (credentials_iterator) { ccapi_credentials_iterator_release ((cc_credentials_iterator_t) credentials_iterator); } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_credentials_iterator_write (cc_credentials_iterator_t in_credentials_iterator, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator; + + if (!in_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!in_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (credentials_iterator->identifier, in_stream); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_credentials_iterator_release (cc_credentials_iterator_t io_credentials_iterator) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) io_credentials_iterator; + + if (!io_credentials_iterator) { err = ccErrBadParam; } + + if (!err) { + err = cci_ipc_send (cci_credentials_iterator_release_msg_id, + credentials_iterator->identifier, + NULL, + NULL); + if (err) { + cci_debug_printf ("%s: cci_ipc_send failed with error %d", + __FUNCTION__, err); + err = ccNoError; + } + } + + if (!err) { + free ((char *) credentials_iterator->functions); + cci_identifier_release (credentials_iterator->identifier); + free (credentials_iterator); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_credentials_iterator_next (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_t *out_credentials) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator; + k5_ipc_stream reply = NULL; + + if (!in_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_credentials_iterator_next_msg_id, + credentials_iterator->identifier, + NULL, + &reply); + } + + if (!err) { + err = cci_credentials_read (out_credentials, reply); + } + + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_credentials_iterator_clone (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_iterator_t *out_credentials_iterator) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator; + k5_ipc_stream reply = NULL; + cci_identifier_t identifier = NULL; + + if (!in_credentials_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ipc_send (cci_credentials_iterator_next_msg_id, + credentials_iterator->identifier, + NULL, + &reply); + } + + if (!err) { + err = cci_identifier_read (&identifier, reply); + } + + if (!err) { + err = cci_credentials_iterator_new (out_credentials_iterator, identifier); + } + + krb5int_ipc_stream_release (reply); + cci_identifier_release (identifier); + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_credentials_iterator_get_compat_version (cc_credentials_iterator_t in_credentials_iterator, + cc_uint32 *out_compat_version) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) in_credentials_iterator; + + if (!in_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!out_compat_version ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_compat_version = credentials_iterator->compat_version; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_credentials_iterator_set_compat_version (cc_credentials_iterator_t io_credentials_iterator, + cc_uint32 in_compat_version) +{ + cc_int32 err = ccNoError; + cci_credentials_iterator_t credentials_iterator = (cci_credentials_iterator_t) io_credentials_iterator; + + if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + credentials_iterator->compat_version = in_compat_version; + } + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_credentials_iterator.h b/krb5-1.21.3/src/ccapi/lib/ccapi_credentials_iterator.h new file mode 100644 index 00000000..56c4505d --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_credentials_iterator.h @@ -0,0 +1,51 @@ +/* ccapi/lib/ccapi_credentials_iterator.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCAPI_CREDENTIALS_ITERATOR_H +#define CCAPI_CREDENTIALS_ITERATOR_H + +#include "cci_common.h" + +cc_int32 cci_credentials_iterator_new (cc_credentials_iterator_t *out_credentials_iterator, + cci_identifier_t in_identifier); + +cc_int32 cci_credentials_iterator_write (cc_credentials_iterator_t in_credentials_iterator, + k5_ipc_stream in_stream); + +cc_int32 ccapi_credentials_iterator_release (cc_credentials_iterator_t io_credentials_iterator); + +cc_int32 ccapi_credentials_iterator_next (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_t *out_credentials); + +cc_int32 ccapi_credentials_iterator_clone (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_iterator_t *out_credentials_iterator); + +cc_int32 cci_credentials_iterator_get_compat_version (cc_credentials_iterator_t in_credentials_iterator, + cc_uint32 *out_compat_version); + +cc_int32 cci_credentials_iterator_set_compat_version (cc_credentials_iterator_t io_credentials_iterator, + cc_uint32 in_compat_version); + +#endif /* CCAPI_CREDENTIALS_ITERATOR_H */ diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_err.et b/krb5-1.21.3/src/ccapi/lib/ccapi_err.et new file mode 100644 index 00000000..44cd2d0b --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_err.et @@ -0,0 +1,74 @@ +# +# $Header$ +# +# Copyright 1998-2006 Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. +# + +error_table_base 201 +error_table_manager "Credentials Cache" +error_table CAPI + +# 201 +error_code ccIteratorEnd, "Reached end of iterator" +error_code ccErrBadParam, "Invalid argument" +error_code ccErrNoMem, "Out of memory" +error_code ccErrInvalidContext, "Invalid credentials cache context" +error_code ccErrInvalidCCache, "Invalid credentials cache" + +# 206 +index 5 +error_code ccErrInvalidString, "Invalid credentials cache string" +error_code ccErrInvalidCredentials, "Invalid credentials" +error_code ccErrInvalidCCacheIterator, "Invalid credentials cache iterator" +error_code ccErrInvalidCredentialsIterator, "Invalid credentials iterator" +error_code ccErrInvalidLock, "Invalid iterator" + +# 211 +index 10 +error_code ccErrBadName, "Invalid credentials cache name" +error_code ccErrBadCredentialsVersion, "Invalid credentials cache version (not 4 or 5)" +error_code ccErrBadAPIVersion, "Invalid CCAPI version" +error_code ccErrContextLocked, "Credentials cache context is already locked" +error_code ccErrContextUnlocked, "Credentials cache context is already unlocked" + +# 216 +index 15 +error_code ccErrCCacheLocked, "Credentials cache is already locked" +error_code ccErrCCacheUnlocked, "Credentials cache is already unlocked" +error_code ccErrBadLockType, "Invalid credentials cache lock type" +error_code ccErrNeverDefault, "Credentials cache has never been the default cache" +error_code ccErrCredentialsNotFound, "Credentials not found" + +# 221 +index 20 +error_code ccErrCCacheNotFound, "Credentials cache not found" +error_code ccErrContextNotFound, "Credentials cache context not found" +error_code ccErrServerUnavailable, "Credentials cache server unavailable" +error_code ccErrServerInsecure, "Credentials cache server in this bootstrap is owned by another user" +error_code ccErrServerCantBecomeUID, "Credentials cache server failed to change effective uids" + +# 226 +index 25 +error_code ccErrTimeOffsetNotSet, "Credentials cache time offset not set" + +end diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_ipc.c b/krb5-1.21.3/src/ccapi/lib/ccapi_ipc.c new file mode 100644 index 00000000..2c1fcba6 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_ipc.c @@ -0,0 +1,119 @@ +/* ccapi/lib/ccapi_ipc.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccapi_ipc.h" +#include "ccapi_os_ipc.h" + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ipc_process_init (void) +{ + return cci_os_ipc_process_init (); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ipc_thread_init (void) +{ + return cci_os_ipc_thread_init (); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 _cci_ipc_send (enum cci_msg_id_t in_request_name, + cc_int32 in_launch_server, + cci_identifier_t in_identifier, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data) +{ + cc_int32 err = ccNoError; + k5_ipc_stream request = NULL; + k5_ipc_stream reply = NULL; + cc_int32 reply_error = 0; + + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + /* in_request_data may be NULL */ + /* out_reply_data may be NULL */ + + if (!err) { + err = cci_message_new_request_header (&request, + in_request_name, + in_identifier); + } + + if (!err && in_request_data) { + err = krb5int_ipc_stream_write (request, + krb5int_ipc_stream_data (in_request_data), + krb5int_ipc_stream_size (in_request_data)); + } + + if (!err) { + err = cci_os_ipc (in_launch_server, request, &reply); + + if (!err && krb5int_ipc_stream_size (reply) > 0) { + err = cci_message_read_reply_header (reply, &reply_error); + } + } + + if (!err && reply_error) { + err = reply_error; + } + + if (!err && out_reply_data) { + *out_reply_data = reply; + reply = NULL; /* take ownership */ + } + + krb5int_ipc_stream_release (request); + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ipc_send (enum cci_msg_id_t in_request_name, + cci_identifier_t in_identifier, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data) +{ + return cci_check_error (_cci_ipc_send (in_request_name, 1, + in_identifier, + in_request_data, + out_reply_data)); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_ipc_send_no_launch (enum cci_msg_id_t in_request_name, + cci_identifier_t in_identifier, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data) +{ + return cci_check_error (_cci_ipc_send (in_request_name, 0, + in_identifier, + in_request_data, + out_reply_data)); +} diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_ipc.h b/krb5-1.21.3/src/ccapi/lib/ccapi_ipc.h new file mode 100644 index 00000000..a23772b2 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_ipc.h @@ -0,0 +1,45 @@ +/* ccapi/lib/ccapi_ipc.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCAPI_IPC_H +#define CCAPI_IPC_H + +#include "cci_common.h" + +cc_int32 cci_ipc_process_init (void); + +cc_int32 cci_ipc_thread_init (void); + +cc_int32 cci_ipc_send (enum cci_msg_id_t in_request_name, + cci_identifier_t in_identifier, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data); + +cc_int32 cci_ipc_send_no_launch (enum cci_msg_id_t in_request_name, + cci_identifier_t in_identifier, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data); + +#endif /* CCAPI_IPC_H */ diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_os_ipc.h b/krb5-1.21.3/src/ccapi/lib/ccapi_os_ipc.h new file mode 100644 index 00000000..fe7c87a0 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_os_ipc.h @@ -0,0 +1,39 @@ +/* ccapi/lib/ccapi_os_ipc.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCAPI_OS_IPC_H +#define CCAPI_OS_IPC_H + +#include "cci_common.h" + +cc_int32 cci_os_ipc_process_init (void); + +cc_int32 cci_os_ipc_thread_init (void); + +cc_int32 cci_os_ipc (cc_int32 in_launch_server, + k5_ipc_stream in_request_stream, + k5_ipc_stream *out_reply_stream); + +#endif /* CCAPI_OS_IPC_H */ diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_string.c b/krb5-1.21.3/src/ccapi/lib/ccapi_string.c new file mode 100644 index 00000000..ab84dfe3 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_string.c @@ -0,0 +1,101 @@ +/* ccapi/lib/ccapi_string.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccapi_string.h" + +/* ------------------------------------------------------------------------ */ + +cc_string_d cci_string_d_initializer = { + NULL, + NULL + VECTOR_FUNCTIONS_INITIALIZER }; + +cc_string_f cci_string_f_initializer = { + ccapi_string_release +}; + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_string_new (cc_string_t *out_string, + char *in_cstring) +{ + cc_int32 err = ccNoError; + cc_string_t string = NULL; + + if (!out_string) { err = cci_check_error (ccErrBadParam); } + if (!in_cstring) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + string = malloc (sizeof (*string)); + if (string) { + *string = cci_string_d_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + string->functions = malloc (sizeof (*string->functions)); + if (string->functions) { + *((cc_string_f *) string->functions) = cci_string_f_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + string->data = strdup (in_cstring); + if (!string->data) { + err = cci_check_error (ccErrNoMem); + } + + } + + if (!err) { + *out_string = string; + string = NULL; /* take ownership */ + } + + if (string) { ccapi_string_release (string); } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccapi_string_release (cc_string_t in_string) +{ + cc_int32 err = ccNoError; + + if (!in_string) { err = ccErrBadParam; } + + if (!err) { + free ((char *) in_string->data); + free ((char *) in_string->functions); + free (in_string); + } + + return err; +} diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_string.h b/krb5-1.21.3/src/ccapi/lib/ccapi_string.h new file mode 100644 index 00000000..02debde9 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_string.h @@ -0,0 +1,36 @@ +/* ccapi/lib/ccapi_string.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCAPI_STRING_H +#define CCAPI_STRING_H + +#include "cci_common.h" + +cc_int32 cci_string_new (cc_string_t *out_string, + char *in_cstring); + +cc_int32 ccapi_string_release (cc_string_t in_string); + +#endif /* CCAPI_STRING_H */ diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_v2.c b/krb5-1.21.3/src/ccapi/lib/ccapi_v2.c new file mode 100644 index 00000000..ae9b790b --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_v2.c @@ -0,0 +1,889 @@ +/* ccapi/lib/ccapi_v2.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "cci_common.h" +#include "ccapi_string.h" +#include "ccapi_context.h" +#include "ccapi_ccache.h" +#include "ccapi_ccache_iterator.h" +#include "ccapi_credentials.h" +#include "ccapi_credentials_iterator.h" +#include + +infoNC infoNC_initializer = { NULL, NULL, CC_CRED_UNKNOWN }; + +/* ------------------------------------------------------------------------ */ + +static cc_int32 cci_remap_version (cc_int32 in_v2_version, + cc_uint32 *out_v3_version) +{ + cc_result err = ccNoError; + + if (!out_v3_version) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + if (in_v2_version == CC_CRED_V5) { + *out_v3_version = cc_credentials_v5; + + } else { + err = ccErrBadCredentialsVersion; + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_result _cci_remap_error (cc_result in_error, + const char *in_function, + const char *in_file, + int in_line) +{ + _cci_check_error (in_error, in_function, in_file, in_line); + + if (in_error >= CC_NOERROR && in_error <= CC_ERR_CRED_VERSION) { + return in_error; + } + + switch (in_error) { + case ccNoError: + return CC_NOERROR; + + case ccIteratorEnd: + return CC_END; + + case ccErrBadParam: + case ccErrContextNotFound: + case ccErrInvalidContext: + case ccErrInvalidCredentials: + case ccErrInvalidCCacheIterator: + case ccErrInvalidCredentialsIterator: + case ccErrInvalidLock: + case ccErrBadLockType: + return CC_BAD_PARM; + + case ccErrNoMem: + return CC_NOMEM; + + case ccErrInvalidCCache: + case ccErrCCacheNotFound: + return CC_NO_EXIST; + + case ccErrCredentialsNotFound: + return CC_NOTFOUND; + + case ccErrBadName: + return CC_BADNAME; + + case ccErrBadCredentialsVersion: + return CC_ERR_CRED_VERSION; + + case ccErrBadAPIVersion: + return CC_BAD_API_VERSION; + + case ccErrContextLocked: + case ccErrContextUnlocked: + case ccErrCCacheLocked: + case ccErrCCacheUnlocked: + return CC_LOCKED; + + case ccErrServerUnavailable: + case ccErrServerInsecure: + case ccErrServerCantBecomeUID: + case ccErrBadInternalMessage: + case ccErrClientNotFound: + return CC_IO; + + case ccErrNotImplemented: + return CC_NOT_SUPP; + + default: + cci_debug_printf ("%s(): Unhandled error", __FUNCTION__); + return CC_BAD_PARM; + } +} +#define cci_remap_error(err) _cci_remap_error(err, __FUNCTION__, __FILE__, __LINE__) + + +#if TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_result cc_shutdown (apiCB **io_context) +{ + cc_result err = ccNoError; + + if (!io_context) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_context_release (*io_context); + } + + if (!err) { + *io_context = NULL; + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_get_change_time (apiCB *in_context, + cc_time_t *out_change_time) +{ + cc_result err = ccNoError; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!out_change_time) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_context_get_change_time (in_context, out_change_time); + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_get_NC_info (apiCB *in_context, + infoNC ***out_info) +{ + cc_result err = CC_NOERROR; + infoNC **info = NULL; + cc_uint64 count = 0; /* Preflight the size */ + cc_uint64 i; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!out_info ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + ccache_cit *iterator = NULL; + + err = cc_seq_fetch_NCs_begin (in_context, &iterator); + + while (!err) { + ccache_p *ccache = NULL; + + err = cc_seq_fetch_NCs_next (in_context, &ccache, iterator); + + if (!err) { count++; } + + if (ccache) { cc_close (in_context, &ccache); } + } + if (err == CC_END) { err = CC_NOERROR; } + + if (!err) { + err = cc_seq_fetch_NCs_end (in_context, &iterator); + } + } + + if (!err) { + info = malloc (sizeof (*info) * (count + 1)); + if (info) { + for (i = 0; i < count + 1; i++) { info[i] = NULL; } + } else { + err = cci_check_error (CC_NOMEM); + } + } + + if (!err) { + ccache_cit *iterator = NULL; + + err = cc_seq_fetch_NCs_begin (in_context, &iterator); + + for (i = 0; !err && i < count; i++) { + ccache_p *ccache = NULL; + + err = cc_seq_fetch_NCs_next (in_context, &ccache, iterator); + + if (!err) { + info[i] = malloc (sizeof (*info[i])); + if (info[i]) { + *info[i] = infoNC_initializer; + } else { + err = cci_check_error (CC_NOMEM); + } + } + + if (!err) { + err = cc_get_name (in_context, ccache, &info[i]->name); + } + + if (!err) { + err = cc_get_principal (in_context, ccache, &info[i]->principal); + } + + if (!err) { + err = cc_get_cred_version (in_context, ccache, &info[i]->vers); + } + + if (ccache) { cc_close (in_context, &ccache); } + } + + if (!err) { + err = cc_seq_fetch_NCs_end (in_context, &iterator); + } + } + + if (!err) { + *out_info = info; + info = NULL; + } + + if (info) { cc_free_NC_info (in_context, &info); } + + return cci_check_error (err); +} + +#if TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 cc_open (apiCB *in_context, + const char *in_name, + cc_int32 in_version, + cc_uint32 in_flags, + ccache_p **out_ccache) +{ + cc_result err = ccNoError; + cc_ccache_t ccache = NULL; + cc_uint32 compat_version; + cc_uint32 real_version; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_remap_version (in_version, &compat_version); + } + + if (!err) { + err = ccapi_context_open_ccache (in_context, in_name, &ccache); + } + + /* We must not allow a CCAPI v2 caller to open a v5-only ccache + as a v4 ccache and vice versa. Allowing that would break + (valid) assumptions made by CCAPI v2 callers. */ + + if (!err) { + err = ccapi_ccache_get_credentials_version (ccache, &real_version); + } + + if (!err) { + /* check the version and set up the ccache to use it */ + if (compat_version & real_version) { + err = cci_ccache_set_compat_version (ccache, compat_version); + } else { + err = ccErrBadCredentialsVersion; + } + } + + if (!err) { + *out_ccache = ccache; + ccache = NULL; + } + + if (ccache) { ccapi_ccache_release (ccache); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_create (apiCB *in_context, + const char *in_name, + const char *in_principal, + cc_int32 in_version, + cc_uint32 in_flags, + ccache_p **out_ccache) +{ + cc_result err = ccNoError; + cc_ccache_t ccache = NULL; + cc_uint32 compat_version; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_remap_version (in_version, &compat_version); + } + + if (!err) { + err = ccapi_context_create_ccache (in_context, in_name, compat_version, + in_principal, &ccache); + } + + if (!err) { + err = cci_ccache_set_compat_version (ccache, compat_version); + } + + if (!err) { + *out_ccache = ccache; + ccache = NULL; + } + + if (ccache) { ccapi_ccache_release (ccache); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_close (apiCB *in_context, + ccache_p **io_ccache) +{ + cc_result err = ccNoError; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_ccache_release (*io_ccache); + } + + if (!err) { + *io_ccache = NULL; + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_destroy (apiCB *in_context, + ccache_p **io_ccache) +{ + cc_result err = ccNoError; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_ccache_destroy (*io_ccache); + } + + if (!err) { + *io_ccache = NULL; + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_get_name (apiCB *in_context, + ccache_p *in_ccache, + char **out_name) +{ + cc_result err = ccNoError; + cc_string_t name = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_name ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_ccache_get_name (in_ccache, &name); + } + + if (!err) { + char *string = strdup (name->data); + if (string) { + *out_name = string; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (name) { ccapi_string_release (name); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_get_cred_version (apiCB *in_context, + ccache_p *in_ccache, + cc_int32 *out_version) +{ + cc_result err = ccNoError; + cc_uint32 compat_version; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_version) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ccache_get_compat_version (in_ccache, &compat_version); + } + + if (!err) { + if (compat_version == cc_credentials_v5) { + *out_version = CC_CRED_V5; + + } else { + err = ccErrBadCredentialsVersion; + } + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_set_principal (apiCB *in_context, + ccache_p *io_ccache, + cc_int32 in_version, + char *in_principal) +{ + cc_result err = ccNoError; + cc_uint32 version; + cc_uint32 compat_version; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_principal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_remap_version (in_version, &version); + } + + if (!err) { + err = cci_ccache_get_compat_version (io_ccache, &compat_version); + } + + if (!err && version != compat_version) { + err = cci_check_error (ccErrBadCredentialsVersion); + } + + if (!err) { + err = ccapi_ccache_set_principal (io_ccache, version, in_principal); + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_get_principal (apiCB *in_context, + ccache_p *in_ccache, + char **out_principal) +{ + cc_result err = ccNoError; + cc_uint32 compat_version; + cc_string_t principal = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_principal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ccache_get_compat_version (in_ccache, &compat_version); + } + + if (!err) { + err = ccapi_ccache_get_principal (in_ccache, compat_version, &principal); + } + + if (!err) { + char *string = strdup (principal->data); + if (string) { + *out_principal = string; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (principal) { ccapi_string_release (principal); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_store (apiCB *in_context, + ccache_p *io_ccache, + cred_union in_credentials) +{ + cc_result err = ccNoError; + cc_credentials_union *creds_union = NULL; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_cred_union_to_credentials_union (&in_credentials, + &creds_union); + } + + if (!err) { + err = ccapi_ccache_store_credentials (io_ccache, creds_union); + } + + if (creds_union) { cci_credentials_union_release (creds_union); } + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_remove_cred (apiCB *in_context, + ccache_p *in_ccache, + cred_union in_credentials) +{ + cc_result err = ccNoError; + cc_credentials_iterator_t iterator = NULL; + cc_uint32 found = 0; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_ccache_new_credentials_iterator (in_ccache, &iterator); + } + + while (!err && !found) { + cc_credentials_t creds = NULL; + + err = ccapi_credentials_iterator_next (iterator, &creds); + + if (!err) { + err = cci_cred_union_compare_to_credentials_union (&in_credentials, + creds->data, + &found); + } + + if (!err && found) { + err = ccapi_ccache_remove_credentials (in_ccache, creds); + } + + ccapi_credentials_release (creds); + } + if (err == ccIteratorEnd) { err = cci_check_error (ccErrCredentialsNotFound); } + + return cci_remap_error (err); +} + +#if TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_result cc_seq_fetch_NCs_begin (apiCB *in_context, + ccache_cit **out_iterator) +{ + cc_result err = ccNoError; + cc_ccache_iterator_t iterator = NULL; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!out_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_context_new_ccache_iterator (in_context, &iterator); + } + + if (!err) { + *out_iterator = (ccache_cit *) iterator; + iterator = NULL; /* take ownership */ + } + + if (iterator) { ccapi_ccache_iterator_release (iterator); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_seq_fetch_NCs_next (apiCB *in_context, + ccache_p **out_ccache, + ccache_cit *in_iterator) +{ + cc_result err = ccNoError; + cc_ccache_iterator_t iterator = (cc_ccache_iterator_t) in_iterator; + cc_ccache_t ccache = NULL; + const char *saved_ccache_name; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ccache_iterator_get_saved_ccache_name (iterator, + &saved_ccache_name); + } + + if (!err) { + if (saved_ccache_name) { + err = ccapi_context_open_ccache (in_context, saved_ccache_name, + &ccache); + + if (!err) { + err = cci_ccache_set_compat_version (ccache, cc_credentials_v5); + } + + if (!err) { + err = cci_ccache_iterator_set_saved_ccache_name (iterator, NULL); + } + + } else { + cc_uint32 version = 0; + + err = ccapi_ccache_iterator_next (iterator, &ccache); + + if (!err) { + err = ccapi_ccache_get_credentials_version (ccache, &version); + } + + if (!err) { + err = cci_ccache_set_compat_version (ccache, version); + } + } + } + + if (!err) { + *out_ccache = ccache; + ccache = NULL; /* take ownership */ + } + + if (ccache) { ccapi_ccache_release (ccache); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_seq_fetch_NCs_end (apiCB *in_context, + ccache_cit **io_iterator) +{ + cc_result err = ccNoError; + cc_ccache_iterator_t iterator = (cc_ccache_iterator_t) *io_iterator; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!io_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_ccache_iterator_release (iterator); + } + + if (!err) { + *io_iterator = NULL; + } + + return cci_remap_error (err); +} + +#if TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_result cc_seq_fetch_creds_begin (apiCB *in_context, + const ccache_p *in_ccache, + ccache_cit **out_iterator) +{ + cc_result err = ccNoError; + cc_credentials_iterator_t iterator = NULL; + cc_uint32 compat_version; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!out_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_ccache_get_compat_version ((cc_ccache_t) in_ccache, + &compat_version); + } + + if (!err) { + err = ccapi_ccache_new_credentials_iterator ((cc_ccache_t) in_ccache, + &iterator); + } + + if (!err) { + err = cci_credentials_iterator_set_compat_version (iterator, + compat_version); + } + + if (!err) { + *out_iterator = (ccache_cit *) iterator; + iterator = NULL; /* take ownership */ + } + + if (iterator) { ccapi_credentials_iterator_release (iterator); } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_seq_fetch_creds_next (apiCB *in_context, + cred_union **out_creds, + ccache_cit *in_iterator) +{ + cc_result err = ccNoError; + cc_credentials_iterator_t iterator = (cc_credentials_iterator_t) in_iterator; + cc_uint32 compat_version; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!out_creds ) { err = cci_check_error (ccErrBadParam); } + if (!in_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_credentials_iterator_get_compat_version (iterator, + &compat_version); + } + + while (!err) { + cc_credentials_t credentials = NULL; + + err = ccapi_credentials_iterator_next (iterator, &credentials); + + if (!err && (credentials->data->version & compat_version)) { + /* got the next credentials for the correct version */ + err = cci_credentials_union_to_cred_union (credentials->data, + out_creds); + break; + } + + if (credentials) { ccapi_credentials_release (credentials); } + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_seq_fetch_creds_end (apiCB *in_context, + ccache_cit **io_iterator) +{ + cc_result err = ccNoError; + cc_credentials_iterator_t iterator = (cc_credentials_iterator_t) *io_iterator; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!io_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccapi_credentials_iterator_release (iterator); + } + + if (!err) { + *io_iterator = NULL; + } + + return cci_remap_error (err); +} + +#if TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_result cc_free_principal (apiCB *in_context, + char **io_principal) +{ + cc_result err = ccNoError; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!io_principal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + free (*io_principal); + *io_principal = NULL; + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_free_name (apiCB *in_context, + char **io_name) +{ + cc_result err = ccNoError; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!io_name ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + free (*io_name); + *io_name = NULL; + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_free_creds (apiCB *in_context, + cred_union **io_credentials) +{ + cc_result err = ccNoError; + + if (!in_context ) { err = cci_check_error (ccErrBadParam); } + if (!io_credentials) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_cred_union_release (*io_credentials); + if (!err) { *io_credentials = NULL; } + } + + return cci_remap_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_result cc_free_NC_info (apiCB *in_context, + infoNC ***io_info) +{ + cc_result err = ccNoError; + + if (!in_context) { err = cci_check_error (ccErrBadParam); } + if (!io_info ) { err = cci_check_error (ccErrBadParam); } + + if (!err && *io_info) { + infoNC **data = *io_info; + int i; + + for (i = 0; data[i] != NULL; i++) { + cc_free_principal (in_context, &data[i]->principal); + cc_free_name (in_context, &data[i]->name); + free (data[i]); + } + free (data); + + *io_info = NULL; + } + + return cci_remap_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/lib/ccapi_v2.exports b/krb5-1.21.3/src/ccapi/lib/ccapi_v2.exports new file mode 100644 index 00000000..efa9fcec --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/ccapi_v2.exports @@ -0,0 +1,23 @@ +cc_shutdown +cc_create +cc_close +cc_destroy +cc_get_change_time +cc_open +cc_store +cc_remove_cred +cc_set_principal +cc_get_principal +cc_get_cred_version +cc_get_name +cc_seq_fetch_NCs_begin +cc_seq_fetch_NCs_next +cc_seq_fetch_NCs_end +cc_seq_fetch_creds_begin +cc_seq_fetch_creds_next +cc_seq_fetch_creds_end +cc_get_NC_info +cc_free_principal +cc_free_name +cc_free_creds +cc_free_NC_info diff --git a/krb5-1.21.3/src/ccapi/lib/deps b/krb5-1.21.3/src/ccapi/lib/deps new file mode 100644 index 00000000..ad996d9f --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/deps @@ -0,0 +1,86 @@ +# +# Generated makefile dependencies follow. +# +ccapi_ccache.so ccapi_ccache.po $(OUTPRE)ccapi_ccache.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccapi_ccache.c ccapi_ccache.h ccapi_credentials.h ccapi_credentials_iterator.h \ + ccapi_ipc.h ccapi_string.h +ccapi_ccache_iterator.so ccapi_ccache_iterator.po $(OUTPRE)ccapi_ccache_iterator.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccapi_ccache.h ccapi_ccache_iterator.c ccapi_ccache_iterator.h \ + ccapi_ipc.h +ccapi_context.so ccapi_context.po $(OUTPRE)ccapi_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccapi_ccache.h ccapi_ccache_iterator.h ccapi_context.c \ + ccapi_context.h ccapi_context_change_time.h ccapi_err.h \ + ccapi_ipc.h ccapi_string.h +ccapi_context_change_time.so ccapi_context_change_time.po \ + $(OUTPRE)ccapi_context_change_time.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccapi_context_change_time.c ccapi_context_change_time.h +ccapi_credentials.so ccapi_credentials.po $(OUTPRE)ccapi_credentials.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccapi_credentials.c ccapi_credentials.h ccapi_string.h +ccapi_credentials_iterator.so ccapi_credentials_iterator.po \ + $(OUTPRE)ccapi_credentials_iterator.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccapi_credentials.h ccapi_credentials_iterator.c ccapi_credentials_iterator.h \ + ccapi_ipc.h +ccapi_err.so ccapi_err.po $(OUTPRE)ccapi_err.$(OBJEXT): \ + $(COM_ERR_DEPS) ccapi_err.c +ccapi_ipc.so ccapi_ipc.po $(OUTPRE)ccapi_ipc.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccapi_ipc.c ccapi_ipc.h ccapi_os_ipc.h +ccapi_string.so ccapi_string.po $(OUTPRE)ccapi_string.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccapi_string.c ccapi_string.h +ccapi_v2.so ccapi_v2.po $(OUTPRE)ccapi_v2.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccapi_ccache.h ccapi_ccache_iterator.h ccapi_context.h \ + ccapi_credentials.h ccapi_credentials_iterator.h ccapi_string.h \ + ccapi_v2.c diff --git a/krb5-1.21.3/src/ccapi/lib/libkrb5-ccapi.exports b/krb5-1.21.3/src/ccapi/lib/libkrb5-ccapi.exports new file mode 100644 index 00000000..1a8560f0 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/libkrb5-ccapi.exports @@ -0,0 +1 @@ +cc_close diff --git a/krb5-1.21.3/src/ccapi/lib/unix/Makefile.in b/krb5-1.21.3/src/ccapi/lib/unix/Makefile.in new file mode 100644 index 00000000..ce47d65d --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/unix/Makefile.in @@ -0,0 +1,12 @@ +mydir=ccapi$(S)lib$(S)unix +BUILDTOP=$(REL)..$(S)..$(S).. +LOCALINCLUDES= -I$(srcdir)/.. -I$(srcdir)/../../common + +STLIBOBJS= stubs.o +OBJS= $(OUTPRE)stubs.$(OBJEXT) + +all-unix: all-libobjs +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/ccapi/lib/unix/deps b/krb5-1.21.3/src/ccapi/lib/unix/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/unix/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/ccapi/lib/unix/stubs.c b/krb5-1.21.3/src/ccapi/lib/unix/stubs.c new file mode 100644 index 00000000..3afd8f10 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/unix/stubs.c @@ -0,0 +1,10 @@ +#include +#include "ccapi_os_ipc.h" + +cc_int32 cci_os_ipc_thread_init (void) +{ + return EINVAL; +} +void cci_os_ipc_thread_fini (void) +{ +} diff --git a/krb5-1.21.3/src/ccapi/lib/win/Makefile.in b/krb5-1.21.3/src/ccapi/lib/win/Makefile.in new file mode 100644 index 00000000..ef6c1cc2 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/win/Makefile.in @@ -0,0 +1,123 @@ +# makefile: Constructs the Kerberos for Windows CCAPI DLL. +# +OBJS = $(OUTPRE)ccapi_ccache.obj \ + $(OUTPRE)ccapi_ccache_iterator.obj \ + $(OUTPRE)ccapi_context.obj \ + $(OUTPRE)ccapi_context_change_time.obj \ + $(OUTPRE)ccapi_credentials.obj \ + $(OUTPRE)ccapi_credentials_iterator.obj \ + $(OUTPRE)ccapi_ipc.obj \ + $(OUTPRE)ccapi_err.obj \ + $(OUTPRE)ccapi_os_ipc.obj \ + $(OUTPRE)ccapi_string.obj \ + $(OUTPRE)ccapi_v2.obj \ + $(OUTPRE)cci_array_internal.obj \ + $(OUTPRE)cci_cred_union.obj \ + $(OUTPRE)cci_debugging.obj \ + $(OUTPRE)cci_identifier.obj \ + $(OUTPRE)cci_message.obj \ + $(OUTPRE)cci_os_debugging.obj \ + $(OUTPRE)cci_os_identifier.obj \ + $(OUTPRE)ccs_reply_proc.obj \ + $(OUTPRE)ccs_reply_s.obj \ + $(OUTPRE)ccs_request_c.obj \ + $(OUTPRE)ccutils.obj \ + $(OUTPRE)client.obj \ + $(OUTPRE)dllmain.obj \ + $(OUTPRE)init.obj \ + $(OUTPRE)secure.obj \ + $(OUTPRE)tls.obj \ + $(OUTPRE)util.obj \ + $(OUTPRE)win-utils.obj + +##### Options +# Set NODEBUG if building release instead of debug + +#BUILDTOP is krb5/src and is relative to krb5/src/ccapi/lib/win, for making Makefile. +BUILDTOP= ..\..\.. +CCAPI = $(BUILDTOP)\CCAPI +CO = $(CCAPI)\common +COWIN = $(CCAPI)\common\win +CCUTIL = $(CCAPI)\common\win\OldCC +LIBDIR = $(CCAPI)\lib +LIBWIN = $(LIBDIR)\win +POSIX = $(BUILDTOP)\lib\krb5\posix +OLDCC = $(LIBWIN)\OldCC +SRCTMP = $(LIBWIN)\srctmp + +!if defined(KRB5_KFW_COMPILE) +KFWINC= /I$(BUILDTOP)\..\..\krbcc\include +!endif + +# Because all the sources are pulled together into the temp directory SRCTMP, +# the only includes we need are to directories outside of ccapi. +LOCALINCLUDES = /I..\$(BUILDTOP) /I..\$(BUILDTOP)\include /I..\$(BUILDTOP)\include\krb5 $(KFWINC) \ + -I..\$(BUILDTOP)\util\et +MIDLINCLUDES = /I..\$(BUILDTOP)\include + +CPPFLAGS = $(CPPFLAGS) /EHsc -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 \ +-D_WIN32_WINNT=0x0501 -D_CRT_SECURE_NO_WARNINGS $(cvarsdll) + + +##### Linker +LINK = link +LIBS = ..\$(CLIB) ..\$(SLIB) kernel32.lib ws2_32.lib user32.lib advapi32.lib +LFLAGS = /nologo $(LOPTS) + +all: Makefile copysrc midl $(OUTPRE)$(CCLIB).dll finish + +ccs_request.h ccs_request_c.c ccs_request_s.c : ccs_request.idl ccs_request.acf + midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \ + ccs_request.idl + +ccs_reply.h ccs_reply_c.c ccs_reply_s.c : ccs_reply.idl ccs_reply.acf + midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \ + ccs_reply.idl + +copysrc : + echo "Copying all sources needed to build $(CCLIB).dll to $(SRCTMP)" + if NOT exist $(SRCTMP)\nul mkdir $(SRCTMP) + xcopy /D/Y $(CO)\*.* $(SRCTMP) + xcopy /D/Y $(COWIN)\*.* $(SRCTMP) + xcopy /D/Y $(CCUTIL)\*.* $(SRCTMP) + xcopy /D/Y $(LIBDIR)\*.* $(SRCTMP) + xcopy /D/Y $(LIBWIN)\*.* $(SRCTMP) + xcopy /D/Y $(OLDCC)\*.* $(SRCTMP) + cd $(SRCTMP) + if NOT exist $(OUTPRE)\nul mkdir $(OUTPRE) + +midl : ccs_request.h ccs_reply.h + +VERSIONRC = $(BUILDTOP)\..\windows\version.rc +CCLIBRES = $(OUTPRE)$(CCLIB).res +# Main program: +$(CCLIBRES): $(VERSIONRC) + $(RC) $(RCFLAGS) -DCCAPI_LIB -fo $@ -r $** + +$(OUTPRE)$(CCLIB).dll: $(OBJS) $(CCLIB).def $(CCLIBRES) + $(LINK) $(LFLAGS) -entry:$(ENTRYPOINT) -dll /map:$*.map /out:$@ /DEF:$(CCLIB).def $(OBJS) \ + /implib:$(CCLIB).lib $(dllflags) $(LIBS) $(KFWLIB) $(CCLIBRES) rpcrt4.lib $(conlibsdll) $(conflags) + +$(CCLIB).def: + echo ;$(CCLIB).def is generated by a Makefile rule. > $(CCLIB).def + echo HEAPSIZE 8192 >> $(CCLIB).def + echo EXPORTS >> $(CCLIB).def + type ccapi.exports >> $(CCLIB).def + type ccapi_v2.exports >> $(CCLIB).def + type debug.exports >> $(CCLIB).def + +finish: + echo "Finished in ccapi/lib/win." + cd .. + +install: + echo "Doing nothing for make install" + +clean: + if exist $(OUTPRE)*.exe del $(OUTPRE)*.exe + if exist $(OUTPRE)*.obj del $(OUTPRE)*.obj + if exist $(OUTPRE)*.res del $(OUTPRE)*.res + if exist $(OUTPRE)*.map del $(OUTPRE)*.map + if exist $(OUTPRE)*.pdb del $(OUTPRE)*.pdb + if exist *.err del *.err + if exist $(SRCTMP) rmdir /s /q $(SRCTMP) diff --git a/krb5-1.21.3/src/ccapi/lib/win/OldCC/ccapi.h b/krb5-1.21.3/src/ccapi/lib/win/OldCC/ccapi.h new file mode 100644 index 00000000..4d6f3faa --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/win/OldCC/ccapi.h @@ -0,0 +1,260 @@ +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 6.00.0366 */ +/* at Fri Nov 30 10:06:16 2007 + */ +/* Compiler settings for ccapi.idl: + Oic, W1, Zp8, env=Win32 (32b run) + protocol : dce , ms_ext, c_ext, oldnames + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +//@@MIDL_FILE_HEADING( ) + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 440 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __ccapi_h__ +#define __ccapi_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifdef __cplusplus +extern "C"{ +#endif + +void * __RPC_USER MIDL_user_allocate(size_t); +void __RPC_USER MIDL_user_free( void * ); + +#ifndef __ccapi_INTERFACE_DEFINED__ +#define __ccapi_INTERFACE_DEFINED__ + +/* interface ccapi */ +/* [implicit_handle][unique][version][uuid] */ + +typedef /* [context_handle] */ struct opaque_handle_CTX *HCTX; + +typedef /* [context_handle] */ struct opaque_handle_CACHE *HCACHE; + +typedef /* [context_handle] */ struct opaque_handle_CACHE_ITER *HCACHE_ITER; + +typedef /* [context_handle] */ struct opaque_handle_CRED_ITER *HCRED_ITER; + +typedef unsigned char CC_CHAR; + +typedef unsigned char CC_UCHAR; + +typedef int CC_INT32; + +typedef unsigned int CC_UINT32; + +typedef CC_INT32 CC_TIME_T; + + +enum __MIDL_ccapi_0001 + { STK_AFS = 0, + STK_DES = 1 + } ; + +enum __MIDL_ccapi_0002 + { CC_API_VER_1 = 1, + CC_API_VER_2 = 2 + } ; + +enum __MIDL_ccapi_0003 + { KRB_NAME_SZ = 40, + KRB_INSTANCE_SZ = 40, + KRB_REALM_SZ = 40, + } ; +typedef struct _NC_INFO + { + /* [string] */ CC_CHAR *name; + /* [string] */ CC_CHAR *principal; + CC_INT32 vers; + } NC_INFO; + +typedef struct _NC_INFO_LIST + { + CC_UINT32 length; + /* [size_is] */ NC_INFO *info; + } NC_INFO_LIST; + +typedef struct _CC_DATA + { + CC_UINT32 type; + CC_UINT32 length; + /* [size_is] */ CC_UCHAR *data; + } CC_DATA; + +typedef struct _CC_DATA_LIST + { + CC_UINT32 count; + /* [size_is] */ CC_DATA *data; + } CC_DATA_LIST; + +typedef struct _V5_CRED + { + /* [string] */ CC_CHAR *client; + /* [string] */ CC_CHAR *server; + CC_DATA keyblock; + CC_TIME_T authtime; + CC_TIME_T starttime; + CC_TIME_T endtime; + CC_TIME_T renew_till; + CC_UINT32 is_skey; + CC_UINT32 ticket_flags; + CC_DATA_LIST addresses; + CC_DATA ticket; + CC_DATA second_ticket; + CC_DATA_LIST authdata; + } V5_CRED; + +typedef /* [switch_type] */ union _CRED_PTR_UNION + { + /* [case()] */ V5_CRED *pV5Cred; + } CRED_PTR_UNION; + +typedef struct _CRED_UNION + { + CC_INT32 cred_type; + /* [switch_is] */ CRED_PTR_UNION cred; + } CRED_UNION; + +CC_INT32 rcc_initialize( + /* [out] */ HCTX *pctx); + +CC_INT32 rcc_shutdown( + /* [out][in] */ HCTX *pctx); + +CC_INT32 rcc_get_change_time( + /* [in] */ HCTX ctx, + /* [out] */ CC_TIME_T *time); + +CC_INT32 rcc_create( + /* [in] */ HCTX ctx, + /* [string][in] */ const CC_CHAR *name, + /* [string][in] */ const CC_CHAR *principal, + /* [in] */ CC_INT32 vers, + /* [in] */ CC_UINT32 flags, + /* [out] */ HCACHE *pcache); + +CC_INT32 rcc_open( + /* [in] */ HCTX ctx, + /* [string][in] */ const CC_CHAR *name, + /* [in] */ CC_INT32 vers, + /* [in] */ CC_UINT32 flags, + /* [out] */ HCACHE *pcache); + +CC_INT32 rcc_close( + /* [out][in] */ HCACHE *pcache); + +CC_INT32 rcc_destroy( + /* [out][in] */ HCACHE *pcache); + +CC_INT32 rcc_seq_fetch_NCs_begin( + /* [in] */ HCTX ctx, + /* [out] */ HCACHE_ITER *piter); + +CC_INT32 rcc_seq_fetch_NCs_end( + /* [out][in] */ HCACHE_ITER *piter); + +CC_INT32 rcc_seq_fetch_NCs_next( + /* [in] */ HCACHE_ITER iter, + /* [out] */ HCACHE *pcache); + +CC_INT32 rcc_seq_fetch_NCs( + /* [in] */ HCTX ctx, + /* [out][in] */ HCACHE_ITER *piter, + /* [out] */ HCACHE *pcache); + +CC_INT32 rcc_get_NC_info( + /* [in] */ HCTX ctx, + /* [out] */ NC_INFO_LIST **info_list); + +CC_INT32 rcc_get_name( + /* [in] */ HCACHE cache, + /* [string][out] */ CC_CHAR **name); + +CC_INT32 rcc_set_principal( + /* [in] */ HCACHE cache, + /* [in] */ CC_INT32 vers, + /* [string][in] */ const CC_CHAR *principal); + +CC_INT32 rcc_get_principal( + /* [in] */ HCACHE cache, + /* [string][out] */ CC_CHAR **principal); + +CC_INT32 rcc_get_cred_version( + /* [in] */ HCACHE cache, + /* [out] */ CC_INT32 *vers); + +CC_INT32 rcc_lock_request( + /* [in] */ HCACHE cache, + /* [in] */ CC_INT32 lock_type); + +CC_INT32 rcc_store( + /* [in] */ HCACHE cache, + /* [in] */ CRED_UNION cred); + +CC_INT32 rcc_remove_cred( + /* [in] */ HCACHE cache, + /* [in] */ CRED_UNION cred); + +CC_INT32 rcc_seq_fetch_creds( + /* [in] */ HCACHE cache, + /* [out][in] */ HCRED_ITER *piter, + /* [out] */ CRED_UNION **cred); + +CC_INT32 rcc_seq_fetch_creds_begin( + /* [in] */ HCACHE cache, + /* [out] */ HCRED_ITER *piter); + +CC_INT32 rcc_seq_fetch_creds_end( + /* [out][in] */ HCRED_ITER *piter); + +CC_INT32 rcc_seq_fetch_creds_next( + /* [in] */ HCRED_ITER iter, + /* [out] */ CRED_UNION **cred); + +CC_UINT32 Connect( + /* [string][in] */ CC_CHAR *name); + +void Shutdown( void); + + +extern handle_t ccapi_IfHandle; + + +extern RPC_IF_HANDLE ccapi_ClientIfHandle; +extern RPC_IF_HANDLE ccapi_ServerIfHandle; +#endif /* __ccapi_INTERFACE_DEFINED__ */ + +/* Additional Prototypes for ALL interfaces */ + +void __RPC_USER HCTX_rundown( HCTX ); +void __RPC_USER HCACHE_rundown( HCACHE ); +void __RPC_USER HCACHE_ITER_rundown( HCACHE_ITER ); +void __RPC_USER HCRED_ITER_rundown( HCRED_ITER ); + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/krb5-1.21.3/src/ccapi/lib/win/OldCC/client.cxx b/krb5-1.21.3/src/ccapi/lib/win/OldCC/client.cxx new file mode 100644 index 00000000..0f95dfce --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/win/OldCC/client.cxx @@ -0,0 +1,388 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "stdio.h" // KPKDBG + +#include "ccs_request.h" + +#include "ccapi.h" +#include "util.h" + +extern "C" { +#include "cci_debugging.h" +#include "tls.h" // KPKDBG + } + +#include "client.h" +#include "init.hxx" +#include "name.h" +#include "secure.hxx" + +#define SECONDS_TO_WAIT 10 + +#define STARTUP "CLIENT STARTUP: " +#define DISCONNECT "CLIENT DISCONNECT: " + +bool Client::s_init = false; +CcOsLock Client::sLock; + +static DWORD bind_client(char* ep OPTIONAL, Init::InitInfo& info, LPSTR* endpoint) { + DWORD status = 0; + unsigned char * pszStringBinding = NULL; + + if (!ep) { + status = alloc_name(endpoint, "ep", isNT()); + } + else { + *endpoint = ep; + } + + if (!status) { + /* Use a convenience function to concatenate the elements of */ + /* the string binding into the proper sequence. */ + status = RpcStringBindingCompose(0, // uuid + (unsigned char*)"ncalrpc", // protseq + 0, // address + (unsigned char*)(*endpoint), // endpoint + 0, // options + &pszStringBinding); + cci_check_error(status); + } + + if (!status) { + /* Set the binding handle that will be used to bind to the server. */ + status = RpcBindingFromStringBinding(pszStringBinding, &ccs_request_IfHandle); + cci_check_error(status); + } + + if (!status) { + // Win9x might call RpcBindingSetAuthInfo (not Ex), but it does not + // quite work on Win9x... + if (isNT()) { + RPC_SECURITY_QOS qos; + qos.Version = RPC_C_SECURITY_QOS_VERSION; + qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT; + qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; + qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY; + + status = info.fRpcBindingSetAuthInfoEx(ccs_request_IfHandle, + 0, // principal + RPC_C_AUTHN_LEVEL_CONNECT, + RPC_C_AUTHN_WINNT, + 0, // current address space + RPC_C_AUTHZ_NAME, + &qos); + cci_check_error(status); + } + } + + if (pszStringBinding) { + DWORD status = RpcStringFree(&pszStringBinding); + cci_check_error(status); + } + return cci_check_error(status); + } + +DWORD find_server(Init::InitInfo& info, LPSTR endpoint) { + DWORD status = 0; + LPSTR event_name = 0; + HANDLE hEvent = 0; + SECURITY_ATTRIBUTES sa = { 0 }; + PSECURITY_ATTRIBUTES psa = 0; + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + char* szExe = 0; + char* szDir = 0; + BOOL bRes = FALSE; + char* cmdline = NULL; + + psa = isNT() ? &sa : 0; + + cci_debug_printf("%s Looking for server; ccs_request_IfHandle:0x%X", __FUNCTION__, ccs_request_IfHandle); + status = cci_check_error(RpcMgmtIsServerListening(ccs_request_IfHandle)); + if (status == RPC_S_NOT_LISTENING) { + cci_debug_printf(" Server *NOT* found!"); + si.cb = sizeof(si); + + status = alloc_module_dir_name(CCAPI_DLL, &szDir); + + if (!status) { + status = alloc_module_dir_name_with_file(CCAPI_DLL, CCAPI_EXE, &szExe); + } + + if (!status) { + status = alloc_name(&event_name, "startup", isNT()); + cci_check_error(status); + } + + if (!status) { + if (isNT()) { + sa.nLength = sizeof(sa); + status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor); + cci_check_error(status); + } + } + + if (!status) { + hEvent = CreateEvent(psa, FALSE, FALSE, event_name); + cci_debug_printf(" CreateEvent(... %s) returned hEvent 0x%X", event_name, hEvent); + if (!hEvent) status = GetLastError(); + } + + if (!status) { + alloc_cmdline_2_args(szExe, endpoint, "-D", &cmdline); + bRes = CreateProcess( szExe, // app name + NULL, //cmdline, // cmd line is + psa, // SA + psa, // SA + FALSE, + CREATE_NEW_PROCESS_GROUP | + NORMAL_PRIORITY_CLASS | +#ifdef CCAPI_LAUNCH_SERVER_WITH_CONSOLE + CREATE_NEW_CONSOLE | +#else + DETACHED_PROCESS | +#endif + 0, + NULL, // environment + szDir, // current dir + &si, + &pi); + if (!bRes) { + status = GetLastError(); + cci_debug_printf(" CreateProcess returned %d; LastError: %d", bRes, status); + } + cci_debug_printf(" Waiting..."); + } + cci_check_error(status); + + if (!status) { + status = WaitForSingleObject(hEvent, (SECONDS_TO_WAIT)*1000); + status = RpcMgmtIsServerListening(ccs_request_IfHandle); + } + } + else if (status) { + cci_debug_printf(" unexpected error while looking for server: 0D%d / 0U%u / 0X%X", status, status, status); + } + + if (szDir) free_alloc_p(&szDir); + if (szExe) free_alloc_p(&szExe); + if (hEvent) CloseHandle(hEvent); + if (pi.hThread) CloseHandle(pi.hThread); + if (pi.hProcess) CloseHandle(pi.hProcess); + if (sa.lpSecurityDescriptor) free_alloc_p(&sa.lpSecurityDescriptor); + return cci_check_error(status); + +} + +static +DWORD +make_random_challenge(DWORD *challenge_out) { + HCRYPTPROV provider; + DWORD status = 0; + *challenge_out = 0; + if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + status = GetLastError(); + cci_check_error(status); + return status; + } + if (!CryptGenRandom(provider, sizeof(*challenge_out), + (BYTE *)challenge_out)) { + status = GetLastError(); + cci_check_error(status); + return status; + } + if (!CryptReleaseContext(provider, 0)) { + /* + * Note: even though CryptReleaseContext() failed, we don't really + * care since a) we've already successfully obtained our challenge + * anyway and b) at least one of the potential errors, "ERROR_BUSY" + * does not really seem to be an error at all. So GetLastError() is + * logged for informational purposes only and should not be returned. + */ + cci_check_error(GetLastError()); + } + return status; +} + +static +DWORD +authenticate_server(Init::InitInfo& info) { + DWORD challenge, desired_response; + HANDLE hMap = 0; + LPSTR mem_name = 0; + PDWORD pvalue = 0; + CC_UINT32 response = 0; + SECURITY_ATTRIBUTES sa = { 0 }; + DWORD status = 0; + + cci_debug_printf("%s entry", __FUNCTION__); + + status = alloc_name(&mem_name, "auth", isNT()); + cci_check_error(status); + + if (!status) { + status = make_random_challenge(&challenge); + desired_response = challenge + 1; + cci_check_error(status); + } + + if (!status) { + if (isNT()) { + sa.nLength = sizeof(sa); + status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor); + } + } + cci_check_error(status); + + if (!status) { + hMap = CreateFileMapping(INVALID_HANDLE_VALUE, isNT() ? &sa : 0, + PAGE_READWRITE, 0, sizeof(DWORD), mem_name); + if (!hMap) + status = GetLastError(); + } + cci_check_error(status); + + if (!status) { + pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (!pvalue) status = GetLastError(); + } + cci_check_error(status); + + if (!status) { + *pvalue = challenge; + + RpcTryExcept { + response = ccs_authenticate( (CC_CHAR*)mem_name ); + } + RpcExcept(1) { + status = RpcExceptionCode(); + cci_check_error(status); + } + RpcEndExcept; + } + cci_check_error(status); + + if (!status) { + // Check response + if ((response != desired_response) && (*pvalue != desired_response)) { + cci_debug_printf(" Could not authenticate server."); + status = ERROR_ACCESS_DENIED; // XXX - CO_E_NOMATCHINGSIDFOUND? + } + else { + cci_debug_printf(" Server authenticated!"); + } + cci_check_error(status); + } + + free_alloc_p(&mem_name); + free_alloc_p(&sa.lpSecurityDescriptor); + if (pvalue) { + BOOL ok = UnmapViewOfFile(pvalue); +// DEBUG_ASSERT(ok); + } + if (hMap) CloseHandle(hMap); + return status; +} + +DWORD +Client::Disconnect() { + DWORD status = 0; + if (ccs_request_IfHandle) { + /* The calls to the remote procedures are complete. */ + /* Free the binding handle */ + status = RpcBindingFree(&ccs_request_IfHandle); + } + s_init = false; + return status; + } + +DWORD +Client::Connect(char* ep OPTIONAL) { + LPSTR endpoint = 0; + DWORD status = 0; + + if (!ccs_request_IfHandle) { + Init::InitInfo info; + + status = Init::Info(info); + cci_check_error(status); + + if (!status) { + status = bind_client(ep, info, &endpoint); + cci_check_error(status); + } + + if (!status) { + status = find_server(info, endpoint); + cci_check_error(status); + } + + if (!status) { + status = authenticate_server(info); + cci_check_error(status); + } + } + + + if (endpoint && (endpoint != ep)) free_alloc_p(&endpoint); + + if (status) Client::Disconnect(); + return status; + } + +DWORD Client::Initialize(char* ep OPTIONAL) { + CcAutoTryLock AL(Client::sLock); + if (!AL.IsLocked() || s_init) + return 0; + SecureClient s; + ccs_request_IfHandle = NULL; + DWORD status = Client::Connect(ep); + if (!status) s_init = true; + return status; + } + +DWORD Client::Cleanup() { + CcAutoLock AL(Client::sLock); + SecureClient s; + return Client::Disconnect(); + } + +DWORD Client::Reconnect(char* ep OPTIONAL) { + CcAutoLock AL(Client::sLock); + SecureClient s; + DWORD status = 0; + + if (Initialized()) { + DWORD status = Client::Cleanup(); + } + if ( (!status) ) { + status = Client::Initialize(ep); + } + + return status; + } diff --git a/krb5-1.21.3/src/ccapi/lib/win/OldCC/client.h b/krb5-1.21.3/src/ccapi/lib/win/OldCC/client.h new file mode 100644 index 00000000..1c67acd1 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/win/OldCC/client.h @@ -0,0 +1,60 @@ +/* ccapi/lib/win/OldCC/client.h */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __DLL_CLIENT_H__ +#define __DLL_CLIENT_H__ + +#include "autolock.hxx" +#include "init.hxx" + +class Client { +public: + static DWORD Initialize(char* ep OPTIONAL); + static DWORD Cleanup(); + static DWORD Reconnect(char* ep OPTIONAL); + + static bool Initialized() { return s_init; } + + static CcOsLock sLock; + +private: + static bool s_init; + + static DWORD Disconnect(); + static DWORD Connect(char* ep OPTIONAL); + }; + +#define CLIENT_INIT_EX(trap, error) \ +do \ +{ \ + INIT_INIT_EX(trap, error); \ + if (!Client::Initialized()) \ + { \ + DWORD status = Client::Initialize(0); \ + if (status) return (trap) ? (error) : status; \ + } \ +} while(0) + +#endif diff --git a/krb5-1.21.3/src/ccapi/lib/win/WINCCAPI.sln b/krb5-1.21.3/src/ccapi/lib/win/WINCCAPI.sln new file mode 100644 index 00000000..cee98915 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/win/WINCCAPI.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WINCCAPI", "WINCCAPI.vcproj", "{1137FC16-E53E-48C1-8293-085B4BE68C32}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1137FC16-E53E-48C1-8293-085B4BE68C32}.Debug|Win32.ActiveCfg = Debug|Win32 + {1137FC16-E53E-48C1-8293-085B4BE68C32}.Debug|Win32.Build.0 = Debug|Win32 + {1137FC16-E53E-48C1-8293-085B4BE68C32}.Release|Win32.ActiveCfg = Release|Win32 + {1137FC16-E53E-48C1-8293-085B4BE68C32}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/krb5-1.21.3/src/ccapi/lib/win/WINCCAPI.vcproj b/krb5-1.21.3/src/ccapi/lib/win/WINCCAPI.vcproj new file mode 100644 index 00000000..9af0e21a --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/win/WINCCAPI.vcproj @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/krb5-1.21.3/src/ccapi/lib/win/ccapi_os_ipc.cxx b/krb5-1.21.3/src/ccapi/lib/win/ccapi_os_ipc.cxx new file mode 100644 index 00000000..1b1f874e --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/win/ccapi_os_ipc.cxx @@ -0,0 +1,365 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +extern "C" { +#include "k5-thread.h" +#include "ccapi_os_ipc.h" +#include "cci_debugging.h" +#include "ccs_reply.h" +#include "ccs_request.h" +#include "ccutils.h" +#include "tls.h" +#include "util.h" +#include "win-utils.h" + } + +#include "autolock.hxx" +#include "CredentialsCache.h" +#include "secure.hxx" +#include "opts.hxx" +#include "client.h" + +extern "C" DWORD GetTlsIndex(); + +#define SECONDS_TO_WAIT 10 +#define CLIENT_REQUEST_RPC_HANDLE ccs_request_IfHandle + +extern HANDLE hCCAPIv2Mutex; +ParseOpts::Opts opts = { 0 }; +PSECURITY_ATTRIBUTES psa = 0; +SECURITY_ATTRIBUTES sa = { 0 }; + +/* The layout of the rest of this module: + + The entrypoints defined in ccs_os_ipc.h: + cci_os_ipc_thread_init + cci_os_ipc + + Other routines needed by those four. + cci_os_connect + handle_exception + */ + +cc_int32 ccapi_connect(const struct tspdata* tsp); +static DWORD handle_exception(DWORD code, struct tspdata* ptspdata); + +extern "C" { +cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, + k5_ipc_stream in_request_stream, + cc_int32 in_msg, + k5_ipc_stream* out_reply_stream); + } + +/* ------------------------------------------------------------------------ */ + +extern "C" cc_int32 cci_os_ipc_process_init (void) { + RPC_STATUS status; + + if (!isNT()) { + status = RpcServerRegisterIf(ccs_reply_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL); // MgrEpv; null means use default + } + else { + status = RpcServerRegisterIfEx(ccs_reply_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL, // MgrEpv; 0 means default + RPC_IF_ALLOW_SECURE_ONLY, + RPC_C_LISTEN_MAX_CALLS_DEFAULT, + NULL); // No security callback. + } + cci_check_error(status); + + if (!status) { + status = RpcServerRegisterAuthInfo(0, // server principal + RPC_C_AUTHN_WINNT, + 0, + 0 ); + cci_check_error(status); + } + + return status; // ugh. needs translation +} + +/* ------------------------------------------------------------------------ */ + +extern "C" cc_int32 cci_os_ipc_thread_init (void) { + cc_int32 err = ccNoError; + struct tspdata* ptspdata; + HANDLE replyEvent = NULL; + UUID __RPC_FAR uuid; + RPC_CSTR __RPC_FAR uuidString = NULL; + char* endpoint = NULL; + + if (!GetTspData(GetTlsIndex(), &ptspdata)) return ccErrNoMem; + + err = cci_check_error(UuidCreate(&uuid)); // Get a UUID + if (err == RPC_S_OK) { // Convert to string + err = UuidToString(&uuid, &uuidString); + cci_check_error(err); + } + if (!err) { // Save in thread local storage + tspdata_setUUID(ptspdata, uuidString); + endpoint = clientEndpoint((const char *)uuidString); + err = RpcServerUseProtseqEp((RPC_CSTR)"ncalrpc", + RPC_C_PROTSEQ_MAX_REQS_DEFAULT, + (RPC_CSTR)endpoint, + sa.lpSecurityDescriptor); // SD + free(endpoint); + cci_check_error(err); + } + + // Initialize old CCAPI if necessary: + if (!err) if (!Init:: Initialized()) err = Init:: Initialize( ); + if (!err) if (!Client::Initialized()) err = Client::Initialize(0); + + if (!err) { + /* Whenever a reply to an RPC request is received, the RPC caller needs to + know when the reply has been received. It does that by waiting for a + client-specific event to be set. Define the event name to be _reply: */ + replyEvent = createThreadEvent((char*)uuidString, REPLY_SUFFIX); + } + + if (!err) { + static bool bListening = false; + if (!bListening) { + err = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); + cci_check_error(err); + } + bListening = err == 0; + } + + if (replyEvent) tspdata_setReplyEvent(ptspdata, replyEvent); + else err = cci_check_error(GetLastError()); + + if (uuidString) RpcStringFree(&uuidString); + + return cci_check_error(err); + } + + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_os_ipc (cc_int32 in_launch_server, + k5_ipc_stream in_request_stream, + k5_ipc_stream* out_reply_stream) { + return cci_os_ipc_msg( in_launch_server, + in_request_stream, + CCMSG_REQUEST, + out_reply_stream); + } + +extern "C" cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, + k5_ipc_stream in_request_stream, + cc_int32 in_msg, + k5_ipc_stream* out_reply_stream) { + + cc_int32 err = ccNoError; + cc_int32 done = FALSE; + cc_int32 try_count = 0; + cc_int32 server_died = FALSE; + TCHAR* pszStringBinding= NULL; + struct tspdata* ptspdata = NULL; + char* uuid = NULL; + int lenUUID = 0; + unsigned int trycount = 0; + time_t sst = 0; + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + HANDLE replyEvent = 0; + BOOL bCCAPI_Connected= FALSE; + BOOL bListening = FALSE; + unsigned char tspdata_handle[8] = { 0 }; + + if (!in_request_stream) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!GetTspData(GetTlsIndex(), &ptspdata)) {return ccErrBadParam;} + bListening = tspdata_getListening(ptspdata); + if (!bListening) { + err = cci_check_error(cci_os_ipc_thread_init()); + bListening = !err; + tspdata_setListening(ptspdata, bListening); + } + + bCCAPI_Connected = tspdata_getConnected (ptspdata); + replyEvent = tspdata_getReplyEvent (ptspdata); + sst = tspdata_getSST (ptspdata); + uuid = tspdata_getUUID(ptspdata); + + // The lazy connection to the server has been put off as long as possible! + // ccapi_connect starts listening for replies as an RPC server and then + // calls ccs_rpc_connect. + if (!err && !bCCAPI_Connected) { + err = cci_check_error(ccapi_connect(ptspdata)); + bCCAPI_Connected = !err; + tspdata_setConnected(ptspdata, bCCAPI_Connected); + } + + // Clear replyEvent so we can detect when a reply to our request has been received: + ResetEvent(replyEvent); + + //++ Use the old CCAPI implementation to try to talk to the server: + // It has all the code to use the RPC in a thread-safe way, make the endpoint, + // (re)connect and (re)start the server. + // Note: the old implementation wrapped the thread-safety stuff in a macro. + // Here it is expanded and thus duplicated for each RPC call. The new code has + // a very limited number of RPC calls, unlike the older code. + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); + SecureClient* s = 0; + SecureClient::Start(s); + CcAutoLock* a = 0; + CcAutoLock::Start(a, Client::sLock); + + // New code using new RPC procedures for sending the data and receiving a reply: + if (!err) { + RpcTryExcept { + if (!GetTspData(GetTlsIndex(), &ptspdata)) {return ccErrBadParam;} + uuid = tspdata_getUUID(ptspdata); + lenUUID = 1 + strlen(uuid); /* 1+ includes terminating \0. */ + /* copy ptr into handle; ptr may be 4 or 8 bytes, depending on platform; handle is always 8 */ + memcpy(tspdata_handle, &ptspdata, sizeof(ptspdata)); + ccs_rpc_request( /* make call with user message: */ + in_msg, /* Message type */ + tspdata_handle, /* Our tspdata* will be sent back to the reply proc. */ + (unsigned char*)uuid, + krb5int_ipc_stream_size(in_request_stream), + (unsigned char*)krb5int_ipc_stream_data(in_request_stream), /* Data buffer */ + sst, /* session start time */ + (long*)(&err) ); /* Return code */ + } + RpcExcept(1) { + err = handle_exception(RpcExceptionCode(), ptspdata); + } + RpcEndExcept; + } + + cci_check_error(err); + CcAutoLock::Stop(a); + SecureClient::Stop(s); + ReleaseMutex(hCCAPIv2Mutex); + //-- Use the old CCAPI implementation to try to talk to the server. + + // Wait for reply handler to set event: + if (!err) { + err = cci_check_error(WaitForSingleObject(replyEvent, INFINITE));//(SECONDS_TO_WAIT)*1000)); + } + + if (!err) { + err = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE)); + } + + if (!err && server_died) { + err = cci_check_error (ccErrServerUnavailable); + } + + if (!err) { + *out_reply_stream = tspdata_getStream(ptspdata); + } + + return cci_check_error (err); + } + + + +static DWORD handle_exception(DWORD code, struct tspdata* ptspdata) { + cci_debug_printf("%s code %u; ccs_request_IfHandle:0x%X", __FUNCTION__, code, ccs_request_IfHandle); + if ( (code == RPC_S_SERVER_UNAVAILABLE) || (code == RPC_S_INVALID_BINDING) ) { + Client::Cleanup(); + tspdata_setConnected(ptspdata, FALSE); + } + return code; + } + + +/* Establish a CCAPI connection with the server. + * The connect logic here is identical to the logic in the send request code. + * TODO: merge this connect code with that request code. + */ +cc_int32 ccapi_connect(const struct tspdata* tsp) { + BOOL bListen = TRUE; + HANDLE replyEvent = 0; + RPC_STATUS status = FALSE; + char* uuid = NULL; + unsigned char tspdata_handle[8] = {0}; + + /* Start listening to our uuid before establishing the connection, + * so that when the server tries to call ccapi_listen, we will be ready. + */ + + /* Build complete RPC uuid using previous CCAPI implementation: */ + replyEvent = tspdata_getReplyEvent(tsp); + uuid = tspdata_getUUID(tsp); + + cci_debug_printf("%s is listening ...", __FUNCTION__); + + // Clear replyEvent so we can detect when a reply to our connect request has been received: + ResetEvent(replyEvent); + + // We use the old CCAPI implementation to try to talk to the server. + // It has all the code to make the uuid, (re)connect and (re)start the server. + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); + SecureClient* s = 0; + SecureClient::Start(s); + CcAutoLock* a = 0; + CcAutoLock::Start(a, Client::sLock); + + // Initialize old CCAPI if necessary: + if (!status) if (!Init:: Initialized()) status = Init:: Initialize( ); + if (!status) if (!Client::Initialized()) status = Client::Initialize(0); + + // New code using new RPC procedures for sending the data and receiving a reply: + if (!status) { + memcpy(tspdata_handle, &tsp, sizeof(tsp)); + RpcTryExcept { + ccs_rpc_connect( /* make call with user message: */ + CCMSG_CONNECT, /* Message type */ + tspdata_handle, /* Our tspdata* will be sent back to the reply proc. */ + (unsigned char*)uuid, + (long*)(&status) ); /* Return code */ + } + RpcExcept(1) { + cci_check_error(RpcExceptionCode()); + status = ccErrBadInternalMessage; + } + RpcEndExcept; + } + + CcAutoLock::Stop(a); + SecureClient::Stop(s); + ReleaseMutex(hCCAPIv2Mutex); + + if (!status) { + status = WaitForSingleObject(replyEvent, INFINITE);//(SECONDS_TO_WAIT)*1000); + status = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE)); + cci_debug_printf(" Server %sFOUND!", (status) ? "NOT " : ""); + } + if (status) { + cci_debug_printf(" unexpected error while looking for server... (%u)", status); + } + + return status; + } diff --git a/krb5-1.21.3/src/ccapi/lib/win/ccs_reply_proc.c b/krb5-1.21.3/src/ccapi/lib/win/ccs_reply_proc.c new file mode 100644 index 00000000..b4dbc0d1 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/win/ccs_reply_proc.c @@ -0,0 +1,91 @@ +/* ccapi/lib/win/ccs_reply_proc.c */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include + +#include "cci_debugging.h" +#include "ccs_reply.h" /* generated by MIDL compiler */ +#include "ccutils.h" +#include "tls.h" +#include "win-utils.h" + + +void ccs_rpc_request_reply( + const long rpcmsg, /* Message type */ + const char tspHandle[], /* Client's tspdata* */ + const char* uuid, /* uuid for making thread-specific event name */ + const long srvStartTime, /* Server Start Time */ + const long cbIn, /* Length of buffer */ + const char* chIn, /* Data buffer */ + long* ret_status ) { /* Return code */ + + HANDLE hEvent = openThreadEvent(uuid, REPLY_SUFFIX); + struct tspdata* tsp; + k5_ipc_stream stream; + long status = 0; + + memcpy(&tsp, tspHandle, sizeof(tsp)); + if (!status) { + status = krb5int_ipc_stream_new (&stream); /* Create a stream for the request data */ + } + + if (!status) { /* Put the data into the stream */ + status = krb5int_ipc_stream_write (stream, chIn, cbIn); + } + + if (!status) { /* Put the data into the stream */ + tspdata_setStream(tsp, stream); + } + + SetEvent(hEvent); + CloseHandle(hEvent); + *ret_status = status; + } + +void ccs_rpc_connect_reply( + const long rpcmsg, /* Message type */ + const char tspHandle[], /* Client's tspdata* */ + const char* uuid, /* uuid for making thread-specific event name */ + const long srvStartTime, /* Server Start Time */ + long* status ) { /* Return code */ + + HANDLE hEvent = openThreadEvent(uuid, REPLY_SUFFIX); + DWORD* p = (DWORD*)(tspHandle); + + SetEvent(hEvent); + CloseHandle(hEvent); + } + +void ccapi_listen( + RPC_ASYNC_STATE* rpcState, + handle_t hBinding, + const long rpcmsg, /* Message type */ + long* status ) { /* Return code */ + + cci_debug_printf("%s %s!", __FUNCTION__, rpcState->UserInfo); + *status = 0; + } diff --git a/krb5-1.21.3/src/ccapi/lib/win/debug.exports b/krb5-1.21.3/src/ccapi/lib/win/debug.exports new file mode 100644 index 00000000..6dc1fc08 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/win/debug.exports @@ -0,0 +1,11 @@ + cci_debug_printf + _cci_check_error + cci_os_ipc + cci_os_ipc_msg + cci_os_ipc_thread_init + krb5int_ipc_stream_data + krb5int_ipc_stream_write + krb5int_ipc_stream_new + + ccs_authenticate + cci_os_ipc_process_init diff --git a/krb5-1.21.3/src/ccapi/lib/win/dllmain.cxx b/krb5-1.21.3/src/ccapi/lib/win/dllmain.cxx new file mode 100644 index 00000000..18aa0055 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/win/dllmain.cxx @@ -0,0 +1,212 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +extern "C" { +#include +#include + +#include "dllmain.h" +#include "tls.h" +#include "cci_debugging.h" +#include "ccapi_context.h" +#include "ccapi_ipc.h" +#include "client.h" + +void cci_process_init__auxinit(); + } + + +#define CCAPI_V2_MUTEX_NAME TEXT("MIT_CCAPI_V4_MUTEX") + +// Process-specific data: +static DWORD dwTlsIndex; +static char _user[UNLEN+1]; // Username is used as part of the server and client endpoints. +static HANDLE sessionToken; +static char* ep_prefices[] = {"CCS", "CCAPI"}; +HANDLE hCCAPIv2Mutex = NULL; +DWORD firstThreadID = 0; + +// These data structures are used by the old CCAPI implementation +// to keep track of the state of the RPC connection. All data is static. +static Init init; +static Client client; + +DWORD GetTlsIndex() {return dwTlsIndex;} + +// DllMain() is the entry-point function for this DLL. +BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle + DWORD fdwReason, // reason called + LPVOID lpvReserved) { // reserved + + struct tspdata* ptspdata; + BOOL fIgnore; + BOOL bStatus; + DWORD status = 0; // 0 is success. + DWORD maxUN = sizeof(_user); + unsigned int i = 0; + unsigned int j = 0; + + switch (fdwReason) { + // The DLL is loading due to process initialization or a call to LoadLibrary: + case DLL_PROCESS_ATTACH: + cci_debug_printf("%s DLL_PROCESS_ATTACH", __FUNCTION__); + // Process-wide mutex used to allow only one thread at a time into the RPC code: + hCCAPIv2Mutex = CreateMutex(NULL, FALSE, CCAPI_V2_MUTEX_NAME); + + // Figure out our username; it's process-wide: + bStatus = GetUserName(_user, &maxUN); + if (!bStatus) return bStatus; + + // Remove any characters that aren't valid endpoint characters: + while (_user[j] != 0) { + if (isalnum(_user[j])) _user[i++] = _user[j]; + j++; + } + _user[i] = '\0'; + + // Our logon session is determined in client.cxx, old CCAPI code carried + // over to this implementation. + + // Allocate a TLS index: + if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE; + + cci_process_init__auxinit(); + // Don't break; fallthrough: Initialize the TLS index for first thread. + + // The attached process creates a new thread: + case DLL_THREAD_ATTACH: + cci_debug_printf("%s DLL_THREAD_ATTACH", __FUNCTION__); + // Don't actually rely on this case for allocation of resources. + // Applications (like SecureCRT) may have threads already + // created (say 'A' and 'B') before the dll is loaded. If the dll + // is loaded in thread 'A' but then used in thread 'B', thread 'B' + // will never execute this code. + fIgnore = TlsSetValue(dwTlsIndex, NULL); + + // Do not call cci_ipc_thread_init() yet; defer until we actually + // need it. On XP, cci_ipc_thread_init() will cause additional + // threads to be immediately spawned, which will bring us right + // back here again ad infinitum, until windows + // resources are exhausted. + break; + + // The thread of the attached process terminates: + case DLL_THREAD_DETACH: + cci_debug_printf("%s DLL_THREAD_DETACH", __FUNCTION__); + // Release the allocated memory for this thread + ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); + if (ptspdata != NULL) { + free(ptspdata); + TlsSetValue(dwTlsIndex, NULL); + } + break; + + // DLL unload due to process termination or FreeLibrary: + case DLL_PROCESS_DETACH: + cci_debug_printf("%s DLL_PROCESS_DETACH", __FUNCTION__); + //++ Copied from previous implementation: + // Process Teardown "Problem" + // + // There are two problems that occur during process teardown: + // + // 1) Windows (NT/9x/2000) does not keep track of load/unload + // ordering dependencies for use in process teardown. + // + // 2) The RPC exception handling in the RPC calls do not work + // during process shutdown in Win9x. + // + // When a process is being torn down in Windows, the krbcc DLL + // may get a DLL_PROCESS_DETACH before other DLLs are done + // with it. Thus, it may disconnect from the RPC server + // before the last shutdown RPC call. + // + // On NT/2000, this is ok because the RPC call will fail and just + // return an error. + // + // On Win9x/Me, the RPC exception will not be caught. + // However, Win9x ignores exceptions during process shutdown, + // so the exception will never be seen unless a debugger is + // attached to the process. + // + // A good potential workaround would be to have a global + // variable that denotes whether the DLL is attached to the + // process. If it is not, all entrypoints into the DLL should + // return failure. + // + // A not as good workaround is below but ifdefed out. + // + // However, we can safely ignore this problem since it can + // only affects people running debuggers under 9x/Me who are + // using multiple DLLs that use this DLL. + // + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); + + // return value is ignored, so we set status for debugging purposes + status = Client::Cleanup(); + status = Init::Cleanup(); + ReleaseMutex( hCCAPIv2Mutex ); + CloseHandle( hCCAPIv2Mutex ); + //-- Copied from previous implementation. + + // Release the allocated memory for this thread: + ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); + if (ptspdata != NULL) + free(ptspdata); + TlsFree(dwTlsIndex); // Release the TLS index. + // Ideally, we would enumerate all other threads here and + // release their thread local storage as well. + break; + + default: + cci_debug_printf("%s unexpected reason %d", __FUNCTION__, fdwReason); + break; + } + + UNREFERENCED_PARAMETER(hinstDLL); // no whining! + UNREFERENCED_PARAMETER(lpvReserved); + return status ? FALSE : TRUE; +} + + +#ifdef __cplusplus // If used by C++ code, +extern "C" { // we need to export the C interface +#endif + +#ifdef __cplusplus +} +#endif + +/*********************************************************************/ +/* MIDL allocate and free */ +/*********************************************************************/ + +extern "C" void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len) { + return(malloc(len)); + } + +extern "C" void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr) { + free(ptr); + } diff --git a/krb5-1.21.3/src/ccapi/lib/win/dllmain.h b/krb5-1.21.3/src/ccapi/lib/win/dllmain.h new file mode 100644 index 00000000..8238566e --- /dev/null +++ b/krb5-1.21.3/src/ccapi/lib/win/dllmain.h @@ -0,0 +1,41 @@ +/* ccapi/lib/win/dllmain.h */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef _dll_h +#define _dll_h + +#include "windows.h" + +#ifdef __cplusplus // If used by C++ code, +extern "C" { // we need to export the C interface +#endif + +DWORD GetTlsIndex(); + +#ifdef __cplusplus +} +#endif + +#endif _dll_h diff --git a/krb5-1.21.3/src/ccapi/server/Makefile.in b/krb5-1.21.3/src/ccapi/server/Makefile.in new file mode 100644 index 00000000..2c01307f --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/Makefile.in @@ -0,0 +1,59 @@ +mydir=ccapi$(S)server +BUILDTOP=$(REL)..$(S).. +SUBDIRS=unix + +LOCALINCLUDES= -I$(srcdir)/../common + +STLIBOBJS= \ + ccs_array.o \ + ccs_cache_collection.o \ + ccs_callback.o \ + ccs_ccache.o \ + ccs_ccache_iterator.o \ + ccs_client.o \ + ccs_credentials.o \ + ccs_credentials_iterator.o \ + ccs_list.o \ + ccs_list_internal.o \ + ccs_lock.o \ + ccs_lock_state.o \ + ccs_pipe.o \ + ccs_server.o + +OBJS= \ + $(OUTPRE)ccs_array.$(OBJEXT) \ + $(OUTPRE)ccs_cache_collection.$(OBJEXT) \ + $(OUTPRE)ccs_callback.$(OBJEXT) \ + $(OUTPRE)ccs_ccache.$(OBJEXT) \ + $(OUTPRE)ccs_ccache_iterator.$(OBJEXT) \ + $(OUTPRE)ccs_client.$(OBJEXT) \ + $(OUTPRE)ccs_credentials.$(OBJEXT) \ + $(OUTPRE)ccs_credentials_iterator.$(OBJEXT) \ + $(OUTPRE)ccs_list.$(OBJEXT) \ + $(OUTPRE)ccs_list_internal.$(OBJEXT) \ + $(OUTPRE)ccs_lock.$(OBJEXT) \ + $(OUTPRE)ccs_lock_state.$(OBJEXT) \ + $(OUTPRE)ccs_pipe.$(OBJEXT) \ + $(OUTPRE)ccs_server.$(OBJEXT) + +SRCS= \ + ccs_array.c \ + ccs_cache_collection.c \ + ccs_callback.c \ + ccs_ccache.c \ + ccs_ccache_iterator.c \ + ccs_client.c \ + ccs_credentials.c \ + ccs_credentials_iterator.c \ + ccs_list.c \ + ccs_list_internal.c \ + ccs_lock.c \ + ccs_lock_state.c \ + ccs_pipe.c \ + ccs_server.c + +all-unix: all-libobjs +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/ccapi/server/ccs_array.c b/krb5-1.21.3/src/ccapi/server/ccs_array.c new file mode 100644 index 00000000..7e0874a8 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_array.c @@ -0,0 +1,309 @@ +/* ccapi/server/ccs_array.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" +#include "cci_array_internal.h" + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_client_object_release (cci_array_object_t io_client) +{ + return cci_check_error (ccs_client_release ((ccs_client_t) io_client)); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_array_new (ccs_client_array_t *out_array) +{ + return cci_array_new (out_array, ccs_client_object_release); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_array_release (ccs_client_array_t io_array) +{ + return cci_array_release (io_array); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint64 ccs_client_array_count (ccs_client_array_t in_array) +{ + return cci_array_count (in_array); +} + +/* ------------------------------------------------------------------------ */ + +ccs_client_t ccs_client_array_object_at_index (ccs_client_array_t io_array, + cc_uint64 in_position) +{ + return (ccs_client_t) cci_array_object_at_index (io_array, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_array_insert (ccs_client_array_t io_array, + ccs_client_t in_client, + cc_uint64 in_position) +{ + return cci_array_insert (io_array, (cci_array_object_t) in_client, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_array_remove (ccs_client_array_t io_array, + cc_uint64 in_position) +{ + return cci_array_remove (io_array, in_position); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_object_release (cci_array_object_t io_lock) +{ + return cci_check_error (ccs_lock_release ((ccs_lock_t) io_lock)); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_array_new (ccs_lock_array_t *out_array) +{ + return cci_array_new (out_array, ccs_lock_object_release); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_array_release (ccs_lock_array_t io_array) +{ + return cci_array_release (io_array); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint64 ccs_lock_array_count (ccs_lock_array_t in_array) +{ + return cci_array_count (in_array); +} + +/* ------------------------------------------------------------------------ */ + +ccs_lock_t ccs_lock_array_object_at_index (ccs_lock_array_t io_array, + cc_uint64 in_position) +{ + return (ccs_lock_t) cci_array_object_at_index (io_array, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_array_insert (ccs_lock_array_t io_array, + ccs_lock_t in_lock, + cc_uint64 in_position) +{ + return cci_array_insert (io_array, (cci_array_object_t) in_lock, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_array_remove (ccs_lock_array_t io_array, + cc_uint64 in_position) +{ + return cci_array_remove (io_array, in_position); +} + +/* ------------------------------------------------------------------------ */ +cc_int32 ccs_lock_array_move (ccs_lock_array_t io_array, + cc_uint64 in_position, + cc_uint64 in_new_position, + cc_uint64 *out_real_new_position) +{ + return cci_array_move (io_array, in_position, in_new_position, out_real_new_position); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_callback_object_release (cci_array_object_t io_callback) +{ + return cci_check_error (ccs_callback_release ((ccs_callback_t) io_callback)); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_array_new (ccs_callback_array_t *out_array) +{ + return cci_array_new (out_array, ccs_callback_object_release); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_array_release (ccs_callback_array_t io_array) +{ + return cci_array_release (io_array); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint64 ccs_callback_array_count (ccs_callback_array_t in_array) +{ + return cci_array_count (in_array); +} + +/* ------------------------------------------------------------------------ */ + +ccs_callback_t ccs_callback_array_object_at_index (ccs_callback_array_t io_array, + cc_uint64 in_position) +{ + return (ccs_callback_t) cci_array_object_at_index (io_array, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_array_insert (ccs_callback_array_t io_array, + ccs_callback_t in_callback, + cc_uint64 in_position) +{ + return cci_array_insert (io_array, (cci_array_object_t) in_callback, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_array_remove (ccs_callback_array_t io_array, + cc_uint64 in_position) +{ + return cci_array_remove (io_array, in_position); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callbackref_array_new (ccs_callbackref_array_t *out_array) +{ + /* Ref arrays do not own their contents; pass NULL for release function */ + return cci_array_new (out_array, NULL); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callbackref_array_release (ccs_callbackref_array_t io_array) +{ + return cci_array_release (io_array); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint64 ccs_callbackref_array_count (ccs_callbackref_array_t in_array) +{ + return cci_array_count (in_array); +} + +/* ------------------------------------------------------------------------ */ + +ccs_callback_t ccs_callbackref_array_object_at_index (ccs_callbackref_array_t io_array, + cc_uint64 in_position) +{ + return (ccs_callback_t) cci_array_object_at_index (io_array, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callbackref_array_insert (ccs_callbackref_array_t io_array, + ccs_callback_t in_callback, + cc_uint64 in_position) +{ + return cci_array_insert (io_array, (cci_array_object_t) in_callback, in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callbackref_array_remove (ccs_callbackref_array_t io_array, + cc_uint64 in_position) +{ + return cci_array_remove (io_array, in_position); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_iteratorref_array_new (ccs_iteratorref_array_t *out_array) +{ + /* Ref arrays do not own their contents; pass NULL for release function */ + return cci_array_new (out_array, NULL); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_iteratorref_array_release (ccs_iteratorref_array_t io_array) +{ + return cci_array_release (io_array); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint64 ccs_iteratorref_array_count (ccs_iteratorref_array_t in_array) +{ + return cci_array_count (in_array); +} + +/* ------------------------------------------------------------------------ */ + +ccs_generic_list_iterator_t ccs_iteratorref_array_object_at_index (ccs_iteratorref_array_t io_array, + cc_uint64 in_position) +{ + return (ccs_generic_list_iterator_t) cci_array_object_at_index (io_array, + in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_iteratorref_array_insert (ccs_iteratorref_array_t io_array, + ccs_generic_list_iterator_t in_iterator, + cc_uint64 in_position) +{ + return cci_array_insert (io_array, + (cci_array_object_t) in_iterator, + in_position); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_iteratorref_array_remove (ccs_iteratorref_array_t io_array, + cc_uint64 in_position) +{ + return cci_array_remove (io_array, in_position); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_array.h b/krb5-1.21.3/src/ccapi/server/ccs_array.h new file mode 100644 index 00000000..470812b3 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_array.h @@ -0,0 +1,132 @@ +/* ccapi/server/ccs_array.h */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_ARRAY_H +#define CCS_ARRAY_H + +#include "ccs_types.h" + +cc_int32 ccs_client_array_new (ccs_client_array_t *out_array); + +cc_int32 ccs_client_array_release (ccs_client_array_t io_array); + +cc_uint64 ccs_client_array_count (ccs_client_array_t in_array); + +ccs_client_t ccs_client_array_object_at_index (ccs_client_array_t io_array, + cc_uint64 in_position); + +cc_int32 ccs_client_array_insert (ccs_client_array_t io_array, + ccs_client_t in_client, + cc_uint64 in_position); + +cc_int32 ccs_client_array_remove (ccs_client_array_t io_array, + cc_uint64 in_position); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_lock_array_new (ccs_lock_array_t *out_array); + +cc_int32 ccs_lock_array_release (ccs_lock_array_t io_array); + +cc_uint64 ccs_lock_array_count (ccs_lock_array_t in_array); + +ccs_lock_t ccs_lock_array_object_at_index (ccs_lock_array_t io_array, + cc_uint64 in_position); + +cc_int32 ccs_lock_array_insert (ccs_lock_array_t io_array, + ccs_lock_t in_lock, + cc_uint64 in_position); + +cc_int32 ccs_lock_array_remove (ccs_lock_array_t io_array, + cc_uint64 in_position); + +cc_int32 ccs_lock_array_move (ccs_lock_array_t io_array, + cc_uint64 in_position, + cc_uint64 in_new_position, + cc_uint64 *out_real_new_position); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_callback_array_new (ccs_callback_array_t *out_array); + +cc_int32 ccs_callback_array_release (ccs_callback_array_t io_array); + +cc_uint64 ccs_callback_array_count (ccs_callback_array_t in_array); + +ccs_callback_t ccs_callback_array_object_at_index (ccs_callback_array_t io_array, + cc_uint64 in_position); + +cc_int32 ccs_callback_array_insert (ccs_callback_array_t io_array, + ccs_callback_t in_callback, + cc_uint64 in_position); + +cc_int32 ccs_callback_array_remove (ccs_callback_array_t io_array, + cc_uint64 in_position); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_callbackref_array_new (ccs_callbackref_array_t *out_array); + +cc_int32 ccs_callbackref_array_release (ccs_callbackref_array_t io_array); + +cc_uint64 ccs_callbackref_array_count (ccs_callbackref_array_t in_array); + +ccs_callback_t ccs_callbackref_array_object_at_index (ccs_callbackref_array_t io_array, + cc_uint64 in_position); + +cc_int32 ccs_callbackref_array_insert (ccs_callbackref_array_t io_array, + ccs_callback_t in_callback, + cc_uint64 in_position); + +cc_int32 ccs_callbackref_array_remove (ccs_callbackref_array_t io_array, + cc_uint64 in_position); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_iteratorref_array_new (ccs_iteratorref_array_t *out_array); + +cc_int32 ccs_iteratorref_array_release (ccs_iteratorref_array_t io_array); + +cc_uint64 ccs_iteratorref_array_count (ccs_iteratorref_array_t in_array); + +ccs_generic_list_iterator_t ccs_iteratorref_array_object_at_index (ccs_iteratorref_array_t io_array, + cc_uint64 in_position); + +cc_int32 ccs_iteratorref_array_insert (ccs_iteratorref_array_t io_array, + ccs_generic_list_iterator_t in_iterator, + cc_uint64 in_position); + +cc_int32 ccs_iteratorref_array_remove (ccs_iteratorref_array_t io_array, + cc_uint64 in_position); + +#endif /* CCS_ARRAY_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_cache_collection.c b/krb5-1.21.3/src/ccapi/server/ccs_cache_collection.c new file mode 100644 index 00000000..33300735 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_cache_collection.c @@ -0,0 +1,1109 @@ +/* ccapi/server/ccs_cache_collection.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-platform.h" /* pull in asprintf decl/defn */ +#include "ccs_common.h" +#include "ccs_os_notify.h" + +struct ccs_cache_collection_d { + cc_time_t last_changed_time; + cc_uint64 next_unique_name; + cci_identifier_t identifier; + ccs_lock_state_t lock_state; + ccs_ccache_list_t ccaches; + ccs_callback_array_t change_callbacks; +}; + +struct ccs_cache_collection_d ccs_cache_collection_initializer = { 0, 0, NULL, NULL, NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_new (ccs_cache_collection_t *out_cache_collection) +{ + cc_int32 err = ccNoError; + ccs_cache_collection_t cache_collection = NULL; + + if (!out_cache_collection) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cache_collection = malloc (sizeof (*cache_collection)); + if (cache_collection) { + *cache_collection = ccs_cache_collection_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = ccs_server_new_identifier (&cache_collection->identifier); + } + + if (!err) { + err = ccs_lock_state_new (&cache_collection->lock_state, + ccErrInvalidContext, + ccErrContextLocked, + ccErrContextUnlocked); + } + + if (!err) { + err = ccs_ccache_list_new (&cache_collection->ccaches); + } + + if (!err) { + err = ccs_callback_array_new (&cache_collection->change_callbacks); + } + + if (!err) { + err = ccs_cache_collection_changed (cache_collection); + } + + if (!err) { + *out_cache_collection = cache_collection; + cache_collection = NULL; + } + + ccs_cache_collection_release (cache_collection); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_release (ccs_cache_collection_t io_cache_collection) +{ + cc_int32 err = ccNoError; + + if (!err && io_cache_collection) { + cci_identifier_release (io_cache_collection->identifier); + ccs_lock_state_release (io_cache_collection->lock_state); + ccs_ccache_list_release (io_cache_collection->ccaches); + ccs_callback_array_release (io_cache_collection->change_callbacks); + free (io_cache_collection); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_compare_identifier (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + + if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_compare (in_cache_collection->identifier, + in_identifier, + out_equal); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_changed (ccs_cache_collection_t io_cache_collection) +{ + cc_int32 err = ccNoError; + k5_ipc_stream reply_data = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_time_t now = time (NULL); + + if (io_cache_collection->last_changed_time < now) { + io_cache_collection->last_changed_time = now; + } else { + io_cache_collection->last_changed_time++; + } + } + + if (!err) { + err = krb5int_ipc_stream_new (&reply_data); + } + + if (!err) { + err = krb5int_ipc_stream_write_time (reply_data, io_cache_collection->last_changed_time); + } + + if (!err) { + /* Loop over callbacks sending messages to them */ + cc_uint64 i; + cc_uint64 count = ccs_callback_array_count (io_cache_collection->change_callbacks); + + for (i = 0; !err && i < count; i++) { + ccs_callback_t callback = ccs_callback_array_object_at_index (io_cache_collection->change_callbacks, i); + + err = ccs_callback_reply_to_client (callback, reply_data); + + if (!err) { + cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback); + err = ccs_callback_array_remove (io_cache_collection->change_callbacks, i); + break; + } + } + } + + if (!err) { + err = ccs_os_notify_cache_collection_changed (io_cache_collection); + } + + krb5int_ipc_stream_release (reply_data); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_invalidate_change_callback (ccs_callback_owner_t io_cache_collection, + ccs_callback_t in_callback) +{ + cc_int32 err = ccNoError; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_callback ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + /* Remove callback */ + ccs_cache_collection_t cache_collection = (ccs_cache_collection_t) io_cache_collection; + cc_uint64 i; + cc_uint64 count = ccs_callback_array_count (cache_collection->change_callbacks); + + for (i = 0; !err && i < count; i++) { + ccs_callback_t callback = ccs_callback_array_object_at_index (cache_collection->change_callbacks, i); + + if (callback == in_callback) { + cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback); + err = ccs_callback_array_remove (cache_collection->change_callbacks, i); + break; + } + } + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_find_ccache_by_name (ccs_cache_collection_t in_cache_collection, + const char *in_name, + ccs_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + ccs_ccache_list_iterator_t iterator = NULL; + + if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches, + CCS_PIPE_NULL, + &iterator); + } + + while (!err) { + ccs_ccache_t ccache = NULL; + + err = ccs_ccache_list_iterator_next (iterator, &ccache); + + if (!err) { + cc_uint32 equal = 0; + + err = ccs_ccache_compare_name (ccache, in_name, &equal); + + if (!err && equal) { + *out_ccache = ccache; + break; + } + } + } + if (err == ccIteratorEnd) { err = ccErrCCacheNotFound; } + + if (iterator) { ccs_ccache_list_iterator_release (iterator); } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_find_ccache (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + ccs_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + + if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_find (in_cache_collection->ccaches, + in_identifier, out_ccache); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_collection_move_ccache (ccs_cache_collection_t io_cache_collection, + cci_identifier_t in_source_identifier, + ccs_ccache_t io_destination_ccache) +{ + cc_int32 err = ccNoError; + ccs_ccache_t source_ccache = NULL; + + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_source_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_find_ccache (io_cache_collection, + in_source_identifier, + &source_ccache); + } + + if (!err) { + err = ccs_ccache_swap_contents (source_ccache, + io_destination_ccache, + io_cache_collection); + } + + if (!err) { + err = ccs_cache_collection_destroy_ccache (io_cache_collection, + in_source_identifier); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_destroy_ccache (ccs_cache_collection_t io_cache_collection, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + ccs_ccache_t ccache = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_find_ccache (io_cache_collection, + in_identifier, + &ccache); + } + + if (!err) { + /* Notify before deletion because after deletion the ccache + * will no longer exist (and won't know about its clients) */ + err = ccs_ccache_changed (ccache, io_cache_collection); + } + + if (!err) { + err = ccs_ccache_list_remove (io_cache_collection->ccaches, + in_identifier); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_find_ccache_iterator (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + ccs_ccache_iterator_t *out_ccache_iterator) +{ + cc_int32 err = ccNoError; + + if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_find_iterator (in_cache_collection->ccaches, + in_identifier, + out_ccache_iterator); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_find_credentials_iterator (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + ccs_ccache_t *out_ccache, + ccs_credentials_iterator_t *out_credentials_iterator) +{ + cc_int32 err = ccNoError; + ccs_ccache_list_iterator_t iterator = NULL; + + if (!in_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches, + CCS_PIPE_NULL, + &iterator); + } + + while (!err) { + ccs_ccache_t ccache = NULL; + + err = ccs_ccache_list_iterator_next (iterator, &ccache); + + if (!err) { + cc_int32 terr = ccs_ccache_find_credentials_iterator (ccache, + in_identifier, + out_credentials_iterator); + if (!terr) { + *out_ccache = ccache; + break; + } + } + } + if (err == ccIteratorEnd) { err = cci_check_error (ccErrInvalidCredentialsIterator); } + + if (iterator) { ccs_ccache_list_iterator_release (iterator); } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_get_next_unique_ccache_name (ccs_cache_collection_t io_cache_collection, + char **out_name) +{ + cc_int32 err = ccNoError; + cc_uint64 count = 0; + char *name = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!out_name ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_list_count (io_cache_collection->ccaches, &count); + } + + if (!err) { + if (count > 0) { + while (!err) { + int ret = asprintf (&name, "%lld", io_cache_collection->next_unique_name++); + if (ret < 0 || !name) { err = cci_check_error (ccErrNoMem); } + + if (!err) { + ccs_ccache_t ccache = NULL; /* temporary to hold ccache pointer */ + err = ccs_cache_collection_find_ccache_by_name (io_cache_collection, + name, &ccache); + } + + if (err == ccErrCCacheNotFound) { + err = ccNoError; + break; /* found a unique one */ + } + } + } else { + name = strdup (k_cci_context_initial_ccache_name); + if (!name) { err = cci_check_error (ccErrNoMem); } + } + } + + if (!err) { + *out_name = name; + name = NULL; + } + + free (name); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_get_default_ccache (ccs_cache_collection_t in_cache_collection, + ccs_ccache_t *out_ccache) +{ + cc_int32 err = ccNoError; + cc_uint64 count = 0; + + if (!in_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_count (in_cache_collection->ccaches, &count); + } + + if (!err) { + if (count > 0) { + /* First ccache is the default */ + ccs_ccache_list_iterator_t iterator = NULL; + + err = ccs_ccache_list_new_iterator (in_cache_collection->ccaches, + CCS_PIPE_NULL, + &iterator); + + if (!err) { + err = ccs_ccache_list_iterator_next (iterator, out_ccache); + } + + ccs_ccache_list_iterator_release (iterator); + + } else { + err = cci_check_error (ccErrCCacheNotFound); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_set_default_ccache (ccs_cache_collection_t io_cache_collection, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + ccs_ccache_t old_default = NULL; + ccs_ccache_t new_default = NULL; + cc_uint32 equal = 0; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_get_default_ccache (io_cache_collection, + &old_default); + } + + if (!err) { + err = ccs_ccache_compare_identifier (old_default, in_identifier, &equal); + } + + + if (!err && !equal) { + err = ccs_ccache_list_push_front (io_cache_collection->ccaches, + in_identifier); + + if (!err) { + err = ccs_ccache_notify_default_state_changed (old_default, + io_cache_collection, + 0 /* no longer default */); + } + + if (!err) { + err = ccs_cache_collection_get_default_ccache (io_cache_collection, + &new_default); + } + + if (!err) { + err = ccs_ccache_notify_default_state_changed (new_default, + io_cache_collection, + 1 /* now default */); + } + + if (!err) { + err = ccs_cache_collection_changed (io_cache_collection); + } + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#pragma mark -- IPC Messages -- +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_sync (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (io_cache_collection->identifier, io_reply_data); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_get_change_time (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_write_time (io_reply_data, io_cache_collection->last_changed_time); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_wait_for_change (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data, + cc_uint32 *out_will_block) +{ + cc_int32 err = ccNoError; + cc_time_t last_wait_for_change_time = 0; + cc_uint32 will_block = 0; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe )) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_time (in_request_data, &last_wait_for_change_time); + } + + if (!err) { + if (last_wait_for_change_time < io_cache_collection->last_changed_time) { + err = krb5int_ipc_stream_write_time (io_reply_data, io_cache_collection->last_changed_time); + + } else { + ccs_callback_t callback = NULL; + + err = ccs_callback_new (&callback, + ccErrInvalidContext, + in_client_pipe, + in_reply_pipe, + (ccs_callback_owner_t) io_cache_collection, + ccs_cache_collection_invalidate_change_callback); + + if (!err) { + err = ccs_callback_array_insert (io_cache_collection->change_callbacks, callback, + ccs_callback_array_count (io_cache_collection->change_callbacks)); + if (!err) { callback = NULL; /* take ownership */ } + + will_block = 1; + } + + ccs_callback_release (callback); + } + } + + if (!err) { + *out_will_block = will_block; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_get_default_ccache_name (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint64 count = 0; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_list_count (io_cache_collection->ccaches, &count); + } + + if (!err) { + if (count > 0) { + ccs_ccache_t ccache = NULL; + + err = ccs_cache_collection_get_default_ccache (io_cache_collection, &ccache); + + if (!err) { + err = ccs_ccache_write_name (ccache, io_reply_data); + } + } else { + err = krb5int_ipc_stream_write_string (io_reply_data, + k_cci_context_initial_ccache_name); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_open_ccache (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + char *name = NULL; + ccs_ccache_t ccache = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_string (in_request_data, &name); + } + + if (!err) { + err = ccs_cache_collection_find_ccache_by_name (io_cache_collection, + name, &ccache); + } + + if (!err) { + err = ccs_ccache_write (ccache, io_reply_data); + } + + krb5int_ipc_stream_free_string (name); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_open_default_ccache (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_ccache_t ccache = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_get_default_ccache (io_cache_collection, + &ccache); + } + + if (!err) { + err = ccs_ccache_write (ccache, io_reply_data); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_create_ccache (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + char *name = NULL; + cc_uint32 cred_vers; + char *principal = NULL; + ccs_ccache_t ccache = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_string (in_request_data, &name); + } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (in_request_data, &cred_vers); + } + + if (!err) { + err = krb5int_ipc_stream_read_string (in_request_data, &principal); + } + + if (!err) { + cc_int32 terr = ccs_cache_collection_find_ccache_by_name (io_cache_collection, + name, + &ccache); + + if (!terr) { + err = ccs_ccache_reset (ccache, io_cache_collection, cred_vers, principal); + + } else { + err = ccs_ccache_new (&ccache, cred_vers, name, principal, + io_cache_collection->ccaches); + } + } + + if (!err) { + err = ccs_ccache_write (ccache, io_reply_data); + } + + if (!err) { + err = ccs_cache_collection_changed (io_cache_collection); + } + + krb5int_ipc_stream_free_string (name); + krb5int_ipc_stream_free_string (principal); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_create_default_ccache (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 cred_vers; + char *principal = NULL; + ccs_ccache_t ccache = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (in_request_data, &cred_vers); + } + + if (!err) { + err = krb5int_ipc_stream_read_string (in_request_data, &principal); + } + + if (!err) { + err = ccs_cache_collection_get_default_ccache (io_cache_collection, + &ccache); + + if (!err) { + err = ccs_ccache_reset (ccache, io_cache_collection, cred_vers, principal); + + } else if (err == ccErrCCacheNotFound) { + char *name = NULL; + + err = ccs_cache_collection_get_next_unique_ccache_name (io_cache_collection, + &name); + + if (!err) { + err = ccs_ccache_new (&ccache, cred_vers, name, principal, + io_cache_collection->ccaches); + } + + free (name); + } + } + + if (!err) { + err = ccs_ccache_write (ccache, io_reply_data); + } + + if (!err) { + err = ccs_cache_collection_changed (io_cache_collection); + } + + krb5int_ipc_stream_free_string (principal); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_create_new_ccache (ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 cred_vers; + char *principal = NULL; + char *name = NULL; + ccs_ccache_t ccache = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (in_request_data, &cred_vers); + } + + if (!err) { + err = krb5int_ipc_stream_read_string (in_request_data, &principal); + } + + if (!err) { + err = ccs_cache_collection_get_next_unique_ccache_name (io_cache_collection, + &name); + } + + if (!err) { + err = ccs_ccache_new (&ccache, cred_vers, name, principal, + io_cache_collection->ccaches); + } + + if (!err) { + err = ccs_ccache_write (ccache, io_reply_data); + } + + if (!err) { + err = ccs_cache_collection_changed (io_cache_collection); + } + + free (name); + krb5int_ipc_stream_free_string (principal); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_new_ccache_iterator (ccs_cache_collection_t io_cache_collection, + ccs_pipe_t in_client_pipe, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_ccache_iterator_t ccache_iterator = NULL; + + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_new_iterator (io_cache_collection->ccaches, + in_client_pipe, + &ccache_iterator); + } + + if (!err) { + err = ccs_ccache_list_iterator_write (ccache_iterator, io_reply_data); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_lock (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 lock_type; + cc_uint32 block; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (in_request_data, &lock_type); + } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (in_request_data, &block); + } + + if (!err) { + err = ccs_lock_state_add (io_cache_collection->lock_state, + in_client_pipe, in_reply_pipe, + lock_type, block, out_will_block); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_unlock (ccs_pipe_t in_client_pipe, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_lock_state_remove (io_cache_collection->lock_state, + in_client_pipe); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + + cc_int32 ccs_cache_collection_handle_message (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_cache_collection_t io_cache_collection, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream *out_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 will_block = 0; + k5_ipc_stream reply_data = NULL; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&reply_data); + } + + if (!err) { + if (in_request_name == cci_context_unused_release_msg_id) { + /* Old release message. Do nothing. */ + + } else if (in_request_name == cci_context_sync_msg_id) { + err = ccs_cache_collection_sync (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_get_change_time_msg_id) { + err = ccs_cache_collection_get_change_time (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_wait_for_change_msg_id) { + err = ccs_cache_collection_wait_for_change (in_client_pipe, in_reply_pipe, + io_cache_collection, + in_request_data, reply_data, + &will_block); + + } else if (in_request_name == cci_context_get_default_ccache_name_msg_id) { + err = ccs_cache_collection_get_default_ccache_name (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_open_ccache_msg_id) { + err = ccs_cache_collection_open_ccache (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_open_default_ccache_msg_id) { + err = ccs_cache_collection_open_default_ccache (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_create_ccache_msg_id) { + err = ccs_cache_collection_create_ccache (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_create_default_ccache_msg_id) { + err = ccs_cache_collection_create_default_ccache (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_create_new_ccache_msg_id) { + err = ccs_cache_collection_create_new_ccache (io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_context_new_ccache_iterator_msg_id) { + err = ccs_cache_collection_new_ccache_iterator (io_cache_collection, + in_client_pipe, + in_request_data, + reply_data); + + } else if (in_request_name == cci_context_lock_msg_id) { + err = ccs_cache_collection_lock (in_client_pipe, in_reply_pipe, + io_cache_collection, + in_request_data, + &will_block, reply_data); + + } else if (in_request_name == cci_context_unlock_msg_id) { + err = ccs_cache_collection_unlock (in_client_pipe, io_cache_collection, + in_request_data, reply_data); + + } else { + err = ccErrBadInternalMessage; + } + } + + if (!err) { + *out_will_block = will_block; + if (!will_block) { + *out_reply_data = reply_data; + reply_data = NULL; /* take ownership */ + } else { + *out_reply_data = NULL; + } + } + + krb5int_ipc_stream_release (reply_data); + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_cache_collection.h b/krb5-1.21.3/src/ccapi/server/ccs_cache_collection.h new file mode 100644 index 00000000..37f7633a --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_cache_collection.h @@ -0,0 +1,72 @@ +/* ccapi/server/ccs_cache_collection.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_CACHE_COLLECTION_H +#define CCS_CACHE_COLLECTION_H + +#include "ccs_types.h" + +cc_int32 ccs_cache_collection_new (ccs_cache_collection_t *out_cache_collection); + +cc_int32 ccs_cache_collection_release (ccs_cache_collection_t io_cache_collection); + +cc_int32 ccs_cache_collection_compare_identifier (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + cc_uint32 *out_equal); + +cc_int32 ccs_cache_collection_changed (ccs_cache_collection_t io_cache_collection); + +cc_int32 ccs_cache_collection_set_default_ccache (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier); + +cc_int32 ccs_cache_collection_find_ccache (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + ccs_ccache_t *out_ccache); + +cc_int32 ccs_ccache_collection_move_ccache (ccs_cache_collection_t io_cache_collection, + cci_identifier_t in_source_identifier, + ccs_ccache_t io_destination_ccache); + +cc_int32 ccs_cache_collection_destroy_ccache (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier); + +cc_int32 ccs_cache_collection_find_ccache_iterator (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + ccs_ccache_iterator_t *out_ccache_iterator); + +cc_int32 ccs_cache_collection_find_credentials_iterator (ccs_cache_collection_t in_cache_collection, + cci_identifier_t in_identifier, + ccs_ccache_t *out_ccache, + ccs_credentials_iterator_t *out_credentials_iterator); + +cc_int32 ccs_cache_collection_handle_message (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_cache_collection_t io_cache_collection, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream *out_reply_data); + +#endif /* CCS_CACHE_COLLECTION_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_callback.c b/krb5-1.21.3/src/ccapi/server/ccs_callback.c new file mode 100644 index 00000000..d758acb1 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_callback.c @@ -0,0 +1,238 @@ +/* ccapi/server/ccs_callback.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" + +struct ccs_callback_d { + cc_int32 pending; + cc_int32 invalid_object_err; + ccs_pipe_t client_pipe; + ccs_pipe_t reply_pipe; + ccs_callback_owner_t owner; /* pointer to owner */ + ccs_callback_owner_invalidate_t owner_invalidate; +}; + +struct ccs_callback_d ccs_callback_initializer = { 1, 1, CCS_PIPE_NULL, CCS_PIPE_NULL, NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_new (ccs_callback_t *out_callback, + cc_int32 in_invalid_object_err, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_callback_owner_t in_owner, + ccs_callback_owner_invalidate_t in_owner_invalidate_function) +{ + cc_int32 err = ccNoError; + ccs_callback_t callback = NULL; + ccs_client_t client = NULL; + + if (!out_callback ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + if (!in_owner ) { err = cci_check_error (ccErrBadParam); } + if (!in_owner_invalidate_function ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + callback = malloc (sizeof (*callback)); + if (callback) { + *callback = ccs_callback_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = ccs_server_client_for_pipe (in_client_pipe, &client); + } + + if (!err) { + err = ccs_pipe_copy (&callback->client_pipe, in_client_pipe); + } + + if (!err) { + err = ccs_pipe_copy (&callback->reply_pipe, in_reply_pipe); + } + + if (!err) { + callback->client_pipe = in_client_pipe; + callback->reply_pipe = in_reply_pipe; + callback->invalid_object_err = in_invalid_object_err; + callback->owner = in_owner; + callback->owner_invalidate = in_owner_invalidate_function; + + err = ccs_client_add_callback (client, callback); + } + + if (!err) { + *out_callback = callback; + callback = NULL; + } + + ccs_callback_release (callback); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_release (ccs_callback_t io_callback) +{ + cc_int32 err = ccNoError; + + if (!err && io_callback) { + ccs_client_t client = NULL; + + if (io_callback->pending) { + err = ccs_server_send_reply (io_callback->reply_pipe, + io_callback->invalid_object_err, NULL); + + io_callback->pending = 0; + } + + if (!err) { + err = ccs_server_client_for_pipe (io_callback->client_pipe, &client); + } + + if (!err && client) { + /* if client object still has a reference to us, remove it */ + err = ccs_client_remove_callback (client, io_callback); + } + + if (!err) { + ccs_pipe_release (io_callback->client_pipe); + ccs_pipe_release (io_callback->reply_pipe); + free (io_callback); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_invalidate (ccs_callback_t io_callback) +{ + cc_int32 err = ccNoError; + + if (!io_callback) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + io_callback->pending = 0; /* client is dead, don't try to talk to it */ + if (io_callback->owner_invalidate) { + err = io_callback->owner_invalidate (io_callback->owner, io_callback); + } else { + cci_debug_printf ("WARNING %s() unable to notify callback owner!", + __FUNCTION__); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_reply_to_client (ccs_callback_t io_callback, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + + if (!io_callback) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + if (io_callback->pending) { + cci_debug_printf ("%s: callback %p replying to client.", __FUNCTION__, io_callback); + + err = ccs_server_send_reply (io_callback->reply_pipe, err, in_stream); + + if (err) { + cci_debug_printf ("WARNING %s() called on a lock belonging to a dead client!", + __FUNCTION__); + } + + io_callback->pending = 0; + } else { + cci_debug_printf ("WARNING %s() called on non-pending callback!", + __FUNCTION__); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint32 ccs_callback_is_pending (ccs_callback_t in_callback, + cc_uint32 *out_pending) +{ + cc_int32 err = ccNoError; + + if (!in_callback) { err = cci_check_error (ccErrBadParam); } + if (!out_pending) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_pending = in_callback->pending; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_is_for_client_pipe (ccs_callback_t in_callback, + ccs_pipe_t in_client_pipe, + cc_uint32 *out_is_for_client_pipe) +{ + cc_int32 err = ccNoError; + + if (!in_callback ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!out_is_for_client_pipe ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_pipe_compare (in_callback->client_pipe, in_client_pipe, + out_is_for_client_pipe); + } + + return cci_check_error (err); +} + + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_callback_client_pipe (ccs_callback_t in_callback, + ccs_pipe_t *out_client_pipe) +{ + cc_int32 err = ccNoError; + + if (!in_callback ) { err = cci_check_error (ccErrBadParam); } + if (!out_client_pipe) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_client_pipe = in_callback->client_pipe; + } + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_callback.h b/krb5-1.21.3/src/ccapi/server/ccs_callback.h new file mode 100644 index 00000000..30c22280 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_callback.h @@ -0,0 +1,61 @@ +/* ccapi/server/ccs_callback.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_CALLBACK_H +#define CCS_CALLBACK_H + +#include "ccs_types.h" + +struct ccs_callback_owner_d; +typedef struct ccs_callback_owner_d *ccs_callback_owner_t; + +typedef cc_int32 (*ccs_callback_owner_invalidate_t) (ccs_callback_owner_t, ccs_callback_t); + + +cc_int32 ccs_callback_new (ccs_callback_t *out_callback, + cc_int32 in_invalid_object_err, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_callback_owner_t in_owner, + ccs_callback_owner_invalidate_t in_owner_invalidate_function); + +cc_int32 ccs_callback_release (ccs_callback_t io_callback); + +cc_int32 ccs_callback_invalidate (ccs_callback_t io_callback); + +cc_int32 ccs_callback_reply_to_client (ccs_callback_t io_callback, + k5_ipc_stream in_stream); + +cc_uint32 ccs_callback_is_pending (ccs_callback_t in_callback, + cc_uint32 *out_pending); + +cc_int32 ccs_callback_is_for_client_pipe (ccs_callback_t in_callback, + ccs_pipe_t in_client_pipe, + cc_uint32 *out_is_for_client_pipe); + +cc_int32 ccs_callback_client_pipe (ccs_callback_t in_callback, + ccs_pipe_t *out_client_pipe); + +#endif /* CCS_CALLBACK_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_ccache.c b/krb5-1.21.3/src/ccapi/server/ccs_ccache.c new file mode 100644 index 00000000..645380a7 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_ccache.c @@ -0,0 +1,1183 @@ +/* ccapi/server/ccs_ccache.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" +#include "ccs_os_notify.h" + +struct ccs_ccache_d { + cci_identifier_t identifier; + ccs_lock_state_t lock_state; + cc_uint32 creds_version; + char *name; + char *v5_principal; + cc_time_t last_default_time; + cc_time_t last_changed_time; + cc_uint32 kdc_time_offset_v5_valid; + cc_time_t kdc_time_offset_v5; + ccs_credentials_list_t credentials; + ccs_callback_array_t change_callbacks; +}; + +struct ccs_ccache_d ccs_ccache_initializer = { NULL, NULL, 0, NULL, NULL, 0, 0, 0, 0, NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_new (ccs_ccache_t *out_ccache, + cc_uint32 in_creds_version, + const char *in_name, + const char *in_principal, + ccs_ccache_list_t io_ccache_list) +{ + cc_int32 err = ccNoError; + ccs_ccache_t ccache = NULL; + + if (!out_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!in_principal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + ccache = malloc (sizeof (*ccache)); + if (ccache) { + *ccache = ccs_ccache_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = ccs_server_new_identifier (&ccache->identifier); + } + + if (!err) { + err = ccs_lock_state_new (&ccache->lock_state, + ccErrInvalidCCache, + ccErrCCacheLocked, + ccErrCCacheUnlocked); + } + + if (!err) { + ccache->name = strdup (in_name); + if (!ccache->name) { err = cci_check_error (ccErrNoMem); } + } + + if (!err) { + ccache->creds_version = in_creds_version; + + if (ccache->creds_version == cc_credentials_v5) { + ccache->v5_principal = strdup (in_principal); + if (!ccache->v5_principal) { err = cci_check_error (ccErrNoMem); } + + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + if (!err) { + err = ccs_credentials_list_new (&ccache->credentials); + } + + if (!err) { + err = ccs_callback_array_new (&ccache->change_callbacks); + } + + if (!err) { + cc_uint64 now = time (NULL); + cc_uint64 count = 0; + + err = ccs_ccache_list_count (io_ccache_list, &count); + + if (!err) { + /* first cache is default */ + ccache->last_default_time = (count == 0) ? now : 0; + cci_debug_printf ("%s ccache->last_default_time is %d.", + __FUNCTION__, ccache->last_default_time); + ccache->last_changed_time = now; + } + } + + if (!err) { + /* Add self to the list of ccaches */ + err = ccs_ccache_list_add (io_ccache_list, ccache); + } + + if (!err) { + *out_ccache = ccache; + ccache = NULL; + } + + ccs_ccache_release (ccache); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_reset (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + cc_uint32 in_creds_version, + const char *in_principal) +{ + cc_int32 err = ccNoError; + char *v5_principal = NULL; + ccs_credentials_list_t credentials = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_principal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + io_ccache->creds_version = in_creds_version; + + if (io_ccache->creds_version == cc_credentials_v5) { + v5_principal = strdup (in_principal); + if (!v5_principal) { err = cci_check_error (ccErrNoMem); } + + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + if (!err) { + err = ccs_credentials_list_new (&credentials); + } + + if (!err) { + io_ccache->kdc_time_offset_v5 = 0; + io_ccache->kdc_time_offset_v5_valid = 0; + + if (io_ccache->v5_principal) { free (io_ccache->v5_principal); } + io_ccache->v5_principal = v5_principal; + v5_principal = NULL; /* take ownership */ + + ccs_credentials_list_release (io_ccache->credentials); + io_ccache->credentials = credentials; + credentials = NULL; /* take ownership */ + + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + free (v5_principal); + ccs_credentials_list_release (credentials); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_swap_contents (ccs_ccache_t io_source_ccache, + ccs_ccache_t io_destination_ccache, + ccs_cache_collection_t io_cache_collection) +{ + cc_int32 err = ccNoError; + + if (!io_source_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_destination_ccache) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + struct ccs_ccache_d temp_ccache = *io_destination_ccache; + + /* swap everything */ + *io_destination_ccache = *io_source_ccache; + *io_source_ccache = temp_ccache; + + /* swap back the name and identifier */ + io_source_ccache->identifier = io_destination_ccache->identifier; + io_destination_ccache->identifier = temp_ccache.identifier; + + io_source_ccache->name = io_destination_ccache->name; + io_destination_ccache->name = temp_ccache.name; + } + + if (!err) { + err = ccs_ccache_changed (io_source_ccache, io_cache_collection); + } + + if (!err) { + err = ccs_ccache_changed (io_destination_ccache, io_cache_collection); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_release (ccs_ccache_t io_ccache) +{ + cc_int32 err = ccNoError; + + if (!err && io_ccache) { + cci_identifier_release (io_ccache->identifier); + ccs_lock_state_release (io_ccache->lock_state); + free (io_ccache->name); + free (io_ccache->v5_principal); + ccs_credentials_list_release (io_ccache->credentials); + ccs_callback_array_release (io_ccache->change_callbacks); + free (io_ccache); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_compare_identifier (ccs_ccache_t in_ccache, + cci_identifier_t in_identifier, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_compare (in_ccache->identifier, + in_identifier, + out_equal); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_compare_name (ccs_ccache_t in_ccache, + const char *in_name, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + + if (!in_ccache) { err = cci_check_error (ccErrBadParam); } + if (!in_name ) { err = cci_check_error (ccErrBadParam); } + if (!out_equal) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_equal = (strcmp (in_ccache->name, in_name) == 0); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_changed (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection) +{ + cc_int32 err = ccNoError; + k5_ipc_stream reply_data = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_time_t now = time (NULL); + + if (io_ccache->last_changed_time < now) { + io_ccache->last_changed_time = now; + } else { + io_ccache->last_changed_time++; + } + } + + if (!err) { + err = ccs_cache_collection_changed (io_cache_collection); + } + + if (!err) { + err = krb5int_ipc_stream_new (&reply_data); + } + + if (!err) { + err = krb5int_ipc_stream_write_time (reply_data, io_ccache->last_changed_time); + } + + if (!err) { + /* Loop over callbacks sending messages to them */ + cc_uint64 i; + cc_uint64 count = ccs_callback_array_count (io_ccache->change_callbacks); + + for (i = 0; !err && i < count; i++) { + ccs_callback_t callback = ccs_callback_array_object_at_index (io_ccache->change_callbacks, i); + + err = ccs_callback_reply_to_client (callback, reply_data); + + if (!err) { + cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback); + err = ccs_callback_array_remove (io_ccache->change_callbacks, i); + break; + } + } + } + + if (!err) { + err = ccs_os_notify_ccache_changed (io_cache_collection, + io_ccache->name); + } + + krb5int_ipc_stream_release (reply_data); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_invalidate_change_callback (ccs_callback_owner_t io_ccache, + ccs_callback_t in_callback) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_callback) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + /* Remove callback */ + ccs_ccache_t ccache = (ccs_ccache_t) io_ccache; + cc_uint64 i; + cc_uint64 count = ccs_callback_array_count (ccache->change_callbacks); + + for (i = 0; !err && i < count; i++) { + ccs_callback_t callback = ccs_callback_array_object_at_index (ccache->change_callbacks, i); + + if (callback == in_callback) { + cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback); + err = ccs_callback_array_remove (ccache->change_callbacks, i); + break; + } + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_notify_default_state_changed (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + cc_uint32 in_new_default_state) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + + if (!err && in_new_default_state) { + cc_time_t now = time (NULL); + + if (io_ccache->last_default_time < now) { + io_ccache->last_default_time = now; + } else { + io_ccache->last_default_time++; + } + } + + if (!err) { + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_find_credentials_iterator (ccs_ccache_t in_ccache, + cci_identifier_t in_identifier, + ccs_credentials_iterator_t *out_credentials_iterator) +{ + cc_int32 err = ccNoError; + + if (!in_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_credentials_list_find_iterator (in_ccache->credentials, + in_identifier, + out_credentials_iterator); + } + + // Don't report ccErrInvalidCredentials to the log file. Non-fatal. + return (err == ccErrInvalidCredentials) ? err : cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_write (ccs_ccache_t in_ccache, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + + if (!in_ccache) { err = cci_check_error (ccErrBadParam); } + if (!io_stream) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (in_ccache->identifier, io_stream); + } + + return cci_check_error (err); +} + + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_write_name (ccs_ccache_t in_ccache, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + + if (!in_ccache) { err = cci_check_error (ccErrBadParam); } + if (!io_stream) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_write_string (io_stream, in_ccache->name); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#pragma mark -- IPC Messages -- +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_destroy (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_destroy_ccache (io_cache_collection, + io_ccache->identifier); + } + + if (!err) { + /* ccache has been destroyed so just mark the cache collection */ + err = ccs_cache_collection_changed (io_cache_collection); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_set_default (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_cache_collection_set_default_ccache (io_cache_collection, + io_ccache->identifier); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_get_credentials_version (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_write_uint32 (io_reply_data, io_ccache->creds_version); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_get_name (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_write_string (io_reply_data, io_ccache->name); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_get_principal (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 version = 0; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (in_request_data, &version); + } + + if (!err) { + if (version == cc_credentials_v5) { + err = krb5int_ipc_stream_write_string (io_reply_data, io_ccache->v5_principal); + + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_set_principal (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 version = 0; + char *principal = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (in_request_data, &version); + } + + if (!err) { + err = krb5int_ipc_stream_read_string (in_request_data, &principal); + } + + if (!err) { + /* reset KDC time offsets because they are per-KDC */ + if (version == cc_credentials_v5) { + io_ccache->kdc_time_offset_v5 = 0; + io_ccache->kdc_time_offset_v5_valid = 0; + + if (io_ccache->v5_principal) { free (io_ccache->v5_principal); } + io_ccache->v5_principal = principal; + principal = NULL; /* take ownership */ + + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + if (!err) { + io_ccache->creds_version |= version; + + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + krb5int_ipc_stream_free_string (principal); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_store_credentials (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_credentials_t credentials = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_credentials_new (&credentials, in_request_data, + io_ccache->creds_version, + io_ccache->credentials); + } + + if (!err) { + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_remove_credentials (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cci_identifier_t credentials_identifier = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_read (&credentials_identifier, in_request_data); + } + + if (!err) { + err = ccs_credentials_list_remove (io_ccache->credentials, credentials_identifier); + } + + if (!err) { + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + cci_identifier_release (credentials_identifier); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_new_credentials_iterator (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + ccs_pipe_t in_client_pipe, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_credentials_iterator_t credentials_iterator = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_credentials_list_new_iterator (io_ccache->credentials, + in_client_pipe, + &credentials_iterator); + } + + if (!err) { + err = ccs_credentials_list_iterator_write (credentials_iterator, io_reply_data); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_move (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cci_identifier_t source_identifier = NULL; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + /* Note: message is sent as the destination ccache to avoid */ + /* extra work on the server when deleting it the source ccache. */ + err = cci_identifier_read (&source_identifier, in_request_data); + } + + if (!err) { + err = ccs_ccache_collection_move_ccache (io_cache_collection, + source_identifier, + io_ccache); + } + + if (!err) { + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + cci_identifier_release (source_identifier); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_lock (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 lock_type; + cc_uint32 block; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (in_request_data, &lock_type); + } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (in_request_data, &block); + } + + if (!err) { + err = ccs_lock_state_add (io_ccache->lock_state, + in_client_pipe, in_reply_pipe, + lock_type, block, out_will_block); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_unlock (ccs_pipe_t in_client_pipe, + ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_lock_state_remove (io_ccache->lock_state, in_client_pipe); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_get_last_default_time (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err && io_ccache->last_default_time == 0) { + err = cci_check_error (ccErrNeverDefault); + } + + if (!err) { + err = krb5int_ipc_stream_write_time (io_reply_data, io_ccache->last_default_time); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_get_change_time (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_write_time (io_reply_data, io_ccache->last_changed_time); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_wait_for_change (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data, + cc_uint32 *out_will_block) +{ + cc_int32 err = ccNoError; + cc_time_t last_wait_for_change_time = 0; + cc_uint32 will_block = 0; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe )) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_time (in_request_data, &last_wait_for_change_time); + } + + if (!err) { + if (last_wait_for_change_time < io_ccache->last_changed_time) { + cci_debug_printf ("%s returning immediately", __FUNCTION__); + err = krb5int_ipc_stream_write_time (io_reply_data, io_ccache->last_changed_time); + + } else { + ccs_callback_t callback = NULL; + + err = ccs_callback_new (&callback, + ccErrInvalidCCache, + in_client_pipe, + in_reply_pipe, + (ccs_callback_owner_t) io_ccache, + ccs_ccache_invalidate_change_callback); + + if (!err) { + err = ccs_callback_array_insert (io_ccache->change_callbacks, callback, + ccs_callback_array_count (io_ccache->change_callbacks)); + if (!err) { callback = NULL; /* take ownership */ } + + cci_debug_printf ("%s blocking", __FUNCTION__); + will_block = 1; + } + + ccs_callback_release (callback); + } + } + + if (!err) { + *out_will_block = will_block; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_get_kdc_time_offset (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 cred_vers = 0; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (in_request_data, &cred_vers); + } + + if (!err) { + if (cred_vers == cc_credentials_v5) { + if (io_ccache->kdc_time_offset_v5_valid) { + err = krb5int_ipc_stream_write_time (io_reply_data, io_ccache->kdc_time_offset_v5); + } else { + err = cci_check_error (ccErrTimeOffsetNotSet); + } + + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_set_kdc_time_offset (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 cred_vers = 0; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (in_request_data, &cred_vers); + } + + if (!err) { + if (cred_vers == cc_credentials_v5) { + err = krb5int_ipc_stream_read_time (in_request_data, &io_ccache->kdc_time_offset_v5); + + if (!err) { + io_ccache->kdc_time_offset_v5_valid = 1; + } + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + if (!err) { + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_clear_kdc_time_offset (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 cred_vers = 0; + + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_read_uint32 (in_request_data, &cred_vers); + } + + if (!err) { + if (cred_vers == cc_credentials_v5) { + io_ccache->kdc_time_offset_v5 = 0; + io_ccache->kdc_time_offset_v5_valid = 0; + + } else { + err = cci_check_error (ccErrBadCredentialsVersion); + } + } + + if (!err) { + err = ccs_ccache_changed (io_ccache, io_cache_collection); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_handle_message (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream *out_reply_data) +{ + cc_int32 err = ccNoError; + cc_uint32 will_block = 0; + k5_ipc_stream reply_data = NULL; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&reply_data); + } + + if (!err) { + if (in_request_name == cci_ccache_destroy_msg_id) { + err = ccs_ccache_destroy (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_set_default_msg_id) { + err = ccs_ccache_set_default (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_get_credentials_version_msg_id) { + err = ccs_ccache_get_credentials_version (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_get_name_msg_id) { + err = ccs_ccache_get_name (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_get_principal_msg_id) { + err = ccs_ccache_get_principal (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_set_principal_msg_id) { + err = ccs_ccache_set_principal (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_store_credentials_msg_id) { + err = ccs_ccache_store_credentials (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_remove_credentials_msg_id) { + err = ccs_ccache_remove_credentials (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_new_credentials_iterator_msg_id) { + err = ccs_ccache_new_credentials_iterator (io_ccache, + io_cache_collection, + in_client_pipe, + in_request_data, + reply_data); + + } else if (in_request_name == cci_ccache_move_msg_id) { + err = ccs_ccache_move (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_lock_msg_id) { + err = ccs_ccache_lock (in_client_pipe, in_reply_pipe, + io_ccache, io_cache_collection, + in_request_data, + &will_block, reply_data); + + } else if (in_request_name == cci_ccache_unlock_msg_id) { + err = ccs_ccache_unlock (in_client_pipe, + io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_get_last_default_time_msg_id) { + err = ccs_ccache_get_last_default_time (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_get_change_time_msg_id) { + err = ccs_ccache_get_change_time (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_wait_for_change_msg_id) { + err = ccs_ccache_wait_for_change (in_client_pipe, in_reply_pipe, + io_ccache, io_cache_collection, + in_request_data, reply_data, + &will_block); + + } else if (in_request_name == cci_ccache_get_kdc_time_offset_msg_id) { + err = ccs_ccache_get_kdc_time_offset (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_set_kdc_time_offset_msg_id) { + err = ccs_ccache_set_kdc_time_offset (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else if (in_request_name == cci_ccache_clear_kdc_time_offset_msg_id) { + err = ccs_ccache_clear_kdc_time_offset (io_ccache, io_cache_collection, + in_request_data, reply_data); + + } else { + err = ccErrBadInternalMessage; + } + } + + if (!err) { + *out_will_block = will_block; + if (!will_block) { + *out_reply_data = reply_data; + reply_data = NULL; /* take ownership */ + } else { + *out_reply_data = NULL; + } + } + + krb5int_ipc_stream_release (reply_data); + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_ccache.h b/krb5-1.21.3/src/ccapi/server/ccs_ccache.h new file mode 100644 index 00000000..8dab0651 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_ccache.h @@ -0,0 +1,82 @@ +/* ccapi/server/ccs_ccache.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_CCACHE_H +#define CCS_CCACHE_H + +#include "ccs_types.h" + +cc_int32 ccs_ccache_new (ccs_ccache_t *out_ccache, + cc_uint32 in_cred_vers, + const char *in_name, + const char *in_principal, + ccs_ccache_list_t io_ccache_list); + +cc_int32 ccs_ccache_reset (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + cc_uint32 in_cred_vers, + const char *in_principal); + +cc_int32 ccs_ccache_swap_contents (ccs_ccache_t io_source_ccache, + ccs_ccache_t io_destination_ccache, + ccs_cache_collection_t io_cache_collection); + +cc_int32 ccs_ccache_release (ccs_ccache_t io_ccache); + +cc_int32 ccs_ccache_changed (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection); + +cc_int32 ccs_ccache_compare_identifier (ccs_ccache_t in_ccache, + cci_identifier_t in_identifier, + cc_uint32 *out_equal); + +cc_int32 ccs_ccache_compare_name (ccs_ccache_t in_ccache, + const char *in_name, + cc_uint32 *out_equal); + +cc_int32 ccs_ccache_notify_default_state_changed (ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + cc_uint32 in_new_default_state); + +cc_int32 ccs_ccache_find_credentials_iterator (ccs_ccache_t in_ccache, + cci_identifier_t in_identifier, + ccs_credentials_iterator_t *out_credentials_iterator); + +cc_int32 ccs_ccache_write (ccs_ccache_t in_ccache, + k5_ipc_stream io_stream); + +cc_int32 ccs_ccache_write_name (ccs_ccache_t in_ccache, + k5_ipc_stream io_stream); + +cc_int32 ccs_ccache_handle_message (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_ccache_t io_ccache, + ccs_cache_collection_t io_cache_collection, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream *out_reply_data); + +#endif /* CCS_CCACHE_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_ccache_iterator.c b/krb5-1.21.3/src/ccapi/server/ccs_ccache_iterator.c new file mode 100644 index 00000000..172e68a8 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_ccache_iterator.c @@ -0,0 +1,156 @@ +/* ccapi/server/ccs_ccache_iterator.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_iterator_release (ccs_ccache_iterator_t io_ccache_iterator, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_ccache_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_iterator_release (io_ccache_iterator); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_iterator_next (ccs_ccache_iterator_t io_ccache_iterator, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_ccache_t ccache = NULL; + + if (!io_ccache_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_iterator_next (io_ccache_iterator, &ccache); + } + + if (!err) { + err = ccs_ccache_write (ccache, io_reply_data); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_iterator_clone (ccs_ccache_iterator_t io_ccache_iterator, + ccs_cache_collection_t io_cache_collection, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_ccache_iterator_t ccache_iterator = NULL; + + if (!io_ccache_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!io_cache_collection) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_ccache_list_iterator_clone (io_ccache_iterator, + &ccache_iterator); + } + + if (!err) { + err = ccs_ccache_list_iterator_write (ccache_iterator, io_reply_data); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + + cc_int32 ccs_ccache_iterator_handle_message (ccs_ccache_iterator_t io_ccache_iterator, + ccs_cache_collection_t io_cache_collection, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data) +{ + cc_int32 err = ccNoError; + k5_ipc_stream reply_data = NULL; + + if (!in_request_data) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&reply_data); + } + + if (!err) { + if (in_request_name == cci_ccache_iterator_release_msg_id) { + err = ccs_ccache_iterator_release (io_ccache_iterator, + io_cache_collection, + in_request_data, + reply_data); + + } else if (in_request_name == cci_ccache_iterator_next_msg_id) { + err = ccs_ccache_iterator_next (io_ccache_iterator, + io_cache_collection, + in_request_data, + reply_data); + + } else if (in_request_name == cci_ccache_iterator_clone_msg_id) { + err = ccs_ccache_iterator_clone (io_ccache_iterator, + io_cache_collection, + in_request_data, + reply_data); + + } else { + err = ccErrBadInternalMessage; + } + } + + if (!err) { + *out_reply_data = reply_data; + reply_data = NULL; /* take ownership */ + } + + krb5int_ipc_stream_release (reply_data); + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_ccache_iterator.h b/krb5-1.21.3/src/ccapi/server/ccs_ccache_iterator.h new file mode 100644 index 00000000..96bf929d --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_ccache_iterator.h @@ -0,0 +1,37 @@ +/* ccapi/server/ccs_ccache_iterator.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_CCACHE_ITERATOR_H +#define CCS_CCACHE_ITERATOR_H + +#include "ccs_types.h" + + cc_int32 ccs_ccache_iterator_handle_message (ccs_ccache_iterator_t io_ccache_iterator, + ccs_cache_collection_t io_cache_collection, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data); + +#endif /* CCS_CCACHE_ITERATOR_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_client.c b/krb5-1.21.3/src/ccapi/server/ccs_client.c new file mode 100644 index 00000000..a7b0ad0b --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_client.c @@ -0,0 +1,236 @@ +/* ccapi/server/ccs_client.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" + +struct ccs_client_d { + ccs_pipe_t client_pipe; + + /* The following arrays do not own their contents */ + ccs_callbackref_array_t callbacks; + ccs_iteratorref_array_t iterators; +}; + +struct ccs_client_d ccs_client_initializer = { CCS_PIPE_NULL, NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_new (ccs_client_t *out_client, + ccs_pipe_t in_client_pipe) +{ + cc_int32 err = ccNoError; + ccs_client_t client = NULL; + + if (!out_client ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + client = malloc (sizeof (*client)); + if (client) { + *client = ccs_client_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = ccs_callbackref_array_new (&client->callbacks); + } + + if (!err) { + err = ccs_iteratorref_array_new (&client->iterators); + } + + if (!err) { + err = ccs_pipe_copy (&client->client_pipe, in_client_pipe); + } + + if (!err) { + *out_client = client; + client = NULL; + } + + ccs_client_release (client); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_release (ccs_client_t io_client) +{ + cc_int32 err = ccNoError; + + if (!err && io_client) { + cc_uint64 i; + cc_uint64 callback_count = ccs_callbackref_array_count (io_client->callbacks); + cc_uint64 iterator_count = ccs_iteratorref_array_count (io_client->iterators); + + for (i = 0; !err && i < callback_count; i++) { + ccs_callback_t callback = ccs_callbackref_array_object_at_index (io_client->callbacks, i); + + cci_debug_printf ("%s: Invalidating callback reference %p.", + __FUNCTION__, callback); + ccs_callback_invalidate (callback); + } + + for (i = 0; !err && i < iterator_count; i++) { + ccs_generic_list_iterator_t iterator = ccs_iteratorref_array_object_at_index (io_client->iterators, i); + + cci_debug_printf ("%s: Invalidating iterator reference %p.", + __FUNCTION__, iterator); + ccs_generic_list_iterator_invalidate (iterator); + } + + ccs_callbackref_array_release (io_client->callbacks); + ccs_iteratorref_array_release (io_client->iterators); + ccs_pipe_release (io_client->client_pipe); + free (io_client); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_add_callback (ccs_client_t io_client, + ccs_callback_t in_callback) +{ + cc_int32 err = ccNoError; + + if (!io_client ) { err = cci_check_error (ccErrBadParam); } + if (!in_callback) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_callbackref_array_insert (io_client->callbacks, in_callback, + ccs_callbackref_array_count (io_client->callbacks)); + } + + return cci_check_error (err); +} + + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_remove_callback (ccs_client_t io_client, + ccs_callback_t in_callback) +{ + cc_int32 err = ccNoError; + cc_uint32 found_callback = 0; + + if (!io_client) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_uint64 i; + cc_uint64 lock_count = ccs_callbackref_array_count (io_client->callbacks); + + for (i = 0; !err && i < lock_count; i++) { + ccs_callback_t callback = ccs_callbackref_array_object_at_index (io_client->callbacks, i); + + if (callback == in_callback) { + cci_debug_printf ("%s: Removing callback reference %p.", __FUNCTION__, callback); + found_callback = 1; + err = ccs_callbackref_array_remove (io_client->callbacks, i); + break; + } + } + } + + if (!err && !found_callback) { + cci_debug_printf ("%s: WARNING! callback not found.", __FUNCTION__); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_add_iterator (ccs_client_t io_client, + ccs_generic_list_iterator_t in_iterator) +{ + cc_int32 err = ccNoError; + + if (!io_client ) { err = cci_check_error (ccErrBadParam); } + if (!in_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_iteratorref_array_insert (io_client->iterators, in_iterator, + ccs_iteratorref_array_count (io_client->iterators)); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_remove_iterator (ccs_client_t io_client, + ccs_generic_list_iterator_t in_iterator) +{ + cc_int32 err = ccNoError; + cc_uint32 found_iterator = 0; + + if (!io_client) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_uint64 i; + cc_uint64 lock_count = ccs_iteratorref_array_count (io_client->iterators); + + for (i = 0; !err && i < lock_count; i++) { + ccs_generic_list_iterator_t iterator = ccs_iteratorref_array_object_at_index (io_client->iterators, i); + + if (iterator == in_iterator) { + cci_debug_printf ("%s: Removing iterator reference %p.", __FUNCTION__, iterator); + found_iterator = 1; + err = ccs_iteratorref_array_remove (io_client->iterators, i); + break; + } + } + } + + if (!err && !found_iterator) { + cci_debug_printf ("%s: WARNING! iterator not found.", __FUNCTION__); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_client_uses_pipe (ccs_client_t in_client, + ccs_pipe_t in_pipe, + cc_uint32 *out_uses_pipe) +{ + cc_int32 err = ccNoError; + + if (!in_client ) { err = cci_check_error (ccErrBadParam); } + if (!in_pipe ) { err = cci_check_error (ccErrBadParam); } + if (!out_uses_pipe) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_pipe_compare (in_client->client_pipe, in_pipe, out_uses_pipe); + } + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_client.h b/krb5-1.21.3/src/ccapi/server/ccs_client.h new file mode 100644 index 00000000..b6070daa --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_client.h @@ -0,0 +1,52 @@ +/* ccapi/server/ccs_client.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_CLIENT_H +#define CCS_CLIENT_H + +#include "ccs_types.h" + +cc_int32 ccs_client_new (ccs_client_t *out_client, + ccs_pipe_t in_client_pipe); + +cc_int32 ccs_client_release (ccs_client_t io_client); + +cc_int32 ccs_client_add_callback (ccs_client_t io_client, + ccs_callback_t in_lock); + +cc_int32 ccs_client_remove_callback (ccs_client_t io_client, + ccs_callback_t in_lock); + +cc_int32 ccs_client_add_iterator (ccs_client_t io_client, + ccs_generic_list_iterator_t in_iterator); + +cc_int32 ccs_client_remove_iterator (ccs_client_t io_client, + ccs_generic_list_iterator_t in_iterator); + +cc_int32 ccs_client_uses_pipe (ccs_client_t in_client, + ccs_pipe_t in_pipe, + cc_uint32 *out_uses_pipe); + +#endif /* CCS_CLIENT_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_common.h b/krb5-1.21.3/src/ccapi/server/ccs_common.h new file mode 100644 index 00000000..eafecd83 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_common.h @@ -0,0 +1,47 @@ +/* ccapi/server/ccs_common.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_COMMON_H +#define CCS_COMMON_H + +#include "cci_common.h" + +#include + +#include "ccs_array.h" +#include "ccs_list.h" +#include "ccs_cache_collection.h" +#include "ccs_ccache_iterator.h" +#include "ccs_ccache.h" +#include "ccs_credentials_iterator.h" +#include "ccs_credentials.h" +#include "ccs_lock.h" +#include "ccs_lock_state.h" +#include "ccs_pipe.h" +#include "ccs_client.h" +#include "ccs_callback.h" +#include "ccs_server.h" + +#endif /* CCS_COMMON_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_credentials.c b/krb5-1.21.3/src/ccapi/server/ccs_credentials.c new file mode 100644 index 00000000..2c68e0f9 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_credentials.c @@ -0,0 +1,139 @@ +/* ccapi/server/ccs_credentials.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" + +struct ccs_credentials_d { + cc_credentials_union *cred_union; + cci_identifier_t identifier; +}; + +struct ccs_credentials_d ccs_credentials_initializer = { NULL, NULL }; + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_new (ccs_credentials_t *out_credentials, + k5_ipc_stream in_stream, + cc_uint32 in_ccache_version, + ccs_credentials_list_t io_credentials_list) +{ + cc_int32 err = ccNoError; + ccs_credentials_t credentials = NULL; + + if (!out_credentials) { err = cci_check_error (ccErrBadParam); } + if (!in_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + credentials = malloc (sizeof (*credentials)); + if (credentials) { + *credentials = ccs_credentials_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = cci_credentials_union_read (&credentials->cred_union, in_stream); + } + + if (!err && !(credentials->cred_union->version & in_ccache_version)) { + /* ccache does not have a principal set for this credentials version */ + err = cci_check_error (ccErrBadCredentialsVersion); + } + + if (!err) { + err = ccs_server_new_identifier (&credentials->identifier); + } + + if (!err) { + err = ccs_credentials_list_add (io_credentials_list, credentials); + } + + if (!err) { + *out_credentials = credentials; + credentials = NULL; + } + + ccs_credentials_release (credentials); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_release (ccs_credentials_t io_credentials) +{ + cc_int32 err = ccNoError; + + if (!err && io_credentials) { + cci_credentials_union_release (io_credentials->cred_union); + cci_identifier_release (io_credentials->identifier); + free (io_credentials); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_write (ccs_credentials_t in_credentials, + k5_ipc_stream io_stream) +{ + cc_int32 err = ccNoError; + + if (!in_credentials) { err = cci_check_error (ccErrBadParam); } + if (!io_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (in_credentials->identifier, io_stream); + } + + if (!err) { + err = cci_credentials_union_write (in_credentials->cred_union, io_stream); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_compare_identifier (ccs_credentials_t in_credentials, + cci_identifier_t in_identifier, + cc_uint32 *out_equal) +{ + cc_int32 err = ccNoError; + + if (!in_credentials) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_equal ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_compare (in_credentials->identifier, + in_identifier, + out_equal); + } + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_credentials.h b/krb5-1.21.3/src/ccapi/server/ccs_credentials.h new file mode 100644 index 00000000..5f096b86 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_credentials.h @@ -0,0 +1,46 @@ +/* ccapi/server/ccs_credentials.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_CREDENTIALS_H +#define CCS_CREDENTIALS_H + +#include "ccs_types.h" + + +cc_int32 ccs_credentials_new (ccs_credentials_t *out_credentials, + k5_ipc_stream in_stream, + cc_uint32 in_ccache_version, + ccs_credentials_list_t io_credentials_list); + +cc_int32 ccs_credentials_release (ccs_credentials_t io_credentials); + +cc_int32 ccs_credentials_write (ccs_credentials_t in_credentials, + k5_ipc_stream io_stream); + +cc_int32 ccs_credentials_compare_identifier (ccs_credentials_t in_credentials, + cci_identifier_t in_identifier, + cc_uint32 *out_equal); + +#endif /* CCS_CREDENTIALS_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_credentials_iterator.c b/krb5-1.21.3/src/ccapi/server/ccs_credentials_iterator.c new file mode 100644 index 00000000..df18041c --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_credentials_iterator.c @@ -0,0 +1,158 @@ +/* ccapi/server/ccs_credentials_iterator.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_credentials_iterator_release (ccs_credentials_iterator_t io_credentials_iterator, + ccs_ccache_t io_ccache, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + + if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_credentials_list_iterator_release (io_credentials_iterator); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_credentials_iterator_next (ccs_credentials_iterator_t io_credentials_iterator, + ccs_ccache_t io_ccache, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_credentials_t credentials = NULL; + + if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_credentials_list_iterator_next (io_credentials_iterator, + &credentials); + } + + if (!err) { + err = ccs_credentials_write (credentials, io_reply_data); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_credentials_iterator_clone (ccs_credentials_iterator_t io_credentials_iterator, + ccs_ccache_t io_ccache, + k5_ipc_stream in_request_data, + k5_ipc_stream io_reply_data) +{ + cc_int32 err = ccNoError; + ccs_credentials_iterator_t credentials_iterator = NULL; + + if (!io_credentials_iterator) { err = cci_check_error (ccErrBadParam); } + if (!io_ccache ) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!io_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_credentials_list_iterator_clone (io_credentials_iterator, + &credentials_iterator); + } + + if (!err) { + err = ccs_credentials_list_iterator_write (credentials_iterator, + io_reply_data); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + + cc_int32 ccs_credentials_iterator_handle_message (ccs_credentials_iterator_t io_credentials_iterator, + ccs_ccache_t io_ccache, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data) +{ + cc_int32 err = ccNoError; + k5_ipc_stream reply_data = NULL; + + if (!in_request_data) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = krb5int_ipc_stream_new (&reply_data); + } + + if (!err) { + if (in_request_name == cci_credentials_iterator_release_msg_id) { + err = ccs_credentials_iterator_release (io_credentials_iterator, + io_ccache, + in_request_data, + reply_data); + + } else if (in_request_name == cci_credentials_iterator_next_msg_id) { + err = ccs_credentials_iterator_next (io_credentials_iterator, + io_ccache, + in_request_data, + reply_data); + + } else if (in_request_name == cci_credentials_iterator_clone_msg_id) { + err = ccs_credentials_iterator_clone (io_credentials_iterator, + io_ccache, + in_request_data, + reply_data); + + } else { + err = ccErrBadInternalMessage; + } + } + + if (!err) { + *out_reply_data = reply_data; + reply_data = NULL; /* take ownership */ + } + + krb5int_ipc_stream_release (reply_data); + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_credentials_iterator.h b/krb5-1.21.3/src/ccapi/server/ccs_credentials_iterator.h new file mode 100644 index 00000000..fc81a82b --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_credentials_iterator.h @@ -0,0 +1,37 @@ +/* ccapi/server/ccs_credentials_iterator.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_CREDENTIALS_ITERATOR_H +#define CCS_CREDENTIALS_ITERATOR_H + +#include "ccs_types.h" + + cc_int32 ccs_credentials_iterator_handle_message (ccs_credentials_iterator_t io_credentials_iterator, + ccs_ccache_t io_ccache, + enum cci_msg_id_t in_request_name, + k5_ipc_stream in_request_data, + k5_ipc_stream *out_reply_data); + +#endif /* CCS_CREDENTIALS_ITERATOR_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_list.c b/krb5-1.21.3/src/ccapi/server/ccs_list.c new file mode 100644 index 00000000..ef9a1906 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_list.c @@ -0,0 +1,361 @@ +/* ccapi/server/ccs_list.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" +#include "ccs_list_internal.h" + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_list_object_release (ccs_list_object_t io_object) +{ + return cci_check_error (ccs_cache_collection_release ((ccs_cache_collection_t) io_object)); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_cache_collection_list_object_compare_identifier (ccs_list_object_t in_cache_collection, + cci_identifier_t in_identifier, + cc_uint32 *out_equal) +{ + return ccs_cache_collection_compare_identifier ((ccs_cache_collection_t) in_cache_collection, + in_identifier, + out_equal); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_list_new (ccs_cache_collection_list_t *out_list) +{ + return ccs_list_new (out_list, + ccErrInvalidContext, + ccErrInvalidContext, + ccs_cache_collection_list_object_compare_identifier, + ccs_cache_collection_list_object_release); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_list_count (ccs_cache_collection_list_t in_list, + cc_uint64 *out_count) +{ + return ccs_list_count (in_list, out_count); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_list_find (ccs_cache_collection_list_t in_list, + cci_identifier_t in_identifier, + ccs_cache_collection_t *out_cache_collection) +{ + return ccs_list_find (in_list, in_identifier, (ccs_list_object_t *) out_cache_collection); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_list_add (ccs_cache_collection_list_t io_list, + ccs_cache_collection_t in_cache_collection) +{ + return ccs_list_add (io_list, (ccs_list_object_t) in_cache_collection); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_list_remove (ccs_cache_collection_list_t io_list, + cci_identifier_t in_identifier) +{ + return ccs_list_remove (io_list, in_identifier); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_cache_collection_list_release (ccs_cache_collection_list_t io_list) +{ + return ccs_list_release (io_list); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_list_object_release (ccs_list_object_t io_ccache) +{ + return cci_check_error (ccs_ccache_release ((ccs_ccache_t) io_ccache)); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_ccache_list_object_compare_identifier (ccs_list_object_t in_ccache, + cci_identifier_t in_identifier, + cc_uint32 *out_equal) +{ + return ccs_ccache_compare_identifier ((ccs_ccache_t) in_ccache, + in_identifier, + out_equal); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_new (ccs_ccache_list_t *out_list) +{ + return ccs_list_new (out_list, + ccErrInvalidCCache, + ccErrInvalidCCacheIterator, + ccs_ccache_list_object_compare_identifier, + ccs_ccache_list_object_release); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_new_iterator (ccs_ccache_list_t in_list, + ccs_pipe_t in_client_pipe, + ccs_ccache_list_iterator_t *out_list_iterator) +{ + return ccs_list_new_iterator (in_list, in_client_pipe, out_list_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_count (ccs_ccache_list_t in_list, + cc_uint64 *out_count) +{ + return ccs_list_count (in_list, out_count); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_find (ccs_ccache_list_t in_list, + cci_identifier_t in_identifier, + ccs_ccache_t *out_ccache) +{ + return ccs_list_find (in_list, in_identifier, (ccs_list_object_t *) out_ccache); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_find_iterator (ccs_ccache_list_t in_list, + cci_identifier_t in_identifier, + ccs_ccache_list_iterator_t *out_list_iterator) +{ + return ccs_list_find_iterator (in_list, in_identifier, + (ccs_list_iterator_t *) out_list_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_add (ccs_ccache_list_t io_list, + ccs_ccache_t in_ccache) +{ + return ccs_list_add (io_list, (ccs_list_object_t) in_ccache); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_remove (ccs_ccache_list_t io_list, + cci_identifier_t in_identifier) +{ + return ccs_list_remove (io_list, in_identifier); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_push_front (ccs_ccache_list_t io_list, + cci_identifier_t in_identifier) +{ + return ccs_list_push_front (io_list, in_identifier); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_release (ccs_ccache_list_t io_list) +{ + return ccs_list_release (io_list); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_iterator_write (ccs_ccache_list_iterator_t in_list_iterator, + k5_ipc_stream in_stream) +{ + return ccs_list_iterator_write (in_list_iterator, in_stream); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_iterator_clone (ccs_ccache_list_iterator_t in_list_iterator, + ccs_ccache_list_iterator_t *out_list_iterator) +{ + return ccs_list_iterator_clone (in_list_iterator, out_list_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_iterator_next (ccs_ccache_list_iterator_t io_list_iterator, + ccs_ccache_t *out_ccache) +{ + return ccs_list_iterator_next (io_list_iterator, (ccs_list_object_t *) out_ccache); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_ccache_list_iterator_release (ccs_ccache_list_iterator_t io_list_iterator) +{ + return ccs_list_iterator_release (io_list_iterator); +} + +#ifdef TARGET_OS_MAC +#pragma mark- +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_credentials_list_object_release (ccs_list_object_t io_object) +{ + return cci_check_error (ccs_credentials_release ((ccs_credentials_t) io_object)); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_credentials_list_object_compare_identifier (ccs_list_object_t in_credentials, + cci_identifier_t in_identifier, + cc_uint32 *out_equal) +{ + return ccs_credentials_compare_identifier ((ccs_credentials_t) in_credentials, + in_identifier, + out_equal); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_new (ccs_credentials_list_t *out_list) +{ + return ccs_list_new (out_list, + ccErrInvalidCredentials, + ccErrInvalidCredentialsIterator, + ccs_credentials_list_object_compare_identifier, + ccs_credentials_list_object_release); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_new_iterator (ccs_credentials_list_t in_list, + ccs_pipe_t in_client_pipe, + ccs_credentials_list_iterator_t *out_list_iterator) +{ + return ccs_list_new_iterator (in_list, in_client_pipe, out_list_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_count (ccs_credentials_list_t in_list, + cc_uint64 *out_count) +{ + return ccs_list_count (in_list, out_count); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_find (ccs_credentials_list_t in_list, + cci_identifier_t in_identifier, + ccs_credentials_t *out_credentials) +{ + return ccs_list_find (in_list, in_identifier, (ccs_list_object_t *) out_credentials); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_find_iterator (ccs_credentials_list_t in_list, + cci_identifier_t in_identifier, + ccs_credentials_list_iterator_t *out_list_iterator) +{ + return ccs_list_find_iterator (in_list, in_identifier, + (ccs_list_iterator_t *) out_list_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_add (ccs_credentials_list_t io_list, + ccs_credentials_t in_credential) +{ + return ccs_list_add (io_list, (ccs_list_object_t) in_credential); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_remove (ccs_credentials_list_t io_list, + cci_identifier_t in_identifier) +{ + return ccs_list_remove (io_list, in_identifier); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_release (ccs_credentials_list_t io_list) +{ + return ccs_list_release (io_list); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_iterator_write (ccs_credentials_list_iterator_t in_list_iterator, + k5_ipc_stream in_stream) +{ + return ccs_list_iterator_write (in_list_iterator, in_stream); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_iterator_clone (ccs_credentials_list_iterator_t in_list_iterator, + ccs_credentials_list_iterator_t *out_list_iterator) +{ + return ccs_list_iterator_clone (in_list_iterator, out_list_iterator); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_iterator_next (ccs_credentials_list_iterator_t io_list_iterator, + ccs_credentials_t *out_credential) +{ + return ccs_list_iterator_next (io_list_iterator, (ccs_list_object_t *) out_credential); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_credentials_list_iterator_release (ccs_credentials_list_iterator_t io_list_iterator) +{ + return ccs_list_iterator_release (io_list_iterator); +} + +#ifdef TARGET_OS_MAC +#pragma mark- +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_generic_list_iterator_invalidate (ccs_generic_list_iterator_t io_list_iterator) +{ + return ccs_list_iterator_invalidate (io_list_iterator); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_list.h b/krb5-1.21.3/src/ccapi/server/ccs_list.h new file mode 100644 index 00000000..7b818f92 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_list.h @@ -0,0 +1,140 @@ +/* ccapi/server/ccs_list.h */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_LIST_H +#define CCS_LIST_H + + +#include "ccs_types.h" + +cc_int32 ccs_cache_collection_list_new (ccs_cache_collection_list_t *out_list); + +cc_int32 ccs_cache_collection_list_count (ccs_cache_collection_list_t in_list, + cc_uint64 *out_count); + +cc_int32 ccs_cache_collection_list_find (ccs_cache_collection_list_t in_list, + cci_identifier_t in_identifier, + ccs_cache_collection_t *out_cache_collection); + +cc_int32 ccs_cache_collection_list_add (ccs_cache_collection_list_t io_list, + ccs_cache_collection_t in_cache_collection); + +cc_int32 ccs_cache_collection_list_remove (ccs_cache_collection_list_t io_list, + cci_identifier_t in_identifier); + +cc_int32 ccs_cache_collection_list_release (ccs_cache_collection_list_t io_list); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_ccache_list_new (ccs_ccache_list_t *out_list); + +cc_int32 ccs_ccache_list_new_iterator (ccs_ccache_list_t in_list, + ccs_pipe_t in_client_pipe, + ccs_ccache_list_iterator_t *out_list_iterator); + +cc_int32 ccs_ccache_list_count (ccs_ccache_list_t in_list, + cc_uint64 *out_count); + +cc_int32 ccs_ccache_list_find (ccs_ccache_list_t in_list, + cci_identifier_t in_identifier, + ccs_ccache_t *out_ccache); + +cc_int32 ccs_ccache_list_find_iterator (ccs_ccache_list_t in_list, + cci_identifier_t in_identifier, + ccs_ccache_list_iterator_t *out_list_iterator); + +cc_int32 ccs_ccache_list_add (ccs_ccache_list_t io_list, + ccs_ccache_t in_ccache); + +cc_int32 ccs_ccache_list_remove (ccs_ccache_list_t io_list, + cci_identifier_t in_identifier); + +cc_int32 ccs_ccache_list_push_front (ccs_ccache_list_t io_list, + cci_identifier_t in_identifier); + +cc_int32 ccs_ccache_list_release (ccs_ccache_list_t io_list); + + +cc_int32 ccs_ccache_list_iterator_write (ccs_ccache_list_iterator_t in_list_iterator, + k5_ipc_stream in_stream); + +cc_int32 ccs_ccache_list_iterator_clone (ccs_ccache_list_iterator_t in_list_iterator, + ccs_ccache_list_iterator_t *out_list_iterator); + +cc_int32 ccs_ccache_list_iterator_next (ccs_ccache_list_iterator_t io_list_iterator, + ccs_ccache_t *out_ccache); + +cc_int32 ccs_ccache_list_iterator_release (ccs_ccache_list_iterator_t io_list_iterator); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_credentials_list_new (ccs_credentials_list_t *out_list); + +cc_int32 ccs_credentials_list_new_iterator (ccs_credentials_list_t in_list, + ccs_pipe_t in_client_pipe, + ccs_credentials_list_iterator_t *out_list_iterator); + +cc_int32 ccs_credentials_list_count (ccs_credentials_list_t in_list, + cc_uint64 *out_count); + +cc_int32 ccs_credentials_list_find (ccs_credentials_list_t in_list, + cci_identifier_t in_identifier, + ccs_credentials_t *out_credentials); + +cc_int32 ccs_credentials_list_find_iterator (ccs_credentials_list_t in_list, + cci_identifier_t in_identifier, + ccs_credentials_list_iterator_t *out_list_iterator); + +cc_int32 ccs_credentials_list_add (ccs_credentials_list_t io_list, + ccs_credentials_t in_credential); + +cc_int32 ccs_credentials_list_remove (ccs_credentials_list_t io_list, + cci_identifier_t in_identifier); + +cc_int32 ccs_credentials_list_release (ccs_credentials_list_t io_list); + + +cc_int32 ccs_credentials_list_iterator_write (ccs_credentials_list_iterator_t in_list_iterator, + k5_ipc_stream in_stream); + +cc_int32 ccs_credentials_list_iterator_clone (ccs_credentials_list_iterator_t in_list_iterator, + ccs_credentials_list_iterator_t *out_list_iterator); + +cc_int32 ccs_credentials_list_iterator_next (ccs_credentials_list_iterator_t io_list_iterator, + ccs_credentials_t *out_credential); + +cc_int32 ccs_credentials_list_iterator_release (ccs_credentials_list_iterator_t io_list_iterator); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +cc_int32 ccs_generic_list_iterator_invalidate (ccs_generic_list_iterator_t io_list_iterator); + +#endif /* CCS_LIST_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_list_internal.c b/krb5-1.21.3/src/ccapi/server/ccs_list_internal.c new file mode 100644 index 00000000..82d64652 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_list_internal.c @@ -0,0 +1,675 @@ +/* ccapi/server/ccs_list_internal.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_list_internal.h" +#include "cci_array_internal.h" +#include "cci_identifier.h" +#include "ccs_server.h" + +typedef enum { + ccs_list_action_insert, + ccs_list_action_remove, + ccs_list_action_push_front +} ccs_list_action_enum; + +/* ------------------------------------------------------------------------ */ + +struct ccs_list_d { + cci_array_t objects; + cci_array_t iterators; + + cc_int32 object_not_found_err; + cc_int32 iterator_not_found_err; + + ccs_object_compare_identifier_t object_compare_identifier; +}; + +struct ccs_list_d ccs_list_initializer = { NULL, NULL, -1, -1, NULL }; + +/* ------------------------------------------------------------------------ */ + +struct ccs_list_iterator_d { + cci_identifier_t identifier; + ccs_pipe_t client_pipe; + ccs_list_t list; + cc_uint64 current; +}; + +struct ccs_list_iterator_d ccs_list_iterator_initializer = { NULL, CCS_PIPE_NULL, NULL, 0 }; + +static cc_int32 ccs_list_iterator_new (ccs_list_iterator_t *out_list_iterator, + ccs_list_t in_list, + ccs_pipe_t in_client_pipe); + +static cc_int32 ccs_list_iterator_object_release (cci_array_object_t io_list_iterator); + +static cc_int32 ccs_list_iterator_update (ccs_list_iterator_t io_list_iterator, + ccs_list_action_enum in_action, + cc_uint64 in_object_index); + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_new (ccs_list_t *out_list, + cc_int32 in_object_not_found_err, + cc_int32 in_iterator_not_found_err, + ccs_object_compare_identifier_t in_object_compare_identifier, + ccs_object_release_t in_object_release) +{ + cc_int32 err = ccNoError; + ccs_list_t list = NULL; + + if (!out_list) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + list = malloc (sizeof (*list)); + if (list) { + *list = ccs_list_initializer; + list->object_not_found_err = in_object_not_found_err; + list->iterator_not_found_err = in_iterator_not_found_err; + list->object_compare_identifier = in_object_compare_identifier; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = cci_array_new (&list->objects, in_object_release); + } + + if (!err) { + err = cci_array_new (&list->iterators, ccs_list_iterator_object_release); + } + + if (!err) { + *out_list = list; + list = NULL; + } + + ccs_list_release (list); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_release (ccs_list_t io_list) +{ + cc_int32 err = ccNoError; + + if (!err && io_list) { + cci_array_release (io_list->iterators); + cci_array_release (io_list->objects); + free (io_list); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_new_iterator (ccs_list_t io_list, + ccs_pipe_t in_client_pipe, + ccs_list_iterator_t *out_list_iterator) +{ + return cci_check_error (ccs_list_iterator_new (out_list_iterator, + io_list, + in_client_pipe)); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_release_iterator (ccs_list_t io_list, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + ccs_list_iterator_t iterator = NULL; + + if (!io_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_list_find_iterator (io_list, in_identifier, &iterator); + } + + if (!err) { + err = ccs_list_iterator_release (iterator); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_count (ccs_list_t in_list, + cc_uint64 *out_count) +{ + cc_int32 err = ccNoError; + + if (!in_list ) { err = cci_check_error (ccErrBadParam); } + if (!out_count) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_count = cci_array_count (in_list->objects); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static ccs_list_iterator_t ccs_list_iterator_at_index (ccs_list_t in_list, + cc_uint64 in_index) +{ + return (ccs_list_iterator_t) cci_array_object_at_index (in_list->iterators, in_index); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_list_find_index (ccs_list_t in_list, + cci_identifier_t in_identifier, + cc_uint64 *out_object_index) +{ + cc_int32 err = ccNoError; + cc_int32 found = 0; + + if (!in_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_object_index) { err = cci_check_error (ccErrBadParam); } + + if (!err && !found) { + cc_uint64 i; + + for (i = 0; !err && i < cci_array_count (in_list->objects); i++) { + cc_uint32 equal = 0; + cci_array_object_t object = cci_array_object_at_index (in_list->objects, i); + + err = in_list->object_compare_identifier (object, in_identifier, &equal); + + if (!err && equal) { + found = 1; + *out_object_index = i; + break; + } + } + } + + if (!err && !found) { + err = cci_check_error (in_list->object_not_found_err); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ +cc_int32 ccs_list_find (ccs_list_t in_list, + cci_identifier_t in_identifier, + ccs_list_object_t *out_object) +{ + cc_int32 err = ccNoError; + cc_uint64 i; + + if (!in_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + if (!out_object ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_list_find_index (in_list, in_identifier, &i); + } + + if (!err) { + *out_object = cci_array_object_at_index (in_list->objects, i); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_list_find_iterator_index (ccs_list_t in_list, + cci_identifier_t in_identifier, + cc_uint64 *out_object_index) +{ + cc_int32 err = ccNoError; + cc_int32 found = 0; + + if (!in_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_object_index) { err = cci_check_error (ccErrBadParam); } + + if (!err && !found) { + cc_uint64 i; + + for (i = 0; !err && i < cci_array_count (in_list->iterators); i++) { + cc_uint32 equal = 0; + ccs_list_iterator_t iterator = ccs_list_iterator_at_index (in_list, i); + + err = cci_identifier_compare (iterator->identifier, in_identifier, &equal); + + if (!err && equal) { + found = 1; + *out_object_index = i; + break; + } + } + } + + if (!err && !found) { + // Don't report this error to the log file. Non-fatal. + return in_list->object_not_found_err; + } else { + return cci_check_error (err); + } +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_find_iterator (ccs_list_t in_list, + cci_identifier_t in_identifier, + ccs_list_iterator_t *out_list_iterator) +{ + cc_int32 err = ccNoError; + cc_uint64 i; + + if (!in_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier ) { err = cci_check_error (ccErrBadParam); } + if (!out_list_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_list_find_iterator_index (in_list, in_identifier, &i); + } + + if (!err) { + *out_list_iterator = ccs_list_iterator_at_index (in_list, i); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_add (ccs_list_t io_list, + ccs_list_object_t in_object) +{ + cc_int32 err = ccNoError; + cc_uint64 add_index; + + if (!io_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_object) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + add_index = cci_array_count (io_list->objects); + + err = cci_array_insert (io_list->objects, in_object, add_index); + } + + if (!err) { + /* Fixup iterator indexes */ + cc_uint64 i; + + for (i = 0; !err && i < cci_array_count (io_list->iterators); i++) { + ccs_list_iterator_t iterator = ccs_list_iterator_at_index (io_list, i); + + err = ccs_list_iterator_update (iterator, ccs_list_action_insert, add_index); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_remove (ccs_list_t io_list, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + cc_uint64 remove_index; + + if (!io_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_list_find_index (io_list, in_identifier, &remove_index); + } + + if (!err) { + err = cci_array_remove (io_list->objects, remove_index); + } + + if (!err) { + /* Fixup iterator indexes */ + cc_uint64 i; + + for (i = 0; !err && i < cci_array_count (io_list->iterators); i++) { + ccs_list_iterator_t iterator = ccs_list_iterator_at_index (io_list, i); + + err = ccs_list_iterator_update (iterator, ccs_list_action_remove, remove_index); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_push_front (ccs_list_t io_list, + cci_identifier_t in_identifier) +{ + cc_int32 err = ccNoError; + cc_uint64 push_front_index; + + if (!io_list ) { err = cci_check_error (ccErrBadParam); } + if (!in_identifier) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_list_find_index (io_list, in_identifier, &push_front_index); + } + + if (!err) { + err = cci_array_push_front (io_list->objects, push_front_index); + } + + if (!err) { + /* Fixup iterator indexes */ + cc_uint64 i; + + for (i = 0; !err && i < cci_array_count (io_list->iterators); i++) { + ccs_list_iterator_t iterator = ccs_list_iterator_at_index (io_list, i); + + err = ccs_list_iterator_update (iterator, + ccs_list_action_push_front, + push_front_index); + } + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_list_iterator_new (ccs_list_iterator_t *out_list_iterator, + ccs_list_t io_list, + ccs_pipe_t in_client_pipe) +{ + cc_int32 err = ccNoError; + ccs_list_iterator_t list_iterator = NULL; + + if (!out_list_iterator) { err = cci_check_error (ccErrBadParam); } + if (!io_list ) { err = cci_check_error (ccErrBadParam); } + /* client_pipe may be NULL if the iterator exists for internal server use */ + + if (!err) { + list_iterator = malloc (sizeof (*list_iterator)); + if (list_iterator) { + *list_iterator = ccs_list_iterator_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = ccs_server_new_identifier (&list_iterator->identifier); + } + + if (!err) { + list_iterator->list = io_list; + list_iterator->current = 0; + + err = cci_array_insert (io_list->iterators, + (cci_array_object_t) list_iterator, + cci_array_count (io_list->iterators)); + } + + if (!err && ccs_pipe_valid (in_client_pipe)) { + ccs_client_t client = NULL; + + err = ccs_pipe_copy (&list_iterator->client_pipe, in_client_pipe); + + if (!err) { + err = ccs_server_client_for_pipe (in_client_pipe, &client); + } + + if (!err) { + err = ccs_client_add_iterator (client, list_iterator); + } + } + + if (!err) { + *out_list_iterator = list_iterator; + list_iterator = NULL; + } + + ccs_list_iterator_release (list_iterator); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_iterator_write (ccs_list_iterator_t in_list_iterator, + k5_ipc_stream in_stream) +{ + cc_int32 err = ccNoError; + + if (!in_list_iterator) { err = cci_check_error (ccErrBadParam); } + if (!in_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_identifier_write (in_list_iterator->identifier, + in_stream); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_iterator_clone (ccs_list_iterator_t in_list_iterator, + ccs_list_iterator_t *out_list_iterator) +{ + cc_int32 err = ccNoError; + ccs_list_iterator_t list_iterator = NULL; + + if (!in_list_iterator ) { err = cci_check_error (ccErrBadParam); } + if (!out_list_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_list_iterator_new (&list_iterator, + in_list_iterator->list, + in_list_iterator->client_pipe); + } + + if (!err) { + list_iterator->current = in_list_iterator->current; + + *out_list_iterator = list_iterator; + list_iterator = NULL; + } + + ccs_list_iterator_release (list_iterator); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_list_iterator_object_release (cci_array_object_t io_list_iterator) +{ + cc_int32 err = ccNoError; + ccs_list_iterator_t list_iterator = (ccs_list_iterator_t) io_list_iterator; + + if (!io_list_iterator) { err = ccErrBadParam; } + + if (!err && ccs_pipe_valid (list_iterator->client_pipe)) { + ccs_client_t client = NULL; + + err = ccs_server_client_for_pipe (list_iterator->client_pipe, &client); + + if (!err && client) { + /* if client object still has a reference to us, remove it */ + err = ccs_client_remove_iterator (client, list_iterator); + } + } + + if (!err) { + ccs_pipe_release (list_iterator->client_pipe); + cci_identifier_release (list_iterator->identifier); + free (io_list_iterator); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_iterator_release (ccs_list_iterator_t io_list_iterator) +{ + cc_int32 err = ccNoError; + + if (!err && io_list_iterator) { + cc_uint64 i = 0; + + if (ccs_list_find_iterator_index (io_list_iterator->list, + io_list_iterator->identifier, + &i) == ccNoError) { + /* cci_array_remove will call ccs_list_iterator_object_release */ + err = cci_array_remove (io_list_iterator->list->iterators, i); + } else { + cci_debug_printf ("Warning: iterator not in iterator list!"); + } + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_iterator_invalidate (ccs_list_iterator_t io_list_iterator) +{ + cc_int32 err = ccNoError; + ccs_list_iterator_t list_iterator = (ccs_list_iterator_t) io_list_iterator; + + if (!io_list_iterator) { err = ccErrBadParam; } + + if (!err) { + /* Client owner died. Remove client reference and then the iterator. */ + if (ccs_pipe_valid (list_iterator->client_pipe)) { + ccs_pipe_release (list_iterator->client_pipe); + list_iterator->client_pipe = CCS_PIPE_NULL; + } + + err = ccs_list_iterator_release (io_list_iterator); + } + + return err; +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_iterator_current (ccs_list_iterator_t io_list_iterator, + ccs_list_object_t *out_object) +{ + cc_int32 err = ccNoError; + + if (!io_list_iterator) { err = cci_check_error (ccErrBadParam); } + if (!out_object ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + if (io_list_iterator->current < cci_array_count (io_list_iterator->list->objects)) { + *out_object = cci_array_object_at_index (io_list_iterator->list->objects, + io_list_iterator->current); + } else { + err = ccIteratorEnd; + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_list_iterator_next (ccs_list_iterator_t io_list_iterator, + ccs_list_object_t *out_object) +{ + cc_int32 err = ccNoError; + + if (!io_list_iterator) { err = cci_check_error (ccErrBadParam); } + if (!out_object ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + if (io_list_iterator->current < cci_array_count (io_list_iterator->list->objects)) { + *out_object = cci_array_object_at_index (io_list_iterator->list->objects, + io_list_iterator->current); + io_list_iterator->current++; + } else { + err = ccIteratorEnd; + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_list_iterator_update (ccs_list_iterator_t io_list_iterator, + ccs_list_action_enum in_action, + cc_uint64 in_object_index) +{ + cc_int32 err = ccNoError; + + if (!io_list_iterator) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + /* When the list changes adjust the current index so that */ + /* we don't unnecessarily skip or double count items */ + if (in_action == ccs_list_action_insert) { + if (io_list_iterator->current > in_object_index) { + io_list_iterator->current++; + } + + } else if (in_action == ccs_list_action_remove) { + if (io_list_iterator->current >= in_object_index) { + io_list_iterator->current--; + } + + } else if (in_action == ccs_list_action_push_front) { + if (io_list_iterator->current < in_object_index) { + io_list_iterator->current++; + } + + } else { + err = cci_check_error (ccErrBadParam); + } + } + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_list_internal.h b/krb5-1.21.3/src/ccapi/server/ccs_list_internal.h new file mode 100644 index 00000000..08cfa201 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_list_internal.h @@ -0,0 +1,94 @@ +/* ccapi/server/ccs_list_internal.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_LIST_INTERNAL_H +#define CCS_LIST_INTERNAL_H + +#include "ccs_common.h" +#include "cci_array_internal.h" + +struct ccs_list_d; +typedef struct ccs_list_d *ccs_list_t; + +struct ccs_list_iterator_d; +typedef struct ccs_list_iterator_d *ccs_list_iterator_t; + +typedef cci_array_object_t ccs_list_object_t; +typedef cc_int32 (*ccs_object_release_t) (ccs_list_object_t); +typedef cc_int32 (*ccs_object_compare_identifier_t) (ccs_list_object_t, cci_identifier_t, cc_uint32 *); + +cc_int32 ccs_list_new (ccs_list_t *out_list, + cc_int32 in_object_not_found_err, + cc_int32 in_iterator_not_found_err, + ccs_object_compare_identifier_t in_object_compare_identifier, + ccs_object_release_t in_object_release); + +cc_int32 ccs_list_release (ccs_list_t io_list); + +cc_int32 ccs_list_new_iterator (ccs_list_t io_list, + ccs_pipe_t in_client_pipe, + ccs_list_iterator_t *out_list_iterator); + +cc_int32 ccs_list_release_iterator (ccs_list_t io_list, + cci_identifier_t in_identifier); + +cc_int32 ccs_list_count (ccs_list_t in_list, + cc_uint64 *out_count); + +cc_int32 ccs_list_find (ccs_list_t in_list, + cci_identifier_t in_identifier, + ccs_list_object_t *out_object); + +cc_int32 ccs_list_find_iterator (ccs_list_t in_list, + cci_identifier_t in_identifier, + ccs_list_iterator_t *out_list_iterator); + +cc_int32 ccs_list_add (ccs_list_t io_list, + ccs_list_object_t in_object); + +cc_int32 ccs_list_remove (ccs_list_t io_list, + cci_identifier_t in_identifier); + +cc_int32 ccs_list_push_front (ccs_list_t io_list, + cci_identifier_t in_identifier); + + +cc_int32 ccs_list_iterator_write (ccs_list_iterator_t in_list_iterator, + k5_ipc_stream in_stream); + +cc_int32 ccs_list_iterator_clone (ccs_list_iterator_t in_list_iterator, + ccs_list_iterator_t *out_list_iterator); + +cc_int32 ccs_list_iterator_current (ccs_list_iterator_t io_list_iterator, + ccs_list_object_t *out_object); + +cc_int32 ccs_list_iterator_next (ccs_list_iterator_t io_list_iterator, + ccs_list_object_t *out_object); + +cc_int32 ccs_list_iterator_invalidate (ccs_list_iterator_t io_list_iterator); + +cc_int32 ccs_list_iterator_release (ccs_list_iterator_t io_list_iterator); + +#endif /* CCS_LIST_INTERNAL_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_lock.c b/krb5-1.21.3/src/ccapi/server/ccs_lock.c new file mode 100644 index 00000000..06886f8c --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_lock.c @@ -0,0 +1,248 @@ +/* ccapi/server/ccs_lock.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" + +struct ccs_lock_d { + cc_uint32 type; + ccs_lock_state_t lock_state_owner; + ccs_callback_t callback; +}; + +struct ccs_lock_d ccs_lock_initializer = { 0, NULL, NULL }; + +static cc_int32 ccs_lock_invalidate_callback (ccs_callback_owner_t io_lock, + ccs_callback_t in_callback); + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_new (ccs_lock_t *out_lock, + cc_uint32 in_type, + cc_int32 in_invalid_object_err, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_lock_state_t in_lock_state_owner) +{ + cc_int32 err = ccNoError; + ccs_lock_t lock = NULL; + + if (!out_lock ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + if (!in_lock_state_owner ) { err = cci_check_error (ccErrBadParam); } + + if (in_type != cc_lock_read && + in_type != cc_lock_write && + in_type != cc_lock_upgrade && + in_type != cc_lock_downgrade) { + err = cci_check_error (ccErrBadLockType); + } + + if (!err) { + lock = malloc (sizeof (*lock)); + if (lock) { + *lock = ccs_lock_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + lock->type = in_type; + lock->lock_state_owner = in_lock_state_owner; + + err = ccs_callback_new (&lock->callback, + in_invalid_object_err, + in_client_pipe, + in_reply_pipe, + (ccs_callback_owner_t) lock, + ccs_lock_invalidate_callback); + } + + if (!err) { + *out_lock = lock; + lock = NULL; + } + + ccs_lock_release (lock); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_release (ccs_lock_t io_lock) +{ + cc_int32 err = ccNoError; + + if (!err && io_lock) { + ccs_callback_release (io_lock->callback); + free (io_lock); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_invalidate_callback (ccs_callback_owner_t io_lock, + ccs_callback_t in_callback) +{ + cc_int32 err = ccNoError; + + if (!io_lock ) { err = cci_check_error (ccErrBadParam); } + if (!in_callback) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + ccs_lock_t lock = (ccs_lock_t) io_lock; + + err = ccs_lock_state_invalidate_lock (lock->lock_state_owner, lock); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_grant_lock (ccs_lock_t io_lock) +{ + cc_int32 err = ccNoError; + + if (!io_lock) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_callback_reply_to_client (io_lock->callback, NULL); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint32 ccs_lock_is_pending (ccs_lock_t in_lock, + cc_uint32 *out_pending) +{ + cc_int32 err = ccNoError; + + if (!in_lock ) { err = cci_check_error (ccErrBadParam); } + if (!out_pending) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_callback_is_pending (in_lock->callback, out_pending); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_type (ccs_lock_t in_lock, + cc_uint32 *out_lock_type) +{ + cc_int32 err = ccNoError; + + if (!in_lock ) { err = cci_check_error (ccErrBadParam); } + if (!out_lock_type) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_lock_type = in_lock->type; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_is_read_lock (ccs_lock_t in_lock, + cc_uint32 *out_is_read_lock) +{ + cc_int32 err = ccNoError; + + if (!in_lock ) { err = cci_check_error (ccErrBadParam); } + if (!out_is_read_lock) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_is_read_lock = (in_lock->type == cc_lock_read || + in_lock->type == cc_lock_downgrade); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_is_write_lock (ccs_lock_t in_lock, + cc_uint32 *out_is_write_lock) +{ + cc_int32 err = ccNoError; + + if (!in_lock ) { err = cci_check_error (ccErrBadParam); } + if (!out_is_write_lock) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + *out_is_write_lock = (in_lock->type == cc_lock_write || + in_lock->type == cc_lock_upgrade); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_is_for_client_pipe (ccs_lock_t in_lock, + ccs_pipe_t in_client_pipe, + cc_uint32 *out_is_for_client_pipe) +{ + cc_int32 err = ccNoError; + + if (!in_lock ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!out_is_for_client_pipe ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_callback_is_for_client_pipe (in_lock->callback, in_client_pipe, + out_is_for_client_pipe); + } + + return cci_check_error (err); +} + + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_client_pipe (ccs_lock_t in_lock, + ccs_pipe_t *out_client_pipe) +{ + cc_int32 err = ccNoError; + + if (!in_lock ) { err = cci_check_error (ccErrBadParam); } + if (!out_client_pipe) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_callback_client_pipe (in_lock->callback, out_client_pipe); + } + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_lock.h b/krb5-1.21.3/src/ccapi/server/ccs_lock.h new file mode 100644 index 00000000..71863ab1 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_lock.h @@ -0,0 +1,61 @@ +/* ccapi/server/ccs_lock.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_LOCK_H +#define CCS_LOCK_H + +#include "ccs_types.h" + +cc_int32 ccs_lock_new (ccs_lock_t *out_lock, + cc_uint32 in_type, + cc_int32 in_invalid_object_err, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_lock_state_t in_lock_state_owner); + +cc_int32 ccs_lock_release (ccs_lock_t io_lock); + +cc_int32 ccs_lock_grant_lock (ccs_lock_t io_lock); + +cc_uint32 ccs_lock_is_pending (ccs_lock_t in_lock, + cc_uint32 *out_pending); + +cc_int32 ccs_lock_type (ccs_lock_t in_lock, + cc_uint32 *out_lock_type); + +cc_int32 ccs_lock_is_read_lock (ccs_lock_t in_lock, + cc_uint32 *out_is_read_lock); + +cc_int32 ccs_lock_is_write_lock (ccs_lock_t in_lock, + cc_uint32 *out_is_write_lock); + +cc_int32 ccs_lock_is_for_client_pipe (ccs_lock_t in_lock, + ccs_pipe_t in_client_pipe, + cc_uint32 *out_is_for_client_pipe); + +cc_int32 ccs_lock_client_pipe (ccs_lock_t in_lock, + ccs_pipe_t *out_client_pipe); + +#endif /* CCS_LOCK_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_lock_state.c b/krb5-1.21.3/src/ccapi/server/ccs_lock_state.c new file mode 100644 index 00000000..681661ea --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_lock_state.c @@ -0,0 +1,525 @@ +/* ccapi/server/ccs_lock_state.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" + +struct ccs_lock_state_d { + cc_int32 invalid_object_err; + cc_int32 pending_lock_err; + cc_int32 no_lock_err; + ccs_lock_array_t locks; + cc_uint64 first_pending_lock_index; +}; + +struct ccs_lock_state_d ccs_lock_state_initializer = { 1, 1, 1, NULL, 0 }; + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_state_new (ccs_lock_state_t *out_lock_state, + cc_int32 in_invalid_object_err, + cc_int32 in_pending_lock_err, + cc_int32 in_no_lock_err) +{ + cc_int32 err = ccNoError; + ccs_lock_state_t lock_state = NULL; + + if (!out_lock_state) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + lock_state = malloc (sizeof (*lock_state)); + if (lock_state) { + *lock_state = ccs_lock_state_initializer; + } else { + err = cci_check_error (ccErrNoMem); + } + } + + if (!err) { + err = ccs_lock_array_new (&lock_state->locks); + } + + if (!err) { + lock_state->invalid_object_err = in_invalid_object_err; + lock_state->pending_lock_err = in_pending_lock_err; + lock_state->no_lock_err = in_no_lock_err; + + *out_lock_state = lock_state; + lock_state = NULL; + } + + ccs_lock_state_release (lock_state); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_state_release (ccs_lock_state_t io_lock_state) +{ + cc_int32 err = ccNoError; + + if (!err && io_lock_state) { + ccs_lock_array_release (io_lock_state->locks); + free (io_lock_state); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_status_add_pending_lock (ccs_lock_state_t io_lock_state, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + cc_uint32 in_lock_type, + cc_uint64 *out_lock_index) +{ + cc_int32 err = ccNoError; + ccs_lock_t lock = NULL; + + if (!io_lock_state ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_lock_new (&lock, in_lock_type, + io_lock_state->invalid_object_err, + in_client_pipe, in_reply_pipe, + io_lock_state); + } + + if (!err) { + err = ccs_lock_array_insert (io_lock_state->locks, lock, + ccs_lock_array_count (io_lock_state->locks)); + if (!err) { lock = NULL; /* take ownership */ } + } + + if (!err) { + *out_lock_index = ccs_lock_array_count (io_lock_state->locks) - 1; + } + + ccs_lock_release (lock); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_status_remove_lock (ccs_lock_state_t io_lock_state, + cc_uint64 in_lock_index) +{ + cc_int32 err = ccNoError; + + if (!io_lock_state) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_lock_array_remove (io_lock_state->locks, in_lock_index); + + if (!err && in_lock_index < io_lock_state->first_pending_lock_index) { + io_lock_state->first_pending_lock_index--; + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_status_grant_lock (ccs_lock_state_t io_lock_state, + cc_uint64 in_pending_lock_index) +{ + cc_int32 err = ccNoError; + ccs_lock_t pending_lock = NULL; + cc_uint32 type = 0; + + if (!io_lock_state) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + pending_lock = ccs_lock_array_object_at_index (io_lock_state->locks, + in_pending_lock_index); + if (!pending_lock || in_pending_lock_index < io_lock_state->first_pending_lock_index) { + err = cci_check_error (ccErrBadParam); + } + } + + if (!err) { + err = ccs_lock_type (pending_lock, &type); + } + + if (!err && (type == cc_lock_upgrade || type == cc_lock_downgrade)) { + /* lock upgrades or downgrades. Find the old lock and remove it. */ + ccs_pipe_t pending_client_pipe = CCS_PIPE_NULL; + + err = ccs_lock_client_pipe (pending_lock, &pending_client_pipe); + + if (!err) { + cc_uint64 i; + + for (i = 0; !err && i < io_lock_state->first_pending_lock_index; i++) { + ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i); + cc_uint32 is_lock_for_client = 0; + + err = ccs_lock_is_for_client_pipe (lock, pending_client_pipe, &is_lock_for_client); + + if (!err && is_lock_for_client) { + cci_debug_printf ("%s: Removing old lock %p at index %d to replace with pending lock %p.", + __FUNCTION__, lock, (int) i, pending_lock); + err = ccs_lock_status_remove_lock (io_lock_state, i); + if (!err) { i--; in_pending_lock_index--; /* We removed one so back up an index */ } + break; + } + } + } + } + + if (!err) { + cc_uint64 new_lock_index = 0; + + err = ccs_lock_array_move (io_lock_state->locks, + in_pending_lock_index, + io_lock_state->first_pending_lock_index, + &new_lock_index); + if (!err) { io_lock_state->first_pending_lock_index++; } + } + + if (!err) { + err = ccs_lock_grant_lock (pending_lock); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_state_check_pending_lock (ccs_lock_state_t io_lock_state, + ccs_pipe_t in_pending_lock_client_pipe, + cc_uint32 in_pending_lock_type, + cc_uint32 *out_grant_lock) +{ + cc_int32 err = ccNoError; + cc_uint32 is_write_locked = 0; + cc_uint32 client_has_lock = 0; + cc_uint32 other_clients_have_locks = 0; + cc_uint32 client_lock_type = 0; + cc_uint64 client_lock_index = 0; + cc_uint32 grant_lock = 0; + + if (!io_lock_state ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_pending_lock_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!out_grant_lock ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_uint64 i; + cc_uint64 lock_count = io_lock_state->first_pending_lock_index; + + for (i = 0; !err && i < lock_count; i++) { + ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i); + cc_uint32 lock_type = 0; + cc_uint32 lock_is_for_client = 0; + + err = ccs_lock_type (lock, &lock_type); + + if (!err) { + err = ccs_lock_is_for_client_pipe (lock, in_pending_lock_client_pipe, + &lock_is_for_client); + } + + if (!err) { + if (lock_type == cc_lock_write || lock_type == cc_lock_upgrade) { + is_write_locked = 1; + } + + if (!lock_is_for_client) { + other_clients_have_locks = 1; + + } else if (!client_has_lock) { /* only record type of 1st lock */ + client_has_lock = 1; + client_lock_type = lock_type; + client_lock_index = i; + } + } + } + } + + if (!err) { + cc_uint64 lock_count = io_lock_state->first_pending_lock_index; + + if (in_pending_lock_type == cc_lock_write) { + if (client_has_lock) { + err = cci_check_error (ccErrBadLockType); + } else { + grant_lock = (lock_count == 0); + } + + } else if (in_pending_lock_type == cc_lock_read) { + if (client_has_lock) { + err = cci_check_error (ccErrBadLockType); + } else { + grant_lock = !is_write_locked; + } + + } else if (in_pending_lock_type == cc_lock_upgrade) { + if (!client_has_lock || (client_lock_type != cc_lock_read && + client_lock_type != cc_lock_downgrade)) { + err = cci_check_error (ccErrBadLockType); + } else { + /* don't grant if other clients have read locks */ + grant_lock = !other_clients_have_locks; + } + + } else if (in_pending_lock_type == cc_lock_downgrade) { + if (!client_has_lock || (client_lock_type != cc_lock_write && + client_lock_type != cc_lock_upgrade)) { + err = cci_check_error (ccErrBadLockType); + } else { + /* downgrades can never block */ + grant_lock = 1; + } + } else { + err = cci_check_error (ccErrBadLockType); + } + } + + if (!err) { + *out_grant_lock = grant_lock; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_lock_status_try_to_grant_pending_locks (ccs_lock_state_t io_lock_state) +{ + cc_int32 err = ccNoError; + cc_uint32 done = 0; + + if (!io_lock_state) { err = cci_check_error (ccErrBadParam); } + + /* Look at the pending locks and see if we can grant them. + * Note that downgrade locks mean we must check all pending locks each pass + * since a downgrade lock might be last in the list. */ + + while (!err && !done) { + cc_uint64 i; + cc_uint64 count = ccs_lock_array_count (io_lock_state->locks); + cc_uint32 granted_lock = 0; + + for (i = io_lock_state->first_pending_lock_index; !err && i < count; i++) { + ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i); + cc_uint32 lock_type = 0; + ccs_pipe_t client_pipe = CCS_PIPE_NULL; + cc_uint32 can_grant_lock_now = 0; + + err = ccs_lock_client_pipe (lock, &client_pipe); + + if (!err) { + err = ccs_lock_type (lock, &lock_type); + } + + if (!err) { + err = ccs_lock_state_check_pending_lock (io_lock_state, client_pipe, + lock_type, &can_grant_lock_now); + } + + if (!err && can_grant_lock_now) { + err = ccs_lock_status_grant_lock (io_lock_state, i); + if (!err) { granted_lock = 1; } + } + } + + if (!err && !granted_lock) { + /* we walked over all the locks and couldn't grant any of them */ + done = 1; + } + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_state_add (ccs_lock_state_t io_lock_state, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + cc_uint32 in_lock_type, + cc_uint32 in_block, + cc_uint32 *out_will_send_reply) +{ + cc_int32 err = ccNoError; + cc_uint32 can_grant_lock_now = 0; + + if (!io_lock_state ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_send_reply ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + /* Sanity check: if there are any pending locks for this client + * the client must have timed out waiting for our reply. Remove any + * existing pending locks for the client. */ + cc_uint64 i; + + for (i = io_lock_state->first_pending_lock_index; !err && i < ccs_lock_array_count (io_lock_state->locks); i++) { + ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i); + cc_uint32 has_pending_lock_for_client = 0; + + err = ccs_lock_is_for_client_pipe (lock, in_client_pipe, &has_pending_lock_for_client); + + if (!err && has_pending_lock_for_client) { + cci_debug_printf ("WARNING %s: Removing unexpected pending lock %p at index %d.", + __FUNCTION__, lock, (int) i); + err = ccs_lock_status_remove_lock (io_lock_state, i); + if (!err) { i--; /* We removed one so back up an index */ } + } + } + } + + if (!err) { + err = ccs_lock_state_check_pending_lock (io_lock_state, in_client_pipe, + in_lock_type, &can_grant_lock_now); + } + + if (!err) { + if (!can_grant_lock_now && (in_block == cc_lock_noblock)) { + err = cci_check_error (io_lock_state->pending_lock_err); + + } else { + cc_uint64 new_lock_index = 0; + + err = ccs_lock_status_add_pending_lock (io_lock_state, + in_client_pipe, + in_reply_pipe, + in_lock_type, + &new_lock_index); + + if (!err && can_grant_lock_now) { + err = ccs_lock_status_grant_lock (io_lock_state, new_lock_index); + + if (!err && (in_lock_type == cc_lock_downgrade)) { + /* downgrades can allow us to grant other locks */ + err = ccs_lock_status_try_to_grant_pending_locks (io_lock_state); + } + } + } + } + + if (!err) { + /* ccs_lock_state_add sends its replies via callback so caller shouldn't */ + *out_will_send_reply = 1; + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_state_remove (ccs_lock_state_t io_lock_state, + ccs_pipe_t in_client_pipe) +{ + cc_int32 err = ccNoError; + cc_uint32 found_lock = 0; + + if (!io_lock_state ) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_uint64 i; + + /* Remove all locks for this client. + * There should only be one so warn if there are multiple */ + for (i = 0; !err && i < io_lock_state->first_pending_lock_index; i++) { + ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i); + cc_uint32 is_for_client = 0; + + err = ccs_lock_is_for_client_pipe (lock, in_client_pipe, &is_for_client); + + if (!err && is_for_client) { + if (found_lock) { + cci_debug_printf ("WARNING %s: Found multiple locks for client.", + __FUNCTION__); + } + + found_lock = 1; + + cci_debug_printf ("%s: Removing lock %p at index %d.", __FUNCTION__, lock, (int) i); + err = ccs_lock_status_remove_lock (io_lock_state, i); + if (!err) { i--; /* We removed one so back up an index */ } + } + } + } + + if (!err && !found_lock) { + err = cci_check_error (io_lock_state->no_lock_err); + } + + if (!err) { + err = ccs_lock_status_try_to_grant_pending_locks (io_lock_state); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_lock_state_invalidate_lock (ccs_lock_state_t io_lock_state, + ccs_lock_t in_lock) +{ + cc_int32 err = ccNoError; + + if (!io_lock_state) { err = ccErrBadParam; } + + if (!err) { + cc_uint64 i; + cc_uint64 count = ccs_lock_array_count (io_lock_state->locks); + + for (i = 0; !err && i < count; i++) { + ccs_lock_t lock = ccs_lock_array_object_at_index (io_lock_state->locks, i); + + if (lock == in_lock) { + err = ccs_lock_status_remove_lock (io_lock_state, i); + + if (!err) { + err = ccs_lock_status_try_to_grant_pending_locks (io_lock_state); + break; + } + } + } + } + + return cci_check_error (err); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_lock_state.h b/krb5-1.21.3/src/ccapi/server/ccs_lock_state.h new file mode 100644 index 00000000..de91fca4 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_lock_state.h @@ -0,0 +1,51 @@ +/* ccapi/server/ccs_lock_state.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_LOCK_STATE_H +#define CCS_LOCK_STATE_H + +#include "ccs_types.h" + +cc_int32 ccs_lock_state_new (ccs_lock_state_t *out_lock_state, + cc_int32 in_invalid_object_err, + cc_int32 in_pending_lock_err, + cc_int32 in_no_lock_err); + +cc_int32 ccs_lock_state_release (ccs_lock_state_t io_lock_state); + +cc_int32 ccs_lock_state_add (ccs_lock_state_t io_lock_state, + ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + cc_uint32 in_lock_type, + cc_uint32 in_block, + cc_uint32 *out_will_send_reply); + +cc_int32 ccs_lock_state_remove (ccs_lock_state_t io_lock_state, + ccs_pipe_t in_client_pipe); + +cc_int32 ccs_lock_state_invalidate_lock (ccs_lock_state_t io_lock_state, + ccs_lock_t in_lock); + +#endif /* CCS_LOCK_STATE_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_os_notify.h b/krb5-1.21.3/src/ccapi/server/ccs_os_notify.h new file mode 100644 index 00000000..4021568f --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_os_notify.h @@ -0,0 +1,37 @@ +/* ccapi/server/ccs_os_notify.h */ +/* + * Copyright 2006-2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_OS_NOTIFY_H +#define CCS_OS_NOTIFY_H + +#include "ccs_types.h" + +cc_int32 ccs_os_notify_cache_collection_changed (ccs_cache_collection_t io_cache_collection); + +cc_int32 ccs_os_notify_ccache_changed (ccs_cache_collection_t io_cache_collection, + const char *in_ccache_name); + + +#endif /* CCS_OS_NOTIFY_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_os_pipe.h b/krb5-1.21.3/src/ccapi/server/ccs_os_pipe.h new file mode 100644 index 00000000..4f6a379c --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_os_pipe.h @@ -0,0 +1,42 @@ +/* ccapi/server/ccs_os_pipe.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_OS_PIPE_H +#define CCS_OS_PIPE_H + +#include "ccs_types.h" + +cc_int32 ccs_os_pipe_valid (ccs_pipe_t in_pipe); + +cc_int32 ccs_os_pipe_compare (ccs_pipe_t in_pipe, + ccs_pipe_t in_compare_to_pipe, + cc_uint32 *out_equal); + +cc_int32 ccs_os_pipe_copy (ccs_pipe_t *out_pipe, + ccs_pipe_t in_pipe); + +cc_int32 ccs_os_pipe_release (ccs_pipe_t io_pipe); + +#endif /* CCS_OS_PIPE_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_os_server.h b/krb5-1.21.3/src/ccapi/server/ccs_os_server.h new file mode 100644 index 00000000..dc89f1d6 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_os_server.h @@ -0,0 +1,40 @@ +/* ccapi/server/ccs_os_server.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_OS_SERVER_H +#define CCS_OS_SERVER_H + +#include "ccs_types.h" + +cc_int32 ccs_os_server_initialize (int argc, const char *argv[]); + +cc_int32 ccs_os_server_cleanup (int argc, const char *argv[]); + +cc_int32 ccs_os_server_listen_loop (int argc, const char *argv[]); + +cc_int32 ccs_os_server_send_reply (ccs_pipe_t in_reply_pipe, + k5_ipc_stream in_reply_stream); + +#endif /* CCS_OS_SERVER_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_pipe.c b/krb5-1.21.3/src/ccapi/server/ccs_pipe.c new file mode 100644 index 00000000..37744f61 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_pipe.c @@ -0,0 +1,58 @@ +/* ccapi/server/ccs_pipe.c */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" +#include "ccs_os_pipe.h" + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_pipe_valid (ccs_pipe_t in_pipe) +{ + return ccs_os_pipe_valid (in_pipe); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_pipe_compare (ccs_pipe_t in_pipe, + ccs_pipe_t in_compare_to_pipe, + cc_uint32 *out_equal) +{ + return ccs_os_pipe_compare (in_pipe, in_compare_to_pipe, out_equal); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_pipe_copy (ccs_pipe_t *out_pipe, + ccs_pipe_t in_pipe) +{ + return ccs_os_pipe_copy (out_pipe, in_pipe); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_pipe_release (ccs_pipe_t io_pipe) +{ + return ccs_os_pipe_release (io_pipe); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_pipe.h b/krb5-1.21.3/src/ccapi/server/ccs_pipe.h new file mode 100644 index 00000000..6e4f9efa --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_pipe.h @@ -0,0 +1,42 @@ +/* ccapi/server/ccs_pipe.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_PIPE_H +#define CCS_PIPE_H + +#include "ccs_types.h" + +cc_int32 ccs_pipe_valid (ccs_pipe_t in_pipe); + +cc_int32 ccs_pipe_compare (ccs_pipe_t in_pipe, + ccs_pipe_t in_compare_to_pipe, + cc_uint32 *out_equal); + +cc_int32 ccs_pipe_copy (ccs_pipe_t *out_pipe, + ccs_pipe_t in_pipe); + +cc_int32 ccs_pipe_release (ccs_pipe_t io_pipe); + +#endif /* CCS_PIPE_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_server.c b/krb5-1.21.3/src/ccapi/server/ccs_server.c new file mode 100644 index 00000000..1fc8d2c5 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_server.c @@ -0,0 +1,408 @@ +/* ccapi/server/ccs_server.c */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" +#include "ccs_os_server.h" + +/* Server Globals: */ + +cci_uuid_string_t g_server_id = NULL; +ccs_cache_collection_t g_cache_collection = NULL; +ccs_client_array_t g_client_array = NULL; + +/* ------------------------------------------------------------------------ */ + +int main (int argc, const char *argv[]) +{ + cc_int32 err = 0; + + if (!err) { + err = ccs_os_server_initialize (argc, argv); + } + + if (!err) { + err = cci_identifier_new_uuid (&g_server_id); + } + + if (!err) { + err = ccs_cache_collection_new (&g_cache_collection); + } + + if (!err) { + err = ccs_client_array_new (&g_client_array); + } + + if (!err) { + err = ccs_os_server_listen_loop (argc, argv); + } + + if (!err) { + free (g_server_id); + cci_check_error (ccs_cache_collection_release (g_cache_collection)); + cci_check_error (ccs_client_array_release (g_client_array)); + + err = ccs_os_server_cleanup (argc, argv); + } + + return cci_check_error (err) ? 1 : 0; +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_new_identifier (cci_identifier_t *out_identifier) +{ + return cci_check_error (cci_identifier_new (out_identifier, + g_server_id)); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_add_client (ccs_pipe_t in_connection_pipe) +{ + cc_int32 err = ccNoError; + ccs_client_t client = NULL; + + if (!err) { + err = ccs_client_new (&client, in_connection_pipe); + } + + if (!err) { + cci_debug_printf ("%s: Adding client %p.", __FUNCTION__, client); + err = ccs_client_array_insert (g_client_array, + client, + ccs_client_array_count (g_client_array)); + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_remove_client (ccs_pipe_t in_connection_pipe) +{ + cc_int32 err = ccNoError; + + if (!err) { + cc_uint64 i; + cc_uint64 count = ccs_client_array_count (g_client_array); + cc_uint32 found = 0; + + for (i = 0; !err && i < count; i++) { + ccs_client_t client = ccs_client_array_object_at_index (g_client_array, i); + + err = ccs_client_uses_pipe (client, in_connection_pipe, &found); + + if (!err && found) { + cci_debug_printf ("%s: Removing client %p.", __FUNCTION__, client); + err = ccs_client_array_remove (g_client_array, i); + break; + } + } + + if (!err && !found) { + cci_debug_printf ("WARNING %s() didn't find client in client list.", + __FUNCTION__); + } + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_client_for_pipe (ccs_pipe_t in_client_pipe, + ccs_client_t *out_client) +{ + cc_int32 err = ccNoError; + ccs_client_t client_for_pipe = NULL; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!out_client ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + cc_uint64 i; + cc_uint64 count = ccs_client_array_count (g_client_array); + + for (i = 0; !err && i < count; i++) { + ccs_client_t client = ccs_client_array_object_at_index (g_client_array, i); + cc_uint32 uses_pipe = 0; + + err = ccs_client_uses_pipe (client, in_client_pipe, &uses_pipe); + + if (!err && uses_pipe) { + client_for_pipe = client; + break; + } + } + } + + if (!err) { + *out_client = client_for_pipe; /* may be NULL if not found */ + } + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_client_is_valid (ccs_pipe_t in_client_pipe, + cc_uint32 *out_client_is_valid) +{ + cc_int32 err = ccNoError; + ccs_client_t client = NULL; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!out_client_is_valid ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = ccs_server_client_for_pipe (in_client_pipe, &client); + } + + if (!err) { + *out_client_is_valid = (client != NULL); + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +static cc_int32 ccs_server_request_demux (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + ccs_cache_collection_t in_cache_collection, + enum cci_msg_id_t in_request_name, + cci_identifier_t in_request_identifier, + k5_ipc_stream in_request_data, + cc_uint32 *out_will_block, + k5_ipc_stream *out_reply_data) +{ + cc_int32 err = ccNoError; + + if (!ccs_pipe_valid (in_reply_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!in_request_data ) { err = cci_check_error (ccErrBadParam); } + if (!out_will_block ) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_data ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + if (in_request_name > cci_context_first_msg_id && + in_request_name < cci_context_last_msg_id) { + /* Note: context identifier doesn't need to match. + * Client just uses the identifier to detect server relaunch. */ + + if (!err) { + err = ccs_cache_collection_handle_message (in_client_pipe, + in_reply_pipe, + in_cache_collection, + in_request_name, + in_request_data, + out_will_block, + out_reply_data); + } + + } else if (in_request_name > cci_ccache_first_msg_id && + in_request_name < cci_ccache_last_msg_id) { + ccs_ccache_t ccache = NULL; + + err = ccs_cache_collection_find_ccache (in_cache_collection, + in_request_identifier, + &ccache); + + if (!err) { + err = ccs_ccache_handle_message (in_client_pipe, + in_reply_pipe, + ccache, + in_cache_collection, + in_request_name, + in_request_data, + out_will_block, + out_reply_data); + } + + } else if (in_request_name > cci_ccache_iterator_first_msg_id && + in_request_name < cci_ccache_iterator_last_msg_id) { + ccs_ccache_iterator_t ccache_iterator = NULL; + + err = ccs_cache_collection_find_ccache_iterator (in_cache_collection, + in_request_identifier, + &ccache_iterator); + + if (!err) { + err = ccs_ccache_iterator_handle_message (ccache_iterator, + in_cache_collection, + in_request_name, + in_request_data, + out_reply_data); + } + + if (!err) { + *out_will_block = 0; /* can't block */ + } + + } else if (in_request_name > cci_credentials_iterator_first_msg_id && + in_request_name < cci_credentials_iterator_last_msg_id) { + ccs_credentials_iterator_t credentials_iterator = NULL; + ccs_ccache_t ccache = NULL; + + err = ccs_cache_collection_find_credentials_iterator (in_cache_collection, + in_request_identifier, + &ccache, + &credentials_iterator); + + if (!err) { + err = ccs_credentials_iterator_handle_message (credentials_iterator, + ccache, + in_request_name, + in_request_data, + out_reply_data); + } + + if (!err) { + *out_will_block = 0; /* can't block */ + } + + } else { + err = ccErrBadInternalMessage; + } + } + + return cci_check_error (err); +} + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_handle_request (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + k5_ipc_stream in_request) +{ + cc_int32 err = ccNoError; + enum cci_msg_id_t request_name = 0; + cci_identifier_t request_identifier = NULL; + cc_uint32 will_block = 0; + k5_ipc_stream reply_data = NULL; + + if (!ccs_pipe_valid (in_client_pipe)) { err = cci_check_error (ccErrBadParam); } + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + if (!in_request ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_message_read_request_header (in_request, + &request_name, + &request_identifier); + } + + if (!err) { + cc_uint32 server_err = 0; + cc_uint32 valid = 0; + ccs_cache_collection_t cache_collection = g_cache_collection; + + server_err = cci_identifier_is_for_server (request_identifier, + g_server_id, + &valid); + + if (!server_err && !valid) { + server_err = cci_message_invalid_object_err (request_name); + } + + if (!server_err) { + + /* Monolithic server implementation would need to select + * cache collection here. Currently we only support per-user + * servers so we always use the same cache collection. */ + + server_err = ccs_server_request_demux (in_client_pipe, + in_reply_pipe, + cache_collection, + request_name, + request_identifier, + in_request, + &will_block, + &reply_data); + } + + if (server_err || !will_block) { + + /* send a reply now if the server isn't blocked on something */ + err = ccs_server_send_reply (in_reply_pipe, server_err, reply_data); + } + } + + cci_identifier_release (request_identifier); + krb5int_ipc_stream_release (reply_data); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_server_send_reply (ccs_pipe_t in_reply_pipe, + cc_int32 in_reply_err, + k5_ipc_stream in_reply_data) +{ + cc_int32 err = ccNoError; + k5_ipc_stream reply = NULL; + + if (!ccs_pipe_valid (in_reply_pipe) ) { err = cci_check_error (ccErrBadParam); } + + if (!err) { + err = cci_message_new_reply_header (&reply, in_reply_err); + } + + if (!err && in_reply_data && krb5int_ipc_stream_size (in_reply_data) > 0) { + err = krb5int_ipc_stream_write (reply, + krb5int_ipc_stream_data (in_reply_data), + krb5int_ipc_stream_size (in_reply_data)); + } + + if (!err) { + err = ccs_os_server_send_reply (in_reply_pipe, reply); + } + + krb5int_ipc_stream_release (reply); + + return cci_check_error (err); +} + +/* ------------------------------------------------------------------------ */ + +cc_uint64 ccs_server_client_count () +{ + return ccs_client_array_count (g_client_array); +} diff --git a/krb5-1.21.3/src/ccapi/server/ccs_server.h b/krb5-1.21.3/src/ccapi/server/ccs_server.h new file mode 100644 index 00000000..e920ad93 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_server.h @@ -0,0 +1,53 @@ +/* ccapi/server/ccs_server.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_SERVER_H +#define CCS_SERVER_H + +#include "ccs_types.h" + +cc_int32 ccs_server_new_identifier (cci_identifier_t *out_identifier); + +cc_int32 ccs_server_add_client (ccs_pipe_t in_connection_pipe); + +cc_int32 ccs_server_remove_client (ccs_pipe_t in_connection_pipe); + +cc_int32 ccs_server_client_for_pipe (ccs_pipe_t in_client_pipe, + ccs_client_t *out_client); + +cc_int32 ccs_server_client_is_valid (ccs_pipe_t in_client_pipe, + cc_uint32 *out_client_is_valid); + +cc_int32 ccs_server_handle_request (ccs_pipe_t in_client_pipe, + ccs_pipe_t in_reply_pipe, + k5_ipc_stream in_request); + +cc_int32 ccs_server_send_reply (ccs_pipe_t in_reply_pipe, + cc_int32 in_reply_err, + k5_ipc_stream in_reply_data); + +cc_uint64 ccs_server_client_count (); + +#endif /* CCS_SERVER_H */ diff --git a/krb5-1.21.3/src/ccapi/server/ccs_types.h b/krb5-1.21.3/src/ccapi/server/ccs_types.h new file mode 100644 index 00000000..773b3166 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/ccs_types.h @@ -0,0 +1,120 @@ +/* ccapi/server/ccs_types.h */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef CCS_TYPES_H +#define CCS_TYPES_H + +#ifdef WIN32 +#pragma warning ( disable : 4068) +#endif + +#include "cci_types.h" + +struct cci_array_d; + +typedef struct cci_array_d *ccs_client_array_t; + +typedef struct cci_array_d *ccs_callback_array_t; + +typedef struct cci_array_d *ccs_callbackref_array_t; + +typedef struct cci_array_d *ccs_iteratorref_array_t; + +typedef struct cci_array_d *ccs_lock_array_t; + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +/* ccs_os_pipe_t is IPC-specific so it's special cased here */ + +#if TARGET_OS_MAC +#include +typedef mach_port_t ccs_pipe_t; /* Mach IPC port */ +#define CCS_PIPE_NULL MACH_PORT_NULL + +#else + +#ifdef WIN32 +/* On Windows, a pipe is s struct: */ +#include "ccs_win_pipe.h" +typedef struct ccs_win_pipe_t* ccs_pipe_t; +#define CCS_PIPE_NULL (ccs_pipe_t)NULL + +#else +typedef int ccs_pipe_t; /* Unix domain socket */ +#define CCS_PIPE_NULL -1 + +#endif +#endif + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +struct ccs_callback_d; +typedef struct ccs_callback_d *ccs_callback_t; + +struct ccs_list_d; +struct ccs_list_iterator_d; + +/* Used for iterator array invalidate function */ +typedef struct ccs_list_iterator_d *ccs_generic_list_iterator_t; + +typedef struct ccs_list_d *ccs_cache_collection_list_t; + +typedef struct ccs_list_d *ccs_ccache_list_t; +typedef struct ccs_list_iterator_d *ccs_ccache_list_iterator_t; + +typedef struct ccs_list_d *ccs_credentials_list_t; +typedef struct ccs_list_iterator_d *ccs_credentials_list_iterator_t; + +#ifdef TARGET_OS_MAC +#pragma mark - +#endif + +struct ccs_client_d; +typedef struct ccs_client_d *ccs_client_t; + +struct ccs_lock_d; +typedef struct ccs_lock_d *ccs_lock_t; + +struct ccs_lock_state_d; +typedef struct ccs_lock_state_d *ccs_lock_state_t; + +struct ccs_credentials_d; +typedef struct ccs_credentials_d *ccs_credentials_t; + +typedef ccs_credentials_list_iterator_t ccs_credentials_iterator_t; + +struct ccs_ccache_d; +typedef struct ccs_ccache_d *ccs_ccache_t; + +typedef ccs_ccache_list_iterator_t ccs_ccache_iterator_t; + +struct ccs_cache_collection_d; +typedef struct ccs_cache_collection_d *ccs_cache_collection_t; + +#endif /* CCS_TYPES_H */ diff --git a/krb5-1.21.3/src/ccapi/server/deps b/krb5-1.21.3/src/ccapi/server/deps new file mode 100644 index 00000000..31582f58 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/deps @@ -0,0 +1,170 @@ +# +# Generated makefile dependencies follow. +# +ccs_array.so ccs_array.po $(OUTPRE)ccs_array.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_array_internal.h $(srcdir)/../common/cci_common.h \ + $(srcdir)/../common/cci_cred_union.h $(srcdir)/../common/cci_debugging.h \ + $(srcdir)/../common/cci_identifier.h $(srcdir)/../common/cci_message.h \ + $(srcdir)/../common/cci_types.h ccs_array.c ccs_array.h \ + ccs_cache_collection.h ccs_callback.h ccs_ccache.h \ + ccs_ccache_iterator.h ccs_client.h ccs_common.h ccs_credentials.h \ + ccs_credentials_iterator.h ccs_list.h ccs_lock.h ccs_lock_state.h \ + ccs_pipe.h ccs_server.h ccs_types.h +ccs_cache_collection.so ccs_cache_collection.po $(OUTPRE)ccs_cache_collection.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccs_array.h ccs_cache_collection.c ccs_cache_collection.h \ + ccs_callback.h ccs_ccache.h ccs_ccache_iterator.h ccs_client.h \ + ccs_common.h ccs_credentials.h ccs_credentials_iterator.h \ + ccs_list.h ccs_lock.h ccs_lock_state.h ccs_os_notify.h \ + ccs_pipe.h ccs_server.h ccs_types.h +ccs_callback.so ccs_callback.po $(OUTPRE)ccs_callback.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccs_array.h ccs_cache_collection.h ccs_callback.c ccs_callback.h \ + ccs_ccache.h ccs_ccache_iterator.h ccs_client.h ccs_common.h \ + ccs_credentials.h ccs_credentials_iterator.h ccs_list.h \ + ccs_lock.h ccs_lock_state.h ccs_pipe.h ccs_server.h \ + ccs_types.h +ccs_ccache.so ccs_ccache.po $(OUTPRE)ccs_ccache.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccs_array.h ccs_cache_collection.h ccs_callback.h ccs_ccache.c \ + ccs_ccache.h ccs_ccache_iterator.h ccs_client.h ccs_common.h \ + ccs_credentials.h ccs_credentials_iterator.h ccs_list.h \ + ccs_lock.h ccs_lock_state.h ccs_os_notify.h ccs_pipe.h \ + ccs_server.h ccs_types.h +ccs_ccache_iterator.so ccs_ccache_iterator.po $(OUTPRE)ccs_ccache_iterator.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccs_array.h ccs_cache_collection.h ccs_callback.h ccs_ccache.h \ + ccs_ccache_iterator.c ccs_ccache_iterator.h ccs_client.h \ + ccs_common.h ccs_credentials.h ccs_credentials_iterator.h \ + ccs_list.h ccs_lock.h ccs_lock_state.h ccs_pipe.h ccs_server.h \ + ccs_types.h +ccs_client.so ccs_client.po $(OUTPRE)ccs_client.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccs_array.h ccs_cache_collection.h ccs_callback.h ccs_ccache.h \ + ccs_ccache_iterator.h ccs_client.c ccs_client.h ccs_common.h \ + ccs_credentials.h ccs_credentials_iterator.h ccs_list.h \ + ccs_lock.h ccs_lock_state.h ccs_pipe.h ccs_server.h \ + ccs_types.h +ccs_credentials.so ccs_credentials.po $(OUTPRE)ccs_credentials.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccs_array.h ccs_cache_collection.h ccs_callback.h ccs_ccache.h \ + ccs_ccache_iterator.h ccs_client.h ccs_common.h ccs_credentials.c \ + ccs_credentials.h ccs_credentials_iterator.h ccs_list.h \ + ccs_lock.h ccs_lock_state.h ccs_pipe.h ccs_server.h \ + ccs_types.h +ccs_credentials_iterator.so ccs_credentials_iterator.po \ + $(OUTPRE)ccs_credentials_iterator.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccs_array.h ccs_cache_collection.h ccs_callback.h ccs_ccache.h \ + ccs_ccache_iterator.h ccs_client.h ccs_common.h ccs_credentials.h \ + ccs_credentials_iterator.c ccs_credentials_iterator.h \ + ccs_list.h ccs_lock.h ccs_lock_state.h ccs_pipe.h ccs_server.h \ + ccs_types.h +ccs_list.so ccs_list.po $(OUTPRE)ccs_list.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_array_internal.h $(srcdir)/../common/cci_common.h \ + $(srcdir)/../common/cci_cred_union.h $(srcdir)/../common/cci_debugging.h \ + $(srcdir)/../common/cci_identifier.h $(srcdir)/../common/cci_message.h \ + $(srcdir)/../common/cci_types.h ccs_array.h ccs_cache_collection.h \ + ccs_callback.h ccs_ccache.h ccs_ccache_iterator.h ccs_client.h \ + ccs_common.h ccs_credentials.h ccs_credentials_iterator.h \ + ccs_list.c ccs_list.h ccs_list_internal.h ccs_lock.h \ + ccs_lock_state.h ccs_pipe.h ccs_server.h ccs_types.h +ccs_list_internal.so ccs_list_internal.po $(OUTPRE)ccs_list_internal.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_array_internal.h $(srcdir)/../common/cci_common.h \ + $(srcdir)/../common/cci_cred_union.h $(srcdir)/../common/cci_debugging.h \ + $(srcdir)/../common/cci_identifier.h $(srcdir)/../common/cci_message.h \ + $(srcdir)/../common/cci_types.h ccs_array.h ccs_cache_collection.h \ + ccs_callback.h ccs_ccache.h ccs_ccache_iterator.h ccs_client.h \ + ccs_common.h ccs_credentials.h ccs_credentials_iterator.h \ + ccs_list.h ccs_list_internal.c ccs_list_internal.h \ + ccs_lock.h ccs_lock_state.h ccs_pipe.h ccs_server.h \ + ccs_types.h +ccs_lock.so ccs_lock.po $(OUTPRE)ccs_lock.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccs_array.h ccs_cache_collection.h ccs_callback.h ccs_ccache.h \ + ccs_ccache_iterator.h ccs_client.h ccs_common.h ccs_credentials.h \ + ccs_credentials_iterator.h ccs_list.h ccs_lock.c ccs_lock.h \ + ccs_lock_state.h ccs_pipe.h ccs_server.h ccs_types.h +ccs_lock_state.so ccs_lock_state.po $(OUTPRE)ccs_lock_state.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccs_array.h ccs_cache_collection.h ccs_callback.h ccs_ccache.h \ + ccs_ccache_iterator.h ccs_client.h ccs_common.h ccs_credentials.h \ + ccs_credentials_iterator.h ccs_list.h ccs_lock.h ccs_lock_state.c \ + ccs_lock_state.h ccs_pipe.h ccs_server.h ccs_types.h +ccs_pipe.so ccs_pipe.po $(OUTPRE)ccs_pipe.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccs_array.h ccs_cache_collection.h ccs_callback.h ccs_ccache.h \ + ccs_ccache_iterator.h ccs_client.h ccs_common.h ccs_credentials.h \ + ccs_credentials_iterator.h ccs_list.h ccs_lock.h ccs_lock_state.h \ + ccs_os_pipe.h ccs_pipe.c ccs_pipe.h ccs_server.h ccs_types.h +ccs_server.so ccs_server.po $(OUTPRE)ccs_server.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/CredentialsCache2.h $(top_srcdir)/include/k5-ipc_stream.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(srcdir)/../common/cci_common.h $(srcdir)/../common/cci_cred_union.h \ + $(srcdir)/../common/cci_debugging.h $(srcdir)/../common/cci_identifier.h \ + $(srcdir)/../common/cci_message.h $(srcdir)/../common/cci_types.h \ + ccs_array.h ccs_cache_collection.h ccs_callback.h ccs_ccache.h \ + ccs_ccache_iterator.h ccs_client.h ccs_common.h ccs_credentials.h \ + ccs_credentials_iterator.h ccs_list.h ccs_lock.h ccs_lock_state.h \ + ccs_os_server.h ccs_pipe.h ccs_server.c ccs_server.h \ + ccs_types.h diff --git a/krb5-1.21.3/src/ccapi/server/unix/Makefile.in b/krb5-1.21.3/src/ccapi/server/unix/Makefile.in new file mode 100644 index 00000000..b3743f06 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/unix/Makefile.in @@ -0,0 +1,12 @@ +mydir=ccapi$(S)server$(S)unix +BUILDTOP=$(REL)..$(S)..$(S).. + +STLIBOBJS= +OBJS= +SRCS= + +all-unix: all-libobjs +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/ccapi/server/unix/deps b/krb5-1.21.3/src/ccapi/server/unix/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/unix/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/ccapi/server/win/Makefile.in b/krb5-1.21.3/src/ccapi/server/win/Makefile.in new file mode 100644 index 00000000..1c925a28 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/win/Makefile.in @@ -0,0 +1,114 @@ +# makefile: Constructs the Kerberos for Windows CCAPI server. + +#BUILDTOP is krb5/src and is relative to krb5/src/ccapi/server/win, for making Makefile. +BUILDTOP=..\..\.. +CCAPI = $(BUILDTOP)\CCAPI +CO = $(CCAPI)\common +COWIN = $(CCAPI)\common\win +CCUTIL = $(CCAPI)\common\win\OldCC +SRVDIR = $(CCAPI)\server +SRVWIN = $(SRVDIR)\win +POSIX = $(BUILDTOP)\lib\krb5\posix +SRCTMP = $(SRVWIN)\srctmp + +!if defined(KRB5_KFW_COMPILE) +KFWINC= /I$(BUILDTOP)\..\..\krbcc\include +!endif + +OBJS = $(OUTPRE)cci_array_internal.$(OBJEXT) \ + $(OUTPRE)cci_cred_union.$(OBJEXT) \ + $(OUTPRE)cci_debugging.$(OBJEXT) \ + $(OUTPRE)cci_identifier.$(OBJEXT) \ + $(OUTPRE)cci_message.$(OBJEXT) \ + $(OUTPRE)cci_os_debugging.$(OBJEXT) \ + $(OUTPRE)cci_os_identifier.$(OBJEXT) \ + $(OUTPRE)ccs_array.$(OBJEXT) \ + $(OUTPRE)ccs_cache_collection.$(OBJEXT) \ + $(OUTPRE)ccs_callback.$(OBJEXT) \ + $(OUTPRE)ccs_ccache.$(OBJEXT) \ + $(OUTPRE)ccs_ccache_iterator.$(OBJEXT) \ + $(OUTPRE)ccs_client.$(OBJEXT) \ + $(OUTPRE)ccs_credentials.$(OBJEXT) \ + $(OUTPRE)ccs_credentials_iterator.$(OBJEXT) \ + $(OUTPRE)ccs_list.$(OBJEXT) \ + $(OUTPRE)ccs_list_internal.$(OBJEXT) \ + $(OUTPRE)ccs_lock.$(OBJEXT) \ + $(OUTPRE)ccs_lock_state.$(OBJEXT) \ + $(OUTPRE)ccs_os_pipe.$(OBJEXT) \ + $(OUTPRE)ccs_os_server.$(OBJEXT) \ + $(OUTPRE)ccs_pipe.$(OBJEXT) \ + $(OUTPRE)ccs_reply_c.$(OBJEXT) \ + $(OUTPRE)ccs_request_proc.$(OBJEXT) \ + $(OUTPRE)ccs_server.$(OBJEXT) \ + $(OUTPRE)ccs_win_pipe.$(OBJEXT) \ + $(OUTPRE)ccs_request_s.$(OBJEXT) \ + $(OUTPRE)ccutils.$(OBJEXT) \ + $(OUTPRE)init.$(OBJEXT) \ + $(OUTPRE)opts.$(OBJEXT) \ + $(OUTPRE)secure.$(OBJEXT) \ + $(OUTPRE)tls.$(OBJEXT) \ + $(OUTPRE)util.$(OBJEXT) \ + $(OUTPRE)win-utils.$(OBJEXT) \ + $(OUTPRE)WorkItem.$(OBJEXT) \ + $(OUTPRE)WorkQueue.$(OBJEXT) + +##### Options + +# Because all the sources are pulled together into the temp directory SRCTMP, +# the only includes we need are to directories outside of ccapi. +LOCALINCLUDES = /I..\$(BUILDTOP) /I..\$(BUILDTOP)\include /I..\$(BUILDTOP)\include\krb5 $(KFWINC) \ + -I..\$(BUILDTOP)\util\et /I. +MIDLI = /I..\$(BUILDTOP)\include + +CPPFLAGS = $(CPPFLAGS) /EHsc -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 \ +-D_WIN32_WINNT=0x0501 -D_CRT_SECURE_NO_WARNINGS + +##### Linker +LINK = link +LIBS = ..\$(SLIB) rpcrt4.lib advapi32.lib ws2_32.lib user32.lib +LFLAGS = /nologo $(LOPTS) + + +all: Makefile copysrc midl $(OUTPRE)ccapiserver.exe finish + +ccs_request.h ccs_request_c.c ccs_request_s.c : ccs_request.idl ccs_request.acf + midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \ + ccs_request.idl + +ccs_reply.h ccs_reply_c.c ccs_reply_s.c : ccs_reply.idl ccs_reply.acf + midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \ + ccs_reply.idl + +copysrc : + echo "Copying all sources needed to build ccapiserver.exe to $(SRCTMP)" + if NOT exist $(SRCTMP)\nul mkdir $(SRCTMP) + xcopy /D/Y $(CO)\*.* $(SRCTMP) + xcopy /D/Y $(COWIN)\*.* $(SRCTMP) + xcopy /D/Y $(CCUTIL)\*.* $(SRCTMP) + xcopy /D/Y $(SRVDIR)\*.* $(SRCTMP) + xcopy /D/Y $(SRVWIN)\*.* $(SRCTMP) + cd $(SRCTMP) + if NOT exist $(OUTPRE)\nul mkdir $(OUTPRE) + +midl : ccs_request.h ccs_reply.h + +VERSIONRC = $(BUILDTOP)\..\windows\version.rc +CCAPISERVERRES = $(OUTPRE)ccapiserver.res +$(CCAPISERVERRES): $(VERSIONRC) + $(RC) $(RCFLAGS) -DCCAPISERVER_APP -fo $@ -r $** + +$(OUTPRE)ccapiserver.exe: $(OBJS) $(CCAPISERVERRES) + $(LINK) $(LFLAGS) /map:$*.map /out:$@ $(OBJS) $(LIBS) $(CCAPISERVERRES) $(conlibsdll) $(conflags) + +finish : + @echo "Finished building ccapiserver.exe" + cd + +clean: + if exist $(OUTPRE)*.exe del $(OUTPRE)*.exe + if exist $(OUTPRE)*.obj del $(OUTPRE)*.obj + if exist $(OUTPRE)*.res del $(OUTPRE)*.res + if exist $(OUTPRE)*.map del $(OUTPRE)*.map + if exist $(OUTPRE)*.pdb del $(OUTPRE)*.pdb + if exist *.err del *.err + if exist $(SRCTMP) rmdir /s /q $(SRCTMP) diff --git a/krb5-1.21.3/src/ccapi/server/win/Server.sln b/krb5-1.21.3/src/ccapi/server/win/Server.sln new file mode 100644 index 00000000..ea1bd455 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/win/Server.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "Server.vcproj", "{114DCD80-6D13-4AAA-9510-B51CE6D94C1C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Debug|Win32.ActiveCfg = Debug|Win32 + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Debug|Win32.Build.0 = Debug|Win32 + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Release|Win32.ActiveCfg = Release|Win32 + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/krb5-1.21.3/src/ccapi/server/win/Server.vcproj b/krb5-1.21.3/src/ccapi/server/win/Server.vcproj new file mode 100644 index 00000000..626c7a3c --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/win/Server.vcproj @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/krb5-1.21.3/src/ccapi/server/win/WorkItem.cpp b/krb5-1.21.3/src/ccapi/server/win/WorkItem.cpp new file mode 100644 index 00000000..79a34873 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/win/WorkItem.cpp @@ -0,0 +1,142 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include "assert.h" + +#pragma warning (disable : 4996) + +#include "win-utils.h" +#include "WorkItem.h" + +extern "C" { +#include "cci_debugging.h" + } + +// CountedBuffer makes a copy of the data. Each CountedBuffer must be deleted. + +void deleteBuffer(char** buf) { + if (*buf) { + delete [](*buf); + *buf = NULL; + } + } + +// WorkItem contains a CountedBuffer which must be deleted, +// so each WorkItem must be deleted. +WorkItem::WorkItem(k5_ipc_stream buf, WIN_PIPE* pipe, const long type, const long sst) +: _buf(buf), _rpcmsg(type), _pipe(pipe), _sst(sst) { } + +WorkItem::WorkItem(const WorkItem& item) : _buf(NULL), _rpcmsg(0), _pipe(NULL), _sst(0) { + + k5_ipc_stream _buf = NULL; + krb5int_ipc_stream_new(&_buf); + krb5int_ipc_stream_write(_buf, + krb5int_ipc_stream_data(item.payload()), + krb5int_ipc_stream_size(item.payload()) ); + WorkItem(_buf, item._pipe, item._rpcmsg, item._sst); + } + +WorkItem::WorkItem() : _buf(NULL), _rpcmsg(CCMSG_INVALID), _pipe(NULL), _sst(0) { } + +WorkItem::~WorkItem() { + if (_buf) krb5int_ipc_stream_release(_buf); + if (_pipe) ccs_win_pipe_release(_pipe); + } + +const k5_ipc_stream WorkItem::take_payload() { + k5_ipc_stream temp = payload(); + _buf = NULL; + return temp; + } + +WIN_PIPE* WorkItem::take_pipe() { + WIN_PIPE* temp = pipe(); + _pipe = NULL; + return temp; + } + +WorkList::WorkList() { + assert(InitializeCriticalSectionAndSpinCount(&cs, 0x80000400)); + } + +WorkList::~WorkList() { + // Delete any WorkItems in the queue: + WorkItem* item; + cci_debug_printf("%s", __FUNCTION__); + char buf[2048]; + char* pbuf = (char*)buf; + while (remove(&item)) { + cci_debug_printf("WorkList::~WorkList() deleting %s", item->print(pbuf)); + delete item; + } + + DeleteCriticalSection(&cs); + } + +char* WorkItem::print(char* buf) { + sprintf(buf, "WorkItem msg#:%d sst:%ld pipe:<%s>/0x%X", _rpcmsg, _sst, + ccs_win_pipe_getUuid(_pipe), ccs_win_pipe_getHandle(_pipe)); + return buf; + } + +int WorkList::initialize() { + hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + return 0; + } + +int WorkList::cleanup() { + CloseHandle(hEvent); + hEvent = INVALID_HANDLE_VALUE; + return 0; + } + +void WorkList::wait() { + WaitForSingleObject(hEvent, INFINITE); + } + +int WorkList::add(WorkItem* item) { + EnterCriticalSection(&cs); + wl.push_front(item); + LeaveCriticalSection(&cs); + SetEvent(hEvent); + return 1; + } + +int WorkList::remove(WorkItem** item) { + bool bEmpty; + + bEmpty = wl.empty() & 1; + + if (!bEmpty) { + EnterCriticalSection(&cs); + *item = wl.back(); + wl.pop_back(); + LeaveCriticalSection(&cs); + } + + return !bEmpty; + } diff --git a/krb5-1.21.3/src/ccapi/server/win/WorkQueue.cpp b/krb5-1.21.3/src/ccapi/server/win/WorkQueue.cpp new file mode 100644 index 00000000..fc5fa7e1 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/win/WorkQueue.cpp @@ -0,0 +1,74 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "WorkQueue.h" +extern "C" { + #include "cci_debugging.h" + } + +#include "WorkItem.h" + +WorkList worklist; + +EXTERN_C int worklist_initialize() { + return worklist.initialize(); + } + +EXTERN_C int worklist_cleanup() { + return worklist.cleanup(); + } + +EXTERN_C void worklist_wait() { + worklist.wait(); + } + +/* C interfaces: */ +EXTERN_C BOOL worklist_isEmpty() { + return worklist.isEmpty() ? TRUE : FALSE; + } + +EXTERN_C int worklist_add( const long rpcmsg, + const ccs_pipe_t pipe, + const k5_ipc_stream stream, + const time_t serverStartTime) { + return worklist.add(new WorkItem(stream, pipe, rpcmsg, serverStartTime) ); + } + +EXTERN_C int worklist_remove(long* rpcmsg, + ccs_pipe_t* pipe, + k5_ipc_stream* stream, + time_t* sst) { + WorkItem* item = NULL; + cc_int32 err = worklist.remove(&item); + + *rpcmsg = item->type(); + *pipe = item->take_pipe(); + *stream = item->take_payload(); + *sst = item->sst(); + delete item; + return err; + } + diff --git a/krb5-1.21.3/src/ccapi/server/win/WorkQueue.h b/krb5-1.21.3/src/ccapi/server/win/WorkQueue.h new file mode 100644 index 00000000..68aa8b1c --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/win/WorkQueue.h @@ -0,0 +1,51 @@ +/* ccapi/server/win/WorkQueue.h */ +/* + * Copyright 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef _work_queue_h +#define _work_queue_h + +#include "windows.h" +#include "ccs_pipe.h" + +EXTERN_C int worklist_initialize(); + +EXTERN_C int worklist_cleanup(); + +/* Wait for work to be added to the list (via worklist_add) from another thread */ +EXTERN_C void worklist_wait(); + +EXTERN_C BOOL worklist_isEmpty(); + +EXTERN_C int worklist_add( const long rpcmsg, + const ccs_pipe_t pipe, + const k5_ipc_stream stream, + const time_t serverStartTime); + +EXTERN_C int worklist_remove(long* rpcmsg, + ccs_pipe_t* pipe, + k5_ipc_stream* stream, + time_t* serverStartTime); + +#endif // _work_queue_h diff --git a/krb5-1.21.3/src/ccapi/server/win/ccs_os_pipe.c b/krb5-1.21.3/src/ccapi/server/win/ccs_os_pipe.c new file mode 100644 index 00000000..7e190cee --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/win/ccs_os_pipe.c @@ -0,0 +1,62 @@ +/* ccapi/server/win/ccs_os_pipe.c */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" +#include "ccs_os_pipe.h" +#include "ccs_win_pipe.h" + +/* ------------------------------------------------------------------------ */ + +/* On Windows, a pipe is a struct. See ccs_win_pipe.h for details. */ + + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_valid (ccs_pipe_t in_pipe) { + return ccs_win_pipe_valid(in_pipe); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_copy (ccs_pipe_t* out_pipe, ccs_pipe_t in_pipe) { + return ccs_win_pipe_copy( + out_pipe, + in_pipe); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_release (ccs_pipe_t io_pipe) { + return ccs_win_pipe_release(io_pipe); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_compare (ccs_pipe_t pipe_1, + ccs_pipe_t pipe_2, + cc_uint32 *out_equal) { + + return ccs_win_pipe_compare(pipe_1, pipe_2, out_equal); + } diff --git a/krb5-1.21.3/src/ccapi/server/win/ccs_os_server.cpp b/krb5-1.21.3/src/ccapi/server/win/ccs_os_server.cpp new file mode 100644 index 00000000..1b54718a --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/win/ccs_os_server.cpp @@ -0,0 +1,950 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "process.h" +#include "windows.h" + +extern "C" { +#include "ccs_common.h" +#include "ccs_os_notify.h" +#include "ccs_os_server.h" +#include "ccs_reply.h" +#include "ccs_request.h" +#include "win-utils.h" +#include "ccutils.h" + } + +#include "WorkQueue.h" +#include "util.h" +#include "opts.hxx" +#include "init.hxx" + +#pragma warning (disable : 4996) + +BOOL bListen = TRUE; /* Why aren't bool and true defined? */ +const char* sessID = NULL; /* The logon session we are running on behalf of. */ +time_t _sst = 0; +unsigned char* pszNetworkAddress = NULL; +unsigned char* pszStringBinding = NULL; +BOOL bRpcHandleInited = FALSE; +_RPC_ASYNC_STATE* rpcState = NULL; + +/* Thread procedures can take only one void* argument. We put all the args we want + to pass into this struct and then pass a pointer to the struct: */ +struct RpcRcvArgs { + char* networkAddress; + unsigned char* protocolSequence; + unsigned char* sessID; /* Used for this server's endpoint */ + unsigned char* uuid; /* Used for client's UUID */ + ParseOpts::Opts* opts; + RPC_STATUS status; + } rpcargs = { NULL, /* pszNetworkAddress */ + (unsigned char*)"ncalrpc", /* pszProtocolSequence */ + NULL, /* sessID placeholder */ + NULL, /* uuid placeholder */ + NULL }; /* Opts placeholder */ + +/* Command line format: + argv[0] Program name + argv[1] session ID to use + argv[2] "D" Debug: go into infinite loop in ccs_os_server_initialize so process + can be attached in debugger. + Any other value: continue + */ +#define N_FIXED_ARGS 3 +#define SERVER_REPLY_RPC_HANDLE ccs_reply_IfHandle + +/* Forward declarations: */ +void receiveLoop(void* rpcargs); +void connectionListener(void* rpcargs); +void Usage(const char* argv0); +void printError(TCHAR* msg); +void setMySST() {_sst = time(&_sst);} +time_t getMySST() {return _sst;} +RPC_STATUS send_connection_reply(ccs_pipe_t in_pipe); +void RPC_ENTRY clientListener( _RPC_ASYNC_STATE*, + void* Context, + RPC_ASYNC_EVENT Event); +RPC_STATUS RPC_ENTRY sec_callback( IN RPC_IF_ID *Interface, + IN void *Context); +RPC_STATUS send_init(char* clientUUID); +//DWORD alloc_name(LPSTR* pname, LPSTR postfix); + + +/* The layout of the rest of this module: + + The four entrypoints defined in ccs_os_server.h: + ccs_os_server_initialize + cc_int32 ccs_os_server_cleanup + cc_int32 ccs_os_server_listen_loop + cc_int32 ccs_os_server_send_reply + + Other routines needed by those four. + */ + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_initialize (int argc, const char *argv[]) { + cc_int32 err = 0; + ParseOpts::Opts opts = { 0 }; + ParseOpts PO; + BOOL bAdjustedShutdown = FALSE; + HMODULE hKernel32 = GetModuleHandle("kernel32"); + + if (!err) { + sessID = argv[1]; + setMySST(); + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + +#ifdef CCAPI_TEST_OPTIONS + PO.SetValidOpts("kemnfubc"); +#else + PO.SetValidOpts("kc"); +#endif + + PO.Parse(opts, argc, (char**)argv); + +// while(*argv[2] == 'D') {} /* Hang here to attach process with debugger. */ + + if (hKernel32) { + typedef BOOL (WINAPI *FP_SetProcessShutdownParameters)(DWORD, DWORD); + FP_SetProcessShutdownParameters pSetProcessShutdownParameters = + (FP_SetProcessShutdownParameters) + GetProcAddress(hKernel32, "SetProcessShutdownParameters"); + if (pSetProcessShutdownParameters) { + bAdjustedShutdown = pSetProcessShutdownParameters(100, 0); + } + } + cci_debug_printf("%s Shutdown Parameters", + bAdjustedShutdown ? "Adjusted" : "Did not adjust"); + + err = Init::Initialize(); + } + +// if (!err) { +// if (opts.bShutdown) { +// status = shutdown_server(opts.pszEndpoint); +// } +// } +// else { +// status = startup_server(opts); +// } + + if (!err) { + err = worklist_initialize(); + } + + if (err) { + Init::Cleanup(); + fprintf( stderr, "An error occurred while %s the server (%u)\n", + opts.bShutdown ? "shutting down" : "starting/running", + err); + exit(cci_check_error (err)); + } + + return cci_check_error (err); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_cleanup (int argc, const char *argv[]) { + cc_int32 err = 0; + + cci_debug_printf("%s for user <%s> shutting down.", argv[0], argv[1]); + + worklist_cleanup(); + + return cci_check_error (err); + } + +/* ------------------------------------------------------------------------ */ + +/* This function takes work items off the work queue and executes them. + * This is the one and only place where the multi-threaded Windows code + * calls into the single-threaded common code. + * + * The actual 'listening' for requests from clients happens after receiveloop + * establishes the RPC endpoint the clients will connect to and the RPC procedures + * put the work items into the work queue. + */ +cc_int32 ccs_os_server_listen_loop (int argc, const char *argv[]) { + cc_int32 err = 0; + uintptr_t threadStatus; + + ParseOpts::Opts opts = { 0 }; + ParseOpts PO; + BOOL bQuitIfNoClients = FALSE; + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + +#ifdef CCAPI_TEST_OPTIONS + PO.SetValidOpts("kemnfubc"); +#else + PO.SetValidOpts("kc"); +#endif + PO.Parse(opts, argc, (char**)argv); + + + //++ debug stuff + #define INFO_BUFFER_SIZE 32767 + TCHAR infoBuf[INFO_BUFFER_SIZE]; + DWORD bufCharCount = INFO_BUFFER_SIZE; + // Get and display the user name. + bufCharCount = INFO_BUFFER_SIZE; + if( !GetUserName( infoBuf, &bufCharCount ) ) printError( TEXT("GetUserName") ); + //-- + + /* Sending the reply from within the request RPC handler doesn't seem to work. + So we listen for requests in a separate thread and put the requests in a + queue. */ + rpcargs.sessID = (unsigned char*)sessID; + rpcargs.opts = &opts; + /// TODO: check for NULL handle, error, etc. probably move to initialize func... + threadStatus = _beginthread(receiveLoop, 0, (void*)&rpcargs); + + /* We handle the queue entries here. Work loop: */ + while (ccs_server_client_count() > 0 || !bQuitIfNoClients) { + worklist_wait(); + while (!worklist_isEmpty()) { + k5_ipc_stream buf = NULL; + long rpcmsg = CCMSG_INVALID; + time_t serverStartTime = 0xDEADDEAD; + RPC_STATUS status = 0; + char* uuid = NULL; + k5_ipc_stream stream = NULL; + ccs_pipe_t pipe = NULL; + ccs_pipe_t pipe2 = NULL; + + if (worklist_remove(&rpcmsg, &pipe, &buf, &serverStartTime)) { + uuid = ccs_win_pipe_getUuid(pipe); + + if (serverStartTime <= getMySST()) { + switch (rpcmsg) { + case CCMSG_CONNECT: { + cci_debug_printf(" Processing CONNECT"); + rpcargs.uuid = (unsigned char*)uuid; + + // Even if a disconnect message is received before this code finishes, + // it won't be dequeued and processed until after this code finishes. + // So we can add the client after starting the connection listener. + connectionListener((void*)&rpcargs); + status = rpcargs.status; + + if (!status) { + status = ccs_server_add_client(pipe); + } + if (!status) {status = send_connection_reply(pipe);} + break; + } + case CCMSG_DISCONNECT: { + cci_debug_printf(" Processing DISCONNECT"); + if (!status) { + status = ccs_server_remove_client(pipe); + } + break; + } + case CCMSG_REQUEST: + cci_debug_printf(" Processing REQUEST"); + ccs_pipe_copy(&pipe2, pipe); + // Dispatch message here, setting both pipes to the client UUID: + err = ccs_server_handle_request (pipe, pipe2, buf); + break; + case CCMSG_PING: + cci_debug_printf(" Processing PING"); + err = krb5int_ipc_stream_new (&stream); + err = krb5int_ipc_stream_write(stream, "This is a test of the emergency broadcasting system", 52); + err = ccs_os_server_send_reply(pipe, stream); + break; + case CCMSG_QUIT: + bQuitIfNoClients = TRUE; + break; + default: + cci_debug_printf("Huh? Received invalid message type %ld from UUID:<%s>", + rpcmsg, uuid); + break; + } + if (buf) krb5int_ipc_stream_release(buf); + /* Don't free uuid, which was allocated here. A pointer to it is in the + rpcargs struct which was passed to connectionListener which will be + received by ccapi_listen when the client exits. ccapi_listen needs + the uuid to know which client to disconnect. + */ + } + // Server's start time is different from what the client thinks. + // That means the server has rebooted since the client connected. + else { + cci_debug_printf("Whoops! Server has rebooted since client established connection."); + } + } + else {cci_debug_printf("Huh? Queue not empty but no item to remove.");} + } + } + return cci_check_error (err); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_send_reply (ccs_pipe_t in_pipe, + k5_ipc_stream in_reply_stream) { + + /* ccs_pipe_t in_reply_pipe is a char* reply endpoint. + k5_ipc_stream in_reply_stream is the data to be sent. + */ + + cc_int32 err = 0; + char* uuid = ccs_win_pipe_getUuid(in_pipe); + UINT64 h = ccs_win_pipe_getHandle(in_pipe); + + if (!err) { + err = send_init(uuid); // Sets RPC handle to be used. + } + + if (!err) { + RpcTryExcept { + long status; + ccs_rpc_request_reply( // make call with user message + CCMSG_REQUEST_REPLY, /* Message type */ + (unsigned char*)&h, /* client's tspdata* */ + (unsigned char*)uuid, + getMySST(), + krb5int_ipc_stream_size(in_reply_stream), /* Length of buffer */ + (const unsigned char*)krb5int_ipc_stream_data(in_reply_stream), /* Data buffer */ + &status ); /* Return code */ + } + RpcExcept(1) { + cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + } + + /* The calls to the remote procedures are complete. */ + /* Free whatever we allocated: */ + err = RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); + + return cci_check_error (err); + } + + +/* Windows-specific routines: */ + +void Usage(const char* argv0) { + printf("Usage:\n"); + printf("%s [m maxcalls] [n mincalls] [f dontwait] [h|?]]\n", argv0); + printf(" CCAPI server process.\n"); + printf(" h|? whow usage message. <\n"); + } + +/* ------------------------------------------------------------------------ */ +/* The receive thread repeatedly issues RpcServerListen. + When a message arrives, it is handled in the RPC procedure. + */ +void receiveLoop(void* rpcargs) { + + struct RpcRcvArgs* rcvargs = (struct RpcRcvArgs*)rpcargs; + RPC_STATUS status = FALSE; + unsigned char* pszSecurity = NULL; + LPSTR endpoint = NULL; + LPSTR event_name = NULL; + PSECURITY_DESCRIPTOR psd = NULL; + HANDLE hEvent = 0; + Init::InitInfo info; + + cci_debug_printf("THREAD BEGIN: %s", __FUNCTION__); + + status = Init::Info(info); + + /* Build complete RPC endpoint using previous CCAPI implementation: */ + if (!status) { + if (!rcvargs->opts->pszEndpoint) { + if (!status) { + status = alloc_name(&endpoint, "ep", isNT()); + } + + if (!status) { + status = alloc_name(&event_name, "startup", isNT()); + } + + if (!status) { + hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name); + // We ignore any error opening the event because we do not know who started us. + // [Comment paraphrased from previous implementation, whence it was copied.] + } + } + else { + endpoint = rcvargs->opts->pszEndpoint; + } + } + + cci_debug_printf("%s Registering endpoint %s", __FUNCTION__, endpoint); + + if (!status && isNT()) { + status = alloc_own_security_descriptor_NT(&psd); + } + + if (!status) { + status = RpcServerUseProtseqEp(rcvargs->protocolSequence, + rcvargs->opts->cMaxCalls, + (RPC_CSTR)endpoint, + rcvargs->opts->bDontProtect ? 0 : psd); // SD + } + + if (!status) { + status = RpcServerRegisterAuthInfo(0, // server principal + RPC_C_AUTHN_WINNT, + 0, + 0); + } + + while (bListen && !status) { + cci_debug_printf("%s is listening ...", __FUNCTION__); + + if (!info.isNT) { + status = RpcServerRegisterIf(ccs_request_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL); // MgrEpv; null means use default + } + else { + status = info.fRpcServerRegisterIfEx(ccs_request_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL, // MgrEpv; 0 means default + RPC_IF_ALLOW_SECURE_ONLY, + rcvargs->opts->cMaxCalls, + rcvargs->opts->bSecCallback ? + (RPC_IF_CALLBACK_FN*)sec_callback : 0 ); + } + + if (!status) { + status = RpcServerListen(rcvargs->opts->cMinCalls, + rcvargs->opts->cMaxCalls, + rcvargs->opts->fDontWait); + } + + if (!status) { + if (rcvargs->opts->fDontWait) { + if (hEvent) SetEvent(hEvent); // Ignore any error -- SetEvent is an optimization. + status = RpcMgmtWaitServerListen(); + } + } + } + + if (status) { // Cleanup in case of errors: + if (hEvent) CloseHandle(hEvent); + free_alloc_p(&event_name); + free_alloc_p(&psd); + if (endpoint && (endpoint != rcvargs->opts->pszEndpoint)) + free_alloc_p(&endpoint); + } + + // tell main thread to shutdown since it won't receive any more messages + worklist_add(CCMSG_QUIT, NULL, NULL, 0); + _endthread(); + } // End receiveLoop + + + +/* ------------------------------------------------------------------------ */ +/* The connection listener thread waits forever for a call to the CCAPI_CLIENT_ + endpoint, ccapi_listen function to complete. If the call completes or gets an + RPC exception, it means the client has disappeared. + + A separate connectionListener is started for each client that has connected to the server. + */ + +void connectionListener(void* rpcargs) { + + struct RpcRcvArgs* rcvargs = (struct RpcRcvArgs*)rpcargs; + RPC_STATUS status = FALSE; + char* endpoint; + unsigned char* pszOptions = NULL; + unsigned char * pszUuid = NULL; + + endpoint = clientEndpoint((char*)rcvargs->uuid); + rpcState = (RPC_ASYNC_STATE*)malloc(sizeof(RPC_ASYNC_STATE)); + status = RpcAsyncInitializeHandle(rpcState, sizeof(RPC_ASYNC_STATE)); + cci_debug_printf(""); + cci_debug_printf("%s About to LISTEN to <%s>", __FUNCTION__, endpoint); + + rpcState->UserInfo = rcvargs->uuid; + rpcState->NotificationType = RpcNotificationTypeApc; + rpcState->u.APC.NotificationRoutine = clientListener; + rpcState->u.APC.hThread = 0; + + /* [If in use] Free previous binding: */ + if (bRpcHandleInited) { + // Free previous binding (could have been used to call ccapi_listen + // in a different client thread). + // Don't check result or update status. + RpcStringFree(&pszStringBinding); + RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); + bRpcHandleInited = FALSE; + } + + /* Set up binding to the client's endpoint: */ + if (!status) { + status = RpcStringBindingCompose( + pszUuid, + pszProtocolSequence, + pszNetworkAddress, + (RPC_CSTR)endpoint, + pszOptions, + &pszStringBinding); + } + + /* Set the binding handle that will be used to bind to the server. */ + if (!status) { + status = RpcBindingFromStringBinding(pszStringBinding, &SERVER_REPLY_RPC_HANDLE); + } + if (!status) {bRpcHandleInited = TRUE;} + + RpcTryExcept { + cci_debug_printf(" Calling remote procedure ccapi_listen"); + ccapi_listen(rpcState, SERVER_REPLY_RPC_HANDLE, CCMSG_LISTEN, &status); + /* Asynchronous call will return immediately. */ + } + RpcExcept(1) { + status = cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + + rcvargs->status = status; + } // End connectionListener + + +void RPC_ENTRY clientListener( + _RPC_ASYNC_STATE* pAsync, + void* Context, + RPC_ASYNC_EVENT Event + ) { + + ccs_pipe_t pipe = ccs_win_pipe_new((char*)pAsync->UserInfo, NULL); + + cci_debug_printf("%s(0x%X, ...) async routine for <0x%X:%s>!", + __FUNCTION__, pAsync, pAsync->UserInfo, pAsync->UserInfo); + + worklist_add( CCMSG_DISCONNECT, + pipe, + NULL, /* No payload with connect request */ + (const time_t)0 ); /* No server session number with connect request */ + } + + +void printError( TCHAR* msg ) { + DWORD eNum; + TCHAR sysMsg[256]; + TCHAR* p; + + eNum = GetLastError( ); + FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, eNum, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + sysMsg, 256, NULL ); + + // Trim the end of the line and terminate it with a null + p = sysMsg; + while( ( *p > 31 ) || ( *p == 9 ) ) + ++p; + do { *p-- = 0; } while( ( p >= sysMsg ) && + ( ( *p == '.' ) || ( *p < 33 ) ) ); + + // Display the message + cci_debug_printf("%s failed with error %d (%s)", msg, eNum, sysMsg); + } + + +RPC_STATUS send_init(char* clientUUID) { + RPC_STATUS status; + unsigned char * pszUuid = NULL; + unsigned char * pszOptions = NULL; + + /* Use a convenience function to concatenate the elements of */ + /* the string binding into the proper sequence. */ + status = RpcStringBindingCompose(pszUuid, + pszProtocolSequence, + pszNetworkAddress, + (unsigned char*)clientEndpoint(clientUUID), + pszOptions, + &pszStringBinding); + if (status) {return (status);} + + /* Set the binding handle that will be used to bind to the RPC server [the 'client']. */ + status = RpcBindingFromStringBinding(pszStringBinding, &SERVER_REPLY_RPC_HANDLE); + return (status); + } + +RPC_STATUS send_finish() { + RPC_STATUS status; + /* Can't shut down client -- it runs listen function which */ + /* server uses to detect the client going away. */ + + /* The calls to the remote procedures are complete. */ + /* Free the string and the binding handle */ + status = RpcStringFree(&pszStringBinding); // remote calls done; unbind + if (status) {return (status);} + + status = RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); // remote calls done; unbind + + return (status); + } + +RPC_STATUS send_connection_reply(ccs_pipe_t in_pipe) { + char* uuid = ccs_win_pipe_getUuid (in_pipe); + UINT64 h = ccs_win_pipe_getHandle(in_pipe); + RPC_STATUS status = send_init(uuid); + + RpcTryExcept { + ccs_rpc_connect_reply( // make call with user message + CCMSG_CONNECT_REPLY, /* Message type */ + (unsigned char*)&h, /* client's tspdata* */ + (unsigned char*)uuid, + getMySST(), /* Server's session number = its start time */ + &status ); /* Return code */ + } + RpcExcept(1) { + cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + + status = send_finish(); + return (status); + } + +RPC_STATUS GetPeerName( RPC_BINDING_HANDLE hClient, + LPTSTR pszClientName, + int iMaxLen) { + RPC_STATUS Status = RPC_S_OK; + RPC_BINDING_HANDLE hServer = NULL; + PTBYTE pszStringBinding = NULL; + PTBYTE pszClientNetAddr = NULL; + PTBYTE pszProtSequence = NULL; + + memset(pszClientName, 0, iMaxLen * sizeof(TCHAR)); + + __try { + // Create a partially bound server handle from the client handle. + Status = RpcBindingServerFromClient (hClient, &hServer); + if (Status != RPC_S_OK) __leave; + + // Get the partially bound server string binding and parse it. + Status = RpcBindingToStringBinding (hServer, + &pszStringBinding); + if (Status != RPC_S_OK) __leave; + + // String binding only contains protocol sequence and client + // address, and is not currently implemented for named pipes. + Status = RpcStringBindingParse (pszStringBinding, NULL, + &pszProtSequence, &pszClientNetAddr, + NULL, NULL); + if (Status != RPC_S_OK) + __leave; + int iLen = lstrlen(pszClientName) + 1; + if (iMaxLen < iLen) + Status = RPC_S_BUFFER_TOO_SMALL; + lstrcpyn(pszClientName, (LPCTSTR)pszClientNetAddr, iMaxLen); + } + __finally { + if (pszProtSequence) + RpcStringFree (&pszProtSequence); + + if (pszClientNetAddr) + RpcStringFree (&pszClientNetAddr); + + if (pszStringBinding) + RpcStringFree (&pszStringBinding); + + if (hServer) + RpcBindingFree (&hServer); + } + return Status; +} + +struct client_auth_info { + RPC_AUTHZ_HANDLE authz_handle; + unsigned char* server_principal; // need to RpcFreeString this + ULONG authn_level; + ULONG authn_svc; + ULONG authz_svc; +}; + +RPC_STATUS +GetClientId( + RPC_BINDING_HANDLE hClient, + char* client_id, + int max_len, + client_auth_info* info + ) +{ + RPC_AUTHZ_HANDLE authz_handle = 0; + unsigned char* server_principal = 0; + ULONG authn_level = 0; + ULONG authn_svc = 0; + ULONG authz_svc = 0; + RPC_STATUS status = 0; + + memset(client_id, 0, max_len); + + if (info) { + memset(info, 0, sizeof(client_auth_info)); + } + + status = RpcBindingInqAuthClient(hClient, &authz_handle, + info ? &server_principal : 0, + &authn_level, &authn_svc, &authz_svc); + if (status == RPC_S_OK) + { + if (info) { + info->server_principal = server_principal; + info->authz_handle = authz_handle; + info->authn_level = authn_level; + info->authn_svc = authn_svc; + info->authz_svc = authz_svc; + } + + if (authn_svc == RPC_C_AUTHN_WINNT) { + WCHAR* username = (WCHAR*)authz_handle; + int len = lstrlenW(username) + 1; + if (max_len < len) + status = RPC_S_BUFFER_TOO_SMALL; + _snprintf(client_id, max_len, "%S", username); + } else { + status = RPC_S_UNKNOWN_AUTHN_SERVICE; + } + } + return status; +} + +char* +rpc_error_to_string( + RPC_STATUS status + ) +{ + switch(status) { + case RPC_S_OK: + return "OK"; + case RPC_S_INVALID_BINDING: + return "Invalid binding"; + case RPC_S_WRONG_KIND_OF_BINDING: + return "Wrong binding"; + case RPC_S_BINDING_HAS_NO_AUTH: + RpcRaiseException(RPC_S_BINDING_HAS_NO_AUTH); + return "Binding has no auth"; + default: + return "BUG: I am confused"; + } +} + +void +print_client_info( + RPC_STATUS peer_status, + const char* peer_name, + RPC_STATUS client_status, + const char* client_id, + client_auth_info* info + ) +{ + if (peer_status == RPC_S_OK || peer_status == RPC_S_BUFFER_TOO_SMALL) { + cci_debug_printf("%s Peer Name is \"%s\"", __FUNCTION__, peer_name); + } else { + cci_debug_printf("%s Error %u getting Peer Name (%s)", + __FUNCTION__, peer_status, rpc_error_to_string(peer_status)); + } + + if (client_status == RPC_S_OK || client_status == RPC_S_BUFFER_TOO_SMALL) { + if (info) { + cci_debug_printf("%s Client Auth Info" + "\tServer Principal: %s\n" + "\tAuthentication Level: %d\n" + "\tAuthentication Service: %d\n" + "\tAuthorization Service: %d\n", + __FUNCTION__, + info->server_principal, + info->authn_level, + info->authn_svc, + info->authz_svc); + } + cci_debug_printf("%s Client ID is \"%s\"", __FUNCTION__, client_id); + } else { + cci_debug_printf("%s Error getting Client Info (%u = %s)", + __FUNCTION__, client_status, rpc_error_to_string(client_status)); + } +} + +DWORD sid_check() { + DWORD status = 0; + HANDLE hToken_c = 0; + HANDLE hToken_s = 0; + PTOKEN_USER ptu_c = 0; + PTOKEN_USER ptu_s = 0; + DWORD len = 0; + BOOL bImpersonate = FALSE; + + // Note GetUserName will fail while impersonating at identify + // level. The workaround is to impersonate, OpenThreadToken, + // revert, call GetTokenInformation, and finally, call + // LookupAccountSid. + + // XXX - Note: This workaround does not appear to work. + // OpenThreadToken fails with error 1346: "Either a requid + // impersonation level was not provided or the provided + // impersonation level is invalid". + + status = RpcImpersonateClient(0); + + if (!status) { + bImpersonate = TRUE; + if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken_c)) + status = GetLastError(); + } + + if (!status) { + status = RpcRevertToSelf(); + } + + if (!status) { + bImpersonate = FALSE; + + len = 0; + GetTokenInformation(hToken_c, TokenUser, ptu_c, 0, &len); + if (len == 0) status = 1; + } + + if (!status) { + if (!(ptu_c = (PTOKEN_USER)LocalAlloc(0, len))) + status = GetLastError(); + } + + if (!status) { + if (!GetTokenInformation(hToken_c, TokenUser, ptu_c, len, &len)) + status = GetLastError(); + } + + if (!status) { + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken_s)) + status = GetLastError(); + } + + if (!status) { + len = 0; + GetTokenInformation(hToken_s, TokenUser, ptu_s, 0, &len); + if (len == 0) status = GetLastError(); + } + + if (!status) { + if (!(ptu_s = (PTOKEN_USER)LocalAlloc(0, len))) + status = GetLastError(); + } + + if (!status) { + if (!GetTokenInformation(hToken_s, TokenUser, ptu_s, len, &len)) + status = GetLastError(); + } + + if (!EqualSid(ptu_s->User.Sid, ptu_c->User.Sid)) + status = RPC_S_ACCESS_DENIED; + +/* Cleanup: */ + if (!hToken_c && !bImpersonate) + cci_debug_printf("%s Cannot impersonate (%u)", __FUNCTION__, status); + else if (!hToken_c) + cci_debug_printf("%s Failed to open client token (%u)", __FUNCTION__, status); + else if (bImpersonate) + cci_debug_printf("%s Failed to revert (%u)", __FUNCTION__, status); + else if (!ptu_c) + cci_debug_printf("%s Failed to get client token user info (%u)", + __FUNCTION__, status); + else if (!hToken_s) + cci_debug_printf("%s Failed to open server token (%u)", __FUNCTION__, status); + else if (!ptu_s) + cci_debug_printf("%s Failed to get server token user info (%u)", + __FUNCTION__, status); + else if (status == RPC_S_ACCESS_DENIED) + cci_debug_printf("%s SID **does not** match!", __FUNCTION__); + else if (status == RPC_S_OK) + cci_debug_printf("%s SID matches!", __FUNCTION__); + else + if (status) { + cci_debug_printf("%s unrecognized error %u", __FUNCTION__, status); + abort(); + } + + if (bImpersonate) RpcRevertToSelf(); + if (hToken_c && hToken_c != INVALID_HANDLE_VALUE) + CloseHandle(hToken_c); + if (ptu_c) LocalFree(ptu_c); + if (hToken_s && hToken_s != INVALID_HANDLE_VALUE) + CloseHandle(hToken_s); + if (ptu_s) LocalFree(ptu_s); + if (status) cci_debug_printf("%s returning %u", __FUNCTION__, status); + return status; + } + +RPC_STATUS RPC_ENTRY sec_callback( IN RPC_IF_ID *Interface, + IN void *Context) { + char peer_name[1024]; + char client_name[1024]; + RPC_STATUS peer_status; + RPC_STATUS client_status; + + cci_debug_printf("%s", __FUNCTION__); + peer_status = GetPeerName(Context, peer_name, sizeof(peer_name)); + client_status = GetClientId(Context, client_name, sizeof(client_name), 0); + print_client_info(peer_status, peer_name, client_status, client_name, 0); + DWORD sid_status = sid_check(); + cci_debug_printf("%s returning (%u)", __FUNCTION__, sid_status); + return sid_status; + } + + + +/*********************************************************************/ +/* MIDL allocate and free */ +/*********************************************************************/ + +extern "C" void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { + return(malloc(len)); + } + +extern "C" void __RPC_USER midl_user_free(void __RPC_FAR * ptr) { + free(ptr); + } + +/* stubs */ +extern "C" cc_int32 +ccs_os_notify_cache_collection_changed (ccs_cache_collection_t cc) +{ + return 0; +} + +extern "C" cc_int32 +ccs_os_notify_ccache_changed (ccs_cache_collection_t cc, const char *name) +{ + return 0; +} diff --git a/krb5-1.21.3/src/ccapi/server/win/ccs_request_proc.c b/krb5-1.21.3/src/ccapi/server/win/ccs_request_proc.c new file mode 100644 index 00000000..c0328ea7 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/win/ccs_request_proc.c @@ -0,0 +1,108 @@ +/* ccapi/server/win/ccs_request_proc.c */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include + +#include "ccs_request.h" // header file generated by MIDL compiler +#include "cci_debugging.h" +#include "WorkQueue.h" +#include "win-utils.h" +#include "ccs_win_pipe.h" + +void ccs_rpc_request( + const long rpcmsg, /* Message type */ + const char tspHandle[], /* Client's tspdata* */ + const char* pszUUID, /* Where client will listen for the reply */ + const long lenRequest, /* Length of buffer */ + const char pbRequest[], /* Data buffer */ + const long serverStartTime, /* Which server session we're talking to */ + long* return_status ) { /* Return code */ + + cc_int32 status = 0; + k5_ipc_stream stream; + UINT64* p = (UINT64*)(tspHandle); + WIN_PIPE* pipe = NULL; + + status = (rpcmsg != CCMSG_REQUEST) && (rpcmsg != CCMSG_PING); + + if (!status) { + status = krb5int_ipc_stream_new (&stream); /* Create a stream for the request data */ + } + + if (!status) { /* Put the data into the stream */ + status = krb5int_ipc_stream_write (stream, pbRequest, lenRequest); + } + + pipe = ccs_win_pipe_new(pszUUID, *p); + worklist_add(rpcmsg, pipe, stream, serverStartTime); + *return_status = status; + } + + +void ccs_rpc_connect( + const long rpcmsg, /* Message type */ + const char tspHandle[], /* Client's tspdata* */ + const char* pszUUID, /* Data buffer */ + long* return_status ) { /* Return code */ + + UINT64* p = (UINT64*)(tspHandle); + WIN_PIPE* pipe = ccs_win_pipe_new(pszUUID, *p); + + worklist_add( rpcmsg, + pipe, + NULL, /* No payload with connect request */ + (const time_t)0 ); /* No server session number with connect request */ + } + + +// 'Authentication' is client setting a value in a file and the server +// returning that value plus one. +CC_UINT32 ccs_authenticate(const CC_CHAR* name) { + HANDLE hMap = 0; + PDWORD pvalue = 0; + CC_UINT32 result = 0; + DWORD status = 0; + + hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, (LPSTR)name); + status = !hMap; + + if (!status) { + pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); + status = !pvalue; + } + + if (!status) { + *pvalue += 1; + result = *pvalue; + } + + if (pvalue) { + UnmapViewOfFile(pvalue); + } + + if (hMap) CloseHandle(hMap); + return result; + } diff --git a/krb5-1.21.3/src/ccapi/server/win/ccs_win_pipe.c b/krb5-1.21.3/src/ccapi/server/win/ccs_win_pipe.c new file mode 100644 index 00000000..99c66701 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/win/ccs_win_pipe.c @@ -0,0 +1,162 @@ +/* ccapi/server/win/ccs_win_pipe.c */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "assert.h" +#include +#include + +#include "ccs_win_pipe.h" +#include "cci_debugging.h" + +/* Ref: +struct ccs_win_pipe_t { + char* uuid; + UINT64 clientHandle; + } + */ + +/* ------------------------------------------------------------------------ */ + +struct ccs_win_pipe_t* ccs_win_pipe_new (const char* uuid, const UINT64 h) { + + cc_int32 err = ccNoError; + struct ccs_win_pipe_t* out_pipe = NULL; + char* uuidCopy = NULL; + + if (!err) { + if (!uuid) {err = cci_check_error(ccErrBadParam);} + } + + if (!err) { + uuidCopy = (char*)malloc(1+strlen(uuid)); + if (!uuidCopy) {err = cci_check_error(ccErrBadParam);} + strcpy(uuidCopy, uuid); + } + + if (!err) { + out_pipe = (struct ccs_win_pipe_t*)malloc(sizeof(struct ccs_win_pipe_t)); + if (!out_pipe) {err = cci_check_error(ccErrBadParam);} + out_pipe->uuid = uuidCopy; + out_pipe->clientHandle = h; + } + + return out_pipe; + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_win_pipe_copy (WIN_PIPE** out_pipe, + const WIN_PIPE* in_pipe) { + + *out_pipe = + ccs_win_pipe_new( + ccs_win_pipe_getUuid (in_pipe), + ccs_win_pipe_getHandle(in_pipe) ); + + return (*out_pipe) ? ccNoError : ccErrBadParam; + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_win_pipe_release(const WIN_PIPE* in_pipe) { + + cc_int32 err = ccNoError; + + if (!ccs_win_pipe_valid(in_pipe)) {err = cci_check_error(ccErrBadParam);} + + if (!err) { + if (!in_pipe->uuid) free(in_pipe->uuid); + if (!in_pipe) free(in_pipe); + } + + return err; + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_win_pipe_valid (const WIN_PIPE* in_pipe) { + + if (!in_pipe) { + cci_check_error(ccErrBadParam); + return FALSE; + } + + if (!in_pipe->uuid) { + cci_check_error(ccErrBadParam); + return FALSE; + } + + return TRUE; + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_win_pipe_compare (const WIN_PIPE* in_pipe_1, + const WIN_PIPE* in_pipe_2, + cc_uint32 *out_equal) { + + cc_int32 err = ccNoError; + int seq = 0; + *out_equal = FALSE; + + if (!ccs_win_pipe_valid(in_pipe_1)) {err = cci_check_error(ccErrBadParam);} + if (!ccs_win_pipe_valid(in_pipe_2)) {err = cci_check_error(ccErrBadParam);} + if (!out_equal) {err = cci_check_error(ccErrBadParam);} + + /* A disconnect doesn't have a tls* with it -- only the uuid. SO only + compare the uuids. + */ + if (!err) { + seq = strcmp( ccs_win_pipe_getUuid(in_pipe_1), + ccs_win_pipe_getUuid(in_pipe_2) ); + *out_equal = (seq == 0); + } + + return err; + } + +/* ------------------------------------------------------------------------ */ + +char* ccs_win_pipe_getUuid (const WIN_PIPE* in_pipe) { + + char* result = NULL; + + if (!ccs_win_pipe_valid(in_pipe)) {cci_check_error(ccErrBadParam);} + else {result = in_pipe->uuid;} + + return result; + } + +/* ------------------------------------------------------------------------ */ + +UINT64 ccs_win_pipe_getHandle (const WIN_PIPE* in_pipe) { + + UINT64 result = 0; + + if (!ccs_win_pipe_valid(in_pipe)) {cci_check_error(ccErrBadParam);} + else {result = in_pipe->clientHandle;} + + return result; + } diff --git a/krb5-1.21.3/src/ccapi/server/win/ccs_win_pipe.h b/krb5-1.21.3/src/ccapi/server/win/ccs_win_pipe.h new file mode 100644 index 00000000..fef99953 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/win/ccs_win_pipe.h @@ -0,0 +1,68 @@ +/* ccapi/server/win/ccs_win_pipe.h */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef _ccs_win_pipe_h_ +#define _ccs_win_pipe_h_ + +#include "windows.h" + +#include "CredentialsCache.h" + +/* ------------------------------------------------------------------------ */ + +/* On Windows, a pipe is a struct containing a UUID and a handle. Both the + UUID and handle are supplied by the client. + + The UUID is used to build the client's reply endpoint. + + The handle is to the requesting client thread's thread local storage struct, + so that the client's one and only reply handler can put reply data where + the requesting thread will be able to see it. + */ + +struct ccs_win_pipe_t { + char* uuid; + UINT64 clientHandle; + }; + +typedef struct ccs_win_pipe_t WIN_PIPE; + +struct ccs_win_pipe_t* ccs_win_pipe_new(const char* uuid, const UINT64 h); + +cc_int32 ccs_win_pipe_release (const WIN_PIPE* io_pipe); + +cc_int32 ccs_win_pipe_compare (const WIN_PIPE* win_pipe_1, + const WIN_PIPE* win_pipe_2, + cc_uint32 *out_equal); + +cc_int32 ccs_win_pipe_copy (WIN_PIPE** out_pipe, + const WIN_PIPE* in_pipe); + +cc_int32 ccs_win_pipe_valid (const WIN_PIPE* in_pipe); + +char* ccs_win_pipe_getUuid (const WIN_PIPE* in_pipe); +UINT64 ccs_win_pipe_getHandle (const WIN_PIPE* in_pipe); + +#endif // _ccs_win_pipe_h_ diff --git a/krb5-1.21.3/src/ccapi/server/win/workitem.h b/krb5-1.21.3/src/ccapi/server/win/workitem.h new file mode 100644 index 00000000..fff56f32 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/server/win/workitem.h @@ -0,0 +1,51 @@ +#ifndef __WorkItem +#define __WorkItem + +#include +#include "windows.h" + +extern "C" { + #include "ccs_pipe.h" + } + +class WorkItem { +private: + k5_ipc_stream _buf; + WIN_PIPE* _pipe; + const long _rpcmsg; + const long _sst; +public: + WorkItem( k5_ipc_stream buf, + WIN_PIPE* pipe, + const long type, + const long serverStartTime); + WorkItem( const WorkItem&); + WorkItem(); + ~WorkItem(); + + const k5_ipc_stream payload() const {return _buf;} + const k5_ipc_stream take_payload(); + WIN_PIPE* take_pipe(); + WIN_PIPE* pipe() const {return _pipe;} + const long type() const {return _rpcmsg;} + const long sst() const {return _sst;} + char* print(char* buf); + }; + +class WorkList { +private: + std::list wl; + CRITICAL_SECTION cs; + HANDLE hEvent; +public: + WorkList(); + ~WorkList(); + int initialize(); + int cleanup(); + void wait(); + int add(WorkItem*); + int remove(WorkItem**); + bool isEmpty() {return wl.empty();} + }; + +#endif // __WorkItem diff --git a/krb5-1.21.3/src/ccapi/test/Makefile.in b/krb5-1.21.3/src/ccapi/test/Makefile.in new file mode 100644 index 00000000..23befe8e --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/Makefile.in @@ -0,0 +1,225 @@ +mydir=ccapi$(S)test +BUILDTOP=..$(S).. +CCAPI=$(BUILDTOP)$(S)CCAPI + +!if defined(KRB5_KFW_COMPILE) +KFWINC= /I$(BUILDTOP)\..\..\krbcc\include +!endif + +# Because all the sources are in ., +# the only includes we need are to directories outside of ccapi. +LOCALINCLUDES = /I$(BUILDTOP) /I$(BUILDTOP)$(S)include /I$(BUILDTOP)$(S)include$(S)krb5 $(KFWINC) \ + -I$(BUILDTOP)$(S)util$(S)et /I. -I$(CCAPI)$(S)COMMON -I$(CCAPI)$(S)LIB + +# run with "make all" to create CCAPI tests in "/tmp/ccapi_test" +# run resulting tests with "sh test_ccapi.sh" + +##DOS##CPPFLAGS = $(CPPFLAGS) /EHsc -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 \ +##DOS## -D_WIN32_WINNT=0x0501 -D_CRT_SECURE_NO_WARNINGS + +##DOS##WINH = cci_debugging.h \ +##DOS## ccs_reply.h \ +##DOS## ccs_request.h \ +##DOS## ccs_request_c.c \ +##DOS## cci_types.h \ +##DOS## win-utils.h + +##DOS##LIBSRC=ccapi_ccache.c \ +##DOS## ccapi_ccache_iterator.c \ +##DOS## ccapi_context.c \ +##DOS## ccapi_context_change_time.c \ +##DOS## ccapi_err.c \ +##DOS## ccapi_ipc.c \ +##DOS## ccapi_credentials.c \ +##DOS## ccapi_credentials_iterator.c \ +##DOS## ccapi_string.c \ +##DOS## ccapi_v2.c + +##DOS##COMSRC=cci_cred_union.c \ +##DOS## cci_identifier.c \ +##DOS## cci_message.c + +##DOS##COWSRC=cci_os_identifier.c + +SRCDIR = . +DSTROOT = $(SRCDIR) +OBJDIR = $(DSTROOT)$(S)ccapi_intermediates +DSTDIR = $(DSTROOT)$(S)ccapi_test +TESTDIR = $(DSTDIR)$(S)tests +SRCTMP = $(SRCDIR)\srctmp + +SCRIPT_NAME = test_ccapi.sh + +OBJECTS = $(OUTPRE)test_ccapi_ccache.$(OBJEXT) \ + $(OUTPRE)test_ccapi_check.$(OBJEXT) \ + $(OUTPRE)test_ccapi_constants.$(OBJEXT) \ + $(OUTPRE)test_ccapi_context.$(OBJEXT) \ + $(OUTPRE)test_ccapi_v2.$(OBJEXT) \ + $(OUTPRE)test_ccapi_globals.$(OBJEXT) \ + $(OUTPRE)test_ccapi_iterators.$(OBJEXT) \ + $(OUTPRE)test_ccapi_log.$(OBJEXT) \ + $(OUTPRE)test_ccapi_util.$(OBJEXT) + +PINGOBJS = $(OUTPRE)ccapi_ccache.$(OBJEXT) \ + $(OUTPRE)ccapi_ccache_iterator.$(OBJEXT) \ + $(OUTPRE)ccapi_context.$(OBJEXT) \ + $(OUTPRE)ccapi_context_change_time.$(OBJEXT) \ + $(OUTPRE)ccapi_err.$(OBJEXT) \ + $(OUTPRE)ccapi_ipc.$(OBJEXT) \ + $(OUTPRE)ccapi_credentials.$(OBJEXT) \ + $(OUTPRE)ccapi_credentials_iterator.$(OBJEXT) \ + $(OUTPRE)ccapi_string.$(OBJEXT) \ + $(OUTPRE)ccapi_v2.$(OBJEXT) \ + $(OUTPRE)cci_cred_union.$(OBJEXT) \ + $(OUTPRE)cci_identifier.$(OBJEXT) \ + $(OUTPRE)cci_os_identifier.$(OBJEXT) \ + $(OUTPRE)cci_message.$(OBJEXT) \ + $(OUTPRE)ccs_request_c.$(OBJEXT) \ + $(OUTPRE)pingtest.$(OBJEXT) \ + $(OBJECTS) + +TESTALLOBJS=$(OUTPRE)main.$(OBJEXT) \ + $(OBJECTS) + +TEST_NAMES = test_cc_ccache_iterator_next \ + test_constants \ + test_cc_initialize \ + test_cc_credentials_iterator_next + +MORE_TESTS = test_cc_context_release \ + test_cc_context_get_change_time \ + test_cc_context_get_default_ccache_name \ + test_cc_context_open_ccache \ + test_cc_context_open_default_ccache \ + test_cc_context_create_ccache \ + test_cc_context_create_default_ccache \ + test_cc_context_create_new_ccache \ + test_cc_context_new_ccache_iterator \ + test_cc_context_compare \ + test_cc_ccache_release \ + test_cc_ccache_destroy \ + test_cc_ccache_set_default \ + test_cc_ccache_get_credentials_version \ + test_cc_ccache_get_name \ + test_cc_ccache_get_principal \ + test_cc_ccache_set_principal \ + test_cc_ccache_store_credentials \ + test_cc_ccache_remove_credentials \ + test_cc_ccache_new_credentials_iterator \ + test_cc_ccache_get_change_time \ + test_cc_ccache_get_last_default_time \ + test_cc_ccache_move \ + test_cc_ccache_compare \ + test_cc_ccache_get_kdc_time_offset \ + test_cc_ccache_set_kdc_time_offset \ + test_cc_ccache_clear_kdc_time_offset \ + test_cc_shutdown \ + test_cc_get_change_time \ + test_cc_open \ + test_cc_create \ + test_cc_close \ + test_cc_destroy \ + test_cc_get_cred_version \ + test_cc_get_name \ + test_cc_get_principal \ + test_cc_set_principal \ + test_cc_store \ + test_cc_remove_cred \ + test_cc_seq_fetch_NCs_begin \ + test_cc_seq_fetch_NCs_next \ + test_cc_seq_fetch_creds_begin \ + test_cc_seq_fetch_creds_next \ + test_cc_get_NC_info + + +##### Linker +LINK = link +LIBS = -lkrb5 +##DOS##LIBS = $(CLIB) $(SLIB) advapi32.lib rpcrt4.lib user32.lib ws2_32.lib $(CCLIB).lib +LFLAGS = /nologo $(LOPTS) + +all-mac: setup-test-dir pingtest simple_lock_test build-base build-tests link-tests copy-script success-message +all-windows: setup-windows build-base $(OUTPRE)pingtest.exe build-tests build-testall copy-script success-message + +# compile base files used by all tests +build-base: $(PINGOBJS) + +##++ These two rules build each element of the list: +# compile each test +build-tests: $(TEST_NAMES) + @echo build-tests complete. + +$(TEST_NAMES): + @echo DBG: $@ + $(CC) $(ALL_CFLAGS) -Fe$(TESTDIR)$(S)$@.exe -Fd$(OBJDIR)$(S)$@.pdb $@.c $(OBJECTS) $(LIBS) +# Clean .obj from .: + $(RM) $@.$(OBJEXT) +##-- These two rules build each element of the list. + +# Make a build directory +setup-test-dir: + @echo "Removing old destination directory... $(DSTDIR)" + if [ -d "$(DSTDIR)" ]; then chmod -R u+w "$(DSTDIR)" && rm -rf "$(DSTDIR)"; fi + mkdir -p "$(TESTDIR)" + if [ -d "$(OBJDIR)" ]; then chmod -R u+w "$(OBJDIR)" && rm -rf "$(OBJDIR)"; fi + mkdir -p "$(OBJDIR)" + +## The same trick as used in TEST_NAMES to run an action on each element ofthe list WINH: +setup-windows: $(WINH) $(LIBSRC) $(COMSRC) $(COWSRC) + if NOT exist $(TESTDIR) mkdir $(TESTDIR) + if NOT exist $(OBJDIR) mkdir $(OBJDIR) + set LINK = link + +# This rule assumes that nmake in ..\lib\win has already run. +# That is how ..\Makefile.in is set up. +$(WINH): + copy ..\lib\win\srctmp\$@ . + +$(LIBSRC): + copy ..\lib\$@ . + +$(COMSRC): + copy ..\common\$@ . + +$(COWSRC): + copy ..\common\win\$@ . + +# This rule assumes that nmake in ..\lib\win\ has already run. +$(OUTPRE)pingtest.exe: $(OBJECTS) $(PINGOBJS) +# There doesn't appear to be any way to examine a variable and return a value +# indicating whether a string is present in it. We use a perl script to +# check the LIB variable. If the path to $(CCLIB).lib isn't present, the script +# deletes a.tmp and the following nmake actions correct LIB. + echo %%PATH%% > a.tmp + perl setlib.pl + if not exist a.tmp ( + @echo Adding ..\lib\win\srctmp to LIB + set LIB=%%LIB%%;..\lib\win\srctmp + ) + $(LINK) $(linkdebug) /map:$(@B)1.map -out:$(*B)1.exe $(conflags) $(PINGOBJS) $(LIBS) + $(LINK) $(LFLAGS) /map:$(@B)2.map /out:$(*B)2.exe $(conflags) $(PINGOBJS) $(LIBS) $(conlibsdll) + +link-tests: $(TEST_NAMES) + +build-testall: $(TEST_NAMES) $(OBJECTS) $(TESTALLOBJS) testall.exe + +testall.exe: + $(LINK) $(linkdebug) /map:$(@B)1.map -out:$(*B)1.exe $(conflags) $(TESTALLOBJS) $(LIBS) $(conslibdll) + + +simple_lock_test: + $(CC) -o $(TESTDIR)/simple_lock_test simple_lock_test.c $(LIBS) + +copy-script: + $(CP) $(SCRIPT_NAME) $(DSTDIR)$(S)$(SCRIPT_NAME) + +success-message: + @echo + @echo "CCAPI tests created in $(DSTDIR)" + +.PHONY: clean + +clean: + -rm -rf "$(OBJDIR)" + -rm -rf $(LIBSRC) + -rm -rf $(WINH) diff --git a/krb5-1.21.3/src/ccapi/test/Makefile.w32 b/krb5-1.21.3/src/ccapi/test/Makefile.w32 new file mode 100644 index 00000000..8c3da951 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/Makefile.w32 @@ -0,0 +1,75 @@ +# . is ccapi/test. +CO = ..\common +COWIN = $(CO)\win +LIBDIR = ..\lib +LIBWIN = $(LIBDIR)\win +SRV = ..\server +SRVWIN = ..\server\win + +!include + +INC = -I..\..\include -I..\..\util\et -I$(CO) -I$(COWIN) -I$(LIBDIR) -I$(LIBWIN) + +!if "$(CPU)" == "i386" +cflags = $(cflags) /EHsc /MTd -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 \ +$(INC) +!else +cflags = $(cflags) /W3 -D_CRTAPI1= -D_CRTAPI2= $(INC) +!endif +LIBS = $(LIBWIN)\ccapi.lib + +DSTROOT = . +SRC = $(DSTROOT) +#OBJDIR = $(DSTROOT)\obj +OBJDIR = . +OBJEXT = obj +TESTDIR = $(DSTROOT)\tests +TESTEXT = exe +DSTDIR = $(DSTROOT)\ccapi_tests + +PINGOBJS = pingtest.obj +SIMPLEOBJS = simple_lock_test.obj + +comobjs = cci_debugging.obj cci_stream.obj +cowobjs = cci_os_debugging.obj +libobjs = ccs_request_c.obj + +#all: build-base simple_lock_test pingtest +all: build-base pingtest + +# compile base files used by all tests +build-base: $(comobjs) $(libobjs) $(srvobjs) + @echo "Base objects built." + +# rule to compile src files +.c.obj: + $(cc) $(cdebug) $(cflags) /Fo$(OBJDIR)\$(*B).$(OBJEXT) $(SRC)\$(*B).c + +$(comobjs) : $(CO)\$(*B).c + $(cc) $(cdebug) $(cflags) $(CO)\$(*B).c + +$(cowobjs) : $(COWIN)\$(*B).c + $(cc) $(cdebug) $(cflags) $(COWIN)\$(*B).c + +$(libobjs) : $(LIBWIN)\$(*B).c + $(cc) $(cdebug) $(cflags) $(LIBWIN)\$(*B).c + +#$(srvobjs) : $(SRVWIN)\$*.c +# $(cc) $(cdebug) $(cflags) $(SRVWIN)\$*.c + +simple_lock_test: simple_lock_test.obj $(OBJS) + @echo R3+ Build $(*B) in $(TESTDIR) + $(cc) $(cdebug) $(cflags) $(*B).c + $(link) $(linkdebug) $(conflags) -out:$(TESTDIR)\$(*B).exe $(*B).obj \ + $(LIBS) rpcrt4.lib + @echo R3- Built $(*B) in $(TESTDIR) + +pingtest: pingtest.obj + @echo R4+ Build $(*B) in $(TESTDIR) + $(cc) $(cdebug) $(cflags) $(*B).c + $(link) $(linkdebug) $(conflags) -out:$(*B).exe $(PINGOBJS) $(libobjs) $(srvobjs) \ + $(LIBS) rpcrt4.lib + @echo R4- Built $(*B) in $(TESTDIR) + +clean: + DEL *.$(OBJEXT) \ No newline at end of file diff --git a/krb5-1.21.3/src/ccapi/test/Pingtest.sln b/krb5-1.21.3/src/ccapi/test/Pingtest.sln new file mode 100644 index 00000000..cf43a1e4 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/Pingtest.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Pingtest", "Pingtest.vcproj", "{04017001-3222-43C4-A03C-8423B5349276}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {04017001-3222-43C4-A03C-8423B5349276}.Debug|Win32.ActiveCfg = Debug|Win32 + {04017001-3222-43C4-A03C-8423B5349276}.Debug|Win32.Build.0 = Debug|Win32 + {04017001-3222-43C4-A03C-8423B5349276}.Release|Win32.ActiveCfg = Release|Win32 + {04017001-3222-43C4-A03C-8423B5349276}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/krb5-1.21.3/src/ccapi/test/deps b/krb5-1.21.3/src/ccapi/test/deps new file mode 100644 index 00000000..e69de29b diff --git a/krb5-1.21.3/src/ccapi/test/main.c b/krb5-1.21.3/src/ccapi/test/main.c new file mode 100644 index 00000000..2ace9678 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/main.c @@ -0,0 +1,90 @@ +#include +#include + +// #include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" +#include "test_ccapi_iterators.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; +// cc_ccache_iterator_t cache_iterator = NULL; +// cc_credentials_iterator_t cred_iterator = NULL; + + fprintf(stdout, "Testing CCAPI against CCAPI v3 rev 8 documentation...\n"); + fprintf(stdout, "Warning: this test suite is woefully incomplete and unpolished.\n"); + + T_CCAPI_INIT; + + // *** ccapi v2 compat *** + err = check_cc_shutdown(); + err = check_cc_get_change_time(); + err = check_cc_open(); + err = check_cc_create(); + err = check_cc_close(); + err = check_cc_destroy(); + err = check_cc_get_cred_version(); + err = check_cc_get_name(); + err = check_cc_get_principal(); + err = check_cc_set_principal(); + err = check_cc_store(); + err = check_cc_remove_cred(); + err = check_cc_seq_fetch_NCs_begin(); + err = check_cc_seq_fetch_NCs_next(); + err = check_cc_seq_fetch_creds_begin(); + err = check_cc_seq_fetch_creds_next(); + err = check_cc_get_NC_info(); + + err = check_constants(); + + // *** cc_context *** + err = check_cc_initialize(); + err = check_cc_context_release(); + err = check_cc_context_get_change_time(); + err = check_cc_context_get_default_ccache_name(); + err = check_cc_context_open_ccache(); + err = check_cc_context_open_default_ccache(); + err = check_cc_context_create_ccache(); + err = check_cc_context_create_default_ccache(); + err = check_cc_context_create_new_ccache(); + err = check_cc_context_new_ccache_iterator(); + // err = check_cc_context_lock(); + // err = check_cc_context_unlock(); + err = check_cc_context_compare(); + + // *** cc_ccache *** + err = check_cc_ccache_release(); + err = check_cc_ccache_destroy(); + err = check_cc_ccache_set_default(); + err = check_cc_ccache_get_credentials_version(); + err = check_cc_ccache_get_name(); + err = check_cc_ccache_get_principal(); + err = check_cc_ccache_set_principal(); + err = check_cc_ccache_store_credentials(); + err = check_cc_ccache_remove_credentials(); + err = check_cc_ccache_new_credentials_iterator(); + // err = check_cc_ccache_lock(); + // err = check_cc_ccache_unlock(); + err = check_cc_ccache_get_change_time(); + err = check_cc_ccache_get_last_default_time(); + err = check_cc_ccache_move(); + err = check_cc_ccache_compare(); + err = check_cc_ccache_get_kdc_time_offset(); + err = check_cc_ccache_set_kdc_time_offset(); + err = check_cc_ccache_clear_kdc_time_offset(); + + // *** cc_ccache_iterator *** + err = check_cc_ccache_iterator_next(); + + // *** cc_credentials_iterator *** + err = check_cc_credentials_iterator_next(); + + fprintf(stdout, "\nFinished testing CCAPI. %d failure%s in total.\n", total_failure_count, (total_failure_count == 1) ? "" : "s"); + + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/pingtest.c b/krb5-1.21.3/src/ccapi/test/pingtest.c new file mode 100644 index 00000000..0ffc15e7 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/pingtest.c @@ -0,0 +1,110 @@ +// pingtest.c +// +// Test RPC to server, with PING message, which exists for no other purpose than this test. + +#include +#include +#include +#include + +#include "cci_debugging.h" +#include "CredentialsCache.h" +#include "win-utils.h" + +#include "ccs_request.h" +#define CLIENT_REQUEST_RPC_HANDLE ccs_request_IfHandle + + +extern cc_int32 cci_os_ipc_thread_init (void); +extern cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, + k5_ipc_stream in_request_stream, + cc_int32 in_msg, + k5_ipc_stream* out_reply_stream); + +static DWORD dwTlsIndex; + +DWORD GetTlsIndex() {return dwTlsIndex;} + +RPC_STATUS send_test(char* endpoint) { + unsigned char* pszNetworkAddress = NULL; + unsigned char* pszOptions = NULL; + unsigned char* pszStringBinding = NULL; + unsigned char* pszUuid = NULL; + RPC_STATUS status; + + status = RpcStringBindingCompose(pszUuid, + (RPC_CSTR)"ncalrpc", + pszNetworkAddress, + (unsigned char*)endpoint, + pszOptions, + &pszStringBinding); + cci_debug_printf("%s pszStringBinding = %s", __FUNCTION__, pszStringBinding); + if (status) {return cci_check_error(status);} + + /* Set the binding handle that will be used to bind to the RPC server [the 'client']. */ + status = RpcBindingFromStringBinding(pszStringBinding, &CLIENT_REQUEST_RPC_HANDLE); + if (status) {return cci_check_error(status);} + + status = RpcStringFree(&pszStringBinding); // Temp var no longer needed. + + if (!status) { + RpcTryExcept { + cci_debug_printf("%s calling remote procedure 'ccs_authenticate'", __FUNCTION__); + status = ccs_authenticate((CC_CHAR*)"DLLMAIN TEST!"); + cci_debug_printf(" ccs_authenticate returned %d", status); + } + RpcExcept(1) { + status = cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + } + + cci_check_error(RpcBindingFree(&CLIENT_REQUEST_RPC_HANDLE)); + + return (status); + } + +int main( int argc, char *argv[]) { + cc_int32 err = 0; + cc_context_t context = NULL; + k5_ipc_stream send_stream = NULL; + k5_ipc_stream reply_stream = NULL; + char* message = "Hello, RPC!"; + + + if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE; + + if (!err) { + err = cci_os_ipc_thread_init(); + } + if (!err) { + err = krb5int_ipc_stream_new (&send_stream); + err = krb5int_ipc_stream_write(send_stream, message, + 1+strlen(message)); + } + + if (!err) { + err = cci_os_ipc_msg(TRUE, send_stream, CCMSG_PING, &reply_stream); + } + Sleep(10*1000); + cci_debug_printf("Try finishing async call."); + + Sleep(INFINITE); + cci_debug_printf("main: return. err == %d", err); + + return 0; + } + + + +/*********************************************************************/ +/* MIDL allocate and free */ +/*********************************************************************/ + +void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { + return(malloc(len)); + } + +void __RPC_USER midl_user_free(void __RPC_FAR * ptr) { + free(ptr); + } diff --git a/krb5-1.21.3/src/ccapi/test/setlib.pl b/krb5-1.21.3/src/ccapi/test/setlib.pl new file mode 100644 index 00000000..bba22506 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/setlib.pl @@ -0,0 +1,10 @@ +#!perl -w + +$b = "lib\\win\\srctmp"; +$a = $ENV{LIB}; +if (! ($a =~ /$b/) ) { + print "$b Not in LIB!\n"; + system("del a.tmp"); + } +else {print "$b in LIB.\n";} +exit(0); \ No newline at end of file diff --git a/krb5-1.21.3/src/ccapi/test/simple_lock_test.c b/krb5-1.21.3/src/ccapi/test/simple_lock_test.c new file mode 100644 index 00000000..8961d999 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/simple_lock_test.c @@ -0,0 +1,91 @@ +/* + simple_lock_test.c + + Initializes two contexts in two different threads and tries to get read locks on both at the same time. + Hangs at line 24. +*/ +#include +#include + +#include "test_ccapi_log.h" + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) +#include +#endif + +#ifdef TARGET_OS_MAC +#include +#include +#include +#else +#include "CredentialsCache.h" +#endif + + +void *other_thread (void) { + cc_int32 err; + cc_context_t context = NULL; + + err = cc_initialize(&context, ccapi_version_7, NULL, NULL); + + log_error("thread: attempting lock. may hang. err == %d", err); + + if (!err) { + // hangs with cc_lock_read which should succeed immediately, but does not hang with write, upgrade, and downgrade, which fail immediately + err = cc_context_lock(context, cc_lock_read, cc_lock_noblock); + } + + if (context) { + cc_context_unlock(context); + cc_context_release(context); + context = NULL; + } + log_error("thread: return. err == %d", err); +} + + +int main (int argc, char *argv[]) { + cc_int32 err; + int status; + cc_context_t context = NULL; + +#ifdef TARGET_OS_MAC + pthread_t thread_id; +#endif + + err = cc_initialize(&context, ccapi_version_7, NULL, NULL); + if (!err) { + err = cc_context_lock(context, cc_lock_read, cc_lock_noblock); + } + + log_error("main: initialized and read locked context. err == %d", err); + +#ifdef TARGET_OS_MAC + status = pthread_create (&thread_id, NULL, (void *) other_thread, NULL); + if (status != 0) { + log_error("pthread_create() returned %d", status); + exit(-1); + } + + pthread_join(thread_id, NULL); +#else + +#endif + + log_error("main: unlocking and releasing context. err == %d", err); + + if (context) { + log_error("main: calling cc_context_unlock"); + cc_context_unlock(context); + log_error("main: calling cc_context_release"); + cc_context_release(context); + context = NULL; + } + + log_error("main: return. err == %d", err); + +#if defined(_WIN32) + UNREFERENCED_PARAMETER(status); // no whining! +#endif + return 0; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c new file mode 100644 index 00000000..1698535f --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_clear_kdc_time_offset.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_clear_kdc_time_offset(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_compare.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_compare.c new file mode 100644 index 00000000..96aaa56c --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_compare.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_compare(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_destroy.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_destroy.c new file mode 100644 index 00000000..95c417ca --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_destroy.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_destroy(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_change_time.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_change_time.c new file mode 100644 index 00000000..a515d5bd --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_change_time.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_get_change_time(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_credentials_version.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_credentials_version.c new file mode 100644 index 00000000..f5df7c07 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_credentials_version.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_get_credentials_version(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c new file mode 100644 index 00000000..13e61165 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_kdc_time_offset.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_get_kdc_time_offset(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_last_default_time.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_last_default_time.c new file mode 100644 index 00000000..4de22e4a --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_last_default_time.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_get_last_default_time(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_name.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_name.c new file mode 100644 index 00000000..f6649974 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_name.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_get_name(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_principal.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_principal.c new file mode 100644 index 00000000..05d7c434 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_get_principal.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_get_principal(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_iterator_next.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_iterator_next.c new file mode 100644 index 00000000..945a98d2 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_iterator_next.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_iterator_next(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_move.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_move.c new file mode 100644 index 00000000..880198c8 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_move.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_move(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_new_credentials_iterator.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_new_credentials_iterator.c new file mode 100644 index 00000000..1338e832 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_new_credentials_iterator.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_new_credentials_iterator(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_release.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_release.c new file mode 100644 index 00000000..75d604c9 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_release.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_release(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_remove_credentials.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_remove_credentials.c new file mode 100644 index 00000000..679da85c --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_remove_credentials.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_remove_credentials(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_set_default.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_set_default.c new file mode 100644 index 00000000..71bba2a4 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_set_default.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_set_default(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c new file mode 100644 index 00000000..b8b21e98 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_set_kdc_time_offset.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_set_kdc_time_offset(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_set_principal.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_set_principal.c new file mode 100644 index 00000000..ec55acd7 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_set_principal.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_set_principal(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_ccache_store_credentials.c b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_store_credentials.c new file mode 100644 index 00000000..c52125bd --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_ccache_store_credentials.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_ccache_store_credentials(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_close.c b/krb5-1.21.3/src/ccapi/test/test_cc_close.c new file mode 100644 index 00000000..b6bc3afa --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_close.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_close(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_context_compare.c b/krb5-1.21.3/src/ccapi/test/test_cc_context_compare.c new file mode 100644 index 00000000..f4965af3 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_context_compare.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_compare(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_context_create_ccache.c b/krb5-1.21.3/src/ccapi/test/test_cc_context_create_ccache.c new file mode 100644 index 00000000..c9429451 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_context_create_ccache.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_create_ccache(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_context_create_default_ccache.c b/krb5-1.21.3/src/ccapi/test/test_cc_context_create_default_ccache.c new file mode 100644 index 00000000..c3fb4054 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_context_create_default_ccache.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_create_default_ccache(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_context_create_new_ccache.c b/krb5-1.21.3/src/ccapi/test/test_cc_context_create_new_ccache.c new file mode 100644 index 00000000..d89fa4f3 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_context_create_new_ccache.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_create_new_ccache(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_context_get_change_time.c b/krb5-1.21.3/src/ccapi/test/test_cc_context_get_change_time.c new file mode 100644 index 00000000..ad5c0a34 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_context_get_change_time.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_get_change_time(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_context_get_default_ccache_name.c b/krb5-1.21.3/src/ccapi/test/test_cc_context_get_default_ccache_name.c new file mode 100644 index 00000000..06fff955 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_context_get_default_ccache_name.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_get_default_ccache_name(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_context_new_ccache_iterator.c b/krb5-1.21.3/src/ccapi/test/test_cc_context_new_ccache_iterator.c new file mode 100644 index 00000000..82209854 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_context_new_ccache_iterator.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_new_ccache_iterator(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_context_open_ccache.c b/krb5-1.21.3/src/ccapi/test/test_cc_context_open_ccache.c new file mode 100644 index 00000000..461d8df6 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_context_open_ccache.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_open_ccache(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_context_open_default_ccache.c b/krb5-1.21.3/src/ccapi/test/test_cc_context_open_default_ccache.c new file mode 100644 index 00000000..09c6b7c3 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_context_open_default_ccache.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_open_default_ccache(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_context_release.c b/krb5-1.21.3/src/ccapi/test/test_cc_context_release.c new file mode 100644 index 00000000..03faf233 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_context_release.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_context_release(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_create.c b/krb5-1.21.3/src/ccapi/test/test_cc_create.c new file mode 100644 index 00000000..a21c4433 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_create.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_create(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_credentials_iterator_next.c b/krb5-1.21.3/src/ccapi/test/test_cc_credentials_iterator_next.c new file mode 100644 index 00000000..ff5f4673 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_credentials_iterator_next.c @@ -0,0 +1,16 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" +#include "test_ccapi_iterators.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_credentials_iterator_next(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_destroy.c b/krb5-1.21.3/src/ccapi/test/test_cc_destroy.c new file mode 100644 index 00000000..e55a8378 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_destroy.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_destroy(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_get_NC_info.c b/krb5-1.21.3/src/ccapi/test/test_cc_get_NC_info.c new file mode 100644 index 00000000..6b8eb374 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_get_NC_info.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_get_NC_info(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_get_change_time.c b/krb5-1.21.3/src/ccapi/test/test_cc_get_change_time.c new file mode 100644 index 00000000..d2058fec --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_get_change_time.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_get_change_time(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_get_cred_version.c b/krb5-1.21.3/src/ccapi/test/test_cc_get_cred_version.c new file mode 100644 index 00000000..1ff86781 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_get_cred_version.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_get_cred_version(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_get_name.c b/krb5-1.21.3/src/ccapi/test/test_cc_get_name.c new file mode 100644 index 00000000..5b6e1462 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_get_name.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_get_name(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_get_principal.c b/krb5-1.21.3/src/ccapi/test/test_cc_get_principal.c new file mode 100644 index 00000000..a809e5d1 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_get_principal.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_get_principal(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_initialize.c b/krb5-1.21.3/src/ccapi/test/test_cc_initialize.c new file mode 100644 index 00000000..1669a29a --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_initialize.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_initialize(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_open.c b/krb5-1.21.3/src/ccapi/test/test_cc_open.c new file mode 100644 index 00000000..83bb6020 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_open.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_open(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_remove_cred.c b/krb5-1.21.3/src/ccapi/test/test_cc_remove_cred.c new file mode 100644 index 00000000..6f841bbc --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_remove_cred.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_remove_cred(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_NCs_begin.c b/krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_NCs_begin.c new file mode 100644 index 00000000..329ca26e --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_NCs_begin.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_seq_fetch_NCs_begin(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_NCs_next.c b/krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_NCs_next.c new file mode 100644 index 00000000..31b5ac07 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_NCs_next.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_seq_fetch_NCs_next(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_creds_begin.c b/krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_creds_begin.c new file mode 100644 index 00000000..5bb5e916 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_creds_begin.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_seq_fetch_creds_begin(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_creds_next.c b/krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_creds_next.c new file mode 100644 index 00000000..83528b30 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_seq_fetch_creds_next.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_seq_fetch_creds_next(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_set_principal.c b/krb5-1.21.3/src/ccapi/test/test_cc_set_principal.c new file mode 100644 index 00000000..04b55df9 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_set_principal.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_set_principal(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_shutdown.c b/krb5-1.21.3/src/ccapi/test/test_cc_shutdown.c new file mode 100644 index 00000000..8756ca9f --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_shutdown.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_shutdown(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_cc_store.c b/krb5-1.21.3/src/ccapi/test/test_cc_store.c new file mode 100644 index 00000000..507b3612 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_cc_store.c @@ -0,0 +1,14 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_v2.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_cc_store(); + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi.bat b/krb5-1.21.3/src/ccapi/test/test_ccapi.bat new file mode 100644 index 00000000..2d5bec53 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi.bat @@ -0,0 +1,43 @@ +# test_ccapi.bat + +@echo "\nBeginning test of CCAPI...\n" +@echo "\nThese tests are based on the CCAPI v3 revision 8 draft documentation.\n" + +#run_test simple_lock_test + +teststest_constants.exe +tests\test_cc_initialize.exe +tests\test_cc_context_get_version.exe +exit 0 + +tests\test_cc_context_release.exe +tests\test_cc_context_get_change_time.exe +tests\test_cc_context_get_default_ccache_name.exe +tests\test_cc_context_open_ccache.exe +tests\test_cc_context_open_default_ccache.exe +tests\test_cc_context_create_ccache.exe +tests\test_cc_context_create_default_ccache.exe +tests\test_cc_context_create_new_ccache.exe +tests\test_cc_context_new_ccache_iterator.exe +tests\test_cc_context_compare.exe +tests\test_cc_ccache_release.exe +tests\test_cc_ccache_destroy.exe +tests\test_cc_ccache_set_default.exe +tests\test_cc_ccache_get_credentials_version.exe +tests\test_cc_ccache_get_name.exe +tests\test_cc_ccache_get_principal.exe +tests\test_cc_ccache_set_principal.exe +tests\test_cc_ccache_store_credentials.exe +tests\test_cc_ccache_remove_credentials.exe +tests\test_cc_ccache_new_credentials_iterator.exe +tests\test_cc_ccache_get_change_time.exe +tests\test_cc_ccache_get_last_default_time.exe +tests\test_cc_ccache_move.exe +tests\test_cc_ccache_compare.exe +tests\test_cc_ccache_get_kdc_time_offset.exe +tests\test_cc_ccache_set_kdc_time_offset.exe +tests\test_cc_ccache_clear_kdc_time_offset.exe +tests\test_cc_ccache_iterator_next.exe +tests\test_cc_credentials_iterator_next.exe + +@echo "Finished testing CCAPI." diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi.sh b/krb5-1.21.3/src/ccapi/test/test_ccapi.sh new file mode 100644 index 00000000..c8959d68 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi.sh @@ -0,0 +1,76 @@ +#!/bin/sh + +# run with ./test-ccapi.sh to run CCAPI tests + +TEST_DIR="tests" +failure_count=0 + +function run_test { + if [[ -e $TEST_DIR/$1 ]]; then + ./$TEST_DIR/$1 + failure_count=`expr $failure_count + $?` + fi +} + +printf "\nBeginning test of CCAPI...\n" +printf "\nThese tests are based on the CCAPI v3 revision 8 draft documentation.\n" + +run_test simple_lock_test + +run_test test_constants + +run_test test_cc_initialize +run_test test_cc_context_release +run_test test_cc_context_get_change_time +run_test test_cc_context_get_default_ccache_name +run_test test_cc_context_open_ccache +run_test test_cc_context_open_default_ccache +run_test test_cc_context_create_ccache +run_test test_cc_context_create_default_ccache +run_test test_cc_context_create_new_ccache +run_test test_cc_context_new_ccache_iterator +run_test test_cc_context_compare + +run_test test_cc_ccache_release +run_test test_cc_ccache_destroy +run_test test_cc_ccache_set_default +run_test test_cc_ccache_get_credentials_version +run_test test_cc_ccache_get_name +run_test test_cc_ccache_get_principal +run_test test_cc_ccache_set_principal +run_test test_cc_ccache_store_credentials +run_test test_cc_ccache_remove_credentials +run_test test_cc_ccache_new_credentials_iterator +run_test test_cc_ccache_get_change_time +run_test test_cc_ccache_get_last_default_time +run_test test_cc_ccache_move +run_test test_cc_ccache_compare +run_test test_cc_ccache_get_kdc_time_offset +run_test test_cc_ccache_set_kdc_time_offset +run_test test_cc_ccache_clear_kdc_time_offset + +run_test test_cc_ccache_iterator_next + +run_test test_cc_credentials_iterator_next + +run_test test_cc_shutdown +run_test test_cc_get_change_time +run_test test_cc_open +run_test test_cc_create +run_test test_cc_close +run_test test_cc_destroy +run_test test_cc_get_cred_version +run_test test_cc_get_name +run_test test_cc_get_principal +run_test test_cc_set_principal +run_test test_cc_store +run_test test_cc_remove_cred +run_test test_cc_seq_fetch_NCs_begin +run_test test_cc_seq_fetch_NCs_next +run_test test_cc_seq_fetch_creds_begin +run_test test_cc_seq_fetch_creds_next +run_test test_cc_get_NC_info + +printf "\nFinished testing CCAPI. $failure_count failures in total.\n" + +exit 0 \ No newline at end of file diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_ccache.c b/krb5-1.21.3/src/ccapi/test/test_ccapi_ccache.c new file mode 100644 index 00000000..fe63e671 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_ccache.c @@ -0,0 +1,1875 @@ +#include +#include +#include +#include +#include "test_ccapi_check.h" +#include "test_ccapi_util.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_release(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_release"); + + #ifndef cc_ccache_release + log_error("cc_ccache_release is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + + + if (!err) { + check_once_cc_ccache_release(context, ccache, ccNoError, NULL); + ccache = NULL; + } + + if (context) { cc_context_release(context); } + + #endif /* cc_ccache_release */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_release(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[2] = { + ccNoError, + ccErrInvalidCCache, + }; + + cc_string_t name = NULL; + + err = cc_ccache_get_name(ccache, &name); + err = cc_ccache_release(ccache); + ccache = NULL; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_release + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err && name) { // try opening released ccache to make sure it still exists + err = cc_context_open_ccache(context, name->data, &ccache); + } + check_if(err == ccErrCCacheNotFound, "released ccache was actually destroyed instead"); + + if (ccache) { cc_ccache_destroy(ccache); } + if (name) { cc_string_release(name); } + + #endif /* cc_ccache_release */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_destroy(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_destroy"); + + #ifndef cc_ccache_destroy + log_error("cc_ccache_destroy is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + + + if (!err) { + check_once_cc_ccache_destroy(context, ccache, ccNoError, NULL); + ccache = NULL; + } + + if (context) { cc_context_release(context); } + + #endif /* cc_ccache_destroy */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_destroy(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[2] = { + ccNoError, + ccErrInvalidCCache, + }; + + cc_string_t name = NULL; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_destroy + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_get_name(ccache, &name); + err = cc_ccache_destroy(ccache); + ccache = NULL; + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err && name) { // try opening released ccache to make sure it still exists + err = cc_context_open_ccache(context, name->data, &ccache); + } + check_if(err != ccErrCCacheNotFound, "destroyed ccache was actually released instead"); + + if (ccache) { cc_ccache_destroy(ccache); } + if (name) { cc_string_release(name); } + + #endif /* cc_ccache_destroy */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_set_default(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_set_default"); + + #ifndef cc_ccache_set_default + log_error("cc_ccache_set_default is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + // try when it's the only ccache (already default) + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's the only ccache (already default)"); + } + if (ccache) { + err = cc_ccache_release(ccache); + ccache = NULL; + } + + // try when it's not the only ccache (and not default) + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "baz@BAR.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's not the only ccache (and not default)"); + } + if (ccache) { + err = cc_ccache_release(ccache); + ccache = NULL; + } + + // try when it's not the only ccache (and already default) + if (!err) { + err = cc_context_open_default_ccache(context, &ccache); + } + if (!err) { + check_once_cc_ccache_set_default(context, ccache, ccNoError, "when it's not the only ccache (and already default)"); + } + if (ccache) { + err = cc_ccache_release(ccache); + ccache = NULL; + } + + if (!err) { + err = destroy_all_ccaches(context); + } + + if (context) { cc_context_release(context); } + + #endif /* cc_ccache_set_default */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_set_default(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[3] = { + ccNoError, + ccErrInvalidCCache, + ccErrCCacheNotFound, + }; + + cc_ccache_t default_ccache = NULL; + cc_string_t name = NULL; + cc_string_t default_name = NULL; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_set_default + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_set_default(ccache); + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + err = cc_ccache_get_name(ccache, &name); + } + if (!err) { + err = cc_context_open_default_ccache(context, &default_ccache); + } + if (!err) { + err = cc_ccache_get_name(default_ccache, &default_name); + } + if (name && default_name) { + check_if(strcmp(name->data, default_name->data), NULL); + } + else { + check_if(1, "cc_ccache_get_name failed"); + } + + if (default_ccache) { cc_ccache_release(default_ccache); } + //if (ccache) { cc_ccache_destroy(ccache); } // ccache is released by the caller + if (default_name) { cc_string_release(default_name); } + if (name) { cc_string_release(name); } + + #endif /* cc_ccache_set_default */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_get_credentials_version(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_get_credentials_version"); + + #ifndef cc_ccache_get_credentials_version + log_error("cc_ccache_get_credentials_version is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + // try one created with v5 creds + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_get_credentials_version(ccache, cc_credentials_v5, ccNoError, "v5 creds"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + + if (ccache) { + cc_ccache_destroy(ccache); + ccache = NULL; + } + + err = ccNoError; + + if (context) { cc_context_release(context); } + + #endif /* cc_ccache_get_credentials_version */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_get_credentials_version(cc_ccache_t ccache, cc_uint32 expected_cred_vers, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrInvalidCCache, + ccErrBadParam, + ccErrCCacheNotFound, + }; + + cc_uint32 stored_cred_vers = 0; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_get_credentials_version + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_get_credentials_version(ccache, &stored_cred_vers); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(stored_cred_vers != expected_cred_vers, NULL); + } + + #endif /* cc_ccache_get_credentials_version */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_get_name(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_get_name"); + + #ifndef cc_ccache_get_name + log_error("cc_ccache_get_name is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // try with unique ccache (which happens to be default) + if (!err) { + err = cc_context_create_ccache(context, "0", cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_get_name(ccache, "0", ccNoError, "unique ccache (which happens to be default)"); + } + else { + log_error("cc_context_create_ccache failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + + // try with unique ccache (which is not default) + if (!err) { + err = cc_context_create_ccache(context, "1", cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_get_name(ccache, "1", ccNoError, "unique ccache (which is not default)"); + } + else { + log_error("cc_context_create_ccache failed, can't complete test"); + failure_count++; + } + + // try with bad param + if (!err) { + check_once_cc_ccache_get_name(ccache, NULL, ccErrBadParam, "NULL param"); + } + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_get_name */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_get_name(cc_ccache_t ccache, const char *expected_name, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrInvalidCCache, + ccErrBadParam, + ccErrCCacheNotFound, + }; + + cc_string_t stored_name = NULL; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_get_name + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (expected_name == NULL) { // we want to try with a NULL param + err = cc_ccache_get_name(ccache, NULL); + } + else { + err = cc_ccache_get_name(ccache, &stored_name); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(strcmp(stored_name->data, expected_name), NULL); + } + + if (stored_name) { cc_string_release(stored_name); } + + #endif /* cc_ccache_get_name */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_ccache_get_principal(cc_ccache_t ccache, + cc_uint32 cred_vers, + const char *expected_principal, + cc_int32 expected_err, + const char *description) { + cc_int32 err = ccNoError; + cc_string_t stored_principal = NULL; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrNoMem, + ccErrBadCredentialsVersion, + ccErrBadParam, + ccErrInvalidCCache, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_get_principal + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (expected_principal == NULL) { // we want to try with a NULL param + err = cc_ccache_get_principal(ccache, cred_vers, NULL); + } + else { + err = cc_ccache_get_principal(ccache, cred_vers, &stored_principal); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(strcmp(stored_principal->data, expected_principal), "expected princ == \"%s\" stored princ == \"%s\"", expected_principal, stored_principal->data); + } + + if (stored_principal) { cc_string_release(stored_principal); } + + #endif /* cc_ccache_get_principal */ + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_get_principal(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_get_principal"); + + #ifndef cc_ccache_get_principal + log_error("cc_ccache_get_principal is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // try with krb5 principal + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo/BAR@BAZ.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_get_principal(ccache, cc_credentials_v5, "foo/BAR@BAZ.ORG", ccNoError, "trying to get krb5 princ for krb5 ccache"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + + // try with bad param + if (!err) { + check_once_cc_ccache_get_principal(ccache, cc_credentials_v5, + NULL, ccErrBadParam, + "passed null out param"); + } + + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_get_principal */ + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_set_principal(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_set_principal"); + + #ifndef cc_ccache_set_principal + log_error("cc_ccache_set_principal is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // replace v5 only ccache's principal + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, + "foo@BAZ.ORG", &ccache); + } + if (!err) { + check_once_cc_ccache_set_principal( + ccache, cc_credentials_v5, "foo/BAZ@BAR.ORG", ccNoError, + "replace v5 only ccache's principal (empty ccache)"); + } + else { + log_error( + "cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + + // bad params + if (!err) { + check_once_cc_ccache_set_principal(ccache, cc_credentials_v5, + NULL, ccErrBadParam, + "NULL principal"); + } + + if (ccache) { + cc_ccache_destroy(ccache); + ccache = NULL; + } + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_set_principal */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_set_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_string_t stored_principal = NULL; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrNoMem, + ccErrInvalidCCache, + ccErrBadCredentialsVersion, + ccErrBadParam, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_set_principal + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_set_principal(ccache, cred_vers, in_principal); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + err = cc_ccache_get_principal(ccache, cred_vers, &stored_principal); + } + + // compare stored with input + if (!err) { + check_if(strcmp(stored_principal->data, in_principal), "expected princ == \"%s\" stored princ == \"%s\"", in_principal, stored_principal->data); + } + + if (stored_principal) { cc_string_release(stored_principal); } + + #endif /* cc_ccache_set_principal */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_store_credentials(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_ccache_t dup_ccache = NULL; + cc_credentials_union creds_union; + cc_string_t name = NULL; + + BEGIN_TEST("cc_ccache_store_credentials"); + + #ifndef cc_ccache_store_credentials + log_error("cc_ccache_store_credentials is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + // cred with matching version and realm + if (!err) { + err = new_v5_creds_union(&creds_union, "BAR.ORG"); + } + + if (!err) { + check_once_cc_ccache_store_credentials(ccache, &creds_union, ccNoError, "ok creds"); + } + + if (&creds_union) { release_v5_creds_union(&creds_union); } + + // try with bad params + check_once_cc_ccache_store_credentials(ccache, NULL, ccErrBadParam, "NULL creds param"); + + // invalid creds + if (!err) { + err = new_v5_creds_union(&creds_union, "BAR.ORG"); + } + + if (!err) { + if (creds_union.credentials.credentials_v5->client) { + free(creds_union.credentials.credentials_v5->client); + creds_union.credentials.credentials_v5->client = NULL; + } + check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrBadParam, "invalid creds (NULL client string)"); + } + + if (&creds_union) { release_v5_creds_union(&creds_union); } + + // non-existent ccache + if (ccache) { + err = cc_ccache_get_name(ccache, &name); + if (!err) { + err = cc_context_open_ccache(context, name->data, &dup_ccache); + } + if (name) { cc_string_release(name); } + if (dup_ccache) { cc_ccache_destroy(dup_ccache); } + } + + if (!err) { + err = new_v5_creds_union(&creds_union, "BAR.ORG"); + } + + if (!err) { + check_once_cc_ccache_store_credentials(ccache, &creds_union, ccErrInvalidCCache, "invalid ccache"); + } + + if (&creds_union) { release_v5_creds_union(&creds_union); } + if (ccache) { cc_ccache_release(ccache); } + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_store_credentials */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_store_credentials(cc_ccache_t ccache, const cc_credentials_union *credentials, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_credentials_iterator_t creds_iterator = NULL; + cc_credentials_t creds = NULL; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrBadParam, + ccErrInvalidCCache, + ccErrInvalidCredentials, + ccErrBadCredentialsVersion, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_store_credentials + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_store_credentials(ccache, credentials); + + // check returned error + check_err(err, expected_err, possible_return_values); + + // make sure credentials were truly stored + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); + } + while (!err) { + err = cc_credentials_iterator_next(creds_iterator, &creds); + if (creds) { + if (compare_v5_creds_unions(credentials, creds->data) == 0) { + break; + } + cc_credentials_release(creds); + creds = NULL; + } + } + + if (err == ccIteratorEnd) { + check_if((creds != NULL), "stored credentials not found in ccache"); + err = ccNoError; + } + if (creds) { cc_credentials_release(creds); } + + #endif /* cc_ccache_store_credentials */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_remove_credentials(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_ccache_t dup_ccache = NULL; + cc_credentials_t creds_array[10]; + cc_credentials_t creds = NULL; + cc_credentials_union creds_union; + cc_credentials_iterator_t creds_iterator = NULL; + cc_string_t name = NULL; + unsigned int i; + + BEGIN_TEST("cc_ccache_remove_credentials"); + + #ifndef cc_ccache_remove_credentials + log_error("cc_ccache_remove_credentials is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + // store 10 creds and retrieve their cc_credentials_t representations + for(i = 0; !err && (i < 10); i++) { + new_v5_creds_union(&creds_union, "BAR.ORG"); + err = cc_ccache_store_credentials(ccache, &creds_union); + if (&creds_union) { release_v5_creds_union(&creds_union); } + } + if (err) { + log_error("failure to store creds_union in remove_creds test"); + } + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); + } + i = 0; + while (!err && i < 10) { + err = cc_credentials_iterator_next(creds_iterator, &creds); + if (creds) { + creds_array[i++] = creds; + creds = NULL; + } + } + if (err == ccIteratorEnd) { err = ccNoError; } + + // remove 10 valid creds + for (i = 0; !err && (i < 8); i++) { + check_once_cc_ccache_remove_credentials(ccache, creds_array[i], ccNoError, "10 ok creds"); + } + + // NULL param + check_once_cc_ccache_remove_credentials(ccache, NULL, ccErrBadParam, "NULL creds in param"); + + // non-existent creds (remove same one twice) + check_once_cc_ccache_remove_credentials(ccache, creds_array[0], ccErrInvalidCredentials, "removed same creds twice"); + + // non-existent ccache + if (ccache) { + err = cc_ccache_get_name(ccache, &name); + if (!err) { + err = cc_context_open_ccache(context, name->data, &dup_ccache); + } + if (name) { cc_string_release(name); } + if (dup_ccache) { cc_ccache_destroy(dup_ccache); } + } + + if (!err) { + err = new_v5_creds_union(&creds_union, "BAR.ORG"); + } + + if (!err) { + check_once_cc_ccache_remove_credentials(ccache, creds_array[8], ccErrInvalidCCache, "invalid ccache"); + } + + for(i = 0; i < 10; i++) { + if (creds_array[i]) { cc_credentials_release(creds_array[i]); } + } + + if (ccache) { cc_ccache_release(ccache); } + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_remove_credentials */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_remove_credentials(cc_ccache_t ccache, cc_credentials_t in_creds, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_credentials_iterator_t creds_iterator = NULL; + cc_credentials_t creds = NULL; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrBadParam, + ccErrInvalidCCache, + ccErrInvalidCredentials, + ccErrCredentialsNotFound, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_remove_credentials + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_remove_credentials(ccache, in_creds); + + // check returned error + check_err(err, expected_err, possible_return_values); + + // make sure credentials were truly removed + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); + } + while (!err) { + err = cc_credentials_iterator_next(creds_iterator, &creds); + if (creds) { + if (compare_v5_creds_unions(in_creds->data, creds->data) == 0) { + break; + } + cc_credentials_release(creds); + creds = NULL; + } + } + + if (err == ccIteratorEnd) { + err = ccNoError; + } + else { + check_if((creds != NULL), "credentials not removed from ccache"); + } + if (creds) { cc_credentials_release(creds); } + + #endif /* cc_ccache_remove_credentials */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + + +int check_cc_ccache_new_credentials_iterator(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_ccache_t dup_ccache = NULL; + cc_credentials_iterator_t creds_iterator = NULL; + cc_string_t name = NULL; + + BEGIN_TEST("cc_ccache_new_credentials_iterator"); + + #ifndef cc_ccache_new_credentials_iterator + log_error("cc_ccache_new_credentials_iterator is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + // valid params + if (!err) { + check_once_cc_ccache_new_credentials_iterator(ccache, &creds_iterator, ccNoError, "valid params"); + } + if (creds_iterator) { + cc_credentials_iterator_release(creds_iterator); + creds_iterator = NULL; + } + + // NULL out param + if (!err) { + check_once_cc_ccache_new_credentials_iterator(ccache, NULL, ccErrBadParam, "NULL out iterator param"); + } + if (creds_iterator) { + cc_credentials_iterator_release(creds_iterator); + creds_iterator = NULL; + } + + // non-existent ccache + if (ccache) { + err = cc_ccache_get_name(ccache, &name); + if (!err) { + err = cc_context_open_ccache(context, name->data, &dup_ccache); + } + if (name) { cc_string_release(name); } + if (dup_ccache) { cc_ccache_destroy(dup_ccache); } + } + + if (!err) { + check_once_cc_ccache_new_credentials_iterator(ccache, &creds_iterator, ccErrInvalidCCache, "invalid ccache"); + } + + if (creds_iterator) { + cc_credentials_iterator_release(creds_iterator); + creds_iterator = NULL; + } + if (ccache) { cc_ccache_release(ccache); } + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_new_credentials_iterator */ + + END_TEST_AND_RETURN +} + + +cc_int32 check_once_cc_ccache_new_credentials_iterator(cc_ccache_t ccache, cc_credentials_iterator_t *iterator, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[5] = { + ccNoError, + ccErrBadParam, + ccErrNoMem, + ccErrCCacheNotFound, + ccErrInvalidCCache, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_new_credentials_iterator + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_new_credentials_iterator(ccache, iterator); + + // check returned error + check_err(err, expected_err, possible_return_values); + + #endif /* cc_ccache_new_credentials_iterator */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_ccache_get_change_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_time_t this_time = 0; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrInvalidCCache, + ccErrBadParam, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_get_change_time + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (last_time == NULL) { + err = cc_ccache_get_change_time(ccache, NULL); // passed NULL to compare against because intention is actually to pass bad param instead + } else { + err = cc_ccache_get_change_time(ccache, &this_time); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if ((!err) && last_time) { + check_if(this_time <= *last_time, "change time didn't increase when expected"); + *last_time = this_time; + } + + #endif /* cc_ccache_get_change_time */ + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_get_change_time(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t dummy_ccache = NULL; + cc_ccache_t ccache = NULL; + cc_credentials_union creds_union; + cc_credentials_iterator_t creds_iterator = NULL; + cc_credentials_t credentials = NULL; + cc_time_t last_time = 0; + + BEGIN_TEST("cc_ccache_get_change_time"); + + #ifndef cc_ccache_get_change_time + log_error("cc_ccache_get_change_time is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // create some ccaches (so that the one we keep around as 'ccache' is not default) + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (ccache) { + cc_ccache_release(ccache); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAZ.ORG", &ccache); + } + + // change it in all the ways it can change, checking after each + + // the ccache is created + if (!err) { + check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "new ccache (change time should be > 0)"); + } + + // the ccache is made default + if (!err) { + err = cc_ccache_set_default(ccache); + } + if (!err) { + check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "non-default ccache became default"); + } + + // the ccache is made not-default + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "something@ELSE.COM", &dummy_ccache); + } + if (!err) { + err = cc_ccache_set_default(dummy_ccache); + } + if (dummy_ccache) { + cc_ccache_release(dummy_ccache); + } + if (!err) { + check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "default ccache became non-default"); + } + + // try with bad params + + // NULL out param + if (!err) { + check_once_cc_ccache_get_change_time(ccache, NULL, ccErrBadParam, "NULL out param for time"); + } + + // store a credential + if (!err) { + new_v5_creds_union(&creds_union, "BAR.ORG"); + err = cc_ccache_store_credentials(ccache, &creds_union); + release_v5_creds_union(&creds_union); + } + check_once_cc_ccache_get_change_time(ccache, &last_time, ccNoError, "stored new credential"); + + if (!err) { + // change principal (fails with ccErrBadInternalMessage) + err = cc_ccache_set_principal(ccache, cc_credentials_v5, "foo@BAR.ORG"); + if (err) { + log_error("failed to change ccache's principal - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + err = ccNoError; + } + } + check_once_cc_context_get_change_time(context, &last_time, ccNoError, "after changing a principle"); + + // remove a credential + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); + } + if (!err) { + err = cc_credentials_iterator_next(creds_iterator, &credentials); + } + if (err == ccIteratorEnd) { + err = ccNoError; + } + if (!err) { + err = cc_ccache_remove_credentials(ccache, credentials); + } + check_once_cc_context_get_change_time(context, &last_time, ccNoError, "after removing a credential"); + + + // invalid ccache + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + check_once_cc_ccache_get_change_time(ccache, &last_time, ccErrInvalidCCache, "getting change time on destroyed ccache"); + } + + if (ccache) { cc_ccache_release(ccache); } + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_get_change_time */ + + END_TEST_AND_RETURN +} + + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_ccache_get_last_default_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_time_t this_time = 0; + + cc_int32 possible_return_values[5] = { + ccNoError, + ccErrInvalidCCache, + ccErrBadParam, + ccErrNeverDefault, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_get_last_default_time + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (last_time == NULL) { + err = cc_ccache_get_last_default_time(ccache, NULL); // passed NULL to compare against because intention is actually to pass bad param instead + } else { + err = cc_ccache_get_last_default_time(ccache, &this_time); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err && last_time) { + check_if(this_time > *last_time, "last default time isn't as expected"); + *last_time = this_time; + } + + #endif /* cc_ccache_get_last_default_time */ + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_get_last_default_time(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache_1 = NULL; + cc_ccache_t ccache_2 = NULL; + cc_time_t last_time_1 = 0; + cc_time_t last_time_2 = 0; + cc_string_t name = NULL; + + BEGIN_TEST("cc_ccache_get_last_default_time"); + + #ifndef cc_ccache_get_last_default_time + log_error("cc_ccache_get_last_default_time is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // create 2 ccaches + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@ONE.ORG", &ccache_1); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@TWO.ORG", &ccache_2); + } + + if (!err) { + err = cc_ccache_get_change_time(ccache_1, &last_time_1); + } + + // since we destroyed all ccaches before creating these two, + // ccache_1 should be default and ccache_2 should never have been default + if (!err) { + check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccNoError, "ccache_1 default at creation"); + check_once_cc_ccache_get_last_default_time(ccache_2, &last_time_2, ccErrNeverDefault, "ccache_2 never default"); + } + + // make ccache_2 default and check each of their times again + if (!err) { + err = cc_ccache_set_default(ccache_2); + } + if (!err) { + err = cc_ccache_get_change_time(ccache_2, &last_time_2); + } + if (!err) { + check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccNoError, "ccache_1 no longer default"); + check_once_cc_ccache_get_last_default_time(ccache_2, &last_time_2, ccNoError, "ccache_2 newly default"); + } + + // NULL param + if (!err) { + check_once_cc_ccache_get_last_default_time(ccache_1, NULL, ccErrBadParam, "NULL out param"); + } + + // non-existent ccache + if (ccache_2) { + cc_ccache_release(ccache_2); + ccache_2 = NULL; + } + if (!err) { + err = cc_ccache_get_name(ccache_1, &name); + } + if (!err) { + err = cc_context_open_ccache(context, name->data, &ccache_2); + } + if (!err) { + cc_ccache_destroy(ccache_2); + ccache_2 = NULL; + } + + if (!err) { + check_once_cc_ccache_get_last_default_time(ccache_1, &last_time_1, ccErrInvalidCCache, "destroyed ccache"); + } + + if (ccache_1) { cc_ccache_release(ccache_1); } + + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_get_last_default_time */ + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +int check_cc_ccache_move(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t source = NULL; + cc_ccache_t destination = NULL; + + cc_credentials_union creds_union; + unsigned int i = 0; + + BEGIN_TEST("cc_ccache_move"); + + #ifndef cc_ccache_move + log_error("cc_ccache_move is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // create 2 ccaches + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@ONE.ORG", &source); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@TWO.ORG", &destination); + } + + // store credentials in each + for (i = 0; !err && (i < 10); i++) { + new_v5_creds_union(&creds_union, "ONE.ORG"); + err = cc_ccache_store_credentials(source, &creds_union); + } + for (i = 0; !err && (i < 10); i++) { + new_v5_creds_union(&creds_union, "TWO.ORG"); + err = cc_ccache_store_credentials(destination, &creds_union); + } + + // move source into destination + if (!err) { + check_once_cc_ccache_move(source, destination, ccNoError, "valid params"); + } + + // NULL param + if (!err) { + check_once_cc_ccache_move(destination, NULL, ccErrBadParam, "NULL destination param"); + } + + // non-existent ccache + if (!err) { + check_once_cc_ccache_move(destination, source, ccErrInvalidCCache, "recently moved source as destination param"); + } + + if (source) { cc_ccache_release(source); } + if (destination) { cc_ccache_release(destination); } + + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_move */ + + END_TEST_AND_RETURN + + +} + +cc_int32 check_once_cc_ccache_move(cc_ccache_t source, cc_ccache_t destination, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_credentials_t dst_creds[10] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; + cc_credentials_t creds = NULL; + cc_credentials_iterator_t cred_iterator = NULL; + unsigned int i = 0; + + cc_string_t src_principal = NULL; + cc_string_t dst_principal = NULL; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrBadParam, + ccErrInvalidCCache, + ccErrCCacheNotFound, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_move + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (destination) { + // verify all of destination's credentials are no longer there (save a list and call remove_cred for each, expecting an err in response) + if (!err) { + err = cc_ccache_new_credentials_iterator(destination, &cred_iterator); + } + while (!err && (i < 10)) { + err = cc_credentials_iterator_next(cred_iterator, &creds); + if (creds) { + dst_creds[i++] = creds; + } + } + if (err == ccIteratorEnd) { + err = ccNoError; + } + if (cred_iterator) { + cc_credentials_iterator_release(cred_iterator); + cred_iterator = NULL; + } + + // verify that destination's principal has changed to source's (strcmp) + if (!err) { + err = cc_ccache_get_principal(source, cc_credentials_v5, &src_principal); + } + } + + + if (!err) { + err = cc_ccache_move(source, destination); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + + if (!err) { + // verify all of destination's credentials are no longer there (save a list and call remove_cred for each, expecting an err in response) + i = 0; + while (dst_creds[i] && (i < 10)) { + err = cc_ccache_remove_credentials(destination, dst_creds[i]); + check_if(!(!err || err == ccErrCredentialsNotFound || ccErrInvalidCredentials), "credentials in destination not removed as promised"); + cc_credentials_release(dst_creds[i]); + i++; + } + err = ccNoError; + } + + // verify that destination's principal has changed to source's (strcmp) + if (!err) { + err = cc_ccache_get_principal(destination, cc_credentials_v5, &dst_principal); + } + if (!err) { + check_if(strcmp(src_principal->data, dst_principal->data), "destination principal not overwritten by source"); + } + + // verify that handles for source are no longer valid (get_change_time) + if (src_principal) { + cc_string_release(src_principal); + src_principal = NULL; + } + if (!err) { + err = cc_ccache_get_principal(source, cc_credentials_v5, &src_principal); + check_if(err != ccErrInvalidCCache, "source ccache was not invalidated after move"); + } + + + if (cred_iterator) { cc_credentials_iterator_release(cred_iterator); } + if (src_principal) { cc_string_release(src_principal); } + if (dst_principal) { cc_string_release(dst_principal); } + + #endif /* cc_ccache_move */ + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_ccache_compare(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache_a = NULL; + cc_ccache_t ccache_b = NULL; + cc_uint32 equal = 0; + + BEGIN_TEST("cc_ccache_compare"); + + #ifndef cc_ccache_compare + log_error("cc_ccache_compare is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache_a); + } + if (!err) { + err = cc_context_open_default_ccache(context, &ccache_b); + } + + equal = 1; + check_once_cc_ccache_compare(ccache_a, ccache_a, &equal, ccNoError, "compare ccache with same pointer"); + equal = 1; + check_once_cc_ccache_compare(ccache_a, ccache_b, &equal, ccNoError, "compare different handles to same ccache"); + + if (ccache_b) { + cc_ccache_release(ccache_b); + ccache_b = NULL; + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "baz@BAR.ORG", &ccache_b); + } + equal = 0; + check_once_cc_ccache_compare(ccache_a, ccache_b, &equal, ccNoError, "compare different ccaches"); + check_once_cc_ccache_compare(ccache_a, NULL, &equal, ccErrBadParam, "NULL compare_to ccache"); + check_once_cc_ccache_compare(ccache_a, ccache_b, NULL, ccErrBadParam, "NULL out param"); + + if (ccache_a) { cc_ccache_release(ccache_a); } + if (ccache_b) { cc_ccache_release(ccache_b); } + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_compare */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_compare(cc_ccache_t ccache, cc_ccache_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_uint32 actually_equal = 0; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrInvalidContext, + ccErrBadParam, + ccErrServerUnavailable, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_compare + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (equal) { + actually_equal = *equal; + } + + err = cc_ccache_compare(ccache, compare_to, equal); + + if (!err && equal) { + if (actually_equal) { + check_if(actually_equal != *equal, "equal ccaches not considered equal"); + } + else { + check_if(actually_equal != *equal, "non-equal ccaches considered equal"); + } + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + #endif /* cc_ccache_compare */ + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_ccache_get_kdc_time_offset(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_time_t time_offset = 0; + + BEGIN_TEST("cc_ccache_get_kdc_time_offset"); + + #ifndef cc_ccache_get_kdc_time_offset + log_error("cc_ccache_get_kdc_time_offset is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + time_offset = 0; + check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, &time_offset, ccErrTimeOffsetNotSet, "brand new ccache (offset not yet set)"); + + time_offset = 10; + if (!err) { + err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, time_offset); + } + if (!err) { + check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, &time_offset, ccNoError, "offset set for v5"); + } + + check_once_cc_ccache_get_kdc_time_offset(ccache, cc_credentials_v5, NULL, ccErrBadParam, "NULL time_offset out param"); + + if (ccache) { cc_ccache_release(ccache); } + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_get_kdc_time_offset */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_get_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t *time_offset, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_time_t expected_offset; + + cc_int32 possible_return_values[7] = { + ccNoError, + ccErrTimeOffsetNotSet, + ccErrCCacheNotFound, + ccErrInvalidCCache, + ccErrBadParam, + ccErrServerUnavailable, + ccErrBadCredentialsVersion, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_get_kdc_time_offset + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (time_offset) { + expected_offset = *time_offset; + } + + err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, time_offset); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err && time_offset) { + check_if(*time_offset != expected_offset, "kdc time offset doesn't match expected value"); + } + + #endif /* cc_ccache_get_kdc_time_offset */ + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_ccache_set_kdc_time_offset(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_set_kdc_time_offset"); + + #ifndef cc_ccache_set_kdc_time_offset + log_error("cc_ccache_set_kdc_time_offset is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + check_once_cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, 0, ccNoError, "first time setting offset (v5)"); + + if (ccache) { cc_ccache_release(ccache); } + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_set_kdc_time_offset */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_set_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t time_offset, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_time_t stored_offset = 0; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrCCacheNotFound, + ccErrInvalidCCache, + ccErrBadParam, + ccErrServerUnavailable, + ccErrBadCredentialsVersion, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_set_kdc_time_offset + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_set_kdc_time_offset(ccache, credentials_version, time_offset); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, &stored_offset); + } + + if (!err) { + check_if(time_offset != stored_offset, "kdc time offset doesn't match expected value"); + } + + #endif /* cc_ccache_set_kdc_time_offset */ + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_ccache_clear_kdc_time_offset(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_ccache_clear_kdc_time_offset"); + + #ifndef cc_ccache_clear_kdc_time_offset + log_error("cc_ccache_clear_kdc_time_offset is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + + check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v5, ccNoError, "clearing an offset that was never set (v5)"); + + err = cc_ccache_set_kdc_time_offset(ccache, cc_credentials_v5, 0); + + check_once_cc_ccache_clear_kdc_time_offset(ccache, cc_credentials_v5, ccNoError, "clearing v5"); + + if (ccache) { cc_ccache_release(ccache); } + + if (context) { + err = destroy_all_ccaches(context); + cc_context_release(context); + } + + #endif /* cc_ccache_clear_kdc_time_offset */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_clear_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_time_t stored_offset = 0; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrCCacheNotFound, + ccErrInvalidCCache, + ccErrBadParam, + ccErrServerUnavailable, + ccErrBadCredentialsVersion, + }; + BEGIN_CHECK_ONCE(description); + + #ifdef cc_ccache_clear_kdc_time_offset + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_ccache_clear_kdc_time_offset(ccache, credentials_version); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + err = cc_ccache_get_kdc_time_offset(ccache, credentials_version, &stored_offset); + check_if(err != ccErrTimeOffsetNotSet, "time offset not cleared"); + } + + #endif /* cc_ccache_clear_kdc_time_offset */ + + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_ccache.h b/krb5-1.21.3/src/ccapi/test/test_ccapi_ccache.h new file mode 100644 index 00000000..ecb06219 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_ccache.h @@ -0,0 +1,49 @@ +#ifndef _TEST_CCAPI_CCACHE_H_ +#define _TEST_CCAPI_CCACHE_H_ + +#include "test_ccapi_globals.h" + +int check_cc_ccache_release(void); +cc_int32 check_once_cc_ccache_release(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description); +int check_cc_ccache_destroy(void); +cc_int32 check_once_cc_ccache_destroy(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description); +int check_cc_ccache_set_default(void); +cc_int32 check_once_cc_ccache_set_default(cc_context_t context, cc_ccache_t ccache, cc_int32 expected_err, const char *description); +int check_cc_ccache_get_credentials_version(void); +cc_int32 check_once_cc_ccache_get_credentials_version(cc_ccache_t ccache, cc_uint32 expected_cred_vers, cc_int32 expected_err, const char *description); +int check_cc_ccache_get_name(void); +cc_int32 check_once_cc_ccache_get_name(cc_ccache_t ccache, const char *expected_name, cc_int32 expected_err, const char *description); +int check_cc_ccache_get_principal(void); +cc_int32 check_once_cc_ccache_get_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *expected_principal, cc_int32 expected_err, const char *description); +int check_cc_ccache_set_principal(void); +cc_int32 check_once_cc_ccache_set_principal(cc_ccache_t ccache, cc_uint32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description); + +int check_cc_ccache_store_credentials(void); +cc_int32 check_once_cc_ccache_store_credentials(cc_ccache_t ccache, const cc_credentials_union *credentials, cc_int32 expected_err, const char *description); +int check_cc_ccache_remove_credentials(void); +cc_int32 check_once_cc_ccache_remove_credentials(cc_ccache_t ccache, cc_credentials_t in_creds, cc_int32 expected_err, const char *description); + +int check_cc_ccache_new_credentials_iterator(void); +cc_int32 check_once_cc_ccache_new_credentials_iterator(cc_ccache_t ccache, cc_credentials_iterator_t *iterator, cc_int32 expected_err, const char *description); + +int check_cc_ccache_get_change_time(void); +cc_int32 check_once_cc_ccache_get_change_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description); +int check_cc_ccache_get_last_default_time(void); +cc_int32 check_once_cc_ccache_get_last_default_time(cc_ccache_t ccache, cc_time_t *last_time, cc_int32 expected_err, const char *description); + +int check_cc_ccache_move(void); +cc_int32 check_once_cc_ccache_move(cc_ccache_t source, cc_ccache_t destination, cc_int32 expected_err, const char *description); + +int check_cc_ccache_compare(void); +cc_int32 check_once_cc_ccache_compare(cc_ccache_t ccache, cc_ccache_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description); + +int check_cc_ccache_get_kdc_time_offset(void); +cc_int32 check_once_cc_ccache_get_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t *time_offset, cc_int32 expected_err, const char *description); + +int check_cc_ccache_set_kdc_time_offset(void); +cc_int32 check_once_cc_ccache_set_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_time_t time_offset, cc_int32 expected_err, const char *description); + +int check_cc_ccache_clear_kdc_time_offset(void); +cc_int32 check_once_cc_ccache_clear_kdc_time_offset(cc_ccache_t ccache, cc_int32 credentials_version, cc_int32 expected_err, const char *description); + +#endif /* _TEST_CCAPI_CCACHE_H_ */ diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_check.c b/krb5-1.21.3/src/ccapi/test/test_ccapi_check.c new file mode 100644 index 00000000..7f55b455 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_check.c @@ -0,0 +1,37 @@ +#include "test_ccapi_check.h" + +int _check_if(int expression, const char *file, int line, const char *expression_string, const char *format, ...) { + if (expression) { + failure_count++; + // call with NULL format to get a generic error message + if (format == NULL) { + _log_error(file, line, expression_string); + } + // call with format and varargs for a more useful error message + else { + va_list ap; + va_start(ap, format); + _log_error_v(file, line, format, ap); + va_end(ap); + } + + if (current_test_activity) { + fprintf(stdout, " (%s)", current_test_activity); + } + } + + return (expression != 0); +} + +int array_contains_int(cc_int32 *array, int size, cc_int32 value) { + if (array != NULL && size > 0) { + int i = 0; + while (i < size && array[i] != value) { + i++; + } + if (i < size) { + return 1; + } + } + return 0; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_check.h b/krb5-1.21.3/src/ccapi/test/test_ccapi_check.h new file mode 100644 index 00000000..0a953481 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_check.h @@ -0,0 +1,43 @@ +#ifndef _TEST_CCAPI_CHECK_H_ +#define _TEST_CCAPI_CHECK_H_ + +#include +#include +#include "test_ccapi_log.h" +#include "test_ccapi_globals.h" + +int _check_if(int expression, const char *file, int line, const char *expression_string, const char *format, ...); + +#define check_int(a, b) \ + check_if(a != b, NULL) + +/* + * if expression evaluates to true, check_if increments the failure_count and prints: + * + * check_if(a!=a, NULL); + * ==> "/path/to/file:line: a!=a" + * + * check_if(a!=a, "This shouldn't be happening"); + * ==> "/path/to/file:line: This shouldn't be happening" + * + * check_if(a!=a, "This has happened %d times now", 3); + * ==> "/path/to/file:line: This has happened 3 times now" +*/ + +#define check_if(expression, format, ...) \ + _check_if(expression, __FILE__, __LINE__, #expression, format , ## __VA_ARGS__) + +#define check_if_not(expression, format, ...) \ + check_if(!(expression), format, ## __VA_ARGS__) + +// first check if err is what we were expecting to get back +// then check if err is even in the set of errors documented for the function +#define check_err(err, expected_err, possible_return_values) \ + do { \ + check_if(err != expected_err, "unexpected error %s (%d), expected %s (%d)", translate_ccapi_error(err), err, translate_ccapi_error(expected_err), expected_err); \ + check_if_not(array_contains_int(possible_return_values, possible_ret_val_count, err), "error not documented as a possible return value: %s (%d)", translate_ccapi_error(err), err); \ + } while( 0 ) + +int array_contains_int(cc_int32 *array, int size, cc_int32 value); + +#endif /* _TEST_CCAPI_CHECK_H_ */ diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_constants.c b/krb5-1.21.3/src/ccapi/test/test_ccapi_constants.c new file mode 100644 index 00000000..57377262 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_constants.c @@ -0,0 +1,64 @@ +#include "test_ccapi_constants.h" +#include "test_ccapi_globals.h" +#include "test_ccapi_check.h" + +int check_constants(void) { + BEGIN_TEST("constants"); + /* API versions */ + + check_int(ccapi_version_2, 2); + check_int(ccapi_version_3, 3); + check_int(ccapi_version_4, 4); + check_int(ccapi_version_5, 5); + check_int(ccapi_version_6, 6); + + /* Errors */ + + check_int(ccNoError , 0 ); // 0 + check_int(ccIteratorEnd , 201); // 201 + check_int(ccErrBadParam , 202); // 202 + check_int(ccErrNoMem , 203); // 203 + check_int(ccErrInvalidContext , 204); // 204 + check_int(ccErrInvalidCCache , 205); // 205 + check_int(ccErrInvalidString , 206); // 206 + check_int(ccErrInvalidCredentials , 207); // 207 + check_int(ccErrInvalidCCacheIterator , 208); // 208 + check_int(ccErrInvalidCredentialsIterator , 209); // 209 + check_int(ccErrInvalidLock , 210); // 210 + check_int(ccErrBadName , 211); // 211 + check_int(ccErrBadCredentialsVersion , 212); // 212 + check_int(ccErrBadAPIVersion , 213); // 213 + check_int(ccErrContextLocked , 214); // 214 + check_int(ccErrContextUnlocked , 215); // 215 + check_int(ccErrCCacheLocked , 216); // 216 + check_int(ccErrCCacheUnlocked , 217); // 217 + check_int(ccErrBadLockType , 218); // 218 + check_int(ccErrNeverDefault , 219); // 219 + check_int(ccErrCredentialsNotFound , 220); // 220 + check_int(ccErrCCacheNotFound , 221); // 221 + check_int(ccErrContextNotFound , 222); // 222 + check_int(ccErrServerUnavailable , 223); // 223 + check_int(ccErrServerInsecure , 224); // 224 + check_int(ccErrServerCantBecomeUID , 225); // 225 + check_int(ccErrTimeOffsetNotSet , 226); // 226 + check_int(ccErrBadInternalMessage , 227); // 227 + check_int(ccErrNotImplemented , 228); // 228 + + /* Credentials versions */ + + check_int(cc_credentials_v5, 2); + + /* Lock types */ + + check_int(cc_lock_read, 0); + check_int(cc_lock_write, 1); + check_int(cc_lock_upgrade, 2); + check_int(cc_lock_downgrade, 3); + + /* Locking Modes */ + + check_int(cc_lock_noblock, 0); + check_int(cc_lock_block, 1); + + END_TEST_AND_RETURN +} diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_constants.h b/krb5-1.21.3/src/ccapi/test/test_ccapi_constants.h new file mode 100644 index 00000000..bc3f4f3b --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_constants.h @@ -0,0 +1,6 @@ +#ifndef _TEST_CCAPI_CONSTANTS_H_ +#define _TEST_CCAPI_CONSTANTS_H_ + +int check_constants(void); + +#endif /* _TEST_CCAPI_CONSTANTS_H_ */ diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_context.c b/krb5-1.21.3/src/ccapi/test/test_ccapi_context.c new file mode 100644 index 00000000..2dc348ea --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_context.c @@ -0,0 +1,987 @@ +#include +#include "test_ccapi_context.h" +#include +#include "test_ccapi_check.h" +#include "test_ccapi_util.h" + +int check_cc_initialize(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + + BEGIN_TEST("cc_initialize"); + + // try every api_version + err = check_once_cc_initialize(&context, ccapi_version_2, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_2"); // err == CC_BAD_API_VERSION (9) would be imported by CredentialsCache2.h + err = check_once_cc_initialize(&context, ccapi_version_3, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_3"); // !err + err = check_once_cc_initialize(&context, ccapi_version_4, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_4"); // " + err = check_once_cc_initialize(&context, ccapi_version_5, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_5"); // " + err = check_once_cc_initialize(&context, ccapi_version_6, NULL, NULL, ccNoError, "cc_initialize with ccapi_version_6"); // " + + // try bad api_version + err = check_once_cc_initialize(&context, INT_MAX, NULL, NULL, ccErrBadAPIVersion, NULL); // err == ccErrBadAPIVersion + + // try bad param + err = check_once_cc_initialize(NULL, ccapi_version_3, NULL, NULL, ccErrBadParam, NULL); // err == ccErrBadParam + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_initialize(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_context_t context; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrNoMem, + ccErrBadAPIVersion, + ccErrBadParam, + }; + + BEGIN_CHECK_ONCE(description); + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_initialize(out_context, in_version, out_supported_version, out_vendor); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (out_context) { context = *out_context; } + else { context = NULL; } + + // check output parameters + if (!err) { + check_if(context == NULL, NULL); + if (context) { + cc_context_release(context); + *out_context = NULL; + } + } else { + check_if(context != NULL, NULL); + } + + return err; +} + +int check_cc_context_release(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + + BEGIN_TEST("cc_context_release"); + + #ifndef cc_context_release + log_error("cc_context_release is not implemented yet"); + failure_count++; + #else + + // try with valid context + err = check_once_cc_context_release(&context, ccNoError, NULL); + + // try with NULL + //err = check_once_cc_context_release(NULL, ccErrInvalidContext); + /* calling with NULL context crashes, because this macro expands to + ((NULL) -> functions -> release (NULL)) which is dereferencing NULL which is bad. */ + + if (context) { cc_context_release(context); } + + #endif /* cc_context_release */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_release(cc_context_t *out_context, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_context_t context = NULL; + + cc_int32 possible_return_values[2] = { + ccNoError, + ccErrInvalidContext, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_release + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (out_context) { + err = cc_initialize(out_context, ccapi_version_3, NULL, NULL); + if (!err) { + context = *out_context; + } + } + + if (err != ccNoError) { + log_error("failure in cc_initialize, unable to perform check"); + return err; + } + else { + err = cc_context_release(context); + // check returned error + check_err(err, expected_err, possible_return_values); + } + + *out_context = NULL; + + #endif /* cc_context_release */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_get_change_time(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_time_t last_change_time = 0; + cc_ccache_t ccache = NULL; + cc_credentials_union creds_union; + cc_credentials_iterator_t creds_iterator = NULL; + cc_credentials_t credentials = NULL; + + BEGIN_TEST("cc_context_get_change_time"); + + #ifndef cc_context_get_change_time + log_error("cc_context_get_change_time is not implemented yet"); + failure_count++; + #else + + /* + * Make a context + * make sure the change time changes after: + * a ccache is created + * a ccache is destroyed + * a credential is stored + * a credential is removed + * a ccache principal is changed + * the default ccache is changed + * clean up memory + */ + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + + // try bad parameters first + err = check_once_cc_context_get_change_time(context, NULL, ccErrBadParam, "NULL param, should fail"); + + // make sure we have a default ccache + err = cc_context_open_default_ccache(context, &ccache); + if (err == ccErrCCacheNotFound) { + err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache); + } + if (!err) { + err = cc_ccache_release(ccache); + } + // either the default ccache already existed or we just created it + // either way, the get_change_time should now give something > 0 + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "first-run, should be > 0"); + + // create a ccache + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after creating a new ccache"); + + // store a credential + if (!err) { + new_v5_creds_union(&creds_union, "BAR.ORG"); + err = cc_ccache_store_credentials(ccache, &creds_union); + release_v5_creds_union(&creds_union); + } + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after storing a credential"); + + if (!err) { + // change principal (fails with ccErrBadInternalMessage) + err = cc_ccache_set_principal(ccache, cc_credentials_v5, "foo@BAR.ORG"); + if (err) { + log_error("failed to change ccache's principal - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + err = ccNoError; + } + } + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after changing a principle"); + + // remove a credential + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &creds_iterator); + } + if (!err) { + err = cc_credentials_iterator_next(creds_iterator, &credentials); + } + if (err == ccIteratorEnd) { + err = ccNoError; + } + if (!err) { + err = cc_ccache_remove_credentials(ccache, credentials); + } + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after removing a credential"); + + if (!err) { + // change default ccache + err = cc_ccache_set_default(ccache); + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after changing default ccache"); + } + + if (ccache) { + // destroy a ccache + err = cc_ccache_destroy(ccache); + check_once_cc_context_get_change_time(context, &last_change_time, ccNoError, "after destroying a ccache"); + } + } + + if (context) { cc_context_release(context); } + + #endif /* cc_get_change_time */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_get_change_time(cc_context_t context, cc_time_t *time, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_time_t last_change_time; + cc_time_t current_change_time = 0; + + cc_int32 possible_return_values[3] = { + ccNoError, + ccErrInvalidContext, + ccErrBadParam, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_get_change_time + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (time != NULL) { // if we were passed NULL, then we're looking to pass a bad param + err = cc_context_get_change_time(context, ¤t_change_time); + } else { + err = cc_context_get_change_time(context, NULL); + } + + check_err(err, expected_err, possible_return_values); + + if (!err) { + last_change_time = *time; + check_if(current_change_time <= last_change_time, "context change time did not increase when it was supposed to (%d <= %d)", current_change_time, last_change_time); + *time = current_change_time; + } + + #endif /* cc_context_get_change_time */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_get_default_ccache_name(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_string_t name = NULL; + + BEGIN_TEST("cc_context_get_default_ccache_name"); + + #ifndef cc_context_get_default_ccache_name + log_error("cc_context_get_default_ccache_name is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + // try bad parameters first + err = check_once_cc_context_get_default_ccache_name(context, NULL, ccErrBadParam, NULL); + + // try with no default + err = destroy_all_ccaches(context); + err = cc_context_open_default_ccache(context, &ccache); + if (err != ccErrCCacheNotFound) { + log_error("didn't remove all ccaches"); + } + err = check_once_cc_context_get_default_ccache_name(context, &name, ccNoError, NULL); + + // try normally + err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + if (ccache) { cc_ccache_release(ccache); } + err = check_once_cc_context_get_default_ccache_name(context, &name, ccNoError, NULL); + + } + + if (context) { cc_context_release(context); } + + #endif /* cc_context_get_default_ccache_name */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_get_default_ccache_name(cc_context_t context, cc_string_t *name, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrInvalidContext, + ccErrBadParam, + ccErrNoMem, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_get_default_ccache_name + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (name != NULL) { // if we were passed NULL, then we're looking to pass a bad param + err = cc_context_get_default_ccache_name(context, name); + } else { + err = cc_context_get_default_ccache_name(context, NULL); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + // not really anything else to check + + if (name && *name) { cc_string_release(*name); } + + #endif /* cc_context_get_default_ccache_name */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_open_ccache(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_string_t name = NULL; + + BEGIN_TEST("cc_context_open_ccache"); + + #ifndef cc_context_open_ccache + log_error("cc_context_open_ccache is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + // make sure we have a default ccache + err = cc_context_open_default_ccache(context, &ccache); + if (err == ccErrCCacheNotFound) { + err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache); + } + if (!err) { + err = cc_ccache_release(ccache); + ccache = NULL; + } + + // try default ccache + err = cc_context_get_default_ccache_name(context, &name); + if (!err) { + err = check_once_cc_context_open_ccache(context, name->data, &ccache, ccNoError, NULL); + } + + // try bad parameters + err = check_once_cc_context_open_ccache(context, NULL, &ccache, ccErrBadParam, NULL); + err = check_once_cc_context_open_ccache(context, name->data, NULL, ccErrBadParam, NULL); + + // try a ccache that doesn't exist (create one and then destroy it) + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + if (!err) { + err = cc_ccache_get_name(ccache, &name); + } + if (!err) { + err = cc_ccache_destroy(ccache); + ccache = NULL; + } + + err = check_once_cc_context_open_ccache(context, name->data, &ccache, ccErrCCacheNotFound, NULL); + } + + if (context) { cc_context_release(context); } + + #endif /* cc_context_open_ccache */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_open_ccache(cc_context_t context, const char *name, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_string_t stored_name = NULL; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrBadName, + ccErrInvalidContext, + ccErrNoMem, + ccErrCCacheNotFound, + ccErrBadParam, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_open_ccache + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (ccache != NULL) { // if we were passed NULL, then we're looking to pass a bad param + err = cc_context_open_ccache(context, name, ccache); + } else { + err = cc_context_open_ccache(context, name, NULL); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(*ccache == NULL, NULL); + + if (!err) { + err = cc_ccache_get_name(*ccache, &stored_name); + } + if (!err) { + check_if(strcmp(stored_name->data, name), NULL); + } + if (stored_name) { cc_string_release(stored_name); } + + + if (ccache && *ccache) { + cc_ccache_release(*ccache); + *ccache = NULL; + } + } + + #endif /* cc_context_open_ccache */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_open_default_ccache(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + + BEGIN_TEST("cc_context_open_default_ccache"); + + #ifndef cc_context_open_default_ccache + log_error("cc_context_open_default_ccache is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + // make sure we have a default ccache + err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache); + if (ccache) { cc_ccache_release(ccache); } + + // try default ccache + if (!err) { + err = check_once_cc_context_open_default_ccache(context, &ccache, ccNoError, NULL); + } + + // try bad parameters + err = check_once_cc_context_open_default_ccache(context, NULL, ccErrBadParam, NULL); + + // try with no default ccache (destroy all ccaches first) + err = destroy_all_ccaches(context); + + err = check_once_cc_context_open_default_ccache(context, &ccache, ccErrCCacheNotFound, NULL); + } + + if (context) { cc_context_release(context); } + + #endif /* cc_context_open_default_ccache */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_open_default_ccache(cc_context_t context, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_string_t given_name = NULL; + cc_string_t default_name = NULL; + + cc_int32 possible_return_values[5] = { + ccNoError, + ccErrInvalidContext, + ccErrNoMem, + ccErrCCacheNotFound, + ccErrBadParam, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_open_default_ccache + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (ccache != NULL) { // if we were passed NULL, then we're looking to pass a bad param + err = cc_context_open_default_ccache(context, ccache); + } else { + err = cc_context_open_default_ccache(context, NULL); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(*ccache == NULL, NULL); + + // make sure this ccache is the one we were looking to get back (compare name with cc_context_get_default_ccache_name) + err = cc_ccache_get_name(*ccache, &given_name); + err = cc_context_get_default_ccache_name(context, &default_name); + if (given_name && default_name) { + check_if(strcmp(given_name->data, default_name->data), "name of ccache returned by cc_context_open_default_ccache doesn't match name returned by cc_context_get_default_ccache_name"); + } + if (given_name) { cc_string_release(given_name); } + if (default_name) { cc_string_release(default_name); } + + if (ccache && *ccache) { + cc_ccache_release(*ccache); + *ccache = NULL; + } + } + + #endif /* cc_context_open_default_ccache */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_create_ccache(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_string_t name = NULL; + + BEGIN_TEST("cc_context_create_ccache"); + + #ifndef cc_context_create_ccache + log_error("cc_context_create_ccache is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + // try making a ccache with a non-unique name (the existing default's name) + if (!err) { + err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo/bar@BAZ.ORG", &ccache); + } + if (!err) { + err = cc_ccache_get_name(ccache, &name); + } + if (ccache) { cc_ccache_release(ccache); } + if (!err) { + err = check_once_cc_context_create_ccache(context, name->data, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccNoError, NULL); + } + + // try making a ccache with a unique name (the now destroyed default's name) + if (ccache) { cc_ccache_destroy(ccache); } + if (!err) { + err = check_once_cc_context_create_ccache(context, name->data, cc_credentials_v5, "foo/baz@BAR.ORG", &ccache, ccNoError, NULL); + } + + // try bad parameters + err = check_once_cc_context_create_ccache(context, NULL, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccErrBadParam, "NULL name"); // NULL name + err = check_once_cc_context_create_ccache(context, "name", cc_credentials_v5, NULL, &ccache, ccErrBadParam, "NULL principal"); // NULL principal + err = check_once_cc_context_create_ccache(context, "name", cc_credentials_v5, "foo@BAR.ORG", NULL, ccErrBadParam, "NULL ccache"); // NULL ccache + } + + if (name) { cc_string_release(name); } + if (ccache) { cc_ccache_destroy(ccache); } + if (context) { cc_context_release(context); } + + #endif /* cc_context_create_ccache */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_create_ccache(cc_context_t context, const char *name, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_string_t stored_name = NULL; + cc_string_t stored_principal = NULL; + cc_uint32 stored_creds_vers = 0; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrBadName, + ccErrBadParam, + ccErrInvalidContext, + ccErrNoMem, + ccErrBadCredentialsVersion, + }; + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_create_ccache + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_context_create_ccache(context, name, cred_vers, principal, ccache); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(*ccache == NULL, NULL); + + // make sure all of the ccache's info matches what we gave it + // name + err = cc_ccache_get_name(*ccache, &stored_name); + if (!err) { check_if(strcmp(stored_name->data, name), NULL); } + if (stored_name) { cc_string_release(stored_name); } + // cred_vers + // FIXME Documented function name of cc_ccache_get_credentials_version is a typo. + // FIXME Documented type of creds param the wrong signedness (should be unsigned) for cc_ccache_get_credentials_version, cc_context_create_ccache, cc_context_create_default_ccache, cc_context_create_new_ccache + err = cc_ccache_get_credentials_version(*ccache, &stored_creds_vers); + if (!err) { check_if(stored_creds_vers != cred_vers, NULL); } + // principal + err = cc_ccache_get_principal(*ccache, cc_credentials_v5, &stored_principal); + if (!err) { check_if(strcmp(stored_principal->data, principal), NULL); } + if (stored_principal) { cc_string_release(stored_principal); } + + if (ccache && *ccache) { + cc_ccache_destroy(*ccache); + *ccache = NULL; + } + } + + #endif /* cc_context_create_ccache */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_create_default_ccache(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_string_t name = NULL; + + BEGIN_TEST("cc_context_create_default_ccache"); + + #ifndef cc_context_create_default_ccache + log_error("cc_context_create_default_ccache is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + // try making the default when there are no existing ccaches + err = destroy_all_ccaches(context); + if (!err) { + err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccNoError, NULL); + } + if (ccache) { cc_ccache_release(ccache); } + + // try making a new default when one already exists + if (!err) { + err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, "foo/baz@BAR.ORG", &ccache, ccNoError, NULL); + } + + // try bad parameters + err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, NULL, &ccache, ccErrBadParam, "NULL principal"); // NULL principal + err = check_once_cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", NULL, ccErrBadParam, "NULL ccache"); // NULL ccache + } + + if (name) { cc_string_release(name); } + if (ccache) { cc_ccache_destroy(ccache); } + if (context) { cc_context_release(context); } + + #endif /* cc_context_create_default_ccache */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_create_default_ccache(cc_context_t context, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_string_t stored_principal = NULL; + cc_uint32 stored_creds_vers = 0; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrBadName, // how can this be possible when the name isn't a parameter? + ccErrBadParam, + ccErrInvalidContext, + ccErrNoMem, + ccErrBadCredentialsVersion, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_create_default_ccache + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_context_create_default_ccache(context, cred_vers, principal, ccache); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + if (ccache) { check_if(*ccache == NULL, NULL); } + // make sure all of the ccache's info matches what we gave it + // cred_vers + err = cc_ccache_get_credentials_version(*ccache, &stored_creds_vers); + if (!err) { check_if(stored_creds_vers != cred_vers, NULL); } + // principal + err = cc_ccache_get_principal(*ccache, cc_credentials_v5, &stored_principal); + if (!err) { check_if(strcmp(stored_principal->data, principal), NULL); } + if (stored_principal) { cc_string_release(stored_principal); } + + if (ccache && *ccache) { + cc_ccache_release(*ccache); + *ccache = NULL; + } + } + + #endif /* cc_context_create_default_ccache */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_create_new_ccache(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_string_t name = NULL; + + BEGIN_TEST("cc_context_create_new_ccache"); + + #ifndef cc_context_create_new_ccache + log_error("cc_context_create_new_ccache is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + // try making when there are no existing ccaches (should have name of default) + err = destroy_all_ccaches(context); + if (!err) { + err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v5, "foo@BAR.ORG", &ccache, ccNoError, NULL); + } + if (ccache) { cc_ccache_release(ccache); } + + // try making a new ccache when one already exists (should not have name of default) + if (!err) { + err = check_once_cc_context_create_new_ccache(context, 0, cc_credentials_v5, "foo/baz@BAR.ORG", &ccache, ccNoError, NULL); + } + if (ccache) { cc_ccache_release(ccache); } + + // try bad parameters + err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v5, NULL, &ccache, ccErrBadParam, "NULL principal"); // NULL principal + err = check_once_cc_context_create_new_ccache(context, 1, cc_credentials_v5, "foo@BAR.ORG", NULL, ccErrBadParam, "NULL ccache"); // NULL ccache + } + + if (name) { cc_string_release(name); } + if (ccache) { cc_ccache_destroy(ccache); } + if (context) { cc_context_release(context); } + + #endif /* cc_context_create_new_ccache */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_create_new_ccache(cc_context_t context, cc_int32 should_be_default, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description) { + cc_int32 err = 0; + cc_string_t name = NULL; + cc_string_t stored_name = NULL; + cc_string_t stored_principal = NULL; + cc_uint32 stored_creds_vers = 0; + + cc_int32 possible_return_values[6] = { + ccNoError, + ccErrBadName, // how can this be possible when the name isn't a parameter? + ccErrBadParam, + ccErrInvalidContext, + ccErrNoMem, + ccErrBadCredentialsVersion, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_create_new_ccache + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_context_create_new_ccache(context, cred_vers, principal, ccache); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + if (ccache) { check_if(*ccache == NULL, NULL); } + // make sure all of the ccache's info matches what we gave it + if (!err) { + err = cc_context_get_default_ccache_name(context, &name); + } + if (!err) { + err = cc_ccache_get_name(*ccache, &stored_name); + } + if (!err) { + if (should_be_default) { + check_if(strcmp(stored_name->data, name->data), "new ccache does not have name of default"); + } + else { + check_if((strcmp(stored_name->data, name->data) == 0), "new cache has name of default"); + } + } + if (name) { cc_string_release(name); } + if (stored_name) { cc_string_release(stored_name); } + + // cred_vers + err = cc_ccache_get_credentials_version(*ccache, &stored_creds_vers); + if (!err) { check_if(stored_creds_vers != cred_vers, NULL); } + // principal + err = cc_ccache_get_principal(*ccache, cc_credentials_v5, &stored_principal); + if (!err) { check_if(strcmp(stored_principal->data, principal), NULL); } + if (stored_principal) { cc_string_release(stored_principal); } + + if (ccache && *ccache) { + cc_ccache_release(*ccache); + *ccache = NULL; + } + } + + #endif /* cc_context_create_new_ccache */ + + END_CHECK_ONCE; + + return err; +} + +int check_cc_context_new_ccache_iterator(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_string_t name = NULL; + cc_ccache_iterator_t iterator = NULL; + + BEGIN_TEST("cc_context_new_ccache_iterator"); + + #ifndef cc_context_new_ccache_iterator + log_error("cc_context_new_ccache_iterator is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + if (!err) { + err = destroy_all_ccaches(context); + } + if (!err) { + // try making when there are no existing ccaches (shouldn't make a difference, but just in case) + check_once_cc_context_new_ccache_iterator(context, &iterator, ccNoError, "when there are no existing ccaches"); + + err = cc_context_create_default_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + // try making when at least one ccache already exists (just to cover all our bases) + check_once_cc_context_new_ccache_iterator(context, &iterator, ccNoError, "when at least one ccache already exists"); + + // try bad parameters + check_once_cc_context_new_ccache_iterator(context, NULL, ccErrBadParam, "NULL param"); // NULL iterator + } + // we'll do a comprehensive test of cc_ccache_iterator related functions later in the test suite + + if (name) { cc_string_release(name); } + if (ccache) { cc_ccache_destroy(ccache); } + if (context) { cc_context_release(context); } + + #endif /* cc_context_new_ccache_iterator */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_new_ccache_iterator(cc_context_t context, cc_ccache_iterator_t *iterator, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrBadParam, + ccErrNoMem, + ccErrInvalidContext, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_create_new_ccache + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_context_new_ccache_iterator(context, iterator); + + // check returned error + check_err(err, expected_err, possible_return_values); + + // we'll do a comprehensive test of cc_ccache_iterator related functions later + + #endif /* cc_context_create_new_ccache */ + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_context_compare(void) { + cc_int32 err = 0; + cc_context_t context_a = NULL; + cc_context_t context_b = NULL; + cc_uint32 equal = 0; + + BEGIN_TEST("cc_context_compare"); + + #ifndef cc_context_compare + log_error("cc_context_compare is not implemented yet"); + failure_count++; + #else + + err = cc_initialize(&context_a, ccapi_version_3, NULL, NULL); + if (!err) { + err = cc_initialize(&context_b, ccapi_version_3, NULL, NULL); + } + + check_once_cc_context_compare(context_a, context_a, &equal, ccNoError, "valid params, same contexts"); + check_once_cc_context_compare(context_a, context_b, &equal, ccNoError, "valid params, different contexts"); + check_once_cc_context_compare(context_a, NULL, &equal, ccErrBadParam, "NULL compare_to context"); + check_once_cc_context_compare(context_a, context_b, NULL, ccErrBadParam, "NULL out param"); + + if (context_a) { cc_context_release(context_a); } + if (context_b) { cc_context_release(context_b); } + + #endif /* cc_context_compare */ + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_context_compare(cc_context_t context, cc_context_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + + cc_int32 possible_return_values[4] = { + ccNoError, + ccErrInvalidContext, + ccErrBadParam, + ccErrServerUnavailable, + }; + + BEGIN_CHECK_ONCE(description); + + #ifdef cc_context_compare + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_context_compare(context, compare_to, equal); + + if (!err) { + *equal = 0; + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + #endif /* cc_context_compare */ + + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_context.h b/krb5-1.21.3/src/ccapi/test/test_ccapi_context.h new file mode 100644 index 00000000..2c3a4ab8 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_context.h @@ -0,0 +1,32 @@ +#ifndef _TEST_CCAPI_CONTEXT_H_ +#define _TEST_CCAPI_CONTEXT_H_ + +#include "test_ccapi_globals.h" + +int check_cc_initialize(void); +cc_int32 check_once_cc_initialize(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description); +int check_cc_context_get_version(void); +cc_int32 check_once_cc_context_get_version(cc_context_t *out_context, cc_int32 in_version, cc_int32 *out_supported_version, char const **out_vendor, cc_int32 expected_err, const char *description); +int check_cc_context_release(void); +cc_int32 check_once_cc_context_release(cc_context_t *out_context, cc_int32 expected_err, const char *description); +int check_cc_context_get_change_time(void); +cc_int32 check_once_cc_context_get_change_time(cc_context_t context, cc_time_t *time, cc_int32 expected_err, const char *description); +int check_cc_context_get_default_ccache_name(void); +cc_int32 check_once_cc_context_get_default_ccache_name(cc_context_t context, cc_string_t *name, cc_int32 expected_err, const char *description); +int check_cc_context_open_ccache(void); +cc_int32 check_once_cc_context_open_ccache(cc_context_t context, const char *name, cc_ccache_t *ccache, cc_int32 expected_err, const char *description); +int check_cc_context_open_default_ccache(void); +cc_int32 check_once_cc_context_open_default_ccache(cc_context_t context, cc_ccache_t *ccache, cc_int32 expected_err, const char *description); +int check_cc_context_create_ccache(void); +cc_int32 check_once_cc_context_create_ccache(cc_context_t context, const char *name, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description); +int check_cc_context_create_default_ccache(void); +cc_int32 check_once_cc_context_create_default_ccache(cc_context_t context, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description); +int check_cc_context_create_new_ccache(void); +cc_int32 check_once_cc_context_create_new_ccache(cc_context_t context, cc_int32 should_be_default, cc_uint32 cred_vers, const char *principal, cc_ccache_t *ccache, cc_int32 expected_err, const char *description); +int check_cc_context_new_ccache_iterator(void); +cc_int32 check_once_cc_context_new_ccache_iterator(cc_context_t context, cc_ccache_iterator_t *iterator, cc_int32 expected_err, const char *description); + +int check_cc_context_compare(void); +cc_int32 check_once_cc_context_compare(cc_context_t context, cc_context_t compare_to, cc_uint32 *equal, cc_int32 expected_err, const char *description); + +#endif /* _TEST_CCAPI_CONTEXT_H_ */ diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_globals.c b/krb5-1.21.3/src/ccapi/test/test_ccapi_globals.c new file mode 100644 index 00000000..a4ea6315 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_globals.c @@ -0,0 +1,87 @@ +#include "test_ccapi_globals.h" + +/* GLOBALS */ +unsigned int total_failure_count = 0; +unsigned int failure_count = 0; + +const char *current_test_name; +const char *current_test_activity; + +const char * ccapi_error_strings[30] = { + + "ccNoError", /* 0 */ + "ccIteratorEnd", /* 201 */ + "ccErrBadParam", + "ccErrNoMem", + "ccErrInvalidContext", + "ccErrInvalidCCache", + + "ccErrInvalidString", /* 206 */ + "ccErrInvalidCredentials", + "ccErrInvalidCCacheIterator", + "ccErrInvalidCredentialsIterator", + "ccErrInvalidLock", + + "ccErrBadName", /* 211 */ + "ccErrBadCredentialsVersion", + "ccErrBadAPIVersion", + "ccErrContextLocked", + "ccErrContextUnlocked", + + "ccErrCCacheLocked", /* 216 */ + "ccErrCCacheUnlocked", + "ccErrBadLockType", + "ccErrNeverDefault", + "ccErrCredentialsNotFound", + + "ccErrCCacheNotFound", /* 221 */ + "ccErrContextNotFound", + "ccErrServerUnavailable", + "ccErrServerInsecure", + "ccErrServerCantBecomeUID", + + "ccErrTimeOffsetNotSet", /* 226 */ + "ccErrBadInternalMessage", + "ccErrNotImplemented", + +}; + +const char * ccapiv2_error_strings[24] = { + + "CC_NOERROR", + "CC_BADNAME", + "CC_NOTFOUND", + "CC_END", + "CC_IO", + "CC_WRITE", + "CC_NOMEM", + "CC_FORMAT", + "CC_LOCKED", + "CC_BAD_API_VERSION", + "CC_NO_EXIST", + "CC_NOT_SUPP", + "CC_BAD_PARM", + "CC_ERR_CACHE_ATTACH", + "CC_ERR_CACHE_RELEASE", + "CC_ERR_CACHE_FULL", + "CC_ERR_CRED_VERSION" + +}; + +const char *translate_ccapi_error(cc_int32 err) { + + if (err == 0) { + return ccapi_error_strings[0]; + } else + if (err >= 0 && err <= 16){ + return ccapiv2_error_strings[err]; + } else + if (err >= 201 && err <= 228){ + return ccapi_error_strings[err - 200]; + } + else { + return "\"Invalid or private CCAPI error\""; + } + + return ""; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_globals.h b/krb5-1.21.3/src/ccapi/test/test_ccapi_globals.h new file mode 100644 index 00000000..fb2d5dbb --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_globals.h @@ -0,0 +1,57 @@ +#ifndef _TEST_CCAPI_GLOBALS_H_ +#define _TEST_CCAPI_GLOBALS_H_ + +#include // gets us TARGET_OS_MAC + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) +#include +#endif + +#ifdef TARGET_OS_MAC +#include +#else +#include +#endif + +/* GLOBALS */ +extern unsigned int total_failure_count; +extern unsigned int failure_count; + +extern const char *current_test_name; +extern const char *current_test_activity; + +extern const char * ccapi_error_strings[30]; + +const char *translate_ccapi_error(cc_int32 err); + +#define T_CCAPI_INIT \ + do { \ + current_test_name = NULL; \ + current_test_activity = NULL; \ + } while( 0 ) + +#define BEGIN_TEST(name) \ + do { \ + current_test_name = name; \ + failure_count = 0; \ + test_header(current_test_name); \ + } while( 0 ) + +#define BEGIN_CHECK_ONCE(x) \ + do { \ + if (x) { \ + current_test_activity = x; \ + } \ + } while( 0 ) + +#define END_CHECK_ONCE \ + do { \ + current_test_activity = NULL; \ + } while( 0 ) + +#define END_TEST_AND_RETURN \ + test_footer(current_test_name, failure_count); \ + total_failure_count += failure_count; \ + return failure_count; + +#endif /* _TEST_CCAPI_GLOBALS_H_ */ diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_iterators.c b/krb5-1.21.3/src/ccapi/test/test_ccapi_iterators.c new file mode 100644 index 00000000..e51c7cf3 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_iterators.c @@ -0,0 +1,246 @@ +#include "test_ccapi_globals.h" +#include "test_ccapi_iterators.h" +#include "test_ccapi_check.h" +#include "test_ccapi_util.h" + +// --------------------------------------------------------------------------- + +int check_cc_ccache_iterator_next(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_ccache_iterator_t iterator = NULL; + unsigned int i; + + BEGIN_TEST("cc_ccache_iterator_next"); + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // iterate with no ccaches + if (!err) { + err = cc_context_new_ccache_iterator(context, &iterator); + } + check_once_cc_ccache_iterator_next(iterator, 0, ccNoError, "iterating over an empty collection"); + if (iterator) { + cc_ccache_iterator_release(iterator); + iterator = NULL; + } + + // iterate with one ccache + if (!err) { + destroy_all_ccaches(context); + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + if (!err) { + err = cc_context_new_ccache_iterator(context, &iterator); + } + check_once_cc_ccache_iterator_next(iterator, 1, ccNoError, "iterating over a collection of 1 ccache"); + if (iterator) { + cc_ccache_iterator_release(iterator); + iterator = NULL; + } + + // iterate with several ccaches + if (!err) { + destroy_all_ccaches(context); + } + for(i = 0; !err && (i < 1000); i++) + { + if (i%100 == 0) fprintf(stdout, "."); + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + } + if (!err) { + err = cc_context_new_ccache_iterator(context, &iterator); + } + check_once_cc_ccache_iterator_next(iterator, 1000, ccNoError, "iterating over a collection of 1000 ccache"); + if (iterator) { + cc_ccache_iterator_release(iterator); + iterator = NULL; + } + + + if (ccache) { cc_ccache_release(ccache); } + if (iterator) { cc_ccache_iterator_release(iterator); } + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_ccache_iterator_next(cc_ccache_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + +// BEGIN_CHECK_ONCE(description); + + cc_int32 possible_return_values[6] = { + ccNoError, + ccIteratorEnd, + ccErrBadParam, + ccErrNoMem, + ccErrInvalidCCacheIterator, + ccErrCCacheNotFound, + }; + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + cc_ccache_t ccache = NULL; + cc_uint32 actual_count = 0; + + while (!err) { + err = cc_ccache_iterator_next(iterator, &ccache); + if (ccache) { + actual_count++; + cc_ccache_release(ccache); + ccache = NULL; + } + } + if (err == ccIteratorEnd) { + err = ccNoError; + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches"); + +// END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_credentials_iterator_next(void) { + cc_int32 err = 0; + cc_context_t context = NULL; + cc_ccache_t ccache = NULL; + cc_credentials_union creds_union; + cc_credentials_iterator_t iterator = NULL; + unsigned int i; + + BEGIN_TEST("cc_credentials_iterator_next"); + + err = cc_initialize(&context, ccapi_version_3, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches(context); + } + + // iterate with no creds + if (!err) { + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &iterator); + } + check_once_cc_credentials_iterator_next(iterator, 0, ccNoError, "iterating over an empty ccache"); + if (iterator) { + cc_ccache_iterator_release(iterator); + iterator = NULL; + } + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + + // iterate with one cred + if (!err) { + destroy_all_ccaches(context); + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + if (!err) { + new_v5_creds_union(&creds_union, "BAR.ORG"); + err = cc_ccache_store_credentials(ccache, &creds_union); + release_v5_creds_union(&creds_union); + } + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &iterator); + } + check_once_cc_credentials_iterator_next(iterator, 1, ccNoError, "iterating over a ccache with 1 cred"); + if (iterator) { + cc_credentials_iterator_release(iterator); + iterator = NULL; + } + if (ccache) { + cc_ccache_release(ccache); + ccache = NULL; + } + + // iterate with several creds + if (!err) { + destroy_all_ccaches(context); + err = cc_context_create_new_ccache(context, cc_credentials_v5, "foo@BAR.ORG", &ccache); + } + for(i = 0; !err && (i < 1000); i++) { + if (i%100 == 0) fprintf(stdout, "."); + new_v5_creds_union(&creds_union, "BAR.ORG"); + err = cc_ccache_store_credentials(ccache, &creds_union); + release_v5_creds_union(&creds_union); + } + if (!err) { + err = cc_ccache_new_credentials_iterator(ccache, &iterator); + } + check_once_cc_credentials_iterator_next(iterator, 1000, ccNoError, "iterating over a ccache with 1000 creds"); + + if (ccache) { cc_ccache_release(ccache); } + if (iterator) { cc_credentials_iterator_release(iterator); } + if (context) { + destroy_all_ccaches(context); + cc_context_release(context); + } + + END_TEST_AND_RETURN +} + +cc_int32 check_once_cc_credentials_iterator_next(cc_credentials_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description) { + cc_int32 err = ccNoError; + cc_credentials_t creds = NULL; + cc_uint32 actual_count = 0; + + cc_int32 possible_return_values[5] = { + ccNoError, + ccIteratorEnd, + ccErrBadParam, + ccErrNoMem, + ccErrInvalidCredentialsIterator, + }; + + BEGIN_CHECK_ONCE(description); + + #define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + while (!err) { + err = cc_credentials_iterator_next(iterator, &creds); + if (creds) { + actual_count++; + cc_credentials_release(creds); + creds = NULL; + } + } + if (err == ccIteratorEnd) { + err = ccNoError; + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches"); + + END_CHECK_ONCE; + + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_iterators.h b/krb5-1.21.3/src/ccapi/test/test_ccapi_iterators.h new file mode 100644 index 00000000..7308c7c4 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_iterators.h @@ -0,0 +1,12 @@ +#ifndef _TEST_CCAPI_ITERATORS_H_ +#define _TEST_CCAPI_ITERATORS_H_ + +#include "test_ccapi_globals.h" + +int check_cc_ccache_iterator_next(void); +cc_int32 check_once_cc_ccache_iterator_next(cc_ccache_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description); + +int check_cc_credentials_iterator_next(void); +cc_int32 check_once_cc_credentials_iterator_next(cc_credentials_iterator_t iterator, cc_uint32 expected_count, cc_int32 expected_err, const char *description); + +#endif /* _TEST_CCAPI_ITERATORS_H_ */ diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_log.c b/krb5-1.21.3/src/ccapi/test/test_ccapi_log.c new file mode 100644 index 00000000..8ecb6931 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_log.c @@ -0,0 +1,45 @@ +#ifndef _TEST_CCAPI_LOG_C_ +#define _TEST_CCAPI_LOG_C_ + +#include "test_ccapi_log.h" + +void _log_error_v(const char *file, int line, const char *format, va_list ap) +{ + fprintf(stdout, "\n\t%s:%d: ", file, line); + if (!format) { + fprintf(stdout, "An unknown error occurred"); + } else { + vfprintf(stdout, format, ap); + } + fflush(stdout); +} + +void _log_error(const char *file, int line, const char *format, ...) +{ + va_list ap; + va_start(ap, format); + _log_error_v(file, line, format, ap); + va_end(ap); +} + +void test_header(const char *msg) { + if (msg != NULL) { + fprintf(stdout, "\nChecking %s... ", msg); + fflush(stdout); + } +} + +void test_footer(const char *msg, int err) { + if (msg != NULL) { + if (!err) { + fprintf(stdout, "OK\n"); + } + else { + fprintf(stdout, "\n*** %d failure%s in %s ***\n", err, (err == 1) ? "" : "s", msg); + } + } +} + + + +#endif /* _TEST_CCAPI_LOG_C_ */ diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_log.h b/krb5-1.21.3/src/ccapi/test/test_ccapi_log.h new file mode 100644 index 00000000..6305c184 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_log.h @@ -0,0 +1,20 @@ +#ifndef _TEST_CCAPI_LOG_H_ +#define _TEST_CCAPI_LOG_H_ + +#include +#include +#include "test_ccapi_globals.h" + +#define log_error(format, ...) \ + _log_error(__FILE__, __LINE__, format , ## __VA_ARGS__) + +void _log_error_v(const char *file, int line, const char *format, va_list ap); +void _log_error(const char *file, int line, const char *format, ...) +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +__attribute__ ((__format__ (__printf__, 3, 4))) +#endif +; +void test_header(const char *msg); +void test_footer(const char *msg, int err); + +#endif /* _TEST_CCAPI_LOG_H_ */ diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_util.c b/krb5-1.21.3/src/ccapi/test/test_ccapi_util.c new file mode 100644 index 00000000..9af1a6b6 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_util.c @@ -0,0 +1,142 @@ +#include +#include +#include +#include +#include +#include + +#include "k5-platform.h" /* pull in asprintf decl/defn */ +#include "test_ccapi_util.h" + + +// --------------------------------------------------------------------------- + +cc_int32 destroy_all_ccaches(cc_context_t context) { + cc_int32 err = ccNoError; + cc_ccache_t ccache = NULL; + + while (!err) { + err = cc_context_open_default_ccache(context, &ccache); + if (!err) { + err = cc_ccache_destroy(ccache); + } + } + if (err == ccErrCCacheNotFound) { + err = ccNoError; + } + else { + log_error("cc_context_open_default_ccache or cc_ccache_destroy failed with %s (%d)", translate_ccapi_error(err), err); + } + + return err; +} + + +// --------------------------------------------------------------------------- + +cc_int32 new_v5_creds_union (cc_credentials_union *out_union, const char *realm) +{ + cc_int32 err = ccNoError; + cc_credentials_union *cred_union = NULL; + cc_credentials_v5_t *v5creds = NULL; + static int num_runs = 1; + char *client = NULL; + char *server = NULL; + + if (!out_union) { err = ccErrBadParam; } + + if (!err) { + v5creds = malloc (sizeof (*v5creds)); + if (!v5creds) { + err = ccErrNoMem; + } + } + + if (!err) { + asprintf(&client, "client@%s", realm); + asprintf(&server, "host/%d%s@%s", num_runs++, realm, realm); + if (!client || !server) { + err = ccErrNoMem; + } + } + + if (!err) { + v5creds->client = client; + v5creds->server = server; + v5creds->keyblock.type = 1; + v5creds->keyblock.length = 0; + v5creds->keyblock.data = NULL; + v5creds->authtime = time (NULL); + v5creds->starttime = time (NULL); + v5creds->endtime = time(NULL) + 1000; + v5creds->renew_till = time(NULL) + 10000; + v5creds->is_skey = 0; + v5creds->ticket_flags = TKT_FLG_FORWARDABLE | TKT_FLG_PROXIABLE | TKT_FLG_RENEWABLE | TKT_FLG_INITIAL; + v5creds->addresses = NULL; + v5creds->ticket.type = 0; + v5creds->ticket.length = 0; + v5creds->ticket.data = NULL; + v5creds->second_ticket.type = 0; + v5creds->second_ticket.length = 0; + v5creds->second_ticket.data = NULL; + v5creds->authdata = NULL; + } + + + if (!err) { + cred_union = malloc (sizeof (*cred_union)); + if (cred_union) { + cred_union->version = cc_credentials_v5; + cred_union->credentials.credentials_v5 = v5creds; + } else { + err = ccErrNoMem; + } + } + if (!err) { + *out_union = *cred_union; + cred_union = NULL; + } + + return err; +} + + +// --------------------------------------------------------------------------- + +void release_v5_creds_union(cc_credentials_union *creds_union) { + cc_credentials_v5_t *v5creds = NULL; + + if (creds_union) { + if (creds_union->credentials.credentials_v5) { + v5creds = creds_union->credentials.credentials_v5; + if (v5creds->client) { free(v5creds->client); } + if (v5creds->server) { free(v5creds->server); } + if (v5creds->keyblock.data) { free(v5creds->keyblock.data); } + if (v5creds->ticket.data) { free(v5creds->ticket.data); } + if (v5creds->second_ticket.data) { free(v5creds->second_ticket.data); } + free(v5creds); + } + //free(creds_union); + } +} + + +// --------------------------------------------------------------------------- + +// return zero when both unions are considered equal, non-zero when not + +int compare_v5_creds_unions(const cc_credentials_union *a, const cc_credentials_union *b) { + int retval = -1; + + if (a && + b && + (a->version == cc_credentials_v5) && + (a->version == b->version) && + (strcmp(a->credentials.credentials_v5->client, b->credentials.credentials_v5->client) == 0) && + (strcmp(a->credentials.credentials_v5->server, b->credentials.credentials_v5->server) == 0)) + { + retval = 0; + } + + return retval; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_util.h b/krb5-1.21.3/src/ccapi/test/test_ccapi_util.h new file mode 100644 index 00000000..4e98e257 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_util.h @@ -0,0 +1,13 @@ +#ifndef _TEST_CCAPI_UTIL_H_ +#define _TEST_CCAPI_UTIL_H_ + +#include "test_ccapi_globals.h" +#include "test_ccapi_log.h" + +cc_int32 destroy_all_ccaches(cc_context_t context); + +cc_int32 new_v5_creds_union(cc_credentials_union *out_union, const char *realm); +void release_v5_creds_union(cc_credentials_union *creds_union); +int compare_v5_creds_unions(const cc_credentials_union *a, const cc_credentials_union *b); + +#endif /* _TEST_CCAPI_UTIL_H_ */ diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_v2.c b/krb5-1.21.3/src/ccapi/test/test_ccapi_v2.c new file mode 100644 index 00000000..c71bb45a --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_v2.c @@ -0,0 +1,1750 @@ +#include +#include "k5-platform.h" /* pull in asprintf decl/defn */ +#include "test_ccapi_v2.h" +#include +#include +#include "test_ccapi_check.h" +#include "test_ccapi_util.h" + +// --------------------------------------------------------------------------- + +static cc_result destroy_all_ccaches_v2(apiCB *context) { + cc_result err = CC_NOERROR; + infoNC **info = NULL; + int i = 0; + + err = cc_get_NC_info(context, &info); + + for (i = 0; !err && info[i]; i++) { + ccache_p *ccache = NULL; + + err = cc_open(context, info[i]->name, info[i]->vers, 0, &ccache); + + if (!err) { cc_destroy(context, &ccache); } + } + + if (info) { cc_free_NC_info(context, &info); } + + if (err) { + log_error("cc_get_NC_info or cc_open failed with %s (%d)", translate_ccapi_error(err), err); + } + + return err; +} + +// --------------------------------------------------------------------------- +// return zero when both unions are considered equal, non-zero when not + +static int compare_v5_creds_unions_compat(const cred_union *a, const cred_union *b) { + int retval = -1; + + if (a && b && a->cred_type == b->cred_type) { + if (a->cred_type == CC_CRED_V5) { + if (!strcmp(a->cred.pV5Cred->client, b->cred.pV5Cred->client) && + !strcmp(a->cred.pV5Cred->server, b->cred.pV5Cred->server) && + a->cred.pV5Cred->starttime == b->cred.pV5Cred->starttime) { + retval = 0; + } + } + } + + return retval; +} + +// --------------------------------------------------------------------------- + +static cc_result new_v5_creds_union_compat (cred_union *out_union, const char *realm) +{ + cc_result err = CC_NOERROR; + cred_union *creds_union = NULL; + cc_credentials_v5_compat *v5creds = NULL; + static int num_runs = 1; + char *client = NULL; + char *server = NULL; + + if (!out_union) { err = CC_BAD_PARM; } + + if (!err) { + v5creds = malloc (sizeof (*v5creds)); + if (!v5creds) { + err = CC_NOMEM; + } + } + + if (!err) { + asprintf(&client, "client@%s", realm); + asprintf(&server, "host/%d%s@%s", num_runs++, realm, realm); + if (!client || !server) { + err = CC_NOMEM; + } + } + + if (!err) { + v5creds->client = client; + v5creds->server = server; + v5creds->keyblock.type = 1; + v5creds->keyblock.length = 0; + v5creds->keyblock.data = NULL; + v5creds->authtime = time (NULL); + v5creds->starttime = time (NULL); + v5creds->endtime = time(NULL) + 1000; + v5creds->renew_till = time(NULL) + 10000; + v5creds->is_skey = 0; + v5creds->ticket_flags = TKT_FLG_FORWARDABLE | TKT_FLG_PROXIABLE | TKT_FLG_RENEWABLE | TKT_FLG_INITIAL; + v5creds->addresses = NULL; + v5creds->ticket.type = 0; + v5creds->ticket.length = 0; + v5creds->ticket.data = NULL; + v5creds->second_ticket.type = 0; + v5creds->second_ticket.length = 0; + v5creds->second_ticket.data = NULL; + v5creds->authdata = NULL; + } + + + if (!err) { + creds_union = malloc (sizeof (*creds_union)); + if (creds_union) { + creds_union->cred_type = CC_CRED_V5; + creds_union->cred.pV5Cred = v5creds; + } else { + err = CC_NOMEM; + } + } + if (!err) { + *out_union = *creds_union; + creds_union = NULL; + } + + return err; +} + +// --------------------------------------------------------------------------- + +static void release_v5_creds_union_compat(cred_union *creds_union) { + cc_credentials_v5_compat *v5creds = NULL; + + if (creds_union) { + if (creds_union->cred.pV5Cred) { + v5creds = creds_union->cred.pV5Cred; + if (v5creds->client) { free(v5creds->client); } + if (v5creds->server) { free(v5creds->server); } + if (v5creds->keyblock.data) { free(v5creds->keyblock.data); } + if (v5creds->ticket.data) { free(v5creds->ticket.data); } + if (v5creds->second_ticket.data) { free(v5creds->second_ticket.data); } + free(v5creds); + } + } +} + +// --------------------------------------------------------------------------- + +int check_cc_shutdown(void) { + cc_result err = 0; + apiCB *context = NULL; + + BEGIN_TEST("cc_shutdown"); + + // try with valid context + err = check_once_cc_shutdown(&context, CC_NOERROR, NULL); + + // try with NULL + err = check_once_cc_shutdown(NULL, CC_BAD_PARM, NULL); + + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +cc_result check_once_cc_shutdown(apiCB **out_context, cc_result expected_err, const char *description) { + cc_result err = 0; + apiCB *context = NULL; + + cc_result possible_return_values[2] = { + CC_NOERROR, + CC_BAD_PARM, + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (out_context) { + err = cc_initialize(out_context, ccapi_version_2, NULL, NULL); + if (!err) { + context = *out_context; + } else { + log_error("failure in cc_initialize, unable to perform check"); + return err; + } + } + + if (!err) { + err = cc_shutdown(&context); + // check returned error + check_err(err, expected_err, possible_return_values); + + } + + if (out_context) { + *out_context = NULL; + } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_get_change_time(void) { + cc_result err = 0; + apiCB *context = NULL; + cc_time_t last_change_time = 0; + ccache_p *ccache = NULL; + cred_union creds_union; + + BEGIN_TEST("cc_get_change_time"); + + /* + * Make a context + * make sure the change time changes after: + * a ccache is created + * a ccache is destroyed + * a credential is stored + * a credential is removed + * a ccache principal is changed + * clean up memory + */ + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + if (!err) { + + // try bad parameters first + err = check_once_cc_get_change_time(context, NULL, CC_BAD_PARM, "NULL param, should fail"); + + // get_change_time should always give something > 0 + check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "first-run, should be > 0"); + + // create a ccache + err = cc_create(context, "TEST_CCACHE", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + if (err) { + log_error("failed to create a ccache - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + } + check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after creating a new ccache"); + + if (!err) { + // change principal + err = cc_set_principal(context, ccache, CC_CRED_V5, "foo@BAR.ORG"); + if (err) { + log_error("failed to change ccache's principal - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + err = CC_NOERROR; + } + } + check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after changing a principle"); + + new_v5_creds_union_compat(&creds_union, "BAR.ORG"); + + // store a credential + if (!err) { + err = cc_store(context, ccache, creds_union); + if (err) { + log_error("failed to store a credential - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + err = CC_NOERROR; + } + } + check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after storing a credential"); + + // remove a credential + if (!err) { + err = cc_remove_cred(context, ccache, creds_union); + if (err) { + log_error("failed to remove a credential - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + err = CC_NOERROR; + } + } + check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after removing a credential"); + + release_v5_creds_union_compat(&creds_union); + + if (ccache) { + // destroy a ccache + err = cc_destroy(context, &ccache); + check_once_cc_get_change_time(context, &last_change_time, CC_NOERROR, "after destroying a ccache"); + } + } + + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_get_change_time(apiCB *context, cc_time_t *last_time, cc_result expected_err, const char *description) { + cc_result err = 0; + cc_time_t last_change_time; + cc_time_t current_change_time = 0; + + cc_result possible_return_values[3] = { + CC_NOERROR, + CC_BAD_PARM, + CC_NO_EXIST, + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (last_time != NULL) { // if we were passed NULL, then we're looking to pass a bad param + err = cc_get_change_time(context, ¤t_change_time); + } else { + err = cc_get_change_time(context, NULL); + } + + check_err(err, expected_err, possible_return_values); + + if (!err) { + last_change_time = *last_time; + check_if(current_change_time <= last_change_time, "context change time did not increase when it was supposed to (%d <= %d)", current_change_time, last_change_time); + *last_time = current_change_time; + } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_open(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name = "TEST_OPEN_CCACHE"; + + BEGIN_TEST("cc_open"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + if (!err) { + // create a ccache + err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + if (err) { + log_error("failed to create a ccache - %s (%d)", translate_ccapi_error(err), err); + failure_count++; + } + if (!err) { + err = cc_close(context, &ccache); + ccache = NULL; + } + + // try default ccache + if (!err) { + err = check_once_cc_open(context, name, CC_CRED_V5, &ccache, CC_NOERROR, NULL); + } + + // try bad parameters + err = check_once_cc_open(context, NULL, CC_CRED_V5, &ccache, CC_BAD_PARM, NULL); + err = check_once_cc_open(context, name, CC_CRED_V5, NULL, CC_BAD_PARM, NULL); + err = check_once_cc_open(context, name, CC_CRED_UNKNOWN, &ccache, CC_ERR_CRED_VERSION, NULL); + } + + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_open(apiCB *context, const char *name, cc_int32 version, ccache_p **ccache, cc_result expected_err, const char *description) { + cc_result err = 0; + char *stored_name = NULL; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_BAD_PARM, + CC_NO_EXIST, + CC_NOMEM, + CC_ERR_CRED_VERSION + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (ccache != NULL) { // if we were passed NULL, then we're looking to pass a bad param + err = cc_open(context, name, version, 0, ccache); + } else { + err = cc_open(context, name, version, 0, NULL); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(*ccache == NULL, NULL); + + if (!err) { + err = cc_get_name(context, *ccache, &stored_name); + } + if (!err) { + check_if(strcmp(stored_name, name), NULL); + } + if (stored_name) { cc_free_name(context, &stored_name); } + + + if (ccache && *ccache) { + cc_ccache_release(*ccache); + *ccache = NULL; + } + } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_create(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name = "TEST_CC_CREATE"; + + BEGIN_TEST("cc_create"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + if (!err) { + if (!err) { + err = cc_open(context, name, CC_CRED_V5, 0, &ccache); + if (!err) { + err = cc_destroy (context, &ccache); + } else { + err = CC_NOERROR; /* ccache does not exist */ + } + } + // try making a ccache with a unique name (the now destroyed cache's name) + if (!err) { + err = check_once_cc_create(context, name, CC_CRED_V5, "foo@BAR.ORG", &ccache, CC_NOERROR, NULL); + } + + // try making a ccache with a non-unique name (the existing cache's name) + if (!err) { + err = check_once_cc_create(context, name, CC_CRED_V5, "foo/baz@BAR.ORG", &ccache, CC_NOERROR, NULL); + } + + // try bad parameters + err = check_once_cc_create(context, NULL, CC_CRED_V5, "foo@BAR.ORG", &ccache, CC_BAD_PARM, "NULL name"); // NULL name + err = check_once_cc_create(context, "name", CC_CRED_MAX, "foo@BAR.ORG", &ccache, CC_ERR_CRED_VERSION, "invalid creds_vers"); // invalid creds_vers + err = check_once_cc_create(context, "name", CC_CRED_V5, NULL, &ccache, CC_BAD_PARM, "NULL principal"); // NULL principal + err = check_once_cc_create(context, "name", CC_CRED_V5, "foo@BAR.ORG", NULL, CC_BAD_PARM, "NULL ccache"); // NULL ccache + } + + if (ccache) { cc_destroy(context, &ccache); } + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_create(apiCB *context, const char *name, cc_int32 cred_vers, const char *principal, ccache_p **ccache, cc_int32 expected_err, const char *description) { + cc_result err = 0; + char *stored_name = NULL; + char *stored_principal = NULL; + cc_int32 stored_creds_vers = 0; + + cc_result possible_return_values[6] = { + CC_NOERROR, + CC_BADNAME, + CC_BAD_PARM, + CC_NO_EXIST, + CC_NOMEM, + CC_ERR_CRED_VERSION, + }; + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_create(context, name, principal, cred_vers, 0, ccache); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(*ccache == NULL, NULL); + + // make sure all of the ccache's info matches what we gave it + // name + err = cc_get_name(context, *ccache, &stored_name); + if (!err) { check_if(strcmp(stored_name, name), NULL); } + if (stored_name) { cc_free_name(context, &stored_name); } + // cred_vers + err = cc_get_cred_version(context, *ccache, &stored_creds_vers); + if (!err) { check_if(stored_creds_vers != cred_vers, NULL); } + // principal + err = cc_get_principal(context, *ccache, &stored_principal); + if (!err) { check_if(strcmp(stored_principal, principal), NULL); } + if (stored_principal) { cc_free_principal(context, &stored_principal); } + + if (ccache && *ccache) { + cc_destroy(context, ccache); + *ccache = NULL; + } + } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_close(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name = "TEST_CC_CLOSE"; + + BEGIN_TEST("cc_close"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + + if (!err) { + check_once_cc_close(context, ccache, CC_NOERROR, NULL); + ccache = NULL; + } + + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_close(apiCB *context, ccache_p *ccache, cc_result expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[2] = { + CC_NOERROR, + CC_BAD_PARM + }; + + char *name = NULL; + + err = cc_get_name(context, ccache, &name); + err = cc_close(context, &ccache); + ccache = NULL; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err && name) { // try opening released ccache to make sure it still exists + err = cc_open(context, name, CC_CRED_V5, 0, &ccache); + } + check_if(err == CC_NO_EXIST, "released ccache was actually destroyed instead"); + check_if(err != CC_NOERROR, "released ccache cannot be opened"); + + if (ccache) { cc_destroy(context, &ccache); } + if (name) { cc_free_name(context, &name); } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_destroy(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name = "TEST_CC_DESTROY"; + + BEGIN_TEST("cc_destroy"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + + if (!err) { + check_once_cc_destroy(context, ccache, CC_NOERROR, NULL); + ccache = NULL; + } + + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_destroy(apiCB *context, ccache_p *ccache, cc_int32 expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[2] = { + CC_NOERROR, + CC_BAD_PARM, + }; + + char *name = NULL; + + BEGIN_CHECK_ONCE(description); + +#ifdef cc_ccache_destroy + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_get_name(context, ccache, &name); + err = cc_destroy(context, &ccache); + ccache = NULL; + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err && name) { // try opening released ccache to make sure it still exists + err = cc_open(context, name, CC_CRED_V5, 0, &ccache); + } + check_if(err != CC_NO_EXIST, "destroyed ccache was actually released instead"); + + if (ccache) { cc_destroy(context, &ccache); } + if (name) { cc_free_name(context, &name); } + +#endif /* cc_ccache_destroy */ + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_get_cred_version(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name = "TEST_CC_GET_CRED_VERSION_V5"; + + BEGIN_TEST("cc_get_cred_version"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + // try one created with v5 creds + if (!err) { + err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + check_once_cc_get_cred_version(context, ccache, CC_CRED_V5, CC_NOERROR, "v5 creds"); + } + else { + log_error("cc_context_create_new_ccache failed, can't complete test"); + failure_count++; + } + + if (ccache) { + cc_destroy(context, &ccache); + ccache = NULL; + } + + err = CC_NOERROR; + + if (ccache) { + cc_destroy(context, &ccache); + ccache = NULL; + } + + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_get_cred_version(apiCB *context, ccache_p *ccache, cc_int32 expected_cred_vers, cc_int32 expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[3] = { + CC_NOERROR, + CC_BAD_PARM, + CC_NO_EXIST, + }; + + cc_int32 stored_cred_vers = 0; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_get_cred_version(context, ccache, &stored_cred_vers); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(stored_cred_vers != expected_cred_vers, NULL); + } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_get_name(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + + BEGIN_TEST("cc_get_name"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + // try with unique ccache (which happens to be default) + if (!err) { + err = cc_create(context, "0", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + check_once_cc_get_name(context, ccache, "0", CC_NOERROR, "unique ccache (which happens to be default)"); + } + else { + log_error("cc_context_create_ccache failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + + // try with unique ccache (which is not default) + if (!err) { + err = cc_context_create_ccache(context, "1", CC_CRED_V5, "foo@BAR.ORG", &ccache); + } + if (!err) { + check_once_cc_get_name(context, ccache, "1", CC_NOERROR, "unique ccache (which is not default)"); + } + else { + log_error("cc_context_create_ccache failed, can't complete test"); + failure_count++; + } + + // try with bad param + if (!err) { + check_once_cc_get_name(context, ccache, NULL, CC_BAD_PARM, "NULL param"); + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + + if (context) { + err = destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_get_name(apiCB *context, ccache_p *ccache, const char *expected_name, cc_int32 expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[4] = { + CC_NOERROR, + CC_NOMEM, + CC_BAD_PARM, + CC_NO_EXIST, + }; + + char *stored_name = NULL; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (expected_name == NULL) { // we want to try with a NULL param + err = cc_get_name(context, ccache, NULL); + } + else { + err = cc_get_name(context, ccache, &stored_name); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(strcmp(stored_name, expected_name), NULL); + } + + if (stored_name) { cc_free_name(context, &stored_name); } + + END_CHECK_ONCE; + + return err; +} + + +// --------------------------------------------------------------------------- + +int check_cc_get_principal(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name_v5 = "TEST_CC_GET_PRINCIPAL_V5"; + + BEGIN_TEST("cc_get_principal"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + // try with krb5 principal + if (!err) { + err = cc_create(context, name_v5, "foo/BAR@BAZ.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + check_once_cc_get_principal(context, ccache, "foo/BAR@BAZ.ORG", CC_NOERROR, "trying to get krb5 princ for krb5 ccache"); + } + else { + log_error("cc_create failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + + // try with bad param + if (!err) { + check_once_cc_get_principal(context, ccache, NULL, CC_BAD_PARM, "passed null out param"); + } + + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + + if (context) { + err = destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_get_principal(apiCB *context, + ccache_p *ccache, + const char *expected_principal, + cc_int32 expected_err, + const char *description) { + cc_result err = CC_NOERROR; + char *stored_principal = NULL; + + cc_result possible_return_values[4] = { + CC_NOERROR, + CC_NOMEM, + CC_NO_EXIST, + CC_BAD_PARM + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + if (expected_principal == NULL) { // we want to try with a NULL param + err = cc_get_principal(context, ccache, NULL); + } + else { + err = cc_get_principal(context, ccache, &stored_principal); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + check_if(strcmp(stored_principal, expected_principal), "expected princ == \"%s\" stored princ == \"%s\"", expected_principal, stored_principal); + } + + if (stored_principal) { cc_free_principal(context, &stored_principal); } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_set_principal(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + char *name_v5 = "TEST_CC_GET_PRINCIPAL_V5"; + + BEGIN_TEST("cc_set_principal"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + // bad params + if (!err) { + err = cc_create(context, name_v5, "foo@BAZ.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + check_once_cc_set_principal(context, ccache, CC_CRED_MAX, "foo/BAZ@BAR.ORG", CC_ERR_CRED_VERSION, "CC_CRED_MAX (not allowed)"); + check_once_cc_set_principal(context, ccache, CC_CRED_V5, NULL, CC_BAD_PARM, "NULL principal"); + } + else { + log_error("cc_create failed, can't complete test"); + failure_count++; + } + if (ccache) { + cc_destroy(context, &ccache); + ccache = NULL; + } + + if (ccache) { + cc_destroy(context, &ccache); + ccache = NULL; + } + + if (context) { + err = destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_int32 check_once_cc_set_principal(apiCB *context, ccache_p *ccache, cc_int32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description) { + cc_result err = CC_NOERROR; + char *stored_principal = NULL; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_NOMEM, + CC_NO_EXIST, + CC_ERR_CRED_VERSION, + CC_BAD_PARM + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_set_principal(context, ccache, cred_vers, (char *) in_principal); + + // check returned error + check_err(err, expected_err, possible_return_values); + + if (!err) { + err = cc_get_principal(context, ccache, &stored_principal); + } + + // compare stored with input + if (!err) { + check_if(strcmp(stored_principal, in_principal), "expected princ == \"%s\" stored princ == \"%s\"", in_principal, stored_principal); + } + + if (stored_principal) { cc_free_principal(context, &stored_principal); } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_store(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + ccache_p *dup_ccache = NULL; + cred_union creds_union; + char *name = NULL; + + BEGIN_TEST("cc_store"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + if (!err) { + err = cc_create(context, "TEST_CC_STORE", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + + // cred with matching version and realm + if (!err) { + err = new_v5_creds_union_compat(&creds_union, "BAR.ORG"); + + if (!err) { + check_once_cc_store(context, ccache, creds_union, CC_NOERROR, "ok creds"); + release_v5_creds_union_compat(&creds_union); + } + } + + // invalid creds + if (!err) { + err = new_v5_creds_union_compat(&creds_union, "BAR.ORG"); + + if (!err) { + if (creds_union.cred.pV5Cred->client) { + free(creds_union.cred.pV5Cred->client); + creds_union.cred.pV5Cred->client = NULL; + } + check_once_cc_store(context, ccache, creds_union, CC_BAD_PARM, "invalid creds (NULL client string)"); + + release_v5_creds_union_compat(&creds_union); + } + } + + // non-existent ccache + if (ccache) { + err = cc_get_name(context, ccache, &name); + if (!err) { + err = cc_open(context, name, CC_CRED_V5, 0, &dup_ccache); + } + if (name) { cc_free_name(context, &name); } + if (dup_ccache) { cc_destroy(context, &dup_ccache); } + } + + if (!err) { + err = new_v5_creds_union_compat(&creds_union, "BAR.ORG"); + + if (!err) { + check_once_cc_store(context, ccache, creds_union, CC_NO_EXIST, "invalid ccache"); + + release_v5_creds_union_compat(&creds_union); + } + } + + if (ccache) { cc_close(context, &ccache); } + if (context) { + destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_store(apiCB *context, ccache_p *ccache, const cred_union in_creds, cc_int32 expected_err, const char *description) { + cc_result err = CC_NOERROR; + ccache_cit *iterator = NULL; + int found = 0; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_BAD_PARM, + CC_ERR_CACHE_FULL, + CC_ERR_CRED_VERSION, + CC_NO_EXIST + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_store(context, ccache, in_creds); + + // check returned error + check_err(err, expected_err, possible_return_values); + + // make sure credentials were truly stored + if (!err) { + err = cc_seq_fetch_creds_begin(context, ccache, &iterator); + } + while (!err && !found) { + cred_union *creds = NULL; + + err = cc_seq_fetch_creds_next(context, &creds, iterator); + if (!err) { + found = !compare_v5_creds_unions_compat(&in_creds, creds); + } + + if (creds) { cc_free_creds(context, &creds); } + } + + if (err == CC_END) { + check_if(found, "stored credentials not found in ccache"); + err = CC_NOERROR; + } + + if (iterator) { cc_seq_fetch_creds_end(context, &iterator); } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_remove_cred(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + cred_union *creds_array[10]; + ccache_cit *iterator = NULL; + char *name = NULL; + unsigned int i; + + BEGIN_TEST("cc_remove_cred"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + if (!err) { + err = cc_create(context, "TEST_CC_REMOVE_CRED", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + + // store 10 creds and retrieve their cc_credentials_t representations + for(i = 0; !err && (i < 10); i++) { + cred_union creds; + + new_v5_creds_union_compat(&creds, "BAR.ORG"); + err = cc_store(context, ccache, creds); + if (err) { + log_error("failure to store creds_union in remove_creds test"); + } + release_v5_creds_union_compat(&creds); + } + + if (!err) { + err = cc_seq_fetch_creds_begin(context, ccache, &iterator); + } + + for (i = 0; !err && i < 10; i++) { + creds_array[i] = NULL; + err = cc_seq_fetch_creds_next(context, &creds_array[i], iterator); + } + if (err == CC_END) { err = CC_NOERROR; } + + // remove 10 valid creds + for (i = 0; !err && (i < 10); i++) { + check_once_cc_remove_cred(context, ccache, *creds_array[i], CC_NOERROR, "10 ok creds"); + } + + // non-existent creds (remove same one twice) + check_once_cc_remove_cred(context, ccache, *creds_array[0], CC_NOTFOUND, "removed same creds twice"); + + // non-existent ccache + if (ccache) { + ccache_p *dup_ccache = NULL; + + err = cc_get_name(context, ccache, &name); + + if (!err) { + err = cc_open(context, name, CC_CRED_V5, 0, &dup_ccache); + } + + if (!err) { + err = cc_destroy(context, &dup_ccache); + check_once_cc_remove_cred(context, ccache, *creds_array[0], CC_NO_EXIST, "invalid ccache"); + } + + if (name) { cc_free_name(context, &name); } + } + + for(i = 0; i < 10 && creds_array[i]; i++) { + cc_free_creds(context, &creds_array[i]); + } + + + if (iterator) { cc_seq_fetch_creds_end(context, &iterator); iterator = NULL; } + if (ccache) { cc_close(context, &ccache); } + if (context) { + destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_remove_cred(apiCB *context, ccache_p *ccache, cred_union in_creds, cc_int32 expected_err, const char *description) { + cc_result err = CC_NOERROR; + ccache_cit *iterator = NULL; + int found = 0; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_BAD_PARM, + CC_ERR_CRED_VERSION, + CC_NOTFOUND, + CC_NO_EXIST + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_remove_cred(context, ccache, in_creds); + + // check returned error + check_err(err, expected_err, possible_return_values); + + // make sure credentials were truly stored + if (!err) { + err = cc_seq_fetch_creds_begin(context, ccache, &iterator); + } + + while (!err && !found) { + cred_union *creds = NULL; + + err = cc_seq_fetch_creds_next(context, &creds, iterator); + if (!err) { + found = !compare_v5_creds_unions_compat(&in_creds, creds); + } + + if (creds) { cc_free_creds(context, &creds); } + } + + if (err == CC_END) { + check_if(found, "credentials not removed from ccache"); + err = CC_NOERROR; + } + + if (iterator) { cc_seq_fetch_creds_end(context, &iterator); } + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_seq_fetch_NCs_begin(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + ccache_cit *iterator = NULL; + + BEGIN_TEST("cc_seq_fetch_NCs_begin"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + if (!err) { + err = destroy_all_ccaches_v2(context); + } + if (!err) { + // try making when there are no existing ccaches (shouldn't make a difference, but just in case) + check_once_cc_seq_fetch_NCs_begin(context, &iterator, CC_NOERROR, "when there are no existing ccaches"); + + err = cc_create(context, "TEST_CC_SEQ_FETCH_NCS_BEGIN", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + // try making when at least one ccache already exists (just to cover all our bases) + check_once_cc_seq_fetch_NCs_begin(context, &iterator, CC_NOERROR, "when at least one ccache already exists"); + + // try bad parameters + check_once_cc_seq_fetch_NCs_begin(context, NULL, CC_BAD_PARM, "NULL param"); // NULL iterator + } + // we'll do a comprehensive test of cc_ccache_iterator related functions later in the test suite + + if (ccache ) { cc_close(context, &ccache); } + if (context) { cc_shutdown(&context); } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_seq_fetch_NCs_begin(apiCB *context, ccache_cit **iterator, cc_result expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[4] = { + CC_NOERROR, + CC_BAD_PARM, + CC_NOMEM, + CC_NO_EXIST + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_seq_fetch_NCs_begin(context, iterator); + + // check returned error + check_err(err, expected_err, possible_return_values); + + // we'll do a comprehensive test of cc_ccache_iterator related functions later + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_seq_fetch_NCs_next(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + ccache_cit *iterator = NULL; + unsigned int i; + + BEGIN_TEST("cc_seq_fetch_NCs_next"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + // iterate with no ccaches + if (!err) { + err = cc_seq_fetch_NCs_begin(context, &iterator); + } + check_once_cc_seq_fetch_NCs_next(context, iterator, 0, CC_NOERROR, "iterating over an empty collection"); + if (iterator) { + cc_seq_fetch_creds_end(context, &iterator); + iterator = NULL; + } + + // iterate with one ccache + if (!err) { + destroy_all_ccaches_v2(context); + err = cc_create(context, "TEST_CC_SEQ_FETCH_NCS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + if (!err) { + err = cc_seq_fetch_NCs_begin(context, &iterator); + } + check_once_cc_seq_fetch_NCs_next(context, iterator, 1, CC_NOERROR, "iterating over a collection of 1 ccache"); + if (iterator) { + cc_seq_fetch_creds_end(context, &iterator); + iterator = NULL; + } + + // iterate with several ccaches + if (!err) { + destroy_all_ccaches_v2(context); + } + for(i = 0; !err && (i < 1000); i++) + { + char *name = NULL; + + if (i%100 == 0) fprintf(stdout, "."); + asprintf (&name, "TEST_CC_SEQ_FETCH_NCS_NEXT_%d", i); + err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + free (name); + } + if (!err) { + err = cc_seq_fetch_NCs_begin(context, &iterator); + } + check_once_cc_seq_fetch_NCs_next(context, iterator, 1000, CC_NOERROR, "iterating over a collection of 1000 ccache"); + if (iterator) { + cc_seq_fetch_creds_end(context, &iterator); + iterator = NULL; + } + + + if (ccache) { cc_close(context, &ccache); } + if (iterator) { cc_seq_fetch_creds_end(context, &iterator); } + if (context) { + destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_seq_fetch_NCs_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_END, + CC_BAD_PARM, + CC_NOMEM, + CC_NO_EXIST + }; +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + ccache_p *ccache = NULL; + cc_uint32 actual_count = 0; + + BEGIN_CHECK_ONCE(description); + + while (!err) { + err = cc_seq_fetch_NCs_next(context, &ccache, iterator); + if (ccache) { + actual_count++; + cc_close(context, &ccache); + ccache = NULL; + } + } + if (err == CC_END) { + err = CC_NOERROR; + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches"); + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_get_NC_info(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + unsigned int i; + + BEGIN_TEST("cc_get_NC_info"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + // iterate with no ccaches + check_once_cc_get_NC_info(context, "", "", CC_CRED_MAX, 0, CC_NOERROR, "iterating over an empty collection"); + + // iterate with one ccache + if (!err) { + destroy_all_ccaches_v2(context); + err = cc_create(context, "TEST_CC_GET_NC_INFO", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + check_once_cc_get_NC_info(context, "TEST_CC_GET_NC_INFO", "foo@BAR.ORG", CC_CRED_V5, 1, CC_NOERROR, "iterating over a collection of 1 ccache"); + + // iterate with several ccaches + if (!err) { + destroy_all_ccaches_v2(context); + } + for(i = 0; !err && (i < 1000); i++) + { + char *name = NULL; + + if (i%100 == 0) fprintf(stdout, "."); + asprintf (&name, "TEST_CC_GET_NC_INFO_%d", i); + err = cc_create(context, name, "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + free (name); + } + check_once_cc_get_NC_info(context, "TEST_CC_GET_NC_INFO", "foo@BAR.ORG", CC_CRED_V5, 1000, CC_NOERROR, "iterating over a collection of 1000 ccache"); + + if (ccache) { cc_close(context, &ccache); } + if (context) { + destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_get_NC_info(apiCB *context, + const char *expected_name_prefix, + const char *expected_principal, + cc_int32 expected_version, + cc_uint32 expected_count, + cc_result expected_err, + const char *description) { + cc_result err = CC_NOERROR; + infoNC **info = NULL; + + cc_result possible_return_values[4] = { + CC_NOERROR, + CC_BAD_PARM, + CC_NOMEM, + CC_NO_EXIST + }; +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + cc_uint32 actual_count = 0; + + BEGIN_CHECK_ONCE(description); + + err = cc_get_NC_info(context, &info); + + for (actual_count = 0; !err && info[actual_count]; actual_count++) { + check_if(strncmp(info[actual_count]->name, expected_name_prefix, strlen(expected_name_prefix)), "got incorrect ccache name"); + check_if(strcmp(info[actual_count]->principal, expected_principal), "got incorrect principal name"); + check_if(info[actual_count]->vers != expected_version, "got incorrect cred version"); + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + check_if(actual_count != expected_count, "NC info didn't list all ccaches"); + + if (info) { cc_free_NC_info (context, &info); } + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_seq_fetch_creds_begin(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + ccache_p *dup_ccache = NULL; + ccache_cit *creds_iterator = NULL; + char *name = NULL; + + BEGIN_TEST("cc_seq_fetch_creds_begin"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + if (!err) { + err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_BEGIN", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + + // valid params + if (!err) { + check_once_cc_seq_fetch_creds_begin(context, ccache, &creds_iterator, CC_NOERROR, "valid params"); + } + if (creds_iterator) { + cc_seq_fetch_creds_end(context, &creds_iterator); + creds_iterator = NULL; + } + + // NULL out param + if (!err) { + check_once_cc_seq_fetch_creds_begin(context, ccache, NULL, CC_BAD_PARM, "NULL out iterator param"); + } + if (creds_iterator) { + cc_seq_fetch_creds_end(context, &creds_iterator); + creds_iterator = NULL; + } + + // non-existent ccache + if (ccache) { + err = cc_get_name(context, ccache, &name); + if (!err) { + err = cc_open(context, name, CC_CRED_V5, 0, &dup_ccache); + } + if (name) { cc_free_name(context, &name); } + if (dup_ccache) { cc_destroy(context, &dup_ccache); } + } + + if (!err) { + check_once_cc_seq_fetch_creds_begin(context, ccache, &creds_iterator, CC_NO_EXIST, "invalid ccache"); + } + + if (creds_iterator) { + cc_seq_fetch_creds_end(context, &creds_iterator); + creds_iterator = NULL; + } + if (ccache) { cc_close(context, &ccache); } + if (context) { + destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_seq_fetch_creds_begin(apiCB *context, ccache_p *ccache, ccache_cit **iterator, cc_result expected_err, const char *description) { + cc_result err = CC_NOERROR; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_BAD_PARM, + CC_NOMEM, + CC_NO_EXIST + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + err = cc_seq_fetch_creds_begin(context, ccache, iterator); + + // check returned error + check_err(err, expected_err, possible_return_values); + + END_CHECK_ONCE; + + return err; +} + +// --------------------------------------------------------------------------- + +int check_cc_seq_fetch_creds_next(void) { + cc_result err = 0; + apiCB *context = NULL; + ccache_p *ccache = NULL; + cred_union creds_union; + ccache_cit *iterator = NULL; + unsigned int i; + + BEGIN_TEST("cc_seq_fetch_creds_next"); + + err = cc_initialize(&context, ccapi_version_2, NULL, NULL); + + if (!err) { + err = destroy_all_ccaches_v2(context); + } + + // iterate with no creds + if (!err) { + err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + err = cc_seq_fetch_creds_begin(context, ccache, &iterator); + } + check_once_cc_seq_fetch_creds_next(context, iterator, 0, CC_NOERROR, "iterating over an empty ccache"); + if (iterator) { + cc_seq_fetch_creds_end(context, &iterator); + iterator = NULL; + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + + // iterate with one cred + if (!err) { + destroy_all_ccaches_v2(context); + err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + if (!err) { + new_v5_creds_union_compat(&creds_union, "BAR.ORG"); + err = cc_store(context, ccache, creds_union); + release_v5_creds_union_compat(&creds_union); + } + if (!err) { + err = cc_seq_fetch_creds_begin(context, ccache, &iterator); + } + check_once_cc_seq_fetch_creds_next(context, iterator, 1, CC_NOERROR, "iterating over a ccache with 1 cred"); + if (iterator) { + cc_seq_fetch_creds_end(context, &iterator); + iterator = NULL; + } + if (ccache) { + cc_close(context, &ccache); + ccache = NULL; + } + + // iterate with several creds + if (!err) { + destroy_all_ccaches_v2(context); + err = cc_create(context, "TEST_CC_SEQ_FETCH_CREDS_NEXT", "foo@BAR.ORG", CC_CRED_V5, 0, &ccache); + } + for(i = 0; !err && (i < 1000); i++) { + if (i%100 == 0) fprintf(stdout, "."); + new_v5_creds_union_compat(&creds_union, "BAR.ORG"); + err = cc_store(context, ccache, creds_union); + release_v5_creds_union_compat(&creds_union); + } + if (!err) { + err = cc_seq_fetch_creds_begin(context, ccache, &iterator); + } + check_once_cc_seq_fetch_creds_next(context, iterator, 1000, CC_NOERROR, "iterating over a ccache with 1000 creds"); + + if (ccache) { cc_close(context, &ccache); } + if (iterator) { cc_seq_fetch_creds_end(context, &iterator); } + if (context) { + destroy_all_ccaches_v2(context); + cc_shutdown(&context); + } + + END_TEST_AND_RETURN +} + +// --------------------------------------------------------------------------- + +cc_result check_once_cc_seq_fetch_creds_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description) { + cc_result err = CC_NOERROR; + cred_union *creds = NULL; + cc_uint32 actual_count = 0; + + cc_result possible_return_values[5] = { + CC_NOERROR, + CC_END, + CC_BAD_PARM, + CC_NOMEM, + CC_NO_EXIST, + }; + + BEGIN_CHECK_ONCE(description); + +#define possible_ret_val_count sizeof(possible_return_values)/sizeof(possible_return_values[0]) + + while (!err) { + err = cc_seq_fetch_creds_next(context, &creds, iterator); + if (creds) { + actual_count++; + cc_free_creds(context, &creds); + creds = NULL; + } + } + if (err == CC_END) { + err = CC_NOERROR; + } + + // check returned error + check_err(err, expected_err, possible_return_values); + + check_if(actual_count != expected_count, "iterator didn't iterate over all ccaches"); + + END_CHECK_ONCE; + + return err; +} diff --git a/krb5-1.21.3/src/ccapi/test/test_ccapi_v2.h b/krb5-1.21.3/src/ccapi/test/test_ccapi_v2.h new file mode 100644 index 00000000..8508daa4 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_ccapi_v2.h @@ -0,0 +1,73 @@ +#ifndef _TEST_CCAPI_V2_H_ +#define _TEST_CCAPI_V2_H_ + +#include "test_ccapi_globals.h" +#ifdef TARGET_OS_MAC +#include +#else +#include +#endif + + +int check_cc_shutdown(void); +cc_result check_once_cc_shutdown(apiCB **out_context, cc_result expected_err, const char *description); + +int check_cc_get_change_time(void); +cc_int32 check_once_cc_get_change_time(apiCB *context, cc_time_t *time, cc_result expected_err, const char *description); + +int check_cc_open(void); +cc_result check_once_cc_open(apiCB *context, const char *name, cc_int32 version, ccache_p **ccache, cc_result expected_err, const char *description); + +int check_cc_create(void); +cc_result check_once_cc_create(apiCB *context, const char *name, cc_int32 cred_vers, const char *principal, ccache_p **ccache, cc_int32 expected_err, const char *description); + +int check_cc_close(void); +cc_result check_once_cc_close(apiCB *context, ccache_p *ccache, cc_result expected_err, const char *description); + +int check_cc_destroy(void); +cc_result check_once_cc_destroy(apiCB *context, ccache_p *ccache, cc_int32 expected_err, const char *description); + +int check_cc_get_cred_version(void); +cc_result check_once_cc_get_cred_version(apiCB *context, ccache_p *ccache, cc_int32 expected_cred_vers, cc_int32 expected_err, const char *description); + +int check_cc_get_name(void); +cc_int32 check_once_cc_get_name(apiCB *context, ccache_p *ccache, const char *expected_name, cc_int32 expected_err, const char *description); + +int check_cc_get_principal(void); +cc_result check_once_cc_get_principal(apiCB *context, + ccache_p *ccache, + const char *expected_principal, + cc_int32 expected_err, + const char *description); + +int check_cc_set_principal(void); +cc_int32 check_once_cc_set_principal(apiCB *context, ccache_p *ccache, cc_int32 cred_vers, const char *in_principal, cc_int32 expected_err, const char *description); + +int check_cc_store(void); +cc_result check_once_cc_store(apiCB *context, ccache_p *ccache, const cred_union in_creds, cc_int32 expected_err, const char *description); + +int check_cc_remove_cred(void); +cc_result check_once_cc_remove_cred(apiCB *context, ccache_p *ccache, cred_union in_creds, cc_int32 expected_err, const char *description); + +int check_cc_seq_fetch_NCs_begin(void); +cc_result check_once_cc_seq_fetch_NCs_begin(apiCB *context, ccache_cit **iterator, cc_result expected_err, const char *description); + +int check_cc_seq_fetch_NCs_next(void); +cc_result check_once_cc_seq_fetch_NCs_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description); + +int check_cc_get_NC_info(void); +cc_result check_once_cc_get_NC_info(apiCB *context, + const char *expected_name, + const char *expected_principal, + cc_int32 expected_version, + cc_uint32 expected_count, + cc_result expected_err, + const char *description); + +int check_cc_seq_fetch_creds_begin(void); +cc_result check_once_cc_seq_fetch_creds_begin(apiCB *context, ccache_p *ccache, ccache_cit **iterator, cc_result expected_err, const char *description); + +int check_cc_seq_fetch_creds_next(void); +cc_result check_once_cc_seq_fetch_creds_next(apiCB *context, ccache_cit *iterator, cc_uint32 expected_count, cc_result expected_err, const char *description); + +#endif /* _TEST_CCAPI_V2_H_ */ diff --git a/krb5-1.21.3/src/ccapi/test/test_constants.c b/krb5-1.21.3/src/ccapi/test/test_constants.c new file mode 100644 index 00000000..f4f272c4 --- /dev/null +++ b/krb5-1.21.3/src/ccapi/test/test_constants.c @@ -0,0 +1,15 @@ +#include +#include + +#include "test_ccapi_check.h" +#include "test_ccapi_constants.h" +#include "test_ccapi_context.h" +#include "test_ccapi_ccache.h" + +int main (int argc, const char * argv[]) { + + cc_int32 err = ccNoError; + T_CCAPI_INIT; + err = check_constants(); + return err; +} diff --git a/krb5-1.21.3/src/clients/Makefile.in b/krb5-1.21.3/src/clients/Makefile.in new file mode 100644 index 00000000..4beb32a6 --- /dev/null +++ b/krb5-1.21.3/src/clients/Makefile.in @@ -0,0 +1,7 @@ +mydir=clients +BUILDTOP=$(REL).. + +SUBDIRS= klist kinit kdestroy kpasswd ksu kvno kcpytkt kdeltkt kswitch +WINSUBDIRS= klist kinit kdestroy kpasswd kvno kcpytkt kdeltkt kswitch + +NO_OUTPRE=1 diff --git a/krb5-1.21.3/src/clients/deps b/krb5-1.21.3/src/clients/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/clients/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/clients/kcpytkt/Makefile.in b/krb5-1.21.3/src/clients/kcpytkt/Makefile.in new file mode 100644 index 00000000..cad4dd41 --- /dev/null +++ b/krb5-1.21.3/src/clients/kcpytkt/Makefile.in @@ -0,0 +1,32 @@ +mydir=kcpytkt +BUILDTOP=$(REL)..$(S).. + +##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc +##WIN32##RCFLAGS=$(CPPFLAGS) -I$(top_srcdir) -D_WIN32 -DRES_ONLY + +##WIN32##KCPYTKT=$(OUTPRE)kcpytkt.exe + +##WIN32##EXERES=$(KCPYTKT:.exe=.res) + +##WIN32##$(EXERES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DKCPYTKT_APP -fo $@ -r $** + +all-unix: kcpytkt +##WIN32##all-windows: $(KCPYTKT) +all-mac: + +kcpytkt: kcpytkt.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ kcpytkt.o $(KRB5_BASE_LIBS) + +##WIN32##$(KCPYTKT): $(OUTPRE)kcpytkt.obj $(SLIB) $(KLIB) $(CLIB) $(EXERES) +##WIN32## link $(EXE_LINKOPTS) /out:$@ $** +##WIN32## $(_VC_MANIFEST_EMBED_EXE) + +clean-unix:: + $(RM) kcpytkt.o kcpytkt + +install-unix: + for f in kcpytkt; do \ + $(INSTALL_PROGRAM) $$f \ + $(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \ + done diff --git a/krb5-1.21.3/src/clients/kcpytkt/kcpytkt.c b/krb5-1.21.3/src/clients/kcpytkt/kcpytkt.c new file mode 100644 index 00000000..0b880226 --- /dev/null +++ b/krb5-1.21.3/src/clients/kcpytkt/kcpytkt.c @@ -0,0 +1,174 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ + +#include +#include +#include +#include +#include "k5-platform.h" + +static char *prog; +static int quiet = 0; + +static void +xusage() +{ + fprintf(stderr, "xusage: %s [-c from_ccache] [-e etype] [-f flags] " + "dest_ccache service1 service2 ...\n", prog); + exit(1); +} + +static void +do_kcpytkt(int argc, char *argv[], char *fromccachestr, char *etypestr, + int flags); + +int +main(int argc, char *argv[]) +{ + int option; + char *etypestr = NULL, *fromccachestr = NULL; + int flags = 0; + + prog = strrchr(argv[0], '/'); + prog = (prog != NULL) ? prog + 1 : argv[0]; + + while ((option = getopt(argc, argv, "c:e:f:hq")) != -1) { + switch (option) { + case 'c': + fromccachestr = optarg; + break; + case 'e': + etypestr = optarg; + break; + case 'f': + flags = atoi(optarg); + break; + case 'q': + quiet = 1; + break; + case 'h': + default: + xusage(); + break; + } + } + + if (argc - optind < 2) + xusage(); + + do_kcpytkt(argc - optind, argv + optind, fromccachestr, etypestr, flags); + return 0; +} + +static void +do_kcpytkt(int count, char *names[], const char *fromccachestr, char *etypestr, + int flags) +{ + krb5_context context; + krb5_error_code ret; + krb5_enctype etype; + krb5_ccache fromccache, destccache; + krb5_principal me; + krb5_creds in_creds, out_creds; + int i, errors, retflags; + char *princ; + + ret = krb5_init_context(&context); + if (ret) { + com_err(prog, ret, "while initializing krb5 library"); + exit(1); + } + if (etypestr != NULL) { + ret = krb5_string_to_enctype(etypestr, &etype); + if (ret) { + com_err(prog, ret, "while converting etype"); + exit(1); + } + retflags = KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES; + } else { + etype = 0; + retflags = KRB5_TC_MATCH_SRV_NAMEONLY; + } + + if (fromccachestr != NULL) + ret = krb5_cc_resolve(context, fromccachestr, &fromccache); + else + ret = krb5_cc_default(context, &fromccache); + if (ret) { + com_err(prog, ret, "while opening source ccache"); + exit(1); + } + + ret = krb5_cc_get_principal(context, fromccache, &me); + if (ret) { + com_err(prog, ret, "while getting client principal name"); + exit(1); + } + + ret = krb5_cc_resolve(context, names[0], &destccache); + if (ret) { + com_err(prog, ret, "while opening destination cache"); + exit(1); + } + + errors = 0; + + for (i = 1; i < count; i++) { + memset(&in_creds, 0, sizeof(in_creds)); + + in_creds.client = me; + + ret = krb5_parse_name(context, names[i], &in_creds.server); + if (ret) { + if (!quiet) { + fprintf(stderr, "%s: %s while parsing principal name\n", + names[i], error_message(ret)); + } + errors++; + continue; + } + + ret = krb5_unparse_name(context, in_creds.server, &princ); + if (ret) { + fprintf(stderr, "%s: %s while printing principal name\n", + names[i], error_message(ret)); + errors++; + continue; + } + + in_creds.keyblock.enctype = etype; + + ret = krb5_cc_retrieve_cred(context, fromccache, retflags, + &in_creds, &out_creds); + if (ret) { + fprintf(stderr, "%s: %s while retrieving credentials\n", + princ, error_message(ret)); + krb5_free_unparsed_name(context, princ); + errors++; + continue; + } + + ret = krb5_cc_store_cred(context, destccache, &out_creds); + krb5_free_principal(context, in_creds.server); + if (ret) { + fprintf(stderr, "%s: %s while removing credentials\n", + princ, error_message(ret)); + krb5_free_cred_contents(context, &out_creds); + krb5_free_unparsed_name(context, princ); + errors++; + continue; + } + + krb5_free_unparsed_name(context, princ); + krb5_free_cred_contents(context, &out_creds); + } + + krb5_free_principal(context, me); + krb5_cc_close(context, fromccache); + krb5_cc_close(context, destccache); + krb5_free_context(context); + + if (errors) + exit(1); + + exit(0); +} diff --git a/krb5-1.21.3/src/clients/kdeltkt/Makefile.in b/krb5-1.21.3/src/clients/kdeltkt/Makefile.in new file mode 100644 index 00000000..b7e0e73e --- /dev/null +++ b/krb5-1.21.3/src/clients/kdeltkt/Makefile.in @@ -0,0 +1,32 @@ +mydir=kvno +BUILDTOP=$(REL)..$(S).. + +##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc +##WIN32##RCFLAGS=$(CPPFLAGS) -I$(top_srcdir) -D_WIN32 -DRES_ONLY + +##WIN32##KDELTKT=$(OUTPRE)kdeltkt.exe + +##WIN32##EXERES=$(KDELTKT:.exe=.res) + +##WIN32##$(EXERES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DKDELTKT_APP -fo $@ -r $** + +all-unix: kdeltkt +##WIN32##all-windows: $(KDELTKT) +all-mac: + +kdeltkt: kdeltkt.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ kdeltkt.o $(KRB5_BASE_LIBS) + +##WIN32##$(KDELTKT): $(OUTPRE)kdeltkt.obj $(SLIB) $(KLIB) $(CLIB) $(EXERES) +##WIN32## link $(EXE_LINKOPTS) /out:$@ $** +##WIN32## $(_VC_MANIFEST_EMBED_EXE) + +clean-unix:: + $(RM) kdeltkt.o kdeltkt + +install-unix: + for f in kdeltkt; do \ + $(INSTALL_PROGRAM) $$f \ + $(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \ + done diff --git a/krb5-1.21.3/src/clients/kdeltkt/kdeltkt.c b/krb5-1.21.3/src/clients/kdeltkt/kdeltkt.c new file mode 100644 index 00000000..cd0bf637 --- /dev/null +++ b/krb5-1.21.3/src/clients/kdeltkt/kdeltkt.c @@ -0,0 +1,169 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ + +#include +#include +#include +#include +#include "k5-platform.h" + +static char *prog; +static int quiet = 0; + +static void +xusage() +{ + fprintf(stderr, "xusage: %s [-c ccache] [-e etype] [-f flags] service1 " + "service2 ...\n", prog); + exit(1); +} + +static void +do_kdeltkt(int argc, char *argv[], char *ccachestr, char *etypestr, int flags); + +int +main(int argc, char *argv[]) +{ + int option; + char *etypestr = NULL, *ccachestr = NULL; + int flags = 0; + + prog = strrchr(argv[0], '/'); + prog = (prog != NULL) ? prog + 1 : argv[0]; + + while ((option = getopt(argc, argv, "c:e:f:hq")) != -1) { + switch (option) { + case 'c': + ccachestr = optarg; + break; + case 'e': + etypestr = optarg; + break; + case 'f': + flags = atoi(optarg); + break; + case 'q': + quiet = 1; + break; + case 'h': + default: + xusage(); + break; + } + } + + if (argc - optind < 1) + xusage(); + + do_kdeltkt(argc - optind, argv + optind, ccachestr, etypestr, flags); + return 0; +} + +static void +do_kdeltkt(int count, char *names[], const char *ccachestr, char *etypestr, + int flags) +{ + krb5_context context; + krb5_error_code ret; + int i, errors; + krb5_enctype etype; + krb5_ccache ccache; + krb5_principal me; + krb5_creds in_creds, out_creds; + int retflags; + char *princ; + + ret = krb5_init_context(&context); + if (ret) { + com_err(prog, ret, "while initializing krb5 library"); + exit(1); + } + + if (etypestr != NULL) { + ret = krb5_string_to_enctype(etypestr, &etype); + if (ret) { + com_err(prog, ret, "while converting etype"); + exit(1); + } + retflags = KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES; + } else { + etype = 0; + retflags = KRB5_TC_MATCH_SRV_NAMEONLY; + } + + if (ccachestr) + ret = krb5_cc_resolve(context, ccachestr, &ccache); + else + ret = krb5_cc_default(context, &ccache); + if (ret) { + com_err(prog, ret, "while opening ccache"); + exit(1); + } + + ret = krb5_cc_get_principal(context, ccache, &me); + if (ret) { + com_err(prog, ret, "while getting client principal name"); + exit(1); + } + + errors = 0; + + for (i = 0; i < count; i++) { + memset(&in_creds, 0, sizeof(in_creds)); + + in_creds.client = me; + + ret = krb5_parse_name(context, names[i], &in_creds.server); + if (ret) { + if (!quiet) { + fprintf(stderr, "%s: %s while parsing principal name\n", + names[i], error_message(ret)); + } + errors++; + continue; + } + + ret = krb5_unparse_name(context, in_creds.server, &princ); + if (ret) { + fprintf(stderr, "%s: %s while printing principal name\n", + names[i], error_message(ret)); + errors++; + continue; + } + + in_creds.keyblock.enctype = etype; + + ret = krb5_cc_retrieve_cred(context, ccache, retflags, + &in_creds, &out_creds); + if (ret) { + fprintf(stderr, "%s: %s while retrieving credentials\n", + princ, error_message(ret)); + krb5_free_unparsed_name(context, princ); + errors++; + continue; + } + + ret = krb5_cc_remove_cred(context, ccache, flags, &out_creds); + + krb5_free_principal(context, in_creds.server); + + if (ret) { + fprintf(stderr, "%s: %s while removing credentials\n", + princ, error_message(ret)); + krb5_free_cred_contents(context, &out_creds); + krb5_free_unparsed_name(context, princ); + errors++; + continue; + } + krb5_free_unparsed_name(context, princ); + krb5_free_cred_contents(context, &out_creds); + } + + krb5_free_principal(context, me); + krb5_cc_close(context, ccache); + krb5_free_context(context); + + if (errors) + exit(1); + + exit(0); +} diff --git a/krb5-1.21.3/src/clients/kdestroy/Makefile.in b/krb5-1.21.3/src/clients/kdestroy/Makefile.in new file mode 100644 index 00000000..beb7d6fa --- /dev/null +++ b/krb5-1.21.3/src/clients/kdestroy/Makefile.in @@ -0,0 +1,35 @@ +mydir=clients$(S)kdestroy +BUILDTOP=$(REL)..$(S).. + +##WIN32##LOCALINCLUDES=-I$(BUILDTOP)\util\windows\ + +SRCS=kdestroy.c + +##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc +##WIN32##RCFLAGS=$(CPPFLAGS) -I$(top_srcdir) -D_WIN32 -DRES_ONLY + +##WIN32##KDESTROY=$(OUTPRE)kdestroy.exe + +##WIN32##EXERES=$(KDESTROY:.exe=.res) + +##WIN32##$(EXERES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DKDESTROY_APP -fo $@ -r $** + +all-unix: kdestroy +##WIN32##all-windows: $(KDESTROY) + +kdestroy: kdestroy.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ kdestroy.o $(KRB5_BASE_LIBS) + +##WIN32##$(KDESTROY): $(OUTPRE)kdestroy.obj $(SLIB) $(KLIB) $(CLIB) $(EXERES) +##WIN32## link $(EXE_LINKOPTS) -out:$@ $** +##WIN32## $(_VC_MANIFEST_EMBED_EXE) + +clean-unix:: + $(RM) kdestroy.o kdestroy + +install-unix: + for f in kdestroy; do \ + $(INSTALL_PROGRAM) $$f \ + $(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \ + done diff --git a/krb5-1.21.3/src/clients/kdestroy/deps b/krb5-1.21.3/src/clients/kdestroy/deps new file mode 100644 index 00000000..bfc94c4c --- /dev/null +++ b/krb5-1.21.3/src/clients/kdestroy/deps @@ -0,0 +1,7 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kdestroy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ + kdestroy.c diff --git a/krb5-1.21.3/src/clients/kdestroy/kdestroy.c b/krb5-1.21.3/src/clients/kdestroy/kdestroy.c new file mode 100644 index 00000000..774b729f --- /dev/null +++ b/krb5-1.21.3/src/clients/kdestroy/kdestroy.c @@ -0,0 +1,229 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* clients/kdestroy/kdestroy.c - Destroy contents of credential cache */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-platform.h" +#include +#include +#include +#include +#include + +#ifdef __STDC__ +#define BELL_CHAR '\a' +#else +#define BELL_CHAR '\007' +#endif + +#ifndef _WIN32 +#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/') + 1 : (x)) +#else +#define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x)) +#endif + +char *progname; + + +static void +usage() +{ + fprintf(stderr, _("Usage: %s [-A] [-q] [-c cache_name] [-p princ_name]\n"), + progname); + fprintf(stderr, _("\t-A destroy all credential caches in collection\n")); + fprintf(stderr, _("\t-q quiet mode\n")); + fprintf(stderr, _("\t-c specify name of credentials cache\n")); + fprintf(stderr, _("\t-p specify principal name within collection\n")); + exit(2); +} + +/* Print a warning if there are still un-destroyed caches in the collection. */ +static void +print_remaining_cc_warning(krb5_context context) +{ + krb5_error_code ret; + krb5_ccache cache; + krb5_cccol_cursor cursor; + + ret = krb5_cccol_cursor_new(context, &cursor); + if (ret) { + com_err(progname, ret, _("while listing credential caches")); + exit(1); + } + + ret = krb5_cccol_cursor_next(context, cursor, &cache); + if (ret == 0 && cache != NULL) { + fprintf(stderr, + _("Other credential caches present, use -A to destroy all\n")); + krb5_cc_close(context, cache); + } + + krb5_cccol_cursor_free(context, &cursor); +} + +int +main(int argc, char *argv[]) +{ + krb5_context context; + krb5_error_code ret; + krb5_ccache cache = NULL; + krb5_cccol_cursor cursor; + krb5_principal princ; + char *cache_name = NULL; + const char *princ_name = NULL; + int code = 0, errflg = 0, quiet = 0, all = 0, c; + + setlocale(LC_ALL, ""); + progname = GET_PROGNAME(argv[0]); + + while ((c = getopt(argc, argv, "54Aqc:p:")) != -1) { + switch (c) { + case 'A': + all = 1; + break; + case 'q': + quiet = 1; + break; + case 'c': + if (cache_name) { + fprintf(stderr, _("Only one -c option allowed\n")); + errflg++; + } else { + cache_name = optarg; + } + break; + case 'p': + if (princ_name != NULL) { + fprintf(stderr, _("Only one -p option allowed\n")); + errflg++; + } else { + princ_name = optarg; + } + break; + case '4': + fprintf(stderr, _("Kerberos 4 is no longer supported\n")); + exit(3); + break; + case '5': + break; + case '?': + default: + errflg++; + break; + } + } + + if (all && princ_name != NULL) { + fprintf(stderr, _("-A option is exclusive with -p option\n")); + errflg++; + } + + if (optind != argc) + errflg++; + + if (errflg) + usage(); + + ret = krb5_init_context(&context); + if (ret) { + com_err(progname, ret, _("while initializing krb5")); + exit(1); + } + + if (cache_name != NULL) { + code = krb5_cc_set_default_name(context, cache_name); + if (code) { + com_err(progname, code, _("while setting default cache name")); + exit(1); + } + } + + if (all) { + code = krb5_cccol_cursor_new(context, &cursor); + if (code) { + com_err(progname, code, _("while listing credential caches")); + exit(1); + } + while (krb5_cccol_cursor_next(context, cursor, &cache) == 0 && + cache != NULL) { + code = krb5_cc_get_full_name(context, cache, &cache_name); + if (code) { + com_err(progname, code, _("composing ccache name")); + exit(1); + } + code = krb5_cc_destroy(context, cache); + if (code && code != KRB5_FCC_NOFILE) { + com_err(progname, code, _("while destroying cache %s"), + cache_name); + } + krb5_free_string(context, cache_name); + } + krb5_cccol_cursor_free(context, &cursor); + krb5_free_context(context); + return 0; + } + + if (princ_name != NULL) { + code = krb5_parse_name(context, princ_name, &princ); + if (code) { + com_err(progname, code, _("while parsing principal name %s"), + princ_name); + exit(1); + } + code = krb5_cc_cache_match(context, princ, &cache); + if (code) { + com_err(progname, code, _("while finding cache for %s"), + princ_name); + exit(1); + } + krb5_free_principal(context, princ); + } else { + code = krb5_cc_default(context, &cache); + if (code) { + com_err(progname, code, _("while resolving ccache")); + exit(1); + } + } + + code = krb5_cc_destroy(context, cache); + if (code != 0) { + com_err(progname, code, _("while destroying cache")); + if (code != KRB5_FCC_NOFILE) { + if (quiet) { + fprintf(stderr, _("Ticket cache NOT destroyed!\n")); + } else { + fprintf(stderr, _("Ticket cache %cNOT%c destroyed!\n"), + BELL_CHAR, BELL_CHAR); + } + errflg = 1; + } + } + + if (!quiet && !errflg && princ_name == NULL) + print_remaining_cc_warning(context); + + krb5_free_context(context); + + return errflg; +} diff --git a/krb5-1.21.3/src/clients/kinit/Makefile.in b/krb5-1.21.3/src/clients/kinit/Makefile.in new file mode 100644 index 00000000..9d02174d --- /dev/null +++ b/krb5-1.21.3/src/clients/kinit/Makefile.in @@ -0,0 +1,34 @@ +mydir=clients$(S)kinit +BUILDTOP=$(REL)..$(S).. + +SRCS=kinit.c kinit_kdb.c +##WIN32##LOCALINCLUDES=-I$(BUILDTOP)\util\windows -I$(BUILDTOP)\util\support + +##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc +##WIN32##RCFLAGS=$(CPPFLAGS) -I$(top_srcdir) -D_WIN32 -DRES_ONLY + +##WIN32##KINIT=$(OUTPRE)kinit.exe + +##WIN32##EXERES=$(KINIT:.exe=.res) + +##WIN32##$(EXERES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DKINIT_APP -fo $@ -r $** + +all-unix: kinit +##WIN32##all-windows: $(KINIT) + +kinit: kinit.o kinit_kdb.o $(KRB5_BASE_DEPLIBS) $(KADMSRV_DEPLIBS) + $(CC_LINK) -o $@ kinit.o kinit_kdb.o $(KADMSRV_LIBS) $(KRB5_BASE_LIBS) + +##WIN32##$(KINIT): $(OUTPRE)kinit.obj $(SLIB) $(KLIB) $(CLIB) $(EXERES) +##WIN32## link $(EXE_LINKOPTS) -out:$@ $** advapi32.lib +##WIN32## $(_VC_MANIFEST_EMBED_EXE) + +clean-unix:: + $(RM) kinit.o kinit_kdb.o kinit + +install-unix: + for f in kinit; do \ + $(INSTALL_PROGRAM) $$f \ + $(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \ + done diff --git a/krb5-1.21.3/src/clients/kinit/deps b/krb5-1.21.3/src/clients/kinit/deps new file mode 100644 index 00000000..56e9d669 --- /dev/null +++ b/krb5-1.21.3/src/clients/kinit/deps @@ -0,0 +1,32 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kinit.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h extern.h kinit.c +$(OUTPRE)kinit_kdb.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + extern.h kinit_kdb.c diff --git a/krb5-1.21.3/src/clients/kinit/extern.h b/krb5-1.21.3/src/clients/kinit/extern.h new file mode 100644 index 00000000..2c286231 --- /dev/null +++ b/krb5-1.21.3/src/clients/kinit/extern.h @@ -0,0 +1,33 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* clients/kinit/extern.h - Global declarations for kinit */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef KINIT_EXTERN_H +#define KINIT_EXTERN_H + +krb5_error_code kinit_kdb_init(krb5_context *pcontext, char *realm); +void kinit_kdb_fini(void); + +#endif /* KINIT_EXTERN_H */ diff --git a/krb5-1.21.3/src/clients/kinit/kinit.c b/krb5-1.21.3/src/clients/kinit/kinit.c new file mode 100644 index 00000000..f4c7b2b8 --- /dev/null +++ b/krb5-1.21.3/src/clients/kinit/kinit.c @@ -0,0 +1,892 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* clients/kinit/kinit.c - Initialize a credential cache */ +/* + * Copyright 1990, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "autoconf.h" +#include +#include "k5-platform.h" /* For asprintf and getopt */ +#include +#include "extern.h" +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/') + 1 : (x)) +#else +#define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x)) +#endif + +#ifdef HAVE_PWD_H +#include +static char * +get_name_from_os() +{ + struct passwd *pw; + + pw = getpwuid(getuid()); + return (pw != NULL) ? pw->pw_name : NULL; +} +#else /* HAVE_PWD_H */ +#ifdef _WIN32 +static char * +get_name_from_os() +{ + static char name[1024]; + DWORD name_size = sizeof(name); + + if (GetUserName(name, &name_size)) { + name[sizeof(name) - 1] = '\0'; /* Just to be extra safe */ + return name; + } else { + return NULL; + } +} +#else /* _WIN32 */ +static char * +get_name_from_os() +{ + return NULL; +} +#endif /* _WIN32 */ +#endif /* HAVE_PWD_H */ + +static char *progname; + +typedef enum { INIT_PW, INIT_KT, RENEW, VALIDATE } action_type; + +struct k_opts +{ + /* In seconds */ + krb5_deltat starttime; + krb5_deltat lifetime; + krb5_deltat rlife; + + int forwardable; + int proxiable; + int request_pac; + int anonymous; + int addresses; + + int not_forwardable; + int not_proxiable; + int not_request_pac; + int no_addresses; + + int verbose; + + char *principal_name; + char *service_name; + char *keytab_name; + char *k5_in_cache_name; + char *k5_out_cache_name; + char *armor_ccache; + + action_type action; + int use_client_keytab; + + int num_pa_opts; + krb5_gic_opt_pa_data *pa_opts; + + int canonicalize; + int enterprise; +}; + +struct k5_data +{ + krb5_context ctx; + krb5_ccache in_cc, out_cc; + krb5_principal me; + char *name; + krb5_boolean switch_to_cache; +}; + +/* + * If struct[2] == NULL, then long_getopt acts as if the short flag struct[3] + * were specified. If struct[2] != NULL, then struct[3] is stored in + * *(struct[2]), the array index which was specified is stored in *index, and + * long_getopt() returns 0. + */ +const char *shopts = "r:fpFPn54aAVl:s:c:kit:T:RS:vX:CEI:"; + +#define USAGE_BREAK "\n\t" + +static void +usage() +{ + fprintf(stderr, + _("Usage: %s [-V] [-l lifetime] [-s start_time] " + "[-r renewable_life]\n" + "\t[-f | -F] [-p | -P] [-n] [-a | -A] [-C] [-E]\n" + "\t[--request-pac | --no-request-pac]\n" + "\t[-v] [-R] [-k [-i|-t keytab_file]] [-c cachename]\n" + "\t[-S service_name] [-I input_ccache] [-T ticket_armor_cache]\n" + "\t[-X [=]] [principal]\n" + "\n"), progname); + + fprintf(stderr, " options:\n"); + fprintf(stderr, _("\t-V verbose\n")); + fprintf(stderr, _("\t-l lifetime\n")); + fprintf(stderr, _("\t-s start time\n")); + fprintf(stderr, _("\t-r renewable lifetime\n")); + fprintf(stderr, _("\t-f forwardable\n")); + fprintf(stderr, _("\t-F not forwardable\n")); + fprintf(stderr, _("\t-p proxiable\n")); + fprintf(stderr, _("\t-P not proxiable\n")); + fprintf(stderr, _("\t-n anonymous\n")); + fprintf(stderr, _("\t-a include addresses\n")); + fprintf(stderr, _("\t-A do not include addresses\n")); + fprintf(stderr, _("\t-v validate\n")); + fprintf(stderr, _("\t-R renew\n")); + fprintf(stderr, _("\t-C canonicalize\n")); + fprintf(stderr, _("\t-E client is enterprise principal name\n")); + fprintf(stderr, _("\t-k use keytab\n")); + fprintf(stderr, _("\t-i use default client keytab (with -k)\n")); + fprintf(stderr, _("\t-t filename of keytab to use\n")); + fprintf(stderr, _("\t-c Kerberos 5 cache name\n")); + fprintf(stderr, _("\t-S service\n")); + fprintf(stderr, _("\t-I input credential cache\n")); + fprintf(stderr, _("\t-T armor credential cache\n")); + fprintf(stderr, _("\t-X [=]\n")); + fprintf(stderr, + _("\t--{,no}-request-pac request KDC include/exclude a PAC\n")); + exit(2); +} + +static krb5_context errctx; +static void +extended_com_err_fn(const char *myprog, errcode_t code, const char *fmt, + va_list args) +{ + const char *emsg; + + emsg = krb5_get_error_message(errctx, code); + fprintf(stderr, "%s: %s ", myprog, emsg); + krb5_free_error_message(errctx, emsg); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); +} + +static int +add_preauth_opt(struct k_opts *opts, char *av) +{ + char *sep, *v; + krb5_gic_opt_pa_data *p, *x; + size_t newsize = (opts->num_pa_opts + 1) * sizeof(*opts->pa_opts); + + x = realloc(opts->pa_opts, newsize); + if (x == NULL) + return ENOMEM; + opts->pa_opts = x; + + p = &opts->pa_opts[opts->num_pa_opts]; + sep = strchr(av, '='); + if (sep) { + *sep = '\0'; + v = ++sep; + p->value = v; + } else { + p->value = "yes"; + } + p->attr = av; + opts->num_pa_opts++; + return 0; +} + +static char * +parse_options(int argc, char **argv, struct k_opts *opts) +{ + struct option long_options[] = { + { "noforwardable", 0, NULL, 'F' }, + { "noproxiable", 0, NULL, 'P' }, + { "addresses", 0, NULL, 'a'}, + { "forwardable", 0, NULL, 'f' }, + { "proxiable", 0, NULL, 'p' }, + { "noaddresses", 0, NULL, 'A' }, + { "canonicalize", 0, NULL, 'C' }, + { "enterprise", 0, NULL, 'E' }, + { "request-pac", 0, &opts->request_pac, 1 }, + { "no-request-pac", 0, &opts->not_request_pac, 1 }, + { NULL, 0, NULL, 0 } + }; + krb5_error_code ret; + int errflg = 0; + int i; + + while ((i = getopt_long(argc, argv, shopts, long_options, 0)) != -1) { + switch (i) { + case 'V': + opts->verbose = 1; + break; + case 'l': + /* Lifetime */ + ret = krb5_string_to_deltat(optarg, &opts->lifetime); + if (ret || opts->lifetime == 0) { + fprintf(stderr, _("Bad lifetime value %s\n"), optarg); + errflg++; + } + break; + case 'r': + /* Renewable Time */ + ret = krb5_string_to_deltat(optarg, &opts->rlife); + if (ret || opts->rlife == 0) { + fprintf(stderr, _("Bad lifetime value %s\n"), optarg); + errflg++; + } + break; + case 'f': + opts->forwardable = 1; + break; + case 'F': + opts->not_forwardable = 1; + break; + case 'p': + opts->proxiable = 1; + break; + case 'P': + opts->not_proxiable = 1; + break; + case 'n': + opts->anonymous = 1; + break; + case 'a': + opts->addresses = 1; + break; + case 'A': + opts->no_addresses = 1; + break; + case 's': + ret = krb5_string_to_deltat(optarg, &opts->starttime); + if (ret || opts->starttime == 0) { + /* Parse as an absolute time; intentionally undocumented + * but left for backwards compatibility. */ + krb5_timestamp abs_starttime; + + ret = krb5_string_to_timestamp(optarg, &abs_starttime); + if (ret || abs_starttime == 0) { + fprintf(stderr, _("Bad start time value %s\n"), optarg); + errflg++; + } else { + opts->starttime = ts_delta(abs_starttime, time(NULL)); + } + } + break; + case 'S': + opts->service_name = optarg; + break; + case 'k': + opts->action = INIT_KT; + break; + case 'i': + opts->use_client_keytab = 1; + break; + case 't': + if (opts->keytab_name != NULL) { + fprintf(stderr, _("Only one -t option allowed.\n")); + errflg++; + } else { + opts->keytab_name = optarg; + } + break; + case 'T': + if (opts->armor_ccache != NULL) { + fprintf(stderr, _("Only one armor_ccache\n")); + errflg++; + } else { + opts->armor_ccache = optarg; + } + break; + case 'R': + opts->action = RENEW; + break; + case 'v': + opts->action = VALIDATE; + break; + case 'c': + if (opts->k5_out_cache_name != NULL) { + fprintf(stderr, _("Only one -c option allowed\n")); + errflg++; + } else { + opts->k5_out_cache_name = optarg; + } + break; + case 'I': + if (opts->k5_in_cache_name != NULL) { + fprintf(stderr, _("Only one -I option allowed\n")); + errflg++; + } else { + opts->k5_in_cache_name = optarg; + } + break; + case 'X': + ret = add_preauth_opt(opts, optarg); + if (ret) { + com_err(progname, ret, _("while adding preauth option")); + errflg++; + } + break; + case 'C': + opts->canonicalize = 1; + break; + case 'E': + opts->enterprise = 1; + break; + case '4': + fprintf(stderr, _("Kerberos 4 is no longer supported\n")); + exit(3); + break; + case '5': + break; + case 0: + /* If this option set a flag, do nothing else now. */ + break; + default: + errflg++; + break; + } + } + + if (opts->forwardable && opts->not_forwardable) { + fprintf(stderr, _("Only one of -f and -F allowed\n")); + errflg++; + } + if (opts->proxiable && opts->not_proxiable) { + fprintf(stderr, _("Only one of -p and -P allowed\n")); + errflg++; + } + if (opts->request_pac && opts->not_request_pac) { + fprintf(stderr, _("Only one of --request-pac and --no-request-pac " + "allowed\n")); + errflg++; + } + if (opts->addresses && opts->no_addresses) { + fprintf(stderr, _("Only one of -a and -A allowed\n")); + errflg++; + } + if (opts->keytab_name != NULL && opts->use_client_keytab == 1) { + fprintf(stderr, _("Only one of -t and -i allowed\n")); + errflg++; + } + if ((opts->keytab_name != NULL || opts->use_client_keytab == 1) && + opts->action != INIT_KT) { + opts->action = INIT_KT; + fprintf(stderr, _("keytab specified, forcing -k\n")); + } + if (argc - optind > 1) { + fprintf(stderr, _("Extra arguments (starting with \"%s\").\n"), + argv[optind + 1]); + errflg++; + } + + if (errflg) + usage(); + + opts->principal_name = (optind == argc - 1) ? argv[optind] : 0; + return opts->principal_name; +} + +static int +k5_begin(struct k_opts *opts, struct k5_data *k5) +{ + krb5_error_code ret; + int success = 0; + int flags = opts->enterprise ? KRB5_PRINCIPAL_PARSE_ENTERPRISE : 0; + krb5_ccache defcache = NULL; + krb5_principal defcache_princ = NULL, princ; + krb5_keytab keytab; + const char *deftype = NULL; + char *defrealm, *name; + + ret = krb5_init_context(&k5->ctx); + if (ret) { + com_err(progname, ret, _("while initializing Kerberos 5 library")); + return 0; + } + errctx = k5->ctx; + + if (opts->k5_out_cache_name) { + ret = krb5_cc_resolve(k5->ctx, opts->k5_out_cache_name, &k5->out_cc); + if (ret) { + com_err(progname, ret, _("resolving ccache %s"), + opts->k5_out_cache_name); + goto cleanup; + } + if (opts->verbose) { + fprintf(stderr, _("Using specified cache: %s\n"), + opts->k5_out_cache_name); + } + } else { + /* Resolve the default ccache and get its type and default principal + * (if it is initialized). */ + ret = krb5_cc_default(k5->ctx, &defcache); + if (ret) { + com_err(progname, ret, _("while getting default ccache")); + goto cleanup; + } + deftype = krb5_cc_get_type(k5->ctx, defcache); + if (krb5_cc_get_principal(k5->ctx, defcache, &defcache_princ) != 0) + defcache_princ = NULL; + } + + /* Choose a client principal name. */ + if (opts->principal_name != NULL) { + /* Use the specified principal name. */ + ret = krb5_parse_name_flags(k5->ctx, opts->principal_name, flags, + &k5->me); + if (ret) { + com_err(progname, ret, _("when parsing name %s"), + opts->principal_name); + goto cleanup; + } + } else if (opts->anonymous) { + /* Use the anonymous principal for the local realm. */ + ret = krb5_get_default_realm(k5->ctx, &defrealm); + if (ret) { + com_err(progname, ret, _("while getting default realm")); + goto cleanup; + } + ret = krb5_build_principal_ext(k5->ctx, &k5->me, + strlen(defrealm), defrealm, + strlen(KRB5_WELLKNOWN_NAMESTR), + KRB5_WELLKNOWN_NAMESTR, + strlen(KRB5_ANONYMOUS_PRINCSTR), + KRB5_ANONYMOUS_PRINCSTR, 0); + krb5_free_default_realm(k5->ctx, defrealm); + if (ret) { + com_err(progname, ret, _("while building principal")); + goto cleanup; + } + } else if (opts->action == INIT_KT && opts->use_client_keytab) { + /* Use the first entry from the client keytab. */ + ret = krb5_kt_client_default(k5->ctx, &keytab); + if (ret) { + com_err(progname, ret, + _("When resolving the default client keytab")); + goto cleanup; + } + ret = k5_kt_get_principal(k5->ctx, keytab, &k5->me); + krb5_kt_close(k5->ctx, keytab); + if (ret) { + com_err(progname, ret, + _("When determining client principal name from keytab")); + goto cleanup; + } + } else if (opts->action == INIT_KT) { + /* Use the default host/service name. */ + ret = krb5_sname_to_principal(k5->ctx, NULL, NULL, KRB5_NT_SRV_HST, + &k5->me); + if (ret) { + com_err(progname, ret, + _("when creating default server principal name")); + goto cleanup; + } + } else if (k5->out_cc != NULL) { + /* If the output ccache is initialized, use its principal. */ + if (krb5_cc_get_principal(k5->ctx, k5->out_cc, &princ) == 0) + k5->me = princ; + } else if (defcache_princ != NULL) { + /* Use the default cache's principal, and use the default cache as the + * output cache. */ + k5->out_cc = defcache; + defcache = NULL; + k5->me = defcache_princ; + defcache_princ = NULL; + } + + /* If we still haven't chosen, use the local username. */ + if (k5->me == NULL) { + name = get_name_from_os(); + if (name == NULL) { + fprintf(stderr, _("Unable to identify user\n")); + goto cleanup; + } + ret = krb5_parse_name_flags(k5->ctx, name, flags, &k5->me); + if (ret) { + com_err(progname, ret, _("when parsing name %s"), name); + goto cleanup; + } + } + + if (k5->out_cc == NULL && krb5_cc_support_switch(k5->ctx, deftype)) { + /* Use an existing cache for the client principal if we can. */ + ret = krb5_cc_cache_match(k5->ctx, k5->me, &k5->out_cc); + if (ret && ret != KRB5_CC_NOTFOUND) { + com_err(progname, ret, _("while searching for ccache for %s"), + opts->principal_name); + goto cleanup; + } + if (!ret) { + if (opts->verbose) { + fprintf(stderr, _("Using existing cache: %s\n"), + krb5_cc_get_name(k5->ctx, k5->out_cc)); + } + k5->switch_to_cache = 1; + } else if (defcache_princ != NULL) { + /* Create a new cache to avoid overwriting the initialized default + * cache. */ + ret = krb5_cc_new_unique(k5->ctx, deftype, NULL, &k5->out_cc); + if (ret) { + com_err(progname, ret, _("while generating new ccache")); + goto cleanup; + } + if (opts->verbose) { + fprintf(stderr, _("Using new cache: %s\n"), + krb5_cc_get_name(k5->ctx, k5->out_cc)); + } + k5->switch_to_cache = 1; + } + } + + /* Use the default cache if we haven't picked one yet. */ + if (k5->out_cc == NULL) { + k5->out_cc = defcache; + defcache = NULL; + if (opts->verbose) { + fprintf(stderr, _("Using default cache: %s\n"), + krb5_cc_get_name(k5->ctx, k5->out_cc)); + } + } + + if (opts->k5_in_cache_name) { + ret = krb5_cc_resolve(k5->ctx, opts->k5_in_cache_name, &k5->in_cc); + if (ret) { + com_err(progname, ret, _("resolving ccache %s"), + opts->k5_in_cache_name); + goto cleanup; + } + if (opts->verbose) { + fprintf(stderr, _("Using specified input cache: %s\n"), + opts->k5_in_cache_name); + } + } + + ret = krb5_unparse_name(k5->ctx, k5->me, &k5->name); + if (ret) { + com_err(progname, ret, _("when unparsing name")); + goto cleanup; + } + if (opts->verbose) + fprintf(stderr, _("Using principal: %s\n"), k5->name); + + opts->principal_name = k5->name; + + success = 1; + +cleanup: + if (defcache != NULL) + krb5_cc_close(k5->ctx, defcache); + krb5_free_principal(k5->ctx, defcache_princ); + return success; +} + +static void +k5_end(struct k5_data *k5) +{ + krb5_free_unparsed_name(k5->ctx, k5->name); + krb5_free_principal(k5->ctx, k5->me); + if (k5->in_cc != NULL) + krb5_cc_close(k5->ctx, k5->in_cc); + if (k5->out_cc != NULL) + krb5_cc_close(k5->ctx, k5->out_cc); + krb5_free_context(k5->ctx); + errctx = NULL; + memset(k5, 0, sizeof(*k5)); +} + +static krb5_error_code KRB5_CALLCONV +kinit_prompter(krb5_context ctx, void *data, const char *name, + const char *banner, int num_prompts, krb5_prompt prompts[]) +{ + krb5_boolean *pwprompt = data; + krb5_prompt_type *ptypes; + int i; + + /* Make a note if we receive a password prompt. */ + ptypes = krb5_get_prompt_types(ctx); + for (i = 0; i < num_prompts; i++) { + if (ptypes != NULL && ptypes[i] == KRB5_PROMPT_TYPE_PASSWORD) + *pwprompt = TRUE; + } + return krb5_prompter_posix(ctx, data, name, banner, num_prompts, prompts); +} + +static int +k5_kinit(struct k_opts *opts, struct k5_data *k5) +{ + int notix = 1; + krb5_keytab keytab = 0; + krb5_creds my_creds; + krb5_error_code ret; + krb5_get_init_creds_opt *options = NULL; + krb5_boolean pwprompt = FALSE; + krb5_address **addresses = NULL; + krb5_principal cprinc; + krb5_ccache mcc = NULL; + int i; + + memset(&my_creds, 0, sizeof(my_creds)); + + ret = krb5_get_init_creds_opt_alloc(k5->ctx, &options); + if (ret) + goto cleanup; + + if (opts->lifetime) + krb5_get_init_creds_opt_set_tkt_life(options, opts->lifetime); + if (opts->rlife) + krb5_get_init_creds_opt_set_renew_life(options, opts->rlife); + if (opts->forwardable) + krb5_get_init_creds_opt_set_forwardable(options, 1); + if (opts->not_forwardable) + krb5_get_init_creds_opt_set_forwardable(options, 0); + if (opts->proxiable) + krb5_get_init_creds_opt_set_proxiable(options, 1); + if (opts->not_proxiable) + krb5_get_init_creds_opt_set_proxiable(options, 0); + if (opts->canonicalize) + krb5_get_init_creds_opt_set_canonicalize(options, 1); + if (opts->anonymous) + krb5_get_init_creds_opt_set_anonymous(options, 1); + if (opts->addresses) { + ret = krb5_os_localaddr(k5->ctx, &addresses); + if (ret) { + com_err(progname, ret, _("getting local addresses")); + goto cleanup; + } + krb5_get_init_creds_opt_set_address_list(options, addresses); + } + if (opts->no_addresses) + krb5_get_init_creds_opt_set_address_list(options, NULL); + if (opts->armor_ccache != NULL) { + krb5_get_init_creds_opt_set_fast_ccache_name(k5->ctx, options, + opts->armor_ccache); + } + if (opts->request_pac) + krb5_get_init_creds_opt_set_pac_request(k5->ctx, options, TRUE); + if (opts->not_request_pac) + krb5_get_init_creds_opt_set_pac_request(k5->ctx, options, FALSE); + + + if (opts->action == INIT_KT && opts->keytab_name != NULL) { +#ifndef _WIN32 + if (strncmp(opts->keytab_name, "KDB:", 4) == 0) { + ret = kinit_kdb_init(&k5->ctx, k5->me->realm.data); + errctx = k5->ctx; + if (ret) { + com_err(progname, ret, + _("while setting up KDB keytab for realm %s"), + k5->me->realm.data); + goto cleanup; + } + } +#endif + + ret = krb5_kt_resolve(k5->ctx, opts->keytab_name, &keytab); + if (ret) { + com_err(progname, ret, _("resolving keytab %s"), + opts->keytab_name); + goto cleanup; + } + if (opts->verbose) + fprintf(stderr, _("Using keytab: %s\n"), opts->keytab_name); + } else if (opts->action == INIT_KT && opts->use_client_keytab) { + ret = krb5_kt_client_default(k5->ctx, &keytab); + if (ret) { + com_err(progname, ret, _("resolving default client keytab")); + goto cleanup; + } + } + + for (i = 0; i < opts->num_pa_opts; i++) { + ret = krb5_get_init_creds_opt_set_pa(k5->ctx, options, + opts->pa_opts[i].attr, + opts->pa_opts[i].value); + if (ret) { + com_err(progname, ret, _("while setting '%s'='%s'"), + opts->pa_opts[i].attr, opts->pa_opts[i].value); + goto cleanup; + } + if (opts->verbose) { + fprintf(stderr, _("PA Option %s = %s\n"), opts->pa_opts[i].attr, + opts->pa_opts[i].value); + } + } + if (k5->in_cc) { + ret = krb5_get_init_creds_opt_set_in_ccache(k5->ctx, options, + k5->in_cc); + if (ret) + goto cleanup; + } + ret = krb5_get_init_creds_opt_set_out_ccache(k5->ctx, options, k5->out_cc); + if (ret) + goto cleanup; + + switch (opts->action) { + case INIT_PW: + ret = krb5_get_init_creds_password(k5->ctx, &my_creds, k5->me, 0, + kinit_prompter, &pwprompt, + opts->starttime, opts->service_name, + options); + break; + case INIT_KT: + ret = krb5_get_init_creds_keytab(k5->ctx, &my_creds, k5->me, keytab, + opts->starttime, opts->service_name, + options); + break; + case VALIDATE: + ret = krb5_get_validated_creds(k5->ctx, &my_creds, k5->me, k5->out_cc, + opts->service_name); + break; + case RENEW: + ret = krb5_get_renewed_creds(k5->ctx, &my_creds, k5->me, k5->out_cc, + opts->service_name); + break; + } + + if (ret) { + char *doing = NULL; + switch (opts->action) { + case INIT_PW: + case INIT_KT: + doing = _("getting initial credentials"); + break; + case VALIDATE: + doing = _("validating credentials"); + break; + case RENEW: + doing = _("renewing credentials"); + break; + } + + /* If reply decryption failed, or if pre-authentication failed and we + * were prompted for a password, assume the password was wrong. */ + if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY || + (pwprompt && ret == KRB5KDC_ERR_PREAUTH_FAILED)) { + fprintf(stderr, _("%s: Password incorrect while %s\n"), progname, + doing); + } else { + com_err(progname, ret, _("while %s"), doing); + } + goto cleanup; + } + + if (opts->action != INIT_PW && opts->action != INIT_KT) { + cprinc = opts->canonicalize ? my_creds.client : k5->me; + ret = krb5_cc_new_unique(k5->ctx, "MEMORY", NULL, &mcc); + if (!ret) + ret = krb5_cc_initialize(k5->ctx, mcc, cprinc); + if (ret) { + com_err(progname, ret, _("when creating temporary cache")); + goto cleanup; + } + if (opts->verbose) + fprintf(stderr, _("Initialized cache\n")); + + ret = k5_cc_store_primary_cred(k5->ctx, mcc, &my_creds); + if (ret) { + com_err(progname, ret, _("while storing credentials")); + goto cleanup; + } + ret = krb5_cc_move(k5->ctx, mcc, k5->out_cc); + if (ret) { + com_err(progname, ret, _("while saving to cache %s"), + opts->k5_out_cache_name ? opts->k5_out_cache_name : ""); + goto cleanup; + } + mcc = NULL; + if (opts->verbose) + fprintf(stderr, _("Stored credentials\n")); + } + notix = 0; + if (k5->switch_to_cache) { + ret = krb5_cc_switch(k5->ctx, k5->out_cc); + if (ret) { + com_err(progname, ret, _("while switching to new ccache")); + goto cleanup; + } + } + +cleanup: +#ifndef _WIN32 + kinit_kdb_fini(); +#endif + if (mcc != NULL) + krb5_cc_destroy(k5->ctx, mcc); + if (options) + krb5_get_init_creds_opt_free(k5->ctx, options); + if (my_creds.client == k5->me) + my_creds.client = 0; + if (opts->pa_opts) { + free(opts->pa_opts); + opts->pa_opts = NULL; + opts->num_pa_opts = 0; + } + krb5_free_cred_contents(k5->ctx, &my_creds); + if (keytab != NULL) + krb5_kt_close(k5->ctx, keytab); + return notix ? 0 : 1; +} + +int +main(int argc, char *argv[]) +{ + struct k_opts opts; + struct k5_data k5; + int authed_k5 = 0; + + setlocale(LC_ALL, ""); + progname = GET_PROGNAME(argv[0]); + + /* Ensure we can be driven from a pipe */ + if (!isatty(fileno(stdin))) + setvbuf(stdin, 0, _IONBF, 0); + if (!isatty(fileno(stdout))) + setvbuf(stdout, 0, _IONBF, 0); + if (!isatty(fileno(stderr))) + setvbuf(stderr, 0, _IONBF, 0); + + memset(&opts, 0, sizeof(opts)); + opts.action = INIT_PW; + + memset(&k5, 0, sizeof(k5)); + + set_com_err_hook(extended_com_err_fn); + + parse_options(argc, argv, &opts); + + if (k5_begin(&opts, &k5)) + authed_k5 = k5_kinit(&opts, &k5); + + if (authed_k5 && opts.verbose) + fprintf(stderr, _("Authenticated to Kerberos v5\n")); + + k5_end(&k5); + + if (!authed_k5) + exit(1); + return 0; +} diff --git a/krb5-1.21.3/src/clients/kinit/kinit_kdb.c b/krb5-1.21.3/src/clients/kinit/kinit_kdb.c new file mode 100644 index 00000000..fbd174bf --- /dev/null +++ b/krb5-1.21.3/src/clients/kinit/kinit_kdb.c @@ -0,0 +1,75 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* clients/kinit/kinit_kdb.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/** + * @file kinit_kdb.c + * Operations to open the KDB and make the KDB key table available + * for kinit. + */ + + +#include +#include +#include +#include "extern.h" + +/* Server handle */ +static void *server_handle; + +/* Free and reinitialize *pcontext with the KDB opened to the given realm, so + * that it can be used with the KDB keytab type. */ +krb5_error_code +kinit_kdb_init(krb5_context *pcontext, char *realm) +{ + kadm5_config_params config; + krb5_error_code ret; + + if (*pcontext) { + krb5_free_context(*pcontext); + *pcontext = NULL; + } + memset(&config, 0, sizeof config); + + ret = kadm5_init_krb5_context(pcontext); + if (ret) + return ret; + + config.mask = KADM5_CONFIG_REALM; + config.realm = realm; + ret = kadm5_init(*pcontext, "kinit", NULL, "kinit", &config, + KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, NULL, + &server_handle); + if (ret) + return ret; + + return krb5_db_register_keytab(*pcontext); +} + +void +kinit_kdb_fini() +{ + kadm5_destroy(server_handle); +} diff --git a/krb5-1.21.3/src/clients/klist/Makefile.in b/krb5-1.21.3/src/clients/klist/Makefile.in new file mode 100644 index 00000000..32348251 --- /dev/null +++ b/krb5-1.21.3/src/clients/klist/Makefile.in @@ -0,0 +1,35 @@ +mydir=clients$(S)klist +BUILDTOP=$(REL)..$(S).. + +##WIN32##LOCALINCLUDES=-I$(BUILDTOP)\util\windows\ + +SRCS = klist.c + +##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc +##WIN32##RCFLAGS=$(CPPFLAGS) -I$(top_srcdir) -D_WIN32 -DRES_ONLY + +##WIN32##KLIST=$(OUTPRE)klist.exe + +##WIN32##EXERES=$(KLIST:.exe=.res) + +##WIN32##$(EXERES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DKLIST_APP -fo $@ -r $** + +all-unix: klist +##WIN32##all-windows: $(KLIST) + +klist: klist.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ klist.o $(KRB5_BASE_LIBS) + +##WIN32##$(KLIST): $(OUTPRE)klist.obj $(SLIB) $(KLIB) $(CLIB) $(EXERES) +##WIN32## link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib +##WIN32## $(_VC_MANIFEST_EMBED_EXE) + +clean-unix:: + $(RM) klist.o klist + +install-unix: + for f in klist; do \ + $(INSTALL_PROGRAM) $$f \ + $(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \ + done diff --git a/krb5-1.21.3/src/clients/klist/deps b/krb5-1.21.3/src/clients/klist/deps new file mode 100644 index 00000000..ef0edbc3 --- /dev/null +++ b/krb5-1.21.3/src/clients/klist/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)klist.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/fake-addrinfo.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + klist.c diff --git a/krb5-1.21.3/src/clients/klist/klist.c b/krb5-1.21.3/src/clients/klist/klist.c new file mode 100644 index 00000000..dcdc5a2d --- /dev/null +++ b/krb5-1.21.3/src/clients/klist/klist.c @@ -0,0 +1,870 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* clients/klist/klist.c - List contents of credential cache or keytab */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include +#include +#include +#include +#include +#include +#include + +/* Need definition of INET6 before network headers, for IRIX. */ +#if defined(HAVE_ARPA_INET_H) +#include +#endif + +#ifndef _WIN32 +#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/') + 1 : (x)) +#else +#define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x)) +#endif + +#ifndef _WIN32 +#include +#include +#endif + +int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0; +int show_etype = 0, show_addresses = 0, no_resolve = 0, print_version = 0; +int show_adtype = 0, show_all = 0, list_all = 0, use_client_keytab = 0; +int show_config = 0; +char *defname; +char *progname; +krb5_timestamp now; +unsigned int timestamp_width; + +krb5_context context; + +static krb5_boolean is_local_tgt(krb5_principal princ, krb5_data *realm); +static char *etype_string(krb5_enctype ); +static void show_credential(krb5_creds *); + +static void list_all_ccaches(void); +static int list_ccache(krb5_ccache); +static void show_all_ccaches(void); +static void do_ccache(void); +static int show_ccache(krb5_ccache); +static int check_ccache(krb5_ccache); +static void do_keytab(const char *); +static void printtime(krb5_timestamp); +static void one_addr(krb5_address *); +static void fillit(FILE *, unsigned int, int); + +#define DEFAULT 0 +#define CCACHE 1 +#define KEYTAB 2 + +static void +usage() +{ + fprintf(stderr, _("Usage: %s [-e] [-V] [[-c] [-l] [-A] [-d] [-f] [-s] " + "[-a [-n]]] [-k [-i] [-t] [-K]] [-C] [name]\n"), + progname); + fprintf(stderr, _("\t-c specifies credentials cache\n")); + fprintf(stderr, _("\t-k specifies keytab\n")); + fprintf(stderr, _("\t (Default is credentials cache)\n")); + fprintf(stderr, _("\t-i uses default client keytab if no name given\n")); + fprintf(stderr, _("\t-l lists credential caches in collection\n")); + fprintf(stderr, _("\t-A shows content of all credential caches\n")); + fprintf(stderr, _("\t-e shows the encryption type\n")); + fprintf(stderr, _("\t-V shows the Kerberos version and exits\n")); + fprintf(stderr, _("\toptions for credential caches:\n")); + fprintf(stderr, _("\t\t-d shows the submitted authorization data " + "types\n")); + fprintf(stderr, _("\t\t-f shows credentials flags\n")); + fprintf(stderr, _("\t\t-s sets exit status based on valid tgt " + "existence\n")); + fprintf(stderr, _("\t\t-a displays the address list\n")); + fprintf(stderr, _("\t\t\t-n do not reverse-resolve\n")); + fprintf(stderr, _("\toptions for keytabs:\n")); + fprintf(stderr, _("\t\t-t shows keytab entry timestamps\n")); + fprintf(stderr, _("\t\t-K shows keytab entry keys\n")); + fprintf(stderr, _("\t\t-C includes configuration data entries\n")); + exit(1); +} + +static void +extended_com_err_fn(const char *prog, errcode_t code, const char *fmt, + va_list args) +{ + const char *msg; + + msg = krb5_get_error_message(context, code); + fprintf(stderr, "%s: %s%s", prog, msg, (*fmt == '\0') ? "" : " "); + krb5_free_error_message(context, msg); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); +} + +int +main(int argc, char *argv[]) +{ + krb5_error_code ret; + char *name, tmp[BUFSIZ]; + int c, mode; + + setlocale(LC_ALL, ""); + progname = GET_PROGNAME(argv[0]); + set_com_err_hook(extended_com_err_fn); + + name = NULL; + mode = DEFAULT; + /* V = version so v can be used for verbose later if desired. */ + while ((c = getopt(argc, argv, "dfetKsnacki45lAVC")) != -1) { + switch (c) { + case 'd': + show_adtype = 1; + break; + case 'f': + show_flags = 1; + break; + case 'e': + show_etype = 1; + break; + case 't': + show_time = 1; + break; + case 'K': + show_keys = 1; + break; + case 's': + status_only = 1; + break; + case 'n': + no_resolve = 1; + break; + case 'a': + show_addresses = 1; + break; + case 'c': + if (mode != DEFAULT) + usage(); + mode = CCACHE; + break; + case 'k': + if (mode != DEFAULT) + usage(); + mode = KEYTAB; + break; + case 'i': + use_client_keytab = 1; + break; + case '4': + fprintf(stderr, _("Kerberos 4 is no longer supported\n")); + exit(3); + break; + case '5': + break; + case 'l': + list_all = 1; + break; + case 'A': + show_all = 1; + break; + case 'C': + show_config = 1; + break; + case 'V': + print_version = 1; + break; + default: + usage(); + break; + } + } + + if (no_resolve && !show_addresses) + usage(); + + if (mode == DEFAULT || mode == CCACHE) { + if (show_time || show_keys) + usage(); + if ((show_all && list_all) || (status_only && list_all)) + usage(); + } else { + if (show_flags || status_only || show_addresses || + show_all || list_all) + usage(); + } + + if (argc - optind > 1) { + fprintf(stderr, _("Extra arguments (starting with \"%s\").\n"), + argv[optind + 1]); + usage(); + } + + if (print_version) { +#ifdef _WIN32 /* No access to autoconf vars; fix somehow. */ + printf("Kerberos for Windows\n"); +#else + printf(_("%s version %s\n"), PACKAGE_NAME, PACKAGE_VERSION); +#endif + exit(0); + } + + name = (optind == argc - 1) ? argv[optind] : NULL; + now = time(0); + + if (!krb5_timestamp_to_sfstring(now, tmp, 20, NULL) || + !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp), NULL)) + timestamp_width = (int)strlen(tmp); + else + timestamp_width = 15; + + ret = krb5_init_context(&context); + if (ret) { + com_err(progname, ret, _("while initializing krb5")); + exit(1); + } + + if (name != NULL && mode != KEYTAB) { + ret = krb5_cc_set_default_name(context, name); + if (ret) { + com_err(progname, ret, _("while setting default cache name")); + exit(1); + } + } + + if (list_all) + list_all_ccaches(); + else if (show_all) + show_all_ccaches(); + else if (mode == DEFAULT || mode == CCACHE) + do_ccache(); + else + do_keytab(name); + return 0; +} + +static void +do_keytab(const char *name) +{ + krb5_error_code ret; + krb5_keytab kt; + krb5_keytab_entry entry; + krb5_kt_cursor cursor; + unsigned int i; + char buf[BUFSIZ]; /* Hopefully large enough for any type */ + char *pname; + + if (name == NULL && use_client_keytab) { + ret = krb5_kt_client_default(context, &kt); + if (ret) { + com_err(progname, ret, _("while getting default client keytab")); + exit(1); + } + } else if (name == NULL) { + ret = krb5_kt_default(context, &kt); + if (ret) { + com_err(progname, ret, _("while getting default keytab")); + exit(1); + } + } else { + ret = krb5_kt_resolve(context, name, &kt); + if (ret) { + com_err(progname, ret, _("while resolving keytab %s"), name); + exit(1); + } + } + + ret = krb5_kt_get_name(context, kt, buf, BUFSIZ); + if (ret) { + com_err(progname, ret, _("while getting keytab name")); + exit(1); + } + + printf("Keytab name: %s\n", buf); + + ret = krb5_kt_start_seq_get(context, kt, &cursor); + if (ret) { + com_err(progname, ret, _("while starting keytab scan")); + exit(1); + } + + /* XXX Translating would disturb table alignment; skip for now. */ + if (show_time) { + printf("KVNO Timestamp"); + fillit(stdout, timestamp_width - sizeof("Timestamp") + 2, (int) ' '); + printf("Principal\n"); + printf("---- "); + fillit(stdout, timestamp_width, (int) '-'); + printf(" "); + fillit(stdout, 78 - timestamp_width - sizeof("KVNO"), (int) '-'); + printf("\n"); + } else { + printf("KVNO Principal\n"); + printf("---- ------------------------------------------------" + "--------------------------\n"); + } + + while ((ret = krb5_kt_next_entry(context, kt, &entry, &cursor)) == 0) { + ret = krb5_unparse_name(context, entry.principal, &pname); + if (ret) { + com_err(progname, ret, _("while unparsing principal name")); + exit(1); + } + printf("%4d ", entry.vno); + if (show_time) { + printtime(entry.timestamp); + printf(" "); + } + printf("%s", pname); + if (show_etype) + printf(" (%s) " , etype_string(entry.key.enctype)); + if (show_keys) { + printf(" (0x"); + for (i = 0; i < entry.key.length; i++) + printf("%02x", entry.key.contents[i]); + printf(")"); + } + printf("\n"); + krb5_free_unparsed_name(context, pname); + krb5_free_keytab_entry_contents(context, &entry); + } + if (ret && ret != KRB5_KT_END) { + com_err(progname, ret, _("while scanning keytab")); + exit(1); + } + ret = krb5_kt_end_seq_get(context, kt, &cursor); + if (ret) { + com_err(progname, ret, _("while ending keytab scan")); + exit(1); + } + exit(0); +} + +static void +list_all_ccaches() +{ + krb5_error_code ret; + krb5_ccache cache; + krb5_cccol_cursor cursor; + int exit_status; + + ret = krb5_cccol_cursor_new(context, &cursor); + if (ret) { + if (!status_only) + com_err(progname, ret, _("while listing ccache collection")); + exit(1); + } + + /* XXX Translating would disturb table alignment; skip for now. */ + printf("%-30s %s\n", "Principal name", "Cache name"); + printf("%-30s %s\n", "--------------", "----------"); + exit_status = 1; + while ((ret = krb5_cccol_cursor_next(context, cursor, &cache)) == 0 && + cache != NULL) { + exit_status = list_ccache(cache) && exit_status; + krb5_cc_close(context, cache); + } + krb5_cccol_cursor_free(context, &cursor); + exit(exit_status); +} + +static int +list_ccache(krb5_ccache cache) +{ + krb5_error_code ret; + krb5_principal princ = NULL; + char *princname = NULL, *ccname = NULL; + int expired, status = 1; + + ret = krb5_cc_get_principal(context, cache, &princ); + if (ret) /* Uninitialized cache file, probably. */ + goto cleanup; + ret = krb5_unparse_name(context, princ, &princname); + if (ret) + goto cleanup; + ret = krb5_cc_get_full_name(context, cache, &ccname); + if (ret) + goto cleanup; + + expired = check_ccache(cache); + + printf("%-30.30s %s", princname, ccname); + if (expired) + printf(" %s", _("(Expired)")); + printf("\n"); + + status = 0; + +cleanup: + krb5_free_principal(context, princ); + krb5_free_unparsed_name(context, princname); + krb5_free_string(context, ccname); + return status; +} + +static void +show_all_ccaches(void) +{ + krb5_error_code ret; + krb5_ccache cache; + krb5_cccol_cursor cursor; + krb5_boolean first; + int exit_status, st; + + ret = krb5_cccol_cursor_new(context, &cursor); + if (ret) { + if (!status_only) + com_err(progname, ret, _("while listing ccache collection")); + exit(1); + } + exit_status = 1; + first = TRUE; + while ((ret = krb5_cccol_cursor_next(context, cursor, &cache)) == 0 && + cache != NULL) { + if (!status_only && !first) + printf("\n"); + first = FALSE; + st = status_only ? check_ccache(cache) : show_ccache(cache); + exit_status = st && exit_status; + krb5_cc_close(context, cache); + } + krb5_cccol_cursor_free(context, &cursor); + exit(exit_status); +} + +static void +do_ccache() +{ + krb5_error_code ret; + krb5_ccache cache; + + ret = krb5_cc_default(context, &cache); + if (ret) { + if (!status_only) + com_err(progname, ret, _("while resolving ccache")); + exit(1); + } + exit(status_only ? check_ccache(cache) : show_ccache(cache)); +} + +/* Display the contents of cache. */ +static int +show_ccache(krb5_ccache cache) +{ + krb5_cc_cursor cur; + krb5_creds creds; + krb5_principal princ; + krb5_error_code ret; + + ret = krb5_cc_get_principal(context, cache, &princ); + if (ret) { + com_err(progname, ret, ""); + return 1; + } + ret = krb5_unparse_name(context, princ, &defname); + if (ret) { + com_err(progname, ret, _("while unparsing principal name")); + return 1; + } + + printf(_("Ticket cache: %s:%s\nDefault principal: %s\n\n"), + krb5_cc_get_type(context, cache), krb5_cc_get_name(context, cache), + defname); + /* XXX Translating would disturb table alignment; skip for now. */ + fputs("Valid starting", stdout); + fillit(stdout, timestamp_width - sizeof("Valid starting") + 3, (int) ' '); + fputs("Expires", stdout); + fillit(stdout, timestamp_width - sizeof("Expires") + 3, (int) ' '); + fputs("Service principal\n", stdout); + + ret = krb5_cc_start_seq_get(context, cache, &cur); + if (ret) { + com_err(progname, ret, _("while starting to retrieve tickets")); + return 1; + } + while ((ret = krb5_cc_next_cred(context, cache, &cur, &creds)) == 0) { + if (show_config || !krb5_is_config_principal(context, creds.server)) + show_credential(&creds); + krb5_free_cred_contents(context, &creds); + } + krb5_free_principal(context, princ); + krb5_free_unparsed_name(context, defname); + defname = NULL; + if (ret == KRB5_CC_END) { + ret = krb5_cc_end_seq_get(context, cache, &cur); + if (ret) { + com_err(progname, ret, _("while finishing ticket retrieval")); + return 1; + } + return 0; + } else { + com_err(progname, ret, _("while retrieving a ticket")); + return 1; + } +} + +/* Return 0 if cache is accessible, present, and unexpired; return 1 if not. */ +static int +check_ccache(krb5_ccache cache) +{ + krb5_error_code ret; + krb5_cc_cursor cur; + krb5_creds creds; + krb5_principal princ; + krb5_boolean found_tgt, found_current_tgt, found_current_cred; + + if (krb5_cc_get_principal(context, cache, &princ) != 0) + return 1; + if (krb5_cc_start_seq_get(context, cache, &cur) != 0) + return 1; + found_tgt = found_current_tgt = found_current_cred = FALSE; + while ((ret = krb5_cc_next_cred(context, cache, &cur, &creds)) == 0) { + if (is_local_tgt(creds.server, &princ->realm)) { + found_tgt = TRUE; + if (ts_after(creds.times.endtime, now)) + found_current_tgt = TRUE; + } else if (!krb5_is_config_principal(context, creds.server) && + ts_after(creds.times.endtime, now)) { + found_current_cred = TRUE; + } + krb5_free_cred_contents(context, &creds); + } + krb5_free_principal(context, princ); + if (ret != KRB5_CC_END) + return 1; + if (krb5_cc_end_seq_get(context, cache, &cur) != 0) + return 1; + + /* If the cache contains at least one local TGT, require that it be + * current. Otherwise accept any current cred. */ + if (found_tgt) + return found_current_tgt ? 0 : 1; + return found_current_cred ? 0 : 1; +} + +/* Return true if princ is the local krbtgt principal for local_realm. */ +static krb5_boolean +is_local_tgt(krb5_principal princ, krb5_data *realm) +{ + return princ->length == 2 && data_eq(princ->realm, *realm) && + data_eq_string(princ->data[0], KRB5_TGS_NAME) && + data_eq(princ->data[1], *realm); +} + +static char * +etype_string(krb5_enctype enctype) +{ + static char buf[100]; + char *bp = buf; + size_t deplen, buflen = sizeof(buf); + + if (krb5int_c_deprecated_enctype(enctype)) { + deplen = strlcpy(bp, "DEPRECATED:", buflen); + buflen -= deplen; + bp += deplen; + } + + if (krb5_enctype_to_name(enctype, FALSE, bp, buflen)) + snprintf(bp, buflen, "etype %d", enctype); + return buf; +} + +static char * +flags_string(krb5_creds *cred) +{ + static char buf[32]; + int i = 0; + + if (cred->ticket_flags & TKT_FLG_FORWARDABLE) + buf[i++] = 'F'; + if (cred->ticket_flags & TKT_FLG_FORWARDED) + buf[i++] = 'f'; + if (cred->ticket_flags & TKT_FLG_PROXIABLE) + buf[i++] = 'P'; + if (cred->ticket_flags & TKT_FLG_PROXY) + buf[i++] = 'p'; + if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE) + buf[i++] = 'D'; + if (cred->ticket_flags & TKT_FLG_POSTDATED) + buf[i++] = 'd'; + if (cred->ticket_flags & TKT_FLG_INVALID) + buf[i++] = 'i'; + if (cred->ticket_flags & TKT_FLG_RENEWABLE) + buf[i++] = 'R'; + if (cred->ticket_flags & TKT_FLG_INITIAL) + buf[i++] = 'I'; + if (cred->ticket_flags & TKT_FLG_HW_AUTH) + buf[i++] = 'H'; + if (cred->ticket_flags & TKT_FLG_PRE_AUTH) + buf[i++] = 'A'; + if (cred->ticket_flags & TKT_FLG_TRANSIT_POLICY_CHECKED) + buf[i++] = 'T'; + if (cred->ticket_flags & TKT_FLG_OK_AS_DELEGATE) + buf[i++] = 'O'; /* D/d are taken. Use short strings? */ + if (cred->ticket_flags & TKT_FLG_ANONYMOUS) + buf[i++] = 'a'; + buf[i] = '\0'; + return buf; +} + +static void +printtime(krb5_timestamp ts) +{ + char timestring[BUFSIZ], fill = ' '; + + if (!krb5_timestamp_to_sfstring(ts, timestring, timestamp_width + 1, + &fill)) + printf("%s", timestring); +} + +static void +print_config_data(int col, krb5_data *data) +{ + unsigned int i; + + for (i = 0; i < data->length; i++) { + while (col < 8) { + putchar(' '); + col++; + } + if (data->data[i] > 0x20 && data->data[i] < 0x7f) { + putchar(data->data[i]); + col++; + } else { + col += printf("\\%03o", (unsigned char)data->data[i]); + } + if (col > 72) { + putchar('\n'); + col = 0; + } + } + if (col > 0) + putchar('\n'); +} + +static void +show_credential(krb5_creds *cred) +{ + krb5_error_code ret; + krb5_ticket *tkt = NULL; + char *name = NULL, *sname = NULL, *tktsname, *flags; + int extra_field = 0, ccol = 0, i; + krb5_boolean is_config = krb5_is_config_principal(context, cred->server); + + ret = krb5_unparse_name(context, cred->client, &name); + if (ret) { + com_err(progname, ret, _("while unparsing client name")); + goto cleanup; + } + ret = krb5_unparse_name(context, cred->server, &sname); + if (ret) { + com_err(progname, ret, _("while unparsing server name")); + goto cleanup; + } + if (!is_config) + (void)krb5_decode_ticket(&cred->ticket, &tkt); + if (!cred->times.starttime) + cred->times.starttime = cred->times.authtime; + + if (!is_config) { + printtime(cred->times.starttime); + putchar(' '); + putchar(' '); + printtime(cred->times.endtime); + putchar(' '); + putchar(' '); + printf("%s\n", sname); + } else { + fputs("config: ", stdout); + ccol = 8; + for (i = 1; i < cred->server->length; i++) { + ccol += printf("%s%.*s%s", + i > 1 ? "(" : "", + (int)cred->server->data[i].length, + cred->server->data[i].data, + i > 1 ? ")" : ""); + } + fputs(" = ", stdout); + ccol += 3; + } + + if (strcmp(name, defname)) { + printf(_("\tfor client %s"), name); + extra_field++; + } + + if (is_config) + print_config_data(ccol, &cred->ticket); + + if (cred->times.renew_till) { + if (!extra_field) + fputs("\t",stdout); + else + fputs(", ",stdout); + fputs(_("renew until "), stdout); + printtime(cred->times.renew_till); + extra_field += 2; + } + + if (show_flags) { + flags = flags_string(cred); + if (flags && *flags) { + if (!extra_field) + fputs("\t",stdout); + else + fputs(", ",stdout); + printf(_("Flags: %s"), flags); + extra_field++; + } + } + + if (extra_field > 2) { + fputs("\n", stdout); + extra_field = 0; + } + + if (show_etype && tkt != NULL) { + if (!extra_field) + fputs("\t",stdout); + else + fputs(", ",stdout); + printf(_("Etype (skey, tkt): %s, "), + etype_string(cred->keyblock.enctype)); + printf("%s ", etype_string(tkt->enc_part.enctype)); + extra_field++; + } + + if (show_adtype) { + if (cred->authdata != NULL) { + if (!extra_field) + fputs("\t",stdout); + else + fputs(", ",stdout); + printf(_("AD types: ")); + for (i = 0; cred->authdata[i] != NULL; i++) { + if (i) + printf(", "); + printf("%d", cred->authdata[i]->ad_type); + } + extra_field++; + } + } + + /* If any additional info was printed, extra_field is non-zero. */ + if (extra_field) + putchar('\n'); + + if (show_addresses) { + if (cred->addresses == NULL || cred->addresses[0] == NULL) { + printf(_("\tAddresses: (none)\n")); + } else { + printf(_("\tAddresses: ")); + one_addr(cred->addresses[0]); + + for (i = 1; cred->addresses[i] != NULL; i++) { + printf(", "); + one_addr(cred->addresses[i]); + } + + printf("\n"); + } + } + + /* Display the ticket server if it is different from the server name the + * entry was cached under (most commonly for referrals). */ + if (tkt != NULL && + !krb5_principal_compare(context, cred->server, tkt->server)) { + ret = krb5_unparse_name(context, tkt->server, &tktsname); + if (ret) { + com_err(progname, ret, _("while unparsing ticket server name")); + goto cleanup; + } + printf(_("\tTicket server: %s\n"), tktsname); + krb5_free_unparsed_name(context, tktsname); + } + +cleanup: + krb5_free_unparsed_name(context, name); + krb5_free_unparsed_name(context, sname); + krb5_free_ticket(context, tkt); +} + +#include "port-sockets.h" +#include "socket-utils.h" /* For ss2sin etc. */ +#include "fake-addrinfo.h" + +static void +one_addr(krb5_address *a) +{ + struct sockaddr_storage ss; + struct sockaddr_in *sinp; + struct sockaddr_in6 *sin6p; + int err; + char namebuf[NI_MAXHOST]; + + memset(&ss, 0, sizeof(ss)); + + switch (a->addrtype) { + case ADDRTYPE_INET: + if (a->length != 4) { + printf(_("broken address (type %d length %d)"), + a->addrtype, a->length); + return; + } + sinp = ss2sin(&ss); + sinp->sin_family = AF_INET; + memcpy(&sinp->sin_addr, a->contents, 4); + break; + case ADDRTYPE_INET6: + if (a->length != 16) { + printf(_("broken address (type %d length %d)"), + a->addrtype, a->length); + return; + } + sin6p = ss2sin6(&ss); + sin6p->sin6_family = AF_INET6; + memcpy(&sin6p->sin6_addr, a->contents, 16); + break; + default: + printf(_("unknown addrtype %d"), a->addrtype); + return; + } + + namebuf[0] = 0; + err = getnameinfo(ss2sa(&ss), sa_socklen(ss2sa(&ss)), namebuf, + sizeof(namebuf), 0, 0, + no_resolve ? NI_NUMERICHOST : 0U); + if (err) { + printf(_("unprintable address (type %d, error %d %s)"), a->addrtype, + err, gai_strerror(err)); + return; + } + printf("%s", namebuf); +} + +static void +fillit(FILE *f, unsigned int num, int c) +{ + unsigned int i; + + for (i = 0; i < num; i++) + fputc(c, f); +} diff --git a/krb5-1.21.3/src/clients/kpasswd/Makefile.in b/krb5-1.21.3/src/clients/kpasswd/Makefile.in new file mode 100644 index 00000000..9c0bbeb1 --- /dev/null +++ b/krb5-1.21.3/src/clients/kpasswd/Makefile.in @@ -0,0 +1,33 @@ +mydir=clients$(S)kpasswd +BUILDTOP=$(REL)..$(S).. + +SRCS=kpasswd.c + +kpasswd: kpasswd.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o kpasswd kpasswd.o $(KRB5_BASE_LIBS) + +kpasswd.o: $(srcdir)/kpasswd.c + +##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc +##WIN32##RCFLAGS=$(CPPFLAGS) -I$(top_srcdir) -D_WIN32 -DRES_ONLY + +##WIN32##KPWD=$(OUTPRE)kpasswd.exe + +##WIN32##EXERES=$(KPWD:.exe=.res) + +##WIN32##$(EXERES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DKPASSWD_APP -fo $@ -r $** + +all-unix: kpasswd + +clean-unix:: + $(RM) kpasswd.o kpasswd + +install-all install-kdc install-server install-client install-unix: + $(INSTALL_PROGRAM) kpasswd $(DESTDIR)$(CLIENT_BINDIR)/`echo kpasswd|sed '$(transform)'` + +##WIN32##all-windows: $(KPWD) + +##WIN32##$(KPWD): $(OUTPRE)kpasswd.obj $(KLIB) $(CLIB) $(EXERES) +##WIN32## link $(EXE_LINKOPTS) -out:$@ $** +##WIN32## $(_VC_MANIFEST_EMBED_EXE) diff --git a/krb5-1.21.3/src/clients/kpasswd/deps b/krb5-1.21.3/src/clients/kpasswd/deps new file mode 100644 index 00000000..360b6d73 --- /dev/null +++ b/krb5-1.21.3/src/clients/kpasswd/deps @@ -0,0 +1,7 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kpasswd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ + kpasswd.c diff --git a/krb5-1.21.3/src/clients/kpasswd/kpasswd.c b/krb5-1.21.3/src/clients/kpasswd/kpasswd.c new file mode 100644 index 00000000..bf2a5bd4 --- /dev/null +++ b/krb5-1.21.3/src/clients/kpasswd/kpasswd.c @@ -0,0 +1,177 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ + +#include "k5-platform.h" +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include + +#define P1 _("Enter new password") +#define P2 _("Enter it again") + +#ifdef HAVE_PWD_H +#include + +static void +get_name_from_passwd_file(char *program_name, krb5_context context, + krb5_principal *me) +{ + struct passwd *pw; + krb5_error_code ret; + + pw = getpwuid(getuid()); + if (pw != NULL) { + ret = krb5_parse_name(context, pw->pw_name, me); + if (ret) { + com_err(program_name, ret, _("when parsing name %s"), pw->pw_name); + exit(1); + } + } else { + fprintf(stderr, _("Unable to identify user from password file\n")); + exit(1); + } +} +#else /* HAVE_PWD_H */ +static void +get_name_from_passwd_file(char *program_name, krb5_context context, + krb5_principal *me) +{ + fprintf(stderr, _("Unable to identify user\n")); + exit(1); +} +#endif /* HAVE_PWD_H */ + +int main(int argc, char *argv[]) +{ + krb5_error_code ret; + krb5_context context; + krb5_principal princ = NULL; + char *pname, *message; + char pw[1024]; + krb5_ccache ccache; + krb5_get_init_creds_opt *opts = NULL; + krb5_creds creds; + unsigned int pwlen; + int result_code; + krb5_data result_code_string, result_string; + + setlocale(LC_ALL, ""); + if (argc > 2) { + fprintf(stderr, _("usage: %s [principal]\n"), argv[0]); + exit(1); + } + + pname = argv[1]; + + ret = krb5_init_context(&context); + if (ret) { + com_err(argv[0], ret, _("initializing kerberos library")); + exit(1); + } + ret = krb5_get_init_creds_opt_alloc(context, &opts); + if (ret) { + com_err(argv[0], ret, _("allocating krb5_get_init_creds_opt")); + exit(1); + } + + /* + * In order, use the first of: + * - A name specified on the command line + * - The principal name from an existing ccache + * - The name corresponding to the ruid of the process + * + * Otherwise, it's an error. + * We always attempt to open the default ccache in order to use FAST if + * possible. + */ + ret = krb5_cc_default(context, &ccache); + if (ret) { + com_err(argv[0], ret, _("opening default ccache")); + exit(1); + } + ret = krb5_cc_get_principal(context, ccache, &princ); + if (ret && ret != KRB5_CC_NOTFOUND && ret != KRB5_FCC_NOFILE) { + com_err(argv[0], ret, _("getting principal from ccache")); + exit(1); + } else if (princ != NULL) { + ret = krb5_get_init_creds_opt_set_fast_ccache(context, opts, ccache); + if (ret) { + com_err(argv[0], ret, _("while setting FAST ccache")); + exit(1); + } + } + ret = krb5_cc_close(context, ccache); + if (ret) { + com_err(argv[0], ret, _("closing ccache")); + exit(1); + } + if (pname != NULL) { + krb5_free_principal(context, princ); + princ = NULL; + ret = krb5_parse_name(context, pname, &princ); + if (ret) { + com_err(argv[0], ret, _("parsing client name")); + exit(1); + } + } + if (princ == NULL) + get_name_from_passwd_file(argv[0], context, &princ); + + krb5_get_init_creds_opt_set_tkt_life(opts, 5 * 60); + krb5_get_init_creds_opt_set_renew_life(opts, 0); + krb5_get_init_creds_opt_set_forwardable(opts, 0); + krb5_get_init_creds_opt_set_proxiable(opts, 0); + + ret = krb5_get_init_creds_password(context, &creds, princ, NULL, + krb5_prompter_posix, NULL, 0, + "kadmin/changepw", opts); + if (ret) { + if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + com_err(argv[0], 0, + _("Password incorrect while getting initial ticket")); + } else { + com_err(argv[0], ret, _("getting initial ticket")); + } + + krb5_get_init_creds_opt_free(context, opts); + exit(1); + } + + pwlen = sizeof(pw); + ret = krb5_read_password(context, P1, P2, pw, &pwlen); + if (ret) { + com_err(argv[0], ret, _("while reading password")); + krb5_get_init_creds_opt_free(context, opts); + exit(1); + } + + ret = krb5_change_password(context, &creds, pw, &result_code, + &result_code_string, &result_string); + if (ret) { + com_err(argv[0], ret, _("changing password")); + krb5_get_init_creds_opt_free(context, opts); + exit(1); + } + + if (result_code) { + if (krb5_chpw_message(context, &result_string, &message) != 0) + message = NULL; + printf("%.*s%s%s\n", + (int)result_code_string.length, result_code_string.data, + message ? ": " : "", message ? message : NULL); + krb5_free_string(context, message); + krb5_get_init_creds_opt_free(context, opts); + exit(2); + } + + free(result_string.data); + free(result_code_string.data); + krb5_get_init_creds_opt_free(context, opts); + + printf(_("Password changed.\n")); + exit(0); +} diff --git a/krb5-1.21.3/src/clients/ksu/Makefile.in b/krb5-1.21.3/src/clients/ksu/Makefile.in new file mode 100644 index 00000000..8b4edce4 --- /dev/null +++ b/krb5-1.21.3/src/clients/ksu/Makefile.in @@ -0,0 +1,35 @@ +mydir=clients$(S)ksu +BUILDTOP=$(REL)..$(S).. +DEFINES = -DGET_TGT_VIA_PASSWD -DPRINC_LOOK_AHEAD -DCMD_PATH='"/usr/local/sbin /usr/local/bin /sbin /bin /usr/sbin /usr/bin"' + +KSU_LIBS=@KSU_LIBS@ + +SRCS = \ + $(srcdir)/krb_auth_su.c \ + $(srcdir)/ccache.c \ + $(srcdir)/authorization.c \ + $(srcdir)/main.c \ + $(srcdir)/heuristic.c \ + $(srcdir)/xmalloc.c \ + $(srcdir)/setenv.c +OBJS = \ + krb_auth_su.o \ + ccache.o \ + authorization.o \ + main.o \ + heuristic.o \ + xmalloc.o @SETENVOBJ@ + +all: ksu + +ksu: $(OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ $(OBJS) $(KRB5_BASE_LIBS) $(KSU_LIBS) + +clean: + $(RM) ksu + +install: + -for f in ksu; do \ + $(INSTALL_SETUID) $$f \ + $(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \ + done diff --git a/krb5-1.21.3/src/clients/ksu/authorization.c b/krb5-1.21.3/src/clients/ksu/authorization.c new file mode 100644 index 00000000..fb9d5d09 --- /dev/null +++ b/krb5-1.21.3/src/clients/ksu/authorization.c @@ -0,0 +1,710 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (c) 1994 by the University of Southern California + * + * EXPORT OF THIS SOFTWARE from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute + * this software and its documentation in source and binary forms is + * hereby granted, provided that any documentation or other materials + * related to such distribution or use acknowledge that the software + * was developed by the University of Southern California. + * + * DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The + * University of Southern California MAKES NO REPRESENTATIONS OR + * WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, the University of Southern California MAKES NO + * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY + * PARTICULAR PURPOSE. The University of Southern + * California shall not be held liable for any liability nor for any + * direct, indirect, or consequential damages with respect to any + * claim by the user or distributor of the ksu software. + * + * KSU was written by: Ari Medvinsky, ari@isi.edu + */ + +#include "ksu.h" + +static void auth_cleanup (FILE *, FILE *, char *); + +krb5_boolean fowner(fp, uid) + FILE *fp; + uid_t uid; +{ + struct stat sbuf; + + /* + * For security reasons, file must be owned either by + * the user himself, or by root. Otherwise, don't grant access. + */ + if (fstat(fileno(fp), &sbuf)) { + return(FALSE); + } + + if ((sbuf.st_uid != uid) && sbuf.st_uid) { + return(FALSE); + } + + return(TRUE); +} + +/* + * Given a Kerberos principal "principal", and a local username "luser", + * determine whether user is authorized to login according to the + * authorization files ~luser/.k5login" and ~luser/.k5users. Returns TRUE + * if authorized, FALSE if not authorized. + * + */ + +krb5_error_code krb5_authorization(context, principal, luser, + cmd, ok, out_fcmd) +/* IN */ + krb5_context context; + krb5_principal principal; + const char *luser; + char *cmd; + /* OUT */ + krb5_boolean *ok; + char **out_fcmd; +{ + struct passwd *pwd; + char *princname; + int k5login_flag =0; + int k5users_flag =0; + krb5_boolean retbool =FALSE; + FILE * login_fp = 0, * users_fp = 0; + krb5_error_code retval = 0; + struct stat st_temp; + + *ok =FALSE; + + /* no account => no access */ + if ((pwd = getpwnam(luser)) == NULL) + return 0; + + retval = krb5_unparse_name(context, principal, &princname); + if (retval) + return retval; + +#ifdef DEBUG + printf("principal to be authorized %s\n", princname); + printf("login file: %s\n", k5login_path); + printf("users file: %s\n", k5users_path); +#endif + + k5login_flag = stat(k5login_path, &st_temp); + k5users_flag = stat(k5users_path, &st_temp); + + /* k5login and k5users must be owned by target user or root */ + if (!k5login_flag){ + if ((login_fp = fopen(k5login_path, "r")) == NULL) + return 0; + if ( fowner(login_fp, pwd->pw_uid) == FALSE) { + fclose(login_fp); + return 0; + } + } + + if (!k5users_flag){ + if ((users_fp = fopen(k5users_path, "r")) == NULL) { + return 0; + } + if ( fowner(users_fp, pwd->pw_uid) == FALSE){ + fclose(users_fp); + return 0; + } + } + + if (auth_debug){ + fprintf(stderr, + "In krb5_authorization: if auth files exist -> can access\n"); + } + + /* if either file exists, + first see if the principal is in the login in file, + if it's not there check the k5users file */ + + if (!k5login_flag){ + if (auth_debug) + fprintf(stderr, + "In krb5_authorization: principal to be authorized %s\n", + princname); + + retval = k5login_lookup(login_fp, princname, &retbool); + if (retval) { + auth_cleanup(users_fp, login_fp, princname); + return retval; + } + if (retbool) { + if (cmd) + *out_fcmd = xstrdup(cmd); + } + } + + if ((!k5users_flag) && (retbool == FALSE) ){ + retval = k5users_lookup (users_fp, princname, + cmd, &retbool, out_fcmd); + if(retval) { + auth_cleanup(users_fp, login_fp, princname); + return retval; + } + } + + if (k5login_flag && k5users_flag){ + + char * kuser = (char *) xcalloc (strlen(princname), sizeof(char)); + if (!(krb5_aname_to_localname(context, principal, + strlen(princname), kuser)) + && (strcmp(kuser, luser) == 0)) { + retbool = TRUE; + } + + free(kuser); + } + + *ok =retbool; + auth_cleanup(users_fp, login_fp, princname); + return 0; +} + +/*********************************************************** +k5login_lookup looks for princname in file fp. Spaces +before the princaname (in the file ) are not ignored +spaces after the princname are ignored. If there are +any tokens after the principal name FALSE is returned. + +***********************************************************/ + +krb5_error_code k5login_lookup (fp, princname, found) + FILE *fp; + char *princname; + krb5_boolean *found; +{ + + krb5_error_code retval; + char * line; + char * fprinc; + char * lp; + krb5_boolean loc_found = FALSE; + + retval = get_line(fp, &line); + if (retval) + return retval; + + while (line){ + fprinc = get_first_token (line, &lp); + + if (fprinc && (!strcmp(princname, fprinc))){ + if( get_next_token (&lp) ){ + free (line); + break; /* nothing should follow princname*/ + } + else{ + loc_found = TRUE; + free (line); + break; + } + } + + free (line); + + retval = get_line(fp, &line); + if (retval) + return retval; + } + + + *found = loc_found; + return 0; + +} + +/*********************************************************** +k5users_lookup looks for princname in file fp. Spaces +before the princaname (in the file ) are not ignored +spaces after the princname are ignored. + +authorization alg: + +if princname is not found return false. + +if princname is found{ + if cmd == NULL then the file entry after principal + name must be nothing or * + + if cmd !=NULL then entry must be matched (* is ok) +} + + +***********************************************************/ +krb5_error_code k5users_lookup (fp, princname, cmd, found, out_fcmd) + FILE *fp; + char *princname; + char *cmd; + krb5_boolean *found; + char **out_fcmd; +{ + krb5_error_code retval; + char * line; + char * fprinc, *fcmd; + char * lp; + char * loc_fcmd = NULL; + krb5_boolean loc_found = FALSE; + + retval = get_line(fp, &line); + if (retval) + return retval; + + while (line){ + fprinc = get_first_token (line, &lp); + + if (fprinc && (!strcmp(princname, fprinc))){ + fcmd = get_next_token (&lp); + + if ((fcmd) && (!strcmp(fcmd, PERMIT_ALL_COMMANDS))){ + if (get_next_token(&lp) == NULL){ + loc_fcmd =cmd ? xstrdup(cmd): NULL; + loc_found = TRUE; + } + free (line); + break; + } + + if (cmd == NULL){ + if (fcmd == NULL) + loc_found = TRUE; + free (line); + break; + + }else{ + if (fcmd != NULL) { + char * temp_rfcmd, *err; + krb5_boolean match; + do { + if(match_commands(fcmd,cmd,&match, + &temp_rfcmd, &err)){ + if (auth_debug){ + fprintf(stderr,"%s",err); + } + loc_fcmd = err; + break; + }else{ + if (match == TRUE){ + loc_fcmd = temp_rfcmd; + loc_found = TRUE; + break; + } + } + + }while ((fcmd = get_next_token( &lp))); + } + free (line); + break; + } + } + + free (line); + + retval = get_line(fp, &line); + if (retval) { + return retval; + } + } + + *out_fcmd = loc_fcmd; + *found = loc_found; + return 0; + +} + + +/*********************************************** +fcmd_resolve - +takes a command specified .k5users file and +resolves it into a full path name. + +************************************************/ + +krb5_boolean fcmd_resolve(fcmd, out_fcmd, out_err) + char *fcmd; + char ***out_fcmd; + char **out_err; +{ + char * err; + char ** tmp_fcmd; + char * path_ptr, *path; + char * lp, * tc; + int i=0; + + tmp_fcmd = (char **) xcalloc (MAX_CMD, sizeof(char *)); + + if (*fcmd == '/'){ /* must be full path */ + tmp_fcmd[0] = xstrdup(fcmd); + tmp_fcmd[1] = NULL; + *out_fcmd = tmp_fcmd; + return TRUE; + }else{ + /* must be either full path or just the cmd name */ + if (strchr(fcmd, '/')){ + asprintf(&err, _("Error: bad entry - %s in %s file, must be " + "either full path or just the cmd name\n"), + fcmd, KRB5_USERS_NAME); + *out_err = err; + return FALSE; + } + +#ifndef CMD_PATH + asprintf(&err, _("Error: bad entry - %s in %s file, since %s is just " + "the cmd name, CMD_PATH must be defined \n"), + fcmd, KRB5_USERS_NAME, fcmd); + *out_err = err; + return FALSE; +#else + + path = xstrdup (CMD_PATH); + path_ptr = path; + + while ((*path_ptr == ' ') || (*path_ptr == '\t')) path_ptr ++; + + tc = get_first_token (path_ptr, &lp); + + if (! tc){ + asprintf(&err, _("Error: bad entry - %s in %s file, CMD_PATH " + "contains no paths \n"), fcmd, KRB5_USERS_NAME); + *out_err = err; + return FALSE; + } + + i=0; + do{ + if (*tc != '/'){ /* must be full path */ + asprintf(&err, _("Error: bad path %s in CMD_PATH for %s must " + "start with '/' \n"), tc, KRB5_USERS_NAME ); + *out_err = err; + return FALSE; + } + + tmp_fcmd[i] = xasprintf("%s/%s", tc, fcmd); + + i++; + + } while((tc = get_next_token (&lp))); + + tmp_fcmd[i] = NULL; + *out_fcmd = tmp_fcmd; + return TRUE; + +#endif /* CMD_PATH */ + } +} + +/******************************************** +cmd_single - checks if cmd consists of a path + or a single token + +********************************************/ + +krb5_boolean cmd_single(cmd) + char * cmd; +{ + + if ( ( strrchr( cmd, '/')) == NULL){ + return TRUE; + }else{ + return FALSE; + } +} + +/******************************************** +cmd_arr_cmp_postfix - compares a command with the postfix + of fcmd +********************************************/ + +int cmd_arr_cmp_postfix(fcmd_arr, cmd) + char **fcmd_arr; + char *cmd; +{ + char * temp_fcmd; + char *ptr; + int result =1; + int i = 0; + + while(fcmd_arr[i]){ + if ( (ptr = strrchr( fcmd_arr[i], '/')) == NULL){ + temp_fcmd = fcmd_arr[i]; + }else { + temp_fcmd = ptr + 1; + } + + result = strcmp (temp_fcmd, cmd); + if (result == 0){ + break; + } + i++; + } + + return result; + + +} + +/********************************************** +cmd_arr_cmp - checks if cmd matches any + of the fcmd entries. + +**********************************************/ + +int cmd_arr_cmp (fcmd_arr, cmd) + char **fcmd_arr; + char *cmd; +{ + int result =1; + int i = 0; + + while(fcmd_arr[i]){ + result = strcmp (fcmd_arr[i], cmd); + if (result == 0){ + break; + } + i++; + } + return result; +} + + +krb5_boolean find_first_cmd_that_exists(fcmd_arr, cmd_out, err_out) + char **fcmd_arr; + char **cmd_out; + char **err_out; +{ + struct stat st_temp; + int i = 0; + krb5_boolean retbool= FALSE; + int j =0; + struct k5buf buf; + + while(fcmd_arr[i]){ + if (!stat (fcmd_arr[i], &st_temp )){ + *cmd_out = xstrdup(fcmd_arr[i]); + retbool = TRUE; + break; + } + i++; + } + + if (retbool == FALSE ){ + k5_buf_init_dynamic(&buf); + k5_buf_add(&buf, _("Error: not found -> ")); + for(j= 0; j < i; j ++) + k5_buf_add_fmt(&buf, " %s ", fcmd_arr[j]); + k5_buf_add(&buf, "\n"); + *err_out = k5_buf_cstring(&buf); + if (*err_out == NULL) { + perror(prog_name); + exit(1); + } + } + + + return retbool; +} + +/*************************************************************** +returns 1 if there is an error, 0 if no error. + +***************************************************************/ + +int match_commands (fcmd, cmd, match, cmd_out, err_out) + char *fcmd; + char *cmd; + krb5_boolean *match; + char **cmd_out; + char **err_out; +{ + char ** fcmd_arr; + char * err; + char * cmd_temp; + + if(fcmd_resolve(fcmd, &fcmd_arr, &err )== FALSE ){ + *err_out = err; + return 1; + } + + if (cmd_single( cmd ) == TRUE){ + if (!cmd_arr_cmp_postfix(fcmd_arr, cmd)){ /* found */ + + if(find_first_cmd_that_exists( fcmd_arr,&cmd_temp,&err)== TRUE){ + *match = TRUE; + *cmd_out = cmd_temp; + return 0; + }else{ + *err_out = err; + return 1; + } + }else{ + *match = FALSE; + return 0; + } + }else{ + if (!cmd_arr_cmp(fcmd_arr, cmd)){ /* found */ + *match = TRUE; + *cmd_out = xstrdup(cmd); + return 0; + } else{ + *match = FALSE; + return 0; + } + } + +} + +/********************************************************* + get_line - returns a line of any length. out_line + is set to null if eof. +*********************************************************/ + +krb5_error_code get_line (fp, out_line) +/* IN */ + FILE *fp; + /* OUT */ + char **out_line; +{ + char * line, *r, *newline , *line_ptr; + int chunk_count = 1; + + line = (char *) xcalloc (BUFSIZ, sizeof (char )); + line_ptr = line; + line[0] = '\0'; + + while (( r = fgets(line_ptr, BUFSIZ , fp)) != NULL){ + newline = strchr(line_ptr, '\n'); + if (newline) { + *newline = '\0'; + break; + } + else { + chunk_count ++; + if(!( line = (char *) realloc( line, + chunk_count * sizeof(char) * BUFSIZ))){ + return ENOMEM; + } + + line_ptr = line + (BUFSIZ -1) *( chunk_count -1) ; + } + } + + if ((r == NULL) && (strlen(line) == 0)) { + *out_line = NULL; + } + else{ + *out_line = line; + } + + return 0; +} + +/******************************************************* +get_first_token - +Expects a '\0' terminated input line . +If there are any spaces before the first token, they +will be returned as part of the first token. + +Note: this routine reuses the space pointed to by line +******************************************************/ + +char * get_first_token (line, lnext) + char *line; + char **lnext; +{ + + char * lptr, * out_ptr; + + + out_ptr = line; + lptr = line; + + while (( *lptr == ' ') || (*lptr == '\t')) lptr ++; + + if (strlen(lptr) == 0) return NULL; + + while (( *lptr != ' ') && (*lptr != '\t') && (*lptr != '\0')) lptr ++; + + if (*lptr == '\0'){ + *lnext = lptr; + } else{ + *lptr = '\0'; + *lnext = lptr + 1; + } + + return out_ptr; +} +/********************************************************** +get_next_token - +returns the next token pointed to by *lnext. +returns NULL if there is no more tokens. +Note: that this function modifies the stream + pointed to by *lnext and does not allocate + space for the returned tocken. It also advances + lnext to the next tocken. +**********************************************************/ + +char * get_next_token (lnext) + char **lnext; +{ + char * lptr, * out_ptr; + + + lptr = *lnext; + + while (( *lptr == ' ') || (*lptr == '\t')) lptr ++; + + if (strlen(lptr) == 0) return NULL; + + out_ptr = lptr; + + while (( *lptr != ' ') && (*lptr != '\t') && (*lptr != '\0')) lptr ++; + + if (*lptr == '\0'){ + *lnext = lptr; + } else{ + *lptr = '\0'; + *lnext = lptr + 1; + } + + return out_ptr; +} + +static void auth_cleanup(users_fp, login_fp, princname) + FILE *users_fp; + FILE *login_fp; + char *princname; +{ + + free (princname); + if (users_fp) + fclose(users_fp); + if (login_fp) + fclose(login_fp); +} + +void init_auth_names(pw_dir) + char *pw_dir; +{ + const char *sep; + int r1, r2; + + sep = ((strlen(pw_dir) == 1) && (*pw_dir == '/')) ? "" : "/"; + r1 = snprintf(k5login_path, sizeof(k5login_path), "%s%s%s", + pw_dir, sep, KRB5_LOGIN_NAME); + r2 = snprintf(k5users_path, sizeof(k5users_path), "%s%s%s", + pw_dir, sep, KRB5_USERS_NAME); + if (SNPRINTF_OVERFLOW(r1, sizeof(k5login_path)) || + SNPRINTF_OVERFLOW(r2, sizeof(k5users_path))) { + fprintf(stderr, _("home directory name `%s' too long, can't search " + "for .k5login\n"), pw_dir); + exit (1); + } +} diff --git a/krb5-1.21.3/src/clients/ksu/ccache.c b/krb5-1.21.3/src/clients/ksu/ccache.c new file mode 100644 index 00000000..cbb9aa2b --- /dev/null +++ b/krb5-1.21.3/src/clients/ksu/ccache.c @@ -0,0 +1,732 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (c) 1994 by the University of Southern California + * + * EXPORT OF THIS SOFTWARE from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute + * this software and its documentation in source and binary forms is + * hereby granted, provided that any documentation or other materials + * related to such distribution or use acknowledge that the software + * was developed by the University of Southern California. + * + * DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The + * University of Southern California MAKES NO REPRESENTATIONS OR + * WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, the University of Southern California MAKES NO + * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY + * PARTICULAR PURPOSE. The University of Southern + * California shall not be held liable for any liability nor for any + * direct, indirect, or consequential damages with respect to any + * claim by the user or distributor of the ksu software. + * + * KSU was written by: Ari Medvinsky, ari@isi.edu + */ + +#include "ksu.h" +#include "k5-base64.h" +#include "adm_proto.h" +#include +#include + +/****************************************************************** +krb5_cache_copy + +gets rid of any expired tickets in the secondary cache, +copies the default cache into the secondary cache, + +************************************************************************/ + +void show_credential(); + +/* modifies only the cc_other, the algorithm may look a bit funny, + but I had to do it this way, since remove function did not come + with k5 beta 3 release. +*/ + +krb5_error_code krb5_ccache_copy(context, cc_def, target_principal, cc_target, + restrict_creds, primary_principal, stored) +/* IN */ + krb5_context context; + krb5_ccache cc_def; + krb5_principal target_principal; + krb5_ccache cc_target; + krb5_boolean restrict_creds; + krb5_principal primary_principal; + /* OUT */ + krb5_boolean *stored; +{ + int i=0; + krb5_error_code retval=0; + krb5_creds ** cc_def_creds_arr = NULL; + krb5_creds ** cc_other_creds_arr = NULL; + + if (ks_ccache_is_initialized(context, cc_def)) { + if((retval = krb5_get_nonexp_tkts(context,cc_def,&cc_def_creds_arr))){ + return retval; + } + } + + retval = krb5_cc_initialize(context, cc_target, target_principal); + if (retval) + return retval; + + if (restrict_creds) { + retval = krb5_store_some_creds(context, cc_target, cc_def_creds_arr, + cc_other_creds_arr, primary_principal, + stored); + } else { + *stored = krb5_find_princ_in_cred_list(context, cc_def_creds_arr, + primary_principal); + retval = krb5_store_all_creds(context, cc_target, cc_def_creds_arr, + cc_other_creds_arr); + } + + if (cc_def_creds_arr){ + while (cc_def_creds_arr[i]){ + krb5_free_creds(context, cc_def_creds_arr[i]); + i++; + } + } + + i=0; + + if(cc_other_creds_arr){ + while (cc_other_creds_arr[i]){ + krb5_free_creds(context, cc_other_creds_arr[i]); + i++; + } + } + + return retval; +} + + +krb5_error_code krb5_store_all_creds(context, cc, creds_def, creds_other) + krb5_context context; + krb5_ccache cc; + krb5_creds **creds_def; + krb5_creds **creds_other; +{ + + int i = 0; + krb5_error_code retval = 0; + krb5_creds ** temp_creds= NULL; + + + if ((creds_def == NULL) && (creds_other == NULL)) + return 0; + + if ((creds_def == NULL) && (creds_other != NULL)) + temp_creds = creds_other; + + if ((creds_def != NULL) && (creds_other == NULL)) + temp_creds = creds_def; + + + if (temp_creds){ + while(temp_creds[i]){ + if ((retval= krb5_cc_store_cred(context, cc, + temp_creds[i]))){ + return retval; + } + i++; + } + } + else { /* both arrays have elements in them */ + + return KRB5KRB_ERR_GENERIC; + +/************ while(creds_other[i]){ + cmp = FALSE; + j = 0; + while(creds_def[j]){ + cmp = compare_creds(creds_other[i],creds_def[j]); + + if( cmp == TRUE) break; + + j++; + } + if (cmp == FALSE){ + if (retval= krb5_cc_store_cred(context, cc, + creds_other[i])){ + return retval; + } + } + i ++; + } + + i=0; + while(creds_def[i]){ + if (retval= krb5_cc_store_cred(context, cc, + creds_def[i])){ + return retval; + } + i++; + } + +**************/ + } + return 0; +} + +krb5_boolean compare_creds(context, cred1, cred2) + krb5_context context; + krb5_creds *cred1; + krb5_creds *cred2; +{ + krb5_boolean retval; + + retval = krb5_principal_compare (context, cred1->client, cred2->client); + + if (retval == TRUE) + retval = krb5_principal_compare (context, cred1->server, cred2->server); + + return retval; +} + + + + +krb5_error_code krb5_get_nonexp_tkts(context, cc, creds_array) + krb5_context context; + krb5_ccache cc; + krb5_creds ***creds_array; +{ + + krb5_creds creds, temp_tktq, temp_tkt; + krb5_creds **temp_creds; + krb5_error_code retval=0; + krb5_cc_cursor cur; + int count = 0; + int chunk_count = 1; + + if ( ! ( temp_creds = (krb5_creds **) malloc( CHUNK * sizeof(krb5_creds *)))){ + return ENOMEM; + } + + + memset(&temp_tktq, 0, sizeof(temp_tktq)); + memset(&temp_tkt, 0, sizeof(temp_tkt)); + memset(&creds, 0, sizeof(creds)); + + /* initialize the cursor */ + if ((retval = krb5_cc_start_seq_get(context, cc, &cur))) { + return retval; + } + + while (!(retval = krb5_cc_next_cred(context, cc, &cur, &creds))){ + + if (!krb5_is_config_principal(context, creds.server) && + (retval = krb5_check_exp(context, creds.times))){ + if (retval != KRB5KRB_AP_ERR_TKT_EXPIRED){ + return retval; + } + if (auth_debug){ + fprintf(stderr,"krb5_ccache_copy: CREDS EXPIRED:\n"); + fputs(" Valid starting Expires Service principal\n",stdout); + show_credential(context, &creds, cc); + fprintf(stderr,"\n"); + } + } + else { /* these credentials didn't expire */ + + if ((retval = krb5_copy_creds(context, &creds, + &temp_creds[count]))){ + return retval; + } + count ++; + + if (count == (chunk_count * CHUNK -1)){ + chunk_count ++; + if (!(temp_creds = (krb5_creds **) realloc(temp_creds, + chunk_count * CHUNK * sizeof(krb5_creds *)))){ + return ENOMEM; + } + } + } + + } + + temp_creds[count] = NULL; + *creds_array = temp_creds; + + if (retval == KRB5_CC_END) { + retval = krb5_cc_end_seq_get(context, cc, &cur); + } + + return retval; + +} + + +krb5_error_code krb5_check_exp(context, tkt_time) + krb5_context context; + krb5_ticket_times tkt_time; +{ + krb5_error_code retval =0; + krb5_timestamp currenttime; + + if ((retval = krb5_timeofday (context, ¤ttime))){ + return retval; + } + if (auth_debug){ + fprintf(stderr,"krb5_check_exp: the krb5_clockskew is %d \n", + context->clockskew); + + fprintf(stderr,"krb5_check_exp: currenttime - endtime %d \n", + ts_delta(currenttime, tkt_time.endtime)); + + } + + if (ts_after(currenttime, ts_incr(tkt_time.endtime, context->clockskew))) { + retval = KRB5KRB_AP_ERR_TKT_EXPIRED ; + return retval; + } + + return 0; +} + + +char *flags_string(cred) + krb5_creds *cred; +{ + static char buf[32]; + int i = 0; + + if (cred->ticket_flags & TKT_FLG_FORWARDABLE) + buf[i++] = 'F'; + if (cred->ticket_flags & TKT_FLG_FORWARDED) + buf[i++] = 'f'; + if (cred->ticket_flags & TKT_FLG_PROXIABLE) + buf[i++] = 'P'; + if (cred->ticket_flags & TKT_FLG_PROXY) + buf[i++] = 'p'; + if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE) + buf[i++] = 'D'; + if (cred->ticket_flags & TKT_FLG_POSTDATED) + buf[i++] = 'd'; + if (cred->ticket_flags & TKT_FLG_INVALID) + buf[i++] = 'i'; + if (cred->ticket_flags & TKT_FLG_RENEWABLE) + buf[i++] = 'R'; + if (cred->ticket_flags & TKT_FLG_INITIAL) + buf[i++] = 'I'; + if (cred->ticket_flags & TKT_FLG_HW_AUTH) + buf[i++] = 'H'; + if (cred->ticket_flags & TKT_FLG_PRE_AUTH) + buf[i++] = 'A'; + buf[i] = '\0'; + return(buf); +} + +void printtime(krb5_timestamp ts) +{ + char fmtbuf[18], fill = ' '; + + if (!krb5_timestamp_to_sfstring(ts, fmtbuf, sizeof(fmtbuf), &fill)) + printf("%s", fmtbuf); +} + + +krb5_error_code +krb5_get_login_princ(luser, princ_list) + const char *luser; + char ***princ_list; +{ + struct stat sbuf; + struct passwd *pwd; + char pbuf[MAXPATHLEN]; + FILE *fp; + char * linebuf; + char *newline; + int gobble, result; + char ** buf_out; + struct stat st_temp; + int count = 0, chunk_count = 1; + + /* no account => no access */ + + if ((pwd = getpwnam(luser)) == NULL) { + return 0; + } + result = snprintf(pbuf, sizeof(pbuf), "%s/.k5login", pwd->pw_dir); + if (SNPRINTF_OVERFLOW(result, sizeof(pbuf))) { + fprintf(stderr, _("home directory path for %s too long\n"), luser); + exit (1); + } + + if (stat(pbuf, &st_temp)) { /* not accessible */ + return 0; + } + + + /* open ~/.k5login */ + if ((fp = fopen(pbuf, "r")) == NULL) { + return 0; + } + /* + * For security reasons, the .k5login file must be owned either by + * the user himself, or by root. Otherwise, don't grant access. + */ + if (fstat(fileno(fp), &sbuf)) { + fclose(fp); + return 0; + } + if ((sbuf.st_uid != pwd->pw_uid) && sbuf.st_uid) { + fclose(fp); + return 0; + } + + /* check each line */ + + + if( !(linebuf = (char *) calloc (BUFSIZ, sizeof(char)))) return ENOMEM; + + if (!(buf_out = (char **) malloc( CHUNK * sizeof(char *)))) return ENOMEM; + + while ( fgets(linebuf, BUFSIZ, fp) != NULL) { + /* null-terminate the input string */ + linebuf[BUFSIZ-1] = '\0'; + newline = NULL; + /* nuke the newline if it exists */ + if ((newline = strchr(linebuf, '\n'))) + *newline = '\0'; + + buf_out[count] = linebuf; + count ++; + + if (count == (chunk_count * CHUNK -1)){ + chunk_count ++; + if (!(buf_out = (char **) realloc(buf_out, + chunk_count * CHUNK * sizeof(char *)))){ + return ENOMEM; + } + } + + /* clean up the rest of the line if necessary */ + if (!newline) + while (((gobble = getc(fp)) != EOF) && gobble != '\n'); + + if( !(linebuf = (char *) calloc (BUFSIZ, sizeof(char)))) return ENOMEM; + } + + buf_out[count] = NULL; + *princ_list = buf_out; + fclose(fp); + return 0; +} + + + +void +show_credential(context, cred, cc) + krb5_context context; + krb5_creds *cred; + krb5_ccache cc; +{ + krb5_error_code retval; + char *name, *sname, *flags; + int first = 1; + krb5_principal princ; + char * defname; + int show_flags =1; + + retval = krb5_unparse_name(context, cred->client, &name); + if (retval) { + com_err(prog_name, retval, _("while unparsing client name")); + return; + } + retval = krb5_unparse_name(context, cred->server, &sname); + if (retval) { + com_err(prog_name, retval, _("while unparsing server name")); + free(name); + return; + } + + if ((retval = krb5_cc_get_principal(context, cc, &princ))) { + com_err(prog_name, retval, _("while retrieving principal name")); + return; + } + if ((retval = krb5_unparse_name(context, princ, &defname))) { + com_err(prog_name, retval, _("while unparsing principal name")); + return; + } + + if (!cred->times.starttime) + cred->times.starttime = cred->times.authtime; + + printtime(cred->times.starttime); + putchar(' '); putchar(' '); + printtime(cred->times.endtime); + putchar(' '); putchar(' '); + + printf("%s\n", sname); + + if (strcmp(name, defname)) { + printf(_("\tfor client %s"), name); + first = 0; + } + + if (cred->times.renew_till) { + if (first) + fputs("\t",stdout); + else + fputs(", ",stdout); + fputs(_("renew until "), stdout); + printtime(cred->times.renew_till); + } + if (show_flags) { + flags = flags_string(cred); + if (flags && *flags) { + if (first) + fputs("\t",stdout); + else + fputs(", ",stdout); + printf(_("Flags: %s"), flags); + first = 0; + } + } + putchar('\n'); + free(name); + free(sname); +} + +/* Create a random string suitable for a filename extension. */ +krb5_error_code +gen_sym(krb5_context context, char **sym_out) +{ + krb5_error_code retval; + char bytes[6], *p, *sym; + krb5_data data = make_data(bytes, sizeof(bytes)); + + *sym_out = NULL; + retval = krb5_c_random_make_octets(context, &data); + if (retval) + return retval; + sym = k5_base64_encode(data.data, data.length); + if (sym == NULL) + return ENOMEM; + /* Tweak the output alphabet just a bit. */ + while ((p = strchr(sym, '/')) != NULL) + *p = '_'; + while ((p = strchr(sym, '+')) != NULL) + *p = '-'; + *sym_out = sym; + return 0; +} + +krb5_error_code krb5_ccache_overwrite(context, ccs, cct, primary_principal) + krb5_context context; + krb5_ccache ccs; + krb5_ccache cct; + krb5_principal primary_principal; +{ + krb5_error_code retval=0; + krb5_principal temp_principal; + krb5_creds ** ccs_creds_arr = NULL; + int i=0; + + if (ks_ccache_is_initialized(context, ccs)) { + if ((retval = krb5_get_nonexp_tkts(context, ccs, &ccs_creds_arr))){ + return retval; + } + } + + if (ks_ccache_is_initialized(context, cct)) { + if ((retval = krb5_cc_get_principal(context, cct, &temp_principal))){ + return retval; + } + }else{ + temp_principal = primary_principal; + } + + if ((retval = krb5_cc_initialize(context, cct, temp_principal))){ + return retval; + } + + retval = krb5_store_all_creds(context, cct, ccs_creds_arr, NULL); + + if (ccs_creds_arr){ + while (ccs_creds_arr[i]){ + krb5_free_creds(context, ccs_creds_arr[i]); + i++; + } + } + + return retval; +} + +krb5_error_code krb5_store_some_creds(context, cc, creds_def, creds_other, prst, + stored) + krb5_context context; + krb5_ccache cc; + krb5_creds **creds_def; + krb5_creds **creds_other; + krb5_principal prst; + krb5_boolean *stored; +{ + + int i = 0; + krb5_error_code retval = 0; + krb5_creds ** temp_creds= NULL; + krb5_boolean temp_stored = FALSE; + + + if ((creds_def == NULL) && (creds_other == NULL)) + return 0; + + if ((creds_def == NULL) && (creds_other != NULL)) + temp_creds = creds_other; + + if ((creds_def != NULL) && (creds_other == NULL)) + temp_creds = creds_def; + + + if (temp_creds){ + while(temp_creds[i]){ + if (krb5_principal_compare(context, + temp_creds[i]->client, + prst)== TRUE) { + + if ((retval = krb5_cc_store_cred(context, + cc,temp_creds[i]))){ + return retval; + } + temp_stored = TRUE; + } + + i++; + } + } + else { /* both arrays have elements in them */ + return KRB5KRB_ERR_GENERIC; + } + + *stored = temp_stored; + return 0; +} + +krb5_error_code krb5_ccache_filter (context, cc, prst) + krb5_context context; + krb5_ccache cc; + krb5_principal prst; +{ + + int i=0; + krb5_error_code retval=0; + krb5_principal temp_principal; + krb5_creds ** cc_creds_arr = NULL; + const char * cc_name; + krb5_boolean stored; + + cc_name = krb5_cc_get_name(context, cc); + + if (ks_ccache_is_initialized(context, cc)) { + if (auth_debug) { + fprintf(stderr,"putting cache %s through a filter for -z option\n", cc_name); + } + + if ((retval = krb5_get_nonexp_tkts(context, cc, &cc_creds_arr))){ + return retval; + } + + if ((retval = krb5_cc_get_principal(context, cc, &temp_principal))){ + return retval; + } + + if ((retval = krb5_cc_initialize(context, cc, temp_principal))){ + return retval; + } + + if ((retval = krb5_store_some_creds(context, cc, cc_creds_arr, + NULL, prst, &stored))){ + return retval; + } + + if (cc_creds_arr){ + while (cc_creds_arr[i]){ + krb5_free_creds(context, cc_creds_arr[i]); + i++; + } + } + } + return 0; +} + +krb5_boolean krb5_find_princ_in_cred_list (context, creds_list, princ) + krb5_context context; + krb5_creds **creds_list; + krb5_principal princ; +{ + + int i = 0; + krb5_boolean temp_stored = FALSE; + + if (creds_list){ + while(creds_list[i]){ + if (krb5_principal_compare(context, + creds_list[i]->client, + princ)== TRUE){ + temp_stored = TRUE; + break; + } + + i++; + } + } + + return temp_stored; +} + +krb5_error_code krb5_find_princ_in_cache (context, cc, princ, found) + krb5_context context; + krb5_ccache cc; + krb5_principal princ; + krb5_boolean *found; +{ + krb5_error_code retval; + krb5_creds ** creds_list = NULL; + + if (ks_ccache_is_initialized(context, cc)) { + if ((retval = krb5_get_nonexp_tkts(context, cc, &creds_list))){ + return retval; + } + } + + *found = krb5_find_princ_in_cred_list(context, creds_list, princ); + return 0; +} + +krb5_boolean +ks_ccache_name_is_initialized(krb5_context context, const char *cctag) +{ + krb5_boolean result; + krb5_ccache cc; + + if (krb5_cc_resolve(context, cctag, &cc) != 0) + return FALSE; + result = ks_ccache_is_initialized(context, cc); + krb5_cc_close(context, cc); + + return result; +} + +krb5_boolean +ks_ccache_is_initialized(krb5_context context, krb5_ccache cc) +{ + krb5_principal princ; + krb5_error_code retval; + + if (cc == NULL) + return FALSE; + + retval = krb5_cc_get_principal(context, cc, &princ); + if (retval == 0) + krb5_free_principal(context, princ); + + return retval == 0; +} diff --git a/krb5-1.21.3/src/clients/ksu/deps b/krb5-1.21.3/src/clients/ksu/deps new file mode 100644 index 00000000..a3a07b94 --- /dev/null +++ b/krb5-1.21.3/src/clients/ksu/deps @@ -0,0 +1,72 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)krb_auth_su.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/k5-util.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + krb_auth_su.c ksu.h +$(OUTPRE)ccache.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/k5-base64.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/k5-util.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ccache.c ksu.h +$(OUTPRE)authorization.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/k5-util.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + authorization.c ksu.h +$(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-util.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h ksu.h main.c +$(OUTPRE)heuristic.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/k5-util.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + heuristic.c ksu.h +$(OUTPRE)xmalloc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/k5-util.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ksu.h xmalloc.c +$(OUTPRE)setenv.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + setenv.c diff --git a/krb5-1.21.3/src/clients/ksu/heuristic.c b/krb5-1.21.3/src/clients/ksu/heuristic.c new file mode 100644 index 00000000..4f7280f4 --- /dev/null +++ b/krb5-1.21.3/src/clients/ksu/heuristic.c @@ -0,0 +1,749 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (c) 1994 by the University of Southern California + * + * EXPORT OF THIS SOFTWARE from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute + * this software and its documentation in source and binary forms is + * hereby granted, provided that any documentation or other materials + * related to such distribution or use acknowledge that the software + * was developed by the University of Southern California. + * + * DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The + * University of Southern California MAKES NO REPRESENTATIONS OR + * WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, the University of Southern California MAKES NO + * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY + * PARTICULAR PURPOSE. The University of Southern + * California shall not be held liable for any liability nor for any + * direct, indirect, or consequential damages with respect to any + * claim by the user or distributor of the ksu software. + * + * KSU was written by: Ari Medvinsky, ari@isi.edu + */ + +#include "ksu.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + + +/******************************************************************* +get_all_princ_from_file - retrieves all principal names + from file pointed to by fp. + +*******************************************************************/ +static void close_time (int, FILE *, int, FILE *); +static krb5_boolean find_str_in_list (char **, char *); + +krb5_error_code get_all_princ_from_file (fp, plist) + FILE *fp; + char ***plist; +{ + + krb5_error_code retval; + char * line, * fprinc, * lp, ** temp_list = NULL; + int count = 0, chunk_count = 1; + + if (!(temp_list = (char **) malloc( CHUNK * sizeof(char *)))) + return ENOMEM; + + retval = get_line(fp, &line); + if (retval) + return retval; + + while (line){ + fprinc = get_first_token (line, &lp); + + if (fprinc ){ + temp_list[count] = xstrdup(fprinc); + count ++; + } + + if(count == (chunk_count * CHUNK -1)){ + chunk_count ++; + if (!(temp_list = (char **) realloc(temp_list, + chunk_count * CHUNK * sizeof(char *)))){ + return ENOMEM; + } + } + + + free (line); + retval = get_line(fp, &line); + if (retval) + return retval; + } + + temp_list[count] = NULL; + + *plist = temp_list; + return 0; +} + +/************************************************************* +list_union - combines list1 and list2 into combined_list. + the space for list1 and list2 is either freed + or used by combined_list. +**************************************************************/ + +krb5_error_code list_union(list1, list2, combined_list) + char **list1; + char **list2; + char ***combined_list; +{ + + unsigned int c1 =0, c2 = 0, i=0, j=0; + char ** tlist; + + if (! list1){ + *combined_list = list2; + return 0; + } + + if (! list2){ + *combined_list = list1; + return 0; + } + + while (list1[c1]) c1++; + while (list2[c2]) c2++; + + if (!(tlist = (char **) calloc( c1 + c2 + 1, sizeof ( char *)))) + return ENOMEM; + + i = 0; + while(list1[i]) { + tlist[i] = list1[i]; + i++; + } + j = 0; + while(list2[j]){ + if(find_str_in_list(list1, list2[j])==FALSE){ + tlist[i] = list2[j]; + i++; + } + j++; + } + + free (list1); + free (list2); + + tlist[i]= NULL; + + *combined_list = tlist; + return 0; +} + +krb5_error_code +filter(fp, cmd, k5users_list, k5users_filt_list) + FILE *fp; + char *cmd; + char **k5users_list; + char ***k5users_filt_list; +{ + + krb5_error_code retval =0; + krb5_boolean found = FALSE; + char * out_cmd = NULL; + unsigned int i=0, j=0, found_count = 0, k=0; + char ** temp_filt_list; + + *k5users_filt_list = NULL; + + if (! k5users_list){ + return 0; + } + + while(k5users_list[i]){ + + retval= k5users_lookup(fp, k5users_list[i], cmd, &found, &out_cmd); + if (retval) + return retval; + + if (found == FALSE){ + free (k5users_list[i]); + k5users_list[i] = NULL; + if (out_cmd) gb_err = out_cmd; + } else + found_count ++; + + i++; + } + + if (! (temp_filt_list = (char **) calloc(found_count +1, sizeof (char*)))) + return ENOMEM; + + for(j= 0, k=0; j < i; j++ ) { + if (k5users_list[j]){ + temp_filt_list[k] = k5users_list[j]; + k++; + } + } + + temp_filt_list[k] = NULL; + + free (k5users_list); + + *k5users_filt_list = temp_filt_list; + return 0; +} + +krb5_error_code +get_authorized_princ_names(luser, cmd, princ_list) + const char *luser; + char *cmd; + char ***princ_list; +{ + + struct passwd *pwd; + int k5login_flag =0; + int k5users_flag =0; + FILE * login_fp = NULL , * users_fp = NULL; + char ** k5login_list = NULL, ** k5users_list = NULL; + char ** k5users_filt_list = NULL; + char ** combined_list = NULL; + struct stat tb; + krb5_error_code retval; + + *princ_list = NULL; + + /* no account => no access */ + + if ((pwd = getpwnam(luser)) == NULL) + return 0; + + k5login_flag = stat(k5login_path, &tb); + k5users_flag = stat(k5users_path, &tb); + + if (!k5login_flag){ + if ((login_fp = fopen(k5login_path, "r")) == NULL) + return 0; + if ( fowner(login_fp, pwd->pw_uid) == FALSE){ + close_time(1 /*k5users_flag*/, (FILE *) 0 /*users_fp*/, + k5login_flag,login_fp); + return 0; + } + } + if (!k5users_flag){ + if ((users_fp = fopen(k5users_path, "r")) == NULL) + return 0; + + if ( fowner(users_fp, pwd->pw_uid) == FALSE){ + close_time(k5users_flag,users_fp, k5login_flag,login_fp); + return 0; + } + + retval = get_all_princ_from_file (users_fp, &k5users_list); + if(retval) { + close_time(k5users_flag,users_fp, k5login_flag,login_fp); + return retval; + } + + rewind(users_fp); + + retval = filter(users_fp,cmd, k5users_list, &k5users_filt_list); + if(retval) { + close_time(k5users_flag,users_fp, k5login_flag, login_fp); + return retval; + } + } + + if (!k5login_flag){ + retval = get_all_princ_from_file (login_fp, &k5login_list); + if(retval) { + close_time(k5users_flag,users_fp, k5login_flag,login_fp); + return retval; + } + } + + close_time(k5users_flag,users_fp, k5login_flag, login_fp); + + retval = list_union(k5login_list, k5users_filt_list, &combined_list); + if (retval){ + return retval; + } + *princ_list = combined_list; + return 0; +} + +static void close_time(k5users_flag, users_fp, k5login_flag, login_fp) + int k5users_flag; + FILE *users_fp; + int k5login_flag; + FILE *login_fp; +{ + + if (!k5users_flag) fclose(users_fp); + if (!k5login_flag) fclose(login_fp); + +} + +static krb5_boolean find_str_in_list(list , elm) + char **list; + char *elm; +{ + + int i=0; + krb5_boolean found = FALSE; + + if (!list) return found; + + while (list[i] ){ + if (!strcmp(list[i], elm)){ + found = TRUE; + break; + } + i++; + } + + return found; +} + +/********************************************************************** +returns the principal that is closes to client (can be the the client +himself). plist contains +a principal list obtained from .k5login and .k5users file. +A principal is picked that has the best chance of getting in. + +**********************************************************************/ + + +krb5_error_code get_closest_principal(context, plist, client, found) + krb5_context context; + char **plist; + krb5_principal *client; + krb5_boolean *found; +{ + krb5_error_code retval =0; + krb5_principal temp_client, best_client = NULL; + int i = 0, j=0, cnelem, pnelem; + krb5_boolean got_one; + + *found = FALSE; + + if (! plist ) return 0; + + cnelem = krb5_princ_size(context, *client); + + while(plist[i]){ + + retval = krb5_parse_name(context, plist[i], &temp_client); + if (retval) + return retval; + + pnelem = krb5_princ_size(context, temp_client); + + if ( cnelem > pnelem){ + i++; + continue; + } + + if (data_eq(*krb5_princ_realm(context, *client), + *krb5_princ_realm(context, temp_client))) { + + got_one = TRUE; + for(j =0; j < cnelem; j ++){ + krb5_data *p1 = + krb5_princ_component(context, *client, j); + krb5_data *p2 = + krb5_princ_component(context, temp_client, j); + + if (!p1 || !p2 || !data_eq(*p1, *p2)) { + got_one = FALSE; + break; + } + } + if (got_one == TRUE){ + if(best_client){ + if(krb5_princ_size(context, best_client) > + krb5_princ_size(context, temp_client)){ + best_client = temp_client; + } + }else + best_client = temp_client; + } + } + i++; + } + + if (best_client) { + *found = TRUE; + *client = best_client; + } + + return 0; +} + +/**************************************************************** +find_either_ticket checks to see whether there is a ticket for the + end server or tgt, if neither is there the return FALSE, +*****************************************************************/ + +krb5_error_code find_either_ticket (context, cc, client, end_server, found) + krb5_context context; + krb5_ccache cc; + krb5_principal client; + krb5_principal end_server; + krb5_boolean *found; +{ + + krb5_principal kdc_server; + krb5_error_code retval; + krb5_boolean temp_found = FALSE; + + if (ks_ccache_is_initialized(context, cc)) { + + retval = find_ticket(context, cc, client, end_server, &temp_found); + if (retval) + return retval; + + if (temp_found == FALSE){ + retval = ksu_tgtname(context, + krb5_princ_realm(context, client), + krb5_princ_realm(context, client), + &kdc_server); + if (retval) + return retval; + + retval = find_ticket(context, cc,client, kdc_server, &temp_found); + if(retval) + return retval; + } + else if (auth_debug) + printf("find_either_ticket: found end server ticket\n"); + } + + *found = temp_found; + + return 0; +} + + +krb5_error_code find_ticket (context, cc, client, server, found) + krb5_context context; + krb5_ccache cc; + krb5_principal client; + krb5_principal server; + krb5_boolean *found; +{ + + krb5_creds tgt, tgtq; + krb5_error_code retval; + + *found = FALSE; + + memset(&tgtq, 0, sizeof(tgtq)); + memset(&tgt, 0, sizeof(tgt)); + + retval= krb5_copy_principal(context, client, &tgtq.client); + if (retval) + return retval; + + retval= krb5_copy_principal(context, server, &tgtq.server); + if (retval) + return retval ; + + retval = krb5_cc_retrieve_cred(context, cc, KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES, + &tgtq, &tgt); + + if (! retval) retval = krb5_check_exp(context, tgt.times); + + if (retval){ + if ((retval != KRB5_CC_NOTFOUND) && + (retval != KRB5KRB_AP_ERR_TKT_EXPIRED)){ + return retval ; + } + } else{ + *found = TRUE; + return 0; + } + + free(tgtq.server); + free(tgtq.client); + + return 0; +} + + + +krb5_error_code find_princ_in_list (context, princ, plist, found) + krb5_context context; + krb5_principal princ; + char **plist; + krb5_boolean *found; +{ + + int i=0; + char * princname; + krb5_error_code retval; + + *found = FALSE; + + if (!plist) return 0; + + retval = krb5_unparse_name(context, princ, &princname); + if (retval) + return retval; + + while (plist[i] ){ + if (!strcmp(plist[i], princname)){ + *found = TRUE; + break; + } + i++; + } + + return 0; + +} + +typedef struct princ_info { + krb5_principal p; + krb5_boolean found; +}princ_info; + +/********************************************************************** +get_best_princ_for_target - + +sets the client name, path_out gets set, if authorization is not possible +path_out gets set to ... + +***********************************************************************/ + +krb5_error_code get_best_princ_for_target(context, source_uid, target_uid, + source_user, target_user, + cc_source, options, cmd, + hostname, client, path_out) + krb5_context context; + uid_t source_uid; + uid_t target_uid; + char *source_user; + char *target_user; + krb5_ccache cc_source; + krb5_get_init_creds_opt *options; + char *cmd; + char *hostname; + krb5_principal *client; + int *path_out; +{ + + princ_info princ_trials[10]; + krb5_principal cc_def_princ = NULL; + krb5_principal temp_client; + krb5_principal target_client; + krb5_principal source_client; + krb5_principal end_server; + krb5_error_code retval; + char ** aplist =NULL; + krb5_boolean found = FALSE; + struct stat tb; + int count =0; + int i; + + *path_out = 0; + + /* -n option was specified client is set we are done */ + if (*client != NULL) + return 0; + + if (ks_ccache_is_initialized(context, cc_source)) { + retval = krb5_cc_get_principal(context, cc_source, &cc_def_princ); + if (retval) + return retval; + } + + retval=krb5_parse_name(context, target_user, &target_client); + if (retval) + return retval; + + retval=krb5_parse_name(context, source_user, &source_client); + if (retval) + return retval; + + if (source_uid == 0){ + if (target_uid != 0) + *client = target_client; /* this will be used to restrict + the cache copty */ + else { + if(cc_def_princ) + *client = cc_def_princ; + else + *client = target_client; + } + + if (auth_debug) + printf(" GET_best_princ_for_target: via source_uid == 0\n"); + + return 0; + } + + /* from here on, the code is for source_uid != 0 */ + + if (source_uid && (source_uid == target_uid)){ + if(cc_def_princ) + *client = cc_def_princ; + else + *client = target_client; + if (auth_debug) + printf("GET_best_princ_for_target: via source_uid == target_uid\n"); + return 0; + } + + /* Become root, then target for looking at .k5login.*/ + if (krb5_seteuid(0) || krb5_seteuid(target_uid) ) { + return errno; + } + + /* if .k5users and .k5login do not exist */ + if (stat(k5login_path, &tb) && stat(k5users_path, &tb) ){ + *client = target_client; + + if (cmd) + *path_out = NOT_AUTHORIZED; + + if (auth_debug) + printf(" GET_best_princ_for_target: via no auth files path\n"); + + return 0; + }else{ + retval = get_authorized_princ_names(target_user, cmd, &aplist); + if (retval) + return retval; + + /* .k5users or .k5login exist, but no authorization */ + if ((!aplist) || (!aplist[0])) { + *path_out = NOT_AUTHORIZED; + if (auth_debug) + printf("GET_best_princ_for_target: via empty auth files path\n"); + return 0; + } + } + + retval = krb5_sname_to_principal(context, hostname, NULL, + KRB5_NT_SRV_HST, &end_server); + if (retval) + return retval; + + + /* first see if default principal of the source cache + * can get us in, then the target_user@realm, then the + * source_user@realm. If all of them fail, try any + * other ticket in the cache. */ + + if (cc_def_princ) + princ_trials[count ++].p = cc_def_princ; + else + princ_trials[count ++].p = NULL; + + princ_trials[count ++].p = target_client; + princ_trials[count ++].p = source_client; + + for (i= 0; i < count; i ++) + princ_trials[i].found = FALSE; + + for (i= 0; i < count; i ++){ + if(princ_trials[i].p) { + retval= find_princ_in_list(context, princ_trials[i].p, aplist, + &found); + if (retval) + return retval; + + if (found == TRUE){ + princ_trials[i].found = TRUE; + + retval = find_either_ticket (context, cc_source, + princ_trials[i].p, + end_server, &found); + if (retval) + return retval; + if (found == TRUE){ + *client = princ_trials[i].p; + if (auth_debug) + printf("GET_best_princ_for_target: via ticket file, choice #%d\n", i); + return 0; + } + } + } + } + + /* out of preferred principals, see if there is any ticket that will + get us in */ + + i=0; + while (aplist[i]){ + retval = krb5_parse_name(context, aplist[i], &temp_client); + if (retval) + return retval; + + retval = find_either_ticket (context, cc_source, temp_client, + end_server, &found); + if (retval) + return retval; + + if (found == TRUE){ + if (auth_debug) + printf("GET_best_princ_for_target: via ticket file, choice: any ok ticket \n" ); + *client = temp_client; + return 0; + } + + krb5_free_principal(context, temp_client); + + i++; + } + + /* no tickets qualified, select a principal, that may be used + for password promting */ + + + for (i=0; i < count; i ++){ + if (princ_trials[i].found == TRUE){ + *client = princ_trials[i].p; + + if (auth_debug) + printf("GET_best_princ_for_target: via prompt passwd list choice #%d \n",i); + return 0; + } + } + +#ifdef PRINC_LOOK_AHEAD + for (i=0; i < count; i ++){ + if (princ_trials[i].p){ + retval=krb5_copy_principal(context, princ_trials[i].p, + &temp_client); + if(retval) + return retval; + + /* get the client name that is the closest + to the three princ in trials */ + + retval=get_closest_principal(context, aplist, &temp_client, + &found); + if(retval) + return retval; + + if (found == TRUE){ + *client = temp_client; + if (auth_debug) + printf("GET_best_princ_for_target: via prompt passwd list choice: approximation of princ in trials # %d \n",i); + return 0; + } + krb5_free_principal(context, temp_client); + } + } + +#endif /* PRINC_LOOK_AHEAD */ + + + if(auth_debug) + printf( "GET_best_princ_for_target: out of luck, can't get appropriate default principal\n"); + + *path_out = NOT_AUTHORIZED; + return 0; +} diff --git a/krb5-1.21.3/src/clients/ksu/krb_auth_su.c b/krb5-1.21.3/src/clients/ksu/krb_auth_su.c new file mode 100644 index 00000000..fb848dca --- /dev/null +++ b/krb5-1.21.3/src/clients/ksu/krb_auth_su.c @@ -0,0 +1,311 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (c) 1994 by the University of Southern California + * + * EXPORT OF THIS SOFTWARE from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute + * this software and its documentation in source and binary forms is + * hereby granted, provided that any documentation or other materials + * related to such distribution or use acknowledge that the software + * was developed by the University of Southern California. + * + * DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The + * University of Southern California MAKES NO REPRESENTATIONS OR + * WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, the University of Southern California MAKES NO + * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY + * PARTICULAR PURPOSE. The University of Southern + * California shall not be held liable for any liability nor for any + * direct, indirect, or consequential damages with respect to any + * claim by the user or distributor of the ksu software. + * + * KSU was written by: Ari Medvinsky, ari@isi.edu + */ + +#include "ksu.h" + + +void plain_dump_principal (); + +krb5_boolean krb5_auth_check(context, client_pname, hostname, options, + target_user, cc, path_passwd, target_uid) + krb5_context context; + krb5_principal client_pname; + char *hostname; + krb5_get_init_creds_opt *options; + char *target_user; + uid_t target_uid; + krb5_ccache cc; + int *path_passwd; +{ + krb5_principal client; + krb5_verify_init_creds_opt vfy_opts; + krb5_creds tgt, tgtq; + krb5_error_code retval =0; + int got_it = 0; + krb5_boolean zero_password; + + *path_passwd = 0; + memset(&tgtq, 0, sizeof(tgtq)); + memset(&tgt, 0, sizeof(tgt)); + + if ((retval= krb5_copy_principal(context, client_pname, &client))){ + com_err(prog_name, retval, _("while copying client principal")); + return (FALSE) ; + } + + if ((retval= krb5_copy_principal(context, client, &tgtq.client))){ + com_err(prog_name, retval, _("while copying client principal")); + return (FALSE) ; + } + + if ((retval = ksu_tgtname(context, krb5_princ_realm(context, client), + krb5_princ_realm(context, client), + &tgtq.server))){ + com_err(prog_name, retval, _("while creating tgt for local realm")); + krb5_free_principal(context, client); + return (FALSE) ; + } + + if (auth_debug){ dump_principal(context, "local tgt principal name", tgtq.server ); } + retval = krb5_cc_retrieve_cred(context, cc, + KRB5_TC_MATCH_SRV_NAMEONLY | KRB5_TC_SUPPORTED_KTYPES, + &tgtq, &tgt); + + if (! retval) retval = krb5_check_exp(context, tgt.times); + + if (retval){ + if ((retval != KRB5_CC_NOTFOUND) && + (retval != KRB5KRB_AP_ERR_TKT_EXPIRED)){ + com_err(prog_name, retval, _("while retrieving creds from cache")); + return (FALSE) ; + } + } else{ + got_it = 1; + } + + if (! got_it){ + +#ifdef GET_TGT_VIA_PASSWD + if (krb5_seteuid(0)||krb5_seteuid(target_uid)) { + com_err("ksu", errno, _("while switching to target uid")); + return FALSE; + } + + + fprintf(stderr, _("WARNING: Your password may be exposed if you enter " + "it here and are logged \n")); + fprintf(stderr, _(" in remotely using an unsecure " + "(non-encrypted) channel. \n")); + + /*get the ticket granting ticket, via passwd(prompt for passwd)*/ + if (ksu_get_tgt_via_passwd(context, client, options, &zero_password, + &tgt) == FALSE) { + krb5_seteuid(0); + + return FALSE; + } + *path_passwd = 1; + if (krb5_seteuid(0)) { + com_err("ksu", errno, _("while reclaiming root uid")); + return FALSE; + } + +#else + plain_dump_principal (context, client); + fprintf(stderr, + _("does not have any appropriate tickets in the cache.\n")); + return FALSE; + +#endif /* GET_TGT_VIA_PASSWD */ + + } + + krb5_verify_init_creds_opt_init(&vfy_opts); + krb5_verify_init_creds_opt_set_ap_req_nofail( &vfy_opts, 1); + retval = krb5_verify_init_creds(context, &tgt, NULL, NULL, NULL, + &vfy_opts); + if (retval) { + com_err(prog_name, retval, _("while verifying ticket for server")); + return (FALSE); + } + + return (TRUE); +} + +krb5_boolean ksu_get_tgt_via_passwd(context, client, options, zero_password, + creds_out) + krb5_context context; + krb5_principal client; + krb5_get_init_creds_opt *options; + krb5_boolean *zero_password; + krb5_creds *creds_out; +{ + krb5_error_code code; + krb5_creds creds; + krb5_timestamp now; + unsigned int pwsize; + char password[255], *client_name, prompt[255]; + int result; + + *zero_password = FALSE; + if (creds_out != NULL) + memset(creds_out, 0, sizeof(*creds_out)); + + if ((code = krb5_unparse_name(context, client, &client_name))) { + com_err (prog_name, code, _("when unparsing name")); + return (FALSE); + } + + memset(&creds, 0, sizeof(creds)); + + if ((code = krb5_timeofday(context, &now))) { + com_err(prog_name, code, _("while getting time of day")); + return (FALSE); + } + + result = snprintf(prompt, sizeof(prompt), _("Kerberos password for %s: "), + client_name); + if (SNPRINTF_OVERFLOW(result, sizeof(prompt))) { + fprintf(stderr, + _("principal name %s too long for internal buffer space\n"), + client_name); + return FALSE; + } + + pwsize = sizeof(password); + + code = krb5_read_password(context, prompt, 0, password, &pwsize); + if (code ) { + com_err(prog_name, code, _("while reading password for '%s'\n"), + client_name); + return (FALSE); + } + + if ( pwsize == 0) { + fprintf(stderr, _("No password given\n")); + *zero_password = TRUE; + return (FALSE); + } + + code = krb5_get_init_creds_password(context, &creds, client, password, + krb5_prompter_posix, NULL, 0, NULL, + options); + zap(password, sizeof(password)); + + + if (code) { + if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) + fprintf(stderr, _("%s: Password incorrect\n"), prog_name); + else + com_err(prog_name, code, _("while getting initial credentials")); + return (FALSE); + } + if (creds_out != NULL) + *creds_out = creds; + else + krb5_free_cred_contents(context, &creds); + return (TRUE); +} + + +void dump_principal (context, str, p) + krb5_context context; + char *str; + krb5_principal p; +{ + char * stname; + krb5_error_code retval; + + if ((retval = krb5_unparse_name(context, p, &stname))) { + fprintf(stderr, _(" %s while unparsing name\n"), + error_message(retval)); + } + fprintf(stderr, " %s: %s\n", str, stname); +} + +void plain_dump_principal (context, p) + krb5_context context; + krb5_principal p; +{ + char * stname; + krb5_error_code retval; + + if ((retval = krb5_unparse_name(context, p, &stname))) { + fprintf(stderr, _(" %s while unparsing name\n"), + error_message(retval)); + } + fprintf(stderr, "%s ", stname); +} + + +/********************************************************************** +returns the principal that is closest to client. plist contains +a principal list obtained from .k5login and parhaps .k5users file. +This routine gets called before getting the password for a tgt. +A principal is picked that has the best chance of getting in. + +**********************************************************************/ + + +krb5_error_code get_best_principal(context, plist, client) + krb5_context context; + char **plist; + krb5_principal *client; +{ + krb5_error_code retval =0; + krb5_principal temp_client, best_client = NULL; + + int i = 0, nelem; + + if (! plist ) return 0; + + nelem = krb5_princ_size(context, *client); + + while(plist[i]){ + + if ((retval = krb5_parse_name(context, plist[i], &temp_client))){ + return retval; + } + + if (data_eq(*krb5_princ_realm(context, *client), + *krb5_princ_realm(context, temp_client))) { + + if (nelem && + krb5_princ_size(context, *client) > 0 && + krb5_princ_size(context, temp_client) > 0) { + krb5_data *p1 = + krb5_princ_component(context, *client, 0); + krb5_data *p2 = + krb5_princ_component(context, temp_client, 0); + + if (data_eq(*p1, *p2)) { + + if (auth_debug){ + fprintf(stderr, + "get_best_principal: compare with %s\n", + plist[i]); + } + + if(best_client){ + if(krb5_princ_size(context, best_client) > + krb5_princ_size(context, temp_client)){ + best_client = temp_client; + } + }else{ + best_client = temp_client; + } + } + } + + } + i++; + } + + if (best_client) *client = best_client; + return 0; +} diff --git a/krb5-1.21.3/src/clients/ksu/ksu.h b/krb5-1.21.3/src/clients/ksu/ksu.h new file mode 100644 index 00000000..66fb4bcc --- /dev/null +++ b/krb5-1.21.3/src/clients/ksu/ksu.h @@ -0,0 +1,247 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (c) 1994 by the University of Southern California + * + * EXPORT OF THIS SOFTWARE from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute + * this software and its documentation in source and binary forms is + * hereby granted, provided that any documentation or other materials + * related to such distribution or use acknowledge that the software + * was developed by the University of Southern California. + * + * DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The + * University of Southern California MAKES NO REPRESENTATIONS OR + * WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, the University of Southern California MAKES NO + * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY + * PARTICULAR PURPOSE. The University of Southern + * California shall not be held liable for any liability nor for any + * direct, indirect, or consequential damages with respect to any + * claim by the user or distributor of the ksu software. + * + * KSU was written by: Ari Medvinsky, ari@isi.edu + */ + +#include "k5-int.h" +#include "k5-util.h" +#include +#include "com_err.h" +#include +#include +#include +#include +#include +#include +/* or is already included by com_err.h. */ + +#define NO_TARGET_FILE '.' +#define SOURCE_USER_LOGIN "." + +#define KRB5_DEFAULT_OPTIONS 0 +#define KRB5_DEFAULT_TKT_LIFE 60*60*12 /* 12 hours */ + +#define KRB5_LOGIN_NAME ".k5login" +#define KRB5_USERS_NAME ".k5users" +#define USE_DEFAULT_REALM_NAME "." +#define PERMIT_ALL_COMMANDS "*" +#define KRB5_SEC_BUFFSIZE 80 +#define NOT_AUTHORIZED 1 + +#define CHUNK 3 +#define CACHE_MODE 0600 +#define MAX_CMD 2048 /* this is temp, should use realloc instead, + as done in most of the code */ + + +extern int optind; +extern char * optarg; + +/* globals */ +extern char * prog_name; +extern int auth_debug; +extern int quiet; +extern char k5login_path[MAXPATHLEN]; +extern char k5users_path[MAXPATHLEN]; +extern char * gb_err; +/***********/ + +/* krb_auth_su.c */ +extern krb5_boolean krb5_auth_check +(krb5_context, krb5_principal, char *, krb5_get_init_creds_opt *, + char *, krb5_ccache, int *, uid_t); + +extern krb5_boolean krb5_fast_auth +(krb5_context, krb5_principal, krb5_principal, char *, + krb5_ccache); + +extern krb5_boolean ksu_get_tgt_via_passwd +(krb5_context, + krb5_principal, krb5_get_init_creds_opt *, krb5_boolean *, krb5_creds *); + +extern void dump_principal +(krb5_context, char *, krb5_principal); + +extern void plain_dump_principal +(krb5_context, krb5_principal); + + +extern krb5_error_code krb5_parse_lifetime +(char *, long *); + +extern krb5_error_code get_best_principal +(krb5_context, char **, krb5_principal *); + +/* ccache.c */ +extern krb5_error_code krb5_ccache_copy +(krb5_context, krb5_ccache, krb5_principal, krb5_ccache, + krb5_boolean, krb5_principal, krb5_boolean *); + +extern krb5_error_code krb5_store_all_creds +(krb5_context, krb5_ccache, krb5_creds **, krb5_creds **); + +extern krb5_error_code krb5_store_all_creds +(krb5_context, krb5_ccache, krb5_creds **, krb5_creds **); + +extern krb5_boolean compare_creds +(krb5_context, krb5_creds *, krb5_creds *); + +extern krb5_error_code krb5_get_nonexp_tkts +(krb5_context, krb5_ccache, krb5_creds ***); + +extern krb5_error_code krb5_check_exp +(krb5_context, krb5_ticket_times); + +extern char *flags_string (krb5_creds *); + +extern krb5_error_code krb5_get_login_princ +(const char *, char ***); + +extern void show_credential +(krb5_context, krb5_creds *, krb5_ccache); + +krb5_error_code gen_sym(krb5_context context, char **sym); + +extern krb5_error_code krb5_ccache_overwrite +(krb5_context, krb5_ccache, krb5_ccache, krb5_principal); + +extern krb5_error_code krb5_store_some_creds +(krb5_context, krb5_ccache, krb5_creds **, krb5_creds **, + krb5_principal, krb5_boolean *); + +extern krb5_boolean ks_ccache_name_is_initialized +(krb5_context, const char *); + +extern krb5_boolean ks_ccache_is_initialized +(krb5_context, krb5_ccache); + +extern krb5_error_code krb5_ccache_refresh +(krb5_context, krb5_ccache); + +extern krb5_error_code krb5_ccache_filter +(krb5_context, krb5_ccache, krb5_principal); + +extern krb5_boolean krb5_find_princ_in_cred_list +(krb5_context, krb5_creds **, krb5_principal); + +extern krb5_error_code krb5_find_princ_in_cache +(krb5_context, krb5_ccache, krb5_principal, krb5_boolean *); + +extern void printtime (krb5_timestamp); + +/* authorization.c */ +extern krb5_boolean fowner (FILE *, uid_t); + +extern krb5_error_code krb5_authorization +(krb5_context, krb5_principal, const char *, char *, + krb5_boolean *, char **); + +extern krb5_error_code k5login_lookup (FILE *, char *, + krb5_boolean *); + +extern krb5_error_code k5users_lookup +(FILE *, char *, char *, krb5_boolean *, char **); + +extern krb5_boolean fcmd_resolve +(char *, char ***, char **); + +extern krb5_boolean cmd_single (char *); + +extern int cmd_arr_cmp_postfix (char **, char *); + +extern int cmd_arr_cmp (char **, char *); + +extern krb5_boolean find_first_cmd_that_exists +(char **, char **, char **); + +extern int match_commands +(char *, char *, krb5_boolean *, char **, char **); + +extern krb5_error_code get_line (FILE *, char **); + +extern char * get_first_token (char *, char **); + +extern char * get_next_token (char **); + +extern void init_auth_names (char *); + +/* main.c */ +extern void usage (void); + +extern int standard_shell (char *); + +extern krb5_error_code get_params (int *, int, char **, char ***); + +/* heuristic.c */ +extern krb5_error_code get_all_princ_from_file (FILE *, char ***); + +extern krb5_error_code list_union (char **, char **, char ***); + +extern krb5_error_code filter (FILE *, char *, char **, char ***); + +extern krb5_error_code get_authorized_princ_names +(const char *, char *, char ***); + +extern krb5_error_code get_closest_principal +(krb5_context, char **, krb5_principal *, krb5_boolean *); + +extern krb5_error_code find_either_ticket +(krb5_context, krb5_ccache, krb5_principal, + krb5_principal, krb5_boolean *); + +extern krb5_error_code find_ticket +(krb5_context, krb5_ccache, krb5_principal, + krb5_principal, krb5_boolean *); + + +extern krb5_error_code find_princ_in_list +(krb5_context, krb5_principal, char **, krb5_boolean *); + +extern krb5_error_code get_best_princ_for_target +(krb5_context, uid_t, uid_t, char *, char *, krb5_ccache, + krb5_get_init_creds_opt *, char *, char *, krb5_principal *, int *); + +extern krb5_error_code ksu_tgtname (krb5_context, const krb5_data *, + const krb5_data *, + krb5_principal *tgtprinc); + +#ifndef min +#define min(a,b) ((a) > (b) ? (b) : (a)) +#endif /* min */ + + +extern char *krb5_lname_file; /* Note: print this out just be sure + that it gets set */ + +extern void *xmalloc (size_t), + *xrealloc (void *, size_t), + *xcalloc (size_t, size_t); + extern char *xstrdup (const char *); + extern char *xasprintf (const char *format, ...); + +#ifndef HAVE_UNSETENV + void unsetenv (char *); +#endif diff --git a/krb5-1.21.3/src/clients/ksu/main.c b/krb5-1.21.3/src/clients/ksu/main.c new file mode 100644 index 00000000..af128617 --- /dev/null +++ b/krb5-1.21.3/src/clients/ksu/main.c @@ -0,0 +1,1087 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (c) 1994 by the University of Southern California + * + * EXPORT OF THIS SOFTWARE from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to copy, modify, and distribute + * this software and its documentation in source and binary forms is + * hereby granted, provided that any documentation or other materials + * related to such distribution or use acknowledge that the software + * was developed by the University of Southern California. + * + * DISCLAIMER OF WARRANTY. THIS SOFTWARE IS PROVIDED "AS IS". The + * University of Southern California MAKES NO REPRESENTATIONS OR + * WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, the University of Southern California MAKES NO + * REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY + * PARTICULAR PURPOSE. The University of Southern + * California shall not be held liable for any liability nor for any + * direct, indirect, or consequential damages with respect to any + * claim by the user or distributor of the ksu software. + * + * KSU was written by: Ari Medvinsky, ari@isi.edu + */ + +#include "ksu.h" +#include "adm_proto.h" +#include +#include +#include +#include + +/* globals */ +char * prog_name; +int auth_debug =0; +char k5login_path[MAXPATHLEN]; +char k5users_path[MAXPATHLEN]; +char * gb_err = NULL; +int quiet = 0; +/***********/ + +#define KS_TEMPORARY_CACHE "MEMORY:_ksu" +#define KS_TEMPORARY_PRINC "_ksu/_ksu@_ksu" +#define _DEF_CSH "/bin/csh" +static int set_env_var (char *, char *); +static void sweep_up (krb5_context, krb5_ccache); +static char * ontty (void); +static krb5_error_code init_ksu_context(krb5_context *); +static krb5_error_code set_ccname_env(krb5_context, krb5_ccache); +static void print_status( const char *fmt, ...) +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) + __attribute__ ((__format__ (__printf__, 1, 2))) +#endif + ; +static krb5_error_code resolve_target_cache(krb5_context ksu_context, + krb5_principal princ, + krb5_ccache *ccache_out, + krb5_boolean *ccache_reused); + +/* Note -e and -a options are mutually exclusive */ +/* insure the proper specification of target user as well as catching + ill specified arguments to commands */ + +void usage (){ + fprintf(stderr, + _("Usage: %s [target user] [-n principal] [-c source cachename] " + "[-k] [-r time] [-p|-P] [-f|-F] [-l lifetime] [-zZ] [-q] " + "[-e command [args... ] ] [-a [args... ] ]\n"), prog_name); +} + +/* for Ultrix and friends ... */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +/* These are file static so sweep_up can get to them*/ +static uid_t source_uid, target_uid; + +int +main (argc, argv) + int argc; + char ** argv; +{ + int hp =0; + int some_rest_copy = 0; + int all_rest_copy = 0; + char *localhostname = NULL; + krb5_get_init_creds_opt *options = NULL; + int option=0; + int statusp=0; + krb5_error_code retval = 0; + krb5_principal client = NULL, tmp_princ = NULL; + krb5_ccache cc_tmp = NULL, cc_target = NULL; + krb5_context ksu_context; + char * cc_target_tag = NULL; + char * target_user = NULL; + char * source_user; + + krb5_ccache cc_source = NULL; + const char * cc_source_tag = NULL; + const char * cc_source_tag_tmp = NULL; + char * cmd = NULL, * exec_cmd = NULL; + int errflg = 0; + krb5_boolean auth_val; + krb5_boolean authorization_val = FALSE; + int path_passwd = 0; + int done =0,i,j; + uid_t ruid = getuid (); + struct passwd *pwd=NULL, *target_pwd ; + char * shell; + char ** params; + int keep_target_cache = 0; + int child_pid, child_pgrp, ret_pid; + extern char * getpass(), *crypt(); + int pargc; + char ** pargv; + krb5_boolean stored = FALSE, cc_reused = FALSE, given_princ = FALSE; + krb5_boolean zero_password; + krb5_boolean restrict_creds; + krb5_deltat lifetime, rlife; + + if (argc == 0) + exit(1); + + params = (char **) xcalloc (2, sizeof (char *)); + params[1] = NULL; + + unsetenv ("KRB5_CONFIG"); + + retval = init_ksu_context(&ksu_context); + if (retval) { + com_err(argv[0], retval, _("while initializing krb5")); + exit(1); + } + + retval = krb5_get_init_creds_opt_alloc(ksu_context, &options); + if (retval) { + com_err(argv[0], retval, _("while initializing krb5")); + exit(1); + } + + if (strrchr(argv[0], '/')) + argv[0] = strrchr(argv[0], '/')+1; + prog_name = argv[0]; + if (strlen (prog_name) > 50) { + /* this many chars *after* last / ?? */ + com_err(prog_name, 0, + _("program name too long - quitting to avoid triggering " + "system logging bugs")); + exit (1); + } + + +#ifndef LOG_NDELAY +#define LOG_NDELAY 0 +#endif + +#ifndef LOG_AUTH /* 4.2 syslog */ + openlog(prog_name, LOG_PID|LOG_NDELAY); +#else + openlog(prog_name, LOG_PID | LOG_NDELAY, LOG_AUTH); +#endif /* 4.2 syslog */ + + + if (( argc == 1) || (argv[1][0] == '-')){ + target_user = xstrdup("root"); + pargc = argc; + pargv = argv; + } else { + target_user = xstrdup(argv[1]); + pargc = argc -1; + + if ((pargv =(char **) calloc(pargc +1,sizeof(char *)))==NULL){ + com_err(prog_name, errno, _("while allocating memory")); + exit(1); + } + + pargv[pargc] = NULL; + pargv[0] = argv[0]; + + for(i =1; i< pargc; i ++){ + pargv[i] = argv[i + 1]; + } + } + + if (krb5_seteuid (ruid)) { + com_err (prog_name, errno, _("while setting euid to source user")); + exit (1); + } + while (!done && + (option = getopt(pargc, pargv,"n:c:r:a:zZDfFpPkql:e:")) != -1) { + switch (option) { + case 'r': + if (strlen (optarg) >= 14) + optarg = "bad-time"; + retval = krb5_string_to_deltat(optarg, &rlife); + if (retval != 0 || rlife == 0) { + fprintf(stderr, _("Bad lifetime value (%s hours?)\n"), optarg); + errflg++; + } + krb5_get_init_creds_opt_set_renew_life(options, rlife); + break; + case 'a': + /* when integrating this remember to pass in pargc, pargv and + take care of params argument */ + optind --; + if (auth_debug){printf("Before get_params optind=%d\n", optind);} + + if ((retval = get_params( & optind, pargc, pargv, ¶ms))){ + com_err(prog_name, retval, _("when gathering parameters")); + errflg++; + } + if(auth_debug){ printf("After get_params optind=%d\n", optind);} + done = 1; + break; + case 'p': + krb5_get_init_creds_opt_set_proxiable(options, 1); + break; + case 'P': + krb5_get_init_creds_opt_set_proxiable(options, 0); + break; + case 'f': + krb5_get_init_creds_opt_set_forwardable(options, 1); + break; + case 'F': + krb5_get_init_creds_opt_set_forwardable(options, 0); + break; + case 'k': + keep_target_cache =1; + break; + case 'q': + quiet =1; + break; + case 'l': + if (strlen (optarg) >= 14) + optarg = "bad-time"; + retval = krb5_string_to_deltat(optarg, &lifetime); + if (retval != 0 || lifetime == 0) { + fprintf(stderr, _("Bad lifetime value (%s hours?)\n"), optarg); + errflg++; + } + krb5_get_init_creds_opt_set_tkt_life(options, lifetime); + break; + case 'n': + if ((retval = krb5_parse_name(ksu_context, optarg, &client))){ + com_err(prog_name, retval, _("when parsing name %s"), optarg); + errflg++; + } + given_princ = TRUE; + break; +#ifdef DEBUG + case 'D': + auth_debug = 1; + break; +#endif + case 'z': + some_rest_copy = 1; + if(all_rest_copy) { + fprintf(stderr, + _("-z option is mutually exclusive with -Z.\n")); + errflg++; + } + break; + case 'Z': + all_rest_copy = 1; + if(some_rest_copy) { + fprintf(stderr, + _("-Z option is mutually exclusive with -z.\n")); + errflg++; + } + break; + case 'c': + if (cc_source_tag == NULL) { + cc_source_tag = xstrdup(optarg); + if ( strchr(cc_source_tag, ':')){ + cc_source_tag_tmp = strchr(cc_source_tag, ':') + 1; + + if (!ks_ccache_name_is_initialized(ksu_context, + cc_source_tag)) { + com_err(prog_name, errno, + _("while looking for credentials cache %s"), + cc_source_tag_tmp); + exit (1); + } + } + else { + fprintf(stderr, _("malformed credential cache name %s\n"), + cc_source_tag); + errflg++; + } + + } else { + fprintf(stderr, _("Only one -c option allowed\n")); + errflg++; + } + break; + case 'e': + cmd = xstrdup(optarg); + if(auth_debug){printf("Before get_params optind=%d\n", optind);} + if ((retval = get_params( & optind, pargc, pargv, ¶ms))){ + com_err(prog_name, retval, _("when gathering parameters")); + errflg++; + } + if(auth_debug){printf("After get_params optind=%d\n", optind);} + done = 1; + + if (auth_debug){ + fprintf(stderr,"Command to be executed: %s\n", cmd); + } + break; + case '?': + default: + errflg++; + break; + } + } + + if (errflg) { + usage(); + exit(2); + } + + if (optind != pargc ){ + usage(); + exit(2); + } + + if (auth_debug){ + for(j=1; params[j] != NULL; j++){ + fprintf (stderr,"params[%d]= %s\n", j,params[j]); + } + } + + /***********************************/ + source_user = getlogin(); /*checks for the the login name in /etc/utmp*/ + + /* verify that that the user exists and get his passwd structure */ + + if (source_user == NULL ||(pwd = getpwnam(source_user)) == NULL || + pwd->pw_uid != ruid){ + pwd = getpwuid(ruid); + } + + if (pwd == NULL) { + fprintf(stderr, _("ksu: who are you?\n")); + exit(1); + } + if (pwd->pw_uid != ruid) { + fprintf (stderr, _("Your uid doesn't match your passwd entry?!\n")); + exit (1); + } + /* Okay, now we have *some* passwd entry that matches the + current real uid. */ + + /* allocate space and copy the usernamane there */ + source_user = xstrdup(pwd->pw_name); + source_uid = pwd->pw_uid; + + if (!strcmp(SOURCE_USER_LOGIN, target_user)){ + target_user = xstrdup (source_user); + } + + if ((target_pwd = getpwnam(target_user)) == NULL){ + fprintf(stderr, _("ksu: unknown login %s\n"), target_user); + exit(1); + } + target_uid = target_pwd->pw_uid; + + init_auth_names(target_pwd->pw_dir); + + /***********************************/ + + if (cc_source_tag == NULL){ + cc_source_tag = krb5_cc_default_name(ksu_context); + cc_source_tag_tmp = strchr(cc_source_tag, ':'); + if (cc_source_tag_tmp == 0) + cc_source_tag_tmp = cc_source_tag; + else + cc_source_tag_tmp++; + } + + /* get a handle for the cache */ + if ((retval = krb5_cc_resolve(ksu_context, cc_source_tag, &cc_source))){ + com_err(prog_name, retval, _("while getting source cache")); + exit(1); + } + + if ((retval = get_best_princ_for_target(ksu_context, source_uid, + target_uid, source_user, + target_user, cc_source, + options, cmd, localhostname, + &client, &hp))){ + com_err(prog_name,retval, _("while selecting the best principal")); + exit(1); + } + + /* We may be running as either source or target, depending on + what happened; become source.*/ + if ( geteuid() != source_uid) { + if (krb5_seteuid(0) || krb5_seteuid(source_uid) ) { + com_err(prog_name, errno, _("while returning to source uid after " + "finding best principal")); + exit(1); + } + } + + if (auth_debug){ + if (hp){ + fprintf(stderr, + "GET_best_princ_for_target result: NOT AUTHORIZED\n"); + }else{ + fprintf(stderr, + "GET_best_princ_for_target result-best principal "); + plain_dump_principal (ksu_context, client); + fprintf(stderr,"\n"); + } + } + + if (hp){ + if (gb_err) fprintf(stderr, "%s", gb_err); + fprintf(stderr, _("account %s: authorization failed\n"), target_user); + + if (cmd != NULL) { + syslog(LOG_WARNING, + "Account %s: authorization for %s for execution of %s failed", + target_user, source_user, cmd); + } else { + syslog(LOG_WARNING, "Account %s: authorization of %s failed", + target_user, source_user); + } + + exit(1); + } + + if (auth_debug) + fprintf(stderr, " source cache = %s\n", cc_source_tag); + + /* + * After proper authentication and authorization, populate a cache for the + * target user. + */ + + /* + * We read the set of creds we want to copy from the source ccache as the + * source uid, become root for authentication, and then become the target + * user to handle authorization and creating the target user's cache. + */ + + /* if root ksu's to a regular user, then + then only the credentials for that particular user + should be copied */ + + restrict_creds = (source_uid == 0) && (target_uid != 0); + retval = krb5_parse_name(ksu_context, KS_TEMPORARY_PRINC, &tmp_princ); + if (retval) { + com_err(prog_name, retval, _("while parsing temporary name")); + exit(1); + } + retval = krb5_cc_resolve(ksu_context, KS_TEMPORARY_CACHE, &cc_tmp); + if (retval) { + com_err(prog_name, retval, _("while creating temporary cache")); + exit(1); + } + retval = krb5_ccache_copy(ksu_context, cc_source, tmp_princ, cc_tmp, + restrict_creds, client, &stored); + if (retval) { + com_err(prog_name, retval, _("while copying cache %s to %s"), + krb5_cc_get_name(ksu_context, cc_source), KS_TEMPORARY_CACHE); + exit(1); + } + krb5_cc_close(ksu_context, cc_source); + + krb5_get_init_creds_opt_set_out_ccache(ksu_context, options, cc_tmp); + + /* Become root for authentication*/ + + if (krb5_seteuid(0)) { + com_err(prog_name, errno, _("while reclaiming root uid")); + exit(1); + } + + if ((source_uid == 0) || (target_uid == source_uid)){ +#ifdef GET_TGT_VIA_PASSWD + if (!all_rest_copy && given_princ && client != NULL && !stored) { + fprintf(stderr, _("WARNING: Your password may be exposed if you " + "enter it here and are logged\n")); + fprintf(stderr, _(" in remotely using an unsecure " + "(non-encrypted) channel.\n")); + if (ksu_get_tgt_via_passwd(ksu_context, client, options, + &zero_password, NULL) == FALSE) { + + if (zero_password == FALSE){ + fprintf(stderr, _("Goodbye\n")); + exit(1); + } + + fprintf(stderr, _("Could not get a tgt for ")); + plain_dump_principal (ksu_context, client); + fprintf(stderr, "\n"); + + } + stored = TRUE; + } +#endif /* GET_TGT_VIA_PASSWD */ + } + + /* if the user is root or same uid then authentication is not necessary, + root gets in automatically */ + + if (source_uid && (source_uid != target_uid)) { + char * client_name; + + auth_val = krb5_auth_check(ksu_context, client, localhostname, + options, target_user, cc_tmp, + &path_passwd, target_uid); + + /* if Kerberos authentication failed then exit */ + if (auth_val ==FALSE){ + fprintf(stderr, _("Authentication failed.\n")); + syslog(LOG_WARNING, "'%s %s' authentication failed for %s%s", + prog_name,target_user,source_user,ontty()); + exit(1); + } + stored = TRUE; + + if ((retval = krb5_unparse_name(ksu_context, client, &client_name))) { + com_err(prog_name, retval, _("When unparsing name")); + exit(1); + } + + print_status(_("Authenticated %s\n"), client_name); + syslog(LOG_NOTICE,"'%s %s' authenticated %s for %s%s", + prog_name,target_user,client_name, + source_user,ontty()); + + /* Run authorization as target.*/ + if (krb5_seteuid(target_uid)) { + com_err(prog_name, errno, _("while switching to target for " + "authorization check")); + exit(1); + } + + if ((retval = krb5_authorization(ksu_context, client,target_user, + cmd, &authorization_val, &exec_cmd))){ + com_err(prog_name,retval, _("while checking authorization")); + krb5_seteuid(0); /*So we have some chance of sweeping up*/ + exit(1); + } + + if (krb5_seteuid(0)) { + com_err(prog_name, errno, _("while switching back from target " + "after authorization check")); + exit(1); + } + if (authorization_val == TRUE){ + + if (cmd) { + print_status(_("Account %s: authorization for %s for " + "execution of\n"), target_user, client_name); + print_status(_(" %s successful\n"), exec_cmd); + syslog(LOG_NOTICE, + "Account %s: authorization for %s for execution of %s successful", + target_user, client_name, exec_cmd); + + }else{ + print_status(_("Account %s: authorization for %s " + "successful\n"), target_user, client_name); + syslog(LOG_NOTICE, + "Account %s: authorization for %s successful", + target_user, client_name); + } + }else { + if (cmd){ + if (exec_cmd){ /* was used to pass back the error msg */ + fprintf(stderr, "%s", exec_cmd ); + syslog(LOG_WARNING, "%s",exec_cmd); + } + fprintf(stderr, _("Account %s: authorization for %s for " + "execution of %s failed\n"), + target_user, client_name, cmd ); + syslog(LOG_WARNING, + "Account %s: authorization for %s for execution of %s failed", + target_user, client_name, cmd ); + + }else{ + fprintf(stderr, _("Account %s: authorization of %s failed\n"), + target_user, client_name); + syslog(LOG_WARNING, + "Account %s: authorization of %s failed", + target_user, client_name); + + } + + exit(1); + } + } + + if( some_rest_copy){ + retval = krb5_ccache_filter(ksu_context, cc_tmp, client); + if (retval) { + com_err(prog_name,retval, _("while calling cc_filter")); + exit(1); + } + } + + if (all_rest_copy){ + retval = krb5_cc_initialize(ksu_context, cc_tmp, tmp_princ); + if (retval) { + com_err(prog_name, retval, _("while erasing target cache")); + exit(1); + } + stored = FALSE; + } + + /* get the shell of the user, this will be the shell used by su */ + target_pwd = getpwnam(target_user); + + if (target_pwd->pw_shell) + shell = xstrdup(target_pwd->pw_shell); + else { + shell = _DEF_CSH; /* default is cshell */ + } + +#ifdef HAVE_GETUSERSHELL + + /* insist that the target login uses a standard shell (root is omitted) */ + + if (!standard_shell(target_pwd->pw_shell) && source_uid) { + fprintf(stderr, _("ksu: permission denied (shell).\n")); + exit(1); + } +#endif /* HAVE_GETUSERSHELL */ + + if (target_pwd->pw_uid){ + + if(set_env_var("USER", target_pwd->pw_name)){ + fprintf(stderr, + _("ksu: couldn't set environment variable USER\n")); + exit(1); + } + } + + if(set_env_var( "HOME", target_pwd->pw_dir)){ + fprintf(stderr, _("ksu: couldn't set environment variable HOME\n")); + exit(1); + } + + if(set_env_var( "SHELL", shell)){ + fprintf(stderr, _("ksu: couldn't set environment variable SHELL\n")); + exit(1); + } + + /* set permissions */ + if (setgid(target_pwd->pw_gid) < 0) { + perror("ksu: setgid"); + exit(1); + } + + if (initgroups(target_user, target_pwd->pw_gid)) { + fprintf(stderr, _("ksu: initgroups failed.\n")); + exit(1); + } + + if ( ! strcmp(target_user, source_user)){ + print_status(_("Leaving uid as %s (%ld)\n"), + target_user, (long) target_pwd->pw_uid); + }else{ + print_status(_("Changing uid to %s (%ld)\n"), + target_user, (long) target_pwd->pw_uid); + } + +#ifdef HAVE_SETLUID + /* + * If we're on a system which keeps track of login uids, then + * set the login uid. If this fails this opens up a problem on DEC OSF + * with C2 enabled. + */ + if (setluid((uid_t) pwd->pw_uid) < 0) { + perror("setluid"); + exit(1); + } +#endif /* HAVE_SETLUID */ + + if (setuid(target_pwd->pw_uid) < 0) { + perror("ksu: setuid"); + exit(1); + } + + retval = resolve_target_cache(ksu_context, client, &cc_target, &cc_reused); + if (retval) + exit(1); + retval = krb5_cc_get_full_name(ksu_context, cc_target, &cc_target_tag); + if (retval) { + com_err(prog_name, retval, _("while getting name of target ccache")); + sweep_up(ksu_context, cc_target); + exit(1); + } + if (auth_debug) + fprintf(stderr, " target cache = %s\n", cc_target_tag); + if (cc_reused) + keep_target_cache = TRUE; + + if (stored) { + retval = krb5_ccache_copy(ksu_context, cc_tmp, client, cc_target, + FALSE, client, &stored); + if (retval) { + com_err(prog_name, retval, _("while copying cache %s to %s"), + KS_TEMPORARY_CACHE, cc_target_tag); + exit(1); + } + + if (!ks_ccache_is_initialized(ksu_context, cc_target)) { + com_err(prog_name, errno, + _("%s does not have correct permissions for %s, " + "%s aborted"), target_user, cc_target_tag, prog_name); + exit(1); + } + } + + krb5_free_string(ksu_context, cc_target_tag); + + /* Set the cc env name to target. */ + retval = set_ccname_env(ksu_context, cc_target); + if (retval != 0) { + sweep_up(ksu_context, cc_target); + exit(1); + } + + if (cmd){ + if ((source_uid == 0) || (source_uid == target_uid )){ + exec_cmd = cmd; + } + + if( !exec_cmd){ + fprintf(stderr, _("Internal error: command %s did not get " + "resolved\n"), cmd); + exit(1); + } + + params[0] = exec_cmd; + } + else{ + params[0] = shell; + } + + if (auth_debug){ + fprintf(stderr, "program to be execed %s\n",params[0]); + } + + if( keep_target_cache ) { + execv(params[0], params); + com_err(prog_name, errno, _("while trying to execv %s"), params[0]); + sweep_up(ksu_context, cc_target); + exit(1); + }else{ + statusp = 1; + switch ((child_pid = fork())) { + default: + if (auth_debug){ + printf(" The child pid is %ld\n", (long) child_pid); + printf(" The parent pid is %ld\n", (long) getpid()); + } + while ((ret_pid = waitpid(child_pid, &statusp, WUNTRACED)) != -1) { + if (WIFSTOPPED(statusp)) { + child_pgrp = tcgetpgrp(1); + kill(getpid(), SIGSTOP); + tcsetpgrp(1, child_pgrp); + kill(child_pid, SIGCONT); + statusp = 1; + continue; + } + break; + } + if (auth_debug){ + printf("The exit status of the child is %d\n", statusp); + } + if (ret_pid == -1) { + com_err(prog_name, errno, _("while calling waitpid")); + } + sweep_up(ksu_context, cc_target); + exit (statusp); + case -1: + com_err(prog_name, errno, _("while trying to fork.")); + sweep_up(ksu_context, cc_target); + exit (1); + case 0: + execv(params[0], params); + com_err(prog_name, errno, _("while trying to execv %s"), + params[0]); + exit (1); + } + } +} + +static krb5_error_code +init_ksu_context(krb5_context *context_out) +{ + krb5_error_code retval; + const char *env_ccname; + krb5_context context; + + *context_out = NULL; + + retval = krb5_init_secure_context(&context); + if (retval) + return retval; + + /* We want to obey KRB5CCNAME in this context even though this is a setuid + * program. (It will only be used when operating as the real uid.) */ + env_ccname = getenv(KRB5_ENV_CCNAME); + if (env_ccname != NULL) { + retval = krb5_cc_set_default_name(context, env_ccname); + if (retval) { + krb5_free_context(context); + return retval; + } + } + + *context_out = context; + return 0; +} + +/* Set KRB5CCNAME in the environment to point to ccache. Print an error + * message on failure. */ +static krb5_error_code +set_ccname_env(krb5_context ksu_context, krb5_ccache ccache) +{ + krb5_error_code retval; + char *ccname; + + retval = krb5_cc_get_full_name(ksu_context, ccache, &ccname); + if (retval) { + com_err(prog_name, retval, _("while reading cache name from ccache")); + return retval; + } + if (set_env_var(KRB5_ENV_CCNAME, ccname)) { + retval = errno; + fprintf(stderr, + _("ksu: couldn't set environment variable %s\n"), + KRB5_ENV_CCNAME); + } + krb5_free_string(ksu_context, ccname); + return retval; +} + +/* + * Get the configured default ccache name. Unset KRB5CCNAME and force a + * recomputation so we don't use values for the source user. Print an error + * message on failure. + */ +static krb5_error_code +get_configured_defccname(krb5_context context, char **target_out) +{ + krb5_error_code retval; + const char *defname; + char *target = NULL; + + *target_out = NULL; + + unsetenv(KRB5_ENV_CCNAME); + + /* Make sure we don't have a cached value for a different uid. */ + retval = krb5_cc_set_default_name(context, NULL); + if (retval != 0) { + com_err(prog_name, retval, _("while resetting target ccache name")); + return retval; + } + + defname = krb5_cc_default_name(context); + if (defname != NULL) { + if (strchr(defname, ':') != NULL) { + target = strdup(defname); + } else { + if (asprintf(&target, "FILE:%s", defname) < 0) + target = NULL; + } + } + if (target == NULL) { + com_err(prog_name, ENOMEM, _("while determining target ccache name")); + return ENOMEM; + } + *target_out = target; + return 0; +} + +/* Determine where the target user's creds should be stored. Print an error + * message on failure. */ +static krb5_error_code +resolve_target_cache(krb5_context context, krb5_principal princ, + krb5_ccache *ccache_out, krb5_boolean *ccache_reused) +{ + krb5_error_code retval; + krb5_boolean switchable, reused = FALSE; + krb5_ccache ccache = NULL; + char *sep, *ccname = NULL, *sym = NULL, *target; + + *ccache_out = NULL; + *ccache_reused = FALSE; + + retval = get_configured_defccname(context, &target); + if (retval != 0) + return retval; + + /* Check if the configured default name uses a switchable type. */ + sep = strchr(target, ':'); + *sep = '\0'; + switchable = krb5_cc_support_switch(context, target); + *sep = ':'; + + if (!switchable) { + /* Try to avoid destroying an in-use target ccache by coming up with + * the name of a cache that doesn't exist yet. */ + do { + free(ccname); + retval = gen_sym(context, &sym); + if (retval) { + com_err(prog_name, retval, + _("while generating part of the target ccache name")); + return retval; + } + if (asprintf(&ccname, "%s.%s", target, sym) < 0) { + retval = ENOMEM; + free(sym); + com_err(prog_name, retval, _("while allocating memory for the " + "target ccache name")); + goto cleanup; + } + free(sym); + } while (ks_ccache_name_is_initialized(context, ccname)); + retval = krb5_cc_resolve(context, ccname, &ccache); + } else { + /* Look for a cache in the collection that we can reuse. */ + retval = krb5_cc_cache_match(context, princ, &ccache); + if (retval == 0) { + reused = TRUE; + } else { + /* There isn't one, so create a new one. */ + *sep = '\0'; + retval = krb5_cc_new_unique(context, target, NULL, &ccache); + *sep = ':'; + if (retval) { + com_err(prog_name, retval, + _("while creating new target ccache")); + goto cleanup; + } + retval = krb5_cc_initialize(context, ccache, princ); + if (retval) { + com_err(prog_name, retval, + _("while initializing target cache")); + goto cleanup; + } + } + } + + *ccache_out = ccache; + *ccache_reused = reused; + +cleanup: + free(target); + return retval; +} + +#ifdef HAVE_GETUSERSHELL + +int standard_shell(sh) + char *sh; +{ + char *cp; + char *getusershell(); + + while ((cp = getusershell()) != NULL) + if (!strcmp(cp, sh)) + return (1); + return (0); +} + +#endif /* HAVE_GETUSERSHELL */ + +static char * ontty() +{ + char *p; + static char buf[MAXPATHLEN + 5]; + int result; + + buf[0] = 0; + if ((p = ttyname(STDERR_FILENO))) { + result = snprintf(buf, sizeof(buf), " on %s", p); + if (SNPRINTF_OVERFLOW(result, sizeof(buf))) { + fprintf(stderr, _("terminal name %s too long\n"), p); + exit (1); + } + } + return (buf); +} + + +static int set_env_var(name, value) + char *name; + char *value; +{ + char * env_var_buf; + + asprintf(&env_var_buf,"%s=%s",name, value); + return putenv(env_var_buf); + +} + +static void sweep_up(context, cc) + krb5_context context; + krb5_ccache cc; +{ + krb5_error_code retval; + + krb5_seteuid(0); + if (krb5_seteuid(target_uid) < 0) { + com_err(prog_name, errno, + _("while changing to target uid for destroying ccache")); + exit(1); + } + + if (ks_ccache_is_initialized(context, cc)) { + if ((retval = krb5_cc_destroy(context, cc))) + com_err(prog_name, retval, _("while destroying cache")); + } +} + +/***************************************************************** +get_params is to be called for the -a option or -e option to + collect all params passed in for the shell or for + cmd. An array is returned containing all params. + optindex is incremented accordingly and the first + element in the returned array is reserved for the + name of the command to be executed or the name of the + shell. +*****************************************************************/ + +krb5_error_code +get_params(optindex, pargc, pargv, params) + int *optindex; + int pargc; + char **pargv; + char ***params; +{ + + int i,j; + char ** ret_params; + int size = pargc - *optindex + 2; + + if ((ret_params = (char **) calloc(size, sizeof (char *)))== NULL ){ + return ENOMEM; + } + + for (i = *optindex, j=1; i < pargc; i++,j++){ + ret_params[j] = pargv[i]; + *optindex = *optindex + 1; + } + + ret_params[size-1] = NULL; + *params = ret_params; + return 0; +} + +static +void print_status(const char *fmt, ...) +{ + va_list ap; + if (! quiet){ + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + } +} + +krb5_error_code +ksu_tgtname(context, server, client, tgtprinc) + krb5_context context; + const krb5_data *server, *client; + krb5_principal *tgtprinc; +{ + return krb5_build_principal_ext(context, tgtprinc, client->length, client->data, + KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, + server->length, server->data, + 0); +} diff --git a/krb5-1.21.3/src/clients/ksu/setenv.c b/krb5-1.21.3/src/clients/ksu/setenv.c new file mode 100644 index 00000000..c7bd369b --- /dev/null +++ b/krb5-1.21.3/src/clients/ksu/setenv.c @@ -0,0 +1,174 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +/* + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* based on @(#)setenv.c 5.2 (Berkeley) 6/27/88 */ + +#include "autoconf.h" +#include +#include +#include +#include + +static char *_findenv(char *, int *); + +#ifndef HAVE_SETENV +extern int setenv(char *, char *, int); +#endif +#ifndef HAVE_UNSETENV +extern void unsetenv(char *); +#endif + +/* + * setenv -- + * Set the value of the environmental variable "name" to be + * "value". If rewrite is set, replace any current value. + */ +#ifndef HAVE_SETENV +int +setenv(name, value, rewrite) + char *name, *value; + int rewrite; +{ + extern char **environ; + static int alloced; /* if allocated space before */ + char *C; + int l_value, offset; + + if (*value == '=') /* no `=' in value */ + ++value; + l_value = strlen(value); + if ((C = _findenv(name, &offset))) { /* find if already exists */ + if (!rewrite) + return(0); + if (strlen(C) >= l_value) { /* old larger; copy over */ + while ((*C++ = *value++)); + return(0); + } + } + else { /* create new slot */ + int cnt; + char **P; + + for (P = environ, cnt = 0; *P; ++P, ++cnt); + if (alloced) { /* just increase size */ + environ = (char **)realloc((char *)environ, + (u_int)(sizeof(char *) * (cnt + 2))); + if (!environ) + return(-1); + } + else { /* get new space */ + alloced = 1; /* copy old entries into it */ + P = (char **)malloc((u_int)(sizeof(char *) * + (cnt + 2))); + if (!P) + return(-1); + memcpy(P, environ, cnt * sizeof(char *)); + environ = P; + } + environ[cnt + 1] = NULL; + offset = cnt; + } + for (C = name; *C && *C != '='; ++C); /* no `=' in name */ + if (!(environ[offset] = /* name + `=' + value */ + malloc((u_int)((int)(C - name) + l_value + 2)))) + return(-1); + for (C = environ[offset]; (*C = *name++) &&( *C != '='); ++C); + for (*C++ = '='; (*C++ = *value++) != NULL;); + return(0); +} +#endif + +/* + * unsetenv(name) -- + * Delete environmental variable "name". + */ +#ifndef HAVE_UNSETENV +void +unsetenv(name) + char *name; +{ + extern char **environ; + char **P; + int offset; + + while (_findenv(name, &offset)) /* if set multiple times */ + for (P = &environ[offset];; ++P) + if (!(*P = *(P + 1))) + break; +} +#endif + +/* based on @(#)getenv.c 5.5 (Berkeley) 6/27/88 */ + +/* + * getenv -- + * Returns ptr to value associated with name, if any, else NULL. + */ +#ifndef HAVE_GETENV +char * +getenv(name) + char *name; +{ + int offset; + + return(_findenv(name, &offset)); +} +#endif + +/* + * _findenv -- + * Returns pointer to value associated with name, if any, else NULL. + * Sets offset to be the offset of the name/value combination in the + * environmental array, for use by setenv(3) and unsetenv(3). + * Explicitly removes '=' in argument name. + * + */ +static char * +_findenv(name, offset) + char *name; + int *offset; +{ + extern char **environ; + int len; + char **P, *C; + + for (C = name, len = 0; *C && *C != '='; ++C, ++len); + for (P = environ; *P; ++P) + if (!strncmp(*P, name, len)) + if (*(C = *P + len) == '=') { + *offset = P - environ; + return(++C); + } + return(NULL); +} diff --git a/krb5-1.21.3/src/clients/ksu/xmalloc.c b/krb5-1.21.3/src/clients/ksu/xmalloc.c new file mode 100644 index 00000000..430a6b3b --- /dev/null +++ b/krb5-1.21.3/src/clients/ksu/xmalloc.c @@ -0,0 +1,80 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* clients/ksu/xmalloc.c - Exit-on-failure allocation wrappers */ +/* + * Copyright 1999 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-platform.h" +#include "ksu.h" + +void *xmalloc (size_t sz) +{ + void *ret = malloc (sz); + if (ret == 0 && sz != 0) { + perror (prog_name); + exit (1); + } + return ret; +} + +void *xrealloc (void *old, size_t newsz) +{ + void *ret = realloc (old, newsz); + if (ret == 0 && newsz != 0) { + perror (prog_name); + exit (1); + } + return ret; +} + +void *xcalloc (size_t nelts, size_t eltsz) +{ + void *ret = calloc (nelts, eltsz); + if (ret == 0 && nelts != 0 && eltsz != 0) { + perror (prog_name); + exit (1); + } + return ret; +} + +char *xstrdup (const char *src) +{ + size_t len = strlen (src) + 1; + char *dst = xmalloc (len); + memcpy (dst, src, len); + return dst; +} + +char *xasprintf (const char *format, ...) +{ + char *out; + va_list args; + + va_start (args, format); + if (vasprintf(&out, format, args) < 0) { + perror (prog_name); + exit (1); + } + va_end(args); + return out; +} diff --git a/krb5-1.21.3/src/clients/kswitch/Makefile.in b/krb5-1.21.3/src/clients/kswitch/Makefile.in new file mode 100644 index 00000000..e3d36806 --- /dev/null +++ b/krb5-1.21.3/src/clients/kswitch/Makefile.in @@ -0,0 +1,33 @@ +mydir=clients$(S)kswitch +BUILDTOP=$(REL)..$(S).. + +SRCS=kswitch.c + +##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc +##WIN32##RCFLAGS=$(CPPFLAGS) -I$(top_srcdir) -D_WIN32 -DRES_ONLY + +##WIN32##KSWITCH=$(OUTPRE)kswitch.exe + +##WIN32##EXERES=$(KSWITCH:.exe=.res) + +##WIN32##$(EXERES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DKSWITCH_APP -fo $@ -r $** + +all-unix: kswitch +##WIN32##all-windows: $(KSWITCH) + +kswitch: kswitch.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ kswitch.o $(KRB5_BASE_LIBS) + +##WIN32##$(KSWITCH): $(OUTPRE)kswitch.obj $(SLIB) $(KLIB) $(CLIB) $(EXERES) +##WIN32## link $(EXE_LINKOPTS) -out:$@ $** +##WIN32## $(_VC_MANIFEST_EMBED_EXE) + +clean-unix:: + $(RM) kswitch.o kswitch + +install-unix: + for f in kswitch; do \ + $(INSTALL_PROGRAM) $$f \ + $(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \ + done diff --git a/krb5-1.21.3/src/clients/kswitch/deps b/krb5-1.21.3/src/clients/kswitch/deps new file mode 100644 index 00000000..0bb88b62 --- /dev/null +++ b/krb5-1.21.3/src/clients/kswitch/deps @@ -0,0 +1,13 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kswitch.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kswitch.c diff --git a/krb5-1.21.3/src/clients/kswitch/kswitch.c b/krb5-1.21.3/src/clients/kswitch/kswitch.c new file mode 100644 index 00000000..9cba7cb2 --- /dev/null +++ b/krb5-1.21.3/src/clients/kswitch/kswitch.c @@ -0,0 +1,129 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* clients/kswitch/kswitch.c - Switch primary credential cache */ +/* + * Copyright 2011 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include + +#ifndef _WIN32 +#define GET_PROGNAME(x) (strrchr((x), '/') ? strrchr((x), '/')+1 : (x)) +#else +#define GET_PROGNAME(x) max(max(strrchr((x), '/'), strrchr((x), '\\')) + 1,(x)) +#endif + +static char *progname; + +static void +usage(void) +{ + fprintf(stderr, _("Usage: %s {-c cache_name | -p principal}\n"), progname); + fprintf(stderr, _("\t-c specify name of credentials cache\n")); + fprintf(stderr, _("\t-p specify name of principal\n")); + exit(2); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + int c; + krb5_ccache cache = NULL; + krb5_principal princ = NULL; + const char *cache_name = NULL, *princ_name = NULL; + krb5_boolean errflag = FALSE; + + setlocale(LC_ALL, ""); + progname = GET_PROGNAME(argv[0]); + + while ((c = getopt(argc, argv, "c:p:")) != -1) { + switch (c) { + case 'c': + case 'p': + if (cache_name || princ_name) { + fprintf(stderr, _("Only one -c or -p option allowed\n")); + errflag = TRUE; + } else if (c == 'c') { + cache_name = optarg; + } else { + princ_name = optarg; + } + break; + case '?': + default: + errflag = TRUE; + break; + } + } + + if (optind != argc) + errflag = TRUE; + + if (!cache_name && !princ_name) { + fprintf(stderr, _("One of -c or -p must be specified\n")); + errflag = TRUE; + } + + if (errflag) + usage(); + + ret = krb5_init_context(&context); + if (ret) { + com_err(progname, ret, _("while initializing krb5")); + exit(1); + } + + if (cache_name) { + ret = krb5_cc_resolve(context, cache_name, &cache); + if (ret != 0) { + com_err(progname, ret, _("while resolving %s"), cache_name); + exit(1); + } + } else { + ret = krb5_parse_name(context, princ_name, &princ); + if (ret) { + com_err(progname, ret, _("while parsing principal name %s"), + princ_name); + exit(1); + } + ret = krb5_cc_cache_match(context, princ, &cache); + if (ret) { + com_err(progname, ret, _("while searching for ccache for %s"), + princ_name); + exit(1); + } + krb5_free_principal(context, princ); + } + + ret = krb5_cc_switch(context, cache); + if (ret != 0) { + com_err(progname, ret, _("while switching to credential cache")); + exit(1); + } + + krb5_cc_close(context, cache); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/clients/kvno/Makefile.in b/krb5-1.21.3/src/clients/kvno/Makefile.in new file mode 100644 index 00000000..5ba87727 --- /dev/null +++ b/krb5-1.21.3/src/clients/kvno/Makefile.in @@ -0,0 +1,39 @@ +mydir=clients$(S)kvno +BUILDTOP=$(REL)..$(S).. + +##WIN32##LOCALINCLUDES=-I$(BUILDTOP)\util\windows\ + +SRCS=kvno.c + +##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc +##WIN32##RCFLAGS=$(CPPFLAGS) -I$(top_srcdir) -D_WIN32 -DRES_ONLY + +##WIN32##KVNO=$(OUTPRE)kvno.exe + +##WIN32##EXERES=$(KVNO:.exe=.res) + +##WIN32##$(EXERES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DKVNO_APP -fo $@ -r $** + +all-unix: kvno + +##WIN32##all-windows: $(KVNO) + +kvno: kvno.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ kvno.o $(KRB5_BASE_LIBS) + +##WIN32##$(KVNO): $(OUTPRE)kvno.obj $(SLIB) $(KLIB) $(CLIB) $(EXERES) +##WIN32## link $(EXE_LINKOPTS) /out:$@ $** +##WIN32## $(_VC_MANIFEST_EMBED_EXE) + +check-pytests: kvno + $(RUNPYTEST) $(srcdir)/t_kvno.py $(PYTESTFLAGS) + +clean-unix:: + $(RM) kvno.o kvno + +install-unix: + for f in kvno; do \ + $(INSTALL_PROGRAM) $$f \ + $(DESTDIR)$(CLIENT_BINDIR)/`echo $$f|sed '$(transform)'`; \ + done diff --git a/krb5-1.21.3/src/clients/kvno/deps b/krb5-1.21.3/src/clients/kvno/deps new file mode 100644 index 00000000..d37d764c --- /dev/null +++ b/krb5-1.21.3/src/clients/kvno/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kvno.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-base64.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kvno.c diff --git a/krb5-1.21.3/src/clients/kvno/kvno.c b/krb5-1.21.3/src/clients/kvno/kvno.c new file mode 100644 index 00000000..03f72f59 --- /dev/null +++ b/krb5-1.21.3/src/clients/kvno/kvno.c @@ -0,0 +1,609 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-platform.h" +#include "k5-buf.h" +#include "k5-base64.h" +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +static char *prog; +static int quiet = 0; + +static void +xusage() +{ + fprintf(stderr, _("usage: %s [-c ccache] [-e etype] [-k keytab] [-q] " + "[-u | -S sname]\n" + "\t[[{-F cert_file | {-I | -U} for_user} [-P]] | " + "--u2u ccache]\n" + "\t[--cached-only] [--no-store] [--out-cache] " + "service1 service2 ...\n"), + prog); + exit(1); +} + +static void do_v5_kvno(int argc, char *argv[], char *ccachestr, char *etypestr, + char *keytab_name, char *sname, int cached_only, + int canon, int no_store, int unknown, char *for_user, + int for_user_enterprise, char *for_user_cert_file, + int proxy, const char *out_ccname, + const char *u2u_ccname); + +#include +static void extended_com_err_fn(const char *myprog, errcode_t code, + const char *fmt, va_list args); + +int +main(int argc, char *argv[]) +{ + enum { OPTION_U2U = 256, OPTION_OUT_CACHE = 257 }; + const char *shopts = "uCc:e:hk:qPS:I:U:F:"; + int option; + char *etypestr = NULL, *ccachestr = NULL, *keytab_name = NULL; + char *sname = NULL, *for_user = NULL, *u2u_ccname = NULL; + char *for_user_cert_file = NULL, *out_ccname = NULL; + int canon = 0, unknown = 0, proxy = 0, for_user_enterprise = 0; + int impersonate = 0, cached_only = 0, no_store = 0; + struct option lopts[] = { + { "cached-only", 0, &cached_only, 1 }, + { "no-store", 0, &no_store, 1 }, + { "out-cache", 1, NULL, OPTION_OUT_CACHE }, + { "u2u", 1, NULL, OPTION_U2U }, + { NULL, 0, NULL, 0 } + }; + + setlocale(LC_ALL, ""); + set_com_err_hook(extended_com_err_fn); + + prog = strrchr(argv[0], '/'); + prog = prog ? (prog + 1) : argv[0]; + + while ((option = getopt_long(argc, argv, shopts, lopts, NULL)) != -1) { + switch (option) { + case 'C': + canon = 1; + break; + case 'c': + ccachestr = optarg; + break; + case 'e': + etypestr = optarg; + break; + case 'h': + xusage(); + break; + case 'k': + keytab_name = optarg; + break; + case 'q': + quiet = 1; + break; + case 'P': + proxy = 1; /* S4U2Proxy - constrained delegation */ + break; + case 'S': + sname = optarg; + if (unknown == 1) { + fprintf(stderr, + _("Options -u and -S are mutually exclusive\n")); + xusage(); + } + break; + case 'u': + unknown = 1; + if (sname != NULL) { + fprintf(stderr, + _("Options -u and -S are mutually exclusive\n")); + xusage(); + } + break; + case 'I': + impersonate = 1; + for_user = optarg; + break; + case 'U': + impersonate = 1; + for_user_enterprise = 1; + for_user = optarg; + break; + case 'F': + impersonate = 1; + for_user_cert_file = optarg; + break; + case OPTION_U2U: + u2u_ccname = optarg; + break; + case OPTION_OUT_CACHE: + out_ccname = optarg; + break; + case 0: + /* If this option set a flag, do nothing else now. */ + break; + default: + xusage(); + break; + } + } + + if (u2u_ccname != NULL && impersonate) { + fprintf(stderr, + _("Options --u2u and -I|-U|-F are mutually exclusive\n")); + xusage(); + } + + if (proxy) { + if (!impersonate) { + fprintf(stderr, _("Option -P (constrained delegation) requires " + "option -I|-U|-F (protocol transition)\n")); + xusage(); + } + } + + if (argc - optind < 1) + xusage(); + + do_v5_kvno(argc - optind, argv + optind, ccachestr, etypestr, keytab_name, + sname, cached_only, canon, no_store, unknown, for_user, + for_user_enterprise, for_user_cert_file, proxy, out_ccname, + u2u_ccname); + return 0; +} + +#include +static krb5_context context; +static void extended_com_err_fn(const char *myprog, errcode_t code, + const char *fmt, va_list args) +{ + const char *emsg; + + emsg = krb5_get_error_message(context, code); + fprintf(stderr, "%s: %s ", myprog, emsg); + krb5_free_error_message(context, emsg); + vfprintf(stderr, fmt, args); + fprintf(stderr, "\n"); +} + +/* Read a line from fp into buf. Trim any trailing whitespace, and return a + * pointer to the first non-whitespace character. */ +static const char * +read_line(FILE *fp, char *buf, size_t bufsize) +{ + char *end, *begin; + + if (fgets(buf, bufsize, fp) == NULL) + return NULL; + + end = buf + strlen(buf); + while (end > buf && isspace((uint8_t)end[-1])) + *--end = '\0'; + + begin = buf; + while (isspace((uint8_t)*begin)) + begin++; + + return begin; +} + +/* Read a certificate from file_name in PEM format, placing the DER + * representation of the certificate in *der_out. */ +static krb5_error_code +read_pem_file(char *file_name, krb5_data *der_out) +{ + krb5_error_code ret = 0; + FILE *fp = NULL; + const char *begin_line = "-----BEGIN CERTIFICATE-----"; + const char *end_line = "-----END ", *line; + char linebuf[256], *b64; + struct k5buf buf = EMPTY_K5BUF; + uint8_t *der_cert; + size_t dlen; + + *der_out = empty_data(); + + fp = fopen(file_name, "r"); + if (fp == NULL) + return errno; + + for (;;) { + line = read_line(fp, linebuf, sizeof(linebuf)); + if (line == NULL) { + ret = EINVAL; + k5_setmsg(context, ret, _("No begin line not found")); + goto cleanup; + } + if (strncmp(line, begin_line, strlen(begin_line)) == 0) + break; + } + + k5_buf_init_dynamic(&buf); + for (;;) { + line = read_line(fp, linebuf, sizeof(linebuf)); + if (line == NULL) { + ret = EINVAL; + k5_setmsg(context, ret, _("No end line found")); + goto cleanup; + } + + if (strncmp(line, end_line, strlen(end_line)) == 0) + break; + + /* Header lines would be expected for an actual privacy-enhanced mail + * message, but not for a certificate. */ + if (*line == '\0' || strchr(line, ':') != NULL) { + ret = EINVAL; + k5_setmsg(context, ret, _("Unexpected header line")); + goto cleanup; + } + + k5_buf_add(&buf, line); + } + + b64 = k5_buf_cstring(&buf); + if (b64 == NULL) { + ret = ENOMEM; + goto cleanup; + } + der_cert = k5_base64_decode(b64, &dlen); + if (der_cert == NULL) { + ret = EINVAL; + k5_setmsg(context, ret, _("Invalid base64")); + goto cleanup; + } + + *der_out = make_data(der_cert, dlen); + +cleanup: + fclose(fp); + k5_buf_free(&buf); + return ret; +} + +/* Request a single service ticket and display its status (unless quiet is + * set). On failure, display an error message and return non-zero. */ +static krb5_error_code +kvno(const char *name, krb5_ccache ccache, krb5_principal me, + krb5_enctype etype, krb5_keytab keytab, const char *sname, + krb5_flags options, int unknown, krb5_principal for_user_princ, + krb5_data *for_user_cert, int proxy, krb5_data *u2u_ticket, + krb5_creds **creds_out) +{ + krb5_error_code ret; + krb5_principal server = NULL; + krb5_ticket *ticket = NULL; + krb5_creds in_creds, *creds = NULL; + char *princ = NULL; + + *creds_out = NULL; + memset(&in_creds, 0, sizeof(in_creds)); + + if (sname != NULL) { + ret = krb5_sname_to_principal(context, name, sname, KRB5_NT_SRV_HST, + &server); + } else { + ret = krb5_parse_name(context, name, &server); + } + if (ret) { + if (!quiet) + com_err(prog, ret, _("while parsing principal name %s"), name); + goto cleanup; + } + if (unknown) + krb5_princ_type(context, server) = KRB5_NT_UNKNOWN; + + ret = krb5_unparse_name(context, server, &princ); + if (ret) { + com_err(prog, ret, _("while formatting parsed principal name for " + "'%s'"), name); + goto cleanup; + } + + in_creds.keyblock.enctype = etype; + + if (u2u_ticket != NULL) + in_creds.second_ticket = *u2u_ticket; + + if (for_user_princ != NULL || for_user_cert != NULL) { + if (!proxy && !krb5_principal_compare(context, me, server)) { + ret = EINVAL; + com_err(prog, ret, + _("client and server principal names must match")); + goto cleanup; + } + + in_creds.client = for_user_princ; + in_creds.server = me; + ret = krb5_get_credentials_for_user(context, options, ccache, + &in_creds, for_user_cert, &creds); + } else { + in_creds.client = me; + in_creds.server = server; + ret = krb5_get_credentials(context, options, ccache, &in_creds, + &creds); + } + + if (ret) { + com_err(prog, ret, _("while getting credentials for %s"), princ); + goto cleanup; + } + + /* We need a native ticket. */ + ret = krb5_decode_ticket(&creds->ticket, &ticket); + if (ret) { + com_err(prog, ret, _("while decoding ticket for %s"), princ); + goto cleanup; + } + + if (keytab != NULL) { + ret = krb5_server_decrypt_ticket_keytab(context, keytab, ticket); + if (ret) { + if (!quiet) { + fprintf(stderr, "%s: kvno = %d, keytab entry invalid\n", princ, + ticket->enc_part.kvno); + } + com_err(prog, ret, _("while decrypting ticket for %s"), princ); + goto cleanup; + } + if (!quiet) { + printf(_("%s: kvno = %d, keytab entry valid\n"), princ, + ticket->enc_part.kvno); + } + } else { + if (!quiet) + printf(_("%s: kvno = %d\n"), princ, ticket->enc_part.kvno); + } + + if (proxy) { + in_creds.client = creds->client; + creds->client = NULL; + krb5_free_creds(context, creds); + creds = NULL; + in_creds.server = server; + + ret = krb5_get_credentials_for_proxy(context, KRB5_GC_CANONICALIZE, + ccache, &in_creds, ticket, + &creds); + krb5_free_principal(context, in_creds.client); + if (ret) { + com_err(prog, ret, _("%s: constrained delegation failed"), + princ); + goto cleanup; + } + } + + *creds_out = creds; + creds = NULL; + +cleanup: + krb5_free_principal(context, server); + krb5_free_ticket(context, ticket); + krb5_free_creds(context, creds); + krb5_free_unparsed_name(context, princ); + return ret; +} + +/* Fetch the encoded local TGT for ccname's default client principal. */ +static krb5_error_code +get_u2u_ticket(const char *ccname, krb5_data **ticket_out) +{ + krb5_error_code ret; + krb5_ccache cc = NULL; + krb5_creds mcred, *creds = NULL; + + *ticket_out = NULL; + memset(&mcred, 0, sizeof(mcred)); + + ret = krb5_cc_resolve(context, ccname, &cc); + if (ret) + goto cleanup; + ret = krb5_cc_get_principal(context, cc, &mcred.client); + if (ret) + goto cleanup; + ret = krb5_build_principal_ext(context, &mcred.server, + mcred.client->realm.length, + mcred.client->realm.data, + KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, + mcred.client->realm.length, + mcred.client->realm.data, 0); + if (ret) + goto cleanup; + ret = krb5_get_credentials(context, KRB5_GC_CACHED, cc, &mcred, &creds); + if (ret) + goto cleanup; + + ret = krb5_copy_data(context, &creds->ticket, ticket_out); + +cleanup: + if (cc != NULL) + krb5_cc_close(context, cc); + krb5_free_cred_contents(context, &mcred); + krb5_free_creds(context, creds); + return ret; +} + +static void +do_v5_kvno(int count, char *names[], char * ccachestr, char *etypestr, + char *keytab_name, char *sname, int cached_only, int canon, + int no_store, int unknown, char *for_user, int for_user_enterprise, + char *for_user_cert_file, int proxy, const char *out_ccname, + const char *u2u_ccname) +{ + krb5_error_code ret; + int i, errors, flags, initialized = 0; + krb5_enctype etype; + krb5_ccache ccache, mcc, out_ccache = NULL; + krb5_principal me; + krb5_keytab keytab = NULL; + krb5_principal for_user_princ = NULL; + krb5_flags options = 0; + krb5_data cert_data = empty_data(), *user_cert = NULL, *u2u_ticket = NULL; + krb5_creds *creds; + + if (canon) + options |= KRB5_GC_CANONICALIZE; + if (cached_only) + options |= KRB5_GC_CACHED; + if (no_store || out_ccname != NULL) + options |= KRB5_GC_NO_STORE; + + ret = krb5_init_context(&context); + if (ret) { + com_err(prog, ret, _("while initializing krb5 library")); + exit(1); + } + + if (etypestr) { + ret = krb5_string_to_enctype(etypestr, &etype); + if (ret) { + com_err(prog, ret, _("while converting etype")); + exit(1); + } + } else { + etype = 0; + } + + if (ccachestr) + ret = krb5_cc_resolve(context, ccachestr, &ccache); + else + ret = krb5_cc_default(context, &ccache); + if (ret) { + com_err(prog, ret, _("while opening ccache")); + exit(1); + } + + if (out_ccname != NULL) { + ret = krb5_cc_resolve(context, out_ccname, &out_ccache); + if (ret) { + com_err(prog, ret, _("while resolving output ccache")); + exit(1); + } + } + + if (keytab_name != NULL) { + ret = krb5_kt_resolve(context, keytab_name, &keytab); + if (ret) { + com_err(prog, ret, _("resolving keytab %s"), keytab_name); + exit(1); + } + } + + if (for_user) { + flags = for_user_enterprise ? KRB5_PRINCIPAL_PARSE_ENTERPRISE : 0; + ret = krb5_parse_name_flags(context, for_user, flags, &for_user_princ); + if (ret) { + com_err(prog, ret, _("while parsing principal name %s"), for_user); + exit(1); + } + } + + if (for_user_cert_file != NULL) { + ret = read_pem_file(for_user_cert_file, &cert_data); + if (ret) { + com_err(prog, ret, _("while reading certificate file %s"), + for_user_cert_file); + exit(1); + } + user_cert = &cert_data; + } + + if (u2u_ccname != NULL) { + ret = get_u2u_ticket(u2u_ccname, &u2u_ticket); + if (ret) { + com_err(prog, ret, _("while getting user-to-user ticket from %s"), + u2u_ccname); + exit(1); + } + options |= KRB5_GC_USER_USER; + } + + ret = krb5_cc_get_principal(context, ccache, &me); + if (ret) { + com_err(prog, ret, _("while getting client principal name")); + exit(1); + } + + if (out_ccache != NULL) { + ret = krb5_cc_new_unique(context, "MEMORY", NULL, &mcc); + if (ret) { + com_err(prog, ret, _("while creating temporary output ccache")); + exit(1); + } + } + + errors = 0; + for (i = 0; i < count; i++) { + if (kvno(names[i], ccache, me, etype, keytab, sname, options, unknown, + for_user_princ, user_cert, proxy, u2u_ticket, &creds) != 0) { + errors++; + } else if (out_ccache != NULL) { + if (!initialized) { + ret = krb5_cc_initialize(context, mcc, creds->client); + if (ret) { + com_err(prog, ret, _("while initializing output ccache")); + exit(1); + } + initialized = 1; + } + if (count == 1) + ret = k5_cc_store_primary_cred(context, mcc, creds); + else + ret = krb5_cc_store_cred(context, mcc, creds); + if (ret) { + com_err(prog, ret, _("while storing creds in output ccache")); + exit(1); + } + } + + krb5_free_creds(context, creds); + } + + if (!errors && out_ccache != NULL) { + ret = krb5_cc_move(context, mcc, out_ccache); + if (ret) { + com_err(prog, ret, _("while writing output ccache")); + exit(1); + } + } + + if (keytab != NULL) + krb5_kt_close(context, keytab); + krb5_free_principal(context, me); + krb5_free_principal(context, for_user_princ); + krb5_cc_close(context, ccache); + krb5_free_data(context, u2u_ticket); + krb5_free_data_contents(context, &cert_data); + krb5_free_context(context); + + if (errors) + exit(1); + + exit(0); +} diff --git a/krb5-1.21.3/src/clients/kvno/t_kvno.py b/krb5-1.21.3/src/clients/kvno/t_kvno.py new file mode 100644 index 00000000..e98b90e8 --- /dev/null +++ b/krb5-1.21.3/src/clients/kvno/t_kvno.py @@ -0,0 +1,75 @@ +from k5test import * + +realm = K5Realm() + +def check_cache(ccache, expected_services): + # Fetch the klist output and skip past the header. + lines = realm.run([klist, '-c', ccache]).splitlines() + lines = lines[4:] + + # For each line not beginning with an indent, match against the + # expected service principals. + svcs = {x: True for x in expected_services} + for l in lines: + if not l.startswith('\t'): + svcprinc = l.split()[4] + if svcprinc in svcs: + del svcs[svcprinc] + else: + fail('unexpected service princ ' + svcprinc) + + if svcs: + fail('services not found in klist output: ' + ' '.join(svcs.keys())) + + +mark('no options') +realm.run([kvno, realm.user_princ], expected_msg='user@KRBTEST.COM: kvno = 1') +check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ]) + +mark('-e') +msgs = ('etypes requested in TGS request: camellia128-cts', + '/KDC has no support for encryption type') +realm.run([kvno, '-e', 'camellia128-cts', realm.host_princ], + expected_code=1, expected_trace=msgs) + +mark('--cached-only') +realm.run([kvno, '--cached-only', realm.user_princ], expected_msg='kvno = 1') +realm.run([kvno, '--cached-only', realm.host_princ], + expected_code=1, expected_msg='Matching credential not found') +check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ]) + +mark('--no-store') +realm.run([kvno, '--no-store', realm.host_princ], expected_msg='kvno = 1') +check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ]) + +mark('--out-cache') # and multiple services +out_ccache = os.path.join(realm.testdir, 'ccache.out') +realm.run([kvno, '--out-cache', out_ccache, + realm.host_princ, realm.admin_princ]) +check_cache(realm.ccache, [realm.krbtgt_princ, realm.user_princ]) +check_cache(out_ccache, [realm.host_princ, realm.admin_princ]) + +mark('--out-cache --cached-only') # tests out-cache overwriting, and -q +realm.run([kvno, '--out-cache', out_ccache, '--cached-only', realm.host_princ], + expected_code=1, expected_msg='Matching credential not found') +out = realm.run([kvno, '-q', '--out-cache', out_ccache, '--cached-only', + realm.user_princ]) +if out: + fail('unexpected kvno output with -q') +check_cache(out_ccache, [realm.user_princ]) + +mark('-U') # and -c +svc_ccache = os.path.join(realm.testdir, 'ccache.svc') +realm.run([kinit, '-k', '-c', svc_ccache, realm.host_princ]) +realm.run([kvno, '-c', svc_ccache, '-U', 'user', realm.host_princ]) +realm.run([klist, '-c', svc_ccache], expected_msg='for client user@') +realm.run([kvno, '-c', svc_ccache, '-U', 'user', '--out-cache', out_ccache, + realm.host_princ]) +out = realm.run([klist, '-c', out_ccache]) +if ('Default principal: user@KRBTEST.COM' not in out): + fail('wrong default principal in klist output') + +# More S4U options are tested in tests/gssapi/t_s4u.py. +# --u2u is tested in tests/t_u2u.py. + +success('kvno tests') diff --git a/krb5-1.21.3/src/config-files/Makefile.in b/krb5-1.21.3/src/config-files/Makefile.in new file mode 100644 index 00000000..0f2a0b2c --- /dev/null +++ b/krb5-1.21.3/src/config-files/Makefile.in @@ -0,0 +1,8 @@ +mydir=config-files +BUILDTOP=$(REL).. +all: + +install: + $(INSTALL_DATA) $(srcdir)/kdc.conf ${DESTDIR}$(EXAMPLEDIR)/kdc.conf + $(INSTALL_DATA) $(srcdir)/krb5.conf ${DESTDIR}$(EXAMPLEDIR)/krb5.conf + $(INSTALL_DATA) $(srcdir)/services.append ${DESTDIR}$(EXAMPLEDIR)/services.append diff --git a/krb5-1.21.3/src/config-files/convert-config-files b/krb5-1.21.3/src/config-files/convert-config-files new file mode 100644 index 00000000..53ddefff --- /dev/null +++ b/krb5-1.21.3/src/config-files/convert-config-files @@ -0,0 +1,84 @@ +#!/usr/bin/perl +# +# This program converts the old-style krb.conf and krb.realms files into the +# new-format krb5.conf file. It takes two arguments; the first is the krb.conf +# file, and the second is the krb.realms file. The krb5.conf file is output +# to stdout. +# +# Written by Theodore Ts'o, 4/25/95 +# + +if ($#ARGV >= 0) { + $krb_conf_file = $ARGV[0]; +} else { + $krb_conf_file = "/etc/krb.conf"; +} + +if ($#ARGV >= 1) { + $krb_realms_file = $ARGV[1]; +} else { + $krb_realms_file = "/etc/krb.realms"; +} + +open(FILE, "<$krb_conf_file") || die "Couldn't open the krb.conf file\n"; + +$_ = ; +strip; +$default_realm = $_; + +while() { + strip; + ($realm, $host, $admin) = split; + if (!defined($realmpt{$realm})) { + $realmpt{$realm} = 1; + } + $realmkdc{$realm . "##" . $realmpt{$realm}} = $host; + $realmpt{$realm}++; + if ($admin eq "admin") { + $realmadmin{$realm} = $host; + } +} + +close(FILE); + +open(FILE, "<$krb_realms_file") || die "Couldn't open krb.realms file"; + +while () { + strip; + ($domain, $realm) = split; + $domain =~ s/\.$//; + $domain =~ tr/[A-Z]/[a-z]/; + $dom_realm{$domain} = $realm; + if ($domain =~ /^\./) { + $domain =~ s/^\.//; + $def_realm{$realm} = $domain; + } +} + +print "[libdefaults]\n\tdefault_realm = $default_realm\n"; + +print "[realms]\n"; + +foreach $realm (sort(keys(%realmpt))) { + print "\t$realm = {\n"; + for ($i = 1; $i < $realmpt{$realm}; $i++) { + printf("\t\tkdc = %s\n", $realmkdc{$realm . "##" . $i}); + + } + if (defined($realmadmin{$realm})) { + print "\t\tadmin_server = $realmadmin{$realm}\n"; + } + if (defined($def_realm{$realm})) { + print "\t\tdefault_domain = $def_realm{$realm}\n"; + } + print "\t}\n"; +} + +print "\n[domain_realm]\n"; + +foreach $domain (keys(%dom_realm)) { + print "\t$domain = $dom_realm{$domain}\n"; +} + + + diff --git a/krb5-1.21.3/src/config-files/deps b/krb5-1.21.3/src/config-files/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/config-files/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/config-files/kdc.conf b/krb5-1.21.3/src/config-files/kdc.conf new file mode 100644 index 00000000..bc5076d5 --- /dev/null +++ b/krb5-1.21.3/src/config-files/kdc.conf @@ -0,0 +1,14 @@ +[kdcdefaults] + kdc_listen = 88 + kdc_tcp_listen = 88 + +[realms] + ATHENA.MIT.EDU = { + database_name = /usr/local/var/krb5kdc/principal + acl_file = /usr/local/var/krb5kdc/kadm5.acl + key_stash_file = /usr/local/var/krb5kdc/.k5.ATHENA.MIT.EDU + kdc_listen = 88 + kdc_tcp_listen = 88 + max_life = 10h 0m 0s + max_renewable_life = 7d 0h 0m 0s + } diff --git a/krb5-1.21.3/src/config-files/krb5.conf b/krb5-1.21.3/src/config-files/krb5.conf new file mode 100644 index 00000000..9d250bfa --- /dev/null +++ b/krb5-1.21.3/src/config-files/krb5.conf @@ -0,0 +1,19 @@ +[libdefaults] + default_realm = ATHENA.MIT.EDU + +[realms] +# use "kdc = ..." if realm admins haven't put SRV records into DNS + ATHENA.MIT.EDU = { + admin_server = kerberos.mit.edu + } + ANDREW.CMU.EDU = { + admin_server = kdc-01.andrew.cmu.edu + } + +[domain_realm] + mit.edu = ATHENA.MIT.EDU + csail.mit.edu = CSAIL.MIT.EDU + .ucsc.edu = CATS.UCSC.EDU + +[logging] +# kdc = CONSOLE diff --git a/krb5-1.21.3/src/config-files/mech b/krb5-1.21.3/src/config-files/mech new file mode 100644 index 00000000..15c9fcd0 --- /dev/null +++ b/krb5-1.21.3/src/config-files/mech @@ -0,0 +1,3 @@ +#kerberos_v5 1.2.840.48018.1.2.2 mech_krb5.so +#mskrb 1.2.840.113554.1.2.2 mech_krb5.so +#spnego 1.3.6.1.5.5.2 mech_spnego.so diff --git a/krb5-1.21.3/src/config-files/services.append b/krb5-1.21.3/src/config-files/services.append new file mode 100644 index 00000000..34d19566 --- /dev/null +++ b/krb5-1.21.3/src/config-files/services.append @@ -0,0 +1,12 @@ +kerberos 88/udp kdc # Kerberos authentication--udp +kerberos 88/tcp kdc # Kerberos authentication--tcp +kerberos_master 751/udp # Kerberos authentication +kerberos_master 751/tcp # Kerberos authentication +kerberos-adm 749/tcp # Kerberos 5 admin/changepw +kerberos-adm 749/udp # Kerberos 5 admin/changepw +kpop 1109/tcp # Pop with Kerberos +kshell 544/tcp cmd # and remote shell +klogin 543/tcp # Kerberos authenticated rlogin +eklogin 2105/tcp # Kerberos encrypted rlogin +krb5_prop 754/tcp # Kerberos replica propagation +krb524 4444/tcp # Kerberos 5 to 4 ticket xlator diff --git a/krb5-1.21.3/src/config/ac-archive/README b/krb5-1.21.3/src/config/ac-archive/README new file mode 100644 index 00000000..7c28643c --- /dev/null +++ b/krb5-1.21.3/src/config/ac-archive/README @@ -0,0 +1,9 @@ +-*- text -*- + +These macros are taken from the autoconf archive at +https://www.gnu.org/software/autoconf-archive/ . They are licensed +under a modified version of the GNU General Public License as noted in +the comments near the top of each file. + +ax_pthread.m4 serial 31 2023-02-20 +ax_recursive_eval.m4 serial 1 2017-01-05 diff --git a/krb5-1.21.3/src/config/ac-archive/ax_pthread.m4 b/krb5-1.21.3/src/config/ac-archive/ax_pthread.m4 new file mode 100644 index 00000000..9f35d139 --- /dev/null +++ b/krb5-1.21.3/src/config/ac-archive/ax_pthread.m4 @@ -0,0 +1,522 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_pthread.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +# +# DESCRIPTION +# +# This macro figures out how to build C programs using POSIX threads. It +# sets the PTHREAD_LIBS output variable to the threads library and linker +# flags, and the PTHREAD_CFLAGS output variable to any special C compiler +# flags that are needed. (The user can also force certain compiler +# flags/libs to be tested by setting these environment variables.) +# +# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is +# needed for multi-threaded programs (defaults to the value of CC +# respectively CXX otherwise). (This is necessary on e.g. AIX to use the +# special cc_r/CC_r compiler alias.) +# +# NOTE: You are assumed to not only compile your program with these flags, +# but also to link with them as well. For example, you might link with +# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# +# If you are only building threaded programs, you may wish to use these +# variables in your default LIBS, CFLAGS, and CC: +# +# LIBS="$PTHREAD_LIBS $LIBS" +# CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" +# CC="$PTHREAD_CC" +# CXX="$PTHREAD_CXX" +# +# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant +# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# +# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the +# PTHREAD_PRIO_INHERIT symbol is defined when compiling with +# PTHREAD_CFLAGS. +# +# ACTION-IF-FOUND is a list of shell commands to run if a threads library +# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it +# is not found. If ACTION-IF-FOUND is not specified, the default action +# will define HAVE_PTHREAD. +# +# Please let the authors know if this macro fails on any platform, or if +# you have any other suggestions or comments. This macro was based on work +# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help +# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by +# Alejandro Forero Cuervo to the autoconf macro repository. We are also +# grateful for the helpful feedback of numerous users. +# +# Updated for Autoconf 2.68 by Daniel Richard G. +# +# LICENSE +# +# Copyright (c) 2008 Steven G. Johnson +# Copyright (c) 2011 Daniel Richard G. +# Copyright (c) 2019 Marc Stevens +# +# 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 . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 31 + +AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) +AC_DEFUN([AX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_SED]) +AC_LANG_PUSH([C]) +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) + AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"]) + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) + AC_MSG_RESULT([$ax_pthread_ok]) + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items with a "," contain both +# C compiler flags (before ",") and linker flags (after ","). Other items +# starting with a "-" are C compiler flags, and remaining items are +# library names, except for "none" which indicates that we try without +# any flags at all, and "pthread-config" which is a program returning +# the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags" + ;; +esac + +# Are we compiling with Clang? + +AC_CACHE_CHECK([whether $CC is Clang], + [ax_cv_PTHREAD_CLANG], + [ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) + fi + ]) +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +# Note that for GCC and Clang -pthread generally implies -lpthread, +# except when -nostdlib is passed. +# This is problematic using libtool to build C++ shared libraries with pthread: +# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460 +# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333 +# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555 +# To solve this, first try -pthread together with -lpthread for GCC + +AS_IF([test "x$GCC" = "xyes"], + [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"]) + +# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first + +AS_IF([test "x$ax_pthread_clang" = "xyes"], + [ax_pthread_flags="-pthread,-lpthread -pthread"]) + + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +AS_IF([test "x$ax_pthread_check_macro" = "x--"], + [ax_pthread_check_cond=0], + [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) + + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + *,*) + PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"` + PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"` + AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void *some_global = NULL; + static void routine(void *a) + { + /* To avoid any unused-parameter or + unused-but-set-parameter warning. */ + some_global = a; + } + static void *start_routine(void *a) { return a; }], + [pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */])], + [ax_pthread_ok=yes], + []) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + AC_MSG_RESULT([$ax_pthread_ok]) + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + + + +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) + + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) + + AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT; + return i;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) + ]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + AS_CASE(["x/$CC"], + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [ + AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"]) + AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])]) + ], + [ + AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC]) + AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])]) + ] + ) + ]) + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" +test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX" + +AC_SUBST([PTHREAD_LIBS]) +AC_SUBST([PTHREAD_CFLAGS]) +AC_SUBST([PTHREAD_CC]) +AC_SUBST([PTHREAD_CXX]) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) + : +else + ax_pthread_ok=no + $2 +fi +AC_LANG_POP +])dnl AX_PTHREAD diff --git a/krb5-1.21.3/src/config/ac-archive/ax_recursive_eval.m4 b/krb5-1.21.3/src/config/ac-archive/ax_recursive_eval.m4 new file mode 100644 index 00000000..0625aca2 --- /dev/null +++ b/krb5-1.21.3/src/config/ac-archive/ax_recursive_eval.m4 @@ -0,0 +1,56 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_recursive_eval.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_RECURSIVE_EVAL(VALUE, RESULT) +# +# DESCRIPTION +# +# Interpolate the VALUE in loop until it doesn't change, and set the +# result to $RESULT. WARNING: It's easy to get an infinite loop with some +# unsane input. +# +# LICENSE +# +# Copyright (c) 2008 Alexandre Duret-Lutz +# +# 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 2 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 . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 1 + +AC_DEFUN([AX_RECURSIVE_EVAL], +[_lcl_receval="$1" +$2=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" + test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" + _lcl_receval_old='' + while test "[$]_lcl_receval_old" != "[$]_lcl_receval"; do + _lcl_receval_old="[$]_lcl_receval" + eval _lcl_receval="\"[$]_lcl_receval\"" + done + echo "[$]_lcl_receval")`]) diff --git a/krb5-1.21.3/src/config/config.guess b/krb5-1.21.3/src/config/config.guess new file mode 100755 index 00000000..69188da7 --- /dev/null +++ b/krb5-1.21.3/src/config/config.guess @@ -0,0 +1,1774 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2023 Free Software Foundation, Inc. + +# shellcheck disable=SC2006,SC2268 # see below for rationale + +timestamp='2023-01-01' + +# This file 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 . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess +# +# Please send patches to . + + +# The "shellcheck disable" line above the timestamp inhibits complaints +# about features and limitations of the classic Bourne shell that were +# superseded or lifted in POSIX. However, this script identifies a wide +# variety of pre-POSIX systems that do not have POSIX shells at all, and +# even some reasonably current systems (Solaris 10 as case-in-point) still +# have a pre-POSIX /bin/sh. + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2023 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +# Just in case it came from the environment. +GUESS= + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 + +set_cc_for_build() { + # prevent multiple calls if $tmp is already set + test "$tmp" && return 0 + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039,SC3028 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD=$driver + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if test -f /.attbin/uname ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case $UNAME_SYSTEM in +Linux|GNU|GNU/*) + LIBC=unknown + + set_cc_for_build + cat <<-EOF > "$dummy.c" + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #elif defined(__GLIBC__) + LIBC=gnu + #else + #include + /* First heuristic to detect musl libc. */ + #ifdef __DEFINED_va_list + LIBC=musl + #endif + #endif + EOF + cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + eval "$cc_set_libc" + + # Second heuristic to detect musl libc. + if [ "$LIBC" = unknown ] && + command -v ldd >/dev/null && + ldd --version 2>&1 | grep -q ^musl; then + LIBC=musl + fi + + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + if [ "$LIBC" = unknown ]; then + LIBC=gnu + fi + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/sysctl -n hw.machine_arch 2>/dev/null || \ + /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \ + echo unknown)` + case $UNAME_MACHINE_ARCH in + aarch64eb) machine=aarch64_be-unknown ;; + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; + *) machine=$UNAME_MACHINE_ARCH-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case $UNAME_MACHINE_ARCH in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case $UNAME_MACHINE_ARCH in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case $UNAME_VERSION in + Debian*) + release='-gnu' + ;; + *) + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + GUESS=$machine-${os}${release}${abi-} + ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE + ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE + ;; + *:SecBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE + ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE + ;; + *:MidnightBSD:*:*) + GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE + ;; + *:ekkoBSD:*:*) + GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE + ;; + *:SolidBSD:*:*) + GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE + ;; + *:OS108:*:*) + GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE + ;; + macppc:MirBSD:*:*) + GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE + ;; + *:MirBSD:*:*) + GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE + ;; + *:Sortix:*:*) + GUESS=$UNAME_MACHINE-unknown-sortix + ;; + *:Twizzler:*:*) + GUESS=$UNAME_MACHINE-unknown-twizzler + ;; + *:Redox:*:*) + GUESS=$UNAME_MACHINE-unknown-redox + ;; + mips:OSF1:*.*) + GUESS=mips-dec-osf1 + ;; + alpha:OSF1:*:*) + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + trap '' 0 + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case $ALPHA_CPU_TYPE in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + GUESS=$UNAME_MACHINE-dec-osf$OSF_REL + ;; + Amiga*:UNIX_System_V:4.0:*) + GUESS=m68k-unknown-sysv4 + ;; + *:[Aa]miga[Oo][Ss]:*:*) + GUESS=$UNAME_MACHINE-unknown-amigaos + ;; + *:[Mm]orph[Oo][Ss]:*:*) + GUESS=$UNAME_MACHINE-unknown-morphos + ;; + *:OS/390:*:*) + GUESS=i370-ibm-openedition + ;; + *:z/VM:*:*) + GUESS=s390-ibm-zvmoe + ;; + *:OS400:*:*) + GUESS=powerpc-ibm-os400 + ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + GUESS=arm-acorn-riscix$UNAME_RELEASE + ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + GUESS=arm-unknown-riscos + ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + GUESS=hppa1.1-hitachi-hiuxmpp + ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + case `(/bin/universe) 2>/dev/null` in + att) GUESS=pyramid-pyramid-sysv3 ;; + *) GUESS=pyramid-pyramid-bsd ;; + esac + ;; + NILE*:*:*:dcosx) + GUESS=pyramid-pyramid-svr4 + ;; + DRS?6000:unix:4.0:6*) + GUESS=sparc-icl-nx6 + ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) GUESS=sparc-icl-nx7 ;; + esac + ;; + s390x:SunOS:*:*) + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL + ;; + sun4H:SunOS:5.*:*) + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-hal-solaris2$SUN_REL + ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-sun-solaris2$SUN_REL + ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + GUESS=i386-pc-auroraux$UNAME_RELEASE + ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + set_cc_for_build + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=$SUN_ARCH-pc-solaris2$SUN_REL + ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=sparc-sun-solaris3$SUN_REL + ;; + sun4*:SunOS:*:*) + case `/usr/bin/arch -k` in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'` + GUESS=sparc-sun-sunos$SUN_REL + ;; + sun3*:SunOS:*:*) + GUESS=m68k-sun-sunos$UNAME_RELEASE + ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 + case `/bin/arch` in + sun3) + GUESS=m68k-sun-sunos$UNAME_RELEASE + ;; + sun4) + GUESS=sparc-sun-sunos$UNAME_RELEASE + ;; + esac + ;; + aushp:SunOS:*:*) + GUESS=sparc-auspex-sunos$UNAME_RELEASE + ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + GUESS=m68k-atari-mint$UNAME_RELEASE + ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + GUESS=m68k-milan-mint$UNAME_RELEASE + ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + GUESS=m68k-hades-mint$UNAME_RELEASE + ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + GUESS=m68k-unknown-mint$UNAME_RELEASE + ;; + m68k:machten:*:*) + GUESS=m68k-apple-machten$UNAME_RELEASE + ;; + powerpc:machten:*:*) + GUESS=powerpc-apple-machten$UNAME_RELEASE + ;; + RISC*:Mach:*:*) + GUESS=mips-dec-mach_bsd4.3 + ;; + RISC*:ULTRIX:*:*) + GUESS=mips-dec-ultrix$UNAME_RELEASE + ;; + VAX*:ULTRIX*:*:*) + GUESS=vax-dec-ultrix$UNAME_RELEASE + ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + GUESS=clipper-intergraph-clix$UNAME_RELEASE + ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && + { echo "$SYSTEM_NAME"; exit; } + GUESS=mips-mips-riscos$UNAME_RELEASE + ;; + Motorola:PowerMAX_OS:*:*) + GUESS=powerpc-motorola-powermax + ;; + Motorola:*:4.3:PL8-*) + GUESS=powerpc-harris-powermax + ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + GUESS=powerpc-harris-powermax + ;; + Night_Hawk:Power_UNIX:*:*) + GUESS=powerpc-harris-powerunix + ;; + m88k:CX/UX:7*:*) + GUESS=m88k-harris-cxux7 + ;; + m88k:*:4*:R4*) + GUESS=m88k-motorola-sysv4 + ;; + m88k:*:3*:R3*) + GUESS=m88k-motorola-sysv3 + ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 + then + if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ + test "$TARGET_BINARY_INTERFACE"x = x + then + GUESS=m88k-dg-dgux$UNAME_RELEASE + else + GUESS=m88k-dg-dguxbcs$UNAME_RELEASE + fi + else + GUESS=i586-dg-dgux$UNAME_RELEASE + fi + ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + GUESS=m88k-dolphin-sysv3 + ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + GUESS=m88k-motorola-sysv3 + ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + GUESS=m88k-tektronix-sysv3 + ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + GUESS=m68k-tektronix-bsd + ;; + *:IRIX*:*:*) + IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'` + GUESS=mips-sgi-irix$IRIX_REL + ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id + ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + GUESS=i386-ibm-aix + ;; + ia64:AIX:*:*) + if test -x /usr/bin/oslevel ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE + fi + GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV + ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` + then + GUESS=$SYSTEM_NAME + else + GUESS=rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + GUESS=rs6000-ibm-aix3.2.4 + else + GUESS=rs6000-ibm-aix3.2 + fi + ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if test -x /usr/bin/lslpp ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \ + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=$UNAME_VERSION.$UNAME_RELEASE + fi + GUESS=$IBM_ARCH-ibm-aix$IBM_REV + ;; + *:AIX:*:*) + GUESS=rs6000-ibm-aix + ;; + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) + GUESS=romp-ibm-bsd4.4 + ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to + ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + GUESS=rs6000-bull-bosx + ;; + DPX/2?00:B.O.S.:*:*) + GUESS=m68k-bull-sysv3 + ;; + 9000/[34]??:4.3bsd:1.*:*) + GUESS=m68k-hp-bsd + ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + GUESS=m68k-hp-bsd4.4 + ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` + case $UNAME_MACHINE in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if test -x /usr/bin/getconf; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case $sc_cpu_version in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case $sc_kernel_bits in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if test "$HP_ARCH" = ""; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if test "$HP_ARCH" = hppa2.0w + then + set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + GUESS=$HP_ARCH-hp-hpux$HPUX_REV + ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'` + GUESS=ia64-hp-hpux$HPUX_REV + ;; + 3050*:HI-UX:*:*) + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } + GUESS=unknown-hitachi-hiuxwe2 + ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + GUESS=hppa1.1-hp-bsd + ;; + 9000/8??:4.3bsd:*:*) + GUESS=hppa1.0-hp-bsd + ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + GUESS=hppa1.0-hp-mpeix + ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + GUESS=hppa1.1-hp-osf + ;; + hp8??:OSF1:*:*) + GUESS=hppa1.0-hp-osf + ;; + i*86:OSF1:*:*) + if test -x /usr/sbin/sysversion ; then + GUESS=$UNAME_MACHINE-unknown-osf1mk + else + GUESS=$UNAME_MACHINE-unknown-osf1 + fi + ;; + parisc*:Lites*:*:*) + GUESS=hppa1.1-hp-lites + ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + GUESS=c1-convex-bsd + ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + GUESS=c34-convex-bsd + ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + GUESS=c38-convex-bsd + ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + GUESS=c4-convex-bsd + ;; + CRAY*Y-MP:*:*:*) + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=ymp-cray-unicos$CRAY_REL + ;; + CRAY*[A-Z]90:*:*:*) + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=t90-cray-unicos$CRAY_REL + ;; + CRAY*T3E:*:*:*) + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=alphaev5-cray-unicosmk$CRAY_REL + ;; + CRAY*SV1:*:*:*) + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=sv1-cray-unicos$CRAY_REL + ;; + *:UNICOS/mp:*:*) + CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'` + GUESS=craynv-cray-unicosmp$CRAY_REL + ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` + GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} + ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL} + ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE + ;; + sparc*:BSD/OS:*:*) + GUESS=sparc-unknown-bsdi$UNAME_RELEASE + ;; + *:BSD/OS:*:*) + GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE + ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi + else + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf + fi + ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case $UNAME_PROCESSOR in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac + FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL + ;; + i*:CYGWIN*:*) + GUESS=$UNAME_MACHINE-pc-cygwin + ;; + *:MINGW64*:*) + GUESS=$UNAME_MACHINE-pc-mingw64 + ;; + *:MINGW*:*) + GUESS=$UNAME_MACHINE-pc-mingw32 + ;; + *:MSYS*:*) + GUESS=$UNAME_MACHINE-pc-msys + ;; + i*:PW*:*) + GUESS=$UNAME_MACHINE-pc-pw32 + ;; + *:SerenityOS:*:*) + GUESS=$UNAME_MACHINE-pc-serenity + ;; + *:Interix*:*) + case $UNAME_MACHINE in + x86) + GUESS=i586-pc-interix$UNAME_RELEASE + ;; + authenticamd | genuineintel | EM64T) + GUESS=x86_64-unknown-interix$UNAME_RELEASE + ;; + IA64) + GUESS=ia64-unknown-interix$UNAME_RELEASE + ;; + esac ;; + i*:UWIN*:*) + GUESS=$UNAME_MACHINE-pc-uwin + ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + GUESS=x86_64-pc-cygwin + ;; + prep*:SunOS:5.*:*) + SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'` + GUESS=powerpcle-unknown-solaris2$SUN_REL + ;; + *:GNU:*:*) + # the GNU system + GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'` + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'` + GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL + ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"` + GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC + ;; + x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*) + GUESS="$UNAME_MACHINE-pc-managarm-mlibc" + ;; + *:[Mm]anagarm:*:*) + GUESS="$UNAME_MACHINE-unknown-managarm-mlibc" + ;; + *:Minix:*:*) + GUESS=$UNAME_MACHINE-unknown-minix + ;; + aarch64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + arm*:Linux:*:*) + set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi + else + GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf + fi + fi + ;; + avr32*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + cris:Linux:*:*) + GUESS=$UNAME_MACHINE-axis-linux-$LIBC + ;; + crisv32:Linux:*:*) + GUESS=$UNAME_MACHINE-axis-linux-$LIBC + ;; + e2k:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + frv:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + hexagon:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + i*86:Linux:*:*) + GUESS=$UNAME_MACHINE-pc-linux-$LIBC + ;; + ia64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + k1om:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + loongarch32:Linux:*:* | loongarch64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + m32r*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + m68*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + mips:Linux:*:* | mips64:Linux:*:*) + set_cc_for_build + IS_GLIBC=0 + test x"${LIBC}" = xgnu && IS_GLIBC=1 + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef mips + #undef mipsel + #undef mips64 + #undef mips64el + #if ${IS_GLIBC} && defined(_ABI64) + LIBCABI=gnuabi64 + #else + #if ${IS_GLIBC} && defined(_ABIN32) + LIBCABI=gnuabin32 + #else + LIBCABI=${LIBC} + #endif + #endif + + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa64r6 + #else + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa32r6 + #else + #if defined(__mips64) + CPU=mips64 + #else + CPU=mips + #endif + #endif + #endif + + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + MIPS_ENDIAN=el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + MIPS_ENDIAN= + #else + MIPS_ENDIAN= + #endif + #endif +EOF + cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'` + eval "$cc_set_vars" + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } + ;; + mips64el:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + openrisc*:Linux:*:*) + GUESS=or1k-unknown-linux-$LIBC + ;; + or32:Linux:*:* | or1k*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + padre:Linux:*:*) + GUESS=sparc-unknown-linux-$LIBC + ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + GUESS=hppa64-unknown-linux-$LIBC + ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;; + PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;; + *) GUESS=hppa-unknown-linux-$LIBC ;; + esac + ;; + ppc64:Linux:*:*) + GUESS=powerpc64-unknown-linux-$LIBC + ;; + ppc:Linux:*:*) + GUESS=powerpc-unknown-linux-$LIBC + ;; + ppc64le:Linux:*:*) + GUESS=powerpc64le-unknown-linux-$LIBC + ;; + ppcle:Linux:*:*) + GUESS=powerpcle-unknown-linux-$LIBC + ;; + riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + s390:Linux:*:* | s390x:Linux:*:*) + GUESS=$UNAME_MACHINE-ibm-linux-$LIBC + ;; + sh64*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + sh*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + tile*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + vax:Linux:*:*) + GUESS=$UNAME_MACHINE-dec-linux-$LIBC + ;; + x86_64:Linux:*:*) + set_cc_for_build + CPU=$UNAME_MACHINE + LIBCABI=$LIBC + if test "$CC_FOR_BUILD" != no_compiler_found; then + ABI=64 + sed 's/^ //' << EOF > "$dummy.c" + #ifdef __i386__ + ABI=x86 + #else + #ifdef __ILP32__ + ABI=x32 + #endif + #endif +EOF + cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'` + eval "$cc_set_abi" + case $ABI in + x86) CPU=i686 ;; + x32) LIBCABI=${LIBC}x32 ;; + esac + fi + GUESS=$CPU-pc-linux-$LIBCABI + ;; + xtensa*:Linux:*:*) + GUESS=$UNAME_MACHINE-unknown-linux-$LIBC + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + GUESS=i386-sequent-sysv4 + ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION + ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + GUESS=$UNAME_MACHINE-pc-os2-emx + ;; + i*86:XTS-300:*:STOP) + GUESS=$UNAME_MACHINE-unknown-stop + ;; + i*86:atheos:*:*) + GUESS=$UNAME_MACHINE-unknown-atheos + ;; + i*86:syllable:*:*) + GUESS=$UNAME_MACHINE-pc-syllable + ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + GUESS=i386-unknown-lynxos$UNAME_RELEASE + ;; + i*86:*DOS:*:*) + GUESS=$UNAME_MACHINE-pc-msdosdjgpp + ;; + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL + else + GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL + fi + ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL + else + GUESS=$UNAME_MACHINE-pc-sysv32 + fi + ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + GUESS=i586-pc-msdosdjgpp + ;; + Intel:Mach:3*:*) + GUESS=i386-pc-mach3 + ;; + paragon:*:*:*) + GUESS=i860-intel-osf1 + ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4 + fi + ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + GUESS=m68010-convergent-sysv + ;; + mc68k:UNIX:SYSTEM5:3.51m) + GUESS=m68k-convergent-sysv + ;; + M680?0:D-NIX:5.3:*) + GUESS=m68k-diab-dnix + ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + GUESS=m68k-unknown-lynxos$UNAME_RELEASE + ;; + mc68030:UNIX_System_V:4.*:*) + GUESS=m68k-atari-sysv4 + ;; + TSUNAMI:LynxOS:2.*:*) + GUESS=sparc-unknown-lynxos$UNAME_RELEASE + ;; + rs6000:LynxOS:2.*:*) + GUESS=rs6000-unknown-lynxos$UNAME_RELEASE + ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + GUESS=powerpc-unknown-lynxos$UNAME_RELEASE + ;; + SM[BE]S:UNIX_SV:*:*) + GUESS=mips-dde-sysv$UNAME_RELEASE + ;; + RM*:ReliantUNIX-*:*:*) + GUESS=mips-sni-sysv4 + ;; + RM*:SINIX-*:*:*) + GUESS=mips-sni-sysv4 + ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + GUESS=$UNAME_MACHINE-sni-sysv4 + else + GUESS=ns32k-sni-sysv + fi + ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + GUESS=i586-unisys-sysv4 + ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + GUESS=hppa1.1-stratus-sysv4 + ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + GUESS=i860-stratus-sysv4 + ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + GUESS=$UNAME_MACHINE-stratus-vos + ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + GUESS=hppa1.1-stratus-vos + ;; + mc68*:A/UX:*:*) + GUESS=m68k-apple-aux$UNAME_RELEASE + ;; + news*:NEWS-OS:6*:*) + GUESS=mips-sony-newsos6 + ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if test -d /usr/nec; then + GUESS=mips-nec-sysv$UNAME_RELEASE + else + GUESS=mips-unknown-sysv$UNAME_RELEASE + fi + ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + GUESS=powerpc-be-beos + ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + GUESS=powerpc-apple-beos + ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + GUESS=i586-pc-beos + ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + GUESS=i586-pc-haiku + ;; + ppc:Haiku:*:*) # Haiku running on Apple PowerPC + GUESS=powerpc-apple-haiku + ;; + *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat) + GUESS=$UNAME_MACHINE-unknown-haiku + ;; + SX-4:SUPER-UX:*:*) + GUESS=sx4-nec-superux$UNAME_RELEASE + ;; + SX-5:SUPER-UX:*:*) + GUESS=sx5-nec-superux$UNAME_RELEASE + ;; + SX-6:SUPER-UX:*:*) + GUESS=sx6-nec-superux$UNAME_RELEASE + ;; + SX-7:SUPER-UX:*:*) + GUESS=sx7-nec-superux$UNAME_RELEASE + ;; + SX-8:SUPER-UX:*:*) + GUESS=sx8-nec-superux$UNAME_RELEASE + ;; + SX-8R:SUPER-UX:*:*) + GUESS=sx8r-nec-superux$UNAME_RELEASE + ;; + SX-ACE:SUPER-UX:*:*) + GUESS=sxace-nec-superux$UNAME_RELEASE + ;; + Power*:Rhapsody:*:*) + GUESS=powerpc-apple-rhapsody$UNAME_RELEASE + ;; + *:Rhapsody:*:*) + GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE + ;; + arm64:Darwin:*:*) + GUESS=aarch64-apple-darwin$UNAME_RELEASE + ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + if command -v xcode-select > /dev/null 2> /dev/null && \ + ! xcode-select --print-path > /dev/null 2> /dev/null ; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build + fi + if test "$CC_FOR_BUILD" != no_compiler_found; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE + fi + GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE + ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE + ;; + *:QNX:*:4*) + GUESS=i386-pc-qnx + ;; + NEO-*:NONSTOP_KERNEL:*:*) + GUESS=neo-tandem-nsk$UNAME_RELEASE + ;; + NSE-*:NONSTOP_KERNEL:*:*) + GUESS=nse-tandem-nsk$UNAME_RELEASE + ;; + NSR-*:NONSTOP_KERNEL:*:*) + GUESS=nsr-tandem-nsk$UNAME_RELEASE + ;; + NSV-*:NONSTOP_KERNEL:*:*) + GUESS=nsv-tandem-nsk$UNAME_RELEASE + ;; + NSX-*:NONSTOP_KERNEL:*:*) + GUESS=nsx-tandem-nsk$UNAME_RELEASE + ;; + *:NonStop-UX:*:*) + GUESS=mips-compaq-nonstopux + ;; + BS2000:POSIX*:*:*) + GUESS=bs2000-siemens-sysv + ;; + DS/*:UNIX_System_V:*:*) + GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE + ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "${cputype-}" = 386; then + UNAME_MACHINE=i386 + elif test "x${cputype-}" != x; then + UNAME_MACHINE=$cputype + fi + GUESS=$UNAME_MACHINE-unknown-plan9 + ;; + *:TOPS-10:*:*) + GUESS=pdp10-unknown-tops10 + ;; + *:TENEX:*:*) + GUESS=pdp10-unknown-tenex + ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + GUESS=pdp10-dec-tops20 + ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + GUESS=pdp10-xkl-tops20 + ;; + *:TOPS-20:*:*) + GUESS=pdp10-unknown-tops20 + ;; + *:ITS:*:*) + GUESS=pdp10-unknown-its + ;; + SEI:*:*:SEIUX) + GUESS=mips-sei-seiux$UNAME_RELEASE + ;; + *:DragonFly:*:*) + DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'` + GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL + ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case $UNAME_MACHINE in + A*) GUESS=alpha-dec-vms ;; + I*) GUESS=ia64-dec-vms ;; + V*) GUESS=vax-dec-vms ;; + esac ;; + *:XENIX:*:SysV) + GUESS=i386-pc-xenix + ;; + i*86:skyos:*:*) + SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'` + GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL + ;; + i*86:rdos:*:*) + GUESS=$UNAME_MACHINE-pc-rdos + ;; + i*86:Fiwix:*:*) + GUESS=$UNAME_MACHINE-pc-fiwix + ;; + *:AROS:*:*) + GUESS=$UNAME_MACHINE-unknown-aros + ;; + x86_64:VMkernel:*:*) + GUESS=$UNAME_MACHINE-unknown-esx + ;; + amd64:Isilon\ OneFS:*:*) + GUESS=x86_64-unknown-onefs + ;; + *:Unleashed:*:*) + GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE + ;; +esac + +# Do we have a guess based on uname results? +if test "x$GUESS" != x; then + echo "$GUESS" + exit +fi + +# No uname command or uname output not recognized. +set_cc_for_build +cat > "$dummy.c" < +#include +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#include +#if defined(_SIZE_T_) || defined(SIGLOST) +#include +#endif +#endif +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); +#endif + +#if defined (vax) +#if !defined (ultrix) +#include +#if defined (BSD) +#if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +#else +#if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#endif +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#else +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname un; + uname (&un); + printf ("vax-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname *un; + uname (&un); + printf ("mips-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("mips-dec-ultrix\n"); exit (0); +#endif +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. +test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } + +echo "$0: unable to guess system type" >&2 + +case $UNAME_MACHINE:$UNAME_SYSTEM in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 <&2 </dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" +EOF +fi + +exit 1 + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/krb5-1.21.3/src/config/config.sub b/krb5-1.21.3/src/config/config.sub new file mode 100755 index 00000000..de4259e4 --- /dev/null +++ b/krb5-1.21.3/src/config/config.sub @@ -0,0 +1,1907 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2023 Free Software Foundation, Inc. + +# shellcheck disable=SC2006,SC2268 # see below for rationale + +timestamp='2023-01-21' + +# This file 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 . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +# The "shellcheck disable" line above the timestamp inhibits complaints +# about features and limitations of the classic Bourne shell that were +# superseded or lifted in POSIX. However, this script identifies a wide +# variety of pre-POSIX systems that do not have POSIX shells at all, and +# even some reasonably current systems (Solaris 10 as case-in-point) still +# have a pre-POSIX /bin/sh. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2023 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo "$1" + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Split fields of configuration type +# shellcheck disable=SC2162 +saved_IFS=$IFS +IFS="-" read field1 field2 field3 field4 <&2 + exit 1 + ;; + *-*-*-*) + basic_machine=$field1-$field2 + basic_os=$field3-$field4 + ;; + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova* | managarm-*) + basic_machine=$field1 + basic_os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + basic_os=linux-android + ;; + *) + basic_machine=$field1-$field2 + basic_os=$field3 + ;; + esac + ;; + *-*) + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec + basic_os= + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + basic_os=$field2 + ;; + zephyr*) + basic_machine=$field1-unknown + basic_os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + basic_os= + ;; + *) + basic_machine=$field1 + basic_os=$field2 + ;; + esac + ;; + esac + ;; + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + basic_os=bsd + ;; + a29khif) + basic_machine=a29k-amd + basic_os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + basic_os=scout + ;; + alliant) + basic_machine=fx80-alliant + basic_os= + ;; + altos | altos3068) + basic_machine=m68k-altos + basic_os= + ;; + am29k) + basic_machine=a29k-none + basic_os=bsd + ;; + amdahl) + basic_machine=580-amdahl + basic_os=sysv + ;; + amiga) + basic_machine=m68k-unknown + basic_os= + ;; + amigaos | amigados) + basic_machine=m68k-unknown + basic_os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + basic_os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + basic_os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + basic_os=bsd + ;; + aros) + basic_machine=i386-pc + basic_os=aros + ;; + aux) + basic_machine=m68k-apple + basic_os=aux + ;; + balance) + basic_machine=ns32k-sequent + basic_os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + basic_os=linux + ;; + cegcc) + basic_machine=arm-unknown + basic_os=cegcc + ;; + convex-c1) + basic_machine=c1-convex + basic_os=bsd + ;; + convex-c2) + basic_machine=c2-convex + basic_os=bsd + ;; + convex-c32) + basic_machine=c32-convex + basic_os=bsd + ;; + convex-c34) + basic_machine=c34-convex + basic_os=bsd + ;; + convex-c38) + basic_machine=c38-convex + basic_os=bsd + ;; + cray) + basic_machine=j90-cray + basic_os=unicos + ;; + crds | unos) + basic_machine=m68k-crds + basic_os= + ;; + da30) + basic_machine=m68k-da30 + basic_os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + basic_os= + ;; + delta88) + basic_machine=m88k-motorola + basic_os=sysv3 + ;; + dicos) + basic_machine=i686-pc + basic_os=dicos + ;; + djgpp) + basic_machine=i586-pc + basic_os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + basic_os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + basic_os=ose + ;; + gmicro) + basic_machine=tron-gmicro + basic_os=sysv + ;; + go32) + basic_machine=i386-pc + basic_os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + basic_os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + basic_os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + basic_os=hms + ;; + harris) + basic_machine=m88k-harris + basic_os=sysv3 + ;; + hp300 | hp300hpux) + basic_machine=m68k-hp + basic_os=hpux + ;; + hp300bsd) + basic_machine=m68k-hp + basic_os=bsd + ;; + hppaosf) + basic_machine=hppa1.1-hp + basic_os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + basic_os=proelf + ;; + i386mach) + basic_machine=i386-mach + basic_os=mach + ;; + isi68 | isi) + basic_machine=m68k-isi + basic_os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + basic_os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + basic_os=sysv + ;; + merlin) + basic_machine=ns32k-utek + basic_os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + basic_os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + basic_os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + basic_os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + basic_os=coff + ;; + morphos) + basic_machine=powerpc-unknown + basic_os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + basic_os=moxiebox + ;; + msdos) + basic_machine=i386-pc + basic_os=msdos + ;; + msys) + basic_machine=i686-pc + basic_os=msys + ;; + mvs) + basic_machine=i370-ibm + basic_os=mvs + ;; + nacl) + basic_machine=le32-unknown + basic_os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + basic_os=sysv4 + ;; + netbsd386) + basic_machine=i386-pc + basic_os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + basic_os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + basic_os=newsos + ;; + news1000) + basic_machine=m68030-sony + basic_os=newsos + ;; + necv70) + basic_machine=v70-nec + basic_os=sysv + ;; + nh3000) + basic_machine=m68k-harris + basic_os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + basic_os=cxux + ;; + nindy960) + basic_machine=i960-intel + basic_os=nindy + ;; + mon960) + basic_machine=i960-intel + basic_os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + basic_os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + basic_os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + basic_os=ose + ;; + os68k) + basic_machine=m68k-none + basic_os=os68k + ;; + paragon) + basic_machine=i860-intel + basic_os=osf + ;; + parisc) + basic_machine=hppa-unknown + basic_os=linux + ;; + psp) + basic_machine=mipsallegrexel-sony + basic_os=psp + ;; + pw32) + basic_machine=i586-unknown + basic_os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + basic_os=rdos + ;; + rdos32) + basic_machine=i386-pc + basic_os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + basic_os=coff + ;; + sa29200) + basic_machine=a29k-amd + basic_os=udi + ;; + sei) + basic_machine=mips-sei + basic_os=seiux + ;; + sequent) + basic_machine=i386-sequent + basic_os= + ;; + sps7) + basic_machine=m68k-bull + basic_os=sysv2 + ;; + st2000) + basic_machine=m68k-tandem + basic_os= + ;; + stratus) + basic_machine=i860-stratus + basic_os=sysv4 + ;; + sun2) + basic_machine=m68000-sun + basic_os= + ;; + sun2os3) + basic_machine=m68000-sun + basic_os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + basic_os=sunos4 + ;; + sun3) + basic_machine=m68k-sun + basic_os= + ;; + sun3os3) + basic_machine=m68k-sun + basic_os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + basic_os=sunos4 + ;; + sun4) + basic_machine=sparc-sun + basic_os= + ;; + sun4os3) + basic_machine=sparc-sun + basic_os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + basic_os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + basic_os=solaris2 + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + basic_os= + ;; + sv1) + basic_machine=sv1-cray + basic_os=unicos + ;; + symmetry) + basic_machine=i386-sequent + basic_os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + basic_os=unicos + ;; + t90) + basic_machine=t90-cray + basic_os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + basic_os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + basic_os=tpf + ;; + udi29k) + basic_machine=a29k-amd + basic_os=udi + ;; + ultra3) + basic_machine=a29k-nyu + basic_os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + basic_os=none + ;; + vaxv) + basic_machine=vax-dec + basic_os=sysv + ;; + vms) + basic_machine=vax-dec + basic_os=vms + ;; + vsta) + basic_machine=i386-pc + basic_os=vsta + ;; + vxworks960) + basic_machine=i960-wrs + basic_os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + basic_os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + basic_os=vxworks + ;; + xbox) + basic_machine=i686-pc + basic_os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + basic_os=unicos + ;; + *) + basic_machine=$1 + basic_os= + ;; + esac + ;; +esac + +# Decode 1-component or ad-hoc basic machines +case $basic_machine in + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond + ;; + op50n) + cpu=hppa1.1 + vendor=oki + ;; + op60c) + cpu=hppa1.1 + vendor=oki + ;; + ibm*) + cpu=i370 + vendor=ibm + ;; + orion105) + cpu=clipper + vendor=highlevel + ;; + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple + ;; + pmac | pmac-mpw) + cpu=powerpc + vendor=apple + ;; + + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + cpu=m68000 + vendor=att + ;; + 3b*) + cpu=we32k + vendor=att + ;; + bluegene*) + cpu=powerpc + vendor=ibm + basic_os=cnk + ;; + decsystem10* | dec10*) + cpu=pdp10 + vendor=dec + basic_os=tops10 + ;; + decsystem20* | dec20*) + cpu=pdp10 + vendor=dec + basic_os=tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + cpu=m68k + vendor=motorola + ;; + dpx2*) + cpu=m68k + vendor=bull + basic_os=sysv3 + ;; + encore | umax | mmax) + cpu=ns32k + vendor=encore + ;; + elxsi) + cpu=elxsi + vendor=elxsi + basic_os=${basic_os:-bsd} + ;; + fx2800) + cpu=i860 + vendor=alliant + ;; + genix) + cpu=ns32k + vendor=ns + ;; + h3050r* | hiux*) + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + cpu=m68000 + vendor=hp + ;; + hp9k3[2-9][0-9]) + cpu=m68k + vendor=hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + i*86v32) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv32 + ;; + i*86v4*) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv4 + ;; + i*86v) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv + ;; + i*86sol2) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=solaris2 + ;; + j90 | j90-cray) + cpu=j90 + vendor=cray + basic_os=${basic_os:-unicos} + ;; + iris | iris4d) + cpu=mips + vendor=sgi + case $basic_os in + irix*) + ;; + *) + basic_os=irix4 + ;; + esac + ;; + miniframe) + cpu=m68000 + vendor=convergent + ;; + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + cpu=m68k + vendor=atari + basic_os=mint + ;; + news-3600 | risc-news) + cpu=mips + vendor=sony + basic_os=newsos + ;; + next | m*-next) + cpu=m68k + vendor=next + case $basic_os in + openstep*) + ;; + nextstep*) + ;; + ns2*) + basic_os=nextstep2 + ;; + *) + basic_os=nextstep3 + ;; + esac + ;; + np1) + cpu=np1 + vendor=gould + ;; + op50n-* | op60c-*) + cpu=hppa1.1 + vendor=oki + basic_os=proelf + ;; + pa-hitachi) + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 + ;; + pbd) + cpu=sparc + vendor=tti + ;; + pbb) + cpu=m68k + vendor=tti + ;; + pc532) + cpu=ns32k + vendor=pc532 + ;; + pn) + cpu=pn + vendor=gould + ;; + power) + cpu=power + vendor=ibm + ;; + ps2) + cpu=i386 + vendor=ibm + ;; + rm[46]00) + cpu=mips + vendor=siemens + ;; + rtpc | rtpc-*) + cpu=romp + vendor=ibm + ;; + sde) + cpu=mipsisa32 + vendor=sde + basic_os=${basic_os:-elf} + ;; + simso-wrs) + cpu=sparclite + vendor=wrs + basic_os=vxworks + ;; + tower | tower-32) + cpu=m68k + vendor=ncr + ;; + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu + ;; + w65) + cpu=w65 + vendor=wdc + ;; + w89k-*) + cpu=hppa1.1 + vendor=winbond + basic_os=proelf + ;; + none) + cpu=none + vendor=none + ;; + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine + ;; + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` + ;; + + *-*) + # shellcheck disable=SC2162 + saved_IFS=$IFS + IFS="-" read cpu vendor <&2 + exit 1 + ;; + esac + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $vendor in + digital*) + vendor=dec + ;; + commodore*) + vendor=cbm + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if test x$basic_os != x +then + +# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just +# set os. +case $basic_os in + gnu/linux*) + kernel=linux + os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'` + ;; + os2-emx) + kernel=os2 + os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'` + ;; + nto-qnx*) + kernel=nto + os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'` + ;; + *-*) + # shellcheck disable=SC2162 + saved_IFS=$IFS + IFS="-" read kernel os <&2 + exit 1 + ;; +esac + +# As a final step for OS-related things, validate the OS-kernel combination +# (given a valid OS), if there is a kernel. +case $kernel-$os in + linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ + | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* ) + ;; + uclinux-uclibc* ) + ;; + managarm-mlibc* | managarm-kernel* ) + ;; + -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* ) + # These are just libc implementations, not actual OSes, and thus + # require a kernel. + echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 + exit 1 + ;; + -kernel* ) + echo "Invalid configuration \`$1': \`$os' needs explicit kernel." 1>&2 + exit 1 + ;; + *-kernel* ) + echo "Invalid configuration \`$1': \`$kernel' does not support \`$os'." 1>&2 + exit 1 + ;; + kfreebsd*-gnu* | kopensolaris*-gnu*) + ;; + vxworks-simlinux | vxworks-simwindows | vxworks-spe) + ;; + nto-qnx*) + ;; + os2-emx) + ;; + *-eabi* | *-gnueabi*) + ;; + -*) + # Blank kernel with real OS is always fine. + ;; + *-*) + echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 + exit 1 + ;; +esac + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +case $vendor in + unknown) + case $cpu-$os in + *-riscix*) + vendor=acorn + ;; + *-sunos*) + vendor=sun + ;; + *-cnk* | *-aix*) + vendor=ibm + ;; + *-beos*) + vendor=be + ;; + *-hpux*) + vendor=hp + ;; + *-mpeix*) + vendor=hp + ;; + *-hiux*) + vendor=hitachi + ;; + *-unos*) + vendor=crds + ;; + *-dgux*) + vendor=dg + ;; + *-luna*) + vendor=omron + ;; + *-genix*) + vendor=ns + ;; + *-clix*) + vendor=intergraph + ;; + *-mvs* | *-opened*) + vendor=ibm + ;; + *-os400*) + vendor=ibm + ;; + s390-* | s390x-*) + vendor=ibm + ;; + *-ptx*) + vendor=sequent + ;; + *-tpf*) + vendor=ibm + ;; + *-vxsim* | *-vxworks* | *-windiss*) + vendor=wrs + ;; + *-aux*) + vendor=apple + ;; + *-hms*) + vendor=hitachi + ;; + *-mpw* | *-macos*) + vendor=apple + ;; + *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) + vendor=atari + ;; + *-vos*) + vendor=stratus + ;; + esac + ;; +esac + +echo "$cpu-$vendor-${kernel:+$kernel-}$os" +exit + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/krb5-1.21.3/src/config/install-sh b/krb5-1.21.3/src/config/install-sh new file mode 100755 index 00000000..f5061e7e --- /dev/null +++ b/krb5-1.21.3/src/config/install-sh @@ -0,0 +1,295 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2003-09-24.23 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename= +transform_arg= +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd= +chgrpcmd= +stripcmd= +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src= +dst= +dir_arg= + +usage="Usage: $0 [OPTION]... SRCFILE DSTFILE + or: $0 -d DIR1 DIR2... + +In the first form, install SRCFILE to DSTFILE, removing SRCFILE by default. +In the second, create the directory path DIR. + +Options: +-b=TRANSFORMBASENAME +-c copy source (using $cpprog) instead of moving (using $mvprog). +-d create directories instead of installing files. +-g GROUP $chgrp installed files to GROUP. +-m MODE $chmod installed files to MODE. +-o USER $chown installed files to USER. +-s strip installed files (using $stripprog). +-t=TRANSFORM +--help display this help and exit. +--version display version info and exit. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG +" + +while test -n "$1"; do + case $1 in + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + -c) instcmd=$cpprog + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + --help) echo "$usage"; exit 0;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + --version) echo "$0 $scriptversion"; exit 0;; + + *) if test -z "$src"; then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if test -z "$src"; then + echo "$0: no input file specified." >&2 + exit 1 +fi + +# Protect names starting with `-'. +case $src in + -*) src=./$src ;; +esac + +if test -n "$dir_arg"; then + dst=$src + src= + + if test -d "$dst"; then + instcmd=: + chmodcmd= + else + instcmd=$mkdirprog + fi +else + # Waiting for this to be detected by the "$instcmd $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst ;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + dst=$dst/`basename "$src"` + fi +fi + +# This sed command emulates the dirname command. +dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. + +# Skip lots of stat calls in the usual case. +if test ! -d "$dstdir"; then + defaultIFS=' + ' + IFS="${IFS-$defaultIFS}" + + oIFS=$IFS + # Some sh's can't handle IFS=/ for some reason. + IFS='%' + set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` + IFS=$oIFS + + pathcomp= + + while test $# -ne 0 ; do + pathcomp=$pathcomp$1 + shift + test -d "$pathcomp" || $mkdirprog "$pathcomp" + pathcomp=$pathcomp/ + done +fi + +if test -n "$dir_arg"; then + $doit $instcmd "$dst" \ + && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } + +else + # If we're going to rename the final executable, determine the name now. + if test -z "$transformarg"; then + dstfile=`basename "$dst"` + else + dstfile=`basename "$dst" $transformbasename \ + | sed $transformarg`$transformbasename + fi + + # don't allow the sed command to completely eliminate the filename. + test -z "$dstfile" && dstfile=`basename "$dst"` + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 + trap '(exit $?); exit' 1 2 13 15 + + # Move or copy the file name to the temp name + $doit $instcmd "$src" "$dsttmp" && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $instcmd $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ + && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ + && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ + && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && + + # Now remove or move aside any old file at destination location. We + # try this two ways since rm can't unlink itself on some systems and + # the destination file might be busy for other reasons. In this case, + # the final cleanup might fail but the new file should still install + # successfully. + { + if test -f "$dstdir/$dstfile"; then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ + || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ + || { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" +fi && + +# The final little trick to "correctly" pass the exit status to the exit trap. +{ + (exit 0); exit +} + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/krb5-1.21.3/src/config/lib.in b/krb5-1.21.3/src/config/lib.in new file mode 100644 index 00000000..774e120a --- /dev/null +++ b/krb5-1.21.3/src/config/lib.in @@ -0,0 +1,164 @@ +### config/lib.in +# *** keep this in sync with libnover.in +# +# Makefile fragment that creates static, shared, and profiled libraries. +# +# The following variables must be set in the Makefile.in: +# +# LIBBASE library name without "lib" or extension +# LIBMAJOR library major version +# LIBMINOR library minor version +# SHLIB_EXPDEPS list of libraries that this one has explicit +# dependencies on, pref. in the form libfoo$(SHLIBEXT) +# SHLIB_EXPLIBS list of libraries that this one has explicit +# dependencies on, in "-lfoo" form. +# RELDIR path to this directory relative to $(TOPLIBD) +# +# Makefile.in can also override the defaults for SHLIB_DIRS, +# SHLIB_RDIRS, and STOBJLISTS from pre.in. + +LIBPREFIX=lib + +SHOBJLISTS=$(STOBJLISTS:.ST=.SH) +PFOBJLISTS=$(STOBJLISTS:.ST=.PF) + +dummy-target-1 $(SUBDIROBJLISTS) $(SUBDIROBJLISTS:.ST=.SH) $(SUBDIROBJLISTS:.ST=.PF): all-recurse + +# Gets invoked as $(PARSE_OBJLISTS) list-of-OBJS.*-files +PARSE_OBJLISTS= set -x && $(PERL) -p -e 'BEGIN { $$SIG{__WARN__} = sub {die @_} }; $$e=$$ARGV; $$e =~ s/OBJS\...$$//; s/^/ /; s/ $$//; s/ / $$e/g;' + +lib$(LIBBASE)$(STLIBEXT): $(STOBJLISTS) + $(RM) $@ + @echo "building static $(LIBBASE) library" + set -x; objlist=`$(PARSE_OBJLISTS) $(STOBJLISTS)` && $(AR) cq $@ $$objlist + $(RANLIB) $@ + +lib$(LIBBASE)$(SHLIBVEXT): $(SHOBJLISTS) $(SHLIB_EXPDEPS) $(SHLIB_EXPORT_FILE_DEP) + $(RM) $@ + @echo "building shared $(LIBBASE) library ($(LIBMAJOR).$(LIBMINOR))" + set -x; objlist=`$(PARSE_OBJLISTS) $(SHOBJLISTS)` && $(MAKE_SHLIB_COMMAND) + +lib$(LIBBASE)$(SHLIBSEXT): lib$(LIBBASE)$(SHLIBVEXT) + $(RM) $@ + $(LN_S) lib$(LIBBASE)$(SHLIBVEXT) $@ +lib$(LIBBASE)$(SHLIBEXT): lib$(LIBBASE)$(SHLIBVEXT) + $(RM) $@ + $(LN_S) lib$(LIBBASE)$(SHLIBVEXT) $@ + +binutils.versions: $(SHLIB_EXPORT_FILE) Makefile + base=`echo "$(LIBBASE)" | sed -e 's/-/_/'`; \ + echo > binutils.versions "$${base}_$(LIBMAJOR)_MIT {" + sed >> binutils.versions < $(SHLIB_EXPORT_FILE) "s/$$/;/" + echo >> binutils.versions "};" + echo >> binutils.versions "HIDDEN { local: __*; _rest*; _save*; *; };" + +darwin.exports: $(SHLIB_EXPORT_FILE) Makefile + sed > darwin-exports.tmp < $(SHLIB_EXPORT_FILE) "s/^/_/" + $(MV) darwin-exports.tmp darwin.exports + +osf1.exports: $(SHLIB_EXPORT_FILE) Makefile + $(RM) osf1.tmp osf1.exports + sed "s/^/-exported_symbol /" < $(SHLIB_EXPORT_FILE) > osf1.tmp + for f in . $(LIBINITFUNC); do \ + if test "$$f" != "." ; then \ + echo " -init $$f"__auxinit >> osf1.tmp; \ + else :; fi; \ + done + a=""; \ + for f in . $(LIBFINIFUNC); do \ + if test "$$f" != "." ; then \ + a="-fini $$f $$a"; \ + else :; fi; \ + done; echo " $$a" >> osf1.tmp + mv -f osf1.tmp osf1.exports + +hpux.exports: $(SHLIB_EXPORT_FILE) Makefile + $(RM) hpux.tmp hpux.exports + sed "s/^/+e /" < $(SHLIB_EXPORT_FILE) > hpux.tmp + a=""; \ + for f in . $(LIBFINIFUNC); do \ + if test "$$f" != .; then \ + a="+I $${f}__auxfini $$a"; \ + else :; fi; \ + done; echo "$$a" >> hpux.tmp + echo "+e errno" >> hpux.tmp + base=`echo "$(LIBBASE)" | sed -e 's/-/_/'`; \ + echo "+e _GLOBAL__FD_lib$${base}_$(LIBMAJOR)_$(LIBMINOR)" >> hpux.tmp; \ + echo "+e _GLOBAL__FI_lib$${base}_$(LIBMAJOR)_$(LIBMINOR)" >> hpux.tmp + mv -f hpux.tmp hpux.exports + +lib$(LIBBASE)$(PFLIBEXT): $(PFOBJLISTS) + $(RM) $@ + @echo "building profiled $(LIBBASE) library" + set -x; objlist=`$(PARSE_OBJLISTS) $(PFOBJLISTS)` && $(AR) cq $@ $$objlist + $(RANLIB) $@ + +$(TOPLIBD)/lib$(LIBBASE)$(STLIBEXT): lib$(LIBBASE)$(STLIBEXT) + $(RM) $@ + (cd $(TOPLIBD) && $(LN_S) $(RELDIR)/lib$(LIBBASE)$(STLIBEXT) .) +$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT): lib$(LIBBASE)$(SHLIBEXT) + $(RM) $@ + (cd $(TOPLIBD) && $(LN_S) $(RELDIR)/lib$(LIBBASE)$(SHLIBEXT) .) +$(TOPLIBD)/lib$(LIBBASE)$(SHLIBSEXT): lib$(LIBBASE)$(SHLIBSEXT) + $(RM) $@ + (cd $(TOPLIBD) && $(LN_S) $(RELDIR)/lib$(LIBBASE)$(SHLIBSEXT) .) +$(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT): lib$(LIBBASE)$(SHLIBVEXT) + $(RM) $@ + (cd $(TOPLIBD) && $(LN_S) $(RELDIR)/lib$(LIBBASE)$(SHLIBVEXT) .) +$(TOPLIBD)/lib$(LIBBASE)$(PFLIBEXT): lib$(LIBBASE)$(PFLIBEXT) + $(RM) $@ + (cd $(TOPLIBD) && $(LN_S) $(RELDIR)/lib$(LIBBASE)$(PFLIBEXT) .) + +all-libs: $(LIBLIST) +all-liblinks: $(LIBLINKS) + +clean-libs: + $(RM) lib$(LIBBASE)$(STLIBEXT) + $(RM) lib$(LIBBASE)$(SHLIBVEXT) + $(RM) lib$(LIBBASE)$(SHLIBSEXT) + $(RM) lib$(LIBBASE)$(SHLIBEXT) + $(RM) lib$(LIBBASE)$(PFLIBEXT) + $(RM) binutils.versions osf1.exports darwin.exports hpux.exports + +clean-liblinks: + $(RM) $(TOPLIBD)/lib$(LIBBASE)$(STLIBEXT) + $(RM) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT) + $(RM) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBSEXT) + $(RM) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) + $(RM) $(TOPLIBD)/lib$(LIBBASE)$(PFLIBEXT) + +install-libs: $(LIBINSTLIST) +install-static: + $(RM) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(STLIBEXT) + $(INSTALL_DATA) lib$(LIBBASE)$(STLIBEXT) $(DESTDIR)$(KRB5_LIBDIR) + $(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(STLIBEXT) +install-shared: + $(RM) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(SHLIBVEXT) + $(RM) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(SHLIBEXT) + $(INSTALL_SHLIB) lib$(LIBBASE)$(SHLIBVEXT) $(DESTDIR)$(KRB5_LIBDIR) + (cd $(DESTDIR)$(KRB5_LIBDIR) && $(LN_S) lib$(LIBBASE)$(SHLIBVEXT) \ + lib$(LIBBASE)$(SHLIBEXT)) +install-shlib-soname: install-shared + $(RM) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(SHLIBSEXT) + (cd $(DESTDIR)$(KRB5_LIBDIR) && $(LN_S) lib$(LIBBASE)$(SHLIBVEXT) \ + lib$(LIBBASE)$(SHLIBSEXT)) +install-profiled: + $(RM) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(PFLIBEXT) + $(INSTALL_DATA) lib$(LIBBASE)$(PFLIBEXT) $(DESTDIR)$(KRB5_LIBDIR) + $(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/lib$(LIBBASE)$(PFLIBEXT) + +Makefile: $(top_srcdir)/config/lib.in +$(BUILDTOP)/config.status: $(top_srcdir)/config/shlib.conf + +# Use the following if links need to be made to $(TOPLIBD): +# all-unix: all-liblinks +# install-unix: install-libs +# clean-unix:: clean-liblinks clean-libs + +# Use the following if links need not be made: +# all-unix: all-libs +# install-unix: install-libs +# clean-unix:: clean-libs + +### +### end config/lib.in diff --git a/krb5-1.21.3/src/config/libnodeps.in b/krb5-1.21.3/src/config/libnodeps.in new file mode 100644 index 00000000..6416a300 --- /dev/null +++ b/krb5-1.21.3/src/config/libnodeps.in @@ -0,0 +1,4 @@ +# Must override when there are no dependencies, because on some +# platforms there's a prefix stuck in front of the library path that +# we won't set (SHLIB_RDIRS). +SHLIB_EXPFLAGS= diff --git a/krb5-1.21.3/src/config/libnover.in b/krb5-1.21.3/src/config/libnover.in new file mode 100644 index 00000000..ab6baea8 --- /dev/null +++ b/krb5-1.21.3/src/config/libnover.in @@ -0,0 +1,132 @@ +### config/libnover.in +# *** keep this in sync with lib.in +# +# Makefile fragment that creates shared libraries sans version +# info (plugin modules). +# +# The following variables must be set in the Makefile.in: +# +# LIBBASE library name without "lib" or extension +# SHLIB_EXPDEPS list of libraries that this one has explicit +# dependencies on, pref. in the form libfoo$(SHLIBEXT) +# SHLIB_EXPLIBS list of libraries that this one has explicit +# dependencies on, in "-lfoo" form. +# RELDIR path to this directory relative to $(TOPLIBD) +# +# Makefile.in can also override the defaults for SHLIB_DIRS, +# SHLIB_RDIRS, and STOBJLISTS from pre.in. + +LIBPREFIX= + +SHOBJLISTS=$(STOBJLISTS:.ST=.SH) +PFOBJLISTS=$(STOBJLISTS:.ST=.PF) + +dummy-target-1 $(SUBDIROBJLISTS) $(SUBDIROBJLISTS:.ST=.SH) $(SUBDIROBJLISTS:.ST=.PF): all-recurse + +# Gets invoked as $(PARSE_OBJLISTS) list-of-OBJS.*-files +PARSE_OBJLISTS= set -x && $(PERL) -p -e 'BEGIN { $$SIG{__WARN__} = sub {die @_} }; $$e=$$ARGV; $$e =~ s/OBJS\...$$//; s/^/ /; s/ $$//; s/ / $$e/g;' + +LIBINSTLIST=install-shared + +libkrb5_$(LIBBASE)$(STLIBEXT): $(STOBJLISTS) + $(RM) $@ + @echo "building static $(LIBBASE) library" + set -x; objlist=`$(PARSE_OBJLISTS) $(STOBJLISTS)` && $(AR) cq $@ $$objlist + $(RANLIB) $@ + +$(LIBBASE)$(DYNOBJEXT): $(SHOBJLISTS) $(DYNOBJ_EXPDEPS) $(SHLIB_EXPORT_FILE_DEP) + $(RM) $@ + @echo "building dynamic $(LIBBASE) object" + set -x; objlist=`$(PARSE_OBJLISTS) $(SHOBJLISTS)` && $(MAKE_DYNOBJ_COMMAND) + +binutils.versions: $(SHLIB_EXPORT_FILE) Makefile + echo > binutils.versions "HIDDEN { local: __*; _rest*; _save*; *; };" + echo >> binutils.versions "$(LIBBASE)_$(LIBMAJOR)_MIT {" + sed >> binutils.versions < $(SHLIB_EXPORT_FILE) "s/$$/;/" + echo >> binutils.versions "};" + +osf1.exports: $(SHLIB_EXPORT_FILE) Makefile + $(RM) osf1.tmp osf1.exports + sed "s/^/-exported_symbol /" < $(SHLIB_EXPORT_FILE) > osf1.tmp + for f in . $(LIBINITFUNC); do \ + if test "$$f" != "." ; then \ + echo " -init $$f"__auxinit >> osf1.tmp; \ + else :; fi; \ + done + a=""; \ + for f in . $(LIBFINIFUNC); do \ + if test "$$f" != "." ; then \ + a="-fini $$f $$a"; \ + else :; fi; \ + done; echo " $$a" >> osf1.tmp; \ + mv -f osf1.tmp osf1.exports + +hpux.exports: $(SHLIB_EXPORT_FILE) Makefile + $(RM) hpux.tmp hpux.exports + sed "s/^/+e /" < $(SHLIB_EXPORT_FILE) > hpux.tmp + a=""; \ + for f in . $(LIBFINIFUNC); do \ + if test "$$f" != .; then \ + a="+I $${f}__auxfini $$a"; \ + else :; fi; \ + done; echo "$$a" >> hpux.tmp + echo "+e errno" >> hpux.tmp + mv -f hpux.tmp hpux.exports + +darwin.exports: $(SHLIB_EXPORT_FILE) Makefile + $(RM) darwin.exports + sed "s/^/_/" < $(SHLIB_EXPORT_FILE) > darwin.exports + +libkrb5_$(LIBBASE)$(PFLIBEXT): $(PFOBJLISTS) + $(RM) $@ + @echo "building profiled $(LIBBASE) library" + set -x; objlist=`$(PARSE_OBJLISTS) $(PFOBJLISTS)` && $(AR) cq $@ $$objlist + $(RANLIB) $@ + +# For static builds, we make a symlink in the main library directory, +# allowing the plugin library to be a dependency of the core libraries +# which use it. +$(TOPLIBD)/libkrb5_$(LIBBASE)$(STLIBEXT): + $(RM) $@ + (cd $(TOPLIBD) && $(LN_S) $(RELDIR)/libkrb5_$(LIBBASE)$(STLIBEXT) .) + +# For shared builds, we make a symlink in the parent directory, allowing +# tests to point plugin_base_dir at $(BUILDTOP)/plugins. +../$(LIBBASE)$(DYNOBJEXT): + $(RM) $@ + (cd .. && $(LN_S) `basename $(mydir)`/$(LIBBASE)$(DYNOBJEXT) .) + +all-liblinks: all-libs $(PLUGINLINK) +all-libs: $(PLUGIN) + +clean-libs: + $(RM) $(LIBBASE)$(DYNOBJEXT) + $(RM) binutils.versions osf1.exports darwin.exports hpux.exports + +clean-liblinks: + $(RM) $(PLUGINLINK) + +install-libs: $(PLUGININST) +install-static: + $(RM) $(DESTDIR)$(KRB5_LIBDIR)/libkrb5_$(LIBBASE)$(STLIBEXT) + $(INSTALL_DATA) libkrb5_$(LIBBASE)$(STLIBEXT) $(DESTDIR)$(KRB5_LIBDIR) + $(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/libkrb5_$(LIBBASE)$(STLIBEXT) +install-plugin: + $(RM) $(DESTDIR)$(MODULE_INSTALL_DIR)/$(LIBBASE)$(DYNOBJEXT) + $(INSTALL_SHLIB) $(LIBBASE)$(DYNOBJEXT) $(DESTDIR)$(MODULE_INSTALL_DIR) + +Makefile: $(top_srcdir)/config/libnover.in +$(BUILDTOP)/config.status: $(top_srcdir)/config/shlib.conf + +# Use the following if links need to be made to $(TOPLIBD): +# all-unix: all-liblinks +# install-unix: install-libs +# clean-unix:: clean-liblinks clean-libs + +# Use the following if links need not be made: +# all-unix: all-libs +# install-unix: install-libs +# clean-unix:: clean-libs + +### +### end config/libnovers.in diff --git a/krb5-1.21.3/src/config/libobj.in b/krb5-1.21.3/src/config/libobj.in new file mode 100644 index 00000000..0f7d2f5b --- /dev/null +++ b/krb5-1.21.3/src/config/libobj.in @@ -0,0 +1,42 @@ +### config/libobj.in +# +# Makefile fragment that builds object files for libraries. +# +# The following variables must be set in Makefile.in: +# +# STLIBOBJS list of .o objects; this must not contain variable +# references. + +.SUFFIXES: .c .so .po +.c.so: + $(CC) $(PICFLAGS) -DSHARED $(ALL_CFLAGS) -c $< -o $*.so.o && $(MV) $*.so.o $*.so +.c.po: + $(CC) $(PROFFLAGS) $(ALL_CFLAGS) -c $< -o $*.po.o && $(MV) $*.po.o $*.po + +# rules to generate object file lists + +OBJS.ST: $(STLIBOBJS) Makefile + @echo $(STLIBOBJS) > $@ + : updated $@ + +OBJS.SH: $(SHLIBOBJS) Makefile + @echo $(SHLIBOBJS) > $@ + : updated $@ + +OBJS.PF: $(PFLIBOBJS) Makefile + @echo $(PFLIBOBJS) > $@ + : updated $@ + +all-libobjs: $(OBJLISTS) + +clean-libobjs: + $(RM) OBJS.ST OBJS.SH OBJS.PF $(STLIBOBJS) $(SHLIBOBJS) $(PFLIBOBJS) + +Makefile: $(top_srcdir)/config/libobj.in +config.status: $(top_srcdir)/config/shlib.conf + +# clean-unix:: clean-libobjs +# all-unix: all-libobjs + +### +### end config/libobj.in diff --git a/krb5-1.21.3/src/config/libpriv.in b/krb5-1.21.3/src/config/libpriv.in new file mode 100644 index 00000000..4fe13c3b --- /dev/null +++ b/krb5-1.21.3/src/config/libpriv.in @@ -0,0 +1,12 @@ +# Additional definitions for private libraries, which we build as archive +# libraries (or equivalent) and do not install. +# +# The defaults (for installed shared libraries) are in pre.in. We +# override them here, before lib.in uses them. +LIBLIST=lib$(LIBBASE)$(STLIBEXT) +LIBLINKS=$(TOPLIBD)/lib$(LIBBASE)$(STLIBEXT) +OBJLISTS=OBJS.ST +LIBINSTLIST= +SHLIBEXT=.so-nobuild +SHLIBVEXT=.so.v-nobuild +SHLIBSEXT=.so.s-nobuild diff --git a/krb5-1.21.3/src/config/mkinstalldirs b/krb5-1.21.3/src/config/mkinstalldirs new file mode 100755 index 00000000..6b3b5fc5 --- /dev/null +++ b/krb5-1.21.3/src/config/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id$ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/krb5-1.21.3/src/config/move-if-changed b/krb5-1.21.3/src/config/move-if-changed new file mode 100755 index 00000000..21403e12 --- /dev/null +++ b/krb5-1.21.3/src/config/move-if-changed @@ -0,0 +1,17 @@ +#!/bin/sh +# Move file 1 to file 2 if they don't already match. +# Good for "make depend" for example, where it'd be nice to keep the +# old datestamp. +if [ $# != 2 ]; then + echo 2>&1 usage: $0 newfile oldfilename + exit 1 +fi +# +if [ ! -r "$2" ]; then + exec mv -f "$1" "$2" +fi +if cmp "$1" "$2" >/dev/null; then + echo "$2 is unchanged" + exec rm -f "$1" +fi +exec mv -f "$1" "$2" diff --git a/krb5-1.21.3/src/config/pkg.m4 b/krb5-1.21.3/src/config/pkg.m4 new file mode 100644 index 00000000..01628d8a --- /dev/null +++ b/krb5-1.21.3/src/config/pkg.m4 @@ -0,0 +1,275 @@ +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# serial 12 (pkg-config-0.29.2) + +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.2]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $2]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR diff --git a/krb5-1.21.3/src/config/post.in b/krb5-1.21.3/src/config/post.in new file mode 100644 index 00000000..4d0cb753 --- /dev/null +++ b/krb5-1.21.3/src/config/post.in @@ -0,0 +1,242 @@ +############################################################ +## config/post.in +## + +# in case there is no default target (very unlikely) +all: + +check-windows: + +# In a few parts of "make check" we run shell scripts which run +# programs linked against krb5 libraries. On macOS 10.11 and higher, +# DYLD_LIBRARY_PATH is cleared by the shell unless System Integrity +# Protection is turned off, so we need to set runtime linker +# environment variables from within test scripts. A Makefile.in which +# runs shell script tests should make its check rule depend on +# runenv.sh and make each script begin with ". ./runenv.sh". +runenv.sh: + $(RUN_SETUP); for i in $(RUN_VARS); do \ + eval echo "$$i=\\\"\$$$$i\\\""; \ + echo "export $$i"; done > $@ + +############################## +# dependency generation +# + +depend: depend-postrecurse +depend-postrecurse: depend-recurse +depend-recurse: depend-prerecurse + +depend-prerecurse: +depend-postrecurse: + +depend-postrecurse: depend-update-makefile + +ALL_DEP_SRCS= $(SRCS) $(EXTRADEPSRCS) + +# be sure to check ALL_DEP_SRCS against *what it would be if SRCS and +# EXTRADEPSRCS are both empty* +$(BUILDTOP)/.depend-verify-srcdir: + @if test "$(srcdir)" = "." ; then \ + echo 1>&2 error: cannot build dependencies with srcdir=. ; \ + echo 1>&2 "(can't distinguish generated files from source files)" ; \ + echo 1>&2 "Run 'make distclean' and create a separate build dir" ; \ + exit 1 ; \ + elif test -f "$(top_srcdir)/include/autoconf.h"; then \ + echo 1>&2 "error: generated headers found in source tree" ; \ + echo 1>&2 "Run 'make distclean' in source tree first" ; \ + exit 1 ; \ + else \ + if test -r $(BUILDTOP)/.depend-verify-srcdir; then :; \ + else (set -x; touch $(BUILDTOP)/.depend-verify-srcdir); fi \ + fi +$(BUILDTOP)/.depend-verify-et: depend-verify-et-$(COM_ERR_VERSION) +depend-verify-et-k5: + @if test -r $(BUILDTOP)/.depend-verify-et; then :; \ + else (set -x; touch $(BUILDTOP)/.depend-verify-et); fi +depend-verify-et-sys depend-verify-et-intlsys: + @echo 1>&2 error: cannot build dependencies using system et package + @exit 1 +$(BUILDTOP)/.depend-verify-ss: depend-verify-ss-$(SS_VERSION) +depend-verify-ss-k5: + @if test -r $(BUILDTOP)/.depend-verify-ss; then :; \ + else (set -x; touch $(BUILDTOP)/.depend-verify-ss); fi +depend-verify-ss-sys: + @echo 1>&2 error: cannot build dependencies using system ss package + @exit 1 +$(BUILDTOP)/.depend-verify-verto: depend-verify-verto-$(VERTO_VERSION) +depend-verify-verto-k5: + @if test -r $(BUILDTOP)/.depend-verify-verto; then :; \ + else (set -x; touch $(BUILDTOP)/.depend-verify-verto); fi +depend-verify-verto-sys: + @echo 1>&2 error: cannot build dependencies using system verto package + @echo 1>&2 Please configure with --without-system-verto + @exit 1 +$(BUILDTOP)/.depend-verify-gcc: depend-verify-gcc-@HAVE_GCC@ +depend-verify-gcc-yes: + @if test -r $(BUILDTOP)/.depend-verify-gcc; then :; \ + else (set -x; touch $(BUILDTOP)/.depend-verify-gcc); fi +depend-verify-gcc-no: + @echo 1>&2 error: The '"depend"' rules are written for gcc. + @echo 1>&2 Please use gcc, or update the rules to handle your compiler. + @exit 1 + +DEP_CFG_VERIFY = $(BUILDTOP)/.depend-verify-srcdir \ + $(BUILDTOP)/.depend-verify-et $(BUILDTOP)/.depend-verify-ss \ + $(BUILDTOP)/.depend-verify-verto +DEP_VERIFY = $(DEP_CFG_VERIFY) $(BUILDTOP)/.depend-verify-gcc + +.d: $(ALL_DEP_SRCS) $(DEP_CFG_VERIFY) depend-dependencies + if test "$(ALL_DEP_SRCS)" != " " ; then \ + $(RM) .dtmp && $(MAKE) .dtmp && mv -f .dtmp .d ; \ + else \ + touch .d ; \ + fi + +# These are dependencies of the depend target that do not get fed to +# the compiler. Examples include generated header files. +depend-dependencies: + +# .dtmp must *always* be out of date so that $? can be used to perform +# VPATH searches on the sources. +# +# NOTE: This will fail when using Make programs whose VPATH support is +# broken. +.dtmp: $(ALL_DEP_SRCS) + $(CC) -M -DDEPEND $(ALL_CFLAGS) $? > .dtmp + +# NOTE: This will also generate spurious $(OUTPRE) and $(OBJEXT) +# references in rules for non-library objects in a directory where +# library objects happen to be built. It's mostly harmless. +.depend: .d $(top_srcdir)/util/depfix.pl + perl $(top_srcdir)/util/depfix.pl '$(top_srcdir)' '$(mydir)' \ + '$(srcdir)' '$(BUILDTOP)' '$(STLIBOBJS)' < .d > .depend + +# Temporarily keep the rule for removing the dependency line eater +# until we're sure we've gotten everything converted and excised the +# old stuff from Makefile.in files. +depend-update-makefile: .depend depend-recurse + if test "$(ALL_DEP_SRCS)" != " " ; then \ + $(CP) .depend $(srcdir)/deps.new ; \ + else \ + echo "# No dependencies here." > $(srcdir)/deps.new ; \ + fi + $(top_srcdir)/config/move-if-changed $(srcdir)/deps.new $(srcdir)/deps + sed -e '/^# +++ Dependency line eater +++/,$$d' \ + < $(srcdir)/Makefile.in > $(srcdir)/Makefile.in.new + $(top_srcdir)/config/move-if-changed $(srcdir)/Makefile.in.new \ + $(srcdir)/Makefile.in + +DEPTARGETS = .depend .d .dtmp $(DEP_VERIFY) +DEPTARGETS_CLEAN = .depend .d .dtmp $(DEPTARGETS_@srcdir@_@CONFIG_RELTOPDIR@) +DEPTARGETS_@top_srcdir@_. = $(DEP_VERIFY) + +# Clear out dependencies. Should only be used temporarily, e.g., while +# moving or renaming headers and then rebuilding dependencies. +undepend: undepend-postrecurse +undepend-recurse: +undepend-postrecurse: undepend-recurse + if test -n "$(SRCS)" ; then \ + sed -e '/^# +++ Dependency line eater +++/,$$d' \ + < $(srcdir)/Makefile.in \ + > $(srcdir)/Makefile.in.new ;\ + echo "# +++ Dependency line eater +++" >> $(srcdir)/Makefile.in.new ;\ + echo "# (dependencies temporarily removed)" >> $(srcdir)/Makefile.in.new ;\ + $(top_srcdir)/config/move-if-changed $(srcdir)/Makefile.in.new $(srcdir)/Makefile.in;\ + else :; fi + +# +# end dependency generation +############################## + +# Python tests +check-unix: check-pytests-@HAVE_PYTHON@ + +# Makefile.in should add rules to check-pytests to execute Python tests. +check-pytests-yes: check-pytests +check-pytests-no: +check-pytests: + +# cmocka tests +check-unix: check-cmocka-@HAVE_CMOCKA@ + +check-cmocka-yes: check-cmocka +check-cmocka-no: +check-cmocka: + +clean: clean-$(WHAT) + +clean-unix:: + $(RM) $(OBJS) $(DEPTARGETS_CLEAN) $(EXTRA_FILES) + $(RM) et-[ch]-*.et et-[ch]-*.[ch] testlog testtrace runenv.sh + -$(RM) -r testdir + +clean-windows:: + $(RM) *.$(OBJEXT) + $(RM) msvc.pdb *.err + +distclean: distclean-$(WHAT) + +distclean-normal-clean: + $(MAKE) NORECURSE=true clean +distclean-prerecurse: distclean-normal-clean +distclean-nuke-configure-state: + $(RM) config.log config.cache config.status Makefile +distclean-postrecurse: distclean-nuke-configure-state + +Makefiles-prerecurse: Makefile + +# mydir = relative path from top to this Makefile +Makefile: $(srcdir)/Makefile.in $(srcdir)/deps $(BUILDTOP)/config.status \ + $(top_srcdir)/config/pre.in $(top_srcdir)/config/post.in + (cd $(BUILDTOP) && $(SHELL) config.status $(mydir)/Makefile) +$(BUILDTOP)/config.status: $(top_srcdir)/configure + (cd $(BUILDTOP) && $(SHELL) config.status --recheck) +$(top_srcdir)/configure: @MAINT@ \ + $(top_srcdir)/configure.ac \ + $(top_srcdir)/patchlevel.h \ + $(top_srcdir)/aclocal.m4 + (cd $(top_srcdir) && \ + $(AUTOCONF) -f --include=$(CONFIG_RELTOPDIR) $(AUTOCONFFLAGS)) + +RECURSE_TARGETS=all-recurse clean-recurse distclean-recurse install-recurse \ + generate-files-mac-recurse \ + check-recurse depend-recurse undepend-recurse \ + Makefiles-recurse install-headers-recurse + +# MY_SUBDIRS overrides any setting of SUBDIRS generated by the +# configure script that generated this Makefile. This is needed when +# the configure script that produced this Makefile creates multiple +# Makefiles in different directories; the setting of SUBDIRS will be +# the same in each. +# +# LOCAL_SUBDIRS seems to account for the case where the configure +# script doesn't call any other subsidiary configure scripts, but +# generates multiple Makefiles. +$(RECURSE_TARGETS): + @case "`echo 'x$(MFLAGS)'|sed -e 's/^x//' -e 's/ --.*$$//'`" \ + in *[ik]*) e="status=1" ;; *) e="exit 1";; esac; \ + do_subdirs="$(SUBDIRS)" ; \ + status=0; \ + if test -n "$$do_subdirs" && test -z "$(NORECURSE)"; then \ + for i in $$do_subdirs ; do \ + if test -d $$i && test -r $$i/Makefile ; then \ + case $$i in .);; *) \ + target=`echo $@|sed s/-recurse//`; \ + echo "making $$target in $(CURRENT_DIR)$$i..."; \ + if (cd $$i ; $(MAKE) \ + CURRENT_DIR=$(CURRENT_DIR)$$i/ $$target) then :; \ + else eval $$e; fi; \ + ;; \ + esac; \ + else \ + echo "Skipping missing directory $(CURRENT_DIR)$$i" ; \ + fi; \ + done; \ + else :; \ + fi;\ + exit $$status + +## +## end of post.in +############################################################ diff --git a/krb5-1.21.3/src/config/pre.in b/krb5-1.21.3/src/config/pre.in new file mode 100644 index 00000000..a0c60c70 --- /dev/null +++ b/krb5-1.21.3/src/config/pre.in @@ -0,0 +1,610 @@ +############################################################ +## config/pre.in +## common prefix for all Makefile.in in the Kerberos V5 tree. +## + +# These are set per-directory by autoconf 2.52 and 2.53: +# srcdir=@srcdir@ +# top_srcdir=@top_srcdir@ +# but these are only set by autoconf 2.53, and thus not useful to us on +# macOS yet (as of 10.2): +# abs_srcdir=@abs_srcdir@ +# abs_top_srcdir=@abs_top_srcdir@ +# builddir=@builddir@ +# abs_builddir=@abs_builddir@ +# top_builddir=@top_builddir@ +# abs_top_builddir=@abs_top_builddir@ +# The "top" variables refer to the directory with the configure (or +# config.status) script. + +WHAT = unix +SHELL=/bin/sh + +all: all-$(WHAT) + +clean: clean-$(WHAT) + +distclean: distclean-$(WHAT) + +install: install-$(WHAT) + +check: check-$(WHAT) + +install-headers: install-headers-$(WHAT) + +############################## +# Recursion rule support +# + +# The commands for the recursion targets live in config/post.in. +# +# General form of recursion rules: +# +# Each recursive target foo-unix has related targets: foo-prerecurse, +# foo-recurse, and foo-postrecurse +# +# The foo-recurse rule is in post.in. It is what actually recursively +# calls make. +# +# foo-recurse depends on foo-prerecurse, so any targets that must be +# built before descending into subdirectories must be dependencies of +# foo-prerecurse. +# +# foo-postrecurse depends on foo-recurse, but targets that must be +# built after descending into subdirectories should be have +# foo-recurse as dependencies in addition to being listed under +# foo-postrecurse, to avoid ordering issues. +# +# The foo-prerecurse, foo-recurse, and foo-postrecurse rules are all +# single-colon rules, to avoid nasty ordering problems with +# double-colon rules. +# +# e.g. +# all: includes foo +# foo: +# echo foo +# includes: +# echo bar +# includes: +# echo baz +# +# will result in "bar", "foo", "baz" on AIX, and possibly others. +all-unix: all-postrecurse +all-postrecurse: all-recurse +all-recurse: all-prerecurse + +all-prerecurse: +all-postrecurse: + +clean-unix:: clean-postrecurse +clean-postrecurse: clean-recurse +clean-recurse: clean-prerecurse + +clean-prerecurse: +clean-postrecurse: + +distclean-unix: distclean-postrecurse +distclean-postrecurse: distclean-recurse +distclean-recurse: distclean-prerecurse + +distclean-prerecurse: +distclean-postrecurse: + +install-unix: install-postrecurse +install-postrecurse: install-recurse +install-recurse: install-prerecurse + +install-prerecurse: +install-postrecurse: + +install-headers-unix: install-headers-postrecurse +install-headers-postrecurse: install-headers-recurse +install-headers-recurse: install-headers-prerecurse + +install-headers-prerecurse: +install-headers-postrecurse: + +check-unix: check-postrecurse +check-postrecurse: check-recurse +check-recurse: check-prerecurse + +check-prerecurse: +check-postrecurse: + +Makefiles: Makefiles-postrecurse +Makefiles-postrecurse: Makefiles-recurse +Makefiles-recurse: Makefiles-prerecurse + +Makefiles-prerecurse: +Makefiles-postrecurse: + +generate-files-mac: generate-files-mac-postrecurse +generate-files-mac-postrecurse: generate-files-mac-recurse +generate-files-mac-recurse: generate-files-mac-prerecurse +generate-files-mac-prerecurse: + +# +# end recursion rule support +############################## + +# Directory syntax: +# +# begin relative path +REL= +# this is magic... should only be used for preceding a program invocation +C=./ +# "/" for UNIX, "\" for Windows; *sigh* +S=/ + +# +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +CONFIG_RELTOPDIR = @CONFIG_RELTOPDIR@ + +# DEFS set by configure +# DEFINES set by local Makefile.in +# LOCALINCLUDES set by local Makefile.in +# CPPFLAGS user override +# CFLAGS user override but starts off set by configure +# WARN_CFLAGS user override but starts off set by configure +# PTHREAD_CFLAGS set by configure, not included in CFLAGS so that we +# don't pull the pthreads library into shared libraries +# ASAN_FLAGS set by configure when --enable-asan is used +ALL_CFLAGS = $(DEFS) $(DEFINES) $(KRB_INCLUDES) $(LOCALINCLUDES) \ + -DKRB5_DEPRECATED=1 \ + -DKRB5_PRIVATE \ + $(CPPFLAGS) $(CFLAGS) $(WARN_CFLAGS) $(PTHREAD_CFLAGS) $(ASAN_FLAGS) +ALL_CXXFLAGS = $(DEFS) $(DEFINES) $(KRB_INCLUDES) $(LOCALINCLUDES) \ + -DKRB5_DEPRECATED=1 \ + -DKRB5_PRIVATE \ + $(CPPFLAGS) $(CXXFLAGS) $(WARN_CXXFLAGS) $(PTHREAD_CFLAGS) \ + $(ASAN_FLAGS) + +CFLAGS = @CFLAGS@ +CXXFLAGS = @CXXFLAGS@ +WARN_CFLAGS = @WARN_CFLAGS@ +WARN_CXXFLAGS = @WARN_CXXFLAGS@ +ASAN_FLAGS = @ASAN_FLAGS@ +PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ +PTHREAD_LIBS = @PTHREAD_LIBS@ +THREAD_LINKOPTS = $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) +CPPFLAGS = @CPPFLAGS@ +DEFS = @DEFS@ +CC = @CC@ +CXX = @CXX@ +LD = $(PURE) @LD@ +KRB_INCLUDES = -I$(BUILDTOP)/include -I$(top_srcdir)/include +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +INSTALL=@INSTALL@ +INSTALL_STRIP= +INSTALL_PROGRAM=@INSTALL_PROGRAM@ $(INSTALL_STRIP) +INSTALL_SCRIPT=@INSTALL_PROGRAM@ +INSTALL_DATA=@INSTALL_DATA@ +INSTALL_SHLIB=@INSTALL_SHLIB@ +INSTALL_SETUID=$(INSTALL) $(INSTALL_STRIP) -m 4755 -o root +## This is needed because autoconf will sometimes define @exec_prefix@ to be +## ${prefix}. +prefix=@prefix@ +INSTALL_PREFIX=$(prefix) +INSTALL_EXEC_PREFIX=@exec_prefix@ +exec_prefix=@exec_prefix@ +datarootdir=@datarootdir@ +localstatedir=@localstatedir@ +runstatedir=@runstatedir@ +datadir = @datadir@ +EXAMPLEDIR = $(datadir)/examples/krb5 + +KRB5MANROOT = @mandir@ +ADMIN_BINDIR = @sbindir@ +SERVER_BINDIR = @sbindir@ +CLIENT_BINDIR =@bindir@ +PKGCONFIG_DIR = @libdir@/pkgconfig +ADMIN_MANDIR = $(KRB5MANROOT)/man8 +SERVER_MANDIR = $(KRB5MANROOT)/man8 +CLIENT_MANDIR = $(KRB5MANROOT)/man1 +FILE_MANDIR = $(KRB5MANROOT)/man5 +ADMIN_CATDIR = $(KRB5MANROOT)/cat8 +SERVER_CATDIR = $(KRB5MANROOT)/cat8 +CLIENT_CATDIR = $(KRB5MANROOT)/cat1 +FILE_CATDIR = $(KRB5MANROOT)/cat5 +OVERVIEW_MANDIR = $(KRB5MANROOT)/man7 +OVERVIEW_CATDIR = $(KRB5MANROOT)/cat7 +KRB5_LIBDIR = @libdir@ +KRB5_INCDIR = @includedir@ +MODULE_DIR = @libdir@/krb5/plugins +KRB5_DB_MODULE_DIR = $(MODULE_DIR)/kdb +KRB5_PA_MODULE_DIR = $(MODULE_DIR)/preauth +KRB5_AD_MODULE_DIR = $(MODULE_DIR)/authdata +KRB5_LIBKRB5_MODULE_DIR = $(MODULE_DIR)/libkrb5 +KRB5_TLS_MODULE_DIR = $(MODULE_DIR)/tls +KRB5_LOCALEDIR = @localedir@ +GSS_MODULE_DIR = @libdir@/gss +KRB5_INCSUBDIRS = \ + $(KRB5_INCDIR)/kadm5 \ + $(KRB5_INCDIR)/krb5 \ + $(KRB5_INCDIR)/gssapi \ + $(KRB5_INCDIR)/gssrpc + +SKIPTESTS = $(BUILDTOP)/skiptests + +RUNPYTEST = PYTHONPATH=$(top_srcdir)/util VALGRIND="$(VALGRIND)" \ + $(PYTHON) + + +transform = @program_transform_name@ + +RM = rm -f +CP = cp +MV = mv -f +RANLIB = @RANLIB@ +AWK = @AWK@ +YACC = @YACC@ +PERL = @PERL@ +PYTHON = @PYTHON@ +AUTOCONF = autoconf +AUTOCONFFLAGS = +AUTOHEADER = autoheader +AUTOHEADERFLAGS = +MOVEIFCHANGED = $(top_srcdir)/config/move-if-changed + +TOPLIBD = $(BUILDTOP)/lib + +OBJEXT = o +EXEEXT = + +# +# variables for libraries, for use in linking programs +# -- this may want to get broken out into a separate frag later +# +# invocation is like: +# prog: foo.o bar.o $(KRB5_BASE_DEPLIBS) +# $(CC_LINK) -o $@ foo.o bar.o $(KRB5_BASE_LIBS) + +CC_LINK=@CC_LINK@ $(ASAN_FLAGS) +CXX_LINK=@CXX_LINK@ $(ASAN_FLAGS) + +# Makefile.in files which build programs can override the list of +# directories to look for dependent libraries in (in the form -Ldir1 +# -Ldir2 ...) and also the list of rpath directories to search (in the +# form dir1:dir2:...). +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) + +# Library Makefile.in files can override this list of directories to +# look for dependent libraries in (in the form -Ldir1 -Ldir2 ...) and +# also the list of rpath directories to search (in the form +# dir1:dir2:...) +SHLIB_DIRS=-L$(TOPLIBD) +SHLIB_RDIRS=$(KRB5_LIBDIR) + +# Multi-directory library Makefile.in files should override this list +# of object files with the full list. +STOBJLISTS=OBJS.ST + +# prefix (with no spaces after) for rpath flag to cc +RPATH_FLAG=@RPATH_FLAG@ + +# link flags to add PROG_RPATH to the rpath +PROG_RPATH_FLAGS=@PROG_RPATH_FLAGS@ + +# this gets set by configure to either $(STLIBEXT) or $(SHLIBEXT), +# depending on whether we're building with shared libraries. +DEPLIBEXT=@DEPLIBEXT@ + +KDB5_PLUGIN_DEPLIBS = @KDB5_PLUGIN_DEPLIBS@ +KDB5_PLUGIN_LIBS = @KDB5_PLUGIN_LIBS@ + +KADMCLNT_DEPLIB = $(TOPLIBD)/libkadm5clnt_mit$(DEPLIBEXT) +KADMSRV_DEPLIB = $(TOPLIBD)/libkadm5srv_mit$(DEPLIBEXT) +KDB5_DEPLIB = $(TOPLIBD)/libkdb5$(DEPLIBEXT) +GSSRPC_DEPLIB = $(TOPLIBD)/libgssrpc$(DEPLIBEXT) +GSS_DEPLIB = $(TOPLIBD)/libgssapi_krb5$(DEPLIBEXT) +KRB5_DEPLIB = $(TOPLIBD)/libkrb5$(DEPLIBEXT) +CRYPTO_DEPLIB = $(TOPLIBD)/libk5crypto$(DEPLIBEXT) +COM_ERR_DEPLIB = $(COM_ERR_DEPLIB-@COM_ERR_VERSION@) +COM_ERR_DEPLIB-sys = # empty +COM_ERR_DEPLIB-intlsys = # empty +COM_ERR_DEPLIB-k5 = $(TOPLIBD)/libcom_err$(DEPLIBEXT) +COM_ERR_LIB = @COM_ERR_LIB@ +SUPPORT_LIBNAME=krb5support +SUPPORT_DEPLIB = $(TOPLIBD)/lib$(SUPPORT_LIBNAME)$(DEPLIBEXT) + +# These are forced to use ".a" as an extension because they're never +# built shared. +SS_DEPLIB = $(SS_DEPLIB-@SS_VERSION@) +SS_DEPLIB-k5 = $(TOPLIBD)/libss.a +SS_DEPLIB-sys = +APPUTILS_DEPLIB = $(TOPLIBD)/libapputils.a + +KRB5_BASE_DEPLIBS = $(KRB5_DEPLIB) $(CRYPTO_DEPLIB) $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB) +KDB5_DEPLIBS = $(KDB5_DEPLIB) $(KDB5_PLUGIN_DEPLIBS) +GSS_DEPLIBS = $(GSS_DEPLIB) +GSSRPC_DEPLIBS = $(GSSRPC_DEPLIB) $(GSS_DEPLIBS) +KADM_COMM_DEPLIBS = $(GSSRPC_DEPLIBS) $(KDB5_DEPLIBS) $(GSSRPC_DEPLIBS) +KADMSRV_DEPLIBS = $(KADMSRV_DEPLIB) $(KDB5_DEPLIBS) $(KADM_COMM_DEPLIBS) +KADMCLNT_DEPLIBS = $(KADMCLNT_DEPLIB) $(KADM_COMM_DEPLIBS) + +# Header file dependencies we might override. +# See util/depfix.sed. +# Also see depend-verify-* in post.in, which wants to confirm that we're using +# the in-tree versions. +COM_ERR_VERSION = @COM_ERR_VERSION@ +COM_ERR_DEPS = $(COM_ERR_DEPS-@COM_ERR_VERSION@) +COM_ERR_DEPS-sys = +COM_ERR_DEPS-intlsys = +COM_ERR_DEPS-k5 = $(BUILDTOP)/include/com_err.h +SS_VERSION = @SS_VERSION@ +SS_DEPS = $(SS_DEPS-@SS_VERSION@) +SS_DEPS-sys = +SS_DEPS-k5 = $(BUILDTOP)/include/ss/ss.h $(BUILDTOP)/include/ss/ss_err.h +VERTO_VERSION = @VERTO_VERSION@ +VERTO_DEPS = $(VERTO_DEPS-@VERTO_VERSION@) +VERTO_DEPS-sys = +VERTO_DEPS-k5 = $(BUILDTOP)/include/verto.h + +# LIBS gets substituted in... e.g. -lnsl -lsocket + +# GEN_LIB is -lgen if needed for regexp +GEN_LIB = @GEN_LIB@ + +# Editline or readline flags and libraries. +RL_CFLAGS = @RL_CFLAGS@ +RL_LIBS = @RL_LIBS@ + +SS_LIB = $(SS_LIB-@SS_VERSION@) +SS_LIB-sys = @SS_LIB@ +SS_LIB-k5 = $(TOPLIBD)/libss.a $(RL_LIBS) +KDB5_LIB = -lkdb5 $(KDB5_PLUGIN_LIBS) + +VERTO_DEPLIB = $(VERTO_DEPLIB-@VERTO_VERSION@) +VERTO_DEPLIB-sys = # empty +VERTO_DEPLIB-k5 = $(TOPLIBD)/libverto$(DEPLIBEXT) +VERTO_CFLAGS = @VERTO_CFLAGS@ +VERTO_LIBS = @VERTO_LIBS@ + +DL_LIB = @DL_LIB@ + +CMOCKA_LIBS = @CMOCKA_LIBS@ +LDAP_LIBS = @LDAP_LIBS@ +LMDB_LIBS = @LMDB_LIBS@ + +KRB5_LIB = -lkrb5 +K5CRYPTO_LIB = -lk5crypto +GSS_KRB5_LIB = -lgssapi_krb5 +SUPPORT_LIB = -l$(SUPPORT_LIBNAME) + +# HESIOD_LIBS is -lhesiod... +HESIOD_LIBS = @HESIOD_LIBS@ + +KRB5_BASE_LIBS = $(KRB5_LIB) $(K5CRYPTO_LIB) $(COM_ERR_LIB) $(SUPPORT_LIB) $(GEN_LIB) $(LIBS) $(DL_LIB) +KDB5_LIBS = $(KDB5_LIB) $(GSSRPC_LIBS) +GSS_LIBS = $(GSS_KRB5_LIB) +# needs fixing if ever used on macOS! +GSSRPC_LIBS = -lgssrpc $(GSS_LIBS) +KADM_COMM_LIBS = $(GSSRPC_LIBS) +# need fixing if ever used on macOS! +KADMSRV_LIBS = -lkadm5srv_mit $(HESIOD_LIBS) $(KDB5_LIBS) $(KADM_COMM_LIBS) +KADMCLNT_LIBS = -lkadm5clnt_mit $(KADM_COMM_LIBS) + +# Misc stuff for linking server programs (and maybe some others, +# eventually) but which we don't want to install. +APPUTILS_LIB = -lapputils + +# So test programs can find their libraries without "make install", etc. +RUN_SETUP=@KRB5_RUN_ENV@ +RUN_VARS=@KRB5_RUN_VARS@ + +# Appropriate command prefix for most C test programs: use libraries +# from the build tree, avoid referencing the installed krb5.conf and +# message catalog, and use valgrind when asked. +RUN_TEST=$(RUN_SETUP) KRB5_CONFIG=$(top_srcdir)/config-files/krb5.conf \ + LC_ALL=C $(VALGRIND) + +# libk5crypto dependencies +CRYPTO_IMPL_CFLAGS = @CRYPTO_IMPL_CFLAGS@ +CRYPTO_IMPL_LIBS = @CRYPTO_IMPL_LIBS@ + +# TLS implementation selection +TLS_IMPL = @TLS_IMPL@ +TLS_IMPL_CFLAGS = @TLS_IMPL_CFLAGS@ +TLS_IMPL_LIBS = @TLS_IMPL_LIBS@ + +# SPAKE preauth back-end libraries +SPAKE_OPENSSL_LIBS = @SPAKE_OPENSSL_LIBS@ + +# Whether we have the SASL header file for the LDAP KDB module +HAVE_SASL = @HAVE_SASL@ + +# Whether we are building support for NIST SPAKE groups using OpenSSL +HAVE_SPAKE_OPENSSL = @HAVE_SPAKE_OPENSSL@ + +# Whether we are building the LMDB KDB module +HAVE_LMDB = @HAVE_LMDB@ + +# Whether we have libresolv 1.1.5 for URI discovery tests +HAVE_RESOLV_WRAPPER = @HAVE_RESOLV_WRAPPER@ + +SIZEOF_TIME_T = @SIZEOF_TIME_T@ + +# error table rules +# +### /* these are invoked as $(...) foo.et, which works, but could be better */ +COMPILE_ET= $(COMPILE_ET-@COM_ERR_VERSION@) +COMPILE_ET-sys= compile_et +COMPILE_ET-intlsys= compile_et --textdomain mit-krb5 +COMPILE_ET-k5= $(BUILDTOP)/util/et/compile_et -d $(top_srcdir)/util/et \ + --textdomain mit-krb5 + +.SUFFIXES: .h .c .et .ct + +# These versions cause both .c and .h files to be generated at once. +# But GNU make doesn't understand this, and parallel builds can trigger +# both of them at once, causing them to stomp on each other. The versions +# below only update one of the files, so compile_et has to get run twice, +# but it won't break parallel builds. +#.et.h: ; $(COMPILE_ET) $< +#.et.c: ; $(COMPILE_ET) $< + +.et.h: + $(RM) et-h-$*.et et-h-$*.c et-h-$*.h + $(CP) $< et-h-$*.et + $(COMPILE_ET) et-h-$*.et + $(MV) et-h-$*.h $*.h + $(RM) et-h-$*.et et-h-$*.c +.et.c: + $(RM) et-c-$*.et et-c-$*.c et-c-$*.h + $(CP) $< et-c-$*.et + $(COMPILE_ET) et-c-$*.et + $(MV) et-c-$*.c $*.c + $(RM) et-c-$*.et et-c-$*.h + +# rule to make object files +# +.SUFFIXES: .cpp .c .o +.c.o: + $(CC) $(ALL_CFLAGS) -c $< +# Use .cpp because that's what autoconf uses in its test. +# If the compiler doesn't accept a .cpp suffix here, it wouldn't +# have accepted it when autoconf tested it. +.cpp.o: + $(CXX) $(ALL_CXXFLAGS) -c $< + +# ss command table rules +# +MAKE_COMMANDS= $(MAKE_COMMANDS-@SS_VERSION@) +MAKE_COMMANDS-sys= mk_cmds +MAKE_COMMANDS-k5= $(BUILDTOP)/util/ss/mk_cmds + +.ct.c: + $(MAKE_COMMANDS) $< + +## Parameters to be set by configure for use in lib.in: +## +# +# These settings are for building shared libraries only. Including +# libpriv.in will override with values appropriate for static +# libraries that we don't install. Some values will depend on whether +# the platform supports major and minor version number extensions on +# shared libraries, hence the FOO_@@ settings. + +LN_S=@LN_S@ +AR=@AR@ + +# Set to "lib$(LIBBASE)$(STLIBEXT) lib$(LIBBASE)$(SHLIBEXT)" or some +# subset thereof by configure; determines which types of libs get +# built. +LIBLIST=@LIBLIST@ + +# Set by configure; list of library symlinks to make to $(TOPLIBD) +LIBLINKS=@LIBLINKS@ + +# Set by configure; name of plugin module to build (libfoo.a or foo.so) +PLUGIN=@PLUGIN@ + +# Set by configure; symlink for plugin module for static plugin linking +PLUGINLINK=@PLUGINLINK@ + +# Set by configure; list of install targets for libraries +LIBINSTLIST=@LIBINSTLIST@ + +# Set by configure; install target +PLUGININST=@PLUGININST@ + +# Some of these should really move to pre.in, since programs will need +# it too. (e.g. stuff that has dependencies on the libraries) + +# usually .a +STLIBEXT=@STLIBEXT@ + +# usually .so.$(LIBMAJOR).$(LIBMINOR) +SHLIBVEXT=@SHLIBVEXT@ + +# usually .so.$(LIBMAJOR) (to allow for major-version compat) +SHLIBSEXT=@SHLIBSEXT@ + +# usually .so +SHLIBEXT=@SHLIBEXT@ + +# usually _p.a +PFLIBEXT=@PFLIBEXT@ + +# +DYNOBJEXT=@DYNOBJEXT@ +MAKE_DYNOBJ_COMMAND=@MAKE_DYNOBJ_COMMAND@ +DYNOBJ_EXPDEPS=@DYNOBJ_EXPDEPS@ +DYNOBJ_EXPFLAGS=@DYNOBJ_EXPFLAGS@ + +# For some platforms, a flag which causes shared library creation to +# check for undefined symbols. Suppressed when using --enable-asan. +UNDEF_CHECK=@UNDEF_CHECK@ + +# File with symbol names to be exported, both functions and data, +# currently not distinguished. +SHLIB_EXPORT_FILE=$(srcdir)/$(LIBPREFIX)$(LIBBASE).exports + +# File that needs to be current for building the shared library, +# usually SHLIB_EXPORT_FILE, but not always, if we have to convert +# it to another, intermediate form for the linker. +SHLIB_EXPORT_FILE_DEP=@SHLIB_EXPORT_FILE_DEP@ + +# Export file checker to run when building in maintainer mode on +# Linux. This gets included in LDCOMBINE_TAIL. +EXPORT_CHECK_CMD = && $(PERL) -w $(top_srcdir)/util/export-check.pl \ + $(SHLIB_EXPORT_FILE) $@ +EXPORT_CHECK = @MAINT@ $(EXPORT_CHECK_CMD) + +# Command to run to build a shared library. +# In systems that require multiple commands, like AIX, it may need +# to change to rearrange where the various parameters fit in. +MAKE_SHLIB_COMMAND=@MAKE_SHLIB_COMMAND@ + +# run path flags for explicit libraries depending on this one, +# e.g. "-R$(SHLIB_RPATH)" +SHLIB_RPATH_FLAGS=@SHLIB_RPATH_FLAGS@ + +# flags for explicit libraries depending on this one, +# e.g. "$(SHLIB_RPATH_FLAGS) $(SHLIB_SHLIB_DIRFLAGS) $(SHLIB_EXPLIBS)" +SHLIB_EXPFLAGS=@SHLIB_EXPFLAGS@ + +## Parameters to be set by configure for use in libobj.in: + +# Set to "OBJS.ST OBJS.SH OBJS.PF" or some subset thereof by +# configure; determines which types of object files get built. +OBJLISTS=@OBJLISTS@ + +# Note that $(LIBSRCS) *cannot* contain any variable references, or +# the suffix substitution will break on some platforms! +SHLIBOBJS=$(STLIBOBJS:.o=@SHOBJEXT@) +PFLIBOBJS=$(STLIBOBJS:.o=@PFOBJEXT@) + +# +# rules to make various types of object files +# +PICFLAGS=@PICFLAGS@ +PROFFLAGS=@PROFFLAGS@ + +# platform-dependent temporary files that should get cleaned up +EXTRA_FILES=@EXTRA_FILES@ + +VALGRIND= +# Need absolute paths here because under kshd or ftpd we may run programs +# while in other directories. +VALGRIND_LOGDIR = `cd $(BUILDTOP)&&pwd` +VALGRIND1 = valgrind --tool=memcheck --log-file=$(VALGRIND_LOGDIR)/vg.%p --trace-children=yes --leak-check=yes --suppressions=`cd $(top_srcdir)&&pwd`/util/valgrind-suppressions + +# Set OFFLINE=yes to disable tests that assume network connectivity. +# (Specifically, this concerns the ability to fetch DNS data for +# mit.edu, to verify that SRV queries are working.) Note that other +# tests still assume that the local hostname can be resolved into +# something that looks like an FQDN, with an IPv4 address. +OFFLINE=no + +# Used when running Python tests. +PYTESTFLAGS= + +## +## end of pre.in +############################################################ diff --git a/krb5-1.21.3/src/config/ren2long b/krb5-1.21.3/src/config/ren2long new file mode 100755 index 00000000..e44dc8d5 --- /dev/null +++ b/krb5-1.21.3/src/config/ren2long @@ -0,0 +1,9 @@ +#!/bin/sh +# +# Shell script that changes names that have been truncated to 8.3 format +# back to their original longer name. The awk script produces a script with +# lines of the following format: +# if [ -f ]; then echo ::mv ; mv ; fi +# These lines then get executed in bin/sh. +# +find . -type f -print | gawk -f $0.awk | sh -x 2> /dev/null diff --git a/krb5-1.21.3/src/config/ren2long.awk b/krb5-1.21.3/src/config/ren2long.awk new file mode 100644 index 00000000..fcf0177e --- /dev/null +++ b/krb5-1.21.3/src/config/ren2long.awk @@ -0,0 +1,75 @@ +# +# Awk script to convert filenames shortened down to 8.3 +# back to their larger size. +# +# Works by looking at every filename and seeing if it's shortened +# 8.3 version exists, and if so then mv the short name to the long +# name. +# +# Usage: find . -type f -print | gawk -f ren2long.awk | sh -x [ 2> /dev/null ] +# + + +# Parse_path +# +# Takes the whole path and converts the basename part to 8.3. If it +# changed in the process we emit a sh command to mv it if the shortened +# name exists. +# +function parse_path(p,P2,N,NEW) { + + P2 = tolower(p) + + NEW = "" + while(1) { + N = index(P2,"/") # Go until all / are parsed + if (N == 0) break + + NEW = NEW name83(substr(P2,1,N-1)) "/"; # More of the path + P2 = substr(P2,N+1) + } + + if (bad[P2] == 1) { + print "echo skipping " p + return + } + NEW = NEW name83(P2) # Append path and 8.3 name + + if (bad[P2] == 2) { + print "if [ -f " NEW " ]; then echo ::rm " NEW " ; rm " NEW " ; fi" + return + } + if (NEW != p) + print "if [ -f " NEW " ]; then echo ::mv " NEW " " p " ; mv " NEW " " p " ; fi" +} +# +# Name83 +# +# Converts the a single component part of a file name into 8.3 format +# +function name83(fname,P,B,E) { + P = index(fname,"."); # Find the extension + + if (P == 0) { # No extension + B = substr(fname,1,8); # Just truncate at 8 chars + return B; + } + + B = substr(fname, 1, P <= 8 ? P-1 : 8); # At most 8 chars in name + E = substr(fname, P+1, 3) # And 3 in extension + P = index(E, ".") # 2 dot problem + if (P) + E = substr(E, 1, P-1) + + B = B "." E # Put name together + return B +} +BEGIN { + bad["krb5-types-aux.h"] = 1 + bad["autoconf.h.in"] = 1 + bad["conv_tkt_skey.c"] = 1 + ##bad["makefile"] = 2 -- windows have legitimate files with this name +} +{ + parse_path($1) # Do it +} diff --git a/krb5-1.21.3/src/config/rm.bat b/krb5-1.21.3/src/config/rm.bat new file mode 100644 index 00000000..4cb1c882 --- /dev/null +++ b/krb5-1.21.3/src/config/rm.bat @@ -0,0 +1,32 @@ +@echo off +:loop +if exist %1 del %1 +shift +if not %1.==. goto loop +exit + +Rem +Rem rm.bat +Rem +Rem Copyright 1995 by the Massachusetts Institute of Technology. +Rem All Rights Reserved. +Rem +Rem Export of this software from the United States of America may +Rem require a specific license from the United States Government. +Rem It is the responsibility of any person or organization contemplating +Rem export to obtain such a license before exporting. +Rem +Rem WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +Rem distribute this software and its documentation for any purpose and +Rem without fee is hereby granted, provided that the above copyright +Rem notice appear in all copies and that both that copyright notice and +Rem this permission notice appear in supporting documentation, and that +Rem the name of M.I.T. not be used in advertising or publicity pertaining +Rem to distribution of the software without specific, written prior +Rem permission. M.I.T. makes no representations about the suitability of +Rem this software for any purpose. It is provided "as is" without express +Rem or implied warranty. +Rem +Rem +Rem Batch file to mimic the functionality of the Unix rm command +Rem diff --git a/krb5-1.21.3/src/config/shlib.conf b/krb5-1.21.3/src/config/shlib.conf new file mode 100644 index 00000000..75b7cc3a --- /dev/null +++ b/krb5-1.21.3/src/config/shlib.conf @@ -0,0 +1,552 @@ +# This shell script fragment should set a bunch of variables: +# +# CC_LINK_STATIC: How to link a program if we're only building static +# libraries for krb5 (but may use other shared libs, and there may +# be a shared krb5 lib already installed that we shouldn't use). +# CC_LINK_SHARED: How to link a program if we're building shared +# libraries. +# CXX_LINK_STATIC, CXX_LINK_SHARED: Variants for C++. +# STLIBEXT: Static library extension. +# SHLIBEXT: Shared library extension. +# SHLIBVEXT: Shared library extension, with major version. +# SHLIBSEXT: Shared library extension, with full version. +# (... finish documenting these ...) + +# +# Set up some defaults. +# +STLIBEXT=.a +# Default to being unable to build shared libraries. +SHLIBEXT=.so-nobuild +SHLIBVEXT=.so.v-nobuild +SHLIBSEXT=.so.s-nobuild +# Most systems support profiled libraries. +PFLIBEXT=_p.a +# Install libraries executable. Some systems (e.g., RPM-based ones) require +# this for package dependency generation, while others are ambivalent or will +# strip it during packaging. +INSTALL_SHLIB='$(INSTALL)' +# Most systems use the same objects for shared libraries and dynamically +# loadable objects. +DYNOBJEXT='$(SHLIBEXT)' +MAKE_DYNOBJ_COMMAND='$(MAKE_SHLIB_COMMAND)' +DYNOBJ_EXPDEPS='$(SHLIB_EXPDEPS)' +DYNOBJ_EXPFLAGS='$(SHLIB_EXPFLAGS)' +# +use_linker_init_option=no +use_linker_fini_option=no + +STOBJEXT=.o +SHOBJEXT=.so +PFOBJEXT=.po +# Default for systems w/o shared libraries +CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' +CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' +# +SHLIB_EXPORT_FILE_DEP='$(SHLIB_EXPORT_FILE)' +# This will do for most platforms, and we'll substitute for +# LDCOMBINE, SHLIB_EXPFLAGS, and LDCOMBINE_TAIL below. +MAKE_SHLIB_COMMAND=x +INIT_FINI_PREP=: + +# Default to static or shared libraries? +default_static=no +default_shared=yes + +# Set up architecture-specific variables. +case $krb5_cv_host in +alpha*-dec-osf*) + SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)' + SHLIBSEXT='.so.$(LIBMAJOR)' + SHLIBEXT=.so + # Alpha OSF/1 doesn't need separate PIC objects + SHOBJEXT=.o + INIT_FINI_PREP=initfini= + LDCOMBINE='$(CC) $(CFLAGS) $(PTHREAD_CFLAGS) -shared -Wl,-expect_unresolved -Wl,\* -Wl,-update_registry -Wl,$(BUILDTOP)/so_locations -Wl,-soname -Wl,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) -Wl,-hidden -Wl,-input,osf1.exports $$initfini' + SHLIB_EXPORT_FILE_DEP=osf1.exports + use_linker_init_option=yes + use_linker_fini_option=yes + EXTRA_FILES="$EXTRA_FILES export" + SHLIB_RPATH_FLAGS='-rpath $(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + PROFFLAGS=-pg + RPATH_FLAG='-Wl,-rpath -Wl,' + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(PTHREAD_CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(PTHREAD_CFLAGS) $(LDFLAGS)' + if test "$ac_cv_c_compiler_gnu" = yes \ + && test "$krb5_cv_prog_gnu_ld" = yes; then + # Really should check for gnu ld vs system ld, too. + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(PTHREAD_CFLAGS) $(LDFLAGS)' + else + # Need -oldstyle_liblookup to avoid picking up shared libs from + # other builds. OSF/1 / Tru64 ld programs look through the entire + # library path for shared libs prior to looking through the + # entire library path for static libs. + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) -Wl,-oldstyle_liblookup $(CFLAGS) $(PTHREAD_CFLAGS) $(LDFLAGS)' + fi + if test "$ac_cv_cxx_compiler_gnu" = yes \ + && test "$krb5_cv_prog_gnu_ld" = yes; then + # Really should check for gnu ld vs system ld, too. + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(PTHREAD_CFLAGS) $(LDFLAGS)' + else + # Need -oldstyle_liblookup to avoid picking up shared libs from + # other builds. OSF/1 / Tru64 ld programs look through the entire + # library path for shared libs prior to looking through the + # entire library path for static libs. + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) -Wl,-oldstyle_liblookup $(CXXFLAGS) $(PTHREAD_CFLAGS) $(LDFLAGS)' + fi + # _RLD_ROOT hack needed to repoint "root" directory for purposes + # of searching for shared libs, since RPATHs take precedence over + # LD_LIBRARY_PATH. + RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`$${LD_LIBRARY_PATH+:$$LD_LIBRARY_PATH} _RLD_ROOT=$${_RLD_ROOT+$$_RLD_ROOT}$${_RLD_ROOT-/}' + RUN_VARS='LD_LIBRARY_PATH _RLD_ROOT' + ;; + +# Note: "-Wl,+s" when building executables enables the use of the +# SHLIB_PATH environment variable for finding shared libraries +# in non-standard directories. If a non-standard search-path for +# shared libraries is compiled into the executable (using +# -Wl,+b,$KRB5_SHLIBDIR), then the order of "-Wl,+b,..." and "-Wl,+s" +# on the commandline of the linker will determine which path +# (compiled-in or SHLIB_PATH) will be searched first. +# +# +I initproc routine gets called at load and unload time for +# shl_load calls, but appears to never be called for link-time +# specified libraries. +# +e sym exports symbol and supposedly prevents other symbols +# from being exported, according to the man page, but the +# latter bit doesn't actually seem to work +# -O +dpv should display any routines eliminated as unused, but -b +# apparently turns that off +*-*-hpux*) + case $host_cpu in + hppa*) + SHLIBEXT=.sl + ;; + ia64*) + SHLIBEXT=.so + ;; + esac + SHLIBVEXT='.$(LIBMAJOR).$(LIBMINOR)' + SHLIBSEXT='.$(LIBMAJOR)' + RPATH_FLAG='-Wl,+b,' + if test "$ac_cv_c_compiler_gnu" = yes; then + PICFLAGS=-fPIC + SHLIB_RPATH_FLAGS='-Wl,+b,$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='-Wl,+s $(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + LDCOMBINE='gcc -fPIC -shared -Wl,+h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) -Wl,-c,hpux.exports' + else + PICFLAGS=+z + SHLIB_RPATH_FLAGS='+b $(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + LDCOMBINE='ld -b +h $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) -c hpux.exports' + fi + MAKE_SHLIB_COMMAND="${LDCOMBINE} -o \$@ \$\$objlist \$(LDFLAGS) \$(SHLIB_EXPFLAGS) ${LDCOMBINE_TAIL}" + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + RUN_ENV='SHLIB_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`' + RUN_VARS='SHLIB_PATH' + SHLIB_EXPORT_FILE_DEP=hpux.exports + # Do *not* set use_linker_init_option=yes here, because in the + # case where the library is specified at program link time, the + # initialization function appears not to get called, only for + # shl_load. But for finalization functions, the shl_load case + # is the one we care about. + # + # Not setting use_linker_init_option here should cause compilation + # failures if the user tries to disable delayed initialization. + use_linker_fini_option=yes + ;; + +mips-sgi-irix6.3) # This is a Kludge; see below + SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)' + SHLIBSEXT='.so.$(LIBMAJOR)' + SHLIBEXT=.so + SHOBJEXT=.o + # Kludge follows: (gcc makes n32 object files but ld expects o32, so we reeducate ld) + if test "$ac_cv_c_compiler_gnu" = yes; then + LDCOMBINE='ld -n32 -shared -ignore_unresolved -update_registry $(BUILDTOP)/so_locations -soname $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)' + else + LDCOMBINE='ld -shared -ignore_unresolved -update_registry $(BUILDTOP)/so_locations -soname $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)' + fi + SHLIB_RPATH_FLAGS='-rpath $(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + # no gprof for Irix... + PROFFLAGS=-p + RPATH_FLAG='-Wl,-rpath -Wl,' + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + # This grossness is necessary due to the presence of *three* + # supported ABIs on Irix, and the precedence of the rpath over + # LD_LIBRARY*_PATH. Like OSF/1, _RLD*_ROOT needs to be set to + # work around this lossage. + # + # Set the N32 and 64 variables first because the unqualified + # variables affect all three and can cause the sed command to fail. + # + # This loop is to reduce the clutter a slight bit. + add='`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`' + RUN_ENV= + for i in N32 64 ''; do + RUN_ENV="${RUN_ENV+$RUN_ENV }LD_LIBRARY${i}_PATH=$add\$\${LD_LIBRARY${i}_PATH+:\$\$LD_LIBRARY${i}_PATH}" + RUN_ENV="${RUN_ENV} _RLD${i}_ROOT=\$\${_RLD${i}_ROOT+\$\${_RLD${i}_ROOT}}\$\${_RLD${i}_ROOT-/}" + RUN_VARS="$RUN_VARS LD_LIBRARY${i}_PATH _RLD${i}_ROOT" + done + ;; + +mips-sgi-irix*) + SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)' + SHLIBSEXT='.so.$(LIBMAJOR)' + SHLIBEXT=.so + SHOBJEXT=.o + if test "$ac_cv_c_compiler_gnu" = yes; then + LDCOMBINE_TAIL="" + INIT_FINI_PREP="initfini=" + else + use_linker_init_option=yes + use_linker_fini_option=yes + INIT_FINI_PREP='initfini=; for f in . $(LIBINITFUNC); do if test $$f = .; then :; else initfini="$$initfini -Wl,-init,$${f}__auxinit"; fi; done; for f in . $(LIBFINIFUNC); do if test $$f = .; then :; else initfini="$$initfini -Wl,-fini,$${f}"; fi; done' + LDCOMBINE_TAIL='-Wl,-exports_file -Wl,$(SHLIB_EXPORT_FILE)' + fi + opts='-Wl,-ignore_unresolved -Wl,-update_registry -Wl,$(BUILDTOP)/so_locations' + + if test "$ac_cv_c_compiler_gnu" = yes \ + && test "$krb5_cv_prog_gnu_ld" = yes; then + opts='' + fi + LDCOMBINE='$(CC) -shared '$opts' -Wl,-soname -Wl,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $$initfini' + SHLIB_RPATH_FLAGS='-rpath $(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + # no gprof for Irix... + PROFFLAGS=-p + RPATH_FLAG='-Wl,-rpath -Wl,' + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + # This grossness is necessary due to the presence of *three* + # supported ABIs on Irix, and the precedence of the rpath over + # LD_LIBRARY*_PATH. Like OSF/1, _RLD*_ROOT needs to be set to + # work around this lossage. + # + # Set the N32 and 64 variables first because the unqualified + # variables affect all three and can cause the sed command to fail. + # + # This loop is to reduce the clutter a slight bit. + add='`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`' + RUN_ENV= + for i in N32 64 ''; do + RUN_ENV="${RUN_ENV+$RUN_ENV }LD_LIBRARY${i}_PATH=$add\$\${LD_LIBRARY${i}_PATH+:\$\$LD_LIBRARY${i}_PATH}" + RUN_ENV="${RUN_ENV} _RLD${i}_ROOT=\$\${_RLD${i}_ROOT+\$\${_RLD${i}_ROOT}}\$\${_RLD${i}_ROOT-/}" + RUN_VARS="$RUN_VARS LD_LIBRARY${i}_PATH _RLD${i}_ROOT" + done + ;; + +# untested... +mips-sni-sysv4) + if test "$ac_cv_c_compiler_gnu" = yes; then + PICFLAGS=-fpic + LDCOMBINE='$(CC) -G -Wl,-h -Wl,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)' + else + PICFLAGS=-Kpic + LDCOMBINE='$(CC) -G -h $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)' + fi + SHLIB_RPATH_FLAGS='-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + SHLIBEXT=.so + SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)' + SHLIBSEXT='.so.$(LIBMAJOR)' + RPATH_FLAG=-R + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`' + RUN_VARS='LD_LIBRARY_PATH' + PROFFLAGS=-pg + ;; + +mips-*-netbsd*) + PICFLAGS=-fPIC + SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)' + SHLIBSEXT='.so.$(LIBMAJOR)' + SHLIBEXT=.so + LDCOMBINE='ld -shared -soname $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)' + SHLIB_RPATH_FLAGS='-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + RPATH_FLAG='-Wl,-rpath -Wl,' + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`' + RUN_VARS='LD_LIBRARY_PATH' + PROFFLAGS=-pg + ;; + +*-*-netbsd*) + PICFLAGS=-fPIC + SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)' + SHLIBEXT=.so + LDCOMBINE='$(CC) -shared' + SHLIB_RPATH_FLAGS='-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + RPATH_FLAG=-R + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`' + RUN_VARS='LD_LIBRARY_PATH' + PROFFLAGS=-pg + ;; + +*-*-freebsd*) + case $krb5_cv_host in + sparc64-*) + PICFLAGS=-fPIC + ;; + *) + PICFLAGS=-fpic + ;; + esac + SHLIBVEXT='.so.$(LIBMAJOR)' + RPATH_FLAG='-Wl,--enable-new-dtags -Wl,-rpath -Wl,' + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + SHLIBEXT=.so + LDCOMBINE='ld -Bshareable' + SHLIB_RPATH_FLAGS='--enable-new-dtags -rpath $(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`' + RUN_VARS='LD_LIBRARY_PATH' + PROFFLAGS=-pg + ;; + +*-*-openbsd*) + PICFLAGS=-fpic + SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)' + SHLIBEXT=.so + LDCOMBINE='ld -Bshareable' + SHLIB_RPATH_FLAGS='-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + RPATH_FLAG=-R + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`' + RUN_VARS='LD_LIBRARY_PATH' + PROFFLAGS=-pg + ;; + +*-*-darwin* | *-*-rhapsody*) + SHLIBVEXT='.$(LIBMAJOR).$(LIBMINOR).dylib' + SHLIBSEXT='.$(LIBMAJOR).dylib' + SHLIB_EXPFLAGS='$(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + SHLIBEXT=.dylib + DYNOBJEXT=.so + SHLIB_EXPORT_FILE_DEP=darwin.exports + LDCOMBINE='$(CC) -undefined error -dead_strip -dynamiclib -compatibility_version $(LIBMAJOR) -current_version $(LIBMAJOR).$(LIBMINOR) -install_name "$(KRB5_LIBDIR)/$(LIBPREFIX)$(LIBBASE)$(SHLIBVEXT)" -exported_symbols_list darwin.exports $(CFLAGS)' + # The -dylib_file option tells the linker where to find indirect dependent + # libraries, without adding them to the dependency list. We need this because + # the direct dependent libraries contain the pathname where the indirect + # dependent libraries will be installed (but haven't been yet). + LDCOMBINE_TAIL="" + for lib in libkrb5support.1.1.dylib libkadm5srv.5.1.dylib libkdb5.4.0.dylib; do + LDCOMBINE_TAIL="$LDCOMBINE_TAIL -dylib_file \"\$(KRB5_LIBDIR)/$lib\":\$(TOPLIBD)/$lib" + done + MAKE_DYNOBJ_COMMAND='$(CC) -bundle $(CFLAGS) $(LDFLAGS) -o $@ $$objlist $(DYNOBJ_EXPFLAGS) $(LDFLAGS) -exported_symbols_list darwin.exports'" ${LDCOMBINE_TAIL}" + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) -dynamic $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) -dynamic $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + RUN_ENV='DYLD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`' + RUN_VARS='DYLD_LIBRARY_PATH' + ;; + +*-*-solaris*) + if test "$ac_cv_c_compiler_gnu" = yes; then + PICFLAGS=-fPIC + LDCOMBINE='$(CC) $(CFLAGS) -shared -h $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)' + else + PICFLAGS=-KPIC + # Solaris cc doesn't default to stuffing the SONAME field... + LDCOMBINE='$(CC) $(CFLAGS) -dy -G -z text -h $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $$initfini' + # + case $krb5_cv_host in + *-*-solaris2.[1-7] | *-*-solaris2.[1-7].*) + # Did Solaris 7 and earlier have a linker option for this? + ;; + *) + INIT_FINI_PREP='initfini=; for f in . $(LIBINITFUNC); do if test $$f = .; then :; else initfini="$$initfini -Wl,-z,initarray=$${f}__auxinit"; fi; done; for f in . $(LIBFINIFUNC); do if test $$f = .; then :; else initfini="$$initfini -Wl,-z,finiarray=$$f"; fi; done' + use_linker_init_option=yes + use_linker_fini_option=yes + ;; + esac + fi + SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)' + SHLIBSEXT='.so.$(LIBMAJOR)' + SHLIBEXT=.so + SHLIB_RPATH_FLAGS='-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + PROFFLAGS=-pg + RPATH_FLAG=-R + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(PURE) $(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(PURE) $(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(PURE) $(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(PURE) $(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`' + RUN_VARS='LD_LIBRARY_PATH' + ;; + +*-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu) + PICFLAGS=-fPIC + SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)' + SHLIBSEXT='.so.$(LIBMAJOR)' + SHLIBEXT=.so + # Linux ld doesn't default to stuffing the SONAME field... + # Use objdump -x to examine the fields of the library + # UNDEF_CHECK is suppressed by --enable-asan + LDCOMBINE='$(CC) -shared -fPIC -Wl,-h,$(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT) $(UNDEF_CHECK)' + UNDEF_CHECK='-Wl,--no-undefined' + # $(EXPORT_CHECK) runs export-check.pl when in maintainer mode. + LDCOMBINE_TAIL='-Wl,--version-script binutils.versions $(EXPORT_CHECK)' + SHLIB_EXPORT_FILE_DEP=binutils.versions + RPATH_FLAG='-Wl,--enable-new-dtags -Wl,-rpath -Wl,' + # For cases where we do have dependencies on other libraries + # built in this tree... + SHLIB_RPATH_FLAGS='$(RPATH_FLAG)$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + PROFFLAGS=-pg + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`' + RUN_VARS='LD_LIBRARY_PATH' + + ## old version: + # Linux libc does weird stuff at shlib link time, must be + # explicitly listed here. This also makes it get used even + # for the libraries marked as not having any dependencies; while + # that's not strictly correct, the resulting behavior -- not adding + # extra -R directories -- is still what we want. + #LDCOMBINE='ld -shared -h $(LIBPREFIX)$(LIBBASE)$(SHLIBSEXT)' + #LDCOMBINE_TAIL="-lc" + #SHLIB_EXPFLAGS='-R$(SHLIB_RDIRS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + + ;; + +*-*-bsdi4*) + PICFLAGS=-fpic + SHLIBVEXT='.so.$(LIBMAJOR)' + SHLIBEXT=.so + LDCOMBINE='ld -Bshareable' + SHLIB_RPATH_FLAGS='-R$(SHLIB_RDIRS)' + SHLIB_EXPFLAGS='$(SHLIB_RPATH_FLAGS) $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + PROG_RPATH_FLAGS='-Wl,-rpath,$(PROG_RPATH)' + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH)' + RUN_ENV='LD_LIBRARY_PATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ +/:/g"`' + RUN_VARS='LD_LIBRARY_PATH' + PROFFLAGS=-pg + ;; + +*-*-aix5*) + SHLIBVEXT='.so.$(LIBMAJOR).$(LIBMINOR)' + SHLIBEXT=.so + # AIX doesn't need separate PIC objects + SHOBJEXT=.o + SHLIB_EXPFLAGS=' $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + PROFFLAGS=-pg + if test "$ac_cv_c_compiler_gnu" = "yes" ; then + wl_prefix=-Wl, + RPATH_FLAG='-Wl,-blibpath:' + LDCOMBINE='$(CC) -shared -v -o $@ $$objlist -nostartfiles -Xlinker -bgcbypass:1 -Xlinker -bfilelist -Xlinker -bM:SRE -Xlinker -bE:$(SHLIB_EXPORT_FILE) -Xlinker -bernotok -Xlinker -brtl $(SHLIB_EXPFLAGS) $(LDFLAGS) -lc $$initfini' + else + wl_prefix= + RPATH_FLAG=-blibpath: + LDCOMBINE='/bin/ld -o $@ $$objlist -H512 -T512 -bnoentry -bgcbypass:1 -bnodelcsect -bfilelist -bM:SRE -bE:$(SHLIB_EXPORT_FILE) -bernotok -brtl $(SHLIB_EXPFLAGS) $(LDFLAGS) -lc $$initfini' + fi + # Assume initialization always delayed. + INIT_FINI_PREP="wl=${wl_prefix}; "'i=1; initfini=; for f in . $(LIBFINIFUNC); do if test $$f != .; then initfini="$$initfini $${wl}-binitfini::$$f:$$i"; else :; fi; i=`expr $$i + 1`; done' + use_linker_fini_option=yes + MAKE_SHLIB_COMMAND="${INIT_FINI_PREP} && ${LDCOMBINE}" + RPATH_TAIL=:/usr/lib:/lib + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH):'"$RPATH_TAIL" + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + # $(PROG_RPATH) is here to handle things like a shared tcl library + RUN_ENV='LIBPATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`:$(PROG_RPATH):/usr/lib:/usr/local/lib' + RUN_VARS='LIBPATH' + ;; + +*-*-aix4.*) + SHLIBVEXT='.a.$(LIBMAJOR).$(LIBMINOR)' + SHLIBEXT=.a + # AIX doesn't need separate PIC objects + SHOBJEXT=.o + SHLIB_EXPFLAGS=' $(SHLIB_DIRS) $(SHLIB_EXPLIBS)' + PROFFLAGS=-pg + # Dynamically loaded object can have whatever suffix, but don't + # make archives like for shared libraries. + DYNOBJEXT=.so + # + if test "$ac_cv_c_compiler_gnu" = "yes" ; then + wl_prefix=-Wl, + RPATH_FLAG='-Wl,-blibpath:' + LDCOMBINE='$(CC) -shared -v -o shr.o.$(LIBMAJOR).$(LIBMINOR) $$objlist -nostartfiles -Xlinker -bgcbypass:1 -Xlinker -bfilelist -Xlinker -bM:SRE -Xlinker -bE:$(SHLIB_EXPORT_FILE) -Xlinker -bernotok $(SHLIB_EXPFLAGS) $(LDFLAGS) -lc $$initfini' + LDCOMBINE_DYN='$(CC) -shared -v -o $@ $$objlist -nostartfiles -Xlinker -bgcbypass:1 -Xlinker -bfilelist -Xlinker -bM:SRE -Xlinker -bE:$(SHLIB_EXPORT_FILE) -Xlinker -bernotok $(SHLIB_EXPFLAGS) $(LDFLAGS) -lc $$initfini' + else + wl_prefix= + RPATH_FLAG=-blibpath: + LDCOMBINE='/bin/ld -o shr.o.$(LIBMAJOR).$(LIBMINOR) $$objlist -H512 -T512 -bnoentry -bgcbypass:1 -bnodelcsect -bfilelist -bM:SRE -bE:$(SHLIB_EXPORT_FILE) -bernotok $(SHLIB_EXPFLAGS) $(LDFLAGS) -lc $$initfini' + LDCOMBINE_DYN='/bin/ld -o $@ $$objlist -H512 -T512 -bnoentry -bgcbypass:1 -bnodelcsect -bfilelist -bM:SRE -bE:$(SHLIB_EXPORT_FILE) -bernotok $(SHLIB_EXPFLAGS) $(LDFLAGS) -lc $$initfini' + fi + # Assume initialization always delayed. + INIT_FINI_PREP="wl=${wl_prefix}; "'i=1; initfini=; for f in . $(LIBFINIFUNC); do if test $$f != .; then initfini="$$initfini $${wl}-binitfini::$$f:$$i"; else :; fi; i=`expr $$i + 1`; done' + use_linker_fini_option=yes + MAKE_SHLIB_COMMAND="${INIT_FINI_PREP} && ${LDCOMBINE}"' && ar cq $@ shr.o.$(LIBMAJOR).$(LIBMINOR) && chmod +x $@ && rm -f shr.o.$(LIBMAJOR).$(LIBMINOR)' + MAKE_DYNOBJ_COMMAND="${INIT_FINI_PREP} && ${LDCOMBINE_DYN}" + RPATH_TAIL=:/usr/lib:/lib + PROG_RPATH_FLAGS='$(RPATH_FLAG)$(PROG_RPATH):'"$RPATH_TAIL" + CC_LINK_SHARED='$(CC) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CFLAGS) $(LDFLAGS)' + CC_LINK_STATIC='$(CC) $(PROG_LIBPATH) $(CFLAGS) $(LDFLAGS)' + CXX_LINK_SHARED='$(CXX) $(PROG_LIBPATH) $(PROG_RPATH_FLAGS) $(CXXFLAGS) $(LDFLAGS)' + CXX_LINK_STATIC='$(CXX) $(PROG_LIBPATH) $(CXXFLAGS) $(LDFLAGS)' + # $(PROG_RPATH) is here to handle things like a shared tcl library + RUN_ENV='LIBPATH=`echo $(PROG_LIBPATH) | sed -e "s/-L//g" -e "s/ /:/g"`:$(PROG_RPATH):/usr/lib:/usr/local/lib' + RUN_VARS='LIBPATH' + ;; +esac + +if test "${MAKE_SHLIB_COMMAND}" = "x" ; then + if test "${INIT_FINI_PREP}" != ":"; then + MAKE_SHLIB_COMMAND="${INIT_FINI_PREP} && ${LDCOMBINE} -o \$@ \$\$objlist \$(SHLIB_EXPFLAGS) \$(LDFLAGS) ${LDCOMBINE_TAIL}" + else + MAKE_SHLIB_COMMAND="${LDCOMBINE} -o \$@ \$\$objlist \$(SHLIB_EXPFLAGS) \$(LDFLAGS) ${LDCOMBINE_TAIL}" + fi +fi diff --git a/krb5-1.21.3/src/config/wconfig.pl b/krb5-1.21.3/src/config/wconfig.pl new file mode 100755 index 00000000..8a9d19f7 --- /dev/null +++ b/krb5-1.21.3/src/config/wconfig.pl @@ -0,0 +1,77 @@ +#! perl +$win_flag = "WIN32##"; +@wflags = (); +$mit_specific = 0; +@ignore_list = ( "DOS#?#?" ); + +foreach $arg (@ARGV) { + if ($arg =~ /^-/) { push @wflags, $arg; } + if ("--mit" eq $arg) { + $mit_specific = 1; + } elsif ("--win16" eq $arg) { + $win_flag = "WIN16##"; + } elsif ("--win32" eq $arg) { + $win_flag = "WIN32##"; + } elsif ($arg =~ /^--enable-/) { + my($a) = $arg . "##"; + $a =~ s/^--enable-//; + $a =~ tr/a-z/A-Z/; + push @ignore_list, $a; + } elsif ($arg =~ /^--ignore=/) { + my($a) = $arg; + $a =~ s/--ignore=//; + push @ignore_list, $a; + } elsif ($arg =~ /^-/) { + print STDERR "Invalid option '$arg'\n"; + exit 1; + } else { + if (! defined $dir) { + $dir = $arg; + } + } +} +push @ignore_list, $win_flag; +push @ignore_list, "MIT##" if $mit_specific; + +if ($#wflags >= 0) { printf "WCONFIG_FLAGS=%s\n", join (" ", @wflags); } + +# This has a couple variations from the old wconfig.c. +# +# The old script wouldn't treat the input strings as regular expressions. +# This one does, and actually it builds one regexp, so the strict order of +# checks done by wconfig.c no longer applies. +# +# And the old script would change "##DOS#" to "#", whereas this +# version (with the regexp given above) will accept and discard 0, 1 +# or 2 "#" marks. +$sub = "sub do_subst { my (\$a) = shift; \$a =~ s/^##(" . join("|", @ignore_list) . ")//; return \$a; }"; +#print STDERR $sub, "\n"; +eval $sub; + +sub process { + my $fh = shift; + while (<$fh>) { + if (/^@/) { + # This branch isn't actually used as far as I can tell. + print "\n"; + next; + } + # Do we want to do any autoconf-style @FOO@ substitutions? + # s/@MAINT@/#/g; + # Are there any options we might want to set at configure time? + print &do_subst($_); + } +} + +if (defined $dir) { + open AUX, "<$dir/win-pre.in" || die "Couldn't open win-pre.in: $!\n"; + &process(\*AUX); + close AUX; +} +&process(\*STDIN); +if (defined $dir) { + open AUX, "<$dir/win-post.in" || die "Couldn't open win-post.in: $!\n"; + &process(\*AUX); + close AUX; +} +exit 0; diff --git a/krb5-1.21.3/src/config/win-post.in b/krb5-1.21.3/src/config/win-post.in new file mode 100644 index 00000000..3f43bda7 --- /dev/null +++ b/krb5-1.21.3/src/config/win-post.in @@ -0,0 +1,128 @@ +# +# Start of Win32 post-config lines (config/win-post.in) +# + +setup-msg: + @set C_RULE_PRINT= $(C_RULE_PRINT) + @set DO_C_RULE_PRINT=1 + +!if defined(NO_OUTPRE) || defined(NO_OUTDIR) +outpre-dir: +!else +outpre-dir: $(OUTPRE3)$(DIRNUL) +!endif + +# +# put all: first just in case no other rules occur here +# +all: + +# +# Set the #define to indicate that we are compiling a DLL. We default to +# compiling the Kerberos library +# +!if defined(DLL_EXP_TYPE) +DLL_FILE_DEF=/D$(DLL_EXP_TYPE)_DLL_FILE +!else +DLL_FILE_DEF=/DKRB5_DLL_FILE +!endif + +# Build the Makefile unless we are in the top-level +#(where there is already an explicit rule). +!if !defined(TOPLEVEL) +Makefile: Makefile.in $(BUILDTOP)\config\win-pre.in $(BUILDTOP)\config\win-post.in + $(WCONFIG) $(BUILDTOP)\config < Makefile.in > Makefile +!endif + +# Recurse into subdirs if WINSUBDIRS or SUBDIRS is defined. Makefiles +# can depend on all-recurse, clean-recurse, or check-recurse to perform +# actions after recursion. +!if defined(SUBDIRS) && !defined(WINSUBDIRS) +WINSUBDIRS=$(SUBDIRS) +!endif +!ifdef WINSUBDIRS + +all-recurse: + @for %d in ($(WINSUBDIRS)) do @(echo Making in $(mydir)\%d && \ + pushd %d && $(MAKE) -$(MFLAGS) && popd) || exit 1 + @echo Making in $(mydir) +all-windows: all-recurse + +clean-recurse: + @for %d in ($(WINSUBDIRS)) do @(echo Making clean in $(mydir)\%d && \ + pushd %d && $(MAKE) -$(MFLAGS) clean && popd) || exit 1 + @echo Making clean in $(mydir) +clean-windows:: clean-recurse + +check-recurse: + @for %d in ($(WINSUBDIRS)) do @(echo Making check in $(mydir)\%d && \ + pushd %d && $(MAKE) -$(MFLAGS) check && popd) || exit 1 + @echo Making check in $(mydir) +check-windows: check-recurse + +!endif # WINSUBDIRS + +# Use 64-bit LIBNAME and OBJFILE on 64-bit platforms, if defined. +!if ("$(CPU)" == "IA64") || ("$(CPU)" == "AMD64") || ("$(CPU)" == "ALPHA64") +!if defined(WIN64LIBNAME) +LIBNAME=$(WIN64LIBNAME) +!endif +!if defined(WIN64OBJFILE) +OBJFILE=$(WIN64OBJFILE) +!endif +!endif + +# Build a library if LIBNAME is defined. +!if defined(LIBNAME) + +!if !defined(OBJFILELIST) +OBJFILELIST=@$(OBJFILE) +!endif +!if !defined(OBJFILEDEP) +OBJFILEDEP=$(OBJFILE) +!endif + +all-windows: $(LIBNAME) +$(LIBNAME): $(OBJFILEDEP) + $(LIBCMD) /out:$(LIBNAME) /nologo $(OBJFILELIST) + +!endif # LIBNAME + + +# Build an object file list if OBJFILE is defined. +!if defined(OBJFILE) +all-windows: $(OBJFILE) +!if defined(LIBOBJS) +$(OBJFILE): $(LIBOBJS) + if exist $(OBJFILE) del $(OBJFILE) +!if defined(PREFIXDIR) + $(LIBECHO) -p $(PREFIXDIR)\ $** > $(OBJFILE) +!else + $(LIBECHO) $** > $(OBJFILE) +!endif # !PREFIXDIR +!endif # LIBOBJS +!endif # OBJFILE + + +check: +check-windows: + +clean-windows:: clean-windows-files clean-windows-dir + + +# This needs to be in the post because we need RM to be defined in terms +# of BUILDTOP +clean-windows-files: +!if "$(OUTPRE3)" == "" +!error ASSERTION FAILURE: OUTPRE3 must be defined!!! +!endif +!if "$(OS)" == "Windows_NT" + @if exist $(OUTPRE3)$(DIRNUL) rd /s/q $(OUTPRE3) +!else + @if exist $(OUTPRE3)$(DIRNUL) deltree /y $(OUTPRE3) +!endif + +# Dependencies +!if exist($(srcdir)/deps) +!include $(srcdir)/deps +!endif diff --git a/krb5-1.21.3/src/config/win-pre.in b/krb5-1.21.3/src/config/win-pre.in new file mode 100644 index 00000000..8ac5fa2f --- /dev/null +++ b/krb5-1.21.3/src/config/win-pre.in @@ -0,0 +1,240 @@ +WHAT=windows + +all: setup-msg outpre-dir + +all: all-$(WHAT) +clean: clean-$(WHAT) +install: install-$(WHAT) +check: check-$(WHAT) + +all-windows: +clean-windows:: +install-windows: +check-windows: + +all-windows: Makefile +clean-windows:: Makefile + +# +# Figure out the CPU +# +!if !defined(CPU) || "$(CPU)" == "" +CPU=$(PROCESSOR_ARCHITECTURE) +!endif # CPU + +!if "$(CPU)" == "" +CPU=i386 +!endif + +# Change x86 or X86 to i386 +!if ( "$(CPU)" == "X86" ) || ( "$(CPU)" == "x86" ) +CPU=i386 +!endif # CPU == X86 + +!if ( "$(CPU)" != "i386" ) && ( "$(CPU)" != "ALPHA" ) && ( "$(CPU)" != "ALPHA64" ) && ( "$(CPU)" != "IA64" ) && ( "$(CPU)" != "AMD64" ) +!error Must specify CPU environment variable ( CPU=i386, CPU=ALPHA, CPU=ALPHA64,CPU=IA64, CPU=AMD64) +!endif + +!if ("$(CPU)" == "IA64" ) || ("$(CPU)" == "AMD64" ) || ("$(CPU)" == "ALPHA64" ) +BITS=64 +!else +BITS=32 +!endif + +# +# End of figuring out CPU +# + +!if "$(OS)" == "Windows_NT" +DIRNUL= +!else +DIRNUL=\nul +!endif + +# NOTE: ^ is an escape char for NMAKE. +!ifdef NODEBUG +OUTPRE_DBG=rel +!else +OUTPRE_DBG=dbg +!endif +OUTPRE1=obj +OUTPRE2=$(OUTPRE1)\$(CPU) +OUTPRE3=$(OUTPRE2)\$(OUTPRE_DBG) +OUTPRE=$(OUTPRE3)^\ + +$(OUTPRE3)$(DIRNUL): + -@if not exist $(OUTPRE1)$(DIRNUL) mkdir $(OUTPRE1) + -@if not exist $(OUTPRE2)$(DIRNUL) mkdir $(OUTPRE2) + -@if not exist $(OUTPRE3)$(DIRNUL) mkdir $(OUTPRE3) + @if exist $(OUTPRE3)$(DIRNUL) echo Output going into $(OUTPRE3) + @if not exist $(OUTPRE1)$(DIRNUL) echo The directory $(OUTPRE1) could not be created. + @if exist $(OUTPRE1)$(DIRNUL) if not exist $(OUTPRE2)$(DIRNUL) echo The directory $(OUTPRE2) could not be created. + @if exist $(OUTPRE2)$(DIRNUL) if not exist $(OUTPRE3)$(DIRNUL) echo The directory $(OUTPRE3) could not be created. + + +clean-windows-dir: + -@if exist $(OUTPRE3)$(DIRNUL) rmdir $(OUTPRE3) + -@if exist $(OUTPRE2)$(DIRNUL) rmdir $(OUTPRE2) + -@if exist $(OUTPRE1)$(DIRNUL) rmdir $(OUTPRE1) + @if exist $(OUTPRE2)$(DIRNUL) echo The directory $(OUTPRE2) is not empty. + @if not exist $(OUTPRE2)$(DIRNUL) if exist $(OUTPRE1)$(DIRNUL) echo The directory $(OUTPRE1) is not empty. + +# Directory syntax: +# +# begin absolute path +ABS=^\ +# begin relative path +REL= +# up-directory +U=.. +# path separator +S=^\ +# this is magic... should only be used for preceding a program invocation +C=.^\ + +srcdir = . +top_srcdir = $(srcdir)\$(BUILDTOP) + +DNSLIBS=dnsapi.lib +DNSFLAGS=-DKRB5_DNS_LOOKUP=1 +!if defined(KRB5_USE_DNS_REALMS) +DNSFLAGS=$(DNSFLAGS) -DKRB5_DNS_LOOKUP_REALM=1 +!endif + +!if ("$(CPU)" == "i386") +TIME_T_FLAGS=-D_USE_32BIT_TIME_T +!endif + +!if defined (NODEBUG) +KFWFLAGS=-DUSE_LEASH=1 +!else +KFWFLAGS=-DUSE_LEASH=1 -DDEBUG -D_CRTDBG_MAP_ALLOC +!endif + +# +# The name of the C compiler for the target +# +CC=cl + +PDB_OPTS=-Fd$(OUTPRE)\ -FD +CPPFLAGS=-I$(top_srcdir)\include -I$(top_srcdir)\include\krb5 $(DNSFLAGS) -DWIN32_LEAN_AND_MEAN -DKRB5_DEPRECATED=1 -DKRB5_PRIVATE -D_CRT_SECURE_NO_DEPRECATE $(KFWFLAGS) $(TIME_T_FLAGS) +# Treat the following warnings as errors: +# 4020: too many actual parameters +# 4024: different types for formal and actual parameter +# 4047: different levels of indirection +CCOPTS=-nologo /EHsc /W3 /we4020 /we4024 /we4047 $(PDB_OPTS) $(DLL_FILE_DEF) +LOPTS=-nologo -incremental:no -manifest + +!if ("$(BITS)" == "64" ) +ENTRYPOINT=_DllMainCRTStartup +!else +ENTRYPOINT=_DllMainCRTStartup@12 +!endif +CCLINKOPTION= +DEBUGOPT=/guard:cf /Zi + +#if the compiler is vstudio 8, generate manifest +!if exists("$(VCINSTALLDIR)\..\..\MICROSOFT VISUAL STUDIO 8") +CCLINKOPTION = $(CCLINKOPTION) /MANIFEST +_VC_MANIFEST_EMBED_EXE = if exist $*.exe.manifest mt.exe -manifest $*.exe.manifest -outputresource:$*.exe;1 +_VC_MANIFEST_EMBED_DLL = if exist $*.dll.manifest mt.exe -manifest $*.dll.manifest -outputresource:$*.dll;2 +!endif + +# /ZI gives better debug info in each object file (MSVC 6.0 or higher). +# /Zi gives debug info in each object file. +# /Gs Avoid stack probes (they don't seem to work anyway) +# /Os optimize for space. FIXME: Do not use /Ox; it miscompiles the DES lib! +# /Od disable optimization (for debugging) +# /MD (Win32) thread safe, ML would be single threaded, don't build with ML + +# +# CCOPTS was for DLL compiles +# CCOPTS2 was for non-DLL compiles (EXEs, for example) +# +!ifdef NODEBUG +!ifdef DEBUG_SYMBOL +CCOPTS=$(DEBUGOPT) $(CCOPTS) +LOPTS=$(LOPTS) -debug +!endif +CCOPTS=/Os /MD $(CCOPTS) +LOPTS=$(LOPTS) +!ifdef DEBUG_SYMBOL +INSTALLDBGSYMS=copy +!else +INSTALLDBGSYMS=rem +!endif +!else +CCOPTS=/Od $(DEBUGOPT) /MDd $(CCOPTS) +LOPTS=$(LOPTS) -debug +INSTALLDBGSYMS=copy +!endif + +# XXX - NOTE: We should probably use DllMainCRTStartup +DLL_LINKOPTS=$(LOPTS) -dll -entry:DllMain +EXE_LINKOPTS=$(LOPTS) + +RM=$(BUILDTOP)\config\rm.bat +LIBECHO=$(BUILDTOP)\util\windows\$(OUTPRE)libecho +CP=copy/b nul:+ +MV=ren +LN=copy +LIBCMD=lib +AWK=rem +RC = rc +CVTRES = cvtres +PERL=perl + +WCONFIG_EXE=$(BUILDTOP)\$(OUTPRE)wconfig.exe +WCONFIG=$(WCONFIG_EXE:.exe=) $(WCONFIG_FLAGS) + +CLIB=$(BUILDTOP)\lib\$(OUTPRE)comerr$(BITS).lib +PLIB=$(BUILDTOP)\lib\$(OUTPRE)xpprof$(BITS).lib +KLIB=$(BUILDTOP)\lib\$(OUTPRE)krb5_$(BITS).lib +SLIB=$(BUILDTOP)\lib\$(OUTPRE)k5sprt$(BITS).lib +GLIB=$(BUILDTOP)\lib\$(OUTPRE)gssapi$(BITS).lib +CCLIB=krbcc$(BITS) +SPAKELIB=spake$(BITS) + +KRB4_INCLUDES=-I$(BUILDTOP)/include/kerberosIV + +COM_ERR_DEPS = $(BUILDTOP)/include/com_err.h + +RANLIB=rem + +OBJEXT=obj +EXEEXT=.exe + +MFLAGS=$(MAKEFLAGS) +!ifdef MIGNORE +MAKE=-$(MAKE) +!endif + +CFLAGS = $(CCOPTS) +ALL_CFLAGS = $(DEFS) $(DEFINES) $(LOCALINCLUDES) $(CPPFLAGS) $(CFLAGS) + +C_RULE_STUFF=$(CC) $(ALL_CFLAGS) -Fo$(OUTPRE)\ -c +C_RULE_PRINT=$(C_RULE_STUFF) +C_RULE=$(C_RULE_STUFF) $< + +{}.rc{$(OUTPRE)}.res: + $(RC) $(RCFLAGS) -fo $@ -r $< + +{}.c{$(OUTPRE)}.obj: + @if "%DO_C_RULE_PRINT%"=="1" echo %C_RULE_PRINT% ... + @set DO_C_RULE_PRINT= + @$(C_RULE) + +{}.cxx{$(OUTPRE)}.obj: + @if "%DO_C_RULE_PRINT%"=="1" echo %C_RULE_PRINT% ... + @set DO_C_RULE_PRINT= + @$(C_RULE) + +{}.cpp{$(OUTPRE)}.obj: + @if "%DO_C_RULE_PRINT%"=="1" echo %C_RULE_PRINT% ... + @set DO_C_RULE_PRINT= + @$(C_RULE) + +# +# End of Win32 pre-config lines (config/win-pre.in) +# + diff --git a/krb5-1.21.3/src/configure b/krb5-1.21.3/src/configure new file mode 100755 index 00000000..1d676796 --- /dev/null +++ b/krb5-1.21.3/src/configure @@ -0,0 +1,16426 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.71 for Kerberos 5 1.21.3. +# +# Report bugs to . +# +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 +# Massachusetts Institute of Technology. +# +# +# +# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, +# Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +as_nop=: +if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 +then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else $as_nop + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + + +# Reset variables that may have inherited troublesome values from +# the environment. + +# IFS needs to be set, to space, tab, and newline, in precisely that order. +# (If _AS_PATH_WALK were called with IFS unset, it would have the +# side effect of setting IFS to empty, thus disabling word splitting.) +# Quoting is to prevent editors from complaining about space-tab. +as_nl=' +' +export as_nl +IFS=" "" $as_nl" + +PS1='$ ' +PS2='> ' +PS4='+ ' + +# Ensure predictable behavior from utilities with locale-dependent output. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# We cannot yet rely on "unset" to work, but we need these variables +# to be unset--not just set to an empty or harmless value--now, to +# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct +# also avoids known problems related to "unset" and subshell syntax +# in other old shells (e.g. bash 2.01 and pdksh 5.2.14). +for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH +do eval test \${$as_var+y} \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done + +# Ensure that fds 0, 1, and 2 are open. +if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi +if (exec 3>&2) ; then :; else exec 2>/dev/null; fi + +# The user is always right. +if ${PATH_SEPARATOR+false} :; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + test -r "$as_dir$0" && as_myself=$as_dir$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="as_nop=: +if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 +then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else \$as_nop + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ) +then : + +else \$as_nop + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +blah=\$(echo \$(echo blah)) +test x\"\$blah\" = xblah || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null +then : + as_have_required=yes +else $as_nop + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null +then : + +else $as_nop + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null +then : + CONFIG_SHELL=$as_shell as_have_required=yes + if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null +then : + break 2 +fi +fi + done;; + esac + as_found=false +done +IFS=$as_save_IFS +if $as_found +then : + +else $as_nop + if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null +then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi +fi + + + if test "x$CONFIG_SHELL" != x +then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno +then : + printf "%s\n" "$0: This script requires a shell more modern than all" + printf "%s\n" "$0: the shells that I found on your system." + if test ${ZSH_VERSION+y} ; then + printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" + printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." + else + printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and krb5-bugs@mit.edu +$0: about your system, including any error possibly output +$0: before this message. Then install a modern shell, or +$0: manually run the script under such a shell if you do +$0: have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit +# as_fn_nop +# --------- +# Do nothing but, unlike ":", preserve the value of $?. +as_fn_nop () +{ + return $? +} +as_nop=as_fn_nop + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null +then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else $as_nop + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null +then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else $as_nop + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + +# as_fn_nop +# --------- +# Do nothing but, unlike ":", preserve the value of $?. +as_fn_nop () +{ + return $? +} +as_nop=as_fn_nop + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + printf "%s\n" "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + + +# Determine whether it's possible to make 'echo' print without a newline. +# These variables are no longer used directly by Autoconf, but are AC_SUBSTed +# for compatibility with existing Makefiles. +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +# For backward compatibility with old third-party macros, we provide +# the shell variables $as_echo and $as_echo_n. New code should use +# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. +as_echo='printf %s\n' +as_echo_n='printf %s' + + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='Kerberos 5' +PACKAGE_TARNAME='krb5' +PACKAGE_VERSION='1.21.3' +PACKAGE_STRING='Kerberos 5 1.21.3' +PACKAGE_BUGREPORT='krb5-bugs@mit.edu' +PACKAGE_URL='' + +ac_unique_file="aclocal.m4" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_STDIO_H +# include +#endif +#ifdef HAVE_STDLIB_H +# include +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_header_c_list= +ac_subst_vars='LTLIBOBJS +PKCS11_MODNAME +DEFCKTNAME +DEFKTNAME +DEFCCNAME +MACOS_FRAMEWORK +OSX +GROFF +VERTO_VERSION +VERTO_LIBS +VERTO_CFLAGS +RL_LIBS +RL_CFLAGS +LIBEDIT_LIBS +LIBEDIT_CFLAGS +lmdb_plugin_dir +LMDB_LIBS +HAVE_LMDB +sam2_plugin +LDAP +ldap_plugin_dir +HAVE_SASL +LDAP_LIBS +SUPPORTLIB_MAJOR +DB_EXTRA_LIBS +HAVE_RESOLV_WRAPPER +CMOCKA_LIBS +HAVE_CMOCKA +HAVE_PYTHON +PYTHON +PYTHON_MINVERSION +LIBOBJS +PKINIT +GSSRPC__BSD_TYPEALIASES +GSSRPC__NETDB_H +GSSRPC__SYS_PARAM_H +GSSRPC__UNISTD_H +GSSRPC__SYS_TIME_H +GSSRPC__SYS_SELECT_H +rpcent_define +include_xom +PRIOCNTL_HACK +YFLAGS +YACC +NSLOOKUP +DIG +FCTSH +BASH +SH5 +SH +KRB5_RCTMPDIR +SIZEOF_TIME_T +SETENVOBJ +KSU_LIBS +EXTRA_SUPPORT_SYMS +GETTIMEOFDAY_ST_OBJ +GETTIMEOFDAY_OBJ +MKSTEMP_ST_OBJ +MKSTEMP_OBJ +ASAN +ASAN_FLAGS +KRB5_RUN_VARS +KRB5_RUN_ENV +AESNI_FLAGS +AESNI_OBJ +YASM +SPAKE_OPENSSL_LIBS +HAVE_SPAKE_OPENSSL +TLS_IMPL_LIBS +TLS_IMPL_CFLAGS +TLS_IMPL +CRYPTO_BUILTIN_TESTS +CRYPTO_IMPL_LIBS +CRYPTO_IMPL_CFLAGS +audit_plugin +AUDIT_IMPL_LIBS +AWK +SECURE_GETENV_INIT +SECURE_GETENV_ST_OBJ +SECURE_GETENV_OBJ +PRINTF_ST_OBJ +PRINTF_OBJ +FNMATCH_ST_OBJ +FNMATCH_OBJ +GETOPT_LONG_ST_OBJ +GETOPT_LONG_OBJ +GETOPT_ST_OBJ +GETOPT_OBJ +STRLCPY_ST_OBJ +STRLCPY_OBJ +po +MSGFMT +LIBUTIL +PROG_RPATH_FLAGS +RPATH_FLAG +CXX_LINK +CC_LINK +GEN_LIB +UNDEF_CHECK +MAKE_DYNOBJ_COMMAND +DYNOBJEXT +LIBINSTLIST +PFLIBEXT +DEPLIBEXT +SHLIBSEXT +SHLIBVEXT +SHLIBEXT +STLIBEXT +INSTALL_SHLIB +DYNOBJ_EXPFLAGS +DYNOBJ_EXPDEPS +SHLIB_EXPORT_FILE_DEP +SHLIB_EXPFLAGS +SHLIB_RPATH_FLAGS +MAKE_SHLIB_COMMAND +KDB5_PLUGIN_LIBS +KDB5_PLUGIN_DEPLIBS +PLUGININST +PLUGINLINK +PLUGIN +LIBLINKS +LIBLIST +PERL +AR +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +RANLIB +LN_S +PROFFLAGS +PICFLAGS +PFOBJEXT +SHOBJEXT +STOBJEXT +OBJLISTS +KRB5_VERSION +DL_LIB +THREAD_SUPPORT +PTHREAD_CFLAGS +PTHREAD_LIBS +PTHREAD_CXX +PTHREAD_CC +ax_pthread_config +EGREP +GREP +SED +krb5_cv_host +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +CONFIG_RELTOPDIR +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +HESIOD_LIBS +HESIOD_DEFS +KDB5_DB_LIB +DB_HEADER_VERSION +DB_VERSION +DB_LIB +DB_HEADER +SS_VERSION +SS_LIB +COM_ERR_LIB +COM_ERR_VERSION +compile_et +COM_ERR_LIBS +COM_ERR_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +LD +CPP +WARN_CXXFLAGS +WARN_CFLAGS +HAVE_GCC +ac_ct_CXX +CXXFLAGS +CXX +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +EXTRA_FILES +SYSCONFCONF +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +runstatedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='lib_frag +libobj_frag +libnover_frag +libpriv_frag +libnodeps_frag' +ac_user_opts=' +enable_option_checking +with_size_optimizations +with_system_et +with_system_ss +with_system_db +with_netlib +enable_dns_for_realm +with_hesiod +enable_maintainer_mode +with_ldap +enable_delayed_initialization +enable_thread_support +enable_static +enable_shared +enable_rpath +enable_profiled +enable_athena +enable_nls +with_vague_errors +enable_audit_plugin +with_crypto_impl +with_tls_impl +with_keyutils +with_spake_openssl +enable_aesni +enable_kdc_lookaside_cache +enable_asan +enable_pkinit +with_lmdb +with_libedit +with_readline +with_system_verto +with_krb5_config +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CXX +CXXFLAGS +CCC +CPP +LD +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +COM_ERR_CFLAGS +COM_ERR_LIBS +SS_LIB +DB_HEADER +DB_LIB +YACC +YFLAGS +LIBEDIT_CFLAGS +LIBEDIT_LIBS +VERTO_CFLAGS +VERTO_LIBS +DEFCCNAME +DEFKTNAME +DEFCKTNAME +PKCS11_MODNAME' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: \`$ac_useropt'" + ac_useropt_orig=$ac_useropt + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: \`$ac_useropt'" + ac_useropt_orig=$ac_useropt + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: \`$ac_useropt'" + ac_useropt_orig=$ac_useropt + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: \`$ac_useropt'" + ac_useropt_orig=$ac_useropt + ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir runstatedir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures Kerberos 5 1.21.3 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/krb5] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of Kerberos 5 1.21.3:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-dns-for-realm enable DNS lookups of Kerberos realm names + --enable-maintainer-mode + enable rebuilding of source files, Makefiles, etc + --disable-delayed-initialization + initialize library code when loaded [delay until + first use] + --disable-thread-support + don't enable thread support [enabled] + + --disable-rpath suppress run path flags in link lines + --enable-athena build with MIT Project Athena configuration + --disable-nls disable native language support + --enable-audit-plugin=IMPL + use audit plugin [ do not use audit ] + --disable-aesni Do not build with AES-NI support + --disable-kdc-lookaside-cache + Disable the cache which detects client retransmits + --enable-asan Build with asan memory checking + --disable-pkinit disable PKINIT plugin support + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-size-optimizations enable a few optimizations to reduce code size + possibly at some run-time cost + --with-system-et use system compile_et and -lcom_err [default: build + and install a local version] + --with-system-ss use system -lss and mk_cmds [private version] + --with-system-db use system Berkeley db [private version] + --with-netlib=LIBS use user defined resolver library + --with-hesiod=path compile with hesiod support [omitted] + --with-ldap compile OpenLDAP database backend module + --with-vague-errors Do not [do] send helpful errors to client + --with-crypto-impl=IMPL use specified crypto implementation [builtin] + --with-tls-impl=IMPL use specified TLS implementation [auto] + --without-keyutils do not link with libkeyutils + --with-spake-openssl use OpenSSL for SPAKE preauth [auto] + --with-lmdb compile LMDB database backend module [auto] + --without-libedit do not compile with libedit + --with-readline compile with GNU Readline + --with-system-verto always use system verto library + --with-krb5-config=PATH path to existing krb5-config program for defaults + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CPP C preprocessor + LD linker command [CC] + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + COM_ERR_CFLAGS + C compiler flags for COM_ERR, overriding pkg-config + COM_ERR_LIBS + linker flags for COM_ERR, overriding pkg-config + SS_LIB system libraries for 'ss' package [-lss] + DB_HEADER header file for system Berkeley db package [db.h] + DB_LIB library for system Berkeley db package [-ldb] + YACC The `Yet Another Compiler Compiler' implementation to use. + Defaults to the first program found out of: `bison -y', `byacc', + `yacc'. + YFLAGS The list of arguments that will be passed by default to $YACC. + This script will default YFLAGS to the empty string to avoid a + default value of `-d' given by some make applications. + LIBEDIT_CFLAGS + C compiler flags for LIBEDIT, overriding pkg-config + LIBEDIT_LIBS + linker flags for LIBEDIT, overriding pkg-config + VERTO_CFLAGS + C compiler flags for VERTO, overriding pkg-config + VERTO_LIBS linker flags for VERTO, overriding pkg-config + DEFCCNAME Default ccache name + DEFKTNAME Default keytab name + DEFCKTNAME Default client keytab name + PKCS11_MODNAME + Default PKCS11 module name + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for configure.gnu first; this name is used for a wrapper for + # Metaconfig's "Configure" on case-insensitive file systems. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +Kerberos 5 configure 1.21.3 +generated by GNU Autoconf 2.71 + +Copyright (C) 2021 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. + +Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 +Massachusetts Institute of Technology. + +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest.beam + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext +then : + ac_retval=0 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest.beam + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext +then : + ac_retval=0 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + } +then : + ac_retval=0 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + } +then : + ac_retval=0 +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that +# executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } +then : + ac_retval=0 +else $as_nop + printf "%s\n" "$as_me: program exited with status $ac_status" >&5 + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +printf %s "checking for $2... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. */ + +#include +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main (void) +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + eval "$3=yes" +else $as_nop + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +printf %s "checking for $2... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval "$3=yes" +else $as_nop + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +eval ac_res=\$$3 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +printf %s "checking for $2... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else $as_nop + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main (void) +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main (void) +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + +else $as_nop + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +eval ac_res=\$$3 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +printf %s "checking for $2.$3... " >&6; } +if eval test \${$4+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main (void) +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval "$4=yes" +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main (void) +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval "$4=yes" +else $as_nop + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +eval ac_res=\$$4 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member + +# ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR +# ------------------------------------------------------------------ +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR. +ac_fn_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +printf %s "checking whether $as_decl_name is declared... " >&6; } +if eval test \${$3+y} +then : + printf %s "(cached) " >&6 +else $as_nop + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + eval ac_save_FLAGS=\$$6 + as_fn_append $6 " $5" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main (void) +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval "$3=yes" +else $as_nop + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + eval $6=\$ac_save_FLAGS + +fi +eval ac_res=\$$3 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_check_decl + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main (void) +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main (void) +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_hi=$ac_mid; break +else $as_nop + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + done +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main (void) +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main (void) +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_lo=$ac_mid; break +else $as_nop + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + done +else $as_nop + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main (void) +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_hi=$ac_mid +else $as_nop + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval (void) { return $2; } +static unsigned long int ulongval (void) { return $2; } +#include +#include +int +main (void) +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO" +then : + echo >>conftest.val; read $3 config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by Kerberos 5 $as_me 1.21.3, which was +generated by GNU Autoconf 2.71. Invocation command line was + + $ $0$ac_configure_args_raw + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + printf "%s\n" "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Sanitize IFS. + IFS=" "" $as_nl" + # Save into config.log some information that might help in debugging. + { + echo + + printf "%s\n" "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + printf "%s\n" "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + printf "%s\n" "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + printf "%s\n" "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + printf "%s\n" "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + printf "%s\n" "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + printf "%s\n" "$as_me: caught signal $ac_signal" + printf "%s\n" "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +printf "%s\n" "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h + +printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h + +printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h + +printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h + +printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h + +printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +if test -n "$CONFIG_SITE"; then + ac_site_files="$CONFIG_SITE" +elif test "x$prefix" != xNONE; then + ac_site_files="$prefix/share/config.site $prefix/etc/config.site" +else + ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" +fi + +for ac_site_file in $ac_site_files +do + case $ac_site_file in #( + */*) : + ;; #( + *) : + ac_site_file=./$ac_site_file ;; +esac + if test -f "$ac_site_file" && test -r "$ac_site_file"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +printf "%s\n" "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +printf "%s\n" "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Test code for whether the C compiler supports C89 (global declarations) +ac_c_conftest_c89_globals=' +/* Does the compiler advertise C89 conformance? + Do not test the value of __STDC__, because some compilers set it to 0 + while being otherwise adequately conformant. */ +#if !defined __STDC__ +# error "Compiler does not advertise C89 conformance" +#endif + +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ +struct buf { int x; }; +struct buf * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not \xHH hex character constants. + These do not provoke an error unfortunately, instead are silently treated + as an "x". The following induces an error, until -std is added to get + proper ANSI mode. Curiously \x00 != x always comes out true, for an + array size at least. It is necessary to write \x00 == 0 to get something + that is true only with -std. */ +int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) '\''x'\'' +int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), + int, int);' + +# Test code for whether the C compiler supports C89 (body of main). +ac_c_conftest_c89_main=' +ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); +' + +# Test code for whether the C compiler supports C99 (global declarations) +ac_c_conftest_c99_globals=' +// Does the compiler advertise C99 conformance? +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L +# error "Compiler does not advertise C99 conformance" +#endif + +#include +extern int puts (const char *); +extern int printf (const char *, ...); +extern int dprintf (int, const char *, ...); +extern void *malloc (size_t); + +// Check varargs macros. These examples are taken from C99 6.10.3.5. +// dprintf is used instead of fprintf to avoid needing to declare +// FILE and stderr. +#define debug(...) dprintf (2, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} + +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + #error "your preprocessor is broken" +#endif +#if BIG_OK +#else + #error "your preprocessor is broken" +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) + continue; + return 0; +} + +// Check varargs and va_copy. +static bool +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); + + const char *str = ""; + int number = 0; + float fnumber = 0; + + while (*format) + { + switch (*format++) + { + case '\''s'\'': // string + str = va_arg (args_copy, const char *); + break; + case '\''d'\'': // int + number = va_arg (args_copy, int); + break; + case '\''f'\'': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); + + return *str && number && fnumber; +} +' + +# Test code for whether the C compiler supports C99 (body of main). +ac_c_conftest_c99_main=' + // Check bool. + _Bool success = false; + success |= (argc != 0); + + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); + test_varargs_macros (); + + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; + + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[0] = argv[0][0]; + dynamic_array[ni.number - 1] = 543; + + // work around unused variable warnings + ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' + || dynamic_array[ni.number - 1] != 543); +' + +# Test code for whether the C compiler supports C11 (global declarations) +ac_c_conftest_c11_globals=' +// Does the compiler advertise C11 conformance? +#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L +# error "Compiler does not advertise C11 conformance" +#endif + +// Check _Alignas. +char _Alignas (double) aligned_as_double; +char _Alignas (0) no_special_alignment; +extern char aligned_as_int; +char _Alignas (0) _Alignas (int) aligned_as_int; + +// Check _Alignof. +enum +{ + int_alignment = _Alignof (int), + int_array_alignment = _Alignof (int[100]), + char_alignment = _Alignof (char) +}; +_Static_assert (0 < -_Alignof (int), "_Alignof is signed"); + +// Check _Noreturn. +int _Noreturn does_not_return (void) { for (;;) continue; } + +// Check _Static_assert. +struct test_static_assert +{ + int x; + _Static_assert (sizeof (int) <= sizeof (long int), + "_Static_assert does not work in struct"); + long int y; +}; + +// Check UTF-8 literals. +#define u8 syntax error! +char const utf8_literal[] = u8"happens to be ASCII" "another string"; + +// Check duplicate typedefs. +typedef long *long_ptr; +typedef long int *long_ptr; +typedef long_ptr long_ptr; + +// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. +struct anonymous +{ + union { + struct { int i; int j; }; + struct { int k; long int l; } w; + }; + int m; +} v1; +' + +# Test code for whether the C compiler supports C11 (body of main). +ac_c_conftest_c11_main=' + _Static_assert ((offsetof (struct anonymous, i) + == offsetof (struct anonymous, w.k)), + "Anonymous union alignment botch"); + v1.i = 2; + v1.w.k = 5; + ok |= v1.i != 5; +' + +# Test code for whether the C compiler supports C11 (complete). +ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} +${ac_c_conftest_c99_globals} +${ac_c_conftest_c11_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_c_conftest_c89_main} + ${ac_c_conftest_c99_main} + ${ac_c_conftest_c11_main} + return ok; +} +" + +# Test code for whether the C compiler supports C99 (complete). +ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} +${ac_c_conftest_c99_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_c_conftest_c89_main} + ${ac_c_conftest_c99_main} + return ok; +} +" + +# Test code for whether the C compiler supports C89 (complete). +ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_c_conftest_c89_main} + return ok; +} +" + +# Test code for whether the C++ compiler supports C++98 (global declarations) +ac_cxx_conftest_cxx98_globals=' +// Does the compiler advertise C++98 conformance? +#if !defined __cplusplus || __cplusplus < 199711L +# error "Compiler does not advertise C++98 conformance" +#endif + +// These inclusions are to reject old compilers that +// lack the unsuffixed header files. +#include +#include + +// and are *not* freestanding headers in C++98. +extern void assert (int); +namespace std { + extern int strcmp (const char *, const char *); +} + +// Namespaces, exceptions, and templates were all added after "C++ 2.0". +using std::exception; +using std::strcmp; + +namespace { + +void test_exception_syntax() +{ + try { + throw "test"; + } catch (const char *s) { + // Extra parentheses suppress a warning when building autoconf itself, + // due to lint rules shared with more typical C programs. + assert (!(strcmp) (s, "test")); + } +} + +template struct test_template +{ + T const val; + explicit test_template(T t) : val(t) {} + template T add(U u) { return static_cast(u) + val; } +}; + +} // anonymous namespace +' + +# Test code for whether the C++ compiler supports C++98 (body of main) +ac_cxx_conftest_cxx98_main=' + assert (argc); + assert (! argv[0]); +{ + test_exception_syntax (); + test_template tt (2.0); + assert (tt.add (4) == 6.0); + assert (true && !false); +} +' + +# Test code for whether the C++ compiler supports C++11 (global declarations) +ac_cxx_conftest_cxx11_globals=' +// Does the compiler advertise C++ 2011 conformance? +#if !defined __cplusplus || __cplusplus < 201103L +# error "Compiler does not advertise C++11 conformance" +#endif + +namespace cxx11test +{ + constexpr int get_val() { return 20; } + + struct testinit + { + int i; + double d; + }; + + class delegate + { + public: + delegate(int n) : n(n) {} + delegate(): delegate(2354) {} + + virtual int getval() { return this->n; }; + protected: + int n; + }; + + class overridden : public delegate + { + public: + overridden(int n): delegate(n) {} + virtual int getval() override final { return this->n * 2; } + }; + + class nocopy + { + public: + nocopy(int i): i(i) {} + nocopy() = default; + nocopy(const nocopy&) = delete; + nocopy & operator=(const nocopy&) = delete; + private: + int i; + }; + + // for testing lambda expressions + template Ret eval(Fn f, Ret v) + { + return f(v); + } + + // for testing variadic templates and trailing return types + template auto sum(V first) -> V + { + return first; + } + template auto sum(V first, Args... rest) -> V + { + return first + sum(rest...); + } +} +' + +# Test code for whether the C++ compiler supports C++11 (body of main) +ac_cxx_conftest_cxx11_main=' +{ + // Test auto and decltype + auto a1 = 6538; + auto a2 = 48573953.4; + auto a3 = "String literal"; + + int total = 0; + for (auto i = a3; *i; ++i) { total += *i; } + + decltype(a2) a4 = 34895.034; +} +{ + // Test constexpr + short sa[cxx11test::get_val()] = { 0 }; +} +{ + // Test initializer lists + cxx11test::testinit il = { 4323, 435234.23544 }; +} +{ + // Test range-based for + int array[] = {9, 7, 13, 15, 4, 18, 12, 10, 5, 3, + 14, 19, 17, 8, 6, 20, 16, 2, 11, 1}; + for (auto &x : array) { x += 23; } +} +{ + // Test lambda expressions + using cxx11test::eval; + assert (eval ([](int x) { return x*2; }, 21) == 42); + double d = 2.0; + assert (eval ([&](double x) { return d += x; }, 3.0) == 5.0); + assert (d == 5.0); + assert (eval ([=](double x) mutable { return d += x; }, 4.0) == 9.0); + assert (d == 5.0); +} +{ + // Test use of variadic templates + using cxx11test::sum; + auto a = sum(1); + auto b = sum(1, 2); + auto c = sum(1.0, 2.0, 3.0); +} +{ + // Test constructor delegation + cxx11test::delegate d1; + cxx11test::delegate d2(); + cxx11test::delegate d3(45); +} +{ + // Test override and final + cxx11test::overridden o1(55464); +} +{ + // Test nullptr + char *c = nullptr; +} +{ + // Test template brackets + test_template<::test_template> v(test_template(12)); +} +{ + // Unicode literals + char const *utf8 = u8"UTF-8 string \u2500"; + char16_t const *utf16 = u"UTF-8 string \u2500"; + char32_t const *utf32 = U"UTF-32 string \u2500"; +} +' + +# Test code for whether the C compiler supports C++11 (complete). +ac_cxx_conftest_cxx11_program="${ac_cxx_conftest_cxx98_globals} +${ac_cxx_conftest_cxx11_globals} + +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_cxx_conftest_cxx98_main} + ${ac_cxx_conftest_cxx11_main} + return ok; +} +" + +# Test code for whether the C compiler supports C++98 (complete). +ac_cxx_conftest_cxx98_program="${ac_cxx_conftest_cxx98_globals} +int +main (int argc, char **argv) +{ + int ok = 0; + ${ac_cxx_conftest_cxx98_main} + return ok; +} +" + +as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" +as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" +as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" +as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" +as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" +as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" +as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" +as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" +as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" + +# Auxiliary files required by this configure script. +ac_aux_files="install-sh config.guess config.sub" + +# Locations in which to look for auxiliary files. +ac_aux_dir_candidates="${srcdir}/./config" + +# Search for a directory containing all of the required auxiliary files, +# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. +# If we don't find one directory that contains all the files we need, +# we report the set of missing files from the *first* directory in +# $ac_aux_dir_candidates and give up. +ac_missing_aux_files="" +ac_first_candidate=: +printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in $ac_aux_dir_candidates +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + as_found=: + + printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 + ac_aux_dir_found=yes + ac_install_sh= + for ac_aux in $ac_aux_files + do + # As a special case, if "install-sh" is required, that requirement + # can be satisfied by any of "install-sh", "install.sh", or "shtool", + # and $ac_install_sh is set appropriately for whichever one is found. + if test x"$ac_aux" = x"install-sh" + then + if test -f "${as_dir}install-sh"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 + ac_install_sh="${as_dir}install-sh -c" + elif test -f "${as_dir}install.sh"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 + ac_install_sh="${as_dir}install.sh -c" + elif test -f "${as_dir}shtool"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 + ac_install_sh="${as_dir}shtool install -c" + else + ac_aux_dir_found=no + if $ac_first_candidate; then + ac_missing_aux_files="${ac_missing_aux_files} install-sh" + else + break + fi + fi + else + if test -f "${as_dir}${ac_aux}"; then + printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 + else + ac_aux_dir_found=no + if $ac_first_candidate; then + ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" + else + break + fi + fi + fi + done + if test "$ac_aux_dir_found" = yes; then + ac_aux_dir="$as_dir" + break + fi + ac_first_candidate=false + + as_found=false +done +IFS=$as_save_IFS +if $as_found +then : + +else $as_nop + as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 +fi + + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +if test -f "${ac_aux_dir}config.guess"; then + ac_config_guess="$SHELL ${ac_aux_dir}config.guess" +fi +if test -f "${ac_aux_dir}config.sub"; then + ac_config_sub="$SHELL ${ac_aux_dir}config.sub" +fi +if test -f "$ac_aux_dir/configure"; then + ac_configure="$SHELL ${ac_aux_dir}configure" +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' + and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +build_dynobj=no + +# If $runstatedir isn't set by autoconf (<2.70), set it manually. +if test x"$runstatedir" = x; then + runstatedir='${localstatedir}/run' +fi + + +# Don't make duplicate profile path entries for /etc/krb5.conf if +# $sysconfdir is /etc +if test "$sysconfdir" = /etc; then + SYSCONFCONF="" +else + SYSCONFCONF=":${sysconfdir}/krb5.conf" +fi + + +ac_reltopdir="." +if test ! -r "$srcdir/./aclocal.m4"; then + as_fn_error $? "Configure could not determine the relative topdir" "$LINENO" 5 +fi +ac_topdir=$srcdir/$ac_reltopdir +ac_config_fragdir=$ac_reltopdir/config +# echo "Looking for $srcdir/$ac_config_fragdir" + + + + + +krb5_ac_cflags_set=${CFLAGS+set} +krb5_ac_cxxflags_set=${CXXFLAGS+set} +krb5_ac_warn_cflags_set=${WARN_CFLAGS+set} +krb5_ac_warn_cxxflags_set=${WARN_CXXFLAGS+set} + + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. +set dummy ${ac_tool_prefix}clang; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}clang" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +printf "%s\n" "$CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "clang", so it can be a program name with args. +set dummy clang; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="clang" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +printf "%s\n" "$ac_ct_CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +fi + + +test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion -version; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +printf %s "checking whether the C compiler works... " >&6; } +ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else $as_nop + ac_file='' +fi +if test -z "$ac_file" +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +printf %s "checking for C compiler default output file name... " >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +printf "%s\n" "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +printf %s "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else $as_nop + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +printf "%s\n" "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +printf %s "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +printf "%s\n" "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +printf %s "checking for suffix of object files... " >&6; } +if test ${ac_cv_objext+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else $as_nop + printf "%s\n" "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +printf "%s\n" "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 +printf %s "checking whether the compiler supports GNU C... " >&6; } +if test ${ac_cv_c_compiler_gnu+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_compiler_gnu=yes +else $as_nop + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+y} +ac_save_CFLAGS=$CFLAGS +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +printf %s "checking whether $CC accepts -g... " >&6; } +if test ${ac_cv_prog_cc_g+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_g=yes +else $as_nop + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + +else $as_nop + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +printf "%s\n" "$ac_cv_prog_cc_g" >&6; } +if test $ac_test_CFLAGS; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +ac_prog_cc_stdc=no +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 +printf %s "checking for $CC option to enable C11 features... " >&6; } +if test ${ac_cv_prog_cc_c11+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c11=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_c_conftest_c11_program +_ACEOF +for ac_arg in '' -std=gnu11 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_c11=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cc_c11" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +fi + +if test "x$ac_cv_prog_cc_c11" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c11" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 +printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } + CC="$CC $ac_cv_prog_cc_c11" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 + ac_prog_cc_stdc=c11 +fi +fi +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 +printf %s "checking for $CC option to enable C99 features... " >&6; } +if test ${ac_cv_prog_cc_c99+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_c_conftest_c99_program +_ACEOF +for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_c99=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +fi + +if test "x$ac_cv_prog_cc_c99" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c99" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } + CC="$CC $ac_cv_prog_cc_c99" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 + ac_prog_cc_stdc=c99 +fi +fi +if test x$ac_prog_cc_stdc = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 +printf %s "checking for $CC option to enable C89 features... " >&6; } +if test ${ac_cv_prog_cc_c89+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_c_conftest_c89_program +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +fi + +if test "x$ac_cv_prog_cc_c89" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cc_c89" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } + CC="$CC $ac_cv_prog_cc_c89" +fi + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 + ac_prog_cc_stdc=c89 +fi +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_CXX+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +printf "%s\n" "$CXX" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC clang++ +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_CXX+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +printf "%s\n" "$ac_ct_CXX" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +printf "%s\n" "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C++" >&5 +printf %s "checking whether the compiler supports GNU C++... " >&6; } +if test ${ac_cv_cxx_compiler_gnu+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + ac_compiler_gnu=yes +else $as_nop + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +printf "%s\n" "$ac_cv_cxx_compiler_gnu" >&6; } +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+y} +ac_save_CXXFLAGS=$CXXFLAGS +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +printf %s "checking whether $CXX accepts -g... " >&6; } +if test ${ac_cv_prog_cxx_g+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_g=yes +else $as_nop + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + +else $as_nop + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +printf "%s\n" "$ac_cv_prog_cxx_g" >&6; } +if test $ac_test_CXXFLAGS; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_prog_cxx_stdcxx=no +if test x$ac_prog_cxx_stdcxx = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++11 features" >&5 +printf %s "checking for $CXX option to enable C++11 features... " >&6; } +if test ${ac_cv_prog_cxx_11+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cxx_11=no +ac_save_CXX=$CXX +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_cxx_conftest_cxx11_program +_ACEOF +for ac_arg in '' -std=gnu++11 -std=gnu++0x -std=c++11 -std=c++0x -qlanglvl=extended0x -AA +do + CXX="$ac_save_CXX $ac_arg" + if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_cxx11=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cxx_cxx11" != "xno" && break +done +rm -f conftest.$ac_ext +CXX=$ac_save_CXX +fi + +if test "x$ac_cv_prog_cxx_cxx11" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cxx_cxx11" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx11" >&5 +printf "%s\n" "$ac_cv_prog_cxx_cxx11" >&6; } + CXX="$CXX $ac_cv_prog_cxx_cxx11" +fi + ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx11 + ac_prog_cxx_stdcxx=cxx11 +fi +fi +if test x$ac_prog_cxx_stdcxx = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CXX option to enable C++98 features" >&5 +printf %s "checking for $CXX option to enable C++98 features... " >&6; } +if test ${ac_cv_prog_cxx_98+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_prog_cxx_98=no +ac_save_CXX=$CXX +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_cxx_conftest_cxx98_program +_ACEOF +for ac_arg in '' -std=gnu++98 -std=c++98 -qlanglvl=extended -AA +do + CXX="$ac_save_CXX $ac_arg" + if ac_fn_cxx_try_compile "$LINENO" +then : + ac_cv_prog_cxx_cxx98=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam + test "x$ac_cv_prog_cxx_cxx98" != "xno" && break +done +rm -f conftest.$ac_ext +CXX=$ac_save_CXX +fi + +if test "x$ac_cv_prog_cxx_cxx98" = xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +printf "%s\n" "unsupported" >&6; } +else $as_nop + if test "x$ac_cv_prog_cxx_cxx98" = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +printf "%s\n" "none needed" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_cxx98" >&5 +printf "%s\n" "$ac_cv_prog_cxx_cxx98" >&6; } + CXX="$CXX $ac_cv_prog_cxx_cxx98" +fi + ac_cv_prog_cxx_stdcxx=$ac_cv_prog_cxx_cxx98 + ac_prog_cxx_stdcxx=cxx98 +fi +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + cflags_warning_test_flags= + cachevar=`echo "krb5_cv_cc_flag_-Werror=unknown-warning-option" | sed -e s/=/_eq_/g -e s/-/_dash_/g -e s/[^a-zA-Z0-9_]/_/g` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if C compiler supports -Werror=unknown-warning-option" >&5 +printf %s "checking if C compiler supports -Werror=unknown-warning-option... " >&6; } +if eval test \${$cachevar+y} +then : + printf %s "(cached) " >&6 +else $as_nop + # first try without, then with + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + old_cflags="$CFLAGS" + CFLAGS="$CFLAGS $cflags_warning_test_flags -Werror=unknown-warning-option" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval $cachevar=yes +else $as_nop + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CFLAGS="$old_cflags" +else $as_nop + as_fn_error $? "compiling simple test program with $CFLAGS failed" "$LINENO" 5 +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +eval ac_res=\$$cachevar + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + if eval test '"${'$cachevar'}"' = yes; then + WARN_CFLAGS="$WARN_CFLAGS -Werror=unknown-warning-option" + fi + eval flag_supported='${'$cachevar'}' + + if test $flag_supported = yes; then + cflags_warning_test_flags=-Werror=unknown-warning-option + fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +printf %s "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test ${ac_cv_prog_CPP+y} +then : + printf %s "(cached) " >&6 +else $as_nop + # Double quotes because $CC needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO" +then : + +else $as_nop + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO" +then : + # Broken: success on invalid input. +continue +else $as_nop + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok +then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +printf "%s\n" "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO" +then : + +else $as_nop + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO" +then : + # Broken: success on invalid input. +continue +else $as_nop + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok +then : + +else $as_nop + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PKG_CONFIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +printf "%s\n" "$PKG_CONFIG" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_ac_pt_PKG_CONFIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + PKG_CONFIG="" + fi +fi +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"` + + + + + # Make sure we can run config.sub. +$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +printf %s "checking build system type... " >&6; } +if test ${ac_cv_build+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +printf "%s\n" "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +printf %s "checking host system type... " >&6; } +if test ${ac_cv_host+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || + as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +printf "%s\n" "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +printf %s "checking for a sed that does not truncate output... " >&6; } +if test ${ac_cv_path_SED+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_prog in sed gsed + do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + printf %s 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + printf "%s\n" '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +printf "%s\n" "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +printf %s "checking for grep that handles long lines and -e... " >&6; } +if test ${ac_cv_path_GREP+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_prog in grep ggrep + do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + printf %s 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + printf "%s\n" 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +printf "%s\n" "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +printf %s "checking for egrep... " >&6; } +if test ${ac_cv_path_EGREP+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_prog in egrep + do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + printf %s 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + printf "%s\n" 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +printf "%s\n" "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + + EXTRA_FILES="" + + +printf "%s\n" "#define _GNU_SOURCE 1" >>confdefs.h + + +printf "%s\n" "#define __STDC_WANT_LIB_EXT1__ 1" >>confdefs.h + + +if test $ac_cv_c_compiler_gnu = yes ; then + HAVE_GCC=yes + else HAVE_GCC= +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU linker" >&5 +printf %s "checking for GNU linker... " >&6; } +if test ${krb5_cv_prog_gnu_ld+y} +then : + printf %s "(cached) " >&6 +else $as_nop + krb5_cv_prog_gnu_ld=no +if test "$GCC" = yes; then + if { ac_try='$CC -Wl,-v 2>&1 | grep "GNU ld" > /dev/null' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + krb5_cv_prog_gnu_ld=yes + fi +fi +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_prog_gnu_ld" >&5 +printf "%s\n" "$krb5_cv_prog_gnu_ld" >&6; } + +# Check whether --with-size-optimizations was given. +if test ${with_size_optimizations+y} +then : + withval=$with_size_optimizations; +else $as_nop + withval=no +fi + +if test "$withval" = yes; then + +printf "%s\n" "#define CONFIG_SMALL 1" >>confdefs.h + +fi +# -Wno-long-long, if needed, for k5-platform.h without inttypes.h etc. +extra_gcc_warn_opts="-Wall -Wcast-align -Wshadow" +# -Wmissing-prototypes +if test "$GCC" = yes ; then + # Putting this here means we get -Os after -O2, which works. + if test "$with_size_optimizations" = yes && test "x$krb5_ac_cflags_set" != xset; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: adding -Os optimization option" >&5 +printf "%s\n" "$as_me: adding -Os optimization option" >&6;} + case "$CFLAGS" in + "-g -O2") CFLAGS="-g -Os" ;; + "-O2") CFLAGS="-Os" ;; + *) CFLAGS="$CFLAGS -Os" ;; + esac + fi + if test "x$krb5_ac_warn_cflags_set" = xset ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not adding extra gcc warning flags because WARN_CFLAGS was set" >&5 +printf "%s\n" "$as_me: not adding extra gcc warning flags because WARN_CFLAGS was set" >&6;} + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: adding extra warning flags for gcc" >&5 +printf "%s\n" "$as_me: adding extra warning flags for gcc" >&6;} + WARN_CFLAGS="$WARN_CFLAGS $extra_gcc_warn_opts -Wmissing-prototypes" + if test "`uname -s`" = Darwin ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: skipping pedantic warnings on Darwin" >&5 +printf "%s\n" "$as_me: skipping pedantic warnings on Darwin" >&6;} + elif test "`uname -s`" = Linux ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: skipping pedantic warnings on Linux" >&5 +printf "%s\n" "$as_me: skipping pedantic warnings on Linux" >&6;} + else + WARN_CFLAGS="$WARN_CFLAGS -pedantic" + fi + if test "$ac_cv_cxx_compiler_gnu" = yes; then + if test "x$krb5_ac_warn_cxxflags_set" = xset ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not adding extra g++ warnings because WARN_CXXFLAGS was set" >&5 +printf "%s\n" "$as_me: not adding extra g++ warnings because WARN_CXXFLAGS was set" >&6;} + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: adding extra warning flags for g++" >&5 +printf "%s\n" "$as_me: adding extra warning flags for g++" >&6;} + WARN_CXXFLAGS="$WARN_CXXFLAGS $extra_gcc_warn_opts" + fi + fi + # Currently, G++ does not support -Wno-format-zero-length. + cachevar=`echo "krb5_cv_cc_flag_-Wno-format-zero-length" | sed -e s/=/_eq_/g -e s/-/_dash_/g -e s/[^a-zA-Z0-9_]/_/g` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if C compiler supports -Wno-format-zero-length" >&5 +printf %s "checking if C compiler supports -Wno-format-zero-length... " >&6; } +if eval test \${$cachevar+y} +then : + printf %s "(cached) " >&6 +else $as_nop + # first try without, then with + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + old_cflags="$CFLAGS" + CFLAGS="$CFLAGS $cflags_warning_test_flags -Wno-format-zero-length" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval $cachevar=yes +else $as_nop + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CFLAGS="$old_cflags" +else $as_nop + as_fn_error $? "compiling simple test program with $CFLAGS failed" "$LINENO" 5 +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +eval ac_res=\$$cachevar + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + if eval test '"${'$cachevar'}"' = yes; then + WARN_CFLAGS="$WARN_CFLAGS -Wno-format-zero-length" + fi + eval flag_supported='${'$cachevar'}' + + # Other flags here may not be supported on some versions of + # gcc that people want to use. + for flag in overflow strict-overflow missing-format-attribute missing-prototypes return-type missing-braces parentheses switch unused-function unused-label unused-variable unused-value unknown-pragmas sign-compare newline-eof error=uninitialized no-maybe-uninitialized error=pointer-arith error=int-conversion error=incompatible-pointer-types error=discarded-qualifiers error=implicit-int ; do + cachevar=`echo "krb5_cv_cc_flag_-W$flag" | sed -e s/=/_eq_/g -e s/-/_dash_/g -e s/[^a-zA-Z0-9_]/_/g` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if C compiler supports -W$flag" >&5 +printf %s "checking if C compiler supports -W$flag... " >&6; } +if eval test \${$cachevar+y} +then : + printf %s "(cached) " >&6 +else $as_nop + # first try without, then with + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + old_cflags="$CFLAGS" + CFLAGS="$CFLAGS $cflags_warning_test_flags -W$flag" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval $cachevar=yes +else $as_nop + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CFLAGS="$old_cflags" +else $as_nop + as_fn_error $? "compiling simple test program with $CFLAGS failed" "$LINENO" 5 +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +eval ac_res=\$$cachevar + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + if eval test '"${'$cachevar'}"' = yes; then + WARN_CFLAGS="$WARN_CFLAGS -W$flag" + fi + eval flag_supported='${'$cachevar'}' + + done + # old-style-definition? generates many, many warnings + # + # Warnings that we'd like to turn into errors on versions of gcc + # that support promoting only specific warnings to errors, but + # we'll take as warnings on older compilers. (If such a warning + # is added after the -Werror=foo feature, you can just put + # error=foo in the above list, and skip the test for the + # warning-only form.) At least in some versions, -Werror= doesn't + # seem to make the conditions actual errors, but still issues + # warnings; I guess we'll take what we can get. + # + # We're currently targeting C89+, not C99, so disallow some + # constructs. + for flag in declaration-after-statement ; do + cachevar=`echo "krb5_cv_cc_flag_-Werror=$flag" | sed -e s/=/_eq_/g -e s/-/_dash_/g -e s/[^a-zA-Z0-9_]/_/g` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if C compiler supports -Werror=$flag" >&5 +printf %s "checking if C compiler supports -Werror=$flag... " >&6; } +if eval test \${$cachevar+y} +then : + printf %s "(cached) " >&6 +else $as_nop + # first try without, then with + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + old_cflags="$CFLAGS" + CFLAGS="$CFLAGS $cflags_warning_test_flags -Werror=$flag" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval $cachevar=yes +else $as_nop + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CFLAGS="$old_cflags" +else $as_nop + as_fn_error $? "compiling simple test program with $CFLAGS failed" "$LINENO" 5 +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +eval ac_res=\$$cachevar + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + if eval test '"${'$cachevar'}"' = yes; then + WARN_CFLAGS="$WARN_CFLAGS -Werror=$flag" + fi + eval flag_supported='${'$cachevar'}' + + if test "$flag_supported" = no; then + cachevar=`echo "krb5_cv_cc_flag_-W$flag" | sed -e s/=/_eq_/g -e s/-/_dash_/g -e s/[^a-zA-Z0-9_]/_/g` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if C compiler supports -W$flag" >&5 +printf %s "checking if C compiler supports -W$flag... " >&6; } +if eval test \${$cachevar+y} +then : + printf %s "(cached) " >&6 +else $as_nop + # first try without, then with + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + old_cflags="$CFLAGS" + CFLAGS="$CFLAGS $cflags_warning_test_flags -W$flag" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval $cachevar=yes +else $as_nop + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CFLAGS="$old_cflags" +else $as_nop + as_fn_error $? "compiling simple test program with $CFLAGS failed" "$LINENO" 5 +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +eval ac_res=\$$cachevar + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + if eval test '"${'$cachevar'}"' = yes; then + WARN_CFLAGS="$WARN_CFLAGS -W$flag" + fi + eval flag_supported='${'$cachevar'}' + + fi + done + # We require function declarations now. + # + # In some compiler versions -- e.g., "gcc version 4.2.1 (Apple + # Inc. build 5664)" -- the -Werror- option works, but the -Werror= + # version doesn't cause implicitly declared functions to be + # flagged as errors. If neither works, -Wall implies + # -Wimplicit-function-declaration so don't bother. + cachevar=`echo "krb5_cv_cc_flag_-Werror-implicit-function-declaration" | sed -e s/=/_eq_/g -e s/-/_dash_/g -e s/[^a-zA-Z0-9_]/_/g` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if C compiler supports -Werror-implicit-function-declaration" >&5 +printf %s "checking if C compiler supports -Werror-implicit-function-declaration... " >&6; } +if eval test \${$cachevar+y} +then : + printf %s "(cached) " >&6 +else $as_nop + # first try without, then with + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + old_cflags="$CFLAGS" + CFLAGS="$CFLAGS $cflags_warning_test_flags -Werror-implicit-function-declaration" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval $cachevar=yes +else $as_nop + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CFLAGS="$old_cflags" +else $as_nop + as_fn_error $? "compiling simple test program with $CFLAGS failed" "$LINENO" 5 +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +eval ac_res=\$$cachevar + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + if eval test '"${'$cachevar'}"' = yes; then + WARN_CFLAGS="$WARN_CFLAGS -Werror-implicit-function-declaration" + fi + eval flag_supported='${'$cachevar'}' + + if test "implicit-function-declaration_supported" = no; then + cachevar=`echo "krb5_cv_cc_flag_-Werror=implicit-function-declaration" | sed -e s/=/_eq_/g -e s/-/_dash_/g -e s/[^a-zA-Z0-9_]/_/g` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if C compiler supports -Werror=implicit-function-declaration" >&5 +printf %s "checking if C compiler supports -Werror=implicit-function-declaration... " >&6; } +if eval test \${$cachevar+y} +then : + printf %s "(cached) " >&6 +else $as_nop + # first try without, then with + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + old_cflags="$CFLAGS" + CFLAGS="$CFLAGS $cflags_warning_test_flags -Werror=implicit-function-declaration" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval $cachevar=yes +else $as_nop + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + CFLAGS="$old_cflags" +else $as_nop + as_fn_error $? "compiling simple test program with $CFLAGS failed" "$LINENO" 5 +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +eval ac_res=\$$cachevar + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } + if eval test '"${'$cachevar'}"' = yes; then + WARN_CFLAGS="$WARN_CFLAGS -Werror=implicit-function-declaration" + fi + eval flag_supported='${'$cachevar'}' + + fi + # + fi + if test "`uname -s`" = Darwin ; then + # Someday this should be a feature test. + # One current (Jaguar = OS 10.2) problem: + # Archive library with foo.o undef sym X and bar.o common sym X, + # if foo.o is pulled in at link time, bar.o may not be, causing + # the linker to complain. + # Dynamic library problems too? + case "$CC $CFLAGS" in + *-fcommon*) ;; # why someone would do this, I don't know + *-fno-common*) ;; # okay, they're already doing the right thing + *) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: disabling the use of common storage on Darwin" >&5 +printf "%s\n" "$as_me: disabling the use of common storage on Darwin" >&6;} + CFLAGS="$CFLAGS -fno-common" + ;; + esac + fi +else + if test "`uname -s`" = AIX ; then + # Using AIX but not GCC, assume native compiler. + # The native compiler appears not to give a nonzero exit + # status for certain classes of errors, like missing arguments + # in function calls. Let's try to fix that with -qhalt=e. + case "$CC $CFLAGS" in + *-qhalt=*) ;; + *) + CFLAGS="$CFLAGS -qhalt=e" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: adding -qhalt=e for better error reporting" >&5 +printf "%s\n" "$as_me: adding -qhalt=e for better error reporting" >&6;} + ;; + esac + # Also, the optimizer isn't turned on by default, which means + # the static inline functions get left in random object files, + # leading to references to pthread_mutex_lock from anything that + # includes k5-int.h whether it uses threads or not. + case "$CC $CFLAGS" in + *-O*) ;; + *) + CFLAGS="$CFLAGS -O" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: adding -O for inline thread-support function elimination" >&5 +printf "%s\n" "$as_me: adding -O for inline thread-support function elimination" >&6;} + ;; + esac + fi + if test "`uname -s`" = SunOS ; then + # Using Solaris but not GCC, assume Sunsoft compiler. + # We have some error-out-on-warning options available. + # Sunsoft 12 compiler defaults to -xc99=all, it appears, so "inline" + # works, but it also means that declaration-in-code warnings won't + # be issued. + # -v -fd -errwarn=E_DECLARATION_IN_CODE ... + if test "x$krb5_ac_warn_cflags_set" = xset ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not adding extra warning flags because WARN_CFLAGS was set" >&5 +printf "%s\n" "$as_me: not adding extra warning flags because WARN_CFLAGS was set" >&6;} + else + WARN_CFLAGS="-errtags=yes -errwarn=E_BAD_PTR_INT_COMBINATION,E_BAD_PTR_INT_COMB_ARG,E_PTR_TO_VOID_IN_ARITHMETIC,E_NO_IMPLICIT_DECL_ALLOWED,E_ATTRIBUTE_PARAM_UNDEFINED" + fi + if test "x$krb5_ac_warn_cxxflags_set" = xset ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not adding extra warning flags because WARN_CXXFLAGS was set" >&5 +printf "%s\n" "$as_me: not adding extra warning flags because WARN_CXXFLAGS was set" >&6;} + else + WARN_CXXFLAGS="-errtags=yes +w +w2 -xport64" + fi + fi +fi + + + +if test -z "$LD" ; then LD=$CC; fi + + + +# Check whether --with-system-et was given. +if test ${with_system_et+y} +then : + withval=$with_system_et; +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which version of com_err to use" >&5 +printf %s "checking which version of com_err to use... " >&6; } +if test "x$with_system_et" = xyes ; then + # This will be changed to "intlsys" if textdomain support is present. + COM_ERR_VERSION=sys + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: system" >&5 +printf "%s\n" "system" >&6; } +else + COM_ERR_VERSION=k5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: krb5" >&5 +printf "%s\n" "krb5" >&6; } +fi +OLDLIBS="$LIBS" +COM_ERR_LIB=-lcom_err +if test $COM_ERR_VERSION = sys; then + +pkg_failed=no +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for com_err" >&5 +printf %s "checking for com_err... " >&6; } + +if test -n "$COM_ERR_CFLAGS"; then + pkg_cv_COM_ERR_CFLAGS="$COM_ERR_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"com_err\""; } >&5 + ($PKG_CONFIG --exists --print-errors "com_err") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_COM_ERR_CFLAGS=`$PKG_CONFIG --cflags "com_err" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$COM_ERR_LIBS"; then + pkg_cv_COM_ERR_LIBS="$COM_ERR_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"com_err\""; } >&5 + ($PKG_CONFIG --exists --print-errors "com_err") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_COM_ERR_LIBS=`$PKG_CONFIG --libs "com_err" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + COM_ERR_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "com_err" 2>&1` + else + COM_ERR_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "com_err" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$COM_ERR_PKG_ERRORS" >&5 + + have_com_err=no +elif test $pkg_failed = untried; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + have_com_err=no +else + COM_ERR_CFLAGS=$pkg_cv_COM_ERR_CFLAGS + COM_ERR_LIBS=$pkg_cv_COM_ERR_LIBS + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + have_com_err=yes +fi + if test "x$have_com_err = xyes"; then + COM_ERR_LIB="$COM_ERR_LIBS" + fi + LIBS="$LIBS $COM_ERR_LIB" + # check for various functions we need + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for add_error_table in -lcom_err" >&5 +printf %s "checking for add_error_table in -lcom_err... " >&6; } +if test ${ac_cv_lib_com_err_add_error_table+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcom_err $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char add_error_table (); +int +main (void) +{ +return add_error_table (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_com_err_add_error_table=yes +else $as_nop + ac_cv_lib_com_err_add_error_table=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_com_err_add_error_table" >&5 +printf "%s\n" "$ac_cv_lib_com_err_add_error_table" >&6; } +if test "x$ac_cv_lib_com_err_add_error_table" = xyes +then : + : +else $as_nop + as_fn_error $? "cannot find add_error_table in com_err library" "$LINENO" 5 +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for remove_error_table in -lcom_err" >&5 +printf %s "checking for remove_error_table in -lcom_err... " >&6; } +if test ${ac_cv_lib_com_err_remove_error_table+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcom_err $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char remove_error_table (); +int +main (void) +{ +return remove_error_table (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_com_err_remove_error_table=yes +else $as_nop + ac_cv_lib_com_err_remove_error_table=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_com_err_remove_error_table" >&5 +printf "%s\n" "$ac_cv_lib_com_err_remove_error_table" >&6; } +if test "x$ac_cv_lib_com_err_remove_error_table" = xyes +then : + : +else $as_nop + as_fn_error $? "cannot find remove_error_table in com_err library" "$LINENO" 5 +fi + + # make sure compile_et provides "et_foo" name + cat >> conf$$e.et <&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_compile_et+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$compile_et"; then + ac_cv_prog_compile_et="$compile_et" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_compile_et="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +compile_et=$ac_cv_prog_compile_et +if test -n "$compile_et"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $compile_et" >&5 +printf "%s\n" "$compile_et" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$compile_et" && break +done +test -n "$compile_et" || compile_et="false" + + if test "$compile_et" = false; then + as_fn_error $? "cannot find compile_et" "$LINENO" 5 + fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether compile_et is useful" >&5 +printf %s "checking whether compile_et is useful... " >&6; } +if test ${krb5_cv_compile_et_useful+y} +then : + printf %s "(cached) " >&6 +else $as_nop + + if compile_et conf$$e.et >/dev/null 2>&1 ; then true ; else + as_fn_error $? "execution failed" "$LINENO" 5 + fi + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include "conf$$e.h" + +int +main (void) +{ +&et_foo_error_table; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + +else $as_nop + as_fn_error $? "cannot use et_foo_error_table" "$LINENO" 5 +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + # Anything else we need to test for? + rm -f conf$$e.c conf$$e.h + krb5_cv_compile_et_useful=yes + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_compile_et_useful" >&5 +printf "%s\n" "$krb5_cv_compile_et_useful" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether compile_et supports --textdomain" >&5 +printf %s "checking whether compile_et supports --textdomain... " >&6; } +if test ${krb5_cv_compile_et_textdomain+y} +then : + printf %s "(cached) " >&6 +else $as_nop + + krb5_cv_compile_et_textdomain=no + if compile_et --textdomain=xyzw conf$$e.et >/dev/null 2>&1 ; then + if grep -q xyzw conf$$e.c; then + krb5_cv_compile_et_textdomain=yes + fi + fi + rm -f conf$$e.c conf$$e.h + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_compile_et_textdomain" >&5 +printf "%s\n" "$krb5_cv_compile_et_textdomain" >&6; } + if test "$krb5_cv_compile_et_textdomain" = yes; then + COM_ERR_VERSION=intlsys + fi + rm -f conf$$e.et +fi + + +LIBS="$OLDLIBS" +if test "$COM_ERR_VERSION" = k5 -o "$COM_ERR_VERSION" = intlsys; then + +printf "%s\n" "#define HAVE_COM_ERR_INTL 1" >>confdefs.h + +fi + + +# Check whether --with-system-ss was given. +if test ${with_system_ss+y} +then : + withval=$with_system_ss; +fi + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking which version of subsystem package to use" >&5 +printf %s "checking which version of subsystem package to use... " >&6; } +if test "x$with_system_ss" = xyes ; then + SS_VERSION=sys + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: system" >&5 +printf "%s\n" "system" >&6; } + # todo: check for various libraries we might need + # in the meantime... + test "x${SS_LIB+set}" = xset || SS_LIB=-lss + old_LIBS="$LIBS" + LIBS="$LIBS $SS_LIB" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether system ss package works" >&5 +printf %s "checking whether system ss package works... " >&6; } +if test ${krb5_cv_system_ss_okay+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test "$cross_compiling" = yes +then : + krb5_cv_system_ss_okay=assumed +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + int main(int argc, char *argv[]) { + if (argc == 42) { + int i, err; + i = ss_create_invocation("foo","foo","",0,&err); + ss_listen(i); + } + return 0; + } +_ACEOF +if ac_fn_c_try_run "$LINENO" +then : + krb5_cv_system_ss_okay=yes +else $as_nop + as_fn_error $? "cannot run test program" "$LINENO" 5 +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_system_ss_okay" >&5 +printf "%s\n" "$krb5_cv_system_ss_okay" >&6; } + LIBS="$old_LIBS" + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if ss_execute_command needs a prototype provided" >&5 +printf %s "checking if ss_execute_command needs a prototype provided... " >&6; } +if test ${krb5_cv_func_ss_execute_command_noproto+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +#undef ss_execute_command + struct k5foo {int foo; } xx; + extern int ss_execute_command (struct k5foo*); + ss_execute_command(&xx); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_func_ss_execute_command_noproto=yes +else $as_nop + krb5_cv_func_ss_execute_command_noproto=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_func_ss_execute_command_noproto" >&5 +printf "%s\n" "$krb5_cv_func_ss_execute_command_noproto" >&6; } +if test $krb5_cv_func_ss_execute_command_noproto = yes; then + +printf "%s\n" "#define NEED_SS_EXECUTE_COMMAND_PROTO 1" >>confdefs.h + +fi + + +else + SS_VERSION=k5 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: krb5" >&5 +printf "%s\n" "krb5" >&6; } +fi + + + + +# Check whether --with-system-db was given. +if test ${with_system_db+y} +then : + withval=$with_system_db; +fi + + + +if test "x$with_system_db" = xyes ; then + DB_VERSION=sys + # TODO: Do we have specific routines we should check for? + # How about known, easily recognizable bugs? + # We want to use bt_rseq in some cases, but no other version but + # ours has it right now. + # + # Okay, check the variables. + test "x${DB_HEADER+set}" = xset || DB_HEADER=db.h + test "x${DB_LIB+set}" = xset || DB_LIB=-ldb + # + if test "x${DB_HEADER}" = xdb.h ; then + DB_HEADER_VERSION=sys + else + DB_HEADER_VERSION=redirect + fi + KDB5_DB_LIB="$DB_LIB" +else + DB_VERSION=k5 + +printf "%s\n" "#define HAVE_BT_RSEQ 1" >>confdefs.h + + DB_HEADER=db.h + DB_HEADER_VERSION=k5 + # libdb gets sucked into libkdb + KDB5_DB_LIB= + # needed for a couple of things that need libdb for its own sake + DB_LIB=-ldb +fi + + + + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +printf %s "checking for an ANSI C-conforming const... " >&6; } +if test ${ac_cv_c_const+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + +#ifndef __cplusplus + /* Ultrix mips cc rejects this sort of thing. */ + typedef int charset[2]; + const charset cs = { 0, 0 }; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* IBM XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* IBM XL C 1.02.0.0 rejects this sort of thing, saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_c_const=yes +else $as_nop + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +printf "%s\n" "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +printf "%s\n" "#define const /**/" >>confdefs.h + +fi + + +# Check whether --with-netlib was given. +if test ${with_netlib+y} +then : + withval=$with_netlib; if test "$withval" = yes -o "$withval" = no ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"netlib will link with C library resolver only\"" >&5 +printf "%s\n" "\"netlib will link with C library resolver only\"" >&6; } + else + LIBS="$LIBS $withval" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: \"netlib will use \'$withval\'\"" >&5 +printf "%s\n" "\"netlib will use \'$withval\'\"" >&6; } + fi + +else $as_nop + + # Most operating systems have gethostbyname() in the default searched + # libraries (i.e. libc): + ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" +if test "x$ac_cv_func_gethostbyname" = xyes +then : + +else $as_nop + + # Some OSes (eg. Solaris) place it in libnsl: + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 +printf %s "checking for gethostbyname in -lnsl... " >&6; } +if test ${ac_cv_lib_nsl_gethostbyname+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main (void) +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_nsl_gethostbyname=yes +else $as_nop + ac_cv_lib_nsl_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 +printf "%s\n" "$ac_cv_lib_nsl_gethostbyname" >&6; } +if test "x$ac_cv_lib_nsl_gethostbyname" = xyes +then : + printf "%s\n" "#define HAVE_LIBNSL 1" >>confdefs.h + + LIBS="-lnsl $LIBS" + +else $as_nop + + # Some strange OSes (SINIX) have it in libsocket: + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lsocket" >&5 +printf %s "checking for gethostbyname in -lsocket... " >&6; } +if test ${ac_cv_lib_socket_gethostbyname+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main (void) +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_socket_gethostbyname=yes +else $as_nop + ac_cv_lib_socket_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_gethostbyname" >&5 +printf "%s\n" "$ac_cv_lib_socket_gethostbyname" >&6; } +if test "x$ac_cv_lib_socket_gethostbyname" = xyes +then : + printf "%s\n" "#define HAVE_LIBSOCKET 1" >>confdefs.h + + LIBS="-lsocket $LIBS" + +else $as_nop + + # Unfortunately libsocket sometimes depends on libnsl. + # AC_CHECK_LIB's API is essentially broken so the following + # ugliness is necessary: + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lsocket" >&5 +printf %s "checking for gethostbyname in -lsocket... " >&6; } +if test ${ac_cv_lib_socket_gethostbyname+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket -lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main (void) +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_socket_gethostbyname=yes +else $as_nop + ac_cv_lib_socket_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_gethostbyname" >&5 +printf "%s\n" "$ac_cv_lib_socket_gethostbyname" >&6; } +if test "x$ac_cv_lib_socket_gethostbyname" = xyes +then : + LIBS="-lsocket -lnsl $LIBS" +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lresolv" >&5 +printf %s "checking for gethostbyname in -lresolv... " >&6; } +if test ${ac_cv_lib_resolv_gethostbyname+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lresolv $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char gethostbyname (); +int +main (void) +{ +return gethostbyname (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_resolv_gethostbyname=yes +else $as_nop + ac_cv_lib_resolv_gethostbyname=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_gethostbyname" >&5 +printf "%s\n" "$ac_cv_lib_resolv_gethostbyname" >&6; } +if test "x$ac_cv_lib_resolv_gethostbyname" = xyes +then : + LIBS="-lresolv $LIBS" +fi + +fi + + +fi + + +fi + + +fi + + ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket" +if test "x$ac_cv_func_socket" = xyes +then : + +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 +printf %s "checking for socket in -lsocket... " >&6; } +if test ${ac_cv_lib_socket_socket+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char socket (); +int +main (void) +{ +return socket (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_socket_socket=yes +else $as_nop + ac_cv_lib_socket_socket=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 +printf "%s\n" "$ac_cv_lib_socket_socket" >&6; } +if test "x$ac_cv_lib_socket_socket" = xyes +then : + printf "%s\n" "#define HAVE_LIBSOCKET 1" >>confdefs.h + + LIBS="-lsocket $LIBS" + +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 +printf %s "checking for socket in -lsocket... " >&6; } +if test ${ac_cv_lib_socket_socket+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket -lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char socket (); +int +main (void) +{ +return socket (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_socket_socket=yes +else $as_nop + ac_cv_lib_socket_socket=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 +printf "%s\n" "$ac_cv_lib_socket_socket" >&6; } +if test "x$ac_cv_lib_socket_socket" = xyes +then : + LIBS="-lsocket -lnsl $LIBS" +fi + +fi + +fi + + +enable_dns=yes + # Check whether --enable-dns-for-realm was given. +if test ${enable_dns_for_realm+y} +then : + enableval=$enable_dns_for_realm; +else $as_nop + enable_dns_for_realm=no +fi + + if test "$enable_dns_for_realm" = yes; then + +printf "%s\n" "#define KRB5_DNS_LOOKUP_REALM 1" >>confdefs.h + + fi + + +printf "%s\n" "#define KRB5_DNS_LOOKUP 1" >>confdefs.h + + + + if test "$enable_dns" = yes ; then + # We assume that if libresolv exists we can link against it. + # This may get us a gethostby* that doesn't respect nsswitch. + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lresolv" >&5 +printf %s "checking for main in -lresolv... " >&6; } +if test ${ac_cv_lib_resolv_main+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lresolv $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main (void) +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_resolv_main=yes +else $as_nop + ac_cv_lib_resolv_main=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_main" >&5 +printf "%s\n" "$ac_cv_lib_resolv_main" >&6; } +if test "x$ac_cv_lib_resolv_main" = xyes +then : + printf "%s\n" "#define HAVE_LIBRESOLV 1" >>confdefs.h + + LIBS="-lresolv $LIBS" + +fi + + +for krb5_func in res_ninit res_nclose res_ndestroy res_nsearch ns_initparse ns_name_uncompress dn_skipname res_search; do + +# Solaris 9 prototypes ns_name_uncompress() in arpa/nameser.h, but +# doesn't export it from libresolv.so, so we use extreme paranoia here +# and check both for the declaration and that we can link against the +# function. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $krb5_func" >&5 +printf %s "checking for $krb5_func... " >&6; } +if eval test \${krb5_cv_func_$krb5_func+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + #include + #include + +int +main (void) +{ +/* + * Use volatile, or else optimization can cause false positives. + */ + void (* volatile p)() = (void (*)())$krb5_func; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + eval "krb5_cv_func_$krb5_func=yes" +else $as_nop + eval "krb5_cv_func_$krb5_func=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$krb5_cv_func_$krb5_func + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } +if test `eval 'as_val=${'krb5_cv_func_$krb5_func'};printf "%s\n" "$as_val"'` = yes +then : + +cat >>confdefs.h <<_ACEOF +#define `printf "%s\n" "HAVE_$krb5_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + if test $krb5_cv_func_res_nsearch = no \ + && test $krb5_cv_func_res_search = no; then + # Attempt to link with res_search(), in case it's not prototyped. + ac_fn_c_check_func "$LINENO" "res_search" "ac_cv_func_res_search" +if test "x$ac_cv_func_res_search" = xyes +then : + +printf "%s\n" "#define HAVE_RES_SEARCH 1" >>confdefs.h + +else $as_nop + as_fn_error $? "cannot find res_nsearch or res_search" "$LINENO" 5 +fi + + fi + fi + + +fi + +# Check whether --with-hesiod was given. +if test ${with_hesiod+y} +then : + withval=$with_hesiod; hesiod=$with_hesiod +else $as_nop + with_hesiod=no +fi + +if test "$with_hesiod" != "no"; then + HESIOD_DEFS=-DHESIOD + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for res_send in -lresolv" >&5 +printf %s "checking for res_send in -lresolv... " >&6; } +if test ${ac_cv_lib_resolv_res_send+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lresolv $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char res_send (); +int +main (void) +{ +return res_send (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_resolv_res_send=yes +else $as_nop + ac_cv_lib_resolv_res_send=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_resolv_res_send" >&5 +printf "%s\n" "$ac_cv_lib_resolv_res_send" >&6; } +if test "x$ac_cv_lib_resolv_res_send" = xyes +then : + res_lib=-lresolv +fi + + if test "$hesiod" != "yes"; then + HESIOD_LIBS="-L${hesiod}/lib -lhesiod $res_lib" + else + HESIOD_LIBS="-lhesiod $res_lib" + fi +else + HESIOD_DEFS= + HESIOD_LIBS= +fi + + # Check whether --enable-maintainer-mode was given. +if test ${enable_maintainer_mode+y} +then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else $as_nop + USE_MAINTAINER_MODE=no +fi + +if test "$USE_MAINTAINER_MODE" = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: enabling maintainer mode" >&5 +printf "%s\n" "$as_me: enabling maintainer mode" >&6;} +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi +MAINT=$MAINTAINER_MODE_TRUE + + + + CONFIG_RELTOPDIR=$ac_reltopdir + +lib_frag=$srcdir/$ac_config_fragdir/lib.in + +libobj_frag=$srcdir/$ac_config_fragdir/libobj.in + +libnover_frag=$srcdir/$ac_config_fragdir/libnover.in + +libpriv_frag=$srcdir/$ac_config_fragdir/libpriv.in + +libnodeps_frag=$srcdir/$ac_config_fragdir/libnodeps.in + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pragma weak references are supported" >&5 +printf %s "checking whether pragma weak references are supported... " >&6; } +if test ${krb5_cv_pragma_weak_ref+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#pragma weak flurbl + extern int flurbl(void); +int +main (void) +{ +if (&flurbl != 0) return flurbl(); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + krb5_cv_pragma_weak_ref=yes +else $as_nop + krb5_cv_pragma_weak_ref=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_pragma_weak_ref" >&5 +printf "%s\n" "$krb5_cv_pragma_weak_ref" >&6; } +if test $krb5_cv_pragma_weak_ref = yes ; then + +printf "%s\n" "#define HAVE_PRAGMA_WEAK_REF 1" >>confdefs.h + +fi + + +# Check whether --with-ldap was given. +if test ${with_ldap+y} +then : + withval=$with_ldap; case "$withval" in + OPENLDAP) with_ldap=yes ;; + yes | no) ;; + *) as_fn_error $? "Invalid option value --with-ldap=\"$withval\"" "$LINENO" 5 ;; +esac +else $as_nop + with_ldap=no +fi + +if test "$with_ldap" = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: enabling OpenLDAP database backend module support" >&5 +printf "%s\n" "$as_me: enabling OpenLDAP database backend module support" >&6;} + OPENLDAP_PLUGIN=yes +fi + +krb5_cv_host=$host + +. $ac_topdir/config/shlib.conf + +# Check whether --enable-delayed-initialization was given. +if test ${enable_delayed_initialization+y} +then : + enableval=$enable_delayed_initialization; +else $as_nop + enable_delayed_initialization=yes +fi + +case "$enable_delayed_initialization" in + yes) + +printf "%s\n" "#define DELAY_INITIALIZER 1" >>confdefs.h + ;; + no) ;; + *) as_fn_error $? "invalid option $enable_delayed_initialization for delayed-initialization" "$LINENO" 5 ;; +esac +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for constructor/destructor attribute support" >&5 +printf %s "checking for constructor/destructor attribute support... " >&6; } +if test ${krb5_cv_attr_constructor_destructor+y} +then : + printf %s "(cached) " >&6 +else $as_nop + rm -f conftest.1 conftest.2 +if test -r conftest.1 || test -r conftest.2 ; then + as_fn_error $? "write error in local file system?" "$LINENO" 5 +fi +true > conftest.1 +true > conftest.2 +if test -r conftest.1 && test -r conftest.2 ; then true ; else + as_fn_error $? "write error in local file system?" "$LINENO" 5 +fi +a=no +b=no +# blindly assume we have 'unlink' and unistd.h. +if test "$cross_compiling" = yes +then : + as_fn_error $? "Cannot test for constructor/destructor support when cross compiling" "$LINENO" 5 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + void foo1() __attribute__((constructor)); + void foo1() { unlink("conftest.1"); } + void foo2() __attribute__((destructor)); + void foo2() { unlink("conftest.2"); } + int main () { return 0; } +_ACEOF +if ac_fn_c_try_run "$LINENO" +then : + test -r conftest.1 || a=yes + test -r conftest.2 || b=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +case $krb5_cv_host in +*-*-aix4.*) + # Under AIX 4.3.3, at least, shared library destructor functions + # appear to get executed in reverse link order (right to left), + # so that a library's destructor function may run after that of + # libraries it depends on, and may still have to access in the + # destructor. + # + # That counts as "not working", for me, but it's a much more + # complicated test case to set up. + b=no + ;; +esac +krb5_cv_attr_constructor_destructor="$a,$b" + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_attr_constructor_destructor" >&5 +printf "%s\n" "$krb5_cv_attr_constructor_destructor" >&6; } +# Okay, krb5_cv_... should be set now. +case $krb5_cv_attr_constructor_destructor in + yes,*) + +printf "%s\n" "#define CONSTRUCTOR_ATTR_WORKS 1" >>confdefs.h + ;; +esac +case $krb5_cv_attr_constructor_destructor in + *,yes) + +printf "%s\n" "#define DESTRUCTOR_ATTR_WORKS 1" >>confdefs.h + ;; +esac + +if test -z "$use_linker_init_option" ; then + as_fn_error $? "ran INITFINI before checking shlib.conf?" "$LINENO" 5 +fi +if test "$use_linker_init_option" = yes; then + +printf "%s\n" "#define USE_LINKER_INIT_OPTION 1" >>confdefs.h + +fi +if test "$use_linker_fini_option" = yes; then + +printf "%s\n" "#define USE_LINKER_FINI_OPTION 1" >>confdefs.h + +fi + + +# Check whether --enable-thread-support was given. +if test ${enable_thread_support+y} +then : + enableval=$enable_thread_support; +else $as_nop + enable_thread_support=yes +fi + +if test "$enable_thread_support" = yes ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: enabling thread support" >&5 +printf "%s\n" "$as_me: enabling thread support" >&6;} + +printf "%s\n" "#define ENABLE_THREADS 1" >>confdefs.h + +fi +if test "$enable_thread_support" = yes; then + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ax_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on Tru64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + if test "x$PTHREAD_CC" != "x" +then : + CC="$PTHREAD_CC" +fi + if test "x$PTHREAD_CXX" != "x" +then : + CXX="$PTHREAD_CXX" +fi + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS" >&5 +printf %s "checking for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char pthread_join (); +int +main (void) +{ +return pthread_join (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +printf "%s\n" "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xno"; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items with a "," contain both +# C compiler flags (before ",") and linker flags (after ","). Other items +# starting with a "-" are C compiler flags, and remaining items are +# library names, except for "none" which indicates that we try without +# any flags at all, and "pthread-config" which is a program returning +# the flags for the Pth emulation library. + +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc +# pthread: Linux, etcetera +# --thread-safe: KAI C++ +# pthread-config: use pthread-config program (for GNU Pth library) + +case $host_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_ZOS_MISSING" >/dev/null 2>&1 +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&5 +printf "%s\n" "$as_me: WARNING: IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support." >&2;} +fi +rm -rf conftest* + + ;; + + solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags" + ;; +esac + +# Are we compiling with Clang? + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC is Clang" >&5 +printf %s "checking whether $CC is Clang... " >&6; } +if test ${ax_cv_PTHREAD_CLANG+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "AX_PTHREAD_CC_IS_CLANG" >/dev/null 2>&1 +then : + ax_cv_PTHREAD_CLANG=yes +fi +rm -rf conftest* + + fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG" >&5 +printf "%s\n" "$ax_cv_PTHREAD_CLANG" >&6; } +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +# Note that for GCC and Clang -pthread generally implies -lpthread, +# except when -nostdlib is passed. +# This is problematic using libtool to build C++ shared libraries with pthread: +# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460 +# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333 +# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555 +# To solve this, first try -pthread together with -lpthread for GCC + +if test "x$GCC" = "xyes" +then : + ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags" +fi + +# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first + +if test "x$ax_pthread_clang" = "xyes" +then : + ax_pthread_flags="-pthread,-lpthread -pthread" +fi + + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $host_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" + ;; + + aix*) + ax_pthread_check_macro="_THREAD_SAFE" + ;; + + *) + ax_pthread_check_macro="--" + ;; +esac +if test "x$ax_pthread_check_macro" = "x--" +then : + ax_pthread_check_cond=0 +else $as_nop + ax_pthread_check_cond="!defined($ax_pthread_check_macro)" +fi + + +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do + + case $ax_pthread_try_flag in + none) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 +printf %s "checking whether pthreads work without any flags... " >&6; } + ;; + + *,*) + PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"` + PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"` + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with \"$PTHREAD_CFLAGS\" and \"$PTHREAD_LIBS\"" >&5 +printf %s "checking whether pthreads work with \"$PTHREAD_CFLAGS\" and \"$PTHREAD_LIBS\"... " >&6; } + ;; + + -*) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $ax_pthread_try_flag" >&5 +printf %s "checking whether pthreads work with $ax_pthread_try_flag... " >&6; } + PTHREAD_CFLAGS="$ax_pthread_try_flag" + ;; + + pthread-config) + # Extract the first word of "pthread-config", so it can be a program name with args. +set dummy pthread-config; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ax_pthread_config+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ax_pthread_config"; then + ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ax_pthread_config="yes" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no" +fi +fi +ax_pthread_config=$ac_cv_prog_ax_pthread_config +if test -n "$ax_pthread_config"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5 +printf "%s\n" "$ax_pthread_config" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + if test "x$ax_pthread_config" = "xno" +then : + continue +fi + PTHREAD_CFLAGS="`pthread-config --cflags`" + PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" + ;; + + *) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$ax_pthread_try_flag" >&5 +printf %s "checking for the pthreads library -l$ax_pthread_try_flag... " >&6; } + PTHREAD_LIBS="-l$ax_pthread_try_flag" + ;; + esac + + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void *some_global = NULL; + static void routine(void *a) + { + /* To avoid any unused-parameter or + unused-but-set-parameter warning. */ + some_global = a; + } + static void *start_routine(void *a) { return a; } +int +main (void) +{ +pthread_t th; pthread_attr_t attr; + pthread_create(&th, 0, start_routine, 0); + pthread_join(th, 0); + pthread_attr_init(&attr); + pthread_cleanup_push(routine, 0); + pthread_cleanup_pop(0) /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ax_pthread_ok=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 +printf "%s\n" "$ax_pthread_ok" >&6; } + if test "x$ax_pthread_ok" = "xyes" +then : + break +fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread" >&5 +printf %s "checking whether Clang needs flag to prevent \"argument unused\" warning when linking with -pthread... " >&6; } +if test ${ax_cv_PTHREAD_CLANG_NO_WARN_FLAG+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`printf "%s\n" "$ac_link" | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + if test "x$ax_pthread_try" = "xunknown" +then : + break +fi + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_link="$ax_pthread_2step_ac_link" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + break +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + if test "x$ax_pthread_try" = "x" +then : + ax_pthread_try=no +fi + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&5 +printf "%s\n" "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" >&6; } + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + + + +# Various other checks: +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + + # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 +printf %s "checking for joinable pthread attribute... " >&6; } +if test ${ax_cv_PTHREAD_JOINABLE_ATTR+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +int attr = $ax_pthread_attr; return attr /* ; */ + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + done + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_JOINABLE_ATTR" >&5 +printf "%s\n" "$ax_cv_PTHREAD_JOINABLE_ATTR" >&6; } + if test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes" +then : + +printf "%s\n" "#define PTHREAD_CREATE_JOINABLE $ax_cv_PTHREAD_JOINABLE_ATTR" >>confdefs.h + + ax_pthread_joinable_attr_defined=yes + +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether more special flags are required for pthreads" >&5 +printf %s "checking whether more special flags are required for pthreads... " >&6; } +if test ${ax_cv_PTHREAD_SPECIAL_FLAGS+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $host_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_SPECIAL_FLAGS" >&5 +printf "%s\n" "$ax_cv_PTHREAD_SPECIAL_FLAGS" >&6; } + if test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes" +then : + PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 +printf %s "checking for PTHREAD_PRIO_INHERIT... " >&6; } +if test ${ax_cv_PTHREAD_PRIO_INHERIT+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +int i = PTHREAD_PRIO_INHERIT; + return i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ax_cv_PTHREAD_PRIO_INHERIT=yes +else $as_nop + ax_cv_PTHREAD_PRIO_INHERIT=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 +printf "%s\n" "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } + if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes" +then : + +printf "%s\n" "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h + + ax_pthread_prio_inherit_defined=yes + +fi + + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" + + # More AIX lossage: compile with *_r variant + if test "x$GCC" != "xyes"; then + case $host_os in + aix*) + case "x/$CC" in #( + x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) : + #handle absolute path differently from PATH based program lookup + case "x$CC" in #( + x/*) : + + if as_fn_executable_p ${CC}_r +then : + PTHREAD_CC="${CC}_r" +fi + if test "x${CXX}" != "x" +then : + if as_fn_executable_p ${CXX}_r +then : + PTHREAD_CXX="${CXX}_r" +fi +fi + ;; #( + *) : + + for ac_prog in ${CC}_r +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_PTHREAD_CC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$PTHREAD_CC"; then + ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_PTHREAD_CC="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PTHREAD_CC=$ac_cv_prog_PTHREAD_CC +if test -n "$PTHREAD_CC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 +printf "%s\n" "$PTHREAD_CC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$PTHREAD_CC" && break +done +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" + + if test "x${CXX}" != "x" +then : + for ac_prog in ${CXX}_r +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_PTHREAD_CXX+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$PTHREAD_CXX"; then + ac_cv_prog_PTHREAD_CXX="$PTHREAD_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_PTHREAD_CXX="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PTHREAD_CXX=$ac_cv_prog_PTHREAD_CXX +if test -n "$PTHREAD_CXX"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CXX" >&5 +printf "%s\n" "$PTHREAD_CXX" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$PTHREAD_CXX" && break +done +test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX" + +fi + + ;; +esac + ;; #( + *) : + ;; +esac + ;; + esac + fi +fi + +test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" +test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX" + + + + + + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test "x$ax_pthread_ok" = "xyes"; then + +printf "%s\n" "#define HAVE_PTHREAD 1" >>confdefs.h + + : +else + ax_pthread_ok=no + as_fn_error $? "cannot determine options for enabling thread support; try --disable-thread-support" "$LINENO" 5 +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: PTHREAD_CC = $PTHREAD_CC" >&5 +printf "%s\n" "$as_me: PTHREAD_CC = $PTHREAD_CC" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: PTHREAD_CFLAGS = $PTHREAD_CFLAGS" >&5 +printf "%s\n" "$as_me: PTHREAD_CFLAGS = $PTHREAD_CFLAGS" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: PTHREAD_LIBS = $PTHREAD_LIBS" >&5 +printf "%s\n" "$as_me: PTHREAD_LIBS = $PTHREAD_LIBS" >&6;} + # AIX and Tru64 don't support weak references, and don't have + # stub versions of the pthread code in libc. + case "${host_os}" in + aix* | osf*) + # On these platforms, we'll always pull in the thread support. + LIBS="$LIBS $PTHREAD_LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + # We don't need to sometimes add the flags we've just folded in... + PTHREAD_LIBS= + PTHREAD_CFLAGS= + ;; + hpux*) + # These are the flags that "gcc -pthread" adds. But we don't + # want "-pthread" because that has link-time effects, and we + # don't exclude CFLAGS when linking. *sigh* + PTHREAD_CFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_C_SOURCE=199506L" + ;; + solaris2.[1-9]) + # On Solaris 10 with gcc 3.4.3, the autoconf archive macro doesn't + # get the right result. XXX What about Solaris 9 and earlier? + if test "$GCC" = yes ; then + PTHREAD_CFLAGS="-D_REENTRANT -pthreads" + fi + ;; + solaris*) + # On Solaris 10 with gcc 3.4.3, the autoconf archive macro doesn't + # get the right result. + if test "$GCC" = yes ; then + PTHREAD_CFLAGS="-D_REENTRANT -pthreads" + fi + # On Solaris 10, the thread support is always available in libc. + +printf "%s\n" "#define NO_WEAK_PTHREADS 1" >>confdefs.h + + ;; + esac + THREAD_SUPPORT=1 +else + PTHREAD_CC="$CC" + PTHREAD_CFLAGS="" + PTHREAD_LIBS="" + THREAD_SUPPORT=0 +fi + +ac_fn_c_check_func "$LINENO" "pthread_once" "ac_cv_func_pthread_once" +if test "x$ac_cv_func_pthread_once" = xyes +then : + printf "%s\n" "#define HAVE_PTHREAD_ONCE 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "pthread_rwlock_init" "ac_cv_func_pthread_rwlock_init" +if test "x$ac_cv_func_pthread_rwlock_init" = xyes +then : + printf "%s\n" "#define HAVE_PTHREAD_RWLOCK_INIT 1" >>confdefs.h + +fi + +old_CC="$CC" +test "$PTHREAD_CC" != "" && test "$ac_cv_c_compiler_gnu" = no && CC=$PTHREAD_CC +old_CFLAGS="$CFLAGS" +# On Solaris, -pthreads is added to CFLAGS, no extra explicit libraries. +CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + +old_LIBS="$LIBS" +LIBS="$PTHREAD_LIBS $LIBS" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: rechecking with PTHREAD_... options" >&5 +printf "%s\n" "$as_me: rechecking with PTHREAD_... options" >&6;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_rwlock_init in -lc" >&5 +printf %s "checking for pthread_rwlock_init in -lc... " >&6; } +if test ${ac_cv_lib_c_pthread_rwlock_init+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char pthread_rwlock_init (); +int +main (void) +{ +return pthread_rwlock_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_c_pthread_rwlock_init=yes +else $as_nop + ac_cv_lib_c_pthread_rwlock_init=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_rwlock_init" >&5 +printf "%s\n" "$ac_cv_lib_c_pthread_rwlock_init" >&6; } +if test "x$ac_cv_lib_c_pthread_rwlock_init" = xyes +then : + +printf "%s\n" "#define HAVE_PTHREAD_RWLOCK_INIT_IN_THREAD_LIB 1" >>confdefs.h + +fi + +LIBS="$old_LIBS" +CC="$old_CC" +CFLAGS="$old_CFLAGS" + + +old_LIBS="$LIBS" +DL_LIB= +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 +printf %s "checking for library containing dlopen... " >&6; } +if test ${ac_cv_search_dlopen+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main (void) +{ +return dlopen (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dl +do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO" +then : + ac_cv_search_dlopen=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext + if test ${ac_cv_search_dlopen+y} +then : + break +fi +done +if test ${ac_cv_search_dlopen+y} +then : + +else $as_nop + ac_cv_search_dlopen=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 +printf "%s\n" "$ac_cv_search_dlopen" >&6; } +ac_res=$ac_cv_search_dlopen +if test "$ac_res" != no +then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +if test "$ac_cv_search_dlopen" != "none required"; then + DL_LIB=$ac_cv_search_dlopen +fi +LIBS="$old_LIBS" + +printf "%s\n" "#define USE_DLOPEN 1" >>confdefs.h + +fi + + + + +KRB5_VERSION=1.21.3 + + + + + + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PKG_CONFIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +printf "%s\n" "$PKG_CONFIG" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_ac_pt_PKG_CONFIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + PKG_CONFIG="" + fi +fi + +ac_header= ac_cache= +for ac_item in $ac_header_c_list +do + if test $ac_cache; then + ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" + if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then + printf "%s\n" "#define $ac_item 1" >> confdefs.h + fi + ac_header= ac_cache= + elif test $ac_header; then + ac_cache=$ac_item + else + ac_header=$ac_item + fi +done + + + + + + + + +if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes +then : + +printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" +if test "x$ac_cv_header_stdint_h" = xyes +then : + +else $as_nop + as_fn_error $? "stdint.h is required" "$LINENO" 5 +fi + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether integers are two's complement" >&5 +printf %s "checking whether integers are two's complement... " >&6; } +if test ${krb5_cv_ints_twos_compl+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main (void) +{ +static int test_array [1 - 2 * !(/* Basic two's complement check */ + ~(-1) == 0 && ~(-1L) == 0L && + /* Check that values with sign bit 1 and value bits 0 are valid */ + -(INT_MIN + 1) == INT_MAX && -(LONG_MIN + 1) == LONG_MAX && + /* Check that unsigned-to-signed conversions preserve bit patterns */ + (int)((unsigned int)INT_MAX + 1) == INT_MIN && + (long)((unsigned long)LONG_MAX + 1) == LONG_MIN)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_ints_twos_compl=yes +else $as_nop + krb5_cv_ints_twos_compl=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_ints_twos_compl" >&5 +printf "%s\n" "$krb5_cv_ints_twos_compl" >&6; } + +if test "$krb5_cv_ints_twos_compl" = "no"; then + as_fn_error $? "integers are not two's complement" "$LINENO" 5 +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether CHAR_BIT is 8" >&5 +printf %s "checking whether CHAR_BIT is 8... " >&6; } +if test ${krb5_cv_char_bit_8+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#if CHAR_BIT != 8 + #error CHAR_BIT != 8 +#endif + +_ACEOF +if ac_fn_c_try_cpp "$LINENO" +then : + krb5_cv_char_bit_8=yes +else $as_nop + krb5_cv_char_bit_8=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_char_bit_8" >&5 +printf "%s\n" "$krb5_cv_char_bit_8" >&6; } + +if test "$krb5_cv_char_bit_8" = "no"; then + as_fn_error $? "CHAR_BIT is not 8" "$LINENO" 5 +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if va_copy is available" >&5 +printf %s "checking if va_copy is available... " >&6; } +if test ${krb5_cv_va_copy+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +void f(va_list ap) { + va_list ap2; + va_copy(ap2, ap); + va_end(ap2); +} +va_list x; +int main() +{ + f(x); + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + krb5_cv_va_copy=yes +else $as_nop + krb5_cv_va_copy=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_va_copy" >&5 +printf "%s\n" "$krb5_cv_va_copy" >&6; } +if test "$krb5_cv_va_copy" = yes; then + +printf "%s\n" "#define HAS_VA_COPY 1" >>confdefs.h + +fi + +# Note that this isn't checking if the copied value *works*, just +# whether the C language constraints permit the copying. If +# va_list is defined as an array type, it can't be assigned. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if va_list objects can be copied by assignment" >&5 +printf %s "checking if va_list objects can be copied by assignment... " >&6; } +if test ${krb5_cv_va_simple_copy+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +void f(va_list va2) { + va_list va1; + va1 = va2; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_va_simple_copy=yes +else $as_nop + krb5_cv_va_simple_copy=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_va_simple_copy" >&5 +printf "%s\n" "$krb5_cv_va_simple_copy" >&6; } +if test "$krb5_cv_va_simple_copy" = yes; then + +printf "%s\n" "#define CAN_COPY_VA_LIST 1" >>confdefs.h + +fi + +# The following lines are so that configure --help gives some global +# configuration options. + + +# Check whether --enable-static was given. +if test ${enable_static+y} +then : + enableval=$enable_static; +else $as_nop + enable_static=no +fi + +# Check whether --enable-shared was given. +if test ${enable_shared+y} +then : + enableval=$enable_shared; +else $as_nop + enable_shared=yes +fi + + +if test "x$enable_static" = "x$enable_shared"; then + as_fn_error $? "--enable-static must be specified with --disable-shared" "$LINENO" 5 +fi + +# Check whether --enable-rpath was given. +if test ${enable_rpath+y} +then : + enableval=$enable_rpath; +else $as_nop + enable_rpath=yes +fi + + +if test "x$enable_rpath" != xyes ; then + # Unset the rpath flag values set by shlib.conf + SHLIB_RPATH_FLAGS= + RPATH_FLAG= + PROG_RPATH_FLAGS= +fi + +if test "$SHLIBEXT" = ".so-nobuild"; then + as_fn_error $? "Shared libraries are not yet supported on this platform." "$LINENO" 5 +fi + +DEPLIBEXT=$SHLIBEXT + +if test "x$enable_static" = xyes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: using static libraries" >&5 +printf "%s\n" "$as_me: using static libraries" >&6;} + LIBLIST='lib$(LIBBASE)$(STLIBEXT)' + LIBLINKS='$(TOPLIBD)/lib$(LIBBASE)$(STLIBEXT)' + PLUGIN='libkrb5_$(LIBBASE)$(STLIBEXT)' + PLUGINLINK='$(TOPLIBD)/libkrb5_$(LIBBASE)$(STLIBEXT)' + PLUGININST=install-static + OBJLISTS=OBJS.ST + LIBINSTLIST=install-static + DEPLIBEXT=$STLIBEXT + +printf "%s\n" "#define STATIC_PLUGINS 1" >>confdefs.h + + + KDB5_PLUGIN_DEPLIBS='$(TOPLIBD)/libkrb5_db2$(DEPLIBEXT)' + KDB5_PLUGIN_LIBS='-lkrb5_db2' + if test "x$OPENLDAP_PLUGIN" = xyes; then + KDB5_PLUGIN_DEBLIBS=$KDB5_PLUGIN_DEPLIBS' $(TOPLIBD)/libkrb5_ldap$(DEPLIBEXT) $(TOPLIBD)/libkdb_ldap$(DEPLIBEXT)' + KDB5_PLUGIN_LIBS=$KDB5_PLUGIN_LIBS' -lkrb5_kldap -lkdb_ldap $(LDAP_LIBS)' + fi + # kadm5srv_mit normally comes before kdb on the link line. Add it + # again after the KDB plugins, since they depend on it for XDR stuff. + KDB5_PLUGIN_DEPLIBS=$KDB5_PLUGIN_DEPLIBS' $(TOPLIBD)/libkadm5srv_mit$(DEPLIBEXT)' + KDB5_PLUGIN_LIBS=$KDB5_PLUGIN_LIBS' -lkadm5srv_mit' + + # avoid duplicate rules generation for AIX and such + SHLIBEXT=.so-nobuild + SHLIBVEXT=.so.v-nobuild + SHLIBSEXT=.so.s-nobuild +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: using shared libraries" >&5 +printf "%s\n" "$as_me: using shared libraries" >&6;} + + # Clear some stuff in case of AIX, etc. + if test "$STLIBEXT" = "$SHLIBEXT" ; then + STLIBEXT=.a-nobuild + fi + case "$SHLIBSEXT" in + .so.s-nobuild) + LIBLIST='lib$(LIBBASE)$(SHLIBEXT)' + LIBLINKS='$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT)' + LIBINSTLIST="install-shared" + ;; + *) + LIBLIST='lib$(LIBBASE)$(SHLIBEXT) lib$(LIBBASE)$(SHLIBSEXT)' + LIBLINKS='$(TOPLIBD)/lib$(LIBBASE)$(SHLIBEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBVEXT) $(TOPLIBD)/lib$(LIBBASE)$(SHLIBSEXT)' + LIBINSTLIST="install-shlib-soname" + ;; + esac + OBJLISTS="OBJS.SH" + PLUGIN='$(LIBBASE)$(DYNOBJEXT)' + PLUGINLINK='../$(PLUGIN)' + PLUGININST=install-plugin + KDB5_PLUGIN_DEPLIBS= + KDB5_PLUGIN_LIBS= +fi +CC_LINK="$CC_LINK_SHARED" +CXX_LINK="$CXX_LINK_SHARED" + +if test -z "$LIBLIST"; then + as_fn_error $? "must enable one of shared or static libraries" "$LINENO" 5 +fi + +# Check whether to build profiled libraries. +# Check whether --enable-profiled was given. +if test ${enable_profiled+y} +then : + enableval=$enable_profiled; if test "$enableval" = yes; then + as_fn_error $? "Sorry, profiled libraries do not work in this release." "$LINENO" 5 +fi +fi + +# Check whether --enable-athena was given. +if test ${enable_athena+y} +then : + enableval=$enable_athena; +fi + + +# Begin autoconf tests for the Makefiles generated out of the top-level +# configure.in... + + + + + + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +printf %s "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +printf "%s\n" "no, using $LN_S" >&6; } +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_RANLIB+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +printf "%s\n" "$RANLIB" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_RANLIB+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +printf "%s\n" "$ac_ct_RANLIB" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + + + # Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +printf %s "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if test ${ac_cv_path_install+y} +then : + printf %s "(cached) " >&6 +else $as_nop + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + # Account for fact that we put trailing slashes in our PATH walk. +case $as_dir in #(( + ./ | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test ${ac_cv_path_install+y}; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +printf "%s\n" "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_AR+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +printf "%s\n" "$AR" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_AR+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="ar" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +printf "%s\n" "$ac_ct_AR" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +else + AR="$ac_cv_prog_AR" +fi + +if test "$AR" = "false"; then + as_fn_error $? "ar not found in PATH" "$LINENO" 5 +fi +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_PERL+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_PERL" && ac_cv_prog_PERL="false" +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +printf "%s\n" "$PERL" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +if test "$ac_cv_prog_PERL" = "false"; then + as_fn_error $? "Perl is now required for Kerberos builds." "$LINENO" 5 +fi + + + + + + + + + + + + + + + + + + + + + + + + + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for working regcomp" >&5 +printf %s "checking for working regcomp... " >&6; } +if test ${ac_cv_func_regcomp+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test "$cross_compiling" = yes +then : + as_fn_error $? "Cannot test regcomp when cross compiling" "$LINENO" 5 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + regex_t x; regmatch_t m; +int +main (void) +{ +return regcomp(&x,"pat.*",0) || regexec(&x,"pattern",1,&m,0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO" +then : + ac_cv_func_regcomp=yes +else $as_nop + ac_cv_func_regcomp=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_regcomp" >&5 +printf "%s\n" "$ac_cv_func_regcomp" >&6; } +test $ac_cv_func_regcomp = yes && +printf "%s\n" "#define HAVE_REGCOMP 1" >>confdefs.h + +if test $ac_cv_func_regcomp = no; then + save_LIBS="$LIBS" + LIBS=-lgen + ac_fn_c_check_func "$LINENO" "compile" "ac_cv_func_compile" +if test "x$ac_cv_func_compile" = xyes +then : + printf "%s\n" "#define HAVE_COMPILE 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "step" "ac_cv_func_step" +if test "x$ac_cv_func_step" = xyes +then : + printf "%s\n" "#define HAVE_STEP 1" >>confdefs.h + +fi + + LIBS="$save_LIBS" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for compile in -lgen" >&5 +printf %s "checking for compile in -lgen... " >&6; } +if test ${ac_cv_lib_gen_compile+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgen $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char compile (); +int +main (void) +{ +return compile (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_gen_compile=yes +else $as_nop + ac_cv_lib_gen_compile=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gen_compile" >&5 +printf "%s\n" "$ac_cv_lib_gen_compile" >&6; } +if test "x$ac_cv_lib_gen_compile" = xyes +then : + GEN_LIB=-lgen +else $as_nop + GEN_LIB= +fi + + +fi + + + + + + +# for kprop +ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" +if test "x$ac_cv_type_mode_t" = xyes +then : + +else $as_nop + +printf "%s\n" "#define mode_t int" >>confdefs.h + +fi + + + + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if daemon needs a prototype provided" >&5 +printf %s "checking if daemon needs a prototype provided... " >&6; } +if test ${krb5_cv_func_daemon_noproto+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef HAVE_UNISTD_H +#include +#endif +int +main (void) +{ +#undef daemon + struct k5foo {int foo; } xx; + extern int daemon (struct k5foo*); + daemon(&xx); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_func_daemon_noproto=yes +else $as_nop + krb5_cv_func_daemon_noproto=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_func_daemon_noproto" >&5 +printf "%s\n" "$krb5_cv_func_daemon_noproto" >&6; } +if test $krb5_cv_func_daemon_noproto = yes; then + +printf "%s\n" "#define NEED_DAEMON_PROTO 1" >>confdefs.h + +fi + + + +sock_set=no +for sock_arg1 in "struct sockaddr *" "void *" +do + for sock_arg2 in "size_t *" "int *" "socklen_t *" + do + if test $sock_set = no; then + +krb5_lib_var=`echo "$sock_arg1 $sock_arg2" | sed 'y% ./+-*%___p_p%'` +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if getsockname() takes arguments $sock_arg1 and $sock_arg2" >&5 +printf %s "checking if getsockname() takes arguments $sock_arg1 and $sock_arg2... " >&6; } +if eval test \${krb5_cv_getsockname_proto_$krb5_lib_var+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + extern int getsockname(int, $sock_arg1, $sock_arg2); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval "krb5_cv_getsockname_proto_$krb5_lib_var=yes" +else $as_nop + eval "krb5_cv_getsockname_proto_$krb5_lib_var=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +if eval "test \"`echo '$krb5_cv_getsockname_proto_'$krb5_lib_var`\" = yes"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + sock_set=yes; res1="$sock_arg1"; res2="$sock_arg2" +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + fi + done +done +if test "$sock_set" = no; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: assuming struct sockaddr and socklen_t for getsockname args" >&5 +printf "%s\n" "$as_me: assuming struct sockaddr and socklen_t for getsockname args" >&6;} + res1="struct sockaddr *" + res2="socklen_t *" +fi +res1=`echo "$res1" | tr -d '*' | sed -e 's/ *$//'` +res2=`echo "$res2" | tr -d '*' | sed -e 's/ *$//'` + +printf "%s\n" "#define GETSOCKNAME_ARG3_TYPE $res2" >>confdefs.h + + + + +printf "%s\n" "#define GETPEERNAME_ARG3_TYPE GETSOCKNAME_ARG3_TYPE" >>confdefs.h + + +LIBUTIL= +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lutil" >&5 +printf %s "checking for main in -lutil... " >&6; } +if test ${ac_cv_lib_util_main+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lutil $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main (void) +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_util_main=yes +else $as_nop + ac_cv_lib_util_main=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_util_main" >&5 +printf "%s\n" "$ac_cv_lib_util_main" >&6; } +if test "x$ac_cv_lib_util_main" = xyes +then : + +printf "%s\n" "#define HAVE_LIBUTIL 1" >>confdefs.h + +LIBUTIL=-lutil + +fi + + + +# Determine if NLS is desired and supported. +po= +# Check whether --enable-nls was given. +if test ${enable_nls+y} +then : + enableval=$enable_nls; +else $as_nop + enable_nls=check +fi + +if test "$enable_nls" != no; then + ac_fn_c_check_header_compile "$LINENO" "libintl.h" "ac_cv_header_libintl_h" "$ac_includes_default" +if test "x$ac_cv_header_libintl_h" = xyes +then : + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing dgettext" >&5 +printf %s "checking for library containing dgettext... " >&6; } +if test ${ac_cv_search_dgettext+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char dgettext (); +int +main (void) +{ +return dgettext (); + ; + return 0; +} +_ACEOF +for ac_lib in '' intl +do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO" +then : + ac_cv_search_dgettext=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext + if test ${ac_cv_search_dgettext+y} +then : + break +fi +done +if test ${ac_cv_search_dgettext+y} +then : + +else $as_nop + ac_cv_search_dgettext=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dgettext" >&5 +printf "%s\n" "$ac_cv_search_dgettext" >&6; } +ac_res=$ac_cv_search_dgettext +if test "$ac_res" != no +then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + + +printf "%s\n" "#define ENABLE_NLS 1" >>confdefs.h + + nls_enabled=yes +fi + +fi + + + # Extract the first word of "msgfmt", so it can be a program name with args. +set dummy msgfmt; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_MSGFMT+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$MSGFMT"; then + ac_cv_prog_MSGFMT="$MSGFMT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_MSGFMT="msgfmt" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MSGFMT=$ac_cv_prog_MSGFMT +if test -n "$MSGFMT"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 +printf "%s\n" "$MSGFMT" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + if test x"$MSGFMT" != x; then + ac_config_files="$ac_config_files po/Makefile:$srcdir/./config/pre.in:po/Makefile.in:po/deps:$srcdir/./config/post.in" + + + + po=po + fi + + # Error out if --enable-nls was explicitly requested but can't be enabled. + if test "$enable_nls" = yes; then + if test "$nls_enabled" != yes -o "x$po" = x; then + as_fn_error $? "NLS support requested but cannot be built" "$LINENO" 5 + fi + fi +fi + + +# for kdc +ac_fn_c_check_header_compile "$LINENO" "sys/sockio.h" "ac_cv_header_sys_sockio_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_sockio_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_SOCKIO_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "$ac_includes_default" +if test "x$ac_cv_header_ifaddrs_h" = xyes +then : + printf "%s\n" "#define HAVE_IFADDRS_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" +if test "x$ac_cv_header_unistd_h" = xyes +then : + printf "%s\n" "#define HAVE_UNISTD_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "fnmatch.h" "ac_cv_header_fnmatch_h" "$ac_includes_default" +if test "x$ac_cv_header_fnmatch_h" = xyes +then : + printf "%s\n" "#define HAVE_FNMATCH_H 1" >>confdefs.h + +fi + +ac_fn_c_check_func "$LINENO" "vsprintf" "ac_cv_func_vsprintf" +if test "x$ac_cv_func_vsprintf" = xyes +then : + printf "%s\n" "#define HAVE_VSPRINTF 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "vasprintf" "ac_cv_func_vasprintf" +if test "x$ac_cv_func_vasprintf" = xyes +then : + printf "%s\n" "#define HAVE_VASPRINTF 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf" +if test "x$ac_cv_func_vsnprintf" = xyes +then : + printf "%s\n" "#define HAVE_VSNPRINTF 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy" +if test "x$ac_cv_func_strlcpy" = xyes +then : + printf "%s\n" "#define HAVE_STRLCPY 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "fnmatch" "ac_cv_func_fnmatch" +if test "x$ac_cv_func_fnmatch" = xyes +then : + printf "%s\n" "#define HAVE_FNMATCH 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "secure_getenv" "ac_cv_func_secure_getenv" +if test "x$ac_cv_func_secure_getenv" = xyes +then : + printf "%s\n" "#define HAVE_SECURE_GETENV 1" >>confdefs.h + +fi + + +EXTRA_SUPPORT_SYMS= +ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy" +if test "x$ac_cv_func_strlcpy" = xyes +then : + STRLCPY_ST_OBJ= +STRLCPY_OBJ= +else $as_nop + STRLCPY_ST_OBJ=strlcpy.o +STRLCPY_OBJ='$(OUTPRE)strlcpy.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_strlcpy krb5int_strlcat" +fi + + + + +ac_fn_c_check_func "$LINENO" "getopt" "ac_cv_func_getopt" +if test "x$ac_cv_func_getopt" = xyes +then : + GETOPT_ST_OBJ= +GETOPT_OBJ= + +printf "%s\n" "#define HAVE_GETOPT 1" >>confdefs.h + +else $as_nop + GETOPT_ST_OBJ='getopt.o' +GETOPT_OBJ='$(OUTPRE)getopt.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS k5_optind k5_optarg k5_opterr k5_optopt k5_getopt" +fi + + + + +ac_fn_c_check_func "$LINENO" "getopt_long" "ac_cv_func_getopt_long" +if test "x$ac_cv_func_getopt_long" = xyes +then : + GETOPT_LONG_ST_OBJ= +GETOPT_LONG_OBJ= + +printf "%s\n" "#define HAVE_GETOPT_LONG 1" >>confdefs.h + +else $as_nop + GETOPT_LONG_ST_OBJ='getopt_long.o' +GETOPT_LONG_OBJ='$(OUTPRE)getopt_long.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS k5_getopt_long" +fi + + + + +ac_fn_c_check_func "$LINENO" "fnmatch" "ac_cv_func_fnmatch" +if test "x$ac_cv_func_fnmatch" = xyes +then : + FNMATCH_ST_OBJ= +FNMATCH_OBJ= +else $as_nop + FNMATCH_ST_OBJ=fnmatch.o +FNMATCH_OBJ='$(OUTPRE)fnmatch.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS k5_fnmatch" +fi + + + + +ac_fn_c_check_func "$LINENO" "vasprintf" "ac_cv_func_vasprintf" +if test "x$ac_cv_func_vasprintf" = xyes +then : + PRINTF_ST_OBJ= +PRINTF_OBJ= +else $as_nop + PRINTF_ST_OBJ=printf.o +PRINTF_OBJ='$(OUTPRE)printf.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_asprintf krb5int_vasprintf" +fi + + + + +if test "x$ac_cv_func_vasprintf" = xyes; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if vasprintf needs a prototype provided" >&5 +printf %s "checking if vasprintf needs a prototype provided... " >&6; } +if test ${krb5_cv_func_vasprintf_noproto+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include + +int +main (void) +{ +#undef vasprintf + struct k5foo {int foo; } xx; + extern int vasprintf (struct k5foo*); + vasprintf(&xx); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_func_vasprintf_noproto=yes +else $as_nop + krb5_cv_func_vasprintf_noproto=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_func_vasprintf_noproto" >&5 +printf "%s\n" "$krb5_cv_func_vasprintf_noproto" >&6; } +if test $krb5_cv_func_vasprintf_noproto = yes; then + +printf "%s\n" "#define NEED_VASPRINTF_PROTO 1" >>confdefs.h + +fi +fi + + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if swab needs a prototype provided" >&5 +printf %s "checking if swab needs a prototype provided... " >&6; } +if test ${krb5_cv_func_swab_noproto+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#ifdef HAVE_UNISTD_H +#include +#endif +/* Solaris 8 declares swab in stdlib.h. */ +#include + +int +main (void) +{ +#undef swab + struct k5foo {int foo; } xx; + extern int swab (struct k5foo*); + swab(&xx); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_func_swab_noproto=yes +else $as_nop + krb5_cv_func_swab_noproto=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_func_swab_noproto" >&5 +printf "%s\n" "$krb5_cv_func_swab_noproto" >&6; } +if test $krb5_cv_func_swab_noproto = yes; then + +printf "%s\n" "#define NEED_SWAB_PROTO 1" >>confdefs.h + +fi + + + +ac_fn_c_check_func "$LINENO" "secure_getenv" "ac_cv_func_secure_getenv" +if test "x$ac_cv_func_secure_getenv" = xyes +then : + SECURE_GETENV_ST_OBJ= +SECURE_GETENV_OBJ= +SECURE_GETENV_INIT= +else $as_nop + SECURE_GETENV_ST_OBJ=secure_getenv.o +SECURE_GETENV_OBJ='$(OUTPRE)secure_getenv.$(OBJEXT)' +SECURE_GETENV_INIT=k5_secure_getenv_init +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS k5_secure_getenv" +fi + + + + + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_AWK+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +printf "%s\n" "$AWK" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$AWK" && break +done + + ac_fn_c_check_member "$LINENO" "struct sockaddr" "sa_len" "ac_cv_member_struct_sockaddr_sa_len" "#include +#include +" +if test "x$ac_cv_member_struct_sockaddr_sa_len" = xyes +then : + +printf "%s\n" "#define HAVE_SA_LEN 1" >>confdefs.h + + +fi + + +ac_fn_c_check_header_compile "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_types_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_TYPES_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_socket_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_SOCKET_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "$ac_includes_default" +if test "x$ac_cv_header_netinet_in_h" = xyes +then : + printf "%s\n" "#define HAVE_NETINET_IN_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "netdb.h" "ac_cv_header_netdb_h" "$ac_includes_default" +if test "x$ac_cv_header_netdb_h" = xyes +then : + printf "%s\n" "#define HAVE_NETDB_H 1" >>confdefs.h + +fi + +ac_fn_c_check_func "$LINENO" "inet_ntop" "ac_cv_func_inet_ntop" +if test "x$ac_cv_func_inet_ntop" = xyes +then : + printf "%s\n" "#define HAVE_INET_NTOP 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "inet_pton" "ac_cv_func_inet_pton" +if test "x$ac_cv_func_inet_pton" = xyes +then : + printf "%s\n" "#define HAVE_INET_PTON 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "getnameinfo" "ac_cv_func_getnameinfo" +if test "x$ac_cv_func_getnameinfo" = xyes +then : + printf "%s\n" "#define HAVE_GETNAMEINFO 1" >>confdefs.h + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo" >&5 +printf %s "checking for getaddrinfo... " >&6; } +if test ${ac_cv_func_getaddrinfo+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef HAVE_NETDB_H + #include + #endif + +int +main (void) +{ +struct addrinfo *ai; + getaddrinfo("kerberos.mit.edu", "echo", 0, &ai); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_func_getaddrinfo=yes +else $as_nop + ac_cv_func_getaddrinfo=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getaddrinfo" >&5 +printf "%s\n" "$ac_cv_func_getaddrinfo" >&6; } +if test $ac_cv_func_getaddrinfo = yes; then + +printf "%s\n" "#define HAVE_GETADDRINFO 1" >>confdefs.h + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for IPv6 compile-time support without -DINET6" >&5 +printf %s "checking for IPv6 compile-time support without -DINET6... " >&6; } +if test ${krb5_cv_inet6+y} +then : + printf %s "(cached) " >&6 +else $as_nop + +if test "$ac_cv_func_inet_ntop" != "yes" ; then + krb5_cv_inet6=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef HAVE_SYS_TYPES_H + #include + #endif + #include + #include + #include + +int +main (void) +{ +struct sockaddr_in6 in; + AF_INET6; + IN6_IS_ADDR_LINKLOCAL(&in.sin6_addr); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_inet6=yes +else $as_nop + krb5_cv_inet6=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_inet6" >&5 +printf "%s\n" "$krb5_cv_inet6" >&6; } +if test "$krb5_cv_inet6" = no && test "$ac_cv_func_inet_ntop" = yes; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for IPv6 compile-time support with -DINET6" >&5 +printf %s "checking for IPv6 compile-time support with -DINET6... " >&6; } +if test ${krb5_cv_inet6_with_dinet6+y} +then : + printf %s "(cached) " >&6 +else $as_nop + +old_CC="$CC" +CC="$CC -DINET6" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef HAVE_SYS_TYPES_H + #include + #endif + #include + #include + #include + +int +main (void) +{ +struct sockaddr_in6 in; + AF_INET6; + IN6_IS_ADDR_LINKLOCAL (&in.sin6_addr); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_inet6_with_dinet6=yes +else $as_nop + krb5_cv_inet6_with_dinet6=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +CC="$old_CC" +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_inet6_with_dinet6" >&5 +printf "%s\n" "$krb5_cv_inet6_with_dinet6" >&6; } +fi +if test $krb5_cv_inet6 = yes || test "$krb5_cv_inet6_with_dinet6" = yes; then + if test "$krb5_cv_inet6_with_dinet6" = yes; then + +printf "%s\n" "#define INET6 1" >>confdefs.h + + fi +fi + + ac_fn_c_check_member "$LINENO" "struct sockaddr" "sa_len" "ac_cv_member_struct_sockaddr_sa_len" "#include +#include +" +if test "x$ac_cv_member_struct_sockaddr_sa_len" = xyes +then : + +printf "%s\n" "#define HAVE_SA_LEN 1" >>confdefs.h + + +fi + + +ac_fn_c_check_func "$LINENO" "sigprocmask" "ac_cv_func_sigprocmask" +if test "x$ac_cv_func_sigprocmask" = xyes +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sigset_t and POSIX_SIGNALS" >&5 +printf %s "checking for sigset_t and POSIX_SIGNALS... " >&6; } +if test ${krb5_cv_type_sigset_t+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main (void) +{ +sigset_t x + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_type_sigset_t=yes +else $as_nop + krb5_cv_type_sigset_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_type_sigset_t" >&5 +printf "%s\n" "$krb5_cv_type_sigset_t" >&6; } +if test $krb5_cv_type_sigset_t = yes; then + +printf "%s\n" "#define POSIX_SIGNALS 1" >>confdefs.h + +fi + +fi + + +# --with-vague-errors disables useful error messages. + + +# Check whether --with-vague-errors was given. +if test ${with_vague_errors+y} +then : + withval=$with_vague_errors; +else $as_nop + withval=no +fi + +if test "$withval" = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Supplying vague error messages to KDC clients" >&5 +printf "%s\n" "$as_me: Supplying vague error messages to KDC clients" >&6;} + +printf "%s\n" "#define KRBCONF_VAGUE_ERRORS 1" >>confdefs.h + +fi + +# Check which (if any) audit plugin to build +audit_plugin="" +# Check whether --enable-audit-plugin was given. +if test ${enable_audit_plugin+y} +then : + enableval=$enable_audit_plugin; +else $as_nop + enableval=no +fi + +if test "$enableval" != no; then + case "$enableval" in + simple) + # if audit_log_user_message is found, we assume + # that audit_open and audit_close are also defined. + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for audit_log_user_message in -laudit" >&5 +printf %s "checking for audit_log_user_message in -laudit... " >&6; } +if test ${ac_cv_lib_audit_audit_log_user_message+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-laudit $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char audit_log_user_message (); +int +main (void) +{ +return audit_log_user_message (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_audit_audit_log_user_message=yes +else $as_nop + ac_cv_lib_audit_audit_log_user_message=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_audit_audit_log_user_message" >&5 +printf "%s\n" "$ac_cv_lib_audit_audit_log_user_message" >&6; } +if test "x$ac_cv_lib_audit_audit_log_user_message" = xyes +then : + AUDIT_IMPL_LIBS=-laudit + ac_config_files="$ac_config_files plugins/audit/simple/Makefile:$srcdir/./config/pre.in:plugins/audit/simple/Makefile.in:plugins/audit/simple/deps:$srcdir/./config/post.in" + + + + audit_plugin=plugins/audit/simple +else $as_nop + as_fn_error $? "libaudit not found or undefined symbol audit_log_user_message" "$LINENO" 5 +fi + + ;; + *) + as_fn_error $? "Unknown audit plugin implementation $enableval." "$LINENO" 5 + ;; + esac +fi + + + +# WITH_CRYPTO_IMPL + +CRYPTO_IMPL=builtin + +# Check whether --with-crypto-impl was given. +if test ${with_crypto_impl+y} +then : + withval=$with_crypto_impl; CRYPTO_IMPL=$withval + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: k5crypto will use '$withval'" >&5 +printf "%s\n" "$as_me: k5crypto will use '$withval'" >&6;} +fi + + +CRYPTO_BUILTIN_TESTS=no +case $CRYPTO_IMPL in +builtin) + CRYPTO_BUILTIN_TESTS=yes + ;; +openssl) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PKCS7_get_signer_info in -lcrypto" >&5 +printf %s "checking for PKCS7_get_signer_info in -lcrypto... " >&6; } +if test ${ac_cv_lib_crypto_PKCS7_get_signer_info+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char PKCS7_get_signer_info (); +int +main (void) +{ +return PKCS7_get_signer_info (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_crypto_PKCS7_get_signer_info=yes +else $as_nop + ac_cv_lib_crypto_PKCS7_get_signer_info=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_PKCS7_get_signer_info" >&5 +printf "%s\n" "$ac_cv_lib_crypto_PKCS7_get_signer_info" >&6; } +if test "x$ac_cv_lib_crypto_PKCS7_get_signer_info" = xyes +then : + printf "%s\n" "#define HAVE_LIBCRYPTO 1" >>confdefs.h + + LIBS="-lcrypto $LIBS" + +fi + + +printf "%s\n" "#define CRYPTO_OPENSSL 1" >>confdefs.h + + ;; +*) + as_fn_error $? "Unknown crypto implementation $withval" "$LINENO" 5 + ;; +esac + + + + +# WITH_TLS_IMPL + + +# Check whether --with-tls-impl was given. +if test ${with_tls_impl+y} +then : + withval=$with_tls_impl; TLS_IMPL=$withval +else $as_nop + TLS_IMPL=auto +fi + +case "$TLS_IMPL" in +openssl|auto) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SSL_CTX_new in -lssl" >&5 +printf %s "checking for SSL_CTX_new in -lssl... " >&6; } +if test ${ac_cv_lib_ssl_SSL_CTX_new+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lssl -lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char SSL_CTX_new (); +int +main (void) +{ +return SSL_CTX_new (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_ssl_SSL_CTX_new=yes +else $as_nop + ac_cv_lib_ssl_SSL_CTX_new=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_CTX_new" >&5 +printf "%s\n" "$ac_cv_lib_ssl_SSL_CTX_new" >&6; } +if test "x$ac_cv_lib_ssl_SSL_CTX_new" = xyes +then : + have_lib_ssl=true +else $as_nop + have_lib_ssl=false +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OpenSSL" >&5 +printf %s "checking for OpenSSL... " >&6; } + if test x$have_lib_ssl = xtrue ; then + +printf "%s\n" "#define TLS_IMPL_OPENSSL 1" >>confdefs.h + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + TLS_IMPL_LIBS="-lssl -lcrypto" + TLS_IMPL=openssl + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: TLS module will use OpenSSL" >&5 +printf "%s\n" "$as_me: TLS module will use OpenSSL" >&6;} + else + if test "$TLS_IMPL" = openssl ; then + as_fn_error $? "OpenSSL not found!" "$LINENO" 5 + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: OpenSSL not found!" >&5 +printf "%s\n" "$as_me: WARNING: OpenSSL not found!" >&2;} + fi + TLS_IMPL=no + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: building without TLS support" >&5 +printf "%s\n" "$as_me: building without TLS support" >&6;} + fi + ;; +no) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: building without TLS support" >&5 +printf "%s\n" "$as_me: building without TLS support" >&6;} + ;; +*) + as_fn_error $? "Unsupported TLS implementation $withval" "$LINENO" 5 + ;; +esac + +if test "$TLS_IMPL" = no; then + +printf "%s\n" "#define TLS_IMPL_NONE 1" >>confdefs.h + +fi + + + + + + +# Check whether --with-keyutils was given. +if test ${with_keyutils+y} +then : + withval=$with_keyutils; +else $as_nop + with_keyutils=check +fi + +if test "$with_keyutils" != no; then + have_keyutils=false + for ac_header in keyutils.h +do : + ac_fn_c_check_header_compile "$LINENO" "keyutils.h" "ac_cv_header_keyutils_h" "$ac_includes_default" +if test "x$ac_cv_header_keyutils_h" = xyes +then : + printf "%s\n" "#define HAVE_KEYUTILS_H 1" >>confdefs.h + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for add_key in -lkeyutils" >&5 +printf %s "checking for add_key in -lkeyutils... " >&6; } +if test ${ac_cv_lib_keyutils_add_key+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lkeyutils $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char add_key (); +int +main (void) +{ +return add_key (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_keyutils_add_key=yes +else $as_nop + ac_cv_lib_keyutils_add_key=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_keyutils_add_key" >&5 +printf "%s\n" "$ac_cv_lib_keyutils_add_key" >&6; } +if test "x$ac_cv_lib_keyutils_add_key" = xyes +then : + have_keyutils=true +fi + +fi + +done + if test "$have_keyutils" = true; then + +printf "%s\n" "#define USE_KEYRING_CCACHE 1" >>confdefs.h + + LIBS="-lkeyutils $LIBS" + # If libkeyutils supports persistent keyrings, use them. + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for keyctl_get_persistent in -lkeyutils" >&5 +printf %s "checking for keyctl_get_persistent in -lkeyutils... " >&6; } +if test ${ac_cv_lib_keyutils_keyctl_get_persistent+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lkeyutils $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char keyctl_get_persistent (); +int +main (void) +{ +return keyctl_get_persistent (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_keyutils_keyctl_get_persistent=yes +else $as_nop + ac_cv_lib_keyutils_keyctl_get_persistent=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_keyutils_keyctl_get_persistent" >&5 +printf "%s\n" "$ac_cv_lib_keyutils_keyctl_get_persistent" >&6; } +if test "x$ac_cv_lib_keyutils_keyctl_get_persistent" = xyes +then : + +printf "%s\n" "#define HAVE_PERSISTENT_KEYRING 1" >>confdefs.h + + +fi + + elif test "$with_keyutils" = yes; then + as_fn_error $? "libkeyutils not found" "$LINENO" 5 + fi +fi + +# The SPAKE preauth plugin currently supports edwards25519 natively, +# and can support three NIST groups using OpenSSL. +HAVE_SPAKE_OPENSSL=no + +# Check whether --with-spake-openssl was given. +if test ${with_spake_openssl+y} +then : + withval=$with_spake_openssl; +else $as_nop + withval=auto +fi + +if test "$withval" = auto -o "$withval" = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for EC_POINT_new in -lcrypto" >&5 +printf %s "checking for EC_POINT_new in -lcrypto... " >&6; } +if test ${ac_cv_lib_crypto_EC_POINT_new+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char EC_POINT_new (); +int +main (void) +{ +return EC_POINT_new (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_crypto_EC_POINT_new=yes +else $as_nop + ac_cv_lib_crypto_EC_POINT_new=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_EC_POINT_new" >&5 +printf "%s\n" "$ac_cv_lib_crypto_EC_POINT_new" >&6; } +if test "x$ac_cv_lib_crypto_EC_POINT_new" = xyes +then : + have_crypto=true +else $as_nop + have_crypto=false +fi + + if test "$have_crypto" = true; then + +printf "%s\n" "#define SPAKE_OPENSSL 1" >>confdefs.h + + SPAKE_OPENSSL_LIBS=-lcrypto + HAVE_SPAKE_OPENSSL=yes + elif test "$withval" = yes; then + as_fn_error $? "OpenSSL libcrypto not found" "$LINENO" 5 + fi +fi + + + +# Check whether --enable-aesni was given. +if test ${enable_aesni+y} +then : + enableval=$enable_aesni; +else $as_nop + enable_aesni=check +fi + +if test "$CRYPTO_IMPL" = builtin -a "x$enable_aesni" != xno; then + case "$host" in + i686-*) + aesni_obj=iaesx86.o + aesni_machine=x86 + ;; + x86_64-*) + aesni_obj=iaesx64.o + aesni_machine=amd64 + ;; + esac + case "$host" in + *-*-linux* | *-*-gnu* | *-*-*bsd* | *-*-solaris*) + # All Unix-like platforms need -D__linux__ for iaesx64.s to + # use the System V x86-64 calling convention. + aesni_flags="-D__linux__ -f elf -m $aesni_machine" + ;; + esac + if test "x$aesni_obj" != x && test "x$aesni_flags" != x; then + # Extract the first word of "yasm", so it can be a program name with args. +set dummy yasm; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_YASM+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$YASM"; then + ac_cv_prog_YASM="$YASM" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_YASM="yasm" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +YASM=$ac_cv_prog_YASM +if test -n "$YASM"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $YASM" >&5 +printf "%s\n" "$YASM" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + ac_fn_c_check_header_compile "$LINENO" "cpuid.h" "ac_cv_header_cpuid_h" "$ac_includes_default" +if test "x$ac_cv_header_cpuid_h" = xyes +then : + printf "%s\n" "#define HAVE_CPUID_H 1" >>confdefs.h + +fi + + if test x"$YASM" != x -a "x$ac_cv_header_cpuid_h" = xyes; then + AESNI_OBJ=$aesni_obj + AESNI_FLAGS=$aesni_flags + +printf "%s\n" "#define AESNI 1" >>confdefs.h + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Building with AES-NI support" >&5 +printf "%s\n" "$as_me: Building with AES-NI support" >&6;} + fi + fi + if test "x$enable_aesni" = xyes -a "x$AESNI_OBJ" = x; then + as_fn_error $? "AES-NI support requested but cannot be built" "$LINENO" 5 + fi +fi + + + +# Check whether --enable-kdc-lookaside-cache was given. +if test ${enable_kdc_lookaside_cache+y} +then : + enableval=$enable_kdc_lookaside_cache; +else $as_nop + enableval=yes +fi + +if test "$enableval" = no ; then + +printf "%s\n" "#define NOCACHE 1" >>confdefs.h + +fi +KRB5_RUN_ENV="$RUN_ENV" +KRB5_RUN_VARS="$RUN_VARS" + + + +# asan is a gcc and clang facility to instrument the code with memory +# error checking. To use it, we compile C and C++ source files with +# -fsanitize=address, and set ASAN=yes to suppress the undefined +# symbols check when building shared libraries. +# Check whether --enable-asan was given. +if test ${enable_asan+y} +then : + enableval=$enable_asan; +else $as_nop + enable_asan=no +fi + +if test "$enable_asan" != no; then + if test "$enable_asan" = yes; then + enable_asan=address + fi + ASAN_FLAGS="$DEFS -fsanitize=$enable_asan" + ASAN=yes + UNDEF_CHECK= +else + ASAN_FLAGS= + ASAN=no +fi + + + +# from old include/configure.in + + +ac_config_headers="$ac_config_headers include/autoconf.h" + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +printf %s "checking for an ANSI C-conforming const... " >&6; } +if test ${ac_cv_c_const+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ + +#ifndef __cplusplus + /* Ultrix mips cc rejects this sort of thing. */ + typedef int charset[2]; + const charset cs = { 0, 0 }; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* IBM XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* IBM XL C 1.02.0.0 rejects this sort of thing, saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_c_const=yes +else $as_nop + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +printf "%s\n" "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +printf "%s\n" "#define const /**/" >>confdefs.h + +fi + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`printf "%s\n" "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 +printf %s "checking for $ac_hdr that defines DIR... " >&6; } +if eval test \${$as_ac_Header+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main (void) +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + eval "$as_ac_Header=yes" +else $as_nop + eval "$as_ac_Header=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +eval ac_res=\$$as_ac_Header + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +printf "%s\n" "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Header"\" = x"yes" +then : + cat >>confdefs.h <<_ACEOF +#define `printf "%s\n" "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +printf %s "checking for library containing opendir... " >&6; } +if test ${ac_cv_search_opendir+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char opendir (); +int +main (void) +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir +do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO" +then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext + if test ${ac_cv_search_opendir+y} +then : + break +fi +done +if test ${ac_cv_search_opendir+y} +then : + +else $as_nop + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +printf "%s\n" "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no +then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +printf %s "checking for library containing opendir... " >&6; } +if test ${ac_cv_search_opendir+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char opendir (); +int +main (void) +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x +do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO" +then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext + if test ${ac_cv_search_opendir+y} +then : + break +fi +done +if test ${ac_cv_search_opendir+y} +then : + +else $as_nop + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +printf "%s\n" "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no +then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5 +printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; } +if test ${ac_cv_c_undeclared_builtin_options+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_save_CFLAGS=$CFLAGS + ac_cv_c_undeclared_builtin_options='cannot detect' + for ac_arg in '' -fno-builtin; do + CFLAGS="$ac_save_CFLAGS $ac_arg" + # This test program should *not* compile successfully. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main (void) +{ +(void) strchr; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + +else $as_nop + # This test program should compile successfully. + # No library function is consistently available on + # freestanding implementations, so test against a dummy + # declaration. Include always-available headers on the + # off chance that they somehow elicit warnings. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +extern void ac_decl (int, char *); + +int +main (void) +{ +(void) ac_decl (0, (char *) 0); + (void) ac_decl; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + if test x"$ac_arg" = x +then : + ac_cv_c_undeclared_builtin_options='none needed' +else $as_nop + ac_cv_c_undeclared_builtin_options=$ac_arg +fi + break +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + done + CFLAGS=$ac_save_CFLAGS + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5 +printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; } + case $ac_cv_c_undeclared_builtin_options in #( + 'cannot detect') : + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot make $CC report undeclared builtins +See \`config.log' for more details" "$LINENO" 5; } ;; #( + 'none needed') : + ac_c_undeclared_builtin_options='' ;; #( + *) : + ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;; +esac + +ac_fn_check_decl "$LINENO" "strerror_r" "ac_cv_have_decl_strerror_r" "$ac_includes_default" "$ac_c_undeclared_builtin_options" "CFLAGS" +if test "x$ac_cv_have_decl_strerror_r" = xyes +then : + ac_have_decl=1 +else $as_nop + ac_have_decl=0 +fi +printf "%s\n" "#define HAVE_DECL_STRERROR_R $ac_have_decl" >>confdefs.h + + +if test $ac_cv_have_decl_strerror_r = yes; then + # For backward compatibility's sake, define HAVE_STRERROR_R. + # (We used to run AC_CHECK_FUNCS_ONCE for strerror_r, as well + # as AC_CHECK_DECLS_ONCE.) + +printf "%s\n" "#define HAVE_STRERROR_R 1" >>confdefs.h + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether strerror_r returns char *" >&5 +printf %s "checking whether strerror_r returns char *... " >&6; } +if test ${ac_cv_func_strerror_r_char_p+y} +then : + printf %s "(cached) " >&6 +else $as_nop + + ac_cv_func_strerror_r_char_p=no + if test $ac_cv_have_decl_strerror_r = yes; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ + + char buf[100]; + char x = *strerror_r (0, buf, sizeof buf); + char *p = strerror_r (0, buf, sizeof buf); + return !p || x; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_func_strerror_r_char_p=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + + fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strerror_r_char_p" >&5 +printf "%s\n" "$ac_cv_func_strerror_r_char_p" >&6; } +if test $ac_cv_func_strerror_r_char_p = yes; then + +printf "%s\n" "#define STRERROR_R_CHAR_P 1" >>confdefs.h + +fi + +ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup" +if test "x$ac_cv_func_strdup" = xyes +then : + printf "%s\n" "#define HAVE_STRDUP 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "setvbuf" "ac_cv_func_setvbuf" +if test "x$ac_cv_func_setvbuf" = xyes +then : + printf "%s\n" "#define HAVE_SETVBUF 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "seteuid" "ac_cv_func_seteuid" +if test "x$ac_cv_func_seteuid" = xyes +then : + printf "%s\n" "#define HAVE_SETEUID 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "setresuid" "ac_cv_func_setresuid" +if test "x$ac_cv_func_setresuid" = xyes +then : + printf "%s\n" "#define HAVE_SETRESUID 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "setreuid" "ac_cv_func_setreuid" +if test "x$ac_cv_func_setreuid" = xyes +then : + printf "%s\n" "#define HAVE_SETREUID 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "setegid" "ac_cv_func_setegid" +if test "x$ac_cv_func_setegid" = xyes +then : + printf "%s\n" "#define HAVE_SETEGID 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "setresgid" "ac_cv_func_setresgid" +if test "x$ac_cv_func_setresgid" = xyes +then : + printf "%s\n" "#define HAVE_SETRESGID 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "setregid" "ac_cv_func_setregid" +if test "x$ac_cv_func_setregid" = xyes +then : + printf "%s\n" "#define HAVE_SETREGID 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "setsid" "ac_cv_func_setsid" +if test "x$ac_cv_func_setsid" = xyes +then : + printf "%s\n" "#define HAVE_SETSID 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "flock" "ac_cv_func_flock" +if test "x$ac_cv_func_flock" = xyes +then : + printf "%s\n" "#define HAVE_FLOCK 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "fchmod" "ac_cv_func_fchmod" +if test "x$ac_cv_func_fchmod" = xyes +then : + printf "%s\n" "#define HAVE_FCHMOD 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "chmod" "ac_cv_func_chmod" +if test "x$ac_cv_func_chmod" = xyes +then : + printf "%s\n" "#define HAVE_CHMOD 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "strptime" "ac_cv_func_strptime" +if test "x$ac_cv_func_strptime" = xyes +then : + printf "%s\n" "#define HAVE_STRPTIME 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "geteuid" "ac_cv_func_geteuid" +if test "x$ac_cv_func_geteuid" = xyes +then : + printf "%s\n" "#define HAVE_GETEUID 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "setenv" "ac_cv_func_setenv" +if test "x$ac_cv_func_setenv" = xyes +then : + printf "%s\n" "#define HAVE_SETENV 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "unsetenv" "ac_cv_func_unsetenv" +if test "x$ac_cv_func_unsetenv" = xyes +then : + printf "%s\n" "#define HAVE_UNSETENV 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "getenv" "ac_cv_func_getenv" +if test "x$ac_cv_func_getenv" = xyes +then : + printf "%s\n" "#define HAVE_GETENV 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "gmtime_r" "ac_cv_func_gmtime_r" +if test "x$ac_cv_func_gmtime_r" = xyes +then : + printf "%s\n" "#define HAVE_GMTIME_R 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "localtime_r" "ac_cv_func_localtime_r" +if test "x$ac_cv_func_localtime_r" = xyes +then : + printf "%s\n" "#define HAVE_LOCALTIME_R 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "bswap16" "ac_cv_func_bswap16" +if test "x$ac_cv_func_bswap16" = xyes +then : + printf "%s\n" "#define HAVE_BSWAP16 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "bswap64" "ac_cv_func_bswap64" +if test "x$ac_cv_func_bswap64" = xyes +then : + printf "%s\n" "#define HAVE_BSWAP64 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp" +if test "x$ac_cv_func_mkstemp" = xyes +then : + printf "%s\n" "#define HAVE_MKSTEMP 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "getusershell" "ac_cv_func_getusershell" +if test "x$ac_cv_func_getusershell" = xyes +then : + printf "%s\n" "#define HAVE_GETUSERSHELL 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "access" "ac_cv_func_access" +if test "x$ac_cv_func_access" = xyes +then : + printf "%s\n" "#define HAVE_ACCESS 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd" +if test "x$ac_cv_func_getcwd" = xyes +then : + printf "%s\n" "#define HAVE_GETCWD 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "srand48" "ac_cv_func_srand48" +if test "x$ac_cv_func_srand48" = xyes +then : + printf "%s\n" "#define HAVE_SRAND48 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "srand" "ac_cv_func_srand" +if test "x$ac_cv_func_srand" = xyes +then : + printf "%s\n" "#define HAVE_SRAND 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "srandom" "ac_cv_func_srandom" +if test "x$ac_cv_func_srandom" = xyes +then : + printf "%s\n" "#define HAVE_SRANDOM 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "stat" "ac_cv_func_stat" +if test "x$ac_cv_func_stat" = xyes +then : + printf "%s\n" "#define HAVE_STAT 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "strchr" "ac_cv_func_strchr" +if test "x$ac_cv_func_strchr" = xyes +then : + printf "%s\n" "#define HAVE_STRCHR 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror" +if test "x$ac_cv_func_strerror" = xyes +then : + printf "%s\n" "#define HAVE_STRERROR 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "timegm" "ac_cv_func_timegm" +if test "x$ac_cv_func_timegm" = xyes +then : + printf "%s\n" "#define HAVE_TIMEGM 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero" +if test "x$ac_cv_func_explicit_bzero" = xyes +then : + printf "%s\n" "#define HAVE_EXPLICIT_BZERO 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "explicit_memset" "ac_cv_func_explicit_memset" +if test "x$ac_cv_func_explicit_memset" = xyes +then : + printf "%s\n" "#define HAVE_EXPLICIT_MEMSET 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "getresuid" "ac_cv_func_getresuid" +if test "x$ac_cv_func_getresuid" = xyes +then : + printf "%s\n" "#define HAVE_GETRESUID 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "getresgid" "ac_cv_func_getresgid" +if test "x$ac_cv_func_getresgid" = xyes +then : + printf "%s\n" "#define HAVE_GETRESGID 1" >>confdefs.h + +fi + + +ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp" +if test "x$ac_cv_func_mkstemp" = xyes +then : + MKSTEMP_ST_OBJ= +MKSTEMP_OBJ= +else $as_nop + MKSTEMP_ST_OBJ='mkstemp.o' +MKSTEMP_OBJ='$(OUTPRE)mkstemp.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_mkstemp" +fi + + + + +ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" +if test "x$ac_cv_func_gettimeofday" = xyes +then : + GETTIMEOFDAY_ST_OBJ= + GETTIMEOFDAY_OBJ= + +printf "%s\n" "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h + + +else $as_nop + GETTIMEOFDAY_ST_OBJ='gettimeofday.o' + GETTIMEOFDAY_OBJ='$(OUTPRE)gettimeofday.$(OBJEXT)' + EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_gettimeofday" +fi + + + + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sys_errlist declaration" >&5 +printf %s "checking for sys_errlist declaration... " >&6; } +if test ${krb5_cv_decl_sys_errlist+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main (void) +{ +1+sys_nerr; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_decl_sys_errlist=yes +else $as_nop + krb5_cv_decl_sys_errlist=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_decl_sys_errlist" >&5 +printf "%s\n" "$krb5_cv_decl_sys_errlist" >&6; } +# assume sys_nerr won't be declared w/o being in libc +if test $krb5_cv_decl_sys_errlist = yes; then + +printf "%s\n" "#define SYS_ERRLIST_DECLARED 1" >>confdefs.h + + +printf "%s\n" "#define HAVE_SYS_ERRLIST 1" >>confdefs.h + +else + # This means that sys_errlist is not declared in errno.h, but may still + # be in libc. + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sys_errlist in libc" >&5 +printf %s "checking for sys_errlist in libc... " >&6; } +if test ${krb5_cv_var_sys_errlist+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +extern int sys_nerr; +int +main (void) +{ +if (1+sys_nerr < 0) return 1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + krb5_cv_var_sys_errlist=yes +else $as_nop + krb5_cv_var_sys_errlist=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_var_sys_errlist" >&5 +printf "%s\n" "$krb5_cv_var_sys_errlist" >&6; } + if test $krb5_cv_var_sys_errlist = yes; then + +printf "%s\n" "#define HAVE_SYS_ERRLIST 1" >>confdefs.h + + # Do this cruft for backwards compatibility for now. + +printf "%s\n" "#define NEED_SYS_ERRLIST 1" >>confdefs.h + + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: sys_errlist is neither in errno.h nor in libc" >&5 +printf "%s\n" "$as_me: WARNING: sys_errlist is neither in errno.h nor in libc" >&2;} + fi +fi +ac_fn_c_check_header_compile "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" +if test "x$ac_cv_header_unistd_h" = xyes +then : + printf "%s\n" "#define HAVE_UNISTD_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "paths.h" "ac_cv_header_paths_h" "$ac_includes_default" +if test "x$ac_cv_header_paths_h" = xyes +then : + printf "%s\n" "#define HAVE_PATHS_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "regex.h" "ac_cv_header_regex_h" "$ac_includes_default" +if test "x$ac_cv_header_regex_h" = xyes +then : + printf "%s\n" "#define HAVE_REGEX_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "regexpr.h" "ac_cv_header_regexpr_h" "$ac_includes_default" +if test "x$ac_cv_header_regexpr_h" = xyes +then : + printf "%s\n" "#define HAVE_REGEXPR_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default" +if test "x$ac_cv_header_fcntl_h" = xyes +then : + printf "%s\n" "#define HAVE_FCNTL_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "memory.h" "ac_cv_header_memory_h" "$ac_includes_default" +if test "x$ac_cv_header_memory_h" = xyes +then : + printf "%s\n" "#define HAVE_MEMORY_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "$ac_includes_default" +if test "x$ac_cv_header_ifaddrs_h" = xyes +then : + printf "%s\n" "#define HAVE_IFADDRS_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sys/filio.h" "ac_cv_header_sys_filio_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_filio_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_FILIO_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "byteswap.h" "ac_cv_header_byteswap_h" "$ac_includes_default" +if test "x$ac_cv_header_byteswap_h" = xyes +then : + printf "%s\n" "#define HAVE_BYTESWAP_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "machine/endian.h" "ac_cv_header_machine_endian_h" "$ac_includes_default" +if test "x$ac_cv_header_machine_endian_h" = xyes +then : + printf "%s\n" "#define HAVE_MACHINE_ENDIAN_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "machine/byte_order.h" "ac_cv_header_machine_byte_order_h" "$ac_includes_default" +if test "x$ac_cv_header_machine_byte_order_h" = xyes +then : + printf "%s\n" "#define HAVE_MACHINE_BYTE_ORDER_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sys/bswap.h" "ac_cv_header_sys_bswap_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_bswap_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_BSWAP_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "endian.h" "ac_cv_header_endian_h" "$ac_includes_default" +if test "x$ac_cv_header_endian_h" = xyes +then : + printf "%s\n" "#define HAVE_ENDIAN_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "pwd.h" "ac_cv_header_pwd_h" "$ac_includes_default" +if test "x$ac_cv_header_pwd_h" = xyes +then : + printf "%s\n" "#define HAVE_PWD_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "arpa/inet.h" "ac_cv_header_arpa_inet_h" "$ac_includes_default" +if test "x$ac_cv_header_arpa_inet_h" = xyes +then : + printf "%s\n" "#define HAVE_ARPA_INET_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "alloca.h" "ac_cv_header_alloca_h" "$ac_includes_default" +if test "x$ac_cv_header_alloca_h" = xyes +then : + printf "%s\n" "#define HAVE_ALLOCA_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default" +if test "x$ac_cv_header_dlfcn_h" = xyes +then : + printf "%s\n" "#define HAVE_DLFCN_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default" +if test "x$ac_cv_header_limits_h" = xyes +then : + printf "%s\n" "#define HAVE_LIMITS_H 1" >>confdefs.h + +fi + +ac_fn_c_check_header_compile "$LINENO" "regexp.h" "ac_cv_header_regexp_h" "#define INIT char *sp = instring; +#define GETC() (*sp++) +#define PEEKC() (*sp) +#define UNGETC(c) (--sp) +#define RETURN(c) return(c) +#define ERROR(c) + +" +if test "x$ac_cv_header_regexp_h" = xyes +then : + +fi + +ac_fn_c_check_member "$LINENO" "struct stat" "st_mtimensec" "ac_cv_member_struct_stat_st_mtimensec" "#include +#include +" +if test "x$ac_cv_member_struct_stat_st_mtimensec" = xyes +then : + +printf "%s\n" "#define HAVE_STRUCT_STAT_ST_MTIMENSEC 1" >>confdefs.h + + +fi +ac_fn_c_check_member "$LINENO" "struct stat" "st_mtimespec.tv_nsec" "ac_cv_member_struct_stat_st_mtimespec_tv_nsec" "#include +#include +" +if test "x$ac_cv_member_struct_stat_st_mtimespec_tv_nsec" = xyes +then : + +printf "%s\n" "#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1" >>confdefs.h + + +fi +ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim.tv_nsec" "ac_cv_member_struct_stat_st_mtim_tv_nsec" "#include +#include +" +if test "x$ac_cv_member_struct_stat_st_mtim_tv_nsec" = xyes +then : + +printf "%s\n" "#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1" >>confdefs.h + + +fi + + +ac_fn_c_check_func "$LINENO" "re_comp" "ac_cv_func_re_comp" +if test "x$ac_cv_func_re_comp" = xyes +then : + printf "%s\n" "#define HAVE_RE_COMP 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "re_exec" "ac_cv_func_re_exec" +if test "x$ac_cv_func_re_exec" = xyes +then : + printf "%s\n" "#define HAVE_RE_EXEC 1" >>confdefs.h + +fi +ac_fn_c_check_func "$LINENO" "regexec" "ac_cv_func_regexec" +if test "x$ac_cv_func_regexec" = xyes +then : + printf "%s\n" "#define HAVE_REGEXEC 1" >>confdefs.h + +fi + + +ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" +if test "x$ac_cv_type_off_t" = xyes +then : + +else $as_nop + +printf "%s\n" "#define off_t long int" >>confdefs.h + +fi + + +# Fancy caching of perror result... +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for perror declaration" >&5 +printf %s "checking for perror declaration... " >&6; } +if test ${krb5_cv_decl_perror+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "perror" >/dev/null 2>&1 +then : + krb5_cv_decl_perror=yes +else $as_nop + krb5_cv_decl_perror=no +fi +rm -rf conftest* + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_decl_perror" >&5 +printf "%s\n" "$krb5_cv_decl_perror" >&6; } +if test $krb5_cv_decl_perror = yes; then + +printf "%s\n" "#define HDR_HAS_PERROR 1" >>confdefs.h + +fi + + +if test "x$ac_cv_func_strptime" = xyes; then +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if strptime needs a prototype provided" >&5 +printf %s "checking if strptime needs a prototype provided... " >&6; } +if test ${krb5_cv_func_strptime_noproto+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +#undef strptime + struct k5foo {int foo; } xx; + extern int strptime (struct k5foo*); + strptime(&xx); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_func_strptime_noproto=yes +else $as_nop + krb5_cv_func_strptime_noproto=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_func_strptime_noproto" >&5 +printf "%s\n" "$krb5_cv_func_strptime_noproto" >&6; } +if test $krb5_cv_func_strptime_noproto = yes; then + +printf "%s\n" "#define NEED_STRPTIME_PROTO 1" >>confdefs.h + +fi +fi + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if argument to wait is int *" >&5 +printf %s "checking if argument to wait is int *... " >&6; } +if test ${krb5_cv_struct_wait+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + extern pid_t wait(int *); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_struct_wait=no +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main (void) +{ +union wait i; + #ifdef WEXITSTATUS + WEXITSTATUS (i); + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_struct_wait=yes +else $as_nop + krb5_cv_struct_wait=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_struct_wait" >&5 +printf "%s\n" "$krb5_cv_struct_wait" >&6; } +if test $krb5_cv_struct_wait = no; then + +printf "%s\n" "#define WAIT_USES_INT 1" >>confdefs.h + +fi + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for use of sigprocmask" >&5 +printf %s "checking for use of sigprocmask... " >&6; } +if test ${krb5_cv_func_sigprocmask_use+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main (void) +{ +sigprocmask(SIG_SETMASK, 0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + krb5_cv_func_sigprocmask_use=yes +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main (void) +{ +sigmask(1); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + krb5_cv_func_sigprocmask_use=no +else $as_nop + krb5_cv_func_sigprocmask_use=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_func_sigprocmask_use" >&5 +printf "%s\n" "$krb5_cv_func_sigprocmask_use" >&6; } +if test $krb5_cv_func_sigprocmask_use = yes; then + +printf "%s\n" "#define USE_SIGPROCMASK 1" >>confdefs.h + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 +printf %s "checking for uid_t in sys/types.h... " >&6; } +if test ${ac_cv_type_uid_t+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "uid_t" >/dev/null 2>&1 +then : + ac_cv_type_uid_t=yes +else $as_nop + ac_cv_type_uid_t=no +fi +rm -rf conftest* + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 +printf "%s\n" "$ac_cv_type_uid_t" >&6; } +if test $ac_cv_type_uid_t = no; then + +printf "%s\n" "#define uid_t int" >>confdefs.h + + +printf "%s\n" "#define gid_t int" >>confdefs.h + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking type of array argument to getgroups" >&5 +printf %s "checking type of array argument to getgroups... " >&6; } +if test ${ac_cv_type_getgroups+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test "$cross_compiling" = yes +then : + ac_cv_type_getgroups=cross +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Thanks to Mike Rendell for this test. */ +$ac_includes_default +#define NGID 256 +#undef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +int +main (void) +{ + gid_t gidset[NGID]; + int i, n; + union { gid_t gval; long int lval; } val; + + val.lval = -1; + for (i = 0; i < NGID; i++) + gidset[i] = val.gval; + n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1, + gidset); + /* Exit non-zero if getgroups seems to require an array of ints. This + happens when gid_t is short int but getgroups modifies an array + of ints. */ + return n > 0 && gidset[n] != val.gval; +} +_ACEOF +if ac_fn_c_try_run "$LINENO" +then : + ac_cv_type_getgroups=gid_t +else $as_nop + ac_cv_type_getgroups=int +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +if test $ac_cv_type_getgroups = cross; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "getgroups.*int.*gid_t" >/dev/null 2>&1 +then : + ac_cv_type_getgroups=gid_t +else $as_nop + ac_cv_type_getgroups=int +fi +rm -rf conftest* + +fi +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_getgroups" >&5 +printf "%s\n" "$ac_cv_type_getgroups" >&6; } + +printf "%s\n" "#define GETGROUPS_T $ac_cv_type_getgroups" >>confdefs.h + + + +ac_fn_c_check_func "$LINENO" "sigsetjmp" "ac_cv_func_sigsetjmp" +if test "x$ac_cv_func_sigsetjmp" = xyes +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sigjmp_buf" >&5 +printf %s "checking for sigjmp_buf... " >&6; } +if test ${krb5_cv_struct_sigjmp_buf+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main (void) +{ +sigjmp_buf x + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_struct_sigjmp_buf=yes +else $as_nop + krb5_cv_struct_sigjmp_buf=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_struct_sigjmp_buf" >&5 +printf "%s\n" "$krb5_cv_struct_sigjmp_buf" >&6; } +if test $krb5_cv_struct_sigjmp_buf = yes; then + +printf "%s\n" "#define POSIX_SETJMP 1" >>confdefs.h + +fi + +fi + + +# *rpcent return types needed for lib/rpc + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking return type of setrpcent" >&5 +printf %s "checking return type of setrpcent... " >&6; } +if test ${k5_cv_type_setrpcent+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + extern void setrpcent(); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + k5_cv_type_setrpcent=void +else $as_nop + k5_cv_type_setrpcent=int +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $k5_cv_type_setrpcent" >&5 +printf "%s\n" "$k5_cv_type_setrpcent" >&6; } + +printf "%s\n" "#define SETRPCENT_TYPE $k5_cv_type_setrpcent" >>confdefs.h + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking return type of endrpcent" >&5 +printf %s "checking return type of endrpcent... " >&6; } +if test ${k5_cv_type_endrpcent+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + extern void endrpcent(); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + k5_cv_type_endrpcent=void +else $as_nop + k5_cv_type_endrpcent=int +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $k5_cv_type_endrpcent" >&5 +printf "%s\n" "$k5_cv_type_endrpcent" >&6; } + +printf "%s\n" "#define ENDRPCENT_TYPE $k5_cv_type_endrpcent" >>confdefs.h + + + +# bswap_16 is a macro in byteswap.h under GNU libc +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for bswap_16" >&5 +printf %s "checking for bswap_16... " >&6; } +if test ${krb5_cv_bswap_16+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if HAVE_BYTESWAP_H + #include + #endif + +int +main (void) +{ +bswap_16(37); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + krb5_cv_bswap_16=yes +else $as_nop + krb5_cv_bswap_16=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_bswap_16" >&5 +printf "%s\n" "$krb5_cv_bswap_16" >&6; } +if test "$krb5_cv_bswap_16" = yes; then + +printf "%s\n" "#define HAVE_BSWAP_16 1" >>confdefs.h + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for bswap_64" >&5 +printf %s "checking for bswap_64... " >&6; } +if test ${krb5_cv_bswap_64+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if HAVE_BYTESWAP_H + #include + #endif + +int +main (void) +{ +bswap_64(37); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + krb5_cv_bswap_64=yes +else $as_nop + krb5_cv_bswap_64=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_bswap_64" >&5 +printf "%s\n" "$krb5_cv_bswap_64" >&6; } +if test "$krb5_cv_bswap_64" = yes; then + +printf "%s\n" "#define HAVE_BSWAP_64 1" >>confdefs.h + +fi + +# Needed for ksu and some appl stuff. + +case $krb5_cv_host in +alpha*-dec-osf*) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for setluid in -lsecurity" >&5 +printf %s "checking for setluid in -lsecurity... " >&6; } +if test ${ac_cv_lib_security_setluid+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsecurity $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char setluid (); +int +main (void) +{ +return setluid (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_security_setluid=yes +else $as_nop + ac_cv_lib_security_setluid=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_security_setluid" >&5 +printf "%s\n" "$ac_cv_lib_security_setluid" >&6; } +if test "x$ac_cv_lib_security_setluid" = xyes +then : + +printf "%s\n" "#define HAVE_SETLUID 1" >>confdefs.h + + KSU_LIBS="-lsecurity" + +fi + + ;; +esac + + +if test $ac_cv_func_setenv = no || test $ac_cv_func_unsetenv = no \ + || test $ac_cv_func_getenv = no; then + SETENVOBJ=setenv.o +else + SETENVOBJ= +fi + + +# Check what the return types for gethostbyname_r and getservbyname_r are. + +ac_fn_c_check_func "$LINENO" "gethostbyname_r" "ac_cv_func_gethostbyname_r" +if test "x$ac_cv_func_gethostbyname_r" = xyes +then : + +ac_cv_func_gethostbyname_r=yes +if test "$ac_cv_func_gethostbyname_r" = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if gethostbyname_r returns an int" >&5 +printf %s "checking if gethostbyname_r returns an int... " >&6; } + if test ${krb5_cv_gethostbyname_r_returns_int+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + extern int gethostbyname_r(); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_gethostbyname_r_returns_int=yes +else $as_nop + krb5_cv_gethostbyname_r_returns_int=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_gethostbyname_r_returns_int" >&5 +printf "%s\n" "$krb5_cv_gethostbyname_r_returns_int" >&6; } + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if gethostbyname_r returns a pointer" >&5 +printf %s "checking if gethostbyname_r returns a pointer... " >&6; } + if test ${krb5_cv_gethostbyname_r_returns_ptr+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + extern struct hostent *gethostbyname_r(); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_gethostbyname_r_returns_ptr=yes +else $as_nop + krb5_cv_gethostbyname_r_returns_ptr=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_gethostbyname_r_returns_ptr" >&5 +printf "%s\n" "$krb5_cv_gethostbyname_r_returns_ptr" >&6; } + + if test "$krb5_cv_gethostbyname_r_returns_int" = "$krb5_cv_gethostbyname_r_returns_ptr"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine return type of gethostbyname_r -- disabling" >&5 +printf "%s\n" "$as_me: WARNING: cannot determine return type of gethostbyname_r -- disabling" >&2;} + ac_cv_func_gethostbyname_r=no + fi + if test "$krb5_cv_gethostbyname_r_returns_int" = yes; then + +printf "%s\n" "#define GETHOSTBYNAME_R_RETURNS_INT 1" >>confdefs.h + + fi +fi +if test "$ac_cv_func_gethostbyname_r" = yes; then + +printf "%s\n" "#define HAVE_GETHOSTBYNAME_R 1" >>confdefs.h + + ac_fn_c_check_func "$LINENO" "gethostbyaddr_r" "ac_cv_func_gethostbyaddr_r" +if test "x$ac_cv_func_gethostbyaddr_r" = xyes +then : + +fi + +fi + +fi + + + +# PTHREAD_CFLAGS changes which variant of these functions is declared +# on Solaris 11, so use it for these tests. +old_CFLAGS=$CFLAGS +CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +ac_fn_c_check_func "$LINENO" "getpwnam_r" "ac_cv_func_getpwnam_r" +if test "x$ac_cv_func_getpwnam_r" = xyes +then : + ac_cv_func_getpwnam_r=yes +else $as_nop + ac_cv_func_getpwnam_r=no +fi + +ac_fn_c_check_func "$LINENO" "getpwuid_r" "ac_cv_func_getpwuid_r" +if test "x$ac_cv_func_getpwuid_r" = xyes +then : + ac_cv_func_getpwuid_r=yes +else $as_nop + ac_cv_func_getpwuid_r=no +fi + +if test "$ac_cv_func_getpwnam_r" = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking return type of getpwnam_r" >&5 +printf %s "checking return type of getpwnam_r... " >&6; } + if test ${krb5_cv_getpwnam_r_return_type+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + extern int getpwnam_r(); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + getpwnam_r_returns_int=yes +else $as_nop + getpwnam_r_returns_int=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + extern struct passwd *getpwnam_r(); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + getpwnam_r_returns_ptr=yes +else $as_nop + getpwnam_r_returns_ptr=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + case "$getpwnam_r_returns_int/$getpwnam_r_returns_ptr" in + yes/no) krb5_cv_getpwnam_r_return_type=int ;; + no/yes) krb5_cv_getpwnam_r_return_type=ptr ;; + *) krb5_cv_getpwnam_r_return_type=unknown ;; + esac +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_getpwnam_r_return_type" >&5 +printf "%s\n" "$krb5_cv_getpwnam_r_return_type" >&6; } + if test $krb5_cv_getpwnam_r_return_type = int; then + +printf "%s\n" "#define GETPWNAM_R_RETURNS_INT 1" >>confdefs.h + + elif test $krb5_cv_getpwnam_r_return_type = unknown; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot determine getpwnam_r return type, disabling getpwnam_r" >&5 +printf "%s\n" "$as_me: WARNING: Cannot determine getpwnam_r return type, disabling getpwnam_r" >&2;} + ac_cv_func_getpwnam_r=no + fi +fi +if test "$ac_cv_func_getpwnam_r" = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking number of arguments to getpwnam_r" >&5 +printf %s "checking number of arguments to getpwnam_r... " >&6; } + if test ${krb5_cv_getpwnam_r_args+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + struct passwd pwx; char buf[1024]; +int +main (void) +{ +getpwnam_r("", &pwx, buf, sizeof(buf)); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + args4=yes +else $as_nop + args4=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + struct passwd pwx, *p; + char buf[1024]; +int +main (void) +{ +getpwnam_r("", &pwx, buf, sizeof(buf), &p); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + args5=yes +else $as_nop + args5=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + case $args4/$args5 in + yes/no) krb5_cv_getpwnam_r_args=4 ;; + no/yes) krb5_cv_getpwnam_r_args=5 ;; + *) krb5_cv_getpwnam_r_args=unknown ;; + esac +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_getpwnam_r_args" >&5 +printf "%s\n" "$krb5_cv_getpwnam_r_args" >&6; } + if test "$krb5_cv_getpwnam_r_args" = unknown; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Cannot determine number of arguments to getpwnam_r, disabling its use." >&5 +printf "%s\n" "$as_me: WARNING: Cannot determine number of arguments to getpwnam_r, disabling its use." >&2;} + ac_cv_func_getpwnam_r=no + else + +printf "%s\n" "#define HAVE_GETPWNAM_R 1" >>confdefs.h + + if test "$krb5_cv_getpwnam_r_args" = 4; then + +printf "%s\n" "#define GETPWNAM_R_4_ARGS 1" >>confdefs.h + + fi + fi +fi +CFLAGS=$old_CFLAGS + +if test "$ac_cv_func_getpwnam_r" = no && test "$ac_cv_func_getpwuid_r" = yes; then + # Actually, we could do this check, and the corresponding checks + # for return type and number of arguments, but I doubt we'll run + # into a system where we'd get to use getpwuid_r but not getpwnam_r. + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: getpwnam_r not useful, so disabling getpwuid_r too" >&5 +printf "%s\n" "$as_me: getpwnam_r not useful, so disabling getpwuid_r too" >&6;} + ac_cv_func_getpwuid_r=no +fi +if test "$ac_cv_func_getpwuid_r" = yes; then + +printf "%s\n" "#define HAVE_GETPWUID_R 1" >>confdefs.h + + # Hack: Assume getpwuid_r is the shorter form if getpwnam_r is. + if test "$krb5_cv_getpwnam_r_args" = 4; then + +printf "%s\n" "#define GETPWUID_R_4_ARGS 1" >>confdefs.h + + fi +fi + +if test "$ac_cv_func_gmtime_r" = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether gmtime_r returns int" >&5 +printf %s "checking whether gmtime_r returns int... " >&6; } + if test ${krb5_cv_gmtime_r_returns_int+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + extern int gmtime_r(); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + return_int=yes +else $as_nop + return_int=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + extern struct tm *gmtime_r(); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + return_ptr=yes +else $as_nop + return_ptr=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + case $return_int/$return_ptr in + yes/no) krb5_cv_gmtime_r_returns_int=yes ;; + no/yes) krb5_cv_gmtime_r_returns_int=no ;; + *) # Can't figure it out, punt the function. + ac_cv_func_gmtime_r=no ;; + esac +fi + + if test "$ac_cv_func_gmtime_r" = no; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unknown -- ignoring gmtime_r" >&5 +printf "%s\n" "unknown -- ignoring gmtime_r" >&6; } + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_gmtime_r_returns_int" >&5 +printf "%s\n" "$krb5_cv_gmtime_r_returns_int" >&6; } + if test "$krb5_cv_gmtime_r_returns_int" = yes; then + +printf "%s\n" "#define GMTIME_R_RETURNS_INT 1" >>confdefs.h + + fi + fi +fi + +ac_fn_c_check_func "$LINENO" "getservbyname_r" "ac_cv_func_getservbyname_r" +if test "x$ac_cv_func_getservbyname_r" = xyes +then : + +ac_cv_func_getservbyname_r=yes +if test "$ac_cv_func_getservbyname_r" = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if getservbyname_r returns an int" >&5 +printf %s "checking if getservbyname_r returns an int... " >&6; } + if test ${krb5_cv_getservbyname_r_returns_int+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + extern int getservbyname_r(); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_getservbyname_r_returns_int=yes +else $as_nop + krb5_cv_getservbyname_r_returns_int=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_getservbyname_r_returns_int" >&5 +printf "%s\n" "$krb5_cv_getservbyname_r_returns_int" >&6; } + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if getservbyname_r returns a pointer" >&5 +printf %s "checking if getservbyname_r returns a pointer... " >&6; } + if test ${krb5_cv_getservbyname_r_returns_ptr+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + extern struct servent *getservbyname_r(); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_getservbyname_r_returns_ptr=yes +else $as_nop + krb5_cv_getservbyname_r_returns_ptr=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_getservbyname_r_returns_ptr" >&5 +printf "%s\n" "$krb5_cv_getservbyname_r_returns_ptr" >&6; } + + if test "$krb5_cv_getservbyname_r_returns_int" = "$krb5_cv_getservbyname_r_returns_ptr"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine return type of getservbyname_r -- disabling" >&5 +printf "%s\n" "$as_me: WARNING: cannot determine return type of getservbyname_r -- disabling" >&2;} + ac_cv_func_getservbyname_r=no + fi + if test "$krb5_cv_getservbyname_r_returns_int" = yes; then + +printf "%s\n" "#define GETSERVBYNAME_R_RETURNS_INT 1" >>confdefs.h + + fi +fi +if test "$ac_cv_func_getservbyname_r" = yes; then + +printf "%s\n" "#define HAVE_GETSERVBYNAME_R 1" >>confdefs.h + + ac_fn_c_check_func "$LINENO" "getservbyport_r" "ac_cv_func_getservbyport_r" +if test "x$ac_cv_func_getservbyport_r" = xyes +then : + +fi + +fi + +fi + + + +ac_fn_c_check_header_compile "$LINENO" "dirent.h" "ac_cv_header_dirent_h" "$ac_includes_default" +if test "x$ac_cv_header_dirent_h" = xyes +then : + +printf "%s\n" "#define USE_DIRENT_H 1" >>confdefs.h + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 +printf %s "checking for uid_t in sys/types.h... " >&6; } +if test ${ac_cv_type_uid_t+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "uid_t" >/dev/null 2>&1 +then : + ac_cv_type_uid_t=yes +else $as_nop + ac_cv_type_uid_t=no +fi +rm -rf conftest* + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 +printf "%s\n" "$ac_cv_type_uid_t" >&6; } +if test $ac_cv_type_uid_t = no; then + +printf "%s\n" "#define uid_t int" >>confdefs.h + + +printf "%s\n" "#define gid_t int" >>confdefs.h + +fi + + +ac_fn_c_check_header_compile "$LINENO" "termios.h" "ac_cv_header_termios_h" "$ac_includes_default" +if test "x$ac_cv_header_termios_h" = xyes +then : + ac_fn_c_check_func "$LINENO" "tcsetattr" "ac_cv_func_tcsetattr" +if test "x$ac_cv_func_tcsetattr" = xyes +then : + +printf "%s\n" "#define POSIX_TERMIOS 1" >>confdefs.h + +fi + +fi + + +ac_fn_c_check_header_compile "$LINENO" "poll.h" "ac_cv_header_poll_h" "$ac_includes_default" +if test "x$ac_cv_header_poll_h" = xyes +then : + printf "%s\n" "#define HAVE_POLL_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes +then : + printf "%s\n" "#define HAVE_STDLIB_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default" +if test "x$ac_cv_header_string_h" = xyes +then : + printf "%s\n" "#define HAVE_STRING_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "stddef.h" "ac_cv_header_stddef_h" "$ac_includes_default" +if test "x$ac_cv_header_stddef_h" = xyes +then : + printf "%s\n" "#define HAVE_STDDEF_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_types_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_TYPES_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sys/file.h" "ac_cv_header_sys_file_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_file_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_FILE_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_param_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_PARAM_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sys/stat.h" "ac_cv_header_sys_stat_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_stat_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_STAT_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_time_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_TIME_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "netinet/in.h" "ac_cv_header_netinet_in_h" "$ac_includes_default" +if test "x$ac_cv_header_netinet_in_h" = xyes +then : + printf "%s\n" "#define HAVE_NETINET_IN_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sys/uio.h" "ac_cv_header_sys_uio_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_uio_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_UIO_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sys/filio.h" "ac_cv_header_sys_filio_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_filio_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_FILIO_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_select_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_SELECT_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "time.h" "ac_cv_header_time_h" "$ac_includes_default" +if test "x$ac_cv_header_time_h" = xyes +then : + printf "%s\n" "#define HAVE_TIME_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "paths.h" "ac_cv_header_paths_h" "$ac_includes_default" +if test "x$ac_cv_header_paths_h" = xyes +then : + printf "%s\n" "#define HAVE_PATHS_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "errno.h" "ac_cv_header_errno_h" "$ac_includes_default" +if test "x$ac_cv_header_errno_h" = xyes +then : + printf "%s\n" "#define HAVE_ERRNO_H 1" >>confdefs.h + +fi + + +# If compiling with IPv6 support, test if in6addr_any functions. +# Irix 6.5.16 defines it, but lacks support in the C library. +if test $krb5_cv_inet6 = yes || test "$krb5_cv_inet6_with_dinet6" = yes ; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for in6addr_any definition in library" >&5 +printf %s "checking for in6addr_any definition in library... " >&6; } +if test ${krb5_cv_var_in6addr_any+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef HAVE_SYS_TYPES_H + #include + #endif + #include + #include + #include + #include + +int +main (void) +{ +struct sockaddr_in6 in; + in.sin6_addr = in6addr_any; + printf("%x", &in); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + krb5_cv_var_in6addr_any=yes +else $as_nop + krb5_cv_var_in6addr_any=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_var_in6addr_any" >&5 +printf "%s\n" "$krb5_cv_var_in6addr_any" >&6; } + if test $krb5_cv_var_in6addr_any = no; then + +printf "%s\n" "#define NEED_INSIXADDR_ANY 1" >>confdefs.h + + fi +fi + +# then from osconf.h, we have + +ac_fn_c_check_type "$LINENO" "time_t" "ac_cv_type_time_t" "$ac_includes_default" +if test "x$ac_cv_type_time_t" = xyes +then : + +else $as_nop + +printf "%s\n" "#define time_t long" >>confdefs.h + +fi + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5 +printf %s "checking size of time_t... " >&6; } +if test ${ac_cv_sizeof_time_t+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (time_t))" "ac_cv_sizeof_time_t" "$ac_includes_default" +then : + +else $as_nop + if test "$ac_cv_type_time_t" = yes; then + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (time_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_time_t=0 + fi +fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_time_t" >&5 +printf "%s\n" "$ac_cv_sizeof_time_t" >&6; } + + + +printf "%s\n" "#define SIZEOF_TIME_T $ac_cv_sizeof_time_t" >>confdefs.h + + +SIZEOF_TIME_T=$ac_cv_sizeof_time_t + + +# Determine where to put the replay cache. + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for replay cache directory" >&5 +printf %s "checking for replay cache directory... " >&6; } +if test ${krb5_cv_sys_rcdir+y} +then : + printf %s "(cached) " >&6 +else $as_nop + +if test $cross_compiling = yes; then + krb5_cv_sys_rcdir=/var/tmp +else + for t_dir in /var/tmp /usr/tmp /var/usr/tmp /tmp ; do + test -d $t_dir || continue + krb5_cv_sys_rcdir=$t_dir + break + done +fi +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_sys_rcdir" >&5 +printf "%s\n" "$krb5_cv_sys_rcdir" >&6; } +KRB5_RCTMPDIR=$krb5_cv_sys_rcdir + + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socklen_t" >&5 +printf %s "checking for socklen_t... " >&6; } +if test ${krb5_cv_has_type_socklen_t+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main (void) +{ +sizeof(socklen_t); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_has_type_socklen_t=yes +else $as_nop + krb5_cv_has_type_socklen_t=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_has_type_socklen_t" >&5 +printf "%s\n" "$krb5_cv_has_type_socklen_t" >&6; } +if test $krb5_cv_has_type_socklen_t = yes; then + +printf "%s\n" "#define HAVE_SOCKLEN_T 1" >>confdefs.h + +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct lifconf" >&5 +printf %s "checking for struct lifconf... " >&6; } +if test ${krb5_cv_has_struct_lifconf+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main (void) +{ +sizeof (struct lifconf); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_has_struct_lifconf=yes +else $as_nop + krb5_cv_has_struct_lifconf=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_has_struct_lifconf" >&5 +printf "%s\n" "$krb5_cv_has_struct_lifconf" >&6; } +if test $krb5_cv_has_struct_lifconf = yes; then + +printf "%s\n" "#define HAVE_STRUCT_LIFCONF 1" >>confdefs.h + +fi +# HP-UX 11 uses stuct if_laddrconf +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct if_laddrconf" >&5 +printf %s "checking for struct if_laddrconf... " >&6; } +if test ${krb5_cv_has_struct_if_laddrconf+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + #include + +int +main (void) +{ +sizeof(struct if_laddrconf); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_has_struct_if_laddrconf=yes +else $as_nop + krb5_cv_has_struct_if_laddrconf=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_has_struct_if_laddrconf" >&5 +printf "%s\n" "$krb5_cv_has_struct_if_laddrconf" >&6; } +if test $krb5_cv_has_struct_if_laddrconf = yes; then + +printf "%s\n" "#define HAVE_STRUCT_IF_LADDRCONF 1" >>confdefs.h + +fi + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for h_errno in netdb.h" >&5 +printf %s "checking for h_errno in netdb.h... " >&6; } +if test ${krb5_cv_header_netdb_h_h_errno+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main (void) +{ +int x = h_errno; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_header_netdb_h_h_errno=yes +else $as_nop + krb5_cv_header_netdb_h_h_errno=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_header_netdb_h_h_errno" >&5 +printf "%s\n" "$krb5_cv_header_netdb_h_h_errno" >&6; } +if test $krb5_cv_header_netdb_h_h_errno = yes; then + +printf "%s\n" "#define HAVE_NETDB_H_H_ERRNO 1" >>confdefs.h + +fi + + +# Check whether --enable-athena was given. +if test ${enable_athena+y} +then : + enableval=$enable_athena; +printf "%s\n" "#define KRB5_ATHENA_COMPAT 1" >>confdefs.h + +fi + + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +printf %s "checking for inline... " >&6; } +if test ${ac_cv_c_inline+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo (void) {return 0; } +$ac_kw foo_t foo (void) {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +printf "%s\n" "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + + + + +ac_fn_c_check_type "$LINENO" "struct cmsghdr" "ac_cv_type_struct_cmsghdr" " +#include +#include +#include + +" +if test "x$ac_cv_type_struct_cmsghdr" = xyes +then : + +printf "%s\n" "#define HAVE_STRUCT_CMSGHDR 1" >>confdefs.h + + +fi +ac_fn_c_check_type "$LINENO" "struct in_pktinfo" "ac_cv_type_struct_in_pktinfo" " +#include +#include +#include + +" +if test "x$ac_cv_type_struct_in_pktinfo" = xyes +then : + +printf "%s\n" "#define HAVE_STRUCT_IN_PKTINFO 1" >>confdefs.h + + +fi +ac_fn_c_check_type "$LINENO" "struct in6_pktinfo" "ac_cv_type_struct_in6_pktinfo" " +#include +#include +#include + +" +if test "x$ac_cv_type_struct_in6_pktinfo" = xyes +then : + +printf "%s\n" "#define HAVE_STRUCT_IN6_PKTINFO 1" >>confdefs.h + + +fi +ac_fn_c_check_type "$LINENO" "struct sockaddr_storage" "ac_cv_type_struct_sockaddr_storage" " +#include +#include +#include + +" +if test "x$ac_cv_type_struct_sockaddr_storage" = xyes +then : + +printf "%s\n" "#define HAVE_STRUCT_SOCKADDR_STORAGE 1" >>confdefs.h + + +fi + +ac_fn_c_check_type "$LINENO" "struct rt_msghdr" "ac_cv_type_struct_rt_msghdr" " +#include +#include +#include + +" +if test "x$ac_cv_type_struct_rt_msghdr" = xyes +then : + +printf "%s\n" "#define HAVE_STRUCT_RT_MSGHDR 1" >>confdefs.h + + +fi + + +# Tests for 64-bit edwards25519 code. +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of size_t" >&5 +printf %s "checking size of size_t... " >&6; } +if test ${ac_cv_sizeof_size_t+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (size_t))" "ac_cv_sizeof_size_t" "$ac_includes_default" +then : + +else $as_nop + if test "$ac_cv_type_size_t" = yes; then + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (size_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_size_t=0 + fi +fi + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_size_t" >&5 +printf "%s\n" "$ac_cv_sizeof_size_t" >&6; } + + + +printf "%s\n" "#define SIZEOF_SIZE_T $ac_cv_sizeof_size_t" >>confdefs.h + + +ac_fn_c_check_type "$LINENO" "__int128_t" "ac_cv_type___int128_t" "$ac_includes_default" +if test "x$ac_cv_type___int128_t" = xyes +then : + +printf "%s\n" "#define HAVE___INT128_T 1" >>confdefs.h + + +fi +ac_fn_c_check_type "$LINENO" "__uint128_t" "ac_cv_type___uint128_t" "$ac_includes_default" +if test "x$ac_cv_type___uint128_t" = xyes +then : + +printf "%s\n" "#define HAVE___UINT128_T 1" >>confdefs.h + + +fi + + +# types libdb2 wants + +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" +if test "x$ac_cv_type_ssize_t" = xyes +then : + +printf "%s\n" "#define HAVE_SSIZE_T 1" >>confdefs.h + + +fi +ac_fn_c_check_type "$LINENO" "u_char" "ac_cv_type_u_char" "$ac_includes_default" +if test "x$ac_cv_type_u_char" = xyes +then : + +printf "%s\n" "#define HAVE_U_CHAR 1" >>confdefs.h + + +fi +ac_fn_c_check_type "$LINENO" "u_int" "ac_cv_type_u_int" "$ac_includes_default" +if test "x$ac_cv_type_u_int" = xyes +then : + +printf "%s\n" "#define HAVE_U_INT 1" >>confdefs.h + + +fi +ac_fn_c_check_type "$LINENO" "u_long" "ac_cv_type_u_long" "$ac_includes_default" +if test "x$ac_cv_type_u_long" = xyes +then : + +printf "%s\n" "#define HAVE_U_LONG 1" >>confdefs.h + + +fi +ac_fn_c_check_type "$LINENO" "u_int8_t" "ac_cv_type_u_int8_t" "$ac_includes_default" +if test "x$ac_cv_type_u_int8_t" = xyes +then : + +printf "%s\n" "#define HAVE_U_INT8_T 1" >>confdefs.h + + +fi +ac_fn_c_check_type "$LINENO" "u_int16_t" "ac_cv_type_u_int16_t" "$ac_includes_default" +if test "x$ac_cv_type_u_int16_t" = xyes +then : + +printf "%s\n" "#define HAVE_U_INT16_T 1" >>confdefs.h + + +fi +ac_fn_c_check_type "$LINENO" "u_int32_t" "ac_cv_type_u_int32_t" "$ac_includes_default" +if test "x$ac_cv_type_u_int32_t" = xyes +then : + +printf "%s\n" "#define HAVE_U_INT32_T 1" >>confdefs.h + + +fi +ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default" +if test "x$ac_cv_type_int8_t" = xyes +then : + +printf "%s\n" "#define HAVE_INT8_T 1" >>confdefs.h + + +fi +ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$ac_includes_default" +if test "x$ac_cv_type_int16_t" = xyes +then : + +printf "%s\n" "#define HAVE_INT16_T 1" >>confdefs.h + + +fi +ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$ac_includes_default" +if test "x$ac_cv_type_int32_t" = xyes +then : + +printf "%s\n" "#define HAVE_INT32_T 1" >>confdefs.h + + +fi + + +# Some libdb2 test programs want a shell that supports functions. +FCTSH=false +# Extract the first word of "sh", so it can be a program name with args. +set dummy sh; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_SH+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $SH in + [\\/]* | ?:[\\/]*) + ac_cv_path_SH="$SH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_SH="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_SH" && ac_cv_path_SH="false" + ;; +esac +fi +SH=$ac_cv_path_SH +if test -n "$SH"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SH" >&5 +printf "%s\n" "$SH" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +# Extract the first word of "sh5", so it can be a program name with args. +set dummy sh5; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_SH5+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $SH5 in + [\\/]* | ?:[\\/]*) + ac_cv_path_SH5="$SH5" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_SH5="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_SH5" && ac_cv_path_SH5="false" + ;; +esac +fi +SH5=$ac_cv_path_SH5 +if test -n "$SH5"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SH5" >&5 +printf "%s\n" "$SH5" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +# Extract the first word of "bash", so it can be a program name with args. +set dummy bash; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_BASH+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $BASH in + [\\/]* | ?:[\\/]*) + ac_cv_path_BASH="$BASH" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_BASH="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_BASH" && ac_cv_path_BASH="false" + ;; +esac +fi +BASH=$ac_cv_path_BASH +if test -n "$BASH"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $BASH" >&5 +printf "%s\n" "$BASH" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +for prog in $SH $SH5 $BASH; do + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if $prog supports functions" >&5 +printf %s "checking if $prog supports functions... " >&6; } + if $prog -c 'foo() { true; }; foo' >/dev/null 2>&1; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + FCTSH=$prog + break + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + fi +done + + +# Test for POSIX 2001 *printf support (X/Open System Interfaces extension +# to ANSI/ISO C 1999 specification). Specifically, positional +# specifications; not checking for other features like %zx at present. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for POSIX printf positional specification support" >&5 +printf %s "checking for POSIX printf positional specification support... " >&6; } +if test ${ac_cv_printf_positional+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test "$cross_compiling" = yes +then : + as_fn_error $? "Cannot test for printf positional argument support when cross compiling" "$LINENO" 5 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + const char expected[] = "200 100"; + int main() + { + char buf[30]; + sprintf(buf, "%2\$x %1\$d", 100, 512); + if (strcmp(expected, buf)) { + fprintf(stderr, "bad result: <%s> wanted: <%s>\n", + buf, expected); + return 1; + } + return 0; + } +_ACEOF +if ac_fn_c_try_run "$LINENO" +then : + ac_cv_printf_positional=yes +else $as_nop + ac_cv_printf_positional=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi + +# Nothing for autoconf.h for now. +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_printf_positional" >&5 +printf "%s\n" "$ac_cv_printf_positional" >&6; } + + +# for t_locate_kdc test + +# Extract the first word of "dig", so it can be a program name with args. +set dummy dig; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_DIG+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $DIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_DIG="$DIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_DIG="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_DIG" && ac_cv_path_DIG="false" + ;; +esac +fi +DIG=$ac_cv_path_DIG +if test -n "$DIG"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $DIG" >&5 +printf "%s\n" "$DIG" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +# Extract the first word of "nslookup", so it can be a program name with args. +set dummy nslookup; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_NSLOOKUP+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $NSLOOKUP in + [\\/]* | ?:[\\/]*) + ac_cv_path_NSLOOKUP="$NSLOOKUP" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_NSLOOKUP="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_NSLOOKUP" && ac_cv_path_NSLOOKUP="false" + ;; +esac +fi +NSLOOKUP=$ac_cv_path_NSLOOKUP +if test -n "$NSLOOKUP"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $NSLOOKUP" >&5 +printf "%s\n" "$NSLOOKUP" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + +# for kadmin + +for ac_prog in 'bison -y' byacc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_YACC+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$YACC"; then + ac_cv_prog_YACC="$YACC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_YACC="$ac_prog" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +YACC=$ac_cv_prog_YACC +if test -n "$YACC"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 +printf "%s\n" "$YACC" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + test -n "$YACC" && break +done +test -n "$YACC" || YACC="yacc" + +ath_compat= +# Check whether --enable-athena was given. +if test ${enable_athena+y} +then : + enableval=$enable_athena; ath_compat=compat +fi + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use priocntl hack" >&5 +printf %s "checking whether to use priocntl hack... " >&6; } +if test ${krb5_cv_priocntl_hack+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $krb5_cv_host in +*-*-solaris2.9*) + if test "$cross_compiling" = yes; then + krb5_cv_priocntl_hack=yes + else + # Solaris patch 117171-11 (sparc) or 117172-11 (x86) + # fixes the Solaris 9 bug where final pty output + # gets lost on close. + if showrev -p | $AWK 'BEGIN { e = 1 } +/Patch: 11717[12]/ { x = index($2, "-"); +if (substr($2, x + 1, length($2) - x) >= 11) +{ e = 0 } else { e = 1 } } +END { exit e; }'; then + krb5_cv_priocntl_hack=no + else + krb5_cv_priocntl_hack=yes + fi + fi + ;; +*) + krb5_cv_priocntl_hack=no + ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_priocntl_hack" >&5 +printf "%s\n" "$krb5_cv_priocntl_hack" >&6; } +if test "$krb5_cv_priocntl_hack" = yes; then + PRIOCNTL_HACK=1 +else + PRIOCNTL_HACK=0 +fi + + +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_PERL+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +printf "%s\n" "$PERL" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + +# lib/gssapi +ac_fn_c_check_header_compile "$LINENO" "xom.h" "ac_cv_header_xom_h" "$ac_includes_default" +if test "x$ac_cv_header_xom_h" = xyes +then : + + include_xom='awk '\''END{printf("%cinclude \n", 35);}'\'' < /dev/null' +else $as_nop + + include_xom='echo "/* no xom.h */"' +fi + + + + +# lib/rpc +### Check where struct rpcent is declared. + +# This is necessary to determine: +# 1. If /usr/include/netdb.h declares struct rpcent +# 2. If /usr/include/rpc/netdb.h declares struct rpcent + +# We have our own rpc/netdb.h, and if /usr/include/netdb.h includes +# rpc/netdb.h, then nastiness could happen. + +# Logic: If /usr/include/netdb.h declares struct rpcent, then check +# rpc/netdb.h. If /usr/include/rpc/netdb.h declares struct rpcent, +# then define STRUCT_RPCENT_IN_RPC_NETDB_H, otherwise do not. If +# neither netdb.h nor rpc/netdb.h declares struct rpcent, then define +# STRUCT_RPCENT_IN_RPC_NETDB_H anyway. + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking where struct rpcent is declared" >&5 +printf %s "checking where struct rpcent is declared... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main (void) +{ +struct rpcent e; + char c = e.r_name[0]; + int i = e.r_number; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + netdb_rpcent=yes +else $as_nop + netdb_rpcent=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +if test "$netdb_rpcent" = yes; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main (void) +{ +struct rpcent e; + char c = e.r_name[0]; + int i = e.r_number; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + rpc_netdb_rpcent=yes +else $as_nop + rpc_netdb_rpcent=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + if test "$rpc_netdb_rpcent" = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: rpc/netdb.h" >&5 +printf "%s\n" "rpc/netdb.h" >&6; } + rpcent_define='#define STRUCT_RPCENT_IN_RPC_NETDB_H' + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: netdb.h" >&5 +printf "%s\n" "netdb.h" >&6; } + fi +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: nowhere" >&5 +printf "%s\n" "nowhere" >&6; } + rpcent_define='#define STRUCT_RPCENT_IN_RPC_NETDB_H' +fi + + +ac_fn_c_check_header_compile "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_select_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_SELECT_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_time_h" = xyes +then : + printf "%s\n" "#define HAVE_SYS_TIME_H 1" >>confdefs.h + +fi +ac_fn_c_check_header_compile "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" +if test "x$ac_cv_header_unistd_h" = xyes +then : + printf "%s\n" "#define HAVE_UNISTD_H 1" >>confdefs.h + +fi + +if test $ac_cv_header_sys_select_h = yes; then + GSSRPC__SYS_SELECT_H='#include ' +else + GSSRPC__SYS_SELECT_H='/* #include */' +fi + +if test $ac_cv_header_sys_time_h = yes; then + GSSRPC__SYS_TIME_H='#include ' +else + GSSRPC__SYS_TIME_H='/* #include */' +fi + +if test $ac_cv_header_unistd_h = yes; then + GSSRPC__UNISTD_H='#include ' +else + GSSRPC__UNISTD_H='/* #include */' +fi + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for MAXHOSTNAMELEN in sys/param.h" >&5 +printf %s "checking for MAXHOSTNAMELEN in sys/param.h... " >&6; } +if test ${krb5_cv_header_sys_param_h_maxhostnamelen+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main (void) +{ +int i = MAXHOSTNAMELEN; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_header_sys_param_h_maxhostnamelen=yes +else $as_nop + krb5_cv_header_sys_param_h_maxhostnamelen=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_header_sys_param_h_maxhostnamelen" >&5 +printf "%s\n" "$krb5_cv_header_sys_param_h_maxhostnamelen" >&6; } +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for MAXHOSTNAMELEN in netdb.h" >&5 +printf %s "checking for MAXHOSTNAMELEN in netdb.h... " >&6; } +if test ${krb5_cv_header_netdb_h_maxhostnamelen+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main (void) +{ +int i = MAXHOSTNAMELEN; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_header_netdb_h_maxhostnamelen=yes +else $as_nop + krb5_cv_header_netdb_h_maxhostnamelen=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_header_netdb_h_maxhostnamelen" >&5 +printf "%s\n" "$krb5_cv_header_netdb_h_maxhostnamelen" >&6; } + +GSSRPC__SYS_PARAM_H='/* #include */' +GSSRPC__NETDB_H='/* #include */' +if test $krb5_cv_header_sys_param_h_maxhostnamelen = yes; then + GSSRPC__SYS_PARAM_H='#include ' +else + if test $krb5_cv_header_netdb_h_maxhostnamelen = yes; then + GSSRPC__NETDB_H='#include ' + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: can't find MAXHOSTNAMELEN definition; faking it" >&5 +printf "%s\n" "$as_me: WARNING: can't find MAXHOSTNAMELEN definition; faking it" >&2;} + fi +fi + + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for BSD type aliases" >&5 +printf %s "checking for BSD type aliases... " >&6; } +if test ${krb5_cv_type_bsdaliases+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #if HAVE_UNISTD_H + #include + #endif + +int +main (void) +{ +u_char c; + u_int i; + u_long l; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + krb5_cv_type_bsdaliases=yes +else $as_nop + krb5_cv_type_bsdaliases=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $krb5_cv_type_bsdaliases" >&5 +printf "%s\n" "$krb5_cv_type_bsdaliases" >&6; } +if test $krb5_cv_type_bsdaliases = yes; then + GSSRPC__BSD_TYPEALIASES='/* #undef GSSRPC__BSD_TYPEALIASES */' +else + GSSRPC__BSD_TYPEALIASES='#define GSSRPC__BSD_TYPEALIASES 1' +fi + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking return type of setrpcent" >&5 +printf %s "checking return type of setrpcent... " >&6; } +if test ${k5_cv_type_setrpcent+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + extern void setrpcent(); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + k5_cv_type_setrpcent=void +else $as_nop + k5_cv_type_setrpcent=int +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $k5_cv_type_setrpcent" >&5 +printf "%s\n" "$k5_cv_type_setrpcent" >&6; } + +printf "%s\n" "#define SETRPCENT_TYPE $k5_cv_type_setrpcent" >>confdefs.h + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking return type of endrpcent" >&5 +printf %s "checking return type of endrpcent... " >&6; } +if test ${k5_cv_type_endrpcent+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + extern void endrpcent(); +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + k5_cv_type_endrpcent=void +else $as_nop + k5_cv_type_endrpcent=int +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $k5_cv_type_endrpcent" >&5 +printf "%s\n" "$k5_cv_type_endrpcent" >&6; } + +printf "%s\n" "#define ENDRPCENT_TYPE $k5_cv_type_endrpcent" >>confdefs.h + +ac_config_files="$ac_config_files include/gssrpc/types.h:include/gssrpc/types.hin" + + +# for pkinit +# Check whether --enable-pkinit was given. +if test ${enable_pkinit+y} +then : + enableval=$enable_pkinit; +else $as_nop + enable_pkinit=try +fi + +if test "$enable_pkinit" = yes || test "$enable_pkinit" = try; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a recent enough OpenSSL" >&5 +printf %s "checking for a recent enough OpenSSL... " >&6; } +if test ${k5_cv_openssl_version_okay+y} +then : + printf %s "(cached) " >&6 +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#if OPENSSL_VERSION_NUMBER < 0x10000000L +# error openssl is too old, need 1.0.0 +#endif +int i = 1; + +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + k5_cv_openssl_version_okay=yes +else $as_nop + k5_cv_openssl_version_okay=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $k5_cv_openssl_version_okay" >&5 +printf "%s\n" "$k5_cv_openssl_version_okay" >&6; } + old_LIBS="$LIBS" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PKCS7_get_signer_info in -lcrypto" >&5 +printf %s "checking for PKCS7_get_signer_info in -lcrypto... " >&6; } +if test ${ac_cv_lib_crypto_PKCS7_get_signer_info+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char PKCS7_get_signer_info (); +int +main (void) +{ +return PKCS7_get_signer_info (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_crypto_PKCS7_get_signer_info=yes +else $as_nop + ac_cv_lib_crypto_PKCS7_get_signer_info=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_PKCS7_get_signer_info" >&5 +printf "%s\n" "$ac_cv_lib_crypto_PKCS7_get_signer_info" >&6; } +if test "x$ac_cv_lib_crypto_PKCS7_get_signer_info" = xyes +then : + printf "%s\n" "#define HAVE_LIBCRYPTO 1" >>confdefs.h + + LIBS="-lcrypto $LIBS" + +fi + + ac_fn_c_check_func "$LINENO" "EVP_PKEY_get_bn_param" "ac_cv_func_EVP_PKEY_get_bn_param" +if test "x$ac_cv_func_EVP_PKEY_get_bn_param" = xyes +then : + printf "%s\n" "#define HAVE_EVP_PKEY_GET_BN_PARAM 1" >>confdefs.h + +fi + + LIBS="$old_LIBS" +fi +if test "$k5_cv_openssl_version_okay" = yes && (test "$enable_pkinit" = yes || test "$enable_pkinit" = try); then + ac_config_files="$ac_config_files plugins/preauth/pkinit/Makefile:$srcdir/./config/pre.in:plugins/preauth/pkinit/Makefile.in:plugins/preauth/pkinit/deps:$srcdir/./config/post.in" + + + + ac_config_files="$ac_config_files tests/softpkcs11/Makefile:$srcdir/./config/pre.in:tests/softpkcs11/Makefile.in:tests/softpkcs11/deps:$srcdir/./config/post.in" + + + + PKINIT=yes +elif test "$k5_cv_openssl_version_okay" = no && test "$enable_pkinit" = yes; then + as_fn_error $? "Version of OpenSSL is too old; cannot enable PKINIT." "$LINENO" 5 +else + +printf "%s\n" "#define DISABLE_PKINIT 1" >>confdefs.h + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Disabling PKINIT support." >&5 +printf "%s\n" "$as_me: Disabling PKINIT support." >&6;} + PKINIT=no +fi + + +# for lib/apputils +ac_fn_c_check_func "$LINENO" "daemon" "ac_cv_func_daemon" +if test "x$ac_cv_func_daemon" = xyes +then : + printf "%s\n" "#define HAVE_DAEMON 1" >>confdefs.h + +else $as_nop + case " $LIBOBJS " in + *" daemon.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS daemon.$ac_objext" + ;; +esac + +fi + + +# For Python tests. Python version 3.2.4 is required as prior +# versions do not accept string input to subprocess.Popen.communicate +# when universal_newlines is set. +PYTHON_MINVERSION=3.2.4 + +# Extract the first word of "python3", so it can be a program name with args. +set dummy python3; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_PYTHON+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$PYTHON"; then + ac_cv_prog_PYTHON="$PYTHON" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_PYTHON="python3" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PYTHON=$ac_cv_prog_PYTHON +if test -n "$PYTHON"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 +printf "%s\n" "$PYTHON" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +if test x"$PYTHON" = x; then + # Extract the first word of "python", so it can be a program name with args. +set dummy python; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_PYTHON+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$PYTHON"; then + ac_cv_prog_PYTHON="$PYTHON" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_PYTHON="python" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PYTHON=$ac_cv_prog_PYTHON +if test -n "$PYTHON"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 +printf "%s\n" "$PYTHON" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +HAVE_PYTHON=no +if test x"$PYTHON" != x; then + wantver="(sys.hexversion >= 0x30204F0)" + if "$PYTHON" -c "import sys; sys.exit(not $wantver and 1 or 0)"; then + HAVE_PYTHON=yes + fi +fi + + +# For cmocka tests. +CMOCKA_LIBS= +HAVE_CMOCKA=no +HAVE_CMOCKA_H=no +HAVE_CMOCKA_LIB=no +ac_fn_c_check_header_compile "$LINENO" "cmocka.h" "ac_cv_header_cmocka_h" " +#include +#include +#include +" +if test "x$ac_cv_header_cmocka_h" = xyes +then : + HAVE_CMOCKA_H=yes +else $as_nop + : +fi + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _cmocka_run_group_tests in -lcmocka" >&5 +printf %s "checking for _cmocka_run_group_tests in -lcmocka... " >&6; } +if test ${ac_cv_lib_cmocka__cmocka_run_group_tests+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcmocka $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char _cmocka_run_group_tests (); +int +main (void) +{ +return _cmocka_run_group_tests (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_cmocka__cmocka_run_group_tests=yes +else $as_nop + ac_cv_lib_cmocka__cmocka_run_group_tests=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cmocka__cmocka_run_group_tests" >&5 +printf "%s\n" "$ac_cv_lib_cmocka__cmocka_run_group_tests" >&6; } +if test "x$ac_cv_lib_cmocka__cmocka_run_group_tests" = xyes +then : + HAVE_CMOCKA_LIB=yes +fi + +if test "$HAVE_CMOCKA_LIB" = yes && test "$HAVE_CMOCKA_H" = yes; then + HAVE_CMOCKA=yes + CMOCKA_LIBS='-lcmocka' + +printf "%s\n" "#define HAVE_CMOCKA 1" >>confdefs.h + +fi + + + +# For URI lookup tests. Requires resolv_wrapper >= 1.1.5 for URI +# support. +HAVE_RESOLV_WRAPPER=0 +if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"resolv_wrapper >= 1.1.5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "resolv_wrapper >= 1.1.5") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + HAVE_RESOLV_WRAPPER=1 +fi + + +# for plugins/kdb/db2 + +# AIX is unusual in that it wants all symbols resolved at link time +# Fortunately, it will allow us to link the kdb library now, even if +# it is linked again later. +case $krb5_cv_host in +*-*-aix*) + DB_EXTRA_LIBS=-ldb + ;; +*) + DB_EXTRA_LIBS= + ;; +esac + + + + +# Warn about possible thread safety issues. These functions have all +# been checked for previously. +tsfuncs="getpwnam_r getpwuid_r gethostbyname_r getservbyname_r gmtime_r localtime_r" +if test "$enable_thread_support" = yes; then + tsmissing="" + for ts in $tsfuncs; do + if eval "test \"\${ac_cv_func_$ts}\" != yes"; then + tsmissing="$tsmissing $ts" + fi + done + if test "$ac_cv_func_res_nsearch/$ac_cv_lib_resolv_res_nsearch" = "no/no"; then + tsmissing="$tsmissing res_nsearch" + fi + if test "$tsmissing" != ""; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Some functions that are needed for library thread" >&5 +printf "%s\n" "$as_me: WARNING: Some functions that are needed for library thread" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: safety appear to be missing." >&5 +printf "%s\n" "$as_me: WARNING: safety appear to be missing." >&2;} + for ts in $tsmissing; do + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: missing thread-safe function: $ts" >&5 +printf "%s\n" "$as_me: WARNING: missing thread-safe function: $ts" >&2;} + done + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Without these functions, the installed libraries" >&5 +printf "%s\n" "$as_me: WARNING: Without these functions, the installed libraries" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: may not be thread-safe." >&5 +printf "%s\n" "$as_me: WARNING: may not be thread-safe." >&2;} + fi # tsmissing not empty +fi # enable_thread_support + +# Sadly, we seem to have accidentally committed ourselves in 1.4 to +# an ABI that includes the existence of libkrb5support.0 even +# though random apps should never use anything from it. And on +# the Mac, to which that didn't apply, we can't use major version 0. + +case $krb5_cv_host in +*-*-darwin* | *-*-rhapsody*) SUPPORTLIB_MAJOR=1 ;; +*) SUPPORTLIB_MAJOR=0 ;; +esac + + + +if test "$COM_ERR_VERSION" = k5 ; then + ac_config_files="$ac_config_files util/et/Makefile:$srcdir/./config/pre.in:util/et/Makefile.in:util/et/deps:$srcdir/./config/post.in" + + + +fi +if test "$SS_VERSION" = k5 ; then + ac_config_files="$ac_config_files util/ss/Makefile:$srcdir/./config/pre.in:util/ss/Makefile.in:util/ss/deps:$srcdir/./config/post.in" + + + +fi + + +ldap_plugin_dir="" +ldap_lib="" +if test -n "$OPENLDAP_PLUGIN"; then + for ac_header in ldap.h lber.h +do : + as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes" +then : + cat >>confdefs.h <<_ACEOF +#define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + : +else $as_nop + as_fn_error $? "$ac_header not found" "$LINENO" 5 +fi + +done + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ldap_str2dn in -lldap" >&5 +printf %s "checking for ldap_str2dn in -lldap... " >&6; } +if test ${ac_cv_lib_ldap_ldap_str2dn+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lldap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char ldap_str2dn (); +int +main (void) +{ +return ldap_str2dn (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_ldap_ldap_str2dn=yes +else $as_nop + ac_cv_lib_ldap_ldap_str2dn=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ldap_str2dn" >&5 +printf "%s\n" "$ac_cv_lib_ldap_ldap_str2dn" >&6; } +if test "x$ac_cv_lib_ldap_ldap_str2dn" = xyes +then : + : +else $as_nop + as_fn_error $? "libldap not found or missing ldap_str2dn" "$LINENO" 5 +fi + + + BER_OKAY=0 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ber_init in -lldap" >&5 +printf %s "checking for ber_init in -lldap... " >&6; } +if test ${ac_cv_lib_ldap_ber_init+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lldap $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char ber_init (); +int +main (void) +{ +return ber_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_ldap_ber_init=yes +else $as_nop + ac_cv_lib_ldap_ber_init=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ldap_ber_init" >&5 +printf "%s\n" "$ac_cv_lib_ldap_ber_init" >&6; } +if test "x$ac_cv_lib_ldap_ber_init" = xyes +then : + BER_OKAY=1 +fi + + if test "$BER_OKAY" = "1"; then + LDAP_LIBS='-lldap' + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ber_init in -llber" >&5 +printf %s "checking for ber_init in -llber... " >&6; } +if test ${ac_cv_lib_lber_ber_init+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-llber $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char ber_init (); +int +main (void) +{ +return ber_init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_lber_ber_init=yes +else $as_nop + ac_cv_lib_lber_ber_init=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lber_ber_init" >&5 +printf "%s\n" "$ac_cv_lib_lber_ber_init" >&6; } +if test "x$ac_cv_lib_lber_ber_init" = xyes +then : + BER_OKAY=1 +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: libber not found" >&5 +printf "%s\n" "$as_me: WARNING: libber not found" >&2;} +fi + + if test "$BER_OKAY" = "1"; then + LDAP_LIBS='-lldap -llber' + else + as_fn_error $? "\"BER library missing - cannot build LDAP database module\"" "$LINENO" 5 + fi + fi + +printf "%s\n" "#define ENABLE_LDAP 1" >>confdefs.h + + + + for ac_header in sasl/sasl.h +do : + ac_fn_c_check_header_compile "$LINENO" "sasl/sasl.h" "ac_cv_header_sasl_sasl_h" "$ac_includes_default" +if test "x$ac_cv_header_sasl_sasl_h" = xyes +then : + printf "%s\n" "#define HAVE_SASL_SASL_H 1" >>confdefs.h + HAVE_SASL=yes +else $as_nop + HAVE_SASL=no +fi + +done + + if test "$HAVE_SASL" = no; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: not building LDAP SASL support" >&5 +printf "%s\n" "$as_me: WARNING: not building LDAP SASL support" >&2;} + fi + + ac_config_files="$ac_config_files plugins/kdb/ldap/Makefile:$srcdir/./config/pre.in:plugins/kdb/ldap/Makefile.in:plugins/kdb/ldap/deps:$srcdir/./config/post.in" + + + + ac_config_files="$ac_config_files plugins/kdb/ldap/ldap_util/Makefile:$srcdir/./config/pre.in:plugins/kdb/ldap/ldap_util/Makefile.in:plugins/kdb/ldap/ldap_util/deps:$srcdir/./config/post.in" + + + + ac_config_files="$ac_config_files plugins/kdb/ldap/libkdb_ldap/Makefile:$srcdir/./config/pre.in:plugins/kdb/ldap/libkdb_ldap/Makefile.in:plugins/kdb/ldap/libkdb_ldap/deps:$srcdir/./config/post.in" + + + + ldap_plugin_dir='plugins/kdb/ldap plugins/kdb/ldap/ldap_util' + LDAP=yes +else + LDAP=no +fi + + +# This check is for plugins/preauth/securid_sam2 +sam2_plugin="" +old_CFLAGS=$CFLAGS +CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SD_Init in -laceclnt" >&5 +printf %s "checking for SD_Init in -laceclnt... " >&6; } +if test ${ac_cv_lib_aceclnt_SD_Init+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-laceclnt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char SD_Init (); +int +main (void) +{ +return SD_Init (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_aceclnt_SD_Init=yes +else $as_nop + ac_cv_lib_aceclnt_SD_Init=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_aceclnt_SD_Init" >&5 +printf "%s\n" "$ac_cv_lib_aceclnt_SD_Init" >&6; } +if test "x$ac_cv_lib_aceclnt_SD_Init" = xyes +then : + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Enabling RSA securID support" >&5 +printf "%s\n" "$as_me: Enabling RSA securID support" >&6;} + ac_config_files="$ac_config_files plugins/preauth/securid_sam2/Makefile:$srcdir/./config/pre.in:plugins/preauth/securid_sam2/Makefile.in:plugins/preauth/securid_sam2/deps:$srcdir/./config/post.in" + + + + sam2_plugin=plugins/preauth/securid_sam2 + +fi + + +CFLAGS=$old_CFLAGS + +lmdb_plugin_dir="" +HAVE_LMDB=no + +# Check whether --with-lmdb was given. +if test ${with_lmdb+y} +then : + withval=$with_lmdb; +else $as_nop + withval=auto +fi + +if test "$withval" = auto -o "$withval" = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for mdb_env_create in -llmdb" >&5 +printf %s "checking for mdb_env_create in -llmdb... " >&6; } +if test ${ac_cv_lib_lmdb_mdb_env_create+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-llmdb $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +char mdb_env_create (); +int +main (void) +{ +return mdb_env_create (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_lmdb_mdb_env_create=yes +else $as_nop + ac_cv_lib_lmdb_mdb_env_create=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lmdb_mdb_env_create" >&5 +printf "%s\n" "$ac_cv_lib_lmdb_mdb_env_create" >&6; } +if test "x$ac_cv_lib_lmdb_mdb_env_create" = xyes +then : + have_lmdb=true +else $as_nop + have_lmdb=false +fi + + if test "$have_lmdb" = true; then + LMDB_LIBS=-llmdb + HAVE_LMDB=yes + lmdb_plugin_dir='plugins/kdb/lmdb' + ac_config_files="$ac_config_files plugins/kdb/lmdb/Makefile:$srcdir/./config/pre.in:plugins/kdb/lmdb/Makefile.in:plugins/kdb/lmdb/deps:$srcdir/./config/post.in" + + + + elif test "$withval" = yes; then + as_fn_error $? "liblmdb not found" "$LINENO" 5 + fi +fi + + + + +# Kludge for simple server --- FIXME is this the best way to do this? + +if test "$ac_cv_lib_socket" = "yes" -a "$ac_cv_lib_nsl" = "yes"; then + +printf "%s\n" "#define BROKEN_STREAMS_SOCKETS 1" >>confdefs.h + +fi + +# Compile with libedit support in ss by default if available. Compile +# with readline only if asked, to avoid a default GPL dependency. + +# Check whether --with-libedit was given. +if test ${with_libedit+y} +then : + withval=$with_libedit; +else $as_nop + with_libedit=default +fi + + +# Check whether --with-readline was given. +if test ${with_readline+y} +then : + withval=$with_readline; +else $as_nop + with_readline=no +fi + +if test "x$with_readline" = xyes; then + with_libedit=no +fi +RL_CFLAGS= +RL_LIBS= +if test "x$with_libedit" != xno; then + +pkg_failed=no +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libedit" >&5 +printf %s "checking for libedit... " >&6; } + +if test -n "$LIBEDIT_CFLAGS"; then + pkg_cv_LIBEDIT_CFLAGS="$LIBEDIT_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libedit\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libedit") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBEDIT_CFLAGS=`$PKG_CONFIG --cflags "libedit" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$LIBEDIT_LIBS"; then + pkg_cv_LIBEDIT_LIBS="$LIBEDIT_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libedit\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libedit") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_LIBEDIT_LIBS=`$PKG_CONFIG --libs "libedit" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + LIBEDIT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libedit" 2>&1` + else + LIBEDIT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libedit" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$LIBEDIT_PKG_ERRORS" >&5 + + have_libedit=no +elif test $pkg_failed = untried; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + have_libedit=no +else + LIBEDIT_CFLAGS=$pkg_cv_LIBEDIT_CFLAGS + LIBEDIT_LIBS=$pkg_cv_LIBEDIT_LIBS + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + have_libedit=yes +fi + if test "x$have_libedit" = xyes; then + RL_CFLAGS=$LIBEDIT_CFLAGS + RL_LIBS=$LIBEDIT_LIBS + +printf "%s\n" "#define HAVE_LIBEDIT 1" >>confdefs.h + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Using libedit for readline support" >&5 +printf "%s\n" "$as_me: Using libedit for readline support" >&6;} + elif test "x$with_libedit" = xyes; then + # We were explicitly asked for libedit and couldn't find it. + as_fn_error $? "Could not detect libedit with pkg-config" "$LINENO" 5 + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Not using any readline support" >&5 +printf "%s\n" "$as_me: Not using any readline support" >&6;} + fi +elif test "x$with_readline" = xyes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Using GNU Readline" >&5 +printf "%s\n" "$as_me: Using GNU Readline" >&6;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lreadline" >&5 +printf %s "checking for main in -lreadline... " >&6; } +if test ${ac_cv_lib_readline_main+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lreadline $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main (void) +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_lib_readline_main=yes +else $as_nop + ac_cv_lib_readline_main=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_main" >&5 +printf "%s\n" "$ac_cv_lib_readline_main" >&6; } +if test "x$ac_cv_lib_readline_main" = xyes +then : + : +else $as_nop + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Cannot find readline library. +See \`config.log' for more details" "$LINENO" 5; } +fi + + +printf "%s\n" "#define HAVE_READLINE 1" >>confdefs.h + + RL_LIBS='-lreadline' +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Not using any readline support" >&5 +printf "%s\n" "Not using any readline support" >&6; } +fi + + + + +# Check whether --with-system-verto was given. +if test ${with_system_verto+y} +then : + withval=$with_system_verto; +else $as_nop + with_system_verto=default +fi + +VERTO_VERSION=k5 +if test "x$with_system_verto" != xno; then + +pkg_failed=no +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libverto" >&5 +printf %s "checking for libverto... " >&6; } + +if test -n "$VERTO_CFLAGS"; then + pkg_cv_VERTO_CFLAGS="$VERTO_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libverto\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libverto") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_VERTO_CFLAGS=`$PKG_CONFIG --cflags "libverto" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$VERTO_LIBS"; then + pkg_cv_VERTO_LIBS="$VERTO_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libverto\""; } >&5 + ($PKG_CONFIG --exists --print-errors "libverto") 2>&5 + ac_status=$? + printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_VERTO_LIBS=`$PKG_CONFIG --libs "libverto" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + VERTO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libverto" 2>&1` + else + VERTO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libverto" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$VERTO_PKG_ERRORS" >&5 + + have_sysverto=no +elif test $pkg_failed = untried; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + have_sysverto=no +else + VERTO_CFLAGS=$pkg_cv_VERTO_CFLAGS + VERTO_LIBS=$pkg_cv_VERTO_LIBS + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + have_sysverto=yes +fi + if test "x$have_sysverto" = xyes; then + VERTO_VERSION=sys + elif test "x$with_system_verto" = xyes; then + as_fn_error $? "cannot detect system libverto" "$LINENO" 5 + fi +fi +if test "x$VERTO_VERSION" = xsys; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Using system libverto" >&5 +printf "%s\n" "$as_me: Using system libverto" >&6;} +else + VERTO_CFLAGS= + VERTO_LIBS="-lverto" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Using built-in libverto" >&5 +printf "%s\n" "$as_me: Using built-in libverto" >&6;} +fi + + + + +# Extract the first word of "groff", so it can be a program name with args. +set dummy groff; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_GROFF+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $GROFF in + [\\/]* | ?:[\\/]*) + ac_cv_path_GROFF="$GROFF" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_GROFF="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +GROFF=$ac_cv_path_GROFF +if test -n "$GROFF"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GROFF" >&5 +printf "%s\n" "$GROFF" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + +# Make localedir work in autoconf 2.5x. +if test "${localedir+set}" != set; then + localedir='$(datadir)/locale' +fi + + +# Determine the default macOS ccache type and whether to build the KCM +# Mach RPC support. +MACOS_FRAMEWORK= +case $host in +*-*-darwin[0-9].* | *-*-darwin10.*) + # Use the normal default cache type for macOS 10.6 (Darwin 10) and + # prior. Build the KCM Mach RPC support. + OSX=osx + ;; +*-*-darwin*) + # macOS 10.6 (Darwin 11) uses the KCM type by default. macOS 11 + # (Darwin 20) uses an xpc-based cache type called XCACHE by default. + # We can access either of these collections via a macos-specific + # implementation of the API cache type. Build the KCM Mach RPC + # support. + OSX=osx + macos_defccname=API: + MACOS_FRAMEWORK="-framework Kerberos" + ;; +*) + # This is not macOS; do not build the Mach RPC support and use the + # normal default cache type. + OSX=no + ;; +esac +if test "$macos_defccname" = API:; then + +printf "%s\n" "#define USE_CCAPI_MACOS 1" >>confdefs.h + +fi + + + +# Build-time default ccache, keytab, and client keytab names. These +# can be given as variable arguments DEFCCNAME, DEFKTNAME, and +# DEFCKTNAME. Otherwise, we try to get the OS defaults from +# krb5-config if we can, or fall back to hardcoded defaults. + + + + +# Check whether --with-krb5-config was given. +if test ${with_krb5_config+y} +then : + withval=$with_krb5_config; +else $as_nop + with_krb5_config=krb5-config +fi + +if test "x$with_krb5_config" != xno; then + if test "x$with_krb5_config" = xyes; then + with_krb5_config=krb5-config + fi + if $with_krb5_config --help 2>&1 | grep defccname >/dev/null; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Using $with_krb5_config for build defaults" >&5 +printf "%s\n" "$as_me: Using $with_krb5_config for build defaults" >&6;} + : "${DEFCCNAME=`$with_krb5_config --defccname`}" + : "${DEFKTNAME=`$with_krb5_config --defktname`}" + : "${DEFCKTNAME=`$with_krb5_config --defcktname`}" + fi +fi +if test "${DEFCCNAME+set}" != set; then + if test "${macos_defccname+set}" = set; then + DEFCCNAME=$macos_defccname + else + DEFCCNAME=FILE:/tmp/krb5cc_%{uid} + fi +fi +if test "${DEFKTNAME+set}" != set; then + DEFKTNAME=FILE:/etc/krb5.keytab +fi +if test "${DEFCKTNAME+set}" != set; then + _lcl_receval="$localstatedir" +exp_localstatedir=`(test "x$prefix" = xNONE && prefix="$ac_default_prefix" + test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" + _lcl_receval_old='' + while test "$_lcl_receval_old" != "$_lcl_receval"; do + _lcl_receval_old="$_lcl_receval" + eval _lcl_receval="\"$_lcl_receval\"" + done + echo "$_lcl_receval")` + DEFCKTNAME=FILE:$exp_localstatedir/krb5/user/%{euid}/client.keytab +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Default ccache name: $DEFCCNAME" >&5 +printf "%s\n" "$as_me: Default ccache name: $DEFCCNAME" >&6;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Default keytab name: $DEFKTNAME" >&5 +printf "%s\n" "$as_me: Default keytab name: $DEFKTNAME" >&6;} +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Default client keytab name: $DEFCKTNAME" >&5 +printf "%s\n" "$as_me: Default client keytab name: $DEFCKTNAME" >&6;} + +printf "%s\n" "#define DEFCCNAME \"$DEFCCNAME\"" >>confdefs.h + + +printf "%s\n" "#define DEFKTNAME \"$DEFKTNAME\"" >>confdefs.h + + +printf "%s\n" "#define DEFCKTNAME \"$DEFCKTNAME\"" >>confdefs.h + + + +if test "${PKCS11_MODNAME+set}" != set; then + PKCS11_MODNAME=opensc-pkcs11.so +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: Default PKCS11 module name: $PKCS11_MODNAME" >&5 +printf "%s\n" "$as_me: Default PKCS11 module name: $PKCS11_MODNAME" >&6;} + +printf "%s\n" "#define PKCS11_MODNAME \"$PKCS11_MODNAME\"" >>confdefs.h + + +ac_config_files="$ac_config_files build-tools/krb5-config" + +ac_config_files="$ac_config_files build-tools/kadm-server.pc build-tools/kadm-client.pc build-tools/kdb.pc build-tools/krb5.pc build-tools/krb5-gssapi.pc build-tools/mit-krb5.pc build-tools/mit-krb5-gssapi.pc build-tools/gssrpc.pc" + + + ac_config_files="$ac_config_files ./Makefile:$srcdir/./config/pre.in:./Makefile.in:./deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files util/Makefile:$srcdir/./config/pre.in:util/Makefile.in:util/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files util/support/Makefile:$srcdir/./config/pre.in:util/support/Makefile.in:util/support/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files util/profile/Makefile:$srcdir/./config/pre.in:util/profile/Makefile.in:util/profile/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files util/profile/testmod/Makefile:$srcdir/./config/pre.in:util/profile/testmod/Makefile.in:util/profile/testmod/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files util/verto/Makefile:$srcdir/./config/pre.in:util/verto/Makefile.in:util/verto/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/Makefile:$srcdir/./config/pre.in:lib/Makefile.in:lib/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/kdb/Makefile:$srcdir/./config/pre.in:lib/kdb/Makefile.in:lib/kdb/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/Makefile:$srcdir/./config/pre.in:lib/crypto/Makefile.in:lib/crypto/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/krb/Makefile:$srcdir/./config/pre.in:lib/crypto/krb/Makefile.in:lib/crypto/krb/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/crypto_tests/Makefile:$srcdir/./config/pre.in:lib/crypto/crypto_tests/Makefile.in:lib/crypto/crypto_tests/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/builtin/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/Makefile.in:lib/crypto/builtin/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/builtin/des/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/des/Makefile.in:lib/crypto/builtin/des/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/builtin/aes/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/aes/Makefile.in:lib/crypto/builtin/aes/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/builtin/camellia/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/camellia/Makefile.in:lib/crypto/builtin/camellia/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/builtin/md4/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/md4/Makefile.in:lib/crypto/builtin/md4/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/builtin/md5/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/md5/Makefile.in:lib/crypto/builtin/md5/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/builtin/sha1/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/sha1/Makefile.in:lib/crypto/builtin/sha1/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/builtin/sha2/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/sha2/Makefile.in:lib/crypto/builtin/sha2/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/builtin/enc_provider/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/enc_provider/Makefile.in:lib/crypto/builtin/enc_provider/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/builtin/hash_provider/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/hash_provider/Makefile.in:lib/crypto/builtin/hash_provider/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/openssl/Makefile:$srcdir/./config/pre.in:lib/crypto/openssl/Makefile.in:lib/crypto/openssl/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/openssl/des/Makefile:$srcdir/./config/pre.in:lib/crypto/openssl/des/Makefile.in:lib/crypto/openssl/des/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/openssl/enc_provider/Makefile:$srcdir/./config/pre.in:lib/crypto/openssl/enc_provider/Makefile.in:lib/crypto/openssl/enc_provider/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/crypto/openssl/hash_provider/Makefile:$srcdir/./config/pre.in:lib/crypto/openssl/hash_provider/Makefile.in:lib/crypto/openssl/hash_provider/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/krb5/Makefile:$srcdir/./config/pre.in:lib/krb5/Makefile.in:lib/krb5/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/krb5/error_tables/Makefile:$srcdir/./config/pre.in:lib/krb5/error_tables/Makefile.in:lib/krb5/error_tables/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/krb5/asn.1/Makefile:$srcdir/./config/pre.in:lib/krb5/asn.1/Makefile.in:lib/krb5/asn.1/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/krb5/ccache/Makefile:$srcdir/./config/pre.in:lib/krb5/ccache/Makefile.in:lib/krb5/ccache/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/krb5/keytab/Makefile:$srcdir/./config/pre.in:lib/krb5/keytab/Makefile.in:lib/krb5/keytab/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/krb5/krb/Makefile:$srcdir/./config/pre.in:lib/krb5/krb/Makefile.in:lib/krb5/krb/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/krb5/rcache/Makefile:$srcdir/./config/pre.in:lib/krb5/rcache/Makefile.in:lib/krb5/rcache/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/krb5/os/Makefile:$srcdir/./config/pre.in:lib/krb5/os/Makefile.in:lib/krb5/os/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/krb5/unicode/Makefile:$srcdir/./config/pre.in:lib/krb5/unicode/Makefile.in:lib/krb5/unicode/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/gssapi/Makefile:$srcdir/./config/pre.in:lib/gssapi/Makefile.in:lib/gssapi/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/gssapi/generic/Makefile:$srcdir/./config/pre.in:lib/gssapi/generic/Makefile.in:lib/gssapi/generic/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/gssapi/krb5/Makefile:$srcdir/./config/pre.in:lib/gssapi/krb5/Makefile.in:lib/gssapi/krb5/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/gssapi/spnego/Makefile:$srcdir/./config/pre.in:lib/gssapi/spnego/Makefile.in:lib/gssapi/spnego/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/gssapi/mechglue/Makefile:$srcdir/./config/pre.in:lib/gssapi/mechglue/Makefile.in:lib/gssapi/mechglue/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/rpc/Makefile:$srcdir/./config/pre.in:lib/rpc/Makefile.in:lib/rpc/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/rpc/unit-test/Makefile:$srcdir/./config/pre.in:lib/rpc/unit-test/Makefile.in:lib/rpc/unit-test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/kadm5/Makefile:$srcdir/./config/pre.in:lib/kadm5/Makefile.in:lib/kadm5/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/kadm5/clnt/Makefile:$srcdir/./config/pre.in:lib/kadm5/clnt/Makefile.in:lib/kadm5/clnt/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/kadm5/srv/Makefile:$srcdir/./config/pre.in:lib/kadm5/srv/Makefile.in:lib/kadm5/srv/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/krad/Makefile:$srcdir/./config/pre.in:lib/krad/Makefile.in:lib/krad/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files lib/apputils/Makefile:$srcdir/./config/pre.in:lib/apputils/Makefile.in:lib/apputils/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files kdc/Makefile:$srcdir/./config/pre.in:kdc/Makefile.in:kdc/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files kprop/Makefile:$srcdir/./config/pre.in:kprop/Makefile.in:kprop/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files config-files/Makefile:$srcdir/./config/pre.in:config-files/Makefile.in:config-files/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files build-tools/Makefile:$srcdir/./config/pre.in:build-tools/Makefile.in:build-tools/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files man/Makefile:$srcdir/./config/pre.in:man/Makefile.in:man/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files doc/Makefile:$srcdir/./config/pre.in:doc/Makefile.in:doc/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files include/Makefile:$srcdir/./config/pre.in:include/Makefile.in:include/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/certauth/test/Makefile:$srcdir/./config/pre.in:plugins/certauth/test/Makefile.in:plugins/certauth/test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/gssapi/negoextest/Makefile:$srcdir/./config/pre.in:plugins/gssapi/negoextest/Makefile.in:plugins/gssapi/negoextest/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/hostrealm/test/Makefile:$srcdir/./config/pre.in:plugins/hostrealm/test/Makefile.in:plugins/hostrealm/test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/localauth/test/Makefile:$srcdir/./config/pre.in:plugins/localauth/test/Makefile.in:plugins/localauth/test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kadm5_hook/test/Makefile:$srcdir/./config/pre.in:plugins/kadm5_hook/test/Makefile.in:plugins/kadm5_hook/test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kadm5_auth/test/Makefile:$srcdir/./config/pre.in:plugins/kadm5_auth/test/Makefile.in:plugins/kadm5_auth/test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/pwqual/test/Makefile:$srcdir/./config/pre.in:plugins/pwqual/test/Makefile.in:plugins/pwqual/test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/audit/Makefile:$srcdir/./config/pre.in:plugins/audit/Makefile.in:plugins/audit/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/audit/test/Makefile:$srcdir/./config/pre.in:plugins/audit/test/Makefile.in:plugins/audit/test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kdb/db2/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/Makefile.in:plugins/kdb/db2/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kdb/db2/libdb2/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/Makefile.in:plugins/kdb/db2/libdb2/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kdb/db2/libdb2/hash/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/hash/Makefile.in:plugins/kdb/db2/libdb2/hash/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kdb/db2/libdb2/btree/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/btree/Makefile.in:plugins/kdb/db2/libdb2/btree/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kdb/db2/libdb2/db/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/db/Makefile.in:plugins/kdb/db2/libdb2/db/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kdb/db2/libdb2/mpool/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/mpool/Makefile.in:plugins/kdb/db2/libdb2/mpool/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kdb/db2/libdb2/recno/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/recno/Makefile.in:plugins/kdb/db2/libdb2/recno/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kdb/db2/libdb2/test/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/test/Makefile.in:plugins/kdb/db2/libdb2/test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kdb/test/Makefile:$srcdir/./config/pre.in:plugins/kdb/test/Makefile.in:plugins/kdb/test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/kdcpolicy/test/Makefile:$srcdir/./config/pre.in:plugins/kdcpolicy/test/Makefile.in:plugins/kdcpolicy/test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/preauth/otp/Makefile:$srcdir/./config/pre.in:plugins/preauth/otp/Makefile.in:plugins/preauth/otp/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/preauth/spake/Makefile:$srcdir/./config/pre.in:plugins/preauth/spake/Makefile.in:plugins/preauth/spake/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/preauth/test/Makefile:$srcdir/./config/pre.in:plugins/preauth/test/Makefile.in:plugins/preauth/test/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/authdata/greet_client/Makefile:$srcdir/./config/pre.in:plugins/authdata/greet_client/Makefile.in:plugins/authdata/greet_client/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/authdata/greet_server/Makefile:$srcdir/./config/pre.in:plugins/authdata/greet_server/Makefile.in:plugins/authdata/greet_server/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files plugins/tls/k5tls/Makefile:$srcdir/./config/pre.in:plugins/tls/k5tls/Makefile.in:plugins/tls/k5tls/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files clients/Makefile:$srcdir/./config/pre.in:clients/Makefile.in:clients/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files clients/klist/Makefile:$srcdir/./config/pre.in:clients/klist/Makefile.in:clients/klist/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files clients/kinit/Makefile:$srcdir/./config/pre.in:clients/kinit/Makefile.in:clients/kinit/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files clients/kvno/Makefile:$srcdir/./config/pre.in:clients/kvno/Makefile.in:clients/kvno/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files clients/kdestroy/Makefile:$srcdir/./config/pre.in:clients/kdestroy/Makefile.in:clients/kdestroy/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files clients/kpasswd/Makefile:$srcdir/./config/pre.in:clients/kpasswd/Makefile.in:clients/kpasswd/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files clients/ksu/Makefile:$srcdir/./config/pre.in:clients/ksu/Makefile.in:clients/ksu/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files clients/kswitch/Makefile:$srcdir/./config/pre.in:clients/kswitch/Makefile.in:clients/kswitch/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files kadmin/Makefile:$srcdir/./config/pre.in:kadmin/Makefile.in:kadmin/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files kadmin/cli/Makefile:$srcdir/./config/pre.in:kadmin/cli/Makefile.in:kadmin/cli/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files kadmin/dbutil/Makefile:$srcdir/./config/pre.in:kadmin/dbutil/Makefile.in:kadmin/dbutil/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files kadmin/ktutil/Makefile:$srcdir/./config/pre.in:kadmin/ktutil/Makefile.in:kadmin/ktutil/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files kadmin/server/Makefile:$srcdir/./config/pre.in:kadmin/server/Makefile.in:kadmin/server/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files appl/Makefile:$srcdir/./config/pre.in:appl/Makefile.in:appl/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files appl/sample/Makefile:$srcdir/./config/pre.in:appl/sample/Makefile.in:appl/sample/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files appl/sample/sclient/Makefile:$srcdir/./config/pre.in:appl/sample/sclient/Makefile.in:appl/sample/sclient/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files appl/sample/sserver/Makefile:$srcdir/./config/pre.in:appl/sample/sserver/Makefile.in:appl/sample/sserver/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files appl/simple/Makefile:$srcdir/./config/pre.in:appl/simple/Makefile.in:appl/simple/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files appl/simple/client/Makefile:$srcdir/./config/pre.in:appl/simple/client/Makefile.in:appl/simple/client/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files appl/simple/server/Makefile:$srcdir/./config/pre.in:appl/simple/server/Makefile.in:appl/simple/server/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files appl/gss-sample/Makefile:$srcdir/./config/pre.in:appl/gss-sample/Makefile.in:appl/gss-sample/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files appl/user_user/Makefile:$srcdir/./config/pre.in:appl/user_user/Makefile.in:appl/user_user/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files tests/Makefile:$srcdir/./config/pre.in:tests/Makefile.in:tests/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files tests/asn.1/Makefile:$srcdir/./config/pre.in:tests/asn.1/Makefile.in:tests/asn.1/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files tests/create/Makefile:$srcdir/./config/pre.in:tests/create/Makefile.in:tests/create/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files tests/hammer/Makefile:$srcdir/./config/pre.in:tests/hammer/Makefile.in:tests/hammer/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files tests/verify/Makefile:$srcdir/./config/pre.in:tests/verify/Makefile.in:tests/verify/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files tests/gssapi/Makefile:$srcdir/./config/pre.in:tests/gssapi/Makefile.in:tests/gssapi/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files tests/threads/Makefile:$srcdir/./config/pre.in:tests/threads/Makefile.in:tests/threads/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files tests/shlib/Makefile:$srcdir/./config/pre.in:tests/shlib/Makefile.in:tests/shlib/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files tests/gss-threads/Makefile:$srcdir/./config/pre.in:tests/gss-threads/Makefile.in:tests/gss-threads/deps:$srcdir/./config/post.in" + ac_config_files="$ac_config_files tests/misc/Makefile:$srcdir/./config/pre.in:tests/misc/Makefile.in:tests/misc/deps:$srcdir/./config/post.in" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +printf "%s\n" "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +as_nop=: +if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 +then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else $as_nop + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + + +# Reset variables that may have inherited troublesome values from +# the environment. + +# IFS needs to be set, to space, tab, and newline, in precisely that order. +# (If _AS_PATH_WALK were called with IFS unset, it would have the +# side effect of setting IFS to empty, thus disabling word splitting.) +# Quoting is to prevent editors from complaining about space-tab. +as_nl=' +' +export as_nl +IFS=" "" $as_nl" + +PS1='$ ' +PS2='> ' +PS4='+ ' + +# Ensure predictable behavior from utilities with locale-dependent output. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# We cannot yet rely on "unset" to work, but we need these variables +# to be unset--not just set to an empty or harmless value--now, to +# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct +# also avoids known problems related to "unset" and subshell syntax +# in other old shells (e.g. bash 2.01 and pdksh 5.2.14). +for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH +do eval test \${$as_var+y} \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done + +# Ensure that fds 0, 1, and 2 are open. +if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi +if (exec 3>&2) ; then :; else exec 2>/dev/null; fi + +# The user is always right. +if ${PATH_SEPARATOR+false} :; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + test -r "$as_dir$0" && as_myself=$as_dir$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + printf "%s\n" "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null +then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else $as_nop + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null +then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else $as_nop + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + +# Determine whether it's possible to make 'echo' print without a newline. +# These variables are no longer used directly by Autoconf, but are AC_SUBSTed +# for compatibility with existing Makefiles. +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +# For backward compatibility with old third-party macros, we provide +# the shell variables $as_echo and $as_echo_n. New code should use +# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. +as_echo='printf %s\n' +as_echo_n='printf %s' + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by Kerberos 5 $as_me 1.21.3, which was +generated by GNU Autoconf 2.71. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to ." + +_ACEOF +ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` +ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config='$ac_cs_config_escaped' +ac_cs_version="\\ +Kerberos 5 config.status 1.21.3 +configured by $0, generated by GNU Autoconf 2.71, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2021 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + printf "%s\n" "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + printf "%s\n" "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + printf "%s\n" "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + printf "%s\n" "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "po/Makefile") CONFIG_FILES="$CONFIG_FILES po/Makefile:$srcdir/./config/pre.in:po/Makefile.in:po/deps:$srcdir/./config/post.in" ;; + "plugins/audit/simple/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/audit/simple/Makefile:$srcdir/./config/pre.in:plugins/audit/simple/Makefile.in:plugins/audit/simple/deps:$srcdir/./config/post.in" ;; + "include/autoconf.h") CONFIG_HEADERS="$CONFIG_HEADERS include/autoconf.h" ;; + "include/gssrpc/types.h") CONFIG_FILES="$CONFIG_FILES include/gssrpc/types.h:include/gssrpc/types.hin" ;; + "plugins/preauth/pkinit/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/preauth/pkinit/Makefile:$srcdir/./config/pre.in:plugins/preauth/pkinit/Makefile.in:plugins/preauth/pkinit/deps:$srcdir/./config/post.in" ;; + "tests/softpkcs11/Makefile") CONFIG_FILES="$CONFIG_FILES tests/softpkcs11/Makefile:$srcdir/./config/pre.in:tests/softpkcs11/Makefile.in:tests/softpkcs11/deps:$srcdir/./config/post.in" ;; + "util/et/Makefile") CONFIG_FILES="$CONFIG_FILES util/et/Makefile:$srcdir/./config/pre.in:util/et/Makefile.in:util/et/deps:$srcdir/./config/post.in" ;; + "util/ss/Makefile") CONFIG_FILES="$CONFIG_FILES util/ss/Makefile:$srcdir/./config/pre.in:util/ss/Makefile.in:util/ss/deps:$srcdir/./config/post.in" ;; + "plugins/kdb/ldap/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/ldap/Makefile:$srcdir/./config/pre.in:plugins/kdb/ldap/Makefile.in:plugins/kdb/ldap/deps:$srcdir/./config/post.in" ;; + "plugins/kdb/ldap/ldap_util/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/ldap/ldap_util/Makefile:$srcdir/./config/pre.in:plugins/kdb/ldap/ldap_util/Makefile.in:plugins/kdb/ldap/ldap_util/deps:$srcdir/./config/post.in" ;; + "plugins/kdb/ldap/libkdb_ldap/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/ldap/libkdb_ldap/Makefile:$srcdir/./config/pre.in:plugins/kdb/ldap/libkdb_ldap/Makefile.in:plugins/kdb/ldap/libkdb_ldap/deps:$srcdir/./config/post.in" ;; + "plugins/preauth/securid_sam2/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/preauth/securid_sam2/Makefile:$srcdir/./config/pre.in:plugins/preauth/securid_sam2/Makefile.in:plugins/preauth/securid_sam2/deps:$srcdir/./config/post.in" ;; + "plugins/kdb/lmdb/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/lmdb/Makefile:$srcdir/./config/pre.in:plugins/kdb/lmdb/Makefile.in:plugins/kdb/lmdb/deps:$srcdir/./config/post.in" ;; + "build-tools/krb5-config") CONFIG_FILES="$CONFIG_FILES build-tools/krb5-config" ;; + "build-tools/kadm-server.pc") CONFIG_FILES="$CONFIG_FILES build-tools/kadm-server.pc" ;; + "build-tools/kadm-client.pc") CONFIG_FILES="$CONFIG_FILES build-tools/kadm-client.pc" ;; + "build-tools/kdb.pc") CONFIG_FILES="$CONFIG_FILES build-tools/kdb.pc" ;; + "build-tools/krb5.pc") CONFIG_FILES="$CONFIG_FILES build-tools/krb5.pc" ;; + "build-tools/krb5-gssapi.pc") CONFIG_FILES="$CONFIG_FILES build-tools/krb5-gssapi.pc" ;; + "build-tools/mit-krb5.pc") CONFIG_FILES="$CONFIG_FILES build-tools/mit-krb5.pc" ;; + "build-tools/mit-krb5-gssapi.pc") CONFIG_FILES="$CONFIG_FILES build-tools/mit-krb5-gssapi.pc" ;; + "build-tools/gssrpc.pc") CONFIG_FILES="$CONFIG_FILES build-tools/gssrpc.pc" ;; + "./Makefile") CONFIG_FILES="$CONFIG_FILES ./Makefile:$srcdir/./config/pre.in:./Makefile.in:./deps:$srcdir/./config/post.in" ;; + "util/Makefile") CONFIG_FILES="$CONFIG_FILES util/Makefile:$srcdir/./config/pre.in:util/Makefile.in:util/deps:$srcdir/./config/post.in" ;; + "util/support/Makefile") CONFIG_FILES="$CONFIG_FILES util/support/Makefile:$srcdir/./config/pre.in:util/support/Makefile.in:util/support/deps:$srcdir/./config/post.in" ;; + "util/profile/Makefile") CONFIG_FILES="$CONFIG_FILES util/profile/Makefile:$srcdir/./config/pre.in:util/profile/Makefile.in:util/profile/deps:$srcdir/./config/post.in" ;; + "util/profile/testmod/Makefile") CONFIG_FILES="$CONFIG_FILES util/profile/testmod/Makefile:$srcdir/./config/pre.in:util/profile/testmod/Makefile.in:util/profile/testmod/deps:$srcdir/./config/post.in" ;; + "util/verto/Makefile") CONFIG_FILES="$CONFIG_FILES util/verto/Makefile:$srcdir/./config/pre.in:util/verto/Makefile.in:util/verto/deps:$srcdir/./config/post.in" ;; + "lib/Makefile") CONFIG_FILES="$CONFIG_FILES lib/Makefile:$srcdir/./config/pre.in:lib/Makefile.in:lib/deps:$srcdir/./config/post.in" ;; + "lib/kdb/Makefile") CONFIG_FILES="$CONFIG_FILES lib/kdb/Makefile:$srcdir/./config/pre.in:lib/kdb/Makefile.in:lib/kdb/deps:$srcdir/./config/post.in" ;; + "lib/crypto/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/Makefile:$srcdir/./config/pre.in:lib/crypto/Makefile.in:lib/crypto/deps:$srcdir/./config/post.in" ;; + "lib/crypto/krb/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/krb/Makefile:$srcdir/./config/pre.in:lib/crypto/krb/Makefile.in:lib/crypto/krb/deps:$srcdir/./config/post.in" ;; + "lib/crypto/crypto_tests/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/crypto_tests/Makefile:$srcdir/./config/pre.in:lib/crypto/crypto_tests/Makefile.in:lib/crypto/crypto_tests/deps:$srcdir/./config/post.in" ;; + "lib/crypto/builtin/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/builtin/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/Makefile.in:lib/crypto/builtin/deps:$srcdir/./config/post.in" ;; + "lib/crypto/builtin/des/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/builtin/des/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/des/Makefile.in:lib/crypto/builtin/des/deps:$srcdir/./config/post.in" ;; + "lib/crypto/builtin/aes/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/builtin/aes/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/aes/Makefile.in:lib/crypto/builtin/aes/deps:$srcdir/./config/post.in" ;; + "lib/crypto/builtin/camellia/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/builtin/camellia/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/camellia/Makefile.in:lib/crypto/builtin/camellia/deps:$srcdir/./config/post.in" ;; + "lib/crypto/builtin/md4/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/builtin/md4/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/md4/Makefile.in:lib/crypto/builtin/md4/deps:$srcdir/./config/post.in" ;; + "lib/crypto/builtin/md5/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/builtin/md5/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/md5/Makefile.in:lib/crypto/builtin/md5/deps:$srcdir/./config/post.in" ;; + "lib/crypto/builtin/sha1/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/builtin/sha1/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/sha1/Makefile.in:lib/crypto/builtin/sha1/deps:$srcdir/./config/post.in" ;; + "lib/crypto/builtin/sha2/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/builtin/sha2/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/sha2/Makefile.in:lib/crypto/builtin/sha2/deps:$srcdir/./config/post.in" ;; + "lib/crypto/builtin/enc_provider/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/builtin/enc_provider/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/enc_provider/Makefile.in:lib/crypto/builtin/enc_provider/deps:$srcdir/./config/post.in" ;; + "lib/crypto/builtin/hash_provider/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/builtin/hash_provider/Makefile:$srcdir/./config/pre.in:lib/crypto/builtin/hash_provider/Makefile.in:lib/crypto/builtin/hash_provider/deps:$srcdir/./config/post.in" ;; + "lib/crypto/openssl/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/openssl/Makefile:$srcdir/./config/pre.in:lib/crypto/openssl/Makefile.in:lib/crypto/openssl/deps:$srcdir/./config/post.in" ;; + "lib/crypto/openssl/des/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/openssl/des/Makefile:$srcdir/./config/pre.in:lib/crypto/openssl/des/Makefile.in:lib/crypto/openssl/des/deps:$srcdir/./config/post.in" ;; + "lib/crypto/openssl/enc_provider/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/openssl/enc_provider/Makefile:$srcdir/./config/pre.in:lib/crypto/openssl/enc_provider/Makefile.in:lib/crypto/openssl/enc_provider/deps:$srcdir/./config/post.in" ;; + "lib/crypto/openssl/hash_provider/Makefile") CONFIG_FILES="$CONFIG_FILES lib/crypto/openssl/hash_provider/Makefile:$srcdir/./config/pre.in:lib/crypto/openssl/hash_provider/Makefile.in:lib/crypto/openssl/hash_provider/deps:$srcdir/./config/post.in" ;; + "lib/krb5/Makefile") CONFIG_FILES="$CONFIG_FILES lib/krb5/Makefile:$srcdir/./config/pre.in:lib/krb5/Makefile.in:lib/krb5/deps:$srcdir/./config/post.in" ;; + "lib/krb5/error_tables/Makefile") CONFIG_FILES="$CONFIG_FILES lib/krb5/error_tables/Makefile:$srcdir/./config/pre.in:lib/krb5/error_tables/Makefile.in:lib/krb5/error_tables/deps:$srcdir/./config/post.in" ;; + "lib/krb5/asn.1/Makefile") CONFIG_FILES="$CONFIG_FILES lib/krb5/asn.1/Makefile:$srcdir/./config/pre.in:lib/krb5/asn.1/Makefile.in:lib/krb5/asn.1/deps:$srcdir/./config/post.in" ;; + "lib/krb5/ccache/Makefile") CONFIG_FILES="$CONFIG_FILES lib/krb5/ccache/Makefile:$srcdir/./config/pre.in:lib/krb5/ccache/Makefile.in:lib/krb5/ccache/deps:$srcdir/./config/post.in" ;; + "lib/krb5/keytab/Makefile") CONFIG_FILES="$CONFIG_FILES lib/krb5/keytab/Makefile:$srcdir/./config/pre.in:lib/krb5/keytab/Makefile.in:lib/krb5/keytab/deps:$srcdir/./config/post.in" ;; + "lib/krb5/krb/Makefile") CONFIG_FILES="$CONFIG_FILES lib/krb5/krb/Makefile:$srcdir/./config/pre.in:lib/krb5/krb/Makefile.in:lib/krb5/krb/deps:$srcdir/./config/post.in" ;; + "lib/krb5/rcache/Makefile") CONFIG_FILES="$CONFIG_FILES lib/krb5/rcache/Makefile:$srcdir/./config/pre.in:lib/krb5/rcache/Makefile.in:lib/krb5/rcache/deps:$srcdir/./config/post.in" ;; + "lib/krb5/os/Makefile") CONFIG_FILES="$CONFIG_FILES lib/krb5/os/Makefile:$srcdir/./config/pre.in:lib/krb5/os/Makefile.in:lib/krb5/os/deps:$srcdir/./config/post.in" ;; + "lib/krb5/unicode/Makefile") CONFIG_FILES="$CONFIG_FILES lib/krb5/unicode/Makefile:$srcdir/./config/pre.in:lib/krb5/unicode/Makefile.in:lib/krb5/unicode/deps:$srcdir/./config/post.in" ;; + "lib/gssapi/Makefile") CONFIG_FILES="$CONFIG_FILES lib/gssapi/Makefile:$srcdir/./config/pre.in:lib/gssapi/Makefile.in:lib/gssapi/deps:$srcdir/./config/post.in" ;; + "lib/gssapi/generic/Makefile") CONFIG_FILES="$CONFIG_FILES lib/gssapi/generic/Makefile:$srcdir/./config/pre.in:lib/gssapi/generic/Makefile.in:lib/gssapi/generic/deps:$srcdir/./config/post.in" ;; + "lib/gssapi/krb5/Makefile") CONFIG_FILES="$CONFIG_FILES lib/gssapi/krb5/Makefile:$srcdir/./config/pre.in:lib/gssapi/krb5/Makefile.in:lib/gssapi/krb5/deps:$srcdir/./config/post.in" ;; + "lib/gssapi/spnego/Makefile") CONFIG_FILES="$CONFIG_FILES lib/gssapi/spnego/Makefile:$srcdir/./config/pre.in:lib/gssapi/spnego/Makefile.in:lib/gssapi/spnego/deps:$srcdir/./config/post.in" ;; + "lib/gssapi/mechglue/Makefile") CONFIG_FILES="$CONFIG_FILES lib/gssapi/mechglue/Makefile:$srcdir/./config/pre.in:lib/gssapi/mechglue/Makefile.in:lib/gssapi/mechglue/deps:$srcdir/./config/post.in" ;; + "lib/rpc/Makefile") CONFIG_FILES="$CONFIG_FILES lib/rpc/Makefile:$srcdir/./config/pre.in:lib/rpc/Makefile.in:lib/rpc/deps:$srcdir/./config/post.in" ;; + "lib/rpc/unit-test/Makefile") CONFIG_FILES="$CONFIG_FILES lib/rpc/unit-test/Makefile:$srcdir/./config/pre.in:lib/rpc/unit-test/Makefile.in:lib/rpc/unit-test/deps:$srcdir/./config/post.in" ;; + "lib/kadm5/Makefile") CONFIG_FILES="$CONFIG_FILES lib/kadm5/Makefile:$srcdir/./config/pre.in:lib/kadm5/Makefile.in:lib/kadm5/deps:$srcdir/./config/post.in" ;; + "lib/kadm5/clnt/Makefile") CONFIG_FILES="$CONFIG_FILES lib/kadm5/clnt/Makefile:$srcdir/./config/pre.in:lib/kadm5/clnt/Makefile.in:lib/kadm5/clnt/deps:$srcdir/./config/post.in" ;; + "lib/kadm5/srv/Makefile") CONFIG_FILES="$CONFIG_FILES lib/kadm5/srv/Makefile:$srcdir/./config/pre.in:lib/kadm5/srv/Makefile.in:lib/kadm5/srv/deps:$srcdir/./config/post.in" ;; + "lib/krad/Makefile") CONFIG_FILES="$CONFIG_FILES lib/krad/Makefile:$srcdir/./config/pre.in:lib/krad/Makefile.in:lib/krad/deps:$srcdir/./config/post.in" ;; + "lib/apputils/Makefile") CONFIG_FILES="$CONFIG_FILES lib/apputils/Makefile:$srcdir/./config/pre.in:lib/apputils/Makefile.in:lib/apputils/deps:$srcdir/./config/post.in" ;; + "kdc/Makefile") CONFIG_FILES="$CONFIG_FILES kdc/Makefile:$srcdir/./config/pre.in:kdc/Makefile.in:kdc/deps:$srcdir/./config/post.in" ;; + "kprop/Makefile") CONFIG_FILES="$CONFIG_FILES kprop/Makefile:$srcdir/./config/pre.in:kprop/Makefile.in:kprop/deps:$srcdir/./config/post.in" ;; + "config-files/Makefile") CONFIG_FILES="$CONFIG_FILES config-files/Makefile:$srcdir/./config/pre.in:config-files/Makefile.in:config-files/deps:$srcdir/./config/post.in" ;; + "build-tools/Makefile") CONFIG_FILES="$CONFIG_FILES build-tools/Makefile:$srcdir/./config/pre.in:build-tools/Makefile.in:build-tools/deps:$srcdir/./config/post.in" ;; + "man/Makefile") CONFIG_FILES="$CONFIG_FILES man/Makefile:$srcdir/./config/pre.in:man/Makefile.in:man/deps:$srcdir/./config/post.in" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile:$srcdir/./config/pre.in:doc/Makefile.in:doc/deps:$srcdir/./config/post.in" ;; + "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile:$srcdir/./config/pre.in:include/Makefile.in:include/deps:$srcdir/./config/post.in" ;; + "plugins/certauth/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/certauth/test/Makefile:$srcdir/./config/pre.in:plugins/certauth/test/Makefile.in:plugins/certauth/test/deps:$srcdir/./config/post.in" ;; + "plugins/gssapi/negoextest/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/gssapi/negoextest/Makefile:$srcdir/./config/pre.in:plugins/gssapi/negoextest/Makefile.in:plugins/gssapi/negoextest/deps:$srcdir/./config/post.in" ;; + "plugins/hostrealm/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/hostrealm/test/Makefile:$srcdir/./config/pre.in:plugins/hostrealm/test/Makefile.in:plugins/hostrealm/test/deps:$srcdir/./config/post.in" ;; + "plugins/localauth/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/localauth/test/Makefile:$srcdir/./config/pre.in:plugins/localauth/test/Makefile.in:plugins/localauth/test/deps:$srcdir/./config/post.in" ;; + "plugins/kadm5_hook/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kadm5_hook/test/Makefile:$srcdir/./config/pre.in:plugins/kadm5_hook/test/Makefile.in:plugins/kadm5_hook/test/deps:$srcdir/./config/post.in" ;; + "plugins/kadm5_auth/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kadm5_auth/test/Makefile:$srcdir/./config/pre.in:plugins/kadm5_auth/test/Makefile.in:plugins/kadm5_auth/test/deps:$srcdir/./config/post.in" ;; + "plugins/pwqual/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/pwqual/test/Makefile:$srcdir/./config/pre.in:plugins/pwqual/test/Makefile.in:plugins/pwqual/test/deps:$srcdir/./config/post.in" ;; + "plugins/audit/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/audit/Makefile:$srcdir/./config/pre.in:plugins/audit/Makefile.in:plugins/audit/deps:$srcdir/./config/post.in" ;; + "plugins/audit/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/audit/test/Makefile:$srcdir/./config/pre.in:plugins/audit/test/Makefile.in:plugins/audit/test/deps:$srcdir/./config/post.in" ;; + "plugins/kdb/db2/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/db2/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/Makefile.in:plugins/kdb/db2/deps:$srcdir/./config/post.in" ;; + "plugins/kdb/db2/libdb2/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/db2/libdb2/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/Makefile.in:plugins/kdb/db2/libdb2/deps:$srcdir/./config/post.in" ;; + "plugins/kdb/db2/libdb2/hash/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/db2/libdb2/hash/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/hash/Makefile.in:plugins/kdb/db2/libdb2/hash/deps:$srcdir/./config/post.in" ;; + "plugins/kdb/db2/libdb2/btree/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/db2/libdb2/btree/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/btree/Makefile.in:plugins/kdb/db2/libdb2/btree/deps:$srcdir/./config/post.in" ;; + "plugins/kdb/db2/libdb2/db/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/db2/libdb2/db/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/db/Makefile.in:plugins/kdb/db2/libdb2/db/deps:$srcdir/./config/post.in" ;; + "plugins/kdb/db2/libdb2/mpool/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/db2/libdb2/mpool/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/mpool/Makefile.in:plugins/kdb/db2/libdb2/mpool/deps:$srcdir/./config/post.in" ;; + "plugins/kdb/db2/libdb2/recno/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/db2/libdb2/recno/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/recno/Makefile.in:plugins/kdb/db2/libdb2/recno/deps:$srcdir/./config/post.in" ;; + "plugins/kdb/db2/libdb2/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/db2/libdb2/test/Makefile:$srcdir/./config/pre.in:plugins/kdb/db2/libdb2/test/Makefile.in:plugins/kdb/db2/libdb2/test/deps:$srcdir/./config/post.in" ;; + "plugins/kdb/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdb/test/Makefile:$srcdir/./config/pre.in:plugins/kdb/test/Makefile.in:plugins/kdb/test/deps:$srcdir/./config/post.in" ;; + "plugins/kdcpolicy/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/kdcpolicy/test/Makefile:$srcdir/./config/pre.in:plugins/kdcpolicy/test/Makefile.in:plugins/kdcpolicy/test/deps:$srcdir/./config/post.in" ;; + "plugins/preauth/otp/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/preauth/otp/Makefile:$srcdir/./config/pre.in:plugins/preauth/otp/Makefile.in:plugins/preauth/otp/deps:$srcdir/./config/post.in" ;; + "plugins/preauth/spake/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/preauth/spake/Makefile:$srcdir/./config/pre.in:plugins/preauth/spake/Makefile.in:plugins/preauth/spake/deps:$srcdir/./config/post.in" ;; + "plugins/preauth/test/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/preauth/test/Makefile:$srcdir/./config/pre.in:plugins/preauth/test/Makefile.in:plugins/preauth/test/deps:$srcdir/./config/post.in" ;; + "plugins/authdata/greet_client/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/authdata/greet_client/Makefile:$srcdir/./config/pre.in:plugins/authdata/greet_client/Makefile.in:plugins/authdata/greet_client/deps:$srcdir/./config/post.in" ;; + "plugins/authdata/greet_server/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/authdata/greet_server/Makefile:$srcdir/./config/pre.in:plugins/authdata/greet_server/Makefile.in:plugins/authdata/greet_server/deps:$srcdir/./config/post.in" ;; + "plugins/tls/k5tls/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/tls/k5tls/Makefile:$srcdir/./config/pre.in:plugins/tls/k5tls/Makefile.in:plugins/tls/k5tls/deps:$srcdir/./config/post.in" ;; + "clients/Makefile") CONFIG_FILES="$CONFIG_FILES clients/Makefile:$srcdir/./config/pre.in:clients/Makefile.in:clients/deps:$srcdir/./config/post.in" ;; + "clients/klist/Makefile") CONFIG_FILES="$CONFIG_FILES clients/klist/Makefile:$srcdir/./config/pre.in:clients/klist/Makefile.in:clients/klist/deps:$srcdir/./config/post.in" ;; + "clients/kinit/Makefile") CONFIG_FILES="$CONFIG_FILES clients/kinit/Makefile:$srcdir/./config/pre.in:clients/kinit/Makefile.in:clients/kinit/deps:$srcdir/./config/post.in" ;; + "clients/kvno/Makefile") CONFIG_FILES="$CONFIG_FILES clients/kvno/Makefile:$srcdir/./config/pre.in:clients/kvno/Makefile.in:clients/kvno/deps:$srcdir/./config/post.in" ;; + "clients/kdestroy/Makefile") CONFIG_FILES="$CONFIG_FILES clients/kdestroy/Makefile:$srcdir/./config/pre.in:clients/kdestroy/Makefile.in:clients/kdestroy/deps:$srcdir/./config/post.in" ;; + "clients/kpasswd/Makefile") CONFIG_FILES="$CONFIG_FILES clients/kpasswd/Makefile:$srcdir/./config/pre.in:clients/kpasswd/Makefile.in:clients/kpasswd/deps:$srcdir/./config/post.in" ;; + "clients/ksu/Makefile") CONFIG_FILES="$CONFIG_FILES clients/ksu/Makefile:$srcdir/./config/pre.in:clients/ksu/Makefile.in:clients/ksu/deps:$srcdir/./config/post.in" ;; + "clients/kswitch/Makefile") CONFIG_FILES="$CONFIG_FILES clients/kswitch/Makefile:$srcdir/./config/pre.in:clients/kswitch/Makefile.in:clients/kswitch/deps:$srcdir/./config/post.in" ;; + "kadmin/Makefile") CONFIG_FILES="$CONFIG_FILES kadmin/Makefile:$srcdir/./config/pre.in:kadmin/Makefile.in:kadmin/deps:$srcdir/./config/post.in" ;; + "kadmin/cli/Makefile") CONFIG_FILES="$CONFIG_FILES kadmin/cli/Makefile:$srcdir/./config/pre.in:kadmin/cli/Makefile.in:kadmin/cli/deps:$srcdir/./config/post.in" ;; + "kadmin/dbutil/Makefile") CONFIG_FILES="$CONFIG_FILES kadmin/dbutil/Makefile:$srcdir/./config/pre.in:kadmin/dbutil/Makefile.in:kadmin/dbutil/deps:$srcdir/./config/post.in" ;; + "kadmin/ktutil/Makefile") CONFIG_FILES="$CONFIG_FILES kadmin/ktutil/Makefile:$srcdir/./config/pre.in:kadmin/ktutil/Makefile.in:kadmin/ktutil/deps:$srcdir/./config/post.in" ;; + "kadmin/server/Makefile") CONFIG_FILES="$CONFIG_FILES kadmin/server/Makefile:$srcdir/./config/pre.in:kadmin/server/Makefile.in:kadmin/server/deps:$srcdir/./config/post.in" ;; + "appl/Makefile") CONFIG_FILES="$CONFIG_FILES appl/Makefile:$srcdir/./config/pre.in:appl/Makefile.in:appl/deps:$srcdir/./config/post.in" ;; + "appl/sample/Makefile") CONFIG_FILES="$CONFIG_FILES appl/sample/Makefile:$srcdir/./config/pre.in:appl/sample/Makefile.in:appl/sample/deps:$srcdir/./config/post.in" ;; + "appl/sample/sclient/Makefile") CONFIG_FILES="$CONFIG_FILES appl/sample/sclient/Makefile:$srcdir/./config/pre.in:appl/sample/sclient/Makefile.in:appl/sample/sclient/deps:$srcdir/./config/post.in" ;; + "appl/sample/sserver/Makefile") CONFIG_FILES="$CONFIG_FILES appl/sample/sserver/Makefile:$srcdir/./config/pre.in:appl/sample/sserver/Makefile.in:appl/sample/sserver/deps:$srcdir/./config/post.in" ;; + "appl/simple/Makefile") CONFIG_FILES="$CONFIG_FILES appl/simple/Makefile:$srcdir/./config/pre.in:appl/simple/Makefile.in:appl/simple/deps:$srcdir/./config/post.in" ;; + "appl/simple/client/Makefile") CONFIG_FILES="$CONFIG_FILES appl/simple/client/Makefile:$srcdir/./config/pre.in:appl/simple/client/Makefile.in:appl/simple/client/deps:$srcdir/./config/post.in" ;; + "appl/simple/server/Makefile") CONFIG_FILES="$CONFIG_FILES appl/simple/server/Makefile:$srcdir/./config/pre.in:appl/simple/server/Makefile.in:appl/simple/server/deps:$srcdir/./config/post.in" ;; + "appl/gss-sample/Makefile") CONFIG_FILES="$CONFIG_FILES appl/gss-sample/Makefile:$srcdir/./config/pre.in:appl/gss-sample/Makefile.in:appl/gss-sample/deps:$srcdir/./config/post.in" ;; + "appl/user_user/Makefile") CONFIG_FILES="$CONFIG_FILES appl/user_user/Makefile:$srcdir/./config/pre.in:appl/user_user/Makefile.in:appl/user_user/deps:$srcdir/./config/post.in" ;; + "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile:$srcdir/./config/pre.in:tests/Makefile.in:tests/deps:$srcdir/./config/post.in" ;; + "tests/asn.1/Makefile") CONFIG_FILES="$CONFIG_FILES tests/asn.1/Makefile:$srcdir/./config/pre.in:tests/asn.1/Makefile.in:tests/asn.1/deps:$srcdir/./config/post.in" ;; + "tests/create/Makefile") CONFIG_FILES="$CONFIG_FILES tests/create/Makefile:$srcdir/./config/pre.in:tests/create/Makefile.in:tests/create/deps:$srcdir/./config/post.in" ;; + "tests/hammer/Makefile") CONFIG_FILES="$CONFIG_FILES tests/hammer/Makefile:$srcdir/./config/pre.in:tests/hammer/Makefile.in:tests/hammer/deps:$srcdir/./config/post.in" ;; + "tests/verify/Makefile") CONFIG_FILES="$CONFIG_FILES tests/verify/Makefile:$srcdir/./config/pre.in:tests/verify/Makefile.in:tests/verify/deps:$srcdir/./config/post.in" ;; + "tests/gssapi/Makefile") CONFIG_FILES="$CONFIG_FILES tests/gssapi/Makefile:$srcdir/./config/pre.in:tests/gssapi/Makefile.in:tests/gssapi/deps:$srcdir/./config/post.in" ;; + "tests/threads/Makefile") CONFIG_FILES="$CONFIG_FILES tests/threads/Makefile:$srcdir/./config/pre.in:tests/threads/Makefile.in:tests/threads/deps:$srcdir/./config/post.in" ;; + "tests/shlib/Makefile") CONFIG_FILES="$CONFIG_FILES tests/shlib/Makefile:$srcdir/./config/pre.in:tests/shlib/Makefile.in:tests/shlib/deps:$srcdir/./config/post.in" ;; + "tests/gss-threads/Makefile") CONFIG_FILES="$CONFIG_FILES tests/gss-threads/Makefile:$srcdir/./config/pre.in:tests/gss-threads/Makefile.in:tests/gss-threads/deps:$srcdir/./config/post.in" ;; + "tests/misc/Makefile") CONFIG_FILES="$CONFIG_FILES tests/misc/Makefile:$srcdir/./config/pre.in:tests/misc/Makefile.in:tests/misc/deps:$srcdir/./config/post.in" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files + test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + +if $AWK 'BEGIN { getline <"/dev/null" }' /dev/null; then + ac_cs_awk_getline=: + ac_cs_awk_pipe_init= + ac_cs_awk_read_file=' + while ((getline aline < (F[key])) > 0) + print(aline) + close(F[key])' + ac_cs_awk_pipe_fini= +else + ac_cs_awk_getline=false + ac_cs_awk_pipe_init="print \"cat <<'|#_!!_#|' &&\"" + ac_cs_awk_read_file=' + print "|#_!!_#|" + print "cat " F[key] " &&" + '$ac_cs_awk_pipe_init + # The final `:' finishes the AND list. + ac_cs_awk_pipe_fini='END { print "|#_!!_#|"; print ":" }' +fi +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + +# Create commands to substitute file output variables. +{ + echo "cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1" && + echo 'cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&' && + echo "$ac_subst_files" | sed 's/.*/F["&"]="$&"/' && + echo "_ACAWK" && + echo "_ACEOF" +} >conf$$files.sh && +. ./conf$$files.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +rm -f conf$$files.sh + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + \$ac_cs_awk_pipe_init +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + if (nfields == 3 && !substed) { + key = field[2] + if (F[key] != "" && line ~ /^[ ]*@.*@[ ]*$/) { + \$ac_cs_awk_read_file + next + } + } + print line +} +\$ac_cs_awk_pipe_fini +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +printf "%s\n" "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`printf "%s\n" "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +printf "%s\n" X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | +if $ac_cs_awk_getline; then + $AWK -f "$ac_tmp/subs.awk" +else + $AWK -f "$ac_tmp/subs.awk" | $SHELL +fi \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + printf "%s\n" "/* $configure_input */" >&1 \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + printf "%s\n" "/* $configure_input */" >&1 \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + + + case $ac_file$ac_mode in + "include/autoconf.h":H) echo timestamp > include/autoconf.stamp ;; + "build-tools/krb5-config":F) chmod +x build-tools/krb5-config ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + diff --git a/krb5-1.21.3/src/configure.ac b/krb5-1.21.3/src/configure.ac new file mode 100644 index 00000000..77be7a20 --- /dev/null +++ b/krb5-1.21.3/src/configure.ac @@ -0,0 +1,1573 @@ +K5_AC_INIT([aclocal.m4]) + +# If $runstatedir isn't set by autoconf (<2.70), set it manually. +if test x"$runstatedir" = x; then + runstatedir='${localstatedir}/run' +fi +AC_SUBST(runstatedir) + +# Don't make duplicate profile path entries for /etc/krb5.conf if +# $sysconfdir is /etc +if test "$sysconfdir" = /etc; then + SYSCONFCONF="" +else + SYSCONFCONF=":${sysconfdir}/krb5.conf" +fi +AC_SUBST(SYSCONFCONF) + +CONFIG_RULES +KRB5_VERSION=K5_VERSION +AC_SUBST(KRB5_VERSION) + + +AC_REQUIRE_CPP + +PKG_PROG_PKG_CONFIG + +AC_CHECK_HEADER([stdint.h], [], + [AC_MSG_ERROR([stdint.h is required])]) + +AC_CACHE_CHECK([whether integers are two's complement], + [krb5_cv_ints_twos_compl], + [AC_COMPILE_IFELSE( + [AC_LANG_BOOL_COMPILE_TRY( +[#include +], + [/* Basic two's complement check */ + ~(-1) == 0 && ~(-1L) == 0L && + /* Check that values with sign bit 1 and value bits 0 are valid */ + -(INT_MIN + 1) == INT_MAX && -(LONG_MIN + 1) == LONG_MAX && + /* Check that unsigned-to-signed conversions preserve bit patterns */ + (int)((unsigned int)INT_MAX + 1) == INT_MIN && + (long)((unsigned long)LONG_MAX + 1) == LONG_MIN])], + [krb5_cv_ints_twos_compl=yes], + [krb5_cv_ints_twos_compl=no])]) + +if test "$krb5_cv_ints_twos_compl" = "no"; then + AC_MSG_ERROR([integers are not two's complement]) +fi + +AC_CACHE_CHECK([whether CHAR_BIT is 8], + [krb5_cv_char_bit_8], + [AC_PREPROC_IFELSE([AC_LANG_SOURCE( +[[#include +#if CHAR_BIT != 8 + #error CHAR_BIT != 8 +#endif +]])], + [krb5_cv_char_bit_8=yes], [krb5_cv_char_bit_8=no])]) + +if test "$krb5_cv_char_bit_8" = "no"; then + AC_MSG_ERROR([CHAR_BIT is not 8]) +fi + +AC_CACHE_CHECK(if va_copy is available, krb5_cv_va_copy, +[AC_LINK_IFELSE([AC_LANG_SOURCE([ +#include +void f(va_list ap) { + va_list ap2; + va_copy(ap2, ap); + va_end(ap2); +} +va_list x; +int main() +{ + f(x); + return 0; +}])], krb5_cv_va_copy=yes, krb5_cv_va_copy=no)]) +if test "$krb5_cv_va_copy" = yes; then + AC_DEFINE(HAS_VA_COPY,1,[Define if va_copy macro or function is available.]) +fi + +# Note that this isn't checking if the copied value *works*, just +# whether the C language constraints permit the copying. If +# va_list is defined as an array type, it can't be assigned. +AC_CACHE_CHECK(if va_list objects can be copied by assignment, + krb5_cv_va_simple_copy, +[AC_COMPILE_IFELSE([ +AC_LANG_SOURCE([#include +void f(va_list va2) { + va_list va1; + va1 = va2; +}])], krb5_cv_va_simple_copy=yes, krb5_cv_va_simple_copy=no)]) +if test "$krb5_cv_va_simple_copy" = yes; then + AC_DEFINE(CAN_COPY_VA_LIST,1,[Define if va_list objects can be simply copied by assignment.]) +fi + +# The following lines are so that configure --help gives some global +# configuration options. + +KRB5_LIB_AUX +AC_ARG_ENABLE([athena], +[ --enable-athena build with MIT Project Athena configuration],,) + +# Begin autoconf tests for the Makefiles generated out of the top-level +# configure.in... + +KRB5_BUILD_LIBOBJS +KRB5_BUILD_LIBRARY +KRB5_BUILD_PROGRAM +# for kprop +AC_TYPE_MODE_T +AC_PROG_INSTALL +KRB5_AC_NEED_DAEMON +KRB5_GETSOCKNAME_ARGS +KRB5_GETPEERNAME_ARGS +LIBUTIL= +AC_CHECK_LIB(util,main,[AC_DEFINE(HAVE_LIBUTIL,1,[Define if the util library is available]) +LIBUTIL=-lutil +]) +AC_SUBST(LIBUTIL) + +# Determine if NLS is desired and supported. +po= +AC_ARG_ENABLE([nls], + [AS_HELP_STRING([--disable-nls], [disable native language support])], + [], [enable_nls=check]) +if test "$enable_nls" != no; then + AC_CHECK_HEADER(libintl.h, [ + AC_SEARCH_LIBS(dgettext, intl, [ + AC_DEFINE(ENABLE_NLS, 1, + [Define if translation functions should be used.]) + nls_enabled=yes])]) + + AC_CHECK_PROG(MSGFMT,msgfmt,msgfmt) + if test x"$MSGFMT" != x; then + K5_GEN_MAKEFILE(po) + po=po + fi + + # Error out if --enable-nls was explicitly requested but can't be enabled. + if test "$enable_nls" = yes; then + if test "$nls_enabled" != yes -o "x$po" = x; then + AC_MSG_ERROR([NLS support requested but cannot be built]) + fi + fi +fi +AC_SUBST(po) + +# for kdc +AC_CHECK_HEADERS(sys/sockio.h ifaddrs.h unistd.h fnmatch.h) +AC_CHECK_FUNCS(vsprintf vasprintf vsnprintf strlcpy fnmatch secure_getenv) + +EXTRA_SUPPORT_SYMS= +AC_CHECK_FUNC(strlcpy, +[STRLCPY_ST_OBJ= +STRLCPY_OBJ=], +[STRLCPY_ST_OBJ=strlcpy.o +STRLCPY_OBJ='$(OUTPRE)strlcpy.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_strlcpy krb5int_strlcat"]) +AC_SUBST(STRLCPY_OBJ) +AC_SUBST(STRLCPY_ST_OBJ) + +AC_CHECK_FUNC(getopt, +[GETOPT_ST_OBJ= +GETOPT_OBJ= +AC_DEFINE(HAVE_GETOPT, 1, [Define if system getopt should be used.])], +[GETOPT_ST_OBJ='getopt.o' +GETOPT_OBJ='$(OUTPRE)getopt.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS k5_optind k5_optarg k5_opterr k5_optopt k5_getopt"]) +AC_SUBST(GETOPT_OBJ) +AC_SUBST(GETOPT_ST_OBJ) + +AC_CHECK_FUNC(getopt_long, +[GETOPT_LONG_ST_OBJ= +GETOPT_LONG_OBJ= +AC_DEFINE(HAVE_GETOPT_LONG, 1, [Define if system getopt_long should be used.])], +[GETOPT_LONG_ST_OBJ='getopt_long.o' +GETOPT_LONG_OBJ='$(OUTPRE)getopt_long.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS k5_getopt_long"]) +AC_SUBST(GETOPT_LONG_OBJ) +AC_SUBST(GETOPT_LONG_ST_OBJ) + +AC_CHECK_FUNC(fnmatch, +[FNMATCH_ST_OBJ= +FNMATCH_OBJ=], +[FNMATCH_ST_OBJ=fnmatch.o +FNMATCH_OBJ='$(OUTPRE)fnmatch.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS k5_fnmatch"]) +AC_SUBST(FNMATCH_OBJ) +AC_SUBST(FNMATCH_ST_OBJ) + +AC_CHECK_FUNC(vasprintf, +[PRINTF_ST_OBJ= +PRINTF_OBJ=], +[PRINTF_ST_OBJ=printf.o +PRINTF_OBJ='$(OUTPRE)printf.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_asprintf krb5int_vasprintf"]) +AC_SUBST(PRINTF_OBJ) +AC_SUBST(PRINTF_ST_OBJ) +KRB5_NEED_PROTO([#include +#include +],vasprintf) +KRB5_NEED_PROTO([#include +#ifdef HAVE_UNISTD_H +#include +#endif +/* Solaris 8 declares swab in stdlib.h. */ +#include +],swab,1) + +AC_CHECK_FUNC(secure_getenv, +[SECURE_GETENV_ST_OBJ= +SECURE_GETENV_OBJ= +SECURE_GETENV_INIT=], +[SECURE_GETENV_ST_OBJ=secure_getenv.o +SECURE_GETENV_OBJ='$(OUTPRE)secure_getenv.$(OBJEXT)' +SECURE_GETENV_INIT=k5_secure_getenv_init +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS k5_secure_getenv"]) +AC_SUBST(SECURE_GETENV_OBJ) +AC_SUBST(SECURE_GETENV_ST_OBJ) +AC_SUBST(SECURE_GETENV_INIT) + +AC_PROG_AWK +KRB5_AC_INET6 +KRB5_SOCKADDR_SA_LEN +CHECK_SIGNALS + +# --with-vague-errors disables useful error messages. + +AC_ARG_WITH([vague-errors], + [AS_HELP_STRING([--with-vague-errors], + [Do not @<:@do@:>@ send helpful errors to client])], + [], [withval=no]) +if test "$withval" = yes; then + AC_MSG_NOTICE(Supplying vague error messages to KDC clients) + AC_DEFINE(KRBCONF_VAGUE_ERRORS,1,[Define if the KDC should return only vague error codes to clients]) +fi + +# Check which (if any) audit plugin to build +audit_plugin="" +AC_ARG_ENABLE([audit-plugin], + [AS_HELP_STRING([--enable-audit-plugin=IMPL], + [use audit plugin @<:@ do not use audit @:>@])], + [], enableval=no) +if test "$enableval" != no; then + case "$enableval" in + simple) + # if audit_log_user_message is found, we assume + # that audit_open and audit_close are also defined. + AC_CHECK_LIB(audit, audit_log_user_message, + [AUDIT_IMPL_LIBS=-laudit + K5_GEN_MAKEFILE(plugins/audit/simple) + audit_plugin=plugins/audit/simple ], + AC_MSG_ERROR([libaudit not found or undefined symbol audit_log_user_message])) + ;; + *) + AC_MSG_ERROR([Unknown audit plugin implementation $enableval.]) + ;; + esac +fi +AC_SUBST(AUDIT_IMPL_LIBS) +AC_SUBST(audit_plugin) + +# WITH_CRYPTO_IMPL + +CRYPTO_IMPL=builtin +AC_ARG_WITH([crypto-impl], + [AS_HELP_STRING([--with-crypto-impl=IMPL], + [use specified crypto implementation @<:@builtin@:>@])], + [CRYPTO_IMPL=$withval + AC_MSG_NOTICE(k5crypto will use '$withval')]) + +CRYPTO_BUILTIN_TESTS=no +case $CRYPTO_IMPL in +builtin) + CRYPTO_BUILTIN_TESTS=yes + ;; +openssl) + AC_CHECK_LIB(crypto, PKCS7_get_signer_info) + AC_DEFINE([CRYPTO_OPENSSL], 1, [Define to use OpenSSL crypto library]) + ;; +*) + AC_MSG_ERROR([Unknown crypto implementation $withval]) + ;; +esac +AC_SUBST([CRYPTO_IMPL_CFLAGS]) +AC_SUBST([CRYPTO_IMPL_LIBS]) +AC_SUBST([CRYPTO_BUILTIN_TESTS]) + +# WITH_TLS_IMPL + +AC_ARG_WITH([tls-impl], + [AS_HELP_STRING([--with-tls-impl=IMPL], + [use specified TLS implementation @<:@auto@:>@])], + [TLS_IMPL=$withval], [TLS_IMPL=auto]) +case "$TLS_IMPL" in +openssl|auto) + AC_CHECK_LIB(ssl,SSL_CTX_new,[have_lib_ssl=true],[have_lib_ssl=false], + -lcrypto) + AC_MSG_CHECKING([for OpenSSL]) + if test x$have_lib_ssl = xtrue ; then + AC_DEFINE(TLS_IMPL_OPENSSL,1,[Define if TLS implementation is OpenSSL]) + AC_MSG_RESULT([yes]) + TLS_IMPL_LIBS="-lssl -lcrypto" + TLS_IMPL=openssl + AC_MSG_NOTICE([TLS module will use OpenSSL]) + else + if test "$TLS_IMPL" = openssl ; then + AC_MSG_ERROR([OpenSSL not found!]) + else + AC_MSG_WARN([OpenSSL not found!]) + fi + TLS_IMPL=no + AC_MSG_NOTICE(building without TLS support) + fi + ;; +no) + AC_MSG_NOTICE(building without TLS support) + ;; +*) + AC_MSG_ERROR([Unsupported TLS implementation $withval]) + ;; +esac + +if test "$TLS_IMPL" = no; then + AC_DEFINE(TLS_IMPL_NONE,1,[Define if no TLS implementation is selected]) +fi + +AC_SUBST(TLS_IMPL) +AC_SUBST(TLS_IMPL_CFLAGS) +AC_SUBST(TLS_IMPL_LIBS) + +AC_ARG_WITH([keyutils], + [AS_HELP_STRING([--without-keyutils], [do not link with libkeyutils])], + [], [with_keyutils=check]) +if test "$with_keyutils" != no; then + have_keyutils=false + AC_CHECK_HEADERS([keyutils.h], + AC_CHECK_LIB(keyutils, add_key, [have_keyutils=true])) + if test "$have_keyutils" = true; then + AC_DEFINE(USE_KEYRING_CCACHE, 1, + [Define if the keyring ccache should be enabled]) + LIBS="-lkeyutils $LIBS" + # If libkeyutils supports persistent keyrings, use them. + AC_CHECK_LIB(keyutils, keyctl_get_persistent, + [AC_DEFINE(HAVE_PERSISTENT_KEYRING, 1, + [Define if persistent keyrings are supported]) + ]) + elif test "$with_keyutils" = yes; then + AC_MSG_ERROR([libkeyutils not found]) + fi +fi + +# The SPAKE preauth plugin currently supports edwards25519 natively, +# and can support three NIST groups using OpenSSL. +HAVE_SPAKE_OPENSSL=no +AC_ARG_WITH([spake-openssl], + [AS_HELP_STRING([--with-spake-openssl], + [use OpenSSL for SPAKE preauth @<:@auto@:>@])], + [], [withval=auto]) +if test "$withval" = auto -o "$withval" = yes; then + AC_CHECK_LIB([crypto],[EC_POINT_new],[have_crypto=true],[have_crypto=false]) + if test "$have_crypto" = true; then + AC_DEFINE(SPAKE_OPENSSL,1,[Define to use OpenSSL for SPAKE preauth]) + SPAKE_OPENSSL_LIBS=-lcrypto + HAVE_SPAKE_OPENSSL=yes + elif test "$withval" = yes; then + AC_MSG_ERROR([OpenSSL libcrypto not found]) + fi +fi +AC_SUBST(HAVE_SPAKE_OPENSSL) +AC_SUBST(SPAKE_OPENSSL_LIBS) + +AC_ARG_ENABLE([aesni], + [AS_HELP_STRING([--disable-aesni], [Do not build with AES-NI support])], + [], [enable_aesni=check]) +if test "$CRYPTO_IMPL" = builtin -a "x$enable_aesni" != xno; then + case "$host" in + i686-*) + aesni_obj=iaesx86.o + aesni_machine=x86 + ;; + x86_64-*) + aesni_obj=iaesx64.o + aesni_machine=amd64 + ;; + esac + case "$host" in + *-*-linux* | *-*-gnu* | *-*-*bsd* | *-*-solaris*) + # All Unix-like platforms need -D__linux__ for iaesx64.s to + # use the System V x86-64 calling convention. + aesni_flags="-D__linux__ -f elf -m $aesni_machine" + ;; + esac + if test "x$aesni_obj" != x && test "x$aesni_flags" != x; then + AC_CHECK_PROG(YASM,yasm,yasm) + AC_CHECK_HEADERS(cpuid.h) + if test x"$YASM" != x -a "x$ac_cv_header_cpuid_h" = xyes; then + AESNI_OBJ=$aesni_obj + AESNI_FLAGS=$aesni_flags + AC_DEFINE(AESNI,1,[Define if AES-NI support is enabled]) + AC_MSG_NOTICE([Building with AES-NI support]) + fi + fi + if test "x$enable_aesni" = xyes -a "x$AESNI_OBJ" = x; then + AC_MSG_ERROR([AES-NI support requested but cannot be built]) + fi +fi +AC_SUBST(AESNI_OBJ) +AC_SUBST(AESNI_FLAGS) + +AC_ARG_ENABLE([kdc-lookaside-cache], + AS_HELP_STRING([--disable-kdc-lookaside-cache], + [Disable the cache which detects client retransmits]), + [], [enableval=yes]) +if test "$enableval" = no ; then + AC_DEFINE(NOCACHE,1,[Define if the KDC should use no lookaside cache]) +fi +KRB5_RUN_FLAGS + +# asan is a gcc and clang facility to instrument the code with memory +# error checking. To use it, we compile C and C++ source files with +# -fsanitize=address, and set ASAN=yes to suppress the undefined +# symbols check when building shared libraries. +AC_ARG_ENABLE([asan], + [AS_HELP_STRING([--enable-asan], [Build with asan memory checking])], + [], [enable_asan=no]) +if test "$enable_asan" != no; then + if test "$enable_asan" = yes; then + enable_asan=address + fi + ASAN_FLAGS="$DEFS -fsanitize=$enable_asan" + ASAN=yes + UNDEF_CHECK= +else + ASAN_FLAGS= + ASAN=no +fi +AC_SUBST(ASAN_FLAGS) +AC_SUBST(ASAN) + +# from old include/configure.in +AH_TEMPLATE([HAVE_STRUCT_SOCKADDR_STORAGE], +[Define if "struct sockaddr_storage" is available.]) + +AC_CONFIG_HEADERS(include/autoconf.h, [echo timestamp > include/autoconf.stamp]) +AC_C_CONST +AC_HEADER_DIRENT +AC_FUNC_STRERROR_R +AC_CHECK_FUNCS(strdup setvbuf seteuid setresuid setreuid setegid setresgid setregid setsid flock fchmod chmod strptime geteuid setenv unsetenv getenv gmtime_r localtime_r bswap16 bswap64 mkstemp getusershell access getcwd srand48 srand srandom stat strchr strerror timegm explicit_bzero explicit_memset getresuid getresgid) + +AC_CHECK_FUNC(mkstemp, +[MKSTEMP_ST_OBJ= +MKSTEMP_OBJ=], +[MKSTEMP_ST_OBJ='mkstemp.o' +MKSTEMP_OBJ='$(OUTPRE)mkstemp.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_mkstemp"]) +AC_SUBST(MKSTEMP_OBJ) +AC_SUBST(MKSTEMP_ST_OBJ) + +AC_CHECK_FUNC(gettimeofday, + [GETTIMEOFDAY_ST_OBJ= + GETTIMEOFDAY_OBJ= + AC_DEFINE(HAVE_GETTIMEOFDAY, 1, [Have the gettimeofday function]) +], + [GETTIMEOFDAY_ST_OBJ='gettimeofday.o' + GETTIMEOFDAY_OBJ='$(OUTPRE)gettimeofday.$(OBJEXT)' + EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_gettimeofday"]) +AC_SUBST(GETTIMEOFDAY_OBJ) +AC_SUBST(GETTIMEOFDAY_ST_OBJ) +AC_SUBST(EXTRA_SUPPORT_SYMS) + +DECLARE_SYS_ERRLIST +AC_CHECK_HEADERS(unistd.h paths.h regex.h regexpr.h fcntl.h memory.h ifaddrs.h sys/filio.h byteswap.h machine/endian.h machine/byte_order.h sys/bswap.h endian.h pwd.h arpa/inet.h alloca.h dlfcn.h limits.h) +AC_CHECK_HEADER(regexp.h, [], [], +[#define INIT char *sp = instring; +#define GETC() (*sp++) +#define PEEKC() (*sp) +#define UNGETC(c) (--sp) +#define RETURN(c) return(c) +#define ERROR(c) +]) +AC_CHECK_MEMBERS([struct stat.st_mtimensec,struct stat.st_mtimespec.tv_nsec,struct stat.st_mtim.tv_nsec],,,[#include +#include ]) +KRB5_AC_REGEX_FUNCS +AC_TYPE_OFF_T + +# Fancy caching of perror result... +AC_MSG_CHECKING(for perror declaration) +AC_CACHE_VAL(krb5_cv_decl_perror, +[AC_EGREP_HEADER(perror, errno.h, + krb5_cv_decl_perror=yes, krb5_cv_decl_perror=no)]) +AC_MSG_RESULT($krb5_cv_decl_perror) +if test $krb5_cv_decl_perror = yes; then + AC_DEFINE(HDR_HAS_PERROR,1,[Define if errno.h declares perror]) +fi + +KRB5_NEED_PROTO([#include ],strptime) +CHECK_WAIT_TYPE +CHECK_SIGPROCMASK +AC_TYPE_GETGROUPS +CHECK_SETJMP + +# *rpcent return types needed for lib/rpc + +AC_MSG_CHECKING([return type of setrpcent]) +AC_CACHE_VAL(k5_cv_type_setrpcent, +[AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([[#include + extern void setrpcent();]])], + [k5_cv_type_setrpcent=void], + [k5_cv_type_setrpcent=int])]) +AC_MSG_RESULT($k5_cv_type_setrpcent) +AC_DEFINE_UNQUOTED(SETRPCENT_TYPE, $k5_cv_type_setrpcent, [Define as return type of setrpcent]) + +AC_MSG_CHECKING([return type of endrpcent]) +AC_CACHE_VAL(k5_cv_type_endrpcent, +[AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#include + extern void endrpcent();]])], + [k5_cv_type_endrpcent=void], [k5_cv_type_endrpcent=int])]) +AC_MSG_RESULT($k5_cv_type_endrpcent) +AC_DEFINE_UNQUOTED(ENDRPCENT_TYPE, $k5_cv_type_endrpcent, [Define as return type of endrpcent]) + + +# bswap_16 is a macro in byteswap.h under GNU libc +AC_MSG_CHECKING(for bswap_16) +AC_CACHE_VAL(krb5_cv_bswap_16, +[AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#if HAVE_BYTESWAP_H + #include + #endif + ]], + [[bswap_16(37);]])], + [krb5_cv_bswap_16=yes], [krb5_cv_bswap_16=no])]) +AC_MSG_RESULT($krb5_cv_bswap_16) +if test "$krb5_cv_bswap_16" = yes; then + AC_DEFINE(HAVE_BSWAP_16,1,[Define to 1 if bswap_16 is available via byteswap.h]) +fi +AC_MSG_CHECKING(for bswap_64) +AC_CACHE_VAL(krb5_cv_bswap_64, +[AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#if HAVE_BYTESWAP_H + #include + #endif + ]], + [[bswap_64(37);]])], + [krb5_cv_bswap_64=yes], [krb5_cv_bswap_64=no])]) +AC_MSG_RESULT($krb5_cv_bswap_64) +if test "$krb5_cv_bswap_64" = yes; then + AC_DEFINE(HAVE_BSWAP_64,1,[Define to 1 if bswap_64 is available via byteswap.h]) +fi + +# Needed for ksu and some appl stuff. + +case $krb5_cv_host in +alpha*-dec-osf*) + AC_CHECK_LIB(security,setluid, + AC_DEFINE(HAVE_SETLUID,1,[Define if setluid provided in OSF/1 security library]) + KSU_LIBS="-lsecurity" + ) + ;; +esac +AC_SUBST(KSU_LIBS) + +if test $ac_cv_func_setenv = no || test $ac_cv_func_unsetenv = no \ + || test $ac_cv_func_getenv = no; then + SETENVOBJ=setenv.o +else + SETENVOBJ= +fi +AC_SUBST(SETENVOBJ) + +# Check what the return types for gethostbyname_r and getservbyname_r are. + +AC_CHECK_FUNC(gethostbyname_r,[ +ac_cv_func_gethostbyname_r=yes +if test "$ac_cv_func_gethostbyname_r" = yes; then + AC_MSG_CHECKING([if gethostbyname_r returns an int]) + AC_CACHE_VAL(krb5_cv_gethostbyname_r_returns_int, + [AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#include + extern int gethostbyname_r();]])], + [krb5_cv_gethostbyname_r_returns_int=yes], + [krb5_cv_gethostbyname_r_returns_int=no])]) + AC_MSG_RESULT($krb5_cv_gethostbyname_r_returns_int) + + AC_MSG_CHECKING([if gethostbyname_r returns a pointer]) + AC_CACHE_VAL(krb5_cv_gethostbyname_r_returns_ptr, + [AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#include + extern struct hostent *gethostbyname_r();]])], + [krb5_cv_gethostbyname_r_returns_ptr=yes], + [krb5_cv_gethostbyname_r_returns_ptr=no])]) + AC_MSG_RESULT($krb5_cv_gethostbyname_r_returns_ptr) + + if test "$krb5_cv_gethostbyname_r_returns_int" = "$krb5_cv_gethostbyname_r_returns_ptr"; then + AC_MSG_WARN(cannot determine return type of gethostbyname_r -- disabling) + ac_cv_func_gethostbyname_r=no + fi + if test "$krb5_cv_gethostbyname_r_returns_int" = yes; then + AC_DEFINE(GETHOSTBYNAME_R_RETURNS_INT, 1, [Define if gethostbyname_r returns int rather than struct hostent * ]) + fi +fi +if test "$ac_cv_func_gethostbyname_r" = yes; then + AC_DEFINE(HAVE_GETHOSTBYNAME_R, 1, [Define if gethostbyname_r exists and its return type is known]) + AC_CHECK_FUNC(gethostbyaddr_r) +fi +]) + + +# PTHREAD_CFLAGS changes which variant of these functions is declared +# on Solaris 11, so use it for these tests. +old_CFLAGS=$CFLAGS +CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +AC_CHECK_FUNC(getpwnam_r,ac_cv_func_getpwnam_r=yes,ac_cv_func_getpwnam_r=no) +AC_CHECK_FUNC(getpwuid_r,ac_cv_func_getpwuid_r=yes,ac_cv_func_getpwuid_r=no) +if test "$ac_cv_func_getpwnam_r" = yes; then + AC_MSG_CHECKING([return type of getpwnam_r]) + AC_CACHE_VAL(krb5_cv_getpwnam_r_return_type, + [AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#include + extern int getpwnam_r();]])], + [getpwnam_r_returns_int=yes], [getpwnam_r_returns_int=no]) + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#include + extern struct passwd *getpwnam_r();]])], + [getpwnam_r_returns_ptr=yes], [getpwnam_r_returns_ptr=no]) + case "$getpwnam_r_returns_int/$getpwnam_r_returns_ptr" in + yes/no) krb5_cv_getpwnam_r_return_type=int ;; + no/yes) krb5_cv_getpwnam_r_return_type=ptr ;; + *) krb5_cv_getpwnam_r_return_type=unknown ;; + esac]) + AC_MSG_RESULT($krb5_cv_getpwnam_r_return_type) + if test $krb5_cv_getpwnam_r_return_type = int; then + AC_DEFINE(GETPWNAM_R_RETURNS_INT, 1, [Define if getpwnam_r returns an int]) + elif test $krb5_cv_getpwnam_r_return_type = unknown; then + AC_MSG_WARN([Cannot determine getpwnam_r return type, disabling getpwnam_r]) + ac_cv_func_getpwnam_r=no + fi +fi +if test "$ac_cv_func_getpwnam_r" = yes; then + AC_MSG_CHECKING([number of arguments to getpwnam_r]) + AC_CACHE_VAL(krb5_cv_getpwnam_r_args, + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + struct passwd pwx; char buf[1024];]], + [[getpwnam_r("", &pwx, buf, sizeof(buf));]])], + [args4=yes], [args4=no]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + struct passwd pwx, *p; + char buf[1024];]], + [[getpwnam_r("", &pwx, buf, sizeof(buf), &p);]])], + [args5=yes], [args5=no]) + case $args4/$args5 in + yes/no) krb5_cv_getpwnam_r_args=4 ;; + no/yes) krb5_cv_getpwnam_r_args=5 ;; + *) krb5_cv_getpwnam_r_args=unknown ;; + esac]) + AC_MSG_RESULT($krb5_cv_getpwnam_r_args) + if test "$krb5_cv_getpwnam_r_args" = unknown; then + AC_MSG_WARN([Cannot determine number of arguments to getpwnam_r, disabling its use.]) + ac_cv_func_getpwnam_r=no + else + AC_DEFINE(HAVE_GETPWNAM_R,1,[Define if getpwnam_r is available and useful.]) + if test "$krb5_cv_getpwnam_r_args" = 4; then + AC_DEFINE(GETPWNAM_R_4_ARGS,1,[Define if getpwnam_r exists but takes only 4 arguments (e.g., POSIX draft 6 implementations like some Solaris releases).]) + fi + fi +fi +CFLAGS=$old_CFLAGS + +if test "$ac_cv_func_getpwnam_r" = no && test "$ac_cv_func_getpwuid_r" = yes; then + # Actually, we could do this check, and the corresponding checks + # for return type and number of arguments, but I doubt we'll run + # into a system where we'd get to use getpwuid_r but not getpwnam_r. + AC_MSG_NOTICE([getpwnam_r not useful, so disabling getpwuid_r too]) + ac_cv_func_getpwuid_r=no +fi +if test "$ac_cv_func_getpwuid_r" = yes; then + AC_DEFINE(HAVE_GETPWUID_R,1,[Define if getpwuid_r is available and useful.]) + # Hack: Assume getpwuid_r is the shorter form if getpwnam_r is. + if test "$krb5_cv_getpwnam_r_args" = 4; then + AC_DEFINE(GETPWUID_R_4_ARGS,1,[Define if getpwuid_r exists but takes only 4 arguments (e.g., POSIX draft 6 implementations like some Solaris releases).]) + fi +fi + +if test "$ac_cv_func_gmtime_r" = yes; then + AC_MSG_CHECKING([whether gmtime_r returns int]) + AC_CACHE_VAL(krb5_cv_gmtime_r_returns_int, + [AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#include + extern int gmtime_r();]])], + [return_int=yes], [return_int=no]) + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE( + [[#include + extern struct tm *gmtime_r();]])], + [return_ptr=yes], [return_ptr=no]) + case $return_int/$return_ptr in + yes/no) krb5_cv_gmtime_r_returns_int=yes ;; + no/yes) krb5_cv_gmtime_r_returns_int=no ;; + *) # Can't figure it out, punt the function. + ac_cv_func_gmtime_r=no ;; + esac]) + if test "$ac_cv_func_gmtime_r" = no; then + AC_MSG_RESULT(unknown -- ignoring gmtime_r) + else + AC_MSG_RESULT($krb5_cv_gmtime_r_returns_int) + if test "$krb5_cv_gmtime_r_returns_int" = yes; then + AC_DEFINE(GMTIME_R_RETURNS_INT,1,[Define if gmtime_r returns int instead of struct tm pointer, as on old HP-UX systems.]) + fi + fi +fi + +AC_CHECK_FUNC(getservbyname_r,[ +ac_cv_func_getservbyname_r=yes +if test "$ac_cv_func_getservbyname_r" = yes; then + AC_MSG_CHECKING([if getservbyname_r returns an int]) + AC_CACHE_VAL(krb5_cv_getservbyname_r_returns_int, + [AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#include + extern int getservbyname_r();]])], + [krb5_cv_getservbyname_r_returns_int=yes], + [krb5_cv_getservbyname_r_returns_int=no])]) + AC_MSG_RESULT($krb5_cv_getservbyname_r_returns_int) + + AC_MSG_CHECKING([if getservbyname_r returns a pointer]) + AC_CACHE_VAL(krb5_cv_getservbyname_r_returns_ptr, + [AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#include + extern struct servent *getservbyname_r();]])], + [krb5_cv_getservbyname_r_returns_ptr=yes], + [krb5_cv_getservbyname_r_returns_ptr=no])]) + AC_MSG_RESULT($krb5_cv_getservbyname_r_returns_ptr) + + if test "$krb5_cv_getservbyname_r_returns_int" = "$krb5_cv_getservbyname_r_returns_ptr"; then + AC_MSG_WARN(cannot determine return type of getservbyname_r -- disabling) + ac_cv_func_getservbyname_r=no + fi + if test "$krb5_cv_getservbyname_r_returns_int" = yes; then + AC_DEFINE(GETSERVBYNAME_R_RETURNS_INT, 1, [Define if getservbyname_r returns int rather than struct servent * ]) + fi +fi +if test "$ac_cv_func_getservbyname_r" = yes; then + AC_DEFINE(HAVE_GETSERVBYNAME_R, 1, [Define if getservbyname_r exists and its return type is known]) + AC_CHECK_FUNC(getservbyport_r) +fi +]) + +CHECK_DIRENT +AC_TYPE_UID_T + +AC_CHECK_HEADER(termios.h, +[AC_CHECK_FUNC([tcsetattr], + AC_DEFINE(POSIX_TERMIOS,1,[Define if termios.h exists and tcsetattr exists]))]) + +AC_CHECK_HEADERS(poll.h stdlib.h string.h stddef.h sys/types.h sys/file.h sys/param.h sys/stat.h sys/time.h netinet/in.h sys/uio.h sys/filio.h sys/select.h time.h paths.h errno.h) + +# If compiling with IPv6 support, test if in6addr_any functions. +# Irix 6.5.16 defines it, but lacks support in the C library. +if test $krb5_cv_inet6 = yes || test "$krb5_cv_inet6_with_dinet6" = yes ; then + AC_CACHE_CHECK([for in6addr_any definition in library], + [krb5_cv_var_in6addr_any], + [AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#ifdef HAVE_SYS_TYPES_H + #include + #endif + #include + #include + #include + #include + ]], + [[struct sockaddr_in6 in; + in.sin6_addr = in6addr_any; + printf("%x", &in);]])], + [krb5_cv_var_in6addr_any=yes], [krb5_cv_var_in6addr_any=no])]) + if test $krb5_cv_var_in6addr_any = no; then + AC_DEFINE(NEED_INSIXADDR_ANY,1,[Define if in6addr_any is not defined in libc]) + fi +fi + +# then from osconf.h, we have + +AC_CHECK_TYPE(time_t, long) +AC_CHECK_SIZEOF(time_t) +SIZEOF_TIME_T=$ac_cv_sizeof_time_t +AC_SUBST(SIZEOF_TIME_T) + +# Determine where to put the replay cache. + +AC_MSG_CHECKING([for replay cache directory]) +AC_CACHE_VAL(krb5_cv_sys_rcdir, +[ +if test $cross_compiling = yes; then + krb5_cv_sys_rcdir=/var/tmp +else + for t_dir in /var/tmp /usr/tmp /var/usr/tmp /tmp ; do + test -d $t_dir || continue + krb5_cv_sys_rcdir=$t_dir + break + done +fi]) +AC_MSG_RESULT($krb5_cv_sys_rcdir) +KRB5_RCTMPDIR=$krb5_cv_sys_rcdir +AC_SUBST(KRB5_RCTMPDIR) + + +AC_MSG_CHECKING(for socklen_t) +AC_CACHE_VAL(krb5_cv_has_type_socklen_t, +[AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + ]], + [[sizeof(socklen_t);]])], + [krb5_cv_has_type_socklen_t=yes], [krb5_cv_has_type_socklen_t=no])]) +AC_MSG_RESULT($krb5_cv_has_type_socklen_t) +if test $krb5_cv_has_type_socklen_t = yes; then + AC_DEFINE(HAVE_SOCKLEN_T,1,[Define if there is a socklen_t type. If not, probably use size_t]) +fi + +AC_MSG_CHECKING(for struct lifconf) +AC_CACHE_VAL(krb5_cv_has_struct_lifconf, +[AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + ]], + [[sizeof (struct lifconf);]])], + [krb5_cv_has_struct_lifconf=yes], [krb5_cv_has_struct_lifconf=no])]) +AC_MSG_RESULT($krb5_cv_has_struct_lifconf) +if test $krb5_cv_has_struct_lifconf = yes; then + AC_DEFINE(HAVE_STRUCT_LIFCONF,1,[Define if there is a struct lifconf.]) +fi +# HP-UX 11 uses stuct if_laddrconf +AC_MSG_CHECKING(for struct if_laddrconf) +AC_CACHE_VAL(krb5_cv_has_struct_if_laddrconf, +[AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + #include + ]], + [[sizeof(struct if_laddrconf);]])], + [krb5_cv_has_struct_if_laddrconf=yes], + [krb5_cv_has_struct_if_laddrconf=no])]) +AC_MSG_RESULT($krb5_cv_has_struct_if_laddrconf) +if test $krb5_cv_has_struct_if_laddrconf = yes; then + AC_DEFINE(HAVE_STRUCT_IF_LADDRCONF,1,[Define if there is a struct if_laddrconf.]) +fi + + +AC_MSG_CHECKING([for h_errno in netdb.h]) +AC_CACHE_VAL(krb5_cv_header_netdb_h_h_errno, +[AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[int x = h_errno;]])], + [krb5_cv_header_netdb_h_h_errno=yes], + [krb5_cv_header_netdb_h_h_errno=no])]) +AC_MSG_RESULT($krb5_cv_header_netdb_h_h_errno) +if test $krb5_cv_header_netdb_h_h_errno = yes; then + AC_DEFINE([HAVE_NETDB_H_H_ERRNO], 1, + [Define if netdb.h declares h_errno]) +fi + + +AC_ARG_ENABLE([athena], +[ --enable-athena build with MIT Project Athena configuration], +AC_DEFINE(KRB5_ATHENA_COMPAT,1,[Define if MIT Project Athena default configuration should be used]),) + + +AC_C_INLINE +AH_TOP([ +#ifndef KRB5_AUTOCONF_H +#define KRB5_AUTOCONF_H +]) +AH_BOTTOM([ +#if defined(__GNUC__) && !defined(inline) +/* Silence gcc pedantic warnings about ANSI C. */ +# define inline __inline__ +#endif +#endif /* KRB5_AUTOCONF_H */ +]) + +AC_CHECK_TYPES([struct cmsghdr, struct in_pktinfo, struct in6_pktinfo, struct sockaddr_storage], , , [ +#include +#include +#include +]) +AC_CHECK_TYPES([struct rt_msghdr], , , [ +#include +#include +#include +]) + +# Tests for 64-bit edwards25519 code. +AC_CHECK_SIZEOF([size_t]) +AC_CHECK_TYPES([__int128_t, __uint128_t]) + +# types libdb2 wants + +AC_CHECK_TYPES([ssize_t, u_char, u_int, u_long, u_int8_t, u_int16_t, u_int32_t, int8_t, int16_t, int32_t]) + +# Some libdb2 test programs want a shell that supports functions. +FCTSH=false +AC_PATH_PROG(SH,sh,false) +AC_PATH_PROG(SH5,sh5,false) +AC_PATH_PROG(BASH,bash,false) +for prog in $SH $SH5 $BASH; do + AC_MSG_CHECKING(if $prog supports functions) + if $prog -c 'foo() { true; }; foo' >/dev/null 2>&1; then + AC_MSG_RESULT(yes) + FCTSH=$prog + break + else + AC_MSG_RESULT(no) + fi +done +AC_SUBST(FCTSH) + +# Test for POSIX 2001 *printf support (X/Open System Interfaces extension +# to ANSI/ISO C 1999 specification). Specifically, positional +# specifications; not checking for other features like %zx at present. +AC_MSG_CHECKING(for POSIX printf positional specification support) +AC_CACHE_VAL(ac_cv_printf_positional, +[AC_RUN_IFELSE( + [AC_LANG_SOURCE( + [[#include + #include + const char expected[] = "200 100"; + int main() + { + char buf[30]; + sprintf(buf, "%2\$x %1\$d", 100, 512); + if (strcmp(expected, buf)) { + fprintf(stderr, "bad result: <%s> wanted: <%s>\n", + buf, expected); + return 1; + } + return 0; + }]])], + [ac_cv_printf_positional=yes], [ac_cv_printf_positional=no], + [AC_MSG_ERROR(Cannot test for printf positional argument support when cross compiling)])]) +# Nothing for autoconf.h for now. +AC_MSG_RESULT($ac_cv_printf_positional) + + +# for t_locate_kdc test + +AC_PATH_PROG(DIG, dig, false) +AC_PATH_PROG(NSLOOKUP, nslookup, false) + +# for kadmin + +AC_PROG_YACC +ath_compat= +AC_ARG_ENABLE([athena], +[ --enable-athena build with MIT Project Athena configuration], +ath_compat=compat,) + +KRB5_AC_PRIOCNTL_HACK + +AC_CHECK_PROG(PERL,perl,perl) + +# lib/gssapi +AC_CHECK_HEADER(xom.h,[ + include_xom='awk '\''END{printf("%cinclude \n", 35);}'\'' < /dev/null'], [ + include_xom='echo "/* no xom.h */"']) +AC_SUBST(include_xom) + + +# lib/rpc +### Check where struct rpcent is declared. + +# This is necessary to determine: +# 1. If /usr/include/netdb.h declares struct rpcent +# 2. If /usr/include/rpc/netdb.h declares struct rpcent + +# We have our own rpc/netdb.h, and if /usr/include/netdb.h includes +# rpc/netdb.h, then nastiness could happen. + +# Logic: If /usr/include/netdb.h declares struct rpcent, then check +# rpc/netdb.h. If /usr/include/rpc/netdb.h declares struct rpcent, +# then define STRUCT_RPCENT_IN_RPC_NETDB_H, otherwise do not. If +# neither netdb.h nor rpc/netdb.h declares struct rpcent, then define +# STRUCT_RPCENT_IN_RPC_NETDB_H anyway. + +AC_MSG_CHECKING([where struct rpcent is declared]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[struct rpcent e; + char c = e.r_name[0]; + int i = e.r_number;]])], + [netdb_rpcent=yes], [netdb_rpcent=no]) +if test "$netdb_rpcent" = yes; then + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[struct rpcent e; + char c = e.r_name[0]; + int i = e.r_number;]])], + [rpc_netdb_rpcent=yes], [rpc_netdb_rpcent=no]) + if test "$rpc_netdb_rpcent" = yes; then + AC_MSG_RESULT([rpc/netdb.h]) + rpcent_define='#define STRUCT_RPCENT_IN_RPC_NETDB_H' + else + AC_MSG_RESULT([netdb.h]) + fi +else + AC_MSG_RESULT([nowhere]) + rpcent_define='#define STRUCT_RPCENT_IN_RPC_NETDB_H' +fi +AC_SUBST(rpcent_define) + +AC_CHECK_HEADERS(sys/select.h sys/time.h unistd.h) +if test $ac_cv_header_sys_select_h = yes; then + GSSRPC__SYS_SELECT_H='#include ' +else + GSSRPC__SYS_SELECT_H='/* #include */' +fi +AC_SUBST(GSSRPC__SYS_SELECT_H) +if test $ac_cv_header_sys_time_h = yes; then + GSSRPC__SYS_TIME_H='#include ' +else + GSSRPC__SYS_TIME_H='/* #include */' +fi +AC_SUBST(GSSRPC__SYS_TIME_H) +if test $ac_cv_header_unistd_h = yes; then + GSSRPC__UNISTD_H='#include ' +else + GSSRPC__UNISTD_H='/* #include */' +fi +AC_SUBST(GSSRPC__UNISTD_H) + +AC_CACHE_CHECK([for MAXHOSTNAMELEN in sys/param.h], +[krb5_cv_header_sys_param_h_maxhostnamelen], +[AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[int i = MAXHOSTNAMELEN;]])], + [krb5_cv_header_sys_param_h_maxhostnamelen=yes], + [krb5_cv_header_sys_param_h_maxhostnamelen=no])]) +AC_CACHE_CHECK([for MAXHOSTNAMELEN in netdb.h], +[krb5_cv_header_netdb_h_maxhostnamelen], +[AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[int i = MAXHOSTNAMELEN;]])], + [krb5_cv_header_netdb_h_maxhostnamelen=yes], + [krb5_cv_header_netdb_h_maxhostnamelen=no])]) + +GSSRPC__SYS_PARAM_H='/* #include */' +GSSRPC__NETDB_H='/* #include */' +if test $krb5_cv_header_sys_param_h_maxhostnamelen = yes; then + GSSRPC__SYS_PARAM_H='#include ' +else + if test $krb5_cv_header_netdb_h_maxhostnamelen = yes; then + GSSRPC__NETDB_H='#include ' + else + AC_MSG_WARN([can't find MAXHOSTNAMELEN definition; faking it]) + fi +fi +AC_SUBST(GSSRPC__SYS_PARAM_H) +AC_SUBST(GSSRPC__NETDB_H) + +AC_CACHE_CHECK([for BSD type aliases], [krb5_cv_type_bsdaliases], +[AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #if HAVE_UNISTD_H + #include + #endif + ]], + [[u_char c; + u_int i; + u_long l;]])], + [krb5_cv_type_bsdaliases=yes], [krb5_cv_type_bsdaliases=no])]) +if test $krb5_cv_type_bsdaliases = yes; then + GSSRPC__BSD_TYPEALIASES='/* #undef GSSRPC__BSD_TYPEALIASES */' +else + GSSRPC__BSD_TYPEALIASES='#define GSSRPC__BSD_TYPEALIASES 1' +fi +AC_SUBST(GSSRPC__BSD_TYPEALIASES) + +AC_MSG_CHECKING([return type of setrpcent]) +AC_CACHE_VAL(k5_cv_type_setrpcent, +[AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#include + extern void setrpcent();]])], + [k5_cv_type_setrpcent=void], [k5_cv_type_setrpcent=int])]) +AC_MSG_RESULT($k5_cv_type_setrpcent) +AC_DEFINE_UNQUOTED(SETRPCENT_TYPE, $k5_cv_type_setrpcent, [Define as return type of setrpcent]) + +AC_MSG_CHECKING([return type of endrpcent]) +AC_CACHE_VAL(k5_cv_type_endrpcent, +[AC_COMPILE_IFELSE( + [AC_LANG_SOURCE( + [[#include + extern void endrpcent();]])], + [k5_cv_type_endrpcent=void], [k5_cv_type_endrpcent=int])]) +AC_MSG_RESULT($k5_cv_type_endrpcent) +AC_DEFINE_UNQUOTED(ENDRPCENT_TYPE, $k5_cv_type_endrpcent, [Define as return type of endrpcent]) +K5_GEN_FILE(include/gssrpc/types.h:include/gssrpc/types.hin) + +# for pkinit +AC_ARG_ENABLE([pkinit], +[ --disable-pkinit disable PKINIT plugin support],, +enable_pkinit=try) +if test "$enable_pkinit" = yes || test "$enable_pkinit" = try; then + AC_CACHE_CHECK(for a recent enough OpenSSL, k5_cv_openssl_version_okay, +[AC_COMPILE_IFELSE([AC_LANG_SOURCE([#include +#if OPENSSL_VERSION_NUMBER < 0x10000000L +# error openssl is too old, need 1.0.0 +#endif +int i = 1; +])], k5_cv_openssl_version_okay=yes, k5_cv_openssl_version_okay=no)]) + old_LIBS="$LIBS" + AC_CHECK_LIB(crypto, PKCS7_get_signer_info) + AC_CHECK_FUNCS(EVP_PKEY_get_bn_param) + LIBS="$old_LIBS" +fi +if test "$k5_cv_openssl_version_okay" = yes && (test "$enable_pkinit" = yes || test "$enable_pkinit" = try); then + K5_GEN_MAKEFILE(plugins/preauth/pkinit) + K5_GEN_MAKEFILE(tests/softpkcs11) + PKINIT=yes +elif test "$k5_cv_openssl_version_okay" = no && test "$enable_pkinit" = yes; then + AC_MSG_ERROR([Version of OpenSSL is too old; cannot enable PKINIT.]) +else + AC_DEFINE([DISABLE_PKINIT], 1, [Define to disable PKINIT plugin support]) + AC_MSG_NOTICE([Disabling PKINIT support.]) + PKINIT=no +fi +AC_SUBST(PKINIT) + +# for lib/apputils +AC_REPLACE_FUNCS(daemon) + +# For Python tests. Python version 3.2.4 is required as prior +# versions do not accept string input to subprocess.Popen.communicate +# when universal_newlines is set. +PYTHON_MINVERSION=3.2.4 +AC_SUBST(PYTHON_MINVERSION) +AC_CHECK_PROG(PYTHON,python3,python3) +if test x"$PYTHON" = x; then + AC_CHECK_PROG(PYTHON,python,python) +fi +HAVE_PYTHON=no +if test x"$PYTHON" != x; then + wantver="(sys.hexversion >= 0x30204F0)" + if "$PYTHON" -c "import sys; sys.exit(not $wantver and 1 or 0)"; then + HAVE_PYTHON=yes + fi +fi +AC_SUBST(HAVE_PYTHON) + +# For cmocka tests. +CMOCKA_LIBS= +HAVE_CMOCKA=no +HAVE_CMOCKA_H=no +HAVE_CMOCKA_LIB=no +AC_CHECK_HEADER(cmocka.h, [HAVE_CMOCKA_H=yes], :, [ +#include +#include +#include ]) +AC_CHECK_LIB(cmocka, _cmocka_run_group_tests, [HAVE_CMOCKA_LIB=yes]) +if test "$HAVE_CMOCKA_LIB" = yes && test "$HAVE_CMOCKA_H" = yes; then + HAVE_CMOCKA=yes + CMOCKA_LIBS='-lcmocka' + AC_DEFINE([HAVE_CMOCKA],1,[Define if cmocka library is available.]) +fi +AC_SUBST(HAVE_CMOCKA) +AC_SUBST(CMOCKA_LIBS) + +# For URI lookup tests. Requires resolv_wrapper >= 1.1.5 for URI +# support. +HAVE_RESOLV_WRAPPER=0 +PKG_CHECK_EXISTS([resolv_wrapper >= 1.1.5], [HAVE_RESOLV_WRAPPER=1]) +AC_SUBST(HAVE_RESOLV_WRAPPER) + +# for plugins/kdb/db2 + +# AIX is unusual in that it wants all symbols resolved at link time +# Fortunately, it will allow us to link the kdb library now, even if +# it is linked again later. +case $krb5_cv_host in +*-*-aix*) + DB_EXTRA_LIBS=-ldb + ;; +*) + DB_EXTRA_LIBS= + ;; +esac +AC_SUBST(DB_EXTRA_LIBS) + + + +# Warn about possible thread safety issues. These functions have all +# been checked for previously. +tsfuncs="getpwnam_r getpwuid_r gethostbyname_r getservbyname_r gmtime_r localtime_r" +if test "$enable_thread_support" = yes; then + tsmissing="" + for ts in $tsfuncs; do + if eval "test \"\${ac_cv_func_$ts}\" != yes"; then + tsmissing="$tsmissing $ts" + fi + done + if test "$ac_cv_func_res_nsearch/$ac_cv_lib_resolv_res_nsearch" = "no/no"; then + tsmissing="$tsmissing res_nsearch" + fi + if test "$tsmissing" != ""; then + AC_MSG_WARN([Some functions that are needed for library thread]) + AC_MSG_WARN([safety appear to be missing.]) + for ts in $tsmissing; do + AC_MSG_WARN([ missing thread-safe function: $ts]) + done + AC_MSG_WARN([Without these functions, the installed libraries]) + AC_MSG_WARN([may not be thread-safe.]) + fi # tsmissing not empty +fi # enable_thread_support + +# Sadly, we seem to have accidentally committed ourselves in 1.4 to +# an ABI that includes the existence of libkrb5support.0 even +# though random apps should never use anything from it. And on +# the Mac, to which that didn't apply, we can't use major version 0. + +case $krb5_cv_host in +*-*-darwin* | *-*-rhapsody*) SUPPORTLIB_MAJOR=1 ;; +*) SUPPORTLIB_MAJOR=0 ;; +esac +AC_SUBST(SUPPORTLIB_MAJOR) + + +if test "$COM_ERR_VERSION" = k5 ; then + K5_GEN_MAKEFILE(util/et) +fi +if test "$SS_VERSION" = k5 ; then + K5_GEN_MAKEFILE(util/ss) +fi + + +ldap_plugin_dir="" +ldap_lib="" +if test -n "$OPENLDAP_PLUGIN"; then + AC_CHECK_HEADERS(ldap.h lber.h, :, [AC_MSG_ERROR($ac_header not found)]) + AC_CHECK_LIB(ldap, ldap_str2dn, :, [AC_MSG_ERROR(libldap not found or missing ldap_str2dn)]) + + BER_OKAY=0 + AC_CHECK_LIB(ldap, ber_init, [BER_OKAY=1]) + if test "$BER_OKAY" = "1"; then + LDAP_LIBS='-lldap' + else + AC_CHECK_LIB(lber, ber_init, [BER_OKAY=1], [AC_MSG_WARN([libber not found])]) + if test "$BER_OKAY" = "1"; then + LDAP_LIBS='-lldap -llber' + else + AC_MSG_ERROR("BER library missing - cannot build LDAP database module") + fi + fi + AC_DEFINE([ENABLE_LDAP], 1, [Define if LDAP KDB support within the Kerberos library (mainly ASN.1 code) should be enabled.]) + AC_SUBST(LDAP_LIBS) + + AC_CHECK_HEADERS([sasl/sasl.h], [HAVE_SASL=yes], [HAVE_SASL=no]) + AC_SUBST(HAVE_SASL) + if test "$HAVE_SASL" = no; then + AC_MSG_WARN([not building LDAP SASL support]) + fi + + K5_GEN_MAKEFILE(plugins/kdb/ldap) + K5_GEN_MAKEFILE(plugins/kdb/ldap/ldap_util) + K5_GEN_MAKEFILE(plugins/kdb/ldap/libkdb_ldap) + ldap_plugin_dir='plugins/kdb/ldap plugins/kdb/ldap/ldap_util' + LDAP=yes +else + LDAP=no +fi +AC_SUBST(ldap_plugin_dir) +AC_SUBST(LDAP) +# This check is for plugins/preauth/securid_sam2 +sam2_plugin="" +old_CFLAGS=$CFLAGS +CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +AC_CHECK_LIB(aceclnt, SD_Init, [ + AC_MSG_NOTICE([Enabling RSA securID support]) + K5_GEN_MAKEFILE(plugins/preauth/securid_sam2) + sam2_plugin=plugins/preauth/securid_sam2 + ]) +AC_SUBST(sam2_plugin) +CFLAGS=$old_CFLAGS + +lmdb_plugin_dir="" +HAVE_LMDB=no +AC_ARG_WITH([lmdb], + [AS_HELP_STRING([--with-lmdb], + [compile LMDB database backend module @<:@auto@:>@])], + [], [withval=auto]) +if test "$withval" = auto -o "$withval" = yes; then + AC_CHECK_LIB([lmdb],[mdb_env_create],[have_lmdb=true],[have_lmdb=false]) + if test "$have_lmdb" = true; then + LMDB_LIBS=-llmdb + HAVE_LMDB=yes + lmdb_plugin_dir='plugins/kdb/lmdb' + K5_GEN_MAKEFILE(plugins/kdb/lmdb) + elif test "$withval" = yes; then + AC_MSG_ERROR([liblmdb not found]) + fi +fi +AC_SUBST(HAVE_LMDB) +AC_SUBST(LMDB_LIBS) +AC_SUBST(lmdb_plugin_dir) + +# Kludge for simple server --- FIXME is this the best way to do this? + +if test "$ac_cv_lib_socket" = "yes" -a "$ac_cv_lib_nsl" = "yes"; then + AC_DEFINE(BROKEN_STREAMS_SOCKETS,1,[Define if socket can't be bound to 0.0.0.0]) +fi + +# Compile with libedit support in ss by default if available. Compile +# with readline only if asked, to avoid a default GPL dependency. +AC_ARG_WITH([libedit], + [AS_HELP_STRING([--without-libedit], [do not compile with libedit])], + [], [with_libedit=default]) +AC_ARG_WITH([readline], + [AS_HELP_STRING([--with-readline], [compile with GNU Readline])], + [], [with_readline=no]) +if test "x$with_readline" = xyes; then + with_libedit=no +fi +RL_CFLAGS= +RL_LIBS= +if test "x$with_libedit" != xno; then + PKG_CHECK_MODULES(LIBEDIT, libedit, [have_libedit=yes], [have_libedit=no]) + if test "x$have_libedit" = xyes; then + RL_CFLAGS=$LIBEDIT_CFLAGS + RL_LIBS=$LIBEDIT_LIBS + AC_DEFINE([HAVE_LIBEDIT], 1, [Define if building with libedit.]) + AC_MSG_NOTICE([Using libedit for readline support]) + elif test "x$with_libedit" = xyes; then + # We were explicitly asked for libedit and couldn't find it. + AC_MSG_ERROR([Could not detect libedit with pkg-config]) + else + AC_MSG_NOTICE([Not using any readline support]) + fi +elif test "x$with_readline" = xyes; then + AC_MSG_NOTICE([Using GNU Readline]) + AC_CHECK_LIB([readline], [main], :, + AC_MSG_FAILURE([Cannot find readline library.])) + AC_DEFINE([HAVE_READLINE], 1, [Define if building with GNU Readline.]) + RL_LIBS='-lreadline' +else + AC_MSG_RESULT([Not using any readline support]) +fi +AC_SUBST([RL_CFLAGS]) +AC_SUBST([RL_LIBS]) + +AC_ARG_WITH([system-verto], + [AS_HELP_STRING([--with-system-verto], [always use system verto library])], + [], [with_system_verto=default]) +VERTO_VERSION=k5 +if test "x$with_system_verto" != xno; then + PKG_CHECK_MODULES(VERTO, libverto, [have_sysverto=yes], [have_sysverto=no]) + if test "x$have_sysverto" = xyes; then + VERTO_VERSION=sys + elif test "x$with_system_verto" = xyes; then + AC_MSG_ERROR([cannot detect system libverto]) + fi +fi +if test "x$VERTO_VERSION" = xsys; then + AC_MSG_NOTICE([Using system libverto]) +else + VERTO_CFLAGS= + VERTO_LIBS="-lverto" + AC_MSG_NOTICE([Using built-in libverto]) +fi +AC_SUBST([VERTO_CFLAGS]) +AC_SUBST([VERTO_LIBS]) +AC_SUBST([VERTO_VERSION]) + +AC_PATH_PROG(GROFF, groff) + +# Make localedir work in autoconf 2.5x. +if test "${localedir+set}" != set; then + localedir='$(datadir)/locale' +fi +AC_SUBST(localedir) + +# Determine the default macOS ccache type and whether to build the KCM +# Mach RPC support. +MACOS_FRAMEWORK= +dnl The outer brackets around the case statement prevent m4 from +dnl eating the brackets in the glob patterns, but also prevent us from +dnl using AC_DEFINE within the body. +[case $host in +*-*-darwin[0-9].* | *-*-darwin10.*) + # Use the normal default cache type for macOS 10.6 (Darwin 10) and + # prior. Build the KCM Mach RPC support. + OSX=osx + ;; +*-*-darwin*) + # macOS 10.6 (Darwin 11) uses the KCM type by default. macOS 11 + # (Darwin 20) uses an xpc-based cache type called XCACHE by default. + # We can access either of these collections via a macos-specific + # implementation of the API cache type. Build the KCM Mach RPC + # support. + OSX=osx + macos_defccname=API: + MACOS_FRAMEWORK="-framework Kerberos" + ;; +*) + # This is not macOS; do not build the Mach RPC support and use the + # normal default cache type. + OSX=no + ;; +esac] +if test "$macos_defccname" = API:; then + AC_DEFINE(USE_CCAPI_MACOS, 1, [Define to build macOS CCAPI client]) +fi +AC_SUBST(OSX) +AC_SUBST(MACOS_FRAMEWORK) + +# Build-time default ccache, keytab, and client keytab names. These +# can be given as variable arguments DEFCCNAME, DEFKTNAME, and +# DEFCKTNAME. Otherwise, we try to get the OS defaults from +# krb5-config if we can, or fall back to hardcoded defaults. +AC_ARG_VAR(DEFCCNAME, [Default ccache name]) +AC_ARG_VAR(DEFKTNAME, [Default keytab name]) +AC_ARG_VAR(DEFCKTNAME, [Default client keytab name]) +AC_ARG_WITH([krb5-config], + [AS_HELP_STRING([--with-krb5-config=PATH], + [path to existing krb5-config program for defaults])], + [], [with_krb5_config=krb5-config]) +if test "x$with_krb5_config" != xno; then + if test "x$with_krb5_config" = xyes; then + with_krb5_config=krb5-config + fi + if $with_krb5_config --help 2>&1 | grep defccname >/dev/null; then + AC_MSG_NOTICE([Using $with_krb5_config for build defaults]) + : "${DEFCCNAME=`$with_krb5_config --defccname`}" + : "${DEFKTNAME=`$with_krb5_config --defktname`}" + : "${DEFCKTNAME=`$with_krb5_config --defcktname`}" + fi +fi +if test "${DEFCCNAME+set}" != set; then + if test "${macos_defccname+set}" = set; then + DEFCCNAME=$macos_defccname + else + DEFCCNAME=FILE:/tmp/krb5cc_%{uid} + fi +fi +if test "${DEFKTNAME+set}" != set; then + DEFKTNAME=FILE:/etc/krb5.keytab +fi +if test "${DEFCKTNAME+set}" != set; then + AX_RECURSIVE_EVAL($localstatedir, exp_localstatedir) + DEFCKTNAME=FILE:$exp_localstatedir/krb5/user/%{euid}/client.keytab +fi +AC_MSG_NOTICE([Default ccache name: $DEFCCNAME]) +AC_MSG_NOTICE([Default keytab name: $DEFKTNAME]) +AC_MSG_NOTICE([Default client keytab name: $DEFCKTNAME]) +AC_DEFINE_UNQUOTED(DEFCCNAME, ["$DEFCCNAME"], [Define to default ccache name]) +AC_DEFINE_UNQUOTED(DEFKTNAME, ["$DEFKTNAME"], [Define to default keytab name]) +AC_DEFINE_UNQUOTED(DEFCKTNAME, ["$DEFCKTNAME"], + [Define to default client keytab name]) + +AC_ARG_VAR(PKCS11_MODNAME, [Default PKCS11 module name]) +if test "${PKCS11_MODNAME+set}" != set; then + PKCS11_MODNAME=opensc-pkcs11.so +fi +AC_MSG_NOTICE([Default PKCS11 module name: $PKCS11_MODNAME]) +AC_DEFINE_UNQUOTED(PKCS11_MODNAME, ["$PKCS11_MODNAME"], + [Default PKCS11 module name]) + +AC_CONFIG_FILES([build-tools/krb5-config], [chmod +x build-tools/krb5-config]) +AC_CONFIG_FILES([build-tools/kadm-server.pc + build-tools/kadm-client.pc + build-tools/kdb.pc + build-tools/krb5.pc + build-tools/krb5-gssapi.pc + build-tools/mit-krb5.pc + build-tools/mit-krb5-gssapi.pc + build-tools/gssrpc.pc +]) +V5_AC_OUTPUT_MAKEFILE(. + + util util/support util/profile util/profile/testmod + util/verto + + lib lib/kdb + + lib/crypto lib/crypto/krb lib/crypto/crypto_tests + lib/crypto/builtin lib/crypto/builtin/des + lib/crypto/builtin/aes lib/crypto/builtin/camellia + lib/crypto/builtin/md4 lib/crypto/builtin/md5 + lib/crypto/builtin/sha1 lib/crypto/builtin/sha2 + lib/crypto/builtin/enc_provider lib/crypto/builtin/hash_provider + lib/crypto/openssl lib/crypto/openssl/des + lib/crypto/openssl/enc_provider lib/crypto/openssl/hash_provider + + lib/krb5 lib/krb5/error_tables lib/krb5/asn.1 lib/krb5/ccache + lib/krb5/keytab lib/krb5/krb lib/krb5/rcache lib/krb5/os + lib/krb5/unicode + + lib/gssapi lib/gssapi/generic lib/gssapi/krb5 lib/gssapi/spnego + lib/gssapi/mechglue + + lib/rpc lib/rpc/unit-test + + lib/kadm5 lib/kadm5/clnt lib/kadm5/srv + lib/krad + lib/apputils + + kdc kprop config-files build-tools man doc include + + plugins/certauth/test + plugins/gssapi/negoextest + plugins/hostrealm/test + plugins/localauth/test + plugins/kadm5_hook/test + plugins/kadm5_auth/test + plugins/pwqual/test + plugins/audit + plugins/audit/test + plugins/kdb/db2 + plugins/kdb/db2/libdb2 + plugins/kdb/db2/libdb2/hash + plugins/kdb/db2/libdb2/btree + plugins/kdb/db2/libdb2/db + plugins/kdb/db2/libdb2/mpool + plugins/kdb/db2/libdb2/recno + plugins/kdb/db2/libdb2/test + plugins/kdb/test + plugins/kdcpolicy/test + plugins/preauth/otp + plugins/preauth/spake + plugins/preauth/test + plugins/authdata/greet_client + plugins/authdata/greet_server + plugins/tls/k5tls + + clients clients/klist clients/kinit clients/kvno + clients/kdestroy clients/kpasswd clients/ksu clients/kswitch + + kadmin kadmin/cli kadmin/dbutil kadmin/ktutil kadmin/server + + appl + appl/sample appl/sample/sclient appl/sample/sserver + appl/simple appl/simple/client appl/simple/server + appl/gss-sample appl/user_user + + tests tests/asn.1 tests/create tests/hammer tests/verify tests/gssapi + tests/threads tests/shlib tests/gss-threads tests/misc +) diff --git a/krb5-1.21.3/src/deps b/krb5-1.21.3/src/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/doc/Doxyfile.in b/krb5-1.21.3/src/doc/Doxyfile.in new file mode 100644 index 00000000..aeaae645 --- /dev/null +++ b/krb5-1.21.3/src/doc/Doxyfile.in @@ -0,0 +1,15 @@ +PROJECT_NAME = Kerberos_doxygen +OUTPUT_DIRECTORY = doxy +JAVADOC_AUTOBRIEF = YES +OPTIMIZE_OUTPUT_FOR_C = YES +WARN_IF_UNDOCUMENTED = NO +SHOW_FILES = NO +EXTENSION_MAPPING = hin=C +INPUT = @SRC@/include/krb5/krb5.hin @DOC@/doxy_examples +EXAMPLE_PATH = @DOC@/doxy_examples +GENERATE_HTML = NO +GENERATE_LATEX = NO +GENERATE_XML = YES +PREDEFINED = KRB5_DEPRECATED KRB5_OLD_CRYPTO +CASE_SENSE_NAMES = NO +QUIET = YES diff --git a/krb5-1.21.3/src/doc/Makefile.in b/krb5-1.21.3/src/doc/Makefile.in new file mode 100644 index 00000000..a1b0cff0 --- /dev/null +++ b/krb5-1.21.3/src/doc/Makefile.in @@ -0,0 +1,135 @@ +mydir=doc +BUILDTOP=$(REL).. + +SPHINX_ARGS=@MAINT@-W +SPHINX_BUILD=sphinx-build $(SPHINX_ARGS) +DOXYGEN=doxygen + +docsrc=$(top_srcdir)/../doc +sysconfdir=@sysconfdir@ +DEFCCNAME=@DEFCCNAME@ +DEFKTNAME=@DEFKTNAME@ +DEFCKTNAME=@DEFCKTNAME@ +PKCS11_MODNAME=@PKCS11_MODNAME@ + +RST_SOURCES= _static \ + _templates \ + conf.py \ + index.rst \ + admin \ + appdev \ + basic \ + build \ + formats \ + plugindev \ + user \ + about.rst \ + build_this.rst \ + copyright.rst \ + mitK5defaults.rst \ + mitK5features.rst \ + mitK5license.rst \ + notice.rst \ + resources.rst + +PDFDIR=$(docsrc)/pdf +PDFDOCS= admin appdev basic build plugindev user +LATEXOPTS= + +# Create HTML documentation in $(docsrc)/html suitable for a +# release tarball or the web site (that is, without substitutions for +# configured paths). This can be done in an unconfigured source tree +# as: +# make -f Makefile.in SPHINX_ARGS= htmlsrc +html: composite + rm -rf $(docsrc)/html + $(SPHINX_BUILD) -q rst_composite $(docsrc)/html + +# Dummy target for use in an unconfigured source tree. +htmlsrc: + $(MAKE) -f Makefile.in srcdir=. top_srcdir=.. PYTHON=python3 html clean + +# Create HTML documentation in html_subst suitable for +# installation by an OS package, with substitutions for configured +# paths. +substhtml: composite paths.py + rm -rf html_subst + cp paths.py rst_composite + $(SPHINX_BUILD) -t pathsubs -q rst_composite html_subst + +# Create an ASCII (okay, UTF-8) version of the NOTICE file +notice.txt: $(docsrc)/conf.py $(docsrc)/notice.rst $(docsrc)/version.py + $(SPHINX_BUILD) -b text -t notice -q $(docsrc) . + +NOTICE: notice.txt + cp notice.txt $(top_srcdir)/../NOTICE + +$(PDFDIR): composite + $(SPHINX_BUILD) -b latex -q rst_composite $(PDFDIR) + # sphinx-build generates a gmake-specific Makefile that we don't use + mv $(PDFDIR)/Makefile $(PDFDIR)/GMakefile + +# Not pretty. Can't use a suffix rule .tex.pdf without a Makefile in +# $(PDFDIR) because pdflatex looks for include files in the current +# working directory. The sphinx-build Makefile is quite conservative +# and runs pdflatex five times; we can be slightly less conservative. +pdf: $(PDFDIR) + (cd $(PDFDIR) && \ + for i in $(PDFDOCS); do \ + texfile=`echo $${i}.tex` && \ + idxfile=`echo $${i}.idx` && \ + pdflatex $(LATEXOPTS) $$texfile && \ + pdflatex $(LATEXOPTS) $$texfile && \ + makeindex -s python.ist $$idxfile || true; \ + pdflatex $(LATEXOPTS) $$texfile && \ + pdflatex $(LATEXOPTS) $$texfile; done && \ + rm -f *.dvi *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla \ + ) + +# Use doxygen to generate API documentation, translate it into RST +# format, and then create a composite of $(docsrc)'s RST and the +# generated files in rst_composite. Used by the html and substhtml targets. +composite: Doxyfile $(docsrc)/version.py + rm -rf doxy rst_apiref rst_composite + $(DOXYGEN) + (cwd=`pwd`; cd $(docsrc)/tools && \ + $(PYTHON) doxy.py -i $$cwd/doxy/xml -o $$cwd/rst_apiref) + mkdir -p rst_composite + do_subdirs="$(RST_SOURCES)" ; \ + for i in $$do_subdirs; do \ + cp -r $(docsrc)/$$i rst_composite; \ + done + cp rst_apiref/*.rst rst_composite/appdev/refs/api + cp rst_apiref/types/*.rst rst_composite/appdev/refs/types + cp rst_apiref/macros/*.rst rst_composite/appdev/refs/macros + cp $(docsrc)/version.py rst_composite + +Doxyfile: $(srcdir)/Doxyfile.in + sed -e 's|@SRC@|$(top_srcdir)|g' \ + -e 's|@DOC@|$(top_srcdir)/../doc|g' $(srcdir)/Doxyfile.in > $@ + +paths.py: + rm -f $@ + echo 'bindir = "``$(CLIENT_BINDIR)``"' > $@ + echo 'sbindir = "``$(SERVER_BINDIR)``"' >> $@ + echo 'libdir = "``$(KRB5_LIBDIR)``"' >> $@ + echo 'localstatedir = "``$(localstatedir)``"' >> $@ + echo 'runstatedir = "``$(runstatedir)``"' >> $@ + echo 'sysconfdir = "``$(sysconfdir)``"' >> $@ + echo 'ccache = "``$(DEFCCNAME)``"' >> $@ + echo 'keytab = "``$(DEFKTNAME)``"' >> $@ + echo 'ckeytab = "``$(DEFCKTNAME)``"' >> $@ + echo 'pkcs11_modname = "``$(PKCS11_MODNAME)``"' >> $@ + +# Dummy rule that man/Makefile can invoke +version.py: $(docsrc)/version.py + +$(docsrc)/version.py: $(top_srcdir)/patchlevel.h $(srcdir)/version.py.in + rm -f $@ + $(CC) -E -I$(top_srcdir) - < $(srcdir)/version.py.in > $@ + +clean: + rm -rf doxy rst_apiref rst_composite rst_notice html_subst \ + Doxyfile paths.py $(docsrc)/version.py notice.txt \ + $(docsrc)/html/.doctrees $(docsrc)/pdf/.doctrees \ + $(docsrc)/tools/*.pyc diff --git a/krb5-1.21.3/src/doc/deps b/krb5-1.21.3/src/doc/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/doc/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/doc/version.py.in b/krb5-1.21.3/src/doc/version.py.in new file mode 100644 index 00000000..0a344a77 --- /dev/null +++ b/krb5-1.21.3/src/doc/version.py.in @@ -0,0 +1,21 @@ +#include "patchlevel.h" + +r_major = KRB5_MAJOR_RELEASE +r_minor = KRB5_MINOR_RELEASE +r_patch = KRB5_PATCHLEVEL + +#ifdef KRB5_RELTAIL +r_tail = KRB5_RELTAIL +#else +r_tail = None +#endif +#ifdef KRB5_RELDATE +r_date = KRB5_RELDATE +#else +r_date = None +#endif +#ifdef KRB5_RELTAG +r_tag = KRB5_RELTAG +#else +r_date = None +#endif diff --git a/krb5-1.21.3/src/include/CredentialsCache.h b/krb5-1.21.3/src/include/CredentialsCache.h new file mode 100644 index 00000000..1c20f9de --- /dev/null +++ b/krb5-1.21.3/src/include/CredentialsCache.h @@ -0,0 +1,1529 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/CredentialsCache.h */ +/* + * Copyright 1998-2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __CREDENTIALSCACHE__ +#define __CREDENTIALSCACHE__ + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) +#include + +/* Notifications which are sent when the ccache collection or a ccache change. + * Notifications are sent to the distributed notification center. + * The object for kCCAPICacheCollectionChangedNotification is NULL. + * The object for kCCAPICCacheChangedNotification is a CFString containing the + * name of the ccache. + * + * Note: Notifications are not sent if the CCacheServer crashes. */ +#define kCCAPICacheCollectionChangedNotification CFSTR ("CCAPICacheCollectionChangedNotification") +#define kCCAPICCacheChangedNotification CFSTR ("CCAPICCacheChangedNotification") +#endif + +#if defined(_WIN32) +#include +#include "win-mac.h" +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)) +#pragma pack(push,2) +#endif + +#if defined(_WIN32) +#define CCACHE_API __declspec(dllexport) + +#if _INTEGRAL_MAX_BITS >= 64 && _MSC_VER >= 1500 && !defined(_WIN64) && !defined(_USE_32BIT_TIME_T) +#if defined(_TIME_T_DEFINED) || defined(_INC_IO) || defined(_INC_TIME) || defined(_INC_WCHAR) +#error time_t has been defined as a 64-bit integer which is incompatible with Kerberos on this platform. +#endif /* _TIME_T_DEFINED */ +#define _USE_32BIT_TIME_T +#endif +#else +#define CCACHE_API +#endif + +/*! + * \mainpage Credentials Cache API (CCAPI) Documentation + * + * \section toc Table of Contents + * + * \li \ref introduction + * \li \ref error_handling + * \li \ref synchronization_atomicity + * \li \ref memory_management + * \li \ref opaque_types + * + * \li \ref ccapi_constants_reference + * \li \ref ccapi_types_reference + * + * \li \ref cc_context_reference + * \li \ref cc_context_f "cc_context_t Functions" + * + * \li \ref cc_ccache_reference + * \li \ref cc_ccache_f "cc_ccache_t Functions" + * + * \li \ref cc_credentials_reference + * \li \ref cc_credentials_f "cc_credentials_t Functions" + * + * \li \ref cc_ccache_iterator_reference + * \li \ref cc_ccache_iterator_f "cc_ccache_iterator_t Functions" + * + * \li \ref cc_credentials_iterator_reference + * \li \ref cc_credentials_iterator_f "cc_credentials_iterator_t Functions" + * + * \li \ref cc_string_reference + * \li \ref cc_string_f "cc_string_t Functions" + * + * \section introduction Introduction + * + * This is the specification for an API which provides Credentials Cache + * services for Kerberos v5 (and previously v4). The idea behind this API is + * that multiple Kerberos implementations can share a single collection of + * credentials caches, mediated by this API specification. On the Mac OS and + * Microsoft Windows platforms this will allow single-login, even when more + * than one Kerberos shared library is in use on a particular system. + * + * Abstractly, a credentials cache collection contains one or more credentials + * caches, or ccaches. A ccache is uniquely identified by its name, which is + * a string internal to the API and not intended to be presented to users. + * The user presentable identifier of a ccache is its principal. + * + * Unlike the previous versions of the API, version 3 of the API could store + * credentials for multiple Kerberos versions in the same ccache. + * + * At any given time, one ccache is the "default" ccache. The exact meaning + * of a default ccache is OS-specific; refer to implementation requirements + * for details. + * + * \section error_handling Error Handling + * + * All functions of the API return some of the error constants listed FIXME; + * the exact list of error constants returned by any API function is provided + * in the function descriptions below. + * + * When returning an error constant other than ccNoError or ccIteratorEnd, API + * functions never modify any of the values passed in by reference. + * + * \section synchronization_atomicity Synchronization and Atomicity + * + * Every function in the API is atomic. In order to make a series of calls + * atomic, callers should lock the ccache or cache collection they are working + * with to advise other callers not to modify that container. Note that + * advisory locks are per container so even if you have a read lock on the cache + * collection other callers can obtain write locks on ccaches in that cache + * collection. + * + * Note that iterators do not iterate over ccaches and credentials atomically + * because locking ccaches and the cache collection over every iteration would + * degrade performance considerably under high load. However, iterators do + * guarantee a consistent view of items they are iterating over. Iterators + * will never return duplicate entries or skip entries when items are removed + * or added to the container they are iterating over. + * + * An application can always lock a ccache or the cache collection to guarantee + * that other callers participating in the advisory locking system do not + * modify the ccache or cache collection. + * + * Implementations should not use copy-on-write techniques to implement locks + * because those techniques imply that same parts of the ccache collection + * remain visible to some callers even though they are not present in the + * collection, which is a potential security risk. For example, a copy-on-write + * technique might make a copy of the entire collection when a read lock is + * acquired, so as to allow the owner of the lock to access the collection in + * an apparently unmodified state, while also allowing others to make + * modifications to the collection. However, this would also enable the owner + * of the lock to indefinitely (until the expiration time) use credentials that + * have actually been deleted from the collection. + * + * \section memory_management Object Memory Management + * + * The lifetime of an object returned by the API is until release() is called + * for it. Releasing one object has no effect on existence of any other object. + * For example, a ccache obtained within a context continue to exist when the + * context is released. + * + * Every object returned by the API (cc_context_t, cc_ccache_t, cc_ccache_iterator_t, + * cc_credentials_t, cc_credentials_iterator_t, cc_string_t) is owned by the + * caller of the API, and it is the responsibility of the caller to call release() + * for every object to prevent memory leaks. + * + * \section opaque_types Opaque Types + * + * All of the opaque high-level types in CCache API are implemented as structures + * of function pointers and private data. To perform some operation on a type, the + * caller of the API has to first obtain an instance of that type, and then call the + * appropriate function pointer from that instance. For example, to call + * get_change_time() on a cc_context_t, one would call cc_initialize() which creates + * a new cc_context_t and then call its get_change_time(), like this: + * + * \code + * cc_context_t context; + * cc_int32 err = cc_initialize (&context, ccapi_version_3, nil, nil); + * if (err == ccNoError) + * time = context->functions->get_change_time (context) + * \endcode + * + * All API functions also have convenience preprocessor macros, which make the API + * seem completely function-based. For example, cc_context_get_change_time + * (context, time) is equivalent to context->functions->get_change_time + * (context, time). The convenience macros follow the following naming convention: + * + * The API function some_function() + * \code + * cc_type_t an_object; + * result = an_object->functions->some_function (opaque_pointer, args) + * \endcode + * + * has an equivalent convenience macro of the form cc_type_some_function(): + * \code + * cc_type_t an_object; + * result = cc_type_some_function (an_object, args) + * \endcode + * + * The specifications below include the names for both the functions and the + * convenience macros, in that order. For clarity, it is recommended that clients + * using the API use the convenience macros, but that is merely a stylistic choice. + * + * Implementing the API in this manner allows us to extend and change the interface + * in the future, while preserving compatibility with older clients. + * + * For example, consider the case when the signature or the semantics of a cc_ccache_t + * function is changed. The API version number is incremented. The library + * implementation contains both a function with the old signature and semantics and + * a function with the new signature and semantics. When a context is created, the API + * version number used in that context is stored in the context, and therefore it can + * be used whenever a ccache is created in that context. When a ccache is created in a + * context with the old API version number, the function pointer structure for the + * ccache is filled with pointers to functions implementing the old semantics; when a + * ccache is created in a context with the new API version number, the function pointer + * structure for the ccache is filled with poitners to functions implementing the new + * semantics. + * + * Similarly, if a function is added to the API, the version number in the context can + * be used to decide whether to include the implementation of the new function in the + * appropriate function pointer structure or not. + */ + +/*! + * \defgroup ccapi_constants_reference Constants + * @{ + */ + +/*! + * API version numbers + * + * These constants are passed into cc_initialize() to indicate the version + * of the API the caller wants to use. + * + * CCAPI v1 and v2 are deprecated and should not be used. + */ +enum { + ccapi_version_2 = 2, + ccapi_version_3 = 3, + ccapi_version_4 = 4, + ccapi_version_5 = 5, + ccapi_version_6 = 6, + ccapi_version_7 = 7, + ccapi_version_max = ccapi_version_7 +}; + +/*! + * Error codes + */ +enum { + + ccNoError = 0, /*!< Success. */ + + ccIteratorEnd = 201, /*!< Iterator is done iterating. */ + ccErrBadParam, /*!< Bad parameter (NULL or invalid pointer where valid pointer expected). */ + ccErrNoMem, /*!< Not enough memory to complete the operation. */ + ccErrInvalidContext, /*!< Context is invalid (e.g., it was released). */ + ccErrInvalidCCache, /*!< CCache is invalid (e.g., it was released or destroyed). */ + + /* 206 */ + ccErrInvalidString, /*!< String is invalid (e.g., it was released). */ + ccErrInvalidCredentials, /*!< Credentials are invalid (e.g., they were released), or they have a bad version. */ + ccErrInvalidCCacheIterator, /*!< CCache iterator is invalid (e.g., it was released). */ + ccErrInvalidCredentialsIterator, /*!< Credentials iterator is invalid (e.g., it was released). */ + ccErrInvalidLock, /*!< Lock is invalid (e.g., it was released). */ + + /* 211 */ + ccErrBadName, /*!< Bad credential cache name format. */ + ccErrBadCredentialsVersion, /*!< Credentials version is invalid. */ + ccErrBadAPIVersion, /*!< Unsupported API version. */ + ccErrContextLocked, /*!< Context is already locked. */ + ccErrContextUnlocked, /*!< Context is not locked by the caller. */ + + /* 216 */ + ccErrCCacheLocked, /*!< CCache is already locked. */ + ccErrCCacheUnlocked, /*!< CCache is not locked by the caller. */ + ccErrBadLockType, /*!< Bad lock type. */ + ccErrNeverDefault, /*!< CCache was never default. */ + ccErrCredentialsNotFound, /*!< Matching credentials not found in the ccache. */ + + /* 221 */ + ccErrCCacheNotFound, /*!< Matching ccache not found in the collection. */ + ccErrContextNotFound, /*!< Matching cache collection not found. */ + ccErrServerUnavailable, /*!< CCacheServer is unavailable. */ + ccErrServerInsecure, /*!< CCacheServer has detected that it is running as the wrong user. */ + ccErrServerCantBecomeUID, /*!< CCacheServer failed to start running as the user. */ + + /* 226 */ + ccErrTimeOffsetNotSet, /*!< KDC time offset not set for this ccache. */ + ccErrBadInternalMessage, /*!< The client and CCacheServer can't communicate (e.g., a version mismatch). */ + ccErrNotImplemented, /*!< API function not supported by this implementation. */ + ccErrClientNotFound /*!< CCacheServer has no record of the caller's process (e.g., the server crashed). */ +}; + +/*! + * Credentials versions + * + * These constants are used in several places in the API to discern Kerberos + * versions. Not all values are valid inputs and outputs for all functions; + * function specifications below detail the allowed values. + * + * Kerberos version constants will always be a bit-field, and can be + * tested as such; for example the following test will tell you if + * a ccacheVersion includes v5 credentials: + * + * if ((ccacheVersion & cc_credentials_v5) != 0) + */ +enum cc_credential_versions { + /* cc_credentials_v4 = 1, */ + cc_credentials_v5 = 2, + /* cc_credentials_v4_v5 = 3 */ +}; + +/*! + * Lock types + * + * These constants are used in the locking functions to describe the + * type of lock requested. Note that all CCAPI locks are advisory + * so only callers using the lock calls will be blocked by each other. + * This is because locking functions were introduced after the CCAPI + * came into common use and we did not want to break existing callers. + */ +enum cc_lock_types { + cc_lock_read = 0, + cc_lock_write = 1, + cc_lock_upgrade = 2, + cc_lock_downgrade = 3 +}; + +/*! + * Locking Modes + * + * These constants are used in the advisory locking functions to + * describe whether or not the lock function should block waiting for + * a lock or return an error immediately. For example, attempting to + * acquire a lock with a non-blocking call will result in an error if the + * lock cannot be acquired; otherwise, the call will block until the lock + * can be acquired. + */ +enum cc_lock_modes { + cc_lock_noblock = 0, + cc_lock_block = 1 +}; + +/*!@}*/ + +/*! + * \defgroup ccapi_types_reference Basic Types + * @{ + */ + +/*! Unsigned 32-bit integer type */ +typedef uint32_t cc_uint32; +/*! Signed 32-bit integer type */ +typedef int32_t cc_int32; +#if defined (WIN32) +typedef __int64 cc_int64; +typedef unsigned __int64 cc_uint64; +#else +/*! Unsigned 64-bit integer type */ +typedef int64_t cc_int64; +/*! Signed 64-bit integer type */ +typedef uint64_t cc_uint64; +#endif +/*! + * The cc_time_t type is used to represent a time in seconds. The time must + * be stored as the number of seconds since midnight GMT on January 1, 1970. + */ +typedef cc_uint32 cc_time_t; + +/*!@}*/ + +/*! + * \defgroup cc_context_reference cc_context_t Overview + * @{ + * + * The cc_context_t type gives the caller access to a ccache collection. + * Before being able to call any functions in the CCache API, the caller + * needs to acquire an instance of cc_context_t by calling cc_initialize(). + * + * For API function documentation see \ref cc_context_f. + */ +struct cc_context_f; +typedef struct cc_context_f cc_context_f; + +struct cc_context_d { + const cc_context_f *functions; +#if TARGET_OS_MAC + const cc_context_f *vector_functions; +#endif +}; +typedef struct cc_context_d cc_context_d; +typedef cc_context_d *cc_context_t; + +/*!@}*/ + +/*! + * \defgroup cc_ccache_reference cc_ccache_t Overview + * @{ + * + * The cc_ccache_t type represents a reference to a ccache. + * Callers can access a ccache and the credentials stored in it + * via a cc_ccache_t. A cc_ccache_t can be acquired via + * cc_context_open_ccache(), cc_context_open_default_ccache(), or + * cc_ccache_iterator_next(). + * + * For API function documentation see \ref cc_ccache_f. + */ +struct cc_ccache_f; +typedef struct cc_ccache_f cc_ccache_f; + +struct cc_ccache_d { + const cc_ccache_f *functions; +#if TARGET_OS_MAC + const cc_ccache_f *vector_functions; +#endif +}; +typedef struct cc_ccache_d cc_ccache_d; +typedef cc_ccache_d *cc_ccache_t; + +/*!@}*/ + +/*! + * \defgroup cc_ccache_iterator_reference cc_ccache_iterator_t Overview + * @{ + * + * The cc_ccache_iterator_t type represents an iterator that + * iterates over a set of ccaches and returns them in all in some + * order. A new instance of this type can be obtained by calling + * cc_context_new_ccache_iterator(). + * + * For API function documentation see \ref cc_ccache_iterator_f. + */ +struct cc_ccache_iterator_f; +typedef struct cc_ccache_iterator_f cc_ccache_iterator_f; + +struct cc_ccache_iterator_d { + const cc_ccache_iterator_f *functions; +#if TARGET_OS_MAC + const cc_ccache_iterator_f *vector_functions; +#endif +}; +typedef struct cc_ccache_iterator_d cc_ccache_iterator_d; +typedef cc_ccache_iterator_d *cc_ccache_iterator_t; +/*!@}*/ + +/*! + * \defgroup cc_credentials_reference cc_credentials_t Overview + * @{ + * + * The cc_credentials_t type is used to store a single set of credentials for + * Kerberos v5. In addition to its only function, release(), it contains a + * pointer to a cc_credentials_union structure. A cc_credentials_union + * structure contains an integer of the enumerator type + * cc_credentials_version, which is #cc_credentials_v5, and a pointer union, + * which contains a cc_credentials_v5_t pointer, depending on the value in + * version. + * + * Variables of the type cc_credentials_t are allocated by the CCAPI + * implementation, and should be released with their release() + * function. API functions which receive credentials structures + * from the caller always accept cc_credentials_union, which is + * allocated by the caller, and accordingly disposed by the caller. + * + * For API functions see \ref cc_credentials_f. + */ + +/*! + * The CCAPI data structure. This structure is similar to a krb5_data structure. + * In a v5 credentials structure, cc_data structures are used + * to store tagged variable-length binary data. Specifically, + * for cc_credentials_v5.ticket and + * cc_credentials_v5.second_ticket, the cc_data.type field must + * be zero. For the cc_credentials_v5.addresses, + * cc_credentials_v5.authdata, and cc_credentials_v5.keyblock, + * the cc_data.type field should be the address type, + * authorization data type, and encryption type, as defined by + * the Kerberos v5 protocol definition. + */ +struct cc_data { + /*! The type of the data as defined by the krb5_data structure. */ + cc_uint32 type; + /*! The length of \a data. */ + cc_uint32 length; + /*! The data buffer. */ + void* data; +}; +typedef struct cc_data cc_data; + +/*! + * If a cc_credentials_t variable is used to store Kerberos v5 c + * redentials, and then credentials.credentials_v5 points to a + * v5 credentials structure. This structure is similar to a + * krb5_creds structure. + */ +struct cc_credentials_v5_t { + /*! A properly quoted string representation of the client principal. */ + char* client; + /*! A properly quoted string representation of the service principal. */ + char* server; + /*! Session encryption key info. */ + cc_data keyblock; + /*! The time when the ticket was issued. */ + cc_time_t authtime; + /*! The time when the ticket becomes valid. */ + cc_time_t starttime; + /*! The time when the ticket expires. */ + cc_time_t endtime; + /*! The time when the ticket becomes no longer renewable (if renewable). */ + cc_time_t renew_till; + /*! 1 if the ticket is encrypted in another ticket's key, or 0 otherwise. */ + cc_uint32 is_skey; + /*! Ticket flags, as defined by the Kerberos 5 API. */ + cc_uint32 ticket_flags; + /*! The the list of network addresses of hosts that are allowed to authenticate + * using this ticket. */ + cc_data** addresses; + /*! Ticket data. */ + cc_data ticket; + /*! Second ticket data. */ + cc_data second_ticket; + /*! Authorization data. */ + cc_data** authdata; +}; +typedef struct cc_credentials_v5_t cc_credentials_v5_t; + +struct cc_credentials_union { + /*! The credentials version of this credentials object. */ + cc_uint32 version; + /*! The credentials. */ + union { + /*! If \a version is #cc_credentials_v5, a pointer to a cc_credentials_v5_t. */ + cc_credentials_v5_t* credentials_v5; + } credentials; +}; +typedef struct cc_credentials_union cc_credentials_union; + +struct cc_credentials_f; +typedef struct cc_credentials_f cc_credentials_f; + +struct cc_credentials_d { + const cc_credentials_union *data; + const cc_credentials_f *functions; +#if TARGET_OS_MAC + const cc_credentials_f *otherFunctions; +#endif +}; +typedef struct cc_credentials_d cc_credentials_d; +typedef cc_credentials_d *cc_credentials_t; +/*!@}*/ + +/*! + * \defgroup cc_credentials_iterator_reference cc_credentials_iterator_t + * @{ + * The cc_credentials_iterator_t type represents an iterator that + * iterates over a set of credentials. A new instance of this type + * can be obtained by calling cc_ccache_new_credentials_iterator(). + * + * For API function documentation see \ref cc_credentials_iterator_f. + */ +struct cc_credentials_iterator_f; +typedef struct cc_credentials_iterator_f cc_credentials_iterator_f; + +struct cc_credentials_iterator_d { + const cc_credentials_iterator_f *functions; +#if TARGET_OS_MAC + const cc_credentials_iterator_f *vector_functions; +#endif +}; +typedef struct cc_credentials_iterator_d cc_credentials_iterator_d; +typedef cc_credentials_iterator_d *cc_credentials_iterator_t; +/*!@}*/ + +/*! + * \defgroup cc_string_reference cc_string_t Overview + * @{ + * The cc_string_t represents a C string returned by the API. + * It has a pointer to the string data and a release() function. + * This type is used for both principal names and ccache names + * returned by the API. Principal names may contain UTF-8 encoded + * strings for internationalization purposes. + * + * For API function documentation see \ref cc_string_f. + */ +struct cc_string_f; +typedef struct cc_string_f cc_string_f; + +struct cc_string_d { + const char *data; + const cc_string_f *functions; +#if TARGET_OS_MAC + const cc_string_f *vector_functions; +#endif +}; +typedef struct cc_string_d cc_string_d; +typedef cc_string_d *cc_string_t; +/*!@}*/ + +/*! + * Function pointer table for cc_context_t. For more information see + * \ref cc_context_reference. + */ +struct cc_context_f { + /*! + * \param io_context the context object to free. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_release(): Release memory associated with a cc_context_t. + */ + cc_int32 (*release) (cc_context_t io_context); + + /*! + * \param in_context the context object for the cache collection to examine. + * \param out_time on exit, the time of the most recent change for the entire ccache collection. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_get_change_time(): Get the last time the cache collection changed. + * + * This function returns the time of the most recent change for the entire ccache collection. + * By maintaining a local copy the caller can deduce whether or not the ccache collection has + * been modified since the previous call to cc_context_get_change_time(). + * + * The time returned by cc_context_get_changed_time() increases whenever: + * + * \li a ccache is created + * \li a ccache is destroyed + * \li a credential is stored + * \li a credential is removed + * \li a ccache principal is changed + * \li the default ccache is changed + * + * \note In order to be able to compare two values returned by cc_context_get_change_time(), + * the caller must use the same context to acquire them. Callers should maintain a single + * context in memory for cc_context_get_change_time() calls rather than creating a new + * context for every call. + * + * \sa wait_for_change + */ + cc_int32 (*get_change_time) (cc_context_t in_context, + cc_time_t *out_time); + + /*! + * \param in_context the context object for the cache collection. + * \param out_name on exit, the name of the default ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_get_default_ccache_name(): Get the name of the default ccache. + * + * This function returns the name of the default ccache. When the default ccache + * exists, its name is returned. If there are no ccaches in the collection, and + * thus there is no default ccache, the name that the default ccache should have + * is returned. The ccache with that name will be used as the default ccache by + * all processes which initialized Kerberos libraries before the ccache was created. + * + * If there is no default ccache, and the client is creating a new ccache, it + * should be created with the default name. If there already is a default ccache, + * and the client wants to create a new ccache (as opposed to reusing an existing + * ccache), it should be created with any unique name; #create_new_ccache() + * can be used to accomplish that more easily. + * + * If the first ccache is created with a name other than the default name, then + * the processes already running will not notice the credentials stored in the + * new ccache, which is normally undesirable. + */ + cc_int32 (*get_default_ccache_name) (cc_context_t in_context, + cc_string_t *out_name); + + /*! + * \param in_context the context object for the cache collection. + * \param in_name the name of the ccache to open. + * \param out_ccache on exit, a ccache object for the ccache + * \return On success, #ccNoError. If no ccache named \a in_name exists, + * #ccErrCCacheNotFound. On failure, an error code representing the failure. + * \brief \b cc_context_open_ccache(): Open a ccache. + * + * Opens an already existing ccache identified by its name. It returns a reference + * to the ccache in \a out_ccache. + * + * The list of all ccache names, principals, and credentials versions may be retrieved + * by calling cc_context_new_cache_iterator(), cc_ccache_get_name(), + * cc_ccache_get_principal(), and cc_ccache_get_cred_version(). + */ + cc_int32 (*open_ccache) (cc_context_t in_context, + const char *in_name, + cc_ccache_t *out_ccache); + + /*! + * \param in_context the context object for the cache collection. + * \param out_ccache on exit, a ccache object for the default ccache + * \return On success, #ccNoError. If no default ccache exists, + * #ccErrCCacheNotFound. On failure, an error code representing the failure. + * \brief \b cc_context_open_default_ccache(): Open the default ccache. + * + * Opens the default ccache. It returns a reference to the ccache in *ccache. + * + * This function performs the same function as calling + * cc_context_get_default_ccache_name followed by cc_context_open_ccache, + * but it performs it atomically. + */ + cc_int32 (*open_default_ccache) (cc_context_t in_context, + cc_ccache_t *out_ccache); + + /*! + * \param in_context the context object for the cache collection. + * \param in_name the name of the new ccache to create + * \param in_cred_vers the version of the credentials the new ccache will hold + * \param in_principal the client principal of the credentials the new ccache will hold + * \param out_ccache on exit, a ccache object for the newly created ccache + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_create_ccache(): Create a new ccache. + * + * Create a new credentials cache. The ccache is uniquely identified by + * its name. The principal given is also associated with the ccache and + * the credentials version specified. A NULL name is not allowed (and + * ccErrBadName is returned if one is passed in). Only cc_credentials_v5 + * can be an input value for cred_vers. + * + * If you want to create a new ccache (with a unique name), you should use + * cc_context_create_new_ccache() instead. If you want to create or reinitialize + * the default cache, you should use cc_context_create_default_ccache(). + * + * If name is non-NULL and there is already a ccache named name: + * + * \li the credentials in the ccache whose version is cred_vers are removed + * \li the principal (of the existing ccache) associated with cred_vers is set to principal + * \li a handle for the existing ccache is returned and all existing handles for the ccache remain valid + * + * If no ccache named name already exists: + * + * \li a new empty ccache is created + * \li the principal of the new ccache associated with cred_vers is set to principal + * \li a handle for the new ccache is returned + * + * For a new ccache, the name should be any unique string. The name is not + * intended to be presented to users. + * + * If the created ccache is the first ccache in the collection, it is made + * the default ccache. Note that normally it is undesirable to create the first + * ccache with a name different from the default ccache name (as returned by + * cc_context_get_default_ccache_name()); see the description of + * cc_context_get_default_ccache_name() for details. + * + * The principal should be a C string containing an unparsed Kerberos + * principal in the format of the appropriate Kerberos version, + * i.e. \verbatim foo/bar/@BAZ \endverbatim for Kerberos v5. + */ + cc_int32 (*create_ccache) (cc_context_t in_context, + const char *in_name, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + + /*! + * \param in_context the context object for the cache collection. + * \param in_cred_vers the version of the credentials the new default ccache will hold + * \param in_principal the client principal of the credentials the new default ccache will hold + * \param out_ccache on exit, a ccache object for the newly created default ccache + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_create_default_ccache(): Create a new default ccache. + * + * Create the default credentials cache. The behavior of this function is + * similar to that of cc_create_ccache(). If there is a default ccache + * (which is always the case except when there are no ccaches at all in + * the collection), it is initialized with the specified credentials version + * and principal, as per cc_create_ccache(); otherwise, a new ccache is + * created, and its name is the name returned by + * cc_context_get_default_ccache_name(). + */ + cc_int32 (*create_default_ccache) (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + + /*! + * \param in_context the context object for the cache collection. + * \param in_cred_vers the version of the credentials the new ccache will hold + * \param in_principal the client principal of the credentials the new ccache will hold + * \param out_ccache on exit, a ccache object for the newly created ccache + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_create_new_ccache(): Create a new uniquely named ccache. + * + * Create a new unique credentials cache. The behavior of this function + * is similar to that of cc_create_ccache(). If there are no ccaches, and + * therefore no default ccache, the new ccache is created with the default + * ccache name as would be returned by get_default_ccache_name(). If there + * are some ccaches, and therefore there is a default ccache, the new ccache + * is created with a new unique name. Clearly, this function never reinitializes + * a ccache, since it always uses a unique name. + */ + cc_int32 (*create_new_ccache) (cc_context_t in_context, + cc_uint32 in_cred_vers, + const char *in_principal, + cc_ccache_t *out_ccache); + + /*! + * \param in_context the context object for the cache collection. + * \param out_iterator on exit, a ccache iterator object for the ccache collection. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_new_ccache_iterator(): Get an iterator for the cache collection. + * + * Used to allocate memory and initialize iterator. Successive calls to iterator's + * next() function will return ccaches in the collection. + * + * If changes are made to the collection while an iterator is being used + * on it, the iterator must return at least the intersection, and at most + * the union, of the set of ccaches that were present when the iteration + * began and the set of ccaches that are present when it ends. + */ + cc_int32 (*new_ccache_iterator) (cc_context_t in_context, + cc_ccache_iterator_t *out_iterator); + + /*! + * \param in_context the context object for the cache collection. + * \param in_lock_type the type of lock to obtain. + * \param in_block whether or not the function should block if the lock cannot be obtained immediately. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_lock(): Lock the cache collection. + * + * Attempts to acquire an advisory lock for the ccache collection. Allowed values + * for lock_type are: + * + * \li cc_lock_read: a read lock. + * \li cc_lock_write: a write lock + * \li cc_lock_upgrade: upgrade an already-obtained read lock to a write lock + * \li cc_lock_downgrade: downgrade an already-obtained write lock to a read lock + * + * If block is cc_lock_block, lock() will not return until the lock is acquired. + * If block is cc_lock_noblock, lock() will return immediately, either acquiring + * the lock and returning ccNoError, or failing to acquire the lock and returning + * an error explaining why. + * + * Locks apply only to the list of ccaches, not the contents of those ccaches. To + * prevent callers participating in the advisory locking from changing the credentials + * in a cache you must also lock that ccache with cc_ccache_lock(). This is so + * that you can get the list of ccaches without preventing applications from + * simultaneously obtaining service tickets. + * + * To avoid having to deal with differences between thread semantics on different + * platforms, locks are granted per context, rather than per thread or per process. + * That means that different threads of execution have to acquire separate contexts + * in order to be able to synchronize with each other. + * + * The lock should be unlocked by using cc_context_unlock(). + * + * \note All locks are advisory. For example, callers which do not call + * cc_context_lock() and cc_context_unlock() will not be prevented from writing + * to the cache collection when you have a read lock. This is because the CCAPI + * locking was added after the first release and thus adding mandatory locks would + * have changed the user experience and performance of existing applications. + */ + cc_int32 (*lock) (cc_context_t in_context, + cc_uint32 in_lock_type, + cc_uint32 in_block); + + /*! + * \param in_context the context object for the cache collection. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_unlock(): Unlock the cache collection. + */ + cc_int32 (*unlock) (cc_context_t in_cc_context); + + /*! + * \param in_context a context object. + * \param in_compare_to_context a context object to compare with \a in_context. + * \param out_equal on exit, whether or not the two contexts refer to the same cache collection. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_compare(): Compare two context objects. + */ + cc_int32 (*compare) (cc_context_t in_cc_context, + cc_context_t in_compare_to_context, + cc_uint32 *out_equal); + + /*! + * \param in_context a context object. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_context_wait_for_change(): Wait for the next change in the cache collection. + * + * This function blocks until the next change is made to the cache collection + * ccache collection. By repeatedly calling cc_context_wait_for_change() from + * a worker thread the caller can effectively receive callbacks whenever the + * cache collection changes. This is considerably more efficient than polling + * with cc_context_get_change_time(). + * + * cc_context_wait_for_change() will return whenever: + * + * \li a ccache is created + * \li a ccache is destroyed + * \li a credential is stored + * \li a credential is removed + * \li a ccache principal is changed + * \li the default ccache is changed + * + * \note In order to make sure that the caller doesn't miss any changes, + * cc_context_wait_for_change() always returns immediately after the first time it + * is called on a new context object. Callers must use the same context object + * for successive calls to cc_context_wait_for_change() rather than creating a new + * context for every call. + * + * \sa get_change_time + */ + cc_int32 (*wait_for_change) (cc_context_t in_cc_context); +}; + +/*! + * Function pointer table for cc_ccache_t. For more information see + * \ref cc_ccache_reference. + */ +struct cc_ccache_f { + /*! + * \param io_ccache the ccache object to release. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_release(): Release memory associated with a cc_ccache_t object. + * \note Does not modify the ccache. If you wish to remove the ccache see cc_ccache_destroy(). + */ + cc_int32 (*release) (cc_ccache_t io_ccache); + + /*! + * \param io_ccache the ccache object to destroy and release. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_destroy(): Destroy a ccache. + * + * Destroy the ccache referred to by \a io_ccache and releases memory associated with + * the \a io_ccache object. After this call \a io_ccache becomes invalid. If + * \a io_ccache was the default ccache, the next ccache in the cache collection (if any) + * becomes the new default. + */ + cc_int32 (*destroy) (cc_ccache_t io_ccache); + + /*! + * \param io_ccache a ccache object to make the new default ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_set_default(): Make a ccache the default ccache. + */ + cc_int32 (*set_default) (cc_ccache_t io_ccache); + + /*! + * \param in_ccache a ccache object. + * \param out_credentials_version on exit, the credentials version of \a in_ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_get_credentials_version(): Get the credentials version of a ccache. + * + * cc_ccache_get_credentials_version() returns one value of the enumerated + * type cc_credentials_vers. The return value is #cc_credentials_v5 (if + * ccache's v5 principal has been set). A ccache's principal is set with + * one of cc_context_create_ccache(), cc_context_create_new_ccache(), + * cc_context_create_default_ccache(), or cc_ccache_set_principal(). + */ + cc_int32 (*get_credentials_version) (cc_ccache_t in_ccache, + cc_uint32 *out_credentials_version); + + /*! + * \param in_ccache a ccache object. + * \param out_name on exit, a cc_string_t representing the name of \a in_ccache. + * \a out_name must be released with cc_string_release(). + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_get_name(): Get the name of a ccache. + */ + cc_int32 (*get_name) (cc_ccache_t in_ccache, + cc_string_t *out_name); + + /*! + * \param in_ccache a ccache object. + * \param in_credentials_version the credentials version to get the principal for. + * \param out_principal on exit, a cc_string_t representing the principal of \a in_ccache. + * \a out_principal must be released with cc_string_release(). + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_get_principal(): Get the principal of a ccache. + * + * Return the principal for the ccache that was set via cc_context_create_ccache(), + * cc_context_create_default_ccache(), cc_context_create_new_ccache(), or + * cc_ccache_set_principal(). + */ + cc_int32 (*get_principal) (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_string_t *out_principal); + + + /*! + * \param in_ccache a ccache object. + * \param in_credentials_version the credentials version to set the principal for. + * \param in_principal a C string representing the new principal of \a in_ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_set_principal(): Set the principal of a ccache. + * + * Set the a principal for ccache. + */ + cc_int32 (*set_principal) (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + const char *in_principal); + + /*! + * \param io_ccache a ccache object. + * \param in_credentials_union the credentials to store in \a io_ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_store_credentials(): Store credentials in a ccache. + * + * Store a copy of credentials in the ccache. + * + * See the description of the credentials types for the meaning of + * cc_credentials_union fields. + * + * Before credentials of a specific credential type can be stored in a + * ccache, the corresponding principal version has to be set. That is, + * before you can store Kerberos v5 credentials in a ccache, the Kerberos + * v5 principal has to be set either by cc_context_create_ccache(), + * cc_context_create_default_ccache(), cc_context_create_new_ccache(), or + * cc_ccache_set_principal(); otherwise, ccErrBadCredentialsVersion is + * returned. + */ + cc_int32 (*store_credentials) (cc_ccache_t io_ccache, + const cc_credentials_union *in_credentials_union); + + /*! + * \param io_ccache a ccache object. + * \param in_credentials the credentials to remove from \a io_ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_remove_credentials(): Remove credentials from a ccache. + * + * Removes credentials from a ccache. Note that credentials must be previously + * acquired from the CCache API; only exactly matching credentials will be + * removed. (This places the burden of determining exactly which credentials + * to remove on the caller, but ensures there is no ambigity about which + * credentials will be removed.) cc_credentials_t objects can be obtained by + * iterating over the ccache's credentials with cc_ccache_new_credentials_iterator(). + * + * If found, the credentials are removed from the ccache. The credentials + * parameter is not modified and should be freed by the caller. It is + * legitimate to call this function while an iterator is traversing the + * ccache, and the deletion of a credential already returned by + * cc_credentials_iterator_next() will not disturb sequence of credentials + * returned by cc_credentials_iterator_next(). + */ + cc_int32 (*remove_credentials) (cc_ccache_t io_ccache, + cc_credentials_t in_credentials); + + /*! + * \param in_ccache a ccache object. + * \param out_credentials_iterator a credentials iterator for \a io_ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_new_credentials_iterator(): Iterate over credentials in a ccache. + * + * Allocates memory for iterator and initializes it. Successive calls to + * cc_credentials_iterator_next() will return credentials from the ccache. + * + * If changes are made to the ccache while an iterator is being used on it, + * the iterator must return at least the intersection, and at most the union, + * of the set of credentials that were in the ccache when the iteration began + * and the set of credentials that are in the ccache when it ends. + */ + cc_int32 (*new_credentials_iterator) (cc_ccache_t in_ccache, + cc_credentials_iterator_t *out_credentials_iterator); + + /*! + * \param io_source_ccache a ccache object to move. + * \param io_destination_ccache a ccache object replace with the contents of \a io_source_ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_move(): Move the contents of one ccache into another, destroying the source. + * + * cc_ccache_move() atomically copies the credentials, credential versions and principals + * from one ccache to another. On successful completion \a io_source_ccache will be + * released and the ccache it points to will be destroyed. Any credentials previously + * in \a io_destination_ccache will be replaced with credentials from \a io_source_ccache. + * The only part of \a io_destination_ccache which remains constant is the name. Any other + * callers referring to \a io_destination_ccache will suddenly see new data in it. + * + * Typically cc_ccache_move() is used when the caller wishes to safely overwrite the + * contents of a ccache with new data which requires several steps to generate. + * cc_ccache_move() allows the caller to create a temporary ccache + * (which can be destroyed if any intermediate step fails) and the atomically copy + * the temporary cache into the destination. + */ + cc_int32 (*move) (cc_ccache_t io_source_ccache, + cc_ccache_t io_destination_ccache); + + /*! + * \param io_ccache the ccache object for the ccache you wish to lock. + * \param in_lock_type the type of lock to obtain. + * \param in_block whether or not the function should block if the lock cannot be obtained immediately. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_lock(): Lock a ccache. + * + * Attempts to acquire an advisory lock for a ccache. Allowed values for lock_type are: + * + * \li cc_lock_read: a read lock. + * \li cc_lock_write: a write lock + * \li cc_lock_upgrade: upgrade an already-obtained read lock to a write lock + * \li cc_lock_downgrade: downgrade an already-obtained write lock to a read lock + * + * If block is cc_lock_block, lock() will not return until the lock is acquired. + * If block is cc_lock_noblock, lock() will return immediately, either acquiring + * the lock and returning ccNoError, or failing to acquire the lock and returning + * an error explaining why. + * + * To avoid having to deal with differences between thread semantics on different + * platforms, locks are granted per ccache, rather than per thread or per process. + * That means that different threads of execution have to acquire separate contexts + * in order to be able to synchronize with each other. + * + * The lock should be unlocked by using cc_ccache_unlock(). + * + * \note All locks are advisory. For example, callers which do not call + * cc_ccache_lock() and cc_ccache_unlock() will not be prevented from writing + * to the ccache when you have a read lock. This is because the CCAPI + * locking was added after the first release and thus adding mandatory locks would + * have changed the user experience and performance of existing applications. + */ + cc_int32 (*lock) (cc_ccache_t io_ccache, + cc_uint32 in_lock_type, + cc_uint32 in_block); + + /*! + * \param io_ccache a ccache object. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_unlock(): Unlock a ccache. + */ + cc_int32 (*unlock) (cc_ccache_t io_ccache); + + /*! + * \param in_ccache a cache object. + * \param out_last_default_time on exit, the last time the ccache was default. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_get_change_time(): Get the last time a ccache was the default ccache. + * + * This function returns the last time when the ccache was made the default ccache. + * This allows clients to sort the ccaches by how recently they were default, which + * is useful for user listing of ccaches. If the ccache was never default, + * ccErrNeverDefault is returned. + */ + cc_int32 (*get_last_default_time) (cc_ccache_t in_ccache, + cc_time_t *out_last_default_time); + + /*! + * \param in_ccache a cache object. + * \param out_change_time on exit, the last time the ccache changed. + * \return On success, #ccNoError. If the ccache was never the default ccache, + * #ccErrNeverDefault. Otherwise, an error code representing the failure. + * \brief \b cc_ccache_get_change_time(): Get the last time a ccache changed. + * + * This function returns the time of the most recent change made to a ccache. + * By maintaining a local copy the caller can deduce whether or not the ccache has + * been modified since the previous call to cc_ccache_get_change_time(). + * + * The time returned by cc_ccache_get_change_time() increases whenever: + * + * \li a credential is stored + * \li a credential is removed + * \li a ccache principal is changed + * \li the ccache becomes the default ccache + * \li the ccache is no longer the default ccache + * + * \note In order to be able to compare two values returned by cc_ccache_get_change_time(), + * the caller must use the same ccache object to acquire them. Callers should maintain a + * single ccache object in memory for cc_ccache_get_change_time() calls rather than + * creating a new ccache object for every call. + * + * \sa wait_for_change + */ + cc_int32 (*get_change_time) (cc_ccache_t in_ccache, + cc_time_t *out_change_time); + + /*! + * \param in_ccache a ccache object. + * \param in_compare_to_ccache a ccache object to compare with \a in_ccache. + * \param out_equal on exit, whether or not the two ccaches refer to the same ccache. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_compare(): Compare two ccache objects. + */ + cc_int32 (*compare) (cc_ccache_t in_ccache, + cc_ccache_t in_compare_to_ccache, + cc_uint32 *out_equal); + + /*! + * \param in_ccache a ccache object. + * \param in_credentials_version the credentials version to get the time offset for. + * \param out_time_offset on exit, the KDC time offset for \a in_ccache for credentials version + * \a in_credentials_version. + * \return On success, #ccNoError if a time offset was obtained or #ccErrTimeOffsetNotSet + * if a time offset has not been set. On failure, an error code representing the failure. + * \brief \b cc_ccache_get_kdc_time_offset(): Get the KDC time offset for credentials in a ccache. + * \sa set_kdc_time_offset, clear_kdc_time_offset + * + * Sometimes the KDC and client's clocks get out of sync. cc_ccache_get_kdc_time_offset() + * returns the difference between the KDC and client's clocks at the time credentials were + * acquired. This offset allows callers to figure out how much time is left on a given + * credential even though the end_time is based on the KDC's clock not the client's clock. + */ + cc_int32 (*get_kdc_time_offset) (cc_ccache_t in_ccache, + cc_uint32 in_credentials_version, + cc_time_t *out_time_offset); + + /*! + * \param in_ccache a ccache object. + * \param in_credentials_version the credentials version to get the time offset for. + * \param in_time_offset the new KDC time offset for \a in_ccache for credentials version + * \a in_credentials_version. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_set_kdc_time_offset(): Set the KDC time offset for credentials in a ccache. + * \sa get_kdc_time_offset, clear_kdc_time_offset + * + * Sometimes the KDC and client's clocks get out of sync. cc_ccache_set_kdc_time_offset() + * sets the difference between the KDC and client's clocks at the time credentials were + * acquired. This offset allows callers to figure out how much time is left on a given + * credential even though the end_time is based on the KDC's clock not the client's clock. + */ + cc_int32 (*set_kdc_time_offset) (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version, + cc_time_t in_time_offset); + + /*! + * \param in_ccache a ccache object. + * \param in_credentials_version the credentials version to get the time offset for. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_clear_kdc_time_offset(): Clear the KDC time offset for credentials in a ccache. + * \sa get_kdc_time_offset, set_kdc_time_offset + * + * Sometimes the KDC and client's clocks get out of sync. cc_ccache_clear_kdc_time_offset() + * clears the difference between the KDC and client's clocks at the time credentials were + * acquired. This offset allows callers to figure out how much time is left on a given + * credential even though the end_time is based on the KDC's clock not the client's clock. + */ + cc_int32 (*clear_kdc_time_offset) (cc_ccache_t io_ccache, + cc_uint32 in_credentials_version); + + /*! + * \param in_ccache a ccache object. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_wait_for_change(): Wait for the next change to a ccache. + * + * This function blocks until the next change is made to the ccache referenced by + * \a in_ccache. By repeatedly calling cc_ccache_wait_for_change() from + * a worker thread the caller can effectively receive callbacks whenever the + * ccache changes. This is considerably more efficient than polling + * with cc_ccache_get_change_time(). + * + * cc_ccache_wait_for_change() will return whenever: + * + * \li a credential is stored + * \li a credential is removed + * \li the ccache principal is changed + * \li the ccache becomes the default ccache + * \li the ccache is no longer the default ccache + * + * \note In order to make sure that the caller doesn't miss any changes, + * cc_ccache_wait_for_change() always returns immediately after the first time it + * is called on a new ccache object. Callers must use the same ccache object + * for successive calls to cc_ccache_wait_for_change() rather than creating a new + * ccache object for every call. + * + * \sa get_change_time + */ + cc_int32 (*wait_for_change) (cc_ccache_t in_ccache); +}; + +/*! + * Function pointer table for cc_string_t. For more information see + * \ref cc_string_reference. + */ +struct cc_string_f { + /*! + * \param io_string the string object to release. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_string_release(): Release memory associated with a cc_string_t object. + */ + cc_int32 (*release) (cc_string_t io_string); +}; + +/*! + * Function pointer table for cc_credentials_t. For more information see + * \ref cc_credentials_reference. + */ +struct cc_credentials_f { + /*! + * \param io_credentials the credentials object to release. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_credentials_release(): Release memory associated with a cc_credentials_t object. + */ + cc_int32 (*release) (cc_credentials_t io_credentials); + + /*! + * \param in_credentials a credentials object. + * \param in_compare_to_credentials a credentials object to compare with \a in_credentials. + * \param out_equal on exit, whether or not the two credentials objects refer to the + * same credentials in the cache collection. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_credentials_compare(): Compare two credentials objects. + */ + cc_int32 (*compare) (cc_credentials_t in_credentials, + cc_credentials_t in_compare_to_credentials, + cc_uint32 *out_equal); +}; + +/*! + * Function pointer table for cc_ccache_iterator_t. For more information see + * \ref cc_ccache_iterator_reference. + */ +struct cc_ccache_iterator_f { + /*! + * \param io_ccache_iterator the ccache iterator object to release. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_iterator_release(): Release memory associated with a cc_ccache_iterator_t object. + */ + cc_int32 (*release) (cc_ccache_iterator_t io_ccache_iterator); + + /*! + * \param in_ccache_iterator a ccache iterator object. + * \param out_ccache on exit, the next ccache in the cache collection. + * \return On success, #ccNoError if the next ccache in the cache collection was + * obtained or #ccIteratorEnd if there are no more ccaches. + * On failure, an error code representing the failure. + * \brief \b cc_ccache_iterator_next(): Get the next ccache in the cache collection. + */ + cc_int32 (*next) (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_t *out_ccache); + + /*! + * \param in_ccache_iterator a ccache iterator object. + * \param out_ccache_iterator on exit, a copy of \a in_ccache_iterator. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_ccache_iterator_clone(): Make a copy of a ccache iterator. + */ + cc_int32 (*clone) (cc_ccache_iterator_t in_ccache_iterator, + cc_ccache_iterator_t *out_ccache_iterator); +}; + +/*! + * Function pointer table for cc_credentials_iterator_t. For more information see + * \ref cc_credentials_iterator_reference. + */ +struct cc_credentials_iterator_f { + /*! + * \param io_credentials_iterator the credentials iterator object to release. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_credentials_iterator_release(): Release memory associated with a cc_credentials_iterator_t object. + */ + cc_int32 (*release) (cc_credentials_iterator_t io_credentials_iterator); + + /*! + * \param in_credentials_iterator a credentials iterator object. + * \param out_credentials on exit, the next credentials in the ccache. + * \return On success, #ccNoError if the next credential in the ccache was obtained + * or #ccIteratorEnd if there are no more credentials. + * On failure, an error code representing the failure. + * \brief \b cc_credentials_iterator_next(): Get the next credentials in the ccache. + */ + cc_int32 (*next) (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_t *out_credentials); + + /*! + * \ingroup cc_credentials_iterator_reference + * \param in_credentials_iterator a credentials iterator object. + * \param out_credentials_iterator on exit, a copy of \a in_credentials_iterator. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * \brief \b cc_credentials_iterator_clone(): Make a copy of a credentials iterator. + */ + cc_int32 (*clone) (cc_credentials_iterator_t in_credentials_iterator, + cc_credentials_iterator_t *out_credentials_iterator); +}; + +/*! + * \ingroup cc_context_reference + * \param out_context on exit, a new context object. Must be free with cc_context_release(). + * \param in_version the requested API version. This should be the maximum version the + * application supports. + * \param out_supported_version if non-NULL, on exit contains the maximum API version + * supported by the implementation. + * \param out_vendor if non-NULL, on exit contains a pointer to a read-only C string which + * contains a string describing the vendor which implemented the credentials cache API. + * \return On success, #ccNoError. On failure, an error code representing the failure. + * May return CCAPI v2 error CC_BAD_API_VERSION if #ccapi_version_2 is passed in. + * \brief Initialize a new cc_context. + */ +CCACHE_API cc_int32 cc_initialize (cc_context_t *out_context, + cc_int32 in_version, + cc_int32 *out_supported_version, + char const **out_vendor); + + +/*! \defgroup helper_macros CCAPI Function Helper Macros + * @{ */ + +/*! Helper macro for cc_context_f release() */ +#define cc_context_release(context) \ + ((context) -> functions -> release (context)) +/*! Helper macro for cc_context_f get_change_time() */ +#define cc_context_get_change_time(context, change_time) \ + ((context) -> functions -> get_change_time (context, change_time)) +/*! Helper macro for cc_context_f get_default_ccache_name() */ +#define cc_context_get_default_ccache_name(context, name) \ + ((context) -> functions -> get_default_ccache_name (context, name)) +/*! Helper macro for cc_context_f open_ccache() */ +#define cc_context_open_ccache(context, name, ccache) \ + ((context) -> functions -> open_ccache (context, name, ccache)) +/*! Helper macro for cc_context_f open_default_ccache() */ +#define cc_context_open_default_ccache(context, ccache) \ + ((context) -> functions -> open_default_ccache (context, ccache)) +/*! Helper macro for cc_context_f create_ccache() */ +#define cc_context_create_ccache(context, name, version, principal, ccache) \ + ((context) -> functions -> create_ccache (context, name, version, principal, ccache)) +/*! Helper macro for cc_context_f create_default_ccache() */ +#define cc_context_create_default_ccache(context, version, principal, ccache) \ + ((context) -> functions -> create_default_ccache (context, version, principal, ccache)) +/*! Helper macro for cc_context_f create_new_ccache() */ +#define cc_context_create_new_ccache(context, version, principal, ccache) \ + ((context) -> functions -> create_new_ccache (context, version, principal, ccache)) +/*! Helper macro for cc_context_f new_ccache_iterator() */ +#define cc_context_new_ccache_iterator(context, iterator) \ + ((context) -> functions -> new_ccache_iterator (context, iterator)) +/*! Helper macro for cc_context_f lock() */ +#define cc_context_lock(context, type, block) \ + ((context) -> functions -> lock (context, type, block)) +/*! Helper macro for cc_context_f unlock() */ +#define cc_context_unlock(context) \ + ((context) -> functions -> unlock (context)) +/*! Helper macro for cc_context_f compare() */ +#define cc_context_compare(context, compare_to, equal) \ + ((context) -> functions -> compare (context, compare_to, equal)) +/*! Helper macro for cc_context_f wait_for_change() */ +#define cc_context_wait_for_change(context) \ + ((context) -> functions -> wait_for_change (context)) + +/*! Helper macro for cc_ccache_f release() */ +#define cc_ccache_release(ccache) \ + ((ccache) -> functions -> release (ccache)) +/*! Helper macro for cc_ccache_f destroy() */ +#define cc_ccache_destroy(ccache) \ + ((ccache) -> functions -> destroy (ccache)) +/*! Helper macro for cc_ccache_f set_default() */ +#define cc_ccache_set_default(ccache) \ + ((ccache) -> functions -> set_default (ccache)) +/*! Helper macro for cc_ccache_f get_credentials_version() */ +#define cc_ccache_get_credentials_version(ccache, version) \ + ((ccache) -> functions -> get_credentials_version (ccache, version)) +/*! Helper macro for cc_ccache_f get_name() */ +#define cc_ccache_get_name(ccache, name) \ + ((ccache) -> functions -> get_name (ccache, name)) +/*! Helper macro for cc_ccache_f get_principal() */ +#define cc_ccache_get_principal(ccache, version, principal) \ + ((ccache) -> functions -> get_principal (ccache, version, principal)) +/*! Helper macro for cc_ccache_f set_principal() */ +#define cc_ccache_set_principal(ccache, version, principal) \ + ((ccache) -> functions -> set_principal (ccache, version, principal)) +/*! Helper macro for cc_ccache_f store_credentials() */ +#define cc_ccache_store_credentials(ccache, credentials) \ + ((ccache) -> functions -> store_credentials (ccache, credentials)) +/*! Helper macro for cc_ccache_f remove_credentials() */ +#define cc_ccache_remove_credentials(ccache, credentials) \ + ((ccache) -> functions -> remove_credentials (ccache, credentials)) +/*! Helper macro for cc_ccache_f new_credentials_iterator() */ +#define cc_ccache_new_credentials_iterator(ccache, iterator) \ + ((ccache) -> functions -> new_credentials_iterator (ccache, iterator)) +/*! Helper macro for cc_ccache_f lock() */ +#define cc_ccache_lock(ccache, type, block) \ + ((ccache) -> functions -> lock (ccache, type, block)) +/*! Helper macro for cc_ccache_f unlock() */ +#define cc_ccache_unlock(ccache) \ + ((ccache) -> functions -> unlock (ccache)) +/*! Helper macro for cc_ccache_f get_last_default_time() */ +#define cc_ccache_get_last_default_time(ccache, last_default_time) \ + ((ccache) -> functions -> get_last_default_time (ccache, last_default_time)) +/*! Helper macro for cc_ccache_f get_change_time() */ +#define cc_ccache_get_change_time(ccache, change_time) \ + ((ccache) -> functions -> get_change_time (ccache, change_time)) +/*! Helper macro for cc_ccache_f move() */ +#define cc_ccache_move(source, destination) \ + ((source) -> functions -> move (source, destination)) +/*! Helper macro for cc_ccache_f compare() */ +#define cc_ccache_compare(ccache, compare_to, equal) \ + ((ccache) -> functions -> compare (ccache, compare_to, equal)) +/*! Helper macro for cc_ccache_f get_kdc_time_offset() */ +#define cc_ccache_get_kdc_time_offset(ccache, version, time_offset) \ + ((ccache) -> functions -> get_kdc_time_offset (ccache, version, time_offset)) +/*! Helper macro for cc_ccache_f set_kdc_time_offset() */ +#define cc_ccache_set_kdc_time_offset(ccache, version, time_offset) \ + ((ccache) -> functions -> set_kdc_time_offset (ccache, version, time_offset)) +/*! Helper macro for cc_ccache_f clear_kdc_time_offset() */ +#define cc_ccache_clear_kdc_time_offset(ccache, version) \ + ((ccache) -> functions -> clear_kdc_time_offset (ccache, version)) +/*! Helper macro for cc_ccache_f wait_for_change() */ +#define cc_ccache_wait_for_change(ccache) \ + ((ccache) -> functions -> wait_for_change (ccache)) + +/*! Helper macro for cc_string_f release() */ +#define cc_string_release(string) \ + ((string) -> functions -> release (string)) + +/*! Helper macro for cc_credentials_f release() */ +#define cc_credentials_release(credentials) \ + ((credentials) -> functions -> release (credentials)) +/*! Helper macro for cc_credentials_f compare() */ +#define cc_credentials_compare(credentials, compare_to, equal) \ + ((credentials) -> functions -> compare (credentials, compare_to, equal)) + +/*! Helper macro for cc_ccache_iterator_f release() */ +#define cc_ccache_iterator_release(iterator) \ + ((iterator) -> functions -> release (iterator)) +/*! Helper macro for cc_ccache_iterator_f next() */ +#define cc_ccache_iterator_next(iterator, ccache) \ + ((iterator) -> functions -> next (iterator, ccache)) +/*! Helper macro for cc_ccache_iterator_f clone() */ +#define cc_ccache_iterator_clone(iterator, new_iterator) \ + ((iterator) -> functions -> clone (iterator, new_iterator)) + +/*! Helper macro for cc_credentials_iterator_f release() */ +#define cc_credentials_iterator_release(iterator) \ + ((iterator) -> functions -> release (iterator)) +/*! Helper macro for cc_credentials_iterator_f next() */ +#define cc_credentials_iterator_next(iterator, credentials) \ + ((iterator) -> functions -> next (iterator, credentials)) +/*! Helper macro for cc_credentials_iterator_f clone() */ +#define cc_credentials_iterator_clone(iterator, new_iterator) \ + ((iterator) -> functions -> clone (iterator, new_iterator)) +/*!@}*/ + +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)) +#pragma pack(pop) +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CREDENTIALSCACHE__ */ diff --git a/krb5-1.21.3/src/include/CredentialsCache2.h b/krb5-1.21.3/src/include/CredentialsCache2.h new file mode 100644 index 00000000..8a5871b0 --- /dev/null +++ b/krb5-1.21.3/src/include/CredentialsCache2.h @@ -0,0 +1,302 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/CredentialsCache2.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This is backwards compatibility for CCache API v2 clients to be able to run + * against the CCache API v3 library + */ + +#ifndef CCAPI_V2_H +#define CCAPI_V2_H + +#include + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) +#include +#include +#ifdef DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER +#define CCAPI_DEPRECATED DEPRECATED_IN_MAC_OS_X_VERSION_10_5_AND_LATER +#endif +#endif + +#ifndef CCAPI_DEPRECATED +#define CCAPI_DEPRECATED +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)) +#pragma pack(push,2) +#endif + +/* Some old types get directly mapped to new types */ + +typedef cc_context_d apiCB; +typedef cc_ccache_d ccache_p; +typedef cc_credentials_iterator_d ccache_cit_creds; +typedef cc_ccache_iterator_d ccache_cit_ccache; +typedef cc_data cc_data_compat; +typedef cc_int32 cc_cred_vers; +typedef cc_int32 cc_result; + +/* This doesn't exist in API v3 */ +typedef cc_uint32 cc_flags; + +/* Credentials types are visible to the caller so we have to keep binary compatibility */ + +typedef struct cc_credentials_v5_compat { + char* client; + char* server; + cc_data_compat keyblock; + cc_time_t authtime; + cc_time_t starttime; + cc_time_t endtime; + cc_time_t renew_till; + cc_uint32 is_skey; + cc_uint32 ticket_flags; + cc_data_compat** addresses; + cc_data_compat ticket; + cc_data_compat second_ticket; + cc_data_compat** authdata; +} cc_credentials_v5_compat; + +enum { + KRB_NAME_SZ = 40, + KRB_INSTANCE_SZ = 40, + KRB_REALM_SZ = 40 +}; + +typedef union cred_ptr_union_compat { + cc_credentials_v5_compat* pV5Cred; +} cred_ptr_union_compat; + +typedef struct cred_union { + cc_int32 cred_type; /* cc_cred_vers */ + cred_ptr_union_compat cred; +} cred_union; + +/* NC info structure is gone in v3 */ + +struct infoNC { + char* name; + char* principal; + cc_int32 vers; +}; + +typedef struct infoNC infoNC; + +/* Some old type names */ + +typedef cc_credentials_v5_compat cc_creds; +struct ccache_cit; +typedef struct ccache_cit ccache_cit; + +enum { + CC_API_VER_2 = ccapi_version_2 +}; + +enum { + CC_NOERROR, + CC_BADNAME, + CC_NOTFOUND, + CC_END, + CC_IO, + CC_WRITE, + CC_NOMEM, + CC_FORMAT, + CC_LOCKED, + CC_BAD_API_VERSION, + CC_NO_EXIST, + CC_NOT_SUPP, + CC_BAD_PARM, + CC_ERR_CACHE_ATTACH, + CC_ERR_CACHE_RELEASE, + CC_ERR_CACHE_FULL, + CC_ERR_CRED_VERSION +}; + +enum { + CC_CRED_UNKNOWN, + /* CC_CRED_V4, */ + CC_CRED_V5, + CC_CRED_MAX +}; + +enum { + CC_LOCK_UNLOCK = 1, + CC_LOCK_READER = 2, + CC_LOCK_WRITER = 3, + CC_LOCK_NOBLOCK = 16 +}; + +CCACHE_API cc_int32 +cc_shutdown (apiCB **io_context) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_get_NC_info (apiCB *in_context, + infoNC ***out_info) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_get_change_time (apiCB *in_context, + cc_time_t *out_change_time) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_open (apiCB *in_context, + const char *in_name, + cc_int32 in_version, + cc_uint32 in_flags, + ccache_p **out_ccache) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_create (apiCB *in_context, + const char *in_name, + const char *in_principal, + cc_int32 in_version, + cc_uint32 in_flags, + ccache_p **out_ccache) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_close (apiCB *in_context, + ccache_p **ioCCache) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_destroy (apiCB *in_context, + ccache_p **io_ccache) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_seq_fetch_NCs_begin (apiCB *in_context, + ccache_cit **out_nc_iterator) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_seq_fetch_NCs_next (apiCB *in_context, + ccache_p **out_ccache, + ccache_cit *in_nc_iterator) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_seq_fetch_NCs_end (apiCB *in_context, + ccache_cit **io_nc_iterator) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_get_name (apiCB *in_context, + ccache_p *in_ccache, + char **out_name) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_get_cred_version (apiCB *in_context, + ccache_p *in_ccache, + cc_int32 *out_version) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_set_principal (apiCB *in_context, + ccache_p *in_ccache, + cc_int32 in_version, + char *in_principal) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_get_principal (apiCB *in_context, + ccache_p *in_ccache, + char **out_principal) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_store (apiCB *in_context, + ccache_p *in_ccache, + cred_union in_credentials) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_remove_cred (apiCB *in_context, + ccache_p *in_ccache, + cred_union in_credentials) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_seq_fetch_creds_begin (apiCB *in_context, + const ccache_p *in_ccache, + ccache_cit **out_ccache_iterator) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_seq_fetch_creds_next (apiCB *in_context, + cred_union **out_cred_union, + ccache_cit *in_ccache_iterator) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_seq_fetch_creds_end (apiCB *in_context, + ccache_cit **io_ccache_iterator) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_free_principal (apiCB *in_context, + char **io_principal) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_free_name (apiCB *in_context, + char **io_name) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_free_creds (apiCB *in_context, + cred_union **io_cred_union) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_free_NC_info (apiCB *in_context, + infoNC ***io_info) + CCAPI_DEPRECATED; + +CCACHE_API cc_int32 +cc_lock_request (apiCB *in_context, + const ccache_p *in_ccache, + const cc_int32 in_lock_type) + CCAPI_DEPRECATED; + +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)) +#pragma pack(pop) +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CCAPI_V2_H */ diff --git a/krb5-1.21.3/src/include/Makefile.in b/krb5-1.21.3/src/include/Makefile.in new file mode 100644 index 00000000..b9dd98e0 --- /dev/null +++ b/krb5-1.21.3/src/include/Makefile.in @@ -0,0 +1,160 @@ +mydir=include +BUILDTOP=$(REL).. +KRB5RCTMPDIR= @KRB5_RCTMPDIR@ +##DOSBUILDTOP = .. +NO_OUTPRE=1 + +all-unix: krb5/krb5.h + +all-unix: maybe-make-db.h-@DB_HEADER_VERSION@ + +generate-files-mac: krb5/krb5.h + +maybe-make-db.h-k5: + : db.h will be installed by util/db2 +maybe-make-db.h-sys: + : fall back to system db.h +maybe-make-db.h-redirect: + test -r db.h || echo '#include <@DB_HEADER@>' > db.h + +ET_HEADERS = adm_err.h asn1_err.h kdb5_err.h krb5_err.h k5e1_err.h +K5_ET_HEADERS = \ + ../lib/krb5/error_tables/krb5_err.h \ + ../lib/krb5/error_tables/k5e1_err.h \ + ../lib/krb5/error_tables/kdb5_err.h \ + ../lib/krb5/error_tables/kv5m_err.h \ + ../lib/krb5/error_tables/krb524_err.h \ + ../lib/krb5/error_tables/asn1_err.h +BUILT_HEADERS = osconf.h + +all-unix: autoconf.h $(BUILT_HEADERS) +all-windows: autoconf.h $(BUILT_HEADERS) verify-calling-conventions-krb5 + +all-unix: @MAINT@ verify-calling-conventions-krb5 + +$(srcdir)/autoconf.h.in: @MAINT@ $(srcdir)/autoconf.stmp +$(srcdir)/autoconf.stmp: $(top_srcdir)/configure.ac $(top_srcdir)/aclocal.m4 + (cd $(top_srcdir) && $(AUTOHEADER) --include=$(CONFIG_RELTOPDIR) $(AUTOHEADERFLAGS)) + touch $(srcdir)/autoconf.stmp + +##DOS##autoconf.h: win-mac.h +##DOS## $(CP) win-mac.h $@ +##DOS##osconf.h: osconf.hin +##DOS## $(CP) osconf.hin $@ + +############################################################################### +##DOS##!if 0 +# config.status will now update autoconf.stamp itself. +autoconf.h: autoconf.stamp +autoconf.stamp: $(srcdir)/autoconf.h.in $(BUILDTOP)/config.status + (cd $(BUILDTOP) && $(SHELL) config.status $(mydir)/autoconf.h) + +SYSCONFDIR = @sysconfdir@ +LOCALSTATEDIR = @localstatedir@ +RUNSTATEDIR = @runstatedir@ +BINDIR = @bindir@ +SBINDIR = @sbindir@ +LIBDIR = @libdir@ +SYSCONFCONF = @SYSCONFCONF@ + +PROCESS_REPLACE = -e "s\"@KRB5RCTMPDIR\"$(KRB5RCTMPDIR)\"" \ + -e "s\"@PREFIX\"$(INSTALL_PREFIX)\"" \ + -e "s\"@EXEC_PREFIX\"$(INSTALL_EXEC_PREFIX)\"" \ + -e "s\"@BINDIR\"$(BINDIR)\"" \ + -e "s\"@LIBDIR\"$(LIBDIR)\"" \ + -e "s\"@SBINDIR\"$(SBINDIR)\"" \ + -e "s\"@MODULEDIR\"$(MODULE_DIR)\"" \ + -e "s\"@GSSMODULEDIR\"$(GSS_MODULE_DIR)\"" \ + -e "s\"@LOCALSTATEDIR\"$(LOCALSTATEDIR)\"" \ + -e "s\"@RUNSTATEDIR\"$(RUNSTATEDIR)\"" \ + -e "s\"@SYSCONFDIR\"$(SYSCONFDIR)\"" \ + -e "s\"@DYNOBJEXT\"$(DYNOBJEXT)\"" \ + -e "s\"@SYSCONFCONF\"$(SYSCONFCONF)\"" + +OSCONFSRC = $(srcdir)/osconf.hin + +osconf.h: $(OSCONFSRC) Makefile + cat $(OSCONFSRC) | sed $(PROCESS_REPLACE) > osconf.new + $(MOVEIFCHANGED) osconf.new osconf.h +##DOS##!endif +############################################################################### + +krb5/krb5.h: krb5.stamp; : krb5.h +krb5.stamp: $(srcdir)/krb5/krb5.hin $(K5_ET_HEADERS) + test -d krb5 || mkdir krb5 + if test -r krb5.h; then \ + if cmp -s krb5.h $(srcdir)/krb5.h; then :; else rm -f krb5.h; fi; \ + else :; fi + echo "/* This file is generated, please don't edit it directly. */" > krb5/krb5.new + echo "#ifndef KRB5_KRB5_H_INCLUDED" >> krb5/krb5.new + echo "#define KRB5_KRB5_H_INCLUDED" >> krb5/krb5.new + cat $(srcdir)/krb5/krb5.hin $(K5_ET_HEADERS) >> krb5/krb5.new + echo "#endif /* KRB5_KRB5_H_INCLUDED */" >> krb5/krb5.new + $(MOVEIFCHANGED) krb5/krb5.new krb5/krb5.h + touch krb5.stamp + +verify-calling-conventions-krb5: private-and-public-decls + $(PERL) -w $(top_srcdir)/util/def-check.pl private-and-public-decls $(top_srcdir)/lib/krb5_32.def + +##DOS##!if 0 +HEADERS_TO_CHECK = krb5/krb5.h $(srcdir)/k5-int.h $(srcdir)/krb5/clpreauth_plugin.h + +private-and-public-decls: $(HEADERS_TO_CHECK) + cat $(HEADERS_TO_CHECK) > $@ +##DOS##!endif +##DOS##private-and-public-decls: +##DOS## copy /y krb5\krb5.h+k5-int.h+krb5\clpreauth_plugin.h $@ + +# +# Build the error table include files: +# asn1_err.h kdb5_err.h krb5_err.h k5e1_err.h kv5m_err.h krb524_err.h + +$(K5_ET_HEADERS): rebuild-error-tables + : $@ +rebuild-error-tables: + (cd ../lib/krb5/error_tables && $(MAKE) includes) + +.PHONY: force rebuild-error-tables +force: + +clean-unix:: + $(RM) krb5/krb5.h krb5_err.h k5e1_err.h kdb5_err.h kv5m_err.h \ + krb524_err.h asn1_err.h private-and-public-decls krb5.stamp + $(RM) $(ET_HEADERS) autoconf.stamp + +clean-windows:: + $(RM) com_err.h profile.h + $(RM) gssapi\gssapi.h gssapi\gssapi_generic.h gssapi\gssapi_krb5.h + $(RM) gssapi\gssapi_alloc.h gssapi\gssapi_ext.h gssapi\timestamp + if exist gssapi\nul rmdir /s /q gssapi + $(RM) osconf.h autoconf.h autoconf.stamp + @echo Making clean in include + +clean: + $(RM) osconf.new $(BUILT_HEADERS) + +distclean: + $(RM) autoconf.h $(srcdir)/autoconf.stmp + +install-headers-unix install: krb5/krb5.h profile.h + $(INSTALL_DATA) $(srcdir)/krb5.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5.h + $(INSTALL_DATA) $(srcdir)/kdb.h $(DESTDIR)$(KRB5_INCDIR)$(S)kdb.h + $(INSTALL_DATA) krb5/krb5.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)krb5.h + $(INSTALL_DATA) $(srcdir)/krb5/certauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)certauth_plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/ccselect_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)ccselect_plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/clpreauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)clpreauth_plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/hostrealm_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)hostrealm_plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/kdcpolicy_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kdcpolicy_plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/kdcpreauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kdcpreauth_plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/localauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)localauth_plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/locate_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)locate_plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/preauth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)preauth_plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/pwqual_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)pwqual_plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/kadm5_auth_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kadm5_auth_plugin.h + $(INSTALL_DATA) $(srcdir)/krb5/kadm5_hook_plugin.h $(DESTDIR)$(KRB5_INCDIR)$(S)krb5$(S)kadm5_hook_plugin.h + $(INSTALL_DATA) profile.h $(DESTDIR)$(KRB5_INCDIR)$(S)profile.h + $(INSTALL_DATA) $(srcdir)/gssapi.h $(DESTDIR)$(KRB5_INCDIR)$(S)gssapi.h + $(INSTALL_DATA) $(srcdir)/krad.h $(DESTDIR)$(KRB5_INCDIR)/krad.h + +depend: krb5/krb5.h $(BUILT_HEADERS) diff --git a/krb5-1.21.3/src/include/adm_proto.h b/krb5-1.21.3/src/include/adm_proto.h new file mode 100644 index 00000000..5d876aa3 --- /dev/null +++ b/krb5-1.21.3/src/include/adm_proto.h @@ -0,0 +1,91 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/adm_proto.h */ +/* + * Copyright 1995, 2007,2008,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef KRB5_ADM_PROTO_H__ +#define KRB5_ADM_PROTO_H__ + +/* + * This is ugly, but avoids having to include k5-int or kdb.h for this. + */ +#ifndef KRB5_KDB5__ +struct _krb5_db_entry; +typedef struct _krb5_db_entry krb5_db_entry; +#endif /* KRB5_KDB5__ */ + +/* Ditto for admin.h */ + +#ifndef KRB5_KDB5__ +struct ___krb5_key_salt_tuple; +typedef struct ___krb5_key_salt_tuple krb5_key_salt_tuple; +#endif /* KRB5_KDB5__ */ + +/* + * Function prototypes. + */ + +/* logger.c */ +krb5_error_code krb5_klog_init(krb5_context, char *, char *, krb5_boolean); +void krb5_klog_set_context(krb5_context); +void krb5_klog_close(krb5_context); +int krb5_klog_syslog(int, const char *, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; +void krb5_klog_reopen (krb5_context); + +/* alt_prof.c */ +krb5_error_code krb5_aprof_getvals(krb5_pointer, const char **, char ***); +krb5_error_code krb5_aprof_get_boolean(krb5_pointer, const char **, int, + krb5_boolean *); +krb5_error_code krb5_aprof_get_deltat(krb5_pointer, const char **, + krb5_boolean, krb5_deltat *); +krb5_error_code krb5_aprof_get_string(krb5_pointer, const char **, + krb5_boolean, char **); +krb5_error_code krb5_aprof_get_string_all(krb5_pointer, const char **, + char **); +krb5_error_code krb5_aprof_get_int32(krb5_pointer, const char **, + krb5_boolean, krb5_int32 *); + +/* str_conv.c */ +krb5_error_code krb5_flagspec_to_mask(const char *, + krb5_flags *, krb5_flags *); +krb5_error_code krb5_flagnum_to_string(int, char **); +krb5_error_code krb5_flags_to_strings(krb5_int32, char ***); + +/* keysalt.c */ +krb5_boolean krb5_keysalt_is_present(krb5_key_salt_tuple *, krb5_int32, + krb5_enctype, krb5_int32); +krb5_error_code krb5_keysalt_iterate(krb5_key_salt_tuple *, krb5_int32, + krb5_boolean, + krb5_error_code (*)(krb5_key_salt_tuple *, + krb5_pointer), + krb5_pointer); + +krb5_error_code krb5_string_to_keysalts(const char *, const char *, + const char *, krb5_boolean, + krb5_key_salt_tuple **, krb5_int32 *); +#endif /* KRB5_ADM_PROTO_H__ */ diff --git a/krb5-1.21.3/src/include/autoconf.h.in b/krb5-1.21.3/src/include/autoconf.h.in new file mode 100644 index 00000000..8a6384c4 --- /dev/null +++ b/krb5-1.21.3/src/include/autoconf.h.in @@ -0,0 +1,765 @@ +/* include/autoconf.h.in. Generated from configure.ac by autoheader. */ + + +#ifndef KRB5_AUTOCONF_H +#define KRB5_AUTOCONF_H + + +/* Define if AES-NI support is enabled */ +#undef AESNI + +/* Define if socket can't be bound to 0.0.0.0 */ +#undef BROKEN_STREAMS_SOCKETS + +/* Define if va_list objects can be simply copied by assignment. */ +#undef CAN_COPY_VA_LIST + +/* Define to reduce code size even if it means more cpu usage */ +#undef CONFIG_SMALL + +/* Define if __attribute__((constructor)) works */ +#undef CONSTRUCTOR_ATTR_WORKS + +/* Define to use OpenSSL crypto library */ +#undef CRYPTO_OPENSSL + +/* Define to default ccache name */ +#undef DEFCCNAME + +/* Define to default client keytab name */ +#undef DEFCKTNAME + +/* Define to default keytab name */ +#undef DEFKTNAME + +/* Define if library initialization should be delayed until first use */ +#undef DELAY_INITIALIZER + +/* Define if __attribute__((destructor)) works */ +#undef DESTRUCTOR_ATTR_WORKS + +/* Define to disable PKINIT plugin support */ +#undef DISABLE_PKINIT + +/* Define if LDAP KDB support within the Kerberos library (mainly ASN.1 code) + should be enabled. */ +#undef ENABLE_LDAP + +/* Define if translation functions should be used. */ +#undef ENABLE_NLS + +/* Define if thread support enabled */ +#undef ENABLE_THREADS + +/* Define as return type of endrpcent */ +#undef ENDRPCENT_TYPE + +/* Define to the type of elements in the array set by `getgroups'. Usually + this is either `int' or `gid_t'. */ +#undef GETGROUPS_T + +/* Define if gethostbyname_r returns int rather than struct hostent * */ +#undef GETHOSTBYNAME_R_RETURNS_INT + +/* Type of getpeername second argument. */ +#undef GETPEERNAME_ARG3_TYPE + +/* Define if getpwnam_r exists but takes only 4 arguments (e.g., POSIX draft 6 + implementations like some Solaris releases). */ +#undef GETPWNAM_R_4_ARGS + +/* Define if getpwnam_r returns an int */ +#undef GETPWNAM_R_RETURNS_INT + +/* Define if getpwuid_r exists but takes only 4 arguments (e.g., POSIX draft 6 + implementations like some Solaris releases). */ +#undef GETPWUID_R_4_ARGS + +/* Define if getservbyname_r returns int rather than struct servent * */ +#undef GETSERVBYNAME_R_RETURNS_INT + +/* Type of pointer target for argument 3 to getsockname */ +#undef GETSOCKNAME_ARG3_TYPE + +/* Define if gmtime_r returns int instead of struct tm pointer, as on old + HP-UX systems. */ +#undef GMTIME_R_RETURNS_INT + +/* Define if va_copy macro or function is available. */ +#undef HAS_VA_COPY + +/* Define to 1 if you have the `access' function. */ +#undef HAVE_ACCESS + +/* Define to 1 if you have the header file. */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the `bswap16' function. */ +#undef HAVE_BSWAP16 + +/* Define to 1 if you have the `bswap64' function. */ +#undef HAVE_BSWAP64 + +/* Define to 1 if bswap_16 is available via byteswap.h */ +#undef HAVE_BSWAP_16 + +/* Define to 1 if bswap_64 is available via byteswap.h */ +#undef HAVE_BSWAP_64 + +/* Define if bt_rseq is available, for recursive btree traversal. */ +#undef HAVE_BT_RSEQ + +/* Define to 1 if you have the header file. */ +#undef HAVE_BYTESWAP_H + +/* Define to 1 if you have the `chmod' function. */ +#undef HAVE_CHMOD + +/* Define if cmocka library is available. */ +#undef HAVE_CMOCKA + +/* Define to 1 if you have the `compile' function. */ +#undef HAVE_COMPILE + +/* Define if com_err has compatible gettext support */ +#undef HAVE_COM_ERR_INTL + +/* Define to 1 if you have the header file. */ +#undef HAVE_CPUID_H + +/* Define to 1 if you have the `daemon' function. */ +#undef HAVE_DAEMON + +/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you + don't. */ +#undef HAVE_DECL_STRERROR_R + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `dn_skipname' function. */ +#undef HAVE_DN_SKIPNAME + +/* Define to 1 if you have the header file. */ +#undef HAVE_ENDIAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if you have the `EVP_PKEY_get_bn_param' function. */ +#undef HAVE_EVP_PKEY_GET_BN_PARAM + +/* Define to 1 if you have the `explicit_bzero' function. */ +#undef HAVE_EXPLICIT_BZERO + +/* Define to 1 if you have the `explicit_memset' function. */ +#undef HAVE_EXPLICIT_MEMSET + +/* Define to 1 if you have the `fchmod' function. */ +#undef HAVE_FCHMOD + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `flock' function. */ +#undef HAVE_FLOCK + +/* Define to 1 if you have the `fnmatch' function. */ +#undef HAVE_FNMATCH + +/* Define to 1 if you have the header file. */ +#undef HAVE_FNMATCH_H + +/* Define if you have the getaddrinfo function */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the `getcwd' function. */ +#undef HAVE_GETCWD + +/* Define to 1 if you have the `getenv' function. */ +#undef HAVE_GETENV + +/* Define to 1 if you have the `geteuid' function. */ +#undef HAVE_GETEUID + +/* Define if gethostbyname_r exists and its return type is known */ +#undef HAVE_GETHOSTBYNAME_R + +/* Define to 1 if you have the `getnameinfo' function. */ +#undef HAVE_GETNAMEINFO + +/* Define if system getopt should be used. */ +#undef HAVE_GETOPT + +/* Define if system getopt_long should be used. */ +#undef HAVE_GETOPT_LONG + +/* Define if getpwnam_r is available and useful. */ +#undef HAVE_GETPWNAM_R + +/* Define if getpwuid_r is available and useful. */ +#undef HAVE_GETPWUID_R + +/* Define to 1 if you have the `getresgid' function. */ +#undef HAVE_GETRESGID + +/* Define to 1 if you have the `getresuid' function. */ +#undef HAVE_GETRESUID + +/* Define if getservbyname_r exists and its return type is known */ +#undef HAVE_GETSERVBYNAME_R + +/* Have the gettimeofday function */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `getusershell' function. */ +#undef HAVE_GETUSERSHELL + +/* Define to 1 if you have the `gmtime_r' function. */ +#undef HAVE_GMTIME_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_IFADDRS_H + +/* Define to 1 if you have the `inet_ntop' function. */ +#undef HAVE_INET_NTOP + +/* Define to 1 if you have the `inet_pton' function. */ +#undef HAVE_INET_PTON + +/* Define to 1 if the system has the type `int16_t'. */ +#undef HAVE_INT16_T + +/* Define to 1 if the system has the type `int32_t'. */ +#undef HAVE_INT32_T + +/* Define to 1 if the system has the type `int8_t'. */ +#undef HAVE_INT8_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_KEYUTILS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LBER_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LDAP_H + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +#undef HAVE_LIBCRYPTO + +/* Define if building with libedit. */ +#undef HAVE_LIBEDIT + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define to 1 if you have the `resolv' library (-lresolv). */ +#undef HAVE_LIBRESOLV + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define if the util library is available */ +#undef HAVE_LIBUTIL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_MACHINE_BYTE_ORDER_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MACHINE_ENDIAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define if netdb.h declares h_errno */ +#undef HAVE_NETDB_H_H_ERRNO + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the `ns_initparse' function. */ +#undef HAVE_NS_INITPARSE + +/* Define to 1 if you have the `ns_name_uncompress' function. */ +#undef HAVE_NS_NAME_UNCOMPRESS + +/* Define to 1 if you have the header file. */ +#undef HAVE_PATHS_H + +/* Define if persistent keyrings are supported */ +#undef HAVE_PERSISTENT_KEYRING + +/* Define to 1 if you have the header file. */ +#undef HAVE_POLL_H + +/* Define if #pragma weak references work */ +#undef HAVE_PRAGMA_WEAK_REF + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Define to 1 if you have the `pthread_once' function. */ +#undef HAVE_PTHREAD_ONCE + +/* Have PTHREAD_PRIO_INHERIT. */ +#undef HAVE_PTHREAD_PRIO_INHERIT + +/* Define to 1 if you have the `pthread_rwlock_init' function. */ +#undef HAVE_PTHREAD_RWLOCK_INIT + +/* Define if pthread_rwlock_init is provided in the thread library. */ +#undef HAVE_PTHREAD_RWLOCK_INIT_IN_THREAD_LIB + +/* Define to 1 if you have the header file. */ +#undef HAVE_PWD_H + +/* Define if building with GNU Readline. */ +#undef HAVE_READLINE + +/* Define if regcomp exists and functions */ +#undef HAVE_REGCOMP + +/* Define to 1 if you have the `regexec' function. */ +#undef HAVE_REGEXEC + +/* Define to 1 if you have the header file. */ +#undef HAVE_REGEXPR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_REGEX_H + +/* Define to 1 if you have the `res_nclose' function. */ +#undef HAVE_RES_NCLOSE + +/* Define to 1 if you have the `res_ndestroy' function. */ +#undef HAVE_RES_NDESTROY + +/* Define to 1 if you have the `res_ninit' function. */ +#undef HAVE_RES_NINIT + +/* Define to 1 if you have the `res_nsearch' function. */ +#undef HAVE_RES_NSEARCH + +/* Define to 1 if you have the `res_search' function */ +#undef HAVE_RES_SEARCH + +/* Define to 1 if you have the `re_comp' function. */ +#undef HAVE_RE_COMP + +/* Define to 1 if you have the `re_exec' function. */ +#undef HAVE_RE_EXEC + +/* Define to 1 if you have the header file. */ +#undef HAVE_SASL_SASL_H + +/* Define if struct sockaddr contains sa_len */ +#undef HAVE_SA_LEN + +/* Define to 1 if you have the `secure_getenv' function. */ +#undef HAVE_SECURE_GETENV + +/* Define to 1 if you have the `setegid' function. */ +#undef HAVE_SETEGID + +/* Define to 1 if you have the `setenv' function. */ +#undef HAVE_SETENV + +/* Define to 1 if you have the `seteuid' function. */ +#undef HAVE_SETEUID + +/* Define if setluid provided in OSF/1 security library */ +#undef HAVE_SETLUID + +/* Define to 1 if you have the `setregid' function. */ +#undef HAVE_SETREGID + +/* Define to 1 if you have the `setresgid' function. */ +#undef HAVE_SETRESGID + +/* Define to 1 if you have the `setresuid' function. */ +#undef HAVE_SETRESUID + +/* Define to 1 if you have the `setreuid' function. */ +#undef HAVE_SETREUID + +/* Define to 1 if you have the `setsid' function. */ +#undef HAVE_SETSID + +/* Define to 1 if you have the `setvbuf' function. */ +#undef HAVE_SETVBUF + +/* Define if there is a socklen_t type. If not, probably use size_t */ +#undef HAVE_SOCKLEN_T + +/* Define to 1 if you have the `srand' function. */ +#undef HAVE_SRAND + +/* Define to 1 if you have the `srand48' function. */ +#undef HAVE_SRAND48 + +/* Define to 1 if you have the `srandom' function. */ +#undef HAVE_SRANDOM + +/* Define to 1 if the system has the type `ssize_t'. */ +#undef HAVE_SSIZE_T + +/* Define to 1 if you have the `stat' function. */ +#undef HAVE_STAT + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `step' function. */ +#undef HAVE_STEP + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define if you have `strerror_r'. */ +#undef HAVE_STRERROR_R + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strlcpy' function. */ +#undef HAVE_STRLCPY + +/* Define to 1 if you have the `strptime' function. */ +#undef HAVE_STRPTIME + +/* Define to 1 if the system has the type `struct cmsghdr'. */ +#undef HAVE_STRUCT_CMSGHDR + +/* Define if there is a struct if_laddrconf. */ +#undef HAVE_STRUCT_IF_LADDRCONF + +/* Define to 1 if the system has the type `struct in6_pktinfo'. */ +#undef HAVE_STRUCT_IN6_PKTINFO + +/* Define to 1 if the system has the type `struct in_pktinfo'. */ +#undef HAVE_STRUCT_IN_PKTINFO + +/* Define if there is a struct lifconf. */ +#undef HAVE_STRUCT_LIFCONF + +/* Define to 1 if the system has the type `struct rt_msghdr'. */ +#undef HAVE_STRUCT_RT_MSGHDR + +/* Define to 1 if the system has the type `struct sockaddr_storage'. */ +#undef HAVE_STRUCT_SOCKADDR_STORAGE + +/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_MTIMENSEC + +/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC + +/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_BSWAP_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define if sys_errlist in libc */ +#undef HAVE_SYS_ERRLIST + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_FILIO_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKIO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UIO_H + +/* Define to 1 if you have the `timegm' function. */ +#undef HAVE_TIMEGM + +/* Define to 1 if you have the header file. */ +#undef HAVE_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `unsetenv' function. */ +#undef HAVE_UNSETENV + +/* Define to 1 if the system has the type `u_char'. */ +#undef HAVE_U_CHAR + +/* Define to 1 if the system has the type `u_int'. */ +#undef HAVE_U_INT + +/* Define to 1 if the system has the type `u_int16_t'. */ +#undef HAVE_U_INT16_T + +/* Define to 1 if the system has the type `u_int32_t'. */ +#undef HAVE_U_INT32_T + +/* Define to 1 if the system has the type `u_int8_t'. */ +#undef HAVE_U_INT8_T + +/* Define to 1 if the system has the type `u_long'. */ +#undef HAVE_U_LONG + +/* Define to 1 if you have the `vasprintf' function. */ +#undef HAVE_VASPRINTF + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Define to 1 if you have the `vsprintf' function. */ +#undef HAVE_VSPRINTF + +/* Define to 1 if the system has the type `__int128_t'. */ +#undef HAVE___INT128_T + +/* Define to 1 if the system has the type `__uint128_t'. */ +#undef HAVE___UINT128_T + +/* Define if errno.h declares perror */ +#undef HDR_HAS_PERROR + +/* May need to be defined to enable IPv6 support, for example on IRIX */ +#undef INET6 + +/* Define if MIT Project Athena default configuration should be used */ +#undef KRB5_ATHENA_COMPAT + +/* Define for DNS support of locating realms and KDCs */ +#undef KRB5_DNS_LOOKUP + +/* Define to enable DNS lookups of Kerberos realm names */ +#undef KRB5_DNS_LOOKUP_REALM + +/* Define if the KDC should return only vague error codes to clients */ +#undef KRBCONF_VAGUE_ERRORS + +/* define if the system header files are missing prototype for daemon() */ +#undef NEED_DAEMON_PROTO + +/* Define if in6addr_any is not defined in libc */ +#undef NEED_INSIXADDR_ANY + +/* define if the system header files are missing prototype for + ss_execute_command() */ +#undef NEED_SS_EXECUTE_COMMAND_PROTO + +/* define if the system header files are missing prototype for strptime() */ +#undef NEED_STRPTIME_PROTO + +/* define if the system header files are missing prototype for swab() */ +#undef NEED_SWAB_PROTO + +/* Define if need to declare sys_errlist */ +#undef NEED_SYS_ERRLIST + +/* define if the system header files are missing prototype for vasprintf() */ +#undef NEED_VASPRINTF_PROTO + +/* Define if the KDC should use no lookaside cache */ +#undef NOCACHE + +/* Define if references to pthread routines should be non-weak. */ +#undef NO_WEAK_PTHREADS + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Default PKCS11 module name */ +#undef PKCS11_MODNAME + +/* Define if setjmp indicates POSIX interface */ +#undef POSIX_SETJMP + +/* Define if POSIX signal handling is used */ +#undef POSIX_SIGNALS + +/* Define if termios.h exists and tcsetattr exists */ +#undef POSIX_TERMIOS + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* Define as return type of setrpcent */ +#undef SETRPCENT_TYPE + +/* The size of `size_t', as computed by sizeof. */ +#undef SIZEOF_SIZE_T + +/* The size of `time_t', as computed by sizeof. */ +#undef SIZEOF_TIME_T + +/* Define to use OpenSSL for SPAKE preauth */ +#undef SPAKE_OPENSSL + +/* Define for static plugin linkage */ +#undef STATIC_PLUGINS + +/* Define to 1 if all of the C90 standard headers exist (not just the ones + required in a freestanding environment). This macro is provided for + backward compatibility; new code need not use it. */ +#undef STDC_HEADERS + +/* Define to 1 if strerror_r returns char *. */ +#undef STRERROR_R_CHAR_P + +/* Define if sys_errlist is defined in errno.h */ +#undef SYS_ERRLIST_DECLARED + +/* Define if no TLS implementation is selected */ +#undef TLS_IMPL_NONE + +/* Define if TLS implementation is OpenSSL */ +#undef TLS_IMPL_OPENSSL + +/* Define to build macOS CCAPI client */ +#undef USE_CCAPI_MACOS + +/* Define if you have dirent.h functionality */ +#undef USE_DIRENT_H + +/* Define if dlopen should be used */ +#undef USE_DLOPEN + +/* Define if the keyring ccache should be enabled */ +#undef USE_KEYRING_CCACHE + +/* Define if link-time options for library finalization will be used */ +#undef USE_LINKER_FINI_OPTION + +/* Define if link-time options for library initialization will be used */ +#undef USE_LINKER_INIT_OPTION + +/* Define if sigprocmask should be used */ +#undef USE_SIGPROCMASK + +/* Define if wait takes int as a argument */ +#undef WAIT_USES_INT + +/* Define to enable extensions in glibc */ +#undef _GNU_SOURCE + +/* Define to enable C11 extensions */ +#undef __STDC_WANT_LIB_EXT1__ + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `int' if doesn't define. */ +#undef gid_t + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to `int' if does not define. */ +#undef mode_t + +/* Define to `long int' if does not define. */ +#undef off_t + +/* Define to `long' if does not define. */ +#undef time_t + +/* Define to `int' if doesn't define. */ +#undef uid_t + + +#if defined(__GNUC__) && !defined(inline) +/* Silence gcc pedantic warnings about ANSI C. */ +# define inline __inline__ +#endif +#endif /* KRB5_AUTOCONF_H */ + diff --git a/krb5-1.21.3/src/include/copyright.h b/krb5-1.21.3/src/include/copyright.h new file mode 100644 index 00000000..705e0a75 --- /dev/null +++ b/krb5-1.21.3/src/include/copyright.h @@ -0,0 +1,41 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1989-1994 by the Massachusetts Institute of Technology, + * Cambridge, MA, USA. All Rights Reserved. + * + * This software is being provided to you, the LICENSEE, by the + * Massachusetts Institute of Technology (M.I.T.) under the following + * license. By obtaining, using and/or copying this software, you agree + * that you have read, understood, and will comply with these terms and + * conditions: + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute + * this software and its documentation for any purpose and without fee or + * royalty is hereby granted, provided that you agree to comply with the + * following copyright notice and statements, including the disclaimer, and + * that the same appear on ALL copies of the software and documentation, + * including modifications that you make for internal use or for + * distribution: + * + * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS + * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF + * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF + * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY + * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + * + * The name of the Massachusetts Institute of Technology or M.I.T. may NOT + * be used in advertising or publicity pertaining to distribution of the + * software. Title to copyright in this software and any associated + * documentation shall at all times remain with M.I.T., and USER agrees to + * preserve same. + * + * Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + */ diff --git a/krb5-1.21.3/src/include/deps b/krb5-1.21.3/src/include/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/include/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/include/fake-addrinfo.h b/krb5-1.21.3/src/include/fake-addrinfo.h new file mode 100644 index 00000000..6d18d4f4 --- /dev/null +++ b/krb5-1.21.3/src/include/fake-addrinfo.h @@ -0,0 +1,234 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2001,2002,2003,2004 by the Massachusetts Institute of Technology, + * Cambridge, MA, USA. All Rights Reserved. + * + * This software is being provided to you, the LICENSEE, by the + * Massachusetts Institute of Technology (M.I.T.) under the following + * license. By obtaining, using and/or copying this software, you agree + * that you have read, understood, and will comply with these terms and + * conditions: + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute + * this software and its documentation for any purpose and without fee or + * royalty is hereby granted, provided that you agree to comply with the + * following copyright notice and statements, including the disclaimer, and + * that the same appear on ALL copies of the software and documentation, + * including modifications that you make for internal use or for + * distribution: + * + * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS + * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF + * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF + * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY + * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + * + * The name of the Massachusetts Institute of Technology or M.I.T. may NOT + * be used in advertising or publicity pertaining to distribution of the + * software. Title to copyright in this software and any associated + * documentation shall at all times remain with M.I.T., and USER agrees to + * preserve same. + * + * Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + */ + +/* Approach overview: + + If a system version is available but buggy, save handles to it (via + inline functions in a support library), redefine the names to refer + to library functions, and in those functions, call the system + versions and fix up the returned data. Use the native data + structures and flag values. + + If no system version exists, use gethostby* and fake it. Define + the data structures and flag values locally. + + + On macOS, getaddrinfo results aren't cached (though + gethostbyname results are), so we need to build a cache here. Now + things are getting really messy. Because the cache is in use, we + use getservbyname, and throw away thread safety. (Not that the + cache is thread safe, but when we get locking support, that'll be + dealt with.) This code needs tearing down and rebuilding, soon. + + + Note that recent Windows developers' code has an interesting hack: + When you include the right header files, with the right set of + macros indicating system versions, you'll get an inline function + that looks for getaddrinfo (or whatever) in the system library, and + calls it if it's there. If it's not there, it fakes it with + gethostby* calls. + + We're taking a simpler approach: A system provides these routines or + it does not. + + Someday, we may want to take into account different versions (say, + different revs of GNU libc) where some are broken in one way, and + some work or are broken in another way. Cross that bridge when we + come to it. */ + +/* To do, maybe: + + + For AIX 4.3.3, using the RFC 2133 definition: Implement + AI_NUMERICHOST. It's not defined in the header file. + + For certain (old?) versions of GNU libc, AI_NUMERICHOST is + defined but not implemented. + + + Use gethostbyname2, inet_aton and other IPv6 or thread-safe + functions if available. But, see + https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=135182 for one + gethostbyname2 problem on Linux. And besides, if a platform is + supporting IPv6 at all, they really should be doing getaddrinfo + by now. + + + inet_ntop, inet_pton + + + Conditionally export/import the function definitions, so a + library can have a single copy instead of multiple. + + + Upgrade host requirements to include working implementations of + these functions, and throw all this away. Pleeease? :-) */ + +#ifndef FAI_DEFINED +#define FAI_DEFINED +#include "port-sockets.h" +#include "socket-utils.h" + +#if !defined (HAVE_GETADDRINFO) + +#undef addrinfo +#define addrinfo my_fake_addrinfo + +struct addrinfo { + int ai_family; /* PF_foo */ + int ai_socktype; /* SOCK_foo */ + int ai_protocol; /* 0, IPPROTO_foo */ + int ai_flags; /* AI_PASSIVE etc */ + size_t ai_addrlen; /* real length of socket address */ + char *ai_canonname; /* canonical name of host */ + struct sockaddr *ai_addr; /* pointer to variable-size address */ + struct addrinfo *ai_next; /* next in linked list */ +}; + +#undef AI_PASSIVE +#define AI_PASSIVE 0x01 +#undef AI_CANONNAME +#define AI_CANONNAME 0x02 +#undef AI_NUMERICHOST +#define AI_NUMERICHOST 0x04 +/* RFC 2553 says these are part of the interface for getipnodebyname, + not for getaddrinfo. RFC 3493 says they're part of the interface + for getaddrinfo, and getipnodeby* are deprecated. Our fake + getaddrinfo implementation here does IPv4 only anyways. */ +#undef AI_V4MAPPED +#define AI_V4MAPPED 0 +#undef AI_ADDRCONFIG +#define AI_ADDRCONFIG 0 +#undef AI_ALL +#define AI_ALL 0 +#undef AI_DEFAULT +#define AI_DEFAULT (AI_V4MAPPED|AI_ADDRCONFIG) + +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif +#ifndef NI_MAXSERV +#define NI_MAXSERV 32 +#endif + +#undef NI_NUMERICHOST +#define NI_NUMERICHOST 0x01 +#undef NI_NUMERICSERV +#define NI_NUMERICSERV 0x02 +#undef NI_NAMEREQD +#define NI_NAMEREQD 0x04 +#undef NI_DGRAM +#define NI_DGRAM 0x08 +#undef NI_NOFQDN +#define NI_NOFQDN 0x10 + + +#undef EAI_ADDRFAMILY +#define EAI_ADDRFAMILY 1 +#undef EAI_AGAIN +#define EAI_AGAIN 2 +#undef EAI_BADFLAGS +#define EAI_BADFLAGS 3 +#undef EAI_FAIL +#define EAI_FAIL 4 +#undef EAI_FAMILY +#define EAI_FAMILY 5 +#undef EAI_MEMORY +#define EAI_MEMORY 6 +#undef EAI_NODATA +#define EAI_NODATA 7 +#undef EAI_NONAME +#define EAI_NONAME 8 +#undef EAI_SERVICE +#define EAI_SERVICE 9 +#undef EAI_SOCKTYPE +#define EAI_SOCKTYPE 10 +#undef EAI_SYSTEM +#define EAI_SYSTEM 11 + +#endif /* ! HAVE_GETADDRINFO */ + +/* Fudge things on older gai implementations. */ +/* AIX 4.3.3 is based on RFC 2133; no AI_NUMERICHOST. */ +#ifndef AI_NUMERICHOST +# define AI_NUMERICHOST 0 +#endif +/* Partial RFC 2553 implementations may not have AI_ADDRCONFIG and + friends, which RFC 3493 says are now part of the getaddrinfo + interface, and we'll want to use. */ +#ifndef AI_ADDRCONFIG +# define AI_ADDRCONFIG 0 +#endif +#ifndef AI_V4MAPPED +# define AI_V4MAPPED 0 +#endif +#ifndef AI_ALL +# define AI_ALL 0 +#endif +#ifndef AI_DEFAULT +# define AI_DEFAULT (AI_ADDRCONFIG|AI_V4MAPPED) +#endif + +#if defined(NEED_INSIXADDR_ANY) +/* If compiling with IPv6 support and C library does not define in6addr_any */ +extern const struct in6_addr krb5int_in6addr_any; +#undef in6addr_any +#define in6addr_any krb5int_in6addr_any +#endif + +/* Call out to stuff defined in libkrb5support. */ +extern int krb5int_getaddrinfo (const char *node, const char *service, + const struct addrinfo *hints, + struct addrinfo **aip); +extern void krb5int_freeaddrinfo (struct addrinfo *ai); +extern const char *krb5int_gai_strerror(int err); +extern int krb5int_getnameinfo (const struct sockaddr *sa, socklen_t salen, + char *hbuf, size_t hbuflen, + char *sbuf, size_t sbuflen, + int flags); +#ifndef IMPLEMENT_FAKE_GETADDRINFO +#undef getaddrinfo +#define getaddrinfo krb5int_getaddrinfo +#undef freeaddrinfo +#define freeaddrinfo krb5int_freeaddrinfo +#undef gai_strerror +#define gai_strerror krb5int_gai_strerror +#undef getnameinfo +#define getnameinfo krb5int_getnameinfo +#endif + +#endif /* FAI_DEFINED */ diff --git a/krb5-1.21.3/src/include/foreachaddr.h b/krb5-1.21.3/src/include/foreachaddr.h new file mode 100644 index 00000000..9ed35eab --- /dev/null +++ b/krb5-1.21.3/src/include/foreachaddr.h @@ -0,0 +1,66 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/foreachaddr.h */ +/* + * Copyright 1990,1991,2000,2001,2002,2004 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * Iterate over the protocol addresses supported by this host, invoking + * a callback function or three supplied by the caller. + * + * XNS support is untested, but "should just work". (Hah!) + */ + +/* This function iterates over all the addresses it can find for the + local system, in one or two passes. In each pass, and between the + two, it can invoke callback functions supplied by the caller. The + two passes should operate on the same information, though not + necessarily in the same order each time. Duplicate and local + addresses should be eliminated. Storage passed to callback + functions should not be assumed to be valid after foreach_localaddr + returns. + + The int return value is an errno value (XXX or krb5_error_code + returned for a socket error) if something internal to + foreach_localaddr fails. If one of the callback functions wants to + indicate an error, it should store something via the 'data' handle. + If any callback function returns a non-zero value, + foreach_localaddr will clean up and return immediately. + + Multiple definitions are provided below, dependent on various + system facilities for extracting the necessary information. */ + +extern int +krb5int_foreach_localaddr (/*@null@*/ void *data, + int (*pass1fn) (/*@null@*/ void *, + struct sockaddr *) /*@*/, + /*@null@*/ int (*betweenfn) (/*@null@*/ void *) /*@*/, + /*@null@*/ int (*pass2fn) (/*@null@*/ void *, + struct sockaddr *) /*@*/) +#if defined(DEBUG) || defined(TEST) +/*@modifies fileSystem@*/ +#endif + ; + +#define foreach_localaddr krb5int_foreach_localaddr diff --git a/krb5-1.21.3/src/include/gssapi.h b/krb5-1.21.3/src/include/gssapi.h new file mode 100644 index 00000000..9383dabd --- /dev/null +++ b/krb5-1.21.3/src/include/gssapi.h @@ -0,0 +1,6 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Wrapper so that #include will work without special include + * paths. + */ +#include diff --git a/krb5-1.21.3/src/include/gssrpc/auth.h b/krb5-1.21.3/src/include/gssrpc/auth.h new file mode 100644 index 00000000..0bfa3ec8 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/auth.h @@ -0,0 +1,205 @@ +/* @(#)auth.h 2.3 88/08/07 4.0 RPCSRC; from 1.17 88/02/08 SMI */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * 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 the "Oracle America, Inc." 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 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. + */ + +/* + * auth.h, Authentication interface. + * + * The data structures are completely opaque to the client. The client + * is required to pass a AUTH * to routines that create rpc + * "sessions". + */ +#ifndef GSSRPC_AUTH_H +#define GSSRPC_AUTH_H + +#include + +GSSRPC__BEGIN_DECLS + +#define MAX_AUTH_BYTES 400 +#define MAXNETNAMELEN 255 /* maximum length of network user's name */ + +/* + * Status returned from authentication check + */ +enum auth_stat { + AUTH_OK=0, + /* + * failed at remote end + */ + AUTH_BADCRED=1, /* bogus credentials (seal broken) */ + AUTH_REJECTEDCRED=2, /* client should begin new session */ + AUTH_BADVERF=3, /* bogus verifier (seal broken) */ + AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */ + AUTH_TOOWEAK=5, /* rejected due to security reasons */ + /* + * failed locally + */ + AUTH_INVALIDRESP=6, /* bogus response verifier */ + AUTH_FAILED=7, /* some unknown reason */ + /* + * RPCSEC_GSS errors + */ + RPCSEC_GSS_CREDPROBLEM = 13, + RPCSEC_GSS_CTXPROBLEM = 14 +}; + +union des_block { + char c[8]; +}; +typedef union des_block des_block; +extern bool_t xdr_des_block(XDR *, des_block *); + +/* + * Authentication info. Opaque to client. + */ +struct opaque_auth { + enum_t oa_flavor; /* flavor of auth */ + caddr_t oa_base; /* address of more auth stuff */ + u_int oa_length; /* not to exceed MAX_AUTH_BYTES */ +}; + + +/* + * Auth handle, interface to client side authenticators. + */ +struct rpc_msg; + +typedef struct AUTH { + struct opaque_auth ah_cred; + struct opaque_auth ah_verf; + union des_block ah_key; + struct auth_ops { + void (*ah_nextverf)(struct AUTH *); + /* nextverf & serialize */ + int (*ah_marshal)(struct AUTH *, XDR *); + /* validate varifier */ + int (*ah_validate)(struct AUTH *, + struct opaque_auth *); + /* refresh credentials */ + int (*ah_refresh)(struct AUTH *, struct rpc_msg *); + /* destroy this structure */ + void (*ah_destroy)(struct AUTH *); + /* encode data for wire */ + int (*ah_wrap)(struct AUTH *, XDR *, + xdrproc_t, caddr_t); + /* decode data from wire */ + int (*ah_unwrap)(struct AUTH *, XDR *, + xdrproc_t, caddr_t); + } *ah_ops; + void *ah_private; +} AUTH; + + +/* + * Authentication ops. + * The ops and the auth handle provide the interface to the authenticators. + * + * AUTH *auth; + * XDR *xdrs; + * struct opaque_auth verf; + */ +#define AUTH_NEXTVERF(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) +#define auth_nextverf(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) + +#define AUTH_MARSHALL(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) +#define auth_marshall(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) + +#define AUTH_VALIDATE(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) +#define auth_validate(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) + +#define AUTH_REFRESH(auth, msg) \ + ((*((auth)->ah_ops->ah_refresh))(auth, msg)) +#define auth_refresh(auth, msg) \ + ((*((auth)->ah_ops->ah_refresh))(auth, msg)) + +#define AUTH_WRAP(auth, xdrs, xfunc, xwhere) \ + ((*((auth)->ah_ops->ah_wrap))(auth, xdrs, \ + xfunc, xwhere)) +#define auth_wrap(auth, xdrs, xfunc, xwhere) \ + ((*((auth)->ah_ops->ah_wrap))(auth, xdrs, \ + xfunc, xwhere)) +#define AUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \ + ((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \ + xfunc, xwhere)) +#define auth_unwrap(auth, xdrs, xfunc, xwhere) \ + ((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \ + xfunc, xwhere)) + +#define AUTH_DESTROY(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) +#define auth_destroy(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) + + +#ifdef GSSRPC__IMPL +/* RENAMED: should be _null_auth if we can use reserved namespace. */ +extern struct opaque_auth gssrpc__null_auth; +#endif + +/* + * These are the various implementations of client side authenticators. + */ + +/* + * Unix style authentication + * AUTH *authunix_create(machname, uid, gid, len, aup_gids) + * char *machname; + * int uid; + * int gid; + * int len; + * int *aup_gids; + */ +extern AUTH *authunix_create(char *machname, int uid, int gid, int len, + int *aup_gids); +extern AUTH *authunix_create_default(void); /* takes no parameters */ +extern AUTH *authnone_create(void); /* takes no parameters */ +extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *); + +#define AUTH_NONE 0 /* no authentication */ +#define AUTH_NULL 0 /* backward compatibility */ +#define AUTH_UNIX 1 /* unix style (uid, gids) */ +#define AUTH_SHORT 2 /* short hand unix style */ +#define AUTH_DES 3 /* des style (encrypted timestamps) */ +#define AUTH_GSSAPI 300001 /* GSS-API style */ +#define RPCSEC_GSS 6 /* RPCSEC_GSS */ + +GSSRPC__END_DECLS + +#endif /* !defined(GSSRPC_AUTH_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/auth_gss.h b/krb5-1.21.3/src/include/gssrpc/auth_gss.h new file mode 100644 index 00000000..9fa87742 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/auth_gss.h @@ -0,0 +1,148 @@ +/* include/gssrpc/auth_gss.h */ +/* + Copyright (c) 2000 The Regents of the University of Michigan. + All rights reserved. + + Copyright (c) 2000 Dug Song . + All rights reserved, all wrongs reversed. + + 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 University 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 ``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 REGENTS 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. + + Id: auth_gss.h,v 1.13 2002/05/08 16:54:33 andros Exp +*/ + +#ifndef GSSRPC_AUTH_GSS_H +#define GSSRPC_AUTH_GSS_H + +#include +#include +#ifdef HAVE_HEIMDAL +#include +#else +#include +#endif + +GSSRPC__BEGIN_DECLS + +/* RPCSEC_GSS control procedures. */ +typedef enum { + RPCSEC_GSS_DATA = 0, + RPCSEC_GSS_INIT = 1, + RPCSEC_GSS_CONTINUE_INIT = 2, + RPCSEC_GSS_DESTROY = 3 +} rpc_gss_proc_t; + +/* RPCSEC_GSS services. */ +typedef enum { + RPCSEC_GSS_SVC_NONE = 1, + RPCSEC_GSS_SVC_INTEGRITY = 2, + RPCSEC_GSS_SVC_PRIVACY = 3 +} rpc_gss_svc_t; + +#define RPCSEC_GSS_VERSION 1 + +/* RPCSEC_GSS security triple. */ +struct rpc_gss_sec { + gss_OID mech; /* mechanism */ + gss_qop_t qop; /* quality of protection */ + rpc_gss_svc_t svc; /* service */ + gss_cred_id_t cred; /* cred handle */ + uint32_t req_flags; /* req flags for init_sec_context */ +}; + +/* Private data required for kernel implementation */ +struct authgss_private_data { + gss_ctx_id_t pd_ctx; /* Session context handle */ + gss_buffer_desc pd_ctx_hndl; /* Credentials context handle */ + uint32_t pd_seq_win; /* Sequence window */ +}; + +/* Krb 5 default mechanism +#define KRB5OID "1.2.840.113554.1.2.2" + +gss_OID_desc krb5oid = { + 20, KRB5OID +}; + */ + +/* +struct rpc_gss_sec krb5mech = { + (gss_OID)&krb5oid, + GSS_QOP_DEFAULT, + RPCSEC_GSS_SVC_NONE +}; +*/ + +/* Credentials. */ +struct rpc_gss_cred { + u_int gc_v; /* version */ + rpc_gss_proc_t gc_proc; /* control procedure */ + uint32_t gc_seq; /* sequence number */ + rpc_gss_svc_t gc_svc; /* service */ + gss_buffer_desc gc_ctx; /* context handle */ +}; + +/* Context creation response. */ +struct rpc_gss_init_res { + gss_buffer_desc gr_ctx; /* context handle */ + uint32_t gr_major; /* major status */ + uint32_t gr_minor; /* minor status */ + uint32_t gr_win; /* sequence window */ + gss_buffer_desc gr_token; /* token */ +}; + +/* Maximum sequence number value. */ +#define MAXSEQ 0x80000000 + +/* Prototypes. */ +bool_t xdr_rpc_gss_buf (XDR *xdrs, gss_buffer_t, u_int maxsize); +bool_t xdr_rpc_gss_cred (XDR *xdrs, struct rpc_gss_cred *p); +bool_t xdr_rpc_gss_init_args (XDR *xdrs, gss_buffer_desc *p); +bool_t xdr_rpc_gss_init_res (XDR *xdrs, struct rpc_gss_init_res *p); +bool_t xdr_rpc_gss_data (XDR *xdrs, xdrproc_t xdr_func, + caddr_t xdr_ptr, gss_ctx_id_t ctx, + gss_qop_t qop, rpc_gss_svc_t svc, + uint32_t seq); +bool_t xdr_rpc_gss_wrap_data (XDR *xdrs, xdrproc_t xdr_func, caddr_t + xdr_ptr, gss_ctx_id_t ctx, gss_qop_t qop, + rpc_gss_svc_t svc, uint32_t seq); +bool_t xdr_rpc_gss_unwrap_data (XDR *xdrs, xdrproc_t xdr_func, caddr_t + xdr_ptr, gss_ctx_id_t ctx, gss_qop_t qop, + rpc_gss_svc_t svc, uint32_t seq); + +AUTH *authgss_create (CLIENT *, gss_name_t, struct rpc_gss_sec *); +AUTH *authgss_create_default (CLIENT *, char *, struct rpc_gss_sec *); +bool_t authgss_service (AUTH *auth, int svc); +bool_t authgss_get_private_data (AUTH *auth, struct authgss_private_data *); + +#ifdef GSSRPC__IMPL +void log_debug (const char *fmt, ...); +void log_status (char *m, OM_uint32 major, OM_uint32 minor); +void log_hexdump (const u_char *buf, int len, int offset); +#endif + +GSSRPC__END_DECLS +#endif /* !defined(GSSRPC_AUTH_GSS_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/auth_gssapi.h b/krb5-1.21.3/src/include/gssrpc/auth_gssapi.h new file mode 100644 index 00000000..9d948532 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/auth_gssapi.h @@ -0,0 +1,162 @@ +/* include/gssrpc/auth_gssapi.h - GSS-API style auth parameters for RPC */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + */ + +#ifndef GSSRPC_AUTH_GSSAPI_H +#define GSSRPC_AUTH_GSSAPI_H + +GSSRPC__BEGIN_DECLS + +#define AUTH_GSSAPI_EXIT 0 +#define AUTH_GSSAPI_INIT 1 +#define AUTH_GSSAPI_CONTINUE_INIT 2 +#define AUTH_GSSAPI_MSG 3 +#define AUTH_GSSAPI_DESTROY 4 + +/* + * Yuck. Some sys/types.h files leak symbols + */ +#ifdef major +#undef major +#endif +#ifdef minor +#undef minor +#endif + +typedef struct _auth_gssapi_name { + char *name; + gss_OID type; +} auth_gssapi_name; + +typedef struct _auth_gssapi_creds { + uint32_t version; + bool_t auth_msg; + gss_buffer_desc client_handle; +} auth_gssapi_creds; + +typedef struct _auth_gssapi_init_arg { + uint32_t version; + gss_buffer_desc token; +} auth_gssapi_init_arg; + +typedef struct _auth_gssapi_init_res { + uint32_t version; + gss_buffer_desc client_handle; + OM_uint32 gss_major, gss_minor; + gss_buffer_desc token; + gss_buffer_desc signed_isn; +} auth_gssapi_init_res; + +typedef void (*auth_gssapi_log_badauth_func) + (OM_uint32 major, + OM_uint32 minor, + struct sockaddr_in *raddr, + caddr_t data); + +/* auth_gssapi_log_badauth_func is IPv4-specific; this version gives the + * transport handle so the fd can be used to get the address. */ +typedef void (*auth_gssapi_log_badauth2_func) + (OM_uint32 major, + OM_uint32 minor, + SVCXPRT *xprt, + caddr_t data); + +typedef void (*auth_gssapi_log_badverf_func) + (gss_name_t client, + gss_name_t server, + struct svc_req *rqst, + struct rpc_msg *msg, + caddr_t data); + +typedef void (*auth_gssapi_log_miscerr_func) + (struct svc_req *rqst, + struct rpc_msg *msg, + char *error, + caddr_t data); + +bool_t xdr_gss_buf(XDR *, gss_buffer_t); +bool_t xdr_authgssapi_creds(XDR *, auth_gssapi_creds *); +bool_t xdr_authgssapi_init_arg(XDR *, auth_gssapi_init_arg *); +bool_t xdr_authgssapi_init_res(XDR *, auth_gssapi_init_res *); + +bool_t auth_gssapi_wrap_data +(OM_uint32 *major, OM_uint32 *minor, + gss_ctx_id_t context, uint32_t seq_num, XDR + *out_xdrs, bool_t (*xdr_func)(), caddr_t + xdr_ptr); +bool_t auth_gssapi_unwrap_data +(OM_uint32 *major, OM_uint32 *minor, + gss_ctx_id_t context, uint32_t seq_num, XDR + *in_xdrs, bool_t (*xdr_func)(), caddr_t + xdr_ptr); + +AUTH *auth_gssapi_create +(CLIENT *clnt, + OM_uint32 *major_status, + OM_uint32 *minor_status, + gss_cred_id_t claimant_cred_handle, + gss_name_t target_name, + gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + gss_OID *actual_mech_type, + OM_uint32 *ret_flags, + OM_uint32 *time_rec); + +AUTH *auth_gssapi_create_default +(CLIENT *clnt, char *service_name); + +void auth_gssapi_display_status +(char *msg, OM_uint32 major, + OM_uint32 minor); + +bool_t auth_gssapi_seal_seq +(gss_ctx_id_t context, uint32_t seq_num, gss_buffer_t out_buf); + +bool_t auth_gssapi_unseal_seq +(gss_ctx_id_t context, gss_buffer_t in_buf, uint32_t *seq_num); + +bool_t svcauth_gssapi_set_names +(auth_gssapi_name *names, int num); +void svcauth_gssapi_unset_names +(void); + +void svcauth_gssapi_set_log_badauth_func +(auth_gssapi_log_badauth_func func, + caddr_t data); +void svcauth_gssapi_set_log_badauth2_func +(auth_gssapi_log_badauth2_func func, + caddr_t data); +void svcauth_gssapi_set_log_badverf_func +(auth_gssapi_log_badverf_func func, + caddr_t data); +void svcauth_gssapi_set_log_miscerr_func +(auth_gssapi_log_miscerr_func func, + caddr_t data); + +void svcauth_gss_set_log_badauth_func(auth_gssapi_log_badauth_func, + caddr_t); +void svcauth_gss_set_log_badauth2_func(auth_gssapi_log_badauth2_func, + caddr_t); +void svcauth_gss_set_log_badverf_func(auth_gssapi_log_badverf_func, + caddr_t); +void svcauth_gss_set_log_miscerr_func(auth_gssapi_log_miscerr_func, + caddr_t data); + +#define GSS_COPY_BUFFER(dest, src) { \ + (dest).length = (src).length; \ + (dest).value = (src).value; } + +#define GSS_DUP_BUFFER(dest, src) { \ + (dest).length = (src).length; \ + (dest).value = (void *) malloc((dest).length); \ + memcpy((dest).value, (src).value, (dest).length); } + +#define GSS_BUFFERS_EQUAL(b1, b2) (((b1).length == (b2).length) && \ + !memcmp((b1).value,(b2).value,(b1.length))) + + +GSSRPC__END_DECLS + +#endif /* !defined(GSSRPC_AUTH_GSSAPI_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/auth_unix.h b/krb5-1.21.3/src/include/gssrpc/auth_unix.h new file mode 100644 index 00000000..6dda1af5 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/auth_unix.h @@ -0,0 +1,82 @@ +/* @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC; from 1.8 88/02/08 SMI */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * 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 the "Oracle America, Inc." 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 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. + */ +/* @(#)auth_unix.h 1.5 86/07/16 SMI */ + +/* + * auth_unix.h, Protocol for UNIX style authentication parameters for RPC + */ + +#ifndef GSSRPC_AUTH_UNIX_H +#define GSSRPC_AUTH_UNIX_H + +GSSRPC__BEGIN_DECLS +/* + * The system is very weak. The client uses no encryption for it + * credentials and only sends null verifiers. The server sends backs + * null verifiers or optionally a verifier that suggests a new short hand + * for the credentials. + */ + +/* The machine name is part of a credential; it may not exceed 255 bytes */ +#define MAX_MACHINE_NAME 255 + +/* gids compose part of a credential; there may not be more than 16 of them */ +#define NGRPS 16 + +/* + * Unix style credentials. + */ +struct authunix_parms { + uint32_t aup_time; + char *aup_machname; + int aup_uid; + int aup_gid; + u_int aup_len; + int *aup_gids; +}; + +extern bool_t xdr_authunix_parms(XDR *, struct authunix_parms *); + +/* + * If a response verifier has flavor AUTH_SHORT, + * then the body of the response verifier encapsulates the following structure; + * again it is serialized in the obvious fashion. + */ +struct short_hand_verf { + struct opaque_auth new_cred; +}; + +GSSRPC__END_DECLS + +#endif /* !defined(GSSRPC_AUTH_UNIX_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/clnt.h b/krb5-1.21.3/src/include/gssrpc/clnt.h new file mode 100644 index 00000000..e5af80d4 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/clnt.h @@ -0,0 +1,346 @@ +/* @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * 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 the "Oracle America, Inc." 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 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. + */ + +/* + * clnt.h - Client side remote procedure call interface. + */ + +#ifndef GSSRPC_CLNT_H +#define GSSRPC_CLNT_H + +GSSRPC__BEGIN_DECLS +/* + * Rpc calls return an enum clnt_stat. This should be looked at more, + * since each implementation is required to live with this (implementation + * independent) list of errors. + */ +enum clnt_stat { + RPC_SUCCESS=0, /* call succeeded */ + /* + * local errors + */ + RPC_CANTENCODEARGS=1, /* can't encode arguments */ + RPC_CANTDECODERES=2, /* can't decode results */ + RPC_CANTSEND=3, /* failure in sending call */ + RPC_CANTRECV=4, /* failure in receiving result */ + RPC_TIMEDOUT=5, /* call timed out */ + /* + * remote errors + */ + RPC_VERSMISMATCH=6, /* rpc versions not compatible */ + RPC_AUTHERROR=7, /* authentication error */ + RPC_PROGUNAVAIL=8, /* program not available */ + RPC_PROGVERSMISMATCH=9, /* program version mismatched */ + RPC_PROCUNAVAIL=10, /* procedure unavailable */ + RPC_CANTDECODEARGS=11, /* decode arguments error */ + RPC_SYSTEMERROR=12, /* generic "other problem" */ + + /* + * callrpc & clnt_create errors + */ + RPC_UNKNOWNHOST=13, /* unknown host name */ + RPC_UNKNOWNPROTO=17, /* unknown protocol */ + + /* + * _ create errors + */ + RPC_PMAPFAILURE=14, /* the pmapper failed in its call */ + RPC_PROGNOTREGISTERED=15, /* remote program is not registered */ + /* + * unspecified error + */ + RPC_FAILED=16 +}; + + +/* + * Error info. + */ +struct rpc_err { + enum clnt_stat re_status; + union { + int RE_errno; /* realated system error */ + enum auth_stat RE_why; /* why the auth error occurred */ + struct { + rpcvers_t low; /* lowest version supported */ + rpcvers_t high; /* highest version supported */ + } RE_vers; + struct { /* maybe meaningful if RPC_FAILED */ + int32_t s1; + int32_t s2; + } RE_lb; /* life boot & debugging only */ + } ru; +#define re_errno ru.RE_errno +#define re_why ru.RE_why +#define re_vers ru.RE_vers +#define re_lb ru.RE_lb +}; + + +/* + * Client rpc handle. + * Created by individual implementations, see e.g. rpc_udp.c. + * Client is responsible for initializing auth, see e.g. auth_none.c. + */ +typedef struct CLIENT { + AUTH *cl_auth; /* authenticator */ + struct clnt_ops { + /* call remote procedure */ + enum clnt_stat (*cl_call)(struct CLIENT *, + rpcproc_t, xdrproc_t, void *, + xdrproc_t, void *, + struct timeval); + /* abort a call */ + void (*cl_abort)(struct CLIENT *); + /* get specific error code */ + void (*cl_geterr)(struct CLIENT *, + struct rpc_err *); + /* frees results */ + bool_t (*cl_freeres)(struct CLIENT *, + xdrproc_t, void *); + /* destroy this structure */ + void (*cl_destroy)(struct CLIENT *); + /* the ioctl() of rpc */ + /* XXX CITI makes 2nd arg take u_int */ + bool_t (*cl_control)(struct CLIENT *, int, + void *); + } *cl_ops; + void *cl_private; /* private stuff */ +} CLIENT; + + +/* + * client side rpc interface ops + * + * Parameter types are: + * + */ + +/* + * enum clnt_stat + * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) + * CLIENT *rh; + * rpcproc_t proc; + * xdrproc_t xargs; + * caddr_t argsp; + * xdrproc_t xres; + * caddr_t resp; + * struct timeval timeout; + */ +#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) +#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) + +/* + * void + * CLNT_ABORT(rh); + * CLIENT *rh; + */ +#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh)) +#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh)) + +/* + * struct rpc_err + * CLNT_GETERR(rh); + * CLIENT *rh; + */ +#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) +#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) + + +/* + * bool_t + * CLNT_FREERES(rh, xres, resp); + * CLIENT *rh; + * xdrproc_t xres; + * caddr_t resp; + */ +#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) +#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) + +/* + * bool_t + * CLNT_CONTROL(cl, request, info) + * CLIENT *cl; + * u_int request; + * char *info; + */ +#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) +#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) + +/* + * control operations that apply to both udp and tcp transports + */ +#define CLSET_TIMEOUT 1 /* set timeout (timeval) */ +#define CLGET_TIMEOUT 2 /* get timeout (timeval) */ +#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */ +/* + * udp only control operations + */ +#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */ +#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */ +/* + * new control operations + */ +#define CLGET_LOCAL_ADDR 6 /* get local address (sockaddr, getsockname)*/ + +/* + * void + * CLNT_DESTROY(rh); + * CLIENT *rh; + */ +#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) +#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) + + +/* + * RPCTEST is a test program which is accessible on every rpc + * transport/port. It is used for testing, performance evaluation, + * and network administration. + */ + +#define RPCTEST_PROGRAM ((rpcprog_t)1) +#define RPCTEST_VERSION ((rpcvers_t)1) +#define RPCTEST_NULL_PROC ((rpcproc_t)2) +#define RPCTEST_NULL_BATCH_PROC ((rpcproc_t)3) + +/* + * By convention, procedure 0 takes null arguments and returns them + */ + +#define NULLPROC ((rpcproc_t)0) + +/* + * Below are the client handle creation routines for the various + * implementations of client side rpc. They can return NULL if a + * creation failure occurs. + */ + +/* + * Memory based rpc (for speed check and testing) + * CLIENT * + * clntraw_create(prog, vers) + * rpcprog_t prog; + * rpcvers_t vers; + */ +extern CLIENT *clntraw_create(rpcprog_t, rpcvers_t); + +/* + * Generic client creation routine. Supported protocols are "udp" and "tcp" + */ +extern CLIENT *clnt_create(char *, rpcprog_t, rpcvers_t, char *); + + +/* + * TCP based rpc + * CLIENT * + * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * rpcprog_t prog; + * rpcvers_t version; + * int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clnttcp_create(struct sockaddr_in *, rpcprog_t, rpcvers_t, + int *, u_int, u_int); + +/* + * UDP based rpc. + * CLIENT * + * clntudp_create(raddr, program, version, wait, sockp) + * struct sockaddr_in *raddr; + * rpcprog_t program; + * rpcvers_t version; + * struct timeval wait; + * int *sockp; + * + * Same as above, but you specify max packet sizes. + * CLIENT * + * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * rpcprog_t program; + * rpcvers_t version; + * struct timeval wait; + * int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clntudp_create(struct sockaddr_in *, rpcprog_t, + rpcvers_t, struct timeval, int *); +extern CLIENT *clntudp_bufcreate(struct sockaddr_in *, rpcprog_t, + rpcvers_t, struct timeval, int *, + u_int, u_int); + +/* + * Print why creation failed + */ +void clnt_pcreateerror(char *); /* stderr */ +char *clnt_spcreateerror(char *); /* string */ + +/* + * Like clnt_perror(), but is more verbose in its output + */ +void clnt_perrno(enum clnt_stat); /* stderr */ + +/* + * Print an English error message, given the client error code + */ +void clnt_perror(CLIENT *, char *); /* stderr */ +char *clnt_sperror(CLIENT *, char *); /* string */ + +/* + * If a creation fails, the following allows the user to figure out why. + */ +struct rpc_createerr { + enum clnt_stat cf_stat; + struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */ +}; + +extern struct rpc_createerr rpc_createerr; + + + +/* + * Copy error message to buffer. + */ +char *clnt_sperrno(enum clnt_stat num); /* string */ + +#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */ +#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */ + +GSSRPC__END_DECLS + +#endif /* !defined(GSSRPC_CLNT_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/netdb.h b/krb5-1.21.3/src/include/gssrpc/netdb.h new file mode 100644 index 00000000..f933fbb7 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/netdb.h @@ -0,0 +1,58 @@ +/* include/gssrpc/netdb.h */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * 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 the "Oracle America, Inc." 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 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. + */ + +/* @(#)netdb.h 2.1 88/07/29 3.9 RPCSRC */ +/* @(#)rpc.h 1.8 87/07/24 SMI */ + +#ifndef RPC_NETDB_H +#define RPC_NETDB_H + +#include +/* since the gssrpc library requires that any application using it be +built with these header files, I am making the decision that any app +which uses the rpcent routines must use this header file, or something +compatible (which most are) --marc */ + +/* Really belongs in */ +#ifdef STRUCT_RPCENT_IN_RPC_NETDB_H +struct rpcent { + char *r_name; /* name of server for this rpc program */ + char **r_aliases; /* alias list */ + int r_number; /* rpc program number */ +}; +#endif /*STRUCT_RPCENT_IN_RPC_NETDB_H*/ + +struct rpcent *getrpcbyname(), *getrpcbynumber(), *getrpcent(); + +#endif diff --git a/krb5-1.21.3/src/include/gssrpc/pmap_clnt.h b/krb5-1.21.3/src/include/gssrpc/pmap_clnt.h new file mode 100644 index 00000000..993bce27 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/pmap_clnt.h @@ -0,0 +1,83 @@ +/* @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.11 88/02/08 SMI */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * 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 the "Oracle America, Inc." 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 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. + */ + +/* + * pmap_clnt.h + * Supplies C routines to get to portmap services. + */ + +#ifndef GSSRPC_PMAP_CLNT_H +#define GSSRPC_PMAP_CLNT_H + +/* + * Usage: + * success = pmap_set(program, version, protocol, port); + * success = pmap_unset(program, version); + * port = pmap_getport(address, program, version, protocol); + * head = pmap_getmaps(address); + * clnt_stat = pmap_rmtcall(address, program, version, procedure, + * xdrargs, argsp, xdrres, resp, tout, port_ptr) + * (works for udp only.) + * clnt_stat = clnt_broadcast(program, version, procedure, + * xdrargs, argsp, xdrres, resp, eachresult) + * (like pmap_rmtcall, except the call is broadcasted to all + * locally connected nets. For each valid response received, + * the procedure eachresult is called. Its form is: + * done = eachresult(resp, raddr) + * bool_t done; + * caddr_t resp; + * struct sockaddr_in raddr; + * where resp points to the results of the call and raddr is the + * address if the responder to the broadcast. + */ + +GSSRPC__BEGIN_DECLS +extern bool_t pmap_set(rpcprog_t, rpcvers_t, rpcprot_t, u_int); +extern bool_t pmap_unset(rpcprog_t, rpcvers_t); +extern struct pmaplist *pmap_getmaps(struct sockaddr_in *); +enum clnt_stat pmap_rmtcall(struct sockaddr_in *, rpcprog_t, + rpcvers_t, rpcproc_t, xdrproc_t, + caddr_t, xdrproc_t, caddr_t, + struct timeval, rpcport_t *); + +typedef bool_t (*resultproc_t)(caddr_t, struct sockaddr_in *); + +enum clnt_stat clnt_broadcast(rpcprog_t, rpcvers_t, rpcproc_t, + xdrproc_t, caddr_t, xdrproc_t, + caddr_t, resultproc_t); +extern u_short pmap_getport(struct sockaddr_in *, + rpcprog_t, + rpcvers_t, rpcprot_t); +GSSRPC__END_DECLS +#endif /* !defined(GSSRPC_PMAP_CLNT_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/pmap_prot.h b/krb5-1.21.3/src/include/gssrpc/pmap_prot.h new file mode 100644 index 00000000..0e35d6b9 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/pmap_prot.h @@ -0,0 +1,103 @@ +/* @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC; from 1.14 88/02/08 SMI */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * 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 the "Oracle America, Inc." 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 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. + */ + +/* + * pmap_prot.h + * Protocol for the local binder service, or pmap. + * + * The following procedures are supported by the protocol: + * + * PMAPPROC_NULL() returns () + * takes nothing, returns nothing + * + * PMAPPROC_SET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Registers the tuple + * [prog, vers, prot, port]. + * + * PMAPPROC_UNSET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Un-registers pair + * [prog, vers]. prot and port are ignored. + * + * PMAPPROC_GETPORT(struct pmap) returns (u_short). + * 0 is failure. Otherwise returns the port number where the pair + * [prog, vers] is registered. It may lie! + * + * PMAPPROC_DUMP() RETURNS (struct pmaplist *) + * + * PMAPPROC_CALLIT(rpcprog_t, rpcvers_t, rpcproc_t, string<>) + * RETURNS (port, string<>); + * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs); + * Calls the procedure on the local machine. If it is not registered, + * this procedure is quite; ie it does not return error information!!! + * This procedure only is supported on rpc/udp and calls via + * rpc/udp. This routine only passes null authentication parameters. + * This file has no interface to xdr routines for PMAPPROC_CALLIT. + * + * The service supports remote procedure calls on udp/ip or tcp/ip socket 111. + */ + +#ifndef GSSRPC_PMAP_PROT_H +#define GSSRPC_PMAP_PROT_H +GSSRPC__BEGIN_DECLS + +#define PMAPPORT ((u_short)111) +#define PMAPPROG ((rpcprog_t)100000) +#define PMAPVERS ((rpcvers_t)2) +#define PMAPVERS_PROTO ((rpcprot_t)2) +#define PMAPVERS_ORIG ((rpcvers_t)1) +#define PMAPPROC_NULL ((rpcproc_t)0) +#define PMAPPROC_SET ((rpcproc_t)1) +#define PMAPPROC_UNSET ((rpcproc_t)2) +#define PMAPPROC_GETPORT ((rpcproc_t)3) +#define PMAPPROC_DUMP ((rpcproc_t)4) +#define PMAPPROC_CALLIT ((rpcproc_t)5) + +struct pmap { + rpcprog_t pm_prog; + rpcvers_t pm_vers; + rpcprot_t pm_prot; + rpcport_t pm_port; +}; + +extern bool_t xdr_pmap(XDR *, struct pmap *); + +struct pmaplist { + struct pmap pml_map; + struct pmaplist *pml_next; +}; + +extern bool_t xdr_pmaplist(XDR *, struct pmaplist **); + +GSSRPC__END_DECLS +#endif /* !defined(GSSRPC_PMAP_PROT_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/pmap_rmt.h b/krb5-1.21.3/src/include/gssrpc/pmap_rmt.h new file mode 100644 index 00000000..e978a8ee --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/pmap_rmt.h @@ -0,0 +1,65 @@ +/* @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC; from 1.2 88/02/08 SMI */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * 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 the "Oracle America, Inc." 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 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. + */ + +/* + * Structures and XDR routines for parameters to and replies from + * the portmapper remote-call-service. + */ + +#ifndef GSSRPC_PMAP_RMT_H +#define GSSRPC_PMAP_RMT_H +GSSRPC__BEGIN_DECLS + +struct rmtcallargs { + rpcprog_t prog; + rpcvers_t vers; + rpcproc_t proc; + uint32_t arglen; + caddr_t args_ptr; + xdrproc_t xdr_args; +}; + +bool_t xdr_rmtcall_args(XDR *, struct rmtcallargs *); + +struct rmtcallres { + rpcport_t *port_ptr; + uint32_t resultslen; + caddr_t results_ptr; + xdrproc_t xdr_results; +}; + +bool_t xdr_rmtcallres(XDR *, struct rmtcallres *); + +GSSRPC__END_DECLS +#endif /* !defined(GSSRPC_PMAP_RMT_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/rename.h b/krb5-1.21.3/src/include/gssrpc/rename.h new file mode 100644 index 00000000..d67502fe --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/rename.h @@ -0,0 +1,280 @@ +/* include/gssrpc/rename.h */ +/* + * Copyright (C) 2004 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * Namespace mangling for various purposes. + * + * Symbols in the object code need to be renamed to not conflict with + * an OS-provided RPC implementation. Without renaming, the conflicts + * can cause problems with things like RPC-enabled NSS + * implementations. + * + * Symbols in headers should not conflict with implementation-reserved + * namespace (prefixes "_[A-Z_]" for any purpose; prefix "_" + * for file scope identifiers and tag names), or unnecessarily impinge + * on user namespace. + * + * The renaming of the header directory is done to avoid problems when + * the OS header files include and might get ours instead. + * OS vendors should replace all the inclusions with + * inclusions, as appropriate. Additionally, vendors + * should probably put some symbols into the implementation namespace. + * + * For example, inclusion protection should change from "GSSRPC_*_H" + * to "_RPC_*_H", struct tags should get "__" prefixes, etc. + * + * This implementation reserves the object code prefix "gssrpc_". + * External names in the RPC API not beginning with "_" get renamed + * with the prefix "gssrpc_" via #define, e.g., "foo" -> "gssrpc_foo". + * External names in the RPC API beginning with "_" get textually + * rewritten. + */ + +#ifndef GSSRPC_RENAME_H +#define GSSRPC_RENAME_H + +/* auth.h */ + +#define xdr_des_block gssrpc_xdr_des_block + +#define authunix_create gssrpc_authunix_create +#define authunix_create_default gssrpc_authunix_create_default +#define authnone_create gssrpc_authnone_create +#define xdr_opaque_auth gssrpc_xdr_opaque_auth + +/* auth_gss.c */ + +#define auth_debug_gss gssrpc_auth_debug_gss +#define misc_debug_gss gssrpc_misc_debug_gss + +/* auth_gss.h */ + +#define xdr_rpc_gss_buf gssrpc_xdr_rpc_gss_buf +#define xdr_rpc_gss_cred gssrpc_xdr_rpc_gss_cred +#define xdr_rpc_gss_init_args gssrpc_xdr_rpc_gss_init_args +#define xdr_rpc_gss_init_res gssrpc_xdr_rpc_gss_init_res +#define xdr_rpc_gss_data gssrpc_xdr_rpc_gss_data +#define xdr_rpc_gss_wrap_data gssrpc_xdr_rpc_gss_wrap_data +#define xdr_rpc_gss_unwrap_data gssrpc_xdr_rpc_gss_unwrap_data + +#define authgss_create gssrpc_authgss_create +#define authgss_create_default gssrpc_authgss_create_default +#define authgss_get_private_data gssrpc_authgss_get_private_data +#define authgss_service gssrpc_authgss_service + +#ifdef GSSRPC__IMPL +#define log_debug gssrpc_log_debug +#define log_status gssrpc_log_status +#define log_hexdump gssrpc_log_hexdump +#endif + +/* auth_gssapi.c */ + +#define auth_debug_gssapi gssrpc_auth_debug_gssapi +#define misc_debug_gssapi gssrpc_misc_debug_gssapi + +/* auth_gssapi.h */ + +#define xdr_gss_buf gssrpc_xdr_gss_buf +#define xdr_authgssapi_creds gssrpc_xdr_authgssapi_creds +#define xdr_authgssapi_init_arg gssrpc_xdr_authgssapi_init_arg +#define xdr_authgssapi_init_res gssrpc_xdr_authgssapi_init_res + +#define auth_gssapi_wrap_data gssrpc_auth_gssapi_wrap_data +#define auth_gssapi_unwrap_data gssrpc_auth_gssapi_unwrap_data +#define auth_gssapi_create gssrpc_auth_gssapi_create +#define auth_gssapi_create_default gssrpc_auth_gssapi_create_default +#define auth_gssapi_display_status gssrpc_auth_gssapi_display_status +#define auth_gssapi_seal_seq gssrpc_auth_gssapi_seal_seq +#define auth_gssapi_unseal_seq gssrpc_auth_gssapi_unseal_seq + +#define svcauth_gssapi_set_names gssrpc_svcauth_gssapi_set_names +#define svcauth_gssapi_unset_names gssrpc_svcauth_gssapi_unset_names +#define svcauth_gssapi_set_log_badauth_func gssrpc_svcauth_gssapi_set_log_badauth_func +#define svcauth_gssapi_set_log_badauth2_func gssrpc_svcauth_gssapi_set_log_badauth2_func +#define svcauth_gssapi_set_log_badverf_func gssrpc_svcauth_gssapi_set_log_badverf_func +#define svcauth_gssapi_set_log_miscerr_func gssrpc_svcauth_gssapi_set_log_miscerr_func + +#define svcauth_gss_set_log_badauth_func gssrpc_svcauth_gss_set_log_badauth_func +#define svcauth_gss_set_log_badauth2_func gssrpc_svcauth_gss_set_log_badauth2_func +#define svcauth_gss_set_log_badverf_func gssrpc_svcauth_gss_set_log_badverf_func +#define svcauth_gss_set_log_miscerr_func gssrpc_svcauth_gss_set_log_miscerr_func + +/* auth_unix.h */ + +#define xdr_authunix_parms gssrpc_xdr_authunix_parms + +/* clnt.h */ + +#define clntraw_create gssrpc_clntraw_create +#define clnt_create gssrpc_clnt_create +#define clnttcp_create gssrpc_clnttcp_create +#define clntudp_create gssrpc_clntudp_create +#define clntudp_bufcreate gssrpc_clntudp_bufcreate +#define clnt_pcreateerror gssrpc_clnt_pcreateerror +#define clnt_spcreateerror gssrpc_clnt_spcreateerror +#define clnt_perrno gssrpc_clnt_perrno +#define clnt_perror gssrpc_clnt_perror +#define clnt_sperror gssrpc_clnt_sperror +/* XXX do we need to rename the struct? */ +#define rpc_createerr gssrpc_rpc_createrr +#define clnt_sperrno gssrpc_clnt_sperrno + +/* pmap_clnt.h */ + +#define pmap_set gssrpc_pmap_set +#define pmap_unset gssrpc_pmap_unset +#define pmap_getmaps gssrpc_pmap_getmaps +#define pmap_rmtcall gssrpc_pmap_rmtcall +#define clnt_broadcast gssrpc_clnt_broadcast +#define pmap_getport gssrpc_pmap_getport + +/* pmap_prot.h */ + +#define xdr_pmap gssrpc_xdr_pmap +#define xdr_pmaplist gssrpc_xdr_pmaplist + +/* pmap_rmt.h */ + +#define xdr_rmtcall_args gssrpc_xdr_rmtcall_args +#define xdr_rmtcallres gssrpc_xdr_rmtcallres + +/* rpc.h */ + +#define get_myaddress gssrpc_get_myaddress +#define bindresvport gssrpc_bindresvport +#define bindresvport_sa gssrpc_bindresvport_sa +#define callrpc gssrpc_callrpc +#define getrpcport gssrpc_getrpcport + +/* rpc_msg.h */ + +#define xdr_callmsg gssrpc_xdr_callmsg +#define xdr_callhdr gssrpc_xdr_callhdr +#define xdr_replymsg gssrpc_xdr_replymsg +#define xdr_accepted_reply gssrpc_xdr_accepted_reply +#define xdr_rejected_reply gssrpc_xdr_rejected_reply + +/* svc.h */ + +#define svc_register gssrpc_svc_register +#define registerrpc gssrpc_registerrpc +#define svc_unregister gssrpc_svc_unregister +#define xprt_register gssrpc_xprt_register +#define xprt_unregister gssrpc_xprt_unregister + +#define svc_sendreply gssrpc_svc_sendreply +#define svcerr_decode gssrpc_svcerr_decode +#define svcerr_weakauth gssrpc_svcerr_weakauth +#define svcerr_noproc gssrpc_svcerr_noproc +#define svcerr_progvers gssrpc_svcerr_progvers +#define svcerr_auth gssrpc_svcerr_auth +#define svcerr_noprog gssrpc_svcerr_noprog +#define svcerr_systemerr gssrpc_svcerr_systemerr + +#define svc_maxfd gssrpc_svc_maxfd +#define svc_fdset gssrpc_svc_fdset +#define svc_fds gssrpc_svc_fds + +#define svc_getreq gssrpc_svc_getreq +#define svc_getreqset gssrpc_svc_getreqset +#define svc_run gssrpc_svc_run + +#define svcraw_create gssrpc_svcraw_create + +#define svcudp_create gssrpc_svcudp_create +#define svcudp_bufcreate gssrpc_svcudp_bufcreate +#define svcudp_enablecache gssrpc_svcudp_enablecache + +#define svctcp_create gssrpc_svctcp_create + +#define svcfd_create gssrpc_svcfd_create + +/* svc_auth.h */ + +#define svc_auth_none_ops gssrpc_svc_auth_none_ops +#define svc_auth_gssapi_ops gssrpc_svc_auth_gssapi_ops +#define svc_auth_gss_ops gssrpc_svc_auth_gss_ops + +#define svcauth_gss_set_svc_name gssrpc_svcauth_gss_set_svc_name +#define svcauth_gss_get_principal gssrpc_svcauth_gss_get_principal + +/* svc_auth_gss.c */ + +#define svc_debug_gss gssrpc_svc_debug_gss + +/* svc_auth_gssapi.c */ + +#define svc_debug_gssapi gssrpc_svc_debug_gssapi + +/* svc_auth_none.c */ + +#define svc_auth_none gssrpc_svc_auth_none + +/* xdr.h */ + +#define xdr_void gssrpc_xdr_void +#define xdr_int gssrpc_xdr_int +#define xdr_u_int gssrpc_xdr_u_int +#define xdr_long gssrpc_xdr_long +#define xdr_u_long gssrpc_xdr_u_long +#define xdr_short gssrpc_xdr_short +#define xdr_u_short gssrpc_xdr_u_short +#define xdr_bool gssrpc_xdr_bool +#define xdr_enum gssrpc_xdr_enum +#define xdr_array gssrpc_xdr_array +#define xdr_bytes gssrpc_xdr_bytes +#define xdr_opaque gssrpc_xdr_opaque +#define xdr_string gssrpc_xdr_string +#define xdr_union gssrpc_xdr_union +#define xdr_char gssrpc_xdr_char +#define xdr_u_char gssrpc_xdr_u_char +#define xdr_vector gssrpc_xdr_vector +#define xdr_float gssrpc_xdr_float +#define xdr_double gssrpc_xdr_double +#define xdr_reference gssrpc_xdr_reference +#define xdr_pointer gssrpc_xdr_pointer +#define xdr_wrapstring gssrpc_xdr_wrapstring +#define xdr_free gssrpc_xdr_free + +#define xdr_sizeof gssrpc_xdr_sizeof + +#define xdr_netobj gssrpc_xdr_netobj +#define xdr_int32 gssrpc_xdr_int32 +#define xdr_u_int32 gssrpc_xdr_u_int32 + +#define xdralloc_create gssrpc_xdralloc_create +#define xdralloc_release gssrpc_xdralloc_release +#define xdralloc_getdata gssrpc_xdralloc_getdata + +#define xdrmem_create gssrpc_xdrmem_create +#define xdrstdio_create gssrpc_xdrstdio_create +#define xdrrec_create gssrpc_xdrrec_create +#define xdrrec_endofrecord gssrpc_xdrrec_endofrecord +#define xdrrec_skiprecord gssrpc_xdrrec_skiprecord +#define xdrrec_eof gssrpc_xdrrec_eof + +#endif /* !defined(GSSRPC_RENAME_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/rpc.h b/krb5-1.21.3/src/include/gssrpc/rpc.h new file mode 100644 index 00000000..78727c49 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/rpc.h @@ -0,0 +1,77 @@ +/* @(#)rpc.h 2.3 88/08/10 4.0 RPCSRC; from 1.9 88/02/08 SMI */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * 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 the "Oracle America, Inc." 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 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. + */ + +/* + * rpc.h, Just includes the billions of rpc header files necessary to + * do remote procedure calling. + */ +#ifndef GSSRPC_RPC_H +#define GSSRPC_RPC_H + +#include /* some typedefs */ +#include + +/* external data representation interfaces */ +#include /* generic (de)serializer */ + +/* Client side only authentication */ +#include /* generic authenticator (client side) */ + +/* Client side (mostly) remote procedure call */ +#include /* generic rpc stuff */ + +/* semi-private protocol headers */ +#include /* protocol for rpc messages */ +#include /* protocol for unix style cred */ +#include /* RPCSEC_GSS */ + +/* Server side only remote procedure callee */ +#include /* service side authenticator */ +#include /* service manager and multiplexer */ + +/* + * get the local host's IP address without consulting + * name service library functions + */ +GSSRPC__BEGIN_DECLS +extern int get_myaddress(struct sockaddr_in *); +extern int bindresvport(int, struct sockaddr_in *); +extern int bindresvport_sa(int, struct sockaddr *); +extern int callrpc(char *, rpcprog_t, rpcvers_t, rpcproc_t, xdrproc_t, + char *, xdrproc_t , char *); +extern int getrpcport(char *, rpcprog_t, rpcvers_t, rpcprot_t); +extern int gssrpc__rpc_dtablesize(void); +GSSRPC__END_DECLS + +#endif /* !defined(GSSRPC_RPC_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/rpc_msg.h b/krb5-1.21.3/src/include/gssrpc/rpc_msg.h new file mode 100644 index 00000000..9403bfc1 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/rpc_msg.h @@ -0,0 +1,207 @@ +/* @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * 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 the "Oracle America, Inc." 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 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. + */ +/* @(#)rpc_msg.h 1.7 86/07/16 SMI */ + +/* + * rpc_msg.h + * rpc message definition + */ + +#ifndef GSSRPC_RPC_MSG_H +#define GSSRPC_RPC_MSG_H + +GSSRPC__BEGIN_DECLS + +#define RPC_MSG_VERSION ((uint32_t) 2) +#define RPC_SERVICE_PORT ((u_short) 2048) + +/* + * Bottom up definition of an rpc message. + * NOTE: call and reply use the same overall struct but + * different parts of unions within it. + */ + +enum msg_type { + CALL=0, + REPLY=1 +}; + +enum reply_stat { + MSG_ACCEPTED=0, + MSG_DENIED=1 +}; + +enum accept_stat { + SUCCESS=0, + PROG_UNAVAIL=1, + PROG_MISMATCH=2, + PROC_UNAVAIL=3, + GARBAGE_ARGS=4, + SYSTEM_ERR=5 +}; + +enum reject_stat { + RPC_MISMATCH=0, + AUTH_ERROR=1 +}; + +/* + * Reply part of an rpc exchange + */ + +/* + * Reply to an rpc request that was accepted by the server. + * Note: there could be an error even though the request was + * accepted. + */ +struct accepted_reply { + struct opaque_auth ar_verf; + enum accept_stat ar_stat; + union { + struct { + rpcvers_t low; + rpcvers_t high; + } AR_versions; + struct { + caddr_t where; + xdrproc_t proc; + } AR_results; + /* and many other null cases */ + } ru; +#define ar_results ru.AR_results +#define ar_vers ru.AR_versions +}; + +/* + * Reply to an rpc request that was rejected by the server. + */ +struct rejected_reply { + enum reject_stat rj_stat; + union { + struct { + rpcvers_t low; + rpcvers_t high; + } RJ_versions; + enum auth_stat RJ_why; /* why authentication did not work */ + } ru; +#define rj_vers ru.RJ_versions +#define rj_why ru.RJ_why +}; + +/* + * Body of a reply to an rpc request. + */ +struct reply_body { + enum reply_stat rp_stat; + union { + struct accepted_reply RP_ar; + struct rejected_reply RP_dr; + } ru; +#define rp_acpt ru.RP_ar +#define rp_rjct ru.RP_dr +}; + +/* + * Body of an rpc request call. + */ +struct call_body { + rpcvers_t cb_rpcvers; /* must be equal to two */ + rpcprog_t cb_prog; + rpcvers_t cb_vers; + rpcproc_t cb_proc; + struct opaque_auth cb_cred; + struct opaque_auth cb_verf; /* protocol specific - provided by client */ +}; + +/* + * The rpc message + */ +struct rpc_msg { + uint32_t rm_xid; + enum msg_type rm_direction; + union { + struct call_body RM_cmb; + struct reply_body RM_rmb; + } ru; +#define rm_call ru.RM_cmb +#define rm_reply ru.RM_rmb +}; +#define acpted_rply ru.RM_rmb.ru.RP_ar +#define rjcted_rply ru.RM_rmb.ru.RP_dr + + +/* + * XDR routine to handle a rpc message. + * xdr_callmsg(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callmsg(XDR *, struct rpc_msg *); + +/* + * XDR routine to pre-serialize the static part of a rpc message. + * xdr_callhdr(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callhdr(XDR *, struct rpc_msg *); + +/* + * XDR routine to handle a rpc reply. + * xdr_replymsg(xdrs, rmsg) + * XDR *xdrs; + * struct rpc_msg *rmsg; + */ +extern bool_t xdr_replymsg(XDR *, struct rpc_msg *); + +/* + * Fills in the error part of a reply message. + * _seterr_reply(msg, error) + * struct rpc_msg *msg; + * struct rpc_err *error; + */ +/* + * RENAMED: should be _seterr_reply or __seterr_reply if we can use + * reserved namespace. + */ +extern void gssrpc__seterr_reply(struct rpc_msg *, struct rpc_err *); + +/* XDR the MSG_ACCEPTED part of a reply message union */ +extern bool_t xdr_accepted_reply(XDR *, struct accepted_reply *); + +/* XDR the MSG_DENIED part of a reply message union */ +extern bool_t xdr_rejected_reply(XDR *, struct rejected_reply *); +GSSRPC__END_DECLS + +#endif /* !defined(GSSRPC_RPC_MSG_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/svc.h b/krb5-1.21.3/src/include/gssrpc/svc.h new file mode 100644 index 00000000..6ef52b95 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/svc.h @@ -0,0 +1,336 @@ +/* @(#)svc.h 2.2 88/07/29 4.0 RPCSRC; from 1.20 88/02/08 SMI */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * 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 the "Oracle America, Inc." 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 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. + */ + +/* + * svc.h, Server-side remote procedure call interface. + */ + +#ifndef GSSRPC_SVC_H +#define GSSRPC_SVC_H + +#include + +GSSRPC__BEGIN_DECLS +/* + * This interface must manage two items concerning remote procedure calling: + * + * 1) An arbitrary number of transport connections upon which rpc requests + * are received. The two most notable transports are TCP and UDP; they are + * created and registered by routines in svc_tcp.c and svc_udp.c, respectively; + * they in turn call xprt_register and xprt_unregister. + * + * 2) An arbitrary number of locally registered services. Services are + * described by the following four data: program number, version number, + * "service dispatch" function, a transport handle, and a boolean that + * indicates whether or not the exported program should be registered with a + * local binder service; if true the program's number and version and the + * port number from the transport handle are registered with the binder. + * These data are registered with the rpc svc system via svc_register. + * + * A service's dispatch function is called whenever an rpc request comes in + * on a transport. The request's program and version numbers must match + * those of the registered service. The dispatch function is passed two + * parameters, struct svc_req * and SVCXPRT *, defined below. + */ + +enum xprt_stat { + XPRT_DIED, + XPRT_MOREREQS, + XPRT_IDLE +}; + +/* + * Server side transport handle + */ +typedef struct SVCXPRT { +#ifdef _WIN32 + SOCKET xp_sock; +#else + int xp_sock; +#endif + u_short xp_port; /* associated port number */ + struct xp_ops { + /* receive incoming requests */ + bool_t (*xp_recv)(struct SVCXPRT *, struct rpc_msg *); + /* get transport status */ + enum xprt_stat (*xp_stat)(struct SVCXPRT *); + /* get arguments */ + bool_t (*xp_getargs)(struct SVCXPRT *, xdrproc_t, + void *); + /* send reply */ + bool_t (*xp_reply)(struct SVCXPRT *, + struct rpc_msg *); + /* free mem allocated for args */ + bool_t (*xp_freeargs)(struct SVCXPRT *, xdrproc_t, + void *); + /* destroy this struct */ + void (*xp_destroy)(struct SVCXPRT *); + } *xp_ops; + int xp_addrlen; /* length of remote address */ + struct sockaddr_in xp_raddr; /* remote address */ + struct opaque_auth xp_verf; /* raw response verifier */ + SVCAUTH *xp_auth; /* auth flavor of current req */ + void *xp_p1; /* private */ + void *xp_p2; /* private */ + int xp_laddrlen; /* length of local address */ + struct sockaddr_in xp_laddr; /* local address */ +} SVCXPRT; + +/* + * Approved way of getting address of caller + */ +#define svc_getcaller(x) (&(x)->xp_raddr) + +/* + * Operations defined on an SVCXPRT handle + * + * SVCXPRT *xprt; + * struct rpc_msg *msg; + * xdrproc_t xargs; + * caddr_t argsp; + */ +#define SVC_RECV(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) +#define svc_recv(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) + +#define SVC_STAT(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) +#define svc_stat(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) + +#define SVC_GETARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) +#define svc_getargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) + +#define SVC_GETARGS_REQ(xprt, req, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs_req)((xprt), (req), (xargs), (argsp)) +#define svc_getargs_req(xprt, req, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs_req)((xprt), (req), (xargs), (argsp)) + +#define SVC_REPLY(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) +#define svc_reply(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) + +#define SVC_REPLY_REQ(xprt, req, msg) \ + (*(xprt)->xp_ops->xp_reply_req) ((xprt), (req), (msg)) +#define svc_reply_req(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply_req) ((xprt), (req), (msg)) + +#define SVC_FREEARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) +#define svc_freeargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) + +#define SVC_DESTROY(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) +#define svc_destroy(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) + + +/* + * Service request + */ +struct svc_req { + rpcprog_t rq_prog; /* service program number */ + rpcvers_t rq_vers; /* service protocol version */ + rpcproc_t rq_proc; /* the desired procedure */ + struct opaque_auth rq_cred; /* raw creds from the wire */ + void * rq_clntcred; /* read only cooked client cred */ + void * rq_svccred; /* read only svc cred/context */ + void * rq_clntname; /* read only client name */ + SVCXPRT *rq_xprt; /* associated transport */ + /* The request's auth flavor *should* be here, but the svc_req */ + /* isn't passed around everywhere it is necessary. The */ + /* transport *is* passed around, so the auth flavor it stored */ + /* there. This means that the transport must be single */ + /* threaded, but other parts of SunRPC already require that. */ + /*SVCAUTH *rq_auth; associated auth flavor */ +}; + + +/* + * Service registration + * + * svc_register(xprt, prog, vers, dispatch, protocol) + * SVCXPRT *xprt; + * rpcprog_t prog; + * rpcvers_t vers; + * void (*dispatch)(); + * int protocol; like IPPROTO_TCP or _UDP; zero means do not register + * + * registerrpc(prog, vers, proc, routine, inproc, outproc) + * returns 0 upon success, -1 if error. + */ +extern bool_t svc_register(SVCXPRT *, rpcprog_t, rpcvers_t, + void (*)(struct svc_req *, SVCXPRT *), int); + +extern int registerrpc(rpcprog_t, rpcvers_t, rpcproc_t, + char *(*)(void *), + xdrproc_t, xdrproc_t); + +/* + * Service un-registration + * + * svc_unregister(prog, vers) + * rpcprog_t prog; + * rpcvers_t vers; + */ +extern void svc_unregister(rpcprog_t, rpcvers_t); + +/* + * Transport registration. + * + * xprt_register(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_register(SVCXPRT *); + +/* + * Transport un-register + * + * xprt_unregister(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_unregister(SVCXPRT *); + + +/* + * When the service routine is called, it must first check to see if + * it knows about the procedure; if not, it should call svcerr_noproc + * and return. If so, it should deserialize its arguments via + * SVC_GETARGS or the new SVC_GETARGS_REQ (both defined above). If + * the deserialization does not work, svcerr_decode should be called + * followed by a return. Successful decoding of the arguments should + * be followed the execution of the procedure's code and a call to + * svc_sendreply or the new svc_sendreply_req. + * + * Also, if the service refuses to execute the procedure due to too- + * weak authentication parameters, svcerr_weakauth should be called. + * Note: do not confuse access-control failure with weak authentication! + * + * NB: In pure implementations of rpc, the caller always waits for a reply + * msg. This message is sent when svc_sendreply is called. + * Therefore pure service implementations should always call + * svc_sendreply even if the function logically returns void; use + * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows + * for the abuse of pure rpc via batched calling or pipelining. In the + * case of a batched call, svc_sendreply should NOT be called since + * this would send a return message, which is what batching tries to avoid. + * It is the service/protocol writer's responsibility to know which calls are + * batched and which are not. Warning: responding to batch calls may + * deadlock the caller and server processes! + */ + +extern bool_t svc_sendreply(SVCXPRT *, xdrproc_t, caddr_t); +extern void svcerr_decode(SVCXPRT *); +extern void svcerr_weakauth(SVCXPRT *); +extern void svcerr_noproc(SVCXPRT *); +extern void svcerr_progvers(SVCXPRT *, rpcvers_t, rpcvers_t); +extern void svcerr_auth(SVCXPRT *, enum auth_stat); +extern void svcerr_noprog(SVCXPRT *); +extern void svcerr_systemerr(SVCXPRT *); + +/* + * Lowest level dispatching -OR- who owns this process anyway. + * Somebody has to wait for incoming requests and then call the correct + * service routine. The routine svc_run does infinite waiting; i.e., + * svc_run never returns. + * Since another (co-existant) package may wish to selectively wait for + * incoming calls or other events outside of the rpc architecture, the + * routine svc_getreq is provided. It must be passed readfds, the + * "in-place" results of a select system call (see select, section 2). + */ + +/* + * Global keeper of rpc service descriptors in use + * dynamic; must be inspected before each call to select + */ +extern int svc_maxfd; +#ifdef FD_SETSIZE +extern fd_set svc_fdset; +/* RENAMED */ +#define gssrpc_svc_fds gsssrpc_svc_fdset.fds_bits[0] /* compatibility */ +#else +extern int svc_fds; +#endif /* def FD_SETSIZE */ +extern int svc_maxfd; + +extern void svc_getreq(int); +#ifdef FD_SETSIZE +extern void svc_getreqset(fd_set *);/* takes fdset instead of int */ +#else +extern void svc_getreqset(int *); +#endif +extern void svc_run(void); /* never returns */ + +/* + * Socket to use on svcxxx_create call to get default socket + */ +#define RPC_ANYSOCK -1 + +/* + * These are the existing service side transport implementations + */ + +/* + * Memory based rpc for testing and timing. + */ +extern SVCXPRT *svcraw_create(void); + +/* + * Udp based rpc. + */ +extern SVCXPRT *svcudp_create(int); +extern SVCXPRT *svcudp_bufcreate(int, u_int, u_int); +extern int svcudp_enablecache(SVCXPRT *, uint32_t); + +/* + * Tcp based rpc. + */ +extern SVCXPRT *svctcp_create(int, u_int, u_int); + +/* + * Like svtcp_create(), except the routine takes any *open* UNIX file + * descriptor as its first input. + */ +extern SVCXPRT *svcfd_create(int, u_int, u_int); + +/* XXX add auth_gsapi_log_*? */ + +GSSRPC__END_DECLS + +#endif /* !defined(GSSRPC_SVC_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/svc_auth.h b/krb5-1.21.3/src/include/gssrpc/svc_auth.h new file mode 100644 index 00000000..45853747 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/svc_auth.h @@ -0,0 +1,119 @@ +/* @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * 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 the "Oracle America, Inc." 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 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. + */ +/* @(#)svc_auth.h 1.6 86/07/16 SMI */ + +/* + * svc_auth.h, Service side of rpc authentication. + */ + +/* + * Interface to server-side authentication flavors. + */ + +#ifndef GSSRPC_SVC_AUTH_H +#define GSSRPC_SVC_AUTH_H + +#include + +GSSRPC__BEGIN_DECLS + +struct svc_req; + +typedef struct SVCAUTH { + struct svc_auth_ops { + int (*svc_ah_wrap)(struct SVCAUTH *, XDR *, xdrproc_t, + caddr_t); + int (*svc_ah_unwrap)(struct SVCAUTH *, XDR *, xdrproc_t, + caddr_t); + int (*svc_ah_destroy)(struct SVCAUTH *); + } *svc_ah_ops; + void * svc_ah_private; +} SVCAUTH; + +#ifdef GSSRPC__IMPL + +extern SVCAUTH svc_auth_none; + +extern struct svc_auth_ops svc_auth_none_ops; +extern struct svc_auth_ops svc_auth_gssapi_ops; +extern struct svc_auth_ops svc_auth_gss_ops; + +/* + * Server side authenticator + */ +/* RENAMED: should be _authenticate. */ +extern enum auth_stat gssrpc__authenticate(struct svc_req *rqst, + struct rpc_msg *msg, bool_t *no_dispatch); + +#define SVCAUTH_WRAP(auth, xdrs, xfunc, xwhere) \ + ((*((auth)->svc_ah_ops->svc_ah_wrap))(auth, xdrs, xfunc, xwhere)) +#define SVCAUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \ + ((*((auth)->svc_ah_ops->svc_ah_unwrap))(auth, xdrs, xfunc, xwhere)) +#define SVCAUTH_DESTROY(auth) \ + ((*((auth)->svc_ah_ops->svc_ah_destroy))(auth)) + +/* no authentication */ +/* RENAMED: should be _svcauth_none. */ +enum auth_stat gssrpc__svcauth_none(struct svc_req *, + struct rpc_msg *, bool_t *); +/* unix style (uid, gids) */ +/* RENAMED: should be _svcauth_unix. */ +enum auth_stat gssrpc__svcauth_unix(struct svc_req *, + struct rpc_msg *, bool_t *); +/* short hand unix style */ +/* RENAMED: should be _svcauth_short. */ +enum auth_stat gssrpc__svcauth_short(struct svc_req *, + struct rpc_msg *, bool_t *); +/* GSS-API style */ +/* RENAMED: should be _svcauth_gssapi. */ +enum auth_stat gssrpc__svcauth_gssapi(struct svc_req *, + struct rpc_msg *, bool_t *); +/* RPCSEC_GSS */ +enum auth_stat gssrpc__svcauth_gss(struct svc_req *, + struct rpc_msg *, bool_t *); + +#endif /* defined(GSSRPC__IMPL) */ + +/* + * Approved way of getting principal of caller + */ +char *svcauth_gss_get_principal(SVCAUTH *auth); +/* + * Approved way of setting server principal + */ +bool_t svcauth_gss_set_svc_name(gss_name_t name); + +GSSRPC__END_DECLS + +#endif /* !defined(GSSRPC_SVC_AUTH_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/types.hin b/krb5-1.21.3/src/include/gssrpc/types.hin new file mode 100644 index 00000000..25901794 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/types.hin @@ -0,0 +1,130 @@ +/* @(#)types.h 2.3 88/08/15 4.0 RPCSRC */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * 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 the “Oracle America, Inc.” 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 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. + */ +/* @(#)types.h 1.18 87/07/24 SMI */ + +/* + * Rpc additions to + */ +#ifndef GSSRPC_TYPES_H +#define GSSRPC_TYPES_H + +#include + +@GSSRPC__SYS_SELECT_H@ +@GSSRPC__SYS_TIME_H@ +@GSSRPC__UNISTD_H@ + +/* + * Try to get MAXHOSTNAMELEN from somewhere. + */ +@GSSRPC__SYS_PARAM_H@ +@GSSRPC__NETDB_H@ + +/* Get htonl(), ntohl(), etc. */ +#include + +#include +#include +#include + +#ifndef GSSRPC__BEGIN_DECLS +#ifdef __cplusplus +#define GSSRPC__BEGIN_DECLS extern "C" { +#define GSSRPC__END_DECLS } +#else +#define GSSRPC__BEGIN_DECLS +#define GSSRPC__END_DECLS +#endif +#endif + +GSSRPC__BEGIN_DECLS + +#if defined(CHAR_BIT) && CHAR_BIT != 8 +#error "Bytes must be exactly 8 bits." +#endif + +/* Define if we need to fake up some BSD type aliases. */ +#ifndef GSSRPC__BSD_TYPEALIASES /* Allow application to override. */ +@GSSRPC__BSD_TYPEALIASES@ +#endif +#if GSSRPC__BSD_TYPEALIASES +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; +#endif + +typedef uint32_t rpcprog_t; +typedef uint32_t rpcvers_t; +typedef uint32_t rpcprot_t; +typedef uint32_t rpcproc_t; +typedef uint32_t rpcport_t; +typedef int32_t rpc_inline_t; + +/* This is for rpc/netdb.h */ +@rpcent_define@ + +typedef int bool_t; +typedef int enum_t; +#ifndef FALSE +# define FALSE (0) +#endif +#ifndef TRUE +# define TRUE (1) +#endif +/* XXX namespace */ +#define __dontcare__ -1 +#ifndef NULL +# define NULL 0 +#endif + +/* + * The below should probably be internal-only, but seem to be + * traditionally exported in RPC implementations. + */ +#define mem_alloc(bsize) malloc(bsize) +#define mem_free(ptr, bsize) free(ptr) + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK (uint32_t)0x7F000001 +#endif +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +GSSRPC__END_DECLS + +#include + +#endif /* !defined(GSSRPC_TYPES_H) */ diff --git a/krb5-1.21.3/src/include/gssrpc/xdr.h b/krb5-1.21.3/src/include/gssrpc/xdr.h new file mode 100644 index 00000000..da9e1737 --- /dev/null +++ b/krb5-1.21.3/src/include/gssrpc/xdr.h @@ -0,0 +1,338 @@ +/* @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * 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 the "Oracle America, Inc." 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 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. + */ +/* @(#)xdr.h 1.19 87/04/22 SMI */ + +/* + * xdr.h, External Data Representation Serialization Routines. + */ + +#ifndef GSSRPC_XDR_H +#define GSSRPC_XDR_H + +#include /* for FILE */ + +GSSRPC__BEGIN_DECLS +/* + * XDR provides a conventional way for converting between C data + * types and an external bit-string representation. Library supplied + * routines provide for the conversion on built-in C data types. These + * routines and utility routines defined here are used to help implement + * a type encode/decode routine for each user-defined type. + * + * Each data type provides a single procedure which takes two arguments: + * + * bool_t + * xdrproc(xdrs, argresp) + * XDR *xdrs; + * *argresp; + * + * xdrs is an instance of a XDR handle, to which or from which the data + * type is to be converted. argresp is a pointer to the structure to be + * converted. The XDR handle contains an operation field which indicates + * which of the operations (ENCODE, DECODE * or FREE) is to be performed. + * + * XDR_DECODE may allocate space if the pointer argresp is null. This + * data can be freed with the XDR_FREE operation. + * + * We write only one procedure per data type to make it easy + * to keep the encode and decode procedures for a data type consistent. + * In many cases the same code performs all operations on a user defined type, + * because all the hard work is done in the component type routines. + * decode as a series of calls on the nested data types. + */ + +/* + * Xdr operations. XDR_ENCODE causes the type to be encoded into the + * stream. XDR_DECODE causes the type to be extracted from the stream. + * XDR_FREE can be used to release the space allocated by an XDR_DECODE + * request. + */ +enum xdr_op { + XDR_ENCODE=0, + XDR_DECODE=1, + XDR_FREE=2 +}; + +/* + * This is the number of bytes per unit of external data. + */ +#define BYTES_PER_XDR_UNIT (4) +#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ + * BYTES_PER_XDR_UNIT) + +/* + * A xdrproc_t exists for each data type which is to be encoded or decoded. + * + * The second argument to the xdrproc_t is a pointer to an opaque pointer. + * The opaque pointer generally points to a structure of the data type + * to be decoded. If this pointer is 0, then the type routines should + * allocate dynamic storage of the appropriate size and return it. + * bool_t (*xdrproc_t)(XDR *, caddr_t *); + * + * XXX can't actually prototype it, because some take three args!!! + */ +typedef bool_t (*xdrproc_t)(); + +/* + * The XDR handle. + * Contains operation which is being applied to the stream, + * an operations vector for the particular implementation (e.g. see xdr_mem.c), + * and two private fields for the use of the particular impelementation. + */ +typedef struct XDR { + enum xdr_op x_op; /* operation; fast additional param */ + struct xdr_ops { + /* get a long from underlying stream */ + bool_t (*x_getlong)(struct XDR *, long *); + + /* put a long to underlying stream */ + bool_t (*x_putlong)(struct XDR *, long *); + + /* get some bytes from underlying stream */ + bool_t (*x_getbytes)(struct XDR *, caddr_t, u_int); + + /* put some bytes to underlying stream */ + bool_t (*x_putbytes)(struct XDR *, caddr_t, u_int); + + /* returns bytes off from beginning */ + u_int (*x_getpostn)(struct XDR *); + + /* lets you reposition the stream */ + bool_t (*x_setpostn)(struct XDR *, u_int); + + /* buf quick ptr to buffered data */ + rpc_inline_t *(*x_inline)(struct XDR *, int); + + /* free privates of this xdr_stream */ + void (*x_destroy)(struct XDR *); + } *x_ops; + caddr_t x_public; /* users' data */ + void * x_private; /* pointer to private data */ + caddr_t x_base; /* private used for position info */ + int x_handy; /* extra private word */ +} XDR; + +/* + * Operations defined on a XDR handle + * + * XDR *xdrs; + * int32_t *longp; + * caddr_t addr; + * u_int len; + * u_int pos; + */ +#define XDR_GETLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) +#define xdr_getlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) + +#define XDR_PUTLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) +#define xdr_putlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) + +#define XDR_GETBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) +#define xdr_getbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) + +#define XDR_PUTBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) +#define xdr_putbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) + +#define XDR_GETPOS(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) +#define xdr_getpos(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) + +#define XDR_SETPOS(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) +#define xdr_setpos(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) + +#define XDR_INLINE(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) +#define xdr_inline(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) + +#define XDR_DESTROY(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) +#define xdr_destroy(xdrs) \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs) + +/* + * Support struct for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * a entry with a null procedure pointer. The xdr_union routine gets + * the discriminant value and then searches the array of structures + * for a matching value. If a match is found the associated xdr routine + * is called to handle that part of the union. If there is + * no match, then a default routine may be called. + * If there is no match and no default routine it is an error. + */ +#define NULL_xdrproc_t ((xdrproc_t)0) +struct xdr_discrim { + int value; + xdrproc_t proc; +}; + +/* + * In-line routines for fast encode/decode of primitive data types. + * Caveat emptor: these use single memory cycles to get the + * data from the underlying buffer, and will fail to operate + * properly if the data is not aligned. The standard way to use these + * is to say: + * if ((buf = XDR_INLINE(xdrs, count)) == NULL) + * return (FALSE); + * <<< macro calls >>> + * where ``count'' is the number of bytes of data occupied + * by the primitive data types. + * + * N.B. and frozen for all time: each data type here uses 4 bytes + * of external representation. + */ +#define IXDR_GET_INT32(buf) ((int32_t)IXDR_GET_U_INT32(buf)) +#define IXDR_PUT_INT32(buf, v) IXDR_PUT_U_INT32((buf),((uint32_t)(v))) +#define IXDR_GET_U_INT32(buf) (ntohl((uint32_t)*(buf)++)) +#define IXDR_PUT_U_INT32(buf, v) (*(buf)++ = (int32_t)htonl((v))) + +#define IXDR_GET_LONG(buf) ((long)IXDR_GET_INT32(buf)) +#define IXDR_PUT_LONG(buf, v) IXDR_PUT_U_INT32((buf),((uint32_t)(v))) + +#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) +#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_INT32(buf)) +#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_U_INT32(buf)) +#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_INT32(buf)) +#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_U_INT32(buf)) + +#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_INT32((buf),((int32_t)(v))) +#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_INT32((buf),((int32_t)(v))) +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_U_INT32((buf),((uint32_t)(v))) +#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_INT32((buf),((int32_t)(v))) +#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_U_INT32((buf),((uint32_t)(v))) + +/* + * These are the "generic" xdr routines. + */ +extern bool_t xdr_void(XDR *, void *); +extern bool_t xdr_int(XDR *, int *); +extern bool_t xdr_u_int(XDR *, u_int *); +extern bool_t xdr_long(XDR *, long *); +extern bool_t xdr_u_long(XDR *, u_long *); +extern bool_t xdr_short(XDR *, short *); +extern bool_t xdr_u_short(XDR *, u_short *); +extern bool_t xdr_bool(XDR *, bool_t *); +extern bool_t xdr_enum(XDR *, enum_t *); +extern bool_t xdr_array(XDR *, caddr_t *, u_int *, + u_int, u_int, xdrproc_t); +extern bool_t xdr_bytes(XDR *, char **, u_int *, u_int); +extern bool_t xdr_opaque(XDR *, caddr_t, u_int); +extern bool_t xdr_string(XDR *, char **, u_int); +extern bool_t xdr_union(XDR *, enum_t *, char *, struct xdr_discrim *, + xdrproc_t); +extern bool_t xdr_char(XDR *, char *); +extern bool_t xdr_u_char(XDR *, u_char *); +extern bool_t xdr_vector(XDR *, char *, u_int, u_int, xdrproc_t); +extern bool_t xdr_float(XDR *, float *); +extern bool_t xdr_double(XDR *, double *); +extern bool_t xdr_reference(XDR *, caddr_t *, u_int, xdrproc_t); +extern bool_t xdr_pointer(XDR *, char **, u_int, xdrproc_t); +extern bool_t xdr_wrapstring(XDR *, char **); + +extern unsigned long xdr_sizeof(xdrproc_t, void *); + +#define xdr_rpcprog xdr_u_int32 +#define xdr_rpcvers xdr_u_int32 +#define xdr_rpcprot xdr_u_int32 +#define xdr_rpcproc xdr_u_int32 +#define xdr_rpcport xdr_u_int32 + +/* + * Common opaque bytes objects used by many rpc protocols; + * declared here due to commonality. + */ +#define MAX_NETOBJ_SZ 2048 +struct netobj { + u_int n_len; + char *n_bytes; +}; +typedef struct netobj netobj; + +extern bool_t xdr_netobj(XDR *, struct netobj *); + +extern bool_t xdr_int32(XDR *, int32_t *); +extern bool_t xdr_u_int32(XDR *, uint32_t *); + +/* + * These are the public routines for the various implementations of + * xdr streams. + */ + +/* XDR allocating memory buffer */ +extern void xdralloc_create(XDR *, enum xdr_op); + +/* destroy xdralloc, save buf */ +extern void xdralloc_release(XDR *); + +/* get buffer from xdralloc */ +extern caddr_t xdralloc_getdata(XDR *); + +/* XDR using memory buffers */ +extern void xdrmem_create(XDR *, caddr_t, u_int, enum xdr_op); + +/* XDR using stdio library */ +extern void xdrstdio_create(XDR *, FILE *, enum xdr_op); + +/* XDR pseudo records for tcp */ +extern void xdrrec_create(XDR *xdrs, u_int, u_int, caddr_t, + int (*) (caddr_t, caddr_t, int), + int (*) (caddr_t, caddr_t, int)); + +/* make end of xdr record */ +extern bool_t xdrrec_endofrecord(XDR *, bool_t); + +/* move to beginning of next record */ +extern bool_t xdrrec_skiprecord (XDR *xdrs); + +/* true if no more input */ +extern bool_t xdrrec_eof (XDR *xdrs); + +/* free memory buffers for xdr */ +extern void xdr_free (xdrproc_t, void *); +GSSRPC__END_DECLS + +#endif /* !defined(GSSRPC_XDR_H) */ diff --git a/krb5-1.21.3/src/include/iprop.h b/krb5-1.21.3/src/include/iprop.h new file mode 100644 index 00000000..7367666e --- /dev/null +++ b/krb5-1.21.3/src/include/iprop.h @@ -0,0 +1,275 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _IPROP_H_RPCGEN +#define _IPROP_H_RPCGEN + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + u_int utf8str_t_len; + char *utf8str_t_val; +} utf8str_t; + +typedef uint32_t kdb_sno_t; + +struct kdbe_time_t { + uint32_t seconds; + uint32_t useconds; +}; +typedef struct kdbe_time_t kdbe_time_t; + +struct kdbe_key_t { + int32_t k_ver; + int32_t k_kvno; + struct { + u_int k_enctype_len; + int32_t *k_enctype_val; + } k_enctype; + struct { + u_int k_contents_len; + utf8str_t *k_contents_val; + } k_contents; +}; +typedef struct kdbe_key_t kdbe_key_t; + +struct kdbe_data_t { + int32_t k_magic; + utf8str_t k_data; +}; +typedef struct kdbe_data_t kdbe_data_t; + +struct kdbe_princ_t { + utf8str_t k_realm; + struct { + u_int k_components_len; + kdbe_data_t *k_components_val; + } k_components; + int32_t k_nametype; +}; +typedef struct kdbe_princ_t kdbe_princ_t; + +struct kdbe_tl_t { + int16_t tl_type; + struct { + u_int tl_data_len; + char *tl_data_val; + } tl_data; +}; +typedef struct kdbe_tl_t kdbe_tl_t; + +typedef struct { + u_int kdbe_pw_hist_t_len; + kdbe_key_t *kdbe_pw_hist_t_val; +} kdbe_pw_hist_t; + +enum kdbe_attr_type_t { + AT_ATTRFLAGS = 0, + AT_MAX_LIFE = 1, + AT_MAX_RENEW_LIFE = 2, + AT_EXP = 3, + AT_PW_EXP = 4, + AT_LAST_SUCCESS = 5, + AT_LAST_FAILED = 6, + AT_FAIL_AUTH_COUNT = 7, + AT_PRINC = 8, + AT_KEYDATA = 9, + AT_TL_DATA = 10, + AT_LEN = 11, + AT_MOD_PRINC = 12, + AT_MOD_TIME = 13, + AT_MOD_WHERE = 14, + AT_PW_LAST_CHANGE = 15, + AT_PW_POLICY = 16, + AT_PW_POLICY_SWITCH = 17, + AT_PW_HIST_KVNO = 18, + AT_PW_HIST = 19 +}; +typedef enum kdbe_attr_type_t kdbe_attr_type_t; + +struct kdbe_val_t { + kdbe_attr_type_t av_type; + union { + uint32_t av_attrflags; + uint32_t av_max_life; + uint32_t av_max_renew_life; + uint32_t av_exp; + uint32_t av_pw_exp; + uint32_t av_last_success; + uint32_t av_last_failed; + uint32_t av_fail_auth_count; + kdbe_princ_t av_princ; + struct { + u_int av_keydata_len; + kdbe_key_t *av_keydata_val; + } av_keydata; + struct { + u_int av_tldata_len; + kdbe_tl_t *av_tldata_val; + } av_tldata; + int16_t av_len; + uint32_t av_pw_last_change; + kdbe_princ_t av_mod_princ; + uint32_t av_mod_time; + utf8str_t av_mod_where; + utf8str_t av_pw_policy; + bool_t av_pw_policy_switch; + uint32_t av_pw_hist_kvno; + struct { + u_int av_pw_hist_len; + kdbe_pw_hist_t *av_pw_hist_val; + } av_pw_hist; + struct { + u_int av_extension_len; + char *av_extension_val; + } av_extension; + } kdbe_val_t_u; +}; +typedef struct kdbe_val_t kdbe_val_t; + +typedef struct { + u_int kdbe_t_len; + kdbe_val_t *kdbe_t_val; +} kdbe_t; + +struct kdb_incr_update_t { + utf8str_t kdb_princ_name; + kdb_sno_t kdb_entry_sno; + kdbe_time_t kdb_time; + kdbe_t kdb_update; + bool_t kdb_deleted; + bool_t kdb_commit; + struct { + u_int kdb_kdcs_seen_by_len; + utf8str_t *kdb_kdcs_seen_by_val; + } kdb_kdcs_seen_by; + struct { + u_int kdb_futures_len; + char *kdb_futures_val; + } kdb_futures; +}; +typedef struct kdb_incr_update_t kdb_incr_update_t; + +typedef struct { + u_int kdb_ulog_t_len; + kdb_incr_update_t *kdb_ulog_t_val; +} kdb_ulog_t; + +enum update_status_t { + UPDATE_OK = 0, + UPDATE_ERROR = 1, + UPDATE_FULL_RESYNC_NEEDED = 2, + UPDATE_BUSY = 3, + UPDATE_NIL = 4, + UPDATE_PERM_DENIED = 5 +}; +typedef enum update_status_t update_status_t; + +struct kdb_last_t { + kdb_sno_t last_sno; + kdbe_time_t last_time; +}; +typedef struct kdb_last_t kdb_last_t; + +struct kdb_incr_result_t { + kdb_last_t lastentry; + kdb_ulog_t updates; + update_status_t ret; +}; +typedef struct kdb_incr_result_t kdb_incr_result_t; + +struct kdb_fullresync_result_t { + kdb_last_t lastentry; + update_status_t ret; +}; +typedef struct kdb_fullresync_result_t kdb_fullresync_result_t; + +#define KRB5_IPROP_PROG 100423 +#define KRB5_IPROP_VERS 1 + +#if defined(__STDC__) || defined(__cplusplus) +#define IPROP_NULL 0 +extern void * iprop_null_1(void *, CLIENT *); +extern void * iprop_null_1_svc(void *, struct svc_req *); +#define IPROP_GET_UPDATES 1 +extern kdb_incr_result_t * iprop_get_updates_1(kdb_last_t *, CLIENT *); +extern kdb_incr_result_t * iprop_get_updates_1_svc(kdb_last_t *, struct svc_req *); +#define IPROP_FULL_RESYNC 2 +extern kdb_fullresync_result_t * iprop_full_resync_1(void *, CLIENT *); +extern kdb_fullresync_result_t * iprop_full_resync_1_svc(void *, struct svc_req *); +#define IPROP_FULL_RESYNC_EXT 3 +extern kdb_fullresync_result_t * iprop_full_resync_ext_1(uint32_t *, CLIENT *); +extern kdb_fullresync_result_t * iprop_full_resync_ext_1_svc(uint32_t *, struct svc_req *); +extern int krb5_iprop_prog_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); + +#else /* K&R C */ +#define IPROP_NULL 0 +extern void * iprop_null_1(); +extern void * iprop_null_1_svc(); +#define IPROP_GET_UPDATES 1 +extern kdb_incr_result_t * iprop_get_updates_1(); +extern kdb_incr_result_t * iprop_get_updates_1_svc(); +#define IPROP_FULL_RESYNC 2 +extern kdb_fullresync_result_t * iprop_full_resync_1(); +extern kdb_fullresync_result_t * iprop_full_resync_1_svc(); +#define IPROP_FULL_RESYNC_EXT 3 +extern kdb_fullresync_result_t * iprop_full_resync_ext_1(uint32_t *, CLIENT *); +extern kdb_fullresync_result_t * iprop_full_resync_ext_1_svc(uint32_t *, struct svc_req *); +extern int krb5_iprop_prog_1_freeresult (); +#endif /* K&R C */ + +/* the xdr functions */ + +#if defined(__STDC__) || defined(__cplusplus) +extern bool_t xdr_utf8str_t (XDR *, utf8str_t*); +extern bool_t xdr_kdb_sno_t (XDR *, kdb_sno_t*); +extern bool_t xdr_kdbe_time_t (XDR *, kdbe_time_t*); +extern bool_t xdr_kdbe_key_t (XDR *, kdbe_key_t*); +extern bool_t xdr_kdbe_data_t (XDR *, kdbe_data_t*); +extern bool_t xdr_kdbe_princ_t (XDR *, kdbe_princ_t*); +extern bool_t xdr_kdbe_tl_t (XDR *, kdbe_tl_t*); +extern bool_t xdr_kdbe_pw_hist_t (XDR *, kdbe_pw_hist_t*); +extern bool_t xdr_kdbe_attr_type_t (XDR *, kdbe_attr_type_t*); +extern bool_t xdr_kdbe_val_t (XDR *, kdbe_val_t*); +extern bool_t xdr_kdbe_t (XDR *, kdbe_t*); +extern bool_t xdr_kdb_incr_update_t (XDR *, kdb_incr_update_t*); +extern bool_t xdr_kdb_ulog_t (XDR *, kdb_ulog_t*); +extern bool_t xdr_update_status_t (XDR *, update_status_t*); +extern bool_t xdr_kdb_last_t (XDR *, kdb_last_t*); +extern bool_t xdr_kdb_incr_result_t (XDR *, kdb_incr_result_t*); +extern bool_t xdr_kdb_fullresync_result_t (XDR *, kdb_fullresync_result_t*); + +#else /* K&R C */ +extern bool_t xdr_utf8str_t (); +extern bool_t xdr_kdb_sno_t (); +extern bool_t xdr_kdbe_time_t (); +extern bool_t xdr_kdbe_key_t (); +extern bool_t xdr_kdbe_data_t (); +extern bool_t xdr_kdbe_princ_t (); +extern bool_t xdr_kdbe_tl_t (); +extern bool_t xdr_kdbe_pw_hist_t (); +extern bool_t xdr_kdbe_attr_type_t (); +extern bool_t xdr_kdbe_val_t (); +extern bool_t xdr_kdbe_t (); +extern bool_t xdr_kdb_incr_update_t (); +extern bool_t xdr_kdb_ulog_t (); +extern bool_t xdr_update_status_t (); +extern bool_t xdr_kdb_last_t (); +extern bool_t xdr_kdb_incr_result_t (); +extern bool_t xdr_kdb_fullresync_result_t (); + +#endif /* K&R C */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_IPROP_H_RPCGEN */ diff --git a/krb5-1.21.3/src/include/iprop_hdr.h b/krb5-1.21.3/src/include/iprop_hdr.h new file mode 100644 index 00000000..d2145493 --- /dev/null +++ b/krb5-1.21.3/src/include/iprop_hdr.h @@ -0,0 +1,50 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +#ifndef _IPROP_HDR_H +#define _IPROP_HDR_H + +/* #pragma ident "@(#)iprop_hdr.h 1.1 04/02/20 SMI" */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This file has some defines common to the iprop client and + * server routines. + */ + +/* + * Maximum size for each ulog entry is 2KB and maximum + * possible attribute-value pairs for each ulog entry is 20 + */ +#define MAXENTRY_SIZE 2048 +#define MAXATTRS_SIZE 20 + +#define KIPROP_SVC_NAME "kiprop" +#define MAX_BACKOFF 300 /* Backoff for a maximum for 5 mts */ + +enum iprop_role { + IPROP_NULL = 0, + IPROP_PRIMARY = 1, + IPROP_REPLICA = 2 +}; +typedef enum iprop_role iprop_role; + +/* + * Full resync dump versioning + */ +#define IPROPX_VERSION_0 0 +#define IPROPX_VERSION_1 1 +#define IPROPX_VERSION IPROPX_VERSION_1 + +#ifdef __cplusplus +} +#endif + +#endif /* !_IPROP_HDR_H */ diff --git a/krb5-1.21.3/src/include/k5-base64.h b/krb5-1.21.3/src/include/k5-base64.h new file mode 100644 index 00000000..a7cc48fb --- /dev/null +++ b/krb5-1.21.3/src/include/k5-base64.h @@ -0,0 +1,52 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-base64.h - base64 declarations */ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. + */ + +#ifndef K5_BASE64_H +#define K5_BASE64_H + +#include + +/* base64-encode data and return it in an allocated buffer. Return NULL if out + * of memory. */ +char *k5_base64_encode(const void *data, size_t len); + +/* + * Decode str as base64 and return the result in an allocated buffer, setting + * *len_out to the length. Return NULL and *len_out == 0 if out of memory, + * NULL and *len_out == SIZE_MAX on invalid input. + */ +void *k5_base64_decode(const char *str, size_t *len_out); + +#endif /* K5_BASE64_H */ diff --git a/krb5-1.21.3/src/include/k5-buf.h b/krb5-1.21.3/src/include/k5-buf.h new file mode 100644 index 00000000..0db90ccf --- /dev/null +++ b/krb5-1.21.3/src/include/k5-buf.h @@ -0,0 +1,177 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-buf.h - k5buf interface declarations */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef K5_BUF_H +#define K5_BUF_H + +#include +#include + +/* + * The k5buf module is intended to allow multi-step string construction in a + * fixed or dynamic buffer without the need to check for a failure at each step + * (and without aborting on malloc failure). If an allocation failure occurs + * or the fixed buffer runs out of room, the buffer will be set to an error + * state which can be detected with k5_buf_status. Data in a buffer is not + * automatically terminated with a zero byte; call k5_buf_cstring() to use the + * contents as a C string. + * + * k5buf structures are usually stack-allocated. Do not put k5buf structure + * pointers into public APIs. It is okay to reference the data and len fields + * of a buffer (they will be NULL/0 if the buffer is in an error state), but do + * not change them. + */ + +/* Buffer type values */ +enum k5buftype { K5BUF_ERROR, K5BUF_FIXED, K5BUF_DYNAMIC, K5BUF_DYNAMIC_ZAP }; + +struct k5buf { + enum k5buftype buftype; + void *data; + size_t space; + size_t len; +}; + +#define EMPTY_K5BUF { K5BUF_ERROR } + +/* Initialize a k5buf using a fixed-sized, existing buffer. SPACE must be + * more than zero, or an assertion failure will result. */ +void k5_buf_init_fixed(struct k5buf *buf, void *data, size_t space); + +/* Initialize a k5buf using an internally allocated dynamic buffer. */ +void k5_buf_init_dynamic(struct k5buf *buf); + +/* Initialize a k5buf using an internally allocated dynamic buffer, zeroing + * memory when reallocating or freeing. */ +void k5_buf_init_dynamic_zap(struct k5buf *buf); + +/* Add a C string to BUF. */ +void k5_buf_add(struct k5buf *buf, const char *data); + +/* Add a counted series of bytes to BUF. */ +void k5_buf_add_len(struct k5buf *buf, const void *data, size_t len); + +/* Add sprintf-style formatted data to BUF. For a fixed-length buffer this + * operation will fail if there isn't room for a zero terminator. */ +void k5_buf_add_fmt(struct k5buf *buf, const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; + +/* Add sprintf-style formatted data to BUF, with a va_list. The value of ap is + * undefined after the call. */ +void k5_buf_add_vfmt(struct k5buf *buf, const char *fmt, va_list ap) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 0))) +#endif + ; + +/* Without changing the length of buf, ensure that there is a zero byte after + * buf.data and return it. Return NULL on error. */ +char *k5_buf_cstring(struct k5buf *buf); + +/* Extend the length of buf by len and return a pointer to the reserved space, + * to be filled in by the caller. Return NULL on error. */ +void *k5_buf_get_space(struct k5buf *buf, size_t len); + +/* Truncate BUF. LEN must be between 0 and the existing buffer + * length, or an assertion failure will result. */ +void k5_buf_truncate(struct k5buf *buf, size_t len); + +/* Return ENOMEM if buf is in an error state, 0 otherwise. */ +int k5_buf_status(struct k5buf *buf); + +/* + * Free the storage used in the dynamic buffer BUF. The caller may choose to + * take responsibility for freeing the data pointer instead of using this + * function. If BUF is a fixed buffer, an assertion failure will result. + * Freeing a buffer in the error state, a buffer initialized with EMPTY_K5BUF, + * or a zeroed k5buf structure is a no-op. + */ +void k5_buf_free(struct k5buf *buf); + +static inline void +k5_buf_add_byte(struct k5buf *buf, uint8_t val) +{ + k5_buf_add_len(buf, &val, 1); +} + +static inline void +k5_buf_add_uint16_be(struct k5buf *buf, uint16_t val) +{ + void *p = k5_buf_get_space(buf, 2); + + if (p != NULL) + store_16_be(val, p); +} + +static inline void +k5_buf_add_uint16_le(struct k5buf *buf, uint16_t val) +{ + void *p = k5_buf_get_space(buf, 2); + + if (p != NULL) + store_16_le(val, p); +} + +static inline void +k5_buf_add_uint32_be(struct k5buf *buf, uint32_t val) +{ + void *p = k5_buf_get_space(buf, 4); + + if (p != NULL) + store_32_be(val, p); +} + +static inline void +k5_buf_add_uint32_le(struct k5buf *buf, uint32_t val) +{ + void *p = k5_buf_get_space(buf, 4); + + if (p != NULL) + store_32_le(val, p); +} + +static inline void +k5_buf_add_uint64_be(struct k5buf *buf, uint64_t val) +{ + void *p = k5_buf_get_space(buf, 8); + + if (p != NULL) + store_64_be(val, p); +} + +static inline void +k5_buf_add_uint64_le(struct k5buf *buf, uint64_t val) +{ + void *p = k5_buf_get_space(buf, 8); + + if (p != NULL) + store_64_le(val, p); +} + +#endif /* K5_BUF_H */ diff --git a/krb5-1.21.3/src/include/k5-cmocka.h b/krb5-1.21.3/src/include/k5-cmocka.h new file mode 100644 index 00000000..c35b10be --- /dev/null +++ b/krb5-1.21.3/src/include/k5-cmocka.h @@ -0,0 +1,16 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-cmocka.h - indirect header file for cmocka test programs */ + +/* + * This header conditionally includes cmocka.h, so that "make depend" can work + * on cmocka test programs when cmocka isn't available. It also includes the + * three system headers required for cmocka.h. + */ + +#include "autoconf.h" +#include +#include +#include +#ifdef HAVE_CMOCKA +#include +#endif diff --git a/krb5-1.21.3/src/include/k5-der.h b/krb5-1.21.3/src/include/k5-der.h new file mode 100644 index 00000000..b8371d9b --- /dev/null +++ b/krb5-1.21.3/src/include/k5-der.h @@ -0,0 +1,149 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-der.h - Distinguished Encoding Rules (DER) declarations */ +/* + * Copyright (C) 2023 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. + */ + +/* + * Most ASN.1 encoding and decoding is done using the table-driven framework in + * libkrb5. When that is not an option, these helpers can be used to encode + * and decode simple types. + */ + +#ifndef K5_DER_H +#define K5_DER_H + +#include +#include +#include "k5-buf.h" +#include "k5-input.h" + +/* Return the number of bytes needed to encode len as a DER encoding length. */ +static inline size_t +k5_der_len_len(size_t len) +{ + size_t llen; + + if (len < 128) + return 1; + llen = 1; + while (len > 0) { + len >>= 8; + llen++; + } + return llen; +} + +/* Return the number of bytes needed to encode a DER value (with identifier + * byte and length) for a given contents length. */ +static inline size_t +k5_der_value_len(size_t contents_len) +{ + return 1 + k5_der_len_len(contents_len) + contents_len; +} + +/* Add a DER identifier byte (composed by the caller, including the ASN.1 + * class, tag, and constructed bit) and length. */ +static inline void +k5_der_add_taglen(struct k5buf *buf, uint8_t idbyte, size_t len) +{ + uint8_t *p; + size_t llen = k5_der_len_len(len); + + p = k5_buf_get_space(buf, 1 + llen); + if (p == NULL) + return; + *p++ = idbyte; + if (len < 128) { + *p = len; + } else { + *p = 0x80 | (llen - 1); + /* Encode the length bytes backwards so the most significant byte is + * first. */ + p += llen; + while (len > 0) { + *--p = len & 0xFF; + len >>= 8; + } + } +} + +/* Add a DER value (identifier byte, length, and contents). */ +static inline void +k5_der_add_value(struct k5buf *buf, uint8_t idbyte, const void *contents, + size_t len) +{ + k5_der_add_taglen(buf, idbyte, len); + k5_buf_add_len(buf, contents, len); +} + +/* + * If the next byte in in matches idbyte and the subsequent DER length is + * valid, advance in past the value, set *contents_out to the value contents, + * and return true. Otherwise return false. Only set an error on in if the + * next bytes matches idbyte but the ensuing length is invalid. contents_out + * may be aliased to in; it will only be written to on successful decoding of a + * value. + */ +static inline bool +k5_der_get_value(struct k5input *in, uint8_t idbyte, + struct k5input *contents_out) +{ + uint8_t lenbyte, i; + size_t len; + const void *bytes; + + /* Do nothing if in is empty or the next byte doesn't match idbyte. */ + if (in->status || in->len == 0 || *in->ptr != idbyte) + return false; + + /* Advance past the identifier byte and decode the length. */ + (void)k5_input_get_byte(in); + lenbyte = k5_input_get_byte(in); + if (lenbyte < 128) { + len = lenbyte; + } else { + len = 0; + for (i = 0; i < (lenbyte & 0x7F); i++) { + if (len > (SIZE_MAX >> 8)) { + k5_input_set_status(in, EOVERFLOW); + return false; + } + len = (len << 8) | k5_input_get_byte(in); + } + } + + bytes = k5_input_get_bytes(in, len); + if (bytes == NULL) + return false; + k5_input_init(contents_out, bytes, len); + return true; +} + +#endif /* K5_DER_H */ diff --git a/krb5-1.21.3/src/include/k5-err.h b/krb5-1.21.3/src/include/k5-err.h new file mode 100644 index 00000000..d9292076 --- /dev/null +++ b/krb5-1.21.3/src/include/k5-err.h @@ -0,0 +1,69 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-err.h */ +/* + * Copyright 2006, 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * Error-message handling + */ + +#ifndef K5_ERR_H +#define K5_ERR_H + +#if defined(_MSDOS) || defined(_WIN32) +#include +#endif +#ifndef KRB5_CALLCONV +#define KRB5_CALLCONV +#define KRB5_CALLCONV_C +#endif + +#include + +struct errinfo { + long code; + char *msg; +}; +#define EMPTY_ERRINFO { 0, NULL } + +void k5_set_error(struct errinfo *ep, long code, const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 4))) +#endif + ; + +void k5_vset_error(struct errinfo *ep, long code, const char *fmt, + va_list args) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 0))) +#endif + ; + +const char *k5_get_error(struct errinfo *ep, long code); +void k5_free_error(struct errinfo *ep, const char *msg); +void k5_clear_error(struct errinfo *ep); +void k5_set_error_info_callout_fn(const char *(KRB5_CALLCONV *f)(long)); + +#endif /* K5_ERR_H */ diff --git a/krb5-1.21.3/src/include/k5-gmt_mktime.h b/krb5-1.21.3/src/include/k5-gmt_mktime.h new file mode 100644 index 00000000..aa82e838 --- /dev/null +++ b/krb5-1.21.3/src/include/k5-gmt_mktime.h @@ -0,0 +1,43 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-gmt_mktime.h */ +/* + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * GMT struct tm conversion + * + * Because of ordering of things in the UNIX build, we can't just keep + * the declaration in k5-int.h and include it in + * util/support/gmt_mktime.c, since k5-int.h includes krb5.h which + * hasn't been built when gmt_mktime.c gets compiled. Hence this + * silly little helper header. + */ + +#ifndef K5_GMT_MKTIME_H +#define K5_GMT_MKTIME_H + +time_t krb5int_gmt_mktime (struct tm *); + +#endif /* K5_GMT_MKTIME_H */ diff --git a/krb5-1.21.3/src/include/k5-hashtab.h b/krb5-1.21.3/src/include/k5-hashtab.h new file mode 100644 index 00000000..e68970ba --- /dev/null +++ b/krb5-1.21.3/src/include/k5-hashtab.h @@ -0,0 +1,82 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-hash.h - hash table interface definitions */ +/* + * Copyright (C) 2018 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. + */ + +/* + * This file contains declarations for a simple hash table using siphash. Some + * limitations which might need to be addressed in the future: + * + * - The table does not manage caller memory. This limitation could be + * addressed by adding an optional free callback to k5_hashtab_create(), to + * be called by k5_hashtab_free() and k5_hashtab_remove(). + * + * - There is no way to iterate over a hash table. + * + * - k5_hashtab_add() does not check for duplicate entries. + */ + +#ifndef K5_HASH_H +#define K5_HASH_H + +#define K5_HASH_SEED_LEN 16 + +struct k5_hashtab; + +/* + * Create a new hash table in *ht_out. seed must point to random bytes if keys + * might be under the control of an attacker; otherwise it may be NULL. + * initial_buckets controls the initial allocation of hash buckets; pass zero + * to use a default value. The number of hash buckets will be doubled as the + * number of entries increases. Return 0 on success, ENOMEM on failure. + */ +int k5_hashtab_create(const uint8_t seed[K5_HASH_SEED_LEN], + size_t initial_buckets, struct k5_hashtab **ht_out); + +/* Release the memory used by a hash table. Keys and values are the caller's + * responsibility. */ +void k5_hashtab_free(struct k5_hashtab *ht); + +/* Add an entry to a hash table. key and val must remain valid until the entry + * is removed or the hash table is freed. The caller must avoid duplicates. */ +int k5_hashtab_add(struct k5_hashtab *ht, const void *key, size_t klen, + void *val); + +/* Remove an entry from a hash table by key. Does not free key or the + * associated value. Return 1 if the key was found and removed, 0 if not. */ +int k5_hashtab_remove(struct k5_hashtab *ht, const void *key, size_t klen); + +/* Retrieve a value from a hash table by key. */ +void *k5_hashtab_get(struct k5_hashtab *ht, const void *key, size_t klen); + +uint64_t k5_siphash24(const uint8_t *data, size_t len, + const uint8_t seed[K5_HASH_SEED_LEN]); + +#endif /* K5_HASH_H */ diff --git a/krb5-1.21.3/src/include/k5-hex.h b/krb5-1.21.3/src/include/k5-hex.h new file mode 100644 index 00000000..75bd2cb1 --- /dev/null +++ b/krb5-1.21.3/src/include/k5-hex.h @@ -0,0 +1,53 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-hex.h - libkrb5support hex encoding/decoding declarations */ +/* + * Copyright (C) 2018 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. + */ + +#ifndef K5_HEX_H +#define K5_HEX_H + +#include "k5-platform.h" + +/* + * Encode len bytes in hex, placing the result in allocated storage in + * *hex_out. Use uppercase hex digits if uppercase is non-zero. Return 0 on + * success, ENOMEM on error. + */ +int k5_hex_encode(const void *bytes, size_t len, int uppercase, + char **hex_out); + +/* + * Decode hex bytes, placing the result in allocated storage in *bytes_out and + * *len_out. Null-terminate the result (primarily for decoding passwords in + * libkdb_ldap). Return 0 on success, ENOMEM or EINVAL on error. + */ +int k5_hex_decode(const char *hex, uint8_t **bytes_out, size_t *len_out); + +#endif /* K5_HEX_H */ diff --git a/krb5-1.21.3/src/include/k5-input.h b/krb5-1.21.3/src/include/k5-input.h new file mode 100644 index 00000000..9f47fa7a --- /dev/null +++ b/krb5-1.21.3/src/include/k5-input.h @@ -0,0 +1,143 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-input.h - k5input helper functions */ +/* + * Copyright (C) 2014 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. + */ + +#ifndef K5_INPUT_H +#define K5_INPUT_H + +#include "k5-platform.h" + +/* + * The k5input module defines helpers for safely consuming a fixed-sized block + * of memory. If an overrun or allocation failure occurs at any step, + * subsequent functions will return default values until the error is detected + * by looking at the status field. + */ + +struct k5input { + const unsigned char *ptr; + size_t len; + int32_t status; +}; + +static inline void +k5_input_init(struct k5input *in, const void *ptr, size_t len) +{ + in->ptr = ptr; + in->len = len; + in->status = 0; +} + +/* Only set the status value of in if it hasn't already been set, so status + * reflects the first thing to go wrong. */ +static inline void +k5_input_set_status(struct k5input *in, int32_t status) +{ + if (!in->status) + in->status = status; +} + +static inline const unsigned char * +k5_input_get_bytes(struct k5input *in, size_t len) +{ + if (in->len < len) + k5_input_set_status(in, EINVAL); + if (in->status) + return NULL; + in->len -= len; + in->ptr += len; + return in->ptr - len; +} + +static inline unsigned char +k5_input_get_byte(struct k5input *in) +{ + const unsigned char *ptr = k5_input_get_bytes(in, 1); + return (ptr == NULL) ? '\0' : *ptr; +} + +static inline uint16_t +k5_input_get_uint16_be(struct k5input *in) +{ + const unsigned char *ptr = k5_input_get_bytes(in, 2); + return (ptr == NULL) ? 0 : load_16_be(ptr); +} + +static inline uint16_t +k5_input_get_uint16_le(struct k5input *in) +{ + const unsigned char *ptr = k5_input_get_bytes(in, 2); + return (ptr == NULL) ? 0 : load_16_le(ptr); +} + +static inline uint16_t +k5_input_get_uint16_n(struct k5input *in) +{ + const unsigned char *ptr = k5_input_get_bytes(in, 2); + return (ptr == NULL) ? 0 : load_16_n(ptr); +} + +static inline uint32_t +k5_input_get_uint32_be(struct k5input *in) +{ + const unsigned char *ptr = k5_input_get_bytes(in, 4); + return (ptr == NULL) ? 0 : load_32_be(ptr); +} + +static inline uint32_t +k5_input_get_uint32_le(struct k5input *in) +{ + const unsigned char *ptr = k5_input_get_bytes(in, 4); + return (ptr == NULL) ? 0 : load_32_le(ptr); +} + +static inline uint32_t +k5_input_get_uint32_n(struct k5input *in) +{ + const unsigned char *ptr = k5_input_get_bytes(in, 4); + return (ptr == NULL) ? 0 : load_32_n(ptr); +} + +static inline uint64_t +k5_input_get_uint64_be(struct k5input *in) +{ + const unsigned char *ptr = k5_input_get_bytes(in, 8); + return (ptr == NULL) ? 0 : load_64_be(ptr); +} + +static inline uint64_t +k5_input_get_uint64_le(struct k5input *in) +{ + const unsigned char *ptr = k5_input_get_bytes(in, 8); + return (ptr == NULL) ? 0 : load_64_le(ptr); +} + +#endif /* K5_BUF_H */ diff --git a/krb5-1.21.3/src/include/k5-int-pkinit.h b/krb5-1.21.3/src/include/k5-int-pkinit.h new file mode 100644 index 00000000..915904e5 --- /dev/null +++ b/krb5-1.21.3/src/include/k5-int-pkinit.h @@ -0,0 +1,204 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * COPYRIGHT (C) 2006 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#ifndef _KRB5_INT_PKINIT_H +#define _KRB5_INT_PKINIT_H + +/* + * pkinit structures + */ + +/* PKAuthenticator */ +typedef struct _krb5_pk_authenticator { + krb5_int32 cusec; /* (0..999999) */ + krb5_timestamp ctime; + krb5_int32 nonce; /* (0..4294967295) */ + krb5_checksum paChecksum; + krb5_data *freshnessToken; +} krb5_pk_authenticator; + +/* AlgorithmIdentifier */ +typedef struct _krb5_algorithm_identifier { + krb5_data algorithm; /* OID */ + krb5_data parameters; /* Optional */ +} krb5_algorithm_identifier; + +/** AuthPack from RFC 4556*/ +typedef struct _krb5_auth_pack { + krb5_pk_authenticator pkAuthenticator; + krb5_data clientPublicValue; /* Optional */ + krb5_algorithm_identifier **supportedCMSTypes; /* Optional */ + krb5_data clientDHNonce; /* Optional */ + krb5_data **supportedKDFs; /* OIDs of KDFs; OPTIONAL */ +} krb5_auth_pack; + +/* ExternalPrincipalIdentifier */ +typedef struct _krb5_external_principal_identifier { + krb5_data subjectName; /* Optional */ + krb5_data issuerAndSerialNumber; /* Optional */ + krb5_data subjectKeyIdentifier; /* Optional */ +} krb5_external_principal_identifier; + +/* PA-PK-AS-REQ (rfc4556 -- PA TYPE 16) */ +typedef struct _krb5_pa_pk_as_req { + krb5_data signedAuthPack; + krb5_external_principal_identifier **trustedCertifiers; /* Optional array */ + krb5_data kdcPkId; /* Optional */ +} krb5_pa_pk_as_req; + +/** Pkinit DHRepInfo */ +typedef struct _krb5_dh_rep_info { + krb5_data dhSignedData; + krb5_data serverDHNonce; /* Optional */ + krb5_data *kdfID; /* OID of selected KDF OPTIONAL */ +} krb5_dh_rep_info; + +/* KDCDHKeyInfo */ +typedef struct _krb5_kdc_dh_key_info { + krb5_data subjectPublicKey; /* BIT STRING */ + krb5_int32 nonce; /* (0..4294967295) */ + krb5_timestamp dhKeyExpiration; /* Optional */ +} krb5_kdc_dh_key_info; + +/* ReplyKeyPack */ +typedef struct _krb5_reply_key_pack { + krb5_keyblock replyKey; + krb5_checksum asChecksum; +} krb5_reply_key_pack; + +/* PA-PK-AS-REP (rfc4556 -- PA TYPE 17) */ +typedef struct _krb5_pa_pk_as_rep { + enum krb5_pa_pk_as_rep_selection { + choice_pa_pk_as_rep_UNKNOWN = -1, + choice_pa_pk_as_rep_dhInfo = 0, + choice_pa_pk_as_rep_encKeyPack = 1 + } choice; + union krb5_pa_pk_as_rep_choices { + krb5_dh_rep_info dh_Info; + krb5_data encKeyPack; + } u; +} krb5_pa_pk_as_rep; + +/* SP80056A OtherInfo, for pkinit algorithm agility */ +typedef struct _krb5_sp80056a_other_info { + krb5_algorithm_identifier algorithm_identifier; + krb5_principal party_u_info; + krb5_principal party_v_info; + krb5_data supp_pub_info; +} krb5_sp80056a_other_info; + +/* PkinitSuppPubInfo, for pkinit algorithm agility */ +typedef struct _krb5_pkinit_supp_pub_info { + krb5_enctype enctype; + krb5_data as_req; + krb5_data pk_as_rep; +} krb5_pkinit_supp_pub_info; + +/* + * Begin "asn1.h" + */ + +/************************************************************************* + * Prototypes for pkinit asn.1 encode routines + *************************************************************************/ + +krb5_error_code +encode_krb5_pa_pk_as_req(const krb5_pa_pk_as_req *rep, krb5_data **code); + +krb5_error_code +encode_krb5_pa_pk_as_rep(const krb5_pa_pk_as_rep *rep, krb5_data **code); + +krb5_error_code +encode_krb5_auth_pack(const krb5_auth_pack *rep, krb5_data **code); + +krb5_error_code +encode_krb5_kdc_dh_key_info(const krb5_kdc_dh_key_info *rep, krb5_data **code); + +krb5_error_code +encode_krb5_reply_key_pack(const krb5_reply_key_pack *, krb5_data **code); + +krb5_error_code +encode_krb5_td_trusted_certifiers(krb5_external_principal_identifier *const *, + krb5_data **code); + +krb5_error_code +encode_krb5_td_dh_parameters(krb5_algorithm_identifier *const *, + krb5_data **code); + +krb5_error_code +encode_krb5_sp80056a_other_info(const krb5_sp80056a_other_info *, + krb5_data **); + +krb5_error_code +encode_krb5_pkinit_supp_pub_info(const krb5_pkinit_supp_pub_info *, + krb5_data **); + +/************************************************************************* + * Prototypes for pkinit asn.1 decode routines + *************************************************************************/ + +krb5_error_code +decode_krb5_pa_pk_as_req(const krb5_data *, krb5_pa_pk_as_req **); + +krb5_error_code +decode_krb5_pa_pk_as_rep(const krb5_data *, krb5_pa_pk_as_rep **); + +krb5_error_code +decode_krb5_auth_pack(const krb5_data *, krb5_auth_pack **); + +krb5_error_code +decode_krb5_kdc_dh_key_info(const krb5_data *, krb5_kdc_dh_key_info **); + +krb5_error_code +decode_krb5_principal_name(const krb5_data *, krb5_principal_data **); + +krb5_error_code +decode_krb5_reply_key_pack(const krb5_data *, krb5_reply_key_pack **); + +krb5_error_code +decode_krb5_td_trusted_certifiers(const krb5_data *, + krb5_external_principal_identifier ***); + +krb5_error_code +decode_krb5_td_dh_parameters(const krb5_data *, krb5_algorithm_identifier ***); + +krb5_error_code +encode_krb5_enc_data(const krb5_enc_data *, krb5_data **); + +krb5_error_code +encode_krb5_encryption_key(const krb5_keyblock *rep, krb5_data **code); + +krb5_error_code +krb5_encrypt_helper(krb5_context context, const krb5_keyblock *key, + krb5_keyusage keyusage, const krb5_data *plain, + krb5_enc_data *cipher); + +#endif /* _KRB5_INT_PKINIT_H */ diff --git a/krb5-1.21.3/src/include/k5-int.h b/krb5-1.21.3/src/include/k5-int.h new file mode 100644 index 00000000..2f7791b7 --- /dev/null +++ b/krb5-1.21.3/src/include/k5-int.h @@ -0,0 +1,2407 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1989,1990,1991,1992,1993,1994,1995,2000,2001, + * 2003,2006,2007,2008,2009 by the Massachusetts Institute of Technology, + * Cambridge, MA, USA. All Rights Reserved. + * + * This software is being provided to you, the LICENSEE, by the + * Massachusetts Institute of Technology (M.I.T.) under the following + * license. By obtaining, using and/or copying this software, you agree + * that you have read, understood, and will comply with these terms and + * conditions: + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute + * this software and its documentation for any purpose and without fee or + * royalty is hereby granted, provided that you agree to comply with the + * following copyright notice and statements, including the disclaimer, and + * that the same appear on ALL copies of the software and documentation, + * including modifications that you make for internal use or for + * distribution: + * + * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS + * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF + * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF + * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY + * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + * + * The name of the Massachusetts Institute of Technology or M.I.T. may NOT + * be used in advertising or publicity pertaining to distribution of the + * software. Title to copyright in this software and any associated + * documentation shall at all times remain with M.I.T., and USER agrees to + * preserve same. + * + * Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * This prototype for k5-int.h (Krb5 internals include file) + * includes the user-visible definitions from krb5.h and then + * includes other definitions that are not user-visible but are + * required for compiling Kerberos internal routines. + * + * John Gilmore, Cygnus Support, Sat Jan 21 22:45:52 PST 1995 + */ + +#ifndef _KRB5_INT_H +#define _KRB5_INT_H + +#ifdef KRB5_GENERAL__ +#error krb5.h included before k5-int.h +#endif /* KRB5_GENERAL__ */ + +#include "osconf.h" + +#if defined(__MACH__) && defined(__APPLE__) +# include +# if TARGET_RT_MAC_CFM +# error "Use KfM 4.0 SDK headers for CFM compilation." +# endif +#endif + +/* + * Begin "k5-config.h" + */ +#ifndef KRB5_CONFIG__ +#define KRB5_CONFIG__ + +/* + * Machine-type definitions: PC Clone 386 running Microloss Windows + */ + +#if defined(_MSDOS) || defined(_WIN32) +#include "win-mac.h" + +/* Kerberos Windows initialization file */ +#define KERBEROS_INI "kerberos.ini" +#define INI_FILES "Files" +#define INI_KRB_CCACHE "krb5cc" /* Location of the ccache */ +#define INI_KRB5_CONF "krb5.ini" /* Location of krb5.conf file */ +#endif + +#include "autoconf.h" + +#ifndef KRB5_SYSTYPES__ +#define KRB5_SYSTYPES__ + +#ifdef HAVE_SYS_TYPES_H /* From autoconf.h */ +#include +#else /* HAVE_SYS_TYPES_H */ +typedef unsigned long u_long; +typedef unsigned int u_int; +typedef unsigned short u_short; +typedef unsigned char u_char; +#endif /* HAVE_SYS_TYPES_H */ +#endif /* KRB5_SYSTYPES__ */ + + +#include "k5-platform.h" + +#define KRB5_KDB_MAX_LIFE (60*60*24) /* one day */ +#define KRB5_KDB_MAX_RLIFE (60*60*24*7) /* one week */ +#define KRB5_KDB_EXPIRATION 2145830400 /* Thu Jan 1 00:00:00 2038 UTC */ + +/* + * Windows requires a different api interface to each function. Here + * just define it as NULL. + */ +#ifndef KRB5_CALLCONV +#define KRB5_CALLCONV +#define KRB5_CALLCONV_C +#endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +/* #define KRB5_OLD_CRYPTO is done in krb5.h */ + +#endif /* KRB5_CONFIG__ */ + +/* + * End "k5-config.h" + */ + +/* + * After loading the configuration definitions, load the Kerberos definitions. + */ +#include +#include "krb5.h" +#include +#include "profile.h" + +#include "port-sockets.h" +#include "socket-utils.h" + +/* Get mutex support; currently used only for the replay cache. */ +#include "k5-thread.h" + +/* Get error info support. */ +#include "k5-err.h" + +/* Get string buffer support. */ +#include "k5-buf.h" + +/* Define tracing macros. */ +#include "k5-trace.h" + +/* Profile variables. Constants are named KRB5_CONF_STRING, where STRING + * matches the variable name. Keep these alphabetized. */ +#define KRB5_CONF_ACL_FILE "acl_file" +#define KRB5_CONF_ADMIN_SERVER "admin_server" +#define KRB5_CONF_ALLOW_DES3 "allow_des3" +#define KRB5_CONF_ALLOW_RC4 "allow_rc4" +#define KRB5_CONF_ALLOW_WEAK_CRYPTO "allow_weak_crypto" +#define KRB5_CONF_AUTH_TO_LOCAL "auth_to_local" +#define KRB5_CONF_AUTH_TO_LOCAL_NAMES "auth_to_local_names" +#define KRB5_CONF_CANONICALIZE "canonicalize" +#define KRB5_CONF_CCACHE_TYPE "ccache_type" +#define KRB5_CONF_CLOCKSKEW "clockskew" +#define KRB5_CONF_DATABASE_NAME "database_name" +#define KRB5_CONF_DB_MODULE_DIR "db_module_dir" +#define KRB5_CONF_DEBUG "debug" +#define KRB5_CONF_DEFAULT "default" +#define KRB5_CONF_DEFAULT_CCACHE_NAME "default_ccache_name" +#define KRB5_CONF_DEFAULT_CLIENT_KEYTAB_NAME "default_client_keytab_name" +#define KRB5_CONF_DEFAULT_DOMAIN "default_domain" +#define KRB5_CONF_DEFAULT_KEYTAB_NAME "default_keytab_name" +#define KRB5_CONF_DEFAULT_PRINCIPAL_EXPIRATION "default_principal_expiration" +#define KRB5_CONF_DEFAULT_PRINCIPAL_FLAGS "default_principal_flags" +#define KRB5_CONF_DEFAULT_RCACHE_NAME "default_rcache_name" +#define KRB5_CONF_DEFAULT_REALM "default_realm" +#define KRB5_CONF_DEFAULT_TGS_ENCTYPES "default_tgs_enctypes" +#define KRB5_CONF_DEFAULT_TKT_ENCTYPES "default_tkt_enctypes" +#define KRB5_CONF_DICT_FILE "dict_file" +#define KRB5_CONF_DISABLE "disable" +#define KRB5_CONF_DISABLE_ENCRYPTED_TIMESTAMP "disable_encrypted_timestamp" +#define KRB5_CONF_DISABLE_LAST_SUCCESS "disable_last_success" +#define KRB5_CONF_DISABLE_LOCKOUT "disable_lockout" +#define KRB5_CONF_DISABLE_PAC "disable_pac" +#define KRB5_CONF_DNS_CANONICALIZE_HOSTNAME "dns_canonicalize_hostname" +#define KRB5_CONF_DNS_FALLBACK "dns_fallback" +#define KRB5_CONF_DNS_LOOKUP_KDC "dns_lookup_kdc" +#define KRB5_CONF_DNS_LOOKUP_REALM "dns_lookup_realm" +#define KRB5_CONF_DNS_URI_LOOKUP "dns_uri_lookup" +#define KRB5_CONF_DOMAIN_REALM "domain_realm" +#define KRB5_CONF_ENABLE_ONLY "enable_only" +#define KRB5_CONF_ENCRYPTED_CHALLENGE_INDICATOR "encrypted_challenge_indicator" +#define KRB5_CONF_ENFORCE_OK_AS_DELEGATE "enforce_ok_as_delegate" +#define KRB5_CONF_ERR_FMT "err_fmt" +#define KRB5_CONF_EXTRA_ADDRESSES "extra_addresses" +#define KRB5_CONF_FORWARDABLE "forwardable" +#define KRB5_CONF_HOST_BASED_SERVICES "host_based_services" +#define KRB5_CONF_HTTP_ANCHORS "http_anchors" +#define KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME "ignore_acceptor_hostname" +#define KRB5_CONF_IPROP_ENABLE "iprop_enable" +#define KRB5_CONF_IPROP_LISTEN "iprop_listen" +#define KRB5_CONF_IPROP_LOGFILE "iprop_logfile" +#define KRB5_CONF_IPROP_MASTER_ULOGSIZE "iprop_master_ulogsize" +#define KRB5_CONF_IPROP_PORT "iprop_port" +#define KRB5_CONF_IPROP_RESYNC_TIMEOUT "iprop_resync_timeout" +#define KRB5_CONF_IPROP_REPLICA_POLL "iprop_replica_poll" +#define KRB5_CONF_IPROP_SLAVE_POLL "iprop_slave_poll" +#define KRB5_CONF_IPROP_ULOGSIZE "iprop_ulogsize" +#define KRB5_CONF_K5LOGIN_AUTHORITATIVE "k5login_authoritative" +#define KRB5_CONF_K5LOGIN_DIRECTORY "k5login_directory" +#define KRB5_CONF_KADMIND_LISTEN "kadmind_listen" +#define KRB5_CONF_KADMIND_PORT "kadmind_port" +#define KRB5_CONF_KCM_MACH_SERVICE "kcm_mach_service" +#define KRB5_CONF_KCM_SOCKET "kcm_socket" +#define KRB5_CONF_KDC "kdc" +#define KRB5_CONF_KDCDEFAULTS "kdcdefaults" +#define KRB5_CONF_KDC_DEFAULT_OPTIONS "kdc_default_options" +#define KRB5_CONF_KDC_LISTEN "kdc_listen" +#define KRB5_CONF_KDC_MAX_DGRAM_REPLY_SIZE "kdc_max_dgram_reply_size" +#define KRB5_CONF_KDC_PORTS "kdc_ports" +#define KRB5_CONF_KDC_TCP_PORTS "kdc_tcp_ports" +#define KRB5_CONF_KDC_TCP_LISTEN "kdc_tcp_listen" +#define KRB5_CONF_KDC_TCP_LISTEN_BACKLOG "kdc_tcp_listen_backlog" +#define KRB5_CONF_KDC_TIMESYNC "kdc_timesync" +#define KRB5_CONF_KEY_STASH_FILE "key_stash_file" +#define KRB5_CONF_KPASSWD_LISTEN "kpasswd_listen" +#define KRB5_CONF_KPASSWD_PORT "kpasswd_port" +#define KRB5_CONF_KPASSWD_SERVER "kpasswd_server" +#define KRB5_CONF_KRB524_SERVER "krb524_server" +#define KRB5_CONF_LDAP_CONNS_PER_SERVER "ldap_conns_per_server" +#define KRB5_CONF_LDAP_KADMIND_DN "ldap_kadmind_dn" +#define KRB5_CONF_LDAP_KADMIND_SASL_AUTHCID "ldap_kadmind_sasl_authcid" +#define KRB5_CONF_LDAP_KADMIND_SASL_AUTHZID "ldap_kadmind_sasl_authzid" +#define KRB5_CONF_LDAP_KADMIND_SASL_MECH "ldap_kadmind_sasl_mech" +#define KRB5_CONF_LDAP_KADMIND_SASL_REALM "ldap_kadmind_sasl_realm" +#define KRB5_CONF_LDAP_KDC_DN "ldap_kdc_dn" +#define KRB5_CONF_LDAP_KDC_SASL_AUTHCID "ldap_kdc_sasl_authcid" +#define KRB5_CONF_LDAP_KDC_SASL_AUTHZID "ldap_kdc_sasl_authzid" +#define KRB5_CONF_LDAP_KDC_SASL_MECH "ldap_kdc_sasl_mech" +#define KRB5_CONF_LDAP_KDC_SASL_REALM "ldap_kdc_sasl_realm" +#define KRB5_CONF_LDAP_KERBEROS_CONTAINER_DN "ldap_kerberos_container_dn" +#define KRB5_CONF_LDAP_SERVERS "ldap_servers" +#define KRB5_CONF_LDAP_SERVICE_PASSWORD_FILE "ldap_service_password_file" +#define KRB5_CONF_LIBDEFAULTS "libdefaults" +#define KRB5_CONF_LOGGING "logging" +#define KRB5_CONF_MAPSIZE "mapsize" +#define KRB5_CONF_MASTER_KDC "master_kdc" +#define KRB5_CONF_MASTER_KEY_NAME "master_key_name" +#define KRB5_CONF_MASTER_KEY_TYPE "master_key_type" +#define KRB5_CONF_MAX_LIFE "max_life" +#define KRB5_CONF_MAX_READERS "max_readers" +#define KRB5_CONF_MAX_RENEWABLE_LIFE "max_renewable_life" +#define KRB5_CONF_MODULE "module" +#define KRB5_CONF_NOADDRESSES "noaddresses" +#define KRB5_CONF_NOSYNC "nosync" +#define KRB5_CONF_NO_HOST_REFERRAL "no_host_referral" +#define KRB5_CONF_PERMITTED_ENCTYPES "permitted_enctypes" +#define KRB5_CONF_PLUGINS "plugins" +#define KRB5_CONF_PLUGIN_BASE_DIR "plugin_base_dir" +#define KRB5_CONF_PREFERRED_PREAUTH_TYPES "preferred_preauth_types" +#define KRB5_CONF_PRIMARY_KDC "primary_kdc" +#define KRB5_CONF_PROXIABLE "proxiable" +#define KRB5_CONF_QUALIFY_SHORTNAME "qualify_shortname" +#define KRB5_CONF_RDNS "rdns" +#define KRB5_CONF_REALMS "realms" +#define KRB5_CONF_REALM_TRY_DOMAINS "realm_try_domains" +#define KRB5_CONF_REJECT_BAD_TRANSIT "reject_bad_transit" +#define KRB5_CONF_RENEW_LIFETIME "renew_lifetime" +#define KRB5_CONF_RESTRICT_ANONYMOUS_TO_TGT "restrict_anonymous_to_tgt" +#define KRB5_CONF_SUPPORTED_ENCTYPES "supported_enctypes" +#define KRB5_CONF_SPAKE_PREAUTH_INDICATOR "spake_preauth_indicator" +#define KRB5_CONF_SPAKE_PREAUTH_KDC_CHALLENGE "spake_preauth_kdc_challenge" +#define KRB5_CONF_SPAKE_PREAUTH_GROUPS "spake_preauth_groups" +#define KRB5_CONF_TICKET_LIFETIME "ticket_lifetime" +#define KRB5_CONF_UDP_PREFERENCE_LIMIT "udp_preference_limit" +#define KRB5_CONF_UNLOCKITER "unlockiter" +#define KRB5_CONF_V4_INSTANCE_CONVERT "v4_instance_convert" +#define KRB5_CONF_V4_REALM "v4_realm" +#define KRB5_CONF_VERIFY_AP_REQ_NOFAIL "verify_ap_req_nofail" +#define KRB5_CONF_CLIENT_AWARE_GSS_BINDINGS "client_aware_channel_bindings" + +/* Cache configuration variables */ +#define KRB5_CC_CONF_FAST_AVAIL "fast_avail" +#define KRB5_CC_CONF_PA_CONFIG_DATA "pa_config_data" +#define KRB5_CC_CONF_PA_TYPE "pa_type" +#define KRB5_CC_CONF_PROXY_IMPERSONATOR "proxy_impersonator" +#define KRB5_CC_CONF_REFRESH_TIME "refresh_time" +#define KRB5_CC_CONF_START_REALM "start_realm" + +/* Error codes used in KRB_ERROR protocol messages. + Return values of library routines are based on a different error table + (which allows non-ambiguous error codes between subsystems) */ + +/* KDC errors */ +#define KDC_ERR_NONE 0 /* No error */ +#define KDC_ERR_NAME_EXP 1 /* Client's entry in DB expired */ +#define KDC_ERR_SERVICE_EXP 2 /* Server's entry in DB expired */ +#define KDC_ERR_BAD_PVNO 3 /* Requested pvno not supported */ +#define KDC_ERR_C_OLD_MAST_KVNO 4 /* C's key encrypted in old master */ +#define KDC_ERR_S_OLD_MAST_KVNO 5 /* S's key encrypted in old master */ +#define KDC_ERR_C_PRINCIPAL_UNKNOWN 6 /* Client not found in Kerberos DB */ +#define KDC_ERR_S_PRINCIPAL_UNKNOWN 7 /* Server not found in Kerberos DB */ +#define KDC_ERR_PRINCIPAL_NOT_UNIQUE 8 /* Multiple entries in Kerberos DB */ +#define KDC_ERR_NULL_KEY 9 /* The C or S has a null key */ +#define KDC_ERR_CANNOT_POSTDATE 10 /* Tkt ineligible for postdating */ +#define KDC_ERR_NEVER_VALID 11 /* Requested starttime > endtime */ +#define KDC_ERR_POLICY 12 /* KDC policy rejects request */ +#define KDC_ERR_BADOPTION 13 /* KDC can't do requested opt. */ +#define KDC_ERR_ENCTYPE_NOSUPP 14 /* No support for encryption type */ +#define KDC_ERR_SUMTYPE_NOSUPP 15 /* No support for checksum type */ +#define KDC_ERR_PADATA_TYPE_NOSUPP 16 /* No support for padata type */ +#define KDC_ERR_TRTYPE_NOSUPP 17 /* No support for transited type */ +#define KDC_ERR_CLIENT_REVOKED 18 /* C's creds have been revoked */ +#define KDC_ERR_SERVICE_REVOKED 19 /* S's creds have been revoked */ +#define KDC_ERR_TGT_REVOKED 20 /* TGT has been revoked */ +#define KDC_ERR_CLIENT_NOTYET 21 /* C not yet valid */ +#define KDC_ERR_SERVICE_NOTYET 22 /* S not yet valid */ +#define KDC_ERR_KEY_EXP 23 /* Password has expired */ +#define KDC_ERR_PREAUTH_FAILED 24 /* Preauthentication failed */ +#define KDC_ERR_PREAUTH_REQUIRED 25 /* Additional preauthentication */ + /* required */ +#define KDC_ERR_SERVER_NOMATCH 26 /* Requested server and */ + /* ticket don't match*/ +#define KDC_ERR_MUST_USE_USER2USER 27 /* Server principal valid for */ + /* user2user only */ +#define KDC_ERR_PATH_NOT_ACCEPTED 28 /* KDC policy rejected transited */ + /* path */ +#define KDC_ERR_SVC_UNAVAILABLE 29 /* A service is not + * available that is + * required to process the + * request */ +/* Application errors */ +#define KRB_AP_ERR_BAD_INTEGRITY 31 /* Decrypt integrity check failed */ +#define KRB_AP_ERR_TKT_EXPIRED 32 /* Ticket expired */ +#define KRB_AP_ERR_TKT_NYV 33 /* Ticket not yet valid */ +#define KRB_AP_ERR_REPEAT 34 /* Request is a replay */ +#define KRB_AP_ERR_NOT_US 35 /* The ticket isn't for us */ +#define KRB_AP_ERR_BADMATCH 36 /* Ticket/authenticator don't match */ +#define KRB_AP_ERR_SKEW 37 /* Clock skew too great */ +#define KRB_AP_ERR_BADADDR 38 /* Incorrect net address */ +#define KRB_AP_ERR_BADVERSION 39 /* Protocol version mismatch */ +#define KRB_AP_ERR_MSG_TYPE 40 /* Invalid message type */ +#define KRB_AP_ERR_MODIFIED 41 /* Message stream modified */ +#define KRB_AP_ERR_BADORDER 42 /* Message out of order */ +#define KRB_AP_ERR_BADKEYVER 44 /* Key version is not available */ +#define KRB_AP_ERR_NOKEY 45 /* Service key not available */ +#define KRB_AP_ERR_MUT_FAIL 46 /* Mutual authentication failed */ +#define KRB_AP_ERR_BADDIRECTION 47 /* Incorrect message direction */ +#define KRB_AP_ERR_METHOD 48 /* Alternative authentication */ + /* method required */ +#define KRB_AP_ERR_BADSEQ 49 /* Incorrect sequence numnber */ + /* in message */ +#define KRB_AP_ERR_INAPP_CKSUM 50 /* Inappropriate type of */ + /* checksum in message */ +#define KRB_AP_PATH_NOT_ACCEPTED 51 /* Policy rejects transited path */ +#define KRB_ERR_RESPONSE_TOO_BIG 52 /* Response too big for UDP, */ + /* retry with TCP */ + +/* other errors */ +#define KRB_ERR_GENERIC 60 /* Generic error (description */ + /* in e-text) */ +#define KRB_ERR_FIELD_TOOLONG 61 /* Field is too long for impl. */ + +/* PKINIT server-reported errors */ +#define KDC_ERR_CLIENT_NOT_TRUSTED 62 /* client cert not trusted */ +#define KDC_ERR_KDC_NOT_TRUSTED 63 +#define KDC_ERR_INVALID_SIG 64 /* client signature verify failed */ +#define KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED 65 /* invalid Diffie-Hellman parameters */ +#define KDC_ERR_CERTIFICATE_MISMATCH 66 +#define KRB_AP_ERR_NO_TGT 67 +#define KDC_ERR_WRONG_REALM 68 +#define KRB_AP_ERR_USER_TO_USER_REQUIRED 69 +#define KDC_ERR_CANT_VERIFY_CERTIFICATE 70 /* client cert not verifiable to */ + /* trusted root cert */ +#define KDC_ERR_INVALID_CERTIFICATE 71 /* client cert had invalid signature */ +#define KDC_ERR_REVOKED_CERTIFICATE 72 /* client cert was revoked */ +#define KDC_ERR_REVOCATION_STATUS_UNKNOWN 73 /* client cert revoked, reason unknown */ +#define KDC_ERR_REVOCATION_STATUS_UNAVAILABLE 74 +#define KDC_ERR_CLIENT_NAME_MISMATCH 75 /* mismatch between client cert and */ + /* principal name */ +#define KDC_ERR_INCONSISTENT_KEY_PURPOSE 77 /* bad extended key use */ +#define KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED 78 /* bad digest algorithm in client cert */ +#define KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED 79 /* missing paChecksum in PA-PK-AS-REQ */ +#define KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED 80 /* bad digest algorithm in SignedData */ +#define KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED 81 +#define KRB_AP_ERR_IAKERB_KDC_NOT_FOUND 85 /* The IAKERB proxy could + not find a KDC */ +#define KRB_AP_ERR_IAKERB_KDC_NO_RESPONSE 86 /* The KDC did not respond + to the IAKERB proxy */ +#define KDC_ERR_PREAUTH_EXPIRED 90 /* RFC 6113 */ +#define KDC_ERR_MORE_PREAUTH_DATA_REQUIRED 91 /* RFC 6113 */ +#define KRB_ERR_MAX 127 /* err table base max offset for protocol err codes */ + +/* + * A null-terminated array of this structure is returned by the KDC as + * the data part of the ETYPE_INFO preauth type. It informs the + * client which encryption types are supported. + * The same data structure is used by both etype-info and etype-info2 + * but s2kparams must be null when encoding etype-info. + */ +typedef struct _krb5_etype_info_entry { + krb5_magic magic; + krb5_enctype etype; + unsigned int length; + krb5_octet *salt; + krb5_data s2kparams; +} krb5_etype_info_entry; + +/* + * This is essentially -1 without sign extension which can screw up + * comparisons on 64 bit machines. If the length is this value, then + * the salt data is not present. This is to distinguish between not + * being set and being of 0 length. + */ +#define KRB5_ETYPE_NO_SALT VALID_UINT_BITS + +typedef krb5_etype_info_entry ** krb5_etype_info; + +/* RFC 4537 */ +typedef struct _krb5_etype_list { + int length; + krb5_enctype *etypes; +} krb5_etype_list; + +/* sam_type values -- informational only */ +#define PA_SAM_TYPE_ENIGMA 1 /* Enigma Logic */ +#define PA_SAM_TYPE_DIGI_PATH 2 /* Digital Pathways */ +#define PA_SAM_TYPE_SKEY_K0 3 /* S/key where KDC has key 0 */ +#define PA_SAM_TYPE_SKEY 4 /* Traditional S/Key */ +#define PA_SAM_TYPE_SECURID 5 /* Security Dynamics */ +#define PA_SAM_TYPE_CRYPTOCARD 6 /* CRYPTOCard */ +#if 1 /* XXX need to figure out who has which numbers assigned */ +#define PA_SAM_TYPE_ACTIVCARD_DEC 6 /* ActivCard decimal mode */ +#define PA_SAM_TYPE_ACTIVCARD_HEX 7 /* ActivCard hex mode */ +#define PA_SAM_TYPE_DIGI_PATH_HEX 8 /* Digital Pathways hex mode */ +#endif +#define PA_SAM_TYPE_EXP_BASE 128 /* experimental */ +#define PA_SAM_TYPE_GRAIL (PA_SAM_TYPE_EXP_BASE+0) /* testing */ +#define PA_SAM_TYPE_SECURID_PREDICT (PA_SAM_TYPE_EXP_BASE+1) /* special */ + +typedef struct _krb5_sam_challenge_2 { + krb5_data sam_challenge_2_body; + krb5_checksum **sam_cksum; /* Array of checksums */ +} krb5_sam_challenge_2; + +typedef struct _krb5_sam_challenge_2_body { + krb5_magic magic; + krb5_int32 sam_type; /* information */ + krb5_flags sam_flags; /* KRB5_SAM_* values */ + krb5_data sam_type_name; + krb5_data sam_track_id; + krb5_data sam_challenge_label; + krb5_data sam_challenge; + krb5_data sam_response_prompt; + krb5_data sam_pk_for_sad; + krb5_int32 sam_nonce; + krb5_enctype sam_etype; +} krb5_sam_challenge_2_body; + +typedef struct _krb5_sam_response_2 { + krb5_magic magic; + krb5_int32 sam_type; /* informational */ + krb5_flags sam_flags; /* KRB5_SAM_* values */ + krb5_data sam_track_id; /* copied */ + krb5_enc_data sam_enc_nonce_or_sad; /* krb5_enc_sam_response_enc */ + krb5_int32 sam_nonce; +} krb5_sam_response_2; + +typedef struct _krb5_enc_sam_response_enc_2 { + krb5_magic magic; + krb5_int32 sam_nonce; + krb5_data sam_sad; +} krb5_enc_sam_response_enc_2; + +/* + * Keep the pkinit definitions in a separate file so that the plugin + * only has to include k5-int-pkinit.h rather than k5-int.h + */ + +#include "k5-int-pkinit.h" + +#define KRB5_OTP_FLAG_NEXTOTP 0x40000000 +#define KRB5_OTP_FLAG_COMBINE 0x20000000 +#define KRB5_OTP_FLAG_COLLECT_PIN 0x10000000 +#define KRB5_OTP_FLAG_NO_COLLECT_PIN 0x08000000 +#define KRB5_OTP_FLAG_ENCRYPT_NONCE 0x04000000 +#define KRB5_OTP_FLAG_SEPARATE_PIN 0x02000000 +#define KRB5_OTP_FLAG_CHECK_DIGIT 0x01000000 + +#define KRB5_OTP_FORMAT_DECIMAL 0x00000000 +#define KRB5_OTP_FORMAT_HEXADECIMAL 0x00000001 +#define KRB5_OTP_FORMAT_ALPHANUMERIC 0x00000002 +#define KRB5_OTP_FORMAT_BINARY 0x00000003 +#define KRB5_OTP_FORMAT_BASE64 0x00000004 + +typedef struct _krb5_otp_tokeninfo { + krb5_flags flags; + krb5_data vendor; + krb5_data challenge; + krb5_int32 length; /* -1 for unspecified */ + krb5_int32 format; /* -1 for unspecified */ + krb5_data token_id; + krb5_data alg_id; + krb5_algorithm_identifier **supported_hash_alg; + krb5_int32 iteration_count; /* -1 for unspecified */ +} krb5_otp_tokeninfo; + +typedef struct _krb5_pa_otp_challenge { + krb5_data nonce; + krb5_data service; + krb5_otp_tokeninfo **tokeninfo; + krb5_data salt; + krb5_data s2kparams; +} krb5_pa_otp_challenge; + +typedef struct _krb5_pa_otp_req { + krb5_int32 flags; + krb5_data nonce; + krb5_enc_data enc_data; + krb5_algorithm_identifier *hash_alg; + krb5_int32 iteration_count; /* -1 for unspecified */ + krb5_data otp_value; + krb5_data pin; + krb5_data challenge; + krb5_timestamp time; + krb5_data counter; + krb5_int32 format; /* -1 for unspecified */ + krb5_data token_id; + krb5_data alg_id; + krb5_data vendor; +} krb5_pa_otp_req; + +typedef struct _krb5_kkdcp_message { + krb5_data kerb_message; + krb5_data target_domain; + krb5_int32 dclocator_hint; +} krb5_kkdcp_message; + +/* Plain text of an encrypted PA-FX-COOKIE value produced by the KDC. */ +typedef struct _krb5_secure_cookie { + time_t time; + krb5_pa_data **data; +} krb5_secure_cookie; + +typedef struct _krb5_pa_pac_options { + krb5_flags options; +} krb5_pa_pac_options; + +/* In PAC options, indicates Resource-Based Constrained Delegation support. */ +#define KRB5_PA_PAC_OPTIONS_RBCD 0x10000000 + +#include +#include + +#ifndef HAVE_STRDUP +extern char *strdup (const char *); +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#endif +#include + +#ifdef HAVE_SYS_STAT_H +#include /* struct stat, stat() */ +#endif + +#ifdef HAVE_SYS_PARAM_H +#include /* MAXPATHLEN */ +#endif + +#ifdef HAVE_SYS_FILE_H +#include /* prototypes for file-related + syscalls; flags for open & + friends */ +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include + +#include "k5-gmt_mktime.h" + +/* libos.spec */ +krb5_error_code krb5_lock_file(krb5_context, int, int); +krb5_error_code krb5_unlock_file(krb5_context, int); +krb5_error_code krb5_sendto_kdc(krb5_context, const krb5_data *, + const krb5_data *, krb5_data *, int *, int); + +krb5_error_code krb5int_init_context_kdc(krb5_context *); + +struct derived_key { + krb5_data constant; + krb5_key dkey; + struct derived_key *next; +}; + +/* Internal structure of an opaque key identifier */ +struct krb5_key_st { + krb5_keyblock keyblock; + int refcount; + struct derived_key *derived; + /* + * Cache of data private to the cipher implementation, which we + * don't want to have to recompute for every operation. This may + * include key schedules, iteration counts, etc. + * + * The cipher implementation is responsible for setting this up + * whenever needed, and the enc_provider key_cleanup method must + * then be provided to dispose of it. + */ + void *cache; +}; + +krb5_error_code +krb5int_arcfour_gsscrypt(const krb5_keyblock *keyblock, krb5_keyusage usage, + const krb5_data *kd_data, krb5_crypto_iov *data, + size_t num_data); + +#define K5_SHA256_HASHLEN (256 / 8) + +/* Write the SHA-256 hash of in (containing n elements) to out. */ +krb5_error_code +k5_sha256(const krb5_data *in, size_t n, uint8_t out[K5_SHA256_HASHLEN]); + +/* Convenience function: zap and free ptr if it is non-NULL. */ +static inline void +zapfree(void *ptr, size_t len) +{ + if (ptr != NULL) { + zap(ptr, len); + free(ptr); + } +} + +/* Convenience function: zap and free zero-terminated str if it is non-NULL. */ +static inline void +zapfreestr(void *str) +{ + if (str != NULL) { + zap(str, strlen((char *)str)); + free(str); + } +} + +/* Convenience function: zap and free krb5_data pointer if it is non-NULL. */ +static inline void +zapfreedata(krb5_data *data) +{ + if (data != NULL) { + zapfree(data->data, data->length); + free(data); + } +} + +void krb5int_c_free_keyblock(krb5_context, krb5_keyblock *key); +void krb5int_c_free_keyblock_contents(krb5_context, krb5_keyblock *); +krb5_error_code krb5int_c_init_keyblock(krb5_context, krb5_enctype enctype, + size_t length, krb5_keyblock **out); +krb5_error_code krb5int_c_copy_keyblock(krb5_context context, + const krb5_keyblock *from, + krb5_keyblock **to); +krb5_error_code krb5int_c_copy_keyblock_contents(krb5_context context, + const krb5_keyblock *from, + krb5_keyblock *to); + +krb5_error_code krb5_crypto_us_timeofday(krb5_timestamp *, krb5_int32 *); + +/* + * End "los-proto.h" + */ + +typedef struct _krb5_os_context { + krb5_magic magic; + krb5_int32 time_offset; + krb5_int32 usec_offset; + krb5_int32 os_flags; + char * default_ccname; +} *krb5_os_context; + +/* + * Flags for the os_flags field + * + * KRB5_OS_TOFFSET_VALID means that the time offset fields are valid. + * The intention is that this facility to correct the system clocks so + * that they reflect the "real" time, for systems where for some + * reason we can't set the system clock. Instead we calculate the + * offset between the system time and real time, and store the offset + * in the os context so that we can correct the system clock as necessary. + * + * KRB5_OS_TOFFSET_TIME means that the time offset fields should be + * returned as the time by the krb5 time routines. This should only + * be used for testing purposes (obviously!) + */ +#define KRB5_OS_TOFFSET_VALID 1 +#define KRB5_OS_TOFFSET_TIME 2 + +/* lock mode flags */ +#define KRB5_LOCKMODE_SHARED 0x0001 +#define KRB5_LOCKMODE_EXCLUSIVE 0x0002 +#define KRB5_LOCKMODE_DONTBLOCK 0x0004 +#define KRB5_LOCKMODE_UNLOCK 0x0008 + +/* + * Begin "preauth.h" + * + * (Originally written by Glen Machin at Sandia Labs.) + */ +/* + * Sandia National Laboratories also makes no representations about the + * suitability of the modifications, or additions to this software for + * any purpose. It is provided "as is" without express or implied warranty. + */ +#ifndef KRB5_PREAUTH__ +#define KRB5_PREAUTH__ + +typedef struct _krb5_pa_enc_ts { + krb5_timestamp patimestamp; + krb5_int32 pausec; +} krb5_pa_enc_ts; + +typedef struct _krb5_pa_for_user { + krb5_principal user; + krb5_checksum cksum; + krb5_data auth_package; +} krb5_pa_for_user; + +typedef struct _krb5_s4u_userid { + krb5_int32 nonce; + krb5_principal user; + krb5_data subject_cert; + krb5_flags options; +} krb5_s4u_userid; + +#define KRB5_S4U_OPTS_CHECK_LOGON_HOURS 0x40000000 /* check logon hour restrictions */ +#define KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE 0x20000000 /* sign with usage 27 instead of 26 */ + +typedef struct _krb5_pa_s4u_x509_user { + krb5_s4u_userid user_id; + krb5_checksum cksum; +} krb5_pa_s4u_x509_user; + +enum { + KRB5_FAST_ARMOR_AP_REQUEST = 0x1 +}; + +typedef struct _krb5_fast_armor { + krb5_int32 armor_type; + krb5_data armor_value; +} krb5_fast_armor; +typedef struct _krb5_fast_armored_req { + krb5_magic magic; + krb5_fast_armor *armor; + krb5_checksum req_checksum; + krb5_enc_data enc_part; +} krb5_fast_armored_req; + +typedef struct _krb5_fast_req { + krb5_magic magic; + krb5_flags fast_options; + /* padata from req_body is used*/ + krb5_kdc_req *req_body; +} krb5_fast_req; + +/* Bits 0-15 are critical in FAST options (RFC 6113 section 7.3). */ +#define UNSUPPORTED_CRITICAL_FAST_OPTIONS 0xbfff0000 +#define KRB5_FAST_OPTION_HIDE_CLIENT_NAMES 0x40000000 + +typedef struct _krb5_fast_finished { + krb5_timestamp timestamp; + krb5_int32 usec; + krb5_principal client; + krb5_checksum ticket_checksum; +} krb5_fast_finished; + +typedef struct _krb5_fast_response { + krb5_magic magic; + krb5_pa_data **padata; + krb5_keyblock *strengthen_key; + krb5_fast_finished *finished; + krb5_int32 nonce; +} krb5_fast_response; + +typedef struct _krb5_ad_kdcissued { + krb5_checksum ad_checksum; + krb5_principal i_principal; + krb5_authdata **elements; +} krb5_ad_kdcissued; + +typedef struct _krb5_iakerb_header { + krb5_data target_realm; + krb5_data *cookie; +} krb5_iakerb_header; + +typedef struct _krb5_iakerb_finished { + krb5_checksum checksum; +} krb5_iakerb_finished; + +typedef struct _krb5_verifier_mac { + krb5_principal princ; + krb5_kvno kvno; + krb5_enctype enctype; + krb5_checksum checksum; +} krb5_verifier_mac; + +/* + * AD-CAMMAC's other-verifiers field is a sequence of Verifier, which is an + * extensible choice with only one selection, Verifier-MAC. For the time being + * we will represent this field directly as an array of krb5_verifier_mac. + * That will have to change if other selections are added. + */ +typedef struct _krb5_cammac { + krb5_authdata **elements; + krb5_verifier_mac *kdc_verifier; + krb5_verifier_mac *svc_verifier; + krb5_verifier_mac **other_verifiers; +} krb5_cammac; + +void krb5_free_etype_info(krb5_context, krb5_etype_info); + +krb5_pa_data * +krb5int_find_pa_data(krb5_context, krb5_pa_data *const *, krb5_preauthtype); +/* Does not return a copy; original padata sequence responsible for freeing*/ + +/* Allocate a pa-data object with uninitialized contents of size len. If len + * is 0, set the contents field to NULL. */ +krb5_error_code +k5_alloc_pa_data(krb5_preauthtype pa_type, size_t len, krb5_pa_data **out); + +/* Free a single pa-data object. */ +void +k5_free_pa_data_element(krb5_pa_data *pa); + +/* Without copying, add single element *pa to *list, reallocating as necessary. + * If *list is NULL, allocate a new list. Set *pa to NULL on success. */ +krb5_error_code +k5_add_pa_data_element(krb5_pa_data ***list, krb5_pa_data **pa); + +/* Without copying, add a pa-data element of type pa_type to *list with the + * contents in data. Set *data to empty_data() on success. */ +krb5_error_code +k5_add_pa_data_from_data(krb5_pa_data ***list, krb5_preauthtype pa_type, + krb5_data *data); + +/* Add an empty pa-data element of type pa_type to *list. */ +krb5_error_code +k5_add_empty_pa_data(krb5_pa_data ***list, krb5_preauthtype pa_type); + +#endif /* KRB5_PREAUTH__ */ +/* + * End "preauth.h" + */ + +krb5_error_code +krb5int_copy_data_contents(krb5_context, const krb5_data *, krb5_data *); + +krb5_error_code +krb5int_copy_data_contents_add0(krb5_context, const krb5_data *, krb5_data *); + +void KRB5_CALLCONV +krb5_free_sam_challenge_2(krb5_context, krb5_sam_challenge_2 *); + +void KRB5_CALLCONV +krb5_free_sam_challenge_2_body(krb5_context, krb5_sam_challenge_2_body *); + +void KRB5_CALLCONV +krb5_free_sam_response_2(krb5_context, krb5_sam_response_2 *); + +void KRB5_CALLCONV +krb5_free_enc_sam_response_enc_2(krb5_context, krb5_enc_sam_response_enc_2 *); + +void KRB5_CALLCONV +krb5_free_sam_challenge_2_contents(krb5_context, krb5_sam_challenge_2 *); + +void KRB5_CALLCONV +krb5_free_sam_challenge_2_body_contents(krb5_context, + krb5_sam_challenge_2_body *); + +void KRB5_CALLCONV +krb5_free_sam_response_2_contents(krb5_context, krb5_sam_response_2 *); + +void KRB5_CALLCONV +krb5_free_enc_sam_response_enc_2_contents(krb5_context, + krb5_enc_sam_response_enc_2 * ); + +void KRB5_CALLCONV +krb5_free_pa_enc_ts(krb5_context, krb5_pa_enc_ts *); + +void KRB5_CALLCONV +krb5_free_pa_for_user(krb5_context, krb5_pa_for_user *); + +void KRB5_CALLCONV +krb5_free_s4u_userid_contents(krb5_context, krb5_s4u_userid *); + +void KRB5_CALLCONV +krb5_free_pa_s4u_x509_user(krb5_context, krb5_pa_s4u_x509_user *); + +void KRB5_CALLCONV +krb5_free_pa_pac_req(krb5_context, krb5_pa_pac_req * ); + +void KRB5_CALLCONV krb5_free_fast_armor(krb5_context, krb5_fast_armor *); +void KRB5_CALLCONV krb5_free_fast_armored_req(krb5_context, + krb5_fast_armored_req *); +void KRB5_CALLCONV krb5_free_fast_req(krb5_context, krb5_fast_req *); +void KRB5_CALLCONV krb5_free_fast_finished(krb5_context, krb5_fast_finished *); +void KRB5_CALLCONV krb5_free_fast_response(krb5_context, krb5_fast_response *); +void KRB5_CALLCONV krb5_free_ad_kdcissued(krb5_context, krb5_ad_kdcissued *); +void KRB5_CALLCONV krb5_free_iakerb_header(krb5_context, krb5_iakerb_header *); +void KRB5_CALLCONV krb5_free_iakerb_finished(krb5_context, + krb5_iakerb_finished *); +void k5_free_algorithm_identifier(krb5_context context, + krb5_algorithm_identifier *val); +void k5_free_otp_tokeninfo(krb5_context context, krb5_otp_tokeninfo *val); +void k5_free_pa_otp_challenge(krb5_context context, + krb5_pa_otp_challenge *val); +void k5_free_pa_otp_req(krb5_context context, krb5_pa_otp_req *val); +void k5_free_kkdcp_message(krb5_context context, krb5_kkdcp_message *val); +void k5_free_cammac(krb5_context context, krb5_cammac *val); +void k5_free_secure_cookie(krb5_context context, krb5_secure_cookie *val); + +krb5_error_code +k5_unwrap_cammac_svc(krb5_context context, const krb5_authdata *ad, + const krb5_keyblock *key, krb5_authdata ***adata_out); +krb5_error_code +k5_authind_decode(const krb5_authdata *ad, krb5_data ***indicators); + +/* #include "krb5/wordsize.h" -- comes in through base-defs.h. */ +#include "com_err.h" +#include "k5-plugin.h" + +#include + +struct _krb5_authdata_context { + krb5_magic magic; + int n_modules; + struct _krb5_authdata_context_module { + krb5_authdatatype ad_type; + void *plugin_context; + authdata_client_plugin_fini_proc client_fini; + krb5_flags flags; + krb5plugin_authdata_client_ftable_v0 *ftable; + authdata_client_request_init_proc client_req_init; + authdata_client_request_fini_proc client_req_fini; + const char *name; + void *request_context; + void **request_context_pp; + } *modules; + struct plugin_dir_handle plugins; +}; + +typedef struct _krb5_authdata_context *krb5_authdata_context; + +void +k5_free_data_ptr_list(krb5_data **list); + +void +k5_zapfree_pa_data(krb5_pa_data **val); + +void KRB5_CALLCONV +krb5int_free_data_list(krb5_context context, krb5_data *data); + +krb5_error_code KRB5_CALLCONV +krb5_authdata_context_init(krb5_context kcontext, + krb5_authdata_context *pcontext); + +void KRB5_CALLCONV +krb5_authdata_context_free(krb5_context kcontext, + krb5_authdata_context context); + +krb5_error_code KRB5_CALLCONV +krb5_authdata_export_authdata(krb5_context kcontext, + krb5_authdata_context context, krb5_flags usage, + krb5_authdata ***pauthdata); + +krb5_error_code KRB5_CALLCONV +krb5_authdata_get_attribute_types(krb5_context kcontext, + krb5_authdata_context context, + krb5_data **attrs); + +krb5_error_code KRB5_CALLCONV +krb5_authdata_get_attribute(krb5_context kcontext, + krb5_authdata_context context, + const krb5_data *attribute, + krb5_boolean *authenticated, + krb5_boolean *complete, krb5_data *value, + krb5_data *display_value, int *more); + +krb5_error_code KRB5_CALLCONV +krb5_authdata_set_attribute(krb5_context kcontext, + krb5_authdata_context context, + krb5_boolean complete, const krb5_data *attribute, + const krb5_data *value); + +krb5_error_code KRB5_CALLCONV +krb5_authdata_delete_attribute(krb5_context kcontext, + krb5_authdata_context context, + const krb5_data *attribute); + +krb5_error_code KRB5_CALLCONV +krb5_authdata_import_attributes(krb5_context kcontext, + krb5_authdata_context context, + krb5_flags usage, const krb5_data *attributes); + +krb5_error_code KRB5_CALLCONV +krb5_authdata_export_attributes(krb5_context kcontext, + krb5_authdata_context context, + krb5_flags usage, krb5_data **pattributes); + +krb5_error_code KRB5_CALLCONV +krb5_authdata_export_internal(krb5_context kcontext, + krb5_authdata_context context, + krb5_boolean restrict_authenticated, + const char *module, void **ptr); + +krb5_error_code KRB5_CALLCONV +krb5_authdata_context_copy(krb5_context kcontext, krb5_authdata_context src, + krb5_authdata_context *dst); + +krb5_error_code KRB5_CALLCONV +krb5_authdata_free_internal(krb5_context kcontext, + krb5_authdata_context context, const char *module, + void *ptr); + +/*** Plugin framework ***/ + +/* + * This framework can be used to create pluggable interfaces. Not all existing + * pluggable interface use this framework, but new ones should. A new + * pluggable interface entails: + * + * - An interface ID definition in the list of #defines below. + * + * - A name in the interface_names array in lib/krb5/krb/plugins.c. + * + * - An installed public header file in include/krb5. The public header should + * include and should declare a vtable structure for each + * supported major version of the interface. + * + * - A consumer API implementation, located within the code unit which makes + * use of the pluggable interface. The consumer API should consist of: + * + * . An interface-specific handle type which contains a vtable structure for + * the module (or a union of several such structures, if there are multiple + * supported major versions) and, optionally, resource data bound to the + * handle. + * + * . An interface-specific loader function which creates a handle or list of + * handles. A list of handles would be created if the interface is a + * one-to-many interface where the consumer wants to consult all available + * modules; a single handle would be created for an interface where the + * consumer wants to consult a specific module. The loader function should + * use k5_plugin_load or k5_plugin_load_all to produce one or a list of + * vtable initializer functions, and should use those functions to fill in + * the vtable structure for the module (if necessary, trying each supported + * major version starting from the most recent). The loader function can + * also bind resource data into the handle based on caller arguments, if + * appropriate. + * + * . For each plugin method, a wrapper function which accepts a krb5_context, + * a plugin handle, and the method arguments. Wrapper functions should + * invoke the method function contained in the handle's vtable. + * + * - Possibly, built-in implementations of the interface, also located within + * the code unit which makes use of the interface. Built-in implementations + * must be registered with k5_plugin_register before the first call to + * k5_plugin_load or k5_plugin_load_all. + * + * A pluggable interface should have one or more currently supported major + * versions, starting at 1. Each major version should have a current minor + * version, also starting at 1. If new methods are added to a vtable, the + * minor version should be incremented and the vtable structure should document + * where each minor vtable version ends. If method signatures for a vtable are + * changed, the major version should be incremented. + * + * Plugin module implementations (either built-in or dynamically loaded) should + * define a function named __initvt, matching the + * signature of krb5_plugin_initvt_fn as declared in include/krb5/plugin.h. + * The initvt function should check the given maj_ver argument against its own + * supported major versions, cast the vtable pointer to the appropriate + * interface-specific vtable type, and fill in the vtable methods, stopping as + * appropriate for the given min_ver. Memory for the vtable structure is + * allocated by the caller, not by the module. + * + * Dynamic plugin modules are registered with the framework through the + * [plugins] section of the profile, as described in the admin documentation + * and krb5.conf man page. + */ + +struct plugin_mapping; + +/* Holds krb5_context information about each pluggable interface. */ +struct plugin_interface { + struct plugin_mapping **modules; + krb5_boolean configured; +}; + +/* A list of plugin interface IDs. Make sure to increment + * PLUGIN_NUM_INTERFACES when a new interface is added, and add an entry to the + * interface_names table in lib/krb5/krb/plugin.c. */ +#define PLUGIN_INTERFACE_PWQUAL 0 +#define PLUGIN_INTERFACE_KADM5_HOOK 1 +#define PLUGIN_INTERFACE_CLPREAUTH 2 +#define PLUGIN_INTERFACE_KDCPREAUTH 3 +#define PLUGIN_INTERFACE_CCSELECT 4 +#define PLUGIN_INTERFACE_LOCALAUTH 5 +#define PLUGIN_INTERFACE_HOSTREALM 6 +#define PLUGIN_INTERFACE_AUDIT 7 +#define PLUGIN_INTERFACE_TLS 8 +#define PLUGIN_INTERFACE_KDCAUTHDATA 9 +#define PLUGIN_INTERFACE_CERTAUTH 10 +#define PLUGIN_INTERFACE_KADM5_AUTH 11 +#define PLUGIN_INTERFACE_KDCPOLICY 12 +#define PLUGIN_NUM_INTERFACES 13 + +/* Retrieve the plugin module of type interface_id and name modname, + * storing the result into module. */ +krb5_error_code +k5_plugin_load(krb5_context context, int interface_id, const char *modname, + krb5_plugin_initvt_fn *module); + +/* Retrieve all plugin modules of type interface_id, storing the result + * into modules. Free the result with k5_plugin_free_handles. */ +krb5_error_code +k5_plugin_load_all(krb5_context context, int interface_id, + krb5_plugin_initvt_fn **modules); + +/* Release a module list allocated by k5_plugin_load_all. */ +void +k5_plugin_free_modules(krb5_context context, krb5_plugin_initvt_fn *modules); + +/* Register a plugin module of type interface_id and name modname. */ +krb5_error_code +k5_plugin_register(krb5_context context, int interface_id, const char *modname, + krb5_plugin_initvt_fn module); + +/* + * Register a plugin module which is part of the krb5 tree but is built as a + * dynamic plugin. Look for the module in modsubdir relative to the + * context->base_plugin_dir. + */ +krb5_error_code +k5_plugin_register_dyn(krb5_context context, int interface_id, + const char *modname, const char *modsubdir); + +/* Destroy the module state within context; used by krb5_free_context. */ +void +k5_plugin_free_context(krb5_context context); + +enum dns_canonhost { + CANONHOST_FALSE = 0, + CANONHOST_TRUE = 1, + CANONHOST_FALLBACK = 2 +}; + +struct _kdb5_dal_handle; /* private, in kdb5.h */ +typedef struct _kdb5_dal_handle kdb5_dal_handle; +struct _kdb_log_context; +typedef struct krb5_preauth_context_st *krb5_preauth_context; +struct ccselect_module_handle; +struct localauth_module_handle; +struct hostrealm_module_handle; +struct k5_tls_vtable_st; +struct _krb5_context { + krb5_magic magic; + krb5_enctype *tgs_etypes; + struct _krb5_os_context os_context; + char *default_realm; + profile_t profile; + kdb5_dal_handle *dal_handle; + /* allowable clock skew */ + krb5_deltat clockskew; + krb5_flags kdc_default_options; + krb5_flags library_options; + krb5_boolean profile_secure; + int fcc_default_format; + krb5_prompt_type *prompt_types; + /* Message size above which we'll try TCP first in send-to-kdc + type code. Aside from the 2**16 size limit, we put no + absolute limit on the UDP packet size. */ + int udp_pref_limit; + + /* Use the config-file ktypes instead of app-specified? */ + krb5_boolean use_conf_ktypes; + + /* locate_kdc module stuff */ + struct plugin_dir_handle libkrb5_plugins; + + /* preauth module stuff */ + krb5_preauth_context preauth_context; + + /* cache module stuff */ + struct ccselect_module_handle **ccselect_handles; + + /* localauth module stuff */ + struct localauth_module_handle **localauth_handles; + + /* hostrealm module stuff */ + struct hostrealm_module_handle **hostrealm_handles; + + /* TLS module vtable (if loaded) */ + struct k5_tls_vtable_st *tls; + + /* error detail info */ + struct errinfo err; + char *err_fmt; + + /* For Sun iprop code; does this really have to be here? */ + struct _kdb_log_context *kdblog_context; + + krb5_boolean allow_weak_crypto; + krb5_boolean allow_des3; + krb5_boolean allow_rc4; + krb5_boolean ignore_acceptor_hostname; + krb5_boolean enforce_ok_as_delegate; + enum dns_canonhost dns_canonicalize_hostname; + + krb5_trace_callback trace_callback; + void *trace_callback_data; + + krb5_pre_send_fn kdc_send_hook; + void *kdc_send_hook_data; + + krb5_post_recv_fn kdc_recv_hook; + void *kdc_recv_hook_data; + + struct plugin_interface plugins[PLUGIN_NUM_INTERFACES]; + char *plugin_base_dir; +}; + +/* could be used in a table to find an etype and initialize a block */ + + +#define KRB5_LIBOPT_SYNC_KDCTIME 0x0001 + +/* internal message representations */ + +typedef struct _krb5_safe { + krb5_magic magic; + krb5_data user_data; /* user data */ + krb5_timestamp timestamp; /* client time, optional */ + krb5_int32 usec; /* microsecond portion of time, + optional */ + krb5_ui_4 seq_number; /* sequence #, optional */ + krb5_address *s_address; /* sender address */ + krb5_address *r_address; /* recipient address, optional */ + krb5_checksum *checksum; /* data integrity checksum */ +} krb5_safe; + +typedef struct _krb5_priv { + krb5_magic magic; + krb5_enc_data enc_part; /* encrypted part */ +} krb5_priv; + +typedef struct _krb5_priv_enc_part { + krb5_magic magic; + krb5_data user_data; /* user data */ + krb5_timestamp timestamp; /* client time, optional */ + krb5_int32 usec; /* microsecond portion of time, opt. */ + krb5_ui_4 seq_number; /* sequence #, optional */ + krb5_address *s_address; /* sender address */ + krb5_address *r_address; /* recipient address, optional */ +} krb5_priv_enc_part; + +void KRB5_CALLCONV krb5_free_safe(krb5_context, krb5_safe *); +void KRB5_CALLCONV krb5_free_priv(krb5_context, krb5_priv *); +void KRB5_CALLCONV krb5_free_priv_enc_part(krb5_context, krb5_priv_enc_part *); + +/* + * Begin "asn1.h" + */ +#ifndef KRB5_ASN1__ +#define KRB5_ASN1__ + +/* ASN.1 encoding knowledge; KEEP IN SYNC WITH ASN.1 defs! */ +/* here we use some knowledge of ASN.1 encodings */ +/* + Ticket is APPLICATION 1. + Authenticator is APPLICATION 2. + AS_REQ is APPLICATION 10. + AS_REP is APPLICATION 11. + TGS_REQ is APPLICATION 12. + TGS_REP is APPLICATION 13. + AP_REQ is APPLICATION 14. + AP_REP is APPLICATION 15. + KRB_SAFE is APPLICATION 20. + KRB_PRIV is APPLICATION 21. + KRB_CRED is APPLICATION 22. + EncASRepPart is APPLICATION 25. + EncTGSRepPart is APPLICATION 26. + EncAPRepPart is APPLICATION 27. + EncKrbPrivPart is APPLICATION 28. + EncKrbCredPart is APPLICATION 29. + KRB_ERROR is APPLICATION 30. +*/ +/* allow either constructed or primitive encoding, so check for bit 6 + set or reset */ +#define krb5int_is_app_tag(dat,tag) \ + ((dat != NULL) && (dat)->length && \ + ((((dat)->data[0] & ~0x20) == ((tag) | 0x40)))) +#define krb5_is_krb_ticket(dat) krb5int_is_app_tag(dat, 1) +#define krb5_is_krb_authenticator(dat) krb5int_is_app_tag(dat, 2) +#define krb5_is_as_req(dat) krb5int_is_app_tag(dat, 10) +#define krb5_is_as_rep(dat) krb5int_is_app_tag(dat, 11) +#define krb5_is_tgs_req(dat) krb5int_is_app_tag(dat, 12) +#define krb5_is_tgs_rep(dat) krb5int_is_app_tag(dat, 13) +#define krb5_is_ap_req(dat) krb5int_is_app_tag(dat, 14) +#define krb5_is_ap_rep(dat) krb5int_is_app_tag(dat, 15) +#define krb5_is_krb_safe(dat) krb5int_is_app_tag(dat, 20) +#define krb5_is_krb_priv(dat) krb5int_is_app_tag(dat, 21) +#define krb5_is_krb_cred(dat) krb5int_is_app_tag(dat, 22) +#define krb5_is_krb_enc_as_rep_part(dat) krb5int_is_app_tag(dat, 25) +#define krb5_is_krb_enc_tgs_rep_part(dat) krb5int_is_app_tag(dat, 26) +#define krb5_is_krb_enc_ap_rep_part(dat) krb5int_is_app_tag(dat, 27) +#define krb5_is_krb_enc_krb_priv_part(dat) krb5int_is_app_tag(dat, 28) +#define krb5_is_krb_enc_krb_cred_part(dat) krb5int_is_app_tag(dat, 29) +#define krb5_is_krb_error(dat) krb5int_is_app_tag(dat, 30) + +/************************************************************************* + * Prototypes for krb5_encode.c + *************************************************************************/ + +/* + krb5_error_code encode_krb5_structure(const krb5_structure *rep, + krb5_data **code); + modifies *code + effects Returns the ASN.1 encoding of *rep in **code. + Returns ASN1_MISSING_FIELD if a required field is empty in *rep. + Returns ENOMEM if memory runs out. +*/ + +krb5_error_code +encode_krb5_authenticator(const krb5_authenticator *rep, krb5_data **code); + +krb5_error_code +encode_krb5_ticket(const krb5_ticket *rep, krb5_data **code); + +krb5_error_code +encode_krb5_enc_tkt_part(const krb5_enc_tkt_part *rep, krb5_data **code); + +krb5_error_code +encode_krb5_enc_kdc_rep_part(const krb5_enc_kdc_rep_part *rep, + krb5_data **code); + +/* yes, the translation is identical to that used for KDC__REP */ +krb5_error_code +encode_krb5_as_rep(const krb5_kdc_rep *rep, krb5_data **code); + +/* yes, the translation is identical to that used for KDC__REP */ +krb5_error_code +encode_krb5_tgs_rep(const krb5_kdc_rep *rep, krb5_data **code); + +krb5_error_code +encode_krb5_ap_req(const krb5_ap_req *rep, krb5_data **code); + +krb5_error_code +encode_krb5_ap_rep(const krb5_ap_rep *rep, krb5_data **code); + +krb5_error_code +encode_krb5_ap_rep_enc_part(const krb5_ap_rep_enc_part *rep, krb5_data **code); + +krb5_error_code +encode_krb5_as_req(const krb5_kdc_req *rep, krb5_data **code); + +krb5_error_code +encode_krb5_tgs_req(const krb5_kdc_req *rep, krb5_data **code); + +krb5_error_code +encode_krb5_kdc_req_body(const krb5_kdc_req *rep, krb5_data **code); + +krb5_error_code +encode_krb5_safe(const krb5_safe *rep, krb5_data **code); + +struct krb5_safe_with_body { + krb5_safe *safe; + krb5_data *body; +}; +krb5_error_code +encode_krb5_safe_with_body(const struct krb5_safe_with_body *rep, + krb5_data **code); + +krb5_error_code +encode_krb5_priv(const krb5_priv *rep, krb5_data **code); + +krb5_error_code +encode_krb5_enc_priv_part(const krb5_priv_enc_part *rep, krb5_data **code); + +krb5_error_code +encode_krb5_cred(const krb5_cred *rep, krb5_data **code); +krb5_error_code +encode_krb5_checksum(const krb5_checksum *, krb5_data **); + +krb5_error_code +encode_krb5_enc_cred_part(const krb5_cred_enc_part *rep, krb5_data **code); + +krb5_error_code +encode_krb5_error(const krb5_error *rep, krb5_data **code); + +krb5_error_code +encode_krb5_authdata(krb5_authdata *const *rep, krb5_data **code); + +krb5_error_code +encode_krb5_padata_sequence(krb5_pa_data *const *rep, krb5_data **code); + +krb5_error_code +encode_krb5_typed_data(krb5_pa_data *const *rep, krb5_data **code); + +krb5_error_code +encode_krb5_etype_info(krb5_etype_info_entry *const *, krb5_data **code); + +krb5_error_code +encode_krb5_etype_info2(krb5_etype_info_entry *const *, krb5_data **code); + +krb5_error_code +encode_krb5_pa_enc_ts(const krb5_pa_enc_ts *, krb5_data **); + +krb5_error_code +encode_krb5_sam_challenge_2(const krb5_sam_challenge_2 * , krb5_data **); + +krb5_error_code +encode_krb5_sam_challenge_2_body(const krb5_sam_challenge_2_body *, + krb5_data **); + +krb5_error_code +encode_krb5_enc_sam_response_enc_2(const krb5_enc_sam_response_enc_2 *, + krb5_data **); + +krb5_error_code +encode_krb5_sam_response_2(const krb5_sam_response_2 * , krb5_data **); + +struct krb5_setpw_req { + krb5_principal target; + krb5_data password; +}; +krb5_error_code +encode_krb5_setpw_req(const struct krb5_setpw_req *rep, krb5_data **code); + +krb5_error_code +encode_krb5_pa_for_user(const krb5_pa_for_user *, krb5_data **); + +krb5_error_code +encode_krb5_s4u_userid(const krb5_s4u_userid *, krb5_data **); + +krb5_error_code +encode_krb5_pa_s4u_x509_user(const krb5_pa_s4u_x509_user *, krb5_data **); + +krb5_error_code +encode_krb5_pa_pac_req(const krb5_pa_pac_req *, krb5_data **); + +krb5_error_code +encode_krb5_etype_list(const krb5_etype_list * , krb5_data **); + +krb5_error_code +encode_krb5_pa_fx_fast_request(const krb5_fast_armored_req *, krb5_data **); + +krb5_error_code +encode_krb5_fast_req(const krb5_fast_req *, krb5_data **); + +krb5_error_code +encode_krb5_pa_fx_fast_reply(const krb5_enc_data *, krb5_data **); + +krb5_error_code +encode_krb5_iakerb_header(const krb5_iakerb_header *, krb5_data **); + +krb5_error_code +encode_krb5_iakerb_finished(const krb5_iakerb_finished *, krb5_data **); + +krb5_error_code +encode_krb5_fast_response(const krb5_fast_response *, krb5_data **); + +krb5_error_code +encode_krb5_ad_kdcissued(const krb5_ad_kdcissued *, krb5_data **); + +krb5_error_code +encode_krb5_otp_tokeninfo(const krb5_otp_tokeninfo *, krb5_data **); + +krb5_error_code +encode_krb5_pa_otp_challenge(const krb5_pa_otp_challenge *, krb5_data **); + +krb5_error_code +encode_krb5_pa_otp_req(const krb5_pa_otp_req *, krb5_data **); + +krb5_error_code +encode_krb5_pa_otp_enc_req(const krb5_data *, krb5_data **); + +krb5_error_code +encode_krb5_kkdcp_message(const krb5_kkdcp_message *, krb5_data **); + +krb5_error_code +encode_krb5_cammac(const krb5_cammac *, krb5_data **); + +krb5_error_code +encode_utf8_strings(krb5_data *const *ut8fstrings, krb5_data **); + +krb5_error_code +encode_krb5_secure_cookie(const krb5_secure_cookie *, krb5_data **); + +krb5_error_code +encode_krb5_pa_pac_options(const krb5_pa_pac_options *, krb5_data **); + +/************************************************************************* + * End of prototypes for krb5_encode.c + *************************************************************************/ + +krb5_error_code +decode_krb5_sam_challenge_2(const krb5_data *, krb5_sam_challenge_2 **); + +krb5_error_code +decode_krb5_sam_challenge_2_body(const krb5_data *, + krb5_sam_challenge_2_body **); + +krb5_error_code +decode_krb5_enc_sam_response_enc_2(const krb5_data *, + krb5_enc_sam_response_enc_2 **); + +krb5_error_code +decode_krb5_sam_response_2(const krb5_data *, krb5_sam_response_2 **); + + +/************************************************************************* + * Prototypes for krb5_decode.c + *************************************************************************/ +/* + krb5_error_code decode_krb5_structure(const krb5_data *code, + krb5_structure **rep); + + requires Expects **rep to not have been allocated; + a new *rep is allocated regardless of the old value. + effects Decodes *code into **rep. + Returns ENOMEM if memory is exhausted. + Returns asn1 and krb5 errors. +*/ + +krb5_error_code +decode_krb5_authenticator(const krb5_data *code, krb5_authenticator **rep); + +krb5_error_code +decode_krb5_ticket(const krb5_data *code, krb5_ticket **rep); + +krb5_error_code +decode_krb5_encryption_key(const krb5_data *output, krb5_keyblock **rep); + +krb5_error_code +decode_krb5_enc_tkt_part(const krb5_data *output, krb5_enc_tkt_part **rep); + +krb5_error_code +decode_krb5_enc_kdc_rep_part(const krb5_data *output, + krb5_enc_kdc_rep_part **rep); + +krb5_error_code +decode_krb5_as_rep(const krb5_data *output, krb5_kdc_rep **rep); + +krb5_error_code +decode_krb5_tgs_rep(const krb5_data *output, krb5_kdc_rep **rep); + +krb5_error_code +decode_krb5_ap_req(const krb5_data *output, krb5_ap_req **rep); + +krb5_error_code +decode_krb5_ap_rep(const krb5_data *output, krb5_ap_rep **rep); + +krb5_error_code +decode_krb5_ap_rep_enc_part(const krb5_data *output, + krb5_ap_rep_enc_part **rep); + +krb5_error_code +decode_krb5_as_req(const krb5_data *output, krb5_kdc_req **rep); + +krb5_error_code +decode_krb5_tgs_req(const krb5_data *output, krb5_kdc_req **rep); + +krb5_error_code +decode_krb5_kdc_req_body(const krb5_data *output, krb5_kdc_req **rep); + +krb5_error_code +decode_krb5_safe(const krb5_data *output, krb5_safe **rep); + +krb5_error_code +decode_krb5_safe_with_body(const krb5_data *output, krb5_safe **rep, + krb5_data **body); + +krb5_error_code +decode_krb5_priv(const krb5_data *output, krb5_priv **rep); + +krb5_error_code +decode_krb5_enc_priv_part(const krb5_data *output, krb5_priv_enc_part **rep); +krb5_error_code +decode_krb5_checksum(const krb5_data *, krb5_checksum **); + +krb5_error_code +decode_krb5_cred(const krb5_data *output, krb5_cred **rep); + +krb5_error_code +decode_krb5_enc_cred_part(const krb5_data *output, krb5_cred_enc_part **rep); + +krb5_error_code +decode_krb5_error(const krb5_data *output, krb5_error **rep); + +krb5_error_code +decode_krb5_authdata(const krb5_data *output, krb5_authdata ***rep); + +krb5_error_code +decode_krb5_padata_sequence(const krb5_data *output, krb5_pa_data ***rep); + +krb5_error_code +decode_krb5_typed_data(const krb5_data *, krb5_pa_data ***); + +krb5_error_code +decode_krb5_etype_info(const krb5_data *output, krb5_etype_info_entry ***rep); + +krb5_error_code +decode_krb5_etype_info2(const krb5_data *output, krb5_etype_info_entry ***rep); + +krb5_error_code +decode_krb5_enc_data(const krb5_data *output, krb5_enc_data **rep); + +krb5_error_code +decode_krb5_pa_enc_ts(const krb5_data *output, krb5_pa_enc_ts **rep); + +krb5_error_code +decode_krb5_setpw_req(const krb5_data *, krb5_data **, krb5_principal *); + +krb5_error_code +decode_krb5_pa_for_user(const krb5_data *, krb5_pa_for_user **); + +krb5_error_code +decode_krb5_pa_s4u_x509_user(const krb5_data *, krb5_pa_s4u_x509_user **); + +krb5_error_code +decode_krb5_pa_pac_req(const krb5_data *, krb5_pa_pac_req **); + +krb5_error_code +decode_krb5_etype_list(const krb5_data *, krb5_etype_list **); + +krb5_error_code +decode_krb5_pa_fx_fast_request(const krb5_data *, krb5_fast_armored_req **); + +krb5_error_code +decode_krb5_fast_req(const krb5_data *, krb5_fast_req **); + +krb5_error_code +decode_krb5_pa_fx_fast_reply(const krb5_data *, krb5_enc_data **); + +krb5_error_code +decode_krb5_fast_response(const krb5_data *, krb5_fast_response **); + +krb5_error_code +decode_krb5_ad_kdcissued(const krb5_data *, krb5_ad_kdcissued **); + +krb5_error_code +decode_krb5_iakerb_header(const krb5_data *, krb5_iakerb_header **); + +krb5_error_code +decode_krb5_iakerb_finished(const krb5_data *, krb5_iakerb_finished **); + +krb5_error_code +decode_krb5_otp_tokeninfo(const krb5_data *, krb5_otp_tokeninfo **); + +krb5_error_code +decode_krb5_pa_otp_challenge(const krb5_data *, krb5_pa_otp_challenge **); + +krb5_error_code +decode_krb5_pa_otp_req(const krb5_data *, krb5_pa_otp_req **); + +krb5_error_code +decode_krb5_pa_otp_enc_req(const krb5_data *, krb5_data **); + +krb5_error_code +decode_krb5_kkdcp_message(const krb5_data *, krb5_kkdcp_message **); + +krb5_error_code +decode_krb5_cammac(const krb5_data *, krb5_cammac **); + +krb5_error_code +decode_utf8_strings(const krb5_data *, krb5_data ***); + +krb5_error_code +decode_krb5_secure_cookie(const krb5_data *, krb5_secure_cookie **); + +krb5_error_code +decode_krb5_pa_pac_options(const krb5_data *, krb5_pa_pac_options **); + +struct _krb5_key_data; /* kdb.h */ + +struct ldap_seqof_key_data { + krb5_int32 mkvno; /* Master key version number */ + krb5_ui_2 kvno; /* kvno of key_data elements (all the same) */ + struct _krb5_key_data *key_data; + krb5_int16 n_key_data; +}; +typedef struct ldap_seqof_key_data ldap_seqof_key_data; + +krb5_error_code +krb5int_ldap_encode_sequence_of_keys(const ldap_seqof_key_data *val, + krb5_data **code); + +krb5_error_code +krb5int_ldap_decode_sequence_of_keys(const krb5_data *in, + ldap_seqof_key_data **rep); + +/************************************************************************* + * End of prototypes for krb5_decode.c + *************************************************************************/ + +#endif /* KRB5_ASN1__ */ +/* + * End "asn1.h" + */ + + +/* + * Internal krb5 library routines + */ +krb5_error_code +krb5_encrypt_tkt_part(krb5_context, const krb5_keyblock *, krb5_ticket *); + +krb5_error_code +krb5_encode_kdc_rep(krb5_context, krb5_msgtype, const krb5_enc_kdc_rep_part *, + int using_subkey, const krb5_keyblock *, krb5_kdc_rep *, + krb5_data ** ); + +/* Return true if s is non-empty and composed solely of digits. */ +krb5_boolean +k5_is_string_numeric(const char *s); + +krb5_error_code +k5_parse_host_string(const char *address, int default_port, char **host_out, + int *port_out); + +krb5_error_code +k5_size_authdata_context(krb5_context kcontext, krb5_authdata_context context, + size_t *sizep); + +krb5_error_code +k5_externalize_authdata_context(krb5_context kcontext, + krb5_authdata_context context, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_internalize_authdata_context(krb5_context kcontext, + krb5_authdata_context *ptr, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_size_auth_context(krb5_auth_context auth_context, size_t *sizep); + +krb5_error_code +k5_externalize_auth_context(krb5_auth_context auth_context, + krb5_octet **buffer, size_t *lenremain); +krb5_error_code +k5_internalize_auth_context(krb5_auth_context *argp, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_size_authdata(krb5_authdata *authdata, size_t *sizep); + +krb5_error_code +k5_externalize_authdata(krb5_authdata *authdata, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_internalize_authdata(krb5_authdata **authdata, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_size_address(krb5_address *address, size_t *sizep); + +krb5_error_code +k5_externalize_address(krb5_address *address, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_internalize_address(krb5_address **argp, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_size_authenticator(krb5_authenticator *authenticator, size_t *sizep); + +krb5_error_code +k5_externalize_authenticator(krb5_authenticator *authenticator, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_internalize_authenticator(krb5_authenticator **argp, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_size_checksum(krb5_checksum *checksum, size_t *sizep); + +krb5_error_code +k5_externalize_checksum(krb5_checksum *checksum, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_internalize_checksum(krb5_checksum **argp, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_size_context(krb5_context context, size_t *sizep); + +krb5_error_code +k5_externalize_context(krb5_context context, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_internalize_context(krb5_context *argp, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_size_keyblock(krb5_keyblock *keyblock, size_t *sizep); + +krb5_error_code +k5_externalize_keyblock(krb5_keyblock *keyblock, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_internalize_keyblock(krb5_keyblock **argp, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_size_principal(krb5_principal principal, size_t *sizep); + +krb5_error_code +k5_externalize_principal(krb5_principal principal, + krb5_octet **buffer, size_t *lenremain); + +krb5_error_code +k5_internalize_principal(krb5_principal *argp, + krb5_octet **buffer, size_t *lenremain); + +/* + * Initialization routines. + */ + +/* [De]serialize 4-byte integer */ +krb5_error_code KRB5_CALLCONV +krb5_ser_pack_int32(krb5_int32, krb5_octet **, size_t *); + +krb5_error_code KRB5_CALLCONV +krb5_ser_unpack_int32(krb5_int32 *, krb5_octet **, size_t *); + +/* [De]serialize 8-byte integer */ +krb5_error_code KRB5_CALLCONV +krb5_ser_pack_int64(int64_t, krb5_octet **, size_t *); + +krb5_error_code KRB5_CALLCONV +krb5_ser_unpack_int64(int64_t *, krb5_octet **, size_t *); + +/* [De]serialize byte string */ +krb5_error_code KRB5_CALLCONV +krb5_ser_pack_bytes(krb5_octet *, size_t, krb5_octet **, size_t *); + +krb5_error_code KRB5_CALLCONV +krb5_ser_unpack_bytes(krb5_octet *, size_t, krb5_octet **, size_t *); + +krb5_error_code KRB5_CALLCONV +krb5int_cc_default(krb5_context, krb5_ccache *); + +krb5_error_code +k5_cc_store_primary_cred(krb5_context, krb5_ccache, krb5_creds *); + +/* Fill in the buffer with random alphanumeric data. */ +krb5_error_code +krb5int_random_string(krb5_context, char *string, unsigned int length); + +/* value to use when requesting a keytab entry and KVNO doesn't matter */ +#define IGNORE_VNO 0 +/* value to use when requesting a keytab entry and enctype doesn't matter */ +#define IGNORE_ENCTYPE 0 + +/* To keep happy libraries which are (for now) accessing internal stuff */ + +/* Make sure to increment by one when changing the struct */ +#define KRB5INT_ACCESS_STRUCT_VERSION 23 + +typedef struct _krb5int_access { + krb5_error_code (*auth_con_get_subkey_enctype)(krb5_context, + krb5_auth_context, + krb5_enctype *); + + krb5_error_code (*mandatory_cksumtype)(krb5_context, krb5_enctype, + krb5_cksumtype *); + krb5_error_code (KRB5_CALLCONV *ser_pack_int64)(int64_t, krb5_octet **, + size_t *); + krb5_error_code (KRB5_CALLCONV *ser_unpack_int64)(int64_t *, krb5_octet **, + size_t *); + + /* Used for KDB LDAP back end. */ + krb5_error_code + (*asn1_ldap_encode_sequence_of_keys)(const ldap_seqof_key_data *val, + krb5_data **code); + + krb5_error_code + (*asn1_ldap_decode_sequence_of_keys)(const krb5_data *in, + ldap_seqof_key_data **); + + /* + * pkinit asn.1 encode/decode functions + */ + krb5_error_code + (*encode_krb5_auth_pack)(const krb5_auth_pack *rep, krb5_data **code); + + krb5_error_code + (*encode_krb5_kdc_dh_key_info)(const krb5_kdc_dh_key_info *rep, + krb5_data **code); + + krb5_error_code + (*encode_krb5_pa_pk_as_rep)(const krb5_pa_pk_as_rep *rep, + krb5_data **code); + + krb5_error_code + (*encode_krb5_pa_pk_as_req)(const krb5_pa_pk_as_req *rep, + krb5_data **code); + + krb5_error_code + (*encode_krb5_reply_key_pack)(const krb5_reply_key_pack *, + krb5_data **code); + + krb5_error_code + (*encode_krb5_td_dh_parameters)(krb5_algorithm_identifier *const *, + krb5_data **code); + + krb5_error_code + (*encode_krb5_td_trusted_certifiers)(krb5_external_principal_identifier * + const *, krb5_data **code); + + krb5_error_code + (*decode_krb5_auth_pack)(const krb5_data *, krb5_auth_pack **); + + krb5_error_code + (*decode_krb5_pa_pk_as_req)(const krb5_data *, krb5_pa_pk_as_req **); + + krb5_error_code + (*decode_krb5_pa_pk_as_rep)(const krb5_data *, krb5_pa_pk_as_rep **); + + krb5_error_code + (*decode_krb5_kdc_dh_key_info)(const krb5_data *, krb5_kdc_dh_key_info **); + + krb5_error_code + (*decode_krb5_principal_name)(const krb5_data *, krb5_principal_data **); + + krb5_error_code + (*decode_krb5_reply_key_pack)(const krb5_data *, krb5_reply_key_pack **); + + krb5_error_code + (*decode_krb5_td_dh_parameters)(const krb5_data *, + krb5_algorithm_identifier ***); + + krb5_error_code + (*decode_krb5_td_trusted_certifiers)(const krb5_data *, + krb5_external_principal_identifier + ***); + + krb5_error_code + (*encode_krb5_kdc_req_body)(const krb5_kdc_req *rep, krb5_data **code); + + void + (KRB5_CALLCONV *free_kdc_req)(krb5_context, krb5_kdc_req * ); + void + (*set_prompt_types)(krb5_context, krb5_prompt_type *); +} krb5int_access; + +#define KRB5INT_ACCESS_VERSION \ + (((krb5_int32)((sizeof(krb5int_access) & 0xFFFF) | \ + (KRB5INT_ACCESS_STRUCT_VERSION << 16))) & 0xFFFFFFFF) + +krb5_error_code KRB5_CALLCONV +krb5int_accessor(krb5int_access*, krb5_int32); + +krb5_error_code KRB5_CALLCONV +krb5int_cc_user_set_default_name(krb5_context context, const char *name); + +krb5_error_code k5_rc_default(krb5_context context, krb5_rcache *rc_out); +krb5_error_code k5_rc_resolve(krb5_context context, const char *name, + krb5_rcache *rc_out); +void k5_rc_close(krb5_context context, krb5_rcache rc); +krb5_error_code k5_rc_store(krb5_context context, krb5_rcache rc, + const krb5_enc_data *authenticator); +const char *k5_rc_get_name(krb5_context context, krb5_rcache rc); + +/* Set *tag_out to the integrity tag of *enc. (Does not allocate memory; + * returned buffer is a subrange of *ctext.) */ +krb5_error_code +k5_rc_tag_from_ciphertext(krb5_context context, const krb5_enc_data *enc, + krb5_data *tag_out); + +/* + * This structure was exposed and used in macros in krb5 1.2, so do not + * change its ABI. + */ +typedef struct _krb5_kt_ops { + krb5_magic magic; + char *prefix; + + /* routines always present */ + krb5_error_code (KRB5_CALLCONV *resolve)(krb5_context, const char *, + krb5_keytab *); + krb5_error_code (KRB5_CALLCONV *get_name)(krb5_context, krb5_keytab, + char *, unsigned int); + krb5_error_code (KRB5_CALLCONV *close)(krb5_context, krb5_keytab); + krb5_error_code (KRB5_CALLCONV *get)(krb5_context, krb5_keytab, + krb5_const_principal, krb5_kvno, + krb5_enctype, krb5_keytab_entry *); + krb5_error_code (KRB5_CALLCONV *start_seq_get)(krb5_context, krb5_keytab, + krb5_kt_cursor *); + krb5_error_code (KRB5_CALLCONV *get_next)(krb5_context, krb5_keytab, + krb5_keytab_entry *, + krb5_kt_cursor *); + krb5_error_code (KRB5_CALLCONV *end_get)(krb5_context, krb5_keytab, + krb5_kt_cursor *); + /* routines to be included on extended version (write routines) */ + krb5_error_code (KRB5_CALLCONV *add)(krb5_context, krb5_keytab, + krb5_keytab_entry *); + krb5_error_code (KRB5_CALLCONV *remove)(krb5_context, krb5_keytab, + krb5_keytab_entry *); +} krb5_kt_ops; + +/* Not sure it's ready for exposure just yet. */ +extern krb5_error_code +krb5int_c_mandatory_cksumtype(krb5_context, krb5_enctype, krb5_cksumtype *); + +/* + * Referral definitions and subfunctions. + */ +#define KRB5_REFERRAL_MAXHOPS 10 + +struct _krb5_kt { /* should move into k5-int.h */ + krb5_magic magic; + const struct _krb5_kt_ops *ops; + krb5_pointer data; +}; + +krb5_error_code krb5_get_default_in_tkt_ktypes(krb5_context, krb5_enctype **); + +krb5_error_code KRB5_CALLCONV +krb5_get_tgs_ktypes(krb5_context, krb5_const_principal, krb5_enctype **); + +krb5_boolean krb5_is_permitted_enctype(krb5_context, krb5_enctype); + +krb5_boolean KRB5_CALLCONV krb5int_c_weak_enctype(krb5_enctype); +krb5_boolean KRB5_CALLCONV krb5int_c_deprecated_enctype(krb5_enctype); +krb5_error_code k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out); + +krb5_error_code krb5_kdc_rep_decrypt_proc(krb5_context, const krb5_keyblock *, + krb5_const_pointer, krb5_kdc_rep *); +krb5_error_code KRB5_CALLCONV krb5_decrypt_tkt_part(krb5_context, + const krb5_keyblock *, + krb5_ticket * ); + +krb5_error_code krb5_get_cred_via_tkt(krb5_context, krb5_creds *, krb5_flags, + krb5_address *const *, krb5_creds *, + krb5_creds **); + +krb5_error_code KRB5_CALLCONV krb5_copy_addr(krb5_context, + const krb5_address *, + krb5_address **); + +void krb5_init_ets(krb5_context); +void krb5_free_ets(krb5_context); +krb5_error_code krb5_generate_subkey(krb5_context, const krb5_keyblock *, + krb5_keyblock **); +krb5_error_code krb5_generate_subkey_extended(krb5_context, + const krb5_keyblock *, + krb5_enctype, krb5_keyblock **); +krb5_error_code krb5_generate_seq_number(krb5_context, const krb5_keyblock *, + krb5_ui_4 *); + +krb5_error_code KRB5_CALLCONV krb5_kt_register(krb5_context, + const struct _krb5_kt_ops *); + +krb5_error_code k5_kt_get_principal(krb5_context context, krb5_keytab keytab, + krb5_principal *princ_out); + +krb5_error_code k5_kt_have_match(krb5_context context, krb5_keytab keytab, + krb5_principal mprinc); + +krb5_error_code krb5_principal2salt_norealm(krb5_context, krb5_const_principal, + krb5_data *); + +unsigned int KRB5_CALLCONV krb5_get_notification_message(void); + +/* chk_trans.c */ +krb5_error_code krb5_check_transited_list(krb5_context, const krb5_data *trans, + const krb5_data *realm1, + const krb5_data *realm2); + +/* free_rtree.c */ +void krb5_free_realm_tree(krb5_context, krb5_principal *); + +void KRB5_CALLCONV krb5_free_authenticator_contents(krb5_context, + krb5_authenticator *); + +void KRB5_CALLCONV krb5_free_address(krb5_context, krb5_address *); + +void KRB5_CALLCONV krb5_free_enc_tkt_part(krb5_context, krb5_enc_tkt_part *); + +void KRB5_CALLCONV krb5_free_tickets(krb5_context, krb5_ticket **); +void KRB5_CALLCONV krb5_free_kdc_req(krb5_context, krb5_kdc_req *); +void KRB5_CALLCONV krb5_free_kdc_rep(krb5_context, krb5_kdc_rep *); +void KRB5_CALLCONV krb5_free_last_req(krb5_context, krb5_last_req_entry **); +void KRB5_CALLCONV krb5_free_enc_kdc_rep_part(krb5_context, + krb5_enc_kdc_rep_part *); +void KRB5_CALLCONV krb5_free_ap_req(krb5_context, krb5_ap_req *); +void KRB5_CALLCONV krb5_free_ap_rep(krb5_context, krb5_ap_rep *); +void KRB5_CALLCONV krb5_free_cred(krb5_context, krb5_cred *); +void KRB5_CALLCONV krb5_free_cred_enc_part(krb5_context, krb5_cred_enc_part *); +void KRB5_CALLCONV krb5_free_pa_data(krb5_context, krb5_pa_data **); +void KRB5_CALLCONV krb5_free_tkt_authent(krb5_context, krb5_tkt_authent *); +void KRB5_CALLCONV krb5_free_enc_data(krb5_context, krb5_enc_data *); +krb5_error_code krb5_set_config_files(krb5_context, const char **); + +krb5_error_code KRB5_CALLCONV krb5_get_default_config_files(char ***filenames); + +void KRB5_CALLCONV krb5_free_config_files(char **filenames); + +krb5_error_code krb5_rd_req_decoded(krb5_context, krb5_auth_context *, + const krb5_ap_req *, krb5_const_principal, + krb5_keytab, krb5_flags *, krb5_ticket **); + +krb5_error_code krb5_rd_req_decoded_anyflag(krb5_context, krb5_auth_context *, + const krb5_ap_req *, + krb5_const_principal, krb5_keytab, + krb5_flags *, krb5_ticket **); + +krb5_error_code KRB5_CALLCONV +krb5_cc_register(krb5_context, const krb5_cc_ops *, krb5_boolean ); + +krb5_error_code krb5_walk_realm_tree(krb5_context, const krb5_data *, + const krb5_data *, krb5_principal **, + int); + +krb5_error_code +krb5_auth_con_set_safe_cksumtype(krb5_context, krb5_auth_context, + krb5_cksumtype); + +krb5_error_code krb5_auth_con_setivector(krb5_context, krb5_auth_context, + krb5_pointer); + +krb5_error_code krb5_auth_con_getivector(krb5_context, krb5_auth_context, + krb5_pointer *); + +krb5_error_code krb5_auth_con_setpermetypes(krb5_context, krb5_auth_context, + const krb5_enctype *); + +krb5_error_code krb5_auth_con_getpermetypes(krb5_context, krb5_auth_context, + krb5_enctype **); + +krb5_error_code krb5_auth_con_get_subkey_enctype(krb5_context context, + krb5_auth_context, + krb5_enctype *); + +krb5_error_code +krb5_auth_con_get_authdata_context(krb5_context context, + krb5_auth_context auth_context, + krb5_authdata_context *ad_context); + +krb5_error_code +krb5_auth_con_set_authdata_context(krb5_context context, + krb5_auth_context auth_context, + krb5_authdata_context ad_context); + +krb5_error_code krb5_read_message(krb5_context, krb5_pointer, krb5_data *); +krb5_error_code krb5_write_message(krb5_context, krb5_pointer, krb5_data *); +int krb5_net_read(krb5_context, int , char *, int); +int krb5_net_write(krb5_context, int , const char *, int); + +krb5_error_code KRB5_CALLCONV krb5_get_realm_domain(krb5_context, + const char *, char ** ); + +krb5_error_code krb5_gen_portaddr(krb5_context, const krb5_address *, + krb5_const_pointer, krb5_address **); + +krb5_error_code krb5_gen_replay_name(krb5_context, const krb5_address *, + const char *, char **); +krb5_error_code krb5_make_fulladdr(krb5_context, krb5_address *, + krb5_address *, krb5_address *); + +krb5_error_code krb5_set_debugging_time(krb5_context, krb5_timestamp, + krb5_int32); +krb5_error_code krb5_use_natural_time(krb5_context); +krb5_error_code krb5_set_time_offsets(krb5_context, krb5_timestamp, + krb5_int32); + +/* Some data comparison and conversion functions. */ +static inline int +data_eq(krb5_data d1, krb5_data d2) +{ + return (d1.length == d2.length && (d1.length == 0 || + !memcmp(d1.data, d2.data, d1.length))); +} + +static inline int +data_eq_string (krb5_data d, const char *s) +{ + return (d.length == strlen(s) && (d.length == 0 || + !memcmp(d.data, s, d.length))); +} + +static inline krb5_data +make_data(void *data, unsigned int len) +{ + krb5_data d; + + d.magic = KV5M_DATA; + d.data = (char *) data; + d.length = len; + return d; +} + +static inline krb5_data +empty_data() +{ + return make_data(NULL, 0); +} + +static inline krb5_data +string2data(char *str) +{ + return make_data(str, strlen(str)); +} + +static inline krb5_error_code +alloc_data(krb5_data *data, unsigned int len) +{ + /* Allocate at least one byte since zero-byte allocs may return NULL. */ + char *ptr = (char *) calloc((len > 0) ? len : 1, 1); + + if (ptr == NULL) + return ENOMEM; + data->magic = KV5M_DATA; + data->data = ptr; + data->length = len; + return 0; +} + +static inline int +authdata_eq(krb5_authdata a1, krb5_authdata a2) +{ + return (a1.ad_type == a2.ad_type && a1.length == a2.length && + (a1.length == 0 || !memcmp(a1.contents, a2.contents, a1.length))); +} + +/* Allocate zeroed memory; set *code to 0 on success or ENOMEM on failure. */ +static inline void * +k5calloc(size_t nmemb, size_t size, krb5_error_code *code) +{ + void *ptr; + + /* Allocate at least one byte since zero-byte allocs may return NULL. */ + ptr = calloc(nmemb ? nmemb : 1, size ? size : 1); + *code = (ptr == NULL) ? ENOMEM : 0; + return ptr; +} + +/* Allocate zeroed memory; set *code to 0 on success or ENOMEM on failure. */ +static inline void * +k5alloc(size_t size, krb5_error_code *code) +{ + return k5calloc(1, size, code); +} + +/* Return a copy of the len bytes of memory at in; set *code to 0 or ENOMEM. */ +static inline void * +k5memdup(const void *in, size_t len, krb5_error_code *code) +{ + void *ptr = k5alloc(len, code); + + if (ptr != NULL && len > 0) + memcpy(ptr, in, len); + return ptr; +} + +/* Like k5memdup, but add a final null byte. */ +static inline void * +k5memdup0(const void *in, size_t len, krb5_error_code *code) +{ + void *ptr = k5alloc(len + 1, code); + + if (ptr != NULL && len > 0) + memcpy(ptr, in, len); + return ptr; +} + +/* Convert a krb5_timestamp to a time_t value, treating the negative range of + * krb5_timestamp as times between 2038 and 2106 (if time_t is 64-bit). */ +static inline time_t +ts2tt(krb5_timestamp timestamp) +{ + return (time_t)(uint32_t)timestamp; +} + +/* Return the delta between two timestamps (a - b) as a signed 32-bit value, + * without relying on undefined behavior. */ +static inline krb5_deltat +ts_delta(krb5_timestamp a, krb5_timestamp b) +{ + return (krb5_deltat)((uint32_t)a - (uint32_t)b); +} + +/* Return (end - start) as an unsigned 32-bit value, or 0 if start > end. */ +static inline uint32_t +ts_interval(krb5_timestamp start, krb5_timestamp end) +{ + if ((uint32_t)start > (uint32_t)end) + return 0; + return (uint32_t)end - (uint32_t)start; +} + +/* Increment a timestamp by a signed 32-bit interval, without relying on + * undefined behavior. */ +static inline krb5_timestamp +ts_incr(krb5_timestamp ts, krb5_deltat delta) +{ + return (krb5_timestamp)((uint32_t)ts + (uint32_t)delta); +} + +/* Return true if a comes after b. */ +static inline krb5_boolean +ts_after(krb5_timestamp a, krb5_timestamp b) +{ + return (uint32_t)a > (uint32_t)b; +} + +/* Return true if a and b are within d seconds. */ +static inline krb5_boolean +ts_within(krb5_timestamp a, krb5_timestamp b, krb5_deltat d) +{ + return !ts_after(a, ts_incr(b, d)) && !ts_after(b, ts_incr(a, d)); +} + +krb5_error_code KRB5_CALLCONV +krb5_get_credentials_for_user(krb5_context context, krb5_flags options, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_data *cert, + krb5_creds **out_creds); + +krb5_error_code KRB5_CALLCONV +krb5_get_credentials_for_proxy(krb5_context context, + krb5_flags options, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_ticket *evidence_tkt, + krb5_creds **out_creds); + +krb5_error_code KRB5_CALLCONV +krb5int_get_authdata_containee_types(krb5_context context, + const krb5_authdata *container, + unsigned int *nad_types, + krb5_authdatatype **ad_types); + +krb5_error_code krb5int_parse_enctype_list(krb5_context context, + const char *profkey, char *profstr, + krb5_enctype *default_list, + krb5_enctype **result); + +krb5_boolean k5_etypes_contains(const krb5_enctype *list, krb5_enctype etype); + +void k5_change_error_message_code(krb5_context ctx, krb5_error_code oldcode, + krb5_error_code newcode); + +/* Define shorter internal names for setting error messages. */ +#define k5_setmsg krb5_set_error_message +#define k5_prependmsg krb5_prepend_error_message +#define k5_wrapmsg krb5_wrap_error_message + +/* + * Like krb5_principal_compare(), but with canonicalization of sname if + * fallback is enabled. This function should be avoided if multiple matches + * are required, since repeated canonicalization is inefficient. + */ +krb5_boolean +k5_sname_compare(krb5_context context, krb5_const_principal sname, + krb5_const_principal princ); + +#endif /* _KRB5_INT_H */ diff --git a/krb5-1.21.3/src/include/k5-ipc_stream.h b/krb5-1.21.3/src/include/k5-ipc_stream.h new file mode 100644 index 00000000..11f8bc76 --- /dev/null +++ b/krb5-1.21.3/src/include/k5-ipc_stream.h @@ -0,0 +1,77 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-ipc_stream.h */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef K5_IPC_STREAM_H +#define K5_IPC_STREAM_H + +#include "k5-platform.h" + +struct k5_ipc_stream_s; +typedef struct k5_ipc_stream_s *k5_ipc_stream; + + +int32_t krb5int_ipc_stream_new (k5_ipc_stream *out_stream); + +uint32_t krb5int_ipc_stream_release (k5_ipc_stream io_stream); + +uint64_t krb5int_ipc_stream_size (k5_ipc_stream in_stream); + +const char *krb5int_ipc_stream_data (k5_ipc_stream in_stream); + +uint32_t krb5int_ipc_stream_read (k5_ipc_stream in_stream, + void *io_data, + uint64_t in_size); +uint32_t krb5int_ipc_stream_write (k5_ipc_stream in_stream, + const void *in_data, + uint64_t in_size); + +uint32_t krb5int_ipc_stream_read_string (k5_ipc_stream io_stream, + char **out_string); +uint32_t krb5int_ipc_stream_write_string (k5_ipc_stream io_stream, + const char *in_string); +void krb5int_ipc_stream_free_string (char *in_string); + +uint32_t krb5int_ipc_stream_read_int32 (k5_ipc_stream io_stream, + int32_t *out_int32); +uint32_t krb5int_ipc_stream_write_int32 (k5_ipc_stream io_stream, + int32_t in_int32); + +uint32_t krb5int_ipc_stream_read_uint32 (k5_ipc_stream io_stream, + uint32_t *out_uint32); +uint32_t krb5int_ipc_stream_write_uint32 (k5_ipc_stream io_stream, + uint32_t in_uint32); + +uint32_t krb5int_ipc_stream_read_int64 (k5_ipc_stream io_stream, + int64_t *out_int64); +uint32_t krb5int_ipc_stream_write_int64 (k5_ipc_stream io_stream, + int64_t in_int64); + +uint32_t krb5int_ipc_stream_read_uint64 (k5_ipc_stream io_stream, + uint64_t *out_uint64); +uint32_t krb5int_ipc_stream_write_uint64 (k5_ipc_stream io_stream, + uint64_t in_uint64); + +#endif /* K5_IPC_STREAM_H */ diff --git a/krb5-1.21.3/src/include/k5-json.h b/krb5-1.21.3/src/include/k5-json.h new file mode 100644 index 00000000..8b22cd39 --- /dev/null +++ b/krb5-1.21.3/src/include/k5-json.h @@ -0,0 +1,218 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-json.h - JSON declarations */ +/* + * Copyright (c) 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2010 Apple Inc. 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. + */ +/* + * Copyright (C) 2012 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. + */ + +#ifndef K5_JSON_H +#define K5_JSON_H + +#include + +#define K5_JSON_TID_NUMBER 0 +#define K5_JSON_TID_NULL 1 +#define K5_JSON_TID_BOOL 2 +#define K5_JSON_TID_MEMORY 128 +#define K5_JSON_TID_ARRAY 129 +#define K5_JSON_TID_OBJECT 130 +#define K5_JSON_TID_STRING 131 + +/* + * The k5_json_value C type can represent any kind of JSON value. It has no + * static type safety since it is represented using a void pointer, so be + * careful with it. Its type can be checked dynamically with k5_json_get_tid() + * and the above constants. + */ +typedef void *k5_json_value; +typedef unsigned int k5_json_tid; + +k5_json_tid k5_json_get_tid(k5_json_value val); + +/* + * k5_json_value objects are reference-counted. These functions increment and + * decrement the refcount, possibly freeing the value. k5_json_retain returns + * its argument and always succeeds. Both functions gracefully accept NULL. + */ +k5_json_value k5_json_retain(k5_json_value val); +void k5_json_release(k5_json_value val); + +/* + * If a k5_json_* function can fail, it returns 0 on success and an errno value + * on failure. + */ + +/* + * Null + */ + +typedef struct k5_json_null_st *k5_json_null; + +int k5_json_null_create(k5_json_null *null_out); + +/* Create a null value as a k5_json_value, for polymorphic convenience. */ +int k5_json_null_create_val(k5_json_value *val_out); + +/* + * Boolean + */ + +typedef struct k5_json_bool_st *k5_json_bool; + +int k5_json_bool_create(int truth, k5_json_bool *val_out); +int k5_json_bool_value(k5_json_bool bval); + +/* + * Array + */ + +typedef struct k5_json_array_st *k5_json_array; + +int k5_json_array_create(k5_json_array *val_out); +size_t k5_json_array_length(k5_json_array array); + +/* Both of these functions increment the reference count on val. */ +int k5_json_array_add(k5_json_array array, k5_json_value val); +void k5_json_array_set(k5_json_array array, size_t idx, k5_json_value val); + +/* Get an alias to the idx-th element of array, without incrementing the + * reference count. The caller must check idx against the array length. */ +k5_json_value k5_json_array_get(k5_json_array array, size_t idx); + +/* + * Create an array from a template and a variable argument list. template + * characters are: + * v: a k5_json_value argument is read, retained, and stored + * n: no argument is read; a null value is stored + * b: an int argument is read and stored as a boolean value + * i: an int argument is read and stored as a number value + * L: a long long argument is read and stored as a number value + * s: a const char * argument is read and stored as a null or string value + * B: const void * and size_t arguments are read and stored as a base64 + * string value + */ +int +k5_json_array_fmt(k5_json_array *array_out, const char *template, ...); + +/* + * Object + */ + +typedef struct k5_json_object_st *k5_json_object; +typedef void (*k5_json_object_iterator_fn)(void *arg, const char *key, + k5_json_value val); + +int k5_json_object_create(k5_json_object *val_out); +void k5_json_object_iterate(k5_json_object obj, + k5_json_object_iterator_fn func, void *arg); + +/* Return the number of mappings in an object. */ +size_t k5_json_object_count(k5_json_object obj); + +/* + * Store val into object at key, incrementing val's reference count and + * releasing any previous value at key. If val is NULL, key is removed from + * obj if it exists, and obj remains unchanged if it does not. + */ +int k5_json_object_set(k5_json_object obj, const char *key, k5_json_value val); + +/* Get an alias to the object's value for key, without incrementing the + * reference count. Returns NULL if there is no value for key. */ +k5_json_value k5_json_object_get(k5_json_object obj, const char *key); + +/* + * String + */ + +typedef struct k5_json_string_st *k5_json_string; + +int k5_json_string_create(const char *cstring, k5_json_string *val_out); +int k5_json_string_create_len(const void *data, size_t len, + k5_json_string *val_out); +const char *k5_json_string_utf8(k5_json_string string); + + +/* Create a base64 string value from binary data. */ +int k5_json_string_create_base64(const void *data, size_t len, + k5_json_string *val_out); + +/* Decode the base64 contents of string. */ +int k5_json_string_unbase64(k5_json_string string, unsigned char **data_out, + size_t *len_out); + +/* + * Number + */ + +typedef struct k5_json_number_st *k5_json_number; + +int k5_json_number_create(long long number, k5_json_number *val_out); +long long k5_json_number_value(k5_json_number number); + +/* + * JSON encoding and decoding + */ + +int k5_json_encode(k5_json_value val, char **json_out); +int k5_json_decode(const char *str, k5_json_value *val_out); + +#endif /* K5_JSON_H */ diff --git a/krb5-1.21.3/src/include/k5-platform.h b/krb5-1.21.3/src/include/k5-platform.h new file mode 100644 index 00000000..11249317 --- /dev/null +++ b/krb5-1.21.3/src/include/k5-platform.h @@ -0,0 +1,1151 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* include/k5-platform.h */ +/* + * Copyright 2003, 2004, 2005, 2007, 2008, 2009 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Some platform-dependent definitions to sync up the C support level. + * Some to a C99-ish level, some related utility code. + * + * Currently: + * + [u]int{8,16,32}_t types + * + 64-bit types and load/store code + * + SIZE_MAX + * + shared library init/fini hooks + * + consistent getpwnam/getpwuid interfaces + * + va_copy fudged if not provided + * + strlcpy/strlcat + * + fnmatch + * + [v]asprintf + * + strerror_r + * + mkstemp + * + zap (support function and macro) + * + constant time memory comparison + * + path manipulation + * + _, N_, dgettext, bindtextdomain (for localization) + * + getopt_long + * + secure_getenv + * + fetching filenames from a directory + */ + +#ifndef K5_PLATFORM_H +#define K5_PLATFORM_H + +#include "autoconf.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_FNMATCH_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef _WIN32 +#define CAN_COPY_VA_LIST +#endif + +/* This attribute prevents unused function warnings in gcc and clang. */ +#ifdef __GNUC__ +#define UNUSED __attribute__((__unused__)) +#else +#define UNUSED +#endif + +#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__)) +#include +#endif + +/* Initialization and finalization function support for libraries. + + At top level, before the functions are defined or even declared: + MAKE_INIT_FUNCTION(init_fn); + MAKE_FINI_FUNCTION(fini_fn); + Then: + int init_fn(void) { ... } + void fini_fn(void) { if (INITIALIZER_RAN(init_fn)) ... } + In code, in the same file: + err = CALL_INIT_FUNCTION(init_fn); + + To trigger or verify the initializer invocation from another file, + a helper function must be created. + + This model handles both the load-time execution (Windows) and + delayed execution (pthread_once) approaches, and should be able to + guarantee in both cases that the init function is run once, in one + thread, before other stuff in the library is done; furthermore, the + finalization code should only run if the initialization code did. + (Maybe I could've made the "if INITIALIZER_RAN" test implicit, via + another function hidden in macros, but this is hairy enough + already.) + + The init_fn and fini_fn names should be chosen such that any + exported names staring with those names, and optionally followed by + additional characters, fits in with any namespace constraints on + the library in question. + + + There's also PROGRAM_EXITING() currently always defined as zero. + If there's some trivial way to find out if the fini function is + being called because the program that the library is linked into is + exiting, we can just skip all the work because the resources are + about to be freed up anyways. Generally this is likely to be the + same as distinguishing whether the library was loaded dynamically + while the program was running, or loaded as part of program + startup. On most platforms, I don't think we can distinguish these + cases easily, and it's probably not worth expending any significant + effort. (Note in particular that atexit() won't do, because if the + library is explicitly loaded and unloaded, it would have to be able + to deregister the atexit callback function. Also, the system limit + on atexit callbacks may be small.) + + + Implementation outline: + + Windows: MAKE_FINI_FUNCTION creates a symbol with a magic name that + is sought at library build time, and code is added to invoke the + function when the library is unloaded. MAKE_INIT_FUNCTION does + likewise, but the function is invoked when the library is loaded, + and an extra variable is declared to hold an error code and a "yes + the initializer ran" flag. CALL_INIT_FUNCTION blows up if the flag + isn't set, otherwise returns the error code. + + UNIX: MAKE_INIT_FUNCTION creates and initializes a variable with a + name derived from the function name, containing a k5_once_t + (pthread_once_t or int), an error code, and a pointer to the + function. The function itself is declared static, but the + associated variable has external linkage. CALL_INIT_FUNCTION + ensures thath the function is called exactly once (pthread_once or + just check the flag) and returns the stored error code (or the + pthread_once error). + + (That's the basic idea. With some debugging assert() calls and + such, it's a bit more complicated. And we also need to handle + doing the pthread test at run time on systems where that works, so + we use the k5_once_t stuff instead.) + + UNIX, with compiler support: MAKE_FINI_FUNCTION declares the + function as a destructor, and the run time linker support or + whatever will cause it to be invoked when the library is unloaded, + the program ends, etc. + + UNIX, with linker support: MAKE_FINI_FUNCTION creates a symbol with + a magic name that is sought at library build time, and linker + options are used to mark it as a finalization function for the + library. The symbol must be exported. + + UNIX, no library finalization support: The finalization function + never runs, and we leak memory. Tough. + + DELAY_INITIALIZER will be defined by the configure script if we + want to use k5_once instead of load-time initialization. That'll + be the preferred method on most systems except Windows, where we + have to initialize some mutexes. + + + + + For maximum flexibility in defining the macros, the function name + parameter should be a simple name, not even a macro defined as + another name. The function should have a unique name, and should + conform to whatever namespace is used by the library in question. + (We do have export lists, but (1) they're not used for all + platforms, and (2) they're not used for static libraries.) + + If the macro expansion needs the function to have been declared, it + must include a declaration. If it is not necessary for the symbol + name to be exported from the object file, the macro should declare + it as "static". Hence the signature must exactly match "void + foo(void)". (ANSI C allows a static declaration followed by a + non-static one; the result is internal linkage.) The macro + expansion has to come before the function, because gcc apparently + won't act on "__attribute__((constructor))" if it comes after the + function definition. + + This is going to be compiler- and environment-specific, and may + require some support at library build time, and/or "asm" + statements. But through macro expansion and auxiliary functions, + we should be able to handle most things except #pragma. + + It's okay for this code to require that the library be built + with the same compiler and compiler options throughout, but + we shouldn't require that the library and application use the + same compiler. + + For static libraries, we don't really care about cleanup too much, + since it's all memory handling and mutex allocation which will all + be cleaned up when the program exits. Thus, it's okay if gcc-built + static libraries don't play nicely with cc-built executables when + it comes to static constructors, just as long as it doesn't cause + linking to fail. + + For dynamic libraries on UNIX, we'll use pthread_once-type support + to do delayed initialization, so if finalization can't be made to + work, we'll only have memory leaks in a load/use/unload cycle. If + anyone (like, say, the OS vendor) complains about this, they can + tell us how to get a shared library finalization function invoked + automatically. + + Currently there's --disable-delayed-initialization for preventing + the initialization from being delayed on UNIX, but that's mainly + just for testing the linker options for initialization, and will + probably be removed at some point. */ + +/* Helper macros. */ + +# define JOIN__2_2(A,B) A ## _ ## _ ## B +# define JOIN__2(A,B) JOIN__2_2(A,B) + +/* XXX Should test USE_LINKER_INIT_OPTION early, and if it's set, + always provide a function by the expected name, even if we're + delaying initialization. */ + +#if defined(DELAY_INITIALIZER) + +/* Run the initialization code during program execution, at the latest + possible moment. This means multiple threads may be active. */ +# include "k5-thread.h" +typedef struct { k5_once_t once; int error, did_run; void (*fn)(void); } k5_init_t; +# ifdef USE_LINKER_INIT_OPTION +# define MAYBE_DUMMY_INIT(NAME) \ + void JOIN__2(NAME, auxinit) () { } +# else +# define MAYBE_DUMMY_INIT(NAME) +# endif +# ifdef __GNUC__ +/* Do it in macro form so we get the file/line of the invocation if + the assertion fails. */ +# define k5_call_init_function(I) \ + (__extension__ ({ \ + k5_init_t *k5int_i = (I); \ + int k5int_err = k5_once(&k5int_i->once, k5int_i->fn); \ + (k5int_err \ + ? k5int_err \ + : (assert(k5int_i->did_run != 0), k5int_i->error)); \ + })) +# define MAYBE_DEFINE_CALLINIT_FUNCTION +# else +# define MAYBE_DEFINE_CALLINIT_FUNCTION \ + static inline int k5_call_init_function(k5_init_t *i) \ + { \ + int err; \ + err = k5_once(&i->once, i->fn); \ + if (err) \ + return err; \ + assert (i->did_run != 0); \ + return i->error; \ + } +# endif +# define MAKE_INIT_FUNCTION(NAME) \ + static int NAME(void); \ + MAYBE_DUMMY_INIT(NAME) \ + /* forward declaration for use in initializer */ \ + static void JOIN__2(NAME, aux) (void); \ + static k5_init_t JOIN__2(NAME, once) = \ + { K5_ONCE_INIT, 0, 0, JOIN__2(NAME, aux) }; \ + MAYBE_DEFINE_CALLINIT_FUNCTION \ + static void JOIN__2(NAME, aux) (void) \ + { \ + JOIN__2(NAME, once).did_run = 1; \ + JOIN__2(NAME, once).error = NAME(); \ + } \ + /* so ';' following macro use won't get error */ \ + static int NAME(void) +# define CALL_INIT_FUNCTION(NAME) \ + k5_call_init_function(& JOIN__2(NAME, once)) +/* This should be called in finalization only, so we shouldn't have + multiple active threads mucking around in our library at this + point. So ignore the once_t object and just look at the flag. + + XXX Could we have problems with memory coherence between processors + if we don't invoke mutex/once routines? Probably not, the + application code should already be coordinating things such that + the library code is not in use by this point, and memory + synchronization will be needed there. */ +# define INITIALIZER_RAN(NAME) \ + (JOIN__2(NAME, once).did_run && JOIN__2(NAME, once).error == 0) + +# define PROGRAM_EXITING() (0) + +#elif defined(__GNUC__) && !defined(_WIN32) && defined(CONSTRUCTOR_ATTR_WORKS) + +/* Run initializer at load time, via GCC/C++ hook magic. */ + +# ifdef USE_LINKER_INIT_OPTION + /* Both gcc and linker option?? Favor gcc. */ +# define MAYBE_DUMMY_INIT(NAME) \ + void JOIN__2(NAME, auxinit) () { } +# else +# define MAYBE_DUMMY_INIT(NAME) +# endif + +typedef struct { int error; unsigned char did_run; } k5_init_t; +# define MAKE_INIT_FUNCTION(NAME) \ + MAYBE_DUMMY_INIT(NAME) \ + static k5_init_t JOIN__2(NAME, ran) \ + = { 0, 2 }; \ + static void JOIN__2(NAME, aux)(void) \ + __attribute__((constructor)); \ + static int NAME(void); \ + static void JOIN__2(NAME, aux)(void) \ + { \ + JOIN__2(NAME, ran).error = NAME(); \ + JOIN__2(NAME, ran).did_run = 3; \ + } \ + static int NAME(void) +# define CALL_INIT_FUNCTION(NAME) \ + (JOIN__2(NAME, ran).did_run == 3 \ + ? JOIN__2(NAME, ran).error \ + : (abort(),0)) +# define INITIALIZER_RAN(NAME) (JOIN__2(NAME,ran).did_run == 3 && JOIN__2(NAME, ran).error == 0) + +# define PROGRAM_EXITING() (0) + +#elif defined(USE_LINKER_INIT_OPTION) || defined(_WIN32) + +/* Run initializer at load time, via linker magic, or in the + case of WIN32, win_glue.c hard-coded knowledge. */ +typedef struct { int error; unsigned char did_run; } k5_init_t; +# define MAKE_INIT_FUNCTION(NAME) \ + static k5_init_t JOIN__2(NAME, ran) \ + = { 0, 2 }; \ + static int NAME(void); \ + void JOIN__2(NAME, auxinit)() \ + { \ + JOIN__2(NAME, ran).error = NAME(); \ + JOIN__2(NAME, ran).did_run = 3; \ + } \ + static int NAME(void) +# define CALL_INIT_FUNCTION(NAME) \ + (JOIN__2(NAME, ran).did_run == 3 \ + ? JOIN__2(NAME, ran).error \ + : (abort(),0)) +# define INITIALIZER_RAN(NAME) \ + (JOIN__2(NAME, ran).error == 0) + +# define PROGRAM_EXITING() (0) + +#else + +# error "Don't know how to do load-time initializers for this configuration." + +# define PROGRAM_EXITING() (0) + +#endif + + + +#if defined(USE_LINKER_FINI_OPTION) || defined(_WIN32) +/* If we're told the linker option will be used, it doesn't really + matter what compiler we're using. Do it the same way + regardless. */ + +# ifdef __hpux + + /* On HP-UX, we need this auxiliary function. At dynamic load or + unload time (but *not* program startup and termination for + link-time specified libraries), the linker-indicated function + is called with a handle on the library and a flag indicating + whether it's being loaded or unloaded. + + The "real" fini function doesn't need to be exported, so + declare it static. + + As usual, the final declaration is just for syntactic + convenience, so the top-level invocation of this macro can be + followed by a semicolon. */ + +# include +# define MAKE_FINI_FUNCTION(NAME) \ + static void NAME(void); \ + void JOIN__2(NAME, auxfini)(shl_t, int); /* silence gcc warnings */ \ + void JOIN__2(NAME, auxfini)(shl_t h, int l) { if (!l) NAME(); } \ + static void NAME(void) + +# else /* not hpux */ + +# define MAKE_FINI_FUNCTION(NAME) \ + void NAME(void) + +# endif + +#elif !defined(SHARED) + +/* + * In this case, we just don't care about finalization. The code will still + * define the function, but we won't do anything with it. + */ +# define MAKE_FINI_FUNCTION(NAME) \ + static void NAME(void) UNUSED + +#elif defined(__GNUC__) && defined(DESTRUCTOR_ATTR_WORKS) +/* If we're using gcc, if the C++ support works, the compiler should + build executables and shared libraries that support the use of + static constructors and destructors. The C compiler supports a + function attribute that makes use of the same facility as C++. + + XXX How do we know if the C++ support actually works? */ +# define MAKE_FINI_FUNCTION(NAME) \ + static void NAME(void) __attribute__((destructor)) + +#else + +# error "Don't know how to do unload-time finalization for this configuration." + +#endif + +#ifndef SIZE_MAX +# define SIZE_MAX ((size_t)((size_t)0 - 1)) +#endif + +#ifdef _WIN32 +# define SSIZE_MAX ((ssize_t)(SIZE_MAX/2)) +#endif + +/* Read and write integer values as (unaligned) octet strings in + specific byte orders. Add per-platform optimizations as + needed. */ + +#if HAVE_ENDIAN_H +# include +#elif HAVE_MACHINE_ENDIAN_H +# include +#endif +/* Check for BIG/LITTLE_ENDIAN macros. If exactly one is defined, use + it. If both are defined, then BYTE_ORDER should be defined and + match one of them. Try those symbols, then try again with an + underscore prefix. */ +#if defined(BIG_ENDIAN) && defined(LITTLE_ENDIAN) +# if BYTE_ORDER == BIG_ENDIAN +# define K5_BE +# endif +# if BYTE_ORDER == LITTLE_ENDIAN +# define K5_LE +# endif +#elif defined(BIG_ENDIAN) +# define K5_BE +#elif defined(LITTLE_ENDIAN) +# define K5_LE +#elif defined(_BIG_ENDIAN) && defined(_LITTLE_ENDIAN) +# if _BYTE_ORDER == _BIG_ENDIAN +# define K5_BE +# endif +# if _BYTE_ORDER == _LITTLE_ENDIAN +# define K5_LE +# endif +#elif defined(_BIG_ENDIAN) +# define K5_BE +#elif defined(_LITTLE_ENDIAN) +# define K5_LE +#elif defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define K5_BE +#elif defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define K5_LE +#endif +#if !defined(K5_BE) && !defined(K5_LE) +/* Look for some architectures we know about. + + MIPS can use either byte order, but the preprocessor tells us which + mode we're compiling for. The GCC config files indicate that + variants of Alpha and IA64 might be out there with both byte + orders, but until we encounter the "wrong" ones in the real world, + just go with the default (unless there are cpp predefines to help + us there too). + + As far as I know, only PDP11 and ARM (which we don't handle here) + have strange byte orders where an 8-byte value isn't laid out as + either 12345678 or 87654321. */ +# if defined(__i386__) || defined(_MIPSEL) || defined(__alpha__) || (defined(__ia64__) && !defined(__hpux)) +# define K5_LE +# endif +# if defined(__hppa__) || defined(__rs6000__) || defined(__sparc__) || defined(_MIPSEB) || defined(__m68k__) || defined(__sparc64__) || defined(__ppc__) || defined(__ppc64__) || (defined(__hpux) && defined(__ia64__)) +# define K5_BE +# endif +#endif +#if defined(K5_BE) && defined(K5_LE) +# error "oops, check the byte order macros" +#endif + +/* Optimize for GCC on platforms with known byte orders. + + GCC's packed structures can be written to with any alignment; the + compiler will use byte operations, unaligned-word operations, or + normal memory ops as appropriate for the architecture. + + This assumes the availability of uint##_t types, which should work + on most of our platforms except Windows, where we're not using + GCC. */ +#ifdef __GNUC__ +# define PUT(SIZE,PTR,VAL) (((struct { uint##SIZE##_t i; } __attribute__((packed)) *)(PTR))->i = (VAL)) +# define GET(SIZE,PTR) (((const struct { uint##SIZE##_t i; } __attribute__((packed)) *)(PTR))->i) +# define PUTSWAPPED(SIZE,PTR,VAL) PUT(SIZE,PTR,SWAP##SIZE(VAL)) +# define GETSWAPPED(SIZE,PTR) SWAP##SIZE(GET(SIZE,PTR)) +#endif +/* To do: Define SWAP16, SWAP32, SWAP64 macros to byte-swap values + with the indicated numbers of bits. + + Linux: byteswap.h, bswap_16 etc. + Solaris 10: none + macOS: machine/endian.h or byte_order.h, NXSwap{Short,Int,LongLong} + NetBSD: sys/bswap.h, bswap16 etc. */ + +#if defined(HAVE_BYTESWAP_H) && defined(HAVE_BSWAP_16) +# include +# define SWAP16 bswap_16 +# define SWAP32 bswap_32 +# ifdef HAVE_BSWAP_64 +# define SWAP64 bswap_64 +# endif +#elif TARGET_OS_MAC +# include +# define SWAP16 k5_swap16 +static inline unsigned int k5_swap16 (unsigned int x) { + x &= 0xffff; + return (x >> 8) | ((x & 0xff) << 8); +} +# define SWAP32 OSSwapInt32 +# define SWAP64 OSSwapInt64 +#elif defined(HAVE_SYS_BSWAP_H) +/* XXX NetBSD/x86 5.0.1 defines bswap16 and bswap32 as inline + functions only, so autoconf doesn't pick up on their existence. + So, no feature macro test for them here. The 64-bit version isn't + inline at all, though, for whatever reason. */ +# include +# define SWAP16 bswap16 +# define SWAP32 bswap32 +/* However, bswap64 causes lots of warnings about 'long long' + constants; probably only on 32-bit platforms. */ +# if LONG_MAX > 0x7fffffffL +# define SWAP64 bswap64 +# endif +#endif + +/* Note that on Windows at least this file can be included from C++ + source, so casts *from* void* are required. */ +static inline void +store_16_be (unsigned int val, void *vp) +{ + unsigned char *p = (unsigned char *) vp; +#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus) + PUT(16,p,val); +#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16) && !defined(__cplusplus) + PUTSWAPPED(16,p,val); +#else + p[0] = (val >> 8) & 0xff; + p[1] = (val ) & 0xff; +#endif +} +static inline void +store_32_be (unsigned int val, void *vp) +{ + unsigned char *p = (unsigned char *) vp; +#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus) + PUT(32,p,val); +#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32) && !defined(__cplusplus) + PUTSWAPPED(32,p,val); +#else + p[0] = (val >> 24) & 0xff; + p[1] = (val >> 16) & 0xff; + p[2] = (val >> 8) & 0xff; + p[3] = (val ) & 0xff; +#endif +} +static inline void +store_64_be (uint64_t val, void *vp) +{ + unsigned char *p = (unsigned char *) vp; +#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus) + PUT(64,p,val); +#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64) && !defined(__cplusplus) + PUTSWAPPED(64,p,val); +#else + p[0] = (unsigned char)((val >> 56) & 0xff); + p[1] = (unsigned char)((val >> 48) & 0xff); + p[2] = (unsigned char)((val >> 40) & 0xff); + p[3] = (unsigned char)((val >> 32) & 0xff); + p[4] = (unsigned char)((val >> 24) & 0xff); + p[5] = (unsigned char)((val >> 16) & 0xff); + p[6] = (unsigned char)((val >> 8) & 0xff); + p[7] = (unsigned char)((val ) & 0xff); +#endif +} +static inline unsigned short +load_16_be (const void *cvp) +{ + const unsigned char *p = (const unsigned char *) cvp; +#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus) + return GET(16,p); +#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP16) && !defined(__cplusplus) + return GETSWAPPED(16,p); +#else + return (p[1] | (p[0] << 8)); +#endif +} +static inline unsigned int +load_32_be (const void *cvp) +{ + const unsigned char *p = (const unsigned char *) cvp; +#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus) + return GET(32,p); +#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP32) && !defined(__cplusplus) + return GETSWAPPED(32,p); +#else + return (p[3] | (p[2] << 8) + | ((uint32_t) p[1] << 16) + | ((uint32_t) p[0] << 24)); +#endif +} +static inline uint64_t +load_64_be (const void *cvp) +{ + const unsigned char *p = (const unsigned char *) cvp; +#if defined(__GNUC__) && defined(K5_BE) && !defined(__cplusplus) + return GET(64,p); +#elif defined(__GNUC__) && defined(K5_LE) && defined(SWAP64) && !defined(__cplusplus) + return GETSWAPPED(64,p); +#else + return ((uint64_t)load_32_be(p) << 32) | load_32_be(p+4); +#endif +} +static inline void +store_16_le (unsigned int val, void *vp) +{ + unsigned char *p = (unsigned char *) vp; +#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus) + PUT(16,p,val); +#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16) && !defined(__cplusplus) + PUTSWAPPED(16,p,val); +#else + p[1] = (val >> 8) & 0xff; + p[0] = (val ) & 0xff; +#endif +} +static inline void +store_32_le (unsigned int val, void *vp) +{ + unsigned char *p = (unsigned char *) vp; +#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus) + PUT(32,p,val); +#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32) && !defined(__cplusplus) + PUTSWAPPED(32,p,val); +#else + p[3] = (val >> 24) & 0xff; + p[2] = (val >> 16) & 0xff; + p[1] = (val >> 8) & 0xff; + p[0] = (val ) & 0xff; +#endif +} +static inline void +store_64_le (uint64_t val, void *vp) +{ + unsigned char *p = (unsigned char *) vp; +#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus) + PUT(64,p,val); +#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64) && !defined(__cplusplus) + PUTSWAPPED(64,p,val); +#else + p[7] = (unsigned char)((val >> 56) & 0xff); + p[6] = (unsigned char)((val >> 48) & 0xff); + p[5] = (unsigned char)((val >> 40) & 0xff); + p[4] = (unsigned char)((val >> 32) & 0xff); + p[3] = (unsigned char)((val >> 24) & 0xff); + p[2] = (unsigned char)((val >> 16) & 0xff); + p[1] = (unsigned char)((val >> 8) & 0xff); + p[0] = (unsigned char)((val ) & 0xff); +#endif +} +static inline unsigned short +load_16_le (const void *cvp) +{ + const unsigned char *p = (const unsigned char *) cvp; +#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus) + return GET(16,p); +#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP16) && !defined(__cplusplus) + return GETSWAPPED(16,p); +#else + return (p[0] | (p[1] << 8)); +#endif +} +static inline unsigned int +load_32_le (const void *cvp) +{ + const unsigned char *p = (const unsigned char *) cvp; +#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus) + return GET(32,p); +#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP32) && !defined(__cplusplus) + return GETSWAPPED(32,p); +#else + return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24)); +#endif +} +static inline uint64_t +load_64_le (const void *cvp) +{ + const unsigned char *p = (const unsigned char *) cvp; +#if defined(__GNUC__) && defined(K5_LE) && !defined(__cplusplus) + return GET(64,p); +#elif defined(__GNUC__) && defined(K5_BE) && defined(SWAP64) && !defined(__cplusplus) + return GETSWAPPED(64,p); +#else + return ((uint64_t)load_32_le(p+4) << 32) | load_32_le(p); +#endif +} + +#define UINT16_TYPE uint16_t +#define UINT32_TYPE uint32_t + +static inline void +store_16_n (unsigned int val, void *vp) +{ + UINT16_TYPE n = val; + memcpy(vp, &n, 2); +} +static inline void +store_32_n (unsigned int val, void *vp) +{ + UINT32_TYPE n = val; + memcpy(vp, &n, 4); +} +static inline void +store_64_n (uint64_t val, void *vp) +{ + uint64_t n = val; + memcpy(vp, &n, 8); +} +static inline unsigned short +load_16_n (const void *p) +{ + UINT16_TYPE n; + memcpy(&n, p, 2); + return n; +} +static inline unsigned int +load_32_n (const void *p) +{ + UINT32_TYPE n; + memcpy(&n, p, 4); + return n; +} +static inline uint64_t +load_64_n (const void *p) +{ + uint64_t n; + memcpy(&n, p, 8); + return n; +} +#undef UINT16_TYPE +#undef UINT32_TYPE + +/* Assume for simplicity that these swaps are identical. */ +static inline uint64_t +k5_htonll (uint64_t val) +{ +#ifdef K5_BE + return val; +#elif defined K5_LE && defined SWAP64 + return SWAP64 (val); +#else + return load_64_be ((unsigned char *)&val); +#endif +} +static inline uint64_t +k5_ntohll (uint64_t val) +{ + return k5_htonll (val); +} + +/* Make the interfaces to getpwnam and getpwuid consistent. + Model the wrappers on the POSIX thread-safe versions, but + use the unsafe system versions if the safe ones don't exist + or we can't figure out their interfaces. */ + +/* int k5_getpwnam_r(const char *, blah blah) */ +#ifdef HAVE_GETPWNAM_R +# ifndef GETPWNAM_R_4_ARGS +/* POSIX */ +# define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \ + (getpwnam_r(NAME,REC,BUF,BUFSIZE,OUT) == 0 \ + ? (*(OUT) == NULL ? -1 : 0) : -1) +# else +/* POSIX drafts? */ +# ifdef GETPWNAM_R_RETURNS_INT +# define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \ + (getpwnam_r(NAME,REC,BUF,BUFSIZE) == 0 \ + ? (*(OUT) = REC, 0) \ + : (*(OUT) = NULL, -1)) +# else +# define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \ + (*(OUT) = getpwnam_r(NAME,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0) +# endif +# endif +#else /* no getpwnam_r, or can't figure out #args or return type */ +/* Will get warnings about unused variables. */ +# define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \ + (*(OUT) = getpwnam(NAME), *(OUT) == NULL ? -1 : 0) +#endif + +/* int k5_getpwuid_r(uid_t, blah blah) */ +#ifdef HAVE_GETPWUID_R +# ifndef GETPWUID_R_4_ARGS +/* POSIX */ +# define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \ + (getpwuid_r(UID,REC,BUF,BUFSIZE,OUT) == 0 \ + ? (*(OUT) == NULL ? -1 : 0) : -1) +# else +/* POSIX drafts? Yes, I mean to test GETPWNAM... here. Less junk to + do at configure time. */ +# ifdef GETPWNAM_R_RETURNS_INT +# define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \ + (getpwuid_r(UID,REC,BUF,BUFSIZE) == 0 \ + ? (*(OUT) = REC, 0) \ + : (*(OUT) = NULL, -1)) +# else +# define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \ + (*(OUT) = getpwuid_r(UID,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0) +# endif +# endif +#else /* no getpwuid_r, or can't figure out #args or return type */ +/* Will get warnings about unused variables. */ +# define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \ + (*(OUT) = getpwuid(UID), *(OUT) == NULL ? -1 : 0) +#endif + +/* Ensure, if possible, that the indicated file descriptor won't be + kept open if we exec another process (e.g., launching a ccapi + server). If we don't know how to do it... well, just go about our + business. Probably most callers won't check the return status + anyways. */ + +/* Macros make the Sun compiler happier, and all variants of this do a + single evaluation of the argument, and fcntl and fileno should + produce reasonable error messages on type mismatches, on any system + with F_SETFD. */ +#ifdef F_SETFD +# ifdef FD_CLOEXEC +# define set_cloexec_fd(FD) ((void)fcntl((FD), F_SETFD, FD_CLOEXEC)) +# else +# define set_cloexec_fd(FD) ((void)fcntl((FD), F_SETFD, 1)) +# endif +#else +# define set_cloexec_fd(FD) ((void)(FD)) +#endif +#define set_cloexec_file(F) set_cloexec_fd(fileno(F)) + +/* Since the original ANSI C spec left it undefined whether or + how you could copy around a va_list, C 99 added va_copy. + For old implementations, let's do our best to fake it. + + XXX Doesn't yet handle implementations with __va_copy (early draft) + or GCC's __builtin_va_copy. */ +#if defined(HAS_VA_COPY) || defined(va_copy) +/* Do nothing. */ +#elif defined(CAN_COPY_VA_LIST) +#define va_copy(dest, src) ((dest) = (src)) +#else +/* Assume array type, but still simply copyable. + + There is, theoretically, the possibility that va_start will + allocate some storage pointed to by the va_list, and in that case + we'll just lose. If anyone cares, we could try to devise a test + for that case. */ +#define va_copy(dest, src) memcpy(dest, src, sizeof(va_list)) +#endif + +/* Provide strlcpy/strlcat interfaces. */ +#ifndef HAVE_STRLCPY +#define strlcpy krb5int_strlcpy +#define strlcat krb5int_strlcat +extern size_t krb5int_strlcpy(char *dst, const char *src, size_t siz); +extern size_t krb5int_strlcat(char *dst, const char *src, size_t siz); +#endif + +/* Provide fnmatch interface. */ +#ifndef HAVE_FNMATCH +#define fnmatch k5_fnmatch +int k5_fnmatch(const char *pattern, const char *string, int flags); +#define FNM_NOMATCH 1 /* Match failed. */ +#define FNM_NOSYS 2 /* Function not implemented. */ +#define FNM_NORES 3 /* Out of resources */ +#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ +#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ +#define FNM_PERIOD 0x04 /* Period must be matched by period. */ +#define FNM_CASEFOLD 0x08 /* Pattern is matched case-insensitive */ +#define FNM_LEADING_DIR 0x10 /* Ignore / after Imatch. */ +#endif + +/* Provide [v]asprintf interfaces. */ +#ifndef HAVE_VSNPRINTF +#ifdef _WIN32 +static inline int +vsnprintf(char *str, size_t size, const char *format, va_list args) +{ + va_list args_copy; + int length; + + va_copy(args_copy, args); + length = _vscprintf(format, args_copy); + va_end(args_copy); + if (size > 0) { + _vsnprintf(str, size, format, args); + str[size - 1] = '\0'; + } + return length; +} +static inline int +snprintf(char *str, size_t size, const char *format, ...) +{ + va_list args; + int n; + + va_start(args, format); + n = vsnprintf(str, size, format, args); + va_end(args); + return n; +} +#else /* not win32 */ +#error We need an implementation of vsnprintf. +#endif /* win32? */ +#endif /* no vsnprintf */ + +#ifndef HAVE_VASPRINTF + +extern int krb5int_vasprintf(char **, const char *, va_list) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 0))) +#endif + ; +extern int krb5int_asprintf(char **, const char *, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; + +#define vasprintf krb5int_vasprintf +/* Assume HAVE_ASPRINTF iff HAVE_VASPRINTF. */ +#define asprintf krb5int_asprintf + +#elif defined(NEED_VASPRINTF_PROTO) + +extern int vasprintf(char **, const char *, va_list) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 0))) +#endif + ; +extern int asprintf(char **, const char *, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; + +#endif /* have vasprintf and prototype? */ + +/* Return true if the snprintf return value RESULT reflects a buffer + overflow for the buffer size SIZE. + + We cast the result to unsigned int for two reasons. First, old + implementations of snprintf (such as the one in Solaris 9 and + prior) return -1 on a buffer overflow. Casting the result to -1 + will convert that value to UINT_MAX, which should compare larger + than any reasonable buffer size. Second, comparing signed and + unsigned integers will generate warnings with some compilers, and + can have unpredictable results, particularly when the relative + widths of the types is not known (size_t may be the same width as + int or larger). +*/ +#define SNPRINTF_OVERFLOW(result, size) \ + ((unsigned int)(result) >= (size_t)(size)) + +#if defined(_WIN32) || !defined(HAVE_STRERROR_R) || defined(STRERROR_R_CHAR_P) +#define strerror_r k5_strerror_r +#endif +extern int k5_strerror_r(int errnum, char *buf, size_t buflen); + +#ifndef HAVE_MKSTEMP +extern int krb5int_mkstemp(char *); +#define mkstemp krb5int_mkstemp +#endif + +#ifndef HAVE_GETTIMEOFDAY +extern int krb5int_gettimeofday(struct timeval *tp, void *ignore); +#define gettimeofday krb5int_gettimeofday +#endif + +/* + * Attempt to zero memory in a way that compilers won't optimize out. + * + * This mechanism should work even for heap storage about to be freed, + * or automatic storage right before we return from a function. + * + * Then, even if we leak uninitialized memory someplace, or UNIX + * "core" files get created with world-read access, some of the most + * sensitive data in the process memory will already be safely wiped. + * + * We're not going so far -- yet -- as to try to protect key data that + * may have been written into swap space.... + */ +#ifdef _WIN32 +# define zap(ptr, len) SecureZeroMemory(ptr, len) +#elif defined(__STDC_LIB_EXT1__) +/* + * Use memset_s() which cannot be optimized out. Avoid memset_s(NULL, 0, 0, 0) + * which would cause a runtime constraint violation. + */ +static inline void zap(void *ptr, size_t len) +{ + if (len > 0) + memset_s(ptr, len, 0, len); +} +#elif defined(HAVE_EXPLICIT_BZERO) +# define zap(ptr, len) explicit_bzero(ptr, len) +#elif defined(HAVE_EXPLICIT_MEMSET) +# define zap(ptr, len) explicit_memset(ptr, 0, len) +#elif defined(__GNUC__) || defined(__clang__) +/* + * Use an asm statement which declares a memory clobber to force the memset to + * be carried out. Avoid memset(NULL, 0, 0) which has undefined behavior. + */ +static inline void zap(void *ptr, size_t len) +{ + if (len > 0) + memset(ptr, 0, len); + __asm__ __volatile__("" : : "g" (ptr) : "memory"); +} +#else +/* + * Use a function from libkrb5support to defeat inlining unless link-time + * optimization is used. The function uses a volatile pointer, which prevents + * current compilers from optimizing out the memset. + */ +# define zap(ptr, len) krb5int_zap(ptr, len) +#endif + +extern void krb5int_zap(void *ptr, size_t len); + +/* + * Return 0 if the n-byte memory regions p1 and p2 are equal, and nonzero if + * they are not. The function is intended to take the same amount of time + * regardless of how many bytes of p1 and p2 are equal. + */ +int k5_bcmp(const void *p1, const void *p2, size_t n); + +/* + * Split a path into parent directory and basename. Either output parameter + * may be NULL if the caller doesn't need it. parent_out will be empty if path + * has no basename. basename_out will be empty if path ends with a path + * separator. Returns 0 on success or ENOMEM on allocation failure. + */ +long k5_path_split(const char *path, char **parent_out, char **basename_out); + +/* + * Compose two path components, inserting the platform-appropriate path + * separator if needed. If path2 is an absolute path, path1 will be discarded + * and path_out will be a copy of path2. Returns 0 on success or ENOMEM on + * allocation failure. + */ +long k5_path_join(const char *path1, const char *path2, char **path_out); + +/* Return 1 if path is absolute, 0 if it is relative. */ +int k5_path_isabs(const char *path); + +/* + * Localization macros. If we have gettext, define _ appropriately for + * translating a string. If we do not have gettext, define _ and + * bindtextdomain as no-ops. N_ is always a no-op; it marks a string for + * extraction to pot files but does not translate it. + */ +#ifdef ENABLE_NLS +#include +#define KRB5_TEXTDOMAIN "mit-krb5" +#define _(s) dgettext(KRB5_TEXTDOMAIN, s) +#else +#define _(s) s +#define dgettext(d, m) m +#define ngettext(m1, m2, n) (((n) == 1) ? m1 : m2) +#define bindtextdomain(p, d) +#endif +#define N_(s) s + +#if !defined(HAVE_GETOPT) || !defined(HAVE_UNISTD_H) +/* Data objects imported from DLLs must be declared as such on Windows. */ +#if defined(_WIN32) && !defined(K5_GETOPT_C) +#define K5_GETOPT_DECL __declspec(dllimport) +#else +#define K5_GETOPT_DECL +#endif +K5_GETOPT_DECL extern int k5_opterr; +K5_GETOPT_DECL extern int k5_optind; +K5_GETOPT_DECL extern int k5_optopt; +K5_GETOPT_DECL extern char *k5_optarg; +#define opterr k5_opterr +#define optind k5_optind +#define optopt k5_optopt +#define optarg k5_optarg + +extern int k5_getopt(int nargc, char * const nargv[], const char *ostr); +#define getopt k5_getopt +#endif /* HAVE_GETOPT */ + +#ifdef HAVE_GETOPT_LONG +#include +#else + +struct option +{ + const char *name; + int has_arg; + int *flag; + int val; +}; + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +extern int k5_getopt_long(int nargc, char **nargv, char *options, + struct option *long_options, int *index); +#define getopt_long k5_getopt_long +#endif /* HAVE_GETOPT_LONG */ + +#if defined(_WIN32) +/* On Windows there is never a need to ignore the process environment. */ +#define secure_getenv getenv +#elif !defined(HAVE_SECURE_GETENV) +#define secure_getenv k5_secure_getenv +extern char *k5_secure_getenv(const char *name); +#endif + +/* Set *fnames_out to a null-terminated list of filenames within dirname, + * sorted according to strcmp(). Return 0 on success, or ENOENT/ENOMEM. */ +int k5_dir_filenames(const char *dirname, char ***fnames_out); +void k5_free_filenames(char **fnames); + +#endif /* K5_PLATFORM_H */ diff --git a/krb5-1.21.3/src/include/k5-plugin.h b/krb5-1.21.3/src/include/k5-plugin.h new file mode 100644 index 00000000..90809e16 --- /dev/null +++ b/krb5-1.21.3/src/include/k5-plugin.h @@ -0,0 +1,121 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * This software is being provided to you, the LICENSEE, by the + * Massachusetts Institute of Technology (M.I.T.) under the following + * license. By obtaining, using and/or copying this software, you agree + * that you have read, understood, and will comply with these terms and + * conditions: + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute + * this software and its documentation for any purpose and without fee or + * royalty is hereby granted, provided that you agree to comply with the + * following copyright notice and statements, including the disclaimer, and + * that the same appear on ALL copies of the software and documentation, + * including modifications that you make for internal use or for + * distribution: + * + * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS + * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF + * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF + * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY + * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + * + * The name of the Massachusetts Institute of Technology or M.I.T. may NOT + * be used in advertising or publicity pertaining to distribution of the + * software. Title to copyright in this software and any associated + * documentation shall at all times remain with M.I.T., and USER agrees to + * preserve same. + * + * Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + */ + +/* Just those definitions which are needed by util/support/plugins.c, + which gets compiled before util/et is built, which happens before + we can construct krb5.h, which is included by k5-int.h. + + So, no krb5 types. */ + +#ifndef K5_PLUGIN_H +#define K5_PLUGIN_H + +#if defined(_MSDOS) || defined(_WIN32) +#include "win-mac.h" +#endif +#include "autoconf.h" +#ifndef KRB5_CALLCONV +#define KRB5_CALLCONV +#define KRB5_CALLCONV_C +#endif + +#include "k5-err.h" + +/* + * Plugins normally export fixed symbol names, but when statically + * linking plugins, we need a different symbol name for each plugin. + * The first argument to PLUGIN_SYMBOL_NAME acts as the + * differentiator, and is only used for static plugin linking. + * + * Although this macro (and thus this header file) are used in plugins + * whose code lies inside the krb5 tree, plugins maintained separately + * from the krb5 tree do not need it; they can just use the fixed + * symbol name unconditionally. + */ +#ifdef STATIC_PLUGINS +#define PLUGIN_SYMBOL_NAME(prefix, symbol) prefix ## _ ## symbol +#else +#define PLUGIN_SYMBOL_NAME(prefix, symbol) symbol +#endif + +struct plugin_file_handle; /* opaque */ + +struct plugin_dir_handle { + /* This points to a NULL-terminated list of pointers to plugin_file_handle structs */ + struct plugin_file_handle **files; +}; +#define PLUGIN_DIR_INIT(P) ((P)->files = NULL) +#define PLUGIN_DIR_OPEN(P) ((P)->files != NULL) + +long KRB5_CALLCONV +krb5int_open_plugin (const char *, struct plugin_file_handle **, struct errinfo *); +void KRB5_CALLCONV +krb5int_close_plugin (struct plugin_file_handle *); + +long KRB5_CALLCONV +krb5int_get_plugin_data (struct plugin_file_handle *, const char *, void **, + struct errinfo *); + +long KRB5_CALLCONV +krb5int_get_plugin_func (struct plugin_file_handle *, const char *, + void (**)(), struct errinfo *); + + +long KRB5_CALLCONV +krb5int_open_plugin_dirs (const char * const *, const char * const *, + struct plugin_dir_handle *, struct errinfo *); +void KRB5_CALLCONV +krb5int_close_plugin_dirs (struct plugin_dir_handle *); + +long KRB5_CALLCONV +krb5int_get_plugin_dir_data (struct plugin_dir_handle *, const char *, + void ***, struct errinfo *); +void KRB5_CALLCONV +krb5int_free_plugin_dir_data (void **); + +long KRB5_CALLCONV +krb5int_get_plugin_dir_func (struct plugin_dir_handle *, const char *, + void (***)(void), struct errinfo *); +void KRB5_CALLCONV +krb5int_free_plugin_dir_func (void (**)(void)); + +#endif /* K5_PLUGIN_H */ diff --git a/krb5-1.21.3/src/include/k5-queue.h b/krb5-1.21.3/src/include/k5-queue.h new file mode 100644 index 00000000..ad6d866f --- /dev/null +++ b/krb5-1.21.3/src/include/k5-queue.h @@ -0,0 +1,637 @@ +/* + * This is a copy of NetBSD's sys/queue.h, edited to use a different symbol for + * multiple inclusion protection and to suppress the include of . + */ + +/* $NetBSD: queue.h,v 1.53 2011/11/19 22:51:31 tls Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. 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 University 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 REGENTS 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 REGENTS 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. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef K5_QUEUE_H +#define K5_QUEUE_H + +/* #include */ + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues, and circular queues. + * + * A singly-linked list is headed by a single forward pointer. The + * elements are singly linked for minimum space and pointer manipulation + * overhead at the expense of O(n) removal for arbitrary elements. New + * elements can be added to the list after an existing element or at the + * head of the list. Elements being removed from the head of the list + * should use the explicit macro for this purpose for optimum + * efficiency. A singly-linked list may only be traversed in the forward + * direction. Singly-linked lists are ideal for applications with large + * datasets and few or no removals or for implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +/* + * List definitions. + */ +#define K5_LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define K5_LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define K5_LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ +#define K5_LIST_INIT(head) do { \ + (head)->lh_first = NULL; \ +} while (/*CONSTCOND*/0) + +#define K5_LIST_INSERT_AFTER(listelm, elm, field) do { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (/*CONSTCOND*/0) + +#define K5_LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (/*CONSTCOND*/0) + +#define K5_LIST_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (/*CONSTCOND*/0) + +#define K5_LIST_REMOVE(elm, field) do { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ +} while (/*CONSTCOND*/0) + +#define K5_LIST_FOREACH(var, head, field) \ + for ((var) = ((head)->lh_first); \ + (var); \ + (var) = ((var)->field.le_next)) + +#define K5_LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = K5_LIST_FIRST((head)); \ + (var) && ((tvar) = K5_LIST_NEXT((var), field), 1); \ + (var) = (tvar)) +/* + * List access methods. + */ +#define K5_LIST_EMPTY(head) ((head)->lh_first == NULL) +#define K5_LIST_FIRST(head) ((head)->lh_first) +#define K5_LIST_NEXT(elm, field) ((elm)->field.le_next) + + +/* + * Singly-linked List definitions. + */ +#define K5_SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define K5_SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define K5_SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define K5_SLIST_INIT(head) do { \ + (head)->slh_first = NULL; \ +} while (/*CONSTCOND*/0) + +#define K5_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define K5_SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define K5_SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (/*CONSTCOND*/0) + +#define K5_SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + K5_SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = (head)->slh_first; \ + while(curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ +} while (/*CONSTCOND*/0) + +#define K5_SLIST_REMOVE_AFTER(slistelm, field) do { \ + (slistelm)->field.sle_next = \ + K5_SLIST_NEXT(K5_SLIST_NEXT((slistelm), field), field); \ +} while (/*CONSTCOND*/0) + +#define K5_SLIST_FOREACH(var, head, field) \ + for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) + +#define K5_SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = K5_SLIST_FIRST((head)); \ + (var) && ((tvar) = K5_SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +/* + * Singly-linked List access methods. + */ +#define K5_SLIST_EMPTY(head) ((head)->slh_first == NULL) +#define K5_SLIST_FIRST(head) ((head)->slh_first) +#define K5_SLIST_NEXT(elm, field) ((elm)->field.sle_next) + + +/* + * Singly-linked Tail queue declarations. + */ +#define K5_STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first; /* first element */ \ + struct type **stqh_last; /* addr of last next element */ \ +} + +#define K5_STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define K5_STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define K5_STAILQ_INIT(head) do { \ + (head)->stqh_first = NULL; \ + (head)->stqh_last = &(head)->stqh_first; \ +} while (/*CONSTCOND*/0) + +#define K5_STAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ + (head)->stqh_last = &(elm)->field.stqe_next; \ + (head)->stqh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define K5_STAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.stqe_next = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &(elm)->field.stqe_next; \ +} while (/*CONSTCOND*/0) + +#define K5_STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\ + (head)->stqh_last = &(elm)->field.stqe_next; \ + (listelm)->field.stqe_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define K5_STAILQ_REMOVE_HEAD(head, field) do { \ + if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \ + (head)->stqh_last = &(head)->stqh_first; \ +} while (/*CONSTCOND*/0) + +#define K5_STAILQ_REMOVE(head, elm, type, field) do { \ + if ((head)->stqh_first == (elm)) { \ + K5_STAILQ_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->stqh_first; \ + while (curelm->field.stqe_next != (elm)) \ + curelm = curelm->field.stqe_next; \ + if ((curelm->field.stqe_next = \ + curelm->field.stqe_next->field.stqe_next) == NULL) \ + (head)->stqh_last = &(curelm)->field.stqe_next; \ + } \ +} while (/*CONSTCOND*/0) + +#define K5_STAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->stqh_first); \ + (var); \ + (var) = ((var)->field.stqe_next)) + +#define K5_STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = K5_STAILQ_FIRST((head)); \ + (var) && ((tvar) = K5_STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define K5_STAILQ_CONCAT(head1, head2) do { \ + if (!K5_STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + K5_STAILQ_INIT((head2)); \ + } \ +} while (/*CONSTCOND*/0) + +#define K5_STAILQ_LAST(head, type, field) \ + (K5_STAILQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *)(void *) \ + ((char *)((head)->stqh_last) - offsetof(struct type, field)))) + +/* + * Singly-linked Tail queue access methods. + */ +#define K5_STAILQ_EMPTY(head) ((head)->stqh_first == NULL) +#define K5_STAILQ_FIRST(head) ((head)->stqh_first) +#define K5_STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + + +/* + * Simple queue definitions. + */ +#define K5_SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define K5_SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define K5_SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue functions. + */ +#define K5_SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (/*CONSTCOND*/0) + +#define K5_SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define K5_SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (/*CONSTCOND*/0) + +#define K5_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define K5_SIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (/*CONSTCOND*/0) + +#define K5_SIMPLEQ_REMOVE(head, elm, type, field) do { \ + if ((head)->sqh_first == (elm)) { \ + K5_SIMPLEQ_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->sqh_first; \ + while (curelm->field.sqe_next != (elm)) \ + curelm = curelm->field.sqe_next; \ + if ((curelm->field.sqe_next = \ + curelm->field.sqe_next->field.sqe_next) == NULL) \ + (head)->sqh_last = &(curelm)->field.sqe_next; \ + } \ +} while (/*CONSTCOND*/0) + +#define K5_SIMPLEQ_FOREACH(var, head, field) \ + for ((var) = ((head)->sqh_first); \ + (var); \ + (var) = ((var)->field.sqe_next)) + +#define K5_SIMPLEQ_FOREACH_SAFE(var, head, field, next) \ + for ((var) = ((head)->sqh_first); \ + (var) && ((next = ((var)->field.sqe_next)), 1); \ + (var) = (next)) + +#define K5_SIMPLEQ_CONCAT(head1, head2) do { \ + if (!K5_SIMPLEQ_EMPTY((head2))) { \ + *(head1)->sqh_last = (head2)->sqh_first; \ + (head1)->sqh_last = (head2)->sqh_last; \ + K5_SIMPLEQ_INIT((head2)); \ + } \ +} while (/*CONSTCOND*/0) + +#define K5_SIMPLEQ_LAST(head, type, field) \ + (K5_SIMPLEQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *)(void *) \ + ((char *)((head)->sqh_last) - offsetof(struct type, field)))) + +/* + * Simple queue access methods. + */ +#define K5_SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL) +#define K5_SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define K5_SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + + +/* + * Tail queue definitions. + */ +#define _K5_TAILQ_HEAD(name, type, qual) \ +struct name { \ + qual type *tqh_first; /* first element */ \ + qual type *qual *tqh_last; /* addr of last next element */ \ +} +#define K5_TAILQ_HEAD(name, type) _K5_TAILQ_HEAD(name, struct type,) + +#define K5_TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define _K5_TAILQ_ENTRY(type, qual) \ +struct { \ + qual type *tqe_next; /* next element */ \ + qual type *qual *tqe_prev; /* address of previous next element */\ +} +#define K5_TAILQ_ENTRY(type) _K5_TAILQ_ENTRY(struct type,) + +/* + * Tail queue functions. + */ +#define K5_TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) + +#define K5_TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) + +#define K5_TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define K5_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define K5_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define K5_TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define K5_TAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->tqh_first); \ + (var); \ + (var) = ((var)->field.tqe_next)) + +#define K5_TAILQ_FOREACH_SAFE(var, head, field, next) \ + for ((var) = ((head)->tqh_first); \ + (var) != NULL && ((next) = K5_TAILQ_NEXT(var, field), 1); \ + (var) = (next)) + +#define K5_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ + (var); \ + (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) + +#define K5_TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \ + for ((var) = K5_TAILQ_LAST((head), headname); \ + (var) && ((prev) = K5_TAILQ_PREV((var), headname, field), 1);\ + (var) = (prev)) + +#define K5_TAILQ_CONCAT(head1, head2, field) do { \ + if (!K5_TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + K5_TAILQ_INIT((head2)); \ + } \ +} while (/*CONSTCOND*/0) + +/* + * Tail queue access methods. + */ +#define K5_TAILQ_EMPTY(head) ((head)->tqh_first == NULL) +#define K5_TAILQ_FIRST(head) ((head)->tqh_first) +#define K5_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define K5_TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +#define K5_TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + + +/* + * Circular queue definitions. + */ +#define K5_CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define K5_CIRCLEQ_HEAD_INITIALIZER(head) \ + { (void *)&head, (void *)&head } + +#define K5_CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue functions. + */ +#define K5_CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = (void *)(head); \ + (head)->cqh_last = (void *)(head); \ +} while (/*CONSTCOND*/0) + +#define K5_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define K5_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (/*CONSTCOND*/0) + +#define K5_CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = (void *)(head); \ + if ((head)->cqh_last == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define K5_CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.cqe_next = (void *)(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (/*CONSTCOND*/0) + +#define K5_CIRCLEQ_REMOVE(head, elm, field) do { \ + if ((elm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ +} while (/*CONSTCOND*/0) + +#define K5_CIRCLEQ_FOREACH(var, head, field) \ + for ((var) = ((head)->cqh_first); \ + (var) != (const void *)(head); \ + (var) = ((var)->field.cqe_next)) + +#define K5_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for ((var) = ((head)->cqh_last); \ + (var) != (const void *)(head); \ + (var) = ((var)->field.cqe_prev)) + +/* + * Circular queue access methods. + */ +#define K5_CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) +#define K5_CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define K5_CIRCLEQ_LAST(head) ((head)->cqh_last) +#define K5_CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define K5_CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) + +#define K5_CIRCLEQ_LOOP_NEXT(head, elm, field) \ + (((elm)->field.cqe_next == (void *)(head)) \ + ? ((head)->cqh_first) \ + : (elm->field.cqe_next)) +#define K5_CIRCLEQ_LOOP_PREV(head, elm, field) \ + (((elm)->field.cqe_prev == (void *)(head)) \ + ? ((head)->cqh_last) \ + : (elm->field.cqe_prev)) + +#endif /* !K5_QUEUE_H */ diff --git a/krb5-1.21.3/src/include/k5-spake.h b/krb5-1.21.3/src/include/k5-spake.h new file mode 100644 index 00000000..ddb5d810 --- /dev/null +++ b/krb5-1.21.3/src/include/k5-spake.h @@ -0,0 +1,107 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-spake.h - SPAKE preauth mech declarations */ +/* + * Copyright (C) 2015 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. + */ + +/* + * The SPAKE preauth mechanism allows long-term client keys to be used for + * preauthentication without exposing them to offline dictionary attacks. The + * negotiated key can also be used for second-factor authentication. This + * header file declares structures and encoder/decoder functions for the + * mechanism's padata messages. + */ + +#ifndef K5_SPAKE_H +#define K5_SPAKE_H + +#include "k5-int.h" + +/* SPAKESecondFactor is contained within a SPAKEChallenge, SPAKEResponse, or + * EncryptedData message and contains a second-factor challenge or response. */ +typedef struct krb5_spake_factor_st { + int32_t type; + krb5_data *data; +} krb5_spake_factor; + +/* SPAKESupport is sent from the client to the KDC to indicate which group the + * client supports. */ +typedef struct krb5_spake_support_st { + int32_t ngroups; + int32_t *groups; +} krb5_spake_support; + +/* SPAKEChallenge is sent from the KDC to the client to communicate its group + * selection, public value, and second-factor challenge options. */ +typedef struct krb5_spake_challenge_st { + int32_t group; + krb5_data pubkey; + krb5_spake_factor **factors; +} krb5_spake_challenge; + +/* SPAKEResponse is sent from the client to the KDC to communicate its public + * value and encrypted second-factor response. */ +typedef struct krb5_spake_response_st { + krb5_data pubkey; + krb5_enc_data factor; +} krb5_spake_response; + +enum krb5_spake_msgtype { + SPAKE_MSGTYPE_UNKNOWN = -1, + SPAKE_MSGTYPE_SUPPORT = 0, + SPAKE_MSGTYPE_CHALLENGE = 1, + SPAKE_MSGTYPE_RESPONSE = 2, + SPAKE_MSGTYPE_ENCDATA = 3 +}; + +/* PA-SPAKE is a choice among the message types which can appear in a PA-SPAKE + * padata element. */ +typedef struct krb5_pa_spake_st { + enum krb5_spake_msgtype choice; + union krb5_spake_message_choices { + krb5_spake_support support; + krb5_spake_challenge challenge; + krb5_spake_response response; + krb5_enc_data encdata; + } u; +} krb5_pa_spake; + +krb5_error_code encode_krb5_spake_factor(const krb5_spake_factor *val, + krb5_data **code_out); +krb5_error_code decode_krb5_spake_factor(const krb5_data *code, + krb5_spake_factor **val_out); +void k5_free_spake_factor(krb5_context context, krb5_spake_factor *val); + +krb5_error_code encode_krb5_pa_spake(const krb5_pa_spake *val, + krb5_data **code_out); +krb5_error_code decode_krb5_pa_spake(const krb5_data *code, + krb5_pa_spake **val_out); +void k5_free_pa_spake(krb5_context context, krb5_pa_spake *val); + +#endif /* K5_SPAKE_H */ diff --git a/krb5-1.21.3/src/include/k5-thread.h b/krb5-1.21.3/src/include/k5-thread.h new file mode 100644 index 00000000..a3101239 --- /dev/null +++ b/krb5-1.21.3/src/include/k5-thread.h @@ -0,0 +1,443 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-thread.h - Preliminary portable thread support */ +/* + * Copyright 2004,2005,2006,2007,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef K5_THREAD_H +#define K5_THREAD_H + +#include "autoconf.h" +#ifndef KRB5_CALLCONV +# define KRB5_CALLCONV +#endif +#ifndef KRB5_CALLCONV_C +# define KRB5_CALLCONV_C +#endif + +/* Interface (tentative): + + Mutex support: + + // Between these two, we should be able to do pure compile-time + // and pure run-time initialization. + // POSIX: partial initializer is PTHREAD_MUTEX_INITIALIZER, + // finish does nothing + // Windows: partial initializer is an invalid handle, + // finish does the real initialization work + k5_mutex_t foo_mutex = K5_MUTEX_PARTIAL_INITIALIZER; + int k5_mutex_finish_init(k5_mutex_t *); + // for dynamic allocation + int k5_mutex_init(k5_mutex_t *); + // Must work for both kinds of alloc, even if it means adding flags. + int k5_mutex_destroy(k5_mutex_t *); + + // As before. + int k5_mutex_lock(k5_mutex_t *); + int k5_mutex_unlock(k5_mutex_t *); + + In each library, one new function to finish the static mutex init, + and any other library-wide initialization that might be desired. + On POSIX, this function would be called via the second support + function (see below). On Windows, it would be called at library + load time. These functions, or functions they calls, should be the + only places that k5_mutex_finish_init gets called. + + A second function or macro called at various possible "first" entry + points which either calls pthread_once on the first function + (POSIX), or checks some flag set by the first function (Windows), + and possibly returns an error. (In the non-threaded case, a simple + flag can be used to avoid multiple invocations, and the mutexes + don't need run-time initialization anyways.) + + A third function for library termination calls mutex_destroy on + each mutex for the library. This function would be called + automatically at library unload time. If it turns out to be needed + at exit time for libraries that don't get unloaded, perhaps we + should also use atexit(). Any static mutexes should be cleaned up + with k5_mutex_destroy here. + + How does that second support function invoke the first support + function only once? Through something modelled on pthread_once + that I haven't written up yet. Probably: + + k5_once_t foo_once = K5_ONCE_INIT; + k5_once(k5_once_t *, void (*)(void)); + + For POSIX: Map onto pthread_once facility. + For non-threaded case: A simple flag. + For Windows: Not needed; library init code takes care of it. + + XXX: A general k5_once mechanism isn't possible for Windows, + without faking it through named mutexes or mutexes initialized at + startup. I was only using it in one place outside these headers, + so I'm dropping the general scheme. Eventually the existing uses + in k5-thread.h and k5-platform.h will be converted to pthread_once + or static variables. + + + Thread-specific data: + + // TSD keys are limited in number in gssapi/krb5/com_err; enumerate + // them all. This allows support code init to allocate the + // necessary storage for pointers all at once, and avoids any + // possible error in key creation. + enum { ... } k5_key_t; + // Register destructor function. Called in library init code. + int k5_key_register(k5_key_t, void (*destructor)(void *)); + // Returns NULL or data. + void *k5_getspecific(k5_key_t); + // Returns error if key out of bounds, or the pointer table can't + // be allocated. A call to k5_key_register must have happened first. + // This may trigger the calling of pthread_setspecific on POSIX. + int k5_setspecific(k5_key_t, void *); + // Called in library termination code. + // Trashes data in all threads, calling the registered destructor + // (but calling it from the current thread). + int k5_key_delete(k5_key_t); + + For the non-threaded version, the support code will have a static + array indexed by k5_key_t values, and get/setspecific simply access + the array elements. + + The TSD destructor table is global state, protected by a mutex if + threads are enabled. + + + Any actual external symbols will use the krb5int_ prefix. The k5_ + names will be simple macros or inline functions to rename the + external symbols, or slightly more complex ones to expand the + implementation inline (e.g., map to POSIX versions and/or debug + code using __FILE__ and the like). + + + More to be added, perhaps. */ + +#include +#ifndef NDEBUG +#include +#include +#endif + +/* The mutex structure we use, k5_mutex_t, is defined to some + OS-specific bits. The use of multiple layers of typedefs are an + artifact resulting from debugging code we once used, implemented as + wrappers around the OS mutex scheme. + + The OS specific bits, in k5_os_mutex, break down into three primary + implementations, POSIX threads, Windows threads, and no thread + support. However, the POSIX thread version is further subdivided: + In one case, we can determine at run time whether the thread + library is linked into the application, and use it only if it is + present; in the other case, we cannot, and the thread library must + be linked in always, but can be used unconditionally. In the + former case, the k5_os_mutex structure needs to hold both the POSIX + and the non-threaded versions. + + The various k5_os_mutex_* operations are the OS-specific versions, + applied to the OS-specific data, and k5_mutex_* uses k5_os_mutex_* + to do the OS-specific parts of the work. */ + +/* Define the OS mutex bit. */ + +typedef char k5_os_nothread_mutex; +# define K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER 0 +/* Empty inline functions avoid the "statement with no effect" + warnings, and do better type-checking than functions that don't use + their arguments. */ +static inline int k5_os_nothread_mutex_finish_init(k5_os_nothread_mutex *m) { + return 0; +} +static inline int k5_os_nothread_mutex_init(k5_os_nothread_mutex *m) { + return 0; +} +static inline int k5_os_nothread_mutex_destroy(k5_os_nothread_mutex *m) { + return 0; +} +static inline int k5_os_nothread_mutex_lock(k5_os_nothread_mutex *m) { + return 0; +} +static inline int k5_os_nothread_mutex_unlock(k5_os_nothread_mutex *m) { + return 0; +} + +/* Values: + 2 - function has not been run + 3 - function has been run + 4 - function is being run -- deadlock detected */ +typedef unsigned char k5_os_nothread_once_t; +# define K5_OS_NOTHREAD_ONCE_INIT 2 +# define k5_os_nothread_once(O,F) \ + (*(O) == 3 ? 0 \ + : *(O) == 2 ? (*(O) = 4, (F)(), *(O) = 3, 0) \ + : (assert(*(O) != 4), assert(*(O) == 2 || *(O) == 3), 0)) + + + +#ifndef ENABLE_THREADS + +typedef k5_os_nothread_mutex k5_os_mutex; +# define K5_OS_MUTEX_PARTIAL_INITIALIZER \ + K5_OS_NOTHREAD_MUTEX_PARTIAL_INITIALIZER +# define k5_os_mutex_finish_init k5_os_nothread_mutex_finish_init +# define k5_os_mutex_init k5_os_nothread_mutex_init +# define k5_os_mutex_destroy k5_os_nothread_mutex_destroy +# define k5_os_mutex_lock k5_os_nothread_mutex_lock +# define k5_os_mutex_unlock k5_os_nothread_mutex_unlock + +# define k5_once_t k5_os_nothread_once_t +# define K5_ONCE_INIT K5_OS_NOTHREAD_ONCE_INIT +# define k5_once k5_os_nothread_once + +#elif HAVE_PTHREAD + +# include + +/* Weak reference support, etc. + + Linux: Stub mutex routines exist, but pthread_once does not. + + Solaris <10: In libc there's a pthread_once that doesn't seem to do + anything. Bleah. But pthread_mutexattr_setrobust_np is defined + only in libpthread. However, some version of GNU libc (Red Hat's + Fedora Core 5, reportedly) seems to have that function, but no + declaration, so we'd have to declare it in order to test for its + address. We now have tests to see if pthread_once actually works, + so stick with that for now. + + Solaris 10: The real thread support now lives in libc, and + libpthread is just a filter object. So we might as well use the + real functions unconditionally. Since we haven't got a test for + this property yet, we use NO_WEAK_PTHREADS defined in aclocal.m4 + depending on the OS type. + + IRIX 6.5 stub pthread support in libc is really annoying. The + pthread_mutex_lock function returns ENOSYS for a program not linked + against -lpthread. No link-time failure, no weak symbols, etc. + The C library doesn't provide pthread_once; we can use weak + reference support for that. + + If weak references are not available, then for now, we assume that + the pthread support routines will always be available -- either the + real thing, or functional stubs that merely prohibit creating + threads. + + If we find a platform with non-functional stubs and no weak + references, we may have to resort to some hack like dlsym on the + symbol tables of the current process. */ + +#if defined(HAVE_PRAGMA_WEAK_REF) && !defined(NO_WEAK_PTHREADS) +# define USE_CONDITIONAL_PTHREADS +#endif + +#ifdef USE_CONDITIONAL_PTHREADS + +/* Can't rely on useful stubs -- see above regarding Solaris. */ +typedef struct { + pthread_once_t o; + k5_os_nothread_once_t n; +} k5_once_t; +# define K5_ONCE_INIT { PTHREAD_ONCE_INIT, K5_OS_NOTHREAD_ONCE_INIT } + +int k5_once(k5_once_t *once, void (*fn)(void)); +#else + +/* no pragma weak support */ + +typedef pthread_once_t k5_once_t; +# define K5_ONCE_INIT PTHREAD_ONCE_INIT +# define k5_once pthread_once + +#endif + +#if defined(__mips) && defined(__sgi) && (defined(_SYSTYPE_SVR4) || defined(__SYSTYPE_SVR4__)) +# ifndef HAVE_PRAGMA_WEAK_REF +# if defined(__GNUC__) && __GNUC__ < 3 +# error "Please update to a newer gcc with weak symbol support, or switch to native cc, reconfigure and recompile." +# else +# error "Weak reference support is required" +# endif +# endif +#endif + +typedef pthread_mutex_t k5_os_mutex; +# define K5_OS_MUTEX_PARTIAL_INITIALIZER \ + PTHREAD_MUTEX_INITIALIZER + +#ifdef USE_CONDITIONAL_PTHREADS + +# define k5_os_mutex_finish_init(M) (0) +int k5_os_mutex_init(k5_os_mutex *m); +int k5_os_mutex_destroy(k5_os_mutex *m); +int k5_os_mutex_lock(k5_os_mutex *m); +int k5_os_mutex_unlock(k5_os_mutex *m); + +#else + +static inline int k5_os_mutex_finish_init(k5_os_mutex *m) { return 0; } +# define k5_os_mutex_init(M) pthread_mutex_init((M), 0) +# define k5_os_mutex_destroy(M) pthread_mutex_destroy((M)) +# define k5_os_mutex_lock(M) pthread_mutex_lock(M) +# define k5_os_mutex_unlock(M) pthread_mutex_unlock(M) + +#endif /* is pthreads always available? */ + +#elif defined _WIN32 + +# define k5_once_t k5_os_nothread_once_t + +typedef struct { + HANDLE h; + int is_locked; +} k5_os_mutex; + +# define K5_OS_MUTEX_PARTIAL_INITIALIZER { INVALID_HANDLE_VALUE, 0 } + +# define k5_os_mutex_finish_init(M) \ + (assert((M)->h == INVALID_HANDLE_VALUE), \ + ((M)->h = CreateMutex(NULL, FALSE, NULL)) ? 0 : GetLastError()) +# define k5_os_mutex_init(M) \ + ((M)->is_locked = 0, \ + ((M)->h = CreateMutex(NULL, FALSE, NULL)) ? 0 : GetLastError()) +# define k5_os_mutex_destroy(M) \ + (CloseHandle((M)->h) ? ((M)->h = 0, 0) : GetLastError()) +# define k5_os_mutex_lock k5_win_mutex_lock + +static inline int k5_win_mutex_lock(k5_os_mutex *m) +{ + DWORD res; + res = WaitForSingleObject(m->h, INFINITE); + if (res == WAIT_FAILED) + return GetLastError(); + /* Eventually these should be turned into some reasonable error + code. */ + assert(res != WAIT_TIMEOUT); + assert(res != WAIT_ABANDONED); + assert(res == WAIT_OBJECT_0); + /* Avoid locking twice. */ + assert(m->is_locked == 0); + m->is_locked = 1; + return 0; +} + +# define k5_os_mutex_unlock(M) \ + (assert((M)->is_locked == 1), \ + (M)->is_locked = 0, \ + ReleaseMutex((M)->h) ? 0 : GetLastError()) + +#else + +# error "Thread support enabled, but thread system unknown" + +#endif + +typedef k5_os_mutex k5_mutex_t; +#define K5_MUTEX_PARTIAL_INITIALIZER K5_OS_MUTEX_PARTIAL_INITIALIZER +static inline int k5_mutex_init(k5_mutex_t *m) +{ + return k5_os_mutex_init(m); +} +static inline int k5_mutex_finish_init(k5_mutex_t *m) +{ + return k5_os_mutex_finish_init(m); +} +#define k5_mutex_destroy(M) \ + (k5_os_mutex_destroy(M)) + +static inline void k5_mutex_lock(k5_mutex_t *m) +{ + int r = k5_os_mutex_lock(m); +#ifndef NDEBUG + if (r != 0) { + fprintf(stderr, "k5_mutex_lock: Received error %d (%s)\n", + r, strerror(r)); + } +#endif + assert(r == 0); +} + +static inline void k5_mutex_unlock(k5_mutex_t *m) +{ + int r = k5_os_mutex_unlock(m); +#ifndef NDEBUG + if (r != 0) { + fprintf(stderr, "k5_mutex_unlock: Received error %d (%s)\n", + r, strerror(r)); + } +#endif + assert(r == 0); +} + +#define k5_mutex_assert_locked(M) ((void)(M)) +#define k5_mutex_assert_unlocked(M) ((void)(M)) +#define k5_assert_locked k5_mutex_assert_locked +#define k5_assert_unlocked k5_mutex_assert_unlocked + +/* Thread-specific data; implemented in a support file, because we'll + need to keep track of some global data for cleanup purposes. + + Note that the callback function type is such that the C library + routine free() is a valid callback. */ +typedef enum { + K5_KEY_COM_ERR, + K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME, + K5_KEY_GSS_KRB5_CCACHE_NAME, + K5_KEY_GSS_KRB5_ERROR_MESSAGE, + K5_KEY_GSS_SPNEGO_STATUS, +#if defined(__MACH__) && defined(__APPLE__) + K5_KEY_IPC_CONNECTION_INFO, +#endif + K5_KEY_MAX +} k5_key_t; +/* rename shorthand symbols for export */ +#define k5_key_register krb5int_key_register +#define k5_getspecific krb5int_getspecific +#define k5_setspecific krb5int_setspecific +#define k5_key_delete krb5int_key_delete +extern int k5_key_register(k5_key_t, void (*)(void *)); +extern void *k5_getspecific(k5_key_t); +extern int k5_setspecific(k5_key_t, void *); +extern int k5_key_delete(k5_key_t); + +extern int KRB5_CALLCONV krb5int_mutex_alloc (k5_mutex_t **); +extern void KRB5_CALLCONV krb5int_mutex_free (k5_mutex_t *); +extern void KRB5_CALLCONV krb5int_mutex_lock (k5_mutex_t *); +extern void KRB5_CALLCONV krb5int_mutex_unlock (k5_mutex_t *); + +/* In time, many of the definitions above should move into the support + library, and this file should be greatly simplified. For type + definitions, that'll take some work, since other data structures + incorporate mutexes directly, and our mutex type is dependent on + configuration options and system attributes. For most functions, + though, it should be relatively easy. + + For now, plugins should use the exported functions, and not the + above macros, and use krb5int_mutex_alloc for allocations. */ +#if defined(PLUGIN) || (defined(CONFIG_SMALL) && !defined(THREAD_SUPPORT_IMPL)) +#undef k5_mutex_lock +#define k5_mutex_lock krb5int_mutex_lock +#undef k5_mutex_unlock +#define k5_mutex_unlock krb5int_mutex_unlock +#endif + +#endif /* multiple inclusion? */ diff --git a/krb5-1.21.3/src/include/k5-tls.h b/krb5-1.21.3/src/include/k5-tls.h new file mode 100644 index 00000000..0661c058 --- /dev/null +++ b/krb5-1.21.3/src/include/k5-tls.h @@ -0,0 +1,104 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-tls.h - internal pluggable interface for TLS */ +/* + * Copyright (C) 2014 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. + */ + +/* + * This internal pluggable interface allows libkrb5 to load an in-tree module + * providing TLS support at runtime. It is currently tailored for the needs of + * the OpenSSL module as used for HTTP proxy support. As an internal + * interface, it can be changed to fit different implementations and consumers + * without regard for backward compatibility. + */ + +#ifndef K5_TLS_H +#define K5_TLS_H + +#include "k5-int.h" + +/* An abstract type for localauth module data. */ +typedef struct k5_tls_handle_st *k5_tls_handle; + +typedef enum { + DATA_READ, DONE, WANT_READ, WANT_WRITE, ERROR_TLS +} k5_tls_status; + +/* + * Create a handle for fd, where the server certificate must match servername + * and be trusted according to anchors. anchors is a null-terminated list + * using the DIR:/FILE:/ENV: syntax borrowed from PKINIT. If anchors is null, + * use the system default trust anchors. + */ +typedef krb5_error_code +(*k5_tls_setup_fn)(krb5_context context, SOCKET fd, const char *servername, + char **anchors, k5_tls_handle *handle_out); + +/* + * Write len bytes of data using TLS. Return DONE if writing is complete, + * WANT_READ or WANT_WRITE if the underlying socket must be readable or + * writable to continue, and ERROR_TLS if the TLS channel or underlying socket + * experienced an error. After WANT_READ or WANT_WRITE, the operation will be + * retried with the same arguments even if some data has already been written. + * (OpenSSL makes this contract easy to fulfill. For other implementations we + * might want to change it.) + */ +typedef k5_tls_status +(*k5_tls_write_fn)(krb5_context context, k5_tls_handle handle, + const void *data, size_t len); + +/* + * Read up to data_size bytes of data using TLS. Return DATA_READ and set + * *len_out if any data is read. Return DONE if there is no more data to be + * read on the connection, WANT_READ or WANT_WRITE if the underlying socket + * must be readable or writable to continue, and ERROR_TLS if the TLS channel + * or underlying socket experienced an error. + * + * After DATA_READ, there may still be pending buffered data to read. The + * caller must call this method again with additional buffer space before + * selecting for reading on the underlying socket. + */ +typedef k5_tls_status +(*k5_tls_read_fn)(krb5_context context, k5_tls_handle handle, void *data, + size_t data_size, size_t *len_out); + +/* Release a handle. Do not pass a null pointer. */ +typedef void +(*k5_tls_free_handle_fn)(krb5_context context, k5_tls_handle handle); + +/* All functions are mandatory unless they are all null, in which case the + * caller should assume that TLS is unsupported. */ +typedef struct k5_tls_vtable_st { + k5_tls_setup_fn setup; + k5_tls_write_fn write; + k5_tls_read_fn read; + k5_tls_free_handle_fn free_handle; +} *k5_tls_vtable; + +#endif /* K5_TLS_H */ diff --git a/krb5-1.21.3/src/include/k5-trace.h b/krb5-1.21.3/src/include/k5-trace.h new file mode 100644 index 00000000..16a898fe --- /dev/null +++ b/krb5-1.21.3/src/include/k5-trace.h @@ -0,0 +1,523 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/k5-trace.h */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This header contains trace macro definitions, which map trace points within + * the code to krb5int_trace() calls with descriptive text strings. + * + * A new trace macro must be defined in this file for each new location to + * be traced; the TRACE() macro should never be used directly. This keeps + * the tracing logic centralized in one place, to facilitate integration with + * alternate tracing backends such as DTrace. + * + * Trace logging is intended to aid power users in diagnosing configuration + * problems by showing what's going on behind the scenes of complex operations. + * Although trace logging is sometimes useful to developers, it is not intended + * as a replacement for a debugger, and it is not desirable to drown the user + * in output. Observe the following guidelines when adding trace points: + * + * - Avoid mentioning function or variable names in messages. + * + * - Try to convey what decisions are being made and what external inputs + * they are based on, not the process of making decisions. + * + * - It is generally not necessary to trace before returning an unrecoverable + * error. If an error code is unclear by itself, make it clearer with + * krb5_set_error_message(). + * + * - Keep macros simple. Add format specifiers to krb5int_trace's formatter + * as necessary (and document them here) instead of transforming macro + * arguments. + * + * - Like printf, the trace formatter interface is not type-safe. Check your + * formats carefully. Cast integral arguments to the appropriate type if + * they do not already patch. + * + * The following specifiers are supported by the formatter (see the + * implementation in lib/krb5/os/trace.c for details): + * + * {int} int, in decimal + * {long} long, in decimal + * {str} const char *, display as C string + * {lenstr} size_t and const char *, as a counted string + * {hexlenstr} size_t and const char *, as hex bytes + * {hashlenstr} size_t and const char *, as four-character hex hash + * {raddr} struct remote_address *, show socket type, address, port + * {data} krb5_data *, display as counted string + * {hexdata} krb5_data *, display as hex bytes + * {errno} int, display as number/errorstring + * {kerr} krb5_error_code, display as number/errorstring + * {keyblock} const krb5_keyblock *, display enctype and hash of key + * {key} krb5_key, display enctype and hash of key + * {cksum} const krb5_checksum *, display cksumtype and hex checksum + * {princ} krb5_principal, unparse and display + * {ptype} krb5_int32, krb5_principal type, display name + * {patype} krb5_preauthtype, a single padata type number + * {patypes} krb5_pa_data **, display list of padata type numbers + * {etype} krb5_enctype, display shortest name of enctype + * {etypes} krb5_enctype *, display list of enctypes + * {ccache} krb5_ccache, display type:name + * {keytab} krb5_keytab, display name + * {creds} krb5_creds *, display clientprinc -> serverprinc + */ + +#ifndef K5_TRACE_H +#define K5_TRACE_H + +#ifdef DISABLE_TRACING +#define TRACE(ctx, ...) +#else + +void krb5int_trace(krb5_context context, const char *fmt, ...); + +/* Try to optimize away argument evaluation and function call when we're not + * tracing, if this source file knows the internals of the context. */ +#ifdef _KRB5_INT_H +#define TRACE(ctx, ...) \ + do { if (ctx->trace_callback != NULL) \ + krb5int_trace(ctx, __VA_ARGS__); } while (0) +#else +#define TRACE(ctx, ...) krb5int_trace(ctx, __VA_ARGS__) +#endif + +#endif /* DISABLE_TRACING */ + +#define TRACE_CC_CACHE_MATCH(c, princ, ret) \ + TRACE(c, "Matching {princ} in collection with result: {kerr}", \ + princ, ret) +#define TRACE_CC_DESTROY(c, cache) \ + TRACE(c, "Destroying ccache {ccache}", cache) +#define TRACE_CC_GEN_NEW(c, cache) \ + TRACE(c, "Generating new unique ccache based on {ccache}", cache) +#define TRACE_CC_GET_CONFIG(c, cache, princ, key, data) \ + TRACE(c, "Read config in {ccache} for {princ}: {str}: {data}", \ + cache, princ, key, data) +#define TRACE_CC_INIT(c, cache, princ) \ + TRACE(c, "Initializing {ccache} with default princ {princ}", \ + cache, princ) +#define TRACE_CC_MOVE(c, src, dst) \ + TRACE(c, "Moving ccache {ccache} to {ccache}", src, dst) +#define TRACE_CC_NEW_UNIQUE(c, type) \ + TRACE(c, "Resolving unique ccache of type {str}", type) +#define TRACE_CC_REMOVE(c, cache, creds) \ + TRACE(c, "Removing {creds} from {ccache}", creds, cache) +#define TRACE_CC_RETRIEVE(c, cache, creds, ret) \ + TRACE(c, "Retrieving {creds} from {ccache} with result: {kerr}", \ + creds, cache, ret) +#define TRACE_CC_RETRIEVE_REF(c, cache, creds, ret) \ + TRACE(c, "Retrying {creds} with result: {kerr}", creds, ret) +#define TRACE_CC_SET_CONFIG(c, cache, princ, key, data) \ + TRACE(c, "Storing config in {ccache} for {princ}: {str}: {data}", \ + cache, princ, key, data) +#define TRACE_CC_STORE(c, cache, creds) \ + TRACE(c, "Storing {creds} in {ccache}", creds, cache) +#define TRACE_CC_STORE_TKT(c, cache, creds) \ + TRACE(c, "Also storing {creds} based on ticket", creds) + +#define TRACE_CCSELECT_VTINIT_FAIL(c, ret) \ + TRACE(c, "ccselect module failed to init vtable: {kerr}", ret) +#define TRACE_CCSELECT_INIT_FAIL(c, name, ret) \ + TRACE(c, "ccselect module {str} failed to init: {kerr}", name, ret) +#define TRACE_CCSELECT_MODCHOICE(c, name, server, cache, princ) \ + TRACE(c, "ccselect module {str} chose cache {ccache} with client " \ + "principal {princ} for server principal {princ}", name, cache, \ + princ, server) +#define TRACE_CCSELECT_MODNOTFOUND(c, name, server, princ) \ + TRACE(c, "ccselect module {str} chose client principal {princ} " \ + "for server principal {princ} but found no cache", name, princ, \ + server) +#define TRACE_CCSELECT_MODFAIL(c, name, ret, server) \ + TRACE(c, "ccselect module {str} yielded error {kerr} for server " \ + "principal {princ}", name, ret, server) +#define TRACE_CCSELECT_NOTFOUND(c, server) \ + TRACE(c, "ccselect can't find appropriate cache for server " \ + "principal {princ}", server) +#define TRACE_CCSELECT_DEFAULT(c, cache, server) \ + TRACE(c, "ccselect choosing default cache {ccache} for server " \ + "principal {princ}", cache, server) + +#define TRACE_DNS_SRV_ANS(c, host, port, prio, weight) \ + TRACE(c, "SRV answer: {int} {int} {int} \"{str}\"", prio, weight, \ + port, host) +#define TRACE_DNS_SRV_NOTFOUND(c) \ + TRACE(c, "No SRV records found") +#define TRACE_DNS_SRV_SEND(c, domain) \ + TRACE(c, "Sending DNS SRV query for {str}", domain) +#define TRACE_DNS_URI_ANS(c, uri, prio, weight) \ + TRACE(c, "URI answer: {int} {int} \"{str}\"", prio, weight, uri) +#define TRACE_DNS_URI_NOTFOUND(c) \ + TRACE(c, "No URI records found") +#define TRACE_DNS_URI_SEND(c, domain) \ + TRACE(c, "Sending DNS URI query for {str}", domain) + +#define TRACE_FAST_ARMOR_CCACHE(c, ccache_name) \ + TRACE(c, "FAST armor ccache: {str}", ccache_name) +#define TRACE_FAST_ARMOR_CCACHE_KEY(c, keyblock) \ + TRACE(c, "Armor ccache session key: {keyblock}", keyblock) +#define TRACE_FAST_ARMOR_KEY(c, keyblock) \ + TRACE(c, "FAST armor key: {keyblock}", keyblock) +#define TRACE_FAST_CCACHE_CONFIG(c) \ + TRACE(c, "Using FAST due to armor ccache negotiation result") +#define TRACE_FAST_DECODE(c) \ + TRACE(c, "Decoding FAST response") +#define TRACE_FAST_ENCODE(c) \ + TRACE(c, "Encoding request body and padata into FAST request") +#define TRACE_FAST_NEGO(c, avail) \ + TRACE(c, "FAST negotiation: {str}available", (avail) ? "" : "un") +#define TRACE_FAST_PADATA_UPGRADE(c) \ + TRACE(c, "Upgrading to FAST due to presence of PA_FX_FAST in reply") +#define TRACE_FAST_REPLY_KEY(c, keyblock) \ + TRACE(c, "FAST reply key: {keyblock}", keyblock) +#define TRACE_FAST_REQUIRED(c) \ + TRACE(c, "Using FAST due to KRB5_FAST_REQUIRED flag") + +#define TRACE_GET_CREDS_FALLBACK(c, hostname) \ + TRACE(c, "Falling back to canonicalized server hostname {str}", hostname) + +#define TRACE_GIC_PWD_CHANGED(c) \ + TRACE(c, "Getting initial TGT with changed password") +#define TRACE_GIC_PWD_CHANGEPW(c, tries) \ + TRACE(c, "Attempting password change; {int} tries remaining", tries) +#define TRACE_GIC_PWD_EXPIRED(c) \ + TRACE(c, "Principal expired; getting changepw ticket") +#define TRACE_GIC_PWD_PRIMARY(c) \ + TRACE(c, "Retrying AS request with primary KDC") + +#define TRACE_GSS_CLIENT_KEYTAB_FAIL(c, ret) \ + TRACE(c, "Unable to resolve default client keytab: {kerr}", ret) + +#define TRACE_ENCTYPE_LIST_UNKNOWN(c, profvar, name) \ + TRACE(c, "Unrecognized enctype name in {str}: {str}", profvar, name) + +#define TRACE_HOSTREALM_VTINIT_FAIL(c, ret) \ + TRACE(c, "hostrealm module failed to init vtable: {kerr}", ret) +#define TRACE_HOSTREALM_INIT_FAIL(c, name, ret) \ + TRACE(c, "hostrealm module {str} failed to init: {kerr}", name, ret) + +#define TRACE_INIT_CREDS(c, princ) \ + TRACE(c, "Getting initial credentials for {princ}", princ) +#define TRACE_INIT_CREDS_AS_KEY_GAK(c, keyblock) \ + TRACE(c, "AS key obtained from gak_fct: {keyblock}", keyblock) +#define TRACE_INIT_CREDS_AS_KEY_PREAUTH(c, keyblock) \ + TRACE(c, "AS key determined by preauth: {keyblock}", keyblock) +#define TRACE_INIT_CREDS_DECRYPTED_REPLY(c, keyblock) \ + TRACE(c, "Decrypted AS reply; session key is: {keyblock}", keyblock) +#define TRACE_INIT_CREDS_ERROR_REPLY(c, code) \ + TRACE(c, "Received error from KDC: {kerr}", code) +#define TRACE_INIT_CREDS_GAK(c, salt, s2kparams) \ + TRACE(c, "Getting AS key, salt \"{data}\", params \"{data}\"", \ + salt, s2kparams) +#define TRACE_INIT_CREDS_IDENTIFIED_REALM(c, realm) \ + TRACE(c, "Identified realm of client principal as {data}", realm) +#define TRACE_INIT_CREDS_KEYTAB_LOOKUP(c, princ, etypes) \ + TRACE(c, "Found entries for {princ} in keytab: {etypes}", princ, etypes) +#define TRACE_INIT_CREDS_KEYTAB_LOOKUP_FAILED(c, code) \ + TRACE(c, "Couldn't lookup etypes in keytab: {kerr}", code) +#define TRACE_INIT_CREDS_PREAUTH(c) \ + TRACE(c, "Preauthenticating using KDC method data") +#define TRACE_INIT_CREDS_PREAUTH_DECRYPT_FAIL(c, code) \ + TRACE(c, "Decrypt with preauth AS key failed: {kerr}", code) +#define TRACE_INIT_CREDS_PREAUTH_MORE(c, patype) \ + TRACE(c, "Continuing preauth mech {patype}", patype) +#define TRACE_INIT_CREDS_PREAUTH_NONE(c) \ + TRACE(c, "Sending unauthenticated request") +#define TRACE_INIT_CREDS_PREAUTH_OPTIMISTIC(c) \ + TRACE(c, "Attempting optimistic preauth") +#define TRACE_INIT_CREDS_PREAUTH_TRYAGAIN(c, patype, code) \ + TRACE(c, "Recovering from KDC error {int} using preauth mech {patype}", \ + patype, (int)code) +#define TRACE_INIT_CREDS_RESTART_FAST(c) \ + TRACE(c, "Restarting to upgrade to FAST") +#define TRACE_INIT_CREDS_RESTART_PREAUTH_FAILED(c) \ + TRACE(c, "Restarting due to PREAUTH_FAILED from FAST negotiation") +#define TRACE_INIT_CREDS_REFERRAL(c, realm) \ + TRACE(c, "Following referral to realm {data}", realm) +#define TRACE_INIT_CREDS_RETRY_TCP(c) \ + TRACE(c, "Request or response is too big for UDP; retrying with TCP") +#define TRACE_INIT_CREDS_SALT_PRINC(c, salt) \ + TRACE(c, "Salt derived from principal: {data}", salt) +#define TRACE_INIT_CREDS_SERVICE(c, service) \ + TRACE(c, "Setting initial creds service to {str}", service) + +#define TRACE_KADM5_AUTH_VTINIT_FAIL(c, ret) \ + TRACE(c, "kadm5_auth module failed to init vtable: {kerr}", ret) +#define TRACE_KADM5_AUTH_INIT_FAIL(c, name, ret) \ + TRACE(c, "kadm5_auth module {str} failed to init: {kerr}", ret) +#define TRACE_KADM5_AUTH_INIT_SKIP(c, name) \ + TRACE(c, "kadm5_auth module {str} declined to initialize", name) + +#define TRACE_KT_GET_ENTRY(c, keytab, princ, vno, enctype, err) \ + TRACE(c, "Retrieving {princ} from {keytab} (vno {int}, enctype {etype}) " \ + "with result: {kerr}", princ, keytab, (int) vno, enctype, err) + +#define TRACE_LOCALAUTH_INIT_CONFLICT(c, type, oldname, newname) \ + TRACE(c, "Ignoring localauth module {str} because it conflicts " \ + "with an2ln type {str} from module {str}", newname, type, oldname) +#define TRACE_LOCALAUTH_VTINIT_FAIL(c, ret) \ + TRACE(c, "localauth module failed to init vtable: {kerr}", ret) +#define TRACE_LOCALAUTH_INIT_FAIL(c, name, ret) \ + TRACE(c, "localauth module {str} failed to init: {kerr}", name, ret) + +#define TRACE_MK_REP(c, ctime, cusec, subkey, seqnum) \ + TRACE(c, "Creating AP-REP, time {long}.{int}, subkey {keyblock}, " \ + "seqnum {int}", (long) ctime, (int) cusec, subkey, (int) seqnum) + +#define TRACE_MK_REQ(c, creds, seqnum, subkey, sesskeyblock) \ + TRACE(c, "Creating authenticator for {creds}, seqnum {int}, " \ + "subkey {key}, session key {keyblock}", creds, (int) seqnum, \ + subkey, sesskeyblock) +#define TRACE_MK_REQ_ETYPES(c, etypes) \ + TRACE(c, "Negotiating for enctypes in authenticator: {etypes}", etypes) + +#define TRACE_MSPAC_VERIFY_FAIL(c, err) \ + TRACE(c, "PAC checksum verification failed: {kerr}", err) +#define TRACE_MSPAC_DISCARD_UNVERF(c) \ + TRACE(c, "Filtering out unverified MS PAC") + +#define TRACE_NEGOEX_INCOMING(c, seqnum, typestr, info) \ + TRACE(c, "NegoEx received [{int}]{str}: {str}", (int)seqnum, typestr, info) +#define TRACE_NEGOEX_OUTGOING(c, seqnum, typestr, info) \ + TRACE(c, "NegoEx sending [{int}]{str}: {str}", (int)seqnum, typestr, info) + +#define TRACE_PLUGIN_LOAD_FAIL(c, modname, err) \ + TRACE(c, "Error loading plugin module {str}: {kerr}", modname, err) +#define TRACE_PLUGIN_LOOKUP_FAIL(c, modname, err) \ + TRACE(c, "Error initializing module {str}: {kerr}", modname, err) + +#define TRACE_PREAUTH_CONFLICT(c, name1, name2, patype) \ + TRACE(c, "Preauth module {str} conflicts with module {str} for pa " \ + "type {patype}", name1, name2, patype) +#define TRACE_PREAUTH_COOKIE(c, len, data) \ + TRACE(c, "Received cookie: {lenstr}", (size_t) len, data) +#define TRACE_PREAUTH_ENC_TS_KEY_GAK(c, keyblock) \ + TRACE(c, "AS key obtained for encrypted timestamp: {keyblock}", keyblock) +#define TRACE_PREAUTH_ENC_TS(c, sec, usec, plain, enc) \ + TRACE(c, "Encrypted timestamp (for {long}.{int}): plain {hexdata}, " \ + "encrypted {hexdata}", (long) sec, (int) usec, plain, enc) +#define TRACE_PREAUTH_ENC_TS_DISABLED(c) \ + TRACE(c, "Ignoring encrypted timestamp because it is disabled") +#define TRACE_PREAUTH_ETYPE_INFO(c, etype, salt, s2kparams) \ + TRACE(c, "Selected etype info: etype {etype}, salt \"{data}\", " \ + "params \"{data}\"", etype, salt, s2kparams) +#define TRACE_PREAUTH_INFO_FAIL(c, patype, code) \ + TRACE(c, "Preauth builtin info function failure, type={patype}: {kerr}", \ + patype, code) +#define TRACE_PREAUTH_INPUT(c, padata) \ + TRACE(c, "Processing preauth types: {patypes}", padata) +#define TRACE_PREAUTH_OUTPUT(c, padata) \ + TRACE(c, "Produced preauth for next request: {patypes}", padata) +#define TRACE_PREAUTH_PROCESS(c, name, patype, real, code) \ + TRACE(c, "Preauth module {str} ({int}) ({str}) returned: " \ + "{kerr}", name, (int) patype, real ? "real" : "info", code) +#define TRACE_PREAUTH_SAM_KEY_GAK(c, keyblock) \ + TRACE(c, "AS key obtained for SAM: {keyblock}", keyblock) +#define TRACE_PREAUTH_SALT(c, salt, patype) \ + TRACE(c, "Received salt \"{data}\" via padata type {patype}", salt, \ + patype) +#define TRACE_PREAUTH_SKIP(c, name, patype) \ + TRACE(c, "Skipping previously used preauth module {str} ({int})", \ + name, (int) patype) +#define TRACE_PREAUTH_TRYAGAIN_INPUT(c, patype, padata) \ + TRACE(c, "Preauth tryagain input types ({int}): {patypes}", patype, padata) +#define TRACE_PREAUTH_TRYAGAIN(c, name, patype, code) \ + TRACE(c, "Preauth module {str} ({int}) tryagain returned: {kerr}", \ + name, (int)patype, code) +#define TRACE_PREAUTH_TRYAGAIN_OUTPUT(c, padata) \ + TRACE(c, "Followup preauth for next request: {patypes}", padata) +#define TRACE_PREAUTH_WRONG_CONTEXT(c) \ + TRACE(c, "Wrong context passed to krb5_init_creds_free(); leaking " \ + "modreq objects") + +#define TRACE_PROFILE_ERR(c,subsection, section, retval) \ + TRACE(c, "Bad value of {str} from [{str}] in conf file: {kerr}", \ + subsection, section, retval) + +#define TRACE_RD_REP(c, ctime, cusec, subkey, seqnum) \ + TRACE(c, "Read AP-REP, time {long}.{int}, subkey {keyblock}, " \ + "seqnum {int}", (long) ctime, (int) cusec, subkey, (int) seqnum) +#define TRACE_RD_REP_DCE(c, ctime, cusec, seqnum) \ + TRACE(c, "Read DCE-style AP-REP, time {long}.{int}, seqnum {int}", \ + (long) ctime, (int) cusec, (int) seqnum) + +#define TRACE_RD_REQ_DECRYPT_ANY(c, princ, keyblock) \ + TRACE(c, "Decrypted AP-REQ with server principal {princ}: " \ + "{keyblock}", princ, keyblock) +#define TRACE_RD_REQ_DECRYPT_SPECIFIC(c, princ, keyblock) \ + TRACE(c, "Decrypted AP-REQ with specified server principal {princ}: " \ + "{keyblock}", princ, keyblock) +#define TRACE_RD_REQ_DECRYPT_FAIL(c, err) \ + TRACE(c, "Failed to decrypt AP-REQ ticket: {kerr}", err) +#define TRACE_RD_REQ_NEGOTIATED_ETYPE(c, etype) \ + TRACE(c, "Negotiated enctype based on authenticator: {etype}", \ + etype) +#define TRACE_RD_REQ_SUBKEY(c, keyblock) \ + TRACE(c, "Authenticator contains subkey: {keyblock}", keyblock) +#define TRACE_RD_REQ_TICKET(c, client, server, keyblock) \ + TRACE(c, "AP-REQ ticket: {princ} -> {princ}, session key {keyblock}", \ + client, server, keyblock) + +#define TRACE_SENDTO_KDC_ERROR_SET_MESSAGE(c, raddr, err) \ + TRACE(c, "Error preparing message to send to {raddr}: {errno}", \ + raddr, err) +#define TRACE_SENDTO_KDC(c, len, rlm, primary, tcp) \ + TRACE(c, "Sending request ({int} bytes) to {data}{str}{str}", len, \ + rlm, (primary) ? " (primary)" : "", (tcp) ? " (tcp only)" : "") +#define TRACE_SENDTO_KDC_K5TLS_LOAD_ERROR(c, ret) \ + TRACE(c, "Error loading k5tls module: {kerr}", ret) +#define TRACE_SENDTO_KDC_PRIMARY(c, primary) \ + TRACE(c, "Response was{str} from primary KDC", (primary) ? "" : " not") +#define TRACE_SENDTO_KDC_RESOLVING(c, hostname) \ + TRACE(c, "Resolving hostname {str}", hostname) +#define TRACE_SENDTO_KDC_RESPONSE(c, len, raddr) \ + TRACE(c, "Received answer ({int} bytes) from {raddr}", len, raddr) +#define TRACE_SENDTO_KDC_HTTPS_ERROR_CONNECT(c, raddr) \ + TRACE(c, "HTTPS error connecting to {raddr}", raddr) +#define TRACE_SENDTO_KDC_HTTPS_ERROR_RECV(c, raddr) \ + TRACE(c, "HTTPS error receiving from {raddr}", raddr) +#define TRACE_SENDTO_KDC_HTTPS_ERROR_SEND(c, raddr) \ + TRACE(c, "HTTPS error sending to {raddr}", raddr) +#define TRACE_SENDTO_KDC_HTTPS_SEND(c, raddr) \ + TRACE(c, "Sending HTTPS request to {raddr}", raddr) +#define TRACE_SENDTO_KDC_HTTPS_ERROR(c, errs) \ + TRACE(c, "HTTPS error: {str}", errs) +#define TRACE_SENDTO_KDC_TCP_CONNECT(c, raddr) \ + TRACE(c, "Initiating TCP connection to {raddr}", raddr) +#define TRACE_SENDTO_KDC_TCP_DISCONNECT(c, raddr) \ + TRACE(c, "Terminating TCP connection to {raddr}", raddr) +#define TRACE_SENDTO_KDC_TCP_ERROR_CONNECT(c, raddr, err) \ + TRACE(c, "TCP error connecting to {raddr}: {errno}", raddr, err) +#define TRACE_SENDTO_KDC_TCP_ERROR_RECV(c, raddr, err) \ + TRACE(c, "TCP error receiving from {raddr}: {errno}", raddr, err) +#define TRACE_SENDTO_KDC_TCP_ERROR_RECV_LEN(c, raddr, err) \ + TRACE(c, "TCP error receiving from {raddr}: {errno}", raddr, err) +#define TRACE_SENDTO_KDC_TCP_ERROR_SEND(c, raddr, err) \ + TRACE(c, "TCP error sending to {raddr}: {errno}", raddr, err) +#define TRACE_SENDTO_KDC_TCP_SEND(c, raddr) \ + TRACE(c, "Sending TCP request to {raddr}", raddr) +#define TRACE_SENDTO_KDC_UDP_ERROR_RECV(c, raddr, err) \ + TRACE(c, "UDP error receiving from {raddr}: {errno}", raddr, err) +#define TRACE_SENDTO_KDC_UDP_ERROR_SEND_INITIAL(c, raddr, err) \ + TRACE(c, "UDP error sending to {raddr}: {errno}", raddr, err) +#define TRACE_SENDTO_KDC_UDP_ERROR_SEND_RETRY(c, raddr, err) \ + TRACE(c, "UDP error sending to {raddr}: {errno}", raddr, err) +#define TRACE_SENDTO_KDC_UDP_SEND_INITIAL(c, raddr) \ + TRACE(c, "Sending initial UDP request to {raddr}", raddr) +#define TRACE_SENDTO_KDC_UDP_SEND_RETRY(c, raddr) \ + TRACE(c, "Sending retry UDP request to {raddr}", raddr) + +#define TRACE_SEND_TGS_ETYPES(c, etypes) \ + TRACE(c, "etypes requested in TGS request: {etypes}", etypes) +#define TRACE_SEND_TGS_SUBKEY(c, keyblock) \ + TRACE(c, "Generated subkey for TGS request: {keyblock}", keyblock) + +#define TRACE_TGS_REPLY(c, client, server, keyblock) \ + TRACE(c, "TGS reply is for {princ} -> {princ} with session key " \ + "{keyblock}", client, server, keyblock) +#define TRACE_TGS_REPLY_DECODE_SESSION(c, keyblock) \ + TRACE(c, "TGS reply didn't decode with subkey; trying session key " \ + "({keyblock)}", keyblock) + +#define TRACE_TLS_ERROR(c, errs) \ + TRACE(c, "TLS error: {str}", errs) +#define TRACE_TLS_NO_REMOTE_CERTIFICATE(c) \ + TRACE(c, "TLS server certificate not received") +#define TRACE_TLS_CERT_ERROR(c, depth, namelen, name, err, errs) \ + TRACE(c, "TLS certificate error at {int} ({lenstr}): {int} ({str})", \ + depth, namelen, name, err, errs) +#define TRACE_TLS_SERVER_NAME_MISMATCH(c, hostname) \ + TRACE(c, "TLS certificate name mismatch: server certificate is " \ + "not for \"{str}\"", hostname) +#define TRACE_TLS_SERVER_NAME_MATCH(c, hostname) \ + TRACE(c, "TLS certificate name matched \"{str}\"", hostname) + +#define TRACE_TKT_CREDS(c, creds, cache) \ + TRACE(c, "Getting credentials {creds} using ccache {ccache}", \ + creds, cache) +#define TRACE_TKT_CREDS_ADVANCE(c, realm) \ + TRACE(c, "Received TGT for {data}; advancing current realm", realm) +#define TRACE_TKT_CREDS_CACHED_INTERMEDIATE_TGT(c, tgt) \ + TRACE(c, "Found cached TGT for intermediate realm: {creds}", tgt) +#define TRACE_TKT_CREDS_CACHED_SERVICE_TGT(c, tgt) \ + TRACE(c, "Found cached TGT for service realm: {creds}", tgt) +#define TRACE_TKT_CREDS_CLOSER_REALM(c, realm) \ + TRACE(c, "Trying next closer realm in path: {data}", realm) +#define TRACE_TKT_CREDS_COMPLETE(c, princ) \ + TRACE(c, "Received creds for desired service {princ}", princ) +#define TRACE_TKT_CREDS_FALLBACK(c, realm) \ + TRACE(c, "Local realm referral failed; trying fallback realm {data}", \ + realm) +#define TRACE_TKT_CREDS_LOCAL_TGT(c, tgt) \ + TRACE(c, "Starting with TGT for client realm: {creds}", tgt) +#define TRACE_TKT_CREDS_NON_TGT(c, princ) \ + TRACE(c, "Received non-TGT referral response ({princ}); trying " \ + "again without referrals", princ) +#define TRACE_TKT_CREDS_OFFPATH(c, realm) \ + TRACE(c, "Received TGT for offpath realm {data}", realm) +#define TRACE_TKT_CREDS_REFERRAL(c, princ) \ + TRACE(c, "Following referral TGT {princ}", princ) +#define TRACE_TKT_CREDS_REFERRAL_REALM(c, princ) \ + TRACE(c, "Server has referral realm; starting with {princ}", princ) +#define TRACE_TKT_CREDS_RESPONSE_CODE(c, code) \ + TRACE(c, "TGS request result: {kerr}", code) +#define TRACE_TKT_CREDS_RETRY_TCP(c) \ + TRACE(c, "Request or response is too big for UDP; retrying with TCP") +#define TRACE_TKT_CREDS_SAME_REALM_TGT(c, realm) \ + TRACE(c, "Received TGT referral back to same realm ({data}); trying " \ + "again without referrals", realm) +#define TRACE_TKT_CREDS_SERVICE_REQ(c, princ, referral) \ + TRACE(c, "Requesting tickets for {princ}, referrals {str}", princ, \ + (referral) ? "on" : "off") +#define TRACE_TKT_CREDS_TARGET_TGT(c, princ) \ + TRACE(c, "Received TGT for service realm: {princ}", princ) +#define TRACE_TKT_CREDS_TARGET_TGT_OFFPATH(c, princ) \ + TRACE(c, "Received TGT for service realm: {princ}", princ) +#define TRACE_TKT_CREDS_TGT_REQ(c, next, cur) \ + TRACE(c, "Requesting TGT {princ} using TGT {princ}", next, cur) +#define TRACE_TKT_CREDS_WRONG_ENCTYPE(c) \ + TRACE(c, "Retrying TGS request with desired service ticket enctypes") + +#define TRACE_TXT_LOOKUP_NOTFOUND(c, host) \ + TRACE(c, "TXT record {str} not found", host) +#define TRACE_TXT_LOOKUP_SUCCESS(c, host, realm) \ + TRACE(c, "TXT record {str} found: {str}", host, realm) + +#define TRACE_CHECK_REPLY_SERVER_DIFFERS(c, request, reply) \ + TRACE(c, "Reply server {princ} differs from requested {princ}", \ + reply, request) + +#define TRACE_GET_CRED_VIA_TKT_EXT(c, request, reply, kdcoptions) \ + TRACE(c, "Get cred via TGT {princ} after requesting {princ} " \ + "(canonicalize {str})", \ + reply, request, (kdcoptions & KDC_OPT_CANONICALIZE) ? "on" : "off") +#define TRACE_GET_CRED_VIA_TKT_EXT_RETURN(c, ret) \ + TRACE(c, "Got cred; {kerr}", ret) + +#define TRACE_KDCPOLICY_VTINIT_FAIL(c, ret) \ + TRACE(c, "KDC policy module failed to init vtable: {kerr}", ret) +#define TRACE_KDCPOLICY_INIT_SKIP(c, name) \ + TRACE(c, "kadm5_auth module {str} declined to initialize", name) + +#endif /* K5_TRACE_H */ diff --git a/krb5-1.21.3/src/include/k5-unicode.h b/krb5-1.21.3/src/include/k5-unicode.h new file mode 100644 index 00000000..81c495f6 --- /dev/null +++ b/krb5-1.21.3/src/include/k5-unicode.h @@ -0,0 +1,103 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2008 by the Massachusetts Institute of Technology, + * Cambridge, MA, USA. All Rights Reserved. + * + * This software is being provided to you, the LICENSEE, by the + * Massachusetts Institute of Technology (M.I.T.) under the following + * license. By obtaining, using and/or copying this software, you agree + * that you have read, understood, and will comply with these terms and + * conditions: + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute + * this software and its documentation for any purpose and without fee or + * royalty is hereby granted, provided that you agree to comply with the + * following copyright notice and statements, including the disclaimer, and + * that the same appear on ALL copies of the software and documentation, + * including modifications that you make for internal use or for + * distribution: + * + * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS + * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF + * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF + * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY + * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + * + * The name of the Massachusetts Institute of Technology or M.I.T. may NOT + * be used in advertising or publicity pertaining to distribution of the + * software. Title to copyright in this software and any associated + * documentation shall at all times remain with M.I.T., and USER agrees to + * preserve same. + * + * Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + */ +/* + * Copyright 1998-2008 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* + * Copyright (C) 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. + * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION + * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT + * HTTPS://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE + * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS + * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC + * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE + * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + */ + +/* This work is part of OpenLDAP Software . */ + +#ifndef K5_UNICODE_H +#define K5_UNICODE_H + +#include "autoconf.h" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#include "k5-utf8.h" + +typedef krb5_ucs4 krb5_unicode; + +#define KRB5_UTF8_NOCASEFOLD 0x0U +#define KRB5_UTF8_CASEFOLD 0x1U +#define KRB5_UTF8_ARG1NFC 0x2U +#define KRB5_UTF8_ARG2NFC 0x4U +#define KRB5_UTF8_APPROX 0x8U + +int krb5int_utf8_normcmp( + const krb5_data *, + const krb5_data *, + unsigned); + +krb5_boolean k5_utf8_validate(const krb5_data *data); + +#endif /* K5_UNICODE_H */ diff --git a/krb5-1.21.3/src/include/k5-utf8.h b/krb5-1.21.3/src/include/k5-utf8.h new file mode 100644 index 00000000..11949f9f --- /dev/null +++ b/krb5-1.21.3/src/include/k5-utf8.h @@ -0,0 +1,120 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2008 by the Massachusetts Institute of Technology, + * Cambridge, MA, USA. All Rights Reserved. + * + * This software is being provided to you, the LICENSEE, by the + * Massachusetts Institute of Technology (M.I.T.) under the following + * license. By obtaining, using and/or copying this software, you agree + * that you have read, understood, and will comply with these terms and + * conditions: + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute + * this software and its documentation for any purpose and without fee or + * royalty is hereby granted, provided that you agree to comply with the + * following copyright notice and statements, including the disclaimer, and + * that the same appear on ALL copies of the software and documentation, + * including modifications that you make for internal use or for + * distribution: + * + * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS + * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF + * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF + * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY + * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + * + * The name of the Massachusetts Institute of Technology or M.I.T. may NOT + * be used in advertising or publicity pertaining to distribution of the + * software. Title to copyright in this software and any associated + * documentation shall at all times remain with M.I.T., and USER agrees to + * preserve same. + * + * Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + */ +/* + * Copyright 1998-2008 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* + * Copyright (C) 2000 Novell, Inc. All Rights Reserved. + * + * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES. + * USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION + * 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT + * HTTPS://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE + * TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS + * WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC + * LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE + * PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + */ +/* This work is part of OpenLDAP Software . */ + +#ifndef K5_UTF8_H +#define K5_UTF8_H + +#include "k5-platform.h" + +typedef uint16_t krb5_ucs2; +typedef uint32_t krb5_ucs4; + +int krb5int_utf8_to_ucs4(const char *p, krb5_ucs4 *out); +size_t krb5int_ucs4_to_utf8(krb5_ucs4 c, char *buf); + +/* + * Convert a little-endian UTF-16 string to an allocated null-terminated UTF-8 + * string. nbytes is the length of ucs2bytes in bytes, and must be an even + * number. Return EINVAL on invalid input, ENOMEM on out of memory, or 0 on + * success. + */ +int k5_utf16le_to_utf8(const uint8_t *utf16bytes, size_t nbytes, + char **utf8_out); + +/* + * Convert a UTF-8 string to an allocated little-endian UTF-16 string. The + * resulting length is in bytes and will always be even. Return EINVAL on + * invalid input, ENOMEM on out of memory, or 0 on success. + */ +int k5_utf8_to_utf16le(const char *utf8, uint8_t **utf16_out, + size_t *nbytes_out); + +/* Optimizations */ +extern const char krb5int_utf8_lentab[128]; +extern const char krb5int_utf8_mintab[32]; + +#define KRB5_UTF8_BV(p) (*(const unsigned char *)(p)) +#define KRB5_UTF8_ISASCII(p) (!(KRB5_UTF8_BV(p) & 0x80)) +#define KRB5_UTF8_CHARLEN(p) (KRB5_UTF8_ISASCII(p) ? 1 : \ + krb5int_utf8_lentab[KRB5_UTF8_BV(p) ^ 0x80]) + +/* This is like CHARLEN but additionally validates to make sure + * the char used the shortest possible encoding. + * 'l' is used to temporarily hold the result of CHARLEN. + */ +#define KRB5_UTF8_CHARLEN2(p, l) ( \ + ((l = KRB5_UTF8_CHARLEN(p)) < 3 || \ + (krb5int_utf8_mintab[KRB5_UTF8_BV(p) & 0x1f] & (p)[1])) ? \ + l : 0) + +/* + * these macros assume 'x' is an ASCII x + * and assume the "C" locale + */ +#define KRB5_UPPER(c) ((c) >= 'A' && (c) <= 'Z') + +#endif /* K5_UTF8_H */ diff --git a/krb5-1.21.3/src/include/k5-util.h b/krb5-1.21.3/src/include/k5-util.h new file mode 100644 index 00000000..b978760c --- /dev/null +++ b/krb5-1.21.3/src/include/k5-util.h @@ -0,0 +1,88 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1989-1998,2002 by the Massachusetts Institute of Technology, + * Cambridge, MA, USA. All Rights Reserved. + * + * This software is being provided to you, the LICENSEE, by the + * Massachusetts Institute of Technology (M.I.T.) under the following + * license. By obtaining, using and/or copying this software, you agree + * that you have read, understood, and will comply with these terms and + * conditions: + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute + * this software and its documentation for any purpose and without fee or + * royalty is hereby granted, provided that you agree to comply with the + * following copyright notice and statements, including the disclaimer, and + * that the same appear on ALL copies of the software and documentation, + * including modifications that you make for internal use or for + * distribution: + * + * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS + * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF + * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF + * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY + * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + * + * The name of the Massachusetts Institute of Technology or M.I.T. may NOT + * be used in advertising or publicity pertaining to distribution of the + * software. Title to copyright in this software and any associated + * documentation shall at all times remain with M.I.T., and USER agrees to + * preserve same. + * + * Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + */ + +/* + * "internal" utility functions used by various applications. + * They live in libkrb5util. + */ + +#include "autoconf.h" + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#include + +#ifndef krb5_seteuid + +#if defined(HAVE_SETEUID) +# define krb5_seteuid(EUID) (seteuid((uid_t)(EUID))) +#elif defined(HAVE_SETRESUID) +# define krb5_seteuid(EUID) setresuid(getuid(), (uid_t)(EUID), geteuid()) +#elif defined(HAVE_SETREUID) +# define krb5_seteuid(EUID) setreuid(geteuid(), (uid_t)(EUID)) +#else +/* You need to add a case to deal with this operating system.*/ +# define krb5_seteuid(EUID) (errno = EPERM, -1) +#endif + +#ifdef HAVE_SETEGID +# define krb5_setegid(EGID) (setegid((gid_t)(EGID))) +#elif defined(HAVE_SETRESGID) +# define krb5_setegid(EGID) (setresgid(getgid(), (gid_t)(EGID), getegid())) +#elif defined(HAVE_SETREGID) +# define krb5_setegid(EGID) (setregid(getegid(), (gid_t)(EGID))) +#else +/* You need to add a case to deal with this operating system.*/ +# define krb5_setegid(EGID) (errno = EPERM, -1) +#endif + +#endif diff --git a/krb5-1.21.3/src/include/kcm.h b/krb5-1.21.3/src/include/kcm.h new file mode 100644 index 00000000..d5d74aaf --- /dev/null +++ b/krb5-1.21.3/src/include/kcm.h @@ -0,0 +1,120 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/kcm.h - Kerberos cache manager protocol declarations */ +/* + * Copyright (C) 2014 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. + */ + +#ifndef KCM_H +#define KCM_H + +#define KCM_PROTOCOL_VERSION_MAJOR 2 +#define KCM_PROTOCOL_VERSION_MINOR 0 + +#define KCM_UUID_LEN 16 + +/* This should ideally be in RUNSTATEDIR, but Heimdal uses a hardcoded + * /var/run, and we need to use the same default path. */ +#define DEFAULT_KCM_SOCKET_PATH "/var/run/.heim_org.h5l.kcm-socket" +#define DEFAULT_KCM_MACH_SERVICE "org.h5l.kcm" + +/* + * All requests begin with: + * major version (1 bytes) + * minor version (1 bytes) + * opcode (16-bit big-endian) + * + * All replies begin with a 32-bit big-endian reply code. + * + * Parameters are appended to the request or reply with no delimiters. Flags, + * time offsets, and lengths are stored as 32-bit big-endian integers. Names + * are marshalled as zero-terminated strings. Principals and credentials are + * marshalled in the v4 FILE ccache format. UUIDs are 16 bytes. UUID lists + * are not delimited, so nothing can come after them. + * + * Flag words must use Heimdal flag values, which are not the same as MIT krb5 + * values for KRB5_GC and KRB5_TC constants. The same flag word may contain + * both kinds of flags in Heimdal, but not in MIT krb5. Defines for the + * applicable Heimdal flag values are given below using KCM_GC and KCM_TC + * prefixes. + */ + +#define KCM_GC_CACHED (1U << 0) + +#define KCM_TC_DONT_MATCH_REALM (1U << 31) +#define KCM_TC_MATCH_KEYTYPE (1U << 30) +#define KCM_TC_MATCH_SRV_NAMEONLY (1U << 29) +#define KCM_TC_MATCH_FLAGS_EXACT (1U << 28) +#define KCM_TC_MATCH_FLAGS (1U << 27) +#define KCM_TC_MATCH_TIMES_EXACT (1U << 26) +#define KCM_TC_MATCH_TIMES (1U << 25) +#define KCM_TC_MATCH_AUTHDATA (1U << 24) +#define KCM_TC_MATCH_2ND_TKT (1U << 23) +#define KCM_TC_MATCH_IS_SKEY (1U << 22) + +/* Opcodes without comments are currently unused in the MIT client + * implementation. */ +typedef enum kcm_opcode { + KCM_OP_NOOP, + KCM_OP_GET_NAME, + KCM_OP_RESOLVE, + KCM_OP_GEN_NEW, /* () -> (name) */ + KCM_OP_INITIALIZE, /* (name, princ) -> () */ + KCM_OP_DESTROY, /* (name) -> () */ + KCM_OP_STORE, /* (name, cred) -> () */ + KCM_OP_RETRIEVE, /* (name, flags, credtag) -> (cred) */ + KCM_OP_GET_PRINCIPAL, /* (name) -> (princ) */ + KCM_OP_GET_CRED_UUID_LIST, /* (name) -> (uuid, ...) */ + KCM_OP_GET_CRED_BY_UUID, /* (name, uuid) -> (cred) */ + KCM_OP_REMOVE_CRED, /* (name, flags, credtag) -> () */ + KCM_OP_SET_FLAGS, + KCM_OP_CHOWN, + KCM_OP_CHMOD, + KCM_OP_GET_INITIAL_TICKET, + KCM_OP_GET_TICKET, + KCM_OP_MOVE_CACHE, + KCM_OP_GET_CACHE_UUID_LIST, /* () -> (uuid, ...) */ + KCM_OP_GET_CACHE_BY_UUID, /* (uuid) -> (name) */ + KCM_OP_GET_DEFAULT_CACHE, /* () -> (name) */ + KCM_OP_SET_DEFAULT_CACHE, /* (name) -> () */ + KCM_OP_GET_KDC_OFFSET, /* (name) -> (offset) */ + KCM_OP_SET_KDC_OFFSET, /* (name, offset) -> () */ + KCM_OP_ADD_NTLM_CRED, + KCM_OP_HAVE_NTLM_CRED, + KCM_OP_DEL_NTLM_CRED, + KCM_OP_DO_NTLM_AUTH, + KCM_OP_GET_NTLM_USER_LIST, + + /* MIT extensions */ + KCM_OP_MIT_EXTENSION_BASE = 13000, + KCM_OP_GET_CRED_LIST, /* (name) -> (count, count*{len, cred}) */ + KCM_OP_REPLACE, /* (name, offset, princ, + * count, count*{len, cred}) -> () */ +} kcm_opcode; + +#endif /* KCM_H */ diff --git a/krb5-1.21.3/src/include/kdb.h b/krb5-1.21.3/src/include/kdb.h new file mode 100644 index 00000000..745b24f3 --- /dev/null +++ b/krb5-1.21.3/src/include/kdb.h @@ -0,0 +1,1457 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1990, 1991, 2016 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* KDC Database interface definitions */ + +/* This API is not considered as stable as the main krb5 API. + * + * - We may make arbitrary incompatible changes between feature + * releases (e.g. from 1.7 to 1.8). + * - We will make some effort to avoid making incompatible changes for + * bugfix releases, but will make them if necessary. + */ + +#ifndef KRB5_KDB5__ +#define KRB5_KDB5__ + +#include +#include + +/* This version will be incremented when incompatible changes are made to the + * KDB API, and will be kept in sync with the libkdb major version. */ +#define KRB5_KDB_API_VERSION 10 + +/* Salt types */ +#define KRB5_KDB_SALTTYPE_NORMAL 0 +/* #define KRB5_KDB_SALTTYPE_V4 1 */ +#define KRB5_KDB_SALTTYPE_NOREALM 2 +#define KRB5_KDB_SALTTYPE_ONLYREALM 3 +#define KRB5_KDB_SALTTYPE_SPECIAL 4 +/* #define KRB5_KDB_SALTTYPE_AFS3 5 */ +#define KRB5_KDB_SALTTYPE_CERTHASH 6 + +/* Attributes */ +#define KRB5_KDB_DISALLOW_POSTDATED 0x00000001 +#define KRB5_KDB_DISALLOW_FORWARDABLE 0x00000002 +#define KRB5_KDB_DISALLOW_TGT_BASED 0x00000004 +#define KRB5_KDB_DISALLOW_RENEWABLE 0x00000008 +#define KRB5_KDB_DISALLOW_PROXIABLE 0x00000010 +#define KRB5_KDB_DISALLOW_DUP_SKEY 0x00000020 +#define KRB5_KDB_DISALLOW_ALL_TIX 0x00000040 +#define KRB5_KDB_REQUIRES_PRE_AUTH 0x00000080 +#define KRB5_KDB_REQUIRES_HW_AUTH 0x00000100 +#define KRB5_KDB_REQUIRES_PWCHANGE 0x00000200 +#define KRB5_KDB_DISALLOW_SVR 0x00001000 +#define KRB5_KDB_PWCHANGE_SERVICE 0x00002000 +#define KRB5_KDB_SUPPORT_DESMD5 0x00004000 +#define KRB5_KDB_NEW_PRINC 0x00008000 +#define KRB5_KDB_OK_AS_DELEGATE 0x00100000 +#define KRB5_KDB_OK_TO_AUTH_AS_DELEGATE 0x00200000 /* S4U2Self OK */ +#define KRB5_KDB_NO_AUTH_DATA_REQUIRED 0x00400000 +#define KRB5_KDB_LOCKDOWN_KEYS 0x00800000 + +/* Creation flags */ +#define KRB5_KDB_CREATE_BTREE 0x00000001 +#define KRB5_KDB_CREATE_HASH 0x00000002 + +/* Entry get flags */ +/* Okay to generate a referral on lookup */ +#define KRB5_KDB_FLAG_REFERRAL_OK 0x00000010 +/* Client principal lookup (client referrals only) */ +#define KRB5_KDB_FLAG_CLIENT 0x00000040 +/* Map cross-realm principals */ +#define KRB5_KDB_FLAG_MAP_PRINCIPALS 0x00000080 +/* Protocol transition */ +#define KRB5_KDB_FLAG_PROTOCOL_TRANSITION 0x00000100 +/* Constrained delegation */ +#define KRB5_KDB_FLAG_CONSTRAINED_DELEGATION 0x00000200 +/* User-to-user */ +#define KRB5_KDB_FLAG_USER_TO_USER 0x00000800 +/* Cross-realm */ +#define KRB5_KDB_FLAG_CROSS_REALM 0x00001000 +/* Issuing referral */ +#define KRB5_KDB_FLAG_ISSUING_REFERRAL 0x00004000 + + +#define KRB5_KDB_FLAGS_S4U ( KRB5_KDB_FLAG_PROTOCOL_TRANSITION | \ + KRB5_KDB_FLAG_CONSTRAINED_DELEGATION ) + +/* KDB iteration flags */ +#define KRB5_DB_ITER_WRITE 0x00000001 +#define KRB5_DB_ITER_REV 0x00000002 +#define KRB5_DB_ITER_RECURSE 0x00000004 + +/* String attribute names recognized by krb5 */ +#define KRB5_KDB_SK_PAC_PRIVSVR_ENCTYPE "pac_privsvr_enctype" +#define KRB5_KDB_SK_SESSION_ENCTYPES "session_enctypes" +#define KRB5_KDB_SK_REQUIRE_AUTH "require_auth" + +#if !defined(_WIN32) + +/* + * Note --- these structures cannot be modified without changing the + * database version number in libkdb.a, but should be expandable by + * adding new tl_data types. + */ +typedef struct _krb5_tl_data { + struct _krb5_tl_data* tl_data_next; /* NOT saved */ + krb5_int16 tl_data_type; + krb5_ui_2 tl_data_length; + krb5_octet * tl_data_contents; +} krb5_tl_data; + +/* String attributes (currently stored inside tl-data) map C string keys to + * values. They can be set via kadmin and consumed by KDC plugins. */ +typedef struct krb5_string_attr_st { + char *key; + char *value; +} krb5_string_attr; + +/* + * If this ever changes up the version number and make the arrays be as + * big as necessary. + * + * Currently the first type is the enctype and the second is the salt type. + */ +typedef struct _krb5_key_data { + krb5_int16 key_data_ver; /* Version */ + krb5_ui_2 key_data_kvno; /* Key Version */ + krb5_int16 key_data_type[2]; /* Array of types */ + krb5_ui_2 key_data_length[2]; /* Array of lengths */ + krb5_octet * key_data_contents[2]; /* Array of pointers */ +} krb5_key_data; + +#define KRB5_KDB_V1_KEY_DATA_ARRAY 2 /* # of array elements */ + +typedef struct _krb5_keysalt { + krb5_int16 type; + krb5_data data; /* Length, data */ +} krb5_keysalt; + +/* + * A principal database entry. Extensions to this structure currently use the + * tl_data list. The e_data and e_length fields are not used by any calling + * code except kdb5_util dump and load, which marshal and unmarshal the array + * in the dump record. KDB modules may use these fields internally as long as + * they set e_length appropriately (non-zero if the data should be marshalled + * across dump and load, zero if not) and handle null e_data values in + * caller-constructed principal entries. + */ +typedef struct _krb5_db_entry_new { + krb5_magic magic; /* NOT saved */ + krb5_ui_2 len; + krb5_ui_4 mask; /* members currently changed/set */ + krb5_flags attributes; + krb5_deltat max_life; + krb5_deltat max_renewable_life; + krb5_timestamp expiration; /* When the client expires */ + krb5_timestamp pw_expiration; /* When its passwd expires */ + krb5_timestamp last_success; /* Last successful passwd */ + krb5_timestamp last_failed; /* Last failed passwd attempt */ + krb5_kvno fail_auth_count; /* # of failed passwd attempt */ + krb5_int16 n_tl_data; + krb5_int16 n_key_data; + krb5_ui_2 e_length; /* Length of extra data */ + krb5_octet * e_data; /* Extra data to be saved */ + + krb5_principal princ; /* Length, data */ + krb5_tl_data * tl_data; /* Linked list */ + + /* key_data must be sorted by kvno in descending order. */ + krb5_key_data * key_data; /* Array */ +} krb5_db_entry; + +typedef struct _osa_policy_ent_t { + int version; + char *name; + krb5_ui_4 pw_min_life; + krb5_ui_4 pw_max_life; + krb5_ui_4 pw_min_length; + krb5_ui_4 pw_min_classes; + krb5_ui_4 pw_history_num; + krb5_ui_4 policy_refcnt; /* no longer used */ + /* Only valid if version > 1 */ + krb5_ui_4 pw_max_fail; /* pwdMaxFailure */ + krb5_ui_4 pw_failcnt_interval; /* pwdFailureCountInterval */ + krb5_ui_4 pw_lockout_duration; /* pwdLockoutDuration */ + /* Only valid if version > 2 */ + krb5_ui_4 attributes; + krb5_ui_4 max_life; + krb5_ui_4 max_renewable_life; + char * allowed_keysalts; + krb5_int16 n_tl_data; + krb5_tl_data * tl_data; +} osa_policy_ent_rec, *osa_policy_ent_t; + +typedef void (*osa_adb_iter_policy_func) (void *, osa_policy_ent_t); + +typedef struct __krb5_key_salt_tuple { + krb5_enctype ks_enctype; + krb5_int32 ks_salttype; +} krb5_key_salt_tuple; + +#define KRB5_KDB_MAGIC_NUMBER 0xdbdbdbdb +#define KRB5_KDB_V1_BASE_LENGTH 38 + +#define KRB5_KDB_MAX_ALLOWED_KS_LEN 512 + +#define KRB5_TL_LAST_PWD_CHANGE 0x0001 +#define KRB5_TL_MOD_PRINC 0x0002 +#define KRB5_TL_KADM_DATA 0x0003 +#define KRB5_TL_KADM5_E_DATA 0x0004 +#define KRB5_TL_RB1_CHALLENGE 0x0005 +#ifdef SECURID +#define KRB5_TL_SECURID_STATE 0x0006 +#endif /* SECURID */ +#define KRB5_TL_USER_CERTIFICATE 0x0007 +#define KRB5_TL_MKVNO 0x0008 +#define KRB5_TL_ACTKVNO 0x0009 +#define KRB5_TL_MKEY_AUX 0x000a + +/* String attributes may not always be represented in tl-data. kadmin clients + * must use the get_strings and set_string RPCs. */ +#define KRB5_TL_STRING_ATTRS 0x000b + +#define KRB5_TL_PAC_LOGON_INFO 0x0100 /* NDR encoded validation info */ +#define KRB5_TL_SERVER_REFERRAL 0x0200 /* ASN.1 encoded ServerReferralInfo */ +#define KRB5_TL_SVR_REFERRAL_DATA 0x0300 /* ASN.1 encoded PA-SVR-REFERRAL-DATA */ +#define KRB5_TL_CONSTRAINED_DELEGATION_ACL 0x0400 /* Each entry is a permitted SPN */ +#define KRB5_TL_LM_KEY 0x0500 /* LM OWF */ +#define KRB5_TL_X509_SUBJECT_ISSUER_NAME 0x0600 /* IssuerDNSubjectDN */ +#define KRB5_TL_LAST_ADMIN_UNLOCK 0x0700 /* Timestamp of admin unlock */ + +#define KRB5_TL_DB_ARGS 0x7fff + +/* version number for KRB5_TL_ACTKVNO data */ +#define KRB5_TL_ACTKVNO_VER 1 + +/* version number for KRB5_TL_MKEY_AUX data */ +#define KRB5_TL_MKEY_AUX_VER 1 + +typedef struct _krb5_actkvno_node { + struct _krb5_actkvno_node *next; + krb5_kvno act_kvno; + krb5_timestamp act_time; +} krb5_actkvno_node; + +typedef struct _krb5_mkey_aux_node { + struct _krb5_mkey_aux_node *next; + krb5_kvno mkey_kvno; /* kvno of mkey protecting the latest_mkey */ + krb5_key_data latest_mkey; /* most recent mkey */ +} krb5_mkey_aux_node; + +typedef struct _krb5_keylist_node { + krb5_keyblock keyblock; + krb5_kvno kvno; + struct _krb5_keylist_node *next; +} krb5_keylist_node; + +/* + * Determines the number of failed KDC requests before DISALLOW_ALL_TIX is set + * on the principal. + */ +#define KRB5_MAX_FAIL_COUNT 5 + +/* XXX depends on knowledge of krb5_parse_name() formats */ +#define KRB5_KDB_M_NAME "K/M" /* Kerberos/Master */ + +/* prompts used by default when reading the KDC password from the keyboard. */ +#define KRB5_KDC_MKEY_1 "Enter KDC database master key" +#define KRB5_KDC_MKEY_2 "Re-enter KDC database master key to verify" + + +extern char *krb5_mkey_pwd_prompt1; +extern char *krb5_mkey_pwd_prompt2; + +/* + * These macros specify the encoding of data within the database. + * + * Data encoding is little-endian. + */ +#ifdef _KRB5_INT_H +#include "k5-platform.h" +#define krb5_kdb_decode_int16(cp, i16) \ + *((krb5_int16 *) &(i16)) = load_16_le(cp) +#define krb5_kdb_decode_int32(cp, i32) \ + *((krb5_int32 *) &(i32)) = load_32_le(cp) +#define krb5_kdb_encode_int16(i16, cp) store_16_le(i16, cp) +#define krb5_kdb_encode_int32(i32, cp) store_32_le(i32, cp) +#endif /* _KRB5_INT_H */ + +#define KRB5_KDB_OPEN_RW 0 +#define KRB5_KDB_OPEN_RO 1 + +#ifndef KRB5_KDB_SRV_TYPE_KDC +#define KRB5_KDB_SRV_TYPE_KDC 0x0100 +#endif + +#ifndef KRB5_KDB_SRV_TYPE_ADMIN +#define KRB5_KDB_SRV_TYPE_ADMIN 0x0200 +#endif + +/* 0x0300 was KRB5_KDB_SRV_TYPE_PASSWD but it is no longer used. */ + +#ifndef KRB5_KDB_SRV_TYPE_OTHER +#define KRB5_KDB_SRV_TYPE_OTHER 0x0400 +#endif + +#define KRB5_KDB_OPT_SET_DB_NAME 0 +#define KRB5_KDB_OPT_SET_LOCK_MODE 1 + +#define KRB5_DB_LOCKMODE_SHARED 0x0001 +#define KRB5_DB_LOCKMODE_EXCLUSIVE 0x0002 +#define KRB5_DB_LOCKMODE_PERMANENT 0x0008 + +/* libkdb.spec */ +krb5_error_code krb5_db_setup_lib_handle(krb5_context kcontext); +krb5_error_code krb5_db_open( krb5_context kcontext, char **db_args, int mode ); +krb5_error_code krb5_db_init ( krb5_context kcontext ); +krb5_error_code krb5_db_create ( krb5_context kcontext, char **db_args ); +krb5_error_code krb5_db_inited ( krb5_context kcontext ); +krb5_error_code kdb5_db_create ( krb5_context kcontext, char **db_args ); +krb5_error_code krb5_db_fini ( krb5_context kcontext ); +const char * krb5_db_errcode2string ( krb5_context kcontext, long err_code ); +krb5_error_code krb5_db_destroy ( krb5_context kcontext, char **db_args ); +krb5_error_code krb5_db_promote ( krb5_context kcontext, char **db_args ); +krb5_error_code krb5_db_get_age ( krb5_context kcontext, char *db_name, time_t *t ); +krb5_error_code krb5_db_lock ( krb5_context kcontext, int lock_mode ); +krb5_error_code krb5_db_unlock ( krb5_context kcontext ); +krb5_error_code krb5_db_get_principal ( krb5_context kcontext, + krb5_const_principal search_for, + unsigned int flags, + krb5_db_entry **entry ); +void krb5_db_free_principal ( krb5_context kcontext, krb5_db_entry *entry ); +krb5_error_code krb5_db_put_principal ( krb5_context kcontext, + krb5_db_entry *entry ); +krb5_error_code krb5_db_delete_principal ( krb5_context kcontext, + krb5_principal search_for ); +krb5_error_code krb5_db_rename_principal ( krb5_context kcontext, + krb5_principal source, + krb5_principal target ); + +/* + * Iterate over principals in the KDB. If the callback may write to the DB, + * the caller must get an exclusive lock with krb5_db_lock before iterating, + * and release it with krb5_db_unlock after iterating. + */ +krb5_error_code krb5_db_iterate ( krb5_context kcontext, + char *match_entry, + int (*func) (krb5_pointer, krb5_db_entry *), + krb5_pointer func_arg, krb5_flags iterflags ); + + +krb5_error_code krb5_db_store_master_key ( krb5_context kcontext, + char *keyfile, + krb5_principal mname, + krb5_kvno kvno, + krb5_keyblock *key, + char *master_pwd); +krb5_error_code krb5_db_store_master_key_list ( krb5_context kcontext, + char *keyfile, + krb5_principal mname, + char *master_pwd); +krb5_error_code krb5_db_fetch_mkey ( krb5_context context, + krb5_principal mname, + krb5_enctype etype, + krb5_boolean fromkeyboard, + krb5_boolean twice, + char *db_args, + krb5_kvno *kvno, + krb5_data *salt, + krb5_keyblock *key); +krb5_error_code +krb5_db_fetch_mkey_list( krb5_context context, + krb5_principal mname, + const krb5_keyblock * mkey ); + +krb5_error_code +krb5_dbe_find_enctype( krb5_context kcontext, + krb5_db_entry *dbentp, + krb5_int32 ktype, + krb5_int32 stype, + krb5_int32 kvno, + krb5_key_data **kdatap); + + +krb5_error_code krb5_dbe_search_enctype ( krb5_context kcontext, + krb5_db_entry *dbentp, + krb5_int32 *start, + krb5_int32 ktype, + krb5_int32 stype, + krb5_int32 kvno, + krb5_key_data **kdatap); + +krb5_error_code +krb5_db_setup_mkey_name ( krb5_context context, + const char *keyname, + const char *realm, + char **fullname, + krb5_principal *principal); + +/** + * Decrypts the key given in @@a key_data. If @a mkey is specified, that + * master key is used. If @a mkey is NULL, then all master keys are tried. + */ +krb5_error_code +krb5_dbe_decrypt_key_data( krb5_context context, + const krb5_keyblock * mkey, + const krb5_key_data * key_data, + krb5_keyblock * dbkey, + krb5_keysalt * keysalt); + +krb5_error_code +krb5_dbe_encrypt_key_data( krb5_context context, + const krb5_keyblock * mkey, + const krb5_keyblock * dbkey, + const krb5_keysalt * keysalt, + int keyver, + krb5_key_data * key_data); + +krb5_error_code +krb5_dbe_fetch_act_key_list(krb5_context context, + krb5_principal princ, + krb5_actkvno_node **act_key_list); + +krb5_error_code +krb5_dbe_find_act_mkey( krb5_context context, + krb5_actkvno_node * act_mkey_list, + krb5_kvno * act_kvno, + krb5_keyblock ** act_mkey); + +krb5_error_code +krb5_dbe_find_mkey( krb5_context context, + krb5_db_entry * entry, + krb5_keyblock ** mkey); + +/* Set *mkvno to mkvno in entry tl_data, or 0 if not present. */ +krb5_error_code +krb5_dbe_lookup_mkvno( krb5_context context, + krb5_db_entry * entry, + krb5_kvno * mkvno); + +krb5_keylist_node * +krb5_db_mkey_list_alias( krb5_context kcontext ); + +/* Set *mkvno to mkvno in entry tl_data, or minimum value from mkey_list. */ +krb5_error_code +krb5_dbe_get_mkvno( krb5_context context, + krb5_db_entry * entry, + krb5_kvno * mkvno); + +krb5_error_code +krb5_dbe_lookup_mod_princ_data( krb5_context context, + krb5_db_entry * entry, + krb5_timestamp * mod_time, + krb5_principal * mod_princ); + +krb5_error_code +krb5_dbe_lookup_mkey_aux( krb5_context context, + krb5_db_entry * entry, + krb5_mkey_aux_node ** mkey_aux_data_list); +krb5_error_code +krb5_dbe_update_mkvno( krb5_context context, + krb5_db_entry * entry, + krb5_kvno mkvno); + +krb5_error_code +krb5_dbe_lookup_actkvno( krb5_context context, + krb5_db_entry * entry, + krb5_actkvno_node ** actkvno_list); + +krb5_error_code +krb5_dbe_update_mkey_aux( krb5_context context, + krb5_db_entry * entry, + krb5_mkey_aux_node * mkey_aux_data_list); + +krb5_error_code +krb5_dbe_update_actkvno(krb5_context context, + krb5_db_entry * entry, + const krb5_actkvno_node *actkvno_list); + +krb5_error_code +krb5_dbe_update_last_pwd_change( krb5_context context, + krb5_db_entry * entry, + krb5_timestamp stamp); + +krb5_error_code +krb5_dbe_update_last_admin_unlock( krb5_context context, + krb5_db_entry * entry, + krb5_timestamp stamp); + +krb5_error_code +krb5_dbe_lookup_tl_data( krb5_context context, + krb5_db_entry * entry, + krb5_tl_data * ret_tl_data); + +krb5_error_code +krb5_dbe_create_key_data( krb5_context context, + krb5_db_entry * entry); + + +krb5_error_code +krb5_dbe_update_mod_princ_data( krb5_context context, + krb5_db_entry * entry, + krb5_timestamp mod_date, + krb5_const_principal mod_princ); + +/* + * These are wrappers around realloc() and free(). Applications and KDB + * modules can use them when manipulating principal and policy entries to + * ensure that they allocate and free memory in a manner compatible with the + * library. Using libkrb5 or libkbd5 functions to construct values (such as + * krb5_copy_principal() to construct the princ field of a krb5_db_entry) is + * also safe. On Unix platforms, just using malloc() and free() is safe as + * long as the application or module does not use a malloc replacement. + */ +void *krb5_db_alloc( krb5_context kcontext, + void *ptr, + size_t size ); +void krb5_db_free( krb5_context kcontext, + void *ptr); + + +krb5_error_code +krb5_dbe_lookup_last_pwd_change( krb5_context context, + krb5_db_entry * entry, + krb5_timestamp * stamp); + +krb5_error_code +krb5_dbe_lookup_last_admin_unlock( krb5_context context, + krb5_db_entry * entry, + krb5_timestamp * stamp); + +/* Retrieve the set of string attributes in entry, in no particular order. + * Free *strings_out with krb5_dbe_free_strings when done. */ +krb5_error_code +krb5_dbe_get_strings(krb5_context context, krb5_db_entry *entry, + krb5_string_attr **strings_out, int *count_out); + +/* Retrieve a single string attribute from entry, or NULL if there is no + * attribute for key. Free *value_out with krb5_dbe_free_string when done. */ +krb5_error_code +krb5_dbe_get_string(krb5_context context, krb5_db_entry *entry, + const char *key, char **value_out); + +/* Change or add a string attribute in entry, or delete it if value is NULL. */ +krb5_error_code +krb5_dbe_set_string(krb5_context context, krb5_db_entry *entry, + const char *key, const char *value); + +krb5_error_code +krb5_dbe_delete_tl_data( krb5_context context, + krb5_db_entry * entry, + krb5_int16 tl_data_type); + +krb5_error_code +krb5_db_update_tl_data(krb5_context context, + krb5_int16 * n_tl_datap, + krb5_tl_data **tl_datap, + krb5_tl_data * new_tl_data); + +krb5_error_code +krb5_dbe_update_tl_data( krb5_context context, + krb5_db_entry * entry, + krb5_tl_data * new_tl_data); + +/* Compute the salt for a key data entry given the corresponding principal. */ +krb5_error_code +krb5_dbe_compute_salt(krb5_context context, const krb5_key_data *key, + krb5_const_principal princ, krb5_int16 *salttype_out, + krb5_data **salt_out); + +/* + * Modify the key data of entry to explicitly store salt values using the + * KRB5_KDB_SALTTYPE_SPECIAL salt type. + */ +krb5_error_code +krb5_dbe_specialize_salt(krb5_context context, krb5_db_entry *entry); + +krb5_error_code +krb5_dbe_cpw( krb5_context kcontext, + krb5_keyblock * master_key, + krb5_key_salt_tuple * ks_tuple, + int ks_tuple_count, + char * passwd, + int new_kvno, + krb5_boolean keepold, + krb5_db_entry * db_entry); + + +krb5_error_code +krb5_dbe_ark( krb5_context context, + krb5_keyblock * master_key, + krb5_key_salt_tuple * ks_tuple, + int ks_tuple_count, + krb5_db_entry * db_entry); + +krb5_error_code +krb5_dbe_crk( krb5_context context, + krb5_keyblock * master_key, + krb5_key_salt_tuple * ks_tuple, + int ks_tuple_count, + krb5_boolean keepold, + krb5_db_entry * db_entry); + +krb5_error_code +krb5_dbe_apw( krb5_context context, + krb5_keyblock * master_key, + krb5_key_salt_tuple * ks_tuple, + int ks_tuple_count, + char * passwd, + krb5_db_entry * db_entry); + +int +krb5_db_get_key_data_kvno( krb5_context context, + int count, + krb5_key_data * data); + +krb5_error_code krb5_db_check_transited_realms(krb5_context kcontext, + const krb5_data *tr_contents, + const krb5_data *client_realm, + const krb5_data *server_realm); + +krb5_error_code krb5_db_check_policy_as(krb5_context kcontext, + krb5_kdc_req *request, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_timestamp kdc_time, + const char **status, + krb5_pa_data ***e_data); + +krb5_error_code krb5_db_check_policy_tgs(krb5_context kcontext, + krb5_kdc_req *request, + krb5_db_entry *server, + krb5_ticket *ticket, + const char **status, + krb5_pa_data ***e_data); + +void krb5_db_audit_as_req(krb5_context kcontext, krb5_kdc_req *request, + const krb5_address *local_addr, + const krb5_address *remote_addr, + krb5_db_entry *client, krb5_db_entry *server, + krb5_timestamp authtime, krb5_error_code error_code); + +void krb5_db_refresh_config(krb5_context kcontext); + +krb5_error_code krb5_db_check_allowed_to_delegate(krb5_context kcontext, + krb5_const_principal client, + const krb5_db_entry *server, + krb5_const_principal proxy); + +krb5_error_code krb5_db_get_s4u_x509_principal(krb5_context kcontext, + const krb5_data *client_cert, + krb5_const_principal in_princ, + unsigned int flags, + krb5_db_entry **entry); + +krb5_error_code krb5_db_allowed_to_delegate_from(krb5_context context, + krb5_const_principal client, + krb5_const_principal server, + krb5_pac server_pac, + const krb5_db_entry *proxy); + +/** + * Sort an array of @a krb5_key_data keys in descending order by their kvno. + * Key data order within a kvno is preserved. + * + * @param key_data + * The @a krb5_key_data array to sort. This is sorted in place so the + * array will be modified. + * @param key_data_length + * The length of @a key_data. + */ +void +krb5_dbe_sort_key_data(krb5_key_data *key_data, size_t key_data_length); + +krb5_error_code +krb5_db_issue_pac(krb5_context context, unsigned int flags, + krb5_db_entry *client, krb5_keyblock *replaced_reply_key, + krb5_db_entry *server, krb5_db_entry *krbtgt, + krb5_timestamp authtime, krb5_pac old_pac, krb5_pac new_pac, + krb5_data ***auth_indicators); + +/* default functions. Should not be directly called */ +/* + * Default functions prototype + */ + +krb5_error_code +krb5_dbe_def_search_enctype( krb5_context kcontext, + krb5_db_entry *dbentp, + krb5_int32 *start, + krb5_int32 ktype, + krb5_int32 stype, + krb5_int32 kvno, + krb5_key_data **kdatap); + +krb5_error_code +krb5_def_store_mkey_list( krb5_context context, + char *keyfile, + krb5_principal mname, + krb5_keylist_node *keylist, + char *master_pwd); + +krb5_error_code +krb5_db_def_fetch_mkey( krb5_context context, + krb5_principal mname, + krb5_keyblock *key, + krb5_kvno *kvno, + char *db_args); + +krb5_error_code +krb5_def_fetch_mkey_list( krb5_context context, + krb5_principal mprinc, + const krb5_keyblock *mkey, + krb5_keylist_node **mkeys_list); + +krb5_error_code +krb5_dbe_def_cpw( krb5_context context, + krb5_keyblock * master_key, + krb5_key_salt_tuple * ks_tuple, + int ks_tuple_count, + char * passwd, + int new_kvno, + krb5_boolean keepold, + krb5_db_entry * db_entry); + +krb5_error_code +krb5_dbe_def_decrypt_key_data( krb5_context context, + const krb5_keyblock * mkey, + const krb5_key_data * key_data, + krb5_keyblock * dbkey, + krb5_keysalt * keysalt); + +krb5_error_code +krb5_dbe_def_encrypt_key_data( krb5_context context, + const krb5_keyblock * mkey, + const krb5_keyblock * dbkey, + const krb5_keysalt * keysalt, + int keyver, + krb5_key_data * key_data); + +krb5_error_code +krb5_db_def_rename_principal( krb5_context kcontext, + krb5_const_principal source, + krb5_const_principal target); + +krb5_error_code +krb5_db_create_policy( krb5_context kcontext, + osa_policy_ent_t policy); + +krb5_error_code +krb5_db_get_policy ( krb5_context kcontext, + char *name, + osa_policy_ent_t *policy ); + +krb5_error_code +krb5_db_put_policy( krb5_context kcontext, + osa_policy_ent_t policy); + +krb5_error_code +krb5_db_iter_policy( krb5_context kcontext, + char *match_entry, + osa_adb_iter_policy_func func, + void *data); + +krb5_error_code +krb5_db_delete_policy( krb5_context kcontext, + char *policy); + +void +krb5_db_free_policy( krb5_context kcontext, + osa_policy_ent_t policy); + + +krb5_error_code +krb5_db_set_context(krb5_context, void *db_context); + +krb5_error_code +krb5_db_get_context(krb5_context, void **db_context); + +void +krb5_dbe_free_key_data_contents(krb5_context, krb5_key_data *); + +void +krb5_dbe_free_key_list(krb5_context, krb5_keylist_node *); + +void +krb5_dbe_free_actkvno_list(krb5_context, krb5_actkvno_node *); + +void +krb5_dbe_free_mkey_aux_list(krb5_context, krb5_mkey_aux_node *); + +void +krb5_dbe_free_tl_data(krb5_context, krb5_tl_data *); + +void +krb5_dbe_free_strings(krb5_context, krb5_string_attr *, int count); + +void +krb5_dbe_free_string(krb5_context, char *); + +/* + * Register the KDB keytab type, allowing "KDB:" to be used as a keytab name. + * For this type to work, the context used for keytab operations must have an + * associated database handle (via krb5_db_open()). + */ +krb5_error_code krb5_db_register_keytab(krb5_context context); + +#define KRB5_KDB_DEF_FLAGS 0 + +#define KDB_MAX_DB_NAME 128 +#define KDB_REALM_SECTION "realms" +#define KDB_MODULE_POINTER "database_module" +#define KDB_MODULE_DEF_SECTION "dbdefaults" +#define KDB_MODULE_SECTION "dbmodules" +#define KDB_LIB_POINTER "db_library" +#define KDB_DATABASE_CONF_FILE DEFAULT_SECURE_PROFILE_PATH +#define KDB_DATABASE_ENV_PROF KDC_PROFILE_ENV + +#define KRB5_KDB_OPEN_RW 0 +#define KRB5_KDB_OPEN_RO 1 + +#define KRB5_KDB_OPT_SET_DB_NAME 0 +#define KRB5_KDB_OPT_SET_LOCK_MODE 1 + +/* + * This number indicates the date of the last incompatible change to the DAL. + * The maj_ver field of the module's vtable structure must match this version. + */ +#define KRB5_KDB_DAL_MAJOR_VERSION 9 + +/* + * Note the following when converting a module to DAL version 9: + * + * - get_authdata_info() and sign_authdata() have been removed, and issue_pac() + * has been added. + * + * - check_allowed_to_delegate() must handle a null proxy argument, returning + * success if server has any authorized delegation targets in the traditional + * scheme. + * + * - allowed_to_delegate_from() accepts a krb5_pac parameter (in place + * server_ad_info) for the impersonator's PAC. + * + * - check_allowed_to_delegate() and allowed_to_delegate_from() must return + * KRB5KDC_ERR_BADOPTION on authorization failure. + * + * - the KRB5_KDB_FLAG_ISSUE_PAC and KRB5_FLAG_CLIENT_REFERRALS_ONLY flags have + * been combined into KRB5_KDB_FLAG_CLIENT. + * + * - the KRB5_KDB_FLAG_CANONICALIZE flag has been renamed to + * KRB5_KDB_FLAG_REFERRAL_OK, and is only passed to get_principal() when a + * realm referral is allowed (AS client and TGS server lookups, when the + * CANONICALIZE option is requested or, for AS requests, when the client is + * an enterprise principal). As of DAL version 8 the KDB module should + * always canonicalize aliases within a realm; the KDC will decide whether to + * use the original or canonical principal. + */ + +/* + * A krb5_context can hold one database object. Modules should use + * krb5_db_set_context and krb5_db_get_context to store state associated with + * the database object. + * + * Some module functions are mandatory for KDC operation; others are optional + * or apply only to administrative operations. If a function is optional, a + * module can leave the function pointer as NULL. Alternatively, modules can + * return KRB5_PLUGIN_OP_NOTSUPP when asked to perform an inapplicable action. + * + * Some module functions have default implementations which will call back into + * the vtable interface. Leave these functions as NULL to use the default + * implementations. + * + * The documentation in these comments describes the DAL as it is currently + * implemented and used, not as it should be. So if anything seems off, that + * probably means the current state of things is off. + * + * Modules must allocate memory for principal entries, policy entries, and + * other structures using an allocator compatible with malloc() as seen by + * libkdb5 and libkrb5. Modules may link against libkdb5 and call + * krb5_db_alloc() to be certain that the same malloc implementation is used. + */ + +typedef struct _kdb_vftabl { + short int maj_ver; + short int min_ver; + + /* + * Mandatory: Invoked after the module library is loaded, when the first DB + * using the module is opened, across all contexts. + */ + krb5_error_code (*init_library)(void); + + /* + * Mandatory: Invoked before the module library is unloaded, after the last + * DB using the module is closed, across all contexts. + */ + krb5_error_code (*fini_library)(void); + + /* + * Mandatory: Initialize a database object. Profile settings should be + * read from conf_section inside KDB_MODULE_SECTION. db_args communicates + * command-line arguments for module-specific flags. mode will be one of + * KRB5_KDB_OPEN_{RW,RO} or'd with one of + * KRB5_KDB_SRV_TYPE_{KDC,ADMIN,PASSWD,OTHER}. + */ + krb5_error_code (*init_module)(krb5_context kcontext, char *conf_section, + char **db_args, int mode); + + /* + * Mandatory: Finalize the database object contained in a context. Free + * any state contained in the db_context pointer and null it out. + */ + krb5_error_code (*fini_module)(krb5_context kcontext); + + /* + * Optional: Initialize a database object while creating the underlying + * database. conf_section and db_args have the same meaning as in + * init_module. This function may return an error if the database already + * exists. Used by kdb5_util create. + * + * If db_args contains the value "temporary", the module should create an + * exclusively locked side copy of the database suitable for loading in a + * propagation from primary to replica. This side copy will later be + * promoted with promote_db, allowing complete updates of the DB with no + * loss in read availability. If the module cannot comply with this + * architecture, it should return an error. + */ + krb5_error_code (*create)(krb5_context kcontext, char *conf_section, + char **db_args); + + /* + * Optional: Destroy a database. conf_section and db_args have the same + * meaning as in init_module. Used by kdb5_util destroy. In current + * usage, the database is destroyed while open, so the module should handle + * that. + */ + krb5_error_code (*destroy)(krb5_context kcontext, char *conf_section, + char **db_args); + + /* + * Deprecated: No longer used as of krb5 1.10; can be removed in the next + * DAL revision. Modules should leave as NULL. + */ + krb5_error_code (*get_age)(krb5_context kcontext, char *db_name, + time_t *age); + + /* + * Optional: Lock the database, with semantics depending on the mode + * argument: + * + * KRB5_DB_LOCKMODE_SHARED: Lock may coexist with other shared locks. + * KRB5_DB_LOCKMODE_EXCLUSIVE: Lock may not coexist with other locks. + * KRB5_DB_LOCKMODE_PERMANENT: Exclusive lock surviving process exit. + * + * Used by the "kadmin lock" command, incremental propagation, and + * kdb5_util dump. Incremental propagation support requires shared locks + * to operate. kdb5_util dump will continue unlocked if the module returns + * KRB5_PLUGIN_OP_NOTSUPP. + */ + krb5_error_code (*lock)(krb5_context kcontext, int mode); + + /* Optional: Release a lock created with db_lock. */ + krb5_error_code (*unlock)(krb5_context kcontext); + + /* + * Mandatory: Set *entry to an allocated entry for the principal + * search_for. If the principal is not found, return KRB5_KDB_NOENTRY. + * + * The meaning of flags are as follows: + * + * KRB5_KDB_FLAG_REFERRAL_OK: Set by the KDC when looking up entries for an + * AS client with canonicalization requested or for an enterprise + * principal, or for a TGS request server with canonicalization + * requested. Determines whether the module should return out-of-realm + * referrals. + * + * KRB5_KDB_FLAG_CLIENT: Set by the KDC when looking up a client principal + * during an AS or TGS request. Affects how the module should return + * out-of-realm referrals. + * + * KRB5_KDB_FLAG_MAP_PRINCIPALS: Set by the KDC when looking up the client + * entry during TGS requests, except for S4U TGS requests and requests + * where the server entry has the KRB5_KDB_NO_AUTH_DATA_REQUIRED + * attribute. Indicates that the module should map foreign principals + * to local principals if it supports doing so. + * + * KRB5_KDB_FLAG_PROTOCOL_TRANSITION: Set by the KDC when looking up the + * client entry during an S4U2Self TGS request. This affects the PAC + * information which should be included when authorization data is + * generated; see the Microsoft S4U specification for details. + * + * KRB5_KDB_FLAG_CONSTRAINED_DELEGATION: Set by the KDC when looking up the + * client entry during an S4U2Proxy TGS request. Also affects PAC + * generation. + * + * KRB5_KDB_FLAG_CROSS_REALM: Set by the KDC after looking up a server + * entry during a TGS request, if the header ticket was issued by a + * different realm. + * + * KRB5_KDB_FLAG_ISSUING_REFERRAL: Set by the KDC after looking up a server + * entry during a TGS request, if the requested server principal is not + * part of the realm being served, and a referral or alternate TGT will + * be issued instead. + * + * A module may return an in-realm alias by setting (*entry)->princ to the + * canonical name. The KDC will decide based on the request whether to use + * the requested name or the canonical name in the issued ticket. + * + * A module can return a referral to another realm if flags contains + * KRB5_KDB_FLAG_REFERRAL_OK. If KRB5_KDB_FLAG_CLIENT is also set, the + * module should return a referral by simply filling in an out-of-realm + * name in (*entry)->princ and setting all other fields to NULL. + * Otherwise, the module should return the entry for the cross-realm TGS of + * the referred-to realm. + */ + krb5_error_code (*get_principal)(krb5_context kcontext, + krb5_const_principal search_for, + unsigned int flags, + krb5_db_entry **entry); + + /* + * Optional: Create or modify a principal entry. db_args communicates + * command-line arguments for module-specific flags. + * + * The mask field of an entry indicates the changed fields. Mask values + * are defined in kadmin's admin.h header. If KADM5_PRINCIPAL is set in + * the mask, the entry is new; otherwise it already exists. All fields of + * an entry are expected to contain correct values, regardless of whether + * they are specified in the mask, so it is acceptable for a module to + * ignore the mask and update the entire entry. + */ + krb5_error_code (*put_principal)(krb5_context kcontext, + krb5_db_entry *entry, char **db_args); + + /* + * Optional: Delete the entry for the principal search_for. If the + * principal did not exist, return KRB5_KDB_NOENTRY. + */ + krb5_error_code (*delete_principal)(krb5_context kcontext, + krb5_const_principal search_for); + + /* + * Optional with default: Rename a principal. If the source principal does + * not exist, return KRB5_KDB_NOENTRY. If the target exists, return an + * error. + * + * NOTE: If the module chooses to implement a custom function for renaming + * a principal instead of using the default, then rename operations will + * fail if iprop logging is enabled. + */ + krb5_error_code (*rename_principal)(krb5_context kcontext, + krb5_const_principal source, + krb5_const_principal target); + + /* + * Optional: For each principal entry in the database, invoke func with the + * arguments func_arg and the entry data. If match_entry is specified, the + * module may narrow the iteration to principal names matching that regular + * expression; a module may alternatively ignore match_entry. + */ + krb5_error_code (*iterate)(krb5_context kcontext, + char *match_entry, + int (*func)(krb5_pointer, krb5_db_entry *), + krb5_pointer func_arg, krb5_flags iterflags); + + /* + * Optional: Create a password policy entry. Return an error if the policy + * already exists. + */ + krb5_error_code (*create_policy)(krb5_context kcontext, + osa_policy_ent_t policy); + + /* + * Optional: Set *policy to the policy entry of the specified name. If the + * entry does not exist, return KRB5_KDB_NOENTRY. + */ + krb5_error_code (*get_policy)(krb5_context kcontext, char *name, + osa_policy_ent_t *policy); + + /* + * Optional: Modify an existing password policy entry to match the values + * in policy. Return an error if the policy does not already exist. + */ + krb5_error_code (*put_policy)(krb5_context kcontext, + osa_policy_ent_t policy); + + /* + * Optional: For each password policy entry in the database, invoke func + * with the arguments data and the entry data. If match_entry is + * specified, the module may narrow the iteration to policy names matching + * that regular expression; a module may alternatively ignore match_entry. + */ + krb5_error_code (*iter_policy)(krb5_context kcontext, char *match_entry, + osa_adb_iter_policy_func func, + void *data); + + /* + * Optional: Delete the password policy entry with the name policy. Return + * an error if the entry does not exist. + */ + krb5_error_code (*delete_policy)(krb5_context kcontext, char *policy); + + /* + * Optional with default: Retrieve a master keyblock from the stash file + * db_args, filling in *key and *kvno. mname is the name of the master + * principal for the realm. + * + * The default implementation reads the master keyblock from a keytab or + * old-format stash file. + */ + krb5_error_code (*fetch_master_key)(krb5_context kcontext, + krb5_principal mname, + krb5_keyblock *key, krb5_kvno *kvno, + char *db_args); + + /* + * Optional with default: Given a keyblock for some version of the + * database's master key, fetch the decrypted master key values from the + * database and store the list into *mkeys_list. The caller will free + * *mkeys_list using a libkdb5 function which uses the standard free() + * function, so the module must not use a custom allocator. + * + * The caller may not know the version number of the master key it has, in + * which case it will pass IGNORE_VNO. + * + * The default implementation ignores kvno and tries the key against the + * current master key data and all KRB5_TL_MKEY_AUX values, which contain + * copies of the master keys encrypted with old master keys. + */ + krb5_error_code (*fetch_master_key_list)(krb5_context kcontext, + krb5_principal mname, + const krb5_keyblock *key, + krb5_keylist_node **mkeys_list); + + /* + * Optional with default: Save a list of master keyblocks, obtained from + * fetch_master_key_list, into the stash file db_arg. The caller will set + * master_pwd to NULL, so the module should just ignore it. mname is the + * name of the master principal for the realm. + * + * The default implementation saves the list of master keys in a + * keytab-format file. + */ + krb5_error_code (*store_master_key_list)(krb5_context kcontext, + char *db_arg, + krb5_principal mname, + krb5_keylist_node *keylist, + char *master_pwd); + + /* + * Optional with default: Starting at position *start, scan the key data of + * a database entry for a key matching the enctype ktype, the salt type + * stype, and the version kvno. Store the resulting key into *kdatap and + * set *start to the position after the key found. If ktype is negative, + * match any enctype. If stype is negative, match any salt type. If kvno + * is zero or negative, find the most recent key version satisfying the + * other constraints. + */ + krb5_error_code (*dbe_search_enctype)(krb5_context kcontext, + krb5_db_entry *dbentp, + krb5_int32 *start, krb5_int32 ktype, + krb5_int32 stype, krb5_int32 kvno, + krb5_key_data **kdatap); + + + /* + * Optional with default: Change the key data for db_entry to include keys + * derived from the password passwd in each of the specified key-salt + * types, at version new_kvno. Discard the old key data if keepold is not + * set. + * + * The default implementation uses the keyblock master_key to encrypt each + * new key, via the function encrypt_key_data. + */ + krb5_error_code (*change_pwd)(krb5_context context, + krb5_keyblock *master_key, + krb5_key_salt_tuple *ks_tuple, + int ks_tuple_count, char *passwd, + int new_kvno, krb5_boolean keepold, + krb5_db_entry *db_entry); + + /* + * Optional: Promote a temporary database to be the live one. context must + * be initialized with an exclusively locked database created with the + * "temporary" db_arg. On success, the database object contained in + * context will be finalized. + * + * This method is used by kdb5_util load to replace the live database with + * minimal loss of read availability. + */ + krb5_error_code (*promote_db)(krb5_context context, char *conf_section, + char **db_args); + + /* + * Optional with default: Decrypt the key in key_data with master keyblock + * mkey, placing the result into dbkey. Copy the salt from key_data, if + * any, into keysalt. Either dbkey or keysalt may be left unmodified on + * successful return if key_data does not contain key or salt information. + * + * The default implementation expects the encrypted key (in krb5_c_encrypt + * format) to be stored in key_data_contents[0], with length given by + * key_data_length[0]. If key_data_ver is 2, it expects the salt to be + * stored, unencrypted, in key_data_contents[1], with length given by + * key_data_length[1]. + */ + krb5_error_code (*decrypt_key_data)(krb5_context kcontext, + const krb5_keyblock *mkey, + const krb5_key_data *key_data, + krb5_keyblock *dbkey, + krb5_keysalt *keysalt); + + /* + * Optional with default: Encrypt dbkey with master keyblock mkey, placing + * the result into key_data along with keysalt. + * + * The default implementation stores the encrypted key (in krb5_c_encrypt + * format) in key_data_contents[0] and the length in key_data_length[0]. + * If keysalt is specified, it sets key_data_ver to 2, and stores the salt + * in key_data_contents[1] and its length in key_data_length[1]. If + * keysalt is not specified, key_data_ver is set to 1. + */ + krb5_error_code (*encrypt_key_data)(krb5_context kcontext, + const krb5_keyblock *mkey, + const krb5_keyblock *dbkey, + const krb5_keysalt *keysalt, + int keyver, krb5_key_data *key_data); + + /* + * Optional: Perform a policy check on a cross-realm ticket's transited + * field. Return 0 if the check authoritatively succeeds, + * KRB5_PLUGIN_NO_HANDLE to use the core transited-checking mechanisms, or + * another error (other than KRB5_PLUGIN_OP_NOTSUPP) if the check fails. + */ + krb5_error_code (*check_transited_realms)(krb5_context kcontext, + const krb5_data *tr_contents, + const krb5_data *client_realm, + const krb5_data *server_realm); + + /* + * Optional: Perform a policy check on an AS request, in addition to the + * standard policy checks. Return 0 if the AS request is allowed. If the + * AS request is not allowed: + * - Place a short string literal into *status. + * - If desired, place data into e_data. Any data placed here will be + * freed by the caller using the standard free function. + * - Return an appropriate error (such as KRB5KDC_ERR_POLICY). + */ + krb5_error_code (*check_policy_as)(krb5_context kcontext, + krb5_kdc_req *request, + krb5_db_entry *client, + krb5_db_entry *server, + krb5_timestamp kdc_time, + const char **status, + krb5_pa_data ***e_data); + + /* + * Optional: Perform a policy check on a TGS request, in addition to the + * standard policy checks. Return 0 if the TGS request is allowed. If the + * TGS request is not allowed: + * - Place a short string literal into *status. + * - If desired, place data into e_data. Any data placed here will be + * freed by the caller using the standard free function. + * - Return an appropriate error (such as KRB5KDC_ERR_POLICY). + * The input parameter ticket contains the TGT used in the TGS request. + */ + krb5_error_code (*check_policy_tgs)(krb5_context kcontext, + krb5_kdc_req *request, + krb5_db_entry *server, + krb5_ticket *ticket, + const char **status, + krb5_pa_data ***e_data); + + /* + * Optional: This method informs the module of a successful or unsuccessful + * AS request. + */ + void (*audit_as_req)(krb5_context kcontext, krb5_kdc_req *request, + const krb5_address *local_addr, + const krb5_address *remote_addr, + krb5_db_entry *client, krb5_db_entry *server, + krb5_timestamp authtime, krb5_error_code error_code); + + /* Note: there is currently no method for auditing TGS requests. */ + + /* + * Optional: This method informs the module of a request to reload + * configuration or other state (that is, the KDC received a SIGHUP). + */ + void (*refresh_config)(krb5_context kcontext); + + /* + * Optional: Perform a policy check on server being allowed to obtain + * tickets from client to proxy. If proxy is NULL, check if server has any + * authorized delegation targets (client will also be NULL in this case). + * (Note that proxy is the target of the delegation, not the delegating + * service; the term "proxy" is from the viewpoint of the delegating + * service asking another service to perform some of its work in the + * authentication context of the client. This terminology comes from the + * Microsoft S4U protocol documentation.) Return 0 if policy allows + * delegation to the specified target (or to any target if proxy is NULL), + * or KRB5KDC_ERR_BADOPTION if not. If this method is not implemented, all + * S4U2Proxy delegation requests will be rejected. + */ + krb5_error_code (*check_allowed_to_delegate)(krb5_context context, + krb5_const_principal client, + const krb5_db_entry *server, + krb5_const_principal proxy); + + /* + * Optional: Free the e_data pointer of a database entry. If this method + * is not implemented, the e_data pointer in principal entries will be + * freed with free() as seen by libkdb5. + */ + void (*free_principal_e_data)(krb5_context kcontext, krb5_octet *e_data); + + /* + * Optional: get a client principal entry based on an X.509 certificate. + * + * If flags include KRB5_KDB_FLAG_REFERRAL_OK, the certificate was + * presented in an AS request. princ->realm indicates the request realm, + * but the data components should be ignored. The module can return an + * out-of-realm client referral as it would for get_principal(). + * + * Otherwise, princ is from a TGS request. If it contains data components + * (and not just a realm), the module should verify that it is the same as + * the lookup result for client_cert. The module should not return a + * referral. + */ + krb5_error_code (*get_s4u_x509_principal)(krb5_context kcontext, + const krb5_data *client_cert, + krb5_const_principal princ, + unsigned int flags, + krb5_db_entry **entry_out); + + /* + * Optional: Perform a policy check on server being allowed to obtain + * tickets from client to proxy. This method is similar to + * check_allowed_to_delegate, but it operates on the target server DB entry + * (called "proxy" here as in Microsoft's protocol documentation) rather + * than the intermediate server entry. server_pac is the verified PAC from + * the authdata of the intermediate server. Return 0 if policy allows the + * delegation, or KRB5KDC_ERR_BADOPTION if not. + * + * This method is called for S4U2Proxy requests and implements the + * resource-based constrained delegation variant, which can support + * cross-realm delegation. If this method is not implemented or if it + * returns a policy error, the KDC will fall back to + * check_allowed_to_delegate if the intermediate and target servers are in + * the same realm and the evidence ticket is forwardable. + */ + krb5_error_code (*allowed_to_delegate_from)(krb5_context context, + krb5_const_principal client, + krb5_const_principal server, + krb5_pac server_pac, + const krb5_db_entry *proxy); + + /* + * Optional: Add buffers to new_pac using krb5_pac_add_buffer() before it + * is signed. + * + * The caller will handle the following buffer types, so do not copy or add + * them: + * + * KRB5_PAC_SERVER_CHECKSUM + * KRB5_PAC_PRIVSVR_CHECKSUM + * KRB5_PAC_TICKET_CHECKSUM + * KRB5_PAC_CLIENT_INFO + * KRB5_PAC_DELEGATION_INFO + * + * For TGS requests, old_pac is the PAC of the header ticket, except when + * KRB5_KDB_FLAG_CONTRAINED_DELEGATION is present in flags, in which case + * it is the PAC of the second ticket. If + * KRB5_KDB_FLAG_PROTOCOL_TRANSITION is present in flags and client is not + * NULL, old_pac is the PAC of the requesting service, not the subject of + * the S4U2Self request, and its buffers should not be copied into new_pac. + * The signatures and PAC_CLIENT_INFO of old_pac have been verified by the + * caller. + * + * If replaced_reply_key is not null, the request is an AS request and the + * reply key was replaced by a preauth mechanism such as PKINIT, meaning + * the Kerberos password or long-term key was not used. The module may use + * this key to encrypt a PAC_CREDENTIALS_INFO buffer containing credentials + * (such as an NTLM hash) that the client would ordinarily derive from the + * Kerberos password or long-term key. + * + * server is the database entry of the server the ticket will be issued to, + * which may be a referral TGS. + * + * signing_krbtgt is the database entry of the krbtgt principal used to + * verify old_pac (or null if old_pac is null). If + * KRB5_KDB_FLAG_CROSS_REALM is present in flags, this entry will be an + * incoming cross-realm TGS, and the PAC fields should undergo appropriate + * filtering based on the trust level of the cross-realm relationship. + * + * auth_indicators points to NULL or a null-terminated list of krb5_data + * pointers, each containing an authentication indicator (RFC 8129). The + * method may modify this list, or free it and replace *auth_indicators + * with NULL, to change which auth indicators will be included in the + * ticket. + */ + krb5_error_code (*issue_pac)(krb5_context context, unsigned int flags, + krb5_db_entry *client, + krb5_keyblock *replaced_reply_key, + krb5_db_entry *server, + krb5_db_entry *signing_krbtgt, + krb5_timestamp authtime, krb5_pac old_pac, + krb5_pac new_pac, + krb5_data ***auth_indicators); + + /* End of minor version 0 for major version 9. */ +} kdb_vftabl; + +#endif /* !defined(_WIN32) */ + +#endif /* KRB5_KDB5__ */ diff --git a/krb5-1.21.3/src/include/kdb_kt.h b/krb5-1.21.3/src/include/kdb_kt.h new file mode 100644 index 00000000..6a71c3c1 --- /dev/null +++ b/krb5-1.21.3/src/include/kdb_kt.h @@ -0,0 +1,38 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/kdb_kt.h - KDC keytab declarations */ +/* + * Copyright 1997 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef KRB5_KDB5_KT_H +#define KRB5_KDB5_KT_H + +#include "kdb.h" + +extern struct _krb5_kt_ops krb5_kt_kdb_ops; + +krb5_error_code krb5_ktkdb_resolve (krb5_context, const char *, krb5_keytab *); + +krb5_error_code krb5_ktkdb_set_context(krb5_context); + +#endif /* KRB5_KDB5_DBM__ */ diff --git a/krb5-1.21.3/src/include/kdb_log.h b/krb5-1.21.3/src/include/kdb_log.h new file mode 100644 index 00000000..42395756 --- /dev/null +++ b/krb5-1.21.3/src/include/kdb_log.h @@ -0,0 +1,113 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _KDB_LOG_H +#define _KDB_LOG_H + +/* #pragma ident "@(#)kdb_log.h 1.3 04/02/23 SMI" */ + +#include +#include +#include +#include "kdb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * DB macros + */ +#define INDEX(ulog, i) (kdb_ent_header_t *)(void *) \ + ((char *)(ulog) + sizeof(kdb_hlog_t) + (i) * ulog->kdb_block) + +/* + * Current DB version # + */ +#define KDB_VERSION 1 + +/* + * DB log states + */ +#define KDB_STABLE 1 +#define KDB_UNSTABLE 2 +#define KDB_CORRUPT 3 + +/* + * DB log constants + */ +#define KDB_ULOG_MAGIC 0x6661212 +#define KDB_ULOG_HDR_MAGIC 0x6662323 + +/* + * Default ulog file attributes + */ +#define DEF_ULOGENTRIES 1000 +#define ULOG_IDLE_TIME 10 /* in seconds */ +/* + * Max size of update entry + update header + * We make this large since resizing can be costly. + */ +#define ULOG_BLOCK 2048 /* Default size of principal record */ + +#define MAXLOGLEN 0x10000000 /* 256 MB log file */ + +/* + * Prototype declarations + */ +krb5_error_code ulog_map(krb5_context context, const char *logname, + uint32_t entries); +krb5_error_code ulog_init_header(krb5_context context); +krb5_error_code ulog_add_update(krb5_context context, kdb_incr_update_t *upd); +krb5_error_code ulog_get_entries(krb5_context context, const kdb_last_t *last, + kdb_incr_result_t *ulog_handle); +krb5_error_code ulog_replay(krb5_context context, kdb_incr_result_t *incr_ret, + char **db_args); +krb5_error_code ulog_conv_2logentry(krb5_context context, krb5_db_entry *entry, + kdb_incr_update_t *update); +krb5_error_code ulog_conv_2dbentry(krb5_context context, krb5_db_entry **entry, + kdb_incr_update_t *update); +void ulog_free_entries(kdb_incr_update_t *updates, int no_of_updates); +krb5_error_code ulog_set_role(krb5_context ctx, iprop_role role); +update_status_t ulog_get_sno_status(krb5_context context, + const kdb_last_t *last); +krb5_error_code ulog_get_last(krb5_context context, kdb_last_t *last_out); +krb5_error_code ulog_set_last(krb5_context context, const kdb_last_t *last); +void ulog_fini(krb5_context context); + +typedef struct kdb_hlog { + uint32_t kdb_hmagic; /* Log header magic # */ + uint16_t db_version_num; /* Kerberos database version no. */ + uint32_t kdb_num; /* # of updates in log */ + kdbe_time_t kdb_first_time; /* Timestamp of first update */ + kdbe_time_t kdb_last_time; /* Timestamp of last update */ + kdb_sno_t kdb_first_sno; /* First serial # in the update log */ + kdb_sno_t kdb_last_sno; /* Last serial # in the update log */ + uint16_t kdb_state; /* State of update log */ + uint16_t kdb_block; /* Block size of each element */ +} kdb_hlog_t; + +typedef struct kdb_ent_header { + uint32_t kdb_umagic; /* Update entry magic # */ + kdb_sno_t kdb_entry_sno; /* Serial # of entry */ + kdbe_time_t kdb_time; /* Timestamp of update */ + bool_t kdb_commit; /* Is the entry committed or not */ + uint32_t kdb_entry_size; /* Size of update entry */ + uint8_t entry_data[4]; /* Address of kdb_incr_update_t */ +} kdb_ent_header_t; + +typedef struct _kdb_log_context { + iprop_role iproprole; + kdb_hlog_t *ulog; + uint32_t ulogentries; + int ulogfd; +} kdb_log_context; + +#ifdef __cplusplus +} +#endif + +#endif /* !_KDB_LOG_H */ diff --git a/krb5-1.21.3/src/include/krad.h b/krb5-1.21.3/src/include/krad.h new file mode 100644 index 00000000..e4edb524 --- /dev/null +++ b/krb5-1.21.3/src/include/krad.h @@ -0,0 +1,265 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +/* + * This API is not considered as stable as the main krb5 API. + * + * - We may make arbitrary incompatible changes between feature releases + * (e.g. from 1.12 to 1.13). + * - We will make some effort to avoid making incompatible changes for + * bugfix releases, but will make them if necessary. + */ + +#ifndef KRAD_H_ +#define KRAD_H_ + +#include +#include +#include +#include + +#define KRAD_PACKET_SIZE_MAX 4096 + +#define KRAD_SERVICE_TYPE_LOGIN 1 +#define KRAD_SERVICE_TYPE_FRAMED 2 +#define KRAD_SERVICE_TYPE_CALLBACK_LOGIN 3 +#define KRAD_SERVICE_TYPE_CALLBACK_FRAMED 4 +#define KRAD_SERVICE_TYPE_OUTBOUND 5 +#define KRAD_SERVICE_TYPE_ADMINISTRATIVE 6 +#define KRAD_SERVICE_TYPE_NAS_PROMPT 7 +#define KRAD_SERVICE_TYPE_AUTHENTICATE_ONLY 8 +#define KRAD_SERVICE_TYPE_CALLBACK_NAS_PROMPT 9 +#define KRAD_SERVICE_TYPE_CALL_CHECK 10 +#define KRAD_SERVICE_TYPE_CALLBACK_ADMINISTRATIVE 11 + +typedef struct krad_attrset_st krad_attrset; +typedef struct krad_packet_st krad_packet; +typedef struct krad_client_st krad_client; +typedef unsigned char krad_code; +typedef unsigned char krad_attr; + +/* Called when a response is received or the request times out. */ +typedef void +(*krad_cb)(krb5_error_code retval, const krad_packet *request, + const krad_packet *response, void *data); + +/* + * Called to iterate over a set of requests. Either the callback will be + * called until it returns NULL, or it will be called with cancel = TRUE to + * terminate in the middle of an iteration. + */ +typedef const krad_packet * +(*krad_packet_iter_cb)(void *data, krb5_boolean cancel); + +/* + * Code + */ + +/* Convert a code name to its number. Only works for codes defined + * by RFC 2875 or 2882. Returns 0 if the name was not found. */ +krad_code +krad_code_name2num(const char *name); + +/* Convert a code number to its name. Only works for attributes defined + * by RFC 2865 or 2882. Returns NULL if the name was not found. */ +const char * +krad_code_num2name(krad_code code); + +/* + * Attribute + */ + +/* Convert an attribute name to its number. Only works for attributes defined + * by RFC 2865. Returns 0 if the name was not found. */ +krad_attr +krad_attr_name2num(const char *name); + +/* Convert an attribute number to its name. Only works for attributes defined + * by RFC 2865. Returns NULL if the name was not found. */ +const char * +krad_attr_num2name(krad_attr type); + +/* + * Attribute set + */ + +/* Create a new attribute set. */ +krb5_error_code +krad_attrset_new(krb5_context ctx, krad_attrset **set); + +/* Create a deep copy of an attribute set. */ +krb5_error_code +krad_attrset_copy(const krad_attrset *set, krad_attrset **copy); + +/* Free an attribute set. */ +void +krad_attrset_free(krad_attrset *set); + +/* Add an attribute to a set. */ +krb5_error_code +krad_attrset_add(krad_attrset *set, krad_attr type, const krb5_data *data); + +/* Add a four-octet unsigned number attribute to the given set. */ +krb5_error_code +krad_attrset_add_number(krad_attrset *set, krad_attr type, krb5_ui_4 num); + +/* Delete the specified attribute. */ +void +krad_attrset_del(krad_attrset *set, krad_attr type, size_t indx); + +/* Get the specified attribute. */ +const krb5_data * +krad_attrset_get(const krad_attrset *set, krad_attr type, size_t indx); + +/* + * Packet + */ + +/* Determine the bytes needed from the socket to get the whole packet. Don't + * cache the return value as it can change! Returns -1 on EBADMSG. */ +ssize_t +krad_packet_bytes_needed(const krb5_data *buffer); + +/* Free a packet. */ +void +krad_packet_free(krad_packet *pkt); + +/* + * Create a new request packet. + * + * This function takes the attributes specified in set and converts them into a + * radius packet. The packet will have a randomized id. If cb is not NULL, it + * will be called passing data as the argument to iterate over a set of + * outstanding requests. In this case, the id will be both random and unique + * across the set of requests. + */ +krb5_error_code +krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code, + const krad_attrset *set, krad_packet_iter_cb cb, + void *data, krad_packet **request); + +/* + * Create a new response packet. + * + * This function is similar to krad_packet_new_requst() except that it crafts a + * packet in response to a request packet. This new packet will borrow values + * from the request such as the id and the authenticator. + */ +krb5_error_code +krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code, + const krad_attrset *set, const krad_packet *request, + krad_packet **response); + +/* + * Decode a request radius packet from krb5_data. + * + * The resulting decoded packet will be a request packet stored in *reqpkt. + * + * If cb is NULL, *duppkt will always be NULL. + * + * If cb is not NULL, it will be called (with the data argument) to iterate + * over a set of requests currently being processed. In this case, if the + * packet is a duplicate of an already received request, the original request + * will be set in *duppkt. + */ +krb5_error_code +krad_packet_decode_request(krb5_context ctx, const char *secret, + const krb5_data *buffer, krad_packet_iter_cb cb, + void *data, const krad_packet **duppkt, + krad_packet **reqpkt); + +/* + * Decode a response radius packet from krb5_data. + * + * The resulting decoded packet will be a response packet stored in *rsppkt. + * + * If cb is NULL, *reqpkt will always be NULL. + * + * If cb is not NULL, it will be called (with the data argument) to iterate + * over a set of requests awaiting responses. In this case, if the response + * packet matches one of these requests, the original request will be set in + * *reqpkt. + */ +krb5_error_code +krad_packet_decode_response(krb5_context ctx, const char *secret, + const krb5_data *buffer, krad_packet_iter_cb cb, + void *data, const krad_packet **reqpkt, + krad_packet **rsppkt); + +/* Encode packet. */ +const krb5_data * +krad_packet_encode(const krad_packet *pkt); + +/* Get the code for the given packet. */ +krad_code +krad_packet_get_code(const krad_packet *pkt); + +/* Get the specified attribute. */ +const krb5_data * +krad_packet_get_attr(const krad_packet *pkt, krad_attr type, size_t indx); + +/* + * Client + */ + +/* Create a new client. */ +krb5_error_code +krad_client_new(krb5_context kctx, verto_ctx *vctx, krad_client **client); + +/* Free the client. */ +void +krad_client_free(krad_client *client); + +/* + * Send a request to a radius server. + * + * The remote host may be specified by one of the following formats: + * - /path/to/unix.socket + * - IPv4 + * - IPv4:port + * - IPv4:service + * - [IPv6] + * - [IPv6]:port + * - [IPv6]:service + * - hostname + * - hostname:port + * - hostname:service + * + * The timeout parameter (milliseconds) is the total timeout across all remote + * hosts (when DNS returns multiple entries) and all retries. For stream + * sockets, the retries parameter is ignored and no retries are performed. + * + * The cb function will be called with the data argument when either a response + * is received or the request times out on all possible remote hosts. + */ +krb5_error_code +krad_client_send(krad_client *rc, krad_code code, const krad_attrset *attrs, + const char *remote, const char *secret, int timeout, + size_t retries, krad_cb cb, void *data); + +#endif /* KRAD_H_ */ diff --git a/krb5-1.21.3/src/include/krb5.h b/krb5-1.21.3/src/include/krb5.h new file mode 100644 index 00000000..62ef9bb9 --- /dev/null +++ b/krb5-1.21.3/src/include/krb5.h @@ -0,0 +1,8 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* The MIT Kerberos header file krb5.h used to live here. + + As of the 1.5 release, we're installing multiple Kerberos headers, + so they're all moving to a krb5/ subdirectory. This file is + present just to keep old software still compiling. Please update + your code to use the new path for the header. */ +#include diff --git a/krb5-1.21.3/src/include/krb5/audit_plugin.h b/krb5-1.21.3/src/include/krb5/audit_plugin.h new file mode 100644 index 00000000..3315d77d --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/audit_plugin.h @@ -0,0 +1,270 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/krb5/audit_plugin.h - Audit plugin interface */ +/* + * 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. + */ +/* + * NOTE: This is a private interface and may change incompatibly + * between versions. + */ +/* + * Declarations for KDC audit plugin module implementers. Audit modules allow + * the KDC to produce log output or audit records in any desired form. + * + * The audit interface has a single supported major version, which is 1. Major + * version 1 has a current minor version of 1. Audit modules should define a + * function named audit__initvt, matching the signature: + * + * krb5_error_code + * audit_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for the interface and maj_ver: + * maj_ver == 1: Cast to krb5_audit_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_AU_PLUGIN_H_INCLUDED +#define KRB5_AU_PLUGIN_H_INCLUDED +#include + +/** KDC processing steps */ +#define AUTHN_REQ_CL 1 /**< Authenticate request and client */ +#define SRVC_PRINC 2 /**< Determine service principal */ +#define VALIDATE_POL 3 /**< Validate local and protocol policies */ +#define ISSUE_TKT 4 /**< Issue ticket */ +#define ENCR_REP 5 /**< Encrypt reply */ + +/** Types of violations */ +#define PROT_CONSTRAINT 1 /**< Protocol constraint */ +#define LOCAL_POLICY 2 /**< Local policy violation */ + +#define REQID_LEN 32 /* Size of the alphanumeric request ID */ + +/** KDC audit state structure and declarations */ +typedef struct _krb5_audit_state { + krb5_kdc_req *request; + krb5_kdc_rep *reply; + krb5_address *cl_addr; /**< client address */ + krb5_ui_4 cl_port; /**< client port */ + int stage; /**< step in KDC processing */ + const char *status; /**< KDC status message */ + char *tkt_in_id; /**< primary (TGT) ticket ID */ + char *tkt_out_id; /**< derived (service or referral TGT) ticket ID */ + /** for s4u2proxy - evidence ticket ID; for u2u - second ticket ID */ + char *evid_tkt_id; + char req_id[REQID_LEN]; /**< request ID */ + krb5_data *cl_realm; /**< referrals: remote client's realm */ + krb5_principal s4u2self_user; /**< impersonated user */ + int violation; /**< local or protocol policy problem */ +} krb5_audit_state; + +/** An abstract type for audit module data. */ +typedef struct krb5_audit_moddata_st *krb5_audit_moddata; + +/* + * Mandatory: + * - krb5_audit_open_fn, + * Open connection to the audit system and initialize audit module data. If + * the underlying (OS or third party) audit facility fails to open, no + * auditable KDC events should be recorded. + */ +typedef krb5_error_code +(*krb5_audit_open_fn)(krb5_audit_moddata *auctx); + +/* + * Mandatory: + * - krb5_audit_close_fn. + * Close connection to the underlying audit system. + */ +typedef krb5_error_code +(*krb5_audit_close_fn)(krb5_audit_moddata auctx); + +/** + * Log KDC-start event. + * + * @param [in] auctx Audit context + * @param [in] ev_success Success/failure of the event being audited + * + * @note Optional. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +typedef krb5_error_code +(*krb5_audit_kdc_start_fn)(krb5_audit_moddata auctx, krb5_boolean ev_success); + +/** + * Log KDC-stop event. + * + * @param [in] auctx Audit context + * @param [in] ev_success Success/failure of the event being audited + * + * @note Optional. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +typedef krb5_error_code +(*krb5_audit_kdc_stop_fn)(krb5_audit_moddata auctx, krb5_boolean ev_success); + +/** + * Log AS exchange event. + * + * @param [in] auctx Audit context + * @param [in] ev_success Success/failure of the event being audited + * @param [in] state AS-request related auditable information + * + * The @a state provides the following data: + * - Full information about KDC request, assigned request ID, client address + * and port, and stage of the AS exchange + * - If available, the information about the encryption types of the short- and + * long-term keys, non-local client's referral realm, KDC status, the TGT + * and its ticket ID + * + * @note Optional. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +typedef krb5_error_code +(*krb5_audit_as_req_fn)(krb5_audit_moddata auctx, + krb5_boolean ev_success, krb5_audit_state *state); + +/** + * Log TGS exchange event. + * + * @param [in] auctx Audit context + * @param [in] ev_success Success/failure of the event being audited + * @param [in] state TGS-request related auditable information + * + * The @a state provides the following data: + * - Full information about KDC request, assigned request ID, primary ticket + * ID, client address and port, and stage of the TGS exchange + * - If available, the information about the encryption types of the short- and + * long-term keys, KDC status, KDC reply, and the output ticket ID + * + * @note Optional. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +typedef krb5_error_code +(*krb5_audit_tgs_req_fn)(krb5_audit_moddata auctx, + krb5_boolean ev_success, krb5_audit_state *state); + +/** + * Log S4U2SELF event. + * + * @param [in] auctx Audit context + * @param [in] ev_success Report on success or failure + * @param [in] state s4u2self related auditable information + * + * The @a state provides the following data: + * - Full information about KDC request, assigned request ID, client address + * and port, and stage of the TGS exchange + * - Requesting server's TGT ID, impersonated user principal name, and service + * "to self" ticket or referral TGT ID + * - If available, KDC status, local policy violation or S4U protocol + * constraints + * + * @note Optional. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +typedef krb5_error_code +(*krb5_audit_s4u2self_fn)(krb5_audit_moddata auctx, + krb5_boolean ev_success, krb5_audit_state *state); + +/** + * Log S4U2PROXY event. + * + * @param [in] auctx Audit context + * @param [in] ev_success Report on success or failure + * @param [in] state s4u2proxy related auditable information + * + * The @a state provides the following data: + * - Full information about request, assigned request ID, client address and + * port, and stage of the TGS exchange + * - Requesting server's TGT ID, delegated user principal name, and evidence + * ticket ID + * - If available, KDC status, local policy violation or S4U protocol + * constraints + * + * @note Optional. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +typedef krb5_error_code +(*krb5_audit_s4u2proxy_fn)(krb5_audit_moddata auctx, + krb5_boolean ev_success, krb5_audit_state *state); + +/** + * Log U2U event. + * + * @param [in] auctx Audit context + * @param [in] ev_success Report on success or failure + * @param [in] state user-to-user related auditable information + * + * The @a state provides the following data: + * - Full information about request, assigned request ID, client address and + * port, and stage of the TGS exchange, + * - Requestor's TGT ID, service ticket ID, and client's principal name in the + * second ticket + * - If available, KDC status + * + * @note Optional. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +typedef krb5_error_code +(*krb5_audit_u2u_fn)(krb5_audit_moddata auctx, + krb5_boolean ev_success, krb5_audit_state *state); + +/* vtable declaration */ +typedef struct krb5_audit_vtable_st { + /* Mandatory: name of module. */ + const char *name; + krb5_audit_open_fn open; + krb5_audit_close_fn close; + krb5_audit_kdc_start_fn kdc_start; + krb5_audit_kdc_stop_fn kdc_stop; + krb5_audit_as_req_fn as_req; + krb5_audit_tgs_req_fn tgs_req; + krb5_audit_s4u2self_fn tgs_s4u2self; + krb5_audit_s4u2proxy_fn tgs_s4u2proxy; + krb5_audit_u2u_fn tgs_u2u; +} *krb5_audit_vtable; + +#endif /* KRB5_AU_PLUGIN_H_INCLUDED */ diff --git a/krb5-1.21.3/src/include/krb5/authdata_plugin.h b/krb5-1.21.3/src/include/krb5/authdata_plugin.h new file mode 100644 index 00000000..d59a8eb7 --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/authdata_plugin.h @@ -0,0 +1,216 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2007 Apple Inc. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Authorization data plugin definitions for Kerberos 5. + * This is considered an INTERNAL interface at this time. + * + * Some work is needed before exporting it: + * + * + Documentation. + * + Sample code. + * + Test cases (preferably automated testing under "make check"). + * + * Other changes that would be nice to have, but not necessarily + * before making this interface public: + * + * + Library support for AD-IF-RELEVANT and similar wrappers. (We can + * make the plugin construct them if it wants them.) + * + KDC could combine/optimize wrapped AD elements provided by + * multiple plugins, e.g., two IF-RELEVANT sequences could be + * merged. (The preauth plugin API also has this bug, we're going + * to need a general fix.) + */ + +#ifndef KRB5_AUTHDATA_PLUGIN_H_INCLUDED +#define KRB5_AUTHDATA_PLUGIN_H_INCLUDED +#include + +typedef krb5_error_code +(*authdata_client_plugin_init_proc)(krb5_context context, + void **plugin_context); + +#define AD_USAGE_AS_REQ 0x01 +#define AD_USAGE_TGS_REQ 0x02 +#define AD_USAGE_AP_REQ 0x04 +#define AD_USAGE_KDC_ISSUED 0x08 +#define AD_INFORMATIONAL 0x10 +#define AD_CAMMAC_PROTECTED 0x20 +#define AD_USAGE_MASK 0x2F + +struct _krb5_authdata_context; + +typedef void +(*authdata_client_plugin_flags_proc)(krb5_context kcontext, + void *plugin_context, + krb5_authdatatype ad_type, + krb5_flags *flags); + +typedef void +(*authdata_client_plugin_fini_proc)(krb5_context kcontext, + void *plugin_context); + +typedef krb5_error_code +(*authdata_client_request_init_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void **request_context); + +typedef void +(*authdata_client_request_fini_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context); + +typedef krb5_error_code +(*authdata_client_import_authdata_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context, + krb5_authdata **authdata, + krb5_boolean kdc_issued_flag, + krb5_const_principal issuer); + +typedef krb5_error_code +(*authdata_client_export_authdata_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context, + krb5_flags usage, + krb5_authdata ***authdata); + +typedef krb5_error_code +(*authdata_client_get_attribute_types_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context, + krb5_data **attrs); + +typedef krb5_error_code +(*authdata_client_get_attribute_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context, + const krb5_data *attribute, + krb5_boolean *authenticated, + krb5_boolean *complete, + krb5_data *value, + krb5_data *display_value, + int *more); + +typedef krb5_error_code +(*authdata_client_set_attribute_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context, + krb5_boolean complete, + const krb5_data *attribute, + const krb5_data *value); + +typedef krb5_error_code +(*authdata_client_delete_attribute_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context, + const krb5_data *attribute); + +typedef krb5_error_code +(*authdata_client_export_internal_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context, + krb5_boolean restrict_authenticated, + void **ptr); + +typedef void +(*authdata_client_free_internal_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context, + void *ptr); + +typedef krb5_error_code +(*authdata_client_verify_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context, + const krb5_auth_context *auth_context, + const krb5_keyblock *key, + const krb5_ap_req *req); + +typedef krb5_error_code +(*authdata_client_size_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context, + size_t *sizep); + +typedef krb5_error_code +(*authdata_client_externalize_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context, + krb5_octet **buffer, + size_t *lenremain); + +typedef krb5_error_code +(*authdata_client_internalize_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context, + krb5_octet **buffer, + size_t *lenremain); + +typedef krb5_error_code +(*authdata_client_copy_proc)(krb5_context kcontext, + struct _krb5_authdata_context *context, + void *plugin_context, + void *request_context, + void *dst_plugin_context, + void *dst_request_context); + +typedef struct krb5plugin_authdata_client_ftable_v0 { + const char *name; + krb5_authdatatype *ad_type_list; + authdata_client_plugin_init_proc init; + authdata_client_plugin_fini_proc fini; + authdata_client_plugin_flags_proc flags; + authdata_client_request_init_proc request_init; + authdata_client_request_fini_proc request_fini; + authdata_client_get_attribute_types_proc get_attribute_types; + authdata_client_get_attribute_proc get_attribute; + authdata_client_set_attribute_proc set_attribute; + authdata_client_delete_attribute_proc delete_attribute; + authdata_client_export_authdata_proc export_authdata; + authdata_client_import_authdata_proc import_authdata; + authdata_client_export_internal_proc export_internal; + authdata_client_free_internal_proc free_internal; + authdata_client_verify_proc verify; + authdata_client_size_proc size; + authdata_client_externalize_proc externalize; + authdata_client_internalize_proc internalize; + authdata_client_copy_proc copy; /* optional */ +} krb5plugin_authdata_client_ftable_v0; + +#endif /* KRB5_AUTHDATA_PLUGIN_H_INCLUDED */ diff --git a/krb5-1.21.3/src/include/krb5/ccselect_plugin.h b/krb5-1.21.3/src/include/krb5/ccselect_plugin.h new file mode 100644 index 00000000..ff963131 --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/ccselect_plugin.h @@ -0,0 +1,105 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Declarations for credential cache selection module implementors. + * + * The ccselect pluggable interface currently has only one supported major + * version, which is 1. Major version 1 has a current minor version number of + * 1. + * + * Credential cache selection modules should define a function named + * ccselect__initvt, matching the signature: + * + * krb5_error_code + * ccselect_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for maj_ver: + * maj_ver == 1: Cast to krb5_ccselect_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_CCSELECT_PLUGIN_H +#define KRB5_CCSELECT_PLUGIN_H + +#include +#include + +/* An abstract type for credential cache selection module data. */ +typedef struct krb5_ccselect_moddata_st *krb5_ccselect_moddata; + +#define KRB5_CCSELECT_PRIORITY_AUTHORITATIVE 2 +#define KRB5_CCSELECT_PRIORITY_HEURISTIC 1 + +/*** Method type declarations ***/ + +/* + * Mandatory: Initialize module data and set *priority_out to one of the + * KRB5_CCSELECT_PRIORITY constants above. Authoritative modules will be + * consulted before heuristic ones. + */ +typedef krb5_error_code +(*krb5_ccselect_init_fn)(krb5_context context, krb5_ccselect_moddata *data_out, + int *priority_out); + +/* + * Mandatory: Select a cache based on a server principal. Return 0 on success, + * with *cache_out set to the selected cache and *princ_out set to its default + * principal. Return KRB5_PLUGIN_NO_HANDLE to defer to other modules. Return + * KRB5_CC_NOTFOUND with *princ_out set if the client principal can be + * authoritatively determined but no cache exists for it. Return other errors + * as appropriate. + */ +typedef krb5_error_code +(*krb5_ccselect_choose_fn)(krb5_context context, krb5_ccselect_moddata data, + krb5_principal server, krb5_ccache *cache_out, + krb5_principal *princ_out); + +/* Optional: Release resources used by module data. */ +typedef void +(*krb5_ccselect_fini_fn)(krb5_context context, krb5_ccselect_moddata data); + +/*** vtable declarations **/ + +/* Credential cache selection plugin vtable for major version 1. */ +typedef struct krb5_ccselect_vtable_st { + const char *name; /* Mandatory: name of module. */ + krb5_ccselect_init_fn init; + krb5_ccselect_choose_fn choose; + krb5_ccselect_fini_fn fini; + /* Minor version 1 ends here. */ +} *krb5_ccselect_vtable; + +#endif /* KRB5_CCSELECT_PLUGIN_H */ diff --git a/krb5-1.21.3/src/include/krb5/certauth_plugin.h b/krb5-1.21.3/src/include/krb5/certauth_plugin.h new file mode 100644 index 00000000..bc8c88ac --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/certauth_plugin.h @@ -0,0 +1,148 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/krb5/certauth_plugin.h - certauth plugin header. */ +/* + * Copyright (C) 2017 by Red Hat, Inc. + * 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. + */ + +/* + * Declarations for certauth plugin module implementors. + * + * The certauth pluggable interface currently has only one supported major + * version, which is 1. Major version 1 has a current minor version number of + * 2. + * + * certauth plugin modules should define a function named + * certauth__initvt, matching the signature: + * + * krb5_error_code + * certauth_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for maj_ver: + * maj_ver == 1: Cast to krb5_certauth_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_CERTAUTH_PLUGIN_H +#define KRB5_CERTAUTH_PLUGIN_H + +#include +#include + +/* Abstract module data type. */ +typedef struct krb5_certauth_moddata_st *krb5_certauth_moddata; + +/* A module can optionally include to inspect the client principal + * entry when authorizing a request. */ +struct _krb5_db_entry_new; + +/* + * Optional: Initialize module data. + */ +typedef krb5_error_code +(*krb5_certauth_init_fn)(krb5_context context, + krb5_certauth_moddata *moddata_out); + +/* + * Optional: Initialize module data. Supersedes init if present. + */ +typedef krb5_error_code +(*krb5_certauth_init_ex_fn)(krb5_context context, const char *const *realmlist, + krb5_certauth_moddata *moddata_out); + +/* + * Optional: Clean up the module data. + */ +typedef void +(*krb5_certauth_fini_fn)(krb5_context context, krb5_certauth_moddata moddata); + +/* + * Mandatory: decode cert as an X.509 certificate and determine whether it is + * authorized to authenticate as the requested client principal princ using + * PKINIT. Return 0 or KRB5_CERTAUTH_HWAUTH if the certificate is authorized. + * Otherwise return one of the following error codes: + * + * - KRB5KDC_ERR_CLIENT_NAME_MISMATCH - incorrect SAN value + * - KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE - incorrect EKU + * - KRB5KDC_ERR_CERTIFICATE_MISMATCH - other extension error + * - KRB5_PLUGIN_NO_HANDLE or KRB5_CERTAUTH_HWAUTH_PASS - the module has no + * opinion about whether cert is authorized + * + * Returning KRB5_CERTAUTH_HWAUTH will authorize the PKINIT authentication and + * cause the hw-authent flag to be set in the issued ticket (new in release + * 1.19). Returning KRB5_CERTAUTH_HWAUTH_PASS does not authorize the PKINIT + * authentication, but causes the hw-authent flag to be set if another module + * authorizes it (new in release 1.20) + * + * - opts is used by built-in modules to receive internal data, and must be + * ignored by other modules. + * - db_entry receives the client principal database entry, and can be ignored + * by modules that do not link with libkdb5. + * - *authinds_out optionally returns a null-terminated list of authentication + * indicator strings upon KRB5_PLUGIN_NO_HANDLE or accepted authorization. + */ +typedef krb5_error_code +(*krb5_certauth_authorize_fn)(krb5_context context, + krb5_certauth_moddata moddata, + const uint8_t *cert, size_t cert_len, + krb5_const_principal princ, const void *opts, + const struct _krb5_db_entry_new *db_entry, + char ***authinds_out); + +/* + * Free indicators allocated by a module. Mandatory if authorize returns + * authentication indicators. + */ +typedef void +(*krb5_certauth_free_indicator_fn)(krb5_context context, + krb5_certauth_moddata moddata, + char **authinds); + +typedef struct krb5_certauth_vtable_st { + const char *name; + krb5_certauth_init_fn init; + krb5_certauth_fini_fn fini; + krb5_certauth_authorize_fn authorize; + krb5_certauth_free_indicator_fn free_ind; + /* Minor version 1 ends here. */ + + krb5_certauth_init_ex_fn init_ex; + /* Minor version 2 ends here. */ +} *krb5_certauth_vtable; + +#endif /* KRB5_CERTAUTH_PLUGIN_H */ diff --git a/krb5-1.21.3/src/include/krb5/clpreauth_plugin.h b/krb5-1.21.3/src/include/krb5/clpreauth_plugin.h new file mode 100644 index 00000000..8832a687 --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/clpreauth_plugin.h @@ -0,0 +1,346 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (c) 2006 Red Hat, Inc. + * Portions copyright (c) 2006, 2011 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. + * * Neither the name of Red Hat, Inc., 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 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. + */ + +/* + * Declarations for clpreauth plugin module implementors. + * + * The clpreauth interface has a single supported major version, which is + * 1. Major version 1 has a current minor version of 2. clpreauth modules + * should define a function named clpreauth__initvt, matching + * the signature: + * + * krb5_error_code + * clpreauth_modname_initvt(krb5_context context, int maj_ver, + * int min_ver, krb5_plugin_vtable vtable); + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for the interface and maj_ver: + * maj_ver == 1: Cast to krb5_clpreauth_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_CLPREAUTH_PLUGIN_H +#define KRB5_CLPREAUTH_PLUGIN_H + +#include +#include + +/* clpreauth mechanism property flags */ + +/* Provides a real answer which we can send back to the KDC. The client + * assumes that one real answer will be enough. */ +#define PA_REAL 0x00000001 + +/* Doesn't provide a real answer, but must be given a chance to run before any + * REAL mechanism callbacks. */ +#define PA_INFO 0x00000002 + +/* Abstract type for a client request information handle. */ +typedef struct krb5_clpreauth_rock_st *krb5_clpreauth_rock; + +/* Abstract types for module data and per-request module data. */ +typedef struct krb5_clpreauth_moddata_st *krb5_clpreauth_moddata; +typedef struct krb5_clpreauth_modreq_st *krb5_clpreauth_modreq; + +/* Before using a callback after version 1, modules must check the vers + * field of the callback structure. */ +typedef struct krb5_clpreauth_callbacks_st { + int vers; + + /* + * If an AS-REP has been received, return the enctype of the AS-REP + * encrypted part. Otherwise return the enctype chosen from etype-info, or + * the first requested enctype if no etype-info was received. + */ + krb5_enctype (*get_etype)(krb5_context context, krb5_clpreauth_rock rock); + + /* Get a pointer to the FAST armor key, or NULL if the client is not using + * FAST. The returned pointer is an alias and should not be freed. */ + krb5_keyblock *(*fast_armor)(krb5_context context, + krb5_clpreauth_rock rock); + + /* + * Get a pointer to the client-supplied reply key, possibly invoking the + * prompter to ask for a password if this has not already been done. The + * returned pointer is an alias and should not be freed. + */ + krb5_error_code (*get_as_key)(krb5_context context, + krb5_clpreauth_rock rock, + krb5_keyblock **keyblock); + + /* Replace the reply key to be used to decrypt the AS response. */ + krb5_error_code (*set_as_key)(krb5_context context, + krb5_clpreauth_rock rock, + const krb5_keyblock *keyblock); + + /* End of version 1 clpreauth callbacks. */ + + /* + * Get the current time for use in a preauth response. If + * allow_unauth_time is true and the library has been configured to allow + * it, the current time will be offset using unauthenticated timestamp + * information received from the KDC in the preauth-required error, if one + * has been received. Otherwise, the timestamp in a preauth-required error + * will only be used if it is protected by a FAST channel. Only set + * allow_unauth_time if using an unauthenticated time offset would not + * create a security issue. + */ + krb5_error_code (*get_preauth_time)(krb5_context context, + krb5_clpreauth_rock rock, + krb5_boolean allow_unauth_time, + krb5_timestamp *time_out, + krb5_int32 *usec_out); + + /* Set a question to be answered by the responder and optionally provide + * a challenge. */ + krb5_error_code (*ask_responder_question)(krb5_context context, + krb5_clpreauth_rock rock, + const char *question, + const char *challenge); + + /* Get an answer from the responder, or NULL if the question was + * unanswered. */ + const char *(*get_responder_answer)(krb5_context context, + krb5_clpreauth_rock rock, + const char *question); + + /* Indicate interest in the AS key through the responder interface. */ + void (*need_as_key)(krb5_context context, krb5_clpreauth_rock rock); + + /* + * Get a configuration/state item from an input ccache, which may allow it + * to retrace the steps it took last time. The returned data string is an + * alias and should not be freed. + */ + const char *(*get_cc_config)(krb5_context context, + krb5_clpreauth_rock rock, const char *key); + + /* + * Set a configuration/state item which will be recorded to an output + * ccache, if the calling application supplied one. Both key and data + * should be valid UTF-8 text. + */ + krb5_error_code (*set_cc_config)(krb5_context context, + krb5_clpreauth_rock rock, + const char *key, const char *data); + + /* End of version 2 clpreauth callbacks (added in 1.11). */ + + /* + * Prevent further fallbacks to other preauth mechanisms if the KDC replies + * with an error. (The module itself can still respond to errors with its + * tryagain method, or continue after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED + * errors with its process method.) A module should invoke this callback + * from the process method when it generates an authenticated request using + * credentials; often this will be the first or only client message + * generated by the mechanism. + */ + void (*disable_fallback)(krb5_context context, krb5_clpreauth_rock rock); + + /* End of version 3 clpreauth callbacks (added in 1.17). */ +} *krb5_clpreauth_callbacks; + +/* + * Optional: per-plugin initialization/cleanup. The init function is called by + * libkrb5 when the plugin is loaded, and the fini function is called before + * the plugin is unloaded. These may be called multiple times in case the + * plugin is used in multiple contexts. The returned context lives the + * lifetime of the krb5_context. + */ +typedef krb5_error_code +(*krb5_clpreauth_init_fn)(krb5_context context, + krb5_clpreauth_moddata *moddata_out); +typedef void +(*krb5_clpreauth_fini_fn)(krb5_context context, + krb5_clpreauth_moddata moddata); + +/* + * Optional (mandatory before MIT krb5 1.12): pa_type will be a member of the + * vtable's pa_type_list. Return PA_REAL if pa_type is a real + * preauthentication type or PA_INFO if it is an informational type. If this + * function is not defined in 1.12 or later, all pa_type values advertised by + * the module will be assumed to be real. + */ +typedef int +(*krb5_clpreauth_get_flags_fn)(krb5_context context, krb5_preauthtype pa_type); + +/* + * Optional: per-request initialization/cleanup. The request_init function is + * called when beginning to process a get_init_creds request and the + * request_fini function is called when processing of the request is complete. + * This is optional. It may be called multiple times in the lifetime of a + * krb5_context. + */ +typedef void +(*krb5_clpreauth_request_init_fn)(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq *modreq_out); +typedef void +(*krb5_clpreauth_request_fini_fn)(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq); + +/* + * Optional: process server-supplied data in pa_data and set responder + * questions. + * + * encoded_previous_request may be NULL if there has been no previous request + * in the AS exchange. + */ +typedef krb5_error_code +(*krb5_clpreauth_prep_questions_fn)(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, + krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, + krb5_kdc_req *request, + krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, + krb5_pa_data *pa_data); + +/* + * Mandatory: process server-supplied data in pa_data and return created data + * in pa_data_out. Also called after the AS-REP is received if the AS-REP + * includes preauthentication data of the associated type. + * + * as_key contains the client-supplied key if known, or an empty keyblock if + * not. If it is empty, the module may use gak_fct to fill it in. + * + * encoded_previous_request may be NULL if there has been no previous request + * in the AS exchange. + */ +typedef krb5_error_code +(*krb5_clpreauth_process_fn)(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, + krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, + krb5_kdc_req *request, + krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, + krb5_pa_data *pa_data, + krb5_prompter_fct prompter, void *prompter_data, + krb5_pa_data ***pa_data_out); + +/* + * Optional: Attempt to use error and error_padata to try to recover from the + * given error. To work with both FAST and non-FAST errors, an implementation + * should generally consult error_padata rather than decoding error->e_data. + * For non-FAST errors, it contains the e_data decoded as either pa-data or + * typed-data. + * + * If this function is provided, and it returns 0 and stores data in + * pa_data_out, then the client library will retransmit the request. + */ +typedef krb5_error_code +(*krb5_clpreauth_tryagain_fn)(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, + krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, + krb5_kdc_req *request, + krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, + krb5_preauthtype pa_type, + krb5_error *error, + krb5_pa_data **error_padata, + krb5_prompter_fct prompter, void *prompter_data, + krb5_pa_data ***pa_data_out); + +/* + * Optional: receive krb5_get_init_creds_opt information. The attr and value + * information supplied should be copied into moddata by the module if it + * wishes to reference it after returning from this call. + */ +typedef krb5_error_code +(*krb5_clpreauth_supply_gic_opts_fn)(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_get_init_creds_opt *opt, + const char *attr, const char *value); + +typedef struct krb5_clpreauth_vtable_st { + /* Mandatory: name of module. */ + const char *name; + + /* Mandatory: pointer to zero-terminated list of pa_types which this module + * can provide services for. */ + krb5_preauthtype *pa_type_list; + + /* Optional: pointer to zero-terminated list of enc_types which this module + * claims to add support for. */ + krb5_enctype *enctype_list; + + krb5_clpreauth_init_fn init; + krb5_clpreauth_fini_fn fini; + krb5_clpreauth_get_flags_fn flags; + krb5_clpreauth_request_init_fn request_init; + krb5_clpreauth_request_fini_fn request_fini; + krb5_clpreauth_process_fn process; + krb5_clpreauth_tryagain_fn tryagain; + krb5_clpreauth_supply_gic_opts_fn gic_opts; + /* Minor version 1 ends here. */ + + krb5_clpreauth_prep_questions_fn prep_questions; + /* Minor version 2 ends here. */ +} *krb5_clpreauth_vtable; + +/* + * This function allows a clpreauth plugin to obtain preauth options. The + * preauth_data returned from this function should be freed by calling + * krb5_get_init_creds_opt_free_pa(). + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_get_pa(krb5_context context, + krb5_get_init_creds_opt *opt, + int *num_preauth_data, + krb5_gic_opt_pa_data **preauth_data); + +/* + * This function frees the preauth_data that was returned by + * krb5_get_init_creds_opt_get_pa(). + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_free_pa(krb5_context context, + int num_preauth_data, + krb5_gic_opt_pa_data *preauth_data); + +#endif /* KRB5_CLPREAUTH_PLUGIN_H */ diff --git a/krb5-1.21.3/src/include/krb5/hostrealm_plugin.h b/krb5-1.21.3/src/include/krb5/hostrealm_plugin.h new file mode 100644 index 00000000..5012c8cb --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/hostrealm_plugin.h @@ -0,0 +1,135 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * 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. + */ + +/* + * Declarations for hostrealm plugin module implementors. + * + * The hostrealm pluggable interface currently has only one supported major + * version, which is 1. Major version 1 has a current minor version number of + * 1. + * + * Hostrealm plugin modules should define a function named + * hostrealm__initvt, matching the signature: + * + * krb5_error_code + * hostrealm_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for maj_ver: + * maj_ver == 1: Cast to krb5_hostrealm_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_HOSTREALM_PLUGIN_H +#define KRB5_HOSTREALM_PLUGIN_H + +#include +#include + +/* An abstract type for hostrealm module data. */ +typedef struct krb5_hostrealm_moddata_st *krb5_hostrealm_moddata; + +/*** Method type declarations ***/ + +/* Optional: Initialize module data. */ +typedef krb5_error_code +(*krb5_hostrealm_init_fn)(krb5_context context, + krb5_hostrealm_moddata *data); + +/* + * Optional: Determine the possible realms of a hostname, using only secure, + * authoritative mechanisms (ones which should be used prior to trying + * referrals when getting a service ticket). Return success with a + * null-terminated list of realms in *realms_out, KRB5_PLUGIN_NO_HANDLE to + * defer to later modules, or another error to terminate processing. + */ +typedef krb5_error_code +(*krb5_hostrealm_host_realm_fn)(krb5_context context, + krb5_hostrealm_moddata data, + const char *host, char ***realms_out); + +/* + * Optional: Determine the possible realms of a hostname, using heuristic or + * less secure mechanisms (ones which should be used after trying referrals + * when getting a service ticket). Return success with a null-terminated list + * of realms in *realms_out, KRB5_PLUGIN_NO_HANDLE to defer to later modules, + * or another error to terminate processing. + */ +typedef krb5_error_code +(*krb5_hostrealm_fallback_realm_fn)(krb5_context context, + krb5_hostrealm_moddata data, + const char *host, char ***realms_out); + +/* + * Optional: Determine the possible default realms of the local host. Return + * success with a null-terminated list of realms in *realms_out, + * KRB5_PLUGIN_NO_HANDLE to defer to later modules, or another error to + * terminate processing. + */ +typedef krb5_error_code +(*krb5_hostrealm_default_realm_fn)(krb5_context context, + krb5_hostrealm_moddata data, + char ***realms_out); + +/* + * Mandatory (if any of the query methods are implemented): Release the memory + * returned by one of the interface methods. + */ +typedef void +(*krb5_hostrealm_free_list_fn)(krb5_context context, + krb5_hostrealm_moddata data, char **list); + +/* Optional: Release resources used by module data. */ +typedef void +(*krb5_hostrealm_fini_fn)(krb5_context context, krb5_hostrealm_moddata data); + +/* hostrealm vtable for major version 1. */ +typedef struct krb5_hostrealm_vtable_st { + const char *name; /* Mandatory: name of module. */ + krb5_hostrealm_init_fn init; + krb5_hostrealm_fini_fn fini; + krb5_hostrealm_host_realm_fn host_realm; + krb5_hostrealm_fallback_realm_fn fallback_realm; + krb5_hostrealm_default_realm_fn default_realm; + krb5_hostrealm_free_list_fn free_list; + /* Minor version 1 ends here. */ +} *krb5_hostrealm_vtable; + +#endif /* KRB5_HOSTREALM_PLUGIN_H */ diff --git a/krb5-1.21.3/src/include/krb5/kadm5_auth_plugin.h b/krb5-1.21.3/src/include/krb5/kadm5_auth_plugin.h new file mode 100644 index 00000000..d514e99b --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/kadm5_auth_plugin.h @@ -0,0 +1,306 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2017 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. + */ + +/* + * Declarations for kadm5_auth plugin module implementors. + * + * The kadm5_auth pluggable interface currently has only one supported major + * version, which is 1. Major version 1 has a current minor version number of + * 1. + * + * kadm5_auth plugin modules should define a function named + * kadm5_auth__initvt, matching the signature: + * + * krb5_error_code + * kadm5_auth_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for maj_ver: + * maj_ver == 1: Cast to krb5_kadm5_auth_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_KADM5_AUTH_PLUGIN_H +#define KRB5_KADM5_AUTH_PLUGIN_H + +#include +#include + +/* An abstract type for kadm5_auth module data. */ +typedef struct kadm5_auth_moddata_st *kadm5_auth_moddata; + +/* + * A module can optionally include to inspect principal or + * policy records from requests that add or modify principals or policies. + * Note that fields of principal and policy structures are only valid if the + * corresponding bit is set in the accompanying mask parameter. + */ +struct _kadm5_principal_ent_t; +struct _kadm5_policy_ent_t; + +/* + * A module can optionally generate restrictions when checking permissions for + * adding or modifying a principal entry. Restriction fields will only be + * honored if the corresponding mask bit is set. The operable mask bits are + * defined in and are: + * + * - KADM5_ATTRIBUTES for require_attrs, forbid_attrs + * - KADM5_POLICY for policy + * - KADM5_POLICY_CLR to require that policy be unset + * - KADM5_PRINC_EXPIRE_TIME for princ_lifetime + * - KADM5_PW_EXPIRATION for pw_lifetime + * - KADM5_MAX_LIFE for max_life + * - KADM5_MAX_RLIFE for max_renewable_life + */ +struct kadm5_auth_restrictions { + long mask; + krb5_flags require_attrs; + krb5_flags forbid_attrs; + krb5_deltat princ_lifetime; + krb5_deltat pw_lifetime; + krb5_deltat max_life; + krb5_deltat max_renewable_life; + char *policy; +}; + +/*** Method type declarations ***/ + +/* + * Optional: Initialize module data. acl_file is the realm's configured ACL + * file, or NULL if none was configured. Return 0 on success, + * KRB5_PLUGIN_NO_HANDLE if the module is inoperable (due to configuration, for + * example), and any other error code to abort kadmind startup. Optionally set + * *data_out to a module data object to be passed to future calls. + */ +typedef krb5_error_code +(*kadm5_auth_init_fn)(krb5_context context, const char *acl_file, + kadm5_auth_moddata *data_out); + +/* Optional: Release resources used by module data. */ +typedef void +(*kadm5_auth_fini_fn)(krb5_context context, kadm5_auth_moddata data); + +/* + * Each check method below should return 0 to explicitly authorize the request, + * KRB5_PLUGIN_NO_HANDLE to neither authorize nor deny the request, and any + * other error code (such as EPERM) to explicitly deny the request. If a check + * method is not defined, the module will neither authorize nor deny the + * request. A request succeeds if at least one kadm5_auth module explicitly + * authorizes the request and none of the modules explicitly deny it. + */ + +/* Optional: authorize an add-principal operation, and optionally generate + * restrictions. */ +typedef krb5_error_code +(*kadm5_auth_addprinc_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target, + const struct _kadm5_principal_ent_t *ent, long mask, + struct kadm5_auth_restrictions **rs_out); + +/* Optional: authorize a modify-principal operation, and optionally generate + * restrictions. */ +typedef krb5_error_code +(*kadm5_auth_modprinc_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target, + const struct _kadm5_principal_ent_t *ent, long mask, + struct kadm5_auth_restrictions **rs_out); + +/* Optional: authorize a set-string operation. */ +typedef krb5_error_code +(*kadm5_auth_setstr_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target, + const char *key, const char *value); + +/* Optional: authorize a change-password operation. */ +typedef krb5_error_code +(*kadm5_auth_cpw_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target); + +/* Optional: authorize a randomize-keys operation. */ +typedef krb5_error_code +(*kadm5_auth_chrand_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize a set-key operation. */ +typedef krb5_error_code +(*kadm5_auth_setkey_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize a purgekeys operation. */ +typedef krb5_error_code +(*kadm5_auth_purgekeys_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize a delete-principal operation. */ +typedef krb5_error_code +(*kadm5_auth_delprinc_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize a rename-principal operation. */ +typedef krb5_error_code +(*kadm5_auth_renprinc_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal src, + krb5_const_principal dest); + +/* Optional: authorize a get-principal operation. */ +typedef krb5_error_code +(*kadm5_auth_getprinc_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize a get-strings operation. */ +typedef krb5_error_code +(*kadm5_auth_getstrs_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize an extract-keys operation. */ +typedef krb5_error_code +(*kadm5_auth_extract_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, + krb5_const_principal target); + +/* Optional: authorize a list-principals operation. */ +typedef krb5_error_code +(*kadm5_auth_listprincs_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client); + +/* Optional: authorize an add-policy operation. */ +typedef krb5_error_code +(*kadm5_auth_addpol_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const struct _kadm5_policy_ent_t *ent, long mask); + +/* Optional: authorize a modify-policy operation. */ +typedef krb5_error_code +(*kadm5_auth_modpol_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const struct _kadm5_policy_ent_t *ent, long mask); + +/* Optional: authorize a delete-policy operation. */ +typedef krb5_error_code +(*kadm5_auth_delpol_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy); + +/* Optional: authorize a get-policy operation. client_policy is the client + * principal's policy name, or NULL if it does not have one. */ +typedef krb5_error_code +(*kadm5_auth_getpol_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const char *client_policy); + +/* Optional: authorize a list-policies operation. */ +typedef krb5_error_code +(*kadm5_auth_listpols_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client); + +/* Optional: authorize an iprop operation. */ +typedef krb5_error_code +(*kadm5_auth_iprop_fn)(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client); + +/* + * Optional: receive a notification that the most recent authorized operation + * has ended. If a kadm5_auth module is also a KDB module, it can assume that + * all KDB methods invoked between a kadm5_auth authorization method invocation + * and a kadm5_auth end invocation are performed as part of the authorized + * operation. + * + * The end method may be invoked without a preceding authorization method in + * some cases; the module must be prepared to ignore such calls. + */ +typedef void +(*kadm5_auth_end_fn)(krb5_context context, kadm5_auth_moddata data); + +/* + * Optional: free a restrictions object. This method does not need to be + * defined if the module does not generate restrictions objects, or if it + * returns aliases to restrictions objects contained from within the module + * data. + */ +typedef void +(*kadm5_auth_free_restrictions_fn)(krb5_context context, + kadm5_auth_moddata data, + struct kadm5_auth_restrictions *rs); + +/* kadm5_auth vtable for major version 1. */ +typedef struct kadm5_auth_vtable_st { + const char *name; /* Mandatory: name of module. */ + kadm5_auth_init_fn init; + kadm5_auth_fini_fn fini; + + kadm5_auth_addprinc_fn addprinc; + kadm5_auth_modprinc_fn modprinc; + kadm5_auth_setstr_fn setstr; + kadm5_auth_cpw_fn cpw; + kadm5_auth_chrand_fn chrand; + kadm5_auth_setkey_fn setkey; + kadm5_auth_purgekeys_fn purgekeys; + kadm5_auth_delprinc_fn delprinc; + kadm5_auth_renprinc_fn renprinc; + + kadm5_auth_getprinc_fn getprinc; + kadm5_auth_getstrs_fn getstrs; + kadm5_auth_extract_fn extract; + kadm5_auth_listprincs_fn listprincs; + + kadm5_auth_addpol_fn addpol; + kadm5_auth_modpol_fn modpol; + kadm5_auth_delpol_fn delpol; + kadm5_auth_getpol_fn getpol; + kadm5_auth_listpols_fn listpols; + + kadm5_auth_iprop_fn iprop; + + kadm5_auth_end_fn end; + + kadm5_auth_free_restrictions_fn free_restrictions; + /* Minor version 1 ends here. */ +} *kadm5_auth_vtable; + +#endif /* KRB5_KADM5_AUTH_PLUGIN_H */ diff --git a/krb5-1.21.3/src/include/krb5/kadm5_hook_plugin.h b/krb5-1.21.3/src/include/krb5/kadm5_hook_plugin.h new file mode 100644 index 00000000..f4f3730f --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/kadm5_hook_plugin.h @@ -0,0 +1,154 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef H_KRB5_KADM5_HOOK_PLUGIN +#define H_KRB5_KADM5_HOOK_PLUGIN + +/** + * @file krb5/krb5_kadm5_hook_plugin.h + * Provide a plugin interface for kadm5 operations. This interface + * permits a plugin to intercept principal modification, creation and + * change password operations. Operations run at two stages: a + * precommit stage that runs before the operation is committed to the + * database and a postcommit operation that runs after the database + * is updated; see #kadm5_hook_stage for details on semantics. + * + * This interface is based on a proposed extension to Heimdal by Russ + * Allbery; it is likely that Heimdal will adopt an approach based on + * stacked kdb modules rather than this interface. For MIT, writing a + * plugin to this interface is significantly easier than stacking kdb + * modules. Also, the kadm5 interface is significantly more stable + * than the kdb interface, so this approach is more desirable than + * stacked kdb modules. + * + * This interface depends on kadm5/admin.h. As such, the interface + * does not provide strong guarantees of ABI stability. + * + * The kadm5_hook interface currently has only one supported major version, + * which is 1. Major version 1 has a current minor version number of 2. + * + * kadm5_hook plugins should: + * kadm5_hook__initvt, matching the signature: + * + * krb5_error_code + * kadm5_hook_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for maj_ver: + * maj_ver == 1: Cast to kadm5_hook_vftable_1 + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#include +#include +#include + +/** + * Whether the operation is being run before or after the database + * update. + */ +enum kadm5_hook_stage { + /** In this stage, any plugin failure prevents following plugins from + * running and aborts the operation.*/ + KADM5_HOOK_STAGE_PRECOMMIT, + /** In this stage, plugin failures are logged but otherwise ignored.*/ + KADM5_HOOK_STAGE_POSTCOMMIT +}; + +/** Opaque module data pointer. */ +typedef struct kadm5_hook_modinfo_st kadm5_hook_modinfo; + +/** + * Interface for the v1 virtual table for the kadm5_hook plugin. + * All entry points are optional. The name field must be provided. + */ +typedef struct kadm5_hook_vtable_1_st { + + /** A text string identifying the plugin for logging messages. */ + const char *name; + + /** Initialize a plugin module. + * @param modinfo returns newly allocated module info for future + * calls. Cleaned up by the fini() function. + */ + kadm5_ret_t (*init)(krb5_context, kadm5_hook_modinfo **modinfo); + + /** Clean up a module and free @a modinfo. */ + void (*fini)(krb5_context, kadm5_hook_modinfo *modinfo); + + /** Indicates that the password is being changed. + * @param stage is an integer from #kadm5_hook_stage enumeration + * @param keepold is true if existing keys are being kept. + * @param newpass is NULL if the key sare being randomized. + */ + kadm5_ret_t (*chpass)(krb5_context, + kadm5_hook_modinfo *modinfo, + int stage, + krb5_principal, krb5_boolean keepold, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + const char *newpass); + + /** Indicate a principal is created. */ + kadm5_ret_t (*create)(krb5_context, + kadm5_hook_modinfo *, + int stage, + kadm5_principal_ent_t, long mask, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + const char *password); + + /** Modify a principal. */ + kadm5_ret_t (*modify)(krb5_context, + kadm5_hook_modinfo *, + int stage, + kadm5_principal_ent_t, long mask); + + /** Indicate a principal is deleted. */ + kadm5_ret_t (*remove)(krb5_context, + kadm5_hook_modinfo *modinfo, + int stage, krb5_principal); + + /* End of minor version 1. */ + + /** Indicate a principal is renamed. */ + kadm5_ret_t (*rename)(krb5_context, + kadm5_hook_modinfo *modinfo, + int stage, krb5_principal, krb5_principal); + + /* End of minor version 2. */ + +} kadm5_hook_vftable_1; + +#endif /*H_KRB5_KADM5_HOOK_PLUGIN*/ diff --git a/krb5-1.21.3/src/include/krb5/kdcauthdata_plugin.h b/krb5-1.21.3/src/include/krb5/kdcauthdata_plugin.h new file mode 100644 index 00000000..53fe69cd --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/kdcauthdata_plugin.h @@ -0,0 +1,129 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2014 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. + */ + +/* + * This interface is not yet public and may change without honoring the + * pluggable interface version system. The header file is deliberately not + * installed by "make install". + * + * This interface references kdb.h, which is not stable. A module which + * references fields of krb5_db_entry, invokes libkdb5 functions, or uses the + * flags argument may not be future-proof even if this interface becomes + * public. + * + * Expecting modules to hand-modify enc_tkt_reply->authorization_data is + * cumbersome for the module, and doesn't work if the module uses a different + * allocator from the krb5 tree. A libkrb5 API to add an authdata value to a + * list would improve this situation. + */ + +/* + * Declarations for kdcauthdata plugin module implementors. + * + * The kdcauthdata interface has a single supported major version, which is 1. + * Major version 1 has a current minor version of 1. kdcauthdata modules + * should define a function named kdcauthdata__initvt, matching the + * signature: + * + * krb5_error_code + * kdcauthdata_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for the interface and maj_ver: + * maj_ver == 1: Cast to krb5_kdcauthdata_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_KDCAUTHDATA_PLUGIN_H +#define KRB5_KDCAUTHDATA_PLUGIN_H + +#include +#include +#include + +/* Abstract type for module data. */ +typedef struct krb5_kdcauthdata_moddata_st *krb5_kdcauthdata_moddata; + +/* Optional: module initialization function. If this function returns an + * error, the KDC will log the failure and ignore the module. */ +typedef krb5_error_code +(*krb5_kdcauthdata_init_fn)(krb5_context context, + krb5_kdcauthdata_moddata *moddata_out); + +/* Optional: module cleanup function. */ +typedef void +(*krb5_kdcauthdata_fini_fn)(krb5_context context, + krb5_kdcauthdata_moddata moddata); + +/* + * Mandatory: authorization data handling function. + * + * All values should be considered input-only, except that the method can + * modify enc_tkt_reply->authorization_data to add authdata values. This field + * is a null-terminated list of allocated pointers; the plugin method must + * reallocate it to make room for any added authdata values. + * + * If this function returns an error, the AS or TGS request will be rejected. + */ +typedef krb5_error_code +(*krb5_kdcauthdata_handle_fn)(krb5_context context, + krb5_kdcauthdata_moddata moddata, + unsigned int flags, + krb5_db_entry *client, krb5_db_entry *server, + krb5_db_entry *header_server, + krb5_keyblock *client_key, + krb5_keyblock *server_key, + krb5_keyblock *header_key, + krb5_data *req_pkt, krb5_kdc_req *req, + krb5_const_principal for_user_princ, + krb5_enc_tkt_part *enc_tkt_req, + krb5_enc_tkt_part *enc_tkt_reply); + +typedef struct krb5_kdcauthdata_vtable_st { + /* Mandatory: name of module. */ + const char *name; + + krb5_kdcauthdata_init_fn init; + krb5_kdcauthdata_fini_fn fini; + krb5_kdcauthdata_handle_fn handle; + /* Minor 1 ends here. */ +} *krb5_kdcauthdata_vtable; + +#endif /* KRB5_KDCAUTHDATA_PLUGIN_H */ diff --git a/krb5-1.21.3/src/include/krb5/kdcpolicy_plugin.h b/krb5-1.21.3/src/include/krb5/kdcpolicy_plugin.h new file mode 100644 index 00000000..c7592c5d --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/kdcpolicy_plugin.h @@ -0,0 +1,128 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/krb5/kdcpolicy_plugin.h - KDC policy plugin interface */ +/* + * Copyright (C) 2017 by Red Hat, Inc. + * 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. + */ + +/* + * Declarations for kdcpolicy plugin module implementors. + * + * The kdcpolicy pluggable interface currently has only one supported major + * version, which is 1. Major version 1 has a current minor version number of + * 1. + * + * kdcpolicy plugin modules should define a function named + * kdcpolicy__initvt, matching the signature: + * + * krb5_error_code + * kdcpolicy_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for maj_ver: + * maj_ver == 1: Cast to krb5_kdcpolicy_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_POLICY_PLUGIN_H +#define KRB5_POLICY_PLUGIN_H + +#include + +/* Abstract module datatype. */ +typedef struct krb5_kdcpolicy_moddata_st *krb5_kdcpolicy_moddata; + +/* A module can optionally include kdb.h to inspect principal entries when + * authorizing requests. */ +struct _krb5_db_entry_new; + +/* + * Optional: Initialize module data. Return 0 on success, + * KRB5_PLUGIN_NO_HANDLE if the module is inoperable (due to configuration, for + * example), and any other error code to abort KDC startup. Optionally set + * *data_out to a module data object to be passed to future calls. + */ +typedef krb5_error_code +(*krb5_kdcpolicy_init_fn)(krb5_context context, + krb5_kdcpolicy_moddata *data_out); + +/* Optional: Clean up module data. */ +typedef krb5_error_code +(*krb5_kdcpolicy_fini_fn)(krb5_context context, + krb5_kdcpolicy_moddata moddata); + +/* + * Optional: return an error code and set status to an appropriate string + * literal to deny an AS request; otherwise return 0. lifetime_out, if set, + * restricts the ticket lifetime. renew_lifetime_out, if set, restricts the + * ticket renewable lifetime. + */ +typedef krb5_error_code +(*krb5_kdcpolicy_check_as_fn)(krb5_context context, + krb5_kdcpolicy_moddata moddata, + const krb5_kdc_req *request, + const struct _krb5_db_entry_new *client, + const struct _krb5_db_entry_new *server, + const char *const *auth_indicators, + const char **status, krb5_deltat *lifetime_out, + krb5_deltat *renew_lifetime_out); + +/* + * Optional: return an error code and set status to an appropriate string + * literal to deny a TGS request; otherwise return 0. lifetime_out, if set, + * restricts the ticket lifetime. renew_lifetime_out, if set, restricts the + * ticket renewable lifetime. + */ +typedef krb5_error_code +(*krb5_kdcpolicy_check_tgs_fn)(krb5_context context, + krb5_kdcpolicy_moddata moddata, + const krb5_kdc_req *request, + const struct _krb5_db_entry_new *server, + const krb5_ticket *ticket, + const char *const *auth_indicators, + const char **status, krb5_deltat *lifetime_out, + krb5_deltat *renew_lifetime_out); + +typedef struct krb5_kdcpolicy_vtable_st { + const char *name; + krb5_kdcpolicy_init_fn init; + krb5_kdcpolicy_fini_fn fini; + krb5_kdcpolicy_check_as_fn check_as; + krb5_kdcpolicy_check_tgs_fn check_tgs; +} *krb5_kdcpolicy_vtable; + +#endif /* KRB5_POLICY_PLUGIN_H */ diff --git a/krb5-1.21.3/src/include/krb5/kdcpreauth_plugin.h b/krb5-1.21.3/src/include/krb5/kdcpreauth_plugin.h new file mode 100644 index 00000000..f40e368c --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/kdcpreauth_plugin.h @@ -0,0 +1,417 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (c) 2006 Red Hat, Inc. + * Portions copyright (c) 2006, 2011 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. + * * Neither the name of Red Hat, Inc., 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 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. + */ + +/* + * Declarations for kdcpreauth plugin module implementors. + * + * The kdcpreauth interface has a single supported major version, which is 1. + * Major version 1 has a current minor version of 2. kdcpreauth modules should + * define a function named kdcpreauth__initvt, matching the + * signature: + * + * krb5_error_code + * kdcpreauth_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for the interface and maj_ver: + * kdcpreauth, maj_ver == 1: Cast to krb5_kdcpreauth_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_KDCPREAUTH_PLUGIN_H +#define KRB5_KDCPREAUTH_PLUGIN_H + +#include +#include + +/* kdcpreauth mechanism property flags */ + +/* + * Causes the KDC to include this mechanism in a list of supported preauth + * types if the user's DB entry flags the user as requiring hardware-based + * preauthentication. + */ +#define PA_HARDWARE 0x00000004 + +/* + * Causes the KDC to include this mechanism in a list of supported preauth + * types if the user's DB entry flags the user as requiring preauthentication, + * and to fail preauthentication if we can't verify the client data. The + * flipside of PA_SUFFICIENT. + */ +#define PA_REQUIRED 0x00000008 + +/* + * Causes the KDC to include this mechanism in a list of supported preauth + * types if the user's DB entry flags the user as requiring preauthentication, + * and to mark preauthentication as successful if we can verify the client + * data. The flipside of PA_REQUIRED. + */ +#define PA_SUFFICIENT 0x00000010 + +/* + * Marks this preauthentication mechanism as one which changes the key which is + * used for encrypting the response to the client. Modules which have this + * flag have their server_return_fn called before modules which do not, and are + * passed over if a previously-called module has modified the encrypting key. + */ +#define PA_REPLACES_KEY 0x00000020 + +/* + * Not really a padata type, so don't include it in any list of preauth types + * which gets sent over the wire. + */ +#define PA_PSEUDO 0x00000080 + +/* + * Indicates that e_data in non-FAST errors should be encoded as typed data + * instead of padata. + */ +#define PA_TYPED_E_DATA 0x00000100 + +/* Abstract type for a KDC callback data handle. */ +typedef struct krb5_kdcpreauth_rock_st *krb5_kdcpreauth_rock; + +/* Abstract type for module data and per-request module data. */ +typedef struct krb5_kdcpreauth_moddata_st *krb5_kdcpreauth_moddata; +typedef struct krb5_kdcpreauth_modreq_st *krb5_kdcpreauth_modreq; + +/* The verto context structure type (typedef is in verto.h; we want to avoid a + * header dependency for the moment). */ +struct verto_ctx; + +/* Before using a callback after version 1, modules must check the vers + * field of the callback structure. */ +typedef struct krb5_kdcpreauth_callbacks_st { + int vers; + + krb5_deltat (*max_time_skew)(krb5_context context, + krb5_kdcpreauth_rock rock); + + /* + * Get an array of krb5_keyblock structures containing the client keys + * matching the request enctypes, terminated by an entry with key type = 0. + * Returns ENOENT if no keys are available for the request enctypes. Free + * the resulting object with the free_keys callback. + */ + krb5_error_code (*client_keys)(krb5_context context, + krb5_kdcpreauth_rock rock, + krb5_keyblock **keys_out); + + /* Free the result of client_keys. */ + void (*free_keys)(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_keyblock *keys); + + /* + * Get the encoded request body, which is sometimes needed for checksums. + * For a FAST request this is the encoded inner request body. The returned + * pointer is an alias and should not be freed. + */ + krb5_data *(*request_body)(krb5_context context, + krb5_kdcpreauth_rock rock); + + /* Get a pointer to the FAST armor key, or NULL if the request did not use + * FAST. The returned pointer is an alias and should not be freed. */ + krb5_keyblock *(*fast_armor)(krb5_context context, + krb5_kdcpreauth_rock rock); + + /* Retrieve a string attribute from the client DB entry, or NULL if no such + * attribute is set. Free the result with the free_string callback. */ + krb5_error_code (*get_string)(krb5_context context, + krb5_kdcpreauth_rock rock, const char *key, + char **value_out); + + /* Free the result of get_string. */ + void (*free_string)(krb5_context context, krb5_kdcpreauth_rock rock, + char *string); + + /* Get a pointer to the client DB entry (returned as a void pointer to + * avoid a dependency on a libkdb5 type). */ + void *(*client_entry)(krb5_context context, krb5_kdcpreauth_rock rock); + + /* Get a pointer to the verto context which should be used by an + * asynchronous edata or verify method. */ + struct verto_ctx *(*event_context)(krb5_context context, + krb5_kdcpreauth_rock rock); + + /* End of version 1 kdcpreauth callbacks. */ + + /* Return true if the client DB entry contains any keys matching the + * request enctypes. */ + krb5_boolean (*have_client_keys)(krb5_context context, + krb5_kdcpreauth_rock rock); + + /* End of version 2 kdcpreauth callbacks. */ + + /* + * Get the current reply key. Initially the reply key is the decrypted + * client long-term key chosen according to the request enctype list, or + * NULL if no matching key was found. The value may be changed by the + * replace_reply_key callback or a return_padata method modifying + * encrypting_key. The returned pointer is an alias and should not be + * freed. + */ + const krb5_keyblock *(*client_keyblock)(krb5_context context, + krb5_kdcpreauth_rock rock); + + /* Assert an authentication indicator in the AS-REP authdata. Duplicate + * indicators will be ignored. */ + krb5_error_code (*add_auth_indicator)(krb5_context context, + krb5_kdcpreauth_rock rock, + const char *indicator); + + /* + * Read a data value for pa_type from the request cookie, placing it in + * *out. The value placed there is an alias and must not be freed. + * Returns true if a value for pa_type was retrieved, false if not. + */ + krb5_boolean (*get_cookie)(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_preauthtype pa_type, krb5_data *out); + + /* + * Set a data value for pa_type to be sent in a secure cookie in the next + * error response. If pa_type is already present, the value is ignored. + * If the preauth mechanism has different preauth types for requests and + * responses, use the request type. Secure cookies are encrypted in a key + * known only to the KDCs, but can be replayed within a short time window + * for requests using the same client principal. + */ + krb5_error_code (*set_cookie)(krb5_context context, + krb5_kdcpreauth_rock rock, + krb5_preauthtype pa_type, + const krb5_data *data); + + /* End of version 3 kdcpreauth callbacks. */ + + /* + * Return true if princ matches the principal named in the request or the + * client principal (possibly canonicalized). If princ does not match, + * attempt a database lookup of princ with aliases allowed and compare the + * result to the client principal, returning true if it matches. + * Otherwise, return false. + */ + krb5_boolean (*match_client)(krb5_context context, + krb5_kdcpreauth_rock rock, + krb5_principal princ); + + /* + * Get an alias to the client DB entry principal (possibly canonicalized). + */ + krb5_principal (*client_name)(krb5_context context, + krb5_kdcpreauth_rock rock); + + /* End of version 4 kdcpreauth callbacks. */ + + /* + * Instruct the KDC to send a freshness token in the method data + * accompanying a PREAUTH_REQUIRED or PREAUTH_FAILED error, if the client + * indicated support for freshness tokens. This callback should only be + * invoked from the edata method. + */ + void (*send_freshness_token)(krb5_context context, + krb5_kdcpreauth_rock rock); + + /* Validate a freshness token sent by the client. Return 0 on success, + * KRB5KDC_ERR_PREAUTH_EXPIRED on error. */ + krb5_error_code (*check_freshness_token)(krb5_context context, + krb5_kdcpreauth_rock rock, + const krb5_data *token); + + /* End of version 5 kdcpreauth callbacks. */ + + /* + * Replace the reply key with key. If is_strengthen is true, key must be a + * derivative of the client long-term key. This callback may be invoked + * from the verify or return_padata methods. If it is invoked from the + * verify method, the new key will appear as the encrypting_key input to + * return_padata. + */ + krb5_error_code (*replace_reply_key)(krb5_context context, + krb5_kdcpreauth_rock rock, + const krb5_keyblock *key, + krb5_boolean is_strengthen); + + /* End of version 6 kdcpreauth callbacks. */ + +} *krb5_kdcpreauth_callbacks; + +/* Optional: preauth plugin initialization function. */ +typedef krb5_error_code +(*krb5_kdcpreauth_init_fn)(krb5_context context, + krb5_kdcpreauth_moddata *moddata_out, + const char **realmnames); + +/* Optional: preauth plugin cleanup function. */ +typedef void +(*krb5_kdcpreauth_fini_fn)(krb5_context context, + krb5_kdcpreauth_moddata moddata); + +/* + * Optional: return the flags which the KDC should use for this module. This + * is a callback instead of a static value because the module may or may not + * wish to count itself as a hardware preauthentication module (in other words, + * the flags may be affected by the configuration, for example if a site + * administrator can force a particular preauthentication type to be supported + * using only hardware). This function is called for each entry entry in the + * server_pa_type_list. + */ +typedef int +(*krb5_kdcpreauth_flags_fn)(krb5_context context, krb5_preauthtype pa_type); + +/* + * Responder for krb5_kdcpreauth_edata_fn. If invoked with a non-zero code, pa + * will be ignored and the padata type will not be included in the hint list. + * If invoked with a zero code and a null pa value, the padata type will be + * included in the list with an empty value. If invoked with a zero code and a + * non-null pa value, pa will be included in the hint list and will later be + * freed by the KDC. + */ +typedef void +(*krb5_kdcpreauth_edata_respond_fn)(void *arg, krb5_error_code code, + krb5_pa_data *pa); + +/* + * Optional: provide pa_data to send to the client as part of the "you need to + * use preauthentication" error. The implementation must invoke the respond + * when complete, whether successful or not, either before returning or + * asynchronously using the verto context returned by cb->event_context(). + * + * This function is not allowed to create a modreq object because we have no + * guarantee that the client will ever make a follow-up request, or that it + * will hit this KDC if it does. + */ +typedef void +(*krb5_kdcpreauth_edata_fn)(krb5_context context, krb5_kdc_req *request, + krb5_kdcpreauth_callbacks cb, + krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, + krb5_preauthtype pa_type, + krb5_kdcpreauth_edata_respond_fn respond, + void *arg); + +/* + * Responder for krb5_kdcpreauth_verify_fn. Invoke with the arg parameter + * supplied to verify, the error code (0 for success), an optional module + * request state object to be consumed by return_fn or free_modreq_fn, optional + * e_data to be passed to the caller if code is nonzero, and optional + * authorization data to be included in the ticket. In non-FAST replies, + * e_data will be encoded as typed-data if the module sets the PA_TYPED_E_DATA + * flag, and as pa-data otherwise. e_data and authz_data will be freed by the + * KDC. + */ +typedef void +(*krb5_kdcpreauth_verify_respond_fn)(void *arg, krb5_error_code code, + krb5_kdcpreauth_modreq modreq, + krb5_pa_data **e_data, + krb5_authdata **authz_data); + +/* + * Optional: verify preauthentication data sent by the client, setting the + * TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags" + * field as appropriate. The implementation must invoke the respond function + * when complete, whether successful or not, either before returning or + * asynchronously using the verto context returned by cb->event_context(). + */ +typedef void +(*krb5_kdcpreauth_verify_fn)(krb5_context context, + krb5_data *req_pkt, krb5_kdc_req *request, + krb5_enc_tkt_part *enc_tkt_reply, + krb5_pa_data *data, + krb5_kdcpreauth_callbacks cb, + krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_verify_respond_fn respond, + void *arg); + +/* + * Optional: generate preauthentication response data to send to the client as + * part of the AS-REP. If it needs to override the key which is used to + * encrypt the response, it can do so by modifying encrypting_key, but it is + * preferrable to use the replace_reply_key callback. + */ +typedef krb5_error_code +(*krb5_kdcpreauth_return_fn)(krb5_context context, + krb5_pa_data *padata, + krb5_data *req_pkt, + krb5_kdc_req *request, + krb5_kdc_rep *reply, + krb5_keyblock *encrypting_key, + krb5_pa_data **send_pa_out, + krb5_kdcpreauth_callbacks cb, + krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq); + +/* Optional: free a per-request context. */ +typedef void +(*krb5_kdcpreauth_free_modreq_fn)(krb5_context, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq); + +/* Optional: invoked after init_fn to provide the module with a pointer to the + * verto main loop. */ +typedef krb5_error_code +(*krb5_kdcpreauth_loop_fn)(krb5_context context, + krb5_kdcpreauth_moddata moddata, + struct verto_ctx *ctx); + +typedef struct krb5_kdcpreauth_vtable_st { + /* Mandatory: name of module. */ + const char *name; + + /* Mandatory: pointer to zero-terminated list of pa_types which this module + * can provide services for. */ + krb5_preauthtype *pa_type_list; + + krb5_kdcpreauth_init_fn init; + krb5_kdcpreauth_fini_fn fini; + krb5_kdcpreauth_flags_fn flags; + krb5_kdcpreauth_edata_fn edata; + krb5_kdcpreauth_verify_fn verify; + krb5_kdcpreauth_return_fn return_padata; + krb5_kdcpreauth_free_modreq_fn free_modreq; + /* Minor 1 ends here. */ + + krb5_kdcpreauth_loop_fn loop; + /* Minor 2 ends here. */ +} *krb5_kdcpreauth_vtable; + +#endif /* KRB5_KDCPREAUTH_PLUGIN_H */ diff --git a/krb5-1.21.3/src/include/krb5/krb5.hin b/krb5-1.21.3/src/include/krb5/krb5.hin new file mode 100644 index 00000000..4e09ed34 --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/krb5.hin @@ -0,0 +1,8590 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* General definitions for Kerberos version 5. */ +/* + * Copyright 1989, 1990, 1995, 2001, 2003, 2007, 2011 by the Massachusetts + * Institute of Technology. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef KRB5_GENERAL__ +#define KRB5_GENERAL__ + + /* By default, do not expose deprecated interfaces. */ +#ifndef KRB5_DEPRECATED +#define KRB5_DEPRECATED 0 +#endif + +#if defined(__MACH__) && defined(__APPLE__) +# include +# if TARGET_RT_MAC_CFM +# error "Use KfM 4.0 SDK headers for CFM compilation." +# endif +#endif + +#if defined(_MSDOS) || defined(_WIN32) +#include +#endif + +#ifndef KRB5_CONFIG__ +#ifndef KRB5_CALLCONV +#define KRB5_CALLCONV +#define KRB5_CALLCONV_C +#endif /* !KRB5_CALLCONV */ +#endif /* !KRB5_CONFIG__ */ + +#ifndef KRB5_CALLCONV_WRONG +#define KRB5_CALLCONV_WRONG +#endif + +#ifndef THREEPARAMOPEN +#define THREEPARAMOPEN(x,y,z) open(x,y,z) +#endif + +#define KRB5_OLD_CRYPTO + +#include +#include /* for *_MAX */ +#include +#include + +#ifndef KRB5INT_BEGIN_DECLS +#if defined(__cplusplus) +#define KRB5INT_BEGIN_DECLS extern "C" { +#define KRB5INT_END_DECLS } +#else +#define KRB5INT_BEGIN_DECLS +#define KRB5INT_END_DECLS +#endif +#endif + +KRB5INT_BEGIN_DECLS + +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)) +#pragma pack(push,2) +#endif + +#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) >= 30203 +# define KRB5_ATTR_DEPRECATED __attribute__((deprecated)) +#elif defined _WIN32 +# define KRB5_ATTR_DEPRECATED __declspec(deprecated) +#else +# define KRB5_ATTR_DEPRECATED +#endif + +/* from profile.h */ +struct _profile_t; +/* typedef struct _profile_t *profile_t; */ + +/* + * begin wordsize.h + */ + +/* + * Word-size related definition. + */ + +typedef uint8_t krb5_octet; +typedef int16_t krb5_int16; +typedef uint16_t krb5_ui_2; +typedef int32_t krb5_int32; +typedef uint32_t krb5_ui_4; + +#define VALID_INT_BITS INT_MAX +#define VALID_UINT_BITS UINT_MAX + +#define KRB5_INT32_MAX 2147483647 +/* this strange form is necessary since - is a unary operator, not a sign + indicator */ +#define KRB5_INT32_MIN (-KRB5_INT32_MAX-1) + +#define KRB5_INT16_MAX 65535 +/* this strange form is necessary since - is a unary operator, not a sign + indicator */ +#define KRB5_INT16_MIN (-KRB5_INT16_MAX-1) + +/* + * end wordsize.h + */ + +/* + * begin "base-defs.h" + */ + +/* + * Basic definitions for Kerberos V5 library + */ + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +typedef unsigned int krb5_boolean; +typedef unsigned int krb5_msgtype; +typedef unsigned int krb5_kvno; + +typedef krb5_int32 krb5_addrtype; +typedef krb5_int32 krb5_enctype; +typedef krb5_int32 krb5_cksumtype; +typedef krb5_int32 krb5_authdatatype; +typedef krb5_int32 krb5_keyusage; +typedef krb5_int32 krb5_cryptotype; + +typedef krb5_int32 krb5_preauthtype; /* This may change, later on */ +typedef krb5_int32 krb5_flags; + +/** + * Represents a timestamp in seconds since the POSIX epoch. This legacy type + * is used frequently in the ABI, but cannot represent timestamps after 2038 as + * a positive number. Code which uses this type should cast values of it to + * uint32_t so that negative values are treated as timestamps between 2038 and + * 2106 on platforms with 64-bit time_t. + */ +typedef krb5_int32 krb5_timestamp; + +typedef krb5_int32 krb5_deltat; + +/** + * Used to convey an operation status. The value 0 indicates success; any + * other values are com_err codes. Use krb5_get_error_message() to obtain a + * string describing the error. + */ +typedef krb5_int32 krb5_error_code; + +typedef krb5_error_code krb5_magic; + +typedef struct _krb5_data { + krb5_magic magic; + unsigned int length; + char *data; +} krb5_data; + +/* Originally introduced for PKINIT; now unused. Do not use this. */ +typedef struct _krb5_octet_data { + krb5_magic magic; + unsigned int length; + krb5_octet *data; +} krb5_octet_data; + +/* Originally used to recognize AFS and default salts. No longer used. */ +#define SALT_TYPE_AFS_LENGTH UINT_MAX +#define SALT_TYPE_NO_LENGTH UINT_MAX + +typedef void * krb5_pointer; +typedef void const * krb5_const_pointer; + +typedef struct krb5_principal_data { + krb5_magic magic; + krb5_data realm; + krb5_data *data; /**< An array of strings */ + krb5_int32 length; + krb5_int32 type; +} krb5_principal_data; + +typedef krb5_principal_data * krb5_principal; + +/* + * Per V5 spec on definition of principal types + */ + +#define KRB5_NT_UNKNOWN 0 /**< Name type not known */ +#define KRB5_NT_PRINCIPAL 1 /**< Just the name of the principal + as in DCE, or for users */ +#define KRB5_NT_SRV_INST 2 /**< Service and other unique instance (krbtgt) */ +#define KRB5_NT_SRV_HST 3 /**< Service with host name as instance + (telnet, rcommands) */ +#define KRB5_NT_SRV_XHST 4 /**< Service with host as remaining components */ +#define KRB5_NT_UID 5 /**< Unique ID */ +#define KRB5_NT_X500_PRINCIPAL 6 /**< PKINIT */ +#define KRB5_NT_SMTP_NAME 7 /**< Name in form of SMTP email name */ +#define KRB5_NT_ENTERPRISE_PRINCIPAL 10 /**< Windows 2000 UPN */ +#define KRB5_NT_WELLKNOWN 11 /**< Well-known (special) principal */ +#define KRB5_WELLKNOWN_NAMESTR "WELLKNOWN" /**< First component of + NT_WELLKNOWN principals */ +#define KRB5_NT_MS_PRINCIPAL -128 /**< Windows 2000 UPN and SID */ +#define KRB5_NT_MS_PRINCIPAL_AND_ID -129 /**< NT 4 style name */ +#define KRB5_NT_ENT_PRINCIPAL_AND_ID -130 /**< NT 4 style name and SID */ + +/** Constant version of krb5_principal_data. */ +typedef const krb5_principal_data *krb5_const_principal; + +#define krb5_princ_realm(context, princ) (&(princ)->realm) +#define krb5_princ_set_realm(context, princ,value) ((princ)->realm = *(value)) +#define krb5_princ_set_realm_length(context, princ,value) (princ)->realm.length = (value) +#define krb5_princ_set_realm_data(context, princ,value) (princ)->realm.data = (value) +#define krb5_princ_size(context, princ) (princ)->length +#define krb5_princ_type(context, princ) (princ)->type +#define krb5_princ_name(context, princ) (princ)->data +#define krb5_princ_component(context, princ,i) \ + (((i) < krb5_princ_size(context, princ)) \ + ? (princ)->data + (i) \ + : NULL) + +/** Constant for realm referrals. */ +#define KRB5_REFERRAL_REALM "" + +/* + * Referral-specific functions. + */ + +/** + * Check for a match with KRB5_REFERRAL_REALM. + * + * @param [in] r Realm to check + * + * @return @c TRUE if @a r is zero-length, @c FALSE otherwise + */ +krb5_boolean KRB5_CALLCONV +krb5_is_referral_realm(const krb5_data *r); + +/** + * Return an anonymous realm data. + * + * This function returns constant storage that must not be freed. + * + * @sa #KRB5_ANONYMOUS_REALMSTR + */ +const krb5_data *KRB5_CALLCONV +krb5_anonymous_realm(void); + +/** + * Build an anonymous principal. + * + * This function returns constant storage that must not be freed. + * + * @sa #KRB5_ANONYMOUS_PRINCSTR + */ +krb5_const_principal KRB5_CALLCONV +krb5_anonymous_principal(void); + +#define KRB5_ANONYMOUS_REALMSTR "WELLKNOWN:ANONYMOUS" /**< Anonymous realm */ +#define KRB5_ANONYMOUS_PRINCSTR "ANONYMOUS" /**< Anonymous principal name */ +/* + * end "base-defs.h" + */ + +/* + * begin "hostaddr.h" + */ + +/** Structure for address */ +typedef struct _krb5_address { + krb5_magic magic; + krb5_addrtype addrtype; + unsigned int length; + krb5_octet *contents; +} krb5_address; + +/* per Kerberos v5 protocol spec */ +#define ADDRTYPE_INET 0x0002 +#define ADDRTYPE_CHAOS 0x0005 +#define ADDRTYPE_XNS 0x0006 +#define ADDRTYPE_ISO 0x0007 +#define ADDRTYPE_DDP 0x0010 +#define ADDRTYPE_NETBIOS 0x0014 +#define ADDRTYPE_INET6 0x0018 +/* not yet in the spec... */ +#define ADDRTYPE_ADDRPORT 0x0100 +#define ADDRTYPE_IPPORT 0x0101 + +/* macros to determine if a type is a local type */ +#define ADDRTYPE_IS_LOCAL(addrtype) (addrtype & 0x8000) + +/* + * end "hostaddr.h" + */ + + +struct _krb5_context; +typedef struct _krb5_context * krb5_context; + +struct _krb5_auth_context; +typedef struct _krb5_auth_context * krb5_auth_context; + +struct _krb5_cryptosystem_entry; + +/* + * begin "encryption.h" + */ + +/** Exposed contents of a key. */ +typedef struct _krb5_keyblock { + krb5_magic magic; + krb5_enctype enctype; + unsigned int length; + krb5_octet *contents; +} krb5_keyblock; + +struct krb5_key_st; +/** + * Opaque identifier for a key. + * + * Use with the krb5_k APIs for better performance for repeated operations with + * the same key and usage. Key identifiers must not be used simultaneously + * within multiple threads, as they may contain mutable internal state and are + * not mutex-protected. + */ +typedef struct krb5_key_st *krb5_key; + +#ifdef KRB5_OLD_CRYPTO +typedef struct _krb5_encrypt_block { + krb5_magic magic; + krb5_enctype crypto_entry; /* to call krb5_encrypt_size, you need + this. it was a pointer, but it + doesn't have to be. gross. */ + krb5_keyblock *key; +} krb5_encrypt_block; +#endif + +typedef struct _krb5_checksum { + krb5_magic magic; + krb5_cksumtype checksum_type; /* checksum type */ + unsigned int length; + krb5_octet *contents; +} krb5_checksum; + +typedef struct _krb5_enc_data { + krb5_magic magic; + krb5_enctype enctype; + krb5_kvno kvno; + krb5_data ciphertext; +} krb5_enc_data; + +/** + * Structure to describe a region of text to be encrypted or decrypted. + * + * The @a flags member describes the type of the iov. + * The @a data member points to the memory that will be manipulated. + * All iov APIs take a pointer to the first element of an array of krb5_crypto_iov's + * along with the size of that array. Buffer contents are manipulated in-place; + * data is overwritten. Callers must allocate the right number of krb5_crypto_iov + * structures before calling into an iov API. + */ +typedef struct _krb5_crypto_iov { + krb5_cryptotype flags; /**< iov type (see KRB5_CRYPTO_TYPE macros) */ + krb5_data data; +} krb5_crypto_iov; + +/* per Kerberos v5 protocol spec */ +#define ENCTYPE_NULL 0x0000 +#define ENCTYPE_DES_CBC_CRC 0x0001 /**< @deprecated no longer supported */ +#define ENCTYPE_DES_CBC_MD4 0x0002 /**< @deprecated no longer supported */ +#define ENCTYPE_DES_CBC_MD5 0x0003 /**< @deprecated no longer supported */ +#define ENCTYPE_DES_CBC_RAW 0x0004 /**< @deprecated no longer supported */ +#define ENCTYPE_DES3_CBC_SHA 0x0005 /**< @deprecated DES-3 cbc with SHA1 */ +#define ENCTYPE_DES3_CBC_RAW 0x0006 /**< @deprecated DES-3 cbc mode raw */ +#define ENCTYPE_DES_HMAC_SHA1 0x0008 /**< @deprecated no longer supported */ +/* PKINIT */ +#define ENCTYPE_DSA_SHA1_CMS 0x0009 /**< DSA with SHA1, CMS signature */ +#define ENCTYPE_MD5_RSA_CMS 0x000a /**< MD5 with RSA, CMS signature */ +#define ENCTYPE_SHA1_RSA_CMS 0x000b /**< SHA1 with RSA, CMS signature */ +#define ENCTYPE_RC2_CBC_ENV 0x000c /**< RC2 cbc mode, CMS enveloped data */ +#define ENCTYPE_RSA_ENV 0x000d /**< RSA encryption, CMS enveloped data */ +#define ENCTYPE_RSA_ES_OAEP_ENV 0x000e /**< RSA w/OEAP encryption, CMS enveloped data */ +#define ENCTYPE_DES3_CBC_ENV 0x000f /**< DES-3 cbc mode, CMS enveloped data */ + +#define ENCTYPE_DES3_CBC_SHA1 0x0010 +#define ENCTYPE_AES128_CTS_HMAC_SHA1_96 0x0011 /**< RFC 3962 */ +#define ENCTYPE_AES256_CTS_HMAC_SHA1_96 0x0012 /**< RFC 3962 */ +#define ENCTYPE_AES128_CTS_HMAC_SHA256_128 0x0013 /**< RFC 8009 */ +#define ENCTYPE_AES256_CTS_HMAC_SHA384_192 0x0014 /**< RFC 8009 */ +#define ENCTYPE_ARCFOUR_HMAC 0x0017 /**< RFC 4757 */ +#define ENCTYPE_ARCFOUR_HMAC_EXP 0x0018 /**< RFC 4757 */ +#define ENCTYPE_CAMELLIA128_CTS_CMAC 0x0019 /**< RFC 6803 */ +#define ENCTYPE_CAMELLIA256_CTS_CMAC 0x001a /**< RFC 6803 */ +#define ENCTYPE_UNKNOWN 0x01ff + +/* + * Historically we used the value 9 for unkeyed SHA-1. RFC 3961 assigns this + * value to rsa-md5-des3, which fortunately is unused. For ABI compatibility + * we allow either 9 or 14 for SHA-1. + */ +#define CKSUMTYPE_CRC32 0x0001 +#define CKSUMTYPE_RSA_MD4 0x0002 +#define CKSUMTYPE_RSA_MD4_DES 0x0003 +#define CKSUMTYPE_DESCBC 0x0004 +/* des-mac-k */ +/* rsa-md4-des-k */ +#define CKSUMTYPE_RSA_MD5 0x0007 +#define CKSUMTYPE_RSA_MD5_DES 0x0008 +#define CKSUMTYPE_NIST_SHA 0x0009 +#define CKSUMTYPE_HMAC_SHA1_DES3 0x000c +#define CKSUMTYPE_SHA1 0x000e /**< RFC 3961 */ +#define CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f /**< RFC 3962. Used with + ENCTYPE_AES128_CTS_HMAC_SHA1_96 */ +#define CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 /**< RFC 3962. Used with + ENCTYPE_AES256_CTS_HMAC_SHA1_96 */ +#define CKSUMTYPE_HMAC_SHA256_128_AES128 0x0013 /**< RFC 8009 */ +#define CKSUMTYPE_HMAC_SHA384_192_AES256 0x0014 /**< RFC 8009 */ +#define CKSUMTYPE_CMAC_CAMELLIA128 0x0011 /**< RFC 6803 */ +#define CKSUMTYPE_CMAC_CAMELLIA256 0x0012 /**< RFC 6803 */ +#define CKSUMTYPE_MD5_HMAC_ARCFOUR -137 /* Microsoft netlogon */ +#define CKSUMTYPE_HMAC_MD5_ARCFOUR -138 /**< RFC 4757 */ + +/* Constants for the deprecated krb5_c_random_add_entropy() */ +enum { + KRB5_C_RANDSOURCE_OLDAPI = 0, + KRB5_C_RANDSOURCE_OSRAND = 1, + KRB5_C_RANDSOURCE_TRUSTEDPARTY = 2, + KRB5_C_RANDSOURCE_TIMING = 3, + KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL = 4, + KRB5_C_RANDSOURCE_MAX = 5 +}; + +#ifndef krb5_roundup +/* round x up to nearest multiple of y */ +#define krb5_roundup(x, y) ((((x) + (y) - 1)/(y))*(y)) +#endif /* roundup */ + +/* macro function definitions to help clean up code */ + +#if 1 +#define krb5_x(ptr,args) ((ptr)?((*(ptr)) args):(abort(),1)) +#define krb5_xc(ptr,args) ((ptr)?((*(ptr)) args):(abort(),(char*)0)) +#else +#define krb5_x(ptr,args) ((*(ptr)) args) +#define krb5_xc(ptr,args) ((*(ptr)) args) +#endif + +/** + * Encrypt data using a key (operates on keyblock). + * + * @param [in] context Library context + * @param [in] key Encryption key + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in,out] cipher_state Cipher state; specify NULL if not needed + * @param [in] input Data to be encrypted + * @param [out] output Encrypted data + * + * This function encrypts the data block @a input and stores the output into @a + * output. The actual encryption key will be derived from @a key and @a usage + * if key derivation is specified for the encryption type. If non-null, @a + * cipher_state specifies the beginning state for the encryption operation, and + * is updated with the state to be passed as input to the next operation. + * + * @note The caller must initialize @a output and allocate at least enough + * space for the result (using krb5_c_encrypt_length() to determine the amount + * of space needed). @a output->length will be set to the actual length of the + * ciphertext. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_encrypt(krb5_context context, const krb5_keyblock *key, + krb5_keyusage usage, const krb5_data *cipher_state, + const krb5_data *input, krb5_enc_data *output); + +/** + * Decrypt data using a key (operates on keyblock). + * + * @param [in] context Library context + * @param [in] key Encryption key + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in,out] cipher_state Cipher state; specify NULL if not needed + * @param [in] input Encrypted data + * @param [out] output Decrypted data + * + * This function decrypts the data block @a input and stores the output into @a + * output. The actual decryption key will be derived from @a key and @a usage + * if key derivation is specified for the encryption type. If non-null, @a + * cipher_state specifies the beginning state for the decryption operation, and + * is updated with the state to be passed as input to the next operation. + * + * @note The caller must initialize @a output and allocate at least enough + * space for the result. The usual practice is to allocate an output buffer as + * long as the ciphertext, and let krb5_c_decrypt() trim @a output->length. + * For some enctypes, the resulting @a output->length may include padding + * bytes. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_decrypt(krb5_context context, const krb5_keyblock *key, + krb5_keyusage usage, const krb5_data *cipher_state, + const krb5_enc_data *input, krb5_data *output); + +/** + * Compute encrypted data length. + * + * @param [in] context Library context + * @param [in] enctype Encryption type + * @param [in] inputlen Length of the data to be encrypted + * @param [out] length Length of the encrypted data + * + * This function computes the length of the ciphertext produced by encrypting + * @a inputlen bytes including padding, confounder, and checksum. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_encrypt_length(krb5_context context, krb5_enctype enctype, + size_t inputlen, size_t *length); + +/** + * Return cipher block size. + * + * @param [in] context Library context + * @param [in] enctype Encryption type + * @param [out] blocksize Block size for @a enctype + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_block_size(krb5_context context, krb5_enctype enctype, + size_t *blocksize); + +/** + * Return length of the specified key in bytes. + * + * @param [in] context Library context + * @param [in] enctype Encryption type + * @param [out] keybytes Number of bytes required to make a key + * @param [out] keylength Length of final key + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_keylengths(krb5_context context, krb5_enctype enctype, + size_t *keybytes, size_t *keylength); + +/** + * Initialize a new cipher state. + * + * @param [in] context Library context + * @param [in] key Key + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [out] new_state New cipher state + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_init_state(krb5_context context, const krb5_keyblock *key, + krb5_keyusage usage, krb5_data *new_state); + +/** + * Free a cipher state previously allocated by krb5_c_init_state(). + * + * @param [in] context Library context + * @param [in] key Key + * @param [in] state Cipher state to be freed + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_free_state(krb5_context context, const krb5_keyblock *key, + krb5_data *state); + +/** + * Generate enctype-specific pseudo-random bytes. + * + * @param [in] context Library context + * @param [in] keyblock Key + * @param [in] input Input data + * @param [out] output Output data + * + * This function selects a pseudo-random function based on @a keyblock and + * computes its value over @a input, placing the result into @a output. + * The caller must preinitialize @a output and allocate space for the + * result, using krb5_c_prf_length() to determine the required length. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_prf(krb5_context context, const krb5_keyblock *keyblock, + krb5_data *input, krb5_data *output); + +/** + * Get the output length of pseudo-random functions for an encryption type. + * + * @param [in] context Library context + * @param [in] enctype Encryption type + * @param [out] len Length of PRF output + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_prf_length(krb5_context context, krb5_enctype enctype, size_t *len); + +/** + * Generate pseudo-random bytes using RFC 6113 PRF+. + * + * @param [in] context Library context + * @param [in] k KDC contribution key + * @param [in] input Input data + * @param [out] output Pseudo-random output buffer + * + * This function fills @a output with PRF+(k, input) as defined in RFC 6113 + * section 5.1. The caller must preinitialize @a output and allocate the + * desired amount of space. The length of the pseudo-random output will match + * the length of @a output. + * + * @note RFC 4402 defines a different PRF+ operation. This function does not + * implement that operation. + * + * @return 0 on success, @c E2BIG if output->length is too large for PRF+ to + * generate, @c ENOMEM on allocation failure, or an error code from + * krb5_c_prf() + */ +krb5_error_code KRB5_CALLCONV +krb5_c_prfplus(krb5_context context, const krb5_keyblock *k, + const krb5_data *input, krb5_data *output); + +/** + * Derive a key using some input data (via RFC 6113 PRF+). + * + * @param [in] context Library context + * @param [in] k KDC contribution key + * @param [in] input Input string + * @param [in] enctype Output key enctype (or @c ENCTYPE_NULL) + * @param [out] out Derived keyblock + * + * This function uses PRF+ as defined in RFC 6113 to derive a key from another + * key and an input string. If @a enctype is @c ENCTYPE_NULL, the output key + * will have the same enctype as the input key. + */ +krb5_error_code KRB5_CALLCONV +krb5_c_derive_prfplus(krb5_context context, const krb5_keyblock *k, + const krb5_data *input, krb5_enctype enctype, + krb5_keyblock **out); + +/** + * Compute the KRB-FX-CF2 combination of two keys and pepper strings. + * + * @param [in] context Library context + * @param [in] k1 KDC contribution key + * @param [in] pepper1 String "PKINIT" + * @param [in] k2 Reply key + * @param [in] pepper2 String "KeyExchange" + * @param [out] out Output key + * + * This function computes the KRB-FX-CF2 function over its inputs and places + * the results in a newly allocated keyblock. This function is simple in that + * it assumes that @a pepper1 and @a pepper2 are C strings with no internal + * nulls and that the enctype of the result will be the same as that of @a k1. + * @a k1 and @a k2 may be of different enctypes. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_fx_cf2_simple(krb5_context context, + const krb5_keyblock *k1, const char *pepper1, + const krb5_keyblock *k2, const char *pepper2, + krb5_keyblock **out); + +/** + * Generate an enctype-specific random encryption key. + * + * @param [in] context Library context + * @param [in] enctype Encryption type of the generated key + * @param [out] k5_random_key An allocated and initialized keyblock + * + * Use krb5_free_keyblock_contents() to free @a k5_random_key when + * no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_make_random_key(krb5_context context, krb5_enctype enctype, + krb5_keyblock *k5_random_key); + +/** + * Generate an enctype-specific key from random data. + * + * @param [in] context Library context + * @param [in] enctype Encryption type + * @param [in] random_data Random input data + * @param [out] k5_random_key Resulting key + * + * This function takes random input data @a random_data and produces a valid + * key @a k5_random_key for a given @a enctype. + * + * @note It is assumed that @a k5_random_key has already been initialized and + * @a k5_random_key->contents has been allocated with the correct length. + * + * @sa krb5_c_keylengths() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_random_to_key(krb5_context context, krb5_enctype enctype, + krb5_data *random_data, krb5_keyblock *k5_random_key); + +/** @deprecated This call is no longer necessary. */ +krb5_error_code KRB5_CALLCONV +krb5_c_random_add_entropy(krb5_context context, unsigned int randsource, + const krb5_data *data); + +/** + * Generate pseudo-random bytes. + * + * @param [in] context Library context + * @param [out] data Random data + * + * Fills in @a data with bytes from the PRNG used by krb5 crypto operations. + * The caller must preinitialize @a data and allocate the desired amount of + * space. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_random_make_octets(krb5_context context, krb5_data *data); + +/** @deprecated This call is no longer necessary. */ +krb5_error_code KRB5_CALLCONV +krb5_c_random_os_entropy(krb5_context context, int strong, int *success); + +/** @deprecated This call is no longer necessary. */ +krb5_error_code KRB5_CALLCONV +krb5_c_random_seed(krb5_context context, krb5_data *data); + +/** + * Convert a string (such a password) to a key. + * + * @param [in] context Library context + * @param [in] enctype Encryption type + * @param [in] string String to be converted + * @param [in] salt Salt value + * @param [out] key Generated key + * + * This function converts @a string to a @a key of encryption type @a enctype, + * using the specified @a salt. The newly created @a key must be released by + * calling krb5_free_keyblock_contents() when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_string_to_key(krb5_context context, krb5_enctype enctype, + const krb5_data *string, const krb5_data *salt, + krb5_keyblock *key); + +/** + * Convert a string (such as a password) to a key with additional parameters. + * + * @param [in] context Library context + * @param [in] enctype Encryption type + * @param [in] string String to be converted + * @param [in] salt Salt value + * @param [in] params Parameters + * @param [out] key Generated key + * + * This function is similar to krb5_c_string_to_key(), but also takes + * parameters which may affect the algorithm in an enctype-dependent way. The + * newly created @a key must be released by calling + * krb5_free_keyblock_contents() when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_string_to_key_with_params(krb5_context context, + krb5_enctype enctype, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key); + +/** + * Compare two encryption types. + * + * @param [in] context Library context + * @param [in] e1 First encryption type + * @param [in] e2 Second encryption type + * @param [out] similar @c TRUE if types are similar, @c FALSE if not + * + * This function determines whether two encryption types use the same kind of + * keys. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_enctype_compare(krb5_context context, krb5_enctype e1, krb5_enctype e2, + krb5_boolean *similar); + +/** + * Compute a checksum (operates on keyblock). + * + * @param [in] context Library context + * @param [in] cksumtype Checksum type (0 for mandatory type) + * @param [in] key Encryption key for a keyed checksum + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in] input Input data + * @param [out] cksum Generated checksum + * + * This function computes a checksum of type @a cksumtype over @a input, using + * @a key if the checksum type is a keyed checksum. If @a cksumtype is 0 and + * @a key is non-null, the checksum type will be the mandatory-to-implement + * checksum type for the key's encryption type. The actual checksum key will + * be derived from @a key and @a usage if key derivation is specified for the + * checksum type. The newly created @a cksum must be released by calling + * krb5_free_checksum_contents() when it is no longer needed. + * + * @note This function is similar to krb5_k_make_checksum(), but operates + * on keyblock @a key. + * + * @sa krb5_c_verify_checksum() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype, + const krb5_keyblock *key, krb5_keyusage usage, + const krb5_data *input, krb5_checksum *cksum); + +/** + * Verify a checksum (operates on keyblock). + * + * @param [in] context Library context + * @param [in] key Encryption key for a keyed checksum + * @param [in] usage @a key usage + * @param [in] data Data to be used to compute a new checksum + * using @a key to compare @a cksum against + * @param [in] cksum Checksum to be verified + * @param [out] valid Non-zero for success, zero for failure + * + * This function verifies that @a cksum is a valid checksum for @a data. If + * the checksum type of @a cksum is a keyed checksum, @a key is used to verify + * the checksum. If the checksum type in @a cksum is 0 and @a key is not NULL, + * the mandatory checksum type for @a key will be used. The actual checksum + * key will be derived from @a key and @a usage if key derivation is specified + * for the checksum type. + * + * @note This function is similar to krb5_k_verify_checksum(), but operates + * on keyblock @a key. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *key, + krb5_keyusage usage, const krb5_data *data, + const krb5_checksum *cksum, krb5_boolean *valid); + +/** + * Return the length of checksums for a checksum type. + * + * @param [in] context Library context + * @param [in] cksumtype Checksum type + * @param [out] length Checksum length + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_checksum_length(krb5_context context, krb5_cksumtype cksumtype, + size_t *length); + +/** + * Return a list of keyed checksum types usable with an encryption type. + * + * @param [in] context Library context + * @param [in] enctype Encryption type + * @param [out] count Count of allowable checksum types + * @param [out] cksumtypes Array of allowable checksum types + * + * Use krb5_free_cksumtypes() to free @a cksumtypes when it is no longer + * needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_keyed_checksum_types(krb5_context context, krb5_enctype enctype, + unsigned int *count, krb5_cksumtype **cksumtypes); + +#define KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS 1 +#define KRB5_KEYUSAGE_KDC_REP_TICKET 2 +#define KRB5_KEYUSAGE_AS_REP_ENCPART 3 +#define KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY 4 +#define KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY 5 +#define KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM 6 +#define KRB5_KEYUSAGE_TGS_REQ_AUTH 7 +#define KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY 8 +#define KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY 9 +#define KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM 10 +#define KRB5_KEYUSAGE_AP_REQ_AUTH 11 +#define KRB5_KEYUSAGE_AP_REP_ENCPART 12 +#define KRB5_KEYUSAGE_KRB_PRIV_ENCPART 13 +#define KRB5_KEYUSAGE_KRB_CRED_ENCPART 14 +#define KRB5_KEYUSAGE_KRB_SAFE_CKSUM 15 +#define KRB5_KEYUSAGE_APP_DATA_ENCRYPT 16 +#define KRB5_KEYUSAGE_APP_DATA_CKSUM 17 +#define KRB5_KEYUSAGE_KRB_ERROR_CKSUM 18 +#define KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM 19 +#define KRB5_KEYUSAGE_AD_MTE 20 +#define KRB5_KEYUSAGE_AD_ITE 21 + +/* XXX need to register these */ + +#define KRB5_KEYUSAGE_GSS_TOK_MIC 22 +#define KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG 23 +#define KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV 24 + +/* Defined in Integrating SAM Mechanisms with Kerberos draft */ +#define KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM 25 +/* Note conflict with KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST */ +#define KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID 26 +/* Note conflict with KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY */ +#define KRB5_KEYUSAGE_PA_SAM_RESPONSE 27 + +/* Defined in [MS-SFU] */ +/* Note conflict with KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID */ +#define KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST 26 +/* Note conflict with KRB5_KEYUSAGE_PA_SAM_RESPONSE */ +#define KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY 27 + +/* unused */ +#define KRB5_KEYUSAGE_PA_REFERRAL 26 + +#define KRB5_KEYUSAGE_AD_SIGNEDPATH -21 +#define KRB5_KEYUSAGE_IAKERB_FINISHED 42 +#define KRB5_KEYUSAGE_PA_PKINIT_KX 44 +#define KRB5_KEYUSAGE_PA_OTP_REQUEST 45 /**< See RFC 6560 section 4.2 */ +/* define in draft-ietf-krb-wg-preauth-framework*/ +#define KRB5_KEYUSAGE_FAST_REQ_CHKSUM 50 +#define KRB5_KEYUSAGE_FAST_ENC 51 +#define KRB5_KEYUSAGE_FAST_REP 52 +#define KRB5_KEYUSAGE_FAST_FINISHED 53 +#define KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT 54 +#define KRB5_KEYUSAGE_ENC_CHALLENGE_KDC 55 +#define KRB5_KEYUSAGE_AS_REQ 56 +#define KRB5_KEYUSAGE_CAMMAC 64 +#define KRB5_KEYUSAGE_SPAKE 65 + +/* Key usage values 512-1023 are reserved for uses internal to a Kerberos + * implementation. */ +#define KRB5_KEYUSAGE_PA_FX_COOKIE 513 /**< Used for encrypted FAST cookies */ +#define KRB5_KEYUSAGE_PA_AS_FRESHNESS 514 /**< Used for freshness tokens */ + +/** + * Verify that a specified encryption type is a valid Kerberos encryption type. + * + * @param [in] ktype Encryption type + * + * @return @c TRUE if @a ktype is valid, @c FALSE if not + */ +krb5_boolean KRB5_CALLCONV +krb5_c_valid_enctype(krb5_enctype ktype); + +/** + * Verify that specified checksum type is a valid Kerberos checksum type. + * + * @param [in] ctype Checksum type + * + * @return @c TRUE if @a ctype is valid, @c FALSE if not + */ +krb5_boolean KRB5_CALLCONV +krb5_c_valid_cksumtype(krb5_cksumtype ctype); + +/** + * Test whether a checksum type is collision-proof. + * + * @param [in] ctype Checksum type + * + * @return @c TRUE if @a ctype is collision-proof, @c FALSE if it is not + * collision-proof or not a valid checksum type. + */ +krb5_boolean KRB5_CALLCONV +krb5_c_is_coll_proof_cksum(krb5_cksumtype ctype); + +/** + * Test whether a checksum type is keyed. + * + * @param [in] ctype Checksum type + * + * @return @c TRUE if @a ctype is a keyed checksum type, @c FALSE otherwise. + */ +krb5_boolean KRB5_CALLCONV +krb5_c_is_keyed_cksum(krb5_cksumtype ctype); + +/* AEAD APIs */ +#define KRB5_CRYPTO_TYPE_EMPTY 0 /**< [in] ignored */ +#define KRB5_CRYPTO_TYPE_HEADER 1 /**< [out] header */ +#define KRB5_CRYPTO_TYPE_DATA 2 /**< [in, out] plaintext */ +#define KRB5_CRYPTO_TYPE_SIGN_ONLY 3 /**< [in] associated data */ +#define KRB5_CRYPTO_TYPE_PADDING 4 /**< [out] padding */ +#define KRB5_CRYPTO_TYPE_TRAILER 5 /**< [out] checksum for encrypt */ +#define KRB5_CRYPTO_TYPE_CHECKSUM 6 /**< [out] checksum for MIC */ +#define KRB5_CRYPTO_TYPE_STREAM 7 /**< [in] entire message without + decomposing the structure into + header, data and trailer buffers */ + +/** + * Fill in a checksum element in IOV array (operates on keyblock) + * + * @param [in] context Library context + * @param [in] cksumtype Checksum type (0 for mandatory type) + * @param [in] key Encryption key for a keyed checksum + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in,out] data IOV array + * @param [in] num_data Size of @a data + * + * Create a checksum in the #KRB5_CRYPTO_TYPE_CHECKSUM element over + * #KRB5_CRYPTO_TYPE_DATA and #KRB5_CRYPTO_TYPE_SIGN_ONLY chunks in @a data. + * Only the #KRB5_CRYPTO_TYPE_CHECKSUM region is modified. + * + * @note This function is similar to krb5_k_make_checksum_iov(), but operates + * on keyblock @a key. + * + * @sa krb5_c_verify_checksum_iov() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_make_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, + const krb5_keyblock *key, krb5_keyusage usage, + krb5_crypto_iov *data, size_t num_data); + +/** + * Validate a checksum element in IOV array (operates on keyblock). + * + * @param [in] context Library context + * @param [in] cksumtype Checksum type (0 for mandatory type) + * @param [in] key Encryption key for a keyed checksum + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in] data IOV array + * @param [in] num_data Size of @a data + * @param [out] valid Non-zero for success, zero for failure + * + * Confirm that the checksum in the #KRB5_CRYPTO_TYPE_CHECKSUM element is a + * valid checksum of the #KRB5_CRYPTO_TYPE_DATA and #KRB5_CRYPTO_TYPE_SIGN_ONLY + * regions in the iov. + * + * @note This function is similar to krb5_k_verify_checksum_iov(), but operates + * on keyblock @a key. + * + * @sa krb5_c_make_checksum_iov() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_verify_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, + const krb5_keyblock *key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_boolean *valid); + +/** + * Encrypt data in place supporting AEAD (operates on keyblock). + * + * @param [in] context Library context + * @param [in] keyblock Encryption key + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in] cipher_state Cipher state; specify NULL if not needed + * @param [in,out] data IOV array. Modified in-place. + * @param [in] num_data Size of @a data + * + * This function encrypts the data block @a data and stores the output in-place. + * The actual encryption key will be derived from @a keyblock and @a usage + * if key derivation is specified for the encryption type. If non-null, @a + * cipher_state specifies the beginning state for the encryption operation, and + * is updated with the state to be passed as input to the next operation. + * The caller must allocate the right number of krb5_crypto_iov + * structures before calling into this API. + * + * @note On return from a krb5_c_encrypt_iov() call, the @a data->length in the + * iov structure are adjusted to reflect actual lengths of the ciphertext used. + * For example, if the padding length is too large, the length will be reduced. + * Lengths are never increased. + * + * @note This function is similar to krb5_k_encrypt_iov(), but operates + * on keyblock @a keyblock. + * + * @sa krb5_c_decrypt_iov() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_encrypt_iov(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *cipher_state, + krb5_crypto_iov *data, size_t num_data); + +/** + * Decrypt data in place supporting AEAD (operates on keyblock). + * + * @param [in] context Library context + * @param [in] keyblock Encryption key + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in] cipher_state Cipher state; specify NULL if not needed + * @param [in,out] data IOV array. Modified in-place. + * @param [in] num_data Size of @a data + * + * This function decrypts the data block @a data and stores the output in-place. + * The actual decryption key will be derived from @a keyblock and @a usage + * if key derivation is specified for the encryption type. If non-null, @a + * cipher_state specifies the beginning state for the decryption operation, and + * is updated with the state to be passed as input to the next operation. + * The caller must allocate the right number of krb5_crypto_iov + * structures before calling into this API. + * + * @note On return from a krb5_c_decrypt_iov() call, the @a data->length in the + * iov structure are adjusted to reflect actual lengths of the ciphertext used. + * For example, if the padding length is too large, the length will be reduced. + * Lengths are never increased. + * + * @note This function is similar to krb5_k_decrypt_iov(), but operates + * on keyblock @a keyblock. + * + * @sa krb5_c_decrypt_iov() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_decrypt_iov(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *cipher_state, + krb5_crypto_iov *data, size_t num_data); + +/** + * Return a length of a message field specific to the encryption type. + * + * @param [in] context Library context + * @param [in] enctype Encryption type + * @param [in] type Type field (See KRB5_CRYPTO_TYPE macros) + * @param [out] size Length of the @a type specific to @a enctype + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_crypto_length(krb5_context context, krb5_enctype enctype, + krb5_cryptotype type, unsigned int *size); + +/** + * Fill in lengths for header, trailer and padding in a IOV array. + * + * @param [in] context Library context + * @param [in] enctype Encryption type + * @param [in,out] data IOV array + * @param [in] num_data Size of @a data + * + * Padding is set to the actual padding required based on the provided + * @a data buffers. Typically this API is used after setting up the data + * buffers and #KRB5_CRYPTO_TYPE_SIGN_ONLY buffers, but before actually + * allocating header, trailer and padding. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_crypto_length_iov(krb5_context context, krb5_enctype enctype, + krb5_crypto_iov *data, size_t num_data); + +/** + * Return a number of padding octets. + * + * @param [in] context Library context + * @param [in] enctype Encryption type + * @param [in] data_length Length of the plaintext to pad + * @param [out] size Number of padding octets + * + * This function returns the number of the padding octets required to pad + * @a data_length octets of plaintext. + * + * @retval 0 Success; otherwise - KRB5_BAD_ENCTYPE + */ +krb5_error_code KRB5_CALLCONV +krb5_c_padding_length(krb5_context context, krb5_enctype enctype, + size_t data_length, unsigned int *size); + +/** + * Create a krb5_key from the enctype and key data in a keyblock. + * + * @param [in] context Library context + * @param [in] key_data Keyblock + * @param [out] out Opaque key + * + * The reference count on a key @a out is set to 1. + * Use krb5_k_free_key() to free @a out when it is no longer needed. + * + * @retval 0 Success; otherwise - KRB5_BAD_ENCTYPE + */ +krb5_error_code KRB5_CALLCONV +krb5_k_create_key(krb5_context context, const krb5_keyblock *key_data, + krb5_key *out); + +/** Increment the reference count on a key. */ +void KRB5_CALLCONV +krb5_k_reference_key(krb5_context context, krb5_key key); + +/** Decrement the reference count on a key and free it if it hits zero. */ +void KRB5_CALLCONV +krb5_k_free_key(krb5_context context, krb5_key key); + +/** Retrieve a copy of the keyblock from a krb5_key structure. */ +krb5_error_code KRB5_CALLCONV +krb5_k_key_keyblock(krb5_context context, krb5_key key, + krb5_keyblock **key_data); + +/** Retrieve the enctype of a krb5_key structure. */ +krb5_enctype KRB5_CALLCONV +krb5_k_key_enctype(krb5_context context, krb5_key key); + +/** + * Encrypt data using a key (operates on opaque key). + * + * @param [in] context Library context + * @param [in] key Encryption key + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in,out] cipher_state Cipher state; specify NULL if not needed + * @param [in] input Data to be encrypted + * @param [out] output Encrypted data + * + * This function encrypts the data block @a input and stores the output into @a + * output. The actual encryption key will be derived from @a key and @a usage + * if key derivation is specified for the encryption type. If non-null, @a + * cipher_state specifies the beginning state for the encryption operation, and + * is updated with the state to be passed as input to the next operation. + * + * @note The caller must initialize @a output and allocate at least enough + * space for the result (using krb5_c_encrypt_length() to determine the amount + * of space needed). @a output->length will be set to the actual length of the + * ciphertext. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_k_encrypt(krb5_context context, krb5_key key, krb5_keyusage usage, + const krb5_data *cipher_state, const krb5_data *input, + krb5_enc_data *output); + +/** + * Encrypt data in place supporting AEAD (operates on opaque key). + * + * @param [in] context Library context + * @param [in] key Encryption key + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in] cipher_state Cipher state; specify NULL if not needed + * @param [in,out] data IOV array. Modified in-place. + * @param [in] num_data Size of @a data + * + * This function encrypts the data block @a data and stores the output in-place. + * The actual encryption key will be derived from @a key and @a usage + * if key derivation is specified for the encryption type. If non-null, @a + * cipher_state specifies the beginning state for the encryption operation, and + * is updated with the state to be passed as input to the next operation. + * The caller must allocate the right number of krb5_crypto_iov + * structures before calling into this API. + * + * @note On return from a krb5_c_encrypt_iov() call, the @a data->length in the + * iov structure are adjusted to reflect actual lengths of the ciphertext used. + * For example, if the padding length is too large, the length will be reduced. + * Lengths are never increased. + * + * @note This function is similar to krb5_c_encrypt_iov(), but operates + * on opaque key @a key. + * + * @sa krb5_k_decrypt_iov() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_k_encrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage, + const krb5_data *cipher_state, krb5_crypto_iov *data, + size_t num_data); + +/** + * Decrypt data using a key (operates on opaque key). + * + * @param [in] context Library context + * @param [in] key Encryption key + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in,out] cipher_state Cipher state; specify NULL if not needed + * @param [in] input Encrypted data + * @param [out] output Decrypted data + * + * This function decrypts the data block @a input and stores the output into @a + * output. The actual decryption key will be derived from @a key and @a usage + * if key derivation is specified for the encryption type. If non-null, @a + * cipher_state specifies the beginning state for the decryption operation, and + * is updated with the state to be passed as input to the next operation. + * + * @note The caller must initialize @a output and allocate at least enough + * space for the result. The usual practice is to allocate an output buffer as + * long as the ciphertext, and let krb5_c_decrypt() trim @a output->length. + * For some enctypes, the resulting @a output->length may include padding + * bytes. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_k_decrypt(krb5_context context, krb5_key key, krb5_keyusage usage, + const krb5_data *cipher_state, const krb5_enc_data *input, + krb5_data *output); + +/** + * Decrypt data in place supporting AEAD (operates on opaque key). + * + * @param [in] context Library context + * @param [in] key Encryption key + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in] cipher_state Cipher state; specify NULL if not needed + * @param [in,out] data IOV array. Modified in-place. + * @param [in] num_data Size of @a data + * + * This function decrypts the data block @a data and stores the output in-place. + * The actual decryption key will be derived from @a key and @a usage + * if key derivation is specified for the encryption type. If non-null, @a + * cipher_state specifies the beginning state for the decryption operation, and + * is updated with the state to be passed as input to the next operation. + * The caller must allocate the right number of krb5_crypto_iov + * structures before calling into this API. + * + * @note On return from a krb5_c_decrypt_iov() call, the @a data->length in the + * iov structure are adjusted to reflect actual lengths of the ciphertext used. + * For example, if the padding length is too large, the length will be reduced. + * Lengths are never increased. + * + * @note This function is similar to krb5_c_decrypt_iov(), but operates + * on opaque key @a key. + * + * @sa krb5_k_encrypt_iov() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_k_decrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage, + const krb5_data *cipher_state, krb5_crypto_iov *data, + size_t num_data); +/** + * Compute a checksum (operates on opaque key). + * + * @param [in] context Library context + * @param [in] cksumtype Checksum type (0 for mandatory type) + * @param [in] key Encryption key for a keyed checksum + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in] input Input data + * @param [out] cksum Generated checksum + * + * This function computes a checksum of type @a cksumtype over @a input, using + * @a key if the checksum type is a keyed checksum. If @a cksumtype is 0 and + * @a key is non-null, the checksum type will be the mandatory-to-implement + * checksum type for the key's encryption type. The actual checksum key will + * be derived from @a key and @a usage if key derivation is specified for the + * checksum type. The newly created @a cksum must be released by calling + * krb5_free_checksum_contents() when it is no longer needed. + * + * @note This function is similar to krb5_c_make_checksum(), but operates + * on opaque @a key. + * + * @sa krb5_c_verify_checksum() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_k_make_checksum(krb5_context context, krb5_cksumtype cksumtype, + krb5_key key, krb5_keyusage usage, const krb5_data *input, + krb5_checksum *cksum); + +/** + * Fill in a checksum element in IOV array (operates on opaque key) + * + * @param [in] context Library context + * @param [in] cksumtype Checksum type (0 for mandatory type) + * @param [in] key Encryption key for a keyed checksum + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in,out] data IOV array + * @param [in] num_data Size of @a data + * + * Create a checksum in the #KRB5_CRYPTO_TYPE_CHECKSUM element over + * #KRB5_CRYPTO_TYPE_DATA and #KRB5_CRYPTO_TYPE_SIGN_ONLY chunks in @a data. + * Only the #KRB5_CRYPTO_TYPE_CHECKSUM region is modified. + * + * @note This function is similar to krb5_c_make_checksum_iov(), but operates + * on opaque @a key. + * + * @sa krb5_k_verify_checksum_iov() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_k_make_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, + krb5_key key, krb5_keyusage usage, + krb5_crypto_iov *data, size_t num_data); + +/** + * Verify a checksum (operates on opaque key). + * + * @param [in] context Library context + * @param [in] key Encryption key for a keyed checksum + * @param [in] usage @a key usage + * @param [in] data Data to be used to compute a new checksum + * using @a key to compare @a cksum against + * @param [in] cksum Checksum to be verified + * @param [out] valid Non-zero for success, zero for failure + * + * This function verifies that @a cksum is a valid checksum for @a data. If + * the checksum type of @a cksum is a keyed checksum, @a key is used to verify + * the checksum. If the checksum type in @a cksum is 0 and @a key is not NULL, + * the mandatory checksum type for @a key will be used. The actual checksum + * key will be derived from @a key and @a usage if key derivation is specified + * for the checksum type. + * + * @note This function is similar to krb5_c_verify_checksum(), but operates + * on opaque @a key. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_k_verify_checksum(krb5_context context, krb5_key key, krb5_keyusage usage, + const krb5_data *data, const krb5_checksum *cksum, + krb5_boolean *valid); + +/** + * Validate a checksum element in IOV array (operates on opaque key). + * + * @param [in] context Library context + * @param [in] cksumtype Checksum type (0 for mandatory type) + * @param [in] key Encryption key for a keyed checksum + * @param [in] usage Key usage (see KRB5_KEYUSAGE macros) + * @param [in] data IOV array + * @param [in] num_data Size of @a data + * @param [out] valid Non-zero for success, zero for failure + * + * Confirm that the checksum in the #KRB5_CRYPTO_TYPE_CHECKSUM element is a + * valid checksum of the #KRB5_CRYPTO_TYPE_DATA and #KRB5_CRYPTO_TYPE_SIGN_ONLY + * regions in the iov. + * + * @note This function is similar to krb5_c_verify_checksum_iov(), but operates + * on opaque @a key. + * + * @sa krb5_k_make_checksum_iov() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_k_verify_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_boolean *valid); + +/** + * Generate enctype-specific pseudo-random bytes (operates on opaque key). + * + * @param [in] context Library context + * @param [in] key Key + * @param [in] input Input data + * @param [out] output Output data + * + * This function selects a pseudo-random function based on @a key and + * computes its value over @a input, placing the result into @a output. + * The caller must preinitialize @a output and allocate space for the + * result. + * + * @note This function is similar to krb5_c_prf(), but operates + * on opaque @a key. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_k_prf(krb5_context context, krb5_key key, krb5_data *input, krb5_data *output); + +#ifdef KRB5_OLD_CRYPTO +/* + * old cryptosystem routine prototypes. These are now layered + * on top of the functions above. + */ +/** @deprecated Replaced by krb5_c_* API family.*/ +krb5_error_code KRB5_CALLCONV +krb5_encrypt(krb5_context context, krb5_const_pointer inptr, + krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock, + krb5_pointer ivec); + +/** @deprecated Replaced by krb5_c_* API family. */ +krb5_error_code KRB5_CALLCONV +krb5_decrypt(krb5_context context, krb5_const_pointer inptr, + krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock, + krb5_pointer ivec); + +/** @deprecated Replaced by krb5_c_* API family. */ +krb5_error_code KRB5_CALLCONV +krb5_process_key(krb5_context context, krb5_encrypt_block *eblock, + const krb5_keyblock * key); + +/** @deprecated Replaced by krb5_c_* API family. */ +krb5_error_code KRB5_CALLCONV +krb5_finish_key(krb5_context context, krb5_encrypt_block * eblock); + +/** @deprecated See krb5_c_string_to_key() */ +krb5_error_code KRB5_CALLCONV +krb5_string_to_key(krb5_context context, const krb5_encrypt_block *eblock, + krb5_keyblock * keyblock, const krb5_data *data, + const krb5_data *salt); + +/** @deprecated Replaced by krb5_c_* API family. */ +krb5_error_code KRB5_CALLCONV +krb5_init_random_key(krb5_context context, const krb5_encrypt_block *eblock, + const krb5_keyblock *keyblock, krb5_pointer *ptr); + +/** @deprecated Replaced by krb5_c_* API family. */ +krb5_error_code KRB5_CALLCONV +krb5_finish_random_key(krb5_context context, const krb5_encrypt_block *eblock, + krb5_pointer *ptr); + +/** @deprecated Replaced by krb5_c_* API family. */ +krb5_error_code KRB5_CALLCONV +krb5_random_key(krb5_context context, const krb5_encrypt_block *eblock, + krb5_pointer ptr, krb5_keyblock **keyblock); + +/** @deprecated Replaced by krb5_c_* API family. */ +krb5_enctype KRB5_CALLCONV +krb5_eblock_enctype(krb5_context context, const krb5_encrypt_block *eblock); + +/** @deprecated Replaced by krb5_c_* API family. */ +krb5_error_code KRB5_CALLCONV +krb5_use_enctype(krb5_context context, krb5_encrypt_block *eblock, + krb5_enctype enctype); + +/** @deprecated Replaced by krb5_c_* API family. */ +size_t KRB5_CALLCONV +krb5_encrypt_size(size_t length, krb5_enctype crypto); + +/** @deprecated See krb5_c_checksum_length() */ +size_t KRB5_CALLCONV +krb5_checksum_size(krb5_context context, krb5_cksumtype ctype); + +/** @deprecated See krb5_c_make_checksum() */ +krb5_error_code KRB5_CALLCONV +krb5_calculate_checksum(krb5_context context, krb5_cksumtype ctype, + krb5_const_pointer in, size_t in_length, + krb5_const_pointer seed, size_t seed_length, + krb5_checksum * outcksum); + +/** @deprecated See krb5_c_verify_checksum() */ +krb5_error_code KRB5_CALLCONV +krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype, + const krb5_checksum * cksum, krb5_const_pointer in, + size_t in_length, krb5_const_pointer seed, + size_t seed_length); + +#endif /* KRB5_OLD_CRYPTO */ + +/* + * end "encryption.h" + */ + +/* + * begin "fieldbits.h" + */ + +/* kdc_options for kdc_request */ +/* options is 32 bits; each host is responsible to put the 4 bytes + representing these bits into net order before transmission */ +/* #define KDC_OPT_RESERVED 0x80000000 */ +#define KDC_OPT_FORWARDABLE 0x40000000 +#define KDC_OPT_FORWARDED 0x20000000 +#define KDC_OPT_PROXIABLE 0x10000000 +#define KDC_OPT_PROXY 0x08000000 +#define KDC_OPT_ALLOW_POSTDATE 0x04000000 +#define KDC_OPT_POSTDATED 0x02000000 +/* #define KDC_OPT_UNUSED 0x01000000 */ +#define KDC_OPT_RENEWABLE 0x00800000 +/* #define KDC_OPT_UNUSED 0x00400000 */ +/* #define KDC_OPT_RESERVED 0x00200000 */ +/* #define KDC_OPT_RESERVED 0x00100000 */ +/* #define KDC_OPT_RESERVED 0x00080000 */ +/* #define KDC_OPT_RESERVED 0x00040000 */ +#define KDC_OPT_CNAME_IN_ADDL_TKT 0x00020000 +#define KDC_OPT_CANONICALIZE 0x00010000 +#define KDC_OPT_REQUEST_ANONYMOUS 0x00008000 +/* #define KDC_OPT_RESERVED 0x00004000 */ +/* #define KDC_OPT_RESERVED 0x00002000 */ +/* #define KDC_OPT_RESERVED 0x00001000 */ +/* #define KDC_OPT_RESERVED 0x00000800 */ +/* #define KDC_OPT_RESERVED 0x00000400 */ +/* #define KDC_OPT_RESERVED 0x00000200 */ +/* #define KDC_OPT_RESERVED 0x00000100 */ +/* #define KDC_OPT_RESERVED 0x00000080 */ +/* #define KDC_OPT_RESERVED 0x00000040 */ +#define KDC_OPT_DISABLE_TRANSITED_CHECK 0x00000020 +#define KDC_OPT_RENEWABLE_OK 0x00000010 +#define KDC_OPT_ENC_TKT_IN_SKEY 0x00000008 +/* #define KDC_OPT_UNUSED 0x00000004 */ +#define KDC_OPT_RENEW 0x00000002 +#define KDC_OPT_VALIDATE 0x00000001 + +/* + * Mask of ticket flags in the TGT which should be converted into KDC + * options when using the TGT to get derivative tickets. + * + * New mask = KDC_OPT_FORWARDABLE | KDC_OPT_PROXIABLE | + * KDC_OPT_ALLOW_POSTDATE | KDC_OPT_RENEWABLE + */ +#define KDC_TKT_COMMON_MASK 0x54800000 + +/* definitions for ap_options fields */ + +/* + * ap_options are 32 bits; each host is responsible to put the 4 bytes + * representing these bits into net order before transmission + */ +#define AP_OPTS_RESERVED 0x80000000 +#define AP_OPTS_USE_SESSION_KEY 0x40000000 /**< Use session key */ +#define AP_OPTS_MUTUAL_REQUIRED 0x20000000 /**< Perform a mutual + authentication exchange */ +#define AP_OPTS_ETYPE_NEGOTIATION 0x00000002 +#define AP_OPTS_USE_SUBKEY 0x00000001 /**< Generate a subsession key + from the current session key + obtained from the + credentials */ +/* #define AP_OPTS_RESERVED 0x10000000 */ +/* #define AP_OPTS_RESERVED 0x08000000 */ +/* #define AP_OPTS_RESERVED 0x04000000 */ +/* #define AP_OPTS_RESERVED 0x02000000 */ +/* #define AP_OPTS_RESERVED 0x01000000 */ +/* #define AP_OPTS_RESERVED 0x00800000 */ +/* #define AP_OPTS_RESERVED 0x00400000 */ +/* #define AP_OPTS_RESERVED 0x00200000 */ +/* #define AP_OPTS_RESERVED 0x00100000 */ +/* #define AP_OPTS_RESERVED 0x00080000 */ +/* #define AP_OPTS_RESERVED 0x00040000 */ +/* #define AP_OPTS_RESERVED 0x00020000 */ +/* #define AP_OPTS_RESERVED 0x00010000 */ +/* #define AP_OPTS_RESERVED 0x00008000 */ +/* #define AP_OPTS_RESERVED 0x00004000 */ +/* #define AP_OPTS_RESERVED 0x00002000 */ +/* #define AP_OPTS_RESERVED 0x00001000 */ +/* #define AP_OPTS_RESERVED 0x00000800 */ +/* #define AP_OPTS_RESERVED 0x00000400 */ +/* #define AP_OPTS_RESERVED 0x00000200 */ +/* #define AP_OPTS_RESERVED 0x00000100 */ +/* #define AP_OPTS_RESERVED 0x00000080 */ +/* #define AP_OPTS_RESERVED 0x00000040 */ +/* #define AP_OPTS_RESERVED 0x00000020 */ +/* #define AP_OPTS_RESERVED 0x00000010 */ +/* #define AP_OPTS_RESERVED 0x00000008 */ +/* #define AP_OPTS_RESERVED 0x00000004 */ + + +#define AP_OPTS_WIRE_MASK 0xfffffff0 + +/* definitions for ad_type fields. */ +#define AD_TYPE_RESERVED 0x8000 +#define AD_TYPE_EXTERNAL 0x4000 +#define AD_TYPE_REGISTERED 0x2000 + +#define AD_TYPE_FIELD_TYPE_MASK 0x1fff + +/* Ticket flags */ +/* flags are 32 bits; each host is responsible to put the 4 bytes + representing these bits into net order before transmission */ +/* #define TKT_FLG_RESERVED 0x80000000 */ +#define TKT_FLG_FORWARDABLE 0x40000000 +#define TKT_FLG_FORWARDED 0x20000000 +#define TKT_FLG_PROXIABLE 0x10000000 +#define TKT_FLG_PROXY 0x08000000 +#define TKT_FLG_MAY_POSTDATE 0x04000000 +#define TKT_FLG_POSTDATED 0x02000000 +#define TKT_FLG_INVALID 0x01000000 +#define TKT_FLG_RENEWABLE 0x00800000 +#define TKT_FLG_INITIAL 0x00400000 +#define TKT_FLG_PRE_AUTH 0x00200000 +#define TKT_FLG_HW_AUTH 0x00100000 +#define TKT_FLG_TRANSIT_POLICY_CHECKED 0x00080000 +#define TKT_FLG_OK_AS_DELEGATE 0x00040000 +#define TKT_FLG_ENC_PA_REP 0x00010000 +#define TKT_FLG_ANONYMOUS 0x00008000 +/* #define TKT_FLG_RESERVED 0x00004000 */ +/* #define TKT_FLG_RESERVED 0x00002000 */ +/* #define TKT_FLG_RESERVED 0x00001000 */ +/* #define TKT_FLG_RESERVED 0x00000800 */ +/* #define TKT_FLG_RESERVED 0x00000400 */ +/* #define TKT_FLG_RESERVED 0x00000200 */ +/* #define TKT_FLG_RESERVED 0x00000100 */ +/* #define TKT_FLG_RESERVED 0x00000080 */ +/* #define TKT_FLG_RESERVED 0x00000040 */ +/* #define TKT_FLG_RESERVED 0x00000020 */ +/* #define TKT_FLG_RESERVED 0x00000010 */ +/* #define TKT_FLG_RESERVED 0x00000008 */ +/* #define TKT_FLG_RESERVED 0x00000004 */ +/* #define TKT_FLG_RESERVED 0x00000002 */ +/* #define TKT_FLG_RESERVED 0x00000001 */ + +/* definitions for lr_type fields. */ +#define LR_TYPE_THIS_SERVER_ONLY 0x8000 + +#define LR_TYPE_INTERPRETATION_MASK 0x7fff + +/* definitions for msec direction bit for KRB_SAFE, KRB_PRIV */ +#define MSEC_DIRBIT 0x8000 +#define MSEC_VAL_MASK 0x7fff + +/* + * end "fieldbits.h" + */ + +/* + * begin "proto.h" + */ + +/** Protocol version number */ +#define KRB5_PVNO 5 + +/* Message types */ + +#define KRB5_AS_REQ ((krb5_msgtype)10) /**< Initial authentication request */ +#define KRB5_AS_REP ((krb5_msgtype)11) /**< Response to AS request */ +#define KRB5_TGS_REQ ((krb5_msgtype)12) /**< Ticket granting server request */ +#define KRB5_TGS_REP ((krb5_msgtype)13) /**< Response to TGS request */ +#define KRB5_AP_REQ ((krb5_msgtype)14) /**< Auth req to application server */ +#define KRB5_AP_REP ((krb5_msgtype)15) /**< Response to mutual AP request */ +#define KRB5_SAFE ((krb5_msgtype)20) /**< Safe application message */ +#define KRB5_PRIV ((krb5_msgtype)21) /**< Private application message */ +#define KRB5_CRED ((krb5_msgtype)22) /**< Cred forwarding message */ +#define KRB5_ERROR ((krb5_msgtype)30) /**< Error response */ + +/* LastReq types */ +#define KRB5_LRQ_NONE 0 +#define KRB5_LRQ_ALL_LAST_TGT 1 +#define KRB5_LRQ_ONE_LAST_TGT (-1) +#define KRB5_LRQ_ALL_LAST_INITIAL 2 +#define KRB5_LRQ_ONE_LAST_INITIAL (-2) +#define KRB5_LRQ_ALL_LAST_TGT_ISSUED 3 +#define KRB5_LRQ_ONE_LAST_TGT_ISSUED (-3) +#define KRB5_LRQ_ALL_LAST_RENEWAL 4 +#define KRB5_LRQ_ONE_LAST_RENEWAL (-4) +#define KRB5_LRQ_ALL_LAST_REQ 5 +#define KRB5_LRQ_ONE_LAST_REQ (-5) +#define KRB5_LRQ_ALL_PW_EXPTIME 6 +#define KRB5_LRQ_ONE_PW_EXPTIME (-6) +#define KRB5_LRQ_ALL_ACCT_EXPTIME 7 +#define KRB5_LRQ_ONE_ACCT_EXPTIME (-7) + +/* PADATA types */ +#define KRB5_PADATA_NONE 0 +#define KRB5_PADATA_AP_REQ 1 +#define KRB5_PADATA_TGS_REQ KRB5_PADATA_AP_REQ +#define KRB5_PADATA_ENC_TIMESTAMP 2 /**< RFC 4120 */ +#define KRB5_PADATA_PW_SALT 3 /**< RFC 4120 */ +#if 0 /* Not used */ +#define KRB5_PADATA_ENC_ENCKEY 4 /* Key encrypted within itself */ +#endif +#define KRB5_PADATA_ENC_UNIX_TIME 5 /**< timestamp encrypted in key. RFC 4120 */ +#define KRB5_PADATA_ENC_SANDIA_SECURID 6 /**< SecurId passcode. RFC 4120 */ +#define KRB5_PADATA_SESAME 7 /**< Sesame project. RFC 4120 */ +#define KRB5_PADATA_OSF_DCE 8 /**< OSF DCE. RFC 4120 */ +#define KRB5_CYBERSAFE_SECUREID 9 /**< Cybersafe. RFC 4120 */ +#define KRB5_PADATA_AFS3_SALT 10 /**< Cygnus. RFC 4120, 3961 */ +#define KRB5_PADATA_ETYPE_INFO 11 /**< Etype info for preauth. RFC 4120 */ +#define KRB5_PADATA_SAM_CHALLENGE 12 /**< SAM/OTP */ +#define KRB5_PADATA_SAM_RESPONSE 13 /**< SAM/OTP */ +#define KRB5_PADATA_PK_AS_REQ_OLD 14 /**< PKINIT */ +#define KRB5_PADATA_PK_AS_REP_OLD 15 /**< PKINIT */ +#define KRB5_PADATA_PK_AS_REQ 16 /**< PKINIT. RFC 4556 */ +#define KRB5_PADATA_PK_AS_REP 17 /**< PKINIT. RFC 4556 */ +#define KRB5_PADATA_ETYPE_INFO2 19 /**< RFC 4120 */ +#define KRB5_PADATA_USE_SPECIFIED_KVNO 20 /**< RFC 4120 */ +#define KRB5_PADATA_SVR_REFERRAL_INFO 20 /**< Windows 2000 referrals. RFC 6820 */ +#define KRB5_PADATA_SAM_REDIRECT 21 /**< SAM/OTP. RFC 4120 */ +#define KRB5_PADATA_GET_FROM_TYPED_DATA 22 /**< Embedded in typed data. RFC 4120 */ +#define KRB5_PADATA_REFERRAL 25 /**< draft referral system */ +#define KRB5_PADATA_SAM_CHALLENGE_2 30 /**< draft challenge system, updated */ +#define KRB5_PADATA_SAM_RESPONSE_2 31 /**< draft challenge system, updated */ +/* MS-KILE */ +#define KRB5_PADATA_PAC_REQUEST 128 /**< include Windows PAC */ +#define KRB5_PADATA_FOR_USER 129 /**< username protocol transition request */ +#define KRB5_PADATA_S4U_X509_USER 130 /**< certificate protocol transition request */ +#define KRB5_PADATA_AS_CHECKSUM 132 /**< AS checksum */ +#define KRB5_PADATA_FX_COOKIE 133 /**< RFC 6113 */ +#define KRB5_PADATA_FX_FAST 136 /**< RFC 6113 */ +#define KRB5_PADATA_FX_ERROR 137 /**< RFC 6113 */ +#define KRB5_PADATA_ENCRYPTED_CHALLENGE 138 /**< RFC 6113 */ +#define KRB5_PADATA_OTP_CHALLENGE 141 /**< RFC 6560 section 4.1 */ +#define KRB5_PADATA_OTP_REQUEST 142 /**< RFC 6560 section 4.2 */ +#define KRB5_PADATA_OTP_PIN_CHANGE 144 /**< RFC 6560 section 4.3 */ +#define KRB5_PADATA_PKINIT_KX 147 /**< RFC 6112 */ +#define KRB5_ENCPADATA_REQ_ENC_PA_REP 149 /**< RFC 6806 */ +#define KRB5_PADATA_AS_FRESHNESS 150 /**< RFC 8070 */ +#define KRB5_PADATA_SPAKE 151 +#define KRB5_PADATA_REDHAT_IDP_OAUTH2 152 /**< Red Hat IdP mechanism */ +#define KRB5_PADATA_REDHAT_PASSKEY 153 /**< Red Hat Passkey mechanism */ +#define KRB5_PADATA_PAC_OPTIONS 167 /**< MS-KILE and MS-SFU */ + +#define KRB5_SAM_USE_SAD_AS_KEY 0x80000000 +#define KRB5_SAM_SEND_ENCRYPTED_SAD 0x40000000 +#define KRB5_SAM_MUST_PK_ENCRYPT_SAD 0x20000000 /**< currently must be zero */ + +/** Transited encoding types */ +#define KRB5_DOMAIN_X500_COMPRESS 1 + +/** alternate authentication types */ +#define KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE 64 + +/* authorization data types. See RFC 4120 section 5.2.6 */ + +#define KRB5_AUTHDATA_IF_RELEVANT 1 +#define KRB5_AUTHDATA_KDC_ISSUED 4 +#define KRB5_AUTHDATA_AND_OR 5 +#define KRB5_AUTHDATA_MANDATORY_FOR_KDC 8 +#define KRB5_AUTHDATA_INITIAL_VERIFIED_CAS 9 +#define KRB5_AUTHDATA_OSF_DCE 64 +#define KRB5_AUTHDATA_SESAME 65 +#define KRB5_AUTHDATA_CAMMAC 96 +#define KRB5_AUTHDATA_WIN2K_PAC 128 +#define KRB5_AUTHDATA_ETYPE_NEGOTIATION 129 /**< RFC 4537 */ +#define KRB5_AUTHDATA_SIGNTICKET 512 /**< @deprecated use PAC */ +#define KRB5_AUTHDATA_FX_ARMOR 71 +#define KRB5_AUTHDATA_AUTH_INDICATOR 97 +#define KRB5_AUTHDATA_AP_OPTIONS 143 + +/* password change constants */ +#define KRB5_KPASSWD_SUCCESS 0 /**< Success */ +#define KRB5_KPASSWD_MALFORMED 1 /**< Malformed request */ +#define KRB5_KPASSWD_HARDERROR 2 /**< Server error */ +#define KRB5_KPASSWD_AUTHERROR 3 /**< Authentication error */ +#define KRB5_KPASSWD_SOFTERROR 4 /**< Password change rejected */ +/* These are Microsoft's extensions in RFC 3244, and it looks like + they'll become standardized, possibly with other additions. */ +#define KRB5_KPASSWD_ACCESSDENIED 5 /**< Not authorized */ +#define KRB5_KPASSWD_BAD_VERSION 6 /**< Unknown RPC version */ +/** The presented credentials were not obtained using a password directly */ +#define KRB5_KPASSWD_INITIAL_FLAG_NEEDED 7 + +/* + * end "proto.h" + */ + +/* Time set */ +/** Ticket start time, end time, and renewal duration. */ +typedef struct _krb5_ticket_times { + krb5_timestamp authtime; /**< Time at which KDC issued the initial ticket that corresponds to this ticket */ + /* XXX ? should ktime in KDC_REP == authtime + in ticket? otherwise client can't get this */ + krb5_timestamp starttime; /**< optional in ticket, if not present, use @a authtime */ + krb5_timestamp endtime; /**< Ticket expiration time */ + krb5_timestamp renew_till; /**< Latest time at which renewal of ticket can be valid */ +} krb5_ticket_times; + +/** Structure for auth data */ +typedef struct _krb5_authdata { + krb5_magic magic; + krb5_authdatatype ad_type; /**< ADTYPE */ + unsigned int length; /**< Length of data */ + krb5_octet *contents; /**< Data */ +} krb5_authdata; + +/** Structure for transited encoding */ +typedef struct _krb5_transited { + krb5_magic magic; + krb5_octet tr_type; /**< Transited encoding type */ + krb5_data tr_contents; /**< Contents */ +} krb5_transited; + +/** Encrypted part of ticket. */ +typedef struct _krb5_enc_tkt_part { + krb5_magic magic; + /* to-be-encrypted portion */ + krb5_flags flags; /**< flags */ + krb5_keyblock *session; /**< session key: includes enctype */ + krb5_principal client; /**< client name/realm */ + krb5_transited transited; /**< list of transited realms */ + krb5_ticket_times times; /**< auth, start, end, renew_till */ + krb5_address **caddrs; /**< array of ptrs to addresses */ + krb5_authdata **authorization_data; /**< auth data */ +} krb5_enc_tkt_part; + +/** + * Ticket structure. + * + * The C representation of the ticket message, with a pointer to the + * C representation of the encrypted part. + */ +typedef struct _krb5_ticket { + krb5_magic magic; + /* cleartext portion */ + krb5_principal server; /**< server name/realm */ + krb5_enc_data enc_part; /**< encryption type, kvno, encrypted encoding */ + krb5_enc_tkt_part *enc_part2; /**< ptr to decrypted version, if available */ +} krb5_ticket; + +/* the unencrypted version */ +/** + * Ticket authenticator. + * + * The C representation of an unencrypted authenticator. + */ +typedef struct _krb5_authenticator { + krb5_magic magic; + krb5_principal client; /**< client name/realm */ + krb5_checksum *checksum; /**< checksum, includes type, optional */ + krb5_int32 cusec; /**< client usec portion */ + krb5_timestamp ctime; /**< client sec portion */ + krb5_keyblock *subkey; /**< true session key, optional */ + krb5_ui_4 seq_number; /**< sequence #, optional */ + krb5_authdata **authorization_data; /**< authoriazation data */ +} krb5_authenticator; + +/** Ticket authentication data. */ +typedef struct _krb5_tkt_authent { + krb5_magic magic; + krb5_ticket *ticket; + krb5_authenticator *authenticator; + krb5_flags ap_options; +} krb5_tkt_authent; + +/** Credentials structure including ticket, session key, and lifetime info. */ +typedef struct _krb5_creds { + krb5_magic magic; + krb5_principal client; /**< client's principal identifier */ + krb5_principal server; /**< server's principal identifier */ + krb5_keyblock keyblock; /**< session encryption key info */ + krb5_ticket_times times; /**< lifetime info */ + krb5_boolean is_skey; /**< true if ticket is encrypted in + another ticket's skey */ + krb5_flags ticket_flags; /**< flags in ticket */ + krb5_address **addresses; /**< addrs in ticket */ + krb5_data ticket; /**< ticket string itself */ + krb5_data second_ticket; /**< second ticket, if related to + ticket (via DUPLICATE-SKEY or + ENC-TKT-IN-SKEY) */ + krb5_authdata **authdata; /**< authorization data */ +} krb5_creds; + +/** Last request entry */ +typedef struct _krb5_last_req_entry { + krb5_magic magic; + krb5_int32 lr_type; /**< LR type */ + krb5_timestamp value; /**< Timestamp */ +} krb5_last_req_entry; + +/** Pre-authentication data */ +typedef struct _krb5_pa_data { + krb5_magic magic; + krb5_preauthtype pa_type; /**< Preauthentication data type */ + unsigned int length; /**< Length of data */ + krb5_octet *contents; /**< Data */ +} krb5_pa_data; + +/* Don't use this; use krb5_pa_data instead. */ +typedef struct _krb5_typed_data { + krb5_magic magic; + krb5_int32 type; + unsigned int length; + krb5_octet *data; +} krb5_typed_data; + +/** C representation of KDC-REQ protocol message, including KDC-REQ-BODY */ +typedef struct _krb5_kdc_req { + krb5_magic magic; + krb5_msgtype msg_type; /**< KRB5_AS_REQ or KRB5_TGS_REQ */ + krb5_pa_data **padata; /**< Preauthentication data */ + /* real body */ + krb5_flags kdc_options; /**< Requested options */ + krb5_principal client; /**< Client principal and realm */ + krb5_principal server; /**< Server principal and realm */ + krb5_timestamp from; /**< Requested start time */ + krb5_timestamp till; /**< Requested end time */ + krb5_timestamp rtime; /**< Requested renewable end time */ + krb5_int32 nonce; /**< Nonce to match request and response */ + int nktypes; /**< Number of enctypes */ + krb5_enctype *ktype; /**< Requested enctypes */ + krb5_address **addresses; /**< Requested addresses (optional) */ + krb5_enc_data authorization_data; /**< Encrypted authz data (optional) */ + krb5_authdata **unenc_authdata; /**< Unencrypted authz data */ + krb5_ticket **second_ticket; /**< Second ticket array (optional) */ +} krb5_kdc_req; + +/** + * C representation of @c EncKDCRepPart protocol message. + * + * This is the cleartext message that is encrypted and inserted in @c KDC-REP. + */ +typedef struct _krb5_enc_kdc_rep_part { + krb5_magic magic; + /* encrypted part: */ + krb5_msgtype msg_type; /**< krb5 message type */ + krb5_keyblock *session; /**< Session key */ + krb5_last_req_entry **last_req; /**< Array of pointers to entries */ + krb5_int32 nonce; /**< Nonce from request */ + krb5_timestamp key_exp; /**< Expiration date */ + krb5_flags flags; /**< Ticket flags */ + krb5_ticket_times times; /**< Lifetime info */ + krb5_principal server; /**< Server's principal identifier */ + krb5_address **caddrs; /**< Array of ptrs to addrs, optional */ + krb5_pa_data **enc_padata; /**< Encrypted preauthentication data */ +} krb5_enc_kdc_rep_part; + +/** Representation of the @c KDC-REP protocol message. */ +typedef struct _krb5_kdc_rep { + krb5_magic magic; + /* cleartext part: */ + krb5_msgtype msg_type; /**< KRB5_AS_REP or KRB5_KDC_REP */ + krb5_pa_data **padata; /**< Preauthentication data from KDC */ + krb5_principal client; /**< Client principal and realm */ + krb5_ticket *ticket; /**< Ticket */ + krb5_enc_data enc_part; /**< Encrypted part of reply */ + krb5_enc_kdc_rep_part *enc_part2; /**< Unencrypted version, if available */ +} krb5_kdc_rep; + +/** Error message structure */ +typedef struct _krb5_error { + krb5_magic magic; + /* some of these may be meaningless in certain contexts */ + krb5_timestamp ctime; /**< Client sec portion; optional */ + krb5_int32 cusec; /**< Client usec portion; optional */ + krb5_int32 susec; /**< Server usec portion */ + krb5_timestamp stime; /**< Server sec portion */ + krb5_ui_4 error; /**< Error code (protocol error #'s) */ + krb5_principal client; /**< Client principal and realm */ + krb5_principal server; /**< Server principal and realm */ + krb5_data text; /**< Descriptive text */ + krb5_data e_data; /**< Additional error-describing data */ +} krb5_error; + +/** Authentication header. */ +typedef struct _krb5_ap_req { + krb5_magic magic; + krb5_flags ap_options; /**< Requested options */ + krb5_ticket *ticket; /**< Ticket */ + krb5_enc_data authenticator; /**< Encrypted authenticator */ +} krb5_ap_req; + +/** + * C representaton of AP-REP message. + * + * The server's response to a client's request for mutual authentication. + */ +typedef struct _krb5_ap_rep { + krb5_magic magic; + krb5_enc_data enc_part; /**< Ciphertext of ApRepEncPart */ +} krb5_ap_rep; + +/** Cleartext that is encrypted and put into @c _krb5_ap_rep. */ +typedef struct _krb5_ap_rep_enc_part { + krb5_magic magic; + krb5_timestamp ctime; /**< Client time, seconds portion */ + krb5_int32 cusec; /**< Client time, microseconds portion */ + krb5_keyblock *subkey; /**< Subkey (optional) */ + krb5_ui_4 seq_number; /**< Sequence number */ +} krb5_ap_rep_enc_part; + +/* Unused */ +typedef struct _krb5_response { + krb5_magic magic; + krb5_octet message_type; + krb5_data response; + krb5_int32 expected_nonce; + krb5_timestamp request_time; +} krb5_response; + +/** Credentials information inserted into @c EncKrbCredPart. */ +typedef struct _krb5_cred_info { + krb5_magic magic; + krb5_keyblock *session; /**< Session key used to encrypt ticket */ + krb5_principal client; /**< Client principal and realm */ + krb5_principal server; /**< Server principal and realm */ + krb5_flags flags; /**< Ticket flags */ + krb5_ticket_times times; /**< Auth, start, end, renew_till */ + krb5_address **caddrs; /**< Array of pointers to addrs (optional) */ +} krb5_cred_info; + +/** Cleartext credentials information. */ +typedef struct _krb5_cred_enc_part { + krb5_magic magic; + krb5_int32 nonce; /**< Nonce (optional) */ + krb5_timestamp timestamp; /**< Generation time, seconds portion */ + krb5_int32 usec; /**< Generation time, microseconds portion */ + krb5_address *s_address; /**< Sender address (optional) */ + krb5_address *r_address; /**< Recipient address (optional) */ + krb5_cred_info **ticket_info; +} krb5_cred_enc_part; + +/** Credentials data structure.*/ +typedef struct _krb5_cred { + krb5_magic magic; + krb5_ticket **tickets; /**< Tickets */ + krb5_enc_data enc_part; /**< Encrypted part */ + krb5_cred_enc_part *enc_part2; /**< Unencrypted version, if available */ +} krb5_cred; + +/* Unused, but here for API compatibility. */ +typedef struct _passwd_phrase_element { + krb5_magic magic; + krb5_data *passwd; + krb5_data *phrase; +} passwd_phrase_element; + +/* Unused, but here for API compatibility. */ +typedef struct _krb5_pwd_data { + krb5_magic magic; + int sequence_count; + passwd_phrase_element **element; +} krb5_pwd_data; + +/* Unused, but here for API compatibility. */ +typedef struct _krb5_pa_svr_referral_data { + /** Referred name, only realm is required */ + krb5_principal principal; +} krb5_pa_svr_referral_data; + +/* Unused, but here for API compatibility. */ +typedef struct _krb5_pa_server_referral_data { + krb5_data *referred_realm; + krb5_principal true_principal_name; + krb5_principal requested_principal_name; + krb5_timestamp referral_valid_until; + krb5_checksum rep_cksum; +} krb5_pa_server_referral_data; + +typedef struct _krb5_pa_pac_req { + /** TRUE if a PAC should be included in TGS-REP */ + krb5_boolean include_pac; +} krb5_pa_pac_req; + +/* + * begin "safepriv.h" + */ + +/** Prevent replays with timestamps and replay cache. */ +#define KRB5_AUTH_CONTEXT_DO_TIME 0x00000001 +/** Save timestamps for application. */ +#define KRB5_AUTH_CONTEXT_RET_TIME 0x00000002 +/** Prevent replays with sequence numbers. */ +#define KRB5_AUTH_CONTEXT_DO_SEQUENCE 0x00000004 +/** Save sequence numbers for application. */ +#define KRB5_AUTH_CONTEXT_RET_SEQUENCE 0x00000008 +#define KRB5_AUTH_CONTEXT_PERMIT_ALL 0x00000010 +#define KRB5_AUTH_CONTEXT_USE_SUBKEY 0x00000020 + +/** + * Replay data. + * + * Sequence number and timestamp information output by krb5_rd_priv() and + * krb5_rd_safe(). + */ +typedef struct krb5_replay_data { + krb5_timestamp timestamp; /**< Timestamp, seconds portion */ + krb5_int32 usec; /**< Timestamp, microseconds portion */ + krb5_ui_4 seq; /**< Sequence number */ +} krb5_replay_data; + +/* Flags for krb5_auth_con_genaddrs(). */ + +/** Generate the local network address. */ +#define KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR 0x00000001 +/** Generate the remote network address. */ +#define KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR 0x00000002 +/** Generate the local network address and the local port. */ +#define KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR 0x00000004 +/** Generate the remote network address and the remote port. */ +#define KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR 0x00000008 + +/** Type of function used as a callback to generate checksum data for mk_req */ +typedef krb5_error_code +(KRB5_CALLCONV * krb5_mk_req_checksum_func)(krb5_context, krb5_auth_context, + void *, krb5_data **); + +/* + * end "safepriv.h" + */ + + +/* + * begin "ccache.h" + */ + +/** Cursor for sequential lookup */ +typedef krb5_pointer krb5_cc_cursor; + +struct _krb5_ccache; +typedef struct _krb5_ccache *krb5_ccache; +struct _krb5_cc_ops; +typedef struct _krb5_cc_ops krb5_cc_ops; + +struct _krb5_cccol_cursor; +/** Cursor for iterating over all ccaches */ +typedef struct _krb5_cccol_cursor *krb5_cccol_cursor; + +/* Flags for krb5_cc_retrieve_cred. */ +/** The requested lifetime must be at least as great as the time specified. */ +#define KRB5_TC_MATCH_TIMES 0x00000001 +/** The is_skey field must match exactly. */ +#define KRB5_TC_MATCH_IS_SKEY 0x00000002 +/** All the flags set in the match credentials must be set. */ +#define KRB5_TC_MATCH_FLAGS 0x00000004 +/** All the time fields must match exactly. */ +#define KRB5_TC_MATCH_TIMES_EXACT 0x00000008 +/** All the flags must match exactly. */ +#define KRB5_TC_MATCH_FLAGS_EXACT 0x00000010 +/** The authorization data must match. */ +#define KRB5_TC_MATCH_AUTHDATA 0x00000020 +/** Only the name portion of the principal name must match. */ +#define KRB5_TC_MATCH_SRV_NAMEONLY 0x00000040 +/** The second ticket must match. */ +#define KRB5_TC_MATCH_2ND_TKT 0x00000080 +/** The encryption key type must match. */ +#define KRB5_TC_MATCH_KTYPE 0x00000100 +/** The supported key types must match. */ +#define KRB5_TC_SUPPORTED_KTYPES 0x00000200 + +/* Flags for krb5_cc_set_flags and similar. */ +/** Open and close the file for each cache operation. */ +#define KRB5_TC_OPENCLOSE 0x00000001 /**< @deprecated has no effect */ +#define KRB5_TC_NOTICKET 0x00000002 + +/** + * Retrieve the name, but not type of a credential cache. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * + * @warning Returns the name of the credential cache. The result is an alias + * into @a cache and should not be freed or modified by the caller. This name + * does not include the cache type, so should not be used as input to + * krb5_cc_resolve(). + * + * @return + * On success - the name of the credential cache. + */ +const char * KRB5_CALLCONV +krb5_cc_get_name(krb5_context context, krb5_ccache cache); + +/** + * Retrieve the full name of a credential cache. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * @param [out] fullname_out Full name of cache + * + * Use krb5_free_string() to free @a fullname_out when it is no longer needed. + * + * @version New in 1.10 + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_get_full_name(krb5_context context, krb5_ccache cache, + char **fullname_out); + +#if KRB5_DEPRECATED +krb5_error_code KRB5_CALLCONV +krb5_cc_gen_new(krb5_context context, krb5_ccache *cache); +#endif /* KRB5_DEPRECATED */ + +/** + * Initialize a credential cache. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * @param [in] principal Default principal name + * + * Destroy any existing contents of @a cache and initialize it for the default + * principal @a principal. + * + * @retval + * 0 Success + * @return + * System errors; Permission errors; Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_initialize(krb5_context context, krb5_ccache cache, + krb5_principal principal); + +/** + * Destroy a credential cache. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * + * This function destroys any existing contents of @a cache and closes the + * handle to it. + * + * @retval + * 0 Success + * @return + * Permission errors + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_destroy(krb5_context context, krb5_ccache cache); + +/** + * Close a credential cache handle. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * + * This function closes a credential cache handle @a cache without affecting + * the contents of the cache. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_close(krb5_context context, krb5_ccache cache); + +/** + * Store credentials in a credential cache. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * @param [in] creds Credentials to be stored in cache + * + * This function stores @a creds into @a cache. If @a creds->server and the + * server in the decoded ticket @a creds->ticket differ, the credentials will + * be stored under both server principal names. + * + * @retval + * 0 Success + * @return Permission errors; storage failure errors; Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_store_cred(krb5_context context, krb5_ccache cache, krb5_creds *creds); + +/** + * Retrieve a specified credentials from a credential cache. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * @param [in] flags Flags bit mask + * @param [in] mcreds Credentials to match + * @param [out] creds Credentials matching the requested value + * + * This function searches a credential cache for credentials matching @a mcreds + * and returns it if found. + * + * Valid values for @a flags are: + * + * @li #KRB5_TC_MATCH_TIMES The requested lifetime must be at least as + * great as in @a mcreds . + * @li #KRB5_TC_MATCH_IS_SKEY The @a is_skey field much match exactly. + * @li #KRB5_TC_MATCH_FLAGS Flags set in @a mcreds must be set. + * @li #KRB5_TC_MATCH_TIMES_EXACT The requested lifetime must match exactly. + * @li #KRB5_TC_MATCH_FLAGS_EXACT Flags must match exactly. + * @li #KRB5_TC_MATCH_AUTHDATA The authorization data must match. + * @li #KRB5_TC_MATCH_SRV_NAMEONLY Only the name portion of the principal + * name must match, not the realm. + * @li #KRB5_TC_MATCH_2ND_TKT The second tickets must match. + * @li #KRB5_TC_MATCH_KTYPE The encryption key types must match. + * @li #KRB5_TC_SUPPORTED_KTYPES Check all matching entries that have any + * supported encryption type and return the + * one with the encryption type listed earliest. + * + * Use krb5_free_cred_contents() to free @a creds when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_retrieve_cred(krb5_context context, krb5_ccache cache, + krb5_flags flags, krb5_creds *mcreds, + krb5_creds *creds); + +/** + * Get the default principal of a credential cache. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * @param [out] principal Primary principal + * + * Returns the default client principal of a credential cache as set by + * krb5_cc_initialize(). + * + * Use krb5_free_principal() to free @a principal when it is no longer needed. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_get_principal(krb5_context context, krb5_ccache cache, + krb5_principal *principal); + +/** + * Prepare to sequentially read every credential in a credential cache. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * @param [out] cursor Cursor + * + * krb5_cc_end_seq_get() must be called to complete the retrieve operation. + * + * @note If the cache represented by @a cache is modified between the time of + * the call to this function and the time of the final krb5_cc_end_seq_get(), + * these changes may not be reflected in the results of krb5_cc_next_cred() + * calls. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_start_seq_get(krb5_context context, krb5_ccache cache, + krb5_cc_cursor *cursor); + +/** + * Retrieve the next entry from the credential cache. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * @param [in] cursor Cursor + * @param [out] creds Next credential cache entry + * + * This function fills in @a creds with the next entry in @a cache and advances + * @a cursor. + * + * Use krb5_free_cred_contents() to free @a creds when it is no longer needed. + * + * @sa krb5_cc_start_seq_get(), krb5_end_seq_get() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_next_cred(krb5_context context, krb5_ccache cache, + krb5_cc_cursor *cursor, krb5_creds *creds); + +/** + * Finish a series of sequential processing credential cache entries. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * @param [in] cursor Cursor + * + * This function finishes processing credential cache entries and invalidates + * @a cursor. + * + * @sa krb5_cc_start_seq_get(), krb5_cc_next_cred() + * + * @retval 0 (always) + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_end_seq_get(krb5_context context, krb5_ccache cache, + krb5_cc_cursor *cursor); + +/** + * Remove credentials from a credential cache. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * @param [in] flags Bitwise-ORed search flags + * @param [in] creds Credentials to be matched + * + * @warning This function is not implemented for some cache types. + * + * This function accepts the same flag values as krb5_cc_retrieve_cred(). + * + * @retval KRB5_CC_NOSUPP Not implemented for this cache type + * @return No matches found; Data cannot be deleted; Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags, + krb5_creds *creds); + +/** + * Set options flags on a credential cache. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * @param [in] flags Flag bit mask + * + * This function resets @a cache flags to @a flags. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_set_flags(krb5_context context, krb5_ccache cache, krb5_flags flags); + +/** + * Retrieve flags from a credential cache structure. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * @param [out] flags Flag bit mask + * + * @warning For memory credential cache always returns a flag mask of 0. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_get_flags(krb5_context context, krb5_ccache cache, krb5_flags *flags); + +/** + * Retrieve the type of a credential cache. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * + * @return The type of a credential cache as an alias that must not be modified + * or freed by the caller. + */ +const char * KRB5_CALLCONV +krb5_cc_get_type(krb5_context context, krb5_ccache cache); + +/** + * Move a credential cache. + * + * @param [in] context Library context + * @param [in] src The credential cache to move the content from + * @param [in] dst The credential cache to move the content to + * + * This function reinitializes @a dst and populates it with the credentials and + * default principal of @a src; then, if successful, destroys @a src. + * + * @retval + * 0 Success; @a src is closed. + * @return + * Kerberos error codes; @a src is still allocated. + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_move(krb5_context context, krb5_ccache src, krb5_ccache dst); + +/** + * Prepare to iterate over the collection of known credential caches. + * + * @param [in] context Library context + * @param [out] cursor Cursor + * + * Get a new cache iteration @a cursor that will iterate over all known + * credential caches independent of type. + * + * Use krb5_cccol_cursor_free() to release @a cursor when it is no longer + * needed. + * + * @sa krb5_cccol_cursor_next() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cccol_cursor_new(krb5_context context, krb5_cccol_cursor *cursor); + +/** + * Get the next credential cache in the collection. + * + * @param [in] context Library context + * @param [in] cursor Cursor + * @param [out] ccache Credential cache handle + * + * @note When all caches are iterated over and the end of the list is reached, + * @a ccache is set to NULL. + * + * Use krb5_cc_close() to close @a ccache when it is no longer needed. + * + * @sa krb5_cccol_cursor_new(), krb5_cccol_cursor_free() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cccol_cursor_next(krb5_context context, krb5_cccol_cursor cursor, + krb5_ccache *ccache); + +/** + * Free a credential cache collection cursor. + * + * @param [in] context Library context + * @param [in] cursor Cursor + * + * @sa krb5_cccol_cursor_new(), krb5_cccol_cursor_next() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cccol_cursor_free(krb5_context context, krb5_cccol_cursor *cursor); + +/** + * Check if the credential cache collection contains any initialized caches. + * + * @param [in] context Library context + * + * @version New in 1.11 + * + * @retval 0 At least one initialized cache is present in the collection + * @retval KRB5_CC_NOTFOUND The collection contains no caches + */ +krb5_error_code KRB5_CALLCONV +krb5_cccol_have_content(krb5_context context); + +/** + * Create a new credential cache of the specified type with a unique name. + * + * @param [in] context Library context + * @param [in] type Credential cache type name + * @param [in] hint Unused + * @param [out] id Credential cache handle + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_new_unique(krb5_context context, const char *type, const char *hint, + krb5_ccache *id); + +/* + * end "ccache.h" + */ + +/* + * begin "rcache.h" + */ + +struct krb5_rc_st; +typedef struct krb5_rc_st *krb5_rcache; + +/* + * end "rcache.h" + */ + +/* + * begin "keytab.h" + */ + + +/* XXX */ +#define MAX_KEYTAB_NAME_LEN 1100 /**< Long enough for MAXPATHLEN + some extra */ + +typedef krb5_pointer krb5_kt_cursor; + +/** A key table entry. */ +typedef struct krb5_keytab_entry_st { + krb5_magic magic; + krb5_principal principal; /**< Principal of this key */ + krb5_timestamp timestamp; /**< Time entry written to keytable */ + krb5_kvno vno; /**< Key version number */ + krb5_keyblock key; /**< The secret key */ +} krb5_keytab_entry; + +struct _krb5_kt; +typedef struct _krb5_kt *krb5_keytab; + +/** + * Return the type of a key table. + * + * @param [in] context Library context + * @param [in] keytab Key table handle + * + * @return The type of a key table as an alias that must not be modified or + * freed by the caller. + */ +const char * KRB5_CALLCONV +krb5_kt_get_type(krb5_context context, krb5_keytab keytab); + +/** + * Get a key table name. + * + * @param [in] context Library context + * @param [in] keytab Key table handle + * @param [out] name Key table name + * @param [in] namelen Maximum length to fill in name + * + * Fill @a name with the name of @a keytab including the type and delimiter. + * + * @sa MAX_KEYTAB_NAME_LEN + * + * @retval + * 0 Success + * @retval + * KRB5_KT_NAME_TOOLONG Key table name does not fit in @a namelen bytes + * + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_get_name(krb5_context context, krb5_keytab keytab, char *name, + unsigned int namelen); + +/** + * Close a key table handle. + * + * @param [in] context Library context + * @param [in] keytab Key table handle + * + * @retval 0 + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_close(krb5_context context, krb5_keytab keytab); + +/** + * Get an entry from a key table. + * + * @param [in] context Library context + * @param [in] keytab Key table handle + * @param [in] principal Principal name + * @param [in] vno Key version number (0 for highest available) + * @param [in] enctype Encryption type (0 zero for any enctype) + * @param [out] entry Returned entry from key table + * + * Retrieve an entry from a key table which matches the @a keytab, @a + * principal, @a vno, and @a enctype. If @a vno is zero, retrieve the + * highest-numbered kvno matching the other fields. If @a enctype is 0, match + * any enctype. + * + * Use krb5_free_keytab_entry_contents() to free @a entry when it is no longer + * needed. + * + * @note If @a vno is zero, the function retrieves the highest-numbered-kvno + * entry that matches the specified principal. + * + * @retval + * 0 Success + * @retval + * Kerberos error codes on failure + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_get_entry(krb5_context context, krb5_keytab keytab, + krb5_const_principal principal, krb5_kvno vno, + krb5_enctype enctype, krb5_keytab_entry *entry); + +/** + * Start a sequential retrieval of key table entries. + * + * @param [in] context Library context + * @param [in] keytab Key table handle + * @param [out] cursor Cursor + * + * Prepare to read sequentially every key in the specified key table. Use + * krb5_kt_end_seq_get() to release the cursor when it is no longer needed. + * + * @sa krb5_kt_next_entry(), krb5_kt_end_seq_get() + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_start_seq_get(krb5_context context, krb5_keytab keytab, + krb5_kt_cursor *cursor); + +/** + * Retrieve the next entry from the key table. + * + * @param [in] context Library context + * @param [in] keytab Key table handle + * @param [out] entry Returned key table entry + * @param [in] cursor Key table cursor + * + * Return the next sequential entry in @a keytab and advance @a cursor. + * Callers must release the returned entry with krb5_kt_free_entry(). + * + * @sa krb5_kt_start_seq_get(), krb5_kt_end_seq_get() + * + * @retval + * 0 Success + * @retval + * KRB5_KT_END - if the last entry was reached + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_next_entry(krb5_context context, krb5_keytab keytab, + krb5_keytab_entry *entry, krb5_kt_cursor *cursor); + +/** + * Release a keytab cursor. + * + * @param [in] context Library context + * @param [in] keytab Key table handle + * @param [out] cursor Cursor + * + * This function should be called to release the cursor created by + * krb5_kt_start_seq_get(). + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_end_seq_get(krb5_context context, krb5_keytab keytab, + krb5_kt_cursor *cursor); + +/** + * Check if a keytab exists and contains entries. + * + * @param [in] context Library context + * @param [in] keytab Key table handle + * + * @version New in 1.11 + * + * @retval 0 Keytab exists and contains entries + * @retval KRB5_KT_NOTFOUND Keytab does not contain entries + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_have_content(krb5_context context, krb5_keytab keytab); + +/* + * end "keytab.h" + */ + +/* + * begin "func-proto.h" + */ + +#define KRB5_INIT_CONTEXT_SECURE 0x1 /**< Use secure context configuration */ +#define KRB5_INIT_CONTEXT_KDC 0x2 /**< Use KDC configuration if available */ + +/** + * Create a krb5 library context. + * + * @param [out] context Library context + * + * The @a context must be released by calling krb5_free_context() when + * it is no longer needed. + * + * @warning Any program or module that needs the Kerberos code to not trust the + * environment must use krb5_init_secure_context(), or clean out the + * environment. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_init_context(krb5_context *context); + +/** + * Create a krb5 library context using only configuration files. + * + * @param [out] context Library context + * + * Create a context structure, using only system configuration files. All + * information passed through the environment variables is ignored. + * + * The @a context must be released by calling krb5_free_context() when + * it is no longer needed. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_init_secure_context(krb5_context *context); + +/** + * Create a krb5 library context using a specified profile. + * + * @param [in] profile Profile object (NULL to create default profile) + * @param [in] flags Context initialization flags + * @param [out] context Library context + * + * Create a context structure, optionally using a specified profile and + * initialization flags. If @a profile is NULL, the default profile will be + * created from config files. If @a profile is non-null, a copy of it will be + * made for the new context; the caller should still clean up its copy. Valid + * flag values are: + * + * @li #KRB5_INIT_CONTEXT_SECURE Ignore environment variables + * @li #KRB5_INIT_CONTEXT_KDC Use KDC configuration if creating profile + */ +krb5_error_code KRB5_CALLCONV +krb5_init_context_profile(struct _profile_t *profile, krb5_flags flags, + krb5_context *context); + +/** + * Free a krb5 library context. + * + * @param [in] context Library context + * + * This function frees a @a context that was created by krb5_init_context() + * or krb5_init_secure_context(). + */ +void KRB5_CALLCONV +krb5_free_context(krb5_context context); + +/** + * Copy a krb5_context structure. + * + * @param [in] ctx Library context + * @param [out] nctx_out New context structure + * + * The newly created context must be released by calling krb5_free_context() + * when it is no longer needed. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_context(krb5_context ctx, krb5_context *nctx_out); + +/** + * Set default TGS encryption types in a krb5_context structure. + * + * @param [in] context Library context + * @param [in] etypes Encryption type(s) to set + * + * This function sets the default enctype list for TGS requests + * made using @a context to @a etypes. + * + * @note This overrides the default list (from config file or built-in). + * + * @retval + * 0 Success + * @retval + * KRB5_PROG_ETYPE_NOSUPP Program lacks support for encryption type + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_set_default_tgs_enctypes(krb5_context context, const krb5_enctype *etypes); + +/** + * Return a list of encryption types permitted for session keys. + * + * @param [in] context Library context + * @param [out] ktypes Zero-terminated list of encryption types + * + * This function returns the list of encryption types permitted for session + * keys within @a context, as determined by configuration or by a previous call + * to krb5_set_default_tgs_enctypes(). + * + * Use krb5_free_enctypes() to free @a ktypes when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes); + +/** + * Test whether the Kerberos library was built with multithread support. + * + * @retval + * TRUE if the library is threadsafe; FALSE otherwise + */ +krb5_boolean KRB5_CALLCONV +krb5_is_thread_safe(void); + +/* libkrb.spec */ + +/** + * Decrypt a ticket using the specified key table. + * + * @param [in] context Library context + * @param [in] kt Key table + * @param [in] ticket Ticket to be decrypted + * + * This function takes a @a ticket as input and decrypts it using + * key data from @a kt. The result is placed into @a ticket->enc_part2. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_server_decrypt_ticket_keytab(krb5_context context, const krb5_keytab kt, + krb5_ticket *ticket); + +/** + * Free an array of credential structures. + * + * @param [in] context Library context + * @param [in] tgts Null-terminated array of credentials to free + * + * @note The last entry in the array @a tgts must be a NULL pointer. + */ +void KRB5_CALLCONV +krb5_free_tgt_creds(krb5_context context, krb5_creds **tgts); + +#define KRB5_GC_USER_USER 1 /**< Want user-user ticket */ +#define KRB5_GC_CACHED 2 /**< Want cached ticket only */ +#define KRB5_GC_CANONICALIZE 4 /**< Set canonicalize KDC option */ +#define KRB5_GC_NO_STORE 8 /**< Do not store in credential cache */ +#define KRB5_GC_FORWARDABLE 16 /**< Acquire forwardable tickets */ +#define KRB5_GC_NO_TRANSIT_CHECK 32 /**< Disable transited check */ +#define KRB5_GC_CONSTRAINED_DELEGATION 64 /**< Constrained delegation */ + +/** + * Get an additional ticket. + * + * @param [in] context Library context + * @param [in] options Options + * @param [in] ccache Credential cache handle + * @param [in] in_creds Input credentials + * @param [out] out_creds Output updated credentials + * + * Use @a ccache or a TGS exchange to get a service ticket matching @a + * in_creds. + * + * Valid values for @a options are: + * @li #KRB5_GC_CACHED Search only credential cache for the ticket + * @li #KRB5_GC_USER_USER Return a user to user authentication ticket + * + * @a in_creds must be non-null. @a in_creds->client and @a in_creds->server + * must be filled in to specify the client and the server respectively. If any + * authorization data needs to be requested for the service ticket (such as + * restrictions on how the ticket can be used), specify it in @a + * in_creds->authdata; otherwise set @a in_creds->authdata to NULL. The + * session key type is specified in @a in_creds->keyblock.enctype, if it is + * nonzero. + * + * The expiration date is specified in @a in_creds->times.endtime. + * The KDC may return tickets with an earlier expiration date. + * If @a in_creds->times.endtime is set to 0, the latest possible + * expiration date will be requested. + * + * Any returned ticket and intermediate ticket-granting tickets are stored + * in @a ccache. + * + * Use krb5_free_creds() to free @a out_creds when it is no longer needed. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_get_credentials(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_creds **out_creds); + +/** + * Serialize a @c krb5_creds object. + * + * @param [in] context Library context + * @param [in] in_creds The credentials object to serialize + * @param [out] data_out The serialized credentials + * + * Serialize @a creds in the format used by the FILE ccache format (vesion 4) + * and KCM ccache protocol. + * + * Use krb5_free_data() to free @a data_out when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_marshal_credentials(krb5_context context, krb5_creds *in_creds, + krb5_data **data_out); + +/** + * Deserialize a @c krb5_creds object. + * + * @param [in] context Library context + * @param [in] data The serialized credentials + * @param [out] creds_out The resulting creds object + * + * Deserialize @a data to credentials in the format used by the FILE ccache + * format (vesion 4) and KCM ccache protocol. + * + * Use krb5_free_creds() to free @a creds_out when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_unmarshal_credentials(krb5_context context, const krb5_data *data, + krb5_creds **creds_out); + +/** @deprecated Replaced by krb5_get_validated_creds. */ +krb5_error_code KRB5_CALLCONV +krb5_get_credentials_validate(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_creds **out_creds); + +/** @deprecated Replaced by krb5_get_renewed_creds. */ +krb5_error_code KRB5_CALLCONV +krb5_get_credentials_renew(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_creds **out_creds); + +/** + * Create a @c KRB_AP_REQ message. + * + * @param [in] context Library context + * @param [in,out] auth_context Pre-existing or newly created auth context + * @param [in] ap_req_options Options (see AP_OPTS macros) + * @param [in] service Service name, or NULL to use @c "host" + * @param [in] hostname Host name, or NULL to use local hostname + * @param [in] in_data Application data to be checksummed in the + * authenticator, or NULL + * @param [in] ccache Credential cache used to obtain credentials + * for the desired service. + * @param [out] outbuf @c AP-REQ message + * + * This function is similar to krb5_mk_req_extended() except that it uses a + * given @a hostname, @a service, and @a ccache to construct a service + * principal name and obtain credentials. + * + * Use krb5_free_data_contents() to free @a outbuf when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_mk_req(krb5_context context, krb5_auth_context *auth_context, + krb5_flags ap_req_options, const char *service, + const char *hostname, krb5_data *in_data, krb5_ccache ccache, + krb5_data *outbuf); + +/** + * Create a @c KRB_AP_REQ message using supplied credentials. + * + * @param [in] context Library context + * @param [in,out] auth_context Pre-existing or newly created auth context + * @param [in] ap_req_options Options (see AP_OPTS macros) + * @param [in] in_data Application data to be checksummed in the + * authenticator, or NULL + * @param [in] in_creds Credentials for the service with valid ticket + * and key + * @param [out] outbuf @c AP-REQ message + * + * Valid @a ap_req_options are: + * @li #AP_OPTS_USE_SESSION_KEY - Use the session key when creating the + * request used for user to user + * authentication. + * @li #AP_OPTS_MUTUAL_REQUIRED - Request a mutual authentication packet from + * the receiver. + * @li #AP_OPTS_USE_SUBKEY - Generate a subsession key from the current + * session key obtained from the credentials. + * + * This function creates a KRB_AP_REQ message using supplied credentials @a + * in_creds. @a auth_context may point to an existing auth context or to NULL, + * in which case a new one will be created. If @a in_data is non-null, a + * checksum of it will be included in the authenticator contained in the + * KRB_AP_REQ message. Use krb5_free_data_contents() to free @a outbuf when it + * is no longer needed. + * + * On successful return, the authenticator is stored in @a auth_context with + * the @a client and @a checksum fields nulled out. (This is to prevent + * pointer-sharing problems; the caller should not need these fields anyway, + * since the caller supplied them.) + * + * @sa krb5_mk_req() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context, + krb5_flags ap_req_options, krb5_data *in_data, + krb5_creds *in_creds, krb5_data *outbuf); + +/** + * Format and encrypt a @c KRB_AP_REP message. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [out] outbuf @c AP-REP message + * + * This function fills in @a outbuf with an AP-REP message using information + * from @a auth_context. + * + * If the flags in @a auth_context indicate that a sequence number should be + * used (either #KRB5_AUTH_CONTEXT_DO_SEQUENCE or + * #KRB5_AUTH_CONTEXT_RET_SEQUENCE) and the local sequence number in @a + * auth_context is 0, a new number will be generated with + * krb5_generate_seq_number(). + * + * Use krb5_free_data_contents() to free @a outbuf when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_mk_rep(krb5_context context, krb5_auth_context auth_context, krb5_data *outbuf); + +/** + * Format and encrypt a @c KRB_AP_REP message for DCE RPC. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [out] outbuf @c AP-REP message + * + * Use krb5_free_data_contents() to free @a outbuf when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_mk_rep_dce(krb5_context context, krb5_auth_context auth_context, krb5_data *outbuf); + +/** + * Parse and decrypt a @c KRB_AP_REP message. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] inbuf AP-REP message + * @param [out] repl Decrypted reply message + * + * This function parses, decrypts and verifies a message from @a inbuf and + * fills in @a repl with a pointer to allocated memory containing the fields + * from the encrypted response. + * + * Use krb5_free_ap_rep_enc_part() to free @a repl when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_rd_rep(krb5_context context, krb5_auth_context auth_context, + const krb5_data *inbuf, krb5_ap_rep_enc_part **repl); + +/** + * Parse and decrypt a @c KRB_AP_REP message for DCE RPC. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] inbuf AP-REP message + * @param [out] nonce Sequence number from the decrypted reply + * + * This function parses, decrypts and verifies a message from @a inbuf and + * fills in @a nonce with a decrypted reply sequence number. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_rd_rep_dce(krb5_context context, krb5_auth_context auth_context, + const krb5_data *inbuf, krb5_ui_4 *nonce); + +/** + * Format and encode a @c KRB_ERROR message. + * + * @param [in] context Library context + * @param [in] dec_err Error structure to be encoded + * @param [out] enc_err Encoded error structure + * + * This function creates a @c KRB_ERROR message in @a enc_err. Use + * krb5_free_data_contents() to free @a enc_err when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_mk_error(krb5_context context, const krb5_error *dec_err, + krb5_data *enc_err); + +/** + * Decode a @c KRB-ERROR message. + * + * @param [in] context Library context + * @param [in] enc_errbuf Encoded error message + * @param [out] dec_error Decoded error message + * + * This function processes @c KRB-ERROR message @a enc_errbuf and returns + * an allocated structure @a dec_error containing the error message. + * Use krb5_free_error() to free @a dec_error when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_rd_error(krb5_context context, const krb5_data *enc_errbuf, + krb5_error **dec_error); + +/** + * Process @c KRB-SAFE message. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] inbuf @c KRB-SAFE message to be parsed + * @param [out] userdata_out Data parsed from @c KRB-SAFE message + * @param [out] rdata_out Replay data. Specify NULL if not needed + * + * This function parses a @c KRB-SAFE message, verifies its integrity, and + * stores its data into @a userdata_out. + * + * @note The @a rdata_out argument is required if the + * #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set + * in @a auth_context. + * + * If @a auth_context has a remote address set, the address will be used to + * verify the sender address in the KRB-SAFE message. If @a auth_context has a + * local address set, it will be used to verify the receiver address in the + * KRB-SAFE message if the message contains one. + * + * If the #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag is set in @a auth_context, the + * sequence number of the KRB-SAFE message is checked against the remote + * sequence number field of @a auth_context. Otherwise, the sequence number is + * not used. + * + * If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in @a auth_context, then the + * timestamp in the message is verified to be within the permitted clock skew + * of the current time, and the message is checked against an in-memory replay + * cache to detect reflections or replays. + * + * Use krb5_free_data_contents() to free @a userdata_out when it is no longer + * needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, + const krb5_data *inbuf, krb5_data *userdata_out, + krb5_replay_data *rdata_out); + +/** + * Process a @c KRB-PRIV message. + * + * @param [in] context Library context + * @param [in] auth_context Authentication structure + * @param [in] inbuf @c KRB-PRIV message to be parsed + * @param [out] userdata_out Data parsed from @c KRB-PRIV message + * @param [out] rdata_out Replay data. Specify NULL if not needed + * + * This function parses a @c KRB-PRIV message, verifies its integrity, and + * stores its unencrypted data into @a userdata_out. + * + * @note The @a rdata_out argument is required if the + * #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set + * in @a auth_context. + * + * If @a auth_context has a remote address set, the address will be used to + * verify the sender address in the KRB-PRIV message. If @a auth_context has a + * local address set, it will be used to verify the receiver address in the + * KRB-PRIV message if the message contains one. + * + * If the #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag is set in @a auth_context, the + * sequence number of the KRB-PRIV message is checked against the remote + * sequence number field of @a auth_context. Otherwise, the sequence number is + * not used. + * + * If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in @a auth_context, then the + * timestamp in the message is verified to be within the permitted clock skew + * of the current time, and the message is checked against an in-memory replay + * cache to detect reflections or replays. + * + * Use krb5_free_data_contents() to free @a userdata_out when it is no longer + * needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_rd_priv(krb5_context context, krb5_auth_context auth_context, + const krb5_data *inbuf, krb5_data *userdata_out, + krb5_replay_data *rdata_out); + +/** + * Convert a string principal name to a krb5_principal structure. + * + * @param [in] context Library context + * @param [in] name String representation of a principal name + * @param [out] principal_out New principal + * + * Convert a string representation of a principal name to a krb5_principal + * structure. + * + * A string representation of a Kerberos name consists of one or more principal + * name components, separated by slashes, optionally followed by the \@ + * character and a realm name. If the realm name is not specified, the local + * realm is used. + * + * To use the slash and \@ symbols as part of a component (quoted) instead of + * using them as a component separator or as a realm prefix), put a backslash + * (\) character in front of the symbol. Similarly, newline, tab, backspace, + * and NULL characters can be included in a component by using @c n, @c t, @c b + * or @c 0, respectively. + * + * @note The realm in a Kerberos @a name cannot contain slash, colon, + * or NULL characters. + * + * Beginning with release 1.20, the name type of the principal will be inferred + * as @c KRB5_NT_SRV_INST or @c KRB5_NT_WELLKNOWN based on the principal name. + * The type will be @c KRB5_NT_PRINCIPAL if a type cannot be inferred. + * + * Use krb5_free_principal() to free @a principal_out when it is no longer + * needed. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_parse_name(krb5_context context, const char *name, + krb5_principal *principal_out); + +#define KRB5_PRINCIPAL_PARSE_NO_REALM 0x1 /**< Error if realm is present */ +#define KRB5_PRINCIPAL_PARSE_REQUIRE_REALM 0x2 /**< Error if realm is not present */ +#define KRB5_PRINCIPAL_PARSE_ENTERPRISE 0x4 /**< Create single-component + enterprise principle */ +#define KRB5_PRINCIPAL_PARSE_IGNORE_REALM 0x8 /**< Ignore realm if present */ +#define KRB5_PRINCIPAL_PARSE_NO_DEF_REALM 0x10 /**< Don't add default realm */ + +/** + * Convert a string principal name to a krb5_principal with flags. + * + * @param [in] context Library context + * @param [in] name String representation of a principal name + * @param [in] flags Flag + * @param [out] principal_out New principal + * + * Similar to krb5_parse_name(), this function converts a single-string + * representation of a principal name to a krb5_principal structure. + * + * The following flags are valid: + * @li #KRB5_PRINCIPAL_PARSE_NO_REALM - no realm must be present in @a name + * @li #KRB5_PRINCIPAL_PARSE_REQUIRE_REALM - realm must be present in @a name + * @li #KRB5_PRINCIPAL_PARSE_ENTERPRISE - create single-component enterprise + * principal + * @li #KRB5_PRINCIPAL_PARSE_IGNORE_REALM - ignore realm if present in @a name + * + * If @c KRB5_PRINCIPAL_PARSE_NO_REALM or @c KRB5_PRINCIPAL_PARSE_IGNORE_REALM + * is specified in @a flags, the realm of the new principal will be empty. + * Otherwise, the default realm for @a context will be used if @a name does not + * specify a realm. + * + * Use krb5_free_principal() to free @a principal_out when it is no longer + * needed. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_parse_name_flags(krb5_context context, const char *name, + int flags, krb5_principal *principal_out); + +/** + * Convert a krb5_principal structure to a string representation. + * + * @param [in] context Library context + * @param [in] principal Principal + * @param [out] name String representation of principal name + * + * The resulting string representation uses the format and quoting conventions + * described for krb5_parse_name(). + * + * Use krb5_free_unparsed_name() to free @a name when it is no longer needed. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_unparse_name(krb5_context context, krb5_const_principal principal, + char **name); + +/** + * Convert krb5_principal structure to string and length. + * + * @param [in] context Library context + * @param [in] principal Principal + * @param [in,out] name String representation of principal name + * @param [in,out] size Size of unparsed name + * + * This function is similar to krb5_unparse_name(), but allows the use of an + * existing buffer for the result. If size is not NULL, then @a name must + * point to either NULL or an existing buffer of at least the size pointed to + * by @a size. The buffer will be allocated or resized if necessary, with the + * new pointer stored into @a name. Whether or not the buffer is resized, the + * necessary space for the result, including null terminator, will be stored + * into @a size. + * + * If size is NULL, this function behaves exactly as krb5_unparse_name(). + * + * @retval + * 0 Success + * @return + * Kerberos error codes. On failure @a name is set to NULL + */ +krb5_error_code KRB5_CALLCONV +krb5_unparse_name_ext(krb5_context context, krb5_const_principal principal, + char **name, unsigned int *size); + +#define KRB5_PRINCIPAL_UNPARSE_SHORT 0x1 /**< Omit realm if it is the local realm */ +#define KRB5_PRINCIPAL_UNPARSE_NO_REALM 0x2 /**< Omit realm always */ +#define KRB5_PRINCIPAL_UNPARSE_DISPLAY 0x4 /**< Don't escape special characters */ + +/** + * Convert krb5_principal structure to a string with flags. + * + * @param [in] context Library context + * @param [in] principal Principal + * @param [in] flags Flags + * @param [out] name String representation of principal name + * + * Similar to krb5_unparse_name(), this function converts a krb5_principal + * structure to a string representation. + * + * The following flags are valid: + * @li #KRB5_PRINCIPAL_UNPARSE_SHORT - omit realm if it is the local realm + * @li #KRB5_PRINCIPAL_UNPARSE_NO_REALM - omit realm + * @li #KRB5_PRINCIPAL_UNPARSE_DISPLAY - do not quote special characters + * + * Use krb5_free_unparsed_name() to free @a name when it is no longer needed. + * + * @retval + * 0 Success + * @return + * Kerberos error codes. On failure @a name is set to NULL + */ +krb5_error_code KRB5_CALLCONV +krb5_unparse_name_flags(krb5_context context, krb5_const_principal principal, + int flags, char **name); + +/** + * Convert krb5_principal structure to string format with flags. + * + * @param [in] context Library context + * @param [in] principal Principal + * @param [in] flags Flags + * @param [out] name Single string format of principal name + * @param [out] size Size of unparsed name buffer + * + * @sa krb5_unparse_name() krb5_unparse_name_flags() krb5_unparse_name_ext() + * + * @retval + * 0 Success + * @return + * Kerberos error codes. On failure @a name is set to NULL + */ +krb5_error_code KRB5_CALLCONV +krb5_unparse_name_flags_ext(krb5_context context, krb5_const_principal principal, + int flags, char **name, unsigned int *size); + +/** + * Set the realm field of a principal + * + * @param [in] context Library context + * @param [in] principal Principal name + * @param [in] realm Realm name + * + * Set the realm name part of @a principal to @a realm, overwriting the + * previous realm. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_set_principal_realm(krb5_context context, krb5_principal principal, + const char *realm); + +/** + * Search a list of addresses for a specified address. + * + * @param [in] context Library context + * @param [in] addr Address to search for + * @param [in] addrlist Address list to be searched (or NULL) + * + * @note If @a addrlist contains only a NetBIOS addresses, it will be treated + * as a null list. + * + * @return + * TRUE if @a addr is listed in @a addrlist, or @c addrlist is NULL; FALSE + * otherwise + */ +krb5_boolean KRB5_CALLCONV_WRONG +krb5_address_search(krb5_context context, const krb5_address *addr, + krb5_address *const *addrlist); + +/** + * Compare two Kerberos addresses. + * + * @param [in] context Library context + * @param [in] addr1 First address to be compared + * @param [in] addr2 Second address to be compared + * + * @return + * TRUE if the addresses are the same, FALSE otherwise + */ +krb5_boolean KRB5_CALLCONV +krb5_address_compare(krb5_context context, const krb5_address *addr1, + const krb5_address *addr2); + +/** + * Return an ordering of the specified addresses. + * + * @param [in] context Library context + * @param [in] addr1 First address + * @param [in] addr2 Second address + * + * @retval 0 if The two addresses are the same + * @retval < 0 First address is less than second + * @retval > 0 First address is greater than second + */ +int KRB5_CALLCONV +krb5_address_order(krb5_context context, const krb5_address *addr1, + const krb5_address *addr2); + +/** + * Compare the realms of two principals. + * + * @param [in] context Library context + * @param [in] princ1 First principal + * @param [in] princ2 Second principal + * + * @retval + * TRUE if the realm names are the same; FALSE otherwise + */ +krb5_boolean KRB5_CALLCONV +krb5_realm_compare(krb5_context context, krb5_const_principal princ1, + krb5_const_principal princ2); + +/** + * Compare two principals. + * + * @param [in] context Library context + * @param [in] princ1 First principal + * @param [in] princ2 Second principal + * + * @retval + * TRUE if the principals are the same; FALSE otherwise + */ +krb5_boolean KRB5_CALLCONV +krb5_principal_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2); + +/** + * Compare two principals ignoring realm components. + * + * @param [in] context Library context + * @param [in] princ1 First principal + * @param [in] princ2 Second principal + * + * Similar to krb5_principal_compare(), but do not compare the realm + * components of the principals. + * + * @retval + * TRUE if the principals are the same; FALSE otherwise + */ +krb5_boolean KRB5_CALLCONV +krb5_principal_compare_any_realm(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2); + +#define KRB5_PRINCIPAL_COMPARE_IGNORE_REALM 1 /**< ignore realm component */ +#define KRB5_PRINCIPAL_COMPARE_ENTERPRISE 2 /**< UPNs as real principals */ +#define KRB5_PRINCIPAL_COMPARE_CASEFOLD 4 /**< case-insensitive */ +#define KRB5_PRINCIPAL_COMPARE_UTF8 8 /**< treat principals as UTF-8 */ + +/** + * Compare two principals with additional flags. + * + * @param [in] context Library context + * @param [in] princ1 First principal + * @param [in] princ2 Second principal + * @param [in] flags Flags + * + * Valid flags are: + * @li #KRB5_PRINCIPAL_COMPARE_IGNORE_REALM - ignore realm component + * @li #KRB5_PRINCIPAL_COMPARE_ENTERPRISE - UPNs as real principals + * @li #KRB5_PRINCIPAL_COMPARE_CASEFOLD case-insensitive + * @li #KRB5_PRINCIPAL_COMPARE_UTF8 - treat principals as UTF-8 + * + * @sa krb5_principal_compare() + * + * @retval + * TRUE if the principal names are the same; FALSE otherwise + */ +krb5_boolean KRB5_CALLCONV +krb5_principal_compare_flags(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2, + int flags); + +/** + * Initialize an empty @c krb5_keyblock. + * + * @param [in] context Library context + * @param [in] enctype Encryption type + * @param [in] length Length of keyblock (or 0) + * @param [out] out New keyblock structure + * + * Initialize a new keyblock and allocate storage for the contents of the key. + * It is legal to pass in a length of 0, in which case contents are left + * unallocated. Use krb5_free_keyblock() to free @a out when it is no longer + * needed. + * + * @note If @a length is set to 0, contents are left unallocated. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_init_keyblock(krb5_context context, krb5_enctype enctype, + size_t length, krb5_keyblock **out); + +/** + * Copy a keyblock. + * + * @param [in] context Library context + * @param [in] from Keyblock to be copied + * @param [out] to Copy of keyblock @a from + * + * This function creates a new keyblock with the same contents as @a from. Use + * krb5_free_keyblock() to free @a to when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_keyblock(krb5_context context, const krb5_keyblock *from, + krb5_keyblock **to); + +/** + * Copy the contents of a keyblock. + * + * @param [in] context Library context + * @param [in] from Key to be copied + * @param [out] to Output key + * + * This function copies the contents of @a from to @a to. Use + * krb5_free_keyblock_contents() to free @a to when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_keyblock_contents(krb5_context context, const krb5_keyblock *from, + krb5_keyblock *to); + +/** + * Copy a krb5_creds structure. + * + * @param [in] context Library context + * @param [in] incred Credentials structure to be copied + * @param [out] outcred Copy of @a incred + * + * This function creates a new credential with the contents of @a incred. Use + * krb5_free_creds() to free @a outcred when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_creds(krb5_context context, const krb5_creds *incred, krb5_creds **outcred); + +/** + * Copy a krb5_data object. + * + * @param [in] context Library context + * @param [in] indata Data object to be copied + * @param [out] outdata Copy of @a indata + * + * This function creates a new krb5_data object with the contents of @a indata. + * Use krb5_free_data() to free @a outdata when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_data(krb5_context context, const krb5_data *indata, krb5_data **outdata); + +/** + * Copy a principal. + * + * @param [in] context Library context + * @param [in] inprinc Principal to be copied + * @param [out] outprinc Copy of @a inprinc + * + * This function creates a new principal structure with the contents of @a + * inprinc. Use krb5_free_principal() to free @a outprinc when it is no longer + * needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_principal(krb5_context context, krb5_const_principal inprinc, + krb5_principal *outprinc); + +/** + * Copy an array of addresses. + * + * @param [in] context Library context + * @param [in] inaddr Array of addresses to be copied + * @param [out] outaddr Copy of array of addresses + * + * This function creates a new address array containing a copy of @a inaddr. + * Use krb5_free_addresses() to free @a outaddr when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_addresses(krb5_context context, krb5_address *const *inaddr, + krb5_address ***outaddr); + +/** + * Copy a krb5_ticket structure. + * + * @param [in] context Library context + * @param [in] from Ticket to be copied + * @param [out] pto Copy of ticket + * + * This function creates a new krb5_ticket structure containing the contents of + * @a from. Use krb5_free_ticket() to free @a pto when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_ticket(krb5_context context, const krb5_ticket *from, krb5_ticket **pto); + +/** + * Copy an authorization data list. + * + * @param [in] context Library context + * @param [in] in_authdat List of @a krb5_authdata structures + * @param [out] out New array of @a krb5_authdata structures + * + * This function creates a new authorization data list containing a copy of @a + * in_authdat, which must be null-terminated. Use krb5_free_authdata() to free + * @a out when it is no longer needed. + * + * @note The last array entry in @a in_authdat must be a NULL pointer. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_authdata(krb5_context context, + krb5_authdata *const *in_authdat, krb5_authdata ***out); + +/** + * Find authorization data elements. + * + * @param [in] context Library context + * @param [in] ticket_authdata Authorization data list from ticket + * @param [in] ap_req_authdata Authorization data list from AP request + * @param [in] ad_type Authorization data type to find + * @param [out] results List of matching entries + * + * This function searches @a ticket_authdata and @a ap_req_authdata for + * elements of type @a ad_type. Either input list may be NULL, in which case + * it will not be searched; otherwise, the input lists must be terminated by + * NULL entries. This function will search inside AD-IF-RELEVANT containers if + * found in either list. Use krb5_free_authdata() to free @a results when it + * is no longer needed. + * + * @version New in 1.10 + */ +krb5_error_code KRB5_CALLCONV +krb5_find_authdata(krb5_context context, krb5_authdata *const *ticket_authdata, + krb5_authdata *const *ap_req_authdata, + krb5_authdatatype ad_type, krb5_authdata ***results); + +/** + * Merge two authorization data lists into a new list. + * + * @param [in] context Library context + * @param [in] inauthdat1 First list of @a krb5_authdata structures + * @param [in] inauthdat2 Second list of @a krb5_authdata structures + * @param [out] outauthdat Merged list of @a krb5_authdata structures + * + * Merge two authdata arrays, such as the array from a ticket + * and authenticator. + * Use krb5_free_authdata() to free @a outauthdat when it is no longer needed. + * + * @note The last array entry in @a inauthdat1 and @a inauthdat2 + * must be a NULL pointer. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_merge_authdata(krb5_context context, + krb5_authdata *const *inauthdat1, + krb5_authdata * const *inauthdat2, + krb5_authdata ***outauthdat); + +/** + * Copy a krb5_authenticator structure. + * + * @param [in] context Library context + * @param [in] authfrom krb5_authenticator structure to be copied + * @param [out] authto Copy of krb5_authenticator structure + * + * This function creates a new krb5_authenticator structure with the content of + * @a authfrom. Use krb5_free_authenticator() to free @a authto when it is no + * longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_authenticator(krb5_context context, const krb5_authenticator *authfrom, + krb5_authenticator **authto); + +/** + * Copy a krb5_checksum structure. + * + * @param [in] context Library context + * @param [in] ckfrom Checksum to be copied + * @param [out] ckto Copy of krb5_checksum structure + * + * This function creates a new krb5_checksum structure with the contents of @a + * ckfrom. Use krb5_free_checksum() to free @a ckto when it is no longer + * needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_checksum(krb5_context context, const krb5_checksum *ckfrom, + krb5_checksum **ckto); + +/** + * Generate a replay cache object for server use and open it. + * + * @param [in] context Library context + * @param [in] piece Unused (replay cache identifier) + * @param [out] rcptr Handle to an open rcache + * + * This function creates a handle to the default replay cache. Use + * krb5_rc_close() to close @a rcptr when it is no longer needed. + * + * @version Prior to release 1.18, this function creates a handle to a + * different replay cache for each unique value of @a piece. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_get_server_rcache(krb5_context context, const krb5_data *piece, + krb5_rcache *rcptr); + +/** + * Build a principal name using length-counted strings. + * + * @param [in] context Library context + * @param [out] princ Principal name + * @param [in] rlen Realm name length + * @param [in] realm Realm name + * @param [in] ... List of unsigned int/char * components, followed by 0 + * + * This function creates a principal from a length-counted string and a + * variable-length list of length-counted components. The list of components + * ends with the first 0 length argument (so it is not possible to specify an + * empty component with this function). Call krb5_free_principal() to free + * allocated memory for principal when it is no longer needed. + * + * Beginning with release 1.20, the name type of the principal will be inferred + * as @c KRB5_NT_SRV_INST or @c KRB5_NT_WELLKNOWN based on the principal name. + * The type will be @c KRB5_NT_PRINCIPAL if a type cannot be inferred. + * + * @code + * Example of how to build principal WELLKNOWN/ANONYMOUS@R + * krb5_build_principal_ext(context, &principal, strlen("R"), "R", + * (unsigned int)strlen(KRB5_WELLKNOWN_NAMESTR), + * KRB5_WELLKNOWN_NAMESTR, + * (unsigned int)strlen(KRB5_ANONYMOUS_PRINCSTR), + * KRB5_ANONYMOUS_PRINCSTR, 0); + * @endcode + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV_C +krb5_build_principal_ext(krb5_context context, krb5_principal * princ, + unsigned int rlen, const char * realm, ...); + +/** + * Build a principal name using null-terminated strings. + * + * @param [in] context Library context + * @param [out] princ Principal name + * @param [in] rlen Realm name length + * @param [in] realm Realm name + * @param [in] ... List of char * components, ending with NULL + * + * Call krb5_free_principal() to free @a princ when it is no longer needed. + * + * Beginning with release 1.20, the name type of the principal will be inferred + * as @c KRB5_NT_SRV_INST or @c KRB5_NT_WELLKNOWN based on the principal name. + * The type will be @c KRB5_NT_PRINCIPAL if a type cannot be inferred. + * + * @note krb5_build_principal() and krb5_build_principal_alloc_va() perform the + * same task. krb5_build_principal() takes variadic arguments. + * krb5_build_principal_alloc_va() takes a pre-computed @a varargs pointer. + * + * @code + * Example of how to build principal H/S@R + * krb5_build_principal(context, &principal, + * strlen("R"), "R", "H", "S", (char*)NULL); + * @endcode + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV_C +krb5_build_principal(krb5_context context, + krb5_principal * princ, + unsigned int rlen, + const char * realm, ...) +#if __GNUC__ >= 4 + __attribute__ ((sentinel)) +#endif + ; +#if KRB5_DEPRECATED +/** @deprecated Replaced by krb5_build_principal_alloc_va(). */ +KRB5_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV +krb5_build_principal_va(krb5_context context, + krb5_principal princ, + unsigned int rlen, + const char *realm, + va_list ap); +#endif + +/** + * Build a principal name, using a precomputed variable argument list + * + * @param [in] context Library context + * @param [out] princ Principal structure + * @param [in] rlen Realm name length + * @param [in] realm Realm name + * @param [in] ap List of char * components, ending with NULL + * + * Similar to krb5_build_principal(), this function builds a principal name, + * but its name components are specified as a va_list. + * + * Use krb5_free_principal() to deallocate @a princ when it is no longer + * needed. + * + * @code + * Function usage example: + * va_list ap; + * va_start(ap, realm); + * krb5_build_principal_alloc_va(context, princ, rlen, realm, ap); + * va_end(ap); + * @endcode + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_build_principal_alloc_va(krb5_context context, + krb5_principal *princ, + unsigned int rlen, + const char *realm, + va_list ap); + +/** + * Convert a Kerberos V4 principal to a Kerberos V5 principal. + * + * @param [in] context Library context + * @param [in] name V4 name + * @param [in] instance V4 instance + * @param [in] realm Realm + * @param [out] princ V5 principal + * + * This function builds a @a princ from V4 specification based on given input + * @a name.instance\@realm. + * + * Use krb5_free_principal() to free @a princ when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_425_conv_principal(krb5_context context, const char *name, + const char *instance, const char *realm, + krb5_principal *princ); + +/** + * Convert a Kerberos V5 principal to a Kerberos V4 principal. + * + * @param [in] context Library context + * @param [in] princ V5 Principal + * @param [out] name V4 principal's name to be filled in + * @param [out] inst V4 principal's instance name to be filled in + * @param [out] realm Principal's realm name to be filled in + * + * This function separates a V5 principal @a princ into @a name, @a instance, + * and @a realm. + * + * @retval + * 0 Success + * @retval + * KRB5_INVALID_PRINCIPAL Invalid principal name + * @retval + * KRB5_CONFIG_CANTOPEN Can't open or find Kerberos configuration file + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_524_conv_principal(krb5_context context, krb5_const_principal princ, + char *name, char *inst, char *realm); +/** + *@deprecated + */ +struct credentials; + +/** + * Convert a Kerberos V5 credentials to a Kerberos V4 credentials + * + * @note Not implemented + * + * @retval KRB524_KRB4_DISABLED (always) + */ +int KRB5_CALLCONV +krb5_524_convert_creds(krb5_context context, krb5_creds *v5creds, + struct credentials *v4creds); + +#if KRB5_DEPRECATED +#define krb524_convert_creds_kdc krb5_524_convert_creds +#define krb524_init_ets(x) (0) +#endif + +/* libkt.spec */ + +/** + * Get a handle for a key table. + * + * @param [in] context Library context + * @param [in] name Name of the key table + * @param [out] ktid Key table handle + * + * Resolve the key table name @a name and set @a ktid to a handle identifying + * the key table. Use krb5_kt_close() to free @a ktid when it is no longer + * needed. + * + * @a name must be of the form @c type:residual, where @a type must be a type + * known to the library and @a residual portion should be specific to the + * particular keytab type. If no @a type is given, the default is @c FILE. + * + * If @a name is of type @c FILE, the keytab file is not opened by this call. + * + * @code + * Example: krb5_kt_resolve(context, "FILE:/tmp/filename", &ktid); + * @endcode + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_resolve(krb5_context context, const char *name, krb5_keytab *ktid); + +/** + * Duplicate keytab handle. + * + * @param [in] context Library context + * @param [in] in Key table handle to be duplicated + * @param [out] out Key table handle + * + * Create a new handle referring to the same key table as @a in. The new + * handle and @a in can be closed independently. + * + * @version New in 1.12 + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_dup(krb5_context context, krb5_keytab in, krb5_keytab *out); + +/** + * Get the default key table name. + * + * @param [in] context Library context + * @param [out] name Default key table name + * @param [in] name_size Space available in @a name + * + * Fill @a name with the name of the default key table for @a context. + * + * @sa MAX_KEYTAB_NAME_LEN + * + * @retval + * 0 Success + * @retval + * KRB5_CONFIG_NOTENUFSPACE Buffer is too short + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_default_name(krb5_context context, char *name, int name_size); + +/** + * Resolve the default key table. + * + * @param [in] context Library context + * @param [out] id Key table handle + * + * Set @a id to a handle to the default key table. The key table is not + * opened. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_default(krb5_context context, krb5_keytab *id); + +/** + * Resolve the default client key table. + * + * @param [in] context Library context + * @param [out] keytab_out Key table handle + * + * Fill @a keytab_out with a handle to the default client key table. + * + * @version New in 1.11 + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_client_default(krb5_context context, krb5_keytab *keytab_out); + +/** + * Free the contents of a key table entry. + * + * @param [in] context Library context + * @param [in] entry Key table entry whose contents are to be freed + * + * @note The pointer is not freed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_free_keytab_entry_contents(krb5_context context, krb5_keytab_entry *entry); + +/** @deprecated Use krb5_free_keytab_entry_contents instead. */ +krb5_error_code KRB5_CALLCONV +krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *entry); + + +/* remove and add are functions, so that they can return NOWRITE + if not a writable keytab */ + +/** + * Remove an entry from a key table. + * + * @param [in] context Library context + * @param [in] id Key table handle + * @param [in] entry Entry to remove from key table + * + * @retval + * 0 Success + * @retval + * KRB5_KT_NOWRITE Key table is not writable + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_remove_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry); + +/** + * Add a new entry to a key table. + * + * @param [in] context Library context + * @param [in] id Key table handle + * @param [in] entry Entry to be added + * + * @retval + * 0 Success + * @retval + * ENOMEM Insufficient memory + * @retval + * KRB5_KT_NOWRITE Key table is not writeable + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_add_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry); + +/** + * Convert a principal name into the default salt for that principal. + * + * @param [in] context Library context + * @param [in] pr Principal name + * @param [out] ret Default salt for @a pr to be filled in + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV_WRONG +krb5_principal2salt(krb5_context context, + krb5_const_principal pr, krb5_data *ret); +/* librc.spec--see rcache.h */ + +/* libcc.spec */ + +/** + * Resolve a credential cache name. + * + * @param [in] context Library context + * @param [in] name Credential cache name to be resolved + * @param [out] cache Credential cache handle + * + * Fills in @a cache with a @a cache handle that corresponds to the name in @a + * name. @a name should be of the form @c type:residual, and @a type must be a + * type known to the library. If the @a name does not contain a colon, + * interpret it as a file name. + * + * @code + * Example: krb5_cc_resolve(context, "MEMORY:C_", &cache); + * @endcode + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_resolve(krb5_context context, const char *name, krb5_ccache *cache); + +/** + * Duplicate ccache handle. + * + * @param [in] context Library context + * @param [in] in Credential cache handle to be duplicated + * @param [out] out Credential cache handle + * + * Create a new handle referring to the same cache as @a in. + * The new handle and @a in can be closed independently. + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_dup(krb5_context context, krb5_ccache in, krb5_ccache *out); + +/** + * Return the name of the default credential cache. + * + * @param [in] context Library context + * + * Return a pointer to the default credential cache name for @a context, as + * determined by a prior call to krb5_cc_set_default_name(), by the KRB5CCNAME + * environment variable, by the default_ccache_name profile variable, or by the + * operating system or build-time default value. The returned value must not + * be modified or freed by the caller. The returned value becomes invalid when + * @a context is destroyed krb5_free_context() or if a subsequent call to + * krb5_cc_set_default_name() is made on @a context. + * + * The default credential cache name is cached in @a context between calls to + * this function, so if the value of KRB5CCNAME changes in the process + * environment after the first call to this function on, that change will not + * be reflected in later calls with the same context. The caller can invoke + * krb5_cc_set_default_name() with a NULL value of @a name to clear the cached + * value and force the default name to be recomputed. + * + * @return + * Name of default credential cache for the current user. + */ +const char *KRB5_CALLCONV +krb5_cc_default_name(krb5_context context); + +/** + * Set the default credential cache name. + * + * @param [in] context Library context + * @param [in] name Default credential cache name or NULL + * + * Set the default credential cache name to @a name for future operations using + * @a context. If @a name is NULL, clear any previous application-set default + * name and forget any cached value of the default name for @a context. + * + * Calls to this function invalidate the result of any previous calls to + * krb5_cc_default_name() using @a context. + * + * @retval + * 0 Success + * @retval + * KV5M_CONTEXT Bad magic number for @c _krb5_context structure + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_set_default_name(krb5_context context, const char *name); + +/** + * Resolve the default credential cache name. + * + * @param [in] context Library context + * @param [out] ccache Pointer to credential cache name + * + * Create a handle to the default credential cache as given by + * krb5_cc_default_name(). + * + * @retval + * 0 Success + * @retval + * KV5M_CONTEXT Bad magic number for @c _krb5_context structure + * @retval + * KRB5_FCC_INTERNAL The name of the default credential cache cannot be + * obtained + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_default(krb5_context context, krb5_ccache *ccache); + +/** + * Copy a credential cache. + * + * @param [in] context Library context + * @param [in] incc Credential cache to be copied + * @param [out] outcc Copy of credential cache to be filled in + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_copy_creds(krb5_context context, krb5_ccache incc, krb5_ccache outcc); + +/** + * Get a configuration value from a credential cache. + * + * @param [in] context Library context + * @param [in] id Credential cache handle + * @param [in] principal Configuration for this principal; + * if NULL, global for the whole cache + * @param [in] key Name of config variable + * @param [out] data Data to be fetched + * + * Use krb5_free_data_contents() to free @a data when it is no longer needed. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_get_config(krb5_context context, krb5_ccache id, + krb5_const_principal principal, + const char *key, krb5_data *data); + +/** + * Store a configuration value in a credential cache. + * + * @param [in] context Library context + * @param [in] id Credential cache handle + * @param [in] principal Configuration for a specific principal; + * if NULL, global for the whole cache + * @param [in] key Name of config variable + * @param [in] data Data to store, or NULL to remove + * + * @note Existing configuration under the same key is over-written. + * + * @warning Before version 1.10 @a data was assumed to be always non-null. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_set_config(krb5_context context, krb5_ccache id, + krb5_const_principal principal, + const char *key, krb5_data *data); + +/** + * Test whether a principal is a configuration principal. + * + * @param [in] context Library context + * @param [in] principal Principal to check + * + * @return + * @c TRUE if the principal is a configuration principal (generated part of + * krb5_cc_set_config()); @c FALSE otherwise. + */ +krb5_boolean KRB5_CALLCONV +krb5_is_config_principal(krb5_context context, krb5_const_principal principal); + +/** + * Make a credential cache the primary cache for its collection. + * + * @param [in] context Library context + * @param [in] cache Credential cache handle + * + * If the type of @a cache supports it, set @a cache to be the primary + * credential cache for the collection it belongs to. + * + * @retval + * 0 Success, or the type of @a cache doesn't support switching + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_switch(krb5_context context, krb5_ccache cache); + +/** + * Determine whether a credential cache type supports switching. + * + * @param [in] context Library context + * @param [in] type Credential cache type + * + * @version New in 1.10 + * + * @retval TRUE if @a type supports switching + * @retval FALSE if it does not or is not a valid credential cache type. + */ +krb5_boolean KRB5_CALLCONV +krb5_cc_support_switch(krb5_context context, const char *type); + +/** + * Find a credential cache with a specified client principal. + * + * @param [in] context Library context + * @param [in] client Client principal + * @param [out] cache_out Credential cache handle + * + * Find a cache within the collection whose default principal is @a client. + * Use @a krb5_cc_close to close @a ccache when it is no longer needed. + * + * @retval 0 Success + * @retval KRB5_CC_NOTFOUND + * + * @sa krb5_cccol_cursor_new + * + * @version New in 1.10 + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_cache_match(krb5_context context, krb5_principal client, + krb5_ccache *cache_out); + +/** + * Select a credential cache to use with a server principal. + * + * @param [in] context Library context + * @param [in] server Server principal + * @param [out] cache_out Credential cache handle + * @param [out] princ_out Client principal + * + * Select a cache within the collection containing credentials most appropriate + * for use with @a server, according to configured rules and heuristics. + * + * Use krb5_cc_close() to release @a cache_out when it is no longer needed. + * Use krb5_free_principal() to release @a princ_out when it is no longer + * needed. Note that @a princ_out is set in some error conditions. + * + * @return + * If an appropriate cache is found, 0 is returned, @a cache_out is set to the + * selected cache, and @a princ_out is set to the default principal of that + * cache. + * + * If the appropriate client principal can be authoritatively determined but + * the cache collection contains no credentials for that principal, then + * KRB5_CC_NOTFOUND is returned, @a cache_out is set to NULL, and @a princ_out + * is set to the appropriate client principal. + * + * If no configured mechanism can determine the appropriate cache or principal, + * KRB5_CC_NOTFOUND is returned and @a cache_out and @a princ_out are set to + * NULL. + * + * Any other error code indicates a fatal error in the processing of a cache + * selection mechanism. + * + * @version New in 1.10 + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_select(krb5_context context, krb5_principal server, + krb5_ccache *cache_out, krb5_principal *princ_out); + +/* krb5_free.c */ +/** + * Free the storage assigned to a principal. + * + * @param [in] context Library context + * @param [in] val Principal to be freed + */ +void KRB5_CALLCONV +krb5_free_principal(krb5_context context, krb5_principal val); + +/** + * Free a krb5_authenticator structure. + * + * @param [in] context Library context + * @param [in] val Authenticator structure to be freed + * + * This function frees the contents of @a val and the structure itself. + */ +void KRB5_CALLCONV +krb5_free_authenticator(krb5_context context, krb5_authenticator *val); + +/** + * Free the data stored in array of addresses. + * + * @param [in] context Library context + * @param [in] val Array of addresses to be freed + * + * This function frees the contents of @a val and the array itself. + * + * @note The last entry in the array must be a NULL pointer. + */ +void KRB5_CALLCONV +krb5_free_addresses(krb5_context context, krb5_address **val); + +/** + * Free the storage assigned to array of authentication data. + * + * @param [in] context Library context + * @param [in] val Array of authentication data to be freed + * + * This function frees the contents of @a val and the array itself. + * + * @note The last entry in the array must be a NULL pointer. + */ +void KRB5_CALLCONV +krb5_free_authdata(krb5_context context, krb5_authdata **val); + +/** + * Free a ticket. + * + * @param [in] context Library context + * @param [in] val Ticket to be freed + * + * This function frees the contents of @a val and the structure itself. + */ +void KRB5_CALLCONV +krb5_free_ticket(krb5_context context, krb5_ticket *val); + +/** + * Free an error allocated by krb5_read_error() or krb5_sendauth(). + * + * @param [in] context Library context + * @param [in] val Error data structure to be freed + * + * This function frees the contents of @a val and the structure itself. + */ +void KRB5_CALLCONV +krb5_free_error(krb5_context context, krb5_error *val); + +/** + * Free a krb5_creds structure. + * + * @param [in] context Library context + * @param [in] val Credential structure to be freed. + * + * This function frees the contents of @a val and the structure itself. + */ +void KRB5_CALLCONV +krb5_free_creds(krb5_context context, krb5_creds *val); + +/** + * Free the contents of a krb5_creds structure. + * + * @param [in] context Library context + * @param [in] val Credential structure to free contents of + * + * This function frees the contents of @a val, but not the structure itself. + */ +void KRB5_CALLCONV +krb5_free_cred_contents(krb5_context context, krb5_creds *val); + +/** + * Free a krb5_checksum structure. + * + * @param [in] context Library context + * @param [in] val Checksum structure to be freed + * + * This function frees the contents of @a val and the structure itself. + */ +void KRB5_CALLCONV +krb5_free_checksum(krb5_context context, krb5_checksum *val); + +/** + * Free the contents of a krb5_checksum structure. + * + * @param [in] context Library context + * @param [in] val Checksum structure to free contents of + * + * This function frees the contents of @a val, but not the structure itself. + * It sets the checksum's data pointer to null and (beginning in release 1.19) + * sets its length to zero. + */ +void KRB5_CALLCONV +krb5_free_checksum_contents(krb5_context context, krb5_checksum *val); + +/** + * Free a krb5_keyblock structure. + * + * @param [in] context Library context + * @param [in] val Keyblock to be freed + * + * This function frees the contents of @a val and the structure itself. + */ +void KRB5_CALLCONV +krb5_free_keyblock(krb5_context context, krb5_keyblock *val); + +/** + * Free the contents of a krb5_keyblock structure. + * + * @param [in] context Library context + * @param [in] key Keyblock to be freed + * + * This function frees the contents of @a key, but not the structure itself. + */ +void KRB5_CALLCONV +krb5_free_keyblock_contents(krb5_context context, krb5_keyblock *key); + +/** + * Free a krb5_ap_rep_enc_part structure. + * + * @param [in] context Library context + * @param [in] val AP-REP enc part to be freed + * + * This function frees the contents of @a val and the structure itself. + */ +void KRB5_CALLCONV +krb5_free_ap_rep_enc_part(krb5_context context, krb5_ap_rep_enc_part *val); + +/** + * Free a krb5_data structure. + * + * @param [in] context Library context + * @param [in] val Data structure to be freed + * + * This function frees the contents of @a val and the structure itself. + */ +void KRB5_CALLCONV +krb5_free_data(krb5_context context, krb5_data *val); + +/* Free a krb5_octet_data structure (should be unused). */ +void KRB5_CALLCONV +krb5_free_octet_data(krb5_context context, krb5_octet_data *val); + +/** + * Free the contents of a krb5_data structure and zero the data field. + * + * @param [in] context Library context + * @param [in] val Data structure to free contents of + * + * This function frees the contents of @a val, but not the structure itself. + * It sets the structure's data pointer to null and (beginning in release 1.19) + * sets its length to zero. + */ +void KRB5_CALLCONV +krb5_free_data_contents(krb5_context context, krb5_data *val); + +/** + * Free a string representation of a principal. + * + * @param [in] context Library context + * @param [in] val Name string to be freed + */ +void KRB5_CALLCONV +krb5_free_unparsed_name(krb5_context context, char *val); + +/** + * Free a string allocated by a krb5 function. + * + * @param [in] context Library context + * @param [in] val String to be freed + * + * @version New in 1.10 + */ +void KRB5_CALLCONV +krb5_free_string(krb5_context context, char *val); + +/** + * Free an array of encryption types. + * + * @param [in] context Library context + * @param [in] val Array of enctypes to be freed + * + * @version New in 1.12 + */ +void KRB5_CALLCONV +krb5_free_enctypes(krb5_context context, krb5_enctype *val); + +/** + * Free an array of checksum types. + * + * @param [in] context Library context + * @param [in] val Array of checksum types to be freed + */ +void KRB5_CALLCONV +krb5_free_cksumtypes(krb5_context context, krb5_cksumtype *val); + +/* From krb5/os, but needed by the outside world */ +/** + * Retrieve the system time of day, in sec and ms, since the epoch. + * + * @param [in] context Library context + * @param [out] seconds System timeofday, seconds portion + * @param [out] microseconds System timeofday, microseconds portion + * + * This function retrieves the system time of day with the context + * specific time offset adjustment. + * + * @sa krb5_crypto_us_timeofday() + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_us_timeofday(krb5_context context, + krb5_timestamp *seconds, krb5_int32 *microseconds); + +/** + * Retrieve the current time with context specific time offset adjustment. + * + * @param [in] context Library context + * @param [out] timeret Timestamp to fill in + * + * This function retrieves the system time of day with the context specific + * time offset adjustment. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_timeofday(krb5_context context, krb5_timestamp *timeret); + +/** + * Check if a timestamp is within the allowed clock skew of the current time. + * + * @param [in] context Library context + * @param [in] date Timestamp to check + * + * This function checks if @a date is close enough to the current time + * according to the configured allowable clock skew. + * + * @version New in 1.10 + * + * @retval 0 Success + * @retval KRB5KRB_AP_ERR_SKEW @a date is not within allowable clock skew + */ +krb5_error_code KRB5_CALLCONV +krb5_check_clockskew(krb5_context context, krb5_timestamp date); + +/** + * Return all interface addresses for this host. + * + * @param [in] context Library context + * @param [out] addr Array of krb5_address pointers, ending with + * NULL + * + * Use krb5_free_addresses() to free @a addr when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_os_localaddr(krb5_context context, krb5_address ***addr); + +/** + * Retrieve the default realm. + * + * @param [in] context Library context + * @param [out] lrealm Default realm name + * + * Retrieves the default realm to be used if no user-specified realm is + * available. + * + * Use krb5_free_default_realm() to free @a lrealm when it is no longer needed. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_get_default_realm(krb5_context context, char **lrealm); + +/** + * Override the default realm for the specified context. + * + * @param [in] context Library context + * @param [in] lrealm Realm name for the default realm + * + * If @a lrealm is NULL, clear the default realm setting. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_set_default_realm(krb5_context context, const char *lrealm); + +/** + * Free a default realm string returned by krb5_get_default_realm(). + * + * @param [in] context Library context + * @param [in] lrealm Realm to be freed + */ +void KRB5_CALLCONV +krb5_free_default_realm(krb5_context context, char *lrealm); + +/** + * Canonicalize a hostname, possibly using name service. + * + * @param [in] context Library context + * @param [in] host Input hostname + * @param [out] canonhost_out Canonicalized hostname + * + * This function canonicalizes orig_hostname, possibly using name service + * lookups if configuration permits. Use krb5_free_string() to free @a + * canonhost_out when it is no longer needed. + * + * @version New in 1.15 + */ +krb5_error_code KRB5_CALLCONV +krb5_expand_hostname(krb5_context context, const char *host, + char **canonhost_out); + +/** + * Generate a full principal name from a service name. + * + * @param [in] context Library context + * @param [in] hostname Host name, or NULL to use local host + * @param [in] sname Service name, or NULL to use @c "host" + * @param [in] type Principal type + * @param [out] ret_princ Generated principal + * + * This function converts a @a hostname and @a sname into @a krb5_principal + * structure @a ret_princ. The returned principal will be of the form @a + * sname\/hostname\@REALM where REALM is determined by krb5_get_host_realm(). + * In some cases this may be the referral (empty) realm. + * + * The @a type can be one of the following: + * + * @li #KRB5_NT_SRV_HST canonicalizes the host name before looking up the + * realm and generating the principal. + * + * @li #KRB5_NT_UNKNOWN accepts the hostname as given, and does not + * canonicalize it. + * + * Use krb5_free_principal to free @a ret_princ when it is no longer needed. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_sname_to_principal(krb5_context context, const char *hostname, const char *sname, + krb5_int32 type, krb5_principal *ret_princ); + +/** + * Test whether a principal matches a matching principal. + * + * @param [in] context Library context + * @param [in] matching Matching principal + * @param [in] princ Principal to test + * + * @note A matching principal is a host-based principal with an empty realm + * and/or second data component (hostname). Profile configuration may cause + * the hostname to be ignored even if it is present. A principal matches a + * matching principal if the former has the same non-empty (and non-ignored) + * components of the latter. + * + * If @a matching is NULL, return TRUE. If @a matching is not a matching + * principal, return the value of krb5_principal_compare(context, matching, + * princ). + * + * @return + * TRUE if @a princ matches @a matching, FALSE otherwise. + */ +krb5_boolean KRB5_CALLCONV +krb5_sname_match(krb5_context context, krb5_const_principal matching, + krb5_const_principal princ); + +/** + * Change a password for an existing Kerberos account. + * + * @param [in] context Library context + * @param [in] creds Credentials for kadmin/changepw service + * @param [in] newpw New password + * @param [out] result_code Numeric error code from server + * @param [out] result_code_string String equivalent to @a result_code + * @param [out] result_string Change password response from the KDC + * + * Change the password for the existing principal identified by @a creds. + * + * The possible values of the output @a result_code are: + * + * @li #KRB5_KPASSWD_SUCCESS (0) - success + * @li #KRB5_KPASSWD_MALFORMED (1) - Malformed request error + * @li #KRB5_KPASSWD_HARDERROR (2) - Server error + * @li #KRB5_KPASSWD_AUTHERROR (3) - Authentication error + * @li #KRB5_KPASSWD_SOFTERROR (4) - Password change rejected + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_change_password(krb5_context context, krb5_creds *creds, + const char *newpw, int *result_code, + krb5_data *result_code_string, krb5_data *result_string); + +/** + * Set a password for a principal using specified credentials. + * + * @param [in] context Library context + * @param [in] creds Credentials for kadmin/changepw service + * @param [in] newpw New password + * @param [in] change_password_for Change the password for this principal + * @param [out] result_code Numeric error code from server + * @param [out] result_code_string String equivalent to @a result_code + * @param [out] result_string Data returned from the remote system + * + * This function uses the credentials @a creds to set the password @a newpw for + * the principal @a change_password_for. It implements the set password + * operation of RFC 3244, for interoperability with Microsoft Windows + * implementations. + * + * @note If @a change_password_for is NULL, the change is performed on the + * current principal. If @a change_password_for is non-null, the change is + * performed on the principal name passed in @a change_password_for. + * + * The error code and strings are returned in @a result_code, + * @a result_code_string and @a result_string. + * + * @sa krb5_set_password_using_ccache() + * + * @retval + * 0 Success and result_code is set to #KRB5_KPASSWD_SUCCESS. + * @return + * Kerberos error codes. + */ +krb5_error_code KRB5_CALLCONV +krb5_set_password(krb5_context context, krb5_creds *creds, const char *newpw, + krb5_principal change_password_for, int *result_code, + krb5_data *result_code_string, krb5_data *result_string); + +/** + * Set a password for a principal using cached credentials. + * + * @param [in] context Library context + * @param [in] ccache Credential cache + * @param [in] newpw New password + * @param [in] change_password_for Change the password for this principal + * @param [out] result_code Numeric error code from server + * @param [out] result_code_string String equivalent to @a result_code + * @param [out] result_string Data returned from the remote system + * + * This function uses the cached credentials from @a ccache to set the password + * @a newpw for the principal @a change_password_for. It implements RFC 3244 + * set password operation (interoperable with MS Windows implementations) using + * the credential cache. + * + * The error code and strings are returned in @a result_code, + * @a result_code_string and @a result_string. + * + * @note If @a change_password_for is set to NULL, the change is performed on + * the default principal in @a ccache. If @a change_password_for is non null, + * the change is performed on the specified principal. + * + * @sa krb5_set_password() + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_set_password_using_ccache(krb5_context context, krb5_ccache ccache, + const char *newpw, + krb5_principal change_password_for, + int *result_code, krb5_data *result_code_string, + krb5_data *result_string); + +/** + * Get a result message for changing or setting a password. + * + * @param [in] context Library context + * @param [in] server_string Data returned from the remote system + * @param [out] message_out A message displayable to the user + * + * This function processes the @a server_string returned in the @a + * result_string parameter of krb5_change_password(), krb5_set_password(), and + * related functions, and returns a displayable string. If @a server_string + * contains Active Directory structured policy information, it will be + * converted into human-readable text. + * + * Use krb5_free_string() to free @a message_out when it is no longer needed. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + * + * @version New in 1.11 + */ +krb5_error_code KRB5_CALLCONV +krb5_chpw_message(krb5_context context, const krb5_data *server_string, + char **message_out); + +/** + * Retrieve configuration profile from the context. + * + * @param [in] context Library context + * @param [out] profile Pointer to data read from a configuration file + * + * This function creates a new @a profile object that reflects profile + * in the supplied @a context. + * + * The @a profile object may be freed with profile_release() function. + * See profile.h and profile API for more details. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_get_profile(krb5_context context, struct _profile_t ** profile); + +#if KRB5_DEPRECATED +/** @deprecated Replaced by krb5_get_init_creds_password().*/ +KRB5_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV +krb5_get_in_tkt_with_password(krb5_context context, krb5_flags options, + krb5_address *const *addrs, krb5_enctype *ktypes, + krb5_preauthtype *pre_auth_types, + const char *password, krb5_ccache ccache, + krb5_creds *creds, krb5_kdc_rep **ret_as_reply); + +/** @deprecated Replaced by krb5_get_init_creds(). */ +KRB5_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV +krb5_get_in_tkt_with_skey(krb5_context context, krb5_flags options, + krb5_address *const *addrs, krb5_enctype *ktypes, + krb5_preauthtype *pre_auth_types, + const krb5_keyblock *key, krb5_ccache ccache, + krb5_creds *creds, krb5_kdc_rep **ret_as_reply); + +/** @deprecated Replaced by krb5_get_init_creds_keytab(). */ +KRB5_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV +krb5_get_in_tkt_with_keytab(krb5_context context, krb5_flags options, + krb5_address *const *addrs, krb5_enctype *ktypes, + krb5_preauthtype *pre_auth_types, + krb5_keytab arg_keytab, krb5_ccache ccache, + krb5_creds *creds, krb5_kdc_rep **ret_as_reply); + +#endif /* KRB5_DEPRECATED */ + +/** + * Parse and decrypt a @c KRB_AP_REQ message. + * + * @param [in] context Library context + * @param [in,out] auth_context Pre-existing or newly created auth context + * @param [in] inbuf AP-REQ message to be parsed + * @param [in] server Matching principal for server, or NULL to + * allow any principal in keytab + * @param [in] keytab Key table, or NULL to use the default + * @param [out] ap_req_options If non-null, the AP-REQ flags on output + * @param [out] ticket If non-null, ticket from the AP-REQ message + * + * This function parses, decrypts and verifies a AP-REQ message from @a inbuf + * and stores the authenticator in @a auth_context. + * + * If a keyblock was specified in @a auth_context using + * krb5_auth_con_setuseruserkey(), that key is used to decrypt the ticket in + * AP-REQ message and @a keytab is ignored. In this case, @a server should be + * specified as a complete principal name to allow for proper transited-path + * checking and replay cache selection. + * + * Otherwise, the decryption key is obtained from @a keytab, or from the + * default keytab if it is NULL. In this case, @a server may be a complete + * principal name, a matching principal (see krb5_sname_match()), or NULL to + * match any principal name. The keys tried against the encrypted part of the + * ticket are determined as follows: + * + * - If @a server is a complete principal name, then its entry in @a keytab is + * tried. + * - Otherwise, if @a keytab is iterable, then all entries in @a keytab which + * match @a server are tried. + * - Otherwise, the server principal in the ticket must match @a server, and + * its entry in @a keytab is tried. + * + * The client specified in the decrypted authenticator must match the client + * specified in the decrypted ticket. + * + * If the @a remote_addr field of @a auth_context is set, the request must come + * from that address. + * + * If a replay cache handle is provided in the @a auth_context, the + * authenticator and ticket are verified against it. If no conflict is found, + * the new authenticator is then stored in the replay cache of @a auth_context. + * + * Various other checks are performed on the decoded data, including + * cross-realm policy, clockskew, and ticket validation times. + * + * On success the authenticator, subkey, and remote sequence number of the + * request are stored in @a auth_context. If the #AP_OPTS_MUTUAL_REQUIRED + * bit is set, the local sequence number is XORed with the remote sequence + * number in the request. + * + * Use krb5_free_ticket() to free @a ticket when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_rd_req(krb5_context context, krb5_auth_context *auth_context, + const krb5_data *inbuf, krb5_const_principal server, + krb5_keytab keytab, krb5_flags *ap_req_options, + krb5_ticket **ticket); + +/** + * Retrieve a service key from a key table. + * + * @param [in] context Library context + * @param [in] keyprocarg Name of a key table (NULL to use default name) + * @param [in] principal Service principal + * @param [in] vno Key version number (0 for highest available) + * @param [in] enctype Encryption type (0 for any type) + * @param [out] key Service key from key table + * + * Open and search the specified key table for the entry identified by @a + * principal, @a enctype, and @a vno. If no key is found, return an error code. + * + * The default key table is used, unless @a keyprocarg is non-null. + * @a keyprocarg designates a specific key table. + * + * Use krb5_free_keyblock() to free @a key when it is no longer needed. + * + * @retval + * 0 Success + * @return Kerberos error code if not found or @a keyprocarg is invalid. + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg, + krb5_principal principal, krb5_kvno vno, + krb5_enctype enctype, krb5_keyblock **key); + +/** + * Format a @c KRB-SAFE message. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] userdata User data in the message + * @param [out] der_out Formatted @c KRB-SAFE buffer + * @param [out] rdata_out Replay data. Specify NULL if not needed + * + * This function creates an integrity protected @c KRB-SAFE message + * using data supplied by the application. + * + * Fields in @a auth_context specify the checksum type, the keyblock that + * can be used to seed the checksum, full addresses (host and port) for + * the sender and receiver, and KRB5_AUTH_CONTEXT flags. + * + * The local address in @a auth_context must be set, and is used to form the + * sender address used in the KRB-SAFE message. The remote address is + * optional; if specified, it will be used to form the receiver address used in + * the message. + * + * @note The @a rdata_out argument is required if the + * #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set + * in @a auth_context. + * + * If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in @a auth_context, a + * timestamp is included in the KRB-SAFE message, and an entry for the message + * is entered in an in-memory replay cache to detect if the message is + * reflected by an attacker. If #KRB5_AUTH_CONTEXT_DO_TIME is not set, no + * replay cache is used. If #KRB5_AUTH_CONTEXT_RET_TIME is set in @a + * auth_context, a timestamp is included in the KRB-SAFE message and is stored + * in @a rdata_out. + * + * If either #KRB5_AUTH_CONTEXT_DO_SEQUENCE or #KRB5_AUTH_CONTEXT_RET_SEQUENCE + * is set, the @a auth_context local sequence number is included in the + * KRB-SAFE message and then incremented. If #KRB5_AUTH_CONTEXT_RET_SEQUENCE + * is set, the sequence number used is stored in @a rdata_out. + * + * Use krb5_free_data_contents() to free @a der_out when it is no longer + * needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_mk_safe(krb5_context context, krb5_auth_context auth_context, + const krb5_data *userdata, krb5_data *der_out, + krb5_replay_data *rdata_out); + +/** + * Format a @c KRB-PRIV message. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] userdata User data for @c KRB-PRIV message + * @param [out] der_out Formatted @c KRB-PRIV message + * @param [out] rdata_out Replay data (NULL if not needed) + * + * This function is similar to krb5_mk_safe(), but the message is encrypted and + * integrity-protected, not just integrity-protected. + * + * The local address in @a auth_context must be set, and is used to form the + * sender address used in the KRB-PRIV message. The remote address is + * optional; if specified, it will be used to form the receiver address used in + * the message. + * + * @note The @a rdata_out argument is required if the + * #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set + * in @a auth_context. + * + * If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in @a auth_context, a + * timestamp is included in the KRB-PRIV message, and an entry for the message + * is entered in an in-memory replay cache to detect if the message is + * reflected by an attacker. If #KRB5_AUTH_CONTEXT_DO_TIME is not set, no + * replay cache is used. If #KRB5_AUTH_CONTEXT_RET_TIME is set in @a + * auth_context, a timestamp is included in the KRB-PRIV message and is stored + * in @a rdata_out. + * + * If either #KRB5_AUTH_CONTEXT_DO_SEQUENCE or #KRB5_AUTH_CONTEXT_RET_SEQUENCE + * is set, the @a auth_context local sequence number is included in the + * KRB-PRIV message and then incremented. If #KRB5_AUTH_CONTEXT_RET_SEQUENCE + * is set, the sequence number used is stored in @a rdata_out. + * + * Use krb5_free_data_contents() to free @a der_out when it is no longer + * needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_mk_priv(krb5_context context, krb5_auth_context auth_context, + const krb5_data *userdata, krb5_data *der_out, + krb5_replay_data *rdata_out); + +/** + * Client function for @c sendauth protocol. + * + * @param [in] context Library context + * @param [in,out] auth_context Pre-existing or newly created auth context + * @param [in] fd File descriptor that describes network socket + * @param [in] appl_version Application protocol version to be matched + * with the receiver's application version + * @param [in] client Client principal + * @param [in] server Server principal + * @param [in] ap_req_options Options (see AP_OPTS macros) + * @param [in] in_data Data to be sent to the server + * @param [in] in_creds Input credentials, or NULL to use @a ccache + * @param [in] ccache Credential cache + * @param [out] error If non-null, contains KRB_ERROR message + * returned from server + * @param [out] rep_result If non-null and @a ap_req_options is + * #AP_OPTS_MUTUAL_REQUIRED, contains the result + * of mutual authentication exchange + * @param [out] out_creds If non-null, the retrieved credentials + * + * This function performs the client side of a sendauth/recvauth exchange by + * sending and receiving messages over @a fd. + * + * Credentials may be specified in three ways: + * + * @li If @a in_creds is NULL, credentials are obtained with + * krb5_get_credentials() using the principals @a client and @a server. @a + * server must be non-null; @a client may NULL to use the default principal of + * @a ccache. + * + * @li If @a in_creds is non-null, but does not contain a ticket, credentials + * for the exchange are obtained with krb5_get_credentials() using @a in_creds. + * In this case, the values of @a client and @a server are unused. + * + * @li If @a in_creds is a complete credentials structure, it used directly. + * In this case, the values of @a client, @a server, and @a ccache are unused. + * + * If the server is using a different application protocol than that specified + * in @a appl_version, an error will be returned. + * + * Use krb5_free_creds() to free @a out_creds, krb5_free_ap_rep_enc_part() to + * free @a rep_result, and krb5_free_error() to free @a error when they are no + * longer needed. + * + * @sa krb5_recvauth() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, + krb5_pointer fd, char *appl_version, krb5_principal client, + krb5_principal server, krb5_flags ap_req_options, + krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, + krb5_error **error, krb5_ap_rep_enc_part **rep_result, + krb5_creds **out_creds); + +/** + * Server function for @a sendauth protocol. + * + * @param [in] context Library context + * @param [in,out] auth_context Pre-existing or newly created auth context + * @param [in] fd File descriptor + * @param [in] appl_version Application protocol version to be matched + * against the client's application version + * @param [in] server Server principal (NULL for any in @a keytab) + * @param [in] flags Additional specifications + * @param [in] keytab Key table containing service keys + * @param [out] ticket Ticket (NULL if not needed) + * + * This function performs the server side of a sendauth/recvauth exchange by + * sending and receiving messages over @a fd. + * + * Use krb5_free_ticket() to free @a ticket when it is no longer needed. + * + * @sa krb5_sendauth() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_recvauth(krb5_context context, krb5_auth_context *auth_context, + krb5_pointer fd, char *appl_version, krb5_principal server, + krb5_int32 flags, krb5_keytab keytab, krb5_ticket **ticket); + +/** + * Server function for @a sendauth protocol with version parameter. + * + * @param [in] context Library context + * @param [in,out] auth_context Pre-existing or newly created auth context + * @param [in] fd File descriptor + * @param [in] server Server principal (NULL for any in @a keytab) + * @param [in] flags Additional specifications + * @param [in] keytab Decryption key + * @param [out] ticket Ticket (NULL if not needed) + * @param [out] version sendauth protocol version (NULL if not needed) + * + * This function is similar to krb5_recvauth() with the additional output + * information place into @a version. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_recvauth_version(krb5_context context, + krb5_auth_context *auth_context, + krb5_pointer fd, + krb5_principal server, + krb5_int32 flags, + krb5_keytab keytab, + krb5_ticket **ticket, + krb5_data *version); + +/** + * Format a @c KRB-CRED message for an array of credentials. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] creds Null-terminated array of credentials + * @param [out] der_out Encoded credentials + * @param [out] rdata_out Replay cache information (NULL if not needed) + * + * This function takes an array of credentials @a creds and formats + * a @c KRB-CRED message @a der_out to pass to krb5_rd_cred(). + * + * The local and remote addresses in @a auth_context are optional; if either is + * specified, they are used to form the sender and receiver addresses in the + * KRB-CRED message. + * + * @note The @a rdata_out argument is required if the + * #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set + * in @a auth_context. + * + * If the #KRB5_AUTH_CONTEXT_DO_TIME flag is set in @a auth_context, an entry + * for the message is entered in an in-memory replay cache to detect if the + * message is reflected by an attacker. If #KRB5_AUTH_CONTEXT_DO_TIME is not + * set, no replay cache is used. If #KRB5_AUTH_CONTEXT_RET_TIME is set in @a + * auth_context, the timestamp used for the KRB-CRED message is stored in @a + * rdata_out. + * + * If either #KRB5_AUTH_CONTEXT_DO_SEQUENCE or #KRB5_AUTH_CONTEXT_RET_SEQUENCE + * is set, the @a auth_context local sequence number is included in the + * KRB-CRED message and then incremented. If #KRB5_AUTH_CONTEXT_RET_SEQUENCE + * is set, the sequence number used is stored in @a rdata_out. + * + * Use krb5_free_data_contents() to free @a der_out when it is no longer + * needed. + * + * The message will be encrypted using the send subkey of @a auth_context if it + * is present, or the session key otherwise. If neither key is present, the + * credentials will not be encrypted, and the message should only be sent over + * a secure channel. No replay cache entry is used in this case. + * + * @retval + * 0 Success + * @retval + * ENOMEM Insufficient memory + * @retval + * KRB5_RC_REQUIRED Message replay detection requires @a rcache parameter + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, + krb5_creds **creds, krb5_data **der_out, + krb5_replay_data *rdata_out); + +/** + * Format a @c KRB-CRED message for a single set of credentials. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] creds Pointer to credentials + * @param [out] der_out Encoded credentials + * @param [out] rdata_out Replay cache data (NULL if not needed) + * + * This is a convenience function that calls krb5_mk_ncred() with a single set + * of credentials. + * + * @retval + * 0 Success + * @retval + * ENOMEM Insufficient memory + * @retval + * KRB5_RC_REQUIRED Message replay detection requires @a rcache parameter + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_mk_1cred(krb5_context context, krb5_auth_context auth_context, + krb5_creds *creds, krb5_data **der_out, + krb5_replay_data *rdata_out); + +/** + * Read and validate a @c KRB-CRED message. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] creddata @c KRB-CRED message + * @param [out] creds_out Null-terminated array of forwarded credentials + * @param [out] rdata_out Replay data (NULL if not needed) + * + * @note The @a rdata_out argument is required if the + * #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set + * in @a auth_context.` + * + * @a creddata will be decrypted using the receiving subkey if it is present in + * @a auth_context, or the session key if the receiving subkey is not present + * or fails to decrypt the message. + * + * Use krb5_free_tgt_creds() to free @a creds_out when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_rd_cred(krb5_context context, krb5_auth_context auth_context, + krb5_data *creddata, krb5_creds ***creds_out, + krb5_replay_data *rdata_out); + +/** + * Get a forwarded TGT and format a @c KRB-CRED message. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] rhost Remote host + * @param [in] client Client principal of TGT + * @param [in] server Principal of server to receive TGT + * @param [in] cc Credential cache handle (NULL to use default) + * @param [in] forwardable Whether TGT should be forwardable + * @param [out] outbuf KRB-CRED message + * + * Get a TGT for use at the remote host @a rhost and format it into a KRB-CRED + * message. If @a rhost is NULL and @a server is of type #KRB5_NT_SRV_HST, + * the second component of @a server will be used. + * + * @retval + * 0 Success + * @retval + * ENOMEM Insufficient memory + * @retval + * KRB5_PRINC_NOMATCH Requested principal and ticket do not match + * @retval + * KRB5_NO_TKT_SUPPLIED Request did not supply a ticket + * @retval + * KRB5_CC_BADNAME Credential cache name or principal name malformed + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, + const char *rhost, krb5_principal client, + krb5_principal server, krb5_ccache cc, int forwardable, + krb5_data *outbuf); + +/** + * Create and initialize an authentication context. + * + * @param [in] context Library context + * @param [out] auth_context Authentication context + * + * This function creates an authentication context to hold configuration and + * state relevant to krb5 functions for authenticating principals and + * protecting messages once authentication has occurred. + * + * By default, flags for the context are set to enable the use of the replay + * cache (#KRB5_AUTH_CONTEXT_DO_TIME), but not sequence numbers. Use + * krb5_auth_con_setflags() to change the flags. + * + * The allocated @a auth_context must be freed with krb5_auth_con_free() when + * it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_init(krb5_context context, krb5_auth_context *auth_context); + +/** + * Free a krb5_auth_context structure. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context to be freed + * + * This function frees an auth context allocated by krb5_auth_con_init(). + * + * @retval 0 (always) + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_free(krb5_context context, krb5_auth_context auth_context); + +/** + * Set a flags field in a krb5_auth_context structure. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] flags Flags bit mask + * + * Valid values for @a flags are: + * @li #KRB5_AUTH_CONTEXT_DO_TIME Use timestamps + * @li #KRB5_AUTH_CONTEXT_RET_TIME Save timestamps + * @li #KRB5_AUTH_CONTEXT_DO_SEQUENCE Use sequence numbers + * @li #KRB5_AUTH_CONTEXT_RET_SEQUENCE Save sequence numbers + * + * @retval 0 (always) + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 flags); + +/** + * Retrieve flags from a krb5_auth_context structure. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [out] flags Flags bit mask + * + * Valid values for @a flags are: + * @li #KRB5_AUTH_CONTEXT_DO_TIME Use timestamps + * @li #KRB5_AUTH_CONTEXT_RET_TIME Save timestamps + * @li #KRB5_AUTH_CONTEXT_DO_SEQUENCE Use sequence numbers + * @li #KRB5_AUTH_CONTEXT_RET_SEQUENCE Save sequence numbers + * + * @retval 0 (always) + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getflags(krb5_context context, krb5_auth_context auth_context, + krb5_int32 *flags); + +/** + * Set a checksum callback in an auth context. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] func Checksum callback + * @param [in] data Callback argument + * + * Set a callback to obtain checksum data in krb5_mk_req(). The callback will + * be invoked after the subkey and local sequence number are stored in @a + * auth_context. + * + * @retval 0 (always) + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_set_checksum_func( krb5_context context, + krb5_auth_context auth_context, + krb5_mk_req_checksum_func func, + void *data); + +/** + * Get the checksum callback from an auth context. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [out] func Checksum callback + * @param [out] data Callback argument + * + * @retval 0 (always) + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_get_checksum_func( krb5_context context, + krb5_auth_context auth_context, + krb5_mk_req_checksum_func *func, + void **data); + +/** + * Set the local and remote addresses in an auth context. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] local_addr Local address + * @param [in] remote_addr Remote address + * + * This function releases the storage assigned to the contents of the local and + * remote addresses of @a auth_context and then sets them to @a local_addr and + * @a remote_addr respectively. + * + * @sa krb5_auth_con_genaddrs() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV_WRONG +krb5_auth_con_setaddrs(krb5_context context, krb5_auth_context auth_context, + krb5_address *local_addr, krb5_address *remote_addr); + +/** + * Retrieve address fields from an auth context. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [out] local_addr Local address (NULL if not needed) + * @param [out] remote_addr Remote address (NULL if not needed) + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getaddrs(krb5_context context, krb5_auth_context auth_context, + krb5_address **local_addr, krb5_address **remote_addr); + +/** + * Set local and remote port fields in an auth context. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] local_port Local port + * @param [in] remote_port Remote port + * + * This function releases the storage assigned to the contents of the local and + * remote ports of @a auth_context and then sets them to @a local_port and @a + * remote_port respectively. + * + * @sa krb5_auth_con_genaddrs() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setports(krb5_context context, krb5_auth_context auth_context, + krb5_address *local_port, krb5_address *remote_port); + +/** + * Set the session key in an auth context. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] keyblock User key + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, + krb5_keyblock *keyblock); + +/** + * Retrieve the session key from an auth context as a keyblock. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [out] keyblock Session key + * + * This function creates a keyblock containing the session key from @a + * auth_context. Use krb5_free_keyblock() to free @a keyblock when it is no + * longer needed + * + * @retval 0 Success. Otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getkey(krb5_context context, krb5_auth_context auth_context, + krb5_keyblock **keyblock); + +/** + * Retrieve the session key from an auth context. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [out] key Session key + * + * This function sets @a key to the session key from @a auth_context. Use + * krb5_k_free_key() to release @a key when it is no longer needed. + * + * @retval 0 (always) + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getkey_k(krb5_context context, krb5_auth_context auth_context, + krb5_key *key); + +/** + * Retrieve the send subkey from an auth context as a keyblock. + * + * @param [in] ctx Library context + * @param [in] ac Authentication context + * @param [out] keyblock Send subkey + * + * This function creates a keyblock containing the send subkey from @a + * auth_context. Use krb5_free_keyblock() to free @a keyblock when it is no + * longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock); + +/** + * Retrieve the send subkey from an auth context. + * + * @param [in] ctx Library context + * @param [in] ac Authentication context + * @param [out] key Send subkey + * + * This function sets @a key to the send subkey from @a auth_context. Use + * krb5_k_free_key() to release @a key when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getsendsubkey_k(krb5_context ctx, krb5_auth_context ac, + krb5_key *key); + +/** + * Retrieve the receiving subkey from an auth context as a keyblock. + * + * @param [in] ctx Library context + * @param [in] ac Authentication context + * @param [out] keyblock Receiving subkey + * + * This function creates a keyblock containing the receiving subkey from @a + * auth_context. Use krb5_free_keyblock() to free @a keyblock when it is no + * longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock); + +/** + * Retrieve the receiving subkey from an auth context as a keyblock. + * + * @param [in] ctx Library context + * @param [in] ac Authentication context + * @param [out] key Receiving subkey + * + * This function sets @a key to the receiving subkey from @a auth_context. Use + * krb5_k_free_key() to release @a key when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getrecvsubkey_k(krb5_context ctx, krb5_auth_context ac, krb5_key *key); + +/** + * Set the send subkey in an auth context with a keyblock. + * + * @param [in] ctx Library context + * @param [in] ac Authentication context + * @param [in] keyblock Send subkey + * + * This function sets the send subkey in @a ac to a copy of @a keyblock. + * + * @retval 0 Success. Otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setsendsubkey(krb5_context ctx, krb5_auth_context ac, + krb5_keyblock *keyblock); + +/** + * Set the send subkey in an auth context. + * + * @param [in] ctx Library context + * @param [in] ac Authentication context + * @param [out] key Send subkey + * + * This function sets the send subkey in @a ac to @a key, incrementing its + * reference count. + * + * @version New in 1.9 + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setsendsubkey_k(krb5_context ctx, krb5_auth_context ac, krb5_key key); + +/** + * Set the receiving subkey in an auth context with a keyblock. + * + * @param [in] ctx Library context + * @param [in] ac Authentication context + * @param [in] keyblock Receiving subkey + * + * This function sets the receiving subkey in @a ac to a copy of @a keyblock. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setrecvsubkey(krb5_context ctx, krb5_auth_context ac, + krb5_keyblock *keyblock); + +/** + * Set the receiving subkey in an auth context. + * + * @param [in] ctx Library context + * @param [in] ac Authentication context + * @param [in] key Receiving subkey + * + * This function sets the receiving subkey in @a ac to @a key, incrementing its + * reference count. + * + * @version New in 1.9 + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setrecvsubkey_k(krb5_context ctx, krb5_auth_context ac, + krb5_key key); + +#if KRB5_DEPRECATED +/** @deprecated Replaced by krb5_auth_con_getsendsubkey(). */ +KRB5_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV +krb5_auth_con_getlocalsubkey(krb5_context context, krb5_auth_context auth_context, + krb5_keyblock **keyblock); + +/** @deprecated Replaced by krb5_auth_con_getrecvsubkey(). */ +KRB5_ATTR_DEPRECATED krb5_error_code KRB5_CALLCONV +krb5_auth_con_getremotesubkey(krb5_context context, krb5_auth_context auth_context, + krb5_keyblock **keyblock); +#endif + +/** + * Retrieve the local sequence number from an auth context. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [out] seqnumber Local sequence number + * + * Retrieve the local sequence number from @a auth_context and return it in @a + * seqnumber. The #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag must be set in @a + * auth_context for this function to be useful. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getlocalseqnumber(krb5_context context, krb5_auth_context auth_context, + krb5_int32 *seqnumber); + +/** + * Retrieve the remote sequence number from an auth context. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [out] seqnumber Remote sequence number + * + * Retrieve the remote sequence number from @a auth_context and return it in @a + * seqnumber. The #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag must be set in @a + * auth_context for this function to be useful. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getremoteseqnumber(krb5_context context, krb5_auth_context auth_context, + krb5_int32 *seqnumber); + +/** + * Cause an auth context to use cipher state. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * + * Prepare @a auth_context to use cipher state when krb5_mk_priv() or + * krb5_rd_priv() encrypt or decrypt data. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_initivector(krb5_context context, krb5_auth_context auth_context); + +/** + * Set the replay cache in an auth context. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] rcache Replay cache haddle + * + * This function sets the replay cache in @a auth_context to @a rcache. @a + * rcache will be closed when @a auth_context is freed, so the caller should + * relinquish that responsibility. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setrcache(krb5_context context, krb5_auth_context auth_context, + krb5_rcache rcache); + +/** + * Retrieve the replay cache from an auth context. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [out] rcache Replay cache handle + * + * This function fetches the replay cache from @a auth_context. The caller + * should not close @a rcache. + * + * @retval 0 (always) + */ +krb5_error_code KRB5_CALLCONV_WRONG +krb5_auth_con_getrcache(krb5_context context, krb5_auth_context auth_context, + krb5_rcache *rcache); + +/** + * Retrieve the authenticator from an auth context. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [out] authenticator Authenticator + * + * Use krb5_free_authenticator() to free @a authenticator when it is no longer + * needed. + * + * @retval 0 Success. Otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getauthenticator(krb5_context context, krb5_auth_context auth_context, + krb5_authenticator **authenticator); + +/** + * Set checksum type in an an auth context. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] cksumtype Checksum type + * + * This function sets the checksum type in @a auth_context to be used by + * krb5_mk_req() for the authenticator checksum. + * + * @retval 0 Success. Otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_set_req_cksumtype(krb5_context context, krb5_auth_context auth_context, + krb5_cksumtype cksumtype); + +#define KRB5_REALM_BRANCH_CHAR '.' + +/* + * end "func-proto.h" + */ + +/* + * begin stuff from libos.h + */ + +/** + * @brief Read a password from keyboard input. + * + * @param [in] context Library context + * @param [in] prompt First user prompt when reading password + * @param [in] prompt2 Second user prompt (NULL to prompt only once) + * @param [out] return_pwd Returned password + * @param [in,out] size_return On input, maximum size of password; on output, + * size of password read + * + * This function reads a password from keyboard input and stores it in @a + * return_pwd. @a size_return should be set by the caller to the amount of + * storage space available in @a return_pwd; on successful return, it will be + * set to the length of the password read. + * + * @a prompt is printed to the terminal, followed by ": ", and then a password + * is read from the keyboard. + * + * If @a prompt2 is NULL, the password is read only once. Otherwise, @a + * prompt2 is printed to the terminal and a second password is read. If the + * two passwords entered are not identical, KRB5_LIBOS_BADPWDMATCH is returned. + * + * Echoing is turned off when the password is read. + * + * @retval + * 0 Success + * @return + * Error in reading or verifying the password + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_read_password(krb5_context context, + const char *prompt, const char *prompt2, + char *return_pwd, unsigned int *size_return); + +/** + * Convert a principal name to a local name. + * + * @param [in] context Library context + * @param [in] aname Principal name + * @param [in] lnsize_in Space available in @a lname + * @param [out] lname Local name buffer to be filled in + * + * If @a aname does not correspond to any local account, KRB5_LNAME_NOTRANS is + * returned. If @a lnsize_in is too small for the local name, + * KRB5_CONFIG_NOTENUFSPACE is returned. + * + * Local names, rather than principal names, can be used by programs that + * translate to an environment-specific name (for example, a user account + * name). + * + * @retval + * 0 Success + * @retval + * System errors + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_aname_to_localname(krb5_context context, krb5_const_principal aname, + int lnsize_in, char *lname); + +/** + * Get the Kerberos realm names for a host. + * + * @param [in] context Library context + * @param [in] host Host name (or NULL) + * @param [out] realmsp Null-terminated list of realm names + * + * Fill in @a realmsp with a pointer to a null-terminated list of realm names. + * If there are no known realms for the host, a list containing the referral + * (empty) realm is returned. + * + * If @a host is NULL, the local host's realms are determined. + * + * Use krb5_free_host_realm() to release @a realmsp when it is no longer + * needed. + * + * @retval + * 0 Success + * @retval + * ENOMEM Insufficient memory + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_get_host_realm(krb5_context context, const char *host, char ***realmsp); + +/** + * + * @param [in] context Library context + * @param [in] hdata Host name (or NULL) + * @param [out] realmsp Null-terminated list of realm names + * + * Fill in @a realmsp with a pointer to a null-terminated list of realm names + * obtained through heuristics or insecure resolution methods which have lower + * priority than KDC referrals. + * + * If @a host is NULL, the local host's realms are determined. + * + * Use krb5_free_host_realm() to release @a realmsp when it is no longer + * needed. + */ +krb5_error_code KRB5_CALLCONV +krb5_get_fallback_host_realm(krb5_context context, + krb5_data *hdata, char ***realmsp); + +/** + * Free the memory allocated by krb5_get_host_realm(). + * + * @param [in] context Library context + * @param [in] realmlist List of realm names to be released + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_free_host_realm(krb5_context context, char *const *realmlist); + +/** + * Determine if a principal is authorized to log in as a local user. + * + * @param [in] context Library context + * @param [in] principal Principal name + * @param [in] luser Local username + * + * Determine whether @a principal is authorized to log in as a local user @a + * luser. + * + * @retval + * TRUE Principal is authorized to log in as user; FALSE otherwise. + */ +krb5_boolean KRB5_CALLCONV +krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser); + +/** + * Generate auth context addresses from a connected socket. + * + * @param [in] context Library context + * @param [in] auth_context Authentication context + * @param [in] infd Connected socket descriptor + * @param [in] flags Flags + * + * This function sets the local and/or remote addresses in @a auth_context + * based on the local and remote endpoints of the socket @a infd. The + * following flags determine the operations performed: + * + * @li #KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR Generate local address. + * @li #KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR Generate remote address. + * @li #KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR Generate local address and port. + * @li #KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR Generate remote address and port. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_genaddrs(krb5_context context, krb5_auth_context auth_context, + int infd, int flags); + +/** + * Set time offset field in a krb5_context structure. + * + * @param [in] context Library context + * @param [in] seconds Real time, seconds portion + * @param [in] microseconds Real time, microseconds portion + * + * This function sets the time offset in @a context to the difference between + * the system time and the real time as determined by @a seconds and @a + * microseconds. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_set_real_time(krb5_context context, krb5_timestamp seconds, + krb5_int32 microseconds); + +/** + * Return the time offsets from the os context. + * + * @param [in] context Library context + * @param [out] seconds Time offset, seconds portion + * @param [out] microseconds Time offset, microseconds portion + * + * This function returns the time offsets in @a context. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_get_time_offsets(krb5_context context, krb5_timestamp *seconds, krb5_int32 *microseconds); + +/* str_conv.c */ +/** + * Convert a string to an encryption type. + * + * @param [in] string String to convert to an encryption type + * @param [out] enctypep Encryption type + * + * @retval 0 Success; otherwise - EINVAL + */ +krb5_error_code KRB5_CALLCONV +krb5_string_to_enctype(char *string, krb5_enctype *enctypep); + +/** + * Convert a string to a salt type. + * + * @param [in] string String to convert to an encryption type + * @param [out] salttypep Salt type to be filled in + * + * @retval 0 Success; otherwise - EINVAL + */ +krb5_error_code KRB5_CALLCONV +krb5_string_to_salttype(char *string, krb5_int32 *salttypep); + +/** + * Convert a string to a checksum type. + * + * @param [in] string String to be converted + * @param [out] cksumtypep Checksum type to be filled in + * + * @retval 0 Success; otherwise - EINVAL + */ +krb5_error_code KRB5_CALLCONV +krb5_string_to_cksumtype(char *string, krb5_cksumtype *cksumtypep); + +/** + * Convert a string to a timestamp. + * + * @param [in] string String to be converted + * @param [out] timestampp Pointer to timestamp + * + * @retval 0 Success; otherwise - EINVAL + */ +krb5_error_code KRB5_CALLCONV +krb5_string_to_timestamp(char *string, krb5_timestamp *timestampp); + +/** + * Convert a string to a delta time value. + * + * @param [in] string String to be converted + * @param [out] deltatp Delta time to be filled in + * + * @retval 0 Success; otherwise - KRB5_DELTAT_BADFORMAT + */ +krb5_error_code KRB5_CALLCONV +krb5_string_to_deltat(char *string, krb5_deltat *deltatp); + +/** + * Convert an encryption type to a string. + * + * @param [in] enctype Encryption type + * @param [out] buffer Buffer to hold encryption type string + * @param [in] buflen Storage available in @a buffer + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_enctype_to_string(krb5_enctype enctype, char *buffer, size_t buflen); + +/** + * Convert an encryption type to a name or alias. + * + * @param [in] enctype Encryption type + * @param [in] shortest Flag + * @param [out] buffer Buffer to hold encryption type string + * @param [in] buflen Storage available in @a buffer + * + * If @a shortest is FALSE, this function returns the enctype's canonical name + * (like "aes128-cts-hmac-sha1-96"). If @a shortest is TRUE, it return the + * enctype's shortest alias (like "aes128-cts"). + * + * @version New in 1.9 + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_enctype_to_name(krb5_enctype enctype, krb5_boolean shortest, + char *buffer, size_t buflen); + +/** + * Convert a salt type to a string. + * + * @param [in] salttype Salttype to convert + * @param [out] buffer Buffer to receive the converted string + * @param [in] buflen Storage available in @a buffer + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_salttype_to_string(krb5_int32 salttype, char *buffer, size_t buflen); + +/** + * Convert a checksum type to a string. + * + * @param [in] cksumtype Checksum type + * @param [out] buffer Buffer to hold converted checksum type + * @param [in] buflen Storage available in @a buffer + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_cksumtype_to_string(krb5_cksumtype cksumtype, char *buffer, size_t buflen); + +/** + * Convert a timestamp to a string. + * + * @param [in] timestamp Timestamp to convert + * @param [out] buffer Buffer to hold converted timestamp + * @param [in] buflen Storage available in @a buffer + * + * The string is returned in the locale's appropriate date and time + * representation. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_timestamp_to_string(krb5_timestamp timestamp, char *buffer, size_t buflen); + +/** + * Convert a timestamp to a string, with optional output padding + * + * @param [in] timestamp Timestamp to convert + * @param [out] buffer Buffer to hold the converted timestamp + * @param [in] buflen Length of buffer + * @param [in] pad Optional value to pad @a buffer if converted + * timestamp does not fill it + * + * If @a pad is not NULL, @a buffer is padded out to @a buflen - 1 characters + * with the value of *@a pad. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_timestamp_to_sfstring(krb5_timestamp timestamp, char *buffer, + size_t buflen, char *pad); + +/** + * Convert a relative time value to a string. + * + * @param [in] deltat Relative time value to convert + * @param [out] buffer Buffer to hold time string + * @param [in] buflen Storage available in @a buffer + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_deltat_to_string(krb5_deltat deltat, char *buffer, size_t buflen); + +/* The name of the Kerberos ticket granting service... and its size */ +#define KRB5_TGS_NAME "krbtgt" +#define KRB5_TGS_NAME_SIZE 6 + +/* flags for recvauth */ +#define KRB5_RECVAUTH_SKIP_VERSION 0x0001 +#define KRB5_RECVAUTH_BADAUTHVERS 0x0002 +/* initial ticket api functions */ + +/** Text for prompt used in prompter callback function. */ +typedef struct _krb5_prompt { + char *prompt; /**< The prompt to show to the user */ + int hidden; /**< Boolean; informative prompt or hidden (e.g. PIN) */ + krb5_data *reply; /**< Must be allocated before call to prompt routine */ +} krb5_prompt; + +/** Pointer to a prompter callback function. */ +typedef krb5_error_code +(KRB5_CALLCONV *krb5_prompter_fct)(krb5_context context, void *data, + const char *name, const char *banner, + int num_prompts, krb5_prompt prompts[]); + +/** + * Prompt user for password. + * + * @param [in] context Library context + * @param data Unused (callback argument) + * @param [in] name Name to output during prompt + * @param [in] banner Banner to output during prompt + * @param [in] num_prompts Number of prompts in @a prompts + * @param [in] prompts Array of prompts and replies + * + * This function is intended to be used as a prompter callback for + * krb5_get_init_creds_password() or krb5_init_creds_init(). + * + * Writes @a name and @a banner to stdout, each followed by a newline, then + * writes each prompt field in the @a prompts array, followed by ": ", and sets + * the reply field of the entry to a line of input read from stdin. If the + * hidden flag is set for a prompt, then terminal echoing is turned off when + * input is read. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + * + */ +krb5_error_code KRB5_CALLCONV +krb5_prompter_posix(krb5_context context, void *data, const char *name, + const char *banner, int num_prompts, + krb5_prompt prompts[]); + +/** + * Long-term password responder question + * + * This question is asked when the long-term password is needed. It has no + * challenge and the response is simply the password string. + * + * @version New in 1.11 + */ +#define KRB5_RESPONDER_QUESTION_PASSWORD "password" + +/** + * OTP responder question + * + * The OTP responder question is asked when the KDC indicates that an OTP + * value is required in order to complete the authentication. The JSON format + * of the challenge is: + * + * { + * "service": , + * "tokenInfo": [ + * { + * "flags": , + * "vendor": , + * "challenge": , + * "length": , + * "format": , + * "tokenID": , + * "algID": , + * }, + * ... + * ] + * } + * + * The answer to the question MUST be JSON formatted: + * + * { + * "tokeninfo": , + * "value": , + * "pin": , + * } + * + * For more detail, please see RFC 6560. + * + * @version New in 1.11 + */ +#define KRB5_RESPONDER_QUESTION_OTP "otp" + +/** + * These format constants identify the format of the token value. + */ +#define KRB5_RESPONDER_OTP_FORMAT_DECIMAL 0 +#define KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL 1 +#define KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC 2 + +/** + * This flag indicates that the token value MUST be collected. + */ +#define KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN 0x0001 + +/** + * This flag indicates that the PIN value MUST be collected. + */ +#define KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN 0x0002 + +/** + * This flag indicates that the token is now in re-synchronization mode with + * the server. The user is expected to reply with the next code displayed on + * the token. + */ +#define KRB5_RESPONDER_OTP_FLAGS_NEXTOTP 0x0004 + +/** + * This flag indicates that the PIN MUST be returned as a separate item. This + * flag only takes effect if KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN is set. If + * this flag is not set, the responder may either concatenate PIN + token value + * and store it as "value" in the answer or it may return them separately. If + * they are returned separately, they will be concatenated internally. + */ +#define KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN 0x0008 + +/** + * PKINIT responder question + * + * The PKINIT responder question is asked when the client needs a password + * that's being used to protect key information, and is formatted as a JSON + * object. A specific identity's flags value, if not zero, is the bitwise-OR + * of one or more of the KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_* flags defined + * below, and possibly other flags to be added later. Any resemblance to + * similarly-named CKF_* values in the PKCS#11 API should not be depended on. + * + * { + * identity : flags , + * ... + * } + * + * The answer to the question MUST be JSON formatted: + * + * { + * identity : password , + * ... + * } + * + * @version New in 1.12 + */ +#define KRB5_RESPONDER_QUESTION_PKINIT "pkinit" + +/** + * This flag indicates that an incorrect PIN was supplied at least once since + * the last time the correct PIN was supplied. + */ +#define KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW (1 << 0) + +/** + * This flag indicates that supplying an incorrect PIN will cause the token to + * lock itself. + */ +#define KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY (1 << 1) + +/** + * This flag indicates that the user PIN is locked, and you can't log in to the + * token with it. + */ +#define KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED (1 << 2) + +/** + * A container for a set of preauthentication questions and answers + * + * A responder context is supplied by the krb5 authentication system to a + * krb5_responder_fn callback. It contains a list of questions and can receive + * answers. Questions contained in a responder context can be listed using + * krb5_responder_list_questions(), retrieved using + * krb5_responder_get_challenge(), or answered using + * krb5_responder_set_answer(). The form of a question's challenge and answer + * depend on the question name. + * + * @version New in 1.11 + */ +typedef struct krb5_responder_context_st *krb5_responder_context; + +/** + * List the question names contained in the responder context. + * + * @param [in] ctx Library context + * @param [in] rctx Responder context + * + * Return a pointer to a null-terminated list of question names which are + * present in @a rctx. The pointer is an alias, valid only as long as the + * lifetime of @a rctx, and should not be modified or freed by the caller. A + * question's challenge can be retrieved using krb5_responder_get_challenge() + * and answered using krb5_responder_set_answer(). + * + * @version New in 1.11 + */ +const char * const * KRB5_CALLCONV +krb5_responder_list_questions(krb5_context ctx, krb5_responder_context rctx); + +/** + * Retrieve the challenge data for a given question in the responder context. + * + * @param [in] ctx Library context + * @param [in] rctx Responder context + * @param [in] question Question name + * + * Return a pointer to a C string containing the challenge for @a question + * within @a rctx, or NULL if the question is not present in @a rctx. The + * structure of the question depends on the question name, but will always be + * printable UTF-8 text. The returned pointer is an alias, valid only as long + * as the lifetime of @a rctx, and should not be modified or freed by the + * caller. + * + * @version New in 1.11 + */ +const char * KRB5_CALLCONV +krb5_responder_get_challenge(krb5_context ctx, krb5_responder_context rctx, + const char *question); + +/** + * Answer a named question in the responder context. + * + * @param [in] ctx Library context + * @param [in] rctx Responder context + * @param [in] question Question name + * @param [in] answer The string to set (MUST be printable UTF-8) + * + * This function supplies an answer to @a question within @a rctx. The + * appropriate form of the answer depends on the question name. + * + * @retval EINVAL @a question is not present within @a rctx + * + * @version New in 1.11 + */ +krb5_error_code KRB5_CALLCONV +krb5_responder_set_answer(krb5_context ctx, krb5_responder_context rctx, + const char *question, const char *answer); + +/** + * Responder function for an initial credential exchange. + * + * @param [in] ctx Library context + * @param [in] data Callback data + * @param [in] rctx Responder context + * + * A responder function is like a prompter function, but is used for handling + * questions and answers as potentially complex data types. Client + * preauthentication modules will insert a set of named "questions" into + * the responder context. Each question may optionally contain a challenge. + * This challenge is printable UTF-8, but may be an encoded value. The + * precise encoding and contents of the challenge are specific to the question + * asked. When the responder is called, it should answer all the questions it + * understands. Like the challenge, the answer MUST be printable UTF-8, but + * may contain structured/encoded data formatted to the expected answer format + * of the question. + * + * If a required question is unanswered, the prompter may be called. + */ +typedef krb5_error_code +(KRB5_CALLCONV *krb5_responder_fn)(krb5_context ctx, void *data, + krb5_responder_context rctx); + +typedef struct _krb5_responder_otp_tokeninfo { + krb5_flags flags; + krb5_int32 format; /* -1 when not specified. */ + krb5_int32 length; /* -1 when not specified. */ + char *vendor; + char *challenge; + char *token_id; + char *alg_id; +} krb5_responder_otp_tokeninfo; + +typedef struct _krb5_responder_otp_challenge { + char *service; + krb5_responder_otp_tokeninfo **tokeninfo; +} krb5_responder_otp_challenge; + +/** + * Decode the KRB5_RESPONDER_QUESTION_OTP to a C struct. + * + * A convenience function which parses the KRB5_RESPONDER_QUESTION_OTP + * question challenge data, making it available in native C. The main feature + * of this function is the ability to interact with OTP tokens without parsing + * the JSON. + * + * The returned value must be passed to krb5_responder_otp_challenge_free() to + * be freed. + * + * @param [in] ctx Library context + * @param [in] rctx Responder context + * @param [out] chl Challenge structure + * + * @version New in 1.11 + */ +krb5_error_code KRB5_CALLCONV +krb5_responder_otp_get_challenge(krb5_context ctx, + krb5_responder_context rctx, + krb5_responder_otp_challenge **chl); + +/** + * Answer the KRB5_RESPONDER_QUESTION_OTP question. + * + * @param [in] ctx Library context + * @param [in] rctx Responder context + * @param [in] ti The index of the tokeninfo selected + * @param [in] value The value to set, or NULL for none + * @param [in] pin The pin to set, or NULL for none + * + * @version New in 1.11 + */ +krb5_error_code KRB5_CALLCONV +krb5_responder_otp_set_answer(krb5_context ctx, krb5_responder_context rctx, + size_t ti, const char *value, const char *pin); + +/** + * Free the value returned by krb5_responder_otp_get_challenge(). + * + * @param [in] ctx Library context + * @param [in] rctx Responder context + * @param [in] chl The challenge to free + * + * @version New in 1.11 + */ +void KRB5_CALLCONV +krb5_responder_otp_challenge_free(krb5_context ctx, + krb5_responder_context rctx, + krb5_responder_otp_challenge *chl); + +typedef struct _krb5_responder_pkinit_identity { + char *identity; + krb5_int32 token_flags; /* 0 when not specified or not applicable. */ +} krb5_responder_pkinit_identity; + +typedef struct _krb5_responder_pkinit_challenge { + krb5_responder_pkinit_identity **identities; +} krb5_responder_pkinit_challenge; + +/** + * Decode the KRB5_RESPONDER_QUESTION_PKINIT to a C struct. + * + * A convenience function which parses the KRB5_RESPONDER_QUESTION_PKINIT + * question challenge data, making it available in native C. The main feature + * of this function is the ability to read the challenge without parsing + * the JSON. + * + * The returned value must be passed to krb5_responder_pkinit_challenge_free() + * to be freed. + * + * @param [in] ctx Library context + * @param [in] rctx Responder context + * @param [out] chl_out Challenge structure + * + * @version New in 1.12 + */ +krb5_error_code KRB5_CALLCONV +krb5_responder_pkinit_get_challenge(krb5_context ctx, + krb5_responder_context rctx, + krb5_responder_pkinit_challenge **chl_out); + +/** + * Answer the KRB5_RESPONDER_QUESTION_PKINIT question for one identity. + * + * @param [in] ctx Library context + * @param [in] rctx Responder context + * @param [in] identity The identity for which a PIN is being supplied + * @param [in] pin The provided PIN, or NULL for none + * + * @version New in 1.12 + */ +krb5_error_code KRB5_CALLCONV +krb5_responder_pkinit_set_answer(krb5_context ctx, krb5_responder_context rctx, + const char *identity, const char *pin); + +/** + * Free the value returned by krb5_responder_pkinit_get_challenge(). + * + * @param [in] ctx Library context + * @param [in] rctx Responder context + * @param [in] chl The challenge to free + * + * @version New in 1.12 + */ +void KRB5_CALLCONV +krb5_responder_pkinit_challenge_free(krb5_context ctx, + krb5_responder_context rctx, + krb5_responder_pkinit_challenge *chl); + +/** Store options for @c _krb5_get_init_creds */ +typedef struct _krb5_get_init_creds_opt { + krb5_flags flags; + krb5_deltat tkt_life; + krb5_deltat renew_life; + int forwardable; + int proxiable; + krb5_enctype *etype_list; + int etype_list_length; + krb5_address **address_list; + krb5_preauthtype *preauth_list; + int preauth_list_length; + krb5_data *salt; +} krb5_get_init_creds_opt; + +#define KRB5_GET_INIT_CREDS_OPT_TKT_LIFE 0x0001 +#define KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE 0x0002 +#define KRB5_GET_INIT_CREDS_OPT_FORWARDABLE 0x0004 +#define KRB5_GET_INIT_CREDS_OPT_PROXIABLE 0x0008 +#define KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST 0x0010 +#define KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST 0x0020 +#define KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST 0x0040 +#define KRB5_GET_INIT_CREDS_OPT_SALT 0x0080 +#define KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT 0x0100 +#define KRB5_GET_INIT_CREDS_OPT_CANONICALIZE 0x0200 +#define KRB5_GET_INIT_CREDS_OPT_ANONYMOUS 0x0400 + + +/** + * Allocate a new initial credential options structure. + * + * @param [in] context Library context + * @param [out] opt New options structure + * + * This function is the preferred way to create an options structure for + * getting initial credentials, and is required to make use of certain options. + * Use krb5_get_init_creds_opt_free() to free @a opt when it is no longer + * needed. + * + * @retval 0 - Success; Kerberos errors otherwise. + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_alloc(krb5_context context, + krb5_get_init_creds_opt **opt); + +/** + * Free initial credential options. + * + * @param [in] context Library context + * @param [in] opt Options structure to free + * + * @sa krb5_get_init_creds_opt_alloc() + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_free(krb5_context context, + krb5_get_init_creds_opt *opt); + +/** @deprecated Use krb5_get_init_creds_opt_alloc() instead. */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt); + +/** + * Set the ticket lifetime in initial credential options. + * + * @param [in] opt Options structure + * @param [in] tkt_life Ticket lifetime + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt, + krb5_deltat tkt_life); + +/** + * Set the ticket renewal lifetime in initial credential options. + * + * @param [in] opt Pointer to @a options field + * @param [in] renew_life Ticket renewal lifetime + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt, + krb5_deltat renew_life); + +/** + * Set or unset the forwardable flag in initial credential options. + * + * @param [in] opt Options structure + * @param [in] forwardable Whether credentials should be forwardable + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt, + int forwardable); + +/** + * Set or unset the proxiable flag in initial credential options. + * + * @param [in] opt Options structure + * @param [in] proxiable Whether credentials should be proxiable + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt, + int proxiable); + +/** + * Set or unset the canonicalize flag in initial credential options. + * + * @param [in] opt Options structure + * @param [in] canonicalize Whether to canonicalize client principal + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_canonicalize(krb5_get_init_creds_opt *opt, + int canonicalize); + +/** + * Set or unset the anonymous flag in initial credential options. + * + * @param [in] opt Options structure + * @param [in] anonymous Whether to make an anonymous request + * + * This function may be used to request anonymous credentials from the KDC by + * setting @a anonymous to non-zero. Note that anonymous credentials are only + * a request; clients must verify that credentials are anonymous if that is a + * requirement. + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_anonymous(krb5_get_init_creds_opt *opt, + int anonymous); + +/** + * Set allowable encryption types in initial credential options. + * + * @param [in] opt Options structure + * @param [in] etype_list Array of encryption types + * @param [in] etype_list_length Length of @a etype_list + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt, + krb5_enctype *etype_list, + int etype_list_length); + +/** + * Set address restrictions in initial credential options. + * + * @param [in] opt Options structure + * @param [in] addresses Null-terminated array of addresses + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt, + krb5_address **addresses); + +/** + * Set preauthentication types in initial credential options. + * + * @param [in] opt Options structure + * @param [in] preauth_list Array of preauthentication types + * @param [in] preauth_list_length Length of @a preauth_list + * + * This function can be used to perform optimistic preauthentication when + * getting initial credentials, in combination with + * krb5_get_init_creds_opt_set_salt() and krb5_get_init_creds_opt_set_pa(). + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, + krb5_preauthtype *preauth_list, + int preauth_list_length); + +/** + * Set salt for optimistic preauthentication in initial credential options. + * + * @param [in] opt Options structure + * @param [in] salt Salt data + * + * When getting initial credentials with a password, a salt string it used to + * convert the password to a key. Normally this salt is obtained from the + * first KDC reply, but when performing optimistic preauthentication, the + * client may need to supply the salt string with this function. + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, + krb5_data *salt); + +/** + * Set or unset change-password-prompt flag in initial credential options. + * + * @param [in] opt Options structure + * @param [in] prompt Whether to prompt to change password + * + * This flag is on by default. It controls whether + * krb5_get_init_creds_password() will react to an expired-password error by + * prompting for a new password and attempting to change the old one. + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_change_password_prompt(krb5_get_init_creds_opt *opt, + int prompt); + +/** Generic preauth option attribute/value pairs */ +typedef struct _krb5_gic_opt_pa_data { + char *attr; + char *value; +} krb5_gic_opt_pa_data; + +/** + * Supply options for preauthentication in initial credential options. + * + * @param [in] context Library context + * @param [in] opt Options structure + * @param [in] attr Preauthentication option name + * @param [in] value Preauthentication option value + * + * This function allows the caller to supply options for preauthentication. + * The values of @a attr and @a value are supplied to each preauthentication + * module available within @a context. + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_pa(krb5_context context, + krb5_get_init_creds_opt *opt, const char *attr, + const char *value); + +/** + * Set location of FAST armor ccache in initial credential options. + * + * @param [in] context Library context + * @param [in] opt Options + * @param [in] fast_ccache_name Credential cache name + * + * Sets the location of a credential cache containing an armor ticket to + * protect an initial credential exchange using the FAST protocol extension. + * + * In version 1.7, setting an armor ccache requires that FAST be used for the + * exchange. In version 1.8 or later, setting the armor ccache causes FAST to + * be used if the KDC supports it; krb5_get_init_creds_opt_set_fast_flags() + * must be used to require that FAST be used. + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_fast_ccache_name(krb5_context context, + krb5_get_init_creds_opt *opt, + const char *fast_ccache_name); + +/** + * Set FAST armor cache in initial credential options. + * + * @param [in] context Library context + * @param [in] opt Options + * @param [in] ccache Credential cache handle + * + * This function is similar to krb5_get_init_creds_opt_set_fast_ccache_name(), + * but uses a credential cache handle instead of a name. + * + * @version New in 1.9 + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_fast_ccache(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_ccache ccache); + +/** + * Set an input credential cache in initial credential options. + * + * @param [in] context Library context + * @param [in] opt Options + * @param [in] ccache Credential cache handle + * + * If an input credential cache is set, then the krb5_get_init_creds family of + * APIs will read settings from it. Setting an input ccache is desirable when + * the application wishes to perform authentication in the same way (using the + * same preauthentication mechanisms, and making the same non-security- + * sensitive choices) as the previous authentication attempt, which stored + * information in the passed-in ccache. + * + * @version New in 1.11 + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_in_ccache(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_ccache ccache); + +/** + * Set an output credential cache in initial credential options. + * + * @param [in] context Library context + * @param [in] opt Options + * @param [in] ccache Credential cache handle + * + * If an output credential cache is set, then the krb5_get_init_creds family of + * APIs will write credentials to it. Setting an output ccache is desirable + * both because it simplifies calling code and because it permits the + * krb5_get_init_creds APIs to write out configuration information about the + * realm to the ccache. + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_out_ccache(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_ccache ccache); + +/** + * @brief Ask the KDC to include or not include a PAC in the ticket + * + * @param [in] context Library context + * @param [in] opt Options structure + * @param [in] req_pac Whether to request a PAC or not + * + * If this option is set, the AS request will include a PAC-REQUEST pa-data + * item explicitly asking the KDC to either include or not include a privilege + * attribute certificate in the ticket authorization data. By default, no + * request is made; typically the KDC will default to including a PAC if it + * supports them. + * + * @version New in 1.15 + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_pac_request(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_boolean req_pac); + +/** + * Set FAST flags in initial credential options. + * + * @param [in] context Library context + * @param [in] opt Options + * @param [in] flags FAST flags + * + * The following flag values are valid: + * @li #KRB5_FAST_REQUIRED - Require FAST to be used + * + * @retval + * 0 - Success; Kerberos errors otherwise. + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_fast_flags(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_flags flags); + +/** + * Retrieve FAST flags from initial credential options. + * + * @param [in] context Library context + * @param [in] opt Options + * @param [out] out_flags FAST flags + * + * @retval + * 0 - Success; Kerberos errors otherwise. + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_get_fast_flags(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_flags *out_flags); + +/* Fast flags*/ +#define KRB5_FAST_REQUIRED 0x0001 /**< Require KDC to support FAST*/ + +typedef void +(KRB5_CALLCONV *krb5_expire_callback_func)(krb5_context context, void *data, + krb5_timestamp password_expiration, + krb5_timestamp account_expiration, + krb5_boolean is_last_req); + +/** + * Set an expiration callback in initial credential options. + * + * @param [in] context Library context + * @param [in] opt Options structure + * @param [in] cb Callback function + * @param [in] data Callback argument + * + * Set a callback to receive password and account expiration times. + * + * @a cb will be invoked if and only if credentials are successfully acquired. + * The callback will receive the @a context from the calling function and the + * @a data argument supplied with this API. The remaining arguments should be + * interpreted as follows: + * + * If @a is_last_req is true, then the KDC reply contained last-req entries + * which unambiguously indicated the password expiration, account expiration, + * or both. (If either value was not present, the corresponding argument will + * be 0.) Furthermore, a non-zero @a password_expiration should be taken as a + * suggestion from the KDC that a warning be displayed. + * + * If @a is_last_req is false, then @a account_expiration will be 0 and @a + * password_expiration will contain the expiration time of either the password + * or account, or 0 if no expiration time was indicated in the KDC reply. The + * callback should independently decide whether to display a password + * expiration warning. + * + * Note that @a cb may be invoked even if credentials are being acquired for + * the kadmin/changepw service in order to change the password. It is the + * caller's responsibility to avoid displaying a password expiry warning in + * this case. + * + * @warning Setting an expire callback with this API will cause + * krb5_get_init_creds_password() not to send password expiry warnings to the + * prompter, as it ordinarily may. + * + * @version New in 1.9 + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_expire_callback(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_expire_callback_func cb, + void *data); + +/** + * Set the responder function in initial credential options. + * + * @param [in] context Library context + * @param [in] opt Options structure + * @param [in] responder Responder function + * @param [in] data Responder data argument + * + * @version New in 1.11 + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_responder(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_responder_fn responder, void *data); + +/** + * Get initial credentials using a password. + * + * @param [in] context Library context + * @param [out] creds New credentials + * @param [in] client Client principal + * @param [in] password Password (or NULL) + * @param [in] prompter Prompter function + * @param [in] data Prompter callback data + * @param [in] start_time Time when ticket becomes valid (0 for now) + * @param [in] in_tkt_service Service name of initial credentials (or NULL) + * @param [in] k5_gic_options Initial credential options + * + * This function requests KDC for an initial credentials for @a client using @a + * password. If @a password is NULL, a password will be prompted for using @a + * prompter if necessary. If @a in_tkt_service is specified, it is parsed as a + * principal name (with the realm ignored) and used as the service principal + * for the request; otherwise the ticket-granting service is used. + * + * @sa krb5_verify_init_creds() + * + * @retval + * 0 Success + * @retval + * EINVAL Invalid argument + * @retval + * KRB5_KDC_UNREACH Cannot contact any KDC for requested realm + * @retval + * KRB5_PREAUTH_FAILED Generic Pre-athentication failure + * @retval + * KRB5_LIBOS_PWDINTR Password read interrupted + * @retval + * KRB5_REALM_CANT_RESOLVE Cannot resolve network address for KDC in requested realm + * @retval + * KRB5KDC_ERR_KEY_EXP Password has expired + * @retval + * KRB5_LIBOS_BADPWDMATCH Password mismatch + * @retval + * KRB5_CHPW_PWDNULL New password cannot be zero length + * @retval + * KRB5_CHPW_FAIL Password change failed + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_password(krb5_context context, krb5_creds *creds, + krb5_principal client, const char *password, + krb5_prompter_fct prompter, void *data, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *k5_gic_options); + +/** + * Retrieve enctype, salt and s2kparams from KDC + * + * @param [in] context Library context + * @param [in] principal Principal whose information is requested + * @param [in] opt Initial credential options + * @param [out] enctype_out The enctype chosen by KDC + * @param [out] salt_out Salt returned from KDC + * @param [out] s2kparams_out String-to-key parameters returned from KDC + * + * Send an initial ticket request for @a principal and extract the encryption + * type, salt type, and string-to-key parameters from the KDC response. If the + * KDC provides no etype-info, set @a enctype_out to @c ENCTYPE_NULL and set @a + * salt_out and @a s2kparams_out to empty. If the KDC etype-info provides no + * salt, compute the default salt and place it in @a salt_out. If the KDC + * etype-info provides no string-to-key parameters, set @a s2kparams_out to + * empty. + * + * @a opt may be used to specify options which affect the initial request, such + * as request encryption types or a FAST armor cache (see + * krb5_get_init_creds_opt_set_etype_list() and + * krb5_get_init_creds_opt_set_fast_ccache_name()). + * + * Use krb5_free_data_contents() to free @a salt_out and @a s2kparams_out when + * they are no longer needed. + * + * @version New in 1.17 + * + * @retval 0 Success + * @return A Kerberos error code + */ +krb5_error_code KRB5_CALLCONV +krb5_get_etype_info(krb5_context context, krb5_principal principal, + krb5_get_init_creds_opt *opt, krb5_enctype *enctype_out, + krb5_data *salt_out, krb5_data *s2kparams_out); + +struct _krb5_init_creds_context; +typedef struct _krb5_init_creds_context *krb5_init_creds_context; + +#define KRB5_INIT_CREDS_STEP_FLAG_CONTINUE 0x1 /**< More responses needed */ + +/** + * Free an initial credentials context. + * + * @param [in] context Library context + * @param [in] ctx Initial credentials context + * + * @a context must be the same as the one passed to krb5_init_creds_init() for + * this initial credentials context. + */ +void KRB5_CALLCONV +krb5_init_creds_free(krb5_context context, krb5_init_creds_context ctx); + +/** + * Acquire credentials using an initial credentials context. + * + * @param [in] context Library context + * @param [in] ctx Initial credentials context + * + * This function synchronously obtains credentials using a context created by + * krb5_init_creds_init(). On successful return, the credentials can be + * retrieved with krb5_init_creds_get_creds(). + * + * @a context must be the same as the one passed to krb5_init_creds_init() for + * this initial credentials context. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_init_creds_get(krb5_context context, krb5_init_creds_context ctx); + +/** + * Retrieve acquired credentials from an initial credentials context. + * + * @param [in] context Library context + * @param [in] ctx Initial credentials context + * @param [out] creds Acquired credentials + * + * This function copies the acquired initial credentials from @a ctx into @a + * creds, after the successful completion of krb5_init_creds_get() or + * krb5_init_creds_step(). Use krb5_free_cred_contents() to free @a creds when + * it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_init_creds_get_creds(krb5_context context, krb5_init_creds_context ctx, + krb5_creds *creds); + +/** + * Get the last error from KDC from an initial credentials context. + * + * @param [in] context Library context + * @param [in] ctx Initial credentials context + * @param [out] error Error from KDC, or NULL if none was received + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_init_creds_get_error(krb5_context context, krb5_init_creds_context ctx, + krb5_error **error); + +/** + * Create a context for acquiring initial credentials. + * + * @param [in] context Library context + * @param [in] client Client principal to get initial creds for + * @param [in] prompter Prompter callback + * @param [in] data Prompter callback argument + * @param [in] start_time Time when credentials become valid (0 for now) + * @param [in] options Options structure (NULL for default) + * @param [out] ctx New initial credentials context + * + * This function creates a new context for acquiring initial credentials. Use + * krb5_init_creds_free() to free @a ctx when it is no longer needed. + * + * Any subsequent calls to krb5_init_creds_step(), krb5_init_creds_get(), or + * krb5_init_creds_free() for this initial credentials context must use the + * same @a context argument as the one passed to this function. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_init_creds_init(krb5_context context, krb5_principal client, + krb5_prompter_fct prompter, void *data, + krb5_deltat start_time, krb5_get_init_creds_opt *options, + krb5_init_creds_context *ctx); + +/** + * Specify a keytab to use for acquiring initial credentials. + * + * @param [in] context Library context + * @param [in] ctx Initial credentials context + * @param [in] keytab Key table handle + * + * This function supplies a keytab containing the client key for an initial + * credentials request. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_init_creds_set_keytab(krb5_context context, krb5_init_creds_context ctx, + krb5_keytab keytab); + +/** + * Get the next KDC request for acquiring initial credentials. + * + * @param [in] context Library context + * @param [in] ctx Initial credentials context + * @param [in] in KDC response (empty on the first call) + * @param [out] out Next KDC request + * @param [out] realm Realm for next KDC request + * @param [out] flags Output flags + * + * This function constructs the next KDC request in an initial credential + * exchange, allowing the caller to control the transport of KDC requests and + * replies. On the first call, @a in should be set to an empty buffer; on + * subsequent calls, it should be set to the KDC's reply to the previous + * request. + * + * If more requests are needed, @a flags will be set to + * #KRB5_INIT_CREDS_STEP_FLAG_CONTINUE and the next request will be placed in + * @a out. If no more requests are needed, @a flags will not contain + * #KRB5_INIT_CREDS_STEP_FLAG_CONTINUE and @a out will be empty. + * + * If this function returns @c KRB5KRB_ERR_RESPONSE_TOO_BIG, the caller should + * transmit the next request using TCP rather than UDP. If this function + * returns any other error, the initial credential exchange has failed. + * + * @a context must be the same as the one passed to krb5_init_creds_init() for + * this initial credentials context. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_init_creds_step(krb5_context context, krb5_init_creds_context ctx, + krb5_data *in, krb5_data *out, krb5_data *realm, + unsigned int *flags); + +/** + * Set a password for acquiring initial credentials. + * + * @param [in] context Library context + * @param [in] ctx Initial credentials context + * @param [in] password Password + * + * This function supplies a password to be used to construct the client key for + * an initial credentials request. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_init_creds_set_password(krb5_context context, krb5_init_creds_context ctx, + const char *password); + +/** + * Specify a service principal for acquiring initial credentials. + * + * @param [in] context Library context + * @param [in] ctx Initial credentials context + * @param [in] service Service principal string + * + * This function supplies a service principal string to acquire initial + * credentials for instead of the default krbtgt service. @a service is parsed + * as a principal name; any realm part is ignored. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_init_creds_set_service(krb5_context context, krb5_init_creds_context ctx, + const char *service); + +/** + * Retrieve ticket times from an initial credentials context. + * + * @param [in] context Library context + * @param [in] ctx Initial credentials context + * @param [out] times Ticket times for acquired credentials + * + * The initial credentials context must have completed obtaining credentials + * via either krb5_init_creds_get() or krb5_init_creds_step(). + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_init_creds_get_times(krb5_context context, krb5_init_creds_context ctx, + krb5_ticket_times *times); + +struct _krb5_tkt_creds_context; +typedef struct _krb5_tkt_creds_context *krb5_tkt_creds_context; + +/** + * Create a context to get credentials from a KDC's Ticket Granting Service. + * + * @param[in] context Library context + * @param[in] ccache Credential cache handle + * @param[in] creds Input credentials + * @param[in] options Options (see KRB5_GC macros) + * @param[out] ctx New TGS request context + * + * This function prepares to obtain credentials matching @a creds, either by + * retrieving them from @a ccache or by making requests to ticket-granting + * services beginning with a ticket-granting ticket for the client principal's + * realm. + * + * The resulting TGS acquisition context can be used asynchronously with + * krb5_tkt_creds_step() or synchronously with krb5_tkt_creds_get(). See also + * krb5_get_credentials() for synchronous use. + * + * Use krb5_tkt_creds_free() to free @a ctx when it is no longer needed. + * + * @version New in 1.9 + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_tkt_creds_init(krb5_context context, krb5_ccache ccache, + krb5_creds *creds, krb5_flags options, + krb5_tkt_creds_context *ctx); + +/** + * Synchronously obtain credentials using a TGS request context. + * + * @param[in] context Library context + * @param[in] ctx TGS request context + * + * This function synchronously obtains credentials using a context created by + * krb5_tkt_creds_init(). On successful return, the credentials can be + * retrieved with krb5_tkt_creds_get_creds(). + * + * @version New in 1.9 + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_tkt_creds_get(krb5_context context, krb5_tkt_creds_context ctx); + +/** + * Retrieve acquired credentials from a TGS request context. + * + * @param[in] context Library context + * @param[in] ctx TGS request context + * @param[out] creds Acquired credentials + * + * This function copies the acquired initial credentials from @a ctx into @a + * creds, after the successful completion of krb5_tkt_creds_get() or + * krb5_tkt_creds_step(). Use krb5_free_cred_contents() to free @a creds when + * it is no longer needed. + * + * @version New in 1.9 + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_tkt_creds_get_creds(krb5_context context, krb5_tkt_creds_context ctx, + krb5_creds *creds); + +/** + * Free a TGS request context. + * + * @param[in] context Library context + * @param[in] ctx TGS request context + * + * @version New in 1.9 + */ +void KRB5_CALLCONV +krb5_tkt_creds_free(krb5_context context, krb5_tkt_creds_context ctx); + +#define KRB5_TKT_CREDS_STEP_FLAG_CONTINUE 0x1 /**< More responses needed */ + +/** + * Get the next KDC request in a TGS exchange. + * + * @param[in] context Library context + * @param[in] ctx TGS request context + * @param[in] in KDC response (empty on the first call) + * @param[out] out Next KDC request + * @param[out] realm Realm for next KDC request + * @param[out] flags Output flags + * + * This function constructs the next KDC request for a TGS exchange, allowing + * the caller to control the transport of KDC requests and replies. On the + * first call, @a in should be set to an empty buffer; on subsequent calls, it + * should be set to the KDC's reply to the previous request. + * + * If more requests are needed, @a flags will be set to + * #KRB5_TKT_CREDS_STEP_FLAG_CONTINUE and the next request will be placed in @a + * out. If no more requests are needed, @a flags will not contain + * #KRB5_TKT_CREDS_STEP_FLAG_CONTINUE and @a out will be empty. + * + * If this function returns @c KRB5KRB_ERR_RESPONSE_TOO_BIG, the caller should + * transmit the next request using TCP rather than UDP. If this function + * returns any other error, the TGS exchange has failed. + * + * @version New in 1.9 + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_tkt_creds_step(krb5_context context, krb5_tkt_creds_context ctx, + krb5_data *in, krb5_data *out, krb5_data *realm, + unsigned int *flags); + +/** + * Retrieve ticket times from a TGS request context. + * + * @param[in] context Library context + * @param[in] ctx TGS request context + * @param[out] times Ticket times for acquired credentials + * + * The TGS request context must have completed obtaining credentials via either + * krb5_tkt_creds_get() or krb5_tkt_creds_step(). + * + * @version New in 1.9 + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_tkt_creds_get_times(krb5_context context, krb5_tkt_creds_context ctx, + krb5_ticket_times *times); + +/** + * Get initial credentials using a key table. + * + * @param [in] context Library context + * @param [out] creds New credentials + * @param [in] client Client principal + * @param [in] arg_keytab Key table handle + * @param [in] start_time Time when ticket becomes valid (0 for now) + * @param [in] in_tkt_service Service name of initial credentials (or NULL) + * @param [in] k5_gic_options Initial credential options + * + * This function requests KDC for an initial credentials for @a client using a + * client key stored in @a arg_keytab. If @a in_tkt_service is specified, it + * is parsed as a principal name (with the realm ignored) and used as the + * service principal for the request; otherwise the ticket-granting service is + * used. + * + * @sa krb5_verify_init_creds() + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_keytab(krb5_context context, krb5_creds *creds, + krb5_principal client, krb5_keytab arg_keytab, + krb5_deltat start_time, const char *in_tkt_service, + krb5_get_init_creds_opt *k5_gic_options); + +typedef struct _krb5_verify_init_creds_opt { + krb5_flags flags; + int ap_req_nofail; /**< boolean */ +} krb5_verify_init_creds_opt; + +#define KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL 0x0001 + +/** + * Initialize a credential verification options structure. + * + * @param [in] k5_vic_options Verification options structure + */ +void KRB5_CALLCONV +krb5_verify_init_creds_opt_init(krb5_verify_init_creds_opt *k5_vic_options); + +/** + * Set whether credential verification is required. + * + * @param [in] k5_vic_options Verification options structure + * @param [in] ap_req_nofail Whether to require successful verification + * + * This function determines how krb5_verify_init_creds() behaves if no keytab + * information is available. If @a ap_req_nofail is @c FALSE, verification + * will be skipped in this case and krb5_verify_init_creds() will return + * successfully. If @a ap_req_nofail is @c TRUE, krb5_verify_init_creds() will + * not return successfully unless verification can be performed. + * + * If this function is not used, the behavior of krb5_verify_init_creds() is + * determined through configuration. + */ +void KRB5_CALLCONV +krb5_verify_init_creds_opt_set_ap_req_nofail(krb5_verify_init_creds_opt * k5_vic_options, + int ap_req_nofail); + +/** + * Verify initial credentials against a keytab. + * + * @param [in] context Library context + * @param [in] creds Initial credentials to be verified + * @param [in] server Server principal (or NULL) + * @param [in] keytab Key table (NULL to use default keytab) + * @param [in] ccache Credential cache for fetched creds (or NULL) + * @param [in] options Verification options (NULL for default options) + * + * This function attempts to verify that @a creds were obtained from a KDC with + * knowledge of a key in @a keytab, or the default keytab if @a keytab is NULL. + * If @a server is provided, the highest-kvno key entry for that principal name + * is used to verify the credentials; otherwise, all unique "host" service + * principals in the keytab are tried. + * + * If the specified keytab does not exist, or is empty, or cannot be read, or + * does not contain an entry for @a server, then credential verification may be + * skipped unless configuration demands that it succeed. The caller can + * control this behavior by providing a verification options structure; see + * krb5_verify_init_creds_opt_init() and + * krb5_verify_init_creds_opt_set_ap_req_nofail(). + * + * If @a ccache is NULL, any additional credentials fetched during the + * verification process will be destroyed. If @a ccache points to NULL, a + * memory ccache will be created for the additional credentials and returned in + * @a ccache. If @a ccache points to a valid credential cache handle, the + * additional credentials will be stored in that cache. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_verify_init_creds(krb5_context context, krb5_creds *creds, + krb5_principal server, krb5_keytab keytab, + krb5_ccache *ccache, + krb5_verify_init_creds_opt *options); + +/** + * Get validated credentials from the KDC. + * + * @param [in] context Library context + * @param [out] creds Validated credentials + * @param [in] client Client principal name + * @param [in] ccache Credential cache + * @param [in] in_tkt_service Server principal string (or NULL) + * + * This function gets a validated credential using a postdated credential from + * @a ccache. If @a in_tkt_service is specified, it is parsed (with the realm + * part ignored) and used as the server principal of the credential; + * otherwise, the ticket-granting service is used. + * + * If successful, the validated credential is placed in @a creds. + * + * @sa krb5_get_renewed_creds() + * + * @retval + * 0 Success + * @retval + * KRB5_NO_2ND_TKT Request missing second ticket + * @retval + * KRB5_NO_TKT_SUPPLIED Request did not supply a ticket + * @retval + * KRB5_PRINC_NOMATCH Requested principal and ticket do not match + * @retval + * KRB5_KDCREP_MODIFIED KDC reply did not match expectations + * @retval + * KRB5_KDCREP_SKEW Clock skew too great in KDC reply + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_get_validated_creds(krb5_context context, krb5_creds *creds, + krb5_principal client, krb5_ccache ccache, + const char *in_tkt_service); + +/** + * Get renewed credential from KDC using an existing credential. + * + * @param [in] context Library context + * @param [out] creds Renewed credentials + * @param [in] client Client principal name + * @param [in] ccache Credential cache + * @param [in] in_tkt_service Server principal string (or NULL) + * + * This function gets a renewed credential using an existing one from @a + * ccache. If @a in_tkt_service is specified, it is parsed (with the realm + * part ignored) and used as the server principal of the credential; otherwise, + * the ticket-granting service is used. + * + * If successful, the renewed credential is placed in @a creds. + * + * @retval + * 0 Success + * @return + * Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_get_renewed_creds(krb5_context context, krb5_creds *creds, + krb5_principal client, krb5_ccache ccache, + const char *in_tkt_service); + +/** + * Decode an ASN.1-formatted ticket. + * + * @param [in] code ASN.1-formatted ticket + * @param [out] rep Decoded ticket information + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_decode_ticket(const krb5_data *code, krb5_ticket **rep); + +/** + * Retrieve a string value from the appdefaults section of krb5.conf. + * + * @param [in] context Library context + * @param [in] appname Application name + * @param [in] realm Realm name + * @param [in] option Option to be checked + * @param [in] default_value Default value to return if no match is found + * @param [out] ret_value String value of @a option + * + * This function gets the application defaults for @a option based on the given + * @a appname and/or @a realm. + * + * @sa krb5_appdefault_boolean() + */ +void KRB5_CALLCONV +krb5_appdefault_string(krb5_context context, const char *appname, + const krb5_data *realm, const char *option, + const char *default_value, char ** ret_value); + +/** + * Retrieve a boolean value from the appdefaults section of krb5.conf. + * + * @param [in] context Library context + * @param [in] appname Application name + * @param [in] realm Realm name + * @param [in] option Option to be checked + * @param [in] default_value Default value to return if no match is found + * @param [out] ret_value Boolean value of @a option + * + * This function gets the application defaults for @a option based on the given + * @a appname and/or @a realm. + * + * @sa krb5_appdefault_string() + */ +void KRB5_CALLCONV +krb5_appdefault_boolean(krb5_context context, const char *appname, + const krb5_data *realm, const char *option, + int default_value, int *ret_value); + +/* + * Prompter enhancements + */ +/** Prompt for password */ +#define KRB5_PROMPT_TYPE_PASSWORD 0x1 +/** Prompt for new password (during password change) */ +#define KRB5_PROMPT_TYPE_NEW_PASSWORD 0x2 +/** Prompt for new password again */ +#define KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN 0x3 +/** Prompt for preauthentication data (such as an OTP value) */ +#define KRB5_PROMPT_TYPE_PREAUTH 0x4 + +typedef krb5_int32 krb5_prompt_type; + +/** + * Get prompt types array from a context. + * + * @param [in] context Library context + * + * @return + * Pointer to an array of prompt types corresponding to the prompter's @a + * prompts arguments. Each type has one of the following values: + * @li #KRB5_PROMPT_TYPE_PASSWORD + * @li #KRB5_PROMPT_TYPE_NEW_PASSWORD + * @li #KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN + * @li #KRB5_PROMPT_TYPE_PREAUTH + */ +krb5_prompt_type* KRB5_CALLCONV +krb5_get_prompt_types(krb5_context context); + +/* Error reporting */ +/** + * Set an extended error message for an error code. + * + * @param [in] ctx Library context + * @param [in] code Error code + * @param [in] fmt Error string for the error code + * @param [in] ... printf(3) style parameters + */ +void KRB5_CALLCONV_C +krb5_set_error_message(krb5_context ctx, krb5_error_code code, const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 4))) +#endif + ; + +/** + * Set an extended error message for an error code using a va_list. + * + * @param [in] ctx Library context + * @param [in] code Error code + * @param [in] fmt Error string for the error code + * @param [in] args List of vprintf(3) style arguments + */ +void KRB5_CALLCONV +krb5_vset_error_message(krb5_context ctx, krb5_error_code code, + const char *fmt, va_list args) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 0))) +#endif + ; + +/** + * Add a prefix to the message for an error code. + * + * @param [in] ctx Library context + * @param [in] code Error code + * @param [in] fmt Format string for error message prefix + * @param [in] ... printf(3) style parameters + * + * Format a message and prepend it to the current message for @a code. The + * prefix will be separated from the old message with a colon and space. + */ +void KRB5_CALLCONV_C +krb5_prepend_error_message(krb5_context ctx, krb5_error_code code, + const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 4))) +#endif + ; + +/** + * Add a prefix to the message for an error code using a va_list. + * + * @param [in] ctx Library context + * @param [in] code Error code + * @param [in] fmt Format string for error message prefix + * @param [in] args List of vprintf(3) style arguments + * + * This function is similar to krb5_prepend_error_message(), but uses a + * va_list instead of variadic arguments. + */ +void KRB5_CALLCONV +krb5_vprepend_error_message(krb5_context ctx, krb5_error_code code, + const char *fmt, va_list args) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 0))) +#endif + ; + +/** + * Add a prefix to a different error code's message. + * + * @param [in] ctx Library context + * @param [in] old_code Previous error code + * @param [in] code Error code + * @param [in] fmt Format string for error message prefix + * @param [in] ... printf(3) style parameters + * + * Format a message and prepend it to the message for @a old_code. The prefix + * will be separated from the old message with a colon and space. Set the + * resulting message as the extended error message for @a code. + */ +void KRB5_CALLCONV_C +krb5_wrap_error_message(krb5_context ctx, krb5_error_code old_code, + krb5_error_code code, const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 4, 5))) +#endif + ; + +/** + * Add a prefix to a different error code's message using a va_list. + * + * @param [in] ctx Library context + * @param [in] old_code Previous error code + * @param [in] code Error code + * @param [in] fmt Format string for error message prefix + * @param [in] args List of vprintf(3) style arguments + * + * This function is similar to krb5_wrap_error_message(), but uses a + * va_list instead of variadic arguments. + */ +void KRB5_CALLCONV +krb5_vwrap_error_message(krb5_context ctx, krb5_error_code old_code, + krb5_error_code code, const char *fmt, va_list args) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 4, 0))) +#endif + ; + +/** + * Copy the most recent extended error message from one context to another. + * + * @param [in] dest_ctx Library context to copy message to + * @param [in] src_ctx Library context with current message + */ +void KRB5_CALLCONV +krb5_copy_error_message(krb5_context dest_ctx, krb5_context src_ctx); + +/** + * Get the (possibly extended) error message for a code. + * + * @param [in] ctx Library context + * @param [in] code Error code + * + * The behavior of krb5_get_error_message() is only defined the first time it + * is called after a failed call to a krb5 function using the same context, and + * only when the error code passed in is the same as that returned by the krb5 + * function. + * + * This function never returns NULL, so its result may be used unconditionally + * as a C string. + * + * The string returned by this function must be freed using + * krb5_free_error_message() + * + * @note Future versions may return the same string for the second + * and following calls. + */ +const char * KRB5_CALLCONV +krb5_get_error_message(krb5_context ctx, krb5_error_code code); + +/** + * Free an error message generated by krb5_get_error_message(). + * + * @param [in] ctx Library context + * @param [in] msg Pointer to error message + */ +void KRB5_CALLCONV +krb5_free_error_message(krb5_context ctx, const char *msg); + +/** + * Clear the extended error message in a context. + * + * @param [in] ctx Library context + * + * This function unsets the extended error message in a context, to ensure that + * it is not mistakenly applied to another occurrence of the same error code. + */ +void KRB5_CALLCONV +krb5_clear_error_message(krb5_context ctx); + +/** + * Unwrap authorization data. + * + * @param [in] context Library context + * @param [in] type Container type (see KRB5_AUTHDATA macros) + * @param [in] container Authorization data to be decoded + * @param [out] authdata List of decoded authorization data + * + * @sa krb5_encode_authdata_container() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_decode_authdata_container(krb5_context context, + krb5_authdatatype type, + const krb5_authdata *container, + krb5_authdata ***authdata); +/** + * Wrap authorization data in a container. + * + * @param [in] context Library context + * @param [in] type Container type (see KRB5_AUTHDATA macros) + * @param [in] authdata List of authorization data to be encoded + * @param [out] container List of encoded authorization data + * + * The result is returned in @a container as a single-element list. + * + * @sa krb5_decode_authdata_container() + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_encode_authdata_container(krb5_context context, + krb5_authdatatype type, + krb5_authdata * const*authdata, + krb5_authdata ***container); + +/* + * AD-KDCIssued + */ +/** + * Encode and sign AD-KDCIssued authorization data. + * + * @param [in] context Library context + * @param [in] key Session key + * @param [in] issuer The name of the issuing principal + * @param [in] authdata List of authorization data to be signed + * @param [out] ad_kdcissued List containing AD-KDCIssued authdata + * + * This function wraps a list of authorization data entries @a authdata in an + * AD-KDCIssued container (see RFC 4120 section 5.2.6.2) signed with @a key. + * The result is returned in @a ad_kdcissued as a single-element list. + */ +krb5_error_code KRB5_CALLCONV +krb5_make_authdata_kdc_issued(krb5_context context, + const krb5_keyblock *key, + krb5_const_principal issuer, + krb5_authdata *const *authdata, + krb5_authdata ***ad_kdcissued); + +/** + * Unwrap and verify AD-KDCIssued authorization data. + * + * @param [in] context Library context + * @param [in] key Session key + * @param [in] ad_kdcissued AD-KDCIssued authorization data to be unwrapped + * @param [out] issuer Name of issuing principal (or NULL) + * @param [out] authdata Unwrapped list of authorization data + * + * This function unwraps an AD-KDCIssued authdatum (see RFC 4120 section + * 5.2.6.2) and verifies its signature against @a key. The issuer field of the + * authdatum element is returned in @a issuer, and the unwrapped list of + * authdata is returned in @a authdata. + */ +krb5_error_code KRB5_CALLCONV +krb5_verify_authdata_kdc_issued(krb5_context context, + const krb5_keyblock *key, + const krb5_authdata *ad_kdcissued, + krb5_principal *issuer, + krb5_authdata ***authdata); + +/* + * Windows PAC + */ + +/* Microsoft defined types of data */ +#define KRB5_PAC_LOGON_INFO 1 /**< Logon information */ +#define KRB5_PAC_CREDENTIALS_INFO 2 /**< Credentials information */ +#define KRB5_PAC_SERVER_CHECKSUM 6 /**< Server checksum */ +#define KRB5_PAC_PRIVSVR_CHECKSUM 7 /**< KDC checksum */ +#define KRB5_PAC_CLIENT_INFO 10 /**< Client name and ticket info */ +#define KRB5_PAC_DELEGATION_INFO 11 /**< Constrained delegation info */ +#define KRB5_PAC_UPN_DNS_INFO 12 /**< User principal name and DNS info */ +#define KRB5_PAC_CLIENT_CLAIMS 13 /**< Client claims information */ +#define KRB5_PAC_DEVICE_INFO 14 /**< Device information */ +#define KRB5_PAC_DEVICE_CLAIMS 15 /**< Device claims information */ +#define KRB5_PAC_TICKET_CHECKSUM 16 /**< Ticket checksum */ +#define KRB5_PAC_ATTRIBUTES_INFO 17 /**< PAC attributes */ +#define KRB5_PAC_REQUESTOR 18 /**< PAC requestor SID */ +#define KRB5_PAC_FULL_CHECKSUM 19 /**< KDC full checksum */ + +struct krb5_pac_data; +/** PAC data structure to convey authorization information */ +typedef struct krb5_pac_data *krb5_pac; + +/** + * Add a buffer to a PAC handle. + * + * @param [in] context Library context + * @param [in] pac PAC handle + * @param [in] type Buffer type + * @param [in] data contents + * + * This function adds a buffer of type @a type and contents @a data to @a pac + * if there isn't already a buffer of this type present. + * + * The valid values of @a type is one of the following: + * @li #KRB5_PAC_LOGON_INFO - Logon information + * @li #KRB5_PAC_CREDENTIALS_INFO - Credentials information + * @li #KRB5_PAC_SERVER_CHECKSUM - Server checksum + * @li #KRB5_PAC_PRIVSVR_CHECKSUM - KDC checksum + * @li #KRB5_PAC_CLIENT_INFO - Client name and ticket information + * @li #KRB5_PAC_DELEGATION_INFO - Constrained delegation information + * @li #KRB5_PAC_UPN_DNS_INFO - User principal name and DNS information + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_add_buffer(krb5_context context, krb5_pac pac, krb5_ui_4 type, + const krb5_data *data); + +/** + * Free a PAC handle. + * + * @param [in] context Library context + * @param [in] pac PAC to be freed + * + * This function frees the contents of @a pac and the structure itself. + */ +void KRB5_CALLCONV +krb5_pac_free(krb5_context context, krb5_pac pac); + +/** + * Retrieve a buffer value from a PAC. + * + * @param [in] context Library context + * @param [in] pac PAC handle + * @param [in] type Type of buffer to retrieve + * @param [out] data Buffer value + * + * Use krb5_free_data_contents() to free @a data when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_get_buffer(krb5_context context, krb5_pac pac, krb5_ui_4 type, + krb5_data *data); + +/** + * Return an array of buffer types in a PAC handle. + * + * @param [in] context Library context + * @param [in] pac PAC handle + * @param [out] len Number of entries in @a types + * @param [out] types Array of buffer types + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_get_types(krb5_context context, krb5_pac pac, size_t *len, + krb5_ui_4 **types); + +/** + * Create an empty Privilege Attribute Certificate (PAC) handle. + * + * @param [in] context Library context + * @param [out] pac New PAC handle + * + * Use krb5_pac_free() to free @a pac when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_init(krb5_context context, krb5_pac *pac); + +/** + * Unparse an encoded PAC into a new handle. + * + * @param [in] context Library context + * @param [in] ptr PAC buffer + * @param [in] len Length of @a ptr + * @param [out] pac PAC handle + * + * Use krb5_pac_free() to free @a pac when it is no longer needed. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_parse(krb5_context context, const void *ptr, size_t len, + krb5_pac *pac); + +/** + * Verify a PAC. + * + * @param [in] context Library context + * @param [in] pac PAC handle + * @param [in] authtime Expected timestamp + * @param [in] principal Expected principal name (or NULL) + * @param [in] server Key to validate server checksum (or NULL) + * @param [in] privsvr Key to validate KDC checksum (or NULL) + * + * This function validates @a pac against the supplied @a server, @a privsvr, + * @a principal and @a authtime. If @a principal is NULL, the principal and + * authtime are not verified. If @a server or @a privsvr is NULL, the + * corresponding checksum is not verified. + * + * If successful, @a pac is marked as verified. + * + * @note A checksum mismatch can occur if the PAC was copied from a cross-realm + * TGT by an ignorant KDC; also macOS Server Open Directory (as of 10.6) + * generates PACs with no server checksum at all. One should consider not + * failing the whole authentication because of this reason, but, instead, + * treating the ticket as if it did not contain a PAC or marking the PAC + * information as non-verified. + * + * @retval 0 Success; otherwise - Kerberos error codes + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_verify(krb5_context context, const krb5_pac pac, + krb5_timestamp authtime, krb5_const_principal principal, + const krb5_keyblock *server, const krb5_keyblock *privsvr); + +/** + * Verify a PAC, possibly from a specified realm. + * + * @param [in] context Library context + * @param [in] pac PAC handle + * @param [in] authtime Expected timestamp + * @param [in] principal Expected principal name (or NULL) + * @param [in] server Key to validate server checksum (or NULL) + * @param [in] privsvr Key to validate KDC checksum (or NULL) + * @param [in] with_realm If true, expect the realm of @a principal + * + * This function is similar to krb5_pac_verify(), but adds a parameter + * @a with_realm. If @a with_realm is true, the PAC_CLIENT_INFO field is + * expected to include the realm of @a principal as well as the name. This + * flag is necessary to verify PACs in cross-realm S4U2Self referral TGTs. + * + * @version New in 1.17 + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_verify_ext(krb5_context context, const krb5_pac pac, + krb5_timestamp authtime, krb5_const_principal principal, + const krb5_keyblock *server, const krb5_keyblock *privsvr, + krb5_boolean with_realm); + +/** + * Verify a PAC, possibly including ticket signature + * + * @param [in] context Library context + * @param [in] enc_tkt Ticket enc-part, possibly containing a PAC + * @param [in] server_princ Canonicalized name of ticket server + * @param [in] server Key to validate server checksum (or NULL) + * @param [in] privsvr Key to validate KDC checksum (or NULL) + * @param [out] pac_out Verified PAC (NULL if no PAC included) + * + * If a PAC is present in @a enc_tkt, verify its signatures. If @a privsvr is + * not NULL and @a server_princ is not a krbtgt or kadmin/changepw service, + * require a ticket signature over @a enc_tkt in addition to the KDC signature. + * Place the verified PAC in @a pac_out. If an invalid PAC signature is found, + * return an error matching the Windows KDC protocol code for that condition as + * closely as possible. + * + * If no PAC is present in @a enc_tkt, set @a pac_out to NULL and return + * successfully. + * + * @note This function does not validate the PAC_CLIENT_INFO buffer. If a + * specific value is expected, the caller can make a separate call to + * krb5_pac_verify_ext() with a principal but no keys. + * + * @retval 0 Success; otherwise - Kerberos error codes + * + * @version New in 1.20 + */ +krb5_error_code KRB5_CALLCONV +krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, + krb5_const_principal server_princ, + const krb5_keyblock *server, + const krb5_keyblock *privsvr, krb5_pac *pac_out); + +/** @deprecated Use krb5_kdc_sign_ticket() instead. */ +krb5_error_code KRB5_CALLCONV +krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + krb5_const_principal principal, const krb5_keyblock *server_key, + const krb5_keyblock *privsvr_key, krb5_data *data); + +/** @deprecated Use krb5_kdc_sign_ticket() instead. */ +krb5_error_code KRB5_CALLCONV +krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + krb5_const_principal principal, + const krb5_keyblock *server_key, + const krb5_keyblock *privsvr_key, krb5_boolean with_realm, + krb5_data *data); + +/** + * Sign a PAC, possibly including a ticket signature + * + * @param [in] context Library context + * @param [in] enc_tkt The ticket for the signature + * @param [in] pac PAC handle + * @param [in] server_princ Canonical ticket server name + * @param [in] client_princ PAC_CLIENT_INFO principal (or NULL) + * @param [in] server Key for server checksum + * @param [in] privsvr Key for KDC and ticket checksum + * @param [in] with_realm If true, include the realm of @a principal + * + * Sign @a pac using the keys @a server and @a privsvr. Include a ticket + * signature over @a enc_tkt if @a server_princ is not a TGS or kadmin/changepw + * principal name. Add the signed PAC's encoding to the authorization data of + * @a enc_tkt in the first slot, wrapped in an AD-IF-RELEVANT container. If @a + * client_princ is non-null, add a PAC_CLIENT_INFO buffer, including the realm + * if @a with_realm is true. + * + * @retval 0 on success, otherwise - Kerberos error codes + * + * @version New in 1.20 + */ +krb5_error_code KRB5_CALLCONV +krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt, + const krb5_pac pac, krb5_const_principal server_princ, + krb5_const_principal client_princ, + const krb5_keyblock *server, const krb5_keyblock *privsvr, + krb5_boolean with_realm); + +/** + * Read client information from a PAC. + * + * @param [in] context Library context + * @param [in] pac PAC handle + * @param [out] authtime_out Authentication timestamp (NULL if not needed) + * @param [out] princname_out Client account name + * + * Read the PAC_CLIENT_INFO buffer in @a pac. Place the client account name as + * a string in @a princname_out. If @a authtime_out is not NULL, place the + * initial authentication timestamp in @a authtime_out. + * + * @retval 0 on success, ENOENT if no PAC_CLIENT_INFO buffer is present in @a + * pac, ERANGE if the buffer contains invalid lengths. + * + * @version New in 1.18 + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_get_client_info(krb5_context context, const krb5_pac pac, + krb5_timestamp *authtime_out, char **princname_out); + +/** + * Allow the application to override the profile's allow_weak_crypto setting. + * + * @param [in] context Library context + * @param [in] enable Boolean flag + * + * This function allows an application to override the allow_weak_crypto + * setting. It is primarily for use by aklog. + * + * @retval 0 (always) + */ +krb5_error_code KRB5_CALLCONV +krb5_allow_weak_crypto(krb5_context context, krb5_boolean enable); + +/** + * A wrapper for passing information to a @c krb5_trace_callback. + * + * Currently, it only contains the formatted message as determined + * the the format string and arguments of the tracing macro, but it + * may be extended to contain more fields in the future. + */ +typedef struct _krb5_trace_info { + const char *message; +} krb5_trace_info; + +typedef void +(KRB5_CALLCONV *krb5_trace_callback)(krb5_context context, + const krb5_trace_info *info, + void *cb_data); + +/** + * Specify a callback function for trace events. + * + * @param [in] context Library context + * @param [in] fn Callback function + * @param [in] cb_data Callback data + * + * Specify a callback for trace events occurring in krb5 operations performed + * within @a context. @a fn will be invoked with @a context as the first + * argument, @a cb_data as the last argument, and a pointer to a + * krb5_trace_info as the second argument. If the trace callback is reset via + * this function or @a context is destroyed, @a fn will be invoked with a NULL + * second argument so it can clean up @a cb_data. Supply a NULL value for @a + * fn to disable trace callbacks within @a context. + * + * @note This function overrides the information passed through the + * @a KRB5_TRACE environment variable. + * + * @version New in 1.9 + * + * @return Returns KRB5_TRACE_NOSUPP if tracing is not supported in the library + * (unless @a fn is NULL). + */ +krb5_error_code KRB5_CALLCONV +krb5_set_trace_callback(krb5_context context, krb5_trace_callback fn, + void *cb_data); + +/** + * Specify a file name for directing trace events. + * + * @param [in] context Library context + * @param [in] filename File name + * + * Open @a filename for appending (creating it, if necessary) and set up a + * callback to write trace events to it. + * + * @note This function overrides the information passed through the + * @a KRB5_TRACE environment variable. + * + * @version New in 1.9 + * + * @retval KRB5_TRACE_NOSUPP Tracing is not supported in the library. + */ +krb5_error_code KRB5_CALLCONV +krb5_set_trace_filename(krb5_context context, const char *filename); + + +/** + * Hook function for inspecting or modifying messages sent to KDCs. + * + * @param [in] context Library context + * @param [in] data Callback data + * @param [in] realm The realm the message will be sent to + * @param [in] message The original message to be sent to the KDC + * @param [out] new_message_out Optional replacement message to be sent + * @param [out] new_reply_out Optional synthetic reply + * + * If the hook function returns an error code, the KDC communication will be + * aborted and the error code will be returned to the library operation which + * initiated the communication. + * + * If the hook function sets @a new_reply_out, @a message will not be sent to + * the KDC, and the given reply will used instead. + * + * If the hook function sets @a new_message_out, the given message will be sent + * to the KDC in place of @a message. + * + * If the hook function returns successfully without setting either output, + * @a message will be sent to the KDC normally. + * + * The hook function should use krb5_copy_data() to construct the value for + * @a new_message_out or @a reply_out, to ensure that it can be freed correctly + * by the library. + * + * @version New in 1.15 + * + * @retval 0 Success + * @return A Kerberos error code + */ +typedef krb5_error_code +(KRB5_CALLCONV *krb5_pre_send_fn)(krb5_context context, void *data, + const krb5_data *realm, + const krb5_data *message, + krb5_data **new_message_out, + krb5_data **new_reply_out); + +/** + * Hook function for inspecting or overriding KDC replies. + * + * @param [in] context Library context + * @param [in] data Callback data + * @param [in] code Status of KDC communication + * @param [in] realm The realm the reply was received from + * @param [in] message The message sent to the realm's KDC + * @param [in] reply The reply received from the KDC + * @param [out] new_reply_out Optional replacement reply + * + * If @a code is zero, @a reply contains the reply received from the KDC. The + * hook function may return an error code to simulate an error, may synthesize + * a different reply by setting @a new_reply_out, or may simply return + * successfully to do nothing. + * + * If @a code is non-zero, KDC communication failed and @a reply should be + * ignored. The hook function may return @a code or a different error code, or + * may synthesize a reply by setting @a new_reply_out and return successfully. + * + * The hook function should use krb5_copy_data() to construct the value for + * @a new_reply_out, to ensure that it can be freed correctly by the library. + * + * @version New in 1.15 + * + * @retval 0 Success + * @return A Kerberos error code + */ +typedef krb5_error_code +(KRB5_CALLCONV *krb5_post_recv_fn)(krb5_context context, void *data, + krb5_error_code code, + const krb5_data *realm, + const krb5_data *message, + const krb5_data *reply, + krb5_data **new_reply_out); + +/** + * Set a KDC pre-send hook function. + * + * @param [in] context Library context + * @param [in] send_hook Hook function (or NULL to disable the hook) + * @param [in] data Callback data to be passed to @a send_hook + * + * @a send_hook will be called before messages are sent to KDCs by library + * functions such as krb5_get_credentials(). The hook function may inspect, + * override, or synthesize its own reply to the message. + * + * @version New in 1.15 + */ +void KRB5_CALLCONV +krb5_set_kdc_send_hook(krb5_context context, krb5_pre_send_fn send_hook, + void *data); + +/** + * Set a KDC post-receive hook function. + * + * @param [in] context The library context. + * @param [in] recv_hook Hook function (or NULL to disable the hook) + * @param [in] data Callback data to be passed to @a recv_hook + * + * @a recv_hook will be called after a reply is received from a KDC during a + * call to a library function such as krb5_get_credentials(). The hook + * function may inspect or override the reply. This hook will not be executed + * if the pre-send hook returns a synthetic reply. + * + * @version New in 1.15 + */ +void KRB5_CALLCONV +krb5_set_kdc_recv_hook(krb5_context context, krb5_post_recv_fn recv_hook, + void *data); + +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)) +#pragma pack(pop) +#endif + +KRB5INT_END_DECLS + +/* Don't use this! We're going to phase it out. It's just here to keep + applications from breaking right away. */ +#define krb5_const const + +#undef KRB5_ATTR_DEPRECATED + +#endif /* KRB5_GENERAL__ */ diff --git a/krb5-1.21.3/src/include/krb5/localauth_plugin.h b/krb5-1.21.3/src/include/krb5/localauth_plugin.h new file mode 100644 index 00000000..df7574ee --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/localauth_plugin.h @@ -0,0 +1,138 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * 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. + */ + +/* + * Declarations for localauth plugin module implementors. + * + * The localauth pluggable interface currently has only one supported major + * version, which is 1. Major version 1 has a current minor version number of + * 1. + * + * Localauth plugin modules should define a function named + * localauth__initvt, matching the signature: + * + * krb5_error_code + * localauth_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for maj_ver: + * maj_ver == 1: Cast to krb5_localauth_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_LOCALAUTH_PLUGIN_H +#define KRB5_LOCALAUTH_PLUGIN_H + +#include +#include + +/* An abstract type for localauth module data. */ +typedef struct krb5_localauth_moddata_st *krb5_localauth_moddata; + +/*** Method type declarations ***/ + +/* Optional: Initialize module data. */ +typedef krb5_error_code +(*krb5_localauth_init_fn)(krb5_context context, + krb5_localauth_moddata *data); + +/* Optional: Release resources used by module data. */ +typedef void +(*krb5_localauth_fini_fn)(krb5_context context, krb5_localauth_moddata data); + +/* + * Optional: Determine whether aname is authorized to log in as the local + * account lname. Return 0 if aname is authorized, EPERM if aname is + * authoritatively not authorized, KRB5_PLUGIN_NO_HANDLE if the module cannot + * determine whether aname is authorized, and any other error code for a + * serious failure to process the request. aname will be considered authorized + * if at least one module returns 0 and all other modules return + * KRB5_PLUGIN_NO_HANDLE. + */ +typedef krb5_error_code +(*krb5_localauth_userok_fn)(krb5_context context, krb5_localauth_moddata data, + krb5_const_principal aname, const char *lname); + +/* + * Optional (mandatory if an2ln_types is set): Determine the local account name + * corresponding to aname. Return 0 and set *lname_out if a mapping can be + * determined; the contents of *lname_out will later be released with a call to + * the module's free_string method. Return KRB5_LNAME_NOTRANS if no mapping + * can be determined. Return any other error code for a serious failure to + * process the request; this will halt the krb5_aname_to_localname operation. + * + * If the module's an2ln_types field is set, this method will only be invoked + * when a profile "auth_to_local" value references one of the module's types. + * type and residual will be set to the type and residual of the auth_to_local + * value. + * + * If the module's an2ln_types field is not set but the an2ln method is + * implemented, this method will be invoked independently of the profile's + * auth_to_local settings, with type and residual set to NULL. If multiple + * modules are registered with an2ln methods but no an2ln_types field, the + * order of invocation is not defined, but all such modules will be consulted + * before the built-in mechanisms are tried. + */ +typedef krb5_error_code +(*krb5_localauth_an2ln_fn)(krb5_context context, krb5_localauth_moddata data, + const char *type, const char *residual, + krb5_const_principal aname, char **lname_out); + +/* + * Optional (mandatory if an2ln is implemented): Release the memory returned by + * an invocation of an2ln. + */ +typedef void +(*krb5_localauth_free_string_fn)(krb5_context context, + krb5_localauth_moddata data, char *str); + +/* localauth vtable for major version 1. */ +typedef struct krb5_localauth_vtable_st { + const char *name; /* Mandatory: name of module. */ + const char **an2ln_types; /* Optional: uppercase auth_to_local types */ + krb5_localauth_init_fn init; + krb5_localauth_fini_fn fini; + krb5_localauth_userok_fn userok; + krb5_localauth_an2ln_fn an2ln; + krb5_localauth_free_string_fn free_string; + /* Minor version 1 ends here. */ +} *krb5_localauth_vtable; + +#endif /* KRB5_LOCALAUTH_PLUGIN_H */ diff --git a/krb5-1.21.3/src/include/krb5/locate_plugin.h b/krb5-1.21.3/src/include/krb5/locate_plugin.h new file mode 100644 index 00000000..7a872a15 --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/locate_plugin.h @@ -0,0 +1,62 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * Service location plugin definitions for Kerberos 5. + */ + +#ifndef KRB5_LOCATE_PLUGIN_H_INCLUDED +#define KRB5_LOCATE_PLUGIN_H_INCLUDED +#include + +enum locate_service_type { + locate_service_kdc = 1, + locate_service_primary_kdc, + locate_service_kadmin, + locate_service_krb524, + locate_service_kpasswd +}; +#define locate_service_master_kdc locate_service_primary_kdc + +typedef struct krb5plugin_service_locate_ftable { + int minor_version; /* currently 0 */ + /* Per-context setup and teardown. Returned void* blob is + private to the plugin. */ + krb5_error_code (*init)(krb5_context, void **); + void (*fini)(void *); + /* Callback function returns non-zero if the plugin function + should quit and return; this may be because of an error, or may + indicate we've already contacted the service, whatever. The + lookup function should only return an error if it detects a + problem, not if the callback function tells it to quit. */ + krb5_error_code (*lookup)(void *, + enum locate_service_type svc, const char *realm, + int socktype, int family, + int (*cbfunc)(void *,int,struct sockaddr *), + void *cbdata); +} krb5plugin_service_locate_ftable; +/* extern krb5plugin_service_locate_ftable service_locator; */ +#endif diff --git a/krb5-1.21.3/src/include/krb5/plugin.h b/krb5-1.21.3/src/include/krb5/plugin.h new file mode 100644 index 00000000..c575efa0 --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/plugin.h @@ -0,0 +1,46 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Generic declarations for dynamic modules implementing krb5 plugin + * modules. */ + +#ifndef KRB5_PLUGIN_H +#define KRB5_PLUGIN_H + +/* krb5_plugin_vtable is an abstract type. Module initvt functions will cast + * it to the appropriate interface-specific vtable type. */ +typedef struct krb5_plugin_vtable_st *krb5_plugin_vtable; + +/* + * krb5_plugin_initvt_fn is the type of all module initvt functions. Based on + * the maj_ver argument, the initvt function should cast vtable to the + * appropriate type and then fill it in. If a vtable has been expanded, + * min_ver indicates which version of the vtable is being filled in. + */ +typedef krb5_error_code +(*krb5_plugin_initvt_fn)(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +#endif /* KRB5_PLUGIN_H */ diff --git a/krb5-1.21.3/src/include/krb5/preauth_plugin.h b/krb5-1.21.3/src/include/krb5/preauth_plugin.h new file mode 100644 index 00000000..cd684463 --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/preauth_plugin.h @@ -0,0 +1,41 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2012 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. + */ + +/* This header includes the clpreauth and kdcpreauth interface declarations, + * for backward compatibility and convenience. */ + +#ifndef KRB5_PREAUTH_PLUGIN_H +#define KRB5_PREAUTH_PLUGIN_H + +#include +#include + +#endif /* KRB5_PREAUTH_PLUGIN_H */ diff --git a/krb5-1.21.3/src/include/krb5/pwqual_plugin.h b/krb5-1.21.3/src/include/krb5/pwqual_plugin.h new file mode 100644 index 00000000..00e7df97 --- /dev/null +++ b/krb5-1.21.3/src/include/krb5/pwqual_plugin.h @@ -0,0 +1,109 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Declarations for password quality plugin module implementors. + * + * The password quality pluggable interface currently has only one supported + * major version, which is 1. Major version 1 has a current minor version + * number of 1. + * + * Password quality plugin modules should define a function named + * pwqual__initvt, matching the signature: + * + * krb5_error_code + * pwqual_modname_initvt(krb5_context context, int maj_ver, int min_ver, + * krb5_plugin_vtable vtable); + * + * The initvt function should: + * + * - Check that the supplied maj_ver number is supported by the module, or + * return KRB5_PLUGIN_VER_NOTSUPP if it is not. + * + * - Cast the vtable pointer as appropriate for maj_ver: + * maj_ver == 1: Cast to krb5_pwqual_vtable + * + * - Initialize the methods of the vtable, stopping as appropriate for the + * supplied min_ver. Optional methods may be left uninitialized. + * + * Memory for the vtable is allocated by the caller, not by the module. + */ + +#ifndef KRB5_PWQUAL_PLUGIN_H +#define KRB5_PWQUAL_PLUGIN_H + +#include +#include +#include + +/* An abstract type for password quality module data. */ +typedef struct krb5_pwqual_moddata_st *krb5_pwqual_moddata; + +/*** Method type declarations ***/ + +/* Optional: Initialize module data. dictfile is the realm's configured + * dictionary filename. */ +typedef krb5_error_code +(*krb5_pwqual_open_fn)(krb5_context context, const char *dict_file, + krb5_pwqual_moddata *data); + +/* + * Mandatory: Check a password for the principal princ, which has an associated + * password policy named policy_name (or no associated policy if policy_name is + * NULL). The parameter languages, if not NULL, contains a null-terminated + * list of client-specified language tags as defined in RFC 5646. The method + * should return one of the following errors if the password fails quality + * standards: + * + * - KADM5_PASS_Q_TOOSHORT: password should be longer + * - KADM5_PASS_Q_CLASS: password must have more character classes + * - KADM5_PASS_Q_DICT: password contains dictionary words + * - KADM5_PASS_Q_GENERIC: unspecified quality failure + * + * The module should also set an extended error message with + * krb5_set_error_message(). The message may be localized according to one of + * the language tags in languages. + */ +typedef krb5_error_code +(*krb5_pwqual_check_fn)(krb5_context context, krb5_pwqual_moddata data, + const char *password, const char *policy_name, + krb5_principal princ, const char **languages); + +/* Optional: Release resources used by module data. */ +typedef void +(*krb5_pwqual_close_fn)(krb5_context context, krb5_pwqual_moddata data); + +/*** vtable declarations **/ + +/* Password quality plugin vtable for major version 1. */ +typedef struct krb5_pwqual_vtable_st { + const char *name; /* Mandatory: name of module. */ + krb5_pwqual_open_fn open; + krb5_pwqual_check_fn check; + krb5_pwqual_close_fn close; + /* Minor version 1 ends here. */ +} *krb5_pwqual_vtable; + +#endif /* KRB5_PWQUAL_PLUGIN_H */ diff --git a/krb5-1.21.3/src/include/net-server.h b/krb5-1.21.3/src/include/net-server.h new file mode 100644 index 00000000..a30749d8 --- /dev/null +++ b/krb5-1.21.3/src/include/net-server.h @@ -0,0 +1,102 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/net-server.h */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Declarations for "API" of network listener/dispatcher in libapputils. */ + +#ifndef NET_SERVER_H +#define NET_SERVER_H + +#include + +/* The delimiter characters supported by the addresses string. */ +#define ADDRESSES_DELIM ",; " + +typedef struct _krb5_fulladdr { + krb5_address * address; + krb5_ui_4 port; +} krb5_fulladdr; + +/* exported from network.c */ +void init_addr(krb5_fulladdr *, struct sockaddr *); + +/* exported from net-server.c */ +verto_ctx *loop_init(verto_ev_type types); + +/* + * Add listener addresses to the loop configuration. + * + * Arguments: + * + * - default_port + * The port for the sockets if not specified in addresses. + * - addresses + * The optional addresses for the listener sockets. Pass NULL for the + * wildcard address. Addresses may be delimited by the characters in + * ADDRESSES_DELIM. Addresses are parsed with k5_parse_host_string(). + * - prognum, versnum, dispatchfn + * For RPC listener sockets, the svc_register() arguments to use when new + * TCP connections are created. + */ +krb5_error_code loop_add_udp_address(int default_port, const char *addresses); +krb5_error_code loop_add_tcp_address(int default_port, const char *addresses); +krb5_error_code loop_add_rpc_service(int default_port, const char *addresses, + u_long prognum, u_long versnum, + void (*dispatchfn)()); + +krb5_error_code loop_setup_network(verto_ctx *ctx, void *handle, + const char *progname, + int tcp_listen_backlog); +krb5_error_code loop_setup_signals(verto_ctx *ctx, void *handle, + void (*reset)()); +void loop_free(verto_ctx *ctx); + +/* to be supplied by the server application */ + +/* + * Two routines for processing an incoming message and getting a + * result to send back. + * + * The first, dispatch(), is for normal processing of a request. The + * second, make_toolong_error(), is obviously for generating an error + * to send back when the incoming message is bigger than + * the main loop can accept. + */ +typedef void (*loop_respond_fn)(void *arg, krb5_error_code code, + krb5_data *response); +void dispatch(void *handle, const krb5_fulladdr *local_addr, + const krb5_fulladdr *remote_addr, krb5_data *request, + int is_tcp, verto_ctx *vctx, loop_respond_fn respond, void *arg); +krb5_error_code make_toolong_error (void *handle, krb5_data **); + +/* + * Contexts are needed in lots of places. Opaque application-provided + * handles are passed around in lots of place, but contexts are not. + * For now, we'll require that the application provide us an easy way + * to get at a context; eventually it should probably be explicitly. + */ +krb5_context get_context(void *handle); + +#endif /* NET_SERVER_H */ diff --git a/krb5-1.21.3/src/include/osconf.hin b/krb5-1.21.3/src/include/osconf.hin new file mode 100644 index 00000000..c24717be --- /dev/null +++ b/krb5-1.21.3/src/include/osconf.hin @@ -0,0 +1,141 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1990,1991,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Site- and OS- dependent configuration */ + +#ifndef KRB5_OSCONF__ +#define KRB5_OSCONF__ + +#if !defined(_WIN32) +/* Don't try to pull in autoconf.h for Windows, since it's not used */ +#ifndef KRB5_AUTOCONF__ +#define KRB5_AUTOCONF__ +#include "autoconf.h" +#endif +#endif + +#if defined(__MACH__) && defined(__APPLE__) +# include +#endif + +#if defined(_WIN32) +#define DEFAULT_PROFILE_FILENAME "krb5.ini" +#else /* !_WINDOWS */ +#if TARGET_OS_MAC +#define DEFAULT_SECURE_PROFILE_PATH "/Library/Preferences/edu.mit.Kerberos:/etc/krb5.conf@SYSCONFCONF" +#define DEFAULT_PROFILE_PATH ("~/Library/Preferences/edu.mit.Kerberos" ":" DEFAULT_SECURE_PROFILE_PATH) +#define KRB5_PLUGIN_BUNDLE_DIR "/System/Library/KerberosPlugins/KerberosFrameworkPlugins" +#define KDB5_PLUGIN_BUNDLE_DIR "/System/Library/KerberosPlugins/KerberosDatabasePlugins" +#define KRB5_AUTHDATA_PLUGIN_BUNDLE_DIR "/System/Library/KerberosPlugins/KerberosAuthDataPlugins" +#else +#define DEFAULT_SECURE_PROFILE_PATH "/etc/krb5.conf@SYSCONFCONF" +#define DEFAULT_PROFILE_PATH DEFAULT_SECURE_PROFILE_PATH +#endif +#endif /* _WINDOWS */ + +#ifdef _WIN32 +#define DEFAULT_PLUGIN_BASE_DIR "%{LIBDIR}\\plugins" +#else +#define DEFAULT_PLUGIN_BASE_DIR "@LIBDIR/krb5/plugins" +#endif + +#if defined(_WIN64) +#define PLUGIN_EXT "64.dll" +#elif defined(_WIN32) +#define PLUGIN_EXT "32.dll" +#else +#define PLUGIN_EXT "@DYNOBJEXT" +#endif + +#define KDC_DIR "@LOCALSTATEDIR/krb5kdc" +#define KDC_RUN_DIR "@RUNSTATEDIR/krb5kdc" +#define DEFAULT_KDB_FILE KDC_DIR "/principal" +#define DEFAULT_KEYFILE_STUB KDC_DIR "/.k5." +#define KRB5_DEFAULT_ADMIN_ACL KDC_DIR "/krb5_adm.acl" +/* Used by old admin server */ +#define DEFAULT_ADMIN_ACL KDC_DIR "/kadm_old.acl" + +/* Location of KDC profile */ +#define DEFAULT_KDC_PROFILE KDC_DIR "/kdc.conf" +#define KDC_PROFILE_ENV "KRB5_KDC_PROFILE" + +#if TARGET_OS_MAC +#define DEFAULT_KDB_LIB_PATH { KDB5_PLUGIN_BUNDLE_DIR, "@MODULEDIR/kdb", NULL } +#else +#define DEFAULT_KDB_LIB_PATH { "@MODULEDIR/kdb", NULL } +#endif + +#define DEFAULT_KDC_ENCTYPE ENCTYPE_AES256_CTS_HMAC_SHA1_96 +#define KDCRCACHE "dfl:krb5kdc_rcache" + +#define KDC_PORTNAME "kerberos" /* for /etc/services or equiv. */ + +#define KRB5_DEFAULT_PORT 88 + +#define DEFAULT_KPASSWD_PORT 464 + +#define DEFAULT_KDC_UDP_PORTLIST "88" +#define DEFAULT_KDC_TCP_PORTLIST "88" +#define DEFAULT_TCP_LISTEN_BACKLOG 5 + +/* + * Defaults for the KADM5 admin system. + */ +#define DEFAULT_KADM5_KEYTAB KDC_DIR "/kadm5.keytab" +#define DEFAULT_KADM5_ACL_FILE KDC_DIR "/kadm5.acl" +#define DEFAULT_KADM5_PORT 749 /* assigned by IANA */ + +#define KRB5_DEFAULT_SUPPORTED_ENCTYPES \ + "aes256-cts-hmac-sha1-96:normal " \ + "aes128-cts-hmac-sha1-96:normal" + +#define MAX_DGRAM_SIZE 65536 + +#define RCTMPDIR "@KRB5RCTMPDIR" /* directory to store replay caches */ + +#define KRB5_PATH_TTY "/dev/tty" +#define KRB5_PATH_LOGIN "@SBINDIR/login.krb5" +#define KRB5_PATH_RLOGIN "@BINDIR/rlogin" + +#define KRB5_ENV_CCNAME "KRB5CCNAME" + +/* + * krb5 replica support follows + */ + +#define KPROP_DEFAULT_FILE KDC_DIR "/replica_datatrans" +#define KPROPD_DEFAULT_FILE KDC_DIR "/from_master" +#define KPROPD_DEFAULT_KDB5_UTIL "@SBINDIR/kdb5_util" +#define KPROPD_DEFAULT_KPROP "@SBINDIR/kprop" +#define KPROPD_DEFAULT_KRB_DB DEFAULT_KDB_FILE +#define KPROPD_ACL_FILE KDC_DIR "/kpropd.acl" + +/* + * GSS mechglue + */ +#define MECH_CONF "@SYSCONFDIR/gss/mech" +#define MECH_LIB_PREFIX "@GSSMODULEDIR/" + +#endif /* KRB5_OSCONF__ */ diff --git a/krb5-1.21.3/src/include/port-sockets.h b/krb5-1.21.3/src/include/port-sockets.h new file mode 100644 index 00000000..57e5d1dd --- /dev/null +++ b/krb5-1.21.3/src/include/port-sockets.h @@ -0,0 +1,297 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#ifndef _PORT_SOCKET_H +#define _PORT_SOCKET_H +#if defined(_WIN32) + +#include +#include +#include + +/* Some of our own infrastructure where the Winsock stuff was too hairy + * to dump into a clean Unix program */ + +typedef WSABUF sg_buf; + +#define SG_ADVANCE(SG, N) \ + ((SG)->len < (N) \ + ? (abort(), 0) \ + : ((SG)->buf += (N), (SG)->len -= (N), 0)) + +#define SG_LEN(SG) ((SG)->len + 0) +#define SG_BUF(SG) ((SG)->buf + 0) +#define SG_SET(SG, B, N) ((SG)->buf = (char *)(B),(SG)->len = (N)) + +#define SOCKET_INITIALIZE() 0 +#define SOCKET_CLEANUP() +#define SOCKET_ERRNO (TranslatedWSAGetLastError()) +#define SOCKET_SET_ERRNO(x) (TranslatedWSASetLastError(x)) +#define SOCKET_NFDS(f) (0) /* select()'s first arg is ignored */ +#define SOCKET_READ(fd, b, l) (recv(fd, b, l, 0)) +#define SOCKET_WRITE(fd, b, l) (send(fd, b, l, 0)) +#define SOCKET_CONNECT connect /* XXX */ +#define SOCKET_GETSOCKNAME getsockname /* XXX */ +#define SOCKET_CLOSE close /* XXX */ +#define SOCKET_EINTR WSAEINTR + +/* + * Return -1 for error or number of bytes written. TMP is a temporary + * variable; must be declared by the caller, and must be used by this macro (to + * avoid compiler warnings). + */ +/* WSASend returns 0 or SOCKET_ERROR. */ +#define SOCKET_WRITEV_TEMP DWORD +#define SOCKET_WRITEV(FD, SG, LEN, TMP) \ + (WSASend((FD), (SG), (LEN), &(TMP), 0, 0, 0) ? \ + (ssize_t)-1 : (ssize_t)(TMP)) + +#define SHUTDOWN_READ SD_RECEIVE +#define SHUTDOWN_WRITE SD_SEND +#define SHUTDOWN_BOTH SD_BOTH + +/* + * Define any missing POSIX socket errors. This is for compatibility with + * older versions of MSVC (pre-2010). + */ +#ifndef EINPROGRESS +#define EINPROGRESS WSAEINPROGRESS +#endif +#ifndef EWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#endif +#ifndef ECONNRESET +#define ECONNRESET WSAECONNRESET +#endif +#ifndef ECONNABORTED +#define ECONNABORTED WSAECONNABORTED +#endif +#ifndef ECONNREFUSED +#define ECONNREFUSED WSAECONNREFUSED +#endif +#ifndef EHOSTUNREACH +#define EHOSTUNREACH WSAEHOSTUNREACH +#endif +#ifndef ETIMEDOUT +#define ETIMEDOUT WSAETIMEDOUT +#endif + +/* Translate posix_error to its Winsock counterpart and set the last Winsock + * error to the result. */ +static __inline void TranslatedWSASetLastError(int posix_error) +{ + int wsa_error; + switch (posix_error) { + case 0: + wsa_error = 0; break; + case EINPROGRESS: + wsa_error = WSAEINPROGRESS; break; + case EWOULDBLOCK: + wsa_error = WSAEWOULDBLOCK; break; + case ECONNRESET: + wsa_error = WSAECONNRESET; break; + case ECONNABORTED: + wsa_error = WSAECONNABORTED; break; + case ECONNREFUSED: + wsa_error = WSAECONNREFUSED; break; + case EHOSTUNREACH: + wsa_error = WSAEHOSTUNREACH; break; + case ETIMEDOUT: + wsa_error = WSAETIMEDOUT; break; + case EAFNOSUPPORT: + wsa_error = WSAEAFNOSUPPORT; break; + case EINVAL: + wsa_error = WSAEINVAL; break; + default: + /* Ideally, we would log via k5-trace here, but we have no context. */ + wsa_error = WSAEINVAL; break; + } + WSASetLastError(wsa_error); +} + +/* + * Translate Winsock errors to their POSIX counterparts. This is necessary for + * MSVC 2010+, where both Winsock and POSIX errors are defined. + */ +static __inline int TranslatedWSAGetLastError() +{ + int err = WSAGetLastError(); + switch (err) { + case 0: + break; + case WSAEINPROGRESS: + err = EINPROGRESS; break; + case WSAEWOULDBLOCK: + err = EWOULDBLOCK; break; + case WSAECONNRESET: + err = ECONNRESET; break; + case WSAECONNABORTED: + err = ECONNABORTED; break; + case WSAECONNREFUSED: + err = ECONNREFUSED; break; + case WSAEHOSTUNREACH: + err = EHOSTUNREACH; break; + case WSAETIMEDOUT: + err = ETIMEDOUT; break; + case WSAEAFNOSUPPORT: + err = EAFNOSUPPORT; break; + case WSAEINVAL: + err = EINVAL; break; + default: + /* Ideally, we would log via k5-trace here, but we have no context. */ + err = EINVAL; break; + } + return err; +} + +#elif defined(__palmos__) + +/* If this source file requires it, define struct sockaddr_in (and possibly + * other things related to network I/O). */ + +#include "autoconf.h" +#include +typedef int socklen_t; + +#else /* UNIX variants */ + +#include "autoconf.h" + +#include +#include /* For struct sockaddr_in and in_addr */ +#include /* For inet_ntoa */ +#include +#include /* For memset */ + +#ifndef HAVE_NETDB_H_H_ERRNO +extern int h_errno; /* In case it's missing, e.g., HP-UX 10.20. */ +#endif + +#include /* For MAXHOSTNAMELEN */ +#include /* For SOCK_*, AF_*, etc */ +#include /* For struct timeval */ +#include /* For struct ifconf, for localaddr.c */ +#ifdef HAVE_SYS_UIO_H +#include /* For struct iovec, for sg_buf */ +#endif +#ifdef HAVE_SYS_FILIO_H +#include /* For FIONBIO on Solaris. */ +#endif + +/* + * Either size_t or int or unsigned int is probably right. Under + * SunOS 4, it looks like int is desired, according to the accept man + * page. + */ +#ifndef HAVE_SOCKLEN_T +typedef int socklen_t; +#endif + +#ifndef HAVE_STRUCT_SOCKADDR_STORAGE +struct krb5int_sockaddr_storage { + struct sockaddr_in s; + /* Plenty of slop just in case we get an ipv6 address anyways. */ + long extra[16]; +}; +#define sockaddr_storage krb5int_sockaddr_storage +#endif + +/* Unix equivalents of Winsock calls */ +#define SOCKET int +#define INVALID_SOCKET ((SOCKET)~0) +#define closesocket close +#define ioctlsocket ioctl +#define SOCKET_ERROR (-1) + +typedef struct iovec sg_buf; + +#define SG_ADVANCE(SG, N) \ + ((SG)->iov_len < (N) \ + ? (abort(), 0) \ + : ((SG)->iov_base = (char *) (SG)->iov_base + (N), \ + (SG)->iov_len -= (N), 0)) + +#define SG_LEN(SG) ((SG)->iov_len + 0) +#define SG_BUF(SG) ((char*)(SG)->iov_base + 0) +#define SG_SET(SG, B, L) ((SG)->iov_base = (char*)(B), (SG)->iov_len = (L)) + +#define SOCKET_INITIALIZE() (0) /* No error (or anything else) */ +#define SOCKET_CLEANUP() /* nothing */ +#define SOCKET_ERRNO errno +#define SOCKET_SET_ERRNO(x) (errno = (x)) +#define SOCKET_NFDS(f) ((f)+1) /* select() arg for a single fd */ +#define SOCKET_READ read +#define SOCKET_WRITE write +static inline int +socket_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) +{ + int st; +#ifdef SO_NOSIGPIPE + int set = 1; +#endif + + st = connect(fd, addr, addrlen); + if (st == -1) + return st; + +#ifdef SO_NOSIGPIPE + st = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(set)); + if (st != 0) + st = -1; +#endif + + return st; +} +#define SOCKET_CONNECT socket_connect +#define SOCKET_GETSOCKNAME getsockname +#define SOCKET_CLOSE close +#define SOCKET_EINTR EINTR +#define SOCKET_WRITEV_TEMP int +static inline ssize_t +socket_sendmsg(SOCKET fd, sg_buf *iov, int iovcnt) +{ + struct msghdr msg; + int flags = 0; + +#ifdef MSG_NOSIGNAL + flags |= MSG_NOSIGNAL; +#endif + + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = iov; + msg.msg_iovlen = iovcnt; + + return sendmsg(fd, &msg, flags); +} +/* Use TMP to avoid compiler warnings and keep things consistent with + * Windows version. */ +#define SOCKET_WRITEV(FD, SG, LEN, TMP) \ + ((TMP) = socket_sendmsg((FD), (SG), (LEN)), (TMP)) + +#define SHUTDOWN_READ 0 +#define SHUTDOWN_WRITE 1 +#define SHUTDOWN_BOTH 2 + +#ifndef HAVE_INET_NTOP +#define inet_ntop(AF,SRC,DST,CNT) \ + ((AF) == AF_INET \ + ? ((CNT) < 16 \ + ? (SOCKET_SET_ERRNO(ENOSPC), (const char *)NULL) \ + : (sprintf((DST), "%d.%d.%d.%d", \ + ((const unsigned char *)(const void *)(SRC))[0] & 0xff, \ + ((const unsigned char *)(const void *)(SRC))[1] & 0xff, \ + ((const unsigned char *)(const void *)(SRC))[2] & 0xff, \ + ((const unsigned char *)(const void *)(SRC))[3] & 0xff), \ + (DST))) \ + : (SOCKET_SET_ERRNO(EAFNOSUPPORT), (const char *)NULL)) +#define HAVE_INET_NTOP +#endif + +#endif /* _WIN32 */ + +#if !defined(_WIN32) +/* UNIX or ...? */ +# ifdef S_SPLINT_S +extern int socket (int, int, int) /*@*/; +# endif +#endif + +#endif /*_PORT_SOCKET_H*/ diff --git a/krb5-1.21.3/src/include/socket-utils.h b/krb5-1.21.3/src/include/socket-utils.h new file mode 100644 index 00000000..e1f33aa3 --- /dev/null +++ b/krb5-1.21.3/src/include/socket-utils.h @@ -0,0 +1,146 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2001,2005 by the Massachusetts Institute of Technology, + * Cambridge, MA, USA. All Rights Reserved. + * + * This software is being provided to you, the LICENSEE, by the + * Massachusetts Institute of Technology (M.I.T.) under the following + * license. By obtaining, using and/or copying this software, you agree + * that you have read, understood, and will comply with these terms and + * conditions: + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute + * this software and its documentation for any purpose and without fee or + * royalty is hereby granted, provided that you agree to comply with the + * following copyright notice and statements, including the disclaimer, and + * that the same appear on ALL copies of the software and documentation, + * including modifications that you make for internal use or for + * distribution: + * + * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS + * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not + * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF + * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF + * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY + * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + * + * The name of the Massachusetts Institute of Technology or M.I.T. may NOT + * be used in advertising or publicity pertaining to distribution of the + * software. Title to copyright in this software and any associated + * documentation shall at all times remain with M.I.T., and USER agrees to + * preserve same. + * + * Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + */ + +#ifndef SOCKET_UTILS_H +#define SOCKET_UTILS_H + +/* Some useful stuff cross-platform for manipulating socket addresses. + We assume at least ipv4 sockaddr_in support. The sockaddr_storage + stuff comes from the ipv6 socket api enhancements; socklen_t is + provided on some systems; the rest is just convenience for internal + use in the krb5 tree. + + Do NOT install this file. */ + +/* for HAVE_SOCKLEN_T etc */ +#include "autoconf.h" +/* for sockaddr_storage */ +#include "port-sockets.h" +/* for "inline" if needed */ +#include "k5-platform.h" + +/* + * There's a lot of confusion between pointers to different sockaddr + * types, and pointers with different degrees of indirection, as in + * the locate_kdc type functions. Use these function to ensure we + * don't do something silly like cast a "sockaddr **" to a + * "sockaddr_in *". + * + * The casts to (void *) are to get GCC to shut up about alignment + * increasing. + */ +static inline struct sockaddr_in *sa2sin (struct sockaddr *sa) +{ + return (struct sockaddr_in *) (void *) sa; +} +static inline struct sockaddr_in6 *sa2sin6 (struct sockaddr *sa) +{ + return (struct sockaddr_in6 *) (void *) sa; +} +static inline struct sockaddr *ss2sa (struct sockaddr_storage *ss) +{ + return (struct sockaddr *) ss; +} +static inline struct sockaddr_in *ss2sin (struct sockaddr_storage *ss) +{ + return (struct sockaddr_in *) ss; +} +static inline struct sockaddr_in6 *ss2sin6 (struct sockaddr_storage *ss) +{ + return (struct sockaddr_in6 *) ss; +} + +/* Set the IPv4 or IPv6 port on sa to port. Do nothing if sa is not an + * Internet socket. */ +static inline void +sa_setport(struct sockaddr *sa, uint16_t port) +{ + if (sa->sa_family == AF_INET) + sa2sin(sa)->sin_port = htons(port); + else if (sa->sa_family == AF_INET6) + sa2sin6(sa)->sin6_port = htons(port); +} + +/* Get the Internet port number of sa, or 0 if it is not an Internet socket. */ +static inline uint16_t +sa_getport(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) + return ntohs(sa2sin(sa)->sin_port); + else if (sa->sa_family == AF_INET6) + return ntohs(sa2sin6(sa)->sin6_port); + else + return 0; +} + +/* Return true if sa is an IPv4 or IPv6 socket address. */ +static inline int +sa_is_inet(struct sockaddr *sa) +{ + return sa->sa_family == AF_INET || sa->sa_family == AF_INET6; +} + +/* Return true if sa is an IPv4 or IPv6 wildcard address. */ +static inline int +sa_is_wildcard(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET6) + return IN6_IS_ADDR_UNSPECIFIED(&sa2sin6(sa)->sin6_addr); + else if (sa->sa_family == AF_INET) + return sa2sin(sa)->sin_addr.s_addr == INADDR_ANY; + return 0; +} + +/* Return the length of an IPv4 or IPv6 socket structure; abort if it is + * neither. */ +static inline socklen_t +sa_socklen(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET6) + return sizeof(struct sockaddr_in6); + else if (sa->sa_family == AF_INET) + return sizeof(struct sockaddr_in); + else + abort(); +} + +#endif /* SOCKET_UTILS_H */ diff --git a/krb5-1.21.3/src/include/win-mac.h b/krb5-1.21.3/src/include/win-mac.h new file mode 100644 index 00000000..0fd3a29e --- /dev/null +++ b/krb5-1.21.3/src/include/win-mac.h @@ -0,0 +1,239 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * This file is now only used on Windows + */ + +/* + * type functions split out of here to make things look nicer in the + * various include files which need these definitions, as well as in + * the util/ directories. + */ + +#ifndef _KRB5_WIN_MAC_H +#define _KRB5_WIN_MAC_H + +#ifdef _WIN32 +#define ID_READ_PWD_DIALOG 10000 +#define ID_READ_PWD_PROMPT 10001 +#define ID_READ_PWD_PROMPT2 10002 +#define ID_READ_PWD_PWD 10003 + +#ifdef RES_ONLY + +#define APSTUDIO_HIDDEN_SYMBOLS +#include + +#else /* ! RES_ONLY */ +#include +#ifdef DEBUG +#include +#endif + +/* To ensure backward compatibility of the ABI use 32-bit time_t on + * 32-bit Windows. + */ +#ifdef _KRB5_INT_H +#ifdef KRB5_GENERAL__ +#error krb5.h included before k5-int.h +#endif /* KRB5_GENERAL__ */ +#if _INTEGRAL_MAX_BITS >= 64 && _MSC_VER >= 1400 && !defined(_WIN64) && !defined(_USE_32BIT_TIME_T) +#if defined(_TIME_T_DEFINED) || defined(_INC_IO) || defined(_INC_TIME) || defined(_INC_WCHAR) +#error time_t has been defined as a 64-bit integer which is incompatible with Kerberos on this platform. +#endif /* _TIME_T_DEFINED */ +#define _USE_32BIT_TIME_T +#endif +#endif + +#define SIZEOF_INT 4 +#define SIZEOF_SHORT 2 +#define SIZEOF_LONG 4 + +#include +#include + +#ifndef SIZE_MAX /* in case Microsoft defines max size of size_t */ +#ifdef MAX_SIZE /* Microsoft defines MAX_SIZE as max size of size_t */ +#define SIZE_MAX MAX_SIZE +#else +#define SIZE_MAX UINT_MAX +#endif +#endif + +#ifndef KRB5_CALLCONV +# define KRB5_CALLCONV __stdcall +# define KRB5_CALLCONV_C __cdecl + +/* + * Use this to mark an incorrect calling convention that has been + * "immortalized" because it was incorrectly exported in a previous + * release. + */ + +# define KRB5_CALLCONV_WRONG KRB5_CALLCONV_C + +#endif /* !KRB5_CALLCONV */ + +#ifndef KRB5_SYSTYPES__ +#define KRB5_SYSTYPES__ +#include +typedef unsigned long u_long; /* Not part of sys/types.h on the pc */ +typedef unsigned int u_int; +typedef unsigned short u_short; +typedef unsigned char u_char; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned int uint32_t; +typedef int int32_t; +#if _INTEGRAL_MAX_BITS >= 64 +typedef unsigned __int64 uint64_t; +typedef __int64 int64_t; +#endif +#ifndef SSIZE_T_DEFINED +#ifdef ssize_t +#undef ssize_t +#endif +#ifdef _WIN64 +typedef __int64 ssize_t; +#else +typedef _W64 int ssize_t; +#endif +#define SSIZE_T_DEFINED +#endif +#endif /* KRB5_SYSTYPES__ */ + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 512 +#endif + +#ifndef MAXPATHLEN +#define MAXPATHLEN 256 /* Also for Windows temp files */ +#endif + +#ifdef KRB5_PRIVATE +#define HAVE_NETINET_IN_H +#define MSDOS_FILESYSTEM +#define HAVE_STRING_H +#define HAVE_SRAND +#define HAVE_ERRNO +#define HAVE_STRDUP +#define HAVE_GETADDRINFO +#define HAVE_GETNAMEINFO +#define NO_USERID +#define NO_PASSWORD +#define HAVE_STRERROR +#define SYS_ERRLIST_DECLARED +#if _MSC_VER >= 1900 +#define HAVE_VSNPRINTF +#endif +/* Visual Studio 2012 errors out when we macroize keywords in C++ mode */ +#ifndef __cplusplus +#define inline __inline +#endif +#define NEED_INSIXADDR_ANY +#define ENABLE_THREADS +#endif + +#define WM_KERBEROS5_CHANGED "Kerberos5 Changed" +#ifdef KRB4 +#define WM_KERBEROS_CHANGED "Kerberos Changed" +#endif + +/* Kerberos Windows initialization file */ +#define KERBEROS_INI "kerberos.ini" +#ifdef CYGNUS +#define KERBEROS_HLP "kerbnet.hlp" +#else +#define KERBEROS_HLP "krb5clnt.hlp" +#endif +#define INI_DEFAULTS "Defaults" +#define INI_USER "User" /* Default user */ +#define INI_INSTANCE "Instance" /* Default instance */ +#define INI_REALM "Realm" /* Default realm */ +#define INI_POSITION "Position" +#define INI_OPTIONS "Options" +#define INI_DURATION "Duration" /* Ticket duration in minutes */ +#define INI_EXPIRATION "Expiration" /* Action on expiration (alert or beep) */ +#define INI_ALERT "Alert" +#define INI_BEEP "Beep" +#define INI_FILES "Files" +#ifdef KRB4 +#define INI_KRB_CONF "krb.conf" /* Location of krb.conf file */ +#define DEF_KRB_CONF "krb.conf" /* Default name for krb.conf file */ +#else +#define INI_KRB5_CONF "krb5.ini" /* From k5-config.h */ +#define INI_KRB_CONF INI_KRB5_CONF /* Location of krb.conf file */ +#define DEF_KRB_CONF INI_KRB5_CONF /* Default name for krb.conf file */ +#define INI_TICKETOPTS "TicketOptions" /* Ticket options */ +#define INI_FORWARDABLE "Forwardable" /* get forwardable tickets */ +#define INI_KRB_CCACHE "krb5cc" /* From k5-config.h */ +#endif +#define INI_KRB_REALMS "krb.realms" /* Location of krb.realms file */ +#define DEF_KRB_REALMS "krb.realms" /* Default name for krb.realms file */ +#define INI_RECENT_LOGINS "Recent Logins" +#define INI_LOGIN "Login" + +#ifdef KRB5_PRIVATE +#define HAS_VOID_TYPE +#define HAVE_STDARG_H +#define HAVE_SYS_TYPES_H +#define HAVE_STDLIB_H +#endif + +/* Ugly. Microsoft, in stdc mode, doesn't support the low-level i/o + * routines directly. Rather, they only export the _ version. + * The following defines works around this problem. + */ +#include +#include +#include +#include +#include +#include + +#ifdef NEED_SYSERROR +/* Only needed by util/et/error_message.c but let's keep the source clean */ +#define sys_nerr _sys_nerr +#define sys_errlist _sys_errlist +#endif + +/* + * Functions with slightly different names on the PC + */ +#ifndef strcasecmp +#define strcasecmp _stricmp +#endif +#ifndef strncasecmp +#define strncasecmp _strnicmp +#endif + +/* VS2005 has deprecated strdup */ +#ifndef strdup +#define strdup _strdup +#endif + +/* Windows has its own name for reentrant strtok. */ +#define strtok_r strtok_s + +HINSTANCE get_lib_instance(void); + +#define GETSOCKNAME_ARG3_TYPE size_t +#define GETPEERNAME_ARG3_TYPE GETSOCKNAME_ARG3_TYPE + +#endif /* !RES_ONLY */ + +#endif /* _WIN32 */ + +#define THREEPARAMOPEN(x,y,z) open(x,y,z) + +#define DEFKTNAME "FILE:%{WINDOWS}\\krb5kt" +#define DEFCKTNAME "FILE:%{WINDOWS}\\krb5clientkt" + +#ifndef KRB5_CALLCONV +#define KRB5_CALLCONV +#endif + +#ifndef KRB5_CALLCONV_C +#define KRB5_CALLCONV_C +#endif + +#endif /* _KRB5_WIN_MAC_H */ diff --git a/krb5-1.21.3/src/kadmin/Makefile.in b/krb5-1.21.3/src/kadmin/Makefile.in new file mode 100644 index 00000000..87cfa43f --- /dev/null +++ b/krb5-1.21.3/src/kadmin/Makefile.in @@ -0,0 +1,6 @@ +mydir=kadmin +BUILDTOP=$(REL).. +SUBDIRS = cli dbutil ktutil server + +all: + diff --git a/krb5-1.21.3/src/kadmin/cli/Makefile.in b/krb5-1.21.3/src/kadmin/cli/Makefile.in new file mode 100644 index 00000000..adfea6e2 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/cli/Makefile.in @@ -0,0 +1,39 @@ +mydir=kadmin$(S)cli +BUILDTOP=$(REL)..$(S).. +KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS) + +PROG = kadmin +COMMON_OBJS = kadmin.o kadmin_ct.o ss_wrapper.o getdate.o +KADMIN_OBJS = $(COMMON_OBJS) keytab.o +LOCAL_OBJS = $(COMMON_OBJS) keytab_local.o + +SRCS = kadmin.c kadmin_ct.c ss_wrapper.c getdate.c keytab.c keytab_local.c + +LOCALINCLUDES=-I$(srcdir) + +all: $(PROG).local $(PROG) + +$(PROG).local: $(LOCAL_OBJS) $(SS_DEPLIB) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $(PROG).local $(LOCAL_OBJS) $(SS_LIB) $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS) + +$(PROG): $(KADMIN_OBJS) $(SS_DEPLIB) $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $(PROG) $(KADMIN_OBJS) $(SS_LIB) $(KADMCLNT_LIBS) $(KRB5_BASE_LIBS) + +kadmin_ct.o: kadmin_ct.c + +install: + $(INSTALL_PROGRAM) $(PROG).local ${DESTDIR}$(ADMIN_BINDIR)/$(PROG).local + $(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(CLIENT_BINDIR)/$(PROG) + $(INSTALL_SCRIPT) $(srcdir)/k5srvutil.sh ${DESTDIR}$(CLIENT_BINDIR)/k5srvutil + +generate-files-mac: kadmin_ct.c getdate.c + +clean: + $(RM) $(PROG).local $(PROG) $(COMMON_OBJS) $(KADMIN_OBJS) $(LOCAL_OBJS) +clean-unix:: + $(RM) datetest getdate.c kadmin_ct.c + +# for testing getdate.y +# CC_LINK is not meant for compilation and this use may break in the future. +datetest: getdate.c + $(CC_LINK) $(ALL_CFLAGS) -DTEST -o datetest getdate.c diff --git a/krb5-1.21.3/src/kadmin/cli/deps b/krb5-1.21.3/src/kadmin/cli/deps new file mode 100644 index 00000000..a5873fc7 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/cli/deps @@ -0,0 +1,70 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kadmin.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kadmin.c kadmin.h +$(OUTPRE)kadmin_ct.$(OBJEXT): $(COM_ERR_DEPS) $(SS_DEPS) \ + kadmin_ct.c +$(OUTPRE)ss_wrapper.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SS_DEPS) \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + kadmin.h ss_wrapper.c +$(OUTPRE)getdate.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + getdate.c +$(OUTPRE)keytab.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kadmin.h keytab.c +$(OUTPRE)keytab_local.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kadmin.h keytab.c keytab_local.c diff --git a/krb5-1.21.3/src/kadmin/cli/getdate.y b/krb5-1.21.3/src/kadmin/cli/getdate.y new file mode 100644 index 00000000..d14cf963 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/cli/getdate.y @@ -0,0 +1,1047 @@ +%{ +/* +** Originally written by Steven M. Bellovin while +** at the University of North Carolina at Chapel Hill. Later tweaked by +** a couple of people on Usenet. Completely overhauled by Rich $alz +** and Jim Berets in August, 1990; +** send any email to Rich. +** +** This grammar has four shift/reduce conflicts. +** +** This code is in the public domain and has no copyright. +*/ +/* SUPPRESS 287 on yaccpar_sccsid *//* Unusd static variable */ +/* SUPPRESS 288 on yyerrlab *//* Label unused */ + +#include "autoconf.h" +#include + +/* Since the code of getdate.y is not included in the Emacs executable + itself, there is no need to #define static in this file. Even if + the code were included in the Emacs executable, it probably + wouldn't do any harm to #undef it here; this will only cause + problems if we try to write to a static variable, which I don't + think this code needs to do. */ +#ifdef emacs +#undef static +#endif + +/* The following block of alloca-related preprocessor directives is here + solely to allow compilation by non GNU-C compilers of the C parser + produced from this file by old versions of bison. Newer versions of + bison include a block similar to this one in bison.simple. */ + +#ifdef __GNUC__ +#undef alloca +#define alloca __builtin_alloca +#else +#ifdef HAVE_ALLOCA_H +#include +#else +#ifdef _AIX /* for Bison */ + #pragma alloca +#else +void *alloca (); +#endif +#endif +#endif + +#include +#include + +#if defined(HAVE_STDLIB_H) +#include +#endif + +/* The code at the top of get_date which figures out the offset of the + current time zone checks various CPP symbols to see if special + tricks are need, but defaults to using the gettimeofday system call. + Include if that will be used. */ + +#if defined(vms) + +#include +#include + +#else + +#include + +#ifdef HAVE_SYS_TIME_H +#include +#endif +#include + +#ifdef timezone +#undef timezone /* needed for sgi */ +#endif + +/* +** We use the obsolete `struct my_timeb' as part of our interface! +** Since the system doesn't have it, we define it here; +** our callers must do likewise. +*/ +struct my_timeb { + time_t time; /* Seconds since the epoch */ + unsigned short millitm; /* Field not used */ + short timezone; /* Minutes west of GMT */ + short dstflag; /* Field not used */ +}; +#endif /* defined(vms) */ + +#if defined (STDC_HEADERS) || defined (USG) +#include +#endif + +/* Some old versions of bison generate parsers that use bcopy. + That loses on systems that don't provide the function, so we have + to redefine it here. */ +#ifndef bcopy +#define bcopy(from, to, len) memcpy ((to), (from), (len)) +#endif + +extern struct tm *gmtime(); +extern struct tm *localtime(); + +#define yyparse getdate_yyparse +#define yylex getdate_yylex +#define yyerror getdate_yyerror + +static int getdate_yylex (void); +static int getdate_yyerror (char *); + + +#define EPOCH 1970 +#define EPOCH_END 2106 /* assumes unsigned 32-bit range */ +#define HOUR(x) ((time_t)(x) * 60) +#define SECSPERDAY (24L * 60L * 60L) + + +/* +** An entry in the lexical lookup table. +*/ +typedef struct _TABLE { + char *name; + int type; + time_t value; +} TABLE; + + +/* +** Daylight-savings mode: on, off, or not yet known. +*/ +typedef enum _DSTMODE { + DSTon, DSToff, DSTmaybe +} DSTMODE; + +/* +** Meridian: am, pm, or 24-hour style. +*/ +typedef enum _MERIDIAN { + MERam, MERpm, MER24 +} MERIDIAN; + + +/* +** Global variables. We could get rid of most of these by using a good +** union as the yacc stack. (This routine was originally written before +** yacc had the %union construct.) Maybe someday; right now we only use +** the %union very rarely. +*/ +static char *yyInput; +static DSTMODE yyDSTmode; +static time_t yyDayOrdinal; +static time_t yyDayNumber; +static int yyHaveDate; +static int yyHaveDay; +static int yyHaveRel; +static int yyHaveTime; +static int yyHaveZone; +static time_t yyTimezone; +static time_t yyDay; +static time_t yyHour; +static time_t yyMinutes; +static time_t yyMonth; +static time_t yySeconds; +static time_t yyYear; +static MERIDIAN yyMeridian; +static time_t yyRelMonth; +static time_t yyRelSeconds; + +%} + +/* This would mute the shift/reduce warnings as per header comment; however, + * it relies on bison extensions. */ +/* %expect 4 */ + +%union { + time_t Number; + enum _MERIDIAN Meridian; +} + +%token tAGO tID tDST tNEVER +%token tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT +%token tSEC_UNIT tSNUMBER tUNUMBER tZONE +%token tMERIDIAN +%type o_merid + +%% + +spec : /* NULL */ + | spec item + | tNEVER { + yyYear = 1970; + yyMonth = 1; + yyDay = 1; + yyHour = yyMinutes = yySeconds = 0; + yyDSTmode = DSToff; + yyTimezone = 0; /* gmt */ + yyHaveDate++; + } + ; + +item : time { + yyHaveTime++; + } + | zone { + yyHaveZone++; + } + | date { + yyHaveDate++; + } + | day { + yyHaveDay++; + } + | rel { + yyHaveRel++; + } + ; + +time : tUNUMBER tMERIDIAN { + yyHour = $1; + yyMinutes = 0; + yySeconds = 0; + yyMeridian = $2; + } + | tUNUMBER ':' tUNUMBER o_merid { + yyHour = $1; + yyMinutes = $3; + yySeconds = 0; + yyMeridian = $4; + } + | tUNUMBER ':' tUNUMBER tSNUMBER { + yyHour = $1; + yyMinutes = $3; + yyMeridian = MER24; + yyDSTmode = DSToff; + yyTimezone = - ($4 % 100 + ($4 / 100) * 60); + } + | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid { + yyHour = $1; + yyMinutes = $3; + yySeconds = $5; + yyMeridian = $6; + } + | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER { + yyHour = $1; + yyMinutes = $3; + yySeconds = $5; + yyMeridian = MER24; + yyDSTmode = DSToff; + yyTimezone = - ($6 % 100 + ($6 / 100) * 60); + } + ; + +zone : tZONE { + yyTimezone = $1; + yyDSTmode = DSToff; + } + | tDAYZONE { + yyTimezone = $1; + yyDSTmode = DSTon; + } + | + tZONE tDST { + yyTimezone = $1; + yyDSTmode = DSTon; + } + ; + +day : tDAY { + yyDayOrdinal = 1; + yyDayNumber = $1; + } + | tDAY ',' { + yyDayOrdinal = 1; + yyDayNumber = $1; + } + | tUNUMBER tDAY { + yyDayOrdinal = $1; + yyDayNumber = $2; + } + ; + +date : tUNUMBER '/' tUNUMBER { + yyMonth = $1; + yyDay = $3; + } + | tUNUMBER '/' tUNUMBER '/' tUNUMBER { + yyMonth = $1; + yyDay = $3; + yyYear = $5; + } + | tUNUMBER tSNUMBER tSNUMBER { + /* ISO 8601 format. yyyy-mm-dd. */ + yyYear = $1; + yyMonth = -$2; + yyDay = -$3; + } + | tUNUMBER tMONTH tSNUMBER { + /* e.g. 17-JUN-1992. */ + yyDay = $1; + yyMonth = $2; + yyYear = -$3; + } + | tMONTH tUNUMBER { + yyMonth = $1; + yyDay = $2; + } + | tMONTH tUNUMBER ',' tUNUMBER { + yyMonth = $1; + yyDay = $2; + yyYear = $4; + } + | tUNUMBER tMONTH { + yyMonth = $2; + yyDay = $1; + } + | tUNUMBER tMONTH tUNUMBER { + yyMonth = $2; + yyDay = $1; + yyYear = $3; + } + ; + +rel : relunit tAGO { + yyRelSeconds = -yyRelSeconds; + yyRelMonth = -yyRelMonth; + } + | relunit + ; + +relunit : tUNUMBER tMINUTE_UNIT { + yyRelSeconds += $1 * $2 * 60L; + } + | tSNUMBER tMINUTE_UNIT { + yyRelSeconds += $1 * $2 * 60L; + } + | tMINUTE_UNIT { + yyRelSeconds += $1 * 60L; + } + | tSNUMBER tSEC_UNIT { + yyRelSeconds += $1; + } + | tUNUMBER tSEC_UNIT { + yyRelSeconds += $1; + } + | tSEC_UNIT { + yyRelSeconds++; + } + | tSNUMBER tMONTH_UNIT { + yyRelMonth += $1 * $2; + } + | tUNUMBER tMONTH_UNIT { + yyRelMonth += $1 * $2; + } + | tMONTH_UNIT { + yyRelMonth += $1; + } + ; + +o_merid : /* NULL */ { + $$ = MER24; + } + | tMERIDIAN { + $$ = $1; + } + ; + +%% + +/* Month and day table. */ +static TABLE const MonthDayTable[] = { + { "january", tMONTH, 1 }, + { "february", tMONTH, 2 }, + { "march", tMONTH, 3 }, + { "april", tMONTH, 4 }, + { "may", tMONTH, 5 }, + { "june", tMONTH, 6 }, + { "july", tMONTH, 7 }, + { "august", tMONTH, 8 }, + { "september", tMONTH, 9 }, + { "sept", tMONTH, 9 }, + { "october", tMONTH, 10 }, + { "november", tMONTH, 11 }, + { "december", tMONTH, 12 }, + { "sunday", tDAY, 0 }, + { "monday", tDAY, 1 }, + { "tuesday", tDAY, 2 }, + { "tues", tDAY, 2 }, + { "wednesday", tDAY, 3 }, + { "wednes", tDAY, 3 }, + { "thursday", tDAY, 4 }, + { "thur", tDAY, 4 }, + { "thurs", tDAY, 4 }, + { "friday", tDAY, 5 }, + { "saturday", tDAY, 6 }, + { NULL } +}; + +/* Time units table. */ +static TABLE const UnitsTable[] = { + { "year", tMONTH_UNIT, 12 }, + { "month", tMONTH_UNIT, 1 }, + { "fortnight", tMINUTE_UNIT, 14 * 24 * 60 }, + { "week", tMINUTE_UNIT, 7 * 24 * 60 }, + { "day", tMINUTE_UNIT, 1 * 24 * 60 }, + { "hour", tMINUTE_UNIT, 60 }, + { "minute", tMINUTE_UNIT, 1 }, + { "min", tMINUTE_UNIT, 1 }, + { "second", tSEC_UNIT, 1 }, + { "sec", tSEC_UNIT, 1 }, + { NULL } +}; + +/* Assorted relative-time words. */ +static TABLE const OtherTable[] = { + { "tomorrow", tMINUTE_UNIT, 1 * 24 * 60 }, + { "yesterday", tMINUTE_UNIT, -1 * 24 * 60 }, + { "today", tMINUTE_UNIT, 0 }, + { "now", tMINUTE_UNIT, 0 }, + { "last", tUNUMBER, -1 }, + { "this", tMINUTE_UNIT, 0 }, + { "next", tUNUMBER, 2 }, + { "first", tUNUMBER, 1 }, +/* { "second", tUNUMBER, 2 }, */ + { "third", tUNUMBER, 3 }, + { "fourth", tUNUMBER, 4 }, + { "fifth", tUNUMBER, 5 }, + { "sixth", tUNUMBER, 6 }, + { "seventh", tUNUMBER, 7 }, + { "eighth", tUNUMBER, 8 }, + { "ninth", tUNUMBER, 9 }, + { "tenth", tUNUMBER, 10 }, + { "eleventh", tUNUMBER, 11 }, + { "twelfth", tUNUMBER, 12 }, + { "ago", tAGO, 1 }, + { "never", tNEVER, 0 }, + { NULL } +}; + +/* The timezone table. */ +/* Some of these are commented out because a time_t can't store a float. */ +static TABLE const TimezoneTable[] = { + { "gmt", tZONE, HOUR( 0) }, /* Greenwich Mean */ + { "ut", tZONE, HOUR( 0) }, /* Universal (Coordinated) */ + { "utc", tZONE, HOUR( 0) }, + { "wet", tZONE, HOUR( 0) }, /* Western European */ + { "bst", tDAYZONE, HOUR( 0) }, /* British Summer */ + { "wat", tZONE, HOUR( 1) }, /* West Africa */ + { "at", tZONE, HOUR( 2) }, /* Azores */ +#if 0 + /* For completeness. BST is also British Summer, and GST is + * also Guam Standard. */ + { "bst", tZONE, HOUR( 3) }, /* Brazil Standard */ + { "gst", tZONE, HOUR( 3) }, /* Greenland Standard */ +#endif +#if 0 + { "nft", tZONE, HOUR(3.5) }, /* Newfoundland */ + { "nst", tZONE, HOUR(3.5) }, /* Newfoundland Standard */ + { "ndt", tDAYZONE, HOUR(3.5) }, /* Newfoundland Daylight */ +#endif + { "ast", tZONE, HOUR( 4) }, /* Atlantic Standard */ + { "adt", tDAYZONE, HOUR( 4) }, /* Atlantic Daylight */ + { "est", tZONE, HOUR( 5) }, /* Eastern Standard */ + { "edt", tDAYZONE, HOUR( 5) }, /* Eastern Daylight */ + { "cst", tZONE, HOUR( 6) }, /* Central Standard */ + { "cdt", tDAYZONE, HOUR( 6) }, /* Central Daylight */ + { "mst", tZONE, HOUR( 7) }, /* Mountain Standard */ + { "mdt", tDAYZONE, HOUR( 7) }, /* Mountain Daylight */ + { "pst", tZONE, HOUR( 8) }, /* Pacific Standard */ + { "pdt", tDAYZONE, HOUR( 8) }, /* Pacific Daylight */ + { "yst", tZONE, HOUR( 9) }, /* Yukon Standard */ + { "ydt", tDAYZONE, HOUR( 9) }, /* Yukon Daylight */ + { "hst", tZONE, HOUR(10) }, /* Hawaii Standard */ + { "hdt", tDAYZONE, HOUR(10) }, /* Hawaii Daylight */ + { "cat", tZONE, HOUR(10) }, /* Central Alaska */ + { "ahst", tZONE, HOUR(10) }, /* Alaska-Hawaii Standard */ + { "nt", tZONE, HOUR(11) }, /* Nome */ + { "idlw", tZONE, HOUR(12) }, /* International Date Line West */ + { "cet", tZONE, -HOUR(1) }, /* Central European */ + { "met", tZONE, -HOUR(1) }, /* Middle European */ + { "mewt", tZONE, -HOUR(1) }, /* Middle European Winter */ + { "mest", tDAYZONE, -HOUR(1) }, /* Middle European Summer */ + { "swt", tZONE, -HOUR(1) }, /* Swedish Winter */ + { "sst", tDAYZONE, -HOUR(1) }, /* Swedish Summer */ + { "fwt", tZONE, -HOUR(1) }, /* French Winter */ + { "fst", tDAYZONE, -HOUR(1) }, /* French Summer */ + { "eet", tZONE, -HOUR(2) }, /* Eastern Europe, USSR Zone 1 */ + { "bt", tZONE, -HOUR(3) }, /* Baghdad, USSR Zone 2 */ +#if 0 + { "it", tZONE, -HOUR(3.5) },/* Iran */ +#endif + { "zp4", tZONE, -HOUR(4) }, /* USSR Zone 3 */ + { "zp5", tZONE, -HOUR(5) }, /* USSR Zone 4 */ +#if 0 + { "ist", tZONE, -HOUR(5.5) },/* Indian Standard */ +#endif + { "zp6", tZONE, -HOUR(6) }, /* USSR Zone 5 */ +#if 0 + /* For completeness. NST is also Newfoundland Stanard, and SST is + * also Swedish Summer. */ + { "nst", tZONE, -HOUR(6.5) },/* North Sumatra */ + { "sst", tZONE, -HOUR(7) }, /* South Sumatra, USSR Zone 6 */ +#endif /* 0 */ + { "wast", tZONE, -HOUR(7) }, /* West Australian Standard */ + { "wadt", tDAYZONE, -HOUR(7) }, /* West Australian Daylight */ +#if 0 + { "jt", tZONE, -HOUR(7.5) },/* Java (3pm in Cronusland!) */ +#endif + { "cct", tZONE, -HOUR(8) }, /* China Coast, USSR Zone 7 */ + { "jst", tZONE, -HOUR(9) }, /* Japan Standard, USSR Zone 8 */ + { "kst", tZONE, -HOUR(9) }, /* Korean Standard */ +#if 0 + { "cast", tZONE, -HOUR(9.5) },/* Central Australian Standard */ + { "cadt", tDAYZONE, -HOUR(9.5) },/* Central Australian Daylight */ +#endif + { "east", tZONE, -HOUR(10) }, /* Eastern Australian Standard */ + { "eadt", tDAYZONE, -HOUR(10) }, /* Eastern Australian Daylight */ + { "gst", tZONE, -HOUR(10) }, /* Guam Standard, USSR Zone 9 */ + { "kdt", tZONE, -HOUR(10) }, /* Korean Daylight */ + { "nzt", tZONE, -HOUR(12) }, /* New Zealand */ + { "nzst", tZONE, -HOUR(12) }, /* New Zealand Standard */ + { "nzdt", tDAYZONE, -HOUR(12) }, /* New Zealand Daylight */ + { "idle", tZONE, -HOUR(12) }, /* International Date Line East */ + { NULL } +}; + +/* ARGSUSED */ +static int +yyerror(char *s) +{ + return 0; +} + + +static time_t +ToSeconds(time_t Hours, time_t Minutes, time_t Seconds, MERIDIAN Meridian) +{ + if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59) + return -1; + switch (Meridian) { + case MER24: + if (Hours < 0 || Hours > 23) + return -1; + return (Hours * 60L + Minutes) * 60L + Seconds; + case MERam: + if (Hours < 1 || Hours > 12) + return -1; + return (Hours * 60L + Minutes) * 60L + Seconds; + case MERpm: + if (Hours < 1 || Hours > 12) + return -1; + return ((Hours + 12) * 60L + Minutes) * 60L + Seconds; + default: + abort (); + } + /* NOTREACHED */ +} + +/* + * From hh:mm:ss [am|pm] mm/dd/yy [tz], compute and return the number + * of seconds since 00:00:00 1/1/70 GMT. + */ +static time_t +Convert(time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes, + time_t Seconds, MERIDIAN Meridian, DSTMODE DSTmode) +{ + static int DaysInMonth[12] = { + 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + time_t tod; + time_t Julian; + int i; + struct tm *tm; + + if (Year < 0) + Year = -Year; + if (Year < 1900) + Year += 1900; + DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0) + ? 29 : 28; + if (Year < EPOCH + || Year > EPOCH_END + || Month < 1 || Month > 12 + /* Lint fluff: "conversion from long may lose accuracy" */ + || Day < 1 || Day > DaysInMonth[(int)--Month]) + return -1; + + for (Julian = Day - 1, i = 0; i < Month; i++) + Julian += DaysInMonth[i]; + for (i = EPOCH; i < Year; i++) + Julian += 365 + ((i % 4 == 0) && ((Year % 100 != 0) || + (Year % 400 == 0))); + Julian *= SECSPERDAY; + Julian += yyTimezone * 60L; + if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0) + return -1; + Julian += tod; + if (DSTmode == DSTon) + Julian -= 60 * 60; + else if (DSTmode == DSTmaybe) { + tm = localtime(&Julian); + if (tm == NULL) + return -1; + else if (tm->tm_isdst) + Julian -= 60 * 60; + } + return Julian; +} + + +static time_t +DSTcorrect(time_t Start, time_t Future, int *error) +{ + time_t StartDay; + time_t FutureDay; + struct tm *tm; + + tm = localtime(&Start); + if (tm == NULL) { + *error = 1; + return -1; + } + StartDay = (tm->tm_hour + 1) % 24; + tm = localtime(&Future); + if (tm == NULL) { + *error = 1; + return -1; + } + FutureDay = (tm->tm_hour + 1) % 24; + *error = 0; + return (Future - Start) + (StartDay - FutureDay) * 60L * 60L; +} + + +static time_t +RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber, int *error) +{ + struct tm *tm; + time_t now; + + now = Start; + tm = localtime(&now); + if (tm == NULL) { + *error = 1; + return -1; + } + now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7); + now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1); + return DSTcorrect(Start, now, error); +} + + +static time_t +RelativeMonth(time_t Start, time_t RelMonth) +{ + struct tm *tm; + time_t Month; + time_t Year; + time_t ret; + int error; + + if (RelMonth == 0) + return 0; + tm = localtime(&Start); + if (tm == NULL) + return -1; + Month = 12 * tm->tm_year + tm->tm_mon + RelMonth; + Year = Month / 12; + Month = Month % 12 + 1; + ret = Convert(Month, (time_t)tm->tm_mday, Year, + (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec, + MER24, DSTmaybe); + if (ret == -1) + return ret; + ret = DSTcorrect(Start, ret, &error); + if (error) + return -1; + return ret; +} + + +static int +LookupWord(char *buff) +{ + char *p; + char *q; + const TABLE *tp; + int i; + int abbrev; + + /* Make it lowercase. */ + for (p = buff; *p; p++) + if (isupper((int) *p)) + *p = tolower((int) *p); + + if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) { + yylval.Meridian = MERam; + return tMERIDIAN; + } + if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) { + yylval.Meridian = MERpm; + return tMERIDIAN; + } + + /* See if we have an abbreviation for a month. */ + if (strlen(buff) == 3) + abbrev = 1; + else if (strlen(buff) == 4 && buff[3] == '.') { + abbrev = 1; + buff[3] = '\0'; + } + else + abbrev = 0; + + for (tp = MonthDayTable; tp->name; tp++) { + if (abbrev) { + if (strncmp(buff, tp->name, 3) == 0) { + yylval.Number = tp->value; + return tp->type; + } + } + else if (strcmp(buff, tp->name) == 0) { + yylval.Number = tp->value; + return tp->type; + } + } + + for (tp = TimezoneTable; tp->name; tp++) + if (strcmp(buff, tp->name) == 0) { + yylval.Number = tp->value; + return tp->type; + } + + if (strcmp(buff, "dst") == 0) + return tDST; + + for (tp = UnitsTable; tp->name; tp++) + if (strcmp(buff, tp->name) == 0) { + yylval.Number = tp->value; + return tp->type; + } + + /* Strip off any plural and try the units table again. */ + i = strlen(buff) - 1; + if (buff[i] == 's') { + buff[i] = '\0'; + for (tp = UnitsTable; tp->name; tp++) + if (strcmp(buff, tp->name) == 0) { + yylval.Number = tp->value; + return tp->type; + } + buff[i] = 's'; /* Put back for "this" in OtherTable. */ + } + + for (tp = OtherTable; tp->name; tp++) + if (strcmp(buff, tp->name) == 0) { + yylval.Number = tp->value; + return tp->type; + } + + /* Drop out any periods and try the timezone table again. */ + for (i = 0, p = q = buff; *q; q++) + if (*q != '.') + *p++ = *q; + else + i++; + *p = '\0'; + if (i) + for (tp = TimezoneTable; tp->name; tp++) + if (strcmp(buff, tp->name) == 0) { + yylval.Number = tp->value; + return tp->type; + } + + return tID; +} + + +static int +yylex() +{ + char c; + char *p; + char buff[20]; + int Count; + int sign; + + for ( ; ; ) { + while (isspace((int) *yyInput)) + yyInput++; + + c = *yyInput; + if (isdigit((int) c) || c == '-' || c == '+') { + if (c == '-' || c == '+') { + sign = c == '-' ? -1 : 1; + if (!isdigit((int) (*++yyInput))) + /* skip the '-' sign */ + continue; + } + else + sign = 0; + for (yylval.Number = 0; isdigit((int) (c = *yyInput++)); ) + yylval.Number = 10 * yylval.Number + c - '0'; + yyInput--; + if (sign < 0) + yylval.Number = -yylval.Number; + return sign ? tSNUMBER : tUNUMBER; + } + if (isalpha((int) c)) { + for (p = buff; isalpha((int) (c = *yyInput++)) || c == '.'; ) + if (p < &buff[sizeof buff - 1]) + *p++ = c; + *p = '\0'; + yyInput--; + return LookupWord(buff); + } + if (c != '(') + return *yyInput++; + Count = 0; + do { + c = *yyInput++; + if (c == '\0') + return c; + if (c == '(') + Count++; + else if (c == ')') + Count--; + } while (Count > 0); + } +} + + +#define TM_YEAR_ORIGIN 1900 + +/* Yield A - B, measured in seconds. */ +static time_t +difftm(struct tm *a, struct tm *b) +{ + int ay = a->tm_year + (TM_YEAR_ORIGIN - 1); + int by = b->tm_year + (TM_YEAR_ORIGIN - 1); + return + ( + ( + ( + /* difference in day of year */ + a->tm_yday - b->tm_yday + /* + intervening leap days */ + + ((ay >> 2) - (by >> 2)) + - (ay/100 - by/100) + + ((ay/100 >> 2) - (by/100 >> 2)) + /* + difference in years * 365 */ + + (time_t)(ay-by) * 365 + )*24 + (a->tm_hour - b->tm_hour) + )*60 + (a->tm_min - b->tm_min) + )*60 + (a->tm_sec - b->tm_sec); +} + +/* For get_date extern declaration compatibility check... yuck. */ +#include +int yyparse(void); + +time_t get_date_rel(char *, time_t); +time_t get_date(char *); + +time_t +get_date_rel(char *p, time_t nowtime) +{ + struct my_timeb *now = NULL; + struct tm *tm, gmt; + struct my_timeb ftz; + time_t Start; + time_t tod; + time_t delta; + int error; + + yyInput = p; + if (now == NULL) { + now = &ftz; + + ftz.time = nowtime; + + if (! (tm = gmtime (&ftz.time))) + return -1; + gmt = *tm; /* Make a copy, in case localtime modifies *tm. */ + tm = localtime(&ftz.time); + if (tm == NULL) + return -1; + ftz.timezone = difftm (&gmt, tm) / 60; + } + + tm = localtime(&now->time); + if (tm == NULL) + return -1; + yyYear = tm->tm_year; + yyMonth = tm->tm_mon + 1; + yyDay = tm->tm_mday; + yyTimezone = now->timezone; + yyDSTmode = DSTmaybe; + yyHour = 0; + yyMinutes = 0; + yySeconds = 0; + yyMeridian = MER24; + yyRelSeconds = 0; + yyRelMonth = 0; + yyHaveDate = 0; + yyHaveDay = 0; + yyHaveRel = 0; + yyHaveTime = 0; + yyHaveZone = 0; + + /* + * When yyparse returns, zero or more of yyHave{Time,Zone,Date,Day,Rel} + * will have been incremented. The value is number of items of + * that type that were found; for all but Rel, more than one is + * illegal. + * + * For each yyHave indicator, the following values are set: + * + * yyHaveTime: + * yyHour, yyMinutes, yySeconds: hh:mm:ss specified, initialized + * to zeros above + * yyMeridian: MERam, MERpm, or MER24 + * yyTimeZone: time zone specified in minutes + * yyDSTmode: DSToff if yyTimeZone is set, otherwise unchanged + * (initialized above to DSTmaybe) + * + * yyHaveZone: + * yyTimezone: as above + * yyDSTmode: DSToff if a non-DST zone is specified, otherwise DSTon + * XXX don't understand interaction with yyHaveTime zone info + * + * yyHaveDay: + * yyDayNumber: 0-6 for Sunday-Saturday + * yyDayOrdinal: val specified with day ("second monday", + * Ordinal=2), otherwise 1 + * + * yyHaveDate: + * yyMonth, yyDay, yyYear: mm/dd/yy specified, initialized to + * today above + * + * yyHaveRel: + * yyRelSeconds: seconds specified with MINUTE_UNITs ("3 hours") or + * SEC_UNITs ("30 seconds") + * yyRelMonth: months specified with MONTH_UNITs ("3 months", "1 + * year") + * + * The code following yyparse turns these values into a single + * date stamp. + */ + if (yyparse() + || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1) + return -1; + + /* + * If an absolute time specified, set Start to the equivalent Unix + * timestamp. Otherwise, set Start to now, and if we do not have + * a relatime time (ie: only yyHaveZone), decrement Start to the + * beginning of today. + * + * By having yyHaveDay in the "absolute" list, "next Monday" means + * midnight next Monday. Otherwise, "next Monday" would mean the + * time right now, next Monday. It's not clear to me why the + * current behavior is preferred. + */ + if (yyHaveDate || yyHaveTime || yyHaveDay) { + Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds, + yyMeridian, yyDSTmode); + if (Start < 0) + return -1; + } + else { + Start = now->time; + if (!yyHaveRel) + Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec; + } + + /* + * Add in the relative time specified. RelativeMonth adds in the + * months, accounting for the fact that the actual length of "3 + * months" depends on where you start counting. + * + * XXX By having this separate from the previous block, we are + * allowing dates like "10:00am 3 months", which means 3 months + * from 10:00am today, or even "1/1/99 two days" which means two + * days after 1/1/99. + * + * XXX Shouldn't this only be done if yyHaveRel, just for + * thoroughness? + */ + Start += yyRelSeconds; + delta = RelativeMonth(Start, yyRelMonth); + if (delta == (time_t) -1) + return -1; + Start += delta; + + /* + * Now, if you specified a day of week and counter, add it in. By + * disallowing Date but allowing Time, you can say "5pm next + * monday". + * + * XXX The yyHaveDay && !yyHaveDate restriction should be enforced + * above and be able to cause failure. + */ + if (yyHaveDay && !yyHaveDate) { + tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber, &error); + if (error != 0) + return -1; + Start += tod; + } + + /* Have to do *something* with a legitimate -1 so it's distinguishable + * from the error return value. (Alternately could set errno on error.) */ + return Start == -1 ? 0 : Start; +} + + +time_t +get_date(char *p) +{ + return get_date_rel(p, time(NULL)); +} + + +#if defined(TEST) + +/* ARGSUSED */ +main(int ac, char *av[]) +{ + char buff[128]; + time_t d; + + (void)printf("Enter date, or blank line to exit.\n\t> "); + (void)fflush(stdout); + while (gets(buff) && buff[0]) { + d = get_date(buff); + if (d == -1) + (void)printf("Bad format - couldn't convert.\n"); + else + (void)printf("%s", ctime(&d)); + (void)printf("\t> "); + (void)fflush(stdout); + } + exit(0); + /* NOTREACHED */ +} +#endif /* defined(TEST) */ diff --git a/krb5-1.21.3/src/kadmin/cli/k5srvutil.sh b/krb5-1.21.3/src/kadmin/cli/k5srvutil.sh new file mode 100755 index 00000000..050fa877 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/cli/k5srvutil.sh @@ -0,0 +1,123 @@ +#!/bin/sh + +# list_princs keytab +# returns a list of principals in the keytab +# sorted and uniquified +list_princs() { + klist -k $keytab | awk '(NR > 3) {print $2}' | sort | uniq +} + +set_command() { + if [ x$command != x ] ; then + cmd_error Only one command can be specified + usage + exit 1 + fi + command=$1 +} + +#interactive_prompt prompt princ +# If in interactive mode return true if the principal should be acted on +# otherwise return true all the time +interactive_prompt() { + if [ $interactive = 0 ] ; then + return 0 + fi + printf "%s for %s? [yn]" "$1" "$2" + read ans + case $ans in + n*|N*) + return 1 + ;; + esac + return 0 + } + +cmd_error() { + echo $@ 2>&1 + } + +usage() { + echo "Usage: $0 [-i] [-f file] [-e keysalts] list|change|delete|delold" +} + + + +change_key() { + princs=`list_princs ` + for princ in $princs; do + if interactive_prompt "Change key " $princ; then + kadmin -k -t $keytab -p $princ -q \ + "ktadd -k $keytab $keysalts $princ" + fi + done + } + +delete_old_keys() { + princs=`list_princs ` + for princ in $princs; do + if interactive_prompt "Delete old keys " $princ; then + kadmin -k -t $keytab -p $princ -q "ktrem -k $keytab $princ old" + fi + done + } + +delete_keys() { + interactive=1 + princs=`list_princs ` + for princ in $princs; do + if interactive_prompt "Delete all keys " $princ; then + kadmin -p $princ -k -t $keytab -q "ktrem -k $keytab $princ all" + fi + done + } + + +keytab=/etc/krb5.keytab +interactive=0 +keysalts="" + +while [ $# -gt 0 ] ; do + opt=$1 + shift + case $opt in + "-f") + keytab=$1 + shift + ;; + "-i") + interactive=1 + ;; + "-e") + keysalts="$keysalts -e \"$1\"" + shift + ;; + change|delold|delete|list) + set_command $opt + ;; + *) + cmd_error Illegal option: $opt + usage + exit 1 + ;; + esac +done + + +case $command in + change) + change_key + ;; + delold) + delete_old_keys + ;; + delete) + delete_keys + ;; + list) + klist -k $keytab + ;; + *) + usage + ;; + esac diff --git a/krb5-1.21.3/src/kadmin/cli/kadmin.c b/krb5-1.21.3/src/kadmin/cli/kadmin.c new file mode 100644 index 00000000..f3ea6fae --- /dev/null +++ b/krb5-1.21.3/src/kadmin/cli/kadmin.c @@ -0,0 +1,1999 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1994, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Base functions for a kadmin command line interface using the OVSecure + * library */ + +/* for "_" macro */ +#include "k5-int.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ +#include +#include "kadmin.h" + +static krb5_boolean script_mode = FALSE; +int exit_status = 0; +char *def_realm = NULL; +char *whoami = NULL; + +void *handle = NULL; +krb5_context context; +char *ccache_name = NULL; + +int locked = 0; + +static void +info(const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 1, 2))) +#endif + ; + +static void +error(const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 1, 2))) +#endif + ; + +/* Like printf, but suppressed if script_mode is set. */ +static void +info(const char *fmt, ...) +{ + va_list ap; + + if (script_mode) + return; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} + +/* Like fprintf to stderr; also set exit_status if script_mode is set. */ +static void +error(const char *fmt, ...) +{ + va_list ap; + + if (script_mode) + exit_status = 1; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +static void +usage() +{ + error(_("Usage: %s [-r realm] [-p principal] [-q query] " + "[clnt|local args]\n" + " [command args...]\n" + "\tclnt args: [-s admin_server[:port]] " + "[[-c ccache]|[-k [-t keytab]]]|[-n] [-O | -N]\n" + "\tlocal args: [-x db_args]* [-d dbname] " + "[-e \"enc:salt ...\"] [-m] [-w password] " + "where,\n\t[-x db_args]* - any number of database specific " + "arguments.\n" + "\t\t\tLook at each database documentation for supported " + "arguments\n"), whoami); + exit(1); +} + +static char * +strdur(time_t duration) +{ + static char out[50]; + int neg, days, hours, minutes, seconds; + + if (duration < 0) { + duration *= -1; + neg = 1; + } else + neg = 0; + days = duration / (24 * 3600); + duration %= 24 * 3600; + hours = duration / 3600; + duration %= 3600; + minutes = duration / 60; + duration %= 60; + seconds = duration; + snprintf(out, sizeof(out), "%s%d %s %02d:%02d:%02d", neg ? "-" : "", + days, days == 1 ? "day" : "days", + hours, minutes, seconds); + return out; +} + +static const char * +strdate(krb5_timestamp when) +{ + struct tm *tm; + static char out[40]; + time_t lcltim = ts2tt(when); + + tm = localtime(&lcltim); + if (tm == NULL || + strftime(out, sizeof(out), "%a %b %d %H:%M:%S %Z %Y", tm) == 0) + strlcpy(out, "(error)", sizeof(out)); + return out; +} + +/* Parse a date string using getdate.y. On failure, output an error message + * and return (time_t)-1. */ +static time_t +parse_date(char *str, time_t now) +{ + time_t date; + + date = get_date_rel(str, now); + if (date == (time_t)-1) + error(_("Invalid date specification \"%s\".\n"), str); + return date; +} + +/* + * Parse a time interval. Use krb5_string_to_deltat() if it works; otherwise + * use getdate.y and subtract now, with sanity checks. On failure, output an + * error message and return (time_t)-1. + */ +static time_t +parse_interval(char *str, time_t now) +{ + time_t date; + krb5_deltat delta; + + if (krb5_string_to_deltat(str, &delta) == 0) + return delta; + + date = parse_date(str, now); + if (date == (time_t)-1) + return date; + + /* Interpret an absolute time of 0 (e.g. "never") as an interval of 0. */ + if (date == 0) + return 0; + + /* Don't return a negative interval if the date is in the past. */ + if (date < now) { + error(_("Interval specification \"%s\" is in the past.\n"), str); + return (time_t)-1; + } + + return date - now; +} + +/* this is a wrapper to go around krb5_parse_principal so we can set + the default realm up properly */ +static krb5_error_code +kadmin_parse_name(char *name, krb5_principal *principal) +{ + char *cp, *fullname; + krb5_error_code retval; + int result; + + /* assumes def_realm is initialized! */ + cp = strchr(name, '@'); + while (cp) { + if (cp - name && *(cp - 1) != '\\') + break; + else + cp = strchr(cp + 1, '@'); + } + if (cp == NULL) + result = asprintf(&fullname, "%s@%s", name, def_realm); + else + result = asprintf(&fullname, "%s", name); + if (result < 0) + return ENOMEM; + retval = krb5_parse_name(context, fullname, principal); + free(fullname); + return retval; +} + +static void +extended_com_err_fn(const char *myprog, errcode_t code, + const char *fmt, va_list args) +{ + const char *emsg; + + if (code) { + emsg = krb5_get_error_message(context, code); + error("%s: %s ", myprog, emsg); + krb5_free_error_message(context, emsg); + } else { + error("%s: ", myprog); + } + vfprintf(stderr, fmt, args); + error("\n"); +} + +/* Create a principal using the oldest appropriate kadm5 API. */ +static krb5_error_code +create_princ(kadm5_principal_ent_rec *princ, long mask, int n_ks, + krb5_key_salt_tuple *ks, char *pass) +{ + if (ks) + return kadm5_create_principal_3(handle, princ, mask, n_ks, ks, pass); + else + return kadm5_create_principal(handle, princ, mask, pass); +} + +/* Randomize a principal's password using the appropriate kadm5 API. */ +krb5_error_code +randkey_princ(void *lhandle, krb5_principal princ, krb5_boolean keepold, + int n_ks, krb5_key_salt_tuple *ks, krb5_keyblock **key, + int *n_keys) +{ + krb5_error_code ret; + + /* Try the newer API first, because the Solaris kadmind only creates DES + * keys when the old API is used. */ + ret = kadm5_randkey_principal_3(lhandle, princ, keepold, n_ks, ks, key, + n_keys); + + /* Fall back to the old version if we get an error and aren't using any new + * parameters. */ + if (ret == KADM5_RPC_ERROR && !keepold && ks == NULL) + ret = kadm5_randkey_principal(lhandle, princ, key, n_keys); + + return ret; +} + +static krb5_boolean +policy_exists(const char *name) +{ + kadm5_policy_ent_rec pol; + + if (kadm5_get_policy(handle, (char *)name, &pol) != 0) + return FALSE; + kadm5_free_policy_ent(handle, &pol); + return TRUE; +} + +void +kadmin_startup(int argc, char *argv[], char **request_out, char ***args_out) +{ + extern char *optarg; + char *princstr = NULL, *keytab_name = NULL, *query = NULL; + char *password = NULL; + char *luser, *canon, *cp; + int optchar, freeprinc = 0, use_keytab = 0, use_anonymous = 0; + struct passwd *pw; + kadm5_ret_t retval; + krb5_ccache cc; + krb5_principal princ; + kadm5_config_params params; + char **db_args = NULL; + int db_args_size = 0; + char *db_name = NULL; + char *svcname, *realm; + + memset(¶ms, 0, sizeof(params)); + + set_com_err_hook(extended_com_err_fn); + + retval = kadm5_init_krb5_context(&context); + if (retval) { + com_err(whoami, retval, _("while initializing krb5 library")); + exit(1); + } + + while ((optchar = getopt(argc, argv, + "+x:r:p:knq:w:d:s:mc:t:e:ON")) != EOF) { + switch (optchar) { + case 'x': + db_args_size++; + db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1)); + if (db_args == NULL) { + error(_("%s: Cannot initialize. Not enough memory\n"), whoami); + exit(1); + } + db_args[db_args_size - 1] = optarg; + db_args[db_args_size] = NULL; + break; + + case 'r': + def_realm = optarg; + break; + case 'p': + princstr = optarg; + break; + case 'c': + ccache_name = optarg; + break; + case 'k': + use_keytab++; + break; + case 'n': + use_anonymous++; + break; + case 't': + keytab_name = optarg; + break; + case 'w': + password = optarg; + break; + case 'q': + query = optarg; + break; + case 'd': + /* db_name has to be passed as part of the db_args. */ + free(db_name); + asprintf(&db_name, "dbname=%s", optarg); + + db_args_size++; + db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1)); + if (db_args == NULL) { + error(_("%s: Cannot initialize. Not enough memory\n"), whoami); + exit(1); + } + db_args[db_args_size - 1] = db_name; + db_args[db_args_size] = NULL; + break; + case 's': + params.admin_server = optarg; + params.mask |= KADM5_CONFIG_ADMIN_SERVER; + break; + case 'm': + params.mkey_from_kbd = 1; + params.mask |= KADM5_CONFIG_MKEY_FROM_KBD; + break; + case 'e': + retval = krb5_string_to_keysalts(optarg, NULL, NULL, 0, + ¶ms.keysalts, + ¶ms.num_keysalts); + if (retval) { + com_err(whoami, retval, _("while parsing keysalts %s"), + optarg); + exit(1); + } + params.mask |= KADM5_CONFIG_ENCTYPES; + break; + case 'O': + params.mask |= KADM5_CONFIG_OLD_AUTH_GSSAPI; + break; + case 'N': + params.mask |= KADM5_CONFIG_AUTH_NOFALLBACK; + break; + default: + usage(); + } + } + if ((ccache_name && use_keytab) || + (keytab_name && !use_keytab) || + (ccache_name && use_anonymous) || + (use_anonymous && use_keytab)) + usage(); + + if (query != NULL && argv[optind] != NULL) { + error(_("%s: -q is exclusive with command-line query"), whoami); + usage(); + } + + if (argv[optind] != NULL) + script_mode = TRUE; + + if (def_realm == NULL && krb5_get_default_realm(context, &def_realm)) { + error(_("%s: unable to get default realm\n"), whoami); + exit(1); + } + + params.mask |= KADM5_CONFIG_REALM; + params.realm = def_realm; + + if (params.mask & KADM5_CONFIG_OLD_AUTH_GSSAPI) + svcname = KADM5_ADMIN_SERVICE; + else + svcname = NULL; + + /* + * Set cc to an open credentials cache, either specified by the -c + * argument or the default. + */ + if (ccache_name == NULL) { + retval = krb5_cc_default(context, &cc); + if (retval) { + com_err(whoami, retval, + _("while opening default credentials cache")); + exit(1); + } + } else { + retval = krb5_cc_resolve(context, ccache_name, &cc); + if (retval) { + com_err(whoami, retval, _("while opening credentials cache %s"), + ccache_name); + exit(1); + } + } + + /* + * If no principal name is specified: If authenticating anonymously, use + * the anonymous principal for the local realm, else if a ccache was + * specified and its primary principal name can be read, it is used, else + * if a keytab was specified, the principal name is host/hostname, + * otherwise append "/admin" to the primary name of the default ccache, + * $USER, or pw_name. + * + * Gee, 100+ lines to figure out the client principal name. This + * should be compressed... + */ + + if (princstr == NULL) { + if (use_anonymous) { + if (asprintf(&princstr, "%s/%s@%s", KRB5_WELLKNOWN_NAMESTR, + KRB5_ANONYMOUS_PRINCSTR, def_realm) < 0) { + error(_("%s: out of memory\n"), whoami); + exit(1); + } + freeprinc++; + } else if (ccache_name != NULL && + !krb5_cc_get_principal(context, cc, &princ)) { + retval = krb5_unparse_name(context, princ, &princstr); + if (retval) { + com_err(whoami, retval, + _("while canonicalizing principal name")); + exit(1); + } + krb5_free_principal(context, princ); + freeprinc++; + } else if (use_keytab != 0) { + retval = krb5_sname_to_principal(context, NULL, "host", + KRB5_NT_SRV_HST, &princ); + if (retval) { + com_err(whoami, retval, _("creating host service principal")); + exit(1); + } + retval = krb5_unparse_name(context, princ, &princstr); + if (retval) { + com_err(whoami, retval, + _("while canonicalizing principal name")); + exit(1); + } + krb5_free_principal(context, princ); + freeprinc++; + } else if (!krb5_cc_get_principal(context, cc, &princ)) { + if (krb5_unparse_name(context, princ, &canon)) { + error(_("%s: unable to canonicalize principal\n"), whoami); + exit(1); + } + /* Strip out realm of principal if it's there. */ + realm = strchr(canon, '@'); + while (realm) { + if (realm > canon && *(realm - 1) != '\\') + break; + realm = strchr(realm + 1, '@'); + } + if (realm) + *realm++ = '\0'; + cp = strchr(canon, '/'); + while (cp) { + if (cp > canon && *(cp - 1) != '\\') + break; + cp = strchr(cp + 1, '/'); + } + if (cp != NULL) + *cp = '\0'; + if (asprintf(&princstr, "%s/admin%s%s", canon, + (realm) ? "@" : "", + (realm) ? realm : "") < 0) { + error(_("%s: out of memory\n"), whoami); + exit(1); + } + free(canon); + krb5_free_principal(context, princ); + freeprinc++; + } else if ((luser = getenv("USER"))) { + if (asprintf(&princstr, "%s/admin@%s", luser, def_realm) < 0) { + error(_("%s: out of memory\n"), whoami); + exit(1); + } + freeprinc++; + } else if ((pw = getpwuid(getuid()))) { + if (asprintf(&princstr, "%s/admin@%s", pw->pw_name, + def_realm) < 0) { + error(_("%s: out of memory\n"), whoami); + exit(1); + } + freeprinc++; + } else { + error(_("%s: unable to figure out a principal name\n"), whoami); + exit(1); + } + } + + retval = krb5_klog_init(context, "admin_server", whoami, 0); + if (retval) { + com_err(whoami, retval, _("while setting up logging")); + exit(1); + } + + /* + * Initialize the kadm5 connection. If we were given a ccache, + * use it. Otherwise, use/prompt for the password. + */ + if (ccache_name) { + info(_("Authenticating as principal %s with existing " + "credentials.\n"), princstr); + retval = kadm5_init_with_creds(context, princstr, cc, svcname, ¶ms, + KADM5_STRUCT_VERSION, + KADM5_API_VERSION_4, db_args, &handle); + } else if (use_anonymous) { + info(_("Authenticating as principal %s with password; " + "anonymous requested.\n"), princstr); + retval = kadm5_init_anonymous(context, princstr, svcname, ¶ms, + KADM5_STRUCT_VERSION, + KADM5_API_VERSION_4, db_args, &handle); + } else if (use_keytab) { + if (keytab_name != NULL) { + info(_("Authenticating as principal %s with keytab %s.\n"), + princstr, keytab_name); + } else { + info(_("Authenticating as principal %s with default keytab.\n"), + princstr); + } + retval = kadm5_init_with_skey(context, princstr, keytab_name, svcname, + ¶ms, KADM5_STRUCT_VERSION, + KADM5_API_VERSION_4, db_args, &handle); + } else { + info(_("Authenticating as principal %s with password.\n"), + princstr); + retval = kadm5_init_with_password(context, princstr, password, svcname, + ¶ms, KADM5_STRUCT_VERSION, + KADM5_API_VERSION_4, db_args, + &handle); + } + if (retval) { + com_err(whoami, retval, _("while initializing %s interface"), whoami); + if (retval == KADM5_BAD_CLIENT_PARAMS || + retval == KADM5_BAD_SERVER_PARAMS) + usage(); + exit(1); + } + if (freeprinc) + free(princstr); + + free(params.keysalts); + free(db_name); + free(db_args); + + retval = krb5_cc_close(context, cc); + if (retval) { + com_err(whoami, retval, _("while closing ccache %s"), ccache_name); + exit(1); + } + + retval = kadm5_init_iprop(handle, 0); + if (retval) { + com_err(whoami, retval, _("while mapping update log")); + exit(1); + } + + *request_out = query; + *args_out = argv + optind; +} + +int +quit() +{ + kadm5_ret_t retval; + + if (locked) { + retval = kadm5_unlock(handle); + if (retval) { + com_err("quit", retval, _("while unlocking locked database")); + return 1; + } + locked = 0; + } + + kadm5_destroy(handle); + if (ccache_name != NULL && !script_mode) { + fprintf(stderr, "\n\a\a\a%s", + _("Administration credentials NOT DESTROYED.\n")); + } + + /* insert more random cleanup here */ + krb5_klog_close(context); + krb5_free_context(context); + return 0; +} + +void +kadmin_lock(int argc, char *argv[]) +{ + kadm5_ret_t retval; + + if (locked) + return; + retval = kadm5_lock(handle); + if (retval) { + com_err("lock", retval, ""); + return; + } + locked = 1; +} + +void +kadmin_unlock(int argc, char *argv[]) +{ + kadm5_ret_t retval; + + if (!locked) + return; + retval = kadm5_unlock(handle); + if (retval) { + com_err("unlock", retval, ""); + return; + } + locked = 0; +} + +void +kadmin_delprinc(int argc, char *argv[]) +{ + kadm5_ret_t retval; + krb5_principal princ = NULL; + char *canon = NULL; + char reply[5]; + + if (! (argc == 2 || + (argc == 3 && !strcmp("-force", argv[1])))) { + error(_("usage: delete_principal [-force] principal\n")); + return; + } + retval = kadmin_parse_name(argv[argc - 1], &princ); + if (retval) { + com_err("delete_principal", retval, _("while parsing principal name")); + return; + } + retval = krb5_unparse_name(context, princ, &canon); + if (retval) { + com_err("delete_principal", retval, + _("while canonicalizing principal")); + goto cleanup; + } + if (argc == 2 && !script_mode) { + printf(_("Are you sure you want to delete the principal \"%s\"? " + "(yes/no): "), canon); + fgets(reply, sizeof (reply), stdin); + if (strcmp("yes\n", reply)) { + fprintf(stderr, _("Principal \"%s\" not deleted\n"), canon); + goto cleanup; + } + } + retval = kadm5_delete_principal(handle, princ); + if (retval) { + com_err("delete_principal", retval, + _("while deleting principal \"%s\""), canon); + goto cleanup; + } + info(_("Principal \"%s\" deleted.\n"), canon); + info(_("Make sure that you have removed this principal from all ACLs " + "before reusing.\n")); + +cleanup: + krb5_free_principal(context, princ); + free(canon); +} + +void +kadmin_renameprinc(int argc, char *argv[]) +{ + kadm5_ret_t retval; + krb5_principal oprinc = NULL, nprinc = NULL; + char *ocanon = NULL, *ncanon = NULL; + char reply[5]; + + if (!(argc == 3 || (argc == 4 && !strcmp("-force", argv[1])))) { + error(_("usage: rename_principal [-force] old_principal " + "new_principal\n")); + return; + } + retval = kadmin_parse_name(argv[argc - 2], &oprinc); + if (retval) { + com_err("rename_principal", retval, + _("while parsing old principal name")); + goto cleanup; + } + retval = kadmin_parse_name(argv[argc - 1], &nprinc); + if (retval) { + com_err("rename_principal", retval, + _("while parsing new principal name")); + goto cleanup; + } + retval = krb5_unparse_name(context, oprinc, &ocanon); + if (retval) { + com_err("rename_principal", retval, + _("while canonicalizing old principal")); + goto cleanup; + } + retval = krb5_unparse_name(context, nprinc, &ncanon); + if (retval) { + com_err("rename_principal", retval, + _("while canonicalizing new principal")); + goto cleanup; + } + if (argc == 3 && !script_mode) { + printf(_("Are you sure you want to rename the principal \"%s\" " + "to \"%s\"? (yes/no): "), ocanon, ncanon); + fgets(reply, sizeof(reply), stdin); + if (strcmp("yes\n", reply)) { + fprintf(stderr, _("Principal \"%s\" not renamed\n"), ocanon); + goto cleanup; + } + } + retval = kadm5_rename_principal(handle, oprinc, nprinc); + if (retval) { + com_err("rename_principal", retval, + _("while renaming principal \"%s\" to \"%s\""), + ocanon, ncanon); + goto cleanup; + } + info(_("Principal \"%s\" renamed to \"%s\".\n"), ocanon, ncanon); + info(_("Make sure that you have removed the old principal from all ACLs " + "before reusing.\n")); + +cleanup: + krb5_free_principal(context, nprinc); + krb5_free_principal(context, oprinc); + free(ncanon); + free(ocanon); +} + +static void +cpw_usage(const char *str) +{ + if (str) + error("%s\n", str); + error(_("usage: change_password [-randkey] [-keepold] " + "[-e keysaltlist] [-pw password] principal\n")); +} + +void +kadmin_cpw(int argc, char *argv[]) +{ + kadm5_ret_t retval; + static char newpw[1024]; + static char prompt1[1024], prompt2[1024]; + char *canon = NULL, *pwarg = NULL; + int n_ks_tuple = 0, randkey = 0; + krb5_boolean keepold = FALSE; + krb5_key_salt_tuple *ks_tuple = NULL; + krb5_principal princ = NULL; + char **db_args = NULL; + int db_args_size = 0; + + if (argc < 1) { + cpw_usage(NULL); + return; + } + for (argv++, argc--; argc > 0 && **argv == '-'; argc--, argv++) { + if (!strcmp("-x", *argv)) { + argc--; + if (argc < 1) { + cpw_usage(_("change_password: missing db argument")); + goto cleanup; + } + db_args_size++; + db_args = realloc(db_args, sizeof(char*) * (db_args_size + 1)); + if (db_args == NULL) { + error(_("change_password: Not enough memory\n")); + exit(1); + } + db_args[db_args_size - 1] = *++argv; + db_args[db_args_size] = NULL; + } else if (!strcmp("-pw", *argv)) { + argc--; + if (argc < 1) { + cpw_usage(_("change_password: missing password arg")); + goto cleanup; + } + pwarg = *++argv; + } else if (!strcmp("-randkey", *argv)) { + randkey++; + } else if (!strcmp("-keepold", *argv)) { + keepold = TRUE; + } else if (!strcmp("-e", *argv)) { + argc--; + if (argc < 1) { + cpw_usage(_("change_password: missing keysaltlist arg")); + goto cleanup; + } + retval = krb5_string_to_keysalts(*++argv, NULL, NULL, 0, + &ks_tuple, &n_ks_tuple); + if (retval) { + com_err("change_password", retval, + _("while parsing keysalts %s"), *argv); + goto cleanup; + } + } else { + com_err("change_password", 0, _("unrecognized option %s"), *argv); + cpw_usage(NULL); + goto cleanup; + } + } + if (argc != 1) { + if (argc < 1) + com_err("change_password", 0, _("missing principal name")); + else + com_err("change_password", 0, _("too many arguments")); + cpw_usage(NULL); + goto cleanup; + } + retval = kadmin_parse_name(*argv, &princ); + if (retval) { + com_err("change_password", retval, _("while parsing principal name")); + goto cleanup; + } + retval = krb5_unparse_name(context, princ, &canon); + if (retval) { + com_err("change_password", retval, + _("while canonicalizing principal")); + goto cleanup; + } + if (pwarg != NULL) { + if (keepold || ks_tuple != NULL) { + retval = kadm5_chpass_principal_3(handle, princ, keepold, + n_ks_tuple, ks_tuple, pwarg); + } else { + retval = kadm5_chpass_principal(handle, princ, pwarg); + } + if (retval) { + com_err("change_password", retval, + _("while changing password for \"%s\"."), canon); + goto cleanup; + } + info(_("Password for \"%s\" changed.\n"), canon); + } else if (randkey) { + retval = randkey_princ(handle, princ, keepold, n_ks_tuple, ks_tuple, + NULL, NULL); + if (retval) { + com_err("change_password", retval, + _("while randomizing key for \"%s\"."), canon); + goto cleanup; + } + info(_("Key for \"%s\" randomized.\n"), canon); + } else { + unsigned int i = sizeof (newpw) - 1; + + snprintf(prompt1, sizeof(prompt1), + _("Enter password for principal \"%s\""), canon); + snprintf(prompt2, sizeof(prompt2), + _("Re-enter password for principal \"%s\""), canon); + retval = krb5_read_password(context, prompt1, prompt2, + newpw, &i); + if (retval) { + com_err("change_password", retval, + _("while reading password for \"%s\"."), canon); + goto cleanup; + } + if (keepold || ks_tuple != NULL) { + retval = kadm5_chpass_principal_3(handle, princ, keepold, + n_ks_tuple, ks_tuple, + newpw); + } else { + retval = kadm5_chpass_principal(handle, princ, newpw); + } + memset(newpw, 0, sizeof (newpw)); + if (retval) { + com_err("change_password", retval, + _("while changing password for \"%s\"."), canon); + goto cleanup; + } + info(_("Password for \"%s\" changed.\n"), canon); + } +cleanup: + free(canon); + free(db_args); + krb5_free_principal(context, princ); + free(ks_tuple); +} + +static void +kadmin_free_tl_data(krb5_int16 *n_tl_datap, krb5_tl_data **tl_datap) +{ + krb5_tl_data *tl_data = *tl_datap, *next; + int n_tl_data = *n_tl_datap; + int i; + + *n_tl_datap = 0; + *tl_datap = NULL; + + for (i = 0; tl_data && (i < n_tl_data); i++) { + next = tl_data->tl_data_next; + free(tl_data->tl_data_contents); + free(tl_data); + tl_data = next; + } +} + +/* Construct a tl_data element and add it to the tail of *tl_datap. */ +static void +add_tl_data(krb5_int16 *n_tl_datap, krb5_tl_data **tl_datap, + krb5_int16 tl_type, krb5_ui_2 len, krb5_octet *contents) +{ + krb5_tl_data *tl_data; + krb5_octet *copy; + + copy = malloc(len); + tl_data = calloc(1, sizeof(*tl_data)); + if (copy == NULL || tl_data == NULL) { + error(_("Not enough memory\n")); + exit(1); + } + memcpy(copy, contents, len); + + tl_data->tl_data_type = tl_type; + tl_data->tl_data_length = len; + tl_data->tl_data_contents = copy; + tl_data->tl_data_next = NULL; + + for (; *tl_datap != NULL; tl_datap = &(*tl_datap)->tl_data_next); + *tl_datap = tl_data; + (*n_tl_datap)++; +} + +static void +unlock_princ(kadm5_principal_ent_t princ, long *mask, const char *caller) +{ + krb5_error_code retval; + krb5_timestamp now; + krb5_octet timebuf[4]; + + /* Zero out the failed auth count. */ + princ->fail_auth_count = 0; + *mask |= KADM5_FAIL_AUTH_COUNT; + + /* Record the timestamp of this unlock operation so that replica KDCs will + * see it, since fail_auth_count is unreplicated. */ + retval = krb5_timeofday(context, &now); + if (retval) { + com_err(caller, retval, _("while getting time")); + exit(1); + } + store_32_le((krb5_int32)now, timebuf); + add_tl_data(&princ->n_tl_data, &princ->tl_data, + KRB5_TL_LAST_ADMIN_UNLOCK, 4, timebuf); + *mask |= KADM5_TL_DATA; +} + +/* + * Parse addprinc or modprinc arguments. Some output fields may be + * filled in on error. + */ +static int +kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc, + long *mask, char **pass, krb5_boolean *randkey, + krb5_boolean *nokey, krb5_key_salt_tuple **ks_tuple, + int *n_ks_tuple, char *caller) +{ + int i; + time_t now, date, interval; + krb5_error_code retval; + + *mask = 0; + *pass = NULL; + *n_ks_tuple = 0; + *ks_tuple = NULL; + time(&now); + *randkey = FALSE; + *nokey = FALSE; + for (i = 1; i < argc - 1; i++) { + if (!strcmp("-x",argv[i])) { + if (++i > argc - 2) + return -1; + + add_tl_data(&oprinc->n_tl_data, &oprinc->tl_data, + KRB5_TL_DB_ARGS, strlen(argv[i]) + 1, + (krb5_octet *)argv[i]); + *mask |= KADM5_TL_DATA; + continue; + } + if (!strcmp("-expire", argv[i])) { + if (++i > argc - 2) + return -1; + date = parse_date(argv[i], now); + if (date == (time_t)-1) + return -1; + oprinc->princ_expire_time = date; + *mask |= KADM5_PRINC_EXPIRE_TIME; + continue; + } + if (!strcmp("-pwexpire", argv[i])) { + if (++i > argc - 2) + return -1; + date = parse_date(argv[i], now); + if (date == (time_t)-1) + return -1; + oprinc->pw_expiration = date; + *mask |= KADM5_PW_EXPIRATION; + continue; + } + if (!strcmp("-maxlife", argv[i])) { + if (++i > argc - 2) + return -1; + interval = parse_interval(argv[i], now); + if (interval == (time_t)-1) + return -1; + oprinc->max_life = interval; + *mask |= KADM5_MAX_LIFE; + continue; + } + if (!strcmp("-maxrenewlife", argv[i])) { + if (++i > argc - 2) + return -1; + interval = parse_interval(argv[i], now); + if (interval == (time_t)-1) + return -1; + oprinc->max_renewable_life = interval; + *mask |= KADM5_MAX_RLIFE; + continue; + } + if (!strcmp("-kvno", argv[i])) { + if (++i > argc - 2) + return -1; + oprinc->kvno = atoi(argv[i]); + *mask |= KADM5_KVNO; + continue; + } + if (!strcmp("-policy", argv[i])) { + if (++i > argc - 2) + return -1; + oprinc->policy = argv[i]; + *mask |= KADM5_POLICY; + continue; + } + if (!strcmp("-clearpolicy", argv[i])) { + oprinc->policy = NULL; + *mask |= KADM5_POLICY_CLR; + continue; + } + if (!strcmp("-pw", argv[i])) { + if (++i > argc - 2) + return -1; + *pass = argv[i]; + continue; + } + if (!strcmp("-randkey", argv[i])) { + *randkey = TRUE; + continue; + } + if (!strcmp("-nokey", argv[i])) { + *nokey = TRUE; + continue; + } + if (!strcmp("-unlock", argv[i])) { + unlock_princ(oprinc, mask, caller); + continue; + } + if (!strcmp("-e", argv[i])) { + if (++i > argc - 2) + return -1; + retval = krb5_string_to_keysalts(argv[i], NULL, NULL, 0, + ks_tuple, n_ks_tuple); + if (retval) { + com_err(caller, retval, _("while parsing keysalts %s"), + argv[i]); + return -1; + } + continue; + } + retval = krb5_flagspec_to_mask(argv[i], &oprinc->attributes, + &oprinc->attributes); + if (retval) + return -1; + else + *mask |= KADM5_ATTRIBUTES; + } + if (i != argc - 1) + return -1; + retval = kadmin_parse_name(argv[i], &oprinc->principal); + if (retval) { + com_err(caller, retval, _("while parsing principal")); + return -1; + } + return 0; +} + +static void +kadmin_addprinc_usage() +{ + error(_("usage: add_principal [options] principal\n")); + error(_("\toptions are:\n")); + error(_("\t\t[-randkey|-nokey] [-x db_princ_args]* [-expire expdate] " + "[-pwexpire pwexpdate] [-maxlife maxtixlife]\n" + "\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n" + "\t\t[-pw password] [-maxrenewlife maxrenewlife]\n" + "\t\t[-e keysaltlist]\n\t\t[{+|-}attribute]\n")); + error(_("\tattributes are:\n")); + error(_("\t\tallow_postdated allow_forwardable allow_tgs_req " + "allow_renewable\n" + "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n" + "\t\trequires_hwauth needchange allow_svr " + "password_changing_service\n" + "\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n" + "\t\tlockdown_keys\n" + "\nwhere,\n\t[-x db_princ_args]* - any number of database " + "specific arguments.\n" + "\t\t\tLook at each database documentation for supported " + "arguments\n")); +} + +static void +kadmin_modprinc_usage() +{ + error(_("usage: modify_principal [options] principal\n")); + error(_("\toptions are:\n")); + error(_("\t\t[-x db_princ_args]* [-expire expdate] " + "[-pwexpire pwexpdate] [-maxlife maxtixlife]\n" + "\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n" + "\t\t[-maxrenewlife maxrenewlife] [-unlock] [{+|-}attribute]\n")); + error(_("\tattributes are:\n")); + error(_("\t\tallow_postdated allow_forwardable allow_tgs_req " + "allow_renewable\n" + "\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n" + "\t\trequires_hwauth needchange allow_svr " + "password_changing_service\n" + "\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n" + "\t\tlockdown_keys\n" + "\nwhere,\n\t[-x db_princ_args]* - any number of database " + "specific arguments.\n" + "\t\t\tLook at each database documentation for supported " + "arguments\n")); +} + +/* Create a dummy password for old-style (pre-1.8) randkey creation. */ +static void +prepare_dummy_password(char *buf, size_t sz) +{ + size_t i; + + /* Must try to pass any password policy in place, and be valid UTF-8. */ + strlcpy(buf, "6F a[", sz); + for (i = strlen(buf); i < sz - 1; i++) + buf[i] = 'a' + (i % 26); + buf[sz - 1] = '\0'; +} + +void +kadmin_addprinc(int argc, char *argv[]) +{ + kadm5_principal_ent_rec princ; + long mask; + krb5_boolean randkey = FALSE, nokey = FALSE, old_style_randkey = FALSE; + int n_ks_tuple; + krb5_key_salt_tuple *ks_tuple = NULL; + char *pass, *canon = NULL; + krb5_error_code retval; + char newpw[1024], dummybuf[256]; + static char prompt1[1024], prompt2[1024]; + + /* Zero all fields in request structure */ + memset(&princ, 0, sizeof(princ)); + + princ.attributes = 0; + if (kadmin_parse_princ_args(argc, argv, &princ, &mask, &pass, &randkey, + &nokey, &ks_tuple, &n_ks_tuple, + "add_principal")) { + kadmin_addprinc_usage(); + goto cleanup; + } + + retval = krb5_unparse_name(context, princ.principal, &canon); + if (retval) { + com_err("add_principal", retval, _("while canonicalizing principal")); + goto cleanup; + } + + if (mask & KADM5_POLICY) { + /* Warn if the specified policy does not exist. */ + if (!script_mode && !policy_exists(princ.policy)) { + fprintf(stderr, _("WARNING: policy \"%s\" does not exist\n"), + princ.policy); + } + } else if (!(mask & KADM5_POLICY_CLR)) { + /* If the policy "default" exists, assign it. */ + if (policy_exists("default")) { + if (!script_mode) { + fprintf(stderr, _("No policy specified for %s; " + "assigning \"default\"\n"), canon); + } + princ.policy = "default"; + mask |= KADM5_POLICY; + } else if (!script_mode) { + fprintf(stderr, _("No policy specified for %s; " + "defaulting to no policy\n"), canon); + } + } + /* Don't send KADM5_POLICY_CLR to the server. */ + mask &= ~KADM5_POLICY_CLR; + + if (nokey) { + pass = NULL; + mask |= KADM5_KEY_DATA; + } else if (randkey) { + pass = NULL; + } else if (pass == NULL) { + unsigned int sz = sizeof(newpw) - 1; + + snprintf(prompt1, sizeof(prompt1), + _("Enter password for principal \"%s\""), canon); + snprintf(prompt2, sizeof(prompt2), + _("Re-enter password for principal \"%s\""), canon); + retval = krb5_read_password(context, prompt1, prompt2, newpw, &sz); + if (retval) { + com_err("add_principal", retval, + _("while reading password for \"%s\"."), canon); + goto cleanup; + } + pass = newpw; + } + mask |= KADM5_PRINCIPAL; + retval = create_princ(&princ, mask, n_ks_tuple, ks_tuple, pass); + if (retval == EINVAL && randkey) { + /* + * The server doesn't support randkey creation. Create the principal + * with a dummy password and disallow tickets. + */ + prepare_dummy_password(dummybuf, sizeof(dummybuf)); + princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; + mask |= KADM5_ATTRIBUTES; + pass = dummybuf; + retval = create_princ(&princ, mask, n_ks_tuple, ks_tuple, pass); + old_style_randkey = 1; + } + if (retval == KADM5_BAD_MASK && nokey) { + error(_("Admin server does not support -nokey while creating " + "\"%s\"\n"), canon); + goto cleanup; + } + if (retval) { + com_err("add_principal", retval, "while creating \"%s\".", canon); + goto cleanup; + } + if (old_style_randkey) { + /* Randomize the password and re-enable tickets. */ + retval = randkey_princ(handle, princ.principal, FALSE, n_ks_tuple, + ks_tuple, NULL, NULL); + if (retval) { + com_err("add_principal", retval, + _("while randomizing key for \"%s\"."), canon); + goto cleanup; + } + princ.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX; /* clear notix */ + mask = KADM5_ATTRIBUTES; + retval = kadm5_modify_principal(handle, &princ, mask); + if (retval) { + com_err("add_principal", retval, + _("while clearing DISALLOW_ALL_TIX for \"%s\"."), canon); + goto cleanup; + } + } + info("Principal \"%s\" created.\n", canon); + +cleanup: + krb5_free_principal(context, princ.principal); + free(ks_tuple); + free(canon); + kadmin_free_tl_data(&princ.n_tl_data, &princ.tl_data); +} + +void +kadmin_modprinc(int argc, char *argv[]) +{ + kadm5_principal_ent_rec princ, oldprinc; + krb5_principal kprinc = NULL; + long mask; + krb5_error_code retval; + char *pass, *canon = NULL; + krb5_boolean randkey = FALSE, nokey = FALSE; + int n_ks_tuple = 0; + krb5_key_salt_tuple *ks_tuple = NULL; + + if (argc < 2) { + kadmin_modprinc_usage(); + return; + } + + memset(&oldprinc, 0, sizeof(oldprinc)); + memset(&princ, 0, sizeof(princ)); + + retval = kadmin_parse_name(argv[argc - 1], &kprinc); + if (retval) { + com_err("modify_principal", retval, _("while parsing principal")); + return; + } + retval = krb5_unparse_name(context, kprinc, &canon); + if (retval) { + com_err("modify_principal", retval, + _("while canonicalizing principal")); + goto cleanup; + } + retval = kadm5_get_principal(handle, kprinc, &oldprinc, + KADM5_PRINCIPAL_NORMAL_MASK); + if (retval) { + com_err("modify_principal", retval, _("while getting \"%s\"."), canon); + goto cleanup; + } + princ.attributes = oldprinc.attributes; + kadm5_free_principal_ent(handle, &oldprinc); + retval = kadmin_parse_princ_args(argc, argv, + &princ, &mask, + &pass, &randkey, &nokey, + &ks_tuple, &n_ks_tuple, + "modify_principal"); + if (retval || ks_tuple != NULL || randkey || nokey || pass) { + kadmin_modprinc_usage(); + goto cleanup; + } + if (mask & KADM5_POLICY) { + /* Warn if the specified policy does not exist. */ + if (!script_mode && !policy_exists(princ.policy)) { + fprintf(stderr, _("WARNING: policy \"%s\" does not exist\n"), + princ.policy); + } + } + if (mask) { + /* Skip this if all we're doing is setting certhash. */ + retval = kadm5_modify_principal(handle, &princ, mask); + } + if (retval) { + com_err("modify_principal", retval, _("while modifying \"%s\"."), + canon); + goto cleanup; + } + info(_("Principal \"%s\" modified.\n"), canon); +cleanup: + krb5_free_principal(context, kprinc); + krb5_free_principal(context, princ.principal); + kadmin_free_tl_data(&princ.n_tl_data, &princ.tl_data); + free(canon); + free(ks_tuple); +} + +void +kadmin_getprinc(int argc, char *argv[]) +{ + kadm5_principal_ent_rec dprinc; + krb5_principal princ = NULL; + krb5_error_code retval; + const char *polname, *noexist; + char *canon = NULL, *princstr = NULL, *modprincstr = NULL; + char **sp = NULL, **attrstrs = NULL; + int i; + + if (!(argc == 2 || (argc == 3 && !strcmp("-terse", argv[1])))) { + error(_("usage: get_principal [-terse] principal\n")); + return; + } + + memset(&dprinc, 0, sizeof(dprinc)); + + retval = kadmin_parse_name(argv[argc - 1], &princ); + if (retval) { + com_err("get_principal", retval, _("while parsing principal")); + return; + } + retval = krb5_unparse_name(context, princ, &canon); + if (retval) { + com_err("get_principal", retval, _("while canonicalizing principal")); + goto cleanup; + } + retval = kadm5_get_principal(handle, princ, &dprinc, + KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA); + if (retval) { + com_err("get_principal", retval, _("while retrieving \"%s\"."), canon); + goto cleanup; + } + retval = krb5_unparse_name(context, dprinc.principal, &princstr); + if (retval) { + com_err("get_principal", retval, _("while unparsing principal")); + goto cleanup; + } + retval = krb5_unparse_name(context, dprinc.mod_name, &modprincstr); + if (retval) { + com_err("get_principal", retval, _("while unparsing principal")); + goto cleanup; + } + if (argc == 2) { + printf(_("Principal: %s\n"), princstr); + printf(_("Expiration date: %s\n"), dprinc.princ_expire_time ? + strdate(dprinc.princ_expire_time) : _("[never]")); + printf(_("Last password change: %s\n"), dprinc.last_pwd_change ? + strdate(dprinc.last_pwd_change) : _("[never]")); + printf(_("Password expiration date: %s\n"), + dprinc.pw_expiration ? + strdate(dprinc.pw_expiration) : _("[never]")); + printf(_("Maximum ticket life: %s\n"), strdur(dprinc.max_life)); + printf(_("Maximum renewable life: %s\n"), + strdur(dprinc.max_renewable_life)); + printf(_("Last modified: %s (%s)\n"), strdate(dprinc.mod_date), + modprincstr); + printf(_("Last successful authentication: %s\n"), + dprinc.last_success ? strdate(dprinc.last_success) : + _("[never]")); + printf("Last failed authentication: %s\n", + dprinc.last_failed ? strdate(dprinc.last_failed) : + "[never]"); + printf(_("Failed password attempts: %d\n"), + dprinc.fail_auth_count); + printf(_("Number of keys: %d\n"), dprinc.n_key_data); + for (i = 0; i < dprinc.n_key_data; i++) { + krb5_key_data *key_data = &dprinc.key_data[i]; + char enctype[BUFSIZ], salttype[BUFSIZ]; + char *deprecated = ""; + + if (krb5_enctype_to_name(key_data->key_data_type[0], FALSE, + enctype, sizeof(enctype))) + snprintf(enctype, sizeof(enctype), _(""), + key_data->key_data_type[0]); + if (!krb5_c_valid_enctype(key_data->key_data_type[0])) + deprecated = "UNSUPPORTED:"; + else if (krb5int_c_deprecated_enctype(key_data->key_data_type[0])) + deprecated = "DEPRECATED:"; + printf("Key: vno %d, %s%s", key_data->key_data_kvno, deprecated, + enctype); + if (key_data->key_data_ver > 1 && + key_data->key_data_type[1] != KRB5_KDB_SALTTYPE_NORMAL) { + if (krb5_salttype_to_string(key_data->key_data_type[1], + salttype, sizeof(salttype))) + snprintf(salttype, sizeof(salttype), _(""), + key_data->key_data_type[1]); + printf(":%s", salttype); + } + printf("\n"); + } + printf(_("MKey: vno %d\n"), dprinc.mkvno); + + printf(_("Attributes:")); + retval = krb5_flags_to_strings(dprinc.attributes, &attrstrs); + if (retval) { + com_err("get_principal", retval, _("while printing flags")); + return; + } + for (sp = attrstrs; sp != NULL && *sp != NULL; sp++) { + printf(" %s", *sp); + free(*sp); + } + free(attrstrs); + printf("\n"); + polname = (dprinc.policy != NULL) ? dprinc.policy : _("[none]"); + noexist = (dprinc.policy != NULL && !policy_exists(dprinc.policy)) ? + _(" [does not exist]") : ""; + printf(_("Policy: %s%s\n"), polname, noexist); + } else { + printf("\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"" + "\t%d\t%d\t%d\t%d\t%d", + princstr, dprinc.princ_expire_time, dprinc.last_pwd_change, + dprinc.pw_expiration, dprinc.max_life, modprincstr, + dprinc.mod_date, dprinc.attributes, dprinc.kvno, + dprinc.mkvno, dprinc.policy ? dprinc.policy : "[none]", + dprinc.max_renewable_life, dprinc.last_success, + dprinc.last_failed, dprinc.fail_auth_count, + dprinc.n_key_data); + for (i = 0; i < dprinc.n_key_data; i++) + printf("\t%d\t%d\t%d\t%d", + dprinc.key_data[i].key_data_ver, + dprinc.key_data[i].key_data_kvno, + dprinc.key_data[i].key_data_type[0], + dprinc.key_data[i].key_data_type[1]); + printf("\n"); + } +cleanup: + krb5_free_principal(context, princ); + kadm5_free_principal_ent(handle, &dprinc); + free(canon); + free(princstr); + free(modprincstr); +} + +void +kadmin_getprincs(int argc, char *argv[]) +{ + krb5_error_code retval; + char *expr, **names; + int i, count; + + expr = NULL; + if (!(argc == 1 || (argc == 2 && (expr = argv[1])))) { + error(_("usage: get_principals [expression]\n")); + return; + } + retval = kadm5_get_principals(handle, expr, &names, &count); + if (retval) { + com_err("get_principals", retval, _("while retrieving list.")); + return; + } + for (i = 0; i < count; i++) + printf("%s\n", names[i]); + kadm5_free_name_list(handle, names, count); +} + +static int +kadmin_parse_policy_args(int argc, char *argv[], kadm5_policy_ent_t policy, + long *mask, char *caller) +{ + krb5_error_code retval; + int i; + time_t now, interval; + + time(&now); + *mask = 0; + for (i = 1; i < argc - 1; i++) { + if (!strcmp(argv[i], "-maxlife")) { + if (++i > argc -2) + return -1; + interval = parse_interval(argv[i], now); + if (interval == (time_t)-1) + return -1; + policy->pw_max_life = interval; + *mask |= KADM5_PW_MAX_LIFE; + continue; + } else if (!strcmp(argv[i], "-minlife")) { + if (++i > argc - 2) + return -1; + interval = parse_interval(argv[i], now); + if (interval == (time_t)-1) + return -1; + policy->pw_min_life = interval; + *mask |= KADM5_PW_MIN_LIFE; + continue; + } else if (!strcmp(argv[i], "-minlength")) { + if (++i > argc - 2) + return -1; + policy->pw_min_length = atoi(argv[i]); + *mask |= KADM5_PW_MIN_LENGTH; + continue; + } else if (!strcmp(argv[i], "-minclasses")) { + if (++i > argc - 2) + return -1; + policy->pw_min_classes = atoi(argv[i]); + *mask |= KADM5_PW_MIN_CLASSES; + continue; + } else if (!strcmp(argv[i], "-history")) { + if (++i > argc - 2) + return -1; + policy->pw_history_num = atoi(argv[i]); + *mask |= KADM5_PW_HISTORY_NUM; + continue; + } else if (strlen(argv[i]) == 11 && + !strcmp(argv[i], "-maxfailure")) { + if (++i > argc - 2) + return -1; + policy->pw_max_fail = atoi(argv[i]); + *mask |= KADM5_PW_MAX_FAILURE; + continue; + } else if (strlen(argv[i]) == 21 && + !strcmp(argv[i], "-failurecountinterval")) { + if (++i > argc - 2) + return -1; + interval = parse_interval(argv[i], now); + if (interval == (time_t)-1) + return -1; + policy->pw_failcnt_interval = interval; + *mask |= KADM5_PW_FAILURE_COUNT_INTERVAL; + continue; + } else if (strlen(argv[i]) == 16 && + !strcmp(argv[i], "-lockoutduration")) { + if (++i > argc - 2) + return -1; + interval = parse_interval(argv[i], now); + if (interval == (time_t)-1) + return -1; + policy->pw_lockout_duration = interval; + *mask |= KADM5_PW_LOCKOUT_DURATION; + continue; + } else if (!strcmp(argv[i], "-allowedkeysalts")) { + krb5_key_salt_tuple *ks_tuple = NULL; + int n_ks_tuple = 0; + + if (++i > argc - 2) + return -1; + if (strcmp(argv[i], "-")) { + retval = krb5_string_to_keysalts(argv[i], ",", NULL, 0, + &ks_tuple, &n_ks_tuple); + if (retval) { + com_err(caller, retval, _("while parsing keysalts %s"), + argv[i]); + return -1; + } + free(ks_tuple); + policy->allowed_keysalts = argv[i]; + } + *mask |= KADM5_POLICY_ALLOWED_KEYSALTS; + continue; + } else + return -1; + } + if (i != argc -1) { + error(_("%s: parser lost count!\n"), caller); + return -1; + } else + return 0; +} + +static void +kadmin_addmodpol_usage(char *func) +{ + error(_("usage; %s [options] policy\n"), func); + error(_("\toptions are:\n")); + error(_("\t\t[-maxlife time] [-minlife time] [-minlength length]\n" + "\t\t[-minclasses number] [-history number]\n" + "\t\t[-maxfailure number] [-failurecountinterval time]\n" + "\t\t[-allowedkeysalts keysalts]\n")); + error(_("\t\t[-lockoutduration time]\n")); +} + +void +kadmin_addpol(int argc, char *argv[]) +{ + krb5_error_code retval; + long mask; + kadm5_policy_ent_rec policy; + + memset(&policy, 0, sizeof(policy)); + if (kadmin_parse_policy_args(argc, argv, &policy, &mask, "add_policy")) { + kadmin_addmodpol_usage("add_policy"); + return; + } + policy.policy = argv[argc - 1]; + mask |= KADM5_POLICY; + retval = kadm5_create_policy(handle, &policy, mask); + if (retval) { + com_err("add_policy", retval, _("while creating policy \"%s\"."), + policy.policy); + } +} + +void +kadmin_modpol(int argc, char *argv[]) +{ + krb5_error_code retval; + long mask; + kadm5_policy_ent_rec policy; + + memset(&policy, 0, sizeof(policy)); + if (kadmin_parse_policy_args(argc, argv, &policy, &mask, + "modify_policy")) { + kadmin_addmodpol_usage("modify_policy"); + return; + } + policy.policy = argv[argc - 1]; + retval = kadm5_modify_policy(handle, &policy, mask); + if (retval) { + com_err("modify_policy", retval, _("while modifying policy \"%s\"."), + policy.policy); + } +} + +void +kadmin_delpol(int argc, char *argv[]) +{ + krb5_error_code retval; + char reply[5]; + + if (!(argc == 2 || (argc == 3 && !strcmp("-force", argv[1])))) { + error(_("usage: delete_policy [-force] policy\n")); + return; + } + if (argc == 2 && !script_mode) { + printf(_("Are you sure you want to delete the policy \"%s\"? " + "(yes/no): "), argv[1]); + fgets(reply, sizeof(reply), stdin); + if (strcmp("yes\n", reply)) { + fprintf(stderr, _("Policy \"%s\" not deleted.\n"), argv[1]); + return; + } + } + retval = kadm5_delete_policy(handle, argv[argc - 1]); + if (retval) { + com_err("delete_policy:", retval, _("while deleting policy \"%s\""), + argv[argc - 1]); + } +} + +void +kadmin_getpol(int argc, char *argv[]) +{ + krb5_error_code retval; + kadm5_policy_ent_rec policy; + + if (!(argc == 2 || (argc == 3 && !strcmp("-terse", argv[1])))) { + error(_("usage: get_policy [-terse] policy\n")); + return; + } + retval = kadm5_get_policy(handle, argv[argc - 1], &policy); + if (retval) { + com_err("get_policy", retval, _("while retrieving policy \"%s\"."), + argv[argc - 1]); + return; + } + if (argc == 2) { + printf(_("Policy: %s\n"), policy.policy); + printf(_("Maximum password life: %s\n"), strdur(policy.pw_max_life)); + printf(_("Minimum password life: %s\n"), strdur(policy.pw_min_life)); + printf(_("Minimum password length: %ld\n"), policy.pw_min_length); + printf(_("Minimum number of password character classes: %ld\n"), + policy.pw_min_classes); + printf(_("Number of old keys kept: %ld\n"), policy.pw_history_num); + printf(_("Maximum password failures before lockout: %lu\n"), + (unsigned long)policy.pw_max_fail); + printf(_("Password failure count reset interval: %s\n"), + strdur(policy.pw_failcnt_interval)); + printf(_("Password lockout duration: %s\n"), + strdur(policy.pw_lockout_duration)); + if (policy.allowed_keysalts != NULL) + printf(_("Allowed key/salt types: %s\n"), policy.allowed_keysalts); + } else { + /* Output 0 where we used to output policy_refcnt. */ + printf("\"%s\"\t%ld\t%ld\t%ld\t%ld\t%ld\t0\t%lu\t%ld\t%ld\t%s\n", + policy.policy, policy.pw_max_life, policy.pw_min_life, + policy.pw_min_length, policy.pw_min_classes, + policy.pw_history_num, (unsigned long)policy.pw_max_fail, + (long)policy.pw_failcnt_interval, + (long)policy.pw_lockout_duration, + (policy.allowed_keysalts == NULL) ? "-" : + policy.allowed_keysalts); + } + kadm5_free_policy_ent(handle, &policy); +} + +void +kadmin_getpols(int argc, char *argv[]) +{ + krb5_error_code retval; + char *expr, **names; + int i, count; + + expr = NULL; + if (!(argc == 1 || (argc == 2 && (expr = argv[1])))) { + error(_("usage: get_policies [expression]\n")); + return; + } + retval = kadm5_get_policies(handle, expr, &names, &count); + if (retval) { + com_err("get_policies", retval, _("while retrieving list.")); + return; + } + for (i = 0; i < count; i++) + printf("%s\n", names[i]); + kadm5_free_name_list(handle, names, count); +} + +void +kadmin_getprivs(int argc, char *argv[]) +{ + static char *privs[] = {"INQUIRE", "ADD", "MODIFY", "DELETE"}; + krb5_error_code retval; + size_t i; + long plist; + + if (argc != 1) { + error(_("usage: get_privs\n")); + return; + } + retval = kadm5_get_privs(handle, &plist); + if (retval) { + com_err("get_privs", retval, _("while retrieving privileges")); + return; + } + printf(_("current privileges:")); + for (i = 0; i < sizeof (privs) / sizeof (char *); i++) { + if (plist & 1 << i) + printf(" %s", privs[i]); + } + printf("\n"); +} + +void +kadmin_purgekeys(int argc, char *argv[]) +{ + kadm5_ret_t retval; + int keepkvno = -1; + char *pname = NULL, *canon = NULL; + krb5_principal princ; + + if (argc == 4 && strcmp(argv[1], "-keepkvno") == 0) { + keepkvno = atoi(argv[2]); + pname = argv[3]; + } else if (argc == 3 && strcmp(argv[1], "-all") == 0) { + keepkvno = KRB5_INT32_MAX; + pname = argv[2]; + } else if (argc == 2) { + pname = argv[1]; + } + if (pname == NULL) { + error(_("usage: purgekeys [-all|-keepkvno oldest_kvno_to_keep] " + "principal\n")); + return; + } + + retval = kadmin_parse_name(pname, &princ); + if (retval) { + com_err("purgekeys", retval, _("while parsing principal")); + return; + } + + retval = krb5_unparse_name(context, princ, &canon); + if (retval) { + com_err("purgekeys", retval, _("while canonicalizing principal")); + goto cleanup; + } + + retval = kadm5_purgekeys(handle, princ, keepkvno); + if (retval) { + com_err("purgekeys", retval, + _("while purging keys for principal \"%s\""), canon); + goto cleanup; + } + + if (keepkvno == KRB5_INT32_MAX) + info(_("All keys for principal \"%s\" removed.\n"), canon); + else + info(_("Old keys for principal \"%s\" purged.\n"), canon); +cleanup: + krb5_free_principal(context, princ); + free(canon); + return; +} + +void +kadmin_getstrings(int argc, char *argv[]) +{ + kadm5_ret_t retval; + char *pname, *canon = NULL; + krb5_principal princ = NULL; + krb5_string_attr *strings = NULL; + int count, i; + + if (argc != 2) { + error(_("usage: get_strings principal\n")); + return; + } + pname = argv[1]; + + retval = kadmin_parse_name(pname, &princ); + if (retval) { + com_err("get_strings", retval, _("while parsing principal")); + return; + } + + retval = krb5_unparse_name(context, princ, &canon); + if (retval) { + com_err("get_strings", retval, _("while canonicalizing principal")); + goto cleanup; + } + + retval = kadm5_get_strings(handle, princ, &strings, &count); + if (retval) { + com_err("get_strings", retval, + _("while getting attributes for principal \"%s\""), canon); + goto cleanup; + } + + if (count == 0) + printf(_("(No string attributes.)\n")); + for (i = 0; i < count; i++) + printf("%s: %s\n", strings[i].key, strings[i].value); + kadm5_free_strings(handle, strings, count); + +cleanup: + krb5_free_principal(context, princ); + free(canon); + return; +} + +void +kadmin_setstring(int argc, char *argv[]) +{ + kadm5_ret_t retval; + char *pname, *canon = NULL, *key, *value; + krb5_principal princ = NULL; + + if (argc != 4) { + error(_("usage: set_string principal key value\n")); + return; + } + pname = argv[1]; + key = argv[2]; + value = argv[3]; + + retval = kadmin_parse_name(pname, &princ); + if (retval) { + com_err("set_string", retval, _("while parsing principal")); + return; + } + + retval = krb5_unparse_name(context, princ, &canon); + if (retval) { + com_err("set_string", retval, _("while canonicalizing principal")); + goto cleanup; + } + + retval = kadm5_set_string(handle, princ, key, value); + if (retval) { + com_err("set_string", retval, + _("while setting attribute on principal \"%s\""), canon); + goto cleanup; + } + + info(_("Attribute set for principal \"%s\".\n"), canon); +cleanup: + krb5_free_principal(context, princ); + free(canon); + return; +} + +void +kadmin_delstring(int argc, char *argv[]) +{ + kadm5_ret_t retval; + char *pname, *canon = NULL, *key; + krb5_principal princ = NULL; + + if (argc != 3) { + error(_("usage: del_string principal key\n")); + return; + } + pname = argv[1]; + key = argv[2]; + + retval = kadmin_parse_name(pname, &princ); + if (retval) { + com_err("delstring", retval, _("while parsing principal")); + return; + } + + retval = krb5_unparse_name(context, princ, &canon); + if (retval) { + com_err("del_string", retval, _("while canonicalizing principal")); + goto cleanup; + } + + retval = kadm5_set_string(handle, princ, key, NULL); + if (retval) { + com_err("del_string", retval, + _("while deleting attribute from principal \"%s\""), canon); + goto cleanup; + } + + info(_("Attribute removed from principal \"%s\".\n"), canon); +cleanup: + krb5_free_principal(context, princ); + free(canon); + return; +} diff --git a/krb5-1.21.3/src/kadmin/cli/kadmin.h b/krb5-1.21.3/src/kadmin/cli/kadmin.h new file mode 100644 index 00000000..4ab1e9d5 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/cli/kadmin.h @@ -0,0 +1,82 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/cli/kadmin.h */ +/* + * Copyright 2001 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * Prototypes for kadmin functions called from SS library. + */ + +#ifndef __KADMIN_H__ +#define __KADMIN_H__ + +/* It would be nice if ss produced a header file we could reference */ +extern void kadmin_startup(int argc, char *argv[], char **request_out, + char ***args_out); +extern int quit (void); +extern void kadmin_lock(int argc, char *argv[]); +extern void kadmin_unlock(int argc, char *argv[]); +extern void kadmin_delprinc(int argc, char *argv[]); +extern void kadmin_renameprinc(int argc, char *argv[]); +extern void kadmin_cpw(int argc, char *argv[]); +extern void kadmin_addprinc(int argc, char *argv[]); +extern void kadmin_modprinc(int argc, char *argv[]); +extern void kadmin_getprinc(int argc, char *argv[]); +extern void kadmin_getprincs(int argc, char *argv[]); +extern void kadmin_addpol(int argc, char *argv[]); +extern void kadmin_modpol(int argc, char *argv[]); +extern void kadmin_delpol(int argc, char *argv[]); +extern void kadmin_getpol(int argc, char *argv[]); +extern void kadmin_getpols(int argc, char *argv[]); +extern void kadmin_getprivs(int argc, char *argv[]); +extern void kadmin_keytab_add(int argc, char *argv[]); +extern void kadmin_keytab_remove(int argc, char *argv[]); +extern void kadmin_purgekeys(int argc, char *argv[]); +extern void kadmin_getstrings(int argc, char *argv[]); +extern void kadmin_setstring(int argc, char *argv[]); +extern void kadmin_delstring(int argc, char *argv[]); + +#include + +krb5_error_code +randkey_princ(void *lhandle, krb5_principal princ, krb5_boolean keepold, + int n_ks, krb5_key_salt_tuple *ks, krb5_keyblock **key, + int *n_keys); + +#include "autoconf.h" + +#ifdef HAVE_SYS_TIME_H +#include +#endif +#include + +extern time_t get_date_rel(char *, time_t); + +/* Yucky global variables */ +extern krb5_context context; +extern char *whoami; +extern void *handle; + +#endif /* __KADMIN_H__ */ diff --git a/krb5-1.21.3/src/kadmin/cli/kadmin_ct.ct b/krb5-1.21.3/src/kadmin/cli/kadmin_ct.ct new file mode 100644 index 00000000..705e4184 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/cli/kadmin_ct.ct @@ -0,0 +1,100 @@ +# Copyright 1994 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. +# +# +# Command table for kadmin CLI for OVSecure +# + +command_table kadmin_cmds; + +request kadmin_addprinc, "Add principal", + add_principal, addprinc, ank; + +request kadmin_delprinc, "Delete principal", + delete_principal, delprinc; + +request kadmin_modprinc, "Modify principal", + modify_principal, modprinc; + +request kadmin_renameprinc, "Rename principal", + rename_principal, renprinc; + +request kadmin_cpw, "Change password", + change_password, cpw; + +request kadmin_getprinc, "Get principal", + get_principal, getprinc; + +request kadmin_getprincs, "List principals", + list_principals, listprincs, get_principals, getprincs; + +request kadmin_addpol, "Add policy", + add_policy, addpol; + +request kadmin_modpol, "Modify policy", + modify_policy, modpol; + +request kadmin_delpol, "Delete policy", + delete_policy, delpol; + +request kadmin_getpol, "Get policy", + get_policy, getpol; + +request kadmin_getpols, "List policies", + list_policies, listpols, get_policies, getpols; + +request kadmin_getprivs, "Get privileges", + get_privs, getprivs; + +request kadmin_keytab_add, "Add entry(s) to a keytab", + ktadd, xst; + +request kadmin_keytab_remove, "Remove entry(s) from a keytab", + ktremove, ktrem; + +request kadmin_lock, "Lock database exclusively (use with extreme caution!)", + lock; + +request kadmin_unlock, "Release exclusive database lock", + unlock; + +request kadmin_purgekeys, "Purge previously retained old keys from a principal", + purgekeys; + +request kadmin_getstrings, "Show string attributes on a principal", + get_strings, getstrs; + +request kadmin_setstring, "Set a string attribute on a principal", + set_string, setstr; + +request kadmin_delstring, "Delete a string attribute on a principal", + del_string, delstr; + +# list_requests is generic -- unrelated to Kerberos +request ss_list_requests, "List available requests.", + list_requests, lr, "?"; + +request ss_quit, "Exit program.", + quit, exit, q; + +end; + diff --git a/krb5-1.21.3/src/kadmin/cli/keytab.c b/krb5-1.21.3/src/kadmin/cli/keytab.c new file mode 100644 index 00000000..b0c8378b --- /dev/null +++ b/krb5-1.21.3/src/kadmin/cli/keytab.c @@ -0,0 +1,505 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + * + * $Id$ + * $Source$ + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" +#include +#include +#include "kadmin.h" + +static void add_principal(void *lhandle, char *keytab_str, krb5_keytab keytab, + krb5_boolean keepold, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, + char *princ_str); +static void remove_principal(char *keytab_str, krb5_keytab keytab, + char *princ_str, char *kvno_str); +static char *etype_string(krb5_enctype enctype); + +static int quiet; + +static int norandkey; + +static void +add_usage() +{ + fprintf(stderr, _("Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] " + "[-norandkey] [principal | -glob princ-exp] [...]\n")); +} + +static void +rem_usage() +{ + fprintf(stderr, _("Usage: ktremove [-k[eytab] keytab] [-q] principal " + "[kvno|\"all\"|\"old\"]\n")); +} + +static int +process_keytab(krb5_context my_context, char **keytab_str, + krb5_keytab *keytab) +{ + int code; + char *name = *keytab_str; + + if (name == NULL) { + name = malloc(BUFSIZ); + if (!name) { + com_err(whoami, ENOMEM, _("while creating keytab name")); + return 1; + } + code = krb5_kt_default(my_context, keytab); + if (code != 0) { + com_err(whoami, code, _("while opening default keytab")); + free(name); + return 1; + } + code = krb5_kt_get_name(my_context, *keytab, name, BUFSIZ); + if (code != 0) { + com_err(whoami, code, _("while getting keytab name")); + free(name); + return 1; + } + } else { + if (strchr(name, ':') != NULL) + name = strdup(name); + else if (asprintf(&name, "WRFILE:%s", name) < 0) + name = NULL; + if (name == NULL) { + com_err(whoami, ENOMEM, _("while creating keytab name")); + return 1; + } + + code = krb5_kt_resolve(my_context, name, keytab); + if (code != 0) { + com_err(whoami, code, _("while resolving keytab %s"), name); + free(name); + return 1; + } + } + + *keytab_str = name; + return 0; +} + +void +kadmin_keytab_add(int argc, char **argv) +{ + krb5_keytab keytab = 0; + char *keytab_str = NULL, **princs; + int code, num, i; + krb5_error_code retval; + int n_ks_tuple = 0; + krb5_boolean keepold = FALSE; + krb5_key_salt_tuple *ks_tuple = NULL; + + argc--; argv++; + quiet = 0; + norandkey = 0; + while (argc) { + if (strncmp(*argv, "-k", 2) == 0) { + argc--; argv++; + if (!argc || keytab_str) { + add_usage(); + return; + } + keytab_str = *argv; + } else if (strcmp(*argv, "-q") == 0) { + quiet++; + } else if (strcmp(*argv, "-norandkey") == 0) { + norandkey++; + } else if (strcmp(*argv, "-e") == 0) { + argc--; + if (argc < 1) { + add_usage(); + return; + } + retval = krb5_string_to_keysalts(*++argv, NULL, NULL, 0, + &ks_tuple, &n_ks_tuple); + if (retval) { + com_err("ktadd", retval, _("while parsing keysalts %s"), + *argv); + + return; + } + } else + break; + argc--; argv++; + } + + if (argc == 0) { + add_usage(); + return; + } + + if (norandkey && ks_tuple) { + fprintf(stderr, + _("cannot specify keysaltlist when not changing key\n")); + return; + } + + if (process_keytab(context, &keytab_str, &keytab)) + return; + + while (*argv) { + if (strcmp(*argv, "-glob") == 0) { + if (*++argv == NULL) { + add_usage(); + break; + } + + code = kadm5_get_principals(handle, *argv, &princs, &num); + if (code) { + com_err(whoami, code, _("while expanding expression \"%s\"."), + *argv); + argv++; + continue; + } + + for (i = 0; i < num; i++) + add_principal(handle, keytab_str, keytab, keepold, + n_ks_tuple, ks_tuple, princs[i]); + kadm5_free_name_list(handle, princs, num); + } else { + add_principal(handle, keytab_str, keytab, keepold, + n_ks_tuple, ks_tuple, *argv); + argv++; + } + } + + code = krb5_kt_close(context, keytab); + if (code != 0) + com_err(whoami, code, _("while closing keytab")); + + free(keytab_str); +} + +void +kadmin_keytab_remove(int argc, char **argv) +{ + krb5_keytab keytab = 0; + char *keytab_str = NULL; + int code; + + argc--; argv++; + quiet = 0; + while (argc) { + if (strncmp(*argv, "-k", 2) == 0) { + argc--; argv++; + if (!argc || keytab_str) { + rem_usage(); + return; + } + keytab_str = *argv; + } else if (strcmp(*argv, "-q") == 0) { + quiet++; + } else + break; + argc--; argv++; + } + + if (argc != 1 && argc != 2) { + rem_usage(); + return; + } + if (process_keytab(context, &keytab_str, &keytab)) + return; + + remove_principal(keytab_str, keytab, argv[0], argv[1]); + + code = krb5_kt_close(context, keytab); + if (code != 0) + com_err(whoami, code, _("while closing keytab")); + + free(keytab_str); +} + +/* Generate new random keys for princ, and convert them into a kadm5_key_data + * array (with no salt information). */ +static krb5_error_code +fetch_new_keys(void *lhandle, krb5_principal princ, krb5_boolean keepold, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, + kadm5_key_data **key_data_out, int *nkeys_out) +{ + krb5_error_code code; + kadm5_key_data *key_data; + kadm5_principal_ent_rec princ_rec; + krb5_keyblock *keys = NULL; + int i, nkeys = 0; + + *key_data_out = NULL; + *nkeys_out = 0; + memset(&princ_rec, 0, sizeof(princ_rec)); + + /* Generate new random keys. */ + code = randkey_princ(lhandle, princ, keepold, n_ks_tuple, ks_tuple, + &keys, &nkeys); + if (code) + goto cleanup; + + /* Get the principal entry to find the kvno of the new keys. (This is not + * atomic, but randkey doesn't report the new kvno.) */ + code = kadm5_get_principal(lhandle, princ, &princ_rec, + KADM5_PRINCIPAL_NORMAL_MASK); + if (code) + goto cleanup; + + key_data = k5calloc(nkeys, sizeof(*key_data), &code); + if (key_data == NULL) + goto cleanup; + + /* Transfer the keyblocks and free the container array. */ + for (i = 0; i < nkeys; i++) { + key_data[i].key = keys[i]; + key_data[i].kvno = princ_rec.kvno; + } + *key_data_out = key_data; + *nkeys_out = nkeys; + free(keys); + keys = NULL; + nkeys = 0; + +cleanup: + for (i = 0; i < nkeys; i++) + krb5_free_keyblock_contents(context, &keys[i]); + free(keys); + kadm5_free_principal_ent(lhandle, &princ_rec); + return code; +} + +static void +add_principal(void *lhandle, char *keytab_str, krb5_keytab keytab, + krb5_boolean keepold, int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, char *princ_str) +{ + krb5_principal princ = NULL; + krb5_keytab_entry new_entry; + kadm5_key_data *key_data; + int code, nkeys, i; + + princ = NULL; + key_data = NULL; + nkeys = 0; + + code = krb5_parse_name(context, princ_str, &princ); + if (code != 0) { + com_err(whoami, code, _("while parsing -add principal name %s"), + princ_str); + goto cleanup; + } + + if (norandkey) { + code = kadm5_get_principal_keys(handle, princ, 0, &key_data, &nkeys); + } else { + code = fetch_new_keys(handle, princ, keepold, n_ks_tuple, ks_tuple, + &key_data, &nkeys); + } + + if (code != 0) { + if (code == KADM5_UNK_PRINC) { + fprintf(stderr, _("%s: Principal %s does not exist.\n"), + whoami, princ_str); + } else + com_err(whoami, code, _("while changing %s's key"), princ_str); + goto cleanup; + } + + for (i = 0; i < nkeys; i++) { + memset(&new_entry, 0, sizeof(new_entry)); + new_entry.principal = princ; + new_entry.key = key_data[i].key; + new_entry.vno = key_data[i].kvno; + + code = krb5_kt_add_entry(context, keytab, &new_entry); + if (code != 0) { + com_err(whoami, code, _("while adding key to keytab")); + goto cleanup; + } + + if (!quiet) { + printf(_("Entry for principal %s with kvno %d, " + "encryption type %s added to keytab %s.\n"), + princ_str, key_data[i].kvno, + etype_string(key_data[i].key.enctype), keytab_str); + } + } + +cleanup: + kadm5_free_kadm5_key_data(context, nkeys, key_data); + krb5_free_principal(context, princ); +} + +static void +remove_principal(char *keytab_str, krb5_keytab keytab, + char *princ_str, char *kvno_str) +{ + krb5_principal princ = NULL; + krb5_keytab_entry entry; + krb5_kt_cursor cursor; + enum { UNDEF, SPEC, HIGH, ALL, OLD } mode; + int code, did_something; + krb5_kvno kvno; + + code = krb5_parse_name(context, princ_str, &princ); + if (code != 0) { + com_err(whoami, code, _("while parsing principal name %s"), princ_str); + goto cleanup; + } + + mode = UNDEF; + if (kvno_str == NULL) { + mode = HIGH; + kvno = 0; + } else if (strcmp(kvno_str, "all") == 0) { + mode = ALL; + kvno = 0; + } else if (strcmp(kvno_str, "old") == 0) { + mode = OLD; + kvno = 0; + } else { + mode = SPEC; + kvno = atoi(kvno_str); + } + + /* kvno is set to specified value for SPEC, 0 otherwise */ + code = krb5_kt_get_entry(context, keytab, princ, kvno, 0, &entry); + if (code != 0) { + if (code == ENOENT) { + fprintf(stderr, _("%s: Keytab %s does not exist.\n"), + whoami, keytab_str); + } else if (code == KRB5_KT_NOTFOUND) { + if (mode != SPEC) { + fprintf(stderr, _("%s: No entry for principal %s exists in " + "keytab %s\n"), + whoami, princ_str, keytab_str); + } else { + fprintf(stderr, _("%s: No entry for principal %s with kvno %d " + "exists in keytab %s\n"), + whoami, princ_str, kvno, keytab_str); + } + } else { + com_err(whoami, code, + _("while retrieving highest kvno from keytab")); + } + goto cleanup; + } + + /* set kvno to spec'ed value for SPEC, highest kvno otherwise */ + if (mode != SPEC) + kvno = entry.vno; + krb5_kt_free_entry(context, &entry); + + code = krb5_kt_start_seq_get(context, keytab, &cursor); + if (code != 0) { + com_err(whoami, code, _("while starting keytab scan")); + goto cleanup; + } + + did_something = 0; + while ((code = krb5_kt_next_entry(context, keytab, &entry, + &cursor)) == 0) { + if (krb5_principal_compare(context, princ, entry.principal) && + ((mode == ALL) || + (mode == SPEC && entry.vno == kvno) || + (mode == OLD && entry.vno != kvno) || + (mode == HIGH && entry.vno == kvno))) { + + /* + * Ack! What a kludge... the scanning functions lock + * the keytab so entries cannot be removed while they + * are operating. + */ + code = krb5_kt_end_seq_get(context, keytab, &cursor); + if (code != 0) { + com_err(whoami, code, + _("while temporarily ending keytab scan")); + goto cleanup; + } + code = krb5_kt_remove_entry(context, keytab, &entry); + if (code != 0) { + com_err(whoami, code, _("while deleting entry from keytab")); + goto cleanup; + } + code = krb5_kt_start_seq_get(context, keytab, &cursor); + if (code != 0) { + com_err(whoami, code, _("while restarting keytab scan")); + goto cleanup; + } + + did_something++; + if (!quiet) { + printf(_("Entry for principal %s with kvno %d removed from " + "keytab %s.\n"), princ_str, entry.vno, keytab_str); + } + } + krb5_kt_free_entry(context, &entry); + } + if (code && code != KRB5_KT_END) { + com_err(whoami, code, _("while scanning keytab")); + goto cleanup; + } + code = krb5_kt_end_seq_get(context, keytab, &cursor); + if (code) { + com_err(whoami, code, _("while ending keytab scan")); + goto cleanup; + } + + /* + * If !did_someting then mode must be OLD or we would have + * already returned with an error. But check it anyway just to + * prevent unexpected error messages... + */ + if (!did_something && mode == OLD) { + fprintf(stderr, _("%s: There is only one entry for principal %s in " + "keytab %s\n"), whoami, princ_str, keytab_str); + } + +cleanup: + krb5_free_principal(context, princ); +} + +/* + * etype_string(enctype): return a string representation of the + * encryption type. XXX copied from klist.c; this should be a + * library function, or perhaps just #defines + */ +static char * +etype_string(krb5_enctype enctype) +{ + static char buf[100]; + krb5_error_code ret; + + ret = krb5_enctype_to_name(enctype, FALSE, buf, sizeof(buf)); + if (ret) + snprintf(buf, sizeof(buf), "etype %d", enctype); + + return buf; +} diff --git a/krb5-1.21.3/src/kadmin/cli/keytab_local.c b/krb5-1.21.3/src/kadmin/cli/keytab_local.c new file mode 100644 index 00000000..bb9cd88d --- /dev/null +++ b/krb5-1.21.3/src/kadmin/cli/keytab_local.c @@ -0,0 +1,10 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * A wrapper around keytab.c used by kadmin.local to expose the -norandkey + * flag. This avoids building two object files from the same source file, + * which is otherwise tricky with compilers that don't support -c and -o + * at the same time. + */ + +#define KADMIN_LOCAL +#include "keytab.c" diff --git a/krb5-1.21.3/src/kadmin/cli/ss_wrapper.c b/krb5-1.21.3/src/kadmin/cli/ss_wrapper.c new file mode 100644 index 00000000..7ae9f1a2 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/cli/ss_wrapper.c @@ -0,0 +1,77 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1994 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include +#include +#include "kadmin.h" + +#ifdef NEED_SS_EXECUTE_COMMAND_PROTO +int ss_execute_command(int, char **); +#endif + +extern ss_request_table kadmin_cmds; +extern int exit_status; +extern char *whoami; + +int +main(int argc, char *argv[]) +{ + char *request, **args; + krb5_error_code retval; + int sci_idx, code = 0; + + setlocale(LC_ALL, ""); + whoami = ((whoami = strrchr(argv[0], '/')) ? whoami+1 : argv[0]); + + kadmin_startup(argc, argv, &request, &args); + sci_idx = ss_create_invocation(whoami, "5.0", NULL, &kadmin_cmds, &retval); + if (retval) { + ss_perror(sci_idx, retval, _("creating invocation")); + exit(1); + } + + if (*args != NULL) { + /* Execute post-option arguments as a single script-mode command. */ + code = ss_execute_command(sci_idx, args); + if (code) { + ss_perror(sci_idx, code, *args); + exit_status = 1; + } + } else if (request != NULL) { + /* Execute the -q option as a single interactive command. */ + code = ss_execute_line(sci_idx, request); + if (code != 0) { + ss_perror(sci_idx, code, request); + exit_status = 1; + } + } else { + /* Prompt for commands. */ + (void)ss_listen(sci_idx); + } + + return quit() ? 1 : exit_status; +} diff --git a/krb5-1.21.3/src/kadmin/dbutil/Makefile.in b/krb5-1.21.3/src/kadmin/dbutil/Makefile.in new file mode 100644 index 00000000..1fa25d2a --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/Makefile.in @@ -0,0 +1,43 @@ +mydir=kadmin$(S)dbutil +BUILDTOP=$(REL)..$(S).. +LOCALINCLUDES = -I. +KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS) + +PROG = kdb5_util + +SRCS = kdb5_util.c kdb5_create.c kadm5_create.c kdb5_destroy.c \ + kdb5_stash.c import_err.c strtok.c dump.c ovload.c kdb5_mkey.c \ + tabdump.c tdumputil.c +EXTRADEPSRCS = t_tdumputil.c + +OBJS = kdb5_util.o kdb5_create.o kadm5_create.o kdb5_destroy.o \ + kdb5_stash.o import_err.o strtok.o dump.o ovload.o kdb5_mkey.o \ + tabdump.o tdumputil.o + +GETDATE = ../cli/getdate.o + +all: $(PROG) + +$(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(GETDATE) + $(CC_LINK) -o $(PROG) $(OBJS) $(GETDATE) $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS) + +import_err.c import_err.h: $(srcdir)/import_err.et + +$(OBJS): import_err.h + +install: + $(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG) + +clean: + $(RM) $(PROG) $(OBJS) import_err.c import_err.h + $(RM) t_tdumputil.o t_tdumputil + +T_TDUMPUTIL_OBJS = t_tdumputil.o tdumputil.o + +t_tdumputil: $(T_TDUMPUTIL_OBJS) $(SUPPORT_DEPLIB) + $(CC_LINK) -o $@ $(T_TDUMPUTIL_OBJS) $(SUPPORT_LIB) + +depend: import_err.h + +check-pytests: t_tdumputil + $(RUNPYTEST) $(srcdir)/t_tdumputil.py $(PYTESTFLAGS) diff --git a/krb5-1.21.3/src/kadmin/dbutil/deps b/krb5-1.21.3/src/kadmin/dbutil/deps new file mode 100644 index 00000000..8b0965aa --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/deps @@ -0,0 +1,206 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kdb5_util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdb5_util.c kdb5_util.h +$(OUTPRE)kdb5_create.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdb5_create.c \ + kdb5_util.h +$(OUTPRE)kadm5_create.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/fake-addrinfo.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/iprop.h $(top_srcdir)/include/iprop_hdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/kdb_log.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kadm5_create.c kdb5_util.h +$(OUTPRE)kdb5_destroy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdb5_destroy.c \ + kdb5_util.h +$(OUTPRE)kdb5_stash.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdb5_stash.c kdb5_util.h +$(OUTPRE)import_err.$(OBJEXT): $(COM_ERR_DEPS) import_err.c +$(OUTPRE)strtok.$(OBJEXT): nstrtok.h strtok.c +$(OUTPRE)dump.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h dump.c kdb5_util.h +$(OUTPRE)ovload.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h import_err.h kdb5_util.h \ + nstrtok.h ovload.c +$(OUTPRE)kdb5_mkey.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdb5_mkey.c kdb5_util.h +$(OUTPRE)tabdump.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-hex.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/kdb_log.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kdb5_util.h tabdump.c tdumputil.h +$(OUTPRE)tdumputil.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h tdumputil.c tdumputil.h +$(OUTPRE)t_tdumputil.$(OBJEXT): t_tdumputil.c tdumputil.h diff --git a/krb5-1.21.3/src/kadmin/dbutil/dump.c b/krb5-1.21.3/src/kadmin/dbutil/dump.c new file mode 100644 index 00000000..a89b5144 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/dump.c @@ -0,0 +1,1650 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/dbutil/dump.c - Dump a KDC database */ +/* + * Copyright 1990,1991,2001,2006,2008,2009,2013 by the Massachusetts Institute + * of Technology. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +#include +#include +#include +#include +#include "kdb5_util.h" +#if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP) +#include +#endif /* HAVE_REGEX_H */ + +/* Needed for master key conversion. */ +static krb5_boolean mkey_convert; +krb5_keyblock new_master_keyblock; +krb5_kvno new_mkvno; + +#define K5Q1(x) #x +#define K5Q(x) K5Q1(x) +#define K5CONST_WIDTH_SCANF_STR(x) "%" K5Q(x) "s" + +/* Use compile(3) if no regcomp present. */ +#if !defined(HAVE_REGCOMP) && defined(HAVE_REGEXP_H) +#define INIT char *sp = instring; +#define GETC() (*sp++) +#define PEEKC() (*sp) +#define UNGETC(c) (--sp) +#define RETURN(c) return(c) +#define ERROR(c) +#define RE_BUF_SIZE 1024 +#include +#endif /* !HAVE_REGCOMP && HAVE_REGEXP_H */ + +typedef krb5_error_code (*dump_func)(krb5_context context, + krb5_db_entry *entry, const char *name, + FILE *fp, krb5_boolean verbose, + krb5_boolean omit_nra); +typedef int (*load_func)(krb5_context context, const char *dumpfile, FILE *fp, + krb5_boolean verbose, int *linenop); + +typedef struct _dump_version { + char *name; + char *header; + int updateonly; + int iprop; + int ipropx; + dump_func dump_princ; + osa_adb_iter_policy_func dump_policy; + load_func load_record; +} dump_version; + +struct dump_args { + FILE *ofile; + krb5_context context; + char **names; + int nnames; + krb5_boolean verbose; + krb5_boolean omit_nra; /* omit non-replicated attributes */ + dump_version *dump; +}; + +/* External data */ +extern krb5_db_entry *master_entry; + +/* + * Re-encrypt the key_data with the new master key... + */ +krb5_error_code +master_key_convert(krb5_context context, krb5_db_entry *db_entry) +{ + krb5_error_code retval; + krb5_keyblock v5plainkey, *key_ptr, *tmp_mkey; + krb5_keysalt keysalt; + krb5_key_data new_key_data, *key_data; + krb5_boolean is_mkey; + krb5_kvno kvno; + int i, j; + + is_mkey = krb5_principal_compare(context, master_princ, db_entry->princ); + + if (is_mkey) { + return add_new_mkey(context, db_entry, &new_master_keyblock, + new_mkvno); + } + + for (i = 0; i < db_entry->n_key_data; i++) { + key_data = &db_entry->key_data[i]; + retval = krb5_dbe_find_mkey(context, db_entry, &tmp_mkey); + if (retval) + return retval; + retval = krb5_dbe_decrypt_key_data(context, tmp_mkey, key_data, + &v5plainkey, &keysalt); + if (retval) + return retval; + + memset(&new_key_data, 0, sizeof(new_key_data)); + + key_ptr = &v5plainkey; + kvno = key_data->key_data_kvno; + + retval = krb5_dbe_encrypt_key_data(context, &new_master_keyblock, + key_ptr, &keysalt, kvno, + &new_key_data); + if (retval) + return retval; + krb5_free_keyblock_contents(context, &v5plainkey); + for (j = 0; j < key_data->key_data_ver; j++) { + if (key_data->key_data_length[j]) + free(key_data->key_data_contents[j]); + } + *key_data = new_key_data; + } + assert(new_mkvno > 0); + return krb5_dbe_update_mkvno(context, db_entry, new_mkvno); +} + +/* Create temp file for new dump to be named ofile. */ +static FILE * +create_ofile(char *ofile, char **tmpname) +{ + int fd = -1; + FILE *f; + + *tmpname = NULL; + if (asprintf(tmpname, "%s-XXXXXX", ofile) < 0) + goto error; + + fd = mkstemp(*tmpname); + if (fd == -1) + goto error; + + f = fdopen(fd, "w+"); + if (f != NULL) + return f; + +error: + com_err(progname, errno, _("while allocating temporary filename dump")); + if (fd >= 0) + unlink(*tmpname); + exit(1); +} + +/* Rename new dump file into place. */ +static void +finish_ofile(char *ofile, char **tmpname) +{ + if (rename(*tmpname, ofile) == -1) { + com_err(progname, errno, _("while renaming dump file into place")); + exit(1); + } + free(*tmpname); + *tmpname = NULL; +} + +/* Create the .dump_ok file. */ +static krb5_boolean +prep_ok_file(krb5_context context, char *file_name, int *fd_out) +{ + static char ok[] = ".dump_ok"; + krb5_error_code retval; + char *file_ok = NULL; + int fd = -1; + krb5_boolean success = FALSE; + + *fd_out = -1; + + if (asprintf(&file_ok, "%s%s", file_name, ok) < 0) { + com_err(progname, ENOMEM, _("while allocating dump_ok filename")); + goto cleanup; + } + + fd = open(file_ok, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd == -1) { + com_err(progname, errno, _("while creating 'ok' file, '%s'"), file_ok); + goto cleanup; + } + retval = krb5_lock_file(context, fd, KRB5_LOCKMODE_EXCLUSIVE); + if (retval) { + com_err(progname, retval, _("while locking 'ok' file, '%s'"), file_ok); + goto cleanup; + } + + *fd_out = fd; + fd = -1; + success = TRUE; + +cleanup: + free(file_ok); + if (fd != -1) + close(fd); + if (!success) + exit_status++; + return success; +} + +/* + * Update the "ok" file. + */ +static void +update_ok_file(krb5_context context, int fd) +{ + write(fd, "", 1); + krb5_lock_file(context, fd, KRB5_LOCKMODE_UNLOCK); + close(fd); +} + +/* Return true if a principal name matches a regular expression or string. */ +static int +name_matches(char *name, struct dump_args *args) +{ +#if HAVE_REGCOMP + regex_t reg; + regmatch_t rmatch; + int st; + char errmsg[BUFSIZ]; +#elif HAVE_REGEXP_H + char regexp_buffer[RE_BUF_SIZE]; +#elif HAVE_RE_COMP + extern char *re_comp(); + char *re_result; +#endif /* HAVE_RE_COMP */ + int i, match; + + /* Check each regular expression in args. */ + match = args->nnames ? 0 : 1; + for (i = 0; i < args->nnames && !match; i++) { +#if HAVE_REGCOMP + /* Compile the regular expression. */ + st = regcomp(®, args->names[i], REG_EXTENDED); + if (st) { + regerror(st, ®, errmsg, sizeof(errmsg)); + fprintf(stderr, _("%s: regular expression error: %s\n"), progname, + errmsg); + break; + } + /* See if we have a match. */ + st = regexec(®, name, 1, &rmatch, 0); + if (st == 0) { + /* See if it matches the whole name. */ + if (rmatch.rm_so == 0 && (size_t)rmatch.rm_eo == strlen(name)) + match = 1; + } else if (st != REG_NOMATCH) { + regerror(st, ®, errmsg, sizeof(errmsg)); + fprintf(stderr, _("%s: regular expression match error: %s\n"), + progname, errmsg); + break; + } + regfree(®); +#elif HAVE_REGEXP_H + /* Compile the regular expression. */ + compile(args->names[i], regexp_buffer, ®exp_buffer[RE_BUF_SIZE], + '\0'); + if (step(name, regexp_buffer)) { + if (loc1 == name && loc2 == &name[strlen(name)]) + match = 1; + } +#elif HAVE_RE_COMP + /* Compile the regular expression. */ + re_result = re_comp(args->names[i]); + if (re_result) { + fprintf(stderr, _("%s: regular expression error: %s\n"), progname, + re_result); + break; + } + if (re_exec(name)) + match = 1; +#else /* HAVE_RE_COMP */ + /* If no regular expression support, then just compare the strings. */ + if (!strcmp(args->names[i], name)) + match = 1; +#endif /* HAVE_REGCOMP */ + } + return match; +} + +/* Output "-1" if len is 0; otherwise output len bytes of data in hex. */ +static void +dump_octets_or_minus1(FILE *fp, unsigned char *data, size_t len) +{ + if (len > 0) { + for (; len > 0; len--) + fprintf(fp, "%02x", *data++); + } else { + fprintf(fp, "-1"); + } +} + +/* + * Dump TL data; common to principals and policies. + * + * If filter_kadm then the KRB5_TL_KADM_DATA (where a principal's policy + * name is stored) is filtered out. This is for dump formats that don't + * support policies. + */ +static void +dump_tl_data(FILE *ofile, krb5_tl_data *tlp, krb5_boolean filter_kadm) +{ + for (; tlp != NULL; tlp = tlp->tl_data_next) { + if (tlp->tl_data_type == KRB5_TL_KADM_DATA && filter_kadm) + continue; + fprintf(ofile, "\t%d\t%d\t", (int)tlp->tl_data_type, + (int)tlp->tl_data_length); + dump_octets_or_minus1(ofile, tlp->tl_data_contents, + tlp->tl_data_length); + } +} + +/* Dump a principal entry in krb5 beta 7 format. Omit kadmin tl-data if kadm + * is false. */ +static krb5_error_code +k5beta7_common(krb5_context context, krb5_db_entry *entry, + const char *name, FILE *fp, krb5_boolean verbose, + krb5_boolean omit_nra, krb5_boolean kadm) +{ + krb5_tl_data *tlp; + krb5_key_data *kdata; + int counter, skip, i; + + /* + * The dump format is as follows: + * len strlen(name) n_tl_data n_key_data e_length + * name + * attributes max_life max_renewable_life expiration + * pw_expiration last_success last_failed fail_auth_count + * n_tl_data*[type length ] + * n_key_data*[ver kvno ver*(type length )] + * + * Fields which are not encapsulated by angle-brackets are to appear + * verbatim. A bracketed field's absence is indicated by a -1 in its + * place. + */ + + /* Make sure that the tagged list is reasonably correct. */ + counter = skip = 0; + for (tlp = entry->tl_data; tlp; tlp = tlp->tl_data_next) { + /* Don't dump tl data types we know aren't understood by earlier + * versions. */ + if (tlp->tl_data_type == KRB5_TL_KADM_DATA && !kadm) + skip++; + else + counter++; + } + + if (counter + skip != entry->n_tl_data) { + fprintf(stderr, _("%s: tagged data list inconsistency for %s " + "(counted %d, stored %d)\n"), progname, name, + counter + skip, (int)entry->n_tl_data); + return EINVAL; + } + + /* Write out header. */ + fprintf(fp, "princ\t%d\t%lu\t%d\t%d\t%d\t%s\t", (int)entry->len, + (unsigned long)strlen(name), counter, (int)entry->n_key_data, + (int)entry->e_length, name); + fprintf(fp, "%d\t%d\t%d\t%u\t%u\t%u\t%u\t%d", entry->attributes, + entry->max_life, entry->max_renewable_life, + (unsigned int)entry->expiration, + (unsigned int)entry->pw_expiration, + (unsigned int)(omit_nra ? 0 : entry->last_success), + (unsigned int)(omit_nra ? 0 : entry->last_failed), + omit_nra ? 0 : entry->fail_auth_count); + + /* Write out tagged data. */ + dump_tl_data(fp, entry->tl_data, !kadm); + fprintf(fp, "\t"); + + /* Write out key data. */ + for (counter = 0; counter < entry->n_key_data; counter++) { + kdata = &entry->key_data[counter]; + fprintf(fp, "%d\t%d\t", (int)kdata->key_data_ver, + (int)kdata->key_data_kvno); + for (i = 0; i < kdata->key_data_ver; i++) { + fprintf(fp, "%d\t%d\t", kdata->key_data_type[i], + kdata->key_data_length[i]); + dump_octets_or_minus1(fp, kdata->key_data_contents[i], + kdata->key_data_length[i]); + fprintf(fp, "\t"); + } + } + + /* Write out extra data. */ + dump_octets_or_minus1(fp, entry->e_data, entry->e_length); + + /* Write trailer. */ + fprintf(fp, ";\n"); + + if (verbose) + fprintf(stderr, "%s\n", name); + + return 0; +} + +/* Output a dump record in krb5b7 format. */ +static krb5_error_code +dump_k5beta7_princ(krb5_context context, krb5_db_entry *entry, + const char *name, FILE *fp, krb5_boolean verbose, + krb5_boolean omit_nra) +{ + return k5beta7_common(context, entry, name, fp, verbose, omit_nra, FALSE); +} + +static krb5_error_code +dump_k5beta7_princ_withpolicy(krb5_context context, krb5_db_entry *entry, + const char *name, FILE *fp, krb5_boolean verbose, + krb5_boolean omit_nra) +{ + return k5beta7_common(context, entry, name, fp, verbose, omit_nra, TRUE); +} + +static void +dump_k5beta7_policy(void *data, osa_policy_ent_t entry) +{ + struct dump_args *arg = data; + + fprintf(arg->ofile, "policy\t%s\t%d\t%d\t%d\t%d\t%d\t%d\n", entry->name, + entry->pw_min_life, entry->pw_max_life, entry->pw_min_length, + entry->pw_min_classes, entry->pw_history_num, 0); +} + +static void +dump_r1_8_policy(void *data, osa_policy_ent_t entry) +{ + struct dump_args *arg = data; + + fprintf(arg->ofile, "policy\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", + entry->name, entry->pw_min_life, entry->pw_max_life, + entry->pw_min_length, entry->pw_min_classes, entry->pw_history_num, + 0, entry->pw_max_fail, entry->pw_failcnt_interval, + entry->pw_lockout_duration); +} + +static void +dump_r1_11_policy(void *data, osa_policy_ent_t entry) +{ + struct dump_args *arg = data; + + fprintf(arg->ofile, "policy\t%s\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t" + "%d\t%d\t%d\t%s\t%d", entry->name, entry->pw_min_life, + entry->pw_max_life, entry->pw_min_length, entry->pw_min_classes, + entry->pw_history_num, 0, entry->pw_max_fail, + entry->pw_failcnt_interval, entry->pw_lockout_duration, + entry->attributes, entry->max_life, entry->max_renewable_life, + entry->allowed_keysalts ? entry->allowed_keysalts : "-", + entry->n_tl_data); + + dump_tl_data(arg->ofile, entry->tl_data, FALSE); + fprintf(arg->ofile, "\n"); +} + +static krb5_error_code +dump_iterator(void *ptr, krb5_db_entry *entry) +{ + krb5_error_code ret; + struct dump_args *args = ptr; + char *name; + + ret = krb5_unparse_name(args->context, entry->princ, &name); + if (ret) { + com_err(progname, ret, _("while unparsing principal name")); + return ret; + } + + /* Re-encode the keys in the new master key, if necessary. */ + if (mkey_convert) { + ret = master_key_convert(args->context, entry); + if (ret) { + com_err(progname, ret, _("while converting %s to new master key"), + name); + goto cleanup; + } + } + + /* Don't dump this entry if we have match strings and it doesn't match. */ + if (args->nnames > 0 && !name_matches(name, args)) + goto cleanup; + + ret = args->dump->dump_princ(args->context, entry, name, args->ofile, + args->verbose, args->omit_nra); + +cleanup: + free(name); + return ret; +} + +static inline void +load_err(const char *fname, int lineno, const char *msg) +{ + fprintf(stderr, _("%s(%d): %s\n"), fname, lineno, msg); +} + +/* Read a string of bytes. Increment *lp for each newline. Return 0 on + * success, 1 on failure. */ +static int +read_string(FILE *f, char *buf, int len, int *lp) +{ + int c, i; + + for (i = 0; i < len; i++) { + c = fgetc(f); + if (c < 0) + return 1; + if (c == '\n') + (*lp)++; + buf[i] = c; + } + buf[len] = '\0'; + return 0; +} + +/* Read a string of two-character representations of bytes. */ +static int +read_octet_string(FILE *f, unsigned char *buf, int len) +{ + int c, i; + + for (i = 0; i < len; i++) { + if (fscanf(f, "%02x", &c) != 1) + return 1; + buf[i] = c; + } + return 0; +} + +/* Read the end of a dumpfile record. */ +static void +read_record_end(FILE *f, const char *fn, int lineno) +{ + int ch; + + if ((ch = fgetc(f)) != ';' || (ch = fgetc(f)) != '\n') { + fprintf(stderr, _("%s(%d): ignoring trash at end of line: "), fn, + lineno); + while (ch != '\n') { + putc(ch, stderr); + ch = fgetc(f); + } + putc(ch, stderr); + } +} + +/* Allocate and form a TL data list of a desired size. */ +static int +alloc_tl_data(krb5_int16 n_tl_data, krb5_tl_data **tldp) +{ + krb5_tl_data **tlp = tldp; + int i; + + for (i = 0; i < n_tl_data; i++) { + *tlp = calloc(1, sizeof(krb5_tl_data)); + if (*tlp == NULL) + return ENOMEM; /* caller cleans up */ + tlp = &((*tlp)->tl_data_next); + } + + return 0; +} + +/* If len is zero, read the string "-1" from fp. Otherwise allocate space and + * read len octets. Return 0 on success, 1 on failure. */ +static int +read_octets_or_minus1(FILE *fp, size_t len, unsigned char **out) +{ + int ival; + unsigned char *buf; + + *out = NULL; + if (len == 0) + return fscanf(fp, "%d", &ival) != 1 || ival != -1; + buf = malloc(len); + if (buf == NULL) + return 1; + if (read_octet_string(fp, buf, len)) { + free(buf); + return 1; + } + *out = buf; + return 0; +} + +/* Read TL data for a principal or policy. Print an error and return -1 on + * failure. */ +static int +process_tl_data(const char *fname, FILE *filep, int lineno, + krb5_tl_data *tl_data) +{ + krb5_tl_data *tl; + int nread, i1; + unsigned int u1; + + for (tl = tl_data; tl; tl = tl->tl_data_next) { + nread = fscanf(filep, "%d\t%u\t", &i1, &u1); + if (nread != 2) { + load_err(fname, lineno, + _("cannot read tagged data type and length")); + return EINVAL; + } + if (i1 < INT16_MIN || i1 > INT16_MAX || u1 > UINT16_MAX) { + load_err(fname, lineno, _("data type or length overflowed")); + return EINVAL; + } + tl->tl_data_type = i1; + tl->tl_data_length = u1; + if (read_octets_or_minus1(filep, tl->tl_data_length, + &tl->tl_data_contents)) { + load_err(fname, lineno, _("cannot read tagged data contents")); + return EINVAL; + } + } + + return 0; +} + +/* Read a beta 7 entry and add it to the database. Return -1 for end of file, + * 0 for success and 1 for failure. */ +static int +process_k5beta7_princ(krb5_context context, const char *fname, FILE *filep, + krb5_boolean verbose, int *linenop) +{ + int retval, nread, i, j; + krb5_db_entry *dbentry; + int t1, t2, t3, t4; + unsigned int u1, u2, u3, u4, u5; + char *name = NULL; + krb5_key_data *kp = NULL, *kd; + krb5_tl_data *tl; + krb5_error_code ret; + + dbentry = calloc(1, sizeof(*dbentry)); + if (dbentry == NULL) + return 1; + (*linenop)++; + nread = fscanf(filep, "%u\t%u\t%u\t%u\t%u\t", &u1, &u2, &u3, &u4, &u5); + if (nread == EOF) { + retval = -1; + goto cleanup; + } + if (nread != 5) { + load_err(fname, *linenop, _("cannot match size tokens")); + goto fail; + } + + /* Get memory for flattened principal name */ + if (u2 > UINT_MAX / 2) { + load_err(fname, *linenop, _("cannot allocate principal (too large)")); + goto fail; + } + name = malloc(u2 + 1); + if (name == NULL) + goto fail; + + /* Get memory for and form tagged data linked list */ + if (u3 > UINT16_MAX) { + load_err(fname, *linenop, _("cannot allocate tl_data (too large)")); + goto fail; + } + if (alloc_tl_data(u3, &dbentry->tl_data)) + goto fail; + dbentry->n_tl_data = u3; + + /* Get memory for key list */ + if (u4 > INT16_MAX) { + load_err(fname, *linenop, _("invalid key_data size")); + goto fail; + } + if (u4 && (kp = calloc(u4, sizeof(krb5_key_data))) == NULL) + goto fail; + + dbentry->len = u1; + dbentry->n_key_data = u4; + dbentry->e_length = u5; + + if (kp != NULL) { + dbentry->key_data = kp; + kp = NULL; + } + + /* Read in and parse the principal name */ + if (read_string(filep, name, u2, linenop)) { + load_err(fname, *linenop, _("cannot read name string")); + goto fail; + } + ret = krb5_parse_name(context, name, &dbentry->princ); + if (ret) { + com_err(progname, ret, _("while parsing name %s"), name); + goto fail; + } + + /* Get the fixed principal attributes */ + nread = fscanf(filep, "%d\t%d\t%d\t%u\t%u\t%d\t%d\t%d\t", + &t1, &t2, &t3, &u1, &u2, &u3, &u4, &u5); + if (nread != 8) { + load_err(fname, *linenop, _("cannot read principal attributes")); + goto fail; + } + dbentry->attributes = t1; + dbentry->max_life = t2; + dbentry->max_renewable_life = t3; + dbentry->expiration = u1; + dbentry->pw_expiration = u2; + dbentry->last_success = u3; + dbentry->last_failed = u4; + dbentry->fail_auth_count = u5; + dbentry->mask = KADM5_LOAD | KADM5_PRINCIPAL | KADM5_ATTRIBUTES | + KADM5_MAX_LIFE | KADM5_MAX_RLIFE | + KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION | KADM5_LAST_SUCCESS | + KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT; + + /* Read tagged data. */ + if (dbentry->n_tl_data) { + if (process_tl_data(fname, filep, *linenop, dbentry->tl_data)) + goto fail; + for (tl = dbentry->tl_data; tl; tl = tl->tl_data_next) { + /* test to set mask fields */ + if (tl->tl_data_type == KRB5_TL_KADM_DATA) { + XDR xdrs; + osa_princ_ent_rec osa_princ_ent; + + /* + * Assuming aux_attributes will always be + * there + */ + dbentry->mask |= KADM5_AUX_ATTRIBUTES; + + /* test for an actual policy reference */ + memset(&osa_princ_ent, 0, sizeof(osa_princ_ent)); + xdrmem_create(&xdrs, (char *)tl->tl_data_contents, + tl->tl_data_length, XDR_DECODE); + if (xdr_osa_princ_ent_rec(&xdrs, &osa_princ_ent)) { + if ((osa_princ_ent.aux_attributes & KADM5_POLICY) && + osa_princ_ent.policy != NULL) + dbentry->mask |= KADM5_POLICY; + kdb_free_entry(NULL, NULL, &osa_princ_ent); + } + xdr_destroy(&xdrs); + } + } + dbentry->mask |= KADM5_TL_DATA; + } + + /* Get the key data. */ + for (i = 0; i < dbentry->n_key_data; i++) { + kd = &dbentry->key_data[i]; + nread = fscanf(filep, "%d\t%d\t", &t1, &t2); + if (nread != 2) { + load_err(fname, *linenop, _("cannot read key size and version")); + goto fail; + } + if (t1 > KRB5_KDB_V1_KEY_DATA_ARRAY) { + load_err(fname, *linenop, _("unsupported key_data_ver version")); + goto fail; + } + if (t2 < 0 || t2 > UINT16_MAX) { + load_err(fname, *linenop, _("invalid kvno")); + goto fail; + } + + kd->key_data_ver = t1; + kd->key_data_kvno = t2; + + for (j = 0; j < t1; j++) { + nread = fscanf(filep, "%d\t%d\t", &t3, &t4); + if (nread != 2 || t4 < 0 || t4 > UINT16_MAX) { + load_err(fname, *linenop, + _("cannot read key type and length")); + goto fail; + } + kd->key_data_type[j] = t3; + kd->key_data_length[j] = t4; + if (read_octets_or_minus1(filep, t4, &kd->key_data_contents[j])) { + load_err(fname, *linenop, _("cannot read key data")); + goto fail; + } + } + } + if (dbentry->n_key_data) + dbentry->mask |= KADM5_KEY_DATA; + + /* Get the extra data */ + if (read_octets_or_minus1(filep, dbentry->e_length, &dbentry->e_data)) { + load_err(fname, *linenop, _("cannot read extra data")); + goto fail; + } + + /* Finally, find the end of the record. */ + read_record_end(filep, fname, *linenop); + + ret = krb5_db_put_principal(context, dbentry); + if (ret) { + com_err(progname, ret, _("while storing %s"), name); + goto fail; + } + + if (verbose) + fprintf(stderr, "%s\n", name); + retval = 0; + +cleanup: + free(kp); + free(name); + krb5_db_free_principal(context, dbentry); + return retval; + +fail: + retval = 1; + goto cleanup; +} + +static int +process_k5beta7_policy(krb5_context context, const char *fname, FILE *filep, + krb5_boolean verbose, int *linenop) +{ + osa_policy_ent_rec rec; + char namebuf[1024]; + unsigned int refcnt; + int nread, ret; + + memset(&rec, 0, sizeof(rec)); + + (*linenop)++; + rec.name = namebuf; + + nread = fscanf(filep, "%1023s\t%u\t%u\t%u\t%u\t%u\t%u", rec.name, + &rec.pw_min_life, &rec.pw_max_life, &rec.pw_min_length, + &rec.pw_min_classes, &rec.pw_history_num, &refcnt); + if (nread == EOF) + return -1; + if (nread != 7) { + fprintf(stderr, _("cannot parse policy (%d read)\n"), nread); + return 1; + } + + ret = krb5_db_create_policy(context, &rec); + if (ret) + ret = krb5_db_put_policy(context, &rec); + if (ret) { + com_err(progname, ret, _("while creating policy")); + return 1; + } + if (verbose) + fprintf(stderr, _("created policy %s\n"), rec.name); + + return 0; +} + +static int +process_r1_8_policy(krb5_context context, const char *fname, FILE *filep, + krb5_boolean verbose, int *linenop) +{ + osa_policy_ent_rec rec; + char namebuf[1024]; + unsigned int refcnt; + int nread, ret; + + memset(&rec, 0, sizeof(rec)); + + (*linenop)++; + rec.name = namebuf; + + nread = fscanf(filep, "%1023s\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u", + rec.name, &rec.pw_min_life, &rec.pw_max_life, + &rec.pw_min_length, &rec.pw_min_classes, + &rec.pw_history_num, &refcnt, &rec.pw_max_fail, + &rec.pw_failcnt_interval, &rec.pw_lockout_duration); + if (nread == EOF) + return -1; + if (nread != 10) { + fprintf(stderr, _("cannot parse policy (%d read)\n"), nread); + return 1; + } + + ret = krb5_db_create_policy(context, &rec); + if (ret) + ret = krb5_db_put_policy(context, &rec); + if (ret) { + com_err(progname, ret, _("while creating policy")); + return 1; + } + if (verbose) + fprintf(stderr, "created policy %s\n", rec.name); + + return 0; +} + +static int +process_r1_11_policy(krb5_context context, const char *fname, FILE *filep, + krb5_boolean verbose, int *linenop) +{ + osa_policy_ent_rec rec; + krb5_tl_data *tl, *tl_next; + char namebuf[1024]; + char keysaltbuf[KRB5_KDB_MAX_ALLOWED_KS_LEN + 1]; + unsigned int refcnt; + int nread, c, ret = 0; + + memset(&rec, 0, sizeof(rec)); + + (*linenop)++; + rec.name = namebuf; + + /* + * Due to a historical error, iprop dumps use the same version before and + * after the 1.11 policy extensions. So we need to accept both 1.8-format + * and 1.11-format policy entries. Begin by reading the 1.8 fields. + */ + nread = fscanf(filep, "%1023s\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\t%u", + rec.name, &rec.pw_min_life, &rec.pw_max_life, + &rec.pw_min_length, &rec.pw_min_classes, + &rec.pw_history_num, &refcnt, &rec.pw_max_fail, + &rec.pw_failcnt_interval, &rec.pw_lockout_duration); + if (nread == EOF) + return -1; + if (nread != 10) { + fprintf(stderr, _("cannot parse policy (%d read)\n"), nread); + return 1; + } + + /* The next character should be a newline (1.8) or a tab (1.11). */ + c = getc(filep); + if (c == EOF) + return -1; + if (c != '\n') { + /* Read the additional 1.11-format fields. */ + rec.allowed_keysalts = keysaltbuf; + nread = fscanf(filep, "%u\t%u\t%u\t" + K5CONST_WIDTH_SCANF_STR(KRB5_KDB_MAX_ALLOWED_KS_LEN) + "\t%hd", &rec.attributes, &rec.max_life, + &rec.max_renewable_life, rec.allowed_keysalts, + &rec.n_tl_data); + if (nread == EOF) + return -1; + if (nread != 5) { + fprintf(stderr, _("cannot parse policy (%d read)\n"), nread); + return 1; + } + + if (rec.allowed_keysalts && !strcmp(rec.allowed_keysalts, "-")) + rec.allowed_keysalts = NULL; + + /* Get TL data */ + ret = alloc_tl_data(rec.n_tl_data, &rec.tl_data); + if (ret) + goto cleanup; + + ret = process_tl_data(fname, filep, *linenop, rec.tl_data); + if (ret) + goto cleanup; + } + + ret = krb5_db_create_policy(context, &rec); + if (ret) + ret = krb5_db_put_policy(context, &rec); + if (ret) { + com_err(progname, ret, _("while creating policy")); + goto cleanup; + } + if (verbose) + fprintf(stderr, "created policy %s\n", rec.name); + +cleanup: + for (tl = rec.tl_data; tl; tl = tl_next) { + tl_next = tl->tl_data_next; + free(tl->tl_data_contents); + free(tl); + } + return ret ? 1 : 0; +} + +/* Read a record which is tagged with "princ" or "policy", calling princfn + * or policyfn as appropriate. */ +static int +process_tagged(krb5_context context, const char *fname, FILE *filep, + krb5_boolean verbose, int *linenop, load_func princfn, + load_func policyfn) +{ + int nread; + char rectype[100]; + + nread = fscanf(filep, "%99s\t", rectype); + if (nread == EOF) + return -1; + if (nread != 1) + return 1; + if (strcmp(rectype, "princ") == 0) + return (*princfn)(context, fname, filep, verbose, linenop); + if (strcmp(rectype, "policy") == 0) + return (*policyfn)(context, fname, filep, verbose, linenop); + if (strcmp(rectype, "End") == 0) /* Only expected for OV format */ + return -1; + + fprintf(stderr, _("unknown record type \"%s\"\n"), rectype); + return 1; +} + +static int +process_k5beta7_record(krb5_context context, const char *fname, FILE *filep, + krb5_boolean verbose, int *linenop) +{ + return process_tagged(context, fname, filep, verbose, linenop, + process_k5beta7_princ, process_k5beta7_policy); +} + +static int +process_r1_8_record(krb5_context context, const char *fname, FILE *filep, + krb5_boolean verbose, int *linenop) +{ + return process_tagged(context, fname, filep, verbose, linenop, + process_k5beta7_princ, process_r1_8_policy); +} + +static int +process_r1_11_record(krb5_context context, const char *fname, FILE *filep, + krb5_boolean verbose, int *linenop) +{ + return process_tagged(context, fname, filep, verbose, linenop, + process_k5beta7_princ, process_r1_11_policy); +} + +dump_version beta7_version = { + "Kerberos version 5", + "kdb5_util load_dump version 4\n", + 0, + 0, + 0, + dump_k5beta7_princ, + dump_k5beta7_policy, + process_k5beta7_record, +}; +dump_version r1_3_version = { + "Kerberos version 5 release 1.3", + "kdb5_util load_dump version 5\n", + 0, + 0, + 0, + dump_k5beta7_princ_withpolicy, + dump_k5beta7_policy, + process_k5beta7_record, +}; +dump_version r1_8_version = { + "Kerberos version 5 release 1.8", + "kdb5_util load_dump version 6\n", + 0, + 0, + 0, + dump_k5beta7_princ_withpolicy, + dump_r1_8_policy, + process_r1_8_record, +}; +dump_version r1_11_version = { + "Kerberos version 5 release 1.11", + "kdb5_util load_dump version 7\n", + 0, + 0, + 0, + dump_k5beta7_princ_withpolicy, + dump_r1_11_policy, + process_r1_11_record, +}; +dump_version iprop_version = { + "Kerberos iprop version", + "iprop", + 0, + 1, + 0, + dump_k5beta7_princ_withpolicy, + dump_k5beta7_policy, + process_k5beta7_record, +}; +dump_version ipropx_1_version = { + "Kerberos iprop extensible version", + "ipropx", + 0, + 1, + 1, + dump_k5beta7_princ_withpolicy, + dump_r1_11_policy, + process_r1_11_record, +}; + +/* Read the dump header. Return 1 on success, 0 if the file is not a + * recognized iprop dump format. */ +static int +parse_iprop_header(char *buf, dump_version **dv, kdb_last_t *last) +{ + char head[128]; + int nread; + uint32_t u[4]; + uint32_t *up = &u[0]; + + nread = sscanf(buf, "%127s %u %u %u %u", head, &u[0], &u[1], &u[2], &u[3]); + if (nread < 1) + return 0; + + if (!strcmp(head, ipropx_1_version.header)) { + if (nread != 5) + return 0; + if (u[0] == IPROPX_VERSION_0) { + *dv = &iprop_version; + } else if (u[0] == IPROPX_VERSION_1) { + *dv = &ipropx_1_version; + } else { + fprintf(stderr, _("%s: Unknown iprop dump version %d\n"), progname, + u[0]); + return 0; + } + up = &u[1]; + } else if (!strcmp(head, iprop_version.header)) { + if (nread != 4) + return 0; + *dv = &iprop_version; + } else { + fprintf(stderr, "Invalid iprop header\n"); + return 0; + } + + last->last_sno = *up++; + last->last_time.seconds = *up++; + last->last_time.useconds = *up++; + return 1; +} + +/* Return true if the serial number and timestamp in an existing dump file is + * in the ulog. */ +static krb5_boolean +current_dump_sno_in_ulog(krb5_context context, const char *ifile) +{ + update_status_t status; + dump_version *junk; + kdb_last_t last; + char buf[BUFSIZ], *r; + FILE *f; + + f = fopen(ifile, "r"); + if (f == NULL) + return 0; /* aliasing other errors to ENOENT here is OK */ + + r = fgets(buf, sizeof(buf), f); + fclose(f); + if (r == NULL) + return errno ? -1 : 0; + + if (!parse_iprop_header(buf, &junk, &last)) + return 0; + + status = ulog_get_sno_status(context, &last); + return status == UPDATE_OK || status == UPDATE_NIL; +} + +void +dump_db(int argc, char **argv) +{ + FILE *f; + struct dump_args args; + char *ofile = NULL, *tmpofile = NULL, *new_mkey_file = NULL; + krb5_error_code ret, retval; + dump_version *dump; + int aindex, ok_fd = -1; + bool_t dump_sno = FALSE; + kdb_log_context *log_ctx; + unsigned int ipropx_version = IPROPX_VERSION_0; + krb5_kvno kt_kvno; + krb5_boolean conditional = FALSE; + kdb_last_t last; + krb5_flags iterflags = 0; + + /* Parse the arguments. */ + dump = &r1_11_version; + args.verbose = FALSE; + args.omit_nra = FALSE; + mkey_convert = FALSE; + log_ctx = util_context->kdblog_context; + + /* + * Parse the qualifiers. + */ + for (aindex = 1; aindex < argc; aindex++) { + if (!strcmp(argv[aindex], "-b7")) { + dump = &beta7_version; + } else if (!strcmp(argv[aindex], "-ov")) { + fprintf(stderr, _("OV dump format not supported\n")); + goto error; + } else if (!strcmp(argv[aindex], "-r13")) { + dump = &r1_3_version; + } else if (!strcmp(argv[aindex], "-r18")) { + dump = &r1_8_version; + } else if (!strncmp(argv[aindex], "-i", 2)) { + /* Intentionally undocumented - only used by kadmin. */ + if (log_ctx && log_ctx->iproprole) { + /* ipropx_version is the maximum version acceptable. */ + ipropx_version = atoi(argv[aindex] + 2); + dump = ipropx_version ? &ipropx_1_version : &iprop_version; + /* + * dump_sno is used to indicate if the serial number should be + * populated in the output file to be used later by iprop for + * updating the replica's update log when loading. + */ + dump_sno = TRUE; + /* FLAG_OMIT_NRA is set to indicate that non-replicated + * attributes should be omitted. */ + args.omit_nra = TRUE; + } else { + fprintf(stderr, _("Iprop not enabled\n")); + goto error; + } + } else if (!strcmp(argv[aindex], "-c")) { + conditional = 1; + } else if (!strcmp(argv[aindex], "-verbose")) { + args.verbose = TRUE; + } else if (!strcmp(argv[aindex], "-mkey_convert")) { + mkey_convert = 1; + } else if (!strcmp(argv[aindex], "-new_mkey_file")) { + new_mkey_file = argv[++aindex]; + mkey_convert = 1; + } else if (!strcmp(argv[aindex], "-rev")) { + iterflags |= KRB5_DB_ITER_REV; + } else if (!strcmp(argv[aindex], "-recurse")) { + iterflags |= KRB5_DB_ITER_RECURSE; + } else { + break; + } + } + + args.names = NULL; + args.nnames = 0; + if (aindex < argc) { + ofile = argv[aindex]; + aindex++; + if (aindex < argc) { + args.names = &argv[aindex]; + args.nnames = argc - aindex; + } + } + + /* If a conditional ipropx dump we check if the existing dump is + * good enough. */ + if (ofile != NULL && conditional) { + if (!dump->iprop) { + com_err(progname, 0, + _("Conditional dump is an undocumented option for " + "use only for iprop dumps")); + goto error; + } + if (current_dump_sno_in_ulog(util_context, ofile)) + return; + } + + /* + * Make sure the database is open. The policy database only has + * to be opened if we try a dump that uses it. + */ + if (!dbactive) { + com_err(progname, 0, _("Database not currently opened!")); + goto error; + } + + /* + * If we're doing a master key conversion, set up for it. + */ + if (mkey_convert) { + if (!valid_master_key) { + /* TRUE here means read the keyboard, but only once */ + retval = krb5_db_fetch_mkey(util_context, master_princ, + master_keyblock.enctype, TRUE, FALSE, + NULL, NULL, NULL, &master_keyblock); + if (retval) { + com_err(progname, retval, _("while reading master key")); + exit(1); + } + retval = krb5_db_fetch_mkey_list(util_context, master_princ, + &master_keyblock); + if (retval) { + com_err(progname, retval, _("while verifying master key")); + exit(1); + } + } + new_master_keyblock.enctype = global_params.enctype; + if (new_master_keyblock.enctype == ENCTYPE_UNKNOWN) + new_master_keyblock.enctype = DEFAULT_KDC_ENCTYPE; + + if (new_mkey_file) { + if (global_params.mask & KADM5_CONFIG_KVNO) + kt_kvno = global_params.kvno; + else + kt_kvno = IGNORE_VNO; + + retval = krb5_db_fetch_mkey(util_context, master_princ, + new_master_keyblock.enctype, FALSE, + FALSE, new_mkey_file, &kt_kvno, NULL, + &new_master_keyblock); + if (retval) { + com_err(progname, retval, _("while reading new master key")); + exit(1); + } + } else { + printf(_("Please enter new master key....\n")); + retval = krb5_db_fetch_mkey(util_context, master_princ, + new_master_keyblock.enctype, TRUE, + TRUE, NULL, NULL, NULL, + &new_master_keyblock); + if (retval) { + com_err(progname, retval, _("while reading new master key")); + exit(1); + } + } + /* Get new master key vno that will be used to protect princs. */ + new_mkvno = get_next_kvno(util_context, master_entry); + } + + ret = 0; + + if (ofile != NULL && strcmp(ofile, "-")) { + /* Discourage accidental dumping to filenames beginning with '-'. */ + if (ofile[0] == '-') + usage(); + if (!prep_ok_file(util_context, ofile, &ok_fd)) + return; /* prep_ok_file() bumps exit_status */ + f = create_ofile(ofile, &tmpofile); + if (f == NULL) { + com_err(progname, errno, _("while opening %s for writing"), ofile); + goto error; + } + } else { + f = stdout; + } + + args.ofile = f; + args.context = util_context; + args.dump = dump; + fprintf(args.ofile, "%s", dump->header); + + if (dump_sno) { + ret = ulog_get_last(util_context, &last); + if (ret) { + com_err(progname, ret, _("while reading update log header")); + goto error; + } + if (ipropx_version) + fprintf(f, " %u", IPROPX_VERSION); + fprintf(f, " %u", last.last_sno); + fprintf(f, " %u", last.last_time.seconds); + fprintf(f, " %u", last.last_time.useconds); + } + + if (dump->header[strlen(dump->header)-1] != '\n') + fputc('\n', args.ofile); + + ret = krb5_db_iterate(util_context, NULL, dump_iterator, &args, iterflags); + if (ret) { + com_err(progname, ret, _("performing %s dump"), dump->name); + goto error; + } + + /* Don't dump policies if specific principal entries were requested. */ + if (dump->dump_policy != NULL && args.nnames == 0) { + ret = krb5_db_iter_policy(util_context, "*", dump->dump_policy, &args); + if (ret) { + com_err(progname, ret, _("performing %s dump"), dump->name); + goto error; + } + } + + if (f != stdout) { + fclose(f); + finish_ofile(ofile, &tmpofile); + update_ok_file(util_context, ok_fd); + } + return; + +error: + if (tmpofile != NULL) + unlink(tmpofile); + free(tmpofile); + exit_status++; +} + +/* Restore the database from any version dump file. */ +static int +restore_dump(krb5_context context, char *dumpfile, FILE *f, + krb5_boolean verbose, dump_version *dump) +{ + int err = 0; + int lineno = 1; + + /* Process the records. */ + while (!(err = dump->load_record(context, dumpfile, f, verbose, &lineno))); + if (err != -1) { + fprintf(stderr, _("%s: error processing line %d of %s\n"), progname, + lineno, dumpfile); + return err; + } + return 0; +} + +void +load_db(int argc, char **argv) +{ + krb5_error_code ret; + FILE *f = NULL; + char *dumpfile = NULL, *dbname, buf[BUFSIZ]; + dump_version *load = NULL; + int aindex; + kdb_log_context *log_ctx; + kdb_last_t last; + krb5_boolean db_locked = FALSE, temp_db_created = FALSE; + krb5_boolean verbose = FALSE, update = FALSE, iprop_load = FALSE; + + /* Parse the arguments. */ + dbname = global_params.dbname; + exit_status = 0; + log_ctx = util_context->kdblog_context; + + for (aindex = 1; aindex < argc; aindex++) { + if (!strcmp(argv[aindex], "-b7")){ + load = &beta7_version; + } else if (!strcmp(argv[aindex], "-ov")) { + fprintf(stderr, _("OV dump format not supported\n")); + goto error; + } else if (!strcmp(argv[aindex], "-r13")) { + load = &r1_3_version; + } else if (!strcmp(argv[aindex], "-r18")){ + load = &r1_8_version; + } else if (!strcmp(argv[aindex], "-i")) { + /* Intentionally undocumented - only used by kadmin. */ + if (log_ctx && log_ctx->iproprole) { + load = &iprop_version; + iprop_load = TRUE; + } else { + fprintf(stderr, _("Iprop not enabled\n")); + goto error; + } + } else if (!strcmp(argv[aindex], "-verbose")) { + verbose = TRUE; + } else if (!strcmp(argv[aindex], "-update")){ + update = TRUE; + } else if (!strcmp(argv[aindex], "-hash")) { + if (!add_db_arg("hash=true")) { + com_err(progname, ENOMEM, _("while parsing options")); + goto error; + } + } else { + break; + } + } + if (argc - aindex != 1) + usage(); + dumpfile = argv[aindex]; + + /* Open the dumpfile. */ + if (dumpfile != NULL) { + f = fopen(dumpfile, "r"); + if (f == NULL) { + com_err(progname, errno, _("while opening %s"), dumpfile); + goto error; + } + } else { + f = stdin; + dumpfile = _("standard input"); + } + + /* Auto-detect dump version if we weren't told, or verify if we were. */ + if (fgets(buf, sizeof(buf), f) == NULL) { + fprintf(stderr, _("%s: can't read dump header in %s\n"), progname, + dumpfile); + goto error; + } + if (load) { + /* Only check what we know; some headers only contain a prefix. + * NB: this should work for ipropx even though load is iprop */ + if (strncmp(buf, load->header, strlen(load->header)) != 0) { + fprintf(stderr, _("%s: dump header bad in %s\n"), progname, + dumpfile); + goto error; + } + } else { + if (strcmp(buf, beta7_version.header) == 0) { + load = &beta7_version; + } else if (strcmp(buf, r1_3_version.header) == 0) { + load = &r1_3_version; + } else if (strcmp(buf, r1_8_version.header) == 0) { + load = &r1_8_version; + } else if (strcmp(buf, r1_11_version.header) == 0) { + load = &r1_11_version; + } else { + fprintf(stderr, _("%s: dump header bad in %s\n"), progname, + dumpfile); + goto error; + } + } + + if (global_params.iprop_enabled && + ulog_map(util_context, global_params.iprop_logfile, + global_params.iprop_ulogsize)) { + fprintf(stderr, _("Could not open iprop ulog\n")); + goto error; + } + + if (load->updateonly && !update) { + fprintf(stderr, _("%s: dump version %s can only be loaded with the " + "-update flag\n"), progname, load->name); + goto error; + } + + /* If we are not in update mode, we create an alternate database and then + * promote it to be the live db. */ + if (!update) { + if (!add_db_arg("temporary")) { + com_err(progname, ENOMEM, _("computing parameters for database")); + goto error; + } + + if (iprop_load && !add_db_arg("merge_nra")) { + com_err(progname, ENOMEM, _("computing parameters for database")); + goto error; + } + + ret = krb5_db_create(util_context, db5util_db_args); + if (ret) { + com_err(progname, ret, _("while creating database")); + goto error; + } + temp_db_created = TRUE; + } else { + /* Initialize the database. */ + ret = krb5_db_open(util_context, db5util_db_args, + KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN); + if (ret) { + com_err(progname, ret, _("while opening database")); + goto error; + } + + /* Make sure the db is left unusable if the update fails, if the db + * supports locking. */ + ret = krb5_db_lock(util_context, KRB5_DB_LOCKMODE_PERMANENT); + if (ret == 0) { + db_locked = TRUE; + } else if (ret != KRB5_PLUGIN_OP_NOTSUPP) { + com_err(progname, ret, _("while permanently locking database")); + goto error; + } + } + + if (log_ctx != NULL && log_ctx->iproprole && !update) { + /* Don't record updates we are making to the temporary DB. We will + * reinitialize or update the ulog header after promoting it. */ + log_ctx->iproprole = IPROP_REPLICA; + if (iprop_load) { + /* Parse the iprop header information. */ + if (!parse_iprop_header(buf, &load, &last)) + goto error; + } + } + + if (restore_dump(util_context, dumpfile ? dumpfile : _("standard input"), + f, verbose, load)) { + fprintf(stderr, _("%s: %s restore failed\n"), progname, load->name); + goto error; + } + + if (db_locked && (ret = krb5_db_unlock(util_context))) { + com_err(progname, ret, _("while unlocking database")); + goto error; + } + + if (!update) { + /* Initialize the ulog header before promoting so we can't leave behind + * the pre-load ulog state if we are killed just after promoting. */ + if (log_ctx != NULL && log_ctx->iproprole) { + ret = ulog_init_header(util_context); + if (ret) { + com_err(progname, ret, _("while reinitializing update log")); + goto error; + } + } + + ret = krb5_db_promote(util_context, db5util_db_args); + /* Ignore a not supported error since there is nothing to do about it + * anyway. */ + if (ret != 0 && ret != KRB5_PLUGIN_OP_NOTSUPP) { + com_err(progname, ret, + _("while making newly loaded database live")); + goto error; + } + + if (log_ctx != NULL && log_ctx->iproprole) { + /* Reinitialize the ulog header since we replaced the DB, and + * record the iprop state if we received it. */ + ret = ulog_init_header(util_context); + if (ret) { + com_err(progname, ret, _("while reinitializing update log")); + goto error; + } + if (iprop_load) { + ret = ulog_set_last(util_context, &last); + if (ret) { + com_err(progname, ret, + _("while writing update log header")); + goto error; + } + } + } + } + +cleanup: + /* If we created a temporary DB but didn't succeed, destroy it. */ + if (exit_status && temp_db_created) { + ret = krb5_db_destroy(util_context, db5util_db_args); + /* Ignore a not supported error since there is nothing to do about + * it anyway. */ + if (ret != 0 && ret != KRB5_PLUGIN_OP_NOTSUPP) { + com_err(progname, ret, _("while deleting bad database %s"), + dbname); + } + } + + if (f != NULL && f != stdin) + fclose(f); + + return; + +error: + exit_status++; + goto cleanup; +} diff --git a/krb5-1.21.3/src/kadmin/dbutil/import_err.et b/krb5-1.21.3/src/kadmin/dbutil/import_err.et new file mode 100644 index 00000000..48bb8fb9 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/import_err.et @@ -0,0 +1,22 @@ +error_table imp +error_code IMPORT_BAD_FILE, "Input not recognized as database dump" +error_code IMPORT_BAD_TOKEN, "Bad token in dump file." +error_code IMPORT_BAD_VERSION, "Bad version in dump file" +error_code IMPORT_BAD_RECORD, "Defective record encountered: " +error_code IMPORT_BAD_FOOTER, "Truncated input file detected." +error_code IMPORT_FAILED, "Import of dump failed" +error_code IMPORT_MISMATCH_COUNT, "Number of records imported does not match count" +error_code IMPORT_UNK_OPTION, "Unknown command line option.\nUsage: ovsec_adm_import [filename]" +error_code IMPORT_WARN_DB, "Warning -- continuing to import will overwrite existing databases!" +error_code IMPORT_RENAME_FAILED, "Database rename Failed!!" +error_code IMPORT_EXTRA_DATA, "Extra data after footer is ignored." +error_code IMPORT_CONFIRM, "Proceed ?" +error_code IMPORT_OPEN_DUMP, "while opening input file" +error_code IMPORT_IMPORT, "while importing databases" +error_code IMPORT_TTY, "cannot open /dev/tty!!" +error_code IMPORT_RENAME_OPEN, "while opening databases" +error_code IMPORT_RENAME_LOCK, "while acquiring permanent lock" +error_code IMPORT_RENAME_UNLOCK, "while releasing permanent lock" +error_code IMPORT_RENAME_CLOSE, "while closing databases" +error_code IMPORT_GET_PARAMS, "while retrieving configuration parameters" +end diff --git a/krb5-1.21.3/src/kadmin/dbutil/kadm5_create.c b/krb5-1.21.3/src/kadmin/dbutil/kadm5_create.c new file mode 100644 index 00000000..db12cac3 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/kadm5_create.c @@ -0,0 +1,225 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + * + * $Source$ + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include +#include +#include +#include +#include + +#include "fake-addrinfo.h" + + +#include +#include +#include "kdb5_util.h" + +static int add_admin_princ(void *handle, krb5_context context, + char *name, char *realm, int attrs, int lifetime); +static int add_admin_princs(void *handle, krb5_context context, char *realm); + +#define ERR 1 +#define OK 0 + +#define ADMIN_LIFETIME 60*60*3 /* 3 hours */ +#define CHANGEPW_LIFETIME 60*5 /* 5 minutes */ + +/* + * Function: kadm5_create + * + * Purpose: create admin principals in KDC database + * + * Arguments: params (r) configuration parameters to use + * + * Effects: Creates KADM5_ADMIN_SERVICE and KADM5_CHANGEPW_SERVICE + * principals in the KDC database and sets their attributes + * appropriately. + */ +int kadm5_create(kadm5_config_params *params) +{ + int retval; + kadm5_config_params lparams; + + /* + * The lock file has to exist before calling kadm5_init, but + * params->admin_lockfile may not be set yet... + */ + retval = kadm5_get_config_params(util_context, 1, params, &lparams); + if (retval) { + com_err(progname, retval, _("while looking up the Kerberos " + "configuration")); + return 1; + } + + retval = kadm5_create_magic_princs(&lparams, util_context); + + kadm5_free_config_params(util_context, &lparams); + + return retval; +} + +int kadm5_create_magic_princs(kadm5_config_params *params, + krb5_context context) +{ + int retval; + void *handle; + + retval = krb5_klog_init(context, "admin_server", progname, 0); + if (retval) + return retval; + if ((retval = kadm5_init(context, progname, NULL, NULL, params, + KADM5_STRUCT_VERSION, + KADM5_API_VERSION_4, + db5util_db_args, + &handle))) { + com_err(progname, retval, _("while initializing the Kerberos admin " + "interface")); + return retval; + } + + retval = add_admin_princs(handle, context, params->realm); + + kadm5_destroy(handle); + + krb5_klog_close(context); + + return retval; +} + +/* + * Function: add_admin_princs + * + * Purpose: create admin principals + * + * Arguments: + * + * rseed (input) random seed + * realm (input) realm, or NULL for default realm + * (output) status, 0 for success, 1 for serious error + * + * Requires: + * + * Effects: + * + * add_admin_princs creates KADM5_ADMIN_SERVICE, + * KADM5_CHANGEPW_SERVICE. If any of these exist a message is + * printed. If any of these existing principal do not have the proper + * attributes, a warning message is printed. + */ +static int add_admin_princs(void *handle, krb5_context context, char *realm) +{ + krb5_error_code ret = 0; + + if ((ret = add_admin_princ(handle, context, + KADM5_ADMIN_SERVICE, realm, + KRB5_KDB_DISALLOW_TGT_BASED | + KRB5_KDB_LOCKDOWN_KEYS, + ADMIN_LIFETIME))) + return ret; + + return add_admin_princ(handle, context, KADM5_CHANGEPW_SERVICE, realm, + KRB5_KDB_DISALLOW_TGT_BASED | + KRB5_KDB_PWCHANGE_SERVICE | KRB5_KDB_LOCKDOWN_KEYS, + CHANGEPW_LIFETIME); +} + +/* + * Function: add_admin_princ + * + * Arguments: + * + * creator (r) principal to use as "mod_by" + * rseed (r) seed for random key generator + * name (r) principal name + * realm (r) realm name for principal + * attrs (r) principal's attributes + * lifetime (r) principal's max life, or 0 + * not_unique (r) error message for multiple entries, never used + * exists (r) warning message for principal exists + * wrong_attrs (r) warning message for wrong attributes + * + * Returns: + * + * OK on success + * ERR on serious errors + * + * Effects: + * + * If the principal is not unique, not_unique is printed (but this + * never happens). If the principal exists, then exists is printed + * and if the principals attributes != attrs, wrong_attrs is printed. + * Otherwise, the principal is created with mod_by creator and + * attributes attrs and max life of lifetime (if not zero). + */ + +int add_admin_princ(void *handle, krb5_context context, + char *name, char *realm, int attrs, int lifetime) +{ + char *fullname = NULL; + krb5_error_code ret; + kadm5_principal_ent_rec ent; + long flags; + int fret; + + memset(&ent, 0, sizeof(ent)); + + if (asprintf(&fullname, "%s@%s", name, realm) < 0) { + com_err(progname, ENOMEM, _("while appending realm to principal")); + fret = ERR; + goto cleanup; + } + ret = krb5_parse_name(context, fullname, &ent.principal); + if (ret) { + com_err(progname, ret, _("while parsing admin principal name")); + fret = ERR; + goto cleanup; + } + ent.max_life = lifetime; + ent.attributes = attrs; + + flags = KADM5_PRINCIPAL | KADM5_ATTRIBUTES; + if (lifetime) + flags |= KADM5_MAX_LIFE; + ret = kadm5_create_principal(handle, &ent, flags, NULL); + if (ret && ret != KADM5_DUP) { + com_err(progname, ret, _("while creating principal %s"), fullname); + fret = ERR; + goto cleanup; + } + + fret = OK; +cleanup: + krb5_free_principal(context, ent.principal); + free(fullname); + return fret; +} diff --git a/krb5-1.21.3/src/kadmin/dbutil/kdb5_create.c b/krb5-1.21.3/src/kadmin/dbutil/kdb5_create.c new file mode 100644 index 00000000..038a0b21 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/kdb5_create.c @@ -0,0 +1,478 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/dbutil/kdb5_create.c - Create a KDC database */ +/* + * Copyright 1990,1991,2001, 2002, 2008 by the Massachusetts Institute of + * Technology. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +#include +#include +#include +#include +#include "kdb5_util.h" + +enum ap_op { + NULL_KEY, /* setup null keys */ + MASTER_KEY, /* use master key as new key */ + TGT_KEY /* special handling for tgt key */ +}; + +struct realm_info { + krb5_deltat max_life; + krb5_deltat max_rlife; + krb5_timestamp expiration; + krb5_flags flags; + krb5_keyblock *key; + krb5_int32 nkslist; + krb5_key_salt_tuple *kslist; +} rblock; + +struct iterate_args { + krb5_context ctx; + struct realm_info *rblock; + krb5_db_entry *dbentp; +}; + +static krb5_error_code add_principal +(krb5_context, + krb5_principal, + enum ap_op, + struct realm_info *); + +/* + * Steps in creating a database: + * + * 1) use the db calls to open/create a new database + * + * 2) get a realm name for the new db + * + * 3) get a master password for the new db; convert to an encryption key. + * + * 4) create various required entries in the database + * + * 5) close & exit + */ + +extern krb5_keyblock master_keyblock; +extern krb5_principal master_princ; +extern char *mkey_fullname; +krb5_data master_salt; + +krb5_data tgt_princ_entries[] = { + {0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME}, + {0, 0, 0} }; + +krb5_data db_creator_entries[] = { + {0, sizeof("db_creation")-1, "db_creation"} }; + +/* XXX knows about contents of krb5_principal, and that tgt names + are of form TGT/REALM@REALM */ +krb5_principal_data tgt_princ = { + 0, /* magic number */ + {0, 0, 0}, /* krb5_data realm */ + tgt_princ_entries, /* krb5_data *data */ + 2, /* int length */ + KRB5_NT_SRV_INST /* int type */ +}; + +krb5_principal_data db_create_princ = { + 0, /* magic number */ + {0, 0, 0}, /* krb5_data realm */ + db_creator_entries, /* krb5_data *data */ + 1, /* int length */ + KRB5_NT_SRV_INST /* int type */ +}; + +extern char *mkey_password; + +extern char *progname; +extern int exit_status; +extern kadm5_config_params global_params; +extern krb5_context util_context; + +void kdb5_create(argc, argv) + int argc; + char *argv[]; +{ + int optchar; + + krb5_error_code retval; + char *pw_str = 0; + unsigned int pw_size = 0; + int do_stash = 0; + krb5_data pwd, seed; + kdb_log_context *log_ctx; + krb5_kvno mkey_kvno; + + while ((optchar = getopt(argc, argv, "sW")) != -1) { + switch(optchar) { + case 's': + do_stash++; + break; + case 'W': + /* Ignore (deprecated weak random option). */ + break; + case '?': + default: + usage(); + return; + } + } + + rblock.max_life = global_params.max_life; + rblock.max_rlife = global_params.max_rlife; + rblock.expiration = global_params.expiration; + rblock.flags = global_params.flags; + rblock.nkslist = global_params.num_keysalts; + rblock.kslist = global_params.keysalts; + + log_ctx = util_context->kdblog_context; + + /* assemble & parse the master key name */ + + if ((retval = krb5_db_setup_mkey_name(util_context, + global_params.mkey_name, + global_params.realm, + &mkey_fullname, &master_princ))) { + com_err(progname, retval, _("while setting up master key name")); + exit_status++; return; + } + + krb5_princ_set_realm_data(util_context, &db_create_princ, global_params.realm); + krb5_princ_set_realm_length(util_context, &db_create_princ, strlen(global_params.realm)); + krb5_princ_set_realm_data(util_context, &tgt_princ, global_params.realm); + krb5_princ_set_realm_length(util_context, &tgt_princ, strlen(global_params.realm)); + krb5_princ_component(util_context, &tgt_princ,1)->data = global_params.realm; + krb5_princ_component(util_context, &tgt_princ,1)->length = strlen(global_params.realm); + + printf(_("Initializing database '%s' for realm '%s',\n" + "master key name '%s'\n"), + global_params.dbname, global_params.realm, mkey_fullname); + + if (!mkey_password) { + printf(_("You will be prompted for the database Master Password.\n")); + printf(_("It is important that you NOT FORGET this password.\n")); + fflush(stdout); + + pw_size = 1024; + pw_str = malloc(pw_size); + if (pw_str == NULL) { + com_err(progname, ENOMEM, _("while creating new master key")); + exit_status++; return; + } + + retval = krb5_read_password(util_context, KRB5_KDC_MKEY_1, KRB5_KDC_MKEY_2, + pw_str, &pw_size); + if (retval) { + com_err(progname, retval, + _("while reading master key from keyboard")); + exit_status++; return; + } + mkey_password = pw_str; + } + + pwd.data = mkey_password; + pwd.length = strlen(mkey_password); + retval = krb5_principal2salt(util_context, master_princ, &master_salt); + if (retval) { + com_err(progname, retval, _("while calculating master key salt")); + exit_status++; return; + } + + retval = krb5_c_string_to_key(util_context, master_keyblock.enctype, + &pwd, &master_salt, &master_keyblock); + if (retval) { + com_err(progname, retval, + _("while transforming master key from password")); + exit_status++; return; + } + + rblock.key = &master_keyblock; + + seed = make_data(master_keyblock.contents, master_keyblock.length); + + if ((retval = krb5_c_random_seed(util_context, &seed))) { + com_err(progname, retval, + _("while initializing random key generator")); + exit_status++; return; + } + if ((retval = krb5_db_create(util_context, + db5util_db_args))) { + com_err(progname, retval, _("while creating database '%s'"), + global_params.dbname); + exit_status++; return; + } +/* if ((retval = krb5_db_fini(util_context))) { */ +/* com_err(progname, retval, "while closing current database"); */ +/* exit_status++; return; */ +/* } */ +/* if ((retval = krb5_db_open(util_context, db5util_db_args, KRB5_KDB_OPEN_RW))) { */ +/* com_err(progname, retval, "while initializing the database '%s'", */ +/* global_params.dbname); */ +/* exit_status++; return; */ +/* } */ + + if (log_ctx && log_ctx->iproprole) { + retval = ulog_map(util_context, global_params.iprop_logfile, + global_params.iprop_ulogsize); + if (retval) { + com_err(argv[0], retval, _("while creating update log")); + exit_status++; + return; + } + + /* + * We're reinitializing the update log in case one already + * existed, but this should never happen. + */ + retval = ulog_init_header(util_context); + if (retval) { + com_err(argv[0], retval, _("while initializing update log")); + exit_status++; + return; + } + + /* + * Since we're creating a new db we shouldn't worry about + * adding the initial principals since any replica might as + * well do full resyncs from this newly created db. + */ + log_ctx->iproprole = IPROP_NULL; + } + + if ((retval = add_principal(util_context, master_princ, MASTER_KEY, &rblock)) || + (retval = add_principal(util_context, &tgt_princ, TGT_KEY, &rblock))) { + com_err(progname, retval, _("while adding entries to the database")); + exit_status++; return; + } + + + + /* + * Always stash the master key so kadm5_create does not prompt for + * it; delete the file below if it was not requested. DO NOT EXIT + * BEFORE DELETING THE KEYFILE if do_stash is not set. + */ + + /* + * Determine the kvno to use, it must be that used to create the master key + * princ. + */ + if (global_params.mask & KADM5_CONFIG_KVNO) + mkey_kvno = global_params.kvno; /* user specified */ + else + mkey_kvno = 1; /* Default */ + + retval = krb5_db_store_master_key(util_context, + global_params.stash_file, + master_princ, + mkey_kvno, + &master_keyblock, + mkey_password); + if (retval) { + com_err(progname, retval, _("while storing key")); + printf(_("Warning: couldn't stash master key.\n")); + } + /* clean up */ + zapfree(pw_str, pw_size); + free(master_salt.data); + + if (kadm5_create(&global_params)) { + if (!do_stash) unlink(global_params.stash_file); + exit_status++; + return; + } + if (!do_stash) unlink(global_params.stash_file); + + return; +} + +static krb5_error_code +tgt_keysalt_iterate(ksent, ptr) + krb5_key_salt_tuple *ksent; + krb5_pointer ptr; +{ + krb5_context context; + krb5_error_code kret; + struct iterate_args *iargs; + krb5_keyblock key; + krb5_int32 ind; + krb5_data pwd; + + iargs = (struct iterate_args *) ptr; + kret = 0; + + context = iargs->ctx; + + /* + * Convert the master key password into a key for this particular + * encryption system. + */ + pwd.data = mkey_password; + pwd.length = strlen(mkey_password); + kret = krb5_c_random_seed(context, &pwd); + if (kret) + return kret; + + if (!(kret = krb5_dbe_create_key_data(iargs->ctx, iargs->dbentp))) { + ind = iargs->dbentp->n_key_data-1; + if (!(kret = krb5_c_make_random_key(context, ksent->ks_enctype, + &key))) { + kret = krb5_dbe_encrypt_key_data(context, iargs->rblock->key, + &key, NULL, 1, + &iargs->dbentp->key_data[ind]); + krb5_free_keyblock_contents(context, &key); + } + } + + return(kret); +} + +static krb5_error_code +add_principal(context, princ, op, pblock) + krb5_context context; + krb5_principal princ; + enum ap_op op; + struct realm_info *pblock; +{ + krb5_error_code retval; + krb5_db_entry *entry = NULL; + krb5_kvno mkey_kvno; + krb5_timestamp now; + struct iterate_args iargs; + krb5_actkvno_node actkvno; + + entry = calloc(1, sizeof(*entry)); + if (entry == NULL) + return ENOMEM; + + entry->len = KRB5_KDB_V1_BASE_LENGTH; + entry->attributes = pblock->flags; + entry->max_life = pblock->max_life; + entry->max_renewable_life = pblock->max_rlife; + entry->expiration = pblock->expiration; + + if ((retval = krb5_copy_principal(context, princ, &entry->princ))) + goto cleanup; + + if ((retval = krb5_timeofday(context, &now))) + goto cleanup; + + if ((retval = krb5_dbe_update_mod_princ_data(context, entry, + now, &db_create_princ))) + goto cleanup; + + switch (op) { + case MASTER_KEY: + if ((entry->key_data=(krb5_key_data*)malloc(sizeof(krb5_key_data))) + == NULL) + goto cleanup; + memset(entry->key_data, 0, sizeof(krb5_key_data)); + entry->n_key_data = 1; + + if (global_params.mask & KADM5_CONFIG_KVNO) + mkey_kvno = global_params.kvno; /* user specified */ + else + mkey_kvno = 1; /* Default */ + entry->attributes |= KRB5_KDB_DISALLOW_ALL_TIX; + if ((retval = krb5_dbe_encrypt_key_data(context, pblock->key, + &master_keyblock, NULL, + mkey_kvno, entry->key_data))) + goto cleanup; + /* + * There should always be at least one "active" mkey so creating the + * KRB5_TL_ACTKVNO entry now so the initial mkey is active. + */ + actkvno.next = NULL; + actkvno.act_kvno = mkey_kvno; + /* earliest possible time in case system clock is set back */ + actkvno.act_time = 0; + if ((retval = krb5_dbe_update_actkvno(context, entry, &actkvno))) + goto cleanup; + + /* so getprinc shows the right kvno */ + if ((retval = krb5_dbe_update_mkvno(context, entry, mkey_kvno))) + goto cleanup; + + break; + case TGT_KEY: + iargs.ctx = context; + iargs.rblock = pblock; + iargs.dbentp = entry; + /* + * Iterate through the key/salt list, ignoring salt types. + */ + if ((retval = krb5_keysalt_iterate(pblock->kslist, + pblock->nkslist, + 1, + tgt_keysalt_iterate, + (krb5_pointer) &iargs))) + goto cleanup; + break; + case NULL_KEY: + retval = EOPNOTSUPP; + goto cleanup; + default: + break; + } + + entry->mask = (KADM5_KEY_DATA | KADM5_PRINCIPAL | KADM5_ATTRIBUTES | + KADM5_MAX_LIFE | KADM5_MAX_RLIFE | KADM5_TL_DATA | + KADM5_PRINC_EXPIRE_TIME); + entry->attributes |= KRB5_KDB_LOCKDOWN_KEYS; + + retval = krb5_db_put_principal(context, entry); + +cleanup: + krb5_db_free_principal(context, entry); + return retval; +} diff --git a/krb5-1.21.3/src/kadmin/dbutil/kdb5_destroy.c b/krb5-1.21.3/src/kadmin/dbutil/kdb5_destroy.c new file mode 100644 index 00000000..fffce742 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/kdb5_destroy.c @@ -0,0 +1,94 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/dbutil/kdb5_destroy.c - Destroy a KDC database */ +/* + * Copyright 1990, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include +#include "com_err.h" +#include +#include +#include "kdb5_util.h" + +extern int exit_status; +extern krb5_boolean dbactive; +extern kadm5_config_params global_params; + +char *yes = "yes\n"; /* \n to compare against result of + fgets */ + +void +kdb5_destroy(argc, argv) + int argc; + char *argv[]; +{ + extern int optind; + int optchar; + char *dbname; + char buf[5]; + krb5_error_code retval1; + int force = 0; + + dbname = global_params.dbname; + + optind = 1; + while ((optchar = getopt(argc, argv, "f")) != -1) { + switch(optchar) { + case 'f': + force++; + break; + case '?': + default: + usage(); + return; + /*NOTREACHED*/ + } + } + if (!force) { + printf(_("Deleting KDC database stored in '%s', are you sure?\n"), + dbname); + printf(_("(type 'yes' to confirm)? ")); + if (fgets(buf, sizeof(buf), stdin) == NULL) { + exit_status++; return; + } + if (strcmp(buf, yes)) { + exit_status++; return; + } + printf(_("OK, deleting database '%s'...\n"), dbname); + } + + retval1 = krb5_db_destroy(util_context, db5util_db_args); + if (retval1) { + com_err(progname, retval1, _("deleting database '%s'"), dbname); + exit_status++; return; + } + + if (global_params.iprop_enabled) { + (void) unlink(global_params.iprop_logfile); + } + + dbactive = FALSE; + printf(_("** Database '%s' destroyed.\n"), dbname); + return; +} diff --git a/krb5-1.21.3/src/kadmin/dbutil/kdb5_mkey.c b/krb5-1.21.3/src/kadmin/dbutil/kdb5_mkey.c new file mode 100644 index 00000000..aceb0a9b --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/kdb5_mkey.c @@ -0,0 +1,1334 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +#include +#include +#include +#include +#include "kdb5_util.h" +#include + +#if defined(HAVE_COMPILE) && defined(HAVE_STEP) +#define SOLARIS_REGEXPS +#elif defined(HAVE_REGCOMP) && defined(HAVE_REGEXEC) +#define POSIX_REGEXPS +#elif defined(HAVE_RE_COMP) && defined(HAVE_RE_EXEC) +#define BSD_REGEXPS +#else +#error I cannot find any regexp functions +#endif +#ifdef SOLARIS_REGEXPS +#include +#endif +#ifdef POSIX_REGEXPS +#include +#endif + +extern krb5_keyblock master_keyblock; /* current mkey */ +extern krb5_kvno master_kvno; +extern krb5_principal master_princ; +extern krb5_data master_salt; +extern char *mkey_fullname; +extern char *mkey_password; +extern char *progname; +extern int exit_status; +extern kadm5_config_params global_params; +extern krb5_context util_context; +extern time_t get_date(char *); + +static const char * +strdate(krb5_timestamp when) +{ + struct tm *tm; + static char out[40]; + time_t lcltim = ts2tt(when); + + tm = localtime(&lcltim); + if (tm == NULL || + strftime(out, sizeof(out), "%a %b %d %H:%M:%S %Z %Y", tm) == 0) + strlcpy(out, "(error)", sizeof(out)); + return out; +} + +krb5_kvno +get_next_kvno(krb5_context context, krb5_db_entry *entry) +{ + krb5_kvno new_kvno; + + new_kvno = krb5_db_get_key_data_kvno(context, entry->n_key_data, + entry->key_data); + new_kvno++; + /* deal with wrapping */ + if (new_kvno == 0) + new_kvno = 1; /* knvo must not be 0 as this is special value (IGNORE_VNO) */ + + return (new_kvno); +} + +krb5_error_code +add_new_mkey(krb5_context context, krb5_db_entry *master_entry, + krb5_keyblock *new_mkey, krb5_kvno use_mkvno) +{ + krb5_error_code retval = 0; + int old_key_data_count, i; + krb5_kvno new_mkey_kvno; + krb5_key_data tmp_key_data; + krb5_mkey_aux_node *mkey_aux_data_head = NULL, **mkey_aux_data; + krb5_keylist_node *keylist_node; + krb5_keylist_node *master_keylist = krb5_db_mkey_list_alias(context); + + /* do this before modifying master_entry key_data */ + new_mkey_kvno = get_next_kvno(context, master_entry); + /* verify the requested mkvno if not 0 is the one that would be used here. */ + if (use_mkvno != 0 && new_mkey_kvno != use_mkvno) + return (KRB5_KDB_KVNONOMATCH); + + old_key_data_count = master_entry->n_key_data; + + /* alloc enough space to hold new and existing key_data */ + /* + * The encrypted key is malloc'ed by krb5_dbe_encrypt_key_data and + * krb5_key_data key_data_contents is a pointer to this key. Using some + * logic from master_key_convert(). + */ + for (i = 0; i < master_entry->n_key_data; i++) + krb5_free_key_data_contents(context, &master_entry->key_data[i]); + free(master_entry->key_data); + master_entry->key_data = (krb5_key_data *) malloc(sizeof(krb5_key_data) * + (old_key_data_count + 1)); + if (master_entry->key_data == NULL) + return (ENOMEM); + + memset(master_entry->key_data, 0, + sizeof(krb5_key_data) * (old_key_data_count + 1)); + master_entry->n_key_data = old_key_data_count + 1; + + /* Note, mkey does not have salt */ + /* add new mkey encrypted with itself to mkey princ entry */ + if ((retval = krb5_dbe_encrypt_key_data(context, new_mkey, new_mkey, NULL, + (int) new_mkey_kvno, + &master_entry->key_data[0]))) { + return (retval); + } + /* the mvkno should be that of the newest mkey */ + if ((retval = krb5_dbe_update_mkvno(context, master_entry, new_mkey_kvno))) { + krb5_free_key_data_contents(context, &master_entry->key_data[0]); + return (retval); + } + /* + * Need to decrypt old keys with the current mkey which is in the global + * master_keyblock and encrypt those keys with the latest mkey. And while + * the old keys are being decrypted, use those to create the + * KRB5_TL_MKEY_AUX entries which store the latest mkey encrypted by one of + * the older mkeys. + * + * The new mkey is followed by existing keys. + * + * First, set up for creating a krb5_mkey_aux_node list which will be used + * to update the mkey aux data for the mkey princ entry. + */ + mkey_aux_data_head = (krb5_mkey_aux_node *) malloc(sizeof(krb5_mkey_aux_node)); + if (mkey_aux_data_head == NULL) { + retval = ENOMEM; + goto clean_n_exit; + } + memset(mkey_aux_data_head, 0, sizeof(krb5_mkey_aux_node)); + mkey_aux_data = &mkey_aux_data_head; + + for (keylist_node = master_keylist, i = 1; keylist_node != NULL; + keylist_node = keylist_node->next, i++) { + + /* + * Create a list of krb5_mkey_aux_node nodes. One node contains the new + * mkey encrypted by an old mkey and the old mkey's kvno (one node per + * old mkey). + */ + if (*mkey_aux_data == NULL) { + /* *mkey_aux_data points to next field of previous node */ + *mkey_aux_data = (krb5_mkey_aux_node *) malloc(sizeof(krb5_mkey_aux_node)); + if (*mkey_aux_data == NULL) { + retval = ENOMEM; + goto clean_n_exit; + } + memset(*mkey_aux_data, 0, sizeof(krb5_mkey_aux_node)); + } + + memset(&tmp_key_data, 0, sizeof(tmp_key_data)); + /* encrypt the new mkey with the older mkey */ + retval = krb5_dbe_encrypt_key_data(context, &keylist_node->keyblock, + new_mkey, NULL, (int) new_mkey_kvno, + &tmp_key_data); + if (retval) + goto clean_n_exit; + + (*mkey_aux_data)->latest_mkey = tmp_key_data; + (*mkey_aux_data)->mkey_kvno = keylist_node->kvno; + mkey_aux_data = &((*mkey_aux_data)->next); + + /* + * Store old key in master_entry keydata past the new mkey + */ + retval = krb5_dbe_encrypt_key_data(context, new_mkey, + &keylist_node->keyblock, + NULL, (int) keylist_node->kvno, + &master_entry->key_data[i]); + if (retval) + goto clean_n_exit; + } + assert(i == old_key_data_count + 1); + + if ((retval = krb5_dbe_update_mkey_aux(context, master_entry, + mkey_aux_data_head))) { + goto clean_n_exit; + } + master_entry->mask |= KADM5_KEY_DATA | KADM5_TL_DATA; + +clean_n_exit: + krb5_dbe_free_mkey_aux_list(context, mkey_aux_data_head); + return (retval); +} + +void +kdb5_add_mkey(int argc, char *argv[]) +{ + int optchar; + krb5_error_code retval; + char *pw_str = 0; + unsigned int pw_size = 0; + int do_stash = 0; + krb5_data pwd; + krb5_kvno new_mkey_kvno; + krb5_keyblock new_mkeyblock; + krb5_enctype new_master_enctype = ENCTYPE_UNKNOWN; + char *new_mkey_password; + krb5_db_entry *master_entry = NULL; + krb5_timestamp now; + + /* + * The command table entry for this command causes open_db_and_mkey() to be + * called first to open the KDB and get the current mkey. + */ + + memset(&new_mkeyblock, 0, sizeof(new_mkeyblock)); + master_salt.data = NULL; + + while ((optchar = getopt(argc, argv, "e:s")) != -1) { + switch(optchar) { + case 'e': + if (krb5_string_to_enctype(optarg, &new_master_enctype)) { + com_err(progname, EINVAL, _("%s is an invalid enctype"), + optarg); + exit_status++; + return; + } + break; + case 's': + do_stash++; + break; + case '?': + default: + usage(); + return; + } + } + + if (new_master_enctype == ENCTYPE_UNKNOWN) + new_master_enctype = global_params.enctype; + + retval = krb5_db_get_principal(util_context, master_princ, 0, + &master_entry); + if (retval != 0) { + com_err(progname, retval, _("while getting master key principal %s"), + mkey_fullname); + exit_status++; + goto cleanup_return; + } + + printf(_("Creating new master key for master key principal '%s'\n"), + mkey_fullname); + + printf(_("You will be prompted for a new database Master Password.\n")); + printf(_("It is important that you NOT FORGET this password.\n")); + fflush(stdout); + + pw_size = 1024; + pw_str = malloc(pw_size); + if (pw_str == NULL) { + com_err(progname, ENOMEM, _("while creating new master key")); + exit_status++; + goto cleanup_return; + } + + retval = krb5_read_password(util_context, KRB5_KDC_MKEY_1, KRB5_KDC_MKEY_2, + pw_str, &pw_size); + if (retval) { + com_err(progname, retval, + _("while reading new master key from keyboard")); + exit_status++; + goto cleanup_return; + } + new_mkey_password = pw_str; + + pwd.data = new_mkey_password; + pwd.length = strlen(new_mkey_password); + retval = krb5_principal2salt(util_context, master_princ, &master_salt); + if (retval) { + com_err(progname, retval, _("while calculating master key salt")); + exit_status++; + goto cleanup_return; + } + + retval = krb5_c_string_to_key(util_context, new_master_enctype, + &pwd, &master_salt, &new_mkeyblock); + if (retval) { + com_err(progname, retval, + _("while transforming master key from password")); + exit_status++; + goto cleanup_return; + } + + new_mkey_kvno = get_next_kvno(util_context, master_entry); + retval = add_new_mkey(util_context, master_entry, &new_mkeyblock, + new_mkey_kvno); + if (retval) { + com_err(progname, retval, + _("adding new master key to master principal")); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_timeofday(util_context, &now))) { + com_err(progname, retval, _("while getting current time")); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_dbe_update_mod_princ_data(util_context, master_entry, + now, master_princ))) { + com_err(progname, retval, _("while updating the master key principal " + "modification time")); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_db_put_principal(util_context, master_entry))) { + com_err(progname, retval, _("while adding master key entry to the " + "database")); + exit_status++; + goto cleanup_return; + } + + if (do_stash) { + retval = krb5_db_store_master_key(util_context, + global_params.stash_file, + master_princ, + new_mkey_kvno, + &new_mkeyblock, + mkey_password); + if (retval) { + com_err(progname, retval, _("while storing key")); + printf(_("Warning: couldn't stash master key.\n")); + } + } + +cleanup_return: + /* clean up */ + krb5_db_free_principal(util_context, master_entry); + zap((char *)new_mkeyblock.contents, new_mkeyblock.length); + free(new_mkeyblock.contents); + if (pw_str) { + zap(pw_str, pw_size); + free(pw_str); + } + free(master_salt.data); + return; +} + +void +kdb5_use_mkey(int argc, char *argv[]) +{ + krb5_error_code retval; + krb5_kvno use_kvno; + krb5_timestamp now, start_time; + krb5_actkvno_node *actkvno_list = NULL, *new_actkvno = NULL, + *prev_actkvno, *cur_actkvno; + krb5_db_entry *master_entry = NULL; + krb5_keylist_node *keylist_node; + krb5_boolean inserted = FALSE; + krb5_keylist_node *master_keylist = krb5_db_mkey_list_alias(util_context); + + if (argc < 2 || argc > 3) { + /* usage calls exit */ + usage(); + } + + use_kvno = atoi(argv[1]); + if (use_kvno == 0) { + com_err(progname, EINVAL, _("0 is an invalid KVNO value")); + exit_status++; + return; + } else { + /* verify use_kvno is valid */ + for (keylist_node = master_keylist; keylist_node != NULL; + keylist_node = keylist_node->next) { + if (use_kvno == keylist_node->kvno) + break; + } + if (!keylist_node) { + com_err(progname, EINVAL, _("%d is an invalid KVNO value"), + use_kvno); + exit_status++; + return; + } + } + + if ((retval = krb5_timeofday(util_context, &now))) { + com_err(progname, retval, _("while getting current time")); + exit_status++; + return; + } + + if (argc == 3) { + time_t t = get_date(argv[2]); + if (t == -1) { + com_err(progname, 0, _("could not parse date-time string '%s'"), + argv[2]); + exit_status++; + return; + } else + start_time = (krb5_timestamp) t; + } else { + start_time = now; + } + + /* + * Need to: + * + * 1. get mkey princ + * 2. get krb5_actkvno_node list + * 3. add use_kvno to actkvno list (sorted in right spot) + * 4. update mkey princ's tl data + * 5. put mkey princ. + */ + + retval = krb5_db_get_principal(util_context, master_princ, 0, + &master_entry); + if (retval != 0) { + com_err(progname, retval, _("while getting master key principal %s"), + mkey_fullname); + exit_status++; + goto cleanup_return; + } + + retval = krb5_dbe_lookup_actkvno(util_context, master_entry, &actkvno_list); + if (retval != 0) { + com_err(progname, retval, + _("while looking up active version of master key")); + exit_status++; + goto cleanup_return; + } + + /* + * If an entry already exists with the same kvno either delete it or if it's + * the only entry, just set its active time. + */ + for (prev_actkvno = NULL, cur_actkvno = actkvno_list; + cur_actkvno != NULL; + prev_actkvno = cur_actkvno, cur_actkvno = cur_actkvno->next) { + + if (cur_actkvno->act_kvno == use_kvno) { + /* delete it */ + if (prev_actkvno) { + prev_actkvno->next = cur_actkvno->next; + cur_actkvno->next = NULL; + krb5_dbe_free_actkvno_list(util_context, cur_actkvno); + } else { + if (cur_actkvno->next) { + /* delete it from front of list */ + actkvno_list = cur_actkvno->next; + cur_actkvno->next = NULL; + krb5_dbe_free_actkvno_list(util_context, cur_actkvno); + } else { + /* There's only one entry, go ahead and change the time */ + cur_actkvno->act_time = start_time; + inserted = TRUE; + } + } + break; + } + } + + if (!inserted) { + /* alloc enough space to hold new and existing key_data */ + new_actkvno = (krb5_actkvno_node *) malloc(sizeof(krb5_actkvno_node)); + if (new_actkvno == NULL) { + com_err(progname, ENOMEM, _("while adding new master key")); + exit_status++; + goto cleanup_return; + } + memset(new_actkvno, 0, sizeof(krb5_actkvno_node)); + new_actkvno->act_kvno = use_kvno; + new_actkvno->act_time = start_time; + + /* insert new act kvno node */ + + if (actkvno_list == NULL) { + /* new actkvno is the list */ + actkvno_list = new_actkvno; + } else { + for (prev_actkvno = NULL, cur_actkvno = actkvno_list; + cur_actkvno != NULL; + prev_actkvno = cur_actkvno, cur_actkvno = cur_actkvno->next) { + + if (ts_after(cur_actkvno->act_time, new_actkvno->act_time)) { + if (prev_actkvno) { + prev_actkvno->next = new_actkvno; + new_actkvno->next = cur_actkvno; + } else { + new_actkvno->next = actkvno_list; + actkvno_list = new_actkvno; + } + break; + } else if (cur_actkvno->next == NULL) { + /* end of line, just add new node to end of list */ + cur_actkvno->next = new_actkvno; + break; + } + } + } + } + + if (ts_after(actkvno_list->act_time, now)) { + com_err(progname, EINVAL, + _("there must be one master key currently active")); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_dbe_update_actkvno(util_context, master_entry, + actkvno_list))) { + com_err(progname, retval, + _("while updating actkvno data for master principal entry")); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_dbe_update_mod_princ_data(util_context, master_entry, + now, master_princ))) { + com_err(progname, retval, _("while updating the master key principal " + "modification time")); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_db_put_principal(util_context, master_entry))) { + com_err(progname, retval, + _("while adding master key entry to the database")); + exit_status++; + goto cleanup_return; + } + +cleanup_return: + /* clean up */ + krb5_db_free_principal(util_context, master_entry); + krb5_dbe_free_actkvno_list(util_context, actkvno_list); + return; +} + +void +kdb5_list_mkeys(int argc, char *argv[]) +{ + krb5_error_code retval; + char *output_str = NULL, enctype[BUFSIZ]; + krb5_kvno act_kvno; + krb5_timestamp act_time; + krb5_actkvno_node *actkvno_list = NULL, *cur_actkvno; + krb5_db_entry *master_entry = NULL; + krb5_keylist_node *cur_kb_node; + krb5_keyblock *act_mkey; + krb5_keylist_node *master_keylist = krb5_db_mkey_list_alias(util_context); + + if (master_keylist == NULL) { + com_err(progname, 0, _("master keylist not initialized")); + exit_status++; + return; + } + + retval = krb5_db_get_principal(util_context, master_princ, 0, + &master_entry); + if (retval != 0) { + com_err(progname, retval, _("while getting master key principal %s"), + mkey_fullname); + exit_status++; + goto cleanup_return; + } + + retval = krb5_dbe_lookup_actkvno(util_context, master_entry, &actkvno_list); + if (retval != 0) { + com_err(progname, retval, _("while looking up active kvno list")); + exit_status++; + goto cleanup_return; + } + + retval = krb5_dbe_find_act_mkey(util_context, actkvno_list, &act_kvno, + &act_mkey); + if (retval != 0) { + com_err(progname, retval, _("while looking up active master key")); + exit_status++; + goto cleanup_return; + } + + printf("Master keys for Principal: %s\n", mkey_fullname); + + for (cur_kb_node = master_keylist; cur_kb_node != NULL; + cur_kb_node = cur_kb_node->next) { + + if ((retval = krb5_enctype_to_name(cur_kb_node->keyblock.enctype, + FALSE, enctype, sizeof(enctype)))) { + com_err(progname, retval, _("while getting enctype description")); + exit_status++; + goto cleanup_return; + } + + act_time = -1; /* assume actkvno entry not found */ + for (cur_actkvno = actkvno_list; cur_actkvno != NULL; + cur_actkvno = cur_actkvno->next) { + if (cur_actkvno->act_kvno == cur_kb_node->kvno) { + act_time = cur_actkvno->act_time; + break; + } + } + + if (cur_kb_node->kvno == act_kvno) { + /* * indicates kvno is currently active */ + retval = asprintf(&output_str, + _("KVNO: %d, Enctype: %s, Active on: %s *\n"), + cur_kb_node->kvno, enctype, strdate(act_time)); + } else { + if (act_time != -1) { + retval = asprintf(&output_str, + _("KVNO: %d, Enctype: %s, Active on: %s\n"), + cur_kb_node->kvno, enctype, strdate(act_time)); + } else { + retval = asprintf(&output_str, + _("KVNO: %d, Enctype: %s, No activate time " + "set\n"), cur_kb_node->kvno, enctype); + } + } + if (retval == -1) { + com_err(progname, ENOMEM, _("asprintf could not allocate enough " + "memory to hold output")); + exit_status++; + goto cleanup_return; + } + printf("%s", output_str); + free(output_str); + output_str = NULL; + } + +cleanup_return: + /* clean up */ + krb5_db_free_principal(util_context, master_entry); + free(output_str); + krb5_dbe_free_actkvno_list(util_context, actkvno_list); + return; +} + +struct update_enc_mkvno { + unsigned int re_match_count; + unsigned int already_current; + unsigned int updated; + unsigned int dry_run : 1; + unsigned int verbose : 1; +#ifdef SOLARIS_REGEXPS + char *expbuf; +#endif +#ifdef POSIX_REGEXPS + regex_t preg; +#endif +#if !defined(SOLARIS_REGEXPS) && !defined(POSIX_REGEXPS) + unsigned char placeholder; +#endif +}; + +/* XXX Duplicated in libkadm5srv! */ +/* + * Function: glob_to_regexp + * + * Arguments: + * + * glob (r) the shell-style glob (?*[]) to convert + * realm (r) the default realm to append, or NULL + * regexp (w) the ed-style regexp created from glob + * + * Effects: + * + * regexp is filled in with allocated memory contained a regular + * expression to be used with re_comp/compile that matches what the + * shell-style glob would match. If glob does not contain an "@" + * character and realm is not NULL, "@*" is appended to the regexp. + * + * Conversion algorithm: + * + * quoted characters are copied quoted + * ? is converted to . + * * is converted to .* + * active characters are quoted: ^, $, . + * [ and ] are active but supported and have the same meaning, so + * they are copied + * other characters are copied + * regexp is anchored with ^ and $ + */ +static int glob_to_regexp(char *glob, char *realm, char **regexp) +{ + int append_realm; + char *p; + + /* validate the glob */ + if (glob[strlen(glob)-1] == '\\') + return EINVAL; + + /* A character of glob can turn into two in regexp, plus ^ and $ */ + /* and trailing null. If glob has no @, also allocate space for */ + /* the realm. */ + append_realm = (realm != NULL) && (strchr(glob, '@') == NULL); + p = (char *) malloc(strlen(glob)*2+ 3 + (append_realm ? 3 : 0)); + if (p == NULL) + return ENOMEM; + *regexp = p; + + *p++ = '^'; + while (*glob) { + switch (*glob) { + case '?': + *p++ = '.'; + break; + case '*': + *p++ = '.'; + *p++ = '*'; + break; + case '.': + case '^': + case '$': + *p++ = '\\'; + *p++ = *glob; + break; + case '\\': + *p++ = '\\'; + *p++ = *++glob; + break; + default: + *p++ = *glob; + break; + } + glob++; + } + + if (append_realm) { + *p++ = '@'; + *p++ = '.'; + *p++ = '*'; + } + + *p++ = '$'; + *p++ = '\0'; + return 0; +} + +static int +update_princ_encryption_1(void *cb, krb5_db_entry *ent) +{ + struct update_enc_mkvno *p = cb; + char *pname = 0; + krb5_error_code retval; + int match; + krb5_timestamp now; + int result; + krb5_kvno old_mkvno; + + retval = krb5_unparse_name(util_context, ent->princ, &pname); + if (retval) { + com_err(progname, retval, + _("getting string representation of principal name")); + goto fail; + } + + if (krb5_principal_compare(util_context, ent->princ, master_princ)) { + goto skip; + } + +#ifdef SOLARIS_REGEXPS + match = (step(pname, p->expbuf) != 0); +#endif +#ifdef POSIX_REGEXPS + match = (regexec(&p->preg, pname, 0, NULL, 0) == 0); +#endif +#ifdef BSD_REGEXPS + match = (re_exec(pname) != 0); +#endif + if (!match) { + goto skip; + } + p->re_match_count++; + retval = krb5_dbe_get_mkvno(util_context, ent, &old_mkvno); + if (retval) { + com_err(progname, retval, + _("determining master key used for principal '%s'"), pname); + goto fail; + } + /* Line up "skip" and "update" messages for viewing. */ + if (old_mkvno == new_mkvno) { + if (p->dry_run && p->verbose) + printf(_("would skip: %s\n"), pname); + else if (p->verbose) + printf(_("skipping: %s\n"), pname); + p->already_current++; + goto skip; + } + if (p->dry_run) { + if (p->verbose) + printf(_("would update: %s\n"), pname); + p->updated++; + goto skip; + } else if (p->verbose) + printf(_("updating: %s\n"), pname); + retval = master_key_convert (util_context, ent); + if (retval) { + com_err(progname, retval, + _("error re-encrypting key for principal '%s'"), pname); + goto fail; + } + if ((retval = krb5_timeofday(util_context, &now))) { + com_err(progname, retval, _("while getting current time")); + goto fail; + } + + if ((retval = krb5_dbe_update_mod_princ_data(util_context, ent, + now, master_princ))) { + com_err(progname, retval, + _("while updating principal '%s' modification time"), pname); + goto fail; + } + + ent->mask |= KADM5_KEY_DATA; + + if ((retval = krb5_db_put_principal(util_context, ent))) { + com_err(progname, retval, _("while updating principal '%s' key data " + "in the database"), pname); + goto fail; + } + p->updated++; +skip: + result = 0; + goto egress; +fail: + exit_status++; + result = 1; +egress: + if (pname) + krb5_free_unparsed_name(util_context, pname); + return result; +} + +extern int are_you_sure (const char *, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 1, 2))) +#endif + ; + +int +are_you_sure (const char *format, ...) +{ + va_list va; + char ansbuf[100]; + + va_start(va, format); + vprintf(format, va); + va_end(va); + printf(_("\n(type 'yes' to confirm)? ")); + fflush(stdout); + if (fgets(ansbuf, sizeof(ansbuf), stdin) == NULL) + return 0; + if (strcmp(ansbuf, "yes\n")) + return 0; + return 1; +} + +void +kdb5_update_princ_encryption(int argc, char *argv[]) +{ + struct update_enc_mkvno data = { 0 }; + char *name_pattern = NULL; + int force = 0; + int optchar; + krb5_error_code retval; + krb5_actkvno_node *actkvno_list = 0; + krb5_db_entry *master_entry = NULL; +#ifdef BSD_REGEXPS + char *msg; +#endif + char *regexp = NULL; + krb5_keyblock *act_mkey; + krb5_keylist_node *master_keylist = krb5_db_mkey_list_alias(util_context); + krb5_flags iterflags = 0; + + while ((optchar = getopt(argc, argv, "fnv")) != -1) { + switch (optchar) { + case 'f': + force = 1; + break; + case 'n': + data.dry_run = 1; + break; + case 'v': + data.verbose = 1; + break; + case '?': + case ':': + default: + usage(); + } + } + if (argv[optind] != NULL) { + name_pattern = argv[optind]; + if (argv[optind+1] != NULL) + usage(); + } + + if (master_keylist == NULL) { + com_err(progname, 0, _("master keylist not initialized")); + exit_status++; + goto cleanup; + } + + /* The glob_to_regexp code only cares if the "realm" parameter is + NULL or not; the string data is irrelevant. */ + if (name_pattern == NULL) + name_pattern = "*"; + if (glob_to_regexp(name_pattern, "hi", ®exp) != 0) { + com_err(progname, ENOMEM, + _("converting glob pattern '%s' to regular expression"), + name_pattern); + exit_status++; + goto cleanup; + } + + if ( +#ifdef SOLARIS_REGEXPS + ((data.expbuf = compile(regexp, NULL, NULL)) == NULL) +#endif +#ifdef POSIX_REGEXPS + ((regcomp(&data.preg, regexp, REG_NOSUB)) != 0) +#endif +#ifdef BSD_REGEXPS + ((msg = (char *) re_comp(regexp)) != NULL) +#endif + ) { + /* XXX syslog msg or regerr(regerrno) */ + com_err(progname, 0, _("error compiling converted regexp '%s'"), + regexp); + exit_status++; + goto cleanup; + } + + retval = krb5_db_get_principal(util_context, master_princ, 0, + &master_entry); + if (retval != 0) { + com_err(progname, retval, _("while getting master key principal %s"), + mkey_fullname); + exit_status++; + goto cleanup; + } + + retval = krb5_dbe_lookup_actkvno(util_context, master_entry, &actkvno_list); + if (retval != 0) { + com_err(progname, retval, _("while looking up active kvno list")); + exit_status++; + goto cleanup; + } + + retval = krb5_dbe_find_act_mkey(util_context, actkvno_list, &new_mkvno, + &act_mkey); + if (retval) { + com_err(progname, retval, _("while looking up active master key")); + exit_status++; + goto cleanup; + } + new_master_keyblock = *act_mkey; + + if (!force && + !data.dry_run && + !are_you_sure(_("Re-encrypt all keys not using master key vno %u?"), + new_mkvno)) { + printf(_("OK, doing nothing.\n")); + exit_status++; + goto cleanup; + } + if (data.verbose) { + if (data.dry_run) { + printf(_("Principals whose keys WOULD BE re-encrypted to master " + "key vno %u:\n"), new_mkvno); + } else { + printf(_("Principals whose keys are being re-encrypted to master " + "key vno %u if necessary:\n"), new_mkvno); + } + } + + if (!data.dry_run) { + /* Grab a write lock so we don't have to upgrade to a write lock and + * reopen the DB while iterating. */ + iterflags = KRB5_DB_ITER_WRITE; + } + + retval = krb5_db_iterate(util_context, name_pattern, + update_princ_encryption_1, &data, iterflags); + /* If exit_status is set, then update_princ_encryption_1 already + printed a message. */ + if (retval != 0 && exit_status == 0) { + com_err(progname, retval, _("trying to process principal database")); + exit_status++; + } + if (data.dry_run) { + printf(_("%u principals processed: %u would be updated, %u already " + "current\n"), + data.re_match_count, data.updated, data.already_current); + } else { + printf(_("%u principals processed: %u updated, %u already current\n"), + data.re_match_count, data.updated, data.already_current); + } + +cleanup: + krb5_db_free_principal(util_context, master_entry); + free(regexp); +#ifdef POSIX_REGEXPS + regfree(&data.preg); +#endif + memset(&new_master_keyblock, 0, sizeof(new_master_keyblock)); + krb5_dbe_free_actkvno_list(util_context, actkvno_list); +} + +struct kvnos_in_use { + krb5_kvno kvno; + unsigned int use_count; +}; + +struct purge_args { + krb5_context kcontext; + struct kvnos_in_use *kvnos; + unsigned int num_kvnos; +}; + +static krb5_error_code +find_mkvnos_in_use(krb5_pointer ptr, + krb5_db_entry *entry) +{ + krb5_error_code retval; + struct purge_args * args; + unsigned int i; + krb5_kvno mkvno; + + args = (struct purge_args *) ptr; + + retval = krb5_dbe_get_mkvno(args->kcontext, entry, &mkvno); + if (retval) + return (retval); + + for (i = 0; i < args->num_kvnos; i++) { + if (args->kvnos[i].kvno == mkvno) { + /* XXX do I need to worry about use_count wrapping? */ + args->kvnos[i].use_count++; + break; + } + } + return 0; +} + +void +kdb5_purge_mkeys(int argc, char *argv[]) +{ + int optchar; + krb5_error_code retval; + krb5_timestamp now; + krb5_db_entry *master_entry = NULL; + krb5_boolean force = FALSE, dry_run = FALSE, verbose = FALSE; + struct purge_args args; + char buf[5]; + unsigned int i, j, k, num_kvnos_inuse, num_kvnos_purged; + unsigned int old_key_data_count; + krb5_actkvno_node *actkvno_list = NULL, *actkvno_entry, *prev_actkvno_entry; + krb5_mkey_aux_node *mkey_aux_list = NULL, *mkey_aux_entry, *prev_mkey_aux_entry; + krb5_key_data *old_key_data; + + /* + * Verify that the master key list has been initialized before doing + * anything else. + */ + if (krb5_db_mkey_list_alias(util_context) == NULL) { + com_err(progname, KRB5_KDB_DBNOTINITED, + _("master keylist not initialized")); + exit_status++; + return; + } + + memset(&args, 0, sizeof(args)); + + optind = 1; + while ((optchar = getopt(argc, argv, "fnv")) != -1) { + switch(optchar) { + case 'f': + force = TRUE; + break; + case 'n': + dry_run = TRUE; /* mkey princ will not be modified */ + force = TRUE; /* implied */ + break; + case 'v': + verbose = TRUE; + break; + case '?': + default: + usage(); + return; + } + } + + retval = krb5_db_get_principal(util_context, master_princ, 0, + &master_entry); + if (retval != 0) { + com_err(progname, retval, _("while getting master key principal %s"), + mkey_fullname); + exit_status++; + goto cleanup_return; + } + + if (!force) { + printf(_("Will purge all unused master keys stored in the '%s' " + "principal, are you sure?\n"), mkey_fullname); + printf(_("(type 'yes' to confirm)? ")); + if (fgets(buf, sizeof(buf), stdin) == NULL) { + exit_status++; + goto cleanup_return; + } + if (strcmp(buf, "yes\n")) { + exit_status++; + goto cleanup_return; + } + printf(_("OK, purging unused master keys from '%s'...\n"), + mkey_fullname); + } + + /* save the old keydata */ + old_key_data_count = master_entry->n_key_data; + if (old_key_data_count == 1) { + if (verbose) + printf(_("There is only one master key which can not be " + "purged.\n")); + goto cleanup_return; + } + old_key_data = master_entry->key_data; + + args.kvnos = (struct kvnos_in_use *) malloc(sizeof(struct kvnos_in_use) * old_key_data_count); + if (args.kvnos == NULL) { + retval = ENOMEM; + com_err(progname, ENOMEM, _("while allocating args.kvnos")); + exit_status++; + goto cleanup_return; + } + memset(args.kvnos, 0, sizeof(struct kvnos_in_use) * old_key_data_count); + args.num_kvnos = old_key_data_count; + args.kcontext = util_context; + + /* populate the kvnos array with all the current mkvnos */ + for (i = 0; i < old_key_data_count; i++) + args.kvnos[i].kvno = master_entry->key_data[i].key_data_kvno; + + if ((retval = krb5_db_iterate(util_context, + NULL, + find_mkvnos_in_use, + (krb5_pointer) &args, 0))) { + com_err(progname, retval, _("while finding master keys in use")); + exit_status++; + goto cleanup_return; + } + /* + * args.kvnos has been marked with the mkvno's that are currently protecting + * princ entries + */ + if (dry_run) { + printf(_("Would purge the following master key(s) from %s:\n"), + mkey_fullname); + } else { + printf(_("Purging the following master key(s) from %s:\n"), + mkey_fullname); + } + + /* find # of keys still in use or print out verbose info */ + for (i = num_kvnos_inuse = num_kvnos_purged = 0; i < args.num_kvnos; i++) { + if (args.kvnos[i].use_count > 0) { + num_kvnos_inuse++; + } else { + /* this key would be deleted */ + if (args.kvnos[i].kvno == master_kvno) { + com_err(progname, KRB5_KDB_STORED_MKEY_NOTCURRENT, + _("master key stash file needs updating, command " + "aborting")); + exit_status++; + goto cleanup_return; + } + num_kvnos_purged++; + printf(_("KVNO: %d\n"), args.kvnos[i].kvno); + } + } + /* didn't find any keys to purge */ + if (num_kvnos_inuse == args.num_kvnos) { + printf(_("All keys in use, nothing purged.\n")); + goto cleanup_return; + } + if (dry_run) { + /* bail before doing anything else */ + printf(_("%d key(s) would be purged.\n"), num_kvnos_purged); + goto cleanup_return; + } + + retval = krb5_dbe_lookup_actkvno(util_context, master_entry, &actkvno_list); + if (retval != 0) { + com_err(progname, retval, _("while looking up active kvno list")); + exit_status++; + goto cleanup_return; + } + + retval = krb5_dbe_lookup_mkey_aux(util_context, master_entry, &mkey_aux_list); + if (retval != 0) { + com_err(progname, retval, _("while looking up mkey aux data list")); + exit_status++; + goto cleanup_return; + } + + master_entry->key_data = (krb5_key_data *) malloc(sizeof(krb5_key_data) * num_kvnos_inuse); + if (master_entry->key_data == NULL) { + retval = ENOMEM; + com_err(progname, ENOMEM, _("while allocating key_data")); + exit_status++; + goto cleanup_return; + } + memset(master_entry->key_data, 0, sizeof(krb5_key_data) * num_kvnos_inuse); + master_entry->n_key_data = num_kvnos_inuse; /* there's only 1 mkey per kvno */ + + /* + * Assuming that the latest mkey will not be purged because it will always + * be "in use" so this code will not bother with encrypting keys again. + */ + for (i = k = 0; i < old_key_data_count; i++) { + for (j = 0; j < args.num_kvnos; j++) { + if (args.kvnos[j].kvno == (krb5_kvno) old_key_data[i].key_data_kvno) { + if (args.kvnos[j].use_count != 0) { + master_entry->key_data[k++] = old_key_data[i]; + memset(&old_key_data[i], 0, sizeof(old_key_data[i])); + break; + } else { + /* remove unused mkey */ + /* adjust the actkno data */ + for (prev_actkvno_entry = actkvno_entry = actkvno_list; + actkvno_entry != NULL; + actkvno_entry = actkvno_entry->next) { + + if (actkvno_entry->act_kvno == args.kvnos[j].kvno) { + if (actkvno_entry == actkvno_list) { + /* remove from head */ + actkvno_list = actkvno_entry->next; + } else if (actkvno_entry->next == NULL) { + /* remove from tail */ + prev_actkvno_entry->next = NULL; + } else { + /* remove in between */ + prev_actkvno_entry->next = actkvno_entry->next; + } + actkvno_entry->next = NULL; + krb5_dbe_free_actkvno_list(util_context, actkvno_entry); + break; /* deleted entry, no need to loop further */ + } else { + prev_actkvno_entry = actkvno_entry; + } + } + /* adjust the mkey aux data */ + for (prev_mkey_aux_entry = mkey_aux_entry = mkey_aux_list; + mkey_aux_entry != NULL; + mkey_aux_entry = mkey_aux_entry->next) { + + if (mkey_aux_entry->mkey_kvno == args.kvnos[j].kvno) { + if (mkey_aux_entry == mkey_aux_list) { + mkey_aux_list = mkey_aux_entry->next; + } else if (mkey_aux_entry->next == NULL) { + prev_mkey_aux_entry->next = NULL; + } else { + prev_mkey_aux_entry->next = mkey_aux_entry->next; + } + mkey_aux_entry->next = NULL; + krb5_dbe_free_mkey_aux_list(util_context, mkey_aux_entry); + break; /* deleted entry, no need to loop further */ + } else { + prev_mkey_aux_entry = mkey_aux_entry; + } + } + } + } + } + } + assert(k == num_kvnos_inuse); + + /* Free any key data entries we did not consume in the loop above. */ + for (i = 0; i < old_key_data_count; i++) + krb5_dbe_free_key_data_contents(util_context, &old_key_data[i]); + free(old_key_data); + + if ((retval = krb5_dbe_update_actkvno(util_context, master_entry, + actkvno_list))) { + com_err(progname, retval, + _("while updating actkvno data for master principal entry")); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_dbe_update_mkey_aux(util_context, master_entry, + mkey_aux_list))) { + com_err(progname, retval, + _("while updating mkey_aux data for master principal entry")); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_timeofday(util_context, &now))) { + com_err(progname, retval, _("while getting current time")); + exit_status++; + goto cleanup_return; + } + + if ((retval = krb5_dbe_update_mod_princ_data(util_context, master_entry, + now, master_princ))) { + com_err(progname, retval, _("while updating the master key principal " + "modification time")); + exit_status++; + goto cleanup_return; + } + + master_entry->mask |= KADM5_KEY_DATA | KADM5_TL_DATA; + + if ((retval = krb5_db_put_principal(util_context, master_entry))) { + com_err(progname, retval, + _("while adding master key entry to the database")); + exit_status++; + goto cleanup_return; + } + printf(_("%d key(s) purged.\n"), num_kvnos_purged); + +cleanup_return: + krb5_db_free_principal(util_context, master_entry); + free(args.kvnos); + krb5_dbe_free_actkvno_list(util_context, actkvno_list); + krb5_dbe_free_mkey_aux_list(util_context, mkey_aux_list); + return; +} diff --git a/krb5-1.21.3/src/kadmin/dbutil/kdb5_stash.c b/krb5-1.21.3/src/kadmin/dbutil/kdb5_stash.c new file mode 100644 index 00000000..e05944f2 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/kdb5_stash.c @@ -0,0 +1,139 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/dbutil/kdb5_stash.c - Store the master database key in a file */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" +#include "com_err.h" +#include +#include +#include "kdb5_util.h" + +extern krb5_keyblock master_keyblock; +extern krb5_principal master_princ; +extern kadm5_config_params global_params; + +extern int exit_status; +extern int close_policy_db; + +void +kdb5_stash(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + int optchar; + krb5_error_code retval; + char *keyfile = 0; + krb5_kvno mkey_kvno; + + keyfile = global_params.stash_file; + + optind = 1; + while ((optchar = getopt(argc, argv, "f:")) != -1) { + switch(optchar) { + case 'f': + keyfile = optarg; + break; + case '?': + default: + usage(); + return; + } + } + + if (!krb5_c_valid_enctype(master_keyblock.enctype)) { + char tmp[32]; + if (krb5_enctype_to_name(master_keyblock.enctype, FALSE, + tmp, sizeof(tmp))) + com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP, + _("while setting up enctype %d"), master_keyblock.enctype); + else + com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP, "%s", tmp); + exit_status++; return; + } + + if (global_params.mask & KADM5_CONFIG_KVNO) + mkey_kvno = global_params.kvno; /* user specified */ + else + mkey_kvno = IGNORE_VNO; /* use whatever krb5_db_fetch_mkey finds */ + + if (!valid_master_key) { + /* TRUE here means read the keyboard, but only once */ + retval = krb5_db_fetch_mkey(util_context, master_princ, + master_keyblock.enctype, + TRUE, FALSE, (char *) NULL, + &mkey_kvno, + NULL, &master_keyblock); + if (retval) { + com_err(progname, retval, _("while reading master key")); + exit_status++; return; + } + + retval = krb5_db_fetch_mkey_list(util_context, master_princ, + &master_keyblock); + if (retval) { + com_err(progname, retval, _("while getting master key list")); + exit_status++; return; + } + } else { + printf(_("Using existing stashed keys to update stash file.\n")); + } + + retval = krb5_db_store_master_key_list(util_context, keyfile, master_princ, + NULL); + if (retval) { + com_err(progname, retval, _("while storing key")); + exit_status++; return; + } + + exit_status = 0; + return; +} diff --git a/krb5-1.21.3/src/kadmin/dbutil/kdb5_util.c b/krb5-1.21.3/src/kadmin/dbutil/kdb5_util.c new file mode 100644 index 00000000..19a59250 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/kdb5_util.c @@ -0,0 +1,611 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/dbutil/kdb5_util.c - Administer a KDC database */ +/* + * (C) Copyright 1990,1991, 1996, 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +#include +#include +#include +#include +#include "kdb5_util.h" + +/* + * XXX Ick, ick, ick. These global variables shouldn't be global.... + */ +char *mkey_password = 0; + +/* + * I can't figure out any way for this not to be global, given how ss + * works. + */ + +int exit_status = 0; +krb5_context util_context; +kadm5_config_params global_params; + +void usage() +{ + fprintf(stderr, + _("Usage: kdb5_util [-r realm] [-d dbname] " + "[-k mkeytype] [-kv mkeyVNO]\n" + "\t [-M mkeyname] [-m] [-sf stashfilename] " + "[-P password]\n" + "\t [-x db_args]* cmd [cmd_options]\n" + "\tcreate [-s]\n" + "\tdestroy [-f]\n" + "\tstash [-f keyfile]\n" + "\tdump [-b7|-r13|-r18] [-verbose]\n" + "\t [-mkey_convert] [-new_mkey_file mkey_file]\n" + "\t [-rev] [-recurse] [filename [princs...]]\n" + "\tload [-b7|-r13|-r18] [-hash] [-verbose] [-update] " + "filename\n" + "\tark [-e etype_list] principal\n" + "\tadd_mkey [-e etype] [-s]\n" + "\tuse_mkey kvno [time]\n" + "\tlist_mkeys\n")); + /* avoid a string length compiler warning */ + fprintf(stderr, + _("\tupdate_princ_encryption [-f] [-n] [-v] [princ-pattern]\n" + "\tpurge_mkeys [-f] [-n] [-v]\n" + "\ttabdump [-H] [-c] [-e] [-n] [-o outfile] dumptype\n" + "\nwhere,\n\t[-x db_args]* - any number of database specific " + "arguments.\n" + "\t\t\tLook at each database documentation for supported " + "arguments\n")); + exit(1); +} + +krb5_keyblock master_keyblock; +krb5_kvno master_kvno; /* fetched */ +extern krb5_principal master_princ; +char *mkey_fullname; +krb5_db_entry *master_entry = NULL; +int valid_master_key = 0; + +char *progname; +krb5_boolean manual_mkey = FALSE; +krb5_boolean dbactive = FALSE; + +static int open_db_and_mkey(void); + +static void add_random_key(int, char **); + +typedef void (*cmd_func)(int, char **); + +struct _cmd_table { + char *name; + cmd_func func; + int opendb; +} cmd_table[] = { + {"create", kdb5_create, 0}, + {"destroy", kdb5_destroy, 1}, /* 1 opens the kdb */ + {"stash", kdb5_stash, 1}, + {"dump", dump_db, 1}, + {"load", load_db, 0}, + {"ark", add_random_key, 1}, + {"add_mkey", kdb5_add_mkey, 1}, + {"use_mkey", kdb5_use_mkey, 1}, + {"list_mkeys", kdb5_list_mkeys, 1}, + {"update_princ_encryption", kdb5_update_princ_encryption, 1}, + {"purge_mkeys", kdb5_purge_mkeys, 1}, + {"tabdump", tabdump, 1}, + {NULL, NULL, 0}, +}; + +static struct _cmd_table *cmd_lookup(name) + char *name; +{ + struct _cmd_table *cmd = cmd_table; + while (cmd->name) { + if (strcmp(cmd->name, name) == 0) + return cmd; + else + cmd++; + } + + return NULL; +} + +#define ARG_VAL (--argc > 0 ? (koptarg = *(++argv)) : (char *)(usage(), NULL)) + +char **db5util_db_args = NULL; +int db5util_db_args_size = 0; + +static void extended_com_err_fn (const char *myprog, errcode_t code, + const char *fmt, va_list args) +{ + const char *emsg; + if (code) { + emsg = krb5_get_error_message (util_context, code); + fprintf (stderr, "%s: %s ", myprog, emsg); + krb5_free_error_message (util_context, emsg); + } else { + fprintf (stderr, "%s: ", myprog); + } + vfprintf (stderr, fmt, args); + fprintf (stderr, "\n"); +} + +int add_db_arg(char *arg) +{ + char **temp; + db5util_db_args_size++; + temp = realloc(db5util_db_args, + sizeof(char *) * (db5util_db_args_size + 1)); + if (temp == NULL) + return 0; + db5util_db_args = temp; + db5util_db_args[db5util_db_args_size-1] = arg; + db5util_db_args[db5util_db_args_size] = NULL; + return 1; +} + +int main(argc, argv) + int argc; + char *argv[]; +{ + struct _cmd_table *cmd = NULL; + char *koptarg, **cmd_argv; + char *db_name_tmp = NULL; + int cmd_argc; + krb5_error_code retval; + + setlocale(LC_ALL, ""); + set_com_err_hook(extended_com_err_fn); + + /* + * Ensure that "progname" is set before calling com_err. + */ + progname = (strrchr(argv[0], '/') ? + strrchr(argv[0], '/') + 1 : argv[0]); + + retval = kadm5_init_krb5_context(&util_context); + if (retval) { + com_err (progname, retval, _("while initializing Kerberos code")); + exit(1); + } + + cmd_argv = (char **) malloc(sizeof(char *)*argc); + if (cmd_argv == NULL) { + com_err(progname, ENOMEM, _("while creating sub-command arguments")); + exit(1); + } + memset(cmd_argv, 0, sizeof(char *)*argc); + cmd_argc = 0; + + argv++; argc--; + while (*argv) { + if (strcmp(*argv, "-P") == 0 && ARG_VAL) { + mkey_password = koptarg; + manual_mkey = TRUE; + } else if (strcmp(*argv, "-d") == 0 && ARG_VAL) { + global_params.dbname = koptarg; + global_params.mask |= KADM5_CONFIG_DBNAME; + + if (asprintf(&db_name_tmp, "dbname=%s", global_params.dbname) < 0) + { + com_err(progname, ENOMEM, + _("while parsing command arguments")); + exit(1); + } + + if (!add_db_arg(db_name_tmp)) { + com_err(progname, ENOMEM, + _("while parsing command arguments\n")); + exit(1); + } + + } else if (strcmp(*argv, "-x") == 0 && ARG_VAL) { + if (!add_db_arg(koptarg)) { + com_err(progname, ENOMEM, + _("while parsing command arguments\n")); + exit(1); + } + + } else if (strcmp(*argv, "-r") == 0 && ARG_VAL) { + global_params.realm = koptarg; + global_params.mask |= KADM5_CONFIG_REALM; + /* not sure this is really necessary */ + if ((retval = krb5_set_default_realm(util_context, + global_params.realm))) { + com_err(progname, retval, + _("while setting default realm name")); + exit(1); + } + } else if (strcmp(*argv, "-k") == 0 && ARG_VAL) { + if (krb5_string_to_enctype(koptarg, &global_params.enctype)) { + com_err(progname, EINVAL, _(": %s is an invalid enctype"), + koptarg); + exit(1); + } else + global_params.mask |= KADM5_CONFIG_ENCTYPE; + } else if (strcmp(*argv, "-kv") == 0 && ARG_VAL) { + global_params.kvno = (krb5_kvno) atoi(koptarg); + if (global_params.kvno == IGNORE_VNO) { + com_err(progname, EINVAL, _(": %s is an invalid mkeyVNO"), + koptarg); + exit(1); + } else + global_params.mask |= KADM5_CONFIG_KVNO; + } else if (strcmp(*argv, "-M") == 0 && ARG_VAL) { + global_params.mkey_name = koptarg; + global_params.mask |= KADM5_CONFIG_MKEY_NAME; + } else if (strcmp(*argv, "-sf") == 0 && ARG_VAL) { + global_params.stash_file = koptarg; + global_params.mask |= KADM5_CONFIG_STASH_FILE; + } else if (strcmp(*argv, "-m") == 0) { + manual_mkey = TRUE; + global_params.mkey_from_kbd = 1; + global_params.mask |= KADM5_CONFIG_MKEY_FROM_KBD; + } else { + cmd_argv[cmd_argc++] = *argv; + } + argv++; argc--; + } + + if (cmd_argv[0] == NULL) + usage(); + cmd = cmd_lookup(cmd_argv[0]); + if (cmd == NULL) + usage(); + + if( !util_context->default_realm ) + { + char *temp = NULL; + retval = krb5_get_default_realm(util_context, &temp); + if( retval ) + { + com_err(progname, retval, _("while getting default realm")); + exit(1); + } + krb5_free_default_realm(util_context, temp); + } + + retval = kadm5_get_config_params(util_context, 1, + &global_params, &global_params); + if (retval) { + com_err(progname, retval, + _("while retrieving configuration parameters")); + exit(1); + } + + /* + * Dump creates files which should not be world-readable. It is + * easiest to do a single umask call here. + */ + (void) umask(077); + + master_keyblock.enctype = global_params.enctype; + if ((master_keyblock.enctype != ENCTYPE_UNKNOWN) && + (!krb5_c_valid_enctype(master_keyblock.enctype))) { + com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP, + "while setting up enctype %d", master_keyblock.enctype); + } + + if (cmd->opendb && open_db_and_mkey()) + return exit_status; + + if (global_params.iprop_enabled == TRUE) + ulog_set_role(util_context, IPROP_PRIMARY); + else + ulog_set_role(util_context, IPROP_NULL); + + (*cmd->func)(cmd_argc, cmd_argv); + + if( db_name_tmp ) + free( db_name_tmp ); + + if( db5util_db_args ) + free(db5util_db_args); + + quit(); + kadm5_free_config_params(util_context, &global_params); + krb5_free_context(util_context); + free(cmd_argv); + return exit_status; +} + +/* + * open_db_and_mkey: Opens the KDC and policy database, and sets the + * global master_* variables. Sets dbactive to TRUE if the databases + * are opened, and valid_master_key to 1 if the global master + * variables are set properly. Returns 0 on success, and 1 on + * failure, but it is not considered a failure if the master key + * cannot be fetched (the master key stash file may not exist when the + * program is run). + */ +static int open_db_and_mkey() +{ + krb5_error_code retval; + krb5_data scratch, pwd, seed; + + dbactive = FALSE; + valid_master_key = 0; + + if ((retval = krb5_db_open(util_context, db5util_db_args, + KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) { + com_err(progname, retval, _("while initializing database")); + exit_status++; + return(1); + } + + /* assemble & parse the master key name */ + + if ((retval = krb5_db_setup_mkey_name(util_context, + global_params.mkey_name, + global_params.realm, + &mkey_fullname, &master_princ))) { + com_err(progname, retval, _("while setting up master key name")); + exit_status++; + return(1); + } + if ((retval = krb5_db_get_principal(util_context, master_princ, 0, + &master_entry))) { + com_err(progname, retval, _("while retrieving master entry")); + exit_status++; + (void) krb5_db_fini(util_context); + return(1); + } + + if (global_params.mask & KADM5_CONFIG_KVNO) + master_kvno = global_params.kvno; /* user specified */ + else + master_kvno = IGNORE_VNO; + + /* the databases are now open, and the master principal exists */ + dbactive = TRUE; + + if (mkey_password) { + pwd.data = mkey_password; + pwd.length = strlen(mkey_password); + retval = krb5_principal2salt(util_context, master_princ, &scratch); + if (retval) { + com_err(progname, retval, _("while calculated master key salt")); + exit_status++; + return(1); + } + + /* If no encryption type is set, use the default */ + if (master_keyblock.enctype == ENCTYPE_UNKNOWN) + master_keyblock.enctype = DEFAULT_KDC_ENCTYPE; + if (!krb5_c_valid_enctype(master_keyblock.enctype)) + com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP, + "while setting up enctype %d", + master_keyblock.enctype); + + retval = krb5_c_string_to_key(util_context, master_keyblock.enctype, + &pwd, &scratch, &master_keyblock); + if (retval) { + com_err(progname, retval, + _("while transforming master key from password")); + exit_status++; + return(1); + } + free(scratch.data); + mkey_password = 0; + + } else { + if ((retval = krb5_db_fetch_mkey(util_context, master_princ, + master_keyblock.enctype, + manual_mkey, FALSE, + global_params.stash_file, + &master_kvno, + 0, &master_keyblock))) { + com_err(progname, retval, _("while reading master key")); + com_err(progname, 0, _("Warning: proceeding without master key")); + exit_status++; + return(0); + } + } + + if ((retval = krb5_db_fetch_mkey_list(util_context, master_princ, + &master_keyblock))) { + com_err(progname, retval, "while getting master key list"); + com_err(progname, 0, "Warning: proceeding without master key list"); + exit_status++; + return(0); + } + + seed.length = master_keyblock.length; + seed.data = (char *) master_keyblock.contents; + + if ((retval = krb5_c_random_seed(util_context, &seed))) { + com_err(progname, retval, _("while seeding random number generator")); + exit_status++; + memset(master_keyblock.contents, 0, master_keyblock.length); + krb5_free_keyblock_contents(util_context, &master_keyblock); + return(1); + } + + if (global_params.iprop_enabled) { + if (ulog_map(util_context, global_params.iprop_logfile, + global_params.iprop_ulogsize)) { + fprintf(stderr, _("%s: Could not map log\n"), progname); + exit_status++; + return(1); + } + } + + valid_master_key = 1; + dbactive = TRUE; + return 0; +} + +#ifdef HAVE_GETCWD +#undef getwd +#endif + +int +quit() +{ + krb5_error_code retval; + static krb5_boolean finished = 0; + + if (finished) + return 0; + ulog_fini(util_context); + retval = krb5_db_fini(util_context); + zapfree(master_keyblock.contents, master_keyblock.length); + krb5_free_principal(util_context, master_princ); + finished = TRUE; + if (retval && retval != KRB5_KDB_DBNOTINITED) { + com_err(progname, retval, _("while closing database")); + exit_status++; + return 1; + } + return 0; +} + +static void +add_random_key(argc, argv) + int argc; + char **argv; +{ + krb5_error_code ret; + krb5_principal princ; + krb5_db_entry *dbent; + krb5_timestamp now; + + krb5_key_salt_tuple *keysalts = NULL; + krb5_int32 num_keysalts = 0; + + int free_keysalts; + char *me = progname; + char *ks_str = NULL; + char *pr_str; + krb5_keyblock *tmp_mkey; + + if (argc < 2) + usage(); + for (argv++, argc--; *argv; argv++, argc--) { + if (!strcmp(*argv, "-e")) { + argv++; argc--; + ks_str = *argv; + continue; + } else + break; + } + if (argc < 1) + usage(); + pr_str = *argv; + ret = krb5_parse_name(util_context, pr_str, &princ); + if (ret) { + com_err(me, ret, _("while parsing principal name %s"), pr_str); + exit_status++; + return; + } + ret = krb5_db_get_principal(util_context, princ, 0, &dbent); + if (ret) { + com_err(me, ret, _("while fetching principal %s"), pr_str); + exit_status++; + return; + } + ret = krb5_string_to_keysalts(ks_str, + NULL, NULL, 0, + &keysalts, + &num_keysalts); + if (ret) { + com_err(me, ret, _("while parsing keysalts %s"), ks_str); + exit_status++; + return; + } + if (!num_keysalts || keysalts == NULL) { + num_keysalts = global_params.num_keysalts; + keysalts = global_params.keysalts; + free_keysalts = 0; + } else + free_keysalts = 1; + + /* Find the mkey used to protect the existing keys */ + ret = krb5_dbe_find_mkey(util_context, dbent, &tmp_mkey); + if (ret) { + com_err(me, ret, _("while finding mkey")); + krb5_db_free_principal(util_context, dbent); + exit_status++; + return; + } + + ret = krb5_dbe_ark(util_context, tmp_mkey, keysalts, num_keysalts, dbent); + if (free_keysalts) + free(keysalts); + if (ret) { + com_err(me, ret, "while randomizing principal %s", pr_str); + krb5_db_free_principal(util_context, dbent); + exit_status++; + return; + } + dbent->attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE; + ret = krb5_timeofday(util_context, &now); + if (ret) { + com_err(me, ret, _("while getting time")); + krb5_db_free_principal(util_context, dbent); + exit_status++; + return; + } + ret = krb5_dbe_update_last_pwd_change(util_context, dbent, now); + if (ret) { + com_err(me, ret, _("while setting changetime")); + krb5_db_free_principal(util_context, dbent); + exit_status++; + return; + } + ret = krb5_db_put_principal(util_context, dbent); + krb5_db_free_principal(util_context, dbent); + if (ret) { + com_err(me, ret, _("while saving principal %s"), pr_str); + exit_status++; + return; + } + printf(_("%s changed\n"), pr_str); +} diff --git a/krb5-1.21.3/src/kadmin/dbutil/kdb5_util.h b/krb5-1.21.3/src/kadmin/dbutil/kdb5_util.h new file mode 100644 index 00000000..69e186d4 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/kdb5_util.h @@ -0,0 +1,99 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/dbutil/kdb5_util.h */ +/* + * Copyright 1992, 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include + +#define REALM_SEP '@' +#define REALM_SEP_STR "@" + +extern char *progname; +#ifndef V4_DECLARES_STATIC +extern krb5_keyblock master_keyblock; +extern krb5_principal master_princ; +#endif +extern krb5_boolean dbactive; +extern int exit_status; +extern krb5_context util_context; +extern kadm5_config_params global_params; +extern int valid_master_key; +extern krb5_db_entry master_db; +extern char **db5util_db_args; +extern int db5util_db_args_size; +extern krb5_kvno new_mkvno; +extern krb5_keyblock new_master_keyblock; +extern int add_db_arg(char *arg); + +extern void usage(void); + +extern void add_key +(char const *, char const *, + krb5_const_principal, const krb5_keyblock *, + krb5_kvno, krb5_keysalt *); +extern int set_dbname_help +(char *, char *); + +extern char *kdb5_util_Init (int, char **); + +extern int quit (void); + +extern int check_for_match +(char *, int, krb5_db_entry *, int, int); + +extern void parse_token +(char *, int *, int *, char *); + +extern int create_db_entry (krb5_principal, krb5_db_entry *); + +extern int kadm5_create_magic_princs (kadm5_config_params *params, + krb5_context context); + +extern int process_ov_principal (krb5_context kcontext, const char *fname, + FILE *filep, krb5_boolean verbose, + int *linenop); + +extern void load_db (int argc, char **argv); +extern void dump_db (int argc, char **argv); +extern void kdb5_create (int argc, char **argv); +extern void kdb5_destroy (int argc, char **argv); +extern void kdb5_stash (int argc, char **argv); +extern void kdb5_add_mkey (int argc, char **argv); +extern void kdb5_use_mkey (int argc, char **argv); +extern void kdb5_list_mkeys (int argc, char **argv); +extern void kdb5_update_princ_encryption (int argc, char **argv); +extern void tabdump (int argc, char **argv); + +extern krb5_error_code master_key_convert(krb5_context context, + krb5_db_entry *db_entry); +extern void kdb5_purge_mkeys (int argc, char **argv); + +extern int kadm5_create (kadm5_config_params *params); + +extern krb5_error_code add_new_mkey(krb5_context, krb5_db_entry *, + krb5_keyblock *, krb5_kvno); + +extern krb5_kvno get_next_kvno(krb5_context, krb5_db_entry *); + +void usage (void); diff --git a/krb5-1.21.3/src/kadmin/dbutil/nstrtok.h b/krb5-1.21.3/src/kadmin/dbutil/nstrtok.h new file mode 100644 index 00000000..3ee8f634 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/nstrtok.h @@ -0,0 +1,3 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* Prototype for nstrtok */ +char *nstrtok(char *, const char *delim); diff --git a/krb5-1.21.3/src/kadmin/dbutil/ovload.c b/krb5-1.21.3/src/kadmin/dbutil/ovload.c new file mode 100644 index 00000000..15a5ab30 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/ovload.c @@ -0,0 +1,205 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include +#include + +#include +#include +#include +#include "import_err.h" +#include "kdb5_util.h" +#include "nstrtok.h" + +#define LINESIZE 32768 /* XXX */ + +static int parse_pw_hist_ent(current, hist) + char *current; + osa_pw_hist_ent *hist; +{ + int tmp, i, j, ret; + char *cp; + + ret = 0; + hist->n_key_data = 1; + + hist->key_data = (krb5_key_data *) malloc(hist->n_key_data * + sizeof(krb5_key_data)); + if (hist->key_data == NULL) + return ENOMEM; + memset(hist->key_data, 0, sizeof(krb5_key_data)*hist->n_key_data); + + for (i = 0; i < hist->n_key_data; i++) { + krb5_key_data *key_data = &hist->key_data[i]; + + key_data->key_data_ver = 1; + + if((cp = nstrtok((char *) NULL, "\t")) == NULL) { + com_err(NULL, IMPORT_BAD_RECORD, "%s", current); + ret = IMPORT_FAILED; + goto done; + } + key_data->key_data_type[0] = atoi(cp); + + if((cp = nstrtok((char *) NULL, "\t")) == NULL) { + com_err(NULL, IMPORT_BAD_RECORD, "%s", current); + ret = IMPORT_FAILED; + goto done; + } + key_data->key_data_length[0] = atoi(cp); + + if((cp = nstrtok((char *) NULL, "\t")) == NULL) { + com_err(NULL, IMPORT_BAD_RECORD, "%s", current); + ret = IMPORT_FAILED; + goto done; + } + if(!(key_data->key_data_contents[0] = + (krb5_octet *) malloc(key_data->key_data_length[0]+1))) { + ret = ENOMEM; + goto done; + } + for(j = 0; j < key_data->key_data_length[0]; j++) { + if(sscanf(cp, "%02x", &tmp) != 1) { + com_err(NULL, IMPORT_BAD_RECORD, "%s", current); + ret = IMPORT_FAILED; + goto done; + } + key_data->key_data_contents[0][j] = tmp; + cp = strchr(cp, ' ') + 1; + } + } + +done: + return ret; +} + +/* + * Function: parse_principal + * + * Purpose: parse principal line in db dump file + * + * Arguments: + * 0 on success, error code on failure + * + * Requires: + * principal database to be opened. + * nstrtok(3) to have a valid buffer in memory. + * + * Effects: + * [effects] + * + * Modifies: + * [modifies] + * + */ +int process_ov_principal(kcontext, fname, filep, verbose, linenop) + krb5_context kcontext; + const char *fname; + FILE *filep; + krb5_boolean verbose; + int *linenop; +{ + XDR xdrs; + osa_princ_ent_t rec; + krb5_error_code ret; + krb5_tl_data tl_data; + krb5_principal princ; + krb5_db_entry *kdb = NULL; + char *current = 0; + char *cp; + unsigned int x; + char line[LINESIZE]; + + if (fgets(line, LINESIZE, filep) == (char *) NULL) { + return IMPORT_BAD_FILE; + } + if((cp = nstrtok(line, "\t")) == NULL) + return IMPORT_BAD_FILE; + if((rec = (osa_princ_ent_t) malloc(sizeof(osa_princ_ent_rec))) == NULL) + return ENOMEM; + memset(rec, 0, sizeof(osa_princ_ent_rec)); + if((ret = krb5_parse_name(kcontext, cp, &princ))) + goto done; + krb5_unparse_name(kcontext, princ, ¤t); + if((cp = nstrtok((char *) NULL, "\t")) == NULL) { + com_err(NULL, IMPORT_BAD_RECORD, "%s", current); + ret = IMPORT_FAILED; + goto done; + } else { + if(strcmp(cp, "")) { + if((rec->policy = strdup(cp)) == NULL) { + ret = ENOMEM; + goto done; + } + } else rec->policy = NULL; + } + if((cp = nstrtok((char *) NULL, "\t")) == NULL) { + com_err(NULL, IMPORT_BAD_RECORD, "%s", current); + ret = IMPORT_FAILED; + goto done; + } + rec->aux_attributes = strtol(cp, (char **)NULL, 16); + if((cp = nstrtok((char *) NULL, "\t")) == NULL) { + com_err(NULL, IMPORT_BAD_RECORD, "%s", current); + ret = IMPORT_FAILED; + goto done; + } + rec->old_key_len = atoi(cp); + if((cp = nstrtok((char *) NULL, "\t")) == NULL) { + com_err(NULL, IMPORT_BAD_RECORD, "%s", current); + ret = IMPORT_FAILED; + goto done; + } + rec->old_key_next = atoi(cp); + if((cp = nstrtok((char *) NULL, "\t")) == NULL) { + com_err(NULL, IMPORT_BAD_RECORD, "%s", current); + ret = IMPORT_FAILED; + goto done; + } + rec->admin_history_kvno = atoi(cp); + if (! rec->old_key_len) { + rec->old_keys = NULL; + } else { + if(!(rec->old_keys = (osa_pw_hist_ent *) + malloc(sizeof(osa_pw_hist_ent) * rec->old_key_len))) { + ret = ENOMEM; + goto done; + } + memset(rec->old_keys,0, + sizeof(osa_pw_hist_ent) * rec->old_key_len); + for(x = 0; x < rec->old_key_len; x++) + parse_pw_hist_ent(current, &rec->old_keys[x]); + } + + xdralloc_create(&xdrs, XDR_ENCODE); + if (! xdr_osa_princ_ent_rec(&xdrs, rec)) { + xdr_destroy(&xdrs); + ret = KADM5_XDR_FAILURE; + goto done; + } + + tl_data.tl_data_type = KRB5_TL_KADM_DATA; + tl_data.tl_data_length = xdr_getpos(&xdrs); + tl_data.tl_data_contents = (krb5_octet *) xdralloc_getdata(&xdrs); + + ret = krb5_db_get_principal(kcontext, princ, 0, &kdb); + if (ret) + goto done; + + ret = krb5_dbe_update_tl_data(kcontext, kdb, &tl_data); + if (ret) + goto done; + + ret = krb5_db_put_principal(kcontext, kdb); + if (ret) + goto done; + + xdr_destroy(&xdrs); + + (*linenop)++; + +done: + free(current); + krb5_free_principal(kcontext, princ); + osa_free_princ_ent(rec); + krb5_db_free_principal(kcontext, kdb); + return ret; +} diff --git a/krb5-1.21.3/src/kadmin/dbutil/strtok.c b/krb5-1.21.3/src/kadmin/dbutil/strtok.c new file mode 100644 index 00000000..dee466ae --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/strtok.c @@ -0,0 +1,105 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + */ + +/* + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that: (1) source distributions retain this entire copyright + * notice and comment, and (2) distributions including binaries display + * the following acknowledgement: ``This product includes software + * developed by the University of California, Berkeley and its contributors'' + * in the documentation or other materials provided with the distribution + * and in all advertising materials mentioning features or use of this + * software. Neither the name of the University 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include +#include +#include "nstrtok.h" + +/* + * Function: nstrtok + * + * Purpose: the same as strtok ... just different. does not deal with + * multiple tokens in row. + * + * Arguments: + * s (input) string to scan + * delim (input) list of delimiters + * string or null on error. + * + * Requires: + * nuttin + * + * Effects: + * sets last to string + * + * Modifies: + * last + * + */ + +char * +nstrtok(s, delim) + char *s; + const char *delim; +{ + const char *spanp; + int c, sc; + char *tok; + static char *last; + + + if (s == NULL && (s = last) == NULL) + return (NULL); + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ +#ifdef OLD +cont: + c = *s++; + for (spanp = delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + last = NULL; + return (NULL); + } + tok = s - 1; +#else + tok = s; +#endif + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + last = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/krb5-1.21.3/src/kadmin/dbutil/t_tdumputil.c b/krb5-1.21.3/src/kadmin/dbutil/t_tdumputil.c new file mode 100644 index 00000000..a9ed0e54 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/t_tdumputil.c @@ -0,0 +1,115 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/t_tdumputil.c - test tdumputil.c functions */ +/* + * Copyright (C) 2015 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. + */ + +#include +#include +#include + +#include "tdumputil.h" + +static char *argv0; + +static void +usage(void) +{ + fprintf(stderr, + "usage: %s: [-T rectype] [-c] nfields {fieldnames} {fields}\n", + argv0); + exit(1); +} + +int +main(int argc, char **argv) +{ + int ch, csv = 0, i, nf; + char **a, *rectype = NULL; + struct rechandle *h; + + argv0 = argv[0]; + while ((ch = getopt(argc, argv, "T:c")) != -1) { + switch (ch) { + case 'T': + rectype = optarg; + break; + case 'c': + csv = 1; + break; + default: + usage(); + break; + } + } + argc -= optind; + argv += optind; + + if (csv) + h = rechandle_csv(stdout, rectype); + else + h = rechandle_tabsep(stdout, rectype); + if (h == NULL) + exit(1); + + if (*argv == NULL) + usage(); + nf = atoi(*argv); + argc--; + argv++; + a = calloc(nf + 1, sizeof(*a)); + if (a == NULL) + exit(1); + + for (i = 0; argv[i] != NULL && i < nf; i++) + a[i] = argv[i]; + if (i != nf) + usage(); + argv += nf; + a[nf] = NULL; + + if (rectype == NULL && writeheader(h, a) < 0) + exit(1); + free(a); + + while (*argv != NULL) { + if (startrec(h) < 0) + exit(1); + for (i = 0; argv[i] != NULL && i < nf; i++) { + if (writefield(h, "%s", argv[i]) < 0) + exit(1); + } + if (i != nf) + usage(); + argv += nf; + if (endrec(h) < 0) + exit(1); + } + exit(0); +} diff --git a/krb5-1.21.3/src/kadmin/dbutil/t_tdumputil.py b/krb5-1.21.3/src/kadmin/dbutil/t_tdumputil.py new file mode 100755 index 00000000..47b2aa7a --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/t_tdumputil.py @@ -0,0 +1,30 @@ +from k5test import * +from subprocess import * + +realm = K5Realm(create_kdb=False) + +def compare(s, expected, msg): + if s == expected: + return + print('expected:', repr(expected)) + print('got:', repr(s)) + fail(msg) + +out = realm.run(['./t_tdumputil', '2', 'field1', 'field2', + 'value1', 'value2']) +expected = 'field1\tfield2\nvalue1\tvalue2\n' +compare(out, expected, 'tab-separated values') + +out = realm.run(['./t_tdumputil', '-c', '2', 'field1', 'field2', + 'space value', 'comma,value', + 'quote"value', 'quotes""value']) +expected = 'field1,field2\nspace value,"comma,value"\n' \ + '"quote""value","quotes""""value"\n' +compare(out, expected, 'comma-separated values') + +out = realm.run(['./t_tdumputil', '-T', 'rectype', '2', 'field1', 'field2', + 'value1', 'value2']) +expected = 'rectype\tvalue1\tvalue2\n' +compare(out, expected, 'rectype prefixed') + +success('tabdump utilities') diff --git a/krb5-1.21.3/src/kadmin/dbutil/tabdump.c b/krb5-1.21.3/src/kadmin/dbutil/tabdump.c new file mode 100644 index 00000000..da55c2d7 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/tabdump.c @@ -0,0 +1,658 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/tabdump.c - reporting-friendly tabular KDB dumps */ +/* + * Copyright (C) 2015 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. + */ + +#include +#include "k5-platform.h" /* for asprintf */ +#include "k5-hex.h" + +#include +#include +#include +#include + +#include +#include + +#include "adm_proto.h" +#include "kdb5_util.h" +#include "tdumputil.h" + +struct tdopts { + int csv; /* 1 for CSV, 0 for tab-separated */ + int emptyhex_empty; /* print empty hex strings as "" not "-1" */ + int numeric; /* numeric instead of symbolic output */ + int omitheader; /* omit field headers */ + int writerectype; /* write record type prefix */ + char *fname; /* output file name */ +}; + +struct rec_args; + +typedef int (tdump_princ_fn)(struct rec_args *, const char *, krb5_db_entry *); +typedef int (tdump_policy_fn)(struct rec_args *, const char *, + kadm5_policy_ent_t); + +/* Descriptor for a tabdump record type */ +struct tdtype { + const char *rectype; + char * const *fieldnames; + tdump_princ_fn *princ_fn; + tdump_policy_fn *policy_fn; +}; + +static tdump_princ_fn keydata; +static tdump_princ_fn keyinfo; +static tdump_princ_fn princ_flags; +static tdump_princ_fn princ_lockout; +static tdump_princ_fn princ_meta; +static tdump_princ_fn princ_stringattrs; +static tdump_princ_fn princ_tktpolicy; + +static char * const keydata_fields[] = { + "name", "keyindex", "kvno", "enctype", "key", "salttype", "salt", NULL +}; +static char * const keyinfo_fields[] = { + "name", "keyindex", "kvno", "enctype", "salttype", "salt", NULL +}; +static char * const princ_flags_fields[] = { + "name", "flag", "value", NULL +}; +static char * const princ_lockout_fields[] = { + "name", "last_success", "last_failed", "fail_count", NULL +}; +static char * const princ_meta_fields[] = { + "name", "modby", "modtime", "lastpwd", "policy", "mkvno", "hist_kvno", NULL +}; +static char * const princ_stringattrs_fields[] = { + "name", "key", "value", NULL +}; +static char * const princ_tktpolicy_fields[] = { + "name", "expiration", "pw_expiration", "max_life", "max_renew_life", NULL +}; + +/* Lookup table for tabdump record types */ +static struct tdtype tdtypes[] = { + {"keydata", keydata_fields, keydata, NULL}, + {"keyinfo", keyinfo_fields, keyinfo, NULL}, + {"princ_flags", princ_flags_fields, princ_flags, NULL}, + {"princ_lockout", princ_lockout_fields, princ_lockout, NULL}, + {"princ_meta", princ_meta_fields, princ_meta, NULL}, + {"princ_stringattrs", princ_stringattrs_fields, princ_stringattrs, NULL}, + {"princ_tktpolicy", princ_tktpolicy_fields, princ_tktpolicy, NULL}, +}; +#define NTDTYPES (sizeof(tdtypes)/sizeof(tdtypes[0])) + +/* State to pass to KDB iterator */ +struct rec_args { + FILE *f; + struct tdtype *tdtype; + struct rechandle *rh; + struct tdopts *opts; +}; + +/* Decode the KADM_DATA from a DB entry.*/ +static int +get_adb(krb5_db_entry *dbe, osa_princ_ent_rec *adb) +{ + XDR xdrs; + int success; + krb5_tl_data tl_data; + krb5_error_code ret; + + memset(adb, 0, sizeof(*adb)); + tl_data.tl_data_type = KRB5_TL_KADM_DATA; + ret = krb5_dbe_lookup_tl_data(util_context, dbe, &tl_data); + if (ret != 0 || tl_data.tl_data_length == 0) + return 0; + xdrmem_create(&xdrs, (caddr_t)tl_data.tl_data_contents, + tl_data.tl_data_length, XDR_DECODE); + success = xdr_osa_princ_ent_rec(&xdrs, adb); + xdr_destroy(&xdrs); + return success; +} + +/* Write a date field as an ISO 8601 UTC date/time representation. */ +static int +write_date_iso(struct rec_args *args, krb5_timestamp when) +{ + char buf[64]; + time_t t; + struct tm *tm = NULL; + struct rechandle *h = args->rh; + + t = ts2tt(when); + tm = gmtime(&t); + if (tm == NULL) { + errno = EINVAL; + return -1; + } + if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", tm) == 0) { + errno = EINVAL; + return -1; + } + if (writefield(h, "%s", buf) < 0) + return -1; + return 0; +} + +/* Write a date field, optionally as a decimal POSIX timestamp. */ +static int +write_date(struct rec_args *args, krb5_timestamp when) +{ + struct tdopts *opts = args->opts; + struct rechandle *h = args->rh; + + if (opts->numeric) + return writefield(h, "%d", when); + + return write_date_iso(args, when); +} + +/* Write an enctype field, optionally as decimal. */ +static krb5_error_code +write_enctype(struct rec_args *args, krb5_int16 etype) +{ + char buf[256]; + krb5_error_code ret; + struct rechandle *h = args->rh; + struct tdopts *opts = args->opts; + + if (!opts->numeric) { + ret = krb5_enctype_to_name(etype, 0, buf, sizeof(buf)); + if (ret == 0) { + if (writefield(h, "%s", buf) < 0) + return errno; + return ret; + } + } + /* decimal if requested, or if conversion failed */ + if (writefield(h, "%d", etype) < 0) + return errno; + return 0; +} + +/* Write a salttype field, optionally as decimal. */ +static krb5_error_code +write_salttype(struct rec_args *args, krb5_int16 salttype) +{ + char buf[256]; + krb5_error_code ret; + struct rechandle *h = args->rh; + struct tdopts *opts = args->opts; + + if (!opts->numeric) { + ret = krb5_salttype_to_string(salttype, buf, sizeof(buf)); + if (ret == 0) { + if (writefield(h, "%s", buf) < 0) + return errno; + return ret; + } + } + /* decimal if requested, or if conversion failed */ + if (writefield(h, "%d", salttype) < 0) + return errno; + return 0; +} + +/* + * Write a field of bytes from krb5_data as a hexadecimal string. Write empty + * strings as "-1" unless requested. + */ +static int +write_data(struct rec_args *args, krb5_data *data) +{ + int ret; + char *hex; + struct rechandle *h = args->rh; + struct tdopts *opts = args->opts; + + if (data->length == 0 && !opts->emptyhex_empty) { + if (writefield(h, "-1") < 0) + return -1; + return 0; + } + + ret = k5_hex_encode(data->data, data->length, FALSE, &hex); + if (ret) { + errno = ret; + return -1; + } + + ret = writefield(h, "%s", hex); + free(hex); + return ret; +} + +/* Write a single record of a keydata/keyinfo key set. */ +static krb5_error_code +keyinfo_rec(struct rec_args *args, const char *name, int i, krb5_key_data *kd, + int dumpkeys) +{ + int ret; + krb5_data data; + struct rechandle *h = args->rh; + + if (startrec(h) < 0) + return errno; + if (writefield(h, "%s", name) < 0) + return errno; + if (writefield(h, "%d", i) < 0) + return errno; + if (writefield(h, "%d", kd->key_data_kvno) < 0) + return errno; + if (write_enctype(args, kd->key_data_type[0]) < 0) + return errno; + if (dumpkeys) { + data.length = kd->key_data_length[0]; + data.data = (void *)kd->key_data_contents[0]; + if (write_data(args, &data) < 0) + return errno; + } + ret = write_salttype(args, kd->key_data_type[1]); + if (ret) + return ret; + data.length = kd->key_data_length[1]; + data.data = (void *)kd->key_data_contents[1]; + if (write_data(args, &data) < 0) + return errno; + if (endrec(h) < 0) + return errno; + return 0; +} + +/* Write out a principal's key set, optionally including actual key data. */ +static krb5_error_code +keyinfo_common(struct rec_args *args, const char *name, krb5_db_entry *entry, + int dumpkeys) +{ + krb5_error_code ret; + krb5_key_data kd; + int i; + + for (i = 0; i < entry->n_key_data; i++) { + kd = entry->key_data[i]; + /* missing salt data -> normal salt */ + if (kd.key_data_ver == 1) { + kd.key_data_ver = 2; + kd.key_data_type[1] = KRB5_KDB_SALTTYPE_NORMAL; + kd.key_data_length[1] = 0; + kd.key_data_contents[1] = NULL; + } + ret = keyinfo_rec(args, name, i, &kd, dumpkeys); + if (ret) + return ret; + } + return 0; +} + +/* Write a principal's key data. */ +static krb5_error_code +keydata(struct rec_args *args, const char *name, krb5_db_entry *dbe) +{ + return keyinfo_common(args, name, dbe, 1); +} + +/* Write a principal's key info (suppressing actual key data). */ +static krb5_error_code +keyinfo(struct rec_args *args, const char *name, krb5_db_entry *dbe) +{ + return keyinfo_common(args, name, dbe, 0); +} + +/* Write a record corresponding to a single principal flag setting. */ +static krb5_error_code +princflag_rec(struct rechandle *h, const char *name, const char *flagname, + int set) +{ + if (startrec(h) < 0) + return errno; + if (writefield(h, "%s", name) < 0) + return errno; + if (writefield(h, "%s", flagname) < 0) + return errno; + if (writefield(h, "%d", set) < 0) + return errno; + if (endrec(h) < 0) + return errno; + return 0; +} + +/* Write a principal's flag settings. */ +static krb5_error_code +princ_flags(struct rec_args *args, const char *name, krb5_db_entry *dbe) +{ + int i; + char *s = NULL; + krb5_flags flags = dbe->attributes; + krb5_error_code ret; + struct tdopts *opts = args->opts; + struct rechandle *h = args->rh; + + for (i = 0; i < 32; i++) { + if (opts->numeric) { + if (asprintf(&s, "0x%08lx", 1UL << i) == -1) + return ENOMEM; + } else { + ret = krb5_flagnum_to_string(i, &s); + if (ret) + return ret; + /* Don't print unknown flags if they're not set and numeric output + * isn't requested. */ + if (!(flags & (1UL << i)) && strncmp(s, "0x", 2) == 0) { + free(s); + continue; + } + } + ret = princflag_rec(h, name, s, ((flags & (1UL << i)) != 0)); + free(s); + if (ret) + return ret; + } + return 0; +} + +/* Write a principal's lockout data. */ +static krb5_error_code +princ_lockout(struct rec_args *args, const char *name, krb5_db_entry *dbe) +{ + struct rechandle *h = args->rh; + + if (startrec(h) < 0) + return errno; + if (writefield(h, "%s", name) < 0) + return errno; + if (write_date(args, dbe->last_success) < 0) + return errno; + if (write_date(args, dbe->last_failed) < 0) + return errno; + if (writefield(h, "%d", dbe->fail_auth_count) < 0) + return errno; + if (endrec(h) < 0) + return errno; + return 0; +} + +/* Write a principal's metadata. */ +static krb5_error_code +princ_meta(struct rec_args *args, const char *name, krb5_db_entry *dbe) +{ + int got_adb = 0; + char *modby; + krb5_kvno mkvno; + const char *policy; + krb5_principal mod_princ = NULL; + krb5_timestamp mod_time, last_pwd; + krb5_error_code ret; + osa_princ_ent_rec adb; + struct rechandle *h = args->rh; + + memset(&adb, 0, sizeof(adb)); + if (startrec(h) < 0) + return errno; + if (writefield(h, "%s", name) < 0) + return errno; + + ret = krb5_dbe_lookup_last_pwd_change(util_context, dbe, &last_pwd); + if (ret) + return ret; + ret = krb5_dbe_get_mkvno(util_context, dbe, &mkvno); + if (ret) + return ret; + + ret = krb5_dbe_lookup_mod_princ_data(util_context, dbe, &mod_time, + &mod_princ); + if (ret) + return ret; + ret = krb5_unparse_name(util_context, mod_princ, &modby); + krb5_free_principal(util_context, mod_princ); + if (ret) + return ret; + ret = writefield(h, "%s", modby); + krb5_free_unparsed_name(util_context, modby); + if (ret < 0) + return errno; + + if (write_date(args, mod_time) < 0) + return errno; + if (write_date(args, last_pwd) < 0) + return errno; + + got_adb = get_adb(dbe, &adb); + if (got_adb && adb.policy != NULL) + policy = adb.policy; + else + policy = ""; + ret = writefield(h, "%s", policy); + if (ret < 0) { + ret = errno; + goto cleanup; + } + if (writefield(h, "%d", mkvno) < 0) { + ret = errno; + goto cleanup; + } + if (writefield(h, "%d", adb.admin_history_kvno) < 0) { + ret = errno; + goto cleanup; + } + if (endrec(h) < 0) + ret = errno; + else + ret = 0; + +cleanup: + kdb_free_entry(NULL, NULL, &adb); + return ret; +} + +/* Write a principal's string attributes. */ +static krb5_error_code +princ_stringattrs(struct rec_args *args, const char *name, krb5_db_entry *dbe) +{ + int i, nattrs; + krb5_error_code ret; + krb5_string_attr *attrs; + struct rechandle *h = args->rh; + + ret = krb5_dbe_get_strings(util_context, dbe, &attrs, &nattrs); + if (ret) + return ret; + for (i = 0; i < nattrs; i++) { + if (startrec(h) < 0) { + ret = errno; + goto cleanup; + } + if (writefield(h, "%s", name) < 0) { + ret = errno; + goto cleanup; + } + if (writefield(h, "%s", attrs[i].key) < 0) { + ret = errno; + goto cleanup; + } + if (writefield(h, "%s", attrs[i].value) < 0) { + ret = errno; + goto cleanup; + } + if (endrec(h) < 0) { + ret = errno; + goto cleanup; + } + } +cleanup: + krb5_dbe_free_strings(util_context, attrs, nattrs); + return ret; +} + +/* Write a principal's ticket policy. */ +static krb5_error_code +princ_tktpolicy(struct rec_args *args, const char *name, krb5_db_entry *dbe) +{ + struct rechandle *h = args->rh; + + if (startrec(h) < 0) + return errno; + if (writefield(h, "%s", name) < 0) + return errno; + if (write_date(args, dbe->expiration) < 0) + return errno; + if (write_date(args, dbe->pw_expiration) < 0) + return errno; + if (writefield(h, "%d", dbe->max_life) < 0) + return errno; + if (writefield(h, "%d", dbe->max_renewable_life) < 0) + return errno; + if (endrec(h) < 0) + return errno; + return 0; +} + +/* Iterator function for krb5_db_iterate() */ +static krb5_error_code +tditer(void *ptr, krb5_db_entry *entry) +{ + krb5_error_code ret; + struct rec_args *args = ptr; + char *name; + + ret = krb5_unparse_name(util_context, entry->princ, &name); + if (ret) { + com_err(progname, ret, _("while unparsing principal name")); + return ret; + } + ret = args->tdtype->princ_fn(args, name, entry); + krb5_free_unparsed_name(util_context, name); + if (ret) + return ret; + return 0; +} + +/* Set up state structure for the iterator. */ +static krb5_error_code +setup_args(struct rec_args *args, struct tdtype *tdtype, + struct tdopts *opts) +{ + FILE *f = NULL; + const char *rectype = NULL; + struct rechandle *rh; + + args->tdtype = tdtype; + args->opts = opts; + if (opts->fname != NULL && strcmp(opts->fname, "-") != 0) { + f = fopen(opts->fname, "w"); + if (f == NULL) { + com_err(progname, errno, _("opening %s for writing"), + opts->fname); + return errno; + } + args->f = f; + } else { + f = stdout; + args->f = NULL; + } + if (opts->writerectype) + rectype = tdtype->rectype; + if (opts->csv) + rh = rechandle_csv(f, rectype); + else + rh = rechandle_tabsep(f, rectype); + if (rh == NULL) + return ENOMEM; + args->rh = rh; + if (!opts->omitheader && writeheader(rh, tdtype->fieldnames) < 0) + return errno; + return 0; +} + +/* Clean up the state structure. */ +static void +cleanup_args(struct rec_args *args) +{ + rechandle_free(args->rh); + if (args->f != NULL) + fclose(args->f); +} + +void +tabdump(int argc, char **argv) +{ + int ch; + size_t i; + const char *rectype; + struct rec_args args; + struct tdopts opts; + krb5_error_code ret; + + memset(&opts, 0, sizeof(opts)); + memset(&args, 0, sizeof(args)); + optind = 1; + while ((ch = getopt(argc, argv, "Hceno:")) != -1) { + switch (ch) { + case 'H': + opts.omitheader = 1; + break; + case 'c': + opts.csv = 1; + break; + case 'e': + opts.emptyhex_empty = 1; + break; + case 'n': + opts.numeric = 1; + break; + case 'o': + opts.fname = optarg; + break; + case '?': + default: + usage(); + break; + } + } + if (argc - optind < 1) + usage(); + rectype = argv[optind]; + for (i = 0; i < NTDTYPES; i++) { + if (strcmp(rectype, tdtypes[i].rectype) == 0) { + setup_args(&args, &tdtypes[i], &opts); + break; + } + } + if (i >= NTDTYPES) + usage(); + ret = krb5_db_iterate(util_context, NULL, tditer, &args, 0); + cleanup_args(&args); + if (ret) { + com_err(progname, ret, _("performing tabular dump")); + exit_status++; + } +} diff --git a/krb5-1.21.3/src/kadmin/dbutil/tdumputil.c b/krb5-1.21.3/src/kadmin/dbutil/tdumputil.c new file mode 100644 index 00000000..076cfa97 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/tdumputil.c @@ -0,0 +1,266 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/tdumputil.c - utilities for tab-separated, etc. files */ +/* + * Copyright (C) 2015 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. + */ + +#include "k5-int.h" +#include "k5-platform.h" /* for vasprintf */ +#include +#include +#include +#include +#include + +#include "tdumputil.h" + +/* + * Structure describing flavor of a tabular output format. + * + * fieldsep is the field separator + * + * recordsep is the record/line separator + * + * quotechar begins and ends a quoted field. If an instance of quotechar + * occurs within a quoted field value, it is doubled. + * + * Values are only quoted if they contain fieldsep, recordsep, or quotechar. + */ +struct flavor { + int fieldsep; /* field separator */ + int recordsep; /* record separator */ + int quotechar; /* quote character */ +}; + +struct rechandle { + FILE *fh; + const char *rectype; + int do_sep; + struct flavor flavor; +}; + +static const struct flavor tabsep = { + '\t', /* fieldsep */ + '\n', /* recordsep */ + '\0' /* quotechar */ +}; + +static const struct flavor csv = { + ',', /* fieldsep */ + '\n', /* recordsep */ + '"' /* quotechar */ +}; + +/* + * Double any quote characters present in a quoted field. + */ +static char * +qquote(struct flavor *fl, const char *s) +{ + const char *sp; + struct k5buf buf; + + k5_buf_init_dynamic(&buf); + for (sp = s; *sp != '\0'; sp++) { + k5_buf_add_len(&buf, sp, 1); + if (*sp == fl->quotechar) + k5_buf_add_len(&buf, sp, 1); + } + return k5_buf_cstring(&buf); +} + +/* + * Write an optionally quoted field. + */ +static int +writequoted(struct rechandle *h, const char *fmt, va_list ap) +{ + int doquote = 0, ret; + char *s = NULL, *qs = NULL; + struct flavor fl = h->flavor; + + assert(fl.quotechar != '\0'); + ret = vasprintf(&s, fmt, ap); + if (ret < 0) + return ret; + if (strchr(s, fl.fieldsep) != NULL) + doquote = 1; + if (strchr(s, fl.recordsep) != NULL) + doquote = 1; + if (strchr(s, fl.quotechar) != NULL) + doquote = 1; + + if (doquote) { + qs = qquote(&fl, s); + if (qs == NULL) { + ret = -1; + goto cleanup; + } + ret = fprintf(h->fh, "%c%s%c", fl.quotechar, qs, fl.quotechar); + } else { + ret = fprintf(h->fh, "%s", s); + } +cleanup: + free(s); + free(qs); + return ret; +} + +/* + * Return a rechandle with the requested file handle and rectype. + * + * rectype must be a valid pointer for the entire lifetime of the rechandle (or + * null) + */ +static struct rechandle * +rechandle_common(FILE *fh, const char *rectype) +{ + struct rechandle *h = calloc(1, sizeof(*h)); + + if (h == NULL) + return NULL; + h->fh = fh; + h->rectype = rectype; + h->do_sep = 0; + return h; +} + +/* + * Return a rechandle for tab-separated output. + */ +struct rechandle * +rechandle_tabsep(FILE *fh, const char *rectype) +{ + struct rechandle *h = rechandle_common(fh, rectype); + + if (h == NULL) + return NULL; + h->flavor = tabsep; + return h; +} + +/* + * Return a rechandle for CSV output. + */ +struct rechandle * +rechandle_csv(FILE *fh, const char *rectype) +{ + struct rechandle *h = rechandle_common(fh, rectype); + + if (h == NULL) + return NULL; + h->flavor = csv; + return h; +} + +/* + * Free a rechandle. + */ +void +rechandle_free(struct rechandle *h) +{ + free(h); +} + +/* + * Start a record. This includes writing a record type prefix (rectype) if + * specified. + */ +int +startrec(struct rechandle *h) +{ + if (h->rectype == NULL) { + h->do_sep = 0; + return 0; + } + h->do_sep = 1; + return fputs(h->rectype, h->fh); +} + +/* + * Write a single field of a record. This includes writing a separator + * character, if appropriate. + */ +int +writefield(struct rechandle *h, const char *fmt, ...) +{ + int ret = 0; + va_list ap; + struct flavor fl = h->flavor; + + if (h->do_sep) { + ret = fputc(fl.fieldsep, h->fh); + if (ret < 0) + return ret; + } + h->do_sep = 1; + va_start(ap, fmt); + if (fl.quotechar == '\0') + ret = vfprintf(h->fh, fmt, ap); + else + ret = writequoted(h, fmt, ap); + va_end(ap); + return ret; +} + +/* + * Finish a record (line). + */ +int +endrec(struct rechandle *h) +{ + int ret = 0; + struct flavor fl = h->flavor; + + ret = fputc(fl.recordsep, h->fh); + h->do_sep = 0; + return ret; +} + +/* + * Write a header line if h->rectype is null. (If rectype is set, it will be + * prefixed to output lines, most likely in a mixed record type output file, so + * it doesn't make sense to output a header line in that case.) + */ +int +writeheader(struct rechandle *h, char * const *a) +{ + int ret = 0; + char * const *p; + + if (h->rectype != NULL) + return 0; + for (p = a; *p != NULL; p++) { + ret = writefield(h, "%s", *p); + if (ret < 0) + return ret; + } + ret = endrec(h); + return ret; +} diff --git a/krb5-1.21.3/src/kadmin/dbutil/tdumputil.h b/krb5-1.21.3/src/kadmin/dbutil/tdumputil.h new file mode 100644 index 00000000..b7437310 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/dbutil/tdumputil.h @@ -0,0 +1,51 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/tdumputil.h - utilities for tab-separated, etc. files */ +/* + * Copyright (C) 2015 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. + */ + +#ifndef TDUMPUTIL_H +#define TDUMPUTIL_H + +struct rechandle; + +struct rechandle *rechandle_csv(FILE *, const char *); +struct rechandle *rechandle_tabsep(FILE *, const char *); +void rechandle_free(struct rechandle *); + +int startrec(struct rechandle *); +int writefield(struct rechandle *, const char *, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; +int endrec(struct rechandle *); +int writeheader(struct rechandle *, char * const *); + +#endif /* TDUMPUTIL_H */ diff --git a/krb5-1.21.3/src/kadmin/deps b/krb5-1.21.3/src/kadmin/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/kadmin/kdbkeys/Makefile.in b/krb5-1.21.3/src/kadmin/kdbkeys/Makefile.in new file mode 100644 index 00000000..996febd8 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/kdbkeys/Makefile.in @@ -0,0 +1,16 @@ +mydir=. +BUILDTOP=$(REL)..$(S).. + +PROG = kdbkeys +OBJS = kdbkeys.o + +all: $(PROG) + +$(PROG): $(OBJS) + $(CC) $(LDFLAGS) -o $(PROG) $(OBJS) $(LIBS) + +install: + $(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG) + +clean: + $(RM) $(PROG) $(OBJS) diff --git a/krb5-1.21.3/src/kadmin/kdbkeys/do-test.pl b/krb5-1.21.3/src/kadmin/kdbkeys/do-test.pl new file mode 100755 index 00000000..7acb425f --- /dev/null +++ b/krb5-1.21.3/src/kadmin/kdbkeys/do-test.pl @@ -0,0 +1,56 @@ +#!/afs/athena/contrib/perl/p + +# +# $Id$ +# + +$debug = $ARGV[1] || $ENV{'VERBOSE_TEST'}; + +die "Need a number.\n" if !$ARGV[0]; + +die "Neither \$TOP nor \$TESTDIR is set.\n" + if (! ($ENV{'TOP'} || $ENV{'TESTDIR'})); + +$TESTDIR = ($ENV{'TESTDIR'} || "$ENV{'TOP'}/testing"); +$INITDB = ($ENV{'INITDB'} || "$TESTDIR/scripts/init_db"); + +for ($i=0; $i<$ARGV[0]; $i++) { + print "Trial $i\n" if $debug; + + system("$INITDB > /dev/null 2>&1") && + die "Error in init_db\n"; + + open(KEYS,"../dbutil/kdb5_util -R dump_db|") || + die "Couldn't run kdb5_util: $!\n"; + chop($header = ); + if ($header ne "kdb5_util load_dump version 4") { + die "Cannot operate on dump version \"$header\"; version 4 required."; + } + while() { + next if ((!/^princ.*kadmin\//) && (!/^princ.*krbtgt/)); + + print if $debug > 1; + + split; + + $princ = $_[6]; + $nkeys = $_[4]; + $ntls = $_[3]; + print "$princ: nkeys $nkeys, ntls $ntls\n" if $debug; + for ($j = 15 + $ntls*3; $nkeys > 0; $nkeys--) { + $ver = $_[$j++]; + $kvno = $_[$j++]; + $keytype = $_[$j++]; + $keylen = $_[$j++]; + $keydata = $_[$j++]; + $j += 3 if ($ver > 1); + + print "$princ, ver $ver, kvno $kvno, type $keytype, len $keylen, " + . "data $keydata\n" if $debug; + + die "Duplicated key $princ = $keydata\n" if + $keys{$keydata}++; + } + } + close(KEYS); +} diff --git a/krb5-1.21.3/src/kadmin/ktutil/Makefile.in b/krb5-1.21.3/src/kadmin/ktutil/Makefile.in new file mode 100644 index 00000000..f8f9b411 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/ktutil/Makefile.in @@ -0,0 +1,30 @@ +mydir=kadmin$(S)ktutil +BUILDTOP=$(REL)..$(S).. + +OBJS= ktutil.o \ + ktutil_ct.o \ + ktutil_funcs.o + +SRCS= $(srcdir)/ktutil.c \ + ktutil_ct.c \ + $(srcdir)/ktutil_funcs.c + +all: ktutil + +ktutil: ktutil.o $(OBJS) $(SS_DEPLIB) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o ktutil $(OBJS) $(SS_LIB) $(KRB5_BASE_LIBS) + +install: + $(INSTALL_PROGRAM) ktutil ${DESTDIR}$(CLIENT_BINDIR)/ktutil + +generate-files-mac: ktutil_ct.c + +# needed until we run makedepend +ktutil_ct.c: ktutil_ct.ct + +ktutil_ct.o: ktutil_ct.c + +clean: + $(RM) ktutil_ct.c ktutil + +depend: ktutil_ct.c diff --git a/krb5-1.21.3/src/kadmin/ktutil/deps b/krb5-1.21.3/src/kadmin/ktutil/deps new file mode 100644 index 00000000..5863e63c --- /dev/null +++ b/krb5-1.21.3/src/kadmin/ktutil/deps @@ -0,0 +1,27 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)ktutil.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SS_DEPS) \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h ktutil.c ktutil.h +$(OUTPRE)ktutil_ct.$(OBJEXT): $(COM_ERR_DEPS) $(SS_DEPS) \ + ktutil_ct.c +$(OUTPRE)ktutil_funcs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-hex.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ktutil.h ktutil_funcs.c diff --git a/krb5-1.21.3/src/kadmin/ktutil/ktutil.c b/krb5-1.21.3/src/kadmin/ktutil/ktutil.c new file mode 100644 index 00000000..92d7023a --- /dev/null +++ b/krb5-1.21.3/src/kadmin/ktutil/ktutil.c @@ -0,0 +1,280 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/ktutil/ktutil.c - SS user interface for ktutil */ +/* + * Copyright 1995, 1996, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "ktutil.h" +#include +#include +#include "adm_proto.h" +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif + +extern ss_request_table ktutil_cmds; +krb5_context kcontext; +krb5_kt_list ktlist = NULL; + +int main(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code retval; + int sci_idx; + + setlocale(LC_ALL, ""); + retval = krb5_init_context(&kcontext); + if (retval) { + com_err(argv[0], retval, _("while initializing krb5")); + exit(1); + } + sci_idx = ss_create_invocation("ktutil", "5.0", (char *)NULL, + &ktutil_cmds, &retval); + if (retval) { + ss_perror(sci_idx, retval, _("creating invocation")); + exit(1); + } + retval = ss_listen(sci_idx); + ktutil_free_kt_list(kcontext, ktlist); + exit(0); +} + +void ktutil_clear_list(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code retval; + + if (argc != 1) { + fprintf(stderr, _("%s: invalid arguments\n"), argv[0]); + return; + } + retval = ktutil_free_kt_list(kcontext, ktlist); + if (retval) + com_err(argv[0], retval, _("while freeing ktlist")); + ktlist = NULL; +} + +void ktutil_read_v5(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code retval; + + if (argc != 2) { + fprintf(stderr, _("%s: must specify keytab to read\n"), argv[0]); + return; + } + retval = ktutil_read_keytab(kcontext, argv[1], &ktlist); + if (retval) + com_err(argv[0], retval, _("while reading keytab \"%s\""), argv[1]); +} + +void ktutil_read_v4(argc, argv) + int argc; + char *argv[]; +{ + fprintf(stderr, _("%s: reading srvtabs is no longer supported\n"), + argv[0]); +} + +void ktutil_write_v5(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code retval; + + if (argc != 2) { + fprintf(stderr, _("%s: must specify keytab to write\n"), argv[0]); + return; + } + retval = ktutil_write_keytab(kcontext, ktlist, argv[1]); + if (retval) + com_err(argv[0], retval, _("while writing keytab \"%s\""), argv[1]); +} + +void ktutil_write_v4(argc, argv) + int argc; + char *argv[]; +{ + fprintf(stderr, _("%s: writing srvtabs is no longer supported\n"), + argv[0]); +} + +void ktutil_add_entry(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code retval; + char *princ = NULL; + char *enctype = NULL; + krb5_kvno kvno = 0; + int use_pass = 0, use_key = 0, use_kvno = 0, fetch = 0, i; + char *salt = NULL; + + for (i = 1; i < argc; i++) { + if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-p", 2)) { + princ = argv[++i]; + continue; + } + if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-k", 2)) { + kvno = (krb5_kvno) atoi(argv[++i]); + use_kvno++; + continue; + } + if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-e", 2)) { + enctype = argv[++i]; + continue; + } + if ((strlen(argv[i]) == 9) && !strncmp(argv[i], "-password", 9)) { + use_pass++; + continue; + } + if ((strlen(argv[i]) == 4) && !strncmp(argv[i], "-key", 4)) { + use_key++; + continue; + } + if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-s", 2)) { + salt = argv[++i]; + continue; + } + if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-f", 2)) + fetch++; + } + + if (princ == NULL || use_pass + use_key != 1 || !use_kvno || + (fetch && salt != NULL)) { + fprintf(stderr, _("usage: %s (-key | -password) -p principal " + "-k kvno [-e enctype] [-f|-s salt]\n"), argv[0]); + return; + } + if (!fetch && enctype == NULL) { + fprintf(stderr, _("enctype must be specified if not using -f\n")); + return; + } + + retval = ktutil_add(kcontext, &ktlist, princ, fetch, kvno, enctype, + use_pass, salt); + if (retval) + com_err(argv[0], retval, _("while adding new entry")); +} + +void ktutil_delete_entry(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code retval; + + if (argc != 2) { + fprintf(stderr, _("%s: must specify entry to delete\n"), argv[0]); + return; + } + retval = ktutil_delete(kcontext, &ktlist, atoi(argv[1])); + if (retval) + com_err(argv[0], retval, _("while deleting entry %d"), atoi(argv[1])); +} + +void ktutil_list(argc, argv) + int argc; + char *argv[]; +{ + krb5_error_code retval; + krb5_kt_list lp; + int show_time = 0, show_keys = 0, show_enctype = 0; + int i; + unsigned int j; + char *pname; + + for (i = 1; i < argc; i++) { + if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-t", 2)) { + show_time++; + continue; + } + if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-k", 2)) { + show_keys++; + continue; + } + if ((strlen(argv[i]) == 2) && !strncmp(argv[i], "-e", 2)) { + show_enctype++; + continue; + } + + fprintf(stderr, _("%s: usage: %s [-t] [-k] [-e]\n"), argv[0], argv[0]); + return; + } + /* XXX Translating would disturb table alignment; skip for now. */ + if (show_time) { + printf("slot KVNO Timestamp Principal\n"); + printf("---- ---- ----------------- ---------------------------------------------------\n"); + } else { + printf("slot KVNO Principal\n"); + printf("---- ---- ---------------------------------------------------------------------\n"); + } + for (i = 1, lp = ktlist; lp; i++, lp = lp->next) { + retval = krb5_unparse_name(kcontext, lp->entry->principal, &pname); + if (retval) { + com_err(argv[0], retval, "while unparsing principal name"); + return; + } + printf("%4d %4d ", i, lp->entry->vno); + if (show_time) { + char fmtbuf[18]; + char fill; + time_t tstamp; + + tstamp = lp->entry->timestamp; + lp->entry->timestamp = tstamp; + fill = ' '; + if (!krb5_timestamp_to_sfstring((krb5_timestamp)lp->entry-> + timestamp, + fmtbuf, + sizeof(fmtbuf), + &fill)) + printf("%s ", fmtbuf); + } + printf("%40s", pname); + if (show_enctype) { + static char buf[256]; + if ((retval = krb5_enctype_to_name(lp->entry->key.enctype, FALSE, + buf, sizeof(buf)))) { + com_err(argv[0], retval, + _("While converting enctype to string")); + return; + } + printf(" (%s) ", buf); + } + + if (show_keys) { + printf(" (0x"); + for (j = 0; j < lp->entry->key.length; j++) + printf("%02x", lp->entry->key.contents[j]); + printf(")"); + } + printf("\n"); + free(pname); + } +} diff --git a/krb5-1.21.3/src/kadmin/ktutil/ktutil.h b/krb5-1.21.3/src/kadmin/ktutil/ktutil.h new file mode 100644 index 00000000..acaf0239 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/ktutil/ktutil.h @@ -0,0 +1,67 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/ktutil/ktutil.h */ +/* + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +typedef struct _krb5_kt_list { + struct _krb5_kt_list *next; + krb5_keytab_entry *entry; +} *krb5_kt_list; + +krb5_error_code ktutil_free_kt_list (krb5_context, krb5_kt_list); + +krb5_error_code ktutil_delete (krb5_context, krb5_kt_list *, int); + +krb5_error_code ktutil_add (krb5_context, + krb5_kt_list *, + char *, + int, + krb5_kvno, + char *, + int, + char *); + +krb5_error_code ktutil_read_keytab (krb5_context, + char *, + krb5_kt_list *); + +krb5_error_code ktutil_write_keytab (krb5_context, + krb5_kt_list, + char *); + +void ktutil_add_entry (int, char *[]); + +void ktutil_clear_list (int, char *[]); + +void ktutil_read_v5 (int, char *[]); + +void ktutil_read_v4 (int, char *[]); + +void ktutil_write_v5 (int, char *[]); + +void ktutil_write_v4 (int, char *[]); + +void ktutil_delete_entry (int, char *[]); + +void ktutil_list (int, char *[]); diff --git a/krb5-1.21.3/src/kadmin/ktutil/ktutil_ct.ct b/krb5-1.21.3/src/kadmin/ktutil/ktutil_ct.ct new file mode 100644 index 00000000..2061ef9d --- /dev/null +++ b/krb5-1.21.3/src/kadmin/ktutil/ktutil_ct.ct @@ -0,0 +1,59 @@ +# Copyright 1995 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. +# +# +# Command table for ktutil +# + +command_table ktutil_cmds; + +request ktutil_clear_list, "Clear the current keylist.", + clear_list, clear; + +request ktutil_read_v5, "Read a krb5 keytab into the current keylist.", + read_kt, rkt; + +request ktutil_read_v4, "Deprecated and removed.", + read_st, rst; + +request ktutil_write_v5, "Write the current keylist to a krb5 keytab.", + write_kt, wkt; + +request ktutil_write_v4, "Deprecated and removed.", + write_st, wst; + +request ktutil_add_entry, "Add an entry to the current keylist.", + add_entry, addent; + +request ktutil_delete_entry, "Delete an entry from the current keylist.", + delete_entry, delent; + +request ktutil_list, "List the current keylist.", + list, l; + +request ss_list_requests, "List available requests.", + list_requests, lr, "?"; + +request ss_quit, "Exit program.", + quit, exit, q; + +end; diff --git a/krb5-1.21.3/src/kadmin/ktutil/ktutil_funcs.c b/krb5-1.21.3/src/kadmin/ktutil/ktutil_funcs.c new file mode 100644 index 00000000..56bed1bb --- /dev/null +++ b/krb5-1.21.3/src/kadmin/ktutil/ktutil_funcs.c @@ -0,0 +1,371 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/ktutil/ktutil_funcs.c */ +/* + *(C) Copyright 1995, 1996 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Utility functions for ktutil. + */ + +#include "k5-int.h" +#include "k5-hex.h" +#include "ktutil.h" +#include +#include + +/* + * Free a kt_list + */ +krb5_error_code ktutil_free_kt_list(context, list) + krb5_context context; + krb5_kt_list list; +{ + krb5_kt_list lp, prev; + krb5_error_code retval = 0; + + for (lp = list; lp;) { + retval = krb5_kt_free_entry(context, lp->entry); + free(lp->entry); + if (retval) + break; + prev = lp; + lp = lp->next; + free(prev); + } + return retval; +} + +/* + * Delete a numbered entry in a kt_list. Takes a pointer to a kt_list + * in case head gets deleted. + */ +krb5_error_code ktutil_delete(context, list, idx) + krb5_context context; + krb5_kt_list *list; + int idx; +{ + krb5_kt_list lp, prev; + int i; + + for (lp = *list, i = 1; lp; prev = lp, lp = lp->next, i++) { + if (i == idx) { + if (i == 1) + *list = lp->next; + else + prev->next = lp->next; + lp->next = NULL; + return ktutil_free_kt_list(context, lp); + } + } + return EINVAL; +} + +/* + * Determine the enctype, salt, and s2kparams for princ based on the presence + * of the -f flag (fetch), the optionally specified salt string, and the + * optionally specified enctype. If the fetch flag is used, salt_str must not + * be given; if the fetch flag is not used, the enctype must be given. + */ +static krb5_error_code +get_etype_info(krb5_context context, krb5_principal princ, int fetch, + char *salt_str, krb5_enctype *enctype_inout, + krb5_data *salt_out, krb5_data *s2kparams_out) +{ + krb5_error_code retval; + krb5_enctype enctype; + krb5_get_init_creds_opt *opt = NULL; + krb5_data salt; + + *salt_out = empty_data(); + *s2kparams_out = empty_data(); + + if (!fetch) { + /* Use the specified enctype and either the specified or default salt. + * Do not produce s2kparams. */ + assert(*enctype_inout != ENCTYPE_NULL); + if (salt_str != NULL) { + salt = string2data(salt_str); + return krb5int_copy_data_contents(context, &salt, salt_out); + } else { + return krb5_principal2salt(context, princ, salt_out); + } + } + + /* Get etype-info from the KDC. */ + assert(salt_str == NULL); + if (*enctype_inout != ENCTYPE_NULL) { + retval = krb5_get_init_creds_opt_alloc(context, &opt); + if (retval) + return retval; + krb5_get_init_creds_opt_set_etype_list(opt, enctype_inout, 1); + } + retval = krb5_get_etype_info(context, princ, opt, &enctype, salt_out, + s2kparams_out); + krb5_get_init_creds_opt_free(context, opt); + if (retval) + return retval; + if (enctype == ENCTYPE_NULL) + return KRB5KDC_ERR_ETYPE_NOSUPP; + + *enctype_inout = enctype; + return 0; +} + +/* + * Create a new keytab entry and add it to the keytab list. + * Based on the value of use_pass, either prompt the user for a + * password or key. If the keytab list is NULL, allocate a new + * one first. + */ +krb5_error_code ktutil_add(context, list, princ_str, fetch, kvno, + enctype_str, use_pass, salt_str) + krb5_context context; + krb5_kt_list *list; + char *princ_str; + int fetch; + krb5_kvno kvno; + char *enctype_str; + int use_pass; + char *salt_str; +{ + krb5_keytab_entry *entry = NULL; + krb5_kt_list lp, *last; + krb5_principal princ; + krb5_enctype enctype = ENCTYPE_NULL; + krb5_timestamp now; + krb5_error_code retval; + krb5_data password = empty_data(), salt = empty_data(); + krb5_data params = empty_data(), *s2kparams; + krb5_keyblock key; + char buf[BUFSIZ]; + char promptstr[1024]; + char *princ_full = NULL; + uint8_t *keybytes; + size_t keylen; + unsigned int pwsize = BUFSIZ; + + retval = krb5_parse_name(context, princ_str, &princ); + if (retval) + goto cleanup; + /* now unparse in order to get the default realm appended + to princ_str, if no realm was specified */ + retval = krb5_unparse_name(context, princ, &princ_full); + if (retval) + goto cleanup; + if (enctype_str != NULL) { + retval = krb5_string_to_enctype(enctype_str, &enctype); + if (retval) { + retval = KRB5_BAD_ENCTYPE; + goto cleanup; + } + } + retval = krb5_timeofday(context, &now); + if (retval) + goto cleanup; + + entry = k5alloc(sizeof(*entry), &retval); + if (entry == NULL) + goto cleanup; + + if (use_pass) { + retval = alloc_data(&password, pwsize); + if (retval) + goto cleanup; + + snprintf(promptstr, sizeof(promptstr), _("Password for %.1000s"), + princ_full); + retval = krb5_read_password(context, promptstr, NULL, password.data, + &password.length); + if (retval) + goto cleanup; + + retval = get_etype_info(context, princ, fetch, salt_str, + &enctype, &salt, ¶ms); + if (retval) + goto cleanup; + s2kparams = (params.length > 0) ? ¶ms : NULL; + retval = krb5_c_string_to_key_with_params(context, enctype, &password, + &salt, s2kparams, &key); + if (retval) + goto cleanup; + entry->key = key; + } else { + printf(_("Key for %s (hex): "), princ_full); + fgets(buf, BUFSIZ, stdin); + /* + * We need to get rid of the trailing '\n' from fgets. + * If we have an even number of hex digits (as we should), + * write a '\0' over the '\n'. If for some reason we have + * an odd number of hex digits, force an even number of hex + * digits by writing a '0' into the last position (the string + * will still be null-terminated). + */ + buf[strlen(buf) - 1] = strlen(buf) % 2 ? '\0' : '0'; + if (strlen(buf) == 0) { + fprintf(stderr, _("addent: Error reading key.\n")); + retval = 0; + goto cleanup; + } + + retval = k5_hex_decode(buf, &keybytes, &keylen); + if (retval) { + if (retval == EINVAL) { + fprintf(stderr, _("addent: Illegal character in key.\n")); + retval = 0; + } + goto cleanup; + } + + entry->key.enctype = enctype; + entry->key.contents = keybytes; + entry->key.length = keylen; + } + entry->principal = princ; + entry->vno = kvno; + entry->timestamp = now; + + /* Add entry to the end of the list (or create a new list if empty). */ + lp = k5alloc(sizeof(*lp), &retval); + if (lp == NULL) + goto cleanup; + lp->next = NULL; + lp->entry = entry; + entry = NULL; + for (last = list; *last != NULL; last = &(*last)->next); + *last = lp; + +cleanup: + krb5_free_keytab_entry_contents(context, entry); + free(entry); + zapfree(password.data, password.length); + krb5_free_data_contents(context, &salt); + krb5_free_data_contents(context, ¶ms); + krb5_free_unparsed_name(context, princ_full); + return retval; +} + +/* + * Read in a keytab and append it to list. If list starts as NULL, + * allocate a new one if necessary. + */ +krb5_error_code ktutil_read_keytab(context, name, list) + krb5_context context; + char *name; + krb5_kt_list *list; +{ + krb5_kt_list lp = NULL, tail = NULL, back = NULL; + krb5_keytab kt; + krb5_keytab_entry *entry; + krb5_kt_cursor cursor; + krb5_error_code retval = 0; + + if (*list) { + /* point lp at the tail of the list */ + for (lp = *list; lp->next; lp = lp->next); + back = lp; + } + retval = krb5_kt_resolve(context, name, &kt); + if (retval) + return retval; + retval = krb5_kt_start_seq_get(context, kt, &cursor); + if (retval) + goto close_kt; + for (;;) { + entry = (krb5_keytab_entry *)malloc(sizeof (krb5_keytab_entry)); + if (!entry) { + retval = ENOMEM; + break; + } + memset(entry, 0, sizeof (*entry)); + retval = krb5_kt_next_entry(context, kt, entry, &cursor); + if (retval) + break; + + if (!lp) { /* if list is empty, start one */ + lp = (krb5_kt_list)malloc(sizeof (*lp)); + if (!lp) { + retval = ENOMEM; + break; + } + } else { + lp->next = (krb5_kt_list)malloc(sizeof (*lp)); + if (!lp->next) { + retval = ENOMEM; + break; + } + lp = lp->next; + } + if (!tail) + tail = lp; + lp->next = NULL; + lp->entry = entry; + } + if (entry) + free(entry); + if (retval) { + if (retval == KRB5_KT_END) + retval = 0; + else { + ktutil_free_kt_list(context, tail); + tail = NULL; + if (back) + back->next = NULL; + } + } + if (!*list) + *list = tail; + krb5_kt_end_seq_get(context, kt, &cursor); +close_kt: + krb5_kt_close(context, kt); + return retval; +} + +/* + * Takes a kt_list and writes it to the named keytab. + */ +krb5_error_code ktutil_write_keytab(context, list, name) + krb5_context context; + krb5_kt_list list; + char *name; +{ + krb5_kt_list lp; + krb5_keytab kt; + char ktname[MAXPATHLEN+sizeof("WRFILE:")+1]; + krb5_error_code retval = 0; + int result; + + result = snprintf(ktname, sizeof(ktname), "WRFILE:%s", name); + if (SNPRINTF_OVERFLOW(result, sizeof(ktname))) + return ENAMETOOLONG; + retval = krb5_kt_resolve(context, ktname, &kt); + if (retval) + return retval; + for (lp = list; lp; lp = lp->next) { + retval = krb5_kt_add_entry(context, kt, lp->entry); + if (retval) + break; + } + krb5_kt_close(context, kt); + return retval; +} diff --git a/krb5-1.21.3/src/kadmin/scripts/inst-hdrs.sh b/krb5-1.21.3/src/kadmin/scripts/inst-hdrs.sh new file mode 100755 index 00000000..242be89e --- /dev/null +++ b/krb5-1.21.3/src/kadmin/scripts/inst-hdrs.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +dir=$1; shift +while [ $# -gt 0 ]; do + file=$1 + cmp -s $file $dir/$file + if [ $? != 0 ]; then + echo "+ rm $dir/$file" + rm -f $dir/$file + echo "+ cp $file $dir/$file" + cp $file $dir/$file + fi + shift +done diff --git a/krb5-1.21.3/src/kadmin/server/Makefile.in b/krb5-1.21.3/src/kadmin/server/Makefile.in new file mode 100644 index 00000000..1e262f68 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/server/Makefile.in @@ -0,0 +1,24 @@ +mydir=kadmin$(S)server +BUILDTOP=$(REL)..$(S).. +KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS) + +LOCALINCLUDES = -I$(top_srcdir)/lib/gssapi/generic \ + -I$(top_srcdir)/lib/gssapi/krb5 -I$(BUILDTOP)/lib/gssapi/generic \ + -I$(BUILDTOP)/lib/gssapi/krb5 + +PROG = kadmind +OBJS = auth.o auth_acl.o auth_self.o kadm_rpc_svc.o server_stubs.o \ + ovsec_kadmd.o schpw.o misc.o ipropd_svc.o +SRCS = auth.o auth_acl.c auth_self.c kadm_rpc_svc.c server_stubs.c \ + ovsec_kadmd.c schpw.c misc.c ipropd_svc.c + +all: $(PROG) + +$(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB) $(VERTO_DEPLIB) + $(CC_LINK) -o $(PROG) $(OBJS) $(APPUTILS_LIB) $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS) $(VERTO_LIBS) + +install: + $(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(SERVER_BINDIR)/$(PROG) + +clean: + $(RM) $(PROG) $(OBJS) diff --git a/krb5-1.21.3/src/kadmin/server/auth.c b/krb5-1.21.3/src/kadmin/server/auth.c new file mode 100644 index 00000000..081b20a8 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/server/auth.c @@ -0,0 +1,314 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/server/auth.c - kadm5_auth pluggable interface consumer */ +/* + * Copyright (C) 2017 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. + */ + +#include "k5-int.h" +#include +#include +#include "auth.h" + +typedef struct { + struct kadm5_auth_vtable_st vt; + kadm5_auth_moddata data; +} *auth_handle; + +static auth_handle *handles; + +void +auth_fini(krb5_context context) +{ + auth_handle *hp, h; + + if (handles == NULL) + return; + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.fini != NULL) + h->vt.fini(context, h->data); + free(h); + } + free(handles); + handles = NULL; +} + +krb5_error_code +auth_init(krb5_context context, const char *acl_file) +{ + krb5_error_code ret; + krb5_plugin_initvt_fn *modules = NULL, *mod; + size_t count; + auth_handle h = NULL; + const int intf = PLUGIN_INTERFACE_KADM5_AUTH; + + ret = k5_plugin_register(context, intf, "acl", kadm5_auth_acl_initvt); + if (ret) + goto cleanup; + ret = k5_plugin_register(context, intf, "self", kadm5_auth_self_initvt); + if (ret) + goto cleanup; + ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_KADM5_AUTH, &modules); + if (ret) + goto cleanup; + + /* Allocate a large enough list of handles. */ + for (count = 0; modules[count] != NULL; count++); + handles = k5calloc(count + 1, sizeof(*handles), &ret); + if (handles == NULL) + goto cleanup; + + /* For each module, allocate a handle, initialize its vtable, and + * initialize its module data. */ + count = 0; + for (mod = modules; *mod != NULL; mod++) { + h = k5alloc(sizeof(*h), &ret); + if (h == NULL) + goto cleanup; + ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&h->vt); + if (ret) { /* Failed vtable init is non-fatal. */ + TRACE_KADM5_AUTH_VTINIT_FAIL(context, ret); + free(h); + h = NULL; + continue; + } + h->data = NULL; + if (h->vt.init != NULL) { + ret = h->vt.init(context, acl_file, &h->data); + if (ret == KRB5_PLUGIN_NO_HANDLE) { + TRACE_KADM5_AUTH_INIT_SKIP(context, h->vt.name); + free(h); + h = NULL; + continue; + } + if (ret) { + TRACE_KADM5_AUTH_INIT_FAIL(context, h->vt.name, ret); + goto cleanup; + } + } + handles[count++] = h; + handles[count] = NULL; + h = NULL; + } + + ret = 0; + +cleanup: + if (ret) + auth_fini(context); + free(h); + k5_plugin_free_modules(context, modules); + return ret; +} + +/* Invoke the appropriate method from h->vt for opcode, passing client and the + * correct subset of p1, p2, s1, s2, polent, and mask for the method. */ +static krb5_error_code +call_module(krb5_context context, auth_handle h, int opcode, + krb5_const_principal client, krb5_const_principal p1, + krb5_const_principal p2, const char *s1, const char *s2, + const kadm5_policy_ent_rec *polent, long mask) +{ + /* addprinc and modprinc are handled through auth_restrict(). */ + assert(opcode != OP_ADDPRINC && opcode != OP_MODPRINC); + + if (opcode == OP_SETSTR && h->vt.setstr != NULL) + return h->vt.setstr(context, h->data, client, p1, s1, s2); + else if (opcode == OP_CPW && h->vt.cpw != NULL) + return h->vt.cpw(context, h->data, client, p1); + else if (opcode == OP_CHRAND && h->vt.chrand != NULL) + return h->vt.chrand(context, h->data, client, p1); + else if (opcode == OP_SETKEY && h->vt.setkey != NULL) + return h->vt.setkey(context, h->data, client, p1); + else if (opcode == OP_PURGEKEYS && h->vt.purgekeys != NULL) + return h->vt.purgekeys(context, h->data, client, p1); + else if (opcode == OP_DELPRINC && h->vt.delprinc != NULL) + return h->vt.delprinc(context, h->data, client, p1); + else if (opcode == OP_RENPRINC && h->vt.renprinc != NULL) + return h->vt.renprinc(context, h->data, client, p1, p2); + else if (opcode == OP_GETPRINC && h->vt.getprinc != NULL) + return h->vt.getprinc(context, h->data, client, p1); + else if (opcode == OP_GETSTRS && h->vt.getstrs != NULL) + return h->vt.getstrs(context, h->data, client, p1); + else if (opcode == OP_EXTRACT && h->vt.extract != NULL) + return h->vt.extract(context, h->data, client, p1); + else if (opcode == OP_LISTPRINCS && h->vt.listprincs != NULL) + return h->vt.listprincs(context, h->data, client); + else if (opcode == OP_ADDPOL && h->vt.addpol != NULL) + return h->vt.addpol(context, h->data, client, s1, polent, mask); + else if (opcode == OP_MODPOL && h->vt.modpol != NULL) + return h->vt.modpol(context, h->data, client, s1, polent, mask); + else if (opcode == OP_DELPOL && h->vt.delpol != NULL) + return h->vt.delpol(context, h->data, client, s1); + else if (opcode == OP_GETPOL && h->vt.getpol != NULL) + return h->vt.getpol(context, h->data, client, s1, s2); + else if (opcode == OP_LISTPOLS && h->vt.listpols != NULL) + return h->vt.listpols(context, h->data, client); + else if (opcode == OP_IPROP && h->vt.iprop != NULL) + return h->vt.iprop(context, h->data, client); + + return KRB5_PLUGIN_NO_HANDLE; +} + +krb5_boolean +auth(krb5_context context, int opcode, krb5_const_principal client, + krb5_const_principal p1, krb5_const_principal p2, const char *s1, + const char *s2, const kadm5_policy_ent_rec *polent, long mask) +{ + krb5_error_code ret; + krb5_boolean authorized = FALSE; + auth_handle *hp, h; + + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + + ret = call_module(context, h, opcode, client, p1, p2, s1, s2, + polent, mask); + if (!ret) + authorized = TRUE; + else if (ret != KRB5_PLUGIN_NO_HANDLE) + return FALSE; + } + + return authorized; +} + +/* Impose restrictions, modifying *ent and *mask. */ +static krb5_error_code +impose_restrictions(krb5_context context, + const struct kadm5_auth_restrictions *rs, + kadm5_principal_ent_t ent, long *mask) +{ + krb5_error_code ret; + krb5_timestamp now; + + if (rs == NULL) + return 0; + if (rs->mask & (KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION)) { + ret = krb5_timeofday(context, &now); + if (ret) + return ret; + } + + if (rs->mask & KADM5_ATTRIBUTES) { + ent->attributes |= rs->require_attrs; + ent->attributes &= rs->forbid_attrs; + *mask |= KADM5_ATTRIBUTES; + } + if (rs->mask & KADM5_POLICY_CLR) { + *mask &= ~KADM5_POLICY; + *mask |= KADM5_POLICY_CLR; + } else if (rs->mask & KADM5_POLICY) { + if (ent->policy != NULL && strcmp(ent->policy, rs->policy) != 0) { + free(ent->policy); + ent->policy = NULL; + } + if (ent->policy == NULL) { + ent->policy = strdup(rs->policy); + if (ent->policy == NULL) + return ENOMEM; + } + *mask |= KADM5_POLICY; + } + if (rs->mask & KADM5_PRINC_EXPIRE_TIME) { + if (!(*mask & KADM5_PRINC_EXPIRE_TIME) || + ts_after(ent->princ_expire_time, ts_incr(now, rs->princ_lifetime))) + ent->princ_expire_time = now + rs->princ_lifetime; + *mask |= KADM5_PRINC_EXPIRE_TIME; + } + if (rs->mask & KADM5_PW_EXPIRATION) { + if (!(*mask & KADM5_PW_EXPIRATION) || + ts_after(ent->pw_expiration, ts_incr(now, rs->pw_lifetime))) + ent->pw_expiration = now + rs->pw_lifetime; + *mask |= KADM5_PW_EXPIRATION; + } + if (rs->mask & KADM5_MAX_LIFE) { + if (!(*mask & KADM5_MAX_LIFE) || ent->max_life > rs->max_life) + ent->max_life = rs->max_life; + *mask |= KADM5_MAX_LIFE; + } + if (rs->mask & KADM5_MAX_RLIFE) { + if (!(*mask & KADM5_MAX_RLIFE) || + ent->max_renewable_life > rs->max_renewable_life) + ent->max_renewable_life = rs->max_renewable_life; + *mask |= KADM5_MAX_RLIFE; + } + return 0; +} + +krb5_boolean +auth_restrict(krb5_context context, int opcode, krb5_const_principal client, + kadm5_principal_ent_t ent, long *mask) +{ + auth_handle *hp, h; + krb5_boolean authorized = FALSE; + krb5_error_code ret, rs_ret; + krb5_const_principal target = ent->principal; + struct kadm5_auth_restrictions *rs; + + assert(opcode == OP_ADDPRINC || opcode == OP_MODPRINC); + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + + ret = KRB5_PLUGIN_NO_HANDLE; + rs = NULL; + if (opcode == OP_ADDPRINC && h->vt.addprinc != NULL) { + ret = h->vt.addprinc(context, h->data, client, target, ent, *mask, + &rs); + } else if (opcode == OP_MODPRINC && h->vt.modprinc != NULL) { + ret = h->vt.modprinc(context, h->data, client, target, ent, *mask, + &rs); + } + if (rs != NULL) { + rs_ret = impose_restrictions(context, rs, ent, mask); + if (h->vt.free_restrictions != NULL) + h->vt.free_restrictions(context, h->data, rs); + if (rs_ret) + return FALSE; + } + if (!ret) + authorized = TRUE; + else if (ret != KRB5_PLUGIN_NO_HANDLE) + return FALSE; + } + + return authorized; +} + +void +auth_end(krb5_context context) +{ + auth_handle *hp, h; + + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.end != NULL) + h->vt.end(context, h->data); + } +} diff --git a/krb5-1.21.3/src/kadmin/server/auth.h b/krb5-1.21.3/src/kadmin/server/auth.h new file mode 100644 index 00000000..4d265add --- /dev/null +++ b/krb5-1.21.3/src/kadmin/server/auth.h @@ -0,0 +1,85 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/server/auth.h - kadmin authorization declarations */ +/* + * Copyright (C) 2017 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. + */ + +#ifndef AUTH_H +#define AUTH_H + +#define OP_ADDPRINC 1 +#define OP_MODPRINC 2 +#define OP_SETSTR 3 +#define OP_CPW 4 +#define OP_CHRAND 5 +#define OP_SETKEY 6 +#define OP_PURGEKEYS 7 +#define OP_DELPRINC 8 +#define OP_RENPRINC 9 +#define OP_GETPRINC 10 +#define OP_GETSTRS 11 +#define OP_EXTRACT 12 +#define OP_LISTPRINCS 13 +#define OP_ADDPOL 14 +#define OP_MODPOL 15 +#define OP_DELPOL 16 +#define OP_GETPOL 17 +#define OP_LISTPOLS 18 +#define OP_IPROP 19 + +/* Initialize all authorization modules. */ +krb5_error_code auth_init(krb5_context context, const char *acl_file); + +/* Release authorization module state. */ +void auth_fini(krb5_context context); + +/* Authorize the operation given by opcode, using the appropriate subset of p1, + * p2, s1, s2, polent, and mask. */ +krb5_boolean auth(krb5_context context, int opcode, + krb5_const_principal client, krb5_const_principal p1, + krb5_const_principal p2, const char *s1, const char *s2, + const kadm5_policy_ent_rec *polent, long mask); + +/* Authorize an add-principal or modify-principal operation, and apply + * restrictions to ent and mask if any modules supply them. */ +krb5_boolean auth_restrict(krb5_context context, int opcode, + krb5_const_principal client, + kadm5_principal_ent_t ent, long *mask); + +/* Notify modules that the most recent authorized operation has ended. */ +void auth_end(krb5_context context); + +/* initvt declarations for built-in modules */ + +krb5_error_code kadm5_auth_acl_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); +krb5_error_code kadm5_auth_self_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); + +#endif /* AUTH_H */ diff --git a/krb5-1.21.3/src/kadmin/server/auth_acl.c b/krb5-1.21.3/src/kadmin/server/auth_acl.c new file mode 100644 index 00000000..ce9ace36 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/server/auth_acl.c @@ -0,0 +1,755 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/server/auth_acl.c - ACL kadm5_auth module */ +/* + * Copyright 1995-2004, 2007, 2008, 2017 by the Massachusetts Institute of + * Technology. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include +#include +#include +#include "adm_proto.h" +#include +#include "auth.h" + +/* + * Access control bits. + */ +#define ACL_ADD 1 +#define ACL_DELETE 2 +#define ACL_MODIFY 4 +#define ACL_CHANGEPW 8 +/* #define ACL_CHANGE_OWN_PW 16 */ +#define ACL_INQUIRE 32 +#define ACL_EXTRACT 64 +#define ACL_LIST 128 +#define ACL_SETKEY 256 +#define ACL_IPROP 512 + +#define ACL_ALL_MASK (ACL_ADD | \ + ACL_DELETE | \ + ACL_MODIFY | \ + ACL_CHANGEPW | \ + ACL_INQUIRE | \ + ACL_LIST | \ + ACL_IPROP | \ + ACL_SETKEY) + +struct acl_op_table { + char op; + uint32_t mask; +}; + +struct acl_entry { + struct acl_entry *next; + krb5_principal client; + uint32_t op_allowed; + krb5_principal target; + struct kadm5_auth_restrictions *rs; +}; + +static const struct acl_op_table acl_op_table[] = { + { 'a', ACL_ADD }, + { 'd', ACL_DELETE }, + { 'm', ACL_MODIFY }, + { 'c', ACL_CHANGEPW }, + { 'i', ACL_INQUIRE }, + { 'l', ACL_LIST }, + { 'p', ACL_IPROP }, + { 's', ACL_SETKEY }, + { 'x', ACL_ALL_MASK }, + { '*', ACL_ALL_MASK }, + { 'e', ACL_EXTRACT }, + { '\0', 0 } +}; + +struct wildstate { + int nwild; + const krb5_data *backref[9]; +}; + +struct acl_state { + struct acl_entry *list; +}; + +/* + * Get a line from the ACL file. Lines ending with \ are continued on the next + * line. The caller should set *lineno to 1 and *incr to 0 before the first + * call. On successful return, *lineno will be the line number of the line + * read. Return a pointer to the line on success, or NULL on end of file or + * read failure. + */ +static char * +get_line(FILE *fp, const char *fname, int *lineno, int *incr) +{ + const int chunksize = 128; + struct k5buf buf; + size_t old_len; + char *p; + + /* Increment *lineno by the number of newlines from the last line. */ + *lineno += *incr; + *incr = 0; + + k5_buf_init_dynamic(&buf); + for (;;) { + /* Read at least part of a line into the buffer. */ + old_len = buf.len; + p = k5_buf_get_space(&buf, chunksize); + if (p == NULL) + return NULL; + + if (fgets(p, chunksize, fp) == NULL) { + /* We reached the end. Return a final unterminated line, if there + * is one and it's not a comment. */ + k5_buf_truncate(&buf, old_len); + if (buf.len > 0 && *(char *)buf.data != '#') + return buf.data; + k5_buf_free(&buf); + return NULL; + } + + /* Set the buffer length based on the actual amount read. */ + k5_buf_truncate(&buf, old_len + strlen(p)); + + p = buf.data; + if (buf.len > 0 && p[buf.len - 1] == '\n') { + /* We have a complete raw line in the buffer. */ + (*incr)++; + k5_buf_truncate(&buf, buf.len - 1); + if (buf.len > 0 && p[buf.len - 1] == '\\') { + /* This line has a continuation marker; keep reading. */ + k5_buf_truncate(&buf, buf.len - 1); + } else if (buf.len == 0 || *p == '#') { + /* This line is empty or a comment. Start over. */ + *lineno += *incr; + *incr = 0; + k5_buf_truncate(&buf, 0); + } else { + return k5_buf_cstring(&buf); + } + } + } +} + +/* + * Parse a restrictions field. Return NULL on failure. + * + * Allowed restrictions are: + * [+-]flagname (recognized by krb5_flagspec_to_mask) + * flag is forced to indicated value + * -clearpolicy policy is forced clear + * -policy pol policy is forced to be "pol" + * -{expire,pwexpire,maxlife,maxrenewlife} deltat + * associated value will be forced to + * MIN(deltat, requested value) + */ +static struct kadm5_auth_restrictions * +parse_restrictions(const char *str, const char *fname) +{ + char *copy = NULL, *token, *arg, *save; + const char *delims = "\t\n\f\v\r ,"; + krb5_deltat delta; + struct kadm5_auth_restrictions *rs; + + copy = strdup(str); + if (copy == NULL) + return NULL; + + rs = calloc(1, sizeof(*rs)); + if (rs == NULL) { + free(copy); + return NULL; + } + + rs->forbid_attrs = ~(krb5_flags)0; + for (token = strtok_r(copy, delims, &save); token != NULL; + token = strtok_r(NULL, delims, &save)) { + + if (krb5_flagspec_to_mask(token, &rs->require_attrs, + &rs->forbid_attrs) == 0) { + rs->mask |= KADM5_ATTRIBUTES; + continue; + } + + if (strcmp(token, "-clearpolicy") == 0) { + rs->mask |= KADM5_POLICY_CLR; + continue; + } + + /* Everything else needs an argument. */ + arg = strtok_r(NULL, delims, &save); + if (arg == NULL) + goto error; + + if (strcmp(token, "-policy") == 0) { + if (rs->policy != NULL) + goto error; + rs->policy = strdup(arg); + if (rs->policy == NULL) + goto error; + rs->mask |= KADM5_POLICY; + continue; + } + + /* All other arguments must be a deltat. */ + if (krb5_string_to_deltat(arg, &delta) != 0) + goto error; + + if (strcmp(token, "-expire") == 0) { + rs->princ_lifetime = delta; + rs->mask |= KADM5_PRINC_EXPIRE_TIME; + } else if (strcmp(token, "-pwexpire") == 0) { + rs->pw_lifetime = delta; + rs->mask |= KADM5_PW_EXPIRATION; + } else if (strcmp(token, "-maxlife") == 0) { + rs->max_life = delta; + rs->mask |= KADM5_MAX_LIFE; + } else if (strcmp(token, "-maxrenewlife") == 0) { + rs->max_renewable_life = delta; + rs->mask |= KADM5_MAX_RLIFE; + } else { + goto error; + } + } + + free(copy); + return rs; + +error: + krb5_klog_syslog(LOG_ERR, _("%s: invalid restrictions: %s"), fname, str); + free(copy); + free(rs->policy); + free(rs); + return NULL; +} + +static void +free_acl_entry(struct acl_entry *entry) +{ + krb5_free_principal(NULL, entry->client); + krb5_free_principal(NULL, entry->target); + if (entry->rs != NULL) { + free(entry->rs->policy); + free(entry->rs); + } + free(entry); +} + +/* Parse the four fields of an ACL entry and return a structure representing + * it. Log a message and return NULL on error. */ +static struct acl_entry * +parse_entry(krb5_context context, const char *client, const char *ops, + const char *target, const char *rs, const char *line, + const char *fname) +{ + struct acl_entry *entry; + const char *op; + char rop; + int t; + + entry = calloc(1, sizeof(*entry)); + if (entry == NULL) + return NULL; + + for (op = ops; *op; op++) { + rop = isupper((unsigned char)*op) ? tolower((unsigned char)*op) : *op; + for (t = 0; acl_op_table[t].op; t++) { + if (rop == acl_op_table[t].op) { + if (rop == *op) + entry->op_allowed |= acl_op_table[t].mask; + else + entry->op_allowed &= ~acl_op_table[t].mask; + break; + } + } + if (!acl_op_table[t].op) { + krb5_klog_syslog(LOG_ERR, + _("Unrecognized ACL operation '%c' in %s"), + *op, line); + goto error; + } + } + + if (strcmp(client, "*") != 0) { + if (krb5_parse_name(context, client, &entry->client) != 0) { + krb5_klog_syslog(LOG_ERR, _("Cannot parse client principal '%s'"), + client); + goto error; + } + } + + if (target != NULL && strcmp(target, "*") != 0) { + if (krb5_parse_name(context, target, &entry->target) != 0) { + krb5_klog_syslog(LOG_ERR, _("Cannot parse target principal '%s'"), + target); + goto error; + } + } + + if (rs != NULL) { + entry->rs = parse_restrictions(rs, fname); + if (entry->rs == NULL) + goto error; + } + + return entry; + +error: + free_acl_entry(entry); + return NULL; +} + +/* Parse the contents of an ACL line. */ +static struct acl_entry * +parse_line(krb5_context context, const char *line, const char *fname) +{ + struct acl_entry *entry = NULL; + char *copy; + char *client, *client_end, *ops, *ops_end, *target, *target_end, *rs, *end; + const char *ws = "\t\n\f\v\r ,"; + + /* + * Format: + * entry ::= [] + * [ [ + * []]] + */ + + /* Make a copy and remove any trailing whitespace. */ + copy = strdup(line); + if (copy == NULL) + return NULL; + end = copy + strlen(copy); + while (end > copy && isspace(end[-1])) + *--end = '\0'; + + /* Find the beginning and end of each field. The end of restrictions is + * the end of copy. */ + client = copy + strspn(copy, ws); + client_end = client + strcspn(client, ws); + ops = client_end + strspn(client_end, ws); + ops_end = ops + strcspn(ops, ws); + target = ops_end + strspn(ops_end, ws); + target_end = target + strcspn(target, ws); + rs = target_end + strspn(target_end, ws); + + /* Terminate the first three fields. */ + *client_end = *ops_end = *target_end = '\0'; + + /* The last two fields are optional; represent them as NULL if not present. + * The first two fields are required. */ + if (*target == '\0') + target = NULL; + if (*rs == '\0') + rs = NULL; + if (*client != '\0' && *ops != '\0') + entry = parse_entry(context, client, ops, target, rs, line, fname); + free(copy); + return entry; +} + +/* Free all ACL entries. */ +static void +free_acl_entries(struct acl_state *state) +{ + struct acl_entry *entry, *next; + + for (entry = state->list; entry != NULL; entry = next) { + next = entry->next; + free_acl_entry(entry); + } + state->list = NULL; +} + +/* Open and parse the ACL file. */ +static krb5_error_code +load_acl_file(krb5_context context, const char *fname, struct acl_state *state) +{ + krb5_error_code ret; + FILE *fp; + char *line; + struct acl_entry **entry_slot; + int lineno, incr; + + state->list = NULL; + + /* Open the ACL file for reading. */ + fp = fopen(fname, "r"); + if (fp == NULL) { + krb5_klog_syslog(LOG_ERR, _("%s while opening ACL file %s"), + error_message(errno), fname); + ret = errno; + k5_setmsg(context, errno, _("Cannot open %s: %s"), fname, + error_message(ret)); + return ret; + } + + set_cloexec_file(fp); + lineno = 1; + incr = 0; + entry_slot = &state->list; + + /* Get a non-comment line. */ + while ((line = get_line(fp, fname, &lineno, &incr)) != NULL) { + /* Parse it. Fail out on syntax error. */ + *entry_slot = parse_line(context, line, fname); + if (*entry_slot == NULL) { + krb5_klog_syslog(LOG_ERR, + _("%s: syntax error at line %d <%.10s...>"), + fname, lineno, line); + k5_setmsg(context, EINVAL, + _("%s: syntax error at line %d <%.10s...>"), + fname, lineno, line); + free_acl_entries(state); + free(line); + fclose(fp); + return EINVAL; + } + entry_slot = &(*entry_slot)->next; + free(line); + } + + fclose(fp); + return 0; +} + +/* + * See if two data entries match. If e1 is a wildcard (matching a whole + * component only) and targetflag is false, save an alias to e2 into + * ws->backref. If e1 is a back-reference and targetflag is true, compare the + * appropriate entry in ws->backref to e2. If ws is NULL, do not store or + * match back-references. + */ +static krb5_boolean +match_data(const krb5_data *e1, const krb5_data *e2, krb5_boolean targetflag, + struct wildstate *ws) +{ + int n; + + if (data_eq_string(*e1, "*")) { + if (ws != NULL && !targetflag) { + if (ws->nwild < 9) + ws->backref[ws->nwild++] = e2; + } + return TRUE; + } + + if (ws != NULL && targetflag && e1->length == 2 && e1->data[0] == '*' && + e1->data[1] >= '1' && e1->data[1] <= '9') { + n = e1->data[1] - '1'; + if (n >= ws->nwild) + return FALSE; + return data_eq(*e2, *ws->backref[n]); + } else { + return data_eq(*e2, *e1); + } +} + +/* Return true if p1 matches p2. p1 may contain wildcards if targetflag is + * false, or backreferences if it is true. */ +static krb5_boolean +match_princ(krb5_const_principal p1, krb5_const_principal p2, + krb5_boolean targetflag, struct wildstate *ws) +{ + int i; + + /* The principals must be of the same length. */ + if (p1->length != p2->length) + return FALSE; + + /* The realm must match, and does not interact with wildcard state. */ + if (!match_data(&p1->realm, &p2->realm, targetflag, NULL)) + return FALSE; + + /* All components of the principals must match. */ + for (i = 0; i < p1->length; i++) { + if (!match_data(&p1->data[i], &p2->data[i], targetflag, ws)) + return FALSE; + } + + return TRUE; +} + +/* Find an ACL entry matching principal and target_principal. Return NULL if + * none is found. */ +static struct acl_entry * +find_entry(struct acl_state *state, krb5_const_principal client, + krb5_const_principal target) +{ + struct acl_entry *entry; + struct wildstate ws; + + for (entry = state->list; entry != NULL; entry = entry->next) { + memset(&ws, 0, sizeof(ws)); + if (entry->client != NULL) { + if (!match_princ(entry->client, client, FALSE, &ws)) + continue; + } + + if (entry->target != NULL) { + if (target == NULL) + continue; + if (!match_princ(entry->target, target, TRUE, &ws)) + continue; + } + + return entry; + } + + return NULL; +} + +/* Return true if op is permitted for this principal. Set *rs_out (if not + * NULL) according to any restrictions in the ACL entry. */ +static krb5_error_code +acl_check(kadm5_auth_moddata data, uint32_t op, krb5_const_principal client, + krb5_const_principal target, struct kadm5_auth_restrictions **rs_out) +{ + struct acl_entry *entry; + + if (rs_out != NULL) + *rs_out = NULL; + + entry = find_entry((struct acl_state *)data, client, target); + if (entry == NULL) + return KRB5_PLUGIN_NO_HANDLE; + if (!(entry->op_allowed & op)) + return KRB5_PLUGIN_NO_HANDLE; + + if (rs_out != NULL && entry->rs != NULL && entry->rs->mask) + *rs_out = entry->rs; + + return 0; +} + +static krb5_error_code +acl_init(krb5_context context, const char *acl_file, + kadm5_auth_moddata *data_out) +{ + krb5_error_code ret; + struct acl_state *state; + + *data_out = NULL; + if (acl_file == NULL) + return KRB5_PLUGIN_NO_HANDLE; + state = malloc(sizeof(*state)); + state->list = NULL; + ret = load_acl_file(context, acl_file, state); + if (ret) { + free(state); + return ret; + } + *data_out = (kadm5_auth_moddata)state; + return 0; +} + +static void +acl_fini(krb5_context context, kadm5_auth_moddata data) +{ + if (data == NULL) + return; + free_acl_entries((struct acl_state *)data); + free(data); +} + +static krb5_error_code +acl_addprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target, + const struct _kadm5_principal_ent_t *ent, long mask, + struct kadm5_auth_restrictions **rs_out) +{ + return acl_check(data, ACL_ADD, client, target, rs_out); +} + +static krb5_error_code +acl_modprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target, + const struct _kadm5_principal_ent_t *ent, long mask, + struct kadm5_auth_restrictions **rs_out) +{ + return acl_check(data, ACL_MODIFY, client, target, rs_out); +} + +static krb5_error_code +acl_setstr(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target, + const char *key, const char *value) +{ + return acl_check(data, ACL_MODIFY, client, target, NULL); +} + +static krb5_error_code +acl_cpw(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_CHANGEPW, client, target, NULL); +} + +static krb5_error_code +acl_chrand(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_CHANGEPW, client, target, NULL); +} + +static krb5_error_code +acl_setkey(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_SETKEY, client, target, NULL); +} + +static krb5_error_code +acl_purgekeys(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_MODIFY, client, target, NULL); +} + +static krb5_error_code +acl_delprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_DELETE, client, target, NULL); +} + +static krb5_error_code +acl_renprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal src, + krb5_const_principal dest) +{ + struct kadm5_auth_restrictions *rs; + + if (acl_check(data, ACL_DELETE, client, src, NULL) == 0 && + acl_check(data, ACL_ADD, client, dest, &rs) == 0 && rs == NULL) + return 0; + return KRB5_PLUGIN_NO_HANDLE; +} + +static krb5_error_code +acl_getprinc(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_INQUIRE, client, target, NULL); +} + +static krb5_error_code +acl_getstrs(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_INQUIRE, client, target, NULL); +} + +static krb5_error_code +acl_extract(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + return acl_check(data, ACL_EXTRACT, client, target, NULL); +} + +static krb5_error_code +acl_listprincs(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client) +{ + return acl_check(data, ACL_LIST, client, NULL, NULL); +} + +static krb5_error_code +acl_addpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const struct _kadm5_policy_ent_t *ent, long mask) +{ + return acl_check(data, ACL_ADD, client, NULL, NULL); +} + +static krb5_error_code +acl_modpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const struct _kadm5_policy_ent_t *ent, long mask) +{ + return acl_check(data, ACL_MODIFY, client, NULL, NULL); +} + +static krb5_error_code +acl_delpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy) +{ + return acl_check(data, ACL_DELETE, client, NULL, NULL); +} + +static krb5_error_code +acl_getpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const char *client_policy) +{ + return acl_check(data, ACL_INQUIRE, client, NULL, NULL); +} + +static krb5_error_code +acl_listpols(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client) +{ + return acl_check(data, ACL_LIST, client, NULL, NULL); +} + +static krb5_error_code +acl_iprop(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client) +{ + return acl_check(data, ACL_IPROP, client, NULL, NULL); +} + +krb5_error_code +kadm5_auth_acl_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + kadm5_auth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (kadm5_auth_vtable)vtable; + vt->name = "acl"; + vt->init = acl_init; + vt->fini = acl_fini; + vt->addprinc = acl_addprinc; + vt->modprinc = acl_modprinc; + vt->setstr = acl_setstr; + vt->cpw = acl_cpw; + vt->chrand = acl_chrand; + vt->setkey = acl_setkey; + vt->purgekeys = acl_purgekeys; + vt->delprinc = acl_delprinc; + vt->renprinc = acl_renprinc; + vt->getprinc = acl_getprinc; + vt->getstrs = acl_getstrs; + vt->extract = acl_extract; + vt->listprincs = acl_listprincs; + vt->addpol = acl_addpol; + vt->modpol = acl_modpol; + vt->delpol = acl_delpol; + vt->getpol = acl_getpol; + vt->listpols = acl_listpols; + vt->iprop = acl_iprop; + return 0; +} diff --git a/krb5-1.21.3/src/kadmin/server/auth_self.c b/krb5-1.21.3/src/kadmin/server/auth_self.c new file mode 100644 index 00000000..253d4bc5 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/server/auth_self.c @@ -0,0 +1,77 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kadmin/server/auth_self.c - self-service kadm5_auth module */ +/* + * Copyright (C) 2017 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. + */ + +#include "k5-int.h" +#include +#include +#include "auth.h" + +/* Authorize a principal to operate on itself. Applies to cpw, chrand, + * purgekeys, getprinc, and getstrs. */ +static krb5_error_code +self_compare(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, krb5_const_principal target) +{ + if (krb5_principal_compare(context, client, target)) + return 0; + return KRB5_PLUGIN_NO_HANDLE; +} + +/* Authorize a principal to get the policy record for its own policy. */ +static krb5_error_code +self_getpol(krb5_context context, kadm5_auth_moddata data, + krb5_const_principal client, const char *policy, + const char *client_policy) +{ + if (client_policy != NULL && strcmp(policy, client_policy) == 0) + return 0; + return KRB5_PLUGIN_NO_HANDLE; +} + +krb5_error_code +kadm5_auth_self_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + kadm5_auth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (kadm5_auth_vtable)vtable; + vt->name = "self"; + vt->cpw = self_compare; + vt->chrand = self_compare; + vt->purgekeys = self_compare; + vt->getprinc = self_compare; + vt->getstrs = self_compare; + vt->getpol = self_getpol; + return 0; +} diff --git a/krb5-1.21.3/src/kadmin/server/deps b/krb5-1.21.3/src/kadmin/server/deps new file mode 100644 index 00000000..69f19366 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/server/deps @@ -0,0 +1,176 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)auth_acl.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kadm5_auth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth.h auth_acl.c +$(OUTPRE)auth_self.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kadm5_auth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth.h auth_self.c +$(OUTPRE)kadm_rpc_svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kadm_rpc_svc.c \ + misc.h +$(OUTPRE)server_stubs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth.h misc.h \ + server_stubs.c +$(OUTPRE)ovsec_kadmd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/kadm_rpc.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(BUILDTOP)/lib/gssapi/generic/gssapi_err_generic.h \ + $(BUILDTOP)/lib/gssapi/krb5/gssapi_err_krb5.h $(COM_ERR_DEPS) \ + $(VERTO_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_gssapi.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/iprop.h $(top_srcdir)/include/iprop_hdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/kdb_kt.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + $(top_srcdir)/lib/gssapi/generic/gssapiP_generic.h \ + $(top_srcdir)/lib/gssapi/generic/gssapi_ext.h $(top_srcdir)/lib/gssapi/generic/gssapi_generic.h \ + $(top_srcdir)/lib/gssapi/krb5/gssapiP_krb5.h $(top_srcdir)/lib/gssapi/krb5/gssapi_krb5.h \ + auth.h misc.h ovsec_kadmd.c +$(OUTPRE)schpw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(VERTO_DEPS) $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + misc.h schpw.c +$(OUTPRE)misc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(VERTO_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth.h misc.c \ + misc.h +$(OUTPRE)ipropd_svc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/kadm_rpc.h \ + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/kdb_log.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \ + $(top_srcdir)/lib/gssapi/krb5/gssapi_krb5.h auth.h \ + ipropd_svc.c misc.h diff --git a/krb5-1.21.3/src/kadmin/server/ipropd_svc.c b/krb5-1.21.3/src/kadmin/server/ipropd_svc.c new file mode 100644 index 00000000..56e9b90b --- /dev/null +++ b/krb5-1.21.3/src/kadmin/server/ipropd_svc.c @@ -0,0 +1,619 @@ +/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t -*- */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* #pragma ident "@(#)ipropd_svc.c 1.2 04/02/20 SMI" */ + + +#include "k5-platform.h" +#include +#include +#include /* rlimit */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "auth.h" +#include "misc.h" +#include "osconf.h" + +extern gss_name_t rqst2name(struct svc_req *rqstp); + +extern void *global_server_handle; +extern int nofork; +extern short l_port; +extern char *kdb5_util; +extern char *kprop; +extern char *dump_file; +extern char *kprop_port; + +static char *reply_ok_str = "UPDATE_OK"; +static char *reply_err_str = "UPDATE_ERROR"; +static char *reply_fr_str = "UPDATE_FULL_RESYNC_NEEDED"; +static char *reply_busy_str = "UPDATE_BUSY"; +static char *reply_nil_str = "UPDATE_NIL"; +static char *reply_perm_str = "UPDATE_PERM_DENIED"; +static char *reply_unknown_str = ""; + +#define LOG_UNAUTH _("Unauthorized request: %s, client=%s, service=%s, addr=%s") +#define LOG_DONE _("Request: %s, %s, %s, client=%s, service=%s, addr=%s") + +#ifdef DPRINT +#undef DPRINT +#endif +#ifdef DEBUG +#define DPRINT(...) \ + do { \ + if (nofork) { \ + fprintf(stderr, __VA_ARGS__); \ + fflush(stderr); \ + } \ + } while (0) +#else +#define DPRINT(...) +#endif + +static void +debprret(char *w, update_status_t ret, kdb_sno_t sno) +{ + switch (ret) { + case UPDATE_OK: + printf("%s: end (OK, sno=%u)\n", + w, sno); + break; + case UPDATE_ERROR: + printf("%s: end (ERROR)\n", w); + break; + case UPDATE_FULL_RESYNC_NEEDED: + printf("%s: end (FR NEEDED)\n", w); + break; + case UPDATE_BUSY: + printf("%s: end (BUSY)\n", w); + break; + case UPDATE_NIL: + printf("%s: end (NIL)\n", w); + break; + case UPDATE_PERM_DENIED: + printf("%s: end (PERM)\n", w); + break; + default: + printf("%s: end (UNKNOWN return code (%d))\n", w, ret); + } +} + +static char * +replystr(update_status_t ret) +{ + switch (ret) { + case UPDATE_OK: + return (reply_ok_str); + case UPDATE_ERROR: + return (reply_err_str); + case UPDATE_FULL_RESYNC_NEEDED: + return (reply_fr_str); + case UPDATE_BUSY: + return (reply_busy_str); + case UPDATE_NIL: + return (reply_nil_str); + case UPDATE_PERM_DENIED: + return (reply_perm_str); + default: + return (reply_unknown_str); + } +} + +/* Returns null on allocation failure. + Regardless of success or failure, frees the input buffer. */ +static char * +buf_to_string(gss_buffer_desc *b) +{ + OM_uint32 min_stat; + char *s = malloc(b->length+1); + + if (s) { + memcpy(s, b->value, b->length); + s[b->length] = 0; + } + (void) gss_release_buffer(&min_stat, b); + return s; +} + +static krb5_boolean +iprop_acl_check(krb5_context context, const char *client_name) +{ + krb5_principal client_princ; + krb5_boolean result; + + if (krb5_parse_name(context, client_name, &client_princ) != 0) + return FALSE; + result = auth(context, OP_IPROP, client_princ, + NULL, NULL, NULL, NULL, NULL, 0); + krb5_free_principal(context, client_princ); + return result; +} + +kdb_incr_result_t * +iprop_get_updates_1_svc(kdb_last_t *arg, struct svc_req *rqstp) +{ + static kdb_incr_result_t ret; + char *whoami = "iprop_get_updates_1"; + int kret; + kadm5_server_handle_t handle = global_server_handle; + char *client_name = 0, *service_name = 0; + char obuf[256] = {0}; + + /* default return code */ + ret.ret = UPDATE_ERROR; + + DPRINT("%s: start, last_sno=%lu\n", whoami, + (unsigned long)arg->last_sno); + + if (!handle) { + krb5_klog_syslog(LOG_ERR, + _("%s: server handle is NULL"), + whoami); + goto out; + } + + { + gss_buffer_desc client_desc, service_desc; + + if (setup_gss_names(rqstp, &client_desc, &service_desc) < 0) { + krb5_klog_syslog(LOG_ERR, + _("%s: setup_gss_names failed"), + whoami); + goto out; + } + client_name = buf_to_string(&client_desc); + service_name = buf_to_string(&service_desc); + if (client_name == NULL || service_name == NULL) { + krb5_klog_syslog(LOG_ERR, + _("%s: out of memory recording principal names"), + whoami); + goto out; + } + } + + DPRINT("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n", whoami, client_name, + service_name); + + if (!iprop_acl_check(handle->context, client_name)) { + ret.ret = UPDATE_PERM_DENIED; + + DPRINT("%s: PERMISSION DENIED: clprinc=`%s'\n\tsvcprinc=`%s'\n", + whoami, client_name, service_name); + + krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami, + client_name, service_name, + client_addr(rqstp->rq_xprt)); + goto out; + } + + kret = ulog_get_entries(handle->context, arg, &ret); + + if (ret.ret == UPDATE_OK) { + (void) snprintf(obuf, sizeof (obuf), + _("%s; Incoming SerialNo=%lu; Outgoing SerialNo=%lu"), + replystr(ret.ret), + (unsigned long)arg->last_sno, + (unsigned long)ret.lastentry.last_sno); + } else { + (void) snprintf(obuf, sizeof (obuf), + _("%s; Incoming SerialNo=%lu; Outgoing SerialNo=N/A"), + replystr(ret.ret), + (unsigned long)arg->last_sno); + } + + DPRINT("%s: request %s %s\n\tclprinc=`%s'\n\tsvcprinc=`%s'\n", + whoami, obuf, + ((kret == 0) ? "success" : error_message(kret)), + client_name, service_name); + + krb5_klog_syslog(LOG_NOTICE, + _("Request: %s, %s, %s, client=%s, service=%s, addr=%s"), + whoami, + obuf, + ((kret == 0) ? "success" : error_message(kret)), + client_name, service_name, + client_addr(rqstp->rq_xprt)); + +out: + if (nofork) + debprret(whoami, ret.ret, ret.lastentry.last_sno); + free(client_name); + free(service_name); + return (&ret); +} + + +/* + * Given a client princ (foo/fqdn@R), copy (in arg cl) the fqdn substring. + * Return arg cl str ptr on success, else NULL. + */ +static char * +getclhoststr(const char *clprinc, char *cl, size_t len) +{ + const char *s, *e; + + if ((s = strchr(clprinc, '/')) == NULL || (e = strchr(++s, '@')) == NULL || + (size_t)(e - s) >= len) + return NULL; + memcpy(cl, s, e - s); + cl[e - s] = '\0'; + return (cl); +} + +static kdb_fullresync_result_t * +ipropx_resync(uint32_t vers, struct svc_req *rqstp) +{ + static kdb_fullresync_result_t ret; + char *ubuf = 0; + char clhost[NI_MAXHOST] = {0}; + int pret, fret; + FILE *p; + kadm5_server_handle_t handle = global_server_handle; + char *client_name = NULL, *service_name = NULL; + char *whoami = "iprop_full_resync_1"; + + /* + * vers contains the highest version number the client is + * willing to accept. A client can always accept a lower + * version: the version number is indicated in the dump + * header. + */ + + /* default return code */ + ret.ret = UPDATE_ERROR; + + if (!handle) { + krb5_klog_syslog(LOG_ERR, + _("%s: server handle is NULL"), + whoami); + goto out; + } + + DPRINT("%s: start\n", whoami); + + { + gss_buffer_desc client_desc, service_desc; + + if (setup_gss_names(rqstp, &client_desc, &service_desc) < 0) { + DPRINT("%s: setup_gss_names failed\n", whoami); + krb5_klog_syslog(LOG_ERR, + _("%s: setup_gss_names failed"), + whoami); + goto out; + } + client_name = buf_to_string(&client_desc); + service_name = buf_to_string(&service_desc); + if (client_name == NULL || service_name == NULL) { + DPRINT("%s: out of memory\n", whoami); + krb5_klog_syslog(LOG_ERR, + _("%s: out of memory recording principal names"), + whoami); + goto out; + } + } + + DPRINT("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n", + whoami, client_name, service_name); + + if (!iprop_acl_check(handle->context, client_name)) { + ret.ret = UPDATE_PERM_DENIED; + + DPRINT("%s: Permission denied\n", whoami); + krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami, + client_name, service_name, + client_addr(rqstp->rq_xprt)); + goto out; + } + + if (!getclhoststr(client_name, clhost, sizeof (clhost))) { + krb5_klog_syslog(LOG_ERR, + _("%s: getclhoststr failed"), + whoami); + goto out; + } + + /* + * Note the -i; modified version of kdb5_util dump format + * to include sno (serial number). This argument is now + * versioned (-i0 for legacy dump format, -i1 for ipropx + * version 1 format, etc). + * + * The -c option ("conditional") causes the dump to dump only if no + * dump already exists or that dump is not in ipropx format, or the + * sno and timestamp in the header of that dump are outside the + * ulog. This allows us to share a single global dump with all + * replicas, since it's OK to share an older dump, as long as its + * sno and timestamp are in the ulog (then the replicas can get the + * subsequent updates very iprop). + */ + if (asprintf(&ubuf, "%s -r %s dump -i%d -c %s", kdb5_util, + handle->params.realm, vers, dump_file) < 0) { + krb5_klog_syslog(LOG_ERR, + _("%s: cannot construct kdb5 util dump string too long; out of memory"), + whoami); + goto out; + } + + /* + * Fork to dump the db and xfer it to the replica. + * (the fork allows parent to return quickly and the child + * acts like a callback to the replica). + */ + fret = fork(); + DPRINT("%s: fork=%d (%d)\n", whoami, fret, getpid()); + + switch (fret) { + case -1: /* error */ + if (nofork) { + perror(whoami); + } + DPRINT("%s: fork failed\n", whoami); + krb5_klog_syslog(LOG_ERR, + _("%s: fork failed: %s"), + whoami, + error_message(errno)); + goto out; + + case 0: /* child */ + DPRINT("%s: run `%s' ...\n", whoami, ubuf); + (void) signal(SIGCHLD, SIG_DFL); + /* run kdb5_util(1M) dump for IProp */ + p = popen(ubuf, "w"); + if (p == NULL) { + krb5_klog_syslog(LOG_ERR, + _("%s: popen failed: %s"), + whoami, error_message(errno)); + _exit(1); + } + pret = pclose(p); + DPRINT("%s: pclose=%d\n", whoami, pret); + if (pret != 0) { + /* XXX popen/pclose may not set errno + properly, and the error could be from the + subprocess anyways. */ + if (nofork) { + perror(whoami); + } + krb5_klog_syslog(LOG_ERR, + _("%s: pclose(popen) failed: %s"), + whoami, + error_message(errno)); + _exit(1); + } + + if (kprop_port != NULL) { + DPRINT("%s: exec `kprop -r %s -f %s -P %s %s' ...\n", + whoami, handle->params.realm, dump_file, kprop_port, + clhost); + pret = execl(kprop, "kprop", "-r", handle->params.realm, "-f", + dump_file, "-P", kprop_port, clhost, NULL); + } else { + DPRINT("%s: exec `kprop -r %s -f %s %s' ...\n", + whoami, handle->params.realm, dump_file, clhost); + pret = execl(kprop, "kprop", "-r", handle->params.realm, "-f", + dump_file, clhost, NULL); + } + perror(whoami); + krb5_klog_syslog(LOG_ERR, + _("%s: exec failed: %s"), + whoami, + error_message(errno)); + _exit(1); + + default: /* parent */ + ret.ret = UPDATE_OK; + /* not used by replica (sno is retrieved from kdb5_util dump) */ + ret.lastentry.last_sno = 0; + ret.lastentry.last_time.seconds = 0; + ret.lastentry.last_time.useconds = 0; + + DPRINT("%s: spawned resync process %d, client=%s, " + "service=%s, addr=%s\n", whoami, fret, client_name, + service_name, client_addr(rqstp->rq_xprt)); + krb5_klog_syslog(LOG_NOTICE, + _("Request: %s, spawned resync process %d, client=%s, service=%s, addr=%s"), + whoami, fret, + client_name, service_name, + client_addr(rqstp->rq_xprt)); + + goto out; + } + +out: + if (nofork) + debprret(whoami, ret.ret, 0); + free(client_name); + free(service_name); + free(ubuf); + return (&ret); +} + +kdb_fullresync_result_t * +iprop_full_resync_1_svc(/* LINTED */ void *argp, struct svc_req *rqstp) +{ + return ipropx_resync(IPROPX_VERSION_0, rqstp); +} + +kdb_fullresync_result_t * +iprop_full_resync_ext_1_svc(uint32_t *argp, struct svc_req *rqstp) +{ + return ipropx_resync(*argp, rqstp); +} + +static int +check_iprop_rpcsec_auth(struct svc_req *rqstp) +{ + /* XXX Since the client can authenticate against any principal in + the database, we need to do a sanity check. Only checking for + "kiprop" now, but that means theoretically the client could be + authenticating to kiprop on some other machine. */ + /* Code taken from kadm_rpc_svc.c, tweaked. */ + + gss_ctx_id_t ctx; + krb5_context kctx; + OM_uint32 maj_stat, min_stat; + gss_name_t name; + krb5_principal princ; + int ret, success; + krb5_data *c1, *realm; + gss_buffer_desc gss_str; + kadm5_server_handle_t handle; + size_t slen; + char *sdots; + + success = 0; + handle = (kadm5_server_handle_t)global_server_handle; + + if (rqstp->rq_cred.oa_flavor != RPCSEC_GSS) + return 0; + + ctx = rqstp->rq_svccred; + + maj_stat = gss_inquire_context(&min_stat, ctx, NULL, &name, + NULL, NULL, NULL, NULL, NULL); + if (maj_stat != GSS_S_COMPLETE) { + krb5_klog_syslog(LOG_ERR, + _("check_rpcsec_auth: failed inquire_context, " + "stat=%u"), maj_stat); + log_badauth(maj_stat, min_stat, rqstp->rq_xprt, NULL); + goto fail_name; + } + + kctx = handle->context; + ret = gss_to_krb5_name_1(rqstp, kctx, name, &princ, &gss_str); + if (ret == 0) + goto fail_name; + + slen = gss_str.length; + trunc_name(&slen, &sdots); + /* + * Since we accept with GSS_C_NO_NAME, the client can authenticate + * against the entire kdb. Therefore, ensure that the service + * name is something reasonable. + */ + if (krb5_princ_size(kctx, princ) != 2) + goto fail_princ; + + c1 = krb5_princ_component(kctx, princ, 0); + realm = krb5_princ_realm(kctx, princ); + if (strncmp(handle->params.realm, realm->data, realm->length) == 0 + && strncmp("kiprop", c1->data, c1->length) == 0) { + success = 1; + } + +fail_princ: + if (!success) { + krb5_klog_syslog(LOG_ERR, _("bad service principal %.*s%s"), + (int) slen, (char *) gss_str.value, sdots); + } + gss_release_buffer(&min_stat, &gss_str); + krb5_free_principal(kctx, princ); +fail_name: + gss_release_name(&min_stat, &name); + return success; +} + +void +krb5_iprop_prog_1(struct svc_req *rqstp, + SVCXPRT *transp) +{ + union { + kdb_last_t iprop_get_updates_1_arg; + } argument; + void *result; + bool_t (*_xdr_argument)(), (*_xdr_result)(); + void *(*local)(/* union XXX *, struct svc_req * */); + char *whoami = "krb5_iprop_prog_1"; + + if (!check_iprop_rpcsec_auth(rqstp)) { + krb5_klog_syslog(LOG_ERR, _("authentication attempt failed: %s, RPC " + "authentication flavor %d"), + client_addr(rqstp->rq_xprt), + rqstp->rq_cred.oa_flavor); + svcerr_weakauth(transp); + return; + } + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply(transp, xdr_void, + (char *)NULL); + return; + + case IPROP_GET_UPDATES: + _xdr_argument = xdr_kdb_last_t; + _xdr_result = xdr_kdb_incr_result_t; + local = (void *(*)()) iprop_get_updates_1_svc; + break; + + case IPROP_FULL_RESYNC: + _xdr_argument = xdr_void; + _xdr_result = xdr_kdb_fullresync_result_t; + local = (void *(*)()) iprop_full_resync_1_svc; + break; + + case IPROP_FULL_RESYNC_EXT: + _xdr_argument = xdr_u_int32; + _xdr_result = xdr_kdb_fullresync_result_t; + local = (void *(*)()) iprop_full_resync_ext_1_svc; + break; + + default: + krb5_klog_syslog(LOG_ERR, + _("RPC unknown request: %d (%s)"), + rqstp->rq_proc, whoami); + svcerr_noproc(transp); + return; + } + (void) memset(&argument, 0, sizeof (argument)); + if (!svc_getargs(transp, _xdr_argument, (caddr_t)&argument)) { + krb5_klog_syslog(LOG_ERR, + _("RPC svc_getargs failed (%s)"), + whoami); + svcerr_decode(transp); + return; + } + result = (*local)(&argument, rqstp); + + if (_xdr_result && result != NULL && + !svc_sendreply(transp, _xdr_result, result)) { + krb5_klog_syslog(LOG_ERR, + _("RPC svc_sendreply failed (%s)"), + whoami); + svcerr_systemerr(transp); + } + if (!svc_freeargs(transp, _xdr_argument, (caddr_t)&argument)) { + krb5_klog_syslog(LOG_ERR, + _("RPC svc_freeargs failed (%s)"), + whoami); + + exit(1); + } + + if (rqstp->rq_proc == IPROP_GET_UPDATES) { + /* LINTED */ + kdb_incr_result_t *r = (kdb_incr_result_t *)result; + + if (r->ret == UPDATE_OK) { + ulog_free_entries(r->updates.kdb_ulog_t_val, + r->updates.kdb_ulog_t_len); + r->updates.kdb_ulog_t_val = NULL; + r->updates.kdb_ulog_t_len = 0; + } + } + +} diff --git a/krb5-1.21.3/src/kadmin/server/kadm_rpc_svc.c b/krb5-1.21.3/src/kadmin/server/kadm_rpc_svc.c new file mode 100644 index 00000000..8371fa76 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/server/kadm_rpc_svc.c @@ -0,0 +1,363 @@ +/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + * + */ + +#include +#include +#include /* for gss_nt_krb5_name */ +#include +#include +#include +#include +#include +#include "misc.h" +#include "kadm5/server_internal.h" + +extern void *global_server_handle; + +static int check_rpcsec_auth(struct svc_req *); + +/* + * Function: kadm_1 + * + * Purpose: RPC processing procedure. + * originally generated from rpcgen + * + * Arguments: + * rqstp (input) rpc request structure + * transp (input) rpc transport structure + * (input/output) + * + * + * Requires: + * Effects: + * Modifies: + */ + +void kadm_1(rqstp, transp) + struct svc_req *rqstp; + SVCXPRT *transp; +{ + union { + cprinc_arg create_principal_2_arg; + dprinc_arg delete_principal_2_arg; + mprinc_arg modify_principal_2_arg; + rprinc_arg rename_principal_2_arg; + gprinc_arg get_principal_2_arg; + chpass_arg chpass_principal_2_arg; + chrand_arg chrand_principal_2_arg; + cpol_arg create_policy_2_arg; + dpol_arg delete_policy_2_arg; + mpol_arg modify_policy_2_arg; + gpol_arg get_policy_2_arg; + setkey_arg setkey_principal_2_arg; + cprinc3_arg create_principal3_2_arg; + chpass3_arg chpass_principal3_2_arg; + chrand3_arg chrand_principal3_2_arg; + setkey3_arg setkey_principal3_2_arg; + setkey4_arg setkey_principal4_2_arg; + getpkeys_arg get_principal_keys_2_arg; + } argument; + union { + generic_ret gen_ret; + gprinc_ret get_principal_2_ret; + chrand_ret chrand_principal_2_ret; + gpol_ret get_policy_2_ret; + getprivs_ret get_privs_2_ret; + gprincs_ret get_princs_2_ret; + gpols_ret get_pols_2_ret; + chrand_ret chrand_principal3_2_ret; + gstrings_ret get_string_2_ret; + getpkeys_ret get_principal_keys_ret; + } result; + bool_t retval; + bool_t (*xdr_argument)(), (*xdr_result)(); + bool_t (*local)(); + + if (rqstp->rq_cred.oa_flavor != AUTH_GSSAPI && + !check_rpcsec_auth(rqstp)) { + krb5_klog_syslog(LOG_ERR, "Authentication attempt failed: %s, " + "RPC authentication flavor %d", + client_addr(rqstp->rq_xprt), + rqstp->rq_cred.oa_flavor); + svcerr_weakauth(transp); + return; + } + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply(transp, xdr_void, (char *)NULL); + return; + + case CREATE_PRINCIPAL: + xdr_argument = xdr_cprinc_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) create_principal_2_svc; + break; + + case DELETE_PRINCIPAL: + xdr_argument = xdr_dprinc_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) delete_principal_2_svc; + break; + + case MODIFY_PRINCIPAL: + xdr_argument = xdr_mprinc_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) modify_principal_2_svc; + break; + + case RENAME_PRINCIPAL: + xdr_argument = xdr_rprinc_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) rename_principal_2_svc; + break; + + case GET_PRINCIPAL: + xdr_argument = xdr_gprinc_arg; + xdr_result = xdr_gprinc_ret; + local = (bool_t (*)()) get_principal_2_svc; + break; + + case GET_PRINCS: + xdr_argument = xdr_gprincs_arg; + xdr_result = xdr_gprincs_ret; + local = (bool_t (*)()) get_princs_2_svc; + break; + + case CHPASS_PRINCIPAL: + xdr_argument = xdr_chpass_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) chpass_principal_2_svc; + break; + + case SETKEY_PRINCIPAL: + xdr_argument = xdr_setkey_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) setkey_principal_2_svc; + break; + + case CHRAND_PRINCIPAL: + xdr_argument = xdr_chrand_arg; + xdr_result = xdr_chrand_ret; + local = (bool_t (*)()) chrand_principal_2_svc; + break; + + case CREATE_POLICY: + xdr_argument = xdr_cpol_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) create_policy_2_svc; + break; + + case DELETE_POLICY: + xdr_argument = xdr_dpol_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) delete_policy_2_svc; + break; + + case MODIFY_POLICY: + xdr_argument = xdr_mpol_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) modify_policy_2_svc; + break; + + case GET_POLICY: + xdr_argument = xdr_gpol_arg; + xdr_result = xdr_gpol_ret; + local = (bool_t (*)()) get_policy_2_svc; + break; + + case GET_POLS: + xdr_argument = xdr_gpols_arg; + xdr_result = xdr_gpols_ret; + local = (bool_t (*)()) get_pols_2_svc; + break; + + case GET_PRIVS: + xdr_argument = xdr_u_int32; + xdr_result = xdr_getprivs_ret; + local = (bool_t (*)()) get_privs_2_svc; + break; + + case INIT: + xdr_argument = xdr_u_int32; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) init_2_svc; + break; + + case CREATE_PRINCIPAL3: + xdr_argument = xdr_cprinc3_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) create_principal3_2_svc; + break; + + case CHPASS_PRINCIPAL3: + xdr_argument = xdr_chpass3_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) chpass_principal3_2_svc; + break; + + case CHRAND_PRINCIPAL3: + xdr_argument = xdr_chrand3_arg; + xdr_result = xdr_chrand_ret; + local = (bool_t (*)()) chrand_principal3_2_svc; + break; + + case SETKEY_PRINCIPAL3: + xdr_argument = xdr_setkey3_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) setkey_principal3_2_svc; + break; + + case PURGEKEYS: + xdr_argument = xdr_purgekeys_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) purgekeys_2_svc; + break; + + case GET_STRINGS: + xdr_argument = xdr_gstrings_arg; + xdr_result = xdr_gstrings_ret; + local = (bool_t (*)()) get_strings_2_svc; + break; + + case SET_STRING: + xdr_argument = xdr_sstring_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) set_string_2_svc; + break; + + case SETKEY_PRINCIPAL4: + xdr_argument = xdr_setkey4_arg; + xdr_result = xdr_generic_ret; + local = (bool_t (*)()) setkey_principal4_2_svc; + break; + + case EXTRACT_KEYS: + xdr_argument = xdr_getpkeys_arg; + xdr_result = xdr_getpkeys_ret; + local = (bool_t (*)()) get_principal_keys_2_svc; + break; + + default: + krb5_klog_syslog(LOG_ERR, "Invalid KADM5 procedure number: %s, %d", + client_addr(rqstp->rq_xprt), rqstp->rq_proc); + svcerr_noproc(transp); + return; + } + memset(&argument, 0, sizeof(argument)); + if (!svc_getargs(transp, xdr_argument, &argument)) { + svcerr_decode(transp); + return; + } + memset(&result, 0, sizeof(result)); + retval = (*local)(&argument, &result, rqstp); + if (retval && !svc_sendreply(transp, xdr_result, (void *)&result)) { + krb5_klog_syslog(LOG_ERR, "WARNING! Unable to send function results, " + "continuing."); + svcerr_systemerr(transp); + } + if (!svc_freeargs(transp, xdr_argument, &argument)) { + krb5_klog_syslog(LOG_ERR, "WARNING! Unable to free arguments, " + "continuing."); + } + if (!svc_freeargs(transp, xdr_result, &result)) { + krb5_klog_syslog(LOG_ERR, "WARNING! Unable to free results, " + "continuing."); + } + return; +} + +static int +check_rpcsec_auth(struct svc_req *rqstp) +{ + gss_ctx_id_t ctx; + krb5_context kctx; + OM_uint32 maj_stat, min_stat; + gss_name_t name; + krb5_principal princ; + int ret, success; + krb5_data *c1, *c2, *realm; + gss_buffer_desc gss_str; + kadm5_server_handle_t handle; + size_t slen; + char *sdots; + + success = 0; + handle = (kadm5_server_handle_t)global_server_handle; + + if (rqstp->rq_cred.oa_flavor != RPCSEC_GSS) + return 0; + + ctx = rqstp->rq_svccred; + + maj_stat = gss_inquire_context(&min_stat, ctx, NULL, &name, + NULL, NULL, NULL, NULL, NULL); + if (maj_stat != GSS_S_COMPLETE) { + krb5_klog_syslog(LOG_ERR, _("check_rpcsec_auth: failed " + "inquire_context, stat=%u"), maj_stat); + log_badauth(maj_stat, min_stat, rqstp->rq_xprt, NULL); + goto fail_name; + } + + kctx = handle->context; + ret = gss_to_krb5_name_1(rqstp, kctx, name, &princ, &gss_str); + if (ret == 0) + goto fail_name; + + slen = gss_str.length; + trunc_name(&slen, &sdots); + /* + * Since we accept with GSS_C_NO_NAME, the client can authenticate + * against the entire kdb. Therefore, ensure that the service + * name is something reasonable. + */ + if (krb5_princ_size(kctx, princ) != 2) + goto fail_princ; + + c1 = krb5_princ_component(kctx, princ, 0); + c2 = krb5_princ_component(kctx, princ, 1); + realm = krb5_princ_realm(kctx, princ); + success = data_eq_string(*realm, handle->params.realm) && + data_eq_string(*c1, "kadmin") && !data_eq_string(*c2, "history"); + +fail_princ: + if (!success) { + krb5_klog_syslog(LOG_ERR, _("bad service principal %.*s%s"), + (int) slen, (char *) gss_str.value, sdots); + } + gss_release_buffer(&min_stat, &gss_str); + krb5_free_principal(kctx, princ); +fail_name: + gss_release_name(&min_stat, &name); + return success; +} + +int +gss_to_krb5_name_1(struct svc_req *rqstp, krb5_context ctx, gss_name_t gss_name, + krb5_principal *princ, gss_buffer_t gss_str) +{ + OM_uint32 status, minor_stat; + gss_OID gss_type; + char *str; + int success; + + status = gss_display_name(&minor_stat, gss_name, gss_str, &gss_type); + if ((status != GSS_S_COMPLETE) || (gss_type != gss_nt_krb5_name)) { + krb5_klog_syslog(LOG_ERR, _("gss_to_krb5_name: failed display_name " + "status %d"), status); + log_badauth(status, minor_stat, rqstp->rq_xprt, NULL); + return 0; + } + str = malloc(gss_str->length +1); + if (str == NULL) + return 0; + *str = '\0'; + + strncat(str, gss_str->value, gss_str->length); + success = (krb5_parse_name(ctx, str, princ) == 0); + free(str); + return success; +} diff --git a/krb5-1.21.3/src/kadmin/server/misc.c b/krb5-1.21.3/src/kadmin/server/misc.c new file mode 100644 index 00000000..2d596e27 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/server/misc.c @@ -0,0 +1,175 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + */ + +#include +#include +#include +#include "misc.h" +#include "auth.h" +#include "net-server.h" +kadm5_ret_t +schpw_util_wrapper(void *server_handle, + krb5_principal client, + krb5_principal target, + krb5_boolean initial_flag, + char *new_pw, char **ret_pw, + char *msg_ret, unsigned int msg_len) +{ + kadm5_ret_t ret; + kadm5_server_handle_t handle = server_handle; + + /* + * If no target is explicitly provided, then the target principal + * is the client principal. + */ + if (target == NULL) + target = client; + + /* If the client is changing its own password, require it to use an initial + * ticket, and enforce the policy min_life. */ + if (krb5_principal_compare(handle->context, client, target)) { + if (!initial_flag) { + strlcpy(msg_ret, "Ticket must be derived from a password", + msg_len); + return KADM5_AUTH_INITIAL; + } + + ret = check_min_life(server_handle, target, msg_ret, msg_len); + if (ret != 0) + return ret; + } + + if (auth(handle->context, OP_CPW, client, target, + NULL, NULL, NULL, NULL, 0)) { + ret = kadm5_chpass_principal_util(server_handle, + target, + new_pw, ret_pw, + msg_ret, msg_len); + } else { + ret = KADM5_AUTH_CHANGEPW; + strlcpy(msg_ret, "Unauthorized request", msg_len); + } + + return ret; +} + +kadm5_ret_t +check_min_life(void *server_handle, krb5_principal principal, + char *msg_ret, unsigned int msg_len) +{ + krb5_timestamp now; + kadm5_ret_t ret; + kadm5_policy_ent_rec pol; + kadm5_principal_ent_rec princ; + kadm5_server_handle_t handle = server_handle; + + if (msg_ret != NULL) + *msg_ret = '\0'; + + ret = krb5_timeofday(handle->context, &now); + if (ret) + return ret; + + ret = kadm5_get_principal(handle->lhandle, principal, + &princ, KADM5_PRINCIPAL_NORMAL_MASK); + if(ret) + return ret; + if(princ.aux_attributes & KADM5_POLICY) { + /* Look up the policy. If it doesn't exist, treat this principal as if + * it had no policy. */ + if((ret=kadm5_get_policy(handle->lhandle, + princ.policy, &pol)) != KADM5_OK) { + (void) kadm5_free_principal_ent(handle->lhandle, &princ); + return (ret == KADM5_UNK_POLICY) ? 0 : ret; + } + if(ts_delta(now, princ.last_pwd_change) < pol.pw_min_life && + !(princ.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) { + if (msg_ret != NULL) { + time_t until; + char *time_string, *ptr; + const char *errstr; + + until = princ.last_pwd_change + pol.pw_min_life; + + time_string = ctime(&until); + if (time_string == NULL) + time_string = "(error)"; + errstr = error_message(CHPASS_UTIL_PASSWORD_TOO_SOON); + + if (strlen(errstr) + strlen(time_string) < msg_len) { + if (*(ptr = &time_string[strlen(time_string)-1]) == '\n') + *ptr = '\0'; + snprintf(msg_ret, msg_len, errstr, time_string); + } + } + + (void) kadm5_free_policy_ent(handle->lhandle, &pol); + (void) kadm5_free_principal_ent(handle->lhandle, &princ); + return KADM5_PASS_TOOSOON; + } + + ret = kadm5_free_policy_ent(handle->lhandle, &pol); + if (ret) { + (void) kadm5_free_principal_ent(handle->lhandle, &princ); + return ret; + } + } + + return kadm5_free_principal_ent(handle->lhandle, &princ); +} + +#define MAXPRINCLEN 125 + +void +trunc_name(size_t *len, char **dots) +{ + *dots = *len > MAXPRINCLEN ? "..." : ""; + *len = *len > MAXPRINCLEN ? MAXPRINCLEN : *len; +} + +krb5_error_code +make_toolong_error (void *handle, krb5_data **out) +{ + krb5_error errpkt; + krb5_error_code retval; + krb5_data *scratch; + kadm5_server_handle_t server_handle = *(void **)handle; + + retval = krb5_us_timeofday(server_handle->context, &errpkt.stime, &errpkt.susec); + if (retval) + return retval; + errpkt.error = KRB_ERR_FIELD_TOOLONG; + retval = krb5_build_principal(server_handle->context, &errpkt.server, + strlen(server_handle->params.realm), + server_handle->params.realm, + "kadmin", "changepw", NULL); + if (retval) + return retval; + errpkt.client = NULL; + errpkt.cusec = 0; + errpkt.ctime = 0; + errpkt.text.length = 0; + errpkt.text.data = 0; + errpkt.e_data.length = 0; + errpkt.e_data.data = 0; + scratch = malloc(sizeof(*scratch)); + if (scratch == NULL) + return ENOMEM; + retval = krb5_mk_error(server_handle->context, &errpkt, scratch); + if (retval) { + free(scratch); + return retval; + } + + *out = scratch; + return 0; +} + +krb5_context get_context(void *handle) +{ + kadm5_server_handle_t server_handle = *(void **)handle; + return server_handle->context; +} diff --git a/krb5-1.21.3/src/kadmin/server/misc.h b/krb5-1.21.3/src/kadmin/server/misc.h new file mode 100644 index 00000000..3a112a0b --- /dev/null +++ b/krb5-1.21.3/src/kadmin/server/misc.h @@ -0,0 +1,54 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1994 OpenVision Technologies, Inc., All Rights Reserved + * + */ + +#ifndef _MISC_H +#define _MISC_H 1 + +#include "net-server.h" /* for krb5_fulladdr */ + +int +setup_gss_names(struct svc_req *, gss_buffer_desc *, + gss_buffer_desc *); + +kadm5_ret_t +schpw_util_wrapper(void *server_handle, krb5_principal client, + krb5_principal target, krb5_boolean initial_flag, + char *new_pw, char **ret_pw, + char *msg_ret, unsigned int msg_len); + +kadm5_ret_t check_min_life(void *server_handle, krb5_principal principal, + char *msg_ret, unsigned int msg_len); + +void kadm_1(struct svc_req *, SVCXPRT *); +void krb5_iprop_prog_1(struct svc_req *, SVCXPRT *); + +void trunc_name(size_t *len, char **dots); + +int +gss_to_krb5_name_1(struct svc_req *rqstp, krb5_context ctx, gss_name_t gss_name, + krb5_principal *princ, gss_buffer_t gss_str); + + +void reset_db(void); + +void log_badauth(OM_uint32 major, OM_uint32 minor, SVCXPRT *xprt, char *data); + +const char *client_addr(SVCXPRT *xprt); + +/* network.c */ +#include "net-server.h" + + +void +krb5_iprop_prog_1(struct svc_req *rqstp, SVCXPRT *transp); + +kadm5_ret_t +kiprop_get_adm_host_srv_name(krb5_context, + const char *, + char **); + + +#endif /* _MISC_H */ diff --git a/krb5-1.21.3/src/kadmin/server/ovsec_kadmd.c b/krb5-1.21.3/src/kadmin/server/ovsec_kadmd.c new file mode 100644 index 00000000..b29a0f5b --- /dev/null +++ b/krb5-1.21.3/src/kadmin/server/ovsec_kadmd.c @@ -0,0 +1,562 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef _AIX +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include "gssapiP_krb5.h" /* for kg_get_context */ +#include +#include +#include +#include +#include "kdb_kt.h" /* for krb5_ktkdb_set_context */ +#include +#include + +#include "misc.h" +#include "auth.h" + +#if defined(NEED_DAEMON_PROTO) +int daemon(int, int); +#endif + +#define TIMEOUT 15 + +gss_name_t gss_changepw_name = NULL, gss_oldchangepw_name = NULL; +void *global_server_handle; +int nofork = 0; +char *kdb5_util = KPROPD_DEFAULT_KDB5_UTIL; +char *kprop = KPROPD_DEFAULT_KPROP; +char *dump_file = KPROP_DEFAULT_FILE; +char *kprop_port = NULL; + +static krb5_context context; +static char *progname; + +static void +usage() +{ + fprintf(stderr, _("Usage: kadmind [-x db_args]* [-r realm] [-m] [-nofork] " + "[-port port-number]\n" + "\t\t[-proponly] [-p path-to-kdb5_util] [-F dump-file]\n" + "\t\t[-K path-to-kprop] [-k kprop-port] [-P pid_file]\n" + "\nwhere,\n\t[-x db_args]* - any number of database " + "specific arguments.\n" + "\t\t\tLook at each database documentation for " + "supported arguments\n")); + exit(1); +} + +/* + * Output a message to stderr and the admin server log, and exit with status 1. + * msg should not be punctuated. If code is given, msg should indicate what + * operation was taking place in the present progressive. Otherwise msg should + * be capitalized and should indicate what went wrong. + */ +static void +fail_to_start(krb5_error_code code, const char *msg) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(context, code); + fprintf(stderr, _("%s: %s while %s, aborting\n"), progname, errmsg, + msg); + krb5_klog_syslog(LOG_ERR, _("%s while %s, aborting\n"), errmsg, msg); + } else { + fprintf(stderr, _("%s: %s, aborting\n"), progname, msg); + krb5_klog_syslog(LOG_ERR, _("%s, aborting"), msg); + } + exit(1); +} + +static int +write_pid_file(const char *pid_file) +{ + FILE *file; + unsigned long pid; + int st1, st2; + + file = fopen(pid_file, "w"); + if (file == NULL) + return errno; + pid = (unsigned long)getpid(); + st1 = (fprintf(file, "%ld\n", pid) < 0) ? errno : 0; + st2 = (fclose(file) == EOF) ? errno : 0; + return st1 ? st1 : st2; +} + +/* Set up the main loop. If proponly is set, don't set up ports for kpasswd or + * kadmin. May set *ctx_out even on error. */ +static krb5_error_code +setup_loop(kadm5_config_params *params, int proponly, verto_ctx **ctx_out) +{ + krb5_error_code ret; + verto_ctx *ctx; + + *ctx_out = ctx = loop_init(VERTO_EV_TYPE_SIGNAL); + if (ctx == NULL) + return ENOMEM; + ret = loop_setup_signals(ctx, &global_server_handle, NULL); + if (ret) + return ret; + if (!proponly) { + ret = loop_add_udp_address(params->kpasswd_port, + params->kpasswd_listen); + if (ret) + return ret; + ret = loop_add_tcp_address(params->kpasswd_port, + params->kpasswd_listen); + if (ret) + return ret; + ret = loop_add_rpc_service(params->kadmind_port, + params->kadmind_listen, + KADM, KADMVERS, kadm_1); + if (ret) + return ret; + } +#ifndef DISABLE_IPROP + if (params->iprop_enabled) { + ret = loop_add_rpc_service(params->iprop_port, params->iprop_listen, + KRB5_IPROP_PROG, KRB5_IPROP_VERS, + krb5_iprop_prog_1); + if (ret) + return ret; + } +#endif + return loop_setup_network(ctx, &global_server_handle, progname, + DEFAULT_TCP_LISTEN_BACKLOG); +} + +/* Point GSSAPI at the KDB keytab so we don't need an actual file keytab. */ +static krb5_error_code +setup_kdb_keytab() +{ + krb5_error_code ret; + + ret = krb5_ktkdb_set_context(context); + if (ret) + return ret; + ret = krb5_db_register_keytab(context); + if (ret) + return ret; + return krb5_gss_register_acceptor_identity("KDB:"); +} + + +/* Return "name@realm". */ +static char * +build_princ_name(char *name, char *realm) +{ + char *fullname; + + if (asprintf(&fullname, "%s@%s", name, realm) < 0) + return NULL; + return fullname; +} + +/* Callback from GSSRPC for garbled/forged/replayed/etc messages. */ +static void +log_badverf(gss_name_t client_name, gss_name_t server_name, + struct svc_req *rqst, struct rpc_msg *msg, char *data) +{ + static const struct { + rpcproc_t proc; + const char *proc_name; + } proc_names[] = { + {1, "CREATE_PRINCIPAL"}, + {2, "DELETE_PRINCIPAL"}, + {3, "MODIFY_PRINCIPAL"}, + {4, "RENAME_PRINCIPAL"}, + {5, "GET_PRINCIPAL"}, + {6, "CHPASS_PRINCIPAL"}, + {7, "CHRAND_PRINCIPAL"}, + {8, "CREATE_POLICY"}, + {9, "DELETE_POLICY"}, + {10, "MODIFY_POLICY"}, + {11, "GET_POLICY"}, + {12, "GET_PRIVS"}, + {13, "INIT"}, + {14, "GET_PRINCS"}, + {15, "GET_POLS"}, + {16, "SETKEY_PRINCIPAL"}, + /* 17 was "SETV4KEY_PRINCIPAL" */ + {18, "CREATE_PRINCIPAL3"}, + {19, "CHPASS_PRINCIPAL3"}, + {20, "CHRAND_PRINCIPAL3"}, + {21, "SETKEY_PRINCIPAL3"}, + {22, "PURGEKEYS"}, + {23, "GET_STRINGS"}, + {24, "SET_STRING"} + }; + OM_uint32 minor; + gss_buffer_desc client, server; + gss_OID gss_type; + const char *a; + rpcproc_t proc; + unsigned int i; + const char *procname; + size_t clen, slen; + char *cdots, *sdots; + + client.length = 0; + client.value = NULL; + server.length = 0; + server.value = NULL; + + (void)gss_display_name(&minor, client_name, &client, &gss_type); + (void)gss_display_name(&minor, server_name, &server, &gss_type); + if (client.value == NULL) { + client.value = "(null)"; + clen = sizeof("(null)") - 1; + } else { + clen = client.length; + } + trunc_name(&clen, &cdots); + if (server.value == NULL) { + server.value = "(null)"; + slen = sizeof("(null)") - 1; + } else { + slen = server.length; + } + trunc_name(&slen, &sdots); + a = client_addr(rqst->rq_xprt); + + proc = msg->rm_call.cb_proc; + procname = NULL; + for (i = 0; i < sizeof(proc_names) / sizeof(*proc_names); i++) { + if (proc_names[i].proc == proc) { + procname = proc_names[i].proc_name; + break; + } + } + if (procname != NULL) { + krb5_klog_syslog(LOG_NOTICE, + _("WARNING! Forged/garbled request: %s, claimed " + "client = %.*s%s, server = %.*s%s, addr = %s"), + procname, (int)clen, (char *)client.value, cdots, + (int)slen, (char *)server.value, sdots, a); + } else { + krb5_klog_syslog(LOG_NOTICE, + _("WARNING! Forged/garbled request: %d, claimed " + "client = %.*s%s, server = %.*s%s, addr = %s"), + proc, (int)clen, (char *)client.value, cdots, + (int)slen, (char *)server.value, sdots, a); + } + + (void)gss_release_buffer(&minor, &client); + (void)gss_release_buffer(&minor, &server); +} + +/* Callback from GSSRPC for miscellaneous errors */ +static void +log_miscerr(struct svc_req *rqst, struct rpc_msg *msg, char *error, char *data) +{ + krb5_klog_syslog(LOG_NOTICE, _("Miscellaneous RPC error: %s, %s"), + client_addr(rqst->rq_xprt), error); +} + +static void +log_badauth_display_status_1(char *m, OM_uint32 code, int type) +{ + OM_uint32 gssstat, minor_stat; + gss_buffer_desc msg; + OM_uint32 msg_ctx; + + msg_ctx = 0; + while (1) { + gssstat = gss_display_status(&minor_stat, code, type, GSS_C_NULL_OID, + &msg_ctx, &msg); + if (gssstat != GSS_S_COMPLETE) { + krb5_klog_syslog(LOG_ERR, _("%s Cannot decode status %d"), m, + (int)code); + return; + } + + krb5_klog_syslog(LOG_NOTICE, "%s %.*s", m, (int)msg.length, + (char *)msg.value); + (void)gss_release_buffer(&minor_stat, &msg); + + if (!msg_ctx) + break; + } +} + +/* Callback from GSSRPC for authentication failures */ +void +log_badauth(OM_uint32 major, OM_uint32 minor, SVCXPRT *xprt, char *data) +{ + krb5_klog_syslog(LOG_NOTICE, _("Authentication attempt failed: %s, " + "GSS-API error strings are:"), + client_addr(xprt)); + log_badauth_display_status_1(" ", major, GSS_C_GSS_CODE); + log_badauth_display_status_1(" ", minor, GSS_C_MECH_CODE); + krb5_klog_syslog(LOG_NOTICE, _(" GSS-API error strings complete.")); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor_status; + gss_buffer_desc in_buf; + gss_OID nt_krb5_name_oid = (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME; + auth_gssapi_name names[4]; + kadm5_config_params params; + verto_ctx *vctx; + const char *pid_file = NULL; + char **db_args = NULL, **tmpargs; + const char *acl_file; + int ret, i, db_args_size = 0, proponly = 0; + + setlocale(LC_ALL, ""); + setvbuf(stderr, NULL, _IONBF, 0); + + names[0].name = names[1].name = names[2].name = names[3].name = NULL; + names[0].type = names[1].type = names[2].type = names[3].type = + nt_krb5_name_oid; + + progname = (strrchr(argv[0], '/') != NULL) ? strrchr(argv[0], '/') + 1 : + argv[0]; + + memset(¶ms, 0, sizeof(params)); + + argc--, argv++; + while (argc) { + if (strcmp(*argv, "-x") == 0) { + argc--, argv++; + if (!argc) + usage(); + db_args_size++; + tmpargs = realloc(db_args, sizeof(char *) * (db_args_size + 1)); + if (tmpargs == NULL) { + fprintf(stderr, _("%s: cannot initialize. Not enough " + "memory\n"), progname); + exit(1); + } + db_args = tmpargs; + db_args[db_args_size - 1] = *argv; + db_args[db_args_size] = NULL; + } else if (strcmp(*argv, "-r") == 0) { + argc--, argv++; + if (!argc) + usage(); + params.realm = *argv; + params.mask |= KADM5_CONFIG_REALM; + argc--, argv++; + continue; + } else if (strcmp(*argv, "-m") == 0) { + params.mkey_from_kbd = 1; + params.mask |= KADM5_CONFIG_MKEY_FROM_KBD; + } else if (strcmp(*argv, "-nofork") == 0) { + nofork = 1; +#ifndef DISABLE_IPROP + } else if (strcmp(*argv, "-proponly") == 0) { + proponly = 1; +#endif + } else if (strcmp(*argv, "-port") == 0) { + argc--, argv++; + if (!argc) + usage(); + params.kadmind_port = atoi(*argv); + params.mask |= KADM5_CONFIG_KADMIND_PORT; + } else if (strcmp(*argv, "-P") == 0) { + argc--, argv++; + if (!argc) + usage(); + pid_file = *argv; + } else if (strcmp(*argv, "-W") == 0) { + /* Ignore (deprecated weak random option). */ + } else if (strcmp(*argv, "-p") == 0) { + argc--, argv++; + if (!argc) + usage(); + kdb5_util = *argv; + } else if (strcmp(*argv, "-F") == 0) { + argc--, argv++; + if (!argc) + usage(); + dump_file = *argv; + } else if (strcmp(*argv, "-K") == 0) { + argc--, argv++; + if (!argc) + usage(); + kprop = *argv; + } else if (strcmp(*argv, "-k") == 0) { + argc--, argv++; + if (!argc) + usage(); + kprop_port = *argv; + } else { + break; + } + argc--, argv++; + } + + if (argc != 0) + usage(); + + ret = kadm5_init_krb5_context(&context); + if (ret) { + fprintf(stderr, _("%s: %s while initializing context, aborting\n"), + progname, error_message(ret)); + exit(1); + } + + krb5_klog_init(context, "admin_server", progname, 1); + + ret = kadm5_init(context, "kadmind", NULL, NULL, ¶ms, + KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, db_args, + &global_server_handle); + if (ret) + fail_to_start(ret, _("initializing")); + + ret = kadm5_get_config_params(context, 1, ¶ms, ¶ms); + if (ret) + fail_to_start(ret, _("getting config parameters")); + if (!(params.mask & KADM5_CONFIG_REALM)) + fail_to_start(0, _("Missing required realm configuration")); + if (!(params.mask & KADM5_CONFIG_ACL_FILE)) + fail_to_start(0, _("Missing required ACL file configuration")); + if (proponly && !params.iprop_enabled) { + fail_to_start(0, _("-proponly can only be used when " + "iprop_enable is true")); + } + + ret = setup_loop(¶ms, proponly, &vctx); + if (ret) + fail_to_start(ret, _("initializing network")); + + names[0].name = build_princ_name(KADM5_ADMIN_SERVICE, params.realm); + names[1].name = build_princ_name(KADM5_CHANGEPW_SERVICE, params.realm); + if (names[0].name == NULL || names[1].name == NULL) + fail_to_start(0, _("Cannot build GSSAPI auth names")); + + ret = setup_kdb_keytab(); + if (ret) + fail_to_start(0, _("Cannot set up KDB keytab")); + + if (svcauth_gssapi_set_names(names, 2) == FALSE) + fail_to_start(0, _("Cannot set GSSAPI authentication names")); + + /* if set_names succeeded, this will too */ + in_buf.value = names[1].name; + in_buf.length = strlen(names[1].name) + 1; + (void)gss_import_name(&minor_status, &in_buf, nt_krb5_name_oid, + &gss_changepw_name); + + svcauth_gssapi_set_log_badauth2_func(log_badauth, NULL); + svcauth_gssapi_set_log_badverf_func(log_badverf, NULL); + svcauth_gssapi_set_log_miscerr_func(log_miscerr, NULL); + + svcauth_gss_set_log_badauth2_func(log_badauth, NULL); + svcauth_gss_set_log_badverf_func(log_badverf, NULL); + svcauth_gss_set_log_miscerr_func(log_miscerr, NULL); + + if (svcauth_gss_set_svc_name(GSS_C_NO_NAME) != TRUE) + fail_to_start(0, _("Cannot initialize GSSAPI service name")); + + acl_file = (*params.acl_file != '\0') ? params.acl_file : NULL; + ret = auth_init(context, acl_file); + if (ret) + fail_to_start(ret, _("initializing ACL file")); + + /* Since some KDB modules are not fork-safe, we must reinitialize the + * server handle after daemonizing. */ + kadm5_destroy(global_server_handle); + global_server_handle = NULL; + + if (!nofork && daemon(0, 0) != 0) + fail_to_start(errno, _("spawning daemon process")); + if (pid_file != NULL) { + ret = write_pid_file(pid_file); + if (ret) + fail_to_start(ret, _("creating PID file")); + } + + ret = kadm5_init(context, "kadmind", NULL, NULL, ¶ms, + KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, db_args, + &global_server_handle); + if (ret) + fail_to_start(ret, _("initializing")); + + if (params.iprop_enabled == TRUE) { + ulog_set_role(context, IPROP_PRIMARY); + + ret = ulog_map(context, params.iprop_logfile, params.iprop_ulogsize); + if (ret) + fail_to_start(ret, _("mapping update log")); + + if (nofork) { + fprintf(stderr, + _("%s: create IPROP svc (PROG=%d, VERS=%d)\n"), + progname, KRB5_IPROP_PROG, KRB5_IPROP_VERS); + } + } + + if (kprop_port == NULL) + kprop_port = getenv("KPROP_PORT"); + + krb5_klog_syslog(LOG_INFO, _("starting")); + if (nofork) + fprintf(stderr, _("%s: starting...\n"), progname); + + verto_run(vctx); + krb5_klog_syslog(LOG_INFO, _("finished, exiting")); + + /* Clean up memory, etc */ + svcauth_gssapi_unset_names(); + kadm5_destroy(global_server_handle); + loop_free(vctx); + auth_fini(context); + (void)gss_release_name(&minor_status, &gss_changepw_name); + (void)gss_release_name(&minor_status, &gss_oldchangepw_name); + for (i = 0; i < 4; i++) + free(names[i].name); + + krb5_klog_close(context); + krb5_free_context(context); + exit(0); +} diff --git a/krb5-1.21.3/src/kadmin/server/schpw.c b/krb5-1.21.3/src/kadmin/server/schpw.c new file mode 100644 index 00000000..00465657 --- /dev/null +++ b/krb5-1.21.3/src/kadmin/server/schpw.c @@ -0,0 +1,469 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include "k5-int.h" +#include +#include +#include /* krb5_klog_syslog */ +#include +#include + +#include "kadm5/server_internal.h" /* XXX for kadm5_server_handle_t */ + +#include "misc.h" + +#ifndef GETSOCKNAME_ARG3_TYPE +#define GETSOCKNAME_ARG3_TYPE int +#endif + +#define RFC3244_VERSION 0xff80 + +static krb5_error_code +process_chpw_request(krb5_context context, void *server_handle, char *realm, + krb5_keytab keytab, const krb5_fulladdr *local_addr, + const krb5_fulladdr *remote_addr, krb5_data *req, + krb5_data *rep) +{ + krb5_error_code ret; + char *ptr; + unsigned int plen, vno; + krb5_data ap_req, ap_rep = empty_data(); + krb5_data cipher = empty_data(), clear = empty_data(); + krb5_auth_context auth_context = NULL; + krb5_principal changepw = NULL; + krb5_principal client, target = NULL; + krb5_ticket *ticket = NULL; + krb5_replay_data replay; + krb5_error krberror; + int numresult; + char strresult[1024]; + char *clientstr = NULL, *targetstr = NULL; + const char *errmsg = NULL; + size_t clen; + char *cdots; + struct sockaddr_storage ss; + socklen_t salen; + char addrbuf[100]; + krb5_address *addr = remote_addr->address; + + *rep = empty_data(); + + if (req->length < 4) { + /* either this, or the server is printing bad messages, + or the caller passed in garbage */ + ret = KRB5KRB_AP_ERR_MODIFIED; + numresult = KRB5_KPASSWD_MALFORMED; + strlcpy(strresult, "Request was truncated", sizeof(strresult)); + goto bailout; + } + + ptr = req->data; + + /* verify length */ + + plen = (*ptr++ & 0xff); + plen = (plen<<8) | (*ptr++ & 0xff); + + if (plen != req->length) { + ret = KRB5KRB_AP_ERR_MODIFIED; + numresult = KRB5_KPASSWD_MALFORMED; + strlcpy(strresult, "Request length was inconsistent", + sizeof(strresult)); + goto bailout; + } + + /* verify version number */ + + vno = (*ptr++ & 0xff) ; + vno = (vno<<8) | (*ptr++ & 0xff); + + if (vno != 1 && vno != RFC3244_VERSION) { + ret = KRB5KDC_ERR_BAD_PVNO; + numresult = KRB5_KPASSWD_BAD_VERSION; + snprintf(strresult, sizeof(strresult), + "Request contained unknown protocol version number %d", vno); + goto bailout; + } + + /* read, check ap-req length */ + + ap_req.length = (*ptr++ & 0xff); + ap_req.length = (ap_req.length<<8) | (*ptr++ & 0xff); + + if (ptr + ap_req.length >= req->data + req->length) { + ret = KRB5KRB_AP_ERR_MODIFIED; + numresult = KRB5_KPASSWD_MALFORMED; + strlcpy(strresult, "Request was truncated in AP-REQ", + sizeof(strresult)); + goto bailout; + } + + /* verify ap_req */ + + ap_req.data = ptr; + ptr += ap_req.length; + + ret = krb5_auth_con_init(context, &auth_context); + if (ret) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, "Failed initializing auth context", + sizeof(strresult)); + goto chpwfail; + } + + ret = krb5_auth_con_setflags(context, auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE); + if (ret) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, "Failed initializing auth context", + sizeof(strresult)); + goto chpwfail; + } + + ret = krb5_build_principal(context, &changepw, strlen(realm), realm, + "kadmin", "changepw", NULL); + if (ret) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, "Failed building kadmin/changepw principal", + sizeof(strresult)); + goto chpwfail; + } + + ret = krb5_rd_req(context, &auth_context, &ap_req, changepw, keytab, + NULL, &ticket); + + if (ret) { + numresult = KRB5_KPASSWD_AUTHERROR; + strlcpy(strresult, "Failed reading application request", + sizeof(strresult)); + goto chpwfail; + } + + /* construct the ap-rep */ + + ret = krb5_mk_rep(context, auth_context, &ap_rep); + if (ret) { + numresult = KRB5_KPASSWD_AUTHERROR; + strlcpy(strresult, "Failed replying to application request", + sizeof(strresult)); + goto chpwfail; + } + + /* decrypt the ChangePasswdData */ + + cipher.length = (req->data + req->length) - ptr; + cipher.data = ptr; + + /* + * Don't set a remote address in auth_context before calling krb5_rd_priv, + * so that we can work against clients behind a NAT. Reflection attacks + * aren't a concern since we use sequence numbers and since our requests + * don't look anything like our responses. Also don't set a local address, + * since we don't know what interface the request was received on. + */ + + ret = krb5_rd_priv(context, auth_context, &cipher, &clear, &replay); + if (ret) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, "Failed decrypting request", sizeof(strresult)); + goto chpwfail; + } + + client = ticket->enc_part2->client; + + /* decode ChangePasswdData for setpw requests */ + if (vno == RFC3244_VERSION) { + krb5_data *clear_data; + + ret = decode_krb5_setpw_req(&clear, &clear_data, &target); + if (ret != 0) { + numresult = KRB5_KPASSWD_MALFORMED; + strlcpy(strresult, "Failed decoding ChangePasswdData", + sizeof(strresult)); + goto chpwfail; + } + + zapfree(clear.data, clear.length); + + clear = *clear_data; + free(clear_data); + + if (target != NULL) { + ret = krb5_unparse_name(context, target, &targetstr); + if (ret != 0) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, "Failed unparsing target name for log", + sizeof(strresult)); + goto chpwfail; + } + } + } + + ret = krb5_unparse_name(context, client, &clientstr); + if (ret) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, "Failed unparsing client name for log", + sizeof(strresult)); + goto chpwfail; + } + + /* change the password */ + + ptr = k5memdup0(clear.data, clear.length, &ret); + ret = schpw_util_wrapper(server_handle, client, target, + (ticket->enc_part2->flags & TKT_FLG_INITIAL) != 0, + ptr, NULL, strresult, sizeof(strresult)); + if (ret) + errmsg = krb5_get_error_message(context, ret); + + /* zap the password */ + zapfree(clear.data, clear.length); + zapfree(ptr, clear.length); + clear = empty_data(); + + clen = strlen(clientstr); + trunc_name(&clen, &cdots); + + switch (addr->addrtype) { + case ADDRTYPE_INET: { + struct sockaddr_in *sin = ss2sin(&ss); + + sin->sin_family = AF_INET; + memcpy(&sin->sin_addr, addr->contents, addr->length); + sin->sin_port = htons(remote_addr->port); + salen = sizeof(*sin); + break; + } + case ADDRTYPE_INET6: { + struct sockaddr_in6 *sin6 = ss2sin6(&ss); + + sin6->sin6_family = AF_INET6; + memcpy(&sin6->sin6_addr, addr->contents, addr->length); + sin6->sin6_port = htons(remote_addr->port); + salen = sizeof(*sin6); + break; + } + default: { + struct sockaddr *sa = ss2sa(&ss); + + sa->sa_family = AF_UNSPEC; + salen = sizeof(*sa); + break; + } + } + + if (getnameinfo(ss2sa(&ss), salen, + addrbuf, sizeof(addrbuf), NULL, 0, + NI_NUMERICHOST | NI_NUMERICSERV) != 0) + strlcpy(addrbuf, "", sizeof(addrbuf)); + + if (vno == RFC3244_VERSION) { + size_t tlen; + char *tdots; + const char *targetp; + + if (target == NULL) { + tlen = clen; + tdots = cdots; + targetp = targetstr; + } else { + tlen = strlen(targetstr); + trunc_name(&tlen, &tdots); + targetp = clientstr; + } + + krb5_klog_syslog(LOG_NOTICE, _("setpw request from %s by %.*s%s for " + "%.*s%s: %s"), addrbuf, (int) clen, + clientstr, cdots, (int) tlen, targetp, tdots, + errmsg ? errmsg : "success"); + } else { + krb5_klog_syslog(LOG_NOTICE, _("chpw request from %s for %.*s%s: %s"), + addrbuf, (int) clen, clientstr, cdots, + errmsg ? errmsg : "success"); + } + switch (ret) { + case KADM5_AUTH_CHANGEPW: + numresult = KRB5_KPASSWD_ACCESSDENIED; + break; + case KADM5_AUTH_INITIAL: + numresult = KRB5_KPASSWD_INITIAL_FLAG_NEEDED; + break; + case KADM5_PASS_Q_TOOSHORT: + case KADM5_PASS_REUSE: + case KADM5_PASS_Q_CLASS: + case KADM5_PASS_Q_DICT: + case KADM5_PASS_Q_GENERIC: + case KADM5_PASS_TOOSOON: + numresult = KRB5_KPASSWD_SOFTERROR; + break; + case 0: + numresult = KRB5_KPASSWD_SUCCESS; + strlcpy(strresult, "", sizeof(strresult)); + break; + default: + numresult = KRB5_KPASSWD_HARDERROR; + break; + } + +chpwfail: + + ret = alloc_data(&clear, 2 + strlen(strresult)); + if (ret) + goto bailout; + + ptr = clear.data; + + *ptr++ = (numresult>>8) & 0xff; + *ptr++ = numresult & 0xff; + + memcpy(ptr, strresult, strlen(strresult)); + + cipher = empty_data(); + + if (ap_rep.length) { + ret = krb5_auth_con_setaddrs(context, auth_context, + local_addr->address, NULL); + if (ret) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, + "Failed storing client and server internet addresses", + sizeof(strresult)); + } else { + ret = krb5_mk_priv(context, auth_context, &clear, &cipher, + &replay); + if (ret) { + numresult = KRB5_KPASSWD_HARDERROR; + strlcpy(strresult, "Failed encrypting reply", + sizeof(strresult)); + } + } + } + + /* if no KRB-PRIV was constructed, then we need a KRB-ERROR. + if this fails, just bail. there's nothing else we can do. */ + + if (cipher.length == 0) { + /* clear out ap_rep now, so that it won't be inserted in the + reply */ + + if (ap_rep.length) { + free(ap_rep.data); + ap_rep = empty_data(); + } + + krberror.ctime = 0; + krberror.cusec = 0; + krberror.susec = 0; + ret = krb5_timeofday(context, &krberror.stime); + if (ret) + goto bailout; + + /* this is really icky. but it's what all the other callers + to mk_error do. */ + krberror.error = ret; + krberror.error -= ERROR_TABLE_BASE_krb5; + if (krberror.error > KRB_ERR_MAX) + krberror.error = KRB_ERR_GENERIC; + + krberror.client = NULL; + + ret = krb5_build_principal(context, &krberror.server, + strlen(realm), realm, + "kadmin", "changepw", NULL); + if (ret) + goto bailout; + krberror.text.length = 0; + krberror.e_data = clear; + + ret = krb5_mk_error(context, &krberror, &cipher); + + krb5_free_principal(context, krberror.server); + + if (ret) + goto bailout; + } + + /* construct the reply */ + + ret = alloc_data(rep, 6 + ap_rep.length + cipher.length); + if (ret) + goto bailout; + ptr = rep->data; + + /* length */ + + *ptr++ = (rep->length>>8) & 0xff; + *ptr++ = rep->length & 0xff; + + /* version == 0x0001 big-endian */ + + *ptr++ = 0; + *ptr++ = 1; + + /* ap_rep length, big-endian */ + + *ptr++ = (ap_rep.length>>8) & 0xff; + *ptr++ = ap_rep.length & 0xff; + + /* ap-rep data */ + + if (ap_rep.length) { + memcpy(ptr, ap_rep.data, ap_rep.length); + ptr += ap_rep.length; + } + + /* krb-priv or krb-error */ + + memcpy(ptr, cipher.data, cipher.length); + +bailout: + krb5_auth_con_free(context, auth_context); + krb5_free_principal(context, changepw); + krb5_free_ticket(context, ticket); + free(ap_rep.data); + free(clear.data); + free(cipher.data); + krb5_free_principal(context, target); + krb5_free_unparsed_name(context, targetstr); + krb5_free_unparsed_name(context, clientstr); + krb5_free_error_message(context, errmsg); + return ret; +} + +/* Dispatch routine for set/change password */ +void +dispatch(void *handle, const krb5_fulladdr *local_addr, + const krb5_fulladdr *remote_addr, krb5_data *request, int is_tcp, + verto_ctx *vctx, loop_respond_fn respond, void *arg) +{ + krb5_error_code ret; + krb5_keytab kt = NULL; + kadm5_server_handle_t server_handle = *(void **)handle; + krb5_data *response = NULL; + const char *emsg; + + ret = krb5_kt_resolve(server_handle->context, "KDB:", &kt); + if (ret != 0) { + emsg = krb5_get_error_message(server_handle->context, ret); + krb5_klog_syslog(LOG_ERR, _("chpw: Couldn't open admin keytab %s"), + emsg); + krb5_free_error_message(server_handle->context, emsg); + goto egress; + } + + response = k5alloc(sizeof(krb5_data), &ret); + if (response == NULL) + goto egress; + + ret = process_chpw_request(server_handle->context, + server_handle, + server_handle->params.realm, + kt, + local_addr, + remote_addr, + request, + response); +egress: + if (ret) + krb5_free_data(server_handle->context, response); + krb5_kt_close(server_handle->context, kt); + (*respond)(arg, ret, ret == 0 ? response : NULL); +} diff --git a/krb5-1.21.3/src/kadmin/server/server_stubs.c b/krb5-1.21.3/src/kadmin/server/server_stubs.c new file mode 100644 index 00000000..ef7e809b --- /dev/null +++ b/krb5-1.21.3/src/kadmin/server/server_stubs.c @@ -0,0 +1,1649 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + */ + +#include +#include +#include +#include /* for gss_nt_krb5_name */ +#include +#include +#include +#include +#include +#include /* krb5_klog_syslog */ +#include "misc.h" +#include "auth.h" + +extern gss_name_t gss_changepw_name; +extern gss_name_t gss_oldchangepw_name; +extern void * global_server_handle; + +#define CHANGEPW_SERVICE(rqstp) \ + (cmp_gss_names_rel_1(acceptor_name(rqstp->rq_svccred), gss_changepw_name) | \ + (gss_oldchangepw_name && \ + cmp_gss_names_rel_1(acceptor_name(rqstp->rq_svccred), \ + gss_oldchangepw_name))) + + +static int gss_to_krb5_name(kadm5_server_handle_t handle, + gss_name_t gss_name, krb5_principal *princ); + +static int gss_name_to_string(gss_name_t gss_name, gss_buffer_desc *str); + +static gss_name_t acceptor_name(gss_ctx_id_t context); + +gss_name_t rqst2name(struct svc_req *rqstp); + +static int cmp_gss_names(gss_name_t n1, gss_name_t n2) +{ + OM_uint32 emin; + int equal; + + if (GSS_ERROR(gss_compare_name(&emin, n1, n2, &equal))) + return(0); + + return(equal); +} + +/* Does a comparison of the names and then releases the first entity */ +/* For use above in CHANGEPW_SERVICE */ +static int cmp_gss_names_rel_1(gss_name_t n1, gss_name_t n2) +{ + OM_uint32 min_stat; + int ret; + + ret = cmp_gss_names(n1, n2); + if (n1) (void) gss_release_name(&min_stat, &n1); + return ret; +} + +/* + * Function check_handle + * + * Purpose: Check a server handle and return a com_err code if it is + * invalid or 0 if it is valid. + * + * Arguments: + * + * handle The server handle. + */ + +static int check_handle(void *handle) +{ + CHECK_HANDLE(handle); + return 0; +} + +/* + * Function: new_server_handle + * + * Purpose: Constructs a server handle suitable for passing into the + * server library API functions, by folding the client's API version + * and calling principal into the server handle returned by + * kadm5_init. + * + * Arguments: + * api_version (input) The API version specified by the client + * rqstp (input) The RPC request + * handle (output) The returned handle + * (output) An error code, or 0 if no error occurred + * + * Effects: + * Returns a pointer to allocated storage containing the server + * handle. If an error occurs, then no allocated storage is + * returned, and the return value of the function will be a + * non-zero com_err code. + * + * The allocated storage for the handle should be freed with + * free_server_handle (see below) when it is no longer needed. + */ + +static kadm5_ret_t new_server_handle(krb5_ui_4 api_version, + struct svc_req *rqstp, + kadm5_server_handle_t + *out_handle) +{ + kadm5_server_handle_t handle; + + *out_handle = NULL; + + if (! (handle = (kadm5_server_handle_t) + malloc(sizeof(*handle)))) + return ENOMEM; + + *handle = *(kadm5_server_handle_t)global_server_handle; + handle->api_version = api_version; + + if (! gss_to_krb5_name(handle, rqst2name(rqstp), + &handle->current_caller)) { + free(handle); + return KADM5_FAILURE; + } + + *out_handle = handle; + return 0; +} + +/* + * Function: free_server_handle + * + * Purpose: Free handle memory allocated by new_server_handle + * + * Arguments: + * handle (input/output) The handle to free + */ +static void free_server_handle(kadm5_server_handle_t handle) +{ + if (!handle) + return; + krb5_free_principal(handle->context, handle->current_caller); + free(handle); +} + +/* Result is stored in a static buffer and is invalidated by the next call. */ +const char * +client_addr(SVCXPRT *xprt) +{ + static char abuf[128]; + struct sockaddr_storage ss; + socklen_t len = sizeof(ss); + const char *p = NULL; + + if (getpeername(xprt->xp_sock, ss2sa(&ss), &len) != 0) + return "(unknown)"; + if (ss2sa(&ss)->sa_family == AF_INET) + p = inet_ntop(AF_INET, &ss2sin(&ss)->sin_addr, abuf, sizeof(abuf)); + else if (ss2sa(&ss)->sa_family == AF_INET6) + p = inet_ntop(AF_INET6, &ss2sin6(&ss)->sin6_addr, abuf, sizeof(abuf)); + return (p == NULL) ? "(unknown)" : p; +} + +/* + * Function: setup_gss_names + * + * Purpose: Create printable representations of the client and server + * names. + * + * Arguments: + * rqstp (r) the RPC request + * client_name (w) the gss_buffer_t for the client name + * server_name (w) the gss_buffer_t for the server name + * + * Effects: + * + * Unparses the client and server names into client_name and + * server_name, both of which must be freed by the caller. Returns 0 + * on success and -1 on failure. + */ +int setup_gss_names(struct svc_req *rqstp, + gss_buffer_desc *client_name, + gss_buffer_desc *server_name) +{ + OM_uint32 maj_stat, min_stat; + gss_name_t server_gss_name; + + if (gss_name_to_string(rqst2name(rqstp), client_name) != 0) + return -1; + maj_stat = gss_inquire_context(&min_stat, rqstp->rq_svccred, NULL, + &server_gss_name, NULL, NULL, NULL, + NULL, NULL); + if (maj_stat != GSS_S_COMPLETE) { + gss_release_buffer(&min_stat, client_name); + gss_release_name(&min_stat, &server_gss_name); + return -1; + } + if (gss_name_to_string(server_gss_name, server_name) != 0) { + gss_release_buffer(&min_stat, client_name); + gss_release_name(&min_stat, &server_gss_name); + return -1; + } + gss_release_name(&min_stat, &server_gss_name); + return 0; +} + +static gss_name_t acceptor_name(gss_ctx_id_t context) +{ + OM_uint32 maj_stat, min_stat; + gss_name_t name; + + maj_stat = gss_inquire_context(&min_stat, context, NULL, &name, + NULL, NULL, NULL, NULL, NULL); + if (maj_stat != GSS_S_COMPLETE) + return NULL; + return name; +} + +static int gss_to_krb5_name(kadm5_server_handle_t handle, + gss_name_t gss_name, krb5_principal *princ) +{ + krb5_error_code ret; + OM_uint32 minor_stat; + gss_buffer_desc gss_str; + int success; + char *s; + + if (gss_name_to_string(gss_name, &gss_str) != 0) + return 0; + s = k5memdup0(gss_str.value, gss_str.length, &ret); + if (s == NULL) { + gss_release_buffer(&minor_stat, &gss_str); + return 0; + } + success = (krb5_parse_name(handle->context, s, princ) == 0); + free(s); + gss_release_buffer(&minor_stat, &gss_str); + return success; +} + +static int +gss_name_to_string(gss_name_t gss_name, gss_buffer_desc *str) +{ + OM_uint32 status, minor_stat; + gss_OID gss_type; + const char pref[] = KRB5_WELLKNOWN_NAMESTR "/" KRB5_ANONYMOUS_PRINCSTR "@"; + const size_t preflen = sizeof(pref) - 1; + + status = gss_display_name(&minor_stat, gss_name, str, &gss_type); + if (status != GSS_S_COMPLETE) + return 1; + if (gss_oid_equal(gss_type, GSS_C_NT_ANONYMOUS)) { + /* Guard against non-krb5 mechs with different anonymous displays. */ + if (str->length < preflen || memcmp(str->value, pref, preflen) != 0) + return 1; + } else if (!gss_oid_equal(gss_type, GSS_KRB5_NT_PRINCIPAL_NAME)) { + return 1; + } + return 0; +} + +/* + * Perform common initialization for server stub functions. A subset of the + * output arguments may be set on failure; the caller is responsible for + * initializing outputs and calling stub_cleanup() on success or failure. + * princ and princ_str_out may be NULL to omit unparsing a principal name. + */ +static kadm5_ret_t +stub_setup(krb5_ui_4 api_version, struct svc_req *rqstp, krb5_principal princ, + kadm5_server_handle_t *handle_out, krb5_ui_4 *api_version_out, + gss_buffer_t client_name_out, gss_buffer_t service_name_out, + char **princ_str_out) +{ + kadm5_ret_t ret; + + ret = new_server_handle(api_version, rqstp, handle_out); + if (ret) + return ret; + + ret = check_handle(*handle_out); + if (ret) + return ret; + + *api_version_out = (*handle_out)->api_version; + + if (setup_gss_names(rqstp, client_name_out, service_name_out) < 0) + return KADM5_FAILURE; + + if (princ_str_out != NULL) { + if (princ == NULL) + return KADM5_BAD_PRINCIPAL; + if (krb5_unparse_name((*handle_out)->context, princ, princ_str_out)) + return KADM5_BAD_PRINCIPAL; + } + + return KADM5_OK; +} + +/* Perform common cleanup for server stub functions. */ +static void +stub_cleanup(kadm5_server_handle_t handle, char *princ_str, + gss_buffer_t client_name, gss_buffer_t service_name) +{ + OM_uint32 minor_stat; + + auth_end(handle->context); + free_server_handle(handle); + free(princ_str); + gss_release_buffer(&minor_stat, client_name); + gss_release_buffer(&minor_stat, service_name); +} + +static krb5_boolean +stub_auth(kadm5_server_handle_t handle, int opcode, krb5_const_principal p1, + krb5_const_principal p2, const char *s1, const char *s2) +{ + return auth(handle->context, opcode, handle->current_caller, p1, p2, + s1, s2, NULL, 0); +} + +static krb5_boolean +stub_auth_pol(kadm5_server_handle_t handle, int opcode, const char *policy, + const kadm5_policy_ent_rec *polent, long mask) +{ + return auth(handle->context, opcode, handle->current_caller, NULL, NULL, + policy, NULL, polent, mask); +} + +static krb5_boolean +stub_auth_restrict(kadm5_server_handle_t handle, int opcode, + kadm5_principal_ent_t ent, long *mask) +{ + return auth_restrict(handle->context, opcode, handle->current_caller, + ent, mask); +} + +/* Return true if the client authenticated to kadmin/changepw and princ is not + * the client principal. */ +static krb5_boolean +changepw_not_self(kadm5_server_handle_t handle, struct svc_req *rqstp, + krb5_const_principal princ) +{ + return CHANGEPW_SERVICE(rqstp) && + !krb5_principal_compare(handle->context, handle->current_caller, + princ); +} + +static krb5_boolean +ticket_is_initial(struct svc_req *rqstp) +{ + OM_uint32 status, minor_stat; + krb5_flags flags; + + status = gss_krb5_get_tkt_flags(&minor_stat, rqstp->rq_svccred, &flags); + if (status != GSS_S_COMPLETE) + return 0; + return (flags & TKT_FLG_INITIAL) != 0; +} + +/* If a key change request is for the client's own principal, verify that the + * client used an initial ticket and enforce the policy min_life. */ +static kadm5_ret_t +check_self_keychange(kadm5_server_handle_t handle, struct svc_req *rqstp, + krb5_principal princ) +{ + if (!krb5_principal_compare(handle->context, handle->current_caller, + princ)) + return 0; + + if (!ticket_is_initial(rqstp)) + return KADM5_AUTH_INITIAL; + + return check_min_life(handle, princ, NULL, 0); +} + +static int +log_unauth( + char *op, + char *target, + gss_buffer_t client, + gss_buffer_t server, + struct svc_req *rqstp) +{ + size_t tlen, clen, slen; + char *tdots, *cdots, *sdots; + + tlen = strlen(target); + trunc_name(&tlen, &tdots); + clen = client->length; + trunc_name(&clen, &cdots); + slen = server->length; + trunc_name(&slen, &sdots); + + /* okay to cast lengths to int because trunc_name limits max value */ + return krb5_klog_syslog(LOG_NOTICE, + _("Unauthorized request: %s, %.*s%s, " + "client=%.*s%s, service=%.*s%s, addr=%s"), + op, (int)tlen, target, tdots, + (int)clen, (char *)client->value, cdots, + (int)slen, (char *)server->value, sdots, + client_addr(rqstp->rq_xprt)); +} + +static int +log_done( + char *op, + char *target, + const char *errmsg, + gss_buffer_t client, + gss_buffer_t server, + struct svc_req *rqstp) +{ + size_t tlen, clen, slen; + char *tdots, *cdots, *sdots; + + if (errmsg == NULL) + errmsg = _("success"); + tlen = strlen(target); + trunc_name(&tlen, &tdots); + clen = client->length; + trunc_name(&clen, &cdots); + slen = server->length; + trunc_name(&slen, &sdots); + + /* okay to cast lengths to int because trunc_name limits max value */ + return krb5_klog_syslog(LOG_NOTICE, + _("Request: %s, %.*s%s, %s, " + "client=%.*s%s, service=%.*s%s, addr=%s"), + op, (int)tlen, target, tdots, errmsg, + (int)clen, (char *)client->value, cdots, + (int)slen, (char *)server->value, sdots, + client_addr(rqstp->rq_xprt)); +} + +bool_t +create_principal_2_svc(cprinc_arg *arg, generic_ret *ret, + struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal, + &handle, &ret->api_version, &client_name, + &service_name, &prime_arg); + if (ret->code) + goto exit_func; + + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth_restrict(handle, OP_ADDPRINC, &arg->rec, &arg->mask)) { + ret->code = KADM5_AUTH_ADD; + log_unauth("kadm5_create_principal", prime_arg, + &client_name, &service_name, rqstp); + } else { + ret->code = kadm5_create_principal(handle, &arg->rec, arg->mask, + arg->passwd); + + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_create_principal", prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +bool_t +create_principal3_2_svc(cprinc3_arg *arg, generic_ret *ret, + struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal, + &handle, &ret->api_version, &client_name, + &service_name, &prime_arg); + if (ret->code) + goto exit_func; + + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth_restrict(handle, OP_ADDPRINC, &arg->rec, &arg->mask)) { + ret->code = KADM5_AUTH_ADD; + log_unauth("kadm5_create_principal", prime_arg, + &client_name, &service_name, rqstp); + } else { + ret->code = kadm5_create_principal_3(handle, &arg->rec, arg->mask, + arg->n_ks_tuple, arg->ks_tuple, + arg->passwd); + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_create_principal", prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +/* Return KADM5_PROTECT_KEYS if KRB5_KDB_LOCKDOWN_KEYS is set for princ. */ +static kadm5_ret_t +check_lockdown_keys(kadm5_server_handle_t handle, krb5_principal princ) +{ + kadm5_principal_ent_rec rec; + kadm5_ret_t ret; + + ret = kadm5_get_principal(handle, princ, &rec, KADM5_ATTRIBUTES); + if (ret) + return ret; + ret = (rec.attributes & KRB5_KDB_LOCKDOWN_KEYS) ? KADM5_PROTECT_KEYS : 0; + kadm5_free_principal_ent(handle, &rec); + return ret; +} + +bool_t +delete_principal_2_svc(dprinc_arg *arg, generic_ret *ret, + struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, + &ret->api_version, &client_name, &service_name, + &prime_arg); + if (ret->code) + goto exit_func; + + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_DELPRINC, arg->princ, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_DELETE; + log_unauth("kadm5_delete_principal", prime_arg, + &client_name, &service_name, rqstp); + } else { + ret->code = check_lockdown_keys(handle, arg->princ); + if (ret->code == KADM5_PROTECT_KEYS) { + log_unauth("kadm5_delete_principal", prime_arg, &client_name, + &service_name, rqstp); + ret->code = KADM5_AUTH_DELETE; + } + } + + if (ret->code == KADM5_OK) + ret->code = kadm5_delete_principal(handle, arg->princ); + if (ret->code != KADM5_AUTH_DELETE) { + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_delete_principal", prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +bool_t +modify_principal_2_svc(mprinc_arg *arg, generic_ret *ret, + struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal, + &handle, &ret->api_version, &client_name, + &service_name, &prime_arg); + if (ret->code) + goto exit_func; + + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth_restrict(handle, OP_MODPRINC, &arg->rec, &arg->mask)) { + ret->code = KADM5_AUTH_MODIFY; + log_unauth("kadm5_modify_principal", prime_arg, + &client_name, &service_name, rqstp); + } else if ((arg->mask & KADM5_ATTRIBUTES) && + (!(arg->rec.attributes & KRB5_KDB_LOCKDOWN_KEYS))) { + ret->code = check_lockdown_keys(handle, arg->rec.principal); + if (ret->code == KADM5_PROTECT_KEYS) { + log_unauth("kadm5_modify_principal", prime_arg, &client_name, + &service_name, rqstp); + ret->code = KADM5_AUTH_MODIFY; + } + } + + if (ret->code == KADM5_OK) { + ret->code = kadm5_modify_principal(handle, &arg->rec, arg->mask); + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_modify_principal", prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +bool_t +rename_principal_2_svc(rprinc_arg *arg, generic_ret *ret, + struct svc_req *rqstp) +{ + char *prime_arg1 = NULL, *prime_arg2 = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + size_t tlen1, tlen2, clen, slen; + char *tdots1, *tdots2, *cdots, *sdots; + + ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, + &ret->api_version, &client_name, &service_name, + NULL); + if (ret->code) + goto exit_func; + + if (krb5_unparse_name(handle->context, arg->src, &prime_arg1) || + krb5_unparse_name(handle->context, arg->dest, &prime_arg2)) { + ret->code = KADM5_BAD_PRINCIPAL; + goto exit_func; + } + tlen1 = strlen(prime_arg1); + trunc_name(&tlen1, &tdots1); + tlen2 = strlen(prime_arg2); + trunc_name(&tlen2, &tdots2); + clen = client_name.length; + trunc_name(&clen, &cdots); + slen = service_name.length; + trunc_name(&slen, &sdots); + + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_RENPRINC, arg->src, arg->dest, NULL, NULL)) { + ret->code = KADM5_AUTH_INSUFFICIENT; + log_unauth("kadm5_rename_principal", prime_arg1, &client_name, + &service_name, rqstp); + } else { + ret->code = check_lockdown_keys(handle, arg->src); + if (ret->code == KADM5_PROTECT_KEYS) { + log_unauth("kadm5_rename_principal", prime_arg1, &client_name, + &service_name, rqstp); + ret->code = KADM5_AUTH_DELETE; + } + } + if (ret->code != KADM5_OK) { + /* okay to cast lengths to int because trunc_name limits max value */ + krb5_klog_syslog(LOG_NOTICE, + _("Unauthorized request: kadm5_rename_principal, " + "%.*s%s to %.*s%s, " + "client=%.*s%s, service=%.*s%s, addr=%s"), + (int)tlen1, prime_arg1, tdots1, + (int)tlen2, prime_arg2, tdots2, + (int)clen, (char *)client_name.value, cdots, + (int)slen, (char *)service_name.value, sdots, + client_addr(rqstp->rq_xprt)); + } else { + ret->code = kadm5_rename_principal(handle, arg->src, arg->dest); + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + /* okay to cast lengths to int because trunc_name limits max value */ + krb5_klog_syslog(LOG_NOTICE, + _("Request: kadm5_rename_principal, " + "%.*s%s to %.*s%s, %s, " + "client=%.*s%s, service=%.*s%s, addr=%s"), + (int)tlen1, prime_arg1, tdots1, + (int)tlen2, prime_arg2, tdots2, + errmsg ? errmsg : _("success"), + (int)clen, (char *)client_name.value, cdots, + (int)slen, (char *)service_name.value, sdots, + client_addr(rqstp->rq_xprt)); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + + } +exit_func: + free(prime_arg1); + free(prime_arg2); + stub_cleanup(handle, NULL, &client_name, &service_name); + return TRUE; +} + +bool_t +get_principal_2_svc(gprinc_arg *arg, gprinc_ret *ret, struct svc_req *rqstp) +{ + char *funcname, *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, + &ret->api_version, &client_name, &service_name, + &prime_arg); + if (ret->code) + goto exit_func; + + funcname = "kadm5_get_principal"; + + if (changepw_not_self(handle, rqstp, arg->princ) || + !stub_auth(handle, OP_GETPRINC, arg->princ, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_GET; + log_unauth(funcname, prime_arg, + &client_name, &service_name, rqstp); + } else { + ret->code = kadm5_get_principal(handle, arg->princ, &ret->rec, + arg->mask); + + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done(funcname, prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +bool_t +get_princs_2_svc(gprincs_arg *arg, gprincs_ret *ret, struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, + &ret->api_version, &client_name, &service_name, + NULL); + if (ret->code) + goto exit_func; + + prime_arg = arg->exp; + if (prime_arg == NULL) + prime_arg = "*"; + + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_LISTPRINCS, NULL, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_LIST; + log_unauth("kadm5_get_principals", prime_arg, + &client_name, &service_name, rqstp); + } else { + ret->code = kadm5_get_principals(handle, arg->exp, &ret->princs, + &ret->count); + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_get_principals", prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + + } + +exit_func: + stub_cleanup(handle, NULL, &client_name, &service_name); + return TRUE; +} + +bool_t +chpass_principal_2_svc(chpass_arg *arg, generic_ret *ret, + struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, + &ret->api_version, &client_name, &service_name, + &prime_arg); + if (ret->code) + goto exit_func; + + ret->code = check_lockdown_keys(handle, arg->princ); + if (ret->code != KADM5_OK) { + if (ret->code == KADM5_PROTECT_KEYS) { + log_unauth("kadm5_chpass_principal", prime_arg, &client_name, + &service_name, rqstp); + ret->code = KADM5_AUTH_CHANGEPW; + } + } else if (changepw_not_self(handle, rqstp, arg->princ) || + !stub_auth(handle, OP_CPW, arg->princ, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_CHANGEPW; + log_unauth("kadm5_chpass_principal", prime_arg, + &client_name, &service_name, rqstp); + } else { + ret->code = check_self_keychange(handle, rqstp, arg->princ); + if (!ret->code) + ret->code = kadm5_chpass_principal(handle, arg->princ, arg->pass); + } + + if (ret->code != KADM5_AUTH_CHANGEPW) { + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_chpass_principal", prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +bool_t +chpass_principal3_2_svc(chpass3_arg *arg, generic_ret *ret, + struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, + &ret->api_version, &client_name, &service_name, + &prime_arg); + if (ret->code) + goto exit_func; + + ret->code = check_lockdown_keys(handle, arg->princ); + if (ret->code != KADM5_OK) { + if (ret->code == KADM5_PROTECT_KEYS) { + log_unauth("kadm5_chpass_principal", prime_arg, &client_name, + &service_name, rqstp); + ret->code = KADM5_AUTH_CHANGEPW; + } + } else if (changepw_not_self(handle, rqstp, arg->princ) || + !stub_auth(handle, OP_CPW, arg->princ, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_CHANGEPW; + log_unauth("kadm5_chpass_principal", prime_arg, + &client_name, &service_name, rqstp); + } else { + ret->code = check_self_keychange(handle, rqstp, arg->princ); + if (!ret->code) { + ret->code = kadm5_chpass_principal_3(handle, arg->princ, + arg->keepold, arg->n_ks_tuple, + arg->ks_tuple, arg->pass); + } + } + + if (ret->code != KADM5_AUTH_CHANGEPW) { + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_chpass_principal", prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +bool_t +setkey_principal_2_svc(setkey_arg *arg, generic_ret *ret, + struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, + &ret->api_version, &client_name, &service_name, + &prime_arg); + if (ret->code) + goto exit_func; + + ret->code = check_lockdown_keys(handle, arg->princ); + if (ret->code != KADM5_OK) { + if (ret->code == KADM5_PROTECT_KEYS) { + log_unauth("kadm5_setkey_principal", prime_arg, &client_name, + &service_name, rqstp); + ret->code = KADM5_AUTH_SETKEY; + } + } else if (!(CHANGEPW_SERVICE(rqstp)) && + stub_auth(handle, OP_SETKEY, arg->princ, NULL, NULL, NULL)) { + ret->code = kadm5_setkey_principal(handle, arg->princ, arg->keyblocks, + arg->n_keys); + } else { + log_unauth("kadm5_setkey_principal", prime_arg, + &client_name, &service_name, rqstp); + ret->code = KADM5_AUTH_SETKEY; + } + + if (ret->code != KADM5_AUTH_SETKEY) { + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_setkey_principal", prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +bool_t +setkey_principal3_2_svc(setkey3_arg *arg, generic_ret *ret, + struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, + &ret->api_version, &client_name, &service_name, + &prime_arg); + if (ret->code) + goto exit_func; + + ret->code = check_lockdown_keys(handle, arg->princ); + if (ret->code != KADM5_OK) { + if (ret->code == KADM5_PROTECT_KEYS) { + log_unauth("kadm5_setkey_principal", prime_arg, &client_name, + &service_name, rqstp); + ret->code = KADM5_AUTH_SETKEY; + } + } else if (!(CHANGEPW_SERVICE(rqstp)) && + stub_auth(handle, OP_SETKEY, arg->princ, NULL, NULL, NULL)) { + ret->code = kadm5_setkey_principal_3(handle, arg->princ, arg->keepold, + arg->n_ks_tuple, arg->ks_tuple, + arg->keyblocks, arg->n_keys); + } else { + log_unauth("kadm5_setkey_principal", prime_arg, + &client_name, &service_name, rqstp); + ret->code = KADM5_AUTH_SETKEY; + } + + if (ret->code != KADM5_AUTH_SETKEY) { + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_setkey_principal", prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +bool_t +setkey_principal4_2_svc(setkey4_arg *arg, generic_ret *ret, + struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, + &ret->api_version, &client_name, &service_name, + &prime_arg); + if (ret->code) + goto exit_func; + + ret->code = check_lockdown_keys(handle, arg->princ); + if (ret->code != KADM5_OK) { + if (ret->code == KADM5_PROTECT_KEYS) { + log_unauth("kadm5_setkey_principal", prime_arg, &client_name, + &service_name, rqstp); + ret->code = KADM5_AUTH_SETKEY; + } + } else if (!(CHANGEPW_SERVICE(rqstp)) && + stub_auth(handle, OP_SETKEY, arg->princ, NULL, NULL, NULL)) { + ret->code = kadm5_setkey_principal_4(handle, arg->princ, arg->keepold, + arg->key_data, arg->n_key_data); + } else { + log_unauth("kadm5_setkey_principal", prime_arg, &client_name, + &service_name, rqstp); + ret->code = KADM5_AUTH_SETKEY; + } + + if (ret->code != KADM5_AUTH_SETKEY) { + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_setkey_principal", prime_arg, errmsg, &client_name, + &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +/* Empty out *keys / *nkeys if princ is protected with the lockdown + * attribute, or if we fail to check. */ +static kadm5_ret_t +chrand_check_lockdown(kadm5_server_handle_t handle, krb5_principal princ, + krb5_keyblock **keys, int *nkeys) +{ + kadm5_ret_t ret; + int i; + + ret = check_lockdown_keys(handle, princ); + if (!ret) + return 0; + + for (i = 0; i < *nkeys; i++) + krb5_free_keyblock_contents(handle->context, &((*keys)[i])); + free(*keys); + *keys = NULL; + *nkeys = 0; + return (ret == KADM5_PROTECT_KEYS) ? KADM5_OK : ret; +} + +bool_t +chrand_principal_2_svc(chrand_arg *arg, chrand_ret *ret, struct svc_req *rqstp) +{ + char *funcname, *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + krb5_keyblock *k; + int nkeys; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, + &ret->api_version, &client_name, &service_name, + &prime_arg); + if (ret->code) + goto exit_func; + + funcname = "kadm5_randkey_principal"; + + if (changepw_not_self(handle, rqstp, arg->princ) || + !stub_auth(handle, OP_CHRAND, arg->princ, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_CHANGEPW; + log_unauth(funcname, prime_arg, + &client_name, &service_name, rqstp); + } else { + ret->code = check_self_keychange(handle, rqstp, arg->princ); + if (!ret->code) { + ret->code = kadm5_randkey_principal(handle, arg->princ, + &k, &nkeys); + } + } + + if (ret->code == KADM5_OK) { + ret->code = chrand_check_lockdown(handle, arg->princ, &k, &nkeys); + if (ret->code == KADM5_PROTECT_KEYS) + ret->code = KADM5_OK; + ret->keys = k; + ret->n_keys = nkeys; + } + + if (ret->code != KADM5_AUTH_CHANGEPW) { + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done(funcname, prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +bool_t +chrand_principal3_2_svc(chrand3_arg *arg, chrand_ret *ret, + struct svc_req *rqstp) +{ + char *funcname, *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + krb5_keyblock *k; + int nkeys; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, + &ret->api_version, &client_name, &service_name, + &prime_arg); + if (ret->code) + goto exit_func; + + funcname = "kadm5_randkey_principal"; + + if (changepw_not_self(handle, rqstp, arg->princ) || + !stub_auth(handle, OP_CHRAND, arg->princ, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_CHANGEPW; + log_unauth(funcname, prime_arg, + &client_name, &service_name, rqstp); + } else { + ret->code = check_self_keychange(handle, rqstp, arg->princ); + if (!ret->code) { + ret->code = kadm5_randkey_principal_3(handle, arg->princ, + arg->keepold, + arg->n_ks_tuple, + arg->ks_tuple, &k, &nkeys); + } + } + + if (ret->code == KADM5_OK) { + ret->code = chrand_check_lockdown(handle, arg->princ, &k, &nkeys); + if (ret->code == KADM5_PROTECT_KEYS) + ret->code = KADM5_OK; + ret->keys = k; + ret->n_keys = nkeys; + } + + if (ret->code != KADM5_AUTH_CHANGEPW) { + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done(funcname, prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +bool_t +create_policy_2_svc(cpol_arg *arg, generic_ret *ret, struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, + &ret->api_version, &client_name, &service_name, + NULL); + if (ret->code) + goto exit_func; + + prime_arg = arg->rec.policy; + + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth_pol(handle, OP_ADDPOL, arg->rec.policy, + &arg->rec, arg->mask)) { + ret->code = KADM5_AUTH_ADD; + log_unauth("kadm5_create_policy", prime_arg, + &client_name, &service_name, rqstp); + + } else { + ret->code = kadm5_create_policy(handle, &arg->rec, arg->mask); + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_create_policy", + ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, NULL, &client_name, &service_name); + return TRUE; +} + +bool_t +delete_policy_2_svc(dpol_arg *arg, generic_ret *ret, struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, + &ret->api_version, &client_name, &service_name, + NULL); + if (ret->code) + goto exit_func; + + prime_arg = arg->name; + + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_DELPOL, NULL, NULL, arg->name, NULL)) { + log_unauth("kadm5_delete_policy", prime_arg, + &client_name, &service_name, rqstp); + ret->code = KADM5_AUTH_DELETE; + } else { + ret->code = kadm5_delete_policy(handle, arg->name); + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_delete_policy", + ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, NULL, &client_name, &service_name); + return TRUE; +} + +bool_t +modify_policy_2_svc(mpol_arg *arg, generic_ret *ret, struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, + &ret->api_version, &client_name, &service_name, + NULL); + if (ret->code) + goto exit_func; + + prime_arg = arg->rec.policy; + + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth_pol(handle, OP_MODPOL, arg->rec.policy, + &arg->rec, arg->mask)) { + log_unauth("kadm5_modify_policy", prime_arg, + &client_name, &service_name, rqstp); + ret->code = KADM5_AUTH_MODIFY; + } else { + ret->code = kadm5_modify_policy(handle, &arg->rec, arg->mask); + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_modify_policy", + ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, NULL, &client_name, &service_name); + return TRUE; +} + +bool_t +get_policy_2_svc(gpol_arg *arg, gpol_ret *ret, struct svc_req *rqstp) +{ + char *funcname, *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_ret_t ret2; + kadm5_principal_ent_rec caller_ent; + kadm5_server_handle_t handle; + const char *errmsg = NULL, *cpolicy = NULL; + + memset(&caller_ent, 0, sizeof(caller_ent)); + + ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, + &ret->api_version, &client_name, &service_name, + NULL); + if (ret->code) + goto exit_func; + + funcname = "kadm5_get_policy"; + + prime_arg = arg->name; + + /* Look up the client principal's policy value. */ + ret2 = kadm5_get_principal(handle->lhandle, handle->current_caller, + &caller_ent, KADM5_PRINCIPAL_NORMAL_MASK); + if (ret2 == KADM5_OK && (caller_ent.aux_attributes & KADM5_POLICY)) + cpolicy = caller_ent.policy; + + ret->code = KADM5_AUTH_GET; + if ((CHANGEPW_SERVICE(rqstp) && + (cpolicy == NULL || strcmp(cpolicy, arg->name) != 0)) || + !stub_auth(handle, OP_GETPOL, NULL, NULL, arg->name, cpolicy)) { + ret->code = KADM5_AUTH_GET; + log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp); + } else { + ret->code = kadm5_get_policy(handle, arg->name, &ret->rec); + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done(funcname, + ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg, + &client_name, &service_name, rqstp); + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + (void)kadm5_free_principal_ent(handle->lhandle, &caller_ent); + stub_cleanup(handle, NULL, &client_name, &service_name); + return TRUE; +} + +bool_t +get_pols_2_svc(gpols_arg *arg, gpols_ret *ret, struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle, + &ret->api_version, &client_name, &service_name, + NULL); + if (ret->code) + goto exit_func; + + prime_arg = arg->exp; + if (prime_arg == NULL) + prime_arg = "*"; + + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_LISTPOLS, NULL, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_LIST; + log_unauth("kadm5_get_policies", prime_arg, + &client_name, &service_name, rqstp); + } else { + ret->code = kadm5_get_policies(handle, arg->exp, &ret->pols, + &ret->count); + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_get_policies", prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, NULL, &client_name, &service_name); + return TRUE; +} + +bool_t +get_privs_2_svc(krb5_ui_4 *arg, getprivs_ret *ret, struct svc_req *rqstp) +{ + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(*arg, rqstp, NULL, &handle, &ret->api_version, + &client_name, &service_name, NULL); + if (ret->code) + goto exit_func; + + ret->code = kadm5_get_privs(handle, &ret->privs); + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_get_privs", client_name.value, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + +exit_func: + stub_cleanup(handle, NULL, &client_name, &service_name); + return TRUE; +} + +bool_t +purgekeys_2_svc(purgekeys_arg *arg, generic_ret *ret, struct svc_req *rqstp) +{ + char *funcname, *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, + &ret->api_version, &client_name, &service_name, + &prime_arg); + if (ret->code) + goto exit_func; + + funcname = "kadm5_purgekeys"; + + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_PURGEKEYS, arg->princ, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_MODIFY; + log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp); + } else { + ret->code = kadm5_purgekeys(handle, arg->princ, arg->keepkvno); + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done(funcname, prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +bool_t +get_strings_2_svc(gstrings_arg *arg, gstrings_ret *ret, struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, + &ret->api_version, &client_name, &service_name, + &prime_arg); + if (ret->code) + goto exit_func; + + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_GETSTRS, arg->princ, NULL, NULL, NULL)) { + ret->code = KADM5_AUTH_GET; + log_unauth("kadm5_get_strings", prime_arg, + &client_name, &service_name, rqstp); + } else { + ret->code = kadm5_get_strings(handle, arg->princ, &ret->strings, + &ret->count); + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_get_strings", prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +bool_t +set_string_2_svc(sstring_arg *arg, generic_ret *ret, struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, + &ret->api_version, &client_name, &service_name, + &prime_arg); + if (ret->code) + goto exit_func; + + if (CHANGEPW_SERVICE(rqstp) || + !stub_auth(handle, OP_SETSTR, arg->princ, NULL, + arg->key, arg->value)) { + ret->code = KADM5_AUTH_MODIFY; + log_unauth("kadm5_mod_strings", prime_arg, + &client_name, &service_name, rqstp); + } else { + ret->code = kadm5_set_string(handle, arg->princ, arg->key, arg->value); + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_mod_strings", prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} + +bool_t +init_2_svc(krb5_ui_4 *arg, generic_ret *ret, struct svc_req *rqstp) +{ + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + size_t clen, slen; + char *cdots, *sdots; + + ret->code = stub_setup(*arg, rqstp, NULL, &handle, &ret->api_version, + &client_name, &service_name, NULL); + if (ret->code) + goto exit_func; + + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + clen = client_name.length; + trunc_name(&clen, &cdots); + slen = service_name.length; + trunc_name(&slen, &sdots); + /* okay to cast lengths to int because trunc_name limits max value */ + krb5_klog_syslog(LOG_NOTICE, _("Request: kadm5_init, %.*s%s, %s, " + "client=%.*s%s, service=%.*s%s, addr=%s, " + "vers=%d, flavor=%d"), + (int)clen, (char *)client_name.value, cdots, + errmsg ? errmsg : _("success"), + (int)clen, (char *)client_name.value, cdots, + (int)slen, (char *)service_name.value, sdots, + client_addr(rqstp->rq_xprt), + ret->api_version & ~(KADM5_API_VERSION_MASK), + rqstp->rq_cred.oa_flavor); + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + +exit_func: + stub_cleanup(handle, NULL, &client_name, &service_name); + return TRUE; +} + +gss_name_t +rqst2name(struct svc_req *rqstp) +{ + + if (rqstp->rq_cred.oa_flavor == RPCSEC_GSS) + return rqstp->rq_clntname; + else + return rqstp->rq_clntcred; +} + +bool_t +get_principal_keys_2_svc(getpkeys_arg *arg, getpkeys_ret *ret, + struct svc_req *rqstp) +{ + char *prime_arg = NULL; + gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER; + kadm5_server_handle_t handle; + const char *errmsg = NULL; + + ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle, + &ret->api_version, &client_name, &service_name, + &prime_arg); + if (ret->code) + goto exit_func; + + if (!(CHANGEPW_SERVICE(rqstp)) && + stub_auth(handle, OP_EXTRACT, arg->princ, NULL, NULL, NULL)) { + ret->code = kadm5_get_principal_keys(handle, arg->princ, arg->kvno, + &ret->key_data, &ret->n_key_data); + } else { + log_unauth("kadm5_get_principal_keys", prime_arg, + &client_name, &service_name, rqstp); + ret->code = KADM5_AUTH_EXTRACT; + } + + if (ret->code == KADM5_OK) { + ret->code = check_lockdown_keys(handle, arg->princ); + if (ret->code != KADM5_OK) { + kadm5_free_kadm5_key_data(handle->context, ret->n_key_data, + ret->key_data); + ret->key_data = NULL; + ret->n_key_data = 0; + } + if (ret->code == KADM5_PROTECT_KEYS) { + log_unauth("kadm5_get_principal_keys", prime_arg, + &client_name, &service_name, rqstp); + ret->code = KADM5_AUTH_EXTRACT; + } + } + + if (ret->code != KADM5_AUTH_EXTRACT) { + if (ret->code != 0) + errmsg = krb5_get_error_message(handle->context, ret->code); + + log_done("kadm5_get_principal_keys", prime_arg, errmsg, + &client_name, &service_name, rqstp); + + if (errmsg != NULL) + krb5_free_error_message(handle->context, errmsg); + } + +exit_func: + stub_cleanup(handle, prime_arg, &client_name, &service_name); + return TRUE; +} diff --git a/krb5-1.21.3/src/kdc/Makefile.in b/krb5-1.21.3/src/kdc/Makefile.in new file mode 100644 index 00000000..ed85ca87 --- /dev/null +++ b/krb5-1.21.3/src/kdc/Makefile.in @@ -0,0 +1,101 @@ +mydir=kdc +BUILDTOP=$(REL).. +DEFINES=-DLIBDIR=\"$(KRB5_LIBDIR)\" + +all: krb5kdc rtest + +# DEFINES = -DBACKWARD_COMPAT $(KRB4DEF) + +LOCALINCLUDES = -I. +SRCS= \ + kdc5_err.c \ + $(srcdir)/authind.c \ + $(srcdir)/cammac.c \ + $(srcdir)/dispatch.c \ + $(srcdir)/do_as_req.c \ + $(srcdir)/do_tgs_req.c \ + $(srcdir)/fast_util.c \ + $(srcdir)/kdc_util.c \ + $(srcdir)/kdc_preauth.c \ + $(srcdir)/kdc_preauth_ec.c \ + $(srcdir)/kdc_preauth_encts.c \ + $(srcdir)/main.c \ + $(srcdir)/ndr.c \ + $(srcdir)/policy.c \ + $(srcdir)/extern.c \ + $(srcdir)/replay.c \ + $(srcdir)/kdc_authdata.c \ + $(srcdir)/kdc_audit.c \ + $(srcdir)/kdc_transit.c \ + $(srcdir)/tgs_policy.c \ + $(srcdir)/kdc_log.c \ + $(srcdir)/t_replay.c + +OBJS= \ + kdc5_err.o \ + authind.o \ + cammac.o \ + dispatch.o \ + do_as_req.o \ + do_tgs_req.o \ + fast_util.o \ + kdc_util.o \ + kdc_preauth.o \ + kdc_preauth_ec.o \ + kdc_preauth_encts.o \ + main.o \ + ndr.o \ + policy.o \ + extern.o \ + replay.o \ + kdc_authdata.o \ + kdc_audit.o \ + kdc_transit.o \ + tgs_policy.o \ + kdc_log.o + +RT_OBJS= rtest.o \ + kdc_transit.o + +depend: kdc5_err.c kdc5_err.h + +kdc5_err.c: kdc5_err.et + +kdc5_err.h: kdc5_err.et + +kdc5_err.o: kdc5_err.h + +krb5kdc: $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB) $(VERTO_DEPLIB) + $(CC_LINK) -o krb5kdc $(OBJS) $(APPUTILS_LIB) $(KADMSRV_LIBS) $(KRB5_BASE_LIBS) $(VERTO_LIBS) + +rtest: $(RT_OBJS) $(KDB5_DEPLIBS) $(KADM_COMM_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o rtest $(RT_OBJS) $(KDB5_LIBS) $(KADM_COMM_LIBS) $(KRB5_BASE_LIBS) + +t_ndr: t_ndr.o ndr.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_ndr.o ndr.o $(KRB5_BASE_LIBS) + +check-unix: rtest runenv.sh t_ndr + $(RUN_TEST) $(srcdir)/rtscript > test.out + cmp test.out $(srcdir)/rtest.good + $(RM) test.out + $(RUN_TEST) ./t_ndr > /dev/null + +T_REPLAY_OBJS=t_replay.o + +t_replay: $(T_REPLAY_OBJS) replay.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ $(T_REPLAY_OBJS) $(CMOCKA_LIBS) $(KRB5_BASE_LIBS) + +check-cmocka: t_replay + $(RUN_TEST) ./t_replay > /dev/null + +check-pytests: + $(RUNPYTEST) $(srcdir)/t_workers.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_emptytgt.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_bigreply.py $(PYTESTFLAGS) + +install: + $(INSTALL_PROGRAM) krb5kdc ${DESTDIR}$(SERVER_BINDIR)/krb5kdc + +clean: + $(RM) kdc5_err.h kdc5_err.c krb5kdc rtest.o rtest t_replay.o t_replay + $(RM) t_ndr.o t_ndr diff --git a/krb5-1.21.3/src/kdc/authind.c b/krb5-1.21.3/src/kdc/authind.c new file mode 100644 index 00000000..9fef4951 --- /dev/null +++ b/krb5-1.21.3/src/kdc/authind.c @@ -0,0 +1,123 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/authind.c - Functions for manipulating authentication indicator lists */ +/* + * Copyright (C) 2015 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. + */ + +#include "k5-int.h" +#include "kdc_util.h" + +/* Return true if ind matches an entry in indicators. */ +krb5_boolean +authind_contains(krb5_data *const *indicators, const char *ind) +{ + for (; indicators != NULL && *indicators != NULL; indicators++) { + if (data_eq_string(**indicators, ind)) + return TRUE; + } + return FALSE; +} + +/* Add ind to *indicators, reallocating as necessary. */ +krb5_error_code +authind_add(krb5_context context, const char *ind, krb5_data ***indicators) +{ + size_t count; + krb5_data **list = *indicators, *dptr, d; + + /* Count the number of existing indicators and check for duplicates. */ + for (count = 0; list != NULL && list[count] != NULL; count++) { + if (data_eq_string(*list[count], ind)) + return 0; + } + + /* Allocate space for a new entry. */ + list = realloc(list, (count + 2) * sizeof(*list)); + if (list == NULL) + return ENOMEM; + *indicators = list; + + /* Add a copy of ind (as a krb5_data object) to the list. */ + d = string2data((char *)ind); + if (krb5_copy_data(context, &d, &dptr) != 0) + return ENOMEM; + list[count++] = dptr; + list[count] = NULL; + return 0; +} + +/* Add all auth indicators from authdata to *indicators, reallocating as + * necessary. (Currently does not compress duplicates.) */ +krb5_error_code +authind_extract(krb5_context context, krb5_authdata **authdata, + krb5_data ***indicators) +{ + krb5_error_code ret; + size_t count, scount; + krb5_authdata **ind_authdata = NULL, **adp; + krb5_data der_indicators, **strings = NULL, **list = *indicators; + + for (count = 0; list != NULL && list[count] != NULL; count++); + + ret = krb5_find_authdata(context, authdata, NULL, + KRB5_AUTHDATA_AUTH_INDICATOR, &ind_authdata); + if (ret) + goto cleanup; + + for (adp = ind_authdata; adp != NULL && *adp != NULL; adp++) { + /* Decode this authdata element into an auth indicator list. */ + der_indicators = make_data((*adp)->contents, (*adp)->length); + ret = decode_utf8_strings(&der_indicators, &strings); + if (ret == ENOMEM) + goto cleanup; + if (ret) + continue; + + /* Count the entries in strings and allocate space in list. */ + for (scount = 0; strings != NULL && strings[scount] != NULL; scount++); + list = realloc(list, (count + scount + 1) * sizeof(*list)); + if (list == NULL) { + ret = ENOMEM; + goto cleanup; + } + *indicators = list; + + /* Steal the krb5_data pointers from strings and free the array. */ + memcpy(list + count, strings, scount * sizeof(*strings)); + count += scount; + list[count] = NULL; + free(strings); + strings = NULL; + } + +cleanup: + krb5_free_authdata(context, ind_authdata); + k5_free_data_ptr_list(strings); + return ret; +} diff --git a/krb5-1.21.3/src/kdc/cammac.c b/krb5-1.21.3/src/kdc/cammac.c new file mode 100644 index 00000000..df5fe966 --- /dev/null +++ b/krb5-1.21.3/src/kdc/cammac.c @@ -0,0 +1,175 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/cammac.c - Functions for wrapping and unwrapping CAMMACs */ +/* + * Copyright (C) 2015 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. + */ + +#include "k5-int.h" +#include "kdc_util.h" + +/* Encode enc_tkt with contents as the authdata field, for use in KDC + * verifier checksums. */ +static krb5_error_code +encode_kdcver_encpart(krb5_enc_tkt_part *enc_tkt, krb5_authdata **contents, + krb5_data **der_out) +{ + krb5_enc_tkt_part ck_enctkt; + + ck_enctkt = *enc_tkt; + ck_enctkt.authorization_data = contents; + return encode_krb5_enc_tkt_part(&ck_enctkt, der_out); +} + +/* + * Create a CAMMAC for contents, using enc_tkt and tgt_key for the KDC + * verifier. tgt_key must be the decrypted first key data entry in tgt. Set + * *cammac_out to a single-element authdata list containing the CAMMAC inside + * an IF-RELEVANT container. + */ +krb5_error_code +cammac_create(krb5_context context, krb5_enc_tkt_part *enc_tkt, + krb5_keyblock *server_key, krb5_db_entry *tgt, + krb5_keyblock *tgt_key, krb5_authdata **contents, + krb5_authdata ***cammac_out) +{ + krb5_error_code ret; + krb5_data *der_authdata = NULL, *der_enctkt = NULL, *der_cammac = NULL; + krb5_authdata ad, *list[2]; + krb5_cammac cammac; + krb5_verifier_mac kdc_verifier, svc_verifier; + krb5_keyblock tgtkey; + krb5_checksum kdc_cksum, svc_cksum; + + *cammac_out = NULL; + memset(&tgtkey, 0, sizeof(tgtkey)); + memset(&kdc_cksum, 0, sizeof(kdc_cksum)); + memset(&svc_cksum, 0, sizeof(svc_cksum)); + + /* Checksum the reply with contents as authdata for the KDC verifier. */ + ret = encode_kdcver_encpart(enc_tkt, contents, &der_enctkt); + if (ret) + goto cleanup; + ret = krb5_c_make_checksum(context, 0, tgt_key, KRB5_KEYUSAGE_CAMMAC, + der_enctkt, &kdc_cksum); + if (ret) + goto cleanup; + kdc_verifier.princ = NULL; + kdc_verifier.kvno = current_kvno(tgt); + kdc_verifier.enctype = ENCTYPE_NULL; + kdc_verifier.checksum = kdc_cksum; + + /* Encode the authdata and checksum it for the service verifier. */ + ret = encode_krb5_authdata(contents, &der_authdata); + if (ret) + goto cleanup; + ret = krb5_c_make_checksum(context, 0, server_key, KRB5_KEYUSAGE_CAMMAC, + der_authdata, &svc_cksum); + if (ret) + goto cleanup; + svc_verifier.princ = NULL; + svc_verifier.kvno = 0; + svc_verifier.enctype = ENCTYPE_NULL; + svc_verifier.checksum = svc_cksum; + + cammac.elements = contents; + cammac.kdc_verifier = &kdc_verifier; + cammac.svc_verifier = &svc_verifier; + cammac.other_verifiers = NULL; + + ret = encode_krb5_cammac(&cammac, &der_cammac); + if (ret) + goto cleanup; + + /* Wrap the encoded CAMMAC in an IF-RELEVANT container and return it as a + * single-element authdata list. */ + ad.ad_type = KRB5_AUTHDATA_CAMMAC; + ad.length = der_cammac->length; + ad.contents = (uint8_t *)der_cammac->data; + list[0] = &ad; + list[1] = NULL; + ret = krb5_encode_authdata_container(context, KRB5_AUTHDATA_IF_RELEVANT, + list, cammac_out); + +cleanup: + krb5_free_data(context, der_enctkt); + krb5_free_data(context, der_authdata); + krb5_free_data(context, der_cammac); + krb5_free_keyblock_contents(context, &tgtkey); + krb5_free_checksum_contents(context, &kdc_cksum); + krb5_free_checksum_contents(context, &svc_cksum); + return ret; +} + +/* + * Return true if cammac's KDC verifier is valid for enc_tkt, using tgt to + * retrieve the TGT key indicated by the verifier. tgt_key must be the + * decrypted first key data entry in tgt. + */ +krb5_boolean +cammac_check_kdcver(krb5_context context, krb5_cammac *cammac, + krb5_enc_tkt_part *enc_tkt, krb5_db_entry *tgt, + krb5_keyblock *tgt_key) +{ + krb5_verifier_mac *ver = cammac->kdc_verifier; + krb5_key_data *kd; + krb5_keyblock tgtkey, *key; + krb5_boolean valid = FALSE; + krb5_data *der_enctkt = NULL; + + memset(&tgtkey, 0, sizeof(tgtkey)); + + if (ver == NULL) + goto cleanup; + + /* Fetch the krbtgt key indicated by the KDC verifier. Only allow the + * first krbtgt key of the specified kvno. */ + if (ver->kvno == current_kvno(tgt)) { + key = tgt_key; + } else { + if (krb5_dbe_find_enctype(context, tgt, -1, -1, ver->kvno, &kd) != 0) + goto cleanup; + if (krb5_dbe_decrypt_key_data(context, NULL, kd, &tgtkey, NULL) != 0) + goto cleanup; + key = &tgtkey; + } + if (ver->enctype != ENCTYPE_NULL && tgtkey.enctype != ver->enctype) + goto cleanup; + + /* Verify the checksum over the DER-encoded enc_tkt with the CAMMAC + * elements as authdata. */ + if (encode_kdcver_encpart(enc_tkt, cammac->elements, &der_enctkt) != 0) + goto cleanup; + (void)krb5_c_verify_checksum(context, key, KRB5_KEYUSAGE_CAMMAC, + der_enctkt, &ver->checksum, &valid); + +cleanup: + krb5_free_keyblock_contents(context, &tgtkey); + krb5_free_data(context, der_enctkt); + return valid; +} diff --git a/krb5-1.21.3/src/kdc/deps b/krb5-1.21.3/src/kdc/deps new file mode 100644 index 00000000..70d557f9 --- /dev/null +++ b/krb5-1.21.3/src/kdc/deps @@ -0,0 +1,310 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kdc5_err.$(OBJEXT): $(COM_ERR_DEPS) kdc5_err.c +$(OUTPRE)authind.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h authind.c kdc_util.h \ + realm_data.h reqstate.h +$(OUTPRE)cammac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cammac.c kdc_util.h \ + realm_data.h reqstate.h +$(OUTPRE)dispatch.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kdcpreauth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + dispatch.c extern.h kdc_util.h realm_data.h reqstate.h +$(OUTPRE)do_as_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(VERTO_DEPS) $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/audit_plugin.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kdcpreauth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + do_as_req.c extern.h kdc_audit.h kdc_util.h policy.h \ + realm_data.h reqstate.h +$(OUTPRE)do_tgs_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/audit_plugin.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h do_tgs_req.c extern.h \ + kdc_audit.h kdc_util.h policy.h realm_data.h reqstate.h +$(OUTPRE)fast_util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h extern.h fast_util.c \ + kdc_util.h realm_data.h reqstate.h +$(OUTPRE)kdc_util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(VERTO_DEPS) $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h extern.h kdc_util.c \ + kdc_util.h realm_data.h reqstate.h +$(OUTPRE)kdc_preauth.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kdcpreauth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + extern.h kdc_preauth.c kdc_util.h realm_data.h reqstate.h +$(OUTPRE)kdc_preauth_ec.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdc_preauth_ec.c \ + kdc_util.h realm_data.h reqstate.h +$(OUTPRE)kdc_preauth_encts.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdc_preauth_encts.c \ + kdc_util.h realm_data.h reqstate.h +$(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(VERTO_DEPS) $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/kdb_kt.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/audit_plugin.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h extern.h kdc5_err.h \ + kdc_audit.h kdc_util.h main.c policy.h realm_data.h \ + reqstate.h +$(OUTPRE)ndr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-input.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/k5-utf8.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdc_util.h ndr.c \ + realm_data.h reqstate.h +$(OUTPRE)policy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kdcpolicy_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h extern.h kdc_util.h \ + policy.c policy.h realm_data.h reqstate.h +$(OUTPRE)extern.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + extern.c extern.h realm_data.h +$(OUTPRE)replay.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-hashtab.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-queue.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h extern.h kdc_util.h \ + realm_data.h replay.c reqstate.h +$(OUTPRE)kdc_authdata.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kdcauthdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h extern.h kdc_authdata.c \ + kdc_util.h realm_data.h reqstate.h +$(OUTPRE)kdc_audit.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/audit_plugin.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdc_audit.c kdc_audit.h \ + kdc_util.h realm_data.h reqstate.h +$(OUTPRE)kdc_transit.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdc_transit.c \ + kdc_util.h realm_data.h reqstate.h +$(OUTPRE)tgs_policy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdc_util.h realm_data.h \ + reqstate.h tgs_policy.c +$(OUTPRE)kdc_log.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kdcpreauth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kdc_log.c kdc_util.h realm_data.h reqstate.h +$(OUTPRE)t_replay.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-cmocka.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-hashtab.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-queue.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kdcpreauth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/net-server.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + extern.h kdc_util.h realm_data.h replay.c reqstate.h \ + t_replay.c diff --git a/krb5-1.21.3/src/kdc/dispatch.c b/krb5-1.21.3/src/kdc/dispatch.c new file mode 100644 index 00000000..28def3be --- /dev/null +++ b/krb5-1.21.3/src/kdc/dispatch.c @@ -0,0 +1,217 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/dispatch.c - Dispatch an incoming packet */ +/* + * Copyright 1990, 2009 by the Massachusetts Institute of Technology. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include +#include "kdc_util.h" +#include "extern.h" +#include "adm_proto.h" +#include "realm_data.h" +#include +#include +#include + +static krb5_error_code make_too_big_error(kdc_realm_t *realm, krb5_data **out); + +struct dispatch_state { + loop_respond_fn respond; + void *arg; + krb5_data *request; + int is_tcp; + kdc_realm_t *active_realm; + krb5_context kdc_err_context; +}; + +static void +finish_dispatch(struct dispatch_state *state, krb5_error_code code, + krb5_data *response) +{ + loop_respond_fn oldrespond = state->respond; + void *oldarg = state->arg; + + if (state->is_tcp == 0 && response && + response->length > (unsigned int)max_dgram_reply_size) { + krb5_free_data(NULL, response); + response = NULL; + code = make_too_big_error(state->active_realm, &response); + if (code) + krb5_klog_syslog(LOG_ERR, "error constructing " + "KRB_ERR_RESPONSE_TOO_BIG error: %s", + error_message(code)); + } + + free(state); + (*oldrespond)(oldarg, code, response); +} + +static void +finish_dispatch_cache(void *arg, krb5_error_code code, krb5_data *response) +{ + struct dispatch_state *state = arg; + krb5_context kdc_err_context = state->kdc_err_context; + +#ifndef NOCACHE + /* Remove the null cache entry unless we actually want to discard this + * request. */ + if (code != KRB5KDC_ERR_DISCARD) + kdc_remove_lookaside(kdc_err_context, state->request); + + /* Put the response into the lookaside buffer (if we produced one). */ + if (code == 0 && response != NULL) + kdc_insert_lookaside(kdc_err_context, state->request, response); +#endif + + finish_dispatch(state, code, response); +} + +void +dispatch(void *cb, const krb5_fulladdr *local_addr, + const krb5_fulladdr *remote_addr, krb5_data *pkt, int is_tcp, + verto_ctx *vctx, loop_respond_fn respond, void *arg) +{ + krb5_error_code retval; + krb5_kdc_req *req = NULL; + krb5_data *response = NULL; + struct dispatch_state *state; + struct server_handle *handle = cb; + krb5_context kdc_err_context = handle->kdc_err_context; + + state = k5alloc(sizeof(*state), &retval); + if (state == NULL) { + (*respond)(arg, retval, NULL); + return; + } + state->respond = respond; + state->arg = arg; + state->request = pkt; + state->is_tcp = is_tcp; + state->kdc_err_context = kdc_err_context; + + /* decode incoming packet, and dispatch */ + +#ifndef NOCACHE + /* try the replay lookaside buffer */ + if (kdc_check_lookaside(kdc_err_context, pkt, &response)) { + /* a hit! */ + const char *name = 0; + char buf[46]; + + name = inet_ntop(ADDRTYPE2FAMILY(remote_addr->address->addrtype), + remote_addr->address->contents, buf, sizeof(buf)); + if (name == 0) + name = "[unknown address type]"; + if (response) + krb5_klog_syslog(LOG_INFO, + "DISPATCH: repeated (retransmitted?) request " + "from %s, resending previous response", name); + else + krb5_klog_syslog(LOG_INFO, + "DISPATCH: repeated (retransmitted?) request " + "from %s during request processing, dropping " + "repeated request", name); + + finish_dispatch(state, response ? 0 : KRB5KDC_ERR_DISCARD, response); + return; + } + + /* Insert a NULL entry into the lookaside to indicate that this request + * is currently being processed. */ + kdc_insert_lookaside(kdc_err_context, pkt, NULL); +#endif + + /* try TGS_REQ first; they are more common! */ + + if (krb5_is_tgs_req(pkt)) + retval = decode_krb5_tgs_req(pkt, &req); + else if (krb5_is_as_req(pkt)) + retval = decode_krb5_as_req(pkt, &req); + else + retval = KRB5KRB_AP_ERR_MSG_TYPE; + if (retval) + goto done; + + state->active_realm = setup_server_realm(handle, req->server); + if (state->active_realm == NULL) { + retval = KRB5KDC_ERR_WRONG_REALM; + goto done; + } + + if (krb5_is_tgs_req(pkt)) { + /* process_tgs_req frees the request */ + retval = process_tgs_req(req, pkt, remote_addr, state->active_realm, + &response); + req = NULL; + } else if (krb5_is_as_req(pkt)) { + /* process_as_req frees the request and calls finish_dispatch_cache. */ + process_as_req(req, pkt, local_addr, remote_addr, state->active_realm, + vctx, finish_dispatch_cache, state); + return; + } + +done: + krb5_free_kdc_req(kdc_err_context, req); + finish_dispatch_cache(state, retval, response); +} + +static krb5_error_code +make_too_big_error(kdc_realm_t *realm, krb5_data **out) +{ + krb5_context context = realm->realm_context; + krb5_error errpkt; + krb5_error_code retval; + krb5_data *scratch; + + *out = NULL; + memset(&errpkt, 0, sizeof(errpkt)); + + retval = krb5_us_timeofday(context, &errpkt.stime, &errpkt.susec); + if (retval) + return retval; + errpkt.error = KRB_ERR_RESPONSE_TOO_BIG; + errpkt.server = realm->realm_tgsprinc; + errpkt.client = NULL; + errpkt.text.length = 0; + errpkt.text.data = 0; + errpkt.e_data.length = 0; + errpkt.e_data.data = 0; + scratch = malloc(sizeof(*scratch)); + if (scratch == NULL) + return ENOMEM; + retval = krb5_mk_error(context, &errpkt, scratch); + if (retval) { + free(scratch); + return retval; + } + + *out = scratch; + return 0; +} + +krb5_context get_context(void *handle) +{ + struct server_handle *sh = handle; + + return sh->kdc_err_context; +} diff --git a/krb5-1.21.3/src/kdc/do_as_req.c b/krb5-1.21.3/src/kdc/do_as_req.c new file mode 100644 index 00000000..6fb214b7 --- /dev/null +++ b/krb5-1.21.3/src/kdc/do_as_req.c @@ -0,0 +1,849 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/do_as_req.c */ +/* + * Portions Copyright (C) 2007 Apple Inc. + * Copyright 1990, 1991, 2007, 2008, 2009, 2013, 2014 by the + * Massachusetts Institute of Technology. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * KDC Routines to deal with AS_REQ's + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "k5-int.h" +#include "com_err.h" + +#include +#ifdef HAVE_NETINET_IN_H +#include +#include +#ifndef hpux +#include +#endif /* hpux */ +#endif /* HAVE_NETINET_IN_H */ + +#include "kdc_util.h" +#include "kdc_audit.h" +#include "policy.h" +#include +#include "adm_proto.h" +#include "extern.h" + +static krb5_error_code +prepare_error_as(struct kdc_request_state *, krb5_kdc_req *, krb5_db_entry *, + krb5_keyblock *, krb5_error_code, krb5_pa_data **, + krb5_boolean, krb5_principal, krb5_data **, const char *); + +/* Determine the key-expiration value according to RFC 4120 section 5.4.2. */ +static krb5_timestamp +get_key_exp(krb5_db_entry *entry) +{ + if (entry->expiration == 0) + return entry->pw_expiration; + if (entry->pw_expiration == 0) + return entry->expiration; + return ts_min(entry->expiration, entry->pw_expiration); +} + +/* + * Find the key in client for the most preferred enctype in req_enctypes. Fill + * in *kb_out with the decrypted keyblock (which the caller must free) and set + * *kd_out to an alias to that key data entry. Set *kd_out to NULL and leave + * *kb_out zeroed if no key is found for any of the requested enctypes. + * kb_out->enctype may differ from the enctype of *kd_out for DES enctypes; in + * this case, kb_out->enctype is the requested enctype used to match the key + * data entry. + */ +static krb5_error_code +select_client_key(krb5_context context, krb5_db_entry *client, + krb5_enctype *req_enctypes, int n_req_enctypes, + krb5_keyblock *kb_out, krb5_key_data **kd_out) +{ + krb5_error_code ret; + krb5_key_data *kd; + krb5_enctype etype; + int i; + + memset(kb_out, 0, sizeof(*kb_out)); + *kd_out = NULL; + + for (i = 0; i < n_req_enctypes; i++) { + etype = req_enctypes[i]; + if (!krb5_c_valid_enctype(etype)) + continue; + if (krb5_dbe_find_enctype(context, client, etype, -1, 0, &kd) == 0) { + /* Decrypt the client key data and set its enctype to the request + * enctype (which may differ from the key data enctype for DES). */ + ret = krb5_dbe_decrypt_key_data(context, NULL, kd, kb_out, NULL); + if (ret) + return ret; + kb_out->enctype = etype; + *kd_out = kd; + return 0; + } + } + return 0; +} + +static krb5_error_code +lookup_client(krb5_context context, krb5_kdc_req *req, unsigned int flags, + krb5_db_entry **entry_out) +{ + krb5_pa_data *pa; + krb5_data cert; + + *entry_out = NULL; + pa = krb5int_find_pa_data(context, req->padata, KRB5_PADATA_S4U_X509_USER); + if (pa != NULL && pa->length != 0 && + req->client->type == KRB5_NT_X500_PRINCIPAL) { + cert = make_data(pa->contents, pa->length); + flags |= KRB5_KDB_FLAG_REFERRAL_OK; + return krb5_db_get_s4u_x509_principal(context, &cert, req->client, + flags, entry_out); + } else { + return krb5_db_get_principal(context, req->client, flags, entry_out); + } +} + +struct as_req_state { + loop_respond_fn respond; + void *arg; + + krb5_principal_data client_princ; + krb5_enc_tkt_part enc_tkt_reply; + krb5_enc_kdc_rep_part reply_encpart; + krb5_ticket ticket_reply; + krb5_keyblock local_tgt_key; + krb5_keyblock server_keyblock; + krb5_keyblock client_keyblock; + krb5_db_entry *client; + krb5_db_entry *server; + krb5_db_entry *local_tgt; + krb5_db_entry *local_tgt_storage; + krb5_key_data *client_key; + krb5_kdc_req *request; + struct krb5_kdcpreauth_rock_st rock; + const char *status; + krb5_pa_data **e_data; + krb5_boolean typed_e_data; + krb5_kdc_rep reply; + krb5_timestamp kdc_time; + krb5_keyblock session_key; + unsigned int c_flags; + krb5_data *req_pkt; + krb5_data *inner_body; + struct kdc_request_state *rstate; + char *sname, *cname; + void *pa_context; + const krb5_fulladdr *local_addr; + const krb5_fulladdr *remote_addr; + krb5_data **auth_indicators; + + krb5_error_code preauth_err; + + kdc_realm_t *active_realm; + krb5_audit_state *au_state; +}; + +static void +finish_process_as_req(struct as_req_state *state, krb5_error_code errcode) +{ + kdc_realm_t *realm = state->active_realm; + krb5_context context = realm->realm_context; + krb5_keyblock *as_encrypting_key = NULL; + krb5_data *response = NULL; + const char *emsg = 0; + int did_log = 0; + loop_respond_fn oldrespond; + void *oldarg; + krb5_audit_state *au_state = state->au_state; + krb5_keyblock *replaced_reply_key = NULL; + + assert(state); + oldrespond = state->respond; + oldarg = state->arg; + + if (errcode) + goto egress; + + au_state->stage = ENCR_REP; + + state->ticket_reply.enc_part2 = &state->enc_tkt_reply; + + errcode = check_kdcpolicy_as(context, state->request, state->client, + state->server, state->auth_indicators, + state->kdc_time, &state->enc_tkt_reply.times, + &state->status); + if (errcode) + goto egress; + + errcode = get_first_current_key(context, state->server, + &state->server_keyblock); + if (errcode) { + state->status = "FINDING_SERVER_KEY"; + goto egress; + } + + /* Start assembling the response */ + state->reply.msg_type = KRB5_AS_REP; + state->reply.client = state->enc_tkt_reply.client; /* post canonization */ + state->reply.ticket = &state->ticket_reply; + state->reply_encpart.session = &state->session_key; + if ((errcode = fetch_last_req_info(state->client, + &state->reply_encpart.last_req))) + goto egress; + state->reply_encpart.nonce = state->request->nonce; + state->reply_encpart.key_exp = get_key_exp(state->client); + state->reply_encpart.flags = state->enc_tkt_reply.flags; + state->reply_encpart.server = state->ticket_reply.server; + state->reply_encpart.times = state->enc_tkt_reply.times; + state->reply_encpart.caddrs = state->enc_tkt_reply.caddrs; + state->reply_encpart.enc_padata = NULL; + + /* Fetch the padata info to be returned (do this before + * authdata to handle possible replacement of reply key + */ + errcode = return_padata(context, &state->rock, state->req_pkt, + state->request, &state->reply, + &state->client_keyblock, &state->pa_context); + if (errcode) { + state->status = "KDC_RETURN_PADATA"; + goto egress; + } + + /* If we didn't find a client long-term key and no preauth mechanism + * replaced the reply key, error out now. */ + if (state->client_keyblock.enctype == ENCTYPE_NULL) { + state->status = "CANT_FIND_CLIENT_KEY"; + errcode = KRB5KDC_ERR_ETYPE_NOSUPP; + goto egress; + } + + if (state->rock.replaced_reply_key) + replaced_reply_key = &state->client_keyblock; + + errcode = handle_authdata(realm, state->c_flags, state->client, + state->server, NULL, state->local_tgt, + &state->local_tgt_key, &state->client_keyblock, + &state->server_keyblock, NULL, + replaced_reply_key, state->req_pkt, + state->request, NULL, NULL, NULL, + &state->auth_indicators, &state->enc_tkt_reply); + if (errcode) { + krb5_klog_syslog(LOG_INFO, _("AS_REQ : handle_authdata (%d)"), + errcode); + state->status = "HANDLE_AUTHDATA"; + goto egress; + } + + errcode = check_indicators(context, state->server, state->auth_indicators); + if (errcode) { + state->status = "HIGHER_AUTHENTICATION_REQUIRED"; + goto egress; + } + + errcode = krb5_encrypt_tkt_part(context, &state->server_keyblock, + &state->ticket_reply); + if (errcode) + goto egress; + + errcode = kau_make_tkt_id(context, &state->ticket_reply, + &au_state->tkt_out_id); + if (errcode) + goto egress; + + state->ticket_reply.enc_part.kvno = current_kvno(state->server); + errcode = kdc_fast_response_handle_padata(state->rstate, + state->request, + &state->reply, + state->client_keyblock.enctype); + if (errcode) + goto egress; + + /* now encode/encrypt the response */ + + state->reply.enc_part.enctype = state->client_keyblock.enctype; + + errcode = kdc_fast_handle_reply_key(state->rstate, &state->client_keyblock, + &as_encrypting_key); + if (errcode) + goto egress; + errcode = return_enc_padata(context, state->req_pkt, state->request, + as_encrypting_key, state->server, + &state->reply_encpart, FALSE); + if (errcode) { + state->status = "KDC_RETURN_ENC_PADATA"; + goto egress; + } + + if (kdc_fast_hide_client(state->rstate)) + state->reply.client = (krb5_principal)krb5_anonymous_principal(); + errcode = krb5_encode_kdc_rep(context, KRB5_AS_REP, &state->reply_encpart, + 0, as_encrypting_key, &state->reply, + &response); + if (state->client_key != NULL) + state->reply.enc_part.kvno = state->client_key->key_data_kvno; + if (errcode) + goto egress; + + /* these parts are left on as a courtesy from krb5_encode_kdc_rep so we + can use them in raw form if needed. But, we don't... */ + memset(state->reply.enc_part.ciphertext.data, 0, + state->reply.enc_part.ciphertext.length); + free(state->reply.enc_part.ciphertext.data); + + log_as_req(context, state->local_addr, state->remote_addr, + state->request, &state->reply, state->client, state->cname, + state->server, state->sname, state->kdc_time, 0, 0, 0); + did_log = 1; + +egress: + if (errcode != 0 && state->status == NULL) + state->status = "UNKNOWN_REASON"; + + au_state->status = state->status; + au_state->reply = &state->reply; + kau_as_req(context, (errcode || state->preauth_err) ? FALSE : TRUE, + au_state); + kau_free_kdc_req(au_state); + + free_padata_context(context, state->pa_context); + if (as_encrypting_key) + krb5_free_keyblock(context, as_encrypting_key); + if (errcode) + emsg = krb5_get_error_message(context, errcode); + + if (state->status) { + log_as_req(context, state->local_addr, state->remote_addr, + state->request, &state->reply, state->client, + state->cname, state->server, state->sname, state->kdc_time, + state->status, errcode, emsg); + did_log = 1; + } + if (errcode) { + if (state->status == 0) { + state->status = emsg; + } + if (errcode != KRB5KDC_ERR_DISCARD) { + errcode = prepare_error_as(state->rstate, state->request, + state->local_tgt, &state->local_tgt_key, + errcode, state->e_data, + state->typed_e_data, + ((state->client != NULL) ? + state->client->princ : NULL), + &response, state->status); + state->status = 0; + } + } + + if (emsg) + krb5_free_error_message(context, emsg); + if (state->enc_tkt_reply.authorization_data != NULL) + krb5_free_authdata(context, state->enc_tkt_reply.authorization_data); + if (state->local_tgt_key.contents != NULL) + krb5_free_keyblock_contents(context, &state->local_tgt_key); + if (state->server_keyblock.contents != NULL) + krb5_free_keyblock_contents(context, &state->server_keyblock); + if (state->client_keyblock.contents != NULL) + krb5_free_keyblock_contents(context, &state->client_keyblock); + if (state->reply.padata != NULL) + krb5_free_pa_data(context, state->reply.padata); + if (state->reply_encpart.enc_padata) + krb5_free_pa_data(context, state->reply_encpart.enc_padata); + + if (state->cname != NULL) + free(state->cname); + if (state->sname != NULL) + free(state->sname); + krb5_db_free_principal(context, state->client); + krb5_db_free_principal(context, state->server); + krb5_db_free_principal(context, state->local_tgt_storage); + if (state->session_key.contents != NULL) + krb5_free_keyblock_contents(context, &state->session_key); + if (state->ticket_reply.enc_part.ciphertext.data != NULL) { + memset(state->ticket_reply.enc_part.ciphertext.data , 0, + state->ticket_reply.enc_part.ciphertext.length); + free(state->ticket_reply.enc_part.ciphertext.data); + } + + krb5_free_pa_data(context, state->e_data); + krb5_free_data(context, state->inner_body); + kdc_free_rstate(state->rstate); + krb5_free_kdc_req(context, state->request); + k5_free_data_ptr_list(state->auth_indicators); + assert(did_log != 0); + + free(state); + (*oldrespond)(oldarg, errcode, response); +} + +static void +finish_missing_required_preauth(void *arg) +{ + struct as_req_state *state = (struct as_req_state *)arg; + + finish_process_as_req(state, state->preauth_err); +} + +static void +finish_preauth(void *arg, krb5_error_code code) +{ + struct as_req_state *state = arg; + krb5_error_code real_code = code; + + if (code) { + if (vague_errors) + code = KRB5KRB_ERR_GENERIC; + state->status = "PREAUTH_FAILED"; + if (real_code == KRB5KDC_ERR_PREAUTH_FAILED) { + state->preauth_err = code; + get_preauth_hint_list(state->request, &state->rock, &state->e_data, + finish_missing_required_preauth, state); + return; + } + } else { + /* + * Final check before handing out ticket: If the client requires + * preauthentication, verify that the proper kind of + * preauthentication was carried out. + */ + state->status = missing_required_preauth(state->client, state->server, + &state->enc_tkt_reply); + if (state->status) { + state->preauth_err = KRB5KDC_ERR_PREAUTH_REQUIRED; + get_preauth_hint_list(state->request, &state->rock, &state->e_data, + finish_missing_required_preauth, state); + return; + } + } + + finish_process_as_req(state, code); +} + +/*ARGSUSED*/ +void +process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, + const krb5_fulladdr *local_addr, + const krb5_fulladdr *remote_addr, kdc_realm_t *realm, + verto_ctx *vctx, loop_respond_fn respond, void *arg) +{ + krb5_context context = realm->realm_context; + krb5_error_code errcode; + krb5_data encoded_req_body; + krb5_enctype useenctype; + struct as_req_state *state; + krb5_audit_state *au_state = NULL; + + state = k5alloc(sizeof(*state), &errcode); + if (state == NULL) { + (*respond)(arg, errcode, NULL); + return; + } + state->respond = respond; + state->arg = arg; + state->request = request; + state->req_pkt = req_pkt; + state->local_addr = local_addr; + state->remote_addr = remote_addr; + state->active_realm = realm; + + errcode = kdc_make_rstate(realm, &state->rstate); + if (errcode != 0) { + (*respond)(arg, errcode, NULL); + free(state); + return; + } + + /* Initialize audit state. */ + errcode = kau_init_kdc_req(context, state->request, remote_addr, + &au_state); + if (errcode) { + (*respond)(arg, errcode, NULL); + kdc_free_rstate(state->rstate); + free(state); + return; + } + state->au_state = au_state; + + if (state->request->msg_type != KRB5_AS_REQ) { + state->status = "VALIDATE_MESSAGE_TYPE"; + errcode = KRB5_BADMSGTYPE; + goto errout; + } + + /* Seed the audit trail with the request ID and basic information. */ + kau_as_req(context, TRUE, au_state); + + errcode = krb5_timeofday(context, &state->kdc_time); + if (errcode) + goto errout; + + if (fetch_asn1_field((unsigned char *) req_pkt->data, + 1, 4, &encoded_req_body) != 0) { + errcode = ASN1_BAD_ID; + goto errout; + } + errcode = kdc_find_fast(&state->request, &encoded_req_body, NULL, NULL, + state->rstate, &state->inner_body); + if (errcode) { + state->status = "FIND_FAST"; + goto errout; + } + if (state->inner_body == NULL) { + /* Not a FAST request; copy the encoded request body. */ + errcode = krb5_copy_data(context, &encoded_req_body, + &state->inner_body); + if (errcode) + goto errout; + } + au_state->request = state->request; + state->rock.request = state->request; + state->rock.inner_body = state->inner_body; + state->rock.rstate = state->rstate; + state->rock.vctx = vctx; + state->rock.auth_indicators = &state->auth_indicators; + state->rock.send_freshness_token = FALSE; + if (!state->request->client) { + state->status = "NULL_CLIENT"; + errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + goto errout; + } + errcode = krb5_unparse_name(context, state->request->client, + &state->cname); + if (errcode) + goto errout; + limit_string(state->cname); + + if (!state->request->server) { + state->status = "NULL_SERVER"; + errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto errout; + } + errcode = krb5_unparse_name(context, state->request->server, + &state->sname); + if (errcode) + goto errout; + limit_string(state->sname); + + setflag(state->c_flags, KRB5_KDB_FLAG_CLIENT); + if (isflagset(state->request->kdc_options, KDC_OPT_CANONICALIZE) || + state->request->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL) + setflag(state->c_flags, KRB5_KDB_FLAG_REFERRAL_OK); + errcode = lookup_client(context, state->request, state->c_flags, + &state->client); + if (errcode == KRB5_KDB_CANTLOCK_DB) + errcode = KRB5KDC_ERR_SVC_UNAVAILABLE; + if (errcode == KRB5_KDB_NOENTRY) { + state->status = "CLIENT_NOT_FOUND"; + if (vague_errors) + errcode = KRB5KRB_ERR_GENERIC; + else + errcode = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + goto errout; + } else if (errcode) { + state->status = "LOOKING_UP_CLIENT"; + goto errout; + } + state->rock.client = state->client; + + au_state->stage = SRVC_PRINC; + + errcode = krb5_db_get_principal(context, state->request->server, 0, + &state->server); + if (errcode == KRB5_KDB_CANTLOCK_DB) + errcode = KRB5KDC_ERR_SVC_UNAVAILABLE; + if (errcode == KRB5_KDB_NOENTRY) { + state->status = "SERVER_NOT_FOUND"; + errcode = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto errout; + } else if (errcode) { + state->status = "LOOKING_UP_SERVER"; + goto errout; + } + + /* If the KDB module returned a different realm for the client and server, + * we need to issue a client realm referral. */ + if (!data_eq(state->server->princ->realm, state->client->princ->realm)) { + state->status = "REFERRAL"; + au_state->cl_realm = &state->client->princ->realm; + errcode = KRB5KDC_ERR_WRONG_REALM; + goto errout; + } + + errcode = get_local_tgt(context, &state->request->server->realm, + state->server, &state->local_tgt, + &state->local_tgt_storage, &state->local_tgt_key); + if (errcode) { + state->status = "GET_LOCAL_TGT"; + goto errout; + } + state->rock.local_tgt = state->local_tgt; + state->rock.local_tgt_key = &state->local_tgt_key; + + au_state->stage = VALIDATE_POL; + + errcode = validate_as_request(realm, state->request, state->client, + state->server, state->kdc_time, + &state->status, &state->e_data); + if (errcode) + goto errout; + + au_state->stage = ISSUE_TKT; + + /* + * Select the keytype for the ticket session key. + */ + useenctype = select_session_keytype(context, state->server, + state->request->nktypes, + state->request->ktype); + if (useenctype == 0) { + /* unsupported ktype */ + state->status = "BAD_ENCRYPTION_TYPE"; + errcode = KRB5KDC_ERR_ETYPE_NOSUPP; + goto errout; + } + + errcode = krb5_c_make_random_key(context, useenctype, &state->session_key); + if (errcode) + goto errout; + + /* + * Canonicalization is only effective if we are issuing a TGT + * (the intention is to allow support for Windows "short" realm + * aliases, nothing more). + */ + if (isflagset(state->request->kdc_options, KDC_OPT_CANONICALIZE) && + krb5_is_tgs_principal(state->request->server) && + krb5_is_tgs_principal(state->server->princ)) { + state->ticket_reply.server = state->server->princ; + } else { + state->ticket_reply.server = state->request->server; + } + + /* Copy options that request the corresponding ticket flags. */ + state->enc_tkt_reply.flags = get_ticket_flags(state->request->kdc_options, + state->client, state->server, + NULL); + state->enc_tkt_reply.times.authtime = state->kdc_time; + + /* + * It should be noted that local policy may affect the + * processing of any of these flags. For example, some + * realms may refuse to issue renewable tickets + */ + + state->enc_tkt_reply.session = &state->session_key; + if (isflagset(state->request->kdc_options, KDC_OPT_CANONICALIZE)) { + state->client_princ = *(state->client->princ); + } else { + state->client_princ = *(state->request->client); + /* The realm is always canonicalized */ + state->client_princ.realm = state->client->princ->realm; + } + state->enc_tkt_reply.client = &state->client_princ; + state->enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS; + state->enc_tkt_reply.transited.tr_contents = empty_string; + + if (isflagset(state->request->kdc_options, KDC_OPT_POSTDATED)) + state->enc_tkt_reply.times.starttime = state->request->from; + else + state->enc_tkt_reply.times.starttime = state->kdc_time; + + kdc_get_ticket_endtime(realm, state->enc_tkt_reply.times.starttime, + kdc_infinity, state->request->till, state->client, + state->server, &state->enc_tkt_reply.times.endtime); + + kdc_get_ticket_renewtime(realm, state->request, NULL, state->client, + state->server, &state->enc_tkt_reply.flags, + &state->enc_tkt_reply.times); + + /* + * starttime is optional, and treated as authtime if not present. + * so we can nuke it if it matches + */ + if (state->enc_tkt_reply.times.starttime == + state->enc_tkt_reply.times.authtime) + state->enc_tkt_reply.times.starttime = 0; + + state->enc_tkt_reply.caddrs = state->request->addresses; + state->enc_tkt_reply.authorization_data = 0; + + /* If anonymous requests are being used, adjust the realm of the client + * principal. */ + if (isflagset(state->request->kdc_options, KDC_OPT_REQUEST_ANONYMOUS)) { + if (!krb5_principal_compare_any_realm(context, state->request->client, + krb5_anonymous_principal())) { + errcode = KRB5KDC_ERR_BADOPTION; + /* Anonymous requested but anonymous principal not used.*/ + state->status = "VALIDATE_ANONYMOUS_PRINCIPAL"; + goto errout; + } + krb5_free_principal(context, state->request->client); + state->request->client = NULL; + errcode = krb5_copy_principal(context, krb5_anonymous_principal(), + &state->request->client); + if (errcode) + goto errout; + state->enc_tkt_reply.client = state->request->client; + setflag(state->client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH); + } + + errcode = select_client_key(context, state->client, state->request->ktype, + state->request->nktypes, + &state->client_keyblock, &state->client_key); + if (errcode) { + state->status = "DECRYPT_CLIENT_KEY"; + goto errout; + } + if (state->client_key != NULL) + state->rock.client_key = state->client_key; + state->rock.client_keyblock = &state->client_keyblock; + + errcode = kdc_fast_read_cookie(context, state->rstate, state->request, + state->local_tgt, &state->local_tgt_key); + if (errcode) { + state->status = "READ_COOKIE"; + goto errout; + } + + /* + * Check the preauthentication if it is there. + */ + if (state->request->padata) { + check_padata(context, &state->rock, state->req_pkt, state->request, + &state->enc_tkt_reply, &state->pa_context, &state->e_data, + &state->typed_e_data, finish_preauth, state); + } else + finish_preauth(state, 0); + return; + +errout: + finish_process_as_req(state, errcode); +} + +static krb5_error_code +prepare_error_as(struct kdc_request_state *rstate, krb5_kdc_req *request, + krb5_db_entry *local_tgt, krb5_keyblock *local_tgt_key, + krb5_error_code code, krb5_pa_data **e_data_in, + krb5_boolean typed_e_data, krb5_principal canon_client, + krb5_data **response, const char *status) +{ + krb5_context context = rstate->realm_data->realm_context; + krb5_error errpkt; + krb5_error_code retval; + krb5_data *scratch = NULL, *e_data_asn1 = NULL, *fast_edata = NULL; + krb5_pa_data **e_data = NULL, *cookie = NULL; + size_t count; + + errpkt.magic = KV5M_ERROR; + + if (e_data_in != NULL) { + /* Add a PA-FX-COOKIE to e_data_in. e_data is a shallow copy + * containing aliases. */ + for (count = 0; e_data_in[count] != NULL; count++); + e_data = calloc(count + 2, sizeof(*e_data)); + if (e_data == NULL) + return ENOMEM; + memcpy(e_data, e_data_in, count * sizeof(*e_data)); + retval = kdc_fast_make_cookie(context, rstate, local_tgt, + local_tgt_key, request->client, &cookie); + e_data[count] = cookie; + } + + errpkt.ctime = 0; + errpkt.cusec = 0; + + retval = krb5_us_timeofday(context, &errpkt.stime, &errpkt.susec); + if (retval) + goto cleanup; + errpkt.error = errcode_to_protocol(code); + errpkt.server = request->server; + errpkt.client = (code == KRB5KDC_ERR_WRONG_REALM) ? canon_client : + request->client; + errpkt.text = string2data((char *)status); + + if (e_data != NULL) { + if (typed_e_data) + retval = encode_krb5_typed_data(e_data, &e_data_asn1); + else + retval = encode_krb5_padata_sequence(e_data, &e_data_asn1); + if (retval) + goto cleanup; + errpkt.e_data = *e_data_asn1; + } else + errpkt.e_data = empty_data(); + + retval = kdc_fast_handle_error(context, rstate, request, e_data, &errpkt, + &fast_edata); + if (retval) + goto cleanup; + if (fast_edata != NULL) + errpkt.e_data = *fast_edata; + + scratch = k5alloc(sizeof(*scratch), &retval); + if (scratch == NULL) + goto cleanup; + if (kdc_fast_hide_client(rstate) && errpkt.client != NULL) + errpkt.client = (krb5_principal)krb5_anonymous_principal(); + retval = krb5_mk_error(context, &errpkt, scratch); + if (retval) + goto cleanup; + + *response = scratch; + scratch = NULL; + +cleanup: + krb5_free_data(context, fast_edata); + krb5_free_data(context, e_data_asn1); + free(scratch); + free(e_data); + if (cookie != NULL) + free(cookie->contents); + free(cookie); + return retval; +} diff --git a/krb5-1.21.3/src/kdc/do_tgs_req.c b/krb5-1.21.3/src/kdc/do_tgs_req.c new file mode 100644 index 00000000..0acc4585 --- /dev/null +++ b/krb5-1.21.3/src/kdc/do_tgs_req.c @@ -0,0 +1,1229 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/do_tgs_req.c - KDC Routines to deal with TGS_REQ's */ +/* + * Copyright 1990, 1991, 2001, 2007, 2008, 2009, 2013, 2014 by the + * Massachusetts Institute of Technology. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "k5-int.h" + +#include +#ifdef HAVE_NETINET_IN_H +#include +#include +#ifndef hpux +#include +#endif +#endif + +#include "kdc_util.h" +#include "kdc_audit.h" +#include "policy.h" +#include "extern.h" +#include "adm_proto.h" +#include + +struct tgs_req_info { + /* The decoded request. Ownership is transferred to this structure. This + * will be replaced with the inner FAST body if present. */ + krb5_kdc_req *req; + + /* + * The decrypted authentication header ticket from the request's + * PA-TGS-REQ, the KDB entry for its server, its encryption key, the + * PA-TGS-REQ subkey if present, and the decoded and verified header ticket + * PAC if present. + */ + krb5_ticket *header_tkt; + krb5_db_entry *header_server; + krb5_keyblock *header_key; + krb5_keyblock *subkey; + krb5_pac header_pac; + + /* + * If a second ticket is present and this is a U2U or S4U2Proxy request, + * the decoded and verified PAC if present, the KDB entry for the second + * ticket server server, and the key used to decrypt the second ticket. + */ + krb5_pac stkt_pac; + krb5_db_entry *stkt_server; + krb5_keyblock *stkt_server_key; + /* For cross-realm S4U2Proxy requests, the client principal retrieved from + * stkt_pac. */ + krb5_principal stkt_pac_client; + + /* Storage for the local TGT KDB entry for the service realm if that isn't + * the header server. */ + krb5_db_entry *local_tgt_storage; + /* The decrypted first key of the local TGT entry. */ + krb5_keyblock local_tgt_key; + + /* The server KDB entry. Normally the requested server, but for referral + * and alternate TGS replies this will be a cross-realm TGT entry. */ + krb5_db_entry *server; + + /* + * The subject client KDB entry for an S4U2Self request, or the header + * ticket client KDB entry for other requests. NULL if + * NO_AUTH_DATA_REQUIRED is set on the server KDB entry and this isn't an + * S4U2Self request, or if the client is in another realm and the KDB + * cannot map its principal name. + */ + krb5_db_entry *client; + + /* The decoded S4U2Self padata from the request, if present. */ + krb5_pa_s4u_x509_user *s4u2self; + + /* Authentication indicators retrieved from the header ticket, for + * non-S4U2Self requests. */ + krb5_data **auth_indicators; + + /* Storage for a transited list with the header TGT realm added, if that + * realm is different from the client and server realm. */ + krb5_data new_transited; + + /* The KDB flags applicable to this request (a subset of {CROSS_REALM, + * ISSUING_REFERRAL, PROTOCOL_TRANSITION, CONSTRAINED_DELEGATION}). */ + unsigned int flags; + + /* Booleans for two of the above flags, for convenience. */ + krb5_boolean is_referral; + krb5_boolean is_crossrealm; + + /* The authtime of subject_tkt. On early failures this may be 0. */ + krb5_timestamp authtime; + + /* The following fields are (or contain) alias pointers and should not be + * freed. */ + + /* The transited list implied by the request, aliasing new_transited or the + * header ticket transited field. */ + krb5_transited transited; + + /* Alias to the decrypted second ticket within req, if one applies to this + * request. */ + const krb5_ticket *stkt; + + /* Alias to stkt for S4U2Proxy requests, header_tkt otherwise. */ + krb5_enc_tkt_part *subject_tkt; + + /* Alias to local_tgt_storage or header_server. */ + krb5_db_entry *local_tgt; + + /* For either kind of S4U request, an alias to the requested client + * principal name. */ + krb5_principal s4u_cprinc; + + /* An alias to the client principal name we should issue the ticket for + * (either header_tkt->enc_part2->client or s4u_cprinc). */ + krb5_principal tkt_client; + + /* The client principal of the PA-TGS-REQ header ticket. On early failures + * this may be NULL. */ + krb5_principal cprinc; + + /* The canonicalized request server principal or referral/alternate TGT. + * On early failures this may be the requested server instead. */ + krb5_principal sprinc; + +}; + +static krb5_error_code +db_get_svc_princ(krb5_context, krb5_principal, krb5_flags, + krb5_db_entry **, const char **); + +static krb5_error_code +prepare_error_tgs(struct kdc_request_state *state, krb5_kdc_req *request, + krb5_ticket *ticket, krb5_error_code code, + krb5_principal canon_server, krb5_data **response, + const char *status, krb5_pa_data **e_data) +{ + krb5_context context = state->realm_data->realm_context; + krb5_error errpkt; + krb5_error_code retval = 0; + krb5_data *scratch, *e_data_asn1 = NULL, *fast_edata = NULL; + + errpkt.magic = KV5M_ERROR; + errpkt.ctime = 0; + errpkt.cusec = 0; + + retval = krb5_us_timeofday(context, &errpkt.stime, &errpkt.susec); + if (retval) + return(retval); + errpkt.error = errcode_to_protocol(code); + errpkt.server = request->server; + if (ticket && ticket->enc_part2) + errpkt.client = ticket->enc_part2->client; + else + errpkt.client = NULL; + errpkt.text.length = strlen(status); + if (!(errpkt.text.data = strdup(status))) + return ENOMEM; + + if (!(scratch = (krb5_data *)malloc(sizeof(*scratch)))) { + free(errpkt.text.data); + return ENOMEM; + } + + if (e_data != NULL) { + retval = encode_krb5_padata_sequence(e_data, &e_data_asn1); + if (retval) { + free(scratch); + free(errpkt.text.data); + return retval; + } + errpkt.e_data = *e_data_asn1; + } else + errpkt.e_data = empty_data(); + + retval = kdc_fast_handle_error(context, state, request, e_data, + &errpkt, &fast_edata); + if (retval) { + free(scratch); + free(errpkt.text.data); + krb5_free_data(context, e_data_asn1); + return retval; + } + if (fast_edata) + errpkt.e_data = *fast_edata; + if (kdc_fast_hide_client(state) && errpkt.client != NULL) + errpkt.client = (krb5_principal)krb5_anonymous_principal(); + retval = krb5_mk_error(context, &errpkt, scratch); + free(errpkt.text.data); + krb5_free_data(context, e_data_asn1); + krb5_free_data(context, fast_edata); + if (retval) + free(scratch); + else + *response = scratch; + + return retval; +} + +/* KDC options that require a second ticket */ +#define STKT_OPTIONS (KDC_OPT_CNAME_IN_ADDL_TKT | KDC_OPT_ENC_TKT_IN_SKEY) +/* + * If req is a second-ticket request and a second ticket is present, decrypt + * it. Set *stkt_out to an alias to the ticket with populated enc_part2. Set + * *server_out to the server DB entry and *key_out to the ticket decryption + * key. + */ +static krb5_error_code +decrypt_2ndtkt(krb5_context context, krb5_kdc_req *req, krb5_flags flags, + krb5_db_entry *local_tgt, krb5_keyblock *local_tgt_key, + const krb5_ticket **stkt_out, krb5_pac *pac_out, + krb5_db_entry **server_out, krb5_keyblock **key_out, + const char **status) +{ + krb5_error_code retval; + krb5_db_entry *server = NULL; + krb5_keyblock *key = NULL; + krb5_kvno kvno; + krb5_ticket *stkt; + + *stkt_out = NULL; + *pac_out = NULL; + *server_out = NULL; + *key_out = NULL; + + if (!(req->kdc_options & STKT_OPTIONS) || req->second_ticket == NULL || + req->second_ticket[0] == NULL) + return 0; + + stkt = req->second_ticket[0]; + retval = kdc_get_server_key(context, stkt, flags, TRUE, &server, &key, + &kvno); + if (retval != 0) { + *status = "2ND_TKT_SERVER"; + goto cleanup; + } + retval = krb5_decrypt_tkt_part(context, key, stkt); + if (retval != 0) { + *status = "2ND_TKT_DECRYPT"; + goto cleanup; + } + retval = get_verified_pac(context, stkt->enc_part2, server, key, local_tgt, + local_tgt_key, pac_out); + if (retval != 0) { + *status = "2ND_TKT_PAC"; + goto cleanup; + } + *stkt_out = stkt; + *server_out = server; + *key_out = key; + server = NULL; + key = NULL; + +cleanup: + krb5_db_free_principal(context, server); + krb5_free_keyblock(context, key); + return retval; +} + +static krb5_error_code +get_2ndtkt_enctype(krb5_kdc_req *req, krb5_enctype *useenctype, + const char **status) +{ + krb5_enctype etype; + krb5_ticket *stkt = req->second_ticket[0]; + int i; + + etype = stkt->enc_part2->session->enctype; + if (!krb5_c_valid_enctype(etype)) { + *status = "BAD_ETYPE_IN_2ND_TKT"; + return KRB5KDC_ERR_ETYPE_NOSUPP; + } + for (i = 0; i < req->nktypes; i++) { + if (req->ktype[i] == etype) { + *useenctype = etype; + break; + } + } + return 0; +} + +static krb5_error_code +gen_session_key(krb5_context context, krb5_kdc_req *req, krb5_db_entry *server, + krb5_keyblock *skey, const char **status) +{ + krb5_error_code retval; + krb5_enctype useenctype = 0; + + /* + * Some special care needs to be taken in the user-to-user + * case, since we don't know what keytypes the application server + * which is doing user-to-user authentication can support. We + * know that it at least must be able to support the encryption + * type of the session key in the TGT, since otherwise it won't be + * able to decrypt the U2U ticket! So we use that in preference + * to anything else. + */ + if (req->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY) { + retval = get_2ndtkt_enctype(req, &useenctype, status); + if (retval != 0) + return retval; + } + if (useenctype == 0) { + useenctype = select_session_keytype(context, server, + req->nktypes, req->ktype); + } + if (useenctype == 0) { + /* unsupported ktype */ + *status = "BAD_ENCRYPTION_TYPE"; + return KRB5KDC_ERR_ETYPE_NOSUPP; + } + + return krb5_c_make_random_key(context, useenctype, skey); +} + +/* + * The request seems to be for a ticket-granting service somewhere else, + * but we don't have a ticket for the final TGS. Try to give the requestor + * some intermediate realm. + */ +static krb5_error_code +find_alternate_tgs(krb5_context context, krb5_principal princ, + krb5_db_entry **server_ptr, const char **status) +{ + krb5_error_code retval; + krb5_principal *plist = NULL, *pl2; + krb5_data tmp; + krb5_db_entry *server = NULL; + + *server_ptr = NULL; + assert(is_cross_tgs_principal(princ)); + retval = krb5_walk_realm_tree(context, &princ->realm, &princ->data[1], + &plist, KRB5_REALM_BRANCH_CHAR); + if (retval) + goto cleanup; + /* move to the end */ + for (pl2 = plist; *pl2; pl2++); + + /* the first entry in this array is for krbtgt/local@local, so we + ignore it */ + while (--pl2 > plist) { + tmp = *krb5_princ_realm(context, *pl2); + krb5_princ_set_realm(context, *pl2, &princ->realm); + retval = db_get_svc_princ(context, *pl2, 0, &server, status); + krb5_princ_set_realm(context, *pl2, &tmp); + if (retval == KRB5_KDB_NOENTRY) + continue; + else if (retval) + goto cleanup; + + log_tgs_alt_tgt(context, server->princ); + *server_ptr = server; + server = NULL; + goto cleanup; + } +cleanup: + if (retval == 0 && *server_ptr == NULL) + retval = KRB5_KDB_NOENTRY; + if (retval != 0) + *status = "UNKNOWN_SERVER"; + + krb5_free_realm_tree(context, plist); + krb5_db_free_principal(context, server); + return retval; +} + +/* Return true if item is an element of the space/comma-separated list. */ +static krb5_boolean +in_list(const char *list, const char *item) +{ + const char *p; + int len = strlen(item); + + if (list == NULL) + return FALSE; + for (p = strstr(list, item); p != NULL; p = strstr(p + 1, item)) { + if ((p == list || isspace((unsigned char)p[-1]) || p[-1] == ',') && + (p[len] == '\0' || isspace((unsigned char)p[len]) || + p[len] == ',')) + return TRUE; + } + return FALSE; +} + +/* + * Check whether the request satisfies the conditions for generating a referral + * TGT. The caller checks whether the hostname component looks like a FQDN. + */ +static krb5_boolean +is_referral_req(kdc_realm_t *realm, krb5_kdc_req *request) +{ + krb5_boolean ret = FALSE; + char *stype = NULL; + char *hostbased = realm->realm_hostbased; + char *no_referral = realm->realm_no_referral; + + if (!(request->kdc_options & KDC_OPT_CANONICALIZE)) + return FALSE; + + if (request->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY) + return FALSE; + + if (request->server->length != 2) + return FALSE; + + stype = data2string(&request->server->data[0]); + if (stype == NULL) + return FALSE; + switch (request->server->type) { + case KRB5_NT_UNKNOWN: + /* Allow referrals for NT-UNKNOWN principals, if configured. */ + if (!in_list(hostbased, stype) && !in_list(hostbased, "*")) + goto cleanup; + /* FALLTHROUGH */ + case KRB5_NT_SRV_HST: + case KRB5_NT_SRV_INST: + /* Deny referrals for specific service types, if configured. */ + if (in_list(no_referral, stype) || in_list(no_referral, "*")) + goto cleanup; + ret = TRUE; + break; + default: + goto cleanup; + } +cleanup: + free(stype); + return ret; +} + +/* + * Find a remote realm TGS principal for an unknown host-based service + * principal. + */ +static krb5_int32 +find_referral_tgs(kdc_realm_t *realm, krb5_kdc_req *request, + krb5_principal *krbtgt_princ) +{ + krb5_context context = realm->realm_context; + krb5_error_code retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + char **realms = NULL, *hostname = NULL; + krb5_data srealm = request->server->realm; + + if (!is_referral_req(realm, request)) + goto cleanup; + + hostname = data2string(&request->server->data[1]); + if (hostname == NULL) { + retval = ENOMEM; + goto cleanup; + } + /* If the hostname doesn't contain a '.', it's not a FQDN. */ + if (strchr(hostname, '.') == NULL) + goto cleanup; + retval = krb5_get_host_realm(context, hostname, &realms); + if (retval) { + /* no match found */ + kdc_err(context, retval, "unable to find realm of host"); + goto cleanup; + } + /* Don't return a referral to the empty realm or the service realm. */ + if (realms == NULL || realms[0] == NULL || *realms[0] == '\0' || + data_eq_string(srealm, realms[0])) { + retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto cleanup; + } + retval = krb5_build_principal(context, krbtgt_princ, + srealm.length, srealm.data, + "krbtgt", realms[0], (char *)0); +cleanup: + krb5_free_host_realm(context, realms); + free(hostname); + + return retval; +} + +static krb5_error_code +db_get_svc_princ(krb5_context ctx, krb5_principal princ, + krb5_flags flags, krb5_db_entry **server, + const char **status) +{ + krb5_error_code ret; + + ret = krb5_db_get_principal(ctx, princ, flags, server); + if (ret == KRB5_KDB_CANTLOCK_DB) + ret = KRB5KDC_ERR_SVC_UNAVAILABLE; + if (ret != 0) { + *status = "LOOKING_UP_SERVER"; + } + return ret; +} + +static krb5_error_code +search_sprinc(kdc_realm_t *realm, krb5_kdc_req *req, + krb5_flags flags, krb5_db_entry **server, const char **status) +{ + krb5_context context = realm->realm_context; + krb5_error_code ret; + krb5_principal princ = req->server; + krb5_principal reftgs = NULL; + krb5_boolean allow_referral; + + /* Do not allow referrals for u2u or ticket modification requests, because + * the server is supposed to match an already-issued ticket. */ + allow_referral = !(req->kdc_options & NO_REFERRAL_OPTION); + if (!allow_referral) + flags &= ~KRB5_KDB_FLAG_REFERRAL_OK; + + ret = db_get_svc_princ(context, princ, flags, server, status); + if (ret == 0 || ret != KRB5_KDB_NOENTRY || !allow_referral) + goto cleanup; + + if (!is_cross_tgs_principal(req->server)) { + ret = find_referral_tgs(realm, req, &reftgs); + if (ret != 0) + goto cleanup; + ret = db_get_svc_princ(context, reftgs, flags, server, status); + if (ret == 0 || ret != KRB5_KDB_NOENTRY) + goto cleanup; + + princ = reftgs; + } + ret = find_alternate_tgs(context, princ, server, status); + +cleanup: + if (ret != 0 && ret != KRB5KDC_ERR_SVC_UNAVAILABLE) { + ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + if (*status == NULL) + *status = "LOOKING_UP_SERVER"; + } + krb5_free_principal(context, reftgs); + return ret; +} + +/* + * Transfer ownership of *reqptr to *t and fill *t with information about the + * request. Decode the PA-TGS-REQ header ticket and the second ticket if + * applicable, and decode and verify their PACs if present. Decode and verify + * the S4U2Self request pa-data if present. Extract authentication indicators + * from the subject ticket. Construct the transited list implied by the + * request. + */ +static krb5_error_code +gather_tgs_req_info(kdc_realm_t *realm, krb5_kdc_req **reqptr, krb5_data *pkt, + const krb5_fulladdr *from, + struct kdc_request_state *fast_state, + krb5_audit_state *au_state, struct tgs_req_info *t, + const char **status) +{ + krb5_context context = realm->realm_context; + krb5_error_code ret; + krb5_pa_data *pa_tgs_req; + unsigned int s_flags; + krb5_enc_tkt_part *header_enc; + krb5_data d; + + /* Transfer ownership of *reqptr to *t. */ + t->req = *reqptr; + *reqptr = NULL; + + if (t->req->msg_type != KRB5_TGS_REQ) + return KRB5_BADMSGTYPE; + + /* Initially set t->sprinc to the outer request server, for logging of + * early failures. */ + t->sprinc = t->req->server; + + /* Read the PA-TGS-REQ authenticator and decrypt the header ticket. */ + ret = kdc_process_tgs_req(realm, t->req, from, pkt, &t->header_tkt, + &t->header_server, &t->header_key, &t->subkey, + &pa_tgs_req); + if (t->header_tkt != NULL && t->header_tkt->enc_part2 != NULL) + t->cprinc = t->header_tkt->enc_part2->client; + if (ret) { + *status = "PROCESS_TGS"; + return ret; + } + ret = kau_make_tkt_id(context, t->header_tkt, &au_state->tkt_in_id); + if (ret) + return ret; + header_enc = t->header_tkt->enc_part2; + + /* If PA-FX-FAST-REQUEST padata is present, replace t->req with the inner + * request body. */ + d = make_data(pa_tgs_req->contents, pa_tgs_req->length); + ret = kdc_find_fast(&t->req, &d, t->subkey, header_enc->session, + fast_state, NULL); + if (ret) { + *status = "FIND_FAST"; + return ret; + } + /* Reset t->sprinc for the inner body and check it. */ + t->sprinc = t->req->server; + if (t->sprinc == NULL) { + *status = "NULL_SERVER"; + return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + } + + /* The header ticket server is usually a TGT, but if it is not, fetch the + * local TGT for the realm. Get the decrypted first local TGT key. */ + ret = get_local_tgt(context, &t->sprinc->realm, t->header_server, + &t->local_tgt, &t->local_tgt_storage, + &t->local_tgt_key); + if (ret) { + *status = "GET_LOCAL_TGT"; + return ret; + } + + /* Decode and verify the header ticket PAC. */ + ret = get_verified_pac(context, header_enc, t->header_server, + t->header_key, t->local_tgt, &t->local_tgt_key, + &t->header_pac); + if (ret) { + *status = "HEADER_PAC"; + return ret; + } + + au_state->request = t->req; + au_state->stage = SRVC_PRINC; + + /* Look up the server principal entry, or a referral/alternate TGT. Reset + * t->sprinc to the canonical server name (its final value). */ + s_flags = (t->req->kdc_options & KDC_OPT_CANONICALIZE) ? + KRB5_KDB_FLAG_REFERRAL_OK : 0; + ret = search_sprinc(realm, t->req, s_flags, &t->server, status); + if (ret) + return ret; + t->sprinc = t->server->princ; + + /* If we got a cross-realm TGS which is not the requested server, we are + * issuing a referral (or alternate TGT, which we treat similarly). */ + if (is_cross_tgs_principal(t->server->princ) && + !krb5_principal_compare(context, t->req->server, t->server->princ)) + t->flags |= KRB5_KDB_FLAG_ISSUING_REFERRAL; + + /* Mark the request as cross-realm if the header ticket server is not from + * this realm. */ + if (!data_eq(t->header_server->princ->realm, t->sprinc->realm)) + t->flags |= KRB5_KDB_FLAG_CROSS_REALM; + + t->is_referral = (t->flags & KRB5_KDB_FLAG_ISSUING_REFERRAL); + t->is_crossrealm = (t->flags & KRB5_KDB_FLAG_CROSS_REALM); + + /* If S4U2Self padata is present, read it to get the requested principal + * name. Look up the requested client if it is in this realm. */ + ret = kdc_process_s4u2self_req(context, t->req, t->server, t->subkey, + header_enc->session, &t->s4u2self, + &t->client, status); + if (t->s4u2self != NULL || ret) { + if (t->s4u2self != NULL) + au_state->s4u2self_user = t->s4u2self->user_id.user; + au_state->status = *status; + kau_s4u2self(context, !ret, au_state); + au_state->s4u2self_user = NULL; + } + if (ret) + return ret; + if (t->s4u2self != NULL) { + t->flags |= KRB5_KDB_FLAG_PROTOCOL_TRANSITION; + t->s4u_cprinc = t->s4u2self->user_id.user; + + /* + * For consistency with Active Directory, don't allow authorization + * data to be disabled if S4U2Self is requested. The requesting + * service likely needs a PAC for an S4U2Proxy operation, even if it + * doesn't need authorization data in tickets received from clients. + */ + t->server->attributes &= ~KRB5_KDB_NO_AUTH_DATA_REQUIRED; + } + + /* For U2U or S4U2Proxy requests, decrypt the second ticket and read its + * PAC. */ + ret = decrypt_2ndtkt(context, t->req, t->flags, t->local_tgt, + &t->local_tgt_key, &t->stkt, &t->stkt_pac, + &t->stkt_server, &t->stkt_server_key, status); + if (ret) + return ret; + + /* Determine the subject ticket and set the authtime for logging. For + * S4U2Proxy requests determine the requested client principal. */ + if (t->req->kdc_options & KDC_OPT_CNAME_IN_ADDL_TKT) { + t->flags |= KRB5_KDB_FLAG_CONSTRAINED_DELEGATION; + ret = kau_make_tkt_id(context, t->stkt, &au_state->evid_tkt_id); + if (ret) + return ret; + if (t->is_crossrealm) { + /* For cross-realm S4U2PROXY requests, the second ticket is a + * cross TGT with the requested client principal in its PAC. */ + if (t->stkt_pac == NULL || + get_pac_princ_with_realm(context, t->stkt_pac, + &t->stkt_pac_client, NULL) != 0) { + au_state->status = *status = "RBCD_PAC_PRINC"; + au_state->violation = PROT_CONSTRAINT; + kau_s4u2proxy(context, FALSE, au_state); + return KRB5KDC_ERR_BADOPTION; + } + t->s4u_cprinc = t->stkt_pac_client; + } else { + /* Otherwise the requested client is the evidence ticket client. */ + t->s4u_cprinc = t->stkt->enc_part2->client; + } + t->subject_tkt = t->stkt->enc_part2; + } else { + t->subject_tkt = header_enc; + } + t->authtime = t->subject_tkt->times.authtime; + + /* For final S4U requests (either type) the issued ticket will be for the + * requested name; otherwise it will be for the header ticket client. */ + t->tkt_client = ((t->flags & KRB5_KDB_FLAGS_S4U) && !t->is_referral) ? + t->s4u_cprinc : header_enc->client; + + if (t->s4u2self == NULL) { + /* Extract auth indicators from the subject ticket. Skip this for + * S4U2Self requests as the subject didn't authenticate. */ + ret = get_auth_indicators(context, t->subject_tkt, t->local_tgt, + &t->local_tgt_key, &t->auth_indicators); + if (ret) { + *status = "GET_AUTH_INDICATORS"; + return ret; + } + + if (!(t->server->attributes & KRB5_KDB_NO_AUTH_DATA_REQUIRED)) { + /* Try to look up the subject principal so that KDB modules can add + * additional authdata. Ask the KDB to map foreign principals. */ + assert(t->client == NULL); + (void)krb5_db_get_principal(context, t->subject_tkt->client, + t->flags | KRB5_KDB_FLAG_CLIENT | + KRB5_KDB_FLAG_MAP_PRINCIPALS, + &t->client); + } + } + + /* + * Compute the transited list implied by the request. Use the existing + * transited list if the realm of the header ticket server is the same as + * the subject or server realm. + */ + if (!t->is_crossrealm || + data_eq(t->header_tkt->server->realm, t->tkt_client->realm)) { + t->transited = header_enc->transited; + } else { + if (header_enc->transited.tr_type != KRB5_DOMAIN_X500_COMPRESS) { + *status = "VALIDATE_TRANSIT_TYPE"; + return KRB5KDC_ERR_TRTYPE_NOSUPP; + } + ret = add_to_transited(&header_enc->transited.tr_contents, + &t->new_transited, t->header_tkt->server, + t->tkt_client, t->req->server); + if (ret) { + *status = "ADD_TO_TRANSITED_LIST"; + return ret; + } + t->transited.tr_type = KRB5_DOMAIN_X500_COMPRESS; + t->transited.tr_contents = t->new_transited; + } + + return 0; +} + +/* Fill in *times_out with the times of the ticket to be issued. Set the + * TKT_FLG_RENEWABLE bit in *tktflags if the ticket will be renewable. */ +static void +compute_ticket_times(kdc_realm_t *realm, struct tgs_req_info *t, + krb5_timestamp kdc_time, krb5_flags *tktflags, + krb5_ticket_times *times) +{ + krb5_timestamp hstarttime; + krb5_deltat hlife; + krb5_ticket_times *htimes = &t->header_tkt->enc_part2->times; + + if (t->req->kdc_options & KDC_OPT_VALIDATE) { + /* Validation requests preserve the header ticket times. */ + *times = *htimes; + return; + } + + /* Preserve the authtime from the subject ticket. */ + times->authtime = t->authtime; + + times->starttime = (t->req->kdc_options & KDC_OPT_POSTDATED) ? + t->req->from : kdc_time; + + if (t->req->kdc_options & KDC_OPT_RENEW) { + /* Give the new ticket the same lifetime as the header ticket, but no + * later than the renewable end time. */ + hstarttime = htimes->starttime ? htimes->starttime : htimes->authtime; + hlife = ts_delta(htimes->endtime, hstarttime); + times->endtime = ts_min(htimes->renew_till, + ts_incr(times->starttime, hlife)); + } else { + kdc_get_ticket_endtime(realm, times->starttime, htimes->endtime, + t->req->till, t->client, t->server, + ×->endtime); + } + + kdc_get_ticket_renewtime(realm, t->req, t->header_tkt->enc_part2, + t->client, t->server, tktflags, times); + + /* starttime is optional, and treated as authtime if not present. + * so we can omit it if it matches. */ + if (times->starttime == times->authtime) + times->starttime = 0; +} + +/* Check the request in *t against semantic protocol constraints and local + * policy. Determine flags and times for the ticket to be issued. */ +static krb5_error_code +check_tgs_req(kdc_realm_t *realm, struct tgs_req_info *t, + krb5_audit_state *au_state, krb5_flags *tktflags, + krb5_ticket_times *times, const char **status, + krb5_pa_data ***e_data) +{ + krb5_context context = realm->realm_context; + krb5_error_code ret; + krb5_timestamp kdc_time; + + au_state->stage = VALIDATE_POL; + + ret = krb5_timeofday(context, &kdc_time); + if (ret) + return ret; + + ret = check_tgs_constraints(realm, t->req, t->server, t->header_tkt, + t->header_pac, t->stkt, t->stkt_pac, + t->stkt_server, kdc_time, t->s4u2self, + t->client, t->is_crossrealm, t->is_referral, + status, e_data); + if (ret) { + au_state->violation = PROT_CONSTRAINT; + return ret; + } + + ret = check_tgs_policy(realm, t->req, t->server, t->header_tkt, + t->header_pac, t->stkt, t->stkt_pac, + t->stkt_pac_client, t->stkt_server, kdc_time, + t->is_crossrealm, t->is_referral, status, e_data); + if (ret) { + au_state->violation = LOCAL_POLICY; + if (t->flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) { + au_state->status = *status; + kau_s4u2proxy(context, FALSE, au_state); + } + return ret; + } + + /* Check auth indicators from the subject ticket, except for S4U2Self + * requests (where the client didn't authenticate). */ + if (t->s4u2self == NULL) { + ret = check_indicators(context, t->server, t->auth_indicators); + if (ret) { + *status = "HIGHER_AUTHENTICATION_REQUIRED"; + return ret; + } + } + + *tktflags = get_ticket_flags(t->req->kdc_options, t->client, t->server, + t->header_tkt->enc_part2); + compute_ticket_times(realm, t, kdc_time, tktflags, times); + + /* For S4U2Self requests, check if we need to suppress the forwardable + * ticket flag. */ + if (t->s4u2self != NULL && !t->is_referral) { + ret = s4u2self_forwardable(context, t->server, tktflags); + if (ret) + return ret; + } + + /* Consult kdcpolicy modules, giving them a chance to modify the times of + * the issued ticket. */ + ret = check_kdcpolicy_tgs(context, t->req, t->server, t->header_tkt, + t->auth_indicators, kdc_time, times, status); + if (ret) + return ret; + + if (!(t->req->kdc_options & KDC_OPT_DISABLE_TRANSITED_CHECK)) { + /* Check the transited path for the issued ticket and set the + * transited-policy-checked flag if successful. */ + ret = kdc_check_transited_list(context, &t->transited.tr_contents, + &t->subject_tkt->client->realm, + &t->req->server->realm); + if (ret) { + /* Log the transited-check failure and continue. */ + log_tgs_badtrans(context, t->cprinc, t->sprinc, + &t->transited.tr_contents, ret); + } else { + *tktflags |= TKT_FLG_TRANSIT_POLICY_CHECKED; + } + } else { + krb5_klog_syslog(LOG_INFO, _("not checking transit path")); + } + + /* By default, reject the request if the transited path was not checked + * successfully. */ + if (realm->realm_reject_bad_transit && + !(*tktflags & TKT_FLG_TRANSIT_POLICY_CHECKED)) { + *status = "BAD_TRANSIT"; + au_state->violation = LOCAL_POLICY; + return KRB5KDC_ERR_POLICY; + } + + return 0; +} + +/* Construct a response issuing a ticket for the request in *t, using tktflags + * and *times for the ticket flags and times. */ +static krb5_error_code +tgs_issue_ticket(kdc_realm_t *realm, struct tgs_req_info *t, + krb5_flags tktflags, krb5_ticket_times *times, krb5_data *pkt, + const krb5_fulladdr *from, + struct kdc_request_state *fast_state, + krb5_audit_state *au_state, const char **status, + krb5_data **response) +{ + krb5_context context = realm->realm_context; + krb5_error_code ret; + krb5_keyblock session_key = { 0 }, server_key = { 0 }; + krb5_keyblock *ticket_encrypting_key, *subject_key; + krb5_keyblock *initial_reply_key, *fast_reply_key = NULL; + krb5_enc_tkt_part enc_tkt_reply = { 0 }; + krb5_ticket ticket_reply = { 0 }; + krb5_enc_kdc_rep_part reply_encpart = { 0 }; + krb5_kdc_rep reply = { 0 }; + krb5_pac subject_pac; + krb5_db_entry *subject_server; + krb5_enc_tkt_part *header_enc_tkt = t->header_tkt->enc_part2; + krb5_last_req_entry nolrentry = { KV5M_LAST_REQ_ENTRY, KRB5_LRQ_NONE, 0 }; + krb5_last_req_entry *nolrarray[2] = { &nolrentry, NULL }; + + au_state->stage = ISSUE_TKT; + + ret = gen_session_key(context, t->req, t->server, &session_key, status); + if (ret) + goto cleanup; + + if (t->flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) { + subject_pac = t->stkt_pac; + subject_server = t->stkt_server; + subject_key = t->stkt_server_key; + } else { + subject_pac = t->header_pac; + subject_server = t->header_server; + subject_key = t->header_key; + } + + initial_reply_key = (t->subkey != NULL) ? t->subkey : + t->header_tkt->enc_part2->session; + + if (t->req->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY) { + /* For user-to-user, encrypt the ticket with the second ticket's + * session key. */ + ticket_encrypting_key = t->stkt->enc_part2->session; + } else { + /* Otherwise encrypt the ticket with the server entry's first long-term + * key. */ + ret = get_first_current_key(context, t->server, &server_key); + if (ret) { + *status = "FINDING_SERVER_KEY"; + goto cleanup; + } + ticket_encrypting_key = &server_key; + } + + if (t->req->kdc_options & (KDC_OPT_VALIDATE | KDC_OPT_RENEW)) { + /* Copy the header ticket server and all enc-part fields except for + * authorization data. */ + ticket_reply.server = t->header_tkt->server; + enc_tkt_reply = *t->header_tkt->enc_part2; + enc_tkt_reply.authorization_data = NULL; + } else { + if (t->req->kdc_options & (KDC_OPT_FORWARDED | KDC_OPT_PROXY)) { + /* Include the requested addresses in the ticket and reply. */ + enc_tkt_reply.caddrs = t->req->addresses; + reply_encpart.caddrs = t->req->addresses; + } else { + /* Use the header ticket addresses and omit them from the reply. */ + enc_tkt_reply.caddrs = header_enc_tkt->caddrs; + reply_encpart.caddrs = NULL; + } + + ticket_reply.server = t->is_referral ? t->sprinc : t->req->server; + } + + enc_tkt_reply.flags = tktflags; + enc_tkt_reply.times = *times; + enc_tkt_reply.client = t->tkt_client; + enc_tkt_reply.session = &session_key; + enc_tkt_reply.transited = t->transited; + + ret = handle_authdata(realm, t->flags, t->client, t->server, + subject_server, t->local_tgt, &t->local_tgt_key, + initial_reply_key, ticket_encrypting_key, + subject_key, NULL, pkt, t->req, t->s4u_cprinc, + subject_pac, t->subject_tkt, &t->auth_indicators, + &enc_tkt_reply); + if (ret) { + krb5_klog_syslog(LOG_INFO, _("TGS_REQ : handle_authdata (%d)"), ret); + *status = "HANDLE_AUTHDATA"; + goto cleanup; + } + + ticket_reply.enc_part2 = &enc_tkt_reply; + + ret = krb5_encrypt_tkt_part(context, ticket_encrypting_key, &ticket_reply); + if (ret) + goto cleanup; + + if (t->req->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY) { + ticket_reply.enc_part.kvno = 0; + kau_u2u(context, TRUE, au_state); + } else { + ticket_reply.enc_part.kvno = current_kvno(t->server); + } + + au_state->stage = ENCR_REP; + + if (t->s4u2self != NULL && + krb5int_find_pa_data(context, t->req->padata, + KRB5_PADATA_S4U_X509_USER) != NULL) { + /* Add an S4U2Self response to the encrypted padata (skipped if the + * request only included PA-FOR-USER padata). */ + ret = kdc_make_s4u2self_rep(context, t->subkey, + t->header_tkt->enc_part2->session, + t->s4u2self, &reply, &reply_encpart); + if (ret) + goto cleanup; + } + + reply_encpart.session = &session_key; + reply_encpart.nonce = t->req->nonce; + reply_encpart.times = enc_tkt_reply.times; + reply_encpart.last_req = nolrarray; + reply_encpart.key_exp = 0; + reply_encpart.flags = enc_tkt_reply.flags; + reply_encpart.server = ticket_reply.server; + + reply.msg_type = KRB5_TGS_REP; + reply.client = enc_tkt_reply.client; + reply.ticket = &ticket_reply; + reply.enc_part.kvno = 0; + reply.enc_part.enctype = initial_reply_key->enctype; + ret = kdc_fast_response_handle_padata(fast_state, t->req, &reply, + initial_reply_key->enctype); + if (ret) + goto cleanup; + ret = kdc_fast_handle_reply_key(fast_state, initial_reply_key, + &fast_reply_key); + if (ret) + goto cleanup; + ret = return_enc_padata(context, pkt, t->req, fast_reply_key, t->server, + &reply_encpart, + t->is_referral && + (t->req->kdc_options & KDC_OPT_CANONICALIZE)); + if (ret) { + *status = "KDC_RETURN_ENC_PADATA"; + goto cleanup; + } + + ret = kau_make_tkt_id(context, &ticket_reply, &au_state->tkt_out_id); + if (ret) + goto cleanup; + + if (kdc_fast_hide_client(fast_state)) + reply.client = (krb5_principal)krb5_anonymous_principal(); + ret = krb5_encode_kdc_rep(context, KRB5_TGS_REP, &reply_encpart, + t->subkey != NULL, fast_reply_key, &reply, + response); + if (ret) + goto cleanup; + + log_tgs_req(context, from, t->req, &reply, t->cprinc, t->sprinc, + t->s4u_cprinc, t->authtime, t->flags, "ISSUE", 0, NULL); + au_state->status = "ISSUE"; + au_state->reply = &reply; + if (t->flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) + kau_s4u2proxy(context, TRUE, au_state); + kau_tgs_req(context, TRUE, au_state); + au_state->reply = NULL; + +cleanup: + zapfree(ticket_reply.enc_part.ciphertext.data, + ticket_reply.enc_part.ciphertext.length); + zapfree(reply.enc_part.ciphertext.data, reply.enc_part.ciphertext.length); + krb5_free_pa_data(context, reply.padata); + krb5_free_pa_data(context, reply_encpart.enc_padata); + krb5_free_authdata(context, enc_tkt_reply.authorization_data); + krb5_free_keyblock_contents(context, &session_key); + krb5_free_keyblock_contents(context, &server_key); + krb5_free_keyblock(context, fast_reply_key); + return ret; +} + +static void +free_req_info(krb5_context context, struct tgs_req_info *t) +{ + krb5_free_kdc_req(context, t->req); + krb5_free_ticket(context, t->header_tkt); + krb5_db_free_principal(context, t->header_server); + krb5_free_keyblock(context, t->header_key); + krb5_free_keyblock(context, t->subkey); + krb5_pac_free(context, t->header_pac); + krb5_pac_free(context, t->stkt_pac); + krb5_db_free_principal(context, t->stkt_server); + krb5_free_keyblock(context, t->stkt_server_key); + krb5_db_free_principal(context, t->local_tgt_storage); + krb5_free_keyblock_contents(context, &t->local_tgt_key); + krb5_db_free_principal(context, t->server); + krb5_db_free_principal(context, t->client); + krb5_free_pa_s4u_x509_user(context, t->s4u2self); + krb5_free_principal(context, t->stkt_pac_client); + k5_free_data_ptr_list(t->auth_indicators); + krb5_free_data_contents(context, &t->new_transited); +} + +krb5_error_code +process_tgs_req(krb5_kdc_req *request, krb5_data *pkt, + const krb5_fulladdr *from, kdc_realm_t *realm, + krb5_data **response) +{ + krb5_context context = realm->realm_context; + krb5_error_code ret; + struct tgs_req_info t = { 0 }; + struct kdc_request_state *fast_state = NULL; + krb5_audit_state *au_state = NULL; + krb5_pa_data **e_data = NULL; + krb5_flags tktflags; + krb5_ticket_times times = { 0 }; + const char *emsg = NULL, *status = NULL; + + ret = kdc_make_rstate(realm, &fast_state); + if (ret) + goto cleanup; + ret = kau_init_kdc_req(context, request, from, &au_state); + if (ret) + goto cleanup; + kau_tgs_req(context, TRUE, au_state); + + ret = gather_tgs_req_info(realm, &request, pkt, from, fast_state, au_state, + &t, &status); + if (ret) + goto cleanup; + + ret = check_tgs_req(realm, &t, au_state, &tktflags, ×, &status, + &e_data); + if (ret) + goto cleanup; + + ret = tgs_issue_ticket(realm, &t, tktflags, ×, pkt, from, fast_state, + au_state, &status, response); + if (ret) + goto cleanup; + +cleanup: + if (status == NULL) + status = "UNKNOWN_REASON"; + + if (ret) { + emsg = krb5_get_error_message(context, ret); + log_tgs_req(context, from, t.req, NULL, t.cprinc, t.sprinc, + t.s4u_cprinc, t.authtime, t.flags, status, ret, emsg); + krb5_free_error_message(context, emsg); + + if (au_state != NULL) { + au_state->status = status; + kau_tgs_req(context, FALSE, au_state); + } + } + + if (ret && fast_state != NULL) { + ret = prepare_error_tgs(fast_state, t.req, t.header_tkt, ret, + (t.server != NULL) ? t.server->princ : NULL, + response, status, e_data); + } + + krb5_free_kdc_req(context, request); + kdc_free_rstate(fast_state); + kau_free_kdc_req(au_state); + free_req_info(context, &t); + krb5_free_pa_data(context, e_data); + return ret; +} diff --git a/krb5-1.21.3/src/kdc/extern.c b/krb5-1.21.3/src/kdc/extern.c new file mode 100644 index 00000000..ff45bf3f --- /dev/null +++ b/krb5-1.21.3/src/kdc/extern.c @@ -0,0 +1,43 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/extern.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * allocations of extern stuff + */ + +#include "k5-int.h" +#include "kdb.h" +#include "extern.h" +#include "realm_data.h" + +/* real declarations of KDC's externs */ +kdc_realm_t **kdc_realmlist = (kdc_realm_t **) NULL; +int kdc_numrealms = 0; +krb5_data empty_string = {0, 0, ""}; +krb5_int32 max_dgram_reply_size = MAX_DGRAM_SIZE; + +/* With ts_after(), this is the largest timestamp value. */ +krb5_timestamp kdc_infinity = -1; diff --git a/krb5-1.21.3/src/kdc/extern.h b/krb5-1.21.3/src/kdc/extern.h new file mode 100644 index 00000000..78b9f301 --- /dev/null +++ b/krb5-1.21.3/src/kdc/extern.h @@ -0,0 +1,36 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/extern.h */ +/* + * Copyright 1990,2001,2007,2009 by the Massachusetts Institute of Technology. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __KRB5_KDC_EXTERN__ +#define __KRB5_KDC_EXTERN__ + +/* various externs for KDC */ +extern krb5_data empty_string; /* an empty string */ +extern krb5_timestamp kdc_infinity; /* greater than all other timestamps */ +extern const int kdc_modifies_kdb; +extern krb5_int32 max_dgram_reply_size; /* maximum datagram size */ + +extern const int vague_errors; +#endif /* __KRB5_KDC_EXTERN__ */ diff --git a/krb5-1.21.3/src/kdc/fast_util.c b/krb5-1.21.3/src/kdc/fast_util.c new file mode 100644 index 00000000..7a6579f1 --- /dev/null +++ b/krb5-1.21.3/src/kdc/fast_util.c @@ -0,0 +1,721 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/fast_util.c */ +/* + * Copyright (C) 2009, 2015 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include + +#include "kdc_util.h" +#include "extern.h" + +/* Let cookies be valid for ten minutes. */ +#define COOKIE_LIFETIME 600 + +static krb5_error_code armor_ap_request +(struct kdc_request_state *state, krb5_fast_armor *armor) +{ + krb5_error_code retval = 0; + krb5_auth_context authcontext = NULL; + krb5_ticket *ticket = NULL; + krb5_keyblock *subkey = NULL; + kdc_realm_t *realm = state->realm_data; + krb5_context context = realm->realm_context; + + assert(armor->armor_type == KRB5_FAST_ARMOR_AP_REQUEST); + krb5_clear_error_message(context); + retval = krb5_auth_con_init(context, &authcontext); + /*disable replay cache*/ + if (retval == 0) + retval = krb5_auth_con_setflags(context, authcontext, 0); + if (retval == 0) + retval = krb5_rd_req(context, &authcontext, &armor->armor_value, + NULL /*server*/, realm->realm_keytab, + NULL, &ticket); + if (retval != 0) { + const char * errmsg = krb5_get_error_message(context, retval); + k5_setmsg(context, retval, _("%s while handling ap-request armor"), + errmsg); + krb5_free_error_message(context, errmsg); + } + if (retval == 0) { + if (!krb5_principal_compare_any_realm(context, realm->realm_tgsprinc, + ticket->server)) { + k5_setmsg(context, KRB5KDC_ERR_SERVER_NOMATCH, + _("ap-request armor for something other than the local " + "TGS")); + retval = KRB5KDC_ERR_SERVER_NOMATCH; + } + } + if (retval == 0) { + retval = krb5_auth_con_getrecvsubkey(context, authcontext, &subkey); + if (retval != 0 || subkey == NULL) { + k5_setmsg(context, KRB5KDC_ERR_POLICY, + _("ap-request armor without subkey")); + retval = KRB5KDC_ERR_POLICY; + } + } + if (retval == 0) + retval = krb5_c_fx_cf2_simple(context, + subkey, "subkeyarmor", + ticket->enc_part2->session, "ticketarmor", + &state->armor_key); + if (ticket) + krb5_free_ticket(context, ticket); + if (subkey) + krb5_free_keyblock(context, subkey); + if (authcontext) + krb5_auth_con_free(context, authcontext); + return retval; +} + +static krb5_error_code +encrypt_fast_reply(struct kdc_request_state *state, + const krb5_fast_response *response, + krb5_data **fx_fast_reply) +{ + krb5_context context = state->realm_data->realm_context; + krb5_error_code retval = 0; + krb5_enc_data encrypted_reply; + krb5_data *encoded_response = NULL; + + assert(state->armor_key); + retval = encode_krb5_fast_response(response, &encoded_response); + if (retval== 0) + retval = krb5_encrypt_helper(context, state->armor_key, + KRB5_KEYUSAGE_FAST_REP, + encoded_response, &encrypted_reply); + if (encoded_response) + krb5_free_data(context, encoded_response); + encoded_response = NULL; + if (retval == 0) { + retval = encode_krb5_pa_fx_fast_reply(&encrypted_reply, + fx_fast_reply); + krb5_free_data_contents(context, &encrypted_reply.ciphertext); + } + return retval; +} + + +/* + * This function will find the FAST padata and, if FAST is successfully + * processed, will free the outer request and update the pointer to point to + * the inner request. checksummed_data points to the data that is in the + * armored_fast_request checksum; either the pa-tgs-req or the kdc-req-body. + */ +krb5_error_code +kdc_find_fast(krb5_kdc_req **requestptr, + krb5_data *checksummed_data, + krb5_keyblock *tgs_subkey, + krb5_keyblock *tgs_session, + struct kdc_request_state *state, + krb5_data **inner_body_out) +{ + krb5_context context = state->realm_data->realm_context; + krb5_error_code retval = 0; + krb5_pa_data *fast_padata; + krb5_data scratch, plaintext, *inner_body = NULL; + krb5_fast_req * fast_req = NULL; + krb5_kdc_req *request = *requestptr; + krb5_fast_armored_req *fast_armored_req = NULL; + krb5_checksum *cksum; + krb5_boolean cksum_valid; + krb5_keyblock empty_keyblock; + + if (inner_body_out != NULL) + *inner_body_out = NULL; + scratch.data = NULL; + krb5_clear_error_message(context); + memset(&empty_keyblock, 0, sizeof(krb5_keyblock)); + fast_padata = krb5int_find_pa_data(context, request->padata, + KRB5_PADATA_FX_FAST); + if (fast_padata != NULL){ + scratch.length = fast_padata->length; + scratch.data = (char *) fast_padata->contents; + retval = decode_krb5_pa_fx_fast_request(&scratch, &fast_armored_req); + if (retval == 0 &&fast_armored_req->armor) { + switch (fast_armored_req->armor->armor_type) { + case KRB5_FAST_ARMOR_AP_REQUEST: + if (tgs_subkey) { + retval = KRB5KDC_ERR_PREAUTH_FAILED; + k5_setmsg(context, retval, + _("Ap-request armor not permitted with TGS")); + break; + } + retval = armor_ap_request(state, fast_armored_req->armor); + break; + default: + k5_setmsg(context, KRB5KDC_ERR_PREAUTH_FAILED, + _("Unknown FAST armor type %d"), + fast_armored_req->armor->armor_type); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + } + } + if (retval == 0 && !state->armor_key) { + if (tgs_subkey) + retval = krb5_c_fx_cf2_simple(context, + tgs_subkey, "subkeyarmor", + tgs_session, "ticketarmor", + &state->armor_key); + else { + retval = KRB5KDC_ERR_PREAUTH_FAILED; + k5_setmsg(context, retval, + _("No armor key but FAST armored request present")); + } + } + if (retval == 0) { + plaintext.length = fast_armored_req->enc_part.ciphertext.length; + plaintext.data = k5alloc(plaintext.length, &retval); + } + if (retval == 0) { + retval = krb5_c_decrypt(context, state->armor_key, + KRB5_KEYUSAGE_FAST_ENC, NULL, + &fast_armored_req->enc_part, + &plaintext); + if (retval == 0) + retval = decode_krb5_fast_req(&plaintext, &fast_req); + if (retval == 0 && inner_body_out != NULL) { + retval = fetch_asn1_field((unsigned char *)plaintext.data, + 1, 2, &scratch); + if (retval == 0) { + retval = krb5_copy_data(context, &scratch, &inner_body); + } + } + if (plaintext.data) + free(plaintext.data); + } + cksum = &fast_armored_req->req_checksum; + if (retval == 0) + retval = krb5_c_verify_checksum(context, state->armor_key, + KRB5_KEYUSAGE_FAST_REQ_CHKSUM, + checksummed_data, cksum, + &cksum_valid); + if (retval == 0 && !cksum_valid) { + retval = KRB5KRB_AP_ERR_MODIFIED; + k5_setmsg(context, retval, + _("FAST req_checksum invalid; request modified")); + } + if (retval == 0) { + if (!krb5_c_is_keyed_cksum(cksum->checksum_type)) { + retval = KRB5KDC_ERR_POLICY; + k5_setmsg(context, retval, + _("Unkeyed checksum used in fast_req")); + } + } + if (retval == 0) { + if ((fast_req->fast_options & UNSUPPORTED_CRITICAL_FAST_OPTIONS) != 0) + retval = KRB5KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTION; + } + if (retval == 0) { + state->fast_options = fast_req->fast_options; + fast_req->req_body->msg_type = request->msg_type; + krb5_free_kdc_req(context, request); + *requestptr = fast_req->req_body; + fast_req->req_body = NULL; + } + } + if (retval == 0 && inner_body_out != NULL) { + *inner_body_out = inner_body; + inner_body = NULL; + } + krb5_free_data(context, inner_body); + if (fast_req) + krb5_free_fast_req(context, fast_req); + if (fast_armored_req) + krb5_free_fast_armored_req(context, fast_armored_req); + return retval; +} + + +krb5_error_code +kdc_make_rstate(kdc_realm_t *active_realm, struct kdc_request_state **out) +{ + struct kdc_request_state *state = malloc( sizeof(struct kdc_request_state)); + if (state == NULL) + return ENOMEM; + memset( state, 0, sizeof(struct kdc_request_state)); + state->realm_data = active_realm; + *out = state; + return 0; +} + +void +kdc_free_rstate (struct kdc_request_state *s) +{ + if (s == NULL) + return; + if (s->armor_key) + krb5_free_keyblock(s->realm_data->realm_context, s->armor_key); + if (s->strengthen_key) + krb5_free_keyblock(s->realm_data->realm_context, s->strengthen_key); + k5_zapfree_pa_data(s->in_cookie_padata); + k5_zapfree_pa_data(s->out_cookie_padata); + free(s); +} + +krb5_error_code +kdc_fast_response_handle_padata(struct kdc_request_state *state, + krb5_kdc_req *request, + krb5_kdc_rep *rep, krb5_enctype enctype) +{ + krb5_context context = state->realm_data->realm_context; + krb5_error_code retval = 0; + krb5_fast_finished finish; + krb5_fast_response fast_response; + krb5_data *encoded_ticket = NULL; + krb5_data *encrypted_reply = NULL; + krb5_pa_data *pa = NULL, **pa_array = NULL; + krb5_cksumtype cksumtype = CKSUMTYPE_RSA_MD5; + krb5_pa_data *empty_padata[] = {NULL}; + krb5_keyblock *strengthen_key = NULL; + + if (!state->armor_key) + return 0; + memset(&finish, 0, sizeof(finish)); + retval = krb5_init_keyblock(context, enctype, 0, &strengthen_key); + if (retval == 0) + retval = krb5_c_make_random_key(context, enctype, strengthen_key); + if (retval == 0) { + state->strengthen_key = strengthen_key; + strengthen_key = NULL; + } + + fast_response.padata = rep->padata; + if (fast_response.padata == NULL) + fast_response.padata = &empty_padata[0]; + fast_response.strengthen_key = state->strengthen_key; + fast_response.nonce = request->nonce; + fast_response.finished = &finish; + finish.client = rep->client; + pa_array = calloc(3, sizeof(*pa_array)); + if (pa_array == NULL) + retval = ENOMEM; + pa = calloc(1, sizeof(krb5_pa_data)); + if (retval == 0 && pa == NULL) + retval = ENOMEM; + if (retval == 0) + retval = krb5_us_timeofday(context, &finish.timestamp, &finish.usec); + if (retval == 0) + retval = encode_krb5_ticket(rep->ticket, &encoded_ticket); + if (retval == 0) + retval = krb5int_c_mandatory_cksumtype(context, + state->armor_key->enctype, + &cksumtype); + if (retval == 0) + retval = krb5_c_make_checksum(context, cksumtype, state->armor_key, + KRB5_KEYUSAGE_FAST_FINISHED, + encoded_ticket, &finish.ticket_checksum); + if (retval == 0) + retval = encrypt_fast_reply(state, &fast_response, &encrypted_reply); + if (retval == 0) { + pa[0].pa_type = KRB5_PADATA_FX_FAST; + pa[0].length = encrypted_reply->length; + pa[0].contents = (unsigned char *) encrypted_reply->data; + pa_array[0] = &pa[0]; + krb5_free_pa_data(context, rep->padata); + rep->padata = pa_array; + pa_array = NULL; + free(encrypted_reply); + encrypted_reply = NULL; + pa = NULL; + } + if (pa) + free(pa); + if (pa_array) + free(pa_array); + if (encrypted_reply) + krb5_free_data(context, encrypted_reply); + if (encoded_ticket) + krb5_free_data(context, encoded_ticket); + if (strengthen_key != NULL) + krb5_free_keyblock(context, strengthen_key); + if (finish.ticket_checksum.contents) + krb5_free_checksum_contents(context, &finish.ticket_checksum); + return retval; +} + + +/* + * We assume the caller is responsible for passing us an in_padata + * sufficient to include in a FAST error. In the FAST case we will + * set *fast_edata_out to the edata to be included in the error; in + * the non-FAST case we will set it to NULL. + */ +krb5_error_code +kdc_fast_handle_error(krb5_context context, + struct kdc_request_state *state, + krb5_kdc_req *request, + krb5_pa_data **in_padata, krb5_error *err, + krb5_data **fast_edata_out) +{ + krb5_error_code retval = 0; + krb5_fast_response resp; + krb5_error fx_error; + krb5_data *encoded_fx_error = NULL, *encrypted_reply = NULL; + krb5_pa_data pa[1]; + krb5_pa_data *outer_pa[3]; + krb5_pa_data **inner_pa = NULL; + size_t size = 0; + + *fast_edata_out = NULL; + memset(outer_pa, 0, sizeof(outer_pa)); + if (state->armor_key == NULL) + return 0; + fx_error = *err; + fx_error.e_data.data = NULL; + fx_error.e_data.length = 0; + for (size = 0; in_padata&&in_padata[size]; size++); + inner_pa = calloc(size + 2, sizeof(krb5_pa_data *)); + if (inner_pa == NULL) + retval = ENOMEM; + if (retval == 0) + for (size=0; in_padata&&in_padata[size]; size++) + inner_pa[size] = in_padata[size]; + if (retval == 0) + retval = encode_krb5_error(&fx_error, &encoded_fx_error); + if (retval == 0) { + pa[0].pa_type = KRB5_PADATA_FX_ERROR; + pa[0].length = encoded_fx_error->length; + pa[0].contents = (unsigned char *) encoded_fx_error->data; + inner_pa[size++] = &pa[0]; + } + if (retval == 0) { + resp.padata = inner_pa; + resp.nonce = request->nonce; + resp.strengthen_key = NULL; + resp.finished = NULL; + } + if (retval == 0) + retval = encrypt_fast_reply(state, &resp, &encrypted_reply); + if (inner_pa) + free(inner_pa); /*contained storage from caller and our stack*/ + if (retval == 0) { + pa[0].pa_type = KRB5_PADATA_FX_FAST; + pa[0].length = encrypted_reply->length; + pa[0].contents = (unsigned char *) encrypted_reply->data; + outer_pa[0] = &pa[0]; + } + retval = encode_krb5_padata_sequence(outer_pa, fast_edata_out); + if (encrypted_reply) + krb5_free_data(context, encrypted_reply); + if (encoded_fx_error) + krb5_free_data(context, encoded_fx_error); + return retval; +} + +krb5_error_code +kdc_fast_handle_reply_key(struct kdc_request_state *state, + krb5_keyblock *existing_key, + krb5_keyblock **out_key) +{ + krb5_context context = state->realm_data->realm_context; + krb5_error_code retval = 0; + + if (state->armor_key) + retval = krb5_c_fx_cf2_simple(context, + state->strengthen_key, "strengthenkey", + existing_key, "replykey", out_key); + else + retval = krb5_copy_keyblock(context, existing_key, out_key); + return retval; +} + +krb5_boolean +kdc_fast_hide_client(struct kdc_request_state *state) +{ + return (state->fast_options & KRB5_FAST_OPTION_HIDE_CLIENT_NAMES) != 0; +} + +/* Create a pa-data entry with the specified type and contents. */ +static krb5_error_code +make_padata(krb5_preauthtype pa_type, const void *contents, size_t len, + krb5_pa_data **out) +{ + if (k5_alloc_pa_data(pa_type, len, out) != 0) + return ENOMEM; + memcpy((*out)->contents, contents, len); + return 0; +} + +/* + * Derive the secure cookie encryption key from tgt_key and client_princ. The + * cookie key is derived with PRF+ using the concatenation of "COOKIE" and the + * unparsed client principal name as input. + */ +static krb5_error_code +derive_cookie_key(krb5_context context, krb5_keyblock *tgt_key, + krb5_const_principal client_princ, krb5_keyblock **key_out) +{ + krb5_error_code ret; + krb5_data d; + char *princstr = NULL, *derive_input = NULL; + + *key_out = NULL; + + /* Construct the input string and derive the cookie key. */ + ret = krb5_unparse_name(context, client_princ, &princstr); + if (ret) + goto cleanup; + if (asprintf(&derive_input, "COOKIE%s", princstr) < 0) { + ret = ENOMEM; + goto cleanup; + } + d = string2data(derive_input); + ret = krb5_c_derive_prfplus(context, tgt_key, &d, ENCTYPE_NULL, key_out); + +cleanup: + krb5_free_unparsed_name(context, princstr); + free(derive_input); + return ret; +} + +/* Derive the cookie key for the specified kvno in tgt. tgt_key must be the + * decrypted first key data entry in tgt. */ +static krb5_error_code +get_cookie_key(krb5_context context, krb5_db_entry *tgt, + krb5_keyblock *tgt_key, krb5_kvno kvno, + krb5_const_principal client_princ, krb5_keyblock **key_out) +{ + krb5_error_code ret; + krb5_keyblock storage, *key; + krb5_key_data *kd; + + *key_out = NULL; + memset(&storage, 0, sizeof(storage)); + + if (kvno == current_kvno(tgt)) { + /* Use the already-decrypted first key. */ + key = tgt_key; + } else { + /* The cookie used an older TGT key; find and decrypt it. */ + ret = krb5_dbe_find_enctype(context, tgt, -1, -1, kvno, &kd); + if (ret) + return ret; + ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &storage, NULL); + if (ret) + return ret; + key = &storage; + } + + ret = derive_cookie_key(context, key, client_princ, key_out); + krb5_free_keyblock_contents(context, &storage); + return ret; +} + +/* Return true if there is any overlap between padata types in cpadata + * (from the cookie) and rpadata (from the request). */ +static krb5_boolean +is_relevant(krb5_pa_data *const *cpadata, krb5_pa_data *const *rpadata) +{ + krb5_pa_data *const *p; + + for (p = cpadata; p != NULL && *p != NULL; p++) { + if (krb5int_find_pa_data(NULL, rpadata, (*p)->pa_type) != NULL) + return TRUE; + } + return FALSE; +} + +/* + * Locate and decode the FAST cookie in req, storing its contents in state for + * later access by preauth modules. If the cookie is expired, return + * KRB5KDC_ERR_PREAUTH_EXPIRED if its contents are relevant to req, and ignore + * it if they aren't. + */ +krb5_error_code +kdc_fast_read_cookie(krb5_context context, struct kdc_request_state *state, + krb5_kdc_req *req, krb5_db_entry *local_tgt, + krb5_keyblock *local_tgt_key) +{ + krb5_error_code ret; + krb5_secure_cookie *cookie = NULL; + krb5_timestamp now; + krb5_keyblock *key = NULL; + krb5_enc_data enc; + krb5_pa_data *pa; + krb5_kvno kvno; + krb5_data plain = empty_data(); + + pa = krb5int_find_pa_data(context, req->padata, KRB5_PADATA_FX_COOKIE); + if (pa == NULL) + return 0; + + /* If it's not an MIT version 1 cookie, ignore it. It may be an empty + * "MIT" cookie or a cookie generated by a different KDC implementation. */ + if (pa->length <= 8 || memcmp(pa->contents, "MIT1", 4) != 0) + return 0; + + /* Extract the kvno and generate the corresponding cookie key. */ + kvno = load_32_be(pa->contents + 4); + ret = get_cookie_key(context, local_tgt, local_tgt_key, kvno, req->client, + &key); + if (ret) + goto cleanup; + + /* Decrypt and decode the cookie. */ + memset(&enc, 0, sizeof(enc)); + enc.enctype = key->enctype; + enc.ciphertext = make_data(pa->contents + 8, pa->length - 8); + ret = alloc_data(&plain, pa->length - 8); + if (ret) + goto cleanup; + ret = krb5_c_decrypt(context, key, KRB5_KEYUSAGE_PA_FX_COOKIE, NULL, &enc, + &plain); + if (ret) + goto cleanup; + ret = decode_krb5_secure_cookie(&plain, &cookie); + if (ret) + goto cleanup; + + /* Check if the cookie is expired. */ + ret = krb5_timeofday(context, &now); + if (ret) + goto cleanup; + if (ts2tt(now) > cookie->time + COOKIE_LIFETIME) { + /* Don't accept the cookie contents. Only return an error if the + * cookie is relevant to the request. */ + if (is_relevant(cookie->data, req->padata)) + ret = KRB5KDC_ERR_PREAUTH_EXPIRED; + goto cleanup; + } + + /* Steal the pa-data list pointer from the cookie and store it in state. */ + state->in_cookie_padata = cookie->data; + cookie->data = NULL; + +cleanup: + zapfree(plain.data, plain.length); + krb5_free_keyblock(context, key); + k5_free_secure_cookie(context, cookie); + return 0; +} + +/* If state contains a cookie value for pa_type, set *out to the corresponding + * data and return true. Otherwise set *out to empty and return false. */ +krb5_boolean +kdc_fast_search_cookie(struct kdc_request_state *state, + krb5_preauthtype pa_type, krb5_data *out) +{ + krb5_pa_data *pa; + + pa = krb5int_find_pa_data(NULL, state->in_cookie_padata, pa_type); + if (pa == NULL) { + *out = empty_data(); + return FALSE; + } else { + *out = make_data(pa->contents, pa->length); + return TRUE; + } +} + +/* Set a cookie value in state for data, to be included in the outgoing + * cookie. Duplicate values are ignored. */ +krb5_error_code +kdc_fast_set_cookie(struct kdc_request_state *state, krb5_preauthtype pa_type, + const krb5_data *data) +{ + krb5_pa_data **list = state->out_cookie_padata; + size_t count; + + for (count = 0; list != NULL && list[count] != NULL; count++) { + if (list[count]->pa_type == pa_type) + return 0; + } + + list = realloc(list, (count + 2) * sizeof(*list)); + if (list == NULL) + return ENOMEM; + state->out_cookie_padata = list; + list[count] = list[count + 1] = NULL; + return make_padata(pa_type, data->data, data->length, &list[count]); +} + +/* Construct a cookie pa-data item using the cookie values from state, or a + * trivial "MIT" cookie if no values are set. */ +krb5_error_code +kdc_fast_make_cookie(krb5_context context, struct kdc_request_state *state, + krb5_db_entry *local_tgt, krb5_keyblock *local_tgt_key, + krb5_const_principal client_princ, + krb5_pa_data **cookie_out) +{ + krb5_error_code ret; + krb5_secure_cookie cookie; + krb5_pa_data **contents = state->out_cookie_padata, *pa; + krb5_keyblock *key = NULL; + krb5_timestamp now; + krb5_enc_data enc; + krb5_data *der_cookie = NULL; + size_t ctlen; + + *cookie_out = NULL; + memset(&enc, 0, sizeof(enc)); + + /* Make a trivial cookie if there are no contents to marshal or we don't + * have a TGT entry to encrypt them. */ + if (contents == NULL || *contents == NULL || local_tgt_key == NULL) + return make_padata(KRB5_PADATA_FX_COOKIE, "MIT", 3, cookie_out); + + ret = derive_cookie_key(context, local_tgt_key, client_princ, &key); + if (ret) + goto cleanup; + + /* Encode the cookie. */ + ret = krb5_timeofday(context, &now); + if (ret) + goto cleanup; + cookie.time = ts2tt(now); + cookie.data = contents; + ret = encode_krb5_secure_cookie(&cookie, &der_cookie); + if (ret) + goto cleanup; + + /* Encrypt the cookie in key. */ + ret = krb5_c_encrypt_length(context, key->enctype, der_cookie->length, + &ctlen); + if (ret) + goto cleanup; + ret = alloc_data(&enc.ciphertext, ctlen); + if (ret) + goto cleanup; + ret = krb5_c_encrypt(context, key, KRB5_KEYUSAGE_PA_FX_COOKIE, NULL, + der_cookie, &enc); + if (ret) + goto cleanup; + + /* Construct the cookie pa-data entry. */ + ret = k5_alloc_pa_data(KRB5_PADATA_FX_COOKIE, 8 + enc.ciphertext.length, + &pa); + memcpy(pa->contents, "MIT1", 4); + store_32_be(current_kvno(local_tgt), pa->contents + 4); + memcpy(pa->contents + 8, enc.ciphertext.data, enc.ciphertext.length); + *cookie_out = pa; + +cleanup: + krb5_free_keyblock(context, key); + if (der_cookie != NULL) { + zapfree(der_cookie->data, der_cookie->length); + free(der_cookie); + } + krb5_free_data_contents(context, &enc.ciphertext); + return ret; +} diff --git a/krb5-1.21.3/src/kdc/kdc5_err.et b/krb5-1.21.3/src/kdc/kdc5_err.et new file mode 100644 index 00000000..9d0ce877 --- /dev/null +++ b/krb5-1.21.3/src/kdc/kdc5_err.et @@ -0,0 +1,35 @@ +# +# kdc/kdc5_err.et +# +# Copyright 1990 by the Massachusetts Institute of Technology. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. +# +# +# KDC internal error table. + +error_table kdc5 + +error_code KDC5_RCSID, "$Id$" +error_code KDC5_NOPORT, "No server port found" +error_code KDC5_NONET, "Network not initialized" +error_code KDC5_IO_RESPONSE, "Short write while sending response" + +end diff --git a/krb5-1.21.3/src/kdc/kdc_audit.c b/krb5-1.21.3/src/kdc/kdc_audit.c new file mode 100644 index 00000000..2333171d --- /dev/null +++ b/krb5-1.21.3/src/kdc/kdc_audit.c @@ -0,0 +1,332 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc_audit.c - Interface for KDC audit plugins. */ +/* + * 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. + */ + +#include "k5-int.h" +#include "kdc_util.h" +#include "kdc_audit.h" +/* for krb5_klog_syslog */ +#include +#include "adm_proto.h" + +struct audit_module_handle_st { + struct krb5_audit_vtable_st vt; + krb5_audit_moddata auctx; +}; +typedef struct audit_module_handle_st *audit_module_handle; + +static audit_module_handle *handles = NULL; + +static void +free_handles(audit_module_handle *list) +{ + audit_module_handle *hp, hdl; + + if (list == NULL) + return; + + for (hp = list; *hp != NULL; hp++) { + hdl = *hp; + if (hdl->vt.close != NULL) + hdl->vt.close(hdl->auctx); + free(hdl); + } + free(list); +} + +/* + * Load all available audit plugin modules and prepare for logging. The list of + * modules is stored as an array in handles. Use unload_audit_modules() to free + * resources allocated by this function. + */ +krb5_error_code +load_audit_modules(krb5_context context) +{ + krb5_error_code ret = 0; + krb5_plugin_initvt_fn *modules = NULL, *mod; + struct krb5_audit_vtable_st vtable; + audit_module_handle *list = NULL, hdl = NULL; + krb5_audit_moddata auctx; + int count = 0; + + if (context == NULL || handles != NULL) + return EINVAL; + + /* Get audit plugin vtable. */ + ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_AUDIT, &modules); + if (ret) + return ret; + + /* Allocate handle, initialize vtable. */ + for (count = 0; modules[count] != NULL; count++); + list = k5calloc(count + 1, sizeof(*list), &ret); + if (list == NULL) + goto cleanup; + count = 0; + for (mod = modules; *mod != NULL; mod++) { + hdl = k5alloc(sizeof(*hdl), &ret); + if (hdl == NULL) + goto cleanup; + ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&hdl->vt); + if (ret) { + free(hdl); + hdl = NULL; + continue; + } + + vtable = hdl->vt; + if (vtable.open != NULL) { + ret = vtable.open(&auctx); + if (ret) { + krb5_klog_syslog(LOG_ERR, + _("audit plugin %s failed to open. error=%i"), + vtable.name, ret); + goto cleanup; + } + hdl->auctx = auctx; + } + list[count++] = hdl; + list[count] = NULL; + hdl = NULL; + } + list[count] = NULL; + handles = list; + list = NULL; + ret = 0; + +cleanup: + free(hdl); + k5_plugin_free_modules(context, modules); + free_handles(list); + return ret; +} + +/* Free resources allocated by load_audit_modules() function. */ +void +unload_audit_modules(krb5_context context) +{ + free_handles(handles); +} + +/* + * Write the output ticket ID into newly-allocated buffer. + * Returns 0 on success. + */ +krb5_error_code +kau_make_tkt_id(krb5_context context, + const krb5_ticket *ticket, char **out) +{ + krb5_error_code ret = 0; + char *hash = NULL, *ptr; + uint8_t hashbytes[K5_SHA256_HASHLEN]; + unsigned int i; + + *out = NULL; + + if (ticket == NULL) + return EINVAL; + + ret = k5_sha256(&ticket->enc_part.ciphertext, 1, hashbytes); + if (ret) + return ret; + + hash = k5alloc(sizeof(hashbytes) * 2 + 1, &ret); + if (hash == NULL) + return ret; + + for (i = 0, ptr = hash; i < sizeof(hashbytes); i++, ptr += 2) + snprintf(ptr, 3, "%02X", hashbytes[i]); + *ptr = '\0'; + *out = hash; + + return 0; +} + +/* + * Create and initialize krb5_audit_state structure. + * Returns 0 on success. + */ +krb5_error_code +kau_init_kdc_req(krb5_context context, + krb5_kdc_req *request, const krb5_fulladdr *from, + krb5_audit_state **state_out) +{ + krb5_error_code ret = 0; + krb5_audit_state *state = NULL; + + state = k5calloc(1, sizeof(*state), &ret); + if (state == NULL) + return ret; + + state->request = request; + state->cl_addr = from->address; + state->cl_port = from->port; + state->stage = AUTHN_REQ_CL; + ret = krb5int_random_string(context, state->req_id, + sizeof(state->req_id)); + if (ret) { + free(state); + return ret; + } + *state_out = state; + + return 0; +} + +/* Free resources allocated by kau_init_kdc_req() and kau_make_tkt_id() + * routines. */ +void +kau_free_kdc_req(krb5_audit_state *state) +{ + if (state == NULL) + return; + free(state->tkt_in_id); + free(state->tkt_out_id); + free(state->evid_tkt_id); + free(state); +} + +/* Call the KDC start/stop audit plugin entry points. */ + +void +kau_kdc_stop(krb5_context context, const krb5_boolean ev_success) +{ + audit_module_handle *hp, hdl; + + if (handles == NULL) + return; + + for (hp = handles; *hp != NULL; hp++) { + hdl = *hp; + if (hdl->vt.kdc_stop != NULL) + hdl->vt.kdc_stop(hdl->auctx, ev_success); + } +} + +void +kau_kdc_start(krb5_context context, const krb5_boolean ev_success) +{ + audit_module_handle *hp, hdl; + + if (handles == NULL) + return; + + for (hp = handles; *hp != NULL; hp++) { + hdl = *hp; + if (hdl->vt.kdc_start != NULL) + hdl->vt.kdc_start(hdl->auctx, ev_success); + } +} + +/* Call the AS-REQ audit plugin entry point. */ +void +kau_as_req(krb5_context context, const krb5_boolean ev_success, + krb5_audit_state *state) +{ + audit_module_handle *hp, hdl; + + if (handles == NULL) + return; + + for (hp = handles; *hp != NULL; hp++) { + hdl = *hp; + if (hdl->vt.as_req != NULL) + hdl->vt.as_req(hdl->auctx, ev_success, state); + } +} + +/* Call the TGS-REQ audit plugin entry point. */ +void +kau_tgs_req(krb5_context context, const krb5_boolean ev_success, + krb5_audit_state *state) +{ + audit_module_handle *hp, hdl; + + if (handles == NULL) + return; + + for (hp = handles; *hp != NULL; hp++) { + hdl = *hp; + if (hdl->vt.tgs_req != NULL) + hdl->vt.tgs_req(hdl->auctx, ev_success, state); + } +} + +/* Call the S4U2Self audit plugin entry point. */ +void +kau_s4u2self(krb5_context context, const krb5_boolean ev_success, + krb5_audit_state *state) +{ + audit_module_handle *hp, hdl; + + if (handles == NULL) + return; + + for (hp = handles; *hp != NULL; hp++) { + hdl = *hp; + if (hdl->vt.tgs_s4u2self != NULL) + hdl->vt.tgs_s4u2self(hdl->auctx, ev_success, state); + } +} + +/* Call the S4U2Proxy audit plugin entry point. */ +void +kau_s4u2proxy(krb5_context context,const krb5_boolean ev_success, + krb5_audit_state *state) +{ + audit_module_handle *hp, hdl; + + if (handles == NULL) + return; + + for (hp = handles; *hp != NULL; hp++) { + hdl = *hp; + if (hdl->vt.tgs_s4u2proxy != NULL) + hdl->vt.tgs_s4u2proxy(hdl->auctx, ev_success, state); + } +} + +/* Call the U2U audit plugin entry point. */ +void +kau_u2u(krb5_context context, const krb5_boolean ev_success, + krb5_audit_state *state) +{ + audit_module_handle *hp, hdl; + + if (handles == NULL) + return; + + for (hp = handles; *hp != NULL; hp++) { + hdl = *hp; + if (hdl->vt.tgs_u2u != NULL) + hdl->vt.tgs_u2u(hdl->auctx, ev_success, state); + } +} diff --git a/krb5-1.21.3/src/kdc/kdc_audit.h b/krb5-1.21.3/src/kdc/kdc_audit.h new file mode 100644 index 00000000..c2f2e217 --- /dev/null +++ b/krb5-1.21.3/src/kdc/kdc_audit.h @@ -0,0 +1,82 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/kdc_audit.h - KDC-facing API for audit */ +/* + * Copyright 2013 by the Massachusetts Institute of Technology. + * + * 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. + */ + +#ifndef KRB5_KDC_AUDIT__ +#define KRB5_KDC_AUDIT__ + +#include +#include +#include + +krb5_error_code load_audit_modules(krb5_context context); +void unload_audit_modules(krb5_context context); + +/* Utilities */ + +krb5_error_code +kau_make_tkt_id(krb5_context context, + const krb5_ticket *ticket, char **out); + +krb5_error_code +kau_init_kdc_req(krb5_context context, krb5_kdc_req *request, + const krb5_fulladdr *from, krb5_audit_state **au_state); + +void kau_free_kdc_req(krb5_audit_state *state); + +/* KDC-facing audit API */ + +void +kau_kdc_start(krb5_context context, const krb5_boolean ev_success); + +void +kau_kdc_stop(krb5_context context, const krb5_boolean ev_success); + +void +kau_as_req(krb5_context context, const krb5_boolean ev_success, + krb5_audit_state *state); + +void +kau_tgs_req(krb5_context context, const krb5_boolean ev_success, + krb5_audit_state *state); + +void +kau_s4u2self(krb5_context context, const krb5_boolean ev_success, + krb5_audit_state *state); + +void +kau_s4u2proxy(krb5_context context, const krb5_boolean ev_success, + krb5_audit_state *state); + +void +kau_u2u(krb5_context context, const krb5_boolean ev_success, + krb5_audit_state *state); + +#endif /* KRB5_KDC_AUDIT__ */ diff --git a/krb5-1.21.3/src/kdc/kdc_authdata.c b/krb5-1.21.3/src/kdc/kdc_authdata.c new file mode 100644 index 00000000..398df219 --- /dev/null +++ b/krb5-1.21.3/src/kdc/kdc_authdata.c @@ -0,0 +1,628 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/kdc_authdata.c - Authorization data routines for the KDC */ +/* + * Copyright (C) 2007 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009 by the Massachusetts Institute of Technology. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "kdc_util.h" +#include "extern.h" +#include +#include "adm_proto.h" + +#include + +#include +#include + +typedef struct kdcauthdata_handle_st { + struct krb5_kdcauthdata_vtable_st vt; + krb5_kdcauthdata_moddata data; +} kdcauthdata_handle; + +static kdcauthdata_handle *authdata_modules; +static size_t n_authdata_modules; + +/* Load authdata plugin modules. */ +krb5_error_code +load_authdata_plugins(krb5_context context) +{ + krb5_error_code ret; + krb5_plugin_initvt_fn *modules = NULL, *mod; + kdcauthdata_handle *list, *h; + size_t count; + + ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_KDCAUTHDATA, &modules); + if (ret) + return ret; + + /* Allocate a large enough list of handles. */ + for (count = 0; modules[count] != NULL; count++); + list = calloc(count + 1, sizeof(*list)); + if (list == NULL) { + k5_plugin_free_modules(context, modules); + return ENOMEM; + } + + /* Initialize each module's vtable and module data. */ + count = 0; + for (mod = modules; *mod != NULL; mod++) { + h = &list[count]; + memset(h, 0, sizeof(*h)); + ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&h->vt); + if (ret) /* Version mismatch, keep going. */ + continue; + if (h->vt.init != NULL) { + ret = h->vt.init(context, &h->data); + if (ret) { + kdc_err(context, ret, _("while loading authdata module %s"), + h->vt.name); + continue; + } + } + count++; + } + + authdata_modules = list; + n_authdata_modules = count; + k5_plugin_free_modules(context, modules); + return 0; +} + +krb5_error_code +unload_authdata_plugins(krb5_context context) +{ + kdcauthdata_handle *h; + size_t i; + + for (i = 0; i < n_authdata_modules; i++) { + h = &authdata_modules[i]; + if (h->vt.fini != NULL) + h->vt.fini(context, h->data); + } + free(authdata_modules); + authdata_modules = NULL; + return 0; +} + +/* Return true if authdata should be filtered when copying from untrusted + * authdata. If desired_type is non-zero, look only for that type. */ +static krb5_boolean +is_kdc_issued_authdatum(krb5_authdata *authdata, + krb5_authdatatype desired_type) +{ + krb5_boolean result = FALSE; + krb5_authdatatype ad_type; + unsigned int i, count = 0; + krb5_authdatatype *ad_types, *containee_types = NULL; + + if (authdata->ad_type == KRB5_AUTHDATA_IF_RELEVANT) { + if (krb5int_get_authdata_containee_types(NULL, authdata, &count, + &containee_types) != 0) + goto cleanup; + ad_types = containee_types; + } else { + ad_type = authdata->ad_type; + count = 1; + ad_types = &ad_type; + } + + for (i = 0; i < count; i++) { + switch (ad_types[i]) { + case KRB5_AUTHDATA_SIGNTICKET: + case KRB5_AUTHDATA_KDC_ISSUED: + case KRB5_AUTHDATA_WIN2K_PAC: + case KRB5_AUTHDATA_CAMMAC: + case KRB5_AUTHDATA_AUTH_INDICATOR: + result = desired_type ? (desired_type == ad_types[i]) : TRUE; + break; + default: + result = FALSE; + break; + } + if (result) + break; + } + +cleanup: + free(containee_types); + return result; +} + +/* Return true if authdata contains any mandatory-for-KDC elements. */ +static krb5_boolean +has_mandatory_for_kdc_authdata(krb5_context context, krb5_authdata **authdata) +{ + int i; + + if (authdata == NULL) + return FALSE; + for (i = 0; authdata[i] != NULL; i++) { + if (authdata[i]->ad_type == KRB5_AUTHDATA_MANDATORY_FOR_KDC) + return TRUE; + } + return FALSE; +} + +/* Add elements from *new_elements to *existing_list, reallocating as + * necessary. On success, release *new_elements and set it to NULL. */ +static krb5_error_code +merge_authdata(krb5_authdata ***existing_list, krb5_authdata ***new_elements) +{ + size_t count = 0, ncount = 0; + krb5_authdata **list = *existing_list, **nlist = *new_elements; + + if (nlist == NULL) + return 0; + + for (count = 0; list != NULL && list[count] != NULL; count++); + for (ncount = 0; nlist[ncount] != NULL; ncount++); + + list = realloc(list, (count + ncount + 1) * sizeof(*list)); + if (list == NULL) + return ENOMEM; + + memcpy(list + count, nlist, ncount * sizeof(*nlist)); + list[count + ncount] = NULL; + free(nlist); + + if (list[0] == NULL) { + free(list); + list = NULL; + } + + *new_elements = NULL; + *existing_list = list; + return 0; +} + +/* Add a copy of new_elements to *existing_list, omitting KDC-issued + * authdata. */ +static krb5_error_code +add_filtered_authdata(krb5_authdata ***existing_list, + krb5_authdata **new_elements) +{ + krb5_error_code ret; + krb5_authdata **copy; + size_t i, j; + + if (new_elements == NULL) + return 0; + + ret = krb5_copy_authdata(NULL, new_elements, ©); + if (ret) + return ret; + + /* Remove KDC-issued elements from copy. */ + j = 0; + for (i = 0; copy[i] != NULL; i++) { + if (is_kdc_issued_authdatum(copy[i], 0)) { + free(copy[i]->contents); + free(copy[i]); + } else { + copy[j++] = copy[i]; + } + } + copy[j] = NULL; + + /* Destructively merge the filtered copy into existing_list. */ + ret = merge_authdata(existing_list, ©); + krb5_free_authdata(NULL, copy); + return ret; +} + +/* Copy TGS-REQ authorization data into the ticket authdata. */ +static krb5_error_code +copy_request_authdata(krb5_context context, krb5_keyblock *client_key, + krb5_kdc_req *req, krb5_enc_tkt_part *enc_tkt_req, + krb5_authdata ***tkt_authdata) +{ + krb5_error_code ret; + krb5_data plaintext; + + assert(enc_tkt_req != NULL); + + ret = alloc_data(&plaintext, req->authorization_data.ciphertext.length); + if (ret) + return ret; + + /* + * RFC 4120 requires authdata in the TGS body to be encrypted in the subkey + * with usage 5 if a subkey is present, and in the TGS session key with key + * usage 4 if it is not. Prior to krb5 1.7, we got this wrong, always + * decrypting the authorization data with the TGS session key and usage 4. + * For the sake of conservatism, try the decryption the old way (wrong if + * client_key is a subkey) first, and then try again the right way (in the + * case where client_key is a subkey) if the first way fails. + */ + ret = krb5_c_decrypt(context, enc_tkt_req->session, + KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY, 0, + &req->authorization_data, &plaintext); + if (ret) { + ret = krb5_c_decrypt(context, client_key, + KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY, 0, + &req->authorization_data, &plaintext); + } + if (ret) + goto cleanup; + + /* Decode the decrypted authdata and make it available to modules in the + * request. */ + ret = decode_krb5_authdata(&plaintext, &req->unenc_authdata); + if (ret) + goto cleanup; + + if (has_mandatory_for_kdc_authdata(context, req->unenc_authdata)) { + ret = KRB5KDC_ERR_POLICY; + goto cleanup; + } + + ret = add_filtered_authdata(tkt_authdata, req->unenc_authdata); + +cleanup: + free(plaintext.data); + return ret; +} + +/* Copy TGT authorization data into the ticket authdata. */ +static krb5_error_code +copy_tgt_authdata(krb5_context context, krb5_kdc_req *request, + krb5_authdata **tgt_authdata, krb5_authdata ***tkt_authdata) +{ + if (has_mandatory_for_kdc_authdata(context, tgt_authdata)) + return KRB5KDC_ERR_POLICY; + + return add_filtered_authdata(tkt_authdata, tgt_authdata); +} + +/* Add authentication indicator authdata to enc_tkt_reply, wrapped in a CAMMAC + * and an IF-RELEVANT container. */ +static krb5_error_code +add_auth_indicators(krb5_context context, krb5_data *const *auth_indicators, + krb5_keyblock *server_key, krb5_db_entry *krbtgt, + krb5_keyblock *krbtgt_key, + krb5_enc_tkt_part *enc_tkt_reply) +{ + krb5_error_code ret; + krb5_data *der_indicators = NULL; + krb5_authdata ad, *list[2], **cammac = NULL; + + if (auth_indicators == NULL || *auth_indicators == NULL) + return 0; + + /* Format the authentication indicators into an authdata list. */ + ret = encode_utf8_strings(auth_indicators, &der_indicators); + if (ret) + goto cleanup; + ad.ad_type = KRB5_AUTHDATA_AUTH_INDICATOR; + ad.length = der_indicators->length; + ad.contents = (uint8_t *)der_indicators->data; + list[0] = &ad; + list[1] = NULL; + + /* Wrap the list in CAMMAC and IF-RELEVANT containers. */ + ret = cammac_create(context, enc_tkt_reply, server_key, krbtgt, krbtgt_key, + list, &cammac); + if (ret) + goto cleanup; + + /* Add the wrapped authdata to the ticket, without copying or filtering. */ + ret = merge_authdata(&enc_tkt_reply->authorization_data, &cammac); + +cleanup: + krb5_free_data(context, der_indicators); + krb5_free_authdata(context, cammac); + return ret; +} + +/* Extract any properly verified authentication indicators from the authdata in + * enc_tkt. */ +krb5_error_code +get_auth_indicators(krb5_context context, krb5_enc_tkt_part *enc_tkt, + krb5_db_entry *local_tgt, krb5_keyblock *local_tgt_key, + krb5_data ***indicators_out) +{ + krb5_error_code ret; + krb5_authdata **cammacs = NULL, **adp; + krb5_cammac *cammac = NULL; + krb5_data **indicators = NULL, der_cammac; + + *indicators_out = NULL; + + ret = krb5_find_authdata(context, enc_tkt->authorization_data, NULL, + KRB5_AUTHDATA_CAMMAC, &cammacs); + if (ret) + goto cleanup; + + for (adp = cammacs; adp != NULL && *adp != NULL; adp++) { + der_cammac = make_data((*adp)->contents, (*adp)->length); + ret = decode_krb5_cammac(&der_cammac, &cammac); + if (ret) + goto cleanup; + if (cammac_check_kdcver(context, cammac, enc_tkt, local_tgt, + local_tgt_key)) { + ret = authind_extract(context, cammac->elements, &indicators); + if (ret) + goto cleanup; + } + k5_free_cammac(context, cammac); + cammac = NULL; + } + + *indicators_out = indicators; + indicators = NULL; + +cleanup: + krb5_free_authdata(context, cammacs); + k5_free_cammac(context, cammac); + k5_free_data_ptr_list(indicators); + return ret; +} + +static krb5_error_code +update_delegation_info(krb5_context context, krb5_kdc_req *req, + krb5_pac old_pac, krb5_pac new_pac) +{ + krb5_error_code ret; + krb5_data ndr_di_in = empty_data(), ndr_di_out = empty_data(); + struct pac_s4u_delegation_info *di = NULL; + char *namestr = NULL; + + ret = krb5_pac_get_buffer(context, old_pac, KRB5_PAC_DELEGATION_INFO, + &ndr_di_in); + if (ret && ret != ENOENT) + goto cleanup; + if (ret) { + /* Create new delegation info. */ + di = k5alloc(sizeof(*di), &ret); + if (di == NULL) + goto cleanup; + di->transited_services = k5calloc(1, sizeof(char *), &ret); + if (di->transited_services == NULL) + goto cleanup; + } else { + /* Decode and modify old delegation info. */ + ret = ndr_dec_delegation_info(&ndr_di_in, &di); + if (ret) + goto cleanup; + } + + /* Set proxy_target to the requested server, without realm. */ + ret = krb5_unparse_name_flags(context, req->server, + KRB5_PRINCIPAL_UNPARSE_DISPLAY | + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &namestr); + if (ret) + goto cleanup; + free(di->proxy_target); + di->proxy_target = namestr; + + /* Add a transited entry for the requesting service, with realm. */ + assert(req->second_ticket != NULL && req->second_ticket[0] != NULL); + ret = krb5_unparse_name(context, req->second_ticket[0]->server, &namestr); + if (ret) + goto cleanup; + di->transited_services[di->transited_services_length++] = namestr; + + ret = ndr_enc_delegation_info(di, &ndr_di_out); + if (ret) + goto cleanup; + + ret = krb5_pac_add_buffer(context, new_pac, KRB5_PAC_DELEGATION_INFO, + &ndr_di_out); + +cleanup: + krb5_free_data_contents(context, &ndr_di_in); + krb5_free_data_contents(context, &ndr_di_out); + ndr_free_delegation_info(di); + return ret; +} + +static krb5_error_code +copy_pac_buffer(krb5_context context, uint32_t buffer_type, krb5_pac old_pac, + krb5_pac new_pac) +{ + krb5_error_code ret; + krb5_data data; + + ret = krb5_pac_get_buffer(context, old_pac, buffer_type, &data); + if (ret) + return ret; + ret = krb5_pac_add_buffer(context, new_pac, buffer_type, &data); + krb5_free_data_contents(context, &data); + return ret; +} + +/* + * Possibly add a signed PAC to enc_tkt_reply. Also possibly add auth + * indicators; these are handled here so that the KDB module's issue_pac() + * method can alter the auth indicator list. + */ +static krb5_error_code +handle_pac(kdc_realm_t *realm, unsigned int flags, krb5_db_entry *client, + krb5_db_entry *server, krb5_db_entry *subject_server, + krb5_db_entry *local_tgt, krb5_keyblock *local_tgt_key, + krb5_keyblock *server_key, krb5_keyblock *subject_key, + krb5_keyblock *replaced_reply_key, krb5_enc_tkt_part *subject_tkt, + krb5_pac subject_pac, krb5_kdc_req *req, + krb5_const_principal altcprinc, krb5_timestamp authtime, + krb5_enc_tkt_part *enc_tkt_reply, krb5_data ***auth_indicators) +{ + krb5_context context = realm->realm_context; + krb5_error_code ret; + krb5_pac new_pac = NULL; + krb5_const_principal pac_client = NULL; + krb5_boolean with_realm, is_as_req = (req->msg_type == KRB5_AS_REQ); + krb5_db_entry *signing_tgt; + krb5_keyblock *privsvr_key = NULL; + + /* Don't add a PAC or auth indicators if the server disables authdata. */ + if (server->attributes & KRB5_KDB_NO_AUTH_DATA_REQUIRED) + return 0; + + /* + * Don't add a PAC if the realm disables them, or to an anonymous ticket, + * or for an AS-REQ if the client requested not to get one, or for a + * TGS-REQ if the subject ticket didn't contain one. + */ + if (realm->realm_disable_pac || + (enc_tkt_reply->flags & TKT_FLG_ANONYMOUS) || + (is_as_req && !include_pac_p(context, req)) || + (!is_as_req && subject_pac == NULL)) { + return add_auth_indicators(context, *auth_indicators, server_key, + local_tgt, local_tgt_key, enc_tkt_reply); + } + + ret = krb5_pac_init(context, &new_pac); + if (ret) + goto cleanup; + + if (subject_pac == NULL) + signing_tgt = NULL; + else if (krb5_is_tgs_principal(subject_server->princ)) + signing_tgt = subject_server; + else + signing_tgt = local_tgt; + + ret = krb5_db_issue_pac(context, flags, client, replaced_reply_key, server, + signing_tgt, authtime, subject_pac, new_pac, + auth_indicators); + if (ret) { + if (ret == KRB5_PLUGIN_OP_NOTSUPP) + ret = 0; + if (ret) + goto cleanup; + } + + ret = add_auth_indicators(context, *auth_indicators, server_key, + local_tgt, local_tgt_key, enc_tkt_reply); + + if ((flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) && + !(flags & KRB5_KDB_FLAG_CROSS_REALM)) { + /* Add delegation info for the first S4U2Proxy request. */ + ret = update_delegation_info(context, req, subject_pac, new_pac); + if (ret) + goto cleanup; + } else if (subject_pac != NULL) { + /* Copy delegation info if it was present in the subject PAC. */ + ret = copy_pac_buffer(context, KRB5_PAC_DELEGATION_INFO, subject_pac, + new_pac); + if (ret && ret != ENOENT) + goto cleanup; + } + + if ((flags & KRB5_KDB_FLAGS_S4U) && + (flags & KRB5_KDB_FLAG_ISSUING_REFERRAL)) { + /* When issuing a referral for either kind of S4U request, add client + * info for the subject with realm. */ + pac_client = altcprinc; + with_realm = TRUE; + } else if (subject_pac == NULL || (flags & KRB5_KDB_FLAGS_S4U)) { + /* For a new PAC or when issuing a final ticket for either kind of S4U + * request, add client info for the ticket client without the realm. */ + pac_client = enc_tkt_reply->client; + with_realm = FALSE; + } else { + /* + * For regular TGS and transitive RBCD requests, copy the client info + * from the incoming PAC, and don't add client info during signing. We + * validated the incoming client info in validate_tgs_request(). + */ + ret = copy_pac_buffer(context, KRB5_PAC_CLIENT_INFO, subject_pac, + new_pac); + if (ret) + goto cleanup; + pac_client = NULL; + with_realm = FALSE; + } + + ret = pac_privsvr_key(context, server, local_tgt_key, &privsvr_key); + if (ret) + goto cleanup; + ret = krb5_kdc_sign_ticket(context, enc_tkt_reply, new_pac, server->princ, + pac_client, server_key, privsvr_key, + with_realm); + if (ret) + goto cleanup; + + ret = 0; + +cleanup: + krb5_pac_free(context, new_pac); + krb5_free_keyblock(context, privsvr_key); + return ret; +} + +krb5_error_code +handle_authdata(kdc_realm_t *realm, unsigned int flags, krb5_db_entry *client, + krb5_db_entry *server, krb5_db_entry *subject_server, + krb5_db_entry *local_tgt, krb5_keyblock *local_tgt_key, + krb5_keyblock *client_key, krb5_keyblock *server_key, + krb5_keyblock *subject_key, krb5_keyblock *replaced_reply_key, + krb5_data *req_pkt, krb5_kdc_req *req, + krb5_const_principal altcprinc, krb5_pac subject_pac, + krb5_enc_tkt_part *enc_tkt_req, krb5_data ***auth_indicators, + krb5_enc_tkt_part *enc_tkt_reply) +{ + krb5_context context = realm->realm_context; + kdcauthdata_handle *h; + krb5_error_code ret = 0; + size_t i; + + if (req->msg_type == KRB5_TGS_REQ && + req->authorization_data.ciphertext.data != NULL) { + /* Copy TGS request authdata. This must be done first so that modules + * have access to the unencrypted request authdata. */ + ret = copy_request_authdata(context, client_key, req, enc_tkt_req, + &enc_tkt_reply->authorization_data); + if (ret) + return ret; + } + + /* Invoke loaded module handlers. */ + if (!isflagset(enc_tkt_reply->flags, TKT_FLG_ANONYMOUS)) { + for (i = 0; i < n_authdata_modules; i++) { + h = &authdata_modules[i]; + ret = h->vt.handle(context, h->data, flags, client, server, + subject_server, client_key, server_key, + subject_key, req_pkt, req, altcprinc, + enc_tkt_req, enc_tkt_reply); + if (ret) + kdc_err(context, ret, "from authdata module %s", h->vt.name); + } + } + + if (req->msg_type == KRB5_TGS_REQ) { + /* Copy authdata from the TGT to the issued ticket. */ + ret = copy_tgt_authdata(context, req, enc_tkt_req->authorization_data, + &enc_tkt_reply->authorization_data); + if (ret) + return ret; + } + + return handle_pac(realm, flags, client, server, subject_server, local_tgt, + local_tgt_key, server_key, subject_key, + replaced_reply_key, enc_tkt_req, subject_pac, req, + altcprinc, enc_tkt_reply->times.authtime, enc_tkt_reply, + auth_indicators); +} diff --git a/krb5-1.21.3/src/kdc/kdc_log.c b/krb5-1.21.3/src/kdc/kdc_log.c new file mode 100644 index 00000000..9a8894c9 --- /dev/null +++ b/krb5-1.21.3/src/kdc/kdc_log.c @@ -0,0 +1,235 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/kdc_log.c - Logging functions for KDC requests */ +/* + * Copyright 2008,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "kdc_util.h" +#include +#include "adm_proto.h" + +/* + * A note on KDC-status string format. + * + * - All letters in the status string should be capitalized; + * - the words in the status phrase are separated by underscores; + * - abbreviations should be avoided. Some acceptable "standard" acronyms + * are AS_REQ, TGS_REP etc. + * - since in almost all cases KDC status string is set on error, no need + * to state this fact as part of the status string; + * - KDC status string should be an imperative phrase. + * + * Example: "MAKE_RANDOM_KEY" + */ + +/* Main logging routines for ticket requests. + + There are a few simple cases -- unparseable requests mainly -- + where messages are logged otherwise, but once a ticket request can + be decoded in some basic way, these routines are used for logging + the details. */ + +/* "status" is null to indicate success. */ +/* Someday, pass local address/port as well. */ +/* Currently no info about name canonicalization is logged. */ +void +log_as_req(krb5_context context, + const krb5_fulladdr *local_addr, + const krb5_fulladdr *remote_addr, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_db_entry *client, const char *cname, + krb5_db_entry *server, const char *sname, + krb5_timestamp authtime, + const char *status, krb5_error_code errcode, const char *emsg) +{ + const char *fromstring = 0; + char fromstringbuf[70]; + char *ktypestr = NULL; + const char *cname2 = cname ? cname : ""; + const char *sname2 = sname ? sname : ""; + + fromstring = inet_ntop(ADDRTYPE2FAMILY(remote_addr->address->addrtype), + remote_addr->address->contents, + fromstringbuf, sizeof(fromstringbuf)); + if (!fromstring) + fromstring = ""; + + ktypestr = ktypes2str(request->ktype, request->nktypes); + + if (status == NULL) { + /* success */ + char *rep_etypestr = rep_etypes2str(reply); + krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: ISSUE: authtime %u, %s, " + "%s for %s"), + ktypestr ? ktypestr : "", fromstring, + (unsigned int)authtime, + rep_etypestr ? rep_etypestr : "", cname2, sname2); + free(rep_etypestr); + } else { + /* fail */ + krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: %s: %s for %s%s%s"), + ktypestr ? ktypestr : "", fromstring, status, cname2, + sname2, emsg ? ", " : "", emsg ? emsg : ""); + } + krb5_db_audit_as_req(context, request, + local_addr->address, remote_addr->address, + client, server, authtime, errcode); + + free(ktypestr); +} + +/* + * Unparse a principal for logging purposes and limit the string length. + * Ignore errors because the most likely errors are memory exhaustion, and many + * other things will fail in the logging functions in that case. + */ +static void +unparse_and_limit(krb5_context ctx, krb5_principal princ, char **str) +{ + /* Ignore errors */ + krb5_unparse_name(ctx, princ, str); + limit_string(*str); +} + +/* Here "status" must be non-null. Error code + KRB5KDC_ERR_SERVER_NOMATCH is handled specially. + + Currently no info about name canonicalization is logged. */ +void +log_tgs_req(krb5_context ctx, const krb5_fulladdr *from, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_principal cprinc, krb5_principal sprinc, + krb5_principal altcprinc, + krb5_timestamp authtime, + unsigned int c_flags, + const char *status, krb5_error_code errcode, const char *emsg) +{ + char *ktypestr = NULL, *rep_etypestr = NULL; + const char *fromstring = 0; + char fromstringbuf[70]; + char *cname = NULL, *sname = NULL, *altcname = NULL; + char *logcname = NULL, *logsname = NULL, *logaltcname = NULL; + + fromstring = inet_ntop(ADDRTYPE2FAMILY(from->address->addrtype), + from->address->contents, + fromstringbuf, sizeof(fromstringbuf)); + if (!fromstring) + fromstring = ""; + + unparse_and_limit(ctx, cprinc, &cname); + logcname = (cname != NULL) ? cname : ""; + unparse_and_limit(ctx, sprinc, &sname); + logsname = (sname != NULL) ? sname : ""; + unparse_and_limit(ctx, altcprinc, &altcname); + logaltcname = (altcname != NULL) ? altcname : ""; + + /* Differences: server-nomatch message logs 2nd ticket's client + name (useful), and doesn't log ktypestr (probably not + important). */ + if (errcode != KRB5KDC_ERR_SERVER_NOMATCH) { + ktypestr = ktypes2str(request->ktype, request->nktypes); + if (reply != NULL) + rep_etypestr = rep_etypes2str(reply); + krb5_klog_syslog(LOG_INFO, _("TGS_REQ (%s) %s: %s: authtime %u, %s%s " + "%s for %s%s%s"), + ktypestr ? ktypestr : "", fromstring, status, + (unsigned int)authtime, + rep_etypestr ? rep_etypestr : "", + !errcode ? "," : "", logcname, logsname, + errcode ? ", " : "", errcode ? emsg : ""); + if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) + krb5_klog_syslog(LOG_INFO, + _("... PROTOCOL-TRANSITION s4u-client=%s"), + logaltcname); + else if (isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) + krb5_klog_syslog(LOG_INFO, + _("... CONSTRAINED-DELEGATION s4u-client=%s"), + logaltcname); + + } else + krb5_klog_syslog(LOG_INFO, _("TGS_REQ %s: %s: authtime %u, %s for %s, " + "2nd tkt client %s"), + fromstring, status, (unsigned int)authtime, + logcname, logsname, logaltcname); + + free(rep_etypestr); + free(ktypestr); + krb5_free_unparsed_name(ctx, cname); + krb5_free_unparsed_name(ctx, sname); + krb5_free_unparsed_name(ctx, altcname); +} + +void +log_tgs_badtrans(krb5_context ctx, krb5_principal cprinc, + krb5_principal sprinc, krb5_data *trcont, + krb5_error_code errcode) +{ + unsigned int tlen; + char *tdots; + const char *emsg = NULL; + char *cname = NULL, *sname = NULL; + char *logcname = NULL, *logsname = NULL; + + unparse_and_limit(ctx, cprinc, &cname); + logcname = (cname != NULL) ? cname : ""; + unparse_and_limit(ctx, sprinc, &sname); + logsname = (sname != NULL) ? sname : ""; + + tlen = trcont->length; + tdots = tlen > 125 ? "..." : ""; + tlen = tlen > 125 ? 125 : tlen; + + if (errcode == KRB5KRB_AP_ERR_ILL_CR_TKT) + krb5_klog_syslog(LOG_INFO, _("bad realm transit path from '%s' " + "to '%s' via '%.*s%s'"), + logcname, logsname, tlen, + trcont->data, tdots); + else { + emsg = krb5_get_error_message(ctx, errcode); + krb5_klog_syslog(LOG_ERR, _("unexpected error checking transit " + "from '%s' to '%s' via '%.*s%s': %s"), + logcname, logsname, tlen, + trcont->data, tdots, + emsg); + krb5_free_error_message(ctx, emsg); + emsg = NULL; + } + krb5_free_unparsed_name(ctx, cname); + krb5_free_unparsed_name(ctx, sname); +} + +void +log_tgs_alt_tgt(krb5_context context, krb5_principal p) +{ + char *sname; + if (krb5_unparse_name(context, p, &sname)) { + krb5_klog_syslog(LOG_INFO, + _("TGS_REQ: issuing alternate TGT")); + } else { + limit_string(sname); + krb5_klog_syslog(LOG_INFO, _("TGS_REQ: issuing TGT %s"), sname); + free(sname); + } + /* OpenSolaris: audit_krb5kdc_tgs_req_alt_tgt(...) */ +} diff --git a/krb5-1.21.3/src/kdc/kdc_preauth.c b/krb5-1.21.3/src/kdc/kdc_preauth.c new file mode 100644 index 00000000..3752be6a --- /dev/null +++ b/krb5-1.21.3/src/kdc/kdc_preauth.c @@ -0,0 +1,1663 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/kdc_preauth.c - Preauthentication routines for the KDC */ +/* + * Copyright 1995, 2003, 2007, 2009 by the Massachusetts Institute of + * Technology. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "k5-int.h" +#include "kdc_util.h" +#include "extern.h" +#include +#include "adm_proto.h" + +#include + +#include +#include + +/* Let freshness tokens be valid for ten minutes. */ +#define FRESHNESS_LIFETIME 600 + +typedef struct preauth_system_st { + const char *name; + int type; + int flags; + krb5_kdcpreauth_moddata moddata; + krb5_kdcpreauth_init_fn init; + krb5_kdcpreauth_fini_fn fini; + krb5_kdcpreauth_edata_fn get_edata; + krb5_kdcpreauth_verify_fn verify_padata; + krb5_kdcpreauth_return_fn return_padata; + krb5_kdcpreauth_free_modreq_fn free_modreq; + krb5_kdcpreauth_loop_fn loop; +} preauth_system; + +static preauth_system *preauth_systems; +static size_t n_preauth_systems; + +static krb5_error_code +make_etype_info(krb5_context context, krb5_boolean etype_info2, + krb5_principal client, krb5_key_data *client_key, + krb5_enctype enctype, krb5_data **der_out); + +/* Get all available kdcpreauth vtables and a count of preauth types they + * support. Return an empty list on failure. */ +static void +get_plugin_vtables(krb5_context context, + struct krb5_kdcpreauth_vtable_st **vtables_out, + size_t *n_tables_out, size_t *n_systems_out) +{ + krb5_plugin_initvt_fn *plugins = NULL, *pl; + struct krb5_kdcpreauth_vtable_st *vtables; + size_t count, n_tables, n_systems, i; + + *vtables_out = NULL; + *n_tables_out = *n_systems_out = 0; + + /* Auto-register encrypted challenge and (if possible) pkinit. */ + k5_plugin_register_dyn(context, PLUGIN_INTERFACE_KDCPREAUTH, "pkinit", + "preauth"); + k5_plugin_register_dyn(context, PLUGIN_INTERFACE_KDCPREAUTH, "otp", + "preauth"); + k5_plugin_register_dyn(context, PLUGIN_INTERFACE_KDCPREAUTH, "spake", + "preauth"); + k5_plugin_register(context, PLUGIN_INTERFACE_KDCPREAUTH, + "encrypted_challenge", + kdcpreauth_encrypted_challenge_initvt); + k5_plugin_register(context, PLUGIN_INTERFACE_KDCPREAUTH, + "encrypted_timestamp", + kdcpreauth_encrypted_timestamp_initvt); + + if (k5_plugin_load_all(context, PLUGIN_INTERFACE_KDCPREAUTH, &plugins)) + return; + for (count = 0; plugins[count]; count++); + vtables = calloc(count + 1, sizeof(*vtables)); + if (vtables == NULL) + goto cleanup; + for (pl = plugins, n_tables = 0; *pl != NULL; pl++) { + if ((*pl)(context, 1, 2, (krb5_plugin_vtable)&vtables[n_tables]) == 0) + n_tables++; + } + for (i = 0, n_systems = 0; i < n_tables; i++) { + for (count = 0; vtables[i].pa_type_list[count] != 0; count++); + n_systems += count; + } + *vtables_out = vtables; + *n_tables_out = n_tables; + *n_systems_out = n_systems; + +cleanup: + k5_plugin_free_modules(context, plugins); +} + +/* Make a list of realm names. The caller should free the list container but + * not the list elements (which are aliases into kdc_realmlist). */ +static krb5_error_code +get_realm_names(struct server_handle *handle, const char ***list_out) +{ + const char **list; + int i; + + list = calloc(handle->kdc_numrealms + 1, sizeof(*list)); + if (list == NULL) + return ENOMEM; + for (i = 0; i < handle->kdc_numrealms; i++) + list[i] = handle->kdc_realmlist[i]->realm_name; + list[i] = NULL; + *list_out = list; + return 0; +} + +void +load_preauth_plugins(struct server_handle *handle, krb5_context context, + verto_ctx *ctx) +{ + krb5_error_code ret; + struct krb5_kdcpreauth_vtable_st *vtables = NULL, *vt; + size_t n_systems, n_tables, i, j; + krb5_kdcpreauth_moddata moddata; + const char **realm_names = NULL, *emsg; + preauth_system *sys; + + /* Get all available kdcpreauth vtables. */ + get_plugin_vtables(context, &vtables, &n_tables, &n_systems); + + /* Allocate the list of static and plugin preauth systems. */ + preauth_systems = calloc(n_systems + 1, sizeof(preauth_system)); + if (preauth_systems == NULL) + goto cleanup; + + if (get_realm_names(handle, &realm_names)) + goto cleanup; + + /* Add the dynamically-loaded mechanisms to the list. */ + n_systems = 0; + for (i = 0; i < n_tables; i++) { + /* Try to initialize this module. */ + vt = &vtables[i]; + moddata = NULL; + if (vt->init) { + ret = vt->init(context, &moddata, realm_names); + if (ret) { + emsg = krb5_get_error_message(context, ret); + krb5_klog_syslog(LOG_ERR, _("preauth %s failed to " + "initialize: %s"), vt->name, emsg); + krb5_free_error_message(context, emsg); + continue; + } + } + + if (vt->loop) { + ret = vt->loop(context, moddata, ctx); + if (ret) { + emsg = krb5_get_error_message(context, ret); + krb5_klog_syslog(LOG_ERR, _("preauth %s failed to setup " + "loop: %s"), vt->name, emsg); + krb5_free_error_message(context, emsg); + if (vt->fini) + vt->fini(context, moddata); + continue; + } + } + + /* Add this module to the systems list once for each pa type. */ + for (j = 0; vt->pa_type_list[j] != 0; j++) { + sys = &preauth_systems[n_systems]; + sys->name = vt->name; + sys->type = vt->pa_type_list[j]; + sys->flags = (vt->flags) ? vt->flags(context, sys->type) : 0; + sys->moddata = moddata; + sys->init = vt->init; + /* Only call fini once for each plugin. */ + sys->fini = (j == 0) ? vt->fini : NULL; + sys->get_edata = vt->edata; + sys->verify_padata = vt->verify; + sys->return_padata = vt->return_padata; + sys->free_modreq = vt->free_modreq; + sys->loop = vt->loop; + n_systems++; + } + } + n_preauth_systems = n_systems; + /* Add the end-of-list marker. */ + preauth_systems[n_systems].name = "[end]"; + preauth_systems[n_systems].type = -1; + +cleanup: + free(vtables); + free(realm_names); +} + +void +unload_preauth_plugins(krb5_context context) +{ + size_t i; + + for (i = 0; i < n_preauth_systems; i++) { + if (preauth_systems[i].fini) + preauth_systems[i].fini(context, preauth_systems[i].moddata); + } + free(preauth_systems); + preauth_systems = NULL; + n_preauth_systems = 0; +} + +/* + * The make_padata_context() function creates a space for storing any + * request-specific module data which will be needed by return_padata() later. + * Each preauth type gets a storage location of its own. + */ +struct request_pa_context { + int n_contexts; + struct { + preauth_system *pa_system; + krb5_kdcpreauth_modreq modreq; + } *contexts; +}; + +static krb5_error_code +make_padata_context(krb5_context context, void **padata_context) +{ + int i; + struct request_pa_context *ret; + + ret = malloc(sizeof(*ret)); + if (ret == NULL) { + return ENOMEM; + } + + ret->n_contexts = n_preauth_systems; + ret->contexts = malloc(sizeof(ret->contexts[0]) * ret->n_contexts); + if (ret->contexts == NULL) { + free(ret); + return ENOMEM; + } + + memset(ret->contexts, 0, sizeof(ret->contexts[0]) * ret->n_contexts); + + for (i = 0; i < ret->n_contexts; i++) { + ret->contexts[i].pa_system = &preauth_systems[i]; + ret->contexts[i].modreq = NULL; + } + + *padata_context = ret; + + return 0; +} + +/* + * The free_padata_context function frees any context information pointers + * which the check_padata() function created but which weren't already cleaned + * up by return_padata(). + */ +void +free_padata_context(krb5_context kcontext, void *padata_context) +{ + struct request_pa_context *context = padata_context; + preauth_system *sys; + int i; + + if (context == NULL) + return; + for (i = 0; i < context->n_contexts; i++) { + sys = context->contexts[i].pa_system; + if (!sys->free_modreq || !context->contexts[i].modreq) + continue; + sys->free_modreq(kcontext, sys->moddata, context->contexts[i].modreq); + context->contexts[i].modreq = NULL; + } + + free(context->contexts); + free(context); +} + +static krb5_deltat +max_time_skew(krb5_context context, krb5_kdcpreauth_rock rock) +{ + return context->clockskew; +} + +static krb5_error_code +client_keys(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_keyblock **keys_out) +{ + krb5_kdc_req *request = rock->request; + krb5_db_entry *client = rock->client; + krb5_keyblock *keys, key; + krb5_key_data *entry_key; + int i, k; + + keys = calloc(request->nktypes + 1, sizeof(krb5_keyblock)); + if (keys == NULL) + return ENOMEM; + + k = 0; + for (i = 0; i < request->nktypes; i++) { + entry_key = NULL; + if (krb5_dbe_find_enctype(context, client, request->ktype[i], + -1, 0, &entry_key) != 0) + continue; + if (krb5_dbe_decrypt_key_data(context, NULL, entry_key, + &key, NULL) != 0) + continue; + keys[k++] = key; + } + if (k == 0) { + free(keys); + return ENOENT; + } + *keys_out = keys; + return 0; +} + +static void free_keys(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_keyblock *keys) +{ + krb5_keyblock *k; + + if (keys == NULL) + return; + for (k = keys; k->enctype != 0; k++) + krb5_free_keyblock_contents(context, k); + free(keys); +} + +static krb5_data * +request_body(krb5_context context, krb5_kdcpreauth_rock rock) +{ + return rock->inner_body; +} + +static krb5_keyblock * +fast_armor(krb5_context context, krb5_kdcpreauth_rock rock) +{ + return rock->rstate->armor_key; +} + +static krb5_error_code +get_string(krb5_context context, krb5_kdcpreauth_rock rock, const char *key, + char **value_out) +{ + return krb5_dbe_get_string(context, rock->client, key, value_out); +} + +static void +free_string(krb5_context context, krb5_kdcpreauth_rock rock, char *string) +{ + krb5_dbe_free_string(context, string); +} + +static void * +client_entry(krb5_context context, krb5_kdcpreauth_rock rock) +{ + return rock->client; +} + +static verto_ctx * +event_context(krb5_context context, krb5_kdcpreauth_rock rock) +{ + return rock->vctx; +} + +static krb5_boolean +have_client_keys(krb5_context context, krb5_kdcpreauth_rock rock) +{ + krb5_kdc_req *request = rock->request; + krb5_key_data *kd; + int i; + + for (i = 0; i < request->nktypes; i++) { + if (krb5_dbe_find_enctype(context, rock->client, request->ktype[i], + -1, 0, &kd) == 0) + return TRUE; + } + return FALSE; +} + +static const krb5_keyblock * +client_keyblock(krb5_context context, krb5_kdcpreauth_rock rock) +{ + if (rock->client_keyblock->enctype == ENCTYPE_NULL) + return NULL; + return rock->client_keyblock; +} + +static krb5_error_code +add_auth_indicator(krb5_context context, krb5_kdcpreauth_rock rock, + const char *indicator) +{ + return authind_add(context, indicator, rock->auth_indicators); +} + +static krb5_boolean +get_cookie(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_preauthtype pa_type, krb5_data *out) +{ + return kdc_fast_search_cookie(rock->rstate, pa_type, out); +} + +static krb5_error_code +set_cookie(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_preauthtype pa_type, const krb5_data *data) +{ + return kdc_fast_set_cookie(rock->rstate, pa_type, data); +} + +static krb5_boolean +match_client(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_principal princ) +{ + krb5_db_entry *ent; + krb5_boolean match = FALSE; + krb5_principal req_client = rock->request->client; + krb5_principal client = rock->client->princ; + + /* Check for a direct match against the request principal or + * the post-canon client principal. */ + if (krb5_principal_compare_flags(context, princ, req_client, + KRB5_PRINCIPAL_COMPARE_ENTERPRISE) || + krb5_principal_compare(context, princ, client)) + return TRUE; + + if (krb5_db_get_principal(context, princ, KRB5_KDB_FLAG_CLIENT, &ent)) + return FALSE; + match = krb5_principal_compare(context, ent->princ, client); + krb5_db_free_principal(context, ent); + return match; +} + +static krb5_principal +client_name(krb5_context context, krb5_kdcpreauth_rock rock) +{ + return rock->client->princ; +} + +static void +send_freshness_token(krb5_context context, krb5_kdcpreauth_rock rock) +{ + rock->send_freshness_token = TRUE; +} + +static krb5_error_code +check_freshness_token(krb5_context context, krb5_kdcpreauth_rock rock, + const krb5_data *token) +{ + krb5_timestamp token_ts, now; + krb5_key_data *kd; + krb5_keyblock kb; + krb5_kvno token_kvno; + krb5_checksum cksum; + krb5_data d; + uint8_t *token_cksum; + size_t token_cksum_len; + krb5_boolean valid = FALSE; + char ckbuf[4]; + + memset(&kb, 0, sizeof(kb)); + + if (krb5_timeofday(context, &now) != 0) + goto cleanup; + + if (token->length <= 8) + goto cleanup; + token_ts = load_32_be(token->data); + token_kvno = load_32_be(token->data + 4); + token_cksum = (uint8_t *)token->data + 8; + token_cksum_len = token->length - 8; + + /* Check if the token timestamp is too old. */ + if (ts_after(now, ts_incr(token_ts, FRESHNESS_LIFETIME))) + goto cleanup; + + /* Fetch and decrypt the local krbtgt key of the token's kvno. */ + if (krb5_dbe_find_enctype(context, rock->local_tgt, -1, -1, token_kvno, + &kd) != 0) + goto cleanup; + if (krb5_dbe_decrypt_key_data(context, NULL, kd, &kb, NULL) != 0) + goto cleanup; + + /* Verify the token checksum against the current KDC time. The checksum + * must use the mandatory checksum type of the krbtgt key's enctype. */ + store_32_be(token_ts, ckbuf); + d = make_data(ckbuf, sizeof(ckbuf)); + cksum.magic = KV5M_CHECKSUM; + cksum.checksum_type = 0; + cksum.length = token_cksum_len; + cksum.contents = token_cksum; + (void)krb5_c_verify_checksum(context, &kb, KRB5_KEYUSAGE_PA_AS_FRESHNESS, + &d, &cksum, &valid); + +cleanup: + krb5_free_keyblock_contents(context, &kb); + return valid ? 0 : KRB5KDC_ERR_PREAUTH_EXPIRED; +} + +static krb5_error_code +replace_reply_key(krb5_context context, krb5_kdcpreauth_rock rock, + const krb5_keyblock *key, krb5_boolean is_strengthen) +{ + krb5_keyblock copy; + + if (krb5_copy_keyblock_contents(context, key, ©) != 0) + return ENOMEM; + krb5_free_keyblock_contents(context, rock->client_keyblock); + *rock->client_keyblock = copy; + if (!is_strengthen) + rock->replaced_reply_key = TRUE; + return 0; +} + +static struct krb5_kdcpreauth_callbacks_st callbacks = { + 6, + max_time_skew, + client_keys, + free_keys, + request_body, + fast_armor, + get_string, + free_string, + client_entry, + event_context, + have_client_keys, + client_keyblock, + add_auth_indicator, + get_cookie, + set_cookie, + match_client, + client_name, + send_freshness_token, + check_freshness_token, + replace_reply_key +}; + +static krb5_error_code +find_pa_system(int type, preauth_system **preauth) +{ + preauth_system *ap; + + if (preauth_systems == NULL) + return KRB5_PREAUTH_BAD_TYPE; + ap = preauth_systems; + while ((ap->type != -1) && (ap->type != type)) + ap++; + if (ap->type == -1) + return(KRB5_PREAUTH_BAD_TYPE); + *preauth = ap; + return 0; +} + +/* Find a pointer to the request-specific module data for pa_sys. */ +static krb5_error_code +find_modreq(preauth_system *pa_sys, struct request_pa_context *context, + krb5_kdcpreauth_modreq **modreq_out) +{ + int i; + + *modreq_out = NULL; + if (context == NULL) + return KRB5KRB_ERR_GENERIC; + + for (i = 0; i < context->n_contexts; i++) { + if (context->contexts[i].pa_system == pa_sys) { + *modreq_out = &context->contexts[i].modreq; + return 0; + } + } + + return KRB5KRB_ERR_GENERIC; +} + +/* + * Create a list of indices into the preauth_systems array, sorted by order of + * preference. + */ +static krb5_boolean +pa_list_includes(krb5_pa_data **pa_data, krb5_preauthtype pa_type) +{ + while (*pa_data != NULL) { + if ((*pa_data)->pa_type == pa_type) + return TRUE; + pa_data++; + } + return FALSE; +} +static void +sort_pa_order(krb5_context context, krb5_kdc_req *request, int *pa_order) +{ + size_t i, j, k, n_repliers, n_key_replacers; + + /* First, set up the default order. */ + i = 0; + for (j = 0; j < n_preauth_systems; j++) { + if (preauth_systems[j].return_padata != NULL) + pa_order[i++] = j; + } + n_repliers = i; + pa_order[n_repliers] = -1; + + /* Reorder so that PA_REPLACES_KEY modules are listed first. */ + for (i = 0; i < n_repliers; i++) { + /* If this module replaces the key, then it's okay to leave it where it + * is in the order. */ + if (preauth_systems[pa_order[i]].flags & PA_REPLACES_KEY) + continue; + /* If not, search for a module which does, and swap in the first one we + * find. */ + for (j = i + 1; j < n_repliers; j++) { + if (preauth_systems[pa_order[j]].flags & PA_REPLACES_KEY) { + k = pa_order[j]; + pa_order[j] = pa_order[i]; + pa_order[i] = k; + break; + } + } + /* If we didn't find one, we have moved all of the key-replacing + * modules, and i is the count of those modules. */ + if (j == n_repliers) + break; + } + n_key_replacers = i; + + if (request->padata != NULL) { + /* Now reorder the subset of modules which replace the key, + * bubbling those which handle pa_data types provided by the + * client ahead of the others. + */ + for (i = 0; i < n_key_replacers; i++) { + if (pa_list_includes(request->padata, + preauth_systems[pa_order[i]].type)) + continue; + for (j = i + 1; j < n_key_replacers; j++) { + if (pa_list_includes(request->padata, + preauth_systems[pa_order[j]].type)) { + k = pa_order[j]; + pa_order[j] = pa_order[i]; + pa_order[i] = k; + break; + } + } + } + } +#ifdef DEBUG + krb5_klog_syslog(LOG_DEBUG, "original preauth mechanism list:"); + for (i = 0; i < n_preauth_systems; i++) { + if (preauth_systems[i].return_padata != NULL) + krb5_klog_syslog(LOG_DEBUG, "... %s(%d)", preauth_systems[i].name, + preauth_systems[i].type); + } + krb5_klog_syslog(LOG_DEBUG, "sorted preauth mechanism list:"); + for (i = 0; pa_order[i] != -1; i++) { + krb5_klog_syslog(LOG_DEBUG, "... %s(%d)", + preauth_systems[pa_order[i]].name, + preauth_systems[pa_order[i]].type); + } +#endif +} + +const char *missing_required_preauth(krb5_db_entry *client, + krb5_db_entry *server, + krb5_enc_tkt_part *enc_tkt_reply) +{ +#ifdef DEBUG + krb5_klog_syslog ( + LOG_DEBUG, + "client needs %spreauth, %shw preauth; request has %spreauth, %shw preauth", + isflagset (client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH) ? "" : "no ", + isflagset (client->attributes, KRB5_KDB_REQUIRES_HW_AUTH) ? "" : "no ", + isflagset (enc_tkt_reply->flags, TKT_FLG_PRE_AUTH) ? "" : "no ", + isflagset (enc_tkt_reply->flags, TKT_FLG_HW_AUTH) ? "" : "no "); +#endif + + if (isflagset(client->attributes, KRB5_KDB_REQUIRES_PRE_AUTH) && + !isflagset(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH)) + return "NEEDED_PREAUTH"; + + if (isflagset(client->attributes, KRB5_KDB_REQUIRES_HW_AUTH) && + !isflagset(enc_tkt_reply->flags, TKT_FLG_HW_AUTH)) + return "NEEDED_HW_PREAUTH"; + + return 0; +} + +/* Return true if request's enctypes indicate support for etype-info2. */ +static krb5_boolean +requires_info2(const krb5_kdc_req *request) +{ + int i; + + for (i = 0; i < request->nktypes; i++) { + if (enctype_requires_etype_info_2(request->ktype[i])) + return TRUE; + } + return FALSE; +} + +/* Add PA-ETYPE-INFO2 and possibly PA-ETYPE-INFO entries to pa_list as + * appropriate for the request and client principal. */ +static krb5_error_code +add_etype_info(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_pa_data ***pa_list) +{ + krb5_error_code ret; + krb5_data *der; + + if (rock->client_key == NULL) + return 0; + + if (!requires_info2(rock->request)) { + /* Include PA-ETYPE-INFO only for old clients. */ + ret = make_etype_info(context, FALSE, rock->client->princ, + rock->client_key, rock->client_keyblock->enctype, + &der); + if (ret) + return ret; + ret = k5_add_pa_data_from_data(pa_list, KRB5_PADATA_ETYPE_INFO, der); + krb5_free_data(context, der); + if (ret) + return ret; + } + + /* Always include PA-ETYPE-INFO2. */ + ret = make_etype_info(context, TRUE, rock->client->princ, rock->client_key, + rock->client_keyblock->enctype, &der); + if (ret) + return ret; + ret = k5_add_pa_data_from_data(pa_list, KRB5_PADATA_ETYPE_INFO2, der); + krb5_free_data(context, der); + return ret; +} + +/* Add PW-SALT entries to pa_list as appropriate for the request and client + * principal. */ +static krb5_error_code +add_pw_salt(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_pa_data ***pa_list) +{ + krb5_error_code ret; + krb5_data *salt = NULL; + krb5_int16 salttype; + + /* Only include this pa-data for old clients. */ + if (rock->client_key == NULL || requires_info2(rock->request)) + return 0; + + ret = krb5_dbe_compute_salt(context, rock->client_key, + rock->request->client, &salttype, &salt); + if (ret) + return 0; + + ret = k5_add_pa_data_from_data(pa_list, KRB5_PADATA_PW_SALT, salt); + krb5_free_data(context, salt); + return ret; +} + +static krb5_error_code +add_freshness_token(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_pa_data ***pa_list) +{ + krb5_error_code ret; + krb5_timestamp now; + krb5_keyblock kb; + krb5_checksum cksum; + krb5_data d; + krb5_pa_data *pa = NULL; + char ckbuf[4]; + + memset(&cksum, 0, sizeof(cksum)); + memset(&kb, 0, sizeof(kb)); + + if (!rock->send_freshness_token) + return 0; + if (krb5int_find_pa_data(context, rock->request->padata, + KRB5_PADATA_AS_FRESHNESS) == NULL) + return 0; + + /* Compute a checksum over the current KDC time. */ + ret = krb5_timeofday(context, &now); + if (ret) + goto cleanup; + store_32_be(now, ckbuf); + d = make_data(ckbuf, sizeof(ckbuf)); + ret = krb5_c_make_checksum(context, 0, rock->local_tgt_key, + KRB5_KEYUSAGE_PA_AS_FRESHNESS, &d, &cksum); + + /* Compose a freshness token from the time, krbtgt kvno, and checksum. */ + ret = k5_alloc_pa_data(KRB5_PADATA_AS_FRESHNESS, 8 + cksum.length, &pa); + if (ret) + goto cleanup; + store_32_be(now, pa->contents); + store_32_be(current_kvno(rock->local_tgt), pa->contents + 4); + memcpy(pa->contents + 8, cksum.contents, cksum.length); + + ret = k5_add_pa_data_element(pa_list, &pa); + +cleanup: + krb5_free_keyblock_contents(context, &kb); + krb5_free_checksum_contents(context, &cksum); + k5_free_pa_data_element(pa); + return ret; +} + +struct hint_state { + kdc_hint_respond_fn respond; + void *arg; + krb5_context context; + + krb5_kdcpreauth_rock rock; + krb5_kdc_req *request; + krb5_pa_data ***e_data_out; + + int hw_only; + preauth_system *ap; + krb5_pa_data **pa_data; + krb5_preauthtype pa_type; +}; + +static void +hint_list_finish(struct hint_state *state, krb5_error_code code) +{ + krb5_context context = state->context; + kdc_hint_respond_fn oldrespond = state->respond; + void *oldarg = state->arg; + + /* Add a freshness token if a preauth module requested it and the client + * request indicates support for it. */ + if (!code) + code = add_freshness_token(context, state->rock, &state->pa_data); + + if (!code) { + if (state->pa_data == NULL) { + krb5_klog_syslog(LOG_INFO, + _("%spreauth required but hint list is empty"), + state->hw_only ? "hw" : ""); + } + + *state->e_data_out = state->pa_data; + state->pa_data = NULL; + } + + krb5_free_pa_data(context, state->pa_data); + free(state); + (*oldrespond)(oldarg); +} + +static void +hint_list_next(struct hint_state *arg); + +static void +finish_get_edata(void *arg, krb5_error_code code, krb5_pa_data *pa) +{ + krb5_error_code ret; + struct hint_state *state = arg; + + if (code == 0) { + if (pa == NULL) { + ret = k5_alloc_pa_data(state->pa_type, 0, &pa); + if (ret) + goto error; + } + ret = k5_add_pa_data_element(&state->pa_data, &pa); + k5_free_pa_data_element(pa); + if (ret) + goto error; + } + + state->ap++; + hint_list_next(state); + return; + +error: + hint_list_finish(state, ret); +} + +static void +hint_list_next(struct hint_state *state) +{ + krb5_context context = state->context; + preauth_system *ap = state->ap; + + if (ap->type == -1) { + hint_list_finish(state, 0); + return; + } + + if (state->hw_only && !(ap->flags & PA_HARDWARE)) + goto next; + if (ap->flags & PA_PSEUDO) + goto next; + + state->pa_type = ap->type; + if (ap->get_edata) { + ap->get_edata(context, state->request, &callbacks, state->rock, + ap->moddata, ap->type, finish_get_edata, state); + } else + finish_get_edata(state, 0, NULL); + return; + +next: + state->ap++; + hint_list_next(state); +} + +void +get_preauth_hint_list(krb5_kdc_req *request, krb5_kdcpreauth_rock rock, + krb5_pa_data ***e_data_out, kdc_hint_respond_fn respond, + void *arg) +{ + krb5_context context = rock->rstate->realm_data->realm_context; + struct hint_state *state; + + *e_data_out = NULL; + + /* Allocate our state. */ + state = calloc(1, sizeof(*state)); + if (state == NULL) + goto error; + state->hw_only = isflagset(rock->client->attributes, + KRB5_KDB_REQUIRES_HW_AUTH); + state->respond = respond; + state->arg = arg; + state->request = request; + state->rock = rock; + state->context = context; + state->e_data_out = e_data_out; + state->pa_data = NULL; + state->ap = preauth_systems; + + /* Add an empty PA-FX-FAST element to advertise FAST support. */ + if (k5_add_empty_pa_data(&state->pa_data, KRB5_PADATA_FX_FAST) != 0) + goto error; + + if (add_etype_info(context, rock, &state->pa_data) != 0) + goto error; + + hint_list_next(state); + return; + +error: + if (state != NULL) + krb5_free_pa_data(context, state->pa_data); + free(state); + (*respond)(arg); +} + +/* + * Add authorization data returned from preauth modules to the ticket + * It is assumed that ad is a "null-terminated" array of krb5_authdata ptrs + */ +static krb5_error_code +add_authorization_data(krb5_enc_tkt_part *enc_tkt_part, krb5_authdata **ad) +{ + krb5_authdata **newad; + int oldones, newones; + int i; + + if (enc_tkt_part == NULL || ad == NULL) + return EINVAL; + + for (newones = 0; ad[newones] != NULL; newones++); + if (newones == 0) + return 0; /* nothing to add */ + + if (enc_tkt_part->authorization_data == NULL) + oldones = 0; + else + for (oldones = 0; + enc_tkt_part->authorization_data[oldones] != NULL; oldones++); + + newad = malloc((oldones + newones + 1) * sizeof(krb5_authdata *)); + if (newad == NULL) + return ENOMEM; + + /* Copy any existing pointers */ + for (i = 0; i < oldones; i++) + newad[i] = enc_tkt_part->authorization_data[i]; + + /* Add the new ones */ + for (i = 0; i < newones; i++) + newad[oldones+i] = ad[i]; + + /* Terminate the new list */ + newad[oldones+i] = NULL; + + /* Free any existing list */ + if (enc_tkt_part->authorization_data != NULL) + free(enc_tkt_part->authorization_data); + + /* Install our new list */ + enc_tkt_part->authorization_data = newad; + + return 0; +} + +struct padata_state { + kdc_preauth_respond_fn respond; + void *arg; + kdc_realm_t *realm; + + krb5_kdcpreauth_modreq *modreq_ptr; + krb5_pa_data **padata; + int pa_found; + krb5_context context; + krb5_kdcpreauth_rock rock; + krb5_data *req_pkt; + krb5_kdc_req *request; + krb5_enc_tkt_part *enc_tkt_reply; + void **padata_context; + + preauth_system *pa_sys; + krb5_pa_data **pa_e_data; + krb5_boolean typed_e_data_flag; + int pa_ok; + krb5_error_code saved_code; + + krb5_pa_data ***e_data_out; + krb5_boolean *typed_e_data_out; +}; + +/* Return code if it is 0 or one of the codes we pass through to the client. + * Otherwise return KRB5KDC_ERR_PREAUTH_FAILED. */ +static krb5_error_code +filter_preauth_error(krb5_error_code code) +{ + /* The following switch statement allows us + * to return some preauth system errors back to the client. + */ + switch(code) { + case 0: + case KRB5KRB_AP_ERR_BAD_INTEGRITY: + case KRB5KRB_AP_ERR_SKEW: + case KRB5KDC_ERR_PREAUTH_REQUIRED: + case KRB5KDC_ERR_ETYPE_NOSUPP: + /* rfc 4556 */ + case KRB5KDC_ERR_CLIENT_NOT_TRUSTED: + case KRB5KDC_ERR_INVALID_SIG: + case KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED: + case KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE: + case KRB5KDC_ERR_INVALID_CERTIFICATE: + case KRB5KDC_ERR_REVOKED_CERTIFICATE: + case KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN: + case KRB5KDC_ERR_CLIENT_NAME_MISMATCH: + case KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE: + case KRB5KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED: + case KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED: + case KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED: + case KRB5KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED: + /* earlier drafts of what became rfc 4556 */ + case KRB5KDC_ERR_CERTIFICATE_MISMATCH: + case KRB5KDC_ERR_KDC_NOT_TRUSTED: + case KRB5KDC_ERR_REVOCATION_STATUS_UNAVAILABLE: + /* This value is shared with + * KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED. */ + /* case KRB5KDC_ERR_KEY_TOO_WEAK: */ + case KRB5KDC_ERR_DISCARD: + /* pkinit alg-agility */ + case KRB5KDC_ERR_NO_ACCEPTABLE_KDF: + /* rfc 6113 */ + case KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED: + return code; + default: + return KRB5KDC_ERR_PREAUTH_FAILED; + } +} + +/* + * If the client performed optimistic pre-authentication for a multi-round-trip + * mechanism, it may need key information to complete the exchange, so send it + * a PA-ETYPE-INFO2 element in addition to the pa-data from the module. + */ +static krb5_error_code +maybe_add_etype_info2(struct padata_state *state, krb5_error_code code) +{ + krb5_error_code ret; + krb5_context context = state->context; + krb5_kdcpreauth_rock rock = state->rock; + krb5_data *der; + + /* Only add key information when requesting another preauth round trip. */ + if (code != KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED) + return 0; + + /* Don't try to add key information when there is no key. */ + if (rock->client_key == NULL) + return 0; + + /* If the client sent a cookie, it has already seen a KDC response with key + * information. */ + if (krb5int_find_pa_data(context, state->request->padata, + KRB5_PADATA_FX_COOKIE) != NULL) + return 0; + + ret = make_etype_info(context, TRUE, rock->client->princ, rock->client_key, + rock->client_keyblock->enctype, &der); + if (ret) + return ret; + ret = k5_add_pa_data_from_data(&state->pa_e_data, KRB5_PADATA_ETYPE_INFO2, + der); + krb5_free_data(context, der); + return ret; +} + +/* Release state and respond to the AS-REQ processing code with the result of + * checking pre-authentication data. */ +static void +finish_check_padata(struct padata_state *state, krb5_error_code code) +{ + kdc_preauth_respond_fn respond; + void *arg; + + if (state->pa_ok || !state->pa_found) { + /* Return successfully. If we didn't match a preauth system, we may + * return PREAUTH_REQUIRED later, but we didn't fail to verify. */ + code = 0; + goto cleanup; + } + + /* Add key information to the saved error pa-data if required. */ + if (maybe_add_etype_info2(state, code) != 0) { + code = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + /* Return any saved error pa-data, stealing the pointer from state. */ + *state->e_data_out = state->pa_e_data; + *state->typed_e_data_out = state->typed_e_data_flag; + state->pa_e_data = NULL; + +cleanup: + /* Discard saved error pa-data if we aren't returning it, free state, and + * respond to the AS-REQ processing code. */ + respond = state->respond; + arg = state->arg; + krb5_free_pa_data(state->context, state->pa_e_data); + free(state); + (*respond)(arg, filter_preauth_error(code)); +} + +static void +next_padata(struct padata_state *state); + +static void +finish_verify_padata(void *arg, krb5_error_code code, + krb5_kdcpreauth_modreq modreq, krb5_pa_data **e_data, + krb5_authdata **authz_data) +{ + struct padata_state *state = arg; + const char *emsg; + krb5_boolean typed_e_data_flag; + + assert(state); + *state->modreq_ptr = modreq; + + if (code) { + emsg = krb5_get_error_message(state->context, code); + krb5_klog_syslog(LOG_INFO, "preauth (%s) verify failure: %s", + state->pa_sys->name, emsg); + krb5_free_error_message(state->context, emsg); + + /* Ignore authorization data returned from modules that fail */ + if (authz_data != NULL) { + krb5_free_authdata(state->context, authz_data); + authz_data = NULL; + } + + typed_e_data_flag = ((state->pa_sys->flags & PA_TYPED_E_DATA) != 0); + + /* + * We'll return edata from either the first PA_REQUIRED module + * that fails, or the first non-PA_REQUIRED module that fails. + * Hang on to edata from the first non-PA_REQUIRED module. + * If we've already got one saved, simply discard this one. + */ + if (state->pa_sys->flags & PA_REQUIRED) { + /* free up any previous edata we might have been saving */ + if (state->pa_e_data != NULL) + krb5_free_pa_data(state->context, state->pa_e_data); + state->pa_e_data = e_data; + state->typed_e_data_flag = typed_e_data_flag; + + /* Make sure we use the current retval */ + state->pa_ok = 0; + finish_check_padata(state, code); + return; + } else if (state->pa_e_data == NULL) { + /* save the first error code and e-data */ + state->pa_e_data = e_data; + state->typed_e_data_flag = typed_e_data_flag; + state->saved_code = code; + } else if (e_data != NULL) { + /* discard this extra e-data from non-PA_REQUIRED module */ + krb5_free_pa_data(state->context, e_data); + } + } else { +#ifdef DEBUG + krb5_klog_syslog (LOG_DEBUG, ".. .. ok"); +#endif + + /* Ignore any edata returned on success */ + if (e_data != NULL) + krb5_free_pa_data(state->context, e_data); + + /* Add any authorization data to the ticket */ + if (authz_data != NULL) { + add_authorization_data(state->enc_tkt_reply, authz_data); + free(authz_data); + } + + state->pa_ok = 1; + if (state->pa_sys->flags & PA_SUFFICIENT) { + finish_check_padata(state, state->saved_code); + return; + } + } + + next_padata(state); +} + +static void +next_padata(struct padata_state *state) +{ + assert(state); + if (!state->padata) + state->padata = state->request->padata; + else + state->padata++; + + if (!*state->padata) { + finish_check_padata(state, state->saved_code); + return; + } + +#ifdef DEBUG + krb5_klog_syslog (LOG_DEBUG, ".. pa_type 0x%x", (*state->padata)->pa_type); +#endif + if (find_pa_system((*state->padata)->pa_type, &state->pa_sys)) + goto next; + if (find_modreq(state->pa_sys, *state->padata_context, &state->modreq_ptr)) + goto next; +#ifdef DEBUG + krb5_klog_syslog (LOG_DEBUG, ".. pa_type %s", state->pa_sys->name); +#endif + if (state->pa_sys->verify_padata == 0) + goto next; + + state->pa_found++; + state->pa_sys->verify_padata(state->context, state->req_pkt, + state->request, state->enc_tkt_reply, + *state->padata, &callbacks, state->rock, + state->pa_sys->moddata, finish_verify_padata, + state); + return; + +next: + next_padata(state); +} + +/* + * This routine is called to verify the preauthentication information + * for a V5 request. + * + * Returns 0 if the pre-authentication is valid, non-zero to indicate + * an error code of some sort. + */ + +void +check_padata(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_data *req_pkt, krb5_kdc_req *request, + krb5_enc_tkt_part *enc_tkt_reply, void **padata_context, + krb5_pa_data ***e_data, krb5_boolean *typed_e_data, + kdc_preauth_respond_fn respond, void *arg) +{ + struct padata_state *state; + + if (request->padata == 0) { + (*respond)(arg, 0); + return; + } + + if (make_padata_context(context, padata_context) != 0) { + (*respond)(arg, KRB5KRB_ERR_GENERIC); + return; + } + + state = calloc(1, sizeof(*state)); + if (state == NULL) { + (*respond)(arg, ENOMEM); + return; + } + state->respond = respond; + state->arg = arg; + state->context = context; + state->rock = rock; + state->req_pkt = req_pkt; + state->request = request; + state->enc_tkt_reply = enc_tkt_reply; + state->padata_context = padata_context; + state->e_data_out = e_data; + state->typed_e_data_out = typed_e_data; + state->realm = rock->rstate->realm_data; + +#ifdef DEBUG + krb5_klog_syslog (LOG_DEBUG, "checking padata"); +#endif + + next_padata(state); +} + +/* Return true if k1 and k2 have the same type and contents. */ +static krb5_boolean +keyblock_equal(const krb5_keyblock *k1, const krb5_keyblock *k2) +{ + if (k1->enctype != k2->enctype) + return FALSE; + if (k1->length != k2->length) + return FALSE; + return memcmp(k1->contents, k2->contents, k1->length) == 0; +} + +/* + * return_padata creates any necessary preauthentication + * structures which should be returned by the KDC to the client + */ +krb5_error_code +return_padata(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_keyblock *encrypting_key, void **padata_context) +{ + krb5_error_code retval; + krb5_pa_data ** padata; + krb5_pa_data ** send_pa_list = NULL; + krb5_pa_data * send_pa; + krb5_pa_data * pa = 0; + krb5_pa_data null_item; + preauth_system * ap; + int * pa_order = NULL; + int * pa_type; + int size = 0; + krb5_kdcpreauth_modreq *modreq_ptr; + krb5_boolean key_modified; + krb5_keyblock original_key; + + memset(&original_key, 0, sizeof(original_key)); + + if ((!*padata_context) && + (make_padata_context(context, padata_context) != 0)) { + return KRB5KRB_ERR_GENERIC; + } + + for (ap = preauth_systems; ap->type != -1; ap++) { + if (ap->return_padata) + size++; + } + + pa_order = k5calloc(size + 1, sizeof(int), &retval); + if (pa_order == NULL) + goto cleanup; + sort_pa_order(context, request, pa_order); + + retval = krb5_copy_keyblock_contents(context, encrypting_key, + &original_key); + if (retval) + goto cleanup; + key_modified = FALSE; + null_item.contents = NULL; + null_item.length = 0; + + for (pa_type = pa_order; *pa_type != -1; pa_type++) { + ap = &preauth_systems[*pa_type]; + if (key_modified && (ap->flags & PA_REPLACES_KEY)) + continue; + if (ap->return_padata == 0) + continue; + if (find_modreq(ap, *padata_context, &modreq_ptr)) + continue; + pa = &null_item; + null_item.pa_type = ap->type; + if (request->padata) { + for (padata = request->padata; *padata; padata++) { + if ((*padata)->pa_type == ap->type) { + pa = *padata; + break; + } + } + } + send_pa = NULL; + retval = ap->return_padata(context, pa, req_pkt, request, reply, + encrypting_key, &send_pa, &callbacks, rock, + ap->moddata, *modreq_ptr); + if (retval) + goto cleanup; + + if (send_pa != NULL) { + retval = k5_add_pa_data_element(&send_pa_list, &send_pa); + k5_free_pa_data_element(send_pa); + if (retval) + goto cleanup; + } + + if (!key_modified && !keyblock_equal(&original_key, encrypting_key)) + key_modified = TRUE; + } + + /* + * Add etype-info and pw-salt pa-data as needed. If we replaced the reply + * key, we can't send consistent etype-info; the salt from the client key + * data doesn't correspond to the replaced reply key, and RFC 4120 section + * 5.2.7.5 forbids us from sending etype-info describing the initial reply + * key in an AS-REP if it doesn't have the same enctype as the replaced + * reply key. For all current and foreseeable preauth mechs, we can assume + * the client received etype-info2 in an earlier step and already computed + * the initial reply key if it needed it. The client can determine the + * enctype of the replaced reply key from the etype field of the enc-part + * field of the AS-REP. + */ + if (!key_modified) { + retval = add_etype_info(context, rock, &send_pa_list); + if (retval) + goto cleanup; + retval = add_pw_salt(context, rock, &send_pa_list); + if (retval) + goto cleanup; + } + + if (send_pa_list != NULL) { + reply->padata = send_pa_list; + send_pa_list = 0; + } + +cleanup: + krb5_free_keyblock_contents(context, &original_key); + free(pa_order); + krb5_free_pa_data(context, send_pa_list); + + return (retval); +} + +static krb5_error_code +_make_etype_info_entry(krb5_context context, + krb5_principal client_princ, krb5_key_data *client_key, + krb5_enctype etype, krb5_etype_info_entry **entry_out, + int etype_info2) +{ + krb5_error_code retval; + krb5_int16 salttype; + krb5_data *salt = NULL; + krb5_etype_info_entry *entry = NULL; + + *entry_out = NULL; + entry = malloc(sizeof(*entry)); + if (entry == NULL) + return ENOMEM; + + entry->magic = KV5M_ETYPE_INFO_ENTRY; + entry->etype = etype; + entry->length = KRB5_ETYPE_NO_SALT; + entry->salt = NULL; + entry->s2kparams = empty_data(); + retval = krb5_dbe_compute_salt(context, client_key, client_princ, + &salttype, &salt); + if (retval) + goto cleanup; + + entry->length = salt->length; + entry->salt = (unsigned char *)salt->data; + salt->data = NULL; + *entry_out = entry; + entry = NULL; + +cleanup: + if (entry != NULL) + krb5_free_data_contents(context, &entry->s2kparams); + free(entry); + krb5_free_data(context, salt); + return retval; +} + +/* Encode an etype-info or etype-info2 message for client_key with the given + * enctype, using client to compute the salt if necessary. */ +static krb5_error_code +make_etype_info(krb5_context context, krb5_boolean etype_info2, + krb5_principal client, krb5_key_data *client_key, + krb5_enctype enctype, krb5_data **der_out) +{ + krb5_error_code retval; + krb5_etype_info_entry **entry = NULL; + + *der_out = NULL; + + entry = k5calloc(2, sizeof(*entry), &retval); + if (entry == NULL) + goto cleanup; + retval = _make_etype_info_entry(context, client, client_key, enctype, + &entry[0], etype_info2); + if (retval != 0) + goto cleanup; + + if (etype_info2) + retval = encode_krb5_etype_info2(entry, der_out); + else + retval = encode_krb5_etype_info(entry, der_out); + +cleanup: + krb5_free_etype_info(context, entry); + return retval; +} + +/* + * Returns TRUE if the PAC should be included + */ +krb5_boolean +include_pac_p(krb5_context context, krb5_kdc_req *request) +{ + krb5_error_code code; + krb5_pa_data **padata; + krb5_boolean retval = TRUE; /* default is to return PAC */ + krb5_data data; + krb5_pa_pac_req *req = NULL; + + if (request->padata == NULL) { + return retval; + } + + for (padata = request->padata; *padata != NULL; padata++) { + if ((*padata)->pa_type == KRB5_PADATA_PAC_REQUEST) { + data.data = (char *)(*padata)->contents; + data.length = (*padata)->length; + + code = decode_krb5_pa_pac_req(&data, &req); + if (code == 0) { + retval = req->include_pac; + krb5_free_pa_pac_req(context, req); + req = NULL; + } + break; + } + } + + return retval; +} + +static krb5_error_code +return_referral_enc_padata( krb5_context context, + krb5_enc_kdc_rep_part *reply, + krb5_db_entry *server) +{ + krb5_error_code code; + krb5_tl_data tl_data; + krb5_pa_data *pa; + + tl_data.tl_data_type = KRB5_TL_SVR_REFERRAL_DATA; + code = krb5_dbe_lookup_tl_data(context, server, &tl_data); + if (code || tl_data.tl_data_length == 0) + return 0; + + code = k5_alloc_pa_data(KRB5_PADATA_SVR_REFERRAL_INFO, + tl_data.tl_data_length, &pa); + if (code) + return code; + memcpy(pa->contents, tl_data.tl_data_contents, tl_data.tl_data_length); + code = k5_add_pa_data_element(&reply->enc_padata, &pa); + k5_free_pa_data_element(pa); + return code; +} + +krb5_error_code +return_enc_padata(krb5_context context, krb5_data *req_pkt, + krb5_kdc_req *request, krb5_keyblock *reply_key, + krb5_db_entry *server, krb5_enc_kdc_rep_part *reply_encpart, + krb5_boolean is_referral) +{ + krb5_error_code code = 0; + /* This should be initialized and only used for Win2K compat and other + * specific standardized uses such as FAST negotiation. */ + if (is_referral) { + code = return_referral_enc_padata(context, reply_encpart, server); + if (code) + return code; + } + code = kdc_handle_protected_negotiation(context, req_pkt, request, reply_key, + &reply_encpart->enc_padata); + if (code) + goto cleanup; + + code = kdc_add_pa_pac_options(context, request, + &reply_encpart->enc_padata); + if (code) + goto cleanup; + + /*Add potentially other enc_padata providers*/ +cleanup: + return code; +} diff --git a/krb5-1.21.3/src/kdc/kdc_preauth_ec.c b/krb5-1.21.3/src/kdc/kdc_preauth_ec.c new file mode 100644 index 00000000..18b18a73 --- /dev/null +++ b/krb5-1.21.3/src/kdc/kdc_preauth_ec.c @@ -0,0 +1,225 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/kdc_preauth_ec.c - Encrypted challenge kdcpreauth module */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Implement Encrypted Challenge fast factor from + * draft-ietf-krb-wg-preauth-framework + */ + +#include +#include +#include "kdc_util.h" + +static void +ec_edata(krb5_context context, krb5_kdc_req *request, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type, + krb5_kdcpreauth_edata_respond_fn respond, void *arg) +{ + krb5_keyblock *armor_key = cb->fast_armor(context, rock); + + /* Encrypted challenge only works with FAST, and requires a client key. */ + if (armor_key == NULL || !cb->have_client_keys(context, rock)) + (*respond)(arg, ENOENT, NULL); + else + (*respond)(arg, 0, NULL); +} + +static void +ec_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, + krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *data, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_verify_respond_fn respond, void *arg) +{ + krb5_error_code ret; + krb5_enc_data *enc = NULL; + krb5_data der_enc_ts = empty_data(), der_enc_data; + krb5_keyblock *armor_key = cb->fast_armor(context, rock); + krb5_pa_enc_ts *ts = NULL; + krb5_keyblock *client_keys = NULL; + krb5_keyblock *challenge_key = NULL; + krb5_keyblock *kdc_challenge_key; + krb5_kdcpreauth_modreq modreq = NULL; + int i = 0; + char *ai = NULL, *realmstr = NULL; + krb5_data realm = request->server->realm; + + if (armor_key == NULL) { + ret = ENOENT; + k5_setmsg(context, ret, + _("Encrypted Challenge used outside of FAST tunnel")); + goto cleanup; + } + + der_enc_data = make_data(data->contents, data->length); + ret = decode_krb5_enc_data(&der_enc_data, &enc); + if (ret) + goto cleanup; + + ret = alloc_data(&der_enc_ts, enc->ciphertext.length); + if (ret) + goto cleanup; + + /* Check for a configured auth indicator. */ + realmstr = k5memdup0(realm.data, realm.length, &ret); + if (realmstr == NULL) + goto cleanup; + ret = profile_get_string(context->profile, KRB5_CONF_REALMS, realmstr, + KRB5_CONF_ENCRYPTED_CHALLENGE_INDICATOR, NULL, + &ai); + if (ret) + goto cleanup; + + ret = cb->client_keys(context, rock, &client_keys); + if (ret) + goto cleanup; + for (i = 0; client_keys[i].enctype != ENCTYPE_NULL; i++) { + ret = krb5_c_fx_cf2_simple(context, armor_key, "clientchallengearmor", + &client_keys[i], "challengelongterm", + &challenge_key); + if (ret) + goto cleanup; + ret = krb5_c_decrypt(context, challenge_key, + KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT, NULL, enc, + &der_enc_ts); + krb5_free_keyblock(context, challenge_key); + if (!ret) + break; + } + + if (client_keys[i].enctype == ENCTYPE_NULL) { + ret = KRB5KDC_ERR_PREAUTH_FAILED; + k5_setmsg(context, ret, + _("Incorrect password in encrypted challenge")); + goto cleanup; + } + + ret = decode_krb5_pa_enc_ts(&der_enc_ts, &ts); + if (ret) + goto cleanup; + ret = krb5_check_clockskew(context, ts->patimestamp); + if (ret) + goto cleanup; + + enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; + + /* + * If this fails, we won't generate a reply to the client. That may cause + * the client to fail, but at this point the KDC has considered this a + * success, so the return value is ignored. + */ + if (krb5_c_fx_cf2_simple(context, armor_key, "kdcchallengearmor", + &client_keys[i], "challengelongterm", + &kdc_challenge_key) == 0) { + modreq = (krb5_kdcpreauth_modreq)kdc_challenge_key; + if (ai != NULL) + cb->add_auth_indicator(context, rock, ai); + } + +cleanup: + cb->free_keys(context, rock, client_keys); + free(der_enc_ts.data); + krb5_free_enc_data(context, enc); + krb5_free_pa_enc_ts(context, ts); + free(realmstr); + free(ai); + + (*respond)(arg, ret, modreq, NULL, NULL); +} + +static krb5_error_code +ec_return(krb5_context context, krb5_pa_data *padata, krb5_data *req_pkt, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_keyblock *encrypting_key, krb5_pa_data **send_pa, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq) +{ + krb5_error_code ret; + krb5_keyblock *challenge_key = (krb5_keyblock *)modreq; + krb5_pa_enc_ts ts; + krb5_data *der_enc_ts = NULL, *der_enc_data = NULL; + krb5_enc_data enc; + krb5_pa_data *pa = NULL; + + enc.ciphertext.data = NULL; + + if (challenge_key == NULL) + return 0; + + ret = krb5_us_timeofday(context, &ts.patimestamp, &ts.pausec); + if (ret) + goto cleanup; + ret = encode_krb5_pa_enc_ts(&ts, &der_enc_ts); + if (ret) + goto cleanup; + ret = krb5_encrypt_helper(context, challenge_key, + KRB5_KEYUSAGE_ENC_CHALLENGE_KDC, der_enc_ts, + &enc); + if (ret) + goto cleanup; + ret = encode_krb5_enc_data(&enc, &der_enc_data); + if (ret) + goto cleanup; + + pa = k5alloc(sizeof(*pa), &ret); + if (pa == NULL) + goto cleanup; + pa->pa_type = KRB5_PADATA_ENCRYPTED_CHALLENGE; + pa->length = der_enc_data->length; + /* Steal the data pointer from der_enc_data. */ + pa->contents = (unsigned char *)der_enc_data->data; + der_enc_data->data = NULL; + + *send_pa = pa; + +cleanup: + krb5_free_keyblock(context, challenge_key); + krb5_free_data(context, der_enc_data); + krb5_free_data(context, der_enc_ts); + krb5_free_data_contents(context, &enc.ciphertext); + return ret; +} + +static krb5_preauthtype ec_types[] = { + KRB5_PADATA_ENCRYPTED_CHALLENGE, 0}; + +krb5_error_code +kdcpreauth_encrypted_challenge_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) +{ + krb5_kdcpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "encrypted_challenge"; + vt->pa_type_list = ec_types; + vt->edata = ec_edata; + vt->verify = ec_verify; + vt->return_padata = ec_return; + return 0; +} diff --git a/krb5-1.21.3/src/kdc/kdc_preauth_encts.c b/krb5-1.21.3/src/kdc/kdc_preauth_encts.c new file mode 100644 index 00000000..25fc7845 --- /dev/null +++ b/krb5-1.21.3/src/kdc/kdc_preauth_encts.c @@ -0,0 +1,138 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/kdc_preauth_encts.c - Encrypted timestamp kdcpreauth module */ +/* + * Copyright (C) 1995, 2003, 2007, 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include "kdc_util.h" + +static void +enc_ts_get(krb5_context context, krb5_kdc_req *request, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type, + krb5_kdcpreauth_edata_respond_fn respond, void *arg) +{ + krb5_keyblock *armor_key = cb->fast_armor(context, rock); + + /* Encrypted timestamp must not be used with FAST, and requires a key. */ + if (armor_key != NULL || !cb->have_client_keys(context, rock)) + (*respond)(arg, ENOENT, NULL); + else + (*respond)(arg, 0, NULL); +} + +static void +enc_ts_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, + krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *pa, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_verify_respond_fn respond, void *arg) +{ + krb5_pa_enc_ts * pa_enc = 0; + krb5_error_code retval; + krb5_data scratch; + krb5_data enc_ts_data; + krb5_enc_data *enc_data = 0; + krb5_keyblock key; + krb5_key_data * client_key; + krb5_int32 start; + + scratch.data = (char *)pa->contents; + scratch.length = pa->length; + + enc_ts_data.data = 0; + + if ((retval = decode_krb5_enc_data(&scratch, &enc_data)) != 0) + goto cleanup; + + enc_ts_data.length = enc_data->ciphertext.length; + if ((enc_ts_data.data = (char *) malloc(enc_ts_data.length)) == NULL) + goto cleanup; + + start = 0; + while (1) { + if ((retval = krb5_dbe_search_enctype(context, rock->client, + &start, enc_data->enctype, + -1, 0, &client_key))) + goto cleanup; + + if ((retval = krb5_dbe_decrypt_key_data(context, NULL, client_key, + &key, NULL))) + goto cleanup; + + key.enctype = enc_data->enctype; + + retval = krb5_c_decrypt(context, &key, KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS, + 0, enc_data, &enc_ts_data); + krb5_free_keyblock_contents(context, &key); + if (retval == 0) + break; + } + + if ((retval = decode_krb5_pa_enc_ts(&enc_ts_data, &pa_enc)) != 0) + goto cleanup; + + retval = krb5_check_clockskew(context, pa_enc->patimestamp); + if (retval) + goto cleanup; + + setflag(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH); + + retval = 0; + +cleanup: + if (enc_data) { + krb5_free_data_contents(context, &enc_data->ciphertext); + free(enc_data); + } + krb5_free_data_contents(context, &enc_ts_data); + if (pa_enc) + free(pa_enc); + /* If we get NO_MATCHING_KEY, it probably means that the password was + * incorrect. */ + if (retval == KRB5_KDB_NO_MATCHING_KEY) + retval = KRB5KDC_ERR_PREAUTH_FAILED; + + (*respond)(arg, retval, NULL, NULL, NULL); +} + +static krb5_preauthtype enc_ts_types[] = { + KRB5_PADATA_ENC_TIMESTAMP, 0 }; + +krb5_error_code +kdcpreauth_encrypted_timestamp_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) +{ + krb5_kdcpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "encrypted_timestamp"; + vt->pa_type_list = enc_ts_types; + vt->edata = enc_ts_get; + vt->verify = enc_ts_verify; + return 0; +} diff --git a/krb5-1.21.3/src/kdc/kdc_transit.c b/krb5-1.21.3/src/kdc/kdc_transit.c new file mode 100644 index 00000000..61aef99e --- /dev/null +++ b/krb5-1.21.3/src/kdc/kdc_transit.c @@ -0,0 +1,414 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/kdc_transit.c */ +/* + * Copyright (C) 2012 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. + */ + +#include "k5-int.h" +#include "kdc_util.h" + +#define MAX_REALM_LN 500 + +/* + * subrealm - determine if r2 is a subrealm of r1 + * + * SUBREALM takes two realms, r1 and r2, and + * determines if r2 is a subrealm of r1. + * r2 is a subrealm of r1 if (r1 is a prefix + * of r2 AND r1 and r2 begin with a /) or if + * (r1 is a suffix of r2 and neither r1 nor r2 + * begin with a /). + * + * RETURNS: If r2 is a subrealm, and r1 is a prefix, the number + * of characters in the suffix of r2 is returned as a + * negative number. + * + * If r2 is a subrealm, and r1 is a suffix, the number + * of characters in the prefix of r2 is returned as a + * positive number. + * + * If r2 is not a subrealm, SUBREALM returns 0. + */ +static int +subrealm(char *r1, char *r2) +{ + size_t l1,l2; + l1 = strlen(r1); + l2 = strlen(r2); + if(l2 <= l1) return(0); + if((*r1 == '/') && (*r2 == '/') && (strncmp(r1,r2,l1) == 0)) return(l1-l2); + if((*r1 != '/') && (*r2 != '/') && (strncmp(r1,r2+l2-l1,l1) == 0)) + return(l2-l1); + return(0); +} + +/* + * add_to_transited Adds the name of the realm which issued the + * ticket granting ticket on which the new ticket to + * be issued is based (note that this is the same as + * the realm of the server listed in the ticket + * granting ticket. + * + * ASSUMPTIONS: This procedure assumes that the transited field from + * the existing ticket granting ticket already appears + * in compressed form. It will add the new realm while + * maintaining that form. As long as each successive + * realm is added using this (or a similar) routine, the + * transited field will be in compressed form. The + * basis step is an empty transited field which is, by + * its nature, in its most compressed form. + * + * ARGUMENTS: krb5_data *tgt_trans Transited field from TGT + * krb5_data *new_trans The transited field for the new ticket + * krb5_principal tgs Name of ticket granting server + * This includes the realm of the KDC + * that issued the ticket granting + * ticket. This is the realm that is + * to be added to the transited field. + * krb5_principal client Name of the client + * krb5_principal server The name of the requested server. + * This may be the an intermediate + * ticket granting server. + * + * The last two argument are needed since they are + * implicitly part of the transited field of the new ticket + * even though they are not explicitly listed. + * + * RETURNS: krb5_error_code - Success, or out of memory + * + * MODIFIES: new_trans: ->length will contain the length of the new + * transited field. + * + * If ->data was not null when this procedure + * is called, the memory referenced by ->data + * will be deallocated. + * + * Memory will be allocated for the new transited field + * ->data will be updated to point to the newly + * allocated memory. + * + * BUGS: The space allocated for the new transited field is the + * maximum that might be needed given the old transited field, + * and the realm to be added. This length is calculated + * assuming that no compression of the new realm is possible. + * This has no adverse consequences other than the allocation + * of more space than required. + * + * This procedure will not yet use the null subfield notation, + * and it will get confused if it sees it. + * + * This procedure does not check for quoted commas in realm + * names. + */ + +char * +data2string (krb5_data *d) +{ + char *s; + s = malloc(d->length + 1); + if (s) { + if (d->length > 0) + memcpy(s, d->data, d->length); + s[d->length] = 0; + } + return s; +} + +krb5_error_code +add_to_transited(krb5_data *tgt_trans, krb5_data *new_trans, + krb5_principal tgs, krb5_principal client, + krb5_principal server) +{ + krb5_error_code retval; + char *realm; + char *trans; + char *otrans, *otrans_ptr; + size_t bufsize; + + /* The following are for stepping through the transited field */ + + char prev[MAX_REALM_LN]; + char next[MAX_REALM_LN]; + char current[MAX_REALM_LN]; + char exp[MAX_REALM_LN]; /* Expanded current realm name */ + + int i; + int clst, nlst; /* count of last character in current and next */ + int pl, pl1; /* prefix length */ + int added; /* TRUE = new realm has been added */ + + realm = data2string(krb5_princ_realm(kdc_context, tgs)); + if (realm == NULL) + return(ENOMEM); + + otrans = data2string(tgt_trans); + if (otrans == NULL) { + free(realm); + return(ENOMEM); + } + /* Keep track of start so we can free */ + otrans_ptr = otrans; + + /* +1 for null, + +1 for extra comma which may be added between + +1 for potential space when leading slash in realm */ + bufsize = strlen(realm) + strlen(otrans) + 3; + if (bufsize > MAX_REALM_LN) + bufsize = MAX_REALM_LN; + if (!(trans = (char *) malloc(bufsize))) { + retval = ENOMEM; + goto fail; + } + + if (new_trans->data) free(new_trans->data); + new_trans->data = trans; + new_trans->length = 0; + + trans[0] = '\0'; + + /* For the purpose of appending, the realm preceding the first */ + /* realm in the transited field is considered the null realm */ + + prev[0] = '\0'; + + /* read field into current */ + for (i = 0; *otrans != '\0';) { + if (*otrans == '\\') { + if (*(++otrans) == '\0') + break; + else + continue; + } + if (*otrans == ',') { + otrans++; + break; + } + current[i++] = *otrans++; + if (i >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + } + current[i] = '\0'; + + added = (krb5_princ_realm(kdc_context, client)->length == strlen(realm) && + !strncmp(krb5_princ_realm(kdc_context, client)->data, realm, strlen(realm))) || + (krb5_princ_realm(kdc_context, server)->length == strlen(realm) && + !strncmp(krb5_princ_realm(kdc_context, server)->data, realm, strlen(realm))); + + while (current[0]) { + + /* figure out expanded form of current name */ + + clst = strlen(current) - 1; + if (current[0] == ' ') { + strncpy(exp, current+1, sizeof(exp) - 1); + exp[sizeof(exp) - 1] = '\0'; + } + else if ((current[0] == '/') && (prev[0] == '/')) { + strncpy(exp, prev, sizeof(exp) - 1); + exp[sizeof(exp) - 1] = '\0'; + if (strlen(exp) + strlen(current) + 1 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + strncat(exp, current, sizeof(exp) - 1 - strlen(exp)); + } + else if (current[clst] == '.') { + strncpy(exp, current, sizeof(exp) - 1); + exp[sizeof(exp) - 1] = '\0'; + if (strlen(exp) + strlen(prev) + 1 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + strncat(exp, prev, sizeof(exp) - 1 - strlen(exp)); + } + else { + strncpy(exp, current, sizeof(exp) - 1); + exp[sizeof(exp) - 1] = '\0'; + } + + /* read field into next */ + for (i = 0; *otrans != '\0';) { + if (*otrans == '\\') { + if (*(++otrans) == '\0') + break; + else + continue; + } + if (*otrans == ',') { + otrans++; + break; + } + next[i++] = *otrans++; + if (i >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + } + next[i] = '\0'; + nlst = i - 1; + + if (!strcmp(exp, realm)) added = TRUE; + + /* If we still have to insert the new realm */ + + if (!added) { + + /* Is the next field compressed? If not, and if the new */ + /* realm is a subrealm of the current realm, compress */ + /* the new realm, and insert immediately following the */ + /* current one. Note that we can not do this if the next*/ + /* field is already compressed since it would mess up */ + /* what has already been done. In most cases, this is */ + /* not a problem because the realm to be added will be a */ + /* subrealm of the next field too, and we will catch */ + /* it in a future iteration. */ + + /* Note that the second test here is an unsigned comparison, + so the first half (or a cast) is also required. */ + assert(nlst < 0 || nlst < (int)sizeof(next)); + if ((nlst < 0 || next[nlst] != '.') && + (next[0] != '/') && + (pl = subrealm(exp, realm))) { + added = TRUE; + current[sizeof(current) - 1] = '\0'; + if (strlen(current) + (pl>0?pl:-pl) + 2 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + strncat(current, ",", sizeof(current) - 1 - strlen(current)); + if (pl > 0) { + strncat(current, realm, (unsigned) pl); + } + else { + strncat(current, realm+strlen(realm)+pl, (unsigned) (-pl)); + } + } + + /* Whether or not the next field is compressed, if the */ + /* realm to be added is a superrealm of the current realm,*/ + /* then the current realm can be compressed. First the */ + /* realm to be added must be compressed relative to the */ + /* previous realm (if possible), and then the current */ + /* realm compressed relative to the new realm. Note that */ + /* if the realm to be added is also a superrealm of the */ + /* previous realm, it would have been added earlier, and */ + /* we would not reach this step this time around. */ + + else if ((pl = subrealm(realm, exp))) { + added = TRUE; + current[0] = '\0'; + if ((pl1 = subrealm(prev,realm))) { + if (strlen(current) + (pl1>0?pl1:-pl1) + 1 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + if (pl1 > 0) { + strncat(current, realm, (unsigned) pl1); + } + else { + strncat(current, realm+strlen(realm)+pl1, (unsigned) (-pl1)); + } + } + else { /* If not a subrealm */ + if ((realm[0] == '/') && prev[0]) { + if (strlen(current) + 2 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + strncat(current, " ", sizeof(current) - 1 - strlen(current)); + current[sizeof(current) - 1] = '\0'; + } + if (strlen(current) + strlen(realm) + 1 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + strncat(current, realm, sizeof(current) - 1 - strlen(current)); + current[sizeof(current) - 1] = '\0'; + } + if (strlen(current) + (pl>0?pl:-pl) + 2 >= MAX_REALM_LN) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + strncat(current,",", sizeof(current) - 1 - strlen(current)); + current[sizeof(current) - 1] = '\0'; + if (pl > 0) { + strncat(current, exp, (unsigned) pl); + } + else { + strncat(current, exp+strlen(exp)+pl, (unsigned)(-pl)); + } + } + } + + if (new_trans->length != 0) { + if (strlcat(trans, ",", bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + } + if (strlcat(trans, current, bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + new_trans->length = strlen(trans); + + strncpy(prev, exp, sizeof(prev) - 1); + prev[sizeof(prev) - 1] = '\0'; + strncpy(current, next, sizeof(current) - 1); + current[sizeof(current) - 1] = '\0'; + } + + if (!added) { + if (new_trans->length != 0) { + if (strlcat(trans, ",", bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + } + if((realm[0] == '/') && trans[0]) { + if (strlcat(trans, " ", bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + } + if (strlcat(trans, realm, bufsize) >= bufsize) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + goto fail; + } + new_trans->length = strlen(trans); + } + + retval = 0; +fail: + free(realm); + free(otrans_ptr); + return (retval); +} diff --git a/krb5-1.21.3/src/kdc/kdc_util.c b/krb5-1.21.3/src/kdc/kdc_util.c new file mode 100644 index 00000000..e54cc751 --- /dev/null +++ b/krb5-1.21.3/src/kdc/kdc_util.c @@ -0,0 +1,1916 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/kdc_util.c - Utility functions for the KDC implementation */ +/* + * Copyright 1990,1991,2007,2008,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "k5-int.h" +#include "kdc_util.h" +#include "extern.h" +#include +#include +#include +#include +#include "adm_proto.h" +#include "net-server.h" +#include + +#ifdef KRBCONF_VAGUE_ERRORS +const int vague_errors = 1; +#else +const int vague_errors = 0; +#endif + +static krb5_error_code kdc_rd_ap_req(kdc_realm_t *realm, krb5_ap_req *apreq, + krb5_auth_context auth_context, + krb5_db_entry **server, + krb5_keyblock **tgskey); +static krb5_error_code find_server_key(krb5_context, + krb5_db_entry *, krb5_enctype, + krb5_kvno, krb5_keyblock **, + krb5_kvno *); + +/* + * Returns TRUE if the kerberos principal is the name of a Kerberos ticket + * service. + */ +krb5_boolean +krb5_is_tgs_principal(krb5_const_principal principal) +{ + if (krb5_princ_size(kdc_context, principal) != 2) + return FALSE; + if (data_eq_string(*krb5_princ_component(kdc_context, principal, 0), + KRB5_TGS_NAME)) + return TRUE; + else + return FALSE; +} + +/* Returns TRUE if principal is the name of a cross-realm TGS. */ +krb5_boolean +is_cross_tgs_principal(krb5_const_principal principal) +{ + return krb5_is_tgs_principal(principal) && + !data_eq(principal->data[1], principal->realm); +} + +/* Return true if princ is the name of a local TGS for any realm. */ +krb5_boolean +is_local_tgs_principal(krb5_const_principal principal) +{ + return krb5_is_tgs_principal(principal) && + data_eq(principal->data[1], principal->realm); +} + +/* + * given authentication data (provides seed for checksum), verify checksum + * for source data. + */ +static krb5_error_code +comp_cksum(krb5_context kcontext, krb5_data *source, krb5_ticket *ticket, + krb5_checksum *his_cksum) +{ + krb5_error_code retval; + krb5_boolean valid; + + if (!krb5_c_valid_cksumtype(his_cksum->checksum_type)) + return KRB5KDC_ERR_SUMTYPE_NOSUPP; + + /* must be collision proof */ + if (!krb5_c_is_coll_proof_cksum(his_cksum->checksum_type)) + return KRB5KRB_AP_ERR_INAPP_CKSUM; + + /* verify checksum */ + if ((retval = krb5_c_verify_checksum(kcontext, ticket->enc_part2->session, + KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, + source, his_cksum, &valid))) + return(retval); + + if (!valid) + return(KRB5KRB_AP_ERR_BAD_INTEGRITY); + + return(0); +} + +/* If a header ticket is decrypted, *ticket_out is filled in even on error. */ +krb5_error_code +kdc_process_tgs_req(kdc_realm_t *realm, krb5_kdc_req *request, + const krb5_fulladdr *from, krb5_data *pkt, + krb5_ticket **ticket_out, krb5_db_entry **krbtgt_ptr, + krb5_keyblock **tgskey, krb5_keyblock **subkey, + krb5_pa_data **pa_tgs_req) +{ + krb5_context context = realm->realm_context; + krb5_pa_data * tmppa; + krb5_ap_req * apreq; + krb5_error_code retval; + krb5_authdata **authdata = NULL; + krb5_data scratch1; + krb5_data * scratch = NULL; + krb5_auth_context auth_context = NULL; + krb5_authenticator * authenticator = NULL; + krb5_checksum * his_cksum = NULL; + krb5_db_entry * krbtgt = NULL; + krb5_ticket * ticket; + + *ticket_out = NULL; + *krbtgt_ptr = NULL; + *tgskey = NULL; + + tmppa = krb5int_find_pa_data(context, request->padata, KRB5_PADATA_AP_REQ); + if (!tmppa) + return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; + + scratch1.length = tmppa->length; + scratch1.data = (char *)tmppa->contents; + if ((retval = decode_krb5_ap_req(&scratch1, &apreq))) + return retval; + ticket = apreq->ticket; + + if (isflagset(apreq->ap_options, AP_OPTS_USE_SESSION_KEY) || + isflagset(apreq->ap_options, AP_OPTS_MUTUAL_REQUIRED)) { + krb5_klog_syslog(LOG_INFO, _("TGS_REQ: SESSION KEY or MUTUAL")); + retval = KRB5KDC_ERR_POLICY; + goto cleanup; + } + + retval = krb5_auth_con_init(context, &auth_context); + if (retval) + goto cleanup; + + /* Don't use a replay cache. */ + retval = krb5_auth_con_setflags(context, auth_context, 0); + if (retval) + goto cleanup; + + retval = krb5_auth_con_setaddrs(context, auth_context, NULL, + from->address); + if (retval) + goto cleanup_auth_context; + + retval = kdc_rd_ap_req(realm, apreq, auth_context, &krbtgt, tgskey); + if (retval) + goto cleanup_auth_context; + + retval = krb5_auth_con_getrecvsubkey(context, auth_context, subkey); + if (retval) + goto cleanup_auth_context; + + retval = krb5_auth_con_getauthenticator(context, auth_context, + &authenticator); + if (retval) + goto cleanup_auth_context; + + retval = krb5_find_authdata(context, ticket->enc_part2->authorization_data, + authenticator->authorization_data, + KRB5_AUTHDATA_FX_ARMOR, &authdata); + if (retval != 0) + goto cleanup_authenticator; + if (authdata&& authdata[0]) { + k5_setmsg(context, KRB5KDC_ERR_POLICY, + "ticket valid only as FAST armor"); + retval = KRB5KDC_ERR_POLICY; + krb5_free_authdata(context, authdata); + goto cleanup_authenticator; + } + krb5_free_authdata(context, authdata); + + + /* Check for a checksum */ + if (!(his_cksum = authenticator->checksum)) { + retval = KRB5KRB_AP_ERR_INAPP_CKSUM; + goto cleanup_authenticator; + } + + /* + * Check application checksum vs. tgs request + * + * We try checksumming the req-body two different ways: first we + * try reaching into the raw asn.1 stream (if available), and + * checksum that directly; if that fails, then we try encoding + * using our local asn.1 library. + */ + if (pkt && (fetch_asn1_field((unsigned char *) pkt->data, + 1, 4, &scratch1) >= 0)) { + if (comp_cksum(context, &scratch1, ticket, his_cksum)) { + if (!(retval = encode_krb5_kdc_req_body(request, &scratch))) + retval = comp_cksum(context, scratch, ticket, his_cksum); + krb5_free_data(context, scratch); + if (retval) + goto cleanup_authenticator; + } + } + + *pa_tgs_req = tmppa; + *krbtgt_ptr = krbtgt; + krbtgt = NULL; + +cleanup_authenticator: + krb5_free_authenticator(context, authenticator); + +cleanup_auth_context: + krb5_auth_con_free(context, auth_context); + +cleanup: + if (retval != 0) { + krb5_free_keyblock(context, *tgskey); + *tgskey = NULL; + } + if (apreq->ticket->enc_part2 != NULL) { + /* Steal the decrypted ticket pointer, even on error. */ + *ticket_out = apreq->ticket; + apreq->ticket = NULL; + } + krb5_free_ap_req(context, apreq); + krb5_db_free_principal(context, krbtgt); + return retval; +} + +/* + * This is a KDC wrapper around krb5_rd_req_decoded_anyflag(). + * + * We can't depend on KDB-as-keytab for handling the AP-REQ here for + * optimization reasons: we want to minimize the number of KDB lookups. We'll + * need the KDB entry for the TGS principal, and the TGS key used to decrypt + * the TGT, elsewhere in the TGS code. + * + * This function also implements key rollover support for kvno 0 cross-realm + * TGTs issued by AD. + */ +static +krb5_error_code +kdc_rd_ap_req(kdc_realm_t *realm, krb5_ap_req *apreq, + krb5_auth_context auth_context, krb5_db_entry **server, + krb5_keyblock **tgskey) +{ + krb5_context context = realm->realm_context; + krb5_error_code retval; + krb5_enctype search_enctype = apreq->ticket->enc_part.enctype; + krb5_boolean match_enctype = 1; + krb5_kvno kvno; + size_t tries = 3; + + /* + * When we issue tickets we use the first key in the principals' highest + * kvno keyset. For non-cross-realm krbtgt principals we want to only + * allow the use of the first key of the principal's keyset that matches + * the given kvno. + */ + if (krb5_is_tgs_principal(apreq->ticket->server) && + !is_cross_tgs_principal(apreq->ticket->server)) { + search_enctype = -1; + match_enctype = 0; + } + + retval = kdc_get_server_key(context, apreq->ticket, 0, match_enctype, + server, NULL, NULL); + if (retval) + return retval; + + *tgskey = NULL; + kvno = apreq->ticket->enc_part.kvno; + do { + krb5_free_keyblock(context, *tgskey); + retval = find_server_key(context, *server, search_enctype, kvno, + tgskey, &kvno); + if (retval) + continue; + + /* Make the TGS key available to krb5_rd_req_decoded_anyflag() */ + retval = krb5_auth_con_setuseruserkey(context, auth_context, *tgskey); + if (retval) + return retval; + + retval = krb5_rd_req_decoded_anyflag(context, &auth_context, apreq, + apreq->ticket->server, + realm->realm_keytab, NULL, NULL); + + /* If the ticket was decrypted, don't try any more keys. */ + if (apreq->ticket->enc_part2 != NULL) + break; + + } while (retval && apreq->ticket->enc_part.kvno == 0 && kvno-- > 1 && + --tries > 0); + + return retval; +} + +/* + * The KDC should take the keytab associated with the realm and pass + * that to the krb5_rd_req_decoded_anyflag(), but we still need to use + * the service (TGS, here) key elsewhere. This approach is faster than + * the KDB keytab approach too. + * + * This is also used by do_tgs_req() for u2u auth. + */ +krb5_error_code +kdc_get_server_key(krb5_context context, + krb5_ticket *ticket, unsigned int flags, + krb5_boolean match_enctype, krb5_db_entry **server_ptr, + krb5_keyblock **key, krb5_kvno *kvno) +{ + krb5_error_code retval; + krb5_db_entry * server = NULL; + krb5_enctype search_enctype = -1; + krb5_kvno search_kvno = -1; + + if (match_enctype) + search_enctype = ticket->enc_part.enctype; + if (ticket->enc_part.kvno) + search_kvno = ticket->enc_part.kvno; + + *server_ptr = NULL; + + retval = krb5_db_get_principal(context, ticket->server, flags, + &server); + if (retval == KRB5_KDB_NOENTRY) { + char *sname; + if (!krb5_unparse_name(context, ticket->server, &sname)) { + limit_string(sname); + krb5_klog_syslog(LOG_ERR, + _("TGS_REQ: UNKNOWN SERVER: server='%s'"), sname); + free(sname); + } + return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + } else if (retval) + return retval; + if (server->attributes & KRB5_KDB_DISALLOW_SVR || + server->attributes & KRB5_KDB_DISALLOW_ALL_TIX) { + retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto errout; + } + + if (key) { + retval = find_server_key(context, server, search_enctype, search_kvno, + key, kvno); + if (retval) + goto errout; + } + *server_ptr = server; + server = NULL; + return 0; + +errout: + krb5_db_free_principal(context, server); + return retval; +} + +/* + * A utility function to get the right key from a KDB entry. Used in handling + * of kvno 0 TGTs, for example. + */ +static +krb5_error_code +find_server_key(krb5_context context, + krb5_db_entry *server, krb5_enctype enctype, krb5_kvno kvno, + krb5_keyblock **key_out, krb5_kvno *kvno_out) +{ + krb5_error_code retval; + krb5_key_data * server_key; + krb5_keyblock * key; + + *key_out = NULL; + retval = krb5_dbe_find_enctype(context, server, enctype, -1, + kvno ? (krb5_int32)kvno : -1, &server_key); + if (retval) + return retval; + if (!server_key) + return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + if ((key = (krb5_keyblock *)malloc(sizeof *key)) == NULL) + return ENOMEM; + retval = krb5_dbe_decrypt_key_data(context, NULL, server_key, + key, NULL); + if (retval) + goto errout; + if (enctype != -1) { + krb5_boolean similar; + retval = krb5_c_enctype_compare(context, enctype, key->enctype, + &similar); + if (retval) + goto errout; + if (!similar) { + retval = KRB5_KDB_NO_PERMITTED_KEY; + goto errout; + } + key->enctype = enctype; + } + *key_out = key; + key = NULL; + if (kvno_out) + *kvno_out = server_key->key_data_kvno; +errout: + krb5_free_keyblock(context, key); + return retval; +} + +/* Find the first key data entry (of a valid enctype) of the highest kvno in + * entry, and decrypt it into *key_out. */ +krb5_error_code +get_first_current_key(krb5_context context, krb5_db_entry *entry, + krb5_keyblock *key_out) +{ + krb5_error_code ret; + krb5_key_data *kd; + + memset(key_out, 0, sizeof(*key_out)); + ret = krb5_dbe_find_enctype(context, entry, -1, -1, 0, &kd); + if (ret) + return ret; + return krb5_dbe_decrypt_key_data(context, NULL, kd, key_out, NULL); +} + +/* + * If candidate is the local TGT for realm, set *alias_out to candidate and + * *storage_out to NULL. Otherwise, load the local TGT into *storage_out and + * set *alias_out to *storage_out. In either case, set *key_out to the + * decrypted first key of the local TGT. + * + * In the future we might generalize this to a small per-request principal + * cache. For now, it saves a load operation in the common case where the AS + * server or TGS header ticket server is the local TGT. + */ +krb5_error_code +get_local_tgt(krb5_context context, const krb5_data *realm, + krb5_db_entry *candidate, krb5_db_entry **alias_out, + krb5_db_entry **storage_out, krb5_keyblock *key_out) +{ + krb5_error_code ret; + krb5_principal princ; + krb5_db_entry *storage = NULL, *tgt; + + *alias_out = NULL; + *storage_out = NULL; + memset(key_out, 0, sizeof(*key_out)); + + ret = krb5_build_principal_ext(context, &princ, realm->length, realm->data, + KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, + realm->length, realm->data, 0); + if (ret) + goto cleanup; + + if (!krb5_principal_compare(context, candidate->princ, princ)) { + ret = krb5_db_get_principal(context, princ, 0, &storage); + if (ret) + goto cleanup; + tgt = storage; + } else { + tgt = candidate; + } + + ret = get_first_current_key(context, tgt, key_out); + if (ret) + goto cleanup; + + *alias_out = tgt; + *storage_out = storage; + storage = NULL; + +cleanup: + krb5_db_free_principal(context, storage); + krb5_free_principal(context, princ); + return ret; +} + +/* If server has a pac_privsvr_enctype attribute and it differs from tgt_key's + * enctype, derive a key of the specified enctype. Otherwise copy tgt_key. */ +krb5_error_code +pac_privsvr_key(krb5_context context, krb5_db_entry *server, + const krb5_keyblock *tgt_key, krb5_keyblock **key_out) +{ + krb5_error_code ret; + char *attrval = NULL; + krb5_enctype privsvr_enctype; + krb5_data prf_input = string2data("pac_privsvr"); + + ret = krb5_dbe_get_string(context, server, KRB5_KDB_SK_PAC_PRIVSVR_ENCTYPE, + &attrval); + if (ret) + return ret; + if (attrval == NULL) + return krb5_copy_keyblock(context, tgt_key, key_out); + + ret = krb5_string_to_enctype(attrval, &privsvr_enctype); + if (ret) { + k5_setmsg(context, ret, _("Invalid pac_privsvr_enctype value %s"), + attrval); + goto cleanup; + } + + if (tgt_key->enctype == privsvr_enctype) { + ret = krb5_copy_keyblock(context, tgt_key, key_out); + } else { + ret = krb5_c_derive_prfplus(context, tgt_key, &prf_input, + privsvr_enctype, key_out); + } + +cleanup: + krb5_dbe_free_string(context, attrval); + return ret; +} + +/* Try verifying a ticket's PAC using a privsvr key either equal to or derived + * from tgt_key, respecting the server's pac_privsvr_enctype value if set. */ +static krb5_error_code +try_verify_pac(krb5_context context, const krb5_enc_tkt_part *enc_tkt, + krb5_db_entry *server, krb5_keyblock *server_key, + const krb5_keyblock *tgt_key, krb5_pac *pac_out) +{ + krb5_error_code ret; + krb5_keyblock *privsvr_key; + + ret = pac_privsvr_key(context, server, tgt_key, &privsvr_key); + if (ret) + return ret; + ret = krb5_kdc_verify_ticket(context, enc_tkt, server->princ, server_key, + privsvr_key, pac_out); + krb5_free_keyblock(context, privsvr_key); + return ret; +} + +/* + * If a PAC is present in enc_tkt, verify it and place it in *pac_out. sprinc + * is the canonical name of the server principal entry used to decrypt enc_tkt. + * server_key is the ticket decryption key. tgt is the local krbtgt entry for + * the ticket server realm, and tgt_key is its first key. + */ +krb5_error_code +get_verified_pac(krb5_context context, const krb5_enc_tkt_part *enc_tkt, + krb5_db_entry *server, krb5_keyblock *server_key, + krb5_db_entry *tgt, krb5_keyblock *tgt_key, krb5_pac *pac_out) +{ + krb5_error_code ret; + krb5_key_data *kd; + krb5_keyblock old_key; + krb5_kvno kvno; + int tries; + + *pac_out = NULL; + + /* For local or cross-realm TGTs we only check the server signature. */ + if (krb5_is_tgs_principal(server->princ)) { + return krb5_kdc_verify_ticket(context, enc_tkt, server->princ, + server_key, NULL, pac_out); + } + + ret = try_verify_pac(context, enc_tkt, server, server_key, tgt_key, + pac_out); + if (ret != KRB5KRB_AP_ERR_MODIFIED && ret != KRB5_BAD_ENCTYPE) + return ret; + + /* There is no kvno in PAC signatures, so try two previous versions. */ + kvno = tgt->key_data[0].key_data_kvno - 1; + for (tries = 2; tries > 0 && kvno > 0; tries--, kvno--) { + ret = krb5_dbe_find_enctype(context, tgt, -1, -1, kvno, &kd); + if (ret) + return KRB5KRB_AP_ERR_MODIFIED; + ret = krb5_dbe_decrypt_key_data(context, NULL, kd, &old_key, NULL); + if (ret) + return ret; + ret = try_verify_pac(context, enc_tkt, server, server_key, &old_key, + pac_out); + krb5_free_keyblock_contents(context, &old_key); + if (!ret) + return 0; + } + + return KRB5KRB_AP_ERR_MODIFIED; +} + +/* + * Fetch the client info from pac and parse it into a principal name, expecting + * a realm in the string. Set *authtime_out to the client info authtime if it + * is not null. + */ +krb5_error_code +get_pac_princ_with_realm(krb5_context context, krb5_pac pac, + krb5_principal *princ_out, + krb5_timestamp *authtime_out) +{ + krb5_error_code ret; + int n_atsigns, flags = KRB5_PRINCIPAL_PARSE_REQUIRE_REALM; + char *client_str = NULL; + const char *p; + + *princ_out = NULL; + + ret = krb5_pac_get_client_info(context, pac, authtime_out, &client_str); + if (ret) + return ret; + + n_atsigns = 0; + for (p = client_str; *p != '\0'; p++) { + if (*p == '@') + n_atsigns++; + } + + if (n_atsigns == 2) { + flags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE; + } else if (n_atsigns != 1) { + ret = KRB5_PARSE_MALFORMED; + goto cleanup; + } + + ret = krb5_parse_name_flags(context, client_str, flags, princ_out); + if (ret) + return ret; + + (*princ_out)->type = KRB5_NT_MS_PRINCIPAL; + +cleanup: + free(client_str); + return 0; +} + +/* This probably wants to be updated if you support last_req stuff */ + +static krb5_last_req_entry nolrentry = { KV5M_LAST_REQ_ENTRY, KRB5_LRQ_NONE, 0 }; +static krb5_last_req_entry *nolrarray[] = { &nolrentry, 0 }; + +krb5_error_code +fetch_last_req_info(krb5_db_entry *dbentry, krb5_last_req_entry ***lrentry) +{ + *lrentry = nolrarray; + return 0; +} + + +/* Convert an API error code to a protocol error code. */ +int +errcode_to_protocol(krb5_error_code code) +{ + int protcode; + + protcode = code - ERROR_TABLE_BASE_krb5; + return (protcode >= 0 && protcode <= 128) ? protcode : KRB_ERR_GENERIC; +} + +/* Return -1 if the AS or TGS request is disallowed due to KDC policy on + * anonymous tickets. */ +int +check_anon(kdc_realm_t *realm, krb5_principal client, krb5_principal server) +{ + /* If restrict_anon is set, reject requests from anonymous clients to + * server principals other than local TGTs. */ + if (realm->realm_restrict_anon && + krb5_principal_compare_any_realm(realm->realm_context, client, + krb5_anonymous_principal()) && + !is_local_tgs_principal(server)) + return -1; + return 0; +} + +krb5_error_code +validate_as_request(kdc_realm_t *realm, krb5_kdc_req *request, + krb5_db_entry *client, krb5_db_entry *server, + krb5_timestamp kdc_time, const char **status, + krb5_pa_data ***e_data) +{ + krb5_context context = realm->realm_context; + krb5_error_code ret; + + /* + * If an option is set that is only allowed in TGS requests, complain. + */ + if (request->kdc_options & AS_INVALID_OPTIONS) { + *status = "INVALID AS OPTIONS"; + return KRB5KDC_ERR_BADOPTION; + } + + /* The client must not be expired */ + if (client->expiration && ts_after(kdc_time, client->expiration)) { + *status = "CLIENT EXPIRED"; + if (vague_errors) + return KRB5KRB_ERR_GENERIC; + else + return KRB5KDC_ERR_NAME_EXP; + } + + /* The client's password must not be expired, unless the server is + a KRB5_KDC_PWCHANGE_SERVICE. */ + if (client->pw_expiration && ts_after(kdc_time, client->pw_expiration) && + !isflagset(server->attributes, KRB5_KDB_PWCHANGE_SERVICE)) { + *status = "CLIENT KEY EXPIRED"; + if (vague_errors) + return KRB5KRB_ERR_GENERIC; + else + return KRB5KDC_ERR_KEY_EXP; + } + + /* The server must not be expired */ + if (server->expiration && ts_after(kdc_time, server->expiration)) { + *status = "SERVICE EXPIRED"; + return KRB5KDC_ERR_SERVICE_EXP; + } + + /* + * If the client requires password changing, then only allow the + * pwchange service. + */ + if (isflagset(client->attributes, KRB5_KDB_REQUIRES_PWCHANGE) && + !isflagset(server->attributes, KRB5_KDB_PWCHANGE_SERVICE)) { + *status = "REQUIRED PWCHANGE"; + return KRB5KDC_ERR_KEY_EXP; + } + + /* Client and server must allow postdating tickets */ + if ((isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE) || + isflagset(request->kdc_options, KDC_OPT_POSTDATED)) && + (isflagset(client->attributes, KRB5_KDB_DISALLOW_POSTDATED) || + isflagset(server->attributes, KRB5_KDB_DISALLOW_POSTDATED))) { + *status = "POSTDATE NOT ALLOWED"; + return KRB5KDC_ERR_CANNOT_POSTDATE; + } + + /* Check to see if client is locked out */ + if (isflagset(client->attributes, KRB5_KDB_DISALLOW_ALL_TIX)) { + *status = "CLIENT LOCKED OUT"; + return KRB5KDC_ERR_CLIENT_REVOKED; + } + + /* Check to see if server is locked out */ + if (isflagset(server->attributes, KRB5_KDB_DISALLOW_ALL_TIX)) { + *status = "SERVICE LOCKED OUT"; + return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + } + + /* Check to see if server is allowed to be a service */ + if (isflagset(server->attributes, KRB5_KDB_DISALLOW_SVR)) { + *status = "SERVICE NOT ALLOWED"; + return KRB5KDC_ERR_MUST_USE_USER2USER; + } + + if (check_anon(realm, client->princ, request->server) != 0) { + *status = "ANONYMOUS NOT ALLOWED"; + return KRB5KDC_ERR_POLICY; + } + + /* Perform KDB module policy checks. */ + ret = krb5_db_check_policy_as(context, request, client, server, kdc_time, + status, e_data); + return (ret == KRB5_PLUGIN_OP_NOTSUPP) ? 0 : ret; +} + +/* + * Compute ticket flags based on the request, the client and server DB entry + * (which may prohibit forwardable or proxiable tickets), and the header + * ticket. client may be NULL for a TGS request (although it may be set, such + * as for an S4U2Self request). header_enc may be NULL for an AS request. + */ +krb5_flags +get_ticket_flags(krb5_flags reqflags, krb5_db_entry *client, + krb5_db_entry *server, krb5_enc_tkt_part *header_enc) +{ + krb5_flags flags; + + /* Validation and renewal TGS requests preserve the header ticket flags. */ + if ((reqflags & (KDC_OPT_VALIDATE | KDC_OPT_RENEW)) && header_enc != NULL) + return header_enc->flags & ~TKT_FLG_INVALID; + + /* Indicate support for encrypted padata (RFC 6806), and set flags based on + * request options and the header ticket. */ + flags = OPTS2FLAGS(reqflags) | TKT_FLG_ENC_PA_REP; + if (reqflags & KDC_OPT_POSTDATED) + flags |= TKT_FLG_INVALID; + if (header_enc != NULL) + flags |= COPY_TKT_FLAGS(header_enc->flags); + if (header_enc == NULL) + flags |= TKT_FLG_INITIAL; + + /* For TGS requests, indicate if the service is marked ok-as-delegate. */ + if (header_enc != NULL && (server->attributes & KRB5_KDB_OK_AS_DELEGATE)) + flags |= TKT_FLG_OK_AS_DELEGATE; + + /* Unset PROXIABLE if it is disallowed. */ + if (client != NULL && (client->attributes & KRB5_KDB_DISALLOW_PROXIABLE)) + flags &= ~TKT_FLG_PROXIABLE; + if (server->attributes & KRB5_KDB_DISALLOW_PROXIABLE) + flags &= ~TKT_FLG_PROXIABLE; + if (header_enc != NULL && !(header_enc->flags & TKT_FLG_PROXIABLE)) + flags &= ~TKT_FLG_PROXIABLE; + + /* Unset FORWARDABLE if it is disallowed. */ + if (client != NULL && (client->attributes & KRB5_KDB_DISALLOW_FORWARDABLE)) + flags &= ~TKT_FLG_FORWARDABLE; + if (server->attributes & KRB5_KDB_DISALLOW_FORWARDABLE) + flags &= ~TKT_FLG_FORWARDABLE; + if (header_enc != NULL && !(header_enc->flags & TKT_FLG_FORWARDABLE)) + flags &= ~TKT_FLG_FORWARDABLE; + + /* We don't currently handle issuing anonymous tickets based on + * non-anonymous ones. */ + if (header_enc != NULL && !(header_enc->flags & TKT_FLG_ANONYMOUS)) + flags &= ~TKT_FLG_ANONYMOUS; + + return flags; +} + +/* Return KRB5KDC_ERR_POLICY if indicators does not contain the required auth + * indicators for server, ENOMEM on allocation error, 0 otherwise. */ +krb5_error_code +check_indicators(krb5_context context, krb5_db_entry *server, + krb5_data *const *indicators) +{ + krb5_error_code ret; + char *str = NULL, *copy = NULL, *save, *ind; + + ret = krb5_dbe_get_string(context, server, KRB5_KDB_SK_REQUIRE_AUTH, &str); + if (ret || str == NULL) + goto cleanup; + copy = strdup(str); + if (copy == NULL) { + ret = ENOMEM; + goto cleanup; + } + + /* Look for any of the space-separated strings in indicators. */ + ind = strtok_r(copy, " ", &save); + while (ind != NULL) { + if (authind_contains(indicators, ind)) + goto cleanup; + ind = strtok_r(NULL, " ", &save); + } + + ret = KRB5KDC_ERR_POLICY; + k5_setmsg(context, ret, + _("Required auth indicators not present in ticket: %s"), str); + +cleanup: + krb5_dbe_free_string(context, str); + free(copy); + return ret; +} + +#define ASN1_ID_CLASS (0xc0) +#define ASN1_ID_TYPE (0x20) +#define ASN1_ID_TAG (0x1f) +#define ASN1_CLASS_UNIV (0) +#define ASN1_CLASS_APP (1) +#define ASN1_CLASS_CTX (2) +#define ASN1_CLASS_PRIV (3) +#define asn1_id_constructed(x) (x & ASN1_ID_TYPE) +#define asn1_id_primitive(x) (!asn1_id_constructed(x)) +#define asn1_id_class(x) ((x & ASN1_ID_CLASS) >> 6) +#define asn1_id_tag(x) (x & ASN1_ID_TAG) + +/* + * asn1length - return encoded length of value. + * + * passed a pointer into the asn.1 stream, which is updated + * to point right after the length bits. + * + * returns -1 on failure. + */ +static int +asn1length(unsigned char **astream) +{ + int length; /* resulting length */ + int sublen; /* sublengths */ + int blen; /* bytes of length */ + unsigned char *p; /* substring searching */ + + if (**astream & 0x80) { + blen = **astream & 0x7f; + if (blen > 3) { + return(-1); + } + for (++*astream, length = 0; blen; ++*astream, blen--) { + length = (length << 8) | **astream; + } + if (length == 0) { + /* indefinite length, figure out by hand */ + p = *astream; + p++; + while (1) { + /* compute value length. */ + if ((sublen = asn1length(&p)) < 0) { + return(-1); + } + p += sublen; + /* check for termination */ + if ((!*p++) && (!*p)) { + p++; + break; + } + } + length = p - *astream; + } + } else { + length = **astream; + ++*astream; + } + return(length); +} + +/* + * fetch_asn1_field - return raw asn.1 stream of subfield. + * + * this routine is passed a context-dependent tag number and "level" and returns + * the size and length of the corresponding level subfield. + * + * levels and are numbered starting from 1. + * + * returns 0 on success, -1 otherwise. + */ +int +fetch_asn1_field(unsigned char *astream, unsigned int level, + unsigned int field, krb5_data *data) +{ + unsigned char *estream; /* end of stream */ + int classes; /* # classes seen so far this level */ + unsigned int levels = 0; /* levels seen so far */ + int lastlevel = 1000; /* last level seen */ + int length; /* various lengths */ + int tag; /* tag number */ + unsigned char savelen; /* saved length of our field */ + + classes = -1; + /* we assume that the first identifier/length will tell us + how long the entire stream is. */ + astream++; + estream = astream; + if ((length = asn1length(&astream)) < 0) { + return(-1); + } + estream += length; + /* search down the stream, checking identifiers. we process identifiers + until we hit the "level" we want, and then process that level for our + subfield, always making sure we don't go off the end of the stream. */ + while (astream < estream) { + if (!asn1_id_constructed(*astream)) { + return(-1); + } + if (asn1_id_class(*astream) == ASN1_CLASS_CTX) { + if ((tag = (int)asn1_id_tag(*astream)) <= lastlevel) { + levels++; + classes = -1; + } + lastlevel = tag; + if (levels == level) { + /* in our context-dependent class, is this the one we're looking for ? */ + if (tag == (int)field) { + /* return length and data */ + astream++; + savelen = *astream; + if ((length = asn1length(&astream)) < 0) { + return(-1); + } + data->length = length; + /* if the field length is indefinite, we will have to subtract two + (terminating octets) from the length returned since we don't want + to pass any info from the "wrapper" back. asn1length will always return + the *total* length of the field, not just what's contained in it */ + if ((savelen & 0xff) == 0x80) { + data->length -=2 ; + } + data->data = (char *)astream; + return(0); + } else if (tag <= classes) { + /* we've seen this class before, something must be wrong */ + return(-1); + } else { + classes = tag; + } + } + } + /* if we're not on our level yet, process this value. otherwise skip over it */ + astream++; + if ((length = asn1length(&astream)) < 0) { + return(-1); + } + if (levels == level) { + astream += length; + } + } + return(-1); +} + +/* Return true if we believe server can support enctype as a session key. */ +static krb5_boolean +dbentry_supports_enctype(krb5_context context, krb5_db_entry *server, + krb5_enctype enctype) +{ + krb5_error_code retval; + krb5_key_data *datap; + char *etypes_str = NULL; + krb5_enctype default_enctypes[1] = { 0 }; + krb5_enctype *etypes = NULL; + krb5_boolean in_list; + + /* Look up the supported session key enctypes list in the KDB. */ + retval = krb5_dbe_get_string(context, server, KRB5_KDB_SK_SESSION_ENCTYPES, + &etypes_str); + if (retval == 0 && etypes_str != NULL && *etypes_str != '\0') { + /* Pass a fake profile key for tracing of unrecognized tokens. */ + retval = krb5int_parse_enctype_list(context, "KDB-session_etypes", + etypes_str, default_enctypes, + &etypes); + if (retval == 0 && etypes != NULL && etypes[0]) { + in_list = k5_etypes_contains(etypes, enctype); + free(etypes_str); + free(etypes); + return in_list; + } + /* Fall through on error or empty list */ + } + free(etypes_str); + free(etypes); + + /* Assume every server without a session_enctypes attribute supports + * aes256-cts-hmac-sha1-96. */ + if (enctype == ENCTYPE_AES256_CTS_HMAC_SHA1_96) + return TRUE; + /* Assume the server supports any enctype it has a long-term key for. */ + return !krb5_dbe_find_enctype(context, server, enctype, -1, 0, &datap); +} + +/* + * This function returns the keytype which should be selected for the + * session key. It is based on the ordered list which the user + * requested, and what the KDC and the application server can support. + */ +krb5_enctype +select_session_keytype(krb5_context context, krb5_db_entry *server, + int nktypes, krb5_enctype *ktype) +{ + int i; + + for (i = 0; i < nktypes; i++) { + if (!krb5_c_valid_enctype(ktype[i])) + continue; + + if (!krb5_is_permitted_enctype(context, ktype[i])) + continue; + + /* + * Prevent these deprecated enctypes from being used as session keys + * unless they are explicitly allowed. In the future they will be more + * comprehensively disabled and eventually removed. + */ + if (ktype[i] == ENCTYPE_DES3_CBC_SHA1 && !context->allow_des3) + continue; + if (ktype[i] == ENCTYPE_ARCFOUR_HMAC && !context->allow_rc4) + continue; + + if (dbentry_supports_enctype(context, server, ktype[i])) + return ktype[i]; + } + + return 0; +} + +/* + * Limit strings to a "reasonable" length to prevent crowding out of + * other useful information in the log entry + */ +#define NAME_LENGTH_LIMIT 128 + +void limit_string(char *name) +{ + int i; + + if (!name) + return; + + if (strlen(name) < NAME_LENGTH_LIMIT) + return; + + i = NAME_LENGTH_LIMIT-4; + name[i++] = '.'; + name[i++] = '.'; + name[i++] = '.'; + name[i] = '\0'; + return; +} + +/* Wrapper of krb5_enctype_to_name() to include the PKINIT types. */ +static krb5_error_code +enctype_name(krb5_enctype ktype, char *buf, size_t buflen) +{ + const char *name, *prefix = ""; + size_t len; + + if (buflen == 0) + return EINVAL; + *buf = '\0'; /* ensure these are always valid C-strings */ + + if (!krb5_c_valid_enctype(ktype)) + prefix = "UNSUPPORTED:"; + else if (krb5int_c_deprecated_enctype(ktype)) + prefix = "DEPRECATED:"; + len = strlcpy(buf, prefix, buflen); + if (len >= buflen) + return ENOMEM; + buflen -= len; + buf += len; + + /* rfc4556 recommends that clients wishing to indicate support for these + * pkinit algorithms include them in the etype field of the AS-REQ. */ + if (ktype == ENCTYPE_DSA_SHA1_CMS) + name = "id-dsa-with-sha1-CmsOID"; + else if (ktype == ENCTYPE_MD5_RSA_CMS) + name = "md5WithRSAEncryption-CmsOID"; + else if (ktype == ENCTYPE_SHA1_RSA_CMS) + name = "sha-1WithRSAEncryption-CmsOID"; + else if (ktype == ENCTYPE_RC2_CBC_ENV) + name = "rc2-cbc-EnvOID"; + else if (ktype == ENCTYPE_RSA_ENV) + name = "rsaEncryption-EnvOID"; + else if (ktype == ENCTYPE_RSA_ES_OAEP_ENV) + name = "id-RSAES-OAEP-EnvOID"; + else if (ktype == ENCTYPE_DES3_CBC_ENV) + name = "des-ede3-cbc-EnvOID"; + else + return krb5_enctype_to_name(ktype, FALSE, buf, buflen); + + if (strlcpy(buf, name, buflen) >= buflen) + return ENOMEM; + return 0; +} + +char * +ktypes2str(krb5_enctype *ktype, int nktypes) +{ + struct k5buf buf; + int i; + char name[64]; + + if (nktypes < 0) + return NULL; + + k5_buf_init_dynamic(&buf); + k5_buf_add_fmt(&buf, "%d etypes {", nktypes); + for (i = 0; i < nktypes; i++) { + enctype_name(ktype[i], name, sizeof(name)); + k5_buf_add_fmt(&buf, "%s%s(%ld)", i ? ", " : "", name, (long)ktype[i]); + } + k5_buf_add(&buf, "}"); + return k5_buf_cstring(&buf); +} + +char * +rep_etypes2str(krb5_kdc_rep *rep) +{ + struct k5buf buf; + char name[64]; + krb5_enctype etype; + + k5_buf_init_dynamic(&buf); + k5_buf_add(&buf, "etypes {rep="); + enctype_name(rep->enc_part.enctype, name, sizeof(name)); + k5_buf_add_fmt(&buf, "%s(%ld)", name, (long)rep->enc_part.enctype); + + if (rep->ticket != NULL) { + etype = rep->ticket->enc_part.enctype; + enctype_name(etype, name, sizeof(name)); + k5_buf_add_fmt(&buf, ", tkt=%s(%ld)", name, (long)etype); + } + + if (rep->ticket != NULL && rep->ticket->enc_part2 != NULL && + rep->ticket->enc_part2->session != NULL) { + etype = rep->ticket->enc_part2->session->enctype; + enctype_name(etype, name, sizeof(name)); + k5_buf_add_fmt(&buf, ", ses=%s(%ld)", name, (long)etype); + } + + k5_buf_add(&buf, "}"); + return k5_buf_cstring(&buf); +} + +static krb5_error_code +verify_for_user_checksum(krb5_context context, + krb5_keyblock *key, + krb5_pa_for_user *req) +{ + krb5_error_code code; + int i; + krb5_int32 name_type; + char *p; + krb5_data data; + krb5_boolean valid = FALSE; + + if (!krb5_c_is_keyed_cksum(req->cksum.checksum_type)) { + return KRB5KRB_AP_ERR_INAPP_CKSUM; + } + + /* + * Checksum is over name type and string components of + * client principal name and auth_package. + */ + data.length = 4; + for (i = 0; i < krb5_princ_size(context, req->user); i++) { + data.length += krb5_princ_component(context, req->user, i)->length; + } + data.length += krb5_princ_realm(context, req->user)->length; + data.length += req->auth_package.length; + + p = data.data = malloc(data.length); + if (data.data == NULL) { + return ENOMEM; + } + + name_type = krb5_princ_type(context, req->user); + p[0] = (name_type >> 0 ) & 0xFF; + p[1] = (name_type >> 8 ) & 0xFF; + p[2] = (name_type >> 16) & 0xFF; + p[3] = (name_type >> 24) & 0xFF; + p += 4; + + for (i = 0; i < krb5_princ_size(context, req->user); i++) { + if (krb5_princ_component(context, req->user, i)->length > 0) { + memcpy(p, krb5_princ_component(context, req->user, i)->data, + krb5_princ_component(context, req->user, i)->length); + } + p += krb5_princ_component(context, req->user, i)->length; + } + + if (krb5_princ_realm(context, req->user)->length > 0) { + memcpy(p, krb5_princ_realm(context, req->user)->data, + krb5_princ_realm(context, req->user)->length); + } + p += krb5_princ_realm(context, req->user)->length; + + if (req->auth_package.length > 0) + memcpy(p, req->auth_package.data, req->auth_package.length); + p += req->auth_package.length; + + code = krb5_c_verify_checksum(context, + key, + KRB5_KEYUSAGE_APP_DATA_CKSUM, + &data, + &req->cksum, + &valid); + + if (code == 0 && valid == FALSE) + code = KRB5KRB_AP_ERR_MODIFIED; + + free(data.data); + + return code; +} + +/* + * Legacy protocol transition (Windows 2003 and above) + */ +static krb5_error_code +kdc_process_for_user(krb5_context context, krb5_pa_data *pa_data, + krb5_keyblock *tgs_session, + krb5_pa_s4u_x509_user **s4u_x509_user, + const char **status) +{ + krb5_error_code code; + krb5_pa_for_user *for_user; + krb5_data req_data; + + req_data.length = pa_data->length; + req_data.data = (char *)pa_data->contents; + + code = decode_krb5_pa_for_user(&req_data, &for_user); + if (code) { + *status = "DECODE_PA_FOR_USER"; + return code; + } + + code = verify_for_user_checksum(context, tgs_session, for_user); + if (code) { + *status = "INVALID_S4U2SELF_CHECKSUM"; + krb5_free_pa_for_user(context, for_user); + return code; + } + + *s4u_x509_user = calloc(1, sizeof(krb5_pa_s4u_x509_user)); + if (*s4u_x509_user == NULL) { + krb5_free_pa_for_user(context, for_user); + return ENOMEM; + } + + (*s4u_x509_user)->user_id.user = for_user->user; + for_user->user = NULL; + krb5_free_pa_for_user(context, for_user); + + return 0; +} + +static krb5_error_code +verify_s4u_x509_user_checksum(krb5_context context, + krb5_keyblock *key, + krb5_data *req_data, + krb5_int32 kdc_req_nonce, + krb5_pa_s4u_x509_user *req) +{ + krb5_error_code code; + krb5_data scratch; + krb5_boolean valid = FALSE; + + if (enctype_requires_etype_info_2(key->enctype) && + !krb5_c_is_keyed_cksum(req->cksum.checksum_type)) + return KRB5KRB_AP_ERR_INAPP_CKSUM; + + if (req->user_id.nonce != kdc_req_nonce) + return KRB5KRB_AP_ERR_MODIFIED; + + /* + * Verify checksum over the encoded userid. If that fails, + * re-encode, and verify that. This is similar to the + * behaviour in kdc_process_tgs_req(). + */ + if (fetch_asn1_field((unsigned char *)req_data->data, 1, 0, &scratch) < 0) + return ASN1_PARSE_ERROR; + + code = krb5_c_verify_checksum(context, + key, + KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST, + &scratch, + &req->cksum, + &valid); + if (code != 0) + return code; + + if (valid == FALSE) { + krb5_data *data; + + code = encode_krb5_s4u_userid(&req->user_id, &data); + if (code != 0) + return code; + + code = krb5_c_verify_checksum(context, + key, + KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST, + data, + &req->cksum, + &valid); + + krb5_free_data(context, data); + + if (code != 0) + return code; + } + + return valid ? 0 : KRB5KRB_AP_ERR_MODIFIED; +} + +/* + * New protocol transition request (Windows 2008 and above) + */ +static krb5_error_code +kdc_process_s4u_x509_user(krb5_context context, + krb5_kdc_req *request, + krb5_pa_data *pa_data, + krb5_keyblock *tgs_subkey, + krb5_keyblock *tgs_session, + krb5_pa_s4u_x509_user **s4u_x509_user, + const char **status) +{ + krb5_error_code code; + krb5_data req_data; + + req_data.length = pa_data->length; + req_data.data = (char *)pa_data->contents; + + code = decode_krb5_pa_s4u_x509_user(&req_data, s4u_x509_user); + if (code) { + *status = "DECODE_PA_S4U_X509_USER"; + return code; + } + + code = verify_s4u_x509_user_checksum(context, + tgs_subkey ? tgs_subkey : + tgs_session, + &req_data, + request->nonce, *s4u_x509_user); + + if (code) { + *status = "INVALID_S4U2SELF_CHECKSUM"; + krb5_free_pa_s4u_x509_user(context, *s4u_x509_user); + *s4u_x509_user = NULL; + return code; + } + + if (krb5_princ_size(context, (*s4u_x509_user)->user_id.user) == 0 && + (*s4u_x509_user)->user_id.subject_cert.length == 0) { + *status = "INVALID_S4U2SELF_REQUEST"; + krb5_free_pa_s4u_x509_user(context, *s4u_x509_user); + *s4u_x509_user = NULL; + return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + } + + return 0; +} + +krb5_error_code +kdc_make_s4u2self_rep(krb5_context context, + krb5_keyblock *tgs_subkey, + krb5_keyblock *tgs_session, + krb5_pa_s4u_x509_user *req_s4u_user, + krb5_kdc_rep *reply, + krb5_enc_kdc_rep_part *reply_encpart) +{ + krb5_error_code code; + krb5_data *der_user_id = NULL, *der_s4u_x509_user = NULL; + krb5_pa_s4u_x509_user rep_s4u_user; + krb5_pa_data *pa = NULL; + krb5_enctype enctype; + krb5_keyusage usage; + + memset(&rep_s4u_user, 0, sizeof(rep_s4u_user)); + + rep_s4u_user.user_id.nonce = req_s4u_user->user_id.nonce; + rep_s4u_user.user_id.user = req_s4u_user->user_id.user; + rep_s4u_user.user_id.options = + req_s4u_user->user_id.options & KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE; + + code = encode_krb5_s4u_userid(&rep_s4u_user.user_id, &der_user_id); + if (code != 0) + goto cleanup; + + if (req_s4u_user->user_id.options & KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE) + usage = KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY; + else + usage = KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST; + + code = krb5_c_make_checksum(context, req_s4u_user->cksum.checksum_type, + tgs_subkey != NULL ? tgs_subkey : tgs_session, + usage, der_user_id, &rep_s4u_user.cksum); + if (code != 0) + goto cleanup; + + code = encode_krb5_pa_s4u_x509_user(&rep_s4u_user, &der_s4u_x509_user); + if (code != 0) + goto cleanup; + + code = k5_add_pa_data_from_data(&reply->padata, KRB5_PADATA_S4U_X509_USER, + der_s4u_x509_user); + if (code != 0) + goto cleanup; + + if (tgs_subkey != NULL) + enctype = tgs_subkey->enctype; + else + enctype = tgs_session->enctype; + + /* + * Owing to a bug in Windows, unkeyed checksums were used for older + * enctypes, including rc4-hmac. A forthcoming workaround for this + * includes the checksum bytes in the encrypted padata. + */ + if (enctype_requires_etype_info_2(enctype) == FALSE) { + code = k5_alloc_pa_data(KRB5_PADATA_S4U_X509_USER, + req_s4u_user->cksum.length + + rep_s4u_user.cksum.length, &pa); + if (code != 0) + goto cleanup; + memcpy(pa->contents, + req_s4u_user->cksum.contents, req_s4u_user->cksum.length); + memcpy(&pa->contents[req_s4u_user->cksum.length], + rep_s4u_user.cksum.contents, rep_s4u_user.cksum.length); + + code = k5_add_pa_data_element(&reply_encpart->enc_padata, &pa); + if (code != 0) + goto cleanup; + } + +cleanup: + if (rep_s4u_user.cksum.contents != NULL) + krb5_free_checksum_contents(context, &rep_s4u_user.cksum); + krb5_free_data(context, der_user_id); + krb5_free_data(context, der_s4u_x509_user); + k5_free_pa_data_element(pa); + return code; +} + +/* Return true if princ canonicalizes to the same principal as entry's. */ +krb5_boolean +is_client_db_alias(krb5_context context, const krb5_db_entry *entry, + krb5_const_principal princ) +{ + krb5_error_code ret; + krb5_db_entry *self; + krb5_boolean is_self = FALSE; + + ret = krb5_db_get_principal(context, princ, KRB5_KDB_FLAG_CLIENT, &self); + if (!ret) { + is_self = krb5_principal_compare(context, entry->princ, self->princ); + krb5_db_free_principal(context, self); + } + + return is_self; +} + +/* + * If S4U2Self padata is present in request, verify the checksum and set + * *s4u_x509_user to the S4U2Self request. If the requested client realm is + * local, look up the client and set *princ_ptr to its DB entry. + */ +krb5_error_code +kdc_process_s4u2self_req(krb5_context context, krb5_kdc_req *request, + const krb5_db_entry *server, + krb5_keyblock *tgs_subkey, krb5_keyblock *tgs_session, + krb5_pa_s4u_x509_user **s4u_x509_user, + krb5_db_entry **princ_ptr, const char **status) +{ + krb5_error_code code; + krb5_pa_data *pa_data; + krb5_db_entry *princ; + krb5_s4u_userid *id; + + *princ_ptr = NULL; + + pa_data = krb5int_find_pa_data(context, request->padata, + KRB5_PADATA_S4U_X509_USER); + if (pa_data != NULL) { + code = kdc_process_s4u_x509_user(context, request, pa_data, tgs_subkey, + tgs_session, s4u_x509_user, status); + if (code != 0) + return code; + } else { + pa_data = krb5int_find_pa_data(context, request->padata, + KRB5_PADATA_FOR_USER); + if (pa_data != NULL) { + code = kdc_process_for_user(context, pa_data, tgs_session, + s4u_x509_user, status); + if (code != 0) + return code; + } else + return 0; + } + id = &(*s4u_x509_user)->user_id; + + if (data_eq(server->princ->realm, id->user->realm)) { + if (id->subject_cert.length != 0) { + code = krb5_db_get_s4u_x509_principal(context, + &id->subject_cert, id->user, + KRB5_KDB_FLAG_CLIENT, + &princ); + if (code == 0 && id->user->length == 0) { + krb5_free_principal(context, id->user); + code = krb5_copy_principal(context, princ->princ, &id->user); + } + } else { + code = krb5_db_get_principal(context, id->user, + KRB5_KDB_FLAG_CLIENT, &princ); + } + if (code == KRB5_KDB_NOENTRY) { + *status = "UNKNOWN_S4U2SELF_PRINCIPAL"; + return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + } else if (code) { + *status = "LOOKING_UP_S4U2SELF_PRINCIPAL"; + return code; /* caller can free for_user */ + } + + /* Ignore password expiration and needchange attributes (as Windows + * does), since S4U2Self is not password authentication. */ + princ->pw_expiration = 0; + clear(princ->attributes, KRB5_KDB_REQUIRES_PWCHANGE); + + *princ_ptr = princ; + } + + return 0; +} + +/* Clear the forwardable flag in tkt if server cannot obtain forwardable + * S4U2Self tickets according to [MS-SFU] 3.2.5.1.2. */ +krb5_error_code +s4u2self_forwardable(krb5_context context, krb5_db_entry *server, + krb5_flags *tktflags) +{ + krb5_error_code ret; + + /* Allow the forwardable flag if server has ok-to-auth-as-delegate set. */ + if (server->attributes & KRB5_KDB_OK_TO_AUTH_AS_DELEGATE) + return 0; + + /* Deny the forwardable flag if server has any authorized delegation + * targets for traditional S4U2Proxy. */ + ret = krb5_db_check_allowed_to_delegate(context, NULL, server, NULL); + if (!ret) + *tktflags &= ~TKT_FLG_FORWARDABLE; + + if (ret == KRB5KDC_ERR_BADOPTION || ret == KRB5_PLUGIN_OP_NOTSUPP) + return 0; + return ret; +} + +krb5_error_code +kdc_check_transited_list(krb5_context context, const krb5_data *trans, + const krb5_data *realm1, const krb5_data *realm2) +{ + krb5_error_code code; + + /* Check against the KDB module. Treat this answer as authoritative if the + * method is supported and doesn't explicitly pass control. */ + code = krb5_db_check_transited_realms(context, trans, realm1, realm2); + if (code != KRB5_PLUGIN_OP_NOTSUPP && code != KRB5_PLUGIN_NO_HANDLE) + return code; + + /* Check using krb5.conf [capaths] or hierarchical relationships. */ + return krb5_check_transited_list(context, trans, realm1, realm2); +} + +krb5_boolean +enctype_requires_etype_info_2(krb5_enctype enctype) +{ + switch(enctype) { + case ENCTYPE_DES3_CBC_SHA1: + case ENCTYPE_DES3_CBC_RAW: + case ENCTYPE_ARCFOUR_HMAC: + case ENCTYPE_ARCFOUR_HMAC_EXP : + return 0; + default: + return krb5_c_valid_enctype(enctype); + } +} + +void +kdc_get_ticket_endtime(kdc_realm_t *realm, krb5_timestamp starttime, + krb5_timestamp endtime, krb5_timestamp till, + krb5_db_entry *client, krb5_db_entry *server, + krb5_timestamp *out_endtime) +{ + krb5_timestamp until; + krb5_deltat life; + + if (till == 0) + till = kdc_infinity; + + until = ts_min(till, endtime); + + /* Determine the requested lifetime, capped at the maximum valid time + * interval. */ + life = ts_delta(until, starttime); + if (ts_after(until, starttime) && life < 0) + life = INT32_MAX; + + if (client != NULL && client->max_life != 0) + life = min(life, client->max_life); + if (server->max_life != 0) + life = min(life, server->max_life); + if (realm->realm_maxlife != 0) + life = min(life, realm->realm_maxlife); + + *out_endtime = ts_incr(starttime, life); +} + +/* + * Set times->renew_till to the requested renewable lifetime as modified by + * policy. Set the TKT_FLG_RENEWABLE bit in *tktflags if we set a nonzero + * renew_till. *times must be filled in except for renew_till. client and tgt + * may be NULL. + */ +void +kdc_get_ticket_renewtime(kdc_realm_t *realm, krb5_kdc_req *request, + krb5_enc_tkt_part *tgt, krb5_db_entry *client, + krb5_db_entry *server, krb5_flags *tktflags, + krb5_ticket_times *times) +{ + krb5_timestamp rtime, max_rlife; + + *tktflags &= ~TKT_FLG_RENEWABLE; + times->renew_till = 0; + + /* Don't issue renewable tickets if the client or server don't allow it, + * or if this is a TGS request and the TGT isn't renewable. */ + if (server->attributes & KRB5_KDB_DISALLOW_RENEWABLE) + return; + if (client != NULL && (client->attributes & KRB5_KDB_DISALLOW_RENEWABLE)) + return; + if (tgt != NULL && !(tgt->flags & TKT_FLG_RENEWABLE)) + return; + + /* Determine the requested renewable time. */ + if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE)) + rtime = request->rtime ? request->rtime : kdc_infinity; + else if (isflagset(request->kdc_options, KDC_OPT_RENEWABLE_OK) && + ts_after(request->till, times->endtime)) + rtime = request->till; + else + return; + + /* Truncate it to the allowable renewable time. */ + if (tgt != NULL) + rtime = ts_min(rtime, tgt->times.renew_till); + max_rlife = min(server->max_renewable_life, realm->realm_maxrlife); + if (client != NULL) + max_rlife = min(max_rlife, client->max_renewable_life); + rtime = ts_min(rtime, ts_incr(times->starttime, max_rlife)); + + /* If the client only specified renewable-ok, don't issue a renewable + * ticket unless the truncated renew time exceeds the ticket end time. */ + if (!isflagset(request->kdc_options, KDC_OPT_RENEWABLE) && + !ts_after(rtime, times->endtime)) + return; + + *tktflags |= TKT_FLG_RENEWABLE; + times->renew_till = rtime; +} + +/** + * Handle protected negotiation of FAST using enc_padata + * - If ENCPADATA_REQ_ENC_PA_REP is present, then: + * - Return ENCPADATA_REQ_ENC_PA_REP with checksum of AS-REQ from client + * - Include PADATA_FX_FAST in the enc_padata to indicate FAST + * @pre @c out_enc_padata has space for at least two more padata + * @param index in/out index into @c out_enc_padata for next item + */ +krb5_error_code +kdc_handle_protected_negotiation(krb5_context context, + krb5_data *req_pkt, krb5_kdc_req *request, + const krb5_keyblock *reply_key, + krb5_pa_data ***out_enc_padata) +{ + krb5_error_code retval = 0; + krb5_checksum checksum; + krb5_data *der_cksum = NULL; + krb5_pa_data *pa_in; + + memset(&checksum, 0, sizeof(checksum)); + + pa_in = krb5int_find_pa_data(context, request->padata, + KRB5_ENCPADATA_REQ_ENC_PA_REP); + if (pa_in == NULL) + return 0; + + /* Compute and encode a checksum over the AS-REQ. */ + retval = krb5_c_make_checksum(context, 0, reply_key, KRB5_KEYUSAGE_AS_REQ, + req_pkt, &checksum); + if (retval != 0) + goto cleanup; + retval = encode_krb5_checksum(&checksum, &der_cksum); + if (retval != 0) + goto cleanup; + + retval = k5_add_pa_data_from_data(out_enc_padata, + KRB5_ENCPADATA_REQ_ENC_PA_REP, + der_cksum); + if (retval) + goto cleanup; + + /* Add a zero-length PA-FX-FAST element to the list. */ + retval = k5_add_empty_pa_data(out_enc_padata, KRB5_PADATA_FX_FAST); + +cleanup: + krb5_free_checksum_contents(context, &checksum); + krb5_free_data(context, der_cksum); + return retval; +} + +krb5_error_code +kdc_get_pa_pac_options(krb5_context context, krb5_pa_data **in_padata, + krb5_pa_pac_options **pac_options_out) +{ + krb5_pa_data *pa; + krb5_data der_pac_options; + + *pac_options_out = NULL; + + pa = krb5int_find_pa_data(context, in_padata, KRB5_PADATA_PAC_OPTIONS); + if (pa == NULL) + return 0; + + der_pac_options = make_data(pa->contents, pa->length); + return decode_krb5_pa_pac_options(&der_pac_options, pac_options_out); +} + +krb5_error_code +kdc_add_pa_pac_options(krb5_context context, krb5_kdc_req *request, + krb5_pa_data ***out_enc_padata) +{ + krb5_error_code ret; + krb5_pa_pac_options *pac_options = NULL; + krb5_data *der_pac_options; + + ret = kdc_get_pa_pac_options(context, request->padata, &pac_options); + if (ret || pac_options == NULL) + return ret; + + /* Only return supported PAC options (currently only resource-based + * constrained delegation support). */ + pac_options->options &= KRB5_PA_PAC_OPTIONS_RBCD; + if (pac_options->options == 0) { + free(pac_options); + return 0; + } + + ret = encode_krb5_pa_pac_options(pac_options, &der_pac_options); + free(pac_options); + if (ret) + return ret; + + ret = k5_add_pa_data_from_data(out_enc_padata, KRB5_PADATA_PAC_OPTIONS, + der_pac_options); + krb5_free_data(context, der_pac_options); + return ret; +} + +krb5_error_code +kdc_get_pa_pac_rbcd(krb5_context context, krb5_pa_data **in_padata, + krb5_boolean *supported) +{ + krb5_error_code retval; + krb5_pa_pac_options *pac_options = NULL; + + *supported = FALSE; + + retval = kdc_get_pa_pac_options(context, in_padata, &pac_options); + if (retval || !pac_options) + return retval; + + if (pac_options->options & KRB5_PA_PAC_OPTIONS_RBCD) + *supported = TRUE; + + free(pac_options); + return 0; +} + +/* + * Although the KDC doesn't call this function directly, + * process_tcp_connection_read() in net-server.c does call it. + */ +krb5_error_code +make_toolong_error (void *handle, krb5_data **out) +{ + krb5_error errpkt; + krb5_error_code retval; + krb5_data *scratch; + struct server_handle *h = handle; + + retval = krb5_us_timeofday(h->kdc_err_context, + &errpkt.stime, &errpkt.susec); + if (retval) + return retval; + errpkt.error = KRB_ERR_FIELD_TOOLONG; + errpkt.server = h->kdc_realmlist[0]->realm_tgsprinc; + errpkt.client = NULL; + errpkt.cusec = 0; + errpkt.ctime = 0; + errpkt.text.length = 0; + errpkt.text.data = 0; + errpkt.e_data.length = 0; + errpkt.e_data.data = 0; + scratch = malloc(sizeof(*scratch)); + if (scratch == NULL) + return ENOMEM; + retval = krb5_mk_error(h->kdc_err_context, &errpkt, scratch); + if (retval) { + free(scratch); + return retval; + } + + *out = scratch; + return 0; +} + +void reset_for_hangup(void *ctx) +{ + int k; + struct server_handle *h = ctx; + + for (k = 0; k < h->kdc_numrealms; k++) + krb5_db_refresh_config(h->kdc_realmlist[k]->realm_context); +} diff --git a/krb5-1.21.3/src/kdc/kdc_util.h b/krb5-1.21.3/src/kdc/kdc_util.h new file mode 100644 index 00000000..58b2f74d --- /dev/null +++ b/krb5-1.21.3/src/kdc/kdc_util.h @@ -0,0 +1,562 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/kdc_util.h */ +/* + * Portions Copyright (C) 2007 Apple Inc. + * Copyright 1990, 2007, 2014 by the Massachusetts Institute of Technology. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * Declarations for policy.c + */ + +#ifndef __KRB5_KDC_UTIL__ +#define __KRB5_KDC_UTIL__ + +#include +#include "kdb.h" +#include "net-server.h" +#include "realm_data.h" +#include "reqstate.h" + +krb5_boolean krb5_is_tgs_principal (krb5_const_principal); +krb5_boolean is_cross_tgs_principal(krb5_const_principal); +krb5_boolean is_local_tgs_principal(krb5_const_principal); +krb5_error_code +add_to_transited (krb5_data *, + krb5_data *, + krb5_principal, + krb5_principal, + krb5_principal); +krb5_error_code +compress_transited (krb5_data *, + krb5_principal, + krb5_data *); +krb5_error_code +fetch_last_req_info (krb5_db_entry *, krb5_last_req_entry ***); + +krb5_error_code +kdc_convert_key (krb5_keyblock *, krb5_keyblock *, int); +krb5_error_code +kdc_process_tgs_req (kdc_realm_t *, krb5_kdc_req *, + const krb5_fulladdr *, + krb5_data *, + krb5_ticket **, + krb5_db_entry **krbtgt_ptr, + krb5_keyblock **, krb5_keyblock **, + krb5_pa_data **pa_tgs_req); + +krb5_error_code +kdc_get_server_key (krb5_context, krb5_ticket *, unsigned int, + krb5_boolean match_enctype, + krb5_db_entry **, krb5_keyblock **, krb5_kvno *); + +krb5_error_code +get_first_current_key(krb5_context context, krb5_db_entry *entry, + krb5_keyblock *key_out); + +krb5_error_code +get_local_tgt(krb5_context context, const krb5_data *realm, + krb5_db_entry *candidate, krb5_db_entry **alias_out, + krb5_db_entry **storage_out, krb5_keyblock *kb_out); + +krb5_error_code +validate_as_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry *, + krb5_db_entry *, krb5_timestamp, + const char **, krb5_pa_data ***); + +krb5_error_code +check_tgs_constraints(kdc_realm_t *realm, krb5_kdc_req *request, + krb5_db_entry *server, krb5_ticket *ticket, krb5_pac pac, + const krb5_ticket *stkt, krb5_pac stkt_pac, + krb5_db_entry *stkt_server, krb5_timestamp kdc_time, + krb5_pa_s4u_x509_user *s4u_x509_user, + krb5_db_entry *s4u2self_client, + krb5_boolean is_crossrealm, krb5_boolean is_referral, + const char **status, krb5_pa_data ***e_data); + +krb5_error_code +check_tgs_policy(kdc_realm_t *realm, krb5_kdc_req *request, + krb5_db_entry *server, krb5_ticket *ticket, + krb5_pac pac, const krb5_ticket *stkt, krb5_pac stkt_pac, + krb5_principal stkt_pac_client, krb5_db_entry *stkt_server, + krb5_timestamp kdc_time, krb5_boolean is_crossrealm, + krb5_boolean is_referral, const char **status, + krb5_pa_data ***e_data); + +krb5_flags +get_ticket_flags(krb5_flags reqflags, krb5_db_entry *client, + krb5_db_entry *server, krb5_enc_tkt_part *header_enc); + +krb5_error_code +check_indicators(krb5_context context, krb5_db_entry *server, + krb5_data *const *indicators); + +int +fetch_asn1_field (unsigned char *, unsigned int, unsigned int, krb5_data *); + +krb5_enctype +select_session_keytype (krb5_context context, krb5_db_entry *server, + int nktypes, krb5_enctype *ktypes); + +void limit_string (char *name); + +char *ktypes2str(krb5_enctype *ktype, int nktypes); + +char *rep_etypes2str(krb5_kdc_rep *rep); + +/* authind.c */ +krb5_boolean +authind_contains(krb5_data *const *indicators, const char *ind); + +krb5_error_code +authind_add(krb5_context context, const char *ind, krb5_data ***indicators); + +krb5_error_code +authind_extract(krb5_context context, krb5_authdata **authdata, + krb5_data ***indicators); + +/* cammac.c */ +krb5_error_code +cammac_create(krb5_context context, krb5_enc_tkt_part *enc_tkt_reply, + krb5_keyblock *server_key, krb5_db_entry *tgt, + krb5_keyblock *tgt_key, krb5_authdata **contents, + krb5_authdata ***cammac_out); + +krb5_boolean +cammac_check_kdcver(krb5_context context, krb5_cammac *cammac, + krb5_enc_tkt_part *enc_tkt, krb5_db_entry *tgt, + krb5_keyblock *tgt_key); + +/* do_as_req.c */ +void +process_as_req (krb5_kdc_req *, krb5_data *, + const krb5_fulladdr *, const krb5_fulladdr *, kdc_realm_t *, + verto_ctx *, loop_respond_fn, void *); + +/* do_tgs_req.c */ +krb5_error_code +process_tgs_req (krb5_kdc_req *, krb5_data *, const krb5_fulladdr *, + kdc_realm_t *, krb5_data ** ); +/* dispatch.c */ +void +dispatch (void *, + const krb5_fulladdr *, + const krb5_fulladdr *, + krb5_data *, + int, + verto_ctx *, + loop_respond_fn, + void *); + +void +kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 4))) +#endif + ; + +/* kdc_preauth.c */ +krb5_boolean +enctype_requires_etype_info_2(krb5_enctype enctype); + +const char * +missing_required_preauth (krb5_db_entry *client, + krb5_db_entry *server, + krb5_enc_tkt_part *enc_tkt_reply); +typedef void (*kdc_hint_respond_fn)(void *arg); +void +get_preauth_hint_list(krb5_kdc_req *request, + krb5_kdcpreauth_rock rock, krb5_pa_data ***e_data_out, + kdc_hint_respond_fn respond, void *arg); +void +load_preauth_plugins(struct server_handle * handle, krb5_context context, + verto_ctx *ctx); +void +unload_preauth_plugins(krb5_context context); + +typedef void (*kdc_preauth_respond_fn)(void *arg, krb5_error_code code); + +void +check_padata(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_data *req_pkt, krb5_kdc_req *request, + krb5_enc_tkt_part *enc_tkt_reply, void **padata_context, + krb5_pa_data ***e_data, krb5_boolean *typed_e_data, + kdc_preauth_respond_fn respond, void *state); + +krb5_error_code +return_padata(krb5_context context, krb5_kdcpreauth_rock rock, + krb5_data *req_pkt, krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_keyblock *encrypting_key, void **padata_context); + +void +free_padata_context(krb5_context context, void *padata_context); + +/* kdc_preauth_ec.c */ +krb5_error_code +kdcpreauth_encrypted_challenge_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); + +/* kdc_preauth_enctsc.c */ +krb5_error_code +kdcpreauth_encrypted_timestamp_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); + +/* kdc_authdata.c */ +krb5_error_code +load_authdata_plugins(krb5_context context); +krb5_error_code +unload_authdata_plugins(krb5_context context); + +krb5_error_code +get_auth_indicators(krb5_context context, krb5_enc_tkt_part *enc_tkt, + krb5_db_entry *local_tgt, krb5_keyblock *local_tgt_key, + krb5_data ***indicators_out); + +krb5_error_code +handle_authdata(kdc_realm_t *realm, unsigned int flags, krb5_db_entry *client, + krb5_db_entry *server, krb5_db_entry *subject_server, + krb5_db_entry *local_tgt, krb5_keyblock *local_tgt_key, + krb5_keyblock *client_key, krb5_keyblock *server_key, + krb5_keyblock *header_key, krb5_keyblock *replaced_reply_key, + krb5_data *req_pkt, krb5_kdc_req *request, + krb5_const_principal altcprinc, krb5_pac subject_pac, + krb5_enc_tkt_part *enc_tkt_request, + krb5_data ***auth_indicators, + krb5_enc_tkt_part *enc_tkt_reply); + +/* replay.c */ +krb5_error_code kdc_init_lookaside(krb5_context context); +krb5_boolean kdc_check_lookaside (krb5_context, krb5_data *, krb5_data **); +void kdc_insert_lookaside (krb5_context, krb5_data *, krb5_data *); +void kdc_remove_lookaside (krb5_context kcontext, krb5_data *); +void kdc_free_lookaside(krb5_context); + +/* kdc_util.c */ +void reset_for_hangup(void *); + +krb5_error_code +pac_privsvr_key(krb5_context context, krb5_db_entry *server, + const krb5_keyblock *tgt_key, krb5_keyblock **key_out); + +krb5_error_code +get_verified_pac(krb5_context context, const krb5_enc_tkt_part *enc_tkt, + krb5_db_entry *server, krb5_keyblock *server_key, + krb5_db_entry *tgt, krb5_keyblock *tgt_key, + krb5_pac *pac_out); + +krb5_error_code +get_pac_princ_with_realm(krb5_context context, krb5_pac pac, + krb5_principal *princ_out, + krb5_timestamp *authtime_out); + +krb5_boolean +include_pac_p(krb5_context context, krb5_kdc_req *request); + +krb5_error_code +return_enc_padata(krb5_context context, + krb5_data *req_pkt, krb5_kdc_req *request, + krb5_keyblock *reply_key, + krb5_db_entry *server, + krb5_enc_kdc_rep_part *reply_encpart, + krb5_boolean is_referral); + +krb5_error_code +kdc_process_s4u2self_req(krb5_context context, krb5_kdc_req *request, + const krb5_db_entry *server, + krb5_keyblock *tgs_subkey, krb5_keyblock *tgs_session, + krb5_pa_s4u_x509_user **s4u2self_req, + krb5_db_entry **princ_ptr, const char **status); + +krb5_error_code +s4u2self_forwardable(krb5_context context, krb5_db_entry *server, + krb5_flags *tktflags); + +krb5_error_code +kdc_make_s4u2self_rep (krb5_context context, + krb5_keyblock *tgs_subkey, + krb5_keyblock *tgs_session, + krb5_pa_s4u_x509_user *req_s4u_user, + krb5_kdc_rep *reply, + krb5_enc_kdc_rep_part *reply_encpart); + +krb5_error_code +kdc_check_transited_list(krb5_context context, const krb5_data *trans, + const krb5_data *realm1, const krb5_data *realm2); + +void +kdc_get_ticket_endtime(kdc_realm_t *realm, krb5_timestamp now, + krb5_timestamp endtime, krb5_timestamp till, + krb5_db_entry *client, krb5_db_entry *server, + krb5_timestamp *out_endtime); + +void +kdc_get_ticket_renewtime(kdc_realm_t *realm, krb5_kdc_req *request, + krb5_enc_tkt_part *tgt, krb5_db_entry *client, + krb5_db_entry *server, krb5_flags *tktflags, + krb5_ticket_times *times); + +void +log_as_req(krb5_context context, + const krb5_fulladdr *local_addr, + const krb5_fulladdr *remote_addr, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_db_entry *client, const char *cname, + krb5_db_entry *server, const char *sname, + krb5_timestamp authtime, + const char *status, krb5_error_code errcode, const char *emsg); +void +log_tgs_req(krb5_context ctx, const krb5_fulladdr *from, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_principal cprinc, krb5_principal sprinc, + krb5_principal altcprinc, + krb5_timestamp authtime, + unsigned int c_flags, + const char *status, krb5_error_code errcode, const char *emsg); +void +log_tgs_badtrans(krb5_context ctx, krb5_principal cprinc, + krb5_principal sprinc, krb5_data *trcont, + krb5_error_code errcode); + +void +log_tgs_alt_tgt(krb5_context context, krb5_principal p); + +krb5_boolean +is_client_db_alias(krb5_context context, const krb5_db_entry *entry, + krb5_const_principal princ); + +/* FAST*/ +enum krb5_fast_kdc_flags { + KRB5_FAST_REPLY_KEY_USED = 0x1, + KRB5_FAST_REPLY_KEY_REPLACED = 0x02 +}; + +/* + * If *requestptr contains FX_FAST padata, compute the armor key, verify the + * checksum over checksummed_data, decode the FAST request, and substitute + * *requestptr with the inner request. Set the armor_key, cookie, and + * fast_options fields in state. state->cookie will be set for a non-FAST + * request if it contains FX_COOKIE padata. If inner_body_out is non-NULL, set + * *inner_body_out to a copy of the encoded inner body, or to NULL if the + * request is not a FAST request. + */ +krb5_error_code +kdc_find_fast (krb5_kdc_req **requestptr, krb5_data *checksummed_data, + krb5_keyblock *tgs_subkey, krb5_keyblock *tgs_session, + struct kdc_request_state *state, krb5_data **inner_body_out); + +krb5_error_code +kdc_fast_response_handle_padata (struct kdc_request_state *state, + krb5_kdc_req *request, + krb5_kdc_rep *rep, + krb5_enctype enctype); +krb5_error_code +kdc_fast_handle_error (krb5_context context, + struct kdc_request_state *state, + krb5_kdc_req *request, + krb5_pa_data **in_padata, krb5_error *err, + krb5_data **fast_edata_out); + +krb5_error_code kdc_fast_handle_reply_key(struct kdc_request_state *state, + krb5_keyblock *existing_key, + krb5_keyblock **out_key); + + +krb5_boolean +kdc_fast_hide_client(struct kdc_request_state *state); + +krb5_error_code +kdc_handle_protected_negotiation( krb5_context context, + krb5_data *req_pkt, krb5_kdc_req *request, + const krb5_keyblock *reply_key, + krb5_pa_data ***out_enc_padata); + +krb5_error_code +kdc_fast_read_cookie(krb5_context context, struct kdc_request_state *state, + krb5_kdc_req *req, krb5_db_entry *local_tgt, + krb5_keyblock *local_tgt_key); + +krb5_boolean kdc_fast_search_cookie(struct kdc_request_state *state, + krb5_preauthtype pa_type, krb5_data *out); + +krb5_error_code kdc_fast_set_cookie(struct kdc_request_state *state, + krb5_preauthtype pa_type, + const krb5_data *data); + +krb5_error_code +kdc_fast_make_cookie(krb5_context context, struct kdc_request_state *state, + krb5_db_entry *local_tgt, krb5_keyblock *local_tgt_key, + krb5_const_principal client_princ, + krb5_pa_data **cookie_out); + +krb5_error_code +kdc_add_pa_pac_options(krb5_context context, krb5_kdc_req *request, + krb5_pa_data ***out_enc_padata); + +krb5_error_code +kdc_get_pa_pac_options(krb5_context context, krb5_pa_data **in_padata, + krb5_pa_pac_options **pac_options_out); + +krb5_error_code +kdc_get_pa_pac_rbcd(krb5_context context, krb5_pa_data **in_padata, + krb5_boolean *supported); + +/* Information handle for kdcpreauth callbacks. All pointers are aliases. */ +struct krb5_kdcpreauth_rock_st { + krb5_kdc_req *request; + krb5_data *inner_body; + krb5_db_entry *client; + krb5_db_entry *local_tgt; + krb5_keyblock *local_tgt_key; + krb5_key_data *client_key; + krb5_keyblock *client_keyblock; + struct kdc_request_state *rstate; + verto_ctx *vctx; + krb5_data ***auth_indicators; + krb5_boolean send_freshness_token; + krb5_boolean replaced_reply_key; +}; + +#define isflagset(flagfield, flag) (flagfield & (flag)) +#define setflag(flagfield, flag) (flagfield |= (flag)) +#define clear(flagfield, flag) (flagfield &= ~(flag)) + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#define ts_min(a, b) (ts_after(a, b) ? (b) : (a)) + +#define ADDRTYPE2FAMILY(X) \ + ((X) == ADDRTYPE_INET6 ? AF_INET6 : (X) == ADDRTYPE_INET ? AF_INET : -1) + +/* RFC 4120: KRB5KDC_ERR_KEY_TOO_WEAK + * RFC 4556: KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED */ +#define KRB5KDC_ERR_KEY_TOO_WEAK KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED +/* TGS-REQ options where the service can be a non-TGS principal */ + +#define NON_TGT_OPTION (KDC_OPT_FORWARDED | KDC_OPT_PROXY | KDC_OPT_RENEW | \ + KDC_OPT_VALIDATE) + +/* TGS-REQ options which are not compatible with referrals */ +#define NO_REFERRAL_OPTION (NON_TGT_OPTION | KDC_OPT_ENC_TKT_IN_SKEY) + +/* Options incompatible with AS and S4U2Self requests */ +#define AS_INVALID_OPTIONS (NO_REFERRAL_OPTION | KDC_OPT_CNAME_IN_ADDL_TKT) + +/* + * Mask of KDC options that request the corresponding ticket flag with + * the same number. Some of these are invalid for AS-REQs, but + * validate_as_request() takes care of that. KDC_OPT_RENEWABLE isn't + * here because it needs special handling in + * kdc_get_ticket_renewtime(). + * + * According to RFC 4120 section 3.1.3 the following AS-REQ options + * request their corresponding ticket flags if local policy allows: + * + * KDC_OPT_FORWARDABLE KDC_OPT_ALLOW_POSTDATE + * KDC_OPT_POSTDATED KDC_OPT_PROXIABLE + * KDC_OPT_RENEWABLE + * + * RFC 1510 section A.6 shows pseudocode indicating that the following + * TGS-REQ options request their corresponding ticket flags if local + * policy allows: + * + * KDC_OPT_FORWARDABLE KDC_OPT_FORWARDED + * KDC_OPT_PROXIABLE KDC_OPT_PROXY + * KDC_OPT_POSTDATED KDC_OPT_RENEWABLE + * + * The above list omits KDC_OPT_ALLOW_POSTDATE, but RFC 4120 section + * 5.4.1 says the TGS also handles it. + * + * RFC 6112 makes KDC_OPT_REQUEST_ANONYMOUS the same bit number as + * TKT_FLG_ANONYMOUS. + */ +#define OPTS_COMMON_FLAGS_MASK \ + (KDC_OPT_FORWARDABLE | KDC_OPT_FORWARDED | \ + KDC_OPT_PROXIABLE | KDC_OPT_PROXY | \ + KDC_OPT_ALLOW_POSTDATE | KDC_OPT_POSTDATED | \ + KDC_OPT_REQUEST_ANONYMOUS) + +/* Copy KDC options that request the corresponding ticket flags. */ +#define OPTS2FLAGS(x) (x & OPTS_COMMON_FLAGS_MASK) + +/* + * Mask of ticket flags for the TGS to propagate from a ticket to a + * derivative ticket. + * + * RFC 4120 section 2.1 says the following flags are carried forward + * from an initial ticket to derivative tickets: + * + * TKT_FLG_PRE_AUTH + * TKT_FLG_HW_AUTH + * + * RFC 4120 section 2.6 says TKT_FLG_FORWARDED is carried forward to + * derivative tickets. Proxy tickets are basically identical to + * forwarded tickets except that a TGT may never be proxied, therefore + * tickets derived from proxy tickets should have TKT_FLAG_PROXY set. + * RFC 4120 and RFC 1510 apparently have an accidental omission in not + * requiring that tickets derived from a proxy ticket have + * TKT_FLG_PROXY set. Previous code also omitted this behavior. + * + * RFC 6112 section 4.2 implies that TKT_FLG_ANONYMOUS must be + * propagated from an anonymous ticket to derivative tickets. + */ +#define TGS_COPIED_FLAGS_MASK \ + (TKT_FLG_FORWARDED | TKT_FLG_PROXY | \ + TKT_FLG_PRE_AUTH | TKT_FLG_HW_AUTH | \ + TKT_FLG_ANONYMOUS) + +/* Copy appropriate header ticket flags to new ticket. */ +#define COPY_TKT_FLAGS(x) (x & TGS_COPIED_FLAGS_MASK) + +int check_anon(kdc_realm_t *realm, krb5_principal client, + krb5_principal server); +int errcode_to_protocol(krb5_error_code code); + +char *data2string(krb5_data *d); + +/* Return the current key version of entry, or 0 if it has no keys. */ +static inline krb5_kvno +current_kvno(krb5_db_entry *entry) +{ + return (entry->n_key_data == 0) ? 0 : entry->key_data[0].key_data_kvno; +} + +/* MS-PAC section 2.9 */ +struct pac_s4u_delegation_info { + char *proxy_target; + uint32_t transited_services_length; + char **transited_services; +}; + +/* Leaves room for one additional service. */ +krb5_error_code +ndr_dec_delegation_info(krb5_data *data, + struct pac_s4u_delegation_info **res); + +krb5_error_code +ndr_enc_delegation_info(struct pac_s4u_delegation_info *in, + krb5_data *out); + +void ndr_free_delegation_info(struct pac_s4u_delegation_info *in); + +#endif /* __KRB5_KDC_UTIL__ */ diff --git a/krb5-1.21.3/src/kdc/main.c b/krb5-1.21.3/src/kdc/main.c new file mode 100644 index 00000000..bfdfef5c --- /dev/null +++ b/krb5-1.21.3/src/kdc/main.c @@ -0,0 +1,1056 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/main.c - Main procedure body for the KDC server process */ +/* + * Copyright 1990,2001,2008,2009,2016 by the Massachusetts Institute of + * Technology. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "com_err.h" +#include +#include "adm_proto.h" +#include "kdc_util.h" +#include "kdc_audit.h" +#include "extern.h" +#include "policy.h" +#include "kdc5_err.h" +#include "kdb_kt.h" +#include "net-server.h" +#ifdef HAVE_NETINET_IN_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#if defined(NEED_DAEMON_PROTO) +extern int daemon(int, int); +#endif + +static void usage (char *); + +static void initialize_realms(krb5_context kcontext, int argc, char **argv, + int *tcp_listen_backlog_out); + +static void finish_realms (void); + +static int nofork = 0; +static int workers = 0; +static int time_offset = 0; +static const char *pid_file = NULL; +static volatile int signal_received = 0; +static volatile int sighup_received = 0; + +#define KRB5_KDC_MAX_REALMS 32 + +static const char *kdc_progname; + +/* + * Static server_handle for this file. Other code will get access to + * it through the application handle that net-server.c uses. + */ +static struct server_handle shandle; + +/* + * We use krb5_klog_init to set up a com_err callback to log error + * messages. The callback also pulls the error message out of the + * context we pass to krb5_klog_init; however, we use realm-specific + * contexts for most of our krb5 library calls, so the error message + * isn't present in the global context. This wrapper ensures that the + * error message state from the call context is copied into the + * context known by krb5_klog. call_context can be NULL if the error + * code did not come from a krb5 library function. + */ +void +kdc_err(krb5_context call_context, errcode_t code, const char *fmt, ...) +{ + va_list ap; + + if (call_context) + krb5_copy_error_message(shandle.kdc_err_context, call_context); + va_start(ap, fmt); + com_err_va(kdc_progname, code, fmt, ap); + va_end(ap); +} + +/* + * Find the realm entry for a given realm. + */ +kdc_realm_t * +find_realm_data(struct server_handle *handle, char *rname, krb5_ui_4 rsize) +{ + int i; + kdc_realm_t **kdc_realmlist = handle->kdc_realmlist; + int kdc_numrealms = handle->kdc_numrealms; + + for (i=0; irealm_name)) && + !strncmp(rname, kdc_realmlist[i]->realm_name, rsize)) + return(kdc_realmlist[i]); + } + return((kdc_realm_t *) NULL); +} + +kdc_realm_t * +setup_server_realm(struct server_handle *handle, krb5_principal sprinc) +{ + kdc_realm_t *newrealm; + kdc_realm_t **kdc_realmlist = handle->kdc_realmlist; + int kdc_numrealms = handle->kdc_numrealms; + + if (sprinc == NULL) + return NULL; + + if (kdc_numrealms > 1) { + newrealm = find_realm_data(handle, sprinc->realm.data, + sprinc->realm.length); + } else { + newrealm = kdc_realmlist[0]; + } + if (newrealm != NULL) { + krb5_klog_set_context(newrealm->realm_context); + shandle.kdc_err_context = newrealm->realm_context; + } + return newrealm; +} + +static void +finish_realm(kdc_realm_t *rdp) +{ + if (rdp->realm_name) + free(rdp->realm_name); + if (rdp->realm_mpname) + free(rdp->realm_mpname); + if (rdp->realm_stash) + free(rdp->realm_stash); + if (rdp->realm_listen) + free(rdp->realm_listen); + if (rdp->realm_tcp_listen) + free(rdp->realm_tcp_listen); + if (rdp->realm_keytab) + krb5_kt_close(rdp->realm_context, rdp->realm_keytab); + if (rdp->realm_hostbased) + free(rdp->realm_hostbased); + if (rdp->realm_no_referral) + free(rdp->realm_no_referral); + if (rdp->realm_context) { + if (rdp->realm_mprinc) + krb5_free_principal(rdp->realm_context, rdp->realm_mprinc); + zapfree(rdp->realm_mkey.contents, rdp->realm_mkey.length); + krb5_db_fini(rdp->realm_context); + if (rdp->realm_tgsprinc) + krb5_free_principal(rdp->realm_context, rdp->realm_tgsprinc); + krb5_free_context(rdp->realm_context); + } + zapfree(rdp, sizeof(*rdp)); +} + +/* Set *val_out to an allocated string containing val1 and/or val2, separated + * by a space if both are set, or NULL if neither is set. */ +static krb5_error_code +combine(const char *val1, const char *val2, char **val_out) +{ + if (val1 == NULL && val2 == NULL) { + *val_out = NULL; + } else if (val1 != NULL && val2 != NULL) { + if (asprintf(val_out, "%s %s", val1, val2) < 0) { + *val_out = NULL; + return ENOMEM; + } + } else { + *val_out = strdup((val1 != NULL) ? val1 : val2); + if (*val_out == NULL) + return ENOMEM; + } + return 0; +} + +/* + * Initialize a realm control structure from the alternate profile or from + * the specified defaults. + * + * After we're complete here, the essence of the realm is embodied in the + * realm data and we should be all set to begin operation for that realm. + */ +static krb5_error_code +init_realm(kdc_realm_t * rdp, krb5_pointer aprof, char *realm, + char *def_mpname, krb5_enctype def_enctype, char *def_udp_listen, + char *def_tcp_listen, krb5_boolean def_manual, + krb5_boolean def_restrict_anon, char **db_args, char *no_referral, + char *hostbased) +{ + krb5_error_code kret; + krb5_boolean manual; + int kdb_open_flags; + char *svalue = NULL; + const char *hierarchy[4]; + krb5_kvno mkvno = IGNORE_VNO; + char ename[32]; + + memset(rdp, 0, sizeof(kdc_realm_t)); + if (!realm) { + kret = EINVAL; + goto whoops; + } + + if (def_enctype != ENCTYPE_UNKNOWN && + krb5int_c_deprecated_enctype(def_enctype)) { + if (krb5_enctype_to_name(def_enctype, FALSE, ename, sizeof(ename))) + ename[0] = '\0'; + fprintf(stderr, + _("Requested master password enctype %s in %s is " + "DEPRECATED!\n"), + ename, realm); + } + + hierarchy[0] = KRB5_CONF_REALMS; + hierarchy[1] = realm; + hierarchy[3] = NULL; + + rdp->realm_name = strdup(realm); + if (rdp->realm_name == NULL) { + kret = ENOMEM; + goto whoops; + } + kret = krb5int_init_context_kdc(&rdp->realm_context); + if (kret) { + kdc_err(NULL, kret, _("while getting context for realm %s"), realm); + goto whoops; + } + if (time_offset != 0) + (void)krb5_set_time_offsets(rdp->realm_context, time_offset, 0); + + /* Handle master key name */ + hierarchy[2] = KRB5_CONF_MASTER_KEY_NAME; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &rdp->realm_mpname)) { + rdp->realm_mpname = (def_mpname) ? strdup(def_mpname) : + strdup(KRB5_KDB_M_NAME); + } + if (!rdp->realm_mpname) { + kret = ENOMEM; + goto whoops; + } + + /* Handle KDC addresses/ports */ + hierarchy[2] = KRB5_CONF_KDC_LISTEN; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &rdp->realm_listen)) { + /* Try the old kdc_ports configuration option. */ + hierarchy[2] = KRB5_CONF_KDC_PORTS; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &rdp->realm_listen)) + rdp->realm_listen = strdup(def_udp_listen); + } + if (!rdp->realm_listen) { + kret = ENOMEM; + goto whoops; + } + hierarchy[2] = KRB5_CONF_KDC_TCP_LISTEN; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, + &rdp->realm_tcp_listen)) { + /* Try the old kdc_tcp_ports configuration option. */ + hierarchy[2] = KRB5_CONF_KDC_TCP_PORTS; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, + &rdp->realm_tcp_listen)) + rdp->realm_tcp_listen = strdup(def_tcp_listen); + } + if (!rdp->realm_tcp_listen) { + kret = ENOMEM; + goto whoops; + } + /* Handle stash file */ + hierarchy[2] = KRB5_CONF_KEY_STASH_FILE; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &rdp->realm_stash)) + manual = def_manual; + else + manual = FALSE; + + hierarchy[2] = KRB5_CONF_RESTRICT_ANONYMOUS_TO_TGT; + if (krb5_aprof_get_boolean(aprof, hierarchy, TRUE, + &rdp->realm_restrict_anon)) + rdp->realm_restrict_anon = def_restrict_anon; + + /* Handle master key type */ + hierarchy[2] = KRB5_CONF_MASTER_KEY_TYPE; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &svalue) || + krb5_string_to_enctype(svalue, &rdp->realm_mkey.enctype)) + rdp->realm_mkey.enctype = manual ? def_enctype : ENCTYPE_UNKNOWN; + free(svalue); + svalue = NULL; + + /* Handle reject-bad-transit flag */ + hierarchy[2] = KRB5_CONF_REJECT_BAD_TRANSIT; + if (krb5_aprof_get_boolean(aprof, hierarchy, TRUE, + &rdp->realm_reject_bad_transit)) + rdp->realm_reject_bad_transit = TRUE; + + /* Handle ticket maximum life */ + hierarchy[2] = KRB5_CONF_MAX_LIFE; + if (krb5_aprof_get_deltat(aprof, hierarchy, TRUE, &rdp->realm_maxlife)) + rdp->realm_maxlife = KRB5_KDB_MAX_LIFE; + + /* Handle ticket renewable maximum life */ + hierarchy[2] = KRB5_CONF_MAX_RENEWABLE_LIFE; + if (krb5_aprof_get_deltat(aprof, hierarchy, TRUE, &rdp->realm_maxrlife)) + rdp->realm_maxrlife = KRB5_KDB_MAX_RLIFE; + + /* Handle KDC referrals */ + hierarchy[2] = KRB5_CONF_NO_HOST_REFERRAL; + (void)krb5_aprof_get_string_all(aprof, hierarchy, &svalue); + kret = combine(no_referral, svalue, &rdp->realm_no_referral); + if (kret) + goto whoops; + free(svalue); + svalue = NULL; + + hierarchy[2] = KRB5_CONF_HOST_BASED_SERVICES; + (void)krb5_aprof_get_string_all(aprof, hierarchy, &svalue); + kret = combine(hostbased, svalue, &rdp->realm_hostbased); + if (kret) + goto whoops; + free(svalue); + svalue = NULL; + + hierarchy[2] = KRB5_CONF_DISABLE_PAC; + if (krb5_aprof_get_boolean(aprof, hierarchy, TRUE, + &rdp->realm_disable_pac)) + rdp->realm_disable_pac = FALSE; + + /* + * We've got our parameters, now go and setup our realm context. + */ + + /* Set the default realm of this context */ + if ((kret = krb5_set_default_realm(rdp->realm_context, realm))) { + kdc_err(rdp->realm_context, kret, + _("while setting default realm to %s"), realm); + goto whoops; + } + + /* first open the database before doing anything */ + kdb_open_flags = KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_KDC; + if ((kret = krb5_db_open(rdp->realm_context, db_args, kdb_open_flags))) { + kdc_err(rdp->realm_context, kret, + _("while initializing database for realm %s"), realm); + goto whoops; + } + + /* Assemble and parse the master key name */ + if ((kret = krb5_db_setup_mkey_name(rdp->realm_context, rdp->realm_mpname, + rdp->realm_name, (char **) NULL, + &rdp->realm_mprinc))) { + kdc_err(rdp->realm_context, kret, + _("while setting up master key name %s for realm %s"), + rdp->realm_mpname, realm); + goto whoops; + } + + /* + * Get the master key (note, may not be the most current mkey). + */ + if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc, + rdp->realm_mkey.enctype, manual, + FALSE, rdp->realm_stash, + &mkvno, NULL, &rdp->realm_mkey))) { + kdc_err(rdp->realm_context, kret, + _("while fetching master key %s for realm %s"), + rdp->realm_mpname, realm); + goto whoops; + } + + if (krb5int_c_deprecated_enctype(rdp->realm_mkey.enctype)) { + if (krb5_enctype_to_name(rdp->realm_mkey.enctype, FALSE, ename, + sizeof(ename))) + ename[0] = '\0'; + fprintf(stderr, _("Stash file %s uses DEPRECATED enctype %s!\n"), + rdp->realm_stash, ename); + } + + if ((kret = krb5_db_fetch_mkey_list(rdp->realm_context, rdp->realm_mprinc, + &rdp->realm_mkey))) { + kdc_err(rdp->realm_context, kret, + _("while fetching master keys list for realm %s"), realm); + goto whoops; + } + + + /* Set up the keytab */ + if ((kret = krb5_ktkdb_resolve(rdp->realm_context, NULL, + &rdp->realm_keytab))) { + kdc_err(rdp->realm_context, kret, + _("while resolving kdb keytab for realm %s"), realm); + goto whoops; + } + + /* Preformat the TGS name */ + if ((kret = krb5_build_principal(rdp->realm_context, &rdp->realm_tgsprinc, + strlen(realm), realm, KRB5_TGS_NAME, + realm, (char *) NULL))) { + kdc_err(rdp->realm_context, kret, + _("while building TGS name for realm %s"), realm); + goto whoops; + } + +whoops: + /* + * If we choked, then clean up any dirt we may have dropped on the floor. + */ + if (kret) { + + finish_realm(rdp); + } + return(kret); +} + +static void +on_monitor_signal(int signo) +{ + signal_received = signo; +} + +static void +on_monitor_sighup(int signo) +{ + sighup_received = 1; +} + +/* + * Kill the worker subprocesses given by pids[0..bound-1], skipping any which + * are set to -1, and wait for them to exit (so that we know the ports are no + * longer in use). + */ +static void +terminate_workers(pid_t *pids, int bound) +{ + int i, status, num_active = 0; + pid_t pid; + + /* Kill the active worker pids. */ + for (i = 0; i < bound; i++) { + if (pids[i] == -1) + continue; + kill(pids[i], SIGTERM); + num_active++; + } + + /* Wait for them to exit. */ + while (num_active > 0) { + pid = wait(&status); + if (pid >= 0) + num_active--; + } +} + +/* + * Create num worker processes and return successfully in each child. The + * parent process will act as a supervisor and will only return from this + * function in error cases. + */ +static krb5_error_code +create_workers(verto_ctx *ctx, int num) +{ + krb5_error_code retval; + int i, status; + pid_t pid, *pids; +#ifdef POSIX_SIGNALS + struct sigaction s_action; +#endif /* POSIX_SIGNALS */ + + /* + * Setup our signal handlers which will forward to the children. + * These handlers will be overridden in the child processes. + */ +#ifdef POSIX_SIGNALS + (void) sigemptyset(&s_action.sa_mask); + s_action.sa_flags = 0; + s_action.sa_handler = on_monitor_signal; + (void) sigaction(SIGINT, &s_action, (struct sigaction *) NULL); + (void) sigaction(SIGTERM, &s_action, (struct sigaction *) NULL); + (void) sigaction(SIGQUIT, &s_action, (struct sigaction *) NULL); + s_action.sa_handler = on_monitor_sighup; + (void) sigaction(SIGHUP, &s_action, (struct sigaction *) NULL); +#else /* POSIX_SIGNALS */ + signal(SIGINT, on_monitor_signal); + signal(SIGTERM, on_monitor_signal); + signal(SIGQUIT, on_monitor_signal); + signal(SIGHUP, on_monitor_sighup); +#endif /* POSIX_SIGNALS */ + + /* Create child worker processes; return in each child. */ + krb5_klog_syslog(LOG_INFO, _("creating %d worker processes"), num); + pids = calloc(num, sizeof(pid_t)); + if (pids == NULL) + return ENOMEM; + for (i = 0; i < num; i++) { + pid = fork(); + if (pid == 0) { + free(pids); + if (!verto_reinitialize(ctx)) { + krb5_klog_syslog(LOG_ERR, + _("Unable to reinitialize main loop")); + return ENOMEM; + } + retval = loop_setup_signals(ctx, &shandle, reset_for_hangup); + if (retval) { + krb5_klog_syslog(LOG_ERR, _("Unable to initialize signal " + "handlers in pid %d"), pid); + return retval; + } + + /* Avoid race condition */ + if (signal_received) + exit(0); + + /* Return control to main() in the new worker process. */ + return 0; + } + if (pid == -1) { + /* Couldn't fork enough times. */ + status = errno; + terminate_workers(pids, i); + free(pids); + return status; + } + pids[i] = pid; + } + + /* We're going to use our own main loop here. */ + loop_free(ctx); + + /* Supervise the worker processes. */ + while (!signal_received) { + /* Wait until a worker process exits or we get a signal. */ + pid = wait(&status); + if (pid >= 0) { + krb5_klog_syslog(LOG_ERR, _("worker %ld exited with status %d"), + (long) pid, status); + + /* Remove the pid from the table. */ + for (i = 0; i < num; i++) { + if (pids[i] == pid) + pids[i] = -1; + } + + /* When one worker process exits, terminate them all, so that KDC + * crashes behave similarly with or without worker processes. */ + break; + } + + /* Propagate HUP signal to worker processes if we received one. */ + if (sighup_received) { + sighup_received = 0; + for (i = 0; i < num; i++) { + if (pids[i] != -1) + kill(pids[i], SIGHUP); + } + } + } + if (signal_received) + krb5_klog_syslog(LOG_INFO, _("signal %d received in supervisor"), + signal_received); + + terminate_workers(pids, num); + free(pids); + exit(0); +} + +static void +usage(char *name) +{ + fprintf(stderr, + _("usage: %s [-x db_args]* [-d dbpathname] [-r dbrealmname]\n" + "\t\t[-T time_offset] [-m] [-k masterenctype]\n" + "\t\t[-M masterkeyname] [-p port] [-P pid_file]\n" + "\t\t[-n] [-w numworkers] [/]\n\n" + "where,\n" + "\t[-x db_args]* - Any number of database specific arguments.\n" + "\t\t\tLook at each database module documentation for " + "\t\t\tsupported arguments\n"), + name); + exit(1); +} + + +static void +initialize_realms(krb5_context kcontext, int argc, char **argv, + int *tcp_listen_backlog_out) +{ + int c; + char *db_name = (char *) NULL; + char *lrealm = (char *) NULL; + char *mkey_name = (char *) NULL; + krb5_error_code retval; + krb5_enctype menctype = ENCTYPE_UNKNOWN; + kdc_realm_t *rdatap = NULL; + krb5_boolean manual = FALSE; + krb5_boolean def_restrict_anon; + char *def_udp_listen = NULL; + char *def_tcp_listen = NULL; + krb5_pointer aprof = kcontext->profile; + const char *hierarchy[3]; + char *no_referral = NULL; + char *hostbased = NULL; + int db_args_size = 0; + char **db_args = NULL; + + extern char *optarg; + + hierarchy[0] = KRB5_CONF_KDCDEFAULTS; + hierarchy[1] = KRB5_CONF_KDC_LISTEN; + hierarchy[2] = NULL; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &def_udp_listen)) { + hierarchy[1] = KRB5_CONF_KDC_PORTS; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &def_udp_listen)) + def_udp_listen = NULL; + } + hierarchy[1] = KRB5_CONF_KDC_TCP_LISTEN; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &def_tcp_listen)) { + hierarchy[1] = KRB5_CONF_KDC_TCP_PORTS; + if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &def_tcp_listen)) + def_tcp_listen = NULL; + } + hierarchy[1] = KRB5_CONF_KDC_MAX_DGRAM_REPLY_SIZE; + if (krb5_aprof_get_int32(aprof, hierarchy, TRUE, &max_dgram_reply_size)) + max_dgram_reply_size = MAX_DGRAM_SIZE; + if (tcp_listen_backlog_out != NULL) { + hierarchy[1] = KRB5_CONF_KDC_TCP_LISTEN_BACKLOG; + if (krb5_aprof_get_int32(aprof, hierarchy, TRUE, + tcp_listen_backlog_out)) + *tcp_listen_backlog_out = DEFAULT_TCP_LISTEN_BACKLOG; + } + hierarchy[1] = KRB5_CONF_RESTRICT_ANONYMOUS_TO_TGT; + if (krb5_aprof_get_boolean(aprof, hierarchy, TRUE, &def_restrict_anon)) + def_restrict_anon = FALSE; + hierarchy[1] = KRB5_CONF_NO_HOST_REFERRAL; + if (krb5_aprof_get_string_all(aprof, hierarchy, &no_referral)) + no_referral = 0; + hierarchy[1] = KRB5_CONF_HOST_BASED_SERVICES; + if (krb5_aprof_get_string_all(aprof, hierarchy, &hostbased)) + hostbased = 0; + + if (def_udp_listen == NULL) { + def_udp_listen = strdup(DEFAULT_KDC_UDP_PORTLIST); + if (def_udp_listen == NULL) { + fprintf(stderr, _(" KDC cannot initialize. Not enough memory\n")); + exit(1); + } + } + if (def_tcp_listen == NULL) { + def_tcp_listen = strdup(DEFAULT_KDC_TCP_PORTLIST); + if (def_tcp_listen == NULL) { + fprintf(stderr, _(" KDC cannot initialize. Not enough memory\n")); + exit(1); + } + } + + /* + * Loop through the option list. Each time we encounter a realm name, use + * the previously scanned options to fill in for defaults. We do this + * twice if worker processes are used, so we must initialize optind. + */ + optind = 1; + while ((c = getopt(argc, argv, "x:r:d:mM:k:R:P:p:nw:4:T:X3")) != -1) { + switch(c) { + case 'x': + db_args_size++; + { + char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ + if( temp == NULL ) + { + fprintf(stderr, _("%s: KDC cannot initialize. Not enough " + "memory\n"), argv[0]); + exit(1); + } + + db_args = temp; + } + db_args[db_args_size-1] = optarg; + db_args[db_args_size] = NULL; + break; + + case 'r': /* realm name for db */ + if (!find_realm_data(&shandle, optarg, (krb5_ui_4) strlen(optarg))) { + if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { + retval = init_realm(rdatap, aprof, optarg, mkey_name, + menctype, def_udp_listen, + def_tcp_listen, manual, + def_restrict_anon, db_args, + no_referral, hostbased); + if (retval) { + fprintf(stderr, _("%s: cannot initialize realm %s - " + "see log file for details\n"), + argv[0], optarg); + exit(1); + } + shandle.kdc_realmlist[shandle.kdc_numrealms] = rdatap; + shandle.kdc_numrealms++; + free(db_args), db_args=NULL, db_args_size = 0; + } + else + { + fprintf(stderr, _("%s: cannot initialize realm %s. Not " + "enough memory\n"), argv[0], optarg); + exit(1); + } + } + break; + case 'd': /* pathname for db */ + /* now db_name is not a separate argument. + * It has to be passed as part of the db_args + */ + if( db_name == NULL ) { + if (asprintf(&db_name, "dbname=%s", optarg) < 0) { + fprintf(stderr, _("%s: KDC cannot initialize. Not enough " + "memory\n"), argv[0]); + exit(1); + } + } + + db_args_size++; + { + char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ + if( temp == NULL ) + { + fprintf(stderr, _("%s: KDC cannot initialize. Not enough " + "memory\n"), argv[0]); + exit(1); + } + + db_args = temp; + } + db_args[db_args_size-1] = db_name; + db_args[db_args_size] = NULL; + break; + case 'm': /* manual type-in of master key */ + manual = TRUE; + if (menctype == ENCTYPE_UNKNOWN) + menctype = DEFAULT_KDC_ENCTYPE; + break; + case 'M': /* master key name in DB */ + mkey_name = optarg; + break; + case 'n': + nofork++; /* don't detach from terminal */ + break; + case 'w': /* create multiple worker processes */ + workers = atoi(optarg); + if (workers <= 0) + usage(argv[0]); + break; + case 'k': /* enctype for master key */ + if (krb5_string_to_enctype(optarg, &menctype)) + com_err(argv[0], 0, _("invalid enctype %s"), optarg); + break; + case 'R': + /* Replay cache name; defunct since we don't use a replay cache. */ + break; + case 'P': + pid_file = optarg; + break; + case 'p': + free(def_udp_listen); + free(def_tcp_listen); + def_udp_listen = strdup(optarg); + def_tcp_listen = strdup(optarg); + if (def_udp_listen == NULL || def_tcp_listen == NULL) { + fprintf(stderr, _(" KDC cannot initialize. Not enough " + "memory\n")); + exit(1); + } + break; + case 'T': + time_offset = atoi(optarg); + break; + case '4': + break; + case 'X': + break; + case '?': + default: + usage(argv[0]); + } + } + + /* + * Check to see if we processed any realms. + */ + if (shandle.kdc_numrealms == 0) { + /* no realm specified, use default realm */ + if ((retval = krb5_get_default_realm(kcontext, &lrealm))) { + com_err(argv[0], retval, + _("while attempting to retrieve default realm")); + fprintf (stderr, + _("%s: %s, attempting to retrieve default realm\n"), + argv[0], krb5_get_error_message(kcontext, retval)); + exit(1); + } + if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { + retval = init_realm(rdatap, aprof, lrealm, mkey_name, menctype, + def_udp_listen, def_tcp_listen, manual, + def_restrict_anon, db_args, no_referral, + hostbased); + if (retval) { + fprintf(stderr, _("%s: cannot initialize realm %s - see log " + "file for details\n"), argv[0], lrealm); + exit(1); + } + shandle.kdc_realmlist[0] = rdatap; + shandle.kdc_numrealms++; + } + krb5_free_default_realm(kcontext, lrealm); + } + + if (def_udp_listen) + free(def_udp_listen); + if (def_tcp_listen) + free(def_tcp_listen); + if (db_args) + free(db_args); + if (db_name) + free(db_name); + if (hostbased) + free(hostbased); + if (no_referral) + free(no_referral); + + return; +} + +static krb5_error_code +write_pid_file(const char *path) +{ + FILE *file; + unsigned long pid; + + file = fopen(path, "w"); + if (file == NULL) + return errno; + pid = (unsigned long) getpid(); + if (fprintf(file, "%ld\n", pid) < 0 || fclose(file) == EOF) + return errno; + return 0; +} + +static void +finish_realms() +{ + int i; + + for (i = 0; i < shandle.kdc_numrealms; i++) { + finish_realm(shandle.kdc_realmlist[i]); + shandle.kdc_realmlist[i] = 0; + } + shandle.kdc_numrealms = 0; +} + +/* + outline: + + process args & setup + + initialize database access (fetch master key, open DB) + + initialize network + + loop: + listen for packet + + determine packet type, dispatch to handling routine + (AS or TGS (or V4?)) + + reflect response + + exit on signal + + clean up secrets, close db + + shut down network + + exit +*/ + +int main(int argc, char **argv) +{ + krb5_error_code retval; + krb5_context kcontext; + kdc_realm_t *realm; + verto_ctx *ctx; + int tcp_listen_backlog; + int errout = 0; + int i; + + setlocale(LC_ALL, ""); + if (strrchr(argv[0], '/')) + argv[0] = strrchr(argv[0], '/')+1; + + shandle.kdc_realmlist = malloc(sizeof(kdc_realm_t *) * + KRB5_KDC_MAX_REALMS); + if (shandle.kdc_realmlist == NULL) { + fprintf(stderr, _("%s: cannot get memory for realm list\n"), argv[0]); + exit(1); + } + memset(shandle.kdc_realmlist, 0, + (size_t) (sizeof(kdc_realm_t *) * KRB5_KDC_MAX_REALMS)); + + /* + * A note about Kerberos contexts: This context, "kcontext", is used + * for the KDC operations, i.e. setup, network connection and error + * reporting. The per-realm operations use the "realm_context" + * associated with each realm. + */ + retval = krb5int_init_context_kdc(&kcontext); + if (retval) { + com_err(argv[0], retval, _("while initializing krb5")); + exit(1); + } + krb5_klog_init(kcontext, "kdc", argv[0], 1); + shandle.kdc_err_context = kcontext; + kdc_progname = argv[0]; + /* N.B.: After this point, com_err sends output to the KDC log + file, and not to stderr. We use the kdc_err wrapper around + com_err to ensure that the error state exists in the context + known to the krb5_klog callback. */ + + initialize_kdc5_error_table(); + + /* + * Scan through the argument list + */ + initialize_realms(kcontext, argc, argv, &tcp_listen_backlog); + +#ifndef NOCACHE + retval = kdc_init_lookaside(kcontext); + if (retval) { + kdc_err(kcontext, retval, _("while initializing lookaside cache")); + finish_realms(); + return 1; + } +#endif + + ctx = loop_init(VERTO_EV_TYPE_NONE); + if (!ctx) { + kdc_err(kcontext, ENOMEM, _("while creating main loop")); + finish_realms(); + return 1; + } + + load_preauth_plugins(&shandle, kcontext, ctx); + load_authdata_plugins(kcontext); + retval = load_kdcpolicy_plugins(kcontext); + if (retval) { + kdc_err(kcontext, retval, _("while loading KDC policy plugin")); + finish_realms(); + return 1; + } + + /* Add each realm's listener addresses to the loop. */ + for (i = 0; i < shandle.kdc_numrealms; i++) { + realm = shandle.kdc_realmlist[i]; + if (*realm->realm_listen != '\0') { + retval = loop_add_udp_address(KRB5_DEFAULT_PORT, + realm->realm_listen); + if (retval) + goto net_init_error; + } + if (*realm->realm_tcp_listen != '\0') { + retval = loop_add_tcp_address(KRB5_DEFAULT_PORT, + realm->realm_tcp_listen); + if (retval) + goto net_init_error; + } + } + + if (workers == 0) { + retval = loop_setup_signals(ctx, &shandle, reset_for_hangup); + if (retval) { + kdc_err(kcontext, retval, _("while initializing signal handlers")); + finish_realms(); + return 1; + } + } + if ((retval = loop_setup_network(ctx, &shandle, kdc_progname, + tcp_listen_backlog))) { + net_init_error: + kdc_err(kcontext, retval, _("while initializing network")); + finish_realms(); + return 1; + } + + /* Clean up realms for now and reinitialize them after daemonizing, since + * some KDB modules are not fork-safe. */ + finish_realms(); + + if (!nofork && daemon(0, 0)) { + kdc_err(kcontext, errno, _("while detaching from tty")); + return 1; + } + if (pid_file != NULL) { + retval = write_pid_file(pid_file); + if (retval) { + kdc_err(kcontext, retval, _("while creating PID file")); + finish_realms(); + return 1; + } + } + if (workers > 0) { + retval = create_workers(ctx, workers); + if (retval) { + kdc_err(kcontext, errno, _("creating worker processes")); + return 1; + } + } + + initialize_realms(kcontext, argc, argv, NULL); + + /* Initialize audit system and audit KDC startup. */ + retval = load_audit_modules(kcontext); + if (retval) { + kdc_err(kcontext, retval, _("while loading audit plugin module(s)")); + finish_realms(); + return 1; + } + krb5_klog_syslog(LOG_INFO, _("commencing operation")); + if (nofork) + fprintf(stderr, _("%s: starting...\n"), kdc_progname); + kau_kdc_start(kcontext, TRUE); + + verto_run(ctx); + kau_kdc_stop(kcontext, TRUE); + krb5_klog_syslog(LOG_INFO, _("shutting down")); + unload_preauth_plugins(kcontext); + unload_authdata_plugins(kcontext); + unload_kdcpolicy_plugins(kcontext); + unload_audit_modules(kcontext); + krb5_klog_close(kcontext); + finish_realms(); + if (shandle.kdc_realmlist) + free(shandle.kdc_realmlist); +#ifndef NOCACHE + kdc_free_lookaside(kcontext); +#endif + loop_free(ctx); + krb5_free_context(kcontext); + return errout; +} diff --git a/krb5-1.21.3/src/kdc/ndr.c b/krb5-1.21.3/src/kdc/ndr.c new file mode 100644 index 00000000..d438408e --- /dev/null +++ b/krb5-1.21.3/src/kdc/ndr.c @@ -0,0 +1,331 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/ndr.c - NDR encoding and decoding functions */ +/* + * Copyright (C) 2021 by Red Hat, Inc. + * 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. + */ + +#include "k5-int.h" +#include "k5-input.h" +#include "k5-buf.h" +#include "k5-utf8.h" +#include "kdc_util.h" + +struct encoded_wchars { + uint16_t bytes_len; + uint16_t num_wchars; + uint8_t *encoded; +}; + +/* + * MS-DTYP 2.3.10: + * + * typedef struct _RPC_UNICODE_STRING { + * unsigned short Length; + * unsigned short MaximumLength; + * [size_is(MaximumLength/2), length_is(Length/2)] WCHAR* Buffer; + * } RPC_UNICODE_STRING, *PRPC_UNICODE_STRING; + * + * Note that Buffer is not a String - there's no termination. + * + * We don't actually decode Length and MaximumLength here - this is a + * conformant-varying array, which means that (per DCE-1.1-RPC 14.3.7.2) where + * those actually appear in the serialized data is variable depending on + * whether the string is at top level of the struct or not. (This also + * affects where the pointer identifier appears.) + * + * See MS-RPCE 4.7 for what an RPC_UNICODE_STRING looks like when not at + * top-level. + */ +static krb5_error_code +dec_wchar_pointer(struct k5input *in, char **out) +{ + const uint8_t *bytes; + uint32_t actual_count; + + /* Maximum count. */ + (void)k5_input_get_uint32_le(in); + /* Offset - all zeroes, "should" not be checked. */ + (void)k5_input_get_uint32_le(in); + + actual_count = k5_input_get_uint32_le(in); + if (actual_count > UINT32_MAX / 2) + return ERANGE; + + bytes = k5_input_get_bytes(in, actual_count * 2); + if (bytes == NULL || k5_utf16le_to_utf8(bytes, actual_count * 2, out) != 0) + return EINVAL; + + /* Always align on 4. */ + if (actual_count % 2 == 1) + (void)k5_input_get_uint16_le(in); + + return 0; +} + +static krb5_error_code +enc_wchar_pointer(const char *utf8, struct encoded_wchars *encoded_out) +{ + krb5_error_code ret; + struct k5buf b; + size_t utf16len, num_wchars; + uint8_t *utf16; + + ret = k5_utf8_to_utf16le(utf8, &utf16, &utf16len); + if (ret) + return ret; + + num_wchars = utf16len / 2; + + k5_buf_init_dynamic(&b); + k5_buf_add_uint32_le(&b, num_wchars + 1); + k5_buf_add_uint32_le(&b, 0); + k5_buf_add_uint32_le(&b, num_wchars); + k5_buf_add_len(&b, utf16, utf16len); + + free(utf16); + + if (num_wchars % 2 == 1) + k5_buf_add_uint16_le(&b, 0); + + ret = k5_buf_status(&b); + if (ret) + return ret; + + encoded_out->bytes_len = b.len; + encoded_out->num_wchars = num_wchars; + encoded_out->encoded = b.data; + return 0; +} + +/* + * Decode a delegation info structure, leaving room to add an additional + * service. + * + * MS-PAC 2.9: + * + * typedef struct _S4U_DELEGATION_INFO { + * RPC_UNICODE_STRING S4U2proxyTarget; + * ULONG TransitedListSize; + * [size_is(TransitedListSize)] PRPC_UNICODE_STRING S4UTransitedServices; + * } S4U_DELEGATION_INFO, *PS4U_DELEGATION_INFO; + */ +krb5_error_code +ndr_dec_delegation_info(krb5_data *data, struct pac_s4u_delegation_info **out) +{ + krb5_error_code ret; + struct pac_s4u_delegation_info *di = NULL; + struct k5input in; + uint32_t i, object_buffer_length, nservices; + uint8_t version, endianness, common_header_length; + + *out = NULL; + + di = k5alloc(sizeof(*di), &ret); + if (di == NULL) + return ret; + + k5_input_init(&in, data->data, data->length); + + /* Common Type Header - MS-RPCE 2.2.6.1 */ + version = k5_input_get_byte(&in); + endianness = k5_input_get_byte(&in); + common_header_length = k5_input_get_uint16_le(&in); + (void)k5_input_get_uint32_le(&in); /* Filler - 0xcccccccc. */ + if (version != 1 || endianness != 0x10 || common_header_length != 8) { + ret = EINVAL; + goto error; + } + + /* Private Header for Constructed Type - MS-RPCE 2.2.6.2 */ + object_buffer_length = k5_input_get_uint32_le(&in); + if (data->length < 16 || object_buffer_length != data->length - 16) { + ret = EINVAL; + goto error; + } + + (void)k5_input_get_uint32_le(&in); /* Filler - 0. */ + + /* This code doesn't handle re-used pointers, which could come into play in + * the unlikely case of a delegation loop. */ + + /* Pointer. Microsoft always starts at 00 00 02 00 */ + (void)k5_input_get_uint32_le(&in); + /* Length of proxy target - 2 */ + (void)k5_input_get_uint16_le(&in); + /* Length of proxy target */ + (void)k5_input_get_uint16_le(&in); + /* Another pointer - 04 00 02 00. Microsoft increments by 4 (le). */ + (void)k5_input_get_uint32_le(&in); + + /* Transited services length - header version. */ + (void)k5_input_get_uint32_le(&in); + + /* More pointer: 08 00 02 00 */ + (void)k5_input_get_uint32_le(&in); + + ret = dec_wchar_pointer(&in, &di->proxy_target); + if (ret) + goto error; + nservices = k5_input_get_uint32_le(&in); + + /* Here, we have encoded 2 bytes of length, 2 bytes of (length + 2), and 4 + * bytes of pointer, for each element (deferred pointers). */ + if (nservices > data->length / 8) { + ret = ERANGE; + goto error; + } + (void)k5_input_get_bytes(&in, 8 * nservices); + + /* Since we're likely to add another entry, leave a blank at the end. */ + di->transited_services = k5calloc(nservices + 1, sizeof(char *), &ret); + if (di->transited_services == NULL) + goto error; + + for (i = 0; i < nservices; i++) { + ret = dec_wchar_pointer(&in, &di->transited_services[i]); + if (ret) + goto error; + di->transited_services_length++; + } + + ret = in.status; + if (ret) + goto error; + + *out = di; + return 0; + +error: + ndr_free_delegation_info(di); + return ret; +} + +/* Empirically, Microsoft starts pointers at 00 00 02 00, and if treated little + * endian, they increase by 4. */ +static inline void +write_ptr(struct k5buf *buf, uint32_t *pointer) +{ + if (*pointer == 0) + *pointer = 0x00020000; + k5_buf_add_uint32_le(buf, *pointer); + *pointer += 4; +} + +krb5_error_code +ndr_enc_delegation_info(struct pac_s4u_delegation_info *in, krb5_data *out) +{ + krb5_error_code ret; + size_t i; + struct k5buf b; + struct encoded_wchars pt_encoded = { 0 }, *tss_encoded = NULL; + uint32_t pointer = 0; + + /* Encode ahead of time since we need the lengths. */ + ret = enc_wchar_pointer(in->proxy_target, &pt_encoded); + if (ret) + goto cleanup; + + tss_encoded = k5calloc(in->transited_services_length, sizeof(*tss_encoded), + &ret); + if (tss_encoded == NULL) + goto cleanup; + + k5_buf_init_dynamic(&b); + + /* Common Type Header - MS-RPCE 2.2.6.1 */ + k5_buf_add_len(&b, "\x01\x10\x08\x00", 4); + k5_buf_add_uint32_le(&b, 0xcccccccc); + + /* Private Header for Constructed Type - MS-RPCE 2.2.6.2 */ + k5_buf_add_uint32_le(&b, 0); /* Skip over where payload length goes. */ + k5_buf_add_uint32_le(&b, 0); /* Filler - all zeroes. */ + + write_ptr(&b, &pointer); + k5_buf_add_uint16_le(&b, 2 * pt_encoded.num_wchars); + k5_buf_add_uint16_le(&b, 2 * (pt_encoded.num_wchars + 1)); + write_ptr(&b, &pointer); + + k5_buf_add_uint32_le(&b, in->transited_services_length); + write_ptr(&b, &pointer); + + k5_buf_add_len(&b, pt_encoded.encoded, pt_encoded.bytes_len); + + k5_buf_add_uint32_le(&b, in->transited_services_length); + + /* Deferred pointers. */ + for (i = 0; i < in->transited_services_length; i++) { + ret = enc_wchar_pointer(in->transited_services[i], &tss_encoded[i]); + if (ret) + goto cleanup; + + k5_buf_add_uint16_le(&b, 2 * tss_encoded[i].num_wchars); + k5_buf_add_uint16_le(&b, 2 * (tss_encoded[i].num_wchars + 1)); + write_ptr(&b, &pointer); + } + + for (i = 0; i < in->transited_services_length; i++) + k5_buf_add_len(&b, tss_encoded[i].encoded, tss_encoded[i].bytes_len); + + /* Now, pad to 8 bytes. RPC_UNICODE_STRING is aligned on 4 bytes. */ + if (b.len % 8 != 0) + k5_buf_add_uint32_le(&b, 0); + + /* Record the payload length where we skipped over it previously. */ + if (b.data != NULL) + store_32_le(b.len - 0x10, ((uint8_t *)b.data) + 8); + + ret = k5_buf_status(&b); + if (ret) + goto cleanup; + + *out = make_data(b.data, b.len); + b.data = NULL; + +cleanup: + free(b.data); + free(pt_encoded.encoded); + for (i = 0; tss_encoded != NULL && i < in->transited_services_length; i++) + free(tss_encoded[i].encoded); + free(tss_encoded); + return ret; +} + +void +ndr_free_delegation_info(struct pac_s4u_delegation_info *di) +{ + uint32_t i; + + if (di == NULL) + return; + free(di->proxy_target); + for (i = 0; i < di->transited_services_length; i++) + free(di->transited_services[i]); + free(di->transited_services); + free(di); +} diff --git a/krb5-1.21.3/src/kdc/policy.c b/krb5-1.21.3/src/kdc/policy.c new file mode 100644 index 00000000..a3ff556c --- /dev/null +++ b/krb5-1.21.3/src/kdc/policy.c @@ -0,0 +1,246 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/policy.c - Policy decision routines for KDC */ +/* + * Copyright (C) 2017 by Red Hat, Inc. + * 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. + */ + +#include "k5-int.h" +#include "kdc_util.h" +#include "extern.h" +#include "policy.h" +#include "adm_proto.h" +#include +#include + +typedef struct kdcpolicy_handle_st { + struct krb5_kdcpolicy_vtable_st vt; + krb5_kdcpolicy_moddata moddata; +} *kdcpolicy_handle; + +static kdcpolicy_handle *handles; + +static void +free_indicators(char **ais) +{ + size_t i; + + if (ais == NULL) + return; + for (i = 0; ais[i] != NULL; i++) + free(ais[i]); + free(ais); +} + +/* Convert inds to a null-terminated list of C strings. */ +static krb5_error_code +authind_strings(krb5_data *const *inds, char ***strs_out) +{ + krb5_error_code ret; + char **list = NULL; + size_t i, count; + + *strs_out = NULL; + + for (count = 0; inds != NULL && inds[count] != NULL; count++); + list = k5calloc(count + 1, sizeof(*list), &ret); + if (list == NULL) + goto error; + + for (i = 0; i < count; i++) { + list[i] = k5memdup0(inds[i]->data, inds[i]->length, &ret); + if (list[i] == NULL) + goto error; + } + + *strs_out = list; + return 0; + +error: + free_indicators(list); + return ret; +} + +/* Constrain times->endtime to life and times->renew_till to rlife, relative to + * now. */ +static void +update_ticket_times(krb5_ticket_times *times, krb5_timestamp now, + krb5_deltat life, krb5_deltat rlife) +{ + if (life) + times->endtime = ts_min(ts_incr(now, life), times->endtime); + if (rlife) + times->renew_till = ts_min(ts_incr(now, rlife), times->renew_till); +} + +/* Check an AS request against kdcpolicy modules, updating times with any + * module endtime constraints. Set an appropriate status string on error. */ +krb5_error_code +check_kdcpolicy_as(krb5_context context, const krb5_kdc_req *request, + const krb5_db_entry *client, const krb5_db_entry *server, + krb5_data *const *auth_indicators, krb5_timestamp kdc_time, + krb5_ticket_times *times, const char **status) +{ + krb5_deltat life = 0, rlife = 0; + krb5_error_code ret; + kdcpolicy_handle *hp, h; + char **ais = NULL; + + *status = NULL; + + ret = authind_strings(auth_indicators, &ais); + if (ret) + goto done; + + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.check_as == NULL) + continue; + + ret = h->vt.check_as(context, h->moddata, request, client, server, + (const char **)ais, status, &life, &rlife); + if (ret) + goto done; + + update_ticket_times(times, kdc_time, life, rlife); + } + +done: + free_indicators(ais); + return ret; +} + +/* + * Check the TGS request against the local TGS policy. Accepts an + * authentication indicator for the module policy decisions. Returns 0 and a + * NULL status string on success. + */ +krb5_error_code +check_kdcpolicy_tgs(krb5_context context, const krb5_kdc_req *request, + const krb5_db_entry *server, const krb5_ticket *ticket, + krb5_data *const *auth_indicators, krb5_timestamp kdc_time, + krb5_ticket_times *times, const char **status) +{ + krb5_deltat life = 0, rlife = 0; + krb5_error_code ret; + kdcpolicy_handle *hp, h; + char **ais = NULL; + + *status = NULL; + + ret = authind_strings(auth_indicators, &ais); + if (ret) + goto done; + + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.check_tgs == NULL) + continue; + + ret = h->vt.check_tgs(context, h->moddata, request, server, ticket, + (const char **)ais, status, &life, &rlife); + if (ret) + goto done; + + update_ticket_times(times, kdc_time, life, rlife); + } + +done: + free_indicators(ais); + return ret; +} + +void +unload_kdcpolicy_plugins(krb5_context context) +{ + kdcpolicy_handle *hp, h; + + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.fini != NULL) + h->vt.fini(context, h->moddata); + free(h); + } + free(handles); + handles = NULL; +} + +krb5_error_code +load_kdcpolicy_plugins(krb5_context context) +{ + krb5_error_code ret; + krb5_plugin_initvt_fn *modules = NULL, *mod; + kdcpolicy_handle h; + size_t count; + + ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_KDCPOLICY, &modules); + if (ret) + goto cleanup; + + for (count = 0; modules[count] != NULL; count++); + handles = k5calloc(count + 1, sizeof(*handles), &ret); + if (handles == NULL) + goto cleanup; + + count = 0; + for (mod = modules; *mod != NULL; mod++) { + h = k5calloc(1, sizeof(*h), &ret); + if (h == NULL) + goto cleanup; + + ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&h->vt); + if (ret) { /* Version mismatch. */ + TRACE_KDCPOLICY_VTINIT_FAIL(context, ret); + free(h); + continue; + } + if (h->vt.init != NULL) { + ret = h->vt.init(context, &h->moddata); + if (ret == KRB5_PLUGIN_NO_HANDLE) { + TRACE_KDCPOLICY_INIT_SKIP(context, h->vt.name); + free(h); + continue; + } + if (ret) { + kdc_err(context, ret, _("while loading policy module %s"), + h->vt.name); + free(h); + goto cleanup; + } + } + handles[count++] = h; + } + + ret = 0; + +cleanup: + if (ret) + unload_kdcpolicy_plugins(context); + k5_plugin_free_modules(context, modules); + return ret; +} diff --git a/krb5-1.21.3/src/kdc/policy.h b/krb5-1.21.3/src/kdc/policy.h new file mode 100644 index 00000000..2a57b0a0 --- /dev/null +++ b/krb5-1.21.3/src/kdc/policy.h @@ -0,0 +1,47 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/policy.h - Declarations for policy.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __KRB5_KDC_POLICY__ +#define __KRB5_KDC_POLICY__ + +krb5_error_code +load_kdcpolicy_plugins(krb5_context context); + +void +unload_kdcpolicy_plugins(krb5_context context); + +krb5_error_code +check_kdcpolicy_as(krb5_context context, const krb5_kdc_req *request, + const krb5_db_entry *client, const krb5_db_entry *server, + krb5_data *const *auth_indicators, krb5_timestamp kdc_time, + krb5_ticket_times *times, const char **status); + +krb5_error_code +check_kdcpolicy_tgs(krb5_context context, const krb5_kdc_req *request, + const krb5_db_entry *server, const krb5_ticket *ticket, + krb5_data *const *auth_indicators, krb5_timestamp kdc_time, + krb5_ticket_times *times, const char **status); + +#endif /* __KRB5_KDC_POLICY__ */ diff --git a/krb5-1.21.3/src/kdc/realm_data.h b/krb5-1.21.3/src/kdc/realm_data.h new file mode 100644 index 00000000..68eed771 --- /dev/null +++ b/krb5-1.21.3/src/kdc/realm_data.h @@ -0,0 +1,88 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/realm_data.h */ +/* + * Copyright (C) 2012 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. + */ + +#ifndef REALM_DATA_H +#define REALM_DATA_H + +typedef struct __kdc_realm_data { + /* + * General Kerberos per-realm data. + */ + char * realm_name; /* Realm name */ +/* XXX the real context should go away once the db_context is done. + * The db_context is then associated with the realm keytab using + * krb5_ktkdb_resolv(). There should be nothing in the context which + * cannot span multiple realms -- proven */ + krb5_context realm_context; /* Context to be used for realm */ + krb5_keytab realm_keytab; /* keytab to be used for this realm */ + char * realm_hostbased; /* referral services for NT-UNKNOWN */ + char * realm_no_referral; /* non-referral services */ + /* + * Database per-realm data. + */ + char * realm_stash; /* Stash file name for realm */ + char * realm_mpname; /* Master principal name for realm */ + krb5_principal realm_mprinc; /* Master principal for realm */ + /* + * Note realm_mkey is mkey read from stash or keyboard and may not be the + * latest. + */ + krb5_keyblock realm_mkey; /* Master key for this realm */ + /* + * TGS per-realm data. + */ + krb5_principal realm_tgsprinc; /* TGS principal for this realm */ + /* + * Other per-realm data. + */ + char *realm_listen; /* Per-realm KDC UDP listen */ + char *realm_tcp_listen; /* Per-realm KDC TCP listen */ + /* + * Per-realm parameters. + */ + krb5_deltat realm_maxlife; /* Maximum ticket life for realm */ + krb5_deltat realm_maxrlife; /* Maximum renewable life for realm */ + krb5_boolean realm_reject_bad_transit; /* Accept unverifiable transited_realm ? */ + krb5_boolean realm_restrict_anon; /* Anon to local TGT only */ + krb5_boolean realm_disable_pac; /* Prevent issuance of PACs. */ +} kdc_realm_t; + +struct server_handle { + kdc_realm_t **kdc_realmlist; + int kdc_numrealms; + krb5_context kdc_err_context; +}; + +kdc_realm_t *find_realm_data(struct server_handle *, char *, krb5_ui_4); +kdc_realm_t *setup_server_realm(struct server_handle *, krb5_principal); + +#endif /* REALM_DATA_H */ diff --git a/krb5-1.21.3/src/kdc/replay.c b/krb5-1.21.3/src/kdc/replay.c new file mode 100644 index 00000000..5125bc63 --- /dev/null +++ b/krb5-1.21.3/src/kdc/replay.c @@ -0,0 +1,231 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/replay.c - Replay lookaside cache for the KDC, to avoid extra work */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "k5-queue.h" +#include "k5-hashtab.h" +#include "kdc_util.h" +#include "extern.h" + +#ifndef NOCACHE + +struct entry { + K5_TAILQ_ENTRY(entry) links; + int num_hits; + krb5_timestamp timein; + krb5_data req_packet; + krb5_data reply_packet; +}; + +#ifndef LOOKASIDE_MAX_SIZE +#define LOOKASIDE_MAX_SIZE (10 * 1024 * 1024) +#endif + +K5_LIST_HEAD(entry_list, entry); +K5_TAILQ_HEAD(entry_queue, entry); + +static struct k5_hashtab *hash_table; +static struct entry_queue expiration_queue; + +static int hits = 0; +static int calls = 0; +static int max_hits_per_entry = 0; +static int num_entries = 0; +static size_t total_size = 0; + +#define STALE_TIME (2*60) /* two minutes */ +#define STALE(ptr, now) (ts_after(now, ts_incr((ptr)->timein, STALE_TIME))) + +/* Return the rough memory footprint of an entry containing req and rep. */ +static size_t +entry_size(const krb5_data *req, const krb5_data *rep) +{ + return sizeof(struct entry) + req->length + + ((rep == NULL) ? 0 : rep->length); +} + +/* Insert an entry into the cache. */ +static struct entry * +insert_entry(krb5_context context, krb5_data *req, krb5_data *rep, + krb5_timestamp time) +{ + krb5_error_code ret; + struct entry *entry; + size_t esize = entry_size(req, rep); + + entry = calloc(1, sizeof(*entry)); + if (entry == NULL) + goto error; + entry->timein = time; + + ret = krb5int_copy_data_contents(context, req, &entry->req_packet); + if (ret) + goto error; + + if (rep != NULL) { + ret = krb5int_copy_data_contents(context, rep, &entry->reply_packet); + if (ret) + goto error; + } + + ret = k5_hashtab_add(hash_table, entry->req_packet.data, + entry->req_packet.length, entry); + if (ret) + goto error; + K5_TAILQ_INSERT_TAIL(&expiration_queue, entry, links); + num_entries++; + total_size += esize; + + return entry; + +error: + if (entry != NULL) { + krb5_free_data_contents(context, &entry->req_packet); + krb5_free_data_contents(context, &entry->reply_packet); + free(entry); + } + return NULL; +} + + +/* Remove entry from its hash bucket and the expiration queue, and free it. */ +static void +discard_entry(krb5_context context, struct entry *entry) +{ + total_size -= entry_size(&entry->req_packet, &entry->reply_packet); + num_entries--; + k5_hashtab_remove(hash_table, entry->req_packet.data, + entry->req_packet.length); + K5_TAILQ_REMOVE(&expiration_queue, entry, links); + krb5_free_data_contents(context, &entry->req_packet); + krb5_free_data_contents(context, &entry->reply_packet); + free(entry); +} + +/* Initialize the lookaside cache structures and randomize the hash seed. */ +krb5_error_code +kdc_init_lookaside(krb5_context context) +{ + krb5_error_code ret; + uint8_t seed[K5_HASH_SEED_LEN]; + krb5_data d = make_data(seed, sizeof(seed)); + + ret = krb5_c_random_make_octets(context, &d); + if (ret) + return ret; + ret = k5_hashtab_create(seed, 8192, &hash_table); + if (ret) + return ret; + K5_TAILQ_INIT(&expiration_queue); + return 0; +} + +/* Remove the lookaside cache entry for a packet. */ +void +kdc_remove_lookaside(krb5_context kcontext, krb5_data *req_packet) +{ + struct entry *e; + + e = k5_hashtab_get(hash_table, req_packet->data, req_packet->length); + if (e != NULL) + discard_entry(kcontext, e); +} + +/* + * Return true and fill in reply_packet_out if req_packet is in the lookaside + * cache; otherwise return false. + * + * If the request was inserted with a NULL reply_packet to indicate that a + * request is still being processed, then return TRUE with reply_packet_out set + * to NULL. + */ +krb5_boolean +kdc_check_lookaside(krb5_context kcontext, krb5_data *req_packet, + krb5_data **reply_packet_out) +{ + struct entry *e; + + *reply_packet_out = NULL; + calls++; + + e = k5_hashtab_get(hash_table, req_packet->data, req_packet->length); + if (e == NULL) + return FALSE; + + e->num_hits++; + hits++; + + /* Leave *reply_packet_out as NULL for an in-progress entry. */ + if (e->reply_packet.length == 0) + return TRUE; + + return (krb5_copy_data(kcontext, &e->reply_packet, + reply_packet_out) == 0); +} + +/* + * Insert a request and reply into the lookaside cache. Assumes it's not + * already there, and can fail silently on memory exhaustion. Also discard old + * entries in the cache. + * + * The reply_packet may be NULL to indicate a request that is still processing. + */ +void +kdc_insert_lookaside(krb5_context kcontext, krb5_data *req_packet, + krb5_data *reply_packet) +{ + struct entry *e, *next; + krb5_timestamp timenow; + size_t esize = entry_size(req_packet, reply_packet); + + if (krb5_timeofday(kcontext, &timenow)) + return; + + /* Purge stale entries and limit the total size of the entries. */ + K5_TAILQ_FOREACH_SAFE(e, &expiration_queue, links, next) { + if (!STALE(e, timenow) && total_size + esize <= LOOKASIDE_MAX_SIZE) + break; + max_hits_per_entry = max(max_hits_per_entry, e->num_hits); + discard_entry(kcontext, e); + } + + insert_entry(kcontext, req_packet, reply_packet, timenow); + return; +} + +/* Free all entries in the lookaside cache. */ +void +kdc_free_lookaside(krb5_context kcontext) +{ + struct entry *e, *next; + + K5_TAILQ_FOREACH_SAFE(e, &expiration_queue, links, next) { + discard_entry(kcontext, e); + } + k5_hashtab_free(hash_table); +} + +#endif /* NOCACHE */ diff --git a/krb5-1.21.3/src/kdc/reqstate.h b/krb5-1.21.3/src/kdc/reqstate.h new file mode 100644 index 00000000..38c399dd --- /dev/null +++ b/krb5-1.21.3/src/kdc/reqstate.h @@ -0,0 +1,54 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/reqstate.h */ +/* + * Copyright (C) 2012 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. + */ + +#ifndef REQSTATE_H +#define REQSTATE_H + +#include "realm_data.h" + +/* Request state */ + +struct kdc_request_state { + krb5_keyblock *armor_key; + krb5_keyblock *strengthen_key; + krb5_pa_data **in_cookie_padata; + krb5_pa_data **out_cookie_padata; + krb5_int32 fast_options; + krb5_int32 fast_internal_flags; + kdc_realm_t *realm_data; +}; + +krb5_error_code kdc_make_rstate(kdc_realm_t *active_realm, + struct kdc_request_state **out); +void kdc_free_rstate(struct kdc_request_state *s); + +#endif /* REQSTATE_H */ diff --git a/krb5-1.21.3/src/kdc/rtest.c b/krb5-1.21.3/src/kdc/rtest.c new file mode 100644 index 00000000..68522841 --- /dev/null +++ b/krb5-1.21.3/src/kdc/rtest.c @@ -0,0 +1,117 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/rtest.c */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include +#include "kdc_util.h" +#include "extern.h" + +void krb5_klog_syslog(void); + +static krb5_principal +make_princ(krb5_context ctx, const char *str, const char *prog) +{ + krb5_principal ret; + char *dat; + + if(!(ret = (krb5_principal) malloc(sizeof(krb5_principal_data)))) { + com_err(prog, ENOMEM, "while allocating principal data"); + exit(3); + } + memset(ret, 0, sizeof(krb5_principal_data)); + + /* We do not include the null... */ + if(!(dat = (char *) malloc(strlen(str)))) { + com_err(prog, ENOMEM, "while allocating principal realm data"); + exit(3); + } + memcpy(dat, str, strlen(str)); + krb5_princ_set_realm_data(ctx, ret, dat); + krb5_princ_set_realm_length(ctx, ret, strlen(str)); + + return ret; +} + +int +main(int argc, char **argv) +{ + krb5_data otrans; + krb5_data ntrans; + krb5_principal tgs, cl, sv; + krb5_error_code kret; + krb5_context ctx; + + if (argc < 4) { + fprintf(stderr, "not enough args\n"); + exit(1); + } + + + /* Get a context */ + kret = krb5int_init_context_kdc(&ctx); + if (kret) { + com_err(argv[0], kret, "while getting krb5 context"); + exit(2); + } + + ntrans.length = 0; + ntrans.data = 0; + + otrans.length = strlen(argv[1]); + if (otrans.length) + otrans.data = (char *) malloc(otrans.length); + else + otrans.data = 0; + memcpy(otrans.data,argv[1], otrans.length); + + tgs = make_princ(ctx, argv[2], argv[0]); + cl = make_princ(ctx, argv[3], argv[0]); + sv = make_princ(ctx, argv[4], argv[0]); + + add_to_transited(&otrans,&ntrans,tgs,cl,sv); + + printf("%s\n",ntrans.data); + + /* Free up all memory so we can profile for leaks */ + if (otrans.data) + free(otrans.data); + free(ntrans.data); + + krb5_free_principal(ctx, tgs); + krb5_free_principal(ctx, cl); + krb5_free_principal(ctx, sv); + krb5_free_context(ctx); + + exit(0); +} + +void krb5_klog_syslog(void) {} +kdc_realm_t * +find_realm_data(struct server_handle *handle, + char *rname, krb5_ui_4 rsize) +{ + return 0; +} diff --git a/krb5-1.21.3/src/kdc/rtest.good b/krb5-1.21.3/src/kdc/rtest.good new file mode 100644 index 00000000..4eecf6e3 --- /dev/null +++ b/krb5-1.21.3/src/kdc/rtest.good @@ -0,0 +1,26 @@ +ATHENA.MIT.EDU +MIT.EDU,ATHENA. +EDU,MIT.,ATHENA. +EDU,MIT.,ATHENA.,WASHINGTON.EDU +EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS. +EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W. +EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W.,SUB3W.CS.WASHINGTON.EDU +EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W. +EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W. +EDU,ATHENA.MIT.,SUB2M.,WASHINGTON.EDU,CS. +/EDU/MIT/ATHENA +/EDU/MIT,/ATHENA +/EDU/MIT,/ATHENA +/EDU,/MIT,/ATHENA +/EDU,/MIT,/ATHENA, /EDU/WASHINGTON +/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS +/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W +/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W, /EDU/WASHINGTON/CS/SUB3W +/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W +/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W +/EDU,/MIT/ATHENA,/SUB2M, /EDU/WASHINGTON,/CS +EDU,MIT.,ATHENA.,ATEST., /COM,/HP,/APOLLO +EDU,MIT.,ATHENA., /COM,/HP,/APOLLO,/HTEST +/COM,/HP,/APOLLO,EDU,MIT.,ATHENA.,ATEST. +/COM,/HP,/APOLLO,ATHENA.MIT.EDU +EDU,MIT.,ATHENA., /COM/HP/APOLLO/HTEST diff --git a/krb5-1.21.3/src/kdc/rtscript b/krb5-1.21.3/src/kdc/rtscript new file mode 100755 index 00000000..53da7da8 --- /dev/null +++ b/krb5-1.21.3/src/kdc/rtscript @@ -0,0 +1,55 @@ +#!/bin/sh +# +# +# Copyright 1991 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. +# +# +# should print out contents of rtest.good +# +. ./runenv.sh +./rtest "" ATHENA.MIT.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU +./rtest ATHENA.MIT.EDU MIT.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU +./rtest "MIT.EDU,ATHENA." EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU +./rtest "EDU,MIT.,ATHENA." WASHINGTON.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU +./rtest "EDU,MIT.,ATHENA.,WASHINGTON.EDU" CS.WASHINGTON.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU +./rtest "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS." SUB2W.CS.WASHINGTON.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU +./rtest "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W." SUB3W.CS.WASHINGTON.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU +./rtest "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W." SUB1W.CS.WASHINGTON.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU +./rtest "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS.,SUB2W." SUB1M.ATHENA.MIT.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU +./rtest "EDU,SUB2M.ATHENA.MIT.,WASHINGTON.EDU,CS." ATHENA.MIT.EDU SUB1W.CS.WASHINGTON.EDU SUB1M.ATHENA.MIT.EDU +./rtest "" /EDU/MIT/ATHENA /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest /EDU/MIT/ATHENA /EDU/MIT /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest " /EDU/MIT/ATHENA" /EDU/MIT /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest "/EDU/MIT,/ATHENA" /EDU /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest "/EDU,/MIT,/ATHENA" /EDU/WASHINGTON /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest "/EDU,/MIT,/ATHENA, /EDU/WASHINGTON" /EDU/WASHINGTON/CS /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest "/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS" /EDU/WASHINGTON/CS/SUB2W /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest "/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W" /EDU/WASHINGTON/CS/SUB3W /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest "/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W" /EDU/WASHINGTON/CS/SUB1W /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest "/EDU,/MIT,/ATHENA, /EDU/WASHINGTON,/CS,/SUB2W" /EDU/MIT/ATHENA/SUB1M /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest "/EDU,/MIT/ATHENA/SUB2M, /EDU/WASHINGTON,/CS" /EDU/MIT/ATHENA /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest "EDU,MIT.,ATHENA., /COM,/HP,/APOLLO" ATEST.ATHENA.MIT.EDU /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest "EDU,MIT.,ATHENA., /COM,/HP,/APOLLO" /COM/HP/APOLLO/HTEST /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest "/COM,/HP,/APOLLO,EDU,MIT.,ATHENA." ATEST.ATHENA.MIT.EDU /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest "/COM,/HP,/APOLLO" ATHENA.MIT.EDU /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M +./rtest "EDU,MIT.,ATHENA." /COM/HP/APOLLO/HTEST /EDU/WASHINGTON/CS/SUB1W /EDU/MIT/ATHENA/SUB1M diff --git a/krb5-1.21.3/src/kdc/t_bigreply.py b/krb5-1.21.3/src/kdc/t_bigreply.py new file mode 100644 index 00000000..ea101ff7 --- /dev/null +++ b/krb5-1.21.3/src/kdc/t_bigreply.py @@ -0,0 +1,32 @@ +from k5test import * +import struct + +# Set the maximum UDP reply size very low, so that all replies go +# through the RESPONSE_TOO_BIG path. +kdc_conf = {'kdcdefaults': {'kdc_max_dgram_reply_size': '10'}} +realm = K5Realm(kdc_conf=kdc_conf, get_creds=False) + +msgs = ('Sending initial UDP request', + 'Received answer', + 'Request or response is too big for UDP; retrying with TCP', + ' to KRBTEST.COM (tcp only)', + 'Initiating TCP connection', + 'Sending TCP request', + 'Terminating TCP connection') +realm.kinit(realm.user_princ, password('user'), expected_trace=msgs) +realm.run([kvno, realm.host_princ], expected_trace=msgs) + +# Pretend to send an absurdly long request over TCP, and verify that +# we get back a reply of plausible length to be an encoded +# KRB_ERR_RESPONSE_TOO_BIG error. +s = socket.create_connection((hostname, realm.portbase)) +s.sendall(b'\xFF\xFF\xFF\xFF') +lenbytes = s.recv(4) +assert(len(lenbytes) == 4) +resplen, = struct.unpack('>L', lenbytes) +if resplen < 10: + fail('KDC response too short (KRB_ERR_RESPONSE_TOO_BIG error expected)') +resp = s.recv(resplen) +assert(len(resp) == resplen) + +success('Large KDC replies') diff --git a/krb5-1.21.3/src/kdc/t_emptytgt.py b/krb5-1.21.3/src/kdc/t_emptytgt.py new file mode 100755 index 00000000..c601c010 --- /dev/null +++ b/krb5-1.21.3/src/kdc/t_emptytgt.py @@ -0,0 +1,6 @@ +from k5test import * + +realm = K5Realm(create_host=False) +realm.run([kvno, 'krbtgt/'], expected_code=1, + expected_msg='not found in Kerberos database') +success('Empty tgt lookup.') diff --git a/krb5-1.21.3/src/kdc/t_ndr.c b/krb5-1.21.3/src/kdc/t_ndr.c new file mode 100644 index 00000000..a3ac661b --- /dev/null +++ b/krb5-1.21.3/src/kdc/t_ndr.c @@ -0,0 +1,188 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/t_ndr.c - tests for ndr.c */ +/* + * Copyright (C) 2021 by Red Hat, Inc. + * 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. + */ + +/* + * Unit tests for the NDR marshalling/unmarshalling in ndr.c + */ + +#include "k5-int.h" +#include "kdc_util.h" + +/* + * Three S4U_DELEGATION_INFO buffers decoded from communication with AD 2019: + * + * - svc1/adserver.ad.test@AD.TEST to svc2/adserver.ad.test@AD.TEST + * - svc1/adserver.ad.test@AD.TEST to longsvc/adserver.ad.test@AD.TEST + * - svc1/adserver.ad.test@AD.TEST to svc2/adserver.ad.test@AD.TEST then + * to longsvc/adserver.ad.test@AD.TEST + */ +static uint8_t s4u_di_short[] = { + 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xa0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x2a, 0x00, 0x2c, 0x00, + 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x73, 0x00, 0x76, 0x00, 0x63, 0x00, 0x32, 0x00, 0x2f, 0x00, 0x61, 0x00, + 0x64, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, + 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x3a, 0x00, 0x3c, 0x00, 0x0c, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x73, 0x00, 0x76, 0x00, + 0x63, 0x00, 0x31, 0x00, 0x2f, 0x00, 0x61, 0x00, 0x64, 0x00, 0x73, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, + 0x61, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, + 0x74, 0x00, 0x40, 0x00, 0x41, 0x00, 0x44, 0x00, 0x2e, 0x00, 0x54, 0x00, + 0x45, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00, +}; + +static uint8_t s4u_di_long[] = { + 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xa8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x6c, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x73, 0x00, 0x76, 0x00, + 0x63, 0x00, 0x2f, 0x00, 0x61, 0x00, 0x64, 0x00, 0x73, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x61, 0x00, + 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x3c, 0x00, 0x0c, 0x00, 0x02, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, + 0x73, 0x00, 0x76, 0x00, 0x63, 0x00, 0x31, 0x00, 0x2f, 0x00, 0x61, 0x00, + 0x64, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, + 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x40, 0x00, 0x41, 0x00, 0x44, 0x00, + 0x2e, 0x00, 0x54, 0x00, 0x45, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +static uint8_t s4u_di_double[] = { + 0x01, 0x10, 0x08, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0x00, 0x32, 0x00, + 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x6c, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x73, 0x00, 0x76, 0x00, + 0x63, 0x00, 0x2f, 0x00, 0x61, 0x00, 0x64, 0x00, 0x73, 0x00, 0x65, 0x00, + 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x61, 0x00, + 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x3c, 0x00, 0x0c, 0x00, 0x02, 0x00, + 0x3a, 0x00, 0x3c, 0x00, 0x10, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x73, 0x00, 0x76, 0x00, + 0x63, 0x00, 0x31, 0x00, 0x2f, 0x00, 0x61, 0x00, 0x64, 0x00, 0x73, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, + 0x61, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, + 0x74, 0x00, 0x40, 0x00, 0x41, 0x00, 0x44, 0x00, 0x2e, 0x00, 0x54, 0x00, + 0x45, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x73, 0x00, 0x76, 0x00, + 0x63, 0x00, 0x32, 0x00, 0x2f, 0x00, 0x61, 0x00, 0x64, 0x00, 0x73, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, + 0x61, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, + 0x74, 0x00, 0x40, 0x00, 0x41, 0x00, 0x44, 0x00, 0x2e, 0x00, 0x54, 0x00, + 0x45, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static uint8_t fuzz1[] = { + 0x01, 0x10, 0x08, 0x20, 0x20, 0x20, 0x20, 0x20, 0x24, 0x00, 0x00, 0x00, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xff, 0xff, 0xff, + 0xff, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x20, 0x20, 0x20 +}; + +static uint8_t fuzz2[] = { + 0x01, 0x10, 0x08, 0x00, 0x00, 0xff, 0xff, 0xff, 0x24, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x16, 0x00, 0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1e +}; + +static void +test_dec_enc(uint8_t *blob, size_t len, char *name, int fail) +{ + krb5_data data_in, data_out; + struct pac_s4u_delegation_info *di = NULL; + krb5_error_code ret; + int eq; + size_t i; + + printf("Checking blob %s...\n", name); + + data_in = make_data(blob, len); + ret = ndr_dec_delegation_info(&data_in, &di); + if (fail) { + if (!ret) { + printf("%s: unexpected decode success\n", name); + exit(1); + } + printf("%s: failed as expected\n", name); + return; + } else if (ret) { + printf("%s: bad decode (%d): %s\n", name, ret, strerror(ret)); + exit(1); + } + + printf("%s, %d\n", di->proxy_target, di->transited_services_length); + for (i = 0; i < di->transited_services_length; i++) + printf(" %s\n", di->transited_services[i]); + + ret = ndr_enc_delegation_info(di, &data_out); + ndr_free_delegation_info(di); + if (ret) { + printf("%s: bad encode (%d): %s\n", name, ret, strerror(ret)); + exit(1); + } + + eq = data_eq(data_in, data_out); + krb5_free_data_contents(NULL, &data_out); + if (!eq) { + printf("%s: re-encoding did not produce the same result\n", name); + exit(1); + } + + printf("%s matched\n\n", name); +} + +#define RUN_TEST(blob) test_dec_enc(blob, sizeof(blob), #blob, 0) +#define RUN_TEST_FAIL(blob) test_dec_enc(blob, sizeof(blob), #blob, 1) + +int +main() +{ + printf("Running NDR tests...\n"); + + RUN_TEST(s4u_di_short); + RUN_TEST(s4u_di_long); + RUN_TEST(s4u_di_double); + RUN_TEST_FAIL(fuzz1); + RUN_TEST_FAIL(fuzz2); + + printf("Passed NDR tests\n"); + return 0; +} diff --git a/krb5-1.21.3/src/kdc/t_replay.c b/krb5-1.21.3/src/kdc/t_replay.c new file mode 100644 index 00000000..57aad886 --- /dev/null +++ b/krb5-1.21.3/src/kdc/t_replay.c @@ -0,0 +1,619 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/t_replay.c - tests for replay.c */ +/* + * Copyright (C) 2016 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. + */ + +/* + * Unit tests for the lookaside cache in replay.c + */ + +#ifndef NOCACHE + +#include "k5-cmocka.h" + +/* For wrapping functions */ +#include "k5-int.h" +#include "krb5.h" + +/* + * Wrapper functions + */ + +static krb5_error_code +__wrap_krb5_timeofday(krb5_context context, krb5_timestamp *timeret) +{ + *timeret = (krb5_timestamp)mock(); + return (krb5_error_code)mock(); +} + +#define krb5_timeofday __wrap_krb5_timeofday + +#include "replay.c" + +#undef krb5_timeofday + +#define SEED 0x6F03A219 +#define replay_unit_test(fn) \ + cmocka_unit_test_setup_teardown(fn, setup_lookaside, destroy_lookaside) + +/* + * Helper functions + */ + +static void +time_return(krb5_timestamp time, krb5_error_code err) +{ + will_return(__wrap_krb5_timeofday, time); + will_return(__wrap_krb5_timeofday, err); +} + +/* + * setup/teardown functions + */ + +static int +global_setup(void **state) +{ + krb5_error_code ret; + krb5_context context = NULL; + + ret = krb5_init_context(&context); + if (ret) + return ret; + + *state = context; + return 0; +} + +static int +global_teardown(void **state) +{ + krb5_free_context(*state); + return 0; +} + +static int +setup_lookaside(void **state) +{ + krb5_error_code ret; + krb5_context context = *state; + + ret = kdc_init_lookaside(context); + if (ret) + return ret; + + /* Ensure some vars are all set to initial values */ + hits = 0; + calls = 0; + max_hits_per_entry = 0; + num_entries = 0; + total_size = 0; + + return 0; +} + +static int +destroy_lookaside(void **state) +{ + kdc_free_lookaside(*state); + return 0; +} + +/* + * entry_size tests + */ + +static void +test_entry_size_no_response(void **state) +{ + size_t result; + const krb5_data req = string2data("I'm a test request"); + + result = entry_size(&req, NULL); + assert_int_equal(result, sizeof(struct entry) + 18); +} + +static void +test_entry_size_w_response(void **state) +{ + size_t result; + const krb5_data req = string2data("I'm a test request"); + const krb5_data rep = string2data("I'm a test response"); + + result = entry_size(&req, &rep); + assert_int_equal(result, sizeof(struct entry) + 18 + 19); +} + +/* + * insert_entry tests + */ + +static void +test_insert_entry(void **state) +{ + struct entry *e; + krb5_context context = *state; + krb5_data req = string2data("I'm a test request"); + krb5_data rep = string2data("I'm a test response"); + + e = insert_entry(context, &req, &rep, 15); + + assert_ptr_equal(k5_hashtab_get(hash_table, req.data, req.length), e); + assert_ptr_equal(K5_TAILQ_FIRST(&expiration_queue), e); + assert_true(data_eq(e->req_packet, req)); + assert_true(data_eq(e->reply_packet, rep)); + assert_int_equal(e->timein, 15); +} + +static void +test_insert_entry_no_response(void **state) +{ + struct entry *e; + krb5_context context = *state; + krb5_data req = string2data("I'm a test request"); + + e = insert_entry(context, &req, NULL, 10); + + assert_ptr_equal(k5_hashtab_get(hash_table, req.data, req.length), e); + assert_ptr_equal(K5_TAILQ_FIRST(&expiration_queue), e); + assert_true(data_eq(e->req_packet, req)); + assert_int_equal(e->reply_packet.length, 0); + assert_int_equal(e->timein, 10); +} + +static void +test_insert_entry_multiple(void **state) +{ + struct entry *e1, *e2; + krb5_context context = *state; + krb5_data req1 = string2data("I'm a test request"); + krb5_data rep1 = string2data("I'm a test response"); + krb5_data req2 = string2data("I'm a different test request"); + + e1 = insert_entry(context, &req1, &rep1, 20); + + assert_ptr_equal(k5_hashtab_get(hash_table, req1.data, req1.length), e1); + assert_ptr_equal(K5_TAILQ_FIRST(&expiration_queue), e1); + assert_true(data_eq(e1->req_packet, req1)); + assert_true(data_eq(e1->reply_packet, rep1)); + assert_int_equal(e1->timein, 20); + + e2 = insert_entry(context, &req2, NULL, 30); + + assert_ptr_equal(k5_hashtab_get(hash_table, req2.data, req2.length), e2); + assert_ptr_equal(K5_TAILQ_LAST(&expiration_queue,entry_queue), e2); + assert_true(data_eq(e2->req_packet, req2)); + assert_int_equal(e2->reply_packet.length, 0); + assert_int_equal(e2->timein, 30); +} + +/* + * discard_entry tests + */ + +static void +test_discard_entry(void **state) +{ + struct entry *e; + krb5_context context = *state; + krb5_data req = string2data("I'm a test request"); + krb5_data rep = string2data("I'm a test response"); + + e = insert_entry(context, &req, &rep, 0); + discard_entry(context, e); + + assert_null(k5_hashtab_get(hash_table, req.data, req.length)); + assert_int_equal(num_entries, 0); + assert_int_equal(total_size, 0); +} + +static void +test_discard_entry_no_response(void **state) +{ + struct entry *e; + krb5_context context = *state; + krb5_data req = string2data("I'm a test request"); + + e = insert_entry(context, &req, NULL, 0); + discard_entry(context, e); + + assert_null(k5_hashtab_get(hash_table, req.data, req.length)); + assert_int_equal(num_entries, 0); + assert_int_equal(total_size, 0); +} + +/* + * kdc_remove_lookaside tests + */ + +static void +test_kdc_remove_lookaside(void **state) +{ + krb5_context context = *state; + krb5_data req = string2data("I'm a test request"); + krb5_data rep = string2data("I'm a test response"); + + insert_entry(context, &req, &rep, 0); + kdc_remove_lookaside(context, &req); + + assert_null(k5_hashtab_get(hash_table, req.data, req.length)); + assert_int_equal(num_entries, 0); + assert_int_equal(total_size, 0); +} + +static void +test_kdc_remove_lookaside_empty_cache(void **state) +{ + krb5_context context = *state; + krb5_data req = string2data("I'm a test request"); + + assert_int_equal(num_entries, 0); + kdc_remove_lookaside(context, &req); + + assert_int_equal(num_entries, 0); + assert_int_equal(total_size, 0); +} + +static void +test_kdc_remove_lookaside_unknown(void **state) +{ + struct entry *e; + krb5_context context = *state; + krb5_data req1 = string2data("I'm a test request"); + krb5_data rep1 = string2data("I'm a test response"); + krb5_data req2 = string2data("I'm a different test request"); + + e = insert_entry(context, &req1, &rep1, 0); + kdc_remove_lookaside(context, &req2); + + assert_ptr_equal(k5_hashtab_get(hash_table, req1.data, req1.length), e); + assert_int_equal(num_entries, 1); + assert_int_equal(total_size, entry_size(&req1, &rep1)); +} + +static void +test_kdc_remove_lookaside_multiple(void **state) +{ + struct entry *e1; + krb5_context context = *state; + krb5_data req1 = string2data("I'm a test request"); + krb5_data rep1 = string2data("I'm a test response"); + krb5_data req2 = string2data("I'm a different test request"); + + e1 = insert_entry(context, &req1, &rep1, 0); + insert_entry(context, &req2, NULL, 0); + + kdc_remove_lookaside(context, &req2); + + assert_null(k5_hashtab_get(hash_table, req2.data, req2.length)); + assert_ptr_equal(k5_hashtab_get(hash_table, req1.data, req1.length), e1); + assert_int_equal(num_entries, 1); + assert_int_equal(total_size, entry_size(&req1, &rep1)); + + kdc_remove_lookaside(context, &req1); + + assert_null(k5_hashtab_get(hash_table, req1.data, req1.length)); + assert_int_equal(num_entries, 0); + assert_int_equal(total_size, 0); +} + +/* + * kdc_check_lookaside tests + */ + +static void +test_kdc_check_lookaside_hit(void **state) +{ + struct entry *e; + krb5_boolean result; + krb5_data *result_data; + krb5_context context = *state; + krb5_data req = string2data("I'm a test request"); + krb5_data rep = string2data("I'm a test response"); + + e = insert_entry(context, &req, &rep, 0); + + result = kdc_check_lookaside(context, &req, &result_data); + + assert_true(result); + assert_true(data_eq(rep, *result_data)); + assert_int_equal(hits, 1); + assert_int_equal(e->num_hits, 1); + + krb5_free_data(context, result_data); +} + +static void +test_kdc_check_lookaside_no_hit(void **state) +{ + krb5_boolean result; + krb5_data *result_data; + krb5_context context = *state; + krb5_data req = string2data("I'm a test request"); + + result = kdc_check_lookaside(context, &req, &result_data); + + assert_false(result); + assert_null(result_data); + assert_int_equal(hits, 0); +} + +static void +test_kdc_check_lookaside_empty(void **state) +{ + krb5_boolean result; + krb5_data *result_data; + krb5_context context = *state; + krb5_data req = string2data("I'm a test request"); + + /* Set result_data so we can verify that it is reset to NULL. */ + result_data = &req; + result = kdc_check_lookaside(context, &req, &result_data); + + assert_false(result); + assert_null(result_data); + assert_int_equal(hits, 0); +} + +static void +test_kdc_check_lookaside_no_response(void **state) +{ + struct entry *e; + krb5_boolean result; + krb5_data *result_data; + krb5_context context = *state; + krb5_data req = string2data("I'm a test request"); + + e = insert_entry(context, &req, NULL, 0); + + /* Set result_data so we can verify that it is reset to NULL. */ + result_data = &req; + result = kdc_check_lookaside(context, &req, &result_data); + + assert_true(result); + assert_null(result_data); + assert_int_equal(hits, 1); + assert_int_equal(e->num_hits, 1); +} + +static void +test_kdc_check_lookaside_hit_multiple(void **state) +{ + struct entry *e1, *e2; + krb5_boolean result; + krb5_data *result_data; + krb5_context context = *state; + krb5_data req1 = string2data("I'm a test request"); + krb5_data rep1 = string2data("I'm a test response"); + krb5_data req2 = string2data("I'm a different test request"); + + e1 = insert_entry(context, &req1, &rep1, 0); + e2 = insert_entry(context, &req2, NULL, 0); + + result = kdc_check_lookaside(context, &req1, &result_data); + + assert_true(result); + assert_true(data_eq(rep1, *result_data)); + assert_int_equal(hits, 1); + assert_int_equal(e1->num_hits, 1); + assert_int_equal(e2->num_hits, 0); + + krb5_free_data(context, result_data); + + /* Set result_data so we can verify that it is reset to NULL. */ + result_data = &req1; + result = kdc_check_lookaside(context, &req2, &result_data); + + assert_true(result); + assert_null(result_data); + assert_int_equal(hits, 2); + assert_int_equal(e1->num_hits, 1); + assert_int_equal(e2->num_hits, 1); +} + +/* + * kdc_insert_lookaside tests + */ + +static void +test_kdc_insert_lookaside_single(void **state) +{ + krb5_context context = *state; + krb5_data req = string2data("I'm a test request"); + krb5_data rep = string2data("I'm a test response"); + struct entry *hash_ent, *exp_ent; + + time_return(0, 0); + kdc_insert_lookaside(context, &req, &rep); + + hash_ent = k5_hashtab_get(hash_table, req.data, req.length); + assert_non_null(hash_ent); + assert_true(data_eq(hash_ent->req_packet, req)); + assert_true(data_eq(hash_ent->reply_packet, rep)); + exp_ent = K5_TAILQ_FIRST(&expiration_queue); + assert_true(data_eq(exp_ent->req_packet, req)); + assert_true(data_eq(exp_ent->reply_packet, rep)); + assert_int_equal(num_entries, 1); + assert_int_equal(total_size, entry_size(&req, &rep)); +} + +static void +test_kdc_insert_lookaside_no_reply(void **state) +{ + krb5_context context = *state; + krb5_data req = string2data("I'm a test request"); + struct entry *hash_ent, *exp_ent; + + time_return(0, 0); + kdc_insert_lookaside(context, &req, NULL); + + hash_ent = k5_hashtab_get(hash_table, req.data, req.length); + assert_non_null(hash_ent); + assert_true(data_eq(hash_ent->req_packet, req)); + assert_int_equal(hash_ent->reply_packet.length, 0); + exp_ent = K5_TAILQ_FIRST(&expiration_queue); + assert_true(data_eq(exp_ent->req_packet, req)); + assert_int_equal(exp_ent->reply_packet.length, 0); + assert_int_equal(num_entries, 1); + assert_int_equal(total_size, entry_size(&req, NULL)); +} + +static void +test_kdc_insert_lookaside_multiple(void **state) +{ + krb5_context context = *state; + krb5_data req1 = string2data("I'm a test request"); + krb5_data rep1 = string2data("I'm a test response"); + size_t e1_size = entry_size(&req1, &rep1); + krb5_data req2 = string2data("I'm a different test request"); + size_t e2_size = entry_size(&req2, NULL); + struct entry *hash1_ent, *hash2_ent, *exp_first, *exp_last; + + time_return(0, 0); + kdc_insert_lookaside(context, &req1, &rep1); + + hash1_ent = k5_hashtab_get(hash_table, req1.data, req1.length); + assert_non_null(hash1_ent); + assert_true(data_eq(hash1_ent->req_packet, req1)); + assert_true(data_eq(hash1_ent->reply_packet, rep1)); + exp_first = K5_TAILQ_FIRST(&expiration_queue); + assert_true(data_eq(exp_first->req_packet, req1)); + assert_true(data_eq(exp_first->reply_packet, rep1)); + assert_int_equal(num_entries, 1); + assert_int_equal(total_size, e1_size); + + time_return(0, 0); + kdc_insert_lookaside(context, &req2, NULL); + + hash2_ent = k5_hashtab_get(hash_table, req2.data, req2.length); + assert_non_null(hash2_ent); + assert_true(data_eq(hash2_ent->req_packet, req2)); + assert_int_equal(hash2_ent->reply_packet.length, 0); + exp_last = K5_TAILQ_LAST(&expiration_queue, entry_queue); + assert_true(data_eq(exp_last->req_packet, req2)); + assert_int_equal(exp_last->reply_packet.length, 0); + assert_int_equal(num_entries, 2); + assert_int_equal(total_size, e1_size + e2_size); +} + +static void +test_kdc_insert_lookaside_cache_expire(void **state) +{ + struct entry *e; + krb5_context context = *state; + krb5_data req1 = string2data("I'm a test request"); + krb5_data rep1 = string2data("I'm a test response"); + size_t e1_size = entry_size(&req1, &rep1); + krb5_data req2 = string2data("I'm a different test request"); + size_t e2_size = entry_size(&req2, NULL); + struct entry *hash1_ent, *hash2_ent, *exp_ent; + + time_return(0, 0); + kdc_insert_lookaside(context, &req1, &rep1); + + hash1_ent = k5_hashtab_get(hash_table, req1.data, req1.length); + assert_non_null(hash1_ent); + assert_true(data_eq(hash1_ent->req_packet, req1)); + assert_true(data_eq(hash1_ent->reply_packet, rep1)); + exp_ent = K5_TAILQ_FIRST(&expiration_queue); + assert_true(data_eq(exp_ent->req_packet, req1)); + assert_true(data_eq(exp_ent->reply_packet, rep1)); + assert_int_equal(num_entries, 1); + assert_int_equal(total_size, e1_size); + + /* Increase hits on entry */ + e = k5_hashtab_get(hash_table, req1.data, req1.length); + assert_non_null(e); + e->num_hits = 5; + + time_return(STALE_TIME + 1, 0); + kdc_insert_lookaside(context, &req2, NULL); + + assert_null(k5_hashtab_get(hash_table, req1.data, req1.length)); + assert_int_equal(max_hits_per_entry, 5); + + hash2_ent = k5_hashtab_get(hash_table, req2.data, req2.length); + assert_non_null(hash2_ent); + assert_true(data_eq(hash2_ent->req_packet, req2)); + assert_int_equal(hash2_ent-> reply_packet.length, 0); + exp_ent = K5_TAILQ_FIRST(&expiration_queue); + assert_true(data_eq(exp_ent->req_packet, req2)); + assert_int_equal(exp_ent->reply_packet.length, 0); + assert_int_equal(num_entries, 1); + assert_int_equal(total_size, e2_size); +} + +int main() +{ + int ret; + + const struct CMUnitTest replay_tests[] = { + /* entry_size tests */ + replay_unit_test(test_entry_size_no_response), + replay_unit_test(test_entry_size_w_response), + /* insert_entry tests */ + replay_unit_test(test_insert_entry), + replay_unit_test(test_insert_entry_no_response), + replay_unit_test(test_insert_entry_multiple), + /* discard_entry tests */ + replay_unit_test(test_discard_entry), + replay_unit_test(test_discard_entry_no_response), + /* kdc_remove_lookaside tests */ + replay_unit_test(test_kdc_remove_lookaside), + replay_unit_test(test_kdc_remove_lookaside_empty_cache), + replay_unit_test(test_kdc_remove_lookaside_unknown), + replay_unit_test(test_kdc_remove_lookaside_multiple), + /* kdc_check_lookaside tests */ + replay_unit_test(test_kdc_check_lookaside_hit), + replay_unit_test(test_kdc_check_lookaside_no_hit), + replay_unit_test(test_kdc_check_lookaside_empty), + replay_unit_test(test_kdc_check_lookaside_no_response), + replay_unit_test(test_kdc_check_lookaside_hit_multiple), + /* kdc_insert_lookaside tests */ + replay_unit_test(test_kdc_insert_lookaside_single), + replay_unit_test(test_kdc_insert_lookaside_no_reply), + replay_unit_test(test_kdc_insert_lookaside_multiple), + replay_unit_test(test_kdc_insert_lookaside_cache_expire) + }; + + ret = cmocka_run_group_tests_name("replay_lookaside", replay_tests, + global_setup, global_teardown); + + return ret; +} + +#else /* NOCACHE */ + +int main() +{ + return 0; +} + +#endif /* NOCACHE */ diff --git a/krb5-1.21.3/src/kdc/t_workers.py b/krb5-1.21.3/src/kdc/t_workers.py new file mode 100755 index 00000000..8de3f34d --- /dev/null +++ b/krb5-1.21.3/src/kdc/t_workers.py @@ -0,0 +1,7 @@ +from k5test import * + +realm = K5Realm(start_kdc=False, create_host=False) +realm.start_kdc(['-w', '3']) +realm.kinit(realm.user_princ, password('user')) +realm.klist(realm.user_princ) +success('KDC worker processes') diff --git a/krb5-1.21.3/src/kdc/tgs_policy.c b/krb5-1.21.3/src/kdc/tgs_policy.c new file mode 100644 index 00000000..33a8242c --- /dev/null +++ b/krb5-1.21.3/src/kdc/tgs_policy.c @@ -0,0 +1,771 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kdc/tgs_policy.c */ +/* + * Copyright (C) 2012 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. + */ + +#include "k5-int.h" +#include "kdc_util.h" + +/* + * Routines that validate a TGS request; checks a lot of things. :-) + * + * Returns a Kerberos protocol error number, which is _not_ the same + * as a com_err error number! + */ + +struct tgsflagrule { + krb5_flags reqflags; /* Flag(s) in TGS-REQ */ + krb5_flags checkflag; /* Flags to check against */ + char *status; /* Status string */ + int err; /* Protocol error code */ +}; + +/* Service principal TGS policy checking functions */ +typedef int (check_tgs_svc_pol_fn)(krb5_kdc_req *, krb5_db_entry *, + krb5_ticket *, krb5_timestamp, + const char **); + +static check_tgs_svc_pol_fn check_tgs_svc_deny_opts; +static check_tgs_svc_pol_fn check_tgs_svc_deny_all; +static check_tgs_svc_pol_fn check_tgs_svc_reqd_flags; +static check_tgs_svc_pol_fn check_tgs_svc_time; + +static check_tgs_svc_pol_fn * const svc_pol_fns[] = { + check_tgs_svc_deny_opts, check_tgs_svc_deny_all, check_tgs_svc_reqd_flags, + check_tgs_svc_time +}; + +static const struct tgsflagrule tgsflagrules[] = { + { KDC_OPT_FORWARDED, TKT_FLG_FORWARDABLE, + "TGT NOT FORWARDABLE", KRB5KDC_ERR_BADOPTION }, + { KDC_OPT_PROXY, TKT_FLG_PROXIABLE, + "TGT NOT PROXIABLE", KRB5KDC_ERR_BADOPTION }, + { (KDC_OPT_ALLOW_POSTDATE | KDC_OPT_POSTDATED), TKT_FLG_MAY_POSTDATE, + "TGT NOT POSTDATABLE", KRB5KDC_ERR_BADOPTION }, + { KDC_OPT_VALIDATE, TKT_FLG_INVALID, + "VALIDATE VALID TICKET", KRB5KDC_ERR_BADOPTION }, + { KDC_OPT_RENEW, TKT_FLG_RENEWABLE, + "TICKET NOT RENEWABLE", KRB5KDC_ERR_BADOPTION } +}; + +/* + * Some TGS-REQ options require that the ticket have corresponding flags set. + */ +static krb5_error_code +check_tgs_opts(krb5_kdc_req *req, krb5_ticket *tkt, const char **status) +{ + size_t i; + size_t nrules = sizeof(tgsflagrules) / sizeof(tgsflagrules[0]); + const struct tgsflagrule *r; + + for (i = 0; i < nrules; i++) { + r = &tgsflagrules[i]; + if (r->reqflags & req->kdc_options) { + if (!(r->checkflag & tkt->enc_part2->flags)) { + *status = r->status; + return r->err; + } + } + } + + if (isflagset(tkt->enc_part2->flags, TKT_FLG_INVALID) && + !isflagset(req->kdc_options, KDC_OPT_VALIDATE)) { + *status = "TICKET NOT VALID"; + return KRB5KRB_AP_ERR_TKT_NYV; + } + + return 0; +} + +static const struct tgsflagrule svcdenyrules[] = { + { KDC_OPT_RENEWABLE, KRB5_KDB_DISALLOW_RENEWABLE, + "NON-RENEWABLE TICKET", KRB5KDC_ERR_POLICY }, + { KDC_OPT_ALLOW_POSTDATE, KRB5_KDB_DISALLOW_POSTDATED, + "NON-POSTDATABLE TICKET", KRB5KDC_ERR_CANNOT_POSTDATE }, + { KDC_OPT_ENC_TKT_IN_SKEY, KRB5_KDB_DISALLOW_DUP_SKEY, + "DUP_SKEY DISALLOWED", KRB5KDC_ERR_POLICY } +}; + +/* + * A service principal can forbid some TGS-REQ options. + */ +static krb5_error_code +check_tgs_svc_deny_opts(krb5_kdc_req *req, krb5_db_entry *server, + krb5_ticket *tkt, krb5_timestamp kdc_time, + const char **status) +{ + size_t i; + size_t nrules = sizeof(svcdenyrules) / sizeof(svcdenyrules[0]); + const struct tgsflagrule *r; + + for (i = 0; i < nrules; i++) { + r = &svcdenyrules[i]; + if (!(r->reqflags & req->kdc_options)) + continue; + if (r->checkflag & server->attributes) { + *status = r->status; + return r->err; + } + } + return 0; +} + +/* + * A service principal can deny all TGS-REQs for it. + */ +static krb5_error_code +check_tgs_svc_deny_all(krb5_kdc_req *req, krb5_db_entry *server, + krb5_ticket *tkt, krb5_timestamp kdc_time, + const char **status) +{ + if (server->attributes & KRB5_KDB_DISALLOW_ALL_TIX) { + *status = "SERVER LOCKED OUT"; + return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + } + if ((server->attributes & KRB5_KDB_DISALLOW_SVR) && + !(req->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY)) { + *status = "SERVER NOT ALLOWED"; + return KRB5KDC_ERR_MUST_USE_USER2USER; + } + if (server->attributes & KRB5_KDB_DISALLOW_TGT_BASED) { + if (krb5_is_tgs_principal(tkt->server)) { + *status = "TGT BASED NOT ALLOWED"; + return KRB5KDC_ERR_POLICY; + } + } + return 0; +} + +/* + * A service principal can require certain TGT flags. + */ +static krb5_error_code +check_tgs_svc_reqd_flags(krb5_kdc_req *req, krb5_db_entry *server, + krb5_ticket *tkt, + krb5_timestamp kdc_time, const char **status) +{ + if (server->attributes & KRB5_KDB_REQUIRES_HW_AUTH) { + if (!(tkt->enc_part2->flags & TKT_FLG_HW_AUTH)) { + *status = "NO HW PREAUTH"; + return KRB5KRB_ERR_GENERIC; + } + } + if (server->attributes & KRB5_KDB_REQUIRES_PRE_AUTH) { + if (!(tkt->enc_part2->flags & TKT_FLG_PRE_AUTH)) { + *status = "NO PREAUTH"; + return KRB5KRB_ERR_GENERIC; + } + } + return 0; +} + +static krb5_error_code +check_tgs_svc_time(krb5_kdc_req *req, krb5_db_entry *server, krb5_ticket *tkt, + krb5_timestamp kdc_time, const char **status) +{ + if (server->expiration && ts_after(kdc_time, server->expiration)) { + *status = "SERVICE EXPIRED"; + return KRB5KDC_ERR_SERVICE_EXP; + } + return 0; +} + +static krb5_error_code +check_tgs_svc_policy(krb5_kdc_req *req, krb5_db_entry *server, + krb5_ticket *tkt, krb5_timestamp kdc_time, + const char **status) +{ + int errcode; + size_t i; + size_t nfns = sizeof(svc_pol_fns) / sizeof(svc_pol_fns[0]); + + for (i = 0; i < nfns; i++) { + errcode = svc_pol_fns[i](req, server, tkt, kdc_time, status); + if (errcode != 0) + return errcode; + } + return 0; +} + +/* + * Check header ticket timestamps against the current time. + */ +static krb5_error_code +check_tgs_times(krb5_kdc_req *req, krb5_ticket_times *times, + krb5_timestamp kdc_time, const char **status) +{ + krb5_timestamp starttime; + + /* For validating a postdated ticket, check the start time vs. the + KDC time. */ + if (req->kdc_options & KDC_OPT_VALIDATE) { + starttime = times->starttime ? times->starttime : times->authtime; + if (ts_after(starttime, kdc_time)) { + *status = "NOT_YET_VALID"; + return KRB5KRB_AP_ERR_TKT_NYV; + } + } + /* + * Check the renew_till time. The endtime was already + * been checked in the initial authentication check. + */ + if ((req->kdc_options & KDC_OPT_RENEW) && + ts_after(kdc_time, times->renew_till)) { + *status = "TKT_EXPIRED"; + return KRB5KRB_AP_ERR_TKT_EXPIRED; + } + return 0; +} + +/* Check for local user tickets issued by foreign realms. This check is + * skipped for S4U2Self requests. */ +static krb5_error_code +check_tgs_lineage(krb5_db_entry *server, krb5_ticket *tkt, + krb5_boolean is_crossrealm, const char **status) +{ + if (is_crossrealm && data_eq(tkt->enc_part2->client->realm, + server->princ->realm)) { + *status = "INVALID LINEAGE"; + return KRB5KDC_ERR_POLICY; + } + return 0; +} + +static krb5_error_code +check_tgs_s4u2self(kdc_realm_t *realm, krb5_kdc_req *req, + krb5_db_entry *server, krb5_ticket *tkt, krb5_pac pac, + krb5_timestamp kdc_time, + krb5_pa_s4u_x509_user *s4u_x509_user, krb5_db_entry *client, + krb5_boolean is_crossrealm, krb5_boolean is_referral, + const char **status, krb5_pa_data ***e_data) +{ + krb5_context context = realm->realm_context; + krb5_db_entry empty_server = { 0 }; + + /* If the server is local, check that the request is for self. */ + if (!is_referral && + !is_client_db_alias(context, server, tkt->enc_part2->client)) { + *status = "INVALID_S4U2SELF_REQUEST_SERVER_MISMATCH"; + return KRB5KRB_AP_ERR_BADMATCH; + } + + /* S4U2Self requests must use options valid for AS requests. */ + if (req->kdc_options & AS_INVALID_OPTIONS) { + *status = "INVALID S4U2SELF OPTIONS"; + return KRB5KDC_ERR_BADOPTION; + } + + /* + * Valid S4U2Self requests can occur in the following combinations: + * + * (1) local TGT, local user, local server + * (2) cross TGT, local user, issuing referral + * (3) cross TGT, non-local user, issuing referral + * (4) cross TGT, non-local user, local server + * + * The first case is for a single-realm S4U2Self scenario; the second, + * third, and fourth cases are for the initial, intermediate (if any), and + * final cross-realm requests in a multi-realm scenario. + */ + + if (!is_crossrealm && is_referral) { + /* This could happen if the requesting server no longer exists, and we + * found a referral instead. Treat this as a server lookup failure. */ + *status = "LOOKING_UP_SERVER"; + return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + } + if (client != NULL && is_crossrealm && !is_referral) { + /* A local server should not need a cross-realm TGT to impersonate + * a local principal. */ + *status = "NOT_CROSS_REALM_REQUEST"; + return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; /* match Windows error */ + } + if (client == NULL && !is_crossrealm) { + /* + * The server is asking to impersonate a principal from another realm, + * using a local TGT. It should instead ask that principal's realm and + * follow referrals back to us. + */ + *status = "S4U2SELF_CLIENT_NOT_OURS"; + return KRB5KDC_ERR_POLICY; /* match Windows error */ + } + if (client == NULL && s4u_x509_user->user_id.user->length == 0) { + /* + * Only a KDC in the client realm can handle a certificate-only + * S4U2Self request. Other KDCs require a principal name and ignore + * the subject-certificate field. + */ + *status = "INVALID_XREALM_S4U2SELF_REQUEST"; + return KRB5KDC_ERR_POLICY; /* match Windows error */ + } + + /* The header ticket PAC must be present. */ + if (pac == NULL) { + *status = "S4U2SELF_NO_PAC"; + return KRB5KDC_ERR_TGT_REVOKED; + } + + if (client != NULL) { + /* The header ticket PAC must be for the impersonator. */ + if (krb5_pac_verify(context, pac, tkt->enc_part2->times.authtime, + tkt->enc_part2->client, NULL, NULL) != 0) { + *status = "S4U2SELF_LOCAL_PAC_CLIENT"; + return KRB5KDC_ERR_BADOPTION; + } + + /* Validate the client policy. Use an empty server principal to bypass + * server policy checks. */ + return validate_as_request(realm, req, client, &empty_server, kdc_time, + status, e_data); + } else { + /* The header ticket PAC must be for the subject, with realm. */ + if (krb5_pac_verify_ext(context, pac, tkt->enc_part2->times.authtime, + s4u_x509_user->user_id.user, NULL, NULL, + TRUE) != 0) { + *status = "S4U2SELF_FOREIGN_PAC_CLIENT"; + return KRB5KDC_ERR_BADOPTION; + } + } + + return 0; +} + +/* + * Validate pac as an S4U2Proxy subject PAC contained within a cross-realm TGT. + * If target_server is non-null, verify that it matches the PAC proxy target. + * Return 0 on success, non-zero on failure. + */ +static int +verify_deleg_pac(krb5_context context, krb5_pac pac, + krb5_enc_tkt_part *enc_tkt, + krb5_const_principal target_server) +{ + krb5_timestamp pac_authtime; + krb5_data deleg_buf = empty_data(); + krb5_principal princ = NULL; + struct pac_s4u_delegation_info *di = NULL; + char *client_str = NULL, *target_str = NULL; + const char *last_transited; + int result = -1; + + /* Make sure the PAC client string can be parsed as a principal with + * realm. */ + if (get_pac_princ_with_realm(context, pac, &princ, &pac_authtime) != 0) + goto cleanup; + if (pac_authtime != enc_tkt->times.authtime) + goto cleanup; + + if (krb5_pac_get_buffer(context, pac, KRB5_PAC_DELEGATION_INFO, + &deleg_buf) != 0) + goto cleanup; + + if (ndr_dec_delegation_info(&deleg_buf, &di) != 0) + goto cleanup; + + if (target_server != NULL) { + if (krb5_unparse_name_flags(context, target_server, + KRB5_PRINCIPAL_UNPARSE_DISPLAY | + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &target_str) != 0) + goto cleanup; + if (strcmp(target_str, di->proxy_target) != 0) + goto cleanup; + } + + /* Check that the most recently added PAC transited service matches the + * requesting impersonator. */ + if (di->transited_services_length == 0) + goto cleanup; + if (krb5_unparse_name(context, enc_tkt->client, &client_str) != 0) + goto cleanup; + last_transited = di->transited_services[di->transited_services_length - 1]; + if (strcmp(last_transited, client_str) != 0) + goto cleanup; + + result = 0; + +cleanup: + free(target_str); + free(client_str); + ndr_free_delegation_info(di); + krb5_free_principal(context, princ); + krb5_free_data_contents(context, &deleg_buf); + return result; +} + +static krb5_error_code +check_tgs_s4u2proxy(krb5_context context, krb5_kdc_req *req, + krb5_db_entry *server, krb5_ticket *tkt, krb5_pac pac, + const krb5_ticket *stkt, krb5_pac stkt_pac, + krb5_db_entry *stkt_server, krb5_boolean is_crossrealm, + krb5_boolean is_referral, const char **status) +{ + /* A forwardable second ticket must be present in the request. */ + if (stkt == NULL) { + *status = "NO_2ND_TKT"; + return KRB5KDC_ERR_BADOPTION; + } + if (!(stkt->enc_part2->flags & TKT_FLG_FORWARDABLE)) { + *status = "EVIDENCE_TKT_NOT_FORWARDABLE"; + return KRB5KDC_ERR_BADOPTION; + } + + /* Constrained delegation is mutually exclusive with renew/forward/etc. + * (and therefore requires the header ticket to be a TGT). */ + if (req->kdc_options & (NON_TGT_OPTION | KDC_OPT_ENC_TKT_IN_SKEY)) { + *status = "INVALID_S4U2PROXY_OPTIONS"; + return KRB5KDC_ERR_BADOPTION; + } + + /* Can't get a TGT (otherwise it would be unconstrained delegation). */ + if (krb5_is_tgs_principal(req->server)) { + *status = "NOT_ALLOWED_TO_DELEGATE"; + return KRB5KDC_ERR_POLICY; + } + + /* The header ticket PAC must be present and for the impersonator. */ + if (pac == NULL) { + *status = "S4U2PROXY_NO_HEADER_PAC"; + return KRB5KDC_ERR_TGT_REVOKED; + } + if (krb5_pac_verify(context, pac, tkt->enc_part2->times.authtime, + tkt->enc_part2->client, NULL, NULL) != 0) { + *status = "S4U2PROXY_HEADER_PAC"; + return KRB5KDC_ERR_BADOPTION; + } + + /* + * An S4U2Proxy request must be an initial request to the impersonator's + * realm (possibly for a target resource in the same realm), or a final + * cross-realm RBCD request to the resource realm. Intermediate + * referral-chasing requests do not use the CNAME-IN-ADDL-TKT flag. + */ + + if (stkt_pac == NULL) { + *status = "S4U2PROXY_NO_STKT_PAC"; + return KRB5KRB_AP_ERR_MODIFIED; + } + if (!is_crossrealm) { + /* For an initial or same-realm request, the second ticket server and + * header ticket client must be the same principal. */ + if (!is_client_db_alias(context, stkt_server, + tkt->enc_part2->client)) { + *status = "EVIDENCE_TICKET_MISMATCH"; + return KRB5KDC_ERR_SERVER_NOMATCH; + } + + /* The second ticket client and PAC client are the subject, and must + * match. */ + if (krb5_pac_verify(context, stkt_pac, stkt->enc_part2->times.authtime, + stkt->enc_part2->client, NULL, NULL) != 0) { + *status = "S4U2PROXY_LOCAL_STKT_PAC"; + return KRB5KDC_ERR_BADOPTION; + } + + } else { + + /* + * For a cross-realm request, the second ticket must be a referral TGT + * to our realm with the impersonator as client. The target server + * must also be local, so we must not be issuing a referral. + */ + if (is_referral || !is_cross_tgs_principal(stkt_server->princ) || + !data_eq(stkt_server->princ->data[1], server->princ->realm) || + !krb5_principal_compare(context, stkt->enc_part2->client, + tkt->enc_part2->client)) { + *status = "XREALM_EVIDENCE_TICKET_MISMATCH"; + return KRB5KDC_ERR_BADOPTION; + } + + /* The second ticket PAC must be present and for the impersonated + * client, with delegation info. */ + if (stkt_pac == NULL || + verify_deleg_pac(context, stkt_pac, stkt->enc_part2, + req->server) != 0) { + *status = "S4U2PROXY_CROSS_STKT_PAC"; + return KRB5KDC_ERR_BADOPTION; + } + } + + return 0; +} + +/* Check the KDB policy for a final RBCD request. */ +static krb5_error_code +check_s4u2proxy_policy(krb5_context context, krb5_kdc_req *req, + krb5_principal desired_client, + krb5_principal impersonator_name, + krb5_db_entry *impersonator, krb5_pac impersonator_pac, + krb5_principal resource_name, krb5_db_entry *resource, + krb5_boolean is_crossrealm, krb5_boolean is_referral, + const char **status) +{ + krb5_error_code ret; + krb5_boolean support_rbcd, policy_denial = FALSE; + + /* Check if the client supports resource-based constrained delegation. */ + ret = kdc_get_pa_pac_rbcd(context, req->padata, &support_rbcd); + if (ret) + return ret; + + if (is_referral) { + if (!support_rbcd) { + /* The client must support RBCD for a referral to be useful. */ + *status = "UNSUPPORTED_S4U2PROXY_REQUEST"; + return KRB5KDC_ERR_BADOPTION; + } + /* Policy will be checked in the resource realm. */ + return 0; + } + + /* Try resource-based authorization if the client supports RBCD. */ + if (support_rbcd) { + ret = krb5_db_allowed_to_delegate_from(context, desired_client, + impersonator_name, + impersonator_pac, resource); + if (ret == KRB5KDC_ERR_BADOPTION) + policy_denial = TRUE; + else if (ret != KRB5_PLUGIN_OP_NOTSUPP) + return ret; + } + + /* Try traditional authorization if the requestor is in this realm. */ + if (!is_crossrealm) { + ret = krb5_db_check_allowed_to_delegate(context, desired_client, + impersonator, resource_name); + if (ret == KRB5KDC_ERR_BADOPTION) + policy_denial = TRUE; + else if (ret != KRB5_PLUGIN_OP_NOTSUPP) + return ret; + } + + *status = policy_denial ? "NOT_ALLOWED_TO_DELEGATE" : + "UNSUPPORTED_S4U2PROXY_REQUEST"; + return KRB5KDC_ERR_BADOPTION; +} + +static krb5_error_code +check_tgs_u2u(krb5_context context, krb5_kdc_req *req, const krb5_ticket *stkt, + krb5_db_entry *server, const char **status) +{ + /* A second ticket must be present in the request. */ + if (stkt == NULL) { + *status = "NO_2ND_TKT"; + return KRB5KDC_ERR_BADOPTION; + } + + /* The second ticket must be a TGT to the server realm. */ + if (!is_local_tgs_principal(stkt->server) || + !data_eq(stkt->server->data[1], server->princ->realm)) { + *status = "2ND_TKT_NOT_TGS"; + return KRB5KDC_ERR_POLICY; + } + + /* The second ticket client must match the requested server. */ + if (!is_client_db_alias(context, server, stkt->enc_part2->client)) { + *status = "2ND_TKT_MISMATCH"; + return KRB5KDC_ERR_SERVER_NOMATCH; + } + + return 0; +} + +/* Validate the PAC of a non-S4U TGS request, if one is present. */ +static krb5_error_code +check_normal_tgs_pac(krb5_context context, krb5_enc_tkt_part *enc_tkt, + krb5_pac pac, krb5_db_entry *server, + krb5_boolean is_crossrealm, const char **status) +{ + /* We don't require a PAC for regular TGS requests. */ + if (pac == NULL) + return 0; + + /* For most requests the header ticket PAC will be for the ticket + * client. */ + if (krb5_pac_verify(context, pac, enc_tkt->times.authtime, enc_tkt->client, + NULL, NULL) == 0) + return 0; + + /* For intermediate RBCD requests the header ticket PAC will be for the + * impersonated client. */ + if (is_crossrealm && is_cross_tgs_principal(server->princ) && + verify_deleg_pac(context, pac, enc_tkt, NULL) == 0) + return 0; + + *status = "HEADER_PAC"; + return KRB5KDC_ERR_BADOPTION; +} + +/* + * Some TGS-REQ options allow for a non-TGS principal in the ticket. Do some + * checks that are peculiar to these cases. (e.g., ticket service principal + * matches requested service principal) + */ +static krb5_error_code +check_tgs_nontgt(krb5_context context, krb5_kdc_req *req, krb5_ticket *tkt, + const char **status) +{ + if (!krb5_principal_compare(context, tkt->server, req->server)) { + *status = "SERVER DIDN'T MATCH TICKET FOR RENEW/FORWARD/ETC"; + return KRB5KDC_ERR_SERVER_NOMATCH; + } + /* Cannot proxy ticket granting tickets. */ + if ((req->kdc_options & KDC_OPT_PROXY) && + krb5_is_tgs_principal(req->server)) { + *status = "CAN'T PROXY TGT"; + return KRB5KDC_ERR_BADOPTION; + } + return 0; +} + +/* + * Do some checks for a normal TGS-REQ (where the ticket service must be a TGS + * principal). + */ +static krb5_error_code +check_tgs_tgt(krb5_kdc_req *req, krb5_ticket *tkt, const char **status) +{ + /* Make sure it's a TGS principal. */ + if (!krb5_is_tgs_principal(tkt->server)) { + *status = "BAD TGS SERVER NAME"; + return KRB5KRB_AP_ERR_NOT_US; + } + /* TGS principal second component must match service realm. */ + if (!data_eq(tkt->server->data[1], req->server->realm)) { + *status = "BAD TGS SERVER INSTANCE"; + return KRB5KRB_AP_ERR_NOT_US; + } + return 0; +} + +krb5_error_code +check_tgs_constraints(kdc_realm_t *realm, krb5_kdc_req *request, + krb5_db_entry *server, krb5_ticket *ticket, krb5_pac pac, + const krb5_ticket *stkt, krb5_pac stkt_pac, + krb5_db_entry *stkt_server, krb5_timestamp kdc_time, + krb5_pa_s4u_x509_user *s4u_x509_user, + krb5_db_entry *s4u2self_client, + krb5_boolean is_crossrealm, krb5_boolean is_referral, + const char **status, krb5_pa_data ***e_data) +{ + krb5_context context = realm->realm_context; + int errcode; + + /* Depends only on request and ticket. */ + errcode = check_tgs_opts(request, ticket, status); + if (errcode != 0) + return errcode; + + /* Depends only on request, ticket times, and current time. */ + errcode = check_tgs_times(request, &ticket->enc_part2->times, kdc_time, + status); + if (errcode != 0) + return errcode; + + if (request->kdc_options & NON_TGT_OPTION) + errcode = check_tgs_nontgt(context, request, ticket, status); + else + errcode = check_tgs_tgt(request, ticket, status); + if (errcode != 0) + return errcode; + + if (s4u_x509_user != NULL) { + errcode = check_tgs_s4u2self(realm, request, server, ticket, pac, + kdc_time, s4u_x509_user, s4u2self_client, + is_crossrealm, is_referral, status, + e_data); + } else { + errcode = check_tgs_lineage(server, ticket, is_crossrealm, status); + } + if (errcode != 0) + return errcode; + + if (request->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY) { + errcode = check_tgs_u2u(context, request, stkt, server, status); + if (errcode != 0) + return errcode; + } + + if (request->kdc_options & KDC_OPT_CNAME_IN_ADDL_TKT) { + errcode = check_tgs_s4u2proxy(context, request, server, ticket, pac, + stkt, stkt_pac, stkt_server, + is_crossrealm, is_referral, status); + if (errcode != 0) + return errcode; + } else if (s4u_x509_user == NULL) { + errcode = check_normal_tgs_pac(context, ticket->enc_part2, pac, server, + is_crossrealm, status); + if (errcode != 0) + return errcode; + } + + return 0; +} + +krb5_error_code +check_tgs_policy(kdc_realm_t *realm, krb5_kdc_req *request, + krb5_db_entry *server, krb5_ticket *ticket, + krb5_pac pac, const krb5_ticket *stkt, krb5_pac stkt_pac, + krb5_principal stkt_pac_client, krb5_db_entry *stkt_server, + krb5_timestamp kdc_time, krb5_boolean is_crossrealm, + krb5_boolean is_referral, const char **status, + krb5_pa_data ***e_data) +{ + krb5_context context = realm->realm_context; + int errcode; + krb5_error_code ret; + krb5_principal desired_client; + + errcode = check_tgs_svc_policy(request, server, ticket, kdc_time, status); + if (errcode != 0) + return errcode; + + if (request->kdc_options & KDC_OPT_CNAME_IN_ADDL_TKT) { + desired_client = (stkt_pac_client != NULL) ? stkt_pac_client : + stkt->enc_part2->client; + errcode = check_s4u2proxy_policy(context, request, desired_client, + ticket->enc_part2->client, + stkt_server, pac, request->server, + server, is_crossrealm, is_referral, + status); + if (errcode != 0) + return errcode; + } + + if (check_anon(realm, ticket->enc_part2->client, request->server) != 0) { + *status = "ANONYMOUS NOT ALLOWED"; + return KRB5KDC_ERR_POLICY; + } + + /* Perform KDB module policy checks. */ + ret = krb5_db_check_policy_tgs(context, request, server, ticket, status, + e_data); + return (ret == KRB5_PLUGIN_OP_NOTSUPP) ? 0 : ret; +} diff --git a/krb5-1.21.3/src/kprop/Makefile.in b/krb5-1.21.3/src/kprop/Makefile.in new file mode 100644 index 00000000..412d72a1 --- /dev/null +++ b/krb5-1.21.3/src/kprop/Makefile.in @@ -0,0 +1,35 @@ +mydir=kprop +BUILDTOP=$(REL).. + +all: kprop kpropd kproplog + +CLIENTSRCS= $(srcdir)/kprop.c $(srcdir)/kprop_util.c +CLIENTOBJS= kprop.o kprop_util.o + +SERVERSRCS= $(srcdir)/kpropd.c $(srcdir)/kpropd_rpc.c $(srcdir)/kprop_util.c +SERVEROBJS= kpropd.o kpropd_rpc.o kprop_util.o + +LOGSRCS= $(srcdir)/kproplog.c +LOGOBJS= kproplog.o + +SRCS= $(CLIENTSRCS) $(SERVERSRCS) $(LOGSRCS) + + +kprop: $(CLIENTOBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o kprop $(CLIENTOBJS) $(KRB5_BASE_LIBS) @LIBUTIL@ + +kpropd: $(SERVEROBJS) $(KDB5_DEPLIB) $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(APPUTILS_DEPLIB) + $(CC_LINK) -o kpropd $(SERVEROBJS) $(KDB5_LIB) $(KADMCLNT_LIBS) $(KRB5_BASE_LIBS) $(APPUTILS_LIB) @LIBUTIL@ + +kproplog: $(LOGOBJS) + $(CC_LINK) -o kproplog $(LOGOBJS) $(KADMSRV_LIBS) $(KRB5_BASE_LIBS) + +install: + for f in kprop kpropd kproplog; do \ + $(INSTALL_PROGRAM) $$f \ + $(DESTDIR)$(SERVER_BINDIR)/`echo $$f|sed '$(transform)'`; \ + done + +clean: + $(RM) $(CLIENTOBJS) $(SERVEROBJS) $(LOGOBJS) + $(RM) kprop kpropd kproplog diff --git a/krb5-1.21.3/src/kprop/deps b/krb5-1.21.3/src/kprop/deps new file mode 100644 index 00000000..cb19b0a6 --- /dev/null +++ b/krb5-1.21.3/src/kprop/deps @@ -0,0 +1,74 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kprop.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/fake-addrinfo.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kprop.c kprop.h +$(OUTPRE)kprop_util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kprop.h kprop_util.c +$(OUTPRE)kpropd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/fake-addrinfo.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/iprop.h $(top_srcdir)/include/iprop_hdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/kdb_log.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kprop.h kpropd.c +$(OUTPRE)kpropd_rpc.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + kpropd_rpc.c +$(OUTPRE)kproplog.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-hex.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/kdb_log.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kproplog.c diff --git a/krb5-1.21.3/src/kprop/kprop.c b/krb5-1.21.3/src/kprop/kprop.c new file mode 100644 index 00000000..8f9fd699 --- /dev/null +++ b/krb5-1.21.3/src/kprop/kprop.c @@ -0,0 +1,594 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kprop/kprop.c */ +/* + * Copyright 1990,1991,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "com_err.h" +#include "fake-addrinfo.h" +#include "kprop.h" + +#ifndef GETSOCKNAME_ARG3_TYPE +#define GETSOCKNAME_ARG3_TYPE unsigned int +#endif + +static char *kprop_version = KPROP_PROT_VERSION; + +static char *progname = NULL; +static int debug = 0; +static char *keytab_path = NULL; +static char *replica_host; +static char *realm = NULL; +static char *def_realm = NULL; +static char *file = KPROP_DEFAULT_FILE; + +/* The Kerberos principal we'll be sending as, initialized in get_tickets. */ +static krb5_principal my_principal; + +static krb5_creds creds; +static krb5_address *sender_addr; +static const char *port = KPROP_SERVICE; +static char *dbpathname; + +static void parse_args(krb5_context context, int argc, char **argv); +static void get_tickets(krb5_context context); +static void usage(void); +static void open_connection(krb5_context context, char *host, int *fd_out); +static void kerberos_authenticate(krb5_context context, + krb5_auth_context *auth_context, int fd, + krb5_principal me, krb5_creds **new_creds); +static int open_database(krb5_context context, char *data_fn, off_t *size); +static void close_database(krb5_context context, int fd); +static void xmit_database(krb5_context context, + krb5_auth_context auth_context, krb5_creds *my_creds, + int fd, int database_fd, off_t in_database_size); +static void send_error(krb5_context context, krb5_creds *my_creds, int fd, + char *err_text, krb5_error_code err_code); +static void update_last_prop_file(char *hostname, char *file_name); + +static void usage() +{ + fprintf(stderr, _("\nUsage: %s [-r realm] [-f file] [-d] [-P port] " + "[-s keytab] replica_host\n\n"), progname); + exit(1); +} + +int +main(int argc, char **argv) +{ + int fd, database_fd; + off_t database_size; + krb5_error_code retval; + krb5_context context; + krb5_creds *my_creds; + krb5_auth_context auth_context; + + setlocale(LC_ALL, ""); + retval = krb5_init_context(&context); + if (retval) { + com_err(argv[0], retval, _("while initializing krb5")); + exit(1); + } + parse_args(context, argc, argv); + get_tickets(context); + + database_fd = open_database(context, file, &database_size); + open_connection(context, replica_host, &fd); + kerberos_authenticate(context, &auth_context, fd, my_principal, &my_creds); + xmit_database(context, auth_context, my_creds, fd, database_fd, + database_size); + update_last_prop_file(replica_host, file); + printf(_("Database propagation to %s: SUCCEEDED\n"), replica_host); + krb5_free_cred_contents(context, my_creds); + close_database(context, database_fd); + krb5_free_default_realm(context, def_realm); + exit(0); +} + +static void +parse_args(krb5_context context, int argc, char **argv) +{ + int c; + krb5_error_code ret; + + progname = argv[0]; + while ((c = getopt(argc, argv, "r:f:dP:s:")) != -1) { + switch (c) { + case 'r': + realm = optarg; + break; + case 'f': + file = optarg; + break; + case 'd': + debug++; + break; + case 'P': + port = optarg; + break; + case 's': + keytab_path = optarg; + break; + default: + usage(); + } + } + if (argc - optind != 1) + usage(); + replica_host = argv[optind]; + + if (realm == NULL) { + ret = krb5_get_default_realm(context, &def_realm); + if (ret) { + com_err(progname, errno, _("while getting default realm")); + exit(1); + } + realm = def_realm; + } +} + +static void +get_tickets(krb5_context context) +{ + char *server; + krb5_error_code retval; + krb5_keytab keytab = NULL; + krb5_principal server_princ = NULL; + + /* Figure out what tickets we'll be using to send. */ + retval = sn2princ_realm(context, NULL, KPROP_SERVICE_NAME, realm, + &my_principal); + if (retval) { + com_err(progname, errno, _("while setting client principal name")); + exit(1); + } + + /* Construct the principal name for the replica host. */ + memset(&creds, 0, sizeof(creds)); + retval = sn2princ_realm(context, replica_host, KPROP_SERVICE_NAME, realm, + &server_princ); + if (retval) { + com_err(progname, errno, _("while setting server principal name")); + exit(1); + } + retval = krb5_unparse_name_flags(context, server_princ, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, &server); + if (retval) { + com_err(progname, retval, _("while unparsing server name")); + exit(1); + } + + if (keytab_path != NULL) { + retval = krb5_kt_resolve(context, keytab_path, &keytab); + if (retval) { + com_err(progname, retval, _("while resolving keytab")); + exit(1); + } + } + + retval = krb5_get_init_creds_keytab(context, &creds, my_principal, keytab, + 0, server, NULL); + if (retval) { + com_err(progname, retval, _("while getting initial credentials\n")); + exit(1); + } + + if (keytab != NULL) + krb5_kt_close(context, keytab); + krb5_free_unparsed_name(context, server); + krb5_free_principal(context, server_princ); +} + +static void +open_connection(krb5_context context, char *host, int *fd_out) +{ + krb5_error_code retval; + GETSOCKNAME_ARG3_TYPE socket_length; + struct addrinfo hints, *res, *answers; + struct sockaddr *sa; + struct sockaddr_storage my_sin; + int s, error; + + *fd_out = -1; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_ADDRCONFIG; + error = getaddrinfo(host, port, &hints, &answers); + if (error != 0) { + com_err(progname, 0, "%s: %s", host, gai_strerror(error)); + exit(1); + } + + s = -1; + retval = EINVAL; + for (res = answers; res != NULL; res = res->ai_next) { + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s < 0) { + com_err(progname, errno, _("while creating socket")); + exit(1); + } + + if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { + retval = errno; + close(s); + s = -1; + continue; + } + + /* We successfully connect()ed */ + *fd_out = s; + + break; + } + + freeaddrinfo(answers); + + if (s == -1) { + com_err(progname, retval, _("while connecting to server")); + exit(1); + } + + /* Set sender_addr. */ + socket_length = sizeof(my_sin); + if (getsockname(s, (struct sockaddr *)&my_sin, &socket_length) < 0) { + com_err(progname, errno, _("while getting local socket address")); + exit(1); + } + sa = (struct sockaddr *)&my_sin; + if (sockaddr2krbaddr(context, sa->sa_family, sa, &sender_addr) != 0) { + com_err(progname, errno, _("while converting local address")); + exit(1); + } +} + +static void +kerberos_authenticate(krb5_context context, krb5_auth_context *auth_context, + int fd, krb5_principal me, krb5_creds **new_creds) +{ + krb5_error_code retval; + krb5_error *error = NULL; + krb5_ap_rep_enc_part *rep_result; + + retval = krb5_auth_con_init(context, auth_context); + if (retval) + exit(1); + + krb5_auth_con_setflags(context, *auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE); + + retval = krb5_auth_con_setaddrs(context, *auth_context, sender_addr, NULL); + if (retval) { + com_err(progname, retval, _("in krb5_auth_con_setaddrs")); + exit(1); + } + + retval = krb5_sendauth(context, auth_context, &fd, kprop_version, + me, creds.server, AP_OPTS_MUTUAL_REQUIRED, NULL, + &creds, NULL, &error, &rep_result, new_creds); + if (retval) { + com_err(progname, retval, _("while authenticating to server")); + if (error != NULL) { + if (error->error == KRB_ERR_GENERIC) { + if (error->text.data) { + fprintf(stderr, _("Generic remote error: %s\n"), + error->text.data); + } + } else if (error->error) { + com_err(progname, + (krb5_error_code)error->error + ERROR_TABLE_BASE_krb5, + _("signalled from server")); + if (error->text.data) { + fprintf(stderr, _("Error text from server: %s\n"), + error->text.data); + } + } + krb5_free_error(context, error); + } + exit(1); + } + krb5_free_ap_rep_enc_part(context, rep_result); +} + +/* + * Open the Kerberos database dump file. Takes care of locking it + * and making sure that the .ok file is more recent that the database + * dump file itself. + * + * Returns the file descriptor of the database dump file. Also fills + * in the size of the database file. + */ +static int +open_database(krb5_context context, char *data_fn, off_t *size) +{ + struct stat stbuf, stbuf_ok; + char *data_ok_fn; + int fd, err; + + dbpathname = strdup(data_fn); + if (dbpathname == NULL) { + com_err(progname, ENOMEM, _("allocating database file name '%s'"), + data_fn); + exit(1); + } + fd = open(dbpathname, O_RDONLY); + if (fd < 0) { + com_err(progname, errno, _("while trying to open %s"), dbpathname); + exit(1); + } + + err = krb5_lock_file(context, fd, + KRB5_LOCKMODE_SHARED | KRB5_LOCKMODE_DONTBLOCK); + if (err == EAGAIN || err == EWOULDBLOCK || errno == EACCES) { + com_err(progname, 0, _("database locked")); + exit(1); + } else if (err) { + com_err(progname, err, _("while trying to lock '%s'"), dbpathname); + exit(1); + } + if (fstat(fd, &stbuf)) { + com_err(progname, errno, _("while trying to stat %s"), data_fn); + exit(1); + } + if (asprintf(&data_ok_fn, "%s.dump_ok", data_fn) < 0) { + com_err(progname, ENOMEM, _("while trying to malloc data_ok_fn")); + exit(1); + } + if (stat(data_ok_fn, &stbuf_ok)) { + com_err(progname, errno, _("while trying to stat %s"), data_ok_fn); + free(data_ok_fn); + exit(1); + } + if (stbuf.st_mtime > stbuf_ok.st_mtime) { + com_err(progname, 0, _("'%s' more recent than '%s'."), data_fn, + data_ok_fn); + exit(1); + } + free(data_ok_fn); + *size = stbuf.st_size; + return fd; +} + +static void +close_database(krb5_context context, int fd) +{ + int err; + + err = krb5_lock_file(context, fd, KRB5_LOCKMODE_UNLOCK); + if (err) + com_err(progname, err, _("while unlocking database '%s'"), dbpathname); + free(dbpathname); + close(fd); +} + +/* + * Now we send over the database. We use the following protocol: + * Send over a KRB_SAFE message with the size. Then we send over the + * database in blocks of KPROP_BLKSIZE, encrypted using KRB_PRIV. + * Then we expect to see a KRB_SAFE message with the size sent back. + * + * At any point in the protocol, we may send a KRB_ERROR message; this + * will abort the entire operation. + */ +static void +xmit_database(krb5_context context, krb5_auth_context auth_context, + krb5_creds *my_creds, int fd, int database_fd, + off_t in_database_size) +{ + krb5_int32 n; + krb5_data inbuf, outbuf; + char buf[KPROP_BUFSIZ], dbsize_buf[KPROP_DBSIZE_MAX_BUFSIZ]; + krb5_error_code retval; + krb5_error *error; + uint64_t database_size = in_database_size, send_size, sent_size; + + /* Send over the size. */ + inbuf = make_data(dbsize_buf, sizeof(dbsize_buf)); + encode_database_size(database_size, &inbuf); + /* KPROP_CKSUMTYPE */ + retval = krb5_mk_safe(context, auth_context, &inbuf, &outbuf, NULL); + if (retval) { + com_err(progname, retval, _("while encoding database size")); + send_error(context, my_creds, fd, _("while encoding database size"), + retval); + exit(1); + } + + retval = krb5_write_message(context, &fd, &outbuf); + if (retval) { + krb5_free_data_contents(context, &outbuf); + com_err(progname, retval, _("while sending database size")); + exit(1); + } + krb5_free_data_contents(context, &outbuf); + + /* Initialize the initial vector. */ + retval = krb5_auth_con_initivector(context, auth_context); + if (retval) { + send_error(context, my_creds, fd, + "failed while initializing i_vector", retval); + com_err(progname, retval, _("while allocating i_vector")); + exit(1); + } + + /* Send over the file, block by block. */ + inbuf.data = buf; + sent_size = 0; + while ((n = read(database_fd, buf, sizeof(buf)))) { + inbuf.length = n; + retval = krb5_mk_priv(context, auth_context, &inbuf, &outbuf, NULL); + if (retval) { + snprintf(buf, sizeof(buf), + "while encoding database block starting at %"PRIu64, + sent_size); + com_err(progname, retval, "%s", buf); + send_error(context, my_creds, fd, buf, retval); + exit(1); + } + + retval = krb5_write_message(context, &fd, &outbuf); + if (retval) { + krb5_free_data_contents(context, &outbuf); + com_err(progname, retval, + _("while sending database block starting at %"PRIu64), + sent_size); + exit(1); + } + krb5_free_data_contents(context, &outbuf); + sent_size += n; + if (debug) + printf("%"PRIu64" bytes sent.\n", sent_size); + } + if (sent_size != database_size) { + com_err(progname, 0, _("Premature EOF found for database file!")); + send_error(context, my_creds, fd, + "Premature EOF found for database file!", + KRB5KRB_ERR_GENERIC); + exit(1); + } + + /* + * OK, we've sent the database; now let's wait for a success + * indication from the remote end. + */ + retval = krb5_read_message(context, &fd, &inbuf); + if (retval) { + com_err(progname, retval, _("while reading response from server")); + exit(1); + } + /* + * If we got an error response back from the server, display + * the error message + */ + if (krb5_is_krb_error(&inbuf)) { + retval = krb5_rd_error(context, &inbuf, &error); + if (retval) { + com_err(progname, retval, + _("while decoding error response from server")); + exit(1); + } + if (error->error == KRB_ERR_GENERIC) { + if (error->text.data) { + fprintf(stderr, _("Generic remote error: %s\n"), + error->text.data); + } + } else if (error->error) { + com_err(progname, + (krb5_error_code)error->error + ERROR_TABLE_BASE_krb5, + _("signalled from server")); + if (error->text.data) { + fprintf(stderr, _("Error text from server: %s\n"), + error->text.data); + } + } + krb5_free_error(context, error); + exit(1); + } + + retval = krb5_rd_safe(context,auth_context,&inbuf,&outbuf,NULL); + if (retval) { + com_err(progname, retval, + "while decoding final size packet from server"); + exit(1); + } + + retval = decode_database_size(&outbuf, &send_size); + if (retval) { + com_err(progname, retval, _("malformed sent database size message")); + exit(1); + } + if (send_size != database_size) { + com_err(progname, 0, _("Kpropd sent database size %"PRIu64 + ", expecting %"PRIu64), + send_size, database_size); + exit(1); + } + free(inbuf.data); + free(outbuf.data); +} + +static void +send_error(krb5_context context, krb5_creds *my_creds, int fd, char *err_text, + krb5_error_code err_code) +{ + krb5_error error; + const char *text; + krb5_data outbuf; + + memset(&error, 0, sizeof(error)); + krb5_us_timeofday(context, &error.ctime, &error.cusec); + error.server = my_creds->server; + error.client = my_principal; + error.error = err_code - ERROR_TABLE_BASE_krb5; + if (error.error > 127) + error.error = KRB_ERR_GENERIC; + text = (err_text != NULL) ? err_text : error_message(err_code); + error.text.length = strlen(text) + 1; + error.text.data = strdup(text); + if (error.text.data) { + if (!krb5_mk_error(context, &error, &outbuf)) { + (void)krb5_write_message(context, &fd, &outbuf); + krb5_free_data_contents(context, &outbuf); + } + free(error.text.data); + } +} + +static void +update_last_prop_file(char *hostname, char *file_name) +{ + char *file_last_prop; + int fd; + static char last_prop[] = ".last_prop"; + + if (asprintf(&file_last_prop, "%s.%s%s", file_name, hostname, + last_prop) < 0) { + com_err(progname, ENOMEM, + _("while allocating filename for update_last_prop_file")); + return; + } + fd = THREEPARAMOPEN(file_last_prop, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd < 0) { + com_err(progname, errno, _("while creating 'last_prop' file, '%s'"), + file_last_prop); + free(file_last_prop); + return; + } + write(fd, "", 1); + free(file_last_prop); + close(fd); +} diff --git a/krb5-1.21.3/src/kprop/kprop.h b/krb5-1.21.3/src/kprop/kprop.h new file mode 100644 index 00000000..3a319b53 --- /dev/null +++ b/krb5-1.21.3/src/kprop/kprop.h @@ -0,0 +1,55 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kprop/kprop.h */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#define KPROP_SERVICE_NAME "host" +#define TGT_SERVICE_NAME "krbtgt" +#define KPROP_SERVICE "krb5_prop" +#define KPROP_PORT 754 + +#define KPROP_PROT_VERSION "kprop5_01" + +#define KPROP_BUFSIZ 32768 +#define KPROP_DBSIZE_MAX_BUFSIZ 12 /* max length of an encoded DB size */ + +/* pathnames are in osconf.h, included via k5-int.h */ + +int sockaddr2krbaddr(krb5_context context, int family, struct sockaddr *sa, + krb5_address **dest); + +krb5_error_code +sn2princ_realm(krb5_context context, const char *hostname, const char *sname, + const char *realm, krb5_principal *princ_out); + +/* + * Encode size in four bytes (for backward compatibility) if it fits; otherwise + * use the larger encoding. buf must be allocated with at least + * KPROP_DBSIZE_MAX_BUFSIZ bytes. + */ +void encode_database_size(uint64_t size, krb5_data *buf); + +/* Decode a database size. Return KRB5KRB_ERR_GENERIC if buf has an invalid + * length or did not encode a 32-bit size compactly. */ +krb5_error_code decode_database_size(const krb5_data *buf, uint64_t *size_out); diff --git a/krb5-1.21.3/src/kprop/kprop_util.c b/krb5-1.21.3/src/kprop/kprop_util.c new file mode 100644 index 00000000..c0aa2c89 --- /dev/null +++ b/krb5-1.21.3/src/kprop/kprop_util.c @@ -0,0 +1,136 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kprop/kprop_util.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* sockaddr2krbaddr() utility function used by kprop and kpropd */ + +#include "k5-int.h" +#include "kprop.h" + +#include +#include + +/* + * Convert an IPv4 or IPv6 socket address to a newly allocated krb5_address. + * There is similar code elsewhere in the tree, so this should possibly become + * a libkrb5 API in the future. + */ +krb5_error_code +sockaddr2krbaddr(krb5_context context, int family, struct sockaddr *sa, + krb5_address **dest) +{ + krb5_address addr; + + addr.magic = KV5M_ADDRESS; + if (family == AF_INET) { + struct sockaddr_in *sa4 = sa2sin(sa); + addr.addrtype = ADDRTYPE_INET; + addr.length = sizeof(sa4->sin_addr); + addr.contents = (krb5_octet *) &sa4->sin_addr; + } else if (family == AF_INET6) { + struct sockaddr_in6 *sa6 = sa2sin6(sa); + if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) { + addr.addrtype = ADDRTYPE_INET; + addr.contents = (krb5_octet *) &sa6->sin6_addr + 12; + addr.length = 4; + } else { + addr.addrtype = ADDRTYPE_INET6; + addr.length = sizeof(sa6->sin6_addr); + addr.contents = (krb5_octet *) &sa6->sin6_addr; + } + } else + return KRB5_PROG_ATYPE_NOSUPP; + + return krb5_copy_addr(context, &addr, dest); +} + +/* Construct a host-based principal, similar to krb5_sname_to_principal() but + * with a specified realm. */ +krb5_error_code +sn2princ_realm(krb5_context context, const char *hostname, const char *sname, + const char *realm, krb5_principal *princ_out) +{ + krb5_error_code ret; + krb5_principal princ; + + *princ_out = NULL; + assert(sname != NULL && realm != NULL); + + ret = krb5_sname_to_principal(context, hostname, sname, KRB5_NT_SRV_HST, + &princ); + if (ret) + return ret; + + ret = krb5_set_principal_realm(context, princ, realm); + if (ret) { + krb5_free_principal(context, princ); + return ret; + } + + *princ_out = princ; + return 0; +} + +void +encode_database_size(uint64_t size, krb5_data *buf) +{ + assert(buf->length >= 12); + if (size > 0 && size <= UINT32_MAX) { + /* Encode in 32 bits for backward compatibility. */ + store_32_be(size, buf->data); + buf->length = 4; + } else { + /* Set the first 32 bits to 0 and encode in the following 64 bits. */ + store_32_be(0, buf->data); + store_64_be(size, buf->data + 4); + buf->length = 12; + } +} + +krb5_error_code +decode_database_size(const krb5_data *buf, uint64_t *size_out) +{ + uint64_t size; + + if (buf->length == 12) { + /* A 12-byte buffer must have the first four bytes zeroed. */ + if (load_32_be(buf->data) != 0) + return KRB5KRB_ERR_GENERIC; + + /* The size is stored in the next 64 bits. Values from 1..2^32-1 must + * be encoded in four bytes. */ + size = load_64_be(buf->data + 4); + if (size > 0 && size <= UINT32_MAX) + return KRB5KRB_ERR_GENERIC; + } else if (buf->length == 4) { + size = load_32_be(buf->data); + } else { + /* Invalid buffer size. */ + return KRB5KRB_ERR_GENERIC; + } + + *size_out = size; + return 0; +} diff --git a/krb5-1.21.3/src/kprop/kpropd.c b/krb5-1.21.3/src/kprop/kpropd.c new file mode 100644 index 00000000..aa3c81ea --- /dev/null +++ b/krb5-1.21.3/src/kprop/kpropd.c @@ -0,0 +1,1620 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* kprop/kpropd.c */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * Copyright 1990,1991,2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + + +#include "k5-int.h" +#include "com_err.h" +#include "fake-addrinfo.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kprop.h" +#include +#include "iprop.h" +#include +#include + +#ifndef GETSOCKNAME_ARG3_TYPE +#define GETSOCKNAME_ARG3_TYPE unsigned int +#endif +#ifndef GETPEERNAME_ARG3_TYPE +#define GETPEERNAME_ARG3_TYPE unsigned int +#endif + +#if defined(NEED_DAEMON_PROTO) +extern int daemon(int, int); +#endif + +#define SYSLOG_CLASS LOG_DAEMON + +int runonce = 0; + +/* + * This struct simulates the use of _kadm5_server_handle_t + * + * This is a COPY of kadm5_server_handle_t from + * lib/kadm5/clnt/client_internal.h! + */ +typedef struct _kadm5_iprop_handle_t { + krb5_ui_4 magic_number; + krb5_ui_4 struct_version; + krb5_ui_4 api_version; + char *cache_name; + int destroy_cache; + CLIENT *clnt; + krb5_context context; + kadm5_config_params params; + struct _kadm5_iprop_handle_t *lhandle; +} *kadm5_iprop_handle_t; + +static char *kprop_version = KPROP_PROT_VERSION; + +static kadm5_config_params params; + +static char *progname; +static int debug = 0; +static int nodaemon = 0; +static char *keytab_path = NULL; +static int standalone = 0; +static const char *pid_file = NULL; + +static pid_t fullprop_child = (pid_t)-1; + +static krb5_principal server; /* This is our server principal name */ +static krb5_principal client; /* This is who we're talking to */ +static krb5_context kpropd_context; +static krb5_auth_context auth_context; +static char *realm = NULL; /* Our realm */ +static char *def_realm = NULL; /* Ref pointer for default realm */ +static char *file = KPROPD_DEFAULT_FILE; +static char *temp_file_name; +static char *kdb5_util = KPROPD_DEFAULT_KDB5_UTIL; +static char *kerb_database = NULL; +static char *acl_file_name = KPROPD_ACL_FILE; + +static krb5_address *receiver_addr; +static const char *port = KPROP_SERVICE; + +static char **db_args = NULL; +static int db_args_size = 0; + +static void parse_args(int argc, char **argv); +static void do_standalone(void); +static void doit(int fd); +static krb5_error_code do_iprop(void); +static void kerberos_authenticate(krb5_context context, int fd, + krb5_principal *clientp, krb5_enctype *etype, + struct sockaddr_storage *my_sin); +static krb5_boolean authorized_principal(krb5_context context, + krb5_principal p, + krb5_enctype auth_etype); +static void recv_database(krb5_context context, int fd, int database_fd, + krb5_data *confmsg); +static void load_database(krb5_context context, char *kdb_util, + char *database_file_name); +static void send_error(krb5_context context, int fd, krb5_error_code err_code, + char *err_text); +static void recv_error(krb5_context context, krb5_data *inbuf); +static unsigned int backoff_from_primary(int *cnt); +static kadm5_ret_t kadm5_get_kiprop_host_srv_name(krb5_context context, + const char *realm_name, + char **host_service_name); + +static void +usage() +{ + fprintf(stderr, + _("\nUsage: %s [-r realm] [-s keytab] [-d] [-D] [-S]\n" + "\t[-f replica_file] [-F kerberos_db_file ]\n" + "\t[-p kdb5_util_pathname] [-x db_args]* [-P port]\n" + "\t[-a acl_file] [-A admin_server] [--pid-file=pid_file]\n"), + progname); + exit(1); +} + +static krb5_error_code +write_pid_file(const char *path) +{ + FILE *fp; + unsigned long pid; + + fp = fopen(path, "w"); + if (fp == NULL) + return errno; + pid = (unsigned long)getpid(); + if (fprintf(fp, "%ld\n", pid) < 0 || fclose(fp) == EOF) + return errno; + return 0; +} + +typedef void (*sig_handler_fn)(int sig); + +static void +signal_wrapper(int sig, sig_handler_fn handler) +{ +#ifdef POSIX_SIGNALS + struct sigaction s_action; + + memset(&s_action, 0, sizeof(s_action)); + sigemptyset(&s_action.sa_mask); + s_action.sa_handler = handler; + sigaction(sig, &s_action, NULL); +#else + signal(sig, handler); +#endif +} + +static void +alarm_handler(int sig) +{ + static char *timeout_msg = "Full propagation timed out\n"; + + write(STDERR_FILENO, timeout_msg, strlen(timeout_msg)); + exit(1); +} + +static void +usr1_handler(int sig) +{ + /* Nothing to do, just let the signal interrupt sleep(). */ +} + +static void +kill_do_standalone(int sig) +{ + if (fullprop_child > 0) { + if (debug) { + fprintf(stderr, _("Killing fullprop child (%d)\n"), + (int)fullprop_child); + } + kill(fullprop_child, sig); + } + /* Make sure our exit status code reflects our having been signaled */ + signal_wrapper(sig, SIG_DFL); + kill(getpid(), sig); +} + +static void +atexit_kill_do_standalone(void) +{ + if (fullprop_child > 0) + kill(fullprop_child, SIGHUP); +} + +int +main(int argc, char **argv) +{ + krb5_error_code retval; + kdb_log_context *log_ctx; + int devnull, sock; + struct stat st; + + setlocale(LC_ALL, ""); + parse_args(argc, argv); + + if (fstat(0, &st) == -1) { + com_err(progname, errno, _("while checking if stdin is a socket")); + exit(1); + } + /* + * Detect whether we're running from inetd; if not then we're in + * standalone mode. + */ + standalone = !S_ISSOCK(st.st_mode); + + log_ctx = kpropd_context->kdblog_context; + + signal_wrapper(SIGPIPE, SIG_IGN); + + if (standalone) { + /* "ready" is a sentinel for the test framework. */ + if (!debug && !nodaemon) { + daemon(0, 0); + } else { + printf(_("ready\n")); + fflush(stdout); + } + if (pid_file != NULL) { + retval = write_pid_file(pid_file); + if (retval) { + syslog(LOG_ERR, _("Could not write pid file %s: %s"), + pid_file, strerror(errno)); + exit(1); + } + } + } else { + /* + * We're an inetd nowait service. Let's not risk anything + * read/write from/to the inetd socket unintentionally. + */ + devnull = open("/dev/null", O_RDWR); + if (devnull == -1) { + syslog(LOG_ERR, _("Could not open /dev/null: %s"), + strerror(errno)); + exit(1); + } + + sock = dup(0); + if (sock == -1) { + syslog(LOG_ERR, _("Could not dup the inetd socket: %s"), + strerror(errno)); + exit(1); + } + + dup2(devnull, STDIN_FILENO); + dup2(devnull, STDOUT_FILENO); + dup2(devnull, STDERR_FILENO); + close(devnull); + doit(sock); + exit(0); + } + + if (log_ctx == NULL || log_ctx->iproprole != IPROP_REPLICA) { + do_standalone(); + /* do_standalone() should never return */ + assert(0); + } + + /* + * This is the iprop case. We'll fork a child to run do_standalone(). The + * parent will run do_iprop(). We try to kill the child if we get killed. + * Catch SIGUSR1, which can be used to interrupt the sleep timer and force + * an iprop request. + */ + signal_wrapper(SIGHUP, kill_do_standalone); + signal_wrapper(SIGINT, kill_do_standalone); + signal_wrapper(SIGQUIT, kill_do_standalone); + signal_wrapper(SIGTERM, kill_do_standalone); + signal_wrapper(SIGSEGV, kill_do_standalone); + signal_wrapper(SIGUSR1, usr1_handler); + atexit(atexit_kill_do_standalone); + fullprop_child = fork(); + switch (fullprop_child) { + case -1: + com_err(progname, errno, _("do_iprop failed.\n")); + break; + case 0: + do_standalone(); + /* do_standalone() should never return */ + /* NOTREACHED */ + break; + default: + retval = do_iprop(); + /* do_iprop() can return due to failures and runonce. */ + kill(fullprop_child, SIGHUP); + wait(NULL); + if (retval) + com_err(progname, retval, _("do_iprop failed.\n")); + else + exit(0); + } + + exit(1); +} + +/* Use getaddrinfo to determine a wildcard listener address, preferring + * IPv6 if available. */ +static int +get_wildcard_addr(struct addrinfo **res) +{ + struct addrinfo hints; + int error; + + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + hints.ai_family = AF_INET6; + error = getaddrinfo(NULL, port, &hints, res); + if (error == 0) + return 0; + hints.ai_family = AF_INET; + return getaddrinfo(NULL, port, &hints, res); +} + +static void +do_standalone() +{ + struct sockaddr_in frominet; + struct addrinfo *res; + GETPEERNAME_ARG3_TYPE fromlen; + int finet, s, ret, error, val, status; + pid_t child_pid; + pid_t wait_pid; + + error = get_wildcard_addr(&res); + if (error != 0) { + fprintf(stderr, _("getaddrinfo: %s\n"), gai_strerror(error)); + exit(1); + } + + finet = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (finet < 0) { + com_err(progname, errno, _("while obtaining socket")); + exit(1); + } + + val = 1; + if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) + com_err(progname, errno, _("while setting SO_REUSEADDR option")); + +#if defined(IPV6_V6ONLY) + /* Make sure dual-stack support is enabled on IPv6 listener sockets if + * possible. */ + val = 0; + if (res->ai_family == AF_INET6 && + setsockopt(finet, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val)) < 0) + com_err(progname, errno, _("while unsetting IPV6_V6ONLY option")); +#endif + + ret = bind(finet, res->ai_addr, res->ai_addrlen); + if (ret < 0) { + com_err(progname, errno, _("while binding listener socket")); + exit(1); + } + if (listen(finet, 5) < 0) { + com_err(progname, errno, "in listen call"); + exit(1); + } + for (;;) { + memset(&frominet, 0, sizeof(frominet)); + fromlen = sizeof(frominet); + if (debug) + fprintf(stderr, _("waiting for a kprop connection\n")); + s = accept(finet, (struct sockaddr *) &frominet, &fromlen); + + if (s < 0) { + int e = errno; + if (e != EINTR) { + com_err(progname, e, _("while accepting connection")); + } + } + child_pid = fork(); + switch (child_pid) { + case -1: + com_err(progname, errno, _("while forking")); + exit(1); + case 0: + close(finet); + + doit(s); + close(s); + _exit(0); + default: + do { + wait_pid = waitpid(child_pid, &status, 0); + } while (wait_pid == -1 && errno == EINTR); + if (wait_pid == -1) { + /* Something bad happened; panic. */ + if (debug) { + fprintf(stderr, _("waitpid() failed to wait for doit() " + "(%d %s)\n"), errno, strerror(errno)); + } + com_err(progname, errno, + _("while waiting to receive database")); + exit(1); + } + if (debug) { + fprintf(stderr, _("Database load process for full propagation " + "completed.\n")); + } + + close(s); + + /* If we are the fullprop child in iprop mode, notify the parent + * process that it should poll for incremental updates. */ + if (fullprop_child == 0) + kill(getppid(), SIGUSR1); + else if (runonce) + exit(0); + } + } + exit(0); +} + +static void +doit(int fd) +{ + struct sockaddr_storage from; + int on = 1; + GETPEERNAME_ARG3_TYPE fromlen; + krb5_error_code retval; + krb5_data confmsg; + int lock_fd; + mode_t omask; + krb5_enctype etype; + int database_fd; + char host[INET6_ADDRSTRLEN + 1]; + + signal_wrapper(SIGALRM, alarm_handler); + alarm(params.iprop_resync_timeout); + fromlen = sizeof(from); + if (getpeername(fd, (struct sockaddr *)&from, &fromlen) < 0) { +#ifdef ENOTSOCK + if (errno == ENOTSOCK && fd == 0 && !standalone) { + fprintf(stderr, + _("%s: Standard input does not appear to be a network " + "socket.\n" + "\t(Not run from inetd, and missing the -S option?)\n"), + progname); + exit(1); + } +#endif + fprintf(stderr, "%s: ", progname); + perror("getpeername"); + exit(1); + } + if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) { + com_err(progname, errno, + _("while attempting setsockopt (SO_KEEPALIVE)")); + } + + if (getnameinfo((const struct sockaddr *) &from, fromlen, + host, sizeof(host), NULL, 0, 0) == 0) { + syslog(LOG_INFO, _("Connection from %s"), host); + if (debug) + fprintf(stderr, "Connection from %s\n", host); + } + + /* + * Now do the authentication + */ + kerberos_authenticate(kpropd_context, fd, &client, &etype, &from); + + if (!authorized_principal(kpropd_context, client, etype)) { + char *name; + + retval = krb5_unparse_name(kpropd_context, client, &name); + if (retval) { + com_err(progname, retval, "While unparsing client name"); + exit(1); + } + if (debug) { + fprintf(stderr, + _("Rejected connection from unauthorized principal %s\n"), + name); + } + syslog(LOG_WARNING, + _("Rejected connection from unauthorized principal %s"), + name); + free(name); + exit(1); + } + omask = umask(077); + lock_fd = open(temp_file_name, O_RDWR | O_CREAT, 0600); + (void)umask(omask); + retval = krb5_lock_file(kpropd_context, lock_fd, + KRB5_LOCKMODE_EXCLUSIVE | KRB5_LOCKMODE_DONTBLOCK); + if (retval) { + com_err(progname, retval, _("while trying to lock '%s'"), + temp_file_name); + exit(1); + } + database_fd = open(temp_file_name, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (database_fd < 0) { + com_err(progname, errno, _("while opening database file, '%s'"), + temp_file_name); + exit(1); + } + recv_database(kpropd_context, fd, database_fd, &confmsg); + if (rename(temp_file_name, file)) { + com_err(progname, errno, _("while renaming %s to %s"), + temp_file_name, file); + exit(1); + } + retval = krb5_lock_file(kpropd_context, lock_fd, KRB5_LOCKMODE_SHARED); + if (retval) { + com_err(progname, retval, _("while downgrading lock on '%s'"), + temp_file_name); + exit(1); + } + load_database(kpropd_context, kdb5_util, file); + retval = krb5_lock_file(kpropd_context, lock_fd, KRB5_LOCKMODE_UNLOCK); + if (retval) { + com_err(progname, retval, _("while unlocking '%s'"), temp_file_name); + exit(1); + } + close(lock_fd); + + /* + * Send the acknowledgement message generated in + * recv_database, then close the socket. + */ + retval = krb5_write_message(kpropd_context, &fd, &confmsg); + if (retval) { + krb5_free_data_contents(kpropd_context, &confmsg); + com_err(progname, retval, _("while sending # of received bytes")); + exit(1); + } + krb5_free_data_contents(kpropd_context, &confmsg); + if (close(fd) < 0) { + com_err(progname, errno, + _("while trying to close database file")); + exit(1); + } + + exit(0); +} + +/* Default timeout can be changed using clnt_control() */ +static struct timeval full_resync_timeout = { 25, 0 }; + +static kdb_fullresync_result_t * +full_resync(CLIENT *clnt) +{ + static kdb_fullresync_result_t clnt_res; + uint32_t vers = IPROPX_VERSION_1; /* max version we support */ + enum clnt_stat status; + + memset(&clnt_res, 0, sizeof(clnt_res)); + + status = clnt_call(clnt, IPROP_FULL_RESYNC_EXT, (xdrproc_t)xdr_u_int32, + &vers, (xdrproc_t)xdr_kdb_fullresync_result_t, + &clnt_res, full_resync_timeout); + if (status == RPC_PROCUNAVAIL) { + status = clnt_call(clnt, IPROP_FULL_RESYNC, (xdrproc_t)xdr_void, + &vers, (xdrproc_t)xdr_kdb_fullresync_result_t, + &clnt_res, full_resync_timeout); + } + + return (status == RPC_SUCCESS) ? &clnt_res : NULL; +} + +/* + * Beg for incrementals from the KDC. + * + * Returns 0 on success IFF runonce is true. + * Returns non-zero on failure due to errors. + */ +krb5_error_code +do_iprop() +{ + kadm5_ret_t retval; + krb5_principal iprop_svc_principal = NULL; + void *server_handle = NULL; + char *iprop_svc_princstr = NULL, *primary_svc_princstr = NULL; + unsigned int pollin, backoff_time; + int backoff_cnt = 0, reinit_cnt = 0; + struct timeval iprop_start, iprop_end; + unsigned long usec; + time_t frrequested = 0, now; + kdb_incr_result_t *incr_ret; + kdb_last_t mylast; + kdb_fullresync_result_t *full_ret; + kadm5_iprop_handle_t handle; + + if (debug) + fprintf(stderr, _("Incremental propagation enabled\n")); + + pollin = params.iprop_poll_time; + if (pollin == 0) + pollin = 10; + + retval = kadm5_get_kiprop_host_srv_name(kpropd_context, realm, + &primary_svc_princstr); + if (retval) { + com_err(progname, retval, _("%s: unable to get kiprop host based " + "service name for realm %s\n"), + progname, realm); + goto done; + } + + retval = sn2princ_realm(kpropd_context, NULL, KIPROP_SVC_NAME, realm, + &iprop_svc_principal); + if (retval) { + com_err(progname, retval, + _("while trying to construct host service principal")); + goto done; + } + + retval = krb5_unparse_name(kpropd_context, iprop_svc_principal, + &iprop_svc_princstr); + if (retval) { + com_err(progname, retval, + _("while canonicalizing principal name")); + goto done; + } + +reinit: + /* + * Authentication, initialize rpcsec_gss handle etc. + */ + if (debug) { + fprintf(stderr, _("Initializing kadm5 as client %s\n"), + iprop_svc_princstr); + } + retval = kadm5_init_with_skey(kpropd_context, iprop_svc_princstr, + keytab_path, + primary_svc_princstr, + ¶ms, + KADM5_STRUCT_VERSION, + KADM5_API_VERSION_4, + db_args, + &server_handle); + + if (retval) { + if (debug) + fprintf(stderr, _("kadm5 initialization failed!\n")); + if (retval == KADM5_RPC_ERROR) { + reinit_cnt++; + if (server_handle) + kadm5_destroy(server_handle); + server_handle = NULL; + handle = NULL; + + com_err(progname, retval, _( + "while attempting to connect" + " to primary KDC ... retrying")); + backoff_time = backoff_from_primary(&reinit_cnt); + if (debug) { + fprintf(stderr, _("Sleeping %d seconds to re-initialize " + "kadm5 (RPC ERROR)\n"), backoff_time); + } + sleep(backoff_time); + goto reinit; + } else { + if (retval == KADM5_BAD_CLIENT_PARAMS || + retval == KADM5_BAD_SERVER_PARAMS) { + com_err(progname, retval, + _("while initializing %s interface"), + progname); + + usage(); + } + reinit_cnt++; + com_err(progname, retval, + _("while initializing %s interface, retrying"), + progname); + backoff_time = backoff_from_primary(&reinit_cnt); + if (debug) { + fprintf(stderr, _("Sleeping %d seconds to re-initialize " + "kadm5 (krb5kdc not running?)\n"), + backoff_time); + } + sleep(backoff_time); + goto reinit; + } + } + + if (debug) + fprintf(stderr, _("kadm5 initialization succeeded\n")); + + /* + * Reset re-initialization count to zero now. + */ + reinit_cnt = backoff_time = 0; + + /* + * Reset the handle to the correct type for the RPC call + */ + handle = server_handle; + + for (;;) { + incr_ret = NULL; + full_ret = NULL; + + /* + * Get the most recent ulog entry sno + ts, which + * we package in the request to the primary KDC + */ + retval = ulog_get_last(kpropd_context, &mylast); + if (retval) { + com_err(progname, retval, _("reading update log header")); + goto done; + } + + /* + * Loop continuously on an iprop_get_updates_1(), + * so that we can keep probing the primary for updates + * or (if needed) do a full resync of the krb5 db. + */ + + if (debug) { + fprintf(stderr, _("Calling iprop_get_updates_1 " + "(sno=%u sec=%u usec=%u)\n"), + (unsigned int)mylast.last_sno, + (unsigned int)mylast.last_time.seconds, + (unsigned int)mylast.last_time.useconds); + } + gettimeofday(&iprop_start, NULL); + incr_ret = iprop_get_updates_1(&mylast, handle->clnt); + if (incr_ret == (kdb_incr_result_t *)NULL) { + clnt_perror(handle->clnt, + _("iprop_get_updates call failed")); + if (server_handle) + kadm5_destroy(server_handle); + server_handle = NULL; + handle = (kadm5_iprop_handle_t)NULL; + if (debug) { + fprintf(stderr, _("Reinitializing iprop because get updates " + "failed\n")); + } + goto reinit; + } + + switch (incr_ret->ret) { + + case UPDATE_FULL_RESYNC_NEEDED: + /* + * If we're already asked for a full resync and we still + * need one and the last one hasn't timed out then just keep + * asking for updates as eventually the resync will finish + * (or, if it times out we'll just try again). Note that + * doit() also applies a timeout to the full resync, thus + * it's OK for us to do the same here. + */ + now = time(NULL); + if (frrequested && + (now - frrequested) < params.iprop_resync_timeout) { + if (debug) + fprintf(stderr, _("Still waiting for full resync\n")); + break; + } else { + frrequested = now; + if (debug) + fprintf(stderr, _("Full resync needed\n")); + syslog(LOG_INFO, _("kpropd: Full resync needed.")); + + full_ret = full_resync(handle->clnt); + if (full_ret == NULL) { + clnt_perror(handle->clnt, + _("iprop_full_resync call failed")); + kadm5_destroy(server_handle); + server_handle = NULL; + handle = NULL; + goto reinit; + } + } + + switch (full_ret->ret) { + case UPDATE_OK: + if (debug) + fprintf(stderr, _("Full resync request granted\n")); + syslog(LOG_INFO, _("Full resync request granted.")); + backoff_cnt = 0; + break; + + case UPDATE_BUSY: + /* + * Exponential backoff + */ + if (debug) + fprintf(stderr, _("Exponential backoff\n")); + backoff_cnt++; + break; + + case UPDATE_PERM_DENIED: + if (debug) + fprintf(stderr, _("Full resync permission denied\n")); + syslog(LOG_ERR, _("Full resync, permission denied.")); + goto error; + + case UPDATE_ERROR: + if (debug) + fprintf(stderr, _("Full resync error from primary\n")); + syslog(LOG_ERR, _(" Full resync, " + "error returned from primary KDC.")); + goto error; + + default: + backoff_cnt = 0; + if (debug) { + fprintf(stderr, + _("Full resync invalid result from primary\n")); + } + syslog(LOG_ERR, _("Full resync, " + "invalid return from primary KDC.")); + break; + } + break; + + case UPDATE_OK: + backoff_cnt = 0; + frrequested = 0; + + /* + * ulog_replay() will convert the ulog updates to db + * entries using the kdb conv api and will commit + * the entries to the replica kdc database + */ + if (debug) { + fprintf(stderr, _("Got incremental updates " + "(sno=%u sec=%u usec=%u)\n"), + (unsigned int)incr_ret->lastentry.last_sno, + (unsigned int)incr_ret->lastentry.last_time.seconds, + (unsigned int)incr_ret->lastentry.last_time.useconds); + } + retval = ulog_replay(kpropd_context, incr_ret, db_args); + + if (retval) { + const char *msg = + krb5_get_error_message(kpropd_context, retval); + if (debug) { + fprintf(stderr, _("ulog_replay failed (%s), updates not " + "registered\n"), msg); + } + syslog(LOG_ERR, _("ulog_replay failed (%s), updates " + "not registered."), msg); + krb5_free_error_message(kpropd_context, msg); + break; + } + + gettimeofday(&iprop_end, NULL); + usec = (iprop_end.tv_sec - iprop_start.tv_sec) * 1000000 + + iprop_end.tv_usec - iprop_start.tv_usec; + syslog(LOG_INFO, _("Incremental updates: %d updates / %lu us"), + incr_ret->updates.kdb_ulog_t_len, usec); + if (debug) { + fprintf(stderr, _("Incremental updates: %d updates / " + "%lu us\n"), + incr_ret->updates.kdb_ulog_t_len, usec); + } + break; + + case UPDATE_PERM_DENIED: + if (debug) + fprintf(stderr, _("get_updates permission denied\n")); + syslog(LOG_ERR, _("get_updates, permission denied.")); + goto error; + + case UPDATE_ERROR: + if (debug) + fprintf(stderr, _("get_updates error from primary\n")); + syslog(LOG_ERR, + _("get_updates, error returned from primary KDC.")); + goto error; + + case UPDATE_BUSY: + /* + * Exponential backoff + */ + if (debug) + fprintf(stderr, _("get_updates primary busy; backoff\n")); + backoff_cnt++; + break; + + case UPDATE_NIL: + /* + * Primary-replica are in sync + */ + if (debug) + fprintf(stderr, _("KDC is synchronized with primary.\n")); + backoff_cnt = 0; + frrequested = 0; + break; + + default: + backoff_cnt = 0; + if (debug) { + fprintf(stderr, + _("get_updates invalid result from primary\n")); + } + syslog(LOG_ERR, + _("get_updates, invalid return from primary KDC.")); + break; + } + + if (runonce == 1 && incr_ret->ret != UPDATE_FULL_RESYNC_NEEDED) + goto done; + + /* + * Sleep for the specified poll interval (Default is 2 mts), + * or do a binary exponential backoff if we get an + * UPDATE_BUSY signal + */ + if (backoff_cnt > 0) { + backoff_time = backoff_from_primary(&backoff_cnt); + if (debug) { + fprintf(stderr, _("Busy signal received " + "from primary, backoff for %d secs\n"), + backoff_time); + } + sleep(backoff_time); + } else { + if (debug) { + fprintf(stderr, _("Waiting for %d seconds before checking " + "for updates again\n"), pollin); + } + sleep(pollin); + } + + } + + +error: + if (debug) + fprintf(stderr, _("ERROR returned by primary, bailing\n")); + syslog(LOG_ERR, _("ERROR returned by primary KDC, bailing.\n")); +done: + free(iprop_svc_princstr); + free(primary_svc_princstr); + krb5_free_principal(kpropd_context, iprop_svc_principal); + krb5_free_default_realm(kpropd_context, def_realm); + kadm5_destroy(server_handle); + krb5_db_fini(kpropd_context); + ulog_fini(kpropd_context); + krb5_free_context(kpropd_context); + + return (runonce == 1) ? 0 : 1; +} + + +/* Do exponential backoff, since primary KDC is BUSY or down. */ +static unsigned int +backoff_from_primary(int *cnt) +{ + unsigned int btime; + + btime = (unsigned int)(2<<(*cnt)); + if (btime > MAX_BACKOFF) { + btime = MAX_BACKOFF; + (*cnt)--; + } + + return btime; +} + +static void +kpropd_com_err_proc(const char *whoami, long code, const char *fmt, + va_list args) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 0))) +#endif + ; + +static void +kpropd_com_err_proc(const char *whoami, long code, const char *fmt, + va_list args) +{ + char error_buf[8096]; + + error_buf[0] = '\0'; + if (fmt) + vsnprintf(error_buf, sizeof(error_buf), fmt, args); + syslog(LOG_ERR, "%s%s%s%s%s", whoami ? whoami : "", whoami ? ": " : "", + code ? error_message(code) : "", code ? " " : "", error_buf); +} + +static void +parse_args(int argc, char **argv) +{ + char **newargs; + int c; + krb5_error_code retval; + enum { PID_FILE = 256 }; + struct option long_options[] = { + { "pid-file", 1, NULL, PID_FILE }, + { NULL, 0, NULL, 0 }, + }; + + memset(¶ms, 0, sizeof(params)); + + /* Since we may modify the KDB with ulog_replay(), we must read the KDC + * profile. */ + retval = krb5int_init_context_kdc(&kpropd_context); + if (retval) { + com_err(argv[0], retval, _("while initializing krb5")); + exit(1); + } + + progname = argv[0]; + while ((c = getopt_long(argc, argv, "A:f:F:p:P:r:s:DdSa:tx:", + long_options, NULL)) != -1) { + switch (c) { + case 'A': + params.mask |= KADM5_CONFIG_ADMIN_SERVER; + params.admin_server = optarg; + break; + case 'f': + file = optarg; + break; + case 'F': + kerb_database = optarg; + break; + case 'p': + kdb5_util = optarg; + break; + case 'P': + port = optarg; + break; + case 'r': + realm = optarg; + break; + case 's': + keytab_path = optarg; + break; + case 'D': + nodaemon++; + break; + case 'd': + debug++; + break; + case 'S': + /* Standalone mode is now auto-detected; see main(). */ + break; + case 'a': + acl_file_name = optarg; + break; + case 't': + /* Undocumented option - for testing only. Run the kpropd + * server exactly once. */ + runonce = 1; + break; + case 'x': + newargs = realloc(db_args, (db_args_size + 2) * sizeof(*db_args)); + if (newargs == NULL) { + com_err(argv[0], errno, _("copying db args")); + exit(1); + } + db_args = newargs; + db_args[db_args_size] = optarg; + db_args[db_args_size + 1] = NULL; + db_args_size++; + break; + case PID_FILE: + pid_file = optarg; + break; + default: + usage(); + } + } + if (optind != argc) + usage(); + + openlog("kpropd", LOG_PID | LOG_ODELAY, SYSLOG_CLASS); + if (!debug) + set_com_err_hook(kpropd_com_err_proc); + + if (realm == NULL) { + retval = krb5_get_default_realm(kpropd_context, &def_realm); + if (retval) { + com_err(progname, retval, _("Unable to get default realm")); + exit(1); + } + realm = def_realm; + } else { + retval = krb5_set_default_realm(kpropd_context, realm); + if (retval) { + com_err(progname, retval, _("Unable to set default realm")); + exit(1); + } + } + + /* Construct service name from local hostname. */ + retval = sn2princ_realm(kpropd_context, NULL, KPROP_SERVICE_NAME, realm, + &server); + if (retval) { + com_err(progname, retval, + _("while trying to construct my service name")); + exit(1); + } + + /* Construct the name of the temporary file. */ + if (asprintf(&temp_file_name, "%s.temp", file) < 0) { + com_err(progname, ENOMEM, + _("while allocating filename for temp file")); + exit(1); + } + + params.realm = realm; + params.mask |= KADM5_CONFIG_REALM; + retval = kadm5_get_config_params(kpropd_context, 1, ¶ms, ¶ms); + if (retval) { + com_err(progname, retval, _("while initializing")); + exit(1); + } + if (params.iprop_enabled == TRUE) { + ulog_set_role(kpropd_context, IPROP_REPLICA); + + if (ulog_map(kpropd_context, params.iprop_logfile, + params.iprop_ulogsize)) { + com_err(progname, errno, _("Unable to map log!\n")); + exit(1); + } + } +} + +/* + * Figure out who's calling on the other end of the connection.... + */ +static void +kerberos_authenticate(krb5_context context, int fd, krb5_principal *clientp, + krb5_enctype *etype, struct sockaddr_storage *my_sin) +{ + krb5_error_code retval; + krb5_ticket *ticket; + struct sockaddr_storage r_sin; + GETSOCKNAME_ARG3_TYPE sin_length; + krb5_keytab keytab = NULL; + char *name, etypebuf[100]; + + sin_length = sizeof(r_sin); + if (getsockname(fd, (struct sockaddr *)&r_sin, &sin_length)) { + com_err(progname, errno, _("while getting local socket address")); + exit(1); + } + + sockaddr2krbaddr(context, r_sin.ss_family, (struct sockaddr *)&r_sin, + &receiver_addr); + + if (debug) { + retval = krb5_unparse_name(context, server, &name); + if (retval) { + com_err(progname, retval, _("while unparsing client name")); + exit(1); + } + fprintf(stderr, "krb5_recvauth(%d, %s, %s, ...)\n", fd, kprop_version, + name); + free(name); + } + + retval = krb5_auth_con_init(context, &auth_context); + if (retval) { + syslog(LOG_ERR, _("Error in krb5_auth_con_ini: %s"), + error_message(retval)); + exit(1); + } + + retval = krb5_auth_con_setflags(context, auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE); + if (retval) { + syslog(LOG_ERR, _("Error in krb5_auth_con_setflags: %s"), + error_message(retval)); + exit(1); + } + + /* + * Do not set a remote address, to allow replication over a NAT that + * changes the client address. A reflection attack against kpropd is + * impossible because kpropd only sends one message at the end. + */ + retval = krb5_auth_con_setaddrs(context, auth_context, receiver_addr, + NULL); + if (retval) { + syslog(LOG_ERR, _("Error in krb5_auth_con_setaddrs: %s"), + error_message(retval)); + exit(1); + } + + if (keytab_path != NULL) { + retval = krb5_kt_resolve(context, keytab_path, &keytab); + if (retval) { + syslog(LOG_ERR, _("Error in krb5_kt_resolve: %s"), + error_message(retval)); + exit(1); + } + } + + retval = krb5_recvauth(context, &auth_context, &fd, kprop_version, server, + 0, keytab, &ticket); + if (retval) { + syslog(LOG_ERR, _("Error in krb5_recvauth: %s"), + error_message(retval)); + exit(1); + } + + retval = krb5_copy_principal(context, ticket->enc_part2->client, clientp); + if (retval) { + syslog(LOG_ERR, _("Error in krb5_copy_prinicpal: %s"), + error_message(retval)); + exit(1); + } + + *etype = ticket->enc_part.enctype; + + if (debug) { + retval = krb5_unparse_name(context, *clientp, &name); + if (retval) { + com_err(progname, retval, _("while unparsing client name")); + exit(1); + } + + retval = krb5_enctype_to_name(*etype, FALSE, etypebuf, + sizeof(etypebuf)); + if (retval) { + com_err(progname, retval, _("while unparsing ticket etype")); + exit(1); + } + + fprintf(stderr, _("authenticated client: %s (etype == %s)\n"), + name, etypebuf); + free(name); + } + + krb5_free_ticket(context, ticket); +} + +static krb5_boolean +authorized_principal(krb5_context context, krb5_principal p, + krb5_enctype auth_etype) +{ + char *name, *ptr, buf[1024]; + krb5_error_code retval; + FILE *acl_file; + int end; + krb5_enctype acl_etype; + + retval = krb5_unparse_name(context, p, &name); + if (retval) + return FALSE; + + acl_file = fopen(acl_file_name, "r"); + if (acl_file == NULL) + return FALSE; + + while (!feof(acl_file)) { + if (!fgets(buf, sizeof(buf), acl_file)) + break; + end = strlen(buf) - 1; + if (buf[end] == '\n') + buf[end] = '\0'; + if (!strncmp(name, buf, strlen(name))) { + ptr = buf + strlen(name); + + /* If the next character is not whitespace or null, then the match + * is only partial. Continue on to new lines. */ + if (*ptr != '\0' && !isspace((int)*ptr)) + continue; + + /* Otherwise, skip trailing whitespace. */ + for (; *ptr != '\0' && isspace((int)*ptr); ptr++) ; + + /* + * Now, look for an etype string. If there isn't one, return true. + * If there is an invalid string, continue. If there is a valid + * string, return true only if it matches the etype passed in, + * otherwise continue. + */ + if (*ptr != '\0' && + ((retval = krb5_string_to_enctype(ptr, &acl_etype)) || + (acl_etype != auth_etype))) + continue; + + free(name); + fclose(acl_file); + return TRUE; + } + } + free(name); + fclose(acl_file); + return FALSE; +} + +static void +recv_database(krb5_context context, int fd, int database_fd, + krb5_data *confmsg) +{ + uint64_t database_size, received_size; + int n; + char buf[1024]; + char dbsize_buf[KPROP_DBSIZE_MAX_BUFSIZ]; + krb5_data inbuf, outbuf; + krb5_error_code retval; + + /* Receive and decode size from client. */ + retval = krb5_read_message(context, &fd, &inbuf); + if (retval) { + send_error(context, fd, retval, "while reading database size"); + com_err(progname, retval, + _("while reading size of database from client")); + exit(1); + } + if (krb5_is_krb_error(&inbuf)) + recv_error(context, &inbuf); + retval = krb5_rd_safe(context,auth_context,&inbuf,&outbuf,NULL); + if (retval) { + send_error(context, fd, retval, "while decoding database size"); + krb5_free_data_contents(context, &inbuf); + com_err(progname, retval, + _("while decoding database size from client")); + exit(1); + } + + retval = decode_database_size(&outbuf, &database_size); + if (retval) { + send_error(context, fd, retval, "malformed database size message"); + com_err(progname, retval, + _("malformed database size message from client")); + exit(1); + } + + krb5_free_data_contents(context, &inbuf); + krb5_free_data_contents(context, &outbuf); + + /* Initialize the initial vector. */ + retval = krb5_auth_con_initivector(context, auth_context); + if (retval) { + send_error(context, fd, retval, + "failed while initializing i_vector"); + com_err(progname, retval, _("while initializing i_vector")); + exit(1); + } + + if (debug) + fprintf(stderr, _("Full propagation transfer started.\n")); + + /* Now start receiving the database from the net. */ + received_size = 0; + while (received_size < database_size) { + retval = krb5_read_message(context, &fd, &inbuf); + if (retval) { + snprintf(buf, sizeof(buf), + "while reading database block starting at offset %"PRIu64, + received_size); + com_err(progname, retval, "%s", buf); + send_error(context, fd, retval, buf); + exit(1); + } + if (krb5_is_krb_error(&inbuf)) + recv_error(context, &inbuf); + retval = krb5_rd_priv(context, auth_context, &inbuf, &outbuf, NULL); + if (retval) { + snprintf(buf, sizeof(buf), + "while decoding database block starting at offset %" + PRIu64, received_size); + com_err(progname, retval, "%s", buf); + send_error(context, fd, retval, buf); + krb5_free_data_contents(context, &inbuf); + exit(1); + } + n = write(database_fd, outbuf.data, outbuf.length); + krb5_free_data_contents(context, &inbuf); + if (n < 0) { + snprintf(buf, sizeof(buf), + "while writing database block starting at offset %"PRIu64, + received_size); + send_error(context, fd, errno, buf); + } else if ((unsigned int)n != outbuf.length) { + snprintf(buf, sizeof(buf), + "incomplete write while writing database block starting " + "at \noffset %"PRIu64" (%d written, %d expected)", + received_size, n, outbuf.length); + send_error(context, fd, KRB5KRB_ERR_GENERIC, buf); + } + received_size += outbuf.length; + krb5_free_data_contents(context, &outbuf); + } + + /* OK, we've seen the entire file. Did we get too many bytes? */ + if (received_size > database_size) { + snprintf(buf, sizeof(buf), + "Received %"PRIu64" bytes, expected %"PRIu64 + " bytes for database file", + received_size, database_size); + send_error(context, fd, KRB5KRB_ERR_GENERIC, buf); + } + + if (debug) + fprintf(stderr, _("Full propagation transfer finished.\n")); + + /* Create message acknowledging number of bytes received, but + * don't send it until kdb5_util returns successfully. */ + inbuf = make_data(dbsize_buf, sizeof(dbsize_buf)); + encode_database_size(database_size, &inbuf); + retval = krb5_mk_safe(context,auth_context,&inbuf,confmsg,NULL); + if (retval) { + com_err(progname, retval, "while encoding # of received bytes"); + send_error(context, fd, retval, "while encoding # of received bytes"); + exit(1); + } +} + + +static void +send_error(krb5_context context, int fd, krb5_error_code err_code, + char *err_text) +{ + krb5_error error; + const char *text; + krb5_data outbuf; + char buf[1024]; + + memset(&error, 0, sizeof(error)); + krb5_us_timeofday(context, &error.stime, &error.susec); + error.server = server; + error.client = client; + + text = (err_text != NULL) ? err_text : error_message(err_code); + + error.error = err_code - ERROR_TABLE_BASE_krb5; + if (error.error > 127) { + error.error = KRB_ERR_GENERIC; + if (err_text) { + snprintf(buf, sizeof(buf), "%s %s", error_message(err_code), + err_text); + text = buf; + } + } + error.text.length = strlen(text) + 1; + error.text.data = strdup(text); + if (error.text.data) { + if (!krb5_mk_error(context, &error, &outbuf)) { + (void)krb5_write_message(context, &fd, &outbuf); + krb5_free_data_contents(context, &outbuf); + } + free(error.text.data); + } +} + +void +recv_error(krb5_context context, krb5_data *inbuf) +{ + krb5_error *error; + krb5_error_code retval; + + retval = krb5_rd_error(context, inbuf, &error); + if (retval) { + com_err(progname, retval, + _("while decoding error packet from client")); + exit(1); + } + if (error->error == KRB_ERR_GENERIC) { + if (error->text.data) + fprintf(stderr, _("Generic remote error: %s\n"), error->text.data); + } else if (error->error) { + com_err(progname, + (krb5_error_code)error->error + ERROR_TABLE_BASE_krb5, + _("signaled from server")); + if (error->text.data) { + fprintf(stderr, _("Error text from client: %s\n"), + error->text.data); + } + } + krb5_free_error(context, error); + exit(1); +} + +static void +load_database(krb5_context context, char *kdb_util, char *database_file_name) +{ + static char *edit_av[10]; + int error_ret, child_pid, count; + + /* has been included, so BSD will be defined on + * BSD systems. */ +#if BSD > 0 && BSD <= 43 +#ifndef WEXITSTATUS +#define WEXITSTATUS(w) (w).w_retcode +#endif + union wait waitb; +#else + int waitb; +#endif + kdb_log_context *log_ctx; + + if (debug) + fprintf(stderr, "calling kdb5_util to load database\n"); + + log_ctx = context->kdblog_context; + + edit_av[0] = kdb_util; + count = 1; + if (realm) { + edit_av[count++] = "-r"; + edit_av[count++] = realm; + } + edit_av[count++] = "load"; + if (kerb_database) { + edit_av[count++] = "-d"; + edit_av[count++] = kerb_database; + } + if (log_ctx && log_ctx->iproprole == IPROP_REPLICA) + edit_av[count++] = "-i"; + edit_av[count++] = database_file_name; + edit_av[count++] = NULL; + + switch (child_pid = fork()) { + case -1: + com_err(progname, errno, _("while trying to fork %s"), kdb_util); + exit(1); + case 0: + execv(kdb_util, edit_av); + com_err(progname, errno, _("while trying to exec %s"), kdb_util); + _exit(1); + /*NOTREACHED*/ + default: + if (debug) + fprintf(stderr, "Load PID is %d\n", child_pid); + if (wait(&waitb) < 0) { + com_err(progname, errno, _("while waiting for %s"), kdb_util); + exit(1); + } + } + + if (!WIFEXITED(waitb)) { + com_err(progname, 0, _("%s load terminated"), kdb_util); + exit(1); + } + + error_ret = WEXITSTATUS(waitb); + if (error_ret) { + com_err(progname, 0, _("%s returned a bad exit status (%d)"), + kdb_util, error_ret); + exit(1); + } + return; +} + +/* + * Get the host base service name for the kiprop principal. Returns + * KADM5_OK on success. Caller must free the storage allocated + * for host_service_name. + */ +static kadm5_ret_t +kadm5_get_kiprop_host_srv_name(krb5_context context, const char *realm_name, + char **host_service_name) +{ + char *name, *host; + + host = params.admin_server; /* XXX */ + if (asprintf(&name, "%s/%s", KADM5_KIPROP_HOST_SERVICE, host) < 0) { + free(host); + return ENOMEM; + } + *host_service_name = name; + + return KADM5_OK; +} diff --git a/krb5-1.21.3/src/kprop/kpropd_rpc.c b/krb5-1.21.3/src/kprop/kpropd_rpc.c new file mode 100644 index 00000000..4877e37e --- /dev/null +++ b/krb5-1.21.3/src/kprop/kpropd_rpc.c @@ -0,0 +1,61 @@ +/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t -*- */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include /* for memset */ +#include "iprop.h" + +/* Default timeout can be changed using clnt_control() */ +static struct timeval TIMEOUT = { 25, 0 }; + +void * +iprop_null_1(void *argp, CLIENT *clnt) +{ + static char clnt_res; + + memset(&clnt_res, 0, sizeof(clnt_res)); + if (clnt_call (clnt, IPROP_NULL, + (xdrproc_t) xdr_void, (caddr_t) argp, + (xdrproc_t) xdr_void, (caddr_t) &clnt_res, + TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return ((void *)&clnt_res); +} + +kdb_incr_result_t * +iprop_get_updates_1(kdb_last_t *argp, CLIENT *clnt) +{ + static kdb_incr_result_t clnt_res; + + memset(&clnt_res, 0, sizeof(clnt_res)); + if (clnt_call (clnt, IPROP_GET_UPDATES, + (xdrproc_t) xdr_kdb_last_t, (caddr_t) argp, + (xdrproc_t) xdr_kdb_incr_result_t, (caddr_t) &clnt_res, + TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&clnt_res); +} + +kdb_fullresync_result_t * +iprop_full_resync_1(void *argp, CLIENT *clnt) +{ + static kdb_fullresync_result_t clnt_res; + + memset(&clnt_res, 0, sizeof(clnt_res)); + if (clnt_call (clnt, IPROP_FULL_RESYNC, + (xdrproc_t) xdr_void, (caddr_t) argp, + (xdrproc_t) xdr_kdb_fullresync_result_t, (caddr_t) &clnt_res, + TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&clnt_res); +} diff --git a/krb5-1.21.3/src/kprop/kproplog.c b/krb5-1.21.3/src/kprop/kproplog.c new file mode 100644 index 00000000..06af2a1d --- /dev/null +++ b/krb5-1.21.3/src/kprop/kproplog.c @@ -0,0 +1,561 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * This module will parse the update logs on the primary or replica servers. + */ + +#include "k5-int.h" +#include "k5-hex.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char *progname; + +static void +usage() +{ + fprintf(stderr, _("\nUsage: %s [-h] [-v] [-v] [-e num]\n\t%s -R\n\n"), + progname, progname); + exit(1); +} + +/* + * Print the attribute flags of principal in human readable form. + */ +static void +print_flags(unsigned int flags) +{ + char **attrstrs, **sp; + + if (krb5_flags_to_strings(flags, &attrstrs) != 0) { + printf("\t\t\t(error)\n"); + return; + } + for (sp = attrstrs; sp != NULL && *sp != NULL; sp++) { + printf("\t\t\t%s\n", *sp); + free(*sp); + } + free(attrstrs); +} + +/* ctime() for uint32_t* */ +static const char * +ctime_uint32(uint32_t *time32) +{ + time_t tmp; + const char *r; + + tmp = *time32; + r = ctime(&tmp); + return (r == NULL) ? "(error)" : r; +} + +/* Display time information. */ +static void +print_time(uint32_t *timep) +{ + if (*timep == 0L) + printf("\t\t\tNone\n"); + else + printf("\t\t\t%s", ctime_uint32(timep)); +} + +static void +print_deltat(uint32_t *deltat) +{ + krb5_error_code ret; + static char buf[30]; + + ret = krb5_deltat_to_string(*deltat, buf, sizeof(buf)); + if (ret) + printf("\t\t\t(error)\n"); + else + printf("\t\t\t%s\n", buf); +} + +/* Display string in hex primitive. */ +static void +print_hex(const char *tag, utf8str_t *str) +{ + unsigned int len; + char *hex; + + len = str->utf8str_t_len; + + if (k5_hex_encode(str->utf8str_t_val, len, FALSE, &hex) != 0) + abort(); + printf("\t\t\t%s(%d): 0x%s\n", tag, len, hex); + free(hex); +} + +/* Display string primitive. */ +static void +print_str(const char *tag, utf8str_t *str) +{ + krb5_error_code ret; + char *s; + + s = k5memdup0(str->utf8str_t_val, str->utf8str_t_len, &ret); + if (s == NULL) { + fprintf(stderr, _("\nCouldn't allocate memory")); + exit(1); + } + printf("\t\t\t%s(%d): %s\n", tag, str->utf8str_t_len, s); + free(s); +} + +/* Display data components. */ +static void +print_data(const char *tag, kdbe_data_t *data) +{ + printf("\t\t\tmagic: 0x%x\n", data->k_magic); + print_str(tag, &data->k_data); +} + +/* Display the principal components. */ +static void +print_princ(kdbe_princ_t *princ) +{ + int i, len; + kdbe_data_t *data; + + print_str("realm", &princ->k_realm); + + len = princ->k_components.k_components_len; + data = princ->k_components.k_components_val; + for (i = 0; i < len; i++, data++) + print_data("princ", data); +} + +/* Display individual key. */ +static void +print_key(kdbe_key_t *k) +{ + unsigned int i; + utf8str_t *str; + + printf("\t\t\tver: %d\n", k->k_ver); + printf("\t\t\tkvno: %d\n", k->k_kvno); + + for (i = 0; i < k->k_enctype.k_enctype_len; i++) + printf("\t\t\tenc type: 0x%x\n", k->k_enctype.k_enctype_val[i]); + + str = k->k_contents.k_contents_val; + for (i = 0; i < k->k_contents.k_contents_len; i++, str++) + print_hex("key", str); +} + +/* Display all key data. */ +static void +print_keydata(kdbe_key_t *keys, unsigned int len) +{ + unsigned int i; + + for (i = 0; i < len; i++, keys++) + print_key(keys); +} + +/* Display TL item. */ +static void +print_tl(kdbe_tl_t *tl) +{ + int i, len; + + printf("\t\t\ttype: 0x%x\n", tl->tl_type); + + len = tl->tl_data.tl_data_len; + + printf("\t\t\tvalue(%d): 0x", len); + for (i = 0; i < len; i++) + printf("%02x", (krb5_octet)tl->tl_data.tl_data_val[i]); + printf("\n"); +} + +/* Display TL data items. */ +static void +print_tldata(kdbe_tl_t *tldata, int len) +{ + int i; + + printf("\t\t\titems: %d\n", len); + for (i = 0; i < len; i++, tldata++) + print_tl(tldata); +} + +/* + * Print the individual types if verbose mode was specified. + * If verbose-verbose then print types along with respective values. + */ +static void +print_attr(kdbe_val_t *val, int vverbose) +{ + switch (val->av_type) { + case AT_ATTRFLAGS: + printf(_("\t\tAttribute flags\n")); + if (vverbose) + print_flags(val->kdbe_val_t_u.av_attrflags); + break; + case AT_MAX_LIFE: + printf(_("\t\tMaximum ticket life\n")); + if (vverbose) + print_deltat(&val->kdbe_val_t_u.av_max_life); + break; + case AT_MAX_RENEW_LIFE: + printf(_("\t\tMaximum renewable life\n")); + if (vverbose) + print_deltat(&val->kdbe_val_t_u.av_max_renew_life); + break; + case AT_EXP: + printf(_("\t\tPrincipal expiration\n")); + if (vverbose) + print_time(&val->kdbe_val_t_u.av_exp); + break; + case AT_PW_EXP: + printf(_("\t\tPassword expiration\n")); + if (vverbose) + print_time(&val->kdbe_val_t_u.av_pw_exp); + break; + case AT_LAST_SUCCESS: + printf(_("\t\tLast successful auth\n")); + if (vverbose) + print_time(&val->kdbe_val_t_u.av_last_success); + break; + case AT_LAST_FAILED: + printf(_("\t\tLast failed auth\n")); + if (vverbose) + print_time(&val->kdbe_val_t_u.av_last_failed); + break; + case AT_FAIL_AUTH_COUNT: + printf(_("\t\tFailed passwd attempt\n")); + if (vverbose) + printf("\t\t\t%d\n", val->kdbe_val_t_u.av_fail_auth_count); + break; + case AT_PRINC: + printf(_("\t\tPrincipal\n")); + if (vverbose) + print_princ(&val->kdbe_val_t_u.av_princ); + break; + case AT_KEYDATA: + printf(_("\t\tKey data\n")); + if (vverbose) { + print_keydata(val->kdbe_val_t_u.av_keydata.av_keydata_val, + val->kdbe_val_t_u.av_keydata.av_keydata_len); + } + break; + case AT_TL_DATA: + printf(_("\t\tTL data\n")); + if (vverbose) { + print_tldata(val->kdbe_val_t_u.av_tldata.av_tldata_val, + val->kdbe_val_t_u.av_tldata.av_tldata_len); + } + break; + case AT_LEN: + printf(_("\t\tLength\n")); + if (vverbose) + printf("\t\t\t%d\n", val->kdbe_val_t_u.av_len); + break; + case AT_PW_LAST_CHANGE: + printf(_("\t\tPassword last changed\n")); + if (vverbose) + print_time(&val->kdbe_val_t_u.av_pw_last_change); + break; + case AT_MOD_PRINC: + printf(_("\t\tModifying principal\n")); + if (vverbose) + print_princ(&val->kdbe_val_t_u.av_mod_princ); + break; + case AT_MOD_TIME: + printf(_("\t\tModification time\n")); + if (vverbose) + print_time(&val->kdbe_val_t_u.av_mod_time); + break; + case AT_MOD_WHERE: + printf(_("\t\tModified where\n")); + if (vverbose) + print_str("where", &val->kdbe_val_t_u.av_mod_where); + break; + case AT_PW_POLICY: + printf(_("\t\tPassword policy\n")); + if (vverbose) + print_str("policy", &val->kdbe_val_t_u.av_pw_policy); + break; + case AT_PW_POLICY_SWITCH: + printf(_("\t\tPassword policy switch\n")); + if (vverbose) + printf("\t\t\t%d\n", val->kdbe_val_t_u.av_pw_policy_switch); + break; + case AT_PW_HIST_KVNO: + printf(_("\t\tPassword history KVNO\n")); + if (vverbose) + printf("\t\t\t%d\n", val->kdbe_val_t_u.av_pw_hist_kvno); + break; + case AT_PW_HIST: + printf(_("\t\tPassword history\n")); + if (vverbose) + printf("\t\t\tPW history elided\n"); + break; + } /* switch */ + +} +/* + * Print the update entry information + */ +static void +print_update(kdb_hlog_t *ulog, uint32_t entry, uint32_t ulogentries, + unsigned int verbose) +{ + XDR xdrs; + uint32_t start_sno, i, j, indx; + char *dbprinc; + kdb_ent_header_t *indx_log; + kdb_incr_update_t upd; + + if (entry && (entry < ulog->kdb_num)) + start_sno = ulog->kdb_last_sno - entry; + else + start_sno = ulog->kdb_first_sno - 1; + + for (i = start_sno; i < ulog->kdb_last_sno; i++) { + indx = i % ulogentries; + + indx_log = INDEX(ulog, indx); + + /* + * Check for corrupt update entry + */ + if (indx_log->kdb_umagic != KDB_ULOG_MAGIC) { + fprintf(stderr, _("Corrupt update entry\n\n")); + exit(1); + } + + printf("---\n"); + printf(_("Update Entry\n")); + + printf(_("\tUpdate serial # : %u\n"), indx_log->kdb_entry_sno); + + /* The initial entry after a reset is a dummy entry; skip it. */ + if (indx_log->kdb_entry_size == 0) { + printf(_("\tDummy entry\n")); + continue; + } + + memset(&upd, 0, sizeof(kdb_incr_update_t)); + xdrmem_create(&xdrs, (char *)indx_log->entry_data, + indx_log->kdb_entry_size, XDR_DECODE); + if (!xdr_kdb_incr_update_t(&xdrs, &upd)) { + printf(_("Entry data decode failure\n\n")); + exit(1); + } + + printf(_("\tUpdate operation : ")); + if (upd.kdb_deleted) + printf(_("Delete\n")); + else + printf(_("Add\n")); + + dbprinc = malloc(upd.kdb_princ_name.utf8str_t_len + 1); + if (dbprinc == NULL) { + printf(_("Could not allocate principal name\n\n")); + exit(1); + } + strncpy(dbprinc, upd.kdb_princ_name.utf8str_t_val, + upd.kdb_princ_name.utf8str_t_len); + dbprinc[upd.kdb_princ_name.utf8str_t_len] = 0; + printf(_("\tUpdate principal : %s\n"), dbprinc); + + printf(_("\tUpdate size : %u\n"), indx_log->kdb_entry_size); + printf(_("\tUpdate committed : %s\n"), + indx_log->kdb_commit ? "True" : "False"); + + if (indx_log->kdb_time.seconds == 0L) { + printf(_("\tUpdate time stamp : None\n")); + } else{ + printf(_("\tUpdate time stamp : %s"), + ctime_uint32(&indx_log->kdb_time.seconds)); + } + + printf(_("\tAttributes changed : %d\n"), upd.kdb_update.kdbe_t_len); + + if (verbose) { + for (j = 0; j < upd.kdb_update.kdbe_t_len; j++) + print_attr(&upd.kdb_update.kdbe_t_val[j], verbose > 1 ? 1 : 0); + } + + xdr_free(xdr_kdb_incr_update_t, (char *)&upd); + free(dbprinc); + } +} + +/* Return a read-only mmap of the ulog, or NULL on failure. */ +static kdb_hlog_t * +map_ulog(const char *filename, int *fd_out) +{ + int fd; + struct stat st; + kdb_hlog_t *ulog = MAP_FAILED; + + *fd_out = -1; + + fd = open(filename, O_RDONLY); + if (fd == -1) + return NULL; + if (fstat(fd, &st) < 0) { + close(fd); + return NULL; + } + ulog = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (ulog == MAP_FAILED) { + close(fd); + return NULL; + } + *fd_out = fd; + return ulog; +} + +int +main(int argc, char **argv) +{ + int c, ulog_fd = -1; + unsigned int verbose = 0; + bool_t headeronly = FALSE, reset = FALSE; + uint32_t entry = 0; + krb5_context context; + kadm5_config_params params; + kdb_hlog_t *ulog = NULL; + + setlocale(LC_ALL, ""); + + progname = argv[0]; + + while ((c = getopt(argc, argv, "Rvhe:")) != -1) { + switch (c) { + case 'h': + headeronly = TRUE; + break; + case 'e': + entry = atoi(optarg); + break; + case 'R': + reset = TRUE; + break; + case 'v': + verbose++; + break; + default: + usage(); + } + } + + if (kadm5_init_krb5_context(&context)) { + fprintf(stderr, _("Unable to initialize Kerberos\n\n")); + exit(1); + } + + memset(¶ms, 0, sizeof(params)); + + if (kadm5_get_config_params(context, 1, ¶ms, ¶ms)) { + fprintf(stderr, _("Couldn't read database_name\n\n")); + exit(1); + } + + printf(_("\nKerberos update log (%s)\n"), params.iprop_logfile); + + if (reset) { + if (ulog_map(context, params.iprop_logfile, params.iprop_ulogsize)) { + fprintf(stderr, _("Unable to map log file %s\n\n"), + params.iprop_logfile); + exit(1); + } + if (ulog_init_header(context) != 0) { + fprintf(stderr, _("Couldn't reinitialize ulog file %s\n\n"), + params.iprop_logfile); + exit(1); + } + printf(_("Reinitialized the ulog.\n")); + ulog_fini(context); + goto done; + } + + ulog = map_ulog(params.iprop_logfile, &ulog_fd); + if (ulog == NULL) { + fprintf(stderr, _("Unable to map log file %s\n\n"), + params.iprop_logfile); + exit(1); + } + + if (ulog->kdb_hmagic != KDB_ULOG_HDR_MAGIC) { + fprintf(stderr, _("Corrupt header log, exiting\n\n")); + exit(1); + } + + printf(_("Update log dump :\n")); + printf(_("\tLog version # : %u\n"), ulog->db_version_num); + printf(_("\tLog state : ")); + switch (ulog->kdb_state) { + case KDB_STABLE: + printf(_("Stable\n")); + break; + case KDB_UNSTABLE: + printf(_("Unstable\n")); + break; + case KDB_CORRUPT: + printf(_("Corrupt\n")); + break; + default: + printf(_("Unknown state: %d\n"), ulog->kdb_state); + break; + } + printf(_("\tEntry block size : %u\n"), ulog->kdb_block); + printf(_("\tNumber of entries : %u\n"), ulog->kdb_num); + + if (ulog->kdb_last_sno == 0) { + printf(_("\tLast serial # : None\n")); + } else { + if (ulog->kdb_first_sno == 0) { + printf(_("\tFirst serial # : None\n")); + } else { + printf(_("\tFirst serial # : ")); + printf("%u\n", ulog->kdb_first_sno); + } + + printf(_("\tLast serial # : ")); + printf("%u\n", ulog->kdb_last_sno); + } + + if (ulog->kdb_last_time.seconds == 0L) { + printf(_("\tLast time stamp : None\n")); + } else { + if (ulog->kdb_first_time.seconds == 0L) { + printf(_("\tFirst time stamp : None\n")); + } else { + printf(_("\tFirst time stamp : %s"), + ctime_uint32(&ulog->kdb_first_time.seconds)); + } + + printf(_("\tLast time stamp : %s\n"), + ctime_uint32(&ulog->kdb_last_time.seconds)); + } + + if (!headeronly && ulog->kdb_num) + print_update(ulog, entry, params.iprop_ulogsize, verbose); + + printf("\n"); + +done: + close(ulog_fd); + kadm5_free_config_params(context, ¶ms); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/kprop/replica_update b/krb5-1.21.3/src/kprop/replica_update new file mode 100644 index 00000000..a8b49446 --- /dev/null +++ b/krb5-1.21.3/src/kprop/replica_update @@ -0,0 +1,30 @@ +#!/bin/sh +# +# Propagate if database (principal.db) has been modified since last dump +# (dumpfile.dump_ok) or if database has been dumped since last successful +# propagation (dumpfile..last_prop) + +KDB_DIR=/usr/local/var/krb5kdc + +KDB_FILE=$KDB_DIR/principal.db +DUMPFILE=$KDB_DIR/replica_datatrans +KDB5_UTIL=/usr/local/sbin/kdb5_util +KPROP=/usr/local/sbin/kprop + +REPLICA=$1 +if [ -z "${REPLICA}" ] +then + echo "Usage $0 replica_server" +fi + +if [ "`ls -t $DUMPFILE.dump_ok $KDB_FILE | sed -n 1p`" = "$KDB_FILE" -o \ + "`ls -t $DUMPFILE.${REPLICA}.last_prop $DUMPFILE.dump_ok | \ + sed -n 1p`" = "$DUMPFILE.dump_ok" ] +then + + date + $KDB5_UTIL dump $DUMPFILE > /dev/null + + $KPROP -d -f $DUMPFILE ${REPLICA} + rm $DUMPFILE +fi diff --git a/krb5-1.21.3/src/lib/Makefile.in b/krb5-1.21.3/src/lib/Makefile.in new file mode 100644 index 00000000..3b812ed8 --- /dev/null +++ b/krb5-1.21.3/src/lib/Makefile.in @@ -0,0 +1,145 @@ +mydir=lib +SUBDIRS=crypto krb5 gssapi rpc kdb kadm5 apputils krad +WINSUBDIRS=crypto krb5 gssapi +BUILDTOP=$(REL).. + +all-unix: + +CLEANLIBS = libkrb5.a libkdb5.a libcrypto.a libgssapi_krb5.a libkadm.a \ + libcom_err.a libpty.a ibss.a libgssapi.a libapputils.a libkrb5.so \ + libcrypto.so + +clean-unix:: + +clean-windows:: + +# Windows stuff to make krb5 and gssapi DLLs. + +##MIT##!if !defined(VS_INC) +##MIT##!message Must define VS_INC to point to version server include dir! +##MIT##!error +##MIT##!endif +##MIT##!if !defined(VS_LIB) +##MIT##!message Must define VS_LIB to point to version server library! +##MIT##!error +##MIT##!endif +##MIT##MITLIBS=$(VS_LIB) +##MIT##MITFLAGS=-I$(VS_INC) /DVERSERV=1 + + + +##WIN32##SLIBS = $(BUILDTOP)\util\support\$(OUTPRE)k5sprt$(BITS).lib +##WIN32##CLIBS = $(BUILDTOP)\util\et\$(OUTPRE)comerr.lib +##WIN32##PLIBS = $(BUILDTOP)\util\profile\$(OUTPRE)profile.lib +##WIN32##KLIBS = krb5\$(OUTPRE)krb5.lib crypto\$(OUTPRE)crypto.lib \ +##WIN32## $(BUILDTOP)\util\profile\$(OUTPRE)profile.lib +##WIN32##GLIBS = gssapi\$(OUTPRE)gssapi.lib + + +##WIN32##SDEF = k5sprt32.def +##WIN32##CDEF = comerr32.def +##WIN32##PDEF = xpprof32.def +##WIN32##KDEF = krb5_32.def +##WIN32##GDEF = gssapi32.def + + + +##WIN32##KRB5RC = krb5.rc +##WIN32##VERSIONRC = $(BUILDTOP)\windows\version.rc + +##WIN32##!if defined(VISUALSTUDIOVERSION) +##WIN32##!if $(VISUALSTUDIOVERSION:.=) >= 140 +##WIN32##!ifdef NODEBUG +##WIN32##WINCRTEXTRA = ucrt.lib vcruntime.lib +##WIN32##!else +##WIN32##WINCRTEXTRA = ucrtd.lib vcruntimed.lib +##WIN32##!endif +##WIN32##!endif +##WIN32##!endif +##WIN32##WINLIBS = kernel32.lib ws2_32.lib user32.lib shell32.lib oldnames.lib \ +##WIN32## version.lib secur32.lib advapi32.lib gdi32.lib delayimp.lib \ +##WIN32## $(WINCRTEXTRA) +##WIN32##WINDLLFLAGS = $(DLL_LINKOPTS) -base:0x1c000000 /DELAYLOAD:secur32.dll \ +##WIN32## /DELAYLOAD:advapi32.dll /DELAY:UNLOAD /DELAY:NOBIND + +##WIN32##S_GLUE=$(OUTPRE)support_glue.obj +##WIN32##K5_GLUE=$(OUTPRE)k5_glue.obj +##WIN32##GSS_GLUE=$(OUTPRE)gss_glue.obj +##WIN32##COMERR_GLUE=$(OUTPRE)comerr_glue.obj +##WIN32##PROF_GLUE=$(OUTPRE)prof_glue.obj + +##WIN32##SGLUE=$(S_GLUE) +##WIN32##CGLUE=$(COMERR_GLUE) +##WIN32##PGLUE=$(PROF_GLUE) +##WIN32##KGLUE=$(K5_GLUE) +##WIN32##GGLUE=$(GSS_GLUE) + +##WIN32##RCFLAGS=$(CPPFLAGS) -I$(top_srcdir) -D_WIN32 -DRES_ONLY + +##WIN32##SRES=$(SLIB:.lib=.res) +##WIN32##CRES=$(CLIB:.lib=.res) +##WIN32##PRES=$(PLIB:.lib=.res) +##WIN32##KRES=$(KLIB:.lib=.res) +##WIN32##GRES=$(GLIB:.lib=.res) + +##WIN32##$(SRES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DSUPPORT_LIB -fo $@ -r $** +##WIN32##$(CRES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DCE_LIB -fo $@ -r $** +##WIN32##$(PRES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DPROF_LIB -fo $@ -r $** +##WIN32##$(KRES): $(KRB5RC) +##WIN32## $(RC) $(RCFLAGS) -DKRB5_LIB -fo $@ -r $** +##WIN32##$(GRES): $(VERSIONRC) +##WIN32## $(RC) $(RCFLAGS) -DGSSAPI_LIB -fo $@ -r $** +##WIN32##$(KRB5RC): $(VERSIONRC) + +##WIN32##$(SLIB): $(SDEF) $(SLIBS) $(SGLUE) $(SRES) +##WIN32## link $(WINDLLFLAGS) -def:$(SDEF) -out:$*.dll \ +##WIN32## $(SLIBS) $(SGLUE) $(SRES) $(WINLIBS) +##WIN32## $(_VC_MANIFEST_EMBED_DLL) +##WIN32##$(SDEF): ..\util\support\libkrb5support.exports +##WIN32## echo EXPORTS > $(SDEF).new +##WIN32## type ..\util\support\libkrb5support.exports >> $(SDEF).new +##WIN32## -$(RM) $(SDEF) +##WIN32## ren $(SDEF).new $(SDEF) + +##WIN32##$(CLIB): $(CDEF) $(CLIBS) $(CGLUE) $(CRES) $(SLIB) +##WIN32## link $(WINDLLFLAGS) -def:$(CDEF) -out:$*.dll \ +##WIN32## $(CLIBS) $(CGLUE) $(CRES) $(SLIB) $(WINLIBS) +##WIN32## $(_VC_MANIFEST_EMBED_DLL) + +##WIN32##$(PLIB): $(PDEF) $(PLIBS) $(PGLUE) $(PRES) $(CLIB) $(SLIB) +##WIN32## link $(WINDLLFLAGS) -def:$(PDEF) -out:$*.dll \ +##WIN32## $(PLIBS) $(PGLUE) $(PRES) $(CLIB) $(SLIB) $(WINLIBS) +##WIN32## $(_VC_MANIFEST_EMBED_DLL) + +##WIN32##$(KLIB): $(KDEF) $(KLIBS) $(KGLUE) $(KRES) $(CLIB) $(SLIB) $(MITLIBS) +##WIN32## link $(WINDLLFLAGS) -def:$(KDEF) -out:$*.dll \ +##WIN32## $(KLIBS) $(KGLUE) $(KRES) $(CLIB) $(SLIB) $(MITLIBS) $(DNSLIBS) $(WINLIBS) +##WIN32## $(_VC_MANIFEST_EMBED_DLL) + +##WIN32##$(GLIB): $(GDEF) $(GLIBS) $(GGLUE) $(GRES) $(KLIB) $(CLIB) $(SLIB) +##WIN32## link $(WINDLLFLAGS) -def:$(GDEF) -out:$*.dll \ +##WIN32## $(GLIBS) $(GGLUE) $(GRES) $(KLIB) $(CLIB) $(SLIB) $(WINLIBS) +##WIN32## $(_VC_MANIFEST_EMBED_DLL) + +##WIN32##$(K5_GLUE): win_glue.c +##WIN32## $(CC) $(ALL_CFLAGS) $(MITFLAGS) /c /DKRB5=1 /Fo$@ $** +##WIN32##$(GSS_GLUE): win_glue.c +##WIN32## $(CC) $(ALL_CFLAGS) /c /DGSSAPI=1 /Fo$@ $** +##WIN32##$(COMERR_GLUE): win_glue.c +##WIN32## $(CC) $(ALL_CFLAGS) /c /DCOMERR=1 /Fo$@ $** +##WIN32##$(PROF_GLUE): win_glue.c +##WIN32## $(CC) $(ALL_CFLAGS) /c /DPROFILELIB=1 /Fo$@ $** +##WIN32##$(S_GLUE): win_glue.c +##WIN32## $(CC) $(ALL_CFLAGS) /c /DSUPPORTLIB=1 /Fo$@ $** + +##WIN32### Build Convenience +##WIN32##comerr.lib: $(CLIB) +##WIN32##krb5.lib: $(KLIB) +##WIN32##gssapi.lib: $(GLIB) +##WIN32##profile.lib: $(PLIB) + +##WIN32##all-windows: all-recurse lib-windows +##WIN32##lib-windows: krb5.lib gssapi.lib profile.lib diff --git a/krb5-1.21.3/src/lib/apputils/Makefile.in b/krb5-1.21.3/src/lib/apputils/Makefile.in new file mode 100644 index 00000000..93e3d87e --- /dev/null +++ b/krb5-1.21.3/src/lib/apputils/Makefile.in @@ -0,0 +1,33 @@ +prefix=@prefix@ +bindir=@bindir@ +datadir=@datadir@ +mydatadir=$(datadir)/apputils +mydir=lib$(S)apputils +BUILDTOP=$(REL)..$(S).. +RELDIR=../lib/apputils +SED = sed + +##DOS##BUILDTOP = ..\.. +##DOS##LIBNAME=$(OUTPRE)apputils.lib +##DOS##XTRA= +##DOS##OBJFILE=$(OUTPRE)apputils.lst + +STLIBOBJS=net-server.o udppktinfo.o @LIBOBJS@ +LIBBASE=apputils + +all-unix: all-liblinks +clean-unix:: clean-liblinks clean-libs clean-libobjs +install-unix: install-libs + +LINTFLAGS=-uhvb +LINTFILES= daemon.c +LIBOBJS=$(OUTPRE)daemon.$(OBJEXT) + +SRCS= $(srcdir)/daemon.c \ + $(srcdir)/net-server.c \ + $(srcdir)/udppktinfo.c + +@libpriv_frag@ +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/apputils/daemon.c b/krb5-1.21.3/src/lib/apputils/daemon.c new file mode 100644 index 00000000..a3d7cd73 --- /dev/null +++ b/krb5-1.21.3/src/lib/apputils/daemon.c @@ -0,0 +1,96 @@ +/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t -*- */ +/* + * Copyright (c) 1990 The Regents of the University of California. + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "k5-int.h" +#include +#include +#include +#include +#ifdef HAVE_PATHS_H +#include +#endif + +#ifndef _PATH_DEVNULL +#define _PATH_DEVNULL "/dev/null" +#endif + +int +daemon(nochdir, noclose) + int nochdir, noclose; +{ + int cpid; + + if ((cpid = fork()) == -1) + return (-1); + if (cpid) + exit(0); +#ifdef HAVE_SETSID + (void) setsid(); +#else +#ifndef TIOCNOTTY + setpgrp(); +#else + { + int n; + + /* + * The open below may hang on pseudo ttys if the person + * who starts named logs out before this point. Thus, + * the need for the timer. + */ + alarm(120); + n = open("/dev/tty", O_RDWR); + alarm(0); + if (n > 0) { + (void) ioctl(n, TIOCNOTTY, (char *)NULL); + (void) close(n); + } + } +#endif +#endif + if (!nochdir) + (void) chdir("/"); + if (!noclose) { + int devnull = open(_PATH_DEVNULL, O_RDWR, 0); + + if (devnull != -1) { + (void) dup2(devnull, 0); + (void) dup2(devnull, 1); + (void) dup2(devnull, 2); + if (devnull > 2) + (void) close(devnull); + } + } + return (0); +} diff --git a/krb5-1.21.3/src/lib/apputils/deps b/krb5-1.21.3/src/lib/apputils/deps new file mode 100644 index 00000000..9605f5c9 --- /dev/null +++ b/krb5-1.21.3/src/lib/apputils/deps @@ -0,0 +1,43 @@ +# +# Generated makefile dependencies follow. +# +daemon.so daemon.po $(OUTPRE)daemon.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h daemon.c +net-server.so net-server.po $(OUTPRE)net-server.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(VERTO_DEPS) $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/fake-addrinfo.h $(top_srcdir)/include/foreachaddr.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/net-server.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h net-server.c udppktinfo.h +udppktinfo.so udppktinfo.po $(OUTPRE)udppktinfo.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + udppktinfo.c udppktinfo.h diff --git a/krb5-1.21.3/src/lib/apputils/net-server.c b/krb5-1.21.3/src/lib/apputils/net-server.c new file mode 100644 index 00000000..1bdc7932 --- /dev/null +++ b/krb5-1.21.3/src/lib/apputils/net-server.c @@ -0,0 +1,1522 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/apputils/net-server.c - Network code for krb5 servers (kdc, kadmind) */ +/* + * Copyright 1990,2000,2007,2008,2009,2010,2016 by the Massachusetts Institute + * of Technology. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "adm_proto.h" +#include +#include + +#include +#include "port-sockets.h" +#include "socket-utils.h" + +#include + +#ifdef HAVE_NETINET_IN_H +#include +#include +#include +#ifdef HAVE_SYS_SOCKIO_H +/* for SIOCGIFCONF, etc. */ +#include +#endif +#include +#if HAVE_SYS_SELECT_H +#include +#endif +#include + +#ifndef ARPHRD_ETHER /* OpenBSD breaks on multiple inclusions */ +#include +#endif + +#ifdef HAVE_SYS_FILIO_H +#include /* FIONBIO */ +#endif + +#include "fake-addrinfo.h" +#include "net-server.h" +#include +#include + +#include "udppktinfo.h" + +/* XXX */ +#define KDC5_NONET (-1779992062L) + +static int tcp_or_rpc_data_counter; +static int max_tcp_or_rpc_data_connections = 45; + +static int +setreuseaddr(int sock, int value) +{ + int st; + + st = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)); + if (st) + return st; +#ifdef SO_REUSEPORT + st = setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)); + if (st) + return st; +#endif + return 0; +} + +#if defined(IPV6_V6ONLY) +static int +setv6only(int sock, int value) +{ + return setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &value, sizeof(value)); +} +#endif + +static const char * +paddr(struct sockaddr *sa) +{ + static char buf[100]; + char portbuf[10]; + if (getnameinfo(sa, sa_socklen(sa), + buf, sizeof(buf), portbuf, sizeof(portbuf), + NI_NUMERICHOST|NI_NUMERICSERV)) + strlcpy(buf, "", sizeof(buf)); + else { + unsigned int len = sizeof(buf) - strlen(buf); + char *p = buf + strlen(buf); + if (len > 2+strlen(portbuf)) { + *p++ = '.'; + len--; + strncpy(p, portbuf, len); + } + } + return buf; +} + +/* KDC data. */ + +enum conn_type { + CONN_UDP, CONN_TCP_LISTENER, CONN_TCP, CONN_RPC_LISTENER, CONN_RPC +}; + +enum bind_type { + UDP, TCP, RPC +}; + +static const char *const bind_type_names[] = { + [UDP] = "UDP", + [TCP] = "TCP", + [RPC] = "RPC", +}; + +/* Per-connection info. */ +struct connection { + void *handle; + const char *prog; + enum conn_type type; + + /* Connection fields (TCP or RPC) */ + struct sockaddr_storage addr_s; + socklen_t addrlen; + char addrbuf[56]; + krb5_address remote_addr_buf; + krb5_fulladdr remote_addr; + + /* Incoming data (TCP) */ + size_t bufsiz; + size_t offset; + char *buffer; + size_t msglen; + + /* Outgoing data (TCP) */ + krb5_data *response; + unsigned char lenbuf[4]; + sg_buf sgbuf[2]; + sg_buf *sgp; + int sgnum; + + /* Crude denial-of-service avoidance support (TCP or RPC) */ + time_t start_time; + + /* RPC-specific fields */ + SVCXPRT *transp; + int rpc_force_close; +}; + +#define SET(TYPE) struct { TYPE *data; size_t n, max; } + +/* Start at the top and work down -- this should allow for deletions + without disrupting the iteration, since we delete by overwriting + the element to be removed with the last element. */ +#define FOREACH_ELT(set,idx,vvar) \ + for (idx = set.n-1; idx >= 0 && (vvar = set.data[idx], 1); idx--) + +#define GROW_SET(set, incr, tmpptr) \ + ((set.max + incr < set.max \ + || ((set.max + incr) * sizeof(set.data[0]) / sizeof(set.data[0]) \ + != set.max + incr)) \ + ? 0 /* overflow */ \ + : ((tmpptr = realloc(set.data, \ + (set.max + incr) * sizeof(set.data[0]))) \ + ? (set.data = tmpptr, set.max += incr, 1) \ + : 0)) + +/* 1 = success, 0 = failure */ +#define ADD(set, val, tmpptr) \ + ((set.n < set.max || GROW_SET(set, 10, tmpptr)) \ + ? (set.data[set.n++] = val, 1) \ + : 0) + +#define DEL(set, idx) \ + (set.data[idx] = set.data[--set.n], 0) + +#define FREE_SET_DATA(set) \ + (free(set.data), set.data = 0, set.max = 0, set.n = 0) + +/* + * N.B.: The Emacs cc-mode indentation code seems to get confused if + * the macro argument here is one word only. So use "unsigned short" + * instead of the "u_short" we were using before. + */ +struct rpc_svc_data { + u_long prognum; + u_long versnum; + void (*dispatch)(); +}; + +struct bind_address { + char *address; + u_short port; + enum bind_type type; + struct rpc_svc_data rpc_svc_data; +}; + +static SET(verto_ev *) events; +static SET(struct bind_address) bind_addresses; + +verto_ctx * +loop_init(verto_ev_type types) +{ + types |= VERTO_EV_TYPE_IO; + types |= VERTO_EV_TYPE_SIGNAL; + types |= VERTO_EV_TYPE_TIMEOUT; + return verto_default(NULL, types); +} + +static void +do_break(verto_ctx *ctx, verto_ev *ev) +{ + krb5_klog_syslog(LOG_DEBUG, _("Got signal to request exit")); + verto_break(ctx); +} + +struct sighup_context { + void *handle; + void (*reset)(void *); +}; + +static void +do_reset(verto_ctx *ctx, verto_ev *ev) +{ + struct sighup_context *sc = (struct sighup_context*) verto_get_private(ev); + + krb5_klog_syslog(LOG_DEBUG, _("Got signal to reset")); + krb5_klog_reopen(get_context(sc->handle)); + if (sc->reset) + sc->reset(sc->handle); +} + +static void +free_sighup_context(verto_ctx *ctx, verto_ev *ev) +{ + free(verto_get_private(ev)); +} + +krb5_error_code +loop_setup_signals(verto_ctx *ctx, void *handle, void (*reset)()) +{ + struct sighup_context *sc; + verto_ev *ev; + + if (!verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_break, SIGINT) || + !verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_break, SIGTERM) || + !verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_break, SIGQUIT) || + !verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, VERTO_SIG_IGN, SIGPIPE)) + return ENOMEM; + + ev = verto_add_signal(ctx, VERTO_EV_FLAG_PERSIST, do_reset, SIGHUP); + if (!ev) + return ENOMEM; + + sc = malloc(sizeof(*sc)); + if (!sc) + return ENOMEM; + + sc->handle = handle; + sc->reset = reset; + verto_set_private(ev, sc, free_sighup_context); + return 0; +} + +/* + * Add a bind address to the loop. + * + * Arguments: + * - address + * A string for the address (or hostname). Pass NULL to use the wildcard + * address. The address is parsed with k5_parse_host_string(). + * - port + * What port the socket should be set to. + * - type + * bind_type for the socket. + * - rpc_data + * For RPC addresses, the svc_register() arguments to use when TCP + * connections are created. Ignored for other types. + */ +static krb5_error_code +loop_add_address(const char *address, int port, enum bind_type type, + struct rpc_svc_data *rpc_data) +{ + struct bind_address addr, val; + int i; + void *tmp; + char *addr_copy = NULL; + + assert(!(type == RPC && rpc_data == NULL)); + + /* Make sure a valid port number was passed. */ + if (port < 0 || port > 65535) { + krb5_klog_syslog(LOG_ERR, _("Invalid port %d"), port); + return EINVAL; + } + + /* Check for conflicting addresses. */ + FOREACH_ELT(bind_addresses, i, val) { + if (type != val.type || port != val.port) + continue; + + /* If a wildcard address is being added, make sure to remove any direct + * addresses. */ + if (address == NULL && val.address != NULL) { + krb5_klog_syslog(LOG_DEBUG, + _("Removing address %s since wildcard address" + " is being added"), + val.address); + free(val.address); + DEL(bind_addresses, i); + } else if (val.address == NULL || !strcmp(address, val.address)) { + krb5_klog_syslog(LOG_DEBUG, + _("Address already added to server")); + return 0; + } + } + + /* Copy the address if it is specified. */ + if (address != NULL) { + addr_copy = strdup(address); + if (addr_copy == NULL) + return ENOMEM; + } + + /* Add the new address to bind_addresses. */ + memset(&addr, 0, sizeof(addr)); + addr.address = addr_copy; + addr.port = port; + addr.type = type; + if (rpc_data != NULL) + addr.rpc_svc_data = *rpc_data; + if (!ADD(bind_addresses, addr, tmp)) { + free(addr_copy); + return ENOMEM; + } + + return 0; +} + +/* + * Add bind addresses to the loop. + * + * Arguments: + * + * - addresses + * A string for the addresses. Pass NULL to use the wildcard address. + * Supported delimiters can be found in ADDRESSES_DELIM. Addresses are + * parsed with k5_parse_host_name(). + * - default_port + * What port the socket should be set to if not specified in addresses. + * - type + * bind_type for the socket. + * - rpc_data + * For RPC addresses, the svc_register() arguments to use when TCP + * connections are created. Ignored for other types. + */ +static krb5_error_code +loop_add_addresses(const char *addresses, int default_port, + enum bind_type type, struct rpc_svc_data *rpc_data) +{ + krb5_error_code ret = 0; + char *addresses_copy = NULL, *host = NULL, *saveptr, *addr; + int port; + + /* If no addresses are set, add a wildcard address. */ + if (addresses == NULL) + return loop_add_address(NULL, default_port, type, rpc_data); + + /* Copy the addresses string before using strtok(). */ + addresses_copy = strdup(addresses); + if (addresses_copy == NULL) { + ret = ENOMEM; + goto cleanup; + } + + /* Start tokenizing the addresses string. If we get NULL the string + * contained no addresses, so add a wildcard address. */ + addr = strtok_r(addresses_copy, ADDRESSES_DELIM, &saveptr); + if (addr == NULL) { + ret = loop_add_address(NULL, default_port, type, rpc_data); + goto cleanup; + } + + /* Loop through each address and add it to the loop. */ + for (; addr != NULL; addr = strtok_r(NULL, ADDRESSES_DELIM, &saveptr)) { + /* Parse the host string. */ + ret = k5_parse_host_string(addr, default_port, &host, &port); + if (ret) + goto cleanup; + + ret = loop_add_address(host, port, type, rpc_data); + if (ret) + goto cleanup; + + free(host); + host = NULL; + } + +cleanup: + free(addresses_copy); + free(host); + return ret; +} + +krb5_error_code +loop_add_udp_address(int default_port, const char *addresses) +{ + return loop_add_addresses(addresses, default_port, UDP, NULL); +} + +krb5_error_code +loop_add_tcp_address(int default_port, const char *addresses) +{ + return loop_add_addresses(addresses, default_port, TCP, NULL); +} + +krb5_error_code +loop_add_rpc_service(int default_port, const char *addresses, u_long prognum, + u_long versnum, void (*dispatchfn)()) +{ + struct rpc_svc_data svc; + + svc.prognum = prognum; + svc.versnum = versnum; + svc.dispatch = dispatchfn; + return loop_add_addresses(addresses, default_port, RPC, &svc); +} + +#define USE_AF AF_INET +#define USE_TYPE SOCK_DGRAM +#define USE_PROTO 0 +#define SOCKET_ERRNO errno +#include "foreachaddr.h" + +static void +free_connection(struct connection *conn) +{ + if (!conn) + return; + if (conn->response) + krb5_free_data(get_context(conn->handle), conn->response); + if (conn->buffer) + free(conn->buffer); + if (conn->type == CONN_RPC_LISTENER && conn->transp != NULL) + svc_destroy(conn->transp); + free(conn); +} + +static void +remove_event_from_set(verto_ev *ev) +{ + verto_ev *tmp; + int i; + + /* Remove the event from the events. */ + FOREACH_ELT(events, i, tmp) + if (tmp == ev) { + DEL(events, i); + break; + } +} + +static void +free_socket(verto_ctx *ctx, verto_ev *ev) +{ + struct connection *conn = NULL; + fd_set fds; + int fd; + + remove_event_from_set(ev); + + fd = verto_get_fd(ev); + conn = verto_get_private(ev); + + /* Close the file descriptor. */ + krb5_klog_syslog(LOG_INFO, _("closing down fd %d"), fd); + if (fd >= 0 && (!conn || conn->type != CONN_RPC || conn->rpc_force_close)) + close(fd); + + /* Free the connection struct. */ + if (conn) { + switch (conn->type) { + case CONN_RPC: + if (conn->rpc_force_close) { + FD_ZERO(&fds); + FD_SET(fd, &fds); + svc_getreqset(&fds); + if (FD_ISSET(fd, &svc_fdset)) { + krb5_klog_syslog(LOG_ERR, + _("descriptor %d closed but still " + "in svc_fdset"), + fd); + } + } + /* Fall through. */ + case CONN_TCP: + tcp_or_rpc_data_counter--; + break; + default: + break; + } + + free_connection(conn); + } +} + +static verto_ev * +make_event(verto_ctx *ctx, verto_ev_flag flags, verto_callback callback, + int sock, struct connection *conn) +{ + verto_ev *ev; + void *tmp; + + ev = verto_add_io(ctx, flags, callback, sock); + if (!ev) { + com_err(conn->prog, ENOMEM, _("cannot create io event")); + return NULL; + } + + if (!ADD(events, ev, tmp)) { + com_err(conn->prog, ENOMEM, _("cannot save event")); + verto_del(ev); + return NULL; + } + + verto_set_private(ev, conn, free_socket); + return ev; +} + +static krb5_error_code +add_fd(int sock, enum conn_type conntype, verto_ev_flag flags, void *handle, + const char *prog, verto_ctx *ctx, verto_callback callback, + verto_ev **ev_out) +{ + struct connection *newconn; + + *ev_out = NULL; + +#ifndef _WIN32 + if (sock >= FD_SETSIZE) { + com_err(prog, 0, _("file descriptor number %d too high"), sock); + return EMFILE; + } +#endif + newconn = malloc(sizeof(*newconn)); + if (newconn == NULL) { + com_err(prog, ENOMEM, + _("cannot allocate storage for connection info")); + return ENOMEM; + } + memset(newconn, 0, sizeof(*newconn)); + newconn->handle = handle; + newconn->prog = prog; + newconn->type = conntype; + + *ev_out = make_event(ctx, flags, callback, sock, newconn); + return 0; +} + +static void process_packet(verto_ctx *ctx, verto_ev *ev); +static void accept_tcp_connection(verto_ctx *ctx, verto_ev *ev); +static void process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev); +static void process_tcp_connection_write(verto_ctx *ctx, verto_ev *ev); +static void accept_rpc_connection(verto_ctx *ctx, verto_ev *ev); +static void process_rpc_connection(verto_ctx *ctx, verto_ev *ev); + +/* + * Create a socket and bind it to addr. Ensure the socket will work with + * select(). Set the socket cloexec, reuseaddr, and if applicable v6-only. + * Does not call listen(). On failure, log an error and return an error code. + */ +static krb5_error_code +create_server_socket(struct sockaddr *addr, int type, const char *prog, + int *fd_out) +{ + int sock, e; + + *fd_out = -1; + + sock = socket(addr->sa_family, type, 0); + if (sock == -1) { + e = errno; + com_err(prog, e, _("Cannot create TCP server socket on %s"), + paddr(addr)); + return e; + } + set_cloexec_fd(sock); + +#ifndef _WIN32 /* Windows FD_SETSIZE is a count. */ + if (sock >= FD_SETSIZE) { + close(sock); + com_err(prog, 0, _("TCP socket fd number %d (for %s) too high"), + sock, paddr(addr)); + return EMFILE; + } +#endif + + if (setreuseaddr(sock, 1) < 0) + com_err(prog, errno, _("Cannot enable SO_REUSEADDR on fd %d"), sock); + + if (addr->sa_family == AF_INET6) { +#ifdef IPV6_V6ONLY + if (setv6only(sock, 1)) { + com_err(prog, errno, _("setsockopt(%d,IPV6_V6ONLY,1) failed"), + sock); + } else { + com_err(prog, 0, _("setsockopt(%d,IPV6_V6ONLY,1) worked"), sock); + } +#else + krb5_klog_syslog(LOG_INFO, _("no IPV6_V6ONLY socket option support")); +#endif /* IPV6_V6ONLY */ + } + + if (bind(sock, addr, sa_socklen(addr)) == -1) { + e = errno; + com_err(prog, e, _("Cannot bind server socket on %s"), paddr(addr)); + close(sock); + return e; + } + + *fd_out = sock; + return 0; +} + +static const int one = 1; + +static int +setnbio(int sock) +{ + return ioctlsocket(sock, FIONBIO, (const void *)&one); +} + +static int +setkeepalive(int sock) +{ + return setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one)); +} + +static int +setnolinger(int s) +{ + static const struct linger ling = { 0, 0 }; + return setsockopt(s, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)); +} + +/* An enum map to socket families for each bind_type. */ +static const int bind_socktypes[] = +{ + [UDP] = SOCK_DGRAM, + [TCP] = SOCK_STREAM, + [RPC] = SOCK_STREAM +}; + +/* An enum map containing conn_type (for struct connection) for each + * bind_type. */ +static const enum conn_type bind_conn_types[] = +{ + [UDP] = CONN_UDP, + [TCP] = CONN_TCP_LISTENER, + [RPC] = CONN_RPC_LISTENER +}; + +/* + * Set up a listening socket. + * + * Arguments: + * + * - ba + * The bind address and port for the socket. + * - ai + * The addrinfo struct to use for creating the socket. + * - ctype + * The conn_type of this socket. + */ +static krb5_error_code +setup_socket(struct bind_address *ba, struct sockaddr *sock_address, + void *handle, const char *prog, verto_ctx *ctx, + int tcp_listen_backlog, verto_callback vcb, enum conn_type ctype) +{ + krb5_error_code ret; + struct connection *conn; + verto_ev_flag flags; + verto_ev *ev = NULL; + int sock = -1; + + krb5_klog_syslog(LOG_DEBUG, _("Setting up %s socket for address %s"), + bind_type_names[ba->type], paddr(sock_address)); + + /* Create the socket. */ + ret = create_server_socket(sock_address, bind_socktypes[ba->type], prog, + &sock); + if (ret) + goto cleanup; + + /* Listen for backlogged connections on TCP sockets. (For RPC sockets this + * will be done by svc_register().) */ + if (ba->type == TCP && listen(sock, tcp_listen_backlog) != 0) { + ret = errno; + com_err(prog, errno, _("Cannot listen on %s server socket on %s"), + bind_type_names[ba->type], paddr(sock_address)); + goto cleanup; + } + + /* Set non-blocking I/O for UDP and TCP listener sockets. */ + if (ba->type != RPC && setnbio(sock) != 0) { + ret = errno; + com_err(prog, errno, + _("cannot set listening %s socket on %s non-blocking"), + bind_type_names[ba->type], paddr(sock_address)); + goto cleanup; + } + + /* Turn off the linger option for TCP sockets. */ + if (ba->type == TCP && setnolinger(sock) != 0) { + ret = errno; + com_err(prog, errno, _("cannot set SO_LINGER on %s socket on %s"), + bind_type_names[ba->type], paddr(sock_address)); + goto cleanup; + } + + /* Try to turn on pktinfo for UDP wildcard sockets. */ + if (ba->type == UDP && sa_is_wildcard(sock_address)) { + krb5_klog_syslog(LOG_DEBUG, _("Setting pktinfo on socket %s"), + paddr(sock_address)); + ret = set_pktinfo(sock, sock_address->sa_family); + if (ret) { + com_err(prog, ret, + _("Cannot request packet info for UDP socket address " + "%s port %d"), paddr(sock_address), ba->port); + krb5_klog_syslog(LOG_INFO, _("System does not support pktinfo yet " + "binding to a wildcard address. " + "Packets are not guaranteed to " + "return on the received address.")); + } + } + + /* Add the socket to the event loop. */ + flags = VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST | + VERTO_EV_FLAG_REINITIABLE; + ret = add_fd(sock, ctype, flags, handle, prog, ctx, vcb, &ev); + if (ret) { + krb5_klog_syslog(LOG_ERR, _("Error attempting to add verto event")); + goto cleanup; + } + + if (ba->type == RPC) { + conn = verto_get_private(ev); + conn->transp = svctcp_create(sock, 0, 0); + if (conn->transp == NULL) { + ret = errno; + krb5_klog_syslog(LOG_ERR, _("Cannot create RPC service: %s"), + strerror(ret)); + goto cleanup; + } + + ret = svc_register(conn->transp, ba->rpc_svc_data.prognum, + ba->rpc_svc_data.versnum, ba->rpc_svc_data.dispatch, + 0); + if (!ret) { + ret = errno; + krb5_klog_syslog(LOG_ERR, _("Cannot register RPC service: %s"), + strerror(ret)); + goto cleanup; + } + } + + ev = NULL; + sock = -1; + ret = 0; + +cleanup: + if (sock >= 0) + close(sock); + if (ev != NULL) + verto_del(ev); + return ret; +} + +/* + * Setup all the socket addresses that the net-server should listen to. + * + * This function uses getaddrinfo to figure out all the addresses. This will + * automatically figure out which socket families that should be used on the + * host making it useful even for wildcard addresses. + */ +static krb5_error_code +setup_addresses(verto_ctx *ctx, void *handle, const char *prog, + int tcp_listen_backlog) +{ + /* An bind_type enum map for the verto callback functions. */ + static verto_callback *const verto_callbacks[] = { + [UDP] = &process_packet, + [TCP] = &accept_tcp_connection, + [RPC] = &accept_rpc_connection + }; + krb5_error_code ret = 0; + size_t i; + int err, bound_any; + struct bind_address addr; + struct addrinfo hints, *ai_list = NULL, *ai = NULL; + verto_callback vcb; + + /* Check to make sure addresses were added to the server. */ + if (bind_addresses.n == 0) { + krb5_klog_syslog(LOG_ERR, _("No addresses added to the net server")); + return EINVAL; + } + + /* Ask for all address families, listener addresses, and no port name + * resolution. */ + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_PASSIVE; +#ifdef AI_NUMERICSERV + hints.ai_flags |= AI_NUMERICSERV; +#endif + + /* Add all the requested addresses. */ + for (i = 0; i < bind_addresses.n; i++) { + addr = bind_addresses.data[i]; + hints.ai_socktype = bind_socktypes[addr.type]; + + /* Call getaddrinfo, using a dummy port value. */ + err = getaddrinfo(addr.address, "0", &hints, &ai_list); + if (err) { + krb5_klog_syslog(LOG_ERR, + _("Failed getting address info (for %s): %s"), + (addr.address == NULL) ? "" : + addr.address, gai_strerror(err)); + ret = EIO; + goto cleanup; + } + + /* + * Loop through all the sockets that getaddrinfo could find to match + * the requested address. For wildcard listeners, this should usually + * have two results, one for each of IPv4 and IPv6, or one or the + * other, depending on the system. On IPv4-only systems, getaddrinfo() + * may return both IPv4 and IPv6 addresses, but creating an IPv6 socket + * may give an EAFNOSUPPORT error, so tolerate that error as long as we + * can bind at least one socket. + */ + bound_any = 0; + for (ai = ai_list; ai != NULL; ai = ai->ai_next) { + /* Make sure getaddrinfo returned a socket with the same type that + * was requested. */ + assert(hints.ai_socktype == ai->ai_socktype); + + /* Set the real port number. */ + sa_setport(ai->ai_addr, addr.port); + + ret = setup_socket(&addr, ai->ai_addr, handle, prog, ctx, + tcp_listen_backlog, verto_callbacks[addr.type], + bind_conn_types[addr.type]); + if (ret) { + krb5_klog_syslog(LOG_ERR, + _("Failed setting up a %s socket (for %s)"), + bind_type_names[addr.type], + paddr(ai->ai_addr)); + if (ret != EAFNOSUPPORT) + goto cleanup; + } else { + bound_any = 1; + } + } + if (!bound_any) + goto cleanup; + ret = 0; + + if (ai_list != NULL) + freeaddrinfo(ai_list); + ai_list = NULL; + } + +cleanup: + if (ai_list != NULL) + freeaddrinfo(ai_list); + return ret; +} + +krb5_error_code +loop_setup_network(verto_ctx *ctx, void *handle, const char *prog, + int tcp_listen_backlog) +{ + krb5_error_code ret; + verto_ev *ev; + int i; + + /* Check to make sure that at least one address was added to the loop. */ + if (bind_addresses.n == 0) + return EINVAL; + + /* Close any open connections. */ + FOREACH_ELT(events, i, ev) + verto_del(ev); + events.n = 0; + + krb5_klog_syslog(LOG_INFO, _("setting up network...")); + ret = setup_addresses(ctx, handle, prog, tcp_listen_backlog); + if (ret) { + com_err(prog, ret, _("Error setting up network")); + exit(1); + } + krb5_klog_syslog (LOG_INFO, _("set up %d sockets"), (int) events.n); + if (events.n == 0) { + /* If no sockets were set up, we can't continue. */ + com_err(prog, 0, _("no sockets set up?")); + exit (1); + } + + return 0; +} + +void +init_addr(krb5_fulladdr *faddr, struct sockaddr *sa) +{ + switch (sa->sa_family) { + case AF_INET: + faddr->address->addrtype = ADDRTYPE_INET; + faddr->address->length = 4; + faddr->address->contents = (krb5_octet *) &sa2sin(sa)->sin_addr; + faddr->port = ntohs(sa2sin(sa)->sin_port); + break; + case AF_INET6: + if (IN6_IS_ADDR_V4MAPPED(&sa2sin6(sa)->sin6_addr)) { + faddr->address->addrtype = ADDRTYPE_INET; + faddr->address->length = 4; + faddr->address->contents = 12 + (krb5_octet *) &sa2sin6(sa)->sin6_addr; + } else { + faddr->address->addrtype = ADDRTYPE_INET6; + faddr->address->length = 16; + faddr->address->contents = (krb5_octet *) &sa2sin6(sa)->sin6_addr; + } + faddr->port = ntohs(sa2sin6(sa)->sin6_port); + break; + default: + faddr->address->addrtype = -1; + faddr->address->length = 0; + faddr->address->contents = 0; + faddr->port = 0; + break; + } +} + +struct udp_dispatch_state { + void *handle; + const char *prog; + int port_fd; + krb5_address remote_addr_buf; + krb5_fulladdr remote_addr; + krb5_address local_addr_buf; + krb5_fulladdr local_addr; + socklen_t saddr_len; + socklen_t daddr_len; + struct sockaddr_storage saddr; + struct sockaddr_storage daddr; + aux_addressing_info auxaddr; + krb5_data request; + char pktbuf[MAX_DGRAM_SIZE]; +}; + +static void +process_packet_response(void *arg, krb5_error_code code, krb5_data *response) +{ + struct udp_dispatch_state *state = arg; + int cc; + + if (code) + com_err(state->prog ? state->prog : NULL, code, + _("while dispatching (udp)")); + if (code || response == NULL) + goto out; + + cc = send_to_from(state->port_fd, response->data, + (socklen_t) response->length, 0, + (struct sockaddr *)&state->saddr, state->saddr_len, + (struct sockaddr *)&state->daddr, state->daddr_len, + &state->auxaddr); + if (cc == -1) { + /* Note that the local address (daddr*) has no port number + * info associated with it. */ + char saddrbuf[NI_MAXHOST], sportbuf[NI_MAXSERV]; + char daddrbuf[NI_MAXHOST]; + int e = errno; + + if (getnameinfo((struct sockaddr *)&state->daddr, state->daddr_len, + daddrbuf, sizeof(daddrbuf), 0, 0, + NI_NUMERICHOST) != 0) { + strlcpy(daddrbuf, "?", sizeof(daddrbuf)); + } + + if (getnameinfo((struct sockaddr *)&state->saddr, state->saddr_len, + saddrbuf, sizeof(saddrbuf), sportbuf, sizeof(sportbuf), + NI_NUMERICHOST|NI_NUMERICSERV) != 0) { + strlcpy(saddrbuf, "?", sizeof(saddrbuf)); + strlcpy(sportbuf, "?", sizeof(sportbuf)); + } + + com_err(state->prog, e, _("while sending reply to %s/%s from %s"), + saddrbuf, sportbuf, daddrbuf); + goto out; + } + if ((size_t)cc != response->length) { + com_err(state->prog, 0, _("short reply write %d vs %d\n"), + response->length, cc); + } + +out: + krb5_free_data(get_context(state->handle), response); + free(state); +} + +static void +process_packet(verto_ctx *ctx, verto_ev *ev) +{ + int cc; + struct connection *conn; + struct udp_dispatch_state *state; + + conn = verto_get_private(ev); + + state = malloc(sizeof(*state)); + if (!state) { + com_err(conn->prog, ENOMEM, _("while dispatching (udp)")); + return; + } + + state->handle = conn->handle; + state->prog = conn->prog; + state->port_fd = verto_get_fd(ev); + assert(state->port_fd >= 0); + + state->saddr_len = sizeof(state->saddr); + state->daddr_len = sizeof(state->daddr); + memset(&state->auxaddr, 0, sizeof(state->auxaddr)); + cc = recv_from_to(state->port_fd, state->pktbuf, sizeof(state->pktbuf), 0, + (struct sockaddr *)&state->saddr, &state->saddr_len, + (struct sockaddr *)&state->daddr, &state->daddr_len, + &state->auxaddr); + if (cc == -1) { + if (errno != EINTR && errno != EAGAIN + /* + * This is how Linux indicates that a previous transmission was + * refused, e.g., if the client timed out before getting the + * response packet. + */ + && errno != ECONNREFUSED + ) + com_err(conn->prog, errno, _("while receiving from network")); + free(state); + return; + } + if (!cc) { /* zero-length packet? */ + free(state); + return; + } + + if (state->daddr_len == 0 && conn->type == CONN_UDP) { + /* + * An address couldn't be obtained, so the PKTINFO option probably + * isn't available. If the socket is bound to a specific address, then + * try to get the address here. + */ + state->daddr_len = sizeof(state->daddr); + if (getsockname(state->port_fd, (struct sockaddr *)&state->daddr, + &state->daddr_len) != 0) + state->daddr_len = 0; + /* On failure, keep going anyways. */ + } + + state->request.length = cc; + state->request.data = state->pktbuf; + + state->remote_addr.address = &state->remote_addr_buf; + init_addr(&state->remote_addr, ss2sa(&state->saddr)); + + state->local_addr.address = &state->local_addr_buf; + init_addr(&state->local_addr, ss2sa(&state->daddr)); + + /* This address is in net order. */ + dispatch(state->handle, &state->local_addr, &state->remote_addr, + &state->request, 0, ctx, process_packet_response, state); +} + +static int +kill_lru_tcp_or_rpc_connection(void *handle, verto_ev *newev) +{ + struct connection *c = NULL, *oldest_c = NULL; + verto_ev *ev, *oldest_ev = NULL; + int i, fd = -1; + + krb5_klog_syslog(LOG_INFO, _("too many connections")); + + FOREACH_ELT (events, i, ev) { + if (ev == newev) + continue; + + c = verto_get_private(ev); + if (!c) + continue; + if (c->type != CONN_TCP && c->type != CONN_RPC) + continue; + if (oldest_c == NULL + || oldest_c->start_time > c->start_time) { + oldest_ev = ev; + oldest_c = c; + } + } + if (oldest_c != NULL) { + krb5_klog_syslog(LOG_INFO, _("dropping %s fd %d from %s"), + c->type == CONN_RPC ? "rpc" : "tcp", + verto_get_fd(oldest_ev), oldest_c->addrbuf); + if (oldest_c->type == CONN_RPC) + oldest_c->rpc_force_close = 1; + verto_del(oldest_ev); + } + return fd; +} + +static void +accept_tcp_connection(verto_ctx *ctx, verto_ev *ev) +{ + int s; + struct sockaddr_storage addr_s; + struct sockaddr *addr = (struct sockaddr *)&addr_s; + socklen_t addrlen = sizeof(addr_s); + struct connection *newconn, *conn; + char tmpbuf[10]; + verto_ev_flag flags; + verto_ev *newev; + + conn = verto_get_private(ev); + s = accept(verto_get_fd(ev), addr, &addrlen); + if (s < 0) + return; + set_cloexec_fd(s); +#ifndef _WIN32 + if (s >= FD_SETSIZE) { + close(s); + return; + } +#endif + setnbio(s), setnolinger(s), setkeepalive(s); + + flags = VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST; + if (add_fd(s, CONN_TCP, flags, conn->handle, conn->prog, ctx, + process_tcp_connection_read, &newev) != 0) { + close(s); + return; + } + newconn = verto_get_private(newev); + + if (getnameinfo((struct sockaddr *)&addr_s, addrlen, + newconn->addrbuf, sizeof(newconn->addrbuf), + tmpbuf, sizeof(tmpbuf), + NI_NUMERICHOST | NI_NUMERICSERV)) + strlcpy(newconn->addrbuf, "???", sizeof(newconn->addrbuf)); + else { + char *p, *end; + p = newconn->addrbuf; + end = p + sizeof(newconn->addrbuf); + p += strlen(p); + if ((size_t)(end - p) > 2 + strlen(tmpbuf)) { + *p++ = '.'; + strlcpy(p, tmpbuf, end - p); + } + } + + newconn->addr_s = addr_s; + newconn->addrlen = addrlen; + newconn->bufsiz = 1024 * 1024; + newconn->buffer = malloc(newconn->bufsiz); + newconn->start_time = time(0); + + if (++tcp_or_rpc_data_counter > max_tcp_or_rpc_data_connections) + kill_lru_tcp_or_rpc_connection(conn->handle, newev); + + if (newconn->buffer == 0) { + com_err(conn->prog, errno, + _("allocating buffer for new TCP session from %s"), + newconn->addrbuf); + verto_del(newev); + return; + } + newconn->offset = 0; + newconn->remote_addr.address = &newconn->remote_addr_buf; + init_addr(&newconn->remote_addr, ss2sa(&newconn->addr_s)); + SG_SET(&newconn->sgbuf[0], newconn->lenbuf, 4); + SG_SET(&newconn->sgbuf[1], 0, 0); +} + +struct tcp_dispatch_state { + struct sockaddr_storage local_saddr; + krb5_address local_addr_buf; + krb5_fulladdr local_addr; + struct connection *conn; + krb5_data request; + verto_ctx *ctx; + int sock; +}; + +static void +process_tcp_response(void *arg, krb5_error_code code, krb5_data *response) +{ + struct tcp_dispatch_state *state = arg; + verto_ev *ev; + + assert(state); + state->conn->response = response; + + if (code) + com_err(state->conn->prog, code, _("while dispatching (tcp)")); + if (code || !response) + goto kill_tcp_connection; + + /* Queue outgoing response. */ + store_32_be(response->length, state->conn->lenbuf); + SG_SET(&state->conn->sgbuf[1], response->data, response->length); + state->conn->sgp = state->conn->sgbuf; + state->conn->sgnum = 2; + + ev = make_event(state->ctx, VERTO_EV_FLAG_IO_WRITE | VERTO_EV_FLAG_PERSIST, + process_tcp_connection_write, state->sock, state->conn); + if (ev) { + free(state); + return; + } + +kill_tcp_connection: + tcp_or_rpc_data_counter--; + free_connection(state->conn); + close(state->sock); + free(state); +} + +/* Creates the tcp_dispatch_state and deletes the verto event. */ +static struct tcp_dispatch_state * +prepare_for_dispatch(verto_ctx *ctx, verto_ev *ev) +{ + struct tcp_dispatch_state *state; + + state = malloc(sizeof(*state)); + if (!state) { + krb5_klog_syslog(LOG_ERR, _("error allocating tcp dispatch private!")); + return NULL; + } + state->conn = verto_get_private(ev); + state->sock = verto_get_fd(ev); + state->ctx = ctx; + verto_set_private(ev, NULL, NULL); /* Don't close the fd or free conn! */ + remove_event_from_set(ev); /* Remove it from the set. */ + verto_del(ev); + return state; +} + +static void +process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev) +{ + struct tcp_dispatch_state *state = NULL; + struct connection *conn = NULL; + ssize_t nread; + size_t len; + + conn = verto_get_private(ev); + + /* + * Read message length and data into one big buffer, already allocated + * at connect time. If we have a complete message, we stop reading, so + * we should only be here if there is no data in the buffer, or only an + * incomplete message. + */ + if (conn->offset < 4) { + krb5_data *response = NULL; + + /* msglen has not been computed. XXX Doing at least two reads + * here, letting the kernel worry about buffering. */ + len = 4 - conn->offset; + nread = SOCKET_READ(verto_get_fd(ev), + conn->buffer + conn->offset, len); + if (nread < 0) /* error */ + goto kill_tcp_connection; + if (nread == 0) /* eof */ + goto kill_tcp_connection; + conn->offset += nread; + if (conn->offset == 4) { + unsigned char *p = (unsigned char *)conn->buffer; + conn->msglen = load_32_be(p); + if (conn->msglen > conn->bufsiz - 4) { + krb5_error_code err; + /* Message too big. */ + krb5_klog_syslog(LOG_ERR, _("TCP client %s wants %lu bytes, " + "cap is %lu"), conn->addrbuf, + (unsigned long) conn->msglen, + (unsigned long) conn->bufsiz - 4); + /* XXX Should return an error. */ + err = make_toolong_error (conn->handle, + &response); + if (err) { + krb5_klog_syslog(LOG_ERR, _("error constructing " + "KRB_ERR_FIELD_TOOLONG error! %s"), + error_message(err)); + goto kill_tcp_connection; + } + + state = prepare_for_dispatch(ctx, ev); + if (!state) { + krb5_free_data(get_context(conn->handle), response); + goto kill_tcp_connection; + } + process_tcp_response(state, 0, response); + } + } + } else { + /* msglen known. */ + socklen_t local_saddrlen = sizeof(struct sockaddr_storage); + + len = conn->msglen - (conn->offset - 4); + nread = SOCKET_READ(verto_get_fd(ev), + conn->buffer + conn->offset, len); + if (nread < 0) /* error */ + goto kill_tcp_connection; + if (nread == 0) /* eof */ + goto kill_tcp_connection; + conn->offset += nread; + if (conn->offset < conn->msglen + 4) + return; + + /* Have a complete message, and exactly one message. */ + state = prepare_for_dispatch(ctx, ev); + if (!state) + goto kill_tcp_connection; + + state->request.length = conn->msglen; + state->request.data = conn->buffer + 4; + + if (getsockname(verto_get_fd(ev), ss2sa(&state->local_saddr), + &local_saddrlen) < 0) { + krb5_klog_syslog(LOG_ERR, _("getsockname failed: %s"), + error_message(errno)); + goto kill_tcp_connection; + } + state->local_addr.address = &state->local_addr_buf; + init_addr(&state->local_addr, ss2sa(&state->local_saddr)); + dispatch(state->conn->handle, &state->local_addr, &conn->remote_addr, + &state->request, 1, ctx, process_tcp_response, state); + } + + return; + +kill_tcp_connection: + verto_del(ev); +} + +static void +process_tcp_connection_write(verto_ctx *ctx, verto_ev *ev) +{ + struct connection *conn; + SOCKET_WRITEV_TEMP tmp; + ssize_t nwrote; + int sock; + + conn = verto_get_private(ev); + sock = verto_get_fd(ev); + + nwrote = SOCKET_WRITEV(sock, conn->sgp, + conn->sgnum, tmp); + if (nwrote > 0) { /* non-error and non-eof */ + while (nwrote) { + sg_buf *sgp = conn->sgp; + if ((size_t)nwrote < SG_LEN(sgp)) { + SG_ADVANCE(sgp, (size_t)nwrote); + nwrote = 0; + } else { + nwrote -= SG_LEN(sgp); + conn->sgp++; + conn->sgnum--; + if (conn->sgnum == 0 && nwrote != 0) + abort(); + } + } + + /* If we still have more data to send, just return so that + * the main loop can call this function again when the socket + * is ready for more writing. */ + if (conn->sgnum > 0) + return; + } + + /* Finished sending. We should go back to reading, though if we + * sent a FIELD_TOOLONG error in reply to a length with the high + * bit set, RFC 4120 says we have to close the TCP stream. */ + verto_del(ev); +} + +void +loop_free(verto_ctx *ctx) +{ + int i; + struct bind_address val; + + verto_free(ctx); + + /* Free each addresses added to the loop. */ + FOREACH_ELT(bind_addresses, i, val) + free(val.address); + FREE_SET_DATA(bind_addresses); + FREE_SET_DATA(events); +} + +static int +have_event_for_fd(int fd) +{ + verto_ev *ev; + int i; + + FOREACH_ELT(events, i, ev) { + if (verto_get_fd(ev) == fd) + return 1; + } + + return 0; +} + +static void +accept_rpc_connection(verto_ctx *ctx, verto_ev *ev) +{ + verto_ev_flag flags; + struct connection *conn; + fd_set fds; + int s; + + conn = verto_get_private(ev); + + /* Service the woken RPC listener descriptor. */ + FD_ZERO(&fds); + FD_SET(verto_get_fd(ev), &fds); + svc_getreqset(&fds); + + /* Scan svc_fdset for any new connections. */ + for (s = 0; s < FD_SETSIZE; s++) { + struct sockaddr_storage addr_s; + struct sockaddr *addr = (struct sockaddr *) &addr_s; + socklen_t addrlen = sizeof(addr_s); + struct connection *newconn; + char tmpbuf[10]; + verto_ev *newev; + + /* If we already have this fd, continue. */ + if (!FD_ISSET(s, &svc_fdset) || have_event_for_fd(s)) + continue; + + flags = VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST; + if (add_fd(s, CONN_RPC, flags, conn->handle, conn->prog, ctx, + process_rpc_connection, &newev) != 0) + continue; + newconn = verto_get_private(newev); + + set_cloexec_fd(s); + + if (getpeername(s, addr, &addrlen) || + getnameinfo(addr, addrlen, + newconn->addrbuf, + sizeof(newconn->addrbuf), + tmpbuf, sizeof(tmpbuf), + NI_NUMERICHOST | NI_NUMERICSERV)) { + strlcpy(newconn->addrbuf, "???", + sizeof(newconn->addrbuf)); + } else { + char *p, *end; + p = newconn->addrbuf; + end = p + sizeof(newconn->addrbuf); + p += strlen(p); + if ((size_t)(end - p) > 2 + strlen(tmpbuf)) { + *p++ = '.'; + strlcpy(p, tmpbuf, end - p); + } + } + + newconn->addr_s = addr_s; + newconn->addrlen = addrlen; + newconn->start_time = time(0); + + if (++tcp_or_rpc_data_counter > max_tcp_or_rpc_data_connections) + kill_lru_tcp_or_rpc_connection(newconn->handle, newev); + + newconn->remote_addr.address = &newconn->remote_addr_buf; + init_addr(&newconn->remote_addr, ss2sa(&newconn->addr_s)); + } +} + +static void +process_rpc_connection(verto_ctx *ctx, verto_ev *ev) +{ + fd_set fds; + + FD_ZERO(&fds); + FD_SET(verto_get_fd(ev), &fds); + svc_getreqset(&fds); + + if (!FD_ISSET(verto_get_fd(ev), &svc_fdset)) + verto_del(ev); +} + +#endif /* INET */ diff --git a/krb5-1.21.3/src/lib/apputils/udppktinfo.c b/krb5-1.21.3/src/lib/apputils/udppktinfo.c new file mode 100644 index 00000000..c6e86f69 --- /dev/null +++ b/krb5-1.21.3/src/lib/apputils/udppktinfo.c @@ -0,0 +1,526 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2016 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* macOS requires this define for IPV6_PKTINFO. */ +#define __APPLE_USE_RFC_3542 + +#include "udppktinfo.h" + +#include +#include + +#if defined(IP_PKTINFO) && defined(HAVE_STRUCT_IN_PKTINFO) +#define HAVE_IP_PKTINFO +#endif + +#if defined(IPV6_PKTINFO) && defined(HAVE_STRUCT_IN6_PKTINFO) +#define HAVE_IPV6_PKTINFO +#endif + +#if defined(HAVE_IP_PKTINFO) || defined(IP_SENDSRCADDR) || \ + defined(HAVE_IPV6_PKTINFO) +#define HAVE_PKTINFO_SUPPORT +#endif + +/* Use RFC 3542 API below, but fall back from IPV6_RECVPKTINFO to IPV6_PKTINFO + * for RFC 2292 implementations. */ +#if !defined(IPV6_RECVPKTINFO) && defined(IPV6_PKTINFO) +#define IPV6_RECVPKTINFO IPV6_PKTINFO +#endif + +/* Parallel, though not standardized. */ +#if !defined(IP_RECVPKTINFO) && defined(IP_PKTINFO) +#define IP_RECVPKTINFO IP_PKTINFO +#endif /* IP_RECVPKTINFO */ + +#if defined(CMSG_SPACE) && defined(HAVE_STRUCT_CMSGHDR) && \ + defined(HAVE_PKTINFO_SUPPORT) +union pktinfo { +#ifdef HAVE_STRUCT_IN6_PKTINFO + struct in6_pktinfo pi6; +#endif +#ifdef HAVE_STRUCT_IN_PKTINFO + struct in_pktinfo pi4; +#endif +#ifdef IP_RECVDSTADDR + struct in_addr iaddr; +#endif + char c; +}; +#endif /* HAVE_IPV6_PKTINFO && HAVE_STRUCT_CMSGHDR && HAVE_PKTINFO_SUPPORT */ + +#ifdef HAVE_IP_PKTINFO + +#define set_ipv4_pktinfo set_ipv4_recvpktinfo +static inline krb5_error_code +set_ipv4_recvpktinfo(int sock) +{ + int sockopt = 1; + return setsockopt(sock, IPPROTO_IP, IP_RECVPKTINFO, &sockopt, + sizeof(sockopt)); +} + +#elif defined(IP_RECVDSTADDR) /* HAVE_IP_PKTINFO */ + +#define set_ipv4_pktinfo set_ipv4_recvdstaddr +static inline krb5_error_code +set_ipv4_recvdstaddr(int sock) +{ + int sockopt = 1; + return setsockopt(sock, IPPROTO_IP, IP_RECVDSTADDR, &sockopt, + sizeof(sockopt)); +} + +#else /* HAVE_IP_PKTINFO || IP_RECVDSTADDR */ +#define set_ipv4_pktinfo(s) EINVAL +#endif /* HAVE_IP_PKTINFO || IP_RECVDSTADDR */ + +#ifdef HAVE_IPV6_PKTINFO + +#define set_ipv6_pktinfo set_ipv6_recvpktinfo +static inline krb5_error_code +set_ipv6_recvpktinfo(int sock) +{ + int sockopt = 1; + return setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &sockopt, + sizeof(sockopt)); +} + +#else /* HAVE_IPV6_PKTINFO */ +#define set_ipv6_pktinfo(s) EINVAL +#endif /* HAVE_IPV6_PKTINFO */ + +/* + * Set pktinfo option on a socket. Takes a socket and the socket address family + * as arguments. + * + * Returns 0 on success, EINVAL if pktinfo is not supported for the address + * family. + */ +krb5_error_code +set_pktinfo(int sock, int family) +{ + switch (family) { + case AF_INET: + return set_ipv4_pktinfo(sock); + case AF_INET6: + return set_ipv6_pktinfo(sock); + default: + return EINVAL; + } +} + +#if defined(HAVE_PKTINFO_SUPPORT) && defined(CMSG_SPACE) + +/* + * Check if a socket is bound to a wildcard address. + * Returns 1 if it is, 0 if it's bound to a specific address, or -1 on error + * with errno set to the error. + */ +static int +is_socket_bound_to_wildcard(int sock) +{ + struct sockaddr_storage bound_addr; + socklen_t bound_addr_len = sizeof(bound_addr); + struct sockaddr *sa = ss2sa(&bound_addr); + + if (getsockname(sock, sa, &bound_addr_len) < 0) + return -1; + + if (!sa_is_inet(sa)) { + errno = EINVAL; + return -1; + } + + return sa_is_wildcard(sa); +} + +#ifdef HAVE_IP_PKTINFO + +static inline struct in_pktinfo * +cmsg2pktinfo(struct cmsghdr *cmsgptr) +{ + return (struct in_pktinfo *)(void *)CMSG_DATA(cmsgptr); +} + +#define check_cmsg_v4_pktinfo check_cmsg_ip_pktinfo +static int +check_cmsg_ip_pktinfo(struct cmsghdr *cmsgptr, struct sockaddr *to, + socklen_t *tolen, aux_addressing_info *auxaddr) +{ + struct in_pktinfo *pktinfo; + + if (cmsgptr->cmsg_level == IPPROTO_IP && + cmsgptr->cmsg_type == IP_PKTINFO && + *tolen >= sizeof(struct sockaddr_in)) { + + memset(to, 0, sizeof(struct sockaddr_in)); + pktinfo = cmsg2pktinfo(cmsgptr); + sa2sin(to)->sin_addr = pktinfo->ipi_addr; + sa2sin(to)->sin_family = AF_INET; + *tolen = sizeof(struct sockaddr_in); + return 1; + } + return 0; +} + +#elif defined(IP_RECVDSTADDR) /* HAVE_IP_PKTINFO */ + +static inline struct in_addr * +cmsg2sin(struct cmsghdr *cmsgptr) +{ + return (struct in_addr *)(void *)CMSG_DATA(cmsgptr); +} + +#define check_cmsg_v4_pktinfo check_cmsg_ip_recvdstaddr +static int +check_cmsg_ip_recvdstaddr(struct cmsghdr *cmsgptr, struct sockaddr *to, + socklen_t *tolen, aux_addressing_info * auxaddr) +{ + if (cmsgptr->cmsg_level == IPPROTO_IP && + cmsgptr->cmsg_type == IP_RECVDSTADDR && + *tolen >= sizeof(struct sockaddr_in)) { + struct in_addr *sin_addr; + + memset(to, 0, sizeof(struct sockaddr_in)); + sin_addr = cmsg2sin(cmsgptr); + sa2sin(to)->sin_addr = *sin_addr; + sa2sin(to)->sin_family = AF_INET; + *tolen = sizeof(struct sockaddr_in); + return 1; + } + return 0; +} + +#else /* HAVE_IP_PKTINFO || IP_RECVDSTADDR */ +#define check_cmsg_v4_pktinfo(c, t, l, a) 0 +#endif /* HAVE_IP_PKTINFO || IP_RECVDSTADDR */ + +#ifdef HAVE_IPV6_PKTINFO + +static inline struct in6_pktinfo * +cmsg2pktinfo6(struct cmsghdr *cmsgptr) +{ + return (struct in6_pktinfo *)(void *)CMSG_DATA(cmsgptr); +} + +#define check_cmsg_v6_pktinfo check_cmsg_ipv6_pktinfo +static int +check_cmsg_ipv6_pktinfo(struct cmsghdr *cmsgptr, struct sockaddr *to, + socklen_t *tolen, aux_addressing_info *auxaddr) +{ + struct in6_pktinfo *pktinfo; + + if (cmsgptr->cmsg_level == IPPROTO_IPV6 && + cmsgptr->cmsg_type == IPV6_PKTINFO && + *tolen >= sizeof(struct sockaddr_in6)) { + + memset(to, 0, sizeof(struct sockaddr_in6)); + pktinfo = cmsg2pktinfo6(cmsgptr); + sa2sin6(to)->sin6_addr = pktinfo->ipi6_addr; + sa2sin6(to)->sin6_family = AF_INET6; + *tolen = sizeof(struct sockaddr_in6); + auxaddr->ipv6_ifindex = pktinfo->ipi6_ifindex; + return 1; + } + return 0; +} +#else /* HAVE_IPV6_PKTINFO */ +#define check_cmsg_v6_pktinfo(c, t, l, a) 0 +#endif /* HAVE_IPV6_PKTINFO */ + +static int +check_cmsg_pktinfo(struct cmsghdr *cmsgptr, struct sockaddr *to, + socklen_t *tolen, aux_addressing_info *auxaddr) +{ + return check_cmsg_v4_pktinfo(cmsgptr, to, tolen, auxaddr) || + check_cmsg_v6_pktinfo(cmsgptr, to, tolen, auxaddr); +} + +/* + * Receive a message from a socket. + * + * Arguments: + * sock + * buf - The buffer to store the message in. + * len - buf length + * flags + * from - Set to the address that sent the message + * fromlen + * to - Set to the address that the message was sent to if possible. + * May not be set in certain cases such as if pktinfo support is + * missing. May be NULL. + * tolen + * auxaddr - Miscellaneous address information. + * + * Returns 0 on success, otherwise an error code. + */ +krb5_error_code +recv_from_to(int sock, void *buf, size_t len, int flags, + struct sockaddr *from, socklen_t * fromlen, + struct sockaddr *to, socklen_t * tolen, + aux_addressing_info *auxaddr) + +{ + int r; + struct iovec iov; + char cmsg[CMSG_SPACE(sizeof(union pktinfo))]; + struct cmsghdr *cmsgptr; + struct msghdr msg; + + /* Don't use pktinfo if the socket isn't bound to a wildcard address. */ + r = is_socket_bound_to_wildcard(sock); + if (r < 0) + return errno; + + if (!to || !tolen || !r) + return recvfrom(sock, buf, len, flags, from, fromlen); + + /* Clobber with something recognizable in case we can't extract the address + * but try to use it anyways. */ + memset(to, 0x40, *tolen); + + iov.iov_base = buf; + iov.iov_len = len; + memset(&msg, 0, sizeof(msg)); + msg.msg_name = from; + msg.msg_namelen = *fromlen; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = cmsg; + msg.msg_controllen = sizeof(cmsg); + + r = recvmsg(sock, &msg, flags); + if (r < 0) + return r; + *fromlen = msg.msg_namelen; + + /* + * On Darwin (and presumably all *BSD with KAME stacks), CMSG_FIRSTHDR + * doesn't check for a non-zero controllen. RFC 3542 recommends making + * this check, even though the (new) spec for CMSG_FIRSTHDR says it's + * supposed to do the check. + */ + if (msg.msg_controllen) { + cmsgptr = CMSG_FIRSTHDR(&msg); + while (cmsgptr) { + if (check_cmsg_pktinfo(cmsgptr, to, tolen, auxaddr)) + return r; + cmsgptr = CMSG_NXTHDR(&msg, cmsgptr); + } + } + /* No info about destination addr was available. */ + *tolen = 0; + return r; +} + +#ifdef HAVE_IP_PKTINFO + +#define set_msg_from_ipv4 set_msg_from_ip_pktinfo +static krb5_error_code +set_msg_from_ip_pktinfo(struct msghdr *msg, struct cmsghdr *cmsgptr, + struct sockaddr *from, socklen_t fromlen, + aux_addressing_info *auxaddr) +{ + struct in_pktinfo *p = cmsg2pktinfo(cmsgptr); + const struct sockaddr_in *from4 = sa2sin(from); + + if (fromlen != sizeof(struct sockaddr_in)) + return EINVAL; + cmsgptr->cmsg_level = IPPROTO_IP; + cmsgptr->cmsg_type = IP_PKTINFO; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + p->ipi_spec_dst = from4->sin_addr; + + msg->msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); + return 0; +} + +#elif defined(IP_SENDSRCADDR) /* HAVE_IP_PKTINFO */ + +#define set_msg_from_ipv4 set_msg_from_ip_sendsrcaddr +static krb5_error_code +set_msg_from_ip_sendsrcaddr(struct msghdr *msg, struct cmsghdr *cmsgptr, + struct sockaddr *from, socklen_t fromlen, + aux_addressing_info *auxaddr) +{ + struct in_addr *sin_addr = cmsg2sin(cmsgptr); + const struct sockaddr_in *from4 = sa2sin(from); + if (fromlen != sizeof(struct sockaddr_in)) + return EINVAL; + cmsgptr->cmsg_level = IPPROTO_IP; + cmsgptr->cmsg_type = IP_SENDSRCADDR; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + msg->msg_controllen = CMSG_SPACE(sizeof(struct in_addr)); + *sin_addr = from4->sin_addr; + return 0; +} + +#else /* HAVE_IP_PKTINFO || IP_SENDSRCADDR */ +#define set_msg_from_ipv4(m, c, f, l, a) EINVAL +#endif /* HAVE_IP_PKTINFO || IP_SENDSRCADDR */ + +#ifdef HAVE_IPV6_PKTINFO + +#define set_msg_from_ipv6 set_msg_from_ipv6_pktinfo +static krb5_error_code +set_msg_from_ipv6_pktinfo(struct msghdr *msg, struct cmsghdr *cmsgptr, + struct sockaddr *from, socklen_t fromlen, + aux_addressing_info *auxaddr) +{ + struct in6_pktinfo *p = cmsg2pktinfo6(cmsgptr); + const struct sockaddr_in6 *from6 = sa2sin6(from); + + if (fromlen != sizeof(struct sockaddr_in6)) + return EINVAL; + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_PKTINFO; + cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + + p->ipi6_addr = from6->sin6_addr; + /* + * Because of the possibility of asymmetric routing, we + * normally don't want to specify an interface. However, + * macOS doesn't like sending from a link-local address + * (which can come up in testing at least, if you wind up + * with a "foo.local" name) unless we do specify the + * interface. + */ + if (IN6_IS_ADDR_LINKLOCAL(&from6->sin6_addr)) + p->ipi6_ifindex = auxaddr->ipv6_ifindex; + /* otherwise, already zero */ + + msg->msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); + return 0; +} + +#else /* HAVE_IPV6_PKTINFO */ +#define set_msg_from_ipv6(m, c, f, l, a) EINVAL +#endif /* HAVE_IPV6_PKTINFO */ + +static krb5_error_code +set_msg_from(int family, struct msghdr *msg, struct cmsghdr *cmsgptr, + struct sockaddr *from, socklen_t fromlen, + aux_addressing_info *auxaddr) +{ + switch (family) { + case AF_INET: + return set_msg_from_ipv4(msg, cmsgptr, from, fromlen, auxaddr); + case AF_INET6: + return set_msg_from_ipv6(msg, cmsgptr, from, fromlen, auxaddr); + } + + return EINVAL; +} + +/* + * Send a message to an address. + * + * Arguments: + * sock + * buf - The message to send. + * len - buf length + * flags + * to - The address to send the message to. + * tolen + * from - The address to attempt to send the message from. May be NULL. + * fromlen + * auxaddr - Miscellaneous address information. + * + * Returns 0 on success, otherwise an error code. + */ +krb5_error_code +send_to_from(int sock, void *buf, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen, struct sockaddr *from, + socklen_t fromlen, aux_addressing_info *auxaddr) +{ + int r; + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsgptr; + char cbuf[CMSG_SPACE(sizeof(union pktinfo))]; + + /* Don't use pktinfo if the socket isn't bound to a wildcard address. */ + r = is_socket_bound_to_wildcard(sock); + if (r < 0) + return errno; + + if (from == NULL || fromlen == 0 || from->sa_family != to->sa_family || !r) + goto use_sendto; + + iov.iov_base = buf; + iov.iov_len = len; + /* Truncation? */ + if (iov.iov_len != len) + return EINVAL; + memset(cbuf, 0, sizeof(cbuf)); + memset(&msg, 0, sizeof(msg)); + msg.msg_name = (void *)to; + msg.msg_namelen = tolen; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = cbuf; + /* CMSG_FIRSTHDR needs a non-zero controllen, or it'll return NULL on + * Linux. */ + msg.msg_controllen = sizeof(cbuf); + cmsgptr = CMSG_FIRSTHDR(&msg); + msg.msg_controllen = 0; + + if (set_msg_from(from->sa_family, &msg, cmsgptr, from, fromlen, auxaddr)) + goto use_sendto; + return sendmsg(sock, &msg, flags); + +use_sendto: + return sendto(sock, buf, len, flags, to, tolen); +} + +#else /* HAVE_PKTINFO_SUPPORT && CMSG_SPACE */ + +krb5_error_code +recv_from_to(int sock, void *buf, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen, + struct sockaddr *to, socklen_t *tolen, + aux_addressing_info *auxaddr) +{ + if (to && tolen) { + /* Clobber with something recognizable in case we try to use the + * address. */ + memset(to, 0x40, *tolen); + *tolen = 0; + } + + return recvfrom(sock, buf, len, flags, from, fromlen); +} + +krb5_error_code +send_to_from(int sock, void *buf, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen, + struct sockaddr *from, socklen_t fromlen, + aux_addressing_info *auxaddr) +{ + return sendto(sock, buf, len, flags, to, tolen); +} + +#endif /* HAVE_PKTINFO_SUPPORT && CMSG_SPACE */ diff --git a/krb5-1.21.3/src/lib/apputils/udppktinfo.h b/krb5-1.21.3/src/lib/apputils/udppktinfo.h new file mode 100644 index 00000000..ff5759ab --- /dev/null +++ b/krb5-1.21.3/src/lib/apputils/udppktinfo.h @@ -0,0 +1,58 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2016 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef UDPPKTINFO_H +#define UDPPKTINFO_H + +#include "k5-int.h" + +/* + * This holds whatever additional information might be needed to + * properly send back to the client from the correct local address. + * + * In this case, we only need one datum so far: On macOS, the + * kernel doesn't seem to like sending from link-local addresses + * unless we specify the correct interface. + */ +typedef union aux_addressing_info +{ + int ipv6_ifindex; +} aux_addressing_info; + +krb5_error_code +set_pktinfo(int sock, int family); + +krb5_error_code +recv_from_to(int sock, void *buf, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen, + struct sockaddr *to, socklen_t *tolen, + aux_addressing_info *auxaddr); + +krb5_error_code +send_to_from(int sock, void *buf, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen, struct sockaddr *from, + socklen_t fromlen, aux_addressing_info *auxaddr); + +#endif /* UDPPKTINFO_H */ diff --git a/krb5-1.21.3/src/lib/comerr32.def b/krb5-1.21.3/src/lib/comerr32.def new file mode 100644 index 00000000..55c024d1 --- /dev/null +++ b/krb5-1.21.3/src/lib/comerr32.def @@ -0,0 +1,12 @@ +;LIBRARY COMERR32 +DESCRIPTION 'DLL for ComErr' +HEAPSIZE 8192 + +EXPORTS + com_err @2 + com_err_va @3 + error_message @4 + add_error_table @1 + remove_error_table @5 + set_com_err_hook @6 + reset_com_err_hook @7 diff --git a/krb5-1.21.3/src/lib/crypto/ISSUES b/krb5-1.21.3/src/lib/crypto/ISSUES new file mode 100644 index 00000000..b821a00c --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/ISSUES @@ -0,0 +1,14 @@ +Issues to be addressed for src/lib/crypto: -*- text -*- + + +Many files here and in subdirectories pollute the namespace. +However, some applications wanting to directly use some of those +routines will expect those names to be available. + +Workaround: Shared library export lists? Define and export internal +names, and provide wrapper library code or weak functions under the +polluting names? + + +Some routines assume "int" is big enough to describe all buffers that +may be supplied. diff --git a/krb5-1.21.3/src/lib/crypto/Makefile.in b/krb5-1.21.3/src/lib/crypto/Makefile.in new file mode 100644 index 00000000..10e8c74c --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/Makefile.in @@ -0,0 +1,48 @@ +mydir=lib$(S)crypto +BUILDTOP=$(REL)..$(S).. +SUBDIRS= krb builtin openssl crypto_tests +WINSUBDIRS= krb builtin crypto_tests +LOCALINCLUDES=$(CRYPTO_IMPL_CFLAGS) + +LIBBASE=k5crypto +LIBMAJOR=3 +LIBMINOR=1 +RELDIR=crypto + +STOBJLISTS=krb/OBJS.ST \ + builtin/OBJS.ST builtin/des/OBJS.ST \ + builtin/aes/OBJS.ST builtin/camellia/OBJS.ST \ + builtin/md4/OBJS.ST builtin/md5/OBJS.ST \ + builtin/sha1/OBJS.ST builtin/sha2/OBJS.ST \ + builtin/enc_provider/OBJS.ST builtin/hash_provider/OBJS.ST \ + openssl/OBJS.ST openssl/des/OBJS.ST \ + openssl/enc_provider/OBJS.ST openssl/hash_provider/OBJS.ST + +SUBDIROBJLISTS=$(STOBJLISTS) + +# No dependencies. Record places to find this shared object if the target +# link editor and loader support it. +DEPLIBS= +SHLIB_EXPLIBS= $(SUPPORT_LIB) $(CRYPTO_IMPL_LIBS) $(LIBS) +SHLIB_EXPDEPLIBS= $(SUPPORT_DEPLIB) +SHLIB_LDFLAGS= $(LDFLAGS) @SHLIB_RPATH_DIRS@ + +##DOS##LIBNAME=$(OUTPRE)crypto.lib +##DOS##OBJFILEDEP=$(OUTPRE)krb.lst $(OUTPRE)aes.lst $(OUTPRE)enc_provider.lst $(OUTPRE)des.lst $(OUTPRE)md5.lst $(OUTPRE)camellia.lst $(OUTPRE)md4.lst $(OUTPRE)hash_provider.lst $(OUTPRE)sha2.lst $(OUTPRE)sha1.lst $(OUTPRE)builtin.lst +##DOS##OBJFILELIST=@$(OUTPRE)krb.lst @$(OUTPRE)aes.lst @$(OUTPRE)enc_provider.lst @$(OUTPRE)des.lst @$(OUTPRE)md5.lst @$(OUTPRE)camellia.lst @$(OUTPRE)md4.lst @$(OUTPRE)hash_provider.lst @$(OUTPRE)sha2.lst @$(OUTPRE)sha1.lst @$(OUTPRE)builtin.lst + +all-unix: all-liblinks +install-unix: install-libs + + +# all-unix: +# install-unix: + +libcrypto.lib: + libdir crypto.lib + +clean-unix:: clean-liblinks clean-libs clean-libobjs + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/builtin/Makefile.in b/krb5-1.21.3/src/lib/crypto/builtin/Makefile.in new file mode 100644 index 00000000..243bb17b --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/Makefile.in @@ -0,0 +1,48 @@ +mydir=lib$(S)crypto$(S)builtin +BUILDTOP=$(REL)..$(S)..$(S).. +SUBDIRS=camellia des aes md4 md5 sha1 sha2 enc_provider hash_provider +LOCALINCLUDES=-I$(srcdir)/../krb $(CRYPTO_IMPL_CFLAGS) + +##DOS##BUILDTOP = ..\..\.. +##DOS##PREFIXDIR = builtin +##DOS##OBJFILE = ..\$(OUTPRE)builtin.lst + +STLIBOBJS=\ + cmac.o \ + hmac.o \ + kdf.o \ + pbkdf2.o + +OBJS=\ + $(OUTPRE)cmac.$(OBJEXT) \ + $(OUTPRE)hmac.$(OBJEXT) \ + $(OUTPRE)kdf.$(OBJEXT) \ + $(OUTPRE)pbkdf2.$(OBJEXT) + +SRCS=\ + $(srcdir)/cmac.c \ + $(srcdir)/hmac.c \ + $(srcdir)/kdf.c \ + $(srcdir)/pbkdf2.c + +SUBDIROBJLISTS= des/OBJS.ST md4/OBJS.ST \ + md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST \ + enc_provider/OBJS.ST \ + hash_provider/OBJS.ST \ + aes/OBJS.ST \ + camellia/OBJS.ST + +STOBJLISTS= $(SUBDIROBJLISTS) OBJS.ST + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs +includes: depend + +depend: $(SRCS) + +clean-unix:: clean-libobjs + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/Makefile.in b/krb5-1.21.3/src/lib/crypto/builtin/aes/Makefile.in new file mode 100644 index 00000000..971f05c8 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/Makefile.in @@ -0,0 +1,66 @@ +mydir=lib$(S)crypto$(S)builtin$(S)aes +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/../../krb $(CRYPTO_IMPL_CFLGAS) + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\aes +##DOS##OBJFILE = ..\..\$(OUTPRE)aes.lst + +YASM=@YASM@ +AESNI_OBJ=@AESNI_OBJ@ +AESNI_FLAGS=@AESNI_FLAGS@ + +STLIBOBJS=\ + aescrypt.o \ + aestab.o \ + aeskey.o \ + @AESNI_OBJ@ + +OBJS=\ + $(OUTPRE)aescrypt.$(OBJEXT) \ + $(OUTPRE)aestab.$(OBJEXT) \ + $(OUTPRE)aeskey.$(OBJEXT) + +SRCS=\ + $(srcdir)/aescrypt.c \ + $(srcdir)/aestab.c \ + $(srcdir)/aeskey.c \ + +GEN_OBJS=\ + $(OUTPRE)aescrypt.$(OBJEXT) \ + $(OUTPRE)aestab.$(OBJEXT) \ + $(OUTPRE)aeskey.$(OBJEXT) + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs # aes-gen + +iaesx64@SHOBJEXT@ iaesx64@STOBJEXT@: $(srcdir)/iaesx64.s + $(YASM) $(AESNI_FLAGS) -o $@ $(srcdir)/iaesx64.s + +iaesx86@SHOBJEXT@ iaesx86@STOBJEXT@: $(srcdir)/iaesx86.s + $(YASM) $(AESNI_FLAGS) -o $@ $(srcdir)/iaesx86.s + +includes: depend + +depend: $(SRCS) + +aes-gen: aes-gen.o $(GEN_OBJS) + $(CC_LINK) -o aes-gen aes-gen.o $(GEN_OBJS) + +run-aes-gen: aes-gen + ./aes-gen > kresults.out + cmp kresults.out $(srcdir)/kresults.expected + +check-unix: check-@CRYPTO_BUILTIN_TESTS@ +check-no: +check-yes: run-aes-gen + + +clean-unix:: clean-libobjs + +clean: + -$(RM) aes-gen aes-gen.o kresults.out + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/aes-gen.c b/krb5-1.21.3/src/lib/crypto/builtin/aes/aes-gen.c new file mode 100644 index 00000000..b528d379 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/aes-gen.c @@ -0,0 +1,352 @@ +/* + * To be compiled against the AES code from: + * https://github.com/BrianGladman/AES + */ +#include +#include +#include +#include +#include "aes.h" + +#define B 16U +uint8_t key[16] = { 0x46, 0x64, 0x31, 0x29, 0x64, 0x86, 0xED, 0x9C, + 0xD7, 0x1F, 0xC2, 0x07, 0x25, 0x48, 0x20, 0xA2 }; +size_t test_case_len[] = { B+1, 2*B-1, 2*B, 2*B+1, 3*B-1, 3*B, 4*B, }; +#define NTESTS (sizeof(test_case_len) / sizeof(*test_case_len)) +uint8_t test_case[NTESTS][4 * B] = { + { 0xC4, 0xA8, 0x5A, 0xEB, 0x0B, 0x20, 0x41, 0x49, + 0x4F, 0x8B, 0xF1, 0xF8, 0xCD, 0x30, 0xF1, 0x13, + 0x94 }, + { 0x22, 0x3C, 0xF8, 0xA8, 0x29, 0x95, 0x80, 0x49, + 0x57, 0x87, 0x6E, 0x9F, 0xA7, 0x11, 0x63, 0x50, + 0x6B, 0x4E, 0x5B, 0x8C, 0x8F, 0xA4, 0xDB, 0x1B, + 0x95, 0xD3, 0xE8, 0xC5, 0xC5, 0xFB, 0x5A }, + { 0xE7, 0x37, 0x52, 0x90, 0x60, 0xE7, 0x10, 0xA9, + 0x3E, 0x97, 0x18, 0xDD, 0x3E, 0x29, 0x41, 0x8E, + 0x94, 0x8F, 0xE9, 0x20, 0x1F, 0x8D, 0xFB, 0x3A, + 0x22, 0xCF, 0x22, 0xE8, 0x94, 0x1D, 0x42, 0x7B }, + { 0x54, 0x94, 0x0B, 0xB4, 0x7C, 0x1B, 0x5E, 0xBA, + 0xB2, 0x76, 0x98, 0xF1, 0x9F, 0xD9, 0x7F, 0x33, + 0x68, 0x69, 0x54, 0x87, 0xF6, 0x4F, 0xC1, 0x19, + 0x1E, 0xE3, 0x01, 0xB2, 0x00, 0x43, 0x2E, 0x54, + 0xD7 }, + { 0x39, 0x09, 0x53, 0x55, 0x67, 0x0E, 0x07, 0xDD, + 0xA6, 0xF8, 0x7C, 0x7F, 0x78, 0xAF, 0xE7, 0xE1, + 0x03, 0x6F, 0xD7, 0x53, 0x30, 0xF0, 0x71, 0x14, + 0xF1, 0x24, 0x14, 0x34, 0x52, 0x69, 0x0C, 0x8B, + 0x72, 0x5F, 0xE0, 0xD9, 0x6D, 0xE8, 0xB6, 0x13, + 0xE0, 0x32, 0x92, 0x58, 0xE1, 0x7A, 0x39 }, + { 0xE5, 0xE9, 0x11, 0x38, 0x19, 0x01, 0xA9, 0x2D, + 0xF3, 0xCD, 0x42, 0x27, 0x1F, 0xAB, 0x33, 0xAB, + 0x1D, 0x93, 0x8B, 0xF6, 0x00, 0x73, 0xAC, 0x14, + 0x54, 0xDE, 0xA6, 0xAC, 0xBF, 0x20, 0xE6, 0xA4, + 0x09, 0xF7, 0xDC, 0x23, 0xF8, 0x86, 0x50, 0xEB, + 0x53, 0x92, 0x13, 0x73, 0x3D, 0x46, 0x1E, 0x5A }, + { 0xD9, 0xA9, 0x50, 0xDA, 0x1D, 0xFC, 0xEE, 0x71, + 0xDA, 0x94, 0x1D, 0x9A, 0xB5, 0x03, 0x3E, 0xBE, + 0xFA, 0x1B, 0xE1, 0xF3, 0xA1, 0x32, 0xDE, 0xF4, + 0xC4, 0xF1, 0x67, 0x02, 0x38, 0x85, 0x5C, 0x11, + 0x2F, 0xAD, 0xEB, 0x4C, 0xA9, 0xD9, 0xBD, 0x84, + 0x6E, 0xDA, 0x1E, 0x23, 0xDE, 0x5C, 0xE1, 0xD8, + 0x77, 0xC3, 0xCB, 0x18, 0xF5, 0xAA, 0x0D, 0xB9, + 0x9B, 0x74, 0xBB, 0xD3, 0xFA, 0x18, 0xE5, 0x29 } +}; +aes_encrypt_ctx ctx; +aes_decrypt_ctx dctx; + +static void init () +{ + AES_RETURN r; + + r = aes_encrypt_key128(key, &ctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + r = aes_decrypt_key128(key, &dctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); +} + +static void hexdump(const unsigned char *ptr, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) + printf ("%s%02X", (i % 16 == 0) ? "\n " : " ", ptr[i]); +} + +static void fips_test () +{ + static const unsigned char fipskey[16] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + }; + static const unsigned char input[16] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }; + static const unsigned char expected[16] = { + 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30, + 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a, + }; + unsigned char output[16]; + unsigned char tmp[16]; + aes_crypt_ctx fipsctx; + int r; + + printf ("FIPS test:\nkey:"); + hexdump (fipskey, 16); + printf ("\ninput:"); + hexdump (input, 16); + r = aes_encrypt_key128(fipskey, &fipsctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + r = aes_encrypt(input, output, &fipsctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + printf ("\noutput:"); + hexdump (output, 16); + printf ("\n"); + if (memcmp(expected, output, 16)) + fprintf(stderr, "wrong results!!!\n"), exit (1); + r = aes_decrypt_key128(fipskey, &fipsctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + r = aes_decrypt(output, tmp, &fipsctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + if (memcmp(input, tmp, 16)) + fprintf(stderr, "decryption failed!!\n"), exit(1); + printf ("ok.\n\n"); +} + +static void +xor (unsigned char *out, const unsigned char *a, const unsigned char *b) +{ + unsigned int i; + for (i = 0; i < B; i++) + out[i] = a[i] ^ b[i]; +} + +static void +ecb_enc (unsigned char *out, unsigned char *in, unsigned int len) +{ + unsigned int i, r; + for (i = 0; i < len; i += 16) { + r = aes_encrypt(in + i, out + i, &ctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + } + if (i != len) abort (); +} + +static void +ecb_dec (unsigned char *out, unsigned char *in, unsigned int len) +{ + unsigned int i, r; + for (i = 0; i < len; i += 16) { + r = aes_decrypt(in + i, out + i, &dctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + } + if (i != len) abort (); +} + +#define D(X) (printf("%s %d: %s=",__FUNCTION__,__LINE__, #X),hexdump(X,B),printf("\n")) + +#undef D +#define D(X) + +static void +cbc_enc (unsigned char *out, unsigned char *in, unsigned char *iv, + unsigned int len) +{ + unsigned int i, r; + unsigned char tmp[B]; + D(iv); + memcpy (tmp, iv, B); + for (i = 0; i < len; i += B) { + D(in+i); + xor (tmp, tmp, in + i); + D(tmp); + r = aes_encrypt(tmp, out + i, &ctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + memcpy (tmp, out + i, B); + D(out+i); + } + if (i != len) abort (); +} + +static void +cbc_dec (unsigned char *out, unsigned char *in, unsigned char *iv, + unsigned int len) +{ + unsigned int i, r; + unsigned char tmp[B]; + memcpy (tmp, iv, B); + for (i = 0; i < len; i += B) { + r = aes_decrypt(in + i, tmp, &dctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + xor (tmp, tmp, iv); + iv = in + i; + memcpy (out + i, tmp, B); + } + if (i != len) abort (); +} + +static void +cts_enc (unsigned char *out, unsigned char *in, unsigned char *iv, + unsigned int len) +{ + int r; + unsigned int len2; + unsigned char pn1[B], pn[B], cn[B], cn1[B]; + + if (len < B + 1) abort (); + len2 = (len - B - 1) & ~(B-1); + cbc_enc (out, in, iv, len2); + out += len2; + in += len2; + len -= len2; + if (len2) + iv = out - B; + if (len <= B || len > 2 * B) + abort (); + printf ("(did CBC mode for %d)\n", len2); + + D(in); + xor (pn1, in, iv); + D(pn1); + r = aes_encrypt(pn1, cn, &ctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + D(cn); + memset (pn, 0, sizeof(pn)); + memcpy (pn, in+B, len-B); + D(pn); + xor (pn, pn, cn); + D(pn); + r = aes_encrypt(pn, cn1, &ctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + D(cn1); + memcpy(out, cn1, B); + memcpy(out+B, cn, len-B); +} + +static void +cts_dec (unsigned char *out, unsigned char *in, unsigned char *iv, + unsigned int len) +{ + int r; + unsigned int len2; + unsigned char pn1[B], pn[B], cn[B], cn1[B]; + + if (len < B + 1) abort (); + len2 = (len - B - 1) & ~(B-1); + cbc_dec (out, in, iv, len2); + out += len2; + in += len2; + len -= len2; + if (len2) + iv = in - B; + if (len <= B || len > 2 * B) + abort (); + + memcpy (cn1, in, B); + r = aes_decrypt(cn1, pn, &dctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + memset (cn, 0, sizeof(cn)); + memcpy (cn, in+B, len-B); + xor (pn, pn, cn); + memcpy (cn+len-B, pn+len-B, 2*B-len); + r = aes_decrypt(cn, pn1, &dctx); + if (r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + xor (pn1, pn1, iv); + memcpy(out, pn1, B); + memcpy(out+B, pn, len-B); +} + +static void ecb_test () +{ + unsigned int testno; + uint8_t output[4 * B], tmp[4 * B]; + + printf ("ECB tests:\n"); + printf ("key:"); + hexdump (key, sizeof(key)); + for (testno = 0; testno < NTESTS; testno++) { + unsigned len = (test_case_len[testno] + 15) & ~15; + printf ("\ntest %d - %d bytes\n", testno, len); + printf ("input:"); + hexdump (test_case[testno], len); + printf ("\n"); + ecb_enc (output, test_case[testno], len); + printf ("output:"); + hexdump (output, len); + printf ("\n"); + ecb_dec (tmp, output, len); + if (memcmp (tmp, test_case[testno], len)) { + printf ("ecb decrypt failed!!"); + hexdump (tmp, len); + printf ("\n"); + exit (1); + } + } + printf ("\n"); +} + +unsigned char ivec[16] = { 0 }; + +static void cbc_test () +{ + unsigned int testno; + uint8_t output[4 * B], tmp[4 * B]; + + printf ("CBC tests:\n"); + printf ("initial vector:"); + hexdump (ivec, sizeof(ivec)); + for (testno = 0; testno < NTESTS; testno++) { + unsigned len = (test_case_len[testno] + 15) & ~15; + printf ("\ntest %d - %d bytes\n", testno, len); + printf ("input:"); + hexdump (test_case[testno], len); + printf ("\n"); + cbc_enc (output, test_case[testno], ivec, len); + printf ("output:"); + hexdump (output, len); + printf ("\n"); + cbc_dec (tmp, output, ivec, len); + if (memcmp (tmp, test_case[testno], len)) { + printf("cbc decrypt failed!!"); + hexdump (tmp, len); + printf ("\n"); + exit(1); + } + } + printf ("\n"); +} + +static void cts_test () +{ + unsigned int testno; + uint8_t output[4 * B], tmp[4 * B]; + + printf ("CTS tests:\n"); + printf ("initial vector:"); + hexdump (ivec, sizeof(ivec)); + for (testno = 0; testno < NTESTS; testno++) { + unsigned int len = test_case_len[testno]; + printf ("\ntest %d - %d bytes\n", testno, len); + printf ("input:"); + hexdump (test_case[testno], len); + printf ("\n"); + cts_enc (output, test_case[testno], ivec, len); + printf ("output:"); + hexdump (output, len); + printf ("\n"); + cts_dec (tmp, output, ivec, len); + if (memcmp (tmp, test_case[testno], len)) + fprintf (stderr, "cts decrypt failed!!\n"), exit(1); + } + printf ("\n"); +} + +int main () +{ + init (); + fips_test (); + + ecb_test(); + cbc_test(); + cts_test(); + + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/aes.h b/krb5-1.21.3/src/lib/crypto/builtin/aes/aes.h new file mode 100644 index 00000000..9b5215eb --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/aes.h @@ -0,0 +1,289 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 02/09/2018 + + This file contains the definitions required to use AES in C. See aesopt.h + for optimisation details. +*/ + +#ifndef _AES_H +#define _AES_H + +/* For MIT krb5, give the linker-visible symbols a prefix. */ +#define aes_decrypt k5_aes_decrypt +#define aes_decrypt_key k5_aes_decrypt_key +#define aes_decrypt_key128 k5_aes_decrypt_key128 +#define aes_decrypt_key256 k5_aes_decrypt_key256 +#define aes_encrypt k5_aes_encrypt +#define aes_encrypt_key k5_aes_encrypt_key +#define aes_encrypt_key128 k5_aes_encrypt_key128 +#define aes_encrypt_key256 k5_aes_encrypt_key256 +#define aes_init k5_aes_init + +#include + +/* This include is used to find 8 & 32 bit unsigned integer types */ +#include "brg_types.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define AES_128 /* if a fast 128 bit key scheduler is needed */ +#undef AES_192 /* if a fast 192 bit key scheduler is needed */ +#define AES_256 /* if a fast 256 bit key scheduler is needed */ +#define AES_VAR /* if variable key size scheduler is needed */ +#if 1 +# define AES_MODES /* if support is needed for modes in the C code */ +#endif /* (these will use AES_NI if it is present) */ +#if 0 /* add this to make direct calls to the AES_NI */ +# /* implemented CBC and CTR modes available */ +# define ADD_AESNI_MODE_CALLS +#endif + +/* The following must also be set in assembler files if being used */ + +#define AES_ENCRYPT /* if support for encryption is needed */ +#define AES_DECRYPT /* if support for decryption is needed */ + +#define AES_BLOCK_SIZE_P2 4 /* AES block size as a power of 2 */ +#define AES_BLOCK_SIZE (1 << AES_BLOCK_SIZE_P2) /* AES block size */ +#define N_COLS 4 /* the number of columns in the state */ + +/* The key schedule length is 11, 13 or 15 16-byte blocks for 128, */ +/* 192 or 256-bit keys respectively. That is 176, 208 or 240 bytes */ +/* or 44, 52 or 60 32-bit words. */ + +#if defined( AES_VAR ) || defined( AES_256 ) +#define KS_LENGTH 60 +#elif defined( AES_192 ) +#define KS_LENGTH 52 +#else +#define KS_LENGTH 44 +#endif + +#define AES_RETURN INT_RETURN + +/* the character array 'inf' in the following structures is used */ +/* to hold AES context information. This AES code uses cx->inf.b[0] */ +/* to hold the number of rounds multiplied by 16. The other three */ +/* elements can be used by code that implements additional modes */ + +typedef union +{ uint32_t l; + uint8_t b[4]; +} aes_inf; + +/* Macros for detecting whether a given context was initialized for */ +/* use with encryption or decryption code. These should only be used */ +/* by e.g. language bindings which lose type information when the */ +/* context pointer is passed to the calling language's runtime. */ +#define IS_ENCRYPTION_CTX(cx) (((cx)->inf.b[2] & (uint8_t)0x01) == 1) +#define IS_DECRYPTION_CTX(cx) (((cx)->inf.b[2] & (uint8_t)0x01) == 0) + +#ifdef _MSC_VER +# pragma warning( disable : 4324 ) +#endif + +#if defined(_MSC_VER) && defined(_WIN64) +#define ALIGNED_(x) __declspec(align(x)) +#elif defined(__GNUC__) && defined(__x86_64__) +#define ALIGNED_(x) __attribute__ ((aligned(x))) +#else +#define ALIGNED_(x) +#endif + +typedef struct ALIGNED_(16) +{ uint32_t ks[KS_LENGTH]; + aes_inf inf; +} aes_crypt_ctx; + +typedef aes_crypt_ctx aes_encrypt_ctx; +typedef aes_crypt_ctx aes_decrypt_ctx; + +#ifdef _MSC_VER +# pragma warning( default : 4324 ) +#endif + +/* This routine must be called before first use if non-static */ +/* tables are being used */ + +AES_RETURN aes_init(void); + +/* Key lengths in the range 16 <= key_len <= 32 are given in bytes, */ +/* those in the range 128 <= key_len <= 256 are given in bits */ + +#if defined( AES_ENCRYPT ) + +#if defined( AES_128 ) || defined( AES_VAR) +AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined( AES_192 ) || defined( AES_VAR) +AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined( AES_256 ) || defined( AES_VAR) +AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); +#endif + +#if defined( AES_VAR ) +AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]); +#endif + +AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]); + +#endif + +#if defined( AES_DECRYPT ) + +#if defined( AES_128 ) || defined( AES_VAR) +AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined( AES_192 ) || defined( AES_VAR) +AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined( AES_256 ) || defined( AES_VAR) +AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); +#endif + +#if defined( AES_VAR ) +AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]); +#endif + +AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]); + +#endif + +#if defined( AES_MODES ) + +/* Multiple calls to the following subroutines for multiple block */ +/* ECB, CBC, CFB, OFB and CTR mode encryption can be used to handle */ +/* long messages incrementally provided that the context AND the iv */ +/* are preserved between all such calls. For the ECB and CBC modes */ +/* each individual call within a series of incremental calls must */ +/* process only full blocks (i.e. len must be a multiple of 16) but */ +/* the CFB, OFB and CTR mode calls can handle multiple incremental */ +/* calls of any length. Each mode is reset when a new AES key is */ +/* set but ECB needs no reset and CBC can be reset without setting */ +/* a new key by setting a new IV value. To reset CFB, OFB and CTR */ +/* without setting the key, aes_mode_reset() must be called and the */ +/* IV must be set. NOTE: All these calls update the IV on exit so */ +/* this has to be reset if a new operation with the same IV as the */ +/* previous one is required (or decryption follows encryption with */ +/* the same IV array). */ + +AES_RETURN aes_test_alignment_detection(unsigned int n); + +AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, const aes_encrypt_ctx cx[1]); + +AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, const aes_decrypt_ctx cx[1]); + +AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, const aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, const aes_decrypt_ctx cx[1]); + +AES_RETURN aes_mode_reset(aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +#define aes_ofb_encrypt aes_ofb_crypt +#define aes_ofb_decrypt aes_ofb_crypt + +AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]); + +typedef void cbuf_inc(unsigned char *cbuf); + +#define aes_ctr_encrypt aes_ctr_crypt +#define aes_ctr_decrypt aes_ctr_crypt + +AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]); + +#endif + +#if 0 && defined( ADD_AESNI_MODE_CALLS ) +# define USE_AES_CONTEXT +#endif + +#ifdef ADD_AESNI_MODE_CALLS +# ifdef USE_AES_CONTEXT + +AES_RETURN aes_CBC_encrypt(const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + const aes_encrypt_ctx cx[1]); + +AES_RETURN aes_CBC_decrypt(const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + const aes_decrypt_ctx cx[1]); + +AES_RETURN AES_CTR_encrypt(const unsigned char *in, + unsigned char *out, + const unsigned char ivec[8], + const unsigned char nonce[4], + unsigned long length, + const aes_encrypt_ctx cx[1]); + +# else + +void aes_CBC_encrypt(const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + unsigned char *key, + int number_of_rounds); + +void aes_CBC_decrypt(const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + unsigned char *key, + int number_of_rounds); + +void aes_CTR_encrypt(const unsigned char *in, + unsigned char *out, + const unsigned char ivec[8], + const unsigned char nonce[4], + unsigned long length, + const unsigned char *key, + int number_of_rounds); + +# endif +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/aes.txt b/krb5-1.21.3/src/lib/crypto/builtin/aes/aes.txt new file mode 100644 index 00000000..25710f29 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/aes.txt @@ -0,0 +1,622 @@ + +An AES (Rijndael) Implementation in C/C++ (as specified in FIPS-197) +==================================================================== + +Change (26/09/2018) +=================== + +1. Changes to test programs to allow them to be built on Linux/GCC + (with thanks to Michael Mohr). + +2. Rationalisation of the defines DLL_IMPORT, DYNAMIC_DLL and USE_DLL + in the test code - now DLL_IMPORT and DLL_DYNAMIC_LOAD + +3. Update the test_avs test to allow the testing of static, DLL and + dynamically loaded DLL libraries. + +Change (21/05/2018) +=================== + +1. Properly dectect presence of AESNI when using GCC (my thanks to + Peter Gutmann for this fix) + +Changes (6/12/2016) +==================== + +1. Changed function definition of has_aes_ni() to has_aes_ni(void), + suggested by Peter Gutmann + +2. Changed the default location for the vsyasm assembler to: + C:\Program Files\yasm + +Changes (27/09/2015) +==================== + +1. Added automatic dynamic table initialisation (my thanks to + Henrik S. Gamann who proposed this addition). + +Changes (09/09/2014) +==================== + +1. Added the ability to use Intel's hardware support for AES + with GCC on Windows and Linux + +Changes (01/09/2014) +==================== + +1. Clarify some user choices in the file aes_amd64.asm + +2. Change the detection of the x86 and x86_64 processors + in aesopt.h to allow assembler code use with GCC + +Changes (14/11/2013) +==================== + +1. Added the ability to use Intel's hardware support for AES + on Windows using Microsoft Visual Studio. + +2. Added the include 'stdint.h' and used the uint_t instead + of the old uint_t (e.g. uint_32t is now uint32_t). + +3. Added a missing .text directive in aes_x86_v2.asm that caused + runtime errors in one build configuration. + +Changes (16/04/2007) +==================== + +These changes remove errors in the VC++ build files and add some +improvements in file naming consitency and portability. There are +no changes to overcome reported bugs in the code. + +1. gen_tabs() has been renamed to aes_init() to better decribe its + function to those not familiar with AES internals. + +2. via_ace.h has been renamed to aes_via_ace.h. + +3. Minor changes have been made to aestab.h and aestab.c to enable + all the code to be compiled in either C or C++. + +4. The code for detecting memory alignment in aesmdoes.c has been + simplified and a new routine has been added: + + aes_test_alignment_detection() + + to check that the aligment test is likely to be correct. + +5. The addition of support for Structured Exception Handling (SEH) + to YASM (well done Peter and Michael!) has allowed the AMD64 + x64 assembler code to be changed to comply with SEH requriements. + +6. Corrections to build files (for win32 debug build). + +Overview +======== + +This code implements AES for both 32 and 64 bit systems with optional +assembler support for x86 and AMD64/EM64T (but optimised for AMD64). + +The basic AES source code files are as follows: + +aes.h the header file needed to use AES in C +aescpp.h the header file required with to use AES in C++ +aesopt.h the header file for setting options (and some common code) +aestab.h the header file for the AES table declaration +aescrypt.c the main C source code file for encryption and decryption +aeskey.c the main C source code file for the key schedule +aestab.c the main file for the AES tables +brg_types.h a header defining some standard types and DLL defines +brg_endian.h a header containing code to detect or define endianness +aes_x86_v1.asm x86 assembler (YASM) alternative to aescrypt.c using + large tables +aes_x86_v2.asm x86 assembler (YASM) alternative to aescrypt.c using + compressed tables +aes_amd64.asm AMD64 assembler (YASM) alternative to aescrypt.c using + compressed tables + +In addition AES modes are implemented in the files: + +aes_modes.c AES modes with optional support for VIA ACE detection and use +aes_via_ace.h the header file for VIA ACE support + +and Intel hardware support for AES (AES_NI) is implemented in the files + +aes_ni.h defines for AES_NI implementation +aes_ni.c the AES_NI implementation + +Other associated files for testing and support are: + +aesaux.h header for auxilliary routines for testsing +aesaux.c auxilliary routines for testsingt +aestst.h header file for setting the testing environment +rdtsc.h a header file that provides access to the Time Stamp Counter +aestst.c a simple test program for quick tests of the AES code +aesgav.c a program to generate and verify the test vector files +aesrav.c a program to verify output against the test vector files +aestmr.c a program to time the code on x86 systems +modetest.c a program to test the AES modes support +vbxam.doc a demonstration of AES DLL use from Visual Basic in Microsoft Word +vb.txt Visual Basic code from the above example (win32 only) +aesxam.c an example of AES use +tablegen.c a program to generate a simplified 'aestab.c' file for + use with compilers that find aestab.c too complex +yasm.rules the YASM build rules file for Microsoft Visual Studio 2005 +via_ace.txt describes support for the VIA ACE cryptography engine +aes.txt this file + +Building The AES Libraries +-------------------------- + +A. Versions +----------- + +The code can be used to build static and dynamic libraries, each in five +versions: + + Key scheduling code in C, encrypt/decrypt in: + + C C source code (win32 and x64) + ASM_X86_V1C large table x86 assembler code (win32) + ASM_X86_V2C compressed table x86 assembler code (win32) + ASM_AMD64 compressed table x64 assembler code (x64) + + Key scheduling and encrypt/decrypt code in assembler: + + ASM_X86_V2 compressed table x86 assembler (win32) + +The C version can be compiled for Win32 or x64 whereas the x86 and x64 +assembler versions are for Win32 and x64 respectively. + +If Intel's hardware support for AES (AES_NI) is available, it can be used +with either the C or the ASM_AMD64 version. If ASM_AMD64 is to be used, it +is important that the define USE_INTEL_AES_IF_PRESENT in asm_amd64.asm is +set to the same value as it has in aesopt.h + +B. YASM +------- + +If you wish to use the x86 assembler files you will also need the YASM open +source x86 assembler (r1331 or later) for Windows which can be obtained from: + + http://www.tortall.net/projects/yasm/ + +This assembler (vsyasm.exe) should be placed in the directory: + + C:\Program Files\yasm + +C. Configuration +---------------- + +The following configurations are available as projects for Visual Studio +but the following descriptions should allow them to be built in other x86 +environments + + lib_generic_c Win32 and x64 + headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h + (+ aes_ni.h for AES_NI) + C source: aescrypt.c, aeskey.c, aestab.c, aes_modes.c + (+ aes_ni.c for AES_NI) + defines + + dll_generic_c Win32 and x64 + headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h + (+ aes_ni.h for AES_NI) + C source: aescrypt.c, aeskey.c, aestab.c, aes_modes.c + (+ aes_ni.c for AES_NI) + defines DLL_EXPORT + + lib_asm_x86_v1c Win32 + headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h + C source: aeskey.c, aestab.c, aes_modes.c + x86 assembler: aes_x86_v1.asm + defines ASM_X86_V1C (set for C and assembler files) + + dll_asm_x86_v1c Win32 + headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h + C source: aeskey.c, aestab.c, aes_modes.c + x86 assembler: aes_x86_v1.asm + defines DLL_EXPORT, ASM_X86_V1C (set for C and assembler files) + + lib_asm_x86_v2c Win32 + headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h + C source: aeskey.c, aestab.c, aes_modes.c + x86 assembler: aes_x86_v2.asm + defines ASM_X86_V2C (set for C and assembler files) + + dll_asm_x86_v2c Win32 + headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h + C source: aeskey.c, aestab.c, aes_modes.c + x86 assembler: aes_x86_v1.asm + defines DLL_EXPORT, ASM_X86_V2C (set for C and assembler files) + + lib_asm_x86_v2 Win32 + headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h + C source: aes_modes.c + x86 assembler: aes_x86_v1.asm + defines ASM_X86_V2 (set for C and assembler files) + + dll_asm_x86_v2 Win32 + headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h + C source: aes_modes.c + x86 assembler: aes_x86_v1.asm + defines DLL_EXPORT, ASM_AMD64_C (set for C and assembler files) + + lib_asm_amd64_c x64 + headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h + (+ aes_ni.h for AES_NI) + C source: aes_modes.c (+ aes_ni.c for AES_NI) + x86 assembler: aes_amd64.asm + defines ASM_AMD64_C (set for C and assembler files) + + dll_asm_amd64_c x64 + headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h + (+ aes_ni.h for AES_NI) + C source: aes_modes.c (+ aes_ni.c for AES_NI) + x86 assembler: aes_amd64.asm + defines DLL_EXPORT, ASM_AMD64_C (set for C and assembler files) + +Notes: + +ASM_X86_V1C is defined if using the version 1 assembler code (aescrypt1.asm). + The defines in the assember file must match those in aes.h and + aesopt.h). Also remember to include/exclude the right assembler + and C files in the build to avoid undefined or multiply defined + symbols - include aes_x86_v1.asm and exclude aescrypt.c + +ASM_X86_V2 is defined if using the version 2 assembler code (aes_x86_v2.asm). + This version provides a full, self contained assembler version + and does not use any C source code files except for the mutiple + block encryption modes that are provided by aes_modes.c. The define + ASM_X86_V2 must be set on the YASM command line (or in aes_x86_v2.asm) + to use this version and all C files except aec_modes.c and, for the + DLL build, aestab.c must be excluded from the build. + +ASM_X86_V2C is defined when using the version 2 assembler code (aes_x86_v2.asm) + with faster key scheduling provided by the in C code (the options in + the assember file must match those in aes.h and aesopt.h). In this + case aeskey.c and aestab.c are needed with aes_x86_v2.asm and the + define ASM_X86_V2C must be set for both the C files and for + aes_x86_v2.asm in the build commands(or in aesopt.h and aes_x86_v2.asm). + Include aes_x86_v2.asm, aeskey.c and aestab.c, exclude aescrypt.c for + this option. + +ASM_AMD64_C is defined when using the AMD64 assembly code because the C key + scheduling is used in this case. + +DLL_EXPORT must be defined to generate the DLL version of the code and + to run tests on it + +DLL_IMPORT must be defined to use the DLL version of the code in an + application program + +Directories the paths for the various directories for test vector input and + output have to be set in aestst.h + +VIA ACE see the via_ace.txt for this item + +Static The static libraries are named: +Libraries + aes_lib_generic_c.lib + aes_lib_asm_x86_v1c.lib + aes_lib_asm_x86_v2.lib + aes_lib_asm_x86_v2c.lib + aes_lib_asm_amd64_c.lib + + and placed in one of the the directories: + + lib\win32\release\ + lib\win32\debug\ + lib\x64\release\ + lib\x64\debug\ + + in the aes root directory depending on the platform(win32 or + x64) and the build (release or debug). After any of these is + built it is then copied into the aes\lib directory, which is + the library location that is subsequently used for testing. + Hence testing is always for the last static library built. + +Dynamic These libraries are named: +Libraries + aes_lib_generic_c.dll + aes_lib_asm_x86_v1c.dll + aes_lib_asm_x86_v2.dll + aes_lib_asm_x86_v2c.dll + aes_lib_asm_amd64_c.dll + + and placed in one of the the directories: + + dll\win32\release\ + dll\win32\debug\ + dll\x64\release\ + dll\x64\debug\ + + in the aes root directory depending on the platform(win32 or + x64) and the build (release or debug). Each DLL library: + + aes_.dll + + has three associated files: + + aes_dll_.lib the library file for implicit linking + aes_dll_.exp the exports file + aes_dll_.pdb the symbol file + + After any DLL is built it and its three related files are then + copied to the aes\dll directory, which is the library location + used in subsequent testing. Hence testing is always for the + last DLL built. + +D. Testing +---------- + +These tests require that the test vector files are placed in the 'testvals' +subdirectory. If the AES Algorithm Validation Suite tests are used then +the *.fax files need to be put in the 'testvals\fax' subdirectory. This is +covered in more detail below. + +The projects test_lib and time_lib are used to test and time the last static +library built. They use the files: + + test_lib: Win32 (x64 for the C and AMD64 versions) + headers: aes.h, aescpp.h, brg_types.h, aesaux.h and aestst.h + C source: aesaux.c, aesrav.c + defines: + + time_lib: Win32 (x64 for the C and AMD64 versions) + headers: aes.h, aescpp.h, brg_types.h, aesaux.h, aestst.h and rdtsc.h + C source: aesaux.c, aestmr.c + defines: + +The projects test_dll and time_dll are used to test and time the last DLL +built. These use the files: + + test_dll: Win32 (x64 for the C and AMD64 versions) + headers: aes.h, aescpp.h, brg_types.h, aesaux.h and aestst.h + C source: aesaux.c, aesrav.c + defines: DLL_IMPORT + + time_dll: Win32 (x64 for the C and AMD64 versions) + headers: aes.h, aescpp.h, brg_types.h, aesaux.h aestst.h and rdtsc.h + C source: aesaux.c, aestmr.c + defines: DLL_IMPORT + +and default to linkingto with the AES DLL using dynamic (run-time) linking. Implicit +linking can be used by adding the lib file associated with the AES DLL (in the aes\dll +sub-directory) to the build (under project Properties|Linker in Visual Studio) and +removing the DLL_DYNAMIC_LOAD define (under project Properties|C/C++|Preprocessor). + +0 Link is linked into this project and the symbol +DLL_DYNAMIC_LOAD is left undefined, then implicit linking will be used + +The above tests take command line arguments that determine which test are run +as follows: + + test_lib /t:[knec] /k:[468] + test_dll /t:[knec] /k:[468] + +where the symbols in square brackets can be used in any combination (without +the brackets) and have the following meanings: + + /t:[knec] selects which tests are used + /k:[468] selects the key lengths used + /c compares output with reference (see later) + + k: generate ECB Known Answer Test files + n: generate ECB Known Answer Test files (new) + e: generate ECB Monte Carlo Test files + c: generate CBC Monte Carlo Test files + +and the characters giving the lengths are digits representing the key lengths +in 32-bit units (4, 6, 8 for lengths of 128, 192 or 256 bits respectively). + +The project test_modes tests the AES modes. It uses the files: + + test_modes: Win32 or x64 + headers: aes.h, aescpp.h, brg_types.h, aesaux,h and aestst.h + C source: aesaux.c, modetest.c + defines: none for static library test, DLL_IMPORT for DLL test + +which again links to the last library built. + +E. Other Applications +--------------------- + +These are: + + gen_tests builds the test_vector files. The commad line is + gen_tests /t:knec /k:468 /c + as described earlier + + test_aes_avs run the AES Algorithm Validation Suite tests for + ECB, CBC, CFB and OFB modes + + gen_tables builds a simple version of aes_tab.c (in aestab2.c) + for compilers that cannot handle the normal version + aes_example provides an example of AES use + +These applications are linked to the last static library built or, if +DLL_IMPORT is defined during compilation, to the last DLL built. + +F. Use of the VIA ACE Cryptography Engine (x86 only) +---------------------------------------------------- + +The use of the code with the VIA ACE cryptography engine in described in the +file via_ace.txt. In outline aes_modes.c is used and USE_VIA_ACE_IF_PRESENT +is defined either in section 2 of aesopt.h or as a compilation option in Visual +Studio. If in addition ASSUME_VIA_ACE_PRESENT is also defined then all normal +AES code will be removed if not needed to support VIA ACE use. If VIA ACE +support is needed and AES assembler is being used only the ASM_X86_V1C and +ASM_X86_V2C versions should be used since ASM_X86_V2 and ASM_AMD64 do not +support the VIA ACE engine. + +G. The AES Test Vector Files +---------------------------- + +These files fall in the following groups (where is a two digit +number): + +1. ecbvk.txt ECB vectors with variable key +2. ecbvt.txt ECB vectors with variable text +3. ecbnk.txt new ECB vectors with variable key +4. ecbnt.txt new ECB vectors with variable text +5. ecbme.txt ECB monte carlo encryption test vectors +6. ecbmd.txt ECB monte carlo decryption test vectors +7. cbcme.txt CBC monte carlo encryption test vectors +8. cbcmd.txt CBC monte carlo decryption test vectors + +The first digit of the numeric suffix on the filename gives the block size +in 32 bit units and the second numeric digit gives the key size. For example, +the file ecbvk44.txt provides the test vectors for ECB encryption with a 128 +bit block size and a 128 bit key size. The test routines expect to find these +files in the 'testvals' subdirectory within the aes root directory. The +'outvals' subdirectory is used for outputs that are compared with the files +in 'testvals'. Note that the monte carlo test vectors are the result of +applying AES iteratively 10000 times, not just once. + +The AES Algorithm Validation Suite tests can be run for ECB, CBC, CFB and +OFB modes (CFB1 and CFB8 are not implemented). The test routine uses the +*.fax test files, which should be placed in the 'testvals\fax' subdirectory. + +H. The Basic AES Calling Interface +---------------------------------- + +The basic AES code keeps its state in a context, there being different +contexts for encryption and decryption: + + aes_encrypt_ctx + aes_decrypt_ctx + +The AES code is initialised with the call + + aes_init(void) + +although this is only essential if the option to generate the AES tables at +run-time has been set in the options (i.e.fixed tables are not being used). + +The AES encryption key is set by one of the calls: + + aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]) + aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]) + aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]) + +or by: + + aes_encrypt_key(const unsigned char *key, int key_len, + aes_encrypt_ctx cx[1]) + +where the key length is set by 'key_len', which can be the length in bits +or bytes. + +Similarly, the AES decryption key is set by one of: + + aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]) + aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]) + aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]) + +or by: + + aes_decrypt_key(const unsigned char *key, int key_len, + aes_decrypt_ctx cx[1]) + +Encryption and decryption for a single 16 byte block is then achieved using: + + aes_encrypt(const unsigned char *in, unsigned char *out, + const aes_encrypt_ctx cx[1]) + aes_decrypt(const unsigned char *in, unsigned char *out, + const aes_decrypt_ctx cx[1]) + +The above subroutines return a value of EXIT_SUCCESS or EXIT_FAILURE +depending on whether the operation succeeded or failed. + +I. The Calling Interface for the AES Modes +------------------------------------------ + +The subroutines for the AES modes, ECB, CBC, CFB, OFB and CTR, each process +blocks of variable length and can also be called several times to complete +single mode operations incrementally on long messages (or those messages, +not all of which are available at the same time). The calls: + + aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, const aes_encrypt_ctx cx[1]) + + aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, const aes_decrypt_ctx cx[1]) + +for ECB operations and those for CBC: + + aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, const aes_encrypt_ctx cx[1]) + + aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, const aes_decrypt_ctx cx[1]) + +can only process blocks whose lengths are multiples of 16 bytes but the calls +for CFB, OFB and CTR mode operations: + + aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]) + + aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]) + + aes_ofb_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]) + + aes_ofb_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *iv, aes_encrypt_ctx cx[1]) + + aes_ctr_encrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]) + + aes_ctr_decrypt(const unsigned char *ibuf, unsigned char *obuf, + int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]) + +can process blocks of any length. Note also that CFB, OFB and CTR mode calls only +use AES encryption contexts even during decryption operations. + +The calls CTR mode operations use a buffer (cbuf) which holds the counter value +together with a function parameter: + + void cbuf_inc(unsigned char *cbuf); + +that is ued to update the counter value after each 16 byte AES operation. The +counter buffer is updated appropriately to allow for incremental operations. + +Please note the following IMPORTANT points about the AES mode subroutines: + + 1. All modes are reset when a new AES key is set. + + 2. Incremental calls to the different modes cannot + be mixed. If a change of mode is needed a new + key must be set or a reset must be issued (see + below). + + 3. For modes with IVs, the IV value is an input AND + an output since it is updated after each call to + the value needed for any subsequent incremental + call(s). If the mode is reset, the IV hence has + to be set (or reset) as well. + + 4. ECB operations must be multiples of 16 bytes + but do not need to be reset for new operations. + + 5. CBC operations must also be multiples of 16 + bytes and are reset for a new operation by + setting the IV. + + 6. CFB, OFB and CTR mode must be reset by setting + a new IV value AND by calling: + + aes_mode_reset(aes_encrypt_ctx cx[1]) + + For CTR mode the cbuf value also has to be reset. + + 7. CFB, OFB and CTR modes only use AES encryption + operations and contexts and do not need AES + decryption operations. + + 8. AES keys remain valid across resets and changes + of mode (but encryption and decryption keys must + both be set if they are needed). + + Brian Gladman 26/09/2018 + \ No newline at end of file diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/aescrypt.c b/krb5-1.21.3/src/lib/crypto/builtin/aes/aescrypt.c new file mode 100644 index 00000000..90a2946e --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/aescrypt.c @@ -0,0 +1,306 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 +*/ + +#include "aesopt.h" +#include "aestab.h" + +#include "crypto_int.h" +#ifdef K5_BUILTIN_AES + +#if defined( USE_INTEL_AES_IF_PRESENT ) +# include "aes_ni.h" +#else +/* map names here to provide the external API ('name' -> 'aes_name') */ +# define aes_xi(x) aes_ ## x +#endif + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c]) +#define so(y,x,c) word_out(y, c, s(x,c)) + +#if defined(ARRAYS) +#define locals(y,x) x[4],y[4] +#else +#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 +#endif + +#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ + s(y,2) = s(x,2); s(y,3) = s(x,3); +#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) +#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) +#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) + +#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) + +/* Visual C++ .Net v7.1 provides the fastest encryption code when using + Pentium optimisation with small code but this is poor for decryption + so we need to control this with the following VC++ pragmas +*/ + +#if defined( _MSC_VER ) && !defined( _WIN64 ) && !defined( __clang__ ) +#pragma optimize( "s", on ) +#endif + +/* Given the column (c) of the output state variable, the following + macros give the input state variables which are needed in its + computation for each row (r) of the state. All the alternative + macros give the same end values but expand into different ways + of calculating these values. In particular the complex macro + used for dynamically variable block sizes is designed to expand + to a compile time constant whenever possible but will expand to + conditional clauses on some branches (I am grateful to Frank + Yellin for this construction) +*/ + +#define fwd_var(x,r,c)\ + ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ + : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\ + : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ + : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))) + +#if defined(FT4_SET) +#undef dec_fmvars +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) +#elif defined(FT1_SET) +#undef dec_fmvars +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c)) +#else +#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c))) +#endif + +#if defined(FL4_SET) +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c)) +#elif defined(FL1_SET) +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c)) +#else +#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c)) +#endif + +AES_RETURN aes_xi(encrypt)(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]) +{ uint32_t locals(b0, b1); + const uint32_t *kp; +#if defined( dec_fmvars ) + dec_fmvars; /* declare variables for fwd_mcol() if needed */ +#endif + + if(cx->inf.b[0] != 10 * AES_BLOCK_SIZE && cx->inf.b[0] != 12 * AES_BLOCK_SIZE && cx->inf.b[0] != 14 * AES_BLOCK_SIZE) + return EXIT_FAILURE; + + kp = cx->ks; + state_in(b0, in, kp); + +#if (ENC_UNROLL == FULL) + + switch(cx->inf.b[0]) + { + case 14 * AES_BLOCK_SIZE: + round(fwd_rnd, b1, b0, kp + 1 * N_COLS); + round(fwd_rnd, b0, b1, kp + 2 * N_COLS); + kp += 2 * N_COLS; + case 12 * AES_BLOCK_SIZE: + round(fwd_rnd, b1, b0, kp + 1 * N_COLS); + round(fwd_rnd, b0, b1, kp + 2 * N_COLS); + kp += 2 * N_COLS; + case 10 * AES_BLOCK_SIZE: + round(fwd_rnd, b1, b0, kp + 1 * N_COLS); + round(fwd_rnd, b0, b1, kp + 2 * N_COLS); + round(fwd_rnd, b1, b0, kp + 3 * N_COLS); + round(fwd_rnd, b0, b1, kp + 4 * N_COLS); + round(fwd_rnd, b1, b0, kp + 5 * N_COLS); + round(fwd_rnd, b0, b1, kp + 6 * N_COLS); + round(fwd_rnd, b1, b0, kp + 7 * N_COLS); + round(fwd_rnd, b0, b1, kp + 8 * N_COLS); + round(fwd_rnd, b1, b0, kp + 9 * N_COLS); + round(fwd_lrnd, b0, b1, kp +10 * N_COLS); + } + +#else + +#if (ENC_UNROLL == PARTIAL) + { uint32_t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1ul; ++rnd) + { + kp += N_COLS; + round(fwd_rnd, b1, b0, kp); + kp += N_COLS; + round(fwd_rnd, b0, b1, kp); + } + kp += N_COLS; + round(fwd_rnd, b1, b0, kp); +#else + { uint32_t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1ul; ++rnd) + { + kp += N_COLS; + round(fwd_rnd, b1, b0, kp); + l_copy(b0, b1); + } +#endif + kp += N_COLS; + round(fwd_lrnd, b0, b1, kp); + } +#endif + + state_out(out, b0); + return EXIT_SUCCESS; +} + +#endif + +#if ( FUNCS_IN_C & DECRYPTION_IN_C) + +/* Visual C++ .Net v7.1 provides the fastest encryption code when using + Pentium optimisation with small code but this is poor for decryption + so we need to control this with the following VC++ pragmas +*/ + +#if defined( _MSC_VER ) && !defined( _WIN64 ) && !defined( __clang__ ) +#pragma optimize( "t", on ) +#endif + +/* Given the column (c) of the output state variable, the following + macros give the input state variables which are needed in its + computation for each row (r) of the state. All the alternative + macros give the same end values but expand into different ways + of calculating these values. In particular the complex macro + used for dynamically variable block sizes is designed to expand + to a compile time constant whenever possible but will expand to + conditional clauses on some branches (I am grateful to Frank + Yellin for this construction) +*/ + +#define inv_var(x,r,c)\ + ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ + : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\ + : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ + : ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))) + +#if defined(IT4_SET) +#undef dec_imvars +#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c)) +#elif defined(IT1_SET) +#undef dec_imvars +#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c)) +#else +#define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))) +#endif + +#if defined(IL4_SET) +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c)) +#elif defined(IL1_SET) +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c)) +#else +#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)) +#endif + +/* This code can work with the decryption key schedule in the */ +/* order that is used for encryption (where the 1st decryption */ +/* round key is at the high end ot the schedule) or with a key */ +/* schedule that has been reversed to put the 1st decryption */ +/* round key at the low end of the schedule in memory (when */ +/* AES_REV_DKS is defined) */ + +#ifdef AES_REV_DKS +#define key_ofs 0 +#define rnd_key(n) (kp + n * N_COLS) +#else +#define key_ofs 1 +#define rnd_key(n) (kp - n * N_COLS) +#endif + +AES_RETURN aes_xi(decrypt)(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]) +{ uint32_t locals(b0, b1); +#if defined( dec_imvars ) + dec_imvars; /* declare variables for inv_mcol() if needed */ +#endif + const uint32_t *kp; + + if(cx->inf.b[0] != 10 * AES_BLOCK_SIZE && cx->inf.b[0] != 12 * AES_BLOCK_SIZE && cx->inf.b[0] != 14 * AES_BLOCK_SIZE) + return EXIT_FAILURE; + + kp = cx->ks + (key_ofs ? (cx->inf.b[0] >> 2) : 0); + state_in(b0, in, kp); + +#if (DEC_UNROLL == FULL) + + kp = cx->ks + (key_ofs ? 0 : (cx->inf.b[0] >> 2)); + switch(cx->inf.b[0]) + { + case 14 * AES_BLOCK_SIZE: + round(inv_rnd, b1, b0, rnd_key(-13)); + round(inv_rnd, b0, b1, rnd_key(-12)); + case 12 * AES_BLOCK_SIZE: + round(inv_rnd, b1, b0, rnd_key(-11)); + round(inv_rnd, b0, b1, rnd_key(-10)); + case 10 * AES_BLOCK_SIZE: + round(inv_rnd, b1, b0, rnd_key(-9)); + round(inv_rnd, b0, b1, rnd_key(-8)); + round(inv_rnd, b1, b0, rnd_key(-7)); + round(inv_rnd, b0, b1, rnd_key(-6)); + round(inv_rnd, b1, b0, rnd_key(-5)); + round(inv_rnd, b0, b1, rnd_key(-4)); + round(inv_rnd, b1, b0, rnd_key(-3)); + round(inv_rnd, b0, b1, rnd_key(-2)); + round(inv_rnd, b1, b0, rnd_key(-1)); + round(inv_lrnd, b0, b1, rnd_key( 0)); + } + +#else + +#if (DEC_UNROLL == PARTIAL) + { uint32_t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1ul; ++rnd) + { + kp = rnd_key(1); + round(inv_rnd, b1, b0, kp); + kp = rnd_key(1); + round(inv_rnd, b0, b1, kp); + } + kp = rnd_key(1); + round(inv_rnd, b1, b0, kp); +#else + { uint32_t rnd; + for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1ul; ++rnd) + { + kp = rnd_key(1); + round(inv_rnd, b1, b0, kp); + l_copy(b0, b1); + } +#endif + kp = rnd_key(1); + round(inv_lrnd, b0, b1, kp); + } +#endif + + state_out(out, b0); + return EXIT_SUCCESS; +} + +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* K5_BUILTIN_AES */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/aeskey.c b/krb5-1.21.3/src/lib/crypto/builtin/aes/aeskey.c new file mode 100644 index 00000000..c5906f00 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/aeskey.c @@ -0,0 +1,578 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 +*/ + +#include "aesopt.h" +#include "aestab.h" + +#include "crypto_int.h" +#ifdef K5_BUILTIN_AES + +#if defined( USE_INTEL_AES_IF_PRESENT ) +# include "aes_ni.h" +#else +/* map names here to provide the external API ('name' -> 'aes_name') */ +# define aes_xi(x) aes_ ## x +#endif + +#ifdef USE_VIA_ACE_IF_PRESENT +# include "aes_via_ace.h" +#endif + +#if defined(__cplusplus) +extern "C" +{ +#endif + +/* Use the low bit in the context's inf.b[2] as a flag to + indicate whether a context was initialized for encryption + or decryption. +*/ +#define MARK_AS_ENCRYPTION_CTX(cx) (cx)->inf.b[2] |= (uint8_t)0x01 +#define MARK_AS_DECRYPTION_CTX(cx) (cx)->inf.b[2] &= (uint8_t)0xfe + +/* Initialise the key schedule from the user supplied key. The key + length can be specified in bytes, with legal values of 16, 24 + and 32, or in bits, with legal values of 128, 192 and 256. These + values correspond with Nk values of 4, 6 and 8 respectively. + + The following macros implement a single cycle in the key + schedule generation process. The number of cycles needed + for each cx->n_col and nk value is: + + nk = 4 5 6 7 8 + ------------------------------ + cx->n_col = 4 10 9 8 7 7 + cx->n_col = 5 14 11 10 9 9 + cx->n_col = 6 19 15 12 11 11 + cx->n_col = 7 21 19 16 13 14 + cx->n_col = 8 29 23 19 17 14 +*/ + +#if defined( REDUCE_CODE_SIZE ) +# define ls_box ls_sub + uint32_t ls_sub(const uint32_t t, const uint32_t n); +# define inv_mcol im_sub + uint32_t im_sub(const uint32_t x); +# ifdef ENC_KS_UNROLL +# undef ENC_KS_UNROLL +# endif +# ifdef DEC_KS_UNROLL +# undef DEC_KS_UNROLL +# endif +#endif + +#if (FUNCS_IN_C & ENC_KEYING_IN_C) + +#if defined(AES_128) || defined( AES_VAR ) + +#define ke4(k,i) \ +{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ + k[4*(i)+5] = ss[1] ^= ss[0]; \ + k[4*(i)+6] = ss[2] ^= ss[1]; \ + k[4*(i)+7] = ss[3] ^= ss[2]; \ +} + +AES_RETURN aes_xi(encrypt_key128)(const unsigned char *key, aes_encrypt_ctx cx[1]) +{ uint32_t ss[4]; + + cx->ks[0] = ss[0] = word_in(key, 0); + cx->ks[1] = ss[1] = word_in(key, 1); + cx->ks[2] = ss[2] = word_in(key, 2); + cx->ks[3] = ss[3] = word_in(key, 3); + +#ifdef ENC_KS_UNROLL + ke4(cx->ks, 0); ke4(cx->ks, 1); + ke4(cx->ks, 2); ke4(cx->ks, 3); + ke4(cx->ks, 4); ke4(cx->ks, 5); + ke4(cx->ks, 6); ke4(cx->ks, 7); + ke4(cx->ks, 8); +#else + { uint32_t i; + for(i = 0; i < 9; ++i) + ke4(cx->ks, i); + } +#endif + ke4(cx->ks, 9); + cx->inf.l = 0; + cx->inf.b[0] = 10 * AES_BLOCK_SIZE; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + MARK_AS_ENCRYPTION_CTX(cx); + return EXIT_SUCCESS; +} + +#endif + +#if defined(AES_192) || defined( AES_VAR ) + +#define kef6(k,i) \ +{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ + k[6*(i)+ 7] = ss[1] ^= ss[0]; \ + k[6*(i)+ 8] = ss[2] ^= ss[1]; \ + k[6*(i)+ 9] = ss[3] ^= ss[2]; \ +} + +#define ke6(k,i) \ +{ kef6(k,i); \ + k[6*(i)+10] = ss[4] ^= ss[3]; \ + k[6*(i)+11] = ss[5] ^= ss[4]; \ +} + +AES_RETURN aes_xi(encrypt_key192)(const unsigned char *key, aes_encrypt_ctx cx[1]) +{ uint32_t ss[6]; + + cx->ks[0] = ss[0] = word_in(key, 0); + cx->ks[1] = ss[1] = word_in(key, 1); + cx->ks[2] = ss[2] = word_in(key, 2); + cx->ks[3] = ss[3] = word_in(key, 3); + cx->ks[4] = ss[4] = word_in(key, 4); + cx->ks[5] = ss[5] = word_in(key, 5); + +#ifdef ENC_KS_UNROLL + ke6(cx->ks, 0); ke6(cx->ks, 1); + ke6(cx->ks, 2); ke6(cx->ks, 3); + ke6(cx->ks, 4); ke6(cx->ks, 5); + ke6(cx->ks, 6); +#else + { uint32_t i; + for(i = 0; i < 7; ++i) + ke6(cx->ks, i); + } +#endif + kef6(cx->ks, 7); + cx->inf.l = 0; + cx->inf.b[0] = 12 * AES_BLOCK_SIZE; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + MARK_AS_ENCRYPTION_CTX(cx); + return EXIT_SUCCESS; +} + +#endif + +#if defined(AES_256) || defined( AES_VAR ) + +#define kef8(k,i) \ +{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ + k[8*(i)+ 9] = ss[1] ^= ss[0]; \ + k[8*(i)+10] = ss[2] ^= ss[1]; \ + k[8*(i)+11] = ss[3] ^= ss[2]; \ +} + +#define ke8(k,i) \ +{ kef8(k,i); \ + k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); \ + k[8*(i)+13] = ss[5] ^= ss[4]; \ + k[8*(i)+14] = ss[6] ^= ss[5]; \ + k[8*(i)+15] = ss[7] ^= ss[6]; \ +} + +AES_RETURN aes_xi(encrypt_key256)(const unsigned char *key, aes_encrypt_ctx cx[1]) +{ uint32_t ss[8]; + + cx->ks[0] = ss[0] = word_in(key, 0); + cx->ks[1] = ss[1] = word_in(key, 1); + cx->ks[2] = ss[2] = word_in(key, 2); + cx->ks[3] = ss[3] = word_in(key, 3); + cx->ks[4] = ss[4] = word_in(key, 4); + cx->ks[5] = ss[5] = word_in(key, 5); + cx->ks[6] = ss[6] = word_in(key, 6); + cx->ks[7] = ss[7] = word_in(key, 7); + +#ifdef ENC_KS_UNROLL + ke8(cx->ks, 0); ke8(cx->ks, 1); + ke8(cx->ks, 2); ke8(cx->ks, 3); + ke8(cx->ks, 4); ke8(cx->ks, 5); +#else + { uint32_t i; + for(i = 0; i < 6; ++i) + ke8(cx->ks, i); + } +#endif + kef8(cx->ks, 6); + cx->inf.l = 0; + cx->inf.b[0] = 14 * AES_BLOCK_SIZE; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + MARK_AS_ENCRYPTION_CTX(cx); + return EXIT_SUCCESS; +} + +#endif + +#endif + +#if (FUNCS_IN_C & DEC_KEYING_IN_C) + +/* this is used to store the decryption round keys */ +/* in forward or reverse order */ + +#ifdef AES_REV_DKS +#define v(n,i) ((n) - (i) + 2 * ((i) & 3)) +#else +#define v(n,i) (i) +#endif + +#if DEC_ROUND == NO_TABLES +#define ff(x) (x) +#else +#define ff(x) inv_mcol(x) +#if defined( dec_imvars ) +#define d_vars dec_imvars +#endif +#endif + +#if defined(AES_128) || defined( AES_VAR ) + +#define k4e(k,i) \ +{ k[v(40,(4*(i))+4)] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ + k[v(40,(4*(i))+5)] = ss[1] ^= ss[0]; \ + k[v(40,(4*(i))+6)] = ss[2] ^= ss[1]; \ + k[v(40,(4*(i))+7)] = ss[3] ^= ss[2]; \ +} + +#if 1 + +#define kdf4(k,i) \ +{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \ + ss[1] = ss[1] ^ ss[3]; \ + ss[2] = ss[2] ^ ss[3]; \ + ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ + ss[i % 4] ^= ss[4]; \ + ss[4] ^= k[v(40,(4*(i)))]; k[v(40,(4*(i))+4)] = ff(ss[4]); \ + ss[4] ^= k[v(40,(4*(i))+1)]; k[v(40,(4*(i))+5)] = ff(ss[4]); \ + ss[4] ^= k[v(40,(4*(i))+2)]; k[v(40,(4*(i))+6)] = ff(ss[4]); \ + ss[4] ^= k[v(40,(4*(i))+3)]; k[v(40,(4*(i))+7)] = ff(ss[4]); \ +} + +#define kd4(k,i) \ +{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ + ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \ + k[v(40,(4*(i))+4)] = ss[4] ^= k[v(40,(4*(i)))]; \ + k[v(40,(4*(i))+5)] = ss[4] ^= k[v(40,(4*(i))+1)]; \ + k[v(40,(4*(i))+6)] = ss[4] ^= k[v(40,(4*(i))+2)]; \ + k[v(40,(4*(i))+7)] = ss[4] ^= k[v(40,(4*(i))+3)]; \ +} + +#define kdl4(k,i) \ +{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \ + k[v(40,(4*(i))+4)] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \ + k[v(40,(4*(i))+5)] = ss[1] ^ ss[3]; \ + k[v(40,(4*(i))+6)] = ss[0]; \ + k[v(40,(4*(i))+7)] = ss[1]; \ +} + +#else + +#define kdf4(k,i) \ +{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ff(ss[0]); \ + ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ff(ss[2]); \ + ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ff(ss[3]); \ +} + +#define kd4(k,i) \ +{ ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[v(40,(4*(i))+ 4)] = ss[4] ^= k[v(40,(4*(i)))]; \ + ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[4] ^= k[v(40,(4*(i))+ 1)]; \ + ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[4] ^= k[v(40,(4*(i))+ 2)]; \ + ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[4] ^= k[v(40,(4*(i))+ 3)]; \ +} + +#define kdl4(k,i) \ +{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ss[0]; \ + ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[1]; \ + ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[2]; \ + ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[3]; \ +} + +#endif + +AES_RETURN aes_xi(decrypt_key128)(const unsigned char *key, aes_decrypt_ctx cx[1]) +{ uint32_t ss[5]; +#if defined( d_vars ) + d_vars; +#endif + + cx->ks[v(40,(0))] = ss[0] = word_in(key, 0); + cx->ks[v(40,(1))] = ss[1] = word_in(key, 1); + cx->ks[v(40,(2))] = ss[2] = word_in(key, 2); + cx->ks[v(40,(3))] = ss[3] = word_in(key, 3); + +#ifdef DEC_KS_UNROLL + kdf4(cx->ks, 0); kd4(cx->ks, 1); + kd4(cx->ks, 2); kd4(cx->ks, 3); + kd4(cx->ks, 4); kd4(cx->ks, 5); + kd4(cx->ks, 6); kd4(cx->ks, 7); + kd4(cx->ks, 8); kdl4(cx->ks, 9); +#else + { uint32_t i; + for(i = 0; i < 10; ++i) + k4e(cx->ks, i); +#if !(DEC_ROUND == NO_TABLES) + for(i = N_COLS; i < 10 * N_COLS; ++i) + cx->ks[i] = inv_mcol(cx->ks[i]); +#endif + } +#endif + cx->inf.l = 0; + cx->inf.b[0] = 10 * AES_BLOCK_SIZE; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + MARK_AS_DECRYPTION_CTX(cx); + return EXIT_SUCCESS; +} + +#endif + +#if defined(AES_192) || defined( AES_VAR ) + +#define k6ef(k,i) \ +{ k[v(48,(6*(i))+ 6)] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ + k[v(48,(6*(i))+ 7)] = ss[1] ^= ss[0]; \ + k[v(48,(6*(i))+ 8)] = ss[2] ^= ss[1]; \ + k[v(48,(6*(i))+ 9)] = ss[3] ^= ss[2]; \ +} + +#define k6e(k,i) \ +{ k6ef(k,i); \ + k[v(48,(6*(i))+10)] = ss[4] ^= ss[3]; \ + k[v(48,(6*(i))+11)] = ss[5] ^= ss[4]; \ +} + +#define kdf6(k,i) \ +{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ff(ss[0]); \ + ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ff(ss[2]); \ + ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ff(ss[3]); \ + ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ff(ss[4]); \ + ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ff(ss[5]); \ +} + +#define kd6(k,i) \ +{ ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[v(48,(6*(i))+ 6)] = ss[6] ^= k[v(48,(6*(i)))]; \ + ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[6] ^= k[v(48,(6*(i))+ 1)]; \ + ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[6] ^= k[v(48,(6*(i))+ 2)]; \ + ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[6] ^= k[v(48,(6*(i))+ 3)]; \ + ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ss[6] ^= k[v(48,(6*(i))+ 4)]; \ + ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ss[6] ^= k[v(48,(6*(i))+ 5)]; \ +} + +#define kdl6(k,i) \ +{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ss[0]; \ + ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[1]; \ + ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[2]; \ + ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[3]; \ +} + +AES_RETURN aes_xi(decrypt_key192)(const unsigned char *key, aes_decrypt_ctx cx[1]) +{ uint32_t ss[7]; +#if defined( d_vars ) + d_vars; +#endif + + cx->ks[v(48,(0))] = ss[0] = word_in(key, 0); + cx->ks[v(48,(1))] = ss[1] = word_in(key, 1); + cx->ks[v(48,(2))] = ss[2] = word_in(key, 2); + cx->ks[v(48,(3))] = ss[3] = word_in(key, 3); + +#ifdef DEC_KS_UNROLL + ss[4] = word_in(key, 4); + ss[5] = word_in(key, 5); + cx->ks[v(48, (4))] = ff(ss[4]); + cx->ks[v(48, (5))] = ff(ss[5]); + kdf6(cx->ks, 0); kd6(cx->ks, 1); + kd6(cx->ks, 2); kd6(cx->ks, 3); + kd6(cx->ks, 4); kd6(cx->ks, 5); + kd6(cx->ks, 6); kdl6(cx->ks, 7); +#else + cx->ks[v(48,(4))] = ss[4] = word_in(key, 4); + cx->ks[v(48,(5))] = ss[5] = word_in(key, 5); + { uint32_t i; + + for(i = 0; i < 7; ++i) + k6e(cx->ks, i); + k6ef(cx->ks, 7); +#if !(DEC_ROUND == NO_TABLES) + for(i = N_COLS; i < 12 * N_COLS; ++i) + cx->ks[i] = inv_mcol(cx->ks[i]); +#endif + } +#endif + cx->inf.l = 0; + cx->inf.b[0] = 12 * AES_BLOCK_SIZE; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + MARK_AS_DECRYPTION_CTX(cx); + return EXIT_SUCCESS; +} + +#endif + +#if defined(AES_256) || defined( AES_VAR ) + +#define k8ef(k,i) \ +{ k[v(56,(8*(i))+ 8)] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ + k[v(56,(8*(i))+ 9)] = ss[1] ^= ss[0]; \ + k[v(56,(8*(i))+10)] = ss[2] ^= ss[1]; \ + k[v(56,(8*(i))+11)] = ss[3] ^= ss[2]; \ +} + +#define k8e(k,i) \ +{ k8ef(k,i); \ + k[v(56,(8*(i))+12)] = ss[4] ^= ls_box(ss[3],0); \ + k[v(56,(8*(i))+13)] = ss[5] ^= ss[4]; \ + k[v(56,(8*(i))+14)] = ss[6] ^= ss[5]; \ + k[v(56,(8*(i))+15)] = ss[7] ^= ss[6]; \ +} + +#define kdf8(k,i) \ +{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ff(ss[0]); \ + ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ff(ss[2]); \ + ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ff(ss[3]); \ + ss[4] ^= ls_box(ss[3],0); k[v(56,(8*(i))+12)] = ff(ss[4]); \ + ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ff(ss[5]); \ + ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ff(ss[6]); \ + ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ff(ss[7]); \ +} + +#define kd8(k,i) \ +{ ss[8] = ls_box(ss[7],3) ^ t_use(r,c)[i]; \ + ss[0] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+ 8)] = ss[8] ^= k[v(56,(8*(i)))]; \ + ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[8] ^= k[v(56,(8*(i))+ 1)]; \ + ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[8] ^= k[v(56,(8*(i))+ 2)]; \ + ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[8] ^= k[v(56,(8*(i))+ 3)]; \ + ss[8] = ls_box(ss[3],0); \ + ss[4] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+12)] = ss[8] ^= k[v(56,(8*(i))+ 4)]; \ + ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ss[8] ^= k[v(56,(8*(i))+ 5)]; \ + ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ss[8] ^= k[v(56,(8*(i))+ 6)]; \ + ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ss[8] ^= k[v(56,(8*(i))+ 7)]; \ +} + +#define kdl8(k,i) \ +{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ss[0]; \ + ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[1]; \ + ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[2]; \ + ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[3]; \ +} + +AES_RETURN aes_xi(decrypt_key256)(const unsigned char *key, aes_decrypt_ctx cx[1]) +{ uint32_t ss[9]; +#if defined( d_vars ) + d_vars; +#endif + + cx->ks[v(56,(0))] = ss[0] = word_in(key, 0); + cx->ks[v(56,(1))] = ss[1] = word_in(key, 1); + cx->ks[v(56,(2))] = ss[2] = word_in(key, 2); + cx->ks[v(56,(3))] = ss[3] = word_in(key, 3); + +#ifdef DEC_KS_UNROLL + ss[4] = word_in(key, 4); + ss[5] = word_in(key, 5); + ss[6] = word_in(key, 6); + ss[7] = word_in(key, 7); + cx->ks[v(56,(4))] = ff(ss[4]); + cx->ks[v(56,(5))] = ff(ss[5]); + cx->ks[v(56,(6))] = ff(ss[6]); + cx->ks[v(56,(7))] = ff(ss[7]); + kdf8(cx->ks, 0); kd8(cx->ks, 1); + kd8(cx->ks, 2); kd8(cx->ks, 3); + kd8(cx->ks, 4); kd8(cx->ks, 5); + kdl8(cx->ks, 6); +#else + cx->ks[v(56,(4))] = ss[4] = word_in(key, 4); + cx->ks[v(56,(5))] = ss[5] = word_in(key, 5); + cx->ks[v(56,(6))] = ss[6] = word_in(key, 6); + cx->ks[v(56,(7))] = ss[7] = word_in(key, 7); + { uint32_t i; + + for(i = 0; i < 6; ++i) + k8e(cx->ks, i); + k8ef(cx->ks, 6); +#if !(DEC_ROUND == NO_TABLES) + for(i = N_COLS; i < 14 * N_COLS; ++i) + cx->ks[i] = inv_mcol(cx->ks[i]); +#endif + } +#endif + cx->inf.l = 0; + cx->inf.b[0] = 14 * AES_BLOCK_SIZE; + +#ifdef USE_VIA_ACE_IF_PRESENT + if(VIA_ACE_AVAILABLE) + cx->inf.b[1] = 0xff; +#endif + MARK_AS_DECRYPTION_CTX(cx); + return EXIT_SUCCESS; +} + +#endif + +#endif + +#if defined( AES_VAR ) + +AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]) +{ + switch(key_len) + { + case 16: case 128: return aes_encrypt_key128(key, cx); + case 24: case 192: return aes_encrypt_key192(key, cx); + case 32: case 256: return aes_encrypt_key256(key, cx); + default: return EXIT_FAILURE; + } +} + +AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]) +{ + switch(key_len) + { + case 16: case 128: return aes_decrypt_key128(key, cx); + case 24: case 192: return aes_decrypt_key192(key, cx); + case 32: case 256: return aes_decrypt_key256(key, cx); + default: return EXIT_FAILURE; + } +} + +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* K5_BUILTIN_AES */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/aesopt.h b/krb5-1.21.3/src/lib/crypto/builtin/aes/aesopt.h new file mode 100644 index 00000000..5d24c8a8 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/aesopt.h @@ -0,0 +1,786 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 + + This file contains the compilation options for AES (Rijndael) and code + that is common across encryption, key scheduling and table generation. + + OPERATION + + These source code files implement the AES algorithm Rijndael designed by + Joan Daemen and Vincent Rijmen. This version is designed for the standard + block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24 + and 32 bytes). + + This version is designed for flexibility and speed using operations on + 32-bit words rather than operations on bytes. It can be compiled with + either big or little endian internal byte order but is faster when the + native byte order for the processor is used. + + THE CIPHER INTERFACE + + The cipher interface is implemented as an array of bytes in which lower + AES bit sequence indexes map to higher numeric significance within bytes. + + uint8_t (an unsigned 8-bit type) + uint32_t (an unsigned 32-bit type) + struct aes_encrypt_ctx (structure for the cipher encryption context) + struct aes_decrypt_ctx (structure for the cipher decryption context) + AES_RETURN the function return type + + C subroutine calls: + + AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); + AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); + AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); + AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, + const aes_encrypt_ctx cx[1]); + + AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); + AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); + AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); + AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, + const aes_decrypt_ctx cx[1]); + + IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that + you call aes_init() before AES is used so that the tables are initialised. + + C++ aes class subroutines: + + Class AESencrypt for encryption + + Constructors: + AESencrypt(void) + AESencrypt(const unsigned char *key) - 128 bit key + Members: + AES_RETURN key128(const unsigned char *key) + AES_RETURN key192(const unsigned char *key) + AES_RETURN key256(const unsigned char *key) + AES_RETURN encrypt(const unsigned char *in, unsigned char *out) const + + Class AESdecrypt for encryption + Constructors: + AESdecrypt(void) + AESdecrypt(const unsigned char *key) - 128 bit key + Members: + AES_RETURN key128(const unsigned char *key) + AES_RETURN key192(const unsigned char *key) + AES_RETURN key256(const unsigned char *key) + AES_RETURN decrypt(const unsigned char *in, unsigned char *out) const +*/ + +#if !defined( _AESOPT_H ) +#define _AESOPT_H + +#if defined( __cplusplus ) +#include "aescpp.h" +#else +#include "aes.h" +#endif + +/* PLATFORM SPECIFIC INCLUDES */ + +#include "brg_endian.h" + +/* CONFIGURATION - THE USE OF DEFINES + + Later in this section there are a number of defines that control the + operation of the code. In each section, the purpose of each define is + explained so that the relevant form can be included or excluded by + setting either 1's or 0's respectively on the branches of the related + #if clauses. The following local defines should not be changed. +*/ + +#define ENCRYPTION_IN_C 1 +#define DECRYPTION_IN_C 2 +#define ENC_KEYING_IN_C 4 +#define DEC_KEYING_IN_C 8 + +#define NO_TABLES 0 +#define ONE_TABLE 1 +#define FOUR_TABLES 4 +#define NONE 0 +#define PARTIAL 1 +#define FULL 2 + +/* --- START OF USER CONFIGURED OPTIONS --- */ + +/* 1. BYTE ORDER WITHIN 32 BIT WORDS + + The fundamental data processing units in Rijndael are 8-bit bytes. The + input, output and key input are all enumerated arrays of bytes in which + bytes are numbered starting at zero and increasing to one less than the + number of bytes in the array in question. This enumeration is only used + for naming bytes and does not imply any adjacency or order relationship + from one byte to another. When these inputs and outputs are considered + as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to + byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. + In this implementation bits are numbered from 0 to 7 starting at the + numerically least significant end of each byte (bit n represents 2^n). + + However, Rijndael can be implemented more efficiently using 32-bit + words by packing bytes into words so that bytes 4*n to 4*n+3 are placed + into word[n]. While in principle these bytes can be assembled into words + in any positions, this implementation only supports the two formats in + which bytes in adjacent positions within words also have adjacent byte + numbers. This order is called big-endian if the lowest numbered bytes + in words have the highest numeric significance and little-endian if the + opposite applies. + + This code can work in either order irrespective of the order used by the + machine on which it runs. Normally the internal byte order will be set + to the order of the processor on which the code is to be run but this + define can be used to reverse this in special situations + + WARNING: Assembler code versions rely on PLATFORM_BYTE_ORDER being set. + This define will hence be redefined later (in section 4) if necessary +*/ + +#if 1 +# define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER +#elif 0 +# define ALGORITHM_BYTE_ORDER IS_LITTLE_ENDIAN +#elif 0 +# define ALGORITHM_BYTE_ORDER IS_BIG_ENDIAN +#else +# error The algorithm byte order is not defined +#endif + +/* 2. Intel AES AND VIA ACE SUPPORT */ + +#if defined( __GNUC__ ) && defined( __i386__ ) && !defined(__BEOS__) \ + || defined( _WIN32 ) && defined( _M_IX86 ) && !(defined( _WIN64 ) \ + || defined( _WIN32_WCE ) || defined( _MSC_VER ) && ( _MSC_VER <= 800 )) +# define VIA_ACE_POSSIBLE +#endif + +/* AESNI is supported by all Windows x64 compilers, but for Linux/GCC + we have to test for SSE 2, SSE 3, and AES to before enabling it; */ +#if !defined( INTEL_AES_POSSIBLE ) +# if defined( _WIN64 ) && defined( _MSC_VER ) \ + || defined( __GNUC__ ) && defined( __x86_64__ ) && \ + defined( __SSE2__ ) && defined( __SSE3__ ) && \ + defined( __AES__ ) +# define INTEL_AES_POSSIBLE +# endif +#endif + +/* Define this option if support for the Intel AESNI is required + If USE_INTEL_AES_IF_PRESENT is defined then AESNI will be used + if it is detected (both present and enabled). + + AESNI uses a decryption key schedule with the first decryption + round key at the high end of the key schedule with the following + round keys at lower positions in memory. So AES_REV_DKS must NOT + be defined when AESNI will be used. Although it is unlikely that + assembler code will be used with an AESNI build, if it is then + AES_REV_DKS must NOT be defined when the assembler files are + built (the definition of USE_INTEL_AES_IF_PRESENT in the assembler + code files must match that here if they are used). +*/ + +#if defined( INTEL_AES_POSSIBLE ) +# if 0 && !defined( USE_INTEL_AES_IF_PRESENT ) +# define USE_INTEL_AES_IF_PRESENT +# endif +#elif defined( USE_INTEL_AES_IF_PRESENT ) +# error: AES_NI is not available on this platform +#endif + +/* Define this option if support for the VIA ACE is required. This uses + inline assembler instructions and is only implemented for the Microsoft, + Intel and GCC compilers. If VIA ACE is known to be present, then defining + ASSUME_VIA_ACE_PRESENT will remove the ordinary encryption/decryption + code. If USE_VIA_ACE_IF_PRESENT is defined then VIA ACE will be used if + it is detected (both present and enabled) but the normal AES code will + also be present. + + When VIA ACE is to be used, all AES encryption contexts MUST be 16 byte + aligned; other input/output buffers do not need to be 16 byte aligned + but there are very large performance gains if this can be arranged. + VIA ACE also requires the decryption key schedule to be in reverse + order (which later checks below ensure). + + AES_REV_DKS must be set for assembler code used with a VIA ACE build +*/ + +#if 0 && defined( VIA_ACE_POSSIBLE ) && !defined( USE_VIA_ACE_IF_PRESENT ) +# define USE_VIA_ACE_IF_PRESENT +#endif + +#if 0 && defined( VIA_ACE_POSSIBLE ) && !defined( ASSUME_VIA_ACE_PRESENT ) +# define ASSUME_VIA_ACE_PRESENT +# endif + +/* 3. ASSEMBLER SUPPORT + + This define (which can be on the command line) enables the use of the + assembler code routines for encryption, decryption and key scheduling + as follows: + + ASM_X86_V1C uses the assembler (aes_x86_v1.asm) with large tables for + encryption and decryption and but with key scheduling in C + ASM_X86_V2 uses assembler (aes_x86_v2.asm) with compressed tables for + encryption, decryption and key scheduling + ASM_X86_V2C uses assembler (aes_x86_v2.asm) with compressed tables for + encryption and decryption and but with key scheduling in C + ASM_AMD64_C uses assembler (aes_amd64.asm) with compressed tables for + encryption and decryption and but with key scheduling in C + + Change one 'if 0' below to 'if 1' to select the version or define + as a compilation option. +*/ + +#if 0 && !defined( ASM_X86_V1C ) +# define ASM_X86_V1C +#elif 0 && !defined( ASM_X86_V2 ) +# define ASM_X86_V2 +#elif 0 && !defined( ASM_X86_V2C ) +# define ASM_X86_V2C +#elif 0 && !defined( ASM_AMD64_C ) +# define ASM_AMD64_C +#endif + +#if defined( __i386 ) || defined( _M_IX86 ) +# define A32_ +#elif defined( __x86_64__ ) || defined( _M_X64 ) +# define A64_ +#endif + +#if (defined ( ASM_X86_V1C ) || defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) \ + && !defined( A32_ ) || defined( ASM_AMD64_C ) && !defined( A64_ ) +# error Assembler code is only available for x86 and AMD64 systems +#endif + +/* 4. FAST INPUT/OUTPUT OPERATIONS. + + On some machines it is possible to improve speed by transferring the + bytes in the input and output arrays to and from the internal 32-bit + variables by addressing these arrays as if they are arrays of 32-bit + words. On some machines this will always be possible but there may + be a large performance penalty if the byte arrays are not aligned on + the normal word boundaries. On other machines this technique will + lead to memory access errors when such 32-bit word accesses are not + properly aligned. The option SAFE_IO avoids such problems but will + often be slower on those machines that support misaligned access + (especially so if care is taken to align the input and output byte + arrays on 32-bit word boundaries). If SAFE_IO is not defined it is + assumed that access to byte arrays as if they are arrays of 32-bit + words will not cause problems when such accesses are misaligned. +*/ +#if 1 && !defined( _MSC_VER ) +# define SAFE_IO +#endif + +/* 5. LOOP UNROLLING + + The code for encryption and decryption cycles through a number of rounds + that can be implemented either in a loop or by expanding the code into a + long sequence of instructions, the latter producing a larger program but + one that will often be much faster. The latter is called loop unrolling. + There are also potential speed advantages in expanding two iterations in + a loop with half the number of iterations, which is called partial loop + unrolling. The following options allow partial or full loop unrolling + to be set independently for encryption and decryption +*/ +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) +# define ENC_UNROLL FULL +#elif 0 +# define ENC_UNROLL PARTIAL +#else +# define ENC_UNROLL NONE +#endif + +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) +# define DEC_UNROLL FULL +#elif 0 +# define DEC_UNROLL PARTIAL +#else +# define DEC_UNROLL NONE +#endif + +#if 1 +# define ENC_KS_UNROLL +#endif + +#if 1 +# define DEC_KS_UNROLL +#endif + +/* 6. FAST FINITE FIELD OPERATIONS + + If this section is included, tables are used to provide faster finite + field arithmetic (this has no effect if STATIC_TABLES is defined). +*/ +#if 1 +# define FF_TABLES +#endif + +/* 7. INTERNAL STATE VARIABLE FORMAT + + The internal state of Rijndael is stored in a number of local 32-bit + word variables which can be defined either as an array or as individual + names variables. Include this section if you want to store these local + variables in arrays. Otherwise individual local variables will be used. +*/ +#if 1 +# define ARRAYS +#endif + +/* 8. FIXED OR DYNAMIC TABLES + + When this section is included the tables used by the code are compiled + statically into the binary file. Otherwise the subroutine aes_init() + must be called to compute them before the code is first used. +*/ +#if 1 && !(defined( _MSC_VER ) && ( _MSC_VER <= 800 )) +# define STATIC_TABLES +#endif + +/* 9. MASKING OR CASTING FROM LONGER VALUES TO BYTES + + In some systems it is better to mask longer values to extract bytes + rather than using a cast. This option allows this choice. +*/ +#if 0 +# define to_byte(x) ((uint8_t)(x)) +#else +# define to_byte(x) ((x) & 0xff) +#endif + +/* 10. TABLE ALIGNMENT + + On some systems speed will be improved by aligning the AES large lookup + tables on particular boundaries. This define should be set to a power of + two giving the desired alignment. It can be left undefined if alignment + is not needed. This option is specific to the Microsoft VC++ compiler - + it seems to sometimes cause trouble for the VC++ version 6 compiler. +*/ + +#if 1 && defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) +# define TABLE_ALIGN 32 +#endif + +/* 11. REDUCE CODE AND TABLE SIZE + + This replaces some expanded macros with function calls if AES_ASM_V2 or + AES_ASM_V2C are defined +*/ + +#if 1 && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) +# define REDUCE_CODE_SIZE +#endif + +/* 12. TABLE OPTIONS + + This cipher proceeds by repeating in a number of cycles known as 'rounds' + which are implemented by a round function which can optionally be speeded + up using tables. The basic tables are each 256 32-bit words, with either + one or four tables being required for each round function depending on + how much speed is required. The encryption and decryption round functions + are different and the last encryption and decryption round functions are + different again making four different round functions in all. + + This means that: + 1. Normal encryption and decryption rounds can each use either 0, 1 + or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + 2. The last encryption and decryption rounds can also use either 0, 1 + or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + + Include or exclude the appropriate definitions below to set the number + of tables used by this implementation. +*/ + +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) /* set tables for the normal encryption round */ +# define ENC_ROUND FOUR_TABLES +#elif 0 +# define ENC_ROUND ONE_TABLE +#else +# define ENC_ROUND NO_TABLES +#endif + +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) /* set tables for the last encryption round */ +# define LAST_ENC_ROUND FOUR_TABLES +#elif 0 +# define LAST_ENC_ROUND ONE_TABLE +#else +# define LAST_ENC_ROUND NO_TABLES +#endif + +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) /* set tables for the normal decryption round */ +# define DEC_ROUND FOUR_TABLES +#elif 0 +# define DEC_ROUND ONE_TABLE +#else +# define DEC_ROUND NO_TABLES +#endif + +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) /* set tables for the last decryption round */ +# define LAST_DEC_ROUND FOUR_TABLES +#elif 0 +# define LAST_DEC_ROUND ONE_TABLE +#else +# define LAST_DEC_ROUND NO_TABLES +#endif + +/* The decryption key schedule can be speeded up with tables in the same + way that the round functions can. Include or exclude the following + defines to set this requirement. +*/ +#if !defined(CONFIG_SMALL) || defined(CONFIG_SMALL_NO_CRYPTO) +# define KEY_SCHED FOUR_TABLES +#elif 0 +# define KEY_SCHED ONE_TABLE +#else +# define KEY_SCHED NO_TABLES +#endif + +/* ---- END OF USER CONFIGURED OPTIONS ---- */ + +/* VIA ACE support is only available for VC++ and GCC */ + +#if !defined( _MSC_VER ) && !defined( __GNUC__ ) +# if defined( ASSUME_VIA_ACE_PRESENT ) +# undef ASSUME_VIA_ACE_PRESENT +# endif +# if defined( USE_VIA_ACE_IF_PRESENT ) +# undef USE_VIA_ACE_IF_PRESENT +# endif +#endif + +#if defined( ASSUME_VIA_ACE_PRESENT ) && !defined( USE_VIA_ACE_IF_PRESENT ) +# define USE_VIA_ACE_IF_PRESENT +#endif + +/* define to reverse decryption key schedule */ +#if 1 || defined( USE_VIA_ACE_IF_PRESENT ) && !defined ( AES_REV_DKS ) +# define AES_REV_DKS +#endif + +/* Intel AESNI uses a decryption key schedule in the encryption order */ +#if defined( USE_INTEL_AES_IF_PRESENT ) && defined ( AES_REV_DKS ) +# undef AES_REV_DKS +#endif + +/* Assembler support requires the use of platform byte order */ + +#if ( defined( ASM_X86_V1C ) || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) ) \ + && (ALGORITHM_BYTE_ORDER != PLATFORM_BYTE_ORDER) +# undef ALGORITHM_BYTE_ORDER +# define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER +#endif + +/* In this implementation the columns of the state array are each held in + 32-bit words. The state array can be held in various ways: in an array + of words, in a number of individual word variables or in a number of + processor registers. The following define maps a variable name x and + a column number c to the way the state array variable is to be held. + The first define below maps the state into an array x[c] whereas the + second form maps the state into a number of individual variables x0, + x1, etc. Another form could map individual state columns to machine + register names. +*/ + +#if defined( ARRAYS ) +# define s(x,c) x[c] +#else +# define s(x,c) x##c +#endif + +/* This implementation provides subroutines for encryption, decryption + and for setting the three key lengths (separately) for encryption + and decryption. Since not all functions are needed, masks are set + up here to determine which will be implemented in C +*/ + +#if !defined( AES_ENCRYPT ) +# define EFUNCS_IN_C 0 +#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ + || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) +# define EFUNCS_IN_C ENC_KEYING_IN_C +#elif !defined( ASM_X86_V2 ) +# define EFUNCS_IN_C ( ENCRYPTION_IN_C | ENC_KEYING_IN_C ) +#else +# define EFUNCS_IN_C 0 +#endif + +#if !defined( AES_DECRYPT ) +# define DFUNCS_IN_C 0 +#elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ + || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) +# define DFUNCS_IN_C DEC_KEYING_IN_C +#elif !defined( ASM_X86_V2 ) +# define DFUNCS_IN_C ( DECRYPTION_IN_C | DEC_KEYING_IN_C ) +#else +# define DFUNCS_IN_C 0 +#endif + +#define FUNCS_IN_C ( EFUNCS_IN_C | DFUNCS_IN_C ) + +/* END OF CONFIGURATION OPTIONS */ + +#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2)) + +/* Disable or report errors on some combinations of options */ + +#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES +# undef LAST_ENC_ROUND +# define LAST_ENC_ROUND NO_TABLES +#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES +# undef LAST_ENC_ROUND +# define LAST_ENC_ROUND ONE_TABLE +#endif + +#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE +# undef ENC_UNROLL +# define ENC_UNROLL NONE +#endif + +#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES +# undef LAST_DEC_ROUND +# define LAST_DEC_ROUND NO_TABLES +#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES +# undef LAST_DEC_ROUND +# define LAST_DEC_ROUND ONE_TABLE +#endif + +#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE +# undef DEC_UNROLL +# define DEC_UNROLL NONE +#endif + +#if defined( bswap32 ) +# define aes_sw32 bswap32 +#elif defined( bswap_32 ) +# define aes_sw32 bswap_32 +#else +# define brot(x,n) (((uint32_t)(x) << n) | ((uint32_t)(x) >> (32 - n))) +# define aes_sw32(x) ((brot((x),8) & 0x00ff00ff) | (brot((x),24) & 0xff00ff00)) +#endif + +/* upr(x,n): rotates bytes within words by n positions, moving bytes to + higher index positions with wrap around into low positions + ups(x,n): moves bytes by n positions to higher index positions in + words but without wrap around + bval(x,n): extracts a byte from a word + + WARNING: The definitions given here are intended only for use with + unsigned variables and with shift counts that are compile + time constants +*/ + +#if ( ALGORITHM_BYTE_ORDER == IS_LITTLE_ENDIAN ) +# define upr(x,n) (((uint32_t)(x) << (8 * (n))) | ((uint32_t)(x) >> (32 - 8 * (n)))) +# define ups(x,n) ((uint32_t) (x) << (8 * (n))) +# define bval(x,n) to_byte((x) >> (8 * (n))) +# define bytes2word(b0, b1, b2, b3) \ + (((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0)) +#endif + +#if ( ALGORITHM_BYTE_ORDER == IS_BIG_ENDIAN ) +# define upr(x,n) (((uint32_t)(x) >> (8 * (n))) | ((uint32_t)(x) << (32 - 8 * (n)))) +# define ups(x,n) ((uint32_t) (x) >> (8 * (n))) +# define bval(x,n) to_byte((x) >> (24 - 8 * (n))) +# define bytes2word(b0, b1, b2, b3) \ + (((uint32_t)(b0) << 24) | ((uint32_t)(b1) << 16) | ((uint32_t)(b2) << 8) | (b3)) +#endif + +#if defined( SAFE_IO ) +# define word_in(x,c) bytes2word(((const uint8_t*)(x)+4*c)[0], ((const uint8_t*)(x)+4*c)[1], \ + ((const uint8_t*)(x)+4*c)[2], ((const uint8_t*)(x)+4*c)[3]) +# define word_out(x,c,v) { ((uint8_t*)(x)+4*c)[0] = bval(v,0); ((uint8_t*)(x)+4*c)[1] = bval(v,1); \ + ((uint8_t*)(x)+4*c)[2] = bval(v,2); ((uint8_t*)(x)+4*c)[3] = bval(v,3); } +#elif ( ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER ) +# define word_in(x,c) (*((uint32_t*)(x)+(c))) +# define word_out(x,c,v) (*((uint32_t*)(x)+(c)) = (v)) +#else +# define word_in(x,c) aes_sw32(*((uint32_t*)(x)+(c))) +# define word_out(x,c,v) (*((uint32_t*)(x)+(c)) = aes_sw32(v)) +#endif + +/* the finite field modular polynomial and elements */ + +#define WPOLY 0x011b +#define BPOLY 0x1b + +/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ + +#define gf_c1 0x80808080 +#define gf_c2 0x7f7f7f7f +#define gf_mulx(x) ((((x) & gf_c2) << 1) ^ ((((x) & gf_c1) >> 7) * BPOLY)) + +/* The following defines provide alternative definitions of gf_mulx that might + give improved performance if a fast 32-bit multiply is not available. Note + that a temporary variable u needs to be defined where gf_mulx is used. + +#define gf_mulx(x) (u = (x) & gf_c1, u |= (u >> 1), ((x) & gf_c2) << 1) ^ ((u >> 3) | (u >> 6)) +#define gf_c4 (0x01010101 * BPOLY) +#define gf_mulx(x) (u = (x) & gf_c1, ((x) & gf_c2) << 1) ^ ((u - (u >> 7)) & gf_c4) +*/ + +/* Work out which tables are needed for the different options */ + +#if defined( ASM_X86_V1C ) +# if defined( ENC_ROUND ) +# undef ENC_ROUND +# endif +# define ENC_ROUND FOUR_TABLES +# if defined( LAST_ENC_ROUND ) +# undef LAST_ENC_ROUND +# endif +# define LAST_ENC_ROUND FOUR_TABLES +# if defined( DEC_ROUND ) +# undef DEC_ROUND +# endif +# define DEC_ROUND FOUR_TABLES +# if defined( LAST_DEC_ROUND ) +# undef LAST_DEC_ROUND +# endif +# define LAST_DEC_ROUND FOUR_TABLES +# if defined( KEY_SCHED ) +# undef KEY_SCHED +# define KEY_SCHED FOUR_TABLES +# endif +#endif + +#if ( FUNCS_IN_C & ENCRYPTION_IN_C ) || defined( ASM_X86_V1C ) +# if ENC_ROUND == ONE_TABLE +# define FT1_SET +# elif ENC_ROUND == FOUR_TABLES +# define FT4_SET +# else +# define SBX_SET +# endif +# if LAST_ENC_ROUND == ONE_TABLE +# define FL1_SET +# elif LAST_ENC_ROUND == FOUR_TABLES +# define FL4_SET +# elif !defined( SBX_SET ) +# define SBX_SET +# endif +#endif + +#if ( FUNCS_IN_C & DECRYPTION_IN_C ) || defined( ASM_X86_V1C ) +# if DEC_ROUND == ONE_TABLE +# define IT1_SET +# elif DEC_ROUND == FOUR_TABLES +# define IT4_SET +# else +# define ISB_SET +# endif +# if LAST_DEC_ROUND == ONE_TABLE +# define IL1_SET +# elif LAST_DEC_ROUND == FOUR_TABLES +# define IL4_SET +# elif !defined(ISB_SET) +# define ISB_SET +# endif +#endif + +#if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C ))) +# if ((FUNCS_IN_C & ENC_KEYING_IN_C) || (FUNCS_IN_C & DEC_KEYING_IN_C)) +# if KEY_SCHED == ONE_TABLE +# if !defined( FL1_SET ) && !defined( FL4_SET ) +# define LS1_SET +# endif +# elif KEY_SCHED == FOUR_TABLES +# if !defined( FL4_SET ) +# define LS4_SET +# endif +# elif !defined( SBX_SET ) +# define SBX_SET +# endif +# endif +# if (FUNCS_IN_C & DEC_KEYING_IN_C) +# if KEY_SCHED == ONE_TABLE +# define IM1_SET +# elif KEY_SCHED == FOUR_TABLES +# define IM4_SET +# elif !defined( SBX_SET ) +# define SBX_SET +# endif +# endif +#endif + +/* generic definitions of Rijndael macros that use tables */ + +#define no_table(x,box,vf,rf,c) bytes2word( \ + box[bval(vf(x,0,c),rf(0,c))], \ + box[bval(vf(x,1,c),rf(1,c))], \ + box[bval(vf(x,2,c),rf(2,c))], \ + box[bval(vf(x,3,c),rf(3,c))]) + +#define one_table(x,op,tab,vf,rf,c) \ + ( tab[bval(vf(x,0,c),rf(0,c))] \ + ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ + ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ + ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) + +#define four_tables(x,tab,vf,rf,c) \ + ( tab[0][bval(vf(x,0,c),rf(0,c))] \ + ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ + ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ + ^ tab[3][bval(vf(x,3,c),rf(3,c))]) + +#define vf1(x,r,c) (x) +#define rf1(r,c) (r) +#define rf2(r,c) ((8+r-c)&3) + +/* perform forward and inverse column mix operation on four bytes in long word x in */ +/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */ + +#if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C ))) + +#if defined( FM4_SET ) /* not currently used */ +# define fwd_mcol(x) four_tables(x,t_use(f,m),vf1,rf1,0) +#elif defined( FM1_SET ) /* not currently used */ +# define fwd_mcol(x) one_table(x,upr,t_use(f,m),vf1,rf1,0) +#else +# define dec_fmvars uint32_t g2 +# define fwd_mcol(x) (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1)) +#endif + +#if defined( IM4_SET ) +# define inv_mcol(x) four_tables(x,t_use(i,m),vf1,rf1,0) +#elif defined( IM1_SET ) +# define inv_mcol(x) one_table(x,upr,t_use(i,m),vf1,rf1,0) +#else +# define dec_imvars uint32_t g2, g4, g9 +# define inv_mcol(x) (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = (x) ^ gf_mulx(g4), g4 ^= g9, \ + (x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1)) +#endif + +#if defined( FL4_SET ) +# define ls_box(x,c) four_tables(x,t_use(f,l),vf1,rf2,c) +#elif defined( LS4_SET ) +# define ls_box(x,c) four_tables(x,t_use(l,s),vf1,rf2,c) +#elif defined( FL1_SET ) +# define ls_box(x,c) one_table(x,upr,t_use(f,l),vf1,rf2,c) +#elif defined( LS1_SET ) +# define ls_box(x,c) one_table(x,upr,t_use(l,s),vf1,rf2,c) +#else +# define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c) +#endif + +#endif + +#if defined( ASM_X86_V1C ) && defined( AES_DECRYPT ) && !defined( ISB_SET ) +# define ISB_SET +#endif + +#endif diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/aestab.c b/krb5-1.21.3/src/lib/crypto/builtin/aes/aestab.c new file mode 100644 index 00000000..740815f1 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/aestab.c @@ -0,0 +1,429 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 +*/ + +#define DO_TABLES + +#include "aes.h" +#include "aesopt.h" + +#include "crypto_int.h" +#ifdef K5_BUILTIN_AES + +#if defined(STATIC_TABLES) + +#define sb_data(w) {\ + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ + w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ + w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ + w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ + w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ + w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ + w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ + w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ + w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ + w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ + w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ + w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ + w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ + w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ + w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ + w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ + w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ + w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ + w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ + w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ + w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ + w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ + w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ + w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ + w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ + w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ + w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ + w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } + +#define isb_data(w) {\ + w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ + w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ + w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ + w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ + w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ + w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ + w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ + w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ + w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ + w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ + w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ + w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ + w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ + w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ + w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ + w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ + w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ + w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ + w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ + w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ + w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ + w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ + w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ + w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ + w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ + w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ + w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ + w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ + w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ + w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ + w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ + w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) } + +#define mm_data(w) {\ + w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ + w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ + w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ + w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ + w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ + w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ + w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ + w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ + w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ + w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ + w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ + w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ + w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ + w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ + w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ + w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ + w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ + w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ + w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ + w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ + w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ + w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ + w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ + w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ + w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ + w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ + w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ + w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ + w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ + w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ + w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ + w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) } + +#define rc_data(w) {\ + w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\ + w(0x1b), w(0x36) } + +#define h0(x) (x) + +#define w0(p) bytes2word(p, 0, 0, 0) +#define w1(p) bytes2word(0, p, 0, 0) +#define w2(p) bytes2word(0, 0, p, 0) +#define w3(p) bytes2word(0, 0, 0, p) + +#define u0(p) bytes2word(f2(p), p, p, f3(p)) +#define u1(p) bytes2word(f3(p), f2(p), p, p) +#define u2(p) bytes2word(p, f3(p), f2(p), p) +#define u3(p) bytes2word(p, p, f3(p), f2(p)) + +#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) +#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) +#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) +#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) + +#endif + +#if defined(STATIC_TABLES) || !defined(FF_TABLES) + +#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) +#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) +#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ + ^ (((x>>5) & 4) * WPOLY)) +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +#else + +#define f2(x) ((x) ? pow[log[x] + 0x19] : 0) +#define f3(x) ((x) ? pow[log[x] + 0x01] : 0) +#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0) +#define fb(x) ((x) ? pow[log[x] + 0x68] : 0) +#define fd(x) ((x) ? pow[log[x] + 0xee] : 0) +#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0) + +#endif + +#include "aestab.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +#if defined(STATIC_TABLES) + +/* implemented in case of wrong call for fixed tables */ + +AES_RETURN aes_init(void) +{ + return EXIT_SUCCESS; +} + +#else /* Generate the tables for the dynamic table option */ + +#if defined(FF_TABLES) + +#define gf_inv(x) ((x) ? pow[ 255 - log[x]] : 0) + +#else + +/* It will generally be sensible to use tables to compute finite + field multiplies and inverses but where memory is scarse this + code might sometimes be better. But it only has effect during + initialisation so its pretty unimportant in overall terms. +*/ + +/* return 2 ^ (n - 1) where n is the bit number of the highest bit + set in x with x in the range 1 < x < 0x00000200. This form is + used so that locals within fi can be bytes rather than words +*/ + +static uint8_t hibit(const uint32_t x) +{ uint8_t r = (uint8_t)((x >> 1) | (x >> 2)); + + r |= (r >> 2); + r |= (r >> 4); + return (r + 1) >> 1; +} + +/* return the inverse of the finite field element x */ + +static uint8_t gf_inv(const uint8_t x) +{ uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; + + if(x < 2) + return x; + + for( ; ; ) + { + if(n1) + while(n2 >= n1) /* divide polynomial p2 by p1 */ + { + n2 /= n1; /* shift smaller polynomial left */ + p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */ + v2 ^= v1 * n2; /* shift accumulated value and */ + n2 = hibit(p2); /* add into result */ + } + else + return v1; + + if(n2) /* repeat with values swapped */ + while(n1 >= n2) + { + n1 /= n2; + p1 ^= p2 * n1; + v1 ^= v2 * n1; + n1 = hibit(p1); + } + else + return v2; + } +} + +#endif + +/* The forward and inverse affine transformations used in the S-box */ +uint8_t fwd_affine(const uint8_t x) +{ uint32_t w = x; + w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4); + return 0x63 ^ ((w ^ (w >> 8)) & 0xff); +} + +uint8_t inv_affine(const uint8_t x) +{ uint32_t w = x; + w = (w << 1) ^ (w << 3) ^ (w << 6); + return 0x05 ^ ((w ^ (w >> 8)) & 0xff); +} + +static int init = 0; + +AES_RETURN aes_init(void) +{ uint32_t i, w; + +#if defined(FF_TABLES) + + uint8_t pow[512], log[256]; + + if(init) + return EXIT_SUCCESS; + /* log and power tables for GF(2^8) finite field with + WPOLY as modular polynomial - the simplest primitive + root is 0x03, used here to generate the tables + */ + + i = 0; w = 1; + do + { + pow[i] = (uint8_t)w; + pow[i + 255] = (uint8_t)w; + log[w] = (uint8_t)i++; + w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0); + } + while (w != 1); + +#else + if(init) + return EXIT_SUCCESS; +#endif + + for(i = 0, w = 1; i < RC_LENGTH; ++i) + { + t_set(r,c)[i] = bytes2word(w, 0, 0, 0); + w = f2(w); + } + + for(i = 0; i < 256; ++i) + { uint8_t b; + + b = fwd_affine(gf_inv((uint8_t)i)); + w = bytes2word(f2(b), b, b, f3(b)); + +#if defined( SBX_SET ) + t_set(s,box)[i] = b; +#endif + +#if defined( FT1_SET ) /* tables for a normal encryption round */ + t_set(f,n)[i] = w; +#endif +#if defined( FT4_SET ) + t_set(f,n)[0][i] = w; + t_set(f,n)[1][i] = upr(w,1); + t_set(f,n)[2][i] = upr(w,2); + t_set(f,n)[3][i] = upr(w,3); +#endif + w = bytes2word(b, 0, 0, 0); + +#if defined( FL1_SET ) /* tables for last encryption round (may also */ + t_set(f,l)[i] = w; /* be used in the key schedule) */ +#endif +#if defined( FL4_SET ) + t_set(f,l)[0][i] = w; + t_set(f,l)[1][i] = upr(w,1); + t_set(f,l)[2][i] = upr(w,2); + t_set(f,l)[3][i] = upr(w,3); +#endif + +#if defined( LS1_SET ) /* table for key schedule if t_set(f,l) above is*/ + t_set(l,s)[i] = w; /* not of the required form */ +#endif +#if defined( LS4_SET ) + t_set(l,s)[0][i] = w; + t_set(l,s)[1][i] = upr(w,1); + t_set(l,s)[2][i] = upr(w,2); + t_set(l,s)[3][i] = upr(w,3); +#endif + + b = gf_inv(inv_affine((uint8_t)i)); + w = bytes2word(fe(b), f9(b), fd(b), fb(b)); + +#if defined( IM1_SET ) /* tables for the inverse mix column operation */ + t_set(i,m)[b] = w; +#endif +#if defined( IM4_SET ) + t_set(i,m)[0][b] = w; + t_set(i,m)[1][b] = upr(w,1); + t_set(i,m)[2][b] = upr(w,2); + t_set(i,m)[3][b] = upr(w,3); +#endif + +#if defined( ISB_SET ) + t_set(i,box)[i] = b; +#endif +#if defined( IT1_SET ) /* tables for a normal decryption round */ + t_set(i,n)[i] = w; +#endif +#if defined( IT4_SET ) + t_set(i,n)[0][i] = w; + t_set(i,n)[1][i] = upr(w,1); + t_set(i,n)[2][i] = upr(w,2); + t_set(i,n)[3][i] = upr(w,3); +#endif + w = bytes2word(b, 0, 0, 0); +#if defined( IL1_SET ) /* tables for last decryption round */ + t_set(i,l)[i] = w; +#endif +#if defined( IL4_SET ) + t_set(i,l)[0][i] = w; + t_set(i,l)[1][i] = upr(w,1); + t_set(i,l)[2][i] = upr(w,2); + t_set(i,l)[3][i] = upr(w,3); +#endif + } + init = 1; + return EXIT_SUCCESS; +} + +/* + Automatic code initialisation (suggested by by Henrik S. Gaßmann) + based on code provided by Joe Lowe and placed in the public domain at: + http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc +*/ + +#ifdef _MSC_VER + +#pragma section(".CRT$XCU", read) + +__declspec(allocate(".CRT$XCU")) void (__cdecl *aes_startup)(void) = aes_init; + +#elif defined(__GNUC__) + +static void aes_startup(void) __attribute__((constructor)); + +static void aes_startup(void) +{ + aes_init(); +} + +#else + +#pragma message( "dynamic tables must be initialised manually on your system" ) + +#endif + +#endif + +#if defined(__cplusplus) +} +#endif + +#else /* K5_BUILTIN_AES */ + +/* Include aestab.h for proper dependency generation, but without defining the + * table objects. */ +#undef DO_TABLES +#include "aestab.h" + +#endif diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/aestab.h b/krb5-1.21.3/src/lib/crypto/builtin/aes/aestab.h new file mode 100644 index 00000000..8fe32d18 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/aestab.h @@ -0,0 +1,173 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 20/12/2007 + + This file contains the code for declaring the tables needed to implement + AES. The file aesopt.h is assumed to be included before this header file. + If there are no global variables, the definitions here can be used to put + the AES tables in a structure so that a pointer can then be added to the + AES context to pass them to the AES routines that need them. If this + facility is used, the calling program has to ensure that this pointer is + managed appropriately. In particular, the value of the t_dec(in,it) item + in the table structure must be set to zero in order to ensure that the + tables are initialised. In practice the three code sequences in aeskey.c + that control the calls to aes_init() and the aes_init() routine itself will + have to be changed for a specific implementation. If global variables are + available it will generally be preferable to use them with the precomputed + STATIC_TABLES option that uses static global tables. + + The following defines can be used to control the way the tables + are defined, initialised and used in embedded environments that + require special features for these purposes + + the 't_dec' construction is used to declare fixed table arrays + the 't_set' construction is used to set fixed table values + the 't_use' construction is used to access fixed table values + + 256 byte tables: + + t_xxx(s,box) => forward S box + t_xxx(i,box) => inverse S box + + 256 32-bit word OR 4 x 256 32-bit word tables: + + t_xxx(f,n) => forward normal round + t_xxx(f,l) => forward last round + t_xxx(i,n) => inverse normal round + t_xxx(i,l) => inverse last round + t_xxx(l,s) => key schedule table + t_xxx(i,m) => key schedule table + + Other variables and tables: + + t_xxx(r,c) => the rcon table +*/ + +#if !defined( _AESTAB_H ) +#define _AESTAB_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#define t_dec(m,n) t_##m##n +#define t_set(m,n) t_##m##n +#define t_use(m,n) t_##m##n + +#if defined(STATIC_TABLES) +# if !defined( __GNUC__ ) && (defined( __MSDOS__ ) || defined( __WIN16__ )) +/* make tables far data to avoid using too much DGROUP space (PG) */ +# define CONST const far +# else +# define CONST const +# endif +#else +# define CONST +#endif + +#if defined(DO_TABLES) +# define EXTERN +#else +# define EXTERN extern +#endif + +#if defined(_MSC_VER) && defined(TABLE_ALIGN) +#define ALIGN __declspec(align(TABLE_ALIGN)) +#else +#define ALIGN +#endif + +#if defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 ) +# define XP_DIR __cdecl +#else +# define XP_DIR +#endif + +#if defined(DO_TABLES) && defined(STATIC_TABLES) +#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] = b(e) +#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) } +EXTERN ALIGN CONST uint32_t t_dec(r,c)[RC_LENGTH] = rc_data(w0); +#else +#define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] +#define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] +EXTERN ALIGN CONST uint32_t t_dec(r,c)[RC_LENGTH]; +#endif + +#if defined( SBX_SET ) + d_1(uint8_t, t_dec(s,box), sb_data, h0); +#endif +#if defined( ISB_SET ) + d_1(uint8_t, t_dec(i,box), isb_data, h0); +#endif + +#if defined( FT1_SET ) + d_1(uint32_t, t_dec(f,n), sb_data, u0); +#endif +#if defined( FT4_SET ) + d_4(uint32_t, t_dec(f,n), sb_data, u0, u1, u2, u3); +#endif + +#if defined( FL1_SET ) + d_1(uint32_t, t_dec(f,l), sb_data, w0); +#endif +#if defined( FL4_SET ) + d_4(uint32_t, t_dec(f,l), sb_data, w0, w1, w2, w3); +#endif + +#if defined( IT1_SET ) + d_1(uint32_t, t_dec(i,n), isb_data, v0); +#endif +#if defined( IT4_SET ) + d_4(uint32_t, t_dec(i,n), isb_data, v0, v1, v2, v3); +#endif + +#if defined( IL1_SET ) + d_1(uint32_t, t_dec(i,l), isb_data, w0); +#endif +#if defined( IL4_SET ) + d_4(uint32_t, t_dec(i,l), isb_data, w0, w1, w2, w3); +#endif + +#if defined( LS1_SET ) +#if defined( FL1_SET ) +#undef LS1_SET +#else + d_1(uint32_t, t_dec(l,s), sb_data, w0); +#endif +#endif + +#if defined( LS4_SET ) +#if defined( FL4_SET ) +#undef LS4_SET +#else + d_4(uint32_t, t_dec(l,s), sb_data, w0, w1, w2, w3); +#endif +#endif + +#if defined( IM1_SET ) + d_1(uint32_t, t_dec(i,m), mm_data, v0); +#endif +#if defined( IM4_SET ) + d_4(uint32_t, t_dec(i,m), mm_data, v0, v1, v2, v3); +#endif + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/brg_endian.h b/krb5-1.21.3/src/lib/crypto/builtin/aes/brg_endian.h new file mode 100644 index 00000000..c0e32b7c --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/brg_endian.h @@ -0,0 +1,144 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 10/09/2018 +*/ + +#ifndef _BRG_ENDIAN_H +#define _BRG_ENDIAN_H + +#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ +#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ + +/* This is needed when using clang with MSVC to avoid including */ +/* endian.h and byteswap.h which are not present on Windows */ +#if defined( _MSC_VER ) && defined( __clang__ ) +# undef __GNUC__ +#endif + +/* Include files where endian defines and byteswap functions may reside */ +#if defined( __sun ) +# include +#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) +# include +#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \ + defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ ) +# include +#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ ) +# if !defined( __MINGW32__ ) && !defined( _AIX ) +# include +# if !defined( __BEOS__ ) +# include +# endif +# endif +#endif + +/* Now attempt to set the define for platform byte order using any */ +/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, ... */ +/* which seem to encompass most endian symbol definitions */ + +#if defined( __ORDER_BIG_ENDIAN__ ) && defined( __ORDER_LITTLE_ENDIAN__ ) +# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( __ORDER_BIG_ENDIAN__ ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( __ORDER_LITTLE_ENDIAN__ ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN ) +# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN ) +# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( _BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( _LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN ) +# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( __BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( __LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ ) +# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__ +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__ +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( __BIG_ENDIAN__ ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( __LITTLE_ENDIAN__ ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +/* if the platform byte order could not be determined, then try to */ +/* set this define using common machine defines */ +#if !defined(PLATFORM_BYTE_ORDER) + +#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \ + defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \ + defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \ + defined( vax ) || defined( vms ) || defined( VMS ) || \ + defined( __VMS ) || defined( _M_X64 ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN + +#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \ + defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \ + defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \ + defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \ + defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \ + defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \ + defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN + +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#else +# error Please edit lines 126 or 128 in brg_endian.h to set the platform byte order +#endif + +#endif + +#endif diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/brg_types.h b/krb5-1.21.3/src/lib/crypto/builtin/aes/brg_types.h new file mode 100644 index 00000000..ce3a1e7b --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/brg_types.h @@ -0,0 +1,217 @@ +/* +--------------------------------------------------------------------------- +Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. + +The redistribution and use of this software (with or without changes) +is allowed without the payment of fees or royalties provided that: + + source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation. + +This software is provided 'as is' with no explicit or implied warranties +in respect of its operation, including, but not limited to, correctness +and fitness for purpose. +--------------------------------------------------------------------------- +Issue Date: 30/09/2017 +*/ + +#ifndef _BRG_TYPES_H +#define _BRG_TYPES_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#include +#include + +#if defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) +# include +# define ptrint_t intptr_t +#elif defined( __ECOS__ ) +# define intptr_t unsigned int +# define ptrint_t intptr_t +#elif defined( __GNUC__ ) && ( __GNUC__ >= 3 ) && !(defined( __HAIKU__ ) || defined( __VxWorks__ )) +# define ptrint_t intptr_t +#else +# define ptrint_t int +#endif + +/* define unsigned 8-bit type if not available in stdint.h */ +#if !defined(UINT8_MAX) + typedef unsigned char uint8_t; +#endif + +/* define unsigned 16-bit type if not available in stdint.h */ +#if !defined(UINT16_MAX) + typedef unsigned short uint16_t; +#endif + +/* define unsigned 32-bit type if not available in stdint.h and define the + macro li_32(h) which converts a sequence of eight hexadecimal characters + into a 32 bit constant +*/ +#if defined(UINT_MAX) && UINT_MAX == 4294967295u +# define li_32(h) 0x##h##u +# if !defined(UINT32_MAX) + typedef unsigned int uint32_t; +# endif +#elif defined(ULONG_MAX) && ULONG_MAX == 4294967295u +# define li_32(h) 0x##h##ul +# if !defined(UINT32_MAX) + typedef unsigned long uint32_t; +# endif +#elif defined( _CRAY ) +# error This code needs 32-bit data types, which Cray machines do not provide +#else +# error Please define uint32_t as a 32-bit unsigned integer type in brg_types.h +#endif + +/* define unsigned 64-bit type if not available in stdint.h and define the + macro li_64(h) which converts a sequence of eight hexadecimal characters + into a 64 bit constant +*/ +#if defined( __BORLANDC__ ) && !defined( __MSDOS__ ) +# define li_64(h) 0x##h##ui64 +# if !defined(UINT64_MAX) + typedef unsigned __int64 uint64_t; +# endif +#elif defined( _MSC_VER ) && ( _MSC_VER < 1300 ) /* 1300 == VC++ 7.0 */ +# define li_64(h) 0x##h##ui64 +# if !defined(UINT64_MAX) + typedef unsigned __int64 uint64_t; +# endif +#elif defined( __sun ) && defined( ULONG_MAX ) && ULONG_MAX == 0xfffffffful +# define li_64(h) 0x##h##ull +# if !defined(UINT64_MAX) + typedef unsigned long long uint64_t; +# endif +#elif defined( __MVS__ ) +# define li_64(h) 0x##h##ull +# if !defined(UINT64_MAX) + typedef unsigned long long uint64_t; +# endif +#elif defined( UINT_MAX ) && UINT_MAX > 4294967295u +# if UINT_MAX == 18446744073709551615u +# define li_64(h) 0x##h##u +# if !defined(UINT64_MAX) + typedef unsigned int uint64_t; +# endif +# endif +#elif defined( ULONG_MAX ) && ULONG_MAX > 4294967295u +# if ULONG_MAX == 18446744073709551615ul +# define li_64(h) 0x##h##ul +# if !defined(UINT64_MAX) && !defined(_UINT64_T) + typedef unsigned long uint64_t; +# endif +# endif +#elif defined( ULLONG_MAX ) && ULLONG_MAX > 4294967295u +# if ULLONG_MAX == 18446744073709551615ull +# define li_64(h) 0x##h##ull +# if !defined(UINT64_MAX) && !defined( __HAIKU__ ) + typedef unsigned long long uint64_t; +# endif +# endif +#elif defined( ULONG_LONG_MAX ) && ULONG_LONG_MAX > 4294967295u +# if ULONG_LONG_MAX == 18446744073709551615ull +# define li_64(h) 0x##h##ull +# if !defined(UINT64_MAX) + typedef unsigned long long uint64_t; +# endif +# endif +#endif + +#if !defined( li_64 ) +# if defined( NEED_UINT_64T ) +# error Please define uint64_t as an unsigned 64 bit type in brg_types.h +# endif +#endif + +#ifndef RETURN_VALUES +# define RETURN_VALUES +# if defined( DLL_EXPORT ) +# if defined( _MSC_VER ) || defined ( __INTEL_COMPILER ) +# define VOID_RETURN __declspec( dllexport ) void __stdcall +# define INT_RETURN __declspec( dllexport ) int __stdcall +# elif defined( __GNUC__ ) +# define VOID_RETURN __declspec( __dllexport__ ) void +# define INT_RETURN __declspec( __dllexport__ ) int +# else +# error Use of the DLL is only available on the Microsoft, Intel and GCC compilers +# endif +# elif defined( DLL_IMPORT ) +# if defined( _MSC_VER ) || defined ( __INTEL_COMPILER ) +# define VOID_RETURN __declspec( dllimport ) void __stdcall +# define INT_RETURN __declspec( dllimport ) int __stdcall +# elif defined( __GNUC__ ) +# define VOID_RETURN __declspec( __dllimport__ ) void +# define INT_RETURN __declspec( __dllimport__ ) int +# else +# error Use of the DLL is only available on the Microsoft, Intel and GCC compilers +# endif +# elif defined( __WATCOMC__ ) +# define VOID_RETURN void __cdecl +# define INT_RETURN int __cdecl +# else +# define VOID_RETURN void +# define INT_RETURN int +# endif +#endif + +/* These defines are used to detect and set the memory alignment of pointers. + Note that offsets are in bytes. + + ALIGN_OFFSET(x,n) return the positive or zero offset of + the memory addressed by the pointer 'x' + from an address that is aligned on an + 'n' byte boundary ('n' is a power of 2) + + ALIGN_FLOOR(x,n) return a pointer that points to memory + that is aligned on an 'n' byte boundary + and is not higher than the memory address + pointed to by 'x' ('n' is a power of 2) + + ALIGN_CEIL(x,n) return a pointer that points to memory + that is aligned on an 'n' byte boundary + and is not lower than the memory address + pointed to by 'x' ('n' is a power of 2) +*/ + +#define ALIGN_OFFSET(x,n) (((ptrint_t)(x)) & ((n) - 1)) +#define ALIGN_FLOOR(x,n) ((uint8_t*)(x) - ( ((ptrint_t)(x)) & ((n) - 1))) +#define ALIGN_CEIL(x,n) ((uint8_t*)(x) + (-((ptrint_t)(x)) & ((n) - 1))) + +/* These defines are used to declare buffers in a way that allows + faster operations on longer variables to be used. In all these + defines 'size' must be a power of 2 and >= 8. NOTE that the + buffer size is in bytes but the type length is in bits + + UNIT_TYPEDEF(x,size) declares a variable 'x' of length + 'size' bits + + BUFR_TYPEDEF(x,size,bsize) declares a buffer 'x' of length 'bsize' + bytes defined as an array of variables + each of 'size' bits (bsize must be a + multiple of size / 8) + + UNIT_CAST(x,size) casts a variable to a type of + length 'size' bits + + UPTR_CAST(x,size) casts a pointer to a pointer to a + variable of length 'size' bits +*/ + +#define UI_TYPE(size) uint##size##_t +#define UNIT_TYPEDEF(x,size) typedef UI_TYPE(size) x +#define BUFR_TYPEDEF(x,size,bsize) typedef UI_TYPE(size) x[bsize / (size >> 3)] +#define UNIT_CAST(x,size) ((UI_TYPE(size) )(x)) +#define UPTR_CAST(x,size) ((UI_TYPE(size)*)(x)) + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/deps b/krb5-1.21.3/src/lib/crypto/builtin/aes/deps new file mode 100644 index 00000000..8574622a --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/deps @@ -0,0 +1,37 @@ +# +# Generated makefile dependencies follow. +# +aescrypt.so aescrypt.po $(OUTPRE)aescrypt.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h aes.h aescrypt.c \ + aesopt.h aestab.h brg_endian.h brg_types.h +aestab.so aestab.po $(OUTPRE)aestab.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + aes.h aesopt.h aestab.c aestab.h brg_endian.h brg_types.h +aeskey.so aeskey.po $(OUTPRE)aeskey.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + aes.h aeskey.c aesopt.h aestab.h brg_endian.h brg_types.h diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/iaesx64.s b/krb5-1.21.3/src/lib/crypto/builtin/aes/iaesx64.s new file mode 100644 index 00000000..bc7210ab --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/iaesx64.s @@ -0,0 +1,799 @@ +[bits 64] +[CPU intelnop] + +; Copyright (c) 2010, Intel Corporation +; 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 Intel Corporation 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 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. + +%define iEncExpandKey128 k5_iEncExpandKey128 +%define iEncExpandKey256 k5_iEncExpandKey256 +%define iDecExpandKey128 k5_iDecExpandKey128 +%define iDecExpandKey256 k5_iDecExpandKey256 +%define iEnc128_CBC k5_iEnc128_CBC +%define iEnc256_CBC k5_iEnc256_CBC +%define iDec128_CBC k5_iDec128_CBC +%define iDec256_CBC k5_iDec256_CBC + +%macro linux_setup 0 +%ifdef __linux__ + mov rcx, rdi + mov rdx, rsi +%endif +%endmacro + +%macro inversekey 1 + movdqu xmm1,%1 + aesimc xmm0,xmm1 + movdqu %1,xmm0 +%endmacro + +%macro aesdeclast1 1 + aesdeclast xmm0,%1 +%endmacro + +%macro aesenclast1 1 + aesenclast xmm0,%1 +%endmacro + +%macro aesdec1 1 + aesdec xmm0,%1 +%endmacro + +%macro aesenc1 1 + aesenc xmm0,%1 +%endmacro + + +%macro aesdeclast1_u 1 + movdqu xmm4,%1 + aesdeclast xmm0,xmm4 +%endmacro + +%macro aesenclast1_u 1 + movdqu xmm4,%1 + aesenclast xmm0,xmm4 +%endmacro + +%macro aesdec1_u 1 + movdqu xmm4,%1 + aesdec xmm0,xmm4 +%endmacro + +%macro aesenc1_u 1 + movdqu xmm4,%1 + aesenc xmm0,xmm4 +%endmacro + +%macro aesdec4 1 + movdqa xmm4,%1 + + aesdec xmm0,xmm4 + aesdec xmm1,xmm4 + aesdec xmm2,xmm4 + aesdec xmm3,xmm4 + +%endmacro + +%macro aesdeclast4 1 + movdqa xmm4,%1 + + aesdeclast xmm0,xmm4 + aesdeclast xmm1,xmm4 + aesdeclast xmm2,xmm4 + aesdeclast xmm3,xmm4 + +%endmacro + + +%macro aesenc4 1 + movdqa xmm4,%1 + + aesenc xmm0,xmm4 + aesenc xmm1,xmm4 + aesenc xmm2,xmm4 + aesenc xmm3,xmm4 + +%endmacro + +%macro aesenclast4 1 + movdqa xmm4,%1 + + aesenclast xmm0,xmm4 + aesenclast xmm1,xmm4 + aesenclast xmm2,xmm4 + aesenclast xmm3,xmm4 + +%endmacro + + +%macro xor_with_input4 1 + movdqu xmm4,[%1] + pxor xmm0,xmm4 + movdqu xmm4,[%1+16] + pxor xmm1,xmm4 + movdqu xmm4,[%1+32] + pxor xmm2,xmm4 + movdqu xmm4,[%1+48] + pxor xmm3,xmm4 +%endmacro + + + +%macro load_and_xor4 2 + movdqa xmm4,%2 + movdqu xmm0,[%1 + 0*16] + pxor xmm0,xmm4 + movdqu xmm1,[%1 + 1*16] + pxor xmm1,xmm4 + movdqu xmm2,[%1 + 2*16] + pxor xmm2,xmm4 + movdqu xmm3,[%1 + 3*16] + pxor xmm3,xmm4 +%endmacro + +%macro store4 1 + movdqu [%1 + 0*16],xmm0 + movdqu [%1 + 1*16],xmm1 + movdqu [%1 + 2*16],xmm2 + movdqu [%1 + 3*16],xmm3 +%endmacro + +%macro copy_round_keys 3 + movdqu xmm4,[%2 + ((%3)*16)] + movdqa [%1 + ((%3)*16)],xmm4 +%endmacro + + +%macro key_expansion_1_192 1 + ;; Assumes the xmm3 includes all zeros at this point. + pshufd xmm2, xmm2, 11111111b + shufps xmm3, xmm1, 00010000b + pxor xmm1, xmm3 + shufps xmm3, xmm1, 10001100b + pxor xmm1, xmm3 + pxor xmm1, xmm2 + movdqu [rdx+%1], xmm1 +%endmacro + +; Calculate w10 and w11 using calculated w9 and known w4-w5 +%macro key_expansion_2_192 1 + movdqa xmm5, xmm4 + pslldq xmm5, 4 + shufps xmm6, xmm1, 11110000b + pxor xmm6, xmm5 + pxor xmm4, xmm6 + pshufd xmm7, xmm4, 00001110b + movdqu [rdx+%1], xmm7 +%endmacro + + +section .rodata +align 16 +shuffle_mask: +DD 0FFFFFFFFh +DD 03020100h +DD 07060504h +DD 0B0A0908h + + + +section .text + +align 16 +key_expansion256: + + pshufd xmm2, xmm2, 011111111b + + movdqa xmm4, xmm1 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pxor xmm1, xmm2 + + movdqu [rdx], xmm1 + add rdx, 0x10 + + aeskeygenassist xmm4, xmm1, 0 + pshufd xmm2, xmm4, 010101010b + + movdqa xmm4, xmm3 + pshufb xmm4, xmm5 + pxor xmm3, xmm4 + pshufb xmm4, xmm5 + pxor xmm3, xmm4 + pshufb xmm4, xmm5 + pxor xmm3, xmm4 + pxor xmm3, xmm2 + + movdqu [rdx], xmm3 + add rdx, 0x10 + + ret + + + +align 16 +key_expansion128: + pshufd xmm2, xmm2, 0xFF; + movdqa xmm3, xmm1 + pshufb xmm3, xmm5 + pxor xmm1, xmm3 + pshufb xmm3, xmm5 + pxor xmm1, xmm3 + pshufb xmm3, xmm5 + pxor xmm1, xmm3 + pxor xmm1, xmm2 + + ; storing the result in the key schedule array + movdqu [rdx], xmm1 + add rdx, 0x10 + ret + + + + + + +align 16 +global iEncExpandKey128 +iEncExpandKey128: + + linux_setup + + movdqu xmm1, [rcx] ; loading the key + + movdqu [rdx], xmm1 + + movdqa xmm5, [shuffle_mask wrt rip] + + add rdx,16 + + aeskeygenassist xmm2, xmm1, 0x1 ; Generating round key 1 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x2 ; Generating round key 2 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x4 ; Generating round key 3 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x8 ; Generating round key 4 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x10 ; Generating round key 5 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x20 ; Generating round key 6 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x40 ; Generating round key 7 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x80 ; Generating round key 8 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x1b ; Generating round key 9 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x36 ; Generating round key 10 + call key_expansion128 + + ret + + + +align 16 +global iDecExpandKey128 +iDecExpandKey128: + + linux_setup + push rcx + push rdx + sub rsp,16+8 + + call iEncExpandKey128 + + add rsp,16+8 + pop rdx + pop rcx + + inversekey [rdx + 1*16] + inversekey [rdx + 2*16] + inversekey [rdx + 3*16] + inversekey [rdx + 4*16] + inversekey [rdx + 5*16] + inversekey [rdx + 6*16] + inversekey [rdx + 7*16] + inversekey [rdx + 8*16] + inversekey [rdx + 9*16] + + ret + + + +align 16 +global iDecExpandKey256 +iDecExpandKey256: + + linux_setup + push rcx + push rdx + sub rsp,16+8 + + call iEncExpandKey256 + + add rsp,16+8 + pop rdx + pop rcx + + inversekey [rdx + 1*16] + inversekey [rdx + 2*16] + inversekey [rdx + 3*16] + inversekey [rdx + 4*16] + inversekey [rdx + 5*16] + inversekey [rdx + 6*16] + inversekey [rdx + 7*16] + inversekey [rdx + 8*16] + inversekey [rdx + 9*16] + inversekey [rdx + 10*16] + inversekey [rdx + 11*16] + inversekey [rdx + 12*16] + inversekey [rdx + 13*16] + + ret + + + + +align 16 +global iEncExpandKey256 +iEncExpandKey256: + + linux_setup + + movdqu xmm1, [rcx] ; loading the key + movdqu xmm3, [rcx+16] + movdqu [rdx], xmm1 ; Storing key in memory where all key schedule will be stored + movdqu [rdx+16], xmm3 + + add rdx,32 + + movdqa xmm5, [shuffle_mask wrt rip] ; this mask is used by key_expansion + + aeskeygenassist xmm2, xmm3, 0x1 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x2 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x4 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x8 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x10 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x20 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x40 ; +; call key_expansion256 + + pshufd xmm2, xmm2, 011111111b + + movdqa xmm4, xmm1 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pxor xmm1, xmm2 + + movdqu [rdx], xmm1 + + + ret + + + +align 16 +global iDec128_CBC +iDec128_CBC: + + linux_setup + sub rsp,16*16+8 + + mov r9,rcx + mov rax,[rcx+24] + movdqu xmm5,[rax] + + mov eax,[rcx+32] ; numblocks + mov rdx,[rcx] + mov r8,[rcx+8] + mov rcx,[rcx+16] + + + sub r8,rdx + + + test eax,eax + jz end_dec128_CBC + + cmp eax,4 + jl lp128decsingle_CBC + + test rcx,0xf + jz lp128decfour_CBC + + copy_round_keys rsp,rcx,0 + copy_round_keys rsp,rcx,1 + copy_round_keys rsp,rcx,2 + copy_round_keys rsp,rcx,3 + copy_round_keys rsp,rcx,4 + copy_round_keys rsp,rcx,5 + copy_round_keys rsp,rcx,6 + copy_round_keys rsp,rcx,7 + copy_round_keys rsp,rcx,8 + copy_round_keys rsp,rcx,9 + copy_round_keys rsp,rcx,10 + mov rcx,rsp + + +align 16 +lp128decfour_CBC: + + test eax,eax + jz end_dec128_CBC + + cmp eax,4 + jl lp128decsingle_CBC + + load_and_xor4 rdx, [rcx+10*16] + add rdx,16*4 + aesdec4 [rcx+9*16] + aesdec4 [rcx+8*16] + aesdec4 [rcx+7*16] + aesdec4 [rcx+6*16] + aesdec4 [rcx+5*16] + aesdec4 [rcx+4*16] + aesdec4 [rcx+3*16] + aesdec4 [rcx+2*16] + aesdec4 [rcx+1*16] + aesdeclast4 [rcx+0*16] + + pxor xmm0,xmm5 + movdqu xmm4,[rdx - 16*4 + 0*16] + pxor xmm1,xmm4 + movdqu xmm4,[rdx - 16*4 + 1*16] + pxor xmm2,xmm4 + movdqu xmm4,[rdx - 16*4 + 2*16] + pxor xmm3,xmm4 + movdqu xmm5,[rdx - 16*4 + 3*16] + + sub eax,4 + store4 r8+rdx-(16*4) + jmp lp128decfour_CBC + + + align 16 +lp128decsingle_CBC: + + movdqu xmm0, [rdx] + movdqa xmm1,xmm0 + movdqu xmm4,[rcx+10*16] + pxor xmm0, xmm4 + aesdec1_u [rcx+9*16] + aesdec1_u [rcx+8*16] + aesdec1_u [rcx+7*16] + aesdec1_u [rcx+6*16] + aesdec1_u [rcx+5*16] + aesdec1_u [rcx+4*16] + aesdec1_u [rcx+3*16] + aesdec1_u [rcx+2*16] + aesdec1_u [rcx+1*16] + aesdeclast1_u [rcx+0*16] + + pxor xmm0,xmm5 + movdqa xmm5,xmm1 + add rdx, 16 + movdqu [r8 + rdx - 16], xmm0 + dec eax + jnz lp128decsingle_CBC + +end_dec128_CBC: + + mov r9,[r9+24] + movdqu [r9],xmm5 + add rsp,16*16+8 + ret + + + +align 16 +global iDec256_CBC +iDec256_CBC: + + linux_setup + sub rsp,16*16+8 + + mov r9,rcx + mov rax,[rcx+24] + movdqu xmm5,[rax] + + mov eax,[rcx+32] ; numblocks + mov rdx,[rcx] + mov r8,[rcx+8] + mov rcx,[rcx+16] + + + sub r8,rdx + + test eax,eax + jz end_dec256_CBC + + cmp eax,4 + jl lp256decsingle_CBC + + test rcx,0xf + jz lp256decfour_CBC + + copy_round_keys rsp,rcx,0 + copy_round_keys rsp,rcx,1 + copy_round_keys rsp,rcx,2 + copy_round_keys rsp,rcx,3 + copy_round_keys rsp,rcx,4 + copy_round_keys rsp,rcx,5 + copy_round_keys rsp,rcx,6 + copy_round_keys rsp,rcx,7 + copy_round_keys rsp,rcx,8 + copy_round_keys rsp,rcx,9 + copy_round_keys rsp,rcx,10 + copy_round_keys rsp,rcx,11 + copy_round_keys rsp,rcx,12 + copy_round_keys rsp,rcx,13 + copy_round_keys rsp,rcx,14 + mov rcx,rsp + +align 16 +lp256decfour_CBC: + + test eax,eax + jz end_dec256_CBC + + cmp eax,4 + jl lp256decsingle_CBC + + load_and_xor4 rdx, [rcx+14*16] + add rdx,16*4 + aesdec4 [rcx+13*16] + aesdec4 [rcx+12*16] + aesdec4 [rcx+11*16] + aesdec4 [rcx+10*16] + aesdec4 [rcx+9*16] + aesdec4 [rcx+8*16] + aesdec4 [rcx+7*16] + aesdec4 [rcx+6*16] + aesdec4 [rcx+5*16] + aesdec4 [rcx+4*16] + aesdec4 [rcx+3*16] + aesdec4 [rcx+2*16] + aesdec4 [rcx+1*16] + aesdeclast4 [rcx+0*16] + + pxor xmm0,xmm5 + movdqu xmm4,[rdx - 16*4 + 0*16] + pxor xmm1,xmm4 + movdqu xmm4,[rdx - 16*4 + 1*16] + pxor xmm2,xmm4 + movdqu xmm4,[rdx - 16*4 + 2*16] + pxor xmm3,xmm4 + movdqu xmm5,[rdx - 16*4 + 3*16] + + sub eax,4 + store4 r8+rdx-(16*4) + jmp lp256decfour_CBC + + + align 16 +lp256decsingle_CBC: + + movdqu xmm0, [rdx] + movdqu xmm4,[rcx+14*16] + movdqa xmm1,xmm0 + pxor xmm0, xmm4 + aesdec1_u [rcx+13*16] + aesdec1_u [rcx+12*16] + aesdec1_u [rcx+11*16] + aesdec1_u [rcx+10*16] + aesdec1_u [rcx+9*16] + aesdec1_u [rcx+8*16] + aesdec1_u [rcx+7*16] + aesdec1_u [rcx+6*16] + aesdec1_u [rcx+5*16] + aesdec1_u [rcx+4*16] + aesdec1_u [rcx+3*16] + aesdec1_u [rcx+2*16] + aesdec1_u [rcx+1*16] + aesdeclast1_u [rcx+0*16] + + pxor xmm0,xmm5 + movdqa xmm5,xmm1 + add rdx, 16 + movdqu [r8 + rdx - 16], xmm0 + dec eax + jnz lp256decsingle_CBC + +end_dec256_CBC: + + mov r9,[r9+24] + movdqu [r9],xmm5 + add rsp,16*16+8 + ret + + + +align 16 +global iEnc128_CBC +iEnc128_CBC: + + linux_setup + sub rsp,16*16+8 + + mov r9,rcx + mov rax,[rcx+24] + movdqu xmm1,[rax] + + mov eax,[rcx+32] ; numblocks + mov rdx,[rcx] + mov r8,[rcx+8] + mov rcx,[rcx+16] + + sub r8,rdx + + + test rcx,0xf + jz lp128encsingle_CBC + + copy_round_keys rsp,rcx,0 + copy_round_keys rsp,rcx,1 + copy_round_keys rsp,rcx,2 + copy_round_keys rsp,rcx,3 + copy_round_keys rsp,rcx,4 + copy_round_keys rsp,rcx,5 + copy_round_keys rsp,rcx,6 + copy_round_keys rsp,rcx,7 + copy_round_keys rsp,rcx,8 + copy_round_keys rsp,rcx,9 + copy_round_keys rsp,rcx,10 + mov rcx,rsp + + + align 16 + +lp128encsingle_CBC: + + movdqu xmm0, [rdx] + movdqu xmm4,[rcx+0*16] + add rdx, 16 + pxor xmm0, xmm1 + pxor xmm0, xmm4 + aesenc1 [rcx+1*16] + aesenc1 [rcx+2*16] + aesenc1 [rcx+3*16] + aesenc1 [rcx+4*16] + aesenc1 [rcx+5*16] + aesenc1 [rcx+6*16] + aesenc1 [rcx+7*16] + aesenc1 [rcx+8*16] + aesenc1 [rcx+9*16] + aesenclast1 [rcx+10*16] + movdqa xmm1,xmm0 + + ; Store output encrypted data into CIPHERTEXT array + movdqu [r8+rdx-16], xmm0 + dec eax + jnz lp128encsingle_CBC + + mov r9,[r9+24] + movdqu [r9],xmm1 + add rsp,16*16+8 + ret + + + +align 16 +global iEnc256_CBC +iEnc256_CBC: + + linux_setup + sub rsp,16*16+8 + + mov r9,rcx + mov rax,[rcx+24] + movdqu xmm1,[rax] + + mov eax,[rcx+32] ; numblocks + mov rdx,[rcx] + mov r8,[rcx+8] + mov rcx,[rcx+16] + + sub r8,rdx + + test rcx,0xf + jz lp256encsingle_CBC + + copy_round_keys rsp,rcx,0 + copy_round_keys rsp,rcx,1 + copy_round_keys rsp,rcx,2 + copy_round_keys rsp,rcx,3 + copy_round_keys rsp,rcx,4 + copy_round_keys rsp,rcx,5 + copy_round_keys rsp,rcx,6 + copy_round_keys rsp,rcx,7 + copy_round_keys rsp,rcx,8 + copy_round_keys rsp,rcx,9 + copy_round_keys rsp,rcx,10 + copy_round_keys rsp,rcx,11 + copy_round_keys rsp,rcx,12 + copy_round_keys rsp,rcx,13 + copy_round_keys rsp,rcx,14 + mov rcx,rsp + + align 16 + +lp256encsingle_CBC: + + movdqu xmm0, [rdx] + movdqu xmm4, [rcx+0*16] + add rdx, 16 + pxor xmm0, xmm1 + pxor xmm0, xmm4 + aesenc1 [rcx+1*16] + aesenc1 [rcx+2*16] + aesenc1 [rcx+3*16] + aesenc1 [rcx+4*16] + aesenc1 [rcx+5*16] + aesenc1 [rcx+6*16] + aesenc1 [rcx+7*16] + aesenc1 [rcx+8*16] + aesenc1 [rcx+9*16] + aesenc1 [rcx+10*16] + aesenc1 [rcx+11*16] + aesenc1 [rcx+12*16] + aesenc1 [rcx+13*16] + aesenclast1 [rcx+14*16] + movdqa xmm1,xmm0 + + ; Store output encrypted data into CIPHERTEXT array + movdqu [r8+rdx-16], xmm0 + dec eax + jnz lp256encsingle_CBC + + mov r9,[r9+24] + movdqu [r9],xmm1 + add rsp,16*16+8 + ret + +; Mark this file as not needing an executable stack. +%ifidn __OUTPUT_FORMAT__,elf +section .note.GNU-stack noalloc noexec nowrite progbits +%endif +%ifidn __OUTPUT_FORMAT__,elf32 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif +%ifidn __OUTPUT_FORMAT__,elf64 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/iaesx86.s b/krb5-1.21.3/src/lib/crypto/builtin/aes/iaesx86.s new file mode 100644 index 00000000..945942c0 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/iaesx86.s @@ -0,0 +1,842 @@ +[bits 32] +[CPU intelnop] + +; Copyright (c) 2010, Intel Corporation +; 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 Intel Corporation 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 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. + +%define _iEncExpandKey128 k5_iEncExpandKey128 +%define _iEncExpandKey256 k5_iEncExpandKey256 +%define _iDecExpandKey128 k5_iDecExpandKey128 +%define _iDecExpandKey256 k5_iDecExpandKey256 +%define _iEnc128_CBC k5_iEnc128_CBC +%define _iEnc256_CBC k5_iEnc256_CBC +%define _iDec128_CBC k5_iDec128_CBC +%define _iDec256_CBC k5_iDec256_CBC + +%macro inversekey 1 + movdqu xmm1,%1 + aesimc xmm0,xmm1 + movdqu %1,xmm0 +%endmacro + + +%macro aesdec4 1 + movdqa xmm4,%1 + + aesdec xmm0,xmm4 + aesdec xmm1,xmm4 + aesdec xmm2,xmm4 + aesdec xmm3,xmm4 + +%endmacro + + +%macro aesdeclast4 1 + movdqa xmm4,%1 + + aesdeclast xmm0,xmm4 + aesdeclast xmm1,xmm4 + aesdeclast xmm2,xmm4 + aesdeclast xmm3,xmm4 + +%endmacro + + +%macro aesenc4 1 + movdqa xmm4,%1 + + aesenc xmm0,xmm4 + aesenc xmm1,xmm4 + aesenc xmm2,xmm4 + aesenc xmm3,xmm4 + +%endmacro + +%macro aesenclast4 1 + movdqa xmm4,%1 + + aesenclast xmm0,xmm4 + aesenclast xmm1,xmm4 + aesenclast xmm2,xmm4 + aesenclast xmm3,xmm4 + +%endmacro + + +%macro aesdeclast1 1 + aesdeclast xmm0,%1 +%endmacro + +%macro aesenclast1 1 + aesenclast xmm0,%1 +%endmacro + +%macro aesdec1 1 + aesdec xmm0,%1 +%endmacro + +;abab +%macro aesenc1 1 + aesenc xmm0,%1 +%endmacro + + +%macro aesdeclast1_u 1 + movdqu xmm4,%1 + aesdeclast xmm0,xmm4 +%endmacro + +%macro aesenclast1_u 1 + movdqu xmm4,%1 + aesenclast xmm0,xmm4 +%endmacro + +%macro aesdec1_u 1 + movdqu xmm4,%1 + aesdec xmm0,xmm4 +%endmacro + +%macro aesenc1_u 1 + movdqu xmm4,%1 + aesenc xmm0,xmm4 +%endmacro + + +%macro load_and_xor4 2 + movdqa xmm4,%2 + movdqu xmm0,[%1 + 0*16] + pxor xmm0,xmm4 + movdqu xmm1,[%1 + 1*16] + pxor xmm1,xmm4 + movdqu xmm2,[%1 + 2*16] + pxor xmm2,xmm4 + movdqu xmm3,[%1 + 3*16] + pxor xmm3,xmm4 +%endmacro + + +%macro xor_with_input4 1 + movdqu xmm4,[%1] + pxor xmm0,xmm4 + movdqu xmm4,[%1+16] + pxor xmm1,xmm4 + movdqu xmm4,[%1+32] + pxor xmm2,xmm4 + movdqu xmm4,[%1+48] + pxor xmm3,xmm4 +%endmacro + +%macro store4 1 + movdqu [%1 + 0*16],xmm0 + movdqu [%1 + 1*16],xmm1 + movdqu [%1 + 2*16],xmm2 + movdqu [%1 + 3*16],xmm3 +%endmacro + + +%macro copy_round_keys 3 + movdqu xmm4,[%2 + ((%3)*16)] + movdqa [%1 + ((%3)*16)],xmm4 +%endmacro + +;abab +%macro copy_round_keyx 3 + movdqu xmm4,[%2 + ((%3)*16)] + movdqa %1,xmm4 +%endmacro + + + +%macro key_expansion_1_192 1 + ;; Assumes the xmm3 includes all zeros at this point. + pshufd xmm2, xmm2, 11111111b + shufps xmm3, xmm1, 00010000b + pxor xmm1, xmm3 + shufps xmm3, xmm1, 10001100b + pxor xmm1, xmm3 + pxor xmm1, xmm2 + movdqu [edx+%1], xmm1 +%endmacro + +; Calculate w10 and w11 using calculated w9 and known w4-w5 +%macro key_expansion_2_192 1 + movdqa xmm5, xmm4 + pslldq xmm5, 4 + shufps xmm6, xmm1, 11110000b + pxor xmm6, xmm5 + pxor xmm4, xmm6 + pshufd xmm7, xmm4, 00001110b + movdqu [edx+%1], xmm7 +%endmacro + + + + + +section .rodata +align 16 +shuffle_mask: +DD 0FFFFFFFFh +DD 03020100h +DD 07060504h +DD 0B0A0908h + + +section .text + + + +align 16 +key_expansion256: + + pshufd xmm2, xmm2, 011111111b + + movdqu xmm4, xmm1 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pxor xmm1, xmm2 + + movdqu [edx], xmm1 + add edx, 0x10 + + aeskeygenassist xmm4, xmm1, 0 + pshufd xmm2, xmm4, 010101010b + + movdqu xmm4, xmm3 + pshufb xmm4, xmm5 + pxor xmm3, xmm4 + pshufb xmm4, xmm5 + pxor xmm3, xmm4 + pshufb xmm4, xmm5 + pxor xmm3, xmm4 + pxor xmm3, xmm2 + + movdqu [edx], xmm3 + add edx, 0x10 + + ret + + + +align 16 +key_expansion128: + pshufd xmm2, xmm2, 0xFF; + movdqu xmm3, xmm1 + pshufb xmm3, xmm5 + pxor xmm1, xmm3 + pshufb xmm3, xmm5 + pxor xmm1, xmm3 + pshufb xmm3, xmm5 + pxor xmm1, xmm3 + pxor xmm1, xmm2 + + ; storing the result in the key schedule array + movdqu [edx], xmm1 + add edx, 0x10 + ret + + + +align 16 +global _iEncExpandKey128 +_iEncExpandKey128: + + mov ecx,[esp-4+8] ;input + mov edx,[esp-4+12] ;ctx + + movdqu xmm1, [ecx] ; loading the key + + movdqu [edx], xmm1 + + call .next +.next: + pop ecx + movdqa xmm5, [ecx-.next+shuffle_mask] + + add edx,16 + + aeskeygenassist xmm2, xmm1, 0x1 ; Generating round key 1 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x2 ; Generating round key 2 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x4 ; Generating round key 3 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x8 ; Generating round key 4 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x10 ; Generating round key 5 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x20 ; Generating round key 6 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x40 ; Generating round key 7 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x80 ; Generating round key 8 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x1b ; Generating round key 9 + call key_expansion128 + aeskeygenassist xmm2, xmm1, 0x36 ; Generating round key 10 + call key_expansion128 + + ret + + + +align 16 +global _iDecExpandKey128 +_iDecExpandKey128: + push DWORD [esp+8] + push DWORD [esp+8] + + call _iEncExpandKey128 + add esp,8 + + mov edx,[esp-4+12] ;ctx + + inversekey [edx + 1*16] + inversekey [edx + 2*16] + inversekey [edx + 3*16] + inversekey [edx + 4*16] + inversekey [edx + 5*16] + inversekey [edx + 6*16] + inversekey [edx + 7*16] + inversekey [edx + 8*16] + inversekey [edx + 9*16] + + ret + + + +align 16 +global _iDecExpandKey256 +_iDecExpandKey256: + push DWORD [esp+8] + push DWORD [esp+8] + + call _iEncExpandKey256 + add esp, 8 + + mov edx, [esp-4+12] ;expanded key + + inversekey [edx + 1*16] + inversekey [edx + 2*16] + inversekey [edx + 3*16] + inversekey [edx + 4*16] + inversekey [edx + 5*16] + inversekey [edx + 6*16] + inversekey [edx + 7*16] + inversekey [edx + 8*16] + inversekey [edx + 9*16] + inversekey [edx + 10*16] + inversekey [edx + 11*16] + inversekey [edx + 12*16] + inversekey [edx + 13*16] + + ret + + + + +align 16 +global _iEncExpandKey256 +_iEncExpandKey256: + mov ecx, [esp-4+8] ;input + mov edx, [esp-4+12] ;expanded key + + + movdqu xmm1, [ecx] ; loading the key + movdqu xmm3, [ecx+16] + movdqu [edx], xmm1 ; Storing key in memory where all key schedule will be stored + movdqu [edx+16], xmm3 + + add edx,32 + + call .next +.next: + pop ecx + movdqa xmm5, [ecx-.next+shuffle_mask] ; this mask is used by key_expansion + + aeskeygenassist xmm2, xmm3, 0x1 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x2 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x4 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x8 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x10 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x20 ; + call key_expansion256 + aeskeygenassist xmm2, xmm3, 0x40 ; +; call key_expansion256 + + pshufd xmm2, xmm2, 011111111b + + movdqu xmm4, xmm1 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pshufb xmm4, xmm5 + pxor xmm1, xmm4 + pxor xmm1, xmm2 + + movdqu [edx], xmm1 + + + ret + + + +align 16 +global _iDec128_CBC +_iDec128_CBC: + mov ecx,[esp-4+8] + + push esi + push edi + push ebp + mov ebp,esp + sub esp,16*16 + and esp,0xfffffff0 + + mov eax,[ecx+12] + movdqu xmm5,[eax] ;iv + + mov eax,[ecx+16] ; numblocks + mov esi,[ecx] + mov edi,[ecx+4] + mov ecx,[ecx+8] + + sub edi,esi + + test eax,eax + jz end_dec128_CBC + + cmp eax,4 + jl lp128decsingle_CBC + + test ecx,0xf + jz lp128decfour_CBC + + copy_round_keys esp,ecx,0 + copy_round_keys esp,ecx,1 + copy_round_keys esp,ecx,2 + copy_round_keys esp,ecx,3 + copy_round_keys esp,ecx,4 + copy_round_keys esp,ecx,5 + copy_round_keys esp,ecx,6 + copy_round_keys esp,ecx,7 + copy_round_keys esp,ecx,8 + copy_round_keys esp,ecx,9 + copy_round_keys esp,ecx,10 + mov ecx,esp + + +align 16 +lp128decfour_CBC: + + test eax,eax + jz end_dec128_CBC + + cmp eax,4 + jl lp128decsingle_CBC + + load_and_xor4 esi, [ecx+10*16] + add esi,16*4 + aesdec4 [ecx+9*16] + aesdec4 [ecx+8*16] + aesdec4 [ecx+7*16] + aesdec4 [ecx+6*16] + aesdec4 [ecx+5*16] + aesdec4 [ecx+4*16] + aesdec4 [ecx+3*16] + aesdec4 [ecx+2*16] + aesdec4 [ecx+1*16] + aesdeclast4 [ecx+0*16] + + pxor xmm0,xmm5 + movdqu xmm4,[esi- 16*4 + 0*16] + pxor xmm1,xmm4 + movdqu xmm4,[esi- 16*4 + 1*16] + pxor xmm2,xmm4 + movdqu xmm4,[esi- 16*4 + 2*16] + pxor xmm3,xmm4 + movdqu xmm5,[esi- 16*4 + 3*16] + + sub eax,4 + store4 esi+edi-(16*4) + jmp lp128decfour_CBC + + + align 16 +lp128decsingle_CBC: + + movdqu xmm0, [esi] + movdqa xmm1,xmm0 + movdqu xmm4,[ecx+10*16] + pxor xmm0, xmm4 + aesdec1_u [ecx+9*16] + aesdec1_u [ecx+8*16] + aesdec1_u [ecx+7*16] + aesdec1_u [ecx+6*16] + aesdec1_u [ecx+5*16] + aesdec1_u [ecx+4*16] + aesdec1_u [ecx+3*16] + aesdec1_u [ecx+2*16] + aesdec1_u [ecx+1*16] + aesdeclast1_u [ecx+0*16] + + pxor xmm0,xmm5 + movdqa xmm5,xmm1 + + add esi, 16 + movdqu [edi+esi - 16], xmm0 + dec eax + jnz lp128decsingle_CBC + +end_dec128_CBC: + + mov esp,ebp + pop ebp + pop edi + pop esi + + mov ecx,[esp-4+8] ; first arg + mov ecx,[ecx+12] + movdqu [ecx],xmm5 ; store last iv for chaining + + ret + + + +align 16 +global _iDec256_CBC +_iDec256_CBC: + mov ecx,[esp-4+8] + + push esi + push edi + push ebp + mov ebp,esp + + sub esp,16*16 + and esp,0xfffffff0 + + mov eax,[ecx+12] + movdqu xmm5,[eax] ;iv + + mov eax,[ecx+16] ; numblocks + mov esi,[ecx] + mov edi,[ecx+4] + mov ecx,[ecx+8] + + sub edi,esi + + test eax,eax + jz end_dec256_CBC + + cmp eax,4 + jl lp256decsingle_CBC + + test ecx,0xf + jz lp256decfour_CBC + + copy_round_keys esp,ecx,0 + copy_round_keys esp,ecx,1 + copy_round_keys esp,ecx,2 + copy_round_keys esp,ecx,3 + copy_round_keys esp,ecx,4 + copy_round_keys esp,ecx,5 + copy_round_keys esp,ecx,6 + copy_round_keys esp,ecx,7 + copy_round_keys esp,ecx,8 + copy_round_keys esp,ecx,9 + copy_round_keys esp,ecx,10 + copy_round_keys esp,ecx,11 + copy_round_keys esp,ecx,12 + copy_round_keys esp,ecx,13 + copy_round_keys esp,ecx,14 + mov ecx,esp + +align 16 +lp256decfour_CBC: + + test eax,eax + jz end_dec256_CBC + + cmp eax,4 + jl lp256decsingle_CBC + + load_and_xor4 esi, [ecx+14*16] + add esi,16*4 + aesdec4 [ecx+13*16] + aesdec4 [ecx+12*16] + aesdec4 [ecx+11*16] + aesdec4 [ecx+10*16] + aesdec4 [ecx+9*16] + aesdec4 [ecx+8*16] + aesdec4 [ecx+7*16] + aesdec4 [ecx+6*16] + aesdec4 [ecx+5*16] + aesdec4 [ecx+4*16] + aesdec4 [ecx+3*16] + aesdec4 [ecx+2*16] + aesdec4 [ecx+1*16] + aesdeclast4 [ecx+0*16] + + pxor xmm0,xmm5 + movdqu xmm4,[esi- 16*4 + 0*16] + pxor xmm1,xmm4 + movdqu xmm4,[esi- 16*4 + 1*16] + pxor xmm2,xmm4 + movdqu xmm4,[esi- 16*4 + 2*16] + pxor xmm3,xmm4 + movdqu xmm5,[esi- 16*4 + 3*16] + + sub eax,4 + store4 esi+edi-(16*4) + jmp lp256decfour_CBC + + + align 16 +lp256decsingle_CBC: + + movdqu xmm0, [esi] + movdqa xmm1,xmm0 + movdqu xmm4, [ecx+14*16] + pxor xmm0, xmm4 + aesdec1_u [ecx+13*16] + aesdec1_u [ecx+12*16] + aesdec1_u [ecx+11*16] + aesdec1_u [ecx+10*16] + aesdec1_u [ecx+9*16] + aesdec1_u [ecx+8*16] + aesdec1_u [ecx+7*16] + aesdec1_u [ecx+6*16] + aesdec1_u [ecx+5*16] + aesdec1_u [ecx+4*16] + aesdec1_u [ecx+3*16] + aesdec1_u [ecx+2*16] + aesdec1_u [ecx+1*16] + aesdeclast1_u [ecx+0*16] + + pxor xmm0,xmm5 + movdqa xmm5,xmm1 + + add esi, 16 + movdqu [edi+esi - 16], xmm0 + dec eax + jnz lp256decsingle_CBC + +end_dec256_CBC: + + + mov esp,ebp + pop ebp + pop edi + pop esi + + mov ecx,[esp-4+8] ; first arg + mov ecx,[ecx+12] + movdqu [ecx],xmm5 ; store last iv for chaining + + ret + + + +align 16 +global _iEnc128_CBC +_iEnc128_CBC: + mov ecx,[esp-4+8] + + push esi + push edi + push ebp + mov ebp,esp + + sub esp,16*16 + and esp,0xfffffff0 + + mov eax,[ecx+12] + movdqu xmm1,[eax] ;iv + + mov eax,[ecx+16] ; numblocks + mov esi,[ecx] + mov edi,[ecx+4] + mov ecx,[ecx+8] + sub edi,esi + + test ecx,0xf + jz lp128encsingle_CBC + + copy_round_keys esp,ecx,0 + copy_round_keys esp,ecx,1 + copy_round_keys esp,ecx,2 + copy_round_keys esp,ecx,3 + copy_round_keys esp,ecx,4 + copy_round_keys esp,ecx,5 + copy_round_keys esp,ecx,6 + copy_round_keys esp,ecx,7 + copy_round_keys esp,ecx,8 + copy_round_keys esp,ecx,9 + copy_round_keys esp,ecx,10 + mov ecx,esp + + align 16 + +lp128encsingle_CBC: + + movdqu xmm0, [esi] + add esi, 16 + pxor xmm0, xmm1 + movdqu xmm4,[ecx+0*16] + pxor xmm0, xmm4 + aesenc1 [ecx+1*16] + aesenc1 [ecx+2*16] + aesenc1 [ecx+3*16] + aesenc1 [ecx+4*16] + aesenc1 [ecx+5*16] + aesenc1 [ecx+6*16] + aesenc1 [ecx+7*16] + aesenc1 [ecx+8*16] + aesenc1 [ecx+9*16] + aesenclast1 [ecx+10*16] + ; Store output encrypted data into CIPHERTEXT array + movdqu [esi+edi-16], xmm0 + movdqa xmm1,xmm0 + dec eax + jnz lp128encsingle_CBC + + + mov esp,ebp + pop ebp + pop edi + pop esi + mov ecx,[esp-4+8] ; first arg + mov ecx,[ecx+12] + movdqu [ecx],xmm1 ; store last iv for chaining + + ret + + + +align 16 +global _iEnc256_CBC +_iEnc256_CBC: + mov ecx,[esp-4+8] ; first arg + + push esi + push edi + push ebp + mov ebp,esp + + sub esp,16*16 + and esp,0xfffffff0 + + mov eax,[ecx+12] + movdqu xmm1,[eax] ;iv + + mov eax,[ecx+16] ; numblocks + mov esi,[ecx] + mov edi,[ecx+4] + mov ecx,[ecx+8] + sub edi,esi + + test ecx,0xf + jz lp256encsingle_CBC + + copy_round_keys esp,ecx,0 + copy_round_keys esp,ecx,1 + copy_round_keys esp,ecx,2 + copy_round_keys esp,ecx,3 + copy_round_keys esp,ecx,4 + copy_round_keys esp,ecx,5 + copy_round_keys esp,ecx,6 + copy_round_keys esp,ecx,7 + copy_round_keys esp,ecx,8 + copy_round_keys esp,ecx,9 + copy_round_keys esp,ecx,10 + copy_round_keys esp,ecx,11 + copy_round_keys esp,ecx,12 + copy_round_keys esp,ecx,13 + copy_round_keys esp,ecx,14 + mov ecx,esp + + align 16 + +lp256encsingle_CBC: + +;abab + movdqu xmm0, [esi] + add esi, 16 + pxor xmm0, xmm1 + movdqu xmm4,[ecx+0*16] + pxor xmm0, xmm4 + aesenc1 [ecx+1*16] + aesenc1 [ecx+2*16] + aesenc1 [ecx+3*16] + aesenc1 [ecx+4*16] + aesenc1 [ecx+5*16] + aesenc1 [ecx+6*16] + aesenc1 [ecx+7*16] + aesenc1 [ecx+8*16] + aesenc1 [ecx+9*16] + aesenc1 [ecx+10*16] + aesenc1 [ecx+11*16] + aesenc1 [ecx+12*16] + aesenc1 [ecx+13*16] + aesenclast1 [ecx+14*16] + ; Store output encrypted data into CIPHERTEXT array + movdqu [esi+edi-16], xmm0 + movdqa xmm1,xmm0 + dec eax + jnz lp256encsingle_CBC + + + mov esp,ebp + pop ebp + pop edi + pop esi + mov ecx,[esp-4+8] + mov ecx,[ecx+12] + movdqu [ecx],xmm1 ; store last iv for chaining + + ret + +; Mark this file as not needing an executable stack. +%ifidn __OUTPUT_FORMAT__,elf +section .note.GNU-stack noalloc noexec nowrite progbits +%endif +%ifidn __OUTPUT_FORMAT__,elf32 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif +%ifidn __OUTPUT_FORMAT__,elf64 +section .note.GNU-stack noalloc noexec nowrite progbits +%endif diff --git a/krb5-1.21.3/src/lib/crypto/builtin/aes/kresults.expected b/krb5-1.21.3/src/lib/crypto/builtin/aes/kresults.expected new file mode 100644 index 00000000..443d5c4d --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/aes/kresults.expected @@ -0,0 +1,223 @@ +FIPS test: +key: + 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +input: + 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF +output: + 69 C4 E0 D8 6A 7B 04 30 D8 CD B7 80 70 B4 C5 5A +ok. + +ECB tests: +key: + 46 64 31 29 64 86 ED 9C D7 1F C2 07 25 48 20 A2 +test 0 - 32 bytes +input: + C4 A8 5A EB 0B 20 41 49 4F 8B F1 F8 CD 30 F1 13 + 94 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +output: + 1B 39 DA 37 40 D3 DF FE AC 89 D6 BB 4C 29 F1 0A + E1 43 64 CB 16 D3 FF CF E8 FA 6A 2C EC A2 69 34 + +test 1 - 32 bytes +input: + 22 3C F8 A8 29 95 80 49 57 87 6E 9F A7 11 63 50 + 6B 4E 5B 8C 8F A4 DB 1B 95 D3 E8 C5 C5 FB 5A 00 +output: + F3 B2 BB 53 D6 F4 A3 AE 9E EB B1 3D B2 F7 E9 90 + 83 FE B6 7B 73 4F CE DB 8E 97 D4 06 96 11 B7 23 + +test 2 - 32 bytes +input: + E7 37 52 90 60 E7 10 A9 3E 97 18 DD 3E 29 41 8E + 94 8F E9 20 1F 8D FB 3A 22 CF 22 E8 94 1D 42 7B +output: + 25 4F 90 96 01 9B 09 27 5E FF 95 69 E0 70 DC 50 + A3 D1 6F E1 EF 7B 6D 2F 4F 93 48 90 02 0D F1 8A + +test 3 - 48 bytes +input: + 54 94 0B B4 7C 1B 5E BA B2 76 98 F1 9F D9 7F 33 + 68 69 54 87 F6 4F C1 19 1E E3 01 B2 00 43 2E 54 + D7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +output: + D3 7F 6D 39 57 32 A6 C5 A4 49 F4 4B C6 EE 0A E0 + 86 D8 A3 C0 E5 6D BB 39 5F C0 CC 0A DA 8F 87 C6 + 14 C1 8E 34 7A A8 2F BB EA 53 F0 7A 64 53 5B 28 + +test 4 - 48 bytes +input: + 39 09 53 55 67 0E 07 DD A6 F8 7C 7F 78 AF E7 E1 + 03 6F D7 53 30 F0 71 14 F1 24 14 34 52 69 0C 8B + 72 5F E0 D9 6D E8 B6 13 E0 32 92 58 E1 7A 39 00 +output: + AD 96 1C 40 05 54 CB 0E 37 32 AE 2C 64 DB EF 8E + B5 76 2B EE F3 A1 04 A1 E0 3F FE CA 17 7B 4C 91 + 53 2F B3 16 33 48 27 D6 49 62 E8 77 10 DC 46 E6 + +test 5 - 48 bytes +input: + E5 E9 11 38 19 01 A9 2D F3 CD 42 27 1F AB 33 AB + 1D 93 8B F6 00 73 AC 14 54 DE A6 AC BF 20 E6 A4 + 09 F7 DC 23 F8 86 50 EB 53 92 13 73 3D 46 1E 5A +output: + 1A 03 F3 10 7A F0 62 07 D1 22 60 2B 9E 07 D0 8D + FE 7A E7 E7 DF 7F 12 C6 5E 29 F9 A2 55 C0 93 F1 + FF AC 97 44 E1 C0 C7 39 F8 7A 4B F8 ED 01 58 6B + +test 6 - 64 bytes +input: + D9 A9 50 DA 1D FC EE 71 DA 94 1D 9A B5 03 3E BE + FA 1B E1 F3 A1 32 DE F4 C4 F1 67 02 38 85 5C 11 + 2F AD EB 4C A9 D9 BD 84 6E DA 1E 23 DE 5C E1 D8 + 77 C3 CB 18 F5 AA 0D B9 9B 74 BB D3 FA 18 E5 29 +output: + D0 18 22 59 85 05 AB 87 0D 9D D0 99 7B 15 CC 43 + 4D C5 13 1B B5 3E 8F 4E B4 75 FC A5 E5 47 94 7F + 14 68 15 F7 6D F1 9E 12 B8 81 39 06 3C 3D F5 44 + 83 BE 19 E3 3E 68 15 A0 50 93 03 73 0C 99 52 C3 + +CBC tests: +initial vector: + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +test 0 - 32 bytes +input: + C4 A8 5A EB 0B 20 41 49 4F 8B F1 F8 CD 30 F1 13 + 94 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +output: + 1B 39 DA 37 40 D3 DF FE AC 89 D6 BB 4C 29 F1 0A + D4 3C 74 F5 5B 8B 3E CF 67 F8 F7 00 03 27 8A 91 + +test 1 - 32 bytes +input: + 22 3C F8 A8 29 95 80 49 57 87 6E 9F A7 11 63 50 + 6B 4E 5B 8C 8F A4 DB 1B 95 D3 E8 C5 C5 FB 5A 00 +output: + F3 B2 BB 53 D6 F4 A3 AE 9E EB B1 3D B2 F7 E9 90 + 54 03 C8 DF 5F 11 82 94 93 4E B3 4B F9 B5 39 D1 + +test 2 - 32 bytes +input: + E7 37 52 90 60 E7 10 A9 3E 97 18 DD 3E 29 41 8E + 94 8F E9 20 1F 8D FB 3A 22 CF 22 E8 94 1D 42 7B +output: + 25 4F 90 96 01 9B 09 27 5E FF 95 69 E0 70 DC 50 + D7 7C 5F B0 DA F7 80 2E 3F 3A 2E B7 5D F0 B3 23 + +test 3 - 48 bytes +input: + 54 94 0B B4 7C 1B 5E BA B2 76 98 F1 9F D9 7F 33 + 68 69 54 87 F6 4F C1 19 1E E3 01 B2 00 43 2E 54 + D7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +output: + D3 7F 6D 39 57 32 A6 C5 A4 49 F4 4B C6 EE 0A E0 + 88 D0 90 16 44 A7 38 01 63 5D BE 56 9E C3 78 7A + 51 6F 31 69 BF 9C 75 AD A1 C6 66 A6 1B A2 38 0D + +test 4 - 48 bytes +input: + 39 09 53 55 67 0E 07 DD A6 F8 7C 7F 78 AF E7 E1 + 03 6F D7 53 30 F0 71 14 F1 24 14 34 52 69 0C 8B + 72 5F E0 D9 6D E8 B6 13 E0 32 92 58 E1 7A 39 00 +output: + AD 96 1C 40 05 54 CB 0E 37 32 AE 2C 64 DB EF 8E + F0 68 8B 66 32 FE 41 EF 11 51 1B 6E F0 C0 17 96 + A1 BD F6 34 5D F3 BC 03 86 72 D0 C3 13 FE C3 95 + +test 5 - 48 bytes +input: + E5 E9 11 38 19 01 A9 2D F3 CD 42 27 1F AB 33 AB + 1D 93 8B F6 00 73 AC 14 54 DE A6 AC BF 20 E6 A4 + 09 F7 DC 23 F8 86 50 EB 53 92 13 73 3D 46 1E 5A +output: + 1A 03 F3 10 7A F0 62 07 D1 22 60 2B 9E 07 D0 8D + 22 F4 2B 92 92 D4 D5 E7 EA 90 72 9F 03 31 10 1F + 65 DE 01 93 8B 51 17 F8 32 6F 4B 05 AF 02 E2 3D + +test 6 - 64 bytes +input: + D9 A9 50 DA 1D FC EE 71 DA 94 1D 9A B5 03 3E BE + FA 1B E1 F3 A1 32 DE F4 C4 F1 67 02 38 85 5C 11 + 2F AD EB 4C A9 D9 BD 84 6E DA 1E 23 DE 5C E1 D8 + 77 C3 CB 18 F5 AA 0D B9 9B 74 BB D3 FA 18 E5 29 +output: + D0 18 22 59 85 05 AB 87 0D 9D D0 99 7B 15 CC 43 + F7 43 1B BF 3C 7D A0 21 1E 3D 3F 6A 4D 8A CE 08 + 37 9D EB CD 52 52 3B C5 76 02 7D 35 19 76 05 7D + 76 22 5A 42 DF 73 CB 5D CE 88 C3 4C CE 92 00 E6 + +CTS tests: +initial vector: + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +test 0 - 17 bytes +input: + C4 A8 5A EB 0B 20 41 49 4F 8B F1 F8 CD 30 F1 13 + 94 +(did CBC mode for 0) +output: + D4 3C 74 F5 5B 8B 3E CF 67 F8 F7 00 03 27 8A 91 + 1B + +test 1 - 31 bytes +input: + 22 3C F8 A8 29 95 80 49 57 87 6E 9F A7 11 63 50 + 6B 4E 5B 8C 8F A4 DB 1B 95 D3 E8 C5 C5 FB 5A +(did CBC mode for 0) +output: + 54 03 C8 DF 5F 11 82 94 93 4E B3 4B F9 B5 39 D1 + F3 B2 BB 53 D6 F4 A3 AE 9E EB B1 3D B2 F7 E9 + +test 2 - 32 bytes +input: + E7 37 52 90 60 E7 10 A9 3E 97 18 DD 3E 29 41 8E + 94 8F E9 20 1F 8D FB 3A 22 CF 22 E8 94 1D 42 7B +(did CBC mode for 0) +output: + D7 7C 5F B0 DA F7 80 2E 3F 3A 2E B7 5D F0 B3 23 + 25 4F 90 96 01 9B 09 27 5E FF 95 69 E0 70 DC 50 + +test 3 - 33 bytes +input: + 54 94 0B B4 7C 1B 5E BA B2 76 98 F1 9F D9 7F 33 + 68 69 54 87 F6 4F C1 19 1E E3 01 B2 00 43 2E 54 + D7 +(did CBC mode for 16) +output: + D3 7F 6D 39 57 32 A6 C5 A4 49 F4 4B C6 EE 0A E0 + 51 6F 31 69 BF 9C 75 AD A1 C6 66 A6 1B A2 38 0D + 88 + +test 4 - 47 bytes +input: + 39 09 53 55 67 0E 07 DD A6 F8 7C 7F 78 AF E7 E1 + 03 6F D7 53 30 F0 71 14 F1 24 14 34 52 69 0C 8B + 72 5F E0 D9 6D E8 B6 13 E0 32 92 58 E1 7A 39 +(did CBC mode for 16) +output: + AD 96 1C 40 05 54 CB 0E 37 32 AE 2C 64 DB EF 8E + A1 BD F6 34 5D F3 BC 03 86 72 D0 C3 13 FE C3 95 + F0 68 8B 66 32 FE 41 EF 11 51 1B 6E F0 C0 17 + +test 5 - 48 bytes +input: + E5 E9 11 38 19 01 A9 2D F3 CD 42 27 1F AB 33 AB + 1D 93 8B F6 00 73 AC 14 54 DE A6 AC BF 20 E6 A4 + 09 F7 DC 23 F8 86 50 EB 53 92 13 73 3D 46 1E 5A +(did CBC mode for 16) +output: + 1A 03 F3 10 7A F0 62 07 D1 22 60 2B 9E 07 D0 8D + 65 DE 01 93 8B 51 17 F8 32 6F 4B 05 AF 02 E2 3D + 22 F4 2B 92 92 D4 D5 E7 EA 90 72 9F 03 31 10 1F + +test 6 - 64 bytes +input: + D9 A9 50 DA 1D FC EE 71 DA 94 1D 9A B5 03 3E BE + FA 1B E1 F3 A1 32 DE F4 C4 F1 67 02 38 85 5C 11 + 2F AD EB 4C A9 D9 BD 84 6E DA 1E 23 DE 5C E1 D8 + 77 C3 CB 18 F5 AA 0D B9 9B 74 BB D3 FA 18 E5 29 +(did CBC mode for 32) +output: + D0 18 22 59 85 05 AB 87 0D 9D D0 99 7B 15 CC 43 + F7 43 1B BF 3C 7D A0 21 1E 3D 3F 6A 4D 8A CE 08 + 76 22 5A 42 DF 73 CB 5D CE 88 C3 4C CE 92 00 E6 + 37 9D EB CD 52 52 3B C5 76 02 7D 35 19 76 05 7D + diff --git a/krb5-1.21.3/src/lib/crypto/builtin/camellia/Makefile.in b/krb5-1.21.3/src/lib/crypto/builtin/camellia/Makefile.in new file mode 100644 index 00000000..88619694 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/camellia/Makefile.in @@ -0,0 +1,43 @@ +thisconfigdir=../../../.. +myfulldir=lib/crypto/builtin/camellia +mydir=lib$(S)crypto$(S)builtin$(S)camellia +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES=-I$(srcdir)/../../krb $(CRYPTO_IMPL_CFLGAS) + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\camellia +##DOS##OBJFILE = ..\..\$(OUTPRE)camellia.lst + +STLIBOBJS= camellia.o + +OBJS= $(OUTPRE)camellia.$(OBJEXT) + +SRCS= $(srcdir)/camellia.c + +GEN_OBJS= $(OUTPRE)camellia.$(OBJEXT) + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs # camellia-gen + +includes: depend + +depend: $(SRCS) + +camellia-gen: camellia-gen.o $(GEN_OBJS) + $(CC_LINK) -o camellia-gen camellia-gen.o $(GEN_OBJS) + +run-camellia-gen: camellia-gen + ./camellia-gen > kresults.out + +check-unix: check-@CRYPTO_BUILTIN_TESTS@ +check-no: +check-yes: run-camellia-gen + + +clean-unix:: clean-libobjs + +clean: + -$(RM) camellia-gen camellia-gen.o kresults.out + +@libobj_frag@ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/camellia/camellia-gen.c b/krb5-1.21.3/src/lib/crypto/builtin/camellia/camellia-gen.c new file mode 100644 index 00000000..23b69c17 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/camellia/camellia-gen.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2009 + * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved. + */ +#include +#include +#include +#include +#include "camellia.h" + +#define B 16U +unsigned char key[16]; +unsigned char test_case_len[] = { B+1, 2*B-1, 2*B, 2*B+1, 3*B-1, 3*B, 4*B, }; +#define NTESTS (sizeof(test_case_len)) +struct { + unsigned char ivec[16]; + unsigned char input[4*16]; + unsigned char output[4*16]; +} test_case[NTESTS]; +camellia_ctx ctx, dctx; + +static void init () +{ + size_t i, j; + cam_rval r; + + srand(42); + for (i = 0; i < 16; i++) + key[i] = 0xff & rand(); + memset(test_case, 0, sizeof(test_case)); + for (i = 0; i < NTESTS; i++) + for (j = 0; j < test_case_len[i]; j++) { + test_case[i].input[j] = 0xff & rand(); + } + + r = camellia_enc_key (key, sizeof(key), &ctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + r = camellia_dec_key (key, sizeof(key), &dctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); +} + +static void hexdump(const unsigned char *ptr, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) + printf ("%s%02X", (i % 16 == 0) ? "\n " : " ", ptr[i]); +} + +static void fips_test () +{ + static const unsigned char fipskey[16] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + static const unsigned char input[16] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + static const unsigned char expected[16] = { + 0x67,0x67,0x31,0x38,0x54,0x96,0x69,0x73, + 0x08,0x57,0x06,0x56,0x48,0xea,0xbe,0x43 + }; + unsigned char output[16]; + unsigned char tmp[16]; + camellia_ctx fipsctx; + int r; + + printf ("FIPS test:\nkey:"); + hexdump (fipskey, 16); + printf ("\ninput:"); + hexdump (input, 16); + r = camellia_enc_key (fipskey, sizeof(fipskey), &fipsctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + r = camellia_enc_blk (input, output, &fipsctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + printf ("\noutput:"); + hexdump (output, 16); + printf ("\n"); + if (memcmp(expected, output, 16)) + fprintf(stderr, "wrong results!!!\n"), exit (1); + r = camellia_dec_key (fipskey, sizeof(fipskey), &fipsctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + r = camellia_dec_blk (output, tmp, &fipsctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + if (memcmp(input, tmp, 16)) + fprintf(stderr, "decryption failed!!\n"), exit(1); + printf ("ok.\n\n"); +} + +static void +xor (unsigned char *out, const unsigned char *a, const unsigned char *b) +{ + size_t i; + for (i = 0; i < B; i++) + out[i] = a[i] ^ b[i]; +} + +static void +ecb_enc (unsigned char *out, unsigned char *in, unsigned int len) +{ + size_t i; + cam_rval r; + for (i = 0; i < len; i += 16) { + r = camellia_enc_blk (in + i, out + i, &ctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + } + if (i != len) abort (); +} + +static void +ecb_dec (unsigned char *out, unsigned char *in, unsigned int len) +{ + size_t i; + cam_rval r; + for (i = 0; i < len; i += 16) { + r = camellia_dec_blk (in + i, out + i, &dctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + } + if (i != len) abort (); +} + +#define D(X) (printf("%s %d: %s=",__FUNCTION__,__LINE__, #X),hexdump(X,B),printf("\n")) + +#undef D +#define D(X) + +static void +cbc_enc (unsigned char *out, unsigned char *in, unsigned char *iv, + unsigned int len) +{ + size_t i; + cam_rval r; + unsigned char tmp[B]; + D(iv); + memcpy (tmp, iv, B); + for (i = 0; i < len; i += B) { + D(in+i); + xor (tmp, tmp, in + i); + D(tmp); + r = camellia_enc_blk (tmp, out + i, &ctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + memcpy (tmp, out + i, B); + D(out+i); + } + if (i != len) abort (); +} + +static void +cbc_dec (unsigned char *out, unsigned char *in, unsigned char *iv, + unsigned int len) +{ + size_t i; + cam_rval r; + unsigned char tmp[B]; + memcpy (tmp, iv, B); + for (i = 0; i < len; i += B) { + r = camellia_dec_blk (in + i, tmp, &dctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + xor (tmp, tmp, iv); + iv = in + i; + memcpy (out + i, tmp, B); + } + if (i != len) abort (); +} + +static void +cts_enc (unsigned char *out, unsigned char *in, unsigned char *iv, + unsigned int len) +{ + int r; + unsigned int len2; + unsigned char pn1[B], pn[B], cn[B], cn1[B]; + + if (len < B + 1) abort (); + len2 = (len - B - 1) & ~(B-1); + cbc_enc (out, in, iv, len2); + out += len2; + in += len2; + len -= len2; + if (len2) + iv = out - B; + if (len <= B || len > 2 * B) + abort (); + printf ("(did CBC mode for %d)\n", len2); + + D(in); + xor (pn1, in, iv); + D(pn1); + r = camellia_enc_blk (pn1, cn, &ctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + D(cn); + memset (pn, 0, sizeof(pn)); + memcpy (pn, in+B, len-B); + D(pn); + xor (pn, pn, cn); + D(pn); + r = camellia_enc_blk (pn, cn1, &ctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + D(cn1); + memcpy(out, cn1, B); + memcpy(out+B, cn, len-B); +} + +static void +cts_dec (unsigned char *out, unsigned char *in, unsigned char *iv, + unsigned int len) +{ + int r; + unsigned int len2; + unsigned char pn1[B], pn[B], cn[B], cn1[B]; + + if (len < B + 1) abort (); + len2 = (len - B - 1) & ~(B-1); + cbc_dec (out, in, iv, len2); + out += len2; + in += len2; + len -= len2; + if (len2) + iv = in - B; + if (len <= B || len > 2 * B) + abort (); + + memcpy (cn1, in, B); + r = camellia_dec_blk (cn1, pn, &dctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + memset (cn, 0, sizeof(cn)); + memcpy (cn, in+B, len-B); + xor (pn, pn, cn); + memcpy (cn+len-B, pn+len-B, 2*B-len); + r = camellia_dec_blk (cn, pn1, &dctx); + if (!r) fprintf(stderr, "error, line %d\n", __LINE__), exit(1); + xor (pn1, pn1, iv); + memcpy(out, pn1, B); + memcpy(out+B, pn, len-B); +} + +static void ecb_test () +{ + size_t testno; + unsigned char tmp[4*B]; + + printf ("ECB tests:\n"); + printf ("key:"); + hexdump (key, sizeof(key)); + for (testno = 0; testno < NTESTS; testno++) { + unsigned len = (test_case_len[testno] + 15) & ~15; + printf ("\ntest %d - %d bytes\n", (int)testno, len); + printf ("input:"); + hexdump (test_case[testno].input, len); + printf ("\n"); + ecb_enc (test_case[testno].output, test_case[testno].input, len); + printf ("output:"); + hexdump (test_case[testno].output, len); + printf ("\n"); + ecb_dec (tmp, test_case[testno].output, len); + if (memcmp (tmp, test_case[testno].input, len)) { + printf ("ecb decrypt failed!!"); + hexdump (tmp, len); + printf ("\n"); + exit (1); + } + } + printf ("\n"); +} + +unsigned char ivec[16] = { 0 }; + +static void cbc_test () +{ + size_t testno; + unsigned char tmp[4*B]; + + printf ("CBC tests:\n"); + printf ("initial vector:"); + hexdump (ivec, sizeof(ivec)); + for (testno = 0; testno < NTESTS; testno++) { + unsigned len = (test_case_len[testno] + 15) & ~15; + printf ("\ntest %d - %d bytes\n", (int)testno, len); + printf ("input:"); + hexdump (test_case[testno].input, len); + printf ("\n"); + cbc_enc (test_case[testno].output, test_case[testno].input, ivec, len); + printf ("output:"); + hexdump (test_case[testno].output, len); + printf ("\n"); + cbc_dec (tmp, test_case[testno].output, ivec, len); + if (memcmp (tmp, test_case[testno].input, len)) { + printf("cbc decrypt failed!!"); + hexdump (tmp, len); + printf ("\n"); + exit(1); + } + } + printf ("\n"); +} + +static void cts_test () +{ + size_t testno; + unsigned char tmp[4*B]; + + printf ("CTS tests:\n"); + printf ("initial vector:"); + hexdump (ivec, sizeof(ivec)); + for (testno = 0; testno < NTESTS; testno++) { + unsigned int len = test_case_len[testno]; + printf ("\ntest %d - %d bytes\n", (int)testno, len); + printf ("input:"); + hexdump (test_case[testno].input, len); + printf ("\n"); + cts_enc (test_case[testno].output, test_case[testno].input, ivec, len); + printf ("output:"); + hexdump (test_case[testno].output, len); + printf ("\n"); + cts_dec (tmp, test_case[testno].output, ivec, len); + if (memcmp (tmp, test_case[testno].input, len)) + fprintf (stderr, "cts decrypt failed!!\n"), exit(1); + } + printf ("\n"); +} + +int main () +{ + init (); + fips_test (); + + ecb_test(); + cbc_test(); + cts_test(); + + return 0; +} + diff --git a/krb5-1.21.3/src/lib/crypto/builtin/camellia/camellia.c b/krb5-1.21.3/src/lib/crypto/builtin/camellia/camellia.c new file mode 100644 index 00000000..f462ceac --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/camellia/camellia.c @@ -0,0 +1,1544 @@ +/* lib/crypto/builtin/camellia/camellia.c - Camellia version 1.2.0 */ +/* + * Copyright (c) 2006,2007,2009 + * NTT (Nippon Telegraph and Telephone Corporation) . 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 as + * the first lines of this file unmodified. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY NTT ``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 NTT 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. + */ + +/* + * Algorithm Specification + * https://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html + */ + + +#include +#include + +#include "camellia.h" + +#include "crypto_int.h" +#ifdef K5_BUILTIN_CAMELLIA + +/* key constants */ + +#define CAMELLIA_SIGMA1L (0xA09E667FL) +#define CAMELLIA_SIGMA1R (0x3BCC908BL) +#define CAMELLIA_SIGMA2L (0xB67AE858L) +#define CAMELLIA_SIGMA2R (0x4CAA73B2L) +#define CAMELLIA_SIGMA3L (0xC6EF372FL) +#define CAMELLIA_SIGMA3R (0xE94F82BEL) +#define CAMELLIA_SIGMA4L (0x54FF53A5L) +#define CAMELLIA_SIGMA4R (0xF1D36F1CL) +#define CAMELLIA_SIGMA5L (0x10E527FAL) +#define CAMELLIA_SIGMA5R (0xDE682D1DL) +#define CAMELLIA_SIGMA6L (0xB05688C2L) +#define CAMELLIA_SIGMA6R (0xB3E6C1FDL) + +/* + * macros + */ + + +#if defined(_MSC_VER) + +# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +# define GETU32(p) SWAP(*((u32 *)(p))) +# define PUTU32(ct, st) {*((u32 *)(ct)) = SWAP((st));} + +#else /* not MS-VC */ + +# define GETU32(pt) \ + (((u32)(pt)[0] << 24) \ + ^ ((u32)(pt)[1] << 16) \ + ^ ((u32)(pt)[2] << 8) \ + ^ ((u32)(pt)[3])) + +# define PUTU32(ct, st) { \ + (ct)[0] = (u8)((st) >> 24); \ + (ct)[1] = (u8)((st) >> 16); \ + (ct)[2] = (u8)((st) >> 8); \ + (ct)[3] = (u8)(st); } + +#endif + +#define CamelliaSubkeyL(INDEX) (subkey[(INDEX)*2]) +#define CamelliaSubkeyR(INDEX) (subkey[(INDEX)*2 + 1]) + +/* rotation right shift 1byte */ +#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24)) +/* rotation left shift 1bit */ +#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31)) +/* rotation left shift 1byte */ +#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24)) + +#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits) \ + do { \ + w0 = ll; \ + ll = (ll << bits) + (lr >> (32 - bits)); \ + lr = (lr << bits) + (rl >> (32 - bits)); \ + rl = (rl << bits) + (rr >> (32 - bits)); \ + rr = (rr << bits) + (w0 >> (32 - bits)); \ + } while(0) + +#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits) \ + do { \ + w0 = ll; \ + w1 = lr; \ + ll = (lr << (bits - 32)) + (rl >> (64 - bits)); \ + lr = (rl << (bits - 32)) + (rr >> (64 - bits)); \ + rl = (rr << (bits - 32)) + (w0 >> (64 - bits)); \ + rr = (w0 << (bits - 32)) + (w1 >> (64 - bits)); \ + } while(0) + +#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)]) +#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)]) +#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)]) +#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)]) + +#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ + do { \ + il = xl ^ kl; \ + ir = xr ^ kr; \ + t0 = il >> 16; \ + t1 = ir >> 16; \ + yl = CAMELLIA_SP1110(ir & 0xff) \ + ^ CAMELLIA_SP0222((t1 >> 8) & 0xff) \ + ^ CAMELLIA_SP3033(t1 & 0xff) \ + ^ CAMELLIA_SP4404((ir >> 8) & 0xff); \ + yr = CAMELLIA_SP1110((t0 >> 8) & 0xff) \ + ^ CAMELLIA_SP0222(t0 & 0xff) \ + ^ CAMELLIA_SP3033((il >> 8) & 0xff) \ + ^ CAMELLIA_SP4404(il & 0xff); \ + yl ^= yr; \ + yr = CAMELLIA_RR8(yr); \ + yr ^= yl; \ + } while(0) + + +/* + * for speed up + * + */ +#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \ + do { \ + t0 = kll; \ + t0 &= ll; \ + lr ^= CAMELLIA_RL1(t0); \ + t1 = klr; \ + t1 |= lr; \ + ll ^= t1; \ + \ + t2 = krr; \ + t2 |= rr; \ + rl ^= t2; \ + t3 = krl; \ + t3 &= rl; \ + rr ^= CAMELLIA_RL1(t3); \ + } while(0) + +#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ + do { \ + ir = CAMELLIA_SP1110(xr & 0xff) \ + ^ CAMELLIA_SP0222((xr >> 24) & 0xff) \ + ^ CAMELLIA_SP3033((xr >> 16) & 0xff) \ + ^ CAMELLIA_SP4404((xr >> 8) & 0xff); \ + il = CAMELLIA_SP1110((xl >> 24) & 0xff) \ + ^ CAMELLIA_SP0222((xl >> 16) & 0xff) \ + ^ CAMELLIA_SP3033((xl >> 8) & 0xff) \ + ^ CAMELLIA_SP4404(xl & 0xff); \ + il ^= kl; \ + ir ^= kr; \ + ir ^= il; \ + il = CAMELLIA_RR8(il); \ + il ^= ir; \ + yl ^= ir; \ + yr ^= il; \ + } while(0) + + +static const u32 camellia_sp1110[256] = { + 0x70707000,0x82828200,0x2c2c2c00,0xececec00, + 0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500, + 0xe4e4e400,0x85858500,0x57575700,0x35353500, + 0xeaeaea00,0x0c0c0c00,0xaeaeae00,0x41414100, + 0x23232300,0xefefef00,0x6b6b6b00,0x93939300, + 0x45454500,0x19191900,0xa5a5a500,0x21212100, + 0xededed00,0x0e0e0e00,0x4f4f4f00,0x4e4e4e00, + 0x1d1d1d00,0x65656500,0x92929200,0xbdbdbd00, + 0x86868600,0xb8b8b800,0xafafaf00,0x8f8f8f00, + 0x7c7c7c00,0xebebeb00,0x1f1f1f00,0xcecece00, + 0x3e3e3e00,0x30303000,0xdcdcdc00,0x5f5f5f00, + 0x5e5e5e00,0xc5c5c500,0x0b0b0b00,0x1a1a1a00, + 0xa6a6a600,0xe1e1e100,0x39393900,0xcacaca00, + 0xd5d5d500,0x47474700,0x5d5d5d00,0x3d3d3d00, + 0xd9d9d900,0x01010100,0x5a5a5a00,0xd6d6d600, + 0x51515100,0x56565600,0x6c6c6c00,0x4d4d4d00, + 0x8b8b8b00,0x0d0d0d00,0x9a9a9a00,0x66666600, + 0xfbfbfb00,0xcccccc00,0xb0b0b000,0x2d2d2d00, + 0x74747400,0x12121200,0x2b2b2b00,0x20202000, + 0xf0f0f000,0xb1b1b100,0x84848400,0x99999900, + 0xdfdfdf00,0x4c4c4c00,0xcbcbcb00,0xc2c2c200, + 0x34343400,0x7e7e7e00,0x76767600,0x05050500, + 0x6d6d6d00,0xb7b7b700,0xa9a9a900,0x31313100, + 0xd1d1d100,0x17171700,0x04040400,0xd7d7d700, + 0x14141400,0x58585800,0x3a3a3a00,0x61616100, + 0xdedede00,0x1b1b1b00,0x11111100,0x1c1c1c00, + 0x32323200,0x0f0f0f00,0x9c9c9c00,0x16161600, + 0x53535300,0x18181800,0xf2f2f200,0x22222200, + 0xfefefe00,0x44444400,0xcfcfcf00,0xb2b2b200, + 0xc3c3c300,0xb5b5b500,0x7a7a7a00,0x91919100, + 0x24242400,0x08080800,0xe8e8e800,0xa8a8a800, + 0x60606000,0xfcfcfc00,0x69696900,0x50505000, + 0xaaaaaa00,0xd0d0d000,0xa0a0a000,0x7d7d7d00, + 0xa1a1a100,0x89898900,0x62626200,0x97979700, + 0x54545400,0x5b5b5b00,0x1e1e1e00,0x95959500, + 0xe0e0e000,0xffffff00,0x64646400,0xd2d2d200, + 0x10101000,0xc4c4c400,0x00000000,0x48484800, + 0xa3a3a300,0xf7f7f700,0x75757500,0xdbdbdb00, + 0x8a8a8a00,0x03030300,0xe6e6e600,0xdadada00, + 0x09090900,0x3f3f3f00,0xdddddd00,0x94949400, + 0x87878700,0x5c5c5c00,0x83838300,0x02020200, + 0xcdcdcd00,0x4a4a4a00,0x90909000,0x33333300, + 0x73737300,0x67676700,0xf6f6f600,0xf3f3f300, + 0x9d9d9d00,0x7f7f7f00,0xbfbfbf00,0xe2e2e200, + 0x52525200,0x9b9b9b00,0xd8d8d800,0x26262600, + 0xc8c8c800,0x37373700,0xc6c6c600,0x3b3b3b00, + 0x81818100,0x96969600,0x6f6f6f00,0x4b4b4b00, + 0x13131300,0xbebebe00,0x63636300,0x2e2e2e00, + 0xe9e9e900,0x79797900,0xa7a7a700,0x8c8c8c00, + 0x9f9f9f00,0x6e6e6e00,0xbcbcbc00,0x8e8e8e00, + 0x29292900,0xf5f5f500,0xf9f9f900,0xb6b6b600, + 0x2f2f2f00,0xfdfdfd00,0xb4b4b400,0x59595900, + 0x78787800,0x98989800,0x06060600,0x6a6a6a00, + 0xe7e7e700,0x46464600,0x71717100,0xbababa00, + 0xd4d4d400,0x25252500,0xababab00,0x42424200, + 0x88888800,0xa2a2a200,0x8d8d8d00,0xfafafa00, + 0x72727200,0x07070700,0xb9b9b900,0x55555500, + 0xf8f8f800,0xeeeeee00,0xacacac00,0x0a0a0a00, + 0x36363600,0x49494900,0x2a2a2a00,0x68686800, + 0x3c3c3c00,0x38383800,0xf1f1f100,0xa4a4a400, + 0x40404000,0x28282800,0xd3d3d300,0x7b7b7b00, + 0xbbbbbb00,0xc9c9c900,0x43434300,0xc1c1c100, + 0x15151500,0xe3e3e300,0xadadad00,0xf4f4f400, + 0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00, +}; + +static const u32 camellia_sp0222[256] = { + 0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9, + 0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb, + 0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a, + 0x00d5d5d5,0x00181818,0x005d5d5d,0x00828282, + 0x00464646,0x00dfdfdf,0x00d6d6d6,0x00272727, + 0x008a8a8a,0x00323232,0x004b4b4b,0x00424242, + 0x00dbdbdb,0x001c1c1c,0x009e9e9e,0x009c9c9c, + 0x003a3a3a,0x00cacaca,0x00252525,0x007b7b7b, + 0x000d0d0d,0x00717171,0x005f5f5f,0x001f1f1f, + 0x00f8f8f8,0x00d7d7d7,0x003e3e3e,0x009d9d9d, + 0x007c7c7c,0x00606060,0x00b9b9b9,0x00bebebe, + 0x00bcbcbc,0x008b8b8b,0x00161616,0x00343434, + 0x004d4d4d,0x00c3c3c3,0x00727272,0x00959595, + 0x00ababab,0x008e8e8e,0x00bababa,0x007a7a7a, + 0x00b3b3b3,0x00020202,0x00b4b4b4,0x00adadad, + 0x00a2a2a2,0x00acacac,0x00d8d8d8,0x009a9a9a, + 0x00171717,0x001a1a1a,0x00353535,0x00cccccc, + 0x00f7f7f7,0x00999999,0x00616161,0x005a5a5a, + 0x00e8e8e8,0x00242424,0x00565656,0x00404040, + 0x00e1e1e1,0x00636363,0x00090909,0x00333333, + 0x00bfbfbf,0x00989898,0x00979797,0x00858585, + 0x00686868,0x00fcfcfc,0x00ececec,0x000a0a0a, + 0x00dadada,0x006f6f6f,0x00535353,0x00626262, + 0x00a3a3a3,0x002e2e2e,0x00080808,0x00afafaf, + 0x00282828,0x00b0b0b0,0x00747474,0x00c2c2c2, + 0x00bdbdbd,0x00363636,0x00222222,0x00383838, + 0x00646464,0x001e1e1e,0x00393939,0x002c2c2c, + 0x00a6a6a6,0x00303030,0x00e5e5e5,0x00444444, + 0x00fdfdfd,0x00888888,0x009f9f9f,0x00656565, + 0x00878787,0x006b6b6b,0x00f4f4f4,0x00232323, + 0x00484848,0x00101010,0x00d1d1d1,0x00515151, + 0x00c0c0c0,0x00f9f9f9,0x00d2d2d2,0x00a0a0a0, + 0x00555555,0x00a1a1a1,0x00414141,0x00fafafa, + 0x00434343,0x00131313,0x00c4c4c4,0x002f2f2f, + 0x00a8a8a8,0x00b6b6b6,0x003c3c3c,0x002b2b2b, + 0x00c1c1c1,0x00ffffff,0x00c8c8c8,0x00a5a5a5, + 0x00202020,0x00898989,0x00000000,0x00909090, + 0x00474747,0x00efefef,0x00eaeaea,0x00b7b7b7, + 0x00151515,0x00060606,0x00cdcdcd,0x00b5b5b5, + 0x00121212,0x007e7e7e,0x00bbbbbb,0x00292929, + 0x000f0f0f,0x00b8b8b8,0x00070707,0x00040404, + 0x009b9b9b,0x00949494,0x00212121,0x00666666, + 0x00e6e6e6,0x00cecece,0x00ededed,0x00e7e7e7, + 0x003b3b3b,0x00fefefe,0x007f7f7f,0x00c5c5c5, + 0x00a4a4a4,0x00373737,0x00b1b1b1,0x004c4c4c, + 0x00919191,0x006e6e6e,0x008d8d8d,0x00767676, + 0x00030303,0x002d2d2d,0x00dedede,0x00969696, + 0x00262626,0x007d7d7d,0x00c6c6c6,0x005c5c5c, + 0x00d3d3d3,0x00f2f2f2,0x004f4f4f,0x00191919, + 0x003f3f3f,0x00dcdcdc,0x00797979,0x001d1d1d, + 0x00525252,0x00ebebeb,0x00f3f3f3,0x006d6d6d, + 0x005e5e5e,0x00fbfbfb,0x00696969,0x00b2b2b2, + 0x00f0f0f0,0x00313131,0x000c0c0c,0x00d4d4d4, + 0x00cfcfcf,0x008c8c8c,0x00e2e2e2,0x00757575, + 0x00a9a9a9,0x004a4a4a,0x00575757,0x00848484, + 0x00111111,0x00454545,0x001b1b1b,0x00f5f5f5, + 0x00e4e4e4,0x000e0e0e,0x00737373,0x00aaaaaa, + 0x00f1f1f1,0x00dddddd,0x00595959,0x00141414, + 0x006c6c6c,0x00929292,0x00545454,0x00d0d0d0, + 0x00787878,0x00707070,0x00e3e3e3,0x00494949, + 0x00808080,0x00505050,0x00a7a7a7,0x00f6f6f6, + 0x00777777,0x00939393,0x00868686,0x00838383, + 0x002a2a2a,0x00c7c7c7,0x005b5b5b,0x00e9e9e9, + 0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d, +}; + +static const u32 camellia_sp3033[256] = { + 0x38003838,0x41004141,0x16001616,0x76007676, + 0xd900d9d9,0x93009393,0x60006060,0xf200f2f2, + 0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a, + 0x75007575,0x06000606,0x57005757,0xa000a0a0, + 0x91009191,0xf700f7f7,0xb500b5b5,0xc900c9c9, + 0xa200a2a2,0x8c008c8c,0xd200d2d2,0x90009090, + 0xf600f6f6,0x07000707,0xa700a7a7,0x27002727, + 0x8e008e8e,0xb200b2b2,0x49004949,0xde00dede, + 0x43004343,0x5c005c5c,0xd700d7d7,0xc700c7c7, + 0x3e003e3e,0xf500f5f5,0x8f008f8f,0x67006767, + 0x1f001f1f,0x18001818,0x6e006e6e,0xaf00afaf, + 0x2f002f2f,0xe200e2e2,0x85008585,0x0d000d0d, + 0x53005353,0xf000f0f0,0x9c009c9c,0x65006565, + 0xea00eaea,0xa300a3a3,0xae00aeae,0x9e009e9e, + 0xec00ecec,0x80008080,0x2d002d2d,0x6b006b6b, + 0xa800a8a8,0x2b002b2b,0x36003636,0xa600a6a6, + 0xc500c5c5,0x86008686,0x4d004d4d,0x33003333, + 0xfd00fdfd,0x66006666,0x58005858,0x96009696, + 0x3a003a3a,0x09000909,0x95009595,0x10001010, + 0x78007878,0xd800d8d8,0x42004242,0xcc00cccc, + 0xef00efef,0x26002626,0xe500e5e5,0x61006161, + 0x1a001a1a,0x3f003f3f,0x3b003b3b,0x82008282, + 0xb600b6b6,0xdb00dbdb,0xd400d4d4,0x98009898, + 0xe800e8e8,0x8b008b8b,0x02000202,0xeb00ebeb, + 0x0a000a0a,0x2c002c2c,0x1d001d1d,0xb000b0b0, + 0x6f006f6f,0x8d008d8d,0x88008888,0x0e000e0e, + 0x19001919,0x87008787,0x4e004e4e,0x0b000b0b, + 0xa900a9a9,0x0c000c0c,0x79007979,0x11001111, + 0x7f007f7f,0x22002222,0xe700e7e7,0x59005959, + 0xe100e1e1,0xda00dada,0x3d003d3d,0xc800c8c8, + 0x12001212,0x04000404,0x74007474,0x54005454, + 0x30003030,0x7e007e7e,0xb400b4b4,0x28002828, + 0x55005555,0x68006868,0x50005050,0xbe00bebe, + 0xd000d0d0,0xc400c4c4,0x31003131,0xcb00cbcb, + 0x2a002a2a,0xad00adad,0x0f000f0f,0xca00caca, + 0x70007070,0xff00ffff,0x32003232,0x69006969, + 0x08000808,0x62006262,0x00000000,0x24002424, + 0xd100d1d1,0xfb00fbfb,0xba00baba,0xed00eded, + 0x45004545,0x81008181,0x73007373,0x6d006d6d, + 0x84008484,0x9f009f9f,0xee00eeee,0x4a004a4a, + 0xc300c3c3,0x2e002e2e,0xc100c1c1,0x01000101, + 0xe600e6e6,0x25002525,0x48004848,0x99009999, + 0xb900b9b9,0xb300b3b3,0x7b007b7b,0xf900f9f9, + 0xce00cece,0xbf00bfbf,0xdf00dfdf,0x71007171, + 0x29002929,0xcd00cdcd,0x6c006c6c,0x13001313, + 0x64006464,0x9b009b9b,0x63006363,0x9d009d9d, + 0xc000c0c0,0x4b004b4b,0xb700b7b7,0xa500a5a5, + 0x89008989,0x5f005f5f,0xb100b1b1,0x17001717, + 0xf400f4f4,0xbc00bcbc,0xd300d3d3,0x46004646, + 0xcf00cfcf,0x37003737,0x5e005e5e,0x47004747, + 0x94009494,0xfa00fafa,0xfc00fcfc,0x5b005b5b, + 0x97009797,0xfe00fefe,0x5a005a5a,0xac00acac, + 0x3c003c3c,0x4c004c4c,0x03000303,0x35003535, + 0xf300f3f3,0x23002323,0xb800b8b8,0x5d005d5d, + 0x6a006a6a,0x92009292,0xd500d5d5,0x21002121, + 0x44004444,0x51005151,0xc600c6c6,0x7d007d7d, + 0x39003939,0x83008383,0xdc00dcdc,0xaa00aaaa, + 0x7c007c7c,0x77007777,0x56005656,0x05000505, + 0x1b001b1b,0xa400a4a4,0x15001515,0x34003434, + 0x1e001e1e,0x1c001c1c,0xf800f8f8,0x52005252, + 0x20002020,0x14001414,0xe900e9e9,0xbd00bdbd, + 0xdd00dddd,0xe400e4e4,0xa100a1a1,0xe000e0e0, + 0x8a008a8a,0xf100f1f1,0xd600d6d6,0x7a007a7a, + 0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f, +}; + +static const u32 camellia_sp4404[256] = { + 0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0, + 0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae, + 0x23230023,0x6b6b006b,0x45450045,0xa5a500a5, + 0xeded00ed,0x4f4f004f,0x1d1d001d,0x92920092, + 0x86860086,0xafaf00af,0x7c7c007c,0x1f1f001f, + 0x3e3e003e,0xdcdc00dc,0x5e5e005e,0x0b0b000b, + 0xa6a600a6,0x39390039,0xd5d500d5,0x5d5d005d, + 0xd9d900d9,0x5a5a005a,0x51510051,0x6c6c006c, + 0x8b8b008b,0x9a9a009a,0xfbfb00fb,0xb0b000b0, + 0x74740074,0x2b2b002b,0xf0f000f0,0x84840084, + 0xdfdf00df,0xcbcb00cb,0x34340034,0x76760076, + 0x6d6d006d,0xa9a900a9,0xd1d100d1,0x04040004, + 0x14140014,0x3a3a003a,0xdede00de,0x11110011, + 0x32320032,0x9c9c009c,0x53530053,0xf2f200f2, + 0xfefe00fe,0xcfcf00cf,0xc3c300c3,0x7a7a007a, + 0x24240024,0xe8e800e8,0x60600060,0x69690069, + 0xaaaa00aa,0xa0a000a0,0xa1a100a1,0x62620062, + 0x54540054,0x1e1e001e,0xe0e000e0,0x64640064, + 0x10100010,0x00000000,0xa3a300a3,0x75750075, + 0x8a8a008a,0xe6e600e6,0x09090009,0xdddd00dd, + 0x87870087,0x83830083,0xcdcd00cd,0x90900090, + 0x73730073,0xf6f600f6,0x9d9d009d,0xbfbf00bf, + 0x52520052,0xd8d800d8,0xc8c800c8,0xc6c600c6, + 0x81810081,0x6f6f006f,0x13130013,0x63630063, + 0xe9e900e9,0xa7a700a7,0x9f9f009f,0xbcbc00bc, + 0x29290029,0xf9f900f9,0x2f2f002f,0xb4b400b4, + 0x78780078,0x06060006,0xe7e700e7,0x71710071, + 0xd4d400d4,0xabab00ab,0x88880088,0x8d8d008d, + 0x72720072,0xb9b900b9,0xf8f800f8,0xacac00ac, + 0x36360036,0x2a2a002a,0x3c3c003c,0xf1f100f1, + 0x40400040,0xd3d300d3,0xbbbb00bb,0x43430043, + 0x15150015,0xadad00ad,0x77770077,0x80800080, + 0x82820082,0xecec00ec,0x27270027,0xe5e500e5, + 0x85850085,0x35350035,0x0c0c000c,0x41410041, + 0xefef00ef,0x93930093,0x19190019,0x21210021, + 0x0e0e000e,0x4e4e004e,0x65650065,0xbdbd00bd, + 0xb8b800b8,0x8f8f008f,0xebeb00eb,0xcece00ce, + 0x30300030,0x5f5f005f,0xc5c500c5,0x1a1a001a, + 0xe1e100e1,0xcaca00ca,0x47470047,0x3d3d003d, + 0x01010001,0xd6d600d6,0x56560056,0x4d4d004d, + 0x0d0d000d,0x66660066,0xcccc00cc,0x2d2d002d, + 0x12120012,0x20200020,0xb1b100b1,0x99990099, + 0x4c4c004c,0xc2c200c2,0x7e7e007e,0x05050005, + 0xb7b700b7,0x31310031,0x17170017,0xd7d700d7, + 0x58580058,0x61610061,0x1b1b001b,0x1c1c001c, + 0x0f0f000f,0x16160016,0x18180018,0x22220022, + 0x44440044,0xb2b200b2,0xb5b500b5,0x91910091, + 0x08080008,0xa8a800a8,0xfcfc00fc,0x50500050, + 0xd0d000d0,0x7d7d007d,0x89890089,0x97970097, + 0x5b5b005b,0x95950095,0xffff00ff,0xd2d200d2, + 0xc4c400c4,0x48480048,0xf7f700f7,0xdbdb00db, + 0x03030003,0xdada00da,0x3f3f003f,0x94940094, + 0x5c5c005c,0x02020002,0x4a4a004a,0x33330033, + 0x67670067,0xf3f300f3,0x7f7f007f,0xe2e200e2, + 0x9b9b009b,0x26260026,0x37370037,0x3b3b003b, + 0x96960096,0x4b4b004b,0xbebe00be,0x2e2e002e, + 0x79790079,0x8c8c008c,0x6e6e006e,0x8e8e008e, + 0xf5f500f5,0xb6b600b6,0xfdfd00fd,0x59590059, + 0x98980098,0x6a6a006a,0x46460046,0xbaba00ba, + 0x25250025,0x42420042,0xa2a200a2,0xfafa00fa, + 0x07070007,0x55550055,0xeeee00ee,0x0a0a000a, + 0x49490049,0x68680068,0x38380038,0xa4a400a4, + 0x28280028,0x7b7b007b,0xc9c900c9,0xc1c100c1, + 0xe3e300e3,0xf4f400f4,0xc7c700c7,0x9e9e009e, +}; + + +/** + * Stuff related to the Camellia key schedule + */ +#define subl(x) subL[(x)] +#define subr(x) subR[(x)] + +void +camellia_setup128(const unsigned char *key, u32 *subkey) +{ + u32 kll, klr, krl, krr; + u32 il, ir, t0, t1, w0, w1; + u32 kw4l, kw4r, dw, tl, tr; + u32 subL[26]; + u32 subR[26]; + + /** + * k == kll || klr || krl || krr (|| is concatination) + */ + kll = GETU32(key ); + klr = GETU32(key + 4); + krl = GETU32(key + 8); + krr = GETU32(key + 12); + /** + * generate KL dependent subkeys + */ + subl(0) = kll; subr(0) = klr; + subl(1) = krl; subr(1) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(4) = kll; subr(4) = klr; + subl(5) = krl; subr(5) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); + subl(10) = kll; subr(10) = klr; + subl(11) = krl; subr(11) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(13) = krl; subr(13) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(16) = kll; subr(16) = klr; + subl(17) = krl; subr(17) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(18) = kll; subr(18) = klr; + subl(19) = krl; subr(19) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(22) = kll; subr(22) = klr; + subl(23) = krl; subr(23) = krr; + + /* generate KA */ + kll = subl(0); klr = subr(0); + krl = subl(1); krr = subr(1); + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, + w0, w1, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, + kll, klr, il, ir, t0, t1); + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, + krl, krr, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, + w0, w1, il, ir, t0, t1); + kll ^= w0; klr ^= w1; + + /* generate KA dependent subkeys */ + subl(2) = kll; subr(2) = klr; + subl(3) = krl; subr(3) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(6) = kll; subr(6) = klr; + subl(7) = krl; subr(7) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(8) = kll; subr(8) = klr; + subl(9) = krl; subr(9) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(12) = kll; subr(12) = klr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(14) = kll; subr(14) = klr; + subl(15) = krl; subr(15) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); + subl(20) = kll; subr(20) = klr; + subl(21) = krl; subr(21) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(24) = kll; subr(24) = klr; + subl(25) = krl; subr(25) = krr; + + + /* absorb kw2 to other subkeys */ + subl(3) ^= subl(1); subr(3) ^= subr(1); + subl(5) ^= subl(1); subr(5) ^= subr(1); + subl(7) ^= subl(1); subr(7) ^= subr(1); + subl(1) ^= subr(1) & ~subr(9); + dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); + subl(11) ^= subl(1); subr(11) ^= subr(1); + subl(13) ^= subl(1); subr(13) ^= subr(1); + subl(15) ^= subl(1); subr(15) ^= subr(1); + subl(1) ^= subr(1) & ~subr(17); + dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); + subl(19) ^= subl(1); subr(19) ^= subr(1); + subl(21) ^= subl(1); subr(21) ^= subr(1); + subl(23) ^= subl(1); subr(23) ^= subr(1); + subl(24) ^= subl(1); subr(24) ^= subr(1); + + /* absorb kw4 to other subkeys */ + kw4l = subl(25); kw4r = subr(25); + subl(22) ^= kw4l; subr(22) ^= kw4r; + subl(20) ^= kw4l; subr(20) ^= kw4r; + subl(18) ^= kw4l; subr(18) ^= kw4r; + kw4l ^= kw4r & ~subr(16); + dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); + subl(14) ^= kw4l; subr(14) ^= kw4r; + subl(12) ^= kw4l; subr(12) ^= kw4r; + subl(10) ^= kw4l; subr(10) ^= kw4r; + kw4l ^= kw4r & ~subr(8); + dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); + subl(6) ^= kw4l; subr(6) ^= kw4r; + subl(4) ^= kw4l; subr(4) ^= kw4r; + subl(2) ^= kw4l; subr(2) ^= kw4r; + subl(0) ^= kw4l; subr(0) ^= kw4r; + + /* key XOR is end of F-function */ + CamelliaSubkeyL(0) = subl(0) ^ subl(2); + CamelliaSubkeyR(0) = subr(0) ^ subr(2); + CamelliaSubkeyL(2) = subl(3); + CamelliaSubkeyR(2) = subr(3); + CamelliaSubkeyL(3) = subl(2) ^ subl(4); + CamelliaSubkeyR(3) = subr(2) ^ subr(4); + CamelliaSubkeyL(4) = subl(3) ^ subl(5); + CamelliaSubkeyR(4) = subr(3) ^ subr(5); + CamelliaSubkeyL(5) = subl(4) ^ subl(6); + CamelliaSubkeyR(5) = subr(4) ^ subr(6); + CamelliaSubkeyL(6) = subl(5) ^ subl(7); + CamelliaSubkeyR(6) = subr(5) ^ subr(7); + tl = subl(10) ^ (subr(10) & ~subr(8)); + dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(7) = subl(6) ^ tl; + CamelliaSubkeyR(7) = subr(6) ^ tr; + CamelliaSubkeyL(8) = subl(8); + CamelliaSubkeyR(8) = subr(8); + CamelliaSubkeyL(9) = subl(9); + CamelliaSubkeyR(9) = subr(9); + tl = subl(7) ^ (subr(7) & ~subr(9)); + dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(10) = tl ^ subl(11); + CamelliaSubkeyR(10) = tr ^ subr(11); + CamelliaSubkeyL(11) = subl(10) ^ subl(12); + CamelliaSubkeyR(11) = subr(10) ^ subr(12); + CamelliaSubkeyL(12) = subl(11) ^ subl(13); + CamelliaSubkeyR(12) = subr(11) ^ subr(13); + CamelliaSubkeyL(13) = subl(12) ^ subl(14); + CamelliaSubkeyR(13) = subr(12) ^ subr(14); + CamelliaSubkeyL(14) = subl(13) ^ subl(15); + CamelliaSubkeyR(14) = subr(13) ^ subr(15); + tl = subl(18) ^ (subr(18) & ~subr(16)); + dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(15) = subl(14) ^ tl; + CamelliaSubkeyR(15) = subr(14) ^ tr; + CamelliaSubkeyL(16) = subl(16); + CamelliaSubkeyR(16) = subr(16); + CamelliaSubkeyL(17) = subl(17); + CamelliaSubkeyR(17) = subr(17); + tl = subl(15) ^ (subr(15) & ~subr(17)); + dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(18) = tl ^ subl(19); + CamelliaSubkeyR(18) = tr ^ subr(19); + CamelliaSubkeyL(19) = subl(18) ^ subl(20); + CamelliaSubkeyR(19) = subr(18) ^ subr(20); + CamelliaSubkeyL(20) = subl(19) ^ subl(21); + CamelliaSubkeyR(20) = subr(19) ^ subr(21); + CamelliaSubkeyL(21) = subl(20) ^ subl(22); + CamelliaSubkeyR(21) = subr(20) ^ subr(22); + CamelliaSubkeyL(22) = subl(21) ^ subl(23); + CamelliaSubkeyR(22) = subr(21) ^ subr(23); + CamelliaSubkeyL(23) = subl(22); + CamelliaSubkeyR(23) = subr(22); + CamelliaSubkeyL(24) = subl(24) ^ subl(23); + CamelliaSubkeyR(24) = subr(24) ^ subr(23); + + /* apply the inverse of the last half of P-function */ + dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw; + dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw; + dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw; + dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw; + dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw; + dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw; + dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw; + dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw; + dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw; + dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw; + dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw; + dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw; + dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw; + dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw; + dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw; + dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw; + dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw; + dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw; + + return; +} + +void +camellia_setup256(const unsigned char *key, u32 *subkey) +{ + u32 kll,klr,krl,krr; /* left half of key */ + u32 krll,krlr,krrl,krrr; /* right half of key */ + u32 il, ir, t0, t1, w0, w1; /* temporary variables */ + u32 kw4l, kw4r, dw, tl, tr; + u32 subL[34]; + u32 subR[34]; + + /** + * key = (kll || klr || krl || krr || krll || krlr || krrl || krrr) + * (|| is concatination) + */ + + kll = GETU32(key ); + klr = GETU32(key + 4); + krl = GETU32(key + 8); + krr = GETU32(key + 12); + krll = GETU32(key + 16); + krlr = GETU32(key + 20); + krrl = GETU32(key + 24); + krrr = GETU32(key + 28); + + /* generate KL dependent subkeys */ + subl(0) = kll; subr(0) = klr; + subl(1) = krl; subr(1) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45); + subl(12) = kll; subr(12) = klr; + subl(13) = krl; subr(13) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(16) = kll; subr(16) = klr; + subl(17) = krl; subr(17) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(22) = kll; subr(22) = klr; + subl(23) = krl; subr(23) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); + subl(30) = kll; subr(30) = klr; + subl(31) = krl; subr(31) = krr; + + /* generate KR dependent subkeys */ + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); + subl(4) = krll; subr(4) = krlr; + subl(5) = krrl; subr(5) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); + subl(8) = krll; subr(8) = krlr; + subl(9) = krrl; subr(9) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(18) = krll; subr(18) = krlr; + subl(19) = krrl; subr(19) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); + subl(26) = krll; subr(26) = krlr; + subl(27) = krrl; subr(27) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); + + /* generate KA */ + kll = subl(0) ^ krll; klr = subr(0) ^ krlr; + krl = subl(1) ^ krrl; krr = subr(1) ^ krrr; + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, + w0, w1, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, + kll, klr, il, ir, t0, t1); + kll ^= krll; klr ^= krlr; + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, + krl, krr, il, ir, t0, t1); + krl ^= w0 ^ krrl; krr ^= w1 ^ krrr; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, + w0, w1, il, ir, t0, t1); + kll ^= w0; klr ^= w1; + + /* generate KB */ + krll ^= kll; krlr ^= klr; + krrl ^= krl; krrr ^= krr; + CAMELLIA_F(krll, krlr, + CAMELLIA_SIGMA5L, CAMELLIA_SIGMA5R, + w0, w1, il, ir, t0, t1); + krrl ^= w0; krrr ^= w1; + CAMELLIA_F(krrl, krrr, + CAMELLIA_SIGMA6L, CAMELLIA_SIGMA6R, + w0, w1, il, ir, t0, t1); + krll ^= w0; krlr ^= w1; + + /* generate KA dependent subkeys */ + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(6) = kll; subr(6) = klr; + subl(7) = krl; subr(7) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); + subl(14) = kll; subr(14) = klr; + subl(15) = krl; subr(15) = krr; + subl(24) = klr; subr(24) = krl; + subl(25) = krr; subr(25) = kll; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49); + subl(28) = kll; subr(28) = klr; + subl(29) = krl; subr(29) = krr; + + /* generate KB dependent subkeys */ + subl(2) = krll; subr(2) = krlr; + subl(3) = krrl; subr(3) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(10) = krll; subr(10) = krlr; + subl(11) = krrl; subr(11) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(20) = krll; subr(20) = krlr; + subl(21) = krrl; subr(21) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51); + subl(32) = krll; subr(32) = krlr; + subl(33) = krrl; subr(33) = krrr; + + /* absorb kw2 to other subkeys */ + subl(3) ^= subl(1); subr(3) ^= subr(1); + subl(5) ^= subl(1); subr(5) ^= subr(1); + subl(7) ^= subl(1); subr(7) ^= subr(1); + subl(1) ^= subr(1) & ~subr(9); + dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); + subl(11) ^= subl(1); subr(11) ^= subr(1); + subl(13) ^= subl(1); subr(13) ^= subr(1); + subl(15) ^= subl(1); subr(15) ^= subr(1); + subl(1) ^= subr(1) & ~subr(17); + dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); + subl(19) ^= subl(1); subr(19) ^= subr(1); + subl(21) ^= subl(1); subr(21) ^= subr(1); + subl(23) ^= subl(1); subr(23) ^= subr(1); + subl(1) ^= subr(1) & ~subr(25); + dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw); + subl(27) ^= subl(1); subr(27) ^= subr(1); + subl(29) ^= subl(1); subr(29) ^= subr(1); + subl(31) ^= subl(1); subr(31) ^= subr(1); + subl(32) ^= subl(1); subr(32) ^= subr(1); + + /* absorb kw4 to other subkeys */ + kw4l = subl(33); kw4r = subr(33); + subl(30) ^= kw4l; subr(30) ^= kw4r; + subl(28) ^= kw4l; subr(28) ^= kw4r; + subl(26) ^= kw4l; subr(26) ^= kw4r; + kw4l ^= kw4r & ~subr(24); + dw = kw4l & subl(24), kw4r ^= CAMELLIA_RL1(dw); + subl(22) ^= kw4l; subr(22) ^= kw4r; + subl(20) ^= kw4l; subr(20) ^= kw4r; + subl(18) ^= kw4l; subr(18) ^= kw4r; + kw4l ^= kw4r & ~subr(16); + dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); + subl(14) ^= kw4l; subr(14) ^= kw4r; + subl(12) ^= kw4l; subr(12) ^= kw4r; + subl(10) ^= kw4l; subr(10) ^= kw4r; + kw4l ^= kw4r & ~subr(8); + dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); + subl(6) ^= kw4l; subr(6) ^= kw4r; + subl(4) ^= kw4l; subr(4) ^= kw4r; + subl(2) ^= kw4l; subr(2) ^= kw4r; + subl(0) ^= kw4l; subr(0) ^= kw4r; + + /* key XOR is end of F-function */ + CamelliaSubkeyL(0) = subl(0) ^ subl(2); + CamelliaSubkeyR(0) = subr(0) ^ subr(2); + CamelliaSubkeyL(2) = subl(3); + CamelliaSubkeyR(2) = subr(3); + CamelliaSubkeyL(3) = subl(2) ^ subl(4); + CamelliaSubkeyR(3) = subr(2) ^ subr(4); + CamelliaSubkeyL(4) = subl(3) ^ subl(5); + CamelliaSubkeyR(4) = subr(3) ^ subr(5); + CamelliaSubkeyL(5) = subl(4) ^ subl(6); + CamelliaSubkeyR(5) = subr(4) ^ subr(6); + CamelliaSubkeyL(6) = subl(5) ^ subl(7); + CamelliaSubkeyR(6) = subr(5) ^ subr(7); + tl = subl(10) ^ (subr(10) & ~subr(8)); + dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(7) = subl(6) ^ tl; + CamelliaSubkeyR(7) = subr(6) ^ tr; + CamelliaSubkeyL(8) = subl(8); + CamelliaSubkeyR(8) = subr(8); + CamelliaSubkeyL(9) = subl(9); + CamelliaSubkeyR(9) = subr(9); + tl = subl(7) ^ (subr(7) & ~subr(9)); + dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(10) = tl ^ subl(11); + CamelliaSubkeyR(10) = tr ^ subr(11); + CamelliaSubkeyL(11) = subl(10) ^ subl(12); + CamelliaSubkeyR(11) = subr(10) ^ subr(12); + CamelliaSubkeyL(12) = subl(11) ^ subl(13); + CamelliaSubkeyR(12) = subr(11) ^ subr(13); + CamelliaSubkeyL(13) = subl(12) ^ subl(14); + CamelliaSubkeyR(13) = subr(12) ^ subr(14); + CamelliaSubkeyL(14) = subl(13) ^ subl(15); + CamelliaSubkeyR(14) = subr(13) ^ subr(15); + tl = subl(18) ^ (subr(18) & ~subr(16)); + dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(15) = subl(14) ^ tl; + CamelliaSubkeyR(15) = subr(14) ^ tr; + CamelliaSubkeyL(16) = subl(16); + CamelliaSubkeyR(16) = subr(16); + CamelliaSubkeyL(17) = subl(17); + CamelliaSubkeyR(17) = subr(17); + tl = subl(15) ^ (subr(15) & ~subr(17)); + dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(18) = tl ^ subl(19); + CamelliaSubkeyR(18) = tr ^ subr(19); + CamelliaSubkeyL(19) = subl(18) ^ subl(20); + CamelliaSubkeyR(19) = subr(18) ^ subr(20); + CamelliaSubkeyL(20) = subl(19) ^ subl(21); + CamelliaSubkeyR(20) = subr(19) ^ subr(21); + CamelliaSubkeyL(21) = subl(20) ^ subl(22); + CamelliaSubkeyR(21) = subr(20) ^ subr(22); + CamelliaSubkeyL(22) = subl(21) ^ subl(23); + CamelliaSubkeyR(22) = subr(21) ^ subr(23); + tl = subl(26) ^ (subr(26) & ~subr(24)); + dw = tl & subl(24), tr = subr(26) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(23) = subl(22) ^ tl; + CamelliaSubkeyR(23) = subr(22) ^ tr; + CamelliaSubkeyL(24) = subl(24); + CamelliaSubkeyR(24) = subr(24); + CamelliaSubkeyL(25) = subl(25); + CamelliaSubkeyR(25) = subr(25); + tl = subl(23) ^ (subr(23) & ~subr(25)); + dw = tl & subl(25), tr = subr(23) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(26) = tl ^ subl(27); + CamelliaSubkeyR(26) = tr ^ subr(27); + CamelliaSubkeyL(27) = subl(26) ^ subl(28); + CamelliaSubkeyR(27) = subr(26) ^ subr(28); + CamelliaSubkeyL(28) = subl(27) ^ subl(29); + CamelliaSubkeyR(28) = subr(27) ^ subr(29); + CamelliaSubkeyL(29) = subl(28) ^ subl(30); + CamelliaSubkeyR(29) = subr(28) ^ subr(30); + CamelliaSubkeyL(30) = subl(29) ^ subl(31); + CamelliaSubkeyR(30) = subr(29) ^ subr(31); + CamelliaSubkeyL(31) = subl(30); + CamelliaSubkeyR(31) = subr(30); + CamelliaSubkeyL(32) = subl(32) ^ subl(31); + CamelliaSubkeyR(32) = subr(32) ^ subr(31); + + /* apply the inverse of the last half of P-function */ + dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw; + dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw; + dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw; + dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw; + dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw; + dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw; + dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw; + dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw; + dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw; + dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw; + dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw; + dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw; + dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw; + dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw; + dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw; + dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw; + dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw; + dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw; + dw = CamelliaSubkeyL(26) ^ CamelliaSubkeyR(26), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(26) = CamelliaSubkeyL(26) ^ dw, CamelliaSubkeyL(26) = dw; + dw = CamelliaSubkeyL(27) ^ CamelliaSubkeyR(27), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(27) = CamelliaSubkeyL(27) ^ dw, CamelliaSubkeyL(27) = dw; + dw = CamelliaSubkeyL(28) ^ CamelliaSubkeyR(28), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(28) = CamelliaSubkeyL(28) ^ dw, CamelliaSubkeyL(28) = dw; + dw = CamelliaSubkeyL(29) ^ CamelliaSubkeyR(29), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(29) = CamelliaSubkeyL(29) ^ dw, CamelliaSubkeyL(29) = dw; + dw = CamelliaSubkeyL(30) ^ CamelliaSubkeyR(30), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(30) = CamelliaSubkeyL(30) ^ dw, CamelliaSubkeyL(30) = dw; + dw = CamelliaSubkeyL(31) ^ CamelliaSubkeyR(31), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(31) = CamelliaSubkeyL(31) ^ dw,CamelliaSubkeyL(31) = dw; + + return; +} + +void +camellia_setup192(const unsigned char *key, u32 *subkey) +{ + unsigned char kk[32]; + u32 krll, krlr, krrl,krrr; + + memcpy(kk, key, 24); + memcpy((unsigned char *)&krll, key+16,4); + memcpy((unsigned char *)&krlr, key+20,4); + krrl = ~krll; + krrr = ~krlr; + memcpy(kk+24, (unsigned char *)&krrl, 4); + memcpy(kk+28, (unsigned char *)&krrr, 4); + camellia_setup256(kk, subkey); + return; +} + + +/** + * Stuff related to camellia encryption/decryption + * + * "io" must be 4byte aligned and big-endian data. + */ +void +camellia_encrypt128(const u32 *subkey, u32 *io) +{ + u32 il, ir, t0, t1; + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(0); + io[1] ^= CamelliaSubkeyR(0); + /* main iteration */ + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(24); + io[3] ^= CamelliaSubkeyR(24); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +void +camellia_decrypt128(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(24); + io[1] ^= CamelliaSubkeyR(24); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(0); + io[3] ^= CamelliaSubkeyR(0); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +/** + * stuff for 192 and 256bit encryption/decryption + */ +void +camellia_encrypt256(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(0); + io[1] ^= CamelliaSubkeyR(0); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(24),CamelliaSubkeyR(24), + CamelliaSubkeyL(25),CamelliaSubkeyR(25), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(26),CamelliaSubkeyR(26), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(27),CamelliaSubkeyR(27), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(28),CamelliaSubkeyR(28), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(29),CamelliaSubkeyR(29), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(30),CamelliaSubkeyR(30), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(31),CamelliaSubkeyR(31), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(32); + io[3] ^= CamelliaSubkeyR(32); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +void +camellia_decrypt256(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary valiables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(32); + io[1] ^= CamelliaSubkeyR(32); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(31),CamelliaSubkeyR(31), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(30),CamelliaSubkeyR(30), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(29),CamelliaSubkeyR(29), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(28),CamelliaSubkeyR(28), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(27),CamelliaSubkeyR(27), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(26),CamelliaSubkeyR(26), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(25),CamelliaSubkeyR(25), + CamelliaSubkeyL(24),CamelliaSubkeyR(24), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(0); + io[3] ^= CamelliaSubkeyR(0); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +/*** + * + * API for compatibility + */ + +void +Camellia_Ekeygen(const int keyBitLength, + const unsigned char *rawKey, + KEY_TABLE_TYPE keyTable) +{ + switch(keyBitLength) { + case 128: + camellia_setup128(rawKey, keyTable); + break; + case 192: + camellia_setup192(rawKey, keyTable); + break; + case 256: + camellia_setup256(rawKey, keyTable); + break; + default: + break; + } +} + + +void +Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, + unsigned char *ciphertext) +{ + u32 tmp[4]; + + tmp[0] = GETU32(plaintext); + tmp[1] = GETU32(plaintext + 4); + tmp[2] = GETU32(plaintext + 8); + tmp[3] = GETU32(plaintext + 12); + + switch (keyBitLength) { + case 128: + camellia_encrypt128(keyTable, tmp); + break; + case 192: + /* fall through */ + case 256: + camellia_encrypt256(keyTable, tmp); + break; + default: + break; + } + + PUTU32(ciphertext, tmp[0]); + PUTU32(ciphertext + 4, tmp[1]); + PUTU32(ciphertext + 8, tmp[2]); + PUTU32(ciphertext + 12, tmp[3]); +} + +void +Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *ciphertext, + const KEY_TABLE_TYPE keyTable, + unsigned char *plaintext) +{ + u32 tmp[4]; + + tmp[0] = GETU32(ciphertext); + tmp[1] = GETU32(ciphertext + 4); + tmp[2] = GETU32(ciphertext + 8); + tmp[3] = GETU32(ciphertext + 12); + + switch (keyBitLength) { + case 128: + camellia_decrypt128(keyTable, tmp); + break; + case 192: + /* fall through */ + case 256: + camellia_decrypt256(keyTable, tmp); + break; + default: + break; + } + PUTU32(plaintext, tmp[0]); + PUTU32(plaintext + 4, tmp[1]); + PUTU32(plaintext + 8, tmp[2]); + PUTU32(plaintext + 12, tmp[3]); +} + +cam_rval +camellia_blk_len(unsigned int blen, camellia_ctx cx[1]){ + if(blen != 16) return camellia_bad; + return camellia_good; +} + +cam_rval +camellia_enc_key(const unsigned char in_key[], unsigned int klen, + camellia_ctx cx[1]){ + switch(klen){ + case 16: + camellia_setup128(in_key, cx->k_sch); + cx->keybitlen = 128; + break; + case 24: + camellia_setup192(in_key, cx->k_sch); + cx->keybitlen = 192; + break; + case 32: + camellia_setup256(in_key, cx->k_sch); + cx->keybitlen = 256; + break; + default: + return camellia_bad; + } + return camellia_good; +} + +cam_rval +camellia_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], + const camellia_ctx cx[1]){ + Camellia_EncryptBlock(cx->keybitlen, in_blk, cx->k_sch, out_blk); + return camellia_good; +} + +cam_rval +camellia_dec_key(const unsigned char in_key[], unsigned int klen, + camellia_ctx cx[1]){ + switch(klen){ + case 16: + camellia_setup128(in_key, cx->k_sch); + cx->keybitlen = 128; + break; + case 24: + camellia_setup192(in_key, cx->k_sch); + cx->keybitlen = 192; + break; + case 32: + camellia_setup256(in_key, cx->k_sch); + cx->keybitlen = 256; + break; + default: + return camellia_bad; + } + return camellia_good; +} + +cam_rval +camellia_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], + const camellia_ctx cx[1]){ + Camellia_DecryptBlock(cx->keybitlen, in_blk, cx->k_sch, out_blk); + return camellia_good; +} + +#endif /* K5_BUILTIN_CAMELLIA */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/camellia/camellia.h b/krb5-1.21.3/src/lib/crypto/builtin/camellia/camellia.h new file mode 100644 index 00000000..571ba68a --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/camellia/camellia.h @@ -0,0 +1,125 @@ +/* lib/crypto/builtin/camellia/camellia.h - Camellia version 1.2.0 */ +/* + * Copyright (c) 2006,2007,2009 + * NTT (Nippon Telegraph and Telephone Corporation) . 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 as + * the first lines of this file unmodified. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY NTT ``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 NTT 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. + */ + +#ifndef HEADER_CAMELLIA_H +#define HEADER_CAMELLIA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define CAMELLIA_BLOCK_SIZE 16 +#define CAMELLIA_TABLE_BYTE_LEN 272 +#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4) + +#ifndef BLOCK_SIZE +#define BLOCK_SIZE CAMELLIA_BLOCK_SIZE +#endif + +typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; + +/* u32 must be 32bit word */ +typedef uint32_t u32; +typedef uint8_t u8; + +/* For the Kerberos 5 tree, hide the Camellia symbol names. */ +#define camellia_setup128 k5_camellia_setup128 +#define camellia_setup192 k5_camellia_setup192 +#define camellia_setup256 k5_camellia_setup256 +#define camellia_encrypt128 k5_camellia_encrypt128 +#define camellia_decrypt128 k5_camellia_decrypt128 +#define camellia_encrypt256 k5_camellia_encrypt256 +#define camellia_decrypt256 k5_camellia_decrypt256 +#define Camellia_Ekeygen k5_Camellia_Ekeygen +#define Camellia_EncryptBlock k5_Camellia_EncryptBlock +#define Camellia_DecryptBlock k5_Camellia_DecryptBlock + +void camellia_setup128(const unsigned char *key, u32 *subkey); +void camellia_setup192(const unsigned char *key, u32 *subkey); +void camellia_setup256(const unsigned char *key, u32 *subkey); +void camellia_encrypt128(const u32 *subkey, u32 *io); +void camellia_decrypt128(const u32 *subkey, u32 *io); +void camellia_encrypt256(const u32 *subkey, u32 *io); +void camellia_decrypt256(const u32 *subkey, u32 *io); + +void Camellia_Ekeygen(const int keyBitLength, + const unsigned char *rawKey, + KEY_TABLE_TYPE keyTable); + +void Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, + unsigned char *cipherText); + +void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *cipherText, + const KEY_TABLE_TYPE keyTable, + unsigned char *plaintext); + + +typedef uint16_t cam_fret; /* type for function return value */ +#define camellia_good 1 +#define camellia_bad 1 +#ifndef CAMELLIA_DLL /* implement normal or DLL functions */ +#define cam_rval cam_fret +#else +#define cam_rval cam_fret __declspec(dllexport) _stdcall +#endif + +typedef struct /* the Camellia context for encryption */ +{ + uint32_t k_sch[CAMELLIA_TABLE_WORD_LEN]; /* the encryption key schedule */ + int keybitlen; /* bitlength of key */ +} camellia_ctx; + + +/* for Kerberos 5 tree -- hide names! */ +#define camellia_blk_len krb5int_camellia_blk_len +#define camellia_enc_key krb5int_camellia_enc_key +#define camellia_enc_blk krb5int_camellia_enc_blk +#define camellia_dec_key krb5int_camellia_dec_key +#define camellia_dec_blk krb5int_camellia_dec_blk + +cam_rval camellia_blk_len(unsigned int blen, camellia_ctx cx[1]); +cam_rval camellia_enc_key(const unsigned char in_key[], unsigned int klen, + camellia_ctx cx[1]); +cam_rval camellia_enc_blk(const unsigned char in_blk[], + unsigned char out_blk[], + const camellia_ctx cx[1]); +cam_rval camellia_dec_key(const unsigned char in_key[], unsigned int klen, + camellia_ctx cx[1]); +cam_rval camellia_dec_blk(const unsigned char in_blk[], + unsigned char out_blk[], + const camellia_ctx cx[1]); + +#ifdef __cplusplus +} +#endif + +#endif /* HEADER_CAMELLIA_H */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/camellia/deps b/krb5-1.21.3/src/lib/crypto/builtin/camellia/deps new file mode 100644 index 00000000..c7e8ae12 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/camellia/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +camellia.so camellia.po $(OUTPRE)camellia.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h camellia.c camellia.h diff --git a/krb5-1.21.3/src/lib/crypto/builtin/cmac.c b/krb5-1.21.3/src/lib/crypto/builtin/cmac.c new file mode 100644 index 00000000..d719aa25 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/cmac.c @@ -0,0 +1,204 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/cmac.c */ +/* + * Copyright 2010 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +#ifdef K5_BUILTIN_CMAC + +#define BLOCK_SIZE 16 + +static unsigned char const_Rb[BLOCK_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 +}; + +static void +xor_128(unsigned char *a, unsigned char *b, unsigned char *out) +{ + int z; + + for (z = 0; z < BLOCK_SIZE / 4; z++) { + unsigned char *aptr = &a[z * 4]; + unsigned char *bptr = &b[z * 4]; + unsigned char *outptr = &out[z * 4]; + + store_32_n(load_32_n(aptr) ^ load_32_n(bptr), outptr); + } +} + +static void +leftshift_onebit(unsigned char *input, unsigned char *output) +{ + int i; + unsigned char overflow = 0; + + for (i = BLOCK_SIZE - 1; i >= 0; i--) { + output[i] = input[i] << 1; + output[i] |= overflow; + overflow = (input[i] & 0x80) ? 1 : 0; + } +} + +/* Generate subkeys K1 and K2 as described in RFC 4493 figure 2.2. */ +static krb5_error_code +generate_subkey(const struct krb5_enc_provider *enc, + krb5_key key, + unsigned char *K1, + unsigned char *K2) +{ + unsigned char L[BLOCK_SIZE]; + unsigned char tmp[BLOCK_SIZE]; + krb5_data d; + krb5_error_code ret; + + /* L := encrypt(K, const_Zero) */ + memset(L, 0, sizeof(L)); + d = make_data(L, BLOCK_SIZE); + ret = encrypt_block(enc, key, &d); + if (ret != 0) + return ret; + + /* K1 := (MSB(L) == 0) ? L << 1 : (L << 1) XOR const_Rb */ + if ((L[0] & 0x80) == 0) { + leftshift_onebit(L, K1); + } else { + leftshift_onebit(L, tmp); + xor_128(tmp, const_Rb, K1); + } + + /* K2 := (MSB(K1) == 0) ? K1 << 1 : (K1 << 1) XOR const_Rb */ + if ((K1[0] & 0x80) == 0) { + leftshift_onebit(K1, K2); + } else { + leftshift_onebit(K1, tmp); + xor_128(tmp, const_Rb, K2); + } + + return 0; +} + +/* Pad out lastb with a 1 bit followed by 0 bits, placing the result in pad. */ +static void +padding(unsigned char *lastb, unsigned char *pad, int length) +{ + int j; + + /* original last block */ + for (j = 0; j < BLOCK_SIZE; j++) { + if (j < length) { + pad[j] = lastb[j]; + } else if (j == length) { + pad[j] = 0x80; + } else { + pad[j] = 0x00; + } + } +} + +/* + * Implementation of CMAC algorithm. When used with AES, this function + * is compatible with RFC 4493 figure 2.3. + */ +krb5_error_code +krb5int_cmac_checksum(const struct krb5_enc_provider *enc, krb5_key key, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + unsigned char Y[BLOCK_SIZE], M_last[BLOCK_SIZE], padded[BLOCK_SIZE]; + unsigned char K1[BLOCK_SIZE], K2[BLOCK_SIZE]; + unsigned char input[BLOCK_SIZE]; + unsigned int n, i, flag; + krb5_error_code ret; + struct iov_cursor cursor; + size_t length; + krb5_crypto_iov iov[1]; + krb5_data d; + + assert(enc->cbc_mac != NULL); + + if (enc->block_size != BLOCK_SIZE) + return KRB5_BAD_MSIZE; + + length = iov_total_length(data, num_data, TRUE); + + /* Step 1. */ + ret = generate_subkey(enc, key, K1, K2); + if (ret != 0) + return ret; + + /* Step 2. */ + n = (length + BLOCK_SIZE - 1) / BLOCK_SIZE; + + /* Step 3. */ + if (n == 0) { + n = 1; + flag = 0; + } else { + flag = ((length % BLOCK_SIZE) == 0); + } + + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = make_data(input, BLOCK_SIZE); + + /* Step 5 (we'll do step 4 in a bit). */ + memset(Y, 0, BLOCK_SIZE); + d = make_data(Y, BLOCK_SIZE); + + /* Step 6 (all but last block). */ + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, TRUE); + for (i = 0; i < n - 1; i++) { + k5_iov_cursor_get(&cursor, input); + + ret = enc->cbc_mac(key, iov, 1, &d, &d); + if (ret != 0) + return ret; + } + + /* Step 4. */ + k5_iov_cursor_get(&cursor, input); + if (flag) { + /* last block is complete block */ + xor_128(input, K1, M_last); + } else { + padding(input, padded, length % BLOCK_SIZE); + xor_128(padded, K2, M_last); + } + + /* Step 6 (last block). */ + iov[0].data = make_data(M_last, BLOCK_SIZE); + ret = enc->cbc_mac(key, iov, 1, &d, &d); + if (ret != 0) + return ret; + + assert(output->length >= d.length); + + output->length = d.length; + memcpy(output->data, d.data, d.length); + + return 0; +} + +#endif /* K5_BUILTIN_CMAC */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/deps b/krb5-1.21.3/src/lib/crypto/builtin/deps new file mode 100644 index 00000000..b6b53380 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/deps @@ -0,0 +1,47 @@ +# +# Generated makefile dependencies follow. +# +cmac.so cmac.po $(OUTPRE)cmac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cmac.c +hmac.so hmac.po $(OUTPRE)hmac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + hmac.c +kdf.so kdf.po $(OUTPRE)kdf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kdf.c +pbkdf2.so pbkdf2.po $(OUTPRE)pbkdf2.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + pbkdf2.c diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/ISSUES b/krb5-1.21.3/src/lib/crypto/builtin/des/ISSUES new file mode 100644 index 00000000..15789110 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/ISSUES @@ -0,0 +1,13 @@ +Issues to be addressed for src/lib/crypto/des: -*- text -*- + + +"const" could be used in more places + + +Array types are used in calling interfaces. Under ANSI C, a value of +type "arraytype *" cannot be assigned to a variable of type "const +arraytype *", so we get compilation warnings. + +Possible fix: Rewrite internal interfaces to not use arrays this way. +Provide external routines compatible with old API, but not using +const? diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/Makefile.in b/krb5-1.21.3/src/lib/crypto/builtin/des/Makefile.in new file mode 100644 index 00000000..397ac87e --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/Makefile.in @@ -0,0 +1,82 @@ +mydir=lib$(S)crypto$(S)builtin$(S)des +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES=-I$(srcdir)/../../krb $(CRYPTO_IMPL_CFLAGS) + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\des +##DOS##OBJFILE = ..\..\$(OUTPRE)des.lst + +STLIBOBJS=\ + d3_aead.o \ + d3_kysched.o \ + des_keys.o \ + f_aead.o \ + f_cksum.o \ + f_parity.o \ + f_sched.o \ + f_tables.o \ + key_sched.o \ + weak_key.o + +OBJS= $(OUTPRE)d3_aead.$(OBJEXT) \ + $(OUTPRE)d3_kysched.$(OBJEXT) \ + $(OUTPRE)des_keys.$(OBJEXT) \ + $(OUTPRE)f_aead.$(OBJEXT) \ + $(OUTPRE)f_cksum.$(OBJEXT) \ + $(OUTPRE)f_parity.$(OBJEXT) \ + $(OUTPRE)f_sched.$(OBJEXT) \ + $(OUTPRE)f_tables.$(OBJEXT) \ + $(OUTPRE)key_sched.$(OBJEXT) \ + $(OUTPRE)weak_key.$(OBJEXT) + +SRCS= $(srcdir)/d3_aead.c \ + $(srcdir)/d3_kysched.c \ + $(srcdir)/des_keys.c \ + $(srcdir)/f_aead.c \ + $(srcdir)/f_cksum.c \ + $(srcdir)/f_parity.c \ + $(srcdir)/f_sched.c \ + $(srcdir)/f_tables.c \ + $(srcdir)/key_sched.c \ + $(srcdir)/weak_key.c + +EXTRADEPSRCS = $(srcdir)/destest.c $(srcdir)/f_cbc.c $(srcdir)/t_verify.c + +##DOS##LIBOBJS = $(OBJS) + +TOBJS = $(OUTPRE)key_sched.$(OBJEXT) $(OUTPRE)f_sched.$(OBJEXT) \ + $(OUTPRE)f_cbc.$(OBJEXT) $(OUTPRE)f_tables.$(OBJEXT) \ + $(OUTPRE)f_cksum.$(OBJEXT) + +verify$(EXEEXT): t_verify.$(OBJEXT) $(TOBJS) f_parity.$(OBJEXT) \ + $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB) + $(CC_LINK) -o $@ t_verify.$(OBJEXT) $(TOBJS) f_parity.$(OBJEXT) \ + $(COM_ERR_LIB) $(SUPPORT_LIB) + +destest$(EXEEXT): destest.$(OBJEXT) $(TOBJS) $(SUPPORT_DEPLIB) + $(CC_LINK) -o $@ destest.$(OBJEXT) $(TOBJS) $(SUPPORT_LIB) + +all-unix: all-libobjs + +check-unix: check-unix-@CRYPTO_BUILTIN_TESTS@ +check-unix-no: +check-unix-yes: verify destest + $(RUN_TEST) ./verify -z + $(RUN_TEST) ./verify -m + $(RUN_TEST) ./verify + $(RUN_TEST) ./destest < $(srcdir)/keytest.data + +includes: depend + +depend: $(SRCS) + +check-windows: + +clean: + $(RM) destest.$(OBJEXT) destest$(EXEEXT) verify$(EXEEXT) \ + t_verify.$(OBJEXT) $(TOBJS) + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/d3_aead.c b/krb5-1.21.3/src/lib/crypto/builtin/des/d3_aead.c new file mode 100644 index 00000000..fb83f73b --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/d3_aead.c @@ -0,0 +1,137 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2008 by the Massachusetts Institute of Technology. + * Copyright 1995 by Richard P. Basch. All Rights Reserved. + * Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Richard P. Basch, + * Lehman Brothers and M.I.T. make no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "crypto_int.h" +#include "des_int.h" +#include "f_tables.h" + +#ifdef K5_BUILTIN_DES + +void +krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp1, *kp2, *kp3; + const unsigned char *ip; + struct iov_cursor cursor; + unsigned char block[MIT_DES_BLOCK_LENGTH]; + + /* Get key pointers here. These won't need to be reinitialized. */ + kp1 = (const unsigned DES_INT32 *)ks1; + kp2 = (const unsigned DES_INT32 *)ks2; + kp3 = (const unsigned DES_INT32 *)ks3; + + /* Initialize left and right with the contents of the initial vector. */ + ip = (ivec != NULL) ? ivec : mit_des_zeroblock; + left = load_32_be(ip); + right = load_32_be(ip + 4); + + k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE); + while (k5_iov_cursor_get(&cursor, block)) { + /* xor this block with the previous ciphertext. */ + left ^= load_32_be(block); + right ^= load_32_be(block + 4); + + /* Encrypt what we have and store it back into block. */ + DES_DO_ENCRYPT(left, right, kp1); + DES_DO_DECRYPT(left, right, kp2); + DES_DO_ENCRYPT(left, right, kp3); + store_32_be(left, block); + store_32_be(right, block + 4); + + k5_iov_cursor_put(&cursor, block); + } + + if (ivec != NULL) { + store_32_be(left, ivec); + store_32_be(right, ivec + 4); + } +} + +void +krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp1, *kp2, *kp3; + const unsigned char *ip; + unsigned DES_INT32 ocipherl, ocipherr; + unsigned DES_INT32 cipherl, cipherr; + struct iov_cursor cursor; + unsigned char block[MIT_DES_BLOCK_LENGTH]; + + /* Get key pointers here. These won't need to be reinitialized. */ + kp1 = (const unsigned DES_INT32 *)ks1; + kp2 = (const unsigned DES_INT32 *)ks2; + kp3 = (const unsigned DES_INT32 *)ks3; + + /* + * Decrypting is harder than encrypting because of + * the necessity of remembering a lot more things. + * Should think about this a little more... + */ + + /* Prime the old cipher with ivec.*/ + ip = (ivec != NULL) ? ivec : mit_des_zeroblock; + ocipherl = load_32_be(ip); + ocipherr = load_32_be(ip + 4); + + k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE); + while (k5_iov_cursor_get(&cursor, block)) { + /* Split this block into left and right. */ + cipherl = left = load_32_be(block); + cipherr = right = load_32_be(block + 4); + + /* Decrypt and xor with the old cipher to get plain text. */ + DES_DO_DECRYPT(left, right, kp3); + DES_DO_ENCRYPT(left, right, kp2); + DES_DO_DECRYPT(left, right, kp1); + left ^= ocipherl; + right ^= ocipherr; + + /* Store the encrypted halves back into block. */ + store_32_be(left, block); + store_32_be(right, block + 4); + + /* Save current cipher block halves. */ + ocipherl = cipherl; + ocipherr = cipherr; + + k5_iov_cursor_put(&cursor, block); + } + + if (ivec != NULL) { + store_32_be(ocipherl, ivec); + store_32_be(ocipherr, ivec + 4); + } +} + +#endif /* K5_BUILTIN_DES */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/d3_kysched.c b/krb5-1.21.3/src/lib/crypto/builtin/des/d3_kysched.c new file mode 100644 index 00000000..55fb9449 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/d3_kysched.c @@ -0,0 +1,55 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1995 by Richard P. Basch. All Rights Reserved. + * Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Richard P. Basch, + * Lehman Brothers and M.I.T. make no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "crypto_int.h" +#include "des_int.h" + +#ifdef K5_BUILTIN_DES + +int +mit_des3_key_sched(mit_des3_cblock k, mit_des3_key_schedule schedule) +{ + mit_des_make_key_sched(k[0],schedule[0]); + mit_des_make_key_sched(k[1],schedule[1]); + mit_des_make_key_sched(k[2],schedule[2]); + + if (!mit_des_check_key_parity(k[0])) /* bad parity --> return -1 */ + return(-1); + if (mit_des_is_weak_key(k[0])) + return(-2); + + if (!mit_des_check_key_parity(k[1])) + return(-1); + if (mit_des_is_weak_key(k[1])) + return(-2); + + if (!mit_des_check_key_parity(k[2])) + return(-1); + if (mit_des_is_weak_key(k[2])) + return(-2); + + /* if key was good, return 0 */ + return 0; +} + +#endif /* K5_BUILTIN_DES */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/deps b/krb5-1.21.3/src/lib/crypto/builtin/des/deps new file mode 100644 index 00000000..1c1239d6 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/deps @@ -0,0 +1,146 @@ +# +# Generated makefile dependencies follow. +# +d3_aead.so d3_aead.po $(OUTPRE)d3_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + d3_aead.c des_int.h f_tables.h +d3_kysched.so d3_kysched.po $(OUTPRE)d3_kysched.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h d3_kysched.c des_int.h +des_keys.so des_keys.po $(OUTPRE)des_keys.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des_int.h des_keys.c +f_aead.so f_aead.po $(OUTPRE)f_aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + des_int.h f_aead.c f_tables.h +f_cksum.so f_cksum.po $(OUTPRE)f_cksum.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + des_int.h f_cksum.c f_tables.h +f_parity.so f_parity.po $(OUTPRE)f_parity.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des_int.h f_parity.c +f_sched.so f_sched.po $(OUTPRE)f_sched.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + des_int.h f_sched.c +f_tables.so f_tables.po $(OUTPRE)f_tables.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des_int.h f_tables.c \ + f_tables.h +key_sched.so key_sched.po $(OUTPRE)key_sched.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des_int.h key_sched.c +weak_key.so weak_key.po $(OUTPRE)weak_key.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des_int.h weak_key.c +destest.so destest.po $(OUTPRE)destest.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des_int.h destest.c +f_cbc.so f_cbc.po $(OUTPRE)f_cbc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des_int.h f_cbc.c \ + f_tables.h +t_verify.so t_verify.po $(OUTPRE)t_verify.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + des_int.h t_verify.c diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/des_int.h b/krb5-1.21.3/src/lib/crypto/builtin/des/des_int.h new file mode 100644 index 00000000..f8dc6b29 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/des_int.h @@ -0,0 +1,285 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/des_int.h */ +/* + * Copyright 1987, 1988, 1990, 2002 by the Massachusetts Institute of + * Technology. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* Private include file for the Data Encryption Standard library. */ + +/* only do the whole thing once */ +#ifndef DES_INTERNAL_DEFS +#define DES_INTERNAL_DEFS + +#include "k5-int.h" +/* + * Begin "mit-des.h" + */ +#ifndef KRB5_MIT_DES__ +#define KRB5_MIT_DES__ + +#if defined(__MACH__) && defined(__APPLE__) +#include +#include +#if TARGET_RT_MAC_CFM +#error "Use KfM 4.0 SDK headers for CFM compilation." +#endif +#if defined(DEPRECATED_IN_MAC_OS_X_VERSION_10_5) && !defined(KRB5_SUPRESS_DEPRECATED_WARNINGS) +#define KRB5INT_DES_DEPRECATED DEPRECATED_IN_MAC_OS_X_VERSION_10_5 +#endif +#endif /* defined(__MACH__) && defined(__APPLE__) */ + +/* Macro to add deprecated attribute to DES types and functions */ +/* Currently only defined on macOS 10.5 and later. */ +#ifndef KRB5INT_DES_DEPRECATED +#define KRB5INT_DES_DEPRECATED +#endif + +#include + +#if UINT_MAX >= 0xFFFFFFFFUL +#define DES_INT32 int +#define DES_UINT32 unsigned int +#else +#define DES_INT32 long +#define DES_UINT32 unsigned long +#endif + +typedef unsigned char des_cblock[8] /* crypto-block size */ +KRB5INT_DES_DEPRECATED; + +/* + * Key schedule. + * + * This used to be + * + * typedef struct des_ks_struct { + * union { DES_INT32 pad; des_cblock _;} __; + * } des_key_schedule[16]; + * + * but it would cause trouble if DES_INT32 were ever more than 4 + * bytes. The reason is that all the encryption functions cast it to + * (DES_INT32 *), and treat it as if it were DES_INT32[32]. If + * 2*sizeof(DES_INT32) is ever more than sizeof(des_cblock), the + * caller-allocated des_key_schedule will be overflowed by the key + * scheduling functions. We can't assume that every platform will + * have an exact 32-bit int, and nothing should be looking inside a + * des_key_schedule anyway. + */ +typedef struct des_ks_struct { DES_INT32 _[2]; } des_key_schedule[16] +KRB5INT_DES_DEPRECATED; + +typedef des_cblock mit_des_cblock; +typedef des_key_schedule mit_des_key_schedule; + +/* Triple-DES structures */ +typedef mit_des_cblock mit_des3_cblock[3]; +typedef mit_des_key_schedule mit_des3_key_schedule[3]; + +#define MIT_DES_ENCRYPT 1 +#define MIT_DES_DECRYPT 0 + +typedef struct mit_des_ran_key_seed { + krb5_encrypt_block eblock; + krb5_data sequence; +} mit_des_random_state; + +/* the first byte of the key is already in the keyblock */ + +#define MIT_DES_BLOCK_LENGTH (8*sizeof(krb5_octet)) +/* This used to be 8*sizeof(krb5_octet) */ +#define MIT_DES_KEYSIZE 8 + +#define MIT_DES_CBC_CKSUM_LENGTH (4*sizeof(krb5_octet)) + +#endif /* KRB5_MIT_DES__ */ +/* + * End "mit-des.h" + */ + +/* afsstring2key.c */ +krb5_error_code mit_afs_string_to_key(krb5_keyblock *keyblock, + const krb5_data *data, + const krb5_data *salt); +char *mit_afs_crypt(const char *pw, const char *salt, char *iobuf); + +/* f_cksum.c */ +unsigned long mit_des_cbc_cksum(const krb5_octet *, krb5_octet *, + unsigned long, const mit_des_key_schedule, + const krb5_octet *); + +/* f_cbc.c (used by test programs) */ +int +mit_des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out, + unsigned long length, const mit_des_key_schedule schedule, + const mit_des_cblock ivec, int enc); + +#define mit_des_zeroblock krb5int_c_mit_des_zeroblock +extern const mit_des_cblock mit_des_zeroblock; + +/* fin_rndkey.c */ +krb5_error_code mit_des_finish_random_key(const krb5_encrypt_block *, + krb5_pointer *); + +/* finish_key.c */ +krb5_error_code mit_des_finish_key(krb5_encrypt_block *); + +/* init_rkey.c */ +krb5_error_code mit_des_init_random_key(const krb5_encrypt_block *, + const krb5_keyblock *, + krb5_pointer *); + +/* key_parity.c */ +void mit_des_fixup_key_parity(mit_des_cblock); +int mit_des_check_key_parity(mit_des_cblock); + +/* key_sched.c */ +int mit_des_key_sched(mit_des_cblock, mit_des_key_schedule); + +/* process_ky.c */ +krb5_error_code mit_des_process_key(krb5_encrypt_block *, + const krb5_keyblock *); + +/* random_key.c */ +krb5_error_code mit_des_random_key(const krb5_encrypt_block *, + krb5_pointer, krb5_keyblock **); + +/* string2key.c */ +krb5_error_code mit_des_string_to_key(const krb5_encrypt_block *, + krb5_keyblock *, const krb5_data *, + const krb5_data *); +krb5_error_code mit_des_string_to_key_int(krb5_keyblock *, const krb5_data *, + const krb5_data *); + +/* weak_key.c */ +int mit_des_is_weak_key(mit_des_cblock); + +/* cmb_keys.c */ +krb5_error_code mit_des_combine_subkeys(const krb5_keyblock *, + const krb5_keyblock *, + krb5_keyblock **); + +/* f_pcbc.c */ +int mit_des_pcbc_encrypt(); + +/* f_sched.c */ +int mit_des_make_key_sched(mit_des_cblock, mit_des_key_schedule); + + +/* misc.c */ +extern void swap_bits(char *); +extern unsigned long long_swap_bits(unsigned long); +extern unsigned long swap_six_bits_to_ansi(unsigned long); +extern unsigned long swap_four_bits_to_ansi(unsigned long); +extern unsigned long swap_bit_pos_1(unsigned long); +extern unsigned long swap_bit_pos_0(unsigned long); +extern unsigned long swap_bit_pos_0_to_ansi(unsigned long); +extern unsigned long rev_swap_bit_pos_0(unsigned long); +extern unsigned long swap_byte_bits(unsigned long); +extern unsigned long swap_long_bytes_bit_number(unsigned long); +#ifdef FILE +/* XXX depends on FILE being a #define! */ +extern void test_set(FILE *, const char *, int, const char *, int); +#endif + +void +krb5int_des3_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec); + +void +krb5int_des3_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule ks1, + const mit_des_key_schedule ks2, + const mit_des_key_schedule ks3, + mit_des_cblock ivec); + +void +krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec); + +void +krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec); + +void +krb5int_des_cbc_mac(const krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule schedule, mit_des_cblock ivec, + mit_des_cblock out); + +/* d3_procky.c */ +krb5_error_code mit_des3_process_key(krb5_encrypt_block *eblock, + const krb5_keyblock *keyblock); + +/* d3_kysched.c */ +int mit_des3_key_sched(mit_des3_cblock key, mit_des3_key_schedule schedule); + +/* d3_str2ky.c */ +krb5_error_code mit_des3_string_to_key(const krb5_encrypt_block *eblock, + krb5_keyblock *keyblock, + const krb5_data *data, + const krb5_data *salt); + +/* u_nfold.c */ +krb5_error_code mit_des_n_fold(const krb5_octet *input, const size_t in_len, + krb5_octet *output, const size_t out_len); + +/* u_rn_key.c */ +int mit_des_is_weak_keyblock(krb5_keyblock *keyblock); + +void mit_des_fixup_keyblock_parity(krb5_keyblock *keyblock); + +krb5_error_code mit_des_set_random_generator_seed(const krb5_data *seed, + krb5_pointer random_state); + +krb5_error_code mit_des_set_random_sequence_number(const krb5_data *sequence, + krb5_pointer random_state); +#endif /*DES_INTERNAL_DEFS*/ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/des_keys.c b/krb5-1.21.3/src/lib/crypto/builtin/des/des_keys.c new file mode 100644 index 00000000..027b09d7 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/des_keys.c @@ -0,0 +1,38 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/des_keys.c - Key functions used by Kerberos code */ +/* + * Copyright (C) 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" +#include "des_int.h" + +#ifdef K5_BUILTIN_DES_KEY_PARITY + +void +k5_des_fixup_key_parity(unsigned char *keybits) +{ + mit_des_fixup_key_parity(keybits); +} + +#endif /* K5_BUILTIN_DES_KEY_PARITY */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/destest.c b/krb5-1.21.3/src/lib/crypto/builtin/des/destest.c new file mode 100644 index 00000000..52114304 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/destest.c @@ -0,0 +1,240 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/destest.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* Test a DES implementation against known inputs & outputs. */ + +#include "des_int.h" +#include +#include + +void convert (char *, unsigned char []); + +void des_cblock_print_file (mit_des_cblock, FILE *); + +krb5_octet zeroblock[8] = {0,0,0,0,0,0,0,0}; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + char block1[17], block2[17], block3[17]; + /* Force tests of unaligned accesses. */ + union { unsigned char c[8*4+3]; long l; } u; + unsigned char *ioblocks = u.c; + unsigned char *input = ioblocks+1; + unsigned char *output = ioblocks+10; + unsigned char *output2 = ioblocks+19; + unsigned char *key = ioblocks+27; + mit_des_key_schedule sched; + int num = 0; + int retval; + + int error = 0; + + while (scanf("%16s %16s %16s", block1, block2, block3) == 3) { + convert(block1, key); + convert(block2, input); + convert(block3, output); + + retval = mit_des_key_sched(key, sched); + if (retval) { + fprintf(stderr, "des test: can't process key: %d\n", retval); + fprintf(stderr, "des test: %s %s %s\n", block1, block2, block3); + exit(1); + } + mit_des_cbc_encrypt((const mit_des_cblock *) input, + (mit_des_cblock *) output2, 8, + sched, zeroblock, 1); + + if (memcmp((char *)output2, (char *)output, 8)) { + fprintf(stderr, + "DES ENCRYPT ERROR, key %s, text %s, real cipher %s, computed cyphertext %02X%02X%02X%02X%02X%02X%02X%02X\n", + block1, block2, block3, + output2[0],output2[1],output2[2],output2[3], + output2[4],output2[5],output2[6],output2[7]); + error++; + } + + /* + * Now try decrypting.... + */ + mit_des_cbc_encrypt((const mit_des_cblock *) output, + (mit_des_cblock *) output2, 8, + sched, zeroblock, 0); + + if (memcmp((char *)output2, (char *)input, 8)) { + fprintf(stderr, + "DES DECRYPT ERROR, key %s, text %s, real cipher %s, computed cleartext %02X%02X%02X%02X%02X%02X%02X%02X\n", + block1, block2, block3, + output2[0],output2[1],output2[2],output2[3], + output2[4],output2[5],output2[6],output2[7]); + error++; + } + + num++; + } + + if (error) + printf("destest: failed to pass the test\n"); + else + printf("destest: %d tests passed successfully\n", num); + + exit( (error > 256 && error % 256) ? 1 : error); +} + +int value[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, -1, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, +}; + +void +convert(text, cblock) + char *text; + unsigned char cblock[]; +{ + int i; + for (i = 0; i < 8; i++) { + if (!isascii((unsigned char)text[i * 2])) + abort (); + if (value[(int) text[i*2]] == -1 || value[(int) text[i*2+1]] == -1) { + printf("Bad value byte %d in %s\n", i, text); + exit(1); + } + cblock[i] = 16*value[(int) text[i*2]] + value[(int) text[i*2+1]]; + } + return; +} + +/* + * Fake out the DES library, for the purposes of testing. + */ + +int +mit_des_is_weak_key(key) + mit_des_cblock key; +{ + return 0; /* fake it out for testing */ +} + +void +des_cblock_print_file(x, fp) + mit_des_cblock x; + FILE *fp; +{ + unsigned char *y = (unsigned char *) x; + int i = 0; + fprintf(fp," 0x { "); + + while (i++ < 8) { + fprintf(fp,"%x",*y++); + if (i < 8) + fprintf(fp,", "); + } + fprintf(fp," }"); +} + + +#define smask(step) ((1<>step)&smask(step))) +#define parity_char(x) pstep(pstep(pstep((x),4),2),1) + +/* + * des_check_key_parity: returns true iff key has the correct des parity. + * See des_fix_key_parity for the definition of + * correct des parity. + */ +int +mit_des_check_key_parity(key) + mit_des_cblock key; +{ + unsigned int i; + + for (i=0; i decrypt, else encrypt */ + Key_schedule schedule; /* addr of key schedule */ + +This is the low level routine that encrypts or decrypts a single 8-byte +block in electronic code book mode. Always transforms the input +data into the output data. + +If encrypt is non-zero, the input (cleartext) is encrypted into the +output (ciphertext) using the specified key_schedule, pre-set via "des_set_key". + +If encrypt is zero, the input (now ciphertext) is decrypted into +the output (now cleartext). + +Input and output may be the same space. + +Does not return any meaningful value. Void is not used for compatibility +with other compilers. + +/* -------------------------------------------------------------- */ + +int + cbc_encrypt(input,output,length,schedule,ivec,encrypt) + + C_Block *input; /* ptr to input data */ + C_Block *output; /* ptr to output data */ + int length; /* desired length, in bytes */ + Key_schedule schedule; /* addr of precomputed schedule */ + C_Block *ivec; /* pointer to 8 byte initialization + * vector + */ + int encrypt /* 0 ==> decrypt; else encrypt*/ + + + If encrypt is non-zero, the routine cipher-block-chain encrypts + the INPUT (cleartext) into the OUTPUT (ciphertext) using the provided + key schedule and initialization vector. If the length is not an integral + multiple of eight bytes, the last block is copied to a temp and zero + filled (highest addresses). The output is ALWAYS an integral multiple + of eight bytes. + + If encrypt is zero, the routine cipher-block chain decrypts the INPUT + (ciphertext) into the OUTPUT (cleartext) using the provided key schedule + and initialization vector. Decryption ALWAYS operates on integral + multiples of 8 bytes, so will round the length provided up to the + appropriate multiple. Consequently, it will always produce the rounded-up + number of bytes of output cleartext. The application must determine if + the output cleartext was zero-padded due to cleartext lengths not integral + multiples of 8. + + No errors or meaningful value are returned. Void is not used for + compatibility with other compilers. + + +/* cbc checksum (MAC) only routine ---------------------------------------- */ +int + cbc_cksum(input,output,length,schedule,ivec) + + C_Block *input; /* >= length bytes of inputtext */ + C_Block *output; /* >= length bytes of outputtext */ + int length; /* in bytes */ + Key_schedule schedule; /* precomputed key schedule */ + C_Block *ivec; /* 8 bytes of ivec */ + + + Produces a cryptographic checksum, 8 bytes, by cipher-block-chain + encrypting the input, discarding the ciphertext output, and only retaining + the last ciphertext 8-byte block. Uses the provided key schedule and ivec. + The input is effectively zero-padded to an integral multiple of + eight bytes, though the original input is not modified. + + No meaningful value is returned. Void is not used for compatibility + with other compilers. + + +/* random_key ----------------------------------------*/ +int + random_key(key) + + C_Block *key; + + The start for the random number generated is set from the current time + in microseconds, then the random number generator is invoked + to create an eight byte output key (not a schedule). The key + generated is set to odd parity per FIPS spec. + + The caller must supply space for the output key, pointed to + by "*key", then after getting a new key, call the des_set_key() + routine when needed. + + No meaningful value is returned. Void is not used for compatibility + with other compilers. + + +/* string_to_key --------------------------------------------*/ + +int + string_to_key(str,key) + char *str; + C_Block *key; + + This routines converts an arbitrary length, null terminated string + to an 8 byte DES key, with each byte parity set to odd, per FIPS spec. + + The algorithm is as follows: + +| Take the first 8 bytes and remove the parity (leaving 56 bits). +| Do the same for the second 8 bytes, and the third, etc. Do this for +| as many sets of 8 bytes as necessary, filling in the remainder of the +| last set with nulls. Fold the second set back on the first (i.e. bit +| 0 over bit 55, and bit 55 over bit 0). Fold the third over the second +| (bit 0 of the third set is now over bit 0 of the first set). Repeat +| until you have done this to all sets. Xor the folded sets. Break the +| result into 8 7 bit bytes, and generate odd parity for each byte. You +| now have 64 bits. Note that DES takes a 64 bit key, and uses only the +| non parity bits. + + +/* read_password -------------------------------------------*/ + +read_password(k,prompt,verify) + C_Block *k; + char *prompt; + int verify; + +This routine issues the supplied prompt, turns off echo, if possible, and +reads an input string. If verify is non-zero, it does it again, for use +in applications such as changing a password. If verify is non-zero, both +versions are compared, and the input is requested repeatedly until they +match. Then, the input string is mapped into a valid DES key, internally +using the string_to_key routine. The newly created key is copied to the +area pointed to by parameter "k". + +No meaningful value is returned. If an error occurs trying to manipulate +the terminal echo, the routine forces the process to exit. + +/* get_line ------------------------*/ +long get_line(p,max) + char *p; + long max; + +Reads input characters from standard input until either a newline appears or +else the max length is reached. The characters read are stuffed into +the string pointed to, which will always be null terminated. The newline +is not inserted in the string. The max parameter includes the byte needed +for the null terminator, so allocate and pass one more than the maximum +string length desired. diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/f_aead.c b/krb5-1.21.3/src/lib/crypto/builtin/des/f_aead.c new file mode 100644 index 00000000..f8877358 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/f_aead.c @@ -0,0 +1,177 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2008 by the Massachusetts Institute of Technology. + * Copyright 1995 by Richard P. Basch. All Rights Reserved. + * Copyright 1995 by Lehman Brothers, Inc. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Richard P. Basch, Lehman Brothers and M.I.T. not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Richard P. Basch, + * Lehman Brothers and M.I.T. make no representations about the suitability + * of this software for any purpose. It is provided "as is" without + * express or implied warranty. + */ + +#include "crypto_int.h" +#include "des_int.h" +#include "f_tables.h" + +#ifdef K5_BUILTIN_DES + +const mit_des_cblock mit_des_zeroblock /* = all zero */; + +void +krb5int_des_cbc_encrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + struct iov_cursor cursor; + unsigned char block[MIT_DES_BLOCK_LENGTH]; + + /* Get key pointer here. This won't need to be reinitialized. */ + kp = (const unsigned DES_INT32 *)schedule; + + /* Initialize left and right with the contents of the initial vector. */ + ip = (ivec != NULL) ? ivec : mit_des_zeroblock; + left = load_32_be(ip); + right = load_32_be(ip + 4); + + k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE); + while (k5_iov_cursor_get(&cursor, block)) { + /* Decompose this block and xor it with the previous ciphertext. */ + left ^= load_32_be(block); + right ^= load_32_be(block + 4); + + /* Encrypt what we have and put back into block. */ + DES_DO_ENCRYPT(left, right, kp); + store_32_be(left, block); + store_32_be(right, block + 4); + + k5_iov_cursor_put(&cursor, block); + } + + if (ivec != NULL) { + store_32_be(left, ivec); + store_32_be(right, ivec + 4); + } +} + +void +krb5int_des_cbc_decrypt(krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule schedule, + mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + unsigned DES_INT32 ocipherl, ocipherr; + unsigned DES_INT32 cipherl, cipherr; + struct iov_cursor cursor; + unsigned char block[MIT_DES_BLOCK_LENGTH]; + + /* Get key pointer here. This won't need to be reinitialized. */ + kp = (const unsigned DES_INT32 *)schedule; + + /* + * Decrypting is harder than encrypting because of + * the necessity of remembering a lot more things. + * Should think about this a little more... + */ + + /* Prime the old cipher with ivec. */ + ip = (ivec != NULL) ? ivec : mit_des_zeroblock; + ocipherl = load_32_be(ip); + ocipherr = load_32_be(ip + 4); + + k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, FALSE); + while (k5_iov_cursor_get(&cursor, block)) { + /* Split this block into left and right. */ + cipherl = left = load_32_be(block); + cipherr = right = load_32_be(block + 4); + + /* Decrypt and xor with the old cipher to get plain text. */ + DES_DO_DECRYPT(left, right, kp); + left ^= ocipherl; + right ^= ocipherr; + + /* Store the encrypted halves back into block. */ + store_32_be(left, block); + store_32_be(right, block + 4); + + /* Save current cipher block halves. */ + ocipherl = cipherl; + ocipherr = cipherr; + + k5_iov_cursor_put(&cursor, block); + } + + if (ivec != NULL) { + store_32_be(ocipherl, ivec); + store_32_be(ocipherr, ivec + 4); + } +} + +void +krb5int_des_cbc_mac(const krb5_crypto_iov *data, unsigned long num_data, + const mit_des_key_schedule schedule, mit_des_cblock ivec, + mit_des_cblock out) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + struct iov_cursor cursor; + unsigned char block[MIT_DES_BLOCK_LENGTH]; + + /* Get key pointer here. This won't need to be reinitialized. */ + kp = (const unsigned DES_INT32 *)schedule; + + /* Initialize left and right with the contents of the initial vector. */ + ip = (ivec != NULL) ? ivec : mit_des_zeroblock; + left = load_32_be(ip); + right = load_32_be(ip + 4); + + k5_iov_cursor_init(&cursor, data, num_data, MIT_DES_BLOCK_LENGTH, TRUE); + while (k5_iov_cursor_get(&cursor, block)) { + /* Decompose this block and xor it with the previous ciphertext. */ + left ^= load_32_be(block); + right ^= load_32_be(block + 4); + + /* Encrypt what we have. */ + DES_DO_ENCRYPT(left, right, kp); + } + + /* Output the final ciphertext block. */ + store_32_be(left, out); + store_32_be(right, out + 4); +} + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) +void krb5int_des_do_encrypt_2 (unsigned DES_INT32 *left, + unsigned DES_INT32 *right, + const unsigned DES_INT32 *kp) +{ + DES_DO_ENCRYPT_1 (*left, *right, kp); +} + +void krb5int_des_do_decrypt_2 (unsigned DES_INT32 *left, + unsigned DES_INT32 *right, + const unsigned DES_INT32 *kp) +{ + DES_DO_DECRYPT_1 (*left, *right, kp); +} +#endif + +#endif /* K5_BUILTIN_DES */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/f_cbc.c b/krb5-1.21.3/src/lib/crypto/builtin/des/f_cbc.c new file mode 100644 index 00000000..84d5382f --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/f_cbc.c @@ -0,0 +1,256 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/f_cbc.c */ +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * CBC functions; used only by the test programs at this time. (krb5 uses the + * functions in f_aead.c instead.) + */ + +/* + * des_cbc_encrypt.c - an implementation of the DES cipher function in cbc mode + */ +#include "des_int.h" +#include "f_tables.h" + +/* + * des_cbc_encrypt - {en,de}crypt a stream in CBC mode + */ + +/* + * This routine performs DES cipher-block-chaining operation, either + * encrypting from cleartext to ciphertext, if encrypt != 0 or + * decrypting from ciphertext to cleartext, if encrypt == 0. + * + * The key schedule is passed as an arg, as well as the cleartext or + * ciphertext. The cleartext and ciphertext should be in host order. + * + * NOTE-- the output is ALWAYS an multiple of 8 bytes long. If not + * enough space was provided, your program will get trashed. + * + * For encryption, the cleartext string is null padded, at the end, to + * an integral multiple of eight bytes. + * + * For decryption, the ciphertext will be used in integral multiples + * of 8 bytes, but only the first "length" bytes returned into the + * cleartext. + */ + +const mit_des_cblock mit_des_zeroblock /* = all zero */; + +static void +des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out, + unsigned long length, const mit_des_key_schedule schedule, + const mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + unsigned char *op; + + /* + * Get key pointer here. This won't need to be reinitialized + */ + kp = (const unsigned DES_INT32 *)schedule; + + /* + * Initialize left and right with the contents of the initial + * vector. + */ + ip = ivec; + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + + /* + * Suitably initialized, now work the length down 8 bytes + * at a time. + */ + ip = *in; + op = *out; + while (length > 0) { + /* + * Get more input, xor it in. If the length is + * greater than or equal to 8 this is straight + * forward. Otherwise we have to fart around. + */ + if (length >= 8) { + unsigned DES_INT32 temp; + GET_HALF_BLOCK(temp, ip); + left ^= temp; + GET_HALF_BLOCK(temp, ip); + right ^= temp; + length -= 8; + } else { + /* + * Oh, shoot. We need to pad the + * end with zeroes. Work backwards + * to do this. + */ + ip += (int) length; + switch(length) { + case 7: + right ^= (*(--ip) & FF_UINT32) << 8; + case 6: + right ^= (*(--ip) & FF_UINT32) << 16; + case 5: + right ^= (*(--ip) & FF_UINT32) << 24; + case 4: + left ^= *(--ip) & FF_UINT32; + case 3: + left ^= (*(--ip) & FF_UINT32) << 8; + case 2: + left ^= (*(--ip) & FF_UINT32) << 16; + case 1: + left ^= (*(--ip) & FF_UINT32) << 24; + break; + } + length = 0; + } + + /* + * Encrypt what we have + */ + DES_DO_ENCRYPT(left, right, kp); + + /* + * Copy the results out + */ + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + } +} + +static void +des_cbc_decrypt(const mit_des_cblock *in, mit_des_cblock *out, + unsigned long length, const mit_des_key_schedule schedule, + const mit_des_cblock ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + unsigned char *op; + unsigned DES_INT32 ocipherl, ocipherr; + unsigned DES_INT32 cipherl, cipherr; + + /* + * Get key pointer here. This won't need to be reinitialized + */ + kp = (const unsigned DES_INT32 *)schedule; + + /* + * Decrypting is harder than encrypting because of + * the necessity of remembering a lot more things. + * Should think about this a little more... + */ + + if (length <= 0) + return; + + /* + * Prime the old cipher with ivec. + */ + ip = ivec; + GET_HALF_BLOCK(ocipherl, ip); + GET_HALF_BLOCK(ocipherr, ip); + + /* + * Now do this in earnest until we run out of length. + */ + ip = *in; + op = *out; + for (;;) { /* check done inside loop */ + /* + * Read a block from the input into left and + * right. Save this cipher block for later. + */ + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + cipherl = left; + cipherr = right; + + /* + * Decrypt this. + */ + DES_DO_DECRYPT(left, right, kp); + + /* + * Xor with the old cipher to get plain + * text. Output 8 or less bytes of this. + */ + left ^= ocipherl; + right ^= ocipherr; + if (length > 8) { + length -= 8; + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + /* + * Save current cipher block here + */ + ocipherl = cipherl; + ocipherr = cipherr; + } else { + /* + * Trouble here. Start at end of output, + * work backwards. + */ + op += (int) length; + switch(length) { + case 8: + *(--op) = (unsigned char) (right & 0xff); + case 7: + *(--op) = (unsigned char) ((right >> 8) & 0xff); + case 6: + *(--op) = (unsigned char) ((right >> 16) & 0xff); + case 5: + *(--op) = (unsigned char) ((right >> 24) & 0xff); + case 4: + *(--op) = (unsigned char) (left & 0xff); + case 3: + *(--op) = (unsigned char) ((left >> 8) & 0xff); + case 2: + *(--op) = (unsigned char) ((left >> 16) & 0xff); + case 1: + *(--op) = (unsigned char) ((left >> 24) & 0xff); + break; + } + break; /* we're done */ + } + } +} + +int +mit_des_cbc_encrypt(const mit_des_cblock *in, mit_des_cblock *out, + unsigned long length, const mit_des_key_schedule schedule, + const mit_des_cblock ivec, int enc) +{ + /* + * Deal with encryption and decryption separately. + */ + if (enc) + des_cbc_encrypt(in, out, length, schedule, ivec); + else + des_cbc_decrypt(in, out, length, schedule, ivec); + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/f_cksum.c b/krb5-1.21.3/src/lib/crypto/builtin/des/f_cksum.c new file mode 100644 index 00000000..615a947f --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/f_cksum.c @@ -0,0 +1,141 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/f_cksum.c */ +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* DES implementation donated by Dennis Ferguson */ + +/* + * des_cbc_cksum.c - compute an 8 byte checksum using DES in CBC mode + */ +#include "crypto_int.h" +#include "des_int.h" +#include "f_tables.h" + +#ifdef K5_BUILTIN_DES + +/* + * This routine performs DES cipher-block-chaining checksum operation, + * a.k.a. Message Authentication Code. It ALWAYS encrypts from input + * to a single 64 bit output MAC checksum. + * + * The key schedule is passed as an arg, as well as the cleartext or + * ciphertext. The cleartext and ciphertext should be in host order. + * + * NOTE-- the output is ALWAYS 8 bytes long. If not enough space was + * provided, your program will get trashed. + * + * The input is null padded, at the end (highest addr), to an integral + * multiple of eight bytes. + */ + +unsigned long +mit_des_cbc_cksum(const krb5_octet *in, krb5_octet *out, + unsigned long length, const mit_des_key_schedule schedule, + const krb5_octet *ivec) +{ + unsigned DES_INT32 left, right; + const unsigned DES_INT32 *kp; + const unsigned char *ip; + unsigned char *op; + DES_INT32 len; + + /* + * Initialize left and right with the contents of the initial + * vector. + */ + ip = ivec; + GET_HALF_BLOCK(left, ip); + GET_HALF_BLOCK(right, ip); + + /* + * Suitably initialized, now work the length down 8 bytes + * at a time. + */ + ip = in; + len = length; + while (len > 0) { + /* + * Get more input, xor it in. If the length is + * greater than or equal to 8 this is straight + * forward. Otherwise we have to fart around. + */ + if (len >= 8) { + unsigned DES_INT32 temp; + GET_HALF_BLOCK(temp, ip); + left ^= temp; + GET_HALF_BLOCK(temp, ip); + right ^= temp; + len -= 8; + } else { + /* + * Oh, shoot. We need to pad the + * end with zeroes. Work backwards + * to do this. + */ + ip += (int) len; + switch(len) { + case 7: + right ^= (*(--ip) & FF_UINT32) << 8; + case 6: + right ^= (*(--ip) & FF_UINT32) << 16; + case 5: + right ^= (*(--ip) & FF_UINT32) << 24; + case 4: + left ^= *(--ip) & FF_UINT32; + case 3: + left ^= (*(--ip) & FF_UINT32) << 8; + case 2: + left ^= (*(--ip) & FF_UINT32) << 16; + case 1: + left ^= (*(--ip) & FF_UINT32) << 24; + break; + } + len = 0; + } + + /* + * Encrypt what we have + */ + kp = (const unsigned DES_INT32 *)schedule; + DES_DO_ENCRYPT(left, right, kp); + } + + /* + * Done. Left and right have the checksum. Put it into + * the output. + */ + op = out; + PUT_HALF_BLOCK(left, op); + PUT_HALF_BLOCK(right, op); + + /* + * Return right. I'll bet the MIT code returns this + * inconsistantly (with the low order byte of the checksum + * not always in the low order byte of the DES_INT32). We won't. + */ + return right & 0xFFFFFFFFUL; +} + +#endif /* K5_BUILTIN_DES */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/f_parity.c b/krb5-1.21.3/src/lib/crypto/builtin/des/f_parity.c new file mode 100644 index 00000000..a658878f --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/f_parity.c @@ -0,0 +1,64 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * These routines check and fix parity of encryption keys for the DES + * algorithm. + * + * They are a replacement for routines in key_parity.c, that don't require + * the table building that they do. + * + * Mark Eichin -- Cygnus Support + */ + +#include "crypto_int.h" +#include "des_int.h" + +#ifdef K5_BUILTIN_DES_KEY_PARITY + +/* + * des_fixup_key_parity: Forces odd parity per byte; parity is bits + * 8,16,...64 in des order, implies 0, 8, 16, ... + * vax order. + */ +#define smask(step) ((1<>step)&smask(step))) +#define parity_char(x) pstep(pstep(pstep((x),4),2),1) + +void +mit_des_fixup_key_parity(mit_des_cblock key) +{ + unsigned int i; + for (i=0; i> 29) & 0x7] + | (PC1_CL[(tmp >> 21) & 0x7] << 1) + | (PC1_CL[(tmp >> 13) & 0x7] << 2) + | (PC1_CL[(tmp >> 5) & 0x7] << 3); + d = PC1_DL[(tmp >> 25) & 0xf] + | (PC1_DL[(tmp >> 17) & 0xf] << 1) + | (PC1_DL[(tmp >> 9) & 0xf] << 2) + | (PC1_DL[(tmp >> 1) & 0xf] << 3); + + tmp = load_32_be(k), k += 4; + + c |= PC1_CR[(tmp >> 28) & 0xf] + | (PC1_CR[(tmp >> 20) & 0xf] << 1) + | (PC1_CR[(tmp >> 12) & 0xf] << 2) + | (PC1_CR[(tmp >> 4) & 0xf] << 3); + d |= PC1_DR[(tmp >> 25) & 0x7] + | (PC1_DR[(tmp >> 17) & 0x7] << 1) + | (PC1_DR[(tmp >> 9) & 0x7] << 2) + | (PC1_DR[(tmp >> 1) & 0x7] << 3); + } + + { + /* + * Need several temporaries in here + */ + unsigned DES_INT32 ltmp, rtmp; + unsigned DES_INT32 *k; + int two_bit_shifts; + int i; + /* + * Now iterate to compute the key schedule. Note that we + * record the entire set of subkeys in 6 bit chunks since + * they are used that way. At 6 bits/char, we need + * 48/6 char's/subkey * 16 subkeys/encryption == 128 bytes. + * The schedule must be this big. + */ + k = (unsigned DES_INT32 *)schedule; + two_bit_shifts = TWO_BIT_SHIFTS; + for (i = 16; i > 0; i--) { + /* + * Do the rotation. One bit and two bit rotations + * are done separately. Note C and D are 28 bits. + */ + if (two_bit_shifts & 0x1) { + c = ((c << 2) & 0xffffffc) | (c >> 26); + d = ((d << 2) & 0xffffffc) | (d >> 26); + } else { + c = ((c << 1) & 0xffffffe) | (c >> 27); + d = ((d << 1) & 0xffffffe) | (d >> 27); + } + two_bit_shifts >>= 1; + + /* + * Apply permutted choice 2 to C to get the first + * 24 bits worth of keys. Note that bits 9, 18, 22 + * and 25 (using DES numbering) in C are unused. The + * shift-mask stuff is done to delete these bits from + * the indices, since this cuts the table size in half. + * + * The table is torqued, by the way. If the standard + * byte order for this (high to low order) is 1234, + * the table actually gives us 4132. + */ + ltmp = PC2_C[0][((c >> 22) & 0x3f)] + | PC2_C[1][((c >> 15) & 0xf) | ((c >> 16) & 0x30)] + | PC2_C[2][((c >> 4) & 0x3) | ((c >> 9) & 0x3c)] + | PC2_C[3][((c ) & 0x7) | ((c >> 4) & 0x38)]; + /* + * Apply permutted choice 2 to D to get the other half. + * Here, bits 7, 10, 15 and 26 go unused. The sqeezing + * actually turns out to be cheaper here. + * + * This table is similarly torqued. If the standard + * byte order is 5678, the table has the bytes permuted + * to give us 7685. + */ + rtmp = PC2_D[0][((d >> 22) & 0x3f)] + | PC2_D[1][((d >> 14) & 0xf) | ((d >> 15) & 0x30)] + | PC2_D[2][((d >> 7) & 0x3f)] + | PC2_D[3][((d ) & 0x3) | ((d >> 1) & 0x3c)]; + + /* + * Make up two words of the key schedule, with a + * byte order which is convenient for the DES + * inner loop. The high order (first) word will + * hold bytes 7135 (high to low order) while the + * second holds bytes 4682. + */ + *k++ = (ltmp & 0x00ffff00) | (rtmp & 0xff0000ff); + *k++ = (ltmp & 0xff0000ff) | (rtmp & 0x00ffff00); + } + } + return (0); +} + +#endif /* K5_BUILTIN_DES */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/f_tables.c b/krb5-1.21.3/src/lib/crypto/builtin/des/f_tables.c new file mode 100644 index 00000000..e50ab1fc --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/f_tables.c @@ -0,0 +1,375 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/f_tables.c */ +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* DES implementation donated by Dennis Ferguson */ + +/* + * des_tables.c - precomputed tables used for the DES cipher function + */ + +/* + * Include the header file so something will complain if the + * declarations get out of sync + */ +#include "crypto_int.h" +#include "des_int.h" +#include "f_tables.h" + +#ifdef K5_BUILTIN_DES + +/* + * These tables may be declared const if you want. Many compilers + * don't support this, though. + */ + +/* + * The DES algorithm which uses these is intended to be fairly speedy + * at the expense of some memory. All the standard hacks are used. + * The S boxes and the P permutation are precomputed into one table. + * The E box never actually appears explicitly since it is easy to apply + * this algorithmically as needed. The initial permutation and final + * (inverse initial) permutation are computed from tables designed to + * permute one byte at a time. This should run pretty fast on machines + * with 32 bit words and bit field/multiple bit shift instructions which + * are fast. + */ + +/* + * The initial permutation array. This is used to compute both the + * left and the right halves of the initial permutation using bytes + * from words made from the following operations: + * + * ((left & 0x55555555) << 1) | (right & 0x55555555) for left half + * (left & 0xaaaaaaaa) | ((right & 0xaaaaaaaa) >> 1) for right half + * + * The scheme is that we index into the table using each byte. The + * result from the high order byte is or'd with the result from the + * next byte shifted left once is or'd with the result from the next + * byte shifted left twice if or'd with the result from the low order + * byte shifted left by three. Clear? + */ + +const unsigned DES_INT32 des_IP_table[256] = { + 0x00000000, 0x00000010, 0x00000001, 0x00000011, + 0x00001000, 0x00001010, 0x00001001, 0x00001011, + 0x00000100, 0x00000110, 0x00000101, 0x00000111, + 0x00001100, 0x00001110, 0x00001101, 0x00001111, + 0x00100000, 0x00100010, 0x00100001, 0x00100011, + 0x00101000, 0x00101010, 0x00101001, 0x00101011, + 0x00100100, 0x00100110, 0x00100101, 0x00100111, + 0x00101100, 0x00101110, 0x00101101, 0x00101111, + 0x00010000, 0x00010010, 0x00010001, 0x00010011, + 0x00011000, 0x00011010, 0x00011001, 0x00011011, + 0x00010100, 0x00010110, 0x00010101, 0x00010111, + 0x00011100, 0x00011110, 0x00011101, 0x00011111, + 0x00110000, 0x00110010, 0x00110001, 0x00110011, + 0x00111000, 0x00111010, 0x00111001, 0x00111011, + 0x00110100, 0x00110110, 0x00110101, 0x00110111, + 0x00111100, 0x00111110, 0x00111101, 0x00111111, + 0x10000000, 0x10000010, 0x10000001, 0x10000011, + 0x10001000, 0x10001010, 0x10001001, 0x10001011, + 0x10000100, 0x10000110, 0x10000101, 0x10000111, + 0x10001100, 0x10001110, 0x10001101, 0x10001111, + 0x10100000, 0x10100010, 0x10100001, 0x10100011, + 0x10101000, 0x10101010, 0x10101001, 0x10101011, + 0x10100100, 0x10100110, 0x10100101, 0x10100111, + 0x10101100, 0x10101110, 0x10101101, 0x10101111, + 0x10010000, 0x10010010, 0x10010001, 0x10010011, + 0x10011000, 0x10011010, 0x10011001, 0x10011011, + 0x10010100, 0x10010110, 0x10010101, 0x10010111, + 0x10011100, 0x10011110, 0x10011101, 0x10011111, + 0x10110000, 0x10110010, 0x10110001, 0x10110011, + 0x10111000, 0x10111010, 0x10111001, 0x10111011, + 0x10110100, 0x10110110, 0x10110101, 0x10110111, + 0x10111100, 0x10111110, 0x10111101, 0x10111111, + 0x01000000, 0x01000010, 0x01000001, 0x01000011, + 0x01001000, 0x01001010, 0x01001001, 0x01001011, + 0x01000100, 0x01000110, 0x01000101, 0x01000111, + 0x01001100, 0x01001110, 0x01001101, 0x01001111, + 0x01100000, 0x01100010, 0x01100001, 0x01100011, + 0x01101000, 0x01101010, 0x01101001, 0x01101011, + 0x01100100, 0x01100110, 0x01100101, 0x01100111, + 0x01101100, 0x01101110, 0x01101101, 0x01101111, + 0x01010000, 0x01010010, 0x01010001, 0x01010011, + 0x01011000, 0x01011010, 0x01011001, 0x01011011, + 0x01010100, 0x01010110, 0x01010101, 0x01010111, + 0x01011100, 0x01011110, 0x01011101, 0x01011111, + 0x01110000, 0x01110010, 0x01110001, 0x01110011, + 0x01111000, 0x01111010, 0x01111001, 0x01111011, + 0x01110100, 0x01110110, 0x01110101, 0x01110111, + 0x01111100, 0x01111110, 0x01111101, 0x01111111, + 0x11000000, 0x11000010, 0x11000001, 0x11000011, + 0x11001000, 0x11001010, 0x11001001, 0x11001011, + 0x11000100, 0x11000110, 0x11000101, 0x11000111, + 0x11001100, 0x11001110, 0x11001101, 0x11001111, + 0x11100000, 0x11100010, 0x11100001, 0x11100011, + 0x11101000, 0x11101010, 0x11101001, 0x11101011, + 0x11100100, 0x11100110, 0x11100101, 0x11100111, + 0x11101100, 0x11101110, 0x11101101, 0x11101111, + 0x11010000, 0x11010010, 0x11010001, 0x11010011, + 0x11011000, 0x11011010, 0x11011001, 0x11011011, + 0x11010100, 0x11010110, 0x11010101, 0x11010111, + 0x11011100, 0x11011110, 0x11011101, 0x11011111, + 0x11110000, 0x11110010, 0x11110001, 0x11110011, + 0x11111000, 0x11111010, 0x11111001, 0x11111011, + 0x11110100, 0x11110110, 0x11110101, 0x11110111, + 0x11111100, 0x11111110, 0x11111101, 0x11111111 +}; + +/* + * The final permutation array. Like the IP array, used + * to compute both the left and right results from the bytes + * of words computed from: + * + * ((left & 0x0f0f0f0f) << 4) | (right & 0x0f0f0f0f) for left result + * (left & 0xf0f0f0f0) | ((right & 0xf0f0f0f0) >> 4) for right result + * + * The result from the high order byte is shifted left 6 bits and + * or'd with the result from the next byte shifted left 4 bits, which + * is or'd with the result from the next byte shifted left 2 bits, + * which is or'd with the result from the low byte. + */ +const unsigned DES_INT32 des_FP_table[256] = { + 0x00000000, 0x02000000, 0x00020000, 0x02020000, + 0x00000200, 0x02000200, 0x00020200, 0x02020200, + 0x00000002, 0x02000002, 0x00020002, 0x02020002, + 0x00000202, 0x02000202, 0x00020202, 0x02020202, + 0x01000000, 0x03000000, 0x01020000, 0x03020000, + 0x01000200, 0x03000200, 0x01020200, 0x03020200, + 0x01000002, 0x03000002, 0x01020002, 0x03020002, + 0x01000202, 0x03000202, 0x01020202, 0x03020202, + 0x00010000, 0x02010000, 0x00030000, 0x02030000, + 0x00010200, 0x02010200, 0x00030200, 0x02030200, + 0x00010002, 0x02010002, 0x00030002, 0x02030002, + 0x00010202, 0x02010202, 0x00030202, 0x02030202, + 0x01010000, 0x03010000, 0x01030000, 0x03030000, + 0x01010200, 0x03010200, 0x01030200, 0x03030200, + 0x01010002, 0x03010002, 0x01030002, 0x03030002, + 0x01010202, 0x03010202, 0x01030202, 0x03030202, + 0x00000100, 0x02000100, 0x00020100, 0x02020100, + 0x00000300, 0x02000300, 0x00020300, 0x02020300, + 0x00000102, 0x02000102, 0x00020102, 0x02020102, + 0x00000302, 0x02000302, 0x00020302, 0x02020302, + 0x01000100, 0x03000100, 0x01020100, 0x03020100, + 0x01000300, 0x03000300, 0x01020300, 0x03020300, + 0x01000102, 0x03000102, 0x01020102, 0x03020102, + 0x01000302, 0x03000302, 0x01020302, 0x03020302, + 0x00010100, 0x02010100, 0x00030100, 0x02030100, + 0x00010300, 0x02010300, 0x00030300, 0x02030300, + 0x00010102, 0x02010102, 0x00030102, 0x02030102, + 0x00010302, 0x02010302, 0x00030302, 0x02030302, + 0x01010100, 0x03010100, 0x01030100, 0x03030100, + 0x01010300, 0x03010300, 0x01030300, 0x03030300, + 0x01010102, 0x03010102, 0x01030102, 0x03030102, + 0x01010302, 0x03010302, 0x01030302, 0x03030302, + 0x00000001, 0x02000001, 0x00020001, 0x02020001, + 0x00000201, 0x02000201, 0x00020201, 0x02020201, + 0x00000003, 0x02000003, 0x00020003, 0x02020003, + 0x00000203, 0x02000203, 0x00020203, 0x02020203, + 0x01000001, 0x03000001, 0x01020001, 0x03020001, + 0x01000201, 0x03000201, 0x01020201, 0x03020201, + 0x01000003, 0x03000003, 0x01020003, 0x03020003, + 0x01000203, 0x03000203, 0x01020203, 0x03020203, + 0x00010001, 0x02010001, 0x00030001, 0x02030001, + 0x00010201, 0x02010201, 0x00030201, 0x02030201, + 0x00010003, 0x02010003, 0x00030003, 0x02030003, + 0x00010203, 0x02010203, 0x00030203, 0x02030203, + 0x01010001, 0x03010001, 0x01030001, 0x03030001, + 0x01010201, 0x03010201, 0x01030201, 0x03030201, + 0x01010003, 0x03010003, 0x01030003, 0x03030003, + 0x01010203, 0x03010203, 0x01030203, 0x03030203, + 0x00000101, 0x02000101, 0x00020101, 0x02020101, + 0x00000301, 0x02000301, 0x00020301, 0x02020301, + 0x00000103, 0x02000103, 0x00020103, 0x02020103, + 0x00000303, 0x02000303, 0x00020303, 0x02020303, + 0x01000101, 0x03000101, 0x01020101, 0x03020101, + 0x01000301, 0x03000301, 0x01020301, 0x03020301, + 0x01000103, 0x03000103, 0x01020103, 0x03020103, + 0x01000303, 0x03000303, 0x01020303, 0x03020303, + 0x00010101, 0x02010101, 0x00030101, 0x02030101, + 0x00010301, 0x02010301, 0x00030301, 0x02030301, + 0x00010103, 0x02010103, 0x00030103, 0x02030103, + 0x00010303, 0x02010303, 0x00030303, 0x02030303, + 0x01010101, 0x03010101, 0x01030101, 0x03030101, + 0x01010301, 0x03010301, 0x01030301, 0x03030301, + 0x01010103, 0x03010103, 0x01030103, 0x03030103, + 0x01010303, 0x03010303, 0x01030303, 0x03030303 +}; + + +/* + * The SP table is actually the S boxes and the P permutation + * table combined. This table is actually reordered from the + * spec, to match the order of key application we follow. + */ +const unsigned DES_INT32 des_SP_table[8][64] = { + { + 0x00100000, 0x02100001, 0x02000401, 0x00000000, /* 7 */ + 0x00000400, 0x02000401, 0x00100401, 0x02100400, + 0x02100401, 0x00100000, 0x00000000, 0x02000001, + 0x00000001, 0x02000000, 0x02100001, 0x00000401, + 0x02000400, 0x00100401, 0x00100001, 0x02000400, + 0x02000001, 0x02100000, 0x02100400, 0x00100001, + 0x02100000, 0x00000400, 0x00000401, 0x02100401, + 0x00100400, 0x00000001, 0x02000000, 0x00100400, + 0x02000000, 0x00100400, 0x00100000, 0x02000401, + 0x02000401, 0x02100001, 0x02100001, 0x00000001, + 0x00100001, 0x02000000, 0x02000400, 0x00100000, + 0x02100400, 0x00000401, 0x00100401, 0x02100400, + 0x00000401, 0x02000001, 0x02100401, 0x02100000, + 0x00100400, 0x00000000, 0x00000001, 0x02100401, + 0x00000000, 0x00100401, 0x02100000, 0x00000400, + 0x02000001, 0x02000400, 0x00000400, 0x00100001, + }, + { + 0x00808200, 0x00000000, 0x00008000, 0x00808202, /* 1 */ + 0x00808002, 0x00008202, 0x00000002, 0x00008000, + 0x00000200, 0x00808200, 0x00808202, 0x00000200, + 0x00800202, 0x00808002, 0x00800000, 0x00000002, + 0x00000202, 0x00800200, 0x00800200, 0x00008200, + 0x00008200, 0x00808000, 0x00808000, 0x00800202, + 0x00008002, 0x00800002, 0x00800002, 0x00008002, + 0x00000000, 0x00000202, 0x00008202, 0x00800000, + 0x00008000, 0x00808202, 0x00000002, 0x00808000, + 0x00808200, 0x00800000, 0x00800000, 0x00000200, + 0x00808002, 0x00008000, 0x00008200, 0x00800002, + 0x00000200, 0x00000002, 0x00800202, 0x00008202, + 0x00808202, 0x00008002, 0x00808000, 0x00800202, + 0x00800002, 0x00000202, 0x00008202, 0x00808200, + 0x00000202, 0x00800200, 0x00800200, 0x00000000, + 0x00008002, 0x00008200, 0x00000000, 0x00808002, + }, + { + 0x00000104, 0x04010100, 0x00000000, 0x04010004, /* 3 */ + 0x04000100, 0x00000000, 0x00010104, 0x04000100, + 0x00010004, 0x04000004, 0x04000004, 0x00010000, + 0x04010104, 0x00010004, 0x04010000, 0x00000104, + 0x04000000, 0x00000004, 0x04010100, 0x00000100, + 0x00010100, 0x04010000, 0x04010004, 0x00010104, + 0x04000104, 0x00010100, 0x00010000, 0x04000104, + 0x00000004, 0x04010104, 0x00000100, 0x04000000, + 0x04010100, 0x04000000, 0x00010004, 0x00000104, + 0x00010000, 0x04010100, 0x04000100, 0x00000000, + 0x00000100, 0x00010004, 0x04010104, 0x04000100, + 0x04000004, 0x00000100, 0x00000000, 0x04010004, + 0x04000104, 0x00010000, 0x04000000, 0x04010104, + 0x00000004, 0x00010104, 0x00010100, 0x04000004, + 0x04010000, 0x04000104, 0x00000104, 0x04010000, + 0x00010104, 0x00000004, 0x04010004, 0x00010100, + }, + { + 0x00000080, 0x01040080, 0x01040000, 0x21000080, /* 5 */ + 0x00040000, 0x00000080, 0x20000000, 0x01040000, + 0x20040080, 0x00040000, 0x01000080, 0x20040080, + 0x21000080, 0x21040000, 0x00040080, 0x20000000, + 0x01000000, 0x20040000, 0x20040000, 0x00000000, + 0x20000080, 0x21040080, 0x21040080, 0x01000080, + 0x21040000, 0x20000080, 0x00000000, 0x21000000, + 0x01040080, 0x01000000, 0x21000000, 0x00040080, + 0x00040000, 0x21000080, 0x00000080, 0x01000000, + 0x20000000, 0x01040000, 0x21000080, 0x20040080, + 0x01000080, 0x20000000, 0x21040000, 0x01040080, + 0x20040080, 0x00000080, 0x01000000, 0x21040000, + 0x21040080, 0x00040080, 0x21000000, 0x21040080, + 0x01040000, 0x00000000, 0x20040000, 0x21000000, + 0x00040080, 0x01000080, 0x20000080, 0x00040000, + 0x00000000, 0x20040000, 0x01040080, 0x20000080, + }, + { + 0x80401000, 0x80001040, 0x80001040, 0x00000040, /* 4 */ + 0x00401040, 0x80400040, 0x80400000, 0x80001000, + 0x00000000, 0x00401000, 0x00401000, 0x80401040, + 0x80000040, 0x00000000, 0x00400040, 0x80400000, + 0x80000000, 0x00001000, 0x00400000, 0x80401000, + 0x00000040, 0x00400000, 0x80001000, 0x00001040, + 0x80400040, 0x80000000, 0x00001040, 0x00400040, + 0x00001000, 0x00401040, 0x80401040, 0x80000040, + 0x00400040, 0x80400000, 0x00401000, 0x80401040, + 0x80000040, 0x00000000, 0x00000000, 0x00401000, + 0x00001040, 0x00400040, 0x80400040, 0x80000000, + 0x80401000, 0x80001040, 0x80001040, 0x00000040, + 0x80401040, 0x80000040, 0x80000000, 0x00001000, + 0x80400000, 0x80001000, 0x00401040, 0x80400040, + 0x80001000, 0x00001040, 0x00400000, 0x80401000, + 0x00000040, 0x00400000, 0x00001000, 0x00401040, + }, + { + 0x10000008, 0x10200000, 0x00002000, 0x10202008, /* 6 */ + 0x10200000, 0x00000008, 0x10202008, 0x00200000, + 0x10002000, 0x00202008, 0x00200000, 0x10000008, + 0x00200008, 0x10002000, 0x10000000, 0x00002008, + 0x00000000, 0x00200008, 0x10002008, 0x00002000, + 0x00202000, 0x10002008, 0x00000008, 0x10200008, + 0x10200008, 0x00000000, 0x00202008, 0x10202000, + 0x00002008, 0x00202000, 0x10202000, 0x10000000, + 0x10002000, 0x00000008, 0x10200008, 0x00202000, + 0x10202008, 0x00200000, 0x00002008, 0x10000008, + 0x00200000, 0x10002000, 0x10000000, 0x00002008, + 0x10000008, 0x10202008, 0x00202000, 0x10200000, + 0x00202008, 0x10202000, 0x00000000, 0x10200008, + 0x00000008, 0x00002000, 0x10200000, 0x00202008, + 0x00002000, 0x00200008, 0x10002008, 0x00000000, + 0x10202000, 0x10000000, 0x00200008, 0x10002008, + }, + { + 0x08000820, 0x00000800, 0x00020000, 0x08020820, /* 8 */ + 0x08000000, 0x08000820, 0x00000020, 0x08000000, + 0x00020020, 0x08020000, 0x08020820, 0x00020800, + 0x08020800, 0x00020820, 0x00000800, 0x00000020, + 0x08020000, 0x08000020, 0x08000800, 0x00000820, + 0x00020800, 0x00020020, 0x08020020, 0x08020800, + 0x00000820, 0x00000000, 0x00000000, 0x08020020, + 0x08000020, 0x08000800, 0x00020820, 0x00020000, + 0x00020820, 0x00020000, 0x08020800, 0x00000800, + 0x00000020, 0x08020020, 0x00000800, 0x00020820, + 0x08000800, 0x00000020, 0x08000020, 0x08020000, + 0x08020020, 0x08000000, 0x00020000, 0x08000820, + 0x00000000, 0x08020820, 0x00020020, 0x08000020, + 0x08020000, 0x08000800, 0x08000820, 0x00000000, + 0x08020820, 0x00020800, 0x00020800, 0x00000820, + 0x00000820, 0x00020020, 0x08000000, 0x08020800, + }, + { + 0x40084010, 0x40004000, 0x00004000, 0x00084010, /* 2 */ + 0x00080000, 0x00000010, 0x40080010, 0x40004010, + 0x40000010, 0x40084010, 0x40084000, 0x40000000, + 0x40004000, 0x00080000, 0x00000010, 0x40080010, + 0x00084000, 0x00080010, 0x40004010, 0x00000000, + 0x40000000, 0x00004000, 0x00084010, 0x40080000, + 0x00080010, 0x40000010, 0x00000000, 0x00084000, + 0x00004010, 0x40084000, 0x40080000, 0x00004010, + 0x00000000, 0x00084010, 0x40080010, 0x00080000, + 0x40004010, 0x40080000, 0x40084000, 0x00004000, + 0x40080000, 0x40004000, 0x00000010, 0x40084010, + 0x00084010, 0x00000010, 0x00004000, 0x40000000, + 0x00004010, 0x40084000, 0x00080000, 0x40000010, + 0x00080010, 0x40004010, 0x40000010, 0x00080010, + 0x00084000, 0x00000000, 0x40004000, 0x00004010, + 0x40000000, 0x40080010, 0x40084010, 0x00084000 + }, +}; + +#endif /* K5_BUILTIN_DES */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/f_tables.h b/krb5-1.21.3/src/lib/crypto/builtin/des/f_tables.h new file mode 100644 index 00000000..fc91b566 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/f_tables.h @@ -0,0 +1,285 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/f_tables.h */ +/* + * Copyright (C) 1990 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * DES implementation donated by Dennis Ferguson + */ + +/* + * des_tables.h - declarations to import the DES tables, used internally + * by some of the library routines. + */ +#ifndef __DES_TABLES_H__ +#define __DES_TABLES_H__ /* nothing */ + +#include "k5-platform.h" +/* + * These may be declared const if you wish. Be sure to change the + * declarations in des_tables.c as well. + */ +extern const unsigned DES_INT32 des_IP_table[256]; +extern const unsigned DES_INT32 des_FP_table[256]; +extern const unsigned DES_INT32 des_SP_table[8][64]; + +/* + * Use standard shortforms to reference these to save typing + */ +#define IP des_IP_table +#define FP des_FP_table +#define SP des_SP_table + +#ifdef DEBUG +#define DEB(foofraw) printf foofraw +#else +#define DEB(foofraw) /* nothing */ +#endif + +/* + * Code to do a DES round using the tables. Note that the E expansion + * is easy to compute algorithmically, especially if done out-of-order. + * Take a look at its form and compare it to everything involving temp + * below. Since SP[0-7] don't have any bits in common set it is okay + * to do the successive xor's. + * + * Note too that the SP table has been reordered to match the order of + * the keys (if the original order of SP was 12345678, the reordered + * table is 71354682). This is unnecessary, but was done since some + * compilers seem to like you going through the matrix from beginning + * to end. + * + * There is a difference in the best way to do this depending on whether + * one is encrypting or decrypting. If encrypting we move forward through + * the keys and hence should move forward through the table. If decrypting + * we go back. Part of the need for this comes from trying to emulate + * existing software which generates a single key schedule and uses it + * both for encrypting and decrypting. Generating separate encryption + * and decryption key schedules would allow one to use the same code + * for both. + * + * left, right and temp should be unsigned DES_INT32 values. left and right + * should be the high and low order parts of the cipher block at the + * current stage of processing (this makes sense if you read the spec). + * kp should be an unsigned DES_INT32 pointer which points at the current + * set of subkeys in the key schedule. It is advanced to the next set + * (i.e. by 8 bytes) when this is done. + * + * This occurs in the innermost loop of the DES function. The four + * variables should really be in registers. + * + * When using this, the inner loop of the DES function might look like: + * + * for (i = 0; i < 8; i++) { + * DES_SP_{EN,DE}CRYPT_ROUND(left, right, temp, kp); + * DES_SP_{EN,DE}CRYPT_ROUND(right, left, temp, kp); + * } + * + * Note the trick above. You are supposed to do 16 rounds, swapping + * left and right at the end of each round. By doing two rounds at + * a time and swapping left and right in the code we can avoid the + * swaps altogether. + */ +#define DES_SP_ENCRYPT_ROUND(left, right, temp, kp) do { \ + (temp) = (((right) >> 11) | ((right) << 21)) ^ *(kp)++; \ + (left) ^= SP[0][((temp) >> 24) & 0x3f] \ + | SP[1][((temp) >> 16) & 0x3f] \ + | SP[2][((temp) >> 8) & 0x3f] \ + | SP[3][((temp) ) & 0x3f]; \ + (temp) = (((right) >> 23) | ((right) << 9)) ^ *(kp)++; \ + (left) ^= SP[4][((temp) >> 24) & 0x3f] \ + | SP[5][((temp) >> 16) & 0x3f] \ + | SP[6][((temp) >> 8) & 0x3f] \ + | SP[7][((temp) ) & 0x3f]; \ + } while(0); + +#define DES_SP_DECRYPT_ROUND(left, right, temp, kp) do { \ + (temp) = (((right) >> 23) | ((right) << 9)) ^ *(--(kp)); \ + (left) ^= SP[7][((temp) ) & 0x3f] \ + | SP[6][((temp) >> 8) & 0x3f] \ + | SP[5][((temp) >> 16) & 0x3f] \ + | SP[4][((temp) >> 24) & 0x3f]; \ + (temp) = (((right) >> 11) | ((right) << 21)) ^ *(--(kp)); \ + (left) ^= SP[3][((temp) ) & 0x3f] \ + | SP[2][((temp) >> 8) & 0x3f] \ + | SP[1][((temp) >> 16) & 0x3f] \ + | SP[0][((temp) >> 24) & 0x3f]; \ + } while (0); + +/* + * Macros to help deal with the initial permutation table. Note + * the IP table only deals with 32 bits at a time, allowing us to + * collect the bits we need to deal with each half into an unsigned + * DES_INT32. By carefully selecting how the bits are ordered we also + * take advantages of symmetries in the table so that we can use a + * single table to compute the permutation of all bytes. This sounds + * complicated, but if you go through the process of designing the + * table you'll find the symmetries fall right out. + * + * The follow macros compute the set of bits used to index the + * table for produce the left and right permuted result. + * + * The inserted cast to unsigned DES_INT32 circumvents a bug in + * the Macintosh MPW 3.2 C compiler which loses the unsignedness and + * propagates the high-order bit in the shift. + */ +#define DES_IP_LEFT_BITS(left, right) \ + ((((left) & 0x55555555) << 1) | ((right) & 0x55555555)) +#define DES_IP_RIGHT_BITS(left, right) \ + (((left) & 0xaaaaaaaa) | \ + ( ( (unsigned DES_INT32) ((right) & 0xaaaaaaaa) ) >> 1)) + +/* + * The following macro does an in-place initial permutation given + * the current left and right parts of the block and a single + * temporary. Use this more as a guide for rolling your own, though. + * The best way to do the IP depends on the form of the data you + * are dealing with. If you use this, though, try to make left, + * right and temp unsigned DES_INT32s. + */ +#define DES_INITIAL_PERM(left, right, temp) do { \ + (temp) = DES_IP_RIGHT_BITS((left), (right)); \ + (right) = DES_IP_LEFT_BITS((left), (right)); \ + (left) = IP[((right) >> 24) & 0xff] \ + | (IP[((right) >> 16) & 0xff] << 1) \ + | (IP[((right) >> 8) & 0xff] << 2) \ + | (IP[(right) & 0xff] << 3); \ + (right) = IP[((temp) >> 24) & 0xff] \ + | (IP[((temp) >> 16) & 0xff] << 1) \ + | (IP[((temp) >> 8) & 0xff] << 2) \ + | (IP[(temp) & 0xff] << 3); \ + } while(0); + +/* + * Now the final permutation stuff. The same comments apply to + * this as to the initial permutation, except that we use different + * bits and shifts. + * + * The inserted cast to unsigned DES_INT32 circumvents a bug in + * the Macintosh MPW 3.2 C compiler which loses the unsignedness and + * propagates the high-order bit in the shift. + */ +#define DES_FP_LEFT_BITS(left, right) \ + ((((left) & 0x0f0f0f0f) << 4) | ((right) & 0x0f0f0f0f)) +#define DES_FP_RIGHT_BITS(left, right) \ + (((left) & 0xf0f0f0f0) | \ + ( ( (unsigned DES_INT32) ((right) & 0xf0f0f0f0) ) >> 4)) + + +/* + * Here is a sample final permutation. Note that there is a trick + * here. DES requires swapping the left and right parts after the + * last cipher round but before the final permutation. We do this + * swapping internally, which is why left and right are confused + * at the beginning. + */ +#define DES_FINAL_PERM(left, right, temp) do { \ + (temp) = DES_FP_RIGHT_BITS((right), (left)); \ + (right) = DES_FP_LEFT_BITS((right), (left)); \ + (left) = (FP[((right) >> 24) & 0xff] << 6) \ + | (FP[((right) >> 16) & 0xff] << 4) \ + | (FP[((right) >> 8) & 0xff] << 2) \ + | FP[(right) & 0xff]; \ + (right) = (FP[((temp) >> 24) & 0xff] << 6) \ + | (FP[((temp) >> 16) & 0xff] << 4) \ + | (FP[((temp) >> 8) & 0xff] << 2) \ + | FP[temp & 0xff]; \ + } while(0); + + +/* + * Finally, as a sample of how all this might be held together, the + * following two macros do in-place encryptions and decryptions. left + * and right are two unsigned DES_INT32 variables which at the beginning + * are expected to hold the clear (encrypted) block in host byte order + * (left the high order four bytes, right the low order). At the end + * they will contain the encrypted (clear) block. temp is an unsigned DES_INT32 + * used as a temporary. kp is an unsigned DES_INT32 pointer pointing at + * the start of the key schedule. All these should be in registers. + * + * You can probably do better than these by rewriting for particular + * situations. These aren't bad, though. + * + * The DEB macros enable debugging when this code breaks (typically + * when a buggy compiler breaks it), by printing the intermediate values + * at each stage of the encryption, so that by comparing the output to + * a known good machine, the location of the first error can be found. + */ +#define DES_DO_ENCRYPT_1(left, right, kp) \ + do { \ + int i; \ + unsigned DES_INT32 temp1; \ + DEB (("do_encrypt %8lX %8lX \n", left, right)); \ + DES_INITIAL_PERM((left), (right), (temp1)); \ + DEB ((" after IP %8lX %8lX\n", left, right)); \ + for (i = 0; i < 8; i++) { \ + DES_SP_ENCRYPT_ROUND((left), (right), (temp1), (kp)); \ + DEB ((" round %2d %8lX %8lX \n", i*2, left, right)); \ + DES_SP_ENCRYPT_ROUND((right), (left), (temp1), (kp)); \ + DEB ((" round %2d %8lX %8lX \n", 1+i*2, left, right)); \ + } \ + DES_FINAL_PERM((left), (right), (temp1)); \ + (kp) -= (2 * 16); \ + DEB ((" after FP %8lX %8lX \n", left, right)); \ + } while (0) + +#define DES_DO_DECRYPT_1(left, right, kp) \ + do { \ + int i; \ + unsigned DES_INT32 temp2; \ + DES_INITIAL_PERM((left), (right), (temp2)); \ + (kp) += (2 * 16); \ + for (i = 0; i < 8; i++) { \ + DES_SP_DECRYPT_ROUND((left), (right), (temp2), (kp)); \ + DES_SP_DECRYPT_ROUND((right), (left), (temp2), (kp)); \ + } \ + DES_FINAL_PERM((left), (right), (temp2)); \ + } while (0) + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) +extern void krb5int_des_do_encrypt_2(unsigned DES_INT32 *l, + unsigned DES_INT32 *r, + const unsigned DES_INT32 *k); +extern void krb5int_des_do_decrypt_2(unsigned DES_INT32 *l, + unsigned DES_INT32 *r, + const unsigned DES_INT32 *k); +#define DES_DO_ENCRYPT(L,R,K) krb5int_des_do_encrypt_2(&(L), &(R), (K)) +#define DES_DO_DECRYPT(L,R,K) krb5int_des_do_decrypt_2(&(L), &(R), (K)) +#else +#define DES_DO_ENCRYPT DES_DO_ENCRYPT_1 +#define DES_DO_DECRYPT DES_DO_DECRYPT_1 +#endif + +/* + * These are handy dandy utility thingies for straightening out bytes. + * Included here because they're used a couple of places. + */ +#define GET_HALF_BLOCK(lr, ip) ((lr) = load_32_be(ip), (ip) += 4) +#define PUT_HALF_BLOCK(lr, op) (store_32_be(lr, op), (op) += 4) + +/* Shorthand that we'll need in several places, for creating values that + really can hold 32 bits regardless of the prevailing int size. */ +#define FF_UINT32 ((unsigned DES_INT32) 0xFF) + +#endif /* __DES_TABLES_H__ */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/key_sched.c b/krb5-1.21.3/src/lib/crypto/builtin/des/key_sched.c new file mode 100644 index 00000000..d6dedd93 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/key_sched.c @@ -0,0 +1,66 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/key_sched.c */ +/* + * Copyright 1985, 1986, 1987, 1988, 1990 by the Massachusetts Institute + * of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This routine computes the DES key schedule given a key. The + * permutations and shifts have been done at compile time, resulting + * in a direct one-step mapping from the input key to the key + * schedule. + * + * Also checks parity and weak keys. + * + * Watch out for the subscripts -- most effectively start at 1 instead + * of at zero. Maybe some bugs in that area. + * + * In case the user wants to cache the computed key schedule, it is + * passed as an arg. Also implies that caller has explicit control + * over zeroing both the key schedule and the key. + * + * Originally written 6/85 by Steve Miller, MIT Project Athena. + */ + +#include "crypto_int.h" +#include "des_int.h" + +#ifdef K5_BUILTIN_DES + +int +mit_des_key_sched(mit_des_cblock k, mit_des_key_schedule schedule) +{ + mit_des_make_key_sched(k,schedule); + + if (!mit_des_check_key_parity(k)) /* bad parity --> return -1 */ + return(-1); + + if (mit_des_is_weak_key(k)) + return(-2); + + /* if key was good, return 0 */ + return 0; +} + +#endif /* K5_BUILTIN_DES */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/keytest.data b/krb5-1.21.3/src/lib/crypto/builtin/des/keytest.data new file mode 100644 index 00000000..7ff34eed --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/keytest.data @@ -0,0 +1,171 @@ +0101010101010101 95F8A5E5DD31D900 8000000000000000 +0101010101010101 DD7F121CA5015619 4000000000000000 +0101010101010101 2E8653104F3834EA 2000000000000000 +0101010101010101 4BD388FF6CD81D4F 1000000000000000 +0101010101010101 20B9E767B2FB1456 0800000000000000 +0101010101010101 55579380D77138EF 0400000000000000 +0101010101010101 6CC5DEFAAF04512F 0200000000000000 +0101010101010101 0D9F279BA5D87260 0100000000000000 +0101010101010101 D9031B0271BD5A0A 0080000000000000 +0101010101010101 424250B37C3DD951 0040000000000000 +0101010101010101 B8061B7ECD9A21E5 0020000000000000 +0101010101010101 F15D0F286B65BD28 0010000000000000 +0101010101010101 ADD0CC8D6E5DEBA1 0008000000000000 +0101010101010101 E6D5F82752AD63D1 0004000000000000 +0101010101010101 ECBFE3BD3F591A5E 0002000000000000 +0101010101010101 F356834379D165CD 0001000000000000 +0101010101010101 2B9F982F20037FA9 0000800000000000 +0101010101010101 889DE068A16F0BE6 0000400000000000 +0101010101010101 E19E275D846A1298 0000200000000000 +0101010101010101 329A8ED523D71AEC 0000100000000000 +0101010101010101 E7FCE22557D23C97 0000080000000000 +0101010101010101 12A9F5817FF2D65D 0000040000000000 +0101010101010101 A484C3AD38DC9C19 0000020000000000 +0101010101010101 FBE00A8A1EF8AD72 0000010000000000 +0101010101010101 750D079407521363 0000008000000000 +0101010101010101 64FEED9C724C2FAF 0000004000000000 +0101010101010101 F02B263B328E2B60 0000002000000000 +0101010101010101 9D64555A9A10B852 0000001000000000 +0101010101010101 D106FF0BED5255D7 0000000800000000 +0101010101010101 E1652C6B138C64A5 0000000400000000 +0101010101010101 E428581186EC8F46 0000000200000000 +0101010101010101 AEB5F5EDE22D1A36 0000000100000000 +0101010101010101 E943D7568AEC0C5C 0000000080000000 +0101010101010101 DF98C8276F54B04B 0000000040000000 +0101010101010101 B160E4680F6C696F 0000000020000000 +0101010101010101 FA0752B07D9C4AB8 0000000010000000 +0101010101010101 CA3A2B036DBC8502 0000000008000000 +0101010101010101 5E0905517BB59BCF 0000000004000000 +0101010101010101 814EEB3B91D90726 0000000002000000 +0101010101010101 4D49DB1532919C9F 0000000001000000 +0101010101010101 25EB5FC3F8CF0621 0000000000800000 +0101010101010101 AB6A20C0620D1C6F 0000000000400000 +0101010101010101 79E90DBC98F92CCA 0000000000200000 +0101010101010101 866ECEDD8072BB0E 0000000000100000 +0101010101010101 8B54536F2F3E64A8 0000000000080000 +0101010101010101 EA51D3975595B86B 0000000000040000 +0101010101010101 CAFFC6AC4542DE31 0000000000020000 +0101010101010101 8DD45A2DDF90796C 0000000000010000 +0101010101010101 1029D55E880EC2D0 0000000000008000 +0101010101010101 5D86CB23639DBEA9 0000000000004000 +0101010101010101 1D1CA853AE7C0C5F 0000000000002000 +0101010101010101 CE332329248F3228 0000000000001000 +0101010101010101 8405D1ABE24FB942 0000000000000800 +0101010101010101 E643D78090CA4207 0000000000000400 +0101010101010101 48221B9937748A23 0000000000000200 +0101010101010101 DD7C0BBD61FAFD54 0000000000000100 +0101010101010101 2FBC291A570DB5C4 0000000000000080 +0101010101010101 E07C30D7E4E26E12 0000000000000040 +0101010101010101 0953E2258E8E90A1 0000000000000020 +0101010101010101 5B711BC4CEEBF2EE 0000000000000010 +0101010101010101 CC083F1E6D9E85F6 0000000000000008 +0101010101010101 D2FD8867D50D2DFE 0000000000000004 +0101010101010101 06E7EA22CE92708F 0000000000000002 +0101010101010101 166B40B44ABA4BD6 0000000000000001 +8001010101010101 0000000000000000 95A8D72813DAA94D +4001010101010101 0000000000000000 0EEC1487DD8C26D5 +2001010101010101 0000000000000000 7AD16FFB79C45926 +1001010101010101 0000000000000000 D3746294CA6A6CF3 +0801010101010101 0000000000000000 809F5F873C1FD761 +0401010101010101 0000000000000000 C02FAFFEC989D1FC +0201010101010101 0000000000000000 4615AA1D33E72F10 +0180010101010101 0000000000000000 2055123350C00858 +0140010101010101 0000000000000000 DF3B99D6577397C8 +0120010101010101 0000000000000000 31FE17369B5288C9 +0110010101010101 0000000000000000 DFDD3CC64DAE1642 +0108010101010101 0000000000000000 178C83CE2B399D94 +0104010101010101 0000000000000000 50F636324A9B7F80 +0102010101010101 0000000000000000 A8468EE3BC18F06D +0101800101010101 0000000000000000 A2DC9E92FD3CDE92 +0101400101010101 0000000000000000 CAC09F797D031287 +0101200101010101 0000000000000000 90BA680B22AEB525 +0101100101010101 0000000000000000 CE7A24F350E280B6 +0101080101010101 0000000000000000 882BFF0AA01A0B87 +0101040101010101 0000000000000000 25610288924511C2 +0101020101010101 0000000000000000 C71516C29C75D170 +0101018001010101 0000000000000000 5199C29A52C9F059 +0101014001010101 0000000000000000 C22F0A294A71F29F +0101012001010101 0000000000000000 EE371483714C02EA +0101011001010101 0000000000000000 A81FBD448F9E522F +0101010801010101 0000000000000000 4F644C92E192DFED +0101010401010101 0000000000000000 1AFA9A66A6DF92AE +0101010201010101 0000000000000000 B3C1CC715CB879D8 +0101010180010101 0000000000000000 19D032E64AB0BD8B +0101010140010101 0000000000000000 3CFAA7A7DC8720DC +0101010120010101 0000000000000000 B7265F7F447AC6F3 +0101010110010101 0000000000000000 9DB73B3C0D163F54 +0101010108010101 0000000000000000 8181B65BABF4A975 +0101010104010101 0000000000000000 93C9B64042EAA240 +0101010102010101 0000000000000000 5570530829705592 +0101010101800101 0000000000000000 8638809E878787A0 +0101010101400101 0000000000000000 41B9A79AF79AC208 +0101010101200101 0000000000000000 7A9BE42F2009A892 +0101010101100101 0000000000000000 29038D56BA6D2745 +0101010101080101 0000000000000000 5495C6ABF1E5DF51 +0101010101040101 0000000000000000 AE13DBD561488933 +0101010101020101 0000000000000000 024D1FFA8904E389 +0101010101018001 0000000000000000 D1399712F99BF02E +0101010101014001 0000000000000000 14C1D7C1CFFEC79E +0101010101012001 0000000000000000 1DE5279DAE3BED6F +0101010101011001 0000000000000000 E941A33F85501303 +0101010101010801 0000000000000000 DA99DBBC9A03F379 +0101010101010401 0000000000000000 B7FC92F91D8E92E9 +0101010101010201 0000000000000000 AE8E5CAA3CA04E85 +0101010101010180 0000000000000000 9CC62DF43B6EED74 +0101010101010140 0000000000000000 D863DBB5C59A91A0 +0101010101010120 0000000000000000 A1AB2190545B91D7 +0101010101010110 0000000000000000 0875041E64C570F7 +0101010101010108 0000000000000000 5A594528BEBEF1CC +0101010101010104 0000000000000000 FCDB3291DE21F0C0 +0101010101010102 0000000000000000 869EFD7F9F265A09 +1046913489980131 0000000000000000 88D55E54F54C97B4 +1007103489988020 0000000000000000 0C0CC00C83EA48FD +10071034C8980120 0000000000000000 83BC8EF3A6570183 +1046103489988020 0000000000000000 DF725DCAD94EA2E9 +1086911519190101 0000000000000000 E652B53B550BE8B0 +1086911519580101 0000000000000000 AF527120C485CBB0 +5107B01519580101 0000000000000000 0F04CE393DB926D5 +1007B01519190101 0000000000000000 C9F00FFC74079067 +3107915498080101 0000000000000000 7CFD82A593252B4E +3107919498080101 0000000000000000 CB49A2F9E91363E3 +10079115B9080140 0000000000000000 00B588BE70D23F56 +3107911598080140 0000000000000000 406A9A6AB43399AE +1007D01589980101 0000000000000000 6CB773611DCA9ADA +9107911589980101 0000000000000000 67FD21C17DBB5D70 +9107D01589190101 0000000000000000 9592CB4110430787 +1007D01598980120 0000000000000000 A6B7FF68A318DDD3 +1007940498190101 0000000000000000 4D102196C914CA16 +0107910491190401 0000000000000000 2DFA9F4573594965 +0107910491190101 0000000000000000 B46604816C0E0774 +0107940491190401 0000000000000000 6E7E6221A4F34E87 +19079210981A0101 0000000000000000 AA85E74643233199 +1007911998190801 0000000000000000 2E5A19DB4D1962D6 +10079119981A0801 0000000000000000 23A866A809D30894 +1007921098190101 0000000000000000 D812D961F017D320 +100791159819010B 0000000000000000 055605816E58608F +1004801598190101 0000000000000000 ABD88E8B1B7716F1 +1004801598190102 0000000000000000 537AC95BE69DA1E1 +1004801598190108 0000000000000000 AED0F6AE3C25CDD8 +1002911598100104 0000000000000000 B3E35A5EE53E7B8D +1002911598190104 0000000000000000 61C79C71921A2EF8 +1002911598100201 0000000000000000 E2F5728F0995013C +1002911698100101 0000000000000000 1AEAC39A61F0A464 +7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B +0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271 +07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A +3849674C2602319E 51454B582DDF440A 7178876E01F19B2A +04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095 +0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B +0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09 +43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A +07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F +04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088 +37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77 +1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A +584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56 +025816164629B007 480D39006EE762F2 A1F9915541020B56 +49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556 +4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC +49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A +018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41 +1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793 diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/t_verify.c b/krb5-1.21.3/src/lib/crypto/builtin/des/t_verify.c new file mode 100644 index 00000000..4a19933c --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/t_verify.c @@ -0,0 +1,395 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/t_verify.c */ +/* + * Copyright 1988, 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * + * Program to test the correctness of the DES library + * implementation. + * + * exit returns 0 ==> success + * -1 ==> error + */ + +#include "k5-int.h" +#include "des_int.h" +#include +#include "com_err.h" + +static void do_encrypt(unsigned char *, unsigned char *); +static void do_decrypt(unsigned char *, unsigned char *); + +char *progname; +int nflag = 2; +int vflag; +int mflag; +int zflag; +int pid; +int mit_des_debug; + +unsigned char cipher_text[64]; +unsigned char clear_text[64] = "Now is the time for all " ; +unsigned char clear_text2[64] = "7654321 Now is the time for "; +unsigned char clear_text3[64] = {2,0,0,0, 1,0,0,0}; +unsigned char output[64]; +unsigned char zero_text[8] = {0x0,0,0,0,0,0,0,0}; +unsigned char msb_text[8] = {0x0,0,0,0, 0,0,0,0x40}; /* to ANSI MSB */ +unsigned char *input; + +/* 0x0123456789abcdef */ +unsigned char default_key[8] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef +}; +unsigned char key2[8] = { 0x08,0x19,0x2a,0x3b,0x4c,0x5d,0x6e,0x7f }; +unsigned char key3[8] = { 0x80,1,1,1,1,1,1,1 }; +mit_des_cblock s_key; +unsigned char default_ivec[8] = { + 0x12,0x34,0x56,0x78,0x90,0xab,0xcd,0xef +}; +unsigned char *ivec; +unsigned char zero_key[8] = {1,1,1,1,1,1,1,1}; /* just parity bits */ + +unsigned char cipher1[8] = { + 0x25,0xdd,0xac,0x3e,0x96,0x17,0x64,0x67 +}; +unsigned char cipher2[8] = { + 0x3f,0xa4,0x0e,0x8a,0x98,0x4d,0x48,0x15 +}; +unsigned char cipher3[64] = { + 0xe5,0xc7,0xcd,0xde,0x87,0x2b,0xf2,0x7c, + 0x43,0xe9,0x34,0x00,0x8c,0x38,0x9c,0x0f, + 0x68,0x37,0x88,0x49,0x9a,0x7c,0x05,0xf6 +}; +unsigned char checksum[8] = { + 0x58,0xd2,0xe7,0x7e,0x86,0x06,0x27,0x33 +}; + +unsigned char zresult[8] = { + 0x8c, 0xa6, 0x4d, 0xe9, 0xc1, 0xb1, 0x23, 0xa7 +}; + +unsigned char mresult[8] = { + 0xa3, 0x80, 0xe0, 0x2a, 0x6b, 0xe5, 0x46, 0x96 +}; + + +/* + * Can also add : + * plaintext = 0, key = 0, cipher = 0x8ca64de9c1b123a7 (or is it a 1?) + */ + +mit_des_key_schedule sched; + +int +main(argc,argv) + int argc; + char *argv[]; +{ + /* Local Declarations */ + size_t in_length; + int retval; + int i, j; + +#ifdef WINDOWS + /* Set screen window buffer to infinite size -- MS default is tiny. */ + _wsetscreenbuf (fileno (stdout), _WINBUFINF); +#endif + progname=argv[0]; /* salt away invoking program */ + + while (--argc > 0 && (*++argv)[0] == '-') + for (i=1; argv[0][i] != '\0'; i++) { + switch (argv[0][i]) { + + /* debug flag */ + case 'd': + mit_des_debug=3; + continue; + + case 'z': + zflag = 1; + continue; + + case 'm': + mflag = 1; + continue; + + default: + printf("%s: illegal flag \"%c\" ", + progname,argv[0][i]); + exit(1); + } + }; + + if (argc) { + fprintf(stderr, "Usage: %s [-dmz]\n", progname); + exit(1); + } + + /* do some initialisation */ + + /* use known input and key */ + + /* ECB zero text zero key */ + if (zflag) { + input = zero_text; + mit_des_key_sched(zero_key, sched); + printf("plaintext = key = 0, cipher = 0x8ca64de9c1b123a7\n"); + do_encrypt(input,cipher_text); + printf("\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) + printf("%02x ",cipher_text[j]); + printf("\n"); + do_decrypt(output,cipher_text); + if ( memcmp((char *)cipher_text, (char *)zresult, 8) ) { + printf("verify: error in zero key test\n"); + exit(-1); + } + + exit(0); + } + + if (mflag) { + input = msb_text; + mit_des_key_sched(key3, sched); + printf("plaintext = 0x00 00 00 00 00 00 00 40, "); + printf("key = 0x80 01 01 01 01 01 01 01\n"); + printf(" cipher = 0xa380e02a6be54696\n"); + do_encrypt(input,cipher_text); + printf("\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) { + printf("%02x ",cipher_text[j]); + } + printf("\n"); + do_decrypt(output,cipher_text); + if ( memcmp((char *)cipher_text, (char *)mresult, 8) ) { + printf("verify: error in msb test\n"); + exit(-1); + } + exit(0); + } + + /* ECB mode Davies and Price */ + { + input = zero_text; + mit_des_key_sched(key2, sched); + printf("Examples per FIPS publication 81, keys ivs and cipher\n"); + printf("in hex. These are the correct answers, see below for\n"); + printf("the actual answers.\n\n"); + printf("Examples per Davies and Price.\n\n"); + printf("EXAMPLE ECB\tkey = 08192a3b4c5d6e7f\n"); + printf("\tclear = 0\n"); + printf("\tcipher = 25 dd ac 3e 96 17 64 67\n"); + printf("ACTUAL ECB\n"); + printf("\tclear \"%s\"\n", input); + do_encrypt(input,cipher_text); + printf("\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) + printf("%02x ",cipher_text[j]); + printf("\n\n"); + do_decrypt(output,cipher_text); + if ( memcmp((char *)cipher_text, (char *)cipher1, 8) ) { + printf("verify: error in ECB encryption\n"); + exit(-1); + } + else + printf("verify: ECB encryption is correct\n\n"); + } + + /* ECB mode */ + { + mit_des_key_sched(default_key, sched); + input = clear_text; + ivec = default_ivec; + printf("EXAMPLE ECB\tkey = 0123456789abcdef\n"); + printf("\tclear = \"Now is the time for all \"\n"); + printf("\tcipher = 3f a4 0e 8a 98 4d 48 15 ...\n"); + printf("ACTUAL ECB\n\tclear \"%s\"",input); + do_encrypt(input,cipher_text); + printf("\n\tcipher = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) { + printf("%02x ",cipher_text[j]); + } + printf("\n\n"); + do_decrypt(output,cipher_text); + if ( memcmp((char *)cipher_text, (char *)cipher2, 8) ) { + printf("verify: error in ECB encryption\n"); + exit(-1); + } + else + printf("verify: ECB encryption is correct\n\n"); + } + + /* CBC mode */ + printf("EXAMPLE CBC\tkey = 0123456789abcdef"); + printf("\tiv = 1234567890abcdef\n"); + printf("\tclear = \"Now is the time for all \"\n"); + printf("\tcipher =\te5 c7 cd de 87 2b f2 7c\n"); + printf("\t\t\t43 e9 34 00 8c 38 9c 0f\n"); + printf("\t\t\t68 37 88 49 9a 7c 05 f6\n"); + + printf("ACTUAL CBC\n\tclear \"%s\"\n",input); + in_length = strlen((char *)input); + if ((retval = mit_des_cbc_encrypt((const mit_des_cblock *) input, + (mit_des_cblock *) cipher_text, + (size_t) in_length, + sched, + ivec, + MIT_DES_ENCRYPT))) { + com_err("des verify", retval, "can't encrypt"); + exit(-1); + } + printf("\tciphertext = (low to high bytes)\n"); + for (i = 0; i <= 2; i++) { + printf("\t\t"); + for (j = 0; j <= 7; j++) { + printf("%02x ",cipher_text[i*8+j]); + } + printf("\n"); + } + if ((retval = mit_des_cbc_encrypt((const mit_des_cblock *) cipher_text, + (mit_des_cblock *) clear_text, + (size_t) in_length, + sched, + ivec, + MIT_DES_DECRYPT))) { + com_err("des verify", retval, "can't decrypt"); + exit(-1); + } + printf("\tdecrypted clear_text = \"%s\"\n",clear_text); + + if ( memcmp((char *)cipher_text, (char *)cipher3, in_length) ) { + printf("verify: error in CBC encryption\n"); + exit(-1); + } + else + printf("verify: CBC encryption is correct\n\n"); + + printf("EXAMPLE CBC checksum"); + printf("\tkey = 0123456789abcdef\tiv = 1234567890abcdef\n"); + printf("\tclear =\t\t\"7654321 Now is the time for \"\n"); + printf("\tchecksum\t58 d2 e7 7e 86 06 27 33, "); + printf("or some part thereof\n"); + input = clear_text2; + mit_des_cbc_cksum(input,cipher_text, strlen((char *)input), + sched,ivec); + printf("ACTUAL CBC checksum\n"); + printf("\t\tencrypted cksum = (low to high bytes)\n\t\t"); + for (j = 0; j<=7; j++) + printf("%02x ",cipher_text[j]); + printf("\n\n"); + if ( memcmp((char *)cipher_text, (char *)checksum, 8) ) { + printf("verify: error in CBC checksum\n"); + exit(-1); + } + else + printf("verify: CBC checksum is correct\n\n"); + + exit(0); +} + +static void +do_encrypt(in,out) + unsigned char *in; + unsigned char *out; +{ + int i, j; + for (i =1; i<=nflag; i++) { + mit_des_cbc_encrypt((const mit_des_cblock *)in, + (mit_des_cblock *)out, + 8, + sched, + zero_text, + MIT_DES_ENCRYPT); + if (mit_des_debug) { + printf("\nclear %s\n",in); + for (j = 0; j<=7; j++) + printf("%02X ",in[j] & 0xff); + printf("\tcipher "); + for (j = 0; j<=7; j++) + printf("%02X ",out[j] & 0xff); + } + } +} + +static void +do_decrypt(in,out) + unsigned char *out; + unsigned char *in; + /* try to invert it */ +{ + int i, j; + for (i =1; i<=nflag; i++) { + mit_des_cbc_encrypt((const mit_des_cblock *)out, + (mit_des_cblock *)in, + 8, + sched, + zero_text, + MIT_DES_DECRYPT); + if (mit_des_debug) { + printf("clear %s\n",in); + for (j = 0; j<=7; j++) + printf("%02X ",in[j] & 0xff); + printf("\tcipher "); + for (j = 0; j<=7; j++) + printf("%02X ",out[j] & 0xff); + } + } +} + +/* + * Fake out the DES library, for the purposes of testing. + */ + +int +mit_des_is_weak_key(key) + mit_des_cblock key; +{ + return 0; /* fake it out for testing */ +} diff --git a/krb5-1.21.3/src/lib/crypto/builtin/des/weak_key.c b/krb5-1.21.3/src/lib/crypto/builtin/des/weak_key.c new file mode 100644 index 00000000..f8304a36 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/des/weak_key.c @@ -0,0 +1,90 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/des/weak_key.c */ +/* + * Copyright 1989,1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + * + * These routines form the library interface to the DES facilities. + * + * Originally written 8/85 by Steve Miller, MIT Project Athena. + */ + +#include "crypto_int.h" +#include "des_int.h" + +#ifdef K5_BUILTIN_DES + +/* + * The following are the weak DES keys: + */ +static const mit_des_cblock weak[16] = { + /* weak keys */ + {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, + {0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe}, + {0x1f,0x1f,0x1f,0x1f,0x0e,0x0e,0x0e,0x0e}, + {0xe0,0xe0,0xe0,0xe0,0xf1,0xf1,0xf1,0xf1}, + + /* semi-weak */ + {0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe}, + {0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01}, + + {0x1f,0xe0,0x1f,0xe0,0x0e,0xf1,0x0e,0xf1}, + {0xe0,0x1f,0xe0,0x1f,0xf1,0x0e,0xf1,0x0e}, + + {0x01,0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1}, + {0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1,0x01}, + + {0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e,0xfe}, + {0xfe,0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e}, + + {0x01,0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e}, + {0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e,0x01}, + + {0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1,0xfe}, + {0xfe,0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1} +}; + +/* + * mit_des_is_weak_key: returns true iff key is a [semi-]weak des key. + * + * Requires: key has correct odd parity. + */ +int +mit_des_is_weak_key(mit_des_cblock key) +{ + unsigned int i; + const mit_des_cblock *weak_p = weak; + + for (i = 0; i < (sizeof(weak)/sizeof(mit_des_cblock)); i++) { + if (!memcmp(weak_p++,key,sizeof(mit_des_cblock))) + return 1; + } + + return 0; +} + +#endif /* K5_BUILTIN_DES */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/Makefile.in b/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/Makefile.in new file mode 100644 index 00000000..6ad7cbd4 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/Makefile.in @@ -0,0 +1,39 @@ +mydir=lib$(S)crypto$(S)builtin$(S)enc_provider +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/../des -I$(srcdir)/../aes -I$(srcdir)/../camellia \ + -I$(srcdir)/../../krb $(CRYPTO_IMPL_CFLAGS) + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\enc_provider +##DOS##OBJFILE = ..\..\$(OUTPRE)enc_provider.lst + +STLIBOBJS= \ + des3.o \ + rc4.o \ + aes.o \ + camellia.o + +OBJS= \ + $(OUTPRE)des3.$(OBJEXT) \ + $(OUTPRE)aes.$(OBJEXT) \ + $(OUTPRE)camellia.$(OBJEXT) \ + $(OUTPRE)rc4.$(OBJEXT) + +SRCS= \ + $(srcdir)/des3.c \ + $(srcdir)/aes.c \ + $(srcdir)/camellia.c \ + $(srcdir)/rc4.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/aes.c b/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/aes.c new file mode 100644 index 00000000..7fa94497 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/aes.c @@ -0,0 +1,412 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/enc_provider/aes.c */ +/* + * Copyright (C) 2003, 2007, 2008 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" +#include "aes.h" + +#ifdef K5_BUILTIN_AES + +/* + * Private per-key data to cache after first generation. We don't + * want to mess with the imported AES implementation too much, so + * we'll just use two copies of its context, one for encryption and + * one for decryption, and use the #rounds field as a flag for whether + * we've initialized each half. + */ +struct aes_key_info_cache { + aes_encrypt_ctx enc_ctx; + aes_decrypt_ctx dec_ctx; + krb5_boolean aesni; +}; +#define CACHE(X) ((struct aes_key_info_cache *)((X)->cache)) + +#ifdef AESNI + +/* Use AES-NI instructions (via assembly functions) when possible. */ + +#include + +struct aes_data +{ + unsigned char *in_block; + unsigned char *out_block; + uint32_t *expanded_key; + unsigned char *iv; + size_t num_blocks; +}; + +void k5_iEncExpandKey128(unsigned char *key, uint32_t *expanded_key); +void k5_iEncExpandKey256(unsigned char *key, uint32_t *expanded_key); +void k5_iDecExpandKey256(unsigned char *key, uint32_t *expanded_key); +void k5_iDecExpandKey128(unsigned char *key, uint32_t *expanded_key); + +void k5_iEnc128_CBC(struct aes_data *data); +void k5_iDec128_CBC(struct aes_data *data); +void k5_iEnc256_CBC(struct aes_data *data); +void k5_iDec256_CBC(struct aes_data *data); + +static krb5_boolean +aesni_supported_by_cpu() +{ + unsigned int a, b, c, d; + + return __get_cpuid(1, &a, &b, &c, &d) && (c & (1 << 25)); +} + +static inline krb5_boolean +aesni_supported(krb5_key key) +{ + return CACHE(key)->aesni; +} + +static void +aesni_expand_enc_key(krb5_key key) +{ + struct aes_key_info_cache *cache = CACHE(key); + + if (key->keyblock.length == 16) + k5_iEncExpandKey128(key->keyblock.contents, cache->enc_ctx.ks); + else + k5_iEncExpandKey256(key->keyblock.contents, cache->enc_ctx.ks); + cache->enc_ctx.inf.l = 1; +} + +static void +aesni_expand_dec_key(krb5_key key) +{ + struct aes_key_info_cache *cache = CACHE(key); + + if (key->keyblock.length == 16) + k5_iDecExpandKey128(key->keyblock.contents, cache->dec_ctx.ks); + else + k5_iDecExpandKey256(key->keyblock.contents, cache->dec_ctx.ks); + cache->dec_ctx.inf.l = 1; +} + +static inline void +aesni_enc(krb5_key key, unsigned char *data, size_t nblocks, unsigned char *iv) +{ + struct aes_key_info_cache *cache = CACHE(key); + struct aes_data d; + + d.in_block = data; + d.out_block = data; + d.expanded_key = cache->enc_ctx.ks; + d.iv = iv; + d.num_blocks = nblocks; + if (key->keyblock.length == 16) + k5_iEnc128_CBC(&d); + else + k5_iEnc256_CBC(&d); +} + +static inline void +aesni_dec(krb5_key key, unsigned char *data, size_t nblocks, unsigned char *iv) +{ + struct aes_key_info_cache *cache = CACHE(key); + struct aes_data d; + + d.in_block = data; + d.out_block = data; + d.expanded_key = cache->dec_ctx.ks; + d.iv = iv; + d.num_blocks = nblocks; + if (key->keyblock.length == 16) + k5_iDec128_CBC(&d); + else + k5_iDec256_CBC(&d); +} + +#else /* not AESNI */ + +#define aesni_supported_by_cpu() FALSE +#define aesni_supported(key) FALSE +#define aesni_expand_enc_key(key) +#define aesni_expand_dec_key(key) +#define aesni_enc(key, data, nblocks, iv) +#define aesni_dec(key, data, nblocks, iv) + +#endif + +/* out = out ^ in */ +static inline void +xorblock(const unsigned char *in, unsigned char *out) +{ + size_t q; + + for (q = 0; q < AES_BLOCK_SIZE; q += 4) + store_32_n(load_32_n(out + q) ^ load_32_n(in + q), out + q); +} + +static inline krb5_error_code +init_key_cache(krb5_key key) +{ + if (key->cache != NULL) + return 0; + key->cache = malloc(sizeof(struct aes_key_info_cache)); + if (key->cache == NULL) + return ENOMEM; + CACHE(key)->enc_ctx.inf.l = CACHE(key)->dec_ctx.inf.l = 0; + CACHE(key)->aesni = aesni_supported_by_cpu(); + return 0; +} + +static inline void +expand_enc_key(krb5_key key) +{ + if (CACHE(key)->enc_ctx.inf.l != 0) + return; + if (aesni_supported(key)) + aesni_expand_enc_key(key); + else if (aes_encrypt_key(key->keyblock.contents, key->keyblock.length, + &CACHE(key)->enc_ctx) != EXIT_SUCCESS) + abort(); +} + +static inline void +expand_dec_key(krb5_key key) +{ + if (CACHE(key)->dec_ctx.inf.l != 0) + return; + if (aesni_supported(key)) + aesni_expand_dec_key(key); + else if (aes_decrypt_key(key->keyblock.contents, key->keyblock.length, + &CACHE(key)->dec_ctx) != EXIT_SUCCESS) + abort(); +} + +/* CBC encrypt nblocks blocks of data in place, using and updating iv. */ +static inline void +cbc_enc(krb5_key key, unsigned char *data, size_t nblocks, unsigned char *iv) +{ + if (aesni_supported(key)) { + aesni_enc(key, data, nblocks, iv); + return; + } + for (; nblocks > 0; nblocks--, data += AES_BLOCK_SIZE) { + xorblock(iv, data); + if (aes_encrypt(data, data, &CACHE(key)->enc_ctx) != EXIT_SUCCESS) + abort(); + memcpy(iv, data, AES_BLOCK_SIZE); + } +} + +/* CBC decrypt nblocks blocks of data in place, using and updating iv. */ +static inline void +cbc_dec(krb5_key key, unsigned char *data, size_t nblocks, unsigned char *iv) +{ + unsigned char last_cipherblock[AES_BLOCK_SIZE]; + + if (aesni_supported(key)) { + aesni_dec(key, data, nblocks, iv); + return; + } + assert(nblocks > 0); + data += (nblocks - 1) * AES_BLOCK_SIZE; + memcpy(last_cipherblock, data, AES_BLOCK_SIZE); + for (; nblocks > 0; nblocks--, data -= AES_BLOCK_SIZE) { + if (aes_decrypt(data, data, &CACHE(key)->dec_ctx) != EXIT_SUCCESS) + abort(); + xorblock(nblocks == 1 ? iv : data - AES_BLOCK_SIZE, data); + } + memcpy(iv, last_cipherblock, AES_BLOCK_SIZE); +} + +krb5_error_code +krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + unsigned char iv[AES_BLOCK_SIZE], block[AES_BLOCK_SIZE]; + unsigned char blockN2[AES_BLOCK_SIZE], blockN1[AES_BLOCK_SIZE]; + size_t input_length, nblocks, ncontig; + struct iov_cursor cursor; + + if (init_key_cache(key)) + return ENOMEM; + expand_enc_key(key); + + k5_iov_cursor_init(&cursor, data, num_data, AES_BLOCK_SIZE, FALSE); + + input_length = iov_total_length(data, num_data, FALSE); + nblocks = (input_length + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE; + if (nblocks == 1) { + k5_iov_cursor_get(&cursor, block); + memset(iv, 0, AES_BLOCK_SIZE); + cbc_enc(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + return 0; + } + + if (ivec != NULL) + memcpy(iv, ivec->data, AES_BLOCK_SIZE); + else + memset(iv, 0, AES_BLOCK_SIZE); + + while (nblocks > 2) { + ncontig = iov_cursor_contig_blocks(&cursor); + if (ncontig > 0) { + /* Encrypt a series of contiguous blocks in place if we can, but + * don't touch the last two blocks. */ + ncontig = (ncontig > nblocks - 2) ? nblocks - 2 : ncontig; + cbc_enc(key, iov_cursor_ptr(&cursor), ncontig, iv); + iov_cursor_advance(&cursor, ncontig); + nblocks -= ncontig; + } else { + k5_iov_cursor_get(&cursor, block); + cbc_enc(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + nblocks--; + } + } + + /* Encrypt the last two blocks and put them back in reverse order, possibly + * truncating the encrypted second-to-last block. */ + k5_iov_cursor_get(&cursor, blockN2); + k5_iov_cursor_get(&cursor, blockN1); + cbc_enc(key, blockN2, 1, iv); + cbc_enc(key, blockN1, 1, iv); + k5_iov_cursor_put(&cursor, blockN1); + k5_iov_cursor_put(&cursor, blockN2); + + if (ivec != NULL) + memcpy(ivec->data, iv, AES_BLOCK_SIZE); + + return 0; +} + +krb5_error_code +krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + unsigned char iv[AES_BLOCK_SIZE], dummy_iv[AES_BLOCK_SIZE]; + unsigned char block[AES_BLOCK_SIZE]; + unsigned char blockN2[AES_BLOCK_SIZE], blockN1[AES_BLOCK_SIZE]; + size_t input_length, last_len, nblocks, ncontig; + struct iov_cursor cursor; + + if (init_key_cache(key)) + return ENOMEM; + expand_dec_key(key); + + k5_iov_cursor_init(&cursor, data, num_data, AES_BLOCK_SIZE, FALSE); + + input_length = iov_total_length(data, num_data, FALSE); + nblocks = (input_length + AES_BLOCK_SIZE - 1) / AES_BLOCK_SIZE; + last_len = input_length - (nblocks - 1) * AES_BLOCK_SIZE; + if (nblocks == 1) { + k5_iov_cursor_get(&cursor, block); + memset(iv, 0, AES_BLOCK_SIZE); + cbc_dec(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + return 0; + } + + if (ivec != NULL) + memcpy(iv, ivec->data, AES_BLOCK_SIZE); + else + memset(iv, 0, AES_BLOCK_SIZE); + + while (nblocks > 2) { + ncontig = iov_cursor_contig_blocks(&cursor); + if (ncontig > 0) { + /* Decrypt a series of contiguous blocks in place if we can, but + * don't touch the last two blocks. */ + ncontig = (ncontig > nblocks - 2) ? nblocks - 2 : ncontig; + cbc_dec(key, iov_cursor_ptr(&cursor), ncontig, iv); + iov_cursor_advance(&cursor, ncontig); + nblocks -= ncontig; + } else { + k5_iov_cursor_get(&cursor, block); + cbc_dec(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + nblocks--; + } + } + + /* Get the last two ciphertext blocks. Save the first as the new iv. */ + k5_iov_cursor_get(&cursor, blockN2); + k5_iov_cursor_get(&cursor, blockN1); + if (ivec != NULL) + memcpy(ivec->data, blockN2, AES_BLOCK_SIZE); + + /* Decrypt the second-to-last ciphertext block, using the final ciphertext + * block as the CBC IV. This produces the final plaintext block. */ + memcpy(dummy_iv, blockN1, sizeof(dummy_iv)); + cbc_dec(key, blockN2, 1, dummy_iv); + + /* Use the final bits of the decrypted plaintext to pad the last ciphertext + * block, and decrypt it to produce the second-to-last plaintext block. */ + memcpy(blockN1 + last_len, blockN2 + last_len, AES_BLOCK_SIZE - last_len); + cbc_dec(key, blockN1, 1, iv); + + /* Put the last two plaintext blocks back into the iovec. */ + k5_iov_cursor_put(&cursor, blockN1); + k5_iov_cursor_put(&cursor, blockN2); + + return 0; +} + +static krb5_error_code +aes_init_state(const krb5_keyblock *key, krb5_keyusage usage, + krb5_data *state) +{ + state->length = 16; + state->data = malloc(16); + if (state->data == NULL) + return ENOMEM; + memset(state->data, 0, state->length); + return 0; +} + +static void +aes_key_cleanup(krb5_key key) +{ + zapfree(key->cache, sizeof(struct aes_key_info_cache)); +} + +const struct krb5_enc_provider krb5int_enc_aes128 = { + 16, + 16, 16, + krb5int_aes_encrypt, + krb5int_aes_decrypt, + NULL, + aes_init_state, + krb5int_default_free_state, + aes_key_cleanup +}; + +const struct krb5_enc_provider krb5int_enc_aes256 = { + 16, + 32, 32, + krb5int_aes_encrypt, + krb5int_aes_decrypt, + NULL, + aes_init_state, + krb5int_default_free_state, + aes_key_cleanup +}; + +#endif /* K5_BUILTIN_AES */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/camellia.c b/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/camellia.c new file mode 100644 index 00000000..801fda00 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/camellia.c @@ -0,0 +1,319 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/enc_provider/camellia.c - Camellia enc provider */ +/* + * Copyright (C) 2009, 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" +#include "camellia.h" + +#ifdef K5_BUILTIN_CAMELLIA + +/* + * Private per-key data to cache after first generation. We don't want to mess + * with the imported Camellia implementation too much, so we'll just use two + * copies of its context, one for encryption and one for decryption, and use + * the keybitlen field as a flag for whether we've initialized each half. + */ +struct camellia_key_info_cache { + camellia_ctx enc_ctx, dec_ctx; +}; +#define CACHE(X) ((struct camellia_key_info_cache *)((X)->cache)) + +/* out = out ^ in */ +static inline void +xorblock(const unsigned char *in, unsigned char *out) +{ + size_t q; + + for (q = 0; q < BLOCK_SIZE; q += 4) + store_32_n(load_32_n(out + q) ^ load_32_n(in + q), out + q); +} + +static inline krb5_error_code +init_key_cache(krb5_key key) +{ + if (key->cache != NULL) + return 0; + key->cache = malloc(sizeof(struct camellia_key_info_cache)); + if (key->cache == NULL) + return ENOMEM; + CACHE(key)->enc_ctx.keybitlen = CACHE(key)->dec_ctx.keybitlen = 0; + return 0; +} + +static inline void +expand_enc_key(krb5_key key) +{ + if (CACHE(key)->enc_ctx.keybitlen) + return; + if (camellia_enc_key(key->keyblock.contents, key->keyblock.length, + &CACHE(key)->enc_ctx) != camellia_good) + abort(); +} + +static inline void +expand_dec_key(krb5_key key) +{ + if (CACHE(key)->dec_ctx.keybitlen) + return; + if (camellia_dec_key(key->keyblock.contents, key->keyblock.length, + &CACHE(key)->dec_ctx) != camellia_good) + abort(); +} + +/* CBC encrypt nblocks blocks of data in place, using and updating iv. */ +static inline void +cbc_enc(krb5_key key, unsigned char *data, size_t nblocks, unsigned char *iv) +{ + for (; nblocks > 0; nblocks--, data += BLOCK_SIZE) { + xorblock(iv, data); + if (camellia_enc_blk(data, data, &CACHE(key)->enc_ctx) != + camellia_good) + abort(); + memcpy(iv, data, BLOCK_SIZE); + } +} + +/* CBC decrypt nblocks blocks of data in place, using and updating iv. */ +static inline void +cbc_dec(krb5_key key, unsigned char *data, size_t nblocks, unsigned char *iv) +{ + unsigned char last_cipherblock[BLOCK_SIZE]; + + assert(nblocks > 0); + data += (nblocks - 1) * BLOCK_SIZE; + memcpy(last_cipherblock, data, BLOCK_SIZE); + for (; nblocks > 0; nblocks--, data -= BLOCK_SIZE) { + if (camellia_dec_blk(data, data, &CACHE(key)->dec_ctx) != + camellia_good) + abort(); + xorblock(nblocks == 1 ? iv : data - BLOCK_SIZE, data); + } + memcpy(iv, last_cipherblock, BLOCK_SIZE); +} + +krb5_error_code +krb5int_camellia_encrypt(krb5_key key, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + unsigned char iv[BLOCK_SIZE], block[BLOCK_SIZE]; + unsigned char blockN2[BLOCK_SIZE], blockN1[BLOCK_SIZE]; + size_t input_length, nblocks, ncontig; + struct iov_cursor cursor; + + if (init_key_cache(key)) + return ENOMEM; + expand_enc_key(key); + + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE); + + input_length = iov_total_length(data, num_data, FALSE); + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (nblocks == 1) { + k5_iov_cursor_get(&cursor, block); + memset(iv, 0, BLOCK_SIZE); + cbc_enc(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + return 0; + } + + if (ivec != NULL) + memcpy(iv, ivec->data, BLOCK_SIZE); + else + memset(iv, 0, BLOCK_SIZE); + + while (nblocks > 2) { + ncontig = iov_cursor_contig_blocks(&cursor); + if (ncontig > 0) { + /* Encrypt a series of contiguous blocks in place if we can, but + * don't touch the last two blocks. */ + ncontig = (ncontig > nblocks - 2) ? nblocks - 2 : ncontig; + cbc_enc(key, iov_cursor_ptr(&cursor), ncontig, iv); + iov_cursor_advance(&cursor, ncontig); + nblocks -= ncontig; + } else { + k5_iov_cursor_get(&cursor, block); + cbc_enc(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + nblocks--; + } + } + + /* Encrypt the last two blocks and put them back in reverse order, possibly + * truncating the encrypted second-to-last block. */ + k5_iov_cursor_get(&cursor, blockN2); + k5_iov_cursor_get(&cursor, blockN1); + cbc_enc(key, blockN2, 1, iv); + cbc_enc(key, blockN1, 1, iv); + k5_iov_cursor_put(&cursor, blockN1); + k5_iov_cursor_put(&cursor, blockN2); + + if (ivec != NULL) + memcpy(ivec->data, iv, BLOCK_SIZE); + + return 0; +} + +static krb5_error_code +krb5int_camellia_decrypt(krb5_key key, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + unsigned char iv[BLOCK_SIZE], dummy_iv[BLOCK_SIZE], block[BLOCK_SIZE]; + unsigned char blockN2[BLOCK_SIZE], blockN1[BLOCK_SIZE]; + size_t input_length, last_len, nblocks, ncontig; + struct iov_cursor cursor; + + if (init_key_cache(key)) + return ENOMEM; + expand_dec_key(key); + + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE); + + input_length = iov_total_length(data, num_data, FALSE); + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + last_len = input_length - (nblocks - 1) * BLOCK_SIZE; + if (nblocks == 1) { + k5_iov_cursor_get(&cursor, block); + memset(iv, 0, BLOCK_SIZE); + cbc_dec(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + return 0; + } + + if (ivec != NULL) + memcpy(iv, ivec->data, BLOCK_SIZE); + else + memset(iv, 0, BLOCK_SIZE); + + while (nblocks > 2) { + ncontig = iov_cursor_contig_blocks(&cursor); + if (ncontig > 0) { + /* Encrypt a series of contiguous blocks in place if we can, but + * don't touch the last two blocks. */ + ncontig = (ncontig > nblocks - 2) ? nblocks - 2 : ncontig; + cbc_dec(key, iov_cursor_ptr(&cursor), ncontig, iv); + iov_cursor_advance(&cursor, ncontig); + nblocks -= ncontig; + } else { + k5_iov_cursor_get(&cursor, block); + cbc_dec(key, block, 1, iv); + k5_iov_cursor_put(&cursor, block); + nblocks--; + } + } + + /* Get the last two ciphertext blocks. Save the first as the new iv. */ + k5_iov_cursor_get(&cursor, blockN2); + k5_iov_cursor_get(&cursor, blockN1); + if (ivec != NULL) + memcpy(ivec->data, blockN2, BLOCK_SIZE); + + /* Decrypt the second-to-last ciphertext block, using the final ciphertext + * block as the CBC IV. This produces the final plaintext block. */ + memcpy(dummy_iv, blockN1, sizeof(dummy_iv)); + cbc_dec(key, blockN2, 1, dummy_iv); + + /* Use the final bits of the decrypted plaintext to pad the last ciphertext + * block, and decrypt it to produce the second-to-last plaintext block. */ + memcpy(blockN1 + last_len, blockN2 + last_len, BLOCK_SIZE - last_len); + cbc_dec(key, blockN1, 1, iv); + + /* Put the last two plaintext blocks back into the iovec. */ + k5_iov_cursor_put(&cursor, blockN1); + k5_iov_cursor_put(&cursor, blockN2); + + return 0; +} + +static krb5_error_code +krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data, + size_t num_data, const krb5_data *ivec, + krb5_data *output) +{ + unsigned char iv[BLOCK_SIZE], block[BLOCK_SIZE]; + struct iov_cursor cursor; + + if (output->length < BLOCK_SIZE) + return KRB5_BAD_MSIZE; + + if (init_key_cache(key)) + return ENOMEM; + expand_enc_key(key); + + if (ivec != NULL) + memcpy(iv, ivec->data, BLOCK_SIZE); + else + memset(iv, 0, BLOCK_SIZE); + + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE); + while (k5_iov_cursor_get(&cursor, block)) + cbc_enc(key, block, 1, iv); + + output->length = BLOCK_SIZE; + memcpy(output->data, iv, BLOCK_SIZE); + + return 0; +} + +static krb5_error_code +camellia_init_state(const krb5_keyblock *key, krb5_keyusage usage, + krb5_data *state) +{ + state->length = 16; + state->data = malloc(16); + if (state->data == NULL) + return ENOMEM; + memset(state->data, 0, state->length); + return 0; +} + +static void +camellia_key_cleanup(krb5_key key) +{ + zapfree(key->cache, sizeof(struct camellia_key_info_cache)); +} + +const struct krb5_enc_provider krb5int_enc_camellia128 = { + 16, + 16, 16, + krb5int_camellia_encrypt, + krb5int_camellia_decrypt, + krb5int_camellia_cbc_mac, + camellia_init_state, + krb5int_default_free_state, + camellia_key_cleanup +}; + +const struct krb5_enc_provider krb5int_enc_camellia256 = { + 16, + 32, 32, + krb5int_camellia_encrypt, + krb5int_camellia_decrypt, + krb5int_camellia_cbc_mac, + camellia_init_state, + krb5int_default_free_state, + camellia_key_cleanup +}; + +#endif /* K5_BUILTIN_CAMELLIA */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/deps b/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/deps new file mode 100644 index 00000000..a3414a38 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/deps @@ -0,0 +1,49 @@ +# +# Generated makefile dependencies follow. +# +des3.so des3.po $(OUTPRE)des3.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(srcdir)/../des/des_int.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des3.c +aes.so aes.po $(OUTPRE)aes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(srcdir)/../aes/aes.h $(srcdir)/../aes/brg_types.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + aes.c +camellia.so camellia.po $(OUTPRE)camellia.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../camellia/camellia.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + camellia.c +rc4.so rc4.po $(OUTPRE)rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + rc4.c diff --git a/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/des3.c b/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/des3.c new file mode 100644 index 00000000..c2634d5e --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/des3.c @@ -0,0 +1,109 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" +#include "des_int.h" + +#ifdef K5_BUILTIN_DES + +static krb5_error_code +validate_and_schedule(krb5_key key, const krb5_data *ivec, + const krb5_crypto_iov *data, size_t num_data, + mit_des3_key_schedule *schedule) +{ + if (key->keyblock.length != 24) + return(KRB5_BAD_KEYSIZE); + if (iov_total_length(data, num_data, FALSE) % 8 != 0) + return(KRB5_BAD_MSIZE); + if (ivec && (ivec->length != 8)) + return(KRB5_BAD_MSIZE); + + switch (mit_des3_key_sched(*(mit_des3_cblock *)key->keyblock.contents, + *schedule)) { + case -1: + return(KRB5DES_BAD_KEYPAR); + case -2: + return(KRB5DES_WEAK_KEY); + } + return 0; +} + +static krb5_error_code +k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + mit_des3_key_schedule schedule; + krb5_error_code err; + + err = validate_and_schedule(key, ivec, data, num_data, &schedule); + if (err) + return err; + + /* this has a return value, but the code always returns zero */ + krb5int_des3_cbc_encrypt(data, num_data, + schedule[0], schedule[1], schedule[2], + ivec != NULL ? (unsigned char *) ivec->data : + NULL); + + zap(schedule, sizeof(schedule)); + + return(0); +} + +static krb5_error_code +k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + mit_des3_key_schedule schedule; + krb5_error_code err; + + err = validate_and_schedule(key, ivec, data, num_data, &schedule); + if (err) + return err; + + /* this has a return value, but the code always returns zero */ + krb5int_des3_cbc_decrypt(data, num_data, + schedule[0], schedule[1], schedule[2], + ivec != NULL ? (unsigned char *) ivec->data : + NULL); + + zap(schedule, sizeof(schedule)); + + return 0; +} + +const struct krb5_enc_provider krb5int_enc_des3 = { + 8, + 21, 24, + k5_des3_encrypt, + k5_des3_decrypt, + NULL, + krb5int_des_init_state, + krb5int_default_free_state +}; + +#endif /* K5_BUILTIN_DES */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/rc4.c b/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/rc4.c new file mode 100644 index 00000000..31291c2a --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/enc_provider/rc4.c @@ -0,0 +1,194 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/enc_provider/rc4.c */ +/* + * Copyright (c) 2000 by Computer Science Laboratory, + * Rensselaer Polytechnic Institute + * + * #include STD_DISCLAIMER + */ + +#include "crypto_int.h" + +#ifdef K5_BUILTIN_RC4 + +typedef struct +{ + unsigned int x; + unsigned int y; + unsigned char state[256]; +} ArcfourContext; + +typedef struct { + int initialized; + ArcfourContext ctx; +} ArcFourCipherState; + +/* gets the next byte from the PRNG */ +#if ((__GNUC__ >= 2) ) +static __inline__ unsigned int k5_arcfour_byte(ArcfourContext *); +#else +static unsigned int k5_arcfour_byte(ArcfourContext *); +#endif /* gcc inlines*/ + +/* Initializes the context and sets the key. */ +static krb5_error_code k5_arcfour_init(ArcfourContext *ctx, const unsigned char *key, + unsigned int keylen); + +/* Encrypts/decrypts data. */ +static void k5_arcfour_crypt(ArcfourContext *ctx, unsigned char *dest, + const unsigned char *src, unsigned int len); + +static inline unsigned int k5_arcfour_byte(ArcfourContext * ctx) +{ + unsigned int x; + unsigned int y; + unsigned int sx, sy; + unsigned char *state; + + state = ctx->state; + x = (ctx->x + 1) & 0xff; + sx = state[x]; + y = (sx + ctx->y) & 0xff; + sy = state[y]; + ctx->x = x; + ctx->y = y; + state[y] = sx; + state[x] = sy; + return state[(sx + sy) & 0xff]; +} + +static void k5_arcfour_crypt(ArcfourContext *ctx, unsigned char *dest, + const unsigned char *src, unsigned int len) +{ + unsigned int i; + for (i = 0; i < len; i++) + dest[i] = src[i] ^ k5_arcfour_byte(ctx); +} + + +static krb5_error_code +k5_arcfour_init(ArcfourContext *ctx, const unsigned char *key, + unsigned int key_len) +{ + unsigned int t, u; + unsigned int keyindex; + unsigned int stateindex; + unsigned char* state; + unsigned int counter; + + if (key_len != 16) + return KRB5_BAD_MSIZE; /*this is probably not the correct error code + to return */ + state = &ctx->state[0]; + ctx->x = 0; + ctx->y = 0; + for (counter = 0; counter < 256; counter++) + state[counter] = counter; + keyindex = 0; + stateindex = 0; + for (counter = 0; counter < 256; counter++) + { + t = state[counter]; + stateindex = (stateindex + key[keyindex] + t) & 0xff; + u = state[stateindex]; + state[stateindex] = t; + state[counter] = u; + if (++keyindex >= key_len) + keyindex = 0; + } + return 0; +} + + +static krb5_error_code +k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data, + size_t num_data) +{ + ArcfourContext *arcfour_ctx = NULL; + ArcFourCipherState *cipher_state = NULL; + krb5_error_code ret; + size_t i; + + if (key->keyblock.length != 16) + return KRB5_BAD_KEYSIZE; + if (state != NULL && (state->length != sizeof(ArcFourCipherState))) + return KRB5_BAD_MSIZE; + + if (state != NULL) { + cipher_state = (ArcFourCipherState *)(void *)state->data; + arcfour_ctx = &cipher_state->ctx; + if (cipher_state->initialized == 0) { + ret = k5_arcfour_init(arcfour_ctx, key->keyblock.contents, + key->keyblock.length); + if (ret != 0) + return ret; + + cipher_state->initialized = 1; + } + } else { + arcfour_ctx = (ArcfourContext *)malloc(sizeof(ArcfourContext)); + if (arcfour_ctx == NULL) + return ENOMEM; + + ret = k5_arcfour_init(arcfour_ctx, key->keyblock.contents, + key->keyblock.length); + if (ret != 0) { + free(arcfour_ctx); + return ret; + } + } + + for (i = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_IOV(iov)) + k5_arcfour_crypt(arcfour_ctx, (unsigned char *)iov->data.data, + (const unsigned char *)iov->data.data, iov->data.length); + } + + if (state == NULL) + zapfree(arcfour_ctx, sizeof(ArcfourContext)); + + return 0; +} + +static krb5_error_code +k5_arcfour_init_state (const krb5_keyblock *key, + krb5_keyusage keyusage, krb5_data *new_state) +{ + /* Note that we can't actually set up the state here because the key + * will change between now and when encrypt is called + * because it is data dependent. Yeah, this has strange + * properties. --SDH + */ + new_state->length = sizeof (ArcFourCipherState); + new_state->data = malloc (new_state->length); + if (new_state->data) { + memset (new_state->data, 0 , new_state->length); + /* That will set initialized to zero*/ + }else { + return (ENOMEM); + } + return 0; +} + +/* Since the arcfour cipher is identical going forwards and backwards, + we just call "docrypt" directly +*/ +const struct krb5_enc_provider krb5int_enc_arcfour = { + /* This seems to work... although I am not sure what the + implications are in other places in the kerberos library */ + 1, + /* Keysize is arbitrary in arcfour, but the constraints of the + system, and to attempt to work with the MSFT system forces us + to 16byte/128bit. Since there is no parity in the key, the + byte and length are the same. */ + 16, 16, + k5_arcfour_docrypt, + k5_arcfour_docrypt, + NULL, + k5_arcfour_init_state, /*xxx not implemented yet*/ + krb5int_default_free_state +}; + +#endif /* K5_BUILTIN_RC4 */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/Makefile.in b/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/Makefile.in new file mode 100644 index 00000000..3fbe525e --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/Makefile.in @@ -0,0 +1,38 @@ +mydir=lib$(S)crypto$(S)builtin$(S)hash_provider +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../krb -I$(srcdir)/../md4 \ + -I$(srcdir)/../md5 -I$(srcdir)/../sha1 -I$(srcdir)/../sha2 \ + $(CRYPTO_IMPL_CFLAGS) + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\hash_provider +##DOS##OBJFILE = ..\..\$(OUTPRE)hash_provider.lst + +STLIBOBJS= \ + hash_md4.o \ + hash_md5.o \ + hash_sha1.o \ + hash_sha2.o + +OBJS= $(OUTPRE)hash_md4.$(OBJEXT) \ + $(OUTPRE)hash_md5.$(OBJEXT) \ + $(OUTPRE)hash_sha1.$(OBJEXT) \ + $(OUTPRE)hash_sha2.$(OBJEXT) + +SRCS= $(srcdir)/hash_md4.c \ + $(srcdir)/hash_md5.c \ + $(srcdir)/hash_sha1.c \ + $(srcdir)/hash_sha2.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/deps b/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/deps new file mode 100644 index 00000000..bfd14f74 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/deps @@ -0,0 +1,51 @@ +# +# Generated makefile dependencies follow. +# +hash_md4.so hash_md4.po $(OUTPRE)hash_md4.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../md4/rsa-md4.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + hash_md4.c +hash_md5.so hash_md5.po $(OUTPRE)hash_md5.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../md5/rsa-md5.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + hash_md5.c +hash_sha1.so hash_sha1.po $(OUTPRE)hash_sha1.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../sha1/shs.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + hash_sha1.c +hash_sha2.so hash_sha2.po $(OUTPRE)hash_sha2.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(srcdir)/../sha2/sha2.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + hash_sha2.c diff --git a/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_md4.c b/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_md4.c new file mode 100644 index 00000000..f7055f85 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_md4.c @@ -0,0 +1,65 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" +#include "rsa-md4.h" + +#ifdef K5_BUILTIN_MD4 + +static krb5_error_code +k5_md4_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + krb5_MD4_CTX ctx; + unsigned int i; + + if (output->length != RSA_MD4_CKSUM_LENGTH) + return(KRB5_CRYPTO_INTERNAL); + + krb5int_MD4Init(&ctx); + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) { + krb5int_MD4Update(&ctx, (unsigned char *) iov->data.data, + iov->data.length); + } + } + krb5int_MD4Final(&ctx); + + memcpy(output->data, ctx.digest, RSA_MD4_CKSUM_LENGTH); + + return(0); +} + +const struct krb5_hash_provider krb5int_hash_md4 = { + "MD4", + RSA_MD4_CKSUM_LENGTH, + 64, + k5_md4_hash +}; + +#endif /* K5_BUILTIN_MD4 */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_md5.c b/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_md5.c new file mode 100644 index 00000000..2f01498a --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_md5.c @@ -0,0 +1,65 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" +#include "rsa-md5.h" + +#ifdef K5_BUILTIN_MD5 + +static krb5_error_code +k5_md5_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + krb5_MD5_CTX ctx; + unsigned int i; + + if (output->length != RSA_MD5_CKSUM_LENGTH) + return KRB5_CRYPTO_INTERNAL; + + krb5int_MD5Init(&ctx); + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) { + krb5int_MD5Update(&ctx, (unsigned char *) iov->data.data, + iov->data.length); + } + } + krb5int_MD5Final(&ctx); + + memcpy(output->data, ctx.digest, RSA_MD5_CKSUM_LENGTH); + + return 0; +} + +const struct krb5_hash_provider krb5int_hash_md5 = { + "MD5", + RSA_MD5_CKSUM_LENGTH, + 64, + k5_md5_hash +}; + +#endif /* K5_BUILTIN_MD5 */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_sha1.c b/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_sha1.c new file mode 100644 index 00000000..4e6e1533 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_sha1.c @@ -0,0 +1,66 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" +#include "shs.h" + +#ifdef K5_BUILTIN_SHA1 + +static krb5_error_code +k5_sha1_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + SHS_INFO ctx; + unsigned int i; + + if (output->length != SHS_DIGESTSIZE) + return KRB5_CRYPTO_INTERNAL; + + shsInit(&ctx); + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) { + shsUpdate(&ctx, (unsigned char *) iov->data.data, + iov->data.length); + } + } + shsFinal(&ctx); + + for (i = 0; i < sizeof(ctx.digest) / sizeof(ctx.digest[0]); i++) + store_32_be(ctx.digest[i], &output->data[i*4]); + + return 0; +} + +const struct krb5_hash_provider krb5int_hash_sha1 = { + "SHA1", + SHS_DIGESTSIZE, + SHS_DATASIZE, + k5_sha1_hash +}; + +#endif /* K5_BUILTIN_SHA1 */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_sha2.c b/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_sha2.c new file mode 100644 index 00000000..fd7b56bb --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/hash_provider/hash_sha2.c @@ -0,0 +1,92 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/hash_provider/sha2.c - SHA-2 hash providers */ +/* + * Copyright (C) 2015 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. + */ + +#include "crypto_int.h" +#include "sha2.h" + +#ifdef K5_BUILTIN_SHA2 + +static krb5_error_code +k5_sha256_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + SHA256_CTX ctx; + size_t i; + const krb5_crypto_iov *iov; + + if (output->length != SHA256_DIGEST_LENGTH) + return KRB5_CRYPTO_INTERNAL; + + k5_sha256_init(&ctx); + for (i = 0; i < num_data; i++) { + iov = &data[i]; + if (SIGN_IOV(iov)) + k5_sha256_update(&ctx, iov->data.data, iov->data.length); + } + k5_sha256_final(output->data, &ctx); + return 0; +} + +static krb5_error_code +k5_sha384_hash(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + SHA384_CTX ctx; + size_t i; + const krb5_crypto_iov *iov; + + if (output->length != SHA384_DIGEST_LENGTH) + return KRB5_CRYPTO_INTERNAL; + + k5_sha384_init(&ctx); + for (i = 0; i < num_data; i++) { + iov = &data[i]; + if (SIGN_IOV(iov)) + k5_sha384_update(&ctx, iov->data.data, iov->data.length); + } + k5_sha384_final(output->data, &ctx); + return 0; +} + +const struct krb5_hash_provider krb5int_hash_sha256 = { + "SHA-256", + SHA256_DIGEST_LENGTH, + SHA256_BLOCK_SIZE, + k5_sha256_hash +}; + +const struct krb5_hash_provider krb5int_hash_sha384 = { + "SHA-384", + SHA384_DIGEST_LENGTH, + SHA384_BLOCK_SIZE, + k5_sha384_hash +}; + +#endif /* K5_BUILTIN_SHA2 */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/hmac.c b/krb5-1.21.3/src/lib/crypto/builtin/hmac.c new file mode 100644 index 00000000..866758eb --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/hmac.c @@ -0,0 +1,124 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +#ifdef K5_BUILTIN_HMAC + +/* + * Because our built-in HMAC implementation doesn't need to invoke any + * encryption or keyed hash functions, it is simplest to define it in terms of + * keyblocks, and then supply a simple wrapper for the "normal" krb5_key-using + * interfaces. The keyblock interfaces are useful for code which creates + * intermediate keyblocks. + */ + +/* + * The HMAC transform looks like: + * + * H(K XOR opad, H(K XOR ipad, text)) + * + * where H is a cryptographic hash + * K is an n byte key + * ipad is the byte 0x36 repeated blocksize times + * opad is the byte 0x5c repeated blocksize times + * and text is the data being protected + */ + +krb5_error_code +krb5int_hmac_keyblock(const struct krb5_hash_provider *hash, + const krb5_keyblock *keyblock, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + unsigned char *xorkey = NULL, *ihash = NULL; + unsigned int i; + krb5_crypto_iov *ihash_iov = NULL, ohash_iov[2]; + krb5_data hashout; + krb5_error_code ret; + + if (keyblock->length > hash->blocksize) + return KRB5_CRYPTO_INTERNAL; + if (output->length < hash->hashsize) + return KRB5_BAD_MSIZE; + + /* Allocate space for the xor key, hash input vector, and inner hash */ + xorkey = k5alloc(hash->blocksize, &ret); + if (xorkey == NULL) + goto cleanup; + ihash = k5alloc(hash->hashsize, &ret); + if (ihash == NULL) + goto cleanup; + ihash_iov = k5calloc(num_data + 1, sizeof(krb5_crypto_iov), &ret); + if (ihash_iov == NULL) + goto cleanup; + + /* Create the inner padded key. */ + memset(xorkey, 0x36, hash->blocksize); + for (i = 0; i < keyblock->length; i++) + xorkey[i] ^= keyblock->contents[i]; + + /* Compute the inner hash over the inner key and input data. */ + ihash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + ihash_iov[0].data = make_data(xorkey, hash->blocksize); + memcpy(ihash_iov + 1, data, num_data * sizeof(krb5_crypto_iov)); + hashout = make_data(ihash, hash->hashsize); + ret = hash->hash(ihash_iov, num_data + 1, &hashout); + if (ret != 0) + goto cleanup; + + /* Create the outer padded key. */ + memset(xorkey, 0x5c, hash->blocksize); + for (i = 0; i < keyblock->length; i++) + xorkey[i] ^= keyblock->contents[i]; + + /* Compute the outer hash over the outer key and inner hash value. */ + ohash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + ohash_iov[0].data = make_data(xorkey, hash->blocksize); + ohash_iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + ohash_iov[1].data = make_data(ihash, hash->hashsize); + output->length = hash->hashsize; + ret = hash->hash(ohash_iov, 2, output); + if (ret != 0) + memset(output->data, 0, output->length); + +cleanup: + zapfree(xorkey, hash->blocksize); + zapfree(ihash, hash->hashsize); + free(ihash_iov); + return ret; +} + +krb5_error_code +krb5int_hmac(const struct krb5_hash_provider *hash, krb5_key key, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + return krb5int_hmac_keyblock(hash, &key->keyblock, data, num_data, output); +} + +#endif /* K5_BUILTIN_HMAC */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/kdf.c b/krb5-1.21.3/src/lib/crypto/builtin/kdf.c new file mode 100644 index 00000000..8a6658bf --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/kdf.c @@ -0,0 +1,190 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +#ifdef K5_BUILTIN_KDF + +krb5_error_code +k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash, + krb5_key key, const krb5_data *label, + const krb5_data *context, krb5_data *rnd_out) +{ + krb5_crypto_iov iov[5]; + krb5_error_code ret; + krb5_data prf; + unsigned char ibuf[4], lbuf[4]; + + if (hash == NULL || rnd_out->length > hash->hashsize) + return KRB5_CRYPTO_INTERNAL; + + /* Allocate encryption data buffer. */ + ret = alloc_data(&prf, hash->hashsize); + if (ret) + return ret; + + /* [i]2: four-byte big-endian binary string giving the block counter (1) */ + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = make_data(ibuf, sizeof(ibuf)); + store_32_be(1, ibuf); + /* Label */ + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data = *label; + /* 0x00: separator byte */ + iov[2].flags = KRB5_CRYPTO_TYPE_DATA; + iov[2].data = make_data("", 1); + /* Context */ + iov[3].flags = KRB5_CRYPTO_TYPE_DATA; + iov[3].data = *context; + /* [L]2: four-byte big-endian binary string giving the output length */ + iov[4].flags = KRB5_CRYPTO_TYPE_DATA; + iov[4].data = make_data(lbuf, sizeof(lbuf)); + store_32_be(rnd_out->length * 8, lbuf); + + ret = krb5int_hmac(hash, key, iov, 5, &prf); + if (!ret) + memcpy(rnd_out->data, prf.data, rnd_out->length); + zapfree(prf.data, prf.length); + return ret; +} + +krb5_error_code +k5_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc, krb5_key key, + const krb5_data *label, krb5_data *rnd_out) +{ + size_t blocksize, keybytes, n; + krb5_crypto_iov iov[6]; + krb5_error_code ret; + krb5_data prf; + unsigned int i; + unsigned char ibuf[4], Lbuf[4]; + + blocksize = enc->block_size; + keybytes = enc->keybytes; + + if (key->keyblock.length != enc->keylength || rnd_out->length != keybytes) + return KRB5_CRYPTO_INTERNAL; + + /* Allocate encryption data buffer. */ + ret = alloc_data(&prf, blocksize); + if (ret) + return ret; + + /* K(i-1): the previous block of PRF output, initially all-zeros. */ + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = prf; + /* [i]2: four-byte big-endian binary string giving the block counter */ + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data = make_data(ibuf, sizeof(ibuf)); + /* Label: the fixed derived-key input */ + iov[2].flags = KRB5_CRYPTO_TYPE_DATA; + iov[2].data = *label; + /* 0x00: separator byte */ + iov[3].flags = KRB5_CRYPTO_TYPE_DATA; + iov[3].data = make_data("", 1); + /* Context: (unused) */ + iov[4].flags = KRB5_CRYPTO_TYPE_DATA; + iov[4].data = empty_data(); + /* [L]2: four-byte big-endian binary string giving the output length */ + iov[5].flags = KRB5_CRYPTO_TYPE_DATA; + iov[5].data = make_data(Lbuf, sizeof(Lbuf)); + store_32_be(rnd_out->length * 8, Lbuf); + + for (i = 1, n = 0; n < keybytes; i++) { + /* Update the block counter. */ + store_32_be(i, ibuf); + + /* Compute a CMAC checksum, storing the result into K(i-1). */ + ret = krb5int_cmac_checksum(enc, key, iov, 6, &prf); + if (ret) + goto cleanup; + + /* Copy the result into the appropriate part of the output buffer. */ + if (keybytes - n <= blocksize) { + memcpy(rnd_out->data + n, prf.data, keybytes - n); + break; + } + memcpy(rnd_out->data + n, prf.data, blocksize); + n += blocksize; + } + +cleanup: + zapfree(prf.data, blocksize); + return ret; +} + +krb5_error_code +k5_derive_random_rfc3961(const struct krb5_enc_provider *enc, krb5_key key, + const krb5_data *constant, krb5_data *rnd_out) +{ + size_t blocksize, keybytes, n; + krb5_error_code ret; + krb5_data block = empty_data(); + + blocksize = enc->block_size; + keybytes = enc->keybytes; + + if (blocksize == 1) + return KRB5_BAD_ENCTYPE; + if (key->keyblock.length != enc->keylength || rnd_out->length != keybytes) + return KRB5_CRYPTO_INTERNAL; + + /* Allocate encryption data buffer. */ + ret = alloc_data(&block, blocksize); + if (ret) + return ret; + + /* Initialize the input block. */ + if (constant->length == blocksize) { + memcpy(block.data, constant->data, blocksize); + } else { + krb5int_nfold(constant->length * 8, (uint8_t *)constant->data, + blocksize * 8, (uint8_t *)block.data); + } + + /* Loop encrypting the blocks until enough key bytes are generated. */ + n = 0; + while (n < keybytes) { + ret = encrypt_block(enc, key, &block); + if (ret) + goto cleanup; + + if ((keybytes - n) <= blocksize) { + memcpy(rnd_out->data + n, block.data, (keybytes - n)); + break; + } + + memcpy(rnd_out->data + n, block.data, blocksize); + n += blocksize; + } + +cleanup: + zapfree(block.data, blocksize); + return ret; +} + +#endif /* K5_BUILTIN_KDF */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/md4/ISSUES b/krb5-1.21.3/src/lib/crypto/builtin/md4/ISSUES new file mode 100644 index 00000000..c343d290 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/md4/ISSUES @@ -0,0 +1,4 @@ +Issues to be addressed for src/lib/crypto/md4: -*- text -*- + + +Assumes int is >= 32 bits. diff --git a/krb5-1.21.3/src/lib/crypto/builtin/md4/Makefile.in b/krb5-1.21.3/src/lib/crypto/builtin/md4/Makefile.in new file mode 100644 index 00000000..0e49400e --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/md4/Makefile.in @@ -0,0 +1,33 @@ +mydir=lib$(S)crypto$(S)builtin$(S)md4 +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES=-I$(srcdir)/../../krb $(CRYPTO_IMPL_CFLAGS) + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\md4 +##DOS##OBJFILE = ..\..\$(OUTPRE)md4.lst + +STLIBOBJS= md4.o + +OBJS= $(OUTPRE)md4.$(OBJEXT) + +SRCS= $(srcdir)/md4.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) + + +check-unix: + +check-windows: + +clean: + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/builtin/md4/deps b/krb5-1.21.3/src/lib/crypto/builtin/md4/deps new file mode 100644 index 00000000..27994226 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/md4/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +md4.so md4.po $(OUTPRE)md4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + md4.c rsa-md4.h diff --git a/krb5-1.21.3/src/lib/crypto/builtin/md4/md4.c b/krb5-1.21.3/src/lib/crypto/builtin/md4/md4.c new file mode 100644 index 00000000..28955ad3 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/md4/md4.c @@ -0,0 +1,247 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/md4/md4.c */ + +/* + * Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + * + * License to copy and use this software is granted provided that + * it is identified as the "RSA Data Security, Inc. MD4 Message + * Digest Algorithm" in all material mentioning or referencing this + * software or this function. + * + * License is also granted to make and use derivative works + * provided that such works are identified as "derived from the RSA + * Data Security, Inc. MD4 Message Digest Algorithm" in all + * material mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning + * either the merchantability of this software or the suitability + * of this software for any particular purpose. It is provided "as + * is" without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +/* +********************************************************************** +** md4.c ** +** RSA Data Security, Inc. MD4 Message Digest Algorithm ** +** Created: 2/17/90 RLR ** +** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** +********************************************************************** +*/ + +#include "crypto_int.h" +#include "rsa-md4.h" + +#ifdef K5_BUILTIN_MD4 + +/* forward declaration */ +static void Transform (krb5_ui_4 *, krb5_ui_4 *); + +static const unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G and H are basic MD4 functions: selection, majority, parity */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) ((((x) << (n)) & 0xffffffff) | ((x) >> (32-(n)))) + +/* FF, GG and HH are MD4 transformations for rounds 1, 2 and 3 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s) \ + {(a) += F ((b), (c), (d)) + (x); \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s));} +#define GG(a, b, c, d, x, s) \ + {(a) += G ((b), (c), (d)) + (x) + 013240474631UL; \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s));} +#define HH(a, b, c, d, x, s) \ + {(a) += H ((b), (c), (d)) + (x) + 015666365641UL; \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s));} + +void +krb5int_MD4Init (krb5_MD4_CTX *mdContext) +{ + mdContext->i[0] = mdContext->i[1] = (krb5_ui_4)0; + + /* Load magic initialization constants. + */ + mdContext->buf[0] = 0x67452301UL; + mdContext->buf[1] = 0xefcdab89UL; + mdContext->buf[2] = 0x98badcfeUL; + mdContext->buf[3] = 0x10325476UL; +} + +void +krb5int_MD4Update (krb5_MD4_CTX *mdContext, const unsigned char *inBuf, unsigned int inLen) +{ + krb5_ui_4 in[16]; + int mdi; + unsigned int i, ii; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((krb5_ui_4)inLen << 3)) < mdContext->i[0]) + mdContext->i[1]++; + mdContext->i[0] += ((krb5_ui_4)inLen << 3); + mdContext->i[1] += ((krb5_ui_4)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) { + in[i] = load_32_le(mdContext->in+ii); + } + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +void +krb5int_MD4Final (krb5_MD4_CTX *mdContext) +{ + krb5_ui_4 in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + krb5int_MD4Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = load_32_le(mdContext->in+ii); + Transform (mdContext->buf, in); + + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + store_32_le(mdContext->buf[i], mdContext->digest+ii); + } +} + +/* Basic MD4 step. Transform buf based on in. + */ +static void Transform (krb5_ui_4 *buf, krb5_ui_4 *in) +{ + krb5_ui_4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) + int i; +#define ROTATE { krb5_ui_4 temp; temp = d, d = c, c = b, b = a, a = temp; } + for (i = 0; i < 16; i++) { + static const unsigned char round1consts[] = { 3, 7, 11, 19, }; + FF (a, b, c, d, in[i], round1consts[i%4]); ROTATE; + } + for (i = 0; i < 16; i++) { + static const unsigned char round2indices[] = { + 0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15 + }; + static const unsigned char round2consts[] = { 3, 5, 9, 13 }; + GG (a, b, c, d, in[round2indices[i]], round2consts[i%4]); ROTATE; + } + for (i = 0; i < 16; i++) { + static const unsigned char round3indices[] = { + 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 + }; + static const unsigned char round3consts[] = { 3, 9, 11, 15 }; + HH (a, b, c, d, in[round3indices[i]], round3consts[i%4]); ROTATE; + } +#else + /* Round 1 */ + FF (a, b, c, d, in[ 0], 3); + FF (d, a, b, c, in[ 1], 7); + FF (c, d, a, b, in[ 2], 11); + FF (b, c, d, a, in[ 3], 19); + FF (a, b, c, d, in[ 4], 3); + FF (d, a, b, c, in[ 5], 7); + FF (c, d, a, b, in[ 6], 11); + FF (b, c, d, a, in[ 7], 19); + FF (a, b, c, d, in[ 8], 3); + FF (d, a, b, c, in[ 9], 7); + FF (c, d, a, b, in[10], 11); + FF (b, c, d, a, in[11], 19); + FF (a, b, c, d, in[12], 3); + FF (d, a, b, c, in[13], 7); + FF (c, d, a, b, in[14], 11); + FF (b, c, d, a, in[15], 19); + + /* Round 2 */ + GG (a, b, c, d, in[ 0], 3); + GG (d, a, b, c, in[ 4], 5); + GG (c, d, a, b, in[ 8], 9); + GG (b, c, d, a, in[12], 13); + GG (a, b, c, d, in[ 1], 3); + GG (d, a, b, c, in[ 5], 5); + GG (c, d, a, b, in[ 9], 9); + GG (b, c, d, a, in[13], 13); + GG (a, b, c, d, in[ 2], 3); + GG (d, a, b, c, in[ 6], 5); + GG (c, d, a, b, in[10], 9); + GG (b, c, d, a, in[14], 13); + GG (a, b, c, d, in[ 3], 3); + GG (d, a, b, c, in[ 7], 5); + GG (c, d, a, b, in[11], 9); + GG (b, c, d, a, in[15], 13); + + /* Round 3 */ + HH (a, b, c, d, in[ 0], 3); + HH (d, a, b, c, in[ 8], 9); + HH (c, d, a, b, in[ 4], 11); + HH (b, c, d, a, in[12], 15); + HH (a, b, c, d, in[ 2], 3); + HH (d, a, b, c, in[10], 9); + HH (c, d, a, b, in[ 6], 11); + HH (b, c, d, a, in[14], 15); + HH (a, b, c, d, in[ 1], 3); + HH (d, a, b, c, in[ 9], 9); + HH (c, d, a, b, in[ 5], 11); + HH (b, c, d, a, in[13], 15); + HH (a, b, c, d, in[ 3], 3); + HH (d, a, b, c, in[11], 9); + HH (c, d, a, b, in[ 7], 11); + HH (b, c, d, a, in[15], 15); +#endif + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +/* +********************************************************************** +** End of md4.c ** +******************************* (cut) ******************************** +*/ + +#endif /* K5_BUILTIN_MD4 */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/md4/rsa-md4.h b/krb5-1.21.3/src/lib/crypto/builtin/md4/rsa-md4.h new file mode 100644 index 00000000..c404e151 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/md4/rsa-md4.h @@ -0,0 +1,90 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/md4/rsa-md4.h */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + * + * License to copy and use this software is granted provided that + * it is identified as the "RSA Data Security, Inc. MD4 Message + * Digest Algorithm" in all material mentioning or referencing this + * software or this function. + * + * License is also granted to make and use derivative works + * provided that such works are identified as "derived from the RSA + * Data Security, Inc. MD4 Message Digest Algorithm" in all + * material mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning + * either the merchantability of this software or the suitability + * of this software for any particular purpose. It is provided "as + * is" without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +/* RSA MD4 header file, with Kerberos/STDC additions. */ + +#ifndef __KRB5_RSA_MD4_H__ +#define __KRB5_RSA_MD4_H__ + +#ifdef unicos61 +#include +#endif /* unicos61 */ + +/* 16 u_char's in the digest */ +#define RSA_MD4_CKSUM_LENGTH 16 +/* des blocksize is 8, so this works nicely... */ +#define OLD_RSA_MD4_DES_CKSUM_LENGTH 16 +#define NEW_RSA_MD4_DES_CKSUM_LENGTH 24 +#define RSA_MD4_DES_CONFOUND_LENGTH 8 + +/* +********************************************************************** +** md4.h -- Header file for implementation of MD4 ** +** RSA Data Security, Inc. MD4 Message Digest Algorithm ** +** Created: 2/17/90 RLR ** +** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** +********************************************************************** +*/ + +/* Data structure for MD4 (Message Digest) computation */ +typedef struct { + krb5_ui_4 i[2]; /* number of _bits_ handled mod 2^64 */ + krb5_ui_4 buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after MD4Final call */ +} krb5_MD4_CTX; + +extern void krb5int_MD4Init(krb5_MD4_CTX *); +extern void krb5int_MD4Update(krb5_MD4_CTX *, const unsigned char *, unsigned int); +extern void krb5int_MD4Final(krb5_MD4_CTX *); + +/* +********************************************************************** +** End of md4.h ** +******************************* (cut) ******************************** +*/ +#endif /* __KRB5_RSA_MD4_H__ */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/md5/ISSUES b/krb5-1.21.3/src/lib/crypto/builtin/md5/ISSUES new file mode 100644 index 00000000..631238ad --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/md5/ISSUES @@ -0,0 +1,4 @@ +Issues to be addressed for src/lib/crypto/md5: -*- text -*- + + +Assumes int is >= 32 bits. diff --git a/krb5-1.21.3/src/lib/crypto/builtin/md5/Makefile.in b/krb5-1.21.3/src/lib/crypto/builtin/md5/Makefile.in new file mode 100644 index 00000000..1b28d218 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/md5/Makefile.in @@ -0,0 +1,32 @@ +mydir=lib$(S)crypto$(S)builtin$(S)md5 +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES=-I$(srcdir)/../../krb $(CRYPTO_IMPL_CFLAGS) + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\md5 +##DOS##OBJFILE = ..\..\$(OUTPRE)md5.lst + +STLIBOBJS= md5.o + +OBJS= $(OUTPRE)md5.$(OBJEXT) + +SRCS= $(srcdir)/md5.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) + +check-unix: + +check-windows: + +clean: + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/builtin/md5/deps b/krb5-1.21.3/src/lib/crypto/builtin/md5/deps new file mode 100644 index 00000000..f727204d --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/md5/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +md5.so md5.po $(OUTPRE)md5.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + md5.c rsa-md5.h diff --git a/krb5-1.21.3/src/lib/crypto/builtin/md5/md5.c b/krb5-1.21.3/src/lib/crypto/builtin/md5/md5.c new file mode 100644 index 00000000..d5e018c7 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/md5/md5.c @@ -0,0 +1,346 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + * + * License to copy and use this software is granted provided that + * it is identified as the "RSA Data Security, Inc. MD5 Message- + * Digest Algorithm" in all material mentioning or referencing this + * software or this function. + * + * License is also granted to make and use derivative works + * provided that such works are identified as "derived from the RSA + * Data Security, Inc. MD5 Message-Digest Algorithm" in all + * material mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning + * either the merchantability of this software or the suitability + * of this software for any particular purpose. It is provided "as + * is" without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +/* +*********************************************************************** +** md5.c -- the source code for MD5 routines ** +** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** +** Created: 2/17/90 RLR ** +** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. ** +*********************************************************************** +*/ + +/* + * Modified by John Carr, MIT, to use Kerberos 5 typedefs. + */ + +#include "crypto_int.h" +#include "rsa-md5.h" + +#ifdef K5_BUILTIN_MD5 + +/* +*********************************************************************** +** Message-digest routines: ** +** To form the message digest for a message M ** +** (1) Initialize a context buffer mdContext using krb5int_MD5Init ** +** (2) Call krb5int_MD5Update on mdContext and M ** +** (3) Call krb5int_MD5Final on mdContext ** +** The message digest is now in mdContext->digest[0...15] ** +*********************************************************************** +*/ + +/* forward declaration */ +static void Transform (krb5_ui_4 *buf, krb5_ui_4 *in); + +static const unsigned char PADDING[64] = { + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* F, G, H and I are basic MD5 functions */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits */ +#define ROTATE_LEFT(x, n) ((((x) << (n)) & 0xffffffff) | ((x) >> (32-(n)))) + +/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ +/* Rotation is separate from addition to prevent recomputation */ +#define FF(a, b, c, d, x, s, ac) \ + {(a) += F ((b), (c), (d)) + (x) + (krb5_ui_4)(ac); \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + (a) &= 0xffffffff; \ + } +#define GG(a, b, c, d, x, s, ac) \ + {(a) += G ((b), (c), (d)) + (x) + (krb5_ui_4)(ac); \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + (a) &= 0xffffffff; \ + } +#define HH(a, b, c, d, x, s, ac) \ + {(a) += H ((b), (c), (d)) + (x) + (krb5_ui_4)(ac); \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + (a) &= 0xffffffff; \ + } +#define II(a, b, c, d, x, s, ac) \ + {(a) += I ((b), (c), (d)) + (x) + (krb5_ui_4)(ac); \ + (a) &= 0xffffffff; \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + (a) &= 0xffffffff; \ + } + +/* The routine krb5int_MD5Init initializes the message-digest context + mdContext. All fields are set to zero. +*/ +void +krb5int_MD5Init (krb5_MD5_CTX *mdContext) +{ + mdContext->i[0] = mdContext->i[1] = (krb5_ui_4)0; + + /* Load magic initialization constants. + */ + mdContext->buf[0] = 0x67452301UL; + mdContext->buf[1] = 0xefcdab89UL; + mdContext->buf[2] = 0x98badcfeUL; + mdContext->buf[3] = 0x10325476UL; +} + +/* The routine krb5int_MD5Update updates the message-digest context to + account for the presence of each of the characters inBuf[0..inLen-1] + in the message whose digest is being computed. +*/ +void +krb5int_MD5Update (krb5_MD5_CTX *mdContext, const unsigned char *inBuf, unsigned int inLen) +{ + krb5_ui_4 in[16]; + int mdi; + unsigned int i, ii; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* update number of bits */ + if ((mdContext->i[0] + ((krb5_ui_4)inLen << 3)) < mdContext->i[0]) + mdContext->i[1]++; + mdContext->i[0] += ((krb5_ui_4)inLen << 3); + mdContext->i[1] += ((krb5_ui_4)inLen >> 29); + + while (inLen--) { + /* add new character to buffer, increment mdi */ + mdContext->in[mdi++] = *inBuf++; + + /* transform if necessary */ + if (mdi == 0x40) { + for (i = 0, ii = 0; i < 16; i++, ii += 4) + in[i] = load_32_le(mdContext->in+ii); + Transform (mdContext->buf, in); + mdi = 0; + } + } +} + +/* The routine krb5int_MD5Final terminates the message-digest computation and + ends with the desired message digest in mdContext->digest[0...15]. +*/ +void +krb5int_MD5Final (krb5_MD5_CTX *mdContext) +{ + krb5_ui_4 in[16]; + int mdi; + unsigned int i, ii; + unsigned int padLen; + + /* save number of bits */ + in[14] = mdContext->i[0]; + in[15] = mdContext->i[1]; + + /* compute number of bytes mod 64 */ + mdi = (int)((mdContext->i[0] >> 3) & 0x3F); + + /* pad out to 56 mod 64 */ + padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); + krb5int_MD5Update (mdContext, PADDING, padLen); + + /* append length in bits and transform */ + for (i = 0, ii = 0; i < 14; i++, ii += 4) + in[i] = load_32_le(mdContext->in+ii); + Transform (mdContext->buf, in); + + /* store buffer in digest */ + for (i = 0, ii = 0; i < 4; i++, ii += 4) { + store_32_le(mdContext->buf[i], mdContext->digest+ii); + } +} + +/* Basic MD5 step. Transforms buf based on in. + */ +static void Transform (krb5_ui_4 *buf, krb5_ui_4 *in) +{ + krb5_ui_4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) + + int i; +#define ROTATE { krb5_ui_4 temp; temp = d, d = c, c = b, b = a, a = temp; } + for (i = 0; i < 16; i++) { + const unsigned char round1s[] = { 7, 12, 17, 22 }; + const krb5_ui_4 round1consts[] = { + 3614090360UL, 3905402710UL, 606105819UL, 3250441966UL, + 4118548399UL, 1200080426UL, 2821735955UL, 4249261313UL, + 1770035416UL, 2336552879UL, 4294925233UL, 2304563134UL, + 1804603682UL, 4254626195UL, 2792965006UL, 1236535329UL, + }; + FF (a, b, c, d, in[i], round1s[i%4], round1consts[i]); + ROTATE; + } + for (i = 0; i < 16; i++) { + const unsigned char round2s[] = { 5, 9, 14, 20 }; + const krb5_ui_4 round2consts[] = { + 4129170786UL, 3225465664UL, 643717713UL, 3921069994UL, + 3593408605UL, 38016083UL, 3634488961UL, 3889429448UL, + 568446438UL, 3275163606UL, 4107603335UL, 1163531501UL, + 2850285829UL, 4243563512UL, 1735328473UL, 2368359562UL, + }; + int r2index = (1 + i * 5) % 16; + GG (a, b, c, d, in[r2index], round2s[i%4], round2consts[i]); + ROTATE; + } + for (i = 0; i < 16; i++) { + static const unsigned char round3s[] = { 4, 11, 16, 23 }; + static const krb5_ui_4 round3consts[] = { + 4294588738UL, 2272392833UL, 1839030562UL, 4259657740UL, + 2763975236UL, 1272893353UL, 4139469664UL, 3200236656UL, + 681279174UL, 3936430074UL, 3572445317UL, 76029189UL, + 3654602809UL, 3873151461UL, 530742520UL, 3299628645UL, + }; + int r3index = (5 + i * 3) % 16; + HH (a, b, c, d, in[r3index], round3s[i%4], round3consts[i]); + ROTATE; + } + for (i = 0; i < 16; i++) { + static const unsigned char round4s[] = { 6, 10, 15, 21 }; + static const krb5_ui_4 round4consts[] = { + 4096336452UL, 1126891415UL, 2878612391UL, 4237533241UL, + 1700485571UL, 2399980690UL, 4293915773UL, 2240044497UL, + 1873313359UL, 4264355552UL, 2734768916UL, 1309151649UL, + 4149444226UL, 3174756917UL, 718787259UL, 3951481745UL, + }; + int r4index = (7 * i) % 16; + II (a, b, c, d, in[r4index], round4s[i%4], round4consts[i]); + ROTATE; + } + +#else + + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF ( a, b, c, d, in[ 0], S11, 3614090360UL); /* 1 */ + FF ( d, a, b, c, in[ 1], S12, 3905402710UL); /* 2 */ + FF ( c, d, a, b, in[ 2], S13, 606105819UL); /* 3 */ + FF ( b, c, d, a, in[ 3], S14, 3250441966UL); /* 4 */ + FF ( a, b, c, d, in[ 4], S11, 4118548399UL); /* 5 */ + FF ( d, a, b, c, in[ 5], S12, 1200080426UL); /* 6 */ + FF ( c, d, a, b, in[ 6], S13, 2821735955UL); /* 7 */ + FF ( b, c, d, a, in[ 7], S14, 4249261313UL); /* 8 */ + FF ( a, b, c, d, in[ 8], S11, 1770035416UL); /* 9 */ + FF ( d, a, b, c, in[ 9], S12, 2336552879UL); /* 10 */ + FF ( c, d, a, b, in[10], S13, 4294925233UL); /* 11 */ + FF ( b, c, d, a, in[11], S14, 2304563134UL); /* 12 */ + FF ( a, b, c, d, in[12], S11, 1804603682UL); /* 13 */ + FF ( d, a, b, c, in[13], S12, 4254626195UL); /* 14 */ + FF ( c, d, a, b, in[14], S13, 2792965006UL); /* 15 */ + FF ( b, c, d, a, in[15], S14, 1236535329UL); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG ( a, b, c, d, in[ 1], S21, 4129170786UL); /* 17 */ + GG ( d, a, b, c, in[ 6], S22, 3225465664UL); /* 18 */ + GG ( c, d, a, b, in[11], S23, 643717713UL); /* 19 */ + GG ( b, c, d, a, in[ 0], S24, 3921069994UL); /* 20 */ + GG ( a, b, c, d, in[ 5], S21, 3593408605UL); /* 21 */ + GG ( d, a, b, c, in[10], S22, 38016083UL); /* 22 */ + GG ( c, d, a, b, in[15], S23, 3634488961UL); /* 23 */ + GG ( b, c, d, a, in[ 4], S24, 3889429448UL); /* 24 */ + GG ( a, b, c, d, in[ 9], S21, 568446438UL); /* 25 */ + GG ( d, a, b, c, in[14], S22, 3275163606UL); /* 26 */ + GG ( c, d, a, b, in[ 3], S23, 4107603335UL); /* 27 */ + GG ( b, c, d, a, in[ 8], S24, 1163531501UL); /* 28 */ + GG ( a, b, c, d, in[13], S21, 2850285829UL); /* 29 */ + GG ( d, a, b, c, in[ 2], S22, 4243563512UL); /* 30 */ + GG ( c, d, a, b, in[ 7], S23, 1735328473UL); /* 31 */ + GG ( b, c, d, a, in[12], S24, 2368359562UL); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH ( a, b, c, d, in[ 5], S31, 4294588738UL); /* 33 */ + HH ( d, a, b, c, in[ 8], S32, 2272392833UL); /* 34 */ + HH ( c, d, a, b, in[11], S33, 1839030562UL); /* 35 */ + HH ( b, c, d, a, in[14], S34, 4259657740UL); /* 36 */ + HH ( a, b, c, d, in[ 1], S31, 2763975236UL); /* 37 */ + HH ( d, a, b, c, in[ 4], S32, 1272893353UL); /* 38 */ + HH ( c, d, a, b, in[ 7], S33, 4139469664UL); /* 39 */ + HH ( b, c, d, a, in[10], S34, 3200236656UL); /* 40 */ + HH ( a, b, c, d, in[13], S31, 681279174UL); /* 41 */ + HH ( d, a, b, c, in[ 0], S32, 3936430074UL); /* 42 */ + HH ( c, d, a, b, in[ 3], S33, 3572445317UL); /* 43 */ + HH ( b, c, d, a, in[ 6], S34, 76029189UL); /* 44 */ + HH ( a, b, c, d, in[ 9], S31, 3654602809UL); /* 45 */ + HH ( d, a, b, c, in[12], S32, 3873151461UL); /* 46 */ + HH ( c, d, a, b, in[15], S33, 530742520UL); /* 47 */ + HH ( b, c, d, a, in[ 2], S34, 3299628645UL); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II ( a, b, c, d, in[ 0], S41, 4096336452UL); /* 49 */ + II ( d, a, b, c, in[ 7], S42, 1126891415UL); /* 50 */ + II ( c, d, a, b, in[14], S43, 2878612391UL); /* 51 */ + II ( b, c, d, a, in[ 5], S44, 4237533241UL); /* 52 */ + II ( a, b, c, d, in[12], S41, 1700485571UL); /* 53 */ + II ( d, a, b, c, in[ 3], S42, 2399980690UL); /* 54 */ + II ( c, d, a, b, in[10], S43, 4293915773UL); /* 55 */ + II ( b, c, d, a, in[ 1], S44, 2240044497UL); /* 56 */ + II ( a, b, c, d, in[ 8], S41, 1873313359UL); /* 57 */ + II ( d, a, b, c, in[15], S42, 4264355552UL); /* 58 */ + II ( c, d, a, b, in[ 6], S43, 2734768916UL); /* 59 */ + II ( b, c, d, a, in[13], S44, 1309151649UL); /* 60 */ + II ( a, b, c, d, in[ 4], S41, 4149444226UL); /* 61 */ + II ( d, a, b, c, in[11], S42, 3174756917UL); /* 62 */ + II ( c, d, a, b, in[ 2], S43, 718787259UL); /* 63 */ + II ( b, c, d, a, in[ 9], S44, 3951481745UL); /* 64 */ + +#endif /* small? */ + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +#endif /* K5_BUILTIN_MD5 */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/md5/rsa-md5.h b/krb5-1.21.3/src/lib/crypto/builtin/md5/rsa-md5.h new file mode 100644 index 00000000..cbdf67cf --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/md5/rsa-md5.h @@ -0,0 +1,59 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. + * + * License to copy and use this software is granted provided that + * it is identified as the "RSA Data Security, Inc. MD5 Message- + * Digest Algorithm" in all material mentioning or referencing this + * software or this function. + * + * License is also granted to make and use derivative works + * provided that such works are identified as "derived from the RSA + * Data Security, Inc. MD5 Message-Digest Algorithm" in all + * material mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning + * either the merchantability of this software or the suitability + * of this software for any particular purpose. It is provided "as + * is" without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +/* +*********************************************************************** +** md5.h -- header file for implementation of MD5 ** +** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** +** Created: 2/17/90 RLR ** +** Revised: 12/27/90 SRD,AJ,BSK,JT Reference C version ** +** Revised (for MD5): RLR 4/27/91 ** +** -- G modified to have y&~z instead of y&z ** +** -- FF, GG, HH modified to add in last register done ** +** -- Access pattern: round 2 works mod 5, round 3 works mod 3 ** +** -- distinct additive constant for each step ** +** -- round 4 added, working mod 7 ** +*********************************************************************** +*/ + +#ifndef KRB5_RSA_MD5__ +#define KRB5_RSA_MD5__ + +/* Data structure for MD5 (Message-Digest) computation */ +typedef struct { + krb5_ui_4 i[2]; /* number of _bits_ handled mod 2^64 */ + krb5_ui_4 buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ + unsigned char digest[16]; /* actual digest after MD5Final call */ +} krb5_MD5_CTX; + +extern void krb5int_MD5Init(krb5_MD5_CTX *); +extern void krb5int_MD5Update(krb5_MD5_CTX *,const unsigned char *,unsigned int); +extern void krb5int_MD5Final(krb5_MD5_CTX *); + +#define RSA_MD5_CKSUM_LENGTH 16 +#define OLD_RSA_MD5_DES_CKSUM_LENGTH 16 +#define NEW_RSA_MD5_DES_CKSUM_LENGTH 24 +#define RSA_MD5_DES_CONFOUND_LENGTH 8 + +#endif /* KRB5_RSA_MD5__ */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/pbkdf2.c b/krb5-1.21.3/src/lib/crypto/builtin/pbkdf2.c new file mode 100644 index 00000000..d7a03a32 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/pbkdf2.c @@ -0,0 +1,221 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/pbkdf2.c - Implementation of PBKDF2 from RFC 2898 */ +/* + * Copyright 2002, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include "crypto_int.h" + +#ifdef K5_BUILTIN_PBKDF2 + +/* + * RFC 2898 specifies PBKDF2 in terms of an underlying pseudo-random + * function with two arguments (password and salt||blockindex). Right + * now we only use PBKDF2 with the hmac-sha1 PRF, also specified in + * RFC 2898, which invokes HMAC with the password as the key and the + * second argument as the text. (HMAC accepts any key size up to the + * block size; the password is pre-hashed with unkeyed SHA1 if it is + * longer than the block size.) + * + * For efficiency, it is better to generate the key from the password + * once at the beginning, so we specify prf_fn in terms of a + * krb5_key first argument. That might not be convenient for a PRF + * which uses the password in some other way, so this might need to be + * adjusted in the future. + */ + +typedef krb5_error_code (*prf_fn)(krb5_key pass, krb5_data *salt, + krb5_data *out); + +static int debug_hmac = 0; + +static void printd (const char *descr, krb5_data *d) { + unsigned int i, j; + const int r = 16; + + printf("%s:", descr); + + for (i = 0; i < d->length; i += r) { + printf("\n %04x: ", i); + for (j = i; j < i + r && j < d->length; j++) + printf(" %02x", 0xff & d->data[j]); + for (; j < i + r; j++) + printf(" "); + printf(" "); + for (j = i; j < i + r && j < d->length; j++) { + int c = 0xff & d->data[j]; + printf("%c", isprint(c) ? c : '.'); + } + } + printf("\n"); +} + +/* + * Implements the hmac-sha1 PRF. pass has been pre-hashed (if + * necessary) and converted to a key already; salt has had the block + * index appended to the original salt. + * + * NetBSD 8 declares an hmac() function in stdlib.h, so avoid that name. + */ +static krb5_error_code +k5_hmac(const struct krb5_hash_provider *hash, krb5_keyblock *pass, + krb5_data *salt, krb5_data *out) +{ + krb5_error_code err; + krb5_crypto_iov iov; + + if (debug_hmac) + printd(" hmac input", salt); + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *salt; + err = krb5int_hmac_keyblock(hash, pass, &iov, 1, out); + if (err == 0 && debug_hmac) + printd(" hmac output", out); + return err; +} + +static krb5_error_code +F(char *output, char *u_tmp1, char *u_tmp2, + const struct krb5_hash_provider *hash, size_t hlen, krb5_keyblock *pass, + const krb5_data *salt, unsigned long count, int i) +{ + unsigned char ibytes[4]; + unsigned int j, k; + krb5_data sdata; + krb5_data out; + krb5_error_code err; + + /* Compute U_1. */ + store_32_be(i, ibytes); + + memcpy(u_tmp2, salt->data, salt->length); + memcpy(u_tmp2 + salt->length, ibytes, 4); + sdata = make_data(u_tmp2, salt->length + 4); + + out = make_data(u_tmp1, hlen); + + err = k5_hmac(hash, pass, &sdata, &out); + if (err) + return err; + + memcpy(output, u_tmp1, hlen); + + /* Compute U_2, .. U_c. */ + sdata.length = hlen; + for (j = 2; j <= count; j++) { + memcpy(u_tmp2, u_tmp1, hlen); + err = k5_hmac(hash, pass, &sdata, &out); + if (err) + return err; + + /* And xor them together. */ + for (k = 0; k < hlen; k++) + output[k] ^= u_tmp1[k]; + } + return 0; +} + +static krb5_error_code +pbkdf2(const struct krb5_hash_provider *hash, krb5_keyblock *pass, + const krb5_data *salt, unsigned long count, const krb5_data *output) +{ + size_t hlen = hash->hashsize; + int l, i; + char *utmp1, *utmp2; + char utmp3[128]; /* XXX length shouldn't be hardcoded! */ + + if (output->length == 0 || hlen == 0) + abort(); + /* Step 1 & 2. */ + if (output->length / hlen > 0xffffffff) + abort(); + /* Step 2. */ + l = (output->length + hlen - 1) / hlen; + + utmp1 = /*output + dklen; */ malloc(hlen); + if (utmp1 == NULL) + return ENOMEM; + utmp2 = /*utmp1 + hlen; */ malloc(salt->length + 4 + hlen); + if (utmp2 == NULL) { + free(utmp1); + return ENOMEM; + } + + /* Step 3. */ + for (i = 1; i <= l; i++) { + krb5_error_code err; + char *out; + + if (i == l) + out = utmp3; + else + out = output->data + (i-1) * hlen; + err = F(out, utmp1, utmp2, hash, hlen, pass, salt, count, i); + if (err) { + free(utmp1); + free(utmp2); + return err; + } + if (i == l) + memcpy(output->data + (i-1) * hlen, utmp3, + output->length - (i-1) * hlen); + + } + free(utmp1); + free(utmp2); + return 0; +} + +krb5_error_code +krb5int_pbkdf2_hmac(const struct krb5_hash_provider *hash, + const krb5_data *out, unsigned long count, + const krb5_data *pass, const krb5_data *salt) +{ + krb5_keyblock keyblock; + char tmp[128]; + krb5_data d; + krb5_crypto_iov iov; + krb5_error_code err; + + assert(hash->hashsize <= sizeof(tmp)); + if (pass->length > hash->blocksize) { + d = make_data(tmp, hash->hashsize); + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *pass; + err = hash->hash(&iov, 1, &d); + if (err) + return err; + keyblock.length = d.length; + keyblock.contents = (krb5_octet *) d.data; + } else { + keyblock.length = pass->length; + keyblock.contents = (krb5_octet *) pass->data; + } + keyblock.enctype = ENCTYPE_NULL; + + err = pbkdf2(hash, &keyblock, salt, count, out); + return err; +} + +#endif /* K5_BUILTIN_PBKDF2 */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/sha1/ISSUES b/krb5-1.21.3/src/lib/crypto/builtin/sha1/ISSUES new file mode 100644 index 00000000..c63faf6e --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/sha1/ISSUES @@ -0,0 +1,8 @@ +Issues to be addressed for src/lib/crypto/sha1: -*- text -*- + + +Assumes int (look for "count") is >= 32 bits. + +Changing the types of internal variables is easy, but shsUpdate takes +an int parameter; changing that could change the ABI on some +platforms. diff --git a/krb5-1.21.3/src/lib/crypto/builtin/sha1/Makefile.in b/krb5-1.21.3/src/lib/crypto/builtin/sha1/Makefile.in new file mode 100644 index 00000000..e9da10c6 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/sha1/Makefile.in @@ -0,0 +1,47 @@ +mydir=lib$(S)crypto$(S)builtin$(S)sha1 +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES=-I$(srcdir)/../../krb $(CRYPTO_IMPL_CFLAGS) + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\sha1 +##DOS##OBJFILE = ..\..\$(OUTPRE)sha1.lst + +STLIBOBJS= shs.o + +OBJS= $(OUTPRE)shs.$(OBJEXT) + +SRCS= $(srcdir)/shs.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) +t_shs: t_shs.o shs.o $(SUPPORT_DEPLIB) + $(CC_LINK) -o t_shs t_shs.o shs.o $(SUPPORT_LIB) + +$(OUTPRE)t_shs.exe: $(OUTPRE)t_shs.obj $(OUTPRE)shs.obj + link -out:$@ $** + +t_shs3: t_shs3.o shs.o $(SUPPORT_DEPLIB) + $(CC_LINK) -o t_shs3 t_shs3.o shs.o $(SUPPORT_LIB) + +check-unix: check-unix-@CRYPTO_BUILTIN_TESTS@ +check-unix-no: +check-unix-yes: t_shs t_shs3 + $(RUN_TEST) $(C)t_shs -x + $(RUN_TEST) $(C)t_shs3 + +check-windows: $(OUTPRE)t_shs.exe $(OUTPRE)t_shs3.exe + $(OUTPRE)$(C)t_shs.exe -x + $(OUTPRE)$(C)t_shs3.exe + +clean: + $(RM) t_shs$(EXEEXT) t_shs.$(OBJEXT) t_shs3$(EXEEXT) t_shs3.$(OBJEXT) + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/builtin/sha1/deps b/krb5-1.21.3/src/lib/crypto/builtin/sha1/deps new file mode 100644 index 00000000..245a4bf2 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/sha1/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +shs.so shs.po $(OUTPRE)shs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + shs.c shs.h diff --git a/krb5-1.21.3/src/lib/crypto/builtin/sha1/shs.c b/krb5-1.21.3/src/lib/crypto/builtin/sha1/shs.c new file mode 100644 index 00000000..f43bd614 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/sha1/shs.c @@ -0,0 +1,386 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include "shs.h" +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#include + +#ifdef K5_BUILTIN_SHA1 + +/* The SHS f()-functions. The f1 and f3 functions can be optimized to + save one boolean operation each - thanks to Rich Schroeppel, + rcs@cs.arizona.edu for discovering this */ + +#define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */ +#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ +#define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */ +#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ + +/* The SHS Mysterious Constants */ + +#define K1 0x5A827999L /* Rounds 0-19 */ +#define K2 0x6ED9EBA1L /* Rounds 20-39 */ +#define K3 0x8F1BBCDCL /* Rounds 40-59 */ +#define K4 0xCA62C1D6L /* Rounds 60-79 */ + +/* SHS initial values */ + +#define h0init 0x67452301L +#define h1init 0xEFCDAB89L +#define h2init 0x98BADCFEL +#define h3init 0x10325476L +#define h4init 0xC3D2E1F0L + +/* Note that it may be necessary to add parentheses to these macros if they + are to be called with expressions as arguments */ + +/* 32-bit rotate left - kludged with shifts */ + +#define ROTL(n,X) ((((X) << (n)) & 0xffffffff) | ((X) >> (32 - n))) + +/* The initial expanding function. The hash function is defined over an + 80-word expanded input array W, where the first 16 are copies of the input + data, and the remaining 64 are defined by + + W[ i ] = W[ i - 16 ] ^ W[ i - 14 ] ^ W[ i - 8 ] ^ W[ i - 3 ] + + This implementation generates these values on the fly in a circular + buffer - thanks to Colin Plumb, colin@nyx10.cs.du.edu for this + optimization. + + The updated SHS changes the expanding function by adding a rotate of 1 + bit. Thanks to Jim Gillogly, jim@rand.org, and an anonymous contributor + for this information */ + +#ifdef NEW_SHS +#define expand(W,i) ( W[ i & 15 ] = ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \ + W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ))) +#else +#define expand(W,i) ( W[ i & 15 ] ^= W[ (i - 14) & 15 ] ^ \ + W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) +#endif /* NEW_SHS */ + +/* The prototype SHS sub-round. The fundamental sub-round is: + + a' = e + ROTL( 5, a ) + f( b, c, d ) + k + data; + b' = a; + c' = ROTL( 30, b ); + d' = c; + e' = d; + + but this is implemented by unrolling the loop 5 times and renaming the + variables ( e, a, b, c, d ) = ( a', b', c', d', e' ) each iteration. + This code is then replicated 20 times for each of the 4 functions, using + the next 20 values from the W[] array each time */ + +#define subRound(a, b, c, d, e, f, k, data) \ + ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, \ + e &= 0xffffffff, b = ROTL( 30, b ) ) + +/* Initialize the SHS values */ + +void shsInit(SHS_INFO *shsInfo) +{ + /* Set the h-vars to their initial values */ + shsInfo->digest[ 0 ] = h0init; + shsInfo->digest[ 1 ] = h1init; + shsInfo->digest[ 2 ] = h2init; + shsInfo->digest[ 3 ] = h3init; + shsInfo->digest[ 4 ] = h4init; + + /* Initialise bit count */ + shsInfo->countLo = shsInfo->countHi = 0; +} + +/* Perform the SHS transformation. Note that this code, like MD5, seems to + break some optimizing compilers due to the complexity of the expressions + and the size of the basic block. It may be necessary to split it into + sections, e.g. based on the four subrounds + + Note that this corrupts the shsInfo->data area */ + +static void SHSTransform (SHS_LONG *digest, const SHS_LONG *data); + +static +void SHSTransform(SHS_LONG *digest, const SHS_LONG *data) +{ + SHS_LONG A, B, C, D, E; /* Local vars */ + SHS_LONG eData[ 16 ]; /* Expanded data */ + + /* Set up first buffer and local data buffer */ + A = digest[ 0 ]; + B = digest[ 1 ]; + C = digest[ 2 ]; + D = digest[ 3 ]; + E = digest[ 4 ]; + memcpy(eData, data, sizeof (eData)); + +#if defined(CONFIG_SMALL) && !defined(CONFIG_SMALL_NO_CRYPTO) + + { + int i; + SHS_LONG temp; + for (i = 0; i < 20; i++) { + SHS_LONG x = (i < 16) ? eData[i] : expand(eData, i); + subRound(A, B, C, D, E, f1, K1, x); + temp = E, E = D, D = C, C = B, B = A, A = temp; + } + for (i = 20; i < 40; i++) { + subRound(A, B, C, D, E, f2, K2, expand(eData, i)); + temp = E, E = D, D = C, C = B, B = A, A = temp; + } + for (i = 40; i < 60; i++) { + subRound(A, B, C, D, E, f3, K3, expand(eData, i)); + temp = E, E = D, D = C, C = B, B = A, A = temp; + } + for (i = 60; i < 80; i++) { + subRound(A, B, C, D, E, f4, K4, expand(eData, i)); + temp = E, E = D, D = C, C = B, B = A, A = temp; + } + } + +#else + + /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */ + subRound( A, B, C, D, E, f1, K1, eData[ 0 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 1 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 2 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 3 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 4 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 5 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 6 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 7 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 8 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 9 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 10 ] ); + subRound( E, A, B, C, D, f1, K1, eData[ 11 ] ); + subRound( D, E, A, B, C, f1, K1, eData[ 12 ] ); + subRound( C, D, E, A, B, f1, K1, eData[ 13 ] ); + subRound( B, C, D, E, A, f1, K1, eData[ 14 ] ); + subRound( A, B, C, D, E, f1, K1, eData[ 15 ] ); + subRound( E, A, B, C, D, f1, K1, expand( eData, 16 ) ); + subRound( D, E, A, B, C, f1, K1, expand( eData, 17 ) ); + subRound( C, D, E, A, B, f1, K1, expand( eData, 18 ) ); + subRound( B, C, D, E, A, f1, K1, expand( eData, 19 ) ); + + subRound( A, B, C, D, E, f2, K2, expand( eData, 20 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 21 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 22 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 23 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 24 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 25 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 26 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 27 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 28 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 29 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 30 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 31 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 32 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 33 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 34 ) ); + subRound( A, B, C, D, E, f2, K2, expand( eData, 35 ) ); + subRound( E, A, B, C, D, f2, K2, expand( eData, 36 ) ); + subRound( D, E, A, B, C, f2, K2, expand( eData, 37 ) ); + subRound( C, D, E, A, B, f2, K2, expand( eData, 38 ) ); + subRound( B, C, D, E, A, f2, K2, expand( eData, 39 ) ); + + subRound( A, B, C, D, E, f3, K3, expand( eData, 40 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 41 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 42 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 43 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 44 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 45 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 46 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 47 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 48 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 49 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 50 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 51 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 52 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 53 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 54 ) ); + subRound( A, B, C, D, E, f3, K3, expand( eData, 55 ) ); + subRound( E, A, B, C, D, f3, K3, expand( eData, 56 ) ); + subRound( D, E, A, B, C, f3, K3, expand( eData, 57 ) ); + subRound( C, D, E, A, B, f3, K3, expand( eData, 58 ) ); + subRound( B, C, D, E, A, f3, K3, expand( eData, 59 ) ); + + subRound( A, B, C, D, E, f4, K4, expand( eData, 60 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 61 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 62 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 63 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 64 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 65 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 66 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 67 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 68 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 69 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 70 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 71 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 72 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 73 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 74 ) ); + subRound( A, B, C, D, E, f4, K4, expand( eData, 75 ) ); + subRound( E, A, B, C, D, f4, K4, expand( eData, 76 ) ); + subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) ); + subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) ); + subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) ); + +#endif + + /* Build message digest */ + digest[ 0 ] += A; + digest[ 0 ] &= 0xffffffff; + digest[ 1 ] += B; + digest[ 1 ] &= 0xffffffff; + digest[ 2 ] += C; + digest[ 2 ] &= 0xffffffff; + digest[ 3 ] += D; + digest[ 3 ] &= 0xffffffff; + digest[ 4 ] += E; + digest[ 4 ] &= 0xffffffff; +} + +/* Update SHS for a block of data */ + +void shsUpdate(SHS_INFO *shsInfo, const SHS_BYTE *buffer, unsigned int count) +{ + SHS_LONG tmp; + unsigned int dataCount; + int canfill; + SHS_LONG *lp; + + /* Update bitcount */ + tmp = shsInfo->countLo; + shsInfo->countLo = tmp + (((SHS_LONG) count) << 3 ); + if ((shsInfo->countLo &= 0xffffffff) < tmp) + shsInfo->countHi++; /* Carry from low to high */ + shsInfo->countHi += count >> 29; + + /* Get count of bytes already in data */ + dataCount = (tmp >> 3) & 0x3F; + + /* Handle any leading odd-sized chunks */ + if (dataCount) { + lp = shsInfo->data + dataCount / 4; + dataCount = SHS_DATASIZE - dataCount; + canfill = (count >= dataCount); + + if (dataCount % 4) { + /* Fill out a full 32 bit word first if needed -- this + is not very efficient (computed shift amount), + but it shouldn't happen often. */ + while (dataCount % 4 && count > 0) { + *lp |= (SHS_LONG) *buffer++ << ((--dataCount % 4) * 8); + count--; + } + lp++; + } + while (lp < shsInfo->data + 16) { + if (count < 4) { + *lp = 0; + switch (count % 4) { + case 3: + *lp |= (SHS_LONG) buffer[2] << 8; + case 2: + *lp |= (SHS_LONG) buffer[1] << 16; + case 1: + *lp |= (SHS_LONG) buffer[0] << 24; + } + count = 0; + break; /* out of while loop */ + } + *lp++ = load_32_be(buffer); + buffer += 4; + count -= 4; + } + if (canfill) { + SHSTransform(shsInfo->digest, shsInfo->data); + } + } + + /* Process data in SHS_DATASIZE chunks */ + while (count >= SHS_DATASIZE) { + lp = shsInfo->data; + while (lp < shsInfo->data + 16) { + *lp++ = load_32_be(buffer); + buffer += 4; + } + SHSTransform(shsInfo->digest, shsInfo->data); + count -= SHS_DATASIZE; + } + + if (count > 0) { + lp = shsInfo->data; + while (count > 4) { + *lp++ = load_32_be(buffer); + buffer += 4; + count -= 4; + } + *lp = 0; + switch (count % 4) { + case 0: + *lp |= ((SHS_LONG) buffer[3]); + case 3: + *lp |= ((SHS_LONG) buffer[2]) << 8; + case 2: + *lp |= ((SHS_LONG) buffer[1]) << 16; + case 1: + *lp |= ((SHS_LONG) buffer[0]) << 24; + } + } +} + +/* Final wrapup - pad to SHS_DATASIZE-byte boundary with the bit pattern + 1 0* (64-bit count of bits processed, MSB-first) */ + +void shsFinal(SHS_INFO *shsInfo) +{ + int count; + SHS_LONG *lp; + + /* Compute number of bytes mod 64 */ + count = (int) shsInfo->countLo; + count = (count >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + lp = shsInfo->data + count / 4; + switch (count % 4) { + case 3: + *lp++ |= (SHS_LONG) 0x80; + break; + case 2: + *lp++ |= (SHS_LONG) 0x80 << 8; + break; + case 1: + *lp++ |= (SHS_LONG) 0x80 << 16; + break; + case 0: + *lp++ = (SHS_LONG) 0x80 << 24; + } + + /* at this point, lp can point *past* shsInfo->data. If it points + there, just Transform and reset. If it points to the last + element, set that to zero. This pads out to 64 bytes if not + enough room for length words */ + + if (lp == shsInfo->data + 15) + *lp++ = 0; + + if (lp == shsInfo->data + 16) { + SHSTransform(shsInfo->digest, shsInfo->data); + lp = shsInfo->data; + } + + /* Pad out to 56 bytes */ + while (lp < shsInfo->data + 14) + *lp++ = 0; + + /* Append length in bits and transform */ + *lp++ = shsInfo->countHi; + *lp++ = shsInfo->countLo; + SHSTransform(shsInfo->digest, shsInfo->data); +} + +#endif /* K5_BUILTIN_SHA1 */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/sha1/shs.h b/krb5-1.21.3/src/lib/crypto/builtin/sha1/shs.h new file mode 100644 index 00000000..4f578eda --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/sha1/shs.h @@ -0,0 +1,46 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#ifndef _SHS_DEFINED + +#include "crypto_int.h" + +#define _SHS_DEFINED + +/* Some useful types */ + +typedef krb5_octet SHS_BYTE; +typedef krb5_ui_4 SHS_LONG; + +/* Define the following to use the updated SHS implementation */ +#define NEW_SHS /**/ + +/* The SHS block size and message digest sizes, in bytes */ + +#define SHS_DATASIZE 64 +#define SHS_DIGESTSIZE 20 + +/* The structure for storing SHS info */ + +typedef struct { + SHS_LONG digest[ 5 ]; /* Message digest */ + SHS_LONG countLo, countHi; /* 64-bit bit count */ + SHS_LONG data[ 16 ]; /* SHS data buffer */ +} SHS_INFO; + +/* Message digest functions (shs.c) */ +void shsInit(SHS_INFO *shsInfo); +void shsUpdate(SHS_INFO *shsInfo, const SHS_BYTE *buffer, unsigned int count); +void shsFinal(SHS_INFO *shsInfo); + + +/* Keyed Message digest functions (hmac_sha.c) */ +krb5_error_code hmac_sha(krb5_octet *text, + int text_len, + krb5_octet *key, + int key_len, + krb5_octet *digest); + + +#define NIST_SHA_CKSUM_LENGTH SHS_DIGESTSIZE +#define HMAC_SHA_CKSUM_LENGTH SHS_DIGESTSIZE + +#endif /* _SHS_DEFINED */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/sha1/t_shs.c b/krb5-1.21.3/src/lib/crypto/builtin/sha1/t_shs.c new file mode 100644 index 00000000..c1d18f55 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/sha1/t_shs.c @@ -0,0 +1,121 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/**************************************************************************** + * * + * SHS Test Code * + * * + ****************************************************************************/ + +#include +#include +#include +#include "shs.h" + +/* Test the SHS implementation */ + +#ifdef NEW_SHS + +static SHS_LONG shsTestResults[][ 5 ] = { + { 0xA9993E36L, 0x4706816AL, 0xBA3E2571L, 0x7850C26CL, 0x9CD0D89DL, }, + { 0x84983E44L, 0x1C3BD26EL, 0xBAAE4AA1L, 0xF95129E5L, 0xE54670F1L, }, + { 0x34AA973CL, 0xD4C4DAA4L, 0xF61EEB2BL, 0xDBAD2731L, 0x6534016FL, } +}; + +#else + +static SHS_LONG shsTestResults[][ 5 ] = { + { 0x0164B8A9L, 0x14CD2A5EL, 0x74C4F7FFL, 0x082C4D97L, 0xF1EDF880L }, + { 0xD2516EE1L, 0xACFA5BAFL, 0x33DFC1C4L, 0x71E43844L, 0x9EF134C8L }, + { 0x3232AFFAL, 0x48628A26L, 0x653B5AAAL, 0x44541FD9L, 0x0D690603L } +}; +#endif /* NEW_SHS */ + +static int compareSHSresults(shsInfo, shsTestLevel) + SHS_INFO *shsInfo; + int shsTestLevel; +{ + int i, fail = 0; + + /* Compare the returned digest and required values */ + for( i = 0; i < 5; i++ ) + if( shsInfo->digest[ i ] != shsTestResults[ shsTestLevel ][ i ] ) + fail = 1; + if (fail) { + printf("\nExpected: "); + for (i = 0; i < 5; i++) { + printf("%8.8lx ", (unsigned long) shsTestResults[shsTestLevel][i]); + } + printf("\nGot: "); + for (i = 0; i < 5; i++) { + printf("%8.8lx ", (unsigned long) shsInfo->digest[i]); + } + printf("\n"); + return( -1 ); + } + return( 0 ); +} + +int +main() +{ + SHS_INFO shsInfo; + unsigned int i; + + /* Make sure we've got the endianness set right. If the machine is + big-endian (up to 64 bits) the following value will be signed, + otherwise it will be unsigned. Unfortunately we can't test for odd + things like middle-endianness without knowing the size of the data + types */ + + /* Test SHS against values given in SHS standards document */ + printf( "Running SHS test 1 ... " ); + shsInit( &shsInfo ); + shsUpdate( &shsInfo, ( SHS_BYTE * ) "abc", 3 ); + shsFinal( &shsInfo ); + if( compareSHSresults( &shsInfo, 0 ) == -1 ) + { + putchar( '\n' ); + puts( "SHS test 1 failed" ); + exit( -1 ); + } +#ifdef NEW_SHS + puts( "passed, result= A9993E364706816ABA3E25717850C26C9CD0D89D" ); +#else + puts( "passed, result= 0164B8A914CD2A5E74C4F7FF082C4D97F1EDF880" ); +#endif /* NEW_SHS */ + + printf( "Running SHS test 2 ... " ); + shsInit( &shsInfo ); + shsUpdate( &shsInfo, ( SHS_BYTE * ) "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56 ); + shsFinal( &shsInfo ); + if( compareSHSresults( &shsInfo, 1 ) == -1 ) + { + putchar( '\n' ); + puts( "SHS test 2 failed" ); + exit( -1 ); + } +#ifdef NEW_SHS + puts( "passed, result= 84983E441C3BD26EBAAE4AA1F95129E5E54670F1" ); +#else + puts( "passed, result= D2516EE1ACFA5BAF33DFC1C471E438449EF134C8" ); +#endif /* NEW_SHS */ + + printf( "Running SHS test 3 ... " ); + shsInit( &shsInfo ); + for( i = 0; i < 15625; i++ ) + shsUpdate( &shsInfo, ( SHS_BYTE * ) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 64 ); + shsFinal( &shsInfo ); + if( compareSHSresults( &shsInfo, 2 ) == -1 ) + { + putchar( '\n' ); + puts( "SHS test 3 failed" ); + exit( -1 ); + } +#ifdef NEW_SHS + puts( "passed, result= 34AA973CD4C4DAA4F61EEB2BDBAD27316534016F" ); +#else + puts( "passed, result= 3232AFFA48628A26653B5AAA44541FD90D690603" ); +#endif /* NEW_SHS */ + + puts( "\nAll SHS tests passed" ); + exit( 0 ); +} diff --git a/krb5-1.21.3/src/lib/crypto/builtin/sha1/t_shs3.c b/krb5-1.21.3/src/lib/crypto/builtin/sha1/t_shs3.c new file mode 100644 index 00000000..7aa0bbde --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/sha1/t_shs3.c @@ -0,0 +1,594 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* test shs code */ + +#include +#include +#include +#include "shs.h" + +static void process(void); +static void test1(void); +static void test2(void); +static void test3(void); +static void test4(void); +static void test5(void); +static void test6(void); +static void test7(void); + +/* When run on a little-endian CPU we need to perform byte reversal on an + array of longwords. It is possible to make the code endianness- + independent by fiddling around with data at the byte level, but this + makes for very slow code, so we rely on the user to sort out endianness + at compile time */ + +static void longReverse( SHS_LONG *buffer, int byteCount ) +{ + SHS_LONG value; + static int init = 0; + char *cp; + + switch (init) { + case 0: + init=1; + cp = (char *) &init; + if (*cp == 1) { + init=2; + break; + } + init=1; + /* fall through - MSB */ + case 1: + return; + } + + byteCount /= sizeof( SHS_LONG ); + while( byteCount-- ) { + value = *buffer; + value = ( ( value & 0xFF00FF00L ) >> 8 ) | + ( ( value & 0x00FF00FFL ) << 8 ); + *buffer++ = ( value << 16 ) | ( value >> 16 ); + } +} + +int rc; +int mode; +int Dflag; + +int +main(argc,argv) + int argc; + char **argv; +{ + char *argp; + + while (--argc > 0) if (*(argp = *++argv)=='-') + while (*++argp) switch(*argp) + { + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + if (mode) goto Usage; + mode = *argp; + break; + case 'D': + if (argc <= 1) goto Usage; + --argc; + Dflag = atoi(*++argv); + break; + case '-': + break; + default: + fprintf (stderr,"Bad switch char <%c>\n", *argp); + Usage: + fprintf(stderr, "Usage: t_shs [-1234567] [-D #]\n"); + exit(1); + } + else goto Usage; + + process(); + exit(rc); +} + +static void process(void) +{ + switch(mode) + { + case '1': + test1(); + break; + case '2': + test2(); + break; + case '3': + test3(); + break; + case '4': + test4(); + break; + case '5': + test5(); + break; + case '6': + test6(); + break; + case '7': + test7(); + break; + default: + test1(); + test2(); + test3(); + test4(); + test5(); + test6(); + test7(); + } +} + +#ifndef shsDigest +static unsigned char * +shsDigest(si) + SHS_INFO *si; +{ + longReverse(si->digest, SHS_DIGESTSIZE); + return (unsigned char*) si->digest; +} +#endif + +unsigned char results1[SHS_DIGESTSIZE] = { + 0xa9,0x99,0x3e,0x36,0x47,0x06,0x81,0x6a,0xba,0x3e, + 0x25,0x71,0x78,0x50,0xc2,0x6c,0x9c,0xd0,0xd8,0x9d}; + +static void test1(void) +{ + SHS_INFO si[1]; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + int i; + + printf("Running SHS test 1 ...\n"); + shsInit(si); + shsUpdate(si, (SHS_BYTE *) "abc", 3); + shsFinal(si); + memcpy(digest, shsDigest(si), SHS_DIGESTSIZE); + if ((failed = memcmp(digest, results1, SHS_DIGESTSIZE)) != 0) + { + fprintf(stderr,"SHS test 1 failed!\n"); + rc = 1; + } + printf ("%s, results = ", failed ? "Failed" : "Passed"); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",digest[i]); + if (failed) + { + printf ("\n, expected "); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",results1[i]); + } + printf("\n"); +} + +unsigned char results2[SHS_DIGESTSIZE] = { + 0x84,0x98,0x3e,0x44,0x1c,0x3b,0xd2,0x6e,0xba,0xae, + 0x4a,0xa1,0xf9,0x51,0x29,0xe5,0xe5,0x46,0x70,0xf1}; + +static void test2(void) +{ + SHS_INFO si[1]; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + int i; + + printf("Running SHS test 2 ...\n"); + shsInit(si); + shsUpdate(si, + (SHS_BYTE *) "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + 56); + shsFinal(si); + memcpy(digest, shsDigest(si), SHS_DIGESTSIZE); + if ((failed = memcmp(digest, results2, SHS_DIGESTSIZE)) != 0) + { + fprintf(stderr,"SHS test 2 failed!\n"); + rc = 1; + } + printf ("%s, results = ", failed ? "Failed" : "Passed"); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",digest[i]); + if (failed) + { + printf ("\n, expected "); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",results2[i]); + } + printf("\n"); +} + +unsigned char results3[SHS_DIGESTSIZE] = { + 0x34,0xaa,0x97,0x3c,0xd4,0xc4,0xda,0xa4,0xf6,0x1e, + 0xeb,0x2b,0xdb,0xad,0x27,0x31,0x65,0x34,0x01,0x6f}; + +static void test3(void) +{ + SHS_INFO si[1]; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + int i; + + printf("Running SHS test 3 ...\n"); + shsInit(si); + for (i = 0; i < 15625; ++i) + shsUpdate(si, + (SHS_BYTE *) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + 64); + shsFinal(si); + memcpy(digest, shsDigest(si), SHS_DIGESTSIZE); + if ((failed = memcmp(digest, results3, SHS_DIGESTSIZE)) != 0) + { + fprintf(stderr,"SHS test 3 failed!\n"); + rc = 1; + } + printf ("%s, results = ", failed ? "Failed" : "Passed"); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",digest[i]); + if (failed) + { + printf ("\n, expected "); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",results3[i]); + } + printf("\n"); +} + +unsigned char randdata[] = { + 0xfe,0x28,0x79,0x25,0xf5,0x03,0xf9,0x1c,0xcd,0x70,0x7b,0xb0,0x42,0x02,0xb8,0x2f, + 0xf3,0x63,0xa2,0x79,0x8e,0x9b,0x33,0xd7,0x2b,0xc4,0xb4,0xd2,0xcb,0x61,0xec,0xbb, + 0x94,0xe1,0x8f,0x53,0x80,0x55,0xd9,0x90,0xb2,0x03,0x58,0xfa,0xa6,0xe5,0x18,0x57, + 0x68,0x04,0x24,0x98,0x41,0x7e,0x84,0xeb,0xc1,0x39,0xbc,0x1d,0xf7,0x4e,0x92,0x72, + 0x1a,0x5b,0xb6,0x99,0x43,0xa5,0x0a,0x45,0x73,0x55,0xfd,0x57,0x83,0x45,0x36,0x5c, + 0xfd,0x39,0x08,0x6e,0xe2,0x01,0x9a,0x8c,0x4e,0x39,0xd2,0x0d,0x5f,0x0e,0x35,0x15, + 0xb9,0xac,0x5f,0xa1,0x8a,0xe6,0xdd,0x6e,0x68,0x9d,0xf6,0x29,0x95,0xf6,0x7d,0x7b, + 0xd9,0x5e,0xf4,0x67,0x25,0xbd,0xee,0xed,0x53,0x60,0xb0,0x47,0xdf,0xef,0xf4,0x41, + 0xbd,0x45,0xcf,0x5c,0x93,0x41,0x87,0x97,0x82,0x39,0x20,0x66,0xb4,0xda,0xcb,0x66, + 0x93,0x02,0x2e,0x7f,0x94,0x4c,0xc7,0x3b,0x2c,0xcf,0xf6,0x99,0x6f,0x13,0xf1,0xc5, + 0x28,0x2b,0xa6,0x6c,0x39,0x26,0x7f,0x76,0x24,0x4a,0x6e,0x01,0x40,0x63,0xf8,0x00, + 0x06,0x23,0x5a,0xaa,0xa6,0x2f,0xd1,0x37,0xc7,0xcc,0x76,0xe9,0x54,0x1e,0x57,0x73, + 0xf5,0x33,0xaa,0x96,0xbe,0x35,0xcd,0x1d,0xd5,0x7d,0xac,0x50,0xd5,0xf8,0x47,0x2d, + 0xd6,0x93,0x5f,0x6e,0x38,0xd3,0xac,0xd0,0x7e,0xad,0x9e,0xf8,0x87,0x95,0x63,0x15, + 0x65,0xa3,0xd4,0xb3,0x9a,0x6c,0xac,0xcd,0x2a,0x54,0x83,0x13,0xc4,0xb4,0x94,0xfa, + 0x76,0x87,0xc5,0x8b,0x4a,0x10,0x92,0x05,0xd1,0x0e,0x97,0xfd,0xc8,0xfb,0xc5,0xdc, + 0x21,0x4c,0xc8,0x77,0x5c,0xed,0x32,0x22,0x77,0xc1,0x38,0x30,0xd7,0x8e,0x2a,0x70, + 0x72,0x67,0x13,0xe4,0xb7,0x18,0xd4,0x76,0xdd,0x32,0x12,0xf4,0x5d,0xc9,0xec,0xc1, + 0x2c,0x8a,0xfe,0x08,0x6c,0xea,0xf6,0xab,0x5a,0x0e,0x8e,0x81,0x1d,0xc8,0x5a,0x4b, + 0xed,0xb9,0x7f,0x4b,0x67,0xe3,0x65,0x46,0xc9,0xf2,0xab,0x37,0x0a,0x98,0x67,0x5b, + 0xb1,0x3b,0x02,0x91,0x38,0x71,0xea,0x62,0x88,0xae,0xb6,0xdb,0xfc,0x55,0x79,0x33, + 0x69,0x95,0x51,0xb6,0xe1,0x3b,0xab,0x22,0x68,0x54,0xf9,0x89,0x9c,0x94,0xe0,0xe3, + 0xd3,0x48,0x5c,0xe9,0x78,0x5b,0xb3,0x4b,0xba,0xd8,0x48,0xd8,0xaf,0x91,0x4e,0x23, + 0x38,0x23,0x23,0x6c,0xdf,0x2e,0xf0,0xff,0xac,0x1d,0x2d,0x27,0x10,0x45,0xa3,0x2d, + 0x8b,0x00,0xcd,0xe2,0xfc,0xb7,0xdb,0x52,0x13,0xb7,0x66,0x79,0xd9,0xd8,0x29,0x0e, + 0x32,0xbd,0x52,0x6b,0x75,0x71,0x08,0x83,0x1b,0x67,0x28,0x93,0x97,0x97,0x32,0xff, + 0x8b,0xd3,0x98,0xa3,0xce,0x2b,0x88,0x37,0x1c,0xcc,0xa0,0xd1,0x19,0x9b,0xe6,0x11, + 0xfc,0xc0,0x3c,0x4e,0xe1,0x35,0x49,0x29,0x19,0xcf,0x1d,0xe1,0x60,0x74,0xc0,0xe9, + 0xf7,0xb4,0x99,0xa0,0x23,0x50,0x51,0x78,0xcf,0xc0,0xe5,0xc2,0x1c,0x16,0xd2,0x24, + 0x5a,0x63,0x54,0x83,0xaa,0x74,0x3d,0x41,0x0d,0x52,0xee,0xfe,0x0f,0x4d,0x13,0xe1, + 0x27,0x00,0xc4,0xf3,0x2b,0x55,0xe0,0x9c,0x81,0xe0,0xfc,0xc2,0x13,0xd4,0x39,0x09 +}; + +unsigned char results4[SHS_DIGESTSIZE] = { + 0x13,0x62,0xfc,0x87,0x68,0x33,0xd5,0x1d,0x2f,0x0c, + 0x73,0xe3,0xfb,0x87,0x6a,0x6b,0xc3,0x25,0x54,0xfc}; + +static void test4(void) +{ + SHS_INFO si[1]; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + int i; + + printf("Running SHS test 4 ...\n"); + shsInit(si); + shsUpdate(si, randdata, 19); + shsFinal(si); + memcpy(digest, shsDigest(si), SHS_DIGESTSIZE); + if ((failed = memcmp(digest, results4, SHS_DIGESTSIZE)) != 0) + { + fprintf(stderr,"SHS test 4 failed!\n"); + rc = 1; + } + printf ("%s, results = ", failed ? "Failed" : "Passed"); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",digest[i]); + if (failed) + { + printf ("\n, expected "); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",results4[i]); + } + printf("\n"); +} + +unsigned char results5[SHS_DIGESTSIZE] = { + 0x19,0x4d,0xf6,0xeb,0x8e,0x02,0x6d,0x37,0x58,0x64, + 0xe5,0x95,0x19,0x2a,0xdd,0x1c,0xc4,0x3c,0x24,0x86}; + +static void test5(void) +{ + SHS_INFO si[1]; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + int i; + + printf("Running SHS test 5 ...\n"); + shsInit(si); + shsUpdate(si, randdata, 19); + shsUpdate(si, randdata+32, 15); + shsFinal(si); + memcpy(digest, shsDigest(si), SHS_DIGESTSIZE); + if ((failed = memcmp(digest, results5, SHS_DIGESTSIZE)) != 0) + { + fprintf(stderr,"SHS test 5 failed!\n"); + rc = 1; + } + printf ("%s, results = ", failed ? "Failed" : "Passed"); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",digest[i]); + if (failed) + { + printf ("\n, expected "); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",results5[i]); + } + printf("\n"); +} + +unsigned char results6[SHS_DIGESTSIZE] = { + 0x4e,0x16,0x57,0x9d,0x4b,0x48,0xa9,0x1c,0x88,0x72, + 0x83,0xdb,0x88,0xd1,0xea,0x3a,0x45,0xdf,0xa1,0x10}; + +static void test6(void) +{ + struct { + unsigned long pad1; + SHS_INFO si1; + unsigned long pad2; + SHS_INFO si2; + unsigned long pad3; + } sdata; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + unsigned int i, j; + + printf("Running SHS test 6 ...\n"); + sdata.pad1 = 0x12345678; + sdata.pad2 = 0x87654321; + sdata.pad3 = 0x78563412; + shsInit((&sdata.si2)); + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #20 %#lx\n", + sdata.pad2); + sdata.pad2 = 0x87654321; + } + if (sdata.pad3 != 0x78563412) { + printf ("Overrun #21 %#lx\n", + sdata.pad3); + sdata.pad3 = 0x78563412; + } + for (i = 0; i < 400; ++i) + { + shsInit(&sdata.si1); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #22 %#lx at %d\n", + sdata.pad1, i); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #23 %#lx at %d\n", + sdata.pad2, i); + sdata.pad2 = 0x87654321; + } + shsUpdate(&sdata.si1, (randdata+sizeof(randdata))-i, i); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #24 %#lx at %d\n", + sdata.pad1, i); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #25 %#lx at %d\n", + sdata.pad2, i); + sdata.pad2 = 0x87654321; + } + shsFinal(&sdata.si1); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #26 %#lx at %d\n", + sdata.pad1, i); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #27 %#lx at %d\n", + sdata.pad2, i); + sdata.pad2 = 0x87654321; + } + memcpy(digest, shsDigest(&sdata.si1), SHS_DIGESTSIZE); + if (Dflag & 1) + { + printf ("%d: ", i); + for (j = 0; j < SHS_DIGESTSIZE; ++j) + printf("%02x",digest[j]); + printf("\n"); + } + shsUpdate((&sdata.si2), digest, SHS_DIGESTSIZE); + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #28 %#lx at %d\n", + sdata.pad2, i); + sdata.pad2 = 0x87654321; + } + if (sdata.pad3 != 0x78563412) { + printf ("Overrun #29 %#lx at %d\n", + sdata.pad3, i); + sdata.pad3 = 0x78563412; + } + if (Dflag & 2) + printf ("%d: %08lx%08lx%08lx%08lx%08lx\n", + i, + (unsigned long) sdata.si2.digest[0], + (unsigned long) sdata.si2.digest[1], + (unsigned long) sdata.si2.digest[2], + (unsigned long) sdata.si2.digest[3], + (unsigned long) sdata.si2.digest[4]); + } + shsFinal((&sdata.si2)); + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #30 %#lx\n", + sdata.pad2); + sdata.pad2 = 0x87654321; + } + if (sdata.pad3 != 0x78563412) { + printf ("Overrun #31 %#lx\n", + sdata.pad3); + sdata.pad3 = 0x78563412; + } + memcpy(digest, shsDigest((&sdata.si2)), SHS_DIGESTSIZE); + if ((failed = memcmp(digest, results6, SHS_DIGESTSIZE)) != 0) + { + fprintf(stderr,"SHS test 6 failed!\n"); + rc = 1; + } + printf ("%s, results = ", failed ? "Failed" : "Passed"); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",digest[i]); + if (failed) + { + printf ("\n, expected "); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",results6[i]); + } + printf("\n"); +} + +unsigned char results7[SHS_DIGESTSIZE] = { + 0x89,0x41,0x65,0xce,0x76,0xc1,0xd1,0xd1,0xc3,0x6f, + 0xab,0x92,0x79,0x30,0x01,0x71,0x63,0x1f,0x74,0xfe}; + +unsigned int jfsize[] = {0,1,31,32, + 33,55,56,63, + 64,65,71,72, + 73,95,96,97, + 119,120,123,127}; +unsigned int kfsize[] = {0,1,31,32,33,55,56,63}; + +static void test7(void) +{ + struct { + unsigned long pad1; + SHS_INFO si1; + unsigned long pad2; + SHS_INFO si2; + unsigned long pad3; + } sdata; + unsigned char digest[SHS_DIGESTSIZE]; + int failed; + unsigned int i, j, k, l; + + printf("Running SHS test 7 ...\n"); + sdata.pad1 = 0x12345678; + sdata.pad2 = 0x87654321; + sdata.pad3 = 0x78563412; + shsInit((&sdata.si2)); + for (i = 1; i <= 128; ++i) + for (j = 0; j < 20; ++j) + for (k = 0; k < 8; ++k) + { + shsInit(&sdata.si1); + shsUpdate(&sdata.si1, (randdata+80+j), i); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #1 %#lx at %d,%d,%d\n", + sdata.pad1, i,j,k); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #2 %#lx at %d,%d,%d\n", + sdata.pad2, i,j,k); + sdata.pad2 = 0x87654321; + } + shsUpdate(&sdata.si1, randdata+i, jfsize[j]); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #3 %#lx at %d,%d,%d\n", + sdata.pad1, i,j,k); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #4 %#lx at %d,%d,%d\n", + sdata.pad2, i,j,k); + sdata.pad2 = 0x87654321; + } + if (k) shsUpdate(&sdata.si1, randdata+(i^j), kfsize[k]); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #5 %#lx at %d,%d,%d\n", + sdata.pad1, i,j,k); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #6 %#lx at %d,%d,%d\n", + sdata.pad2, i,j,k); + sdata.pad2 = 0x87654321; + } + shsFinal(&sdata.si1); + if (sdata.pad1 != 0x12345678) { + printf ("Overrun #7 %#lx at %d,%d,%d\n", + sdata.pad1, i,j,k); + sdata.pad1 = 0x12345678; + } + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #8 %#lx at %d,%d,%d\n", + sdata.pad2, i,j,k); + sdata.pad2 = 0x87654321; + } + memcpy(digest, shsDigest(&sdata.si1), SHS_DIGESTSIZE); + if (Dflag & 1) + { + printf ("%d,%d,%d: ", i, j, k); + for (l = 0; l < SHS_DIGESTSIZE; ++l) + printf("%02x",digest[l]); + printf("\n"); + } + shsUpdate((&sdata.si2), digest, SHS_DIGESTSIZE); + if (sdata.pad2 != 0x87654321) { + printf ("Overrun #9 %#lx at %d,%d,%d\n", + sdata.pad2, i,j,k); + sdata.pad2 = 0x87654321; + } + if (sdata.pad3 != 0x78563412) { + printf ("Overrun #10 %#lx at %d,%d,%d\n", + sdata.pad3, i,j,k); + sdata.pad3 = 0x78563412; + } + if (Dflag & 2) + printf ("%d,%d,%d: %08lx%08lx%08lx%08lx%08lx\n", + i,j,k, + (unsigned long) sdata.si2.digest[0], + (unsigned long) sdata.si2.digest[1], + (unsigned long) sdata.si2.digest[2], + (unsigned long) sdata.si2.digest[3], + (unsigned long) sdata.si2.digest[4]); + } + shsFinal((&sdata.si2)); + memcpy(digest, shsDigest((&sdata.si2)), SHS_DIGESTSIZE); + if ((failed = memcmp(digest, results7, SHS_DIGESTSIZE)) != 0) + { + fprintf(stderr,"SHS test 7 failed!\n"); + rc = 1; + } + printf ("%s, results = ", failed ? "Failed" : "Passed"); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",digest[i]); + if (failed) + { + printf ("\n, expected "); + for (i = 0; i < SHS_DIGESTSIZE; ++i) + printf("%02x",results7[i]); + } + printf("\n"); +} diff --git a/krb5-1.21.3/src/lib/crypto/builtin/sha2/Makefile.in b/krb5-1.21.3/src/lib/crypto/builtin/sha2/Makefile.in new file mode 100644 index 00000000..9cf58ce0 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/sha2/Makefile.in @@ -0,0 +1,26 @@ +mydir=lib$(S)crypto$(S)builtin$(S)sha2 +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES=-I$(srcdir)/../../krb $(CRYPTO_IMPL_CFLAGS) + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = builtin\sha2 +##DOS##OBJFILE = ..\..\$(OUTPRE)sha2.lst + +STLIBOBJS= sha256.o sha512.o + +OBJS= $(OUTPRE)sha256.$(OBJEXT) $(OUTPRE)sha512.$(OBJEXT) + +SRCS= $(srcdir)/sha256.c $(srcdir)/sha512.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/builtin/sha2/deps b/krb5-1.21.3/src/lib/crypto/builtin/sha2/deps new file mode 100644 index 00000000..cfaa1aa6 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/sha2/deps @@ -0,0 +1,25 @@ +# +# Generated makefile dependencies follow. +# +sha256.so sha256.po $(OUTPRE)sha256.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + sha2.h sha256.c +sha512.so sha512.po $(OUTPRE)sha512.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + sha2.h sha512.c diff --git a/krb5-1.21.3/src/lib/crypto/builtin/sha2/sha2.h b/krb5-1.21.3/src/lib/crypto/builtin/sha2/sha2.h new file mode 100644 index 00000000..3aebd3e1 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/sha2/sha2.h @@ -0,0 +1,78 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/sha2/sha2.h - SHA-256 declarations */ +/* + * Copyright (c) 1995 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. + */ + +#ifndef SHA2_H +#define SHA2_H 1 + +#include "crypto_int.h" + +#define SHA256_DIGEST_LENGTH 32 +#define SHA384_DIGEST_LENGTH 48 +#define SHA512_DIGEST_LENGTH 64 + +#define SHA256_BLOCK_SIZE 64 +#define SHA384_BLOCK_SIZE 128 +#define SHA512_BLOCK_SIZE 128 + +struct sha256state { + unsigned int sz[2]; + uint32_t counter[8]; + unsigned char save[64]; +}; + +struct sha512state { + uint64_t sz[2]; + uint64_t counter[8]; + unsigned char save[128]; +}; + +/* SHA-384 and SHA-512 use the same state object. */ +typedef struct sha256state SHA256_CTX; +typedef struct sha512state SHA384_CTX; +typedef struct sha512state SHA512_CTX; + +void k5_sha256_init(SHA256_CTX *); +void k5_sha256_update(SHA256_CTX *, const void *, size_t); +void k5_sha256_final(void *, SHA256_CTX *); + +void k5_sha384_init(SHA384_CTX *); +void k5_sha384_update(SHA384_CTX *, const void *, size_t); +void k5_sha384_final(void *, SHA384_CTX *); + +void k5_sha512_init(SHA512_CTX *); +void k5_sha512_update(SHA512_CTX *, const void *, size_t); +void k5_sha512_final(void *, SHA512_CTX *); + +#endif /* SHA2_H */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/sha2/sha256.c b/krb5-1.21.3/src/lib/crypto/builtin/sha2/sha256.c new file mode 100644 index 00000000..cd80bcb6 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/sha2/sha256.c @@ -0,0 +1,273 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/builtin/sha2/sha256.c - SHA-256 implementation */ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 "sha2.h" + +#ifdef K5_BUILTIN_SHA2 + +#ifdef K5_BE +#define WORDS_BIGENDIAN +#endif + +#ifndef min +#define min(a,b) (((a)>(b))?(b):(a)) +#endif + +/* Vector Crays doesn't have a good 32-bit type, or more precisely, + * int32_t as defined by isn't 32 bits, and we don't + * want to depend in being able to redefine this type. To cope with + * this we have to clamp the result in some places to [0,2^32); no + * need to do this on other machines. Did I say this was a mess? + */ + +#ifdef _CRAY +#define CRAYFIX(X) ((X) & 0xffffffff) +#else +#define CRAYFIX(X) (X) +#endif + +static inline uint32_t +cshift (uint32_t x, unsigned int n) +{ + x = CRAYFIX(x); + return CRAYFIX((x << n) | (x >> (32 - n))); +} + +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#define ROTR(x,n) (((x)>>(n)) | ((x) << (32 - (n)))) + +#define Sigma0(x) (ROTR(x,2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define Sigma1(x) (ROTR(x,6) ^ ROTR(x,11) ^ ROTR(x,25)) +#define sigma0(x) (ROTR(x,7) ^ ROTR(x,18) ^ ((x)>>3)) +#define sigma1(x) (ROTR(x,17) ^ ROTR(x,19) ^ ((x)>>10)) + +#define A m->counter[0] +#define B m->counter[1] +#define C m->counter[2] +#define D m->counter[3] +#define E m->counter[4] +#define F m->counter[5] +#define G m->counter[6] +#define H m->counter[7] + +static const uint32_t constant_256[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +void +k5_sha256_init(SHA256_CTX *m) +{ + m->sz[0] = 0; + m->sz[1] = 0; + A = 0x6a09e667; + B = 0xbb67ae85; + C = 0x3c6ef372; + D = 0xa54ff53a; + E = 0x510e527f; + F = 0x9b05688c; + G = 0x1f83d9ab; + H = 0x5be0cd19; +} + +static void +calc(SHA256_CTX *m, uint32_t *in) +{ + uint32_t AA, BB, CC, DD, EE, FF, GG, HH; + uint32_t data[64]; + int i; + + AA = A; + BB = B; + CC = C; + DD = D; + EE = E; + FF = F; + GG = G; + HH = H; + + for (i = 0; i < 16; ++i) + data[i] = in[i]; + for (i = 16; i < 64; ++i) + data[i] = sigma1(data[i-2]) + data[i-7] + + sigma0(data[i-15]) + data[i - 16]; + + for (i = 0; i < 64; i++) { + uint32_t T1, T2; + + T1 = HH + Sigma1(EE) + Ch(EE, FF, GG) + constant_256[i] + data[i]; + T2 = Sigma0(AA) + Maj(AA,BB,CC); + + HH = GG; + GG = FF; + FF = EE; + EE = DD + T1; + DD = CC; + CC = BB; + BB = AA; + AA = T1 + T2; + } + + A += AA; + B += BB; + C += CC; + D += DD; + E += EE; + F += FF; + G += GG; + H += HH; +} + +/* + * From `Performance analysis of MD5' by Joseph D. Touch + */ + +#if !defined(WORDS_BIGENDIAN) || defined(_CRAY) +static inline uint32_t +swap_uint32_t(uint32_t t) +{ +#define ROL(x,n) ((x)<<(n))|((x)>>(32-(n))) + uint32_t temp1, temp2; + + temp1 = cshift(t, 16); + temp2 = temp1 >> 8; + temp1 &= 0x00ff00ff; + temp2 &= 0x00ff00ff; + temp1 <<= 8; + return temp1 | temp2; +} +#endif + +struct x32 { + unsigned int a:32; + unsigned int b:32; +}; + +void +k5_sha256_update(SHA256_CTX *m, const void *v, size_t len) +{ + const unsigned char *p = v; + size_t old_sz = m->sz[0]; + size_t offset; + + m->sz[0] += len * 8; + if (m->sz[0] < old_sz) + ++m->sz[1]; + offset = (old_sz / 8) % 64; + while(len > 0){ + size_t l = min(len, 64 - offset); + memcpy(m->save + offset, p, l); + offset += l; + p += l; + len -= l; + if(offset == 64){ +#if !defined(WORDS_BIGENDIAN) || defined(_CRAY) + int i; + uint32_t current[16]; + struct x32 *u = (struct x32*)(void*)m->save; + for(i = 0; i < 8; i++){ + current[2*i+0] = swap_uint32_t(u[i].a); + current[2*i+1] = swap_uint32_t(u[i].b); + } + calc(m, current); +#else + calc(m, (uint32_t*)(void*)m->save); +#endif + offset = 0; + } + } +} + +void +k5_sha256_final(void *res, SHA256_CTX *m) +{ + unsigned char zeros[72]; + unsigned offset = (m->sz[0] / 8) % 64; + unsigned int dstart = (120 - offset - 1) % 64 + 1; + + *zeros = 0x80; + memset (zeros + 1, 0, sizeof(zeros) - 1); + zeros[dstart+7] = (m->sz[0] >> 0) & 0xff; + zeros[dstart+6] = (m->sz[0] >> 8) & 0xff; + zeros[dstart+5] = (m->sz[0] >> 16) & 0xff; + zeros[dstart+4] = (m->sz[0] >> 24) & 0xff; + zeros[dstart+3] = (m->sz[1] >> 0) & 0xff; + zeros[dstart+2] = (m->sz[1] >> 8) & 0xff; + zeros[dstart+1] = (m->sz[1] >> 16) & 0xff; + zeros[dstart+0] = (m->sz[1] >> 24) & 0xff; + k5_sha256_update(m, zeros, dstart + 8); + { + int i; + unsigned char *r = (unsigned char*)res; + + for (i = 0; i < 8; ++i) { + r[4*i+3] = m->counter[i] & 0xFF; + r[4*i+2] = (m->counter[i] >> 8) & 0xFF; + r[4*i+1] = (m->counter[i] >> 16) & 0xFF; + r[4*i] = (m->counter[i] >> 24) & 0xFF; + } + } +} + +krb5_error_code +k5_sha256(const krb5_data *in, size_t n, uint8_t out[K5_SHA256_HASHLEN]) +{ + SHA256_CTX ctx; + size_t i; + + k5_sha256_init(&ctx); + for (i = 0; i < n; i++) + k5_sha256_update(&ctx, in[i].data, in[i].length); + k5_sha256_final(out, &ctx); + return 0; +} + +#endif /* K5_BUILTIN_SHA2 */ diff --git a/krb5-1.21.3/src/lib/crypto/builtin/sha2/sha512.c b/krb5-1.21.3/src/lib/crypto/builtin/sha2/sha512.c new file mode 100644 index 00000000..6f23968f --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/builtin/sha2/sha512.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2006, 2010 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 "sha2.h" + +#ifdef K5_BUILTIN_SHA2 + +#ifdef K5_BE +#define WORDS_BIGENDIAN +#endif + +#ifndef min +#define min(a,b) (((a)>(b))?(b):(a)) +#endif + +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#define ROTR(x,n) (((x)>>(n)) | ((x) << (64 - (n)))) + +#define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) +#define sigma0(x) (ROTR(x,1) ^ ROTR(x,8) ^ ((x)>>7)) +#define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ ((x)>>6)) + +#define A m->counter[0] +#define B m->counter[1] +#define C m->counter[2] +#define D m->counter[3] +#define E m->counter[4] +#define F m->counter[5] +#define G m->counter[6] +#define H m->counter[7] + +static const uint64_t constant_512[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, + 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, + 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, + 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, + 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, + 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL, + 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, + 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, + 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, + 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL, + 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, + 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, + 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, + 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL, + 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, + 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, + 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, + 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL, + 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, + 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, + 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, + 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL, + 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, + 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, + 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, + 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL, + 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +}; + +static inline uint64_t +cshift64 (uint64_t x, unsigned int n) +{ + return ((uint64_t)x << (uint64_t)n) | ((uint64_t)x >> ((uint64_t)64 - (uint64_t)n)); +} + +void +k5_sha512_init (SHA512_CTX *m) +{ + m->sz[0] = 0; + m->sz[1] = 0; + A = 0x6a09e667f3bcc908ULL; + B = 0xbb67ae8584caa73bULL; + C = 0x3c6ef372fe94f82bULL; + D = 0xa54ff53a5f1d36f1ULL; + E = 0x510e527fade682d1ULL; + F = 0x9b05688c2b3e6c1fULL; + G = 0x1f83d9abfb41bd6bULL; + H = 0x5be0cd19137e2179ULL; +} + +static void +calc (SHA512_CTX *m, uint64_t *in) +{ + uint64_t AA, BB, CC, DD, EE, FF, GG, HH; + uint64_t data[80]; + int i; + + AA = A; + BB = B; + CC = C; + DD = D; + EE = E; + FF = F; + GG = G; + HH = H; + + for (i = 0; i < 16; ++i) + data[i] = in[i]; + for (i = 16; i < 80; ++i) + data[i] = sigma1(data[i-2]) + data[i-7] + + sigma0(data[i-15]) + data[i - 16]; + + for (i = 0; i < 80; i++) { + uint64_t T1, T2; + + T1 = HH + Sigma1(EE) + Ch(EE, FF, GG) + constant_512[i] + data[i]; + T2 = Sigma0(AA) + Maj(AA,BB,CC); + + HH = GG; + GG = FF; + FF = EE; + EE = DD + T1; + DD = CC; + CC = BB; + BB = AA; + AA = T1 + T2; + } + + A += AA; + B += BB; + C += CC; + D += DD; + E += EE; + F += FF; + G += GG; + H += HH; +} + +/* + * From `Performance analysis of MD5' by Joseph D. Touch + */ + +#if !defined(WORDS_BIGENDIAN) || defined(_CRAY) +static inline uint64_t +swap_uint64_t (uint64_t t) +{ + uint64_t temp; + + temp = cshift64(t, 32); + temp = ((temp & 0xff00ff00ff00ff00ULL) >> 8) | + ((temp & 0x00ff00ff00ff00ffULL) << 8); + return ((temp & 0xffff0000ffff0000ULL) >> 16) | + ((temp & 0x0000ffff0000ffffULL) << 16); +} + +struct x64{ + uint64_t a; + uint64_t b; +}; +#endif + +void +k5_sha512_update (SHA512_CTX *m, const void *v, size_t len) +{ + const unsigned char *p = v; + size_t old_sz = m->sz[0]; + size_t offset; + + m->sz[0] += len * 8; + if (m->sz[0] < old_sz) + ++m->sz[1]; + offset = (old_sz / 8) % 128; + while(len > 0){ + size_t l = min(len, 128 - offset); + memcpy(m->save + offset, p, l); + offset += l; + p += l; + len -= l; + if(offset == 128){ +#if !defined(WORDS_BIGENDIAN) || defined(_CRAY) + int i; + uint64_t current[16]; + struct x64 *us = (struct x64*)(void*)m->save; + for(i = 0; i < 8; i++){ + current[2*i+0] = swap_uint64_t(us[i].a); + current[2*i+1] = swap_uint64_t(us[i].b); + } + calc(m, current); +#else + calc(m, (uint64_t*)(void*)m->save); +#endif + offset = 0; + } + } +} + +void +k5_sha512_final (void *res, SHA512_CTX *m) +{ + unsigned char zeros[128 + 16]; + unsigned offset = (m->sz[0] / 8) % 128; + unsigned int dstart = (240 - offset - 1) % 128 + 1; + + *zeros = 0x80; + memset (zeros + 1, 0, sizeof(zeros) - 1); + zeros[dstart+15] = (m->sz[0] >> 0) & 0xff; + zeros[dstart+14] = (m->sz[0] >> 8) & 0xff; + zeros[dstart+13] = (m->sz[0] >> 16) & 0xff; + zeros[dstart+12] = (m->sz[0] >> 24) & 0xff; + zeros[dstart+11] = (m->sz[0] >> 32) & 0xff; + zeros[dstart+10] = (m->sz[0] >> 40) & 0xff; + zeros[dstart+9] = (m->sz[0] >> 48) & 0xff; + zeros[dstart+8] = (m->sz[0] >> 56) & 0xff; + + zeros[dstart+7] = (m->sz[1] >> 0) & 0xff; + zeros[dstart+6] = (m->sz[1] >> 8) & 0xff; + zeros[dstart+5] = (m->sz[1] >> 16) & 0xff; + zeros[dstart+4] = (m->sz[1] >> 24) & 0xff; + zeros[dstart+3] = (m->sz[1] >> 32) & 0xff; + zeros[dstart+2] = (m->sz[1] >> 40) & 0xff; + zeros[dstart+1] = (m->sz[1] >> 48) & 0xff; + zeros[dstart+0] = (m->sz[1] >> 56) & 0xff; + k5_sha512_update (m, zeros, dstart + 16); + { + int i; + unsigned char *r = (unsigned char*)res; + + for (i = 0; i < 8; ++i) { + r[8*i+7] = m->counter[i] & 0xFF; + r[8*i+6] = (m->counter[i] >> 8) & 0xFF; + r[8*i+5] = (m->counter[i] >> 16) & 0xFF; + r[8*i+4] = (m->counter[i] >> 24) & 0xFF; + r[8*i+3] = (m->counter[i] >> 32) & 0XFF; + r[8*i+2] = (m->counter[i] >> 40) & 0xFF; + r[8*i+1] = (m->counter[i] >> 48) & 0xFF; + r[8*i] = (m->counter[i] >> 56) & 0xFF; + } + } +} + +void +k5_sha384_init (SHA384_CTX *m) +{ + m->sz[0] = 0; + m->sz[1] = 0; + A = 0xcbbb9d5dc1059ed8ULL; + B = 0x629a292a367cd507ULL; + C = 0x9159015a3070dd17ULL; + D = 0x152fecd8f70e5939ULL; + E = 0x67332667ffc00b31ULL; + F = 0x8eb44a8768581511ULL; + G = 0xdb0c2e0d64f98fa7ULL; + H = 0x47b5481dbefa4fa4ULL; +} + +void +k5_sha384_update (SHA384_CTX *m, const void *v, size_t len) +{ + k5_sha512_update(m, v, len); +} + +void +k5_sha384_final (void *res, SHA384_CTX *m) +{ + unsigned char data[SHA512_DIGEST_LENGTH]; + k5_sha512_final(data, m); + memcpy(res, data, SHA384_DIGEST_LENGTH); +} + +#endif /* K5_BUILTIN_SHA2 */ diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/Makefile.in b/krb5-1.21.3/src/lib/crypto/crypto_tests/Makefile.in new file mode 100644 index 00000000..1a3fe596 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/Makefile.in @@ -0,0 +1,147 @@ +mydir=lib$(S)crypto$(S)crypto_tests +BUILDTOP=$(REL)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/../krb + +EXTRADEPSRCS=\ + $(srcdir)/t_nfold.c \ + $(srcdir)/t_encrypt.c \ + $(srcdir)/t_decrypt.c \ + $(srcdir)/t_prf.c \ + $(srcdir)/t_cmac.c \ + $(srcdir)/t_hmac.c \ + $(srcdir)/t_pkcs5.c \ + $(srcdir)/t_cts.c \ + $(srcdir)/vectors.c \ + $(srcdir)/aes-test.c \ + $(srcdir)/camellia-test.c \ + $(srcdir)/t_cf2.c \ + $(srcdir)/t_cksums.c \ + $(srcdir)/t_mddriver.c \ + $(srcdir)/t_kperf.c \ + $(srcdir)/t_sha2.c \ + $(srcdir)/t_short.c \ + $(srcdir)/t_str2key.c \ + $(srcdir)/t_derive.c \ + $(srcdir)/t_fork.c + +##DOS##BUILDTOP = ..\..\.. + +check-unix: t_nfold t_encrypt t_decrypt t_prf t_cmac t_hmac \ + t_cksums \ + aes-test \ + camellia-test \ + t_mddriver4 t_mddriver \ + t_cts t_sha2 t_short t_str2key t_derive t_fork t_cf2 + $(RUN_TEST) ./t_nfold + $(RUN_TEST) ./t_encrypt + $(RUN_TEST) ./t_decrypt + $(RUN_TEST) ./t_cmac + $(RUN_TEST) ./t_hmac + $(RUN_TEST) ./t_prf + $(RUN_TEST) ./t_cksums + $(RUN_TEST) ./t_cts + $(RUN_TEST) ./aes-test -k > vk.txt + cmp vk.txt $(srcdir)/expect-vk.txt + $(RUN_TEST) ./aes-test > vt.txt + cmp vt.txt $(srcdir)/expect-vt.txt + $(RUN_TEST) ./camellia-test > camellia-vt.txt + cmp camellia-vt.txt $(srcdir)/camellia-expect-vt.txt + $(RUN_TEST) $(C)t_mddriver4 -x + $(RUN_TEST) $(C)t_mddriver -x + $(RUN_TEST) ./t_sha2 + $(RUN_TEST) ./t_short + $(RUN_TEST) ./t_str2key + $(RUN_TEST) ./t_derive + $(RUN_TEST) ./t_fork + $(RUN_TEST) ./t_cf2 <$(srcdir)/t_cf2.in >t_cf2.output + diff t_cf2.output $(srcdir)/t_cf2.expected +# $(RUN_TEST) ./t_pkcs5 + +t_nfold$(EXEEXT): t_nfold.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_nfold.$(OBJEXT) $(KRB5_BASE_LIBS) + +t_encrypt$(EXEEXT): t_encrypt.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_encrypt.$(OBJEXT) $(KRB5_BASE_LIBS) + +t_decrypt$(EXEEXT): t_decrypt.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_decrypt.$(OBJEXT) $(KRB5_BASE_LIBS) + +t_prf$(EXEEXT): t_prf.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_prf.$(OBJEXT) $(KRB5_BASE_LIBS) + +t_cmac$(EXEEXT): t_cmac.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_cmac.$(OBJEXT) $(KRB5_BASE_LIBS) + +t_hmac$(EXEEXT): t_hmac.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_hmac.$(OBJEXT) $(KRB5_BASE_LIBS) + +#t_pkcs5$(EXEEXT): t_pkcs5.$(OBJEXT) $(KRB5_BASE_DEPLIBS) +# $(CC_LINK) -o $@ t_pkcs5.$(OBJEXT) $(KRB5_BASE_LIBS) + +vectors$(EXEEXT): vectors.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ vectors.$(OBJEXT) $(KRB5_BASE_LIBS) + +t_cts$(EXEEXT): t_cts.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_cts.$(OBJEXT) \ + $(KRB5_BASE_LIBS) + +t_sha2$(EXEEXT): t_sha2.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_sha2.$(OBJEXT) \ + $(KRB5_BASE_LIBS) + +t_short$(EXEEXT): t_short.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_short.$(OBJEXT) \ + $(KRB5_BASE_LIBS) + +t_cksums: t_cksums.o $(CRYTPO_DEPLIB) + $(CC_LINK) -o t_cksums t_cksums.o -lkrb5 $(KRB5_BASE_LIBS) + +aes-test: aes-test.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o aes-test aes-test.$(OBJEXT) $(KRB5_BASE_LIBS) + +camellia-test: camellia-test.$(OBJEXT) $(CRYPTO_DEPLIB) + $(CC_LINK) -o camellia-test camellia-test.$(OBJEXT) $(KRB5_BASE_LIBS) + +t_mddriver4.o: $(srcdir)/t_mddriver.c + $(CC) -DMD=4 $(ALL_CFLAGS) -o t_mddriver4.o -c $(srcdir)/t_mddriver.c + +t_mddriver4: t_mddriver4.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -DMD4 -o t_mddriver4 t_mddriver4.o $(KRB5_BASE_LIBS) + +t_mddriver: t_mddriver.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_mddriver t_mddriver.o $(KRB5_BASE_LIBS) + +t_kperf: t_kperf.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_kperf t_kperf.o $(KRB5_BASE_LIBS) + +t_str2key$(EXEEXT): t_str2key.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_str2key.$(OBJEXT) $(KRB5_BASE_LIBS) + +t_derive$(EXEEXT): t_derive.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_derive.$(OBJEXT) $(KRB5_BASE_LIBS) + +t_fork$(EXEEXT): t_fork.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_fork.$(OBJEXT) $(KRB5_BASE_LIBS) + +t_cf2$(EXEEXT): t_cf2.$(OBJEXT) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_cf2.$(OBJEXT) $(KRB5_BASE_LIBS) + +clean: + $(RM) t_nfold.o t_nfold t_encrypt t_encrypt.o \ + t_decrypt.o t_decrypt t_cmac.o t_cmac \ + t_hmac.o t_hmac t_pkcs5.o t_pkcs5 pbkdf2.o t_prf t_prf.o \ + aes-test.o aes-test vt.txt vk.txt kresults.out \ + t_cts.o t_cts \ + t_mddriver4.o t_mddriver4 t_mddriver.o t_mddriver \ + t_cksums t_cksums.o \ + t_kperf.o t_kperf t_sha2.o t_sha2 t_short t_short.o t_str2key \ + t_str2key.o t_derive t_derive.o t_fork t_fork.o \ + t_mddriver$(EXEEXT) $(OUTPRE)t_mddriver.$(OBJEXT) \ + camellia-test camellia-test.o camellia-vt.txt \ + t_cf2 t_cf2.o t_cf2.output + + -$(RM) t_prf.output + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/Poly.pm b/krb5-1.21.3/src/lib/crypto/crypto_tests/Poly.pm new file mode 100644 index 00000000..cad0f77b --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/Poly.pm @@ -0,0 +1,182 @@ +# Copyright 2002 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +package Poly; + +# Poly: implements some basic operations on polynomials in the field +# of integers (mod 2). +# +# The rep is an array of coefficients, highest order term first. +# +# This is rather slow at the moment. + +use overload + '+' => \&add, + '-' => \&add, + '*' => \&mul, + '%' => sub {$_[2] ? mod($_[1], $_[0]) : mod($_[0], $_[1])}, + '/' => sub { $_[2] ? scalar(div($_[1], $_[0])) + : scalar(div($_[0], $_[1])) }, + '<=>' => sub {$_[2] ? pcmp($_[1], $_[0]) : pcmp($_[0], $_[1])}, + '""' => \&str +; + +use Carp; + +# doesn't do much beyond normalize and bless +sub new { + my $this = shift; + my $class = ref($this) || $this; + my(@x) = @_; + return bless [norm(@x)], $class; +} + +# stringified P(x) +sub pretty { + my(@x) = @{+shift}; + my $n = @x; + local $_; + return "0" if !@x; + return join " + ", map {$n--; $_ ? ("x^$n") : ()} @x; +} + +sub print { + my $self = shift; + print $self->pretty, "\n"; +} + +# This assumes normalization. +sub order { + my $self = shift; + return $#{$self}; +} + +sub str { + return overload::StrVal($_[0]); +} + +# strip leading zero coefficients +sub norm { + my(@x) = @_; + shift @x while @x && !$x[0]; + return @x; +} + +# multiply $self by the single term of power $n +sub multerm { + my($self, $n) = @_; + return $self->new(@$self, (0) x $n); +} + +# This is really an order comparison; different polys of same order +# compare equal. It also assumes prior normalization. +sub pcmp { + my @x = @{+shift}; + my @y = @{+shift}; + return @x <=> @y; +} + +# convenience constructor; takes list of non-zero terms +sub powers2poly +{ + my $self = shift; + my $poly = $self->new; + my $n; + foreach $n (@_) { + $poly += $one->multerm($n); + } + return $poly; +} + +sub add { + my $self = shift; + my @x = @$self; + my @y = @{+shift}; + my @r; + unshift @r, (pop @x || 0) ^ (pop @y || 0) + while @x || @y; + return $self->new(@r); +} + +sub mul { + my($self) = shift; + my @y = @{+shift}; + my $r = $self->new; + my $power = 0; + while (@y) { + $r += $self->multerm($power) if pop @y; + $power++; + } + return $r; +} + +sub oldmod { + my($self, $div) = @_; + my @num = @$self; + my @div = @$div; + my $r = $self->new(splice @num, 0, @div); + do { + push @$r, shift @num while @num && $r < $div; + $r += $div if $r >= $div; + } while @num; + return $r; +} + +sub div { + my($self, $div) = @_; + my $q = $self->new; + my $r = $self->new(@$self); + my $one = $self->new(1); + my ($tp, $power); + croak "divide by zero" if !@$div; + while ($div <= $r) { + $power = 0; + $power++ while ($tp = $div->multerm($power)) < $r; + $q += $one->multerm($power); + $r -= $tp; + } + return wantarray ? ($q, $r) : $q; +} + +sub mod { + (&div)[1]; +} + +# bits and octets both big-endian +sub hex { + my @x = @{+shift}; + my $minwidth = shift || 32; + unshift @x, 0 while @x % 8 || @x < $minwidth; + return unpack "H*", pack "B*", join "", @x; +} + +# bit-reversal of above +sub revhex { + my @x = @{+shift}; + my $minwidth = shift || 32; + unshift @x, 0 while @x % 8 || @x < $minwidth; + return unpack "H*", pack "B*", join "", reverse @x; +} + +$one = Poly->new(1); + +1; diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/aes-test.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/aes-test.c new file mode 100644 index 00000000..a7382a48 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/aes-test.c @@ -0,0 +1,144 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/aes-test.c */ +/* + * Copyright (C) 2002 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Subset of NIST tests for AES; specifically, the variable-key and + * variable-text tests for 128- and 256-bit keys. + */ + +#include +#include "crypto_int.h" + +static char key[32]; +static char plain[16], cipher[16], zero[16]; + +static krb5_keyblock enc_key; +static krb5_data ivec; +static void init() +{ + enc_key.contents = (krb5_octet *)key; + enc_key.length = 16; + ivec.data = zero; + ivec.length = 16; +} +static void enc() +{ + krb5_key k; + krb5_crypto_iov iov; + + memcpy(cipher, plain, 16); + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data(cipher, 16); + krb5_k_create_key(NULL, &enc_key, &k); + krb5int_aes_encrypt(k, &ivec, &iov, 1); + krb5_k_free_key(NULL, k); +} + +static void hexdump(const char *label, const char *cp, int len) +{ + printf("%s=", label); + while (len--) printf("%02X", 0xff & *cp++); + printf("\n"); +} + +static void set_bit(char *ptr, int bitnum) +{ + int bytenum; + bytenum = bitnum / 8; + bitnum %= 8; + /* First bit is the high bit! */ + ptr[bytenum] = 1 << (7 - bitnum); +} + +/* Variable-Key tests */ +static void vk_test_1(int len, krb5_enctype etype) +{ + int i; + + enc_key.length = len; + enc_key.enctype = etype; + printf("\nKEYSIZE=%d\n\n", len * 8); + memset(plain, 0, sizeof(plain)); + hexdump("PT", plain, 16); + for (i = 0; i < len * 8; i++) { + memset(key, 0, len); + set_bit(key, i); + printf("\nI=%d\n", i+1); + hexdump("KEY", key, len); + enc(); + hexdump("CT", cipher, 16); + } + printf("\n==========\n"); +} +static void vk_test() +{ + vk_test_1(16, ENCTYPE_AES128_CTS_HMAC_SHA1_96); + vk_test_1(32, ENCTYPE_AES256_CTS_HMAC_SHA1_96); +} + +/* Variable-Text tests */ +static void vt_test_1(int len, krb5_enctype etype) +{ + int i; + + enc_key.length = len; + enc_key.enctype = etype; + printf("\nKEYSIZE=%d\n\n", len * 8); + memset(key, 0, len); + hexdump("KEY", key, len); + for (i = 0; i < 16 * 8; i++) { + memset(plain, 0, sizeof(plain)); + set_bit(plain, i); + printf("\nI=%d\n", i+1); + hexdump("PT", plain, 16); + enc(); + hexdump("CT", cipher, 16); + } + printf("\n==========\n"); +} +static void vt_test() +{ + vt_test_1(16, ENCTYPE_AES128_CTS_HMAC_SHA1_96); + vt_test_1(32, ENCTYPE_AES256_CTS_HMAC_SHA1_96); +} + + +int main (int argc, char *argv[]) +{ + if (argc > 2 || (argc == 2 && strcmp(argv[1], "-k"))) { + fprintf(stderr, + "usage:\t%s -k\tfor variable-key tests\n" + " or:\t%s \tfor variable-plaintext tests\n", + argv[0], argv[0]); + return 1; + } + init(); + if (argc == 2) + vk_test(); + else + vt_test(); + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/camellia-expect-vt.txt b/krb5-1.21.3/src/lib/crypto/crypto_tests/camellia-expect-vt.txt new file mode 100644 index 00000000..e6ebe8a8 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/camellia-expect-vt.txt @@ -0,0 +1,1036 @@ + +KEYSIZE=128 + +KEY=00000000000000000000000000000000 + +I=1 +PT=80000000000000000000000000000000 +CT=07923A39EB0A817D1C4D87BDB82D1F1C + +I=2 +PT=40000000000000000000000000000000 +CT=48CD6419809672D2349260D89A08D3D3 + +I=3 +PT=20000000000000000000000000000000 +CT=D07493CCB2E95CE0B4945A05ACC97D82 + +I=4 +PT=10000000000000000000000000000000 +CT=5DBE1EAC9F7080A88DBED7F6DA101448 + +I=5 +PT=08000000000000000000000000000000 +CT=F01EE477D199DF2701027034B229622F + +I=6 +PT=04000000000000000000000000000000 +CT=C841587ABD9A912E563774CB569D051E + +I=7 +PT=02000000000000000000000000000000 +CT=1D9BC0C04546F0915C8CCD11391A455C + +I=8 +PT=01000000000000000000000000000000 +CT=05E6EBB4BA167F5C479CEFF3152F943B + +I=9 +PT=00800000000000000000000000000000 +CT=93211E0F788845B9FC0E4551FFE92AC9 + +I=10 +PT=00400000000000000000000000000000 +CT=B6D35701CD8FADDE383BBE8E6B70BAF7 + +I=11 +PT=00200000000000000000000000000000 +CT=8358F9F4EBCFEE348CB30551ACB151A0 + +I=12 +PT=00100000000000000000000000000000 +CT=D57516EB5AD93C523E40521BF447AFCE + +I=13 +PT=00080000000000000000000000000000 +CT=66B2534C279C439133F52E5AD8B439A9 + +I=14 +PT=00040000000000000000000000000000 +CT=A71C69184A9F63C2992A5F18F77C1FE9 + +I=15 +PT=00020000000000000000000000000000 +CT=1ADCBE49AEACB9ECEBBD492B10E82C7B + +I=16 +PT=00010000000000000000000000000000 +CT=27E3BCFB227C5561DB6CF7FC30387036 + +I=17 +PT=00008000000000000000000000000000 +CT=F4AE20365CC9D06B0CAE6B695ED2CEC1 + +I=18 +PT=00004000000000000000000000000000 +CT=3DD682F0B641ED32AD3D43EA2A0456E4 + +I=19 +PT=00002000000000000000000000000000 +CT=6E5D14A95ECC290B509EA6B673652E3A + +I=20 +PT=00001000000000000000000000000000 +CT=F1CDF0F8D7B3FFD95422D7CC0CF40B7B + +I=21 +PT=00000800000000000000000000000000 +CT=A9253D459A34C385A1F1B2CFFA3935C5 + +I=22 +PT=00000400000000000000000000000000 +CT=291024D99FF09A47A1DEE45BA700AE52 + +I=23 +PT=00000200000000000000000000000000 +CT=49241D9459B277187BB10081C60361C0 + +I=24 +PT=00000100000000000000000000000000 +CT=AD9BA365CC4DD5553D2D9FE303841D88 + +I=25 +PT=00000080000000000000000000000000 +CT=C2ECA616664A249DC622CC11196B4AE1 + +I=26 +PT=00000040000000000000000000000000 +CT=6E1A2D4794BB0DC08777A0BC7523E70E + +I=27 +PT=00000020000000000000000000000000 +CT=6DB1F0CF59656BDD235E82B8CEF0BE8E + +I=28 +PT=00000010000000000000000000000000 +CT=52F239C5EAF401EBDC54D2F011FF4B6A + +I=29 +PT=00000008000000000000000000000000 +CT=6B58A08F648414B67FD6847D2AA51CBF + +I=30 +PT=00000004000000000000000000000000 +CT=2959DD5367885A75EB48053CF3251A36 + +I=31 +PT=00000002000000000000000000000000 +CT=630B292E3B88EF641CDFD531E206605E + +I=32 +PT=00000001000000000000000000000000 +CT=4BBB88EF82B70593FCC56AFD91540FDB + +I=33 +PT=00000000800000000000000000000000 +CT=0A13055B118A45C606999257BD191426 + +I=34 +PT=00000000400000000000000000000000 +CT=5CF8E5C9F15D7E4F865020224853EB77 + +I=35 +PT=00000000200000000000000000000000 +CT=3898805042C7A4315C5EE51AF2DE47E2 + +I=36 +PT=00000000100000000000000000000000 +CT=8D3F96372E87CBB0B375425B3A10B9E7 + +I=37 +PT=00000000080000000000000000000000 +CT=4D9510A378BD784A70A66BCC75B7D3C8 + +I=38 +PT=00000000040000000000000000000000 +CT=70DB1902D37CFBDFB98F7C516F79D416 + +I=39 +PT=00000000020000000000000000000000 +CT=383C6C2AABEF7FDE25CD470BF774A331 + +I=40 +PT=00000000010000000000000000000000 +CT=47CBCB5288349B1A15DC9F81FBEE6B8F + +I=41 +PT=00000000008000000000000000000000 +CT=21DA34D4468EEB13AED95DAE0FF48310 + +I=42 +PT=00000000004000000000000000000000 +CT=021C9A8E6BD36FBD036411E5D852A80F + +I=43 +PT=00000000002000000000000000000000 +CT=6A459E2F839AF60ACDE83774D0BB5574 + +I=44 +PT=00000000001000000000000000000000 +CT=C19255121F1B933CAE09E58AEC0E9977 + +I=45 +PT=00000000000800000000000000000000 +CT=7BA949E27B2BE148A6B801F9305F43D5 + +I=46 +PT=00000000000400000000000000000000 +CT=E8CEB1026BCF7BCEA32E8A380EA76DB7 + +I=47 +PT=00000000000200000000000000000000 +CT=63F97747ED56A8F521B20CC65F6F9465 + +I=48 +PT=00000000000100000000000000000000 +CT=2091CFDC629819106188424AC694F75B + +I=49 +PT=00000000000080000000000000000000 +CT=A91BDF8E8B88407942423CCE000527C4 + +I=50 +PT=00000000000040000000000000000000 +CT=73F9B44B9635A3FD683DBF8D49E9825B + +I=51 +PT=00000000000020000000000000000000 +CT=9DC64B2133FAD5069FD9A7CC2FFFD1CC + +I=52 +PT=00000000000010000000000000000000 +CT=28240F81FEC36B71E13F1FEA7A7641E3 + +I=53 +PT=00000000000008000000000000000000 +CT=20DD39FEE96CD2EFF972872A692B28FD + +I=54 +PT=00000000000004000000000000000000 +CT=47A9E40483EC1925B635E47E964E8E93 + +I=55 +PT=00000000000002000000000000000000 +CT=9C0EBD822C49FB3D853DF5B315A87BA0 + +I=56 +PT=00000000000001000000000000000000 +CT=C18D813FDB45A594C6DC24E5A1F6CE32 + +I=57 +PT=00000000000000800000000000000000 +CT=7E5467FF245ECF80CB55C2D8E91F0711 + +I=58 +PT=00000000000000400000000000000000 +CT=394D4365B77954FDEA4145FCF7A7A041 + +I=59 +PT=00000000000000200000000000000000 +CT=B1D8311A492ED11F11E57B29221610C4 + +I=60 +PT=00000000000000100000000000000000 +CT=E5FBB947A63AEA90163AF04AD6951EF8 + +I=61 +PT=00000000000000080000000000000000 +CT=CA0627DDF580F0E7D59562825C9D0492 + +I=62 +PT=00000000000000040000000000000000 +CT=EF98FFD1AED295AAE1860F0274C8F555 + +I=63 +PT=00000000000000020000000000000000 +CT=8C698E5CFFF08FACE10C2DC5FF1E2A81 + +I=64 +PT=00000000000000010000000000000000 +CT=35A7767E02032C35B5CE1A6F49C57C28 + +I=65 +PT=00000000000000008000000000000000 +CT=AB36F8734E76EBA306CF00D6763D90B0 + +I=66 +PT=00000000000000004000000000000000 +CT=E854EB66D4EC66889B5E6CD4F44A5806 + +I=67 +PT=00000000000000002000000000000000 +CT=15B66DF1455ACD640B8716BCF5DB2D69 + +I=68 +PT=00000000000000001000000000000000 +CT=4C57AB5333E5C2D4B7E30A007E449F48 + +I=69 +PT=00000000000000000800000000000000 +CT=BA3E7FF28EB38EA09D8DB1440A9A3552 + +I=70 +PT=00000000000000000400000000000000 +CT=64E60227AFD80C40C70186CC94804C1A + +I=71 +PT=00000000000000000200000000000000 +CT=CEB4423C20B4C91C2551F6FC227C9514 + +I=72 +PT=00000000000000000100000000000000 +CT=F736894B843EF32DA28576DE500D448C + +I=73 +PT=00000000000000000080000000000000 +CT=58FDA98B678D15053D4B6C060368108C + +I=74 +PT=00000000000000000040000000000000 +CT=E28CAE384E578F47657755EBCD97996C + +I=75 +PT=00000000000000000020000000000000 +CT=0A64617BD4B5B166668240D105B7B6A2 + +I=76 +PT=00000000000000000010000000000000 +CT=4BD090C7E3D365B5EA80F19B4798881E + +I=77 +PT=00000000000000000008000000000000 +CT=BC7B6CB9BFF4F72973BB2CD20A512C06 + +I=78 +PT=00000000000000000004000000000000 +CT=4C7ADDC5C867594E9EE75F0AA6AB9C23 + +I=79 +PT=00000000000000000002000000000000 +CT=1FBD05C71A36691AC6566A5298101D53 + +I=80 +PT=00000000000000000001000000000000 +CT=42D7D6B1F499D412F8793972BD968DA2 + +I=81 +PT=00000000000000000000800000000000 +CT=260EC86E2786FC68824576B934F32814 + +I=82 +PT=00000000000000000000400000000000 +CT=576C26DFD7046F9357F34BEA7DFB26A0 + +I=83 +PT=00000000000000000000200000000000 +CT=6D55E54BFB6F927174A02294C95E0F8F + +I=84 +PT=00000000000000000000100000000000 +CT=1A6CE91DD458229C7675A34950D10E23 + +I=85 +PT=00000000000000000000080000000000 +CT=DAD0D5E7E000652825AA34D228EA8D8F + +I=86 +PT=00000000000000000000040000000000 +CT=E68013F48D75EAD2BBC0B0BDA5E690BF + +I=87 +PT=00000000000000000000020000000000 +CT=A07D92312FBAE37BFE8A834210AE4F9C + +I=88 +PT=00000000000000000000010000000000 +CT=6EEE5F8544CD7D456366EB448813989A + +I=89 +PT=00000000000000000000008000000000 +CT=F8E5C7FF4B79D7ABE8BFA2DD148820A8 + +I=90 +PT=00000000000000000000004000000000 +CT=C6349D75C7472BBD66F95B3A07C79C91 + +I=91 +PT=00000000000000000000002000000000 +CT=B85713C12D8658951CD1AD21C74D2CD2 + +I=92 +PT=00000000000000000000001000000000 +CT=907AA00B9F7D47A97623FB55BA911F29 + +I=93 +PT=00000000000000000000000800000000 +CT=DC3CD0ED23D11776FAB43A2A6A8F3557 + +I=94 +PT=00000000000000000000000400000000 +CT=4BFE58A8FD69179C14765B09AB70B705 + +I=95 +PT=00000000000000000000000200000000 +CT=A23996E0EA67EC280356E5F77130A551 + +I=96 +PT=00000000000000000000000100000000 +CT=CDEADE859B3AACD273CCA85A3E2E45F2 + +I=97 +PT=00000000000000000000000080000000 +CT=E0FC78489857D84DA03F40CE97147174 + +I=98 +PT=00000000000000000000000040000000 +CT=7615EA6351F6BB12855E8579C6995D8E + +I=99 +PT=00000000000000000000000020000000 +CT=13E184344FE28C2E70ED0E4D0A8037F9 + +I=100 +PT=00000000000000000000000010000000 +CT=A5FE395F568482B87BC3EB208C81C942 + +I=101 +PT=00000000000000000000000008000000 +CT=B3103E11AF06C85565823F8CAA3159F6 + +I=102 +PT=00000000000000000000000004000000 +CT=7EBC2234D271B89C519C396985300030 + +I=103 +PT=00000000000000000000000002000000 +CT=0661D338F2E0C939BA1687820A768467 + +I=104 +PT=00000000000000000000000001000000 +CT=EC2B42667C0195A90715499617884DA5 + +I=105 +PT=00000000000000000000000000800000 +CT=AE077BA19D24E7188DDD3682FF196892 + +I=106 +PT=00000000000000000000000000400000 +CT=98823C24B9C65A66073C7952DC2B4B5E + +I=107 +PT=00000000000000000000000000200000 +CT=6AB58432CBB3C2F503DA2D16796CC297 + +I=108 +PT=00000000000000000000000000100000 +CT=EEB5EBB3A53E4196C2F22BC1A4DDF5E8 + +I=109 +PT=00000000000000000000000000080000 +CT=33DC40AC5FDC126D38878416AF6C0FA6 + +I=110 +PT=00000000000000000000000000040000 +CT=38EDDC08E18B4AD982CEA921D2765A9A + +I=111 +PT=00000000000000000000000000020000 +CT=7D6BEA038E9347C642E18631660A9558 + +I=112 +PT=00000000000000000000000000010000 +CT=FDA57921A473B5EE3700AD5ADF035019 + +I=113 +PT=00000000000000000000000000008000 +CT=699B4812E200337E9C1D2C397F0DFE4E + +I=114 +PT=00000000000000000000000000004000 +CT=7A1EADF68B0807145D6C414852DECFC8 + +I=115 +PT=00000000000000000000000000002000 +CT=1645FFAA8AD76689C01DA8C40882781F + +I=116 +PT=00000000000000000000000000001000 +CT=BA0C053BE702FA62FC66D8FEB12FC97E + +I=117 +PT=00000000000000000000000000000800 +CT=841FD8AF69CF2C31F7D4D7B6959662B5 + +I=118 +PT=00000000000000000000000000000400 +CT=F675D59BDB33231861268F539829DA0B + +I=119 +PT=00000000000000000000000000000200 +CT=A4967F45ABB4E8C7DC5E3806680F35E0 + +I=120 +PT=00000000000000000000000000000100 +CT=4D7E08081CC82F92ABA7C58C99F8343F + +I=121 +PT=00000000000000000000000000000080 +CT=9AEFDB287C119B82353612B60ECCBFD8 + +I=122 +PT=00000000000000000000000000000040 +CT=979BB6A1553A17592A86E78DF144A699 + +I=123 +PT=00000000000000000000000000000020 +CT=A6FA8CAB06FD2E5BF3A858983C01757A + +I=124 +PT=00000000000000000000000000000010 +CT=BE8511254C31E25420B91D6FEF1710ED + +I=125 +PT=00000000000000000000000000000008 +CT=F589A908D18A21894971C0433581E1A5 + +I=126 +PT=00000000000000000000000000000004 +CT=4237585130E7C9F715235EB1D8C94DE7 + +I=127 +PT=00000000000000000000000000000002 +CT=DEFE3E0B5C54C94B4F2A0F5A46F6210D + +I=128 +PT=00000000000000000000000000000001 +CT=F5574ACC3148DFCB9015200631024DF9 + +========== + +KEYSIZE=256 + +KEY=0000000000000000000000000000000000000000000000000000000000000000 + +I=1 +PT=80000000000000000000000000000000 +CT=B0C6B88AEA518AB09E847248E91B1B9D + +I=2 +PT=40000000000000000000000000000000 +CT=B8D7684E35FA1DB15BDCEE7A48659858 + +I=3 +PT=20000000000000000000000000000000 +CT=F0CAD59AF92FBB79F36951E697492750 + +I=4 +PT=10000000000000000000000000000000 +CT=117100F6635389560DC4A2DA24EBA70F + +I=5 +PT=08000000000000000000000000000000 +CT=DBDD62355553019ED84C35886421E532 + +I=6 +PT=04000000000000000000000000000000 +CT=9CB8D04FA506F19848F7B9110518BFC8 + +I=7 +PT=02000000000000000000000000000000 +CT=E4308E253BC3444D293500701BA82C6A + +I=8 +PT=01000000000000000000000000000000 +CT=EA2FAE53F7F30C0170A20E95A068503E + +I=9 +PT=00800000000000000000000000000000 +CT=14B14839EA221880B2C64D1FE000B93D + +I=10 +PT=00400000000000000000000000000000 +CT=A5CFC075B342D5101AACC334E73058BB + +I=11 +PT=00200000000000000000000000000000 +CT=477EA56B2EBAD0F8AC5E1936866560FF + +I=12 +PT=00100000000000000000000000000000 +CT=107E8598418404196EC59F63E45B7F6D + +I=13 +PT=00080000000000000000000000000000 +CT=FF6A891E7C1C074A68FEC291928FDD8D + +I=14 +PT=00040000000000000000000000000000 +CT=F64C250A13F45D377ADB7545B2B157A9 + +I=15 +PT=00020000000000000000000000000000 +CT=FAD0F252086F11C830C65B63197CBC38 + +I=16 +PT=00010000000000000000000000000000 +CT=9DCB89B209441F02AD0D25C6AB826629 + +I=17 +PT=00008000000000000000000000000000 +CT=E62E4ED4E4F34EDC563710D960E09D4C + +I=18 +PT=00004000000000000000000000000000 +CT=98A1B926BA06895C3F2E84CCBACBC356 + +I=19 +PT=00002000000000000000000000000000 +CT=29BE0BE4DB7F4D196718AEA38F3B0BFD + +I=20 +PT=00001000000000000000000000000000 +CT=F670C4EBECBA0B43E71F6D752BFD4854 + +I=21 +PT=00000800000000000000000000000000 +CT=7D7666B4484CDB7E3605468E093A787C + +I=22 +PT=00000400000000000000000000000000 +CT=562D06B181C091DA6C43642AE99460C6 + +I=23 +PT=00000200000000000000000000000000 +CT=AB0EFB5975E6186B7D76BC9672453488 + +I=24 +PT=00000100000000000000000000000000 +CT=10C0756538E7BFF88D19AE2B1F7B859A + +I=25 +PT=00000080000000000000000000000000 +CT=AF7FCD5248F8C72F1695AA05DD1CADE0 + +I=26 +PT=00000040000000000000000000000000 +CT=9841E555655609A75D7BE20B8A90EF1E + +I=27 +PT=00000020000000000000000000000000 +CT=27F9546E6A1B7464780000561783569C + +I=28 +PT=00000010000000000000000000000000 +CT=8671D935D7A8354EECB7288803D42D7A + +I=29 +PT=00000008000000000000000000000000 +CT=0DA44F508DEBC6F044394624FCEB8EBE + +I=30 +PT=00000004000000000000000000000000 +CT=AB137369BE6D93FBB18006BDB236EC09 + +I=31 +PT=00000002000000000000000000000000 +CT=EB90C4E597A7E1779FFA260886E26F75 + +I=32 +PT=00000001000000000000000000000000 +CT=618CF3588D5C128EAF252616230E08F7 + +I=33 +PT=00000000800000000000000000000000 +CT=98DC4DB49D197AB9152D12B9DE2D73CA + +I=34 +PT=00000000400000000000000000000000 +CT=5BDDE24B15702A35E1F140C57D206443 + +I=35 +PT=00000000200000000000000000000000 +CT=CF755809882BED8BA2F9F1A4ED296A2B + +I=36 +PT=00000000100000000000000000000000 +CT=F1A8DBB999538AE89D16F92A7F4D1DF1 + +I=37 +PT=00000000080000000000000000000000 +CT=775222FDDAAECB81CF675C4E0B98179E + +I=38 +PT=00000000040000000000000000000000 +CT=12A648CADCD153C760A965826683119A + +I=39 +PT=00000000020000000000000000000000 +CT=0503FB10AB241E7CF45D8CDEEE474335 + +I=40 +PT=00000000010000000000000000000000 +CT=3D299C0070CBBD831B802690B8E7CA24 + +I=41 +PT=00000000008000000000000000000000 +CT=33105BD4D11D66753DC34D128BEFE3F4 + +I=42 +PT=00000000004000000000000000000000 +CT=5EFCE2B4B987C0F77D27B44836881682 + +I=43 +PT=00000000002000000000000000000000 +CT=7835449454128035D7F0EA99E327577B + +I=44 +PT=00000000001000000000000000000000 +CT=27BEDDA0601BE35122FB1D272D73AB3E + +I=45 +PT=00000000000800000000000000000000 +CT=54C3F99FF48E318CC515EDE75800C4B3 + +I=46 +PT=00000000000400000000000000000000 +CT=C627C329F8E48299F6FDB23B9DBEA0BB + +I=47 +PT=00000000000200000000000000000000 +CT=1B6578F9E23BD8C1845A02431C5F9AA3 + +I=48 +PT=00000000000100000000000000000000 +CT=6DB2FB8C0B9344D0547C0FF1292020C6 + +I=49 +PT=00000000000080000000000000000000 +CT=4FAD9B2C37C131493FBEF53581FA4F83 + +I=50 +PT=00000000000040000000000000000000 +CT=47502A01E93D2C87BD5584F6AFD3D99D + +I=51 +PT=00000000000020000000000000000000 +CT=056E1C6F651BFE50271B3B7A18E76D84 + +I=52 +PT=00000000000010000000000000000000 +CT=5632BAF6627B3D96AD4E06FA6A561F55 + +I=53 +PT=00000000000008000000000000000000 +CT=E29807CAACDFA2D41A7D9E91FA7FD8EB + +I=54 +PT=00000000000004000000000000000000 +CT=81DD44BB5D1822DEE605F9E6FF01D7B3 + +I=55 +PT=00000000000002000000000000000000 +CT=5C3649925E47D7FF96482A8FBD9666FD + +I=56 +PT=00000000000001000000000000000000 +CT=695415A836E66E737887845EC08A1ADB + +I=57 +PT=00000000000000800000000000000000 +CT=F5416BCE292D9E2CEA5D1CC70BBAEED1 + +I=58 +PT=00000000000000400000000000000000 +CT=7AEC4F1388FC29C47F7FED74ADDE8485 + +I=59 +PT=00000000000000200000000000000000 +CT=82A9F1A6CE08BC4876E649D8A8EA7EB6 + +I=60 +PT=00000000000000100000000000000000 +CT=B6296C88ADF1A792908B065EEB04BFC2 + +I=61 +PT=00000000000000080000000000000000 +CT=E766A39AECCA40BDBFBE6FF3FA292913 + +I=62 +PT=00000000000000040000000000000000 +CT=C6D081454EA00D83C23B5A62C84359E1 + +I=63 +PT=00000000000000020000000000000000 +CT=85D259A79CCA80484504D1603F7A8F53 + +I=64 +PT=00000000000000010000000000000000 +CT=D8291FA1C6DC250078824B2D0A20883F + +I=65 +PT=00000000000000008000000000000000 +CT=95387CB74C48FFBD1F8D64A6CC45E074 + +I=66 +PT=00000000000000004000000000000000 +CT=A17F975F538F56CDF629B516011DE837 + +I=67 +PT=00000000000000002000000000000000 +CT=B50B615A1654C6E1CB6AB33716C097FE + +I=68 +PT=00000000000000001000000000000000 +CT=7BBB2CBB874DF6C8B821DA7FB0F9011B + +I=69 +PT=00000000000000000800000000000000 +CT=E9EFE074D096A275E47CD2E6206DF6A1 + +I=70 +PT=00000000000000000400000000000000 +CT=88F2F8D5A836406AE8BBB98C65BBDA55 + +I=71 +PT=00000000000000000200000000000000 +CT=F64620D8D87585A3EF038B9AD58F5EA0 + +I=72 +PT=00000000000000000100000000000000 +CT=694438EC141C8ED5F2F898B4554A298F + +I=73 +PT=00000000000000000080000000000000 +CT=3E6226EC7726A1EE5F5FA9B18CCE8C44 + +I=74 +PT=00000000000000000040000000000000 +CT=8AB6949E79911647800B9E87362AB97A + +I=75 +PT=00000000000000000020000000000000 +CT=093C5CF24EDAF7F9F1C8A80DE4FF50A9 + +I=76 +PT=00000000000000000010000000000000 +CT=28A36E50061F19E240351ED0E378CBF4 + +I=77 +PT=00000000000000000008000000000000 +CT=B93BB36CB88BF26EA79198652AA51D3C + +I=78 +PT=00000000000000000004000000000000 +CT=DE4948083D044FAC9BCA6DA8CD67B8A6 + +I=79 +PT=00000000000000000002000000000000 +CT=6E778B5BDA6CA118117E47470D080D3C + +I=80 +PT=00000000000000000001000000000000 +CT=0A9107324DA32B4281D032A3487EF875 + +I=81 +PT=00000000000000000000800000000000 +CT=18ED5635312D71ABD123CCE779D4D68A + +I=82 +PT=00000000000000000000400000000000 +CT=2E3C63F95C4BC1F944BAB06DEDC9AA8E + +I=83 +PT=00000000000000000000200000000000 +CT=ACCC869EF07004C8C3C709083BE7BA2F + +I=84 +PT=00000000000000000000100000000000 +CT=DF60B34FB1A59147CC1FB049C1578206 + +I=85 +PT=00000000000000000000080000000000 +CT=4228DC636C08E41021054AA0E1E2227A + +I=86 +PT=00000000000000000000040000000000 +CT=7CE27F66EFD735FFD6B3E1738C50495B + +I=87 +PT=00000000000000000000020000000000 +CT=F8E74B33A9CDE351DA0BBC06D69093D7 + +I=88 +PT=00000000000000000000010000000000 +CT=AE0D22A5B37B8DC5D81CC641EED334D0 + +I=89 +PT=00000000000000000000008000000000 +CT=C181C6CA5E163743458B9167A0B6A16A + +I=90 +PT=00000000000000000000004000000000 +CT=5171F4F6095E4B276CFBA1F07223FBE6 + +I=91 +PT=00000000000000000000002000000000 +CT=2732F4D3A8C9D1D8D493840D6E0B864F + +I=92 +PT=00000000000000000000001000000000 +CT=3EF04E0059A061D973532CA5C1DFBE7B + +I=93 +PT=00000000000000000000000800000000 +CT=6D9A8F23579E4978EBAA87B5ADEB77E5 + +I=94 +PT=00000000000000000000000400000000 +CT=BBD08873CC44BA4253C0C41FEEB7F124 + +I=95 +PT=00000000000000000000000200000000 +CT=72E4B2437CBD283F3809CE686F6A591E + +I=96 +PT=00000000000000000000000100000000 +CT=6E5580514B92512B1BF4B1B987B9AA1B + +I=97 +PT=00000000000000000000000080000000 +CT=5EF5D0C5BCBDCB604D3A083B68CE0FA3 + +I=98 +PT=00000000000000000000000040000000 +CT=9D991FDD723AD2182777A15CA0E0F665 + +I=99 +PT=00000000000000000000000020000000 +CT=24440626EFC8F86BEA7DE78085AB8A22 + +I=100 +PT=00000000000000000000000010000000 +CT=17C3630D62D13C1E826C0FCCBD74A864 + +I=101 +PT=00000000000000000000000008000000 +CT=4CF5AB86A56AB134A7FE46CCE3F9FCE9 + +I=102 +PT=00000000000000000000000004000000 +CT=3E6B9C0388F6D9B8F458F30221907607 + +I=103 +PT=00000000000000000000000002000000 +CT=AD9C926B8A5CD98EEE88200617E59958 + +I=104 +PT=00000000000000000000000001000000 +CT=AFF8AED5E075E02AF720CA4BF0028B3B + +I=105 +PT=00000000000000000000000000800000 +CT=D90EAFF909202BB209BB3BB8C7F9A954 + +I=106 +PT=00000000000000000000000000400000 +CT=2C709B00E6A22F00F64A7D8EE341853F + +I=107 +PT=00000000000000000000000000200000 +CT=CCEC598F0D9F0BF201B2F487136D54A4 + +I=108 +PT=00000000000000000000000000100000 +CT=73B2883A0A166AAE1BF14E60A5195FA3 + +I=109 +PT=00000000000000000000000000080000 +CT=E676867BD9AD5EF915143388496779D7 + +I=110 +PT=00000000000000000000000000040000 +CT=CDCB73D1BFCFD4BE7F1DAA9B1C6A4055 + +I=111 +PT=00000000000000000000000000020000 +CT=02A3A5C89DAA24CD2C517F7A73286A89 + +I=112 +PT=00000000000000000000000000010000 +CT=C0FA2AC9E92EE58C2DD12D6D43AB7035 + +I=113 +PT=00000000000000000000000000008000 +CT=EDC2CB1F7291353BDBF2385519E6AE16 + +I=114 +PT=00000000000000000000000000004000 +CT=B4B62D16D197A98CD3B978812B9D9884 + +I=115 +PT=00000000000000000000000000002000 +CT=5CDFC95A529A905101CEA26BC1B891ED + +I=116 +PT=00000000000000000000000000001000 +CT=CC7150CD3650B98363296C7C4ED368D1 + +I=117 +PT=00000000000000000000000000000800 +CT=CC57706B0C6526B8E25A5DBD32EACBDB + +I=118 +PT=00000000000000000000000000000400 +CT=30D30456AD98B182D64C649648F6AEC9 + +I=119 +PT=00000000000000000000000000000200 +CT=D7E9DA7F631938EB649A08AF82FBD75F + +I=120 +PT=00000000000000000000000000000100 +CT=B8DA2AF6600B07895B5D0FFAF4991469 + +I=121 +PT=00000000000000000000000000000080 +CT=0F6F64F930BA6C178943322B98114599 + +I=122 +PT=00000000000000000000000000000040 +CT=8B1F247802E47C91BEE2AA34ECFD7A01 + +I=123 +PT=00000000000000000000000000000020 +CT=7A6985778D3A66E97F23E01F0D0E45E7 + +I=124 +PT=00000000000000000000000000000010 +CT=BA664AC39855518DFDEE10D1B3111FAE + +I=125 +PT=00000000000000000000000000000008 +CT=7C92854D801A1648F65CA81813DDBF83 + +I=126 +PT=00000000000000000000000000000004 +CT=6A3F25AAB7E92D9CF378E5D9C040F26B + +I=127 +PT=00000000000000000000000000000002 +CT=3D4B2CDE666761BA5DFB305178E667FB + +I=128 +PT=00000000000000000000000000000001 +CT=9CDB269B5D293BC5DB9C55B057D9B591 + +========== diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/camellia-test.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/camellia-test.c new file mode 100644 index 00000000..23d14667 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/camellia-test.c @@ -0,0 +1,141 @@ +/* lib/crypto/crypto_tests/camellia-test.c */ +/* + * Copyright (c) 2009 + * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * Subset of NIST tests for AES as applied to Camellia; specifically, the + * variable-key and variable-text tests for 128- and 256-bit keys. + */ + +#include +#include "crypto_int.h" + +static char key[32]; +static char plain[16], cipher[16], zero[16]; + +static krb5_keyblock enc_key; +static krb5_data ivec; +static void init() +{ + enc_key.contents = (unsigned char *)key; + enc_key.length = 16; + ivec.data = zero; + ivec.length = 16; +} +static void enc() +{ + krb5_key k; + krb5_crypto_iov iov; + + memcpy(cipher, plain, 16); + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data(cipher, 16); + krb5_k_create_key(NULL, &enc_key, &k); + krb5int_camellia_encrypt(k, &ivec, &iov, 1); + krb5_k_free_key(NULL, k); +} + +static void hexdump(const char *label, const char *cp, int len) +{ + printf("%s=", label); + while (len--) printf("%02X", 0xff & *cp++); + printf("\n"); +} + +static void set_bit(char *ptr, int bitnum) +{ + int bytenum; + bytenum = bitnum / 8; + bitnum %= 8; + /* First bit is the high bit! */ + ptr[bytenum] = 1 << (7 - bitnum); +} + +/* Variable-Key tests */ +static void vk_test_1(int len) +{ + int i; + + enc_key.enctype = ENCTYPE_CAMELLIA128_CTS_CMAC; + enc_key.length = len; + printf("\nKEYSIZE=%d\n\n", len * 8); + memset(plain, 0, sizeof(plain)); + hexdump("PT", plain, 16); + for (i = 0; i < len * 8; i++) { + memset(key, 0, len); + set_bit(key, i); + printf("\nI=%d\n", i+1); + hexdump("KEY", key, len); + enc(); + hexdump("CT", cipher, 16); + } + printf("\n==========\n"); +} +static void vk_test() +{ + vk_test_1(16); + vk_test_1(32); +} + +/* Variable-Text tests */ +static void vt_test_1(int len, krb5_enctype etype) +{ + int i; + + enc_key.enctype = etype; + enc_key.length = len; + printf("\nKEYSIZE=%d\n\n", len * 8); + memset(key, 0, len); + hexdump("KEY", key, len); + for (i = 0; i < 16 * 8; i++) { + memset(plain, 0, sizeof(plain)); + set_bit(plain, i); + printf("\nI=%d\n", i+1); + hexdump("PT", plain, 16); + enc(); + hexdump("CT", cipher, 16); + } + printf("\n==========\n"); +} +static void vt_test() +{ + vt_test_1(16, ENCTYPE_CAMELLIA128_CTS_CMAC); + vt_test_1(32, ENCTYPE_CAMELLIA256_CTS_CMAC); +} + +int main (int argc, char *argv[]) +{ + if (argc > 2 || (argc == 2 && strcmp(argv[1], "-k"))) { + fprintf(stderr, + "usage:\t%s -k\tfor variable-key tests\n" + " or:\t%s \tfor variable-plaintext tests\n", + argv[0], argv[0]); + return 1; + } + init(); + if (argc == 2) + vk_test(); + else + vt_test(); + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/deps b/krb5-1.21.3/src/lib/crypto/crypto_tests/deps new file mode 100644 index 00000000..598b6e5e --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/deps @@ -0,0 +1,206 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)t_nfold.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_nfold.c +$(OUTPRE)t_encrypt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_encrypt.c +$(OUTPRE)t_decrypt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_decrypt.c +$(OUTPRE)t_prf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_prf.c +$(OUTPRE)t_cmac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_cmac.c +$(OUTPRE)t_hmac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-hex.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_hmac.c +$(OUTPRE)t_pkcs5.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_pkcs5.c +$(OUTPRE)t_cts.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_cts.c +$(OUTPRE)vectors.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + vectors.c +$(OUTPRE)aes-test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + aes-test.c +$(OUTPRE)camellia-test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + camellia-test.c +$(OUTPRE)t_cf2.$(OBJEXT): $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h t_cf2.c +$(OUTPRE)t_cksums.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_cksums.c +$(OUTPRE)t_mddriver.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_mddriver.c +$(OUTPRE)t_kperf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_kperf.c +$(OUTPRE)t_sha2.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_sha2.c +$(OUTPRE)t_short.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_short.c +$(OUTPRE)t_str2key.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_str2key.c +$(OUTPRE)t_derive.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_derive.c +$(OUTPRE)t_fork.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_fork.c diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/expect-vk.txt b/krb5-1.21.3/src/lib/crypto/crypto_tests/expect-vk.txt new file mode 100644 index 00000000..bbd2c587 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/expect-vk.txt @@ -0,0 +1,1548 @@ + +KEYSIZE=128 + +PT=00000000000000000000000000000000 + +I=1 +KEY=80000000000000000000000000000000 +CT=0EDD33D3C621E546455BD8BA1418BEC8 + +I=2 +KEY=40000000000000000000000000000000 +CT=C0CC0C5DA5BD63ACD44A80774FAD5222 + +I=3 +KEY=20000000000000000000000000000000 +CT=2F0B4B71BC77851B9CA56D42EB8FF080 + +I=4 +KEY=10000000000000000000000000000000 +CT=6B1E2FFFE8A114009D8FE22F6DB5F876 + +I=5 +KEY=08000000000000000000000000000000 +CT=9AA042C315F94CBB97B62202F83358F5 + +I=6 +KEY=04000000000000000000000000000000 +CT=DBE01DE67E346A800C4C4B4880311DE4 + +I=7 +KEY=02000000000000000000000000000000 +CT=C117D2238D53836ACD92DDCDB85D6A21 + +I=8 +KEY=01000000000000000000000000000000 +CT=DC0ED85DF9611ABB7249CDD168C5467E + +I=9 +KEY=00800000000000000000000000000000 +CT=807D678FFF1F56FA92DE3381904842F2 + +I=10 +KEY=00400000000000000000000000000000 +CT=0E53B3FCAD8E4B130EF73AEB957FB402 + +I=11 +KEY=00200000000000000000000000000000 +CT=969FFD3B7C35439417E7BDE923035D65 + +I=12 +KEY=00100000000000000000000000000000 +CT=A99B512C19CA56070491166A1503BF15 + +I=13 +KEY=00080000000000000000000000000000 +CT=6E9985252126EE344D26AE369D2327E3 + +I=14 +KEY=00040000000000000000000000000000 +CT=B85F4809F904C275491FCDCD1610387E + +I=15 +KEY=00020000000000000000000000000000 +CT=ED365B8D7D20C1F5D53FB94DD211DF7B + +I=16 +KEY=00010000000000000000000000000000 +CT=B3A575E86A8DB4A7135D604C43304896 + +I=17 +KEY=00008000000000000000000000000000 +CT=89704BCB8E69F846259EB0ACCBC7F8A2 + +I=18 +KEY=00004000000000000000000000000000 +CT=C56EE7C92197861F10D7A92B90882055 + +I=19 +KEY=00002000000000000000000000000000 +CT=92F296F6846E0EAF9422A5A24A08B069 + +I=20 +KEY=00001000000000000000000000000000 +CT=E67E32BB8F11DEB8699318BEE9E91A60 + +I=21 +KEY=00000800000000000000000000000000 +CT=B08EEF85EAF626DD91B65C4C3A97D92B + +I=22 +KEY=00000400000000000000000000000000 +CT=661083A6ADDCE79BB4E0859AB5538013 + +I=23 +KEY=00000200000000000000000000000000 +CT=55DFE2941E0EB10AFC0B333BD34DE1FE + +I=24 +KEY=00000100000000000000000000000000 +CT=6BFE5945E715C9662609770F8846087A + +I=25 +KEY=00000080000000000000000000000000 +CT=79848E9C30C2F8CDA8B325F7FED2B139 + +I=26 +KEY=00000040000000000000000000000000 +CT=7A713A53B99FEF34AC04DEEF80965BD0 + +I=27 +KEY=00000020000000000000000000000000 +CT=18144A2B46620D32C3C32CE52D49257F + +I=28 +KEY=00000010000000000000000000000000 +CT=872E827C70887C80749F7B8BB1847C7E + +I=29 +KEY=00000008000000000000000000000000 +CT=6B86C6A4FE6A60C59B1A3102F8DE49F3 + +I=30 +KEY=00000004000000000000000000000000 +CT=9848BB3DFDF6F532F094679A4C231A20 + +I=31 +KEY=00000002000000000000000000000000 +CT=925AD528E852E329B2091CD3F1C2BCEE + +I=32 +KEY=00000001000000000000000000000000 +CT=80DF436544B0DD596722E46792A40CD8 + +I=33 +KEY=00000000800000000000000000000000 +CT=525DAF18F93E83E1E74BBBDDE4263BBA + +I=34 +KEY=00000000400000000000000000000000 +CT=F65C9D2EE485D24701FFA3313B9D5BE6 + +I=35 +KEY=00000000200000000000000000000000 +CT=E4FC8D8BCA06425BDF94AFA40FCC14BA + +I=36 +KEY=00000000100000000000000000000000 +CT=A53F0A5CA1E4E6440BB975FF320DE6F8 + +I=37 +KEY=00000000080000000000000000000000 +CT=D55313B9394080462E87E02899B553F0 + +I=38 +KEY=00000000040000000000000000000000 +CT=34A71D761F71BCD344384C7F97D27906 + +I=39 +KEY=00000000020000000000000000000000 +CT=233F3D819599612EBC89580245C996A8 + +I=40 +KEY=00000000010000000000000000000000 +CT=B4F1374E5268DBCB676E447529E53F89 + +I=41 +KEY=00000000008000000000000000000000 +CT=0816BD27861D2BA891D1044E39951E96 + +I=42 +KEY=00000000004000000000000000000000 +CT=F3BE9EA3F10C73CA64FDE5DB13A951D1 + +I=43 +KEY=00000000002000000000000000000000 +CT=2448086A8106FBD03048DDF857D3F1C8 + +I=44 +KEY=00000000001000000000000000000000 +CT=670756E65BEC8B68F03D77CDCDCE7B91 + +I=45 +KEY=00000000000800000000000000000000 +CT=EF968CF0D36FD6C6EFFD225F6FB44CA9 + +I=46 +KEY=00000000000400000000000000000000 +CT=2E8767157922E3826DDCEC1B0CC1E105 + +I=47 +KEY=00000000000200000000000000000000 +CT=78CE7EEC670E45A967BAB17E26A1AD36 + +I=48 +KEY=00000000000100000000000000000000 +CT=3C5CEE825655F098F6E81A2F417DA3FB + +I=49 +KEY=00000000000080000000000000000000 +CT=67BFDB431DCE1292200BC6F5207ADB12 + +I=50 +KEY=00000000000040000000000000000000 +CT=7540FD38E447C0779228548747843A6F + +I=51 +KEY=00000000000020000000000000000000 +CT=B85E513301F8A936EA9EC8A21A85B5E6 + +I=52 +KEY=00000000000010000000000000000000 +CT=04C67DBF16C11427D507A455DE2C9BC5 + +I=53 +KEY=00000000000008000000000000000000 +CT=03F75EB8959E55079CFFB4FF149A37B6 + +I=54 +KEY=00000000000004000000000000000000 +CT=74550287F666C63BB9BC7838433434B0 + +I=55 +KEY=00000000000002000000000000000000 +CT=7D537200195EBC3AEFD1EAAB1C385221 + +I=56 +KEY=00000000000001000000000000000000 +CT=CE24E4D40C68A82B535CBD3C8E21652A + +I=57 +KEY=00000000000000800000000000000000 +CT=AB20072405AA8FC40265C6F1F3DC8BC0 + +I=58 +KEY=00000000000000400000000000000000 +CT=6CFD2CF688F566B093F67B9B3839E80A + +I=59 +KEY=00000000000000200000000000000000 +CT=BD95977E6B7239D407A012C5544BF584 + +I=60 +KEY=00000000000000100000000000000000 +CT=DF9C0130AC77E7C72C997F587B46DBE0 + +I=61 +KEY=00000000000000080000000000000000 +CT=E7F1B82CADC53A648798945B34EFEFF2 + +I=62 +KEY=00000000000000040000000000000000 +CT=932C6DBF69255CF13EDCDB72233ACEA3 + +I=63 +KEY=00000000000000020000000000000000 +CT=5C76002BC7206560EFE550C80B8F12CC + +I=64 +KEY=00000000000000010000000000000000 +CT=F6B7BDD1CAEEBAB574683893C4475484 + +I=65 +KEY=00000000000000008000000000000000 +CT=A920E37CC6DC6B31DA8C0169569F5034 + +I=66 +KEY=00000000000000004000000000000000 +CT=919380ECD9C778BC513148B0C28D65FD + +I=67 +KEY=00000000000000002000000000000000 +CT=EE67308DD3F2D9E6C2170755E5784BE1 + +I=68 +KEY=00000000000000001000000000000000 +CT=3CC73E53B85609023A05E149B223AE09 + +I=69 +KEY=00000000000000000800000000000000 +CT=983E8AF7CF05EBB28D71EB841C9406E6 + +I=70 +KEY=00000000000000000400000000000000 +CT=0F3099B2D31FA5299EE5BF43193287FC + +I=71 +KEY=00000000000000000200000000000000 +CT=B763D84F38C27FE6931DCEB6715D4DB6 + +I=72 +KEY=00000000000000000100000000000000 +CT=5AE3C9B0E3CC29C0C61565CD01F8A248 + +I=73 +KEY=00000000000000000080000000000000 +CT=F58083572CD90981958565D48D2DEE25 + +I=74 +KEY=00000000000000000040000000000000 +CT=7E6255EEF8F70C0EF10337AAB1CCCEF8 + +I=75 +KEY=00000000000000000020000000000000 +CT=AAD4BAC34DB22821841CE2F631961902 + +I=76 +KEY=00000000000000000010000000000000 +CT=D7431C0409BB1441BA9C6858DC7D4E81 + +I=77 +KEY=00000000000000000008000000000000 +CT=EF9298C65E339F6E801A59C626456993 + +I=78 +KEY=00000000000000000004000000000000 +CT=53FE29F68FF541ABC3F0EF3350B72F7E + +I=79 +KEY=00000000000000000002000000000000 +CT=F6BBA5C10DB02529E2C2DA3FB582CC14 + +I=80 +KEY=00000000000000000001000000000000 +CT=E4239AA37FC531A386DAD1126FC0E9CD + +I=81 +KEY=00000000000000000000800000000000 +CT=8F7758F857D15BBE7BFD0E416404C365 + +I=82 +KEY=00000000000000000000400000000000 +CT=D273EB57C687BCD1B4EA7218A509E7B8 + +I=83 +KEY=00000000000000000000200000000000 +CT=65D64F8D76E8B3423FA25C4EB58A210A + +I=84 +KEY=00000000000000000000100000000000 +CT=623D802B4EC450D66A16625702FCDBE0 + +I=85 +KEY=00000000000000000000080000000000 +CT=7496460CB28E5791BAEAF9B68FB00022 + +I=86 +KEY=00000000000000000000040000000000 +CT=34EA600F18BB0694B41681A49D510C1D + +I=87 +KEY=00000000000000000000020000000000 +CT=5F8FF0D47D5766D29B5D6E8F46423BD8 + +I=88 +KEY=00000000000000000000010000000000 +CT=225F9286C5928BF09F84D3F93F541959 + +I=89 +KEY=00000000000000000000008000000000 +CT=B21E90D25DF383416A5F072CEBEB1FFB + +I=90 +KEY=00000000000000000000004000000000 +CT=4AEFCDA089318125453EB9E8EB5E492E + +I=91 +KEY=00000000000000000000002000000000 +CT=4D3E75C6CD40EC4869BC85158591ADB8 + +I=92 +KEY=00000000000000000000001000000000 +CT=63A8B904405436A1B99D7751866771B7 + +I=93 +KEY=00000000000000000000000800000000 +CT=64F0DAAE47529199792EAE172BA53293 + +I=94 +KEY=00000000000000000000000400000000 +CT=C3EEF84BEA18225D515A8C852A9047EE + +I=95 +KEY=00000000000000000000000200000000 +CT=A44AC422B47D47B81AF73B3E9AC9596E + +I=96 +KEY=00000000000000000000000100000000 +CT=D16E04A8FBC435094F8D53ADF25F5084 + +I=97 +KEY=00000000000000000000000080000000 +CT=EF13DC34BAB03E124EEAD8B6BF44B532 + +I=98 +KEY=00000000000000000000000040000000 +CT=D94799075C24DCC067AF0D392049250D + +I=99 +KEY=00000000000000000000000020000000 +CT=14F431771EDDCE4764C21A2254B5E3C8 + +I=100 +KEY=00000000000000000000000010000000 +CT=7039329F36F2ED682B02991F28D64679 + +I=101 +KEY=00000000000000000000000008000000 +CT=124EE24EDE5551639DB8B8B941F6141D + +I=102 +KEY=00000000000000000000000004000000 +CT=C2852879A34D5184E478EC918B993FEE + +I=103 +KEY=00000000000000000000000002000000 +CT=86A806A3525B93E432053C9AB5ABBEDF + +I=104 +KEY=00000000000000000000000001000000 +CT=C1609BF5A4F07E37C17A36366EC23ECC + +I=105 +KEY=00000000000000000000000000800000 +CT=7E81E7CB92159A51FFCEA331B1E8EA53 + +I=106 +KEY=00000000000000000000000000400000 +CT=37A7BE002856C5A59A6E03EAFCE7729A + +I=107 +KEY=00000000000000000000000000200000 +CT=BDF98A5A4F91E890C9A1D1E5FAAB138F + +I=108 +KEY=00000000000000000000000000100000 +CT=4E96ACB66E051F2BC739CC3D3E34A26B + +I=109 +KEY=00000000000000000000000000080000 +CT=EE996CDD120EB86E21ECFA49E8E1FCF1 + +I=110 +KEY=00000000000000000000000000040000 +CT=61B9E6B579DBF6070C351A1440DD85FF + +I=111 +KEY=00000000000000000000000000020000 +CT=AC369E484316440B40DFC83AA96E28E7 + +I=112 +KEY=00000000000000000000000000010000 +CT=0A2D16DE985C76D45C579C1159413BBE + +I=113 +KEY=00000000000000000000000000008000 +CT=DA3FDC38DA1D374FA4802CDA1A1C6B0F + +I=114 +KEY=00000000000000000000000000004000 +CT=B842523D4C41C2211AFE43A5800ADCE3 + +I=115 +KEY=00000000000000000000000000002000 +CT=9E2CDA90D8E992DBA6C73D8229567192 + +I=116 +KEY=00000000000000000000000000001000 +CT=D49583B781D9E20F5BE101415957FC49 + +I=117 +KEY=00000000000000000000000000000800 +CT=EF09DA5C12B376E458B9B8670032498E + +I=118 +KEY=00000000000000000000000000000400 +CT=A96BE0463DA774461A5E1D5A9DD1AC10 + +I=119 +KEY=00000000000000000000000000000200 +CT=32CEE3341060790D2D4B1362EF397090 + +I=120 +KEY=00000000000000000000000000000100 +CT=21CEA416A3D3359D2C4D58FB6A035F06 + +I=121 +KEY=00000000000000000000000000000080 +CT=172AEAB3D507678ECAF455C12587ADB7 + +I=122 +KEY=00000000000000000000000000000040 +CT=B6F897941EF8EBFF9FE80A567EF38478 + +I=123 +KEY=00000000000000000000000000000020 +CT=A9723259D94A7DC662FB0C782CA3F1DD + +I=124 +KEY=00000000000000000000000000000010 +CT=2F91C984B9A4839F30001B9F430493B4 + +I=125 +KEY=00000000000000000000000000000008 +CT=0472406345A610B048CB99EE0EF3FA0F + +I=126 +KEY=00000000000000000000000000000004 +CT=F5F39086646F8C05ED16EFA4B617957C + +I=127 +KEY=00000000000000000000000000000002 +CT=26D50F485A30408D5AF47A5736292450 + +I=128 +KEY=00000000000000000000000000000001 +CT=0545AAD56DA2A97C3663D1432A3D1C84 + +========== + +KEYSIZE=256 + +PT=00000000000000000000000000000000 + +I=1 +KEY=8000000000000000000000000000000000000000000000000000000000000000 +CT=E35A6DCB19B201A01EBCFA8AA22B5759 + +I=2 +KEY=4000000000000000000000000000000000000000000000000000000000000000 +CT=5075C2405B76F22F553488CAE47CE90B + +I=3 +KEY=2000000000000000000000000000000000000000000000000000000000000000 +CT=49DF95D844A0145A7DE01C91793302D3 + +I=4 +KEY=1000000000000000000000000000000000000000000000000000000000000000 +CT=E7396D778E940B8418A86120E5F421FE + +I=5 +KEY=0800000000000000000000000000000000000000000000000000000000000000 +CT=05F535C36FCEDE4657BE37F4087DB1EF + +I=6 +KEY=0400000000000000000000000000000000000000000000000000000000000000 +CT=D0C1DDDD10DA777C68AB36AF51F2C204 + +I=7 +KEY=0200000000000000000000000000000000000000000000000000000000000000 +CT=1C55FB811B5C6464C4E5DE1535A75514 + +I=8 +KEY=0100000000000000000000000000000000000000000000000000000000000000 +CT=52917F3AE957D5230D3A2AF57C7B5A71 + +I=9 +KEY=0080000000000000000000000000000000000000000000000000000000000000 +CT=C6E3D5501752DD5E9AEF086D6B45D705 + +I=10 +KEY=0040000000000000000000000000000000000000000000000000000000000000 +CT=A24A9C7AF1D9B1E17E1C9A3E711B3FA7 + +I=11 +KEY=0020000000000000000000000000000000000000000000000000000000000000 +CT=B881ECA724A6D43DBC6B96F6F59A0D20 + +I=12 +KEY=0010000000000000000000000000000000000000000000000000000000000000 +CT=EC524D9A24DFFF2A9639879B83B8E137 + +I=13 +KEY=0008000000000000000000000000000000000000000000000000000000000000 +CT=34C4F345F5466215A037F443635D6F75 + +I=14 +KEY=0004000000000000000000000000000000000000000000000000000000000000 +CT=5BA5055BEDB8895F672E29F2EB5A355D + +I=15 +KEY=0002000000000000000000000000000000000000000000000000000000000000 +CT=B3F692AA3A435259EBBEF9B51AD1E08D + +I=16 +KEY=0001000000000000000000000000000000000000000000000000000000000000 +CT=414FEB4376F2C64A5D2FBB2ED531BA7D + +I=17 +KEY=0000800000000000000000000000000000000000000000000000000000000000 +CT=A20D519E3BCA3303F07E81719F61605E + +I=18 +KEY=0000400000000000000000000000000000000000000000000000000000000000 +CT=A08D10E520AF811F45BD60A2DC0DC4B1 + +I=19 +KEY=0000200000000000000000000000000000000000000000000000000000000000 +CT=B06893A8C563C430E6F3858826EFBBE4 + +I=20 +KEY=0000100000000000000000000000000000000000000000000000000000000000 +CT=0FFEE26AE2D3929C6BD9C6BEDFF84409 + +I=21 +KEY=0000080000000000000000000000000000000000000000000000000000000000 +CT=4D0F5E906ED77801FC0EF53EDC5F9E2B + +I=22 +KEY=0000040000000000000000000000000000000000000000000000000000000000 +CT=8B6EC00119AD8B026DCE56EA7DEFE930 + +I=23 +KEY=0000020000000000000000000000000000000000000000000000000000000000 +CT=69026591D43363EE9D83B5007F0B484E + +I=24 +KEY=0000010000000000000000000000000000000000000000000000000000000000 +CT=27135D86950C6A2F86872706279A4761 + +I=25 +KEY=0000008000000000000000000000000000000000000000000000000000000000 +CT=35E6DB8723F281DA410C3AC8535ED77C + +I=26 +KEY=0000004000000000000000000000000000000000000000000000000000000000 +CT=57427CF214B8C28E4BBF487CCB8D0E09 + +I=27 +KEY=0000002000000000000000000000000000000000000000000000000000000000 +CT=6DF01BF56E5131AC87F96E99CAB86367 + +I=28 +KEY=0000001000000000000000000000000000000000000000000000000000000000 +CT=3856C5B55790B768BBF7D43031579BCF + +I=29 +KEY=0000000800000000000000000000000000000000000000000000000000000000 +CT=1E6ED8FB7C15BC4D2F63BA7037ED44D0 + +I=30 +KEY=0000000400000000000000000000000000000000000000000000000000000000 +CT=E1B2ED6CD8D93D455534E401156D4BCF + +I=31 +KEY=0000000200000000000000000000000000000000000000000000000000000000 +CT=EFBCCA5BDFDAD10E875F02336212CE36 + +I=32 +KEY=0000000100000000000000000000000000000000000000000000000000000000 +CT=0B777F02FD18DCE2646DCFE868DFAFAD + +I=33 +KEY=0000000080000000000000000000000000000000000000000000000000000000 +CT=C8A104B5693D1B14F5BF1F10100BF508 + +I=34 +KEY=0000000040000000000000000000000000000000000000000000000000000000 +CT=4CCE6615244AFCB38408FECE219962EA + +I=35 +KEY=0000000020000000000000000000000000000000000000000000000000000000 +CT=F99E7845D3A255B394C9C050CBA258B1 + +I=36 +KEY=0000000010000000000000000000000000000000000000000000000000000000 +CT=B4AFBB787F9BCFB7B55FDF447F611295 + +I=37 +KEY=0000000008000000000000000000000000000000000000000000000000000000 +CT=AE1C426A697FAF2808B7EF6ADDB5C020 + +I=38 +KEY=0000000004000000000000000000000000000000000000000000000000000000 +CT=7572F92811A85B9BDD38DEAD9945BCAE + +I=39 +KEY=0000000002000000000000000000000000000000000000000000000000000000 +CT=71BC7AA46E43FB95A181527D9F6A360F + +I=40 +KEY=0000000001000000000000000000000000000000000000000000000000000000 +CT=5542EF2923066F1EC8F546DD0D8E7CA8 + +I=41 +KEY=0000000000800000000000000000000000000000000000000000000000000000 +CT=6B92317C7D623790B748FDD7EFC42422 + +I=42 +KEY=0000000000400000000000000000000000000000000000000000000000000000 +CT=0FE7C097E899C71EF045360F8D6C25CF + +I=43 +KEY=0000000000200000000000000000000000000000000000000000000000000000 +CT=4ECE7EE107D0264D04693151C25B9DF6 + +I=44 +KEY=0000000000100000000000000000000000000000000000000000000000000000 +CT=FD6AE687CBFCA9E301045888D3BB9605 + +I=45 +KEY=0000000000080000000000000000000000000000000000000000000000000000 +CT=476B579C8556C7254424902CC1D6D36E + +I=46 +KEY=0000000000040000000000000000000000000000000000000000000000000000 +CT=4133CBCDFDD6B8860A1FC18665D6D71B + +I=47 +KEY=0000000000020000000000000000000000000000000000000000000000000000 +CT=3B36EC2664798C108B816812C65DFDC7 + +I=48 +KEY=0000000000010000000000000000000000000000000000000000000000000000 +CT=364E20A234FEA385D48DC5A09C9E70CF + +I=49 +KEY=0000000000008000000000000000000000000000000000000000000000000000 +CT=4A4BA25969DE3F5EE5642C71AAD0EFD1 + +I=50 +KEY=0000000000004000000000000000000000000000000000000000000000000000 +CT=E42CBAAE43297F67A76C1C501BB79E36 + +I=51 +KEY=0000000000002000000000000000000000000000000000000000000000000000 +CT=23CEDEDA4C15B4C037E8C61492217937 + +I=52 +KEY=0000000000001000000000000000000000000000000000000000000000000000 +CT=A1719147A1F4A1A1180BD16E8593DCDE + +I=53 +KEY=0000000000000800000000000000000000000000000000000000000000000000 +CT=AB82337E9FB0EC60D1F25A1D0014192C + +I=54 +KEY=0000000000000400000000000000000000000000000000000000000000000000 +CT=74BF2D8FC5A8388DF1A3A4D7D33FC164 + +I=55 +KEY=0000000000000200000000000000000000000000000000000000000000000000 +CT=D5B493317E6FBC6FFFD664B3C491368A + +I=56 +KEY=0000000000000100000000000000000000000000000000000000000000000000 +CT=BA767381586DA56A2A8D503D5F7ADA0B + +I=57 +KEY=0000000000000080000000000000000000000000000000000000000000000000 +CT=E8E6BC57DFE9CCADB0DECABF4E5CF91F + +I=58 +KEY=0000000000000040000000000000000000000000000000000000000000000000 +CT=3C8E5A5CDC9CEED90815D1F84BB2998C + +I=59 +KEY=0000000000000020000000000000000000000000000000000000000000000000 +CT=283843020BA38F056001B2FD585F7CC9 + +I=60 +KEY=0000000000000010000000000000000000000000000000000000000000000000 +CT=D8ADC7426F623ECE8741A70621D28870 + +I=61 +KEY=0000000000000008000000000000000000000000000000000000000000000000 +CT=D7C5C215592D06F00E6A80DA69A28EA9 + +I=62 +KEY=0000000000000004000000000000000000000000000000000000000000000000 +CT=52CF6FA433C3C870CAC70190358F7F16 + +I=63 +KEY=0000000000000002000000000000000000000000000000000000000000000000 +CT=F63D442A584DA71786ADEC9F3346DF75 + +I=64 +KEY=0000000000000001000000000000000000000000000000000000000000000000 +CT=549078F4B0CA7079B45F9A5ADAFAFD99 + +I=65 +KEY=0000000000000000800000000000000000000000000000000000000000000000 +CT=F2A5986EE4E9984BE2BAFB79EA8152FA + +I=66 +KEY=0000000000000000400000000000000000000000000000000000000000000000 +CT=8A74535017B4DB2776668A1FAE64384C + +I=67 +KEY=0000000000000000200000000000000000000000000000000000000000000000 +CT=E613342F57A97FD95DC088711A5D0ECD + +I=68 +KEY=0000000000000000100000000000000000000000000000000000000000000000 +CT=3FFAEBF6B22CF1DC82AE17CD48175B01 + +I=69 +KEY=0000000000000000080000000000000000000000000000000000000000000000 +CT=BAFD52EFA15C248CCBF9757735E6B1CE + +I=70 +KEY=0000000000000000040000000000000000000000000000000000000000000000 +CT=7AF94BC018D9DDD4539D2DD1C6F4000F + +I=71 +KEY=0000000000000000020000000000000000000000000000000000000000000000 +CT=FE177AD61CA0FDB281086FBA8FE76803 + +I=72 +KEY=0000000000000000010000000000000000000000000000000000000000000000 +CT=74DBEA15E2E9285BAD163D7D534251B6 + +I=73 +KEY=0000000000000000008000000000000000000000000000000000000000000000 +CT=23DD21331B3A92F200FE56FF050FFE74 + +I=74 +KEY=0000000000000000004000000000000000000000000000000000000000000000 +CT=A69C5AA34AB20A858CAFA766EACED6D8 + +I=75 +KEY=0000000000000000002000000000000000000000000000000000000000000000 +CT=3F72BB4DF2A4F941A4A09CB78F04B97A + +I=76 +KEY=0000000000000000001000000000000000000000000000000000000000000000 +CT=72CC43577E1FD5FD14622D24D97FCDCC + +I=77 +KEY=0000000000000000000800000000000000000000000000000000000000000000 +CT=D83AF8EBE93E0B6B99CAFADE224937D1 + +I=78 +KEY=0000000000000000000400000000000000000000000000000000000000000000 +CT=44042329128D56CAA8D084C8BD769D1E + +I=79 +KEY=0000000000000000000200000000000000000000000000000000000000000000 +CT=14102D72290DE4F2C430ADD1ED64BA1D + +I=80 +KEY=0000000000000000000100000000000000000000000000000000000000000000 +CT=449124097B1ECD0AE7065206DF06F03C + +I=81 +KEY=0000000000000000000080000000000000000000000000000000000000000000 +CT=D060A99F8CC153A42E11E5F97BD7584A + +I=82 +KEY=0000000000000000000040000000000000000000000000000000000000000000 +CT=65605B3EA9261488D53E48602ADEA299 + +I=83 +KEY=0000000000000000000020000000000000000000000000000000000000000000 +CT=C5E5CAD7A208DE8EA6BE049EFE5C7346 + +I=84 +KEY=0000000000000000000010000000000000000000000000000000000000000000 +CT=4C280C46D2181646048DD5BC0C0831A5 + +I=85 +KEY=0000000000000000000008000000000000000000000000000000000000000000 +CT=5DD65CF37F2A0929559AABAFDA08E730 + +I=86 +KEY=0000000000000000000004000000000000000000000000000000000000000000 +CT=31F2335CAAF264172F69A693225E6D22 + +I=87 +KEY=0000000000000000000002000000000000000000000000000000000000000000 +CT=3E28B35F99A72662590DA96426DD377F + +I=88 +KEY=0000000000000000000001000000000000000000000000000000000000000000 +CT=570F40F5D7B20441486578ED344343BE + +I=89 +KEY=0000000000000000000000800000000000000000000000000000000000000000 +CT=C54308AD1C9E3B19F8B7417873045A8C + +I=90 +KEY=0000000000000000000000400000000000000000000000000000000000000000 +CT=CBF335E39CE13ADE2B696179E8FD0CE1 + +I=91 +KEY=0000000000000000000000200000000000000000000000000000000000000000 +CT=9C2FBF422355D8293083D51F4A3C18A9 + +I=92 +KEY=0000000000000000000000100000000000000000000000000000000000000000 +CT=5ED8B5A31ECEFAB16C9AA6986DA67BCE + +I=93 +KEY=0000000000000000000000080000000000000000000000000000000000000000 +CT=627815DCFC814ABC75900041B1DD7B59 + +I=94 +KEY=0000000000000000000000040000000000000000000000000000000000000000 +CT=9EF3E82A50A59F166260494F7A7F2CC3 + +I=95 +KEY=0000000000000000000000020000000000000000000000000000000000000000 +CT=878CD0D8D920888B5935D6C351128737 + +I=96 +KEY=0000000000000000000000010000000000000000000000000000000000000000 +CT=E44429474D6FC3084EB2A6B8B46AF754 + +I=97 +KEY=0000000000000000000000008000000000000000000000000000000000000000 +CT=EBAACF9641D54E1FB18D0A2BE4F19BE5 + +I=98 +KEY=0000000000000000000000004000000000000000000000000000000000000000 +CT=13B3BF497CEE780E123C7E193DEA3A01 + +I=99 +KEY=0000000000000000000000002000000000000000000000000000000000000000 +CT=6E8F381DE00A41161F0DF03B4155BFD4 + +I=100 +KEY=0000000000000000000000001000000000000000000000000000000000000000 +CT=35E4F29BBA2BAE01144910783C3FEF49 + +I=101 +KEY=0000000000000000000000000800000000000000000000000000000000000000 +CT=55B17BD66788CEAC366398A31F289FFB + +I=102 +KEY=0000000000000000000000000400000000000000000000000000000000000000 +CT=11341F56C0D6D1008D28741DAA7679CE + +I=103 +KEY=0000000000000000000000000200000000000000000000000000000000000000 +CT=4DF7253DF421D83358BDBE924745D98C + +I=104 +KEY=0000000000000000000000000100000000000000000000000000000000000000 +CT=BAE2EE651116D93EDC8E83B5F3347BE1 + +I=105 +KEY=0000000000000000000000000080000000000000000000000000000000000000 +CT=F9721ABD06709157183AF3965A659D9D + +I=106 +KEY=0000000000000000000000000040000000000000000000000000000000000000 +CT=19A1C252A613FE2860A4AE6D75CE6FA3 + +I=107 +KEY=0000000000000000000000000020000000000000000000000000000000000000 +CT=B5DDB2F5D9752C949FBDE3FFF5556C6E + +I=108 +KEY=0000000000000000000000000010000000000000000000000000000000000000 +CT=81B044FCFFC78ECCFCD171AAD0405C66 + +I=109 +KEY=0000000000000000000000000008000000000000000000000000000000000000 +CT=C640566D3C06020EB2C42F1D62E56A9B + +I=110 +KEY=0000000000000000000000000004000000000000000000000000000000000000 +CT=EA6C4BCF425291679FDFFD26A424FBCC + +I=111 +KEY=0000000000000000000000000002000000000000000000000000000000000000 +CT=57F6901465D9440D9F15EE2CBA5A4090 + +I=112 +KEY=0000000000000000000000000001000000000000000000000000000000000000 +CT=FBCFA74CADC7406260F63D96C8AAB6B1 + +I=113 +KEY=0000000000000000000000000000800000000000000000000000000000000000 +CT=DFF4F096CEA211D4BBDACA033D0EC7D1 + +I=114 +KEY=0000000000000000000000000000400000000000000000000000000000000000 +CT=1EE5190D551F0F42F675227A381296A9 + +I=115 +KEY=0000000000000000000000000000200000000000000000000000000000000000 +CT=F98E1905012E580F097623C10B93054F + +I=116 +KEY=0000000000000000000000000000100000000000000000000000000000000000 +CT=E7D43743D21DD3C9F168C86856558B9A + +I=117 +KEY=0000000000000000000000000000080000000000000000000000000000000000 +CT=632A9DDA730DAB67593C5D08D8AC1059 + +I=118 +KEY=0000000000000000000000000000040000000000000000000000000000000000 +CT=E084317000715B9057BC9DE9F3AB6124 + +I=119 +KEY=0000000000000000000000000000020000000000000000000000000000000000 +CT=61F9EF33A0BB4E666C2ED99101919FAB + +I=120 +KEY=0000000000000000000000000000010000000000000000000000000000000000 +CT=6DC1D68A11834657D46703C22578D59A + +I=121 +KEY=0000000000000000000000000000008000000000000000000000000000000000 +CT=53AC1548863D3D16F1D4DC7242E05F2C + +I=122 +KEY=0000000000000000000000000000004000000000000000000000000000000000 +CT=E82CD587A408306AD78CEAE0916B9F8C + +I=123 +KEY=0000000000000000000000000000002000000000000000000000000000000000 +CT=0FD2D40EA6AD17A3A767F0A8600D6295 + +I=124 +KEY=0000000000000000000000000000001000000000000000000000000000000000 +CT=AD84CC8255ADB39DFCA23F92761AE7E9 + +I=125 +KEY=0000000000000000000000000000000800000000000000000000000000000000 +CT=F4F20CF7D51BEE7DA024A2B11A7ECA0B + +I=126 +KEY=0000000000000000000000000000000400000000000000000000000000000000 +CT=5057691B85D9CE93A193214DB0A016B6 + +I=127 +KEY=0000000000000000000000000000000200000000000000000000000000000000 +CT=0F58C960876390BDEF4BB6BE95CAA1EE + +I=128 +KEY=0000000000000000000000000000000100000000000000000000000000000000 +CT=9A3E66EEBC21BC0BD9430B341EF465FA + +I=129 +KEY=0000000000000000000000000000000080000000000000000000000000000000 +CT=20415035F34B8BCBCB28ABF07F78F0D4 + +I=130 +KEY=0000000000000000000000000000000040000000000000000000000000000000 +CT=AC89FC7BA10479EBF10DE65BCEF89B3C + +I=131 +KEY=0000000000000000000000000000000020000000000000000000000000000000 +CT=068FA75A30BE443171AF3F6FEB1A20D2 + +I=132 +KEY=0000000000000000000000000000000010000000000000000000000000000000 +CT=50E02F213246C525A8C27700CA34B502 + +I=133 +KEY=0000000000000000000000000000000008000000000000000000000000000000 +CT=227DA47D5A0906DB3AB042BB0A695FB6 + +I=134 +KEY=0000000000000000000000000000000004000000000000000000000000000000 +CT=8663AC30ED12514F1DE46777F4514BFC + +I=135 +KEY=0000000000000000000000000000000002000000000000000000000000000000 +CT=A987D4BC12E1DE9F4B6DF43567C34A8B + +I=136 +KEY=0000000000000000000000000000000001000000000000000000000000000000 +CT=6D5A0370F599ACA605F63B04E5143D0C + +I=137 +KEY=0000000000000000000000000000000000800000000000000000000000000000 +CT=9809266E378B07B7AFDB3BAA97B7E442 + +I=138 +KEY=0000000000000000000000000000000000400000000000000000000000000000 +CT=8F753252B30CCCACE12D9A301F4D5090 + +I=139 +KEY=0000000000000000000000000000000000200000000000000000000000000000 +CT=032465F6C0CE34D41962F561692A1AFF + +I=140 +KEY=0000000000000000000000000000000000100000000000000000000000000000 +CT=C50E9AD5BEB8F3B00821DD47FF8AC093 + +I=141 +KEY=0000000000000000000000000000000000080000000000000000000000000000 +CT=9C6FEA3D46268D54A6829B2AD25BB276 + +I=142 +KEY=0000000000000000000000000000000000040000000000000000000000000000 +CT=0FD8575E87706F561343D7B3A41E044A + +I=143 +KEY=0000000000000000000000000000000000020000000000000000000000000000 +CT=BEE9BEB3739540D88CBCE77925F0A114 + +I=144 +KEY=0000000000000000000000000000000000010000000000000000000000000000 +CT=D24EAEE7FFFBAC3D6F26C2DCE0DCDE28 + +I=145 +KEY=0000000000000000000000000000000000008000000000000000000000000000 +CT=47771A90398FF0F7FA821C2F8F5E1398 + +I=146 +KEY=0000000000000000000000000000000000004000000000000000000000000000 +CT=4639741B6F84B135AD118C8249B64ED0 + +I=147 +KEY=0000000000000000000000000000000000002000000000000000000000000000 +CT=8EE5505EC85567697A3306F250A27720 + +I=148 +KEY=0000000000000000000000000000000000001000000000000000000000000000 +CT=7C8A19AC1AEFBC5E0119D91A5F05D4C2 + +I=149 +KEY=0000000000000000000000000000000000000800000000000000000000000000 +CT=5141B9B672E54773B672E3A6C424887B + +I=150 +KEY=0000000000000000000000000000000000000400000000000000000000000000 +CT=B5A2D3CD206653C6402F34FB0AE3613D + +I=151 +KEY=0000000000000000000000000000000000000200000000000000000000000000 +CT=0F5BD9408738231D114B0A82753279A3 + +I=152 +KEY=0000000000000000000000000000000000000100000000000000000000000000 +CT=FEF033FF4268EA487FC74C5E43A45338 + +I=153 +KEY=0000000000000000000000000000000000000080000000000000000000000000 +CT=A3EDC09DCD529B113910D904AD855581 + +I=154 +KEY=0000000000000000000000000000000000000040000000000000000000000000 +CT=AB8FBB6F27A0AC7C55B59FDD36B72F1C + +I=155 +KEY=0000000000000000000000000000000000000020000000000000000000000000 +CT=EEA44D5ED4D769CC930CD83D8999EC46 + +I=156 +KEY=0000000000000000000000000000000000000010000000000000000000000000 +CT=6972276803AE9AA7C6F431AB10979C34 + +I=157 +KEY=0000000000000000000000000000000000000008000000000000000000000000 +CT=86DEAA9F39244101818178474D7DBDE9 + +I=158 +KEY=0000000000000000000000000000000000000004000000000000000000000000 +CT=88C6B466EA361D662D8D08CBF181F4FE + +I=159 +KEY=0000000000000000000000000000000000000002000000000000000000000000 +CT=91AB2C6B7C63FF59F7CBEEBF91B20B95 + +I=160 +KEY=0000000000000000000000000000000000000001000000000000000000000000 +CT=2DFE6C146AD5B3D8C3C1718F13B48E01 + +I=161 +KEY=0000000000000000000000000000000000000000800000000000000000000000 +CT=C7CFF1623451711391A302EEC3584AAA + +I=162 +KEY=0000000000000000000000000000000000000000400000000000000000000000 +CT=089FE845CC05011686C66019D18BE050 + +I=163 +KEY=0000000000000000000000000000000000000000200000000000000000000000 +CT=08C8410B9B427211A67124B0DCCEAD48 + +I=164 +KEY=0000000000000000000000000000000000000000100000000000000000000000 +CT=8D91592F5566085254784606334D7629 + +I=165 +KEY=0000000000000000000000000000000000000000080000000000000000000000 +CT=3298FEAAF2E1201D6299FF8846639C97 + +I=166 +KEY=0000000000000000000000000000000000000000040000000000000000000000 +CT=C497CB9F0BDFE0EFC8C2F3F90760AA72 + +I=167 +KEY=0000000000000000000000000000000000000000020000000000000000000000 +CT=2788AFD046E0309CBE4424690DA2AB89 + +I=168 +KEY=0000000000000000000000000000000000000000010000000000000000000000 +CT=E9891707F25EF29FEE372890D4258982 + +I=169 +KEY=0000000000000000000000000000000000000000008000000000000000000000 +CT=DB041D94A23D45D4D4DCED5A030CAF61 + +I=170 +KEY=0000000000000000000000000000000000000000004000000000000000000000 +CT=FFAFDBF0ECB18DF9EA02C27077448E6D + +I=171 +KEY=0000000000000000000000000000000000000000002000000000000000000000 +CT=2DAAA42A7D0A1D3B0E4761D99CF2150A + +I=172 +KEY=0000000000000000000000000000000000000000001000000000000000000000 +CT=3B7A54CB7CF30ABE263DD6ED5BFE8D63 + +I=173 +KEY=0000000000000000000000000000000000000000000800000000000000000000 +CT=EEFA090174C590C448A55D43648F534A + +I=174 +KEY=0000000000000000000000000000000000000000000400000000000000000000 +CT=9E15798731ED42F43EA2740A691DA872 + +I=175 +KEY=0000000000000000000000000000000000000000000200000000000000000000 +CT=31FBD661540A5DEAAD1017CFD3909EC8 + +I=176 +KEY=0000000000000000000000000000000000000000000100000000000000000000 +CT=CDA9AE05F224140E28CB951721B44D6A + +I=177 +KEY=0000000000000000000000000000000000000000000080000000000000000000 +CT=0C5BC512C60A1EAC3434EFB1A8FBB182 + +I=178 +KEY=0000000000000000000000000000000000000000000040000000000000000000 +CT=AA863610DEEEEB62D045E87EA30B59B5 + +I=179 +KEY=0000000000000000000000000000000000000000000020000000000000000000 +CT=6AC2448DE568D279C7EEBE1DF403920C + +I=180 +KEY=0000000000000000000000000000000000000000000010000000000000000000 +CT=E2011E3D292B26888AE801215FD0CB40 + +I=181 +KEY=0000000000000000000000000000000000000000000008000000000000000000 +CT=E06F3E15EE3A61672D1C99BADE5B9DBE + +I=182 +KEY=0000000000000000000000000000000000000000000004000000000000000000 +CT=BB7027F0548CF6712CEB4C7A4B28E178 + +I=183 +KEY=0000000000000000000000000000000000000000000002000000000000000000 +CT=061EC21FB70FADBDF87C3BD2AE23825B + +I=184 +KEY=0000000000000000000000000000000000000000000001000000000000000000 +CT=4C21F26FE94ABBAC381352375314C3EB + +I=185 +KEY=0000000000000000000000000000000000000000000000800000000000000000 +CT=F7CEE6DD99909C2B569EEDA61ED8942E + +I=186 +KEY=0000000000000000000000000000000000000000000000400000000000000000 +CT=CE98C4A876C65E4CCB261EBB1D9DF7F5 + +I=187 +KEY=0000000000000000000000000000000000000000000000200000000000000000 +CT=A5491881CF833C3604ABC08044F402AC + +I=188 +KEY=0000000000000000000000000000000000000000000000100000000000000000 +CT=A1BA16E64CCCB3087D57A768507B0BFC + +I=189 +KEY=0000000000000000000000000000000000000000000000080000000000000000 +CT=D55951E202D2949EBD3BE43120C738BF + +I=190 +KEY=0000000000000000000000000000000000000000000000040000000000000000 +CT=EBB8E43069E69F450EFEC65DCD52B7FD + +I=191 +KEY=0000000000000000000000000000000000000000000000020000000000000000 +CT=2B292135663B4AA5ABFE9423D57E7EE9 + +I=192 +KEY=0000000000000000000000000000000000000000000000010000000000000000 +CT=E91BF974B3BE3AD966249D8655292A85 + +I=193 +KEY=0000000000000000000000000000000000000000000000008000000000000000 +CT=384365998EAA9562236CC58F6ADF9610 + +I=194 +KEY=0000000000000000000000000000000000000000000000004000000000000000 +CT=C2E997012AA3D4D8D359C9A947CBE69F + +I=195 +KEY=0000000000000000000000000000000000000000000000002000000000000000 +CT=F49421204148BA213BE87E2D5C22B0BF + +I=196 +KEY=0000000000000000000000000000000000000000000000001000000000000000 +CT=82ED0ED9953AA92E4DF30929CA65C00F + +I=197 +KEY=0000000000000000000000000000000000000000000000000800000000000000 +CT=291EB1D11653C8479437C74A977F5106 + +I=198 +KEY=0000000000000000000000000000000000000000000000000400000000000000 +CT=BCB997B1939B8983ABD550D6025683E3 + +I=199 +KEY=0000000000000000000000000000000000000000000000000200000000000000 +CT=1FBA2592C6F489775CAADA71F9B983E9 + +I=200 +KEY=0000000000000000000000000000000000000000000000000100000000000000 +CT=969F66F217AF1A3DB9E41C1B29039824 + +I=201 +KEY=0000000000000000000000000000000000000000000000000080000000000000 +CT=A54BB7D6B17E423AC0A7744C19073CB8 + +I=202 +KEY=0000000000000000000000000000000000000000000000000040000000000000 +CT=B0AC6E6578D1021F47DCF9748A32EAD5 + +I=203 +KEY=0000000000000000000000000000000000000000000000000020000000000000 +CT=B87B361C3B7B194C77A4358D4669153E + +I=204 +KEY=0000000000000000000000000000000000000000000000000010000000000000 +CT=46A133847F96EAA8282A799DC8899D58 + +I=205 +KEY=0000000000000000000000000000000000000000000000000008000000000000 +CT=2265EC3A9F2D5C9547A091CC8CFB18EA + +I=206 +KEY=0000000000000000000000000000000000000000000000000004000000000000 +CT=54CBF3A6FC4FE56D426117AA1FFD1DDE + +I=207 +KEY=0000000000000000000000000000000000000000000000000002000000000000 +CT=5312877CCEAB6CFB0905394A370A8003 + +I=208 +KEY=0000000000000000000000000000000000000000000000000001000000000000 +CT=7190BD6EC613FE38B84ECFE28F702FE4 + +I=209 +KEY=0000000000000000000000000000000000000000000000000000800000000000 +CT=D1FA5B9CA89A43B04C05F0EF29EF68CD + +I=210 +KEY=0000000000000000000000000000000000000000000000000000400000000000 +CT=808285751548ED934FD1056D2D9AE8BA + +I=211 +KEY=0000000000000000000000000000000000000000000000000000200000000000 +CT=2758DEF3E7B95A9AE89777BE64D5A6CF + +I=212 +KEY=0000000000000000000000000000000000000000000000000000100000000000 +CT=07D81F87DB3E0ACC82B01E08FB22F3C1 + +I=213 +KEY=0000000000000000000000000000000000000000000000000000080000000000 +CT=8DA250E5553D650711A75EE1CB4FD1C7 + +I=214 +KEY=0000000000000000000000000000000000000000000000000000040000000000 +CT=A93D946BD0E87F32719DF5F158CEE669 + +I=215 +KEY=0000000000000000000000000000000000000000000000000000020000000000 +CT=03945236EC2A4D4EAF30B8ABEB54330D + +I=216 +KEY=0000000000000000000000000000000000000000000000000000010000000000 +CT=11CC35301F24B79DDE31AEA2D1354F88 + +I=217 +KEY=0000000000000000000000000000000000000000000000000000008000000000 +CT=E73715B3E8D9A290F44AE6FFBF247E5D + +I=218 +KEY=0000000000000000000000000000000000000000000000000000004000000000 +CT=7345E07732B71CB158BBF64CCA5C5B96 + +I=219 +KEY=0000000000000000000000000000000000000000000000000000002000000000 +CT=6E128F296D24705A1924FD9B70C4ED04 + +I=220 +KEY=0000000000000000000000000000000000000000000000000000001000000000 +CT=95A789776F036783FBD330947083F54F + +I=221 +KEY=0000000000000000000000000000000000000000000000000000000800000000 +CT=360DEC2533EA4AA2E3E54FD3DE2906EB + +I=222 +KEY=0000000000000000000000000000000000000000000000000000000400000000 +CT=E68EFD7FECF4D601EA22727BD764965B + +I=223 +KEY=0000000000000000000000000000000000000000000000000000000200000000 +CT=9065C64A8BFF44AC33EDBB611CF83D7B + +I=224 +KEY=0000000000000000000000000000000000000000000000000000000100000000 +CT=8F33C8DF2A7A51CE8090E8F123BC3723 + +I=225 +KEY=0000000000000000000000000000000000000000000000000000000080000000 +CT=807F391FFBA8291BA625623210F99018 + +I=226 +KEY=0000000000000000000000000000000000000000000000000000000040000000 +CT=5E8B3F3A701522CE5CAA761C929D6292 + +I=227 +KEY=0000000000000000000000000000000000000000000000000000000020000000 +CT=3BA404DC38735A78289E3809E8364835 + +I=228 +KEY=0000000000000000000000000000000000000000000000000000000010000000 +CT=D23BEDBAD229F8305DC425B6B759DCC9 + +I=229 +KEY=0000000000000000000000000000000000000000000000000000000008000000 +CT=44880F21CF5913040AE376AEE2A10AD8 + +I=230 +KEY=0000000000000000000000000000000000000000000000000000000004000000 +CT=9BC98E29D057C0E828C3B5CCE69256C1 + +I=231 +KEY=0000000000000000000000000000000000000000000000000000000002000000 +CT=B293CC7A975DA141A68279368057CC41 + +I=232 +KEY=0000000000000000000000000000000000000000000000000000000001000000 +CT=8D60FB87ACD91385B313BE5F1D7BD30F + +I=233 +KEY=0000000000000000000000000000000000000000000000000000000000800000 +CT=2C8E56132D70291B303C48FDF75543CD + +I=234 +KEY=0000000000000000000000000000000000000000000000000000000000400000 +CT=D1F80035B826791F6CE4E59B7DB1BB0D + +I=235 +KEY=0000000000000000000000000000000000000000000000000000000000200000 +CT=42CE6224FC36469339A133DD08173BD4 + +I=236 +KEY=0000000000000000000000000000000000000000000000000000000000100000 +CT=61817155EA41BCBA2AF7F06AE7CBF585 + +I=237 +KEY=0000000000000000000000000000000000000000000000000000000000080000 +CT=D1923A9866068D2EF5FB77D57C3315B6 + +I=238 +KEY=0000000000000000000000000000000000000000000000000000000000040000 +CT=B37CBDB5D719F49691CA968EF2E84140 + +I=239 +KEY=0000000000000000000000000000000000000000000000000000000000020000 +CT=EC974E653A055D7F8F22171030F68E1D + +I=240 +KEY=0000000000000000000000000000000000000000000000000000000000010000 +CT=DDE5D3B9AAD9C32213BB3675A822499C + +I=241 +KEY=0000000000000000000000000000000000000000000000000000000000008000 +CT=D3B6E9216EA1AE57EB1C628A3C38AB78 + +I=242 +KEY=0000000000000000000000000000000000000000000000000000000000004000 +CT=82C99ECC69472B7E96324B042AE8B87A + +I=243 +KEY=0000000000000000000000000000000000000000000000000000000000002000 +CT=97144DC5338C43600F84439C0AA0D147 + +I=244 +KEY=0000000000000000000000000000000000000000000000000000000000001000 +CT=400AC4A0BBADA1DB2121EB144C7E5209 + +I=245 +KEY=0000000000000000000000000000000000000000000000000000000000000800 +CT=EFD9D550EB419ED278F4885A490AB54C + +I=246 +KEY=0000000000000000000000000000000000000000000000000000000000000400 +CT=2AB7816E149B7C0404C88A8857793670 + +I=247 +KEY=0000000000000000000000000000000000000000000000000000000000000200 +CT=5B591DFF9E8DEE15BAD24C025DBCA481 + +I=248 +KEY=0000000000000000000000000000000000000000000000000000000000000100 +CT=0C06633E30721C3749F49AD8CBF2B754 + +I=249 +KEY=0000000000000000000000000000000000000000000000000000000000000080 +CT=96D6D31A41B5123B2035FD91A921D4CA + +I=250 +KEY=0000000000000000000000000000000000000000000000000000000000000040 +CT=E7F6C34D86668BC2805CA7793C5E86AD + +I=251 +KEY=0000000000000000000000000000000000000000000000000000000000000020 +CT=F46DFF5FF500D6879C4D3E45CF0CF0F3 + +I=252 +KEY=0000000000000000000000000000000000000000000000000000000000000010 +CT=60D842D9C61DA7495C116197B7CECBBE + +I=253 +KEY=0000000000000000000000000000000000000000000000000000000000000008 +CT=D45B24EDB673353EBDF248B8FA06B67A + +I=254 +KEY=0000000000000000000000000000000000000000000000000000000000000004 +CT=119EAEBCC165D0BD02C0D35DC82EF992 + +I=255 +KEY=0000000000000000000000000000000000000000000000000000000000000002 +CT=E673143680414ADA301D0ED34626B9FE + +I=256 +KEY=0000000000000000000000000000000000000000000000000000000000000001 +CT=6B6CFE160A6263631B292F879EEFF926 + +========== diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/expect-vt.txt b/krb5-1.21.3/src/lib/crypto/crypto_tests/expect-vt.txt new file mode 100644 index 00000000..02b238c0 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/expect-vt.txt @@ -0,0 +1,1036 @@ + +KEYSIZE=128 + +KEY=00000000000000000000000000000000 + +I=1 +PT=80000000000000000000000000000000 +CT=3AD78E726C1EC02B7EBFE92B23D9EC34 + +I=2 +PT=40000000000000000000000000000000 +CT=45BC707D29E8204D88DFBA2F0B0CAD9B + +I=3 +PT=20000000000000000000000000000000 +CT=161556838018F52805CDBD6202002E3F + +I=4 +PT=10000000000000000000000000000000 +CT=F5569B3AB6A6D11EFDE1BF0A64C6854A + +I=5 +PT=08000000000000000000000000000000 +CT=64E82B50E501FBD7DD4116921159B83E + +I=6 +PT=04000000000000000000000000000000 +CT=BAAC12FB613A7DE11450375C74034041 + +I=7 +PT=02000000000000000000000000000000 +CT=BCF176A7EAAD8085EBACEA362462A281 + +I=8 +PT=01000000000000000000000000000000 +CT=47711816E91D6FF059BBBF2BF58E0FD3 + +I=9 +PT=00800000000000000000000000000000 +CT=B970DFBE40698AF1638FE38BD3DF3B2F + +I=10 +PT=00400000000000000000000000000000 +CT=F95B59A44F391E14CF20B74BDC32FCFF + +I=11 +PT=00200000000000000000000000000000 +CT=720F74AE04A2A435B9A7256E49378F5B + +I=12 +PT=00100000000000000000000000000000 +CT=2A0445F61D36BFA7E277070730CF76DA + +I=13 +PT=00080000000000000000000000000000 +CT=8D0536B997AEFEC1D94011BAB6699A03 + +I=14 +PT=00040000000000000000000000000000 +CT=674F002E19F6ED47EFF319E51FAD4498 + +I=15 +PT=00020000000000000000000000000000 +CT=292C02C5CB9163C80AC0F6CF1DD8E92D + +I=16 +PT=00010000000000000000000000000000 +CT=FA321CF18EF5FE727DD82A5C1E945141 + +I=17 +PT=00008000000000000000000000000000 +CT=A5A7AFE1034C39CCCEBE3C584BC0BE05 + +I=18 +PT=00004000000000000000000000000000 +CT=4FF5A52E697E77D081205DBDB21CEA39 + +I=19 +PT=00002000000000000000000000000000 +CT=209E88DC94C9003000CE0769AF7B7166 + +I=20 +PT=00001000000000000000000000000000 +CT=5DEE41AF864CB4B650E5F51551824D38 + +I=21 +PT=00000800000000000000000000000000 +CT=A79A63FA7E4503AE6D6E09F5F9053030 + +I=22 +PT=00000400000000000000000000000000 +CT=A48316749FAE7FAC7002031A6AFD8BA7 + +I=23 +PT=00000200000000000000000000000000 +CT=D6EEE8A7357A0E1D64262CA9C337AC42 + +I=24 +PT=00000100000000000000000000000000 +CT=B013CA8A62A858053E9FB667ED39829E + +I=25 +PT=00000080000000000000000000000000 +CT=DF6EA9E4538A45A52D5C1A43C88F4B55 + +I=26 +PT=00000040000000000000000000000000 +CT=7D03BA451371591D3FD5547D9165C73B + +I=27 +PT=00000020000000000000000000000000 +CT=0E0426281A6277E186499D365D5F49FF + +I=28 +PT=00000010000000000000000000000000 +CT=DBC02169DD2059E6CC4C57C1FEDF5AB4 + +I=29 +PT=00000008000000000000000000000000 +CT=826590E05D167DA6F00DCC75E22788EB + +I=30 +PT=00000004000000000000000000000000 +CT=34A73F21A04421D9786335FAAB49423A + +I=31 +PT=00000002000000000000000000000000 +CT=ED347D0E0128EE1A7392A1D36AB78AA9 + +I=32 +PT=00000001000000000000000000000000 +CT=EE944B2FE6E9FC888042608DA9615F75 + +I=33 +PT=00000000800000000000000000000000 +CT=9E7C85A909EF7218BA7947CFB4718F46 + +I=34 +PT=00000000400000000000000000000000 +CT=811AE07A0B2B1F816587FA73699AE77D + +I=35 +PT=00000000200000000000000000000000 +CT=68466FBF43C2FE13D4B18F7EC5EA745F + +I=36 +PT=00000000100000000000000000000000 +CT=D20B015C7191B219780956E6101F9354 + +I=37 +PT=00000000080000000000000000000000 +CT=5939D5C1BBF54EE1B3E326D757BDDE25 + +I=38 +PT=00000000040000000000000000000000 +CT=B1FDAFE9A0240E8FFEA19CE94B5105D3 + +I=39 +PT=00000000020000000000000000000000 +CT=D62962ECE02CDD68C06BDFEFB2F9495B + +I=40 +PT=00000000010000000000000000000000 +CT=B3BB2DE6F3C26587BA8BAC4F7AD9499A + +I=41 +PT=00000000008000000000000000000000 +CT=E0B1072D6D9FF703D6FBEF77852B0A6B + +I=42 +PT=00000000004000000000000000000000 +CT=D8DD51C907F478DE0228E83E61FD1758 + +I=43 +PT=00000000002000000000000000000000 +CT=A42DFFE6E7C1671C06A25236FDD10017 + +I=44 +PT=00000000001000000000000000000000 +CT=25ACF141550BFAB9EF451B6C6A5B2163 + +I=45 +PT=00000000000800000000000000000000 +CT=4DA7FCA3949B16E821DBC84F19581018 + +I=46 +PT=00000000000400000000000000000000 +CT=7D49B6347CBCC8919C7FA96A37A7A215 + +I=47 +PT=00000000000200000000000000000000 +CT=900024B29A08C6721B95BA3B753DDB4D + +I=48 +PT=00000000000100000000000000000000 +CT=6D2182FB283B6934D90BA7848CAB5E66 + +I=49 +PT=00000000000080000000000000000000 +CT=F73EF01B448D23A4D90DE8B2F9666E7A + +I=50 +PT=00000000000040000000000000000000 +CT=4AD9CDA2418643E9A3D926AF5E6B0412 + +I=51 +PT=00000000000020000000000000000000 +CT=7CAEC8E7E5953997D545B033201C8C5B + +I=52 +PT=00000000000010000000000000000000 +CT=3C43CA1F6B6864503E27B48D88230CF5 + +I=53 +PT=00000000000008000000000000000000 +CT=44F779B93108FE9FEEC880D79BA74488 + +I=54 +PT=00000000000004000000000000000000 +CT=9E50E8D9CFD3A682A78E527C9072A1CF + +I=55 +PT=00000000000002000000000000000000 +CT=68D000CBC838BBE3C505D6F814C01F28 + +I=56 +PT=00000000000001000000000000000000 +CT=2CB2A9FEC1ACD1D9B0FA05205E304F57 + +I=57 +PT=00000000000000800000000000000000 +CT=01EB2806606E46444520A5CC6180CD4B + +I=58 +PT=00000000000000400000000000000000 +CT=DAA9B25168CC702326F217F1A0C0B162 + +I=59 +PT=00000000000000200000000000000000 +CT=3E07E648975D9578D03555B1755807ED + +I=60 +PT=00000000000000100000000000000000 +CT=0B45F52E802C8B8DE09579425B80B711 + +I=61 +PT=00000000000000080000000000000000 +CT=659595DA0B68F6DF0DD6CA77202986E1 + +I=62 +PT=00000000000000040000000000000000 +CT=05FF42873893536E58C8FA98A45C73C4 + +I=63 +PT=00000000000000020000000000000000 +CT=B5B03421DE8BBFFC4EADEC767339A9BD + +I=64 +PT=00000000000000010000000000000000 +CT=788BCD111ECF73D4E78D2E21BEF55460 + +I=65 +PT=00000000000000008000000000000000 +CT=909CD9EC6790359F982DC6F2393D5315 + +I=66 +PT=00000000000000004000000000000000 +CT=332950F361535FF24EFAC8C76293F12C + +I=67 +PT=00000000000000002000000000000000 +CT=A68CCD4E330FFDA9D576DA436DB53D75 + +I=68 +PT=00000000000000001000000000000000 +CT=27C8A1CCFDB0B015D1ED5B3E77143791 + +I=69 +PT=00000000000000000800000000000000 +CT=D76A4B95887A77DF610DD3E1D3B20325 + +I=70 +PT=00000000000000000400000000000000 +CT=C068AB0DE71C66DAE83C361EF4B2D989 + +I=71 +PT=00000000000000000200000000000000 +CT=C2120BCD49EDA9A288B3B4BE79AC8158 + +I=72 +PT=00000000000000000100000000000000 +CT=0C546F62BF2773CD0F564FCECA7BA688 + +I=73 +PT=00000000000000000080000000000000 +CT=18F3462BEDE4920213CCB66DAB1640AA + +I=74 +PT=00000000000000000040000000000000 +CT=FE42F245EDD0E24B216AEBD8B392D690 + +I=75 +PT=00000000000000000020000000000000 +CT=3D3EEBC8D3D1558A194C2D00C337FF2B + +I=76 +PT=00000000000000000010000000000000 +CT=29AAEDF043E785DB42836F79BE6CBA28 + +I=77 +PT=00000000000000000008000000000000 +CT=215F90C6744E2944358E78619159A611 + +I=78 +PT=00000000000000000004000000000000 +CT=8606B1AA9E1D548E5442B06551E2C6DC + +I=79 +PT=00000000000000000002000000000000 +CT=987BB4B8740EC0EDE7FEA97DF033B5B1 + +I=80 +PT=00000000000000000001000000000000 +CT=C0A3500DA5B0AE07D2F450930BEEDF1B + +I=81 +PT=00000000000000000000800000000000 +CT=525FDF8312FE8F32C781481A8DAAAE37 + +I=82 +PT=00000000000000000000400000000000 +CT=BFD2C56AE5FB9C9DE33A6944572A6487 + +I=83 +PT=00000000000000000000200000000000 +CT=7975A57A425CDF5AA1FA929101F650B0 + +I=84 +PT=00000000000000000000100000000000 +CT=BF174BC49609A8709B2CD8366DAA79FE + +I=85 +PT=00000000000000000000080000000000 +CT=06C50C43222F56C874B1704E9F44BF7D + +I=86 +PT=00000000000000000000040000000000 +CT=0CEC48CD34043EA29CA3B8ED5278721E + +I=87 +PT=00000000000000000000020000000000 +CT=9548EA34A1560197B304D0ACB8A1698D + +I=88 +PT=00000000000000000000010000000000 +CT=22F9E9B1BD73B6B5B7D3062C986272F3 + +I=89 +PT=00000000000000000000008000000000 +CT=FEE8E934BD0873295059002230E298D4 + +I=90 +PT=00000000000000000000004000000000 +CT=1B08E2E3EB820D139CB4ABBDBE81D00D + +I=91 +PT=00000000000000000000002000000000 +CT=0021177681E4D90CEAF69DCED0145125 + +I=92 +PT=00000000000000000000001000000000 +CT=4A8E314452CA8A8A3619FC54BC423643 + +I=93 +PT=00000000000000000000000800000000 +CT=65047474F7222C94C6965425FF1BFD0A + +I=94 +PT=00000000000000000000000400000000 +CT=E123F551A9C4A8489622B16F961A9AA4 + +I=95 +PT=00000000000000000000000200000000 +CT=EF05530948B80915028BB2B6FE429380 + +I=96 +PT=00000000000000000000000100000000 +CT=72535B7FE0F0F777CEDCD55CD77E2DDF + +I=97 +PT=00000000000000000000000080000000 +CT=3423D8EFC31FA2F4C365C77D8F3B5C63 + +I=98 +PT=00000000000000000000000040000000 +CT=DE0E51C264663F3C5DBC59580A98D8E4 + +I=99 +PT=00000000000000000000000020000000 +CT=B2D9391166680947AB09264156719679 + +I=100 +PT=00000000000000000000000010000000 +CT=10DB79F23B06D263835C424AF749ADB7 + +I=101 +PT=00000000000000000000000008000000 +CT=DDF72D27E6B01EC107EA3E005B59563B + +I=102 +PT=00000000000000000000000004000000 +CT=8266B57485A5954A4236751DE07F6694 + +I=103 +PT=00000000000000000000000002000000 +CT=669A501E1F1ADE6E5523DE01D6DBC987 + +I=104 +PT=00000000000000000000000001000000 +CT=C20C48F2989725D461D1DB589DC0896E + +I=105 +PT=00000000000000000000000000800000 +CT=DE35158E7810ED1191825D2AA98FA97D + +I=106 +PT=00000000000000000000000000400000 +CT=4FE294F2C0F34D0671B693A237EBDDC8 + +I=107 +PT=00000000000000000000000000200000 +CT=087AE74B10CCBFDF6739FEB9559C01A4 + +I=108 +PT=00000000000000000000000000100000 +CT=5DC278970B7DEF77A5536C77AB59C207 + +I=109 +PT=00000000000000000000000000080000 +CT=7607F078C77085184EAA9B060C1FBFFF + +I=110 +PT=00000000000000000000000000040000 +CT=9DB841531BCBE7998DAD19993FB3CC00 + +I=111 +PT=00000000000000000000000000020000 +CT=D6A089B654854A94560BAE13298835B8 + +I=112 +PT=00000000000000000000000000010000 +CT=E1E223C4CF90CC5D195B370D65114622 + +I=113 +PT=00000000000000000000000000008000 +CT=1CBED73C50D053BDAD372CEEE54836A1 + +I=114 +PT=00000000000000000000000000004000 +CT=D309E69376D257ADF2BFDA152B26555F + +I=115 +PT=00000000000000000000000000002000 +CT=740F7649117F0DEE6EAA7789A9994C36 + +I=116 +PT=00000000000000000000000000001000 +CT=76AE64417C297184D668C5FD908B3CE5 + +I=117 +PT=00000000000000000000000000000800 +CT=6095FEA4AA8035591F1787A819C48787 + +I=118 +PT=00000000000000000000000000000400 +CT=D1FF4E7ACD1C79967FEBAB0F7465D450 + +I=119 +PT=00000000000000000000000000000200 +CT=5F5AD3C42B9489557BB63BF49ECF5F8A + +I=120 +PT=00000000000000000000000000000100 +CT=FB56CC09B680B1D07C5A52149E29F07C + +I=121 +PT=00000000000000000000000000000080 +CT=FF49B8DF4A97CBE03833E66197620DAD + +I=122 +PT=00000000000000000000000000000040 +CT=5E070ADE533D2E090ED0F5BE13BC0983 + +I=123 +PT=00000000000000000000000000000020 +CT=3AB4FB1D2B7BA376590A2C241D1F508D + +I=124 +PT=00000000000000000000000000000010 +CT=58B2431BC0BEDE02550F40238969EC78 + +I=125 +PT=00000000000000000000000000000008 +CT=0253786E126504F0DAB90C48A30321DE + +I=126 +PT=00000000000000000000000000000004 +CT=200211214E7394DA2089B6ACD093ABE0 + +I=127 +PT=00000000000000000000000000000002 +CT=0388DACE60B6A392F328C2B971B2FE78 + +I=128 +PT=00000000000000000000000000000001 +CT=58E2FCCEFA7E3061367F1D57A4E7455A + +========== + +KEYSIZE=256 + +KEY=0000000000000000000000000000000000000000000000000000000000000000 + +I=1 +PT=80000000000000000000000000000000 +CT=DDC6BF790C15760D8D9AEB6F9A75FD4E + +I=2 +PT=40000000000000000000000000000000 +CT=C7098C217C334D0C9BDF37EA13B0822C + +I=3 +PT=20000000000000000000000000000000 +CT=60F0FB0D4C56A8D4EEFEC5264204042D + +I=4 +PT=10000000000000000000000000000000 +CT=73376FBBF654D0686E0E84001477106B + +I=5 +PT=08000000000000000000000000000000 +CT=2F443B52BA5F0C6EA0602C7C4FD259B6 + +I=6 +PT=04000000000000000000000000000000 +CT=75D11B0E3A68C4223D88DBF017977DD7 + +I=7 +PT=02000000000000000000000000000000 +CT=779B38D15BFFB63D8D609D551A5CC98E + +I=8 +PT=01000000000000000000000000000000 +CT=5275F3D86B4FB8684593133EBFA53CD3 + +I=9 +PT=00800000000000000000000000000000 +CT=1CEF2074B336CEC62F12DEA2F6AB1481 + +I=10 +PT=00400000000000000000000000000000 +CT=1AEF5ABBAD9D7160874578DCD8BAE172 + +I=11 +PT=00200000000000000000000000000000 +CT=46C525DB17E72F26BF03216846B6F609 + +I=12 +PT=00100000000000000000000000000000 +CT=E24411F941BBE08788781E3EC52CBAA4 + +I=13 +PT=00080000000000000000000000000000 +CT=83A3DEDD1DD27018F6A6477E40527581 + +I=14 +PT=00040000000000000000000000000000 +CT=B68F8A2CDBAB0C923C67FC8F0F1087DE + +I=15 +PT=00020000000000000000000000000000 +CT=649944A70C32BF87A7409E7AE128FDE8 + +I=16 +PT=00010000000000000000000000000000 +CT=2846526D67387539C89314DE9E0C2D02 + +I=17 +PT=00008000000000000000000000000000 +CT=A9A0B8402E53C70DD1688054BA58DDFD + +I=18 +PT=00004000000000000000000000000000 +CT=4A72E6E1B79C83AC4BE3EBA5699EED48 + +I=19 +PT=00002000000000000000000000000000 +CT=B0E36B867BA4FF2B77D0614B0E364E4C + +I=20 +PT=00001000000000000000000000000000 +CT=49B57DE141F6418E3090F24DDD4014B6 + +I=21 +PT=00000800000000000000000000000000 +CT=A6C0D5B9797258E1987AC5F6CD20146D + +I=22 +PT=00000400000000000000000000000000 +CT=426CF4BDCAA369175965D26E7C71EEA2 + +I=23 +PT=00000200000000000000000000000000 +CT=E27F484CE54BC99BC1A52BDA3B518A26 + +I=24 +PT=00000100000000000000000000000000 +CT=D16D186284C7E6EE64B8104E0EF20BA5 + +I=25 +PT=00000080000000000000000000000000 +CT=6431F8538AD54E1E044A9F71F8EF556B + +I=26 +PT=00000040000000000000000000000000 +CT=ECD57CEB451D27EB96C55B2042257E8E + +I=27 +PT=00000020000000000000000000000000 +CT=4F0F188DC911B1954AFBC734C9F68872 + +I=28 +PT=00000010000000000000000000000000 +CT=B54DEF0337626B65614E81EDFDE620F3 + +I=29 +PT=00000008000000000000000000000000 +CT=6655D8074CAE0B90B0D3A3FE72D4D9DB + +I=30 +PT=00000004000000000000000000000000 +CT=C6B74B6B9EB4FC0C9A237DB1B616D09A + +I=31 +PT=00000002000000000000000000000000 +CT=D7B5D076EA56EC2B20791D7AD51CCF8F + +I=32 +PT=00000001000000000000000000000000 +CT=FE160C224BF003CE3BDDC90CB52ED22C + +I=33 +PT=00000000800000000000000000000000 +CT=5E00DA9BA94B5EC0D258D8A8002E0F6A + +I=34 +PT=00000000400000000000000000000000 +CT=09AC6DCFF4DACFF1651E2BA212A292A3 + +I=35 +PT=00000000200000000000000000000000 +CT=B283617E318D99AF83A05D9810BA89F7 + +I=36 +PT=00000000100000000000000000000000 +CT=0B5F70CCB40B0EF2538AE9B4A9770B35 + +I=37 +PT=00000000080000000000000000000000 +CT=43282BF180248FB517839B37F4DDAAE4 + +I=38 +PT=00000000040000000000000000000000 +CT=DDBD534C8B2E6D30A268F88C55AD765B + +I=39 +PT=00000000020000000000000000000000 +CT=A41A164E50EC2D9F175E752B755E0B5C + +I=40 +PT=00000000010000000000000000000000 +CT=37BFF99FF2F7AA97779E4ADF6F13FB10 + +I=41 +PT=00000000008000000000000000000000 +CT=9BA4F7BD298152903A683C4CEC669216 + +I=42 +PT=00000000004000000000000000000000 +CT=5FB750C7CE10DE7B4504248914D0DA06 + +I=43 +PT=00000000002000000000000000000000 +CT=3E748BFA108E086F51D56EC74A9E0FB9 + +I=44 +PT=00000000001000000000000000000000 +CT=31D4E56B99F5B73C1B8437DF332AFB98 + +I=45 +PT=00000000000800000000000000000000 +CT=9DC6717B84FC55D266E7B1D9B5C52A5F + +I=46 +PT=00000000000400000000000000000000 +CT=8EF8BA007F23C0A50FC120E07041BCCD + +I=47 +PT=00000000000200000000000000000000 +CT=C58F38E1839FC1918A12B8C9E88C66B6 + +I=48 +PT=00000000000100000000000000000000 +CT=B695D72A3FCF508C4050E12E40061C2D + +I=49 +PT=00000000000080000000000000000000 +CT=5D2736AD478A50583BC8C11BEFF16D7A + +I=50 +PT=00000000000040000000000000000000 +CT=DF0EACA8F17847AD41F9578F14C7B56B + +I=51 +PT=00000000000020000000000000000000 +CT=E5AA14AD48AD0A3C47CC35D5F8020E51 + +I=52 +PT=00000000000010000000000000000000 +CT=11BE6C8F58EBD8CEF1A53F591A68E8CE + +I=53 +PT=00000000000008000000000000000000 +CT=ECFE7BAFCBF42C1FEE015488770B3053 + +I=54 +PT=00000000000004000000000000000000 +CT=E552649F8D8EC4A1E1CD6DF50B6E6777 + +I=55 +PT=00000000000002000000000000000000 +CT=521C0629DE93B9119CDB1DDC5809DDEA + +I=56 +PT=00000000000001000000000000000000 +CT=CB38A62A0BAB1784156BA038CBA99BF6 + +I=57 +PT=00000000000000800000000000000000 +CT=76CCEE8AAACD394DE1EEF3DDA10CB54B + +I=58 +PT=00000000000000400000000000000000 +CT=6AFF910FA1D5673140E2DB59B8416049 + +I=59 +PT=00000000000000200000000000000000 +CT=064A12C0EF73FB386801BF4F35F3120D + +I=60 +PT=00000000000000100000000000000000 +CT=2240E374929D5B1BB8FF0FFDDDF640EC + +I=61 +PT=00000000000000080000000000000000 +CT=D4BA15C904C7692185DE85C02052E180 + +I=62 +PT=00000000000000040000000000000000 +CT=1714A315AB0166728A44CD91D4AE9018 + +I=63 +PT=00000000000000020000000000000000 +CT=6C970BDD9F0E222722EA31A1D12DD0AD + +I=64 +PT=00000000000000010000000000000000 +CT=F5956EDF02BD36A401BBB6CE77C3D3FB + +I=65 +PT=00000000000000008000000000000000 +CT=0CA11F122CCD7C259DC597EED3DF9BC4 + +I=66 +PT=00000000000000004000000000000000 +CT=50109AB4912AD2560B206F331B62EB6C + +I=67 +PT=00000000000000002000000000000000 +CT=DBE7C91A4175614889A2D4BEFD64845E + +I=68 +PT=00000000000000001000000000000000 +CT=0D3322853A571A6B46B79C0228E0DD25 + +I=69 +PT=00000000000000000800000000000000 +CT=96E4EE0BB9A11C6FB8522F285BADDEB6 + +I=70 +PT=00000000000000000400000000000000 +CT=96705C52D2CFCE82E630C93477C79C49 + +I=71 +PT=00000000000000000200000000000000 +CT=C50130AED6A126149D71F3888C83C232 + +I=72 +PT=00000000000000000100000000000000 +CT=4816EFE3DEB380566EBA0C17BF582090 + +I=73 +PT=00000000000000000080000000000000 +CT=0390857B4C8C98E4CF7A2B6F3394C507 + +I=74 +PT=00000000000000000040000000000000 +CT=422E73A02025EBE8B8B5D6E0FA24FCB2 + +I=75 +PT=00000000000000000020000000000000 +CT=3271AA7F4BF1D7C38050A43076D4FF76 + +I=76 +PT=00000000000000000010000000000000 +CT=D2074946F0D37B8975607BFC2E70234C + +I=77 +PT=00000000000000000008000000000000 +CT=1A509194C1270AB92E5A42D3A9F8D98B + +I=78 +PT=00000000000000000004000000000000 +CT=512438946360CCC4A5C6D73F6EED7130 + +I=79 +PT=00000000000000000002000000000000 +CT=98CFCDEC46EBEA1A286B3004F2746A0D + +I=80 +PT=00000000000000000001000000000000 +CT=A1CF369949677A3AF3D58E3EABF2741B + +I=81 +PT=00000000000000000000800000000000 +CT=D84C2E1A0E4A52166FA8FF6889D1E5E2 + +I=82 +PT=00000000000000000000400000000000 +CT=4AD91CCEEF60119B5078FD162D2735DE + +I=83 +PT=00000000000000000000200000000000 +CT=2860793D818E97AAFF1D339D7702438D + +I=84 +PT=00000000000000000000100000000000 +CT=6F9068BE73364AE250D89D78A6C9CE6F + +I=85 +PT=00000000000000000000080000000000 +CT=024FC3FEF4883FEB1A8DD005305FECCE + +I=86 +PT=00000000000000000000040000000000 +CT=08A61FE0816D75EA15EB3C9FB9CCDED6 + +I=87 +PT=00000000000000000000020000000000 +CT=449C86DFA13F260175CE39797686FFA4 + +I=88 +PT=00000000000000000000010000000000 +CT=4FFFFC29A59858E1133F2BFB1A8A4817 + +I=89 +PT=00000000000000000000008000000000 +CT=19425D1F6480B25096561295697DC2B7 + +I=90 +PT=00000000000000000000004000000000 +CT=31974727ECDD2C77C3A428FC3A8CB3FC + +I=91 +PT=00000000000000000000002000000000 +CT=A57CD704B3C95E744D08DF443458F2F5 + +I=92 +PT=00000000000000000000001000000000 +CT=486D8C193DB1ED73ACB17990442FC40B + +I=93 +PT=00000000000000000000000800000000 +CT=5E4DBF4E83AB3BC055B9FCC7A6B3A763 + +I=94 +PT=00000000000000000000000400000000 +CT=ACF2E0A693FBBCBA4D41B861E0D89E37 + +I=95 +PT=00000000000000000000000200000000 +CT=32A7CB2AE066A51D2B78FC4B4CFCB608 + +I=96 +PT=00000000000000000000000100000000 +CT=677D494DBB73CAF55C1990158DA12F14 + +I=97 +PT=00000000000000000000000080000000 +CT=082A0D2367512ADF0D75A151BFBE0A17 + +I=98 +PT=00000000000000000000000040000000 +CT=5E5BB7337923C482CE8CBA249E6A8C7D + +I=99 +PT=00000000000000000000000020000000 +CT=D3001BA7C7026EE3E5003179530AFCFC + +I=100 +PT=00000000000000000000000010000000 +CT=46EC44F8931E629FE8FD8961312EDDE1 + +I=101 +PT=00000000000000000000000008000000 +CT=C5F8ECD79C7B30E81D17E32079969310 + +I=102 +PT=00000000000000000000000004000000 +CT=5B8AD6919E24CAEBCC55401AEE0C9802 + +I=103 +PT=00000000000000000000000002000000 +CT=C2302B7E701B5CC7F8B29E3516DBBFA6 + +I=104 +PT=00000000000000000000000001000000 +CT=A1D04D6A76F9F7A94D49FAA64A87F244 + +I=105 +PT=00000000000000000000000000800000 +CT=7FB6F92D35B5CB6C631600EDB9E860BA + +I=106 +PT=00000000000000000000000000400000 +CT=B2EF7078BCFACE07AEEC3F9B48830EB3 + +I=107 +PT=00000000000000000000000000200000 +CT=F475A7493D24C7036E53390374C378B3 + +I=108 +PT=00000000000000000000000000100000 +CT=B36802AC987377A37BD8EADC97C57D60 + +I=109 +PT=00000000000000000000000000080000 +CT=ADDCD3D19689C4DDC738CE5F69DC9505 + +I=110 +PT=00000000000000000000000000040000 +CT=0DAF8CA22884915403C0F0BB1F4BD74F + +I=111 +PT=00000000000000000000000000020000 +CT=4AF36BAE2660503B3248E4685059FD05 + +I=112 +PT=00000000000000000000000000010000 +CT=7D5631814DD8E917D97A0D514C743971 + +I=113 +PT=00000000000000000000000000008000 +CT=BC3352500FC0CBB9DB5B5F6B491C1BE8 + +I=114 +PT=00000000000000000000000000004000 +CT=6A4A30BA87E87AF65C90AEB7AFEDC76B + +I=115 +PT=00000000000000000000000000002000 +CT=77E6125897668AC8E73E8C79A6FF8336 + +I=116 +PT=00000000000000000000000000001000 +CT=3FA9D39104EBB323C7AAAA248960DD1E + +I=117 +PT=00000000000000000000000000000800 +CT=FAD75AD76AB10ADC49036B250E229D39 + +I=118 +PT=00000000000000000000000000000400 +CT=2FACAA5FE35B228A16AC74088D702EC4 + +I=119 +PT=00000000000000000000000000000200 +CT=88B6CBCFDFEF8AD91720A1BB69A1F33E + +I=120 +PT=00000000000000000000000000000100 +CT=C7E9D250998632D444356242EF04058D + +I=121 +PT=00000000000000000000000000000080 +CT=B14DAD8D3D9153F46C0D3A1AD63C7A05 + +I=122 +PT=00000000000000000000000000000040 +CT=60ABA678A506608D0845966D29B5F790 + +I=123 +PT=00000000000000000000000000000020 +CT=482DC43F2388EF25D24144E144BD834E + +I=124 +PT=00000000000000000000000000000010 +CT=1490A05A7CEE43BDE98B56E309DC0126 + +I=125 +PT=00000000000000000000000000000008 +CT=ABFA77CD6E85DA245FB0BDC5E52CFC29 + +I=126 +PT=00000000000000000000000000000004 +CT=DD4AB1284D4AE17B41E85924470C36F7 + +I=127 +PT=00000000000000000000000000000002 +CT=CEA7403D4D606B6E074EC5D3BAF39D18 + +I=128 +PT=00000000000000000000000000000001 +CT=530F8AFBC74536B9A963B4F1C4CB738B + +========== diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.c new file mode 100644 index 00000000..67c9dcde --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.c @@ -0,0 +1,98 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_cf2.c */ +/* + * Copyright (C) 2004, 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This file contains tests for the KRB-FX-CF2 code in Kerberos, based on the + * PRF regression tests. It reads an input file, and writes an output file. + * It is assumed that the output file will be diffed against expected output to + * see whether regression tests pass. The input file is a very primitive + * format. + * + * Line 1: enctype + * Line 2: key to pass to string2key; also used as salt + * Line 3: second key to pass to string2key + * Line 4: pepper1 + * Line 5: pepper2 + * + * scanf is used to read the file, so interior spaces are not permitted. The + * program outputs the hex bytes of the key. + */ +#include + +#include +#include +#include + +int main () { + krb5_error_code ret; + char pepper1[1025], pepper2[1025]; + krb5_keyblock *k1 = NULL, *k2 = NULL, *out = NULL; + krb5_data s2k; + unsigned int i; + while (1) { + krb5_enctype enctype; + char s[1025]; + + if (scanf( "%d", &enctype) == EOF) + break; + if (scanf("%1024s", &s[0]) == EOF) + break; + ret = krb5_init_keyblock(0, enctype, 0, &k1); + assert(!ret); + s2k.data = &s[0]; + s2k.length = strlen(s); + ret = krb5_c_string_to_key (0, enctype, &s2k, &s2k, k1); + assert(!ret); + if (scanf("%1024s", &s[0]) == EOF) + break; + ret = krb5_init_keyblock(0, enctype, 0, &k2); + assert(!ret); + s2k.data = &s[0]; + s2k.length = strlen(s); + ret = krb5_c_string_to_key (0, enctype, &s2k, &s2k, k2); + assert(!ret); + if (scanf("%1024s %1024s", pepper1, pepper2) == EOF) + break; + ret = krb5_c_fx_cf2_simple(0, k1, pepper1, k2, pepper2, &out); + assert(!ret); + i = out->length; + for (; i > 0; i--) { + printf ("%02x", + (unsigned int) ((unsigned char) out->contents[out->length-i])); + } + printf ("\n"); + + krb5_free_keyblock(0,out); + out = NULL; + + krb5_free_keyblock(0, k1); + k1 = NULL; + krb5_free_keyblock(0, k2); + k2 = NULL; + } + + return (0); +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.comments b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.comments new file mode 100644 index 00000000..0643b650 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.comments @@ -0,0 +1,6 @@ +The first test mirrors the first two tests in t_prf.in. + +The second test mirrors the following four tests in t_prf.in. + +The third and fourth tests are simple tests of the DES and 3DES PRF. +The fifth test is the same simple test for RC4. diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.expected b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.expected new file mode 100644 index 00000000..f8251a16 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.expected @@ -0,0 +1,6 @@ +97df97e4b798b29eb31ed7280287a92a +4d6ca4e629785c1f01baf55e2e548566b9617ae3a96868c337cb93b5e72b1c7b +e58f9eb643862c13ad38e529313462a7f73e62834fe54a01 +24d7f6b6bae4e5c00d2082c5ebab3672 +edd02a39d2dbde31611c16e610be062c +67f6ea530aea85a37dcbb23349ea52dcc61ca8493ff557252327fd8304341584 diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.in b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.in new file mode 100644 index 00000000..73e2f8fb --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cf2.in @@ -0,0 +1,30 @@ +17 +key1 +key2 +a +b +18 +key1 +key2 +a +b +16 +key1 +key2 +a +b +23 +key1 +key2 +a +b +19 +key1 +key2 +a +b +20 +key1 +key2 +a +b diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cksums.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cksums.c new file mode 100644 index 00000000..557340ec --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cksums.c @@ -0,0 +1,260 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_cksums.c - Test known checksum results */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This harness tests checksum results against known values. With the -v flag, + * results for all tests are displayed. This harness only works for + * deterministic checksums. + */ + +#include "k5-int.h" + +struct test { + krb5_data plaintext; + krb5_cksumtype sumtype; + krb5_enctype enctype; + krb5_keyusage usage; + krb5_data keybits; + krb5_data cksum; +} test_cases[] = { + { + { KV5M_DATA, 3, "one" }, + CKSUMTYPE_RSA_MD4, 0, 0, { KV5M_DATA, 0, "" }, + { KV5M_DATA, 16, + "\x30\x5D\xCC\x2C\x0F\xDD\x53\x39\x96\x95\x52\xC7\xB8\x99\x63\x48" } + }, + { + { KV5M_DATA, 19, "two three four five" }, + CKSUMTYPE_RSA_MD5, 0, 0, { KV5M_DATA, 0, "" }, + { KV5M_DATA, 16, + "\xBA\xB5\x32\x15\x51\xE1\x08\x44\x90\x86\x96\x35\xB3\xC2\x68\x15" } + }, + { + { KV5M_DATA, 0, "" }, + CKSUMTYPE_SHA1, 0, 0, { KV5M_DATA, 0, "" }, + { KV5M_DATA, 20, + "\xDA\x39\xA3\xEE\x5E\x6B\x4B\x0D\x32\x55\xBF\xEF\x95\x60\x18\x90" + "\xAF\xD8\x07\x09" } + }, + { + { KV5M_DATA, 9, "six seven" }, + CKSUMTYPE_HMAC_SHA1_DES3, ENCTYPE_DES3_CBC_SHA1, 2, + { KV5M_DATA, 24, + "\x7A\x25\xDF\x89\x92\x29\x6D\xCE\xDA\x0E\x13\x5B\xC4\x04\x6E\x23" + "\x75\xB3\xC1\x4C\x98\xFB\xC1\x62" }, + { KV5M_DATA, 20, + "\x0E\xEF\xC9\xC3\xE0\x49\xAA\xBC\x1B\xA5\xC4\x01\x67\x7D\x9A\xB6" + "\x99\x08\x2B\xB4" } + }, + { + { KV5M_DATA, 37, "eight nine ten eleven twelve thirteen" }, + CKSUMTYPE_HMAC_SHA1_96_AES128, ENCTYPE_AES128_CTS_HMAC_SHA1_96, 3, + { KV5M_DATA, 16, + "\x90\x62\x43\x0C\x8C\xDA\x33\x88\x92\x2E\x6D\x6A\x50\x9F\x5B\x7A" }, + { KV5M_DATA, 12, + "\x01\xA4\xB0\x88\xD4\x56\x28\xF6\x94\x66\x14\xE3" } + }, + { + { KV5M_DATA, 8, "fourteen" }, + CKSUMTYPE_HMAC_SHA1_96_AES256, ENCTYPE_AES256_CTS_HMAC_SHA1_96, 4, + { KV5M_DATA, 32, + "\xB1\xAE\x4C\xD8\x46\x2A\xFF\x16\x77\x05\x3C\xC9\x27\x9A\xAC\x30" + "\xB7\x96\xFB\x81\xCE\x21\x47\x4D\xD3\xDD\xBC\xFE\xA4\xEC\x76\xD7" }, + { KV5M_DATA, 12, + "\xE0\x87\x39\xE3\x27\x9E\x29\x03\xEC\x8E\x38\x36" } + }, + { + { KV5M_DATA, 15, "fifteen sixteen" }, + CKSUMTYPE_MD5_HMAC_ARCFOUR, ENCTYPE_ARCFOUR_HMAC, 5, + { KV5M_DATA, 16, + "\xF7\xD3\xA1\x55\xAF\x5E\x23\x8A\x0B\x7A\x87\x1A\x96\xBA\x2A\xB2" }, + { KV5M_DATA, 16, + "\x9F\x41\xDF\x30\x49\x07\xDE\x73\x54\x47\x00\x1F\xD2\xA1\x97\xB9" } + }, + { + { KV5M_DATA, 34, "seventeen eighteen nineteen twenty" }, + CKSUMTYPE_HMAC_MD5_ARCFOUR, ENCTYPE_ARCFOUR_HMAC, 6, + { KV5M_DATA, 16, + "\xF7\xD3\xA1\x55\xAF\x5E\x23\x8A\x0B\x7A\x87\x1A\x96\xBA\x2A\xB2" }, + { KV5M_DATA, 16, + "\xEB\x38\xCC\x97\xE2\x23\x0F\x59\xDA\x41\x17\xDC\x58\x59\xD7\xEC" } + }, + { + { KV5M_DATA, 11, "abcdefghijk" }, + CKSUMTYPE_CMAC_CAMELLIA128, ENCTYPE_CAMELLIA128_CTS_CMAC, 7, + { KV5M_DATA, 16, + "\x1D\xC4\x6A\x8D\x76\x3F\x4F\x93\x74\x2B\xCB\xA3\x38\x75\x76\xC3" }, + { KV5M_DATA, 16, + "\x11\x78\xE6\xC5\xC4\x7A\x8C\x1A\xE0\xC4\xB9\xC7\xD4\xEB\x7B\x6B" } + }, + { + { KV5M_DATA, 26, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + CKSUMTYPE_CMAC_CAMELLIA128, ENCTYPE_CAMELLIA128_CTS_CMAC, 8, + { KV5M_DATA, 16, + "\x50\x27\xBC\x23\x1D\x0F\x3A\x9D\x23\x33\x3F\x1C\xA6\xFD\xBE\x7C" }, + { KV5M_DATA, 16, + "\xD1\xB3\x4F\x70\x04\xA7\x31\xF2\x3A\x0C\x00\xBF\x6C\x3F\x75\x3A" } + }, + { + { KV5M_DATA, 9, "123456789" }, + CKSUMTYPE_CMAC_CAMELLIA256, ENCTYPE_CAMELLIA256_CTS_CMAC, 9, + { KV5M_DATA, 32, + "\xB6\x1C\x86\xCC\x4E\x5D\x27\x57\x54\x5A\xD4\x23\x39\x9F\xB7\x03" + "\x1E\xCA\xB9\x13\xCB\xB9\x00\xBD\x7A\x3C\x6D\xD8\xBF\x92\x01\x5B" }, + { KV5M_DATA, 16, + "\x87\xA1\x2C\xFD\x2B\x96\x21\x48\x10\xF0\x1C\x82\x6E\x77\x44\xB1" } + }, + { + { KV5M_DATA, 30, "!@#$%^&*()!@#$%^&*()!@#$%^&*()" }, + CKSUMTYPE_CMAC_CAMELLIA256, ENCTYPE_CAMELLIA256_CTS_CMAC, 10, + { KV5M_DATA, 32, + "\x32\x16\x4C\x5B\x43\x4D\x1D\x15\x38\xE4\xCF\xD9\xBE\x80\x40\xFE" + "\x8C\x4A\xC7\xAC\xC4\xB9\x3D\x33\x14\xD2\x13\x36\x68\x14\x7A\x05" }, + { KV5M_DATA, 16, + "\x3F\xA0\xB4\x23\x55\xE5\x2B\x18\x91\x87\x29\x4A\xA2\x52\xAB\x64" } + }, + { + { KV5M_DATA, 21, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14" }, + CKSUMTYPE_HMAC_SHA256_128_AES128, ENCTYPE_AES128_CTS_HMAC_SHA256_128, + 2, + { KV5M_DATA, 16, + "\x37\x05\xD9\x60\x80\xC1\x77\x28\xA0\xE8\x00\xEA\xB6\xE0\xD2\x3C" }, + { KV5M_DATA, 16, + "\xD7\x83\x67\x18\x66\x43\xD6\x7B\x41\x1C\xBA\x91\x39\xFC\x1D\xEE" } + }, + { + { KV5M_DATA, 21, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14" }, + CKSUMTYPE_HMAC_SHA384_192_AES256, ENCTYPE_AES256_CTS_HMAC_SHA384_192, + 2, + { KV5M_DATA, 32, + "\x6D\x40\x4D\x37\xFA\xF7\x9F\x9D\xF0\xD3\x35\x68\xD3\x20\x66\x98" + "\x00\xEB\x48\x36\x47\x2E\xA8\xA0\x26\xD1\x6B\x71\x82\x46\x0C\x52" }, + { KV5M_DATA, 24, + "\x45\xEE\x79\x15\x67\xEE\xFC\xA3\x7F\x4A\xC1\xE0\x22\x2D\xE8\x0D" + "\x43\xC3\xBF\xA0\x66\x99\x67\x2A" } + }, +}; + +static void +printhex(const char *head, void *data, size_t len) +{ + size_t i; + + printf("%s", head); + for (i = 0; i < len; i++) { + printf("%02X", ((unsigned char*)data)[i]); + if (i % 16 == 15 && i + 1 < len) + printf("\n%*s", (int)strlen(head), ""); + else if (i + 1 < len) + printf(" "); + } + printf("\n"); +} + +int +main(int argc, char **argv) +{ + krb5_error_code ret; + krb5_context context = NULL; + size_t i; + struct test *test; + krb5_keyblock kb, *kbp; + krb5_checksum cksum; + krb5_cksumtype mtype; + krb5_boolean valid, verbose = FALSE; + int status = 0; + + if (argc >= 2 && strcmp(argv[1], "-v") == 0) + verbose = TRUE; + for (i = 0; i < sizeof(test_cases) / sizeof(*test_cases); i++) { + test = &test_cases[i]; + if (test->enctype != 0) { + kb.magic = KV5M_KEYBLOCK; + kb.enctype = test->enctype; + kb.length = test->keybits.length; + kb.contents = (unsigned char *)test->keybits.data; + kbp = &kb; + } else + kbp = NULL; + ret = krb5_c_make_checksum(context, test->sumtype, kbp, test->usage, + &test->plaintext, &cksum); + assert(!ret); + if (verbose) { + char buf[64]; + krb5_cksumtype_to_string(test->sumtype, buf, sizeof(buf)); + printf("\nTest %d:\n", (int)i); + printf("Plaintext: %.*s\n", (int)test->plaintext.length, + test->plaintext.data); + printf("Checksum type: %s\n", buf); + if (test->enctype != 0) { + krb5_enctype_to_name(test->enctype, FALSE, buf, sizeof(buf)); + printf("Enctype: %s\n", buf); + printhex("Key: ", test->keybits.data, test->keybits.length); + printf("Key usage: %d\n", (int)test->usage); + } + printhex("Checksum: ", cksum.contents, cksum.length); + } + if (test->cksum.length != cksum.length || + memcmp(test->cksum.data, cksum.contents, cksum.length) != 0) { + printf("derive test %d failed\n", (int)i); + status = 1; + if (!verbose) + break; + } + + /* Test that the checksum verifies successfully. */ + ret = krb5_c_verify_checksum(context, kbp, test->usage, + &test->plaintext, &cksum, &valid); + assert(!ret); + if (!valid) { + printf("test %d verify failed\n", (int)i); + status = 1; + if (!verbose) + break; + } + + if (kbp != NULL) { + ret = krb5int_c_mandatory_cksumtype(context, kbp->enctype, &mtype); + assert(!ret); + if (test->sumtype == mtype) { + /* Test that a checksum type of 0 uses the mandatory checksum + * type for the key. */ + cksum.checksum_type = 0; + ret = krb5_c_verify_checksum(context, kbp, test->usage, + &test->plaintext, &cksum, &valid); + assert(!ret && valid); + } + } + + krb5_free_checksum_contents(context, &cksum); + assert(cksum.length == 0); + } + return status; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cmac.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cmac.c new file mode 100644 index 00000000..565c35da --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cmac.c @@ -0,0 +1,147 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_cmac.c */ +/* + * Copyright 2010 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Test vectors for CMAC. Inputs are taken from RFC 4493 section 4. Outputs + * are changed for the use of Camellia-128 in place of AES-128. + * + * Ideally we would double-check subkey values, but we have no easy way to see + * them. + * + * Ideally we would test AES-CMAC against the expected results in RFC 4493, + * instead of Camellia-CMAC against results we generated ourselves. This has + * been done manually, but is not convenient to do automatically since the + * AES-128 enc provider has no cbc_mac method and therefore cannot be used with + * krb5int_cmac_checksum. + */ + +#include "crypto_int.h" + +/* All examples use the following Camellia-128 key. */ +static unsigned char keybytes[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; + +/* Example inputs are this message truncated to 0, 16, 40, and 64 bytes. */ +unsigned char input[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 +}; + +/* Expected result of CMAC on empty input. */ +static unsigned char cmac1[] = { + 0xba, 0x92, 0x57, 0x82, 0xaa, 0xa1, 0xf5, 0xd9, + 0xa0, 0x0f, 0x89, 0x64, 0x80, 0x94, 0xfc, 0x71 +}; + +/* Expected result of CMAC on first 16 bytes of input. */ +static unsigned char cmac2[] = { + 0x6d, 0x96, 0x28, 0x54, 0xa3, 0xb9, 0xfd, 0xa5, + 0x6d, 0x7d, 0x45, 0xa9, 0x5e, 0xe1, 0x79, 0x93 +}; + +/* Expected result of CMAC on first 40 bytes of input. */ +static unsigned char cmac3[] = { + 0x5c, 0x18, 0xd1, 0x19, 0xcc, 0xd6, 0x76, 0x61, + 0x44, 0xac, 0x18, 0x66, 0x13, 0x1d, 0x9f, 0x22 +}; + +/* Expected result of CMAC on all 64 bytes of input. */ +static unsigned char cmac4[] = { + 0xc2, 0x69, 0x9a, 0x6e, 0xba, 0x55, 0xce, 0x9d, + 0x93, 0x9a, 0x8a, 0x4e, 0x19, 0x46, 0x6e, 0xe9 +}; + +static void +check_result(const char *name, const unsigned char *result, + const unsigned char *expected) +{ + int i; + + for (i = 0; i < 16; i++) { + if (result[i] != expected[i]) { + fprintf(stderr, "CMAC test vector failure: %s\n", name); + exit(1); + } + } +} + +int +main(int argc, char **argv) +{ + krb5_error_code ret; + krb5_context context = NULL; + krb5_keyblock keyblock; + krb5_key key; + const struct krb5_enc_provider *enc = &krb5int_enc_camellia128; + krb5_crypto_iov iov; + unsigned char resultbuf[16]; + krb5_data result = make_data(resultbuf, 16); + + /* Create the example key. */ + keyblock.magic = KV5M_KEYBLOCK; + keyblock.enctype = ENCTYPE_CAMELLIA128_CTS_CMAC; + keyblock.length = 16; + keyblock.contents = keybytes; + ret = krb5_k_create_key(context, &keyblock, &key); + assert(!ret); + + /* Example 1. */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data(input, 0); + ret = krb5int_cmac_checksum(enc, key, &iov, 1, &result); + assert(!ret); + check_result("example 1", resultbuf, cmac1); + + /* Example 2. */ + iov.data.length = 16; + ret = krb5int_cmac_checksum(enc, key, &iov, 1, &result); + assert(!ret); + check_result("example 2", resultbuf, cmac2); + + /* Example 3. */ + iov.data.length = 40; + ret = krb5int_cmac_checksum(enc, key, &iov, 1, &result); + assert(!ret); + check_result("example 3", resultbuf, cmac3); + + /* Example 4. */ + iov.data.length = 64; + ret = krb5int_cmac_checksum(enc, key, &iov, 1, &result); + assert(!ret); + check_result("example 4", resultbuf, cmac4); + + printf("All CMAC tests passed.\n"); + krb5_k_free_key(context, key); + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cts.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cts.c new file mode 100644 index 00000000..fe505169 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_cts.c @@ -0,0 +1,151 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_cts.c */ +/* + * Copyright 2001, 2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * Test vectors for crypto code, matching data submitted for inclusion + * with RFC1510bis. + * + * N.B.: Doesn't compile -- this file uses some routines internal to our + * crypto library which are declared "static" and thus aren't accessible + * without modifying the other sources. + */ + +#include +#include +#include +#include +#include "crypto_int.h" + +#define ASIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0])) + +const char *whoami; + +#define JURISIC "Juri\305\241i\304\207" /* hi Miro */ +#define ESZETT "\303\237" +#define GCLEF "\360\235\204\236" /* outside BMP, woo hoo! */ + +static void printd (const char *descr, krb5_data *d) { + unsigned int i, j; + const int r = 16; + + printf("%s:", descr); + + for (i = 0; i < d->length; i += r) { + printf("\n %04x: ", i); + for (j = i; j < i + r && j < d->length; j++) + printf(" %02x", 0xff & d->data[j]); +#ifdef SHOW_TEXT + for (; j < i + r; j++) + printf(" "); + printf(" "); + for (j = i; j < i + r && j < d->length; j++) { + int c = 0xff & d->data[j]; + printf("%c", isprint(c) ? c : '.'); + } +#endif + } + printf("\n"); +} +static void printk(const char *descr, krb5_keyblock *k) { + krb5_data d; + d.data = (char *) k->contents; + d.length = k->length; + printd(descr, &d); +} + +static void test_cts() +{ + static const char input[4*16] = + "I would like the General Gau's Chicken, please, and wonton soup."; + static const unsigned char aeskey[16] = "chicken teriyaki"; + static const int lengths[] = { 17, 31, 32, 47, 48, 64 }; + + unsigned int i; + char outbuf[64], encivbuf[16], decivbuf[16]; + krb5_crypto_iov iov; + krb5_data in, enciv, deciv; + krb5_keyblock keyblock; + krb5_key key; + krb5_error_code err; + + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data.data = outbuf; + in.data = (char *)input; + enciv.length = deciv.length = 16; + enciv.data = encivbuf; + deciv.data = decivbuf; + keyblock.contents = (krb5_octet *)aeskey; + keyblock.length = 16; + keyblock.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96; + + err = krb5_k_create_key(NULL, &keyblock, &key); + if (err) { + printf("error %ld from krb5_k_create_key\n", (long)err); + exit(1); + } + + memset(enciv.data, 0, 16); + printk("AES 128-bit key", &keyblock); + for (i = 0; i < sizeof(lengths)/sizeof(lengths[0]); i++) { + memset(enciv.data, 0, 16); + memset(deciv.data, 0, 16); + + printf("\n"); + iov.data.length = in.length = lengths[i]; + memcpy(outbuf, input, lengths[i]); + printd("IV", &enciv); + err = krb5int_aes_encrypt(key, &enciv, &iov, 1); + if (err) { + printf("error %ld from krb5int_aes_encrypt\n", (long)err); + exit(1); + } + printd("Input", &in); + printd("Output", &iov.data); + printd("Next IV", &enciv); + err = krb5int_aes_decrypt(key, &deciv, &iov, 1); + if (err) { + printf("error %ld from krb5int_aes_decrypt\n", (long)err); + exit(1); + } + if (memcmp(outbuf, input, lengths[i]) != 0) { + printd("Decryption result DOESN'T MATCH", &iov.data); + exit(1); + } + if (memcmp(enciv.data, deciv.data, 16)) { + printd("Decryption IV result DOESN'T MATCH", &deciv); + exit(1); + } + } + krb5_k_free_key(NULL, key); +} + +int main (int argc, char **argv) +{ + whoami = argv[0]; + test_cts(); + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_decrypt.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_decrypt.c new file mode 100644 index 00000000..a40a8550 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_decrypt.c @@ -0,0 +1,623 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_decrypt.c - Test decrypting known ciphertexts */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This harness decrypts known ciphertexts to detect changes in encryption code + * which are self-compatible but not compatible across versions. With the -g + * flag, the program generates a set of test cases. + */ + +#include "k5-int.h" + +struct test { + krb5_enctype enctype; + krb5_data plaintext; + krb5_keyusage usage; + krb5_data keybits; + krb5_data ciphertext; +} test_cases[] = { + { + ENCTYPE_DES3_CBC_SHA1, + { KV5M_DATA, 0, "", }, 0, + { KV5M_DATA, 24, + "\x7A\x25\xDF\x89\x92\x29\x6D\xCE\xDA\x0E\x13\x5B\xC4\x04\x6E\x23" + "\x75\xB3\xC1\x4C\x98\xFB\xC1\x62" }, + { KV5M_DATA, 28, + "\x54\x8A\xF4\xD5\x04\xF7\xD7\x23\x30\x3F\x12\x17\x5F\xE8\x38\x6B" + "\x7B\x53\x35\xA9\x67\xBA\xD6\x1F\x3B\xF0\xB1\x43" } + }, + { + ENCTYPE_DES3_CBC_SHA1, + { KV5M_DATA, 1, "1", }, 1, + { KV5M_DATA, 24, + "\xBC\x07\x83\x89\x15\x13\xD5\xCE\x57\xBC\x13\x8F\xD3\xC1\x1A\xE6" + "\x40\x45\x23\x85\x32\x29\x62\xB6" }, + { KV5M_DATA, 36, + "\x9C\x3C\x1D\xBA\x47\x47\xD8\x5A\xF2\x91\x6E\x47\x45\xF2\xDC\xE3" + "\x80\x46\x79\x6E\x51\x04\xBC\xCD\xFB\x66\x9A\x91\xD4\x4B\xC3\x56" + "\x66\x09\x45\xC7" } + }, + { + ENCTYPE_DES3_CBC_SHA1, + { KV5M_DATA, 9, "9 bytesss", }, 2, + { KV5M_DATA, 24, + "\x2F\xD0\xF7\x25\xCE\x04\x10\x0D\x2F\xC8\xA1\x80\x98\x83\x1F\x85" + "\x0B\x45\xD9\xEF\x85\x0B\xD9\x20" }, + { KV5M_DATA, 44, + "\xCF\x91\x44\xEB\xC8\x69\x79\x81\x07\x5A\x8B\xAD\x8D\x74\xE5\xD7" + "\xD5\x91\xEB\x7D\x97\x70\xC7\xAD\xA2\x5E\xE8\xC5\xB3\xD6\x94\x44" + "\xDF\xEC\x79\xA5\xB7\xA0\x14\x82\xD9\xAF\x74\xE6" } + }, + { + ENCTYPE_DES3_CBC_SHA1, + { KV5M_DATA, 13, "13 bytes byte", }, 3, + { KV5M_DATA, 24, + "\x0D\xD5\x20\x94\xE0\xF4\x1C\xEC\xCB\x5B\xE5\x10\xA7\x64\xB3\x51" + "\x76\xE3\x98\x13\x32\xF1\xE5\x98" }, + { KV5M_DATA, 44, + "\x83\x9A\x17\x08\x1E\xCB\xAF\xBC\xDC\x91\xB8\x8C\x69\x55\xDD\x3C" + "\x45\x14\x02\x3C\xF1\x77\xB7\x7B\xF0\xD0\x17\x7A\x16\xF7\x05\xE8" + "\x49\xCB\x77\x81\xD7\x6A\x31\x6B\x19\x3F\x8D\x30" } + }, + { + ENCTYPE_DES3_CBC_SHA1, + { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4, + { KV5M_DATA, 24, + "\xF1\x16\x86\xCB\xBC\x9E\x23\xEA\x54\xFE\xCD\x2A\x3D\xCD\xFB\x20" + "\xB6\xFE\x98\xBF\x26\x45\xC4\xC4" }, + { KV5M_DATA, 60, + "\x89\x43\x3E\x83\xFD\x0E\xA3\x66\x6C\xFF\xCD\x18\xD8\xDE\xEB\xC5" + "\x3B\x9A\x34\xED\xBE\xB1\x59\xD9\xF6\x67\xC6\xC2\xB9\xA9\x64\x40" + "\x1D\x55\xE7\xE9\xC6\x8D\x64\x8D\x65\xC3\xAA\x84\xFF\xA3\x79\x0C" + "\x14\xA8\x64\xDA\x80\x73\xA9\xA9\x5C\x4B\xA2\xBC" } + }, + + { + ENCTYPE_ARCFOUR_HMAC, + { KV5M_DATA, 0, "", }, 0, + { KV5M_DATA, 16, + "\xF8\x1F\xEC\x39\x25\x5F\x57\x84\xE8\x50\xC4\x37\x7C\x88\xBD\x85" }, + { KV5M_DATA, 24, + "\x02\xC1\xEB\x15\x58\x61\x44\x12\x2E\xC7\x17\x76\x3D\xD3\x48\xBF" + "\x00\x43\x4D\xDC\x65\x85\x95\x4C" } + }, + { + ENCTYPE_ARCFOUR_HMAC, + { KV5M_DATA, 1, "1", }, 1, + { KV5M_DATA, 16, + "\x67\xD1\x30\x0D\x28\x12\x23\x86\x7F\x96\x47\xFF\x48\x72\x12\x73" }, + { KV5M_DATA, 25, + "\x61\x56\xE0\xCC\x04\xE0\xA0\x87\x4F\x9F\xDA\x00\x8F\x49\x8A\x7A" + "\xDB\xBC\x80\xB7\x0B\x14\xDD\xDB\xC0" } + }, + { + ENCTYPE_ARCFOUR_HMAC, + { KV5M_DATA, 9, "9 bytesss", }, 2, + { KV5M_DATA, 16, + "\x3E\x40\xAB\x60\x93\x69\x52\x81\xB3\xAC\x1A\x93\x04\x22\x4D\x98" }, + { KV5M_DATA, 33, + "\x0F\x9A\xD1\x21\xD9\x9D\x4A\x09\x44\x8E\x4F\x1F\x71\x8C\x4F\x5C" + "\xBE\x60\x96\x26\x2C\x66\xF2\x9D\xF2\x32\xA8\x7C\x9F\x98\x75\x5D" + "\x55" } + }, + { + ENCTYPE_ARCFOUR_HMAC, + { KV5M_DATA, 13, "13 bytes byte", }, 3, + { KV5M_DATA, 16, + "\x4B\xA2\xFB\xF0\x37\x9F\xAE\xD8\x7A\x25\x4D\x3B\x35\x3D\x5A\x7E" }, + { KV5M_DATA, 37, + "\x61\x2C\x57\x56\x8B\x17\xA7\x03\x52\xBA\xE8\xCF\x26\xFB\x94\x59" + "\xA6\xF3\x35\x3C\xD3\x5F\xD4\x39\xDB\x31\x07\xCB\xEC\x76\x5D\x32" + "\x6D\xFC\x04\xC1\xDD" } + }, + { + ENCTYPE_ARCFOUR_HMAC, + { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4, + { KV5M_DATA, 16, + "\x68\xF2\x63\xDB\x3F\xCE\x15\xD0\x31\xC9\xEA\xB0\x2D\x67\x10\x7A" }, + { KV5M_DATA, 54, + "\x95\xF9\x04\x7C\x3A\xD7\x58\x91\xC2\xE9\xB0\x4B\x16\x56\x6D\xC8" + "\xB6\xEB\x9C\xE4\x23\x1A\xFB\x25\x42\xEF\x87\xA7\xB5\xA0\xF2\x60" + "\xA9\x9F\x04\x60\x50\x8D\xE0\xCE\xCC\x63\x2D\x07\xC3\x54\x12\x4E" + "\x46\xC5\xD2\x23\x4E\xB8" } + }, + + { + ENCTYPE_ARCFOUR_HMAC_EXP, + { KV5M_DATA, 0, "", }, 0, + { KV5M_DATA, 16, + "\xF7\xD3\xA1\x55\xAF\x5E\x23\x8A\x0B\x7A\x87\x1A\x96\xBA\x2A\xB2" }, + { KV5M_DATA, 24, + "\x28\x27\xF0\xE9\x0F\x62\xE7\x46\x0C\x4E\x2F\xB3\x9F\x96\x57\xBA" + "\x8B\xFA\xA9\x91\xD7\xFD\xAD\xFF" } + }, + { + ENCTYPE_ARCFOUR_HMAC_EXP, + { KV5M_DATA, 1, "1", }, 1, + { KV5M_DATA, 16, + "\xDE\xEA\xA0\x60\x7D\xB7\x99\xE2\xFD\xD6\xDB\x29\x86\xBB\x8D\x65" }, + { KV5M_DATA, 25, + "\x3D\xDA\x39\x2E\x2E\x27\x5A\x4D\x75\x18\x3F\xA6\x32\x8A\x0A\x4E" + "\x6B\x75\x2D\xF6\xCD\x2A\x25\xFA\x4E" } + }, + { + ENCTYPE_ARCFOUR_HMAC_EXP, + { KV5M_DATA, 9, "9 bytesss", }, 2, + { KV5M_DATA, 16, + "\x33\xAD\x7F\xC2\x67\x86\x15\x56\x9B\x2B\x09\x83\x6E\x0A\x3A\xB6" }, + { KV5M_DATA, 33, + "\x09\xD1\x36\xAC\x48\x5D\x92\x64\x4E\xC6\x70\x1D\x6A\x0D\x03\xE8" + "\x98\x2D\x7A\x3C\xA7\xEF\xD0\xF8\xF4\xF8\x36\x60\xEF\x42\x77\xBB" + "\x81" } + }, + { + ENCTYPE_ARCFOUR_HMAC_EXP, + { KV5M_DATA, 13, "13 bytes byte", }, 3, + { KV5M_DATA, 16, + "\x39\xF2\x5C\xD4\xF0\xD4\x1B\x2B\x2D\x9D\x30\x0F\xCB\x29\x81\xCB" }, + { KV5M_DATA, 37, + "\x91\x23\x88\xD7\xC0\x76\x12\x81\x9E\x3B\x64\x0F\xF5\xCE\xCD\xAF" + "\x72\xE5\xA5\x9D\xF1\x0F\x10\x91\xA6\xBE\xC3\x9C\xAA\xD7\x48\xAF" + "\x9B\xD2\xD8\xD5\x46" } + }, + { + ENCTYPE_ARCFOUR_HMAC_EXP, + { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4, + { KV5M_DATA, 16, + "\x9F\x72\x55\x42\xD9\xF7\x2A\xA1\xF3\x86\xCB\xE7\x89\x69\x84\xFC" }, + { KV5M_DATA, 54, + "\x78\xB3\x5A\x08\xB0\x8B\xE2\x65\xAE\xB4\x14\x5F\x07\x65\x13\xB6" + "\xB5\x6E\xFE\xD3\xF7\x52\x65\x74\xAF\x74\xF7\xD2\xF9\xBA\xE9\x6E" + "\xAB\xB7\x6F\x2D\x87\x38\x6D\x2E\x93\xE3\xA7\x7B\x99\x91\x9F\x1D" + "\x97\x64\x90\xE2\xBD\x45" } + }, + + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + { KV5M_DATA, 0, "", }, 0, + { KV5M_DATA, 16, + "\x5A\x5C\x0F\x0B\xA5\x4F\x38\x28\xB2\x19\x5E\x66\xCA\x24\xA2\x89" }, + { KV5M_DATA, 28, + "\x49\xFF\x8E\x11\xC1\x73\xD9\x58\x3A\x32\x54\xFB\xE7\xB1\xF1\xDF" + "\x36\xC5\x38\xE8\x41\x67\x84\xA1\x67\x2E\x66\x76" } + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + { KV5M_DATA, 1, "1", }, 1, + { KV5M_DATA, 16, + "\x98\x45\x0E\x3F\x3B\xAA\x13\xF5\xC9\x9B\xEB\x93\x69\x81\xB0\x6F" }, + { KV5M_DATA, 29, + "\xF8\x67\x42\xF5\x37\xB3\x5D\xC2\x17\x4A\x4D\xBA\xA9\x20\xFA\xF9" + "\x04\x20\x90\xB0\x65\xE1\xEB\xB1\xCA\xD9\xA6\x53\x94" } + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + { KV5M_DATA, 9, "9 bytesss", }, 2, + { KV5M_DATA, 16, + "\x90\x62\x43\x0C\x8C\xDA\x33\x88\x92\x2E\x6D\x6A\x50\x9F\x5B\x7A" }, + { KV5M_DATA, 37, + "\x68\xFB\x96\x79\x60\x1F\x45\xC7\x88\x57\xB2\xBF\x82\x0F\xD6\xE5" + "\x3E\xCA\x8D\x42\xFD\x4B\x1D\x70\x24\xA0\x92\x05\xAB\xB7\xCD\x2E" + "\xC2\x6C\x35\x5D\x2F" } + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + { KV5M_DATA, 13, "13 bytes byte", }, 3, + { KV5M_DATA, 16, + "\x03\x3E\xE6\x50\x2C\x54\xFD\x23\xE2\x77\x91\xE9\x87\x98\x38\x27" }, + { KV5M_DATA, 41, + "\xEC\x36\x6D\x03\x27\xA9\x33\xBF\x49\x33\x0E\x65\x0E\x49\xBC\x6B" + "\x97\x46\x37\xFE\x80\xBF\x53\x2F\xE5\x17\x95\xB4\x80\x97\x18\xE6" + "\x19\x47\x24\xDB\x94\x8D\x1F\xD6\x37" } + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4, + { KV5M_DATA, 16, + "\xDC\xEE\xB7\x0B\x3D\xE7\x65\x62\xE6\x89\x22\x6C\x76\x42\x91\x48" }, + { KV5M_DATA, 58, + "\xC9\x60\x81\x03\x2D\x5D\x8E\xEB\x7E\x32\xB4\x08\x9F\x78\x9D\x0F" + "\xAA\x48\x1D\xEA\x74\xC0\xF9\x7C\xBF\x31\x46\xDD\xFC\xF8\xE8\x00" + "\x15\x6E\xCB\x53\x2F\xC2\x03\xE3\x0F\xF6\x00\xB6\x3B\x35\x09\x39" + "\xFE\xCE\x51\x0F\x02\xD7\xFF\x1E\x7B\xAC" } + }, + + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + { KV5M_DATA, 0, "", }, 0, + { KV5M_DATA, 32, + "\x17\xF2\x75\xF2\x95\x4F\x2E\xD1\xF9\x0C\x37\x7B\xA7\xF4\xD6\xA3" + "\x69\xAA\x01\x36\xE0\xBF\x0C\x92\x7A\xD6\x13\x3C\x69\x37\x59\xA9" }, + { KV5M_DATA, 28, + "\xE5\x09\x4C\x55\xEE\x7B\x38\x26\x2E\x2B\x04\x42\x80\xB0\x69\x37" + "\x9A\x95\xBF\x95\xBD\x83\x76\xFB\x32\x81\xB4\x35" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + { KV5M_DATA, 1, "1", }, 1, + { KV5M_DATA, 32, + "\xB9\x47\x7E\x1F\xF0\x32\x9C\x00\x50\xE2\x0C\xE6\xC7\x2D\x2D\xFF" + "\x27\xE8\xFE\x54\x1A\xB0\x95\x44\x29\xA9\xCB\x5B\x4F\x7B\x1E\x2A" }, + { KV5M_DATA, 29, + "\x40\x61\x50\xB9\x7A\xEB\x76\xD4\x3B\x36\xB6\x2C\xC1\xEC\xDF\xBE" + "\x6F\x40\xE9\x57\x55\xE0\xBE\xB5\xC2\x78\x25\xF3\xA4" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + { KV5M_DATA, 9, "9 bytesss", }, 2, + { KV5M_DATA, 32, + "\xB1\xAE\x4C\xD8\x46\x2A\xFF\x16\x77\x05\x3C\xC9\x27\x9A\xAC\x30" + "\xB7\x96\xFB\x81\xCE\x21\x47\x4D\xD3\xDD\xBC\xFE\xA4\xEC\x76\xD7" }, + { KV5M_DATA, 37, + "\x09\x95\x7A\xA2\x5F\xCA\xF8\x8F\x7B\x39\xE4\x40\x6E\x63\x30\x12" + "\xD5\xFE\xA2\x18\x53\xF6\x47\x8D\xA7\x06\x5C\xAE\xF4\x1F\xD4\x54" + "\xA4\x08\x24\xEE\xC5" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + { KV5M_DATA, 13, "13 bytes byte", }, 3, + { KV5M_DATA, 32, + "\xE5\xA7\x2B\xE9\xB7\x92\x6C\x12\x25\xBA\xFE\xF9\xC1\x87\x2E\x7B" + "\xA4\xCD\xB2\xB1\x78\x93\xD8\x4A\xBD\x90\xAC\xDD\x87\x64\xD9\x66" }, + { KV5M_DATA, 41, + "\xD8\xF1\xAA\xFE\xEC\x84\x58\x7C\xC3\xE7\x00\xA7\x74\xE5\x66\x51" + "\xA6\xD6\x93\xE1\x74\xEC\x44\x73\xB5\xE6\xD9\x6F\x80\x29\x7A\x65" + "\x3F\xB8\x18\xAD\x89\x3E\x71\x9F\x96" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4, + { KV5M_DATA, 32, + "\xF1\xC7\x95\xE9\x24\x8A\x09\x33\x8D\x82\xC3\xF8\xD5\xB5\x67\x04" + "\x0B\x01\x10\x73\x68\x45\x04\x13\x47\x23\x5B\x14\x04\x23\x13\x98" }, + { KV5M_DATA, 58, + "\xD1\x13\x7A\x4D\x63\x4C\xFE\xCE\x92\x4D\xBC\x3B\xF6\x79\x06\x48" + "\xBD\x5C\xFF\x7D\xE0\xE7\xB9\x94\x60\x21\x1D\x0D\xAE\xF3\xD7\x9A" + "\x29\x5C\x68\x88\x58\xF3\xB3\x4B\x9C\xBD\x6E\xEB\xAE\x81\xDA\xF6" + "\xB7\x34\xD4\xD4\x98\xB6\x71\x4F\x1C\x1D" } + }, + + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + { KV5M_DATA, 0, "", }, 0, + { KV5M_DATA, 16, + "\x1D\xC4\x6A\x8D\x76\x3F\x4F\x93\x74\x2B\xCB\xA3\x38\x75\x76\xC3" }, + { KV5M_DATA, 32, + "\xC4\x66\xF1\x87\x10\x69\x92\x1E\xDB\x7C\x6F\xDE\x24\x4A\x52\xDB" + "\x0B\xA1\x0E\xDC\x19\x7B\xDB\x80\x06\x65\x8C\xA3\xCC\xCE\x6E\xB8" } + }, + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + { KV5M_DATA, 1, "1", }, 1, + { KV5M_DATA, 16, + "\x50\x27\xBC\x23\x1D\x0F\x3A\x9D\x23\x33\x3F\x1C\xA6\xFD\xBE\x7C" }, + { KV5M_DATA, 33, + "\x84\x2D\x21\xFD\x95\x03\x11\xC0\xDD\x46\x4A\x3F\x4B\xE8\xD6\xDA" + "\x88\xA5\x6D\x55\x9C\x9B\x47\xD3\xF9\xA8\x50\x67\xAF\x66\x15\x59" + "\xB8" } + }, + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + { KV5M_DATA, 9, "9 bytesss", }, 2, + { KV5M_DATA, 16, + "\xA1\xBB\x61\xE8\x05\xF9\xBA\x6D\xDE\x8F\xDB\xDD\xC0\x5C\xDE\xA0" }, + { KV5M_DATA, 41, + "\x61\x9F\xF0\x72\xE3\x62\x86\xFF\x0A\x28\xDE\xB3\xA3\x52\xEC\x0D" + "\x0E\xDF\x5C\x51\x60\xD6\x63\xC9\x01\x75\x8C\xCF\x9D\x1E\xD3\x3D" + "\x71\xDB\x8F\x23\xAA\xBF\x83\x48\xA0" } + }, + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + { KV5M_DATA, 13, "13 bytes byte", }, 3, + { KV5M_DATA, 16, + "\x2C\xA2\x7A\x5F\xAF\x55\x32\x24\x45\x06\x43\x4E\x1C\xEF\x66\x76" }, + { KV5M_DATA, 45, + "\xB8\xEC\xA3\x16\x7A\xE6\x31\x55\x12\xE5\x9F\x98\xA7\xC5\x00\x20" + "\x5E\x5F\x63\xFF\x3B\xB3\x89\xAF\x1C\x41\xA2\x1D\x64\x0D\x86\x15" + "\xC9\xED\x3F\xBE\xB0\x5A\xB6\xAC\xB6\x76\x89\xB5\xEA" } + }, + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4, + { KV5M_DATA, 16, + "\x78\x24\xF8\xC1\x6F\x83\xFF\x35\x4C\x6B\xF7\x51\x5B\x97\x3F\x43" }, + { KV5M_DATA, 62, + "\xA2\x6A\x39\x05\xA4\xFF\xD5\x81\x6B\x7B\x1E\x27\x38\x0D\x08\x09" + "\x0C\x8E\xC1\xF3\x04\x49\x6E\x1A\xBD\xCD\x2B\xDC\xD1\xDF\xFC\x66" + "\x09\x89\xE1\x17\xA7\x13\xDD\xBB\x57\xA4\x14\x6C\x15\x87\xCB\xA4" + "\x35\x66\x65\x59\x1D\x22\x40\x28\x2F\x58\x42\xB1\x05\xA5" } + }, + + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + { KV5M_DATA, 0, "", }, 0, + { KV5M_DATA, 32, + "\xB6\x1C\x86\xCC\x4E\x5D\x27\x57\x54\x5A\xD4\x23\x39\x9F\xB7\x03" + "\x1E\xCA\xB9\x13\xCB\xB9\x00\xBD\x7A\x3C\x6D\xD8\xBF\x92\x01\x5B" }, + { KV5M_DATA, 32, + "\x03\x88\x6D\x03\x31\x0B\x47\xA6\xD8\xF0\x6D\x7B\x94\xD1\xDD\x83" + "\x7E\xCC\xE3\x15\xEF\x65\x2A\xFF\x62\x08\x59\xD9\x4A\x25\x92\x66" } + }, + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + { KV5M_DATA, 1, "1", }, 1, + { KV5M_DATA, 32, + "\x1B\x97\xFE\x0A\x19\x0E\x20\x21\xEB\x30\x75\x3E\x1B\x6E\x1E\x77" + "\xB0\x75\x4B\x1D\x68\x46\x10\x35\x58\x64\x10\x49\x63\x46\x38\x33" }, + { KV5M_DATA, 33, + "\x2C\x9C\x15\x70\x13\x3C\x99\xBF\x6A\x34\xBC\x1B\x02\x12\x00\x2F" + "\xD1\x94\x33\x87\x49\xDB\x41\x35\x49\x7A\x34\x7C\xFC\xD9\xD1\x8A" + "\x12" } + }, + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + { KV5M_DATA, 9, "9 bytesss", }, 2, + { KV5M_DATA, 32, + "\x32\x16\x4C\x5B\x43\x4D\x1D\x15\x38\xE4\xCF\xD9\xBE\x80\x40\xFE" + "\x8C\x4A\xC7\xAC\xC4\xB9\x3D\x33\x14\xD2\x13\x36\x68\x14\x7A\x05" }, + { KV5M_DATA, 41, + "\x9C\x6D\xE7\x5F\x81\x2D\xE7\xED\x0D\x28\xB2\x96\x35\x57\xA1\x15" + "\x64\x09\x98\x27\x5B\x0A\xF5\x15\x27\x09\x91\x3F\xF5\x2A\x2A\x9C" + "\x8E\x63\xB8\x72\xF9\x2E\x64\xC8\x39" } + }, + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + { KV5M_DATA, 13, "13 bytes byte", }, 3, + { KV5M_DATA, 32, + "\xB0\x38\xB1\x32\xCD\x8E\x06\x61\x22\x67\xFA\xB7\x17\x00\x66\xD8" + "\x8A\xEC\xCB\xA0\xB7\x44\xBF\xC6\x0D\xC8\x9B\xCA\x18\x2D\x07\x15" }, + { KV5M_DATA, 45, + "\xEE\xEC\x85\xA9\x81\x3C\xDC\x53\x67\x72\xAB\x9B\x42\xDE\xFC\x57" + "\x06\xF7\x26\xE9\x75\xDD\xE0\x5A\x87\xEB\x54\x06\xEA\x32\x4C\xA1" + "\x85\xC9\x98\x6B\x42\xAA\xBE\x79\x4B\x84\x82\x1B\xEE" } + }, + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + { KV5M_DATA, 30, "30 bytes bytes bytes bytes byt", }, 4, + { KV5M_DATA, 32, + "\xCC\xFC\xD3\x49\xBF\x4C\x66\x77\xE8\x6E\x4B\x02\xB8\xEA\xB9\x24" + "\xA5\x46\xAC\x73\x1C\xF9\xBF\x69\x89\xB9\x96\xE7\xD6\xBF\xBB\xA7" }, + { KV5M_DATA, 62, + "\x0E\x44\x68\x09\x85\x85\x5F\x2D\x1F\x18\x12\x52\x9C\xA8\x3B\xFD" + "\x8E\x34\x9D\xE6\xFD\x9A\xDA\x0B\xAA\xA0\x48\xD6\x8E\x26\x5F\xEB" + "\xF3\x4A\xD1\x25\x5A\x34\x49\x99\xAD\x37\x14\x68\x87\xA6\xC6\x84" + "\x57\x31\xAC\x7F\x46\x37\x6A\x05\x04\xCD\x06\x57\x14\x74" } + }, + + { + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + { KV5M_DATA, 0, "", }, 2, + { KV5M_DATA, 16, + "\x37\x05\xD9\x60\x80\xC1\x77\x28\xA0\xE8\x00\xEA\xB6\xE0\xD2\x3C" }, + { KV5M_DATA, 32, + "\xEF\x85\xFB\x89\x0B\xB8\x47\x2F\x4D\xAB\x20\x39\x4D\xCA\x78\x1D" + "\xAD\x87\x7E\xDA\x39\xD5\x0C\x87\x0C\x0D\x5A\x0A\x8E\x48\xC7\x18" } + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + { KV5M_DATA, 6, "\x00\x01\x02\x03\x04\x05", }, 2, + { KV5M_DATA, 16, + "\x37\x05\xD9\x60\x80\xC1\x77\x28\xA0\xE8\x00\xEA\xB6\xE0\xD2\x3C" }, + { KV5M_DATA, 38, + "\x84\xD7\xF3\x07\x54\xED\x98\x7B\xAB\x0B\xF3\x50\x6B\xEB\x09\xCF" + "\xB5\x54\x02\xCE\xF7\xE6\x87\x7C\xE9\x9E\x24\x7E\x52\xD1\x6E\xD4" + "\x42\x1D\xFD\xF8\x97\x6C" } + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + { KV5M_DATA, 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" }, + 2, + { KV5M_DATA, 16, + "\x37\x05\xD9\x60\x80\xC1\x77\x28\xA0\xE8\x00\xEA\xB6\xE0\xD2\x3C" }, + { KV5M_DATA, 48, + "\x35\x17\xD6\x40\xF5\x0D\xDC\x8A\xD3\x62\x87\x22\xB3\x56\x9D\x2A" + "\xE0\x74\x93\xFA\x82\x63\x25\x40\x80\xEA\x65\xC1\x00\x8E\x8F\xC2" + "\x95\xFB\x48\x52\xE7\xD8\x3E\x1E\x7C\x48\xC3\x7E\xEB\xE6\xB0\xD3" } + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + { KV5M_DATA, 21, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14" }, + 2, + { KV5M_DATA, 16, + "\x37\x05\xD9\x60\x80\xC1\x77\x28\xA0\xE8\x00\xEA\xB6\xE0\xD2\x3C" }, + { KV5M_DATA, 53, + "\x72\x0F\x73\xB1\x8D\x98\x59\xCD\x6C\xCB\x43\x46\x11\x5C\xD3\x36" + "\xC7\x0F\x58\xED\xC0\xC4\x43\x7C\x55\x73\x54\x4C\x31\xC8\x13\xBC" + "\xE1\xE6\xD0\x72\xC1\x86\xB3\x9A\x41\x3C\x2F\x92\xCA\x9B\x83\x34" + "\xA2\x87\xFF\xCB\xFC" } + }, + + { + ENCTYPE_AES256_CTS_HMAC_SHA384_192, + { KV5M_DATA, 0, "", }, 2, + { KV5M_DATA, 32, + "\x6D\x40\x4D\x37\xFA\xF7\x9F\x9D\xF0\xD3\x35\x68\xD3\x20\x66\x98" + "\x00\xEB\x48\x36\x47\x2E\xA8\xA0\x26\xD1\x6B\x71\x82\x46\x0C\x52" }, + { KV5M_DATA, 40, + "\x41\xF5\x3F\xA5\xBF\xE7\x02\x6D\x91\xFA\xF9\xBE\x95\x91\x95\xA0" + "\x58\x70\x72\x73\xA9\x6A\x40\xF0\xA0\x19\x60\x62\x1A\xC6\x12\x74" + "\x8B\x9B\xBF\xBE\x7E\xB4\xCE\x3C" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA384_192, + { KV5M_DATA, 6, "\x00\x01\x02\x03\x04\x05", }, 2, + { KV5M_DATA, 32, + "\x6D\x40\x4D\x37\xFA\xF7\x9F\x9D\xF0\xD3\x35\x68\xD3\x20\x66\x98" + "\x00\xEB\x48\x36\x47\x2E\xA8\xA0\x26\xD1\x6B\x71\x82\x46\x0C\x52" }, + { KV5M_DATA, 46, + "\x4E\xD7\xB3\x7C\x2B\xCA\xC8\xF7\x4F\x23\xC1\xCF\x07\xE6\x2B\xC7" + "\xB7\x5F\xB3\xF6\x37\xB9\xF5\x59\xC7\xF6\x64\xF6\x9E\xAB\x7B\x60" + "\x92\x23\x75\x26\xEA\x0D\x1F\x61\xCB\x20\xD6\x9D\x10\xF2" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA384_192, + { KV5M_DATA, 16, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" }, + 2, + { KV5M_DATA, 32, + "\x6D\x40\x4D\x37\xFA\xF7\x9F\x9D\xF0\xD3\x35\x68\xD3\x20\x66\x98" + "\x00\xEB\x48\x36\x47\x2E\xA8\xA0\x26\xD1\x6B\x71\x82\x46\x0C\x52" }, + { KV5M_DATA, 56, + "\xBC\x47\xFF\xEC\x79\x98\xEB\x91\xE8\x11\x5C\xF8\xD1\x9D\xAC\x4B" + "\xBB\xE2\xE1\x63\xE8\x7D\xD3\x7F\x49\xBE\xCA\x92\x02\x77\x64\xF6" + "\x8C\xF5\x1F\x14\xD7\x98\xC2\x27\x3F\x35\xDF\x57\x4D\x1F\x93\x2E" + "\x40\xC4\xFF\x25\x5B\x36\xA2\x66" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA384_192, + { KV5M_DATA, 21, + "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F" + "\x10\x11\x12\x13\x14" }, + 2, + { KV5M_DATA, 32, + "\x6D\x40\x4D\x37\xFA\xF7\x9F\x9D\xF0\xD3\x35\x68\xD3\x20\x66\x98" + "\x00\xEB\x48\x36\x47\x2E\xA8\xA0\x26\xD1\x6B\x71\x82\x46\x0C\x52" }, + { KV5M_DATA, 61, + "\x40\x01\x3E\x2D\xF5\x8E\x87\x51\x95\x7D\x28\x78\xBC\xD2\xD6\xFE" + "\x10\x1C\xCF\xD5\x56\xCB\x1E\xAE\x79\xDB\x3C\x3E\xE8\x64\x29\xF2" + "\xB2\xA6\x02\xAC\x86\xFE\xF6\xEC\xB6\x47\xD6\x29\x5F\xAE\x07\x7A" + "\x1F\xEB\x51\x75\x08\xD2\xC1\x6B\x41\x92\xE0\x1F\x62" } + }, +}; + +static void +printhex(const char *head, void *data, size_t len) +{ + size_t i; + + printf("%s", head); + for (i = 0; i < len; i++) { + printf("%02X", ((unsigned char*)data)[i]); + if (i % 16 == 15 && i + 1 < len) + printf("\n%*s", (int)strlen(head), ""); + else if (i + 1 < len) + printf(" "); + } + printf("\n"); +} + +static krb5_enctype +enctypes[] = { + ENCTYPE_DES3_CBC_SHA1, + ENCTYPE_ARCFOUR_HMAC, + ENCTYPE_ARCFOUR_HMAC_EXP, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_CAMELLIA128_CTS_CMAC, + ENCTYPE_CAMELLIA256_CTS_CMAC, + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + ENCTYPE_AES256_CTS_HMAC_SHA384_192 +}; + +static char *plaintexts[] = { + "", + "1", + "9 bytesss", + "13 bytes byte", + "30 bytes bytes bytes bytes byt" +}; + +static int +generate(krb5_context context) +{ + krb5_error_code ret; + size_t i, j; + krb5_keyblock kb; + krb5_data plain, seed = string2data("seed"); + krb5_enc_data enc; + size_t enclen; + char buf[64]; + + ret = krb5_c_random_seed(context, &seed); + assert(!ret); + for (i = 0; i < sizeof(enctypes) / sizeof(*enctypes); i++) { + for (j = 0; j < sizeof(plaintexts) / sizeof(*plaintexts); j++) { + ret = krb5_c_make_random_key(context, enctypes[i], &kb); + assert(!ret); + plain = string2data(plaintexts[j]); + ret = krb5_c_encrypt_length(context, enctypes[i], plain.length, + &enclen); + assert(!ret); + ret = alloc_data(&enc.ciphertext, enclen); + assert(!ret); + ret = krb5_c_encrypt(context, &kb, j, NULL, &plain, &enc); + assert(!ret); + krb5_enctype_to_name(enctypes[i], FALSE, buf, sizeof(buf)); + printf("\nEnctype: %s\n", buf); + printf("Plaintext: %s\n", plaintexts[j]); + printhex("Key: ", kb.contents, kb.length); + printhex("Ciphertext: ", enc.ciphertext.data, + enc.ciphertext.length); + free(enc.ciphertext.data); + } + } + return 0; +} + +int +main(int argc, char **argv) +{ + krb5_error_code ret; + krb5_context context = NULL; + krb5_data plain; + size_t i; + struct test *test; + krb5_keyblock kb; + krb5_enc_data enc; + + if (argc >= 2 && strcmp(argv[1], "-g") == 0) + return generate(context); + + for (i = 0; i < sizeof(test_cases) / sizeof(*test_cases); i++) { + test = &test_cases[i]; + kb.magic = KV5M_KEYBLOCK; + kb.enctype = test->enctype; + kb.length = test->keybits.length; + kb.contents = (unsigned char *)test->keybits.data; + ret = alloc_data(&plain, test->ciphertext.length); + assert(!ret); + enc.magic = KV5M_ENC_DATA; + enc.enctype = test->enctype; + enc.kvno = 0; + enc.ciphertext = test->ciphertext; + if (krb5_c_decrypt(context, &kb, test->usage, NULL, &enc, + &plain) != 0) { + printf("decrypt test %d failed to decrypt\n", (int)i); + return 1; + } + assert(plain.length >= test->plaintext.length); + if (memcmp(plain.data, test->plaintext.data, + test->plaintext.length) != 0) { + printf("decrypt test %d produced wrong result\n", (int)i); + return 1; + } + free(plain.data); + } + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_derive.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_derive.c new file mode 100644 index 00000000..afbf7477 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_derive.c @@ -0,0 +1,375 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_derive.c - Test harness for key derivation */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This harness detects changes in key derivation results using known values. + * With the -v flag, results for all tests are displayed. + */ + +#include "crypto_int.h" + +struct test { + krb5_enctype enctype; + krb5_data inkey; + krb5_data constant; + enum deriv_alg alg; + krb5_data expected_key; +} test_cases[] = { + /* Kc, Ke, Kei for a DES3 key */ + { + ENCTYPE_DES3_CBC_SHA1, + { KV5M_DATA, 24, + "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C\x31\x3E\x3B\xFE" + "\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" }, + { KV5M_DATA, 5, "\0\0\0\2\x99" }, + DERIVE_RFC3961, + { KV5M_DATA, 24, + "\xF7\x8C\x49\x6D\x16\xE6\xC2\xDA\xE0\xE0\xB6\xC2\x40\x57\xA8\x4C" + "\x04\x26\xAE\xEF\x26\xFD\x6D\xCE" } + }, + { + ENCTYPE_DES3_CBC_SHA1, + { KV5M_DATA, 24, + "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C\x31\x3E\x3B\xFE" + "\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" }, + { KV5M_DATA, 5, "\0\0\0\2\xAA" }, + DERIVE_RFC3961, + { KV5M_DATA, 24, + "\x5B\x57\x23\xD0\xB6\x34\xCB\x68\x4C\x3E\xBA\x52\x64\xE9\xA7\x0D" + "\x52\xE6\x83\x23\x1A\xD3\xC4\xCE" } + }, + { + ENCTYPE_DES3_CBC_SHA1, + { KV5M_DATA, 24, + "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C\x31\x3E\x3B\xFE" + "\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" }, + { KV5M_DATA, 5, "\0\0\0\2\x55" }, + DERIVE_RFC3961, + { KV5M_DATA, 24, + "\xA7\x7C\x94\x98\x0E\x9B\x73\x45\xA8\x15\x25\xC4\x23\xA7\x37\xCE" + "\x67\xF4\xCD\x91\xB6\xB3\xDA\x45" } + }, + + /* Kc, Ke, Ki for an AES-128 key */ + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + { KV5M_DATA, 16, + "\x42\x26\x3C\x6E\x89\xF4\xFC\x28\xB8\xDF\x68\xEE\x09\x79\x9F\x15" }, + { KV5M_DATA, 5, "\0\0\0\2\x99" }, + DERIVE_RFC3961, + { KV5M_DATA, 16, + "\x34\x28\x0A\x38\x2B\xC9\x27\x69\xB2\xDA\x2F\x9E\xF0\x66\x85\x4B" } + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + { KV5M_DATA, 16, + "\x42\x26\x3C\x6E\x89\xF4\xFC\x28\xB8\xDF\x68\xEE\x09\x79\x9F\x15" }, + { KV5M_DATA, 5, "\0\0\0\2\xAA" }, + DERIVE_RFC3961, + { KV5M_DATA, 16, + "\x5B\x14\xFC\x4E\x25\x0E\x14\xDD\xF9\xDC\xCF\x1A\xF6\x67\x4F\x53" } + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + { KV5M_DATA, 16, + "\x42\x26\x3C\x6E\x89\xF4\xFC\x28\xB8\xDF\x68\xEE\x09\x79\x9F\x15" }, + { KV5M_DATA, 5, "\0\0\0\2\x55" }, + DERIVE_RFC3961, + { KV5M_DATA, 16, + "\x4E\xD3\x10\x63\x62\x16\x84\xF0\x9A\xE8\xD8\x99\x91\xAF\x3E\x8F" } + }, + + /* Kc, Ke, Ki for an AES-256 key */ + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + { KV5M_DATA, 32, + "\xFE\x69\x7B\x52\xBC\x0D\x3C\xE1\x44\x32\xBA\x03\x6A\x92\xE6\x5B" + "\xBB\x52\x28\x09\x90\xA2\xFA\x27\x88\x39\x98\xD7\x2A\xF3\x01\x61" }, + { KV5M_DATA, 5, "\0\0\0\2\x99" }, + DERIVE_RFC3961, + { KV5M_DATA, 32, + "\xBF\xAB\x38\x8B\xDC\xB2\x38\xE9\xF9\xC9\x8D\x6A\x87\x83\x04\xF0" + "\x4D\x30\xC8\x25\x56\x37\x5A\xC5\x07\xA7\xA8\x52\x79\x0F\x46\x74" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + { KV5M_DATA, 32, + "\xFE\x69\x7B\x52\xBC\x0D\x3C\xE1\x44\x32\xBA\x03\x6A\x92\xE6\x5B" + "\xBB\x52\x28\x09\x90\xA2\xFA\x27\x88\x39\x98\xD7\x2A\xF3\x01\x61" }, + { KV5M_DATA, 5, "\0\0\0\2\xAA" }, + DERIVE_RFC3961, + { KV5M_DATA, 32, + "\xC7\xCF\xD9\xCD\x75\xFE\x79\x3A\x58\x6A\x54\x2D\x87\xE0\xD1\x39" + "\x6F\x11\x34\xA1\x04\xBB\x1A\x91\x90\xB8\xC9\x0A\xDA\x3D\xDF\x37" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + { KV5M_DATA, 32, + "\xFE\x69\x7B\x52\xBC\x0D\x3C\xE1\x44\x32\xBA\x03\x6A\x92\xE6\x5B" + "\xBB\x52\x28\x09\x90\xA2\xFA\x27\x88\x39\x98\xD7\x2A\xF3\x01\x61" }, + { KV5M_DATA, 5, "\0\0\0\2\x55" }, + DERIVE_RFC3961, + { KV5M_DATA, 32, + "\x97\x15\x1B\x4C\x76\x94\x50\x63\xE2\xEB\x05\x29\xDC\x06\x7D\x97" + "\xD7\xBB\xA9\x07\x76\xD8\x12\x6D\x91\xF3\x4F\x31\x01\xAE\xA8\xBA" } + }, + + /* Kc, Ke, Ki for a Camellia-128 key */ + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + { KV5M_DATA, 16, + "\x57\xD0\x29\x72\x98\xFF\xD9\xD3\x5D\xE5\xA4\x7F\xB4\xBD\xE2\x4B" }, + { KV5M_DATA, 5, "\0\0\0\2\x99" }, + DERIVE_SP800_108_CMAC, + { KV5M_DATA, 16, + "\xD1\x55\x77\x5A\x20\x9D\x05\xF0\x2B\x38\xD4\x2A\x38\x9E\x5A\x56" } + }, + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + { KV5M_DATA, 16, + "\x57\xD0\x29\x72\x98\xFF\xD9\xD3\x5D\xE5\xA4\x7F\xB4\xBD\xE2\x4B" }, + { KV5M_DATA, 5, "\0\0\0\2\xAA" }, + DERIVE_SP800_108_CMAC, + { KV5M_DATA, 16, + "\x64\xDF\x83\xF8\x5A\x53\x2F\x17\x57\x7D\x8C\x37\x03\x57\x96\xAB" } + }, + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + { KV5M_DATA, 16, + "\x57\xD0\x29\x72\x98\xFF\xD9\xD3\x5D\xE5\xA4\x7F\xB4\xBD\xE2\x4B" }, + { KV5M_DATA, 5, "\0\0\0\2\x55" }, + DERIVE_SP800_108_CMAC, + { KV5M_DATA, 16, + "\x3E\x4F\xBD\xF3\x0F\xB8\x25\x9C\x42\x5C\xB6\xC9\x6F\x1F\x46\x35" } + }, + + /* Kc, Ke, Ki for a Camellia-256 key */ + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + { KV5M_DATA, 32, + "\xB9\xD6\x82\x8B\x20\x56\xB7\xBE\x65\x6D\x88\xA1\x23\xB1\xFA\xC6" + "\x82\x14\xAC\x2B\x72\x7E\xCF\x5F\x69\xAF\xE0\xC4\xDF\x2A\x6D\x2C" }, + { KV5M_DATA, 5, "\0\0\0\2\x99" }, + DERIVE_SP800_108_CMAC, + { KV5M_DATA, 32, + "\xE4\x67\xF9\xA9\x55\x2B\xC7\xD3\x15\x5A\x62\x20\xAF\x9C\x19\x22" + "\x0E\xEE\xD4\xFF\x78\xB0\xD1\xE6\xA1\x54\x49\x91\x46\x1A\x9E\x50" } + }, + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + { KV5M_DATA, 32, + "\xB9\xD6\x82\x8B\x20\x56\xB7\xBE\x65\x6D\x88\xA1\x23\xB1\xFA\xC6" + "\x82\x14\xAC\x2B\x72\x7E\xCF\x5F\x69\xAF\xE0\xC4\xDF\x2A\x6D\x2C" }, + { KV5M_DATA, 5, "\0\0\0\2\xAA" }, + DERIVE_SP800_108_CMAC, + { KV5M_DATA, 32, + "\x41\x2A\xEF\xC3\x62\xA7\x28\x5F\xC3\x96\x6C\x6A\x51\x81\xE7\x60" + "\x5A\xE6\x75\x23\x5B\x6D\x54\x9F\xBF\xC9\xAB\x66\x30\xA4\xC6\x04" } + }, + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + { KV5M_DATA, 32, + "\xB9\xD6\x82\x8B\x20\x56\xB7\xBE\x65\x6D\x88\xA1\x23\xB1\xFA\xC6" + "\x82\x14\xAC\x2B\x72\x7E\xCF\x5F\x69\xAF\xE0\xC4\xDF\x2A\x6D\x2C" }, + { KV5M_DATA, 5, "\0\0\0\2\x55" }, + DERIVE_SP800_108_CMAC, + { KV5M_DATA, 32, + "\xFA\x62\x4F\xA0\xE5\x23\x99\x3F\xA3\x88\xAE\xFD\xC6\x7E\x67\xEB" + "\xCD\x8C\x08\xE8\xA0\x24\x6B\x1D\x73\xB0\xD1\xDD\x9F\xC5\x82\xB0" } + }, + + /* Kc, Ke, Ki for an aes128-sha2 key. */ + { + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + { KV5M_DATA, 16, + "\x37\x05\xD9\x60\x80\xC1\x77\x28\xA0\xE8\x00\xEA\xB6\xE0\xD2\x3C" }, + { KV5M_DATA, 5, "\0\0\0\2\x99" }, + DERIVE_SP800_108_HMAC, + { KV5M_DATA, 16, + "\xB3\x1A\x01\x8A\x48\xF5\x47\x76\xF4\x03\xE9\xA3\x96\x32\x5D\xC3" } + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + { KV5M_DATA, 16, + "\x37\x05\xD9\x60\x80\xC1\x77\x28\xA0\xE8\x00\xEA\xB6\xE0\xD2\x3C" }, + { KV5M_DATA, 5, "\0\0\0\2\xAA" }, + DERIVE_SP800_108_HMAC, + { KV5M_DATA, 16, + "\x9B\x19\x7D\xD1\xE8\xC5\x60\x9D\x6E\x67\xC3\xE3\x7C\x62\xC7\x2E" } + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + { KV5M_DATA, 16, + "\x37\x05\xD9\x60\x80\xC1\x77\x28\xA0\xE8\x00\xEA\xB6\xE0\xD2\x3C" }, + { KV5M_DATA, 5, "\0\0\0\2\x55" }, + DERIVE_SP800_108_HMAC, + { KV5M_DATA, 16, + "\x9F\xDA\x0E\x56\xAB\x2D\x85\xE1\x56\x9A\x68\x86\x96\xC2\x6A\x6C" } + }, + + /* Kc, Ke, Ki for an aes256-sha2 key. */ + { + ENCTYPE_AES256_CTS_HMAC_SHA384_192, + { KV5M_DATA, 32, + "\x6D\x40\x4D\x37\xFA\xF7\x9F\x9D\xF0\xD3\x35\x68\xD3\x20\x66\x98" + "\x00\xEB\x48\x36\x47\x2E\xA8\xA0\x26\xD1\x6B\x71\x82\x46\x0C\x52" }, + { KV5M_DATA, 5, "\0\0\0\2\x99" }, + DERIVE_SP800_108_HMAC, + { KV5M_DATA, 24, + "\xEF\x57\x18\xBE\x86\xCC\x84\x96\x3D\x8B\xBB\x50\x31\xE9\xF5\xC4" + "\xBA\x41\xF2\x8F\xAF\x69\xE7\x3D" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA384_192, + { KV5M_DATA, 32, + "\x6D\x40\x4D\x37\xFA\xF7\x9F\x9D\xF0\xD3\x35\x68\xD3\x20\x66\x98" + "\x00\xEB\x48\x36\x47\x2E\xA8\xA0\x26\xD1\x6B\x71\x82\x46\x0C\x52" }, + { KV5M_DATA, 5, "\0\0\0\2\xAA" }, + DERIVE_SP800_108_HMAC, + { KV5M_DATA, 32, + "\x56\xAB\x22\xBE\xE6\x3D\x82\xD7\xBC\x52\x27\xF6\x77\x3F\x8E\xA7" + "\xA5\xEB\x1C\x82\x51\x60\xC3\x83\x12\x98\x0C\x44\x2E\x5C\x7E\x49" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA384_192, + { KV5M_DATA, 32, + "\x6D\x40\x4D\x37\xFA\xF7\x9F\x9D\xF0\xD3\x35\x68\xD3\x20\x66\x98" + "\x00\xEB\x48\x36\x47\x2E\xA8\xA0\x26\xD1\x6B\x71\x82\x46\x0C\x52" }, + { KV5M_DATA, 5, "\0\0\0\2\x55" }, + DERIVE_SP800_108_HMAC, + { KV5M_DATA, 24, + "\x69\xB1\x65\x14\xE3\xCD\x8E\x56\xB8\x20\x10\xD5\xC7\x30\x12\xB6" + "\x22\xC4\xD0\x0F\xFC\x23\xED\x1F" } + }, +}; + +static void +printhex(const char *head, void *data, size_t len) +{ + size_t i; + + printf("%s", head); + for (i = 0; i < len; i++) { + printf("%02X", ((unsigned char*)data)[i]); + if (i % 16 == 15 && i + 1 < len) + printf("\n%*s", (int)strlen(head), ""); + else if (i + 1 < len) + printf(" "); + } + printf("\n"); +} + +static const struct krb5_enc_provider * +get_enc_provider(krb5_enctype enctype) +{ + switch (enctype) { + case ENCTYPE_DES3_CBC_SHA1: return &krb5int_enc_des3; + case ENCTYPE_AES128_CTS_HMAC_SHA1_96: return &krb5int_enc_aes128; + case ENCTYPE_AES256_CTS_HMAC_SHA1_96: return &krb5int_enc_aes256; + case ENCTYPE_CAMELLIA128_CTS_CMAC: return &krb5int_enc_camellia128; + case ENCTYPE_CAMELLIA256_CTS_CMAC: return &krb5int_enc_camellia256; + case ENCTYPE_AES128_CTS_HMAC_SHA256_128: return &krb5int_enc_aes128; + case ENCTYPE_AES256_CTS_HMAC_SHA384_192: return &krb5int_enc_aes256; + } + abort(); +} + +static const struct krb5_hash_provider * +get_hash_provider(krb5_enctype enctype) +{ + switch (enctype) { + case ENCTYPE_AES128_CTS_HMAC_SHA256_128: return &krb5int_hash_sha256; + case ENCTYPE_AES256_CTS_HMAC_SHA384_192: return &krb5int_hash_sha384; + } + return NULL; +} + +int +main(int argc, char **argv) +{ + krb5_error_code ret; + krb5_context context = NULL; + size_t i; + struct test *test; + krb5_keyblock kb; + krb5_key inkey = NULL, key = NULL; + krb5_data rnd = empty_data(), outcmp; + const struct krb5_enc_provider *enc; + const struct krb5_hash_provider *hash; + krb5_boolean verbose = FALSE; + int status = 0; + + if (argc >= 2 && strcmp(argv[1], "-v") == 0) + verbose = TRUE; + for (i = 0; i < sizeof(test_cases) / sizeof(*test_cases); i++) { + test = &test_cases[i]; + kb.magic = KV5M_KEYBLOCK; + kb.enctype = test->enctype; + kb.length = test->inkey.length; + kb.contents = (unsigned char *)test->inkey.data; + ret = krb5_k_create_key(context, &kb, &inkey); + assert(!ret); + enc = get_enc_provider(test->enctype); + hash = get_hash_provider(test->enctype); + if (test->expected_key.length == enc->keylength) { + ret = krb5int_derive_key(enc, hash, inkey, &key, &test->constant, + test->alg); + assert(!ret); + outcmp = make_data(key->keyblock.contents, key->keyblock.length); + } else { + ret = alloc_data(&rnd, test->expected_key.length); + assert(!ret); + ret = krb5int_derive_random(enc, hash, inkey, &rnd, + &test->constant, test->alg); + assert(!ret); + outcmp = rnd; + } + if (verbose) { + char buf[64]; + krb5_enctype_to_name(test->enctype, FALSE, buf, sizeof(buf)); + printf("\nTest %d:\n", (int)i); + printf("Enctype: %s\n", buf); + printhex("Input key: ", inkey->keyblock.contents, + inkey->keyblock.length); + printhex("Constant: ", test->constant.data, test->constant.length); + printhex("Output: ", outcmp.data, outcmp.length); + } + assert(outcmp.length == test->expected_key.length); + if (memcmp(outcmp.data, test->expected_key.data, outcmp.length) != 0) { + printf("derive test %d failed\n", (int)i); + status = 1; + if (!verbose) + break; + } + + krb5_k_free_key(context, inkey); + krb5_k_free_key(context, key); + zapfree(rnd.data, rnd.length); + inkey = key = NULL; + rnd = empty_data(); + } + return status; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_encrypt.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_encrypt.c new file mode 100644 index 00000000..bd9b9469 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_encrypt.c @@ -0,0 +1,289 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_encrypt.c */ +/* + * Copyright 2001, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * <<< Description >>> + */ +/* + * Some black-box tests of crypto systems. Make sure that we can decrypt things we encrypt, etc. + */ + +#include "crypto_int.h" +#include + +/* What enctypes should we test?*/ +krb5_enctype interesting_enctypes[] = { + ENCTYPE_DES3_CBC_SHA1, + ENCTYPE_ARCFOUR_HMAC, + ENCTYPE_ARCFOUR_HMAC_EXP, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_CAMELLIA128_CTS_CMAC, + ENCTYPE_CAMELLIA256_CTS_CMAC, + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + ENCTYPE_AES256_CTS_HMAC_SHA384_192, + 0 +}; + +static void +test(const char *msg, krb5_error_code retval) +{ + printf("%s: . . . ", msg); + if (retval) { + printf("Failed: %s\n", error_message(retval)); + abort(); + } else + printf("OK\n"); +} + +static int compare_results(krb5_data *d1, krb5_data *d2) +{ + if (d1->length != d2->length) { + /* Decryption can leave a little trailing cruft. + For the current cryptosystems, this can be up to 7 bytes. */ + if (d1->length + 8 <= d2->length) + return EINVAL; + if (d1->length > d2->length) + return EINVAL; + } + if (memcmp(d1->data, d2->data, d1->length)) { + return EINVAL; + } + return 0; +} + +static void +display(const char *msg, const krb5_data *d) +{ + unsigned int i; + + printf("%s:", msg); + for (i = 0; i < d->length; i++) + printf(" %02X", (unsigned char) d->data[i]); + printf("\n"); +} + +int +main () +{ + krb5_context context = 0; + krb5_data in, in2, out, out2, check, check2, state, signdata; + krb5_crypto_iov iov[5]; + int i, j, pos; + unsigned int dummy; + size_t len; + krb5_enc_data enc_out, enc_out2; + krb5_keyblock *keyblock; + krb5_key key; + + memset(iov, 0, sizeof(iov)); + + in.data = "This is a test.\n"; + in.length = strlen (in.data); + in2.data = "This is another test.\n"; + in2.length = strlen (in2.data); + + test ("Seeding random number generator", + krb5_c_random_seed (context, &in)); + + /* Set up output buffers. */ + out.data = malloc(2048); + out2.data = malloc(2048); + check.data = malloc(2048); + check2.data = malloc(2048); + if (out.data == NULL || out2.data == NULL + || check.data == NULL || check2.data == NULL) + abort(); + out.magic = KV5M_DATA; + out.length = 2048; + out2.magic = KV5M_DATA; + out2.length = 2048; + check.length = 2048; + check2.length = 2048; + + for (i = 0; interesting_enctypes[i]; i++) { + krb5_enctype enctype = interesting_enctypes [i]; + + printf ("Testing enctype %d\n", enctype); + test ("Initializing a keyblock", + krb5_init_keyblock (context, enctype, 0, &keyblock)); + test ("Generating random keyblock", + krb5_c_make_random_key (context, enctype, keyblock)); + test ("Creating opaque key from keyblock", + krb5_k_create_key (context, keyblock, &key)); + + enc_out.ciphertext = out; + enc_out2.ciphertext = out2; + /* We use an intermediate `len' because size_t may be different size + than `int' */ + krb5_c_encrypt_length (context, keyblock->enctype, in.length, &len); + enc_out.ciphertext.length = len; + + /* Encrypt, decrypt, and see if we got the plaintext back again. */ + test ("Encrypting (c)", + krb5_c_encrypt (context, keyblock, 7, 0, &in, &enc_out)); + display ("Enc output", &enc_out.ciphertext); + test ("Decrypting", + krb5_c_decrypt (context, keyblock, 7, 0, &enc_out, &check)); + test ("Comparing", compare_results (&in, &check)); + + /* Try again with the opaque-key-using variants. */ + memset(out.data, 0, out.length); + test ("Encrypting (k)", + krb5_k_encrypt (context, key, 7, 0, &in, &enc_out)); + display ("Enc output", &enc_out.ciphertext); + test ("Decrypting", + krb5_k_decrypt (context, key, 7, 0, &enc_out, &check)); + test ("Comparing", compare_results (&in, &check)); + + /* Check if this enctype supports IOV encryption. */ + if ( krb5_c_crypto_length(context, keyblock->enctype, + KRB5_CRYPTO_TYPE_HEADER, &dummy) == 0 ){ + /* Set up iovecs for stream decryption. */ + memcpy(out2.data, enc_out.ciphertext.data, enc_out.ciphertext.length); + iov[0].flags= KRB5_CRYPTO_TYPE_STREAM; + iov[0].data.data = out2.data; + iov[0].data.length = enc_out.ciphertext.length; + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + + /* Decrypt the encrypted data from above and check it. */ + test("IOV stream decrypting (c)", + krb5_c_decrypt_iov( context, keyblock, 7, 0, iov, 2)); + test("Comparing results", + compare_results(&in, &iov[1].data)); + + /* Try again with the opaque-key-using variant. */ + memcpy(out2.data, enc_out.ciphertext.data, enc_out.ciphertext.length); + test("IOV stream decrypting (k)", + krb5_k_decrypt_iov( context, key, 7, 0, iov, 2)); + test("Comparing results", + compare_results(&in, &iov[1].data)); + + /* Set up iovecs for AEAD encryption. */ + signdata.magic = KV5M_DATA; + signdata.data = (char *) "This should be signed"; + signdata.length = strlen(signdata.data); + iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data = in; /*We'll need to copy memory before encrypt*/ + iov[2].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + iov[2].data = signdata; + iov[3].flags = KRB5_CRYPTO_TYPE_PADDING; + iov[4].flags = KRB5_CRYPTO_TYPE_TRAILER; + + /* "Allocate" data for the iovec buffers from the "out" buffer. */ + test("Setting up iov lengths", + krb5_c_crypto_length_iov(context, keyblock->enctype, iov, 5)); + for (j=0,pos=0; j <= 4; j++ ){ + if (iov[j].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY) + continue; + iov[j].data.data = &out.data[pos]; + pos += iov[j].data.length; + } + assert (iov[1].data.length == in.length); + memcpy(iov[1].data.data, in.data, in.length); + + /* Encrypt and decrypt in place, and check the result. */ + test("iov encrypting (c)", + krb5_c_encrypt_iov(context, keyblock, 7, 0, iov, 5)); + assert(iov[1].data.length == in.length); + display("Header", &iov[0].data); + display("Data", &iov[1].data); + display("Padding", &iov[3].data); + display("Trailer", &iov[4].data); + test("iov decrypting", + krb5_c_decrypt_iov(context, keyblock, 7, 0, iov, 5)); + test("Comparing results", + compare_results(&in, &iov[1].data)); + + /* Try again with opaque-key-using variants. */ + test("iov encrypting (k)", + krb5_k_encrypt_iov(context, key, 7, 0, iov, 5)); + assert(iov[1].data.length == in.length); + display("Header", &iov[0].data); + display("Data", &iov[1].data); + display("Padding", &iov[3].data); + display("Trailer", &iov[4].data); + test("iov decrypting", + krb5_k_decrypt_iov(context, key, 7, 0, iov, 5)); + test("Comparing results", + compare_results(&in, &iov[1].data)); + } + + enc_out.ciphertext.length = out.length; + check.length = 2048; + + test ("init_state", + krb5_c_init_state (context, keyblock, 7, &state)); + test ("Encrypting with state", + krb5_c_encrypt (context, keyblock, 7, &state, &in, &enc_out)); + display ("Enc output", &enc_out.ciphertext); + test ("Encrypting again with state", + krb5_c_encrypt (context, keyblock, 7, &state, &in2, &enc_out2)); + display ("Enc output", &enc_out2.ciphertext); + test ("free_state", + krb5_c_free_state (context, keyblock, &state)); + test ("init_state", + krb5_c_init_state (context, keyblock, 7, &state)); + test ("Decrypting with state", + krb5_c_decrypt (context, keyblock, 7, &state, &enc_out, &check)); + test ("Decrypting again with state", + krb5_c_decrypt (context, keyblock, 7, &state, &enc_out2, &check2)); + test ("free_state", + krb5_c_free_state (context, keyblock, &state)); + test ("Comparing", + compare_results (&in, &check)); + test ("Comparing", + compare_results (&in2, &check2)); + + krb5_free_keyblock (context, keyblock); + krb5_k_free_key (context, key); + } + + /* Test the RC4 decrypt fallback from key usage 9 to 8. */ + test ("Initializing an RC4 keyblock", + krb5_init_keyblock (context, ENCTYPE_ARCFOUR_HMAC, 0, &keyblock)); + test ("Generating random RC4 key", + krb5_c_make_random_key (context, ENCTYPE_ARCFOUR_HMAC, keyblock)); + enc_out.ciphertext = out; + krb5_c_encrypt_length (context, keyblock->enctype, in.length, &len); + enc_out.ciphertext.length = len; + check.length = 2048; + test ("Encrypting with RC4 key usage 8", + krb5_c_encrypt (context, keyblock, 8, 0, &in, &enc_out)); + display ("Enc output", &enc_out.ciphertext); + test ("Decrypting with RC4 key usage 9", + krb5_c_decrypt (context, keyblock, 9, 0, &enc_out, &check)); + test ("Comparing", compare_results (&in, &check)); + + krb5_free_keyblock (context, keyblock); + free(out.data); + free(out2.data); + free(check.data); + free(check2.data); + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_fork.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_fork.c new file mode 100644 index 00000000..428fc8a6 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_fork.c @@ -0,0 +1,117 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_fork.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Test basic libk5crypto behavior across forks. This is primarily interesting + * for back ends with PKCS11-based constraints. + */ + +#include "k5-int.h" +#include +#include +#include + +static krb5_context ctx = NULL; + +static void +t(krb5_error_code code) +{ + if (code != 0) { + fprintf(stderr, "Failure: %s\n", krb5_get_error_message(ctx, code)); + exit(1); + } +} + +static void +prepare_enc_data(krb5_key key, size_t in_len, krb5_enc_data *enc_data) +{ + size_t out_len; + + t(krb5_c_encrypt_length(ctx, key->keyblock.enctype, in_len, &out_len)); + t(alloc_data(&enc_data->ciphertext, out_len)); +} + +int +main() +{ + krb5_keyblock kb_aes, kb_rc4; + krb5_key key_aes, key_rc4; + krb5_data state_rc4, plain = string2data("plain"), decrypted; + krb5_enc_data out_aes, out_rc4; + pid_t pid, wpid; + int status; + + /* Seed the PRNG instead of creating a context, so we don't need + * krb5.conf. */ + t(krb5_c_random_seed(ctx, &plain)); + + /* Create AES and RC4 ciphertexts with random keys. Use cipher state for + * RC4. */ + t(krb5_c_make_random_key(ctx, ENCTYPE_AES256_CTS_HMAC_SHA1_96, &kb_aes)); + t(krb5_c_make_random_key(ctx, ENCTYPE_ARCFOUR_HMAC, &kb_rc4)); + t(krb5_k_create_key(ctx, &kb_aes, &key_aes)); + t(krb5_k_create_key(ctx, &kb_rc4, &key_rc4)); + prepare_enc_data(key_aes, plain.length, &out_aes); + prepare_enc_data(key_aes, plain.length, &out_rc4); + t(krb5_c_init_state(ctx, &kb_rc4, 0, &state_rc4)); + t(krb5_k_encrypt(ctx, key_aes, 0, NULL, &plain, &out_aes)); + t(krb5_k_encrypt(ctx, key_rc4, 0, &state_rc4, &plain, &out_rc4)); + + /* Fork; continue in both parent and child. */ + pid = fork(); + assert(pid >= 0); + + /* Decrypt the AES message with both key and keyblock. */ + t(alloc_data(&decrypted, plain.length)); + t(krb5_k_decrypt(ctx, key_aes, 0, NULL, &out_aes, &decrypted)); + assert(data_eq(plain, decrypted)); + t(krb5_c_decrypt(ctx, &kb_aes, 0, NULL, &out_aes, &decrypted)); + assert(data_eq(plain, decrypted)); + + /* Encrypt another RC4 message. */ + t(krb5_k_encrypt(ctx, key_rc4, 0, &state_rc4, &plain, &out_rc4)); + t(krb5_c_free_state(ctx, &kb_rc4, &state_rc4)); + + krb5_free_keyblock_contents(ctx, &kb_aes); + krb5_free_keyblock_contents(ctx, &kb_rc4); + krb5_k_free_key(ctx, key_aes); + krb5_k_free_key(ctx, key_rc4); + krb5_free_data_contents(ctx, &out_aes.ciphertext); + krb5_free_data_contents(ctx, &out_rc4.ciphertext); + krb5_free_data_contents(ctx, &decrypted); + + /* If we're the parent, make sure the child succeeded. */ + if (pid != 0) { + wpid = wait(&status); + assert(wpid == pid); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { + fprintf(stderr, "Child failed with status %d\n", status); + return 1; + } + } + + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_hmac.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_hmac.c new file mode 100644 index 00000000..da359cb4 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_hmac.c @@ -0,0 +1,263 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_hmac.c */ +/* + * Copyright 2001,2002 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Test vectors for HMAC-MD5 and HMAC-SHA1 (placeholder only). + * Tests taken from RFC 2202. + */ + +#include +#include +#include +#include + +#include +#include "crypto_int.h" + +#define ASIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0])) + +const char *whoami; + +static void keyToData (krb5_keyblock *k, krb5_data *d) { + d->length = k->length; + d->data = (char *) k->contents; +} + +static void printd (const char *descr, krb5_data *d) { + unsigned int i, j; + const int r = 16; + + printf("%s (%d bytes):", descr, d->length); + + for (i = 0; i < d->length; i += r) { + printf("\n %04x: ", i); + for (j = i; j < i + r && j < d->length; j++) + printf(" %02x", 0xff & d->data[j]); + for (; j < i + r; j++) + printf(" "); + printf(" "); + for (j = i; j < i + r && j < d->length; j++) { + int c = 0xff & d->data[j]; + printf("%c", isprint(c) ? c : '.'); + } + } + printf("\n"); +} +static void printk(const char *descr, krb5_keyblock *k) { + krb5_data d; + keyToData(k,&d); + printd(descr, &d); +} + + + +struct hmac_test { + int key_len; + unsigned char key[180]; + int data_len; + unsigned char data[80]; + const char *hexdigest; +}; + +static krb5_error_code hmac1(const struct krb5_hash_provider *h, + krb5_keyblock *key, + krb5_data *in, krb5_data *out) +{ + char tmp[40]; + size_t blocksize, hashsize; + krb5_error_code err; + krb5_key k; + krb5_crypto_iov iov; + krb5_data d; + + printk(" test key", key); + blocksize = h->blocksize; + hashsize = h->hashsize; + if (hashsize > sizeof(tmp)) + abort(); + if (key->length > blocksize) { + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data(key->contents, key->length); + d = make_data(tmp, hashsize); + err = h->hash(&iov, 1, &d); + if (err) { + com_err(whoami, err, "hashing key before calling hmac"); + exit(1); + } + key->length = d.length; + key->contents = (krb5_octet *) d.data; + printk(" pre-hashed key", key); + } + printd(" hmac input", in); + krb5_k_create_key(NULL, key, &k); + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *in; + err = krb5int_hmac(h, k, &iov, 1, out); + krb5_k_free_key(NULL, k); + if (err == 0) + printd(" hmac output", out); + return err; +} + +static void test_hmac() +{ + krb5_keyblock key; + krb5_data in, out; + char outbuf[20], *hexdigest; + krb5_error_code err; + unsigned int i; + int lose = 0; + + /* RFC 2202 test vector. */ + static const struct hmac_test md5tests[] = { + { + 16, { + 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, + 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, + }, + 8, "Hi There", + "9294727a3638bb1c13f48ef8158bfc9d" + }, + + { + 4, "Jefe", + 28, "what do ya want for nothing?", + "750c783e6ab0b503eaa86e310a5db738" + }, + + { + 16, { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa + }, + 50, { + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + }, + "56be34521d144c88dbb8c733f0e8b3f6" + }, + + { + 25, { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, + 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x19 + }, + 50, { + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + }, + "697eaf0aca3a3aea3a75164746ffaa79" + }, + + { + 16, { + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c + }, + 20, "Test With Truncation", + "56461ef2342edc00f9bab995690efd4c" + }, + + { + 80, { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + }, + 54, "Test Using Larger Than Block-Size Key - Hash Key First", + "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd" + }, + + { + 80, { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + }, + 73, + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", + "6f630fad67cda0ee1fb1f562db3aa53e" + }, + }; + + for (i = 0; i < sizeof(md5tests)/sizeof(md5tests[0]); i++) { + key.contents = (krb5_octet *)md5tests[i].key; + key.length = md5tests[i].key_len; + in = make_data((char *)md5tests[i].data, md5tests[i].data_len); + + out.data = outbuf; + out.length = 20; + printf("\nTest #%d:\n", i+1); + err = hmac1(&krb5int_hash_md5, &key, &in, &out); + if (err) { + com_err(whoami, err, "computing hmac"); + exit(1); + } + + if (k5_hex_encode(out.data, out.length, FALSE, &hexdigest) != 0) + abort(); + if (strcmp(hexdigest, md5tests[i].hexdigest)) { + printf("*** CHECK FAILED!\n" + "\tReturned: 0x%s.\n" + "\tExpected: 0x%s.\n", hexdigest, md5tests[i].hexdigest); + lose++; + } else + printf("Matches expected result.\n"); + free(hexdigest); + } + + /* Do again with SHA-1 tests.... */ + + if (lose) { + printf("%d failures; exiting.\n", lose); + exit(1); + } +} + + +int main (int argc, char **argv) +{ + whoami = argv[0]; + test_hmac(); + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_kperf.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_kperf.c new file mode 100644 index 00000000..dc73e179 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_kperf.c @@ -0,0 +1,123 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_kperf.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This file contains a harness to measure the performance improvement + * of using the the krb5_k functions (which cache derived keys) over + * the equivalent krb5_c functions which do not. Sample usages: + * + * ./t_kperf ce aes128-cts 10 100000 + * ./t_kperf kv aes256-cts 1024 10000 + * + * The first usage encrypts ('e') a hundred thousand ten-byte blobs + * with aes128-cts, using the non-caching APIs ('c'). The second + * usage verifies ('v') ten thousand checksums over 1K blobs with the + * first available keyed checksum type for aes256-cts, using the + * caching APIs ('k'). Run commands under "time" to measure how much + * time is used by the operations. + */ + +#include "k5-int.h" + +int +main(int argc, char **argv) +{ + krb5_error_code ret; + krb5_keyblock kblock; + krb5_key key; + krb5_enctype enctype; + krb5_cksumtype cktype; + int blocksize, num_blocks, intf, op, i; + size_t outlen, cklen; + krb5_data block; + krb5_enc_data outblock; + krb5_checksum sum; + krb5_boolean val; + + if (argc != 5) { + fprintf(stderr, "Usage: t_kperf {c|k}{e|d|m|v} type size nblocks\n"); + exit(1); + } + intf = argv[1][0]; + assert(intf == 'c' || intf =='k'); + op = argv[1][1]; + ret = krb5_string_to_enctype(argv[2], &enctype); + assert(!ret); + blocksize = atoi(argv[3]); + num_blocks = atoi(argv[4]); + + block.data = "notrandom"; + block.length = 9; + krb5_c_random_seed(NULL, &block); + + krb5_c_make_random_key(NULL, enctype, &kblock); + krb5_k_create_key(NULL, &kblock, &key); + + block.length = blocksize; + block.data = calloc(1, blocksize); + + krb5_c_encrypt_length(NULL, enctype, blocksize, &outlen); + outblock.enctype = enctype; + outblock.ciphertext.length = outlen; + outblock.ciphertext.data = calloc(1, outlen); + + krb5int_c_mandatory_cksumtype(NULL, enctype, &cktype); + krb5_c_checksum_length(NULL, cktype, &cklen); + sum.checksum_type = cktype; + sum.length = cklen; + sum.contents = calloc(1, cklen); + + /* + * Decrypting typically involves copying the output after checking the + * hash, so we need to create a valid ciphertext to correctly measure its + * performance. + */ + if (op == 'd') + krb5_c_encrypt(NULL, &kblock, 0, NULL, &block, &outblock); + + for (i = 0; i < num_blocks; i++) { + if (intf == 'c') { + if (op == 'e') + krb5_c_encrypt(NULL, &kblock, 0, NULL, &block, &outblock); + else if (op == 'd') + krb5_c_decrypt(NULL, &kblock, 0, NULL, &outblock, &block); + else if (op == 'm') + krb5_c_make_checksum(NULL, cktype, &kblock, 0, &block, &sum); + else if (op == 'v') + krb5_c_verify_checksum(NULL, &kblock, 0, &block, &sum, &val); + } else { + if (op == 'e') + krb5_k_encrypt(NULL, key, 0, NULL, &block, &outblock); + else if (op == 'd') + krb5_k_decrypt(NULL, key, 0, NULL, &outblock, &block); + else if (op == 'm') + krb5_k_make_checksum(NULL, cktype, key, 0, &block, &sum); + else if (op == 'v') + krb5_k_verify_checksum(NULL, key, 0, &block, &sum, &val); + } + } + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_mdcksum.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_mdcksum.c new file mode 100644 index 00000000..b34f9a86 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_mdcksum.c @@ -0,0 +1,203 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_mdcksum.c */ +/* + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Test checksum and checksum compatibility for rsa-md[4,5]-des. */ + +#ifndef MD +#define MD 5 +#endif /* MD */ + +#include "k5-int.h" +#if MD == 4 +#include "rsa-md4.h" +#endif /* MD == 4 */ +#if MD == 5 +#include "rsa-md5.h" +#endif /* MD == 5 */ +#include "des_int.h" + +#define MD5_K5BETA_COMPAT +#define MD4_K5BETA_COMPAT + +#if MD == 4 +#define CONFOUNDER_LENGTH RSA_MD4_DES_CONFOUND_LENGTH +#define NEW_CHECKSUM_LENGTH NEW_RSA_MD4_DES_CKSUM_LENGTH +#define OLD_CHECKSUM_LENGTH OLD_RSA_MD4_DES_CKSUM_LENGTH +#define CHECKSUM_TYPE CKSUMTYPE_RSA_MD4_DES +#ifdef MD4_K5BETA_COMPAT +#define K5BETA_COMPAT 1 +#else /* MD4_K5BETA_COMPAT */ +#undef K5BETA_COMPAT +#endif /* MD4_K5BETA_COMPAT */ +#define CKSUM_FUNCTION krb5_md4_crypto_sum_func +#define COMPAT_FUNCTION krb5_md4_crypto_compat_sum_func +#define VERIFY_FUNCTION krb5_md4_crypto_verify_func +#endif /* MD == 4 */ + +#if MD == 5 +#define CONFOUNDER_LENGTH RSA_MD5_DES_CONFOUND_LENGTH +#define NEW_CHECKSUM_LENGTH NEW_RSA_MD5_DES_CKSUM_LENGTH +#define OLD_CHECKSUM_LENGTH OLD_RSA_MD5_DES_CKSUM_LENGTH +#define CHECKSUM_TYPE CKSUMTYPE_RSA_MD5_DES +#ifdef MD5_K5BETA_COMPAT +#define K5BETA_COMPAT 1 +#else /* MD5_K5BETA_COMPAT */ +#undef K5BETA_COMPAT +#endif /* MD5_K5BETA_COMPAT */ +#define CKSUM_FUNCTION krb5_md5_crypto_sum_func +#define COMPAT_FUNCTION krb5_md5_crypto_compat_sum_func +#define VERIFY_FUNCTION krb5_md5_crypto_verify_func +#endif /* MD == 5 */ + +static void +print_checksum(text, number, message, checksum) + char *text; + int number; + char *message; + krb5_checksum *checksum; +{ + int i; + + printf("%s MD%d checksum(\"%s\") = ", text, number, message); + for (i=0; ilength; i++) + printf("%02x", checksum->contents[i]); + printf("\n"); +} + +/* + * Test the checksum verification of Old Style (tm) and correct RSA-MD[4,5]-DES + * checksums. + */ +int +main(argc, argv) + int argc; + char **argv; +{ + int msgindex; + krb5_context kcontext; + krb5_encrypt_block encblock; + krb5_keyblock keyblock; + krb5_error_code kret; + krb5_checksum oldstyle_checksum; + krb5_checksum newstyle_checksum; + krb5_data pwdata; + char *pwd; + + pwd = "test password"; + pwdata.length = strlen(pwd); + pwdata.data = pwd; + krb5_use_enctype(kcontext, &encblock, DEFAULT_KDC_ENCTYPE); + if ((kret = mit_des_string_to_key(&encblock, &keyblock, &pwdata, NULL))) { + printf("mit_des_string_to_key choked with %d\n", kret); + return(kret); + } + if ((kret = mit_des_process_key(&encblock, &keyblock))) { + printf("mit_des_process_key choked with %d\n", kret); + return(kret); + } + + oldstyle_checksum.length = OLD_CHECKSUM_LENGTH; + if (!(oldstyle_checksum.contents = (krb5_octet *) malloc(OLD_CHECKSUM_LENGTH))) { + printf("cannot get memory for old style checksum\n"); + return(ENOMEM); + } + newstyle_checksum.length = NEW_CHECKSUM_LENGTH; + if (!(newstyle_checksum.contents = (krb5_octet *) + malloc(NEW_CHECKSUM_LENGTH))) { + printf("cannot get memory for new style checksum\n"); + return(ENOMEM); + } + for (msgindex = 1; msgindex < argc; msgindex++) { + if ((kret = CKSUM_FUNCTION(argv[msgindex], + strlen(argv[msgindex]), + (krb5_pointer) keyblock.contents, + keyblock.length, + &newstyle_checksum))) { + printf("krb5_calculate_checksum choked with %d\n", kret); + break; + } + print_checksum("correct", MD, argv[msgindex], &newstyle_checksum); +#ifdef K5BETA_COMPAT + if ((kret = COMPAT_FUNCTION(argv[msgindex], + strlen(argv[msgindex]), + (krb5_pointer) keyblock.contents, + keyblock.length, + &oldstyle_checksum))) { + printf("old style calculate_checksum choked with %d\n", kret); + break; + } + print_checksum("old", MD, argv[msgindex], &oldstyle_checksum); +#endif /* K5BETA_COMPAT */ + if ((kret = VERIFY_FUNCTION(&newstyle_checksum, + argv[msgindex], + strlen(argv[msgindex]), + (krb5_pointer) keyblock.contents, + keyblock.length))) { + printf("verify on new checksum choked with %d\n", kret); + break; + } + printf("Verify succeeded for \"%s\"\n", argv[msgindex]); +#ifdef K5BETA_COMPAT + if ((kret = VERIFY_FUNCTION(&oldstyle_checksum, + argv[msgindex], + strlen(argv[msgindex]), + (krb5_pointer) keyblock.contents, + keyblock.length))) { + printf("verify on old checksum choked with %d\n", kret); + break; + } + printf("Compatible checksum verify succeeded for \"%s\"\n", + argv[msgindex]); +#endif /* K5BETA_COMPAT */ + newstyle_checksum.contents[0]++; + if (!(kret = VERIFY_FUNCTION(&newstyle_checksum, + argv[msgindex], + strlen(argv[msgindex]), + (krb5_pointer) keyblock.contents, + keyblock.length))) { + printf("verify on new checksum should have choked\n"); + break; + } + printf("Verify of bad checksum OK for \"%s\"\n", argv[msgindex]); +#ifdef K5BETA_COMPAT + oldstyle_checksum.contents[0]++; + if (!(kret = VERIFY_FUNCTION(&oldstyle_checksum, + argv[msgindex], + strlen(argv[msgindex]), + (krb5_pointer) keyblock.contents, + keyblock.length))) { + printf("verify on old checksum should have choked\n"); + break; + } + printf("Compatible checksum verify of altered checksum OK for \"%s\"\n", + argv[msgindex]); +#endif /* K5BETA_COMPAT */ + kret = 0; + } + if (!kret) + printf("%d tests passed successfully for MD%d checksum\n", argc-1, MD); + return(kret); +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_mddriver.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_mddriver.c new file mode 100644 index 00000000..ad65d031 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_mddriver.c @@ -0,0 +1,256 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_mddriver.c - test driver for MD2, MD4 and MD5 */ +/* + * Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All + * rights reserved. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + */ + +/* The following makes MD default to MD5 if it has not already been + defined with C compiler flags. +*/ +#ifndef MD +#define MD 5 +#endif + +#include "crypto_int.h" + +/* Length of test block, number of test blocks. + */ +#define TEST_BLOCK_LEN 1000 +#define TEST_BLOCK_COUNT 1000 + +static void MDHash (char *, size_t, size_t, unsigned char *); +static void MDString (char *); +static void MDTimeTrial (void); +static void MDTestSuite (void); +static void MDPrint (unsigned char [16]); + +struct md_test_entry { + char *string; + unsigned char digest[16]; +}; + +#if MD == 4 +#define MDProvider krb5int_hash_md4 + +#define HAVE_TEST_SUITE +/* Test suite from RFC 1320 */ + +struct md_test_entry md_test_suite[] = { + { "", + {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31, + 0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0 }}, + { "a", + {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46, + 0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24 }}, + { "abc", + {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52, + 0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d }}, + { "message digest", + {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8, + 0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b }}, + { "abcdefghijklmnopqrstuvwxyz", + {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd, + 0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9 }}, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35, + 0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4 }}, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19, + 0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36 }}, + {0, {0}} +}; + +#endif + +#if MD == 5 +#define MDProvider krb5int_hash_md5 + +#define HAVE_TEST_SUITE +/* Test suite from RFC 1321 */ + +struct md_test_entry md_test_suite[] = { + { "", + {0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, + 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e }}, + { "a", + {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, + 0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 }}, + { "abc", + {0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, + 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 }}, + { "message digest", + {0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, + 0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 }}, + { "abcdefghijklmnopqrstuvwxyz", + {0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, + 0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b }}, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + {0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, + 0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f }}, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890", + {0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, + 0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a }}, + { 0, {0} } +}; + +#endif + +/* Main driver. + + Arguments (may be any combination): + -sstring - digests string + -t - runs time trial + -x - runs test script +*/ +int main (argc, argv) + int argc; + char *argv[]; +{ + int i; + + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-' && argv[i][1] == 's') + MDString (argv[i] + 2); + else if (strcmp (argv[i], "-t") == 0) + MDTimeTrial (); + else if (strcmp (argv[i], "-x") == 0) + MDTestSuite (); + } + return (0); +} + +static void MDHash (bytes, len, count, out) + char *bytes; + size_t len, count; + unsigned char *out; +{ + krb5_crypto_iov *iov; + krb5_data outdata = make_data (out, MDProvider.hashsize); + size_t i; + + iov = malloc (count * sizeof(*iov)); + if (iov == NULL) + abort (); + for (i = 0; i < count; i++) { + iov[i].flags = KRB5_CRYPTO_TYPE_DATA; + iov[i].data = make_data (bytes, len); + } + MDProvider.hash(iov, count, &outdata); + free(iov); +} + +/* Digests a string and prints the result. + */ +static void MDString (string) + char *string; +{ + unsigned char digest[16]; + + MDHash (string, strlen(string), 1, digest); + printf ("MD%d (\"%s\") = ", MD, string); + MDPrint (digest); + printf ("\n"); +} + +/* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte + blocks. +*/ +static void MDTimeTrial () +{ + time_t endTime, startTime; + unsigned char block[TEST_BLOCK_LEN], digest[16]; + unsigned int i; + + printf("MD%d time trial. Digesting %d %d-byte blocks ...", MD, + TEST_BLOCK_LEN, TEST_BLOCK_COUNT); + + /* Initialize block */ + for (i = 0; i < TEST_BLOCK_LEN; i++) + block[i] = (unsigned char)(i & 0xff); + + /* Start timer */ + time (&startTime); + + /* Digest blocks */ + MDHash ((char *)block, TEST_BLOCK_LEN, TEST_BLOCK_COUNT, digest); + + /* Stop timer */ + time (&endTime); + + printf (" done\n"); + printf ("Digest = "); + MDPrint (digest); + printf ("\nTime = %ld seconds\n", (long)(endTime-startTime)); + printf + ("Speed = %ld bytes/second\n", + (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime)); +} + +/* Digests a reference suite of strings and prints the results. + */ +static void MDTestSuite () +{ +#ifdef HAVE_TEST_SUITE + struct md_test_entry *entry; + int num_tests = 0, num_failed = 0; + unsigned char digest[16]; + + printf ("MD%d test suite:\n\n", MD); + for (entry = md_test_suite; entry->string; entry++) { + unsigned int len = strlen (entry->string); + + MDHash (entry->string, len, 1, digest); + + printf ("MD%d (\"%s\") = ", MD, entry->string); + MDPrint (digest); + printf ("\n"); + if (memcmp(digest, entry->digest, 16) != 0) { + printf("\tIncorrect MD%d digest! Should have been:\n\t\t ", MD); + MDPrint(entry->digest); + printf("\n"); + num_failed++; + } + num_tests++; + } + if (num_failed) { + printf("%d out of %d tests failed for MD%d!!!\n", num_failed, + num_tests, MD); + exit(1); + } else { + printf ("%d tests passed successfully for MD%d.\n", num_tests, MD); + exit(0); + } +#else + + printf ("MD%d test suite:\n", MD); + MDString (""); + MDString ("a"); + MDString ("abc"); + MDString ("message digest"); + MDString ("abcdefghijklmnopqrstuvwxyz"); + MDString + ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); + MDString + ("12345678901234567890123456789012345678901234567890123456789012345678901234567890"); +#endif +} + +/* Prints a message digest in hexadecimal. + */ +static void MDPrint (digest) + unsigned char digest[16]; +{ + unsigned int i; + + for (i = 0; i < 16; i++) + printf ("%02x", digest[i]); +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_nfold.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_nfold.c new file mode 100644 index 00000000..b94353c2 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_nfold.c @@ -0,0 +1,160 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_nfold.c - Test nfold implementation correctness */ +/* + * Copyright 1988, 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include +#include + +#include "crypto_int.h" + +#define ASIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0])) + +static void printhex (size_t len, const unsigned char *p) +{ + while (len--) + printf ("%02x", 0xff & *p++); +} + +static void printstringhex (const unsigned char *p) { + printhex (strlen ((const char *) p), p); +} + +static void rfc_tests () +{ + unsigned i; + struct { + char *input; + unsigned int n; + unsigned char exp[192/8]; + } tests[] = { + { "012345", 64, + { 0xbe,0x07,0x26,0x31,0x27,0x6b,0x19,0x55, } + }, + { "password", 56, + { 0x78,0xa0,0x7b,0x6c,0xaf,0x85,0xfa, } + }, + { "Rough Consensus, and Running Code", 64, + { 0xbb,0x6e,0xd3,0x08,0x70,0xb7,0xf0,0xe0, } + }, + { "password", 168, + { 0x59,0xe4,0xa8,0xca,0x7c,0x03,0x85,0xc3, + 0xc3,0x7b,0x3f,0x6d,0x20,0x00,0x24,0x7c, + 0xb6,0xe6,0xbd,0x5b,0x3e, } + }, + { "MASSACHVSETTS INSTITVTE OF TECHNOLOGY", 192, + { 0xdb,0x3b,0x0d,0x8f,0x0b,0x06,0x1e,0x60, + 0x32,0x82,0xb3,0x08,0xa5,0x08,0x41,0x22, + 0x9a,0xd7,0x98,0xfa,0xb9,0x54,0x0c,0x1b, } + }, + }; + unsigned char outbuf[192/8]; + + printf ("RFC tests:\n"); + for (i = 0; i < ASIZE (tests); i++) { + unsigned char *p = (unsigned char *) tests[i].input; + assert (tests[i].n / 8 <= sizeof (outbuf)); + krb5int_nfold (8 * strlen ((char *) p), p, tests[i].n, outbuf); + printf ("%d-fold(\"%s\") =\n", tests[i].n, p); + printf ("%d-fold(", tests[i].n); + printstringhex (p); + printf (") =\n\t"); + printhex (tests[i].n / 8, outbuf); + printf ("\n\n"); + if (memcmp (outbuf, tests[i].exp, tests[i].n/8) != 0) { + printf ("wrong value! expected:\n\t"); + printhex (tests[i].n / 8, tests[i].exp); + exit (1); + } + } +} + +static void fold_kerberos(unsigned int nbytes) +{ + unsigned char cipher_text[300]; + unsigned int j; + + if (nbytes > 300) + abort(); + + printf("%d-fold(\"kerberos\") =\n\t", nbytes*8); + krb5int_nfold(64, (unsigned char *) "kerberos", 8*nbytes, cipher_text); + for (j=0; jlength, d->data); +} + +static void test_pbkdf2_rfc3211() +{ + char x[100]; + krb5_error_code err; + krb5_data d, pass, salt; + int i; + + /* RFC 3211 test cases. */ + static const struct { + const char *pass; + const char *salt; + unsigned int count; + size_t len; + const unsigned char expected[24]; + } t[] = { + { "password", "\x12\x34\x56\x78\x78\x56\x34\x12", 5, 8, + { 0xD1, 0xDA, 0xA7, 0x86, 0x15, 0xF2, 0x87, 0xE6 } }, + { "All n-entities must communicate with other " + "n-entities via n-1 entiteeheehees", + "\x12\x34\x56\x78\x78\x56\x34\x12", 500, 24, + { 0x6A, 0x89, 0x70, 0xBF, 0x68, 0xC9, 0x2C, 0xAE, + 0xA8, 0x4A, 0x8D, 0xF2, 0x85, 0x10, 0x85, 0x86, + 0x07, 0x12, 0x63, 0x80, 0xCC, 0x47, 0xAB, 0x2D } }, + }; + + d.data = x; + printf("RFC 3211 test of PBKDF#2\n"); + + for (i = 0; i < sizeof(t)/sizeof(t[0]); i++) { + + printf("pkbdf2(iter_count=%d, dklen=%d (%d bytes), salt=12 34 56 78 78 56 34 12,\n" + " pass=%s):\n ->", + t[i].count, t[i].len * 8, t[i].len, t[i].pass); + + d.length = t[i].len; + pass.data = t[i].pass; + pass.length = strlen(pass.data); + salt.data = t[i].salt; + salt.length = strlen(salt.data); + err = krb5int_pbkdf2_hmac_sha1 (&d, t[i].count, &pass, &salt); + if (err) { + printf("error in computing pbkdf2: %s\n", error_message(err)); + exit(1); + } + printdata(&d); + if (!memcmp(x, t[i].expected, t[i].len)) + printf("\nTest passed.\n\n"); + else { + printf("\n*** CHECK FAILED!\n"); + exit(1); + } + } +} + +int main () +{ + test_pbkdf2_rfc3211(); + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_prf.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_prf.c new file mode 100644 index 00000000..d9877bd1 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_prf.c @@ -0,0 +1,149 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_prf.c - PRF test cases */ +/* + * Copyright (C) 2015 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. + */ + +#include "k5-int.h" + +struct test { + krb5_enctype enctype; + krb5_data keybits; + krb5_data prf_input; + krb5_data expected; +} tests[] = { + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + { KV5M_DATA, 16, + "\xAE\x27\x2E\x7C\xDE\xC8\x6A\xC5\x13\x8C\xDB\x19\x6D\x8E\x29\x7D" }, + { KV5M_DATA, 2, "\x01\x61" }, + { KV5M_DATA, 16, + "\x77\xB3\x9A\x37\xA8\x68\x92\x0F\x2A\x51\xF9\xDD\x15\x0C\x57\x17" } + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + { KV5M_DATA, 16, + "\x67\xAB\x1C\xFE\xF3\x5E\x4C\x27\xFF\xDE\xAC\x60\x38\x5A\x3E\x9C" }, + { KV5M_DATA, 2, "\x01\x62" }, + { KV5M_DATA, 16, + "\xE0\x6C\x0D\xD3\x1F\xF0\x20\x91\x99\x4F\x2E\xF5\x17\x8B\xFE\x3D" } + }, + + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + { KV5M_DATA, 32, + "\xC0\x1F\x15\x72\x11\xF7\xB7\x7E\xAA\xF4\x57\xC3\xE1\x56\x69\x01" + "\x27\xEE\x12\x7D\x81\x0B\xA6\x39\x2E\x97\xBA\xA2\x43\xEB\x06\x16" }, + { KV5M_DATA, 2, "\x01\x61" }, + { KV5M_DATA, 16, + "\xB2\x62\x8C\x78\x8E\x2E\x9C\x4A\x9B\xB4\x64\x46\x78\xC2\x9F\x2F" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + { KV5M_DATA, 32, + "\xC0\x1F\x15\x72\x11\xF7\xB7\x7E\xAA\xF4\x57\xC3\xE1\x56\x69\x01" + "\x27\xEE\x12\x7D\x81\x0B\xA6\x39\x2E\x97\xBA\xA2\x43\xEB\x06\x16" }, + { KV5M_DATA, 2, "\x02\x61" }, + { KV5M_DATA, 16, + "\xB4\x06\x37\x33\x50\xCE\xE8\xA6\x12\x6F\x4A\x9B\x65\xA0\xCD\x21" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + { KV5M_DATA, 32, + "\x9D\x52\x0D\x2D\x98\x0A\xA7\xCB\x6B\x69\x36\x82\xB6\x2D\xA2\x58" + "\xB3\x33\x86\x79\x51\x64\x2C\xE6\x47\xAE\x62\xB1\xE5\xE0\xB5\xE9" }, + { KV5M_DATA, 2, "\x01\x62" }, + { KV5M_DATA, 16, + "\xFF\x0E\x28\x9E\xA7\x56\xC0\x55\x9A\x0E\x91\x18\x56\x96\x1A\x49" } + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + { KV5M_DATA, 32, + "\x9D\x52\x0D\x2D\x98\x0A\xA7\xCB\x6B\x69\x36\x82\xB6\x2D\xA2\x58" + "\xB3\x33\x86\x79\x51\x64\x2C\xE6\x47\xAE\x62\xB1\xE5\xE0\xB5\xE9" }, + { KV5M_DATA, 2, "\x02\x62" }, + { KV5M_DATA, 16, + "\x0D\x67\x4D\xD0\xF9\xA6\x80\x65\x25\xA4\xD9\x2E\x82\x8B\xD1\x5A" } + }, + + { + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + { KV5M_DATA, 16, + "\x37\x05\xD9\x60\x80\xC1\x77\x28\xA0\xE8\x00\xEA\xB6\xE0\xD2\x3C" }, + { KV5M_DATA, 4, "test" }, + { KV5M_DATA, 32, + "\x9D\x18\x86\x16\xF6\x38\x52\xFE\x86\x91\x5B\xB8\x40\xB4\xA8\x86" + "\xFF\x3E\x6B\xB0\xF8\x19\xB4\x9B\x89\x33\x93\xD3\x93\x85\x42\x95" } + }, + + { + ENCTYPE_AES256_CTS_HMAC_SHA384_192, + { KV5M_DATA, 32, + "\x6D\x40\x4D\x37\xFA\xF7\x9F\x9D\xF0\xD3\x35\x68\xD3\x20\x66\x98" + "\x00\xEB\x48\x36\x47\x2E\xA8\xA0\x26\xD1\x6B\x71\x82\x46\x0C\x52" }, + { KV5M_DATA, 4, "test" }, + { KV5M_DATA, 48, + "\x98\x01\xF6\x9A\x36\x8C\x2B\xF6\x75\xE5\x95\x21\xE1\x77\xD9\xA0" + "\x7F\x67\xEF\xE1\xCF\xDE\x8D\x3C\x8D\x6F\x6A\x02\x56\xE3\xB1\x7D" + "\xB3\xC1\xB6\x2A\xD1\xB8\x55\x33\x60\xD1\x73\x67\xEB\x15\x14\xD2" } + }, +}; + +int +main() +{ + krb5_error_code ret; + krb5_data output; + krb5_keyblock kb; + size_t i, prfsz; + const struct test *test; + + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { + test = &tests[i]; + kb.magic = KV5M_KEYBLOCK; + kb.enctype = test->enctype; + kb.length = test->keybits.length; + kb.contents = (uint8_t *)test->keybits.data; + + ret = krb5_c_prf_length(NULL, test->enctype, &prfsz); + assert(!ret); + ret = alloc_data(&output, prfsz); + assert(!ret); + ret = krb5_c_prf(NULL, &kb, &tests[i].prf_input, &output); + assert(!ret); + + if (!data_eq(output, tests[i].expected)) { + printf("Test %d failed\n", (int)i); + exit(1); + } + free(output.data); + } + + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_prng.comments b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_prng.comments new file mode 100644 index 00000000..1666b706 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_prng.comments @@ -0,0 +1,14 @@ +Things this test tries to do: +*adding data +* getting random data +* adding more data but not enough for reseed +*getting more random data +*adding enough to trigger a reseed +*getting more random data +* getting random data without a reseed inbetween +* getting enough data to trigger a gate + + +If you adjust the blocksize or the seeding parameters then this test +should be adjusted. + diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_prng.expected b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_prng.expected new file mode 100644 index 00000000..f7f16505 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_prng.expected @@ -0,0 +1,4 @@ +d2f8fbd707a8ece5cb11a02f +eb4cb6e06236ea1c0529f7acbfca8d78cb85bb1d +a244005ae870604342b0386025874ec4306c1dd483c118621b +63e6408afdf9fd225839a7afcc6da6ae494fb4f82bd21ea06bb17ca0848bdae8cea671f545aac52699951caba960c536024b4102f47d61d61fd7b17582a4cf50ba7d215062558f71483249e079689893f3bf25def7f45f9e852281269904d401d6719e3115f6410088c6c5171e878494362684d2116633bb9ea8d9ed5faec73cb076c44d5d639bc2c8ae3de54f0e1e092d5ea439e607e9cd73053bbdf40723f5b48f298fdeeef845e22e06f2f6362fc67fba366e638a7988999d456dcc3d53b23388d685620a7c446d28cd94b13049761b64779db5412e78ac4bab2aacf103fd1b9ceb7213d43710d6a46fd4223fa20e0a68d3e16a82cbadea650ba815dc9ee99b4eb8e2acdac866a05d90ab9de3246db0560fb4b36633bb642c3ea9bf358937dda743f9cef1148791c2cac58995b8eb8fdb1c0cce1686e04ebef5ae7aae36691faafbe8920d3c013f125b687eb019faefa70fc750c52e2e2e33f426824bf1da31268a9bb8d9501f2290375755f8bf77b46639346b4011b78ce9d81105c7791ec5991a2f1eab037488b604df1a21c5c4e36a7c76dca5884d36e30fe8d30d0e7d93fab72062219390655eace2b434b0e2cd21ec9c5a8aa13e783afadcdf386fc43b960c518acb38d7e3da2f67695c1c1c25c4f251b40f4c2e42e89f6f642c32e66159f6ce24aa910fb5d95e3a899a4de5efcf570996e1a662d14362b65d00524df79cd56be93bd572526e4dfd1cf9f7586bc021105cf5456b28c1f45a6d354d000a113e15f64aa0b5253830c07afc8fa47b58dbba8bbae1645b2093035f2387036229dec6f7141b444b8bb7d0382a742bd5c746ba2d7af3af1cadb2dd90bda87d5daed2d2eebd243c7b2d06955d0cc7fe1061d4cfa3b061aaeb97084d9f9a7ec9dbe9e642f4f090d57b5ea1bd8b393f00896d3dc7089e1fc4c2fed7336c2a8c6d119a682c6cc4ae1ccedd30292f2c5570bf4d6287ce8e20b8b34e7fc38e87273f588cd33b8c913defaee5f6bf8fdeda72531c845a6f97a84d5e9b9a6497d4c48614dee7693df35faedc008fded852be8d4bffd475476336e54ed48a827b99d3f0e39019a40d43aef5ae522ec6e280f6a8e7d2713f3c3188bed2476a84af5a5afefa0fa178ed07de0e073693e8790f8bbd0cf9183e48f140b556e723565c382cf7a4c186748189a14e603e4ac70e2b80c266334231207721d16d834a973b48cfec584620624686603cfd66d55dbf8dd8eccd99d85f041c624ec3a7bec314af95d2313afd43cc5cc19249cf85b7ab0b5a4530b597341e7477b249fef1a07eb0d8fa790e9bce752e8b2f7086e98ab44751e0a1b37f29682ce67c0de7a2fd036f26ed719fc343bbf49432aec651d884c99c24d5943c747f7ec3b48d4c2236a8cb6151794daeda073774cc88ff121fdd423b81ef2f34c8f281ca2e5366faee87ff7a623484f2937cc0680ed76ead32b43cb6c67a21f8089b435f38a404d267397c6435cfac16591a3573d9e92f8c4a8028719c22662b903ddb16e08ea7bb2d6b8938c06bdddb4d174c7f2c5d812ed3a34ba8859a1ae841b3b9d5522372018c9aa55b048df826f05a087f185808cb66899f320783a1c4aa2dcd5f2665405ba7e5726e122b67559a39da30956e49fe7711d1b2506e159c5ea42ce0a1ad497220ee3b3e5ebcb73db975bd08e8be56e5f4533b8295b10d4b0fef466de6540f8fe10530c9716d83a12f5ffbba5b4dbc50ed89388d04e7a15d3d9d251041ed5303efa2525bc62a5aeb821f7838676811784584534be8a7fc667f09c3fe1bbf7d0aad29324f562086ecb8326829413867 diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_prng.seed b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_prng.seed new file mode 100644 index 00000000..79f4f645 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_prng.seed @@ -0,0 +1,25 @@ +2 +20 + c9 72 2b e4 90 e1 fa 4b da d4 2f 43 0d dd d9 91 + 39 d0 23 c4 +0 +1 +24 + 87 1c 4f d4 4a 8b b8 cf 54 4e eb 9b 1f bb 7a 8e + 9a 7d 8d 62 + ca 41 18 00 +12 +0 +0 +20 +1 +24 + 28 d4 bd d4 81 85 ca 70 d5 f0 e4 a4 f3 45 80 01 + 6a 34 79 69 0e e0 cd 21 +25 +2 +40 + de 7c f0 c5 6a 37 0b 34 f4 0c 3a 19 31 eb 66 f1 + ae 5f c6 a3 64 3f 2e a9 76 e1 87 93 df b6 94 86 + bd 96 57 3f 31 e6 88 8c +1290 diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_sha2.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_sha2.c new file mode 100644 index 00000000..e6fa5849 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_sha2.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 +#include "crypto_int.h" + +#define ONE_MILLION_A "one million a's" + +struct test { + char *str; + unsigned char hash[64]; +}; + +struct test sha256_tests[] = { + { "abc", + { 0xba,0x78,0x16,0xbf,0x8f,0x01,0xcf,0xea, + 0x41,0x41,0x40,0xde,0x5d,0xae,0x22,0x23, + 0xb0,0x03,0x61,0xa3,0x96,0x17,0x7a,0x9c, + 0xb4,0x10,0xff,0x61,0xf2,0x00,0x15,0xad }}, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { 0x24,0x8d,0x6a,0x61,0xd2,0x06,0x38,0xb8, + 0xe5,0xc0,0x26,0x93,0x0c,0x3e,0x60,0x39, + 0xa3,0x3c,0xe4,0x59,0x64,0xff,0x21,0x67, + 0xf6,0xec,0xed,0xd4,0x19,0xdb,0x06,0xc1 }}, + { ONE_MILLION_A, + { 0xcd,0xc7,0x6e,0x5c,0x99,0x14,0xfb,0x92, + 0x81,0xa1,0xc7,0xe2,0x84,0xd7,0x3e,0x67, + 0xf1,0x80,0x9a,0x48,0xa4,0x97,0x20,0x0e, + 0x04,0x6d,0x39,0xcc,0xc7,0x11,0x2c,0xd0 }}, + { NULL } +}; + +struct test sha384_tests[] = { + { "abc", + { 0xcb,0x00,0x75,0x3f,0x45,0xa3,0x5e,0x8b, + 0xb5,0xa0,0x3d,0x69,0x9a,0xc6,0x50,0x07, + 0x27,0x2c,0x32,0xab,0x0e,0xde,0xd1,0x63, + 0x1a,0x8b,0x60,0x5a,0x43,0xff,0x5b,0xed, + 0x80,0x86,0x07,0x2b,0xa1,0xe7,0xcc,0x23, + 0x58,0xba,0xec,0xa1,0x34,0xc8,0x25,0xa7 }}, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno" + "ijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + { 0x09,0x33,0x0c,0x33,0xf7,0x11,0x47,0xe8, + 0x3d,0x19,0x2f,0xc7,0x82,0xcd,0x1b,0x47, + 0x53,0x11,0x1b,0x17,0x3b,0x3b,0x05,0xd2, + 0x2f,0xa0,0x80,0x86,0xe3,0xb0,0xf7,0x12, + 0xfc,0xc7,0xc7,0x1a,0x55,0x7e,0x2d,0xb9, + 0x66,0xc3,0xe9,0xfa,0x91,0x74,0x60,0x39 }}, + { ONE_MILLION_A, + { 0x9d,0x0e,0x18,0x09,0x71,0x64,0x74,0xcb, + 0x08,0x6e,0x83,0x4e,0x31,0x0a,0x4a,0x1c, + 0xed,0x14,0x9e,0x9c,0x00,0xf2,0x48,0x52, + 0x79,0x72,0xce,0xc5,0x70,0x4c,0x2a,0x5b, + 0x07,0xb8,0xb3,0xdc,0x38,0xec,0xc4,0xeb, + 0xae,0x97,0xdd,0xd8,0x7f,0x3d,0x89,0x85 }}, + { NULL } +}; + +static int +hash_test(const struct krb5_hash_provider *hash, struct test *tests) +{ + struct test *t; + krb5_crypto_iov iov, *iovs; + krb5_data hval; + size_t i; + + if (alloc_data(&hval, hash->hashsize)) + abort(); + for (t = tests; t->str; ++t) { + if (strcmp(t->str, ONE_MILLION_A) == 0) { + /* Hash a million 'a's using a thousand iovs. */ + iovs = calloc(1000, sizeof(*iovs)); + assert(iovs != NULL); + for (i = 0; i < 1000; i++) { + iovs[i].flags = KRB5_CRYPTO_TYPE_DATA; + if (alloc_data(&iovs[i].data, 1000) != 0) + abort(); + memset(iovs[i].data.data, 'a', 1000); + } + if (hash->hash(iovs, 1000, &hval) != 0) + abort(); + if (memcmp(hval.data, t->hash, hval.length) != 0) + abort(); + for (i = 0; i < 1000; i++) + free(iovs[i].data.data); + free(iovs); + } else { + /* Hash the input in the test. */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = string2data(t->str); + if (hash->hash(&iov, 1, &hval) != 0) + abort(); + if (memcmp(hval.data, t->hash, hval.length) != 0) + abort(); + + if (hash == &krb5int_hash_sha256) { + /* Try again using k5_sha256(). */ + if (k5_sha256(&iov.data, 1, (uint8_t *)hval.data) != 0) + abort(); + if (memcmp(hval.data, t->hash, hval.length) != 0) + abort(); + } + } + } + free(hval.data); + return 0; +} + +int +main() +{ + hash_test(&krb5int_hash_sha256, sha256_tests); + hash_test(&krb5int_hash_sha384, sha384_tests); + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_short.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_short.c new file mode 100644 index 00000000..d4c2b97d --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_short.c @@ -0,0 +1,130 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_short.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Tests the outcome of decrypting overly short tokens. This program can be + * run under a tool like valgrind to detect bad memory accesses; when run + * normally by the test suite, it verifies that each operation returns + * KRB5_BAD_MSIZE. + */ + +#include "k5-int.h" + +krb5_enctype interesting_enctypes[] = { + ENCTYPE_DES3_CBC_SHA1, + ENCTYPE_ARCFOUR_HMAC, + ENCTYPE_ARCFOUR_HMAC_EXP, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_CAMELLIA128_CTS_CMAC, + ENCTYPE_CAMELLIA256_CTS_CMAC, + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + ENCTYPE_AES256_CTS_HMAC_SHA384_192, + 0 +}; + +/* Abort if an operation unexpectedly fails. */ +static void +x(krb5_error_code code) +{ + if (code != 0) + abort(); +} + +/* Abort if a decrypt operation doesn't have the expected result. */ +static void +check_decrypt_result(krb5_error_code code, size_t len, size_t min_len) +{ + if (len < min_len) { + /* Undersized tokens should always result in BAD_MSIZE. */ + if (code != KRB5_BAD_MSIZE) + abort(); + } else { + /* Min-size tokens should succeed or fail the integrity check. */ + if (code != 0 && code != KRB5KRB_AP_ERR_BAD_INTEGRITY) + abort(); + } +} + +static void +test_enctype(krb5_enctype enctype) +{ + krb5_error_code ret; + krb5_keyblock keyblock; + krb5_enc_data input; + krb5_data output; + krb5_crypto_iov iov[2]; + unsigned int dummy; + size_t min_len, len; + + printf("Testing enctype %d\n", (int) enctype); + x(krb5_c_encrypt_length(NULL, enctype, 0, &min_len)); + x(krb5_c_make_random_key(NULL, enctype, &keyblock)); + input.enctype = enctype; + + /* Try each length up to the minimum length. */ + for (len = 0; len <= min_len; len++) { + input.ciphertext.data = calloc(len, 1); + input.ciphertext.length = len; + output.data = calloc(len, 1); + output.length = len; + + /* Attempt a normal decryption. */ + ret = krb5_c_decrypt(NULL, &keyblock, 0, NULL, &input, &output); + check_decrypt_result(ret, len, min_len); + + if (krb5_c_crypto_length(NULL, enctype, KRB5_CRYPTO_TYPE_HEADER, + &dummy) == 0) { + /* Attempt an IOV stream decryption. */ + iov[0].flags = KRB5_CRYPTO_TYPE_STREAM; + iov[0].data = input.ciphertext; + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data.data = NULL; + iov[1].data.length = 0; + ret = krb5_c_decrypt_iov(NULL, &keyblock, 0, NULL, iov, 2); + check_decrypt_result(ret, len, min_len); + } + + free(input.ciphertext.data); + free(output.data); + } + krb5int_c_free_keyblock_contents (NULL, &keyblock); + +} + +int +main(int argc, char **argv) +{ + int i; + krb5_data notrandom; + + notrandom.data = "notrandom"; + notrandom.length = 9; + krb5_c_random_seed(NULL, ¬random); + for (i = 0; interesting_enctypes[i]; i++) + test_enctype(interesting_enctypes[i]); + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/t_str2key.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_str2key.c new file mode 100644 index 00000000..cdb1acc6 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/t_str2key.c @@ -0,0 +1,514 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/t_str2key.c - String-to-key test vectors */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +struct test { + krb5_enctype enctype; + char *string; + krb5_data salt; + krb5_data params; + krb5_data expected_key; + krb5_error_code expected_err; + krb5_boolean allow_weak; +} test_cases[] = { + /* Test vectors from RFC 3961 appendix A.4. */ + { + ENCTYPE_DES3_CBC_SHA1, + "password", + { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 0, NULL }, + { KV5M_DATA, 24, "\x85\x0B\xB5\x13\x58\x54\x8C\xD0\x5E\x86\x76\x8C" + "\x31\x3E\x3B\xFE\xF7\x51\x19\x37\xDC\xF7\x2C\x3E" }, + 0, + FALSE + }, + { + ENCTYPE_DES3_CBC_SHA1, + "potatoe", + { KV5M_DATA, 19, "WHITEHOUSE.GOVdanny" }, + { KV5M_DATA, 0, NULL }, + { KV5M_DATA, 24, "\xDF\xCD\x23\x3D\xD0\xA4\x32\x04\xEA\x6D\xC4\x37" + "\xFB\x15\xE0\x61\xB0\x29\x79\xC1\xF7\x4F\x37\x7A" }, + 0, + FALSE + }, + { + ENCTYPE_DES3_CBC_SHA1, + "penny", + { KV5M_DATA, 19, "EXAMPLE.COMbuckaroo" }, + { KV5M_DATA, 0, NULL }, + { KV5M_DATA, 24, "\x6D\x2F\xCD\xF2\xD6\xFB\xBC\x3D\xDC\xAD\xB5\xDA" + "\x57\x10\xA2\x34\x89\xB0\xD3\xB6\x9D\x5D\x9D\x4A" }, + 0, + FALSE + }, + { + ENCTYPE_DES3_CBC_SHA1, + "\xC3\x9F", + { KV5M_DATA, 23, "ATHENA.MIT.EDUJuri\xC5\xA1\x69\xC4\x87" }, + { KV5M_DATA, 0, NULL }, + { KV5M_DATA, 24, "\x16\xD5\xA4\x0E\x1C\xE3\xBA\xCB\x61\xB9\xDC\xE0" + "\x04\x70\x32\x4C\x83\x19\x73\xA7\xB9\x52\xFE\xB0" }, + 0, + FALSE + }, + { + ENCTYPE_DES3_CBC_SHA1, + "\xF0\x9D\x84\x9E", + { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, + { KV5M_DATA, 0, NULL }, + { KV5M_DATA, 24, "\x85\x76\x37\x26\x58\x5D\xBC\x1C\xCE\x6E\xC4\x3E" + "\x1F\x75\x1F\x07\xF1\xC4\xCB\xB0\x98\xF4\x0B\x19" }, + 0, + FALSE + }, + + /* Test vectors from RFC 3962 appendix B. */ + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + "password", + { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\0\0\0\1" }, + { KV5M_DATA, 16, + "\x42\x26\x3C\x6E\x89\xF4\xFC\x28\xB8\xDF\x68\xEE\x09\x79\x9F\x15" }, + 0, + TRUE + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + "password", + { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\0\0\0\1" }, + { KV5M_DATA, 32, + "\xFE\x69\x7B\x52\xBC\x0D\x3C\xE1\x44\x32\xBA\x03\x6A\x92\xE6\x5B" + "\xBB\x52\x28\x09\x90\xA2\xFA\x27\x88\x39\x98\xD7\x2A\xF3\x01\x61" }, + 0, + TRUE + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + "password", + { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\0\0\0\2" }, + { KV5M_DATA, 16, + "\xC6\x51\xBF\x29\xE2\x30\x0A\xC2\x7F\xA4\x69\xD6\x93\xBD\xDA\x13" }, + 0, + TRUE + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + "password", + { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\0\0\0\2" }, + { KV5M_DATA, 32, + "\xA2\xE1\x6D\x16\xB3\x60\x69\xC1\x35\xD5\xE9\xD2\xE2\x5F\x89\x61" + "\x02\x68\x56\x18\xB9\x59\x14\xB4\x67\xC6\x76\x22\x22\x58\x24\xFF" }, + 0, + TRUE + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + "password", + { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ + { KV5M_DATA, 16, + "\x4C\x01\xCD\x46\xD6\x32\xD0\x1E\x6D\xBE\x23\x0A\x01\xED\x64\x2A" }, + 0, + TRUE + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + "password", + { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ + { KV5M_DATA, 32, + "\x55\xA6\xAC\x74\x0A\xD1\x7B\x48\x46\x94\x10\x51\xE1\xE8\xB0\xA7" + "\x54\x8D\x93\xB0\xAB\x30\xA8\xBC\x3F\xF1\x62\x80\x38\x2B\x8C\x2A" }, + 0, + TRUE + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + "password", + { KV5M_DATA, 8, "\x12\x34\x56\x78\x78\x56\x34\x12" }, + { KV5M_DATA, 4, "\0\0\0\5" }, + { KV5M_DATA, 16, + "\xE9\xB2\x3D\x52\x27\x37\x47\xDD\x5C\x35\xCB\x55\xBE\x61\x9D\x8E" }, + 0, + TRUE + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + "password", + { KV5M_DATA, 8, "\x12\x34\x56\x78\x78\x56\x34\x12" }, + { KV5M_DATA, 4, "\0\0\0\5" }, + { KV5M_DATA, 32, + "\x97\xA4\xE7\x86\xBE\x20\xD8\x1A\x38\x2D\x5E\xBC\x96\xD5\x90\x9C" + "\xAB\xCD\xAD\xC8\x7C\xA4\x8F\x57\x45\x04\x15\x9F\x16\xC3\x6E\x31" }, + 0, + TRUE + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + { KV5M_DATA, 29, "pass phrase equals block size" }, + { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ + { KV5M_DATA, 16, + "\x59\xD1\xBB\x78\x9A\x82\x8B\x1A\xA5\x4E\xF9\xC2\x88\x3F\x69\xED" }, + 0, + TRUE + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + { KV5M_DATA, 29, "pass phrase equals block size" }, + { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ + { KV5M_DATA, 32, + "\x89\xAD\xEE\x36\x08\xDB\x8B\xC7\x1F\x1B\xFB\xFE\x45\x94\x86\xB0" + "\x56\x18\xB7\x0C\xBA\xE2\x20\x92\x53\x4E\x56\xC5\x53\xBA\x4B\x34" }, + 0, + TRUE + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + { KV5M_DATA, 30, "pass phrase exceeds block size" }, + { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ + { KV5M_DATA, 16, + "\xCB\x80\x05\xDC\x5F\x90\x17\x9A\x7F\x02\x10\x4C\x00\x18\x75\x1D" }, + 0, + TRUE + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + { KV5M_DATA, 30, "pass phrase exceeds block size" }, + { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ + { KV5M_DATA, 32, + "\xD7\x8C\x5C\x9C\xB8\x72\xA8\xC9\xDA\xD4\x69\x7F\x0B\xB5\xB2\xD2" + "\x14\x96\xC8\x2B\xEB\x2C\xAE\xDA\x21\x12\xFC\xEE\xA0\x57\x40\x1B" }, + 0, + TRUE + }, + { + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + "\xF0\x9D\x84\x9E", + { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, + { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */ + { KV5M_DATA, 16, + "\xF1\x49\xC1\xF2\xE1\x54\xA7\x34\x52\xD4\x3E\x7F\xE6\x2A\x56\xE5" }, + 0, + TRUE + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + "\xF0\x9D\x84\x9E", + { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, + { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */ + { KV5M_DATA, 32, + "\x4B\x6D\x98\x39\xF8\x44\x06\xDF\x1F\x09\xCC\x16\x6D\xB4\xB8\x3C" + "\x57\x18\x48\xB7\x84\xA3\xD6\xBD\xC3\x46\x58\x9A\x3E\x39\x3F\x9E" }, + 0, + TRUE + }, + /* Check for KRB5_ERR_BAD_S2K_PARAMS return when weak iteration counts are + * forbidden. */ + { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, + "\xF0\x9D\x84\x9E", + { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, + { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */ + { KV5M_DATA, 32, + "\x4B\x6D\x98\x39\xF8\x44\x06\xDF\x1F\x09\xCC\x16\x6D\xB4\xB8\x3C" + "\x57\x18\x48\xB7\x84\xA3\xD6\xBD\xC3\x46\x58\x9A\x3E\x39\x3F\x9E" }, + KRB5_ERR_BAD_S2K_PARAMS, + FALSE + }, + + /* The same inputs applied to Camellia enctypes. */ + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + "password", + { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\0\0\0\1" }, + { KV5M_DATA, 16, + "\x57\xD0\x29\x72\x98\xFF\xD9\xD3\x5D\xE5\xA4\x7F\xB4\xBD\xE2\x4B" }, + 0, + TRUE + }, + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + "password", + { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\0\0\0\1" }, + { KV5M_DATA, 32, + "\xB9\xD6\x82\x8B\x20\x56\xB7\xBE\x65\x6D\x88\xA1\x23\xB1\xFA\xC6" + "\x82\x14\xAC\x2B\x72\x7E\xCF\x5F\x69\xAF\xE0\xC4\xDF\x2A\x6D\x2C" }, + 0, + TRUE + }, + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + "password", + { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\0\0\0\2" }, + { KV5M_DATA, 16, + "\x73\xF1\xB5\x3A\xA0\xF3\x10\xF9\x3B\x1D\xE8\xCC\xAA\x0C\xB1\x52" }, + 0, + TRUE + }, + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + "password", + { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\0\0\0\2" }, + { KV5M_DATA, 32, + "\x83\xFC\x58\x66\xE5\xF8\xF4\xC6\xF3\x86\x63\xC6\x5C\x87\x54\x9F" + "\x34\x2B\xC4\x7E\xD3\x94\xDC\x9D\x3C\xD4\xD1\x63\xAD\xE3\x75\xE3" }, + 0, + TRUE + }, + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + "password", + { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ + { KV5M_DATA, 16, + "\x8E\x57\x11\x45\x45\x28\x55\x57\x5F\xD9\x16\xE7\xB0\x44\x87\xAA" }, + 0, + TRUE + }, + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + "password", + { KV5M_DATA, 21, "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ + { KV5M_DATA, 32, + "\x77\xF4\x21\xA6\xF2\x5E\x13\x83\x95\xE8\x37\xE5\xD8\x5D\x38\x5B" + "\x4C\x1B\xFD\x77\x2E\x11\x2C\xD9\x20\x8C\xE7\x2A\x53\x0B\x15\xE6" }, + 0, + TRUE + }, + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + "password", + { KV5M_DATA, 8, "\x12\x34\x56\x78\x78\x56\x34\x12" }, + { KV5M_DATA, 4, "\0\0\0\5" }, + { KV5M_DATA, 16, + "\x00\x49\x8F\xD9\x16\xBF\xC1\xC2\xB1\x03\x1C\x17\x08\x01\xB3\x81" }, + 0, + TRUE + }, + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + "password", + { KV5M_DATA, 8, "\x12\x34\x56\x78\x78\x56\x34\x12" }, + { KV5M_DATA, 4, "\0\0\0\5" }, + { KV5M_DATA, 32, + "\x11\x08\x3A\x00\xBD\xFE\x6A\x41\xB2\xF1\x97\x16\xD6\x20\x2F\x0A" + "\xFA\x94\x28\x9A\xFE\x8B\x27\xA0\x49\xBD\x28\xB1\xD7\x6C\x38\x9A" }, + 0, + TRUE + }, + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + { KV5M_DATA, 29, "pass phrase equals block size" }, + { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ + { KV5M_DATA, 16, + "\x8B\xF6\xC3\xEF\x70\x9B\x98\x1D\xBB\x58\x5D\x08\x68\x43\xBE\x05" }, + 0, + TRUE + }, + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + { KV5M_DATA, 29, "pass phrase equals block size" }, + { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ + { KV5M_DATA, 32, + "\x11\x9F\xE2\xA1\xCB\x0B\x1B\xE0\x10\xB9\x06\x7A\x73\xDB\x63\xED" + "\x46\x65\xB4\xE5\x3A\x98\xD1\x78\x03\x5D\xCF\xE8\x43\xA6\xB9\xB0" }, + 0, + TRUE + }, + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + { KV5M_DATA, 30, "pass phrase exceeds block size" }, + { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ + { KV5M_DATA, 16, + "\x57\x52\xAC\x8D\x6A\xD1\xCC\xFE\x84\x30\xB3\x12\x87\x1C\x2F\x74" }, + 0, + TRUE + }, + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + { KV5M_DATA, 30, "pass phrase exceeds block size" }, + { KV5M_DATA, 4, "\0\0\x04\xB0" }, /* 1200 */ + { KV5M_DATA, 32, + "\x61\x4D\x5D\xFC\x0B\xA6\xD3\x90\xB4\x12\xB8\x9A\xE4\xD5\xB0\x88" + "\xB6\x12\xB3\x16\x51\x09\x94\x67\x9D\xDB\x43\x83\xC7\x12\x6D\xDF" }, + 0, + TRUE + }, + { + ENCTYPE_CAMELLIA128_CTS_CMAC, + "\xf0\x9d\x84\x9e", + { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, + { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */ + { KV5M_DATA, 16, + "\xCC\x75\xC7\xFD\x26\x0F\x1C\x16\x58\x01\x1F\xCC\x0D\x56\x06\x16" }, + 0, + TRUE + }, + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + "\xf0\x9d\x84\x9e", + { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, + { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */ + { KV5M_DATA, 32, + "\x16\x3B\x76\x8C\x6D\xB1\x48\xB4\xEE\xC7\x16\x3D\xF5\xAE\xD7\x0E" + "\x20\x6B\x68\xCE\xC0\x78\xBC\x06\x9E\xD6\x8A\x7E\xD3\x6B\x1E\xCC" }, + 0, + TRUE + }, + /* Check for KRB5_ERR_BAD_S2K_PARAMS return when weak iteration counts are + * forbidden. */ + { + ENCTYPE_CAMELLIA256_CTS_CMAC, + "\xf0\x9d\x84\x9e", + { KV5M_DATA, 18, "EXAMPLE.COMpianist" }, + { KV5M_DATA, 4, "\0\0\0\x32" }, /* 50 */ + { KV5M_DATA, 32, + "\x16\x3B\x76\x8C\x6D\xB1\x48\xB4\xEE\xC7\x16\x3D\xF5\xAE\xD7\x0E" + "\x20\x6B\x68\xCE\xC0\x78\xBC\x06\x9E\xD6\x8A\x7E\xD3\x6B\x1E\xCC" }, + KRB5_ERR_BAD_S2K_PARAMS, + FALSE + }, + + { + ENCTYPE_AES128_CTS_HMAC_SHA256_128, + "password", + { KV5M_DATA, 37, + "\x10\xDF\x9D\xD7\x83\xE5\xBC\x8A\xCE\xA1\x73\x0E\x74\x35\x5F\x61" + "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\x00\x00\x80\x00" }, + { KV5M_DATA, 16, + "\x08\x9B\xCA\x48\xB1\x05\xEA\x6E\xA7\x7C\xA5\xD2\xF3\x9D\xC5\xE7" }, + 0, + FALSE + }, + { + ENCTYPE_AES256_CTS_HMAC_SHA384_192, + "password", + { KV5M_DATA, 37, + "\x10\xDF\x9D\xD7\x83\xE5\xBC\x8A\xCE\xA1\x73\x0E\x74\x35\x5F\x61" + "ATHENA.MIT.EDUraeburn" }, + { KV5M_DATA, 4, "\x00\x00\x80\x00" }, + { KV5M_DATA, 32, + "\x45\xBD\x80\x6D\xBF\x6A\x83\x3A\x9C\xFF\xC1\xC9\x45\x89\xA2\x22" + "\x36\x7A\x79\xBC\x21\xC4\x13\x71\x89\x06\xE9\xF5\x78\xA7\x84\x67" }, + 0, + FALSE + }, +}; + +static void +printhex(const char *head, void *data, size_t len) +{ + size_t i; + + printf("%s", head); + for (i = 0; i < len; i++) { + printf("%02X", ((unsigned char*)data)[i]); + if (i % 16 == 15 && i + 1 < len) + printf("\n%*s", (int)strlen(head), ""); + else if (i + 1 < len) + printf(" "); + } + printf("\n"); +} + +extern int k5_allow_weak_pbkdf2iter; + +int +main(int argc, char **argv) +{ + krb5_context context = NULL; + krb5_data string; + krb5_error_code ret; + krb5_keyblock *keyblock; + size_t i; + struct test *test; + krb5_boolean verbose = FALSE; + int status = 0; + + if (argc >= 2 && strcmp(argv[1], "-v") == 0) + verbose = TRUE; + for (i = 0; i < sizeof(test_cases) / sizeof(*test_cases); i++) { + test = &test_cases[i]; + string = string2data(test->string); + ret = krb5_init_keyblock(context, test->enctype, 0, &keyblock); + assert(!ret); + k5_allow_weak_pbkdf2iter = test->allow_weak; + ret = krb5_c_string_to_key_with_params(context, test->enctype, + &string, &test->salt, + &test->params, keyblock); + if (ret != test->expected_err) { + com_err(argv[0], ret, "in krb5_c_string_to_key_with_params"); + exit(1); + } + if (verbose) { + char buf[64]; + krb5_enctype_to_name(test->enctype, FALSE, buf, sizeof(buf)); + printf("\nTest %d:\n", (int)i); + printf("Enctype: %s\n", buf); + printf("String: %s\n", test->string); + printhex("Salt: ", test->salt.data, test->salt.length); + printhex("Params: ", test->params.data, test->params.length); + if (test->expected_err == 0) + printhex("Key: ", keyblock->contents, keyblock->length); + else + printf("Expected error: %d\n", (int)test->expected_err); + } + if (test->expected_err != 0) { + krb5_free_keyblock(context, keyblock); + continue; + } + assert(keyblock->length == test->expected_key.length); + if (memcmp(keyblock->contents, test->expected_key.data, + keyblock->length) != 0) { + printf("str2key test %d failed\n", (int)i); + status = 1; + if (!verbose) + break; + } + krb5_free_keyblock(context, keyblock); + } + return status; +} diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/test/Readme.txt b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/Readme.txt new file mode 100644 index 00000000..69dbb5b9 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/Readme.txt @@ -0,0 +1,22 @@ +README + +Algorithm: Rijndael +Submitter: Joan Daemen and Vincent Rijmen + +Test values: Known Answer Tests and Monte Carlo Tests +----------------------------------------------------------- + +This directory contains the following files: + +Readme.txt: This file. + +cbc_d_m.txt: Test values for the CBC decryption MCT. +cbc_e_m.txt: Test values for the CBC encryption MCT. +ecb_d_m.txt: Test values for the ECB decryption MCT. +ecb_e_m.txt: Test values for the ECB encryption MCT. +ecb_vk.txt: Test values for the Variable Key KAT. +ecb_vt.txt: Test values for the Variable Text KAT. +ecb_iv.txt: Test values for the Intermediate Values KAT. +ecb_iv.readme: Detailed information about the Intermediate Values KAT. +ecb_tbl.txt: Test values for the Table KAT. + diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/test/cbc_d_m.txt b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/cbc_d_m.txt new file mode 100644 index 00000000..e216f3b8 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/cbc_d_m.txt @@ -0,0 +1,7224 @@ + +========================= + +FILENAME: "cbc_d_m.txt" + +Cipher Block Chaining (CBC) Mode - DECRYPTION +Monte Carlo Test + +Algorithm Name: Rijndael +Principal Submitter: Joan Daemen + +========== + +KEYSIZE=128 + +I=0 +KEY=00000000000000000000000000000000 +IV=00000000000000000000000000000000 +CT=00000000000000000000000000000000 +PT=FACA37E0B0C85373DF706E73F7C9AF86 + +I=1 +KEY=FACA37E0B0C85373DF706E73F7C9AF86 +IV=52D0C29FF8793A519BD6A8289FC80E6A +CT=FACA37E0B0C85373DF706E73F7C9AF86 +PT=F5372F9735C5685F1DA362AF6ECB2940 + +I=2 +KEY=0FFD1877850D3B2CC2D30CDC990286C6 +IV=DD74BB1AC6F0F866C7992C61F59D5594 +CT=F5372F9735C5685F1DA362AF6ECB2940 +PT=5496A4C29C7670F61B5D5DF6181F5947 + +I=3 +KEY=5B6BBCB5197B4BDAD98E512A811DDF81 +IV=3795C88134F7C011433397D1443FEB3A +CT=5496A4C29C7670F61B5D5DF6181F5947 +PT=940CC5A2AF4F1F8D1862B47BCF63E4CA + +I=4 +KEY=CF677917B6345457C1ECE5514E7E3B4B +IV=0FC1413900225B47AF9E139E1650EA23 +CT=940CC5A2AF4F1F8D1862B47BCF63E4CA +PT=08832415D97820DE305A58A9AD111A9E + +I=5 +KEY=C7E45D026F4C7489F1B6BDF8E36F21D5 +IV=3032F64674FA243D61DF8C16313D81F3 +CT=08832415D97820DE305A58A9AD111A9E +PT=BD4089775FD1BDB0A6C4F36D1DDAA93E + +I=6 +KEY=7AA4D475309DC93957724E95FEB588EB +IV=47D7F440B43888F173AE5A492F1A99F8 +CT=BD4089775FD1BDB0A6C4F36D1DDAA93E +PT=AB9955F74612859267D61FEA85A75ADC + +I=7 +KEY=D13D8182768F4CAB30A4517F7B12D237 +IV=6D9E57242195D27771D1C7A748378AB0 +CT=AB9955F74612859267D61FEA85A75ADC +PT=168F213FB678D8A46D0E55EFD1C49BB3 + +I=8 +KEY=C7B2A0BDC0F7940F5DAA0490AAD64984 +IV=1B98968FB5ABD95930525C1257DEB364 +CT=168F213FB678D8A46D0E55EFD1C49BB3 +PT=3C4CEECFF9560501C5D8C901D87C8E7B + +I=9 +KEY=FBFE4E7239A1910E9872CD9172AAC7FF +IV=35EB7B6D3F63AAE927C5346C9C2CB91D +CT=3C4CEECFF9560501C5D8C901D87C8E7B +PT=9D206BE0CC60296BF3A486A8C69778EF + +I=10 +KEY=66DE2592F5C1B8656BD64B39B43DBF10 +IV=226646B36D8E9B9279F94378CCBF8FBA +CT=9D206BE0CC60296BF3A486A8C69778EF +PT=9DA7B8094BD0F0BEA26848C84B8E083C + +I=11 +KEY=FB799D9BBE1148DBC9BE03F1FFB3B72C +IV=3E3A2B0E1C70A19BCD7222708AA94F26 +CT=9DA7B8094BD0F0BEA26848C84B8E083C +PT=6A93B2F318C14C2D3E58455B86A4F5D7 + +I=12 +KEY=91EA2F68A6D004F6F7E646AA791742FB +IV=1F256942B3CD691858A20664BB24545E +CT=6A93B2F318C14C2D3E58455B86A4F5D7 +PT=4A19AC6C6FEB654D3675A2BE32E5A820 + +I=13 +KEY=DBF38304C93B61BBC193E4144BF2EADB +IV=631F2EDE05C1C950BCE67DF53BA53ED6 +CT=4A19AC6C6FEB654D3675A2BE32E5A820 +PT=799EAB8E9C864A13490FD6B089F764C5 + +I=14 +KEY=A26D288A55BD2BA8889C32A4C2058E1E +IV=F6AD064E0DBF4AF4AA5165E1FE0E86FA +CT=799EAB8E9C864A13490FD6B089F764C5 +PT=2FA3F38CA1216C6D911C1779F333413E + +I=15 +KEY=8DCEDB06F49C47C5198025DD3136CF20 +IV=DA039AC5F4EDCD84472B23CFA1252EC3 +CT=2FA3F38CA1216C6D911C1779F333413E +PT=2FC703AD6A7DAF8B0BDDD8586C1D67D0 + +I=16 +KEY=A209D8AB9EE1E84E125DFD855D2BA8F0 +IV=341B5FDA8AB434461A7B7A87EF0C530C +CT=2FC703AD6A7DAF8B0BDDD8586C1D67D0 +PT=54723CABFBE32DEEDFEBF4292A5710FA + +I=17 +KEY=F67BE4006502C5A0CDB609AC777CB80A +IV=2C42AD577B0BE057555C3FCB6FC0089E +CT=54723CABFBE32DEEDFEBF4292A5710FA +PT=6B1E2A8C1A9CBB95D1B34AAFE15A78D3 + +I=18 +KEY=9D65CE8C7F9E7E351C0543039626C0D9 +IV=E5E06583A834BF16118ED5FA401A2D6F +CT=6B1E2A8C1A9CBB95D1B34AAFE15A78D3 +PT=F4E57BFAB65375B3AD49CD78814F0C16 + +I=19 +KEY=6980B576C9CD0B86B14C8E7B1769CCCF +IV=71E59389FF6F992225B32960593F9362 +CT=F4E57BFAB65375B3AD49CD78814F0C16 +PT=90A31B5934FCF6822526C973114BD953 + +I=20 +KEY=F923AE2FFD31FD04946A47080622159C +IV=2A4B31492B9BAEC402C255978BB96D40 +CT=90A31B5934FCF6822526C973114BD953 +PT=61F88BA8D438A0FD23F0101465C7FD4E + +I=21 +KEY=98DB258729095DF9B79A571C63E5E8D2 +IV=607640CEA12DCF7F188B2B65C7F4153D +CT=61F88BA8D438A0FD23F0101465C7FD4E +PT=F62D206DF53F41CA898F3A8EB6A843FF + +I=22 +KEY=6EF605EADC361C333E156D92D54DAB2D +IV=D69C32E12303361B465BE9A484BCA723 +CT=F62D206DF53F41CA898F3A8EB6A843FF +PT=364BC3F9FDA5FB1AEEA7691550A58320 + +I=23 +KEY=58BDC6132193E729D0B2048785E8280D +IV=C207B8347B8DB8BC6845827BB6986B0E +CT=364BC3F9FDA5FB1AEEA7691550A58320 +PT=DAA6386A073CD1653E9A9DB0A97970BA + +I=24 +KEY=821BFE7926AF364CEE2899372C9158B7 +IV=6C5D2B186393280253D6922A8421C3A9 +CT=DAA6386A073CD1653E9A9DB0A97970BA +PT=AAF74F0E0A0141A811853AE8B120BC00 + +I=25 +KEY=28ECB1772CAE77E4FFADA3DF9DB1E4B7 +IV=3CB62EF0E649027DDDB76206D0F4D355 +CT=AAF74F0E0A0141A811853AE8B120BC00 +PT=22A0F9611447C1A85F397DD79E3206F9 + +I=26 +KEY=0A4C481638E9B64CA094DE080383E24E +IV=C4320FA90686AE0F9E979CBF1391F6D6 +CT=22A0F9611447C1A85F397DD79E3206F9 +PT=1871ABDEAA7E057E76D41ED9191FAC39 + +I=27 +KEY=123DE3C89297B332D640C0D11A9C4E77 +IV=FBFD18AADF7C5E8E96EB976A535BF312 +CT=1871ABDEAA7E057E76D41ED9191FAC39 +PT=BF52994F41B1DEF78C6A057642C52D89 + +I=28 +KEY=AD6F7A87D3266DC55A2AC5A7585963FE +IV=C195141578ADF4C92113C8A9A63FF072 +CT=BF52994F41B1DEF78C6A057642C52D89 +PT=3EAFB00E3B4A0E6DF74743A7EDAD0FE4 + +I=29 +KEY=93C0CA89E86C63A8AD6D8600B5F46C1A +IV=D1C4E98C4A9AC79B7CCBC052ACF78913 +CT=3EAFB00E3B4A0E6DF74743A7EDAD0FE4 +PT=4393544AB2387A93496D683C2B8970C7 + +I=30 +KEY=D0539EC35A54193BE400EE3C9E7D1CDD +IV=80517C6341DAF4DCBCCAE452F3040147 +CT=4393544AB2387A93496D683C2B8970C7 +PT=51DAC594293708A918E9EFC04F7F2F1C + +I=31 +KEY=81895B5773631192FCE901FCD10233C1 +IV=69DE50406B4E3E8A94C1367E1E3D5464 +CT=51DAC594293708A918E9EFC04F7F2F1C +PT=035B64F06C8166000C82BF15CC88446D + +I=32 +KEY=82D23FA71FE27792F06BBEE91D8A77AC +IV=8EA2E38145BBD79881B7EB31B8818A21 +CT=035B64F06C8166000C82BF15CC88446D +PT=F3EFFA770A21741551F309E1967CC2E4 + +I=33 +KEY=713DC5D015C30387A198B7088BF6B548 +IV=0DCAA309668E11509828152553FF2306 +CT=F3EFFA770A21741551F309E1967CC2E4 +PT=62BA0548E7AD136BEB4E38AECD7942D9 + +I=34 +KEY=1387C098F26E10EC4AD68FA6468FF791 +IV=D031FCA5F3C88926CC3BDDC448537B69 +CT=62BA0548E7AD136BEB4E38AECD7942D9 +PT=38E3D4C7AF0C3E494F1D580AC5430634 + +I=35 +KEY=2B64145F5D622EA505CBD7AC83CCF1A5 +IV=6FFA5A45EDA60294B0224EEB8C36C455 +CT=38E3D4C7AF0C3E494F1D580AC5430634 +PT=2231EB6A6588CBCB56B930B7F1CF9E04 + +I=36 +KEY=0955FF3538EAE56E5372E71B72036FA1 +IV=B5375674631ECC3334A318993CB81F9A +CT=2231EB6A6588CBCB56B930B7F1CF9E04 +PT=59692274C130D6820287EA10F7E64602 + +I=37 +KEY=503CDD41F9DA33EC51F50D0B85E529A3 +IV=A93D6E028B5C2BD17A29C6CA1617A0A2 +CT=59692274C130D6820287EA10F7E64602 +PT=5975A95327DE7749EA8DEDC580E5E8C7 + +I=38 +KEY=09497412DE0444A5BB78E0CE0500C164 +IV=26E00CB161145FCD00C39BC4FB1E5CBB +CT=5975A95327DE7749EA8DEDC580E5E8C7 +PT=D1F7E36BC8FF4439820CB617E745A9CC + +I=39 +KEY=D8BE977916FB009C397456D9E24568A8 +IV=72E78D9E15C8FBA864C6C40CEBB190B8 +CT=D1F7E36BC8FF4439820CB617E745A9CC +PT=76FB4F20C902E9AA89854440631092B5 + +I=40 +KEY=AE45D859DFF9E936B0F112998155FA1D +IV=4B6C585FEF52490EA62BAAD08FAA3DCF +CT=76FB4F20C902E9AA89854440631092B5 +PT=6D7D4487DCD624B2FC5002DFE7D2D347 + +I=41 +KEY=C3389CDE032FCD844CA110466687295A +IV=E94FD23A598DDE077CD1DAEE97FDADD9 +CT=6D7D4487DCD624B2FC5002DFE7D2D347 +PT=7297F8F85B21E1A5CB902DCC5F6738F9 + +I=42 +KEY=B1AF6426580E2C2187313D8A39E011A3 +IV=86E495D31EEFCBC30064414FBD78FAE5 +CT=7297F8F85B21E1A5CB902DCC5F6738F9 +PT=4A6978AACC6968931FB1B83D53D31FEF + +I=43 +KEY=FBC61C8C946744B2988085B76A330E4C +IV=6BA7664AB5ED4F7956D6C3FAA7C42961 +CT=4A6978AACC6968931FB1B83D53D31FEF +PT=6B63FAAF9DB43A2B6025F29B1D6A331C + +I=44 +KEY=90A5E62309D37E99F8A5772C77593D50 +IV=37D17D1702EA34A3C75376AA0F9D24AD +CT=6B63FAAF9DB43A2B6025F29B1D6A331C +PT=8317A07BEE0BF16B88D7D197884AC6CF + +I=45 +KEY=13B24658E7D88FF27072A6BBFF13FB9F +IV=29B89B238062495C260AF44C63AA809F +CT=8317A07BEE0BF16B88D7D197884AC6CF +PT=0443BFEBCA7C85CBD0CB66AB9D75425D + +I=46 +KEY=17F1F9B32DA40A39A0B9C0106266B9C2 +IV=08CF82854AE07429C4A866AA727CEA2E +CT=0443BFEBCA7C85CBD0CB66AB9D75425D +PT=6B1EB033CB844F9BDD96BA2C67D139C7 + +I=47 +KEY=7CEF4980E62045A27D2F7A3C05B78005 +IV=05579F3E0017EBF6083756DC0A50A2E9 +CT=6B1EB033CB844F9BDD96BA2C67D139C7 +PT=E7904CBFB41EBE4178B4D633AFC9B311 + +I=48 +KEY=9B7F053F523EFBE3059BAC0FAA7E3314 +IV=E6B2CB0CE57E02A230DCD16C08614823 +CT=E7904CBFB41EBE4178B4D633AFC9B311 +PT=96EAAA148F05FAD1F0FC06E135EC5DF8 + +I=49 +KEY=0D95AF2BDD3B0132F567AAEE9F926EEC +IV=4268294B10AD58BE9E570A9485963682 +CT=96EAAA148F05FAD1F0FC06E135EC5DF8 +PT=9F2F712F62DE747EE479A0A74384B196 + +I=50 +KEY=92BADE04BFE5754C111E0A49DC16DF7A +IV=A5C558F5D4658089CD9FB295EDAE64DB +CT=9F2F712F62DE747EE479A0A74384B196 +PT=9CF7F00094C4E2D96D752C2312FC135E + +I=51 +KEY=0E4D2E042B2197957C6B266ACEEACC24 +IV=1CE301F294BDF4C906E5F0A6FA7C22BB +CT=9CF7F00094C4E2D96D752C2312FC135E +PT=ABA58D548DB6E9BE977FDDC85E16C2DE + +I=52 +KEY=A5E8A350A6977E2BEB14FBA290FC0EFA +IV=66C1FF1E4B52A3542B48306EC33F171D +CT=ABA58D548DB6E9BE977FDDC85E16C2DE +PT=802948E1A5177FBE97ABA26B996FDF1B + +I=53 +KEY=25C1EBB1038001957CBF59C90993D1E1 +IV=197A546DEB2E19E17507276B9ED95135 +CT=802948E1A5177FBE97ABA26B996FDF1B +PT=67D931C0946ECDF2F8E41000726D1A56 + +I=54 +KEY=4218DA7197EECC67845B49C97BFECBB7 +IV=D11DA3CE92ADA0686F7BF12A4796D9F7 +CT=67D931C0946ECDF2F8E41000726D1A56 +PT=386C68821385E8CFCDD5678FE2AA89F8 + +I=55 +KEY=7A74B2F3846B24A8498E2E469954424F +IV=4DDE413EBC3F30E2F3A9F48DA1258DAF +CT=386C68821385E8CFCDD5678FE2AA89F8 +PT=1638C741EFE3B1CC45C7754783350825 + +I=56 +KEY=6C4C75B26B8895640C495B011A614A6A +IV=5B4F013B085E3A04A16A409E8C3BB270 +CT=1638C741EFE3B1CC45C7754783350825 +PT=91AB00C3828D3DF72BEC487EF4652567 + +I=57 +KEY=FDE77571E905A89327A5137FEE046F0D +IV=98074F522144682FF1498C61581F8B0E +CT=91AB00C3828D3DF72BEC487EF4652567 +PT=BC5BA874D2F3039837528993FB275EBA + +I=58 +KEY=41BCDD053BF6AB0B10F79AEC152331B7 +IV=B65C1A6F80CA024B92176D57061ECDFE +CT=BC5BA874D2F3039837528993FB275EBA +PT=B7DE1BEE1867F4DC3F974E0D8B416DB0 + +I=59 +KEY=F662C6EB23915FD72F60D4E19E625C07 +IV=7268C08FA807D83C9830F54A59F32662 +CT=B7DE1BEE1867F4DC3F974E0D8B416DB0 +PT=19769B9EB30B8DE5FD640ACE78F01F0A + +I=60 +KEY=EF145D75909AD232D204DE2FE692430D +IV=B260792BAB22BAAB6CCF3AE1DD3A0F85 +CT=19769B9EB30B8DE5FD640ACE78F01F0A +PT=2079F2C0A0DE164CD41FCE29D8CE3178 + +I=61 +KEY=CF6DAFB53044C47E061B10063E5C7275 +IV=6ABCE7B41E112B91B8E6BC0DBE37600C +CT=2079F2C0A0DE164CD41FCE29D8CE3178 +PT=0D3A678FAB06E743A9134C103B39B61D + +I=62 +KEY=C257C83A9B42233DAF085C160565C468 +IV=CEB1E776DBEF46BF8B949C0AF0EBEAD2 +CT=0D3A678FAB06E743A9134C103B39B61D +PT=80339ADB34BCDE3384D66170373AEEAC + +I=63 +KEY=426452E1AFFEFD0E2BDE3D66325F2AC4 +IV=EAAC373FCA05E610C1C5D4437AFD5631 +CT=80339ADB34BCDE3384D66170373AEEAC +PT=38D52D75E5783A08FBFE622633D6CF47 + +I=64 +KEY=7AB17F944A86C706D0205F400189E583 +IV=2A25ED6933CAAA95569ADA1AC7480942 +CT=38D52D75E5783A08FBFE622633D6CF47 +PT=3204F1EACBB520A69F0939F45BC82041 + +I=65 +KEY=48B58E7E8133E7A04F2966B45A41C5C2 +IV=9C6819799DAF61111ACC3C0ECEB0F8BF +CT=3204F1EACBB520A69F0939F45BC82041 +PT=16BD33EE541798BEE114E9D7F9141A9C + +I=66 +KEY=5E08BD90D5247F1EAE3D8F63A355DF5E +IV=C181F4DF1EE0E13BF76044A3DA5E3BC4 +CT=16BD33EE541798BEE114E9D7F9141A9C +PT=A0A68CF016C6AD8DAC4D5634EAADEBE5 + +I=67 +KEY=FEAE3160C3E2D2930270D95749F834BB +IV=2A4EE2CD011AF421616789DB790354FD +CT=A0A68CF016C6AD8DAC4D5634EAADEBE5 +PT=FCE7D92FD0B3A1C7920558F653E1019B + +I=68 +KEY=0249E84F13517354907581A11A193520 +IV=A7F7E2B701F34F308C0F28514DFAA15F +CT=FCE7D92FD0B3A1C7920558F653E1019B +PT=F16A084B2DE16D5E3E5405665DE3C623 + +I=69 +KEY=F323E0043EB01E0AAE2184C747FAF303 +IV=6D319828AAA75DFE99BEEDD21B983C7D +CT=F16A084B2DE16D5E3E5405665DE3C623 +PT=CE20AE629887DF02064F2D9DB092E1DB + +I=70 +KEY=3D034E66A637C108A86EA95AF76812D8 +IV=9484E76149F41901AF8AFD3152C56506 +CT=CE20AE629887DF02064F2D9DB092E1DB +PT=B457A655282213C1B7C5C2A206C7FCB9 + +I=71 +KEY=8954E8338E15D2C91FAB6BF8F1AFEE61 +IV=329E089DC915BD71B1F8D0713BFC4F97 +CT=B457A655282213C1B7C5C2A206C7FCB9 +PT=A89B8F7541FFF719A3C7DE1577CE1C3F + +I=72 +KEY=21CF6746CFEA25D0BC6CB5ED8661F25E +IV=FA381CAC5777234E6DF8A28A4E6671D8 +CT=A89B8F7541FFF719A3C7DE1577CE1C3F +PT=C4E73D25647350527C1F93F6C1D90296 + +I=73 +KEY=E5285A63AB997582C073261B47B8F0C8 +IV=082ACF3D2661514F0E00BDABC9015946 +CT=C4E73D25647350527C1F93F6C1D90296 +PT=34BF6DECECFE1C9AE3AA34B6DB3741EF + +I=74 +KEY=D197378F4767691823D912AD9C8FB127 +IV=3E56B658F899B6DBBA4EAF6E629F3555 +CT=34BF6DECECFE1C9AE3AA34B6DB3741EF +PT=FD86C78538176DC5D48BE2EC6B89D581 + +I=75 +KEY=2C11F00A7F7004DDF752F041F70664A6 +IV=765B823193F2738E6CACBB0154C941B1 +CT=FD86C78538176DC5D48BE2EC6B89D581 +PT=524E035AB9DEB29E467B9586A90F3A42 + +I=76 +KEY=7E5FF350C6AEB643B12965C75E095EE4 +IV=DE2B3EC0A3FF29EC67BBE1B124E9451A +CT=524E035AB9DEB29E467B9586A90F3A42 +PT=83DE1E768EED94BA09E623845A057834 + +I=77 +KEY=FD81ED26484322F9B8CF4643040C26D0 +IV=A5CF4D996D8460E71DDA938461BB884B +CT=83DE1E768EED94BA09E623845A057834 +PT=D8381D17B9BCF942F408DBB2B7B2D6B7 + +I=78 +KEY=25B9F031F1FFDBBB4CC79DF1B3BEF067 +IV=899696B8EDC4E8B60489742A2559C909 +CT=D8381D17B9BCF942F408DBB2B7B2D6B7 +PT=BF1D8175015D0A0341427DE1F7DDE379 + +I=79 +KEY=9AA47144F0A2D1B80D85E0104463131E +IV=AD76D13B2F2A3F938F5C810A38A83D09 +CT=BF1D8175015D0A0341427DE1F7DDE379 +PT=58114DEFF8CFF10F06B390EB01B13394 + +I=80 +KEY=C2B53CAB086D20B70B3670FB45D2208A +IV=9EC540C144AB57D4E5A9185F55E71E50 +CT=58114DEFF8CFF10F06B390EB01B13394 +PT=53E72B9603CE221F0160791DF51F6B3E + +I=81 +KEY=9152173D0BA302A80A5609E6B0CD4BB4 +IV=B780257238CA60FD998819B2D04CEB92 +CT=53E72B9603CE221F0160791DF51F6B3E +PT=AF0238554AAFFB0FB5DFAC35E3CE8F4C + +I=82 +KEY=3E502F68410CF9A7BF89A5D35303C4F8 +IV=3509BC884089ADEB90137A39AEA75CFC +CT=AF0238554AAFFB0FB5DFAC35E3CE8F4C +PT=20844D3F4F637B974D38B7E5F1C84205 + +I=83 +KEY=1ED462570E6F8230F2B11236A2CB86FD +IV=52BAB07EB72804630E4BD769F0172FDA +CT=20844D3F4F637B974D38B7E5F1C84205 +PT=68404E006D2F16572EDFAE636A62C537 + +I=84 +KEY=76942C5763409467DC6EBC55C8A943CA +IV=E4B417D85F36F3A25CF04AB05157F247 +CT=68404E006D2F16572EDFAE636A62C537 +PT=13C8DF4117D4EA3645F1825700F8FFA5 + +I=85 +KEY=655CF31674947E51999F3E02C851BC6F +IV=3FE0683442B6B5DF515209DE16F8FD4B +CT=13C8DF4117D4EA3645F1825700F8FFA5 +PT=42307D929439F2723202A5206D640431 + +I=86 +KEY=276C8E84E0AD8C23AB9D9B22A535B85E +IV=33FAD11D9D4057E7ED989F1520450C32 +CT=42307D929439F2723202A5206D640431 +PT=5ED8AF875ACF37BE8FAAC16D4AB8072B + +I=87 +KEY=79B42103BA62BB9D24375A4FEF8DBF75 +IV=807852E5AD0EB5E0C3A2AAF18DFB14F9 +CT=5ED8AF875ACF37BE8FAAC16D4AB8072B +PT=79C950A45ECDC8B676A5CFF324A81DA8 + +I=88 +KEY=007D71A7E4AF732B529295BCCB25A2DD +IV=516BC35B52C26C99E21C0147CB7DD99E +CT=79C950A45ECDC8B676A5CFF324A81DA8 +PT=595C3DDCFBD90661A3A70B94C470A26B + +I=89 +KEY=59214C7B1F76754AF1359E280F5500B6 +IV=FDABDD4BD60725F5E640629416F417D3 +CT=595C3DDCFBD90661A3A70B94C470A26B +PT=7957CF3989083D25B54C6890EC58DB0C + +I=90 +KEY=20768342967E486F4479F6B8E30DDBBA +IV=CADFADF417898DE3786D5DF869396611 +CT=7957CF3989083D25B54C6890EC58DB0C +PT=6C1E8DF34FC80DD2ECA00A1EDC5FC239 + +I=91 +KEY=4C680EB1D9B645BDA8D9FCA63F521983 +IV=A7DF9FA44AA2B49B9E26C6148CCAF36F +CT=6C1E8DF34FC80DD2ECA00A1EDC5FC239 +PT=72B5A426C9DC3B336756FB10B00626CE + +I=92 +KEY=3EDDAA97106A7E8ECF8F07B68F543F4D +IV=50FF574915D407A97A74CC399DE2D901 +CT=72B5A426C9DC3B336756FB10B00626CE +PT=194826159D7FAB9166D64F1DD6F627B0 + +I=93 +KEY=27958C828D15D51FA95948AB59A218FD +IV=A1E3BC848C019B6FC3F7072F9A866C52 +CT=194826159D7FAB9166D64F1DD6F627B0 +PT=0186B2316FC29104D3549C49F92AE414 + +I=94 +KEY=26133EB3E2D7441B7A0DD4E2A088FCE9 +IV=4DBA42F1031AE32016524C7F86781528 +CT=0186B2316FC29104D3549C49F92AE414 +PT=373384DB7383D3A4914C0141BB104B81 + +I=95 +KEY=1120BA68915497BFEB41D5A31B98B768 +IV=FFCB87107AC596D71BA807902D524247 +CT=373384DB7383D3A4914C0141BB104B81 +PT=25465CE5FA2AD65D75586064A18516A8 + +I=96 +KEY=3466E68D6B7E41E29E19B5C7BA1DA1C0 +IV=55879596C3F0A295FA00CFEF1B056248 +CT=25465CE5FA2AD65D75586064A18516A8 +PT=2311A52CEC4A16B5F4FCA613BC0BDB83 + +I=97 +KEY=177743A1873457576AE513D406167A43 +IV=B1A7DABF3D2384BF8754B829659B3989 +CT=2311A52CEC4A16B5F4FCA613BC0BDB83 +PT=357F4BF62308CD5C48F34E9E644DD515 + +I=98 +KEY=22080857A43C9A0B22165D4A625BAF56 +IV=72BF477FE8CF428CFA856323E18B3135 +CT=357F4BF62308CD5C48F34E9E644DD515 +PT=17758539D1896B92BFB811D30C9BA134 + +I=99 +KEY=357D8D6E75B5F1999DAE4C996EC00E62 +IV=4CBA048DFA50910EC94FE5D6AA5DD502 +CT=17758539D1896B92BFB811D30C9BA134 +PT=372B6DCEE44D18D3791C4E8FB0A91971 + +I=100 +KEY=0256E0A091F8E94AE4B20216DE691713 +IV=86F4F670CA3B191B860D6C8A9A35A872 +CT=372B6DCEE44D18D3791C4E8FB0A91971 +PT=66D3FABC4885C1F4897D9160C152D570 + +I=101 +KEY=64851A1CD97D28BE6DCF93761F3BC263 +IV=08490B2E8588FE564F0112D76D6108E9 +CT=66D3FABC4885C1F4897D9160C152D570 +PT=926278E71894F32B5E2A5A1F5FA695E7 + +I=102 +KEY=F6E762FBC1E9DB9533E5C969409D5784 +IV=D3A2E4AFFDD8A7CC1498EF0E812087B7 +CT=926278E71894F32B5E2A5A1F5FA695E7 +PT=A455F5D65D91563D9C15E6B745F29531 + +I=103 +KEY=52B2972D9C788DA8AFF02FDE056FC2B5 +IV=6CB8822EA67C247A6A0CBAD830B3562C +CT=A455F5D65D91563D9C15E6B745F29531 +PT=4544371A5E3A8E7AD9885AECD3868AF3 + +I=104 +KEY=17F6A037C24203D276787532D6E94846 +IV=93E3CAD8BE023F6451ADAA525988A974 +CT=4544371A5E3A8E7AD9885AECD3868AF3 +PT=8473F4F1D77AC1F46706EBD108CB48A5 + +I=105 +KEY=938554C61538C226117E9EE3DE2200E3 +IV=A7E7B354606EF4C1D00BF4F128CCE966 +CT=8473F4F1D77AC1F46706EBD108CB48A5 +PT=787ADE453DCE2FA7F6F24CD33C9A5CDC + +I=106 +KEY=EBFF8A8328F6ED81E78CD230E2B85C3F +IV=97A2CF706C1871B502D15B028C5F0D80 +CT=787ADE453DCE2FA7F6F24CD33C9A5CDC +PT=E6A7E5B65DC124FBE1C1FFFE18A34D8A + +I=107 +KEY=0D586F357537C97A064D2DCEFA1B11B5 +IV=9BBDCAF2A3CC7FC5BF6285631A4636FD +CT=E6A7E5B65DC124FBE1C1FFFE18A34D8A +PT=6A391E9F475546720836312BBEB0B3A9 + +I=108 +KEY=676171AA32628F080E7B1CE544ABA21C +IV=603EEDE91F925A2228537E8BDD26C96B +CT=6A391E9F475546720836312BBEB0B3A9 +PT=D75086BA446563AAB1873FDEBE611D67 + +I=109 +KEY=B031F7107607ECA2BFFC233BFACABF7B +IV=546B8CA37AACE2BC2C85014F2ACD6315 +CT=D75086BA446563AAB1873FDEBE611D67 +PT=63A4D826625CBD9F10083E62330BCFBC + +I=110 +KEY=D3952F36145B513DAFF41D59C9C170C7 +IV=BC2E6E9DD10152C8281B798F711A9334 +CT=63A4D826625CBD9F10083E62330BCFBC +PT=41275EFDFC86B5BDCCCDCA2BBFA5B90D + +I=111 +KEY=92B271CBE8DDE4806339D7727664C9CA +IV=D940A8D1B3448AA9148C7F6DFC266B00 +CT=41275EFDFC86B5BDCCCDCA2BBFA5B90D +PT=56AC1BCB285044710D26EFC42A0ABA56 + +I=112 +KEY=C41E6A00C08DA0F16E1F38B65C6E739C +IV=214238FF5F4D01F3A6694EC80E15BCF7 +CT=56AC1BCB285044710D26EFC42A0ABA56 +PT=5AF2877973AB9787E42202AC0C6E7538 + +I=113 +KEY=9EECED79B32637768A3D3A1A500006A4 +IV=561B4934904E327F3B3639CED6C7A995 +CT=5AF2877973AB9787E42202AC0C6E7538 +PT=787F52F6D9CD9085D782B95FD68F70F8 + +I=114 +KEY=E693BF8F6AEBA7F35DBF8345868F765C +IV=06B93FB1A99BD387A091509B8C6D3482 +CT=787F52F6D9CD9085D782B95FD68F70F8 +PT=E7B1DB917C92E488C6B02AC4C42AFD79 + +I=115 +KEY=0122641E1679437B9B0FA98142A58B25 +IV=1D57A61FED51218BD8C1357CE58F21EB +CT=E7B1DB917C92E488C6B02AC4C42AFD79 +PT=2FBAB770D511EACA849F654DE429DE84 + +I=116 +KEY=2E98D36EC368A9B11F90CCCCA68C55A1 +IV=CB311C43EC32D59941CEF81BB9CF4E57 +CT=2FBAB770D511EACA849F654DE429DE84 +PT=A8FE17AEA961C2A450DD5EAABAA19613 + +I=117 +KEY=8666C4C06A096B154F4D92661C2DC3B2 +IV=B9D7B74D62DD89A01EE3093A5C2A0470 +CT=A8FE17AEA961C2A450DD5EAABAA19613 +PT=D9E598A4DBAF82BDF9474BE13B997FF5 + +I=118 +KEY=5F835C64B1A6E9A8B60AD98727B4BC47 +IV=6398D8A38C38A9B54DCF18C0D76758BA +CT=D9E598A4DBAF82BDF9474BE13B997FF5 +PT=291DB2BC325CD7A94032E7C1208921A5 + +I=119 +KEY=769EEED883FA3E01F6383E46073D9DE2 +IV=4774C7E1BB97117BCA26A897B9302EFA +CT=291DB2BC325CD7A94032E7C1208921A5 +PT=DFC55866F85055F06E752E04AAC4C36A + +I=120 +KEY=A95BB6BE7BAA6BF1984D1042ADF95E88 +IV=BDA0616700CD2817FE4425F6F541E8C1 +CT=DFC55866F85055F06E752E04AAC4C36A +PT=7CACB3A88E7114F7737B05D0FB3AF7F3 + +I=121 +KEY=D5F70516F5DB7F06EB36159256C3A97B +IV=1EF4836BD363B89EE73911B14EBE9262 +CT=7CACB3A88E7114F7737B05D0FB3AF7F3 +PT=3282F1F6B3C04E325FB13E85D18CDBBC + +I=122 +KEY=E775F4E0461B3134B4872B17874F72C7 +IV=E35D47CEDBD30701A64FE504C6BC4199 +CT=3282F1F6B3C04E325FB13E85D18CDBBC +PT=BFB9748A3C825CDA3EA5D001F6AD305F + +I=123 +KEY=58CC806A7A996DEE8A22FB1671E24298 +IV=7A3676377E0B4F815B4B8C9A98DCAB4D +CT=BFB9748A3C825CDA3EA5D001F6AD305F +PT=B33787380A4C3BD5B32EC335916F9229 + +I=124 +KEY=EBFB075270D5563B390C3823E08DD0B1 +IV=B3E40B27DBF6D985D4F57BD4D2899DC8 +CT=B33787380A4C3BD5B32EC335916F9229 +PT=BCD5E40A3B4885ACA82BEC952BA8A973 + +I=125 +KEY=572EE3584B9DD3979127D4B6CB2579C2 +IV=897608FE3238F80CD24192CC64F4F695 +CT=BCD5E40A3B4885ACA82BEC952BA8A973 +PT=793E22E0B01FFE63E89C84A0D0FE1216 + +I=126 +KEY=2E10C1B8FB822DF479BB50161BDB6BD4 +IV=D84401CF83566FEA8FB859C446C22632 +CT=793E22E0B01FFE63E89C84A0D0FE1216 +PT=96858A96FEB19712B10A44FBF8E633D9 + +I=127 +KEY=B8954B2E0533BAE6C8B114EDE33D580D +IV=7210E127BFB706EF9CD24139C0927E01 +CT=96858A96FEB19712B10A44FBF8E633D9 +PT=28A34CC75A215117331D6B88387E16F8 + +I=128 +KEY=903607E95F12EBF1FBAC7F65DB434EF5 +IV=744B8DD281919F79FC529DA15AA0F18F +CT=28A34CC75A215117331D6B88387E16F8 +PT=43FE41DC9FFB88F93ADC43D41BA3E4B2 + +I=129 +KEY=D3C84635C0E96308C1703CB1C0E0AA47 +IV=5C7379A90F1E47F88C7424E8CD31E55D +CT=43FE41DC9FFB88F93ADC43D41BA3E4B2 +PT=66D6D0E84CEB8672D38DDE557CCCFFF6 + +I=130 +KEY=B51E96DD8C02E57A12FDE2E4BC2C55B1 +IV=529B92CD068415627C4BE49874347F98 +CT=66D6D0E84CEB8672D38DDE557CCCFFF6 +PT=F817D013CB041CA41B6D611ED261FAE9 + +I=131 +KEY=4D0946CE4706F9DE099083FA6E4DAF58 +IV=9B4452DD48C3EECEFDB6A6CFAE670117 +CT=F817D013CB041CA41B6D611ED261FAE9 +PT=56420C70CC459A131CD531EDC39ED6E9 + +I=132 +KEY=1B4B4ABE8B4363CD1545B217ADD379B1 +IV=264ABBC30CC98DA3C06B935B1364A317 +CT=56420C70CC459A131CD531EDC39ED6E9 +PT=650DA8C4CB11E4ABFE8841D20443BB04 + +I=133 +KEY=7E46E27A40528766EBCDF3C5A990C2B5 +IV=DBABF7B18568FED50C69DA0C9AA5395D +CT=650DA8C4CB11E4ABFE8841D20443BB04 +PT=94E6CE02AE253F3BE4A59775CAB7B11B + +I=134 +KEY=EAA02C78EE77B85D0F6864B0632773AE +IV=F0D2E456CE063CB68988C1C397038480 +CT=94E6CE02AE253F3BE4A59775CAB7B11B +PT=124F09DAC6A45E6077DCECE971B24ED1 + +I=135 +KEY=F8EF25A228D3E63D78B4885912953D7F +IV=C19A6D2D35E606E552580B002023C966 +CT=124F09DAC6A45E6077DCECE971B24ED1 +PT=AAD649FD1168DFCB431A7216571ED4C1 + +I=136 +KEY=52396C5F39BB39F63BAEFA4F458BE9BE +IV=DF1A307B1D25BC2751ECDC791EC51B16 +CT=AAD649FD1168DFCB431A7216571ED4C1 +PT=992749C940CBBB0944F5248E8D65268C + +I=137 +KEY=CB1E2596797082FF7F5BDEC1C8EECF32 +IV=D8B0466FC4344C6BF4E57584E5F48A36 +CT=992749C940CBBB0944F5248E8D65268C +PT=FF16B9246C325A3B96250875A9D5C4BE + +I=138 +KEY=34089CB21542D8C4E97ED6B4613B0B8C +IV=B8C3E4ECF57631CE1EEA74AD99545BA2 +CT=FF16B9246C325A3B96250875A9D5C4BE +PT=72EDB906165FE6A19E02435AC6457C9A + +I=139 +KEY=46E525B4031D3E65777C95EEA77E7716 +IV=9C4F78D05257C64D752C576B5BB16245 +CT=72EDB906165FE6A19E02435AC6457C9A +PT=0C2F00362B8733D343DCAF884A6BFD46 + +I=140 +KEY=4ACA2582289A0DB634A03A66ED158A50 +IV=C51122198D2FD566ACA1BD07C28BCC7A +CT=0C2F00362B8733D343DCAF884A6BFD46 +PT=C7F5C00F42695CF7870240DA73D487F7 + +I=141 +KEY=8D3FE58D6AF35141B3A27ABC9EC10DA7 +IV=14769B7962371925822C42F0411BDC65 +CT=C7F5C00F42695CF7870240DA73D487F7 +PT=F4BC8A4310A4CD2F396F43B81BD060EB + +I=142 +KEY=79836FCE7A579C6E8ACD390485116D4C +IV=CDA4414DF23427B937D586C1A8164479 +CT=F4BC8A4310A4CD2F396F43B81BD060EB +PT=1B996A525174C35466103BCBD53ECB9C + +I=143 +KEY=621A059C2B235F3AECDD02CF502FA6D0 +IV=1DA9E7C02BE868E118E4B9BF5928BFCF +CT=1B996A525174C35466103BCBD53ECB9C +PT=2B4EC5CB9DE50257B5901C6D49B5EB54 + +I=144 +KEY=4954C057B6C65D6D594D1EA2199A4D84 +IV=55433149AA93215BF53CB8FE66CD683A +CT=2B4EC5CB9DE50257B5901C6D49B5EB54 +PT=5A5B9ACA3BDA951DC4C4DFB7DD15AD18 + +I=145 +KEY=130F5A9D8D1CC8709D89C115C48FE09C +IV=695C69EA8C4257D2758364AFF6387DA0 +CT=5A5B9ACA3BDA951DC4C4DFB7DD15AD18 +PT=5BB08593BA52E94F07CB14FF564AF299 + +I=146 +KEY=48BFDF0E374E213F9A42D5EA92C51205 +IV=665463164601CD0045C684729CDD5E7D +CT=5BB08593BA52E94F07CB14FF564AF299 +PT=DB1840467889551150026A90E3FC272F + +I=147 +KEY=93A79F484FC7742ECA40BF7A7139352A +IV=355C4B87A682712460C80ABA630F7BE8 +CT=DB1840467889551150026A90E3FC272F +PT=9F7BD8EF96A1ECC75B4E3031E65FE8FC + +I=148 +KEY=0CDC47A7D96698E9910E8F4B9766DDD6 +IV=FBF20FEC0A9E9B530DD3745955A1960C +CT=9F7BD8EF96A1ECC75B4E3031E65FE8FC +PT=DCF003E1DDD4B52F5B680568B42EEECF + +I=149 +KEY=D02C444604B22DC6CA668A2323483319 +IV=04EADC638E309466B9500B1C3A308856 +CT=DCF003E1DDD4B52F5B680568B42EEECF +PT=DDD2F2AEFEF4A4641747699170DF0129 + +I=150 +KEY=0DFEB6E8FA4689A2DD21E3B253973230 +IV=FB521123E5BB45F1AC7083C382B95E10 +CT=DDD2F2AEFEF4A4641747699170DF0129 +PT=7D6C54E4369E965513DE1E95E8A37433 + +I=151 +KEY=7092E20CCCD81FF7CEFFFD27BB344603 +IV=0E71300101915AEE97563493B4B2EFB9 +CT=7D6C54E4369E965513DE1E95E8A37433 +PT=B7F5C4275EF7D3A23E8E9A4BC2BCA700 + +I=152 +KEY=C767262B922FCC55F071676C7988E103 +IV=8BBC970D4E24F6F1A92859BBAE70B757 +CT=B7F5C4275EF7D3A23E8E9A4BC2BCA700 +PT=679FA9A8AB3EE2F0663D4DC95FEC3847 + +I=153 +KEY=A0F88F8339112EA5964C2AA52664D944 +IV=B8D28B6903859465F996A0DF491DDAAA +CT=679FA9A8AB3EE2F0663D4DC95FEC3847 +PT=914DCEAC5B00940A415C2144DAA1EF03 + +I=154 +KEY=31B5412F6211BAAFD7100BE1FCC53647 +IV=06E1FF99E63E0EDDA1D95682B541D026 +CT=914DCEAC5B00940A415C2144DAA1EF03 +PT=A718031A531395DA071B828A10A2B9DC + +I=155 +KEY=96AD423531022F75D00B896BEC678F9B +IV=F18546028693CC0A72E218460AC932E9 +CT=A718031A531395DA071B828A10A2B9DC +PT=19D996B9FF549029D800CF977C0E0A88 + +I=156 +KEY=8F74D48CCE56BF5C080B46FC90698513 +IV=7E98DAFA8DE35537A0B0AA8FA32E01DF +CT=19D996B9FF549029D800CF977C0E0A88 +PT=6A7D514FBE9963987E0EE5DD22FDC8BD + +I=157 +KEY=E50985C370CFDCC47605A321B2944DAE +IV=071F44277D12AD6E653FB747C11BEFB7 +CT=6A7D514FBE9963987E0EE5DD22FDC8BD +PT=AB07C464DF72DF58411A7CBF906F43A6 + +I=158 +KEY=4E0E41A7AFBD039C371FDF9E22FB0E08 +IV=BDA8979A0DE78999AE0659D2744BC21B +CT=AB07C464DF72DF58411A7CBF906F43A6 +PT=A8ABC34FF51FD998427A7837BB0F22BB + +I=159 +KEY=E6A582E85AA2DA047565A7A999F42CB3 +IV=3CA763C4375A6C70F072B52C42A02560 +CT=A8ABC34FF51FD998427A7837BB0F22BB +PT=9E82A41AB2A2748695663075C5BF1C09 + +I=160 +KEY=782726F2E800AE82E00397DC5C4B30BA +IV=B1DD4DC8715CA0B8BA3426395B61ABA4 +CT=9E82A41AB2A2748695663075C5BF1C09 +PT=3C891AEFC6645F3C23A2E3A2E1A522EF + +I=161 +KEY=44AE3C1D2E64F1BEC3A1747EBDEE1255 +IV=932F28E3FC0F85A0E703AD6079A68CC0 +CT=3C891AEFC6645F3C23A2E3A2E1A522EF +PT=D4FDD9C3D36E80E0AFA95ABEC2E62FB9 + +I=162 +KEY=9053E5DEFD0A715E6C082EC07F083DEC +IV=1AD1530DE6274BBA3A097004D85DF8FA +CT=D4FDD9C3D36E80E0AFA95ABEC2E62FB9 +PT=9FACBB106FBF34D9B25A83AD4F45AA38 + +I=163 +KEY=0FFF5ECE92B54587DE52AD6D304D97D4 +IV=8412EAA361AB8193AD529FA36944FE3D +CT=9FACBB106FBF34D9B25A83AD4F45AA38 +PT=E95628B6A14326AC153B228C0DD25063 + +I=164 +KEY=E6A9767833F6632BCB698FE13D9FC7B7 +IV=9F1D906FD25CCCA7565D82CDA44B4A57 +CT=E95628B6A14326AC153B228C0DD25063 +PT=7B1ECD07E452D593D00E326F8FD9F2B5 + +I=165 +KEY=9DB7BB7FD7A4B6B81B67BD8EB2463502 +IV=9C91B12734A86451492400EE5759C190 +CT=7B1ECD07E452D593D00E326F8FD9F2B5 +PT=A99874C1ECA463D335B37179348AEF4F + +I=166 +KEY=342FCFBE3B00D56B2ED4CCF786CCDA4D +IV=9060C6E8E2B51E5F1000860ECB5A608C +CT=A99874C1ECA463D335B37179348AEF4F +PT=F9296E658C3048C58FE6404AB6E0186C + +I=167 +KEY=CD06A1DBB7309DAEA1328CBD302CC221 +IV=ADCB427405EDF8078622AFC6C731D3EF +CT=F9296E658C3048C58FE6404AB6E0186C +PT=8D3A4ABFB8F57AEBB1284B78BFDD240D + +I=168 +KEY=403CEB640FC5E745101AC7C58FF1E62C +IV=4CED30477756892A49FE6358700F5DE7 +CT=8D3A4ABFB8F57AEBB1284B78BFDD240D +PT=7C71310D5241B8B461847FA7E2B4D506 + +I=169 +KEY=3C4DDA695D845FF1719EB8626D45332A +IV=52A3B8E21588368AA3AD2131B283B34C +CT=7C71310D5241B8B461847FA7E2B4D506 +PT=380A1E2925FC8061FBC69B08B4C7C6C8 + +I=170 +KEY=0447C4407878DF908A58236AD982F5E2 +IV=B7AD265DF50ABD77C1D1D02BAF06CEBD +CT=380A1E2925FC8061FBC69B08B4C7C6C8 +PT=6931E262570F27732A75629A384492CA + +I=171 +KEY=6D7626222F77F8E3A02D41F0E1C66728 +IV=DD7D3CA7F6CE54775836734B10685A99 +CT=6931E262570F27732A75629A384492CA +PT=336D0AB3F9A793469C544E98CFDC8AD6 + +I=172 +KEY=5E1B2C91D6D06BA53C790F682E1AEDFE +IV=54087C05437049FBAFC9BF6C56AD16CC +CT=336D0AB3F9A793469C544E98CFDC8AD6 +PT=0098A640F1D04E5557F748B80215082A + +I=173 +KEY=5E838AD1270025F06B8E47D02C0FE5D4 +IV=DD13A93C7FAEF14820D6A168AF9969DB +CT=0098A640F1D04E5557F748B80215082A +PT=48660EDDC3ACAC1A814AE088650DE007 + +I=174 +KEY=16E5840CE4AC89EAEAC4A758490205D3 +IV=589C43A680F7AE6E15DE25FD50F18BED +CT=48660EDDC3ACAC1A814AE088650DE007 +PT=047740C48160A14563C0049316C7B78E + +I=175 +KEY=1292C4C865CC28AF8904A3CB5FC5B25D +IV=22DB095AF8268D37AC536FDA3A81B7C2 +CT=047740C48160A14563C0049316C7B78E +PT=D9679ABB1AED1524E8DA2ECA89172853 + +I=176 +KEY=CBF55E737F213D8B61DE8D01D6D29A0E +IV=77FDCCC9BAB3B7E81D7B9D14540ED3A7 +CT=D9679ABB1AED1524E8DA2ECA89172853 +PT=C774AD9EF683A59747AB41DA044471C4 + +I=177 +KEY=0C81F3ED89A2981C2675CCDBD296EBCA +IV=2E266970512C0F6D404367978C70B5C6 +CT=C774AD9EF683A59747AB41DA044471C4 +PT=927C98AFDE6F108268A306A1A818EE89 + +I=178 +KEY=9EFD6B4257CD889E4ED6CA7A7A8E0543 +IV=E2B0A0F146E931136932D8188B7DC980 +CT=927C98AFDE6F108268A306A1A818EE89 +PT=D3C11AF1EF255D65EAAEE5B5C5BF3CD9 + +I=179 +KEY=4D3C71B3B8E8D5FBA4782FCFBF31399A +IV=ABA118A590A8A69D41D20ED13F7DA4C9 +CT=D3C11AF1EF255D65EAAEE5B5C5BF3CD9 +PT=760B1C47EB476A246CE41163B7425C7B + +I=180 +KEY=3B376DF453AFBFDFC89C3EAC087365E1 +IV=8A395FFEE93FF820FBC086932216324F +CT=760B1C47EB476A246CE41163B7425C7B +PT=4EEAE25D1654A461D6A56896EDFFEAB7 + +I=181 +KEY=75DD8FA945FB1BBE1E39563AE58C8F56 +IV=82D68DE458D38127E2A17DA736BC1651 +CT=4EEAE25D1654A461D6A56896EDFFEAB7 +PT=BD7ABD27F3515B9FD337ADADBA5E9EC9 + +I=182 +KEY=C8A7328EB6AA4021CD0EFB975FD2119F +IV=95757C38F4CB26C29DF174FD8B1F35E8 +CT=BD7ABD27F3515B9FD337ADADBA5E9EC9 +PT=E32EF56DE91CC21C158822BDB841A02C + +I=183 +KEY=2B89C7E35FB6823DD886D92AE793B1B3 +IV=AFFB434005E300E99E815A8E5B46E159 +CT=E32EF56DE91CC21C158822BDB841A02C +PT=578B7692D68BD4D65A159C9CCDC81F64 + +I=184 +KEY=7C02B171893D56EB829345B62A5BAED7 +IV=15E783551969F275EF25A429F68BA0DB +CT=578B7692D68BD4D65A159C9CCDC81F64 +PT=0F70D77F31DE8F0010628377C8E4A1C3 + +I=185 +KEY=7372660EB8E3D9EB92F1C6C1E2BF0F14 +IV=078B6E3FC7C79D52A5C49847A7C5D0BB +CT=0F70D77F31DE8F0010628377C8E4A1C3 +PT=A4F29F6A50A4A15789D4647774C96997 + +I=186 +KEY=D780F964E84778BC1B25A2B696766683 +IV=C9B2C903F131856C0D8218146479513A +CT=A4F29F6A50A4A15789D4647774C96997 +PT=7AD4F764911F8F1E8C9356F00B1468EE + +I=187 +KEY=AD540E007958F7A297B6F4469D620E6D +IV=780DAD9DBA12DDC713ECF44057B8B56E +CT=7AD4F764911F8F1E8C9356F00B1468EE +PT=A00EAFD28A95C7F39137773F28F9A0D3 + +I=188 +KEY=0D5AA1D2F3CD305106818379B59BAEBE +IV=6643BF26488FB21BCDAA7D4FABAA5BC3 +CT=A00EAFD28A95C7F39137773F28F9A0D3 +PT=FC884EEEB73B2F66C97D742A441B0463 + +I=189 +KEY=F1D2EF3C44F61F37CFFCF753F180AADD +IV=7B707442550BF1FA4C1B74F0DC3237FC +CT=FC884EEEB73B2F66C97D742A441B0463 +PT=9C260AA82C6902B068495B4844507F7D + +I=190 +KEY=6DF4E594689F1D87A7B5AC1BB5D0D5A0 +IV=8329E8DE2980225DA61158BF467B1D79 +CT=9C260AA82C6902B068495B4844507F7D +PT=1C12FEAA35AD2DD21DE6411C3A3BB6D5 + +I=191 +KEY=71E61B3E5D323055BA53ED078FEB6375 +IV=EFD514D7CF3FAC49DBB5BB3505B9B18F +CT=1C12FEAA35AD2DD21DE6411C3A3BB6D5 +PT=15F26D34E8E1037A5A2393CEA5DB396B + +I=192 +KEY=6414760AB5D3332FE0707EC92A305A1E +IV=9EFC37C295552B965B29A23AC2788D8B +CT=15F26D34E8E1037A5A2393CEA5DB396B +PT=76F0C79955566A0A091AA46E0C59455E + +I=193 +KEY=12E4B193E0855925E96ADAA726691F40 +IV=5BA54E33128A7526A9130E632BE00D65 +CT=76F0C79955566A0A091AA46E0C59455E +PT=1EA06231EBEEB995E2F94B88A4004333 + +I=194 +KEY=0C44D3A20B6BE0B00B93912F82695C73 +IV=9B1C6FA42510E530D2282BF8C5516DCE +CT=1EA06231EBEEB995E2F94B88A4004333 +PT=16C36348884B32AC1CB1DE2D3C158981 + +I=195 +KEY=1A87B0EA8320D21C17224F02BE7CD5F2 +IV=F755F641EED4C828DCBECC327D93F4AF +CT=16C36348884B32AC1CB1DE2D3C158981 +PT=6581A3FB5F61C6C1904F35E787BF552D + +I=196 +KEY=7F061311DC4114DD876D7AE539C380DF +IV=5D799F356C1672707716C47DA4384C01 +CT=6581A3FB5F61C6C1904F35E787BF552D +PT=0BA11F8EE845E03641928825B3344994 + +I=197 +KEY=74A70C9F3404F4EBC6FFF2C08AF7C94B +IV=89A5592031795CEAECF1C1F274813818 +CT=0BA11F8EE845E03641928825B3344994 +PT=1CF907A6C8A33C7806819EB97B854588 + +I=198 +KEY=685E0B39FCA7C893C07E6C79F1728CC3 +IV=BBE87558AF456066B9CE3EBB8729D554 +CT=1CF907A6C8A33C7806819EB97B854588 +PT=722BB2E53CE7846F40B5EA18AF1430B0 + +I=199 +KEY=1A75B9DCC0404CFC80CB86615E66BC73 +IV=2CC42E6DA36883482ACB5D9D92823186 +CT=722BB2E53CE7846F40B5EA18AF1430B0 +PT=E667D6A95E9C56BB56E4436CC1B69874 + +I=200 +KEY=FC126F759EDC1A47D62FC50D9FD02407 +IV=F18DD0388BF5692B7394BAFDC4854308 +CT=E667D6A95E9C56BB56E4436CC1B69874 +PT=3C9A76798C468470EEBC5F7B915879A3 + +I=201 +KEY=C088190C129A9E3738939A760E885DA4 +IV=8262D8603FE0F4AE8BF5795690992F1C +CT=3C9A76798C468470EEBC5F7B915879A3 +PT=3CAFB994BDEF76370D8A5129B63BECDB + +I=202 +KEY=FC27A098AF75E8003519CB5FB8B3B17F +IV=AB090F7A86CFD9A7C1BD8869BBB4D27B +CT=3CAFB994BDEF76370D8A5129B63BECDB +PT=50D037733D2C3242024BD322ADDF01CB + +I=203 +KEY=ACF797EB9259DA423752187D156CB0B4 +IV=3581D6724722C3892C712B2AA1066824 +CT=50D037733D2C3242024BD322ADDF01CB +PT=0D7CB755305EF09692FCED530CCC1336 + +I=204 +KEY=A18B20BEA2072AD4A5AEF52E19A0A382 +IV=9D0DAD6448895ECBE05F8DC73E014E3C +CT=0D7CB755305EF09692FCED530CCC1336 +PT=D66389E01F44C60B26BCF3F9B39DAB55 + +I=205 +KEY=77E8A95EBD43ECDF831206D7AA3D08D7 +IV=7BDC3CD62CD79C7E6CB8FAE104175DE4 +CT=D66389E01F44C60B26BCF3F9B39DAB55 +PT=CC9F59409D636BE5C555AC2841650CD7 + +I=206 +KEY=BB77F01E2020873A4647AAFFEB580400 +IV=A4FBE42983B236097E40C1E244B14748 +CT=CC9F59409D636BE5C555AC2841650CD7 +PT=34804672FCEF79481269B1D254DDCAF9 + +I=207 +KEY=8FF7B66CDCCFFE72542E1B2DBF85CEF9 +IV=700B37E771E88E5DCD9C81D6FD16B995 +CT=34804672FCEF79481269B1D254DDCAF9 +PT=62FC00FDF1F6BF44FFBEB5BED5589A64 + +I=208 +KEY=ED0BB6912D394136AB90AE936ADD549D +IV=F3A9954079382ACD97C3EC198522AE69 +CT=62FC00FDF1F6BF44FFBEB5BED5589A64 +PT=F7901904A02544E064400A2625121C4C + +I=209 +KEY=1A9BAF958D1C05D6CFD0A4B54FCF48D1 +IV=3799F5DEF76C56F8B0A69889B85760AA +CT=F7901904A02544E064400A2625121C4C +PT=A915D55AE8E14497F2693A55F83041F5 + +I=210 +KEY=B38E7ACF65FD41413DB99EE0B7FF0924 +IV=5421F3F4CDD3C6F9BF38184BC61904AA +CT=A915D55AE8E14497F2693A55F83041F5 +PT=66EA0D0968631F3BDA46921078E495C1 + +I=211 +KEY=D56477C60D9E5E7AE7FF0CF0CF1B9CE5 +IV=3B87243EE38BD474E4CBF34A7C592CFC +CT=66EA0D0968631F3BDA46921078E495C1 +PT=283826367D00718849A6539EE8CAD8BF + +I=212 +KEY=FD5C51F0709E2FF2AE595F6E27D1445A +IV=0FB53077D2BC27C544CD400A28212291 +CT=283826367D00718849A6539EE8CAD8BF +PT=B15EA2718FB406D457C8B96530EDC014 + +I=213 +KEY=4C02F381FF2A2926F991E60B173C844E +IV=8BFE654E422E9BCCE7F1357053E1130C +CT=B15EA2718FB406D457C8B96530EDC014 +PT=44238CE0F1765C7983BF408D5ECFA2BA + +I=214 +KEY=08217F610E5C755F7A2EA68649F326F4 +IV=86841D597FA91F54CBAD3C57FC1FC492 +CT=44238CE0F1765C7983BF408D5ECFA2BA +PT=BB6408099CA64F1216D204865449E967 + +I=215 +KEY=B345776892FA3A4D6CFCA2001DBACF93 +IV=849198CEA19F4AD76013D172867A0D20 +CT=BB6408099CA64F1216D204865449E967 +PT=B7E109C6813E686ADA396DDB277AD960 + +I=216 +KEY=04A47EAE13C45227B6C5CFDB3AC016F3 +IV=9C5E0182124701DA958CF68E1B9F8CC1 +CT=B7E109C6813E686ADA396DDB277AD960 +PT=65C77CB822CA10AE1F95B91F0A3F6436 + +I=217 +KEY=61630216310E4289A95076C430FF72C5 +IV=2BB9026F793A64A325E02B922E3A51DD +CT=65C77CB822CA10AE1F95B91F0A3F6436 +PT=48E9DB9FC3F883AD28A0299561444197 + +I=218 +KEY=298AD989F2F6C12481F05F5151BB3352 +IV=6BE0B03639C858D8F2CAE00EFE8FECCA +CT=48E9DB9FC3F883AD28A0299561444197 +PT=02B277AB327BCB5C91831BD376DC5211 + +I=219 +KEY=2B38AE22C08D0A781073448227676143 +IV=ADC033E3EEC3705031D2FB24205823A2 +CT=02B277AB327BCB5C91831BD376DC5211 +PT=FE288D6703CF6AB1635483305A82F192 + +I=220 +KEY=D5102345C34260C97327C7B27DE590D1 +IV=F637C38CB5DF86458225143E157B9415 +CT=FE288D6703CF6AB1635483305A82F192 +PT=B07BF02F795D13D972D5D6E556E8BA37 + +I=221 +KEY=656BD36ABA1F731001F211572B0D2AE6 +IV=824B7BBB3A339BF045C3CFEA9FD842B9 +CT=B07BF02F795D13D972D5D6E556E8BA37 +PT=D4661C2E102C6644724DA54BE291215D + +I=222 +KEY=B10DCF44AA33155473BFB41CC99C0BBB +IV=21FA242B2B9FFF0C7DC6B712A38A333B +CT=D4661C2E102C6644724DA54BE291215D +PT=F7EDEE448559A6ACD68815B6EEAF6E38 + +I=223 +KEY=46E021002F6AB3F8A537A1AA27336583 +IV=390906ECE51C92800D620E1CD1FD3574 +CT=F7EDEE448559A6ACD68815B6EEAF6E38 +PT=07257C91424F65E6752470A6960DF6D9 + +I=224 +KEY=41C55D916D25D61ED013D10CB13E935A +IV=918A010EC2B106DE32A220315999DF7D +CT=07257C91424F65E6752470A6960DF6D9 +PT=CCB4F3FCFFDEE9E93DD3AB4CC2DB870E + +I=225 +KEY=8D71AE6D92FB3FF7EDC07A4073E51454 +IV=7CF6B4948C4E04ED235F2CC96B0A6B49 +CT=CCB4F3FCFFDEE9E93DD3AB4CC2DB870E +PT=C455220E8C8847FF2592074A53104105 + +I=226 +KEY=49248C631E737808C8527D0A20F55551 +IV=4839E74C868786D0A109603CF98F1100 +CT=C455220E8C8847FF2592074A53104105 +PT=B4D0F5B4C15D7AD556ED4964A94C898F + +I=227 +KEY=FDF479D7DF2E02DD9EBF346E89B9DCDE +IV=5C6D9649E47FAA8A2DCAFB317B6BC0EA +CT=B4D0F5B4C15D7AD556ED4964A94C898F +PT=B515D2904555793DDC142618DCFF8464 + +I=228 +KEY=48E1AB479A7B7BE042AB1276554658BA +IV=E3573B4137C13BBA6CDD10D71042B8F6 +CT=B515D2904555793DDC142618DCFF8464 +PT=2C272D6589E2E6EE09067882795E9FB9 + +I=229 +KEY=64C6862213999D0E4BAD6AF42C18C703 +IV=08E335104FC5D18E2C11EF34B805F060 +CT=2C272D6589E2E6EE09067882795E9FB9 +PT=B38E39322245C4A2E170EBF36D764AD5 + +I=230 +KEY=D748BF1031DC59ACAADD8107416E8DD6 +IV=E134D0DEA38A23983766DA18DADA70E0 +CT=B38E39322245C4A2E170EBF36D764AD5 +PT=E7556255602B48D7CAC710A004FFFD2E + +I=231 +KEY=301DDD4551F7117B601A91A7459170F8 +IV=301C2808833418F45D5F97FB09A99504 +CT=E7556255602B48D7CAC710A004FFFD2E +PT=D4356D51B1C486AAC8BCF2F65312758C + +I=232 +KEY=E428B014E03397D1A8A6635116830574 +IV=264D556FA9A9D73510F562BBF983A4F7 +CT=D4356D51B1C486AAC8BCF2F65312758C +PT=B4D003D6C542B576A3EAEC8F1B017F5B + +I=233 +KEY=50F8B3C2257122A70B4C8FDE0D827A2F +IV=8821647AD3E9E529909E60D0F75DA400 +CT=B4D003D6C542B576A3EAEC8F1B017F5B +PT=10056819F314FF21114BE6209AB5508C + +I=234 +KEY=40FDDBDBD665DD861A0769FE97372AA3 +IV=CBD574F4DB1EFEE4E2EC9485D1192E04 +CT=10056819F314FF21114BE6209AB5508C +PT=6E7AA061FE85B6F8972CB0E793BE0CB0 + +I=235 +KEY=2E877BBA28E06B7E8D2BD91904892613 +IV=4F98EE1501681EC0E7834FE941DF6C6B +CT=6E7AA061FE85B6F8972CB0E793BE0CB0 +PT=45E0C0014219D77686E82E74E60608CA + +I=236 +KEY=6B67BBBB6AF9BC080BC3F76DE28F2ED9 +IV=1D34CAB2FF836A7E6568823784519170 +CT=45E0C0014219D77686E82E74E60608CA +PT=ACF686F9D6723EAFDBFE512AB3A8C6B1 + +I=237 +KEY=C7913D42BC8B82A7D03DA6475127E868 +IV=BEA74B4435F9F79D39B8CCE1F090D4B8 +CT=ACF686F9D6723EAFDBFE512AB3A8C6B1 +PT=F11FE34D158D40DEA10033BCE0253F30 + +I=238 +KEY=368EDE0FA906C279713D95FBB102D758 +IV=DF30EE5D8CA298BE630DDE4B6D8AD7AA +CT=F11FE34D158D40DEA10033BCE0253F30 +PT=4E970ACAB8B19C942C85FAA7825C5E67 + +I=239 +KEY=7819D4C511B75EED5DB86F5C335E893F +IV=DC3CCC928C02710EE91391032A3B557D +CT=4E970ACAB8B19C942C85FAA7825C5E67 +PT=0FF6C292507CF135036E04A391210466 + +I=240 +KEY=77EF165741CBAFD85ED66BFFA27F8D59 +IV=7CC57A486E05E36F852278450C03D39F +CT=0FF6C292507CF135036E04A391210466 +PT=BBEF94C8179E7A124492A252507D58E7 + +I=241 +KEY=CC00829F5655D5CA1A44C9ADF202D5BE +IV=BBB92F65197F8D6B388191E78E90A858 +CT=BBEF94C8179E7A124492A252507D58E7 +PT=BAF11150DD418ED7C28072A718815954 + +I=242 +KEY=76F193CF8B145B1DD8C4BB0AEA838CEA +IV=99DA5A29F934BE23EB74B6DE4E8CC740 +CT=BAF11150DD418ED7C28072A718815954 +PT=A935099B91A35655C850939D2FED1569 + +I=243 +KEY=DFC49A541AB70D4810942897C56E9983 +IV=92401B7E92A49FA5A6905E51E49D51C2 +CT=A935099B91A35655C850939D2FED1569 +PT=F60E1B5D10CDA17FC762798B86B8708D + +I=244 +KEY=29CA81090A7AAC37D7F6511C43D6E90E +IV=C2A57521674EB0FB3E46DE2CC1DCF419 +CT=F60E1B5D10CDA17FC762798B86B8708D +PT=0B976079B61F46E7F3CCCD17E23D872F + +I=245 +KEY=225DE170BC65EAD0243A9C0BA1EB6E21 +IV=66970AE807FED1E3581496C9FBE5FF50 +CT=0B976079B61F46E7F3CCCD17E23D872F +PT=FB44F0094A5FC03BD0A27391E58D0AA3 + +I=246 +KEY=D9191179F63A2AEBF498EF9A44666482 +IV=ED7B2ED1AFF7DB9B514D6E4DFAEA484B +CT=FB44F0094A5FC03BD0A27391E58D0AA3 +PT=41A534A69AD25FEB39BB9F754F15D8FE + +I=247 +KEY=98BC25DF6CE87500CD2370EF0B73BC7C +IV=B7E8C7F08BCE1CF1CC2568E18C18C92B +CT=41A534A69AD25FEB39BB9F754F15D8FE +PT=022B28D4F7355E14F99F654B6C35BC16 + +I=248 +KEY=9A970D0B9BDD2B1434BC15A46746006A +IV=F2EF32464FC7E5F3D397C259CB963B7F +CT=022B28D4F7355E14F99F654B6C35BC16 +PT=28F18EA03ADEB36C40FD8FBC590EC6C8 + +I=249 +KEY=B26683ABA103987874419A183E48C6A2 +IV=687E822CCFC5800E88E59ED7DEC1409D +CT=28F18EA03ADEB36C40FD8FBC590EC6C8 +PT=661F9AEA300100333D64FCDD1212C663 + +I=250 +KEY=D47919419102984B492566C52C5A00C1 +IV=3922BB08EE1B4CC75881D1D6F66B8EE0 +CT=661F9AEA300100333D64FCDD1212C663 +PT=11C4D360F585EDF544D5479AE1ABDBE6 + +I=251 +KEY=C5BDCA21648775BE0DF0215FCDF1DB27 +IV=9B7C0D7D0EA8CAD77B331F2E0CA1E639 +CT=11C4D360F585EDF544D5479AE1ABDBE6 +PT=2E4695733B01CC78993E6EB464784223 + +I=252 +KEY=EBFB5F525F86B9C694CE4FEBA9899904 +IV=A2BF273F12FE1F4B2F56A86CAFD9C5BF +CT=2E4695733B01CC78993E6EB464784223 +PT=1CC514E9F4B13FFEF3B076DAC8C62877 + +I=253 +KEY=F73E4BBBAB378638677E3931614FB173 +IV=1D4960EBE667AC5DE5ED767183838846 +CT=1CC514E9F4B13FFEF3B076DAC8C62877 +PT=3B1A7D179DDED66A37F3053B8B231EEA + +I=254 +KEY=CC2436AC36E95052508D3C0AEA6CAF99 +IV=974643FDFDB695A44B7EF8676A2B87DD +CT=3B1A7D179DDED66A37F3053B8B231EEA +PT=620A4E7A25E8D05779C0FB8CEBA55A74 + +I=255 +KEY=AE2E78D613018005294DC78601C9F5ED +IV=C9A1D92DB7D553DCAEB3BB81B489257A +CT=620A4E7A25E8D05779C0FB8CEBA55A74 +PT=93508503278ECECE65D67B5F50962C4E + +I=256 +KEY=3D7EFDD5348F4ECB4C9BBCD9515FD9A3 +IV=108E736F1DCD178A8648F6AA6D527732 +CT=93508503278ECECE65D67B5F50962C4E +PT=EA9E953D8B62FFAFF9FAFB97F614D65C + +I=257 +KEY=D7E068E8BFEDB164B561474EA74B0FFF +IV=B893A94302C0DAFB19D7B6656085DCA9 +CT=EA9E953D8B62FFAFF9FAFB97F614D65C +PT=1452ED26E774029EF30D272F8548C2F8 + +I=258 +KEY=C3B285CE5899B3FA466C60612203CD07 +IV=668FF6719E5A29A99876227EEDE5818F +CT=1452ED26E774029EF30D272F8548C2F8 +PT=4083167E5ED1A1A449C1825B84F321E1 + +I=259 +KEY=833193B00648125E0FADE23AA6F0ECE6 +IV=9F6375A022543AB8303368A235813F02 +CT=4083167E5ED1A1A449C1825B84F321E1 +PT=9206639D076685FD2078F9B984B7A03F + +I=260 +KEY=1137F02D012E97A32FD51B8322474CD9 +IV=1B95128E90B110AED9D543D2A996271F +CT=9206639D076685FD2078F9B984B7A03F +PT=AAA3F2BD0126DFD5007DD2835CCB0109 + +I=261 +KEY=BB940290000848762FA8C9007E8C4DD0 +IV=BB2E26A9CDEF9D1B2940EFFBA1971A5D +CT=AAA3F2BD0126DFD5007DD2835CCB0109 +PT=B58BB3761519C1726D75AE96313FB7DE + +I=262 +KEY=0E1FB1E61511890442DD67964FB3FA0E +IV=68D3EC37EE43E3F24072F69F2DFA768D +CT=B58BB3761519C1726D75AE96313FB7DE +PT=4558CD47C012B7293396D7EDFE3CEA85 + +I=263 +KEY=4B477CA1D5033E2D714BB07BB18F108B +IV=F7E107DBF4DDBF7974B699536A4E2803 +CT=4558CD47C012B7293396D7EDFE3CEA85 +PT=6F43B6B28AEF5DD1B66279ACAAB9A589 + +I=264 +KEY=2404CA135FEC63FCC729C9D71B36B502 +IV=B3E6DA8DE5DDF7ED6F832D1306A1C04A +CT=6F43B6B28AEF5DD1B66279ACAAB9A589 +PT=1BA743E148BC164C4C8324D665B5A3BD + +I=265 +KEY=3FA389F2175075B08BAAED017E8316BF +IV=8BBBB56B39893C8F286561EF6E47E66A +CT=1BA743E148BC164C4C8324D665B5A3BD +PT=49A40365092DD1360D916AAEAFD03FC1 + +I=266 +KEY=76078A971E7DA486863B87AFD153297E +IV=48BA08703A306F772E78F660173A26B3 +CT=49A40365092DD1360D916AAEAFD03FC1 +PT=DF7DEB5968D683AAA274B0D5D3F9AA03 + +I=267 +KEY=A97A61CE76AB272C244F377A02AA837D +IV=0C7832F9CDF65DADA7FA809B8DE709C3 +CT=DF7DEB5968D683AAA274B0D5D3F9AA03 +PT=69689E97E9B166DA53E25BDFBCAF4A97 + +I=268 +KEY=C012FF599F1A41F677AD6CA5BE05C9EA +IV=05BC03F59CD8C5FAE4A7240E6168CF41 +CT=69689E97E9B166DA53E25BDFBCAF4A97 +PT=5F87DC71EF2918F75A94E43007FF50E6 + +I=269 +KEY=9F952328703359012D398895B9FA990C +IV=4233E654802B55155E158B650B64718E +CT=5F87DC71EF2918F75A94E43007FF50E6 +PT=4F170790775A6A147E99D251C401969A + +I=270 +KEY=D08224B80769331553A05AC47DFB0F96 +IV=4AEAE53003D5085F5963CC36C4589941 +CT=4F170790775A6A147E99D251C401969A +PT=E566D46360EF38E5CFF0C2E7E7E0D679 + +I=271 +KEY=35E4F0DB67860BF09C5098239A1BD9EF +IV=F6CBFF51F6E59B7AAA9EB1261707429A +CT=E566D46360EF38E5CFF0C2E7E7E0D679 +PT=F7189C4B9E1048ED66D9B7CCD089C5F9 + +I=272 +KEY=C2FC6C90F996431DFA892FEF4A921C16 +IV=0A05A4BFBBCC8B3E218C123A95FFF475 +CT=F7189C4B9E1048ED66D9B7CCD089C5F9 +PT=68FB0909789DBFA672BEEF5DF0017B63 + +I=273 +KEY=AA076599810BFCBB8837C0B2BA936775 +IV=DF1A3AF147E72C2CEAE5D8713D52F572 +CT=68FB0909789DBFA672BEEF5DF0017B63 +PT=AF2784590089186BED3A48ADC1B68562 + +I=274 +KEY=0520E1C08182E4D0650D881F7B25E217 +IV=BFDC5ECF596F5F3CFFEAAF4B961209FA +CT=AF2784590089186BED3A48ADC1B68562 +PT=E8C29D3C129AB8FA797EFDCE4CE4D4F2 + +I=275 +KEY=EDE27CFC93185C2A1C7375D137C136E5 +IV=49195E71516D5117C26814F98FD94C31 +CT=E8C29D3C129AB8FA797EFDCE4CE4D4F2 +PT=6ACF2AE12C38DB520F49E6C90D4B8F03 + +I=276 +KEY=872D561DBF208778133A93183A8AB9E6 +IV=E4FA7788D6E7AFBD08884BFCFA74D30C +CT=6ACF2AE12C38DB520F49E6C90D4B8F03 +PT=78FEA3B57D6176C44CE753FB01416CA6 + +I=277 +KEY=FFD3F5A8C241F1BC5FDDC0E33BCBD540 +IV=08E333F43615229D95E7C425A04EA2B7 +CT=78FEA3B57D6176C44CE753FB01416CA6 +PT=5030D7131ABBD7AC323BA31B602B776E + +I=278 +KEY=AFE322BBD8FA26106DE663F85BE0A22E +IV=64BDE35106D9A66A4216EA20F6C52D06 +CT=5030D7131ABBD7AC323BA31B602B776E +PT=14B32E8BD3BD9D82613E32536E6A9F91 + +I=279 +KEY=BB500C300B47BB920CD851AB358A3DBF +IV=8FB9E6BDCD50610E97CF731216CFE698 +CT=14B32E8BD3BD9D82613E32536E6A9F91 +PT=1F22542AFCE63AA92CCDAF45F8DAEEF0 + +I=280 +KEY=A472581AF7A1813B2015FEEECD50D34F +IV=E18B3C5EDA8CDA9E94A376CEEF687D9F +CT=1F22542AFCE63AA92CCDAF45F8DAEEF0 +PT=FC986510E3ED40994D1C33201D0EDB27 + +I=281 +KEY=58EA3D0A144CC1A26D09CDCED05E0868 +IV=D1828C9DDB263064AD259A2360B3DFBA +CT=FC986510E3ED40994D1C33201D0EDB27 +PT=06C1CE557C9AC5D40560CF2D40DCC47C + +I=282 +KEY=5E2BF35F68D60476686902E39082CC14 +IV=3454FD0698CC8CD949970509C23E50F6 +CT=06C1CE557C9AC5D40560CF2D40DCC47C +PT=4287FA420FD9AFCAB7E290273BDF4054 + +I=283 +KEY=1CAC091D670FABBCDF8B92C4AB5D8C40 +IV=C2F0C044A975ADBD20DE56858A074886 +CT=4287FA420FD9AFCAB7E290273BDF4054 +PT=447AFDD3ACF0DEEB0385799789FBAFF0 + +I=284 +KEY=58D6F4CECBFF7557DC0EEB5322A623B0 +IV=299C337821B0779A7ADC3A04316A6373 +CT=447AFDD3ACF0DEEB0385799789FBAFF0 +PT=BA0BBC980827E87EEA51E66C92C96B31 + +I=285 +KEY=E2DD4856C3D89D29365F0D3FB06F4881 +IV=2368291AD179C3C143E636898EB3E104 +CT=BA0BBC980827E87EEA51E66C92C96B31 +PT=77A6131415B251049423FFFB1F3A8A3A + +I=286 +KEY=957B5B42D66ACC2DA27CF2C4AF55C2BB +IV=14300EA81B57E102AEDD97CCD466E18A +CT=77A6131415B251049423FFFB1F3A8A3A +PT=A7AEC0CC599D56347A72D934DDAC7899 + +I=287 +KEY=32D59B8E8FF79A19D80E2BF072F9BA22 +IV=FD62415C90DACCD22EC364877DB0CB24 +CT=A7AEC0CC599D56347A72D934DDAC7899 +PT=1B1100FCB9F85D8CCFDEC5865083B44D + +I=288 +KEY=29C49B72360FC79517D0EE76227A0E6F +IV=6CB24892D26E43E63819C372D5EB4F6D +CT=1B1100FCB9F85D8CCFDEC5865083B44D +PT=33E9BBD018604F301C2543878FCCCA5C + +I=289 +KEY=1A2D20A22E6F88A50BF5ADF1ADB6C433 +IV=50D84A03998B897D1AE217FEA9A955C4 +CT=33E9BBD018604F301C2543878FCCCA5C +PT=07163D652DB035C091830042D6047DF3 + +I=290 +KEY=1D3B1DC703DFBD659A76ADB37BB2B9C0 +IV=092DF26C855F07690836203E3E1790D0 +CT=07163D652DB035C091830042D6047DF3 +PT=AD6647AF8EFCD4F3B2ECDB4D6FFFC1EB + +I=291 +KEY=B05D5A688D236996289A76FE144D782B +IV=68634C941957E3F58F71BE37D7C5C78B +CT=AD6647AF8EFCD4F3B2ECDB4D6FFFC1EB +PT=D2B51122154D10F67D2C07BD75D5E8E2 + +I=292 +KEY=62E84B4A986E796055B67143619890C9 +IV=3C85044F6438FAA021BB7985A63A959D +CT=D2B51122154D10F67D2C07BD75D5E8E2 +PT=4131E9296FECD2DF35EDFBF0CBD0E54B + +I=293 +KEY=23D9A263F782ABBF605B8AB3AA487582 +IV=46D47F3F12B6ADD5580CE8CE7C7359CD +CT=4131E9296FECD2DF35EDFBF0CBD0E54B +PT=5AEA3E73A6EC0D9D683A3526AC1C0E58 + +I=294 +KEY=79339C10516EA6220861BF9506547BDA +IV=D3C58B190FDA0838C770C2185C553D97 +CT=5AEA3E73A6EC0D9D683A3526AC1C0E58 +PT=A21B17CB4588C30CAD6DF25A5E83E273 + +I=295 +KEY=DB288BDB14E6652EA50C4DCF58D799A9 +IV=870E7F0E3109712E84C58BEC0E7032F6 +CT=A21B17CB4588C30CAD6DF25A5E83E273 +PT=0021FF3BB8336E607B8DE10117005230 + +I=296 +KEY=DB0974E0ACD50B4EDE81ACCE4FD7CB99 +IV=2FC82B298A60FC40DA3EFD4E800DB063 +CT=0021FF3BB8336E607B8DE10117005230 +PT=2EFA32680ECD84891B447393F7C1AC88 + +I=297 +KEY=F5F34688A2188FC7C5C5DF5DB8166711 +IV=E1B86C9FC466B72BE40F65973FC41FC4 +CT=2EFA32680ECD84891B447393F7C1AC88 +PT=722117C1EE83FBA840EFEE86A930579F + +I=298 +KEY=87D251494C9B746F852A31DB1126308E +IV=48E347A705B6E322153BFE567931346F +CT=722117C1EE83FBA840EFEE86A930579F +PT=A684344231EC4C03726A0DC20EADA36D + +I=299 +KEY=2156650B7D77386CF7403C191F8B93E3 +IV=4CD618E5F959FC4C66602263F6C5C652 +CT=A684344231EC4C03726A0DC20EADA36D +PT=F40BFBEAC1C1BD1621FBAE1B605BD092 + +I=300 +KEY=D55D9EE1BCB6857AD6BB92027FD04371 +IV=5A41E8952E6B1C551C4691DE9C0A4B6D +CT=F40BFBEAC1C1BD1621FBAE1B605BD092 +PT=6ECDBFB3947C7E81C7BD4BE93B603728 + +I=301 +KEY=BB90215228CAFBFB1106D9EB44B07459 +IV=52E2726B0855F993E1075077B3AB1E77 +CT=6ECDBFB3947C7E81C7BD4BE93B603728 +PT=71E051375A3B974FE523DA47862E24AE + +I=302 +KEY=CA70706572F16CB4F42503ACC29E50F7 +IV=76B6637161FBE4760FCE90E9868B441A +CT=71E051375A3B974FE523DA47862E24AE +PT=CC6CFBCF9A62A3AE55F6B040673B25B3 + +I=303 +KEY=061C8BAAE893CF1AA1D3B3ECA5A57544 +IV=5563B0C2350A4ED76EE0C322480884FB +CT=CC6CFBCF9A62A3AE55F6B040673B25B3 +PT=DA71B26C4EE3FB1FD413FD0757B379E6 + +I=304 +KEY=DC6D39C6A670340575C04EEBF2160CA2 +IV=45C1C5DAF8DE9170C01E554DD36C564E +CT=DA71B26C4EE3FB1FD413FD0757B379E6 +PT=BCD4BC394FFB46207EF0A8EC9883BD55 + +I=305 +KEY=60B985FFE98B72250B30E6076A95B1F7 +IV=38E5B69E6D82A760BFD65CBAACC56F8A +CT=BCD4BC394FFB46207EF0A8EC9883BD55 +PT=FD997E7A7B77E5DF637182399779AF75 + +I=306 +KEY=9D20FB8592FC97FA6841643EFDEC1E82 +IV=8EB39B261910419E43B178DCD6803572 +CT=FD997E7A7B77E5DF637182399779AF75 +PT=71749C51136457B604CD8B4C193928A8 + +I=307 +KEY=EC5467D48198C04C6C8CEF72E4D5362A +IV=6DFA447305215066A0B5671E5AB80951 +CT=71749C51136457B604CD8B4C193928A8 +PT=DF48D76E54B4264304B0EC036DFDADDE + +I=308 +KEY=331CB0BAD52CE60F683C037189289BF4 +IV=8C2B316ECA96DB57322853E07BE47AB3 +CT=DF48D76E54B4264304B0EC036DFDADDE +PT=5E2BD374B9856C573A4DEBF1B8F453EC + +I=309 +KEY=6D3763CE6CA98A585271E88031DCC818 +IV=E541AC59CFDBEA97D1AE5221F849838E +CT=5E2BD374B9856C573A4DEBF1B8F453EC +PT=D7F97B76A8D3076D343A22459EC4765D + +I=310 +KEY=BACE18B8C47A8D35664BCAC5AF18BE45 +IV=B359889A22B9502571E4817C47BC5348 +CT=D7F97B76A8D3076D343A22459EC4765D +PT=E24F05EEE812BD3389AC0AAC4172F5C6 + +I=311 +KEY=58811D562C683006EFE7C069EE6A4B83 +IV=33F8D881A783051987103096B6C734C3 +CT=E24F05EEE812BD3389AC0AAC4172F5C6 +PT=A2AB44CC9C41A8748201DA6F9429AB39 + +I=312 +KEY=FA2A599AB02998726DE61A067A43E0BA +IV=2028704442AE252BCF1D081C5EE2D80B +CT=A2AB44CC9C41A8748201DA6F9429AB39 +PT=E8FA100D1D28186196BAF990A80109AA + +I=313 +KEY=12D04997AD018013FB5CE396D242E910 +IV=6384E3612062BC6850C94C3B14934A6F +CT=E8FA100D1D28186196BAF990A80109AA +PT=683AEF47A8990E2F8AAD8813789069B1 + +I=314 +KEY=7AEAA6D005988E3C71F16B85AAD280A1 +IV=12F78728F3B0EFAC7D304257E47ED5C8 +CT=683AEF47A8990E2F8AAD8813789069B1 +PT=F3121C95A5BACDEAEFA87C4EE40B6C6D + +I=315 +KEY=89F8BA45A02243D69E5917CB4ED9ECCC +IV=FE654BC69677E13383C4206BFB7896A6 +CT=F3121C95A5BACDEAEFA87C4EE40B6C6D +PT=AE9701378E128847A2669B516795D586 + +I=316 +KEY=276FBB722E30CB913C3F8C9A294C394A +IV=E79D5C468BCBA36A79B74F32F28FA635 +CT=AE9701378E128847A2669B516795D586 +PT=D97D988A40C5B323794F160FE8639262 + +I=317 +KEY=FE1223F86EF578B245709A95C12FAB28 +IV=4F3055450C627AD4712E042666AC0812 +CT=D97D988A40C5B323794F160FE8639262 +PT=32381BA55D5C0C91D683D57593772496 + +I=318 +KEY=CC2A385D33A9742393F34FE052588FBE +IV=172165B468B83B62B41A2B4310461193 +CT=32381BA55D5C0C91D683D57593772496 +PT=4D555F31A60F1007B96FBB458B06A619 + +I=319 +KEY=817F676C95A664242A9CF4A5D95E29A7 +IV=5D5EEBEA67DCD5F7851619F1BAA6414E +CT=4D555F31A60F1007B96FBB458B06A619 +PT=23D1AC0F18C20FCE7E5CC4619F8376D5 + +I=320 +KEY=A2AECB638D646BEA54C030C446DD5F72 +IV=54154B82B5820D5892DABD15B403345D +CT=23D1AC0F18C20FCE7E5CC4619F8376D5 +PT=2E55905A38F818CC04D8A792D2007332 + +I=321 +KEY=8CFB5B39B59C73265018975694DD2C40 +IV=AC47D7619A587DC8213B749918FCFEA8 +CT=2E55905A38F818CC04D8A792D2007332 +PT=010F3396885F8F6BF15170B8E6D221BD + +I=322 +KEY=8DF468AF3DC3FC4DA149E7EE720F0DFD +IV=6CE249D2E89C61ACD029AA3C122427D1 +CT=010F3396885F8F6BF15170B8E6D221BD +PT=4DB3972D9851B8A4B3150A43210D36F0 + +I=323 +KEY=C047FF82A59244E9125CEDAD53023B0D +IV=07A578889914E113C1C4DE01DC4B1DE4 +CT=4DB3972D9851B8A4B3150A43210D36F0 +PT=84F64CFFD705E82704FF3DA4FC074B34 + +I=324 +KEY=44B1B37D7297ACCE16A3D009AF057039 +IV=CE73ADCD7BCF1807C084276EDD765256 +CT=84F64CFFD705E82704FF3DA4FC074B34 +PT=5964DF8E8D656846EE574635787F7B18 + +I=325 +KEY=1DD56CF3FFF2C488F8F4963CD77A0B21 +IV=679903574013011E62CC5798B9633607 +CT=5964DF8E8D656846EE574635787F7B18 +PT=E28E7E3AA93802BEEFE258F38F5D2E5C + +I=326 +KEY=FF5B12C956CAC6361716CECF5827257D +IV=678D8583A022C60BCE2C227627A548B2 +CT=E28E7E3AA93802BEEFE258F38F5D2E5C +PT=D297684A7C50765C413BFA37B5E1E256 + +I=327 +KEY=2DCC7A832A9AB06A562D34F8EDC6C72B +IV=4EF9AACC21733B65B4DD0B1F105D4037 +CT=D297684A7C50765C413BFA37B5E1E256 +PT=9EF5F9A2B14B090A201DE74E4CF714C8 + +I=328 +KEY=B33983219BD1B9607630D3B6A131D3E3 +IV=5CC41FCC9EC19619BA06D10BBC6E1F5F +CT=9EF5F9A2B14B090A201DE74E4CF714C8 +PT=81EF000CF6CA737E0F449927E66F6392 + +I=329 +KEY=32D6832D6D1BCA1E79744A91475EB071 +IV=6DE60CE2986CF80C5D588FA1F9A8C3A0 +CT=81EF000CF6CA737E0F449927E66F6392 +PT=3BE177EE9F8F7BE3BCE0FAA70C0A5025 + +I=330 +KEY=0937F4C3F294B1FDC594B0364B54E054 +IV=BE2F86A52BEED4497790D6134CF0D64E +CT=3BE177EE9F8F7BE3BCE0FAA70C0A5025 +PT=DD313134DB126529F349808B3E766795 + +I=331 +KEY=D406C5F72986D4D436DD30BD752287C1 +IV=A89E52478FDEF91AF151097CED84579C +CT=DD313134DB126529F349808B3E766795 +PT=330203EA36484C8E091F00CD2255E599 + +I=332 +KEY=E704C61D1FCE985A3FC2307057776258 +IV=1AEF7BA63A3E3B6D2EB8EB1980D3E581 +CT=330203EA36484C8E091F00CD2255E599 +PT=E28A47CDB7DB0351006C1D9FB227FCEF + +I=333 +KEY=058E81D0A8159B0B3FAE2DEFE5509EB7 +IV=F67C7FCF8C5AA1574A165D8CBE694BF4 +CT=E28A47CDB7DB0351006C1D9FB227FCEF +PT=ACF869797690853BE142BB7BAC735FC8 + +I=334 +KEY=A976E8A9DE851E30DEEC96944923C17F +IV=636F181C4735E700897928BFC60A43EB +CT=ACF869797690853BE142BB7BAC735FC8 +PT=60FF9BF36809DAEB94F823FC6458B26A + +I=335 +KEY=C989735AB68CC4DB4A14B5682D7B7315 +IV=0829C0EE6B170C490C7A73401761CEAA +CT=60FF9BF36809DAEB94F823FC6458B26A +PT=17630CBEAB904F7996301515F24A1F27 + +I=336 +KEY=DEEA7FE41D1C8BA2DC24A07DDF316C32 +IV=A4E0624D86F1098D2DD4D0408897ACED +CT=17630CBEAB904F7996301515F24A1F27 +PT=A1E35C3E2FA1B1DB11DB96E7DD58AB37 + +I=337 +KEY=7F0923DA32BD3A79CDFF369A0269C705 +IV=D3639A296FF168ED773785CFCACD1015 +CT=A1E35C3E2FA1B1DB11DB96E7DD58AB37 +PT=14F5408460708A69A22A2023B01969CE + +I=338 +KEY=6BFC635E52CDB0106FD516B9B270AECB +IV=37CD0428A0C08CC6AABAAA05D8830557 +CT=14F5408460708A69A22A2023B01969CE +PT=516991CA6530D20AB121394F51288880 + +I=339 +KEY=3A95F29437FD621ADEF42FF6E358264B +IV=FB52F5A95F2E3665D44F0AEACB88B108 +CT=516991CA6530D20AB121394F51288880 +PT=FB0C32B66729736F8E5EC8C92D80FDC5 + +I=340 +KEY=C199C02250D4117550AAE73FCED8DB8E +IV=403B43C740215D94E8FBAE22846D3B0A +CT=FB0C32B66729736F8E5EC8C92D80FDC5 +PT=C243054D022E7E9EFC21F965C71D63EB + +I=341 +KEY=03DAC56F52FA6FEBAC8B1E5A09C5B865 +IV=663796B211E7F6E05B4A107B16A904B0 +CT=C243054D022E7E9EFC21F965C71D63EB +PT=6CA56F6792355B2A7A60A4467A85F71E + +I=342 +KEY=6F7FAA08C0CF34C1D6EBBA1C73404F7B +IV=A23B73DF1477EC98202135164C6EF1AB +CT=6CA56F6792355B2A7A60A4467A85F71E +PT=BC590C8B427B013F873B2F5F8D66D5D1 + +I=343 +KEY=D326A68382B435FE51D09543FE269AAA +IV=E84DF462C62D594AAD94C33C446E18FC +CT=BC590C8B427B013F873B2F5F8D66D5D1 +PT=D37CAA9BEA300FF6219349DBA25DA0A6 + +I=344 +KEY=005A0C1868843A087043DC985C7B3A0C +IV=9AAD322884EBE93D0FA084E144600174 +CT=D37CAA9BEA300FF6219349DBA25DA0A6 +PT=AE50C328AFFC39A103C767C1FD337449 + +I=345 +KEY=AE0ACF30C77803A97384BB59A1484E45 +IV=9CEE91362FB0D50ABCEB58EF49EC3614 +CT=AE50C328AFFC39A103C767C1FD337449 +PT=882939453C6E156CD023B468EDD16C95 + +I=346 +KEY=2623F675FB1616C5A3A70F314C9922D0 +IV=5626126CC424BF26D92C822442E4221E +CT=882939453C6E156CD023B468EDD16C95 +PT=B9A97FE0DEF66604F6CE928AAB532EC2 + +I=347 +KEY=9F8A899525E070C155699DBBE7CA0C12 +IV=E5BB374C14E36FD0C2D5F9191C967EC7 +CT=B9A97FE0DEF66604F6CE928AAB532EC2 +PT=6ED0FF2FE8DA900A33AE20F7C1C2E457 + +I=348 +KEY=F15A76BACD3AE0CB66C7BD4C2608E845 +IV=4493B9F0FF63D392273302B6932C8F77 +CT=6ED0FF2FE8DA900A33AE20F7C1C2E457 +PT=B7583A56BED55067A520B4F5E5C1528F + +I=349 +KEY=46024CEC73EFB0ACC3E709B9C3C9BACA +IV=12E2BFD3EAB69E5132E3CDF8BAFBD45E +CT=B7583A56BED55067A520B4F5E5C1528F +PT=28874485575E292B0C83E1B568019BF0 + +I=350 +KEY=6E85086924B19987CF64E80CABC8213A +IV=3CEFDC726C919CA265CD6C28A05DE542 +CT=28874485575E292B0C83E1B568019BF0 +PT=A35D16BBB96BF3F9E06D96EDA9BB44BB + +I=351 +KEY=CDD81ED29DDA6A7E2F097EE102736581 +IV=4AE79901700F018D1E5D95A9FAD762F2 +CT=A35D16BBB96BF3F9E06D96EDA9BB44BB +PT=367E6880D369D482E7E64CFCD1BCC870 + +I=352 +KEY=FBA676524EB3BEFCC8EF321DD3CFADF1 +IV=52EEDB058A8E1FE7C651D484F86F941F +CT=367E6880D369D482E7E64CFCD1BCC870 +PT=32B33E97C94953392A738A964DB121FC + +I=353 +KEY=C91548C587FAEDC5E29CB88B9E7E8C0D +IV=B3704291187E9D55901DD237EC1E2F24 +CT=32B33E97C94953392A738A964DB121FC +PT=965A9A0C0287AB8535436E95CC9BFB99 + +I=354 +KEY=5F4FD2C9857D4640D7DFD61E52E57794 +IV=B3878FC256FA4F9ED0BA05FF51C0CE2A +CT=965A9A0C0287AB8535436E95CC9BFB99 +PT=367A5C93099ACF72353DAC320A3B766E + +I=355 +KEY=69358E5A8CE78932E2E27A2C58DE01FA +IV=774EA78AECAF5A1D7CC1785DE91CAB01 +CT=367A5C93099ACF72353DAC320A3B766E +PT=116EDEB1D0E6F8D1BB58AF648429B792 + +I=356 +KEY=785B50EB5C0171E359BAD548DCF7B668 +IV=FB1EC4218C5F733A54DEA7F753F45D68 +CT=116EDEB1D0E6F8D1BB58AF648429B792 +PT=EF3C679822E3A906F380CD07EBE65F09 + +I=357 +KEY=976737737EE2D8E5AA3A184F3711E961 +IV=8BBE09AFE41C5A78EBA0524212AC570F +CT=EF3C679822E3A906F380CD07EBE65F09 +PT=291B066A30A3B11681D414A4BB5311D5 + +I=358 +KEY=BE7C31194E4169F32BEE0CEB8C42F8B4 +IV=4E8F651C06778A964AA7D43999E41FD6 +CT=291B066A30A3B11681D414A4BB5311D5 +PT=764F8FD22FE0BD98852F259EA6DC6F7C + +I=359 +KEY=C833BECB61A1D46BAEC129752A9E97C8 +IV=E90A35007EE7F001D1F5982BF2477C82 +CT=764F8FD22FE0BD98852F259EA6DC6F7C +PT=66016373A6B1A3797A1B2D2B19B73126 + +I=360 +KEY=AE32DDB8C7107712D4DA045E3329A6EE +IV=46FF289808B1AF6B290CB5AF05747085 +CT=66016373A6B1A3797A1B2D2B19B73126 +PT=3367064ECF5CA978001887DBDE40DE5A + +I=361 +KEY=9D55DBF6084CDE6AD4C28385ED6978B4 +IV=9BAC8819E1CA613CFAA730FBC2034168 +CT=3367064ECF5CA978001887DBDE40DE5A +PT=5C4F01D47C9DA94DE95FC26763CC1146 + +I=362 +KEY=C11ADA2274D177273D9D41E28EA569F2 +IV=A5CE34A846E1D0A737963C49FAD6378E +CT=5C4F01D47C9DA94DE95FC26763CC1146 +PT=D41D854E42863F161E76A2397020C321 + +I=363 +KEY=15075F6C3657483123EBE3DBFE85AAD3 +IV=2CC823722DD3E8F15035875ED43513E2 +CT=D41D854E42863F161E76A2397020C321 +PT=1C542DC0B54A053471AF583C909AB3C4 + +I=364 +KEY=095372AC831D4D055244BBE76E1F1917 +IV=9799D03B6AD46BECD981279B35DF707C +CT=1C542DC0B54A053471AF583C909AB3C4 +PT=958D0254D7AFE1E678A9844DF4F4D18D + +I=365 +KEY=9CDE70F854B2ACE32AED3FAA9AEBC89A +IV=E0E401C7BA5E319F0D60AB765CBEE176 +CT=958D0254D7AFE1E678A9844DF4F4D18D +PT=C54888169B30587E732BD7213EE5B1A3 + +I=366 +KEY=5996F8EECF82F49D59C6E88BA40E7939 +IV=711DA6521732E6868111DCC1C835F9DF +CT=C54888169B30587E732BD7213EE5B1A3 +PT=446F234FCADA809A8B2E167A86C9EB36 + +I=367 +KEY=1DF9DBA105587407D2E8FEF122C7920F +IV=B7008BC907C546A56743C292185C2B02 +CT=446F234FCADA809A8B2E167A86C9EB36 +PT=6AD93BC7E18B48810664CD1C528BA6C4 + +I=368 +KEY=7720E066E4D33C86D48C33ED704C34CB +IV=4D7DD98183E56F71D72DB76187FC5F95 +CT=6AD93BC7E18B48810664CD1C528BA6C4 +PT=0D75BD2B8683FB819EB7F71E2E0836A7 + +I=369 +KEY=7A555D4D6250C7074A3BC4F35E44026C +IV=F4DCFB73BBE7EB5348D56F81BCBC0971 +CT=0D75BD2B8683FB819EB7F71E2E0836A7 +PT=8CBE14862E93FE011A4F45518C7258FA + +I=370 +KEY=F6EB49CB4CC33906507481A2D2365A96 +IV=5432FBF1480AA398F09CA5AF375FA394 +CT=8CBE14862E93FE011A4F45518C7258FA +PT=4026D669905762F0790B6497646A2D4D + +I=371 +KEY=B6CD9FA2DC945BF6297FE535B65C77DB +IV=CA462DC9F029A8311CA45A4116DADC1D +CT=4026D669905762F0790B6497646A2D4D +PT=A8CD2E187CF274756E5736D420853435 + +I=372 +KEY=1E00B1BAA0662F834728D3E196D943EE +IV=4FC9E7688352F4700C5F380BFD1F4FB2 +CT=A8CD2E187CF274756E5736D420853435 +PT=A99410B60322340E279C87D3D26793AA + +I=373 +KEY=B794A10CA3441B8D60B4543244BED044 +IV=4D90B1A30EB7E957FAE3DC8C132F4F42 +CT=A99410B60322340E279C87D3D26793AA +PT=D136F990196C667EC35E3A0492C39968 + +I=374 +KEY=66A2589CBA287DF3A3EA6E36D67D492C +IV=6FAD87F358F0C702C5E9E599093219ED +CT=D136F990196C667EC35E3A0492C39968 +PT=8CE49C1BAACAB69432DDA2FF4250C7B2 + +I=375 +KEY=EA46C48710E2CB679137CCC9942D8E9E +IV=2B6FF495B7E482360E31949C7C9B2E2B +CT=8CE49C1BAACAB69432DDA2FF4250C7B2 +PT=7942B80F57EA24FA200451B37899F9E2 + +I=376 +KEY=93047C884708EF9DB1339D7AECB4777C +IV=21FDC4C9B03A1A9A3F87FF9AAC80FAAE +CT=7942B80F57EA24FA200451B37899F9E2 +PT=DE156D56E199FDBB2600DBF9FC254003 + +I=377 +KEY=4D1111DEA6911226973346831091377F +IV=387612E399C62916B394A9FC6BC0F059 +CT=DE156D56E199FDBB2600DBF9FC254003 +PT=C302C494D910640271695324E64B0992 + +I=378 +KEY=8E13D54A7F817624E65A15A7F6DA3EED +IV=34BCABDE4646BCC05CAF7E61CBF1F8D2 +CT=C302C494D910640271695324E64B0992 +PT=110CE84E5B81867CE4FCCD1BBB5FD792 + +I=379 +KEY=9F1F3D042400F05802A6D8BC4D85E97F +IV=C7898DA9ABF2A3D364C228A83525B04F +CT=110CE84E5B81867CE4FCCD1BBB5FD792 +PT=7B94C0E4849AD65291F0F7BD464C544C + +I=380 +KEY=E48BFDE0A09A260A93562F010BC9BD33 +IV=00E079EEBC47AF3ED3796DBF4A2B55FC +CT=7B94C0E4849AD65291F0F7BD464C544C +PT=D6518596BB53E44452393BD4440D805C + +I=381 +KEY=32DA78761BC9C24EC16F14D54FC43D6F +IV=03E168F8AF2303593E0F936648D253DC +CT=D6518596BB53E44452393BD4440D805C +PT=0C4B51FB33380BB215F29F3FCE7CA0DA + +I=382 +KEY=3E91298D28F1C9FCD49D8BEA81B89DB5 +IV=15E1ECD59BC092C974FA4738C66D9604 +CT=0C4B51FB33380BB215F29F3FCE7CA0DA +PT=3FC98D86A558B711807930AAA391C9BF + +I=383 +KEY=0158A40B8DA97EED54E4BB402229540A +IV=303BD4A407015A9E899816E0FABF288D +CT=3FC98D86A558B711807930AAA391C9BF +PT=85D77D90C312FE938F6C1983014BD572 + +I=384 +KEY=848FD99B4EBB807EDB88A2C323628178 +IV=E018FA96FD433CFD162E8E67D4F37015 +CT=85D77D90C312FE938F6C1983014BD572 +PT=4F49C1740EA88B5767CE36C95158DD63 + +I=385 +KEY=CBC618EF40130B29BC46940A723A5C1B +IV=84013D3E2AA0C77650644CD6862096A7 +CT=4F49C1740EA88B5767CE36C95158DD63 +PT=E6F1409ABA890AC3A50FC4AAD82E1872 + +I=386 +KEY=2D375875FA9A01EA194950A0AA144469 +IV=8BFD137593BFF254414349F1147B9BFF +CT=E6F1409ABA890AC3A50FC4AAD82E1872 +PT=66F6E29696CFDC72EE905636614D2A72 + +I=387 +KEY=4BC1BAE36C55DD98F7D90696CB596E1B +IV=8EC295602FB66C4A2DCA65F66B07E010 +CT=66F6E29696CFDC72EE905636614D2A72 +PT=553B45792AE0625B357C4B68A4BB767F + +I=388 +KEY=1EFAFF9A46B5BFC3C2A54DFE6FE21864 +IV=5999E221475D06295451E52FF88F9F97 +CT=553B45792AE0625B357C4B68A4BB767F +PT=FAB6F53166BFDB89DF68D46D423C243E + +I=389 +KEY=E44C0AAB200A644A1DCD99932DDE3C5A +IV=49D1944CBD7BE00C671B8E996F9A3EB9 +CT=FAB6F53166BFDB89DF68D46D423C243E +PT=308DDB3FE0415C46AE450C78FC5F2558 + +I=390 +KEY=D4C1D194C04B380CB38895EBD1811902 +IV=9785FEE180794318514967B4199CFB93 +CT=308DDB3FE0415C46AE450C78FC5F2558 +PT=6659969D1BD493A3851E75981BACCCB0 + +I=391 +KEY=B2984709DB9FABAF3696E073CA2DD5B2 +IV=4FD1DAE14DB75AC0E6C94388805AC3B5 +CT=6659969D1BD493A3851E75981BACCCB0 +PT=B56B950D84DCA131FD8A5E2601037B36 + +I=392 +KEY=07F3D2045F430A9ECB1CBE55CB2EAE84 +IV=3ED415E7DDDADD2DC7F0376E6CA42EFE +CT=B56B950D84DCA131FD8A5E2601037B36 +PT=8648F40FA13018563E6F1A799D9FCD91 + +I=393 +KEY=81BB260BFE7312C8F573A42C56B16315 +IV=FEAF76717C0905A601509BD68C6D08E5 +CT=8648F40FA13018563E6F1A799D9FCD91 +PT=66DE6D7A74B36C7EE2737DA526F5C8CD + +I=394 +KEY=E7654B718AC07EB61700D9897044ABD8 +IV=2B808C340320DD64AB9278A9D9A3E247 +CT=66DE6D7A74B36C7EE2737DA526F5C8CD +PT=9BB0D29CDA21452F60B5897186F3FAFB + +I=395 +KEY=7CD599ED50E13B9977B550F8F6B75123 +IV=D2EB48117E2E9FB2058800DE1A442799 +CT=9BB0D29CDA21452F60B5897186F3FAFB +PT=489CDC3A2C1AE7510E03AE36D5EAB0E5 + +I=396 +KEY=344945D77CFBDCC879B6FECE235DE1C6 +IV=427765E0671AA6D32634447687E9B209 +CT=489CDC3A2C1AE7510E03AE36D5EAB0E5 +PT=1D65D0E1235AE47DBCC2C65B59892C4C + +I=397 +KEY=292C95365FA138B5C57438957AD4CD8A +IV=D75E9F074D965FE902287B3BB1483315 +CT=1D65D0E1235AE47DBCC2C65B59892C4C +PT=E75B7AE5A8C3B93F15D0E3EBD04E1B4B + +I=398 +KEY=CE77EFD3F762818AD0A4DB7EAA9AD6C1 +IV=5455FD9A01E04E48CA777CF8185697ED +CT=E75B7AE5A8C3B93F15D0E3EBD04E1B4B +PT=11F4A35F6C225A9DF1CA6BAF92E11B07 + +I=399 +KEY=DF834C8C9B40DB17216EB0D1387BCDC6 +IV=3C608F664492626B2208DC92E819411A +CT=11F4A35F6C225A9DF1CA6BAF92E11B07 +PT=9B8FB71E035CEFF9CBFA1346E5ACEFE0 + +========== + +KEYSIZE=192 + +I=0 +KEY=000000000000000000000000000000000000000000000000 +IV=00000000000000000000000000000000 +CT=00000000000000000000000000000000 +PT=5DF678DD17BA4E75B61768C6ADEF7C7B + +I=1 +KEY=8AB601AF30C47B225DF678DD17BA4E75B61768C6ADEF7C7B +IV=3B243F1A9BA094EE8AB601AF30C47B22 +CT=5DF678DD17BA4E75B61768C6ADEF7C7B +PT=F9604074F8FA45AC71959888DD056F9F + +I=2 +KEY=D443B8E25A882D05A49638A9EF400BD9C782F04E70EA13E4 +IV=467E32A79443B0735EF5B94D6A4C5627 +CT=F9604074F8FA45AC71959888DD056F9F +PT=98A957EA6DBE623B7E08F919812A3898 + +I=3 +KEY=5742DCD38C8FD46D3C3F6F4382FE69E2B98A0957F1C02B7C +IV=B9E1062EEDD9A1ED83016431D607F968 +CT=98A957EA6DBE623B7E08F919812A3898 +PT=AD6D29D6482764BB4BC27A87AE5CD877 + +I=4 +KEY=B33625F7872DE4A191524695CAD90D59F24873D05F9CF30B +IV=BD1AAC94D2D39445E474F9240BA230CC +CT=AD6D29D6482764BB4BC27A87AE5CD877 +PT=DA5EB591FDC48F0D9E4EBD373E5717A3 + +I=5 +KEY=35DA9F0A5DB187964B0CF304371D82546C06CEE761CBE4A8 +IV=4782561ED717916986ECBAFDDA9C6337 +CT=DA5EB591FDC48F0D9E4EBD373E5717A3 +PT=3F6E771434E26D4FA5A57CEF9DEE05D6 + +I=6 +KEY=A8182E4F8FD8C7987462841003FFEF1BC9A3B208FC25E17E +IV=093273C6E96EA5399DC2B145D269400E +CT=3F6E771434E26D4FA5A57CEF9DEE05D6 +PT=F8FBFC8CBDD4AA8E8DA58DEA7F2F344C + +I=7 +KEY=71A581F408C35DA48C99789CBE2B459544063FE2830AD532 +IV=3900E8650CA62A25D9BDAFBB871B9A3C +CT=F8FBFC8CBDD4AA8E8DA58DEA7F2F344C +PT=B969AA871D3B35C260D8B36C7E9E8913 + +I=8 +KEY=BCD0E4B5F0B7FB5035F0D21BA310705724DE8C8EFD945C21 +IV=0E2BCF13C2A18FF5CD756541F874A6F4 +CT=B969AA871D3B35C260D8B36C7E9E8913 +PT=6205EECCDD965D45339A2DFE85F52AD7 + +I=9 +KEY=A2796321044D9F5557F53CD77E862D121744A170786176F6 +IV=8B935AB4C17D24D21EA98794F4FA6405 +CT=6205EECCDD965D45339A2DFE85F52AD7 +PT=6BC27204DA1B9BC27E463D0E71557D99 + +I=10 +KEY=AD4506295D5309603C374ED3A49DB6D069029C7E09340B6F +IV=A9AF68AB4EFDB7770F3C6508591E9635 +CT=6BC27204DA1B9BC27E463D0E71557D99 +PT=DB1576A8F1BD88F73E6938E72F9C6DCD + +I=11 +KEY=61ECB6C8660E5E20E722387B55203E27576BA49926A866A2 +IV=DF83746D72419F65CCA9B0E13B5D5740 +CT=DB1576A8F1BD88F73E6938E72F9C6DCD +PT=150D14977B15FD304890D7B9C4F8536E + +I=12 +KEY=03679C91B6C57828F22F2CEC2E35C3171FFB7320E25035CC +IV=59D101131EA2FD7F628B2A59D0CB2608 +CT=150D14977B15FD304890D7B9C4F8536E +PT=7AE22B73B412A81D0BCF422C68DA37F8 + +I=13 +KEY=9A087B9DBC37B12988CD079F9A276B0A1434310C8A8A0234 +IV=F26F03A3C84A49F0996FE70C0AF2C901 +CT=7AE22B73B412A81D0BCF422C68DA37F8 +PT=2D1584CE9B85E7264228A8AFF8FAFF01 + +I=14 +KEY=07489932E5335B38A5D8835101A28C2C561C99A37270FD35 +IV=E76AB1C798119F5D9D40E2AF5904EA11 +CT=2D1584CE9B85E7264228A8AFF8FAFF01 +PT=C1067030225453E808F1FF324C44BE7F + +I=15 +KEY=DC3726E33013BC9964DEF36123F6DFC45EED66913E34434A +IV=55010D6199E792E3DB7FBFD1D520E7A1 +CT=C1067030225453E808F1FF324C44BE7F +PT=3AD7DBD96BB69D63BE39B9A16574AC74 + +I=16 +KEY=EDD4EC10B074A36C5E0928B8484042A7E0D4DF305B40EF3E +IV=18C6FE6D0A2FDD7E31E3CAF380671FF5 +CT=3AD7DBD96BB69D63BE39B9A16574AC74 +PT=3D5D82A4C06B9DDCCC8A6B8BF228482F + +I=17 +KEY=23824573BD3CE30D6354AA1C882BDF7B2C5EB4BBA968A711 +IV=E1DEAECBCFC06BCCCE56A9630D484061 +CT=3D5D82A4C06B9DDCCC8A6B8BF228482F +PT=C0E5F9618F2FAB97EA82F8164DC89860 + +I=18 +KEY=AAA43BC528933502A3B1537D070474ECC6DC4CADE4A03F71 +IV=2CE22FDF7E87B7CC89267EB695AFD60F +CT=C0E5F9618F2FAB97EA82F8164DC89860 +PT=6942155FC9EF8F7CFE37CD6FED03CECF + +I=19 +KEY=A2686C442D636D31CAF34622CEEBFB9038EB81C209A3F1BE +IV=B7772CF7B44B856308CC578105F05833 +CT=6942155FC9EF8F7CFE37CD6FED03CECF +PT=6BA4C261F5173862A6789FB026099571 + +I=20 +KEY=29F645A446D84EACA15784433BFCC3F29E931E722FAA64CF +IV=15CA23A60D99FFF68B9E29E06BBB239D +CT=6BA4C261F5173862A6789FB026099571 +PT=AA9E8C6497CAC6B0C8CC92F8DFE7B455 + +I=21 +KEY=5E9165527010387F0BC90827AC360542565F8C8AF04DD09A +IV=53193227307BBE49776720F636C876D3 +CT=AA9E8C6497CAC6B0C8CC92F8DFE7B455 +PT=7DA426C712E7F2F35087D6AA31CF56AB + +I=22 +KEY=92DC0EEE09F5169E766D2EE0BED1F7B106D85A20C1828631 +IV=85A3D20949963F95CC4D6BBC79E52EE1 +CT=7DA426C712E7F2F35087D6AA31CF56AB +PT=09B9FF5E5833B6CE0010C3D0C4A84C19 + +I=23 +KEY=C45B938E7C18B4107FD4D1BEE6E2417F06C899F0052ACA28 +IV=292A007187D730B956879D6075EDA28E +CT=09B9FF5E5833B6CE0010C3D0C4A84C19 +PT=178F7AC0FF63C33683A001F5C4171316 + +I=24 +KEY=03D99546E931B761685BAB7E1981824985689805C13DD93E +IV=A8D8CD3B96215FCDC78206C895290371 +CT=178F7AC0FF63C33683A001F5C4171316 +PT=C39B82763CF6901170902BE6DC1B9305 + +I=25 +KEY=B52384CAC0B230F5ABC0290825771258F5F8B3E31D264A3B +IV=451968C3AA8D0319B6FA118C29838794 +CT=C39B82763CF6901170902BE6DC1B9305 +PT=85D827F61EC17FD00B10356292C863E2 + +I=26 +KEY=DCF617A990AC4CBB2E180EFE3BB66D88FEE886818FEE29D9 +IV=575103DAEFD233E269D59363501E7C4E +CT=85D827F61EC17FD00B10356292C863E2 +PT=535BAC956D5CAB917E1A1BC28E82F28F + +I=27 +KEY=14D0FCAFFD961CFD7D43A26B56EAC61980F29D43016CDB56 +IV=7DE780ACCF9F1896C826EB066D3A5046 +CT=535BAC956D5CAB917E1A1BC28E82F28F +PT=7E73E89F187EA6D5F5A3044A19C85941 + +I=28 +KEY=AF5BFBC086F1392203304AF44E9460CC7551990918A48217 +IV=633F0251217DECEDBB8B076F7B6725DF +CT=7E73E89F187EA6D5F5A3044A19C85941 +PT=B0976DFD4F0620203AC4ED89D395BAFF + +I=29 +KEY=79FFB93DCF243047B3A72709019240EC4F957480CB3138E8 +IV=C1AAE3E35613DAADD6A442FD49D50965 +CT=B0976DFD4F0620203AC4ED89D395BAFF +PT=5ECB838EC7F9F2E7ADBD719599F829B9 + +I=30 +KEY=681F54ADA7685555ED6CA487C66BB20BE228051552C91151 +IV=4F00D9CD31BE1CC611E0ED90684C6512 +CT=5ECB838EC7F9F2E7ADBD719599F829B9 +PT=8DDA96BD88D3D756306D249ABF99F5F9 + +I=31 +KEY=8663BEBF11817A3060B6323A4EB8655DD245218FED50E4A8 +IV=7CC24DC4B003DE90EE7CEA12B6E92F65 +CT=8DDA96BD88D3D756306D249ABF99F5F9 +PT=479E96E558540B71508FEF3173A6FC68 + +I=32 +KEY=831519BE48B0021A2728A4DF16EC6E2C82CACEBE9EF618C0 +IV=59FFA792DC8618070576A7015931782A +CT=479E96E558540B71508FEF3173A6FC68 +PT=080EA053745BEEBDBC5F7D964EEBD2F7 + +I=33 +KEY=AFC20AF72699543A2F26048C62B780913E95B328D01DCA37 +IV=4E5BDD875324CAC02CD713496E295620 +CT=080EA053745BEEBDBC5F7D964EEBD2F7 +PT=B5A58D345C0260A9E274E2E593B76C44 + +I=34 +KEY=46AEAF002B9A297E9A8389B83EB5E038DCE151CD43AAA673 +IV=C67419FDA89E68B1E96CA5F70D037D44 +CT=B5A58D345C0260A9E274E2E593B76C44 +PT=5200F2D475CA388841CB0DD02C7EB7F6 + +I=35 +KEY=1598E4DD7DA3D7B0C8837B6C4B7FD8B09D2A5C1D6FD41185 +IV=9F5C74A1FE2DFF2153364BDD5639FECE +CT=5200F2D475CA388841CB0DD02C7EB7F6 +PT=B2639C2D26BF2CAF2371CA3A4F3D3476 + +I=36 +KEY=FE63AA4A158B41AE7AE0E7416DC0F41FBE5B962720E925F3 +IV=2DC59704D531C890EBFB4E976828961E +CT=B2639C2D26BF2CAF2371CA3A4F3D3476 +PT=C758ADC41E334CCBF34C40E2AEAA3852 + +I=37 +KEY=86B214FA7F89CE06BDB84A8573F3B8D44D17D6C58E431DA1 +IV=D0982ADEECE45CCC78D1BEB06A028FA8 +CT=C758ADC41E334CCBF34C40E2AEAA3852 +PT=F8E0AA1E780F18A50371CBCB1B63E83F + +I=38 +KEY=C0C34A59DC653DCE4558E09B0BFCA0714E661D0E9520F59E +IV=A252B0F29766A24B46715EA3A3ECF3C8 +CT=F8E0AA1E780F18A50371CBCB1B63E83F +PT=554B524391A7A1679210CFC0152A65CE + +I=39 +KEY=3CF3D7DDFFF704231013B2D89A5B0116DC76D2CE800A9050 +IV=42EE716B821C18FCFC309D84239239ED +CT=554B524391A7A1679210CFC0152A65CE +PT=3273E6C51751407B7E4ECDED7970746D + +I=40 +KEY=7FCC684C43B958F02260541D8D0A416DA2381F23F97AE43D +IV=A4FCB2B8AB7158B9433FBF91BC4E5CD3 +CT=3273E6C51751407B7E4ECDED7970746D +PT=D90B75848AC14ACA3CAD9AF2A15F315F + +I=41 +KEY=240724B451241314FB6B219907CB0BA79E9585D15825D562 +IV=5C4FA1918B04D5F85BCB4CF8129D4BE4 +CT=D90B75848AC14ACA3CAD9AF2A15F315F +PT=753C59B87C45B21D527527C6C2DDEB0D + +I=42 +KEY=F0BEECC2DB5D16F98E5778217B8EB9BACCE0A2179AF83E6F +IV=4E41A4AB69AEE73FD4B9C8768A7905ED +CT=753C59B87C45B21D527527C6C2DDEB0D +PT=156E851810ADB0BF2D28B6150D32CAC7 + +I=43 +KEY=C2FB954C95633B5B9B39FD396B230905E1C8140297CAF4A8 +IV=983906FA7F156CF33245798E4E3E2DA2 +CT=156E851810ADB0BF2D28B6150D32CAC7 +PT=26E671DACE32070A601796207BD045B5 + +I=44 +KEY=BF0BD4C6DDBE22DABDDF8CE3A5110E0F81DF8222EC1AB11D +IV=B3188D29356783AF7DF0418A48DD1981 +CT=26E671DACE32070A601796207BD045B5 +PT=ADAD9072859250A8590F6F54C24E5A77 + +I=45 +KEY=2E4F07AD61768CC010721C9120835EA7D8D0ED762E54EB6A +IV=639F27016A9D99B99144D36BBCC8AE1A +CT=ADAD9072859250A8590F6F54C24E5A77 +PT=AC8AD3933D51D5D71CA90FB73A53F6AD + +I=46 +KEY=9963998A6F982462BCF8CF021DD28B70C479E2C114071DC7 +IV=B2A3ACB0CE942F13B72C9E270EEEA8A2 +CT=AC8AD3933D51D5D71CA90FB73A53F6AD +PT=7319F2825648168F07D525618DA9979A + +I=47 +KEY=417FD42690AAE310CFE13D804B9A9DFFC3ACC7A099AE8A5D +IV=EBB0EF7CE1ACF152D81C4DACFF32C772 +CT=7319F2825648168F07D525618DA9979A +PT=4FC19392439D6CBE6699419355E0590B + +I=48 +KEY=30CD3A2A0910C7268020AE120807F141A5358633CC4ED356 +IV=4DCACE79E4C3ADFE71B2EE0C99BA2436 +CT=4FC19392439D6CBE6699419355E0590B +PT=047FF92A523900A3C46D906163927DDD + +I=49 +KEY=F13EE3ACC9C19E4C845F57385A3EF1E261581652AFDCAE8B +IV=E260680204844E6FC1F3D986C0D1596A +CT=047FF92A523900A3C46D906163927DDD +PT=2DAE78D178D069918CCC11D675E09655 + +I=50 +KEY=91556C720DC982D5A9F12FE922EE9873ED940784DA3C38DE +IV=A4E4973E74B61315606B8FDEC4081C99 +CT=2DAE78D178D069918CCC11D675E09655 +PT=6315A6A029ED7FC5AB3CD38D8DAE561A + +I=51 +KEY=9120A23E63AF3BC2CAE489490B03E7B646A8D40957926EC4 +IV=C02DA24531C794BD0075CE4C6E66B917 +CT=6315A6A029ED7FC5AB3CD38D8DAE561A +PT=65A796C69B769E59D34AD19803F117C6 + +I=52 +KEY=5C6847E25C66145DAF431F8F907579EF95E2059154637902 +IV=0D72A6B0F3959C89CD48E5DC3FC92F9F +CT=65A796C69B769E59D34AD19803F117C6 +PT=70770D19D03DF488FB627F460A225F39 + +I=53 +KEY=F5ECA4C905FF0EC2DF34129640488D676E807AD75E41263B +IV=2F60424B5062D978A984E32B59991A9F +CT=70770D19D03DF488FB627F460A225F39 +PT=C8A66A2CD18286D2148230BAB7D81E11 + +I=54 +KEY=FF86E251C5EC6129179278BA91CA0BB57A024A6DE999382A +IV=CC7330AE077936B10A6A4698C0136FEB +CT=C8A66A2CD18286D2148230BAB7D81E11 +PT=FC0B47BA3E51927A632F457A919818DC + +I=55 +KEY=5C0A7344D6FD6983EB993F00AF9B99CF192D0F17780120F6 +IV=CA119AEE5576E06EA38C9115131108AA +CT=FC0B47BA3E51927A632F457A919818DC +PT=AEEDB360C58C4CDC7ACE87AA1A4B785B + +I=56 +KEY=426948BD499E8A9845748C606A17D51363E388BD624A58AD +IV=920C491DE39D52501E633BF99F63E31B +CT=AEEDB360C58C4CDC7ACE87AA1A4B785B +PT=737ECC4294FF69495DC37DC795EC13CE + +I=57 +KEY=F8AD0E545AA212E6360A4022FEE8BC5A3E20F57AF7A64B63 +IV=B975B70450A41A2DBAC446E9133C987E +CT=737ECC4294FF69495DC37DC795EC13CE +PT=3E7CDC26CCC69E02D08248224A22961E + +I=58 +KEY=C2834233A26DCD8A08769C04322E2258EEA2BD58BD84DD7D +IV=A88326DC57AB80FC3A2E4C67F8CFDF6C +CT=3E7CDC26CCC69E02D08248224A22961E +PT=88177B6502254344A364023BCAD29E79 + +I=59 +KEY=962D892D6CDED6798061E761300B611C4DC6BF6377564304 +IV=D95CFF470B1796D754AECB1ECEB31BF3 +CT=88177B6502254344A364023BCAD29E79 +PT=A10FA825EB6DA0E242D9A381F607472D + +I=60 +KEY=3ADA98C76065214A216E4F44DB66C1FE0F1F1CE281510429 +IV=FBD25798351AF35DACF711EA0CBBF733 +CT=A10FA825EB6DA0E242D9A381F607472D +PT=6B5EE3A222DF46560A12E91C006D303F + +I=61 +KEY=C6AB975CF71B6DDF4A30ACE6F9B987A8050DF5FE813C3416 +IV=6CDB3875008754DAFC710F9B977E4C95 +CT=6B5EE3A222DF46560A12E91C006D303F +PT=A0047B92A93ACF32138A818B6E32B3EE + +I=62 +KEY=FFD0E16A5C955EBAEA34D7745083489A16877475EF0E87F8 +IV=F7061CA37B11E445397B7636AB8E3365 +CT=A0047B92A93ACF32138A818B6E32B3EE +PT=1707FC063700E98FF5FDA98A07A8A1C7 + +I=63 +KEY=AA71EC7061FA246CFD332B726783A115E37ADDFFE8A6263F +IV=1853E27FC0689E6755A10D1A3D6F7AD6 +CT=1707FC063700E98FF5FDA98A07A8A1C7 +PT=06320FA4C0E2F42B364B991243FA053D + +I=64 +KEY=D8685685696CBF5CFB0124D6A761553ED53144EDAB5C2302 +IV=E19A3BEC7EBCA3C87219BAF508969B30 +CT=06320FA4C0E2F42B364B991243FA053D +PT=BB70503E9715D653710C0630211755A7 + +I=65 +KEY=28C2AFFA406EF763407174E83074836DA43D42DD8A4B76A5 +IV=5F3BCA36562AFA82F0AAF97F2902483F +CT=BB70503E9715D653710C0630211755A7 +PT=D632FEF42560770DF318C570AFC85285 + +I=66 +KEY=260B8E0723E9AF3D96438A1C1514F460572587AD25832420 +IV=328A42D3898A81C20EC921FD6387585E +CT=D632FEF42560770DF318C570AFC85285 +PT=B1C847FFF455D002E55FCFAF4A4F69A4 + +I=67 +KEY=F39D3CD6A68DC6BC278BCDE3E1412462B27A48026FCC4D84 +IV=C89E7B4C1BAED0FAD596B2D185646981 +CT=B1C847FFF455D002E55FCFAF4A4F69A4 +PT=9C484252E1FE52CD2DFCCAA3E0118F07 + +I=68 +KEY=61A9714C87B94F27BBC38FB100BF76AF9F8682A18FDDC283 +IV=56B7D716EC6F9A6D92344D9A2134899B +CT=9C484252E1FE52CD2DFCCAA3E0118F07 +PT=85A142323B9877E86F3A5874EA613E87 + +I=69 +KEY=B504BE17C673E81F3E62CD833B270147F0BCDAD565BCFC04 +IV=BEF2C82884510475D4ADCF5B41CAA738 +CT=85A142323B9877E86F3A5874EA613E87 +PT=53D0EF74268F55C1B6CA84415E5A2F6F + +I=70 +KEY=1A63CC27BE45C5106DB222F71DA8548646765E943BE6D36B +IV=CC958CC3874510F0AF67723078362D0F +CT=53D0EF74268F55C1B6CA84415E5A2F6F +PT=7B7DB0F3EFAD244FFCC6991452001DF6 + +I=71 +KEY=4B17520C49F46EAF16CF9204F20570C9BAB0C78069E6CE9D +IV=48D7C0690532AFCC51749E2BF7B1ABBF +CT=7B7DB0F3EFAD244FFCC6991452001DF6 +PT=DD0661DCA2BE8C20E95B3A84CCACDB10 + +I=72 +KEY=1ADE412393310021CBC9F3D850BBFCE953EBFD04A54A158D +IV=4B96B2D0CCADFF7D51C9132FDAC56E8E +CT=DD0661DCA2BE8C20E95B3A84CCACDB10 +PT=E505435777F3781121A4A374684E3268 + +I=73 +KEY=493467065AE405B82ECCB08F274884F8724F5E70CD0427E5 +IV=1E8116EB95B94AFC53EA2625C9D50599 +CT=E505435777F3781121A4A374684E3268 +PT=EF4B4E997DA0DCCBDBB36C020D03E8B5 + +I=74 +KEY=4C94816DF6EBDEF5C187FE165AE85833A9FC3272C007CF50 +IV=29094410F6017E5805A0E66BAC0FDB4D +CT=EF4B4E997DA0DCCBDBB36C020D03E8B5 +PT=FA9BAB377C654ED894024BEBDCED2FA0 + +I=75 +KEY=697A0BC179C07A633B1C5521268D16EB3DFE79991CEAE0F0 +IV=83DD12597A405FB725EE8AAC8F2BA496 +CT=FA9BAB377C654ED894024BEBDCED2FA0 +PT=DD1FDA63382552D007F6F8E995820640 + +I=76 +KEY=D40786ED2A6C15E8E6038F421EA8443B3A0881708968E6B0 +IV=2F3AE5594D9CCEDCBD7D8D2C53AC6F8B +CT=DD1FDA63382552D007F6F8E995820640 +PT=C5FF0EB50BA651F436D0566385860ADA + +I=77 +KEY=9D47680C0159F69A23FC81F7150E15CF0CD8D7130CEEEC6A +IV=1BCFAD6802C41B9A4940EEE12B35E372 +CT=C5FF0EB50BA651F436D0566385860ADA +PT=67AE61A77D77CBFD48C080B21313BBAB + +I=78 +KEY=86E61E031542D2DB4452E0506879DE32441857A11FFD57C1 +IV=3DF4DA1F65C739511BA1760F141B2441 +CT=67AE61A77D77CBFD48C080B21313BBAB +PT=68C8512217CB9C3BBF28011FA5BED044 + +I=79 +KEY=4F93757DE614CB1D2C9AB1727FB24209FB3056BEBA438785 +IV=B2C15424EF4E4637C9756B7EF35619C6 +CT=68C8512217CB9C3BBF28011FA5BED044 +PT=233898C850826172965695499748A1B0 + +I=80 +KEY=C56E54BBB54B22CC0FA229BA2F30237B6D66C3F72D0B2635 +IV=DC2FF5992D9383EF8AFD21C6535FE9D1 +CT=233898C850826172965695499748A1B0 +PT=70069F5E963A820D640B40697BD24716 + +I=81 +KEY=A1EF05CB5AAE7A977FA4B6E4B90AA176096D839E56D96123 +IV=EE8CB982124A394C64815170EFE5585B +CT=70069F5E963A820D640B40697BD24716 +PT=B136CA2EF42A9CFF53410554B28A8F65 + +I=82 +KEY=ACEC084A8CED2F4FCE927CCA4D203D895A2C86CAE453EE46 +IV=515D8B6C167EC8570D030D81D64355D8 +CT=B136CA2EF42A9CFF53410554B28A8F65 +PT=123600CD1B5A664430413021DDC8CBBE + +I=83 +KEY=8325A9391B4E106ADCA47C07567A5BCD6A6DB6EB399B25F8 +IV=5A55A24EC8154E532FC9A17397A33F25 +CT=123600CD1B5A664430413021DDC8CBBE +PT=8ECCA03E10D415557C4E7D92DDBFD791 + +I=84 +KEY=DB877966BE0E84575268DC3946AE4E981623CB79E424F269 +IV=659705F3774E141758A2D05FA540943D +CT=8ECCA03E10D415557C4E7D92DDBFD791 +PT=CB70B675AC6BF92237F1C479516E7E6A + +I=85 +KEY=59027658DEC2B5DE99186A4CEAC5B7BA21D20F00B54A8C03 +IV=C9B803CE2D57D26F82850F3E60CC3189 +CT=CB70B675AC6BF92237F1C479516E7E6A +PT=5D99D06E9BEB82AB1CE22201E8467DBC + +I=86 +KEY=652E430F984201E0C481BA22712E35113D302D015D0CF1BF +IV=1838FACBEAC13CF73C2C35574680B43E +CT=5D99D06E9BEB82AB1CE22201E8467DBC +PT=11D7AED0B552D62677DEB874BF7CF8ED + +I=87 +KEY=8377A2C11B73082DD55614F2C47CE3374AEE9575E2700952 +IV=068170C7E11427DFE659E1CE833109CD +CT=11D7AED0B552D62677DEB874BF7CF8ED +PT=74B108D32ABE8401D22F2C3FB008F670 + +I=88 +KEY=7B89A5C45B0A22BBA1E71C21EEC2673698C1B94A5278FF22 +IV=5283DAD6FA2B605DF8FE070540792A96 +CT=74B108D32ABE8401D22F2C3FB008F670 +PT=7883BD8C4DA81C21C4A5847AD801B7AE + +I=89 +KEY=101261A4D23FDA13D964A1ADA36A7B175C643D308A79488C +IV=E2ED92DE4829CB526B9BC4608935F8A8 +CT=7883BD8C4DA81C21C4A5847AD801B7AE +PT=C865B27C21F6F6E681759C318607D2B9 + +I=90 +KEY=E6A6A13B7A64EB51110113D1829C8DF1DD11A1010C7E9A35 +IV=AB325AD4F1FF1C52F6B4C09FA85B3142 +CT=C865B27C21F6F6E681759C318607D2B9 +PT=E31D7AC0E8ADB302BC6C23A0B1D693ED + +I=91 +KEY=64D366C4F61E139BF21C69116A313EF3617D82A1BDA809D8 +IV=A5201D1770A12A898275C7FF8C7AF8CA +CT=E31D7AC0E8ADB302BC6C23A0B1D693ED +PT=CAE6A97EE64228EEEF02E135944C5C62 + +I=92 +KEY=B006CEF05093DE2238FAC06F8C73161D8E7F639429E455BA +IV=62BD7E3EA22E26BAD4D5A834A68DCDB9 +CT=CAE6A97EE64228EEEF02E135944C5C62 +PT=B7AEF117099F799BB0752C7260A2DFB5 + +I=93 +KEY=160AFF18C06B6C4A8F54317885EC6F863E0A4FE649468A0F +IV=AEBB967838133F64A60C31E890F8B268 +CT=B7AEF117099F799BB0752C7260A2DFB5 +PT=81CCC6EDAD41D9C7986D4E175C71551D + +I=94 +KEY=21112CBE896259CE0E98F79528ADB641A66701F11537DF12 +IV=B695BBE7FA331039371BD3A649093584 +CT=81CCC6EDAD41D9C7986D4E175C71551D +PT=9039E01C6485040A2EDAF4C27FE93870 + +I=95 +KEY=60272333C1B4CCC39EA117894C28B24B88BDF5336ADEE762 +IV=4EE830907337D60241360F8D48D6950D +CT=9039E01C6485040A2EDAF4C27FE93870 +PT=44D359DBE4BE436D5133CD81B72DB5C7 + +I=96 +KEY=25C676A781511A98DA724E52A896F126D98E38B2DDF352A5 +IV=38491C9FD517260445E1559440E5D65B +CT=44D359DBE4BE436D5133CD81B72DB5C7 +PT=7B47F95ED30563BE218E40DB4EAAE836 + +I=97 +KEY=59A7B7512B5DC429A135B70C7B939298F80078699359BA93 +IV=1FD8B8BA8B0492E67C61C1F6AA0CDEB1 +CT=7B47F95ED30563BE218E40DB4EAAE836 +PT=C417F6A6824B165D4C26D631F77E45AC + +I=98 +KEY=82E6CF234BC0AA10652241AAF9D884C5B426AE586427FF3F +IV=5FB017B65FE4AF34DB417872609D6E39 +CT=C417F6A6824B165D4C26D631F77E45AC +PT=41EC9A06B318A4D06636ED5403F46CB7 + +I=99 +KEY=82D69A1D747CF6E024CEDBAC4AC02015D210430C67D39388 +IV=1CC1F56321366F420030553E3FBC5CF0 +CT=41EC9A06B318A4D06636ED5403F46CB7 +PT=38E467F81D919F0A1704E9F5CDF4D5FC + +I=100 +KEY=29EFCA26B9C67E141C2ABC545751BF1FC514AAF9AA274674 +IV=A83BDBF4326AE806AB39503BCDBA88F4 +CT=38E467F81D919F0A1704E9F5CDF4D5FC +PT=A08359A20D6F405018F8180A3E8D0FD1 + +I=101 +KEY=AB20AC8C3C5DA5BEBCA9E5F65A3EFF4FDDECB2F394AA49A5 +IV=A14B10E1A998B04E82CF66AA859BDBAA +CT=A08359A20D6F405018F8180A3E8D0FD1 +PT=A16C303138057144A3ECA63E7398DC93 + +I=102 +KEY=86C5E861B9CEAF041DC5D5C7623B8E0B7E0014CDE7329536 +IV=181D943EA950561D2DE544ED85930ABA +CT=A16C303138057144A3ECA63E7398DC93 +PT=EA1A2E30D890D01979D2BCE1EBE6C922 + +I=103 +KEY=90321C401E4B6B30F7DFFBF7BAAB5E1207D2A82C0CD45C14 +IV=12BDB944D898BC5A16F7F421A785C434 +CT=EA1A2E30D890D01979D2BCE1EBE6C922 +PT=C0D620FCF33031DAD617ADBE8F6D13AC + +I=104 +KEY=84964C3B41FE8E4F3709DB0B499B6FC8D1C5059283B94FB8 +IV=0615AD27B29C55F814A4507B5FB5E57F +CT=C0D620FCF33031DAD617ADBE8F6D13AC +PT=EC4B9AEDBE44C4B74B693D08AA1D175A + +I=105 +KEY=6C6361F2C87BC168DB4241E6F7DFAB7F9AAC389A29A458E2 +IV=E79F33FFCD79681CE8F52DC989854F27 +CT=EC4B9AEDBE44C4B74B693D08AA1D175A +PT=F34D426225ADEC3BD2580BF21EF24B3E + +I=106 +KEY=FDA3FB79F1A16865280F0384D272474448F43368375613DC +IV=1DFE18B10032D35F91C09A8B39DAA90D +CT=F34D426225ADEC3BD2580BF21EF24B3E +PT=E14841B0D0CC1E698DE8053B9F1621E1 + +I=107 +KEY=562D3BF792909255C947423402BE592DC51C3653A840323D +IV=247A46C43AE54F1FAB8EC08E6331FA30 +CT=E14841B0D0CC1E698DE8053B9F1621E1 +PT=D21381B5032426EC3582BBD23739E04E + +I=108 +KEY=9D375E6E32C30A801B54C381019A7FC1F09E8D819F79D273 +IV=E05018C26DC38BBDCB1A6599A05398D5 +CT=D21381B5032426EC3582BBD23739E04E +PT=82034FF505FE67B94373770348A934E5 + +I=109 +KEY=7D1A900B515478DB99578C7404641878B3EDFA82D7D0E696 +IV=498AEA38AB55250CE02DCE656397725B +CT=82034FF505FE67B94373770348A934E5 +PT=018B5B1787138D222F6B39C1291ECD2C + +I=110 +KEY=E74B55A39F67C54298DCD7638377955A9C86C343FECE2BBA +IV=DD89DF396236F9A59A51C5A8CE33BD99 +CT=018B5B1787138D222F6B39C1291ECD2C +PT=CABCB7EA14E821726602272A46CEB825 + +I=111 +KEY=D3FFFE0F27D9200352606089979FB428FA84E469B800939F +IV=A707D154BAC28BDC34B4ABACB8BEE541 +CT=CABCB7EA14E821726602272A46CEB825 +PT=0840D09DF2B14ED4B340D32101D68A54 + +I=112 +KEY=485EC313821A37095A20B014652EFAFC49C43748B9D619CB +IV=ADEF6A8A49BF208B9BA13D1CA5C3170A +CT=0840D09DF2B14ED4B340D32101D68A54 +PT=5EB0166FB04AF38F9EA60929FD641844 + +I=113 +KEY=E841074638A154D90490A67BD5640973D7623E6144B2018F +IV=B1956D86A4F79E40A01FC455BABB63D0 +CT=5EB0166FB04AF38F9EA60929FD641844 +PT=2ECBDAFBD0336A436D89FC12944750EC + +I=114 +KEY=17E86798DB7A64E42A5B7C8005576330BAEBC273D0F55163 +IV=0AFFE19CA1425218FFA960DEE3DB303D +CT=2ECBDAFBD0336A436D89FC12944750EC +PT=A326D8C07EF7A21302A3C6A9C67C371A + +I=115 +KEY=D1A6F2AB7C130A60897DA4407BA0C123B84804DA16896679 +IV=6F630069CD0333BDC64E9533A7696E84 +CT=A326D8C07EF7A21302A3C6A9C67C371A +PT=6D06DDFB9B12A71298E32318F582EF72 + +I=116 +KEY=C7D58104581CB5C5E47B79BBE0B2663120AB27C2E30B890B +IV=80E47BA8410247C5167373AF240FBFA5 +CT=6D06DDFB9B12A71298E32318F582EF72 +PT=E1391A50F140E255A9B2E628F25B9B1D + +I=117 +KEY=00D8EEC433F7D68E054263EB11F284648919C1EA11501216 +IV=96F652822C5D4496C70D6FC06BEB634B +CT=E1391A50F140E255A9B2E628F25B9B1D +PT=1418A2DC8D6DBA4942932D6944011D8A + +I=118 +KEY=71D444358CCCF986115AC1379C9F3E2DCB8AEC8355510F9C +IV=410374DE0D8A79FA710CAAF1BF3B2F08 +CT=1418A2DC8D6DBA4942932D6944011D8A +PT=A70A2C48CF5786868844274B8C493C56 + +I=119 +KEY=B9FD9626EC74A129B650ED7F53C8B8AB43CECBC8D91833CA +IV=8362FAE290801C25C829D21360B858AF +CT=A70A2C48CF5786868844274B8C493C56 +PT=3484BA42558B199E8477B8F8280CDE91 + +I=120 +KEY=94CAEE912A7B443582D4573D0643A135C7B97330F114ED5B +IV=F6ABE3F0A7FFC9E02D3778B7C60FE51C +CT=3484BA42558B199E8477B8F8280CDE91 +PT=5D79433F85C7D4C258487080E340F049 + +I=121 +KEY=1D2F762CF08FAE0ADFAD1402838475F79FF103B012541D12 +IV=A0C57652FBF9107C89E598BDDAF4EA3F +CT=5D79433F85C7D4C258487080E340F049 +PT=C51891EA2E68BC60E84912A91F470201 + +I=122 +KEY=9E691D03A3AEB6491AB585E8ADECC99777B811190D131F13 +IV=8426C338234DB9E183466B2F53211843 +CT=C51891EA2E68BC60E84912A91F470201 +PT=F946FD67DD7F92A7A6B93B4F71F70243 + +I=123 +KEY=61EA6FD274C07ADDE3F3788F70935B30D1012A567CE41D50 +IV=2C2AF70B07E9E6F9FF8372D1D76ECC94 +CT=F946FD67DD7F92A7A6B93B4F71F70243 +PT=B4CB0EFF14F8CDC693CC8E7DCEE8E0B0 + +I=124 +KEY=84F27E5BF8B55DA657387670646B96F642CDA42BB20CFDE0 +IV=693782638B439464E51811898C75277B +CT=B4CB0EFF14F8CDC693CC8E7DCEE8E0B0 +PT=EF6DDB56AAE9CFFE128FB3776DD94D20 + +I=125 +KEY=5B1111EADAECDD73B855AD26CE8259085042175CDFD5B0C0 +IV=A14AAEF7A1BF063BDFE36FB1225980D5 +CT=EF6DDB56AAE9CFFE128FB3776DD94D20 +PT=4ACC6AF28293A647093AE788BA778835 + +I=126 +KEY=A924DC707FB16DF1F299C7D44C11FF4F5978F0D465A238F5 +IV=3F7E73BFA24B0C02F235CD9AA55DB082 +CT=4ACC6AF28293A647093AE788BA778835 +PT=5A7989DC61AD6B66B3E83A29168BEDB9 + +I=127 +KEY=164FBEF9EBAEEF03A8E04E082DBC9429EA90CAFD7329D54C +IV=2FB4F1A000B78156BF6B6289941F82F2 +CT=5A7989DC61AD6B66B3E83A29168BEDB9 +PT=246A94AB8488B39C52DE68E8CA5AE0D2 + +I=128 +KEY=B1F4A368B64A78EC8C8ADAA3A93427B5B84EA215B973359E +IV=5D178EC8305B804FA7BB1D915DE497EF +CT=246A94AB8488B39C52DE68E8CA5AE0D2 +PT=F7C758F8DC8FC0891907EBBF299F70B8 + +I=129 +KEY=9161A39C256814AA7B4D825B75BBE73CA14949AA90EC4526 +IV=C87E61A9434EB29F209500F493226C46 +CT=F7C758F8DC8FC0891907EBBF299F70B8 +PT=E2D82C5506BEFA7D7BF032E4C72141CF + +I=130 +KEY=0BFDA1B2CF4B15199995AE0E73051D41DAB97B4E57CD04E9 +IV=5D00992780D9832B9A9C022EEA2301B3 +CT=E2D82C5506BEFA7D7BF032E4C72141CF +PT=F3A0DF1793FC88117E87478FD9E5A1A8 + +I=131 +KEY=F8F5F6016FECDCAF6A357119E0F99550A43E3CC18E28A541 +IV=2800EECA83EB078CF30857B3A0A7C9B6 +CT=F3A0DF1793FC88117E87478FD9E5A1A8 +PT=BEB572C53E9985218ED9012BAB4A9F5B + +I=132 +KEY=84F3E0D153E140D6D48003DCDE6010712AE73DEA25623A1A +IV=E2BEAF80F4A1DDA27C0616D03C0D9C79 +CT=BEB572C53E9985218ED9012BAB4A9F5B +PT=7F4B21C4B7466149CB890B77AC538752 + +I=133 +KEY=B69E5A72FE9B1B85ABCB221869267138E16E369D8931BD48 +IV=FE0A667B9B2BDD29326DBAA3AD7A5B53 +CT=7F4B21C4B7466149CB890B77AC538752 +PT=4B239C8F83F0A10DC6A3497CC3CF9C8E + +I=134 +KEY=0BCF87D2538E0EADE0E8BE97EAD6D03527CD7FE14AFE21C6 +IV=878250C5EA7834CFBD51DDA0AD151528 +CT=4B239C8F83F0A10DC6A3497CC3CF9C8E +PT=89F2B4B8C5AB2988CDEA61F4D4A1BCD4 + +I=135 +KEY=97A4FDCD2E0C993E691A0A2F2F7DF9BDEA271E159E5F9D12 +IV=95E34D44C3E2FE319C6B7A1F7D829793 +CT=89F2B4B8C5AB2988CDEA61F4D4A1BCD4 +PT=C622E28004842564F193C0E58AB40FCB + +I=136 +KEY=38F0A45980CEF0B9AF38E8AF2BF9DCD91BB4DEF014EB92D9 +IV=1BC195727D154539AF545994AEC26987 +CT=C622E28004842564F193C0E58AB40FCB +PT=DF360FBC1607BCC1E6EE9088AEE62EC7 + +I=137 +KEY=6638E0333D7A6765700EE7133DFE6018FD5A4E78BA0DBC1E +IV=F0AB65A69AA4486A5EC8446ABDB497DC +CT=DF360FBC1607BCC1E6EE9088AEE62EC7 +PT=9A8E5BFE223FA9D747164FC1C98B9CDC + +I=138 +KEY=5103611D32D7A1EFEA80BCED1FC1C9CFBA4C01B9738620C2 +IV=A6617B5DA41B2A32373B812E0FADC68A +CT=9A8E5BFE223FA9D747164FC1C98B9CDC +PT=F0143DD4EC3A85F9FA4D5579BD7268A1 + +I=139 +KEY=64FD310AF27CF98C1A948139F3FB4C36400154C0CEF44863 +IV=EBCB744B477F25E635FE5017C0AB5863 +CT=F0143DD4EC3A85F9FA4D5579BD7268A1 +PT=C5C1FED629BF81EE343E4DAEE6BC4D44 + +I=140 +KEY=9390B012FA7D48D9DF557FEFDA44CDD8743F196E28480527 +IV=7AF352D33C08F3FEF76D81180801B155 +CT=C5C1FED629BF81EE343E4DAEE6BC4D44 +PT=26C4460F0B79E16263C38C240C276E5C + +I=141 +KEY=F578E5DF6818CB58F99139E0D13D2CBA17FC954A246F6B7B +IV=05DA148A4EB4D12966E855CD92658381 +CT=26C4460F0B79E16263C38C240C276E5C +PT=E0E249ADB3A39EE2BB48959426874123 + +I=142 +KEY=F23F67282BAFE10E1973704D629EB258ACB400DE02E82A58 +IV=7748B1652DE54EF9074782F743B72A56 +CT=E0E249ADB3A39EE2BB48959426874123 +PT=C2299AAE24C941DC44E5D492BC492FED + +I=143 +KEY=5CAC16BD99EC5067DB5AEAE34657F384E851D44CBEA105B5 +IV=4F599B9C20378305AE937195B243B169 +CT=C2299AAE24C941DC44E5D492BC492FED +PT=780DA1D6FD961DA4756375A15B8BA620 + +I=144 +KEY=9FF7C1766F7F6F9FA3574B35BBC1EE209D32A1EDE52AA395 +IV=044A8C7FFE220414C35BD7CBF6933FF8 +CT=780DA1D6FD961DA4756375A15B8BA620 +PT=E63FE8BE6566E9ECCCDBEC442BCCCBD5 + +I=145 +KEY=3EA408C4CD15E6F24568A38BDEA707CC51E94DA9CEE66840 +IV=05DE81CD5892F1FEA153C9B2A26A896D +CT=E63FE8BE6566E9ECCCDBEC442BCCCBD5 +PT=19F5E5DDDF0F6FABA9B16B732C6058B8 + +I=146 +KEY=29FF0DD567A810385C9D465601A86867F85826DAE28630F8 +IV=0A2A8BF3BE53E2B5175B0511AABDF6CA +CT=19F5E5DDDF0F6FABA9B16B732C6058B8 +PT=41FCD9F8972431F43669863F37B4A18C + +I=147 +KEY=842E4C2F46849E731D619FAE968C5993CE31A0E5D5329174 +IV=1EABD419CA4C0D0BADD141FA212C8E4B +CT=41FCD9F8972431F43669863F37B4A18C +PT=9857CFE1CFE1046F88DF3EB8ECC92E40 + +I=148 +KEY=8EE3344CCB9DE2038536504F596D5DFC46EE9E5D39FBBF34 +IV=FA266CF1AF82A2250ACD78638D197C70 +CT=9857CFE1CFE1046F88DF3EB8ECC92E40 +PT=DE4C55865FB82BDA1FC0D024791C1B22 + +I=149 +KEY=DEEEC86215A6098D5B7A05C906D57626592E4E7940E7A416 +IV=F9B4CFCA36A1B0AB500DFC2EDE3BEB8E +CT=DE4C55865FB82BDA1FC0D024791C1B22 +PT=077F866BF30097D12650855C71B7DB9C + +I=150 +KEY=50872D11A2E463D65C0583A2F5D5E1F77F7ECB2531507F8A +IV=53D4E4CE2C06FCC38E69E573B7426A5B +CT=077F866BF30097D12650855C71B7DB9C +PT=670BBCB81CDE03B883D9B784124F5851 + +I=151 +KEY=7DE3AF7C8550901C3B0E3F1AE90BE24FFCA77CA1231F27DB +IV=C26330B1219C4B4A2D64826D27B4F3CA +CT=670BBCB81CDE03B883D9B784124F5851 +PT=D6141C300F5E5119E1B5F4BBF415A6DD + +I=152 +KEY=BB126D64220A8DB9ED1A232AE655B3561D12881AD70A8106 +IV=74D773D0F053239CC6F1C218A75A1DA5 +CT=D6141C300F5E5119E1B5F4BBF415A6DD +PT=8F742130206F1047FE9CAAE4F2C31B19 + +I=153 +KEY=9845C3A02214A55D626E021AC63AA311E38E22FE25C99A1F +IV=7EC0B4E8BD4BD3EB2357AEC4001E28E4 +CT=8F742130206F1047FE9CAAE4F2C31B19 +PT=47D0D28AF3164CC77FBAB5C015CAC1C9 + +I=154 +KEY=BBC47FAB874E0ED425BED090352CEFD69C34973E30035BD6 +IV=833EC00D894BD8502381BC0BA55AAB89 +CT=47D0D28AF3164CC77FBAB5C015CAC1C9 +PT=3202B04CFC260747BF839FF754A01E26 + +I=155 +KEY=BCC028DA5F286DE017BC60DCC90AE89123B708C964A345F0 +IV=8BCC8079D2175F4407045771D8666334 +CT=3202B04CFC260747BF839FF754A01E26 +PT=75E9FBADAD8885FB2398427EE94C5899 + +I=156 +KEY=352B0CD3E3BA0EB462559B7164826D6A002F4AB78DEF1D69 +IV=0B159F18C1F33EA389EB2409BC926354 +CT=75E9FBADAD8885FB2398427EE94C5899 +PT=90DA906982058C84D2E75B5DAE0EA756 + +I=157 +KEY=6F32D4393B37EA77F28F0B18E687E1EED2C811EA23E1BA3F +IV=2F5C35DA76038E4F5A19D8EAD88DE4C3 +CT=90DA906982058C84D2E75B5DAE0EA756 +PT=705C22072FDFB807A49BAE0FD4D254AF + +I=158 +KEY=5740616769DDF57482D3291FC95859E97653BFE5F733EE90 +IV=B276B0CE56828D683872B55E52EA1F03 +CT=705C22072FDFB807A49BAE0FD4D254AF +PT=A966EE217CF2BDBC17A0BB55AE769FEB + +I=159 +KEY=C9E379BDBC05CC402BB5C73EB5AAE45561F304B05945717B +IV=E1F41EF2147CB5CE9EA318DAD5D83934 +CT=A966EE217CF2BDBC17A0BB55AE769FEB +PT=239D761F1F0437935464C4959546B6BB + +I=160 +KEY=7B2C4F503FCC91AE0828B121AAAED3C63597C025CC03C7C0 +IV=6F90097C7822030DB2CF36ED83C95DEE +CT=239D761F1F0437935464C4959546B6BB +PT=499477B6476BA58CAEF81290ABDD46C4 + +I=161 +KEY=42BC1C4F29D1801D41BCC697EDC5764A9B6FD2B567DE8104 +IV=1571EE53AE1ACAEF3990531F161D11B3 +CT=499477B6476BA58CAEF81290ABDD46C4 +PT=ACC1FB947EB4C7F115871859CD254D96 + +I=162 +KEY=9BE24C041BF4DEECED7D3D039371B1BB8EE8CAECAAFBCC92 +IV=E24F4DBEF2122A73D95E504B32255EF1 +CT=ACC1FB947EB4C7F115871859CD254D96 +PT=85DC9D7ADF342B0733CF9812CFD58F0A + +I=163 +KEY=83BEBEB5727649F268A1A0794C459ABCBD2752FE652E4398 +IV=AF0690E77B1F140B185CF2B16982971E +CT=85DC9D7ADF342B0733CF9812CFD58F0A +PT=7ED8B4DCBD1D13BEA5C819E99ECF75AA + +I=164 +KEY=7020802D561D88AD167914A5F158890218EF4B17FBE13632 +IV=F0AC93D8DDD31D5BF39E3E98246BC15F +CT=7ED8B4DCBD1D13BEA5C819E99ECF75AA +PT=C81F0464C2DE212229370C7A4ED2E890 + +I=165 +KEY=39F8EA2D638410ABDE6610C13386A82031D8476DB533DEA2 +IV=FD6338FAE6F6B00B49D86A0035999806 +CT=C81F0464C2DE212229370C7A4ED2E890 +PT=23A0FA99C632BCC62A035A09514C3EBA + +I=166 +KEY=52FA33F30EFD8D0FFDC6EA58F5B414E61BDB1D64E47FE018 +IV=04C6E0136D8E04C16B02D9DE6D799DA4 +CT=23A0FA99C632BCC62A035A09514C3EBA +PT=9F7F1081AE4B6AD51D395D764D2D5B68 + +I=167 +KEY=95C21BD9257B233A62B9FAD95BFF7E3306E24012A952BB70 +IV=72410E03AAE65889C738282A2B86AE35 +CT=9F7F1081AE4B6AD51D395D764D2D5B68 +PT=5F088092968BF4AF04BF862A6721DF2B + +I=168 +KEY=058F749326AE1DD53DB17A4BCD748A9C025DC638CE73645B +IV=D678325E266D12D7904D6F4A03D53EEF +CT=5F088092968BF4AF04BF862A6721DF2B +PT=15670F60D1D70E129418AC14A425DD70 + +I=169 +KEY=23D2D59C5EF4AF3D28D6752B1CA3848E96456A2C6A56B92B +IV=BB7B672A91E9A61A265DA10F785AB2E8 +CT=15670F60D1D70E129418AC14A425DD70 +PT=3273AC9D250F729AE790A941739C79BF + +I=170 +KEY=E11B1F94517914C81AA5D9B639ACF61471D5C36D19CAC094 +IV=AB84F623EFA11728C2C9CA080F8DBBF5 +CT=3273AC9D250F729AE790A941739C79BF +PT=9B135880CB56A8E6CF3A364CC6E02175 + +I=171 +KEY=66F867085DBE626581B68136F2FA5EF2BEEFF521DF2AE1E1 +IV=01ED899C8DC9C09E87E3789C0CC776AD +CT=9B135880CB56A8E6CF3A364CC6E02175 +PT=681D6FC5447CCFE1152156CFF6172B6A + +I=172 +KEY=98505FCD27DAB39EE9ABEEF3B6869113ABCEA3EE293DCA8B +IV=A58C8285C31035B1FEA838C57A64D1FB +CT=681D6FC5447CCFE1152156CFF6172B6A +PT=6E30DF3FBD67A5FD491E315EF3A268A0 + +I=173 +KEY=9F904A41C19B57A9879B31CC0BE134EEE2D092B0DA9FA22B +IV=6F46DCB3A84FD96907C0158CE641E437 +CT=6E30DF3FBD67A5FD491E315EF3A268A0 +PT=5B4980E24D8F9CABE017991326FBBE95 + +I=174 +KEY=A330D5A6779731D6DCD2B12E466EA84502C70BA3FC641CBE +IV=C5BDAB77E0CA95463CA09FE7B60C667F +CT=5B4980E24D8F9CABE017991326FBBE95 +PT=7324530BF94BD80D286C9BE2FE4113D3 + +I=175 +KEY=20F008DE76D7968AAFF6E225BF2570482AAB904102250F6D +IV=32F5EC4AEBB997C583C0DD780140A75C +CT=7324530BF94BD80D286C9BE2FE4113D3 +PT=B163425AB21DF6AFBD2C7000E777E902 + +I=176 +KEY=0F48153B232E71F41E95A07F0D3886E79787E041E552E66F +IV=3D1854E0C481B28E2FB81DE555F9E77E +CT=B163425AB21DF6AFBD2C7000E777E902 +PT=EB1A6C86C3811E3081325F35BA7F2DCA + +I=177 +KEY=96EE2134FD40CA34F58FCCF9CEB998D716B5BF745F2DCBA5 +IV=8629366A8B8E266499A6340FDE6EBBC0 +CT=EB1A6C86C3811E3081325F35BA7F2DCA +PT=E9675AF0035C3F8E9D5E58D0652BF5C7 + +I=178 +KEY=BF754C828BFE309B1CE89609CDE5A7598BEBE7A43A063E62 +IV=566D5FCEC3FF7D43299B6DB676BEFAAF +CT=E9675AF0035C3F8E9D5E58D0652BF5C7 +PT=24B4DA85EEFAA123948C6B5E0E07EB08 + +I=179 +KEY=F0223B4AF5C885B4385C4C8C231F067A1F678CFA3401D56A +IV=67B98EC651B057104F5777C87E36B52F +CT=24B4DA85EEFAA123948C6B5E0E07EB08 +PT=753CFEBBB9E623453B8BB2976B8D7BD4 + +I=180 +KEY=04665169E091DEF74D60B2379AF9253F24EC3E6D5F8CAEBE +IV=BC3806A9E56A1DACF4446A2315595B43 +CT=753CFEBBB9E623453B8BB2976B8D7BD4 +PT=6949284723B4F795D530B366FAE70876 + +I=181 +KEY=9CABB1CFD4E46F8324299A70B94DD2AAF1DC8D0BA56BA6C8 +IV=8C864563BB8D45A098CDE0A63475B174 +CT=6949284723B4F795D530B366FAE70876 +PT=D43FED9A25C62349787F0336BFFBBFEB + +I=182 +KEY=4407065E88AE79D9F01677EA9C8BF1E389A38E3D1A901923 +IV=539CC5888B34198FD8ACB7915C4A165A +CT=D43FED9A25C62349787F0336BFFBBFEB +PT=030733E175916579F582A778B261DA1C + +I=183 +KEY=84D1EE80E8FA54DEF311440BE91A949A7C212945A8F1C33F +IV=78306F4F56DEF759C0D6E8DE60542D07 +CT=030733E175916579F582A778B261DA1C +PT=F7B1ABE4B4AE3CB726F9A88B06D4552A + +I=184 +KEY=E885BEA6176A75D804A0EFEF5DB4A82D5AD881CEAE259615 +IV=3AC80B78F744208A6C545026FF902106 +CT=F7B1ABE4B4AE3CB726F9A88B06D4552A +PT=DA984A2C346A4B758E066EB509079168 + +I=185 +KEY=2E0317B2DB3F9893DE38A5C369DEE358D4DEEF7BA722077D +IV=FC74E03B1068A6FEC686A914CC55ED4B +CT=DA984A2C346A4B758E066EB509079168 +PT=21F473636EF27B91F29BB1CE67908763 + +I=186 +KEY=850E1B37E1F7DD89FFCCD6A0072C98C926455EB5C0B2801E +IV=7DFD76EE7EF97796AB0D0C853AC8451A +CT=21F473636EF27B91F29BB1CE67908763 +PT=9EEF6E211CC8EDBD3C4FBE3E14B13C70 + +I=187 +KEY=655D365D66CAA5C36123B8811BE475741A0AE08BD403BC6E +IV=33318C04CC0B3CBDE0532D6A873D784A +CT=9EEF6E211CC8EDBD3C4FBE3E14B13C70 +PT=8AB49333CA7B2E58E7B24536BB34DEE7 + +I=188 +KEY=BE3C315647F981DCEB972BB2D19F5B2CFDB8A5BD6F376289 +IV=79D06A0D66B5C2B1DB61070B2133241F +CT=8AB49333CA7B2E58E7B24536BB34DEE7 +PT=323D1E775FD729005DA7A2853A855ED4 + +I=189 +KEY=3126E544A65724C4D9AA35C58E48722CA01F073855B23C5D +IV=CC5C9D95685AF1228F1AD412E1AEA518 +CT=323D1E775FD729005DA7A2853A855ED4 +PT=E283016FEDADEBA2BEC7ADB5A8DEA8B9 + +I=190 +KEY=BCF052AFAFA4852D3B2934AA63E5998E1ED8AA8DFD6C94E4 +IV=2753144E0A26D9FE8DD6B7EB09F3A1E9 +CT=E283016FEDADEBA2BEC7ADB5A8DEA8B9 +PT=9A9BB977D53BBD47550DC60A49AFA0FA + +I=191 +KEY=ECB724A85CBC7B58A1B28DDDB6DE24C94BD56C87B4C3341E +IV=27F910046A94AA3B50477607F318FE75 +CT=9A9BB977D53BBD47550DC60A49AFA0FA +PT=AF4C7AC3B02C1B077E8F97B59AE52A21 + +I=192 +KEY=BCA9E9794F9004AB0EFEF71E06F23FCE355AFB322E261E3F +IV=8AF06705FE272571501ECDD1132C7FF3 +CT=AF4C7AC3B02C1B077E8F97B59AE52A21 +PT=A97DEE2A64DFA7C198B6A4F21E80F7DF + +I=193 +KEY=10DCC14B9A309E25A7831934622D980FADEC5FC030A6E9E0 +IV=B04E1C6FC657B8AEAC752832D5A09A8E +CT=A97DEE2A64DFA7C198B6A4F21E80F7DF +PT=34E8228A24C7A16F9ED3F4B9A94AA70D + +I=194 +KEY=9CB6EE6AAEFAFBED936B3BBE46EA3960333FAB7999EC4EED +IV=6A966EBB8F80A1608C6A2F2134CA65C8 +CT=34E8228A24C7A16F9ED3F4B9A94AA70D +PT=99E6CA896906CBAA9B8D01155D1DB162 + +I=195 +KEY=461916712E8BD6F10A8DF1372FECF2CAA8B2AA6CC4F1FF8F +IV=EAF849974783FAA7DAAFF81B80712D1C +CT=99E6CA896906CBAA9B8D01155D1DB162 +PT=6009B53EB4690C1F1F10639F1FD7640A + +I=196 +KEY=5B9B91A966F9CE146A8444099B85FED5B7A2C9F3DB269B85 +IV=3FB045D182F781EB1D8287D8487218E5 +CT=6009B53EB4690C1F1F10639F1FD7640A +PT=88ED4BC34A27F4C4B480B99857EBF541 + +I=197 +KEY=404F7D8B0E966F02E2690FCAD1A20A110322706B8CCD6EC4 +IV=49C0F4571BAEBE4C1BD4EC22686FA116 +CT=88ED4BC34A27F4C4B480B99857EBF541 +PT=B88F0E3E01FEDF97766AC6B762D2EBC3 + +I=198 +KEY=CB2EA99F330A3A865AE601F4D05CD5867548B6DCEE1F8507 +IV=2518DA0D88C02EC38B61D4143D9C5584 +CT=B88F0E3E01FEDF97766AC6B762D2EBC3 +PT=C1C167FF37E89937DCB8D79C9BC9EC74 + +I=199 +KEY=913C795CF72CD1219B27660BE7B44CB1A9F0614075D66973 +IV=37769A59390261FB5A12D0C3C426EBA7 +CT=C1C167FF37E89937DCB8D79C9BC9EC74 +PT=64D912270A1E60192CDAAD8168219E56 + +I=200 +KEY=05F19DF919E44144FFFE742CEDAA2CA8852ACCC11DF7F725 +IV=63E9D4D1BDD7FEAD94CDE4A5EEC89065 +CT=64D912270A1E60192CDAAD8168219E56 +PT=C9AD2DBB1C686A67A3E21A5659576A2B + +I=201 +KEY=099D0DCE5E4E194236535997F1C246CF26C8D69744A09D0E +IV=A01E3F917EF4652F0C6C903747AA5806 +CT=C9AD2DBB1C686A67A3E21A5659576A2B +PT=244C740B4B136C6C480D0147163868D1 + +I=202 +KEY=EA1F242E9C75C712121F2D9CBAD12AA36EC5D7D05298F5DF +IV=C9D2288C473BCB3EE38229E0C23BDE50 +CT=244C740B4B136C6C480D0147163868D1 +PT=A6B125A9C570CC3ECBB5D302ADB96E34 + +I=203 +KEY=CD5D7C91FBDC81A1B4AE08357FA1E69DA57004D2FF219BEB +IV=871F525F8ED73B7F274258BF67A946B3 +CT=A6B125A9C570CC3ECBB5D302ADB96E34 +PT=0F9862A4A21E1FB365135C07577FB3EE + +I=204 +KEY=F7D9B8C22BDC8005BB366A91DDBFF92EC06358D5A85E2805 +IV=01BB0A9A8737C19D3A84C453D00001A4 +CT=0F9862A4A21E1FB365135C07577FB3EE +PT=D833DB436E1751B882D03FADF683690B + +I=205 +KEY=83F81E3CED72F22F6305B1D2B3A8A89642B367785EDD410E +IV=80E0E7001CCA60CA7421A6FEC6AE722A +CT=D833DB436E1751B882D03FADF683690B +PT=0AE2C64D2C577C420F26F2F48AA58D62 + +I=206 +KEY=63310E5F2F8F0E0769E7779F9FFFD4D44D95958CD478CC6C +IV=57E54995CDC9417DE0C91063C2FDFC28 +CT=0AE2C64D2C577C420F26F2F48AA58D62 +PT=B0E2976AA3891A2C71AFEB063E3C4383 + +I=207 +KEY=F3AE2989B3980DC9D905E0F53C76CEF83C3A7E8AEA448FEF +IV=999DD6C2B1C528E2909F27D69C1703CE +CT=B0E2976AA3891A2C71AFEB063E3C4383 +PT=16F8A305177ECDBA15403FE5D8EEF60D + +I=208 +KEY=52CF17D8DEA4CE5ACFFD43F02B080342297A416F32AA79E2 +IV=C9F5BC961057F845A1613E516D3CC393 +CT=16F8A305177ECDBA15403FE5D8EEF60D +PT=A607A3EE165E82711B30B44CF4E0C4CF + +I=209 +KEY=E22ADE79E75FE58E69FAE01E3D568133324AF523C64ABD2D +IV=E153F25DD207351AB0E5C9A139FB2BD4 +CT=A607A3EE165E82711B30B44CF4E0C4CF +PT=5191CDD0D077AD6BE956AF8E8E39FECA + +I=210 +KEY=38C58EA4EA1E8D4C386B2DCEED212C58DB1C5AAD487343E7 +IV=F55357187F06B142DAEF50DD0D4168C2 +CT=5191CDD0D077AD6BE956AF8E8E39FECA +PT=F63A42508522E5F09C31F160298E8E6F + +I=211 +KEY=8C29CD4F1330EF25CE516F9E6803C9A8472DABCD61FDCD88 +IV=2CBD520E6F6F89C7B4EC43EBF92E6269 +CT=F63A42508522E5F09C31F160298E8E6F +PT=E58ED2EA8671DC5D527CDE01C6D9655D + +I=212 +KEY=3650C9671F38CD752BDFBD74EE7215F5155175CCA724A8D5 +IV=73CA969AECA5574BBA7904280C082250 +CT=E58ED2EA8671DC5D527CDE01C6D9655D +PT=5FFCACC68357B6709F5B10D48C65EA40 + +I=213 +KEY=6F68A078A75FF5A1742311B26D25A3858A0A65182B414295 +IV=DEA2D7D8F9FE3E7D5938691FB86738D4 +CT=5FFCACC68357B6709F5B10D48C65EA40 +PT=10BBA695F25C1F9412DB80F59F937F84 + +I=214 +KEY=9E08E5F9EEC5A7606498B7279F79BC1198D1E5EDB4D23D11 +IV=20E4DE61513233E5F1604581499A52C1 +CT=10BBA695F25C1F9412DB80F59F937F84 +PT=36CAF539734BCAF8250595E5E5DB3E94 + +I=215 +KEY=F72A5636B3A2D23B5252421EEC3276E9BDD4700851090385 +IV=9DEBE05128A2A1A06922B3CF5D67755B +CT=36CAF539734BCAF8250595E5E5DB3E94 +PT=C64074C9A34850C6FD1B12CD8AE9EF30 + +I=216 +KEY=D74FABF587AB10AA941236D74F7A262F40CF62C5DBE0ECB5 +IV=DEF3A637247B78C02065FDC33409C291 +CT=C64074C9A34850C6FD1B12CD8AE9EF30 +PT=DF663CE4199BC64ACB9B6F99D69EC679 + +I=217 +KEY=8D12BAEA80612A284B740A3356E1E0658B540D5C0D7E2ACC +IV=7D9C0365E66F1A355A5D111F07CA3A82 +CT=DF663CE4199BC64ACB9B6F99D69EC679 +PT=CD1BCBDCE7F8C008177E25B83604EE83 + +I=218 +KEY=57B4196767474175866FC1EFB119206D9C2A28E43B7AC44F +IV=41846FA05FC28ABCDAA6A38DE7266B5D +CT=CD1BCBDCE7F8C008177E25B83604EE83 +PT=CD7E96FE44368C4AD22E9D4F6BE3C2C2 + +I=219 +KEY=CBA15BF34D728F0E4B115711F52FAC274E04B5AB5099068D +IV=873A6522E20108C09C1542942A35CE7B +CT=CD7E96FE44368C4AD22E9D4F6BE3C2C2 +PT=BCC88D6EAF2E41D9AA6E7C91DADCF92E + +I=220 +KEY=D3071140E7C7E244F7D9DA7F5A01EDFEE46AC93A8A45FFA3 +IV=A50F782EA949C2A718A64AB3AAB56D4A +CT=BCC88D6EAF2E41D9AA6E7C91DADCF92E +PT=1FFD3EC8E0D0AD8F3D23961703C0C445 + +I=221 +KEY=3F44AB6E12394D24E824E4B7BAD14071D9495F2D89853BE6 +IV=501500DC8A97D00BEC43BA2EF5FEAF60 +CT=1FFD3EC8E0D0AD8F3D23961703C0C445 +PT=1D3D85A9A4BF101E12CC79640D716AC6 + +I=222 +KEY=D6B97A7D0CEBEA71F519611E1E6E506FCB85264984F45120 +IV=84933D2D2F1F6C13E9FDD1131ED2A755 +CT=1D3D85A9A4BF101E12CC79640D716AC6 +PT=A2228D0483F9CF74CAA301FD30D7DB68 + +I=223 +KEY=E86CCBF22BAF7B31573BEC1A9D979F1B012627B4B4238A48 +IV=4AE5BFEB7168981E3ED5B18F27449140 +CT=A2228D0483F9CF74CAA301FD30D7DB68 +PT=D43E1D2C7447B7C08BCA25F8371AEECF + +I=224 +KEY=0279786975DB97998305F136E9D028DB8AEC024C83396487 +IV=2FC19D77503C0296EA15B39B5E74ECA8 +CT=D43E1D2C7447B7C08BCA25F8371AEECF +PT=4F97B6C0B7D10763CD5CE3A45855FEC0 + +I=225 +KEY=7F842708B71AD43BCC9247F65E012FB847B0E1E8DB6C9A47 +IV=BAC3ED277430C4537DFD5F61C2C143A2 +CT=4F97B6C0B7D10763CD5CE3A45855FEC0 +PT=067B1521895AE654CA0C20492A9714B8 + +I=226 +KEY=2FA21F709793A1C7CAE952D7D75BC9EC8DBCC1A1F1FB8EFF +IV=66014BDC0AD70ABB50263878208975FC +CT=067B1521895AE654CA0C20492A9714B8 +PT=E07E7A1D3F39E45E3A755A82EE3C2EBC + +I=227 +KEY=671468BAD93EDBD32A9728CAE8622DB2B7C99B231FC7A043 +IV=47BFF88E3EC2E8DC48B677CA4EAD7A14 +CT=E07E7A1D3F39E45E3A755A82EE3C2EBC +PT=0933D51670E8918147A56816B838BC74 + +I=228 +KEY=9749A2F6B448445023A4FDDC988ABC33F06CF335A7FF1C37 +IV=58F8C33F4725EED2F05DCA4C6D769F83 +CT=0933D51670E8918147A56816B838BC74 +PT=E90570CDFC2CDCC99826780CA7CD7A1C + +I=229 +KEY=C43D753C2489B403CAA18D1164A660FA684A8B390032662B +IV=C4027E5BF29E96A65374D7CA90C1F053 +CT=E90570CDFC2CDCC99826780CA7CD7A1C +PT=65B6C303491459554CDDA630AAB36C12 + +I=230 +KEY=32F2C804DF89C908AF174E122DB239AF24972D09AA810A39 +IV=51DE94724DCE9B10F6CFBD38FB007D0B +CT=65B6C303491459554CDDA630AAB36C12 +PT=A0B1694685785EFBDD6DB8E4FC312BC4 + +I=231 +KEY=9431549183D690920FA62754A8CA6754F9FA95ED56B021FD +IV=5CBDC9F06F45D2F5A6C39C955C5F599A +CT=A0B1694685785EFBDD6DB8E4FC312BC4 +PT=C271A8F639D1A293F4B8899428F618C2 + +I=232 +KEY=0AA1211F2A2134DACDD78FA2911BC5C70D421C797E46393F +IV=E52D7ACAF5DFAF799E90758EA9F7A448 +CT=C271A8F639D1A293F4B8899428F618C2 +PT=AB7968C2A1859D5AEBFAEB201910B672 + +I=233 +KEY=88BFBDDC6D21FC0E66AEE760309E589DE6B8F75967568F4D +IV=15AF9C49191BF995821E9CC34700C8D4 +CT=AB7968C2A1859D5AEBFAEB201910B672 +PT=59D394BB9C41BE21C050A9DF2DD94C2B + +I=234 +KEY=05AB922FA8B6F5FF3F7D73DBACDFE6BC26E85E864A8FC366 +IV=0FB568270892E7A98D142FF3C59709F1 +CT=59D394BB9C41BE21C050A9DF2DD94C2B +PT=43F89BAE0DCCB0EAF30411E6239A753C + +I=235 +KEY=7A7ED7932DED53767C85E875A1135656D5EC4F606915B65A +IV=48F1E1DAEE9C16CD7FD545BC855BA689 +CT=43F89BAE0DCCB0EAF30411E6239A753C +PT=8196A2F49E2508443F86B294D71A5D5E + +I=236 +KEY=8955F595C21BF3AAFD134A813F365E12EA6AFDF4BE0FEB04 +IV=B3DEB1ED557CB477F32B2206EFF6A0DC +CT=8196A2F49E2508443F86B294D71A5D5E +PT=5ED45F8741E7FC5C77CAACA9D3DFA26D + +I=237 +KEY=09205C9C2A528A5BA3C715067ED1A24E9DA0515D6DD04969 +IV=3742941BC0992AAC8075A909E84979F1 +CT=5ED45F8741E7FC5C77CAACA9D3DFA26D +PT=F60C9F9616A03B40655CB733EE1C3B68 + +I=238 +KEY=46DAA0A9A034745355CB8A906871990EF8FCE66E83CC7201 +IV=A3E1EA7D9E5BA6CE4FFAFC358A66FE08 +CT=F60C9F9616A03B40655CB733EE1C3B68 +PT=E73F7E14A3A245B1E594F659D996ED06 + +I=239 +KEY=DA145A69C9D459E1B2F4F484CBD3DCBF1D6810375A5A9F07 +IV=F5D4EB0EAB3486D29CCEFAC069E02DB2 +CT=E73F7E14A3A245B1E594F659D996ED06 +PT=52651C2039168170765B235D85BF6CEC + +I=240 +KEY=61CD045E05969B9FE091E8A4F2C55DCF6B33336ADFE5F3EB +IV=F7162437A85A186ABBD95E37CC42C27E +CT=52651C2039168170765B235D85BF6CEC +PT=665C920C4BB95B5C716D60AE9C30DB1B + +I=241 +KEY=BDF9F289D095660D86CD7AA8B97C06931A5E53C443D528F0 +IV=ADD7416105DB0CF0DC34F6D7D503FD92 +CT=665C920C4BB95B5C716D60AE9C30DB1B +PT=F6E1D36CF7D41F70885587A85B897EA2 + +I=242 +KEY=4CBAF7692571D8C5702CA9C44EA819E3920BD46C185C5652 +IV=9FBF3815905FCD9FF14305E0F5E4BEC8 +CT=F6E1D36CF7D41F70885587A85B897EA2 +PT=137DB7F20F98671E37F55E401D0482E2 + +I=243 +KEY=CEBF572BB09CC72963511E3641307EFDA5FE8A2C0558D4B0 +IV=0C3951BDCA9582CA8205A04295ED1FEC +CT=137DB7F20F98671E37F55E401D0482E2 +PT=72125C79A48573158496EFCC5CA552D4 + +I=244 +KEY=0D8978CF8179CBBF1143424FE5B50DE8216865E059FD8664 +IV=898422AB0DB951B1C3362FE431E50C96 +CT=72125C79A48573158496EFCC5CA552D4 +PT=6B12016832DE435A963FFFA857824CF7 + +I=245 +KEY=180D2DA794FEAF777A514327D76B4EB2B7579A480E7FCA93 +IV=0B47A508EAD8008015845568158764C8 +CT=6B12016832DE435A963FFFA857824CF7 +PT=18693A241FB5687CF3A793B9B7EE4B15 + +I=246 +KEY=3D6C36453DCA611462387903C8DE26CE44F009F1B9918186 +IV=857CC19C3E72C1AD25611BE2A934CE63 +CT=18693A241FB5687CF3A793B9B7EE4B15 +PT=4E04BD363AFC26BDDD3D98892A7C705A + +I=247 +KEY=8B626E8D8E075BCE2C3CC435F222007399CD917893EDF1DC +IV=6E4FCD034F6E2AF5B60E58C8B3CD3ADA +CT=4E04BD363AFC26BDDD3D98892A7C705A +PT=06FB2C371C3F54518AA0A2766CE1CCF3 + +I=248 +KEY=A5ECEB5BAE22C2E72AC7E802EE1D5422136D330EFF0C3D2F +IV=4A23E1EFBB43855E2E8E85D620259929 +CT=06FB2C371C3F54518AA0A2766CE1CCF3 +PT=D7DE2C298EB1EF273A6386986BDEC555 + +I=249 +KEY=B25537EEFD5BDA7AFD19C42B60ACBB05290EB59694D2F87A +IV=9034BBDBF74A369E17B9DCB55379189D +CT=D7DE2C298EB1EF273A6386986BDEC555 +PT=0F4A1CEA83DA845DEC063ADFF173F424 + +I=250 +KEY=39FEF1C45697DABCF253D8C1E3763F58C5088F4965A10C5E +IV=2B5EF64E50A2CF5F8BABC62AABCC00C6 +CT=0F4A1CEA83DA845DEC063ADFF173F424 +PT=CE27F8AF55009D3658D166B960CA12D6 + +I=251 +KEY=5657BBA1106032F13C74206EB676A26E9DD9E9F0056B1E88 +IV=CE96953F749BBFD66FA94A6546F7E84D +CT=CE27F8AF55009D3658D166B960CA12D6 +PT=BF1458E052637EFC0EEF352621606029 + +I=252 +KEY=A1BC53DEFD62921A8360788EE415DC929336DCD6240B7EA1 +IV=B944FC42142E4940F7EBE87FED02A0EB +CT=BF1458E052637EFC0EEF352621606029 +PT=E4D96706DB5B0DA8FA429BB65BFBE4D8 + +I=253 +KEY=DAC8C0328BA4104167B91F883F4ED13A697447607FF09A79 +IV=A8D8E3A3BB687ECC7B7493EC76C6825B +CT=E4D96706DB5B0DA8FA429BB65BFBE4D8 +PT=1B11FF1367FE94F7759D1BEC40B8FDCC + +I=254 +KEY=03AE3AA5E62CA4927CA8E09B58B045CD1CE95C8C3F4867B5 +IV=35D7DB1466E14E3ED966FA976D88B4D3 +CT=1B11FF1367FE94F7759D1BEC40B8FDCC +PT=0989D688C947C616AC13B63892E35E74 + +I=255 +KEY=EAD5A60BB601C1147521361391F783DBB0FAEAB4ADAB39C1 +IV=59BA56CC11EFA9A2E97B9CAE502D6586 +CT=0989D688C947C616AC13B63892E35E74 +PT=978C150575871FB2C8847AA0CB092108 + +I=256 +KEY=C608EE8A971A0383E2AD2316E4709C69787E901466A218C9 +IV=253A79448D79B0B72CDD4881211BC297 +CT=978C150575871FB2C8847AA0CB092108 +PT=D08629CCCF6B869B10768DE9E2984B2E + +I=257 +KEY=D8EB4FC4230D3E39322B0ADA2B1B1AF268081DFD843A53E7 +IV=E9A7FDB26A37B6601EE3A14EB4173DBA +CT=D08629CCCF6B869B10768DE9E2984B2E +PT=E320AECF3803401AB95E09EB50A6EDA5 + +I=258 +KEY=E3F18E12233B5A30D10BA41513185AE8D1561416D49CBE42 +IV=4C6B62E3E6658BE73B1AC1D600366409 +CT=E320AECF3803401AB95E09EB50A6EDA5 +PT=D29E97683C9989C75D5D73EAADC23EE2 + +I=259 +KEY=7D9DEAA58D97A2FC0395337D2F81D32F8C0B67FC795E80A0 +IV=414A2961119CE4D79E6C64B7AEACF8CC +CT=D29E97683C9989C75D5D73EAADC23EE2 +PT=8D859D878DF32FDD26AF4984D48A1BD2 + +I=260 +KEY=E4A19E3554E8D73B8E10AEFAA272FCF2AAA42E78ADD49B72 +IV=9DF8066FCF854065993C7490D97F75C7 +CT=8D859D878DF32FDD26AF4984D48A1BD2 +PT=7B524B71439722F0555D4681F7EEAAC9 + +I=261 +KEY=0C93CDDA4435E903F542E58BE1E5DE02FFF968F95A3A31BB +IV=9529BF1B1ACEEDA5E83253EF10DD3E38 +CT=7B524B71439722F0555D4681F7EEAAC9 +PT=8C8ECC9829F06F73497EA90D48CD7FC5 + +I=262 +KEY=637747C6EF7B72B579CC2913C815B171B687C1F412F74E7E +IV=ADC9666D259469516FE48A1CAB4E9BB6 +CT=8C8ECC9829F06F73497EA90D48CD7FC5 +PT=6E416C2563212821F0D8E7D75297B11F + +I=263 +KEY=7E4BB22E1A7C4E25178D4536AB349950465F26234060FF61 +IV=C3BE9A54FDDA99731D3CF5E8F5073C90 +CT=6E416C2563212821F0D8E7D75297B11F +PT=EFC73DFA5FB87EA16284E25D22360C2F + +I=264 +KEY=62B7D329DC5EA208F84A78CCF48CE7F124DBC47E6256F34E +IV=E2145312DF24CBDB1CFC6107C622EC2D +CT=EFC73DFA5FB87EA16284E25D22360C2F +PT=1191FC5E2EFA9F19004C7D00E1F4D8B1 + +I=265 +KEY=039B0E1DE399831EE9DB8492DA7678E82497B97E83A22BFF +IV=0931D0D100EEB87D612CDD343FC72116 +CT=1191FC5E2EFA9F19004C7D00E1F4D8B1 +PT=717B1B902086B97296B7E97BC01C259E + +I=266 +KEY=CB02B3C8CA4A0C9498A09F02FAF0C19AB220500543BE0E61 +IV=65D0C1DFC85C7FB9C899BDD529D38F8A +CT=717B1B902086B97296B7E97BC01C259E +PT=569097DA8C43871CC5A55AC150ABCD31 + +I=267 +KEY=5FFAEE959D35C247CE3008D876B3468677850AC41315C350 +IV=7A4A448600ACA08994F85D5D577FCED3 +CT=569097DA8C43871CC5A55AC150ABCD31 +PT=4046F3DF53DFC1B56400501F08200FE0 + +I=268 +KEY=0CA33FAAA4B25FEB8E76FB07256C873313855ADB1B35CCB0 +IV=C83E2121AA25A5295359D13F39879DAC +CT=4046F3DF53DFC1B56400501F08200FE0 +PT=87C5362AAF3F31B05C92189E38FD9C66 + +I=269 +KEY=5B782B675EE9A8A509B3CD2D8A53B6834F17424523C850D6 +IV=567E0CD5EAFC699457DB14CDFA5BF74E +CT=87C5362AAF3F31B05C92189E38FD9C66 +PT=03A5CD79734810F4D9559FDC97A4B1A1 + +I=270 +KEY=B069B5DCAADA727F0A160054F91BA6779642DD99B46CE177 +IV=5397ED8A6DF7641EEB119EBBF433DADA +CT=03A5CD79734810F4D9559FDC97A4B1A1 +PT=1B1ECDDFD726C66594DF7B050F6758FF + +I=271 +KEY=52477DE5EFBAE2621108CD8B2E3D6012029DA69CBB0BB988 +IV=52151355DA4369C8E22EC8394560901D +CT=1B1ECDDFD726C66594DF7B050F6758FF +PT=26E9A7A560DD36D9767A51DA06301BBD + +I=272 +KEY=6E59FF11BED37F8837E16A2E4EE056CB74E7F746BD3BA235 +IV=FB1A5F8FA1C3D1F43C1E82F451699DEA +CT=26E9A7A560DD36D9767A51DA06301BBD +PT=C2FAB5CDDB329F2EA1E1459251A3CB1B + +I=273 +KEY=504DE2EC58CE17BBF51BDFE395D2C9E5D506B2D4EC98692E +IV=6BCD90C4D648AB783E141DFDE61D6833 +CT=C2FAB5CDDB329F2EA1E1459251A3CB1B +PT=4293D0A26E81DBE9FED6113B1954D59F + +I=274 +KEY=CC6C6C4150E763AAB7880F41FB53120C2BD0A3EFF5CCBCB1 +IV=0F61DAA62B7E95A79C218EAD08297411 +CT=4293D0A26E81DBE9FED6113B1954D59F +PT=5DC81F054088DB9B3D1F8AD4BACC2039 + +I=275 +KEY=BD3B4967A596578FEA401044BBDBC99716CF293B4F009C88 +IV=0C6435697122955071572526F5713425 +CT=5DC81F054088DB9B3D1F8AD4BACC2039 +PT=B6FB950586C671E968FFC709B79E8AF8 + +I=276 +KEY=9A08B753E07CD6535CBB85413D1DB87E7E30EE32F89E1670 +IV=377A670B7487B3EB2733FE3445EA81DC +CT=B6FB950586C671E968FFC709B79E8AF8 +PT=ED69B1E52F5F095EFF0AC73A76039B65 + +I=277 +KEY=E5FAA83242346B4EB1D234A41242B120813A29088E9D8D15 +IV=DBEEED8784AD80B57FF21F61A248BD1D +CT=ED69B1E52F5F095EFF0AC73A76039B65 +PT=FBC0C9A6FBC2CCD02BF5A009B43FE903 + +I=278 +KEY=44770F6B1653E2754A12FD02E9807DF0AACF89013AA26416 +IV=7D9B061A6209E0FAA18DA7595467893B +CT=FBC0C9A6FBC2CCD02BF5A009B43FE903 +PT=ADBE2B6C2C979C90E019991C5E81F69E + +I=279 +KEY=89A3B49BBE885D34E7ACD66EC517E1604AD6101D64239288 +IV=5495C29E4DDA4E26CDD4BBF0A8DBBF41 +CT=ADBE2B6C2C979C90E019991C5E81F69E +PT=E382D6611C0B2591BE9B7B6BC66D479D + +I=280 +KEY=457D838277C2797B042E000FD91CC4F1F44D6B76A24ED515 +IV=0303BB8A65CCE419CCDE3719C94A244F +CT=E382D6611C0B2591BE9B7B6BC66D479D +PT=7A39D5BFC7ADB6B7539A1AA45A31A7E5 + +I=281 +KEY=814AD70FBAF9D8AA7E17D5B01EB17246A7D771D2F87F72F0 +IV=550BD125E57ADE94C437548DCD3BA1D1 +CT=7A39D5BFC7ADB6B7539A1AA45A31A7E5 +PT=3CB8FF426FF48FA93EFAEDC559833C86 + +I=282 +KEY=89599F584B46337342AF2AF27145FDEF992D9C17A1FC4E76 +IV=45800DE7659A8FD008134857F1BFEBD9 +CT=3CB8FF426FF48FA93EFAEDC559833C86 +PT=2F5C7660310DE65B1C5254E2176A15CA + +I=283 +KEY=8EF84BDE14C7412B6DF35C9240481BB4857FC8F5B6965BBC +IV=5142FFEADEC300C107A1D4865F817258 +CT=2F5C7660310DE65B1C5254E2176A15CA +PT=7A3056742CF8CFDE9CBEAE32607E8DE3 + +I=284 +KEY=F076085EE3EA165617C30AE66CB0D46A19C166C7D6E8D65F +IV=02FBB83EDCB092957E8E4380F72D577D +CT=7A3056742CF8CFDE9CBEAE32607E8DE3 +PT=B2B7B7551B2A1D59601003C6EDD70A78 + +I=285 +KEY=7D74D286D9CEC1C3A574BDB3779AC93379D165013B3FDC27 +IV=890E42EAA4C59B078D02DAD83A24D795 +CT=B2B7B7551B2A1D59601003C6EDD70A78 +PT=8B617CCD9B1289F485167DC13126795C + +I=286 +KEY=8BA3AA3C04001B9D2E15C17EEC8840C7FCC718C00A19A57B +IV=F96182D81751ECCAF6D778BADDCEDA5E +CT=8B617CCD9B1289F485167DC13126795C +PT=D4800EE4A5E29A18C655AD5CE23063F9 + +I=287 +KEY=E51B3BF1DF7B0D54FA95CF9A496ADADF3A92B59CE829C682 +IV=46297563D303DF226EB891CDDB7B16C9 +CT=D4800EE4A5E29A18C655AD5CE23063F9 +PT=4A6008072DCEB7602BF120F0984FF1D6 + +I=288 +KEY=82091A039C558D36B0F5C79D64A46DBF1163956C70663754 +IV=28E82D15BAC860EA671221F2432E8062 +CT=4A6008072DCEB7602BF120F0984FF1D6 +PT=B05CD61BC646851726441B147FBB1AD3 + +I=289 +KEY=C503B4B113DE349700A91186A2E2E8A837278E780FDD2D87 +IV=342F9FDEEEBE130A470AAEB28F8BB9A1 +CT=B05CD61BC646851726441B147FBB1AD3 +PT=33E1834199EE6CD5C6F950D4823B2337 + +I=290 +KEY=4B06065B748AFB69334892C73B0C847DF1DEDEAC8DE60EB0 +IV=02928C43C0FF24968E05B2EA6754CFFE +CT=33E1834199EE6CD5C6F950D4823B2337 +PT=BA0BD1FFA54258361D3A8BD9F3C689E4 + +I=291 +KEY=AD0B10216B5D496B894343389E4EDC4BECE455757E208754 +IV=50DC56062E88C9CAE60D167A1FD7B202 +CT=BA0BD1FFA54258361D3A8BD9F3C689E4 +PT=4911046D8F1D2BCF54F22B5A83AF5AE1 + +I=292 +KEY=AF6CC229A2618121C05247551153F784B8167E2FFD8FDDB5 +IV=A7CC6A2B280A9DE80267D208C93CC84A +CT=4911046D8F1D2BCF54F22B5A83AF5AE1 +PT=254CA1983D7B794911B455E857CE902B + +I=293 +KEY=66413E8C7D11836FE51EE6CD2C288ECDA9A22BC7AA414D9E +IV=D01066ADC643A032C92DFCA5DF70024E +CT=254CA1983D7B794911B455E857CE902B +PT=B0A100E60D0404D123D10AE78E9CFFCB + +I=294 +KEY=D13AF271F9C3337455BFE62B212C8A1C8A73212024DDB255 +IV=20D00A218F07ECEDB77BCCFD84D2B01B +CT=B0A100E60D0404D123D10AE78E9CFFCB +PT=D4CD0CC7D2EBAB050108E94365D34FAA + +I=295 +KEY=8B3C7094C3AD8B018172EAECF3C721198B7BC863410EFDFF +IV=EC5F46869A00FFC25A0682E53A6EB875 +CT=D4CD0CC7D2EBAB050108E94365D34FAA +PT=DF913CC34675469401CCA41DB50BFBA4 + +I=296 +KEY=7DCF9D4559C3EA3A5EE3D62FB5B2678D8AB76C7EF405065B +IV=8718728B7105A417F6F3EDD19A6E613B +CT=DF913CC34675469401CCA41DB50BFBA4 +PT=5B09F0AF91EA41851A232543E97A6ED4 + +I=297 +KEY=C3E6C2A9975117B605EA2680245826089094493D1D7F688F +IV=21D001128A401EBFBE295FECCE92FD8C +CT=5B09F0AF91EA41851A232543E97A6ED4 +PT=8544DFD1E46D14FF1B0E9CF43A7E9EB6 + +I=298 +KEY=54C6D7971066FDD380AEF951C03532F78B9AD5C92701F639 +IV=F861E1C66C3F21779720153E8737EA65 +CT=8544DFD1E46D14FF1B0E9CF43A7E9EB6 +PT=586696A67E355CCDC41AD16D87786773 + +I=299 +KEY=B47A128050D1FC84D8C86FF7BE006E3A4F8004A4A079914A +IV=55A87D49D3640887E0BCC51740B70157 +CT=586696A67E355CCDC41AD16D87786773 +PT=6C7FF8D2F033B33C729C556E0731ACFF + +I=300 +KEY=C66EA18D75351D93B4B797254E33DD063D1C51CAA7483DB5 +IV=7224A11A5D122A607214B30D25E4E117 +CT=6C7FF8D2F033B33C729C556E0731ACFF +PT=BC031D9B497C64B15EE143CF4D2130B1 + +I=301 +KEY=00432A82295B2C6708B48ABE074FB9B763FD1205EA690D04 +IV=61D8239BE618CC39C62D8B0F5C6E31F4 +CT=BC031D9B497C64B15EE143CF4D2130B1 +PT=325D14CCDE09311A8069C5522FD050FD + +I=302 +KEY=E03B01935511FA7E3AE99E72D94688ADE394D757C5B95DF9 +IV=339B83266B282A96E0782B117C4AD619 +CT=325D14CCDE09311A8069C5522FD050FD +PT=FA25D0913004A26A3232F743ACC7677E + +I=303 +KEY=47F79639F27D47E9C0CC4EE3E9422AC7D1A62014697E3A87 +IV=C5F60E2EC86A0971A7CC97AAA76CBD97 +CT=FA25D0913004A26A3232F743ACC7677E +PT=61AA67B567F1CE94326B4711F8115727 + +I=304 +KEY=EE86C028A3B01E7EA16629568EB3E453E3CD6705916F6DA0 +IV=4037462A5B08A27FA971561151CD5997 +CT=61AA67B567F1CE94326B4711F8115727 +PT=35D0FD8AFF6CBDF34065CED4796D9D27 + +I=305 +KEY=EE88DBE9CCC930CB94B6D4DC71DF59A0A3A8A9D1E802F087 +IV=20CB619D26A05953000E1BC16F792EB5 +CT=35D0FD8AFF6CBDF34065CED4796D9D27 +PT=DD69B839EAE7D0DF79F5D06140D54325 + +I=306 +KEY=C77ADB703861D01649DF6CE59B38897FDA5D79B0A8D7B3A2 +IV=16CFCF6A4F3272EA29F20099F4A8E0DD +CT=DD69B839EAE7D0DF79F5D06140D54325 +PT=CA93E79E612893AA0D979ABDF5CA788A + +I=307 +KEY=3F486F048B5D9716834C8B7BFA101AD5D7CAE30D5D1DCB28 +IV=58332C3A8F187A96F832B474B33C4700 +CT=CA93E79E612893AA0D979ABDF5CA788A +PT=39974A1C62DF12F62EC9F75704B0EFA8 + +I=308 +KEY=B9022C8EA2C6FEF4BADBC16798CF0823F903145A59AD2480 +IV=3C09D97EFC480CD6864A438A299B69E2 +CT=39974A1C62DF12F62EC9F75704B0EFA8 +PT=B840EFC34BCD941BF551E437D633BB3A + +I=309 +KEY=D22317E3BB60B9FA029B2EA4D3029C380C52F06D8F9E9FBA +IV=C755A4CF1FAD90046B213B6D19A6470E +CT=B840EFC34BCD941BF551E437D633BB3A +PT=979F6217FD73CAB73A1DE1FACF68542C + +I=310 +KEY=E196EBBFCDA64F7095044CB32E71568F364F119740F6CB96 +IV=D342A7B4EF6CB49F33B5FC5C76C6F68A +CT=979F6217FD73CAB73A1DE1FACF68542C +PT=A290A25CFBCB1BEE137AFB860BB2CF29 + +I=311 +KEY=B756B878A99088B83794EEEFD5BA4D612535EA114B4404BF +IV=D92C9835E799541056C053C76436C7C8 +CT=A290A25CFBCB1BEE137AFB860BB2CF29 +PT=7E99249836CA5167C88BD3431C78C2E0 + +I=312 +KEY=2515F524203B507E490DCA77E3701C06EDBE3952573CC65F +IV=FD7219F6C131C4BD92434D5C89ABD8C6 +CT=7E99249836CA5167C88BD3431C78C2E0 +PT=5B7DAB9C2148A2B7ACCE4723D1D63B3F + +I=313 +KEY=28A33899811FE9B7127061EBC238BEB141707E7186EAFD60 +IV=F6B29A78141D8F8A0DB6CDBDA124B9C9 +CT=5B7DAB9C2148A2B7ACCE4723D1D63B3F +PT=12BAE3836257C52B88ECEEAAE8DE3B80 + +I=314 +KEY=85C6089FEF19163500CA8268A06F7B9AC99C90DB6E34C6E0 +IV=AE11E9BE14B4ECB1AD6530066E06FF82 +CT=12BAE3836257C52B88ECEEAAE8DE3B80 +PT=71C5D9F8747D428DE30736C4DD33E3E5 + +I=315 +KEY=86665ED5DA56FE90710F5B90D41239172A9BA61FB3072505 +IV=2CBAA91201D1980B03A0564A354FE8A5 +CT=71C5D9F8747D428DE30736C4DD33E3E5 +PT=D824A3FB80554CCD519D730D25EED2AF + +I=316 +KEY=F6D0840D75423D5CA92BF86B544775DA7B06D51296E9F7AA +IV=66AA086063C3768C70B6DAD8AF14C3CC +CT=D824A3FB80554CCD519D730D25EED2AF +PT=C974BCBE88ACA9D29312192BE52885BD + +I=317 +KEY=56F2FDAAB52A8691605F44D5DCEBDC08E814CC3973C17217 +IV=14D16CCEDE70F435A02279A7C068BBCD +CT=C974BCBE88ACA9D29312192BE52885BD +PT=23B74C4B5E661FA157F571F4C13AA3AE + +I=318 +KEY=676109782F02525643E8089E828DC3A9BFE1BDCDB2FBD1B9 +IV=46BB517768227D1D3193F4D29A28D4C7 +CT=23B74C4B5E661FA157F571F4C13AA3AE +PT=BDF2A1A79D553C85F5867B2BD5259A82 + +I=319 +KEY=D21B20B085B317EDFE1AA9391FD8FF2C4A67C6E667DE4B3B +IV=054B26F10A7F2D69B57A29C8AAB145BB +CT=BDF2A1A79D553C85F5867B2BD5259A82 +PT=1E02970BE31FEE63C9BCCC79FB41F670 + +I=320 +KEY=3CF3F93D44647FB7E0183E32FCC7114F83DB0A9F9C9FBD4B +IV=C44342FC579F9083EEE8D98DC1D7685A +CT=1E02970BE31FEE63C9BCCC79FB41F670 +PT=70F71372F64174D7C8757F043812439F + +I=321 +KEY=2C83CB76D99E054E90EF2D400A8665984BAE759BA48DFED4 +IV=884B46D9FBE7D99C1070324B9DFA7AF9 +CT=70F71372F64174D7C8757F043812439F +PT=46B20E91579B5CC0ADE9327478DF25FA + +I=322 +KEY=0ADEA18FAA36E94BD65D23D15D1D3958E64747EFDC52DB2E +IV=F256BC3206E11E9C265D6AF973A8EC05 +CT=46B20E91579B5CC0ADE9327478DF25FA +PT=51FE245369F67740615E159E28C2D56C + +I=323 +KEY=E0C00F8BFD4ADCD087A3078234EB4E1887195271F4900E42 +IV=836F6756B9EC572DEA1EAE04577C359B +CT=51FE245369F67740615E159E28C2D56C +PT=58A1B407358C1F9783A05C0A43D5B4FB + +I=324 +KEY=EEA0B17E70A6FC53DF02B3850167518F04B90E7BB745BAB9 +IV=0E584BF6D72F08310E60BEF58DEC2083 +CT=58A1B407358C1F9783A05C0A43D5B4FB +PT=6212DD8752996CC4D747790D5F2BC7E7 + +I=325 +KEY=B6E49EEA07D03112BD106E0253FE3D4BD3FE7776E86E7D5E +IV=2BA760FB0CC14D1858442F947776CD41 +CT=6212DD8752996CC4D747790D5F2BC7E7 +PT=DB16C25BDE0B95F4EC7B34FA2096E6A6 + +I=326 +KEY=F64DCEBA5E71D73E6606AC598DF5A8BF3F85438CC8F89BF8 +IV=674AA4866EE9988E40A9505059A1E62C +CT=DB16C25BDE0B95F4EC7B34FA2096E6A6 +PT=BB98BBB3289F3B5A96C5D3DA92F8CD0F + +I=327 +KEY=23CBCCA3D63DABB8DD9E17EAA56A93E5A94090565A0056F7 +IV=E3D676539CBD9676D5860219884C7C86 +CT=BB98BBB3289F3B5A96C5D3DA92F8CD0F +PT=324C1661B1E289EA3DAC27AF14E026C5 + +I=328 +KEY=D6F7C4A098C4E809EFD2018B14881A0F94ECB7F94EE07032 +IV=E7FB3F340E160FB5F53C08034EF943B1 +CT=324C1661B1E289EA3DAC27AF14E026C5 +PT=6EDA104789445C38F66EC2562F95FBDB + +I=329 +KEY=4B795FAB98879223810811CC9DCC4637628275AF61758BE9 +IV=C5E830814D72E9449D8E9B0B00437A2A +CT=6EDA104789445C38F66EC2562F95FBDB +PT=C834C54858181891C7D654A7502C0B60 + +I=330 +KEY=AA317465E376BAF2493CD484C5D45EA6A554210831598089 +IV=2388FCCDB47CB5DBE1482BCE7BF128D1 +CT=C834C54858181891C7D654A7502C0B60 +PT=9C5F5599557D176050BBAC4258B87F66 + +I=331 +KEY=B601C39C0E5F02DED563811D90A949C6F5EF8D4A69E1FFEF +IV=10C2528D377387311C30B7F9ED29B82C +CT=9C5F5599557D176050BBAC4258B87F66 +PT=ED5F51A6AFA843D467E21F6C68992273 + +I=332 +KEY=44A1FE3F8349D500383CD0BB3F010A12920D92260178DD9C +IV=9E73D9FB1D2471E8F2A03DA38D16D7DE +CT=ED5F51A6AFA843D467E21F6C68992273 +PT=D7A5F18382F892264008F75707254D95 + +I=333 +KEY=568F031D75B9B48FEF992138BDF99834D2056571065D9009 +IV=DEC9B60FA5A91887122EFD22F6F0618F +CT=D7A5F18382F892264008F75707254D95 +PT=D13A34D9F57884ECEE2FA1A412584BE4 + +I=334 +KEY=72CFCCE9FE5EB48A3EA315E148811CD83C2AC4D51405DBED +IV=75C70261D0C49D692440CFF48BE70005 +CT=D13A34D9F57884ECEE2FA1A412584BE4 +PT=064D550098F0813D145A2AA296064CCF + +I=335 +KEY=58448186BD1ED1FC38EE40E1D0719DE52870EE7782039722 +IV=754A1B79A75BD3B32A8B4D6F43406576 +CT=064D550098F0813D145A2AA296064CCF +PT=D7CD7D2B23E42F7A9808D48C28982743 + +I=336 +KEY=6FF7BCC770079D57EF233DCAF395B29FB0783AFBAA9BB061 +IV=25EE1F4D8F257C6437B33D41CD194CAB +CT=D7CD7D2B23E42F7A9808D48C28982743 +PT=6F55D4C7A13F08A1D936C5F0177040CA + +I=337 +KEY=7ECBB104AA3505E58076E90D52AABA3E694EFF0BBDEBF0AB +IV=E21F1527B69B89C8113C0DC3DA3298B2 +CT=6F55D4C7A13F08A1D936C5F0177040CA +PT=7F061908571CDDBC1F8F82A31A3AF1F9 + +I=338 +KEY=135D99B5F2482FFAFF70F00505B6678276C17DA8A7D10152 +IV=5DA54CDB26A0DC2D6D9628B1587D2A1F +CT=7F061908571CDDBC1F8F82A31A3AF1F9 +PT=30AB085953DE3E8027DE0C8A185A7D02 + +I=339 +KEY=3C76458A987B66F0CFDBF85C56685902511F7122BF8B7C50 +IV=E0614E072D2563DD2F2BDC3F6A33490A +CT=30AB085953DE3E8027DE0C8A185A7D02 +PT=92C915E98AEBF6265C43A66AC5B40787 + +I=340 +KEY=EBD41B4484EA67A05D12EDB5DC83AF240D5CD7487A3F7BD7 +IV=6EA27DF02FA0A9A9D7A25ECE1C910150 +CT=92C915E98AEBF6265C43A66AC5B40787 +PT=E9AC0996F97FFBA0F7C860A089CDF99F + +I=341 +KEY=85B6BBBC8E2243D3B4BEE42325FC5484FA94B7E8F3F28248 +IV=46D915F802932C936E62A0F80AC82473 +CT=E9AC0996F97FFBA0F7C860A089CDF99F +PT=BA1D082EDB28E255CB37AFEDB497D43A + +I=342 +KEY=BDA8736E56DDB34F0EA3EC0DFED4B6D131A3180547655672 +IV=0A7B9BCBE89E4CDE381EC8D2D8FFF09C +CT=BA1D082EDB28E255CB37AFEDB497D43A +PT=63298FE15A14C4A4E582C57772A0581E + +I=343 +KEY=9B5DC0C3B097B7CE6D8A63ECA4C07275D421DD7235C50E6C +IV=81F4666446CB470526F5B3ADE64A0481 +CT=63298FE15A14C4A4E582C57772A0581E +PT=AE79390C6789DFCF7110BA93281E9895 + +I=344 +KEY=E64DDC6A55048E35C3F35AE0C349ADBAA53167E11DDB96F9 +IV=DB4439803A1ACA807D101CA9E59339FB +CT=AE79390C6789DFCF7110BA93281E9895 +PT=2C9DF2ED511595756E5CF6D33442D3A3 + +I=345 +KEY=9C75AC9CBA0918CDEF6EA80D925C38CFCB6D91322999455A +IV=B73DBACA0C10AD0A7A3870F6EF0D96F8 +CT=2C9DF2ED511595756E5CF6D33442D3A3 +PT=90FDAEAEDC379128B73515CB2AAC9B7A + +I=346 +KEY=A045744F6BB9205F7F9306A34E6BA9E77C5884F90335DE20 +IV=356BBCDD4EBDA8F93C30D8D3D1B03892 +CT=90FDAEAEDC379128B73515CB2AAC9B7A +PT=E66EA385E1F20791090CA24ADB250AFC + +I=347 +KEY=48E94FAC40CFC94B99FDA526AF99AE76755426B3D810D4DC +IV=ABAF17EBE3658829E8AC3BE32B76E914 +CT=E66EA385E1F20791090CA24ADB250AFC +PT=A17C6802F4322D97C6966B523B54CF88 + +I=348 +KEY=3FC9CD7847FF49D73881CD245BAB83E1B3C24DE1E3441B54 +IV=7D25F4EE8B874E2D772082D40730809C +CT=A17C6802F4322D97C6966B523B54CF88 +PT=CBEC825D143BF30C58B608B58ABFB618 + +I=349 +KEY=D4464B5CD3CFAD06F36D4F794F9070EDEB74455469FBAD4C +IV=93D0E88641960F8EEB8F86249430E4D1 +CT=CBEC825D143BF30C58B608B58ABFB618 +PT=D7A8E224DAA4DB7629790D3D4D5A8560 + +I=350 +KEY=73DD2DA38114D0BD24C5AD5D9534AB9BC20D486924A1282C +IV=3E6B8F8084BAA391A79B66FF52DB7DBB +CT=D7A8E224DAA4DB7629790D3D4D5A8560 +PT=EB7EAD5CF27BA091DEF8D7839EFD7C90 + +I=351 +KEY=CDA609EB23BB90EBCFBB0001674F0B0A1CF59FEABA5C54BC +IV=8EEE61573B01F1E4BE7B2448A2AF4056 +CT=EB7EAD5CF27BA091DEF8D7839EFD7C90 +PT=2EFA41B666ECBBB1D699C1FB8CA9E175 + +I=352 +KEY=768FCC098B8F48FFE14141B701A3B0BBCA6C5E1136F5B5C9 +IV=60BC671273707E17BB29C5E2A834D814 +CT=2EFA41B666ECBBB1D699C1FB8CA9E175 +PT=44D7245914CF3BF73831D4225BD32FDD + +I=353 +KEY=91F2FFA6BB520FD1A59665EE156C8B4CF25D8A336D269A14 +IV=21187FBCFC5E01BEE77D33AF30DD472E +CT=44D7245914CF3BF73831D4225BD32FDD +PT=E9FA049C77C326A4F03D2C9E740DE4A1 + +I=354 +KEY=2FC9C39B5DBC560E4C6C617262AFADE80260A6AD192B7EB5 +IV=72912E59A0095846BE3B3C3DE6EE59DF +CT=E9FA049C77C326A4F03D2C9E740DE4A1 +PT=9A62281465C72FDAA73E00E343A99BC3 + +I=355 +KEY=F401ED3768BC72D4D60E496607688232A55EA64E5A82E576 +IV=88022668FE843060DBC82EAC350024DA +CT=9A62281465C72FDAA73E00E343A99BC3 +PT=FAD9ADA4B98A4141A2857F93F6F71DEB + +I=356 +KEY=1AD741BDF8A18D8E2CD7E4C2BEE2C37307DBD9DDAC75F89D +IV=F98FECC470C84631EED6AC8A901DFF5A +CT=FAD9ADA4B98A4141A2857F93F6F71DEB +PT=630453171FEE434834490229830E1C1A + +I=357 +KEY=24F7B99681335EAD4FD3B7D5A10C803B3392DBF42F7BE487 +IV=5D69B4D81847DABD3E20F82B7992D323 +CT=630453171FEE434834490229830E1C1A +PT=DE613189001598BA6AE67F259F9FD349 + +I=358 +KEY=60E401E96083FF2291B2865CA11918815974A4D1B0E437CE +IV=AADE84AD4127FCDA4413B87FE1B0A18F +CT=DE613189001598BA6AE67F259F9FD349 +PT=CA18925634072DEC80F2F724A0F24235 + +I=359 +KEY=66831E7F4FC51DB95BAA140A951E356DD98653F5101675FB +IV=1C1E2F698C5DD62006671F962F46E29B +CT=CA18925634072DEC80F2F724A0F24235 +PT=B289F06551C56B77F5CDF7B321E0E8E3 + +I=360 +KEY=48FB1A5B41F634D5E923E46FC4DB5E1A2C4BA44631F69D18 +IV=6A872620ED13A14B2E7804240E33296C +CT=B289F06551C56B77F5CDF7B321E0E8E3 +PT=13B1F93DD388A192D6FB836C90E0E022 + +I=361 +KEY=F13FA6E33170F596FA921D521753FF88FAB0272AA1167D3A +IV=40BF714207DA180BB9C4BCB87086C143 +CT=13B1F93DD388A192D6FB836C90E0E022 +PT=298B7B19A27EA1BE9574588A5885F64B + +I=362 +KEY=CE171639A4DDA77DD319664BB52D5E366FC47FA0F9938B71 +IV=8FB32729166E154F3F28B0DA95AD52EB +CT=298B7B19A27EA1BE9574588A5885F64B +PT=11FA000C73485654A8918360DF3C1F5E + +I=363 +KEY=9322B0E9AE4D6B20C2E36647C6650862C755FCC026AF942F +IV=809DE75B169C56BE5D35A6D00A90CC5D +CT=11FA000C73485654A8918360DF3C1F5E +PT=05533E642958E2F6F29BB1848BE225CB + +I=364 +KEY=21B86D89874D627FC7B05823EF3DEA9435CE4D44AD4DB1E4 +IV=81CF24C876471695B29ADD602900095F +CT=05533E642958E2F6F29BB1848BE225CB +PT=613DB485B9565B4889887282A3C8CFB5 + +I=365 +KEY=6E5AD95BDDA04D12A68DECA6566BB1DCBC463FC60E857E51 +IV=7E3AC16D28733BD84FE2B4D25AED2F6D +CT=613DB485B9565B4889887282A3C8CFB5 +PT=0CDDDA3B3375430B601BA1CCBD567284 + +I=366 +KEY=807937B80E55E814AA50369D651EF2D7DC5D9E0AB3D30CD5 +IV=C49324EE3A928684EE23EEE3D3F5A506 +CT=0CDDDA3B3375430B601BA1CCBD567284 +PT=C47A6E22A123AB6397F9C2AFFA6D45AB + +I=367 +KEY=20B3595EFE3D3DA76E2A58BFC43D59B44BA45CA549BE497E +IV=B188E4D3A2AC3F42A0CA6EE6F068D5B3 +CT=C47A6E22A123AB6397F9C2AFFA6D45AB +PT=71592AFCA1FEEE8AB6D6CEF22C14A21D + +I=368 +KEY=A97EAD081EDF66D11F73724365C3B73EFD72925765AAEB63 +IV=0DFF90FA3722469289CDF456E0E25B76 +CT=71592AFCA1FEEE8AB6D6CEF22C14A21D +PT=F4E0C4BCF8B386CF1BD457BD1FB65646 + +I=369 +KEY=DA90448D67D59E3CEB93B6FF9D7031F1E6A6C5EA7A1CBD25 +IV=154DB6488872217073EEE985790AF8ED +CT=F4E0C4BCF8B386CF1BD457BD1FB65646 +PT=9ED1119909322C280FE92B7840792605 + +I=370 +KEY=CF62D3016C8507F17542A76694421DD9E94FEE923A659B20 +IV=ED45F0A7D33FC08515F2978C0B5099CD +CT=9ED1119909322C280FE92B7840792605 +PT=F812615F1BE701E74FCEEFC288303C7C + +I=371 +KEY=C2681849C663E45A8D50C6398FA51C3EA6810150B255A75C +IV=19E09027253115100D0ACB48AAE6E3AB +CT=F812615F1BE701E74FCEEFC288303C7C +PT=25897C51C5FEDBFDC630BF8E9F3B2875 + +I=372 +KEY=F47C452077541CEEA8D9BA684A5BC7C360B1BEDE2D6E8F29 +IV=2C2EE28C518163DF36145D69B137F8B4 +CT=25897C51C5FEDBFDC630BF8E9F3B2875 +PT=9929E5E9F0CA00D0E02022E2FCFAFC3F + +I=373 +KEY=F7BF8679C8D86E2C31F05F81BA91C71380919C3CD1947316 +IV=FCF0C5D85049463103C3C359BF8C72C2 +CT=9929E5E9F0CA00D0E02022E2FCFAFC3F +PT=3B603A3FDAA669E7C965708C9789E329 + +I=374 +KEY=9312EDA0B14017910A9065BE6037AEF449F4ECB0461D903F +IV=364CDACF5762B18864AD6BD9799879BD +CT=3B603A3FDAA669E7C965708C9789E329 +PT=AC33F7B1A778C36617668C98E20B318A + +I=375 +KEY=D5BC989407D78D82A6A3920FC74F6D925E926028A416A1B5 +IV=5FB00506C71711D046AE7534B6979A13 +CT=AC33F7B1A778C36617668C98E20B318A +PT=B408AF5509EF45E0AEDF12570FAE3651 + +I=376 +KEY=6BBB14591C12578112AB3D5ACEA02872F04D727FABB897E4 +IV=D41F58F192CF60D6BE078CCD1BC5DA03 +CT=B408AF5509EF45E0AEDF12570FAE3651 +PT=39EB055E027AC0DEA5992B7BA3753AB5 + +I=377 +KEY=3F71566EA7D07EBF2B403804CCDAE8AC55D4590408CDAD51 +IV=7E495DEC2224696554CA4237BBC2293E +CT=39EB055E027AC0DEA5992B7BA3753AB5 +PT=832B01D2AD4F0EE077244CF9B6ABE31C + +I=378 +KEY=0BDC563CE47527D1A86B39D66195E64C22F015FDBE664E4D +IV=4FE13E98163C3F7734AD005243A5596E +CT=832B01D2AD4F0EE077244CF9B6ABE31C +PT=926EB7E17FA4262D1D390D83CDAC6FB2 + +I=379 +KEY=07D4D606747858B63A058E371E31C0613FC9187E73CA21FF +IV=12D459160DCFFEFE0C08803A900D7F67 +CT=926EB7E17FA4262D1D390D83CDAC6FB2 +PT=DBFBC3313F86C26BA54B9F69BA93C665 + +I=380 +KEY=84BE014D4BFA8ACCE1FE4D0621B7020A9A828717C959E79A +IV=179322B7D19F3A38836AD74B3F82D27A +CT=DBFBC3313F86C26BA54B9F69BA93C665 +PT=39B00A1A655B298F56271B2BDBA6B16B + +I=381 +KEY=A921F537F5F324CAD84E471C44EC2B85CCA59C3C12FF56F1 +IV=D4B03D3AB6FF79D22D9FF47ABE09AE06 +CT=39B00A1A655B298F56271B2BDBA6B16B +PT=7C5DABBF7C7951808DCD35DB2617B763 + +I=382 +KEY=3BB6AACEEEC21A9FA413ECA338957A054168A9E734E8E192 +IV=5C92A3C4C3C8567792975FF91B313E55 +CT=7C5DABBF7C7951808DCD35DB2617B763 +PT=BD88FB3B815415503D4F9264AFEA7887 + +I=383 +KEY=008F402C3524BCA8199B1798B9C16F557C273B839B029915 +IV=08360D06E31B3AA43B39EAE2DBE6A637 +CT=BD88FB3B815415503D4F9264AFEA7887 +PT=B2813AFBC477618F4C6A436C97AA26F2 + +I=384 +KEY=8AB9F9FC4EE8B2D4AB1A2D637DB60EDA304D78EF0CA8BFE7 +IV=DCF7EF19F68916268A36B9D07BCC0E7C +CT=B2813AFBC477618F4C6A436C97AA26F2 +PT=1E96D52E46B1D73EB00778B203946F28 + +I=385 +KEY=CA9D4CE917399619B58CF84D3B07D9E4804A005D0F3CD0CF +IV=63A112DB63DDECB54024B51559D124CD +CT=1E96D52E46B1D73EB00778B203946F28 +PT=C03D770FE4B1733C5E59DD68F0060D5A + +I=386 +KEY=1D8268F833FC772575B18F42DFB6AAD8DE13DD35FF3ADD95 +IV=8B7AC769F85BA650D71F241124C5E13C +CT=C03D770FE4B1733C5E59DD68F0060D5A +PT=6495A8A3667DEDE2CAB58BA3B2F7034E + +I=387 +KEY=CCCEE884786AF28A112427E1B9CB473A14A656964DCDDEDB +IV=280C5BD88E3B88ACD14C807C4B9685AF +CT=6495A8A3667DEDE2CAB58BA3B2F7034E +PT=4CC3C2AC85EBD619E708988C9FEC60C6 + +I=388 +KEY=8B85284B2B06874D5DE7E54D3C209123F3AECE1AD221BE1D +IV=62E112946391FEFB474BC0CF536C75C7 +CT=4CC3C2AC85EBD619E708988C9FEC60C6 +PT=1522371FD5D53919F52CD97258CEBDA7 + +I=389 +KEY=B2EBBE81CF234A7E48C5D252E9F5A83A068217688AEF03BA +IV=8A936BAE971C0C9F396E96CAE425CD33 +CT=1522371FD5D53919F52CD97258CEBDA7 +PT=4AA882DCB39AA79E8439E9ECE9F4F3BD + +I=390 +KEY=043B9FDDEC299802026D508E5A6F0FA482BBFE84631BF007 +IV=6FA7FCDBA3B1BCA5B6D0215C230AD27C +CT=4AA882DCB39AA79E8439E9ECE9F4F3BD +PT=28C1E45D8D01AD148FA7D7C4F41ACE04 + +I=391 +KEY=1074F9BD3FFD4EAF2AACB4D3D76EA2B00D1C294097013E03 +IV=1210BAF1D69B23FE144F6660D3D4D6AD +CT=28C1E45D8D01AD148FA7D7C4F41ACE04 +PT=3ABE04FC59C3BDF9D7721902DEFCB439 + +I=392 +KEY=D97F3440E3684D291012B02F8EAD1F49DA6E304249FD8A3A +IV=C271800852E147D5C90BCDFDDC950386 +CT=3ABE04FC59C3BDF9D7721902DEFCB439 +PT=3A563A6A047E16123B289B047BB54C4E + +I=393 +KEY=49A10E68A38B02F42A448A458AD3095BE146AB463248C674 +IV=9DB6856C7E01CF3690DE3A2840E34FDD +CT=3A563A6A047E16123B289B047BB54C4E +PT=F8CB54B8D16274E9A20C0F026866E52F + +I=394 +KEY=9DD96DCFD4A1B11FD28FDEFD5BB17DB2434AA4445A2E235B +IV=233C069312D97A03D47863A7772AB3EB +CT=F8CB54B8D16274E9A20C0F026866E52F +PT=0302D25C39BF21F67F1AF2E1951D40F9 + +I=395 +KEY=746E55928D7E549DD18D0CA1620E5C443C5056A5CF3363A2 +IV=B6086C5FEEE9A078E9B7385D59DFE582 +CT=0302D25C39BF21F67F1AF2E1951D40F9 +PT=721192A3A5140DD63D93E0D6ACC4A4B8 + +I=396 +KEY=7E6FC505EAAB07E4A39C9E02C71A519201C3B67363F7C71A +IV=9828A03F0ADCE33E0A01909767D55379 +CT=721192A3A5140DD63D93E0D6ACC4A4B8 +PT=1C0F7440EF41FF18E263392741AD9D8B + +I=397 +KEY=D13AD442CAE026C3BF93EA42285BAE8AE3A08F54225A5A91 +IV=4FC707A846B4469AAF551147204B2127 +CT=1C0F7440EF41FF18E263392741AD9D8B +PT=442F978615AC3983AA5ABEA81AD1ACA6 + +I=398 +KEY=043A4EFFCD44EEB1FBBC7DC43DF7970949FA31FC388BF637 +IV=05D58B4A88A961AFD5009ABD07A4C872 +CT=442F978615AC3983AA5ABEA81AD1ACA6 +PT=E75C29413A33AA1210F36AADEC02FCEE + +I=399 +KEY=81492E2C6296C9341CE0548507C43D1B59095B51D4890AD9 +IV=D89794EAA1791507857360D3AFD22785 +CT=E75C29413A33AA1210F36AADEC02FCEE +PT=6342BFDDD2F6610350458B6695463484 + +========== + +KEYSIZE=256 + +I=0 +KEY=0000000000000000000000000000000000000000000000000000000000000000 +IV=00000000000000000000000000000000 +CT=00000000000000000000000000000000 +PT=4804E1818FE6297519A3E88C57310413 + +I=1 +KEY=098E3797788EA3BCD5477BF1660373944804E1818FE6297519A3E88C57310413 +IV=098E3797788EA3BCD5477BF166037394 +CT=4804E1818FE6297519A3E88C57310413 +PT=D36C27EBB8FA0BC9FA368DF850FD45FB + +I=2 +KEY=D949E143F98BDE24BD40A256F9E369339B68C66A371C22BCE395657407CC41E8 +IV=D0C7D6D481057D986807D9A79FE01AA7 +CT=D36C27EBB8FA0BC9FA368DF850FD45FB +PT=EBCB4DC84155682856D94B442BC597EE + +I=3 +KEY=296352DA0158E197EBC80771EC1ECC7D70A38BA276494A94B54C2E302C09D606 +IV=F02AB399F8D33FB35688A52715FDA54E +CT=EBCB4DC84155682856D94B442BC597EE +PT=23AA6A6B4BE8C04E19707CA330804C4E + +I=4 +KEY=5D3E9E2EA4DEDDB65A58DADB5B9679BC5309E1C93DA18ADAAC3C52931C899A48 +IV=745DCCF4A5863C21B190DDAAB788B5C1 +CT=23AA6A6B4BE8C04E19707CA330804C4E +PT=9B1AA0F33416484BA68740E821F95CD3 + +I=5 +KEY=E35024184CCA14687DB19E13093D2A31C813413A09B7C2910ABB127B3D70C69B +IV=BE6EBA36E814C9DE27E944C852AB538D +CT=9B1AA0F33416484BA68740E821F95CD3 +PT=8A8C6ADF453CB7A2FC4F3690FF7C6F23 + +I=6 +KEY=FDC6EB83FF93BA06DE2D09CB33F05406429F2BE54C8B7533F6F424EBC20CA9B8 +IV=1E96CF9BB359AE6EA39C97D83ACD7E37 +CT=8A8C6ADF453CB7A2FC4F3690FF7C6F23 +PT=B104182A3D85B857FB342BD06063E989 + +I=7 +KEY=7177668BAC9407FB2835524D58F1311EF39B33CF710ECD640DC00F3BA26F4031 +IV=8CB18D085307BDFDF6185B866B016518 +CT=B104182A3D85B857FB342BD06063E989 +PT=68AD7EB507FAEE8FF54E5B7EB4314208 + +I=8 +KEY=790AE8470B39A60E9F32F4025B2251849B364D7A76F423EBF88E5445165E0239 +IV=087D8ECCA7ADA1F5B707A64F03D3609A +CT=68AD7EB507FAEE8FF54E5B7EB4314208 +PT=99736D55B2730FDBC4FCD9128A3E6F06 + +I=9 +KEY=4EAF05AC15913059B6B0E43EFA7ADC1C0245202FC4872C303C728D579C606D3F +IV=37A5EDEB1EA896572982103CA1588D98 +CT=99736D55B2730FDBC4FCD9128A3E6F06 +PT=DF326CEE98EE253C855D171D93AA9455 + +I=10 +KEY=55EE1CCDBA5A04040F4212DFBF6ABC89DD774CC15C69090CB92F9A4A0FCAF96A +IV=1B411961AFCB345DB9F2F6E145106095 +CT=DF326CEE98EE253C855D171D93AA9455 +PT=B4E41BD5257CD7AF0A6F020BEE5F4067 + +I=11 +KEY=6190A91725B7D4E8DD42F3F3B4E42E14699357147915DEA3B3409841E195B90D +IV=347EB5DA9FEDD0ECD200E12C0B8E929D +CT=B4E41BD5257CD7AF0A6F020BEE5F4067 +PT=3608F41CA4C677E74F48B113D9B336B0 + +I=12 +KEY=0A93E973CCBAC75C9C0AA05502A43E945F9BA308DDD3A944FC08295238268FBD +IV=6B034064E90D13B4414853A6B6401080 +CT=3608F41CA4C677E74F48B113D9B336B0 +PT=FB54DBB9C0C7176C4C9E1E4E6688B570 + +I=13 +KEY=584CCAEDD52F491A935D892AD132F75AA4CF78B11D14BE28B096371C5EAE3ACD +IV=52DF239E19958E460F57297FD396C9CE +CT=FB54DBB9C0C7176C4C9E1E4E6688B570 +PT=F40A6A6AE95E9D163D88AAE9A2D359BC + +I=14 +KEY=0DD784E96CAB96D702DD3972E95317FD50C512DBF44A233E8D1E9DF5FC7D6371 +IV=559B4E04B984DFCD9180B0583861E0A7 +CT=F40A6A6AE95E9D163D88AAE9A2D359BC +PT=0FE04B8BB249E49E24FEB6FFE106121C + +I=15 +KEY=2BC3A4EBD80215F0130EC1F76821BC515F2559504603C7A0A9E02B0A1D7B716D +IV=26142002B4A9832711D3F8858172ABAC +CT=0FE04B8BB249E49E24FEB6FFE106121C +PT=EBA4EF8D541919A0D0947359344D61C9 + +I=16 +KEY=0B5856BE9A78457868F7CF9C9C58EF7AB481B6DD121ADE0079745853293610A4 +IV=209BF255427A50887BF90E6BF479532B +CT=EBA4EF8D541919A0D0947359344D61C9 +PT=06484C36A29BD3CA7CBAB7FBEA47313B + +I=17 +KEY=C004F13C83AA1FD5C2A592D27B47C437B2C9FAEBB0810DCA05CEEFA8C371219F +IV=CB5CA78219D25AADAA525D4EE71F2B4D +CT=06484C36A29BD3CA7CBAB7FBEA47313B +PT=376157B7DB3B027980C5EF0E88B3F9EF + +I=18 +KEY=AD89203CAD17908C4F44F3FD2D61505385A8AD5C6BBA0FB3850B00A64BC2D870 +IV=6D8DD1002EBD8F598DE1612F56269464 +CT=376157B7DB3B027980C5EF0E88B3F9EF +PT=756783C2F0EE73BBD81B908F660AA6F7 + +I=19 +KEY=FBE990A6247EABC0CD5090DF0C566E01F0CF2E9E9B547C085D1090292DC87E87 +IV=5660B09A89693B4C8214632221373E52 +CT=756783C2F0EE73BBD81B908F660AA6F7 +PT=6CC64B773ECDFA9749DB33197F7EA0AB + +I=20 +KEY=FEC46AD20DA3E667B26D79B11A82A40F9C0965E9A599869F14CBA33052B6DE2C +IV=052DFA7429DD4DA77F3DE96E16D4CA0E +CT=6CC64B773ECDFA9749DB33197F7EA0AB +PT=9230E4DCA927E2F8E617A2EBC4F11477 + +I=21 +KEY=F4396B035E4E1BD914877124D1CD4B370E3981350CBE6467F2DC01DB9647CA5B +IV=0AFD01D153EDFDBEA6EA0895CB4FEF38 +CT=9230E4DCA927E2F8E617A2EBC4F11477 +PT=6ACD9F3939A86EE4236A3C060D2F5C3C + +I=22 +KEY=49C90E620094D6A85E75BD886FAFE79264F41E0C35160A83D1B63DDD9B689667 +IV=BDF065615EDACD714AF2CCACBE62ACA5 +CT=6ACD9F3939A86EE4236A3C060D2F5C3C +PT=E5F4F050827F69B60B417063AC1060E4 + +I=23 +KEY=1AED4D36938AB2D5D884EF2F106D2CEF8100EE5CB7696335DAF74DBE3778F683 +IV=53244354931E647D86F152A77FC2CB7D +CT=E5F4F050827F69B60B417063AC1060E4 +PT=5CE4B0B3C32700B6B887E05A88EE0239 + +I=24 +KEY=EF14B937F6E0F19AC8ADBD208DD60EE5DDE45EEF744E63836270ADE4BF96F4BA +IV=F5F9F401656A434F1029520F9DBB220A +CT=5CE4B0B3C32700B6B887E05A88EE0239 +PT=4794284E2BB56A47332E84AD7A2006A2 + +I=25 +KEY=182581A233332DDCD43C25AF9AA3AD7F9A7076A15FFB09C4515E2949C5B6F218 +IV=F7313895C5D3DC461C91988F1775A39A +CT=4794284E2BB56A47332E84AD7A2006A2 +PT=C8AE2CAA7C257508C3AB75BE28D2602F + +I=26 +KEY=ABE7FE236E28332AE7A74A9EA03B97A952DE5A0B23DE7CCC92F55CF7ED649237 +IV=B3C27F815D1B1EF6339B6F313A983AD6 +CT=C8AE2CAA7C257508C3AB75BE28D2602F +PT=A9FD4B9D4833B647FF60F8013C3B5B9D + +I=27 +KEY=08248BDC5F9186DCD65DA6344A10C57EFB2311966BEDCA8B6D95A4F6D15FC9AA +IV=A3C375FF31B9B5F631FAECAAEA2B52D7 +CT=A9FD4B9D4833B647FF60F8013C3B5B9D +PT=C871D7B4C0167DCFDD79AF1DEAC49D4F + +I=28 +KEY=BF29FB1B11AA7DB8742FF06458C384853352C622ABFBB744B0EC0BEB3B9B54E5 +IV=B70D70C74E3BFB64A272565012D341FB +CT=C871D7B4C0167DCFDD79AF1DEAC49D4F +PT=E2DE7BAC726C404FC7BA5099E39409CA + +I=29 +KEY=1810253DDF0CC5ECE2381FB4C2BEEDCCD18CBD8ED997F70B77565B72D80F5D2F +IV=A739DE26CEA6B8549617EFD09A7D6949 +CT=E2DE7BAC726C404FC7BA5099E39409CA +PT=D4A8257110EF7FFE2A1F026B28D7483A + +I=30 +KEY=F343D1EC9AEB200B65DB4AA369F6A47E052498FFC97888F55D495919F0D81515 +IV=EB53F4D145E7E5E787E35517AB4849B2 +CT=D4A8257110EF7FFE2A1F026B28D7483A +PT=9EA25895CFEAEAD224095C4687726D06 + +I=31 +KEY=86A93B0F219E1FFEBC0E4BA0334046AA9B86C06A069262277940055F77AA7813 +IV=75EAEAE3BB753FF5D9D501035AB6E2D4 +CT=9EA25895CFEAEAD224095C4687726D06 +PT=5C5DD66E7AD197DA86844D53C8ACEA0E + +I=32 +KEY=2278C61356CB0A951DAE3B6DC76868C9C7DB16047C43F5FDFFC4480CBF06921D +IV=A4D1FD1C7755156BA1A070CDF4282E63 +CT=5C5DD66E7AD197DA86844D53C8ACEA0E +PT=011959D35C8FE620E1C49D1804912F26 + +I=33 +KEY=E1972A31ACF850A22CBC592AF6CAF6F0C6C24FD720CC13DD1E00D514BB97BD3B +IV=C3EFEC22FA335A373112624731A29E39 +CT=011959D35C8FE620E1C49D1804912F26 +PT=895DDA7BB43DC3060B41DA70CAE4D2ED + +I=34 +KEY=BB4A76B5E8FD3820CC5D4A44F527E6704F9F95AC94F1D0DB15410F6471736FD6 +IV=5ADD5C8444056882E0E1136E03ED1080 +CT=895DDA7BB43DC3060B41DA70CAE4D2ED +PT=94E8BBC942B4127A0A8EBEC59319CF57 + +I=35 +KEY=4D98C60F0FA316B2DA3D11CFB3B9FE0CDB772E65D645C2A11FCFB1A1E26AA081 +IV=F6D2B0BAE75E2E9216605B8B469E187C +CT=94E8BBC942B4127A0A8EBEC59319CF57 +PT=274FE85E229321D4A6B2E9D4F0D3830F + +I=36 +KEY=A9FC5AC4A7B3550BC34E4BA94C0D328BFC38C63BF4D6E375B97D587512B9238E +IV=E4649CCBA81043B919735A66FFB4CC87 +CT=274FE85E229321D4A6B2E9D4F0D3830F +PT=256AC08E72D79B0CB7457B26769AC226 + +I=37 +KEY=1C44DEF03398188AC1B2EF6A6E91A33FD95206B5860178790E3823536423E1A8 +IV=B5B88434942B4D8102FCA4C3229C91B4 +CT=256AC08E72D79B0CB7457B26769AC226 +PT=366D17A14CA0FC192DBB731C1C305874 + +I=38 +KEY=3D80B92C01F9721032366B20D97DC097EF3F1114CAA184602383504F7813B9DC +IV=21C467DC32616A9AF384844AB7EC63A8 +CT=366D17A14CA0FC192DBB731C1C305874 +PT=000B4A6054663874ECAE310144BA9377 + +I=39 +KEY=48DD38DC16A4CE76338C95A866C1C795EF345B749EC7BC14CF2D614E3CA92AAB +IV=755D81F0175DBC6601BAFE88BFBC0702 +CT=000B4A6054663874ECAE310144BA9377 +PT=32B32D65566626D794FB296CA816B0A8 + +I=40 +KEY=C62EFA02F23FE796799BF9151FBFD8D7DD877611C8A19AC35BD6482294BF9A03 +IV=8EF3C2DEE49B29E04A176CBD797E1F42 +CT=32B32D65566626D794FB296CA816B0A8 +PT=D743A090101B1BAF5B83E8C06517E193 + +I=41 +KEY=91400A96EEADA906ABD4C3F6863CE4750AC4D681D8BA816C0055A0E2F1A87B90 +IV=576EF0941C924E90D24F3AE399833CA2 +CT=D743A090101B1BAF5B83E8C06517E193 +PT=2DE61760BEE8F811B3FEB44D2C566DB0 + +I=42 +KEY=9983EAD4BF987E39644D7D0963F93DB62722C1E16652797DB3AB14AFDDFE1620 +IV=08C3E0425135D73FCF99BEFFE5C5D9C3 +CT=2DE61760BEE8F811B3FEB44D2C566DB0 +PT=E97598EFFED4128DCCCDD7A04D8405E1 + +I=43 +KEY=B72929D2D02A00D36E7C3BD11CDB9FA4CE57590E98866BF07F66C30F907A13C1 +IV=2EAAC3066FB27EEA0A3146D87F22A212 +CT=E97598EFFED4128DCCCDD7A04D8405E1 +PT=5983276B92B95898302385F5156B6201 + +I=44 +KEY=CC9928E45F7885515986E0D431F3288E97D47E650A3F33684F4546FA851171C0 +IV=7BB001368F52858237FADB052D28B72A +CT=5983276B92B95898302385F5156B6201 +PT=ABDEFF06E04995FD2C5472D05056A0A3 + +I=45 +KEY=59A2D8FCED30176B73FF5642BCE4A9163C0A8163EA76A6956311342AD547D163 +IV=953BF018B248923A2A79B6968D178198 +CT=ABDEFF06E04995FD2C5472D05056A0A3 +PT=E4210D117B05F3EADC8AF75D1A80B823 + +I=46 +KEY=FFCCE373B679DE040165054D9EECA460D82B8C729173557FBF9BC377CFC76940 +IV=A66E3B8F5B49C96F729A530F22080D76 +CT=E4210D117B05F3EADC8AF75D1A80B823 +PT=4786111E1B0F2CA78E43CC0D154BC1EA + +I=47 +KEY=36E29D3C942DBC6A12B53088632260649FAD9D6C8A7C79D831D80F7ADA8CA8AA +IV=C92E7E4F2254626E13D035C5FDCEC404 +CT=4786111E1B0F2CA78E43CC0D154BC1EA +PT=122DC3B40007BA36BC7E7EE808911DAE + +I=48 +KEY=3692660415E53226D2758E60FD6E3F5F8D805ED88A7BC3EE8DA67192D21DB504 +IV=0070FB3881C88E4CC0C0BEE89E4C5F3B +CT=122DC3B40007BA36BC7E7EE808911DAE +PT=5E443EC882C1B938C2A4C412D3A92FDF + +I=49 +KEY=E3C167B38A29EDFBDC37A50F434C7056D3C4601008BA7AD64F02B58001B49ADB +IV=D55301B79FCCDFDD0E422B6FBE224F09 +CT=5E443EC882C1B938C2A4C412D3A92FDF +PT=14A8F43BA8829B134D6BD110E6D43F92 + +I=50 +KEY=8AD38A575E425D347C5B5BFB08A5173CC76C942BA038E1C502696490E760A549 +IV=6912EDE4D46BB0CFA06CFEF44BE9676A +CT=14A8F43BA8829B134D6BD110E6D43F92 +PT=025982911796C2FE34C89157BF2959BD + +I=51 +KEY=AE4ABA37DD2C3C5109B13C3DD9FCB67EC53516BAB7AE233B36A1F5C75849FCF4 +IV=24993060836E616575EA67C6D159A142 +CT=025982911796C2FE34C89157BF2959BD +PT=BC658642A8EEBEC6DBE2A76BCD70799B + +I=52 +KEY=31AC934C58BF87AD1EE4357BBE315175795090F81F409DFDED4352AC9539856F +IV=9FE6297B8593BBFC1755094667CDE70B +CT=BC658642A8EEBEC6DBE2A76BCD70799B +PT=132CE1CC36EFE58A4A53534B962D2D70 + +I=53 +KEY=79F7C18CA600203D404363908749B22F6A7C713429AF7877A71001E70314A81F +IV=485B52C0FEBFA7905EA756EB3978E35A +CT=132CE1CC36EFE58A4A53534B962D2D70 +PT=8D2BA39F08ED00BEB51543C0FCCFA57C + +I=54 +KEY=162A4089A1E46EAB5C9592BF1F98BCC2E757D2AB214278C912054227FFDB0D63 +IV=6FDD810507E44E961CD6F12F98D10EED +CT=8D2BA39F08ED00BEB51543C0FCCFA57C +PT=2E8D05A8A3066094025FE07F3A53A94E + +I=55 +KEY=DB5F33F93F2B795EDA54095937B79E4CC9DAD7038244185D105AA258C588A42D +IV=CD7573709ECF17F586C19BE6282F228E +CT=2E8D05A8A3066094025FE07F3A53A94E +PT=D39EC2261C53AD45F91627E1B1F62D22 + +I=56 +KEY=CCA770427DF8CF5350864D4E86E6D8891A4415259E17B518E94C85B9747E890F +IV=17F843BB42D3B60D8AD24417B15146C5 +CT=D39EC2261C53AD45F91627E1B1F62D22 +PT=F517DC01890C3D300520B6CE343B7F94 + +I=57 +KEY=25F53E7CC6590220E9426296568DE496EF53C924171B8828EC6C33774045F69B +IV=E9524E3EBBA1CD73B9C42FD8D06B3C1F +CT=F517DC01890C3D300520B6CE343B7F94 +PT=ECBCCBB21AC2D07E3ECACD26D42E4444 + +I=58 +KEY=6D4A92C82C6C3D44CED65D76BB33B23E03EF02960DD95856D2A6FE51946BB2DF +IV=48BFACB4EA353F6427943FE0EDBE56A8 +CT=ECBCCBB21AC2D07E3ECACD26D42E4444 +PT=6FF7C241A5FF025FAA8C4DAF5E0950AE + +I=59 +KEY=A3D0AB0A0F8EDF232D111458D3B8B1C66C18C0D7A8265A09782AB3FECA62E271 +IV=CE9A39C223E2E267E3C7492E688B03F8 +CT=6FF7C241A5FF025FAA8C4DAF5E0950AE +PT=3B7E4B74F021F9E995627DE42B03D7D8 + +I=60 +KEY=A8E2D59CF188CDA75C80FA49889F7EE357668BA35807A3E0ED48CE1AE16135A9 +IV=0B327E96FE0612847191EE115B27CF25 +CT=3B7E4B74F021F9E995627DE42B03D7D8 +PT=6759C15ED1049A51953E814C2445F3C6 + +I=61 +KEY=092010B28BD3C8E59D09CE85169190BB303F4AFD890339B178764F56C524C66F +IV=A1C2C52E7A5B0542C18934CC9E0EEE58 +CT=6759C15ED1049A51953E814C2445F3C6 +PT=05F681CB7984491E2CE5B1025F860BEB + +I=62 +KEY=538E3068E1059FE89C27D5F19405274835C9CB36F08770AF5493FE549AA2CD84 +IV=5AAE20DA6AD6570D012E1B748294B7F3 +CT=05F681CB7984491E2CE5B1025F860BEB +PT=E046F5B143CEEAC44EF520F2C3BFA96E + +I=63 +KEY=78B5D2551099875910844A17ABBACD64D58F3E87B3499A6B1A66DEA6591D64EA +IV=2B3BE23DF19C18B18CA39FE63FBFEA2C +CT=E046F5B143CEEAC44EF520F2C3BFA96E +PT=0F508DD1BCC6C520A81AE7EC75361179 + +I=64 +KEY=8D6E7E66F496C358A369EF7C49D117A3DADFB3560F8F5F4BB27C394A2C2B7593 +IV=F5DBAC33E40F4401B3EDA56BE26BDAC7 +CT=0F508DD1BCC6C520A81AE7EC75361179 +PT=BAE114FFF19FD11336D454BF0FF6954D + +I=65 +KEY=781164DD6F90037E9896672FD24F1AF6603EA7A9FE108E5884A86DF523DDE0DE +IV=F57F1ABB9B06C0263BFF88539B9E0D55 +CT=BAE114FFF19FD11336D454BF0FF6954D +PT=FE73CE62C227459729E8FDC9116EC6BB + +I=66 +KEY=9268D6C0E8DE5AFBCCE137EADE6293E49E4D69CB3C37CBCFAD40903C32B32665 +IV=EA79B21D874E5985547750C50C2D8912 +CT=FE73CE62C227459729E8FDC9116EC6BB +PT=B13971219C12C12A8308213759196B0D + +I=67 +KEY=701EB5AEF8262D8634B53AF1768ED68E2F7418EAA0250AE52E48B10B6BAA4D68 +IV=E276636E10F8777DF8540D1BA8EC456A +CT=B13971219C12C12A8308213759196B0D +PT=4F5A36173C16ED45F5D36B9D1AED84FF + +I=68 +KEY=40D027792516E1FE962F63B9C939677C602E2EFD9C33E7A0DB9BDA967147C997 +IV=30CE92D7DD30CC78A29A5948BFB7B1F2 +CT=4F5A36173C16ED45F5D36B9D1AED84FF +PT=9FB89D6FEFE606058FE40B5492643596 + +I=69 +KEY=CAAFC0DD2E4FC86AC19B40BC34F14630FF96B39273D5E1A5547FD1C2E323FC01 +IV=8A7FE7A40B59299457B42305FDC8214C +CT=9FB89D6FEFE606058FE40B5492643596 +PT=F6D0717F197CBAE383B55117FCBE07AC + +I=70 +KEY=CE03D67B6DAB9CFAA0C20129475620230946C2ED6AA95B46D7CA80D51F9DFBAD +IV=04AC16A643E454906159419573A76613 +CT=F6D0717F197CBAE383B55117FCBE07AC +PT=7747114FF82F8C7568BE51912CFDB51A + +I=71 +KEY=DDCEDD32E5F0D26F7707DAE453288B537E01D3A29286D733BF74D14433604EB7 +IV=13CD0B49885B4E95D7C5DBCD147EAB70 +CT=7747114FF82F8C7568BE51912CFDB51A +PT=E75313A8DFA7EB0AD1664B14D2DBE284 + +I=72 +KEY=6B032958C3379BD4BEC22CD4271EB4589952C00A4D213C396E129A50E1BBAC33 +IV=B6CDF46A26C749BBC9C5F63074363F0B +CT=E75313A8DFA7EB0AD1664B14D2DBE284 +PT=42FEDBDC4F0BD11DA42163D76E952DC7 + +I=73 +KEY=1710F6CF86EDB5F1364F19CA676ED69BDBAC1BD6022AED24CA33F9878F2E81F4 +IV=7C13DF9745DA2E25888D351E407062C3 +CT=42FEDBDC4F0BD11DA42163D76E952DC7 +PT=6E0166BA404B3AEFACCA8E972F087EA5 + +I=74 +KEY=9D9711F138D0C2D1003E2C99BB0F0447B5AD7D6C4261D7CB66F97710A026FF51 +IV=8A87E73EBE3D772036713553DC61D2DC +CT=6E0166BA404B3AEFACCA8E972F087EA5 +PT=644A1DCFCA2EC01C3E8911768837D99E + +I=75 +KEY=1BD7E446FADA5507ECE26BBB635045E7D1E760A3884F17D758706666281126CF +IV=8640F5B7C20A97D6ECDC4722D85F41A0 +CT=644A1DCFCA2EC01C3E8911768837D99E +PT=4E69AE75BD37DB8024DBD1A11D6D414E + +I=76 +KEY=3454FD4B259FB4C086288ADAFF6464CD9F8ECED63578CC577CABB7C7357C6781 +IV=2F83190DDF45E1C76ACAE1619C34212A +CT=4E69AE75BD37DB8024DBD1A11D6D414E +PT=F63964784AD35374EAFC933AC11A48B6 + +I=77 +KEY=97EFD593918FB16F2D6889C118C5ED4469B7AAAE7FAB9F23965724FDF4662F37 +IV=A3BB28D8B41005AFAB40031BE7A18989 +CT=F63964784AD35374EAFC933AC11A48B6 +PT=51CBF7F67A22DA909567D67F1919ECEF + +I=78 +KEY=481E90BC31903905C08D0E5AEF79A514387C5D58058945B30330F282ED7FC3D8 +IV=DFF1452FA01F886AEDE5879BF7BC4850 +CT=51CBF7F67A22DA909567D67F1919ECEF +PT=9AE181DE8DB65E7E242926091A17D0B1 + +I=79 +KEY=35A4F86146CED63BDCB485B0AE4C205AA29DDC86883F1BCD2719D48BF7681369 +IV=7DBA68DD775EEF3E1C398BEA4135854E +CT=9AE181DE8DB65E7E242926091A17D0B1 +PT=47E15B5AC96A7FDB805F3B8862D9055F + +I=80 +KEY=5ECF20C5884FDF95C2B7C17D40CD6923E57C87DC41556416A746EF0395B11636 +IV=6B6BD8A4CE8109AE1E0344CDEE814979 +CT=47E15B5AC96A7FDB805F3B8862D9055F +PT=1806C474A1ECE5D8183E725804FB92C3 + +I=81 +KEY=AC473047ADF97E75C100CBBD73FA0892FD7A43A8E0B981CEBF789D5B914A84F5 +IV=F288108225B6A1E003B70AC0333761B1 +CT=1806C474A1ECE5D8183E725804FB92C3 +PT=0A0615424DAD4EFC25EC43B13C672727 + +I=82 +KEY=6620AE39484EDD0EC21A3E3F659537DDF77C56EAAD14CF329A94DEEAAD2DA3D2 +IV=CA679E7EE5B7A37B031AF582166F3F4F +CT=0A0615424DAD4EFC25EC43B13C672727 +PT=551639A520D0D043CAD42CB02900D5EF + +I=83 +KEY=04D696BB056CC59492B376CB3A0286EAA26A6F4F8DC41F715040F25A842D763D +IV=62F638824D22189A50A948F45F97B137 +CT=551639A520D0D043CAD42CB02900D5EF +PT=DF906B0E72FEACC9B45381B992E23A5A + +I=84 +KEY=0AED1F2A6660BDBA660E00137E38C1C97DFA0441FF3AB3B8E41373E316CF4C67 +IV=0E3B8991630C782EF4BD76D8443A4723 +CT=DF906B0E72FEACC9B45381B992E23A5A +PT=D477C6287D05C0F83B27B1FD91F5F908 + +I=85 +KEY=E0A51B848A913A860FD2C39941C8C3A1A98DC269823F7340DF34C21E873AB56F +IV=EA4804AEECF1873C69DCC38A3FF00268 +CT=D477C6287D05C0F83B27B1FD91F5F908 +PT=6AB7E109C085B0BA7C8A8B76482F9C80 + +I=86 +KEY=A8B0500EC0292EF668A03E8293E235BAC33A236042BAC3FAA3BE4968CF1529EF +IV=48154B8A4AB814706772FD1BD22AF61B +CT=6AB7E109C085B0BA7C8A8B76482F9C80 +PT=71A31000A5763A0C79B6353E39FFBE84 + +I=87 +KEY=34C53C34901B693F4611F20F1DD5125EB2993360E7CCF9F6DA087C56F6EA976B +IV=9C756C3A503247C92EB1CC8D8E3727E4 +CT=71A31000A5763A0C79B6353E39FFBE84 +PT=B5B377EBEBC0B32A5A0C7E2A2504C32A + +I=88 +KEY=A13850B9164EF60EB77E06819605AC01072A448B0C0C4ADC8004027CD3EE5441 +IV=95FD6C8D86559F31F16FF48E8BD0BE5F +CT=B5B377EBEBC0B32A5A0C7E2A2504C32A +PT=B74459D1E7C5CF9106C362572FE9C917 + +I=89 +KEY=37261F6D588FF9028A23319CE02DDA71B06E1D5AEBC9854D86C7602BFC079D56 +IV=961E4FD44EC10F0C3D5D371D76287670 +CT=B74459D1E7C5CF9106C362572FE9C917 +PT=5777A0854A6E00DB0B6B199BDD35447A + +I=90 +KEY=085A7B276E58B9175204A87D74B9E78AE719BDDFA1A785968DAC79B02132D92C +IV=3F7C644A36D74015D82799E194943DFB +CT=5777A0854A6E00DB0B6B199BDD35447A +PT=01CC73B6EE44403DFED2C91D6F0DC441 + +I=91 +KEY=61DC99DD0C1470F511D79DCC2541002AE6D5CE694FE3C5AB737EB0AD4E3F1D6D +IV=6986E2FA624CC9E243D335B151F8E7A0 +CT=01CC73B6EE44403DFED2C91D6F0DC441 +PT=8993161CF3E75DE836BB2C1955581DB6 + +I=92 +KEY=AEB68207F1E4395794BA7E28CE9BF7996F46D875BC04984345C59CB41B6700DB +IV=CF6A1BDAFDF049A2856DE3E4EBDAF7B3 +CT=8993161CF3E75DE836BB2C1955581DB6 +PT=2A4D6929ED3A66E71EFC40F1840CD649 + +I=93 +KEY=DBF8A8AED7B6D7BCFD1B5BEEC3F01AC0450BB15C513EFEA45B39DC459F6BD692 +IV=754E2AA92652EEEB69A125C60D6BED59 +CT=2A4D6929ED3A66E71EFC40F1840CD649 +PT=596CE09B1176A9FB5A9973086A0E4C12 + +I=94 +KEY=1A61C7F2FB652E256190C0896F800CD61C6751C74048575F01A0AF4DF5659A80 +IV=C1996F5C2CD3F9999C8B9B67AC701616 +CT=596CE09B1176A9FB5A9973086A0E4C12 +PT=B57AC41360C13F6831689C311BD0ED2C + +I=95 +KEY=FC3828E6A9487698231D11C10C353F2DA91D95D42089683730C8337CEEB577AC +IV=E659EF14522D58BD428DD14863B533FB +CT=B57AC41360C13F6831689C311BD0ED2C +PT=F58AA69EEBF25943C728FA26524DE154 + +I=96 +KEY=9D16CAD42D19D1A3B9CB12566745B2765C97334ACB7B3174F7E0C95ABCF896F8 +IV=612EE2328451A73B9AD603976B708D5B +CT=F58AA69EEBF25943C728FA26524DE154 +PT=4A678FED6C5E5898A47F2DFE9DF71DF2 + +I=97 +KEY=D9A8554717435E69EFD4A617CA70B0D216F0BCA7A72569EC539FE4A4210F8B0A +IV=44BE9F933A5A8FCA561FB441AD3502A4 +CT=4A678FED6C5E5898A47F2DFE9DF71DF2 +PT=38011537A04E6C4A81510899741F2FFC + +I=98 +KEY=AA9D9A7B4E187F8D78AAEE11967A20A42EF1A990076B05A6D2CEEC3D5510A4F6 +IV=7335CF3C595B21E4977E48065C0A9076 +CT=38011537A04E6C4A81510899741F2FFC +PT=6472060F536BC5F83A3C247F63C3580E + +I=99 +KEY=90A5D8CD93F0AE068E8DC72CA5DD6E184A83AF9F5400C05EE8F2C84236D3FCF8 +IV=3A3842B6DDE8D18BF627293D33A74EBC +CT=6472060F536BC5F83A3C247F63C3580E +PT=08B99B59D0584DAC0412796871FE3F27 + +I=100 +KEY=489520777A18D5BF65B85AAEA29DB3D8423A34C684588DF2ECE0B12A472DC3DF +IV=D830F8BAE9E87BB9EB359D820740DDC0 +CT=08B99B59D0584DAC0412796871FE3F27 +PT=E8B8579DF9E918B3D24C18E17068AD66 + +I=101 +KEY=69542EE000ACEEFB5E0EB471F3CD0927AA82635B7DB195413EACA9CB37456EB9 +IV=21C10E977AB43B443BB6EEDF5150BAFF +CT=E8B8579DF9E918B3D24C18E17068AD66 +PT=9B6C3234993F6900B3E572B5A43CA644 + +I=102 +KEY=E88C863186548F35DF6EFB48743B7C1831EE516FE48EFC418D49DB7E9379C8FD +IV=81D8A8D186F861CE81604F3987F6753F +CT=9B6C3234993F6900B3E572B5A43CA644 +PT=E0A2962A02698489813292D33D02D0AB + +I=103 +KEY=C9DD7904D060B79B83F97A1FC93E50DED14CC745E6E778C80C7B49ADAE7B1856 +IV=2151FF35563438AE5C978157BD052CC6 +CT=E0A2962A02698489813292D33D02D0AB +PT=10C80B22D8EC54B855E103D6B76C03BC + +I=104 +KEY=D208B7A87003A507561FA5C7422A85C5C184CC673E0B2C70599A4A7B19171BEA +IV=1BD5CEACA063129CD5E6DFD88B14D51B +CT=10C80B22D8EC54B855E103D6B76C03BC +PT=CE88B76CC2223EB68BA9B5852C1921DB + +I=105 +KEY=27B0E1BF8EA57E8AD51BC3FA278369780F0C7B0BFC2912C6D233FFFE350E3A31 +IV=F5B85617FEA6DB8D8304663D65A9ECBD +CT=CE88B76CC2223EB68BA9B5852C1921DB +PT=00401EEE034A193C86A23152AF4B767E + +I=106 +KEY=45E37A710D9E754EE90B7C1DBB894DC20F4C65E5FF630BFA5491CEAC9A454C4F +IV=62539BCE833B0BC43C10BFE79C0A24BA +CT=00401EEE034A193C86A23152AF4B767E +PT=CEF1DC8A618BF71C68720E6EEDE31EEF + +I=107 +KEY=B432E78F49D50B045C8B598EEA3D4142C1BDB96F9EE8FCE63CE3C0C277A652A0 +IV=F1D19DFE444B7E4AB580259351B40C80 +CT=CEF1DC8A618BF71C68720E6EEDE31EEF +PT=EF8FB3790627F31E5CBF21B31FF942DE + +I=108 +KEY=F5CE9C0AF13DA60D32912620673AEE572E320A1698CF0FF8605CE171685F107E +IV=41FC7B85B8E8AD096E1A7FAE8D07AF15 +CT=EF8FB3790627F31E5CBF21B31FF942DE +PT=2EF1C697D948D712AA177855B0D56650 + +I=109 +KEY=DA14D71084F47D87385EF58128C7517F00C3CC814187D8EACA4B9924D88A762E +IV=2FDA4B1A75C9DB8A0ACFD3A14FFDBF28 +CT=2EF1C697D948D712AA177855B0D56650 +PT=0A20E82375680D134FE05AC74E3A0217 + +I=110 +KEY=B68F8C980984E2508E9706117256A4A70AE324A234EFD5F985ABC3E396B07439 +IV=6C9B5B888D709FD7B6C9F3905A91F5D8 +CT=0A20E82375680D134FE05AC74E3A0217 +PT=46AF886AB871A3DABDEB32F1738E180B + +I=111 +KEY=078A8955ECB2F6ACB249E2DB36B660794C4CACC88C9E76233840F112E53E6C32 +IV=B10505CDE53614FC3CDEE4CA44E0C4DE +CT=46AF886AB871A3DABDEB32F1738E180B +PT=79949181E3D20A3042C1E7BDAE73330B + +I=112 +KEY=7CB2A8360EE65417A979D9B5D4A32D2935D83D496F4C7C137A8116AF4B4D5F39 +IV=7B382163E254A2BB1B303B6EE2154D50 +CT=79949181E3D20A3042C1E7BDAE73330B +PT=12C5E55F6EA47BC44392AE9FB888C1FB + +I=113 +KEY=E5835F97C4FF1B007D695DD0E72324A9271DD81601E807D73913B830F3C59EC2 +IV=9931F7A1CA194F17D410846533800980 +CT=12C5E55F6EA47BC44392AE9FB888C1FB +PT=FCA15AB64A01FA6E89FE41F72A67D9E8 + +I=114 +KEY=50932FF04CCCE411AA0541726C1C4CD7DBBC82A04BE9FDB9B0EDF9C7D9A2472A +IV=B51070678833FF11D76C1CA28B3F687E +CT=FCA15AB64A01FA6E89FE41F72A67D9E8 +PT=7B75EC39F707C3C90691BE561AD5CAC6 + +I=115 +KEY=ECAEC5FD6AF5F7DF2587C1A40CB046ADA0C96E99BCEE3E70B67C4791C3778DEC +IV=BC3DEA0D263913CE8F8280D660AC0A7A +CT=7B75EC39F707C3C90691BE561AD5CAC6 +PT=1D3D15FFA0B69EFA8E146301411DFA49 + +I=116 +KEY=82F88C3850CC3D111C2125F34840A9A2BDF47B661C58A08A38682490826A77A5 +IV=6E5649C53A39CACE39A6E45744F0EF0F +CT=1D3D15FFA0B69EFA8E146301411DFA49 +PT=34AFB3D6F0BD9ACB6954BB96B1067F9E + +I=117 +KEY=702FEC9E7F0D2369FF35D4B7A1269AD3895BC8B0ECE53A41513C9F06336C083B +IV=F2D760A62FC11E78E314F144E9663371 +CT=34AFB3D6F0BD9ACB6954BB96B1067F9E +PT=899E4C8192661CCA7C73CDFBC3DCA2F3 + +I=118 +KEY=A1DF98E4585C1A4C15C42AD0782C925000C584317E83268B2D4F52FDF0B0AAC8 +IV=D1F0747A27513925EAF1FE67D90A0883 +CT=899E4C8192661CCA7C73CDFBC3DCA2F3 +PT=3097C0413291E217FB0E3A8A2D908C12 + +I=119 +KEY=9F9082177BF33D8AF6131018E1EFD49F305244704C12C49CD6416877DD2026DA +IV=3E4F1AF323AF27C6E3D73AC899C346CF +CT=3097C0413291E217FB0E3A8A2D908C12 +PT=6C71968295905F881F95DC8BA481CA72 + +I=120 +KEY=B7E5B267EDBFFD4DB4526BA2A1978C105C23D2F2D9829B14C9D4B4FC79A1ECA8 +IV=28753070964CC0C742417BBA4078588F +CT=6C71968295905F881F95DC8BA481CA72 +PT=96D0AB98DBD0CB94A68FC41BEF0B418D + +I=121 +KEY=127FAA6C94663FA9008A1FB7A419C036CAF3796A025250806F5B70E796AAAD25 +IV=A59A180B79D9C2E4B4D87415058E4C26 +CT=96D0AB98DBD0CB94A68FC41BEF0B418D +PT=9E3E4428A911FB328A9F89D7D5E527DB + +I=122 +KEY=1B9493F07E7E5F07473E6997AE15CCDC54CD3D42AB43ABB2E5C4F930434F8AFE +IV=09EB399CEA1860AE47B476200A0C0CEA +CT=9E3E4428A911FB328A9F89D7D5E527DB +PT=0DB5EF3481A9945BAF2E499B5CDE8DDC + +I=123 +KEY=7B2B8201EEF1601C44006A6D7E06EE355978D2762AEA3FE94AEAB0AB1F910722 +IV=60BF11F1908F3F1B033E03FAD01322E9 +CT=0DB5EF3481A9945BAF2E499B5CDE8DDC +PT=C0569DD7DCAE99859D3987B04FFD8CF0 + +I=124 +KEY=B2D7FEE25A564FA00CEDC8E05BAC7F7D992E4FA1F644A66CD7D3371B506C8BD2 +IV=C9FC7CE3B4A72FBC48EDA28D25AA9148 +CT=C0569DD7DCAE99859D3987B04FFD8CF0 +PT=D8AF74B5BB8E632299D32E8DD4DDA012 + +I=125 +KEY=5A06C176A290538BC549CAA8041539A941813B144DCAC54E4E00199684B12BC0 +IV=E8D13F94F8C61C2BC9A402485FB946D4 +CT=D8AF74B5BB8E632299D32E8DD4DDA012 +PT=0821FB911EDE8CDCD97DDAEDCCDB7B1C + +I=126 +KEY=1318D23A3A966D16FDEEE300571F3A8549A0C08553144992977DC37B486A50DC +IV=491E134C98063E9D38A729A8530A032C +CT=0821FB911EDE8CDCD97DDAEDCCDB7B1C +PT=BCB2831AF3721C020FC1D683C19AEBEA + +I=127 +KEY=D6D24AA79B3CA4434CCE2B1470B4FE18F512439FA066559098BC15F889F0BB36 +IV=C5CA989DA1AAC955B120C81427ABC49D +CT=BCB2831AF3721C020FC1D683C19AEBEA +PT=BE869BB3C18EB622CCAC81B6F5B62CC4 + +I=128 +KEY=5F62348BCD9ADB23A19E683400D968404B94D82C61E8E3B25410944E7C4697F2 +IV=89B07E2C56A67F60ED504320706D9658 +CT=BE869BB3C18EB622CCAC81B6F5B62CC4 +PT=C8D3EDD549FEA614B4F2348F82DE5531 + +I=129 +KEY=A64795E417B7C9344185F6B0C66C096B834735F9281645A6E0E2A0C1FE98C2C3 +IV=F925A16FDA2D1217E01B9E84C6B5612B +CT=C8D3EDD549FEA614B4F2348F82DE5531 +PT=4049BDBD9C302D8F2E06F10D34317784 + +I=130 +KEY=CD1F9AB35436014B0CF7ECE9FF98C2BDC30E8844B4266829CEE451CCCAA9B547 +IV=6B580F574381C87F4D721A5939F4CBD6 +CT=4049BDBD9C302D8F2E06F10D34317784 +PT=E1338EA5C5462E8C458E5546FA60324D + +I=131 +KEY=78F7558C14BB5100CE93CD49C22BE2D9223D06E1716046A58B6A048A30C9870A +IV=B5E8CF3F408D504BC26421A03DB32064 +CT=E1338EA5C5462E8C458E5546FA60324D +PT=055984AA929F4D45F5812DC719D4EF24 + +I=132 +KEY=2DBC5092C4C7AB427576EBA2855E00562764824BE3FF0BE07EEB294D291D682E +IV=554B051ED07CFA42BBE526EB4775E28F +CT=055984AA929F4D45F5812DC719D4EF24 +PT=ABC519C4290C69D98BF7AC2A56767202 + +I=133 +KEY=68FA1D8FE36FC5B48A7486FBB34A7B598CA19B8FCAF36239F51C85677F6B1A2C +IV=45464D1D27A86EF6FF026D5936147B0F +CT=ABC519C4290C69D98BF7AC2A56767202 +PT=C825E44799B1739A1F4CB406BBEABEDD + +I=134 +KEY=A2302849850FD33D4048B898DB6C7B0244847FC8534211A3EA503161C481A4F1 +IV=CACA35C666601689CA3C3E636826005B +CT=C825E44799B1739A1F4CB406BBEABEDD +PT=D24EE8D56CE09AFE1061B4016ADD61F7 + +I=135 +KEY=9B2E669EA4BB938072E6E97B0ACF834E96CA971D3FA28B5DFA318560AE5CC506 +IV=391E4ED721B440BD32AE51E3D1A3F84C +CT=D24EE8D56CE09AFE1061B4016ADD61F7 +PT=50FECB118EABF93BB97102E9212C883D + +I=136 +KEY=A07C5EBAC9D0F862AD525C76460B4BA9C6345C0CB1097266434087898F704D3B +IV=3B5238246D6B6BE2DFB4B50D4CC4C8E7 +CT=50FECB118EABF93BB97102E9212C883D +PT=C370C26BD3805211A4679399DFA4DDCB + +I=137 +KEY=414C776222058D6285574741B2B4D11D05449E6762892077E727141050D490F0 +IV=E13029D8EBD5750028051B37F4BF9AB4 +CT=C370C26BD3805211A4679399DFA4DDCB +PT=79715A04DF9216268C77A152CA96C2F6 + +I=138 +KEY=5E54A416470FE8BA263C0FC88FD884297C35C463BD1B36516B50B5429A425206 +IV=1F18D374650A65D8A36B48893D6C5534 +CT=79715A04DF9216268C77A152CA96C2F6 +PT=06DF18B5FAF35F03FE22E39CAE430655 + +I=139 +KEY=98C55CFFB53FA72345EF936283F64BB17AEADCD647E86952957256DE34015453 +IV=C691F8E9F2304F9963D39CAA0C2ECF98 +CT=06DF18B5FAF35F03FE22E39CAE430655 +PT=1AED42EB32C4BAEAF9946818AA00C324 + +I=140 +KEY=B8332B1EE5D6A4E1BBFA20AEAE22330560079E3D752CD3B86CE63EC69E019777 +IV=20F677E150E903C2FE15B3CC2DD478B4 +CT=1AED42EB32C4BAEAF9946818AA00C324 +PT=D276B6A6D480165A944572EF76D4B3E8 + +I=141 +KEY=6E50753A2A0814A778FA2BC773C6A7A2B271289BA1ACC5E2F8A34C29E8D5249F +IV=D6635E24CFDEB046C3000B69DDE494A7 +CT=D276B6A6D480165A944572EF76D4B3E8 +PT=BA46F59DFADC6CA2CBB7D80E33D7B24B + +I=142 +KEY=D8E1763EAD728AB8AA2284964BE586880837DD065B70A94033149427DB0296D4 +IV=B6B10304877A9E1FD2D8AF513823212A +CT=BA46F59DFADC6CA2CBB7D80E33D7B24B +PT=FC9B9F7B5120E1D8B2DD58D211EFF053 + +I=143 +KEY=458CB146C73342F9D5EE4364C400E8E5F4AC427D0A50489881C9CCF5CAED6687 +IV=9D6DC7786A41C8417FCCC7F28FE56E6D +CT=FC9B9F7B5120E1D8B2DD58D211EFF053 +PT=6AD8BCAEFF6F0BF9F360FF601C9B7A43 + +I=144 +KEY=F1FBE00DA1F634ACACB6E2F4F15C11179E74FED3F53F436172A93395D6761CC4 +IV=B477514B66C576557958A190355CF9F2 +CT=6AD8BCAEFF6F0BF9F360FF601C9B7A43 +PT=BB6E45D060E186323AC2B50CFB988856 + +I=145 +KEY=3FBC35054FFF43657936BB676A5C5D1F251ABB0395DEC553486B86992DEE9492 +IV=CE47D508EE0977C9D58059939B004C08 +CT=BB6E45D060E186323AC2B50CFB988856 +PT=31B6157397933EE35DEE5B40FE7237BB + +I=146 +KEY=D49B4E96F8FC2D91FBED3985C53BEB8314ACAE70024DFBB01585DDD9D39CA329 +IV=EB277B93B7036EF482DB82E2AF67B69C +CT=31B6157397933EE35DEE5B40FE7237BB +PT=EFEB82ED91C5C60FB8F910542804B57B + +I=147 +KEY=8D4ABC926827F066B4391FF4B3D6EC99FB472C9D93883DBFAD7CCD8DFB981652 +IV=59D1F20490DBDDF74FD4267176ED071A +CT=EFEB82ED91C5C60FB8F910542804B57B +PT=E30D071737AB9991F000302502BE84A6 + +I=148 +KEY=086A14365F781B2FAF533B1534F458D2184A2B8AA423A42E5D7CFDA8F92692F4 +IV=8520A8A4375FEB491B6A24E18722B44B +CT=E30D071737AB9991F000302502BE84A6 +PT=856AF9DF9A9FE5038B75C98E0E1C720F + +I=149 +KEY=A64DE8CF2DF04ADB60E88C769F7025BC9D20D2553EBC412DD6093426F73AE0FB +IV=AE27FCF9728851F4CFBBB763AB847D6E +CT=856AF9DF9A9FE5038B75C98E0E1C720F +PT=D84910F298F91E081480A912B1AF32D6 + +I=150 +KEY=C52575277A0BD189E2F746FC51CA77844569C2A7A6455F25C2899D344695D22D +IV=63689DE857FB9B52821FCA8ACEBA5238 +CT=D84910F298F91E081480A912B1AF32D6 +PT=57E4A4A2D639D414ED7F82583B4FFA52 + +I=151 +KEY=CB9A5219490F7EE31B030ECE521C589B128D6605707C8B312FF61F6C7DDA287F +IV=0EBF273E3304AF6AF9F4483203D62F1F +CT=57E4A4A2D639D414ED7F82583B4FFA52 +PT=1CECC8218392F2047C0B70BEBFCC5846 + +I=152 +KEY=AA6412AAC8FC309E6BCDFFD1DA01B6470E61AE24F3EE793553FD6FD2C2167039 +IV=61FE40B381F34E7D70CEF11F881DEEDC +CT=1CECC8218392F2047C0B70BEBFCC5846 +PT=EC2B86A04DB2B4F41830E5EA035531E3 + +I=153 +KEY=EFF5BC892E47F4C7EA859969255AC665E24A2884BE5CCDC14BCD8A38C14341DA +IV=4591AE23E6BBC459814866B8FF5B7022 +CT=EC2B86A04DB2B4F41830E5EA035531E3 +PT=8A1A8EE6E08F61E99FC37AC177881C8A + +I=154 +KEY=D62E9405D7402765E30FDAD7A29B2E716850A6625ED3AC28D40EF0F9B6CB5D50 +IV=39DB288CF907D3A2098A43BE87C1E814 +CT=8A1A8EE6E08F61E99FC37AC177881C8A +PT=F21583AC8C5F03C19A1A9B856C97D6E0 + +I=155 +KEY=D49F229B7DB6973EDE6BD14AB20234379A4525CED28CAFE94E146B7CDA5C8BB0 +IV=02B1B69EAAF6B05B3D640B9D10991A46 +CT=F21583AC8C5F03C19A1A9B856C97D6E0 +PT=323191D5997CF0424B7F5501CBD55B17 + +I=156 +KEY=08B1021CD316864EF5B370CBF891FD27A874B41B4BF05FAB056B3E7D1189D0A7 +IV=DC2E2087AEA011702BD8A1814A93C910 +CT=323191D5997CF0424B7F5501CBD55B17 +PT=B2BBCC6E54CB33319536A81174B0D73B + +I=157 +KEY=786AE1D89ECC32C8883D984E7DC5FD0A1ACF78751F3B6C9A905D966C6539079C +IV=70DBE3C44DDAB4867D8EE8858554002D +CT=B2BBCC6E54CB33319536A81174B0D73B +PT=6E4ADDA6895734D891F328C6D0C71467 + +I=158 +KEY=E6C7441B75AF8701E29376287A126CB07485A5D3966C584201AEBEAAB5FE13FB +IV=9EADA5C3EB63B5C96AAEEE6607D791BA +CT=6E4ADDA6895734D891F328C6D0C71467 +PT=8BED3D2AAB5271F90EE5335520E87AA2 + +I=159 +KEY=22D515400072783951742ACDF2FA6DC8FF6898F93D3E29BB0F4B8DFF95166959 +IV=C412515B75DDFF38B3E75CE588E80178 +CT=8BED3D2AAB5271F90EE5335520E87AA2 +PT=D3059CA1B293AA1F52D459643C5FAB5C + +I=160 +KEY=D6E6A383AF38A1CD2889A5F79A23CE512C6D04588FAD83A45D9FD49BA949C205 +IV=F433B6C3AF4AD9F479FD8F3A68D9A399 +CT=D3059CA1B293AA1F52D459643C5FAB5C +PT=C20D8580ACA043B0ED2F409EEA42C0F0 + +I=161 +KEY=AA95A47ADECB61AAD1A05DA0CE6B17BDEE6081D8230DC014B0B09405430B02F5 +IV=7C7307F971F3C067F929F8575448D9EC +CT=C20D8580ACA043B0ED2F409EEA42C0F0 +PT=61C0D0081F176C53DE83B70608201EE6 + +I=162 +KEY=168A56A528A70354AD74C59A8AF33A508FA051D03C1AAC476E3323034B2B1C13 +IV=BC1FF2DFF66C62FE7CD4983A44982DED +CT=61C0D0081F176C53DE83B70608201EE6 +PT=C016536FEFC08B69867AB2946FFBE011 + +I=163 +KEY=92157F38953622D8C0E191DAC4179A6A4FB602BFD3DA272EE849919724D0FC02 +IV=849F299DBD91218C6D9554404EE4A03A +CT=C016536FEFC08B69867AB2946FFBE011 +PT=6923FF03C812710270438F67EF2F42D1 + +I=164 +KEY=CCB6779947D31DF17182FB54555B49422695FDBC1BC8562C980A1EF0CBFFBED3 +IV=5EA308A1D2E53F29B1636A8E914CD328 +CT=6923FF03C812710270438F67EF2F42D1 +PT=0D1674014AD9DC2150E073E2FCF006A8 + +I=165 +KEY=22AA52C07B42CFEB5E75687D395D86092B8389BD51118A0DC8EA6D12370FB87B +IV=EE1C25593C91D21A2FF793296C06CF4B +CT=0D1674014AD9DC2150E073E2FCF006A8 +PT=6399A65CC66E9318F2CEE1103B8FFB90 + +I=166 +KEY=527EF084271AC57F5D33F2E7C7BE1FF1481A2FE1977F19153A248C020C8043EB +IV=70D4A2445C580A9403469A9AFEE399F8 +CT=6399A65CC66E9318F2CEE1103B8FFB90 +PT=511CBDD6CFA31788A43C765301D6BAAB + +I=167 +KEY=D826E762C9EA31B6F4415B3AE5ED888B1906923758DC0E9D9E18FA510D56F940 +IV=8A5817E6EEF0F4C9A972A9DD2253977A +CT=511CBDD6CFA31788A43C765301D6BAAB +PT=B04E78AB18AE3F5B825087D9D5794BD7 + +I=168 +KEY=B4C2DEE60A738C428B187EC3A3A4A982A948EA9C407231C61C487D88D82FB297 +IV=6CE43984C399BDF47F5925F946492109 +CT=B04E78AB18AE3F5B825087D9D5794BD7 +PT=6B013F9A972D82BD5A87DA6C1DD5FD0F + +I=169 +KEY=C4A41F8C4B26391F6C0D629C6B052BD8C249D506D75FB37B46CFA7E4C5FA4F98 +IV=7066C16A4155B55DE7151C5FC8A1825A +CT=6B013F9A972D82BD5A87DA6C1DD5FD0F +PT=9005F8243C6486F63590E7508503719C + +I=170 +KEY=91A18F2681FCACE1C80DC772BD0F2628524C2D22EB3B358D735F40B440F93E04 +IV=550590AACADA95FEA400A5EED60A0DF0 +CT=9005F8243C6486F63590E7508503719C +PT=39DEEEC3D3AEEBBF4B573462B375B5E4 + +I=171 +KEY=E8FF0EE1269AFDCA213F69757C84704D6B92C3E13895DE32380874D6F38C8BE0 +IV=795E81C7A766512BE932AE07C18B5665 +CT=39DEEEC3D3AEEBBF4B573462B375B5E4 +PT=1910F8E7C3D863784058CB35D674AEEB + +I=172 +KEY=F00751EFCCECA0ECA3C252F396B4078E72823B06FB4DBD4A7850BFE325F8250B +IV=18F85F0EEA765D2682FD3B86EA3077C3 +CT=1910F8E7C3D863784058CB35D674AEEB +PT=4A71250E55629D3C5CC62B18B4B67653 + +I=173 +KEY=383A1B81E82B8174A9B9F0AF9EA498A338F31E08AE2F2076249694FB914E5358 +IV=C83D4A6E24C721980A7BA25C08109F2D +CT=4A71250E55629D3C5CC62B18B4B67653 +PT=19CBB63FBB92C7A10B676DBB5EB29060 + +I=174 +KEY=A6695341053BD5B1E15A6CD73DEF84E12138A83715BDE7D72FF1F940CFFCC338 +IV=9E5348C0ED1054C548E39C78A34B1C42 +CT=19CBB63FBB92C7A10B676DBB5EB29060 +PT=18BA0A45E67D2CFEC691203FC2509837 + +I=175 +KEY=71B4C384EF619E5D6CADBFC7D53564913982A272F3C0CB29E960D97F0DAC5B0F +IV=D7DD90C5EA5A4BEC8DF7D310E8DAE070 +CT=18BA0A45E67D2CFEC691203FC2509837 +PT=7699C8550933C30D630AC16D8DA6F13D + +I=176 +KEY=7D0527970FD45C35817091A317A2EAB04F1B6A27FAF308248A6A1812800AAA32 +IV=0CB1E413E0B5C268EDDD2E64C2978E21 +CT=7699C8550933C30D630AC16D8DA6F13D +PT=78FE8EEC14618ED34F63E8671434ADA7 + +I=177 +KEY=204ECE43E91409C515077FACC37C4DF837E5E4CBEE9286F7C509F075943E0795 +IV=5D4BE9D4E6C055F09477EE0FD4DEA748 +CT=78FE8EEC14618ED34F63E8671434ADA7 +PT=0907F75149A74B49F302D2C08CF18AF5 + +I=178 +KEY=8E80DC69B6CC0F0D7F1F0BE6E9F178AD3EE2139AA735CDBE360B22B518CF8D60 +IV=AECE122A5FD806C86A18744A2A8D3555 +CT=0907F75149A74B49F302D2C08CF18AF5 +PT=FE24023BCABCD83E6212FA53E7320D92 + +I=179 +KEY=5152CCE87D9CCC930D7B376C4F1B334BC0C611A16D8915805419D8E6FFFD80F2 +IV=DFD21081CB50C39E72643C8AA6EA4BE6 +CT=FE24023BCABCD83E6212FA53E7320D92 +PT=9526CDED534CB3366306F8C731F87CD6 + +I=180 +KEY=00C9D78F67F1B63181ADE21A02675C6755E0DC4C3EC5A6B6371F2021CE05FC24 +IV=519B1B671A6D7AA28CD6D5764D7C6F2C +CT=9526CDED534CB3366306F8C731F87CD6 +PT=801F005EA2E9287FFD8D9B01BE8E2205 + +I=181 +KEY=442603CF6A012BDB23086BD7EFD7396ED5FFDC129C2C8EC9CA92BB20708BDE21 +IV=44EFD4400DF09DEAA2A589CDEDB06509 +CT=801F005EA2E9287FFD8D9B01BE8E2205 +PT=7558994ACE0299E34EB586B832C98560 + +I=182 +KEY=B153C7C49983077FB0C79C30266A487AA0A74558522E172A84273D9842425B41 +IV=F575C40BF3822CA493CFF7E7C9BD7114 +CT=7558994ACE0299E34EB586B832C98560 +PT=324273A52FFBFBCAC5401CFCD3075C98 + +I=183 +KEY=0E038D82F7FAD738824EF9FEB6F6627692E536FD7DD5ECE041672164914507D9 +IV=BF504A466E79D047328965CE909C2A0C +CT=324273A52FFBFBCAC5401CFCD3075C98 +PT=509E651E053E85340A5B545AA0E40A71 + +I=184 +KEY=B2237D5D0E16B5F9A8FD7274F4CA1206C27B53E378EB69D44B3C753E31A10DA8 +IV=BC20F0DFF9EC62C12AB38B8A423C7070 +CT=509E651E053E85340A5B545AA0E40A71 +PT=1716AB4DCAB205D62EF356E4C565BA70 + +I=185 +KEY=CBE25CF8F3CAB9849F44F330AD8B17E1D56DF8AEB2596C0265CF23DAF4C4B7D8 +IV=79C121A5FDDC0C7D37B98144594105E7 +CT=1716AB4DCAB205D62EF356E4C565BA70 +PT=093CA7764E7F6828EF210E89D3D01C73 + +I=186 +KEY=2BF3C06B0CAE728C8A6134634D5DEAF1DC515FD8FC26042A8AEE2D532714ABAB +IV=E0119C93FF64CB081525C753E0D6FD10 +CT=093CA7764E7F6828EF210E89D3D01C73 +PT=86F8B39DB10EB8B3CFED4C98BBBFFAE1 + +I=187 +KEY=A2C742CFF575CA98D3261BE7DA99E3935AA9EC454D28BC99450361CB9CAB514A +IV=893482A4F9DBB81459472F8497C40962 +CT=86F8B39DB10EB8B3CFED4C98BBBFFAE1 +PT=8BF9C14617B3CE1511ABBD484439D041 + +I=188 +KEY=F8AB8BAD8F2C5A54ED4C80AD094A36D4D1502D035A9B728C54A8DC83D892810B +IV=5A6CC9627A5990CC3E6A9B4AD3D3D547 +CT=8BF9C14617B3CE1511ABBD484439D041 +PT=C41B937B1D5E10D982C7850685997862 + +I=189 +KEY=4DBA6859C8D681253E8F6278BE76D87D154BBE7847C56255D66F59855D0BF969 +IV=B511E3F447FADB71D3C3E2D5B73CEEA9 +CT=C41B937B1D5E10D982C7850685997862 +PT=467114F3F33C8BA65AA76C297E9DA11C + +I=190 +KEY=2738E652A9F41B48B443B487B2AF6D7C533AAA8BB4F9E9F38CC835AC23965875 +IV=6A828E0B61229A6D8ACCD6FF0CD9B501 +CT=467114F3F33C8BA65AA76C297E9DA11C +PT=CB9D772C72BC5BB3E18087CABADDE5B2 + +I=191 +KEY=A1C138E8AFAA19465AE9BD1968C19E8798A7DDA7C645B2406D48B266994BBDC7 +IV=86F9DEBA065E020EEEAA099EDA6EF3FB +CT=CB9D772C72BC5BB3E18087CABADDE5B2 +PT=678837A26F65190F44107C19A01F97E6 + +I=192 +KEY=CD73AF62C6130630324F71F35042BC9AFF2FEA05A920AB4F2958CE7F39542A21 +IV=6CB2978A69B91F7668A6CCEA3883221D +CT=678837A26F65190F44107C19A01F97E6 +PT=E395804E9F2D61447B5207AA438F7D98 + +I=193 +KEY=F076EAF59DAC3F3975E9CBED6697A21B1CBA6A4B360DCA0B520AC9D57ADB57B9 +IV=3D0545975BBF390947A6BA1E36D51E81 +CT=E395804E9F2D61447B5207AA438F7D98 +PT=CA6E3E780C170E950306FEE08CAB46D9 + +I=194 +KEY=87DD7A9906E626E1AC55611A52EBC196D6D454333A1AC49E510C3735F6701160 +IV=77AB906C9B4A19D8D9BCAAF7347C638D +CT=CA6E3E780C170E950306FEE08CAB46D9 +PT=419B7C538E827E431B2C2BA5AEB95373 + +I=195 +KEY=C8D569C710030750FDA3A48E748BED26974F2860B498BADD4A201C9058C94213 +IV=4F08135E16E521B151F6C59426602CB0 +CT=419B7C538E827E431B2C2BA5AEB95373 +PT=1D6607B51B0DA629C62D00CB20870FEA + +I=196 +KEY=A3A22E3CED89316BC747E3326CB53C448A292FD5AF951CF48C0D1C5B784E4DF9 +IV=6B7747FBFD8A363B3AE447BC183ED162 +CT=1D6607B51B0DA629C62D00CB20870FEA +PT=58169D0006C9031C7CCE502F086B0CD6 + +I=197 +KEY=DDB2F456CFE201D5E1DD9EFC6593813FD23FB2D5A95C1FE8F0C34C747025412F +IV=7E10DA6A226B30BE269A7DCE0926BD7B +CT=58169D0006C9031C7CCE502F086B0CD6 +PT=8001E1BDAE24A2A9ABE102C2BEB4AD70 + +I=198 +KEY=A990048427C8E19BABE1D0BB5D6A83CA523E53680778BD415B224EB6CE91EC5F +IV=7422F0D2E82AE04E4A3C4E4738F902F5 +CT=8001E1BDAE24A2A9ABE102C2BEB4AD70 +PT=EA143E99846F5DF1C1A2AD0565D3AE45 + +I=199 +KEY=5074E20E5B70B571A7155A3AAFE3AF2AB82A6DF18317E0B09A80E3B3AB42421A +IV=F9E4E68A7CB854EA0CF48A81F2892CE0 +CT=EA143E99846F5DF1C1A2AD0565D3AE45 +PT=C1EBFE1B00D813BB5AC9E4B007977B19 + +I=200 +KEY=50315F6BF520F26A044751215225348179C193EA83CFF30BC0490703ACD53903 +IV=0045BD65AE50471BA3520B1BFDC69BAB +CT=C1EBFE1B00D813BB5AC9E4B007977B19 +PT=3476AA08CB11F13D8DD858CF10472D03 + +I=201 +KEY=03D2536F9830D74A9B2AEDD1508CE4764DB739E248DE02364D915FCCBC921400 +IV=53E30C046D1025209F6DBCF002A9D0F7 +CT=3476AA08CB11F13D8DD858CF10472D03 +PT=C79BED3BB201F29B65CDF5709654317C + +I=202 +KEY=4AC2173AD99E09ECCB4A647AF96C26F98A2CD4D9FADFF0AD285CAABC2AC6257C +IV=4910445541AEDEA6506089ABA9E0C28F +CT=C79BED3BB201F29B65CDF5709654317C +PT=E5E144D56A2FF95D644D51E73AEAE922 + +I=203 +KEY=9F46778CA9C15CB9978C0DF359056F3D6FCD900C90F009F04C11FB5B102CCC5E +IV=D58460B6705F55555CC66989A06949C4 +CT=E5E144D56A2FF95D644D51E73AEAE922 +PT=38582F30FDE74A162CCD85955C2E48FC + +I=204 +KEY=63038F8EA2934D0C65F181BE92B9664A5795BF3C6D1743E660DC7ECE4C0284A2 +IV=FC45F8020B5211B5F27D8C4DCBBC0977 +CT=38582F30FDE74A162CCD85955C2E48FC +PT=266E808D7E9206C9294F0349D1CEF1DA + +I=205 +KEY=D43CC15DCAB5047B8C67D61F1735C6A471FB3FB11385452F49937D879DCC7578 +IV=B73F4ED368264977E99657A1858CA0EE +CT=266E808D7E9206C9294F0349D1CEF1DA +PT=8E3D1F7DC678C32352782D52E4CD44D5 + +I=206 +KEY=9979232A388E0E6C766279CFE7E047B4FFC620CCD5FD860C1BEB50D5790131AD +IV=4D45E277F23B0A17FA05AFD0F0D58110 +CT=8E3D1F7DC678C32352782D52E4CD44D5 +PT=DDC8075418E2A649D4E78144528682F9 + +I=207 +KEY=43479EA72BF3B417CF224B15749043C5220E2798CD1F2045CF0CD1912B87B354 +IV=DA3EBD8D137DBA7BB94032DA93700471 +CT=DDC8075418E2A649D4E78144528682F9 +PT=4096B4F51C77C8A00A5308D8C3175B6A + +I=208 +KEY=7AE39630885C3ACDCF915625141DF45A6298936DD168E8E5C55FD949E890E83E +IV=39A40897A3AF8EDA00B31D30608DB79F +CT=4096B4F51C77C8A00A5308D8C3175B6A +PT=60D0385ECE913BEC6760BAA0BCCDE853 + +I=209 +KEY=82496ADB8A91DAE80C249D2BD8F00C990248AB331FF9D309A23F63E9545D006D +IV=F8AAFCEB02CDE025C3B5CB0ECCEDF8C3 +CT=60D0385ECE913BEC6760BAA0BCCDE853 +PT=79A86909141C27366744FC614808705B + +I=210 +KEY=EF7FEE5E3FDAC015E8016A7A9D3EB8677BE0C23A0BE5F43FC57B9F881C557036 +IV=6D368485B54B1AFDE425F75145CEB4FE +CT=79A86909141C27366744FC614808705B +PT=9817CE82A9D821189878991B32360409 + +I=211 +KEY=A400D423453A59F64968E8B80140AAF6E3F70CB8A23DD5275D0306932E63743F +IV=4B7F3A7D7AE099E3A16982C29C7E1291 +CT=9817CE82A9D821189878991B32360409 +PT=C3259E5D4A3E82FDC862E862E4449DA2 + +I=212 +KEY=B9280C8996C8BEC6888CB4D9D1E76B0620D292E5E80357DA9561EEF1CA27E99D +IV=1D28D8AAD3F2E730C1E45C61D0A7C1F0 +CT=C3259E5D4A3E82FDC862E862E4449DA2 +PT=F035078B9A3E45B4ED561F001DB21E47 + +I=213 +KEY=9686D9BB259CD14FA7D58C9789932385D0E7956E723D126E7837F1F1D795F7DA +IV=2FAED532B3546F892F59384E58744883 +CT=F035078B9A3E45B4ED561F001DB21E47 +PT=596B9F7F2122A11C599626B16B6AC340 + +I=214 +KEY=736E847DDC4C794A3AA2E22C1AF85EF1898C0A11531FB37221A1D740BCFF349A +IV=E5E85DC6F9D0A8059D776EBB936B7D74 +CT=596B9F7F2122A11C599626B16B6AC340 +PT=800FCC5CE3B08CFFDD70FB5270DED220 + +I=215 +KEY=728D3E35CD653621D41E591530770B370983C64DB0AF3F8DFCD12C12CC21E6BA +IV=01E3BA4811294F6BEEBCBB392A8F55C6 +CT=800FCC5CE3B08CFFDD70FB5270DED220 +PT=5515A58EB0013D2EE561BD2826761209 + +I=216 +KEY=929F6FD8250BAD33FAE4ED108843A2645C9663C300AE02A319B0913AEA57F4B3 +IV=E01251EDE86E9B122EFAB405B834A953 +CT=5515A58EB0013D2EE561BD2826761209 +PT=8B7B3AB73287CEAAA0098D41F0B3A28B + +I=217 +KEY=3F54C218B02F6097C3F31A05F5CCB8C4D7ED59743229CC09B9B91C7B1AE45638 +IV=ADCBADC09524CDA43917F7157D8F1AA0 +CT=8B7B3AB73287CEAAA0098D41F0B3A28B +PT=90CDCF132600F622D1339197B441A4C0 + +I=218 +KEY=2F60AEE4E6A6F7109193112BC756D7F24720966714293A2B688A8DECAEA5F2F8 +IV=10346CFC5689978752600B2E329A6F36 +CT=90CDCF132600F622D1339197B441A4C0 +PT=EA089BEC0DEE1305828522B8AD4F5A99 + +I=219 +KEY=33623A9F86F3AF456D92076B132E46A3AD280D8B19C7292EEA0FAF5403EAA861 +IV=1C02947B60555855FC011640D4789151 +CT=EA089BEC0DEE1305828522B8AD4F5A99 +PT=339C14562AE38F84BE0FB1569C234287 + +I=220 +KEY=6291ED0B63ED8C18A713DDCBFCA054E19EB419DD3324A6AA54001E029FC9EAE6 +IV=51F3D794E51E235DCA81DAA0EF8E1242 +CT=339C14562AE38F84BE0FB1569C234287 +PT=31050E95B1F08B9139EF7F8D42110978 + +I=221 +KEY=7BEF1BE3E67AA478C5D9F50350D221CCAFB1174882D42D3B6DEF618FDDD8E39E +IV=197EF6E88597286062CA28C8AC72752D +CT=31050E95B1F08B9139EF7F8D42110978 +PT=18DE66E3B58C9ABAB99987826AF0D0AF + +I=222 +KEY=3DEB69283844069B400C2E7127B8CD2EB76F71AB3758B781D476E60DB7283331 +IV=460472CBDE3EA2E385D5DB72776AECE2 +CT=18DE66E3B58C9ABAB99987826AF0D0AF +PT=B75D11E28C94DB969FE009B984DA956B + +I=223 +KEY=754C5BEC642540EC8BAD0778773CA8E700326049BBCC6C174B96EFB433F2A65A +IV=48A732C45C614677CBA12909508465C9 +CT=B75D11E28C94DB969FE009B984DA956B +PT=7CEEE835FC734108785B367A28C62058 + +I=224 +KEY=01B0A659138DEE7CF1EFA11DD0A209247CDC887C47BF2D1F33CDD9CE1B348602 +IV=74FCFDB577A8AE907A42A665A79EA1C3 +CT=7CEEE835FC734108785B367A28C62058 +PT=F1E848F6C257D6D56B4FBCA36900614C + +I=225 +KEY=F9531CEDC3C5C76A90195BF1E5FB5ED98D34C08A85E8FBCA5882656D7234E74E +IV=F8E3BAB4D048291661F6FAEC355957FD +CT=F1E848F6C257D6D56B4FBCA36900614C +PT=7B06A193C8B84977E56B382D424D2A78 + +I=226 +KEY=D409DB9768430BCA0E2B68BA1CFE93A5F63261194D50B2BDBDE95D403079CD36 +IV=2D5AC77AAB86CCA09E32334BF905CD7C +CT=7B06A193C8B84977E56B382D424D2A78 +PT=413356E3367ACBDD88ADA6DF5E09FFC6 + +I=227 +KEY=8425B50A014625BA114ABAC1585C3F68B70137FA7B2A79603544FB9F6E7032F0 +IV=502C6E9D69052E701F61D27B44A2ACCD +CT=413356E3367ACBDD88ADA6DF5E09FFC6 +PT=13B524E8AEBFE32CC9559B500D9E9A82 + +I=228 +KEY=3ED2EEDFF8C12697C9CEB18B8DC86798A4B41312D5959A4CFC1160CF63EEA872 +IV=BAF75BD5F987032DD8840B4AD59458F0 +CT=13B524E8AEBFE32CC9559B500D9E9A82 +PT=91775D8DF510277669BC11697965AE99 + +I=229 +KEY=B3C35FF0F6B2DDCF5522A35E75040BB135C34E9F2085BD3A95AD71A61A8B06EB +IV=8D11B12F0E73FB589CEC12D5F8CC6C29 +CT=91775D8DF510277669BC11697965AE99 +PT=0AA5B5A593FED4CE1FD66736774649D2 + +I=230 +KEY=5581EEED032A31D6F8077BEED79ABB1E3F66FB3AB37B69F48A7B16906DCD4F39 +IV=E642B11DF598EC19AD25D8B0A29EB0AF +CT=0AA5B5A593FED4CE1FD66736774649D2 +PT=3DB595E23D32347092E5D94A8376DB5D + +I=231 +KEY=2337ABB014AD70D3E290033BD6FC75D702D36ED88E495D84189ECFDAEEBB9464 +IV=76B6455D178741051A9778D50166CEC9 +CT=3DB595E23D32347092E5D94A8376DB5D +PT=2AF2DEC9D2D4F0BA81D1FC88E421C034 + +I=232 +KEY=7C8A43D8CA68E782BBD49C18477683052821B0115C9DAD3E994F33520A9A5450 +IV=5FBDE868DEC5975159449F23918AF6D2 +CT=2AF2DEC9D2D4F0BA81D1FC88E421C034 +PT=8AF90FCCBEDCDF709AEE93FEF45C03EC + +I=233 +KEY=37FDC789E91F58F691931C86C4505926A2D8BFDDE241724E03A1A0ACFEC657BC +IV=4B7784512377BF742A47809E8326DA23 +CT=8AF90FCCBEDCDF709AEE93FEF45C03EC +PT=8E98DF785A601DF26465D9A0D163D650 + +I=234 +KEY=57C30D92BD234BE693F15534768970FC2C4060A5B8216FBC67C4790C2FA581EC +IV=603ECA1B543C1310026249B2B2D929DA +CT=8E98DF785A601DF26465D9A0D163D650 +PT=21D3EAC95A088A548E5C0E56001BD103 + +I=235 +KEY=1F9A07E73DB0530F84B6DB88C5EA0AFD0D938A6CE229E5E8E998775A2FBE50EF +IV=48590A75809318E917478EBCB3637A01 +CT=21D3EAC95A088A548E5C0E56001BD103 +PT=48A8853D9E4E4A6351E5F5734911D569 + +I=236 +KEY=219E87740C05905A3DAC677C78C5E6D4453B0F517C67AF8BB87D822966AF8586 +IV=3E04809331B5C355B91ABCF4BD2FEC29 +CT=48A8853D9E4E4A6351E5F5734911D569 +PT=C75ECB64A655DC6803FC976A1CAE78A9 + +I=237 +KEY=D445B2CF4C6B8AF073FCDFF8907C4B278265C435DA3273E3BB8115437A01FD2F +IV=F5DB35BB406E1AAA4E50B884E8B9ADF3 +CT=C75ECB64A655DC6803FC976A1CAE78A9 +PT=F063E6C6A62D07B1CA90594CB9041DE4 + +I=238 +KEY=3DECAA3153A9658A2CAA5578AF2C55CD720622F37C1F745271114C0FC305E0CB +IV=E9A918FE1FC2EF7A5F568A803F501EEA +CT=F063E6C6A62D07B1CA90594CB9041DE4 +PT=45F375DDBA20D20CB6C5EAB28AA85D06 + +I=239 +KEY=31766034845DF8A1AEDFC70CE3CD5B1D37F5572EC63FA65EC7D4A6BD49ADBDCD +IV=0C9ACA05D7F49D2B827592744CE10ED0 +CT=45F375DDBA20D20CB6C5EAB28AA85D06 +PT=5D117AAC285D5A6948390FDAFBDACAD5 + +I=240 +KEY=BF17727E1D5DCA94C9CCA8E11DFBF22A6AE42D82EE62FC378FEDA967B2777718 +IV=8E61124A9900323567136FEDFE36A937 +CT=5D117AAC285D5A6948390FDAFBDACAD5 +PT=C8B61B172D930641A88E9E13236E11F9 + +I=241 +KEY=B82DB30F4271245293FC4CB6A0C10D4FA2523695C3F1FA7627633774911966E1 +IV=073AC1715F2CEEC65A30E457BD3AFF65 +CT=C8B61B172D930641A88E9E13236E11F9 +PT=FE05708E08F8568BB55175CEEF9E0433 + +I=242 +KEY=28AE9BD5E181AC41CF2F9B4710DD160C5C57461BCB09ACFD923242BA7E8762D2 +IV=908328DAA3F088135CD3D7F1B01C1B43 +CT=FE05708E08F8568BB55175CEEF9E0433 +PT=D7DB71EAC2EF31AE105227E34134AD3C + +I=243 +KEY=437D385B59B4AB247A5BCFC0C0F8596F8B8C37F109E69D53826065593FB3CFEE +IV=6BD3A38EB8350765B5745487D0254F63 +CT=D7DB71EAC2EF31AE105227E34134AD3C +PT=ECD51D08C870983992708FC1FDFA9D15 + +I=244 +KEY=4EF45D9C1FCA58D42D9E7E2E9C7D0B8F67592AF9C196056A1010EA98C24952FB +IV=0D8965C7467EF3F057C5B1EE5C8552E0 +CT=ECD51D08C870983992708FC1FDFA9D15 +PT=F436BA32E9D089248AC47E40AA6B4BAC + +I=245 +KEY=D3F16D0CF75471A24F273B3E8EF0A3A0936F90CB28468C4E9AD494D868221957 +IV=9D053090E89E297662B94510128DA82F +CT=F436BA32E9D089248AC47E40AA6B4BAC +PT=F43E89C3DBD391B5778B30A36A9E42F3 + +I=246 +KEY=953E7AB7369425A4F396D764F3EA047F67511908F3951DFBED5FA47B02BC5BA4 +IV=46CF17BBC1C05406BCB1EC5A7D1AA7DF +CT=F43E89C3DBD391B5778B30A36A9E42F3 +PT=B12ABB428A29703B929EFDB0031694D1 + +I=247 +KEY=C8DDFEFD3C72822B72C78757EE8EF856D67BA24A79BC6DC07FC159CB01AACF75 +IV=5DE3844A0AE6A78F815150331D64FC29 +CT=B12ABB428A29703B929EFDB0031694D1 +PT=79F19D2BD0A025D2D9822A28F5304446 + +I=248 +KEY=870A25E9511D3F1BCFA941DA41FD00C0AF8A3F61A91C4812A64373E3F49A8B33 +IV=4FD7DB146D6FBD30BD6EC68DAF73F896 +CT=79F19D2BD0A025D2D9822A28F5304446 +PT=C52D5EF8D7A1353F5C1FF7BA33F9ED97 + +I=249 +KEY=178B86564949AE1A0CE50E61F4D3F8776AA761997EBD7D2DFA5C8459C76366A4 +IV=9081A3BF18549101C34C4FBBB52EF8B7 +CT=C52D5EF8D7A1353F5C1FF7BA33F9ED97 +PT=82FAB7DF4BE409880B8F66210DE8D2E5 + +I=250 +KEY=C3F845809E635052F94076E1F3026779E85DD646355974A5F1D3E278CA8BB441 +IV=D473C3D6D72AFE48F5A5788007D19F0E +CT=82FAB7DF4BE409880B8F66210DE8D2E5 +PT=52C05722F125348666DFCF0F2D052530 + +I=251 +KEY=34AE823E21F4C45784F2E125CF5039FCBA9D8164C47C4023970C2D77E78E9171 +IV=F756C7BEBF9794057DB297C43C525E85 +CT=52C05722F125348666DFCF0F2D052530 +PT=DE7FAAF4A10D4D5404847FA080C1DC1C + +I=252 +KEY=9D1EEFC6B62427F5A2CBB2047AB0E41B64E22B9065710D77938852D7674F4D6D +IV=A9B06DF897D0E3A226395321B5E0DDE7 +CT=DE7FAAF4A10D4D5404847FA080C1DC1C +PT=49327927599012EE87FF64F45AC9A9AE + +I=253 +KEY=2C7B21A79BE0B5B0E4DCC427DE8D91572DD052B73CE11F99147736233D86E4C3 +IV=B165CE612DC4924546177623A43D754C +CT=49327927599012EE87FF64F45AC9A9AE +PT=6E11B9F592DD99CD94F8999D9476F4CF + +I=254 +KEY=F4A72FB6D161B9E15A41576C5A7CBF3F43C1EB42AE3C8654808FAFBEA9F0100C +IV=D8DC0E114A810C51BE9D934B84F12E68 +CT=6E11B9F592DD99CD94F8999D9476F4CF +PT=108AC1FE3E008D1C3058917157003E2C + +I=255 +KEY=2E5FE97C58B060C9BACA9E9CC14CFC89534B2ABC903C0B48B0D73ECFFEF02E20 +IV=DAF8C6CA89D1D928E08BC9F09B3043B6 +CT=108AC1FE3E008D1C3058917157003E2C +PT=B315EF45A3BD77688AD0976EF5DCA26B + +I=256 +KEY=9D763A80B96B112E1DAEA50A98C0B6F7E05EC5F933817C203A07A9A10B2C8C4B +IV=B329D3FCE1DB71E7A7643B96598C4A7E +CT=B315EF45A3BD77688AD0976EF5DCA26B +PT=7BF8DABED803049DF8D1F34ED00536F7 + +I=257 +KEY=DF5F07523E7E305B48AAD9C205AE826C9BA61F47EB8278BDC2D65AEFDB29BABC +IV=42293DD28715217555047CC89D6E349B +CT=7BF8DABED803049DF8D1F34ED00536F7 +PT=E55FE84DF3137D16E74DC01A1BFDA4A7 + +I=258 +KEY=80CF537EC8836ADD0FB72F35B2EF703D7EF9F70A189105AB259B9AF5C0D41E1B +IV=5F90542CF6FD5A86471DF6F7B741F251 +CT=E55FE84DF3137D16E74DC01A1BFDA4A7 +PT=6019F9DA2DFDCDCB14C2C6CE5B34432D + +I=259 +KEY=4469D3622A022CFB7614C9C9EB36E6031EE00ED0356CC86031595C3B9BE05D36 +IV=C4A6801CE281462679A3E6FC59D9963E +CT=6019F9DA2DFDCDCB14C2C6CE5B34432D +PT=6D2788861A8F9526D1EC8A6A8AFBA629 + +I=260 +KEY=DED804546FA6B0BCD8C9FD9119616F9873C786562FE35D46E0B5D651111BFB1F +IV=9AB1D73645A49C47AEDD3458F257899B +CT=6D2788861A8F9526D1EC8A6A8AFBA629 +PT=81D5CDEA70E433A2A341FFB13ECCEC54 + +I=261 +KEY=24FD3D900606EEF8F31156D30EA094ADF2124BBC5F076EE443F429E02FD7174B +IV=FA2539C469A05E442BD8AB4217C1FB35 +CT=81D5CDEA70E433A2A341FFB13ECCEC54 +PT=F74B4869E92F918A95B508E382A83FA6 + +I=262 +KEY=C24CA269EAADDFBA060AAF15C2265DE6055903D5B628FF6ED6412103AD7F28ED +IV=E6B19FF9ECAB3142F51BF9C6CC86C94B +CT=F74B4869E92F918A95B508E382A83FA6 +PT=EF3293511A17D0E089A8F88E396B4F31 + +I=263 +KEY=789C94E8D2B6D6FD022ED678F42E796CEA6B9084AC3F2F8E5FE9D98D941467DC +IV=BAD03681381B09470424796D3608248A +CT=EF3293511A17D0E089A8F88E396B4F31 +PT=0D70FCE243309D716D8FA672A11EBCB8 + +I=264 +KEY=B8DFB47D720C26AE22AD6C87785CCB97E71B6C66EF0FB2FF32667FFF350ADB64 +IV=C0432095A0BAF0532083BAFF8C72B2FB +CT=0D70FCE243309D716D8FA672A11EBCB8 +PT=831365AB30D062F2B1C051A9EA03AEEB + +I=265 +KEY=938BCEFF0FD9AEC61CF2B0509A645A19640809CDDFDFD00D83A62E56DF09758F +IV=2B547A827DD588683E5FDCD7E238918E +CT=831365AB30D062F2B1C051A9EA03AEEB +PT=EFE7E9DC254FF4AA70ABF327566A5448 + +I=266 +KEY=BBF0C86D05BF543EC3B9A9240833187F8BEFE011FA9024A7F30DDD71896321C7 +IV=287B06920A66FAF8DF4B197492574266 +CT=EFE7E9DC254FF4AA70ABF327566A5448 +PT=2D41BEE483BD2BAD16026AD7AA5ABA07 + +I=267 +KEY=B744A9326EC1D56CBFF51D969D075C7DA6AE5EF5792D0F0AE50FB7A623399BC0 +IV=0CB4615F6B7E81527C4CB4B295344402 +CT=2D41BEE483BD2BAD16026AD7AA5ABA07 +PT=079460C9B745A53999932C5ECFE6A37B + +I=268 +KEY=AE49C59DD393E9EC9030AEDAD7FC61FEA13A3E3CCE68AA337C9C9BF8ECDF38BB +IV=190D6CAFBD523C802FC5B34C4AFB3D83 +CT=079460C9B745A53999932C5ECFE6A37B +PT=CE7C5851D0437368FEDC7E39270A7430 + +I=269 +KEY=8176855633B6FB2445BDDC2FD8D299576F46666D1E2BD95B8240E5C1CBD54C8B +IV=2F3F40CBE02512C8D58D72F50F2EF8A9 +CT=CE7C5851D0437368FEDC7E39270A7430 +PT=A0C3F2D688E4370AD2F08C09B28DBCC1 + +I=270 +KEY=050E71C47B278C5825DE84513A732D11CF8594BB96CFEE5150B069C87958F04A +IV=8478F4924891777C6063587EE2A1B446 +CT=A0C3F2D688E4370AD2F08C09B28DBCC1 +PT=BE472E609ABB030B96739A959EDBDD21 + +I=271 +KEY=502E4BDCF449E96CB16D5B6C097D20CC71C2BADB0C74ED5AC6C3F35DE7832D6B +IV=55203A188F6E653494B3DF3D330E0DDD +CT=BE472E609ABB030B96739A959EDBDD21 +PT=FE4227D6AC71519FA0F2078433DF69CA + +I=272 +KEY=C3DDDE6B2E80381010569BC093561F628F809D0DA005BCC56631F4D9D45C44A1 +IV=93F395B7DAC9D17CA13BC0AC9A2B3FAE +CT=FE4227D6AC71519FA0F2078433DF69CA +PT=3F8439C7648C5C2B5877643C536E14F9 + +I=273 +KEY=1CC65CB104317D620D729EDEB4C4B512B004A4CAC489E0EE3E4690E587325058 +IV=DF1B82DA2AB145721D24051E2792AA70 +CT=3F8439C7648C5C2B5877643C536E14F9 +PT=E189B969BF38C8A2F38BF3F12267B5B4 + +I=274 +KEY=D121C8556039F07E231F9E88DE60572B518D1DA37BB1284CCDCD6314A555E5EC +IV=CDE794E464088D1C2E6D00566AA4E239 +CT=E189B969BF38C8A2F38BF3F12267B5B4 +PT=EF15CCEC56DCD62681FC7564A1095ECD + +I=275 +KEY=C87070F4AA767BE043B29FE3AF258C91BE98D14F2D6DFE6A4C311670045CBB21 +IV=1951B8A1CA4F8B9E60AD016B7145DBBA +CT=EF15CCEC56DCD62681FC7564A1095ECD +PT=BD38CD579A7124DD0814DB21FC0E7D96 + +I=276 +KEY=08167C643CA7CAD8729B17EB91918AC103A01C18B71CDAB74425CD51F852C6B7 +IV=C0660C9096D1B138312988083EB40650 +CT=BD38CD579A7124DD0814DB21FC0E7D96 +PT=565F580B61E456544D8D553948AD95FD + +I=277 +KEY=55BB77ED49C419EEA418365F2750857355FF4413D6F88CE309A89868B0FF534A +IV=5DAD0B897563D336D68321B4B6C10FB2 +CT=565F580B61E456544D8D553948AD95FD +PT=1AA68EAC78C2B5BFF996F0B58C56432F + +I=278 +KEY=8FEC3C85819F24EE1DA186AB212A19D44F59CABFAE3A395CF03E68DD3CA91065 +IV=DA574B68C85B3D00B9B9B0F4067A9CA7 +CT=1AA68EAC78C2B5BFF996F0B58C56432F +PT=65660FBF6C166604D9E717671488D734 + +I=279 +KEY=D1D19B25C23EA5923D45493905B867D12A3FC500C22C5F5829D97FBA2821C751 +IV=5E3DA7A043A1817C20E4CF9224927E05 +CT=65660FBF6C166604D9E717671488D734 +PT=477CBD97B467AA1AAB738E294092FAA3 + +I=280 +KEY=E1972BE045093EC4475DCE6351CDEDCB6D437897764BF54282AAF19368B33DF2 +IV=3046B0C587379B567A18875A54758A1A +CT=477CBD97B467AA1AAB738E294092FAA3 +PT=C0ED90D90AE11390A275BD03BE00E1D5 + +I=281 +KEY=6F622A270D77AE65084E2070343E8C7FADAEE84E7CAAE6D220DF4C90D6B3DC27 +IV=8EF501C7487E90A14F13EE1365F361B4 +CT=C0ED90D90AE11390A275BD03BE00E1D5 +PT=296FED9B8CF7C532721A2188DDB1A441 + +I=282 +KEY=FF7209EA94C0401544991FDB57F77F2084C105D5F05D23E052C56D180B027866 +IV=901023CD99B7EE704CD73FAB63C9F35F +CT=296FED9B8CF7C532721A2188DDB1A441 +PT=4AE1C2EB8D1CEB5804FA992708150590 + +I=283 +KEY=73C6F94AD63DE39C289AE20179FDDDD7CE20C73E7D41C8B8563FF43F03177DF6 +IV=8CB4F0A042FDA3896C03FDDA2E0AA2F7 +CT=4AE1C2EB8D1CEB5804FA992708150590 +PT=A4EAC8940C12F9CEAC78DFDC99DF68B4 + +I=284 +KEY=A7369886016682F6075678509FFB86ED6ACA0FAA71533176FA472BE39AC81542 +IV=D4F061CCD75B616A2FCC9A51E6065B3A +CT=A4EAC8940C12F9CEAC78DFDC99DF68B4 +PT=70B05A9959E7C4E4545BB3AECCD8B33D + +I=285 +KEY=F01B9FF32CE9CA699F69ADBBC209BBD21A7A553328B4F592AE1C984D5610A67F +IV=572D07752D8F489F983FD5EB5DF23D3F +CT=70B05A9959E7C4E4545BB3AECCD8B33D +PT=F4978960F1382713A5A7183B9694DE85 + +I=286 +KEY=FF05A97961A5CA725CD2E1B2A9D58304EEEDDC53D98CD2810BBB8076C08478FA +IV=0F1E368A4D4C001BC3BB4C096BDC38D6 +CT=F4978960F1382713A5A7183B9694DE85 +PT=EDCC3B8D26928086F1C6727833405424 + +I=287 +KEY=AA4DB35CCBD936D13D1B7DB64638B99A0321E7DEFF1E5207FA7DF20EF3C42CDE +IV=55481A25AA7CFCA361C99C04EFED3A9E +CT=EDCC3B8D26928086F1C6727833405424 +PT=12A36AC1DA72345291CF206FA04F102F + +I=288 +KEY=611E32BF030B7B377AEC338C7FA6D88311828D1F256C66556BB2D261538B3CF1 +IV=CB5381E3C8D24DE647F74E3A399E6119 +CT=12A36AC1DA72345291CF206FA04F102F +PT=8DA0003E090444453B932F0CDBBFA54E + +I=289 +KEY=43E230241EF150AC761C1307C43C3E209C228D212C6822105021FD6D883499BF +IV=22FC029B1DFA2B9B0CF0208BBB9AE6A3 +CT=8DA0003E090444453B932F0CDBBFA54E +PT=A3D9F2112895CEA937A2B18ABB589CC0 + +I=290 +KEY=1FE38E9028DAC8A1E65A04C78BD0E7523FFB7F3004FDECB967834CE7336C057F +IV=5C01BEB4362B980D904617C04FECD972 +CT=A3D9F2112895CEA937A2B18ABB589CC0 +PT=191EE02B9FED198599B5BC2F36271ABB + +I=291 +KEY=5FFD20799D7A7E7A328BD57B13F6E52F26E59F1B9B10F53CFE36F0C8054B1FC4 +IV=401EAEE9B5A0B6DBD4D1D1BC9826027D +CT=191EE02B9FED198599B5BC2F36271ABB +PT=EFC32006AE746D1E3F65E6C7ADF32804 + +I=292 +KEY=EFEFD2A0F1917EB5BFD2337260E11023C926BF1D35649822C153160FA8B837C0 +IV=B012F2D96CEB00CF8D59E6097317F50C +CT=EFC32006AE746D1E3F65E6C7ADF32804 +PT=F9C49B0BFFA354EEBBE3DE29BF9D2623 + +I=293 +KEY=7676D792019D370A67526977EC5FDB5B30E22416CAC7CCCC7AB0C826172511E3 +IV=99990532F00C49BFD8805A058CBECB78 +CT=F9C49B0BFFA354EEBBE3DE29BF9D2623 +PT=EAEAE4BFF789E64D80D88CE5BC0E15CC + +I=294 +KEY=69202B4EB33EB35987DD82026714F603DA08C0A93D4E2A81FA6844C3AB2B042F +IV=1F56FCDCB2A38453E08FEB758B4B2D58 +CT=EAEAE4BFF789E64D80D88CE5BC0E15CC +PT=96C362F59FD2457A5ED68A116B4AA682 + +I=295 +KEY=DE8B4CC7995B3E061E126157B0C2AF984CCBA25CA29C6FFBA4BECED2C061A2AD +IV=B7AB67892A658D5F99CFE355D7D6599B +CT=96C362F59FD2457A5ED68A116B4AA682 +PT=5498BE46DCE840F7B593BE2BC0D252CB + +I=296 +KEY=1BFE119E1B63BA06E9A590709A2985D218531C1A7E742F0C112D70F900B3F066 +IV=C5755D5982388400F7B7F1272AEB2A4A +CT=5498BE46DCE840F7B593BE2BC0D252CB +PT=697482966F491ACB46E7171A4813D916 + +I=297 +KEY=9E6361F9775A88FAAD09711E9691798C71279E8C113D35C757CA67E348A02970 +IV=859D70676C3932FC44ACE16E0CB8FC5E +CT=697482966F491ACB46E7171A4813D916 +PT=A799874DC7721D96DEEFAB5FE1A01A8E + +I=298 +KEY=7D1EF621D3ADC4BD4EC1861167FA5B0CD6BE19C1D64F28518925CCBCA90033FE +IV=E37D97D8A4F74C47E3C8F70FF16B2280 +CT=A799874DC7721D96DEEFAB5FE1A01A8E +PT=2D19344625CF5E6DE07EE960F4AEC5CF + +I=299 +KEY=7DFD0BE692B47C022DC789EF5291D2F5FBA72D87F380763C695B25DC5DAEF631 +IV=00E3FDC74119B8BF63060FFE356B89F9 +CT=2D19344625CF5E6DE07EE960F4AEC5CF +PT=F80C5143F173AE672DA4DDC8272C13EF + +I=300 +KEY=A78C66D30475B93F0A87E6E4A8BFA3AE03AB7CC402F3D85B44FFF8147A82E5DE +IV=DA716D3596C1C53D27406F0BFA2E715B +CT=F80C5143F173AE672DA4DDC8272C13EF +PT=76BDB7A63614A41C9D52718B3514E03C + +I=301 +KEY=9542E4B9D92DAF7B463C83DA257422B37516CB6234E77C47D9AD899F4F9605E2 +IV=32CE826ADD5816444CBB653E8DCB811D +CT=76BDB7A63614A41C9D52718B3514E03C +PT=93F65B7B961EE6B623A026576FF8890B + +I=302 +KEY=6932CD66A25D1DE274C7D5DF540917BFE6E09019A2F99AF1FA0DAFC8206E8CE9 +IV=FC7029DF7B70B29932FB5605717D350C +CT=93F65B7B961EE6B623A026576FF8890B +PT=FA5BEB508ABCBCB1B1D56C0E207A032D + +I=303 +KEY=595CCC3640445FF5BBF303FF7845AB821CBB7B49284526404BD8C3C600148FC4 +IV=306E0150E2194217CF34D6202C4CBC3D +CT=FA5BEB508ABCBCB1B1D56C0E207A032D +PT=BFAEA3EB7C617567EB302D571DBF2811 + +I=304 +KEY=BF5382311BF88FC9E32D5BADC832BE48A315D8A254245327A0E8EE911DABA7D5 +IV=E60F4E075BBCD03C58DE5852B07715CA +CT=BFAEA3EB7C617567EB302D571DBF2811 +PT=4B0E63933414184D43B0AA714AA31E02 + +I=305 +KEY=B50A2FF8FAC6820638CCBA3A0CA6519CE81BBB3160304B6AE35844E05708B9D7 +IV=0A59ADC9E13E0DCFDBE1E197C494EFD4 +CT=4B0E63933414184D43B0AA714AA31E02 +PT=0073CA04B300003AF3C1035C664E0646 + +I=306 +KEY=1A32AA7CA8B5D83C47F56C5D24EDBD38E8687135D3304B50109947BC3146BF91 +IV=AF38858452735A3A7F39D667284BECA4 +CT=0073CA04B300003AF3C1035C664E0646 +PT=75CFE6D4A4F05D8EBB5C614AC7FB48C8 + +I=307 +KEY=C321C5381F5A334C8B82DD2F0E4C73AE9DA797E177C016DEABC526F6F6BDF759 +IV=D9136F44B7EFEB70CC77B1722AA1CE96 +CT=75CFE6D4A4F05D8EBB5C614AC7FB48C8 +PT=B0D8DB37DF5C3A87B9E5D562283E8FEE + +I=308 +KEY=40879EA19753F0F22B1C1BF438A446532D7F4CD6A89C2C591220F394DE8378B7 +IV=83A65B998809C3BEA09EC6DB36E835FD +CT=B0D8DB37DF5C3A87B9E5D562283E8FEE +PT=9C885637CC7666C04B424DD6EF1F3EDB + +I=309 +KEY=B6824C9F800B1E7825135F250DB99FC8B1F71AE164EA4A995962BE42319C466C +IV=F605D23E1758EE8A0E0F44D1351DD99B +CT=9C885637CC7666C04B424DD6EF1F3EDB +PT=3E7F4437656E63E0ADC6C764B20FE92D + +I=310 +KEY=7FA3CDE5856B1F0D9AE33E9E6ED1532E8F885ED601842979F4A479268393AF41 +IV=C921817A05600175BFF061BB6368CCE6 +CT=3E7F4437656E63E0ADC6C764B20FE92D +PT=B19CCFDAADEC54C8DD5F4FD53D3C5824 + +I=311 +KEY=3E3ABA34DB005D9FF2CEF1321BCD018E3E14910CAC687DB129FB36F3BEAFF765 +IV=419977D15E6B4292682DCFAC751C52A0 +CT=B19CCFDAADEC54C8DD5F4FD53D3C5824 +PT=84F7D061322A4042913C0BD14F5F1391 + +I=312 +KEY=FB474D499955CB1F37FBA309DD55E09DBAE3416D9E423DF3B8C73D22F1F0E4F4 +IV=C57DF77D42559680C535523BC698E113 +CT=84F7D061322A4042913C0BD14F5F1391 +PT=CBCD716DA9C53D7AFFFE65B780926660 + +I=313 +KEY=7C1D07031362A7439F9DD5272DAD1D9B712E3000378700894739589571628294 +IV=875A4A4A8A376C5CA866762EF0F8FD06 +CT=CBCD716DA9C53D7AFFFE65B780926660 +PT=F605D205704496C5BFCEE88130920CDE + +I=314 +KEY=7E9E72A6032523643F0965E8BFCB0793872BE20547C3964CF8F7B01441F08E4A +IV=028375A510478427A094B0CF92661A08 +CT=F605D205704496C5BFCEE88130920CDE +PT=CFA8B47DEB5770925EA29484D82CDBB4 + +I=315 +KEY=518CA0A8C81E9DDCE1060410C69F0ACE48835678AC94E6DEA655249099DC55FE +IV=2F12D20ECB3BBEB8DE0F61F879540D5D +CT=CFA8B47DEB5770925EA29484D82CDBB4 +PT=1065AD49D2DD48EB9540F23A69469B92 + +I=316 +KEY=45E6A5A17D8D1AEA04CD8E184D0A1BF758E6FB317E49AE353315D6AAF09ACE6C +IV=146A0509B5938736E5CB8A088B951139 +CT=1065AD49D2DD48EB9540F23A69469B92 +PT=DB12EE00C65069CFEA509BA5BD5BB6BC + +I=317 +KEY=FC8F8F7F8A440A6CEB920D4311851B3A83F41531B819C7FAD9454D0F4DC178D0 +IV=B9692ADEF7C91086EF5F835B5C8F00CD +CT=DB12EE00C65069CFEA509BA5BD5BB6BC +PT=B66316FB3CCC9B262A34C205AE43F42B + +I=318 +KEY=42D666DF2C1575E3B346FCBCD208AD9F359703CA84D55CDCF3718F0AE3828CFB +IV=BE59E9A0A6517F8F58D4F1FFC38DB6A5 +CT=B66316FB3CCC9B262A34C205AE43F42B +PT=4C851D9BDC164194A6D1FDE274C06D1B + +I=319 +KEY=786B9456901DFA9FF85C686DEEDCA02079121E5158C31D4855A072E89742E1E0 +IV=3ABDF289BC088F7C4B1A94D13CD40DBF +CT=4C851D9BDC164194A6D1FDE274C06D1B +PT=5507F1EB271BDBC0A6DD8BBAEC843A05 + +I=320 +KEY=C79B5CD424E592D392FECD3233CEA70B2C15EFBA7FD8C688F37DF9527BC6DBE5 +IV=BFF0C882B4F8684C6AA2A55FDD12072B +CT=5507F1EB271BDBC0A6DD8BBAEC843A05 +PT=BB10EF7C98DE0255C836D5319B94B166 + +I=321 +KEY=10ABC5B835E6E6BD02E90B63D22EF9E7970500C6E706C4DD3B4B2C63E0526A83 +IV=D730996C1103746E9017C651E1E05EEC +CT=BB10EF7C98DE0255C836D5319B94B166 +PT=E8B797AFDC378DB47F172260963A6E2C + +I=322 +KEY=75E05AAAB4E6981A20E4177D214B81EA7FB297693B314969445C0E03766804AF +IV=654B9F1281007EA7220D1C1EF365780D +CT=E8B797AFDC378DB47F172260963A6E2C +PT=58ED1CC5A208A0E7340167E79F5DA7C2 + +I=323 +KEY=A69FECC296D12216128BD1D2C48B373D275F8BAC9939E98E705D69E4E935A36D +IV=D37FB6682237BA0C326FC6AFE5C0B6D7 +CT=58ED1CC5A208A0E7340167E79F5DA7C2 +PT=FEDA5FB215819B441BE18B0AED27A1FD + +I=324 +KEY=7EED1776E603DD6C20F08B4C6B121525D985D41E8CB872CA6BBCE2EE04120290 +IV=D872FBB470D2FF7A327B5A9EAF992218 +CT=FEDA5FB215819B441BE18B0AED27A1FD +PT=7CD64E29A704F13688DB206F7F337685 + +I=325 +KEY=D4479A0AF29AF7145EC3FB89FEF8BBA7A5539A372BBC83FCE367C2817B217415 +IV=AAAA8D7C14992A787E3370C595EAAE82 +CT=7CD64E29A704F13688DB206F7F337685 +PT=25D6728244F28F79D1BC707BE94ECA13 + +I=326 +KEY=7FB45D09003B25EFEB5F68CCB7E09C008085E8B56F4E0C8532DBB2FA926FBE06 +IV=ABF3C703F2A1D2FBB59C9345491827A7 +CT=25D6728244F28F79D1BC707BE94ECA13 +PT=47AF03717893A10D7F40D5A3D9B82534 + +I=327 +KEY=35EE9428D4EC49EC103EDF32F4FBEE16C72AEBC417DDAD884D9B67594BD79B32 +IV=4A5AC921D4D76C03FB61B7FE431B7216 +CT=47AF03717893A10D7F40D5A3D9B82534 +PT=B6C25C0E4CA560707588321AAF41119C + +I=328 +KEY=B12C0149A6EDD2DC3742D10822FEDDF771E8B7CA5B78CDF838135543E4968AAE +IV=84C2956172019B30277C0E3AD60533E1 +CT=B6C25C0E4CA560707588321AAF41119C +PT=09137DF5460434E863647B4B50E17A60 + +I=329 +KEY=CFEC596CE216B14A955E7CBC095C198678FBCA3F1D7CF9105B772E08B477F0CE +IV=7EC0582544FB6396A21CADB42BA2C471 +CT=09137DF5460434E863647B4B50E17A60 +PT=17A26688B271E9765F41C71CD8CF0C25 + +I=330 +KEY=35903FF91CC199C048C6C031AA2F4FC96F59ACB7AF0D10660436E9146CB8FCEB +IV=FA7C6695FED7288ADD98BC8DA373564F +CT=17A26688B271E9765F41C71CD8CF0C25 +PT=62E3C4D53DECB83FCD5F57D1971D58FB + +I=331 +KEY=F262476804B79C1F85FEB875CCD5FC3E0DBA686292E1A859C969BEC5FBA5A410 +IV=C7F27891187605DFCD38784466FAB3F7 +CT=62E3C4D53DECB83FCD5F57D1971D58FB +PT=3495C5855D819B6FF779FC7AC59BEB53 + +I=332 +KEY=DC61E5CFC9BAE6B23B894486AD478ADD392FADE7CF6033363E1042BF3E3E4F43 +IV=2E03A2A7CD0D7AADBE77FCF3619276E3 +CT=3495C5855D819B6FF779FC7AC59BEB53 +PT=7440ABE9E1374208CFBCCC18ADC6089F + +I=333 +KEY=C9D2E747A1A6D594CCAE434B7605C8FB4D6F060E2E57713EF1AC8EA793F847DC +IV=15B30288681C3326F72707CDDB424226 +CT=7440ABE9E1374208CFBCCC18ADC6089F +PT=B6802F0F62A28AF7326CDB2144E8DE87 + +I=334 +KEY=99FEF610CFFFACBE8C6AD0A2B0C8F8A7FBEF29014CF5FBC9C3C05586D710995B +IV=502C11576E59792A40C493E9C6CD305C +CT=B6802F0F62A28AF7326CDB2144E8DE87 +PT=B84D7D91E60C131F6F042D403D85C47B + +I=335 +KEY=91EB2713A930B6A53993029D5A056B4143A25490AAF9E8D6ACC478C6EA955D20 +IV=0815D10366CF1A1BB5F9D23FEACD93E6 +CT=B84D7D91E60C131F6F042D403D85C47B +PT=4DDF64827A16F90B5E6B306E8F227DB7 + +I=336 +KEY=C15019D3523304CC9231B33C53C7FE1E0E7D3012D0EF11DDF2AF48A865B72097 +IV=50BB3EC0FB03B269ABA2B1A109C2955F +CT=4DDF64827A16F90B5E6B306E8F227DB7 +PT=FDF6E5B6486E11839EB3A7F5C3898F54 + +I=337 +KEY=E24B749901384F48B2E740C51175E311F38BD5A49881005E6C1CEF5DA63EAFC3 +IV=231B6D4A530B4B8420D6F3F942B21D0F +CT=FDF6E5B6486E11839EB3A7F5C3898F54 +PT=841EF37B4AF82CC5EB00E11775079D81 + +I=338 +KEY=44B7FFFA042DCA1BF276D4911D4B0BE2779526DFD2792C9B871C0E4AD3393242 +IV=A6FC8B6305158553409194540C3EE8F3 +CT=841EF37B4AF82CC5EB00E11775079D81 +PT=1725AF7F70B65FBB060D29B3BCDF0A31 + +I=339 +KEY=B724B2CD569E436B20594E10576934BF60B089A0A2CF7320811127F96FE63873 +IV=F3934D3752B38970D22F9A814A223F5D +CT=1725AF7F70B65FBB060D29B3BCDF0A31 +PT=2CCC6D09954E5FE6C6A87E18950EED02 + +I=340 +KEY=E9EB02E31CABD14DFF231F1F649294044C7CE4A937812CC647B959E1FAE8D571 +IV=5ECFB02E4A359226DF7A510F33FBA0BB +CT=2CCC6D09954E5FE6C6A87E18950EED02 +PT=C82C82AF68EACE2AF22C3266F898F573 + +I=341 +KEY=90C8F71B05BE122AFE5D58A7A1AAB666845066065F6BE2ECB5956B8702702002 +IV=7923F5F81915C367017E47B8C5382262 +CT=C82C82AF68EACE2AF22C3266F898F573 +PT=377F6966928959F2D68F3A2BD0EA3735 + +I=342 +KEY=1BE70B607CF9A9E35DF916C4CC103FEBB32F0F60CDE2BB1E631A51ACD29A1737 +IV=8B2FFC7B7947BBC9A3A44E636DBA898D +CT=377F6966928959F2D68F3A2BD0EA3735 +PT=3A8CCF4943B9866A9ABBEC0BA46F25DB + +I=343 +KEY=631B2C30FEA26433F0CBCD01B1CE974089A3C0298E5B3D74F9A1BDA776F532EC +IV=78FC2750825BCDD0AD32DBC57DDEA8AB +CT=3A8CCF4943B9866A9ABBEC0BA46F25DB +PT=3B767EAB7F0C2D24BBE5565E93DC3E24 + +I=344 +KEY=8785E70A8CD45A8FE1E4382DC62D563DB2D5BE82F15710504244EBF9E5290CC8 +IV=E49ECB3A72763EBC112FF52C77E3C17D +CT=3B767EAB7F0C2D24BBE5565E93DC3E24 +PT=619610C6A4A8E9B196E65D2E5D463968 + +I=345 +KEY=B49BAD1E8EB8B9CF7F32048A81E5BCD3D343AE4455FFF9E1D4A2B6D7B86F35A0 +IV=331E4A14026CE3409ED63CA747C8EAEE +CT=619610C6A4A8E9B196E65D2E5D463968 +PT=F12AF66580B33C3113C45CF5EFD52F4F + +I=346 +KEY=3C92453C6342B6CDC18BFE05241EB5D922695821D54CC5D0C766EA2257BA1AEF +IV=8809E822EDFA0F02BEB9FA8FA5FB090A +CT=F12AF66580B33C3113C45CF5EFD52F4F +PT=A427E0B2CD34285167999A9F18295D26 + +I=347 +KEY=24A1F21CA68CF23F1674BF5328219987864EB8931878ED81A0FF70BD4F9347C9 +IV=1833B720C5CE44F2D7FF41560C3F2C5E +CT=A427E0B2CD34285167999A9F18295D26 +PT=85F5855ACB2741070E1C89F904CBDBEA + +I=348 +KEY=B5479F4D4A0DBBFFBF86C576009F241403BB3DC9D35FAC86AEE3F9444B589C23 +IV=91E66D51EC8149C0A9F27A2528BEBD93 +CT=85F5855ACB2741070E1C89F904CBDBEA +PT=295D7A02348A185F5C54113C734E9003 + +I=349 +KEY=AA9CE82B0B649063C874699C71E8A94E2AE647CBE7D5B4D9F2B7E87838160C20 +IV=1FDB776641692B9C77F2ACEA71778D5A +CT=295D7A02348A185F5C54113C734E9003 +PT=E466F369B840296AAB1A24ED32A19F51 + +I=350 +KEY=A2BA72E2906E04C42C0047EF222FFFE6CE80B4A25F959DB359ADCC950AB79371 +IV=08269AC99B0A94A7E4742E7353C756A8 +CT=E466F369B840296AAB1A24ED32A19F51 +PT=099CEB8099DD025E4A57015168F75388 + +I=351 +KEY=EA9B425CCD937976EB04693F16C4DAC4C71C5F22C6489FED13FACDC46240C0F9 +IV=482130BE5DFD7DB2C7042ED034EB2522 +CT=099CEB8099DD025E4A57015168F75388 +PT=E40CD2C0A7E7CB35C64AEB396338A801 + +I=352 +KEY=D31BCE56BA19A7CB6057C5F2CCB3786223108DE261AF54D8D5B026FD017868F8 +IV=39808C0A778ADEBD8B53ACCDDA77A2A6 +CT=E40CD2C0A7E7CB35C64AEB396338A801 +PT=12E94732A52D15C624A8E554AB54C9A4 + +I=353 +KEY=F0CD039C509E0EFF71B18AE3FEEB186D31F9CAD0C482411EF118C3A9AA2CA15C +IV=23D6CDCAEA87A93411E64F113258600F +CT=12E94732A52D15C624A8E554AB54C9A4 +PT=241C32C2C0C5C6CBE4BB354C054C68D7 + +I=354 +KEY=0579BEABF73DD177C1F1F0827DA20BA115E5F812044787D515A3F6E5AF60C98B +IV=F5B4BD37A7A3DF88B0407A61834913CC +CT=241C32C2C0C5C6CBE4BB354C054C68D7 +PT=E4EA5643CF19EF64820A1B591DE1C378 + +I=355 +KEY=99C7C61F7153FFA0F07380D052431667F10FAE51CB5E68B197A9EDBCB2810AF3 +IV=9CBE78B4866E2ED7318270522FE11DC6 +CT=E4EA5643CF19EF64820A1B591DE1C378 +PT=BC86D5465171B667CE837F874D933FF4 + +I=356 +KEY=C2A65A0A2E71F6E7E2BD9FBB5049F7914D897B179A2FDED6592A923BFF123507 +IV=5B619C155F22094712CE1F6B020AE1F6 +CT=BC86D5465171B667CE837F874D933FF4 +PT=EEB9DC4EBD27720AD3527A1323D85413 + +I=357 +KEY=B635E7EFD987991CD29414B3EBAB2EA4A330A7592708ACDC8A78E828DCCA6114 +IV=7493BDE5F7F66FFB30298B08BBE2D935 +CT=EEB9DC4EBD27720AD3527A1323D85413 +PT=78591E006B877AC6880834E3F98FD6B0 + +I=358 +KEY=F5849125E52B6DF3CD8144DDB64178DDDB69B9594C8FD61A0270DCCB2545B7A4 +IV=43B176CA3CACF4EF1F15506E5DEA5679 +CT=78591E006B877AC6880834E3F98FD6B0 +PT=8F9A67CF96F4608D56923CB267855F3F + +I=359 +KEY=41885734A072249ADE0091A0AD87F47854F3DE96DA7BB69754E2E07942C0E89B +IV=B40CC611455949691381D57D1BC68CA5 +CT=8F9A67CF96F4608D56923CB267855F3F +PT=1B0B8D9118CBECBA2D5AD17A261F9D56 + +I=360 +KEY=FF1A5B86E3545D9CB01A1222EC99A81C4FF85307C2B05A2D79B8310364DF75CD +IV=BE920CB2432679066E1A8382411E5C64 +CT=1B0B8D9118CBECBA2D5AD17A261F9D56 +PT=6225E63F0C1A5DE00FD63032908A51F3 + +I=361 +KEY=836FB4DC9C17E5AD70404B41CC4A043E2DDDB538CEAA07CD766E0131F455243E +IV=7C75EF5A7F43B831C05A596320D3AC22 +CT=6225E63F0C1A5DE00FD63032908A51F3 +PT=7C66E540C016FB81A345E10331FCAFF3 + +I=362 +KEY=63CA7D0E2675E43626B5311A7BA7131B51BB50780EBCFC4CD52BE032C5A98BCD +IV=E0A5C9D2BA62019B56F57A5BB7ED1725 +CT=7C66E540C016FB81A345E10331FCAFF3 +PT=2F010053D3C59BB8ACB5B13B197A4204 + +I=363 +KEY=6B5C4A2DD70FFF3023B2A775BECF05607EBA502BDD7967F4799E5109DCD3C9C9 +IV=08963723F17A1B060507966FC568167B +CT=2F010053D3C59BB8ACB5B13B197A4204 +PT=8918E06B8619B43E859171A345E246AE + +I=364 +KEY=575661F811B8D8B50980A55848A48949F7A2B0405B60D3CAFC0F20AA99318F67 +IV=3C0A2BD5C6B727852A32022DF66B8C29 +CT=8918E06B8619B43E859171A345E246AE +PT=60FF920A8495AD880459737525C109D6 + +I=365 +KEY=5FACBE49DE8F64786918067E7E361681975D224ADFF57E42F85653DFBCF086B1 +IV=08FADFB1CF37BCCD6098A32636929FC8 +CT=60FF920A8495AD880459737525C109D6 +PT=03F09A2C18DB8BAE5CCC93B9165A1D16 + +I=366 +KEY=9BFDA5803AC1C3004F0B138885DE59FE94ADB866C72EF5ECA49AC066AAAA9BA7 +IV=C4511BC9E44EA778261315F6FBE84F7F +CT=03F09A2C18DB8BAE5CCC93B9165A1D16 +PT=52CB3AF36047F4D14C2EAEE3C3F8AF2A + +I=367 +KEY=614239035D7EF489DE2F88FDB6188EC3C6668295A769013DE8B46E856952348D +IV=FABF9C8367BF378991249B7533C6D73D +CT=52CB3AF36047F4D14C2EAEE3C3F8AF2A +PT=249794B3822BB06708B5D5777D297C40 + +I=368 +KEY=20BEFE90BA9C7EE9CFB1E569FE354258E2F116262542B15AE001BBF2147B48CD +IV=41FCC793E7E28A60119E6D94482DCC9B +CT=249794B3822BB06708B5D5777D297C40 +PT=1836AE59EAE452DAC108618DECD666BD + +I=369 +KEY=E11E8BF6DE253E4FBADEDFD44B34BE15FAC7B87FCFA6E3802109DA7FF8AD2E70 +IV=C1A0756664B940A6756F3ABDB501FC4D +CT=1836AE59EAE452DAC108618DECD666BD +PT=20EE84DEB0E7B0C83D74CE251AA1615C + +I=370 +KEY=D519038D457B4BCD9DD50C8F64FE2F2ADA293CA17F4153481C7D145AE20C4F2C +IV=3407887B9B5E7582270BD35B2FCA913F +CT=20EE84DEB0E7B0C83D74CE251AA1615C +PT=6FA7D3584A2E4B803AC1AC07B09931A2 + +I=371 +KEY=82F1611CFB9E7AF9F9274C6BF1B96BEBB58EEFF9356F18C826BCB85D52957E8E +IV=57E86291BEE5313464F240E4954744C1 +CT=6FA7D3584A2E4B803AC1AC07B09931A2 +PT=A7B8F8AC07BAB843F4E7942A6E4A85D5 + +I=372 +KEY=DFF5A6DE8ADE9AB78CF1E637F44FD3351236175532D5A08BD25B2C773CDFFB5B +IV=5D04C7C27140E04E75D6AA5C05F6B8DE +CT=A7B8F8AC07BAB843F4E7942A6E4A85D5 +PT=7F3C3702404E6E013474A0AA0EF85527 + +I=373 +KEY=9C6A11136F64F462E7C5CB30049CDA056D0A2057729BCE8AE62F8CDD3227AE7C +IV=439FB7CDE5BA6ED56B342D07F0D30930 +CT=7F3C3702404E6E013474A0AA0EF85527 +PT=7C0C44DC96872DEE0BAC71DDBDCC84E3 + +I=374 +KEY=2C95624ADD9B1E09F13AE579333B22BB1106648BE41CE364ED83FD008FEB2A9F +IV=B0FF7359B2FFEA6B16FF2E4937A7F8BE +CT=7C0C44DC96872DEE0BAC71DDBDCC84E3 +PT=B9E4597C562E9B5C0E6815E64F767CE9 + +I=375 +KEY=CBB3F14A21E49825990B89E7D07BC386A8E23DF7B2327838E3EBE8E6C09D5676 +IV=E7269300FC7F862C68316C9EE340E13D +CT=B9E4597C562E9B5C0E6815E64F767CE9 +PT=4B37A1FD978F50BE9EA482CFBEACFA08 + +I=376 +KEY=65B742FFD29D9B07F3956625AED7382EE3D59C0A25BD28867D4F6A297E31AC7E +IV=AE04B3B5F37903226A9EEFC27EACFBA8 +CT=4B37A1FD978F50BE9EA482CFBEACFA08 +PT=D3406B71FFC847C364199666A808C43A + +I=377 +KEY=6C6A4DE74AF6C443B4F6A1C7DAB4A28E3095F77BDA756F451956FC4FD6396844 +IV=09DD0F18986B5F444763C7E274639AA0 +CT=D3406B71FFC847C364199666A808C43A +PT=94744ECE39108CB8084DF8A17C49CDCC + +I=378 +KEY=AD09E82AFAA9F5168CD9B83F44C096A0A4E1B9B5E365E3FD111B04EEAA70A588 +IV=C163A5CDB05F3155382F19F89E74342E +CT=94744ECE39108CB8084DF8A17C49CDCC +PT=45EF43A20D7F174DA1463DDA678BBFFB + +I=379 +KEY=DC29CBF4E8B92311A9AA788C437A8EDDE10EFA17EE1AF4B0B05D3934CDFB1A73 +IV=712023DE1210D6072573C0B307BA187D +CT=45EF43A20D7F174DA1463DDA678BBFFB +PT=4480FB073AA197507E376C56B824C753 + +I=380 +KEY=93308B36D3A2E1A952B96FE4687B2DF9A58E0110D4BB63E0CE6A556275DFDD20 +IV=4F1940C23B1BC2B8FB1317682B01A324 +CT=4480FB073AA197507E376C56B824C753 +PT=C8BBB77D206EF37C7C40DB175D105271 + +I=381 +KEY=9682C995955D18471758C504201E93AC6D35B66DF4D5909CB22A8E7528CF8F51 +IV=05B242A346FFF9EE45E1AAE04865BE55 +CT=C8BBB77D206EF37C7C40DB175D105271 +PT=50C0B9001C716D53470FC9B011191402 + +I=382 +KEY=60854B33BE79B0E631B1AF9046C46D153DF50F6DE8A4FDCFF52547C539D69B53 +IV=F60782A62B24A8A126E96A9466DAFEB9 +CT=50C0B9001C716D53470FC9B011191402 +PT=8DB5367A34C5E5B93486AB07CA8BB02E + +I=383 +KEY=7EE74E63D01F31D44B3860471B0BE50FB0403917DC611876C1A3ECC2F35D2B7D +IV=1E6205506E6681327A89CFD75DCF881A +CT=8DB5367A34C5E5B93486AB07CA8BB02E +PT=4F9B922C88C1750829D9088F16EDB529 + +I=384 +KEY=A65EE6CE576182F487D2C21C4F8539F3FFDBAB3B54A06D7EE87AE44DE5B09E54 +IV=D8B9A8AD877EB320CCEAA25B548EDCFC +CT=4F9B922C88C1750829D9088F16EDB529 +PT=05A705F6B55D3ACF3E95E8264FEFFDCC + +I=385 +KEY=64F9A7DF5DA898C968746F96692F1892FA7CAECDE1FD57B1D6EF0C6BAA5F6398 +IV=C2A741110AC91A3DEFA6AD8A26AA2161 +CT=05A705F6B55D3ACF3E95E8264FEFFDCC +PT=D1FB7C1A698990AC81068D08BE1CE91F + +I=386 +KEY=019663655974433AD5731BC4388A067D2B87D2D78874C71D57E9816314438A87 +IV=656FC4BA04DCDBF3BD07745251A51EEF +CT=D1FB7C1A698990AC81068D08BE1CE91F +PT=A1CD24AAFCEE3A60A025B983D10D8E54 + +I=387 +KEY=16EF87A84F0627345CED6385A62374778A4AF67D749AFD7DF7CC38E0C54E04D3 +IV=1779E4CD1672640E899E78419EA9720A +CT=A1CD24AAFCEE3A60A025B983D10D8E54 +PT=B9064D063D2C8D8D935B53CBEF3224E2 + +I=388 +KEY=80931C61E23BA976FFC9288F74AD876D334CBB7B49B670F064976B2B2A7C2031 +IV=967C9BC9AD3D8E42A3244B0AD28EF31A +CT=B9064D063D2C8D8D935B53CBEF3224E2 +PT=8AD3B2222D84A4B25DC1311378027207 + +I=389 +KEY=227ACE0315678DEE433049D8CDFEE2D8B99F09596432D44239565A38527E5236 +IV=A2E9D262F75C2498BCF96157B95365B5 +CT=8AD3B2222D84A4B25DC1311378027207 +PT=3A7FC9D43F1F997FAF4931101C5B5FD4 + +I=390 +KEY=11799A22D50C53A89EDF396B7C7565AD83E0C08D5B2D4D3D961F6B284E250DE2 +IV=33035421C06BDE46DDEF70B3B18B8775 +CT=3A7FC9D43F1F997FAF4931101C5B5FD4 +PT=930860056FE2FDDC10059D09385C0415 + +I=391 +KEY=58DE85D9975D5F8A16C47C834568EF1D10E8A08834CFB0E1861AF621767909F7 +IV=49A71FFB42510C22881B45E8391D8AB0 +CT=930860056FE2FDDC10059D09385C0415 +PT=F41CCB823840FF7D16C6990A14E591D9 + +I=392 +KEY=3C8567CD05AF33761FE05FBDC2596EBFE4F46B0A0C8F4F9C90DC6F2B629C982E +IV=645BE21492F26CFC0924233E873181A2 +CT=F41CCB823840FF7D16C6990A14E591D9 +PT=82899B698456363C175791B845D5736F + +I=393 +KEY=F50F05CBDDFEBE7A656EE5C08CC24FF5667DF06388D979A0878BFE932749EB41 +IV=C98A6206D8518D0C7A8EBA7D4E9B214A +CT=82899B698456363C175791B845D5736F +PT=CF85BFDA1DFF5ADFFAF1B3E000B407F3 + +I=394 +KEY=B44AA91A374D1C5A7BD00557CBD24962A9F84FB99526237F7D7A4D7327FDECB2 +IV=4145ACD1EAB3A2201EBEE09747100697 +CT=CF85BFDA1DFF5ADFFAF1B3E000B407F3 +PT=34EEA75CC20C6EDEE9A5379C3B5CF01A + +I=395 +KEY=4C401127C0AFABBEA4C93FD80BA009CC9D16E8E5572A4DA194DF7AEF1CA11CA8 +IV=F80AB83DF7E2B7E4DF193A8FC07240AE +CT=34EEA75CC20C6EDEE9A5379C3B5CF01A +PT=27C6392ABE790B448CC9216B3FCF5454 + +I=396 +KEY=44D59CB8EBCC91362462D1D8FE193270BAD0D1CFE95346E518165B84236E48FC +IV=08958D9F2B633A8880ABEE00F5B93BBC +CT=27C6392ABE790B448CC9216B3FCF5454 +PT=2C39AC10C7D51B61D8F437D9BAA24A55 + +I=397 +KEY=E42795DA2BF8FA7A3B0E83923A5E243196E97DDF2E865D84C0E26C5D99CC02A9 +IV=A0F20962C0346B4C1F6C524AC4471641 +CT=2C39AC10C7D51B61D8F437D9BAA24A55 +PT=F828BC735827C106E61F8FFFE9453A77 + +I=398 +KEY=7F05DC0CD80178018D3A90E4A0CE63156EC1C1AC76A19C8226FDE3A2708938DE +IV=9B2249D6F3F9827BB63413769A904724 +CT=F828BC735827C106E61F8FFFE9453A77 +PT=DF8129A79852FEE2A8015A2379A7215B + +I=399 +KEY=935560C6072D897477D71AC4C12188D0B140E80BEEF362608EFCB981092E1985 +IV=EC50BCCADF2CF175FAED8A2061EFEBC5 +CT=DF8129A79852FEE2A8015A2379A7215B +PT=CD6429CF3F81F8B4F82BC627A8283096 + +=========== \ No newline at end of file diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/test/cbc_e_m.txt b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/cbc_e_m.txt new file mode 100644 index 00000000..cd344785 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/cbc_e_m.txt @@ -0,0 +1,7224 @@ + +========================= + +FILENAME: "cbc_e_m.txt" + +Cipher Block Chaining (CBC) Mode - ENCRYPTION +Monte Carlo Test + +Algorithm Name: Rijndael +Principal Submitter: Joan Daemen + +========== + +KEYSIZE=128 + +I=0 +KEY=00000000000000000000000000000000 +IV=00000000000000000000000000000000 +PT=00000000000000000000000000000000 +CT=8A05FC5E095AF4848A08D328D3688E3D + +I=1 +KEY=8A05FC5E095AF4848A08D328D3688E3D +IV=8A05FC5E095AF4848A08D328D3688E3D +PT=204F17E2444381F6114FF53934C0BCD3 +CT=192D9B3AA10BB2F7846CCBA0085C657A + +I=2 +KEY=93286764A85146730E641888DB34EB47 +IV=192D9B3AA10BB2F7846CCBA0085C657A +PT=983BF6F5A6DFBCDAA19370666E83A99A +CT=40D8DAF6D1FDA0A073B3BD18B7695D2E + +I=3 +KEY=D3F0BD9279ACE6D37DD7A5906C5DB669 +IV=40D8DAF6D1FDA0A073B3BD18B7695D2E +PT=C48CD503A21C8AD0B2483EF15F79571D +CT=3EDBE80D69A1D2248CA55FC17C4EF3C5 + +I=4 +KEY=ED2B559F100D34F7F172FA51101345AC +IV=3EDBE80D69A1D2248CA55FC17C4EF3C5 +PT=6A49A07B90CE830C20BC239646D936C0 +CT=D87891CF573C99EAE4349A70CA099415 + +I=5 +KEY=3553C4504731AD1D15466021DA1AD1B9 +IV=D87891CF573C99EAE4349A70CA099415 +PT=0ACB9A969946F523317BB932CE1561A4 +CT=24E8F1013F479BBE655DF088C9316BC7 + +I=6 +KEY=11BB3551787636A3701B90A9132BBA7E +IV=24E8F1013F479BBE655DF088C9316BC7 +PT=3DFC8683C1D626A26E2513EB747E8B0F +CT=2C92E80D8D1F70B411C28BD9FDABF21D + +I=7 +KEY=3D29DD5CF569461761D91B70EE804863 +IV=2C92E80D8D1F70B411C28BD9FDABF21D +PT=FAE2D6A36DBD17199F257643C89EB608 +CT=A61810A2798A70A9D2B37E88DEF9AE0F + +I=8 +KEY=9B31CDFE8CE336BEB36A65F83079E66C +IV=A61810A2798A70A9D2B37E88DEF9AE0F +PT=CB97F090318A6B10F5044EB8333ECDD6 +CT=0034FA480DE6F65D98D30B026118718F + +I=9 +KEY=9B0537B68105C0E32BB96EFA516197E3 +IV=0034FA480DE6F65D98D30B026118718F +PT=1B8030AC682BA677A7A3ACDC7FB33BB6 +CT=BEA24548CBC4A6630C9F1251F2C3DC51 + +I=10 +KEY=25A772FE4AC1668027267CABA3A24BB2 +IV=BEA24548CBC4A6630C9F1251F2C3DC51 +PT=D0524282C9AC395508CB2991822E8F42 +CT=4F278DD0B06CBFBAA928635E7CA81B68 + +I=11 +KEY=6A80FF2EFAADD93A8E0E1FF5DF0A50DA +IV=4F278DD0B06CBFBAA928635E7CA81B68 +PT=49EA900E2F61DF8CDEA7D479F59C4C30 +CT=EDFF930BB183F8DAC2FC0BD01AD65882 + +I=12 +KEY=877F6C254B2E21E04CF21425C5DC0858 +IV=EDFF930BB183F8DAC2FC0BD01AD65882 +PT=A1BBEB4E44EF725497B8C589192CC900 +CT=A6FE530E9509D48BAF30F601D04DB19D + +I=13 +KEY=21813F2BDE27F56BE3C2E2241591B9C5 +IV=A6FE530E9509D48BAF30F601D04DB19D +PT=4AD71402771A83F41F7E3AC004150CB7 +CT=FF1148A2E07401F7291B418D62618B65 + +I=14 +KEY=DE9077893E53F49CCAD9A3A977F032A0 +IV=FF1148A2E07401F7291B418D62618B65 +PT=AC47A1FD3490D6E809D40D4BEB8FF639 +CT=4420D4686F7A4D77A72810E89A5E0DF1 + +I=15 +KEY=9AB0A3E15129B9EB6DF1B341EDAE3F51 +IV=4420D4686F7A4D77A72810E89A5E0DF1 +PT=F22E1865DD87A88238173FC693C382E7 +CT=A4C7DE5DF9E2B6A20A1E22F8D7496ACD + +I=16 +KEY=3E777DBCA8CB0F4967EF91B93AE7559C +IV=A4C7DE5DF9E2B6A20A1E22F8D7496ACD +PT=929EFB34B1C552221B648A3D2C678EC9 +CT=D93DBCCA25FA4D9D8C37B3F107FCFA3C + +I=17 +KEY=E74AC1768D3142D4EBD822483D1BAFA0 +IV=D93DBCCA25FA4D9D8C37B3F107FCFA3C +PT=771C61ABB1E9BAB6F678336C8193307E +CT=75F491C2EA85184ACA3C96B769FA9698 + +I=18 +KEY=92BE50B467B45A9E21E4B4FF54E13938 +IV=75F491C2EA85184ACA3C96B769FA9698 +PT=55E42F98CCED821FE211D29674E77F48 +CT=A9C7536B77265ECBF7AC5ECD1EF5DDE2 + +I=19 +KEY=3B7903DF10920455D648EA324A14E4DA +IV=A9C7536B77265ECBF7AC5ECD1EF5DDE2 +PT=56BC0FA54F6F1E04A9A8893D3964EA68 +CT=3C749BF7EFA55CE924D1B33291C2B586 + +I=20 +KEY=070D9828FF3758BCF2995900DBD6515C +IV=3C749BF7EFA55CE924D1B33291C2B586 +PT=45D9BBBB1F3BB33EE182F09C90B1661C +CT=C4708DBAEBD202CDD2054DDCB1AF7BAB + +I=21 +KEY=C37D159214E55A71209C14DC6A792AF7 +IV=C4708DBAEBD202CDD2054DDCB1AF7BAB +PT=37765B154264AD781BBE5F5717DE7038 +CT=87457FD2EE747645576A27F46B00EC30 + +I=22 +KEY=44386A40FA912C3477F633280179C6C7 +IV=87457FD2EE747645576A27F46B00EC30 +PT=A7150BBC7BE3837E145AB83E554B49DE +CT=E25743DAD8E627803DA6C5E587C82384 + +I=23 +KEY=A66F299A22770BB44A50F6CD86B1E543 +IV=E25743DAD8E627803DA6C5E587C82384 +PT=173343A8488146FC9E4B59C2DF42BAF3 +CT=0D0A78CD5E3EB40F92FB55351122E92B + +I=24 +KEY=AB6551577C49BFBBD8ABA3F897930C68 +IV=0D0A78CD5E3EB40F92FB55351122E92B +PT=3B68CFE78B5DEA8F5165A2034D8C2823 +CT=1921B523A2F9B5F53C740D451C9FCE0C + +I=25 +KEY=B244E474DEB00A4EE4DFAEBD8B0CC264 +IV=1921B523A2F9B5F53C740D451C9FCE0C +PT=FDDD484B52C7F3A32F4514BEF5A646E3 +CT=6EAC2BB6EDF35C1267FF4F10700F3CD7 + +I=26 +KEY=DCE8CFC23343565C8320E1ADFB03FEB3 +IV=6EAC2BB6EDF35C1267FF4F10700F3CD7 +PT=CDAD592E5467AD1FA1B71D8AC050FCE0 +CT=D9624E40A8C9A2C58ABEDBAEB865DC1F + +I=27 +KEY=058A81829B8AF499099E3A03436622AC +IV=D9624E40A8C9A2C58ABEDBAEB865DC1F +PT=F9E90A4D7A9EF66818004CBC47C8C6EA +CT=DE15C7322B32738BB493E7FA27AFE6E2 + +I=28 +KEY=DB9F46B0B0B88712BD0DDDF964C9C44E +IV=DE15C7322B32738BB493E7FA27AFE6E2 +PT=FE3CC4AE4A13AC8946407CEEE220290B +CT=5822C79D627AD8A0C4975873D62C5E11 + +I=29 +KEY=83BD812DD2C25FB2799A858AB2E59A5F +IV=5822C79D627AD8A0C4975873D62C5E11 +PT=A5106EBD8888CC3A6884AC8E8EA9C97A +CT=F5AD0473A4228662D9F76E7A5ED4DBDD + +I=30 +KEY=7610855E76E0D9D0A06DEBF0EC314182 +IV=F5AD0473A4228662D9F76E7A5ED4DBDD +PT=4F30B073FB95CD0F0317E749F20E7A7D +CT=4B39DA1FA331CFEB1D6713054C6E9474 + +I=31 +KEY=3D295F41D5D1163BBD0AF8F5A05FD5F6 +IV=4B39DA1FA331CFEB1D6713054C6E9474 +PT=4850735E17F01A3B131E1B78B3A6EB96 +CT=32D1BE8640859CFAB16D64CE8795729B + +I=32 +KEY=0FF8E1C795548AC10C679C3B27CAA76D +IV=32D1BE8640859CFAB16D64CE8795729B +PT=A8C4B9E0069935CB046ACBB49C0B1205 +CT=47DC1150929AA9610938CB0CFE92995E + +I=33 +KEY=4824F09707CE23A0055F5737D9583E33 +IV=47DC1150929AA9610938CB0CFE92995E +PT=13F5DA56D399A7DAA004D0BE76845E68 +CT=BCA6BD8971837B8A81B923E5B2ED0D83 + +I=34 +KEY=F4824D1E764D582A84E674D26BB533B0 +IV=BCA6BD8971837B8A81B923E5B2ED0D83 +PT=8397C79E02FDFE6B7D47FA0181EA453A +CT=23D991B7DA5E96966830E7B40B5A2D8A + +I=35 +KEY=D75BDCA9AC13CEBCECD6936660EF1E3A +IV=23D991B7DA5E96966830E7B40B5A2D8A +PT=18987E5504E23C0F862BCA8DFFC2B07F +CT=17AA31C49F584DEF77C8E7891B11652B + +I=36 +KEY=C0F1ED6D334B83539B1E74EF7BFE7B11 +IV=17AA31C49F584DEF77C8E7891B11652B +PT=A34D44CC1C6E171D7D48447F87E2F2C1 +CT=DD1F90F66D4062E6823F0F229562D110 + +I=37 +KEY=1DEE7D9B5E0BE1B519217BCDEE9CAA01 +IV=DD1F90F66D4062E6823F0F229562D110 +PT=C9793582E22B8840BBAA3D7669208CCC +CT=8F5B876777F7CA903B1D6346AA8BDAE7 + +I=38 +KEY=92B5FAFC29FC2B25223C188B441770E6 +IV=8F5B876777F7CA903B1D6346AA8BDAE7 +PT=730EACFEE3817A94B88117ABB3F9CDE4 +CT=388780BA989C0A8BB5BD9E4086D91EF7 + +I=39 +KEY=AA327A46B16021AE978186CBC2CE6E11 +IV=388780BA989C0A8BB5BD9E4086D91EF7 +PT=F004D3A14C6C94FA2D39BE0C71119658 +CT=7F4C33E4F5C055C05DB4B7691061B307 + +I=40 +KEY=D57E49A244A0746ECA3531A2D2AFDD16 +IV=7F4C33E4F5C055C05DB4B7691061B307 +PT=575F86A5D1637CB86449F8BC0F1573D3 +CT=F6FE1919F174065AB31AC43E0D733A81 + +I=41 +KEY=238050BBB5D47234792FF59CDFDCE797 +IV=F6FE1919F174065AB31AC43E0D733A81 +PT=14F8E2DB61B05E094CA4C0E9DA7800EE +CT=4CB876F2DC169F955E639C6C916340A6 + +I=42 +KEY=6F38264969C2EDA1274C69F04EBFA731 +IV=4CB876F2DC169F955E639C6C916340A6 +PT=F88BA2E4AA4ABDD381778DFD1DA1856F +CT=AEEB80B469D89E45BC3426B6CCC50440 + +I=43 +KEY=C1D3A6FD001A73E49B784F46827AA371 +IV=AEEB80B469D89E45BC3426B6CCC50440 +PT=195F74019B65C0F7D724491BDE8C8B88 +CT=2FD7CCDBDB2B2037C104F0A707A11EDA + +I=44 +KEY=EE046A26DB3153D35A7CBFE185DBBDAB +IV=2FD7CCDBDB2B2037C104F0A707A11EDA +PT=FF51887AB5FEC9C97CB61BB2DE9CDBC6 +CT=8DF7BB99B781C63F4F8B2A7D5DFF2960 + +I=45 +KEY=63F3D1BF6CB095EC15F7959CD82494CB +IV=8DF7BB99B781C63F4F8B2A7D5DFF2960 +PT=A35AAB0055E99FA980D59B242B8C6257 +CT=7D96ECC20571E9E85C16E3BDADA374CA + +I=46 +KEY=1E653D7D69C17C0449E176217587E001 +IV=7D96ECC20571E9E85C16E3BDADA374CA +PT=02CC392194874CD531025588C96E2D22 +CT=AA1DC2E69CE582DFA9A1B435854FCBB1 + +I=47 +KEY=B478FF9BF524FEDBE040C214F0C82BB0 +IV=AA1DC2E69CE582DFA9A1B435854FCBB1 +PT=94CC5DB118EF53C904B0EEC23AC650FD +CT=DA0CA33BCCE4ABA1936833127D1F5E25 + +I=48 +KEY=6E745CA039C0557A7328F1068DD77595 +IV=DA0CA33BCCE4ABA1936833127D1F5E25 +PT=52F009E929526E923BE4F43B66876725 +CT=B5E80FF4DADD69BB7493B9F72A752811 + +I=49 +KEY=DB9C5354E31D3CC107BB48F1A7A25D84 +IV=B5E80FF4DADD69BB7493B9F72A752811 +PT=6B88B42E99E5B4F838064A711B71DE1F +CT=5CDDCE45516C6D1654647A1A541AC435 + +I=50 +KEY=87419D11B27151D753DF32EBF3B899B1 +IV=5CDDCE45516C6D1654647A1A541AC435 +PT=9E25CBDD8E2D7D68FF72932E35879175 +CT=3C7E88A9A6462D08ADA5910A3FCE611A + +I=51 +KEY=BB3F15B814377CDFFE7AA3E1CC76F8AB +IV=3C7E88A9A6462D08ADA5910A3FCE611A +PT=72A4EF1D82A3AC5C1DFDF8C4DCFB9F6E +CT=E428200E1C3BE9A5141F73590B7473B8 + +I=52 +KEY=5F1735B6080C957AEA65D0B8C7028B13 +IV=E428200E1C3BE9A5141F73590B7473B8 +PT=7CD8053F2FD743A44CC39F75C1E81075 +CT=AB3B8A79653E884053AFC8C14504AF77 + +I=53 +KEY=F42CBFCF6D321D3AB9CA187982062464 +IV=AB3B8A79653E884053AFC8C14504AF77 +PT=0731077A8B6854CB90AFFAE3A3B199C4 +CT=53B7DFD6D12DDE7966C62FCC1946A4AC + +I=54 +KEY=A79B6019BC1FC343DF0C37B59B4080C8 +IV=53B7DFD6D12DDE7966C62FCC1946A4AC +PT=E4E26CA1DA697F30E0542763313A79B7 +CT=6DEC201BBB90B66A3B2DFF4FA1DDF7C4 + +I=55 +KEY=CA774002078F7529E421C8FA3A9D770C +IV=6DEC201BBB90B66A3B2DFF4FA1DDF7C4 +PT=C2CF11681C4767A78B2F95AFB50CF155 +CT=F535B7CD4135A39E0E344BD2CFA14B83 + +I=56 +KEY=3F42F7CF46BAD6B7EA158328F53C3C8F +IV=F535B7CD4135A39E0E344BD2CFA14B83 +PT=606618948C1ED454B9B0F92435381D2D +CT=209AC483682C48AA197BB64417127656 + +I=57 +KEY=1FD8334C2E969E1DF36E356CE22E4AD9 +IV=209AC483682C48AA197BB64417127656 +PT=8F8A70AADF2F8BFB5E137F86AC83D32F +CT=76F5F43A888D7F22D698A73810ED5B15 + +I=58 +KEY=692DC776A61BE13F25F69254F2C311CC +IV=76F5F43A888D7F22D698A73810ED5B15 +PT=E9E8AEBF16A5F4E1C26B4A385163E844 +CT=625C62F33C9548F2651FB0A08BF45286 + +I=59 +KEY=0B71A5859A8EA9CD40E922F47937434A +IV=625C62F33C9548F2651FB0A08BF45286 +PT=C69CFD36C50EBA06E3B3C4AB7C9B694E +CT=3931CE6DF783063F26920D4048B00C82 + +I=60 +KEY=32406BE86D0DAFF2667B2FB431874FC8 +IV=3931CE6DF783063F26920D4048B00C82 +PT=5DFE322DD692BA8DD9CD328A5AF9A3B7 +CT=A3CA3ECE725C84281144052A80EA5176 + +I=61 +KEY=918A55261F512BDA773F2A9EB16D1EBE +IV=A3CA3ECE725C84281144052A80EA5176 +PT=4BBD16BF74226F816767A7207C672C9A +CT=94552690A231354F8F9BEF295E55F142 + +I=62 +KEY=05DF73B6BD601E95F8A4C5B7EF38EFFC +IV=94552690A231354F8F9BEF295E55F142 +PT=7055D0C535B2B0501FF6AAEE46E03818 +CT=771908987F00C2D822897E7EEA148F29 + +I=63 +KEY=72C67B2EC260DC4DDA2DBBC9052C60D5 +IV=771908987F00C2D822897E7EEA148F29 +PT=7336B9D4977BDDA811C0C5EBEA539574 +CT=7AA84598115B181863081AFCC239EDD2 + +I=64 +KEY=086E3EB6D33BC455B925A135C7158D07 +IV=7AA84598115B181863081AFCC239EDD2 +PT=5296C8546532BAEACBEC9F29916FB6B2 +CT=3D95967035AF639B2D2814DEB9B7F86A + +I=65 +KEY=35FBA8C6E694A7CE940DB5EB7EA2756D +IV=3D95967035AF639B2D2814DEB9B7F86A +PT=430880F5576C7783BC1336F900DDD037 +CT=4D70AAD2FC9EF403B463A72DB4CFE640 + +I=66 +KEY=788B02141A0A53CD206E12C6CA6D932D +IV=4D70AAD2FC9EF403B463A72DB4CFE640 +PT=E489B93778DE0C42FEFB6122ECA46BDC +CT=165DDB405546934E81CB6B0B89B4A40E + +I=67 +KEY=6ED6D9544F4CC083A1A579CD43D93723 +IV=165DDB405546934E81CB6B0B89B4A40E +PT=8E5481ACD58BFC5D141C1F71CDE91E37 +CT=693775A3661CE9D0E4CB4888431C64A5 + +I=68 +KEY=07E1ACF729502953456E314500C55386 +IV=693775A3661CE9D0E4CB4888431C64A5 +PT=4AAA5E507EFB9FAD15E5F4C77F46AF89 +CT=C42391D50B1210C67B6AD642745A4DAC + +I=69 +KEY=C3C23D22224239953E04E707749F1E2A +IV=C42391D50B1210C67B6AD642745A4DAC +PT=4E0748F8716801B099494037485B8BA4 +CT=A4CB7F010AC42B4C3C14F02353F3644A + +I=70 +KEY=67094223288612D902101724276C7A60 +IV=A4CB7F010AC42B4C3C14F02353F3644A +PT=0B7B41D57885DB37A2FC355C8D03FF3C +CT=1BB0CBD24537B36EB555BE8C0FEC3A1F + +I=71 +KEY=7CB989F16DB1A1B7B745A9A82880407F +IV=1BB0CBD24537B36EB555BE8C0FEC3A1F +PT=4696F9A564354194142AB7B8630B4279 +CT=18B10BAE39D4FA58F586A067A8E38BC5 + +I=72 +KEY=6408825F54655BEF42C309CF8063CBBA +IV=18B10BAE39D4FA58F586A067A8E38BC5 +PT=0B59EBABAB994F2DDB3DE383454BECE8 +CT=C09C6670B93ECD303BA53DE58DD81A64 + +I=73 +KEY=A494E42FED5B96DF7966342A0DBBD1DE +IV=C09C6670B93ECD303BA53DE58DD81A64 +PT=2F897F3385E71133CEC8367411E830A3 +CT=45EA7CB9119DF7367294F9FE36D4A09F + +I=74 +KEY=E17E9896FCC661E90BF2CDD43B6F7141 +IV=45EA7CB9119DF7367294F9FE36D4A09F +PT=8CDE9D975B51A098F4CAC93DC58C002F +CT=02DDD735439A8AE03E976E629A6C992C + +I=75 +KEY=E3A34FA3BF5CEB093565A3B6A103E86D +IV=02DDD735439A8AE03E976E629A6C992C +PT=1E20571F82C2C6884A6F90A23FD3A925 +CT=B040686B866AE80A88B899031F2F0EE4 + +I=76 +KEY=53E327C839360303BDDD3AB5BE2CE689 +IV=B040686B866AE80A88B899031F2F0EE4 +PT=0851624711970ADE2F456D5DAFB17E05 +CT=201756BC061706513264A3C489D95A0C + +I=77 +KEY=73F471743F2105528FB9997137F5BC85 +IV=201756BC061706513264A3C489D95A0C +PT=E8B1410DE742136E71F54D31FEAA72EB +CT=2EF27C31AA488648FCE0F1804D658092 + +I=78 +KEY=5D060D459569831A735968F17A903C17 +IV=2EF27C31AA488648FCE0F1804D658092 +PT=97E0CA84C9B22C8942C7FC5088EAED04 +CT=7545F1D9C8F5F8B441EDCDAF00462344 + +I=79 +KEY=2843FC9C5D9C7BAE32B4A55E7AD61F53 +IV=7545F1D9C8F5F8B441EDCDAF00462344 +PT=7B5572C09E998656B55C53748CF77C21 +CT=347875EFD6BD978CD1B2EA949F7E2358 + +I=80 +KEY=1C3B89738B21EC22E3064FCAE5A83C0B +IV=347875EFD6BD978CD1B2EA949F7E2358 +PT=A30001AA29D70B0A141B8FC8B9B2E210 +CT=9C956408BA335CCC9F02F31CC45FD5E6 + +I=81 +KEY=80AEED7B3112B0EE7C04BCD621F7E9ED +IV=9C956408BA335CCC9F02F31CC45FD5E6 +PT=839783D75859393B215010F63159FA45 +CT=B70E700F4A7ED08618754960B83BD0F2 + +I=82 +KEY=37A09D747B6C60686471F5B699CC391F +IV=B70E700F4A7ED08618754960B83BD0F2 +PT=1E3C630BC8C34BF8822686043D14E4D6 +CT=4721B6796F82D47D6EEB9CB11A19605E + +I=83 +KEY=70812B0D14EEB4150A9A690783D55941 +IV=4721B6796F82D47D6EEB9CB11A19605E +PT=CEE1B977E8B75623CC4E2C4F4765FE2A +CT=3382E1B076680BBBE7C451582016DD11 + +I=84 +KEY=4303CABD6286BFAEED5E385FA3C38450 +IV=3382E1B076680BBBE7C451582016DD11 +PT=02365457AB60C892A0C34A7067AB7608 +CT=AB581732E06B90AA0C835C1C7B6D18B5 + +I=85 +KEY=E85BDD8F82ED2F04E1DD6443D8AE9CE5 +IV=AB581732E06B90AA0C835C1C7B6D18B5 +PT=222B7ED84C648C12FFDD6E8E13EEC651 +CT=3E2E592CEEAD3B5E16860E80E406E882 + +I=86 +KEY=D67584A36C40145AF75B6AC33CA87467 +IV=3E2E592CEEAD3B5E16860E80E406E882 +PT=7D24BD646EEBA44ED27B11DA42D72FF8 +CT=9163F6DBE0D8BB79A154D92E37A07E1C + +I=87 +KEY=471672788C98AF23560FB3ED0B080A7B +IV=9163F6DBE0D8BB79A154D92E37A07E1C +PT=42B571FFB3275F5A8E26616A3F0E3403 +CT=E1340E61513FE8146F29E111392E2C3A + +I=88 +KEY=A6227C19DDA74737392652FC32262641 +IV=E1340E61513FE8146F29E111392E2C3A +PT=6EFD16D48E03B6E1CD74777ABC891DA8 +CT=3D703B4FD8A8A7F015D0FD47DE0C5A28 + +I=89 +KEY=9B524756050FE0C72CF6AFBBEC2A7C69 +IV=3D703B4FD8A8A7F015D0FD47DE0C5A28 +PT=7956129687AC95397E14821A17F267DE +CT=C5C6D2BAABDBE0B82CDFFFE7A92C8344 + +I=90 +KEY=5E9495ECAED4007F0029505C4506FF2D +IV=C5C6D2BAABDBE0B82CDFFFE7A92C8344 +PT=AC661770332FE0A45B80791C3A5D1241 +CT=6F7BDE1BD17C5B10064B52EB54EE90B0 + +I=91 +KEY=31EF4BF77FA85B6F066202B711E86F9D +IV=6F7BDE1BD17C5B10064B52EB54EE90B0 +PT=1DE0702C81667A979E5E3542DA95C5AD +CT=DC7E35D5B02AFF4B92C190265E01C0F8 + +I=92 +KEY=ED917E22CF82A42494A392914FE9AF65 +IV=DC7E35D5B02AFF4B92C190265E01C0F8 +PT=A491CB4321C757FD353B560C0B3EA4D0 +CT=D753F5A6C5D7E17F4024FD8675B23E7F + +I=93 +KEY=3AC28B840A55455BD4876F173A5B911A +IV=D753F5A6C5D7E17F4024FD8675B23E7F +PT=418FA3B3E9B4E463D04AC3A3361DCA57 +CT=B635529E8080B33E9AD6D79B8203112D + +I=94 +KEY=8CF7D91A8AD5F6654E51B88CB8588037 +IV=B635529E8080B33E9AD6D79B8203112D +PT=C87E4ED505989807D1DBDA4769804EA3 +CT=43E763CD1B9EE4BC474B79C1E0DA2564 + +I=95 +KEY=CF10BAD7914B12D9091AC14D5882A553 +IV=43E763CD1B9EE4BC474B79C1E0DA2564 +PT=042F084454D0EE01AB00D3921E1BCA06 +CT=C799956FF8A7A05B71123EBC4AA09C0C + +I=96 +KEY=08892FB869ECB2827808FFF11222395F +IV=C799956FF8A7A05B71123EBC4AA09C0C +PT=9A8E40400C51A438DCE498AD3455DE51 +CT=76679B0E26B1B6CA2A8D90944777C57F + +I=97 +KEY=7EEEB4B64F5D044852856F655555FC20 +IV=76679B0E26B1B6CA2A8D90944777C57F +PT=227E122D3AF18A3CAA973B33B3356CE7 +CT=B2F52396F02D2DFFE36C5F9238AC1EBE + +I=98 +KEY=CC1B9720BF7029B7B1E930F76DF9E29E +IV=B2F52396F02D2DFFE36C5F9238AC1EBE +PT=0D9CDD97E2FE0E78CF16B1596DC20ABA +CT=7C8EDD3A079835954238E0FE4872AAE1 + +I=99 +KEY=B0954A1AB8E81C22F3D1D009258B487F +IV=7C8EDD3A079835954238E0FE4872AAE1 +PT=925A7ECD233B3B3CCDE2221A03C5F720 +CT=D7C9FD3EF010C8577087591149D5640F + +I=100 +KEY=675CB72448F8D475835689186C5E2C70 +IV=D7C9FD3EF010C8577087591149D5640F +PT=59FEFBE5179F0E7E48F3D97CDA314FF5 +CT=2608CCE6BA917551DEF84FA7BCA9B23C + +I=101 +KEY=41547BC2F269A1245DAEC6BFD0F79E4C +IV=2608CCE6BA917551DEF84FA7BCA9B23C +PT=7F24A1BA8762294194F76322A6B28A16 +CT=EFF1513B52D5D74D2202898AC99552C4 + +I=102 +KEY=AEA52AF9A0BC76697FAC4F351962CC88 +IV=EFF1513B52D5D74D2202898AC99552C4 +PT=79B43F27F3E144C4EFBF383698A1EC90 +CT=B4B3B020D44D059666E86D22072916B5 + +I=103 +KEY=1A169AD974F173FF194422171E4BDA3D +IV=B4B3B020D44D059666E86D22072916B5 +PT=8BF20B60B4774354857BA2979CD396F9 +CT=6F1A3D43CC2171A808AE8D38396DE1D1 + +I=104 +KEY=750CA79AB8D0025711EAAF2F27263BEC +IV=6F1A3D43CC2171A808AE8D38396DE1D1 +PT=74955DDACFB8A5467D069F1EF341248B +CT=47C23A68DA351C22EBF86FDBD8F723B4 + +I=105 +KEY=32CE9DF262E51E75FA12C0F4FFD11858 +IV=47C23A68DA351C22EBF86FDBD8F723B4 +PT=25D7A186ED990020E10A23C5CFB1CEF9 +CT=D5F2E2C2CED730479D87E0AF0FEF8A73 + +I=106 +KEY=E73C7F30AC322E326795205BF03E922B +IV=D5F2E2C2CED730479D87E0AF0FEF8A73 +PT=13480F2EDCCB62B8F9A7DF98238571FC +CT=F29A46A7F1B1D1D4F5FE30E569D7A801 + +I=107 +KEY=15A639975D83FFE6926B10BE99E93A2A +IV=F29A46A7F1B1D1D4F5FE30E569D7A801 +PT=75E138123B5A98596303ACF9DAEEA714 +CT=9F6E9A13913DF78AC67BD20303AF49B5 + +I=108 +KEY=8AC8A384CCBE086C5410C2BD9A46739F +IV=9F6E9A13913DF78AC67BD20303AF49B5 +PT=DBD0AE00FD06761626366EB251412A32 +CT=46AC9F42239B22A163CE0FDEAA103D44 + +I=109 +KEY=CC643CC6EF252ACD37DECD6330564EDB +IV=46AC9F42239B22A163CE0FDEAA103D44 +PT=B8768A8AF461C9547D1F982FE90E96B6 +CT=95D7C8F969B0EEB03FEC257043597315 + +I=110 +KEY=59B3F43F8695C47D0832E813730F3DCE +IV=95D7C8F969B0EEB03FEC257043597315 +PT=3D20CC8AD484048251C7A81C7E3CA59C +CT=6B74AF42435BC640A826EC443207574E + +I=111 +KEY=32C75B7DC5CE023DA014045741086A80 +IV=6B74AF42435BC640A826EC443207574E +PT=BF719F78B23BAFD4A50634BCD9361095 +CT=31E3919F36D79FBF61884227110C10FF + +I=112 +KEY=0324CAE2F3199D82C19C467050047A7F +IV=31E3919F36D79FBF61884227110C10FF +PT=E1D32740BB8B6D67AD3038887899F090 +CT=A1CD90683CE041D6CA20780176FDD5F4 + +I=113 +KEY=A2E95A8ACFF9DC540BBC3E7126F9AF8B +IV=A1CD90683CE041D6CA20780176FDD5F4 +PT=3069EA97F092ACDCF41649377B8FCBC8 +CT=7220F866A10DC711DC1D277B4C8F204D + +I=114 +KEY=D0C9A2EC6EF41B45D7A1190A6A768FC6 +IV=7220F866A10DC711DC1D277B4C8F204D +PT=B0563A5E0EE1E2B96F3F7D04EE39EA7C +CT=CF81CA348B98C532B172F032AE0A6FED + +I=115 +KEY=1F4868D8E56CDE7766D3E938C47CE02B +IV=CF81CA348B98C532B172F032AE0A6FED +PT=B1B78BD75C30DD4E1E198ACB98B498A6 +CT=99C990D64D27D47ED0C1E7F186AC6674 + +I=116 +KEY=8681F80EA84B0A09B6120EC942D0865F +IV=99C990D64D27D47ED0C1E7F186AC6674 +PT=D413E3CC66E9938E4E0CFC1975E38C8C +CT=30C7DAD86FEF77C43A44A3EF8B116354 + +I=117 +KEY=B64622D6C7A47DCD8C56AD26C9C1E50B +IV=30C7DAD86FEF77C43A44A3EF8B116354 +PT=CD85D9334481AE85B8816233CA4AF7DB +CT=9E717B45239DD908138837154B803654 + +I=118 +KEY=28375993E439A4C59FDE9A338241D35F +IV=9E717B45239DD908138837154B803654 +PT=925BA3760D655D5B788802DDE25732BB +CT=4A6E32C01709EBCCC9BCA43FD5DFDFB3 + +I=119 +KEY=62596B53F3304F0956623E0C579E0CEC +IV=4A6E32C01709EBCCC9BCA43FD5DFDFB3 +PT=0AA6264BFCC7BD07FA8F94E1EF739633 +CT=7263392DC9DA868BC0317A6D4AD52553 + +I=120 +KEY=103A527E3AEAC982965344611D4B29BF +IV=7263392DC9DA868BC0317A6D4AD52553 +PT=FB385BD8ECE7C4DFE2351D851141888D +CT=AA49B1DDA3AF4D05D861667E88AD61AB + +I=121 +KEY=BA73E3A3994584874E32221F95E64814 +IV=AA49B1DDA3AF4D05D861667E88AD61AB +PT=510E13E20BB06EAD335F10F2C69831D3 +CT=3AC256A92F69AF35DB05DDCA61CF1EE4 + +I=122 +KEY=80B1B50AB62C2BB29537FFD5F42956F0 +IV=3AC256A92F69AF35DB05DDCA61CF1EE4 +PT=0A07CAA0EC6CB726F1A38847253BECB6 +CT=037497736381429A5E5A139C44A6C64A + +I=123 +KEY=83C52279D5AD6928CB6DEC49B08F90BA +IV=037497736381429A5E5A139C44A6C64A +PT=864FEF67C8902757E2CFB28DA2EF3C8D +CT=5393D7F9F37A5B9F1F82C1BE20435149 + +I=124 +KEY=D056F58026D732B7D4EF2DF790CCC1F3 +IV=5393D7F9F37A5B9F1F82C1BE20435149 +PT=ED2D2A671677067B30540D4C9D86905F +CT=2969AC5FB94EC76209C6DF58F6B8AA01 + +I=125 +KEY=F93F59DF9F99F5D5DD29F2AF66746BF2 +IV=2969AC5FB94EC76209C6DF58F6B8AA01 +PT=67ED14454DAD764C1772BCB1E0527954 +CT=150F94E1940F9D2ACC735F79B0912A06 + +I=126 +KEY=EC30CD3E0B9668FF115AADD6D6E541F4 +IV=150F94E1940F9D2ACC735F79B0912A06 +PT=517A4852F68370EDD879E32F52FD4D2B +CT=6EFD8E4E4C096A2033B3DA8A1F0066AF + +I=127 +KEY=82CD4370479F02DF22E9775CC9E5275B +IV=6EFD8E4E4C096A2033B3DA8A1F0066AF +PT=DBF4CAD912437115658E5BA5E1724739 +CT=899D9126CD85D2D4053AD9EE7156041B + +I=128 +KEY=0B50D2568A1AD00B27D3AEB2B8B32340 +IV=899D9126CD85D2D4053AD9EE7156041B +PT=69B302F96AFCF802AC639EBABC52ECFB +CT=819E4B8319807088FF306E125E52DAD3 + +I=129 +KEY=8ACE99D5939AA083D8E3C0A0E6E1F993 +IV=819E4B8319807088FF306E125E52DAD3 +PT=F5CA57371833F0AF98F0EC02DFE518ED +CT=4DFA3739235D14660DF7D5FDE36F6567 + +I=130 +KEY=C734AEECB0C7B4E5D514155D058E9CF4 +IV=4DFA3739235D14660DF7D5FDE36F6567 +PT=29BBD9264B9792BED8A8EFA43F943A7D +CT=4EA36ECCBCCD9FAFD8FB588BD53826A7 + +I=131 +KEY=8997C0200C0A2B4A0DEF4DD6D0B6BA53 +IV=4EA36ECCBCCD9FAFD8FB588BD53826A7 +PT=149120CFC3D7C671F287AA77A4A3EF97 +CT=0282357C78C8944A5520AF80506DE30D + +I=132 +KEY=8B15F55C74C2BF0058CFE25680DB595E +IV=0282357C78C8944A5520AF80506DE30D +PT=02C2E0CCB12F5216213D493325F38FC3 +CT=C827C36F654137A2BB127D1782285B10 + +I=133 +KEY=43323633118388A2E3DD9F4102F3024E +IV=C827C36F654137A2BB127D1782285B10 +PT=FA1693AD90401791FF9093A562EC66EB +CT=3723A94BC91032BF8DB599ABEFB784D1 + +I=134 +KEY=74119F78D893BA1D6E6806EAED44869F +IV=3723A94BC91032BF8DB599ABEFB784D1 +PT=5410CBE33ABB58AB0B0E86F5817E6F2C +CT=26A520B5B475632EE8806648BFC028AF + +I=135 +KEY=52B4BFCD6CE6D93386E860A25284AE30 +IV=26A520B5B475632EE8806648BFC028AF +PT=B01A11D200C24F4333029DE3BFF49601 +CT=36D5E00E0A53D7CE1498215AFA686905 + +I=136 +KEY=64615FC366B50EFD927041F8A8ECC735 +IV=36D5E00E0A53D7CE1498215AFA686905 +PT=252E4460E9A391D54CE9E516663E59AE +CT=829F0B7B17ED5F2FB7A014A6CD9D8052 + +I=137 +KEY=E6FE54B8715851D225D0555E65714767 +IV=829F0B7B17ED5F2FB7A014A6CD9D8052 +PT=BCC51A6493F6847BEA8219329F67308D +CT=BAB1D358D08DA13BEC485051F2EBFE2E + +I=138 +KEY=5C4F87E0A1D5F0E9C998050F979AB949 +IV=BAB1D358D08DA13BEC485051F2EBFE2E +PT=D89236011B3C2338E95322D4716AEE59 +CT=29BA99F8CF8B48134B1330E75BD7254E + +I=139 +KEY=75F51E186E5EB8FA828B35E8CC4D9C07 +IV=29BA99F8CF8B48134B1330E75BD7254E +PT=21D0EB5857C93A0D4D75253E1020C00E +CT=9D557274FE14AA69673441117A2D7DA2 + +I=140 +KEY=E8A06C6C904A1293E5BF74F9B660E1A5 +IV=9D557274FE14AA69673441117A2D7DA2 +PT=3C3BB454584C4C7570089B6E631BA035 +CT=543EF50A024E77ACE685BD0BBB47232D + +I=141 +KEY=BC9E99669204653F033AC9F20D27C288 +IV=543EF50A024E77ACE685BD0BBB47232D +PT=8ED890BC903AEAC7C3C685980EDB3370 +CT=884BD68868D89DE9DEDB2D95A8B992FB + +I=142 +KEY=34D54FEEFADCF8D6DDE1E467A59E5073 +IV=884BD68868D89DE9DEDB2D95A8B992FB +PT=684DEBD6DEDE24BD0F4F8AFA47F08AEF +CT=DB00984CAEB14CF5A1FDE8E8E9C03830 + +I=143 +KEY=EFD5D7A2546DB4237C1C0C8F4C5E6843 +IV=DB00984CAEB14CF5A1FDE8E8E9C03830 +PT=C42B245443F2695F306455199C7C76FE +CT=0CA808425E8EBDDD5519130F4900329F + +I=144 +KEY=E37DDFE00AE309FE29051F80055E5ADC +IV=0CA808425E8EBDDD5519130F4900329F +PT=1655F89334CCB6ED8E140088997BD2D1 +CT=0DAE2F85CD81874DCD7368277D0C386D + +I=145 +KEY=EED3F065C7628EB3E47677A7785262B1 +IV=0DAE2F85CD81874DCD7368277D0C386D +PT=2B7A2DF6E0CAC83837AFDC8B2134E6A6 +CT=E3BF66A6784432E6CE61B769C3CFDB35 + +I=146 +KEY=0D6C96C3BF26BC552A17C0CEBB9DB984 +IV=E3BF66A6784432E6CE61B769C3CFDB35 +PT=8FED19E77B9690EC8F70272364B4EB74 +CT=473925552401311F24EE4F40B5A3ECB5 + +I=147 +KEY=4A55B3969B278D4A0EF98F8E0E3E5531 +IV=473925552401311F24EE4F40B5A3ECB5 +PT=032D9AF654037E2586B12CF031E4AB4C +CT=E9E1E4ACF3F4E25CB8093F6B27665DFF + +I=148 +KEY=A3B4573A68D36F16B6F0B0E5295808CE +IV=E9E1E4ACF3F4E25CB8093F6B27665DFF +PT=E6EF26B3721F6C772D231584DD480441 +CT=2D9F85D63FED609876DF97F0E6B85564 + +I=149 +KEY=8E2BD2EC573E0F8EC02F2715CFE05DAA +IV=2D9F85D63FED609876DF97F0E6B85564 +PT=E641EBC4A734C71669D948F1BEEE675A +CT=3A61F4BED09FD7A7AED71E9FD53D2EE3 + +I=150 +KEY=B44A265287A1D8296EF8398A1ADD7349 +IV=3A61F4BED09FD7A7AED71E9FD53D2EE3 +PT=36DB43747CD9215857886A0DE2008509 +CT=6BE2AD95F4A642F3FD73D9543B53D479 + +I=151 +KEY=DFA88BC773079ADA938BE0DE218EA730 +IV=6BE2AD95F4A642F3FD73D9543B53D479 +PT=58A73313B31B8C1EB3C144C9363EE94B +CT=BF198D336DF857BFBA069634C25CF45B + +I=152 +KEY=60B106F41EFFCD65298D76EAE3D2536B +IV=BF198D336DF857BFBA069634C25CF45B +PT=E0974E1BBEFE21422ECED27858535F87 +CT=7945132F6F7EED6B61E1CF9C47E2AB2A + +I=153 +KEY=19F415DB7181200E486CB976A430F841 +IV=7945132F6F7EED6B61E1CF9C47E2AB2A +PT=6F36B63A1A8B426282CA4E61B7E37B3A +CT=AF441F330C8C199E9776D92A92B02216 + +I=154 +KEY=B6B00AE87D0D3990DF1A605C3680DA57 +IV=AF441F330C8C199E9776D92A92B02216 +PT=99AD2B814D3A4C0E1C27D4251C55C74A +CT=F34463A538E46E87B0F24EAA36B674A7 + +I=155 +KEY=45F4694D45E957176FE82EF60036AEF0 +IV=F34463A538E46E87B0F24EAA36B674A7 +PT=6D05C19E42D0561C198A10FA55F4C870 +CT=5D54D3C72D55015D0149FA1591208824 + +I=156 +KEY=18A0BA8A68BC564A6EA1D4E3911626D4 +IV=5D54D3C72D55015D0149FA1591208824 +PT=7AA7A04DE8CD21F59BA5369CA175CEC3 +CT=D2EBE35C33210B39CD4F443BB577DBD8 + +I=157 +KEY=CA4B59D65B9D5D73A3EE90D82461FD0C +IV=D2EBE35C33210B39CD4F443BB577DBD8 +PT=2DA2A48FE13FA4DD5271A02FB7F98AEC +CT=2F4AD89C0D915DF978160E9E882AD28E + +I=158 +KEY=E501814A560C008ADBF89E46AC4B2F82 +IV=2F4AD89C0D915DF978160E9E882AD28E +PT=82EB831B9FF9DA7D06553A456133766B +CT=09A04C7CBED3D60ADB6CFDD012DEED17 + +I=159 +KEY=ECA1CD36E8DFD68000946396BE95C295 +IV=09A04C7CBED3D60ADB6CFDD012DEED17 +PT=8D4FD1CE8CB9745E9E65182D94F8307A +CT=193C6FAB40C87C7029983EDD52628400 + +I=160 +KEY=F59DA29DA817AAF0290C5D4BECF74695 +IV=193C6FAB40C87C7029983EDD52628400 +PT=F06A061082E499E65A5DED0D22323F57 +CT=7166BD655D8128E7B09D37B38478B480 + +I=161 +KEY=84FB1FF8F596821799916AF8688FF215 +IV=7166BD655D8128E7B09D37B38478B480 +PT=DCEC808551EA98534E1A9EDF457125DA +CT=5DFAAFB695D34A7AF2D39CD2D01FD4BD + +I=162 +KEY=D901B04E6045C86D6B42F62AB89026A8 +IV=5DFAAFB695D34A7AF2D39CD2D01FD4BD +PT=FAE59C96604D062F49C8C93FA7E4D5FC +CT=85F63AFC88A1CED4E73B849C295692F2 + +I=163 +KEY=5CF78AB2E8E406B98C7972B691C6B45A +IV=85F63AFC88A1CED4E73B849C295692F2 +PT=7FE1EA6A7A525A7E0222D6269F7D6A40 +CT=DC60A8554BF9E783D0E92283EC0D00AF + +I=164 +KEY=809722E7A31DE13A5C9050357DCBB4F5 +IV=DC60A8554BF9E783D0E92283EC0D00AF +PT=89C93828CE30D4CD7025D9F2CF864371 +CT=EF10720E8F10FBABC96BB5F4E5287D12 + +I=165 +KEY=6F8750E92C0D1A9195FBE5C198E3C9E7 +IV=EF10720E8F10FBABC96BB5F4E5287D12 +PT=A8DEA35D4A712ACE8F38A2CA2CB6BCFB +CT=EED271733DC7B81AD09C86C8F8D69255 + +I=166 +KEY=8155219A11CAA28B4567630960355BB2 +IV=EED271733DC7B81AD09C86C8F8D69255 +PT=6720AD239EFECF5785B238D4DA39DD6A +CT=DC47B1FAC154CB0C39ADF4C92F8C2902 + +I=167 +KEY=5D129060D09E69877CCA97C04FB972B0 +IV=DC47B1FAC154CB0C39ADF4C92F8C2902 +PT=D41DEA3BC44CC552B5ACCFEEFAF225F5 +CT=AD4828834513730BF275C854D35BF09E + +I=168 +KEY=F05AB8E3958D1A8C8EBF5F949CE2822E +IV=AD4828834513730BF275C854D35BF09E +PT=5059DA9258A7DE12865E1E2173399BC9 +CT=82CA6B085A452CFDFFBDE5C7B738CDAB + +I=169 +KEY=7290D3EBCFC836717102BA532BDA4F85 +IV=82CA6B085A452CFDFFBDE5C7B738CDAB +PT=9625B8A444C3E4D3554A8C6E33E1B810 +CT=4F44C38189E1011970690D0ED4BCB9C7 + +I=170 +KEY=3DD4106A46293768016BB75DFF66F642 +IV=4F44C38189E1011970690D0ED4BCB9C7 +PT=373FBCA7529A9FA9AF77295FC55B0BEE +CT=27BE0578B0F898C04133AA4D3C1A5A7C + +I=171 +KEY=1A6A1512F6D1AFA840581D10C37CAC3E +IV=27BE0578B0F898C04133AA4D3C1A5A7C +PT=37FC0A286DFFD5A76643D1D45C858F64 +CT=B9C70B34F78F3DA7796C32D0918474A5 + +I=172 +KEY=A3AD1E26015E920F39342FC052F8D89B +IV=B9C70B34F78F3DA7796C32D0918474A5 +PT=E1EAC69AA2A8F05B8747E2624D00F4BB +CT=846985C471F10676E63BCD09C32506F3 + +I=173 +KEY=27C49BE270AF9479DF0FE2C991DDDE68 +IV=846985C471F10676E63BCD09C32506F3 +PT=6EB0046D9C6854C63447296F4F6D3D21 +CT=F754559746C52113C29AF782E96B6105 + +I=174 +KEY=D090CE75366AB56A1D95154B78B6BF6D +IV=F754559746C52113C29AF782E96B6105 +PT=F65269422328F40D8A53F4F14DB88583 +CT=AE6B4EABF8DC479A1E3F8C3F30A4A797 + +I=175 +KEY=7EFB80DECEB6F2F003AA9974481218FA +IV=AE6B4EABF8DC479A1E3F8C3F30A4A797 +PT=765B38DC041DEC130A3A294D9F89A16D +CT=87645926B9D85AC4AB023D2104CC3FA2 + +I=176 +KEY=F99FD9F8776EA834A8A8A4554CDE2758 +IV=87645926B9D85AC4AB023D2104CC3FA2 +PT=8070950120E0FBE07C70B171364AD173 +CT=0125D51139CE00DB848B8A9AD3FEB90B + +I=177 +KEY=F8BA0CE94EA0A8EF2C232ECF9F209E53 +IV=0125D51139CE00DB848B8A9AD3FEB90B +PT=1EF45DD2CD61667469569CFAD445341C +CT=E1651756A2C0D132C671D74748244E49 + +I=178 +KEY=19DF1BBFEC6079DDEA52F988D704D01A +IV=E1651756A2C0D132C671D74748244E49 +PT=26BEF7E8A3D0AC50DC64B8215CCBC44F +CT=94049FBD554A6CFFE7927D6EC07D6242 + +I=179 +KEY=8DDB8402B92A15220DC084E61779B258 +IV=94049FBD554A6CFFE7927D6EC07D6242 +PT=803F34FA967583623D0CA4D76FC56787 +CT=974BBE04952D8F0DD70F4353FEB092EB + +I=180 +KEY=1A903A062C079A2FDACFC7B5E9C920B3 +IV=974BBE04952D8F0DD70F4353FEB092EB +PT=023E5D307CE85244144D59A53DB504E7 +CT=2615B9F94F9024EA616648FF15E3B65F + +I=181 +KEY=3C8583FF6397BEC5BBA98F4AFC2A96EC +IV=2615B9F94F9024EA616648FF15E3B65F +PT=1A84130B09CE3E7AB1F400B9FE295BEB +CT=39A2A3B6EFB5EBE805CBAD5817EAEEDA + +I=182 +KEY=052720498C22552DBE622212EBC07836 +IV=39A2A3B6EFB5EBE805CBAD5817EAEEDA +PT=B83609055302D99DE46B7153AE3DFCE2 +CT=93F72B839E2AD731B5E894B56ADADCF4 + +I=183 +KEY=96D00BCA1208821C0B8AB6A7811AA4C2 +IV=93F72B839E2AD731B5E894B56ADADCF4 +PT=85E69EBDE13C05526EA8AE1D24B487F3 +CT=D0ADA333801DFDBFC2420B73CD2B92A5 + +I=184 +KEY=467DA8F992157FA3C9C8BDD44C313667 +IV=D0ADA333801DFDBFC2420B73CD2B92A5 +PT=F24782E953B9B1BBF3B925659C99415B +CT=F59A3D0B65E8F16DC73CCD6C27E8C705 + +I=185 +KEY=B3E795F2F7FD8ECE0EF470B86BD9F162 +IV=F59A3D0B65E8F16DC73CCD6C27E8C705 +PT=73BE517552E054D78583BEA03B84A245 +CT=7904DBE3A103D936EB4B960C180B0651 + +I=186 +KEY=CAE34E1156FE57F8E5BFE6B473D2F733 +IV=7904DBE3A103D936EB4B960C180B0651 +PT=91998E9582D8357DD5D8B95A9D85912F +CT=C2DE0D0145A45DEABD6DE1FD62161EB1 + +I=187 +KEY=083D4310135A0A1258D2074911C4E982 +IV=C2DE0D0145A45DEABD6DE1FD62161EB1 +PT=2A5D4EC49712B9CF1E2D9C6C5EFACC2A +CT=974264BDC574C738243DDC008EC4C15A + +I=188 +KEY=9F7F27ADD62ECD2A7CEFDB499F0028D8 +IV=974264BDC574C738243DDC008EC4C15A +PT=F74520C3745B9B9F9D19642AA57451FB +CT=F4EE51C2ECC32F4806F9C8588880525B + +I=189 +KEY=6B91766F3AEDE2627A16131117807A83 +IV=F4EE51C2ECC32F4806F9C8588880525B +PT=4A7D6FC6712F451F58DF0AC2D517189E +CT=F4978F5F53AA4C336BEE0C62F432B44F + +I=190 +KEY=9F06F9306947AE5111F81F73E3B2CECC +IV=F4978F5F53AA4C336BEE0C62F432B44F +PT=00DAD17491C973991FEC296972B691BC +CT=09DAA53C2E394BF83113BE48E5D0CCA2 + +I=191 +KEY=96DC5C0C477EE5A920EBA13B0662026E +IV=09DAA53C2E394BF83113BE48E5D0CCA2 +PT=C00943704C1336F01A1D23FD98BE7E8B +CT=D0DE529664BF241DBED3168DA5BC1B28 + +I=192 +KEY=46020E9A23C1C1B49E38B7B6A3DE1946 +IV=D0DE529664BF241DBED3168DA5BC1B28 +PT=A07FAD9770CC32C5680F33A2D67044A4 +CT=F6A44922B3744BE96C46742A79A49CBB + +I=193 +KEY=B0A647B890B58A5DF27EC39CDA7A85FD +IV=F6A44922B3744BE96C46742A79A49CBB +PT=D5450C670BE84169AD1E62C5ECB8365F +CT=47D229908D4C1EA34E429C34B7D635F5 + +I=194 +KEY=F7746E281DF994FEBC3C5FA86DACB008 +IV=47D229908D4C1EA34E429C34B7D635F5 +PT=9E90D30BE92104667A16522237D645A6 +CT=6463AC2096842A0958ACF45370C0626F + +I=195 +KEY=9317C2088B7DBEF7E490ABFB1D6CD267 +IV=6463AC2096842A0958ACF45370C0626F +PT=74382A7BF713DE8E8D17AE389E03C3AC +CT=ECDCEF7613C362D288AC23D38722DC4C + +I=196 +KEY=7FCB2D7E98BEDC256C3C88289A4E0E2B +IV=ECDCEF7613C362D288AC23D38722DC4C +PT=DB2EC6F41A72F426D9F5DBC65CEC1C5C +CT=DFE2DA423ACE2DFB053265E9E9B214E2 + +I=197 +KEY=A029F73CA270F1DE690EEDC173FC1AC9 +IV=DFE2DA423ACE2DFB053265E9E9B214E2 +PT=35998CB9958DC9DE0550FC3EA722D571 +CT=5EBCA79BF99165D9FFE355D9B24ECB5D + +I=198 +KEY=FE9550A75BE1940796EDB818C1B2D194 +IV=5EBCA79BF99165D9FFE355D9B24ECB5D +PT=9BDA7BC96736FE2140911C98E8E02E1C +CT=782D3EFD5F599E8D3C85D06128677EC2 + +I=199 +KEY=86B86E5A04B80A8AAA686879E9D5AF56 +IV=782D3EFD5F599E8D3C85D06128677EC2 +PT=8014C1F398E4DCC7F4E5E09E5FAFB080 +CT=E01AE2D961F31BBAE3DA7429627572AB + +I=200 +KEY=66A28C83654B113049B21C508BA0DDFD +IV=E01AE2D961F31BBAE3DA7429627572AB +PT=97D66D66D1731EEFF14519620616A10B +CT=BC41ED9D568D6ED36212C92DEEB40A0E + +I=201 +KEY=DAE3611E33C67FE32BA0D57D6514D7F3 +IV=BC41ED9D568D6ED36212C92DEEB40A0E +PT=F7646B60C237ED24F467141980EB4F00 +CT=CB8DF2D164E5B4AB3193D02E71959F63 + +I=202 +KEY=116E93CF5723CB481A33055314814890 +IV=CB8DF2D164E5B4AB3193D02E71959F63 +PT=4A3A241B26AC7A1C88AA2FB750DF6E5A +CT=E396FB47A686ABAA350B84C250E5EAE9 + +I=203 +KEY=F2F86888F1A560E22F3881914464A279 +IV=E396FB47A686ABAA350B84C250E5EAE9 +PT=A71348309D176A072167C4B1B8A295C0 +CT=29AF21F96564EB591E9A60B1BE88DEC7 + +I=204 +KEY=DB57497194C18BBB31A2E120FAEC7CBE +IV=29AF21F96564EB591E9A60B1BE88DEC7 +PT=BC528364EF78D6432177FE0CF1CDECD1 +CT=34CD9D96D4455AE0C15B6B970F1EC905 + +I=205 +KEY=EF9AD4E74084D15BF0F98AB7F5F2B5BB +IV=34CD9D96D4455AE0C15B6B970F1EC905 +PT=18972F6992299533EE23AA5824C25892 +CT=2E05E3E2079A055310FD9318590A6F41 + +I=206 +KEY=C19F3705471ED408E00419AFACF8DAFA +IV=2E05E3E2079A055310FD9318590A6F41 +PT=5441FF0D0A4062D5D0DF29BF2FDA85B4 +CT=47D4EAECE59C733EEFCB7B9D5BE95A98 + +I=207 +KEY=864BDDE9A282A7360FCF6232F7118062 +IV=47D4EAECE59C733EEFCB7B9D5BE95A98 +PT=ED3E19B5AB5389AA3A58D97F6604F4C0 +CT=00525B7D5BFC0651AEF6770F6281E6DC + +I=208 +KEY=86198694F97EA167A139153D959066BE +IV=00525B7D5BFC0651AEF6770F6281E6DC +PT=8BD4869C88A9BD3DCFE89B98B93F6EB3 +CT=AFB2215E6DC04E9467F44227FD4BDB98 + +I=209 +KEY=29ABA7CA94BEEFF3C6CD571A68DBBD26 +IV=AFB2215E6DC04E9467F44227FD4BDB98 +PT=6E7269FC27BDCC42D64CEF41A612F771 +CT=7B769B90279C95E31D8B3D792FA27FA8 + +I=210 +KEY=52DD3C5AB3227A10DB466A634779C28E +IV=7B769B90279C95E31D8B3D792FA27FA8 +PT=E00316E79DC10D179002B1BACC146027 +CT=E3870CDE5CF99B7C4C489AF81153002F + +I=211 +KEY=B15A3084EFDBE16C970EF09B562AC2A1 +IV=E3870CDE5CF99B7C4C489AF81153002F +PT=FB2FC78A79C33225E6EAAA06B76FA793 +CT=4DFC91F8971635348EF35141E8C291F7 + +I=212 +KEY=FCA6A17C78CDD45819FDA1DABEE85356 +IV=4DFC91F8971635348EF35141E8C291F7 +PT=69C8EE14F21832BB077F1A5414851FFE +CT=DA51BE36F96AA8C80DED9DB2A701D72F + +I=213 +KEY=26F71F4A81A77C9014103C6819E98479 +IV=DA51BE36F96AA8C80DED9DB2A701D72F +PT=766EC1664D2194E0F89B69861A4A8501 +CT=2ACA6359CD935CA2294F9FB5A50F4993 + +I=214 +KEY=0C3D7C134C3420323D5FA3DDBCE6CDEA +IV=2ACA6359CD935CA2294F9FB5A50F4993 +PT=1D95E551169BD538836CC349BC6B1772 +CT=315518F0AC6C1DC9939CB802336DA968 + +I=215 +KEY=3D6864E3E0583DFBAEC31BDF8F8B6482 +IV=315518F0AC6C1DC9939CB802336DA968 +PT=4F6BFE727AECDAB5A32DF8CFFC43D6A9 +CT=34C3ECD89376B4D771CA0669C2C3E26C + +I=216 +KEY=09AB883B732E892CDF091DB64D4886EE +IV=34C3ECD89376B4D771CA0669C2C3E26C +PT=AA8B1DA2E015D482EE08FA2B4A2B77B6 +CT=A3F4DD9DDC375C90579C274527612C6E + +I=217 +KEY=AA5F55A6AF19D5BC88953AF36A29AA80 +IV=A3F4DD9DDC375C90579C274527612C6E +PT=2EE6982D9E0AA5FCB61F3E66E52A0D6D +CT=C45C9E4DE76782E2599BD73B132BFE90 + +I=218 +KEY=6E03CBEB487E575ED10EEDC879025410 +IV=C45C9E4DE76782E2599BD73B132BFE90 +PT=6E58E5B1EDF1BFABAD643D8223F0FA81 +CT=32221DA62DA2B441B5E66A197A5C69F1 + +I=219 +KEY=5C21D64D65DCE31F64E887D1035E3DE1 +IV=32221DA62DA2B441B5E66A197A5C69F1 +PT=D5A81DF4B6BE17A531478961D78CAB46 +CT=E1FEB5C31B1671F15DC1F7713E5DD7FE + +I=220 +KEY=BDDF638E7ECA92EE392970A03D03EA1F +IV=E1FEB5C31B1671F15DC1F7713E5DD7FE +PT=D360948141A1D3ECFF5E8D6BDC022685 +CT=FF07F02135FB458D63EE68C4B1463A99 + +I=221 +KEY=42D893AF4B31D7635AC718648C45D086 +IV=FF07F02135FB458D63EE68C4B1463A99 +PT=E3C1E44333C9307E90EE2FBA6A7708A5 +CT=1AE4E8466B84B59EECF5E6BEB6140DF2 + +I=222 +KEY=583C7BE920B562FDB632FEDA3A51DD74 +IV=1AE4E8466B84B59EECF5E6BEB6140DF2 +PT=653AA343CE35F72E2ADB5FFCD2DFCBA8 +CT=3CB44BC123DDCD55B812D265CC5E974E + +I=223 +KEY=648830280368AFA80E202CBFF60F4A3A +IV=3CB44BC123DDCD55B812D265CC5E974E +PT=E96A66BFE5F0E8083A01664A47226672 +CT=BB6C54E118FA895F2AC4CC036166E390 + +I=224 +KEY=DFE464C91B9226F724E4E0BC9769A9AA +IV=BB6C54E118FA895F2AC4CC036166E390 +PT=A5B240D8E5731E1BFA7C4FDFB4EED81F +CT=DA20870677A6214F26FDACBA81B41882 + +I=225 +KEY=05C4E3CF6C3407B802194C0616DDB128 +IV=DA20870677A6214F26FDACBA81B41882 +PT=92FF6EAB4A6D1AD3941E6A91D8C9105B +CT=F079AA86FC9FD361DBA0C21CCD4B0F6C + +I=226 +KEY=F5BD494990ABD4D9D9B98E1ADB96BE44 +IV=F079AA86FC9FD361DBA0C21CCD4B0F6C +PT=DFF005175EF746B83CB00AC13337E248 +CT=B6021E0AA1A921C7BCC3FDAB1C3EA44A + +I=227 +KEY=43BF57433102F51E657A73B1C7A81A0E +IV=B6021E0AA1A921C7BCC3FDAB1C3EA44A +PT=DDDC1AA804AD13813C6AEA540557C097 +CT=41F0E4AB03801DCE585727B7C41F48BD + +I=228 +KEY=024FB3E83282E8D03D2D540603B752B3 +IV=41F0E4AB03801DCE585727B7C41F48BD +PT=4C6421E5A487C9C452958CAB38AC7098 +CT=6EFDD855BAF2D13437C01097ABB633DE + +I=229 +KEY=6CB26BBD887039E40AED4491A801616D +IV=6EFDD855BAF2D13437C01097ABB633DE +PT=2A11519D5463F2B96A5E0FCE6E4710D7 +CT=5E8243E5C54A109CCC0BF622A299EF68 + +I=230 +KEY=323028584D3A2978C6E6B2B30A988E05 +IV=5E8243E5C54A109CCC0BF622A299EF68 +PT=252145DACAD23E8B85AB7637B22C42F2 +CT=2C9A476418F01C589ADC0CA10BF4A183 + +I=231 +KEY=1EAA6F3C55CA35205C3ABE12016C2F86 +IV=2C9A476418F01C589ADC0CA10BF4A183 +PT=A22C36DC7D00645FEFE8683EA4231787 +CT=DA3A4AC19EF6A0F950E26B00834AFE41 + +I=232 +KEY=C49025FDCB3C95D90CD8D5128226D1C7 +IV=DA3A4AC19EF6A0F950E26B00834AFE41 +PT=B0DC92D3B4878156B768923286F0433F +CT=10BBC2A8C8F650FD8EED7CC9F5EAD05D + +I=233 +KEY=D42BE75503CAC5248235A9DB77CC019A +IV=10BBC2A8C8F650FD8EED7CC9F5EAD05D +PT=83A9338157091D4AECAF60E887AE09F7 +CT=757993A70F78B25F02FA0355E04DE27B + +I=234 +KEY=A15274F20CB2777B80CFAA8E9781E3E1 +IV=757993A70F78B25F02FA0355E04DE27B +PT=9D818ACA2C753E7314F51699D3062031 +CT=E2E74C76C09516135876D54AFC940D80 + +I=235 +KEY=43B53884CC276168D8B97FC46B15EE61 +IV=E2E74C76C09516135876D54AFC940D80 +PT=BDD36F881F8D1FC56780E291D1359EE1 +CT=22F76A2DB98544549DEA21FFCDC2B943 + +I=236 +KEY=614252A975A2253C45535E3BA6D75722 +IV=22F76A2DB98544549DEA21FFCDC2B943 +PT=4C9C16802A4BB1202D4FAC9E76C57A43 +CT=166B0FF778D72B6102D6ADF990A70A23 + +I=237 +KEY=77295D5E0D750E5D4785F3C236705D01 +IV=166B0FF778D72B6102D6ADF990A70A23 +PT=0045ECDDAA51EE6FDB226E2D9471F46C +CT=D7724DC8A1413BC1B9D6F305794426F0 + +I=238 +KEY=A05B1096AC34359CFE5300C74F347BF1 +IV=D7724DC8A1413BC1B9D6F305794426F0 +PT=25C55C60290DF3D0DC3274CD2AE0ED21 +CT=41F0196DFE0B1F664A107D12A6FF3D79 + +I=239 +KEY=E1AB09FB523F2AFAB4437DD5E9CB4688 +IV=41F0196DFE0B1F664A107D12A6FF3D79 +PT=9A44454F7A335C89BEFF1D94D3FDB320 +CT=3F37D7ADFB9933FFBAC1F7D07F31046E + +I=240 +KEY=DE9CDE56A9A619050E828A0596FA42E6 +IV=3F37D7ADFB9933FFBAC1F7D07F31046E +PT=03D7F09054233696BEF84AB8D5B77091 +CT=02D226A748153C27A723F02461FFF913 + +I=241 +KEY=DC4EF8F1E1B32522A9A17A21F705BBF5 +IV=02D226A748153C27A723F02461FFF913 +PT=D5C82A6F048A2AA0E5CF4F1EDADD68B3 +CT=4BD7486C212E7F78228478BBF0A7AD3D + +I=242 +KEY=9799B09DC09D5A5A8B25029A07A216C8 +IV=4BD7486C212E7F78228478BBF0A7AD3D +PT=936431AD9F800606240C33EAF661D3DA +CT=3EFE00CA0A96AF4425E683512DAC0164 + +I=243 +KEY=A967B057CA0BF51EAEC381CB2A0E17AC +IV=3EFE00CA0A96AF4425E683512DAC0164 +PT=280DC27864BED0D548B5B4F9A7FA38DE +CT=7023640C8D6B02F6C4C7E007C169C592 + +I=244 +KEY=D944D45B4760F7E86A0461CCEB67D23E +IV=7023640C8D6B02F6C4C7E007C169C592 +PT=CD0F58962915E5A514E5D6DA8BB868E8 +CT=D08419A75363E9622FAA09DB589915F1 + +I=245 +KEY=09C0CDFC14031E8A45AE6817B3FEC7CF +IV=D08419A75363E9622FAA09DB589915F1 +PT=09A6099FDDDBBC15EE79224B01C49DF0 +CT=6CDD2B0279D9DB3C71329C1BB2C24C2F + +I=246 +KEY=651DE6FE6DDAC5B6349CF40C013C8BE0 +IV=6CDD2B0279D9DB3C71329C1BB2C24C2F +PT=B24B11FD8A6FC6B2703FFBEBC85B6C44 +CT=CCB0F6F32BDE2339A1842A7EDC8C99C7 + +I=247 +KEY=A9AD100D4604E68F9518DE72DDB01227 +IV=CCB0F6F32BDE2339A1842A7EDC8C99C7 +PT=2E471506C55D1762CDB9EAEF29E23C01 +CT=DAD62227A5F328CC33F054EEB346E3D3 + +I=248 +KEY=737B322AE3F7CE43A6E88A9C6EF6F1F4 +IV=DAD62227A5F328CC33F054EEB346E3D3 +PT=5598344020E32F9B2C509D06F4E7804A +CT=18DE226F7CAA4EF2712A223C4709C9E2 + +I=249 +KEY=6BA510459F5D80B1D7C2A8A029FF3816 +IV=18DE226F7CAA4EF2712A223C4709C9E2 +PT=549A87BE74B62BAC3F0FDC2A878F5669 +CT=DB082C8D70948B6BF08D4848E4DB0231 + +I=250 +KEY=B0AD3CC8EFC90BDA274FE0E8CD243A27 +IV=DB082C8D70948B6BF08D4848E4DB0231 +PT=08946428BF90FBF0951A35D6FB72A48A +CT=29CBD3E3F2074514E63A7B2A651AB031 + +I=251 +KEY=9966EF2B1DCE4ECEC1759BC2A83E8A16 +IV=29CBD3E3F2074514E63A7B2A651AB031 +PT=7EBEC38F7787EE1BDD6A648334FA3076 +CT=0037935821278E879BCBB2FBE4ECC23E + +I=252 +KEY=99517C733CE9C0495ABE29394CD24828 +IV=0037935821278E879BCBB2FBE4ECC23E +PT=01D77828928164A830C249D96AC6F8B4 +CT=47501831F9DF42C234E9FE9169075888 + +I=253 +KEY=DE016442C536828B6E57D7A825D510A0 +IV=47501831F9DF42C234E9FE9169075888 +PT=608349FF8FFC31B072CFA7DF649E15B8 +CT=BC10B1D412BC05404B2E38A1D75DA421 + +I=254 +KEY=6211D596D78A87CB2579EF09F288B481 +IV=BC10B1D412BC05404B2E38A1D75DA421 +PT=B16325BD78FC0451216FF476D4CAE293 +CT=6ABD8010E9CBAE61E05A9E30C622B501 + +I=255 +KEY=08AC55863E4129AAC523713934AA0180 +IV=6ABD8010E9CBAE61E05A9E30C622B501 +PT=E613C244F74C61B078C9E59E06E7AD85 +CT=E896B8BD539C30D9A58E5EF6629B279C + +I=256 +KEY=E03AED3B6DDD197360AD2FCF5631261C +IV=E896B8BD539C30D9A58E5EF6629B279C +PT=6CFF7A909AAB2C0DC61FB8F11B45E661 +CT=30D15AAA05F56FA2D21E9974FB3FF5DA + +I=257 +KEY=D0EBB791682876D1B2B3B6BBAD0ED3C6 +IV=30D15AAA05F56FA2D21E9974FB3FF5DA +PT=6BFAC8E8FB9C3D5AF813B4DF90AD863B +CT=43B99F3DA3C1BCCE9038118E2968EFA1 + +I=258 +KEY=935228ACCBE9CA1F228BA73584663C67 +IV=43B99F3DA3C1BCCE9038118E2968EFA1 +PT=064D09E9F5104602E191DC39F18E6A1A +CT=EBC5796519BE4E05262A10D56FA0F72D + +I=259 +KEY=789751C9D257841A04A1B7E0EBC6CB4A +IV=EBC5796519BE4E05262A10D56FA0F72D +PT=C2B528D69ED3028A359D4472D98807A7 +CT=5F2B51DD025E775A63DFE5B9FBF54986 + +I=260 +KEY=27BC0014D009F340677E5259103382CC +IV=5F2B51DD025E775A63DFE5B9FBF54986 +PT=D5CF62940967AF7225F79E87136751F5 +CT=F56D88E433CEA445C6E4D6298DFB6C27 + +I=261 +KEY=D2D188F0E3C75705A19A84709DC8EEEB +IV=F56D88E433CEA445C6E4D6298DFB6C27 +PT=3BE3171202E762846D2CA00FB2CB141A +CT=4C168A0129F2D48E249777A366D1AEF1 + +I=262 +KEY=9EC702F1CA35838B850DF3D3FB19401A +IV=4C168A0129F2D48E249777A366D1AEF1 +PT=5B82A34141C236FAED7E1A78D3C426C4 +CT=E11FEBEF79E425480442D45A8C105B44 + +I=263 +KEY=7FD8E91EB3D1A6C3814F278977091B5E +IV=E11FEBEF79E425480442D45A8C105B44 +PT=86CFADD3F1B368B3A6E57148CA343D38 +CT=5F5F3548BDBB2A5337FBF07DF76526DD + +I=264 +KEY=2087DC560E6A8C90B6B4D7F4806C3D83 +IV=5F5F3548BDBB2A5337FBF07DF76526DD +PT=A4474ACA97100C7A357A66119D678798 +CT=013ADA262021F88617773CF478067EC8 + +I=265 +KEY=21BD06702E4B7416A1C3EB00F86A434B +IV=013ADA262021F88617773CF478067EC8 +PT=6D66801C39DB803B5DA5A80E30DB0D89 +CT=F46BE70F65FC5641318292AE0C79E5C5 + +I=266 +KEY=D5D6E17F4BB72257904179AEF413A68E +IV=F46BE70F65FC5641318292AE0C79E5C5 +PT=C9499B32D8F47313EB351139DB81AB25 +CT=8573A25F86C7784BF7A0153DF812805C + +I=267 +KEY=50A54320CD705A1C67E16C930C0126D2 +IV=8573A25F86C7784BF7A0153DF812805C +PT=4B09D37A4A57B320C34B1D70F74EB36A +CT=036913128A2B71CE3D05D52D61E48E86 + +I=268 +KEY=53CC5032475B2BD25AE4B9BE6DE5A854 +IV=036913128A2B71CE3D05D52D61E48E86 +PT=EA3A92794B204C0345765CEE2A04AF27 +CT=5A53E929182859CC28D4EB1CB9579B71 + +I=269 +KEY=099FB91B5F73721E723052A2D4B23325 +IV=5A53E929182859CC28D4EB1CB9579B71 +PT=2714E38858426C5631BB2BB4FA289985 +CT=DF4BD734DEC60475D47FE40502439AAE + +I=270 +KEY=D6D46E2F81B5766BA64FB6A7D6F1A98B +IV=DF4BD734DEC60475D47FE40502439AAE +PT=69AC3FD2273926E2DAD3F5BED9F21491 +CT=EBCCD0B121C4009EA7F038F30F5B6B05 + +I=271 +KEY=3D18BE9EA07176F501BF8E54D9AAC28E +IV=EBCCD0B121C4009EA7F038F30F5B6B05 +PT=07520CD471E27BAC35387DB47E706784 +CT=299FE603BBA51BD1582CBD42BC9568EA + +I=272 +KEY=1487589D1BD46D2459933316653FAA64 +IV=299FE603BBA51BD1582CBD42BC9568EA +PT=39598B70B8EB190049823472E3596E42 +CT=68DD98FE52B454F85D6F6A6C742223FA + +I=273 +KEY=7C5AC063496039DC04FC597A111D899E +IV=68DD98FE52B454F85D6F6A6C742223FA +PT=C7E13ABBBA75F527AB1320DD930B24F1 +CT=906B569E44263A4E6F41A52802D3FC59 + +I=274 +KEY=EC3196FD0D4603926BBDFC5213CE75C7 +IV=906B569E44263A4E6F41A52802D3FC59 +PT=9F5D8E50F06895D5D7E6D1DAA247D45F +CT=E5ECBDCC55A9D952BE0F93DFA0FE2C31 + +I=275 +KEY=09DD2B3158EFDAC0D5B26F8DB33059F6 +IV=E5ECBDCC55A9D952BE0F93DFA0FE2C31 +PT=EC3F35C1E6371F106443BD1446D58A0A +CT=4837A3D703E80BFE50D742E378956F3A + +I=276 +KEY=41EA88E65B07D13E85652D6ECBA536CC +IV=4837A3D703E80BFE50D742E378956F3A +PT=7998C3B7B5C94540DFC5BF777D700D48 +CT=DF1564E5E47503A779020D27394571E9 + +I=277 +KEY=9EFFEC03BF72D299FC672049F2E04725 +IV=DF1564E5E47503A779020D27394571E9 +PT=63BEA75A2440C5D123F335F72137B0B6 +CT=5147239C3F6E4A158989BE96C0275D41 + +I=278 +KEY=CFB8CF9F801C988C75EE9EDF32C71A64 +IV=5147239C3F6E4A158989BE96C0275D41 +PT=09C656A0DFCF893DDBE5E2B3D88E5F1F +CT=7E4DEE30DED62EE15CD957530B62559D + +I=279 +KEY=B1F521AF5ECAB66D2937C98C39A54FF9 +IV=7E4DEE30DED62EE15CD957530B62559D +PT=71DC22F489DD422CDE09F01DAA427567 +CT=6F62D6359F07F6BDBB4C02BBE50B273C + +I=280 +KEY=DE97F79AC1CD40D0927BCB37DCAE68C5 +IV=6F62D6359F07F6BDBB4C02BBE50B273C +PT=C2A9BC94CAE48DBEB37B4B506AD4336A +CT=902D9E9F82DE4E66E42B4FEA79AF4077 + +I=281 +KEY=4EBA690543130EB6765084DDA50128B2 +IV=902D9E9F82DE4E66E42B4FEA79AF4077 +PT=69EE7E15EEC2EA953A32E1714961BA9E +CT=72CB5DE8AF6CDC60A00A15CEAF249DBD + +I=282 +KEY=3C7134EDEC7FD2D6D65A91130A25B50F +IV=72CB5DE8AF6CDC60A00A15CEAF249DBD +PT=4C0A3B88FDFAEFEC38858A927C38AE6A +CT=68C2BFA5DE837B927BD75C6DE6008595 + +I=283 +KEY=54B38B4832FCA944AD8DCD7EEC25309A +IV=68C2BFA5DE837B927BD75C6DE6008595 +PT=CE75CCA2D7B0199EB1DA7E33A0E50AB7 +CT=4FFCCBB31FB1FCC0FCB38F0B557BE67A + +I=284 +KEY=1B4F40FB2D4D5584513E4275B95ED6E0 +IV=4FFCCBB31FB1FCC0FCB38F0B557BE67A +PT=E0ECA2ABC1F389B149E746CFB039539E +CT=249FB11DF8C0ED1F346F6D69B8FD0470 + +I=285 +KEY=3FD0F1E6D58DB89B65512F1C01A3D290 +IV=249FB11DF8C0ED1F346F6D69B8FD0470 +PT=BFA871CA5EC16C0B353679782BE04394 +CT=8127E6D8EEC1111518065EDC34CD4B4C + +I=286 +KEY=BEF7173E3B4CA98E7D5771C0356E99DC +IV=8127E6D8EEC1111518065EDC34CD4B4C +PT=1EF816C565B2F56E772C96AD5C92842D +CT=C8DC75AE1E2DBD005D94E69D6776C498 + +I=287 +KEY=762B62902561148E20C3975D52185D44 +IV=C8DC75AE1E2DBD005D94E69D6776C498 +PT=9F2B9873F88EBF21A3BB3DCD853C812E +CT=861D4FF061E85D44173252244F143692 + +I=288 +KEY=F0362D60448949CA37F1C5791D0C6BD6 +IV=861D4FF061E85D44173252244F143692 +PT=6CDEA8A806516A1A0E1CBB5AA123862A +CT=16DA4EE5C5044F66EFCC313754FBCD9E + +I=289 +KEY=E6EC6385818D06ACD83DF44E49F7A648 +IV=16DA4EE5C5044F66EFCC313754FBCD9E +PT=5B637BB469073B5E54EC006F47C4D546 +CT=C2C50037BBBEC252B7D5CF10C38BD665 + +I=290 +KEY=242963B23A33C4FE6FE83B5E8A7C702D +IV=C2C50037BBBEC252B7D5CF10C38BD665 +PT=38DADBF2BA4A80A6A190D9E2AA245167 +CT=721222A5A67E96246DA1B9C59B67DDD5 + +I=291 +KEY=563B41179C4D52DA0249829B111BADF8 +IV=721222A5A67E96246DA1B9C59B67DDD5 +PT=CB52378F6E4E7FCB1891D3BB4D086B9F +CT=D28B8F54E8BDA9A20965984D5DA27FC9 + +I=292 +KEY=84B0CE4374F0FB780B2C1AD64CB9D231 +IV=D28B8F54E8BDA9A20965984D5DA27FC9 +PT=E66015A1B848EF190F981DEFEDB98C93 +CT=012C5D9B847C9583B0BE03999D24E277 + +I=293 +KEY=859C93D8F08C6EFBBB92194FD19D3046 +IV=012C5D9B847C9583B0BE03999D24E277 +PT=F5B2BAD53323A52A2B99CC12782CD6F9 +CT=D1EFB7E7A34F75887038FC4827E894C1 + +I=294 +KEY=5473243F53C31B73CBAAE507F675A487 +IV=D1EFB7E7A34F75887038FC4827E894C1 +PT=11C0C41C3F547B5D7FC94115327AB3D5 +CT=2CF97D8995AA8FDC4C05205D3D8B757F + +I=295 +KEY=788A59B6C66994AF87AFC55ACBFED1F8 +IV=2CF97D8995AA8FDC4C05205D3D8B757F +PT=3F911029D8B69CA1A323A277090B9C07 +CT=44BB04C6253F3ADD454264EA97490475 + +I=296 +KEY=3C315D70E356AE72C2EDA1B05CB7D58D +IV=44BB04C6253F3ADD454264EA97490475 +PT=9D7724EFD1AE76904458EF1360953AA4 +CT=5D6F876E4FDD6921B243EB1F6EF50F82 + +I=297 +KEY=615EDA1EAC8BC75370AE4AAF3242DA0F +IV=5D6F876E4FDD6921B243EB1F6EF50F82 +PT=44A26554FE355D95706431B344701B03 +CT=5F3226B39DF230163D2C474F04BAD36E + +I=298 +KEY=3E6CFCAD3179F7454D820DE036F80961 +IV=5F3226B39DF230163D2C474F04BAD36E +PT=5D8B62C8CD3B04451A599989F3165530 +CT=A247CF8E1D8F480DA4155DA846A2B64E + +I=299 +KEY=9C2B33232CF6BF48E9975048705ABF2F +IV=A247CF8E1D8F480DA4155DA846A2B64E +PT=610D3798E62E9338D5987BAC82D48CD7 +CT=2A92B5AAEA43CFBAA62842DEE7F43A19 + +I=300 +KEY=B6B98689C6B570F24FBF129697AE8536 +IV=2A92B5AAEA43CFBAA62842DEE7F43A19 +PT=F77943AA429BCCC5253156474E719389 +CT=7D475AFF824080E9C95D4E49D4F5090D + +I=301 +KEY=CBFEDC7644F5F01B86E25CDF435B8C3B +IV=7D475AFF824080E9C95D4E49D4F5090D +PT=5E6269D157164B2C544D3052E9DB8553 +CT=AD4628B05F5A765E557015B4A41505EA + +I=302 +KEY=66B8F4C61BAF8645D392496BE74E89D1 +IV=AD4628B05F5A765E557015B4A41505EA +PT=77126BD6C08A094981FEC9E2DE91B2BF +CT=59C24F269E3884A4F8E3F9FB05BF448F + +I=303 +KEY=3F7ABBE0859702E12B71B090E2F1CD5E +IV=59C24F269E3884A4F8E3F9FB05BF448F +PT=7775F90D2189E91B75AB8AD93C0D44F2 +CT=B72873115D4761B8BAEB5B5892B79DF8 + +I=304 +KEY=8852C8F1D8D06359919AEBC8704650A6 +IV=B72873115D4761B8BAEB5B5892B79DF8 +PT=03D9C45A2A152ADAA53E1D42AB33555B +CT=FE0C3F22E6B467DC1C628C928D03DB5B + +I=305 +KEY=765EF7D33E6404858DF8675AFD458BFD +IV=FE0C3F22E6B467DC1C628C928D03DB5B +PT=279791AC4189634A6066BCDCAA2EF9B4 +CT=7F3ABBA943C8E3EF19C3BA2C98C9685F + +I=306 +KEY=09644C7A7DACE76A943BDD76658CE3A2 +IV=7F3ABBA943C8E3EF19C3BA2C98C9685F +PT=E46E5FB6019BA52524A383A18A89583A +CT=C96D250343B134241221490AB39931DB + +I=307 +KEY=C00969793E1DD34E861A947CD615D279 +IV=C96D250343B134241221490AB39931DB +PT=A3A544B8982C2F9EA0CD0ABC4D6392E2 +CT=951D54AABDF6F5B70E700C4896EB2685 + +I=308 +KEY=55143DD383EB26F9886A983440FEF4FC +IV=951D54AABDF6F5B70E700C4896EB2685 +PT=43FEB2051478A02BA1F054C9E82F0209 +CT=1F90165BE29C6C86D09AD07B1C006CA6 + +I=309 +KEY=4A842B8861774A7F58F0484F5CFE985A +IV=1F90165BE29C6C86D09AD07B1C006CA6 +PT=558AD95B25BAB5205FB7E529C96E5B59 +CT=40C0A0427C12AB1F72A7ADF96F82D437 + +I=310 +KEY=0A448BCA1D65E1602A57E5B6337C4C6D +IV=40C0A0427C12AB1F72A7ADF96F82D437 +PT=BABA13A1244DEFF5E4A2AB8183775773 +CT=FB08FDF3BF4394BA1A92C45B7F5F3060 + +I=311 +KEY=F14C7639A22675DA30C521ED4C237C0D +IV=FB08FDF3BF4394BA1A92C45B7F5F3060 +PT=46E036ECCDBE88931E552E45CBBC2BDC +CT=311AE8C2B7CB633178874BDEEEE0602F + +I=312 +KEY=C0569EFB15ED16EB48426A33A2C31C22 +IV=311AE8C2B7CB633178874BDEEEE0602F +PT=4D5C919959478AD0D9862BA509233102 +CT=1DC85D9A8877C79698C7D1C1610CBAE9 + +I=313 +KEY=DD9EC3619D9AD17DD085BBF2C3CFA6CB +IV=1DC85D9A8877C79698C7D1C1610CBAE9 +PT=D423E31E9FD6E4F4373FA7AD31CC6011 +CT=FC55E7BEA15BD539EDACB202F0218D4A + +I=314 +KEY=21CB24DF3CC104443D2909F033EE2B81 +IV=FC55E7BEA15BD539EDACB202F0218D4A +PT=52C2C696A4343C0F280A3BC8F6AA19EA +CT=FFD9FECD3A4EC194568A96C5A899E8D2 + +I=315 +KEY=DE12DA12068FC5D06BA39F359B77C353 +IV=FFD9FECD3A4EC194568A96C5A899E8D2 +PT=3B2266FAB514211E8E33AFA566898083 +CT=DC1A545F354365A0002180BACCE0AD25 + +I=316 +KEY=02088E4D33CCA0706B821F8F57976E76 +IV=DC1A545F354365A0002180BACCE0AD25 +PT=DC20E6BD8B8AC822CF2B505E580E6A80 +CT=51CF4C11F15B8B565B875F769C2FD37F + +I=317 +KEY=53C7C25CC2972B26300540F9CBB8BD09 +IV=51CF4C11F15B8B565B875F769C2FD37F +PT=67B4C3E2AFC3402901549265186303FB +CT=A118B7E5B10DAB4DDB449877AB1E6897 + +I=318 +KEY=F2DF75B9739A806BEB41D88E60A6D59E +IV=A118B7E5B10DAB4DDB449877AB1E6897 +PT=971952EE322CD68462B4CE8B772BBA48 +CT=A2988AAC94D8A7EFB32B34CC07911F3E + +I=319 +KEY=5047FF15E7422784586AEC426737CAA0 +IV=A2988AAC94D8A7EFB32B34CC07911F3E +PT=64C2665506EDDED98EC55D2CCED7762C +CT=86AEB7B90565D05293A8D9146880C307 + +I=320 +KEY=D6E948ACE227F7D6CBC235560FB709A7 +IV=86AEB7B90565D05293A8D9146880C307 +PT=A5E7E411209DD2A34AA8CDA3153A69E4 +CT=27746442FAC1DF26B11A55251AAFD865 + +I=321 +KEY=F19D2CEE18E628F07AD860731518D1C2 +IV=27746442FAC1DF26B11A55251AAFD865 +PT=83A41EF5F664A909BC47939D7858C221 +CT=619A164C3F2119FFCA3832A5EA958E01 + +I=322 +KEY=90073AA227C7310FB0E052D6FF8D5FC3 +IV=619A164C3F2119FFCA3832A5EA958E01 +PT=1F5A31EBB2C515728DB07EE3160D03CD +CT=DEE1692D386EF5A8861BE5D8A4630906 + +I=323 +KEY=4EE6538F1FA9C4A736FBB70E5BEE56C5 +IV=DEE1692D386EF5A8861BE5D8A4630906 +PT=297B343F5EE6221FB6CC40E0C836B387 +CT=B2BA45B0A776A950C32DD5F302201FC3 + +I=324 +KEY=FC5C163FB8DF6DF7F5D662FD59CE4906 +IV=B2BA45B0A776A950C32DD5F302201FC3 +PT=CC3601DC94B13116DF3012860A522D2D +CT=6D141746B23B4E1EF20DFE6C14D6ECE4 + +I=325 +KEY=914801790AE423E907DB9C914D18A5E2 +IV=6D141746B23B4E1EF20DFE6C14D6ECE4 +PT=FE07DA9A6E8B712B1FDFC3C1CC87146D +CT=0D80E8F5557A88A271133F8929125C72 + +I=326 +KEY=9CC8E98C5F9EAB4B76C8A318640AF990 +IV=0D80E8F5557A88A271133F8929125C72 +PT=EBDC0192755A685D6275532E93D33890 +CT=B88A629A8E22A78BAF98C9E623F48134 + +I=327 +KEY=24428B16D1BC0CC0D9506AFE47FE78A4 +IV=B88A629A8E22A78BAF98C9E623F48134 +PT=78AD3067BE2E9536ADB58DA49D7CA6DA +CT=0A9C2D318240F4FA4FF91CC5D23A371F + +I=328 +KEY=2EDEA62753FCF83A96A9763B95C44FBB +IV=0A9C2D318240F4FA4FF91CC5D23A371F +PT=04C72A08CCC36B4211AFE98637C4CEFF +CT=A42618A89B9E618DDD7A983081E086B9 + +I=329 +KEY=8AF8BE8FC86299B74BD3EE0B1424C902 +IV=A42618A89B9E618DDD7A983081E086B9 +PT=22D4A346027B8E5FEE1C0C0C45CA7DCB +CT=7CC4479AE05A295723F27545E1A46B7B + +I=330 +KEY=F63CF9152838B0E068219B4EF580A279 +IV=7CC4479AE05A295723F27545E1A46B7B +PT=05090A5C8F3CD0E7F7EA11B33CDF3C1D +CT=815BCEB2A29EA2A491C8E39B117790EC + +I=331 +KEY=776737A78AA61244F9E978D5E4F73295 +IV=815BCEB2A29EA2A491C8E39B117790EC +PT=7B40F8A4AC0E4C6BD73A59FFC91CA77D +CT=E4ED412F3ECDD4B7409BEEAEDC2C755F + +I=332 +KEY=938A7688B46BC6F3B972967B38DB47CA +IV=E4ED412F3ECDD4B7409BEEAEDC2C755F +PT=047E2E4681A97ED20308F1FE4B132F7B +CT=10153209AED4115329587180D65A0B97 + +I=333 +KEY=839F44811ABFD7A0902AE7FBEE814C5D +IV=10153209AED4115329587180D65A0B97 +PT=32671E6C0D28744AB457587BBB6DD21E +CT=847F781EDF77A870C4EA99CCC1721917 + +I=334 +KEY=07E03C9FC5C87FD054C07E372FF3554A +IV=847F781EDF77A870C4EA99CCC1721917 +PT=EC3159B002B95054F00D57049D91E32B +CT=05CC06529764F6747FCB2B62569C428C + +I=335 +KEY=022C3ACD52AC89A42B0B5555796F17C6 +IV=05CC06529764F6747FCB2B62569C428C +PT=9A930743113957D10EC643D8D8034C73 +CT=D1C7957073C2A44D9483DD11F3FA2B1E + +I=336 +KEY=D3EBAFBD216E2DE9BF8888448A953CD8 +IV=D1C7957073C2A44D9483DD11F3FA2B1E +PT=2E061A5B483D0D834D3019954E54CF80 +CT=0AC3300C59DB7A76A1E16DC5BF167B70 + +I=337 +KEY=D9289FB178B5579F1E69E581358347A8 +IV=0AC3300C59DB7A76A1E16DC5BF167B70 +PT=2A6E00DF7820913341D26EF611A7BEC1 +CT=5A5A1BE396D3C56DB0690B92A925D8D8 + +I=338 +KEY=83728452EE6692F2AE00EE139CA69F70 +IV=5A5A1BE396D3C56DB0690B92A925D8D8 +PT=E871C79BA6132F15C80A85F4BC732E77 +CT=829ABA07496E1269437680257308029D + +I=339 +KEY=01E83E55A708809BED766E36EFAE9DED +IV=829ABA07496E1269437680257308029D +PT=5955643AB76251E6AF97BC2490D09A72 +CT=3FEDBF80B703D067126EF55B02A41175 + +I=340 +KEY=3E0581D5100B50FCFF189B6DED0A8C98 +IV=3FEDBF80B703D067126EF55B02A41175 +PT=32BCF86ECA6CCE8F9C1C87AD9FDF8238 +CT=B59D6C5FCA91EDBFE75E795638CAD286 + +I=341 +KEY=8B98ED8ADA9ABD431846E23BD5C05E1E +IV=B59D6C5FCA91EDBFE75E795638CAD286 +PT=01A08051FC1D98C1BDAE4CA1D41D91E6 +CT=21CB8EF8BBE6C371A26BFF92701C3D1A + +I=342 +KEY=AA536372617C7E32BA2D1DA9A5DC6304 +IV=21CB8EF8BBE6C371A26BFF92701C3D1A +PT=5F5D891DF8D595D3FEDAEF0174B0A1D1 +CT=23D0FB6489113D3D4AA6470210698391 + +I=343 +KEY=89839816E86D430FF08B5AABB5B5E095 +IV=23D0FB6489113D3D4AA6470210698391 +PT=54FEAB37EFCD36D28E943DD85E803812 +CT=45F0556ED9A8ED0E1C8B0A0BA648E069 + +I=344 +KEY=CC73CD7831C5AE01EC0050A013FD00FC +IV=45F0556ED9A8ED0E1C8B0A0BA648E069 +PT=7AF4BC398ACAD37F526BDE12F3ED59ED +CT=C41E115EE06FFE5DED10480A1BE5B720 + +I=345 +KEY=086DDC26D1AA505C011018AA0818B7DC +IV=C41E115EE06FFE5DED10480A1BE5B720 +PT=CF15E4B6DDF60A4EE0CB6CBFA8AD499B +CT=1098A41E2C97C9D70626E4D1841F5CC1 + +I=346 +KEY=18F57838FD3D998B0736FC7B8C07EB1D +IV=1098A41E2C97C9D70626E4D1841F5CC1 +PT=BAD4050A0013AB8BC556F367AB634D94 +CT=D9B58211EB935246A5E04FCD3BE10B54 + +I=347 +KEY=C140FA2916AECBCDA2D6B3B6B7E6E049 +IV=D9B58211EB935246A5E04FCD3BE10B54 +PT=CEFF0AF7EF4EA7EF3B0E8BF7FB756E77 +CT=50FAE8C770EF7F9D5FE93B090B9D5C66 + +I=348 +KEY=91BA12EE6641B450FD3F88BFBC7BBC2F +IV=50FAE8C770EF7F9D5FE93B090B9D5C66 +PT=3B8C412B4156B413AD06CB181B4C5EAA +CT=E47249D4B5F24FF415B0E669EBF471B1 + +I=349 +KEY=75C85B3AD3B3FBA4E88F6ED6578FCD9E +IV=E47249D4B5F24FF415B0E669EBF471B1 +PT=56C612C5C594CAFB7B1CE8131E786DF0 +CT=6AF057199C217EECB886D940F61B91C5 + +I=350 +KEY=1F380C234F9285485009B796A1945C5B +IV=6AF057199C217EECB886D940F61B91C5 +PT=5629EF768743AB63D5B79B511C0A6BEF +CT=A5A76C330984D34310D021A6C2BDE9BC + +I=351 +KEY=BA9F60104616560B40D996306329B5E7 +IV=A5A76C330984D34310D021A6C2BDE9BC +PT=ED8DF427A02692C09D7AAEF2EDAA1249 +CT=8AAEFBA5DE0AAA41D947E3238B279913 + +I=352 +KEY=30319BB5981CFC4A999E7513E80E2CF4 +IV=8AAEFBA5DE0AAA41D947E3238B279913 +PT=949339605F30310FC557F2CA4815B034 +CT=9408BCB67EA573E7B5359B67918C16B9 + +I=353 +KEY=A4392703E6B98FAD2CABEE7479823A4D +IV=9408BCB67EA573E7B5359B67918C16B9 +PT=03607642CBBCCA2134837AC4BB452682 +CT=90660AF3DD0EAC1B61BB60EB49408586 + +I=354 +KEY=345F2DF03BB723B64D108E9F30C2BFCB +IV=90660AF3DD0EAC1B61BB60EB49408586 +PT=DE00E32930E14BD4297F9D789D0C25A1 +CT=1C48AC020174C0D87443229C113E2838 + +I=355 +KEY=281781F23AC3E36E3953AC0321FC97F3 +IV=1C48AC020174C0D87443229C113E2838 +PT=9CA7A04855F8404176D7D30B594B65AC +CT=7ACCB3FD4F9C7A5BFB83A969EB6D211A + +I=356 +KEY=52DB320F755F9935C2D0056ACA91B6E9 +IV=7ACCB3FD4F9C7A5BFB83A969EB6D211A +PT=DC0B392E998A347ECB789A51A09F1B1D +CT=22BED79EF2CAFF83BE8CEE5D7001DE21 + +I=357 +KEY=7065E591879566B67C5CEB37BA9068C8 +IV=22BED79EF2CAFF83BE8CEE5D7001DE21 +PT=07210334590A9314031D98F7DFBB84B9 +CT=44B16879886BC331407D1E7C7F247A04 + +I=358 +KEY=34D48DE80FFEA5873C21F54BC5B412CC +IV=44B16879886BC331407D1E7C7F247A04 +PT=27DDF18405E56989E59ED442C8825DD6 +CT=2787AD57159450916A45C72D0E074D53 + +I=359 +KEY=135320BF1A6AF51656643266CBB35F9F +IV=2787AD57159450916A45C72D0E074D53 +PT=4F43202A454BB0F3A9440DA558BEE228 +CT=3C1B83C66CEEEB27644BC66ACC3117E8 + +I=360 +KEY=2F48A37976841E31322FF40C07824877 +IV=3C1B83C66CEEEB27644BC66ACC3117E8 +PT=28ED6A88BDE4ADEFDA5C0F629109A7A3 +CT=B6009481F8C5D3EE37C645CF238238A1 + +I=361 +KEY=994837F88E41CDDF05E9B1C3240070D6 +IV=B6009481F8C5D3EE37C645CF238238A1 +PT=48DC5A3700CD4A7A9B066DC0E2667544 +CT=C1A20854601D7A81CAC51E9237BDC030 + +I=362 +KEY=58EA3FACEE5CB75ECF2CAF5113BDB0E6 +IV=C1A20854601D7A81CAC51E9237BDC030 +PT=1F84C71120B50FDF715B60DB69DECBE0 +CT=663EDB4EFD3F6AC2259A43C926ACE66D + +I=363 +KEY=3ED4E4E21363DD9CEAB6EC983511568B +IV=663EDB4EFD3F6AC2259A43C926ACE66D +PT=D6F9C59367A57E1DBDC2F4627524BC9A +CT=CA84A10F987212D75B744A7966ABBABA + +I=364 +KEY=F45045ED8B11CF4BB1C2A6E153BAEC31 +IV=CA84A10F987212D75B744A7966ABBABA +PT=1D8BC84060844CE5C40C716F2190C2BB +CT=ABAEEB339C4D150E894392444E021710 + +I=365 +KEY=5FFEAEDE175CDA45388134A51DB8FB21 +IV=ABAEEB339C4D150E894392444E021710 +PT=1300843AABCFB110198F0F0102C0A4D5 +CT=DBA9A1F8EE9AB8300D0273F71EAC5D1C + +I=366 +KEY=84570F26F9C66275358347520314A63D +IV=DBA9A1F8EE9AB8300D0273F71EAC5D1C +PT=1EA11B05D7DA9D770BA9AB619267B7A3 +CT=4921F1CB4A9AA6594C205D8FF0B2DEC9 + +I=367 +KEY=CD76FEEDB35CC42C79A31ADDF3A678F4 +IV=4921F1CB4A9AA6594C205D8FF0B2DEC9 +PT=9ABA414156563E88A8CCDB3BD226F66C +CT=4CF623AC6E145E2D61CAD28BFBF1F1E5 + +I=368 +KEY=8180DD41DD489A011869C85608578911 +IV=4CF623AC6E145E2D61CAD28BFBF1F1E5 +PT=FEF20625FA0C788DB8A20298F6933F6F +CT=67C491A5CA1A065980BDECE44B7979F1 + +I=369 +KEY=E6444CE417529C5898D424B2432EF0E0 +IV=67C491A5CA1A065980BDECE44B7979F1 +PT=79C4A475D0E064D72D48AF6357A0E6A0 +CT=529766CDD1223ED05C055108F91E6526 + +I=370 +KEY=B4D32A29C670A288C4D175BABA3095C6 +IV=529766CDD1223ED05C055108F91E6526 +PT=0758AA9195AE8684B9FEEBEF8E1226AE +CT=2AEC009219ECD0499DD729352C220E7D + +I=371 +KEY=9E3F2ABBDF9C72C159065C8F96129BBB +IV=2AEC009219ECD0499DD729352C220E7D +PT=886713433798AB16E87A8AD3A8CD0C87 +CT=0DE2A7554E343B6FFC6D1ECF4A8AF0DD + +I=372 +KEY=93DD8DEE91A849AEA56B4240DC986B66 +IV=0DE2A7554E343B6FFC6D1ECF4A8AF0DD +PT=984E8BA3DFFB4E9A1244D65BEA7DC594 +CT=8111340B4AF2CD82FF15447143069276 + +I=373 +KEY=12CCB9E5DB5A842C5A7E06319F9EF910 +IV=8111340B4AF2CD82FF15447143069276 +PT=A4F6C8ACF4F1050D11E42FEF1B6C8B68 +CT=BB4693FA1399583EACB21D2675E6D156 + +I=374 +KEY=A98A2A1FC8C3DC12F6CC1B17EA782846 +IV=BB4693FA1399583EACB21D2675E6D156 +PT=C5DBE1A937D6EA2FDD9A1A2FD25217B9 +CT=BC01B078339637D796F822B7E58D968D + +I=375 +KEY=158B9A67FB55EBC5603439A00FF5BECB +IV=BC01B078339637D796F822B7E58D968D +PT=DBD0494B0FE3149F8BCB8A70D344E811 +CT=600C1EFBDCA314A6F9714DEE413B9BD2 + +I=376 +KEY=7587849C27F6FF639945744E4ECE2519 +IV=600C1EFBDCA314A6F9714DEE413B9BD2 +PT=FCA88DCB484317D7F886E7437BC9E669 +CT=2E3788A647105DD0A286E2EFFD469C99 + +I=377 +KEY=5BB00C3A60E6A2B33BC396A1B388B980 +IV=2E3788A647105DD0A286E2EFFD469C99 +PT=65AF28E41B3DA5ACE3B2CC9A25EAD28C +CT=5411E48B57058A52C8560423BCFFBCD2 + +I=378 +KEY=0FA1E8B137E328E1F39592820F770552 +IV=5411E48B57058A52C8560423BCFFBCD2 +PT=6DD82A9F1CF0A5134A76899B04BE37D5 +CT=C3F69C8ED682BF252D5119D1695126E1 + +I=379 +KEY=CC57743FE16197C4DEC48B53662623B3 +IV=C3F69C8ED682BF252D5119D1695126E1 +PT=DE729AB3803144FD958D8597396BC8ED +CT=0941B78975FD2945B4AA81E8C58E3CB2 + +I=380 +KEY=C516C3B6949CBE816A6E0ABBA3A81F01 +IV=0941B78975FD2945B4AA81E8C58E3CB2 +PT=D8404E7A17254EB40683A8919A9563B4 +CT=BF647E0346C013E138A2F0B06E7BB142 + +I=381 +KEY=7A72BDB5D25CAD6052CCFA0BCDD3AE43 +IV=BF647E0346C013E138A2F0B06E7BB142 +PT=214089EC2996CE9FA2BBFEFBCAC03509 +CT=AFDA67B9451FF758CC87BBD93C7D4BE4 + +I=382 +KEY=D5A8DA0C97435A389E4B41D2F1AEE5A7 +IV=AFDA67B9451FF758CC87BBD93C7D4BE4 +PT=9406E9D4FB4592A609BBDB23CE5F9D7F +CT=B18202E4CA510695540371A8B6523616 + +I=383 +KEY=642AD8E85D125CADCA48307A47FCD3B1 +IV=B18202E4CA510695540371A8B6523616 +PT=FEE45BE0503B4093747AFCEA9881D30D +CT=64E149A4A1840F93D675B041ED81D45A + +I=384 +KEY=00CB914CFC96533E1C3D803BAA7D07EB +IV=64E149A4A1840F93D675B041ED81D45A +PT=880368D5609350167C7826DA30DCFF59 +CT=65A363E9837DFBBDA2688E6F4FBE6C35 + +I=385 +KEY=6568F2A57FEBA883BE550E54E5C36BDE +IV=65A363E9837DFBBDA2688E6F4FBE6C35 +PT=29C5940D09A8723B441FC469C909813A +CT=2A47FDF5BF600891DF4D9E8AA34748BA + +I=386 +KEY=4F2F0F50C08BA012611890DE46842364 +IV=2A47FDF5BF600891DF4D9E8AA34748BA +PT=20AF0FF7BAC0F468C12BD2816A8B1620 +CT=68A637E4B94EC150C84A6EBB005BB79B + +I=387 +KEY=278938B479C56142A952FE6546DF94FF +IV=68A637E4B94EC150C84A6EBB005BB79B +PT=42906D013A3F0A426B01B489ECA6CAD7 +CT=A090CA02FCD40F01CA0D1A699E30C164 + +I=388 +KEY=8719F2B685116E43635FE40CD8EF559B +IV=A090CA02FCD40F01CA0D1A699E30C164 +PT=05A02D4D7D90BCA74ECE791CD865CB88 +CT=F70109F0EBBA56959B3013565E2BDFFC + +I=389 +KEY=7018FB466EAB38D6F86FF75A86C48A67 +IV=F70109F0EBBA56959B3013565E2BDFFC +PT=C373AB7B8F770212F9D5CEF40099086C +CT=67221CC1F104809B8A5D35431963812D + +I=390 +KEY=173AE7879FAFB84D7232C2199FA70B4A +IV=67221CC1F104809B8A5D35431963812D +PT=8C59B2A7FD50EC66ABACC0531BE33237 +CT=E06166175F68155DB86E268F3C5524AE + +I=391 +KEY=F75B8190C0C7AD10CA5CE496A3F22FE4 +IV=E06166175F68155DB86E268F3C5524AE +PT=D39790AED2970355A6337AAD2CA4D501 +CT=85E89883242A3B68F4AAF922646EB385 + +I=392 +KEY=72B31913E4ED96783EF61DB4C79C9C61 +IV=85E89883242A3B68F4AAF922646EB385 +PT=87D4160C7C97476D0884A22B5983AA65 +CT=038C79FDFAA0B4F4AD9DC336F46CACDF + +I=393 +KEY=713F60EE1E4D228C936BDE8233F030BE +IV=038C79FDFAA0B4F4AD9DC336F46CACDF +PT=3B59088B5ADC77E4B3FC31897C6389B5 +CT=F6C92ECB3332E5E93C9DE29F27F94BB3 + +I=394 +KEY=87F64E252D7FC765AFF63C1D14097B0D +IV=F6C92ECB3332E5E93C9DE29F27F94BB3 +PT=68BA9BEBB40B3E35D2E577A2831CF9DB +CT=7B72342488233DAD5ACF0A8D54EA9E8B + +I=395 +KEY=FC847A01A55CFAC8F539369040E3E586 +IV=7B72342488233DAD5ACF0A8D54EA9E8B +PT=7816251219B8C7F009ADD7A1898D02CF +CT=45CBA66AD6045917C3E8257D3ECBECDB + +I=396 +KEY=B94FDC6B7358A3DF36D113ED7E28095D +IV=45CBA66AD6045917C3E8257D3ECBECDB +PT=F542FEAB12E2EA9AE761E58108784E37 +CT=82E289465F5838036B9880C33AEBCB83 + +I=397 +KEY=3BAD552D2C009BDC5D49932E44C3C2DE +IV=82E289465F5838036B9880C33AEBCB83 +PT=3B8208791DAE56383CC2BCB44097C9D3 +CT=F02F2B89DE46D01F46AD95C82AF0C20E + +I=398 +KEY=CB827EA4F2464BC31BE406E66E3300D0 +IV=F02F2B89DE46D01F46AD95C82AF0C20E +PT=3F2C0F7A0AEAB04F318C661ABCFED153 +CT=8D4FAF6332578524301ACA22AD86965B + +I=399 +KEY=46CDD1C7C011CEE72BFECCC4C3B5968B +IV=8D4FAF6332578524301ACA22AD86965B +PT=A27200B51D69AAC22F1C567F8BCEABFA +CT=2F844CBF78EBA70DA7A49601388F1AB6 + +========== + +KEYSIZE=192 + +I=0 +KEY=000000000000000000000000000000000000000000000000 +IV=00000000000000000000000000000000 +PT=00000000000000000000000000000000 +CT=7BD966D53AD8C1BB85D2ADFAE87BB104 + +I=1 +KEY=506339DAE3B35BEB7BD966D53AD8C1BB85D2ADFAE87BB104 +IV=7BD966D53AD8C1BB85D2ADFAE87BB104 +PT=0555C410F44C7AA4506339DAE3B35BEB +CT=869C061BE9CFEAB5D285B0724A9A8970 + +I=2 +KEY=74D3414C2374367BFD4560CED3172B0E57571D88A2E13874 +IV=869C061BE9CFEAB5D285B0724A9A8970 +PT=C6FB25A188CF7F3F24B07896C0C76D90 +CT=9E58A52B3840DBE16E8063A18220FEE4 + +I=3 +KEY=DDE2DF4EEC312FA3631DC5E5EB57F0EF39D77E2920C1C690 +IV=9E58A52B3840DBE16E8063A18220FEE4 +PT=84E3D4168A8469A6A9319E02CF4519D8 +CT=730A256C202B9D57F3C0D73AD4B6CBED + +I=4 +KEY=9D973AECAF19E9951017E089CB7C6DB8CA17A913F4770D7D +IV=730A256C202B9D57F3C0D73AD4B6CBED +PT=E000CE26CD3185B44075E5A24328C636 +CT=E79EF11C5C1FD1AB75280BCFFCFE89D4 + +I=5 +KEY=7A52007B2C40C9F4F78911959763BC13BF3FA2DC088984A9 +IV=E79EF11C5C1FD1AB75280BCFFCFE89D4 +PT=19D79403BB238816E7C53A9783592061 +CT=65744444724F1052D0B8674EDC8083B5 + +I=6 +KEY=40D50426A8D09F3292FD55D1E52CAC416F87C592D409071C +IV=65744444724F1052D0B8674EDC8083B5 +PT=FDFA33685E2B5BBC3A87045D849056C6 +CT=23C6377D3D076491AD93E2B6112289C7 + +I=7 +KEY=6FD062412FE1AE4EB13B62ACD82BC8D0C2142724C52B8EDB +IV=23C6377D3D076491AD93E2B6112289C7 +PT=5056DDDEF15831502F0566678731317C +CT=F13A83088536BF30E5E9018BE57D7D89 + +I=8 +KEY=EB4DB5F469D0EE9B4001E1A45D1D77E027FD26AF2056F352 +IV=F13A83088536BF30E5E9018BE57D7D89 +PT=0EE535A4A524668F849DD7B5463140D5 +CT=3F496CB19B21C37159528BF345473E6D + +I=9 +KEY=AA6E5744B909D9A87F488D15C63CB4917EAFAD5C6511CD3F +IV=3F496CB19B21C37159528BF345473E6D +PT=3A11F90EB51C81ED4123E2B0D0D93733 +CT=CF79C1EDEE17A68DC7E673006AEC90D9 + +I=10 +KEY=64AB0C0C9471B77FB0314CF8282B121CB949DE5C0FFD5DE6 +IV=CF79C1EDEE17A68DC7E673006AEC90D9 +PT=85187E7F91280A5BCEC55B482D786ED7 +CT=92D1757BEBCE6E0406407819AF82353F + +I=11 +KEY=9E5720C1DC2E285C22E03983C3E57C18BF09A645A07F68D9 +IV=92D1757BEBCE6E0406407819AF82353F +PT=45147511BC08EC76FAFC2CCD485F9F23 +CT=8C0228F57523D746E67D27A8E6C426D9 + +I=12 +KEY=EBBB8245582E4367AEE21176B6C6AB5E597481ED46BB4E00 +IV=8C0228F57523D746E67D27A8E6C426D9 +PT=73B9EEAC644CBB8875ECA28484006B3B +CT=D0025BF1FC35DD9BDA20F42DF775AF71 + +I=13 +KEY=5F938EE9CC63C9E87EE04A874AF376C5835475C0B1CEE171 +IV=D0025BF1FC35DD9BDA20F42DF775AF71 +PT=DE2507F01BC8B212B4280CAC944D8A8F +CT=3FDDD3E04B2CBE79BB07D82182CD3787 + +I=14 +KEY=B94E2EC5F6E86EDC413D996701DFC8BC3853ADE13303D6F6 +IV=3FDDD3E04B2CBE79BB07D82182CD3787 +PT=90CE32BCC16C20F7E6DDA02C3A8BA734 +CT=F7B491E4C40B60BE8ACF16D68E3ED60F + +I=15 +KEY=DE41ABD8C44F5DF6B6890883C5D4A802B29CBB37BD3D00F9 +IV=F7B491E4C40B60BE8ACF16D68E3ED60F +PT=B7ACCA62BB9974BC670F851D32A7332A +CT=7ED4055D367CB31A4CF1CC17132E00B5 + +I=16 +KEY=E2A57C71F23BC4DEC85D0DDEF3A81B18FE6D7720AE13004C +IV=7ED4055D367CB31A4CF1CC17132E00B5 +PT=1CA59C2384797B803CE4D7A936749928 +CT=8D50A87F14D466323929BB52FA60FA42 + +I=17 +KEY=2FA1A78B8BCC301C450DA5A1E77C7D2AC744CC725473FA0E +IV=8D50A87F14D466323929BB52FA60FA42 +PT=0A623319F2A051ACCD04DBFA79F7F4C2 +CT=7C02D378606FC33DFCEF8AA2A000383E + +I=18 +KEY=A949CE493892DF58390F76D98713BE173BAB46D0F473C230 +IV=7C02D378606FC33DFCEF8AA2A000383E +PT=EE8F5FF6A7FF813386E869C2B35EEF44 +CT=CAE55B9CCBB5A68EBF0D2AB55E079FD4 + +I=19 +KEY=E159445FE4201A6CF3EA2D454CA6189984A66C65AA745DE4 +IV=CAE55B9CCBB5A68EBF0D2AB55E079FD4 +PT=9699456986535C4648108A16DCB2C534 +CT=9056685FBFECC7A6143DB5AC314DAC88 + +I=20 +KEY=EE4F7BF96BF1163E63BC451AF34ADF3F909BD9C99B39F16C +IV=9056685FBFECC7A6143DB5AC314DAC88 +PT=16D6C34C3B57AC0A0F163FA68FD10C52 +CT=4D6A5542F0680CE37E88119141F321F5 + +I=21 +KEY=27F8CEE0120E8A0F2ED610580322D3DCEE13C858DACAD099 +IV=4D6A5542F0680CE37E88119141F321F5 +PT=337839926E36EC77C9B7B51979FF9C31 +CT=78E16D6027F0D190E78825C2F52E5364 + +I=22 +KEY=0AF4D3D8EB9FF18A56377D3824D2024C099BED9A2FE483FD +IV=78E16D6027F0D190E78825C2F52E5364 +PT=8F96B66F934467C72D0C1D38F9917B85 +CT=82A81B33F80A105DD7D9CC6DDFECDB96 + +I=23 +KEY=AD2AFC821170D967D49F660BDCD81211DE4221F7F008586B +IV=82A81B33F80A105DD7D9CC6DDFECDB96 +PT=E2CB8E6E329C6660A7DE2F5AFAEF28ED +CT=0BCD68A063BA3540B3E04C885DF45BD0 + +I=24 +KEY=5B50EE72BD6CE837DF520EABBF6227516DA26D7FADFC03BB +IV=0BCD68A063BA3540B3E04C885DF45BD0 +PT=31A14C64CD8BCC8FF67A12F0AC1C3150 +CT=DB27EA5834BF572EA50E03E0773C1010 + +I=25 +KEY=BF4D8A58F54D47620475E4F38BDD707FC8AC6E9FDAC013AB +IV=DB27EA5834BF572EA50E03E0773C1010 +PT=26755B5C0BE60998E41D642A4821AF55 +CT=655A896243B5E86B2F74299A317A2E4C + +I=26 +KEY=8DC190D88B17EAB9612F6D91C8689814E7D84705EBBA3DE7 +IV=655A896243B5E86B2F74299A317A2E4C +PT=C6920ADCED82F661328C1A807E5AADDB +CT=9F45472FDBB732C745AD228810392EA2 + +I=27 +KEY=B44071C6F14CDA97FE6A2ABE13DFAAD3A275658DFB831345 +IV=9F45472FDBB732C745AD228810392EA2 +PT=2178DFA9784E563E3981E11E7A5B302E +CT=9F985FBF08235845E396BFCE54BCE7C8 + +I=28 +KEY=A3C12E42B53D829E61F275011BFCF29641E3DA43AF3FF48D +IV=9F985FBF08235845E396BFCE54BCE7C8 +PT=44977E2274DA25AE17815F8444715809 +CT=033EAF4FAC934D123012279B1663C80B + +I=29 +KEY=8FD2B79E25E39C4A62CCDA4EB76FBF8471F1FDD8B95C3C86 +IV=033EAF4FAC934D123012279B1663C80B +PT=425088D4626CD7972C1399DC90DE1ED4 +CT=A962CB4707B0048BB81F4225EFC85E48 + +I=30 +KEY=3D68793EF46B8125CBAE1109B0DFBB0FC9EEBFFD569462CE +IV=A962CB4707B0048BB81F4225EFC85E48 +PT=EF21ED587C272175B2BACEA0D1881D6F +CT=6F3A0D63A22C003F7F65B09098F667DB + +I=31 +KEY=6A4FB651BE9D0BAFA4941C6A12F3BB30B68B0F6DCE620515 +IV=6F3A0D63A22C003F7F65B09098F667DB +PT=16054E60B460B2D15727CF6F4AF68A8A +CT=8BB46230FF03665765F2E5AAEA14104F + +I=32 +KEY=3F5991D63C15A1822F207E5AEDF0DD67D379EAC72476155A +IV=8BB46230FF03665765F2E5AAEA14104F +PT=82D0B12FEA88917F551627878288AA2D +CT=8E1A664131FAB09E786E111C3C20A7BB + +I=33 +KEY=456F69D38929ED82A13A181BDC0A6DF9AB17FBDB1856B2E1 +IV=8E1A664131FAB09E786E111C3C20A7BB +PT=1384D3B7CAEB528A7A36F805B53C4C00 +CT=92D99BF1D71026D2BF78E32421E34E52 + +I=34 +KEY=658891F63379484C33E383EA0B1A4B2B146F18FF39B5FCB3 +IV=92D99BF1D71026D2BF78E32421E34E52 +PT=9F60C3117269E88920E7F825BA50A5CE +CT=7DB6782C68EC5FC75A2A75E4EA7B4071 + +I=35 +KEY=9193E2EACE8423F64E55FBC663F614EC4E456D1BD3CEBCC2 +IV=7DB6782C68EC5FC75A2A75E4EA7B4071 +PT=232ECA0370EBD920F41B731CFDFD6BBA +CT=D76A1E73E977533E6D7C74277DAFEB48 + +I=36 +KEY=F4C34FE273D0FCB5993FE5B58A8147D22339193CAE61578A +IV=D76A1E73E977533E6D7C74277DAFEB48 +PT=5BCD8C6C4D14321F6550AD08BD54DF43 +CT=4A69E9081DDD43A6061700C7DA8F5E73 + +I=37 +KEY=DC82C155896C5D5CD3560CBD975C0474252E19FB74EE09F9 +IV=4A69E9081DDD43A6061700C7DA8F5E73 +PT=C914BB961EA890D828418EB7FABCA1E9 +CT=91EE5BE28C27F055258BC3E1F37E2DEC + +I=38 +KEY=08F1655EA3656F1C42B8575F1B7BF42100A5DA1A87902415 +IV=91EE5BE28C27F055258BC3E1F37E2DEC +PT=11804F73D788115CD473A40B2A093240 +CT=86B9BE5AFD2A8A49E2651C314CAE0918 + +I=39 +KEY=59D7EFD92140A147C401E905E6517E68E2C0C62BCB3E2D0D +IV=86B9BE5AFD2A8A49E2651C314CAE0918 +PT=6E2A1E436926174E51268A878225CE5B +CT=C642F5ED78DB76738A89296B1C4A0932 + +I=40 +KEY=F6E75E7867D0FB4A02431CE89E8A081B6849EF40D774243F +IV=C642F5ED78DB76738A89296B1C4A0932 +PT=15896B8B864CF068AF30B1A146905A0D +CT=24288AE027547E499EBADE9260C8F037 + +I=41 +KEY=9A048C2BC98E15B2266B9608B9DE7652F6F331D2B7BCD408 +IV=24288AE027547E499EBADE9260C8F037 +PT=FF9A330C205DC3006CE3D253AE5EEEF8 +CT=BD9B3D670D24EDDA1EAD1DB06C8A83C7 + +I=42 +KEY=97E8C017644E9FED9BF0AB6FB4FA9B88E85E2C62DB3657CF +IV=BD9B3D670D24EDDA1EAD1DB06C8A83C7 +PT=C9A3916C34A7CCD90DEC4C3CADC08A5F +CT=1FCCBC65C44E4680E1593EE0EEFEA9A9 + +I=43 +KEY=3A2862113BD3312D843C170A70B4DD080907128235C8FE66 +IV=1FCCBC65C44E4680E1593EE0EEFEA9A9 +PT=EAF9C4A80EE93585ADC0A2065F9DAEC0 +CT=2C0004064936696B10D039D9795BABC7 + +I=44 +KEY=33FAE356C0C96F17A83C130C3982B46319D72B5B4C9355A1 +IV=2C0004064936696B10D039D9795BABC7 +PT=4181525880CA468909D28147FB1A5E3A +CT=79F193EB9A9A48464FF007D73E9B4106 + +I=45 +KEY=2136A7940C9B9FAFD1CD80E7A318FC2556272C8C720814A7 +IV=79F193EB9A9A48464FF007D73E9B4106 +PT=2899D75DFB84950E12CC44C2CC52F0B8 +CT=DA12307CE9A6BA0FCE5A76AE1747E619 + +I=46 +KEY=0C839679750274320BDFB09B4ABE462A987D5A22654FF2BE +IV=DA12307CE9A6BA0FCE5A76AE1747E619 +PT=2C71B8623CA5BF292DB531ED7999EB9D +CT=A59997FA19B58BC71CB05E7140386C94 + +I=47 +KEY=4D3CDB92797645C1AE462761530BCDED84CD045325779E2A +IV=A59997FA19B58BC71CB05E7140386C94 +PT=63F4FC202A1B921241BF4DEB0C7431F3 +CT=49E65D7422398035DD1E4EBAD37C699D + +I=48 +KEY=38082D7CC27EBABBE7A07A1571324DD859D34AE9F60BF7B7 +IV=49E65D7422398035DD1E4EBAD37C699D +PT=7F0E2FD5D4B5A0CB7534F6EEBB08FF7A +CT=64DF24483FC73174FB6482A6E2B895E0 + +I=49 +KEY=1557398CFBFF31F8837F5E5D4EF57CACA2B7C84F14B36257 +IV=64DF24483FC73174FB6482A6E2B895E0 +PT=0F525FCF2A1E3D612D5F14F039818B43 +CT=028880CC8AA1B92CB807F1102663E658 + +I=50 +KEY=229C31F1D34A529581F7DE91C454C5801AB0395F32D0840F +IV=028880CC8AA1B92CB807F1102663E658 +PT=219604B99FF2BE7B37CB087D28B5636D +CT=FAC8B66D1BA7849392CC235D0276110E + +I=51 +KEY=C75DE76D40D536277B3F68FCDFF34113887C1A0230A69501 +IV=FAC8B66D1BA7849392CC235D0276110E +PT=3319C80C038E565FE5C1D69C939F64B2 +CT=79770F286419EEFD855868EC4ADF3775 + +I=52 +KEY=5F0B08B451490B27024867D4BBEAAFEE0D2472EE7A79A274 +IV=79770F286419EEFD855868EC4ADF3775 +PT=E173A8580816CAFA9856EFD9119C3D00 +CT=FC0AA487B09DF657DB58DBF83E13E137 + +I=53 +KEY=E86E8BFBF1D65541FE42C3530B7759B9D67CA916446A4343 +IV=FC0AA487B09DF657DB58DBF83E13E137 +PT=01274C45F202C22CB765834FA09F5E66 +CT=9691EA44FC67CA29E50E7FF7DBC4D0CA + +I=54 +KEY=7849550CA6CCD87268D32917F71093903372D6E19FAE9389 +IV=9691EA44FC67CA29E50E7FF7DBC4D0CA +PT=026BD493499B7BA99027DEF7571A8D33 +CT=5206F7CF45A59FD6444CCBB6B034CF45 + +I=55 +KEY=52D81D6104DBF6DF3AD5DED8B2B50C46773E1D572F9A5CCC +IV=5206F7CF45A59FD6444CCBB6B034CF45 +PT=33CA15B3D921E7752A91486DA2172EAD +CT=F4A41D18E3EF9DE46917BADB1B5EC613 + +I=56 +KEY=36FB680165ABD632CE71C3C0515A91A21E29A78C34C49ADF +IV=F4A41D18E3EF9DE46917BADB1B5EC613 +PT=65F3084285AA869464237560617020ED +CT=6C4154D3245D2546979118A36120A911 + +I=57 +KEY=6E7548B98AA0640AA23097137507B4E489B8BF2F55E433CE +IV=6C4154D3245D2546979118A36120A911 +PT=6CF540F502D90886588E20B8EF0BB238 +CT=2A52376A7E494ADEDD53A416F73FE9C0 + +I=58 +KEY=A0D840A0E3CC1EA58862A0790B4EFE3A54EB1B39A2DBDA0E +IV=2A52376A7E494ADEDD53A416F73FE9C0 +PT=708AE2375F305572CEAD0819696C7AAF +CT=7A0EF052184147EA279839380B3DBB32 + +I=59 +KEY=153CF68E4A1C1FCEF26C502B130FB9D073732201A9E6613C +IV=7A0EF052184147EA279839380B3DBB32 +PT=A8267215107D3DD0B5E4B62EA9D0016B +CT=F193B80D57571F94A4F5373149163AA1 + +I=60 +KEY=E0B0657A66C37D8703FFE8264458A644D7861530E0F05B9D +IV=F193B80D57571F94A4F5373149163AA1 +PT=EE4B04302CB02990F58C93F42CDF6249 +CT=A28E99815C930AC05ADA4524A7E5968C + +I=61 +KEY=94760F8A93926E4DA17171A718CBAC848D5C50144715CD11 +IV=A28E99815C930AC05ADA4524A7E5968C +PT=34D122B717CBA59174C66AF0F55113CA +CT=6F9342E7915613450E823EC9A781DAA3 + +I=62 +KEY=0B352460A1579376CEE23340899DBFC183DE6EDDE09417B2 +IV=6F9342E7915613450E823EC9A781DAA3 +PT=D8689ED21F3EA8E29F432BEA32C5FD3B +CT=584BB944532A830F7F8DCDBE42E7DBFC + +I=63 +KEY=999A5CEB73DFCC1796A98A04DAB73CCEFC53A363A273CC4E +IV=584BB944532A830F7F8DCDBE42E7DBFC +PT=4E87F73D46D0C0AF92AF788BD2885F61 +CT=4AC372A4D3273C71F69D50168A9235A1 + +I=64 +KEY=42C59FFD5AA69C11DC6AF8A0099000BF0ACEF37528E1F9EF +IV=4AC372A4D3273C71F69D50168A9235A1 +PT=324DC9C2D34E95F9DB5FC31629795006 +CT=60E53CC2D5E4900D48A0C5F7EE3BC810 + +I=65 +KEY=843EBDEF0CEEBA5BBC8FC462DC7490B2426E3682C6DA31FF +IV=60E53CC2D5E4900D48A0C5F7EE3BC810 +PT=8B94F018A7115B3AC6FB22125648264A +CT=4BD7DF7DFD03A24809B751F59FACF417 + +I=66 +KEY=98E40853FA954FF5F7581B1F217732FA4BD967775976C5E8 +IV=4BD7DF7DFD03A24809B751F59FACF417 +PT=109C734AC21ED2631CDAB5BCF67BF5AE +CT=B7A3CF7E58A413C5065E9CFD23C750F9 + +I=67 +KEY=5419462C5329544A40FBD46179D3213F4D87FB8A7AB19511 +IV=B7A3CF7E58A413C5065E9CFD23C750F9 +PT=8CA507ACCDB3A793CCFD4E7FA9BC1BBF +CT=6285C3D0FD2645192C5DD046D73414CE + +I=68 +KEY=B58628819840885D227E17B184F5642661DA2BCCAD8581DF +IV=6285C3D0FD2645192C5DD046D73414CE +PT=7DE48BAD03BB9F53E19F6EADCB69DC17 +CT=583FBCEB09646CEC19D00620E5455FD5 + +I=69 +KEY=73F7F00EF22ED1B07A41AB5A8D9108CA780A2DEC48C0DE0A +IV=583FBCEB09646CEC19D00620E5455FD5 +PT=126D3F2A0BC1B168C671D88F6A6E59ED +CT=886A5273055AF7AE37EFB726DC90FD9E + +I=70 +KEY=69735F80F0B876DAF22BF92988CBFF644FE59ACA94502394 +IV=886A5273055AF7AE37EFB726DC90FD9E +PT=0B4D3F58D83D866A1A84AF8E0296A76A +CT=FD068F02BB6C2611EF78CD963EF2F78F + +I=71 +KEY=92E5FF32D46494880F2D762B33A7D975A09D575CAAA2D41B +IV=FD068F02BB6C2611EF78CD963EF2F78F +PT=705667CBCC87BF3DFB96A0B224DCE252 +CT=34713FD3FA07F0B3F94EC0FB17BB465F + +I=72 +KEY=A0DF9DCB873A1ADC3B5C49F8C9A029C659D397A7BD199244 +IV=34713FD3FA07F0B3F94EC0FB17BB465F +PT=4BF66F55275D6CB3323A62F9535E8E54 +CT=82C8A179661207B7FE178A266C607074 + +I=73 +KEY=2D1604ADAA49C3FBB994E881AFB22E71A7C41D81D179E230 +IV=82C8A179661207B7FE178A266C607074 +PT=167203BBB933707A8DC999662D73D927 +CT=DCDBCC8D11C632CB220C6E95B399A1CC + +I=74 +KEY=7D2C4B0C0D0B001A654F240CBE741CBA85C8731462E043FC +IV=DCDBCC8D11C632CB220C6E95B399A1CC +PT=668F998350BDA831503A4FA1A742C3E1 +CT=8827EBFCB24470266D5C0BA05D5974A4 + +I=75 +KEY=BE3A4CF21186C2C7ED68CFF00C306C9CE89478B43FB93758 +IV=8827EBFCB24470266D5C0BA05D5974A4 +PT=B8D1D48F3C41094EC31607FE1C8DC2DD +CT=61E59DECE1AEFFDEB9B216828953D70F + +I=76 +KEY=D0CE372842DC32508C8D521CED9E934251266E36B6EAE057 +IV=61E59DECE1AEFFDEB9B216828953D70F +PT=49A4495257D08AA56EF47BDA535AF097 +CT=ECD04FFB385CCC1D13C312A5C31810DE + +I=77 +KEY=E7274C14C4163169605D1DE7D5C25F5F42E57C9375F2F089 +IV=ECD04FFB385CCC1D13C312A5C31810DE +PT=3EED6F60FD9050A737E97B3C86CA0339 +CT=D9C90455AFBF5465F89752FB6F60BDFF + +I=78 +KEY=71E35A00CAFB898BB99419B27A7D0B3ABA722E681A924D76 +IV=D9C90455AFBF5465F89752FB6F60BDFF +PT=5CE6E7F07945191396C416140EEDB8E2 +CT=F6E795B326CFD6CCC0E230E4FE770878 + +I=79 +KEY=79DFA388989B29204F738C015CB2DDF67A901E8CE4E5450E +IV=F6E795B326CFD6CCC0E230E4FE770878 +PT=314A5784B7909F89083CF9885260A0AB +CT=6B3A00F05F79F25E4E9EDA81034A9B7B + +I=80 +KEY=75F6D5983AE6D7AC24498CF103CB2FA8340EC40DE7AFDE75 +IV=6B3A00F05F79F25E4E9EDA81034A9B7B +PT=DEC42B1A6184FDF80C297610A27DFE8C +CT=6A19BEA8826427E309BD55BCBBE246B4 + +I=81 +KEY=E47EEE65549BF1634E50325981AF084B3DB391B15C4D98C1 +IV=6A19BEA8826427E309BD55BCBBE246B4 +PT=63C46CFF49FF13B291883BFD6E7D26CF +CT=738C0B0E580C0B1ED488DDE8502CB754 + +I=82 +KEY=E6DBE45547556F403DDC3957D9A30355E93B4C590C612F95 +IV=738C0B0E580C0B1ED488DDE8502CB754 +PT=E951F5C902BD351502A50A3013CE9E23 +CT=389E33F3DAB3FAB7B2ACB853C0150B8D + +I=83 +KEY=EBA5A1BDF9FC558905420AA40310F9E25B97F40ACC742418 +IV=389E33F3DAB3FAB7B2ACB853C0150B8D +PT=54EFC45B4036B60D0D7E45E8BEA93AC9 +CT=EACAE8A4B5CCBDB28ED2162670DBD4B1 + +I=84 +KEY=B570945030615F75EF88E200B6DC4450D545E22CBCAFF0A9 +IV=EACAE8A4B5CCBDB28ED2162670DBD4B1 +PT=7F3BA6FE23AE45665ED535EDC99D0AFC +CT=535FEA61623ECD22FA1A95BF95320252 + +I=85 +KEY=F332D3DE8556F82EBCD70861D4E289722F5F7793299DF2FB +IV=535FEA61623ECD22FA1A95BF95320252 +PT=8FEB6943B22437D34642478EB537A75B +CT=CD23D928E1D3221E4D3C51670C071276 + +I=86 +KEY=1402D325D7EBA90871F4D1493531AB6C626326F4259AE08D +IV=CD23D928E1D3221E4D3C51670C071276 +PT=8B01EE4509B58B49E73000FB52BD5126 +CT=56DC7F1BE2CC26A369B3BCA71BF8FAB8 + +I=87 +KEY=389C95DC5BF411B62728AE52D7FD8DCF0BD09A533E621A35 +IV=56DC7F1BE2CC26A369B3BCA71BF8FAB8 +PT=9BFE561402B07B4C2C9E46F98C1FB8BE +CT=A059CFB443009F0ACD8E5051BD16C837 + +I=88 +KEY=89180FBFF0A12019877161E694FD12C5C65ECA028374D202 +IV=A059CFB443009F0ACD8E5051BD16C837 +PT=C8D55810C7A22E30B1849A63AB5531AF +CT=62CEB7D9A6D23B40CFD75990D1040BA4 + +I=89 +KEY=08BE01CF1E620DBEE5BFD63F322F2985098993925270D9A6 +IV=62CEB7D9A6D23B40CFD75990D1040BA4 +PT=F888764A970B03BC81A60E70EEC32DA7 +CT=F6D89003ABBF003AF013EB221AF17F99 + +I=90 +KEY=5EB9AC53FC544ADE1367463C999029BFF99A78B04881A63F +IV=F6D89003ABBF003AF013EB221AF17F99 +PT=26A25CFC1E699D8B5607AD9CE2364760 +CT=74C9E920DC16396E89774B82E7803EF5 + +I=91 +KEY=D8FAD6E8CDC96CEF67AEAF1C458610D170ED3332AF0198CA +IV=74C9E920DC16396E89774B82E7803EF5 +PT=76AFDD045A30FAA486437ABB319D2631 +CT=A5B997689B88AAC0611C2963C8C1B7CE + +I=92 +KEY=7E774E64A5F209B2C2173874DE0EBA1111F11A5167C02F04 +IV=A5B997689B88AAC0611C2963C8C1B7CE +PT=ABF525144D3415DEA68D988C683B655D +CT=7A2F39D97547C3CD336577E41C0483ED + +I=93 +KEY=0406C21AE6E015E0B83801ADAB4979DC22946DB57BC4ACE9 +IV=7A2F39D97547C3CD336577E41C0483ED +PT=E0C2466426630D1B7A718C7E43121C52 +CT=67899F7D0890E90383C05A7984604241 + +I=94 +KEY=D9249A4AFDF40BEADFB19ED0A3D990DFA15437CCFFA4EEA8 +IV=67899F7D0890E90383C05A7984604241 +PT=07E55341FCD016D7DD2258501B141E0A +CT=7B1CBCD270B09E9A1D15714D8366D174 + +I=95 +KEY=B2242464CD4D2448A4AD2202D3690E45BC4146817CC23FDC +IV=7B1CBCD270B09E9A1D15714D8366D174 +PT=25C6E62F44ABFF406B00BE2E30B92FA2 +CT=C86E27E5CA4461CE656D893A16477966 + +I=96 +KEY=602CDF824C043C836CC305E7192D6F8BD92CCFBB6A8546BA +IV=C86E27E5CA4461CE656D893A16477966 +PT=3F9D262E375F057BD208FBE6814918CB +CT=8129054CF746CB79112942AE35142E4D + +I=97 +KEY=73F82C9EE4B4D0E8EDEA00ABEE6BA4F2C8058D155F9168F7 +IV=8129054CF746CB79112942AE35142E4D +PT=7BC798EAC4C17B2D13D4F31CA8B0EC6B +CT=36F21910B1677AF19586E55E360FB8DD + +I=98 +KEY=E5FC538A60CC29A3DB1819BB5F0CDE035D83684B699ED02A +IV=36F21910B1677AF19586E55E360FB8DD +PT=D3E39037253E5BAA96047F148478F94B +CT=BA7CE80E0853D264368EE61D8E71EEBE + +I=99 +KEY=D9381EF81441B6C16164F1B5575F0C676B0D8E56E7EF3E94 +IV=BA7CE80E0853D264368EE61D8E71EEBE +PT=DE4FFDFADB81FABB3CC44D72748D9F62 +CT=971AD82D1F46F1087B37103B4BE5DD8C + +I=100 +KEY=A0BF8B4740D929C9F67E29984819FD6F103A9E6DAC0AE318 +IV=971AD82D1F46F1087B37103B4BE5DD8C +PT=FE6355B5D860522B798795BF54989F08 +CT=D17268155EE586F352BB031929441700 + +I=101 +KEY=477A0AB591FFEC5C270C418D16FC7B9C42819D74854EF418 +IV=D17268155EE586F352BB031929441700 +PT=166A50EEE05F4A39E7C581F2D126C595 +CT=2CD84FB5B587BE8B04638A9EDBA17AE2 + +I=102 +KEY=50005B4C4B11BFB20BD40E38A37BC51746E217EA5EEF8EFA +IV=2CD84FB5B587BE8B04638A9EDBA17AE2 +PT=1296DC2C1741EB2A177A51F9DAEE53EE +CT=8C2A5A31951FB2D9E8D35CD3C007B8B3 + +I=103 +KEY=E1E88DDBA5D849DF87FE5409366477CEAE314B399EE83649 +IV=8C2A5A31951FB2D9E8D35CD3C007B8B3 +PT=57C5E1A070E3C2AEB1E8D697EEC9F66D +CT=AA9E935BA264C9FD0C07072AF8499CD7 + +I=104 +KEY=D465F0FB195068CF2D60C7529400BE33A2364C1366A1AA9E +IV=AA9E935BA264C9FD0C07072AF8499CD7 +PT=77D0522670E00BD7358D7D20BC882110 +CT=A22DF6CE12C75FB99F5159A1E3E4249F + +I=105 +KEY=4DEB1B5E6398E4AD8F4D319C86C7E18A3D6715B285458E01 +IV=A22DF6CE12C75FB99F5159A1E3E4249F +PT=D6F96D22896A2574998EEBA57AC88C62 +CT=B356102A9158C569469E61093146B9F0 + +I=106 +KEY=D73E5CA946860BDD3C1B21B6179F24E37BF974BBB40337F1 +IV=B356102A9158C569469E61093146B9F0 +PT=2E72F61FC21F57A09AD547F7251EEF70 +CT=AB2BABFB88D3C3ACE4CBA81E0E250AD3 + +I=107 +KEY=6B592CE635873DE197308A4D9F4CE74F9F32DCA5BA263D22 +IV=AB2BABFB88D3C3ACE4CBA81E0E250AD3 +PT=39B02C01155705C9BC67704F7301363C +CT=8A4AC90E9095479F3C02DE7B08C01F1C + +I=108 +KEY=1026EE98CAC684081D7A43430FD9A0D0A33002DEB2E6223E +IV=8A4AC90E9095479F3C02DE7B08C01F1C +PT=14F49DBECEE88DBB7B7FC27EFF41B9E9 +CT=62E4E3C43938D014D90C4A1D8CD09639 + +I=109 +KEY=20972278E7C0FFC17F9EA08736E170C47A3C48C33E36B407 +IV=62E4E3C43938D014D90C4A1D8CD09639 +PT=56EFB0EA336A674930B1CCE02D067BC9 +CT=5E8EB865BFC1999D57A67280E37CA129 + +I=110 +KEY=2BEE1A1965A7F17C211018E28920E9592D9A3A43DD4A152E +IV=5E8EB865BFC1999D57A67280E37CA129 +PT=9CF6F073F2F0C7CB0B79386182670EBD +CT=D3B98A4562FAB47ED3D09C55E75EE51B + +I=111 +KEY=EB85E491647FD6ACF2A992A7EBDA5D27FE4AA6163A14F035 +IV=D3B98A4562FAB47ED3D09C55E75EE51B +PT=61964EF472752F21C06BFE8801D827D0 +CT=CF3D65AEEDD747416AF436A3B909828F + +I=112 +KEY=E94E6286941EC36D3D94F709060D1A6694BE90B5831D72BA +IV=CF3D65AEEDD747416AF436A3B909828F +PT=6C0B536EA1099A4202CB8617F06115C1 +CT=5DB0625B34C01C47490B5200E8A205FC + +I=113 +KEY=F5D756E568CA6BA06024955232CD0621DDB5C2B56BBF7746 +IV=5DB0625B34C01C47490B5200E8A205FC +PT=08D5CD9945D190AB1C993463FCD4A8CD +CT=771B5C66F79E262FAAC6F92F128669CB + +I=114 +KEY=462C74E6E222DE77173FC934C553200E77733B9A79391E8D +IV=771B5C66F79E262FAAC6F92F128669CB +PT=5628EC55D7AB7634B3FB22038AE8B5D7 +CT=31C436E7CA7343A93AA0B74A38CCDAC0 + +I=115 +KEY=5062F2489F4C68FE26FBFFD30F2063A74DD38CD041F5C44D +IV=31C436E7CA7343A93AA0B74A38CCDAC0 +PT=F279C45DBD75C458164E86AE7D6EB689 +CT=845320B41FD6F1D4DBB36D19D8A4A268 + +I=116 +KEY=5A27EC509FED17B6A2A8DF6710F692739660E1C999516625 +IV=845320B41FD6F1D4DBB36D19D8A4A268 +PT=7C0CB5E4FFE703260A451E1800A17F48 +CT=D8F9FB52BE1B342D6FBBB8A7FCDEFD89 + +I=117 +KEY=E925EC8E99BF11E97A512435AEEDA65EF9DB596E658F9BAC +IV=D8F9FB52BE1B342D6FBBB8A7FCDEFD89 +PT=187F3648643AF8E6B30200DE0652065F +CT=240647A32D765031C79D8893CC19EBA9 + +I=118 +KEY=5574034BCE64FADD5E576396839BF66F3E46D1FDA9967005 +IV=240647A32D765031C79D8893CC19EBA9 +PT=AF808097E0C68C8FBC51EFC557DBEB34 +CT=2A3805A7D773F9C00635779752C9CCE7 + +I=119 +KEY=D842A9983BBDAA5E746F663154E80FAF3873A66AFB5FBCE2 +IV=2A3805A7D773F9C00635779752C9CCE7 +PT=D44486CCC61C68588D36AAD3F5D95083 +CT=2219F0C7A805BEC4A4931F84CBFFC598 + +I=120 +KEY=CD622302BD70E2CD567696F6FCEDB16B9CE0B9EE30A0797A +IV=2219F0C7A805BEC4A4931F84CBFFC598 +PT=67DA1BC4F2BC2F3315208A9A86CD4893 +CT=8B1F4353CF6969888BBD6654AB65C2A8 + +I=121 +KEY=80A1D0CA7667F291DD69D5A53384D8E3175DDFBA9BC5BBD2 +IV=8B1F4353CF6969888BBD6654AB65C2A8 +PT=D114FDA8E61BEAC44DC3F3C8CB17105C +CT=B6F0C0F016A1FA033C37D1128D9B2EF3 + +I=122 +KEY=2C9B755C3B8B44416B991555252522E02B6A0EA8165E9521 +IV=B6F0C0F016A1FA033C37D1128D9B2EF3 +PT=738DBCE3EE7E70EAAC3AA5964DECB6D0 +CT=14FB0A67CB0729CA25152581D8C3FEEF + +I=123 +KEY=5D05BDFBF482E4D37F621F32EE220B2A0E7F2B29CE9D6BCE +IV=14FB0A67CB0729CA25152581D8C3FEEF +PT=D3186497981F294B719EC8A7CF09A092 +CT=14C988C52C7ED50EBD10219F1F58C213 + +I=124 +KEY=9E044D195FA8557C6BAB97F7C25CDE24B36F0AB6D1C5A9DD +IV=14C988C52C7ED50EBD10219F1F58C213 +PT=C062585284FDE540C301F0E2AB2AB1AF +CT=1FE7E153E69F95F102624ACEB9067FA1 + +I=125 +KEY=2B116B6F1FD581C6744C76A424C34BD5B10D407868C3D67C +IV=1FE7E153E69F95F102624ACEB9067FA1 +PT=F18294D40CAA674DB5152676407DD4BA +CT=AB43B2C61C9F23B96EFE293C6730A98F + +I=126 +KEY=EAF1AFBDD2CEDB9ADF0FC462385C686CDFF369440FF37FF3 +IV=AB43B2C61C9F23B96EFE293C6730A98F +PT=7D465730C5422413C1E0C4D2CD1B5A5C +CT=B1413F447CA81C678287EE2366544547 + +I=127 +KEY=4FA6C7DA7A84D4CB6E4EFB2644F4740B5D74876769A73AB4 +IV=B1413F447CA81C678287EE2366544547 +PT=C7BFA1BFA26828F7A5576867A84A0F51 +CT=7AE90F988557F3A41BBDB4B69C5FF56A + +I=128 +KEY=C9B0E3C7CEF4003014A7F4BEC1A387AF46C933D1F5F8CFDE +IV=7AE90F988557F3A41BBDB4B69C5FF56A +PT=5173C32806105AD18616241DB470D4FB +CT=F2EF675645D284F042FAEBE87AE3ECAE + +I=129 +KEY=DB855274F6CC030BE64893E88471035F0433D8398F1B2370 +IV=F2EF675645D284F042FAEBE87AE3ECAE +PT=6DF6B7F917B2F8431235B1B33838033B +CT=30D4F068BC2FDEC79CF81A4FA641A495 + +I=130 +KEY=F37DBF11472A4F87D69C6380385EDD9898CBC276295A87E5 +IV=30D4F068BC2FDEC79CF81A4FA641A495 +PT=F4C98D268B7D175728F8ED65B1E64C8C +CT=0CEB234560B935E5B08C7EA2AA4A962D + +I=131 +KEY=1A2F5A0827B2F861DA7740C558E7E87D2847BCD4831011C8 +IV=0CEB234560B935E5B08C7EA2AA4A962D +PT=9873E312B815DC81E952E5196098B7E6 +CT=7BED84EFC02836F6D165AD27DEEF2B21 + +I=132 +KEY=9C815F2A4EC42D02A19AC42A98CFDE8BF92211F35DFF3AE9 +IV=7BED84EFC02836F6D165AD27DEEF2B21 +PT=D8765DE55131DC4186AE05226976D563 +CT=C36FEDCB97DA734243A20C49D5942DD1 + +I=133 +KEY=9A12CC40F3C185AA62F529E10F15ADC9BA801DBA886B1738 +IV=C36FEDCB97DA734243A20C49D5942DD1 +PT=18B252CEB124BD110693936ABD05A8A8 +CT=94C9A6BDB97522FACEE2E869C3C48FB0 + +I=134 +KEY=F08C23DDC110ED40F63C8F5CB6608F337462F5D34BAF9888 +IV=94C9A6BDB97522FACEE2E869C3C48FB0 +PT=154FF810E3F0CE586A9EEF9D32D168EA +CT=AFC8D15F80F19F942FCA22DA0DF79937 + +I=135 +KEY=B1224FF7293C5DC559F45E03369110A75BA8D709465801BF +IV=AFC8D15F80F19F942FCA22DA0DF79937 +PT=259A6B069CA3273C41AE6C2AE82CB085 +CT=5AADC1716B2ED4FC7CA9825A32EA2FB1 + +I=136 +KEY=D29A829813CC5B4103599F725DBFC45B2701555374B22E0E +IV=5AADC1716B2ED4FC7CA9825A32EA2FB1 +PT=CB78C574D9B1B9EF63B8CD6F3AF00684 +CT=EACB8D3001640F340DFB459CD8D162BD + +I=137 +KEY=1049116DD39F7B30E99212425CDBCB6F2AFA10CFAC634CB3 +IV=EACB8D3001640F340DFB459CD8D162BD +PT=DF461D135DE19FA2C2D393F5C0532071 +CT=9115EB33739C04AAE22765621A8852C5 + +I=138 +KEY=A129CBBF89658D977887F9712F47CFC5C8DD75ADB6EB1E76 +IV=9115EB33739C04AAE22765621A8852C5 +PT=E32AF908A190B95FB160DAD25AFAF6A7 +CT=B171D8AC24C6873B54F42D5DAC51ED34 + +I=139 +KEY=EE7226D88DFA48DFC9F621DD0B8148FE9C2958F01ABAF342 +IV=B171D8AC24C6873B54F42D5DAC51ED34 +PT=0A669BB00E2123B54F5BED67049FC548 +CT=CFFC81B70593A36D022248D1CBE7FC58 + +I=140 +KEY=C907918503B2C1C0060AA06A0E12EB939E0B1021D15D0F1A +IV=CFFC81B70593A36D022248D1CBE7FC58 +PT=E9B1E6FA006D4CEE2775B75D8E48891F +CT=0B3B02FC8A8D677B8077D7FDF9EB0396 + +I=141 +KEY=E468A0560DB602C10D31A296849F8CE81E7CC7DC28B60C8C +IV=0B3B02FC8A8D677B8077D7FDF9EB0396 +PT=AA3626C69662AE442D6F31D30E04C301 +CT=2C78C31D4B2EBAEF54CB6D04C4375196 + +I=142 +KEY=EB8BCD80D3E35CCB2149618BCFB136074AB7AAD8EC815D1A +IV=2C78C31D4B2EBAEF54CB6D04C4375196 +PT=5017BD9EB52514180FE36DD6DE555E0A +CT=67D2DD54A0881186DFA6A608C036CE61 + +I=143 +KEY=7065D92686BA37E9469BBCDF6F39278195110CD02CB7937B +IV=67D2DD54A0881186DFA6A608C036CE61 +PT=6CBC1C2DAA3A7F7B9BEE14A655596B22 +CT=62163C88A40E7CFF7522A3DC32F30BCF + +I=144 +KEY=E0B4AE9D6C9A5A92248D8057CB375B7EE033AF0C1E4498B4 +IV=62163C88A40E7CFF7522A3DC32F30BCF +PT=0F6C44EE5E2587A790D177BBEA206D7B +CT=B84A631DE451F109C48785DE3D4099C2 + +I=145 +KEY=DDCDB4F73AA0C8789CC7E34A2F66AA7724B42AD223040176 +IV=B84A631DE451F109C48785DE3D4099C2 +PT=EE1EA5C5340C2F263D791A6A563A92EA +CT=D438E983DB81DA9341CE1AC45F4E7E52 + +I=146 +KEY=813604E941CBDF6448FF0AC9F4E770E4657A30167C4A7F24 +IV=D438E983DB81DA9341CE1AC45F4E7E52 +PT=08E1F94874432DBD5CFBB01E7B6B171C +CT=0E1C069CB75D4EDF4243D1E6D7175425 + +I=147 +KEY=D64EB9DE5A3B546B46E30C5543BA3E3B2739E1F0AB5D2B01 +IV=0E1C069CB75D4EDF4243D1E6D7175425 +PT=CFCDC1C0EFE678FB5778BD371BF08B0F +CT=CBC0ED542E26A1943926EF7897A79E97 + +I=148 +KEY=D1659785D1D551948D23E1016D9C9FAF1E1F0E883CFAB596 +IV=CBC0ED542E26A1943926EF7897A79E97 +PT=1FEA178A348CAE8B072B2E5B8BEE05FF +CT=C743A7B60EB7C24867DA82AFF15ED18A + +I=149 +KEY=05786C3E1FBE51864A6046B7632B5DE779C58C27CDA4641C +IV=C743A7B60EB7C24867DA82AFF15ED18A +PT=3A4EF6696CD26875D41DFBBBCE6B0012 +CT=EA23014227CF7B563AEFF86DB947FAC4 + +I=150 +KEY=CE1E5D5BF32BF0CAA04347F544E426B1432A744A74E39ED8 +IV=EA23014227CF7B563AEFF86DB947FAC4 +PT=DFDF9B4032986E90CB663165EC95A14C +CT=EAF762B60A106C03B76742E69CEE385A + +I=151 +KEY=F8EAC01B3F7E925A4AB425434EF44AB2F44D36ACE80DA682 +IV=EAF762B60A106C03B76742E69CEE385A +PT=2BDC6EAB1D86311D36F49D40CC556290 +CT=E6CC0491C3509240ED848AE304CC3385 + +I=152 +KEY=BF5AE8B244244B4BAC7821D28DA4D8F219C9BC4FECC19507 +IV=E6CC0491C3509240ED848AE304CC3385 +PT=81D4E28E02717AB347B028A97B5AD911 +CT=11EE9D22AC798AB5FEF6C6188845F425 + +I=153 +KEY=5C6538235111334FBD96BCF021DD5247E73F7A5764846122 +IV=11EE9D22AC798AB5FEF6C6188845F425 +PT=DDE402413BB09DFBE33FD09115357804 +CT=3F054911089500FD2CD0645DBFE2A8D3 + +I=154 +KEY=FAC914FA6B6CA1AB8293F5E1294852BACBEF1E0ADB66C9F1 +IV=3F054911089500FD2CD0645DBFE2A8D3 +PT=345343E023AC39FFA6AC2CD93A7D92E4 +CT=7538E78DE8FC09D203010C61422E6B5A + +I=155 +KEY=1E62F54271EA4374F7AB126CC1B45B68C8EE126B9948A2AB +IV=7538E78DE8FC09D203010C61422E6B5A +PT=0EC4357C476EB76AE4ABE1B81A86E2DF +CT=3A4D0093A2B7FF807BAA6A815538507E + +I=156 +KEY=5AD3B884BE5653BBCDE612FF6303A4E8B34478EACC70F2D5 +IV=3A4D0093A2B7FF807BAA6A815538507E +PT=F59FD86893B7DF7244B14DC6CFBC10CF +CT=2C2FD7DF94FDDC2CA1C05EF5878583FF + +I=157 +KEY=B9039E1678902ECCE1C9C520F7FE78C41284261F4BF5712A +IV=2C2FD7DF94FDDC2CA1C05EF5878583FF +PT=4600E6CCD65B575AE3D02692C6C67D77 +CT=59C9FA2E4A2227C3E5B831899A3CCBFD + +I=158 +KEY=394A8245256D72B8B8003F0EBDDC5F07F73C1796D1C9BAD7 +IV=59C9FA2E4A2227C3E5B831899A3CCBFD +PT=3030D8E24F7BEA0580491C535DFD5C74 +CT=DEAFC4A07A3FB5D5AA09FF6A2515AB4A + +I=159 +KEY=2496931DFCFF2E7166AFFBAEC7E3EAD25D35E8FCF4DC119D +IV=DEAFC4A07A3FB5D5AA09FF6A2515AB4A +PT=63CD1CC241B267791DDC1158D9925CC9 +CT=B1B0AED275FCE241B5726E943B37C130 + +I=160 +KEY=53CBA419E5CED1C8D71F557CB21F0893E8478668CFEBD0AD +IV=B1B0AED275FCE241B5726E943B37C130 +PT=85F4E06A05C8704A775D37041931FFB9 +CT=B0DFD3EF3AF538791E69AF59CAA7B8CC + +I=161 +KEY=DFB0E5440EB582F667C0869388EA30EAF62E2931054C6861 +IV=B0DFD3EF3AF538791E69AF59CAA7B8CC +PT=B7BDA6C504797C8B8C7B415DEB7B533E +CT=220F810B0D5A9ED8794932D0BF6150D6 + +I=162 +KEY=B26A70894070BC9B45CF079885B0AE328F671BE1BA2D38B7 +IV=220F810B0D5A9ED8794932D0BF6150D6 +PT=0113567BFAC19EB86DDA95CD4EC53E6D +CT=56C77682CA1A041B312061F3FB9A1A59 + +I=163 +KEY=36EDA74B7133D5871308711A4FAAAA29BE477A1241B722EE +IV=56C77682CA1A041B312061F3FB9A1A59 +PT=4D39AD87258968FA8487D7C23143691C +CT=4F18208E63B2D84CC7A0707617DD7B63 + +I=164 +KEY=F7589312CE997AFE5C1051942C18726579E70A64566A598D +IV=4F18208E63B2D84CC7A0707617DD7B63 +PT=1B82F5C849E0F965C1B53459BFAAAF79 +CT=85CE0310DEFB36474B38C4347D7EEE8B + +I=165 +KEY=F770FC7B1E183E31D9DE5284F2E3442232DFCE502B14B706 +IV=85CE0310DEFB36474B38C4347D7EEE8B +PT=7B56EBC47E780FB000286F69D08144CF +CT=CB5AE674DB1426618F577BBD63309EA4 + +I=166 +KEY=79AD3040CCC9FD521284B4F029F76243BD88B5ED482429A2 +IV=CB5AE674DB1426618F577BBD63309EA4 +PT=47A5B213BC3DF61B8EDDCC3BD2D1C363 +CT=1E26AB2D8B156913995FCAC1ABD99D68 + +I=167 +KEY=10BB9597F823B61F0CA21FDDA2E20B5024D77F2CE3FDB4CA +IV=1E26AB2D8B156913995FCAC1ABD99D68 +PT=D31FC11C9FD6E7F86916A5D734EA4B4D +CT=84E0E24F155E5EFCA9AE9C5F2F26BD25 + +I=168 +KEY=E1264A2AD33800FF8842FD92B7BC55AC8D79E373CCDB09EF +IV=84E0E24F155E5EFCA9AE9C5F2F26BD25 +PT=F77FE11AE4BEB403F19DDFBD2B1BB6E0 +CT=B41973B0D807A43A822EB57555B818D4 + +I=169 +KEY=A19ABDD25ED272693C5B8E226FBBF1960F5756069963113B +IV=B41973B0D807A43A822EB57555B818D4 +PT=FECAAA8EA9C1883640BCF7F88DEA7296 +CT=949634E68FB9086AE623EAF5E867D4A5 + +I=170 +KEY=DD904ECCC94F64D0A8CDBAC4E002F9FCE974BCF37104C59E +IV=949634E68FB9086AE623EAF5E867D4A5 +PT=E8A413C2ADB97D387C0AF31E979D16B9 +CT=96BE2B618F8A961E5DC892F429A8B6FC + +I=171 +KEY=1B83C20396D7D0D33E7391A56F886FE2B4BC2E0758AC7362 +IV=96BE2B618F8A961E5DC892F429A8B6FC +PT=1408434BF0C3432BC6138CCF5F98B403 +CT=C0A9596F56E48F459D2C405F47DCA44C + +I=172 +KEY=B04C71DBEA60DB15FEDAC8CA396CE0A729906E581F70D72E +IV=C0A9596F56E48F459D2C405F47DCA44C +PT=5E7F070C7EE8A852ABCFB3D87CB70BC6 +CT=A4739C93911C72C959E89544500843BD + +I=173 +KEY=9BFC8026BC1D965B5AA95459A870926E7078FB1C4F789493 +IV=A4739C93911C72C959E89544500843BD +PT=718C23D1F537A6E72BB0F1FD567D4D4E +CT=4D581200B1E446CC3AD306138BF2898B + +I=174 +KEY=FEA9DF8F4FECB3ED17F146591994D4A24AABFD0FC48A1D18 +IV=4D581200B1E446CC3AD306138BF2898B +PT=E4DD231D871795E065555FA9F3F125B6 +CT=E53EFC19D8048073167B1473C5EBA6D9 + +I=175 +KEY=62DF036D6F96D937F2CFBA40C19054D15CD0E97C0161BBC1 +IV=E53EFC19D8048073167B1473C5EBA6D9 +PT=9AB809114F10C3FD9C76DCE2207A6ADA +CT=BDB0C3D9732DE5813C4C72CF01FF5194 + +I=176 +KEY=CFEF04F0343587004F7F7999B2BDB150609C9BB3009EEA55 +IV=BDB0C3D9732DE5813C4C72CF01FF5194 +PT=B4CFE094F8B4EEE5AD30079D5BA35E37 +CT=D00B5B980D8B10DF3D7D4C0BE5975C1C + +I=177 +KEY=CBF2C475C11FA6B89F742201BF36A18F5DE1D7B8E509B649 +IV=D00B5B980D8B10DF3D7D4C0BE5975C1C +PT=34B39728291953DC041DC085F52A21B8 +CT=ADF5CDFDCC23AD8AD111454B2DB69013 + +I=178 +KEY=C96820A08056F7C23281EFFC73150C058CF092F3C8BF265A +IV=ADF5CDFDCC23AD8AD111454B2DB69013 +PT=4C8152CCAA0A23AC029AE4D54149517A +CT=F070979F68BAEBBD6CE8CE8A549C0E12 + +I=179 +KEY=61A6BBDB58B4C9D4C2F178631BAFE7B8E0185C799C232848 +IV=F070979F68BAEBBD6CE8CE8A549C0E12 +PT=0B6AF20EF8550A1BA8CE9B7BD8E23E16 +CT=8A75D276384A4F468B459466A304D418 + +I=180 +KEY=D3EC560DE8B1BBEE4884AA1523E5A8FE6B5DC81F3F27FC50 +IV=8A75D276384A4F468B459466A304D418 +PT=259A18BABFD09145B24AEDD6B005723A +CT=B7C04F66EB771CBD97F948098E23C655 + +I=181 +KEY=16FE806749FDDF8CFF44E573C892B443FCA48016B1043A05 +IV=B7C04F66EB771CBD97F948098E23C655 +PT=E00B5E4B3D9E64D0C512D66AA14C6462 +CT=29FB08289BD19BCC0FEB0F433D5CACEE + +I=182 +KEY=9CC345922C8912D5D6BFED5B53432F8FF34F8F558C5896EB +IV=29FB08289BD19BCC0FEB0F433D5CACEE +PT=07BAA266554EAE0C8A3DC5F56574CD59 +CT=495C245E2F3CC52499B9C1AD7C4484BA + +I=183 +KEY=7DDDCF7DE759FDEC9FE3C9057C7FEAAB6AF64EF8F01C1251 +IV=495C245E2F3CC52499B9C1AD7C4484BA +PT=2E5360D5563EB7D4E11E8AEFCBD0EF39 +CT=68267051421D3AFA19A2E43D501B940B + +I=184 +KEY=4BA2EAD4106DD4B7F7C5B9543E62D0517354AAC5A007865A +IV=68267051421D3AFA19A2E43D501B940B +PT=050EBC6942F92D95367F25A9F734295B +CT=1781558A2A8B7C29AC82D6610B67E3CF + +I=185 +KEY=CFCCD4ECD20E051CE044ECDE14E9AC78DFD67CA4AB606595 +IV=1781558A2A8B7C29AC82D6610B67E3CF +PT=1AC90B21EB197E26846E3E38C263D1AB +CT=BF5FE87A2E882A64493850EC3A0E93A5 + +I=186 +KEY=C9EA5F992C77DD9C5F1B04A43A61861C96EE2C48916EF630 +IV=BF5FE87A2E882A64493850EC3A0E93A5 +PT=58F997704D085DC506268B75FE79D880 +CT=8F43A961964E3452094E8E71295177CD + +I=187 +KEY=1136648F9E0A53C3D058ADC5AC2FB24E9FA0A239B83F81FD +IV=8F43A961964E3452094E8E71295177CD +PT=086041AB29E423EFD8DC3B16B27D8E5F +CT=BF69230BAB6200B7828DC04A13B88E83 + +I=188 +KEY=47040E2D6DFBE3006F318ECE074DB2F91D2D6273AB870F7E +IV=BF69230BAB6200B7828DC04A13B88E83 +PT=57865A8650D3202056326AA2F3F1B0C3 +CT=A012FAEE65E2C4F0AC22CB63AB75E35D + +I=189 +KEY=868F8310E79C0473CF23742062AF7609B10FA91000F2EC23 +IV=A012FAEE65E2C4F0AC22CB63AB75E35D +PT=F3ABB47DAE94B82EC18B8D3D8A67E773 +CT=F35BBD3C516F86384DA3BB6B5CCC8B37 + +I=190 +KEY=5C71ADCE480714DA3C78C91C33C0F031FCAC127B5C3E6714 +IV=F35BBD3C516F86384DA3BB6B5CCC8B37 +PT=CDB3E57FA6DDFF9FDAFE2EDEAF9B10A9 +CT=627A15E65B37C2B9575E8A781271AE64 + +I=191 +KEY=B603092BC5FD004F5E02DCFA68F73288ABF298034E4FC970 +IV=627A15E65B37C2B9575E8A781271AE64 +PT=7E04F9A0F723DF00EA72A4E58DFA1495 +CT=15427D27E783A5476345C83F3E8A3319 + +I=192 +KEY=4DB5A9F825C5E8C24B40A1DD8F7497CFC8B7503C70C5FA69 +IV=15427D27E783A5476345C83F3E8A3319 +PT=842B94BE25E8747BFBB6A0D3E038E88D +CT=35812AFD1A90B0B7D52B45EAD9CAF083 + +I=193 +KEY=D4F2CCC0734F9ACD7EC18B2095E427781D9C15D6A90F0AEA +IV=35812AFD1A90B0B7D52B45EAD9CAF083 +PT=3FAB7D4C741B8CD499476538568A720F +CT=C1A59CD3D9E6650F0D16947D26BFC20D + +I=194 +KEY=CB28A8313E133469BF6417F34C024277108A81AB8FB0C8E7 +IV=C1A59CD3D9E6650F0D16947D26BFC20D +PT=37AC888DCE5CDFD31FDA64F14D5CAEA4 +CT=CB0313E9A046711866CA65702A45CDB6 + +I=195 +KEY=C5BFEB8246ABAF467467041AEC44336F7640E4DBA5F50551 +IV=CB0313E9A046711866CA65702A45CDB6 +PT=326C9E3EB49138ED0E9743B378B89B2F +CT=ACE8FC6C6ABBC8124FE35C7976585DF6 + +I=196 +KEY=110891F8FDF0F254D88FF87686FFFB7D39A3B8A2D3AD58A7 +IV=ACE8FC6C6ABBC8124FE35C7976585DF6 +PT=964239EB84C57F61D4B77A7ABB5B5D12 +CT=0762EF13B80A8B77D04AF797B67D5AA6 + +I=197 +KEY=EFF558976586AC91DFED17653EF5700AE9E94F3565D00201 +IV=0762EF13B80A8B77D04AF797B67D5AA6 +PT=5ECA17ADFE3C2C21FEFDC96F98765EC5 +CT=B60CC9CD9DE93E2A6FB0B59369B1628E + +I=198 +KEY=4494A36EABE3555E69E1DEA8A31C4E208659FAA60C61608F +IV=B60CC9CD9DE93E2A6FB0B59369B1628E +PT=7A659E803888296BAB61FBF9CE65F9CF +CT=73258A43C7DA66FFE4DC9384FC7A60C1 + +I=199 +KEY=1780249B48B8F7561AC454EB64C628DF62856922F01B004E +IV=73258A43C7DA66FFE4DC9384FC7A60C1 +PT=8D9C3DCF612320B4531487F5E35BA208 +CT=F0F5D51C06F2D900CC4BE8D3512CA4B6 + +I=200 +KEY=9FF03D1E23BD9959EA3181F76234F1DFAECE81F1A137A4F8 +IV=F0F5D51C06F2D900CC4BE8D3512CA4B6 +PT=F002AEC878B80A0B887019856B056E0F +CT=E1321C52A51D9345296A0EF2A9DC9CC5 + +I=201 +KEY=6042967162EDA50B0B039DA5C729629A87A48F0308EB383D +IV=E1321C52A51D9345296A0EF2A9DC9CC5 +PT=C5EA4A519D9BAF8FFFB2AB6F41503C52 +CT=ED79D8FC9C60B583E29D0A65A6A5F321 + +I=202 +KEY=250C416206B9D0A9E67A45595B49D71965398566AE4ECB1C +IV=ED79D8FC9C60B583E29D0A65A6A5F321 +PT=34D771B44B3943DE454ED713645475A2 +CT=7A08F9096109535C262407EB323EF7BC + +I=203 +KEY=6357BC1B7B12F1C09C72BC503A408445431D828D9C703CA0 +IV=7A08F9096109535C262407EB323EF7BC +PT=60A1EEAE2B16841A465BFD797DAB2169 +CT=24C7F1A39F8B2F03C256F5C59B69C31A + +I=204 +KEY=18BF29D147A9675BB8B54DF3A5CBAB46814B77480719FFBA +IV=24C7F1A39F8B2F03C256F5C59B69C31A +PT=BFD7B314F959298B7BE895CA3CBB969B +CT=7DDA5DF3CC7C69AA490FB597888396B2 + +I=205 +KEY=E8B13C48FBABCD19C56F100069B7C2ECC844C2DF8F9A6908 +IV=7DDA5DF3CC7C69AA490FB597888396B2 +PT=23F8A60BD2354901F00E1599BC02AA42 +CT=04CEB4BE252293A822C77B9C4C27822B + +I=206 +KEY=BF275C4D9FC54BC0C1A1A4BE4C955144EA83B943C3BDEB23 +IV=04CEB4BE252293A822C77B9C4C27822B +PT=2182C0577EAA3C2A57966005646E86D9 +CT=0F24034642E351984620BB2647F5D649 + +I=207 +KEY=40B459144A6415C2CE85A7F80E7600DCACA3026584483D6A +IV=0F24034642E351984620BB2647F5D649 +PT=F59318D1D3D9A9E0FF930559D5A15E02 +CT=DB98808C46668D79AB059C5554CEEB1A + +I=208 +KEY=D5A01AB42D709E6A151D277448108DA507A69E30D086D670 +IV=DB98808C46668D79AB059C5554CEEB1A +PT=49CF142E621D1A8D951443A067148BA8 +CT=15C32FE5E9BCA5F8D09EA2E4D145FE3D + +I=209 +KEY=8191AB3C11B4B72700DE0891A1AC285DD7383CD401C3284D +IV=15C32FE5E9BCA5F8D09EA2E4D145FE3D +PT=5C1E9B721987B8BF5431B1883CC4294D +CT=AA7CA217D0514CA4F20C50293121E8D8 + +I=210 +KEY=69D24875B8A5B5D1AAA2AA8671FD64F925346CFD30E2C095 +IV=AA7CA217D0514CA4F20C50293121E8D8 +PT=8239553D8FB88E17E843E349A91102F6 +CT=C4068B901CB07904F843BF6F3CDC4FF8 + +I=211 +KEY=12BAE3B5B2C03E746EA421166D4D1DFDDD77D3920C3E8F6D +IV=C4068B901CB07904F843BF6F3CDC4FF8 +PT=80D797C671D3BFF67B68ABC00A658BA5 +CT=9F835417C4D622DB52651897DC23E1C3 + +I=212 +KEY=1A0CFD7FA1284652F1277501A99B3F268F12CB05D01D6EAE +IV=9F835417C4D622DB52651897DC23E1C3 +PT=C36513D78FBBFDCC08B61ECA13E87826 +CT=0156C998E85BE92F0EF998442204EB19 + +I=213 +KEY=7829D1FE113103B0F071BC9941C0D60981EB5341F21985B7 +IV=0156C998E85BE92F0EF998442204EB19 +PT=000894F1AF39A67562252C81B01945E2 +CT=6A554057C0A3EB723B693258BC5E899D + +I=214 +KEY=D719D37FC9087D2F9A24FCCE81633D7BBA8261194E470C2A +IV=6A554057C0A3EB723B693258BC5E899D +PT=B92413276BF142D0AF300281D8397E9F +CT=395F80E405813D97576954A23C77C2CA + +I=215 +KEY=39E173517A321A5AA37B7C2A84E200ECEDEB35BB7230CEE0 +IV=395F80E405813D97576954A23C77C2CA +PT=AA95F2BD255DBE23EEF8A02EB33A6775 +CT=1B1BC5D3DABD536E91177EF1BF2B7E39 + +I=216 +KEY=EE1FB67D907C597BB860B9F95E5F53827CFC4B4ACD1BB0D9 +IV=1B1BC5D3DABD536E91177EF1BF2B7E39 +PT=985E81E0BF5FF6EFD7FEC52CEA4E4321 +CT=20F42326749CC7CCD54188DEA46F4EC1 + +I=217 +KEY=41D333EC5E537B8098949ADF2AC3944EA9BDC3946974FE18 +IV=20F42326749CC7CCD54188DEA46F4EC1 +PT=901FD7D22F220608AFCC8591CE2F22FB +CT=AFFC6F2668097B58A0CFF619A3FDD1CB + +I=218 +KEY=F6E392EF75572C6A3768F5F942CAEF160972358DCA892FD3 +IV=AFFC6F2668097B58A0CFF619A3FDD1CB +PT=45AEB51360C50AB1B730A1032B0457EA +CT=1B75CF440CE8521069599B7889F21C1D + +I=219 +KEY=47C82CF46472D3732C1D3ABD4E22BD06602BAEF5437B33CE +IV=1B75CF440CE8521069599B7889F21C1D +PT=7E931056CC33D22CB12BBE1B1125FF19 +CT=F6079ADBAA8D28F371F0156B170FB7BD + +I=220 +KEY=DDA62A9922B04902DA1AA066E4AF95F511DBBB9E54748473 +IV=F6079ADBAA8D28F371F0156B170FB7BD +PT=2BE3DA337C9187109A6E066D46C29A71 +CT=7D2FC16B26971DDC20C6F7510C47B352 + +I=221 +KEY=570C8CA5236A2E65A735610DC2388829311D4CCF58333721 +IV=7D2FC16B26971DDC20C6F7510C47B352 +PT=43596064590570F88AAAA63C01DA6767 +CT=5FBA845FB25FE6AE015E4E8A228ED645 + +I=222 +KEY=6CEA158ED663A4B7F88FE55270676E87304302457ABDE164 +IV=5FBA845FB25FE6AE015E4E8A228ED645 +PT=1E265F0AA9A20C603BE6992BF5098AD2 +CT=A729E250D736A43966DD0D9C461ECEC0 + +I=223 +KEY=AACCE3387C0DF35D5FA60702A751CABE569E0FD93CA32FA4 +IV=A729E250D736A43966DD0D9C461ECEC0 +PT=B08AAE113CCE6226C626F6B6AA6E57EA +CT=A8192E964A74A6ABDB463ECFA483A1E3 + +I=224 +KEY=207F19ABDA13F728F7BF2994ED256C158DD8311698208E47 +IV=A8192E964A74A6ABDB463ECFA483A1E3 +PT=858CF92E6B1793448AB3FA93A61E0475 +CT=060C7CCCD58E6348518161C7878AA71B + +I=225 +KEY=AB05AD81CF07091AF1B3555838AB0F5DDC5950D11FAA295C +IV=060C7CCCD58E6348518161C7878AA71B +PT=424D175035503C728B7AB42A1514FE32 +CT=8ECAA12830B0C5B4C6950E69AFD31B66 + +I=226 +KEY=3A8E1CC01464AF9B7F79F470081BCAE91ACC5EB8B079323A +IV=8ECAA12830B0C5B4C6950E69AFD31B66 +PT=6E5A94391F1FE5A9918BB141DB63A681 +CT=65C3A891192324A7FA3C882B2C09CB8D + +I=227 +KEY=8004AB13CF38B3ED1ABA5CE11138EE4EE0F0D6939C70F9B7 +IV=65C3A891192324A7FA3C882B2C09CB8D +PT=584E219335CA4642BA8AB7D3DB5C1C76 +CT=F29F8735A403414621F2100AF38A500C + +I=228 +KEY=D37BB962CFC53E77E825DBD4B53BAF08C102C6996FFAA9BB +IV=F29F8735A403414621F2100AF38A500C +PT=CCB996C23C627D4D537F127100FD8D9A +CT=9C6A7655E25E9231E46C0D3B57C7FCAB + +I=229 +KEY=C23B3C983C79179A744FAD8157653D39256ECBA2383D5510 +IV=9C6A7655E25E9231E46C0D3B57C7FCAB +PT=5D727E12D3932F56114085FAF3BC29ED +CT=6C5AA7364755AF599AB6F86EC8B24C52 + +I=230 +KEY=4462CD1DD817170C18150AB710309260BFD833CCF08F1942 +IV=6C5AA7364755AF599AB6F86EC8B24C52 +PT=D7A99C8F3BC37AD08659F185E46E0096 +CT=821D7EAC8FD041C0C8CF1011661FBB9E + +I=231 +KEY=1BA52BEF2B010D169A08741B9FE0D3A0771723DD9690A2DC +IV=821D7EAC8FD041C0C8CF1011661FBB9E +PT=704F3525510FCC745FC7E6F2F3161A1A +CT=44591D71D64FC38010E402874853E9BC + +I=232 +KEY=C6A6818229CC65E6DE51696A49AF102067F3215ADEC34B60 +IV=44591D71D64FC38010E402874853E9BC +PT=5D5769AE155C9F43DD03AA6D02CD68F0 +CT=E5647FF6C843543E484FC13B58A345B9 + +I=233 +KEY=41F27DD5905B299C3B35169C81EC441E2FBCE06186600ED9 +IV=E5647FF6C843543E484FC13B58A345B9 +PT=ADF29030DFDFCCEE8754FC57B9974C7A +CT=E6EA42E2F046D3ED75081A50770563D1 + +I=234 +KEY=3A8018855EDC80D2DDDF547E71AA97F35AB4FA31F1656D08 +IV=E6EA42E2F046D3ED75081A50770563D1 +PT=096F74717D5583477B726550CE87A94E +CT=D75682FE37396887659E87895F1C6441 + +I=235 +KEY=6C94C2634142DA310A89D6804693FF743F2A7DB8AE790949 +IV=D75682FE37396887659E87895F1C6441 +PT=F1B527DD4935FBDE5614DAE61F9E5AE3 +CT=15755CFE84E113AA751E4D5BB098ABC7 + +I=236 +KEY=4BA407D7C6426C641FFC8A7EC272ECDE4A3430E31EE1A28E +IV=15755CFE84E113AA751E4D5BB098ABC7 +PT=7C4433DCC314DBD72730C5B48700B655 +CT=B048F209CE1B1FAEC33392D2D8F326A1 + +I=237 +KEY=A56FD7BCEEA55474AFB478770C69F3708907A231C612842F +IV=B048F209CE1B1FAEC33392D2D8F326A1 +PT=D40C7CD8D80C8C6CEECBD06B28E73810 +CT=8E1F4830F94004C286C39D0EC014A963 + +I=238 +KEY=0730B7B664CFD1E321AB3047F529F7B20FC43F3F06062D4C +IV=8E1F4830F94004C286C39D0EC014A963 +PT=B16772FE8C8A573FA25F600A8A6A8597 +CT=3FB92771D2BE2D33C40AB0409998B229 + +I=239 +KEY=0A08E43B13C57EB41E1217362797DA81CBCE8F7F9F9E9F65 +IV=3FB92771D2BE2D33C40AB0409998B229 +PT=D4883476825EA2D30D38538D770AAF57 +CT=190106DE79836016C57A16BBBA6893D2 + +I=240 +KEY=195B7E1B67872B0D071311E85E14BA970EB499C425F60CB7 +IV=190106DE79836016C57A16BBBA6893D2 +PT=3B8F4F140FDFFB6B13539A20744255B9 +CT=C06398537B4F534203D57184543E6516 + +I=241 +KEY=BE0C4A8A9B581D16C77089BB255BE9D50D61E84071C869A1 +IV=C06398537B4F534203D57184543E6516 +PT=E50D127AE258061DA7573491FCDF361B +CT=FF615CCC9F2D3DBB3074C835ECE4224E + +I=242 +KEY=662A224DAB1233C83811D577BA76D46E3D1520759D2C4BEF +IV=FF615CCC9F2D3DBB3074C835ECE4224E +PT=347C976D20470968D82668C7304A2EDE +CT=B5FB1BCCBC838B87FDB10FEFE6CDC45B + +I=243 +KEY=F4F3B47D9CC8BA798DEACEBB06F55FE9C0A42F9A7BE18FB4 +IV=B5FB1BCCBC838B87FDB10FEFE6CDC45B +PT=BC276D1002C5DD8292D9963037DA89B1 +CT=151F88A44A76568FAC756011B827778D + +I=244 +KEY=7EA3C03193B737DE98F5461F4C8309666CD14F8BC3C6F839 +IV=151F88A44A76568FAC756011B827778D +PT=BCD9054596EE644E8A50744C0F7F8DA7 +CT=C1B0B6FDD717881442496794A2C890F2 + +I=245 +KEY=C4D94D5C4169EE4B5945F0E29B9481722E98281F610E68CB +IV=C1B0B6FDD717881442496794A2C890F2 +PT=3D7F68D3014F3BEDBA7A8D6DD2DED995 +CT=181100A04881DCF9813E4A22C6C1BB3B + +I=246 +KEY=A9A9483D9FC46DD34154F042D3155D8BAFA6623DA7CFD3F0 +IV=181100A04881DCF9813E4A22C6C1BB3B +PT=0FE2E2A97DFFB4966D700561DEAD8398 +CT=AA4BEC4007C38C7B86B6F9EED33E5EB1 + +I=247 +KEY=5F08A3C09F4AE90BEB1F1C02D4D6D1F029109BD374F18D41 +IV=AA4BEC4007C38C7B86B6F9EED33E5EB1 +PT=C2392264CE43C57AF6A1EBFD008E84D8 +CT=A0756CCDA72462CD89DF9990C0FE6676 + +I=248 +KEY=6A1A4F2D25DFC9F94B6A70CF73F2B33DA0CF0243B40FEB37 +IV=A0756CCDA72462CD89DF9990C0FE6676 +PT=A6650A3432CCA74A3512ECEDBA9520F2 +CT=F5044AECC6F35C99FCDBA26DD15E1474 + +I=249 +KEY=B475174A46D0CDC2BE6E3A23B501EFA45C14A02E6551FF43 +IV=F5044AECC6F35C99FCDBA26DD15E1474 +PT=07967DE17DEB720CDE6F5867630F043B +CT=60645B559E7321D7FA8A3F925CFC0FA4 + +I=250 +KEY=8DBB9D8A4A2E7E61DE0A61762B72CE73A69E9FBC39ADF0E7 +IV=60645B559E7321D7FA8A3F925CFC0FA4 +PT=D8D3FD2077545DD039CE8AC00CFEB3A3 +CT=C4C6FD53A2572D643AA631FB85B84D0B + +I=251 +KEY=97D34E4B3B9E081A1ACC9C258925E3179C38AE47BC15BDEC +IV=C4C6FD53A2572D643AA631FB85B84D0B +PT=F31D8F3C8AC67E081A68D3C171B0767B +CT=E1A0E460E2D1483FE954F26F45CCE7A0 + +I=252 +KEY=5372C72A4ABF72D9FB6C78456BF4AB28756C5C28F9D95A4C +IV=E1A0E460E2D1483FE954F26F45CCE7A0 +PT=422C5429CE7BD811C4A1896171217AC3 +CT=2695923CFB2141F05A0F144FF021BD36 + +I=253 +KEY=A8CA6DB8A8758322DDF9EA7990D5EAD82F63486709F8E77A +IV=2695923CFB2141F05A0F144FF021BD36 +PT=780771C65FCB907BFBB8AA92E2CAF1FB +CT=A9820B527F71E95CC1F53033149FB26F + +I=254 +KEY=62ABF1F4178F3C73747BE12BEFA40384EE9678541D675515 +IV=A9820B527F71E95CC1F53033149FB26F +PT=CCC14BD8DF1CA8A4CA619C4CBFFABF51 +CT=2BAD4E8CD7D6420D36DC2F8E77DCA072 + +I=255 +KEY=C79B767D31D9F0FC5FD6AFA738724189D84A57DA6ABBF567 +IV=2BAD4E8CD7D6420D36DC2F8E77DCA072 +PT=1EFF63C71B10DCC7A53087892656CC8F +CT=C21303AAB04E2CAF1893396DD405B265 + +I=256 +KEY=1F3C7FF71340DEEC9DC5AC0D883C6D26C0D96EB7BEBE4702 +IV=C21303AAB04E2CAF1893396DD405B265 +PT=209270B7768E5553D8A7098A22992E10 +CT=B220025B5307C9D5D1EEB4B427E7263F + +I=257 +KEY=867CB381E6D532B32FE5AE56DB3BA4F31137DA039959613D +IV=B220025B5307C9D5D1EEB4B427E7263F +PT=8546A6C9B4CEF0229940CC76F595EC5F +CT=B925C660EBE409050DA369E58C601F4D + +I=258 +KEY=33B33F93622E509296C0683630DFADF61C94B3E615397E70 +IV=B925C660EBE409050DA369E58C601F4D +PT=1F4930242C2951C4B5CF8C1284FB6221 +CT=67DA7B4BEAB2152D21C54F389F9282D4 + +I=259 +KEY=E8EC3394AF44DD34F11A137DDA6DB8DB3D51FCDE8AABFCA4 +IV=67DA7B4BEAB2152D21C54F389F9282D4 +PT=41611AE93BE61306DB5F0C07CD6A8DA6 +CT=4C116D3ED0B021129CCD1764D132A72D + +I=260 +KEY=92F61F4CB5794268BD0B7E430ADD99C9A19CEBBA5B995B89 +IV=4C116D3ED0B021129CCD1764D132A72D +PT=E7B1E63FBD5B4CA77A1A2CD81A3D9F5C +CT=FE1C3096C14AF2A4DC840207BFFFC0AF + +I=261 +KEY=08DC826B4DDBAC4D43174ED5CB976B6D7D18E9BDE4669B26 +IV=FE1C3096C14AF2A4DC840207BFFFC0AF +PT=9A0D034B1931FD599A2A9D27F8A2EE25 +CT=ED500812A10CC6C4EED0836871F85AA9 + +I=262 +KEY=486EBC43A876FF2AAE4746C76A9BADA993C86AD5959EC18F +IV=ED500812A10CC6C4EED0836871F85AA9 +PT=8237641B58069AFD40B23E28E5AD5367 +CT=0AD90C1C13E7C1318057A417C0B9B97C + +I=263 +KEY=F340D2CAC4645595A49E4ADB797C6C98139FCEC2552778F3 +IV=0AD90C1C13E7C1318057A417C0B9B97C +PT=905119E1F11E4B04BB2E6E896C12AABF +CT=B260FFA5806A4A6D8845FA6146A565ED + +I=264 +KEY=DF326741BD1EE2FF16FEB57EF91626F59BDA34A313821D1E +IV=B260FFA5806A4A6D8845FA6146A565ED +PT=4F639233904531162C72B58B797AB76A +CT=2D27A1A3968E30EBCA463C8709D0FD83 + +I=265 +KEY=D4C684692E05983C3BD914DD6F98161E519C08241A52E09D +IV=2D27A1A3968E30EBCA463C8709D0FD83 +PT=428B700FB3CD18790BF4E328931B7AC3 +CT=D350CCF3B440006C9F18E99DD5B69920 + +I=266 +KEY=9DD5275FFDCD5D2DE889D82EDBD81672CE84E1B9CFE479BD +IV=D350CCF3B440006C9F18E99DD5B69920 +PT=97F4A6256A9E22FB4913A336D3C8C511 +CT=F5A0571EB7E4719B862EBC47141EA319 + +I=267 +KEY=0A3B329A4973D7A21D298F306C3C67E948AA5DFEDBFADAA4 +IV=F5A0571EB7E4719B862EBC47141EA319 +PT=E355F7EBA4DAC16B97EE15C5B4BE8A8F +CT=4F18730073D3E78CAD356441F1317B2D + +I=268 +KEY=3BB3A19EF4EB8A755231FC301FEF8065E59F39BF2ACBA189 +IV=4F18730073D3E78CAD356441F1317B2D +PT=A20B3B6C41E88E9D31889304BD985DD7 +CT=AEAECB17B9009AAF1E4E9CC02653194B + +I=269 +KEY=4B9DDD2F821CE4D1FC9F3727A6EF1ACAFBD1A57F0C98B8C2 +IV=AEAECB17B9009AAF1E4E9CC02653194B +PT=5D2E4A96F9BB4AD4702E7CB176F76EA4 +CT=26851709960A42D5711EBDC7D40535FC + +I=270 +KEY=D7273499C5BA2842DA1A202E30E5581F8ACF18B8D89D8D3E +IV=26851709960A42D5711EBDC7D40535FC +PT=202534EA0A1952A19CBAE9B647A6CC93 +CT=FF8BFFB98EDA7E54664AE879551B5497 + +I=271 +KEY=7870FF6B66070AB02591DF97BE3F264BEC85F0C18D86D9A9 +IV=FF8BFFB98EDA7E54664AE879551B5497 +PT=365CFE282B9508CFAF57CBF2A3BD22F2 +CT=D0809C84A97221E6F8DCB483B38EC7E1 + +I=272 +KEY=F4E6DFDF4A081200F5114313174D07AD145944423E081E48 +IV=D0809C84A97221E6F8DCB483B38EC7E1 +PT=915323F59134AB838C9620B42C0F18B0 +CT=DC8A24B8DECF81E0412DBF10127119EC + +I=273 +KEY=336A7C81A4BE3FE9299B67ABC982864D5574FB522C7907A4 +IV=DC8A24B8DECF81E0412DBF10127119EC +PT=0FC4387E49F666B8C78CA35EEEB62DE9 +CT=84E370DF6CA478BA85FC0874393CE442 + +I=274 +KEY=F8ADC39E17CDDEB0AD781774A526FEF7D088F3261545E3E6 +IV=84E370DF6CA478BA85FC0874393CE442 +PT=34BFEFD3E43D8EE0CBC7BF1FB373E159 +CT=2C109A8363D1D0FB69CA77ABFA922F05 + +I=275 +KEY=2B26D271208BD64F81688DF7C6F72E0CB942848DEFD7CCE3 +IV=2C109A8363D1D0FB69CA77ABFA922F05 +PT=D28D86D5199E7E30D38B11EF374608FF +CT=F1749EFE66D339BC99AE4D9F63C90490 + +I=276 +KEY=ACB8D3E6F5A45F0C701C1309A02417B020ECC9128C1EC873 +IV=F1749EFE66D339BC99AE4D9F63C90490 +PT=2ADAFA1911C5E9BD879E0197D52F8943 +CT=3B2A7C4278E1F071BFA29A6B0BFF4A15 + +I=277 +KEY=CCEE75264DD770C44B366F4BD8C5E7C19F4E537987E18266 +IV=3B2A7C4278E1F071BFA29A6B0BFF4A15 +PT=84E244B62DF08DC76056A6C0B8732FC8 +CT=A35F83A5EE0B1C3B9DAD76DEAED96D72 + +I=278 +KEY=F8F9239CDB5CC963E869ECEE36CEFBFA02E325A72938EF14 +IV=A35F83A5EE0B1C3B9DAD76DEAED96D72 +PT=F0B652F296CF162B341756BA968BB9A7 +CT=D5867FFE2FB75E309D3345611B25E3B0 + +I=279 +KEY=509A10ABA5EAF2963DEF93101979A5CA9FD060C6321D0CA4 +IV=D5867FFE2FB75E309D3345611B25E3B0 +PT=C47D42AE34131463A86333377EB63BF5 +CT=6E136F01638AFBE3554218431DF44E7E + +I=280 +KEY=9B52C39C38F16CCE53FCFC117AF35E29CA9278852FE942DA +IV=6E136F01638AFBE3554218431DF44E7E +PT=78E05783EAEBE1BDCBC8D3379D1B9E58 +CT=FB6ACD3D0CF805374AD07EF5C038EBF6 + +I=281 +KEY=2044F086923D5E43A896312C760B5B1E80420670EFD1A92C +IV=FB6ACD3D0CF805374AD07EF5C038EBF6 +PT=02415B8E4D915492BB16331AAACC328D +CT=0086C26DA11540FF5F485D7B238FD98C + +I=282 +KEY=12CE4C4109606CD7A810F341D71E1BE1DF0A5B0BCC5E70A0 +IV=0086C26DA11540FF5F485D7B238FD98C +PT=0A2988237132B0B3328ABCC79B5D3294 +CT=F2E94C71A2AE0FCB096D8259B931CF8D + +I=283 +KEY=21BBCDA7FBC5229C5AF9BF3075B0142AD667D952756FBF2D +IV=F2E94C71A2AE0FCB096D8259B931CF8D +PT=4234B6C7F1CE98A3337581E6F2A54E4B +CT=3B52E7834263C6790763706943741FD8 + +I=284 +KEY=BB451732881A996161AB58B337D3D253D104A93B361BA0F5 +IV=3B52E7834263C6790763706943741FD8 +PT=F8509FB57E14501F9AFEDA9573DFBBFD +CT=93FCA9F122CB707213D0CD72D8E6BF74 + +I=285 +KEY=857D076E9A127A84F257F1421518A221C2D46449EEFD1F81 +IV=93FCA9F122CB707213D0CD72D8E6BF74 +PT=AA4D07DFAD030BE03E38105C1208E3E5 +CT=50717568D21862AECFAA898337405C96 + +I=286 +KEY=1BCFD020D63709E0A226842AC700C08F0D7EEDCAD9BD4317 +IV=50717568D21862AECFAA898337405C96 +PT=7B488D7BBB2D538E9EB2D74E4C257364 +CT=0338D74260CB6CBB1B220DE7E4CC0BCF + +I=287 +KEY=CCDDF5D0BBCE202DA11E5368A7CBAC34165CE02D3D7148D8 +IV=0338D74260CB6CBB1B220DE7E4CC0BCF +PT=16E01F8B3E94AC26D71225F06DF929CD +CT=698AD17BB2F5F06C0465BEE34A7DCEDD + +I=288 +KEY=B7F556BC9BB4DC49C8948213153E5C5812395ECE770C8605 +IV=698AD17BB2F5F06C0465BEE34A7DCEDD +PT=3ED0C80AFDEFE8BF7B28A36C207AFC64 +CT=E20129557F795C2B1CC32A5494824A4B + +I=289 +KEY=4B00D75969C3549C2A95AB466A4700730EFA749AE38ECC4E +IV=E20129557F795C2B1CC32A5494824A4B +PT=20BE0CD6C2244384FCF581E5F27788D5 +CT=C2F9DD55E91F4796636FEC9745410087 + +I=290 +KEY=5EDCC5155BA684A4E86C7613835847E56D95980DA6CFCCC9 +IV=C2F9DD55E91F4796636FEC9745410087 +PT=B2DF53DF1139FB9915DC124C3265D038 +CT=015D51CD3568EB4EC210B58FFA89A409 + +I=291 +KEY=21BA26AC6880AACDE93127DEB630ACABAF852D825C4668C0 +IV=015D51CD3568EB4EC210B58FFA89A409 +PT=401094B8B47CBDC87F66E3B933262E69 +CT=2987D39C19E6997957BDD0CAF010F778 + +I=292 +KEY=BBA7ABC0A20CCBDEC0B6F442AFD635D2F838FD48AC569FB8 +IV=2987D39C19E6997957BDD0CAF010F778 +PT=EFC30498827AAD9A9A1D8D6CCA8C6113 +CT=E01AA987C9520EF8EBF53E97371D056B + +I=293 +KEY=5322D81BAA29410320AC5DC566843B2A13CDC3DF9B4B9AD3 +IV=E01AA987C9520EF8EBF53E97371D056B +PT=685D6F660D40105CE88573DB08258ADD +CT=D1265ABFCFA75FC65E94983BFF75CD48 + +I=294 +KEY=19DF73EBF1CEF669F18A077AA92364EC4D595BE4643E579B +IV=D1265ABFCFA75FC65E94983BFF75CD48 +PT=DD6E090E9981E5F24AFDABF05BE7B76A +CT=605FDD1CA95B8FE1A5E26DBA10241914 + +I=295 +KEY=F7D1D0CA3DAA851891D5DA660078EB0DE8BB365E741A4E8F +IV=605FDD1CA95B8FE1A5E26DBA10241914 +PT=9F8442EE8B5A325FEE0EA321CC647371 +CT=76D67121FDEAEB6B81DBB29565F71E8E + +I=296 +KEY=FFFF200EA04824E9E703AB47FD920066696084CB11ED5001 +IV=76D67121FDEAEB6B81DBB29565F71E8E +PT=5AF386509F0C8BAA082EF0C49DE2A1F1 +CT=7E1D833DC8D73228B7DFDE918E31E5E7 + +I=297 +KEY=2A7D40B689490FC7991E287A3545324EDEBF5A5A9FDCB5E6 +IV=7E1D833DC8D73228B7DFDE918E31E5E7 +PT=02AB05F508ACDD21D58260B829012B2E +CT=D6CA06D415EA5D750B5D06C252645A43 + +I=298 +KEY=134154161A39E2CF4FD42EAE20AF6F3BD5E25C98CDB8EFA5 +IV=D6CA06D415EA5D750B5D06C252645A43 +PT=E63873AE14DD3BA8393C14A09370ED08 +CT=BFEA32E77BC1607921C54027C01C3EDF + +I=299 +KEY=AD8AF90935A6B455F03E1C495B6E0F42F4271CBF0DA4D17A +IV=BFEA32E77BC1607921C54027C01C3EDF +PT=BAD47B1FBF949870BECBAD1F2F9F569A +CT=A86FFC9A91C79AFE47899B3934F3E05E + +I=300 +KEY=D88A2E828514CEC25851E0D3CAA995BCB3AE878639573124 +IV=A86FFC9A91C79AFE47899B3934F3E05E +PT=2A2115074A9767747500D78BB0B27A97 +CT=507ED155CC3ED3B1922BBC166812A7FE + +I=301 +KEY=2CDDF1A577A3C86C082F31860697460D21853B90514596DA +IV=507ED155CC3ED3B1922BBC166812A7FE +PT=308D27178ABA22BCF457DF27F2B706AE +CT=87F4EEA7CD2438F3EDCB650824A2D638 + +I=302 +KEY=2B9D006908018D648FDBDF21CBB37EFECC4E5E9875E740E2 +IV=87F4EEA7CD2438F3EDCB650824A2D638 +PT=28F6C452D061E3DB0740F1CC7FA24508 +CT=DBA57DDA73A4E987EA32EF113877E908 + +I=303 +KEY=FC69838410D06425547EA2FBB8179779267CB1894D90A9EA +IV=DBA57DDA73A4E987EA32EF113877E908 +PT=91CFB50FFBE97D8AD7F483ED18D1E941 +CT=1720ED3E3B685A19CDA66BD09BD4DA5F + +I=304 +KEY=541AAB6191E2C51F435E4FC5837FCD60EBDADA59D64473B5 +IV=1720ED3E3B685A19CDA66BD09BD4DA5F +PT=78FF980C48FAEBA0A87328E58132A13A +CT=ED2E260103CAA77598FD195D02B484C8 + +I=305 +KEY=761B0A3F50E2ACC1AE7069C480B56A157327C304D4F0F77D +IV=ED2E260103CAA77598FD195D02B484C8 +PT=8C01554039D8F8EE2201A15EC10069DE +CT=A9F0E16716B3AC14E06F18F5AEECB541 + +I=306 +KEY=70056CD35CF430D5078088A39606C6019348DBF17A1C423C +IV=A9F0E16716B3AC14E06F18F5AEECB541 +PT=C139651464D1614B061E66EC0C169C14 +CT=A41DDF008E0D52B627982D4196C3069E + +I=307 +KEY=EE1932746487B7BEA39D57A3180B94B7B4D0F6B0ECDF44A2 +IV=A41DDF008E0D52B627982D4196C3069E +PT=C617572884721A3D9E1C5EA73873876B +CT=44E5304E35A21660C450FAF84D87B13B + +I=308 +KEY=13D43E4526F8243FE77867ED2DA982D770800C48A158F599 +IV=44E5304E35A21660C450FAF84D87B13B +PT=9C72E08DD264D6B7FDCD0C31427F9381 +CT=173B2C7A54A1A3CF3D39DCB68DA1C539 + +I=309 +KEY=7CB72DE2CAED4080F0434B97790821184DB9D0FE2CF930A0 +IV=173B2C7A54A1A3CF3D39DCB68DA1C539 +PT=4DF3764F679E29446F6313A7EC1564BF +CT=F1A167A3EB8F3FAB9F9B1570475ED15A + +I=310 +KEY=A7E6340A1278A3E801E22C3492871EB3D222C58E6BA7E1FA +IV=F1A167A3EB8F3FAB9F9B1570475ED15A +PT=2ED419EA11AAF8F3DB5119E8D895E368 +CT=2C5C5B10E285FE6C7E4750D2F9C1BD23 + +I=311 +KEY=4B535B4D088F09192DBE77247002E0DFAC65955C92665CD9 +IV=2C5C5B10E285FE6C7E4750D2F9C1BD23 +PT=A3E9EA99771D0C02ECB56F471AF7AAF1 +CT=A12B4A15DBFAE2E7D4A7A792CD3C121A + +I=312 +KEY=2F0E7BAD76DC0A718C953D31ABF8023878C232CE5F5A4EC3 +IV=A12B4A15DBFAE2E7D4A7A792CD3C121A +PT=1CC105D2604628B7645D20E07E530368 +CT=65CE700B785D901C5E5E08F7E74BB296 + +I=313 +KEY=6111C386DE35C954E95B4D3AD3A59224269C3A39B811FC55 +IV=65CE700B785D901C5E5E08F7E74BB296 +PT=F902717AF7F0794E4E1FB82BA8E9C325 +CT=E7F3BD1056C504285FFC7F65B395DCAE + +I=314 +KEY=3B8F85E6FD28C4610EA8F02A8560960C7960455C0B8420FB +IV=E7F3BD1056C504285FFC7F65B395DCAE +PT=20A5529420D6D4C35A9E4660231D0D35 +CT=6CC36458ADECCA8B7198FD272A8C76C8 + +I=315 +KEY=D404C97E089F240B626B9472288C5C8708F8B87B21085633 +IV=6CC36458ADECCA8B7198FD272A8C76C8 +PT=1094639F6723C9B0EF8B4C98F5B7E06A +CT=D01C3C1E036D804563F04926ED203146 + +I=316 +KEY=4779B44770085E18B277A86C2BE1DCC26B08F15DCC286775 +IV=D01C3C1E036D804563F04926ED203146 +PT=A482437681DFE307937D7D3978977A13 +CT=319D579DE9E55C8A3B2097EE8C93375F + +I=317 +KEY=22362304D7417BB483EAFFF1C2048048502866B340BB502A +IV=319D579DE9E55C8A3B2097EE8C93375F +PT=7AF0C8274B5C243B654F9743A74925AC +CT=5F722165B8B422E088814B77A6B4D8E4 + +I=318 +KEY=06FDA49350C16FEADC98DE947AB0A2A8D8A92DC4E60F88CE +IV=5F722165B8B422E088814B77A6B4D8E4 +PT=A37964FA3E8145EF24CB87978780145E +CT=C0417773DFD3FC83C2CE12D388F5DD8F + +I=319 +KEY=366245F8CBC490611CD9A9E7A5635E2B1A673F176EFA5541 +IV=C0417773DFD3FC83C2CE12D388F5DD8F +PT=5D7E1E14F7BD7DB6309FE16B9B05FF8B +CT=2EAE64B58C18AC7ADD2EE62896AB708D + +I=320 +KEY=A1BB8A9F9BE8F1383277CD52297BF251C749D93FF85125CC +IV=2EAE64B58C18AC7ADD2EE62896AB708D +PT=3ADC6991BF15554F97D9CF67502C6159 +CT=069FC966F8A985AD41617CB0148D2B96 + +I=321 +KEY=7AB228E4114C14AB34E80434D1D277FC8628A58FECDC0E5A +IV=069FC966F8A985AD41617CB0148D2B96 +PT=4405B80CCE92FD71DB09A27B8AA4E593 +CT=13459A0239A33BC41424A5D03C6B2864 + +I=322 +KEY=78D1BC27E5CBBB1D27AD9E36E8714C38920C005FD0B7263E +IV=13459A0239A33BC41424A5D03C6B2864 +PT=B9BAA861988616CD026394C3F487AFB6 +CT=08DA968A2BAEB9B763EB42BF555A2BFA + +I=323 +KEY=F53B033A22EA1D7B2F7708BCC3DFF58FF1E742E085ED0DC4 +IV=08DA968A2BAEB9B763EB42BF555A2BFA +PT=30654265AD0FB24E8DEABF1DC721A666 +CT=E8412BDC1E75AC8E2C28552E2195795E + +I=324 +KEY=4928B51AF5C2408CC7362360DDAA5901DDCF17CEA478749A +IV=E8412BDC1E75AC8E2C28552E2195795E +PT=EEB05E487EEB907FBC13B620D7285DF7 +CT=E01839F95680D27E048383236D59EE85 + +I=325 +KEY=C4DB91EAFC4C26D7272E1A998B2A8B7FD94C94EDC9219A1F +IV=E01839F95680D27E048383236D59EE85 +PT=BA0160229D7471FE8DF324F0098E665B +CT=D41902E6BE946CEB1612CFEE2F33F7CD + +I=326 +KEY=B550731E659834A1F337187F35BEE794CF5E5B03E6126DD2 +IV=D41902E6BE946CEB1612CFEE2F33F7CD +PT=7DC970AFAF99BA6C718BE2F499D41276 +CT=326C3523173D62E9E145592E7A774311 + +I=327 +KEY=5F87F6C2402B2352C15B2D5C2283857D2E1B022D9C652EC3 +IV=326C3523173D62E9E145592E7A774311 +PT=24ED6DAE1B24CC2BEAD785DC25B317F3 +CT=DDAE8AFF94604FFA82AE4FFB06953C01 + +I=328 +KEY=3636C04061996CD01CF5A7A3B6E3CA87ACB54DD69AF012C2 +IV=DDAE8AFF94604FFA82AE4FFB06953C01 +PT=98E262805B8D9FD169B1368221B24F82 +CT=0D75DCFA4941BCE658DB2C71CB270BE7 + +I=329 +KEY=64B9A0DE7DDA73C011807B59FFA27661F46E61A751D71925 +IV=0D75DCFA4941BCE658DB2C71CB270BE7 +PT=2BC34C226D41D8CE528F609E1C431F10 +CT=D70ED1DCDB9420E4B4A0D2A7C5148DE3 + +I=330 +KEY=F64196479D35F74BC68EAA852436568540CEB30094C394C6 +IV=D70ED1DCDB9420E4B4A0D2A7C5148DE3 +PT=1015CB1E4569986C92F83699E0EF848B +CT=524314DCCF2ADE5F8C3D241824C2BA73 + +I=331 +KEY=686AB32115A2884C94CDBE59EB1C88DACCF39718B0012EB5 +IV=524314DCCF2ADE5F8C3D241824C2BA73 +PT=FB8B49053F724B7D9E2B256688977F07 +CT=7C579324F7251EDF95BDE2320104ACA6 + +I=332 +KEY=34DD68E6F442F6D9E89A2D7D1C399605594E752AB1058213 +IV=7C579324F7251EDF95BDE2320104ACA6 +PT=A3B71504A8DAA3515CB7DBC7E1E07E95 +CT=921A66278A6D1E61D4B509F199F8FE55 + +I=333 +KEY=19C9F40A858DD9EA7A804B5A965488648DFB7CDB28FD7C46 +IV=921A66278A6D1E61D4B509F199F8FE55 +PT=B0B651905E1B38FB2D149CEC71CF2F33 +CT=F2C37CF94514C902A0E438159C2C9F5F + +I=334 +KEY=B68812FC7D4E40D6884337A3D34041662D1F44CEB4D1E319 +IV=F2C37CF94514C902A0E438159C2C9F5F +PT=7DE03F498839F8DAAF41E6F6F8C3993C +CT=4596A25A85D06BCC74F686F8F1E8C203 + +I=335 +KEY=2836F982CA563379CDD595F956902AAA59E9C2364539211A +IV=4596A25A85D06BCC74F686F8F1E8C203 +PT=D5425E42151014ED9EBEEB7EB71873AF +CT=0BA46EFA61FB07430C51D7CE267E1F47 + +I=336 +KEY=BC8C7F9051C98892C671FB03376B2DE955B815F863473E5D +IV=0BA46EFA61FB07430C51D7CE267E1F47 +PT=5D060EEC179C1B9E94BA86129B9FBBEB +CT=49F7D7D7BAB7795A4E74A854C8C1AC53 + +I=337 +KEY=E661F49B22BC92358F862CD48DDC54B31BCCBDACAB86920E +IV=49F7D7D7BAB7795A4E74A854C8C1AC53 +PT=C598926A437A27A45AED8B0B73751AA7 +CT=0EB97E32AEC4CE3959197C5B72C1ABC5 + +I=338 +KEY=E625AB8664BCF057813F52E623189A8A42D5C1F7D94739CB +IV=0EB97E32AEC4CE3959197C5B72C1ABC5 +PT=B7272C4D712F9CF500445F1D46006262 +CT=DA9F53564E69AED610BCCAD13C00A241 + +I=339 +KEY=75FC1D46AFD886915BA001B06D71345C52690B26E5479B8A +IV=DA9F53564E69AED610BCCAD13C00A241 +PT=FE7513CF9353BBF093D9B6C0CB6476C6 +CT=7F61B6F9B7C14EB6179F2DA597EC1183 + +I=340 +KEY=F92D3201DA84422024C1B749DAB07AEA45F6268372AB8A09 +IV=7F61B6F9B7C14EB6179F2DA597EC1183 +PT=4E4D3DF58D7D9C338CD12F47755CC4B1 +CT=F9216373C300AA9BE96BD8C98F9716B7 + +I=341 +KEY=680384A1E522C848DDE0D43A19B0D071AC9DFE4AFD3C9CBE +IV=F9216373C300AA9BE96BD8C98F9716B7 +PT=1A7B30192D54142E912EB6A03FA68A68 +CT=8512BA1B57BC04EF3C021DB1EC3CA9C6 + +I=342 +KEY=DE3B85BD09EC93B858F26E214E0CD49E909FE3FB11003578 +IV=8512BA1B57BC04EF3C021DB1EC3CA9C6 +PT=86587FF85D73F77FB638011CECCE5BF0 +CT=FA582C37D4063D61428C886A9FD54C84 + +I=343 +KEY=C574CA7322F443FBA2AA42169A0AE9FFD2136B918ED579FC +IV=FA582C37D4063D61428C886A9FD54C84 +PT=3A7425A8B7BC3A941B4F4FCE2B18D043 +CT=7571B4D46CBC671964AB5BDE9C843DCF + +I=344 +KEY=078109812EFBA9DBD7DBF6C2F6B68EE6B6B8304F12514433 +IV=7571B4D46CBC671964AB5BDE9C843DCF +PT=5224060F0848F028C2F5C3F20C0FEA20 +CT=DA9EB72D65D492FE88B819674B8433C1 + +I=345 +KEY=5BF7FA2E15A87C850D4541EF93621C183E00292859D577F2 +IV=DA9EB72D65D492FE88B819674B8433C1 +PT=2622B2A19CBBAD065C76F3AF3B53D55E +CT=C66EF470CEDDD499AE6214E75DE9051B + +I=346 +KEY=ECBE2377CAF0C9E9CB2BB59F5DBFC88190623DCF043C72E9 +IV=C66EF470CEDDD499AE6214E75DE9051B +PT=833F22A76D51E360B749D959DF58B56C +CT=57407E3DEFFF753E879619424FCE5713 + +I=347 +KEY=4EAB83DA78D60CB09C6BCBA2B240BDBF17F4248D4BF225FA +IV=57407E3DEFFF753E879619424FCE5713 +PT=25781A534FB9192CA215A0ADB226C559 +CT=644D89381439E7BBED7DC344CBF4C886 + +I=348 +KEY=C4977EF1F6271D6CF826429AA6795A04FA89E7C98006ED7C +IV=644D89381439E7BBED7DC344CBF4C886 +PT=E8EDD9AA25A8C5B08A3CFD2B8EF111DC +CT=CA4B2680D0EE8E28818BE8DE8D625ADC + +I=349 +KEY=80212F6D11C6DAE2326D641A7697D42C7B020F170D64B7A0 +IV=CA4B2680D0EE8E28818BE8DE8D625ADC +PT=8F667EEDB79E930644B6519CE7E1C78E +CT=5497F477AD5E65BB748A781533F1BCEF + +I=350 +KEY=A05DF1DF7E0393A566FA906DDBC9B1970F8877023E950B4F +IV=5497F477AD5E65BB748A781533F1BCEF +PT=099FDB76E6D21788207CDEB26FC54947 +CT=C8C541B359BF1B53441C4EFFFD2F65AF + +I=351 +KEY=3970F236F800D18BAE3FD1DE8276AAC44B9439FDC3BA6EE0 +IV=C8C541B359BF1B53441C4EFFFD2F65AF +PT=C79FA2079ECCEBCD992D03E98603422E +CT=E59765A861DE0168161EA1360B5966A9 + +I=352 +KEY=8ED3BFA3E4C9453C4BA8B476E3A8ABAC5D8A98CBC8E30849 +IV=E59765A861DE0168161EA1360B5966A9 +PT=AFBCD48F06709730B7A34D951CC994B7 +CT=5A65435BD1B4DB742E8AFF8C402927FC + +I=353 +KEY=2A3F01E56E45895B11CDF72D321C70D87300674788CA2FB5 +IV=5A65435BD1B4DB742E8AFF8C402927FC +PT=CF684F64B8CCD2EDA4ECBE468A8CCC67 +CT=551AF68D50D23408F47214C0B18E6C8A + +I=354 +KEY=CA12AC8D17941E6244D701A062CE44D0877273873944433F +IV=551AF68D50D23408F47214C0B18E6C8A +PT=561072AC144854C1E02DAD6879D19739 +CT=ADFF035C89E040A4C3CCE190D6CB7283 + +I=355 +KEY=D1CA1B08A51B5086E92802FCEB2E047444BE9217EF8F31BC +IV=ADFF035C89E040A4C3CCE190D6CB7283 +PT=827ADE7D0F329D9A1BD8B785B28F4EE4 +CT=425F5596D3FD37243EE59D6FC1F5ADCC + +I=356 +KEY=54EC325FE63AA470AB77576A38D333507A5B0F782E7A9C70 +IV=425F5596D3FD37243EE59D6FC1F5ADCC +PT=4AAF21E64F8DBDB0852629574321F4F6 +CT=D85520FE860C9F320CDC8192A900F499 + +I=357 +KEY=5B4612BC35BFC12473227794BEDFAC6276878EEA877A68E9 +IV=D85520FE860C9F320CDC8192A900F499 +PT=0D046A402A1860C70FAA20E3D3856554 +CT=11C20F3ACED79B37402B2F04886D4CC7 + +I=358 +KEY=5052384CE705101562E078AE7008375536ACA1EE0F17242E +IV=11C20F3ACED79B37402B2F04886D4CC7 +PT=7546E6521BBBFAFE0B142AF0D2BAD131 +CT=BCDA339266E3AFB779AF17CE34218BE5 + +I=359 +KEY=F7ECFB2AA4FC6DE2DE3A4B3C16EB98E24F03B6203B36AFCB +IV=BCDA339266E3AFB779AF17CE34218BE5 +PT=85DF7958789E9090A7BEC36643F97DF7 +CT=300D46EAB6466314BB00DBC869C77F4E + +I=360 +KEY=1E27229506EC9555EE370DD6A0ADFBF6F4036DE852F1D085 +IV=300D46EAB6466314BB00DBC869C77F4E +PT=C6CED700614467A0E9CBD9BFA210F8B7 +CT=51735C075A14FE95D4A02F527A9474D3 + +I=361 +KEY=857F653E1E811CABBF4451D1FAB9056320A342BA2865A456 +IV=51735C075A14FE95D4A02F527A9474D3 +PT=53D436401D6811B19B5847AB186D89FE +CT=827017531E56980C4357549D0E70114F + +I=362 +KEY=1BCE612F3A5262223D344682E4EF9D6F63F416272615B519 +IV=827017531E56980C4357549D0E70114F +PT=4C1BD17FFD65AB2C9EB1041124D37E89 +CT=751BCA9516123906561FB8AF2208CEE1 + +I=363 +KEY=7C7034EC27524FC3482F8C17F2FDA46935EBAE88041D7BF8 +IV=751BCA9516123906561FB8AF2208CEE1 +PT=7C23D6E77039F35267BE55C31D002DE1 +CT=82CAFBBE859FA80B2A8E58CEC074B01A + +I=364 +KEY=7F31EEE0447BB53CCAE577A977620C621F65F646C469CBE2 +IV=82CAFBBE859FA80B2A8E58CEC074B01A +PT=B91FF7759419BBB10341DA0C6329FAFF +CT=B7614376C9BAFC92E17E39D2BDF1F2EF + +I=365 +KEY=E705144BCE40FC987D8434DFBED8F0F0FE1BCF947998390D +IV=B7614376C9BAFC92E17E39D2BDF1F2EF +PT=72B3472217AC80979834FAAB8A3B49A4 +CT=A63BA38FDDFE99D28BA447871BBA6211 + +I=366 +KEY=15C813D2D9AD1494DBBF97506326692275BF881362225B1C +IV=A63BA38FDDFE99D28BA447871BBA6211 +PT=349F8E5FAE004B51F2CD079917EDE80C +CT=C87E448872E619419766CB46787F2581 + +I=367 +KEY=B12B790C217821DA13C1D3D811C07063E2D943551A5D7E9D +IV=C87E448872E619419766CB46787F2581 +PT=EC474C794E3C8322A4E36ADEF8D5354E +CT=73DD478F7F41857F7A5DE7EDF3F1AF7B + +I=368 +KEY=1CFA6A54B3E572DC601C94576E81F51C9884A4B8E9ACD1E6 +IV=73DD478F7F41857F7A5DE7EDF3F1AF7B +PT=48F8361EF11F94C1ADD11358929D5306 +CT=8B85DE2CBE5C96CBDFE16064079754D9 + +I=369 +KEY=6718C10E683F4D73EB994A7BD0DD63D74765C4DCEE3B853F +IV=8B85DE2CBE5C96CBDFE16064079754D9 +PT=59BFDA108542EDDB7BE2AB5ADBDA3FAF +CT=56FF53384CED780F604F86EC0CE26B26 + +I=370 +KEY=704ED4F1E96776A2BD6619439C301BD8272A4230E2D9EE19 +IV=56FF53384CED780F604F86EC0CE26B26 +PT=468FDBDB8BC26B5A175615FF81583BD1 +CT=7B0C2436262A262C5FAFC3A9B786DB00 + +I=371 +KEY=67AFB86317B622B2C66A3D75BA1A3DF478858199555F3519 +IV=7B0C2436262A262C5FAFC3A9B786DB00 +PT=768BE978E5E8CA6E17E16C92FED15410 +CT=D32206D5D1521AB667516391810F5719 + +I=372 +KEY=0BF4E0C32EA3D69615483BA06B4827421FD4E208D4506200 +IV=D32206D5D1521AB667516391810F5719 +PT=1943C5D93D10A0E36C5B58A03915F424 +CT=6BCE2BEC0D5A0DA9051AF2B34A873694 + +I=373 +KEY=924D1C527572A2EF7E86104C66122AEB1ACE10BB9ED75494 +IV=6BCE2BEC0D5A0DA9051AF2B34A873694 +PT=E3020D099D0841C299B9FC915BD17479 +CT=3BEBA6BA0762BF5FAA4D26B70071B4A9 + +I=374 +KEY=CFA41DB53F2F8766456DB6F6617095B4B083360C9EA6E03D +IV=3BEBA6BA0762BF5FAA4D26B70071B4A9 +PT=31F7316F0D1012CD5DE901E74A5D2589 +CT=C4253CED7F88DF97596B08A15BAEF533 + +I=375 +KEY=E2B9D43008C1537281488A1B1EF84A23E9E83EADC508150E +IV=C4253CED7F88DF97596B08A15BAEF533 +PT=00365D6755A898E62D1DC98537EED414 +CT=2D4EB6BA84D1C0C978EA20C1693BB75C + +I=376 +KEY=43EA75DFD5B35CCBAC063CA19A298AEA91021E6CAC33A252 +IV=2D4EB6BA84D1C0C978EA20C1693BB75C +PT=599279C68B67A988A153A1EFDD720FB9 +CT=03698CC5E133AD8855B847C124FD2778 + +I=377 +KEY=8F2C76FCFBD8060DAF6FB0647B1A2762C4BA59AD88CE852A +IV=03698CC5E133AD8855B847C124FD2778 +PT=47EFAF7E090B94B5CCC603232E6B5AC6 +CT=8D44C11C25ADE5631E05FAAECCA70AF7 + +I=378 +KEY=E02084775A2E1A4E222B71785EB7C201DABFA30344698FDD +IV=8D44C11C25ADE5631E05FAAECCA70AF7 +PT=394EC624EBC0D79E6F0CF28BA1F61C43 +CT=5EB407847213D5E950C66787B140BC35 + +I=379 +KEY=D8208A70940589F47C9F76FC2CA417E88A79C484F52933E8 +IV=5EB407847213D5E950C66787B140BC35 +PT=F28816D227AC09F538000E07CE2B93BA +CT=2D4FBD74A027526BADC8C2A433963C22 + +I=380 +KEY=858193C76AFE48D951D0CB888C83458327B10620C6BF0FCA +IV=2D4FBD74A027526BADC8C2A433963C22 +PT=FBAA6C644F8E08885DA119B7FEFBC12D +CT=FA2DAE761EBBFDE4B77CBCD2381165DB + +I=381 +KEY=DA9A9F800056FC6EABFD65FE9238B86790CDBAF2FEAE6A11 +IV=FA2DAE761EBBFDE4B77CBCD2381165DB +PT=F66A574C26D0F15C5F1B0C476AA8B4B7 +CT=DB18F5B16BF19C2BCCA36091A302BF38 + +I=382 +KEY=BD2AB07F036032AB70E5904FF9C9244C5C6EDA635DACD529 +IV=DB18F5B16BF19C2BCCA36091A302BF38 +PT=04B0C1A19C6D38B467B02FFF0336CEC5 +CT=D3F01581B21DF4E470EE595CAB44912C + +I=383 +KEY=7EF57F6BDE41D79CA31585CE4BD4D0A82C80833FF6E84405 +IV=D3F01581B21DF4E470EE595CAB44912C +PT=83BF32E0F3F3CEE7C3DFCF14DD21E537 +CT=10C69B9A04E0851B63D85D025BBACA29 + +I=384 +KEY=22057A9912BB6B76B3D31E544F3455B34F58DE3DAD528E2C +IV=10C69B9A04E0851B63D85D025BBACA29 +PT=150ACC96322893CC5CF005F2CCFABCEA +CT=2743FE5769DDA5D591318E200AF672D0 + +I=385 +KEY=742A2117B51176E69490E00326E9F066DE69501DA7A4FCFC +IV=2743FE5769DDA5D591318E200AF672D0 +PT=93246C1A26F66DAF562F5B8EA7AA1D90 +CT=5CA8FC8DB4A20B2CA8AB86B1B40DA1A1 + +I=386 +KEY=3C09F8C3B20BE749C8381C8E924BFB4A76C2D6AC13A95D5D +IV=5CA8FC8DB4A20B2CA8AB86B1B40DA1A1 +PT=D91806E0F3451C374823D9D4071A91AF +CT=25701E4C6685C98333566EB75498AEB7 + +I=387 +KEY=DD0386F2D0D1E8FFED4802C2F4CE32C94594B81B4731F3EA +IV=25701E4C6685C98333566EB75498AEB7 +PT=701A5D7027053688E10A7E3162DA0FB6 +CT=E4A5889FC49B62F767F61F1D2810801A + +I=388 +KEY=BB9A1FA7287B0D3D09ED8A5D3055503E2262A7066F2173F0 +IV=E4A5889FC49B62F767F61F1D2810801A +PT=A110B0A38255279B66999955F8AAE5C2 +CT=F1A9BDA2045F3EAE2AB9CEE2AD352270 + +I=389 +KEY=21B561DC3C44B5A5F84437FF340A6E9008DB69E4C2145180 +IV=F1A9BDA2045F3EAE2AB9CEE2AD352270 +PT=1562CF8420963B479A2F7E7B143FB898 +CT=E7E2BA657D3482A4825D643B8C01B52E + +I=390 +KEY=60A0FA1F5FA435401FA68D9A493EEC348A860DDF4E15E4AE +IV=E7E2BA657D3482A4825D643B8C01B52E +PT=930490633BC4EDC941159BC363E080E5 +CT=2FDBCD145EB8620594834B0D63BBD137 + +I=391 +KEY=7DD1686F811E4017307D408E17868E311E0546D22DAE3599 +IV=2FDBCD145EB8620594834B0D63BBD137 +PT=4BB1C43F4ABC51CD1D719270DEBA7557 +CT=B703658AD9FFCDE05E2C7E252990402E + +I=392 +KEY=18203DC5AAA632F5877E2504CE7943D1402938F7043E75B7 +IV=B703658AD9FFCDE05E2C7E252990402E +PT=47931942F275F05E65F155AA2BB872E2 +CT=5B79CB7FA90D3BB5A979A4588D4DE434 + +I=393 +KEY=9F6D532CBAF42FCDDC07EE7B67747864E9509CAF89739183 +IV=5B79CB7FA90D3BB5A979A4588D4DE434 +PT=E3A36DF4EB896B4D874D6EE910521D38 +CT=61BF460521E67B3CAC638F3298EF9310 + +I=394 +KEY=ED4F97BC99036E83BDB8A87E469203584533139D119C0293 +IV=61BF460521E67B3CAC638F3298EF9310 +PT=55EABDF72CCB5D737222C49023F7414E +CT=8A27D87B53B2FB8BBAFF7851AF1D51F2 + +I=395 +KEY=E1B9A7291D885F8E379F70051520F8D3FFCC6BCCBE815361 +IV=8A27D87B53B2FB8BBAFF7851AF1D51F2 +PT=D30271EA236E948F0CF63095848B310D +CT=15075FDCBD2D6FC15B9A3841A2D58C34 + +I=396 +KEY=976B101EE3E10E0822982FD9A80D9712A456538D1C54DF55 +IV=15075FDCBD2D6FC15B9A3841A2D58C34 +PT=879EED3434159D8076D2B737FE695186 +CT=6896582462983FAAE443078F9768B339 + +I=397 +KEY=A7A3277BF5F605FC4A0E77FDCA95A8B8401554028B3C6C6C +IV=6896582462983FAAE443078F9768B339 +PT=89DDABE96D1069ED30C8376516170BF4 +CT=96FE6B921416B667AA5B34D2D2E25747 + +I=398 +KEY=DD57026B1D4E32A8DCF01C6FDE831EDFEA4E60D059DE3B2B +IV=96FE6B921416B667AA5B34D2D2E25747 +PT=8144C8BB09FC72827AF42510E8B83754 +CT=EEDC3677AB7B57829F6D733F8090DA8A + +I=399 +KEY=B4D1BDF297DC0574322C2A1875F8495D752313EFD94EE1A1 +IV=EEDC3677AB7B57829F6D733F8090DA8A +PT=510F7A55799B39786986BF998A9237DC +CT=BA50C94440C04A8C0899D42658E25437 + +========== + +KEYSIZE=256 + +I=0 +KEY=0000000000000000000000000000000000000000000000000000000000000000 +IV=00000000000000000000000000000000 +PT=00000000000000000000000000000000 +CT=FE3C53653E2F45B56FCD88B2CC898FF0 + +I=1 +KEY=B2493DE29713367D9FAA93469F8EF596FE3C53653E2F45B56FCD88B2CC898FF0 +IV=FE3C53653E2F45B56FCD88B2CC898FF0 +PT=B2493DE29713367D9FAA93469F8EF596 +CT=7CE2ABAF8BEF23C4816DC8CE842048A7 + +I=2 +KEY=33A36646FE56F70DC0C51A3117E639F182DEF8CAB5C06671EEA0407C48A9C757 +IV=7CE2ABAF8BEF23C4816DC8CE842048A7 +PT=81EA5BA46945C1705F6F89778868CC67 +CT=50CD14A12C6852D39654C816BFAF9AC2 + +I=3 +KEY=0D6A3DACE75B104CA8A303A32670BF3AD213EC6B99A834A278F4886AF7065D95 +IV=50CD14A12C6852D39654C816BFAF9AC2 +PT=3EC95BEA190DE74168661992319686CB +CT=3F411DAD0E339FE281637133BF46BD13 + +I=4 +KEY=A53BE0709BF686A7DB7C3848D81AB66BED52F1C6979BAB40F997F9594840E086 +IV=3F411DAD0E339FE281637133BF46BD13 +PT=A851DDDC7CAD96EB73DF3BEBFE6A0951 +CT=5BA2C7663A4061719A7CCC2AF2A3EE8A + +I=5 +KEY=ECF3490CB7717A5236A3A94811BEBF13B6F036A0ADDBCA3163EB3573BAE30E0C +IV=5BA2C7663A4061719A7CCC2AF2A3EE8A +PT=49C8A97C2C87FCF5EDDF9100C9A40978 +CT=F105031CE7E5111317745C64F4F6D150 + +I=6 +KEY=CE8A062A2A9F9EDE2EFB43A8602BB47847F535BC4A3EDB22749F69174E15DF5C +IV=F105031CE7E5111317745C64F4F6D150 +PT=22794F269DEEE48C1858EAE071950B6B +CT=C8F030398A873550A34386D9A153D833 + +I=7 +KEY=2BE39545B8FC27444178BF0004C7F1048F050585C0B9EE72D7DCEFCEEF46076F +IV=C8F030398A873550A34386D9A153D833 +PT=E569936F9263B99A6F83FCA864EC457C +CT=519CF42C0BBFCBD79679089BC5E963B4 + +I=8 +KEY=80E9C0F78F99E309935C0A69B961D787DE99F1A9CB0625A541A5E7552AAF64DB +IV=519CF42C0BBFCBD79679089BC5E963B4 +PT=AB0A55B23765C44DD224B569BDA62683 +CT=64AC8FEA3B83584E9B7379B48F88B7A4 + +I=9 +KEY=48DDBDA704BA7702960820A0D2CA485CBA357E43F0857DEBDAD69EE1A527D37F +IV=64AC8FEA3B83584E9B7379B48F88B7A4 +PT=C8347D508B23940B05542AC96BAB9FDB +CT=2B1F53F35A308673E9B1E004C32B2080 + +I=10 +KEY=D26C4C6BE601D63BDDE6F1A49B5124CB912A2DB0AAB5FB9833677EE5660CF3FF +IV=2B1F53F35A308673E9B1E004C32B2080 +PT=9AB1F1CCE2BBA1394BEED104499B6C97 +CT=0DAE66B5741FE38E544D9EC4E90ABDAF + +I=11 +KEY=D241355DB8FC5F23D0D207F72E290F189C844B05DEAA1816672AE0218F064E50 +IV=0DAE66B5741FE38E544D9EC4E90ABDAF +PT=002D79365EFD89180D34F653B5782BD3 +CT=D00122636CC0D9D62E614EAF0963C448 + +I=12 +KEY=1BC3268A0B674A05B2FC6E18460231564C856966B26AC1C0494BAE8E86658A18 +IV=D00122636CC0D9D62E614EAF0963C448 +PT=C98213D7B39B1526622E69EF682B3E4E +CT=30EF014D1766651C524B3CC82F0140C6 + +I=13 +KEY=50BE5951A5C2403C52425897C442A8457C6A682BA50CA4DC1B009246A964CADE +IV=30EF014D1766651C524B3CC82F0140C6 +PT=4B7D7FDBAEA50A39E0BE368F82409913 +CT=BAD488702B447FABEC2074E1DD37E631 + +I=14 +KEY=C007EE52430FF98EDD206C94ED349DE6C6BEE05B8E48DB77F720E6A774532CEF +IV=BAD488702B447FABEC2074E1DD37E631 +PT=90B9B703E6CDB9B28F623403297635A3 +CT=EC3862EB60E7D8D0827645BD690F71B8 + +I=15 +KEY=AE37C1DBEBF9B269E8D10CC4F046F9FC2A8682B0EEAF03A77556A31A1D5C5D57 +IV=EC3862EB60E7D8D0827645BD690F71B8 +PT=6E302F89A8F64BE735F160501D72641A +CT=6073D1F25F3697C1E07384C67D71D8AE + +I=16 +KEY=86E8B9050AB24200E3757B67F08761534AF55342B1999466952527DC602D85F9 +IV=6073D1F25F3697C1E07384C67D71D8AE +PT=28DF78DEE14BF0690BA477A300C198AF +CT=90EF55AB8837792F82CF0F002E36F8DB + +I=17 +KEY=DE93EA10BB6DC2B0A6D3919561CE5AE4DA1A06E939AEED4917EA28DC4E1B7D22 +IV=90EF55AB8837792F82CF0F002E36F8DB +PT=587B5315B1DF80B045A6EAF291493BB7 +CT=063783CB1A2137732D10CA6233C5CE93 + +I=18 +KEY=3D147E3727A1FEB2C6F36AB9DF772E97DC2D8522238FDA3A3AFAE2BE7DDEB3B1 +IV=063783CB1A2137732D10CA6233C5CE93 +PT=E38794279CCC3C026020FB2CBEB97473 +CT=79C5CEEE64BFD33948D2E08EBE25B7E9 + +I=19 +KEY=34586C52923969647663A0D69436D7D1A5E84BCC4730090372280230C3FB0458 +IV=79C5CEEE64BFD33948D2E08EBE25B7E9 +PT=094C1265B59897D6B090CA6F4B41F946 +CT=87DFB65D575F56670DB739C988FD7DE5 + +I=20 +KEY=53724BF79612A7F0237927604619DD592237FD91106F5F647F9F3BF94B0679BD +IV=87DFB65D575F56670DB739C988FD7DE5 +PT=672A27A5042BCE94551A87B6D22F0A88 +CT=643F46BC77A5FE2434753B9C38142583 + +I=21 +KEY=8FBC30746F29985FFFA43C8BD3C4FC664608BB2D67CAA1404BEA006573125C3E +IV=643F46BC77A5FE2434753B9C38142583 +PT=DCCE7B83F93B3FAFDCDD1BEB95DD213F +CT=FD774BD6874EA7C0D790A5015440B664 + +I=22 +KEY=9A61A910701A4A42873549F78D3D9FD1BB7FF0FBE08406809C7AA5642752EA5A +IV=FD774BD6874EA7C0D790A5015440B664 +PT=15DD99641F33D21D7891757C5EF963B7 +CT=BFCEF4403428F5C96C24C249962371D4 + +I=23 +KEY=8D98738F6DF30113AF69A7A61C1582EE04B104BBD4ACF349F05E672DB1719B8E +IV=BFCEF4403428F5C96C24C249962371D4 +PT=17F9DA9F1DE94B51285CEE5191281D3F +CT=CC79F35C41F0E6C0EB03472B1D13029E + +I=24 +KEY=976C27F1A15FF6780043636FC4777090C8C8F7E7955C15891B5D2006AC629910 +IV=CC79F35C41F0E6C0EB03472B1D13029E +PT=1AF4547ECCACF76BAF2AC4C9D862F27E +CT=0629B80F94FBC2C1984985B9F3B85BDD + +I=25 +KEY=E8934C533DED166F58D65C9E60A906A5CEE14FE801A7D7488314A5BF5FDAC2CD +IV=0629B80F94FBC2C1984985B9F3B85BDD +PT=7FFF6BA29CB2E01758953FF1A4DE7635 +CT=F2A70F4ED1A836696841D523F2650B55 + +I=26 +KEY=8116688C16D2C26D162C4D813FB267103C4640A6D00FE121EB55709CADBFC998 +IV=F2A70F4ED1A836696841D523F2650B55 +PT=698524DF2B3FD4024EFA111F5F1B61B5 +CT=A9B5565EB9B5D5DAC52BE0F449FBE11A + +I=27 +KEY=5A7062E77C6D20563AFD0BFDAAE04BE995F316F869BA34FB2E7E9068E4442882 +IV=A9B5565EB9B5D5DAC52BE0F449FBE11A +PT=DB660A6B6ABFE23B2CD1467C95522CF9 +CT=E47F675379D4CE3DDABA0F906BE014B2 + +I=28 +KEY=4DDC0A5938F4A3DC1AF8D3AFD3DF6198718C71AB106EFAC6F4C49FF88FA43C30 +IV=E47F675379D4CE3DDABA0F906BE014B2 +PT=17AC68BE4499838A2005D852793F2A71 +CT=7B95AB0E030C70B7940ECDAEFCA570A5 + +I=29 +KEY=E287EFC66626600AF3453F68BE53E5250A19DAA513628A7160CA525673014C95 +IV=7B95AB0E030C70B7940ECDAEFCA570A5 +PT=AF5BE59F5ED2C3D6E9BDECC76D8C84BD +CT=E854E5DE0C42D57B869C29FC8D5AFFF3 + +I=30 +KEY=7F3415A538F60B24A58447E1D38805B3E24D3F7B1F205F0AE6567BAAFE5BB366 +IV=E854E5DE0C42D57B869C29FC8D5AFFF3 +PT=9DB3FA635ED06B2E56C178896DDBE096 +CT=4E55EDEDC35CDEAB3BFB2B5D39871625 + +I=31 +KEY=59E5F5ECC5693DA07046636094970E8CAC18D296DC7C81A1DDAD50F7C7DCA543 +IV=4E55EDEDC35CDEAB3BFB2B5D39871625 +PT=26D1E049FD9F3684D5C22481471F0B3F +CT=3355C2CC762E58FA941E0004209CA710 + +I=32 +KEY=0B62CF7EA869036A529E9D184574CD609F4D105AAA52D95B49B350F3E7400253 +IV=3355C2CC762E58FA941E0004209CA710 +PT=52873A926D003ECA22D8FE78D1E3C3EC +CT=9B86680D69D38870268D42E78EDA2B50 + +I=33 +KEY=CEDC9CCC4DC42CB055EDC50597EE24DF04CB7857C381512B6F3E1214699A2903 +IV=9B86680D69D38870268D42E78EDA2B50 +PT=C5BE53B2E5AD2FDA0773581DD29AE9BF +CT=05DD4896F08EEAA6A53FA7BCF183F538 + +I=34 +KEY=CA30B422016C86247D75B618D19247AC011630C1330FBB8DCA01B5A89819DC3B +IV=05DD4896F08EEAA6A53FA7BCF183F538 +PT=04EC28EE4CA8AA942898731D467C6373 +CT=F81E56F4390D65C7959348A6FBD8A94E + +I=35 +KEY=B7096A2EC0259DA21ACA6DBE637A9F15F90866350A02DE4A5F92FD0E63C17575 +IV=F81E56F4390D65C7959348A6FBD8A94E +PT=7D39DE0CC1491B8667BFDBA6B2E8D8B9 +CT=4364CA2D90FA256084DF8E2FCDC62AB3 + +I=36 +KEY=436C0894D4436149EE685F0061BDF3AEBA6CAC189AF8FB2ADB4D7321AE075FC6 +IV=4364CA2D90FA256084DF8E2FCDC62AB3 +PT=F46562BA1466FCEBF4A232BE02C76CBB +CT=0991DE19A5ABE5F7E8AE24120789B9AB + +I=37 +KEY=44E1636AFF962EC4F1C446A89B9393C6B3FD72013F531EDD33E35733A98EE66D +IV=0991DE19A5ABE5F7E8AE24120789B9AB +PT=078D6BFE2BD54F8D1FAC19A8FA2E6068 +CT=0F4EF4FA608671AC5F71063CF6C1EBDE + +I=38 +KEY=44289918A9E99F859FC2F604FE38B86EBCB386FB5FD56F716C92510F5F4F0DB3 +IV=0F4EF4FA608671AC5F71063CF6C1EBDE +PT=00C9FA72567FB1416E06B0AC65AB2BA8 +CT=2D6A2A1CC9D208C16236BBC9451EC5E1 + +I=39 +KEY=BE5907C77B0939D20575F27427A2C3FE91D9ACE7960767B00EA4EAC61A51C852 +IV=2D6A2A1CC9D208C16236BBC9451EC5E1 +PT=FA719EDFD2E0A6579AB70470D99A7B90 +CT=237A8DFBA42708BBF7E540766F2059F1 + +I=40 +KEY=CD97125720F2002207AC44C456CDDF0DB2A3211C32206F0BF941AAB0757191A3 +IV=237A8DFBA42708BBF7E540766F2059F1 +PT=73CE15905BFB39F002D9B6B0716F1CF3 +CT=2D1AB5CF3E9C27ADA9FB45F15007A7BB + +I=41 +KEY=123F64F2A28C80C2F6E000F69C8E5A639FB994D30CBC48A650BAEF4125763618 +IV=2D1AB5CF3E9C27ADA9FB45F15007A7BB +PT=DFA876A5827E80E0F14C4432CA43856E +CT=7039C9AF1E10FE99A91483EA578AE6DD + +I=42 +KEY=6CD69C4F5AD7CB5E9E4574F6A48FDB28EF805D7C12ACB63FF9AE6CAB72FCD0C5 +IV=7039C9AF1E10FE99A91483EA578AE6DD +PT=7EE9F8BDF85B4B9C68A574003801814B +CT=116DD8566366A19EEAF2F3E744B3EF9C + +I=43 +KEY=C73969C7D6D057003E2E215D94978792FEED852A71CA17A1135C9F4C364F3F59 +IV=116DD8566366A19EEAF2F3E744B3EF9C +PT=ABEFF5888C079C5EA06B55AB30185CBA +CT=648A801EF27E77D964BB751A32B8CFE8 + +I=44 +KEY=E0960DD6E807F3D0B5DF057D0D1E6DCC9A67053483B4607877E7EA5604F7F0B1 +IV=648A801EF27E77D964BB751A32B8CFE8 +PT=27AF64113ED7A4D08BF124209989EA5E +CT=D18AE728717C535049868FA6F1B4294E + +I=45 +KEY=466AE043435C6CCA67FF1C5D4B4175DA4BEDE21CF2C833283E6165F0F543D9FF +IV=D18AE728717C535049868FA6F1B4294E +PT=A6FCED95AB5B9F1AD2201920465F1816 +CT=169B55360728DA8F582C488F2569411F + +I=46 +KEY=27E1BC4931601D667CD807454D58B2BB5D76B72AF5E0E9A7664D2D7FD02A98E0 +IV=169B55360728DA8F582C488F2569411F +PT=618B5C0A723C71AC1B271B180619C761 +CT=67DADCF7C31CA394F46F18AB1AEA022E + +I=47 +KEY=2D4EB1F3A709F0A4CA5E2CD47F8F10123AAC6BDD36FC4A33922235D4CAC09ACE +IV=67DADCF7C31CA394F46F18AB1AEA022E +PT=0AAF0DBA9669EDC2B6862B9132D7A2A9 +CT=A5D49BDF099335166BBFDCBE29C90B80 + +I=48 +KEY=2A90CE470EB8C9400B056307D53452BE9F78F0023F6F7F25F99DE96AE309914E +IV=A5D49BDF099335166BBFDCBE29C90B80 +PT=07DE7FB4A9B139E4C15B4FD3AABB42AC +CT=5AFC238F19E369E77278593C6E20A946 + +I=49 +KEY=90B696E9A0792BFF7BF21BE373731CB5C584D38D268C16C28BE5B0568D293808 +IV=5AFC238F19E369E77278593C6E20A946 +PT=BA2658AEAEC1E2BF70F778E4A6474E0B +CT=2861A363922099D0F0B2A5AD2A5F421E + +I=50 +KEY=4FE5C563B7DB98C6B9CCA52F313FBAFCEDE570EEB4AC8F127B5715FBA7767A16 +IV=2861A363922099D0F0B2A5AD2A5F421E +PT=DF53538A17A2B339C23EBECC424CA649 +CT=D76E51B6EA5F74D0116C4D16EDD0DFAC + +I=51 +KEY=EBF784D98E40372429819EE23BE85B723A8B21585EF3FBC26A3B58ED4AA6A5BA +IV=D76E51B6EA5F74D0116C4D16EDD0DFAC +PT=A41241BA399BAFE2904D3BCD0AD7E18E +CT=6214F5E50EC99F40B86951CE395C8315 + +I=52 +KEY=C01A5093C6A29CEED72D14D903BD17E8589FD4BD503A6482D252092373FA26AF +IV=6214F5E50EC99F40B86951CE395C8315 +PT=2BEDD44A48E2ABCAFEAC8A3B38554C9A +CT=6CFC2188E40E806BBE277988B924627E + +I=53 +KEY=A8C3A10380B6D4D1CEFABF57F3C695193463F535B434E4E96C7570ABCADE44D1 +IV=6CFC2188E40E806BBE277988B924627E +PT=68D9F1904614483F19D7AB8EF07B82F1 +CT=B98E851902AEC129FD1607DECA9E0669 + +I=54 +KEY=B828711ABA1D06408099944287112DE58DED702CB69A25C091637775004042B8 +IV=B98E851902AEC129FD1607DECA9E0669 +PT=10EBD0193AABD2914E632B1574D7B8FC +CT=DBDA9DB56E6FF915D67D7DEE541DD6A3 + +I=55 +KEY=3B0E9FE343D665ABB3706243EF023C765637ED99D8F5DCD5471E0A9B545D941B +IV=DBDA9DB56E6FF915D67D7DEE541DD6A3 +PT=8326EEF9F9CB63EB33E9F60168131193 +CT=399802CE3FF3878A73C7D85E19FDD54B + +I=56 +KEY=9270D72D972B46C8E630FBD1AA67FBED6FAFEF57E7065B5F34D9D2C54DA04150 +IV=399802CE3FF3878A73C7D85E19FDD54B +PT=A97E48CED4FD2363554099924565C79B +CT=40FABA067414961FD964EC91196943E3 + +I=57 +KEY=017211AC512541BFBDD0292385AA20862F5555519312CD40EDBD3E5454C902B3 +IV=40FABA067414961FD964EC91196943E3 +PT=9302C681C60E07775BE0D2F22FCDDB6B +CT=6BF1125E581341510FD02B9450886B17 + +I=58 +KEY=AC2652A877F924710178641D20B239B944A4470FCB018C11E26D15C0044169A4 +IV=6BF1125E581341510FD02B9450886B17 +PT=AD54430426DC65CEBCA84D3EA518193F +CT=74871D2EF6D1F29181B0A2530885EEC8 + +I=59 +KEY=0BF012A9F0CB194C1F00893D4803E10130235A213DD07E8063DDB7930CC4876C +IV=74871D2EF6D1F29181B0A2530885EEC8 +PT=A7D6400187323D3D1E78ED2068B1D8B8 +CT=2A2DC9F5CB47C94D430ECAAAB1D0811E + +I=60 +KEY=8D22EEEA013E327509E84630166331DB1A0E93D4F697B7CD20D37D39BD140672 +IV=2A2DC9F5CB47C94D430ECAAAB1D0811E +PT=86D2FC43F1F52B3916E8CF0D5E60D0DA +CT=BC318E32957CE6577CD06E2D3166CD1F + +I=61 +KEY=1C4909D11840D978FD7232D0FBC0E6A3A63F1DE663EB519A5C0313148C72CB6D +IV=BC318E32957CE6577CD06E2D3166CD1F +PT=916BE73B197EEB0DF49A74E0EDA3D778 +CT=E9858DBB1B5145ABB598ADE882346DDB + +I=62 +KEY=DD2ED3C6FCE0034F19259D57A35B60CF4FBA905D78BA1431E99BBEFC0E46A6B6 +IV=E9858DBB1B5145ABB598ADE882346DDB +PT=C167DA17E4A0DA37E457AF87589B866C +CT=1E04B15BBF727BEAC33C0C26141636DD + +I=63 +KEY=81C434CDF7EABAA49252EC86DFE15FBA51BE2106C7C86FDB2AA7B2DA1A50906B +IV=1E04B15BBF727BEAC33C0C26141636DD +PT=5CEAE70B0B0AB9EB8B7771D17CBA3F75 +CT=EB21AED731D594017F5729262A1E23B4 + +I=64 +KEY=AEF6BF8323CAE4C2270CC5E51B0A3BFFBA9F8FD1F61DFBDA55F09BFC304EB3DF +IV=EB21AED731D594017F5729262A1E23B4 +PT=2F328B4ED4205E66B55E2963C4EB6445 +CT=EB73CFADA0ACB98B37091CB81489CC7C + +I=65 +KEY=BC3BD548867FA82FF80EF67B38016A1E51EC407C56B1425162F9874424C77FA3 +IV=EB73CFADA0ACB98B37091CB81489CC7C +PT=12CD6ACBA5B54CEDDF02339E230B51E1 +CT=1FEEF226D6759E8813B98A5D43B2F22A + +I=66 +KEY=E1F5760C694DBE5688A0241B5517B4B14E02B25A80C4DCD971400D1967758D89 +IV=1FEEF226D6759E8813B98A5D43B2F22A +PT=5DCEA344EF32167970AED2606D16DEAF +CT=9C591D087F0F45C8AE3DEC9C455FE200 + +I=67 +KEY=ABF2D79C472D0159FA9AE646D0C0FC9CD25BAF52FFCB9911DF7DE185222A6F89 +IV=9C591D087F0F45C8AE3DEC9C455FE200 +PT=4A07A1902E60BF0F723AC25D85D7482D +CT=62C4F4D7E4AC5ABC03BECA3CA56DA4FD + +I=68 +KEY=E58A351A4DD79A2ED6D386E11A8563F2B09F5B851B67C3ADDCC32BB98747CB74 +IV=62C4F4D7E4AC5ABC03BECA3CA56DA4FD +PT=4E78E2860AFA9B772C4960A7CA459F6E +CT=AD8557C0D04675CC312C7A106D5C8B83 + +I=69 +KEY=BCF7BB1010AF5CEB05E06339689067E31D1A0C45CB21B661EDEF51A9EA1B40F7 +IV=AD8557C0D04675CC312C7A106D5C8B83 +PT=597D8E0A5D78C6C5D333E5D872150411 +CT=80159F4F5E0C2DC07D3CD3C52A1A8E6D + +I=70 +KEY=328BB8EB86055D2BB52A02E40BB5D2C39D0F930A952D9BA190D3826CC001CE9A +IV=80159F4F5E0C2DC07D3CD3C52A1A8E6D +PT=8E7C03FB96AA01C0B0CA61DD6325B520 +CT=F58A2EE5A5BDE8CA0A96F4F4B64BE737 + +I=71 +KEY=F192AE51D926A2B68C38EA4E48A0590F6885BDEF3090736B9A457698764A29AD +IV=F58A2EE5A5BDE8CA0A96F4F4B64BE737 +PT=C31916BA5F23FF9D3912E8AA43158BCC +CT=B4C0DD55013AEFE12D94F31B861134CC + +I=72 +KEY=5EE48E38C2C805E2AACC89AD8682E552DC4560BA31AA9C8AB7D18583F05B1D61 +IV=B4C0DD55013AEFE12D94F31B861134CC +PT=AF7620691BEEA75426F463E3CE22BC5D +CT=FD8B06AEF9B3C25D11B950A6648276BB + +I=73 +KEY=F425B9BF4D114251736EE7FCDB430B6721CE6614C8195ED7A668D52594D96BDA +IV=FD8B06AEF9B3C25D11B950A6648276BB +PT=AAC137878FD947B3D9A26E515DC1EE35 +CT=31BE8DF4A8A749FBF11AB07D8479A10B + +I=74 +KEY=61A2D5337BCB827887F884AD98C67BEA1070EBE060BE172C5772655810A0CAD1 +IV=31BE8DF4A8A749FBF11AB07D8479A10B +PT=95876C8C36DAC029F49663514385708D +CT=E9A2EF0C882781788D50033B79FE181F + +I=75 +KEY=E930B2277AC4475FB0A94519F60DE552F9D204ECE8999654DA226663695ED2CE +IV=E9A2EF0C882781788D50033B79FE181F +PT=88926714010FC5273751C1B46ECB9EB8 +CT=17FFCD5A010709A2737570E038D63B27 + +I=76 +KEY=B944CE978DF68F8FBFF0A5EA62AAC299EE2DC9B6E99E9FF6A95716835188E9E9 +IV=17FFCD5A010709A2737570E038D63B27 +PT=50747CB0F732C8D00F59E0F394A727CB +CT=E12B89FA1B1DD3B29F02219FD3D7D3D2 + +I=77 +KEY=0E2D7FCEB557462267BED2CCA8B48CD70F06404CF2834C443655371C825F3A3B +IV=E12B89FA1B1DD3B29F02219FD3D7D3D2 +PT=B769B15938A1C9ADD84E7726CA1E4E4E +CT=75AE99B6022B08E36FB88A6F4D7698BF + +I=78 +KEY=8046D73D60912221694B2AFE703EDB167AA8D9FAF0A844A759EDBD73CF29A284 +IV=75AE99B6022B08E36FB88A6F4D7698BF +PT=8E6BA8F3D5C664030EF5F832D88A57C1 +CT=CF32DCE11FDB098A6435315342796064 + +I=79 +KEY=20716D6975C32231968BF76725144CBAB59A051BEF734D2D3DD88C208D50C2E0 +IV=CF32DCE11FDB098A6435315342796064 +PT=A037BA5415520010FFC0DD99552A97AC +CT=80F12B261317C66F21AC811230848468 + +I=80 +KEY=AD5A2011E425AFFD57E7191336D37D25356B2E3DFC648B421C740D32BDD44688 +IV=80F12B261317C66F21AC811230848468 +PT=8D2B4D7891E68DCCC16CEE7413C7319F +CT=F2C6B70C19A5748C6D2B5DE41544854F + +I=81 +KEY=49D4228508C789105CF457D10FA56048C7AD9931E5C1FFCE715F50D6A890C3C7 +IV=F2C6B70C19A5748C6D2B5DE41544854F +PT=E48E0294ECE226ED0B134EC239761D6D +CT=A31FB3535978DAA555DD617FAB27A97A + +I=82 +KEY=67CE710A3E778CB4A37D1F2274D4462D64B22A62BCB9256B248231A903B76ABD +IV=A31FB3535978DAA555DD617FAB27A97A +PT=2E1A538F36B005A4FF8948F37B712665 +CT=97336ECFAE89015E0B5A7D1C154C71BF + +I=83 +KEY=A87C517EF43CACC6D41EEB661DD1142CF38144AD123024352FD84CB516FB1B02 +IV=97336ECFAE89015E0B5A7D1C154C71BF +PT=CFB22074CA4B20727763F44469055201 +CT=466CD227A6A9D5FC3C0579064530FCE0 + +I=84 +KEY=D73F926A5B5DD8F5B82DE8F77E0E0697B5ED968AB499F1C913DD35B353CBE7E2 +IV=466CD227A6A9D5FC3C0579064530FCE0 +PT=7F43C314AF6174336C33039163DF12BB +CT=4F444B4554E965A113DC0097AA8FAD7A + +I=85 +KEY=7A19BE1C42A13B85B754834E9808DF4BFAA9DDCFE070946800013524F9444A98 +IV=4F444B4554E965A113DC0097AA8FAD7A +PT=AD262C7619FCE3700F796BB9E606D9DC +CT=F7078ABE7617867274CBBEDA1082B987 + +I=86 +KEY=D256675EDBF987B5CA86C21DE177C6A00DAE57719667121A74CA8BFEE9C6F31F +IV=F7078ABE7617867274CBBEDA1082B987 +PT=A84FD9429958BC307DD24153797F19EB +CT=676ACAB66B04597F1A33FF462BD5E0EE + +I=87 +KEY=C025616AB6F89BB1B90AA0E8F63FF1CC6AC49DC7FD634B656EF974B8C21313F1 +IV=676ACAB66B04597F1A33FF462BD5E0EE +PT=127306346D011C04738C62F51748376C +CT=BF66B8DD1E540A4FED759FDB9A44B439 + +I=88 +KEY=2A437D44D93C25B3233FB168D63751A5D5A2251AE337412A838CEB635857A7C8 +IV=BF66B8DD1E540A4FED759FDB9A44B439 +PT=EA661C2E6FC4BE029A3511802008A069 +CT=EC8DBB5B3FE245180856B312D3052A87 + +I=89 +KEY=838278123F0261D1F287C9FF94CA4A55392F9E41DCD504328BDA58718B528D4F +IV=EC8DBB5B3FE245180856B312D3052A87 +PT=A9C10556E63E4462D1B8789742FD1BF0 +CT=02E1E60312BB371912C35E3EBC6EA755 + +I=90 +KEY=64F3A47C8C7CFA9FF2AC88637C598E6A3BCE7842CE6E332B9919064F373C2A1A +IV=02E1E60312BB371912C35E3EBC6EA755 +PT=E771DC6EB37E9B4E002B419CE893C43F +CT=73D7499EBB38716D71CCB737CFFFA3FB + +I=91 +KEY=585ABE6B779F22400FC2AC3B55B39E91481931DC75564246E8D5B178F8C389E1 +IV=73D7499EBB38716D71CCB737CFFFA3FB +PT=3CA91A17FBE3D8DFFD6E245829EA10FB +CT=CEE7721855B7381D369ECC1C9337BB02 + +I=92 +KEY=7BC1E883465CBBB9BA624FF99308259386FE43C420E17A5BDE4B7D646BF432E3 +IV=CEE7721855B7381D369ECC1C9337BB02 +PT=239B56E831C399F9B5A0E3C2C6BBBB02 +CT=B6F48D369383974D163E4F17FDFC59EF + +I=93 +KEY=70032AF50BB5E080D4AA7722CEDC7DA9300ACEF2B362ED16C875327396086B0C +IV=B6F48D369383974D163E4F17FDFC59EF +PT=0BC2C2764DE95B396EC838DB5DD4583A +CT=E8372DA404126C63190626D95583629D + +I=94 +KEY=5C61B59BDA2FF51D4F4F740578466EA9D83DE356B7708175D17314AAC38B0991 +IV=E8372DA404126C63190626D95583629D +PT=2C629F6ED19A159D9BE50327B69A1300 +CT=F717B53E51665D0854C895EA1D1D7E77 + +I=95 +KEY=59A35E82B9C8D8FF25CFC5BAD979A9052F2A5668E616DC7D85BB8140DE9677E6 +IV=F717B53E51665D0854C895EA1D1D7E77 +PT=05C2EB1963E72DE26A80B1BFA13FC7AC +CT=7D3EE90EEF7C16872F98296977AA9557 + +I=96 +KEY=5BC419836F7C4F57957E13E39B2181455214BF66096ACAFAAA23A829A93CE2B1 +IV=7D3EE90EEF7C16872F98296977AA9557 +PT=02674701D6B497A8B0B1D65942582840 +CT=6DCD0C4B5633078FDEA9AE24781CB212 + +I=97 +KEY=E6D2BB67584AA2FAAE1D0DAD8C9C60253FD9B32D5F59CD75748A060DD12050A3 +IV=6DCD0C4B5633078FDEA9AE24781CB212 +PT=BD16A2E43736EDAD3B631E4E17BDE160 +CT=6515251260A73AE868E992B6D49579C5 + +I=98 +KEY=57637851C3C08A2923EBD2FEA27472DC5ACC963F3FFEF79D1C6394BB05B52966 +IV=6515251260A73AE868E992B6D49579C5 +PT=B1B1C3369B8A28D38DF6DF532EE812F9 +CT=1A40C2C15F03867E81F951B545396BB4 + +I=99 +KEY=E08E94110F1E64554848AB1966299B7D408C54FE60FD71E39D9AC50E408C42D2 +IV=1A40C2C15F03867E81F951B545396BB4 +PT=B7EDEC40CCDEEE7C6BA379E7C45DE9A1 +CT=DD331F336D669EFD37106099EA51010D + +I=100 +KEY=17F2544156745EC108BF97DA806752C39DBF4BCD0D9BEF1EAA8AA597AADD43DF +IV=DD331F336D669EFD37106099EA51010D +PT=F77CC050596A3A9440F73CC3E64EC9BE +CT=0EF37EC0B6071874FF68926D98A0EEAB + +I=101 +KEY=C97ABFF115E20A6C72A6206DB63EC0FD934C350DBB9CF76A55E237FA327DAD74 +IV=0EF37EC0B6071874FF68926D98A0EEAB +PT=DE88EBB0439654AD7A19B7B73659923E +CT=DA1DAEB42178A7657A40BD72A06CEDDC + +I=102 +KEY=77AB469FBC999BB2922D460413E2012049519BB99AE4500F2FA28A88921140A8 +IV=DA1DAEB42178A7657A40BD72A06CEDDC +PT=BED1F96EA97B91DEE08B6669A5DCC1DD +CT=E78523134FC8EAA77CC85E0EEC60FCD3 + +I=103 +KEY=4F88FA6F4053B3A15094ED532C2F47DCAED4B8AAD52CBAA8536AD4867E71BC7B +IV=E78523134FC8EAA77CC85E0EEC60FCD3 +PT=3823BCF0FCCA2813C2B9AB573FCD46FC +CT=BC540D1838D7AD8E8B1C44B96684DD31 + +I=104 +KEY=D178E105443700CFEE007AB3BAA71E4C1280B5B2EDFB1726D876903F18F5614A +IV=BC540D1838D7AD8E8B1C44B96684DD31 +PT=9EF01B6A0464B36EBE9497E096885990 +CT=6C6B95A5D8F4E7F1A5864DDBFCDCEED8 + +I=105 +KEY=8F6A589BA0ED1A67FE426368A7E523047EEB2017350FF0D77DF0DDE4E4298F92 +IV=6C6B95A5D8F4E7F1A5864DDBFCDCEED8 +PT=5E12B99EE4DA1AA8104219DB1D423D48 +CT=B58C92AE19B332621E7A4E5512C88596 + +I=106 +KEY=147895B157BF16B87C32AAA17480A886CB67B2B92CBCC2B5638A93B1F6E10A04 +IV=B58C92AE19B332621E7A4E5512C88596 +PT=9B12CD2AF7520CDF8270C9C9D3658B82 +CT=4D1D90F007BB5099C382E69C9CD1F7E5 + +I=107 +KEY=4C8441FCEBBD595999864A6CC37F7EDB867A22492B07922CA008752D6A30FDE1 +IV=4D1D90F007BB5099C382E69C9CD1F7E5 +PT=58FCD44DBC024FE1E5B4E0CDB7FFD65D +CT=7F59920056EC32FA48F8A9CCCFFE437A + +I=108 +KEY=CD922EEA60F0F136A799C650F5D4B030F923B0497DEBA0D6E8F0DCE1A5CEBE9B +IV=7F59920056EC32FA48F8A9CCCFFE437A +PT=81166F168B4DA86F3E1F8C3C36ABCEEB +CT=A546F57E48A783694577D59F7FD01D9E + +I=109 +KEY=90DE3ECB26E68BDD3C4B7AB9B9CDE6195C654537354C23BFAD87097EDA1EA305 +IV=A546F57E48A783694577D59F7FD01D9E +PT=5D4C102146167AEB9BD2BCE94C195629 +CT=6342B8CB1E493F916585FF1BBFC42AB3 + +I=110 +KEY=ADF1869FEA15122394E1F6FF6B51E5DE3F27FDFC2B051C2EC802F66565DA89B6 +IV=6342B8CB1E493F916585FF1BBFC42AB3 +PT=3D2FB854CCF399FEA8AA8C46D29C03C7 +CT=052AEDF54016429320B04243E308ECFE + +I=111 +KEY=DF52D7982845CBAEB4E56592906B63943A0D10096B135EBDE8B2B42686D26548 +IV=052AEDF54016429320B04243E308ECFE +PT=72A35107C250D98D2004936DFB3A864A +CT=EE147A64DC2E31222A3A14B133769ACE + +I=112 +KEY=5D6B5899612FF15825029DEB0B37CB4ED4196A6DB73D6F9FC288A097B5A4FF86 +IV=EE147A64DC2E31222A3A14B133769ACE +PT=82398F01496A3AF691E7F8799B5CA8DA +CT=8330EF868E72D33172D7DEC7B440056C + +I=113 +KEY=FC23917C478894C9490A6585CCB8A716572985EB394FBCAEB05F7E5001E4FAEA +IV=8330EF868E72D33172D7DEC7B440056C +PT=A148C9E526A765916C08F86EC78F6C58 +CT=DC83E3727C4E9754A82BFCFFD924ACB3 + +I=114 +KEY=BCD556FA7AFA27F9675F45922924DFA68BAA669945012BFA187482AFD8C05659 +IV=DC83E3727C4E9754A82BFCFFD924ACB3 +PT=40F6C7863D72B3302E552017E59C78B0 +CT=C0B97D9320DC3E893953E1D93859D3E4 + +I=115 +KEY=A0F23A11C85F008CFEC20F76BD6751054B131B0A65DD157321276376E09985BD +IV=C0B97D9320DC3E893953E1D93859D3E4 +PT=1C276CEBB2A52775999D4AE494438EA3 +CT=8C28875C39211D01A084A59BA71D0C31 + +I=116 +KEY=2BB58C8FE9FE5BAEC5DB3F6A7EB98187C73B9C565CFC087281A3C6ED4784898C +IV=8C28875C39211D01A084A59BA71D0C31 +PT=8B47B69E21A15B223B19301CC3DED082 +CT=7865E390E8019259A117669082ED5CCC + +I=117 +KEY=6035A1AC1F0C1871EA06773DEA40B5C5BF5E7FC6B4FD9A2B20B4A07DC569D540 +IV=7865E390E8019259A117669082ED5CCC +PT=4B802D23F6F243DF2FDD485794F93442 +CT=DC7BA7C54217B8DEE966C0672DBE79CD + +I=118 +KEY=CCA70BB373BA65736D25078BB99980F66325D803F6EA22F5C9D2601AE8D7AC8D +IV=DC7BA7C54217B8DEE966C0672DBE79CD +PT=AC92AA1F6CB67D02872370B653D93533 +CT=CBB60FB6BE7240A2037CDA46DAAAC4E4 + +I=119 +KEY=E6D9E4347ABCE875CDFB026A9B1CE767A893D7B548986257CAAEBA5C327D6869 +IV=CBB60FB6BE7240A2037CDA46DAAAC4E4 +PT=2A7EEF8709068D06A0DE05E122856791 +CT=3B0863884DCFFDAAE439E3BCFC2E0491 + +I=120 +KEY=90C0678C9B9796FACBD3A9E8E40A46E6939BB43D05579FFD2E9759E0CE536CF8 +IV=3B0863884DCFFDAAE439E3BCFC2E0491 +PT=761983B8E12B7E8F0628AB827F16A181 +CT=1407CDBD04CA6450D15A276B0E45D500 + +I=121 +KEY=A3505D86BF4B95AEC0F720B4CBDF4985879C7980019DFBADFFCD7E8BC016B9F8 +IV=1407CDBD04CA6450D15A276B0E45D500 +PT=33903A0A24DC03540B24895C2FD50F63 +CT=94B64DF8376EAF94F24EB0457DF81418 + +I=122 +KEY=EAD741BA44D8637A4D49A089E4A122F2132A347836F354390D83CECEBDEEADE0 +IV=94B64DF8376EAF94F24EB0457DF81418 +PT=49871C3CFB93F6D48DBE803D2F7E6B77 +CT=6E2DE304D4A21A218291FD9B59FED9BF + +I=123 +KEY=278551B22B73239BF36E61370FFF43EA7D07D77CE2514E188F123355E410745F +IV=6E2DE304D4A21A218291FD9B59FED9BF +PT=CD5210086FAB40E1BE27C1BEEB5E6118 +CT=72A1E7B22D6B8B8C38C4CCD545466879 + +I=124 +KEY=C7046CA82928EA5AE1E6998399A090BB0FA630CECF3AC594B7D6FF80A1561C26 +IV=72A1E7B22D6B8B8C38C4CCD545466879 +PT=E0813D1A025BC9C11288F8B4965FD351 +CT=F5F1B011C644D119625733433C3DBB40 + +I=125 +KEY=82AF7079A309A3B1367E4DC8EE90B8C5FA5780DF097E148DD581CCC39D6BA766 +IV=F5F1B011C644D119625733433C3DBB40 +PT=45AB1CD18A2149EBD798D44B7730287E +CT=FDD90319FC2878AE4E23CE63C6660D1A + +I=126 +KEY=EB439411E1412BA8D6DB9F3052753D3F078E83C6F5566C239BA202A05B0DAA7C +IV=FDD90319FC2878AE4E23CE63C6660D1A +PT=69ECE46842488819E0A5D2F8BCE585FA +CT=0B3948AEFD674622289CB41E3F668A5C + +I=127 +KEY=C2FDF3EB8C01693C7FB990CE6D7F56E10CB7CB6808312A01B33EB6BE646B2020 +IV=0B3948AEFD674622289CB41E3F668A5C +PT=29BE67FA6D404294A9620FFE3F0A6BDE +CT=9F5BF60EB5CCF9D9F3A20DA569209636 + +I=128 +KEY=ECF0B5C32A3163495086894AB263166D93EC3D66BDFDD3D8409CBB1B0D4BB616 +IV=9F5BF60EB5CCF9D9F3A20DA569209636 +PT=2E0D4628A6300A752F3F1984DF1C408C +CT=3FED40A5796B3D1FF8805E5EF8922511 + +I=129 +KEY=259CAA194EE9BE90B2B1E7654CBDCD03AC017DC3C496EEC7B81CE545F5D99307 +IV=3FED40A5796B3D1FF8805E5EF8922511 +PT=C96C1FDA64D8DDD9E2376E2FFEDEDB6E +CT=2973A39E09EF5F4F42B29E6730ECC127 + +I=130 +KEY=FAAB18CE5FA7895BAA9EC69A55F690208572DE5DCD79B188FAAE7B22C5355220 +IV=2973A39E09EF5F4F42B29E6730ECC127 +PT=DF37B2D7114E37CB182F21FF194B5D23 +CT=F8C4C1A86B0665E2124CFFA9128FFEFD + +I=131 +KEY=3806BAB3764E794DF526A17BCE0112877DB61FF5A67FD46AE8E2848BD7BAACDD +IV=F8C4C1A86B0665E2124CFFA9128FFEFD +PT=C2ADA27D29E9F0165FB867E19BF782A7 +CT=90996F6629A41FC86A9520DD33AE5B3F + +I=132 +KEY=B7F781357E024140C3797D01C286E72BED2F70938FDBCBA28277A456E414F7E2 +IV=90996F6629A41FC86A9520DD33AE5B3F +PT=8FF13B86084C380D365FDC7A0C87F5AC +CT=9DAFB2F259BFD18945A0A6EFF9A81A75 + +I=133 +KEY=B67D37A8E281AFD015C38A72F5662BEE7080C261D6641A2BC7D702B91DBCED97 +IV=9DAFB2F259BFD18945A0A6EFF9A81A75 +PT=018AB69D9C83EE90D6BAF77337E0CCC5 +CT=C89F523289AE2A7C8F796C2252CB0597 + +I=134 +KEY=A47B97F34FB4A8F219ED7A59EFE40080B81F90535FCA305748AE6E9B4F77E800 +IV=C89F523289AE2A7C8F796C2252CB0597 +PT=1206A05BAD3507220C2EF02B1A822B6E +CT=3AACC4E5DE152BB1730C6D10C9A81A0A + +I=135 +KEY=E8EBBFDA61B6BC6735953F8E448B5E0282B354B681DF1BE63BA2038B86DFF20A +IV=3AACC4E5DE152BB1730C6D10C9A81A0A +PT=4C9028292E0214952C7845D7AB6F5E82 +CT=1E315BFFFDC3DA42438E683263B496DD + +I=136 +KEY=EE950FF3D603DECEE18F4ACF99A623589C820F497C1CC1A4782C6BB9E56B64D7 +IV=1E315BFFFDC3DA42438E683263B496DD +PT=067EB029B7B562A9D41A7541DD2D7D5A +CT=9B021A44CD9FF920DFE1EC97B3EE8AE4 + +I=137 +KEY=E073E1149A4A605E041167F3739F17240780150DB1833884A7CD872E5685EE33 +IV=9B021A44CD9FF920DFE1EC97B3EE8AE4 +PT=0EE6EEE74C49BE90E59E2D3CEA39347C +CT=4F62EE03D7A8337ECB3DCC0EA5444C2D + +I=138 +KEY=BF449E4B7DFA404D3F18C0266725F67248E2FB0E662B0BFA6CF04B20F3C1A21E +IV=4F62EE03D7A8337ECB3DCC0EA5444C2D +PT=5F377F5FE7B020133B09A7D514BAE156 +CT=AC8767B1E15D6D1ECACCCBF2D0FAB043 + +I=139 +KEY=3AB2898399D0F8467B37A5C916D9117AE4659CBF877666E4A63C80D2233B125D +IV=AC8767B1E15D6D1ECACCCBF2D0FAB043 +PT=85F617C8E42AB80B442F65EF71FCE708 +CT=9CA6E27F1966AE133CB7B98C2B13C1DA + +I=140 +KEY=06A09B6D5A6BCA82B26D0625F2A89FA178C37EC09E10C8F79A8B395E0828D387 +IV=9CA6E27F1966AE133CB7B98C2B13C1DA +PT=3C1212EEC3BB32C4C95AA3ECE4718EDB +CT=B7A6788E6D9886047D1450B093F5B6FE + +I=141 +KEY=79A26263675E11BE581DDEA79A20CAACCF65064EF3884EF3E79F69EE9BDD6579 +IV=B7A6788E6D9886047D1450B093F5B6FE +PT=7F02F90E3D35DB3CEA70D8826888550D +CT=5C1785DC27BC301DEAFAEF325A4CCBFD + +I=142 +KEY=21DEF781026D9ACB4108C6F9847C635F93728392D4347EEE0D6586DCC191AE84 +IV=5C1785DC27BC301DEAFAEF325A4CCBFD +PT=587C95E265338B751915185E1E5CA9F3 +CT=9577E8F6DF5921C4B518974A2F1FCF07 + +I=143 +KEY=EB000BAA170733EA4D077BDD7DA1623506056B640B6D5F2AB87D1196EE8E6183 +IV=9577E8F6DF5921C4B518974A2F1FCF07 +PT=CADEFC2B156AA9210C0FBD24F9DD016A +CT=09F8E3DA7C5E39F2F13C2B72001D1D56 + +I=144 +KEY=D56A1025AB5F7B5F943B3AECAF87A2800FFD88BE773366D849413AE4EE937CD5 +IV=09F8E3DA7C5E39F2F13C2B72001D1D56 +PT=3E6A1B8FBC5848B5D93C4131D226C0B5 +CT=7344F33968E177F3864908F02915739A + +I=145 +KEY=876077EA9BDB2134098B73CAD4411D997CB97B871FD2112BCF083214C7860F4F +IV=7344F33968E177F3864908F02915739A +PT=520A67CF30845A6B9DB049267BC6BF19 +CT=EC286360EF2A54CE894ED06ACF39970C + +I=146 +KEY=AA9943761AD545F47EBCF5CD4584C3B3909118E7F0F845E54646E27E08BF9843 +IV=EC286360EF2A54CE894ED06ACF39970C +PT=2DF9349C810E64C07737860791C5DE2A +CT=89F4BE70D36A05C84FD2124F6A69786B + +I=147 +KEY=5C285D3FD07EF5F6664B1F4C4CA771E31965A6972392402D0994F03162D6E028 +IV=89F4BE70D36A05C84FD2124F6A69786B +PT=F6B11E49CAABB00218F7EA810923B250 +CT=9A65E99C06E0744056365C4A26CD001F + +I=148 +KEY=F28851656D77922A55655DBE4610993683004F0B2572346D5FA2AC7B441BE037 +IV=9A65E99C06E0744056365C4A26CD001F +PT=AEA00C5ABD0967DC332E42F20AB7E8D5 +CT=566ECB7B317C81CF87BC483B4B6CF417 + +I=149 +KEY=62428DD3F6B04C564CA6D9DA9A9A64B3D56E8470140EB5A2D81EE4400F771420 +IV=566ECB7B317C81CF87BC483B4B6CF417 +PT=90CADCB69BC7DE7C19C38464DC8AFD85 +CT=16E3F727D2D4CC2E88C2A4B0DFEF34AF + +I=150 +KEY=78A68A0EC33E2C0198538C1EA591AF46C38D7357C6DA798C50DC40F0D098208F +IV=16E3F727D2D4CC2E88C2A4B0DFEF34AF +PT=1AE407DD358E6057D4F555C43F0BCBF5 +CT=6F6606018F5491FC43864FC29B572551 + +I=151 +KEY=4EFBCF71F7A0DA7564DAF1F0488AA933ACEB7556498EE870135A0F324BCF05DE +IV=6F6606018F5491FC43864FC29B572551 +PT=365D457F349EF674FC897DEEED1B0675 +CT=BC07194E716B4D78F64E14B6E5762439 + +I=152 +KEY=A4BBF15395604071DF929A4922A129DD10EC6C1838E5A508E5141B84AEB921E7 +IV=BC07194E716B4D78F64E14B6E5762439 +PT=EA403E2262C09A04BB486BB96A2B80EE +CT=BF1994171481FB4F84AB092F437EA9C7 + +I=153 +KEY=665F10926596E8F5691ACE10AA5075AEAFF5F80F2C645E4761BF12ABEDC78820 +IV=BF1994171481FB4F84AB092F437EA9C7 +PT=C2E4E1C1F0F6A884B688545988F15C73 +CT=254FE05D25B67D3BF6C2688F46A7FAD8 + +I=154 +KEY=15F4BA29EBAAF160AC95507FDA03D7D58ABA185209D2237C977D7A24AB6072F8 +IV=254FE05D25B67D3BF6C2688F46A7FAD8 +PT=73ABAABB8E3C1995C58F9E6F7053A27B +CT=A03B8DB2C1C9B6C574A8499C6E5869CF + +I=155 +KEY=96A760AB52E1D6A5ACFCA016E98D0BA12A8195E0C81B95B9E3D533B8C5381B37 +IV=A03B8DB2C1C9B6C574A8499C6E5869CF +PT=8353DA82B94B27C50069F069338EDC74 +CT=088F141F097F659145DE8E1EDB2300B5 + +I=156 +KEY=7C06F9EE0327C811CEE3CC3B2B492620220E81FFC164F028A60BBDA61E1B1B82 +IV=088F141F097F659145DE8E1EDB2300B5 +PT=EAA1994551C61EB4621F6C2DC2C42D81 +CT=43703327BFDAF109F6F9C5969D3C7649 + +I=157 +KEY=0F8AC1E3014DD99D1A440A693CB73B51617EB2D87EBE012150F2783083276DCB +IV=43703327BFDAF109F6F9C5969D3C7649 +PT=738C380D026A118CD4A7C65217FE1D71 +CT=BDAC873D0A674CDA98105DC3070F7BE4 + +I=158 +KEY=E595998ABEF32CABDD4A441B4042BF8BDCD235E574D94DFBC8E225F38428162F +IV=BDAC873D0A674CDA98105DC3070F7BE4 +PT=EA1F5869BFBEF536C70E4E727CF584DA +CT=A1A89122CF532FBC69E74A70F1E7346F + +I=159 +KEY=FBA3999F7BF540184E9BE7715CA8C0497D7AA4C7BB8A6247A1056F8375CF2240 +IV=A1A89122CF532FBC69E74A70F1E7346F +PT=1E360015C5066CB393D1A36A1CEA7FC2 +CT=68C2A6FF8EABE7EA05E5DD6093C00129 + +I=160 +KEY=65AF7CB5F5CEF75FEF0BF5F746D7DD7D15B80238352185ADA4E0B2E3E60F2369 +IV=68C2A6FF8EABE7EA05E5DD6093C00129 +PT=9E0CE52A8E3BB747A19012861A7F1D34 +CT=1EA92E63C6926082B04F69E658CFA478 + +I=161 +KEY=7D3BA807729873EB2021AC1817B2C7D30B112C5BF3B3E52F14AFDB05BEC08711 +IV=1EA92E63C6926082B04F69E658CFA478 +PT=1894D4B2875684B4CF2A59EF51651AAE +CT=45A943F0B6430ABA20C562469AE98A6D + +I=162 +KEY=5ECAEF5BF4EC899C7BFAEE2F50B864924EB86FAB45F0EF95346AB94324290D7C +IV=45A943F0B6430ABA20C562469AE98A6D +PT=23F1475C8674FA775BDB4237470AA341 +CT=6CDF579A8429606CC9BC56D010845954 + +I=163 +KEY=8D394BD1C8C1D1F8A67A3BA16530662A22673831C1D98FF9FDD6EF9334AD5428 +IV=6CDF579A8429606CC9BC56D010845954 +PT=D3F3A48A3C2D5864DD80D58E358802B8 +CT=96E9E19694DB9931AC09A7B6296FEAA8 + +I=164 +KEY=9ABEC4725C717368463710CB2D45774DB48ED9A7550216C851DF48251DC2BE80 +IV=96E9E19694DB9931AC09A7B6296FEAA8 +PT=17878FA394B0A290E04D2B6A48751167 +CT=176C9B9B32A539F35BDFB21B38C42134 + +I=165 +KEY=3CA1E23510949D81242F16DE0E9B2B3AA3E2423C67A72F3B0A00FA3E25069FB4 +IV=176C9B9B32A539F35BDFB21B38C42134 +PT=A61F26474CE5EEE96218061523DE5C77 +CT=06004480169FB7B6D4DBA7453A85E54D + +I=166 +KEY=2A72AA0C7EAA3113480EF57A83C272D7A5E206BC7138988DDEDB5D7B1F837AF9 +IV=06004480169FB7B6D4DBA7453A85E54D +PT=16D348396E3EAC926C21E3A48D5959ED +CT=FF2F4F6E32133CE8C70252937FE5BDA6 + +I=167 +KEY=90C0C8FC5B65BE92E643956293A70AF35ACD49D2432BA46519D90FE86066C75F +IV=FF2F4F6E32133CE8C70252937FE5BDA6 +PT=BAB262F025CF8F81AE4D601810657824 +CT=0972CCC79C412DB6FBC5918B8E6EAB7C + +I=168 +KEY=E0AF49BAC4BD146E83C884327FFB682353BF8515DF6A89D3E21C9E63EE086C23 +IV=0972CCC79C412DB6FBC5918B8E6EAB7C +PT=706F81469FD8AAFC658B1150EC5C62D0 +CT=2D8C668310308FCF7B3E325F50AA89E5 + +I=169 +KEY=E5C29451893B7B94249E89469E58DEAD7E33E396CF5A061C9922AC3CBEA2E5C6 +IV=2D8C668310308FCF7B3E325F50AA89E5 +PT=056DDDEB4D866FFAA7560D74E1A3B68E +CT=8342DD95F1040E763C82E36F8F74822F + +I=170 +KEY=4A9AD7CAFA46AE63362069120B502D33FD713E033E5E086AA5A04F5331D667E9 +IV=8342DD95F1040E763C82E36F8F74822F +PT=AF58439B737DD5F712BEE0549508F39E +CT=8CA83627884D9B7A62F096BD37C14EFF + +I=171 +KEY=21AEFC00E7CC2942F319630702ECCC6B71D90824B6139310C750D9EE06172916 +IV=8CA83627884D9B7A62F096BD37C14EFF +PT=6B342BCA1D8A8721C5390A1509BCE158 +CT=13073AB95C0C0587372564189A4C176F + +I=172 +KEY=7E615F002723795F6E37182ECC0C429E62DE329DEA1F9697F075BDF69C5B3E79 +IV=13073AB95C0C0587372564189A4C176F +PT=5FCFA300C0EF501D9D2E7B29CEE08EF5 +CT=247A01C6A7072F64CB463E6580DA222E + +I=173 +KEY=C2A25232803E901B35080B5CA64DEC2646A4335B4D18B9F33B3383931C811C57 +IV=247A01C6A7072F64CB463E6580DA222E +PT=BCC30D32A71DE9445B3F13726A41AEB8 +CT=562355D078402DA76B0CCAAC2BE63DAE + +I=174 +KEY=46C06B83AD1C5CD849C53A11C05137141087668B35589454503F493F376721F9 +IV=562355D078402DA76B0CCAAC2BE63DAE +PT=846239B12D22CCC37CCD314D661CDB32 +CT=841B1644CCE1BF9DB0D537733047DB7F + +I=175 +KEY=CB3AD5FB9E07D380841D712E7A71FC15949C70CFF9B92BC9E0EA7E4C0720FA86 +IV=841B1644CCE1BF9DB0D537733047DB7F +PT=8DFABE78331B8F58CDD84B3FBA20CB01 +CT=DE34C065627DB86A2D0AE89FB31BDA86 + +I=176 +KEY=240CFC15D60F6AE4A53D2C25BD71DD6E4AA8B0AA9BC493A3CDE096D3B43B2000 +IV=DE34C065627DB86A2D0AE89FB31BDA86 +PT=EF3629EE4808B96421205D0BC700217B +CT=38DD744B95756614261178685FBF097F + +I=177 +KEY=FAA7CBA4AAAD9576591C12233960F1C87275C4E10EB1F5B7EBF1EEBBEB84297F +IV=38DD744B95756614261178685FBF097F +PT=DEAB37B17CA2FF92FC213E0684112CA6 +CT=DC1CF4E4633355111AD09BE1C6BC1E39 + +I=178 +KEY=29E0D33A81FFDCE220D1587C36C5EB09AE6930056D82A0A6F121755A2D383746 +IV=DC1CF4E4633355111AD09BE1C6BC1E39 +PT=D347189E2B52499479CD4A5F0FA51AC1 +CT=2A5DC4E8C16753D202B638E5003AF83D + +I=179 +KEY=956C5751C5B439990A006DB1B52336E78434F4EDACE5F374F3974DBF2D02CF7B +IV=2A5DC4E8C16753D202B638E5003AF83D +PT=BC8C846B444BE57B2AD135CD83E6DDEE +CT=70F5676DC7646EA8F8A913AE6AD21949 + +I=180 +KEY=8AD9D44BC9018FD05B103360575592FEF4C193806B819DDC0B3E5E1147D0D632 +IV=70F5676DC7646EA8F8A913AE6AD21949 +PT=1FB5831A0CB5B64951105ED1E276A419 +CT=C44DA6A603A1E9C02F18123D5CAD5291 + +I=181 +KEY=DA77F2DA5CD7148B15FE8CA898C9A25E308C35266820741C24264C2C1B7D84A3 +IV=C44DA6A603A1E9C02F18123D5CAD5291 +PT=50AE269195D69B5B4EEEBFC8CF9C30A0 +CT=53C2D89EC4D5867DC79168D21C9B8755 + +I=182 +KEY=4A4FD6AED6825A2A0C2114460F029EDA634EEDB8ACF5F261E3B724FE07E603F6 +IV=53C2D89EC4D5867DC79168D21C9B8755 +PT=903824748A554EA119DF98EE97CB3C84 +CT=79B9DABE5171A614CAFDEA11637A1800 + +I=183 +KEY=29102930967275801BD019D6766FDA1A1AF73706FD845475294ACEEF649C1BF6 +IV=79B9DABE5171A614CAFDEA11637A1800 +PT=635FFF9E40F02FAA17F10D90796D44C0 +CT=8AB92FA5EA50F1185112FE4D8D2FCC21 + +I=184 +KEY=F4ABA34B232C18EAD6D367320651C374904E18A317D4A56D785830A2E9B3D7D7 +IV=8AB92FA5EA50F1185112FE4D8D2FCC21 +PT=DDBB8A7BB55E6D6ACD037EE4703E196E +CT=FB97C84040732D7B308C5959059D90A9 + +I=185 +KEY=FB140F98A79F5D5D68B80301CB7B640E6BD9D0E357A7881648D469FBEC2E477E +IV=FB97C84040732D7B308C5959059D90A9 +PT=0FBFACD384B345B7BE6B6433CD2AA77A +CT=D0D0119D500519BF5B4770C494B41680 + +I=186 +KEY=BC98221C0792D22B6EB258E57DB0D8B0BB09C17E07A291A91393193F789A51FE +IV=D0D0119D500519BF5B4770C494B41680 +PT=478C2D84A00D8F76060A5BE4B6CBBCBE +CT=94842399FC93828D30979DAD9210B827 + +I=187 +KEY=C92F345AC3CB803EA91C123F97E7005A2F8DE2E7FB31132423048492EA8AE9D9 +IV=94842399FC93828D30979DAD9210B827 +PT=75B71646C4595215C7AE4ADAEA57D8EA +CT=5BDB886E7A7DBBA8679704F13F44B981 + +I=188 +KEY=3EACAF51FEA9A9886D0B9D1B6BA8436574566A89814CA88C44938063D5CE5058 +IV=5BDB886E7A7DBBA8679704F13F44B981 +PT=F7839B0B3D6229B6C4178F24FC4F433F +CT=A2DA893257EE0F732A80FC52887A0788 + +I=189 +KEY=72E26FEDC250C5FED59FE29C966B61FAD68CE3BBD6A2A7FF6E137C315DB457D0 +IV=A2DA893257EE0F732A80FC52887A0788 +PT=4C4EC0BC3CF96C76B8947F87FDC3229F +CT=2F7877481B1162B01616C9F3268B4C44 + +I=190 +KEY=901C1268AD3582E6A9FA4C5CBB99D07EF9F494F3CDB3C54F7805B5C27B3F1B94 +IV=2F7877481B1162B01616C9F3268B4C44 +PT=E2FE7D856F6547187C65AEC02DF2B184 +CT=9FFA4AF8D0F096CC40A9F879076211E0 + +I=191 +KEY=EAF814EC49F2254E4933FAF977D7BEEC660EDE0B1D43538338AC4DBB7C5D0A74 +IV=9FFA4AF8D0F096CC40A9F879076211E0 +PT=7AE40684E4C7A7A8E0C9B6A5CC4E6E92 +CT=886097F5BC20C157A605CBEFCA5663D7 + +I=192 +KEY=8ED70BBA192093A0C9AD62E86C27091FEE6E49FEA16392D49EA98654B60B69A3 +IV=886097F5BC20C157A605CBEFCA5663D7 +PT=642F1F5650D2B6EE809E98111BF0B7F3 +CT=00DBBB84F52B3C9B28325161072753B6 + +I=193 +KEY=18280464C9E683CFFF9B75A5FD74EE96EEB5F27A5448AE4FB69BD735B12C3A15 +IV=00DBBB84F52B3C9B28325161072753B6 +PT=96FF0FDED0C6106F3636174D9153E789 +CT=714A27832B326F0A8FA745012DE4D936 + +I=194 +KEY=F464EE1298B09059016082CCC5ABC0129FFFD5F97F7AC145393C92349CC8E323 +IV=714A27832B326F0A8FA745012DE4D936 +PT=EC4CEA7651561396FEFBF76938DF2E84 +CT=5DE8A5CDBA7A6111A646AA17CA5324D4 + +I=195 +KEY=EE7301D63C482593ABB33CF4A57F1101C2177034C500A0549F7A3823569BC7F7 +IV=5DE8A5CDBA7A6111A646AA17CA5324D4 +PT=1A17EFC4A4F8B5CAAAD3BE3860D4D113 +CT=EA197ECF36E63616EBB0D9D7C1BD9A22 + +I=196 +KEY=10528506D50D143EAC40D83731DD55F0280E0EFBF3E6964274CAE1F497265DD5 +IV=EA197ECF36E63616EBB0D9D7C1BD9A22 +PT=FE2184D0E94531AD07F3E4C394A244F1 +CT=798349D56EC37993B0E131F8E3F64860 + +I=197 +KEY=438E1B672254504B972927644802ED36518D472E9D25EFD1C42BD00C74D015B5 +IV=798349D56EC37993B0E131F8E3F64860 +PT=53DC9E61F75944753B69FF5379DFB8C6 +CT=545E4CD72E74F5A91B29DDBA60BCEB5A + +I=198 +KEY=7E32F16A4E2E125A95FF9963C6F9796105D30BF9B3511A78DF020DB6146CFEEF +IV=545E4CD72E74F5A91B29DDBA60BCEB5A +PT=3DBCEA0D6C7A421102D6BE078EFB9457 +CT=084142F2C892DCF8A37A509DF0D669BC + +I=199 +KEY=B1BEC1C124A0941D0BA6C75239C17E250D92490B7BC3C6807C785D2BE4BA9753 +IV=084142F2C892DCF8A37A509DF0D669BC +PT=CF8C30AB6A8E86479E595E31FF380744 +CT=0A96C326C9D642F1F84C8772BCF8EB4A + +I=200 +KEY=80D7A5A2AE29B42143046D45B6B6B36C07048A2DB21584718434DA5958427C19 +IV=0A96C326C9D642F1F84C8772BCF8EB4A +PT=316964638A89203C48A2AA178F77CD49 +CT=273916ED09A517CE5C6A294D82E78980 + +I=201 +KEY=4D1C892DF27868BBB0FE803145C1D731203D9CC0BBB093BFD85EF314DAA5F599 +IV=273916ED09A517CE5C6A294D82E78980 +PT=CDCB2C8F5C51DC9AF3FAED74F377645D +CT=7183A7C83964ECFB2A1E44FFCFEBB7C1 + +I=202 +KEY=8C9B28041ECD5149A51207ACE38F0D0351BE3B0882D47F44F240B7EB154E4258 +IV=7183A7C83964ECFB2A1E44FFCFEBB7C1 +PT=C187A129ECB539F215EC879DA64EDA32 +CT=6015DF395D795DECA0A2F833E3614000 + +I=203 +KEY=FF175C7C745BB06E51EEDAA4F2C61E0F31ABE431DFAD22A852E24FD8F62F0258 +IV=6015DF395D795DECA0A2F833E3614000 +PT=738C74786A96E127F4FCDD081149130C +CT=B6B466B56B0E994E672072C273BA067D + +I=204 +KEY=0C84C64E1BB3B86E9AF5A8405D950B3A871F8284B4A3BBE635C23D1A85950425 +IV=B6B466B56B0E994E672072C273BA067D +PT=F3939A326FE80800CB1B72E4AF531535 +CT=C8566E37DF2E2958DDD5D2DB49889BA8 + +I=205 +KEY=5FF4C2A08B85338172D2779BF789DA234F49ECB36B8D92BEE817EFC1CC1D9F8D +IV=C8566E37DF2E2958DDD5D2DB49889BA8 +PT=537004EE90368BEFE827DFDBAA1CD119 +CT=C4A8D14DB86637E94AF515764BC7DF44 + +I=206 +KEY=BD81DE1813AEC9BAFDDC90E4A563CB338BE13DFED3EBA557A2E2FAB787DA40C9 +IV=C4A8D14DB86637E94AF515764BC7DF44 +PT=E2751CB8982BFA3B8F0EE77F52EA1110 +CT=5707495E4CBA3727FBA5D7F4F61AF35C + +I=207 +KEY=AE1B09CB7D99BAC0A71B3E83815F10A2DCE674A09F51927059472D4371C0B395 +IV=5707495E4CBA3727FBA5D7F4F61AF35C +PT=139AD7D36E37737A5AC7AE67243CDB91 +CT=C770CD182DFF66E4D6A7BFEFE2820AE1 + +I=208 +KEY=4F7491F03447293C42DE8393E7AD91741B96B9B8B2AEF4948FE092AC9342B974 +IV=C770CD182DFF66E4D6A7BFEFE2820AE1 +PT=E16F983B49DE93FCE5C5BD1066F281D6 +CT=E2044134ACD21D5AD026671BDC0CB2E4 + +I=209 +KEY=A747EF80608CED4309800CA0B1C73081F992F88C1E7CE9CE5FC6F5B74F4E0B90 +IV=E2044134ACD21D5AD026671BDC0CB2E4 +PT=E8337E7054CBC47F4B5E8F33566AA1F5 +CT=303CF7780126AD06B5272A8350639C93 + +I=210 +KEY=E5EBF5E471F2CA9F38492F604438B9C0C9AE0FF41F5A44C8EAE1DF341F2D9703 +IV=303CF7780126AD06B5272A8350639C93 +PT=42AC1A64117E27DC31C923C0F5FF8941 +CT=DACCD42953603A1321CAD9C236454598 + +I=211 +KEY=B5E5C9211A5C43F2267B4A2411FC2CC21362DBDD4C3A7EDBCB2B06F62968D29B +IV=DACCD42953603A1321CAD9C236454598 +PT=500E3CC56BAE896D1E32654455C49502 +CT=F9AB4D1D8255E83B330031EBE2ECE5C6 + +I=212 +KEY=8D78453D63A2DD8D08BF5F250F2581CFEAC996C0CE6F96E0F82B371DCB84375D +IV=F9AB4D1D8255E83B330031EBE2ECE5C6 +PT=389D8C1C79FE9E7F2EC415011ED9AD0D +CT=0F28E2D4CC948D36E18F80184A594841 + +I=213 +KEY=2E921775036404FD9939EE83C9585481E5E1741402FB1BD619A4B70581DD7F1C +IV=0F28E2D4CC948D36E18F80184A594841 +PT=A3EA524860C6D9709186B1A6C67DD54E +CT=A4756EAB45BCF716A52038C729E420C6 + +I=214 +KEY=9F86FEF42701B1D779BD46BE515680FC41941ABF4747ECC0BC848FC2A8395FDA +IV=A4756EAB45BCF716A52038C729E420C6 +PT=B114E9812465B52AE084A83D980ED47D +CT=9834425E009006673E777E3552E83D20 + +I=215 +KEY=2212046FFD03BA552089FBF7B2F3EF32D9A058E147D7EAA782F3F1F7FAD162FA +IV=9834425E009006673E777E3552E83D20 +PT=BD94FA9BDA020B825934BD49E3A56FCE +CT=AEA572D530A3694EAFF6DFDE30B80D5A + +I=216 +KEY=F73BB21F916D8011751AFDDDCD130A6477052A34777483E92D052E29CA696FA0 +IV=AEA572D530A3694EAFF6DFDE30B80D5A +PT=D529B6706C6E3A445593062A7FE0E556 +CT=86394E06B621147758CAB012852035A6 + +I=217 +KEY=EE44A367A3CDDFED7DBD980BF731B4E5F13C6432C155979E75CF9E3B4F495A06 +IV=86394E06B621147758CAB012852035A6 +PT=197F117832A05FFC08A765D63A22BE81 +CT=3CBC18C1AC02C0A7595199E08F1F552B + +I=218 +KEY=1558BABB3DCD830F693E7950F736BCADCD807CF36D5757392C9E07DBC0560F2D +IV=3CBC18C1AC02C0A7595199E08F1F552B +PT=FB1C19DC9E005CE21483E15B00070848 +CT=5A9CFD8BFE10CF7FBD0F9A3FAF6C117B + +I=219 +KEY=D083F58141F5E5AF3D5479739D55780D971C81789347984691919DE46F3A1E56 +IV=5A9CFD8BFE10CF7FBD0F9A3FAF6C117B +PT=C5DB4F3A7C3866A0546A00236A63C4A0 +CT=61A437D4E2F1C3779F1EBE906C5D2C12 + +I=220 +KEY=C60824F2DDC67623D270974E9F87BD27F6B8B6AC71B65B310E8F237403673244 +IV=61A437D4E2F1C3779F1EBE906C5D2C12 +PT=168BD1739C33938CEF24EE3D02D2C52A +CT=FC675EE1B12B47410A20CFAC23FD20EE + +I=221 +KEY=F73A715AD84DB0A6F55AD584922001920ADFE84DC09D1C7004AFECD8209A12AA +IV=FC675EE1B12B47410A20CFAC23FD20EE +PT=313255A8058BC685272A42CA0DA7BCB5 +CT=82E3FB6189716D94C8E9D30E1ECCABC4 + +I=222 +KEY=6ABBDCE21E2ECECBCAA3473897A2E178883C132C49EC71E4CC463FD63E56B96E +IV=82E3FB6189716D94C8E9D30E1ECCABC4 +PT=9D81ADB8C6637E6D3FF992BC0582E0EA +CT=BD84DCE4994B505EED71596B454BDF85 + +I=223 +KEY=0D4F68CDB9B53B08E22DDDFE4FD5FCC035B8CFC8D0A721BA213766BD7B1D66EB +IV=BD84DCE4994B505EED71596B454BDF85 +PT=67F4B42FA79BF5C3288E9AC6D8771DB8 +CT=1B3AA490C6E874BA77CE55D71789616C + +I=224 +KEY=3D8E3121698DD7E9D1835EFF5FA02DB22E826B58164F550056F9336A6C940787 +IV=1B3AA490C6E874BA77CE55D71789616C +PT=30C159ECD038ECE133AE83011075D172 +CT=D6EE171B39B5E40535FBF5A7CB4C6953 + +I=225 +KEY=1A5B2249CA785F0DB58FF5B07CCCFCDEF86C7C432FFAB1056302C6CDA7D86ED4 +IV=D6EE171B39B5E40535FBF5A7CB4C6953 +PT=27D51368A3F588E4640CAB4F236CD16C +CT=8691BE10D13B4C08246938750EE33643 + +I=226 +KEY=48AD5DEF217F83DC5039ECD1191ABE3A7EFDC253FEC1FD0D476BFEB8A93B5897 +IV=8691BE10D13B4C08246938750EE33643 +PT=52F67FA6EB07DCD1E5B6196165D642E4 +CT=E40AD0EE818639E37349E1132B138D63 + +I=227 +KEY=FEB84B0B264A8A6FB8D4DE065DA68A479AF712BD7F47C4EE34221FAB8228D5F4 +IV=E40AD0EE818639E37349E1132B138D63 +PT=B61516E4073509B3E8ED32D744BC347D +CT=6E40A22767A39C978F279D40B447099D + +I=228 +KEY=2FE79FCC3C959901BAAEE8C55B71D01FF4B7B09A18E45879BB0582EB366FDC69 +IV=6E40A22767A39C978F279D40B447099D +PT=D15FD4C71ADF136E027A36C306D75A58 +CT=C2DE8C5200F6FCBF1A4D6178909DF110 + +I=229 +KEY=C3EB1424EFD0ACDF3670C4943CB2CF5936693CC81812A4C6A148E393A6F22D79 +IV=C2DE8C5200F6FCBF1A4D6178909DF110 +PT=EC0C8BE8D34535DE8CDE2C5167C31F46 +CT=104CBECB1134CAE09B2FE8C5CE2E0901 + +I=230 +KEY=DF9F70702DA816906F3907575DF4D3032625820309266E263A670B5668DC2478 +IV=104CBECB1134CAE09B2FE8C5CE2E0901 +PT=1C746454C278BA4F5949C3C361461C5A +CT=65287F66F01AC054B1051D700EDDBF2B + +I=231 +KEY=F6C4CE3006A43EFBE18C5FF305F32C37430DFD65F93CAE728B62162666019B53 +IV=65287F66F01AC054B1051D700EDDBF2B +PT=295BBE402B0C286B8EB558A45807FF34 +CT=4933D44FD414225CB1E6951240D28150 + +I=232 +KEY=3963CE7465D89FBE550649326262DB450A3E292A2D288C2E3A84833426D31A03 +IV=4933D44FD414225CB1E6951240D28150 +PT=CFA70044637CA145B48A16C16791F772 +CT=3733351F76DE0E07581F84600E38EFDD + +I=233 +KEY=42468662273D8CB3EFAB19DBC802888B3D0D1C355BF68229629B075428EBF5DE +IV=3733351F76DE0E07581F84600E38EFDD +PT=7B25481642E5130DBAAD50E9AA6053CE +CT=F16F22EB9CCD854591AE2FC28E1D4B59 + +I=234 +KEY=E2B3E5EA6573FC8ABE4E890FA4F5502DCC623EDEC73B076CF3352896A6F6BE87 +IV=F16F22EB9CCD854591AE2FC28E1D4B59 +PT=A0F56388424E703951E590D46CF7D8A6 +CT=1D607C6E9BAD454DD5DE785F2A78F990 + +I=235 +KEY=FDB55AF96E09AF677AA4737992E13C9ED10242B05C96422126EB50C98C8E4717 +IV=1D607C6E9BAD454DD5DE785F2A78F990 +PT=1F06BF130B7A53EDC4EAFA7636146CB3 +CT=7B16B6A8F88E05F6A9A036A67CB8A2B6 + +I=236 +KEY=E546D74518CF4AA64B399EA321C570CAAA14F418A41847D78F4B666FF036E5A1 +IV=7B16B6A8F88E05F6A9A036A67CB8A2B6 +PT=18F38DBC76C6E5C1319DEDDAB3244C54 +CT=63AD66FCF9D52195CD0339443F554311 + +I=237 +KEY=2F9B91A24BEF0E503DC576E4F8D32C16C9B992E45DCD664242485F2BCF63A6B0 +IV=63AD66FCF9D52195CD0339443F554311 +PT=CADD46E7532044F676FCE847D9165CDC +CT=6293FBB897D8F0C60171BEA3072CA512 + +I=238 +KEY=97B7DF112EFFE9279D5EDF932889D84BAB2A695CCA1596844339E188C84F03A2 +IV=6293FBB897D8F0C60171BEA3072CA512 +PT=B82C4EB36510E777A09BA977D05AF45D +CT=9555D7F244448C80E965CE6AB7EF0F7B + +I=239 +KEY=39F26B429FE4111DAA984F03112B339F3E7FBEAE8E511A04AA5C2FE27FA00CD9 +IV=9555D7F244448C80E965CE6AB7EF0F7B +PT=AE45B453B11BF83A37C6909039A2EBD4 +CT=FA242C9DB2984E9EFA8CD98AE7C29D6F + +I=240 +KEY=64C6D001CB3C8AFC24A72DA11D172727C45B92333CC9549A50D0F668986291B6 +IV=FA242C9DB2984E9EFA8CD98AE7C29D6F +PT=5D34BB4354D89BE18E3F62A20C3C14B8 +CT=2998B59B0441F068D7F3FCE7AEAA6FD9 + +I=241 +KEY=FE56E2EB2434CA49D46A684DBCE2426CEDC327A83888A4F287230A8F36C8FE6F +IV=2998B59B0441F068D7F3FCE7AEAA6FD9 +PT=9A9032EAEF0840B5F0CD45ECA1F5654B +CT=A3F77BBA27BA88F33D4330EB2CC0EFBA + +I=242 +KEY=0F9B3CAD0EDFA9C429F3A005C78FE9F84E345C121F322C01BA603A641A0811D5 +IV=A3F77BBA27BA88F33D4330EB2CC0EFBA +PT=F1CDDE462AEB638DFD99C8487B6DAB94 +CT=9C751C64BCB82229ABA5130353455CCB + +I=243 +KEY=1725A4C019FB909FB1DE2ACA00E9A33DD2414076A38A0E2811C52967494D4D1E +IV=9C751C64BCB82229ABA5130353455CCB +PT=18BE986D1724395B982D8ACFC7664AC5 +CT=540DE482B7170E925FA4B429F6BCD458 + +I=244 +KEY=E2A619367235AA4611A72FD4FAF68FB3864CA4F4149D00BA4E619D4EBFF19946 +IV=540DE482B7170E925FA4B429F6BCD458 +PT=F583BDF66BCE3AD9A079051EFA1F2C8E +CT=6AADE1E1A12F5C83AF434CAD95B29678 + +I=245 +KEY=8629FB2CC8C06A07EC910681499E917FECE14515B5B25C39E122D1E32A430F3E +IV=6AADE1E1A12F5C83AF434CAD95B29678 +PT=648FE21ABAF5C041FD362955B3681ECC +CT=11308758A1C2075FEAECD260867CA343 + +I=246 +KEY=5EDD76C395D2A0D3D547CFB394B439EAFDD1C24D14705B660BCE0383AC3FAC7D +IV=11308758A1C2075FEAECD260867CA343 +PT=D8F48DEF5D12CAD439D6C932DD2AA895 +CT=14C9A904A3909A8FF44D88E22F8626DF + +I=247 +KEY=AF3FA8D6034564D7151C3933C7986CFCE9186B49B7E0C1E9FF838B6183B98AA2 +IV=14C9A904A3909A8FF44D88E22F8626DF +PT=F1E2DE159697C404C05BF680532C5516 +CT=A042D7F391A37E5A3EDB3022400EC797 + +I=248 +KEY=8ACC720216DBDBDB4C213FE65E575A09495ABCBA2643BFB3C158BB43C3B74D35 +IV=A042D7F391A37E5A3EDB3022400EC797 +PT=25F3DAD4159EBF0C593D06D599CF36F5 +CT=439FEF326223A65F7A555C6231178190 + +I=249 +KEY=F2882A52603203A71895A5870CCF7EE40AC55388446019ECBB0DE721F2A0CCA5 +IV=439FEF326223A65F7A555C6231178190 +PT=7844585076E9D87C54B49A61529824ED +CT=6FE1286C19AA3BC802F1C6C7B58DB4C4 + +I=250 +KEY=57EFB10BFC21E28397A9D5E5A533D35B65247BE45DCA2224B9FC21E6472D7861 +IV=6FE1286C19AA3BC802F1C6C7B58DB4C4 +PT=A5679B599C13E1248F3C7062A9FCADBF +CT=C38D763981392FF038573CA341DD8EA1 + +I=251 +KEY=19328A5147BC2E7C5149DA257487D734A6A90DDDDCF30DD481AB1D4506F0F6C0 +IV=C38D763981392FF038573CA341DD8EA1 +PT=4EDD3B5ABB9DCCFFC6E00FC0D1B4046F +CT=5FD553A2848C683B138D50F2741B124D + +I=252 +KEY=ED66DE43FE0F966850EF6754E21B69A0F97C5E7F587F65EF92264DB772EBE48D +IV=5FD553A2848C683B138D50F2741B124D +PT=F4545412B9B3B81401A6BD71969CBE94 +CT=910CDCBE38068A51185A879FF2B45B9C + +I=253 +KEY=E53D9016DE7DF4E2377968864B6F69F8687082C16079EFBE8A7CCA28805FBF11 +IV=910CDCBE38068A51185A879FF2B45B9C +PT=085B4E552072628A67960FD2A9740058 +CT=E0A0E68A14893501D75BC42B8EFC6F96 + +I=254 +KEY=C88C4383E2D16541765E5DB85957C59188D0644B74F0DABF5D270E030EA3D087 +IV=E0A0E68A14893501D75BC42B8EFC6F96 +PT=2DB1D3953CAC91A34127353E1238AC69 +CT=A66DD21DA627347F962A0AB7DCA887ED + +I=255 +KEY=6F01CC5C22DE71C7C2D5B429AA756A392EBDB656D2D7EEC0CB0D04B4D20B576A +IV=A66DD21DA627347F962A0AB7DCA887ED +PT=A78D8FDFC00F1486B48BE991F322AFA8 +CT=87551BC7A6B6D9B76239CB8A31FF1993 + +I=256 +KEY=DAC405506CD3779FC2400B459B7C6B6EA9E8AD9174613777A934CF3EE3F44EF9 +IV=87551BC7A6B6D9B76239CB8A31FF1993 +PT=B5C5C90C4E0D06580095BF6C31090157 +CT=B909B206A041F33EB3AC7ED481DFBA21 + +I=257 +KEY=E482333E6FBAA8427A2E30D56069E0B810E11F97D420C4491A98B1EA622BF4D8 +IV=B909B206A041F33EB3AC7ED481DFBA21 +PT=3E46366E0369DFDDB86E3B90FB158BD6 +CT=DE5E71F446794D3402400C96FBFEB93F + +I=258 +KEY=176CAD69CD20690B95DA40B95C43AC54CEBF6E639259897D18D8BD7C99D54DE7 +IV=DE5E71F446794D3402400C96FBFEB93F +PT=F3EE9E57A29AC149EFF4706C3C2A4CEC +CT=175A7C580A99E985A2FD2F185D9BAADB + +I=259 +KEY=FA4DD79A64960C8264624CDF215B54A1D9E5123B98C060F8BA259264C44EE73C +IV=175A7C580A99E985A2FD2F185D9BAADB +PT=ED217AF3A9B66589F1B80C667D18F8F5 +CT=413EB5D166C1D196F0239FF34D184013 + +I=260 +KEY=49855C1008EAF59432518A9F3807A0B398DBA7EAFE01B16E4A060D978956A72F +IV=413EB5D166C1D196F0239FF34D184013 +PT=B3C88B8A6C7CF9165633C640195CF412 +CT=69A3A63C580336296FF826600C754747 + +I=261 +KEY=849D231AE9F90F233F328BE6EE0AC180F17801D6A602874725FE2BF78523E068 +IV=69A3A63C580336296FF826600C754747 +PT=CD187F0AE113FAB70D630179D60D6133 +CT=B9AF0CA2B502C2DEB66834BD729AA528 + +I=262 +KEY=40E3F7EA3E7CFBDBF57935DBB124CF7F48D70D741300459993961F4AF7B94540 +IV=B9AF0CA2B502C2DEB66834BD729AA528 +PT=C47ED4F0D785F4F8CA4BBE3D5F2E0EFF +CT=99E16968796AB521FC460A8DF6744FA8 + +I=263 +KEY=4FDF8D16B85E527490FBE95EA34138D6D136641C6A6AF0B86FD015C701CD0AE8 +IV=99E16968796AB521FC460A8DF6744FA8 +PT=0F3C7AFC8622A9AF6582DC851265F7A9 +CT=7B871B0153657949D1FE7259E16791B7 + +I=264 +KEY=6AD7099EA6DC50F5CC836C3EB934CF92AAB17F1D390F89F1BE2E679EE0AA9B5F +IV=7B871B0153657949D1FE7259E16791B7 +PT=250884881E8202815C7885601A75F744 +CT=8D6B80EAC01BF7E204A79DD14BFDB71A + +I=265 +KEY=0860DD776AD2014ED90D0837A5A298B627DAFFF7F9147E13BA89FA4FAB572C45 +IV=8D6B80EAC01BF7E204A79DD14BFDB71A +PT=62B7D4E9CC0E51BB158E64091C965724 +CT=DAD6A83408559AD3003C6995DC099303 + +I=266 +KEY=9E8757199D96CA08B9C3CEF817E902B8FD0C57C3F141E4C0BAB593DA775EBF46 +IV=DAD6A83408559AD3003C6995DC099303 +PT=96E78A6EF744CB4660CEC6CFB24B9A0E +CT=AA6EF32AFC8AA6ADCDE86D86CC59AFB4 + +I=267 +KEY=483AD9696154B929F35016B648F5952B5762A4E90DCB426D775DFE5CBB0710F2 +IV=AA6EF32AFC8AA6ADCDE86D86CC59AFB4 +PT=D6BD8E70FCC273214A93D84E5F1C9793 +CT=713F9516A55FBFA4AE8155EC12A3AB5D + +I=268 +KEY=027B7F5F83B26099A4CE8FCC1AB84529265D31FFA894FDC9D9DCABB0A9A4BBAF +IV=713F9516A55FBFA4AE8155EC12A3AB5D +PT=4A41A636E2E6D9B0579E997A524DD002 +CT=B2E4BEAF6DB84214E379B89697191379 + +I=269 +KEY=D7AEFAD28855BB04A9604527F8376CAF94B98F50C52CBFDD3AA513263EBDA8D6 +IV=B2E4BEAF6DB84214E379B89697191379 +PT=D5D5858D0BE7DB9D0DAECAEBE28F2986 +CT=9FE3B8941D9F85B1400CC45B7BDE8E9F + +I=270 +KEY=B5EBE7CB901F69E61EC6F011E6A46A2E0B5A37C4D8B33A6C7AA9D77D45632649 +IV=9FE3B8941D9F85B1400CC45B7BDE8E9F +PT=62451D19184AD2E2B7A6B5361E930681 +CT=E9ABFC5563B4AD1718EF4A91F7D60913 + +I=271 +KEY=571805B63BC20F5784AF56FDB71CBCD7E2F1CB91BB07977B62469DECB2B52F5A +IV=E9ABFC5563B4AD1718EF4A91F7D60913 +PT=E2F3E27DABDD66B19A69A6EC51B8D6F9 +CT=D825DC1C8C73A84BDFEFD9799D9E3960 + +I=272 +KEY=9EED79D9ABB11094FB4475ED2EC042133AD4178D37743F30BDA944952F2B163A +IV=D825DC1C8C73A84BDFEFD9799D9E3960 +PT=C9F57C6F90731FC37FEB231099DCFEC4 +CT=7D0DC4C31259FD0A46D2D2282F1FE22E + +I=273 +KEY=EF905E20846E064A3B3281FD2BD59AB647D9D34E252DC23AFB7B96BD0034F414 +IV=7D0DC4C31259FD0A46D2D2282F1FE22E +PT=717D27F92FDF16DEC076F4100515D8A5 +CT=93FAFC16EFF504A9D2B791A272A78135 + +I=274 +KEY=8F219C67ACF0F1C745FA0ABBADE96015D4232F58CAD8C69329CC071F72937521 +IV=93FAFC16EFF504A9D2B791A272A78135 +PT=60B1C247289EF78D7EC88B46863CFAA3 +CT=EF387517F8C781A79700C8196DCA6F1A + +I=275 +KEY=48C6408FD8FA84D30DD53B83B31C425D3B1B5A4F321F4734BECCCF061F591A3B +IV=EF387517F8C781A79700C8196DCA6F1A +PT=C7E7DCE8740A7514482F31381EF52248 +CT=A6166002C7239645D55494BB64840B26 + +I=276 +KEY=1C9EB0648715CA5738A4FD27A63693A09D0D3A4DF53CD1716B985BBD7BDD111D +IV=A6166002C7239645D55494BB64840B26 +PT=5458F0EB5FEF4E843571C6A4152AD1FD +CT=FB35646B2008AD29AFF508B94179F223 + +I=277 +KEY=4AA2E4BAC74E8CD9AEA969550D27877866385E26D5347C58C46D53043AA4E33E +IV=FB35646B2008AD29AFF508B94179F223 +PT=563C54DE405B468E960D9472AB1114D8 +CT=59C1692D4598AD622B6586A06892E11D + +I=278 +KEY=B9F5A3BAAA0C2F6EA5E835F6E6E5D50E3FF9370B90ACD13AEF08D5A452360223 +IV=59C1692D4598AD622B6586A06892E11D +PT=F35747006D42A3B70B415CA3EBC25276 +CT=3131E251A6A4AC7226A1809553198AB8 + +I=279 +KEY=EF46814F8656D3D8ABAF3B08EFEBC3150EC8D55A36087D48C9A95531012F889B +IV=3131E251A6A4AC7226A1809553198AB8 +PT=56B322F52C5AFCB60E470EFE090E161B +CT=2E30D8D5B7B636307A6D354FBED41A2D + +I=280 +KEY=3DFBE0FE20F0421CAABD62E2CDB0E60F20F80D8F81BE4B78B3C4607EBFFB92B6 +IV=2E30D8D5B7B636307A6D354FBED41A2D +PT=D2BD61B1A6A691C4011259EA225B251A +CT=6D791952F9416FC09B78517A2FFE986F + +I=281 +KEY=5197CF05753D155C5B08A5EB51B82F2D4D8114DD78FF24B828BC310490050AD9 +IV=6D791952F9416FC09B78517A2FFE986F +PT=6C6C2FFB55CD5740F1B5C7099C08C922 +CT=37A8E0B9375AD5669A396D980D68D0F3 + +I=282 +KEY=B3EFE2F914264AAAB7C7FD9C4843619E7A29F4644FA5F1DEB2855C9C9D6DDA2A +IV=37A8E0B9375AD5669A396D980D68D0F3 +PT=E2782DFC611B5FF6ECCF587719FB4EB3 +CT=BC65630DB71EE8DA2194E5DFBC48360E + +I=283 +KEY=CAAB7758FF4AFF39A98C2202A26165CFC64C9769F8BB19049311B9432125EC24 +IV=BC65630DB71EE8DA2194E5DFBC48360E +PT=794495A1EB6CB5931E4BDF9EEA220451 +CT=9C47136C1B510BFCEFA7F6659BDA08C2 + +I=284 +KEY=CC38852E17544DB004372C4A3AA3DFDB5A0B8405E3EA12F87CB64F26BAFFE4E6 +IV=9C47136C1B510BFCEFA7F6659BDA08C2 +PT=0693F276E81EB289ADBB0E4898C2BA14 +CT=68AC57D13EC53C250FEBFC64B1992B1C + +I=285 +KEY=108FE55553F353DFABD421E15A18C9F532A7D3D4DD2F2EDD735DB3420B66CFFA +IV=68AC57D13EC53C250FEBFC64B1992B1C +PT=DCB7607B44A71E6FAFE30DAB60BB162E +CT=9A8C11E031E57B77138A3637784D1D71 + +I=286 +KEY=C432EA6E854DE8C191C6F0ED4A2BF1D7A82BC234ECCA55AA60D78575732BD28B +IV=9A8C11E031E57B77138A3637784D1D71 +PT=D4BD0F3BD6BEBB1E3A12D10C10333822 +CT=3BBB1E76A491A5AA145ED931BB886333 + +I=287 +KEY=980941D5FEFD458061B1B443E39818299390DC42485BF00074895C44C8A3B1B8 +IV=3BBB1E76A491A5AA145ED931BB886333 +PT=5C3BABBB7BB0AD41F07744AEA9B3E9FE +CT=F79F1B46F57BDD36B58DDA33619D3920 + +I=288 +KEY=B4FF33FB094612B6A3438A285C3AEA41640FC704BD202D36C1048677A93E8898 +IV=F79F1B46F57BDD36B58DDA33619D3920 +PT=2CF6722EF7BB5736C2F23E6BBFA2F268 +CT=F1C3ED72D0B6D917DD6F8AE86CFD8CBF + +I=289 +KEY=BC81027596771F9C591BE6C61762B1E795CC2A766D96F4211C6B0C9FC5C30427 +IV=F1C3ED72D0B6D917DD6F8AE86CFD8CBF +PT=087E318E9F310D2AFA586CEE4B585BA6 +CT=EAF1AACEEB9F9BE0E880911BFEEAC2AC + +I=290 +KEY=D41458000DDED43B83DAA81B1D7FFB597F3D80B886096FC1F4EB9D843B29C68B +IV=EAF1AACEEB9F9BE0E880911BFEEAC2AC +PT=68955A759BA9CBA7DAC14EDD0A1D4ABE +CT=7B35179E67E9B40346F7DE6356EDC98F + +I=291 +KEY=FACDC2B3BA9E125B2A734DE75F99F48C04089726E1E0DBC2B21C43E76DC40F04 +IV=7B35179E67E9B40346F7DE6356EDC98F +PT=2ED99AB3B740C660A9A9E5FC42E60FD5 +CT=0EDE849D7E56B296B12C1EDF37436A8D + +I=292 +KEY=E73022253439EB4464CE0B205BBB0F1F0AD613BB9FB6695403305D385A876589 +IV=0EDE849D7E56B296B12C1EDF37436A8D +PT=1DFDE0968EA7F91F4EBD46C70422FB93 +CT=D02F1EAF3CF6A6B681BAF8ECB921FFC4 + +I=293 +KEY=9F3671205266DC4F7C771EBA74265F36DAF90D14A340CFE2828AA5D4E3A69A4D +IV=D02F1EAF3CF6A6B681BAF8ECB921FFC4 +PT=78065305665F370B18B9159A2F9D5029 +CT=E365BE1A125C6930DFDCBB33E6937EC5 + +I=294 +KEY=111A3E012C9D5CB2967E8BD22907D6F7399CB30EB11CA6D25D561EE70535E488 +IV=E365BE1A125C6930DFDCBB33E6937EC5 +PT=8E2C4F217EFB80FDEA0995685D2189C1 +CT=C5B24EEC5CDD17AA56838B09EC4AB725 + +I=295 +KEY=15DA3EE4EE9A560B05493FFC971713A5FC2EFDE2EDC1B1780BD595EEE97F53AD +IV=C5B24EEC5CDD17AA56838B09EC4AB725 +PT=04C000E5C2070AB99337B42EBE10C552 +CT=4D8A43CD28BBCB86953FA55A409BF130 + +I=296 +KEY=2C8B30484D954192818342F3766C1415B1A4BE2FC57A7AFE9EEA30B4A9E4A29D +IV=4D8A43CD28BBCB86953FA55A409BF130 +PT=39510EACA30F179984CA7D0FE17B07B0 +CT=A524A6329E6DCE041F72459234ECDE78 + +I=297 +KEY=0F162BAD5F298EE0B0164CFED6A7AC271480181D5B17B4FA819875269D087CE5 +IV=A524A6329E6DCE041F72459234ECDE78 +PT=239D1BE512BCCF7231950E0DA0CBB832 +CT=90BBC5130D1C06182F737FE7F0FCD00D + +I=298 +KEY=62744CA02B6684D05A91F2049D403480843BDD0E560BB2E2AEEB0AC16DF4ACE8 +IV=90BBC5130D1C06182F737FE7F0FCD00D +PT=6D62670D744F0A30EA87BEFA4BE798A7 +CT=35F293EDDEC8D9446A4ACD34602839B5 + +I=299 +KEY=21F5373DA5D6BF15BC163383F62EA92FB1C94EE388C36BA6C4A1C7F50DDC955D +IV=35F293EDDEC8D9446A4ACD34602839B5 +PT=43817B9D8EB03BC5E687C1876B6E9DAF +CT=E45CF478D7C84325143165F58B041A13 + +I=300 +KEY=4CF4A508B4DF37A831916353620DC1F45595BA9B5F0B2883D090A20086D88F4E +IV=E45CF478D7C84325143165F58B041A13 +PT=6D019235110988BD8D8750D0942368DB +CT=964983C30745D7EEA1BD5E287DAC466C + +I=301 +KEY=35C99C004D01E89F94A9B3BC79C492D7C3DC3958584EFF6D712DFC28FB74C922 +IV=964983C30745D7EEA1BD5E287DAC466C +PT=793D3908F9DEDF37A538D0EF1BC95323 +CT=6834813D8403A963AD36C1A18CA605C0 + +I=302 +KEY=F185723D6A2D2A6F9F4B9194A444AA2AABE8B865DC4D560EDC1B3D8977D2CCE2 +IV=6834813D8403A963AD36C1A18CA605C0 +PT=C44CEE3D272CC2F00BE22228DD8038FD +CT=61F35AA76E1E0EC2D5E4F4F432B68260 + +I=303 +KEY=B571B0BC6CFD2BA23611FB9A900A31FACA1BE2C2B25358CC09FFC97D45644E82 +IV=61F35AA76E1E0EC2D5E4F4F432B68260 +PT=44F4C28106D001CDA95A6A0E344E9BD0 +CT=DD081A96602E6665B860466B8D14050E + +I=304 +KEY=2A5757156C596DE633D0D8908011C3771713F854D27D3EA9B19F8F16C8704B8C +IV=DD081A96602E6665B860466B8D14050E +PT=9F26E7A900A4464405C1230A101BF28D +CT=5BF18EA3D7F3ED1D941EA1B995313B98 + +I=305 +KEY=DA008B517FA48E908A72B8525CC31AEF4CE276F7058ED3B425812EAF5D417014 +IV=5BF18EA3D7F3ED1D941EA1B995313B98 +PT=F057DC4413FDE376B9A260C2DCD2D998 +CT=74C361B6A13013E9ABF6841601513539 + +I=306 +KEY=E313244DC22AC16C1D59AC494AA728D738211741A4BEC05D8E77AAB95C10452D +IV=74C361B6A13013E9ABF6841601513539 +PT=3913AF1CBD8E4FFC972B141B16643238 +CT=9937614570FD404D5B39BA43D3A20602 + +I=307 +KEY=92A7173E943CBA80AF56203552625E8AA1167604D4438010D54E10FA8FB2432F +IV=9937614570FD404D5B39BA43D3A20602 +PT=71B4337356167BECB20F8C7C18C5765D +CT=726FCDDF8E6738B51D767828EBDFC71E + +I=308 +KEY=242C75C141A58DC403020E52421BB347D379BBDB5A24B8A5C83868D2646D8431 +IV=726FCDDF8E6738B51D767828EBDFC71E +PT=B68B62FFD5993744AC542E671079EDCD +CT=78F735344BF10EED47969F1C02ECBF8C + +I=309 +KEY=5247008C3EB79AA67E5D2E0B95D0AC3AAB8E8EEF11D5B6488FAEF7CE66813BBD +IV=78F735344BF10EED47969F1C02ECBF8C +PT=766B754D7F1217627D5F2059D7CB1F7D +CT=7D6A6CA54B084105DF6A778A4913BB04 + +I=310 +KEY=06E7C1A6C8BC6A3355A86F61B41E70C6D6E4E24A5ADDF74D50C480442F9280B9 +IV=7D6A6CA54B084105DF6A778A4913BB04 +PT=54A0C12AF60BF0952BF5416A21CEDCFC +CT=11F0A303D6C0ED5E18F40248AF1A794B + +I=311 +KEY=D7722746B58D494BE9B97F586CA4BB0AC71441498C1D1A134830820C8088F9F2 +IV=11F0A303D6C0ED5E18F40248AF1A794B +PT=D195E6E07D312378BC111039D8BACBCC +CT=2A715E8AC7101415E65EBF34CC4CD786 + +I=312 +KEY=98B1E5954DE8000B6FFFE98D918B6237ED651FC34B0D0E06AE6E3D384CC42E74 +IV=2A715E8AC7101415E65EBF34CC4CD786 +PT=4FC3C2D3F8654940864696D5FD2FD93D +CT=965E8AF93D390E424C9F4F1FBF9D98A5 + +I=313 +KEY=74B910207ACD1D7C801724D53ED6BBC47B3B953A76340044E2F17227F359B6D1 +IV=965E8AF93D390E424C9F4F1FBF9D98A5 +PT=EC08F5B537251D77EFE8CD58AF5DD9F3 +CT=294782DD29C65B6C445C5D92F50E6D19 + +I=314 +KEY=3E1AD36FDCC33F6B3425B5D52717845E527C17E75FF25B28A6AD2FB50657DBC8 +IV=294782DD29C65B6C445C5D92F50E6D19 +PT=4AA3C34FA60E2217B432910019C13F9A +CT=E22098E7EDBEECC49FA8E31B76E925CA + +I=315 +KEY=BE9F93FE153DF61370F6709F8265DCCDB05C8F00B24CB7EC3905CCAE70BEFE02 +IV=E22098E7EDBEECC49FA8E31B76E925CA +PT=80854091C9FEC97844D3C54AA5725893 +CT=24E80C1F59A4EA36044358E0C0D4F29D + +I=316 +KEY=A790F593CFA1643BD2EB3A1AAB8176A294B4831FEBE85DDA3D46944EB06A0C9F +IV=24E80C1F59A4EA36044358E0C0D4F29D +PT=190F666DDA9C9228A21D4A8529E4AA6F +CT=63CF21803941B521532FF36F9FBFC7BD + +I=317 +KEY=0CF6F000352B4B583E4AEE707D111DC9F77BA29FD2A9E8FB6E6967212FD5CB22 +IV=63CF21803941B521532FF36F9FBFC7BD +PT=AB660593FA8A2F63ECA1D46AD6906B6B +CT=250941C1D45C82B0D9C381293CDD833A + +I=318 +KEY=1F875BCF1967857990EC97864B1EA9F8D272E35E06F56A4BB7AAE60813084818 +IV=250941C1D45C82B0D9C381293CDD833A +PT=1371ABCF2C4CCE21AEA679F6360FB431 +CT=8303B962DAFC4A225C0FD6EA60D29CF4 + +I=319 +KEY=42FE25BF51418FE7A7C7A1828219E1DB51715A3CDC092069EBA530E273DAD4EC +IV=8303B962DAFC4A225C0FD6EA60D29CF4 +PT=5D797E7048260A9E372B3604C9074823 +CT=29E2DB359FAB42C0A83A4059A059CB51 + +I=320 +KEY=6C821A4893FE0EAC88FC1F98BD44AD0A7893810943A262A9439F70BBD3831FBD +IV=29E2DB359FAB42C0A83A4059A059CB51 +PT=2E7C3FF7C2BF814B2F3BBE1A3F5D4CD1 +CT=02BDB7EC18279FA9B7788D95FEB4000E + +I=321 +KEY=411670D389D0A04859FDC26DE5AAD1297A2E36E55B85FD00F4E7FD2E2D371FB3 +IV=02BDB7EC18279FA9B7788D95FEB4000E +PT=2D946A9B1A2EAEE4D101DDF558EE7C23 +CT=3960A92A34967F13B754F2265A6F68C1 + +I=322 +KEY=851BCD18F6043DE625BBEA33E1E860E3434E9FCF6F13821343B30F0877587772 +IV=3960A92A34967F13B754F2265A6F68C1 +PT=C40DBDCB7FD49DAE7C46285E0442B1CA +CT=EF396AB8613AC6083932734D38869458 + +I=323 +KEY=1944F363F3143A380F26BD4831A6BD9EAC77F5770E29441B7A817C454FDEE32A +IV=EF396AB8613AC6083932734D38869458 +PT=9C5F3E7B051007DE2A9D577BD04EDD7D +CT=CB73B8D257CC1A8235E48DA0E6AECC4E + +I=324 +KEY=C2F3C203F591C78914E31BA1E083AB9867044DA559E55E994F65F1E5A9702F64 +IV=CB73B8D257CC1A8235E48DA0E6AECC4E +PT=DBB731600685FDB11BC5A6E9D1251606 +CT=3B0B12757B5D1B6E0130FCC306E9DBAA + +I=325 +KEY=0DCB66B972631AFBB1DA22F1418EE1C45C0F5FD022B845F74E550D26AF99F4CE +IV=3B0B12757B5D1B6E0130FCC306E9DBAA +PT=CF38A4BA87F2DD72A5393950A10D4A5C +CT=CCEF4079CE8FAF0E6B8CD4C8751059E1 + +I=326 +KEY=8FF976D3C735506D86A3540664F1C40590E01FA9EC37EAF925D9D9EEDA89AD2F +IV=CCEF4079CE8FAF0E6B8CD4C8751059E1 +PT=8232106AB5564A96377976F7257F25C1 +CT=D835D2FA5583D9B2C16424960163DF7F + +I=327 +KEY=3499925B26E4F846CAA230EC069F127F48D5CD53B9B4334BE4BDFD78DBEA7250 +IV=D835D2FA5583D9B2C16424960163DF7F +PT=BB60E488E1D1A82B4C0164EA626ED67A +CT=4634485DB5D9C40FA2F6EF36E477F0B7 + +I=328 +KEY=7A133EEC3DD747FE38A3370F8927A3C70EE1850E0C6DF744464B124E3F9D82E7 +IV=4634485DB5D9C40FA2F6EF36E477F0B7 +PT=4E8AACB71B33BFB8F20107E38FB8B1B8 +CT=AE30CD2A5D84CEF10B9C15EE1FE20CEB + +I=329 +KEY=F573665345317BAB5F14881777A0D789A0D1482451E939B54DD707A0207F8E0C +IV=AE30CD2A5D84CEF10B9C15EE1FE20CEB +PT=8F6058BF78E63C5567B7BF18FE87744E +CT=B3926CDE5BFB1363DCCA28CDA2DC4CD8 + +I=330 +KEY=FEFB661FA786BF2DA1B70FD7D06B86E8134324FA0A122AD6911D2F6D82A3C2D4 +IV=B3926CDE5BFB1363DCCA28CDA2DC4CD8 +PT=0B88004CE2B7C486FEA387C0A7CB5161 +CT=633388FA9EAE0DB2036F63CB2E21C266 + +I=331 +KEY=BFC495DFBA60078708D992724C9201577070AC0094BC276492724CA6AC8200B2 +IV=633388FA9EAE0DB2036F63CB2E21C266 +PT=413FF3C01DE6B8AAA96E9DA59CF987BF +CT=54ACB838D247D26A1544B2E42F18CF3F + +I=332 +KEY=EB0113E4FFE1201B59EAE94706B2571F24DC143846FBF50E8736FE42839ACF8D +IV=54ACB838D247D26A1544B2E42F18CF3F +PT=54C5863B4581279C51337B354A205648 +CT=B9210B8A8639CA5C94A1CF1169F89DDB + +I=333 +KEY=0E1D5F7873FD6440227C5529AEB4C7999DFD1FB2C0C23F5213973153EA625256 +IV=B9210B8A8639CA5C94A1CF1169F89DDB +PT=E51C4C9C8C1C445B7B96BC6EA8069086 +CT=8990488561B43B03CF9FE631E2E7D5E7 + +I=334 +KEY=8B2759471137DBF37906B394EFEF96D2146D5737A1760451DC08D762088587B1 +IV=8990488561B43B03CF9FE631E2E7D5E7 +PT=853A063F62CABFB35B7AE6BD415B514B +CT=9DCE77D8CCC0F041FA717C28474E9A30 + +I=335 +KEY=0D4B29E8D6F39CA01BC01CE73E2834C689A320EF6DB6F4102679AB4A4FCB1D81 +IV=9DCE77D8CCC0F041FA717C28474E9A30 +PT=866C70AFC7C4475362C6AF73D1C7A214 +CT=E1DA174FE5848D21735E55B91CA48A9B + +I=336 +KEY=55228F6FF93B7DE9304CD75991C133A5687937A0883279315527FEF3536F971A +IV=E1DA174FE5848D21735E55B91CA48A9B +PT=5869A6872FC8E1492B8CCBBEAFE90763 +CT=C578F53AD69AD508711E674F8DD2A843 + +I=337 +KEY=35CA943437046860F72A1F8554127676AD01C29A5EA8AC39243999BCDEBD3F59 +IV=C578F53AD69AD508711E674F8DD2A843 +PT=60E81B5BCE3F1589C766C8DCC5D345D3 +CT=177A50196260D3F0A3F97423899EBEE2 + +I=338 +KEY=B8C3B8414C112FC2E2E848733D5CF69CBA7B92833CC87FC987C0ED9F572381BB +IV=177A50196260D3F0A3F97423899EBEE2 +PT=8D092C757B1547A215C257F6694E80EA +CT=6B03A799C51C7D0A9D3C9929617E69B1 + +I=339 +KEY=E82B651AE5740119104FE3284CE780E4D178351AF9D402C31AFC74B6365DE80A +IV=6B03A799C51C7D0A9D3C9929617E69B1 +PT=50E8DD5BA9652EDBF2A7AB5B71BB7678 +CT=8D4C7C1157422E7B6DDA47C5C2C246F4 + +I=340 +KEY=3C0B660F2B78F768812AC671D3107AD85C34490BAE962CB877263373F49FAEFE +IV=8D4C7C1157422E7B6DDA47C5C2C246F4 +PT=D4200315CE0CF671916525599FF7FA3C +CT=787B3C51094569BC1F139102964DF5AF + +I=341 +KEY=A197B59C700A4786E840733047964FD4244F755AA7D345046835A27162D25B51 +IV=787B3C51094569BC1F139102964DF5AF +PT=9D9CD3935B72B0EE696AB5419486350C +CT=AE02945B4E63AC35B6AC2DFA2DF3CEBA + +I=342 +KEY=00E75C4B909D44A94FA20EDA6C3628418A4DE101E9B0E931DE998F8B4F2195EB +IV=AE02945B4E63AC35B6AC2DFA2DF3CEBA +PT=A170E9D7E097032FA7E27DEA2BA06795 +CT=AC4AACD3597FE73F519F7CEDAFE6E000 + +I=343 +KEY=4626BE31853C15DE412EF2A42328D47326074DD2B0CF0E0E8F06F366E0C775EB +IV=AC4AACD3597FE73F519F7CEDAFE6E000 +PT=46C1E27A15A151770E8CFC7E4F1EFC32 +CT=5EB8B35708A135E041603BA323663F34 + +I=344 +KEY=1733A037E76437411F49821D948A098978BFFE85B86E3BEECE66C8C5C3A14ADF +IV=5EB8B35708A135E041603BA323663F34 +PT=51151E066258229F5E6770B9B7A2DDFA +CT=6674FB922570377334A4F22D13E95BD8 + +I=345 +KEY=8474275A2E4D5E5448EB8D34B65EE7081ECB05179D1E0C9DFAC23AE8D0481107 +IV=6674FB922570377334A4F22D13E95BD8 +PT=9347876DC929691557A20F2922D4EE81 +CT=F0E3F09C0350C0172E449A01F24AB828 + +I=346 +KEY=765AA3F4014B8475CF832DE6128F7F2DEE28F58B9E4ECC8AD486A0E92202A92F +IV=F0E3F09C0350C0172E449A01F24AB828 +PT=F22E84AE2F06DA218768A0D2A4D19825 +CT=CC156010299679ADEE9CC000FD5C90E5 + +I=347 +KEY=DD3D3AFC83B7EEBC58CE35B35719B587223D959BB7D8B5273A1A60E9DF5E39CA +IV=CC156010299679ADEE9CC000FD5C90E5 +PT=AB67990882FC6AC9974D18554596CAAA +CT=80354EDEA10038E903C4896313236CE5 + +I=348 +KEY=4764BB8C98BCF3FD4A21A370AE5432BBA208DB4516D88DCE39DEE98ACC7D552F +IV=80354EDEA10038E903C4896313236CE5 +PT=9A5981701B0B1D4112EF96C3F94D873C +CT=15140DC26F383EB99425FB51D445CC98 + +I=349 +KEY=DF729AB7D09BC85489F8AD373EBDDA70B71CD68779E0B377ADFB12DB183899B7 +IV=15140DC26F383EB99425FB51D445CC98 +PT=9816213B48273BA9C3D90E4790E9E8CB +CT=163465787010C97D3C2023D803F62556 + +I=350 +KEY=A945B0C5997C596B5155A6BCA5055127A128B3FF09F07A0A91DB31031BCEBCE1 +IV=163465787010C97D3C2023D803F62556 +PT=76372A7249E7913FD8AD0B8B9BB88B57 +CT=23E861D557EE72534C8B729240E3A54F + +I=351 +KEY=0E1C166F2B947D14D0C7E6ABD280A31E82C0D22A5E1E0859DD5043915B2D19AE +IV=23E861D557EE72534C8B729240E3A54F +PT=A759A6AAB2E8247F819240177785F239 +CT=652CA6A199D7DBC37936FCD70636989F + +I=352 +KEY=208A37149072011877E3E85B3DC7F4A7E7EC748BC7C9D39AA466BF465D1B8131 +IV=652CA6A199D7DBC37936FCD70636989F +PT=2E96217BBBE67C0CA7240EF0EF4757B9 +CT=7C29D6F4788553E3C50A48027478A98F + +I=353 +KEY=A8FFCB194C077EEED66632AEBE01652E9BC5A27FBF4C8079616CF744296328BE +IV=7C29D6F4788553E3C50A48027478A98F +PT=8875FC0DDC757FF6A185DAF583C69189 +CT=7B886FC819D625B224F2516901788E88 + +I=354 +KEY=3716969BDDBF04FF4010D4667CCA994AE04DCDB7A69AA5CB459EA62D281BA636 +IV=7B886FC819D625B224F2516901788E88 +PT=9FE95D8291B87A119676E6C8C2CBFC64 +CT=3EAB925C025F379153CE2C7191026976 + +I=355 +KEY=991D0D313717C7AC62537C8572DE094BDEE65FEBA4C5925A16508A5CB919CF40 +IV=3EAB925C025F379153CE2C7191026976 +PT=AE0B9BAAEAA8C3532243A8E30E149001 +CT=B9904B8BDF431FDDB9166086C9D3E24C + +I=356 +KEY=315772BB82A3DD286FE5891934B19434677614607B868D87AF46EADA70CA2D0C +IV=B9904B8BDF431FDDB9166086C9D3E24C +PT=A84A7F8AB5B41A840DB6F59C466F9D7F +CT=3C7029336ECCA5D352DB9D0C060D3830 + +I=357 +KEY=C99E4E6A8C1D42A9E431FF8B2A8ACA615B063D53154A2854FD9D77D676C7153C +IV=3C7029336ECCA5D352DB9D0C060D3830 +PT=F8C93CD10EBE9F818BD476921E3B5E55 +CT=4AF4290AA79EB96435D2D3FC745033D7 + +I=358 +KEY=55317B8B407B7D089ED2CEF7BE80E99111F21459B2D49130C84FA42A029726EB +IV=4AF4290AA79EB96435D2D3FC745033D7 +PT=9CAF35E1CC663FA17AE3317C940A23F0 +CT=BFCA0B6B31AAD81F1BDC743B48B7CCA4 + +I=359 +KEY=6EAE6D8B06AA25493BA3608357D71404AE381F32837E492FD393D0114A20EA4F +IV=BFCA0B6B31AAD81F1BDC743B48B7CCA4 +PT=3B9F160046D15841A571AE74E957FD95 +CT=89C1D565569A12A68B2E808AB5CFA2E3 + +I=360 +KEY=3245D7C1F5571A1329E1B2303F8A689D27F9CA57D5E45B8958BD509BFFEF48AC +IV=89C1D565569A12A68B2E808AB5CFA2E3 +PT=5CEBBA4AF3FD3F5A1242D2B3685D7C99 +CT=EC8EEAED7894646B1D1A5E058ED41178 + +I=361 +KEY=1DE05811428569D3F89CF1C01AF434AFCB7720BAAD703FE245A70E9E713B59D4 +IV=EC8EEAED7894646B1D1A5E058ED41178 +PT=2FA58FD0B7D273C0D17D43F0257E5C32 +CT=92802F392579C66AD72D2E85776720E8 + +I=362 +KEY=0A8FB6D844AB0B73C05A121085E07FFE59F70F838809F988928A201B065C793C +IV=92802F392579C66AD72D2E85776720E8 +PT=176FEEC9062E62A038C6E3D09F144B51 +CT=461DBCF9894F5319FE772F6529FBCEC0 + +I=363 +KEY=4E6818B3BBEF69FA7ABEC1EBE2E54CDC1FEAB37A0146AA916CFD0F7E2FA7B7FC +IV=461DBCF9894F5319FE772F6529FBCEC0 +PT=44E7AE6BFF446289BAE4D3FB67053322 +CT=794CA9DC41BAE95D415A6D1119582763 + +I=364 +KEY=4A1EABB13924B188441724141F1C88A966A61AA640FC43CC2DA7626F36FF909F +IV=794CA9DC41BAE95D415A6D1119582763 +PT=0476B30282CBD8723EA9E5FFFDF9C475 +CT=B761EAF5CC07651BD33D8BF93913EAE8 + +I=365 +KEY=FFE4E48F8D96710A1BE7DBE36F4905CDD1C7F0538CFB26D7FE9AE9960FEC7A77 +IV=B761EAF5CC07651BD33D8BF93913EAE8 +PT=B5FA4F3EB4B2C0825FF0FFF770558D64 +CT=0B5146EB77161E60D6D1E2FAEAE80694 + +I=366 +KEY=7A4F383AF4BB2DC6588E75EE82C7D9CFDA96B6B8FBED38B7284B0B6CE5047CE3 +IV=0B5146EB77161E60D6D1E2FAEAE80694 +PT=85ABDCB5792D5CCC4369AE0DED8EDC02 +CT=07635064CE85F6AE17961AF1F2B44469 + +I=367 +KEY=EFFE7F8BBBEC8BEC83FA199102763BEDDDF5E6DC3568CE193FDD119D17B0388A +IV=07635064CE85F6AE17961AF1F2B44469 +PT=95B147B14F57A62ADB746C7F80B1E222 +CT=3A9CD5F30C421FF333BA2C2F0A7AD07D + +I=368 +KEY=1DF51B7A35E11E2AF79E8C59094A1ECFE769332F392AD1EA0C673DB21DCAE8F7 +IV=3A9CD5F30C421FF333BA2C2F0A7AD07D +PT=F20B64F18E0D95C6746495C80B3C2522 +CT=F60032C249CF561CB02421DA189A57D1 + +I=369 +KEY=CC09FFE72A10AE27FE14934A6628AB83116901ED70E587F6BC431C680550BF26 +IV=F60032C249CF561CB02421DA189A57D1 +PT=D1FCE49D1FF1B00D098A1F136F62B54C +CT=EAD5844B160C08F9CDAA15FD5936EF26 + +I=370 +KEY=09C84CA0DA0B9FD79D3090E690BAB419FBBC85A666E98F0F71E909955C665000 +IV=EAD5844B160C08F9CDAA15FD5936EF26 +PT=C5C1B347F01B31F0632403ACF6921F9A +CT=26AD72F011133FD4CED8F38A1ABE7D73 + +I=371 +KEY=74FA53C172A2003EC5933F486FCC7BBFDD11F75677FAB0DBBF31FA1F46D82D73 +IV=26AD72F011133FD4CED8F38A1ABE7D73 +PT=7D321F61A8A99FE958A3AFAEFF76CFA6 +CT=F115FBC0D3F386527176D1DF6AD4B38A + +I=372 +KEY=0E5BA209B7BC28D184E73BD37F35C1312C040C96A4093689CE472BC02C0C9EF9 +IV=F115FBC0D3F386527176D1DF6AD4B38A +PT=7AA1F1C8C51E28EF4174049B10F9BA8E +CT=27ED0BA04734E70317BF58E11B0DD051 + +I=373 +KEY=9404D9139B6597D1F7C7519713C6CBC80BE90736E33DD18AD9F8732137014EA8 +IV=27ED0BA04734E70317BF58E11B0DD051 +PT=9A5F7B1A2CD9BF0073206A446CF30AF9 +CT=24080A577426F8F270A13F3A5F3DB546 + +I=374 +KEY=E72476BC679C8DCBAB92BBA5D48BF6D32FE10D61971B2978A9594C1B683CFBEE +IV=24080A577426F8F270A13F3A5F3DB546 +PT=7320AFAFFCF91A1A5C55EA32C74D3D1B +CT=A754CC0464E35B387435790505F2DCE5 + +I=375 +KEY=4548DE389CCAD4A65B02A9B5FE90930188B5C165F3F87240DD6C351E6DCE270B +IV=A754CC0464E35B387435790505F2DCE5 +PT=A26CA884FB56596DF09012102A1B65D2 +CT=D9AED2566884E97D081EADB45780AA7D + +I=376 +KEY=2E54365B503140D0EC9074DFA05F4B2C511B13339B7C9B3DD57298AA3A4E8D76 +IV=D9AED2566884E97D081EADB45780AA7D +PT=6B1CE863CCFB9476B792DD6A5ECFD82D +CT=9FA221E082CAD838AB4B210A8794BD8F + +I=377 +KEY=7C9FB092B8A96465076E14C575E9A8F0CEB932D319B643057E39B9A0BDDA30F9 +IV=9FA221E082CAD838AB4B210A8794BD8F +PT=52CB86C9E89824B5EBFE601AD5B6E3DC +CT=AAEA6DE5734CF14BED503512EB071C2A + +I=378 +KEY=90AB85A18F2B0255D4F43AF5E98DAA7E64535F366AFAB24E93698CB256DD2CD3 +IV=AAEA6DE5734CF14BED503512EB071C2A +PT=EC34353337826630D39A2E309C64028E +CT=1359A157B415EB63E038AB7354E6B0F2 + +I=379 +KEY=9135D4D54A1CE6BBF4F23AFDE23F537C770AFE61DEEF592D735127C1023B9C21 +IV=1359A157B415EB63E038AB7354E6B0F2 +PT=019E5174C537E4EE200600080BB2F902 +CT=0764EBDBFAE8FD447244408A5153CC3B + +I=380 +KEY=4B5F1BC60EF5DCE83474A3970EB2ABA8706E15BA2407A4690115674B5368501A +IV=0764EBDBFAE8FD447244408A5153CC3B +PT=DA6ACF1344E93A53C086996AEC8DF8D4 +CT=A31F69E0055E8D4162AC06C088925FBA + +I=381 +KEY=9DD8E8D75BE2E4D1BC70B30DAE0B375FD3717C5A2159292863B9618BDBFA0FA0 +IV=A31F69E0055E8D4162AC06C088925FBA +PT=D687F311551738398804109AA0B99CF7 +CT=EB84AC035534CDF1698E660F529E0EC7 + +I=382 +KEY=4A2B2FC8446B4C2575CFE584A490680238F5D059746DE4D90A37078489640167 +IV=EB84AC035534CDF1698E660F529E0EC7 +PT=D7F3C71F1F89A8F4C9BF56890A9B5F5D +CT=9236D37A28C2CF29237127173B93C5D5 + +I=383 +KEY=9BE42576823EEAADB34657A5CBB44B21AAC303235CAF2BF029462093B2F7C4B2 +IV=9236D37A28C2CF29237127173B93C5D5 +PT=D1CF0ABEC655A688C689B2216F242323 +CT=86C122CFA62B1356FEE33FECF598ACC9 + +I=384 +KEY=5DFC1838B052E95A948D0AC31736CBE62C0221ECFA8438A6D7A51F7F476F687B +IV=86C122CFA62B1356FEE33FECF598ACC9 +PT=C6183D4E326C03F727CB5D66DC8280C7 +CT=8A9926125B1CA354B1D7A9FED0850FEE + +I=385 +KEY=2B12FA914EE7674EADED81C47A67A1B4A69B07FEA1989BF26672B68197EA6795 +IV=8A9926125B1CA354B1D7A9FED0850FEE +PT=76EEE2A9FEB58E1439608B076D516A52 +CT=AD99A2A427BFF7A17C375DB38764EBFC + +I=386 +KEY=10607DE088CB92382089EF99B7C054280B02A55A86276C531A45EB32108E8C69 +IV=AD99A2A427BFF7A17C375DB38764EBFC +PT=3B728771C62CF5768D646E5DCDA7F59C +CT=0E141FD7D6928E7B7885638B6334947C + +I=387 +KEY=605ECCB38F9FFD9DAB2DB523313FFADB0516BA8D50B5E22862C088B973BA1815 +IV=0E141FD7D6928E7B7885638B6334947C +PT=703EB15307546FA58BA45ABA86FFAEF3 +CT=996CB8723B08B99A4959072DC8A73292 + +I=388 +KEY=C6371257BDA461F3A4D2F1ED5DD4B0B69C7A02FF6BBD5BB22B998F94BB1D2A87 +IV=996CB8723B08B99A4959072DC8A73292 +PT=A669DEE4323B9C6E0FFF44CE6CEB4A6D +CT=72966BAA5E4D7FA9129088F2C072E301 + +I=389 +KEY=DDD8877C25005F9B8336823CBF4D4B1DEEEC695535F0241B390907667B6FC986 +IV=72966BAA5E4D7FA9129088F2C072E301 +PT=1BEF952B98A43E6827E473D1E299FBAB +CT=32C321C999A2D68EA4517D332C785FC4 + +I=390 +KEY=00882DCBC6CFDED1A2ED7D9892F494A5DC2F489CAC52F2959D587A5557179642 +IV=32C321C999A2D68EA4517D332C785FC4 +PT=DD50AAB7E3CF814A21DBFFA42DB9DFB8 +CT=391D95DD63982E0A9AF3980A234DB5B9 + +I=391 +KEY=234B9097BD6519EFE106103720AC937DE532DD41CFCADC9F07ABE25F745A23FB +IV=391D95DD63982E0A9AF3980A234DB5B9 +PT=23C3BD5C7BAAC73E43EB6DAFB25807D8 +CT=D3A279EE1BABABA71DB01DC35EBA879D + +I=392 +KEY=AFF7D52D959CC7E41F1F3FF3CA2425053690A4AFD46177381A1BFF9C2AE0A466 +IV=D3A279EE1BABABA71DB01DC35EBA879D +PT=8CBC45BA28F9DE0BFE192FC4EA88B678 +CT=B4696871EE3A9D035BC32308DA5A5DA7 + +I=393 +KEY=B557440CEEB6E4EF54F6CD1B222246AC82F9CCDE3A5BEA3B41D8DC94F0BAF9C1 +IV=B4696871EE3A9D035BC32308DA5A5DA7 +PT=1AA091217B2A230B4BE9F2E8E80663A9 +CT=C5047AFD7884E0124928229AA6E72F67 + +I=394 +KEY=BF64C071FAAD2C48CB269C03563FA06147FDB62342DF0A2908F0FE0E565DD6A6 +IV=C5047AFD7884E0124928229AA6E72F67 +PT=0A33847D141BC8A79FD05118741DE6CD +CT=240D684E6BAD3FD4E41D58DB871E93CD + +I=395 +KEY=F6945509258A1584398F5438DFD679DB63F0DE6D297235FDECEDA6D5D143456B +IV=240D684E6BAD3FD4E41D58DB871E93CD +PT=49F09578DF2739CCF2A9C83B89E9D9BA +CT=F66917F0C3C67774F9263062F918DDD5 + +I=396 +KEY=A8E48107D59287ABBA374E7CE5BC28E89599C99DEAB4428915CB96B7285B98BE +IV=F66917F0C3C67774F9263062F918DDD5 +PT=5E70D40EF018922F83B81A443A6A5133 +CT=85C42456F11D0191BC4B4DD4EA0406EE + +I=397 +KEY=E4F367569F4F9114AFE937A0190C9738105DEDCB1BA94318A980DB63C25F9E50 +IV=85C42456F11D0191BC4B4DD4EA0406EE +PT=4C17E6514ADD16BF15DE79DCFCB0BFD0 +CT=D48B6C87A25C71113947569411C2186A + +I=398 +KEY=987ED2D586DA9AB08C584BBEA0478953C4D6814CB9F5320990C78DF7D39D863A +IV=D48B6C87A25C71113947569411C2186A +PT=7C8DB58319950BA423B17C1EB94B1E6B +CT=AB6957C2F3D360593E9096F3A392A701 + +I=399 +KEY=3DF2BF13B7FF97CA13567A890E11C9796FBFD68E4A265250AE571B04700F213B +IV=AB6957C2F3D360593E9096F3A392A701 +PT=A58C6DC631250D7A9F0E3137AE56402A +CT=C0FEFFF07506A0B4CD7B8B0CF25D3664 + +=========== \ No newline at end of file diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_d_m.txt b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_d_m.txt new file mode 100644 index 00000000..d99a69af --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_d_m.txt @@ -0,0 +1,6024 @@ + +========================= + +FILENAME: "ecb_d_m.txt" + +Electronic Codebook (ECB) Mode - DECRYPTION +Monte Carlo Test + +Algorithm Name: Rijndael +Principal Submitter: Joan Daemen + +========================= + +KEYSIZE=128 + +I=0 +KEY=00000000000000000000000000000000 +CT=00000000000000000000000000000000 +PT=44416AC2D1F53C583303917E6BE9EBE0 + +I=1 +KEY=44416AC2D1F53C583303917E6BE9EBE0 +CT=44416AC2D1F53C583303917E6BE9EBE0 +PT=E3FD51123B48A2E2AB1DB29894202222 + +I=2 +KEY=A7BC3BD0EABD9EBA981E23E6FFC9C9C2 +CT=E3FD51123B48A2E2AB1DB29894202222 +PT=877B88A77AEF04F05546539E17259F53 + +I=3 +KEY=20C7B37790529A4ACD587078E8EC5691 +CT=877B88A77AEF04F05546539E17259F53 +PT=C7A71C1B46261602EB1EE48FDA8155A4 + +I=4 +KEY=E760AF6CD6748C48264694F7326D0335 +CT=C7A71C1B46261602EB1EE48FDA8155A4 +PT=6B6AC8E00FAF7E045ECCFC426A137221 + +I=5 +KEY=8C0A678CD9DBF24C788A68B5587E7114 +CT=6B6AC8E00FAF7E045ECCFC426A137221 +PT=3F252821FA79AFC3F1798B343AAD41EE + +I=6 +KEY=B32F4FAD23A25D8F89F3E38162D330FA +CT=3F252821FA79AFC3F1798B343AAD41EE +PT=0B55C691E1F97205D137FF34478E5BC9 + +I=7 +KEY=B87A893CC25B2F8A58C41CB5255D6B33 +CT=0B55C691E1F97205D137FF34478E5BC9 +PT=F6CCC1CC18A3199D6427EDCA0BB2DF90 + +I=8 +KEY=4EB648F0DAF836173CE3F17F2EEFB4A3 +CT=F6CCC1CC18A3199D6427EDCA0BB2DF90 +PT=0CDD7D9734B1515C73DDA60EFF28CD89 + +I=9 +KEY=426B3567EE49674B4F3E5771D1C7792A +CT=0CDD7D9734B1515C73DDA60EFF28CD89 +PT=3E813131EDD440D9054799CEA508FF6F + +I=10 +KEY=7CEA0456039D27924A79CEBF74CF8645 +CT=3E813131EDD440D9054799CEA508FF6F +PT=8C6859BD0B6E078FAA6B686297653232 + +I=11 +KEY=F0825DEB08F3201DE012A6DDE3AAB477 +CT=8C6859BD0B6E078FAA6B686297653232 +PT=C966A4106C1DCE062D1346EB5E5133BB + +I=12 +KEY=39E4F9FB64EEEE1BCD01E036BDFB87CC +CT=C966A4106C1DCE062D1346EB5E5133BB +PT=4F4AE38B53FD7800F0E9F5C214E16F2A + +I=13 +KEY=76AE1A703713961B3DE815F4A91AE8E6 +CT=4F4AE38B53FD7800F0E9F5C214E16F2A +PT=C73A033491DC0B6A77FEA2FBCC9D305E + +I=14 +KEY=B1941944A6CF9D714A16B70F6587D8B8 +CT=C73A033491DC0B6A77FEA2FBCC9D305E +PT=C928C2A05BB44816EFBE6B13E94BC70E + +I=15 +KEY=78BCDBE4FD7BD567A5A8DC1C8CCC1FB6 +CT=C928C2A05BB44816EFBE6B13E94BC70E +PT=A7C1593E7B4BAEE5256D4081337E7CAF + +I=16 +KEY=DF7D82DA86307B8280C59C9DBFB26319 +CT=A7C1593E7B4BAEE5256D4081337E7CAF +PT=7ECD305AC27AEBFA2B8F85F9AC312638 + +I=17 +KEY=A1B0B280444A9078AB4A196413834521 +CT=7ECD305AC27AEBFA2B8F85F9AC312638 +PT=A24D1403A58B94798F5F3565ABFD3B44 + +I=18 +KEY=03FDA683E1C1040124152C01B87E7E65 +CT=A24D1403A58B94798F5F3565ABFD3B44 +PT=5B6E097B3B0E21DCC9CE9970701C7BD5 + +I=19 +KEY=5893AFF8DACF25DDEDDBB571C86205B0 +CT=5B6E097B3B0E21DCC9CE9970701C7BD5 +PT=4E21CEA52B3111AC8F6B204A1F5E65E2 + +I=20 +KEY=16B2615DF1FE347162B0953BD73C6052 +CT=4E21CEA52B3111AC8F6B204A1F5E65E2 +PT=806DDC5C37ADEEBB6FCE4730939D7A99 + +I=21 +KEY=96DFBD01C653DACA0D7ED20B44A11ACB +CT=806DDC5C37ADEEBB6FCE4730939D7A99 +PT=3462F7C6D3E071A0D3ACE7FD79149776 + +I=22 +KEY=A2BD4AC715B3AB6ADED235F63DB58DBD +CT=3462F7C6D3E071A0D3ACE7FD79149776 +PT=AF0FFF307B72284E794C8A64C30299D2 + +I=23 +KEY=0DB2B5F76EC18324A79EBF92FEB7146F +CT=AF0FFF307B72284E794C8A64C30299D2 +PT=E482B613FBCF9C4422D85E3160B1FB0F + +I=24 +KEY=E93003E4950E1F608546E1A39E06EF60 +CT=E482B613FBCF9C4422D85E3160B1FB0F +PT=FADC8EF9C95540AD69897DECAB2D50D5 + +I=25 +KEY=13EC8D1D5C5B5FCDECCF9C4F352BBFB5 +CT=FADC8EF9C95540AD69897DECAB2D50D5 +PT=2A765E237FB5230D792D455596A17118 + +I=26 +KEY=399AD33E23EE7CC095E2D91AA38ACEAD +CT=2A765E237FB5230D792D455596A17118 +PT=0887DA8012C7F95BD6ADB18D1ED3C2DB + +I=27 +KEY=311D09BE3129859B434F6897BD590C76 +CT=0887DA8012C7F95BD6ADB18D1ED3C2DB +PT=3BB831A7B6FAC3649176471012FAD1C1 + +I=28 +KEY=0AA5381987D346FFD2392F87AFA3DDB7 +CT=3BB831A7B6FAC3649176471012FAD1C1 +PT=E4F8629AB3489A0945B8B7188B953DE5 + +I=29 +KEY=EE5D5A83349BDCF69781989F2436E052 +CT=E4F8629AB3489A0945B8B7188B953DE5 +PT=1D4B0B5B321EB711939AB481239E2541 + +I=30 +KEY=F31651D806856BE7041B2C1E07A8C513 +CT=1D4B0B5B321EB711939AB481239E2541 +PT=71A368D5A33665D6FF9F33FECAFC6884 + +I=31 +KEY=82B5390DA5B30E31FB841FE0CD54AD97 +CT=71A368D5A33665D6FF9F33FECAFC6884 +PT=8ACF418080075BA23B05A52552773B84 + +I=32 +KEY=087A788D25B45593C081BAC59F239613 +CT=8ACF418080075BA23B05A52552773B84 +PT=E0E6058735F4FE765E882521D769FB41 + +I=33 +KEY=E89C7D0A1040ABE59E099FE4484A6D52 +CT=E0E6058735F4FE765E882521D769FB41 +PT=70DCE91F818DF2CDC4269F1B4EA0A465 + +I=34 +KEY=9840941591CD59285A2F00FF06EAC937 +CT=70DCE91F818DF2CDC4269F1B4EA0A465 +PT=E2F809D6DD77D72EF6DB5A82C42BF1CF + +I=35 +KEY=7AB89DC34CBA8E06ACF45A7DC2C138F8 +CT=E2F809D6DD77D72EF6DB5A82C42BF1CF +PT=0741D11DDD877957E753ECF8DB91C72B + +I=36 +KEY=7DF94CDE913DF7514BA7B6851950FFD3 +CT=0741D11DDD877957E753ECF8DB91C72B +PT=03E411012CA3B5B3CC163677D4B52456 + +I=37 +KEY=7E1D5DDFBD9E42E287B180F2CDE5DB85 +CT=03E411012CA3B5B3CC163677D4B52456 +PT=0270D90790EF8347ACFB87EB2FEC2710 + +I=38 +KEY=7C6D84D82D71C1A52B4A0719E209FC95 +CT=0270D90790EF8347ACFB87EB2FEC2710 +PT=3AE40270512374AF4022638E0A7A6D8E + +I=39 +KEY=468986A87C52B50A6B686497E873911B +CT=3AE40270512374AF4022638E0A7A6D8E +PT=8008D87E928A980FECA08CAF1EC91DDA + +I=40 +KEY=C6815ED6EED82D0587C8E838F6BA8CC1 +CT=8008D87E928A980FECA08CAF1EC91DDA +PT=1D479A54832FF1A81D30008EFDF16A34 + +I=41 +KEY=DBC6C4826DF7DCAD9AF8E8B60B4BE6F5 +CT=1D479A54832FF1A81D30008EFDF16A34 +PT=9E731FECD9A767BDA0C84B4C4D552BD3 + +I=42 +KEY=45B5DB6EB450BB103A30A3FA461ECD26 +CT=9E731FECD9A767BDA0C84B4C4D552BD3 +PT=C2211A6B16CD27C6C73A5C3C1A0132AC + +I=43 +KEY=8794C105A29D9CD6FD0AFFC65C1FFF8A +CT=C2211A6B16CD27C6C73A5C3C1A0132AC +PT=7E523DD6F25706F971F020F88FFA0CF7 + +I=44 +KEY=F9C6FCD350CA9A2F8CFADF3ED3E5F37D +CT=7E523DD6F25706F971F020F88FFA0CF7 +PT=0EDC01C6C1A8DA6A7C9EEE3587CB098E + +I=45 +KEY=F71AFD1591624045F064310B542EFAF3 +CT=0EDC01C6C1A8DA6A7C9EEE3587CB098E +PT=EE479106871DA872632794633B1ACF0E + +I=46 +KEY=195D6C13167FE8379343A5686F3435FD +CT=EE479106871DA872632794633B1ACF0E +PT=7EC1A4578D911F336184DACCCA92D943 + +I=47 +KEY=679CC8449BEEF704F2C77FA4A5A6ECBE +CT=7EC1A4578D911F336184DACCCA92D943 +PT=53715F25AE02513F181E3DECBB007803 + +I=48 +KEY=34ED976135ECA63BEAD942481EA694BD +CT=53715F25AE02513F181E3DECBB007803 +PT=304D5764B5206F8204A69D1BED11FA62 + +I=49 +KEY=04A0C00580CCC9B9EE7FDF53F3B76EDF +CT=304D5764B5206F8204A69D1BED11FA62 +PT=5A7590ADEF208BFD808499A2BFE9B011 + +I=50 +KEY=5ED550A86FEC42446EFB46F14C5EDECE +CT=5A7590ADEF208BFD808499A2BFE9B011 +PT=2502C0F68A721A93ECE8D7B6C2097BA4 + +I=51 +KEY=7BD7905EE59E58D7821391478E57A56A +CT=2502C0F68A721A93ECE8D7B6C2097BA4 +PT=1C814E26A6464086D606C7B4C6DFD85B + +I=52 +KEY=6756DE7843D81851541556F348887D31 +CT=1C814E26A6464086D606C7B4C6DFD85B +PT=9D55D6EA99BA391190068205DD9AE69C + +I=53 +KEY=FA030892DA622140C413D4F695129BAD +CT=9D55D6EA99BA391190068205DD9AE69C +PT=9D1212D0BD8C26422EEFF4DDB16B2EF3 + +I=54 +KEY=67111A4267EE0702EAFC202B2479B55E +CT=9D1212D0BD8C26422EEFF4DDB16B2EF3 +PT=54DF71E70141E1712449CDC1AC7D07F6 + +I=55 +KEY=33CE6BA566AFE673CEB5EDEA8804B2A8 +CT=54DF71E70141E1712449CDC1AC7D07F6 +PT=AF3DE6F3510978928C129CFC19FB29B4 + +I=56 +KEY=9CF38D5637A69EE142A7711691FF9B1C +CT=AF3DE6F3510978928C129CFC19FB29B4 +PT=830DB7014774C7DF870C8456BC0162AB + +I=57 +KEY=1FFE3A5770D2593EC5ABF5402DFEF9B7 +CT=830DB7014774C7DF870C8456BC0162AB +PT=6606C0A36A18BEFF33485F95B82C30E7 + +I=58 +KEY=79F8FAF41ACAE7C1F6E3AAD595D2C950 +CT=6606C0A36A18BEFF33485F95B82C30E7 +PT=4B1E64672B89056DF693E73B419E786E + +I=59 +KEY=32E69E933143E2AC00704DEED44CB13E +CT=4B1E64672B89056DF693E73B419E786E +PT=1877DEEAFF10A5A3F5E9A811BF7595BA + +I=60 +KEY=2A914079CE53470FF599E5FF6B392484 +CT=1877DEEAFF10A5A3F5E9A811BF7595BA +PT=A11A48215BF59CC53BC8A009DCA3973D + +I=61 +KEY=8B8B085895A6DBCACE5145F6B79AB3B9 +CT=A11A48215BF59CC53BC8A009DCA3973D +PT=E80535676DE8898A3624B8127EC21024 + +I=62 +KEY=638E3D3FF84E5240F875FDE4C958A39D +CT=E80535676DE8898A3624B8127EC21024 +PT=E2977A804EC9A8B03C85234AD3A95B52 + +I=63 +KEY=811947BFB687FAF0C4F0DEAE1AF1F8CF +CT=E2977A804EC9A8B03C85234AD3A95B52 +PT=D776D8BF13F736483862328571C06C61 + +I=64 +KEY=566F9F00A570CCB8FC92EC2B6B3194AE +CT=D776D8BF13F736483862328571C06C61 +PT=3AF7969F3247A0914037209556997164 + +I=65 +KEY=6C98099F97376C29BCA5CCBE3DA8E5CA +CT=3AF7969F3247A0914037209556997164 +PT=4F87DDC715CEE3A9D67645AD920DF74A + +I=66 +KEY=231FD45882F98F806AD38913AFA51280 +CT=4F87DDC715CEE3A9D67645AD920DF74A +PT=9E88CA52E6B0C160E52B23F36882DBA1 + +I=67 +KEY=BD971E0A64494EE08FF8AAE0C727C921 +CT=9E88CA52E6B0C160E52B23F36882DBA1 +PT=CAD26E5881D9D4E52C7595C773E0FDAB + +I=68 +KEY=77457052E5909A05A38D3F27B4C7348A +CT=CAD26E5881D9D4E52C7595C773E0FDAB +PT=C2D0B3D713CFCA5ABB7B9DED14429F37 + +I=69 +KEY=B595C385F65F505F18F6A2CAA085ABBD +CT=C2D0B3D713CFCA5ABB7B9DED14429F37 +PT=DD7AADA7524A4878F7C598C4CBCD9CAB + +I=70 +KEY=68EF6E22A4151827EF333A0E6B483716 +CT=DD7AADA7524A4878F7C598C4CBCD9CAB +PT=A0F33B1FCC3F4A4B0982F0823C4ED3C9 + +I=71 +KEY=C81C553D682A526CE6B1CA8C5706E4DF +CT=A0F33B1FCC3F4A4B0982F0823C4ED3C9 +PT=B22BB23CD68E8779A8C0FC9A350CB756 + +I=72 +KEY=7A37E701BEA4D5154E713616620A5389 +CT=B22BB23CD68E8779A8C0FC9A350CB756 +PT=EA4D96AC54BD8387AD36AC8C855A9D44 + +I=73 +KEY=907A71ADEA195692E3479A9AE750CECD +CT=EA4D96AC54BD8387AD36AC8C855A9D44 +PT=A3B90CFDE355723BC94999784534FA74 + +I=74 +KEY=33C37D50094C24A92A0E03E2A26434B9 +CT=A3B90CFDE355723BC94999784534FA74 +PT=55636C86A64383768CB948FF57B29322 + +I=75 +KEY=66A011D6AF0FA7DFA6B74B1DF5D6A79B +CT=55636C86A64383768CB948FF57B29322 +PT=B29CCDFD8E7BE50892F0D77DD969F97E + +I=76 +KEY=D43CDC2B217442D734479C602CBF5EE5 +CT=B29CCDFD8E7BE50892F0D77DD969F97E +PT=9CF0432822EABDF489B57EDD9CEF7FEA + +I=77 +KEY=48CC9F03039EFF23BDF2E2BDB050210F +CT=9CF0432822EABDF489B57EDD9CEF7FEA +PT=AA753B7D38E807D691005899385DC6DA + +I=78 +KEY=E2B9A47E3B76F8F52CF2BA24880DE7D5 +CT=AA753B7D38E807D691005899385DC6DA +PT=E4F0681527FA7AD3D1E7C78C03FB79FA + +I=79 +KEY=0649CC6B1C8C8226FD157DA88BF69E2F +CT=E4F0681527FA7AD3D1E7C78C03FB79FA +PT=7923AF8E50F378B9C97D2F162348025B + +I=80 +KEY=7F6A63E54C7FFA9F346852BEA8BE9C74 +CT=7923AF8E50F378B9C97D2F162348025B +PT=3BEFAB920CA31A6B8B87E11DF97B42DE + +I=81 +KEY=4485C87740DCE0F4BFEFB3A351C5DEAA +CT=3BEFAB920CA31A6B8B87E11DF97B42DE +PT=4661D6B8004611976A21C69804D102C0 + +I=82 +KEY=02E41ECF409AF163D5CE753B5514DC6A +CT=4661D6B8004611976A21C69804D102C0 +PT=B861DF2279F2AEE4FCFD7D322AD0BE2B + +I=83 +KEY=BA85C1ED39685F87293308097FC46241 +CT=B861DF2279F2AEE4FCFD7D322AD0BE2B +PT=1785745618A541F9454443FFB494F2E9 + +I=84 +KEY=AD00B5BB21CD1E7E6C774BF6CB5090A8 +CT=1785745618A541F9454443FFB494F2E9 +PT=AA7507A80B4CCF33E8B4F09E2D7004F6 + +I=85 +KEY=0775B2132A81D14D84C3BB68E620945E +CT=AA7507A80B4CCF33E8B4F09E2D7004F6 +PT=433412B8F10F81A557AC461823097FC7 + +I=86 +KEY=4441A0ABDB8E50E8D36FFD70C529EB99 +CT=433412B8F10F81A557AC461823097FC7 +PT=EC3206BDB3765876B74952C411D40373 + +I=87 +KEY=A873A61668F8089E6426AFB4D4FDE8EA +CT=EC3206BDB3765876B74952C411D40373 +PT=F7F994027D328FA3D70C9DEABD3BE733 + +I=88 +KEY=5F8A321415CA873DB32A325E69C60FD9 +CT=F7F994027D328FA3D70C9DEABD3BE733 +PT=E2A8419BF86A2408ED8D0274A5CE0E10 + +I=89 +KEY=BD22738FEDA0A3355EA7302ACC0801C9 +CT=E2A8419BF86A2408ED8D0274A5CE0E10 +PT=80FB8CD5243C89D77F503B2F16979F90 + +I=90 +KEY=3DD9FF5AC99C2AE221F70B05DA9F9E59 +CT=80FB8CD5243C89D77F503B2F16979F90 +PT=F7773137F233AE2609C2C9AC36F58224 + +I=91 +KEY=CAAECE6D3BAF84C42835C2A9EC6A1C7D +CT=F7773137F233AE2609C2C9AC36F58224 +PT=F3D0A1DADA4A009E8E4C0EF717469BCD + +I=92 +KEY=397E6FB7E1E5845AA679CC5EFB2C87B0 +CT=F3D0A1DADA4A009E8E4C0EF717469BCD +PT=0AC0FF22EB653A26A3F1F0CFE3808609 + +I=93 +KEY=33BE90950A80BE7C05883C9118AC01B9 +CT=0AC0FF22EB653A26A3F1F0CFE3808609 +PT=28FF865CE11720BB1B56EF49D7D1840D + +I=94 +KEY=1B4116C9EB979EC71EDED3D8CF7D85B4 +CT=28FF865CE11720BB1B56EF49D7D1840D +PT=001FAF58E22F5E8ED6BCC7FD581D7C2F + +I=95 +KEY=1B5EB99109B8C049C86214259760F99B +CT=001FAF58E22F5E8ED6BCC7FD581D7C2F +PT=32B41303A58AB49CB4CB2322B77383B3 + +I=96 +KEY=29EAAA92AC3274D57CA9370720137A28 +CT=32B41303A58AB49CB4CB2322B77383B3 +PT=9C52020FCDE0306C8E19CDF68FEFDF50 + +I=97 +KEY=B5B8A89D61D244B9F2B0FAF1AFFCA578 +CT=9C52020FCDE0306C8E19CDF68FEFDF50 +PT=2E3452997687D12E3A8C59B9178B09E2 + +I=98 +KEY=9B8CFA0417559597C83CA348B877AC9A +CT=2E3452997687D12E3A8C59B9178B09E2 +PT=872CF16DBB7CD6EA8EBB91A60BDE0C6F + +I=99 +KEY=1CA00B69AC29437D468732EEB3A9A0F5 +CT=872CF16DBB7CD6EA8EBB91A60BDE0C6F +PT=7862C78E3B209535E6C6BE92F5EDF42B + +I=100 +KEY=64C2CCE79709D648A0418C7C464454DE +CT=7862C78E3B209535E6C6BE92F5EDF42B +PT=9185D8487C1D2DB679A52FDA2FE5FFCD + +I=101 +KEY=F54714AFEB14FBFED9E4A3A669A1AB13 +CT=9185D8487C1D2DB679A52FDA2FE5FFCD +PT=77C3AF8C81CDB1CDEF5C0429CF3E5DA4 + +I=102 +KEY=8284BB236AD94A3336B8A78FA69FF6B7 +CT=77C3AF8C81CDB1CDEF5C0429CF3E5DA4 +PT=6F36C74290EA6332E98CD23D08AEF7F9 + +I=103 +KEY=EDB27C61FA332901DF3475B2AE31014E +CT=6F36C74290EA6332E98CD23D08AEF7F9 +PT=4A7831538FA1D32E3F8631BEFD99AA73 + +I=104 +KEY=A7CA4D327592FA2FE0B2440C53A8AB3D +CT=4A7831538FA1D32E3F8631BEFD99AA73 +PT=5D2B599D9AF9054A99C25577C9286C9E + +I=105 +KEY=FAE114AFEF6BFF657970117B9A80C7A3 +CT=5D2B599D9AF9054A99C25577C9286C9E +PT=65E4088200BCC01FCEE39C6E42082FD8 + +I=106 +KEY=9F051C2DEFD73F7AB7938D15D888E87B +CT=65E4088200BCC01FCEE39C6E42082FD8 +PT=4588E0D3AABBEFE611B9576391B903E9 + +I=107 +KEY=DA8DFCFE456CD09CA62ADA764931EB92 +CT=4588E0D3AABBEFE611B9576391B903E9 +PT=A55622F833FF271DD8A8F01CF5828FCF + +I=108 +KEY=7FDBDE067693F7817E822A6ABCB3645D +CT=A55622F833FF271DD8A8F01CF5828FCF +PT=8C954010C870B2DB7FA44E1DEBFE6DE8 + +I=109 +KEY=F34E9E16BEE3455A01266477574D09B5 +CT=8C954010C870B2DB7FA44E1DEBFE6DE8 +PT=58B7BD00ED18FC81E618807DE65305B8 + +I=110 +KEY=ABF9231653FBB9DBE73EE40AB11E0C0D +CT=58B7BD00ED18FC81E618807DE65305B8 +PT=EF82E5F4879039F2A1A4CC2F2044BD14 + +I=111 +KEY=447BC6E2D46B8029469A2825915AB119 +CT=EF82E5F4879039F2A1A4CC2F2044BD14 +PT=2B6C12307F14FD50B41D8F972B19AC76 + +I=112 +KEY=6F17D4D2AB7F7D79F287A7B2BA431D6F +CT=2B6C12307F14FD50B41D8F972B19AC76 +PT=C9B6D042CE76892D17F70D4EE00A0D79 + +I=113 +KEY=A6A104906509F454E570AAFC5A491016 +CT=C9B6D042CE76892D17F70D4EE00A0D79 +PT=1B08F9293BBFC44DDCF2C1D26A9DD00B + +I=114 +KEY=BDA9FDB95EB6301939826B2E30D4C01D +CT=1B08F9293BBFC44DDCF2C1D26A9DD00B +PT=4FD353B247048FAAA728E10C691C70CA + +I=115 +KEY=F27AAE0B19B2BFB39EAA8A2259C8B0D7 +CT=4FD353B247048FAAA728E10C691C70CA +PT=0BBB6FDBC62C428B85111BC7C93AE994 + +I=116 +KEY=F9C1C1D0DF9EFD381BBB91E590F25943 +CT=0BBB6FDBC62C428B85111BC7C93AE994 +PT=9C1A213A5772DE6C15CE7406F84BED03 + +I=117 +KEY=65DBE0EA88EC23540E75E5E368B9B440 +CT=9C1A213A5772DE6C15CE7406F84BED03 +PT=AB3DE06BBDB213D64F735CA990DC373C + +I=118 +KEY=CEE60081355E30824106B94AF865837C +CT=AB3DE06BBDB213D64F735CA990DC373C +PT=6C004A1A114E90C7903AA4A0120A2B10 + +I=119 +KEY=A2E64A9B2410A045D13C1DEAEA6FA86C +CT=6C004A1A114E90C7903AA4A0120A2B10 +PT=6405A033C294E72119A8955712548121 + +I=120 +KEY=C6E3EAA8E6844764C89488BDF83B294D +CT=6405A033C294E72119A8955712548121 +PT=AE8A3BAC7279B1BC152A5AD8EBAC3EAD + +I=121 +KEY=6869D10494FDF6D8DDBED265139717E0 +CT=AE8A3BAC7279B1BC152A5AD8EBAC3EAD +PT=4ADDA9999D2BE20D8925F39699563294 + +I=122 +KEY=22B4789D09D614D5549B21F38AC12574 +CT=4ADDA9999D2BE20D8925F39699563294 +PT=BC5CA33CB2A1A580EB92946C77A63467 + +I=123 +KEY=9EE8DBA1BB77B155BF09B59FFD671113 +CT=BC5CA33CB2A1A580EB92946C77A63467 +PT=F7ABEAD301264A3E59EABA0B9606DC92 + +I=124 +KEY=69433172BA51FB6BE6E30F946B61CD81 +CT=F7ABEAD301264A3E59EABA0B9606DC92 +PT=2566114A10BE9BF19E0910486DAB6BE5 + +I=125 +KEY=4C252038AAEF609A78EA1FDC06CAA664 +CT=2566114A10BE9BF19E0910486DAB6BE5 +PT=AF72E1B179660A1B833D9D4FC8473B6B + +I=126 +KEY=E357C189D3896A81FBD78293CE8D9D0F +CT=AF72E1B179660A1B833D9D4FC8473B6B +PT=DFF968B761D8E154B74C9D568C12008E + +I=127 +KEY=3CAEA93EB2518BD54C9B1FC5429F9D81 +CT=DFF968B761D8E154B74C9D568C12008E +PT=42DF098BCB57D0D25269E29C9BC99DE6 + +I=128 +KEY=7E71A0B579065B071EF2FD59D9560067 +CT=42DF098BCB57D0D25269E29C9BC99DE6 +PT=66C34CAAEFC2009B985D1E622FC61AB4 + +I=129 +KEY=18B2EC1F96C45B9C86AFE33BF6901AD3 +CT=66C34CAAEFC2009B985D1E622FC61AB4 +PT=150C1BF943982C5EA1A6839D94F23288 + +I=130 +KEY=0DBEF7E6D55C77C2270960A66262285B +CT=150C1BF943982C5EA1A6839D94F23288 +PT=048BFBB28879206964C5F3B41264011A + +I=131 +KEY=09350C545D2557AB43CC931270062941 +CT=048BFBB28879206964C5F3B41264011A +PT=54D2DC53B87EC949F0FA0E134EE26D50 + +I=132 +KEY=5DE7D007E55B9EE2B3369D013EE44411 +CT=54D2DC53B87EC949F0FA0E134EE26D50 +PT=1BA46AFE1AE87C4F0254BF02DF3B6D37 + +I=133 +KEY=4643BAF9FFB3E2ADB1622203E1DF2926 +CT=1BA46AFE1AE87C4F0254BF02DF3B6D37 +PT=7733E74E743C9E997AC2ED36B2E89CE8 + +I=134 +KEY=31705DB78B8F7C34CBA0CF355337B5CE +CT=7733E74E743C9E997AC2ED36B2E89CE8 +PT=670AEA160FAC67ABCECA140EB8195EB5 + +I=135 +KEY=567AB7A184231B9F056ADB3BEB2EEB7B +CT=670AEA160FAC67ABCECA140EB8195EB5 +PT=7CFD74D510AC894FF5B698280386F4FF + +I=136 +KEY=2A87C374948F92D0F0DC4313E8A81F84 +CT=7CFD74D510AC894FF5B698280386F4FF +PT=10D03F32C0694E9FFF598E101998105E + +I=137 +KEY=3A57FC4654E6DC4F0F85CD03F1300FDA +CT=10D03F32C0694E9FFF598E101998105E +PT=351D6E8D1C26F36973356F6235B8ABAD + +I=138 +KEY=0F4A92CB48C02F267CB0A261C488A477 +CT=351D6E8D1C26F36973356F6235B8ABAD +PT=0DDDA7AA09FBD986C0B9EA2B018FAE4F + +I=139 +KEY=02973561413BF6A0BC09484AC5070A38 +CT=0DDDA7AA09FBD986C0B9EA2B018FAE4F +PT=31C5B68B7A08D1B7320FAB052CC3B0D1 + +I=140 +KEY=335283EA3B3327178E06E34FE9C4BAE9 +CT=31C5B68B7A08D1B7320FAB052CC3B0D1 +PT=501B8D9EE91468522029020A39484DB5 + +I=141 +KEY=63490E74D2274F45AE2FE145D08CF75C +CT=501B8D9EE91468522029020A39484DB5 +PT=2714FBA566DFD4909B8ABF29B1D5A8E8 + +I=142 +KEY=445DF5D1B4F89BD535A55E6C61595FB4 +CT=2714FBA566DFD4909B8ABF29B1D5A8E8 +PT=94485381E5088D67BC1335C89FA5C2B8 + +I=143 +KEY=D015A65051F016B289B66BA4FEFC9D0C +CT=94485381E5088D67BC1335C89FA5C2B8 +PT=BE5BEE26D6686A0EB5838C237FEF79B7 + +I=144 +KEY=6E4E487687987CBC3C35E7878113E4BB +CT=BE5BEE26D6686A0EB5838C237FEF79B7 +PT=417F73D46CFBE3C5C9AD513BCBC6D185 + +I=145 +KEY=2F313BA2EB639F79F598B6BC4AD5353E +CT=417F73D46CFBE3C5C9AD513BCBC6D185 +PT=AE3B07350B3BE7D4F9F6FE2F95622449 + +I=146 +KEY=810A3C97E05878AD0C6E4893DFB71177 +CT=AE3B07350B3BE7D4F9F6FE2F95622449 +PT=7BD4231225A7B665953AB034E24A7C7A + +I=147 +KEY=FADE1F85C5FFCEC89954F8A73DFD6D0D +CT=7BD4231225A7B665953AB034E24A7C7A +PT=3C1FBE8F3CEB1438B4A64E59FAF291CF + +I=148 +KEY=C6C1A10AF914DAF02DF2B6FEC70FFCC2 +CT=3C1FBE8F3CEB1438B4A64E59FAF291CF +PT=ACFF7F1E71AA952CF8ADB24FEE18A7BB + +I=149 +KEY=6A3EDE1488BE4FDCD55F04B129175B79 +CT=ACFF7F1E71AA952CF8ADB24FEE18A7BB +PT=3C3A6D3FD73B36317417106A92E2B43E + +I=150 +KEY=5604B32B5F8579EDA14814DBBBF5EF47 +CT=3C3A6D3FD73B36317417106A92E2B43E +PT=F34F8C719A4A74DD8F4FA4CBC520827A + +I=151 +KEY=A54B3F5AC5CF0D302E07B0107ED56D3D +CT=F34F8C719A4A74DD8F4FA4CBC520827A +PT=6A5D56FB6C7EBA15112AF8A093F3E1E1 + +I=152 +KEY=CF1669A1A9B1B7253F2D48B0ED268CDC +CT=6A5D56FB6C7EBA15112AF8A093F3E1E1 +PT=8BF39EE3B8ED0F6A6EA92319A81B10E6 + +I=153 +KEY=44E5F742115CB84F51846BA9453D9C3A +CT=8BF39EE3B8ED0F6A6EA92319A81B10E6 +PT=2BC796D320C444BBBAD466D686F460F6 + +I=154 +KEY=6F2261913198FCF4EB500D7FC3C9FCCC +CT=2BC796D320C444BBBAD466D686F460F6 +PT=2CF595F424ED50B1A146E387B128CBA3 + +I=155 +KEY=43D7F4651575AC454A16EEF872E1376F +CT=2CF595F424ED50B1A146E387B128CBA3 +PT=56F2E856045BAE66EA003A6C39205344 + +I=156 +KEY=15251C33112E0223A016D4944BC1642B +CT=56F2E856045BAE66EA003A6C39205344 +PT=31C83401BD83424BA6E94C0D6D453D9A + +I=157 +KEY=24ED2832ACAD406806FF9899268459B1 +CT=31C83401BD83424BA6E94C0D6D453D9A +PT=A687F05992CCB57CDE61AFF8878913ED + +I=158 +KEY=826AD86B3E61F514D89E3761A10D4A5C +CT=A687F05992CCB57CDE61AFF8878913ED +PT=16E771193C2473502F415C27FB101D94 + +I=159 +KEY=948DA97202458644F7DF6B465A1D57C8 +CT=16E771193C2473502F415C27FB101D94 +PT=C69CDBA29C9EDC3407C1C73A756A0B6E + +I=160 +KEY=521172D09EDB5A70F01EAC7C2F775CA6 +CT=C69CDBA29C9EDC3407C1C73A756A0B6E +PT=566D82281F48E3217F3852115CF2E944 + +I=161 +KEY=047CF0F88193B9518F26FE6D7385B5E2 +CT=566D82281F48E3217F3852115CF2E944 +PT=B3FEBC8F8F0F0B652C4358BCC9BF54DF + +I=162 +KEY=B7824C770E9CB234A365A6D1BA3AE13D +CT=B3FEBC8F8F0F0B652C4358BCC9BF54DF +PT=BBB84877094B3EB86203D17C92CF5168 + +I=163 +KEY=0C3A040007D78C8CC16677AD28F5B055 +CT=BBB84877094B3EB86203D17C92CF5168 +PT=2C45E5A3F8C564862DA4D8AD428D3E67 + +I=164 +KEY=207FE1A3FF12E80AECC2AF006A788E32 +CT=2C45E5A3F8C564862DA4D8AD428D3E67 +PT=10ADC2AF56600D95AD8BB579EF5170C9 + +I=165 +KEY=30D2230CA972E59F41491A798529FEFB +CT=10ADC2AF56600D95AD8BB579EF5170C9 +PT=1854BB8AC568F3599153BE1AC60BA78D + +I=166 +KEY=288698866C1A16C6D01AA46343225976 +CT=1854BB8AC568F3599153BE1AC60BA78D +PT=E641765C80D8812A1A0F4606C639642E + +I=167 +KEY=CEC7EEDAECC297ECCA15E265851B3D58 +CT=E641765C80D8812A1A0F4606C639642E +PT=317AC70CEAA87AE66A15C22BD5E534E5 + +I=168 +KEY=FFBD29D6066AED0AA000204E50FE09BD +CT=317AC70CEAA87AE66A15C22BD5E534E5 +PT=BFFB8D7B3D9F54727944ABC3F6474362 + +I=169 +KEY=4046A4AD3BF5B978D9448B8DA6B94ADF +CT=BFFB8D7B3D9F54727944ABC3F6474362 +PT=060765D1D9D289B862DA274CFDB4D7A0 + +I=170 +KEY=4641C17CE22730C0BB9EACC15B0D9D7F +CT=060765D1D9D289B862DA274CFDB4D7A0 +PT=FBAFA4C1D6CEF2A45E9E084311FDF858 + +I=171 +KEY=BDEE65BD34E9C264E500A4824AF06527 +CT=FBAFA4C1D6CEF2A45E9E084311FDF858 +PT=F7F36BFDA77362B470B0B074241C58E9 + +I=172 +KEY=4A1D0E40939AA0D095B014F66EEC3DCE +CT=F7F36BFDA77362B470B0B074241C58E9 +PT=2FC236EDCD573A6DCFBA7930E9CF4698 + +I=173 +KEY=65DF38AD5ECD9ABD5A0A6DC687237B56 +CT=2FC236EDCD573A6DCFBA7930E9CF4698 +PT=949A9994DC976595BFACA5F31116A165 + +I=174 +KEY=F145A139825AFF28E5A6C8359635DA33 +CT=949A9994DC976595BFACA5F31116A165 +PT=19373CA9D519BF83EAA4C17E1EE8225C + +I=175 +KEY=E8729D90574340AB0F02094B88DDF86F +CT=19373CA9D519BF83EAA4C17E1EE8225C +PT=685C783918997A7572B0A09315F1F2DB + +I=176 +KEY=802EE5A94FDA3ADE7DB2A9D89D2C0AB4 +CT=685C783918997A7572B0A09315F1F2DB +PT=FC0CB1792EADB7E8DECB021A435DE1E7 + +I=177 +KEY=7C2254D061778D36A379ABC2DE71EB53 +CT=FC0CB1792EADB7E8DECB021A435DE1E7 +PT=797C5E5B4F3B38E7C72FF7AAAB270E86 + +I=178 +KEY=055E0A8B2E4CB5D164565C687556E5D5 +CT=797C5E5B4F3B38E7C72FF7AAAB270E86 +PT=A5AB675262EA186F777681647B6AA1F9 + +I=179 +KEY=A0F56DD94CA6ADBE1320DD0C0E3C442C +CT=A5AB675262EA186F777681647B6AA1F9 +PT=08CDF6AF55BBB247D0DE1A69CD041A78 + +I=180 +KEY=A8389B76191D1FF9C3FEC765C3385E54 +CT=08CDF6AF55BBB247D0DE1A69CD041A78 +PT=DED1F3C30AB5EC3455C7B6A756E5FF03 + +I=181 +KEY=76E968B513A8F3CD963971C295DDA157 +CT=DED1F3C30AB5EC3455C7B6A756E5FF03 +PT=C759A17B354D668D1BA5541D16241D9F + +I=182 +KEY=B1B0C9CE26E595408D9C25DF83F9BCC8 +CT=C759A17B354D668D1BA5541D16241D9F +PT=97E011FE7B327B8292270D4CD18BD9AC + +I=183 +KEY=2650D8305DD7EEC21FBB289352726564 +CT=97E011FE7B327B8292270D4CD18BD9AC +PT=9F004E4282F790C06681F16262EF78CF + +I=184 +KEY=B9509672DF207E02793AD9F1309D1DAB +CT=9F004E4282F790C06681F16262EF78CF +PT=6B34AA95EFD874915DAE275CE34A04B9 + +I=185 +KEY=D2643CE730F80A932494FEADD3D71912 +CT=6B34AA95EFD874915DAE275CE34A04B9 +PT=96966D118C50B67849F93B109492B5EB + +I=186 +KEY=44F251F6BCA8BCEB6D6DC5BD4745ACF9 +CT=96966D118C50B67849F93B109492B5EB +PT=2CA6F85E4F29BE884392A0FEDD08D5A7 + +I=187 +KEY=6854A9A8F38102632EFF65439A4D795E +CT=2CA6F85E4F29BE884392A0FEDD08D5A7 +PT=21B71D4F23DDC002CAAFB7426009BD27 + +I=188 +KEY=49E3B4E7D05CC261E450D201FA44C479 +CT=21B71D4F23DDC002CAAFB7426009BD27 +PT=BF059F1945E9E51B22B308849757B475 + +I=189 +KEY=F6E62BFE95B5277AC6E3DA856D13700C +CT=BF059F1945E9E51B22B308849757B475 +PT=434F4E756A3178472E12B80A1C2ED83E + +I=190 +KEY=B5A9658BFF845F3DE8F1628F713DA832 +CT=434F4E756A3178472E12B80A1C2ED83E +PT=37DB2B0D5967700CDE348FB60661A6D4 + +I=191 +KEY=82724E86A6E32F3136C5ED39775C0EE6 +CT=37DB2B0D5967700CDE348FB60661A6D4 +PT=D31C5130F8F217AC0014B5F37B9BB86B + +I=192 +KEY=516E1FB65E11389D36D158CA0CC7B68D +CT=D31C5130F8F217AC0014B5F37B9BB86B +PT=3B8CD15967907F9C617697EBEF395B16 + +I=193 +KEY=6AE2CEEF3981470157A7CF21E3FEED9B +CT=3B8CD15967907F9C617697EBEF395B16 +PT=AF17B5E5236BF46576379CD4E5AF8A34 + +I=194 +KEY=C5F57B0A1AEAB364219053F5065167AF +CT=AF17B5E5236BF46576379CD4E5AF8A34 +PT=88286D6FB237181EC239C1D70C0D6675 + +I=195 +KEY=4DDD1665A8DDAB7AE3A992220A5C01DA +CT=88286D6FB237181EC239C1D70C0D6675 +PT=8A5207BB1283343B3692045183451A7D + +I=196 +KEY=C78F11DEBA5E9F41D53B967389191BA7 +CT=8A5207BB1283343B3692045183451A7D +PT=53C12FAC4B0185AA0CE067FC67EC5B9C + +I=197 +KEY=944E3E72F15F1AEBD9DBF18FEEF5403B +CT=53C12FAC4B0185AA0CE067FC67EC5B9C +PT=BBA2BB9B1CA48D2E97E0C39E500EB9C0 + +I=198 +KEY=2FEC85E9EDFB97C54E3B3211BEFBF9FB +CT=BBA2BB9B1CA48D2E97E0C39E500EB9C0 +PT=8BA2341064B7B5184CD7E7A40FA0358E + +I=199 +KEY=A44EB1F9894C22DD02ECD5B5B15BCC75 +CT=8BA2341064B7B5184CD7E7A40FA0358E +PT=97121EEEA68CC6200FBC0B311849E625 + +I=200 +KEY=335CAF172FC0E4FD0D50DE84A9122A50 +CT=97121EEEA68CC6200FBC0B311849E625 +PT=027FA370A9412B342043A15F19294961 + +I=201 +KEY=31230C678681CFC92D137FDBB03B6331 +CT=027FA370A9412B342043A15F19294961 +PT=72CFBE6BA03AB28A53A6727717D1199A + +I=202 +KEY=43ECB20C26BB7D437EB50DACA7EA7AAB +CT=72CFBE6BA03AB28A53A6727717D1199A +PT=7A15B1B4B4ED35F9C208500FE7C4C1C7 + +I=203 +KEY=39F903B8925648BABCBD5DA3402EBB6C +CT=7A15B1B4B4ED35F9C208500FE7C4C1C7 +PT=AF46496D09254FAB5F381E93EEB4FBB0 + +I=204 +KEY=96BF4AD59B730711E3854330AE9A40DC +CT=AF46496D09254FAB5F381E93EEB4FBB0 +PT=ADA064E0F4324E8B0C062F6E33C7D016 + +I=205 +KEY=3B1F2E356F41499AEF836C5E9D5D90CA +CT=ADA064E0F4324E8B0C062F6E33C7D016 +PT=7723A61733BD5BBFAB8C559ED379B8B5 + +I=206 +KEY=4C3C88225CFC1225440F39C04E24287F +CT=7723A61733BD5BBFAB8C559ED379B8B5 +PT=5D210E8F35DD863316E89FADA70E8392 + +I=207 +KEY=111D86AD6921941652E7A66DE92AABED +CT=5D210E8F35DD863316E89FADA70E8392 +PT=92B1D20E7D87787950990052DE2ABA4F + +I=208 +KEY=83AC54A314A6EC6F027EA63F370011A2 +CT=92B1D20E7D87787950990052DE2ABA4F +PT=178E494D23AA6AC13AC180727C47FD2A + +I=209 +KEY=94221DEE370C86AE38BF264D4B47EC88 +CT=178E494D23AA6AC13AC180727C47FD2A +PT=CB9C10817C059D5BE4F123576FF459C6 + +I=210 +KEY=5FBE0D6F4B091BF5DC4E051A24B3B54E +CT=CB9C10817C059D5BE4F123576FF459C6 +PT=4934C56CC7BAF0A8DEBB62CFB2B0DEBF + +I=211 +KEY=168AC8038CB3EB5D02F567D596036BF1 +CT=4934C56CC7BAF0A8DEBB62CFB2B0DEBF +PT=F6F2A4B90B357D88401702C968D9EC02 + +I=212 +KEY=E0786CBA878696D542E2651CFEDA87F3 +CT=F6F2A4B90B357D88401702C968D9EC02 +PT=06A35CAD7B36751BEE345C33112EB6D1 + +I=213 +KEY=E6DB3017FCB0E3CEACD6392FEFF43122 +CT=06A35CAD7B36751BEE345C33112EB6D1 +PT=3244CDE10DF48795DA702CD8C2F4CABD + +I=214 +KEY=D49FFDF6F144645B76A615F72D00FB9F +CT=3244CDE10DF48795DA702CD8C2F4CABD +PT=47C06F5BEA8C3503512E0E200966C546 + +I=215 +KEY=935F92AD1BC8515827881BD724663ED9 +CT=47C06F5BEA8C3503512E0E200966C546 +PT=68A077D25CBEA7F76B88D8C6A414D0CE + +I=216 +KEY=FBFFE57F4776F6AF4C00C3118072EE17 +CT=68A077D25CBEA7F76B88D8C6A414D0CE +PT=DDF110C2C79B46C5132CCEF654280D7E + +I=217 +KEY=260EF5BD80EDB06A5F2C0DE7D45AE369 +CT=DDF110C2C79B46C5132CCEF654280D7E +PT=0AB610A0082813076D052011C12DC924 + +I=218 +KEY=2CB8E51D88C5A36D32292DF615772A4D +CT=0AB610A0082813076D052011C12DC924 +PT=8C42F49EDAE1BD6B631E74B68B1B8444 + +I=219 +KEY=A0FA118352241E06513759409E6CAE09 +CT=8C42F49EDAE1BD6B631E74B68B1B8444 +PT=B5A5B6E50B3A066D16DF883F353019FE + +I=220 +KEY=155FA766591E186B47E8D17FAB5CB7F7 +CT=B5A5B6E50B3A066D16DF883F353019FE +PT=70CFA25AFC9919937E2FC90900F0B398 + +I=221 +KEY=6590053CA58701F839C71876ABAC046F +CT=70CFA25AFC9919937E2FC90900F0B398 +PT=B927A5911AE33DEAB619DAFEE22CD0DF + +I=222 +KEY=DCB7A0ADBF643C128FDEC2884980D4B0 +CT=B927A5911AE33DEAB619DAFEE22CD0DF +PT=10C548438C5B976EDD624129B2102D7A + +I=223 +KEY=CC72E8EE333FAB7C52BC83A1FB90F9CA +CT=10C548438C5B976EDD624129B2102D7A +PT=4549E45DA2F8FE82972DC7DF3548CAFF + +I=224 +KEY=893B0CB391C755FEC591447ECED83335 +CT=4549E45DA2F8FE82972DC7DF3548CAFF +PT=2B85505E64089FEB6B5763011E778C96 + +I=225 +KEY=A2BE5CEDF5CFCA15AEC6277FD0AFBFA3 +CT=2B85505E64089FEB6B5763011E778C96 +PT=4B157930F9A6EBE3D9D6AC9FADDEB35C + +I=226 +KEY=E9AB25DD0C6921F677108BE07D710CFF +CT=4B157930F9A6EBE3D9D6AC9FADDEB35C +PT=12341C0FE9EB6757BFFCC4BC1A8F2585 + +I=227 +KEY=FB9F39D2E58246A1C8EC4F5C67FE297A +CT=12341C0FE9EB6757BFFCC4BC1A8F2585 +PT=5422D62D794B02FC04BE01198EE23ACE + +I=228 +KEY=AFBDEFFF9CC9445DCC524E45E91C13B4 +CT=5422D62D794B02FC04BE01198EE23ACE +PT=42D43022FD6DB571BCB2FDE653C9068C + +I=229 +KEY=ED69DFDD61A4F12C70E0B3A3BAD51538 +CT=42D43022FD6DB571BCB2FDE653C9068C +PT=80BD3AAED5D519B75D22BF060EF1DFC6 + +I=230 +KEY=6DD4E573B471E89B2DC20CA5B424CAFE +CT=80BD3AAED5D519B75D22BF060EF1DFC6 +PT=B72973F9016A348CDDCCFFC2DD291B5A + +I=231 +KEY=DAFD968AB51BDC17F00EF367690DD1A4 +CT=B72973F9016A348CDDCCFFC2DD291B5A +PT=5692E61C86A7B2C043ABBED712390361 + +I=232 +KEY=8C6F709633BC6ED7B3A54DB07B34D2C5 +CT=5692E61C86A7B2C043ABBED712390361 +PT=75138737269AA27855C2CFD2DCEDEFC4 + +I=233 +KEY=F97CF7A11526CCAFE6678262A7D93D01 +CT=75138737269AA27855C2CFD2DCEDEFC4 +PT=A022AA28CECC4BB5EB28BA5B7828AB6E + +I=234 +KEY=595E5D89DBEA871A0D4F3839DFF1966F +CT=A022AA28CECC4BB5EB28BA5B7828AB6E +PT=17B0BF87EE02AA44705B1B1B4DF7D3F4 + +I=235 +KEY=4EEEE20E35E82D5E7D1423229206459B +CT=17B0BF87EE02AA44705B1B1B4DF7D3F4 +PT=095A5A041C43DCFEB5D0DF3E7659344A + +I=236 +KEY=47B4B80A29ABF1A0C8C4FC1CE45F71D1 +CT=095A5A041C43DCFEB5D0DF3E7659344A +PT=9DCE0D1C572509F3367EE952B89044E5 + +I=237 +KEY=DA7AB5167E8EF853FEBA154E5CCF3534 +CT=9DCE0D1C572509F3367EE952B89044E5 +PT=E6075BCC82399A91E52034EA2F197058 + +I=238 +KEY=3C7DEEDAFCB762C21B9A21A473D6456C +CT=E6075BCC82399A91E52034EA2F197058 +PT=431D243CEE96B424B0FA4FEC5E707036 + +I=239 +KEY=7F60CAE61221D6E6AB606E482DA6355A +CT=431D243CEE96B424B0FA4FEC5E707036 +PT=5EF70106A2EA454CA9405A8AA1B54EF0 + +I=240 +KEY=2197CBE0B0CB93AA022034C28C137BAA +CT=5EF70106A2EA454CA9405A8AA1B54EF0 +PT=09B003CB7E2ADDD587A2ABCDD03D234F + +I=241 +KEY=2827C82BCEE14E7F85829F0F5C2E58E5 +CT=09B003CB7E2ADDD587A2ABCDD03D234F +PT=3647FAC6EF758113DC768E7737098DE9 + +I=242 +KEY=1E6032ED2194CF6C59F411786B27D50C +CT=3647FAC6EF758113DC768E7737098DE9 +PT=C043BD96A88492C85431B72C708C3C60 + +I=243 +KEY=DE238F7B89105DA40DC5A6541BABE96C +CT=C043BD96A88492C85431B72C708C3C60 +PT=299A25142A6B5D334158D359DD9CD574 + +I=244 +KEY=F7B9AA6FA37B00974C9D750DC6373C18 +CT=299A25142A6B5D334158D359DD9CD574 +PT=21E56C2202C8D6F81EDC63A8A1EA4B6A + +I=245 +KEY=D65CC64DA1B3D66F524116A567DD7772 +CT=21E56C2202C8D6F81EDC63A8A1EA4B6A +PT=FD3565957E3845065B7AEF27A900FDD5 + +I=246 +KEY=2B69A3D8DF8B9369093BF982CEDD8AA7 +CT=FD3565957E3845065B7AEF27A900FDD5 +PT=A4DB9120D1ED0419342AFC2CBF114647 + +I=247 +KEY=8FB232F80E6697703D1105AE71CCCCE0 +CT=A4DB9120D1ED0419342AFC2CBF114647 +PT=27FDDEA1E746BD217CFB4CD7A511BACE + +I=248 +KEY=A84FEC59E9202A5141EA4979D4DD762E +CT=27FDDEA1E746BD217CFB4CD7A511BACE +PT=6A9189FD46E47B22F151A213D023442B + +I=249 +KEY=C2DE65A4AFC45173B0BBEB6A04FE3205 +CT=6A9189FD46E47B22F151A213D023442B +PT=1C729701404C76D5D7A156C39CF52542 + +I=250 +KEY=DEACF2A5EF8827A6671ABDA9980B1747 +CT=1C729701404C76D5D7A156C39CF52542 +PT=6F97CB4564E0783DFE962DCB13FEDF72 + +I=251 +KEY=B13B39E08B685F9B998C90628BF5C835 +CT=6F97CB4564E0783DFE962DCB13FEDF72 +PT=F818140A280299B182CDA37CBE9B27AB + +I=252 +KEY=49232DEAA36AC62A1B41331E356EEF9E +CT=F818140A280299B182CDA37CBE9B27AB +PT=20E9F2BE7017C2945005FD8A420A5B7D + +I=253 +KEY=69CADF54D37D04BE4B44CE947764B4E3 +CT=20E9F2BE7017C2945005FD8A420A5B7D +PT=60BB97C634161EF6A36056193B6EDDB0 + +I=254 +KEY=09714892E76B1A48E824988D4C0A6953 +CT=60BB97C634161EF6A36056193B6EDDB0 +PT=E4B9777B7390EF430A93FF7DD0B68CD4 + +I=255 +KEY=EDC83FE994FBF50BE2B767F09CBCE587 +CT=E4B9777B7390EF430A93FF7DD0B68CD4 +PT=E5E3BD960CF15BBDB8A6C08711A884CF + +I=256 +KEY=082B827F980AAEB65A11A7778D146148 +CT=E5E3BD960CF15BBDB8A6C08711A884CF +PT=71A6AEFD0181DCE69A116585044C7F66 + +I=257 +KEY=798D2C82998B7250C000C2F289581E2E +CT=71A6AEFD0181DCE69A116585044C7F66 +PT=8E9C1CFFDB8972617D74DA0E9ED065D1 + +I=258 +KEY=F711307D42020031BD7418FC17887BFF +CT=8E9C1CFFDB8972617D74DA0E9ED065D1 +PT=CE7882AB901A199910FC463A4D1D626A + +I=259 +KEY=3969B2D6D21819A8AD885EC65A951995 +CT=CE7882AB901A199910FC463A4D1D626A +PT=2334546032E850D0029CB1AD6AFCEA7A + +I=260 +KEY=1A5DE6B6E0F04978AF14EF6B3069F3EF +CT=2334546032E850D0029CB1AD6AFCEA7A +PT=88B4CF0D4AB7BD00BE98DA1626063A69 + +I=261 +KEY=92E929BBAA47F478118C357D166FC986 +CT=88B4CF0D4AB7BD00BE98DA1626063A69 +PT=5A7FF831F28E5EC4A11DA524E2323925 + +I=262 +KEY=C896D18A58C9AABCB0919059F45DF0A3 +CT=5A7FF831F28E5EC4A11DA524E2323925 +PT=DF000551EF9BBD914969BD1B353BDC8C + +I=263 +KEY=1796D4DBB752172DF9F82D42C1662C2F +CT=DF000551EF9BBD914969BD1B353BDC8C +PT=1EECBC47697208193C354E28D23E8CE9 + +I=264 +KEY=097A689CDE201F34C5CD636A1358A0C6 +CT=1EECBC47697208193C354E28D23E8CE9 +PT=DF85CD4B3F821A7411F9F5D1FDF9DB85 + +I=265 +KEY=D6FFA5D7E1A20540D43496BBEEA17B43 +CT=DF85CD4B3F821A7411F9F5D1FDF9DB85 +PT=038E765F1910D8C0C1251254605218F2 + +I=266 +KEY=D571D388F8B2DD80151184EF8EF363B1 +CT=038E765F1910D8C0C1251254605218F2 +PT=FBA8FE850294EEAEE75F56C974BF7DE4 + +I=267 +KEY=2ED92D0DFA26332EF24ED226FA4C1E55 +CT=FBA8FE850294EEAEE75F56C974BF7DE4 +PT=47F9D6F7A3E2A1BFA360EA1BA8B0450E + +I=268 +KEY=6920FBFA59C49291512E383D52FC5B5B +CT=47F9D6F7A3E2A1BFA360EA1BA8B0450E +PT=FD6F4A4825DE5E776BFD569223CB5A2C + +I=269 +KEY=944FB1B27C1ACCE63AD36EAF71370177 +CT=FD6F4A4825DE5E776BFD569223CB5A2C +PT=10430ED7EE0FDB8FBC348F8E08286622 + +I=270 +KEY=840CBF659215176986E7E121791F6755 +CT=10430ED7EE0FDB8FBC348F8E08286622 +PT=4B75D5C573185303B01EB649884758B1 + +I=271 +KEY=CF796AA0E10D446A36F95768F1583FE4 +CT=4B75D5C573185303B01EB649884758B1 +PT=85CCA4271A941517D55D05B4F29527C3 + +I=272 +KEY=4AB5CE87FB99517DE3A452DC03CD1827 +CT=85CCA4271A941517D55D05B4F29527C3 +PT=615EA2D44C52D639B6AD05D621B4A1A6 + +I=273 +KEY=2BEB6C53B7CB87445509570A2279B981 +CT=615EA2D44C52D639B6AD05D621B4A1A6 +PT=1DFD1E93D34ABFE45BA6BF6BD3FBF30E + +I=274 +KEY=361672C0648138A00EAFE861F1824A8F +CT=1DFD1E93D34ABFE45BA6BF6BD3FBF30E +PT=B65C3F09FFFF752DEE2F8F2D441A51CA + +I=275 +KEY=804A4DC99B7E4D8DE080674CB5981B45 +CT=B65C3F09FFFF752DEE2F8F2D441A51CA +PT=3B36D6FD4F7ACAD4681FF4398AC7AFB3 + +I=276 +KEY=BB7C9B34D4048759889F93753F5FB4F6 +CT=3B36D6FD4F7ACAD4681FF4398AC7AFB3 +PT=F3CDEFABE450D887CD585C280BB22367 + +I=277 +KEY=48B1749F30545FDE45C7CF5D34ED9791 +CT=F3CDEFABE450D887CD585C280BB22367 +PT=ECC49251BAD79981CA1B1F683A843531 + +I=278 +KEY=A475E6CE8A83C65F8FDCD0350E69A2A0 +CT=ECC49251BAD79981CA1B1F683A843531 +PT=8BE43F0A30663108513A0E5F49F9152C + +I=279 +KEY=2F91D9C4BAE5F757DEE6DE6A4790B78C +CT=8BE43F0A30663108513A0E5F49F9152C +PT=DB3D559FCEBE0FAF3B218161BA6B3F07 + +I=280 +KEY=F4AC8C5B745BF8F8E5C75F0BFDFB888B +CT=DB3D559FCEBE0FAF3B218161BA6B3F07 +PT=8F0C3AE11B03433C07CABD26BF47A430 + +I=281 +KEY=7BA0B6BA6F58BBC4E20DE22D42BC2CBB +CT=8F0C3AE11B03433C07CABD26BF47A430 +PT=73578DC3464CE3EE0314B206E1E9504C + +I=282 +KEY=08F73B792914582AE119502BA3557CF7 +CT=73578DC3464CE3EE0314B206E1E9504C +PT=60DA2C12B296804C608348A54EE1C60D + +I=283 +KEY=682D176B9B82D866819A188EEDB4BAFA +CT=60DA2C12B296804C608348A54EE1C60D +PT=A960934724BDC61E5429E59856FC1902 + +I=284 +KEY=C14D842CBF3F1E78D5B3FD16BB48A3F8 +CT=A960934724BDC61E5429E59856FC1902 +PT=6B7E71535C6B7B09BDF19AF79CD58C95 + +I=285 +KEY=AA33F57FE3546571684267E1279D2F6D +CT=6B7E71535C6B7B09BDF19AF79CD58C95 +PT=B95E0126EF320F1E6F288366DB7F2773 + +I=286 +KEY=136DF4590C666A6F076AE487FCE2081E +CT=B95E0126EF320F1E6F288366DB7F2773 +PT=6403B99D6FE0F85128FDD1F05B81AA6E + +I=287 +KEY=776E4DC46386923E2F973577A763A270 +CT=6403B99D6FE0F85128FDD1F05B81AA6E +PT=9EBA25F2D6CE5817F4317F3AFE6421E7 + +I=288 +KEY=E9D46836B548CA29DBA64A4D59078397 +CT=9EBA25F2D6CE5817F4317F3AFE6421E7 +PT=5E77AAE8A3C5EEAF4732BB310DAC3771 + +I=289 +KEY=B7A3C2DE168D24869C94F17C54ABB4E6 +CT=5E77AAE8A3C5EEAF4732BB310DAC3771 +PT=5FD00675371300B60C30EFCEE0171080 + +I=290 +KEY=E873C4AB219E243090A41EB2B4BCA466 +CT=5FD00675371300B60C30EFCEE0171080 +PT=482D701DBCE3AE108F65836C12A41C2C + +I=291 +KEY=A05EB4B69D7D8A201FC19DDEA618B84A +CT=482D701DBCE3AE108F65836C12A41C2C +PT=2966D81642542925891D8F7409051E4A + +I=292 +KEY=89386CA0DF29A30596DC12AAAF1DA600 +CT=2966D81642542925891D8F7409051E4A +PT=2FD6F3DB9DD1DEDED9F32D1806AE69D6 + +I=293 +KEY=A6EE9F7B42F87DDB4F2F3FB2A9B3CFD6 +CT=2FD6F3DB9DD1DEDED9F32D1806AE69D6 +PT=9B59277165B792790E29ADB53ADE60DB + +I=294 +KEY=3DB7B80A274FEFA241069207936DAF0D +CT=9B59277165B792790E29ADB53ADE60DB +PT=A4873C5246044200B56C25FFADAB15D6 + +I=295 +KEY=99308458614BADA2F46AB7F83EC6BADB +CT=A4873C5246044200B56C25FFADAB15D6 +PT=9E2BBBD65649EB2A0CD974AD32BF382F + +I=296 +KEY=071B3F8E37024688F8B3C3550C7982F4 +CT=9E2BBBD65649EB2A0CD974AD32BF382F +PT=F83F4408675892DADA4833A43F22FFC8 + +I=297 +KEY=FF247B86505AD45222FBF0F1335B7D3C +CT=F83F4408675892DADA4833A43F22FFC8 +PT=19C337CCBF8D06DC68D9A16DB294EF44 + +I=298 +KEY=E6E74C4AEFD7D28E4A22519C81CF9278 +CT=19C337CCBF8D06DC68D9A16DB294EF44 +PT=433578E0901A4F4B134E6DCF68249FC7 + +I=299 +KEY=A5D234AA7FCD9DC5596C3C53E9EB0DBF +CT=433578E0901A4F4B134E6DCF68249FC7 +PT=7F317CB0B3279C894B8A08289797FFF1 + +I=300 +KEY=DAE3481ACCEA014C12E6347B7E7CF24E +CT=7F317CB0B3279C894B8A08289797FFF1 +PT=AFFB4CA21A2A36FD24BB18C5AED17789 + +I=301 +KEY=751804B8D6C037B1365D2CBED0AD85C7 +CT=AFFB4CA21A2A36FD24BB18C5AED17789 +PT=394DA5EC353A68B844D1BC24A468DA5C + +I=302 +KEY=4C55A154E3FA5F09728C909A74C55F9B +CT=394DA5EC353A68B844D1BC24A468DA5C +PT=C649C174B98A06351F26C117D14FF290 + +I=303 +KEY=8A1C60205A70593C6DAA518DA58AAD0B +CT=C649C174B98A06351F26C117D14FF290 +PT=2E122AA7C90B57304A80C19480627DD7 + +I=304 +KEY=A40E4A87937B0E0C272A901925E8D0DC +CT=2E122AA7C90B57304A80C19480627DD7 +PT=9841ADE6A65834CE89959EFE8F059ED6 + +I=305 +KEY=3C4FE76135233AC2AEBF0EE7AAED4E0A +CT=9841ADE6A65834CE89959EFE8F059ED6 +PT=6B70D74762A4BEFBD15B9EC6835CB69B + +I=306 +KEY=573F3026578784397FE4902129B1F891 +CT=6B70D74762A4BEFBD15B9EC6835CB69B +PT=2E8B5DEF53E2294C0C953A9B8BD9399D + +I=307 +KEY=79B46DC90465AD757371AABAA268C10C +CT=2E8B5DEF53E2294C0C953A9B8BD9399D +PT=D32D00F78BA00F6CEA792598B89779E4 + +I=308 +KEY=AA996D3E8FC5A21999088F221AFFB8E8 +CT=D32D00F78BA00F6CEA792598B89779E4 +PT=7059DCC6CB8D295B95F2978F25927B31 + +I=309 +KEY=DAC0B1F844488B420CFA18AD3F6DC3D9 +CT=7059DCC6CB8D295B95F2978F25927B31 +PT=833A1AFA7DC4CAF54F5B36981A98D7E3 + +I=310 +KEY=59FAAB02398C41B743A12E3525F5143A +CT=833A1AFA7DC4CAF54F5B36981A98D7E3 +PT=4CC5A526400B493AAA28909A2F4932BF + +I=311 +KEY=153F0E247987088DE989BEAF0ABC2685 +CT=4CC5A526400B493AAA28909A2F4932BF +PT=D7134DEE2967104D161876A0802B3727 + +I=312 +KEY=C22C43CA50E018C0FF91C80F8A9711A2 +CT=D7134DEE2967104D161876A0802B3727 +PT=C45DB7BC52D7A0D53399B91EFB686D32 + +I=313 +KEY=0671F4760237B815CC08711171FF7C90 +CT=C45DB7BC52D7A0D53399B91EFB686D32 +PT=2F49EA2A8D7F44909BCF41C3640FD0AB + +I=314 +KEY=29381E5C8F48FC8557C730D215F0AC3B +CT=2F49EA2A8D7F44909BCF41C3640FD0AB +PT=6D416059758F4AC555A05D83E9CFC4DE + +I=315 +KEY=44797E05FAC7B64002676D51FC3F68E5 +CT=6D416059758F4AC555A05D83E9CFC4DE +PT=2721015DDF85EC87ED8480A87705CD37 + +I=316 +KEY=63587F5825425AC7EFE3EDF98B3AA5D2 +CT=2721015DDF85EC87ED8480A87705CD37 +PT=3B045F5DD5ADC6E5D341E2E6A5B919D3 + +I=317 +KEY=585C2005F0EF9C223CA20F1F2E83BC01 +CT=3B045F5DD5ADC6E5D341E2E6A5B919D3 +PT=85DA9719FF16899B343BE56FDF9F86BF + +I=318 +KEY=DD86B71C0FF915B90899EA70F11C3ABE +CT=85DA9719FF16899B343BE56FDF9F86BF +PT=67FD32AC2783C381E77AE0BB8ACEECCD + +I=319 +KEY=BA7B85B0287AD638EFE30ACB7BD2D673 +CT=67FD32AC2783C381E77AE0BB8ACEECCD +PT=D8BEC715849E6A2A164F0139B8EC038E + +I=320 +KEY=62C542A5ACE4BC12F9AC0BF2C33ED5FD +CT=D8BEC715849E6A2A164F0139B8EC038E +PT=6ECA9375A207148E36203C8BD885A520 + +I=321 +KEY=0C0FD1D00EE3A89CCF8C37791BBB70DD +CT=6ECA9375A207148E36203C8BD885A520 +PT=A96877A8369B7086EF76D8281C066068 + +I=322 +KEY=A567A6783878D81A20FAEF5107BD10B5 +CT=A96877A8369B7086EF76D8281C066068 +PT=2D6DDF2C136F5ACDC12D33D52ECD6397 + +I=323 +KEY=880A79542B1782D7E1D7DC8429707322 +CT=2D6DDF2C136F5ACDC12D33D52ECD6397 +PT=E2F3EFF780EEDAD7B820CF57F946AB21 + +I=324 +KEY=6AF996A3ABF9580059F713D3D036D803 +CT=E2F3EFF780EEDAD7B820CF57F946AB21 +PT=D083829AB624DC46BF55F15C2ACA2CDC + +I=325 +KEY=BA7A14391DDD8446E6A2E28FFAFCF4DF +CT=D083829AB624DC46BF55F15C2ACA2CDC +PT=637A1328711A701F011B0D66953A11FC + +I=326 +KEY=D90007116CC7F459E7B9EFE96FC6E523 +CT=637A1328711A701F011B0D66953A11FC +PT=9230F9E8C4AA7D697641B4E800AECE8B + +I=327 +KEY=4B30FEF9A86D893091F85B016F682BA8 +CT=9230F9E8C4AA7D697641B4E800AECE8B +PT=CABC2F3EBCB87AEF4550060FB6F95C7D + +I=328 +KEY=818CD1C714D5F3DFD4A85D0ED99177D5 +CT=CABC2F3EBCB87AEF4550060FB6F95C7D +PT=25C93DA609BEDFD48D88B7E005EA9D4D + +I=329 +KEY=A445EC611D6B2C0B5920EAEEDC7BEA98 +CT=25C93DA609BEDFD48D88B7E005EA9D4D +PT=E445C1B43DC6AA0D47C766675676CA29 + +I=330 +KEY=40002DD520AD86061EE78C898A0D20B1 +CT=E445C1B43DC6AA0D47C766675676CA29 +PT=3F8A99E9D556F0CE0B0F3B4FE89A7C15 + +I=331 +KEY=7F8AB43CF5FB76C815E8B7C662975CA4 +CT=3F8A99E9D556F0CE0B0F3B4FE89A7C15 +PT=BE04197CADBDBC917AB288D85C554D4A + +I=332 +KEY=C18EAD405846CA596F5A3F1E3EC211EE +CT=BE04197CADBDBC917AB288D85C554D4A +PT=2CF8FE59EED67AF15BD6C09C8DA37882 + +I=333 +KEY=ED765319B690B0A8348CFF82B361696C +CT=2CF8FE59EED67AF15BD6C09C8DA37882 +PT=FF8CBF98D0B15198ACDC53D7247511C5 + +I=334 +KEY=12FAEC816621E1309850AC55971478A9 +CT=FF8CBF98D0B15198ACDC53D7247511C5 +PT=27794678855BAE2BDE7EB75487813E28 + +I=335 +KEY=3583AAF9E37A4F1B462E1B0110954681 +CT=27794678855BAE2BDE7EB75487813E28 +PT=5681B2CECDE71663A864D0288607D86B + +I=336 +KEY=630218372E9D5978EE4ACB2996929EEA +CT=5681B2CECDE71663A864D0288607D86B +PT=8936EB6E65F2CD2B3AFD1310B5B2D6C8 + +I=337 +KEY=EA34F3594B6F9453D4B7D83923204822 +CT=8936EB6E65F2CD2B3AFD1310B5B2D6C8 +PT=16045490148187B05CC46B80099A4530 + +I=338 +KEY=FC30A7C95FEE13E38873B3B92ABA0D12 +CT=16045490148187B05CC46B80099A4530 +PT=FE909FFB1D490B028867288FE682EEE9 + +I=339 +KEY=02A0383242A718E100149B36CC38E3FB +CT=FE909FFB1D490B028867288FE682EEE9 +PT=7B3E5C0017089A7842866ABA6364FFEA + +I=340 +KEY=799E643255AF82994292F18CAF5C1C11 +CT=7B3E5C0017089A7842866ABA6364FFEA +PT=CC263F129618975F204AE499F115C69B + +I=341 +KEY=B5B85B20C3B715C662D815155E49DA8A +CT=CC263F129618975F204AE499F115C69B +PT=997ACE7EABF6EBF9CC7BBCC2670CF1A0 + +I=342 +KEY=2CC2955E6841FE3FAEA3A9D739452B2A +CT=997ACE7EABF6EBF9CC7BBCC2670CF1A0 +PT=88D4A74B19278ED442068D0954DFA8B2 + +I=343 +KEY=A4163215716670EBECA524DE6D9A8398 +CT=88D4A74B19278ED442068D0954DFA8B2 +PT=F1CC6407AB254178DEFEF983112D6AC5 + +I=344 +KEY=55DA5612DA433193325BDD5D7CB7E95D +CT=F1CC6407AB254178DEFEF983112D6AC5 +PT=689A0E429CDAF1BD1197C160BF962544 + +I=345 +KEY=3D4058504699C02E23CC1C3DC321CC19 +CT=689A0E429CDAF1BD1197C160BF962544 +PT=54CF618196D978C0460CF8051DF5BE18 + +I=346 +KEY=698F39D1D040B8EE65C0E438DED47201 +CT=54CF618196D978C0460CF8051DF5BE18 +PT=4AA0EF106F23B43C3DD371C66404C602 + +I=347 +KEY=232FD6C1BF630CD2581395FEBAD0B403 +CT=4AA0EF106F23B43C3DD371C66404C602 +PT=A5185CAE1718143FC6CC329D9F233E17 + +I=348 +KEY=86378A6FA87B18ED9EDFA76325F38A14 +CT=A5185CAE1718143FC6CC329D9F233E17 +PT=A2A7E8855D25A0C475961E9B7ED7BE35 + +I=349 +KEY=249062EAF55EB829EB49B9F85B243421 +CT=A2A7E8855D25A0C475961E9B7ED7BE35 +PT=E0B7536B335FB98F197F762B3B97CECE + +I=350 +KEY=C4273181C60101A6F236CFD360B3FAEF +CT=E0B7536B335FB98F197F762B3B97CECE +PT=C45C38164083871528D8B3BA7423BFEA + +I=351 +KEY=007B0997868286B3DAEE7C6914904505 +CT=C45C38164083871528D8B3BA7423BFEA +PT=017AEBDEF43CF9664C582356A4A0C374 + +I=352 +KEY=0101E24972BE7FD596B65F3FB0308671 +CT=017AEBDEF43CF9664C582356A4A0C374 +PT=BBB48EA21B5EDCCF5346A7B4E6796BED + +I=353 +KEY=BAB56CEB69E0A31AC5F0F88B5649ED9C +CT=BBB48EA21B5EDCCF5346A7B4E6796BED +PT=3A53DFCB6067F9E98653136A44A4B537 + +I=354 +KEY=80E6B32009875AF343A3EBE112ED58AB +CT=3A53DFCB6067F9E98653136A44A4B537 +PT=951BA0E2272E46FC8CC3990E002EEFF0 + +I=355 +KEY=15FD13C22EA91C0FCF6072EF12C3B75B +CT=951BA0E2272E46FC8CC3990E002EEFF0 +PT=249202E40BC5892B9CEE96279E69432A + +I=356 +KEY=316F1126256C9524538EE4C88CAAF471 +CT=249202E40BC5892B9CEE96279E69432A +PT=B90CE5BF126163B37F75032A88AFD615 + +I=357 +KEY=8863F499370DF6972CFBE7E204052264 +CT=B90CE5BF126163B37F75032A88AFD615 +PT=E0BDD9E1FF493D82777BD7FB4035D309 + +I=358 +KEY=68DE2D78C844CB155B8030194430F16D +CT=E0BDD9E1FF493D82777BD7FB4035D309 +PT=0A3A5E377CDB2D1F6CB09E200494F578 + +I=359 +KEY=62E4734FB49FE60A3730AE3940A40415 +CT=0A3A5E377CDB2D1F6CB09E200494F578 +PT=483DF6E2936389D1FC09921497AF8AE7 + +I=360 +KEY=2AD985AD27FC6FDBCB393C2DD70B8EF2 +CT=483DF6E2936389D1FC09921497AF8AE7 +PT=7A90B7B1E493109323A54AD285090EC6 + +I=361 +KEY=5049321CC36F7F48E89C76FF52028034 +CT=7A90B7B1E493109323A54AD285090EC6 +PT=B6471BF36A24B5B0CAC19BDD4C83DC50 + +I=362 +KEY=E60E29EFA94BCAF8225DED221E815C64 +CT=B6471BF36A24B5B0CAC19BDD4C83DC50 +PT=EFBDC6ECADCE6AA5DBD302E7A0647700 + +I=363 +KEY=09B3EF030485A05DF98EEFC5BEE52B64 +CT=EFBDC6ECADCE6AA5DBD302E7A0647700 +PT=783A89B88CC875F743B645BA1449CEE7 + +I=364 +KEY=718966BB884DD5AABA38AA7FAAACE583 +CT=783A89B88CC875F743B645BA1449CEE7 +PT=EAD61D2577852D4EA276F3699EFB2BDC + +I=365 +KEY=9B5F7B9EFFC8F8E4184E59163457CE5F +CT=EAD61D2577852D4EA276F3699EFB2BDC +PT=9E804D8814AF4FC67BA931D1C72774C7 + +I=366 +KEY=05DF3616EB67B72263E768C7F370BA98 +CT=9E804D8814AF4FC67BA931D1C72774C7 +PT=7C383CC27D8C2B117AC72088EB334FD9 + +I=367 +KEY=79E70AD496EB9C331920484F1843F541 +CT=7C383CC27D8C2B117AC72088EB334FD9 +PT=9D4BE61ECECB2E60EC621A6320C0E844 + +I=368 +KEY=E4ACECCA5820B253F542522C38831D05 +CT=9D4BE61ECECB2E60EC621A6320C0E844 +PT=227992ADFC526D9AA99BA629E7523198 + +I=369 +KEY=C6D57E67A472DFC95CD9F405DFD12C9D +CT=227992ADFC526D9AA99BA629E7523198 +PT=93A265FB7650BE75CBDD8732F65F09A5 + +I=370 +KEY=55771B9CD22261BC97047337298E2538 +CT=93A265FB7650BE75CBDD8732F65F09A5 +PT=5AB3354B8D28F041C5A7FDAB828996BC + +I=371 +KEY=0FC42ED75F0A91FD52A38E9CAB07B384 +CT=5AB3354B8D28F041C5A7FDAB828996BC +PT=BA5C6566701BD3791C2DA51CDC5AB6DD + +I=372 +KEY=B5984BB12F1142844E8E2B80775D0559 +CT=BA5C6566701BD3791C2DA51CDC5AB6DD +PT=2C96CE0653EFB1113C6E822DD4AE6200 + +I=373 +KEY=990E85B77CFEF39572E0A9ADA3F36759 +CT=2C96CE0653EFB1113C6E822DD4AE6200 +PT=1065F5519472C78BADAB79EC00BBCABA + +I=374 +KEY=896B70E6E88C341EDF4BD041A348ADE3 +CT=1065F5519472C78BADAB79EC00BBCABA +PT=049AA7D4B4C1A59C1A16E3E5D8B46515 + +I=375 +KEY=8DF1D7325C4D9182C55D33A47BFCC8F6 +CT=049AA7D4B4C1A59C1A16E3E5D8B46515 +PT=C8F1C4179DD8FCD6942D07AF7392F481 + +I=376 +KEY=45001325C1956D545170340B086E3C77 +CT=C8F1C4179DD8FCD6942D07AF7392F481 +PT=9C9AE90AFE18822197EA47FE2F48813F + +I=377 +KEY=D99AFA2F3F8DEF75C69A73F52726BD48 +CT=9C9AE90AFE18822197EA47FE2F48813F +PT=DFBABE8688391CC868CDE134DDFFE1F0 + +I=378 +KEY=062044A9B7B4F3BDAE5792C1FAD95CB8 +CT=DFBABE8688391CC868CDE134DDFFE1F0 +PT=72BE585F98DA4DC03998B5820D5230A9 + +I=379 +KEY=749E1CF62F6EBE7D97CF2743F78B6C11 +CT=72BE585F98DA4DC03998B5820D5230A9 +PT=BCF3D47B888599A27AD63D6EFD8FB86F + +I=380 +KEY=C86DC88DA7EB27DFED191A2D0A04D47E +CT=BCF3D47B888599A27AD63D6EFD8FB86F +PT=62F7A2AD05BB46CB81B9601129100455 + +I=381 +KEY=AA9A6A20A25061146CA07A3C2314D02B +CT=62F7A2AD05BB46CB81B9601129100455 +PT=FA4D3B82232D19BE14A57422012C7751 + +I=382 +KEY=50D751A2817D78AA78050E1E2238A77A +CT=FA4D3B82232D19BE14A57422012C7751 +PT=40953AAA3D6C1BBE375A1E275754C98C + +I=383 +KEY=10426B08BC1163144F5F1039756C6EF6 +CT=40953AAA3D6C1BBE375A1E275754C98C +PT=CE9123C6A5A66AF788A8515721D646A0 + +I=384 +KEY=DED348CE19B709E3C7F7416E54BA2856 +CT=CE9123C6A5A66AF788A8515721D646A0 +PT=E45F3483E343F5C3C0AC77E955369AB3 + +I=385 +KEY=3A8C7C4DFAF4FC20075B3687018CB2E5 +CT=E45F3483E343F5C3C0AC77E955369AB3 +PT=6E7CE5F4BE070EC870691CDD494A767E + +I=386 +KEY=54F099B944F3F2E877322A5A48C6C49B +CT=6E7CE5F4BE070EC870691CDD494A767E +PT=2BB1EE551920A632E90EB9E462280365 + +I=387 +KEY=7F4177EC5DD354DA9E3C93BE2AEEC7FE +CT=2BB1EE551920A632E90EB9E462280365 +PT=692E0FA8B1C39CB96A11E21EA1B3365E + +I=388 +KEY=166F7844EC10C863F42D71A08B5DF1A0 +CT=692E0FA8B1C39CB96A11E21EA1B3365E +PT=345C0DE98A9F472B6BCBE241BB346590 + +I=389 +KEY=223375AD668F8F489FE693E130699430 +CT=345C0DE98A9F472B6BCBE241BB346590 +PT=D9D9313DC80FB90608614ECCC962207F + +I=390 +KEY=FBEA4490AE80364E9787DD2DF90BB44F +CT=D9D9313DC80FB90608614ECCC962207F +PT=7AEE31C488D1DD54B9AD8EE3AEFE546C + +I=391 +KEY=810475542651EB1A2E2A53CE57F5E023 +CT=7AEE31C488D1DD54B9AD8EE3AEFE546C +PT=9CF27E1202080D9F3A9B5E02290204EA + +I=392 +KEY=1DF60B462459E68514B10DCC7EF7E4C9 +CT=9CF27E1202080D9F3A9B5E02290204EA +PT=670085C6D3B95C6017DB9163B9D2D565 + +I=393 +KEY=7AF68E80F7E0BAE5036A9CAFC72531AC +CT=670085C6D3B95C6017DB9163B9D2D565 +PT=2A36E88DF74BA4B24283FEE52DDE5AA4 + +I=394 +KEY=50C0660D00AB1E5741E9624AEAFB6B08 +CT=2A36E88DF74BA4B24283FEE52DDE5AA4 +PT=81B75B31F130467F4A1FA6CA4A329E5E + +I=395 +KEY=D1773D3CF19B58280BF6C480A0C9F556 +CT=81B75B31F130467F4A1FA6CA4A329E5E +PT=D0A0347102BD11F9E2BD8E8A72D53ADC + +I=396 +KEY=01D7094DF32649D1E94B4A0AD21CCF8A +CT=D0A0347102BD11F9E2BD8E8A72D53ADC +PT=97F0187509608DF1D9B27AB5D005E505 + +I=397 +KEY=96271138FA46C42030F930BF02192A8F +CT=97F0187509608DF1D9B27AB5D005E505 +PT=E60139E36ECD7B24C7C98772C92A1E87 + +I=398 +KEY=702628DB948BBF04F730B7CDCB333408 +CT=E60139E36ECD7B24C7C98772C92A1E87 +PT=7E92E19E07A469E7D49D3D07EF719157 + +I=399 +KEY=0EB4C945932FD6E323AD8ACA2442A55F +CT=7E92E19E07A469E7D49D3D07EF719157 +PT=F5BF8B37136F2E1F6BEC6F572021E3BA + +========================= + +KEYSIZE=192 + +I=0 +KEY=000000000000000000000000000000000000000000000000 +CT=00000000000000000000000000000000 +PT=48E31E9E256718F29229319C19F15BA4 + +I=1 +KEY=9643D8334A63DF4D48E31E9E256718F29229319C19F15BA4 +CT=48E31E9E256718F29229319C19F15BA4 +PT=CC01684BE9B29ED01EA7923E7D2380AA + +I=2 +KEY=EF334C87288C43DE84E276D5CCD586228C8EA3A264D2DB0E +CT=CC01684BE9B29ED01EA7923E7D2380AA +PT=8726B4E66D6B8FBAA22D42981A5A40CC + +I=3 +KEY=0891A045BB044B9D03C4C233A1BE09982EA3E13A7E889BC2 +CT=8726B4E66D6B8FBAA22D42981A5A40CC +PT=83B9A21A0710FDB9C603797613772ED6 + +I=4 +KEY=A5233519DE914717807D6029A6AEF421E8A0984C6DFFB514 +CT=83B9A21A0710FDB9C603797613772ED6 +PT=F15479A2B2C250F7E5C11D333D867CBD + +I=5 +KEY=A1CB19726DB4C2C77129198B146CA4D60D61857F5079C9A9 +CT=F15479A2B2C250F7E5C11D333D867CBD +PT=C1AF401BD4E62D8BA15BEC3690F2FB25 + +I=6 +KEY=04B03C15DB8324B3B0865990C08A895DAC3A6949C08B328C +CT=C1AF401BD4E62D8BA15BEC3690F2FB25 +PT=01E01E3B10470286035EBD7502EF11A0 + +I=7 +KEY=A1CB0164AB1E88EDB16647ABD0CD8BDBAF64D43CC264232C +CT=01E01E3B10470286035EBD7502EF11A0 +PT=A681127825B718411291106AB416779A + +I=8 +KEY=27BFD9CB824C525617E755D3F57A939ABDF5C456767254B6 +CT=A681127825B718411291106AB416779A +PT=5C2EBA728589A9CAA15E28E7D8E59AA0 + +I=9 +KEY=B308E0DCE108194C4BC9EFA170F33A501CABECB1AE97CE16 +CT=5C2EBA728589A9CAA15E28E7D8E59AA0 +PT=E738305279BE636648B6D5FFA3E97E4A + +I=10 +KEY=FE787701EE66664BACF1DFF3094D5936541D394E0D7EB05C +CT=E738305279BE636648B6D5FFA3E97E4A +PT=5AF7D4C9439C7412FD7236E7685659DF + +I=11 +KEY=DD93D742AFA0B19CF6060B3A4AD12D24A96F0FA96528E983 +CT=5AF7D4C9439C7412FD7236E7685659DF +PT=30D0681D4060E24D1427D1AAC498DB1B + +I=12 +KEY=D5D19C2FEA9DC94BC6D663270AB1CF69BD48DE03A1B03298 +CT=30D0681D4060E24D1427D1AAC498DB1B +PT=FC9B6752064B1CCE75EBFBE91AF8F2CD + +I=13 +KEY=EB0954ECE44620833A4D04750CFAD3A7C8A325EABB48C055 +CT=FC9B6752064B1CCE75EBFBE91AF8F2CD +PT=61E6AE6E035BCC3C94EF00101216904A + +I=14 +KEY=E6E5AB38545B6DF75BABAA1B0FA11F9B5C4C25FAA95E501F +CT=61E6AE6E035BCC3C94EF00101216904A +PT=BF738A4E55F036126CC9B56DED530B8C + +I=15 +KEY=E8C670F71E5B62B6E4D820555A51298930859097440D5B93 +CT=BF738A4E55F036126CC9B56DED530B8C +PT=6B9CD4C227FC30C14FD881B838D9F8F5 + +I=16 +KEY=23FF647DD75770418F44F4977DAD19487F5D112F7CD4A366 +CT=6B9CD4C227FC30C14FD881B838D9F8F5 +PT=6173EF2B5C9B569A1BD4B62C7C913844 + +I=17 +KEY=DB94124B11CC03D9EE371BBC21364FD26489A70300459B22 +CT=6173EF2B5C9B569A1BD4B62C7C913844 +PT=709EF90F853E55123A917FB258E900F9 + +I=18 +KEY=4821CA96B50ACA049EA9E2B3A4081AC05E18D8B158AC9BDB +CT=709EF90F853E55123A917FB258E900F9 +PT=5D73D99E47B1DB28E0ED9B9D1C212CFA + +I=19 +KEY=FA47C5BF5E688F8BC3DA3B2DE3B9C1E8BEF5432C448DB721 +CT=5D73D99E47B1DB28E0ED9B9D1C212CFA +PT=32016FFCB2AA5EA6EA0C808F60613CA2 + +I=20 +KEY=C66A73E0D1261C2CF1DB54D151139F4E54F9C3A324EC8B83 +CT=32016FFCB2AA5EA6EA0C808F60613CA2 +PT=CAA3704F7FD76EBACB1D2A266A0899FF + +I=21 +KEY=FAE8E04094E572A33B78249E2EC4F1F49FE4E9854EE4127C +CT=CAA3704F7FD76EBACB1D2A266A0899FF +PT=E32DBD027A1A36B2EC8D0A98C9293E7E + +I=22 +KEY=8F2FBF9E40182950D855999C54DEC7467369E31D87CD2C02 +CT=E32DBD027A1A36B2EC8D0A98C9293E7E +PT=1C117311882C0D5159A9DFD5C3C68D95 + +I=23 +KEY=F6FB8F6DFAA034BFC444EA8DDCF2CA172AC03CC8440BA197 +CT=1C117311882C0D5159A9DFD5C3C68D95 +PT=5E379C2471DB04582CD861E6F8A419D7 + +I=24 +KEY=699DCA67F4EF50C49A7376A9AD29CE4F06185D2EBCAFB840 +CT=5E379C2471DB04582CD861E6F8A419D7 +PT=5932A84C6ACBD8452EE9AC47CE4B6BD8 + +I=25 +KEY=F568B4F126486CE4C341DEE5C7E2160A28F1F16972E4D398 +CT=5932A84C6ACBD8452EE9AC47CE4B6BD8 +PT=00634EED1D18C84AE0A8198CF791DE81 + +I=26 +KEY=C49E5E8D366B6FE7C3229008DAFADE40C859E8E585750D19 +CT=00634EED1D18C84AE0A8198CF791DE81 +PT=E10C93B1C466FFF0B6EB6DB50AF271EC + +I=27 +KEY=22B07DB9ED443A9D222E03B91E9C21B07EB285508F877CF5 +CT=E10C93B1C466FFF0B6EB6DB50AF271EC +PT=58A0C680F565E63A7E41C6EAC50A3B01 + +I=28 +KEY=2BDF4CCE2B4CAFDD7A8EC539EBF9C78A00F343BA4A8D47F4 +CT=58A0C680F565E63A7E41C6EAC50A3B01 +PT=92921B2AA7FC6367199A4C42FAE0E2A4 + +I=29 +KEY=E2BE29F6905D41C5E81CDE134C05A4ED19690FF8B06DA550 +CT=92921B2AA7FC6367199A4C42FAE0E2A4 +PT=B6EC2A692D2657E5506F2C3BA1912799 + +I=30 +KEY=E43634FD3DB719C75EF0F47A6123F308490623C311FC82C9 +CT=B6EC2A692D2657E5506F2C3BA1912799 +PT=23ECD0813B1A7090CF9BE874D6B0846C + +I=31 +KEY=ACA2F21EF46E30B57D1C24FB5A398398869DCBB7C74C06A5 +CT=23ECD0813B1A7090CF9BE874D6B0846C +PT=04BD52F4C1AB8DF4816A6E11F8B54452 + +I=32 +KEY=0130B37AFE24D66079A1760F9B920E6C07F7A5A63FF942F7 +CT=04BD52F4C1AB8DF4816A6E11F8B54452 +PT=DFA0074DEFEDB44D0D96AD6020D1A37D + +I=33 +KEY=00AC6BF5E3AD20FFA6017142747FBA210A6108C61F28E18A +CT=DFA0074DEFEDB44D0D96AD6020D1A37D +PT=5AB15057E05F73FAAF12C0EC26D3F02F + +I=34 +KEY=E3A70EBF3D9167AAFCB021159420C9DBA573C82A39FB11A5 +CT=5AB15057E05F73FAAF12C0EC26D3F02F +PT=6ECC2F23AB7854E97F215C52EF1E62E0 + +I=35 +KEY=CBCD9116DC78FA64927C0E363F589D32DA529478D6E57345 +CT=6ECC2F23AB7854E97F215C52EF1E62E0 +PT=930B3EBDE0989049056022E83FC9EF1E + +I=36 +KEY=FBB5E5462DE715180177308BDFC00D7BDF32B690E92C9C5B +CT=930B3EBDE0989049056022E83FC9EF1E +PT=1EE4ABB9ACD70B93A83BCD8751F858DE + +I=37 +KEY=E5D2B1ACD8BE6DF21F939B32731706E877097B17B8D4C485 +CT=1EE4ABB9ACD70B93A83BCD8751F858DE +PT=FCAC610EA0D309C6D36EED5A4BC04036 + +I=38 +KEY=54DD0B6CB083BDE8E33FFA3CD3C40F2EA467964DF31484B3 +CT=FCAC610EA0D309C6D36EED5A4BC04036 +PT=161D5EE8F50A3F69A11ADFEAF1A2A2AA + +I=39 +KEY=28309F7EB99AAEE1F522A4D426CE3047057D49A702B62619 +CT=161D5EE8F50A3F69A11ADFEAF1A2A2AA +PT=D9D365B061D2F3BF9DF94181837621B4 + +I=40 +KEY=E55ECDDFAE95A2C92CF1C164471CC3F89884082681C007AD +CT=D9D365B061D2F3BF9DF94181837621B4 +PT=938647A6AAD455D89A6DFEFE60D62331 + +I=41 +KEY=C9CEE1C9D89DF76ABF7786C2EDC8962002E9F6D8E116249C +CT=938647A6AAD455D89A6DFEFE60D62331 +PT=06A002DDC7DC4F22F9B1D5734C312AAA + +I=42 +KEY=B26709109B66C916B9D7841F2A14D902FB5823ABAD270E36 +CT=06A002DDC7DC4F22F9B1D5734C312AAA +PT=BB45E9BE2237E3288F56EDD0D9AD6734 + +I=43 +KEY=2FAD2FF32E10680502926DA108233A2A740ECE7B748A6902 +CT=BB45E9BE2237E3288F56EDD0D9AD6734 +PT=CF5A1338F5FA7ED4C77F6EA3836F079A + +I=44 +KEY=63D3D62540C790D1CDC87E99FDD944FEB371A0D8F7E56E98 +CT=CF5A1338F5FA7ED4C77F6EA3836F079A +PT=32F2D628117ADB46383FC101B58E95A6 + +I=45 +KEY=0DF38CE71CF26A19FF3AA8B1ECA39FB88B4E61D9426BFB3E +CT=32F2D628117ADB46383FC101B58E95A6 +PT=3A3CCEA99D43887AC64498AB4EFC87DD + +I=46 +KEY=7EEEB78A0C9BAA9FC506661871E017C24D0AF9720C977CE3 +CT=3A3CCEA99D43887AC64498AB4EFC87DD +PT=787DC1C632C4AA77D42324338C510146 + +I=47 +KEY=4DF02EE427AE29A1BD7BA7DE4324BDB59929DD4180C67DA5 +CT=787DC1C632C4AA77D42324338C510146 +PT=BB0635A471D26B80E5E387E4F14A1626 + +I=48 +KEY=D6983F5E8BE728D9067D927A32F6D6357CCA5AA5718C6B83 +CT=BB0635A471D26B80E5E387E4F14A1626 +PT=14A9AA3EE6343C2D57E0F2ED7A05DC0D + +I=49 +KEY=BD84A7CD471613B512D43844D4C2EA182B2AA8480B89B78E +CT=14A9AA3EE6343C2D57E0F2ED7A05DC0D +PT=25E254AD6C33908BC07B3DEC4052F549 + +I=50 +KEY=E54A2146242AADFB37366CE9B8F17A93EB5195A44BDB42C7 +CT=25E254AD6C33908BC07B3DEC4052F549 +PT=10E09F426E6F33CD21DF1EB748A46088 + +I=51 +KEY=0517B745BCE24E0527D6F3ABD69E495ECA8E8B13037F224F +CT=10E09F426E6F33CD21DF1EB748A46088 +PT=B65D2FFE83F9469AA2B1ABC559EAAB87 + +I=52 +KEY=8297790C75E8931C918BDC5555670FC4683F20D65A9589C8 +CT=B65D2FFE83F9469AA2B1ABC559EAAB87 +PT=E743F6441CCF9703FF4B8E3F4921ACDF + +I=53 +KEY=7EC47C0C5663CD4C76C82A1149A898C79774AEE913B42517 +CT=E743F6441CCF9703FF4B8E3F4921ACDF +PT=BECC5CF2F2C62A9E7D3CF979A9E96F94 + +I=54 +KEY=FBB1F10529FABEB3C80476E3BB6EB259EA485790BA5D4A83 +CT=BECC5CF2F2C62A9E7D3CF979A9E96F94 +PT=3718199958EAA473B980B95F9C76E03F + +I=55 +KEY=EE4113D30720269DFF1C6F7AE384162A53C8EECF262BAABC +CT=3718199958EAA473B980B95F9C76E03F +PT=D15525B8BBB6D209E0BB3B6F5ACB2556 + +I=56 +KEY=488286944DC6B0842E494AC25832C423B373D5A07CE08FEA +CT=D15525B8BBB6D209E0BB3B6F5ACB2556 +PT=0270AF07DDA52DF7CA7B0EE7DF098A80 + +I=57 +KEY=A32A880A84E7EDB82C39E5C58597E9D47908DB47A3E9056A +CT=0270AF07DDA52DF7CA7B0EE7DF098A80 +PT=2D380F99A182CD14CFFEF5E88B93B416 + +I=58 +KEY=DBD0FD5053BC52C60101EA5C241524C0B6F62EAF287AB17C +CT=2D380F99A182CD14CFFEF5E88B93B416 +PT=47FE8C67DCBC616E4C984D323EA4A45B + +I=59 +KEY=D79F78A4726F5FCA46FF663BF8A945AEFA6E639D16DE1527 +CT=47FE8C67DCBC616E4C984D323EA4A45B +PT=FA595C69C3286771FB8C921DFBBFFC2E + +I=60 +KEY=0C88AAD46F951FB6BCA63A523B8122DF01E2F180ED61E909 +CT=FA595C69C3286771FB8C921DFBBFFC2E +PT=8FA64C511FCE6FC987B327D12EBDADAD + +I=61 +KEY=762EEA21D382067E33007603244F4D168651D651C3DC44A4 +CT=8FA64C511FCE6FC987B327D12EBDADAD +PT=8F52C709508408B40C241FD38E515E76 + +I=62 +KEY=EA05788C20FB364EBC52B10A74CB45A28A75C9824D8D1AD2 +CT=8F52C709508408B40C241FD38E515E76 +PT=7CFD332B306684AC92279CE06F1287D8 + +I=63 +KEY=D4B2582B094D874DC0AF822144ADC10E18525562229F9D0A +CT=7CFD332B306684AC92279CE06F1287D8 +PT=0DA14F6619665E0128044355481BD658 + +I=64 +KEY=C080E7033FDF1BCFCD0ECD475DCB9F0F305616376A844B52 +CT=0DA14F6619665E0128044355481BD658 +PT=FEDEBE73AA4047AF27E86A8B9E8E2ED7 + +I=65 +KEY=C5BA9667999CF2D633D07334F78BD8A017BE7CBCF40A6585 +CT=FEDEBE73AA4047AF27E86A8B9E8E2ED7 +PT=12CD6896129E376AAB9C0E980F3B7CD2 + +I=66 +KEY=65FF092A539C4600211D1BA2E515EFCABC227224FB311957 +CT=12CD6896129E376AAB9C0E980F3B7CD2 +PT=04E7939B352F7B5C38B7EC5784EC78C2 + +I=67 +KEY=F98E7062F9EBE61C25FA8839D03A949684959E737FDD6195 +CT=04E7939B352F7B5C38B7EC5784EC78C2 +PT=0184996278A57E36E608E95616C46964 + +I=68 +KEY=306FBEFB3BF4E241247E115BA89FEAA0629D7725691908F1 +CT=0184996278A57E36E608E95616C46964 +PT=92179E392E05C8B96A0CFAC36109B09E + +I=69 +KEY=EE641F5DB58F9057B6698F62869A221908918DE60810B86F +CT=92179E392E05C8B96A0CFAC36109B09E +PT=7F197B01172C809635198E6B156D13BC + +I=70 +KEY=EADB8B255F98FD9DC970F46391B6A28F3D88038D1D7DABD3 +CT=7F197B01172C809635198E6B156D13BC +PT=46F6DD79AD079DCFBC451B24ECDDA4FA + +I=71 +KEY=47225D75FE68FFA08F86291A3CB13F4081CD18A9F1A00F29 +CT=46F6DD79AD079DCFBC451B24ECDDA4FA +PT=B5DAA09E3545F92FF44176187A1F9179 + +I=72 +KEY=7CDECC21E72E54F43A5C898409F4C66F758C6EB18BBF9E50 +CT=B5DAA09E3545F92FF44176187A1F9179 +PT=F51A35F3DD410132EEC9E9F22A6F6FAB + +I=73 +KEY=75D1AAFDBFE72C94CF46BC77D4B5C75D9B458743A1D0F1FB +CT=F51A35F3DD410132EEC9E9F22A6F6FAB +PT=D1CC6D95B58793C342CF14AF250D5E40 + +I=74 +KEY=41874C54BD58757A1E8AD1E26132549ED98A93EC84DDAFBB +CT=D1CC6D95B58793C342CF14AF250D5E40 +PT=A1FAB3B352A887A829357528FED4B80E + +I=75 +KEY=1D94704F4A51A5CABF706251339AD336F0BFE6C47A0917B5 +CT=A1FAB3B352A887A829357528FED4B80E +PT=CBC6473B3AA4DE2D64EED554CA241EAC + +I=76 +KEY=A41B52E0AE7E568074B6256A093E0D1B94513390B02D0919 +CT=CBC6473B3AA4DE2D64EED554CA241EAC +PT=19DC6E89D71DCE5DCECD1A6F85C3FBD6 + +I=77 +KEY=85F21BCD70691F596D6A4BE3DE23C3465A9C29FF35EEF2CF +CT=19DC6E89D71DCE5DCECD1A6F85C3FBD6 +PT=EC6974E51B21F26A100E66183C68FD15 + +I=78 +KEY=CAD0B254A88B669681033F06C502312C4A924FE709860FDA +CT=EC6974E51B21F26A100E66183C68FD15 +PT=A16B6F78009B6E30CB758E87AD4D8034 + +I=79 +KEY=8AC49B19582BFCF32068507EC5995F1C81E7C160A4CB8FEE +CT=A16B6F78009B6E30CB758E87AD4D8034 +PT=CB5C20AAFA898193BC34FF3EE460B313 + +I=80 +KEY=988F8D4F3A66AC99EB3470D43F10DE8F3DD33E5E40AB3CFD +CT=CB5C20AAFA898193BC34FF3EE460B313 +PT=397F92C8E69E0916E30DC6889779799E + +I=81 +KEY=DE2D26C6130E006ED24BE21CD98ED799DEDEF8D6D7D24563 +CT=397F92C8E69E0916E30DC6889779799E +PT=9A9CBD9380E2187855CAE5A73D58480F + +I=82 +KEY=BF6BE6D55C04977348D75F8F596CCFE18B141D71EA8A0D6C +CT=9A9CBD9380E2187855CAE5A73D58480F +PT=B67B360EE0FF297D3662F5B7CDB82CB9 + +I=83 +KEY=6582BCA895FA1221FEAC6981B993E69CBD76E8C6273221D5 +CT=B67B360EE0FF297D3662F5B7CDB82CB9 +PT=2D146ED9236082D2D71810969A1AB1FB + +I=84 +KEY=6AC68BB8BBC7F520D3B807589AF3644E6A6EF850BD28902E +CT=2D146ED9236082D2D71810969A1AB1FB +PT=4B9F55652C40B6DA963A98D875ADACE4 + +I=85 +KEY=180DAB1B14A92DB29827523DB6B3D294FC546088C8853CCA +CT=4B9F55652C40B6DA963A98D875ADACE4 +PT=FC0A8A3D511F5FAFF0A3DD13B49E5A13 + +I=86 +KEY=7ABD7440D5EE5FE2642DD800E7AC8D3B0CF7BD9B7C1B66D9 +CT=FC0A8A3D511F5FAFF0A3DD13B49E5A13 +PT=4231C02AD3231C3EB7AEB9135B95AC4B + +I=87 +KEY=54ACAE182B5FDACF261C182A348F9105BB590488278ECA92 +CT=4231C02AD3231C3EB7AEB9135B95AC4B +PT=4C3A949ACCCBB55F9415C81B1413FD9D + +I=88 +KEY=015706F99E81CC026A268CB0F844245A2F4CCC93339D370F +CT=4C3A949ACCCBB55F9415C81B1413FD9D +PT=E9B1CEAF77B64A88CC3E020B16E1BF7E + +I=89 +KEY=929BD0A1CC6450E78397421F8FF26ED2E372CE98257C8871 +CT=E9B1CEAF77B64A88CC3E020B16E1BF7E +PT=98FFEA0827068CB0B508CA520D8B43F7 + +I=90 +KEY=9B81EC47D8442D311B68A817A8F4E262567A04CA28F7CB86 +CT=98FFEA0827068CB0B508CA520D8B43F7 +PT=BEDA572C3CA3FEF97F7071DA35414EA1 + +I=91 +KEY=93B211B869CBECCBA5B2FF3B94571C9B290A75101DB68527 +CT=BEDA572C3CA3FEF97F7071DA35414EA1 +PT=35E8CB8302748C8623A09980909FB516 + +I=92 +KEY=BC5320E4025EB960905A34B89623901D0AAAEC908D293031 +CT=35E8CB8302748C8623A09980909FB516 +PT=E136148B2FA5AF5CD3F8BC3883566CB8 + +I=93 +KEY=C4EC937F948D0B5A716C2033B9863F41D95250A80E7F5C89 +CT=E136148B2FA5AF5CD3F8BC3883566CB8 +PT=B7CE40E3E3D30191CDF4AB5BE98F347A + +I=94 +KEY=6D381856C149D9DCC6A260D05A553ED014A6FBF3E7F068F3 +CT=B7CE40E3E3D30191CDF4AB5BE98F347A +PT=A821E934DAAE37FF3136E769DAC315FB + +I=95 +KEY=A3679C5957C656DE6E8389E480FB092F25901C9A3D337D08 +CT=A821E934DAAE37FF3136E769DAC315FB +PT=4227B96A0CC6CA1C21BCF8B1ADB3BDE1 + +I=96 +KEY=BE7112453B1DF3EC2CA4308E8C3DC333042CE42B9080C0E9 +CT=4227B96A0CC6CA1C21BCF8B1ADB3BDE1 +PT=EE36BBFDDF19165F9E64AE79B4CF06A9 + +I=97 +KEY=AEA4A2D5CD0A2FC7C2928B735324D56C9A484A52244FC640 +CT=EE36BBFDDF19165F9E64AE79B4CF06A9 +PT=C3DFE088C6767BC939F492C1FA9604CD + +I=98 +KEY=A16FC5F22F03984F014D6BFB9552AEA5A3BCD893DED9C28D +CT=C3DFE088C6767BC939F492C1FA9604CD +PT=DB1202E468119D977868F6E294E3CC3A + +I=99 +KEY=A4E0565DD419BDD1DA5F691FFD433332DBD42E714A3A0EB7 +CT=DB1202E468119D977868F6E294E3CC3A +PT=6F2F682BA4F95EB8C5B883C7660B2653 + +I=100 +KEY=3CAEE44D0E85058EB570013459BA6D8A1E6CADB62C3128E4 +CT=6F2F682BA4F95EB8C5B883C7660B2653 +PT=1036B4AA6C897D36DFE6658A953E5075 + +I=101 +KEY=4E883A500CA89963A546B59E353310BCC18AC83CB90F7891 +CT=1036B4AA6C897D36DFE6658A953E5075 +PT=04FCB3A81E5319A16CCF212719906229 + +I=102 +KEY=ADED5A405C5C095AA1BA06362B60091DAD45E91BA09F1AB8 +CT=04FCB3A81E5319A16CCF212719906229 +PT=CD79BAC069BB58605D43005B927816E5 + +I=103 +KEY=5499B441405D16B06CC3BCF642DB517DF006E94032E70C5D +CT=CD79BAC069BB58605D43005B927816E5 +PT=DB5B3C625D1F66CF28A86CC100472398 + +I=104 +KEY=D31221246382CA8EB79880941FC437B2D8AE858132A02FC5 +CT=DB5B3C625D1F66CF28A86CC100472398 +PT=D8732A2C16EC6AE202371AF03A6F91E8 + +I=105 +KEY=CDF928E97051F08B6FEBAAB809285D50DA999F7108CFBE2D +CT=D8732A2C16EC6AE202371AF03A6F91E8 +PT=F0A1A353A8AB9A893F621F0BEA3B4F01 + +I=106 +KEY=10CC2EED0ECBD1E69F4A09EBA183C7D9E5FB807AE2F4F12C +CT=F0A1A353A8AB9A893F621F0BEA3B4F01 +PT=27E4451BD15E43F301E138713DC12E78 + +I=107 +KEY=03C4F5E1FD3D34D1B8AE4CF070DD842AE41AB80BDF35DF54 +CT=27E4451BD15E43F301E138713DC12E78 +PT=C7FA931DA414CB37A9BDB6F128E082EE + +I=108 +KEY=CC5D7D36D085E3257F54DFEDD4C94F1D4DA70EFAF7D55DBA +CT=C7FA931DA414CB37A9BDB6F128E082EE +PT=A6777D51A0A1C94DD74A18795341015F + +I=109 +KEY=9F4EE4750FF3F53AD923A2BC746886509AED1683A4945CE5 +CT=A6777D51A0A1C94DD74A18795341015F +PT=32A4D930A5597E02D7076E399D18D895 + +I=110 +KEY=8525417BB6D8095BEB877B8CD131F8524DEA78BA398C8470 +CT=32A4D930A5597E02D7076E399D18D895 +PT=1B78FCF274EEB1E597998EE4EFFF9F8B + +I=111 +KEY=54EFA98071F1EF62F0FF877EA5DF49B7DA73F65ED6731BFB +CT=1B78FCF274EEB1E597998EE4EFFF9F8B +PT=2997FEE2823CC84DA14E8439449F5C7C + +I=112 +KEY=2505931CE4D41D16D968799C27E381FA7B3D726792EC4787 +CT=2997FEE2823CC84DA14E8439449F5C7C +PT=810534A9E8DB2808FEE681B13C04411D + +I=113 +KEY=C2DF863BEB4F27AB586D4D35CF38A9F285DBF3D6AEE8069A +CT=810534A9E8DB2808FEE681B13C04411D +PT=BE2380994365F1D7FC8278E86C8B497D + +I=114 +KEY=036C0C95D0C26B66E64ECDAC8C5D582579598B3EC2634FE7 +CT=BE2380994365F1D7FC8278E86C8B497D +PT=EFEC3977D5A21DC4AC786E786CA3ECE9 + +I=115 +KEY=BD05AD63A0A9F1B509A2F4DB59FF45E1D521E546AEC0A30E +CT=EFEC3977D5A21DC4AC786E786CA3ECE9 +PT=22A7280D8231895EA4F0B6A39AC583C3 + +I=116 +KEY=A16DFA00981597B42B05DCD6DBCECCBF71D153E5340520CD +CT=22A7280D8231895EA4F0B6A39AC583C3 +PT=0CC61E91B3CBCD0E190D52059E27647A + +I=117 +KEY=ABC1AD453235832727C3C247680501B168DC01E0AA2244B7 +CT=0CC61E91B3CBCD0E190D52059E27647A +PT=5CE91F77F7C8F0AB1BBA802D2FFF0E9B + +I=118 +KEY=64D40ACA0F526EC67B2ADD309FCDF11A736681CD85DD4A2C +CT=5CE91F77F7C8F0AB1BBA802D2FFF0E9B +PT=255459BE5A27E08942A049F6EC44582E + +I=119 +KEY=8BB5C7D8B2B177855E7E848EC5EA119331C6C83B69991202 +CT=255459BE5A27E08942A049F6EC44582E +PT=28E2E20115C3665D9D88CB74681301EA + +I=120 +KEY=4E30FCC4C182F471769C668FD02977CEAC4E034F018A13E8 +CT=28E2E20115C3665D9D88CB74681301EA +PT=2E96E6BBCD999F4B1507C7EC9E4B8430 + +I=121 +KEY=906B361E9D72E107580A80341DB0E885B949C4A39FC197D8 +CT=2E96E6BBCD999F4B1507C7EC9E4B8430 +PT=03DED0A95164E5FA215E9C49C433E95B + +I=122 +KEY=F656F5D9D973C02C5BD4509D4CD40D7F981758EA5BF27E83 +CT=03DED0A95164E5FA215E9C49C433E95B +PT=AD9C16D2567B73FCA4866FE16CF09CDA + +I=123 +KEY=8811A4ACDF37A140F648464F1AAF7E833C91370B3702E259 +CT=AD9C16D2567B73FCA4866FE16CF09CDA +PT=68539BFF0F8CC23A0A3267796A11B75C + +I=124 +KEY=E5AF2E8CDBAD01589E1BDDB01523BCB936A350725D135505 +CT=68539BFF0F8CC23A0A3267796A11B75C +PT=B15F623E5A7D73452A419EB04AFCF72E + +I=125 +KEY=C9E743CAD731A62E2F44BF8E4F5ECFFC1CE2CEC217EFA22B +CT=B15F623E5A7D73452A419EB04AFCF72E +PT=520142AFDA69E9CFA98D8DD59CCB12BC + +I=126 +KEY=6CF6C656FFBB77807D45FD2195372633B56F43178B24B097 +CT=520142AFDA69E9CFA98D8DD59CCB12BC +PT=7EC2A8430F23A5E183E0032DAB5232C5 + +I=127 +KEY=772CEE9F934D57D4038755629A1483D2368F403A20768252 +CT=7EC2A8430F23A5E183E0032DAB5232C5 +PT=E5E3A5D968B1FF774B55CCA06BE3BD65 + +I=128 +KEY=9A4DAB93F3C74EBBE664F0BBF2A57CA57DDA8C9A4B953F37 +CT=E5E3A5D968B1FF774B55CCA06BE3BD65 +PT=9608643D0A34DA28372A7E7E34427E1B + +I=129 +KEY=EF0F60BCBA3374E0706C9486F891A68D4AF0F2E47FD7412C +CT=9608643D0A34DA28372A7E7E34427E1B +PT=B22BD410584F29610801B18EDAB1BD19 + +I=130 +KEY=DE013A6C3440AFF3C2474096A0DE8FEC42F1436AA566FC35 +CT=B22BD410584F29610801B18EDAB1BD19 +PT=ADEC4519F1A7AD74BCCECABEDCF20D73 + +I=131 +KEY=2B5B547A934A5A376FAB058F51792298FE3F89D47994F146 +CT=ADEC4519F1A7AD74BCCECABEDCF20D73 +PT=E04D4FF54191BEEEF5B295A32DA2ADE5 + +I=132 +KEY=BF356F2FFC2C538F8FE64A7A10E89C760B8D1C7754365CA3 +CT=E04D4FF54191BEEEF5B295A32DA2ADE5 +PT=3F9531EDD5072F7A9F2A62ECC2CCE50A + +I=133 +KEY=7CEBD7310CC4791AB0737B97C5EFB30C94A77E9B96FAB9A9 +CT=3F9531EDD5072F7A9F2A62ECC2CCE50A +PT=C3DC95781FAE7BB6C02BD08B3617DDF1 + +I=134 +KEY=192741D2AB9C887673AFEEEFDA41C8BA548CAE10A0ED6458 +CT=C3DC95781FAE7BB6C02BD08B3617DDF1 +PT=F69B837F168B9A9E637E7357B65F2B60 + +I=135 +KEY=38552740A79FB5BF85346D90CCCA522437F2DD4716B24F38 +CT=F69B837F168B9A9E637E7357B65F2B60 +PT=40DCDF58E7EFDD62C114A83F8AC898BB + +I=136 +KEY=A0AED2C07C2168B6C5E8B2C82B258F46F6E675789C7AD783 +CT=40DCDF58E7EFDD62C114A83F8AC898BB +PT=27F78F3BD8E04A8646EBF364155A71ED + +I=137 +KEY=2B4FAEBF17993E12E21F3DF3F3C5C5C0B00D861C8920A66E +CT=27F78F3BD8E04A8646EBF364155A71ED +PT=F305DFC8EAD44E786F59B0551C7104F5 + +I=138 +KEY=96819F6E9738209F111AE23B19118BB8DF5436499551A29B +CT=F305DFC8EAD44E786F59B0551C7104F5 +PT=2E47F833BE7C06ED1E42AC11366F4BEF + +I=139 +KEY=AAEA16BAC3E84DD73F5D1A08A76D8D55C1169A58A33EE974 +CT=2E47F833BE7C06ED1E42AC11366F4BEF +PT=A9D3A511C3D76779B607AAB2556823AD + +I=140 +KEY=F66BA47C56AC5A36968EBF1964BAEA2C771130EAF656CAD9 +CT=A9D3A511C3D76779B607AAB2556823AD +PT=153A7CC2387C05289F759C85076CDD88 + +I=141 +KEY=1D892BCCFAF3DA1083B4C3DB5CC6EF04E864AC6FF13A1751 +CT=153A7CC2387C05289F759C85076CDD88 +PT=76B6089030D914F0F4C6078193207A7D + +I=142 +KEY=DAEBAF980095A397F502CB4B6C1FFBF41CA2ABEE621A6D2C +CT=76B6089030D914F0F4C6078193207A7D +PT=EB71D127848BA397451D45801830461E + +I=143 +KEY=85F86FADA92076AB1E731A6CE894586359BFEE6E7A2A2B32 +CT=EB71D127848BA397451D45801830461E +PT=B79D9BE1B2DB808B412413C203C710DF + +I=144 +KEY=BEADDA5CE1E7F3D4A9EE818D5A4FD8E8189BFDAC79ED3BED +CT=B79D9BE1B2DB808B412413C203C710DF +PT=E6423467C3CA69D94C944FA2A97BB61F + +I=145 +KEY=D4664C8DCFA8304D4FACB5EA9985B131540FB20ED0968DF2 +CT=E6423467C3CA69D94C944FA2A97BB61F +PT=18EFF53B7D62A9D9ED8AB9ABE67FC110 + +I=146 +KEY=9CCF1EEAF55FEA5A574340D1E4E718E8B9850BA536E94CE2 +CT=18EFF53B7D62A9D9ED8AB9ABE67FC110 +PT=8E6A4AC577153D806ED71A07319CAB67 + +I=147 +KEY=7D840184CB9D3A05D9290A1493F22568D75211A20775E785 +CT=8E6A4AC577153D806ED71A07319CAB67 +PT=B7B23D8E7D344F39B3EA0D67CCF37377 + +I=148 +KEY=D72F35B6DD825B656E9B379AEEC66A5164B81CC5CB8694F2 +CT=B7B23D8E7D344F39B3EA0D67CCF37377 +PT=3385AD0503AF68BFBFBEAA89B1C87736 + +I=149 +KEY=48335F06D7C27C955D1E9A9FED6902EEDB06B64C7A4EE3C4 +CT=3385AD0503AF68BFBFBEAA89B1C87736 +PT=9FC40A6B984BEEC182AB650B05CEF38C + +I=150 +KEY=A66149286535FD6EC2DA90F47522EC2F59ADD3477F801048 +CT=9FC40A6B984BEEC182AB650B05CEF38C +PT=4CEC52C9DE143486DFC9D098637DFBB5 + +I=151 +KEY=7EA78450FAEEF8BF8E36C23DAB36D8A9866403DF1CFDEBFD +CT=4CEC52C9DE143486DFC9D098637DFBB5 +PT=EB8E40333ACD18EFB04DC0A857DDCD7A + +I=152 +KEY=197DDF842BAEF36E65B8820E91FBC0463629C3774B202687 +CT=EB8E40333ACD18EFB04DC0A857DDCD7A +PT=F1AFF04058F819B0F191398C8022130F + +I=153 +KEY=D68841CF848B0F619417724EC903D9F6C7B8FAFBCB023588 +CT=F1AFF04058F819B0F191398C8022130F +PT=6DF4A95D8D602C0E53F5A5C350D3EB64 + +I=154 +KEY=6DFA0F7B01A2F011F9E3DB134463F5F8944D5F389BD1DEEC +CT=6DF4A95D8D602C0E53F5A5C350D3EB64 +PT=057D8F9BE9260BB3A0382CD2EF7D1FCA + +I=155 +KEY=88227C4AD1CBC8F0FC9E5488AD45FE4B347573EA74ACC126 +CT=057D8F9BE9260BB3A0382CD2EF7D1FCA +PT=D4EDACCB9B7B35F2A0690E22C91E25AE + +I=156 +KEY=848B8E3213D366B22873F843363ECBB9941C7DC8BDB2E488 +CT=D4EDACCB9B7B35F2A0690E22C91E25AE +PT=A2F61B5BDD9F580B26C329B878BAFA3C + +I=157 +KEY=FA3A476D1C6E33FD8A85E318EBA193B2B2DF5470C5081EB4 +CT=A2F61B5BDD9F580B26C329B878BAFA3C +PT=5A0616880CD40B72B58CF268EC8F934B + +I=158 +KEY=C9F77D58F58D5FEDD083F590E77598C00753A61829878DFF +CT=5A0616880CD40B72B58CF268EC8F934B +PT=0E42047D7EDE2A5FBB37767A69A45B9B + +I=159 +KEY=00A523C700FBB663DEC1F1ED99ABB29FBC64D0624023D664 +CT=0E42047D7EDE2A5FBB37767A69A45B9B +PT=2AFA823A10BB436A7B00816C80A52711 + +I=160 +KEY=660275323A59E807F43B73D78910F1F5C764510EC086F175 +CT=2AFA823A10BB436A7B00816C80A52711 +PT=B2406F3F9160E25DF7C9AA81AF6EB449 + +I=161 +KEY=47A4FCDB97D4A383467B1CE8187013A830ADFB8F6FE8453C +CT=B2406F3F9160E25DF7C9AA81AF6EB449 +PT=B1E01D2A401495F8DDAEAB7B04BEB23D + +I=162 +KEY=2BDD5B54D4EB236AF79B01C258648650ED0350F46B56F701 +CT=B1E01D2A401495F8DDAEAB7B04BEB23D +PT=390572A9ECE28A0E0BBDC729DBE5F79A + +I=163 +KEY=328202460B65D004CE9E736BB4860C5EE6BE97DDB0B3009B +CT=390572A9ECE28A0E0BBDC729DBE5F79A +PT=5D41665811702124C597DB4E3BD950E1 + +I=164 +KEY=94457C0A759DF4E993DF1533A5F62D7A23294C938B6A507A +CT=5D41665811702124C597DB4E3BD950E1 +PT=689EB1CB1586D127696E8725DEE49E58 + +I=165 +KEY=4E0226CA850DDC79FB41A4F8B070FC5D4A47CBB6558ECE22 +CT=689EB1CB1586D127696E8725DEE49E58 +PT=A2D9DF62AC8BF8A93E7A954416864052 + +I=166 +KEY=659C817A1C10A24D59987B9A1CFB04F4743D5EF243088E70 +CT=A2D9DF62AC8BF8A93E7A954416864052 +PT=507835696F1920BD4A05797563DF5769 + +I=167 +KEY=92192D9175187FB409E04EF373E224493E38278720D7D919 +CT=507835696F1920BD4A05797563DF5769 +PT=2070413F5103482B6C83129304E5AC87 + +I=168 +KEY=6959063FBA59CCEC29900FCC22E16C6252BB35142432759E +CT=2070413F5103482B6C83129304E5AC87 +PT=BF7FD1E21B41B1F1C2625C1097F1BCB8 + +I=169 +KEY=5722993710D811B196EFDE2E39A0DD9390D96904B3C3C926 +CT=BF7FD1E21B41B1F1C2625C1097F1BCB8 +PT=6E2236654F2999545F50FA9CF63F9F2E + +I=170 +KEY=038FA98E7A226A9FF8CDE84B768944C7CF89939845FC5608 +CT=6E2236654F2999545F50FA9CF63F9F2E +PT=3F370291CEDCB115C8EE409A8EEB46D6 + +I=171 +KEY=CACF0199725D5466C7FAEADAB855F5D20767D302CB1710DE +CT=3F370291CEDCB115C8EE409A8EEB46D6 +PT=84023DB96D373EC8315AE78A3B7E82FB + +I=172 +KEY=7B40321CB11520D143F8D763D562CB1A363D3488F0699225 +CT=84023DB96D373EC8315AE78A3B7E82FB +PT=C35064D82A3016FE2C2E2CC0627E7B5C + +I=173 +KEY=F045CFEC2A6BC7E580A8B3BBFF52DDE41A1318489217E979 +CT=C35064D82A3016FE2C2E2CC0627E7B5C +PT=D78DFFE87C0F95856C31A07BADA23084 + +I=174 +KEY=86B3CA5F50CEF6C557254C53835D48617622B8333FB5D9FD +CT=D78DFFE87C0F95856C31A07BADA23084 +PT=5B5B5D3CA5C6E5CF18F3E4EE802BE82B + +I=175 +KEY=E6D99DC0C58655B70C7E116F269BADAE6ED15CDDBF9E31D6 +CT=5B5B5D3CA5C6E5CF18F3E4EE802BE82B +PT=DB65A82F6EB7A410A367165900E85117 + +I=176 +KEY=B8F770CFBE47D070D71BB940482C09BECDB64A84BF7660C1 +CT=DB65A82F6EB7A410A367165900E85117 +PT=FE8BE8484D925043102238FF63FDAC57 + +I=177 +KEY=FF09ADB06FE587192990510805BE59FDDD94727BDC8BCC96 +CT=FE8BE8484D925043102238FF63FDAC57 +PT=AC36E01A7AD482A8D89703D2A6528720 + +I=178 +KEY=B5C937A4019CDAD185A6B1127F6ADB55050371A97AD94BB6 +CT=AC36E01A7AD482A8D89703D2A6528720 +PT=9F3698CE06C6497C89B58CA723F7ECAA + +I=179 +KEY=F60CAF8FB99B63B21A9029DC79AC92298CB6FD0E592EA71C +CT=9F3698CE06C6497C89B58CA723F7ECAA +PT=FB8CE2E1D332FE4557B6C5CF1676F2FB + +I=180 +KEY=B7CF2BABD58B5FDCE11CCB3DAA9E6C6CDB0038C14F5855E7 +CT=FB8CE2E1D332FE4557B6C5CF1676F2FB +PT=A2631F612698318AD454E9DB10319DA6 + +I=181 +KEY=FD99B4137CAFC47F437FD45C8C065DE60F54D11A5F69C841 +CT=A2631F612698318AD454E9DB10319DA6 +PT=FCA42B332B5974EE6DFA54B54EC89AC7 + +I=182 +KEY=271CEEF189AD367DBFDBFF6FA75F290862AE85AF11A15286 +CT=FCA42B332B5974EE6DFA54B54EC89AC7 +PT=A70DBBDFCE54B8648C3FC4A8A58CCDF8 + +I=183 +KEY=7B78F7ECC9B28EC718D644B0690B916CEE914107B42D9F7E +CT=A70DBBDFCE54B8648C3FC4A8A58CCDF8 +PT=C90CE914F9310F9C3EE065DD95281A51 + +I=184 +KEY=762F521ADF6C5F24D1DAADA4903A9EF0D07124DA2105852F +CT=C90CE914F9310F9C3EE065DD95281A51 +PT=63E8430CE22F531E4A4D4583533F6FC4 + +I=185 +KEY=A88A493EB3C28C49B232EEA87215CDEE9A3C6159723AEAEB +CT=63E8430CE22F531E4A4D4583533F6FC4 +PT=E7562DC647910A052F4AFBF165A68A3A + +I=186 +KEY=1C97343A60EE05035564C36E3584C7EBB5769AA8179C60D1 +CT=E7562DC647910A052F4AFBF165A68A3A +PT=3E070B3F65FD01B49849513B556DB199 + +I=187 +KEY=C5110692100A332E6B63C8515079C65F2D3FCB9342F1D148 +CT=3E070B3F65FD01B49849513B556DB199 +PT=3DE5A45B2CAA4FAFAC3032F89F15195D + +I=188 +KEY=D94D8CAA9EBD67F056866C0A7CD389F0810FF96BDDE4C815 +CT=3DE5A45B2CAA4FAFAC3032F89F15195D +PT=A36A163E8806B1E053EBE439B0D1302F + +I=189 +KEY=1C1D7A3E9358048CF5EC7A34F4D53810D2E41D526D35F83A +CT=A36A163E8806B1E053EBE439B0D1302F +PT=67CA4B988CCABA4E4DBEE6C387562762 + +I=190 +KEY=9182E40D14973087922631AC781F825E9F5AFB91EA63DF58 +CT=67CA4B988CCABA4E4DBEE6C387562762 +PT=9F404F0E1A9FE5A988CE6E4A54FE9E23 + +I=191 +KEY=7D89ECFC0DCFFE0A0D667EA2628067F7179495DBBE9D417B +CT=9F404F0E1A9FE5A988CE6E4A54FE9E23 +PT=D71EFD794457C71614E4266C77193444 + +I=192 +KEY=AC7A11D29CDA0FB6DA7883DB26D7A0E10370B3B7C984753F +CT=D71EFD794457C71614E4266C77193444 +PT=185DBF418A6834CD118B16EAF381F3CB + +I=193 +KEY=1029D5FA3D38927EC2253C9AACBF942C12FBA55D3A0586F4 +CT=185DBF418A6834CD118B16EAF381F3CB +PT=737A502DEE68DDFA3FEECD42ACE124EA + +I=194 +KEY=F261B484C642750CB15F6CB742D749D62D15681F96E4A21E +CT=737A502DEE68DDFA3FEECD42ACE124EA +PT=FD11B0F356455913E892928B5B16946B + +I=195 +KEY=BCCFAF05FF47A5EC4C4EDC44149210C5C587FA94CDF23675 +CT=FD11B0F356455913E892928B5B16946B +PT=4B06F6D6D149BAF25D4C76E46EFF8571 + +I=196 +KEY=1000A15983B73D6807482A92C5DBAA3798CB8C70A30DB304 +CT=4B06F6D6D149BAF25D4C76E46EFF8571 +PT=450713DA24492403C48CB16D2F39744E + +I=197 +KEY=306F097E64B634AC424F3948E1928E345C473D1D8C34C74A +CT=450713DA24492403C48CB16D2F39744E +PT=998CA5E3C80B66EB11EAD376FA358A92 + +I=198 +KEY=13965208C3EF77E1DBC39CAB2999E8DF4DADEE6B76014DD8 +CT=998CA5E3C80B66EB11EAD376FA358A92 +PT=F54A34F6F0833CA808D60A8F75BB0585 + +I=199 +KEY=1A6DC3FDD0D1F97C2E89A85DD91AD477457BE4E403BA485D +CT=F54A34F6F0833CA808D60A8F75BB0585 +PT=8760D5CBD1DA48807BAEAF7F781680F2 + +I=200 +KEY=228897B4E2F16967A9E97D9608C09CF73ED54B9B7BACC8AF +CT=8760D5CBD1DA48807BAEAF7F781680F2 +PT=EF57DF7161E1BC0F7B466A50C576691A + +I=201 +KEY=D0E8190E72A305C946BEA2E7692120F8459321CBBEDAA1B5 +CT=EF57DF7161E1BC0F7B466A50C576691A +PT=E01ECA338A93EA38E43B2F364314C121 + +I=202 +KEY=087F0486B80659F0A6A068D4E3B2CAC0A1A80EFDFDCE6094 +CT=E01ECA338A93EA38E43B2F364314C121 +PT=A7683273638D02272FF6A311BB94256F + +I=203 +KEY=1D807E4730DDA3EB01C85AA7803FC8E78E5EADEC465A45FB +CT=A7683273638D02272FF6A311BB94256F +PT=1BCC3DF6B07BD2615C13E381F5F877C3 + +I=204 +KEY=D4D4F2780D52D7521A04675130441A86D24D4E6DB3A23238 +CT=1BCC3DF6B07BD2615C13E381F5F877C3 +PT=D1B3B793D1377E82A2DE5D46E53791FB + +I=205 +KEY=86D08D85652DB662CBB7D0C2E17364047093132B5695A3C3 +CT=D1B3B793D1377E82A2DE5D46E53791FB +PT=9AC7AF9B82621E18E4FF613EAA609F46 + +I=206 +KEY=C03996907AC99A7A51707F5963117A1C946C7215FCF53C85 +CT=9AC7AF9B82621E18E4FF613EAA609F46 +PT=57F3FA35A42C29F33DEC4671140264A4 + +I=207 +KEY=F8CA52D95C587EF80683856CC73D53EFA9803464E8F75821 +CT=57F3FA35A42C29F33DEC4671140264A4 +PT=A887ED8BF6C19F5012F317A4FCF3D7BF + +I=208 +KEY=DE99CC8F9756C1DCAE0468E731FCCCBFBB7323C014048F9E +CT=A887ED8BF6C19F5012F317A4FCF3D7BF +PT=A29C8D764BCF211C789158A9B8EB330C + +I=209 +KEY=9228DB1B61E0D8670C98E5917A33EDA3C3E27B69ACEFBC92 +CT=A29C8D764BCF211C789158A9B8EB330C +PT=EB6AFD9B36315DB322EC8C4243043F50 + +I=210 +KEY=24AFE14097C2A217E7F2180A4C02B010E10EF72BEFEB83C2 +CT=EB6AFD9B36315DB322EC8C4243043F50 +PT=05C8AC90CCD00E2A3809C68C11D6D65A + +I=211 +KEY=32810943F9313BD0E23AB49A80D2BE3AD90731A7FE3D5598 +CT=05C8AC90CCD00E2A3809C68C11D6D65A +PT=E39991B58C52154166AD09367B04C67A + +I=212 +KEY=FBEC72A177254EA501A3252F0C80AB7BBFAA3891853993E2 +CT=E39991B58C52154166AD09367B04C67A +PT=CBC8974F72F77A1821FC69B29FE2DB60 + +I=213 +KEY=C706D206DE538439CA6BB2607E77D1639E5651231ADB4882 +CT=CBC8974F72F77A1821FC69B29FE2DB60 +PT=1D08F4E2B8DFED1032B6CA5211B3E34C + +I=214 +KEY=9A7EB0A4F8E67F87D7634682C6A83C73ACE09B710B68ABCE +CT=1D08F4E2B8DFED1032B6CA5211B3E34C +PT=1888CEC22449EFF96BDC2C7A242BBBDC + +I=215 +KEY=70CA2CAD6A50D22BCFEB8840E2E1D38AC73CB70B2F431012 +CT=1888CEC22449EFF96BDC2C7A242BBBDC +PT=032E6155677B6A72D7F94C7A9A9AA53F + +I=216 +KEY=B16697FEA247CDB9CCC5E915859AB9F810C5FB71B5D9B52D +CT=032E6155677B6A72D7F94C7A9A9AA53F +PT=9B43BBD1C0CEBF7593E9BC0ABB626E96 + +I=217 +KEY=7A3E844BEB897A63578652C44554068D832C477B0EBBDBBB +CT=9B43BBD1C0CEBF7593E9BC0ABB626E96 +PT=8D661E03C61C28D5786EBCEBE0D5B63D + +I=218 +KEY=E7A1B96EFC4D5FB5DAE04CC783482E58FB42FB90EE6E6D86 +CT=8D661E03C61C28D5786EBCEBE0D5B63D +PT=F61D5DCBF8F2F3F0EAB387149790E079 + +I=219 +KEY=0EDA761C06FBA0A02CFD110C7BBADDA811F17C8479FE8DFF +CT=F61D5DCBF8F2F3F0EAB387149790E079 +PT=1F03E0957B6892533BBEAB06EB35AD4F + +I=220 +KEY=E242AD5B7141916133FEF19900D24FFB2A4FD78292CB20B0 +CT=1F03E0957B6892533BBEAB06EB35AD4F +PT=BB9E7343035F88764B229D506E7ADC7B + +I=221 +KEY=D901A6CF874A6A77886082DA038DC78D616D4AD2FCB1FCCB +CT=BB9E7343035F88764B229D506E7ADC7B +PT=3934EBF7AD2243C0D09734E30B41C0E4 + +I=222 +KEY=0F488E86E7D92F29B154692DAEAF844DB1FA7E31F7F03C2F +CT=3934EBF7AD2243C0D09734E30B41C0E4 +PT=B9CE1A1A9595E7235F5B10FBA29ACCD2 + +I=223 +KEY=A7E2CF991692247A089A73373B3A636EEEA16ECA556AF0FD +CT=B9CE1A1A9595E7235F5B10FBA29ACCD2 +PT=624EBA65EE9E3E1BDF8C5AA7E1283A65 + +I=224 +KEY=1DE03E09395E56CE6AD4C952D5A45D75312D346DB442CA98 +CT=624EBA65EE9E3E1BDF8C5AA7E1283A65 +PT=375132E5F47DA19E80CC8652BE5A3692 + +I=225 +KEY=51B6813629EFE53C5D85FBB721D9FCEBB1E1B23F0A18FC0A +CT=375132E5F47DA19E80CC8652BE5A3692 +PT=8165A4126FE75EFC6AFF7BFD732F94A6 + +I=226 +KEY=8DD50DFF93624339DCE05FA54E3EA217DB1EC9C2793768AC +CT=8165A4126FE75EFC6AFF7BFD732F94A6 +PT=35012FABD289E6B7FB07946591D18F0D + +I=227 +KEY=C7A4F75CB74C7F3DE9E1700E9CB744A020195DA7E8E6E7A1 +CT=35012FABD289E6B7FB07946591D18F0D +PT=C26F37D700677ED72F4FC2C8F6AEADE2 + +I=228 +KEY=198B572CD0E711352B8E47D99CD03A770F569F6F1E484A43 +CT=C26F37D700677ED72F4FC2C8F6AEADE2 +PT=CB29ECE41596736B72AED2460AEEFBA2 + +I=229 +KEY=0A1FB41CA720E357E0A7AB3D8946491C7DF84D2914A6B1E1 +CT=CB29ECE41596736B72AED2460AEEFBA2 +PT=7F7BD6FAF9C37D5522A3BF480CCEBF20 + +I=230 +KEY=7E383601899DEA729FDC7DC7708534495F5BF26118680EC1 +CT=7F7BD6FAF9C37D5522A3BF480CCEBF20 +PT=C501E371005DF57E0037F41A744D026F + +I=231 +KEY=13ACF410865B41E15ADD9EB670D8C1375F6C067B6C250CAE +CT=C501E371005DF57E0037F41A744D026F +PT=624EF8749580108CDC7A020179F81D0F + +I=232 +KEY=75F025072AA2406F389366C2E558D1BB8316047A15DD11A1 +CT=624EF8749580108CDC7A020179F81D0F +PT=40D72550603522C67180DE6EC3D30139 + +I=233 +KEY=C5ED76F88EA65C3D78444392856DF37DF296DA14D60E1098 +CT=40D72550603522C67180DE6EC3D30139 +PT=96C6F647AFB90F804431F9E2F1780F29 + +I=234 +KEY=E827DFF88D0B1A43EE82B5D52AD4FCFDB6A723F627761FB1 +CT=96C6F647AFB90F804431F9E2F1780F29 +PT=CCB934A501DDAD11E994938A214EB189 + +I=235 +KEY=F0777D1BFF12EE42223B81702B0951EC5F33B07C0638AE38 +CT=CCB934A501DDAD11E994938A214EB189 +PT=07825F2D35E761C76893B697E30E4D08 + +I=236 +KEY=6912B59C06C90D3725B9DE5D1EEE302B37A006EBE536E330 +CT=07825F2D35E761C76893B697E30E4D08 +PT=1F674E97F88EB1DA1DD24C0AB4321258 + +I=237 +KEY=AE24933526FAE5F83ADE90CAE66081F12A724AE15104F168 +CT=1F674E97F88EB1DA1DD24C0AB4321258 +PT=B6DE499EBE0B3C30F1DAC8E40FE9F10C + +I=238 +KEY=F348F88852CF356C8C00D954586BBDC1DBA882055EED0064 +CT=B6DE499EBE0B3C30F1DAC8E40FE9F10C +PT=105E31DBDE33764B098862AF6D0B6CD2 + +I=239 +KEY=83B06CC00A17D3149C5EE88F8658CB8AD220E0AA33E66CB6 +CT=105E31DBDE33764B098862AF6D0B6CD2 +PT=697D6537677B20C188246FBF4997C7CB + +I=240 +KEY=A5381A9C91D61A01F5238DB8E123EB4B5A048F157A71AB7D +CT=697D6537677B20C188246FBF4997C7CB +PT=4FBFB0EFBA92C1E0189E2C3097AA35BA + +I=241 +KEY=FDF831A7D1345AFEBA9C3D575BB12AAB429AA325EDDB9EC7 +CT=4FBFB0EFBA92C1E0189E2C3097AA35BA +PT=600288531DCEB99B69A7890CE804FA9F + +I=242 +KEY=A10ED54E7B2B2B2BDA9EB504467F93302B3D2A2905DF6458 +CT=600288531DCEB99B69A7890CE804FA9F +PT=EE94D4376D9332C8DCD05C695EDB124F + +I=243 +KEY=2F69F01250D7745F340A61332BECA1F8F7ED76405B047617 +CT=EE94D4376D9332C8DCD05C695EDB124F +PT=7EDC3182C36DC5A172B170A919524888 + +I=244 +KEY=FCD5F8FAB347624E4AD650B1E8816459855C06E942563E9F +CT=7EDC3182C36DC5A172B170A919524888 +PT=95FA03C96DFCB9ABCFF23B5ABFBABCDE + +I=245 +KEY=A9307E62197A747EDF2C5378857DDDF24AAE3DB3FDEC8241 +CT=95FA03C96DFCB9ABCFF23B5ABFBABCDE +PT=6CE2C6CFC61667965C20B0BE11B55DDE + +I=246 +KEY=DA3B03896DDFDE08B3CE95B7436BBA64168E8D0DEC59DF9F +CT=6CE2C6CFC61667965C20B0BE11B55DDE +PT=3DBDFBE63A6FAE7572C778108A62A27C + +I=247 +KEY=7D766BAD6E536CE38E736E51790414116449F51D663B7DE3 +CT=3DBDFBE63A6FAE7572C778108A62A27C +PT=1C197D3449FED6ED6924E14B43A17BF0 + +I=248 +KEY=36F69C30B0272CAB926A136530FAC2FC0D6D1456259A0613 +CT=1C197D3449FED6ED6924E14B43A17BF0 +PT=0B0CCC6F508C18168284F7976AD81BEE + +I=249 +KEY=632661C312B2EB5D9966DF0A6076DAEA8FE9E3C14F421DFD +CT=0B0CCC6F508C18168284F7976AD81BEE +PT=F437B8FD92CE37D8D74550C5BE29BF99 + +I=250 +KEY=5FB1BDFC29EFE2DA6D5167F7F2B8ED3258ACB304F16BA264 +CT=F437B8FD92CE37D8D74550C5BE29BF99 +PT=78F6E6F6480A04F5632EA112170F928C + +I=251 +KEY=2B24C5188F4A2E7B15A78101BAB2E9C73B821216E66430E8 +CT=78F6E6F6480A04F5632EA112170F928C +PT=2FD38831EE4D09DD8DB9A84B5825B528 + +I=252 +KEY=F816FB720A08828C3A74093054FFE01AB63BBA5DBE4185C0 +CT=2FD38831EE4D09DD8DB9A84B5825B528 +PT=ED307697B51CFAD7052A3A7B3A564990 + +I=253 +KEY=776B08F4778FAB96D7447FA7E1E31ACDB31180268417CC50 +CT=ED307697B51CFAD7052A3A7B3A564990 +PT=DB9952A98F0D4B045C624EFA5619CAF9 + +I=254 +KEY=C7A944C9BA2D5F740CDD2D0E6EEE51C9EF73CEDCD20E06A9 +CT=DB9952A98F0D4B045C624EFA5619CAF9 +PT=DADA40BF0E367AF50874BB2628251AA3 + +I=255 +KEY=69B8688D9C1ECD95D6076DB160D82B3CE70775FAFA2B1C0A +CT=DADA40BF0E367AF50874BB2628251AA3 +PT=35DFA85D3F2D7F47DD7865EA0BC73A5C + +I=256 +KEY=7E6C7E90EDE36F44E3D8C5EC5FF5547B3A7F1010F1EC2656 +CT=35DFA85D3F2D7F47DD7865EA0BC73A5C +PT=EE0231F994C2DB6C7C04746170F03E54 + +I=257 +KEY=0E56C8FD184AB5D40DDAF415CB378F17467B6471811C1802 +CT=EE0231F994C2DB6C7C04746170F03E54 +PT=D9F314FEAD11122CE8F532ED0C0B129C + +I=258 +KEY=267BC5325796002BD429E0EB66269D3BAE8E569C8D170A9E +CT=D9F314FEAD11122CE8F532ED0C0B129C +PT=74A32BDFF53A59F09AAFB328977E05B1 + +I=259 +KEY=889B6087CAAD1B43A08ACB34931CC4CB3421E5B41A690F2F +CT=74A32BDFF53A59F09AAFB328977E05B1 +PT=D4CCC3077C15EE470D5EFCF815A48410 + +I=260 +KEY=F9AE78D077E3F98574460833EF092A8C397F194C0FCD8B3F +CT=D4CCC3077C15EE470D5EFCF815A48410 +PT=29284B0E7776DFB8BB536B3C16399D62 + +I=261 +KEY=71BBCD4B1F4B04265D6E433D987FF534822C727019F4165D +CT=29284B0E7776DFB8BB536B3C16399D62 +PT=202326CEAD57A5C13592FFBFFD5BF508 + +I=262 +KEY=F6F461C7931CF0317D4D65F3352850F5B7BE8DCFE4AFE355 +CT=202326CEAD57A5C13592FFBFFD5BF508 +PT=B9AFAD0658E1A4A1EECAA25B2863AD53 + +I=263 +KEY=BC0D82D3B7909D54C4E2C8F56DC9F45459742F94CCCC4E06 +CT=B9AFAD0658E1A4A1EECAA25B2863AD53 +PT=DE7AC7F7381DD34F3148911F306F4161 + +I=264 +KEY=339FFE2E01AB1D621A980F0255D4271B683CBE8BFCA30F67 +CT=DE7AC7F7381DD34F3148911F306F4161 +PT=F197DE9FED1EA08F6C17E631BF5449FE + +I=265 +KEY=EC908F9A4F266644EB0FD19DB8CA8794042B58BA43F74699 +CT=F197DE9FED1EA08F6C17E631BF5449FE +PT=7E1416C06ED3F56782DB5CB536B9B56E + +I=266 +KEY=CFE36CCCC94F8A5B951BC75DD61972F386F0040F754EF3F7 +CT=7E1416C06ED3F56782DB5CB536B9B56E +PT=BE1FE1F7B4CFF55D15BBCB6D9313729D + +I=267 +KEY=90690906407FB8AC2B0426AA62D687AE934BCF62E65D816A +CT=BE1FE1F7B4CFF55D15BBCB6D9313729D +PT=50E6818C06583D3D1C99C4A127D118CF + +I=268 +KEY=5D2A712578EC47217BE2A726648EBA938FD20BC3C18C99A5 +CT=50E6818C06583D3D1C99C4A127D118CF +PT=E1BFD3ED18E9A6D7BF383D590DA23B59 + +I=269 +KEY=3CA141EE57D7E0FC9A5D74CB7C671C4430EA369ACC2EA2FC +CT=E1BFD3ED18E9A6D7BF383D590DA23B59 +PT=03961127347C141C01F5276CB9BB31F7 + +I=270 +KEY=65E9B8AE22DC52A599CB65EC481B0858311F11F67595930B +CT=03961127347C141C01F5276CB9BB31F7 +PT=E9A8336DC0B530A86988B2DE74EDFFA1 + +I=271 +KEY=870A30E0F3B836FA7063568188AE38F05897A32801786CAA +CT=E9A8336DC0B530A86988B2DE74EDFFA1 +PT=B5FA5E388CFFFE2BA33436CC39A73972 + +I=272 +KEY=4B81E55C765F570CC59908B90451C6DBFBA395E438DF55D8 +CT=B5FA5E388CFFFE2BA33436CC39A73972 +PT=CEF4896BBC86F1E02312479C40D96DAE + +I=273 +KEY=0FAB0DCFB6E3E7940B6D81D2B8D7373BD8B1D27878063876 +CT=CEF4896BBC86F1E02312479C40D96DAE +PT=F195F5321FCAA68B0B0CBA83978A8084 + +I=274 +KEY=F860076D3847A80BFAF874E0A71D91B0D3BD68FBEF8CB8F2 +CT=F195F5321FCAA68B0B0CBA83978A8084 +PT=861575205386223EBC6B48B22C35A2A6 + +I=275 +KEY=B2DB77DC3E18C3A77CED01C0F49BB38E6FD62049C3B91A54 +CT=861575205386223EBC6B48B22C35A2A6 +PT=DC074F3D41C62DA9D609A982DEB9E074 + +I=276 +KEY=E632B0C6EE68910EA0EA4EFDB55D9E27B9DF89CB1D00FA20 +CT=DC074F3D41C62DA9D609A982DEB9E074 +PT=6933F4F193B028A22B913453B0B4C9A2 + +I=277 +KEY=88AA3FEE5FDFA336C9D9BA0C26EDB685924EBD98ADB43382 +CT=6933F4F193B028A22B913453B0B4C9A2 +PT=56811E665DDFBEA07A7C2C762F0D5C73 + +I=278 +KEY=2A0A1FE31ADFC64F9F58A46A7B320825E83291EE82B96FF1 +CT=56811E665DDFBEA07A7C2C762F0D5C73 +PT=CFF92E47C8C973ADA7B57D9FE320B356 + +I=279 +KEY=7958F9D10B6DC91050A18A2DB3FB7B884F87EC716199DCA7 +CT=CFF92E47C8C973ADA7B57D9FE320B356 +PT=A55A4F827552761580DC27E0712051B1 + +I=280 +KEY=ADDB73FE13D439CAF5FBC5AFC6A90D9DCF5BCB9110B98D16 +CT=A55A4F827552761580DC27E0712051B1 +PT=734B095C3C54FCDE26C33659C82CACCB + +I=281 +KEY=E979AF9C739F60AE86B0CCF3FAFDF143E998FDC8D89521DD +CT=734B095C3C54FCDE26C33659C82CACCB +PT=122A4F2ADE6C69364943658517A56587 + +I=282 +KEY=E05BDC75E94EB2A8949A83D924919875A0DB984DCF30445A +CT=122A4F2ADE6C69364943658517A56587 +PT=C6EF3170C5EF69B479AC6653E8B7E979 + +I=283 +KEY=67AF0BE0DE572F595275B2A9E17EF1C1D977FE1E2787AD23 +CT=C6EF3170C5EF69B479AC6653E8B7E979 +PT=51113FF8A1000A5449F24E8E5363FB72 + +I=284 +KEY=7C8DCBB512AE775603648D51407EFB959085B09074E45651 +CT=51113FF8A1000A5449F24E8E5363FB72 +PT=B9341E24A41C9D9CE56D6E4F17A7A311 + +I=285 +KEY=EEBE49DAF88030F5BA509375E462660975E8DEDF6343F540 +CT=B9341E24A41C9D9CE56D6E4F17A7A311 +PT=26A135C466B061791DE40A40E9366FC6 + +I=286 +KEY=A06A0B9127769EF79CF1A6B182D20770680CD49F8A759A86 +CT=26A135C466B061791DE40A40E9366FC6 +PT=AE832B68C147CF8A70A8E5CCC3FF05F2 + +I=287 +KEY=CD394B7808099B2832728DD94395C8FA18A43153498A9F74 +CT=AE832B68C147CF8A70A8E5CCC3FF05F2 +PT=72747F478E3AE57C6C7D6D4E5C4FCE71 + +I=288 +KEY=80D4A1BD538D11434006F29ECDAF2D8674D95C1D15C55105 +CT=72747F478E3AE57C6C7D6D4E5C4FCE71 +PT=21539022400BEE401E8FE7E9F0F7AAC3 + +I=289 +KEY=C8BCB868E11B46E3615562BC8DA4C3C66A56BBF4E532FBC6 +CT=21539022400BEE401E8FE7E9F0F7AAC3 +PT=44149C7C375F07B7169C8A9A14133C8C + +I=290 +KEY=DFC35DD4FAD95C2A2541FEC0BAFBC4717CCA316EF121C74A +CT=44149C7C375F07B7169C8A9A14133C8C +PT=2A7FA9D2EACC0C5444510E7D69EB3FD6 + +I=291 +KEY=73B0B53EE6D591140F3E57125037C825389B3F1398CAF89C +CT=2A7FA9D2EACC0C5444510E7D69EB3FD6 +PT=9949145B8C88D03BBA46FEBE9856B732 + +I=292 +KEY=7BFBD6A0A317DEE996774349DCBF181E82DDC1AD009C4FAE +CT=9949145B8C88D03BBA46FEBE9856B732 +PT=714E072347ECDEA4F8EB2B02746FBC66 + +I=293 +KEY=CA326A1D191B2BC6E739446A9B53C6BA7A36EAAF74F3F3C8 +CT=714E072347ECDEA4F8EB2B02746FBC66 +PT=CCF2295814759A5004E8C3E2B97C4958 + +I=294 +KEY=428400F7196D32C62BCB6D328F265CEA7EDE294DCD8FBA90 +CT=CCF2295814759A5004E8C3E2B97C4958 +PT=12108AB0753EAAE007DEFF2EBA8A3EF0 + +I=295 +KEY=3E38F6FA3F49742339DBE782FA18F60A7900D66377058460 +CT=12108AB0753EAAE007DEFF2EBA8A3EF0 +PT=0109AC127FB55B91BC922EDFF3C43819 + +I=296 +KEY=07C585ABD1C227D638D24B9085ADAD9BC592F8BC84C1BC79 +CT=0109AC127FB55B91BC922EDFF3C43819 +PT=33FF03F6966E81EE28889CFA0B9BA8B9 + +I=297 +KEY=FB823872148252C20B2D486613C32C75ED1A64468F5A14C0 +CT=33FF03F6966E81EE28889CFA0B9BA8B9 +PT=D8468C180BAC0F6D703611DDAD951014 + +I=298 +KEY=F81900EAD21ECE3BD36BC47E186F23189D2C759B22CF04D4 +CT=D8468C180BAC0F6D703611DDAD951014 +PT=07994906A8377D64F2D32DB4BB170EF1 + +I=299 +KEY=2ADC8C0244307531D4F28D78B0585E7C6FFF582F99D80A25 +CT=07994906A8377D64F2D32DB4BB170EF1 +PT=48382015F82AA7EC8944C40275595CEF + +I=300 +KEY=2E917F5C5BAB80939CCAAD6D4872F990E6BB9C2DEC8156CA +CT=48382015F82AA7EC8944C40275595CEF +PT=D4EEE0A1A56118EB8F6AE16FE16F70ED + +I=301 +KEY=126D396B29E0252248244DCCED13E17B69D17D420DEE2627 +CT=D4EEE0A1A56118EB8F6AE16FE16F70ED +PT=358E5FAE4A4ED6B1058E32942AE030DB + +I=302 +KEY=D390A60684F5C9147DAA1262A75D37CA6C5F4FD6270E16FC +CT=358E5FAE4A4ED6B1058E32942AE030DB +PT=B9730D311EA8312DAC34F444A4560DDC + +I=303 +KEY=0B2A03E62FCD9B06C4D91F53B9F506E7C06BBB9283581B20 +CT=B9730D311EA8312DAC34F444A4560DDC +PT=D64F286B32B4058A51B73844BCA93DDA + +I=304 +KEY=5858183C5713BBD6129637388B41036D91DC83D63FF126FA +CT=D64F286B32B4058A51B73844BCA93DDA +PT=78425B7FE64D972C642ED17369ED8844 + +I=305 +KEY=C555D9DC23D3A1846AD46C476D0C9441F5F252A5561CAEBE +CT=78425B7FE64D972C642ED17369ED8844 +PT=2DE9202F4CD7F67C7B7F94CF7F3B9B5A + +I=306 +KEY=7BA871DA6E336CFA473D4C6821DB623D8E8DC66A292735E4 +CT=2DE9202F4CD7F67C7B7F94CF7F3B9B5A +PT=A30322EC9A51266B50153995BCEBC846 + +I=307 +KEY=55BF35687EBA169AE43E6E84BB8A4456DE98FFFF95CCFDA2 +CT=A30322EC9A51266B50153995BCEBC846 +PT=14754B0469683F36E4791FD9B8B1C585 + +I=308 +KEY=0404CAE90360F118F04B2580D2E27B603AE1E0262D7D3827 +CT=14754B0469683F36E4791FD9B8B1C585 +PT=E8592DC147A1DC4F48D43E365B9D63FF + +I=309 +KEY=109E16AA717A4EF4181208419543A72F7235DE1076E05BD8 +CT=E8592DC147A1DC4F48D43E365B9D63FF +PT=47A3BF0743562C7D412563C94C2CD717 + +I=310 +KEY=0A8DC7647F8C06D15FB1B746D6158B523310BDD93ACC8CCF +CT=47A3BF0743562C7D412563C94C2CD717 +PT=63F8C6A062937471364050815D856793 + +I=311 +KEY=CC9B8854C13F73623C4971E6B486FF230550ED586749EB5C +CT=63F8C6A062937471364050815D856793 +PT=E70443AF44BF549607251A86CD83A4D3 + +I=312 +KEY=2D067D896DF1E749DB4D3249F039ABB50275F7DEAACA4F8F +CT=E70443AF44BF549607251A86CD83A4D3 +PT=ACEF2AE95CA660AEE513BF48BCF7D125 + +I=313 +KEY=DEC45DD3C0DAD30A77A218A0AC9FCB1BE7664896163D9EAA +CT=ACEF2AE95CA660AEE513BF48BCF7D125 +PT=859E9E4001245A50ED76055539672F1A + +I=314 +KEY=6F208E93D9C89CE8F23C86E0ADBB914B0A104DC32F5AB1B0 +CT=859E9E4001245A50ED76055539672F1A +PT=42B059061FE4C86C7AC2B7C8B62820C2 + +I=315 +KEY=86EC7CE558994E8EB08CDFE6B25F592770D2FA0B99729172 +CT=42B059061FE4C86C7AC2B7C8B62820C2 +PT=01C6296F1532450F182D6A3FC8249DD7 + +I=316 +KEY=C74B31CEC9B31130B14AF689A76D1C2868FF903451560CA5 +CT=01C6296F1532450F182D6A3FC8249DD7 +PT=14334054946821E3FE8D72D1EF402EE1 + +I=317 +KEY=AC636B2AD3699560A579B6DD33053DCB9672E2E5BE162244 +CT=14334054946821E3FE8D72D1EF402EE1 +PT=F09B2FE9A8F17CD847532D4979D2A8C4 + +I=318 +KEY=6F956E3680FC783155E299349BF44113D121CFACC7C48A80 +CT=F09B2FE9A8F17CD847532D4979D2A8C4 +PT=4C97BD8822E63C7A2EE0E444563AF1C8 + +I=319 +KEY=C69B2FB718C41B1A197524BCB9127D69FFC12BE891FE7B48 +CT=4C97BD8822E63C7A2EE0E444563AF1C8 +PT=344E85BE2C8B36430C8058B310062171 + +I=320 +KEY=BFFA143B8A18CACF2D3BA10295994B2AF341735B81F85A39 +CT=344E85BE2C8B36430C8058B310062171 +PT=FF3F882CB22D13A8631DCA6DD702D0E0 + +I=321 +KEY=22F58A0FC077AB5FD204292E27B45882905CB93656FA8AD9 +CT=FF3F882CB22D13A8631DCA6DD702D0E0 +PT=866B2E52CF71505973D9D6642C8178BB + +I=322 +KEY=DC8CE7A9130F3662546F077CE8C508DBE3856F527A7BF262 +CT=866B2E52CF71505973D9D6642C8178BB +PT=4802741ADF67A3811A8AEC7008D8827E + +I=323 +KEY=743B09AA8FD3C6A01C6D736637A2AB5AF90F832272A3701C +CT=4802741ADF67A3811A8AEC7008D8827E +PT=FD3701579815D02BE878C74ABB98C59B + +I=324 +KEY=865B3EC9EFBE27D0E15A7231AFB77B7111774468C93BB587 +CT=FD3701579815D02BE878C74ABB98C59B +PT=99BCA8250D54F3A9A72054AF5578F842 + +I=325 +KEY=041C037E08923FFF78E6DA14A2E388D8B65710C79C434DC5 +CT=99BCA8250D54F3A9A72054AF5578F842 +PT=F0DA5C0E446547356D5027BA346A831C + +I=326 +KEY=FBABCE025CF5FF3D883C861AE686CFEDDB07377DA829CED9 +CT=F0DA5C0E446547356D5027BA346A831C +PT=EED0140AF408652DD879E3289536C389 + +I=327 +KEY=3F12399A3E5C0F9566EC9210128EAAC0037ED4553D1F0D50 +CT=EED0140AF408652DD879E3289536C389 +PT=FDC7299A95BDB941A299478B7B409EF8 + +I=328 +KEY=D541517B701036E39B2BBB8A87331381A1E793DE465F93A8 +CT=FDC7299A95BDB941A299478B7B409EF8 +PT=5BE5AEC30578CD03BA7B17E8B16AAFBF + +I=329 +KEY=6657840FF425DD8AC0CE1549824BDE821B9C8436F7353C17 +CT=5BE5AEC30578CD03BA7B17E8B16AAFBF +PT=3C7A9745F48DA61CF7875A449E24C735 + +I=330 +KEY=52D29BBD64550DFBFCB4820C76C6789EEC1BDE726911FB22 +CT=3C7A9745F48DA61CF7875A449E24C735 +PT=69516DE0343F3552830D28CE8B9A282C + +I=331 +KEY=3699B16BB0349B9195E5EFEC42F94DCC6F16F6BCE28BD30E +CT=69516DE0343F3552830D28CE8B9A282C +PT=EB09EE300286690EA65A30526A43B86B + +I=332 +KEY=60E79B9E7C41814E7EEC01DC407F24C2C94CC6EE88C86B65 +CT=EB09EE300286690EA65A30526A43B86B +PT=A235384FE517A5F455BBE6B850C05E33 + +I=333 +KEY=11F650282BBCB584DCD93993A56881369CF72056D8083556 +CT=A235384FE517A5F455BBE6B850C05E33 +PT=41E297350390E91EC00FF875B3CA60BA + +I=334 +KEY=11B449F7EE983AB89D3BAEA6A6F868285CF8D8236BC255EC +CT=41E297350390E91EC00FF875B3CA60BA +PT=5FB9F6408D54401A9A76288AE3A04944 + +I=335 +KEY=54CBA9A5782ED91FC28258E62BAC2832C68EF0A988621CA8 +CT=5FB9F6408D54401A9A76288AE3A04944 +PT=7C9CD2510E96FF37BF75E57E84098535 + +I=336 +KEY=871169F28E704C95BE1E8AB7253AD70579FB15D70C6B999D +CT=7C9CD2510E96FF37BF75E57E84098535 +PT=8E041B8C74A84D747B02714452B34F11 + +I=337 +KEY=7F44ED6AA755957A301A913B51929A7102F964935ED8D68C +CT=8E041B8C74A84D747B02714452B34F11 +PT=3698639F56657A40D52B9B8015448C2A + +I=338 +KEY=EEAF09001996BA6E0682F2A407F7E031D7D2FF134B9C5AA6 +CT=3698639F56657A40D52B9B8015448C2A +PT=79FB5E4A065D29E1CA3E15897B60032F + +I=339 +KEY=D21CCA06254A64C97F79ACEE01AAC9D01DECEA9A30FC5989 +CT=79FB5E4A065D29E1CA3E15897B60032F +PT=C582F5F8D9D2E9323C769B2B1AE369BD + +I=340 +KEY=29D2F84E4568BA6FBAFB5916D87820E2219A71B12A1F3034 +CT=C582F5F8D9D2E9323C769B2B1AE369BD +PT=916405DC8F2AD50548997D87BCCADBFB + +I=341 +KEY=43AC4D54A8A0222F2B9F5CCA5752F5E769030C3696D5EBCF +CT=916405DC8F2AD50548997D87BCCADBFB +PT=0E9FF0E147A47056EC6B09837C9E0E62 + +I=342 +KEY=9AF110B8274794772500AC2B10F685B1856805B5EA4BE5AD +CT=0E9FF0E147A47056EC6B09837C9E0E62 +PT=3B6E3CAAC358427980E66E3D30D39E4F + +I=343 +KEY=49F910E7957BC95C1E6E9081D3AEC7C8058E6B88DA987BE2 +CT=3B6E3CAAC358427980E66E3D30D39E4F +PT=25CBE5AB4C6785C0F2847CF89F2635AB + +I=344 +KEY=64D90092DD97AC3C3BA5752A9FC94208F70A177045BE4E49 +CT=25CBE5AB4C6785C0F2847CF89F2635AB +PT=3D9200D39461D8B2CE7874DA20BFD9DA + +I=345 +KEY=C7A8403AFB011673063775F90BA89ABA397263AA65019793 +CT=3D9200D39461D8B2CE7874DA20BFD9DA +PT=E61E7E06A1E1F656AE8F8C29C96E5A16 + +I=346 +KEY=071AF635AF7A9602E0290BFFAA496CEC97FDEF83AC6FCD85 +CT=E61E7E06A1E1F656AE8F8C29C96E5A16 +PT=7488BB35F06E94F31A744D1EA95E71D0 + +I=347 +KEY=A4B5ECB7047E08D694A1B0CA5A27F81F8D89A29D0531BC55 +CT=7488BB35F06E94F31A744D1EA95E71D0 +PT=3912DC00C0AB79C473CA2CC8F69262F0 + +I=348 +KEY=BD4478B38A0E9347ADB36CCA9A8C81DBFE438E55F3A3DEA5 +CT=3912DC00C0AB79C473CA2CC8F69262F0 +PT=C4B546F134A016DADA8E7C478B1E7D45 + +I=349 +KEY=F7B6F476517483AD69062A3BAE2C970124CDF21278BDA3E0 +CT=C4B546F134A016DADA8E7C478B1E7D45 +PT=298524C5D468EBFA97DEFEC7B80EE752 + +I=350 +KEY=8E0C5244F7417C2440830EFE7A447CFBB3130CD5C0B344B2 +CT=298524C5D468EBFA97DEFEC7B80EE752 +PT=B27EFB90BA3A27A1077C6742D5B68396 + +I=351 +KEY=C6E8F264FA0C9A9AF2FDF56EC07E5B5AB46F6B971505C724 +CT=B27EFB90BA3A27A1077C6742D5B68396 +PT=D02C27A94DD3B772B338C7462379B009 + +I=352 +KEY=AD694D243DCC6B7B22D1D2C78DADEC280757ACD1367C772D +CT=D02C27A94DD3B772B338C7462379B009 +PT=1CED06084E67BA4BAD3C331F4074B9FF + +I=353 +KEY=68AEF48D86D395583E3CD4CFC3CA5663AA6B9FCE7608CED2 +CT=1CED06084E67BA4BAD3C331F4074B9FF +PT=C0D7811FE8630B3E7C3A60DA9042A6B2 + +I=354 +KEY=670A8D40573F598AFEEB55D02BA95D5DD651FF14E64A6860 +CT=C0D7811FE8630B3E7C3A60DA9042A6B2 +PT=45F92C84CE2AEC6E7953C8AAC5901D0F + +I=355 +KEY=D44FD97B0D59C923BB127954E583B133AF0237BE23DA756F +CT=45F92C84CE2AEC6E7953C8AAC5901D0F +PT=23A4863C994EFE93E7CE1C89FE14143D + +I=356 +KEY=4E08C6A539C74A6598B6FF687CCD4FA048CC2B37DDCE6152 +CT=23A4863C994EFE93E7CE1C89FE14143D +PT=85EB5F46988211E3077FDBE38F1EBE6B + +I=357 +KEY=21B17D5E461224B31D5DA02EE44F5E434FB3F0D452D0DF39 +CT=85EB5F46988211E3077FDBE38F1EBE6B +PT=59CF6CCC81A8BC17A52D7550B40C7514 + +I=358 +KEY=6CC595309F161F3E4492CCE265E7E254EA9E8584E6DCAA2D +CT=59CF6CCC81A8BC17A52D7550B40C7514 +PT=13DF4C2AA74A4B9123B3A57FE94F85BE + +I=359 +KEY=77B90151B41B1B7D574D80C8C2ADA9C5C92D20FB0F932F93 +CT=13DF4C2AA74A4B9123B3A57FE94F85BE +PT=6DEDE53AD5DC2A87744DA0EA561977A3 + +I=360 +KEY=8E1683C57C1817C23AA065F217718342BD608011598A5830 +CT=6DEDE53AD5DC2A87744DA0EA561977A3 +PT=F9D912AAB5ED1ACBD0475411DF98F49C + +I=361 +KEY=E9FDD94AE4B4FABAC3797758A29C99896D27D4008612ACAC +CT=F9D912AAB5ED1ACBD0475411DF98F49C +PT=853C907D9FD35B61D2ABBE5C1A89DB4B + +I=362 +KEY=BCC524DF4D452AE14645E7253D4FC2E8BF8C6A5C9C9B77E7 +CT=853C907D9FD35B61D2ABBE5C1A89DB4B +PT=874C4BC1993FBA12136443B57F9523BE + +I=363 +KEY=9F5EFA7196589240C109ACE4A47078FAACE829E9E30E5459 +CT=874C4BC1993FBA12136443B57F9523BE +PT=E6B6E9133DD0EC2844EF3CC0C2F9E4AC + +I=364 +KEY=2F0731DB4FA3024127BF45F799A094D2E807152921F7B0F5 +CT=E6B6E9133DD0EC2844EF3CC0C2F9E4AC +PT=20B41EE01134041DF8D11BB7F86928EA + +I=365 +KEY=7E44D240F06AAA5E070B5B17889490CF10D60E9ED99E981F +CT=20B41EE01134041DF8D11BB7F86928EA +PT=BF6B03096DCDC052B1325CC34BF6E56C + +I=366 +KEY=D8D3E3D538C8CA34B860581EE559509DA1E4525D92687D73 +CT=BF6B03096DCDC052B1325CC34BF6E56C +PT=5ED3E40FB5C34DD1F370C3AD72C7C24D + +I=367 +KEY=F3DF20767CDA5E0CE6B3BC11509A1D4C529491F0E0AFBF3E +CT=5ED3E40FB5C34DD1F370C3AD72C7C24D +PT=3EA6BCE2317C5D696DF8240C481B34DD + +I=368 +KEY=484932A15D75173FD81500F361E640253F6CB5FCA8B48BE3 +CT=3EA6BCE2317C5D696DF8240C481B34DD +PT=41D6E077746FE1A9307E1107631A5D2C + +I=369 +KEY=EF960956685DE1CE99C3E0841589A18C0F12A4FBCBAED6CF +CT=41D6E077746FE1A9307E1107631A5D2C +PT=D0C6DDEF0A623686BA303C278D445964 + +I=370 +KEY=82477D8D682C1D4849053D6B1FEB970AB52298DC46EA8FAB +CT=D0C6DDEF0A623686BA303C278D445964 +PT=EEFFA6025D6CAFBF9DC18E5B1B99A6ED + +I=371 +KEY=15D8DCF80A26856AA7FA9B69428738B528E316875D732946 +CT=EEFFA6025D6CAFBF9DC18E5B1B99A6ED +PT=38E222ABAA07CDAE9CC02FAC84EC0FC1 + +I=372 +KEY=556151278277D7579F18B9C2E880F51BB423392BD99F2687 +CT=38E222ABAA07CDAE9CC02FAC84EC0FC1 +PT=B00C719E6A320E4385794EB7F23C0D80 + +I=373 +KEY=777F91003E4410572F14C85C82B2FB58315A779C2BA32B07 +CT=B00C719E6A320E4385794EB7F23C0D80 +PT=0E667CA932023D2EFD8DDBDED5A43D78 + +I=374 +KEY=130507FC817F14432172B4F5B0B0C676CCD7AC42FE07167F +CT=0E667CA932023D2EFD8DDBDED5A43D78 +PT=6B15DA892F0B5916F31BB74FC7D03F9A + +I=375 +KEY=D045A84BBF62DE2E4A676E7C9FBB9F603FCC1B0D39D729E5 +CT=6B15DA892F0B5916F31BB74FC7D03F9A +PT=EBEF6DC298D63BF6E6E46F833B217033 + +I=376 +KEY=7742FB68CDF60735A18803BE076DA496D928748E02F659D6 +CT=EBEF6DC298D63BF6E6E46F833B217033 +PT=48DC6F65F193AFCCE559EA6F04FBD79A + +I=377 +KEY=5CE32BC22C77B664E9546CDBF6FE0B5A3C719EE1060D8E4C +CT=48DC6F65F193AFCCE559EA6F04FBD79A +PT=D0596880F92716C51E41519C640AEFDA + +I=378 +KEY=2DA6B73C5131E24C390D045B0FD91D9F2230CF7D62076196 +CT=D0596880F92716C51E41519C640AEFDA +PT=ABB7C3E499086F53C4DB97640168943B + +I=379 +KEY=E41C1A826978491892BAC7BF96D172CCE6EB5819636FF5AD +CT=ABB7C3E499086F53C4DB97640168943B +PT=0CC58B3D0370317E1025E1AF97962646 + +I=380 +KEY=501012EE411DCDC59E7F4C8295A143B2F6CEB9B6F4F9D3EB +CT=0CC58B3D0370317E1025E1AF97962646 +PT=28920AED2B644C4346FC146903887244 + +I=381 +KEY=97B7E8C1147A5062B6ED466FBEC50FF1B032ADDFF771A1AF +CT=28920AED2B644C4346FC146903887244 +PT=E7A28DA5EC871DAF8C2D196C7ED8977F + +I=382 +KEY=988B9928402BCD63514FCBCA5242125E3C1FB4B389A936D0 +CT=E7A28DA5EC871DAF8C2D196C7ED8977F +PT=013876A92413AED2E360A241FE021B25 + +I=383 +KEY=3432357430ACC9135077BD637651BC8CDF7F16F277AB2DF5 +CT=013876A92413AED2E360A241FE021B25 +PT=10F1A56A8CFDA1D5044D5D0E53F6A773 + +I=384 +KEY=CE94F859CD3E85F440861809FAAC1D59DB324BFC245D8A86 +CT=10F1A56A8CFDA1D5044D5D0E53F6A773 +PT=941C717EE6642DD474719F099AEEB1EB + +I=385 +KEY=A1BFA52EA232FDF0D49A69771CC8308DAF43D4F5BEB33B6D +CT=941C717EE6642DD474719F099AEEB1EB +PT=F31B47230ABC94977E14E1080528C1C9 + +I=386 +KEY=37B36A8E7A3B4F2A27812E541674A41AD15735FDBB9BFAA4 +CT=F31B47230ABC94977E14E1080528C1C9 +PT=A91264221890CA93541B662F64A11C62 + +I=387 +KEY=04F603F98A9D1AC78E934A760EE46E89854C53D2DF3AE6C6 +CT=A91264221890CA93541B662F64A11C62 +PT=05F5171B639825EC67A37B3671F2F884 + +I=388 +KEY=A294EBBBD53D18DD8B665D6D6D7C4B65E2EF28E4AEC81E42 +CT=05F5171B639825EC67A37B3671F2F884 +PT=B6FE84EB2987DE956953DEBA6FD2E029 + +I=389 +KEY=E0E38A82F60E8EED3D98D98644FB95F08BBCF65EC11AFE6B +CT=B6FE84EB2987DE956953DEBA6FD2E029 +PT=2741338CF00FBC70C4B1C67C97E85B97 + +I=390 +KEY=2193D386143F6D761AD9EA0AB4F429804F0D302256F2A5FC +CT=2741338CF00FBC70C4B1C67C97E85B97 +PT=E56C7C453E2E13028AD812F9CDB78E2F + +I=391 +KEY=05AD3BC4F1B29F17FFB5964F8ADA3A82C5D522DB9B452BD3 +CT=E56C7C453E2E13028AD812F9CDB78E2F +PT=9A9B49AC0691F1576D515E935F042229 + +I=392 +KEY=1588C005075F4674652EDFE38C4BCBD5A8847C48C44109FA +CT=9A9B49AC0691F1576D515E935F042229 +PT=143E5F64AD38373D3B54FA24CC7C0AF5 + +I=393 +KEY=731083CCCB22E7CF711080872173FCE893D0866C083D030F +CT=143E5F64AD38373D3B54FA24CC7C0AF5 +PT=61F6AF426601588CB7C525255EC1A06D + +I=394 +KEY=DACEE3906B98DFC110E62FC54772A4642415A34956FCA362 +CT=61F6AF426601588CB7C525255EC1A06D +PT=DB5DC1C3B3413F653D72F8744C2DD881 + +I=395 +KEY=D9ACA0F56DCA4FC0CBBBEE06F4339B0119675B3D1AD17BE3 +CT=DB5DC1C3B3413F653D72F8744C2DD881 +PT=4E9D548DA49E992AD3123F53558909C9 + +I=396 +KEY=12C2FE0C57D21C208526BA8B50AD022BCA75646E4F58722A +CT=4E9D548DA49E992AD3123F53558909C9 +PT=EB2E835192E64ABC30C3F2662B703C47 + +I=397 +KEY=7A43322D6174BA786E0839DAC24B4897FAB6960864284E6D +CT=EB2E835192E64ABC30C3F2662B703C47 +PT=CD0690863F63F2B263D4C11190A7985B + +I=398 +KEY=EBC6D71978D39185A30EA95CFD28BA2599625719F48FD636 +CT=CD0690863F63F2B263D4C11190A7985B +PT=C044E800B65CA78559D0642C370C7D3E + +I=399 +KEY=A1B6CE2EEC5FC386634A415C4B741DA0C0B23335C383AB08 +CT=C044E800B65CA78559D0642C370C7D3E +PT=F1A81B68F6E5A6271A8CB24E7D9491EF + +========================= + +KEYSIZE=256 + +I=0 +KEY=0000000000000000000000000000000000000000000000000000000000000000 +CT=00000000000000000000000000000000 +PT=058CCFFDBBCB382D1F6F56585D8A4ADE + +I=1 +KEY=85C6B2BB2300148F945AEBF1F021CF79058CCFFDBBCB382D1F6F56585D8A4ADE +CT=058CCFFDBBCB382D1F6F56585D8A4ADE +PT=15173A0EB65F5CC05E704EFE61D9E346 + +I=2 +KEY=2447EC44111548FBB670B98F182D5DEE109BF5F30D9464ED411F18A63C53A998 +CT=15173A0EB65F5CC05E704EFE61D9E346 +PT=85F083ACC676D91EDD1ABFB43935237A + +I=3 +KEY=85D3E1D750CAA89BEE274AA7C32C2207956B765FCBE2BDF39C05A71205668AE2 +CT=85F083ACC676D91EDD1ABFB43935237A +PT=42C8F0ABC58E0BEAC32911D2DD9FA8C8 + +I=4 +KEY=CE86B24954745B2BAAF27010202EE7FAD7A386F40E6CB6195F2CB6C0D8F9222A +CT=42C8F0ABC58E0BEAC32911D2DD9FA8C8 +PT=5E44123D2CA07981B073BB2749F557D6 + +I=5 +KEY=CD7BCBBA4555A0D034FD7B528A1D042C89E794C922CCCF98EF5F0DE7910C75FC +CT=5E44123D2CA07981B073BB2749F557D6 +PT=8B649458EA90F4F7E13467E509B7F164 + +I=6 +KEY=EF28DFAED7794B1C7B892F3C98FCDC9602830091C85C3B6F0E6B6A0298BB8498 +CT=8B649458EA90F4F7E13467E509B7F164 +PT=F240D1F579DA2CA8839F7072DF52EBA3 + +I=7 +KEY=C66605EC92F96B49F08CBC6276A0DC68F0C3D164B18617C78DF41A7047E96F3B +CT=F240D1F579DA2CA8839F7072DF52EBA3 +PT=B05297490A394B4A1736DE7F8DC12969 + +I=8 +KEY=347403B6E6344E1525B8D2BD4DCA343F4091462DBBBF5C8D9AC2C40FCA284652 +CT=B05297490A394B4A1736DE7F8DC12969 +PT=8BA49D44B98E67501235CE1C2F26BB28 + +I=9 +KEY=B932CD0C70488602C56F92A0DA57BE27CB35DB6902313BDD88F70A13E50EFD7A +CT=8BA49D44B98E67501235CE1C2F26BB28 +PT=86CE4E4D040C49F2717407157454162E + +I=10 +KEY=28F8B6B4AB2B0B81F3676F6E422D438C4DFB9524063D722FF9830D06915AEB54 +CT=86CE4E4D040C49F2717407157454162E +PT=4E9CA7FB0FF9F38FC821CA91052483F9 + +I=11 +KEY=5CD19F4D3C5B58602B101E15B39F51E4036732DF09C481A031A2C797947E68AD +CT=4E9CA7FB0FF9F38FC821CA91052483F9 +PT=55E49ED59245C1850CB0C17C1CEEA05E + +I=12 +KEY=E822BB0D1F25F3DCA6FE0CB1A8AF39F15683AC0A9B8140253D1206EB8890C8F3 +CT=55E49ED59245C1850CB0C17C1CEEA05E +PT=F7F0BFA319AC289C9F64E6FCDD531B44 + +I=13 +KEY=8B64FF354C6E303F14EA34C9F667FEC9A17313A9822D68B9A276E01755C3D3B7 +CT=F7F0BFA319AC289C9F64E6FCDD531B44 +PT=6ACB8A177226AE47E2170F77D2FE4923 + +I=14 +KEY=1A9D440EBAC3F3625E229B66C5D9249CCBB899BEF00BC6FE4061EF60873D9A94 +CT=6ACB8A177226AE47E2170F77D2FE4923 +PT=BAA9BB819332A87D6004164927EAC699 + +I=15 +KEY=97F92B9AD44A3182FF10E07747C560B37111223F63396E832065F929A0D75C0D +CT=BAA9BB819332A87D6004164927EAC699 +PT=EB84793E2D68632900B0517392EC4B94 + +I=16 +KEY=2AEEBA2AC59870A7B4274B80FE74D55A9A955B014E510DAA20D5A85A323B1799 +CT=EB84793E2D68632900B0517392EC4B94 +PT=6C662FBE2B22394CC1D45453772C72BA + +I=17 +KEY=EEA4B3C4F96C42E3B7DF5A3870C85B69F6F374BF657334E6E101FC0945176523 +CT=6C662FBE2B22394CC1D45453772C72BA +PT=70D2BBC1FA7D49848D94112DA93A3C3C + +I=18 +KEY=F930D1529C654F31549809C6CD5CC4608621CF7E9F0E7D626C95ED24EC2D591F +CT=70D2BBC1FA7D49848D94112DA93A3C3C +PT=1AFF91E67039133946638E4E505310C2 + +I=19 +KEY=5D0F461C1A5FF7BA5C93F0CED9DD49FF9CDE5E98EF376E5B2AF6636ABC7E49DD +CT=1AFF91E67039133946638E4E505310C2 +PT=8E4358B22DE7BCDC8B8409E6250633BF + +I=20 +KEY=AA4B475845EB19F601856A40AB517594129D062AC2D0D287A1726A8C99787A62 +CT=8E4358B22DE7BCDC8B8409E6250633BF +PT=2A79FE5A222C9503954346D6C15AC679 + +I=21 +KEY=9703F4DD85A3BE85343FFD15950A266B38E4F870E0FC478434312C5A5822BC1B +CT=2A79FE5A222C9503954346D6C15AC679 +PT=0FF812C5B863282C294D7069F830EE86 + +I=22 +KEY=3DD1B2ACBC6568851E767D20D82AD324371CEAB5589F6FA81D7C5C33A012529D +CT=0FF812C5B863282C294D7069F830EE86 +PT=D449218625DE49D2B9514E032CA096E7 + +I=23 +KEY=95CC16235D3DFF4F7DB2116D2B380F39E355CB337D41267AA42D12308CB2C47A +CT=D449218625DE49D2B9514E032CA096E7 +PT=F951EAC3BC78DB0AE13FDC33048D2D81 + +I=24 +KEY=A6F55AFBDA7EA939F6F2A28530C416781A0421F0C139FD704512CE03883FE9FB +CT=F951EAC3BC78DB0AE13FDC33048D2D81 +PT=7D5A03A955F6403F918AC915AC22B797 + +I=25 +KEY=7C5D39885F4C0F4FCF672321B711C5B7675E225994CFBD4FD4980716241D5E6C +CT=7D5A03A955F6403F918AC915AC22B797 +PT=CA2E1C274073AD2A3AE35C60ECA52A58 + +I=26 +KEY=4E7B914B84BFA1A2D7BD409AFADD2EDCAD703E7ED4BC1065EE7B5B76C8B87434 +CT=CA2E1C274073AD2A3AE35C60ECA52A58 +PT=C5048FA0148CED10A06E107269DA9C95 + +I=27 +KEY=F62D8C4822C5F89D51E3C68695D91CA66874B1DEC030FD754E154B04A162E8A1 +CT=C5048FA0148CED10A06E107269DA9C95 +PT=CB9B457A7A24577DA71AC335F0572DAB + +I=28 +KEY=C37AAD7CB20087F4B98390C59D3ECFB2A3EFF4A4BA14AA08E90F88315135C50A +CT=CB9B457A7A24577DA71AC335F0572DAB +PT=FA60BFF170DD30C29DF1807C1612CD67 + +I=29 +KEY=1A2C6858B37D0341BF8796FB72D00B72598F4B55CAC99ACA74FE084D4727086D +CT=FA60BFF170DD30C29DF1807C1612CD67 +PT=E2FACFB5DF4E69C911838FCC546D0C8E + +I=30 +KEY=039B73E3A8DCF3C678FBC246AAECDAECBB7584E01587F303657D8781134A04E3 +CT=E2FACFB5DF4E69C911838FCC546D0C8E +PT=749AB2B9176AFDB8B6714DF44BBF2B58 + +I=31 +KEY=773D90EA7ECA29DFD9141A42EB2BBC64CFEF365902ED0EBBD30CCA7558F52FBB +CT=749AB2B9176AFDB8B6714DF44BBF2B58 +PT=0285E58D09A8D33FB196FD16A8DF37C0 + +I=32 +KEY=598262B046B44784D977F6BE2553C6ACCD6AD3D40B45DD84629A3763F02A187B +CT=0285E58D09A8D33FB196FD16A8DF37C0 +PT=1C952C46AE829D8805031A44F9D85521 + +I=33 +KEY=AFAE657D3220CD1E6199A49754525F4AD1FFFF92A5C7400C67992D2709F24D5A +CT=1C952C46AE829D8805031A44F9D85521 +PT=EED0A47E63FF354B4D9C53F7FD75D720 + +I=34 +KEY=A61F583BCFD120B8CABE1E4C616F4FC73F2F5BECC63875472A057ED0F4879A7A +CT=EED0A47E63FF354B4D9C53F7FD75D720 +PT=10C1F0F7C32AD36F03AEA8DCE6AAE7BC + +I=35 +KEY=FB76D4B83A7F50482A92F5A92CB60F522FEEAB1B0512A62829ABD60C122D7DC6 +CT=10C1F0F7C32AD36F03AEA8DCE6AAE7BC +PT=372488DF6543180F1F2AE15E5B0C8785 + +I=36 +KEY=35EAC2BA73F55570CB727220C027FE6218CA23C46051BE27368137524921FA43 +CT=372488DF6543180F1F2AE15E5B0C8785 +PT=3DE420FF3699D68DB69966F57D09045A + +I=37 +KEY=48B6E08B9FD9B5C130E1829CD4540D9C252E033B56C868AA801851A73428FE19 +CT=3DE420FF3699D68DB69966F57D09045A +PT=7858F396DC520131C789CB8F8C919CCD + +I=38 +KEY=DB39C13F29241FF29C5BEB839705AD5B5D76F0AD8A9A699B47919A28B8B962D4 +CT=7858F396DC520131C789CB8F8C919CCD +PT=07BE8BBF9FCD7D04888E61935DD7222F + +I=39 +KEY=A5F9B675531AB58C1FFC316C9359EA335AC87B121557149FCF1FFBBBE56E40FB +CT=07BE8BBF9FCD7D04888E61935DD7222F +PT=EDD619B7C12E2AF6BDAA953B2E7871EF + +I=40 +KEY=A02D1F14A64BBC67DD7EE9EAB3FB0EADB71E62A5D4793E6972B56E80CB163114 +CT=EDD619B7C12E2AF6BDAA953B2E7871EF +PT=C748CDB645F1A1E44A63FAF00B2C3A45 + +I=41 +KEY=177D7A6843B5ABBEB212E68734A7A05C7056AF1391889F8D38D69470C03A0B51 +CT=C748CDB645F1A1E44A63FAF00B2C3A45 +PT=BD3ED4C8CD7DBF4299AC63FE119D291E + +I=42 +KEY=BD9BDC6BD09DEED3E75C918BE55E5332CD687BDB5CF520CFA17AF78ED1A7224F +CT=BD3ED4C8CD7DBF4299AC63FE119D291E +PT=A16B82F958441E90A965427C854EECBB + +I=43 +KEY=E6325C33EC76F8EDE02707A3AE82F1096C03F92204B13E5F081FB5F254E9CEF4 +CT=A16B82F958441E90A965427C854EECBB +PT=E04E642689D1AB78E7CDE26D0563901C + +I=44 +KEY=B8543DB3071AB9F0802D4106FBDA59648C4D9D048D609527EFD2579F518A5EE8 +CT=E04E642689D1AB78E7CDE26D0563901C +PT=08E59C72C13C030DA3C50300861EA097 + +I=45 +KEY=ECDD43A6B225DB325BFFE5462B66E97884A801764C5C962A4C17549FD794FE7F +CT=08E59C72C13C030DA3C50300861EA097 +PT=C224B2EFEE07AAC33F1F6EB1295D9A50 + +I=46 +KEY=741D627C8B47BED4497C71FDC9854912468CB399A25B3CE973083A2EFEC9642F +CT=C224B2EFEE07AAC33F1F6EB1295D9A50 +PT=1653CE734D27B44369D4FE582E7A885F + +I=47 +KEY=A47BDC62B1D80815AC6BF04481C5601F50DF7DEAEF7C88AA1ADCC476D0B3EC70 +CT=1653CE734D27B44369D4FE582E7A885F +PT=CADC89828B6147FAEC581DDCFF3C0960 + +I=48 +KEY=CB91E738F51C111DAC2E0A3BF7B076A39A03F468641DCF50F684D9AA2F8FE510 +CT=CADC89828B6147FAEC581DDCFF3C0960 +PT=49402F0F4AFA2518D57C5D1CFCECC0F2 + +I=49 +KEY=BDA1FFAEE7B93EDFCA4374871A149550D343DB672EE7EA4823F884B6D36325E2 +CT=49402F0F4AFA2518D57C5D1CFCECC0F2 +PT=EBFF53AB449DE5A53EDC6E595AA47B10 + +I=50 +KEY=18D865B8E8C779268D3876C22AF479FB38BC88CC6A7A0FED1D24EAEF89C75EF2 +CT=EBFF53AB449DE5A53EDC6E595AA47B10 +PT=30073458509F9AC9DA21B2DF566AB3BE + +I=51 +KEY=967E2580238300563A34A6E70D84B4FF08BBBC943AE59524C7055830DFADED4C +CT=30073458509F9AC9DA21B2DF566AB3BE +PT=5AB9F90CC2A7603A68E2ACA95A2DE55D + +I=52 +KEY=A469A4E2F0B3847F3B52886FAD7DBAF652024598F842F51EAFE7F49985800811 +CT=5AB9F90CC2A7603A68E2ACA95A2DE55D +PT=F22A13F395B6064172CA9DC572C26B2E + +I=53 +KEY=9EA4946ED73FF8BB8700C18967C01968A028566B6DF4F35FDD2D695CF742633F +CT=F22A13F395B6064172CA9DC572C26B2E +PT=26E44B9F3DEBA8EE3531DDFA42F1DC14 + +I=54 +KEY=3D25EEEACEF18702FD3896283CFF8A8386CC1DF4501F5BB1E81CB4A6B5B3BF2B +CT=26E44B9F3DEBA8EE3531DDFA42F1DC14 +PT=32D9F05174FFF34594E952B7ADE09737 + +I=55 +KEY=8BF2A692F6A35980C0CF02FF4650871BB415EDA524E0A8F47CF5E6111853281C +CT=32D9F05174FFF34594E952B7ADE09737 +PT=7BEF027DEB1FF22774CE8A8A101DD41B + +I=56 +KEY=C90BF0E1A8B615B4C8BD318260BB80AECFFAEFD8CFFF5AD3083B6C9B084EFC07 +CT=7BEF027DEB1FF22774CE8A8A101DD41B +PT=CF6B2444DFBBFE5B6A1CA99F2D13DE9A + +I=57 +KEY=C2A4C82B4AAEE0A22315026C6FE396900091CB9C1044A4886227C504255D229D +CT=CF6B2444DFBBFE5B6A1CA99F2D13DE9A +PT=14AD8C7B0F0460A3F48D5CD2CFFB385C + +I=58 +KEY=BF76E610192E2AEF42FF8F487CDDC318143C47E71F40C42B96AA99D6EAA61AC1 +CT=14AD8C7B0F0460A3F48D5CD2CFFB385C +PT=A5A850FC44A09C5985CE9661AF84F186 + +I=59 +KEY=1E42AEC368C600F18CBFA305EB559946B194171B5BE0587213640FB74522EB47 +CT=A5A850FC44A09C5985CE9661AF84F186 +PT=E2895D416951FDA66B695ABFA313F89D + +I=60 +KEY=4E9BC121E32849DAA501BEA4E534D9C2531D4A5A32B1A5D4780D5508E63113DA +CT=E2895D416951FDA66B695ABFA313F89D +PT=91E93AAECC5FB253F7463F101B2A4132 + +I=61 +KEY=ACC045A67F680F14D3F8DA454C922071C2F470F4FEEE17878F4B6A18FD1B52E8 +CT=91E93AAECC5FB253F7463F101B2A4132 +PT=F0F339022B4001E72F3BCC1A140603AD + +I=62 +KEY=4B47D2639B4A04D3C87D35DB4E63E563320749F6D5AE1660A070A602E91D5145 +CT=F0F339022B4001E72F3BCC1A140603AD +PT=DBECAFF90EDD4555A5D9A23817520D51 + +I=63 +KEY=C73B1C617BE90F2710DFF2C3AC60E0F9E9EBE60FDB73533505A9043AFE4F5C14 +CT=DBECAFF90EDD4555A5D9A23817520D51 +PT=73315A63A8889095AFED497AEFE657B4 + +I=64 +KEY=7F368758F7B303DE356481ED8EBFA46F9ADABC6C73FBC3A0AA444D4011A90BA0 +CT=73315A63A8889095AFED497AEFE657B4 +PT=3AB7E2F81D24D857308A1FC785559333 + +I=65 +KEY=6D7EF76412498AB3C70AA3006CC87188A06D5E946EDF1BF79ACE528794FC9893 +CT=3AB7E2F81D24D857308A1FC785559333 +PT=7EAA2814E372F674AB0B6E0E428D1AF4 + +I=66 +KEY=D626AD50A7B86153BF9215A6A8F7E908DEC776808DADED8331C53C89D6718267 +CT=7EAA2814E372F674AB0B6E0E428D1AF4 +PT=ADD212A59AC9EF6A55AEAC22D35A1BFE + +I=67 +KEY=4B9C7ED9AC7835C87DAB8BEF3ED6878B73156425176402E9646B90AB052B9999 +CT=ADD212A59AC9EF6A55AEAC22D35A1BFE +PT=203ECD34AE1BB2F23BC673DBD74FA07B + +I=68 +KEY=E34FBDEF9D81B464DD1138093F132051532BA911B97FB01B5FADE370D26439E2 +CT=203ECD34AE1BB2F23BC673DBD74FA07B +PT=0A18AFD5EEBBD338299897EA1F01324C + +I=69 +KEY=77BD51D39775121C22343FFC66D40F0B593306C457C463237635749ACD650BAE +CT=0A18AFD5EEBBD338299897EA1F01324C +PT=2892A6AE9517642A0977942360FB8104 + +I=70 +KEY=2761BF5478726AF184C86B45AE331A7E71A1A06AC2D307097F42E0B9AD9E8AAA +CT=2892A6AE9517642A0977942360FB8104 +PT=8A4CD7685B9A1E663C3130C34BC418B9 + +I=71 +KEY=DD168B81E90D806FF468BE5E551F3344FBED77029949196F4373D07AE65A9213 +CT=8A4CD7685B9A1E663C3130C34BC418B9 +PT=C7C0A15A1A22363B378D5DD27A69D4C2 + +I=72 +KEY=3442C07C0E98F523F9278D934F424BD83C2DD658836B2F5474FE8DA89C3346D1 +CT=C7C0A15A1A22363B378D5DD27A69D4C2 +PT=55A8EF8CAE213FE3FD6AA77E7415400A + +I=73 +KEY=291BD1577921B2947BC470C19727F0BD698539D42D4A10B789942AD6E82606DB +CT=55A8EF8CAE213FE3FD6AA77E7415400A +PT=0B07BEB71461356645936996AC45EB87 + +I=74 +KEY=46475B4C21F0F4895FEFCC67632DBCDC62828763392B25D1CC0743404463ED5C +CT=0B07BEB71461356645936996AC45EB87 +PT=6DFA5978F740C18CEE6F70FF50008BFD + +I=75 +KEY=CF89BDDE5D363B3C44DB6FED2DAB47AA0F78DE1BCE6BE45D226833BF146366A1 +CT=6DFA5978F740C18CEE6F70FF50008BFD +PT=6F58747F0336A2C4D2A397511E06D703 + +I=76 +KEY=85F7D4A4503F7C3D52998384F8B29BEF6020AA64CD5D4699F0CBA4EE0A65B1A2 +CT=6F58747F0336A2C4D2A397511E06D703 +PT=32AC7B1B8FFA7D411F46C129EEFFAF13 + +I=77 +KEY=CDE87D2DFB6198CFC737D93433419757528CD17F42A73BD8EF8D65C7E49A1EB1 +CT=32AC7B1B8FFA7D411F46C129EEFFAF13 +PT=CF5D039714814E72ECE7B9D5D1B27D11 + +I=78 +KEY=BCB9F75F11496AABFE2633E393B59B449DD1D2E8562675AA036ADC12352863A0 +CT=CF5D039714814E72ECE7B9D5D1B27D11 +PT=3455F997002A1818967E2679A07C1D56 + +I=79 +KEY=99E143B3524E724A009533AEC659E15BA9842B7F560C6DB29514FA6B95547EF6 +CT=3455F997002A1818967E2679A07C1D56 +PT=1F2113D44E290F1379A3CEC6D57D6279 + +I=80 +KEY=90086C83794D6878FF2CE748ECA6EDF4B6A538AB182562A1ECB734AD40291C8F +CT=1F2113D44E290F1379A3CEC6D57D6279 +PT=88866DB676AA3B21954AFDE0A0F33007 + +I=81 +KEY=FA254EB868F6CD5965346ACAE326BD2A3E23551D6E8F598079FDC94DE0DA2C88 +CT=88866DB676AA3B21954AFDE0A0F33007 +PT=A1665AD0252764E2691E65FEFB609CDA + +I=82 +KEY=92032C92FEEB0A5CD5D71AAF1BF5F47D9F450FCD4BA83D6210E3ACB31BBAB052 +CT=A1665AD0252764E2691E65FEFB609CDA +PT=988CE348430A206546379A8C684C00F1 + +I=83 +KEY=CF32144187F7B98256B5B4204DFABC8807C9EC8508A21D0756D4363F73F6B0A3 +CT=988CE348430A206546379A8C684C00F1 +PT=60289F0B6A9ADD08BF8924AA6D7F4D12 + +I=84 +KEY=A7BD244360E3C325F3EA315C86959DD867E1738E6238C00FE95D12951E89FDB1 +CT=60289F0B6A9ADD08BF8924AA6D7F4D12 +PT=FA3EA122499D7E083D81F147D9D68B09 + +I=85 +KEY=86213610EDC35A883A3364E8D529C6459DDFD2AC2BA5BE07D4DCE3D2C75F76B8 +CT=FA3EA122499D7E083D81F147D9D68B09 +PT=8E0B2452EF0515FC554A0AADF107714D + +I=86 +KEY=92CC3AE4A2A68CD93634075E902C66CB13D4F6FEC4A0ABFB8196E97F365807F5 +CT=8E0B2452EF0515FC554A0AADF107714D +PT=463CEAE83A50BA54280E792AB6B29B94 + +I=87 +KEY=6D86FA00DBB949A29D4A6166F1EF531E55E81C16FEF011AFA998905580EA9C61 +CT=463CEAE83A50BA54280E792AB6B29B94 +PT=416CA710B874E50CC98DF842B3435AD1 + +I=88 +KEY=C9400C98A04F5041BE1C6090A866F7DA1484BB064684F4A36015681733A9C6B0 +CT=416CA710B874E50CC98DF842B3435AD1 +PT=3BA8BB5C572C0404E4B8199528825904 + +I=89 +KEY=ED5043E9699B37844033E8BD170588342F2C005A11A8F0A784AD71821B2B9FB4 +CT=3BA8BB5C572C0404E4B8199528825904 +PT=1D2812DE70AA2D59894DA4DA7FE906FC + +I=90 +KEY=1964C6C301EEEF60B34E8E35175CAF8D320412846102DDFE0DE0D55864C29948 +CT=1D2812DE70AA2D59894DA4DA7FE906FC +PT=2735CAAFE653442FFC2E878AE2829998 + +I=91 +KEY=567B1E0737D0F72F82EB3A47D17209191531D82B875199D1F1CE52D2864000D0 +CT=2735CAAFE653442FFC2E878AE2829998 +PT=07B5FA4835E5DFC67E02F490A497145D + +I=92 +KEY=89AAD6DCA6A8973580D02768EBC8372412842263B2B446178FCCA64222D7148D +CT=07B5FA4835E5DFC67E02F490A497145D +PT=A31272EC8623213B015811FAE12330CE + +I=93 +KEY=4B4AB47A0DBA39907D8E919767E69518B196508F3497672C8E94B7B8C3F42443 +CT=A31272EC8623213B015811FAE12330CE +PT=9132AB51C9738A62CABDE4977947E0BF + +I=94 +KEY=BEC71999AEE5517C243B65830D30DEBB20A4FBDEFDE4ED4E4429532FBAB3C4FC +CT=9132AB51C9738A62CABDE4977947E0BF +PT=689375EA83B61894631E6EFA2D509531 + +I=95 +KEY=77CE2C97A458300D7C95C6871CEB56D648378E347E52F5DA27373DD597E351CD +CT=689375EA83B61894631E6EFA2D509531 +PT=AAA5C6C5917DFC103383DE6C79EB2BA6 + +I=96 +KEY=0AD691774612F7EFA41FE39B8B3A2D14E29248F1EF2F09CA14B4E3B9EE087A6B +CT=AAA5C6C5917DFC103383DE6C79EB2BA6 +PT=29D9945BDB3770ED2A41D2760D0DC51D + +I=97 +KEY=4E1D42ADC4CEF6BAE3A5B9E08F7ACD65CB4BDCAA341879273EF531CFE305BF76 +CT=29D9945BDB3770ED2A41D2760D0DC51D +PT=2F9B3C4E1FDCDC8F7D5DFBEA342284F2 + +I=98 +KEY=2D76A3E35C075DB14E40A59F46E07A81E4D0E0E42BC4A5A843A8CA25D7273B84 +CT=2F9B3C4E1FDCDC8F7D5DFBEA342284F2 +PT=ED4CFCF1C8D226EBACCC8FF11B1C81B8 + +I=99 +KEY=E7364D0D17D723A69C0BA956778BD0E9099C1C15E3168343EF6445D4CC3BBA3C +CT=ED4CFCF1C8D226EBACCC8FF11B1C81B8 +PT=2F9B5E1392B767E8497F849D00E98193 + +I=100 +KEY=709380C7012CB4272A69F6D4936B163E2607420671A1E4ABA61BC149CCD23BAF +CT=2F9B5E1392B767E8497F849D00E98193 +PT=3BE783A4A38EFB44150AA7A08E1888F6 + +I=101 +KEY=98FF27B8AB7B91F690231E24608076EF1DE0C1A2D22F1FEFB31166E942CAB359 +CT=3BE783A4A38EFB44150AA7A08E1888F6 +PT=F35AED9C83E53D2EADDE507345096218 + +I=102 +KEY=24F9D2FF633EE9AAED7321CFCF4D1D20EEBA2C3E51CA22C11ECF369A07C3D141 +CT=F35AED9C83E53D2EADDE507345096218 +PT=A22BF93FD521A6E59C196022FF252DC2 + +I=103 +KEY=70E491840BC5C42A878655E18E9AAAA74C91D50184EB842482D656B8F8E6FC83 +CT=A22BF93FD521A6E59C196022FF252DC2 +PT=11E67B52F8CD97D63268485EB546E1FE + +I=104 +KEY=098FF2D6DE55FF5C66D5AD7D5949643A5D77AE537C2613F2B0BE1EE64DA01D7D +CT=11E67B52F8CD97D63268485EB546E1FE +PT=1E67AF3F7E7FDEFB868696E96F718ACC + +I=105 +KEY=B89EA7CBAE57B8AD39F23B22A8F651A44310016C0259CD093638880F22D197B1 +CT=1E67AF3F7E7FDEFB868696E96F718ACC +PT=332B0045710B2DD6EC3D619051580C7F + +I=106 +KEY=39F71BC56EBFA91088499DC41A0C5B5B703B01297352E0DFDA05E99F73899BCE +CT=332B0045710B2DD6EC3D619051580C7F +PT=86F3D75D18F7AB31C6C52C19B0C35023 + +I=107 +KEY=417147DB03FDA0B26BEED7FE8A9487D5F6C8D6746BA54BEE1CC0C586C34ACBED +CT=86F3D75D18F7AB31C6C52C19B0C35023 +PT=452E6C2DA8B93A1E282F1A86AECB9F15 + +I=108 +KEY=C4336C26C20AD7811578044800A51E8EB3E6BA59C31C71F034EFDF006D8154F8 +CT=452E6C2DA8B93A1E282F1A86AECB9F15 +PT=637F010BAC28AC108331F4E26B262D3A + +I=109 +KEY=D0369C75D40EEF29CF7588FB87EE2ED2D099BB526F34DDE0B7DE2BE206A779C2 +CT=637F010BAC28AC108331F4E26B262D3A +PT=3F3DCA8B4C2DDFD556880A17FB575E7B + +I=110 +KEY=4DE25218630A678C287EC42F93985D22EFA471D923190235E15621F5FDF027B9 +CT=3F3DCA8B4C2DDFD556880A17FB575E7B +PT=3DA8C1D40B51A8BC6E728D7A1E6B3B2E + +I=111 +KEY=C0526C3096805B532433C0248E153A00D20CB00D2848AA898F24AC8FE39B1C97 +CT=3DA8C1D40B51A8BC6E728D7A1E6B3B2E +PT=449B050578191E4C156F7040EF27D5EC + +I=112 +KEY=6A1B7384328BAA25B6A857FB12A90FD49697B5085051B4C59A4BDCCF0CBCC97B +CT=449B050578191E4C156F7040EF27D5EC +PT=D58ACA128F936803BDD5EC1E6DECAB04 + +I=113 +KEY=44B7F3EB0EF0EF4325353D30F35C4D71431D7F1ADFC2DCC6279E30D16150627F +CT=D58ACA128F936803BDD5EC1E6DECAB04 +PT=77F1011F968AD46338CA68D5DF37959E + +I=114 +KEY=E1E6BBD70AEAC4D65159422B3DFE82DF34EC7E05494808A51F545804BE67F7E1 +CT=77F1011F968AD46338CA68D5DF37959E +PT=FC692161766A29C9E6A86C353E2F3FE5 + +I=115 +KEY=5C33A88179175BB12593D6574245A6A6C8855F643F22216CF9FC34318048C804 +CT=FC692161766A29C9E6A86C353E2F3FE5 +PT=F5FD2F77BC4908F470142417048C6233 + +I=116 +KEY=E6A3CDD47570AEC4FC3B3453F78F253F3D787013836B299889E8102684C4AA37 +CT=F5FD2F77BC4908F470142417048C6233 +PT=FBDC2774D7E426CBD8B62ABD0E0EAA6F + +I=117 +KEY=4F5B3EDC53366D4C74D94663E17CBDB6C6A45767548F0F53515E3A9B8ACA0058 +CT=FBDC2774D7E426CBD8B62ABD0E0EAA6F +PT=796D978C9D724C1C9445EC5BD272CEB0 + +I=118 +KEY=9119AD19E78100B3D04BED87FF5C22B5BFC9C0EBC9FD434FC51BD6C058B8CEE8 +CT=796D978C9D724C1C9445EC5BD272CEB0 +PT=15ECF7D3F516D3CBA0307959287A5BAB + +I=119 +KEY=600B4D7604FF2650611C453A50D02275AA2537383CEB9084652BAF9970C29543 +CT=15ECF7D3F516D3CBA0307959287A5BAB +PT=DA67996084E9C74C143310FC3CF207DD + +I=120 +KEY=3B8E0B73BBF745BB360EA50E7DA9B3297042AE58B80257C87118BF654C30929E +CT=DA67996084E9C74C143310FC3CF207DD +PT=6E9BC50580D45D54FEEC74830C0D9516 + +I=121 +KEY=231592D0CE761359AE2E85CC4E4156A01ED96B5D38D60A9C8FF4CBE6403D0788 +CT=6E9BC50580D45D54FEEC74830C0D9516 +PT=A4B0F6A50C72C5EE755FA5595334DF2E + +I=122 +KEY=7ABD82D278910B909B0D6219EF5E0D98BA699DF834A4CF72FAAB6EBF1309D8A6 +CT=A4B0F6A50C72C5EE755FA5595334DF2E +PT=24CDAEEB54A1EB7E2D4A0BEE526EA6E0 + +I=123 +KEY=5C8F7B23850BD287F011E257D691F8979EA433136005240CD7E1655141677E46 +CT=24CDAEEB54A1EB7E2D4A0BEE526EA6E0 +PT=84F24CDC0AA63CEA2DDE8F94C8776765 + +I=124 +KEY=DF8EEE46309021F6E7D7D41908B6CABE1A567FCF6AA318E6FA3FEAC589101923 +CT=84F24CDC0AA63CEA2DDE8F94C8776765 +PT=EEA20542DEDB0B99A2144942FFEAC820 + +I=125 +KEY=8634A663D618B3BB54F44A5849170ACDF4F47A8DB478137F582BA38776FAD103 +CT=EEA20542DEDB0B99A2144942FFEAC820 +PT=CDD91737753BE9F672A60DD722202127 + +I=126 +KEY=E41913E97F21A4E6A948ABEB45279E0D392D6DBAC143FA892A8DAE5054DAF024 +CT=CDD91737753BE9F672A60DD722202127 +PT=E6E2F7846E06BB90F19B21521DD4D238 + +I=127 +KEY=1E63624B5EADBE7D42255F208CC7D348DFCF9A3EAF454119DB168F02490E221C +CT=E6E2F7846E06BB90F19B21521DD4D238 +PT=0110CA2647D43C8BD012976113EFB860 + +I=128 +KEY=8476329019AA4D0D91C71E0DFFF47906DEDF5018E8917D920B0418635AE19A7C +CT=0110CA2647D43C8BD012976113EFB860 +PT=CC9AACC98876387D09565F1A20D329AF + +I=129 +KEY=DB1C0803BC1AD91C5621FA8C54AA83EF1245FCD160E745EF025247797A32B3D3 +CT=CC9AACC98876387D09565F1A20D329AF +PT=55AB296D67DEEBA179AD8093C1952CC2 + +I=130 +KEY=5C0887FF7C888D7800C43BC9E88D9B3B47EED5BC0739AE4E7BFFC7EABBA79F11 +CT=55AB296D67DEEBA179AD8093C1952CC2 +PT=27016691505182706848CD5D7A2C5CAB + +I=131 +KEY=0FFBE12ADFA17F3BF26622C20311D38960EFB32D57682C3E13B70AB7C18BC3BA +CT=27016691505182706848CD5D7A2C5CAB +PT=5E6C9FAF480FFE51D7687ADE203D5367 + +I=132 +KEY=C4C12330BC21062618E2E83EC3755DAC3E832C821F67D26FC4DF7069E1B690DD +CT=5E6C9FAF480FFE51D7687ADE203D5367 +PT=082FF20DC6AFBA3888348E5724F5C526 + +I=133 +KEY=3F6BF56A0136C1058924FCD831A65EBC36ACDE8FD9C868574CEBFE3EC54355FB +CT=082FF20DC6AFBA3888348E5724F5C526 +PT=67AE68CDDA349A067339F28FA216A188 + +I=134 +KEY=4AB9E8E9B5BB84353006AB43065C6B8F5102B64203FCF2513FD20CB16755F473 +CT=67AE68CDDA349A067339F28FA216A188 +PT=3316F37F97D679B78A537A0E107923AB + +I=135 +KEY=E04DE045508423D735B20168C7974CC26214453D942A8BE6B58176BF772CD7D8 +CT=3316F37F97D679B78A537A0E107923AB +PT=00AEB331686999C5F5FB1E7C6CCF1072 + +I=136 +KEY=D4D19E570760468E9703F0E49C4AC9F262BAF60CFC431223407A68C31BE3C7AA +CT=00AEB331686999C5F5FB1E7C6CCF1072 +PT=29A5DB93D2AE9B1ED9714213EAD9AA1C + +I=137 +KEY=6D6789354D2CC3EFA9ABFC466F21A6E24B1F2D9F2EED893D990B2AD0F13A6DB6 +CT=29A5DB93D2AE9B1ED9714213EAD9AA1C +PT=E98426CB0F858A084EB66311188D9200 + +I=138 +KEY=06ED66801B81943BF1640AAE222A23C7A29B0B5421680335D7BD49C1E9B7FFB6 +CT=E98426CB0F858A084EB66311188D9200 +PT=21527326577425261F2D40268C428E29 + +I=139 +KEY=2232758279A806C21870C85273C12FA883C97872761C2613C89009E765F5719F +CT=21527326577425261F2D40268C428E29 +PT=CC9393A43B8A8194C0EC29F989E597A6 + +I=140 +KEY=E7E22C2A6E6D4A1BFE7B706047094AF44F5AEBD64D96A787087C201EEC10E639 +CT=CC9393A43B8A8194C0EC29F989E597A6 +PT=714846062B262A823B24164900DF91AD + +I=141 +KEY=89A78F64BCAEE02CAC92928134C2567C3E12ADD066B08D0533583657ECCF7794 +CT=714846062B262A823B24164900DF91AD +PT=1D0AC79D1E9BB36A6A6A8E49538C08FF + +I=142 +KEY=4F6E8D81296C95FAA0FE6F2D324A392223186A4D782B3E6F5932B81EBF437F6B +CT=1D0AC79D1E9BB36A6A6A8E49538C08FF +PT=403D8B10E0AB31493589AFFA8E8B1BEE + +I=143 +KEY=24E398291CF018E4666728F4F635F74D6325E15D98800F266CBB17E431C86485 +CT=403D8B10E0AB31493589AFFA8E8B1BEE +PT=9E0516EDA401DAAF6AC013841C0D63C8 + +I=144 +KEY=F80CF8AF1FA463D2ED7C7F59C1B239B0FD20F7B03C81D589067B04602DC5074D +CT=9E0516EDA401DAAF6AC013841C0D63C8 +PT=74B2B200922B21AA20A0C5860CFB7E4D + +I=145 +KEY=577A5456424E1A76C3E113EB82CCDF34899245B0AEAAF42326DBC1E6213E7900 +CT=74B2B200922B21AA20A0C5860CFB7E4D +PT=25AFF27E13888A638CDA2673D7F16AFD + +I=146 +KEY=7C623BBD4777E6EF9BC058DF5BA27BEAAC3DB7CEBD227E40AA01E795F6CF13FD +CT=25AFF27E13888A638CDA2673D7F16AFD +PT=A54F400AB9C52913D7302BA36BF217DD + +I=147 +KEY=A8B33E433720C4B925C4F0315DDB73B00972F7C404E757537D31CC369D3D0420 +CT=A54F400AB9C52913D7302BA36BF217DD +PT=48A263A07112AA95EA1414CE03545790 + +I=148 +KEY=DA864B91AED3E2FAC25782F4A50C13C841D0946475F5FDC69725D8F89E6953B0 +CT=48A263A07112AA95EA1414CE03545790 +PT=541547E924522E59C1721D130B64D92F + +I=149 +KEY=EEB5FF6F9C435510E12934F5E806553E15C5D38D51A7D39F5657C5EB950D8A9F +CT=541547E924522E59C1721D130B64D92F +PT=5830544939EB4607145538388840248B + +I=150 +KEY=24E609AD29E4C601189CB2FE119767884DF587C4684C95984202FDD31D4DAE14 +CT=5830544939EB4607145538388840248B +PT=CBE1F82FD3318448AA36ADB5967EF865 + +I=151 +KEY=5A7EBB76C38C2E5F038612A06E84BB2C86147FEBBB7D11D0E83450668B335671 +CT=CBE1F82FD3318448AA36ADB5967EF865 +PT=3B104547D2D620879E3CB2B5774C0FB4 + +I=152 +KEY=827EFCB7BC862C2466B8C79FC297AD3DBD043AAC69AB31577608E2D3FC7F59C5 +CT=3B104547D2D620879E3CB2B5774C0FB4 +PT=B667F7544FE49A07611A160E3312F69A + +I=153 +KEY=9BC6C18805144F98CAEA7B252B3EE2930B63CDF8264FAB501712F4DDCF6DAF5F +CT=B667F7544FE49A07611A160E3312F69A +PT=C3E928FDEB5D7DDF7CF32C4DBCFE32F3 + +I=154 +KEY=2BC00DF6D26F9A968C3BFF47AE761718C88AE505CD12D68F6BE1D89073939DAC +CT=C3E928FDEB5D7DDF7CF32C4DBCFE32F3 +PT=72A9CF7AA2EDAF1907D77D10A02A45DE + +I=155 +KEY=15A0EE054E2D5E7EDCF3FC766860ACCDBA232A7F6FFF79966C36A580D3B9D872 +CT=72A9CF7AA2EDAF1907D77D10A02A45DE +PT=97ABFAAD506940F88FDC8F55AD7EA919 + +I=156 +KEY=C56C11F3A96852119C16751963C24CD42D88D0D23F96396EE3EA2AD57EC7716B +CT=97ABFAAD506940F88FDC8F55AD7EA919 +PT=DD55A02B1EB01EB091CA6337D0BEB5BD + +I=157 +KEY=8634CC7B3416FCE337AAFA39791D1545F0DD70F9212627DE722049E2AE79C4D6 +CT=DD55A02B1EB01EB091CA6337D0BEB5BD +PT=C5EB3DF5A328B267F3895CECD4A828AF + +I=158 +KEY=DDC1361E1432CCAC3551E2478A321A0035364D0C820E95B981A9150E7AD1EC79 +CT=C5EB3DF5A328B267F3895CECD4A828AF +PT=49952DACD97FD5583A7D9C4FF515EC17 + +I=159 +KEY=52658EEC2A7441D866CFA15944BB12857CA360A05B7140E1BBD489418FC4006E +CT=49952DACD97FD5583A7D9C4FF515EC17 +PT=4971EEEF871E935AC470BD770802B04B + +I=160 +KEY=05FC7A181B1935EA8DCEC961B0DFC14B35D28E4FDC6FD3BB7FA4343687C6B025 +CT=4971EEEF871E935AC470BD770802B04B +PT=3DB5E9165C24EC3790DC3E53E5E5D2DE + +I=161 +KEY=8D2793B7BDCF80338AA39C86008361BC08676759804B3F8CEF780A65622362FB +CT=3DB5E9165C24EC3790DC3E53E5E5D2DE +PT=1FDB5D4FBB59F082B3B617C8A23734F1 + +I=162 +KEY=37BE37961B77866869826907BB9E9C1717BC3A163B12CF0E5CCE1DADC014560A +CT=1FDB5D4FBB59F082B3B617C8A23734F1 +PT=8C59775AD3FF7C337B22C8E785321E25 + +I=163 +KEY=F3184EA1C8FFE3D436BEE076AA999B659BE54D4CE8EDB33D27ECD54A4526482F +CT=8C59775AD3FF7C337B22C8E785321E25 +PT=0CB834FCC0CFDAECAF4AFC5A2E38DF23 + +I=164 +KEY=CACF50D99B066EB84CBFAEEC9B0D6769975D79B0282269D188A629106B1E970C +CT=0CB834FCC0CFDAECAF4AFC5A2E38DF23 +PT=229EB7B6A97D91921BCD8C95A0D7C17B + +I=165 +KEY=3FA80E4FB785B9FC3B058CC62D289958B5C3CE06815FF843936BA585CBC95677 +CT=229EB7B6A97D91921BCD8C95A0D7C17B +PT=0D7692C281DD4FF35D9B1620E1385C34 + +I=166 +KEY=CE2A3A893C96A4F1AA81AD52EBCC3C23B8B55CC40082B7B0CEF0B3A52AF10A43 +CT=0D7692C281DD4FF35D9B1620E1385C34 +PT=D3C5FE594F5C8C5A359235448EB20146 + +I=167 +KEY=FC8642DB8CB42D1B1251CB7FE6AFF90D6B70A29D4FDE3BEAFB6286E1A4430B05 +CT=D3C5FE594F5C8C5A359235448EB20146 +PT=8C0F88460C700D96847249807B84223F + +I=168 +KEY=2A9C9FD184A5B2418FD415A228A5C0AFE77F2ADB43AE367C7F10CF61DFC7293A +CT=8C0F88460C700D96847249807B84223F +PT=5A4237A5C2DABDCDA6389D5FC66032F6 + +I=169 +KEY=FDB533163E989D2FA32CCA5D3CC5D376BD3D1D7E81748BB1D928523E19A71BCC +CT=5A4237A5C2DABDCDA6389D5FC66032F6 +PT=BF8AAC6B1536CCCCECCC9D6BE970EB3E + +I=170 +KEY=3C4B3CF0FD0C4292B2497175D4400F8902B7B1159442477D35E4CF55F0D7F0F2 +CT=BF8AAC6B1536CCCCECCC9D6BE970EB3E +PT=97CE58407FD26D63C86765CB05EA6277 + +I=171 +KEY=367862F3E2C5520EA2269392B6139E9C9579E955EB902A1EFD83AA9EF53D9285 +CT=97CE58407FD26D63C86765CB05EA6277 +PT=B411687B044B624077A92D8C130697B9 + +I=172 +KEY=0300AF491DAF6C607417FB1FD9B1EC612168812EEFDB485E8A2A8712E63B053C +CT=B411687B044B624077A92D8C130697B9 +PT=D22E92A5132EA85F4FB25EE19C248008 + +I=173 +KEY=7C92EF49A7D27E97F1884299B635F0ADF346138BFCF5E001C598D9F37A1F8534 +CT=D22E92A5132EA85F4FB25EE19C248008 +PT=FD6817CD680A2A8CE93E4B4F9CAA72AA + +I=174 +KEY=80EABB1D8C9B5F769FCAC87ED8D0C9CA0E2E044694FFCA8D2CA692BCE6B5F79E +CT=FD6817CD680A2A8CE93E4B4F9CAA72AA +PT=8DDD9B3B9278D2DE3453EA6769E1C39C + +I=175 +KEY=FB345E2D7BBBED527259FAEAEA79C05D83F39F7D0687185318F578DB8F543402 +CT=8DDD9B3B9278D2DE3453EA6769E1C39C +PT=AE69F5CD8D342E74113E979ACE3539F2 + +I=176 +KEY=7D93DC33FF2266770291160CD317C65E2D9A6AB08BB3362709CBEF4141610DF0 +CT=AE69F5CD8D342E74113E979ACE3539F2 +PT=30E19A4E84997172486DAE4FB4C41E58 + +I=177 +KEY=82362FF3E9C1AD93474CF4CABD354E7E1D7BF0FE0F2A475541A6410EF5A513A8 +CT=30E19A4E84997172486DAE4FB4C41E58 +PT=75B3D07617EB189512DC5161908940C1 + +I=178 +KEY=8EFD0FCB3855CCC16BD919FBD17596C768C8208818C15FC0537A106F652C5369 +CT=75B3D07617EB189512DC5161908940C1 +PT=FD13E89107FAFA44998721AD726C620F + +I=179 +KEY=2299D22282C798107F489637DCD479C395DBC8191F3BA584CAFD31C217403166 +CT=FD13E89107FAFA44998721AD726C620F +PT=C1B0210C0387864717BD7D02063B6A69 + +I=180 +KEY=75E05597A2BBDF23E5BD172C83548C9B546BE9151CBC23C3DD404CC0117B5B0F +CT=C1B0210C0387864717BD7D02063B6A69 +PT=0E442B38E9024CCA5DC43A7B8D5F6FCF + +I=181 +KEY=4DBC8DCB8C25B5F4AD374BA3064216555A2FC22DF5BE6F09808476BB9C2434C0 +CT=0E442B38E9024CCA5DC43A7B8D5F6FCF +PT=8FD213EC19D62FD2C19E6C91B97E56A0 + +I=182 +KEY=E393BAD07E955EBC1446B847DE5A891ED5FDD1C1EC6840DB411A1A2A255A6260 +CT=8FD213EC19D62FD2C19E6C91B97E56A0 +PT=F52ADFD33A68EE198F33708E676D0CE9 + +I=183 +KEY=3F33A76F87DB0388C2D66C7F2EFAA1B820D70E12D600AEC2CE296AA442376E89 +CT=F52ADFD33A68EE198F33708E676D0CE9 +PT=7649EB4283505EEEE1BE16DB6677B3F5 + +I=184 +KEY=04BC65DE70C9E01EEEDA5A507C218C8D569EE5505550F02C2F977C7F2440DD7C +CT=7649EB4283505EEEE1BE16DB6677B3F5 +PT=6FB1C4AD8A5B8A606621A8BF4277F3DC + +I=185 +KEY=8A6EF9710F4AE10EB60C8D25A8F67C50392F21FDDF0B7A4C49B6D4C066372EA0 +CT=6FB1C4AD8A5B8A606621A8BF4277F3DC +PT=22C2CF9572D708F688291056E2F8E120 + +I=186 +KEY=ED6D084D5F8AA4F201F9C20EA26A90E81BEDEE68ADDC72BAC19FC49684CFCF80 +CT=22C2CF9572D708F688291056E2F8E120 +PT=28AC7257911ECEB549D910BFA0905AE5 + +I=187 +KEY=BA2735927D6A76B952C08A219FBB572233419C3F3CC2BC0F8846D429245F9565 +CT=28AC7257911ECEB549D910BFA0905AE5 +PT=2A1F3842DF988CDA0C6415450A657DB2 + +I=188 +KEY=53BCC06CCCBC31A5BEE2CE88E6EAEFAC195EA47DE35A30D58422C16C2E3AE8D7 +CT=2A1F3842DF988CDA0C6415450A657DB2 +PT=6055EB3A24DE4D87C6BA5073A5BAC919 + +I=189 +KEY=DF88C3CEC31C7B88D8AC0C7AAA2CED99790B4F47C7847D524298911F8B8021CE +CT=6055EB3A24DE4D87C6BA5073A5BAC919 +PT=CC051CCD37068B41935FD14538DFEF82 + +I=190 +KEY=265B351B93FF456D5A1EAADD2BEA1296B50E538AF082F613D1C7405AB35FCE4C +CT=CC051CCD37068B41935FD14538DFEF82 +PT=225B63F455DD72EC87CF6FD5DF0FDAF3 + +I=191 +KEY=BAC4C541E0A693CF8A3892A82F67CD959755307EA55F84FF56082F8F6C5014BF +CT=225B63F455DD72EC87CF6FD5DF0FDAF3 +PT=64027F6B72F0A11628F66D5C502658E8 + +I=192 +KEY=E8F68EF4909A128F331DFEFAE8560EBCF3574F15D7AF25E97EFE42D33C764C57 +CT=64027F6B72F0A11628F66D5C502658E8 +PT=529AAF9163EDA1BC39E66D2556BE938B + +I=193 +KEY=1951B1A50BED04096C17E816D4EC6225A1CDE084B442845547182FF66AC8DFDC +CT=529AAF9163EDA1BC39E66D2556BE938B +PT=F93E85D98EB9BDDD7D3844421235FBAB + +I=194 +KEY=D39AF070909FBC0E3226E28041B0286158F3655D3AFB39883A206BB478FD2477 +CT=F93E85D98EB9BDDD7D3844421235FBAB +PT=16B6B3CC08003BA36C9E84B1EE9CD7CC + +I=195 +KEY=B705C6CCD010B980E386B8690C83E96C4E45D69132FB022B56BEEF059661F3BB +CT=16B6B3CC08003BA36C9E84B1EE9CD7CC +PT=301AFE66055149FA5775A9CE19F1FF63 + +I=196 +KEY=B3C813D4FCBD31ED95E7E71CEC15153E7E5F28F737AA4BD101CB46CB8F900CD8 +CT=301AFE66055149FA5775A9CE19F1FF63 +PT=1090E68F7C8400861589E304A5B815CD + +I=197 +KEY=0EBC30ADB6946B6415C0309D636C79F46ECFCE784B2E4B571442A5CF2A281915 +CT=1090E68F7C8400861589E304A5B815CD +PT=2778F0C712804C0B8D085B196A4D73C4 + +I=198 +KEY=9C5815C6705B39DEECB8BDDDC9329A0D49B73EBF59AE075C994AFED640656AD1 +CT=2778F0C712804C0B8D085B196A4D73C4 +PT=14FECB137DC9C38A04D92B60A177A61D + +I=199 +KEY=9D83B41F8F415B5F3B2C08682383471B5D49F5AC2467C4D69D93D5B6E112CCCC +CT=14FECB137DC9C38A04D92B60A177A61D +PT=0EF1321EA52EAA7624E3F2EFD0C886AF + +I=200 +KEY=2960CEE0AF043ED1A549BA223F6C1CF153B8C7B281496EA0B970275931DA4A63 +CT=0EF1321EA52EAA7624E3F2EFD0C886AF +PT=AFA8B2129577EC178B59D42D1B92D313 + +I=201 +KEY=51E0DECF48A151021C70EC3EE3CE9008FC1075A0143E82B73229F3742A489970 +CT=AFA8B2129577EC178B59D42D1B92D313 +PT=3351631344E6EF86712327D3C05EBDEB + +I=202 +KEY=5F34A789B0B1185BA7D1BB3EF2677060CF4116B350D86D31430AD4A7EA16249B +CT=3351631344E6EF86712327D3C05EBDEB +PT=C299D0556B0D15014627CADBCCC3DC33 + +I=203 +KEY=FC3E420F84F4C75802DCF68ABF0030E70DD8C6E63BD57830052D1E7C26D5F8A8 +CT=C299D0556B0D15014627CADBCCC3DC33 +PT=CEB83A2B9DD76B649BAAE48A8B772A5C + +I=204 +KEY=C04448AD77DBF33F22A2346C7A40F813C360FCCDA60213549E87FAF6ADA2D2F4 +CT=CEB83A2B9DD76B649BAAE48A8B772A5C +PT=A8C6AEC94E82BC68AC8E29A8CB9504F6 + +I=205 +KEY=3FA863ECC4AFA141DD7349C44F94FEE16BA65204E880AF3C3209D35E6637D602 +CT=A8C6AEC94E82BC68AC8E29A8CB9504F6 +PT=1EDED55C8D3309F828C17AF072C79D7A + +I=206 +KEY=8893E5FB27191AE09E4AB5F062289F117578875865B3A6C41AC8A9AE14F04B78 +CT=1EDED55C8D3309F828C17AF072C79D7A +PT=FD2AC22891FB294EB0AD2BADFE759C29 + +I=207 +KEY=90BA1205BB7927E86F9895855648D3EB88524570F4488F8AAA658203EA85D751 +CT=FD2AC22891FB294EB0AD2BADFE759C29 +PT=2FE6AE59ACD516EE1567A7A1C43FDE2A + +I=208 +KEY=278FD88834EA67564F301785C4045D6FA7B4EB29589D9964BF0225A22EBA097B +CT=2FE6AE59ACD516EE1567A7A1C43FDE2A +PT=35BEC13F159F61C7EF4C860AD3B41A75 + +I=209 +KEY=E9D2F23C213D02724737A5E907BFBDF0920A2A164D02F8A3504EA3A8FD0E130E +CT=35BEC13F159F61C7EF4C860AD3B41A75 +PT=650D65D6ED716DA515EAAF1A7447C3FB + +I=210 +KEY=4A0A997634E2D9305795FC90291F6FD9F7074FC0A073950645A40CB28949D0F5 +CT=650D65D6ED716DA515EAAF1A7447C3FB +PT=7AFE0D2F234A6CDEDD7103DA09147285 + +I=211 +KEY=BD671DD81F8FCD9D472564589AA13F5D8DF942EF8339F9D898D50F68805DA270 +CT=7AFE0D2F234A6CDEDD7103DA09147285 +PT=40627620B17313AF42EA7DD6CFD900F9 + +I=212 +KEY=5668F777C46BF78DC664E72186626BF5CD9B34CF324AEA77DA3F72BE4F84A289 +CT=40627620B17313AF42EA7DD6CFD900F9 +PT=0C62985837C8C6FB468BD6E3928F8497 + +I=213 +KEY=B82B5D4C3DEF62CFAE064CFDB5D904EFC1F9AC9705822C8C9CB4A45DDD0B261E +CT=0C62985837C8C6FB468BD6E3928F8497 +PT=A1FFF4635AAF2AD8AE6EA8C70858EF3B + +I=214 +KEY=6A179EF63528EFA2B12DBA23D1EC8D21600658F45F2D065432DA0C9AD553C925 +CT=A1FFF4635AAF2AD8AE6EA8C70858EF3B +PT=403F8E2D050E2976487BBEDD6466357E + +I=215 +KEY=6857720AC4DDCFFE8A96B455C973901A2039D6D95A232F227AA1B247B135FC5B +CT=403F8E2D050E2976487BBEDD6466357E +PT=2DD7EB8476988C850E8D95DC598FC61A + +I=216 +KEY=5B938E230BFE9056471E7C83A6ED03930DEE3D5D2CBBA3A7742C279BE8BA3A41 +CT=2DD7EB8476988C850E8D95DC598FC61A +PT=676B96F400AE18138B302FD3D70D490E + +I=217 +KEY=4CE7ECA340DEC23715C53343EB9162DA6A85ABA92C15BBB4FF1C08483FB7734F +CT=676B96F400AE18138B302FD3D70D490E +PT=620AAA14B94BF6B60A83129085BCF02B + +I=218 +KEY=1024ECE618D140CAE8B9DFC8EB1DE137088F01BD955E4D02F59F1AD8BA0B8364 +CT=620AAA14B94BF6B60A83129085BCF02B +PT=B701A38325DC282045C6F914394B9F70 + +I=219 +KEY=6B8C6DA855E1E72E4A6AC44601B24D60BF8EA23EB0826522B059E3CC83401C14 +CT=B701A38325DC282045C6F914394B9F70 +PT=808D0B334B775C59F8C34A3524CB4126 + +I=220 +KEY=C50A625A89465321DACCB9EB40DEF57D3F03A90DFBF5397B489AA9F9A78B5D32 +CT=808D0B334B775C59F8C34A3524CB4126 +PT=4E29C921CC295F6A3082C1BC02ACDA70 + +I=221 +KEY=973341A4E3DB315FA97C7EEDF493EA71712A602C37DC661178186845A5278742 +CT=4E29C921CC295F6A3082C1BC02ACDA70 +PT=77BC204E50EFCA2AEBDC16D3F3C3D739 + +I=222 +KEY=639EB8FB16B34B55550705FDCFF7C8CC069640626733AC3B93C47E9656E4507B +CT=77BC204E50EFCA2AEBDC16D3F3C3D739 +PT=A677A7B55AA03EB0587EE00123D047F3 + +I=223 +KEY=610A9602B725E4D87AB2904E91050D90A0E1E7D73D93928BCBBA9E9775341788 +CT=A677A7B55AA03EB0587EE00123D047F3 +PT=09AF5421548AC11466370484F8C556DE + +I=224 +KEY=314A6E0BD202458489059738917B6678A94EB3F66919539FAD8D9A138DF14156 +CT=09AF5421548AC11466370484F8C556DE +PT=B6CDD2336AB8735EE7A9946A1FE7EE0C + +I=225 +KEY=73658C0F88490F7C3B9F2B7B39551BBF1F8361C503A120C14A240E799216AF5A +CT=B6CDD2336AB8735EE7A9946A1FE7EE0C +PT=B5A2F3B47E4AC87BC06612587253930E + +I=226 +KEY=968794DEC3E866DE4F999C860E9851E9AA2192717DEBE8BA8A421C21E0453C54 +CT=B5A2F3B47E4AC87BC06612587253930E +PT=09C9C38BB3348147EB284FFA24D87244 + +I=227 +KEY=205605E66A4BE2CF61E13243E104FED9A3E851FACEDF69FD616A53DBC49D4E10 +CT=09C9C38BB3348147EB284FFA24D87244 +PT=9D1EDCA2674E5A30416DF7CC2938DC63 + +I=228 +KEY=9CA7508C83DB6E56EFF3489F2BD30C573EF68D58A99133CD2007A417EDA59273 +CT=9D1EDCA2674E5A30416DF7CC2938DC63 +PT=E8A2282B47DAB6A666A4607BBC857FC6 + +I=229 +KEY=0F98884E85FEB533CFC281C2F4437915D654A573EE4B856B46A3C46C5120EDB5 +CT=E8A2282B47DAB6A666A4607BBC857FC6 +PT=B6675D2263DC1C1E0F04A9A9BC666D2D + +I=230 +KEY=3F3ED6DC6E08DF2515D08273832429286033F8518D97997549A76DC5ED468098 +CT=B6675D2263DC1C1E0F04A9A9BC666D2D +PT=D6FF2642FD84C80674EAF8674242248D + +I=231 +KEY=67910C06B57CD52767674B70F59337D8B6CCDE13701351733D4D95A2AF04A415 +CT=D6FF2642FD84C80674EAF8674242248D +PT=47D4419A669253C39A0CC96C7CD612C0 + +I=232 +KEY=43EE254E414DB89044EE2F703B340F6AF1189F89168102B0A7415CCED3D2B6D5 +CT=47D4419A669253C39A0CC96C7CD612C0 +PT=B2B3FD7A1D4B0695B3499430F2E44CEA + +I=233 +KEY=89C9881E6D6CEFF00DDFC5618655FA4543AB62F30BCA04251408C8FE2136FA3F +CT=B2B3FD7A1D4B0695B3499430F2E44CEA +PT=4AAD0AE20AFF0675CF78992DFD2B685C + +I=234 +KEY=2C24846D047677F89EF73B917962D0FA0906681101350250DB7051D3DC1D9263 +CT=4AAD0AE20AFF0675CF78992DFD2B685C +PT=C90343412CFE70201CE22D9AD2222788 + +I=235 +KEY=770637F8F8F32915BF7630919D0726AEC0052B502DCB7270C7927C490E3FB5EB +CT=C90343412CFE70201CE22D9AD2222788 +PT=923FE89134FAF362802C5A2EBF399D2C + +I=236 +KEY=426891CF6B068FAC7FFB5A04874AEC78523AC3C11931811247BE2667B10628C7 +CT=923FE89134FAF362802C5A2EBF399D2C +PT=9C08F05026196BA3550A2496049B720B + +I=237 +KEY=B66BCCA5EFAF3F448BDD52DC48F2B904CE3233913F28EAB112B402F1B59D5ACC +CT=9C08F05026196BA3550A2496049B720B +PT=7B487FD67D0C2D987C3DEFD335C2EF17 + +I=238 +KEY=079CCBC13FCFB0D032293FDFEC563F86B57A4C474224C7296E89ED22805FB5DB +CT=7B487FD67D0C2D987C3DEFD335C2EF17 +PT=CEC12158856704CE8ABF0CA6C6F3006B + +I=239 +KEY=998AFEF458902CA632D60843A88D36637BBB6D1FC743C3E7E436E18446ACB5B0 +CT=CEC12158856704CE8ABF0CA6C6F3006B +PT=DA19C7C7283ADD9C5145ABBA53F1E7E1 + +I=240 +KEY=95EDAF196289EE6D24AA752DF489DEFCA1A2AAD8EF791E7BB5734A3E155D5251 +CT=DA19C7C7283ADD9C5145ABBA53F1E7E1 +PT=F043A57E686C1FE7DACB858F0C3E6857 + +I=241 +KEY=3050D2C04C0860414427BF5B19792D7651E10FA68715019C6FB8CFB119633A06 +CT=F043A57E686C1FE7DACB858F0C3E6857 +PT=2FB7B264BB4B3FAFA01A6BB93CC2958D + +I=242 +KEY=26186DD7BE83659550BA3B52D99975037E56BDC23C5E3E33CFA2A40825A1AF8B +CT=2FB7B264BB4B3FAFA01A6BB93CC2958D +PT=D46BBD3ABD958DA722F3591578C30F5E + +I=243 +KEY=DE1D625B9C840580FDDE57EDE82419D1AA3D00F881CBB394ED51FD1D5D62A0D5 +CT=D46BBD3ABD958DA722F3591578C30F5E +PT=3D69379AB60535902C38AB5E121DD035 + +I=244 +KEY=FF9396CB65FFB9D47EF4E0253FD98BBA9754376237CE8604C16956434F7F70E0 +CT=3D69379AB60535902C38AB5E121DD035 +PT=A5767F4E6C8482290BC7B76D23EEF145 + +I=245 +KEY=B98B5F1CA9752B1B07514B72C3D585F23222482C5B4A042DCAAEE12E6C9181A5 +CT=A5767F4E6C8482290BC7B76D23EEF145 +PT=9388736A82C99337C49BB4F32437B1DA + +I=246 +KEY=5F130919FB4ED29397E4781550B1D444A1AA3B46D983971A0E3555DD48A6307F +CT=9388736A82C99337C49BB4F32437B1DA +PT=915C6C5181E797DADC289F8FFF60CD19 + +I=247 +KEY=D3F202F140D38545C8A04EC2D0993E2B30F65717586400C0D21DCA52B7C6FD66 +CT=915C6C5181E797DADC289F8FFF60CD19 +PT=A61167CDBE95ABFAD9C1A58BDA90F0D4 + +I=248 +KEY=FBFA83B249C3B13C83E8FC111611391296E730DAE6F1AB3A0BDC6FD96D560DB2 +CT=A61167CDBE95ABFAD9C1A58BDA90F0D4 +PT=9AF2B4CF00B037976D0F5CAC4201885D + +I=249 +KEY=CC24CC54D0889912C7AD2473EBA8BBB30C158415E6419CAD66D333752F5785EF +CT=9AF2B4CF00B037976D0F5CAC4201885D +PT=A9B74046119B6699FD5EFD1E476BEE64 + +I=250 +KEY=F520F18D9FACA98E5F57226127FA9B6BA5A2C453F7DAFA349B8DCE6B683C6B8B +CT=A9B74046119B6699FD5EFD1E476BEE64 +PT=CD7EAA1EF3B91B69FD3E54FCC5A802E9 + +I=251 +KEY=9BFD59A9F78FB1BE6F13B701D7EB0F6268DC6E4D0463E15D66B39A97AD946962 +CT=CD7EAA1EF3B91B69FD3E54FCC5A802E9 +PT=FD7095C419E2722425E6D4CA1A393D8C + +I=252 +KEY=C1C39AC5158C8CDBE82CF37D00B7896995ACFB891D81937943554E5DB7AD54EE +CT=FD7095C419E2722425E6D4CA1A393D8C +PT=9963CE47EB0322135C5D20B923FC341A + +I=253 +KEY=C9E26AE18D08643029C92F11BD3E8AA40CCF35CEF682B16A1F086EE4945160F4 +CT=9963CE47EB0322135C5D20B923FC341A +PT=11589A1BDD037FABABBB9BF5AAC859A7 + +I=254 +KEY=2183FF3C1EB1DF48DB8FA5F87F279F891D97AFD52B81CEC1B4B3F5113E993953 +CT=11589A1BDD037FABABBB9BF5AAC859A7 +PT=B6CEE1CD709BE6E055041FC2E1A87539 + +I=255 +KEY=738690954B4B92CE2367567B3A960E8DAB594E185B1A2821E1B7EAD3DF314C6A +CT=B6CEE1CD709BE6E055041FC2E1A87539 +PT=D776658F01CCEC460FA7145C6C6CBD42 + +I=256 +KEY=71AB2DBD9923F08E516D8DF0CF57CC227C2F2B975AD6C467EE10FE8FB35DF128 +CT=D776658F01CCEC460FA7145C6C6CBD42 +PT=0C6D2578060A0A1024230D838AA45234 + +I=257 +KEY=1C0E18C83D74E46DDF65BFC3335CFF0D70420EEF5CDCCE77CA33F30C39F9A31C +CT=0C6D2578060A0A1024230D838AA45234 +PT=BFD55D67EF4883200FDAEEA5D44F0302 + +I=258 +KEY=7DA814BD80D8CBBEE778E030682E7F34CF975388B3944D57C5E91DA9EDB6A01E +CT=BFD55D67EF4883200FDAEEA5D44F0302 +PT=E821629542650FAFEF08D94AC889078A + +I=259 +KEY=10490CD6F16D915CE9891C69E10884D827B6311DF1F142F82AE1C4E3253FA794 +CT=E821629542650FAFEF08D94AC889078A +PT=F2F81CD9CBD3E932686B6195A97EE13A + +I=260 +KEY=F0114F7C7101931F6A4595A6C3D2F34AD54E2DC43A22ABCA428AA5768C4146AE +CT=F2F81CD9CBD3E932686B6195A97EE13A +PT=C90348C14450EE3D9BFA30377D4B2440 + +I=261 +KEY=C5802B19BA4921D3750A590F02658F621C4D65057E7245F7D9709541F10A62EE +CT=C90348C14450EE3D9BFA30377D4B2440 +PT=619E907C4E7FD3A723E34B8D3880D71B + +I=262 +KEY=236500CE70AC49E98907DC4EDAE41CCA7DD3F579300D9650FA93DECCC98AB5F5 +CT=619E907C4E7FD3A723E34B8D3880D71B +PT=932A17E8FDA853F6DB1C9271EC4FBF56 + +I=263 +KEY=7BB7D14473E7E2D70F3C8C90D4B1035CEEF9E291CDA5C5A6218F4CBD25C50AA3 +CT=932A17E8FDA853F6DB1C9271EC4FBF56 +PT=549CB80C490E592E18ACC04FAA933489 + +I=264 +KEY=415AD8391B32F6E61A861B4C8A4BBC6DBA655A9D84AB9C8839238CF28F563E2A +CT=549CB80C490E592E18ACC04FAA933489 +PT=BF6337BEDE116D5A60B06DA8B270159C + +I=265 +KEY=058F24C125EB3E94B54BB6F1F099501C05066D235ABAF1D25993E15A3D262BB6 +CT=BF6337BEDE116D5A60B06DA8B270159C +PT=CBD3D52496E6DF0DBD065BD924C5001F + +I=266 +KEY=B85B96EC639098C392FD33D11A49251ECED5B807CC5C2EDFE495BA8319E32BA9 +CT=CBD3D52496E6DF0DBD065BD924C5001F +PT=AF8879C67DF265E118096478FBA003AD + +I=267 +KEY=526BF9DCAF4A4DFD05FAD0EA3B58131D615DC1C1B1AE4B3EFC9CDEFBE2432804 +CT=AF8879C67DF265E118096478FBA003AD +PT=C627176029E2D22A51F5630B129A1095 + +I=268 +KEY=553316781F120EE83A2D083D97D19F99A77AD6A1984C9914AD69BDF0F0D93891 +CT=C627176029E2D22A51F5630B129A1095 +PT=F46AC5870C65636D6C200312F2A15BE6 + +I=269 +KEY=E9A37578C1402447D6CC1161F126D5C7531013269429FA79C149BEE202786377 +CT=F46AC5870C65636D6C200312F2A15BE6 +PT=4FBBFF3856FC0DEC7EE18585FFA4AC16 + +I=270 +KEY=78521B42D0FBE8EA8BB6D44D66AE476D1CABEC1EC2D5F795BFA83B67FDDCCF61 +CT=4FBBFF3856FC0DEC7EE18585FFA4AC16 +PT=8711DAE7DD9B3F6D9FAD03669C1C8F5E + +I=271 +KEY=851C9A078620280FBCDDFB4FD3745C749BBA36F91F4EC8F82005380161C0403F +CT=8711DAE7DD9B3F6D9FAD03669C1C8F5E +PT=050E884136E09368DEFBC43F6B3182CC + +I=272 +KEY=50CCAA51D781B7090285D907E68B1F7A9EB4BEB829AE5B90FEFEFC3E0AF1C2F3 +CT=050E884136E09368DEFBC43F6B3182CC +PT=CEC37197CEE3E0D797F441CC0541B851 + +I=273 +KEY=DAB5ECB43982EAE8412102E2B7BC7CEA5077CF2FE74DBB47690ABDF20FB07AA2 +CT=CEC37197CEE3E0D797F441CC0541B851 +PT=197ECC091E5620DCA63BA2E6CFBC9F43 + +I=274 +KEY=57974D1C4BBF761C9E09B8DAD3E510DF49090326F91B9B9BCF311F14C00CE5E1 +CT=197ECC091E5620DCA63BA2E6CFBC9F43 +PT=F2E836DEE9668E81D74A3C0F03CF3C10 + +I=275 +KEY=E37677110C5A9A59EC06E0968BF5D14EBBE135F8107D151A187B231BC3C3D9F1 +CT=F2E836DEE9668E81D74A3C0F03CF3C10 +PT=DD581BB9F4A7BEC66CAC7916871F55C8 + +I=276 +KEY=2CD760C245E62EA5B477BDA094B3AD5166B92E41E4DAABDC74D75A0D44DC8C39 +CT=DD581BB9F4A7BEC66CAC7916871F55C8 +PT=7B05D43A3BE733E0DE6E2CE494141B46 + +I=277 +KEY=DE35BF6BC48E8B8E6A30DB886C9D75DD1DBCFA7BDF3D983CAAB976E9D0C8977F +CT=7B05D43A3BE733E0DE6E2CE494141B46 +PT=1D561DCAA42E92568DD6ACD583FF7BCE + +I=278 +KEY=8AD7FCADA5D092DD5D221532EED3FD1000EAE7B17B130A6A276FDA3C5337ECB1 +CT=1D561DCAA42E92568DD6ACD583FF7BCE +PT=1E9AB09A76FD91CC33B85390BDE631F8 + +I=279 +KEY=534EEF6B1450693335980E00CD3CDE361E70572B0DEE9BA614D789ACEED1DD49 +CT=1E9AB09A76FD91CC33B85390BDE631F8 +PT=CBD0E3A07952EAC118A81B76D09276FD + +I=280 +KEY=8A39C2221622785E4DA9B14DAAE6ADF3D5A0B48B74BC71670C7F92DA3E43ABB4 +CT=CBD0E3A07952EAC118A81B76D09276FD +PT=AC20057B857E6C34F7E68A5765573538 + +I=281 +KEY=50887AD2D325CBC04B5FD69518318BAD7980B1F0F1C21D53FB99188D5B149E8C +CT=AC20057B857E6C34F7E68A5765573538 +PT=DDFFD26BA5B33AEA36A0A6D75EAA047C + +I=282 +KEY=9613965C1776C5BAEA3CEE6154AABC9FA47F639B547127B9CD39BE5A05BE9AF0 +CT=DDFFD26BA5B33AEA36A0A6D75EAA047C +PT=F0883B6DD3CA0515CB9F1ABA646CCB69 + +I=283 +KEY=E7F6DB8A94597956CEE07447F9BB5CA454F758F687BB22AC06A6A4E061D25199 +CT=F0883B6DD3CA0515CB9F1ABA646CCB69 +PT=F4E27CA9E27B3E81B981298738C01FDA + +I=284 +KEY=0CB665943D6E6E32886A94C070366FB2A015245F65C01C2DBF278D6759124E43 +CT=F4E27CA9E27B3E81B981298738C01FDA +PT=B03B2EB7A1E13E1A17C51FF5684E2A72 + +I=285 +KEY=1EA698290E4B1D41B0CC4F3B9A9398FF102E0AE8C4212237A8E29292315C6431 +CT=B03B2EB7A1E13E1A17C51FF5684E2A72 +PT=BE133CCCE406C1C0BC1707115B5B0C84 + +I=286 +KEY=BA38F49FA3D4A74ED41F8DA958A953C7AE3D36242027E3F714F595836A0768B5 +CT=BE133CCCE406C1C0BC1707115B5B0C84 +PT=A15B1C9BCF319AEF262E366C142A0DCF + +I=287 +KEY=935F2CEECBBCF3465DB9B0DB927AF4310F662ABFEF16791832DBA3EF7E2D657A +CT=A15B1C9BCF319AEF262E366C142A0DCF +PT=7A8DA23874D28EB75261D87D57451EAE + +I=288 +KEY=B8E67B884E3E229EBB516065499F790275EB88879BC4F7AF60BA7B9229687BD4 +CT=7A8DA23874D28EB75261D87D57451EAE +PT=9331C989A7E291FD94BA4C945A79126E + +I=289 +KEY=CFB51BE6CDA499D66E7B36CAAC220FB7E6DA410E3C266652F4003706731169BA +CT=9331C989A7E291FD94BA4C945A79126E +PT=70A2F921A8BB0548D91A114478308448 + +I=290 +KEY=19821B21FED0C1659AF4E16F49F63B699678B82F949D631A2D1A26420B21EDF2 +CT=70A2F921A8BB0548D91A114478308448 +PT=8ED8FC98045BA0EF9C15E9565EECE5BB + +I=291 +KEY=27DA5E31E794D670BDB701F361B8977018A044B790C6C3F5B10FCF1455CD0849 +CT=8ED8FC98045BA0EF9C15E9565EECE5BB +PT=F6621989AFC0427E3E84039B6C6C2E75 + +I=292 +KEY=64E8F7C4292DF7D0B01BED3FAE08DA4FEEC25D3E3F06818B8F8BCC8F39A1263C +CT=F6621989AFC0427E3E84039B6C6C2E75 +PT=68F4804D1E8D383FAF4E76F80FB8F92B + +I=293 +KEY=EE626AFFE4997C11CAE2714FF96D84B18636DD73218BB9B420C5BA773619DF17 +CT=68F4804D1E8D383FAF4E76F80FB8F92B +PT=2D61F123E2479D56AE5C327A57F6A28B + +I=294 +KEY=EA24B2DB953084C818B0E6F34BA1584DAB572C50C3CC24E28E99880D61EF7D9C +CT=2D61F123E2479D56AE5C327A57F6A28B +PT=C6CD16E7A122D105EE398E6C7F15B4EF + +I=295 +KEY=F209D1ADE0869F674F6FEDCD3DB7D2EB6D9A3AB762EEF5E760A006611EFAC973 +CT=C6CD16E7A122D105EE398E6C7F15B4EF +PT=EDD6BBA5787DA2BF6A1ADF297DB98281 + +I=296 +KEY=302BEB9AA2ACB3594D7E50859C187294804C81121A9357580ABAD94863434BF2 +CT=EDD6BBA5787DA2BF6A1ADF297DB98281 +PT=4A51E54F4F81469A06F6001F2F32F4AC + +I=297 +KEY=3270FC87B4DC04FDD3F20C01407BE123CA1D645D551211C20C4CD9574C71BF5E +CT=4A51E54F4F81469A06F6001F2F32F4AC +PT=F7A2303EA59907BCC32AA4FC5A6DE448 + +I=298 +KEY=C85326465BF46A442BC1E544F9041C4A3DBF5463F08B167ECF667DAB161C5B16 +CT=F7A2303EA59907BCC32AA4FC5A6DE448 +PT=2274E43F9F8A7081DF74D5225EC28AD8 + +I=299 +KEY=A54E889A4D9FFBF993C53A9DD3B951391FCBB05C6F0166FF1012A88948DED1CE +CT=2274E43F9F8A7081DF74D5225EC28AD8 +PT=0C8358EC431313223B59126BDBB36571 + +I=300 +KEY=FA14699C20CFFE7DB68786E6117F95851348E8B02C1275DD2B4BBAE2936DB4BF +CT=0C8358EC431313223B59126BDBB36571 +PT=03237A81EEA2EAFBB5AC0B3E635CC1AC + +I=301 +KEY=B3744022A5397A735A4271261A2C96DF106B9231C2B09F269EE7B1DCF0317513 +CT=03237A81EEA2EAFBB5AC0B3E635CC1AC +PT=409EBF7DF31FD9557118B1B5CAB5EBE3 + +I=302 +KEY=8C7A22A934DCBC5E084E472DBAE4848350F52D4C31AF4673EFFF00693A849EF0 +CT=409EBF7DF31FD9557118B1B5CAB5EBE3 +PT=6CF5C9CF4A62C668B6481F7A12EE43DB + +I=303 +KEY=DB0497ED308C95BC9703265174B654D23C00E4837BCD801B59B71F13286ADD2B +CT=6CF5C9CF4A62C668B6481F7A12EE43DB +PT=D8A84E93CFF3EB9DC891333BDA5F3560 + +I=304 +KEY=7A88D30D4CC9AB8EFA76139B68F0028AE4A8AA10B43E6B8691262C28F235E84B +CT=D8A84E93CFF3EB9DC891333BDA5F3560 +PT=009E0C2454E321326336CC56D0660F91 + +I=305 +KEY=55A78B8839B395B552630641648DFCE5E436A634E0DD4AB4F210E07E2253E7DA +CT=009E0C2454E321326336CC56D0660F91 +PT=EBC89334F29560D9B9AEAE2F1D9DC65B + +I=306 +KEY=B41A907C82EDE32C6C1FD0DFED0A232D0FFE350012482A6D4BBE4E513FCE2181 +CT=EBC89334F29560D9B9AEAE2F1D9DC65B +PT=4DA63E94EBB4DA255800C9B25068E47E + +I=307 +KEY=3E428E8A77067008EFDE7BD6174B05B742580B94F9FCF04813BE87E36FA6C5FF +CT=4DA63E94EBB4DA255800C9B25068E47E +PT=6833E2CEFA8CF4B5B4607FA49D7B658D + +I=308 +KEY=39D17AE8C7232386F8339427E4A79AAC2A6BE95A037004FDA7DEF847F2DDA072 +CT=6833E2CEFA8CF4B5B4607FA49D7B658D +PT=41D882B653BEFEEEB9AE354F5ABCC058 + +I=309 +KEY=E8D52C97FA4149312A45D3EFE0A326086BB36BEC50CEFA131E70CD08A861602A +CT=41D882B653BEFEEEB9AE354F5ABCC058 +PT=D54A329BCF56B703BE0F02EE3AACB933 + +I=310 +KEY=D36FAED6CF436A491111890449BC3C66BEF959779F984D10A07FCFE692CDD919 +CT=D54A329BCF56B703BE0F02EE3AACB933 +PT=5FAAEB95E0F9D0C3C43BF725DADC9595 + +I=311 +KEY=9D7BCBB15816A0A941BBB787D2EEA155E153B2E27F619DD3644438C348114C8C +CT=5FAAEB95E0F9D0C3C43BF725DADC9595 +PT=BC699D5E82FD43B45A7B925E8C1A2F3C + +I=312 +KEY=F2EB78917ECAC2E77C19B892E846AE715D3A2FBCFD9CDE673E3FAA9DC40B63B0 +CT=BC699D5E82FD43B45A7B925E8C1A2F3C +PT=773D115B40F0E9EF780B2D10846FA684 + +I=313 +KEY=B10B9F0CECA554749EC178F3C63547DD2A073EE7BD6C37884634878D4064C534 +CT=773D115B40F0E9EF780B2D10846FA684 +PT=50095809CC96520EB8E3A66F499EE147 + +I=314 +KEY=E86E52AEB04DE0D3DC85A91E9B10D2677A0E66EE71FA6586FED721E209FA2473 +CT=50095809CC96520EB8E3A66F499EE147 +PT=6994CF8BA4C731CA33DAFE33D2A0BF94 + +I=315 +KEY=44C3C8A2F0F931926AC73F3E5351B114139AA965D53D544CCD0DDFD1DB5A9BE7 +CT=6994CF8BA4C731CA33DAFE33D2A0BF94 +PT=981902A8FD71DF8B67D52E6FC2813B90 + +I=316 +KEY=2D309D3D2603EC7E7B4EA626E9BDECFE8B83ABCD284C8BC7AAD8F1BE19DBA077 +CT=981902A8FD71DF8B67D52E6FC2813B90 +PT=35FA9A93AE142F562E62771991752B78 + +I=317 +KEY=E80939BCB4DB83768EBAD3CF2DD3F270BE79315E8658A49184BA86A788AE8B0F +CT=35FA9A93AE142F562E62771991752B78 +PT=A3651DBF8585004F0729AF4CA615C674 + +I=318 +KEY=BF1A4C57D4434FA59A2E45DB589AA16F1D1C2CE103DDA4DE839329EB2EBB4D7B +CT=A3651DBF8585004F0729AF4CA615C674 +PT=AF31F082CACEB768627B93A4D3E5349A + +I=319 +KEY=6EB47730BACAAB2207A3D12B0652B0CDB22DDC63C91313B6E1E8BA4FFD5E79E1 +CT=AF31F082CACEB768627B93A4D3E5349A +PT=57B75D2B640F45DB2D4A1F71F08545A5 + +I=320 +KEY=3EB0F3D31E648E260FE9F6FA8812ADD1E59A8148AD1C566DCCA2A53E0DDB3C44 +CT=57B75D2B640F45DB2D4A1F71F08545A5 +PT=A812DA38D7B82DF310366FA62FFD11E6 + +I=321 +KEY=0409A87F024E710C27E456CA170B60184D885B707AA47B9EDC94CA9822262DA2 +CT=A812DA38D7B82DF310366FA62FFD11E6 +PT=447F235914368F2BECD5FF98D1A34205 + +I=322 +KEY=7DE3A1E7234BF755908324E13DF413EB09F778296E92F4B530413500F3856FA7 +CT=447F235914368F2BECD5FF98D1A34205 +PT=5205860E4562B5CD6748EF89BF2791E9 + +I=323 +KEY=12EE9519335A2D827649D4EB047EB5255BF2FE272BF041785709DA894CA2FE4E +CT=5205860E4562B5CD6748EF89BF2791E9 +PT=30C0229AFDFF59E24426ACAD8D4AEFDB + +I=324 +KEY=78FF32A055D51E0A9D6E77D838AE72AD6B32DCBDD60F189A132F7624C1E81195 +CT=30C0229AFDFF59E24426ACAD8D4AEFDB +PT=FF467C6E0F82F5D2F9487DDBDB43EFB3 + +I=325 +KEY=6E49FA4CDEFC70619F739B488DD434969474A0D3D98DED48EA670BFF1AABFE26 +CT=FF467C6E0F82F5D2F9487DDBDB43EFB3 +PT=7E375B3D13871B09CA4D3357AC5EBB0E + +I=326 +KEY=90791666C996FF15EED1E20BAFB6B4B3EA43FBEECA0AF641202A38A8B6F54528 +CT=7E375B3D13871B09CA4D3357AC5EBB0E +PT=E64A319F6FBD96BD799760C4077F9713 + +I=327 +KEY=7F0D0CAB938585CF65726A6CB01DE8B00C09CA71A5B760FC59BD586CB18AD23B +CT=E64A319F6FBD96BD799760C4077F9713 +PT=1487C8488C675BD46FAF2EEC0BC7AE7E + +I=328 +KEY=7B429E6D59D4D65E16ED325F49E93D9C188E023929D03B2836127680BA4D7C45 +CT=1487C8488C675BD46FAF2EEC0BC7AE7E +PT=1F103E64A4F5239C9157E70487C50941 + +I=329 +KEY=AF20B02C3C5BD4E33E34359B86BBF2CF079E3C5D8D2518B4A74591843D887504 +CT=1F103E64A4F5239C9157E70487C50941 +PT=24C8481DD1A2245735597A18A2433E41 + +I=330 +KEY=E4F3CE6AFF9926837BAAB04C311F72A7235674405C873CE3921CEB9C9FCB4B45 +CT=24C8481DD1A2245735597A18A2433E41 +PT=3D9E715A686DE9AF8EE37AF54F82AA8A + +I=331 +KEY=A9BACBEC55AA453A83FF82CFDDB7F2F91EC8051A34EAD54C1CFF9169D049E1CF +CT=3D9E715A686DE9AF8EE37AF54F82AA8A +PT=B330735D9AB5B96501CDAF61A8EAD19F + +I=332 +KEY=5826BE9127DB557D401AF4DE6343F8AFADF87647AE5F6C291D323E0878A33050 +CT=B330735D9AB5B96501CDAF61A8EAD19F +PT=61AE40475EA11DBCC364F5377673CE37 + +I=333 +KEY=A8F0146E46A5391D0663380DF9F1FD6FCC563600F0FE7195DE56CB3F0ED0FE67 +CT=61AE40475EA11DBCC364F5377673CE37 +PT=525C1ED538B23D7CFA4A43114CF35BD4 + +I=334 +KEY=20F90A51E7A0BB9B88AE1DD28C8B484A9E0A28D5C84C4CE9241C882E4223A5B3 +CT=525C1ED538B23D7CFA4A43114CF35BD4 +PT=C2957E002E35236D455F53006495E4B7 + +I=335 +KEY=A71CC695B7AEB0D5148FA622536669385C9F56D5E6796F846143DB2E26B64104 +CT=C2957E002E35236D455F53006495E4B7 +PT=76F9C97A4B414E5DE532082BB12F5362 + +I=336 +KEY=617CF5726F26BD9A3B52FC0D902A97AD2A669FAFAD3821D98471D30597991266 +CT=76F9C97A4B414E5DE532082BB12F5362 +PT=F4D9E814D4C61B2FB1D7CDCCBAF14AA1 + +I=337 +KEY=D4DBBCC269A61933E4D63C3BDA5F522EDEBF77BB79FE3AF635A61EC92D6858C7 +CT=F4D9E814D4C61B2FB1D7CDCCBAF14AA1 +PT=6B51AF38B42F226D62474A97BD001FFF + +I=338 +KEY=512FAF06A5885D032A885EC030AF3C18B5EED883CDD1189B57E1545E90684738 +CT=6B51AF38B42F226D62474A97BD001FFF +PT=868C58D6B805CF8F9EB04A8BA123371A + +I=339 +KEY=BDD2CB78E9B554FC7FEEEC05D02309F23362805575D4D714C9511ED5314B7022 +CT=868C58D6B805CF8F9EB04A8BA123371A +PT=1752558A1F90975140CA41F68BE5333F + +I=340 +KEY=15CC46826BFD5B45ABAE9B0B2756D39C2430D5DF6A444045899B5F23BAAE431D +CT=1752558A1F90975140CA41F68BE5333F +PT=68801EAB4042E7390E64AA53C38C1D15 + +I=341 +KEY=DF5FB425C5B25E15EA717736D8ABE6644CB0CB742A06A77C87FFF57079225E08 +CT=68801EAB4042E7390E64AA53C38C1D15 +PT=02FE87211909D8954EC90EF53100F26D + +I=342 +KEY=CD73FCED5EBA6038DD8B8A000111BEF94E4E4C55330F7FE9C936FB854822AC65 +CT=02FE87211909D8954EC90EF53100F26D +PT=3A51FAFD22A2CC95B532023A37BBF0FE + +I=343 +KEY=EF890ED47D9F1581CC98C88F3BF7F88D741FB6A811ADB37C7C04F9BF7F995C9B +CT=3A51FAFD22A2CC95B532023A37BBF0FE +PT=D233A6BBC315BA5F4630AE7F99F77116 + +I=344 +KEY=AA9CA1A7DFA24E1936E49D34054F7749A62C1013D2B809233A3457C0E66E2D8D +CT=D233A6BBC315BA5F4630AE7F99F77116 +PT=E6B9619D7B0E1DF6CFE79FD51533406B + +I=345 +KEY=ADC4161B346687F98D4CB5B661662A8A4095718EA9B614D5F5D3C815F35D6DE6 +CT=E6B9619D7B0E1DF6CFE79FD51533406B +PT=A746D31BCB29F7512E3F6E5EFD14FDAD + +I=346 +KEY=9C1CA3776C9ED13D220453C8AEFA0ECDE7D3A295629FE384DBECA64B0E49904B +CT=A746D31BCB29F7512E3F6E5EFD14FDAD +PT=B2489A51878848EC37E6782FB2110122 + +I=347 +KEY=B64A5B45ABFDEC3EF8164FCEAE89919E559B38C4E517AB68EC0ADE64BC589169 +CT=B2489A51878848EC37E6782FB2110122 +PT=EF77F9367A063FDB874C9FC96983EAD1 + +I=348 +KEY=AEFFDEE2501961FEEB985134E2B651EDBAECC1F29F1194B36B4641ADD5DB7BB8 +CT=EF77F9367A063FDB874C9FC96983EAD1 +PT=4ECFF4DA51BB2BE1EF8E85C4BBE51C69 + +I=349 +KEY=6B28BA96CEB25B3862F413A2CBED4889F4233528CEAABF5284C8C4696E3E67D1 +CT=4ECFF4DA51BB2BE1EF8E85C4BBE51C69 +PT=0CAEAF484505A1AF13BB0ADCC665F91C + +I=350 +KEY=2062889724A47DD541F1F0A3FC8C5952F88D9A608BAF1EFD9773CEB5A85B9ECD +CT=0CAEAF484505A1AF13BB0ADCC665F91C +PT=6C75CA469CACCCE29CAE88202E02727C + +I=351 +KEY=C2115A8A6EE164B944A8C8128EBAB8E694F850261703D21F0BDD46958659ECB1 +CT=6C75CA469CACCCE29CAE88202E02727C +PT=567060CEFF3AEDDE8AB5823450E35967 + +I=352 +KEY=C3D2704E15936C6916073E234D0012CCC28830E8E8393FC18168C4A1D6BAB5D6 +CT=567060CEFF3AEDDE8AB5823450E35967 +PT=E04F927E409060080EC530D5C344CA24 + +I=353 +KEY=49173A9FB3283181B71264E3FB5591FA22C7A296A8A95FC98FADF47415FE7FF2 +CT=E04F927E409060080EC530D5C344CA24 +PT=4D473408396C17D4BA3DBB63B46E7727 + +I=354 +KEY=8BF3DDDC9217496E29F46E61233D62B66F80969E91C5481D35904F17A19008D5 +CT=4D473408396C17D4BA3DBB63B46E7727 +PT=BB6779933AC9E435C637CDA146A04284 + +I=355 +KEY=6ACA3C31248BFBB5BB9FD54C4B31BC21D4E7EF0DAB0CAC28F3A782B6E7304A51 +CT=BB6779933AC9E435C637CDA146A04284 +PT=5C2129A55114540ED68591C60E45D6CF + +I=356 +KEY=1A270DAD402DC752332671216A6C3BFF88C6C6A8FA18F82625221370E9759C9E +CT=5C2129A55114540ED68591C60E45D6CF +PT=57790B87F69BF1C007E563A82987EEAE + +I=357 +KEY=6E39E75268AC2C51ABE11CE3CE16CAF3DFBFCD2F0C8309E622C770D8C0F27230 +CT=57790B87F69BF1C007E563A82987EEAE +PT=58790B192C8B90B76F34990E28A6689A + +I=358 +KEY=2367A67114D722A79F9434B5A418BEEB87C6C636200899514DF3E9D6E8541AAA +CT=58790B192C8B90B76F34990E28A6689A +PT=599CA8B58EFE301A87CE72540CCB4067 + +I=359 +KEY=A4CE195518F7E36D7E0D5C9666802411DE5A6E83AEF6A94BCA3D9B82E49F5ACD +CT=599CA8B58EFE301A87CE72540CCB4067 +PT=4483131C7E03089F898166A5B3E85E3A + +I=360 +KEY=73C5204211D3648DAAF5FE071186C0E99AD97D9FD0F5A1D443BCFD27577704F7 +CT=4483131C7E03089F898166A5B3E85E3A +PT=DBF64C5A0897B343BAF7047A6C564D02 + +I=361 +KEY=1A3831AFF223BB2FE79C8EF8845E553C412F31C5D8621297F94BF95D3B2149F5 +CT=DBF64C5A0897B343BAF7047A6C564D02 +PT=B24420DA45E3620B619978CB09F1860C + +I=362 +KEY=31EF243EF87C32148751F8F299151042F36B111F9D81709C98D2819632D0CFF9 +CT=B24420DA45E3620B619978CB09F1860C +PT=12B466EF6AE6F28AF78AC184DB8B3C83 + +I=363 +KEY=9E935E6F5D76BEE2E639F2880C8352EEE1DF77F0F76782166F584012E95BF37A +CT=12B466EF6AE6F28AF78AC184DB8B3C83 +PT=518E89A35CF55D591DE8BB924D8F96E7 + +I=364 +KEY=C6398957838B02B5948A95DCBFBF2813B051FE53AB92DF4F72B0FB80A4D4659D +CT=518E89A35CF55D591DE8BB924D8F96E7 +PT=1FDF7FE52BD46EF54F1F7A6242B04BD8 + +I=365 +KEY=5764E84D9000518C185717581E0D70E5AF8E81B68046B1BA3DAF81E2E6642E45 +CT=1FDF7FE52BD46EF54F1F7A6242B04BD8 +PT=2C68E67C37B50056E80DC09B9ED84AA8 + +I=366 +KEY=5F8CB51BF30B954B4AC09620B0A20FCA83E667CAB7F3B1ECD5A2417978BC64ED +CT=2C68E67C37B50056E80DC09B9ED84AA8 +PT=14CC2D821B03BE21355A779B9066BE41 + +I=367 +KEY=50B32E6D62EE3B8CE2DD5797BA70D8D2972A4A48ACF00FCDE0F836E2E8DADAAC +CT=14CC2D821B03BE21355A779B9066BE41 +PT=BB09D339888C27294E73326E64AC3B21 + +I=368 +KEY=E1B2199CAF1C3FA78E973ACF5C3AC8702C239971247C28E4AE8B048C8C76E18D +CT=BB09D339888C27294E73326E64AC3B21 +PT=BCFBD8255802CC8233AEA86E49089328 + +I=369 +KEY=3403D2498A4562E73734D065E9B44AD890D841547C7EE4669D25ACE2C57E72A5 +CT=BCFBD8255802CC8233AEA86E49089328 +PT=5A919AC72F12DB1FAB8E4876FBA8842B + +I=370 +KEY=B979FA15F93E5ACA1F6E452C9053751BCA49DB93536C3F7936ABE4943ED6F68E +CT=5A919AC72F12DB1FAB8E4876FBA8842B +PT=BDB03BD29FD3828AF1AE8C729F37F88A + +I=371 +KEY=A8CDF9FE3C0227A9107C700C404AE39777F9E041CCBFBDF3C70568E6A1E10E04 +CT=BDB03BD29FD3828AF1AE8C729F37F88A +PT=0AAC43CE316476F3A532D44B4DFBF4B8 + +I=372 +KEY=B4D497FBD5DE2CA68FF60C701E208A257D55A38FFDDBCB006237BCADEC1AFABC +CT=0AAC43CE316476F3A532D44B4DFBF4B8 +PT=853A5EE7CB3C4BB3F0120BB2CFFB4436 + +I=373 +KEY=A019DCC09A4CAAA3772BF4C54C8828E9F86FFD6836E780B39225B71F23E1BE8A +CT=853A5EE7CB3C4BB3F0120BB2CFFB4436 +PT=B525599C918446AF4EA9F6965F3971EA + +I=374 +KEY=238BF8B851B0864F9BEC8E242B7795D14D4AA4F4A763C61CDC8C41897CD8CF60 +CT=B525599C918446AF4EA9F6965F3971EA +PT=A8377EC293D41F74A0A2DB66BA7D3D2F + +I=375 +KEY=AF9E313988F294AE6A8155BC76F2514BE57DDA3634B7D9687C2E9AEFC6A5F24F +CT=A8377EC293D41F74A0A2DB66BA7D3D2F +PT=301BD4D318101A02166EBC23DED9C12D + +I=376 +KEY=3B6186F7ACE8E9B022DDE0ECF5D808D3D5660EE52CA7C36A6A4026CC187C3362 +CT=301BD4D318101A02166EBC23DED9C12D +PT=05BD0686BE53B94FB1B42AE407BE081C + +I=377 +KEY=EADED20A0F405D9E3AAE404FB074162ED0DB086392F47A25DBF40C281FC23B7E +CT=05BD0686BE53B94FB1B42AE407BE081C +PT=7A3AF681F2043806EDB761F65D9A6C3A + +I=378 +KEY=AA6F474F5F5FF513FC992E4232061B75AAE1FEE260F0422336436DDE42585744 +CT=7A3AF681F2043806EDB761F65D9A6C3A +PT=3C297DE35CCF4E6E0A800B9A3EE37C95 + +I=379 +KEY=68BFE30863F135A09B81BE2800CBBC3796C883013C3F0C4D3CC366447CBB2BD1 +CT=3C297DE35CCF4E6E0A800B9A3EE37C95 +PT=5F8AAC15C74CC7EA87A1AC185103A9D7 + +I=380 +KEY=9093DEBE66D714180BEB8FE51C4807ADC9422F14FB73CBA7BB62CA5C2DB88206 +CT=5F8AAC15C74CC7EA87A1AC185103A9D7 +PT=083AF3AF30961FD5A077F5564D55E9E9 + +I=381 +KEY=A1E1049159A94DF638092C90F7707CD7C178DCBBCBE5D4721B153F0A60ED6BEF +CT=083AF3AF30961FD5A077F5564D55E9E9 +PT=89BEFF6AB40B18ECD9413446E848253A + +I=382 +KEY=7C506732A8863DB1BF61EFC710F22D2348C623D17FEECC9EC2540B4C88A54ED5 +CT=89BEFF6AB40B18ECD9413446E848253A +PT=095B2C04636C9C5BF9735BCA21211EAA + +I=383 +KEY=7283413612863BA1E1B5AE93DF1318F5419D0FD51C8250C53B275086A984507F +CT=095B2C04636C9C5BF9735BCA21211EAA +PT=E95DB3DB1E3A478C8A31212B28E0E7BC + +I=384 +KEY=BE861CED86D725162D938727D7AEFC1BA8C0BC0E02B81749B11671AD8164B7C3 +CT=E95DB3DB1E3A478C8A31212B28E0E7BC +PT=9927F1D7EF0631500E1DF058932BF320 + +I=385 +KEY=45AA89CBCE192CEEC22BF5F33DDE0E8D31E74DD9EDBE2619BF0B81F5124F44E3 +CT=9927F1D7EF0631500E1DF058932BF320 +PT=4B1147179F2AF27E5C9DBB7F01CC56A8 + +I=386 +KEY=B08A08DABC52884E9EBB310236815BFE7AF60ACE7294D467E3963A8A1383124B +CT=4B1147179F2AF27E5C9DBB7F01CC56A8 +PT=E9752A7D47734DACAC6E74A1A3EC4956 + +I=387 +KEY=34B4424CE75A4A1BCE9E6C825F5F0DC1938320B335E799CB4FF84E2BB06F5B1D +CT=E9752A7D47734DACAC6E74A1A3EC4956 +PT=AB2D652BCEE42804C5155980DA02CECC + +I=388 +KEY=F9954BB1A793565A79AA2B9DF408A34A38AE4598FB03B1CF8AED17AB6A6D95D1 +CT=AB2D652BCEE42804C5155980DA02CECC +PT=3C6651362E89F6C6B28C04CA22F110EC + +I=389 +KEY=9548931715FB259E318020E30D68165604C814AED58A470938611361489C853D +CT=3C6651362E89F6C6B28C04CA22F110EC +PT=15598364698838475AB96F95CFCF3342 + +I=390 +KEY=1CDB0706417BBE66B559237109353221119197CABC027F4E62D87CF48753B67F +CT=15598364698838475AB96F95CFCF3342 +PT=D8B3BB941893206E1CA6654B81F403E4 + +I=391 +KEY=8C4AD897B595252B0987673F45EE73F2C9222C5EA4915F207E7E19BF06A7B59B +CT=D8B3BB941893206E1CA6654B81F403E4 +PT=ECE471CC2FF45C26C7143C41702F90D2 + +I=392 +KEY=A6D3DF3279B7405256C0D22DA240524125C65D928B650306B96A25FE76882549 +CT=ECE471CC2FF45C26C7143C41702F90D2 +PT=AB387AE5A5FC892C311D97C22467940D + +I=393 +KEY=36F250F7C3906C7E0020055422CDB8B28EFE27772E998A2A8877B23C52EFB144 +CT=AB387AE5A5FC892C311D97C22467940D +PT=FF48C2C77D5F52DF27C4060DF7F895D7 + +I=394 +KEY=4FF045275860B943EDE02C802F34B71B71B6E5B053C6D8F5AFB3B431A5172493 +CT=FF48C2C77D5F52DF27C4060DF7F895D7 +PT=221BC444E2A6A7F8DE9DA16AB01EB2AC + +I=395 +KEY=E15B4E0E242FBABF1D47E9DBE6D0660253AD21F4B1607F0D712E155B1509963F +CT=221BC444E2A6A7F8DE9DA16AB01EB2AC +PT=DE252D19973ABD9F182049D39455784B + +I=396 +KEY=401023A611A3133C895A3684AB3E7C9D8D880CED265AC292690E5C88815CEE74 +CT=DE252D19973ABD9F182049D39455784B +PT=843163BD101982EE948039915C8F60D8 + +I=397 +KEY=B9DDF52C271F143E523532E45E6F368D09B96F503643407CFD8E6519DDD38EAC +CT=843163BD101982EE948039915C8F60D8 +PT=6FD9D36B751854C3417F29E8F3B654D9 + +I=398 +KEY=AC7F45F8630CE02525F9F4941B4E13206660BC3B435B14BFBCF14CF12E65DA75 +CT=6FD9D36B751854C3417F29E8F3B654D9 +PT=E1268BA8A1473DEDE6CA64DDF2C8B805 + +I=399 +KEY=DE11FF0A429E1CD3DE016DAC294F771187463793E21C29525A3B282CDCAD6270 +CT=E1268BA8A1473DEDE6CA64DDF2C8B805 +PT=4DE0C6DF7CB1697284604D60271BC59A + +=========== \ No newline at end of file diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_e_m.txt b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_e_m.txt new file mode 100644 index 00000000..40a95e7c --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_e_m.txt @@ -0,0 +1,6024 @@ + +========================= + +FILENAME: "ecb_e_m.txt" + +Electronic Codebook (ECB) Mode - ENCRYPTION +Monte Carlo Test + +Algorithm Name: Rijndael +Principal Submitter: Joan Daemen + +========================= + +KEYSIZE=128 + +I=0 +KEY=00000000000000000000000000000000 +PT=00000000000000000000000000000000 +CT=C34C052CC0DA8D73451AFE5F03BE297F + +I=1 +KEY=C34C052CC0DA8D73451AFE5F03BE297F +PT=C34C052CC0DA8D73451AFE5F03BE297F +CT=0AC15A9AFBB24D54AD99E987208272E2 + +I=2 +KEY=C98D5FB63B68C027E88317D8233C5B9D +PT=0AC15A9AFBB24D54AD99E987208272E2 +CT=A3D43BFFA65D0E80092F67A314857870 + +I=3 +KEY=6A5964499D35CEA7E1AC707B37B923ED +PT=A3D43BFFA65D0E80092F67A314857870 +CT=355F697E8B868B65B25A04E18D782AFA + +I=4 +KEY=5F060D3716B345C253F6749ABAC10917 +PT=355F697E8B868B65B25A04E18D782AFA +CT=ACC863637868E3E068D2FD6E3508454A + +I=5 +KEY=F3CE6E546EDBA6223B2489F48FC94C5D +PT=ACC863637868E3E068D2FD6E3508454A +CT=665F9F12A824F3D52A1C71D6210D5470 + +I=6 +KEY=9591F146C6FF55F71138F822AEC4182D +PT=665F9F12A824F3D52A1C71D6210D5470 +CT=9B27361DBC8E5618E8E98036F5AD40B0 + +I=7 +KEY=0EB6C75B7A7103EFF9D178145B69589D +PT=9B27361DBC8E5618E8E98036F5AD40B0 +CT=21D9BD7EBA0163A293F2D56C316CBD36 + +I=8 +KEY=2F6F7A25C070604D6A23AD786A05E5AB +PT=21D9BD7EBA0163A293F2D56C316CBD36 +CT=3E8037A9988E28FF81F2A7154ACD91BE + +I=9 +KEY=11EF4D8C58FE48B2EBD10A6D20C87415 +PT=3E8037A9988E28FF81F2A7154ACD91BE +CT=014EE14F1AA8C0D4A47A72F197F4DCB0 + +I=10 +KEY=10A1ACC3425688664FAB789CB73CA8A5 +PT=014EE14F1AA8C0D4A47A72F197F4DCB0 +CT=0B542083DBC03A96AA00C1A5AE58C9F1 + +I=11 +KEY=1BF58C409996B2F0E5ABB93919646154 +PT=0B542083DBC03A96AA00C1A5AE58C9F1 +CT=7340B59E1E3BB9211CE167F2DEBDB090 + +I=12 +KEY=68B539DE87AD0BD1F94ADECBC7D9D1C4 +PT=7340B59E1E3BB9211CE167F2DEBDB090 +CT=67E05F75135BA834CBCDCFF068541BBE + +I=13 +KEY=0F5566AB94F6A3E53287113BAF8DCA7A +PT=67E05F75135BA834CBCDCFF068541BBE +CT=8BD5553105C3507B0A07FDB351B25B4F + +I=14 +KEY=8480339A9135F39E3880EC88FE3F9135 +PT=8BD5553105C3507B0A07FDB351B25B4F +CT=649F061F95C0A79BD3066EFFE5B27CAB + +I=15 +KEY=E01F358504F55405EB8682771B8DED9E +PT=649F061F95C0A79BD3066EFFE5B27CAB +CT=697F4EB0603340E90FE91C27B6D9CEAA + +I=16 +KEY=89607B3564C614ECE46F9E50AD542334 +PT=697F4EB0603340E90FE91C27B6D9CEAA +CT=A8CBBA624FA28A7F8637324E1E20CB9C + +I=17 +KEY=21ABC1572B649E936258AC1EB374E8A8 +PT=A8CBBA624FA28A7F8637324E1E20CB9C +CT=73B852132DE715872A40EB25B1133C00 + +I=18 +KEY=5213934406838B144818473B0267D4A8 +PT=73B852132DE715872A40EB25B1133C00 +CT=1328A1C2F386BB3E4D4BE0942B8249A2 + +I=19 +KEY=413B3286F505302A0553A7AF29E59D0A +PT=1328A1C2F386BB3E4D4BE0942B8249A2 +CT=06F72DEA0067F543AA8C342CC9191745 + +I=20 +KEY=47CC1F6CF562C569AFDF9383E0FC8A4F +PT=06F72DEA0067F543AA8C342CC9191745 +CT=110B6011B60C94382C2321BFCAA62A1C + +I=21 +KEY=56C77F7D436E515183FCB23C2A5AA053 +PT=110B6011B60C94382C2321BFCAA62A1C +CT=80C90EF6794361DFA400EFE922F45A59 + +I=22 +KEY=D60E718B3A2D308E27FC5DD508AEFA0A +PT=80C90EF6794361DFA400EFE922F45A59 +CT=F8DF0AC62EE229245DB1F300F2E5B143 + +I=23 +KEY=2ED17B4D14CF19AA7A4DAED5FA4B4B49 +PT=F8DF0AC62EE229245DB1F300F2E5B143 +CT=45390146539E773B502E84A0C29AD5B0 + +I=24 +KEY=6BE87A0B47516E912A632A7538D19EF9 +PT=45390146539E773B502E84A0C29AD5B0 +CT=B07721757865838BDFC2329998B5174F + +I=25 +KEY=DB9F5B7E3F34ED1AF5A118ECA06489B6 +PT=B07721757865838BDFC2329998B5174F +CT=B83F3B7A9FFBA35DF1D6661A0F8AD0F4 + +I=26 +KEY=63A06004A0CF4E4704777EF6AFEE5942 +PT=B83F3B7A9FFBA35DF1D6661A0F8AD0F4 +CT=7098C99B1B245DE623B78F1B07D08EBE + +I=27 +KEY=1338A99FBBEB13A127C0F1EDA83ED7FC +PT=7098C99B1B245DE623B78F1B07D08EBE +CT=58A095EF9268B923920238486D0B13E1 + +I=28 +KEY=4B983C702983AA82B5C2C9A5C535C41D +PT=58A095EF9268B923920238486D0B13E1 +CT=97DD8052CE0D87715075A42942C120ED + +I=29 +KEY=DC45BC22E78E2DF3E5B76D8C87F4E4F0 +PT=97DD8052CE0D87715075A42942C120ED +CT=F480B5A67DAFCB9524DC21453AF66FAF + +I=30 +KEY=28C509849A21E666C16B4CC9BD028B5F +PT=F480B5A67DAFCB9524DC21453AF66FAF +CT=71CE64CE8C98367F2F12E6851AC70FF3 + +I=31 +KEY=590B6D4A16B9D019EE79AA4CA7C584AC +PT=71CE64CE8C98367F2F12E6851AC70FF3 +CT=81C3AA693CC1C647399701DA17D5FDD5 + +I=32 +KEY=D8C8C7232A78165ED7EEAB96B0107979 +PT=81C3AA693CC1C647399701DA17D5FDD5 +CT=5BB93103F6DDF0415592EE2217704D41 + +I=33 +KEY=8371F620DCA5E61F827C45B4A7603438 +PT=5BB93103F6DDF0415592EE2217704D41 +CT=87B8B17FF9079829AB5C47E055FFCEE3 + +I=34 +KEY=04C9475F25A27E3629200254F29FFADB +PT=87B8B17FF9079829AB5C47E055FFCEE3 +CT=615FE7D34154F42D6CE9D647904295E0 + +I=35 +KEY=6596A08C64F68A1B45C9D41362DD6F3B +PT=615FE7D34154F42D6CE9D647904295E0 +CT=A60C213CDF9B54DF9041948F98585CE2 + +I=36 +KEY=C39A81B0BB6DDEC4D588409CFA8533D9 +PT=A60C213CDF9B54DF9041948F98585CE2 +CT=FB126C61071EB9167B6FF28E5244E624 + +I=37 +KEY=3888EDD1BC7367D2AEE7B212A8C1D5FD +PT=FB126C61071EB9167B6FF28E5244E624 +CT=8A79CE45F030B91B53D1591D10FF1B02 + +I=38 +KEY=B2F123944C43DEC9FD36EB0FB83ECEFF +PT=8A79CE45F030B91B53D1591D10FF1B02 +CT=BE20190BAE15162F43E93F67A580192B + +I=39 +KEY=0CD13A9FE256C8E6BEDFD4681DBED7D4 +PT=BE20190BAE15162F43E93F67A580192B +CT=0107D3E3511F91545D02B498A9E3C318 + +I=40 +KEY=0DD6E97CB34959B2E3DD60F0B45D14CC +PT=0107D3E3511F91545D02B498A9E3C318 +CT=2A832A1205D6B5FCF1B20126EE59DD9D + +I=41 +KEY=2755C36EB69FEC4E126F61D65A04C951 +PT=2A832A1205D6B5FCF1B20126EE59DD9D +CT=F362782F550DCBFC49CEF15C3A0ABA7A + +I=42 +KEY=D437BB41E39227B25BA1908A600E732B +PT=F362782F550DCBFC49CEF15C3A0ABA7A +CT=51A8A0C6434A3BE8C939B6DDD56EAA53 + +I=43 +KEY=859F1B87A0D81C5A92982657B560D978 +PT=51A8A0C6434A3BE8C939B6DDD56EAA53 +CT=89D3F1086F3D96C18A76C61F25A52221 + +I=44 +KEY=0C4CEA8FCFE58A9B18EEE04890C5FB59 +PT=89D3F1086F3D96C18A76C61F25A52221 +CT=A5F7E0A5FA70DDB718EF970F50EB7B86 + +I=45 +KEY=A9BB0A2A3595572C00017747C02E80DF +PT=A5F7E0A5FA70DDB718EF970F50EB7B86 +CT=7BB64305538E71AFBF993B5BD23D5523 + +I=46 +KEY=D20D492F661B2683BF984C1C1213D5FC +PT=7BB64305538E71AFBF993B5BD23D5523 +CT=E6BF8F5338568603EC668C6D15331FA5 + +I=47 +KEY=34B2C67C5E4DA08053FEC0710720CA59 +PT=E6BF8F5338568603EC668C6D15331FA5 +CT=27644649FCDF52085CDB20E3DEE1E2F6 + +I=48 +KEY=13D68035A292F2880F25E092D9C128AF +PT=27644649FCDF52085CDB20E3DEE1E2F6 +CT=7629AACAED7F49938373C83410AD1744 + +I=49 +KEY=65FF2AFF4FEDBB1B8C5628A6C96C3FEB +PT=7629AACAED7F49938373C83410AD1744 +CT=D440FC6E9A65819934FAF8641C05A17C + +I=50 +KEY=B1BFD691D5883A82B8ACD0C2D5699E97 +PT=D440FC6E9A65819934FAF8641C05A17C +CT=FBEE29FEFD725E1852B58502D3076C46 + +I=51 +KEY=4A51FF6F28FA649AEA1955C0066EF2D1 +PT=FBEE29FEFD725E1852B58502D3076C46 +CT=E345A47A6C89BE4350CDD8C9D319529D + +I=52 +KEY=A9145B154473DAD9BAD48D09D577A04C +PT=E345A47A6C89BE4350CDD8C9D319529D +CT=1C6A7CBAF21E483B6025DB6DA573C5C6 + +I=53 +KEY=B57E27AFB66D92E2DAF156647004658A +PT=1C6A7CBAF21E483B6025DB6DA573C5C6 +CT=2B05F4D8EB50D851A013798753B65A1F + +I=54 +KEY=9E7BD3775D3D4AB37AE22FE323B23F95 +PT=2B05F4D8EB50D851A013798753B65A1F +CT=CEFE04978228A0DBCCE9EE42B21DD34A + +I=55 +KEY=5085D7E0DF15EA68B60BC1A191AFECDF +PT=CEFE04978228A0DBCCE9EE42B21DD34A +CT=7B41DF8CD85B61EA800536648DBDA2AE + +I=56 +KEY=2BC4086C074E8B82360EF7C51C124E71 +PT=7B41DF8CD85B61EA800536648DBDA2AE +CT=08688872151D18CD19E2FC14B9E4C962 + +I=57 +KEY=23AC801E1253934F2FEC0BD1A5F68713 +PT=08688872151D18CD19E2FC14B9E4C962 +CT=F08C88BE5E748C4D82D2E7D7813A33AF + +I=58 +KEY=D32008A04C271F02AD3EEC0624CCB4BC +PT=F08C88BE5E748C4D82D2E7D7813A33AF +CT=319B7D38AB1AC3AEA0A0490C341F4F20 + +I=59 +KEY=E2BB7598E73DDCAC0D9EA50A10D3FB9C +PT=319B7D38AB1AC3AEA0A0490C341F4F20 +CT=EE70748772E8D88B2717D78F31F0EA86 + +I=60 +KEY=0CCB011F95D504272A8972852123111A +PT=EE70748772E8D88B2717D78F31F0EA86 +CT=A3A5DC791EA1BBB9D7A2B292572DFD5C + +I=61 +KEY=AF6EDD668B74BF9EFD2BC017760EEC46 +PT=A3A5DC791EA1BBB9D7A2B292572DFD5C +CT=255692B06B3A18498BCAF99F7B3EE374 + +I=62 +KEY=8A384FD6E04EA7D776E139880D300F32 +PT=255692B06B3A18498BCAF99F7B3EE374 +CT=500E492232891293875F50279B5DC5C3 + +I=63 +KEY=DA3606F4D2C7B544F1BE69AF966DCAF1 +PT=500E492232891293875F50279B5DC5C3 +CT=57C3FCCE9B5BA3BC19BBF7BB9B37A9AC + +I=64 +KEY=8DF5FA3A499C16F8E8059E140D5A635D +PT=57C3FCCE9B5BA3BC19BBF7BB9B37A9AC +CT=BF06FDFDB687C8B24FB0E2A6D6D37EA5 + +I=65 +KEY=32F307C7FF1BDE4AA7B57CB2DB891DF8 +PT=BF06FDFDB687C8B24FB0E2A6D6D37EA5 +CT=6D459ED545CF3C6FF2746411CD9B3E31 + +I=66 +KEY=5FB69912BAD4E22555C118A3161223C9 +PT=6D459ED545CF3C6FF2746411CD9B3E31 +CT=C74E0704A9D9EC2D90F75B34FC95CD32 + +I=67 +KEY=98F89E16130D0E08C5364397EA87EEFB +PT=C74E0704A9D9EC2D90F75B34FC95CD32 +CT=0453D4FBC2D7F8E0AD0AD90F98D1EC5C + +I=68 +KEY=9CAB4AEDD1DAF6E8683C9A98725602A7 +PT=0453D4FBC2D7F8E0AD0AD90F98D1EC5C +CT=5BBA052D6C39DC1E9553B7646CB7344B + +I=69 +KEY=C7114FC0BDE32AF6FD6F2DFC1EE136EC +PT=5BBA052D6C39DC1E9553B7646CB7344B +CT=9870FFE04984426501ECB55FFBB363CB + +I=70 +KEY=5F61B020F4676893FC8398A3E5525527 +PT=9870FFE04984426501ECB55FFBB363CB +CT=1363D65F7C943FC4512E41A717D3704D + +I=71 +KEY=4C02667F88F35757ADADD904F281256A +PT=1363D65F7C943FC4512E41A717D3704D +CT=664762AED6BC5FB74A646A928837FC83 + +I=72 +KEY=2A4504D15E4F08E0E7C9B3967AB6D9E9 +PT=664762AED6BC5FB74A646A928837FC83 +CT=655CB6BAB4B0532273689E4DC9234C42 + +I=73 +KEY=4F19B26BEAFF5BC294A12DDBB39595AB +PT=655CB6BAB4B0532273689E4DC9234C42 +CT=E8AAE0E0B9D2BE6259AEBC478DC90FD9 + +I=74 +KEY=A7B3528B532DE5A0CD0F919C3E5C9A72 +PT=E8AAE0E0B9D2BE6259AEBC478DC90FD9 +CT=FECACAF43DD920FA3078256C6A587741 + +I=75 +KEY=5979987F6EF4C55AFD77B4F05404ED33 +PT=FECACAF43DD920FA3078256C6A587741 +CT=11F3F56529B8B172D87A4C86BB90F3B6 + +I=76 +KEY=488A6D1A474C7428250DF876EF941E85 +PT=11F3F56529B8B172D87A4C86BB90F3B6 +CT=B44340D44F1ABA37CB09FE57FC771A9E + +I=77 +KEY=FCC92DCE0856CE1FEE04062113E3041B +PT=B44340D44F1ABA37CB09FE57FC771A9E +CT=C49F12B88C34A0D696FE283B01D5710C + +I=78 +KEY=38563F7684626EC978FA2E1A12367517 +PT=C49F12B88C34A0D696FE283B01D5710C +CT=58D6D2D36C14DDBDA7604AB740918D76 + +I=79 +KEY=6080EDA5E876B374DF9A64AD52A7F861 +PT=58D6D2D36C14DDBDA7604AB740918D76 +CT=21F735F77B0EAD7551CE06900A568EB3 + +I=80 +KEY=4177D85293781E018E54623D58F176D2 +PT=21F735F77B0EAD7551CE06900A568EB3 +CT=FE2E9BDB393BF6D1BBF108B8AC3B6818 + +I=81 +KEY=BF594389AA43E8D035A56A85F4CA1ECA +PT=FE2E9BDB393BF6D1BBF108B8AC3B6818 +CT=FECFCD3722C6C8E6608258341220E739 + +I=82 +KEY=41968EBE88852036552732B1E6EAF9F3 +PT=FECFCD3722C6C8E6608258341220E739 +CT=10A8BB234C9D9A22DEC7887E931F85BD + +I=83 +KEY=513E359DC418BA148BE0BACF75F57C4E +PT=10A8BB234C9D9A22DEC7887E931F85BD +CT=767EB7DBA70BC7094DF7A5BDD233EB5C + +I=84 +KEY=2740824663137D1DC6171F72A7C69712 +PT=767EB7DBA70BC7094DF7A5BDD233EB5C +CT=FCD7184F3F4DB7CA182225B9A358209D + +I=85 +KEY=DB979A095C5ECAD7DE353ACB049EB78F +PT=FCD7184F3F4DB7CA182225B9A358209D +CT=A5CD025AEBF0380EAC66EF034806179F + +I=86 +KEY=7E5A9853B7AEF2D97253D5C84C98A010 +PT=A5CD025AEBF0380EAC66EF034806179F +CT=FE46F4A72C7031FE8D900152CD20B95F + +I=87 +KEY=801C6CF49BDEC327FFC3D49A81B8194F +PT=FE46F4A72C7031FE8D900152CD20B95F +CT=CF1ACB502A4B608C61364891E34F93A0 + +I=88 +KEY=4F06A7A4B195A3AB9EF59C0B62F78AEF +PT=CF1ACB502A4B608C61364891E34F93A0 +CT=95AB1367FF6C03DE87FFA282A3E52200 + +I=89 +KEY=DAADB4C34EF9A075190A3E89C112A8EF +PT=95AB1367FF6C03DE87FFA282A3E52200 +CT=762B6393252B347F55AF3E4CA16F2FC9 + +I=90 +KEY=AC86D7506BD2940A4CA500C5607D8726 +PT=762B6393252B347F55AF3E4CA16F2FC9 +CT=A63491A22E23AD921ADAB9CC0DA20521 + +I=91 +KEY=0AB246F245F13998567FB9096DDF8207 +PT=A63491A22E23AD921ADAB9CC0DA20521 +CT=C0852A5E7CEEAFB5FA87C440B598BFD6 + +I=92 +KEY=CA376CAC391F962DACF87D49D8473DD1 +PT=C0852A5E7CEEAFB5FA87C440B598BFD6 +CT=485747C528B08033169E991E98E4CBB5 + +I=93 +KEY=82602B6911AF161EBA66E45740A3F664 +PT=485747C528B08033169E991E98E4CBB5 +CT=415B95B222161A8C9ED20CF99C26848C + +I=94 +KEY=C33BBEDB33B90C9224B4E8AEDC8572E8 +PT=415B95B222161A8C9ED20CF99C26848C +CT=7E673E6348C38CD40C9B11F4C9F3E3A0 + +I=95 +KEY=BD5C80B87B7A8046282FF95A15769148 +PT=7E673E6348C38CD40C9B11F4C9F3E3A0 +CT=B88508E55279AFF0D848C38DBEC76B2C + +I=96 +KEY=05D9885D29032FB6F0673AD7ABB1FA64 +PT=B88508E55279AFF0D848C38DBEC76B2C +CT=3902B5DC34E815BA50A53DB9C8FFAA92 + +I=97 +KEY=3CDB3D811DEB3A0CA0C2076E634E50F6 +PT=3902B5DC34E815BA50A53DB9C8FFAA92 +CT=FEF57F51360547EA6B88085B8656A1D0 + +I=98 +KEY=C22E42D02BEE7DE6CB4A0F35E518F126 +PT=FEF57F51360547EA6B88085B8656A1D0 +CT=94D052E1F097106A5B714ADD0EF79E64 + +I=99 +KEY=56FE1031DB796D8C903B45E8EBEF6F42 +PT=94D052E1F097106A5B714ADD0EF79E64 +CT=7FD3EF411360E5270F63A8BACCCC74C0 + +I=100 +KEY=292DFF70C81988AB9F58ED5227231B82 +PT=7FD3EF411360E5270F63A8BACCCC74C0 +CT=F572692DE6EFBC2309B947D1A75BE009 + +I=101 +KEY=DC5F965D2EF6348896E1AA838078FB8B +PT=F572692DE6EFBC2309B947D1A75BE009 +CT=BFD3233C513448C283C05311B8085B5C + +I=102 +KEY=638CB5617FC27C4A1521F9923870A0D7 +PT=BFD3233C513448C283C05311B8085B5C +CT=078739F570071AA1A96A1F00F31E05FD + +I=103 +KEY=640B8C940FC566EBBC4BE692CB6EA52A +PT=078739F570071AA1A96A1F00F31E05FD +CT=947CA236277CDD0AC13C194B99E8CF16 + +I=104 +KEY=F0772EA228B9BBE17D77FFD952866A3C +PT=947CA236277CDD0AC13C194B99E8CF16 +CT=34DE5F2D355BC4ACE54AD0CB8C008CB8 + +I=105 +KEY=C4A9718F1DE27F4D983D2F12DE86E684 +PT=34DE5F2D355BC4ACE54AD0CB8C008CB8 +CT=E5729CBD84C89B914F35412F902A2CA3 + +I=106 +KEY=21DBED32992AE4DCD7086E3D4EACCA27 +PT=E5729CBD84C89B914F35412F902A2CA3 +CT=EB326D6ABAFC93EADBEC9B05CE4AAF0C + +I=107 +KEY=CAE9805823D677360CE4F53880E6652B +PT=EB326D6ABAFC93EADBEC9B05CE4AAF0C +CT=9F088089F8D8E8E28A9A2A1FF50F2ED3 + +I=108 +KEY=55E100D1DB0E9FD4867EDF2775E94BF8 +PT=9F088089F8D8E8E28A9A2A1FF50F2ED3 +CT=C8D2BF3D6ADB57F478656D4808142160 + +I=109 +KEY=9D33BFECB1D5C820FE1BB26F7DFD6A98 +PT=C8D2BF3D6ADB57F478656D4808142160 +CT=062016811215B9DBDD3C794A15FBEBBA + +I=110 +KEY=9B13A96DA3C071FB2327CB2568068122 +PT=062016811215B9DBDD3C794A15FBEBBA +CT=71F9F04E9AED1C302E5ED2AD36B5C7F5 + +I=111 +KEY=EAEA5923392D6DCB0D7919885EB346D7 +PT=71F9F04E9AED1C302E5ED2AD36B5C7F5 +CT=253982568F6C3FDFDE173E46B614989C + +I=112 +KEY=CFD3DB75B6415214D36E27CEE8A7DE4B +PT=253982568F6C3FDFDE173E46B614989C +CT=6D51D51276A6FA9C933E4D4496D0455E + +I=113 +KEY=A2820E67C0E7A88840506A8A7E779B15 +PT=6D51D51276A6FA9C933E4D4496D0455E +CT=B9A6924F773CE826BBBC6DDBFA4E146A + +I=114 +KEY=1B249C28B7DB40AEFBEC075184398F7F +PT=B9A6924F773CE826BBBC6DDBFA4E146A +CT=474943C523162BC81186779A07144BC6 + +I=115 +KEY=5C6DDFED94CD6B66EA6A70CB832DC4B9 +PT=474943C523162BC81186779A07144BC6 +CT=20128A092B99B4BC212B1107C3BA1DF9 + +I=116 +KEY=7C7F55E4BF54DFDACB4161CC4097D940 +PT=20128A092B99B4BC212B1107C3BA1DF9 +CT=90330B8FB5A50E958250A953EF5145C7 + +I=117 +KEY=EC4C5E6B0AF1D14F4911C89FAFC69C87 +PT=90330B8FB5A50E958250A953EF5145C7 +CT=C1B788D0EB2C8C7B9E020CC2BEACD595 + +I=118 +KEY=2DFBD6BBE1DD5D34D713C45D116A4912 +PT=C1B788D0EB2C8C7B9E020CC2BEACD595 +CT=EF87960DABBE82F6CFA8045CE4A9EED0 + +I=119 +KEY=C27C40B64A63DFC218BBC001F5C3A7C2 +PT=EF87960DABBE82F6CFA8045CE4A9EED0 +CT=405C8408D5027DF90CBE3159701D161A + +I=120 +KEY=8220C4BE9F61A23B1405F15885DEB1D8 +PT=405C8408D5027DF90CBE3159701D161A +CT=FCAB7F88E85D6573A98D23D684A5A5F3 + +I=121 +KEY=7E8BBB36773CC748BD88D28E017B142B +PT=FCAB7F88E85D6573A98D23D684A5A5F3 +CT=191E6F1EECBF5149F4D49446E97D8820 + +I=122 +KEY=6795D4289B839601495C46C8E8069C0B +PT=191E6F1EECBF5149F4D49446E97D8820 +CT=C77128F53D48594194EFBA67E46C6B23 + +I=123 +KEY=A0E4FCDDA6CBCF40DDB3FCAF0C6AF728 +PT=C77128F53D48594194EFBA67E46C6B23 +CT=DFB898170571450CC5E2244AE4D3AF43 + +I=124 +KEY=7F5C64CAA3BA8A4C1851D8E5E8B9586B +PT=DFB898170571450CC5E2244AE4D3AF43 +CT=3BD1633B5053609A3B42CC098F9F5D87 + +I=125 +KEY=448D07F1F3E9EAD6231314EC672605EC +PT=3BD1633B5053609A3B42CC098F9F5D87 +CT=AC15B23F205AEB10470F853BA18361E0 + +I=126 +KEY=E898B5CED3B301C6641C91D7C6A5640C +PT=AC15B23F205AEB10470F853BA18361E0 +CT=2DA73BA6E01B1ADFBEEAFA2E37942078 + +I=127 +KEY=C53F8E6833A81B19DAF66BF9F1314474 +PT=2DA73BA6E01B1ADFBEEAFA2E37942078 +CT=C5B3D7089173958B32340B88D35B738B + +I=128 +KEY=008C5960A2DB8E92E8C26071226A37FF +PT=C5B3D7089173958B32340B88D35B738B +CT=8318BAA96569F3ADCD30C08D54494392 + +I=129 +KEY=8394E3C9C7B27D3F25F2A0FC7623746D +PT=8318BAA96569F3ADCD30C08D54494392 +CT=4F6F2A06A1A344B261084563BCCC5A5A + +I=130 +KEY=CCFBC9CF6611398D44FAE59FCAEF2E37 +PT=4F6F2A06A1A344B261084563BCCC5A5A +CT=07EC18166362BF049A48D146A63FF378 + +I=131 +KEY=CB17D1D905738689DEB234D96CD0DD4F +PT=07EC18166362BF049A48D146A63FF378 +CT=81CB17ABAC28A3ED135442454C212646 + +I=132 +KEY=4ADCC672A95B2564CDE6769C20F1FB09 +PT=81CB17ABAC28A3ED135442454C212646 +CT=C1CBDE45E27B9B1198CE93A51E38D9C5 + +I=133 +KEY=8B1718374B20BE755528E5393EC922CC +PT=C1CBDE45E27B9B1198CE93A51E38D9C5 +CT=8E4EB89DDFEE065784556FA0B426954A + +I=134 +KEY=0559A0AA94CEB822D17D8A998AEFB786 +PT=8E4EB89DDFEE065784556FA0B426954A +CT=6A966414CC6FE52F957E9DE7012EC4BD + +I=135 +KEY=6FCFC4BE58A15D0D4403177E8BC1733B +PT=6A966414CC6FE52F957E9DE7012EC4BD +CT=7C88474D963BFDFE61F052F51D1796EF + +I=136 +KEY=134783F3CE9AA0F325F3458B96D6E5D4 +PT=7C88474D963BFDFE61F052F51D1796EF +CT=6269F5DA04B09D442DDCB46001573AE9 + +I=137 +KEY=712E7629CA2A3DB7082FF1EB9781DF3D +PT=6269F5DA04B09D442DDCB46001573AE9 +CT=FBD2965ACE0B360A12EF39873A8F3805 + +I=138 +KEY=8AFCE07304210BBD1AC0C86CAD0EE738 +PT=FBD2965ACE0B360A12EF39873A8F3805 +CT=5B46EF12C9BE55DCD5571D82E5BC6FF1 + +I=139 +KEY=D1BA0F61CD9F5E61CF97D5EE48B288C9 +PT=5B46EF12C9BE55DCD5571D82E5BC6FF1 +CT=403DEFDB60876F3161CF02F319F5EA9A + +I=140 +KEY=9187E0BAAD183150AE58D71D51476253 +PT=403DEFDB60876F3161CF02F319F5EA9A +CT=70FD321C583C1B54ED6AD3A79721E84A + +I=141 +KEY=E17AD2A6F5242A04433204BAC6668A19 +PT=70FD321C583C1B54ED6AD3A79721E84A +CT=32AE26E948D563782532AC711BFAB644 + +I=142 +KEY=D3D4F44FBDF1497C6600A8CBDD9C3C5D +PT=32AE26E948D563782532AC711BFAB644 +CT=ECF948F5EBB98E4C7286046E0F7AF127 + +I=143 +KEY=3F2DBCBA5648C7301486ACA5D2E6CD7A +PT=ECF948F5EBB98E4C7286046E0F7AF127 +CT=818F87EFA0B5E4098E737AD44DB537BA + +I=144 +KEY=BEA23B55F6FD23399AF5D6719F53FAC0 +PT=818F87EFA0B5E4098E737AD44DB537BA +CT=029F170737413F1BFBE02C292D506E44 + +I=145 +KEY=BC3D2C52C1BC1C226115FA58B2039484 +PT=029F170737413F1BFBE02C292D506E44 +CT=77A7C520912761121373E35FD3B5AF0F + +I=146 +KEY=CB9AE972509B7D307266190761B63B8B +PT=77A7C520912761121373E35FD3B5AF0F +CT=D407B965C368E1F77195ED446BEEBA73 + +I=147 +KEY=1F9D501793F39CC703F3F4430A5881F8 +PT=D407B965C368E1F77195ED446BEEBA73 +CT=D1F304E0B3614A4840F128AA364BA6A3 + +I=148 +KEY=CE6E54F72092D68F4302DCE93C13275B +PT=D1F304E0B3614A4840F128AA364BA6A3 +CT=69B748543EE72474D0CC301BDBD50A6C + +I=149 +KEY=A7D91CA31E75F2FB93CEECF2E7C62D37 +PT=69B748543EE72474D0CC301BDBD50A6C +CT=BA471D91DBC6D27EBA7B510E67830C3F + +I=150 +KEY=1D9E0132C5B3208529B5BDFC80452108 +PT=BA471D91DBC6D27EBA7B510E67830C3F +CT=7C0CF396D078E01A741613B1E1D7A9CB + +I=151 +KEY=6192F2A415CBC09F5DA3AE4D619288C3 +PT=7C0CF396D078E01A741613B1E1D7A9CB +CT=6F670A289398F49C75ACBBE9EAC2ABFC + +I=152 +KEY=0EF5F88C86533403280F15A48B50233F +PT=6F670A289398F49C75ACBBE9EAC2ABFC +CT=C392EF479528BF1B02296E6C894E4FDD + +I=153 +KEY=CD6717CB137B8B182A267BC8021E6CE2 +PT=C392EF479528BF1B02296E6C894E4FDD +CT=C4226C8C98D5F137A4C6A239E04B0FB3 + +I=154 +KEY=09457B478BAE7A2F8EE0D9F1E2556351 +PT=C4226C8C98D5F137A4C6A239E04B0FB3 +CT=2382714FC945AD4A1E03858B63973B9E + +I=155 +KEY=2AC70A0842EBD76590E35C7A81C258CF +PT=2382714FC945AD4A1E03858B63973B9E +CT=E41F350AC9320A8A23E27C0349978168 + +I=156 +KEY=CED83F028BD9DDEFB3012079C855D9A7 +PT=E41F350AC9320A8A23E27C0349978168 +CT=7E9137997CB7676F3D0141797C6F31A8 + +I=157 +KEY=B049089BF76EBA808E006100B43AE80F +PT=7E9137997CB7676F3D0141797C6F31A8 +CT=4BF7EBC15369A757981EE4A0B7F55706 + +I=158 +KEY=FBBEE35AA4071DD7161E85A003CFBF09 +PT=4BF7EBC15369A757981EE4A0B7F55706 +CT=EC677E86A8D2A5935D33D6471A58A781 + +I=159 +KEY=17D99DDC0CD5B8444B2D53E719971888 +PT=EC677E86A8D2A5935D33D6471A58A781 +CT=F31066D48884BC9B37F218FCF385344B + +I=160 +KEY=E4C9FB08845104DF7CDF4B1BEA122CC3 +PT=F31066D48884BC9B37F218FCF385344B +CT=51CFEA4E482A7B7BCF4D31DA5CED4370 + +I=161 +KEY=B5061146CC7B7FA4B3927AC1B6FF6FB3 +PT=51CFEA4E482A7B7BCF4D31DA5CED4370 +CT=89F3CD1590669A16F8460991BFD3CF5C + +I=162 +KEY=3CF5DC535C1DE5B24BD47350092CA0EF +PT=89F3CD1590669A16F8460991BFD3CF5C +CT=9930DA8E5DBC1F6C87B0B41BD386E2E0 + +I=163 +KEY=A5C506DD01A1FADECC64C74BDAAA420F +PT=9930DA8E5DBC1F6C87B0B41BD386E2E0 +CT=41A8CB583E5B9D2BA7CDA3763B6529C0 + +I=164 +KEY=E46DCD853FFA67F56BA9643DE1CF6BCF +PT=41A8CB583E5B9D2BA7CDA3763B6529C0 +CT=53479DCFB0C69624B42B9C272B0A1A85 + +I=165 +KEY=B72A504A8F3CF1D1DF82F81ACAC5714A +PT=53479DCFB0C69624B42B9C272B0A1A85 +CT=E72F27AE86E913EF55309120358BAD35 + +I=166 +KEY=500577E409D5E23E8AB2693AFF4EDC7F +PT=E72F27AE86E913EF55309120358BAD35 +CT=9B1EF901BACC70819DBC627C7CDC8CD9 + +I=167 +KEY=CB1B8EE5B31992BF170E0B46839250A6 +PT=9B1EF901BACC70819DBC627C7CDC8CD9 +CT=9546C7B789345E4C32EE84BCE8E78C7E + +I=168 +KEY=5E5D49523A2DCCF325E08FFA6B75DCD8 +PT=9546C7B789345E4C32EE84BCE8E78C7E +CT=33700B93E03CE8202BAC7E64E3255108 + +I=169 +KEY=6D2D42C1DA1124D30E4CF19E88508DD0 +PT=33700B93E03CE8202BAC7E64E3255108 +CT=44246615BCA5C0A8DCB7E63729398F0A + +I=170 +KEY=290924D466B4E47BD2FB17A9A16902DA +PT=44246615BCA5C0A8DCB7E63729398F0A +CT=3215FC55FEE5A30BFA11F8EBBC912652 + +I=171 +KEY=1B1CD8819851477028EAEF421DF82488 +PT=3215FC55FEE5A30BFA11F8EBBC912652 +CT=796C9136407BC4F484B253DAEB206912 + +I=172 +KEY=627049B7D82A8384AC58BC98F6D84D9A +PT=796C9136407BC4F484B253DAEB206912 +CT=B18977B404F0671C10AA979389408CCA + +I=173 +KEY=D3F93E03DCDAE498BCF22B0B7F98C150 +PT=B18977B404F0671C10AA979389408CCA +CT=B2592621EE947D4ED9AD4295E0675F93 + +I=174 +KEY=61A01822324E99D6655F699E9FFF9EC3 +PT=B2592621EE947D4ED9AD4295E0675F93 +CT=62D3B7E28765DA8F83EBE19C97293C0A + +I=175 +KEY=0373AFC0B52B4359E6B4880208D6A2C9 +PT=62D3B7E28765DA8F83EBE19C97293C0A +CT=F417D650D6B7631542CFF8F95FC81C9B + +I=176 +KEY=F7647990639C204CA47B70FB571EBE52 +PT=F417D650D6B7631542CFF8F95FC81C9B +CT=700A5DE153D6B438FFF7BA902DEC32FF + +I=177 +KEY=876E2471304A94745B8CCA6B7AF28CAD +PT=700A5DE153D6B438FFF7BA902DEC32FF +CT=67DC08A48F1EC7E32121B8693BB23621 + +I=178 +KEY=E0B22CD5BF5453977AAD72024140BA8C +PT=67DC08A48F1EC7E32121B8693BB23621 +CT=90038BB156A7F7992E260E9CBFAC0D82 + +I=179 +KEY=70B1A764E9F3A40E548B7C9EFEECB70E +PT=90038BB156A7F7992E260E9CBFAC0D82 +CT=C6BB1407C2D037BF238BEC772BA95352 + +I=180 +KEY=B60AB3632B2393B1770090E9D545E45C +PT=C6BB1407C2D037BF238BEC772BA95352 +CT=8C3D249574FF74F84053977219D69F5E + +I=181 +KEY=3A3797F65FDCE7493753079BCC937B02 +PT=8C3D249574FF74F84053977219D69F5E +CT=131F7FC5A1528AD5DCB167AFAA8BFD47 + +I=182 +KEY=2928E833FE8E6D9CEBE2603466188645 +PT=131F7FC5A1528AD5DCB167AFAA8BFD47 +CT=6E68AE6FDF2C10B42B85486D3EFBCEB9 + +I=183 +KEY=4740465C21A27D28C067285958E348FC +PT=6E68AE6FDF2C10B42B85486D3EFBCEB9 +CT=26808ABFA3967D742D64A26CADF8DD70 + +I=184 +KEY=61C0CCE38234005CED038A35F51B958C +PT=26808ABFA3967D742D64A26CADF8DD70 +CT=8BBCBA5E4C219D000A2F6B701CDA09C3 + +I=185 +KEY=EA7C76BDCE159D5CE72CE145E9C19C4F +PT=8BBCBA5E4C219D000A2F6B701CDA09C3 +CT=5D707BB328BEFF51C8C1D984C1608AA0 + +I=186 +KEY=B70C0D0EE6AB620D2FED38C128A116EF +PT=5D707BB328BEFF51C8C1D984C1608AA0 +CT=8D0A485482B914FC282C2DA9F7147D0C + +I=187 +KEY=3A06455A641276F107C11568DFB56BE3 +PT=8D0A485482B914FC282C2DA9F7147D0C +CT=C5678BC12445627CBAA94177F070F736 + +I=188 +KEY=FF61CE9B4057148DBD68541F2FC59CD5 +PT=C5678BC12445627CBAA94177F070F736 +CT=EB9B50846E92C20CD6EDBA7A3A260684 + +I=189 +KEY=14FA9E1F2EC5D6816B85EE6515E39A51 +PT=EB9B50846E92C20CD6EDBA7A3A260684 +CT=E2178B471A3F72A271013C4CBE41FA1C + +I=190 +KEY=F6ED155834FAA4231A84D229ABA2604D +PT=E2178B471A3F72A271013C4CBE41FA1C +CT=C10C8084A17D90339E5ED8C638B902A4 + +I=191 +KEY=37E195DC9587341084DA0AEF931B62E9 +PT=C10C8084A17D90339E5ED8C638B902A4 +CT=03C839CCF269548279F30A1F45C30556 + +I=192 +KEY=3429AC1067EE6092FD2900F0D6D867BF +PT=03C839CCF269548279F30A1F45C30556 +CT=1C5DC5C94B5C7E332D4122A0A4FACD96 + +I=193 +KEY=287469D92CB21EA1D06822507222AA29 +PT=1C5DC5C94B5C7E332D4122A0A4FACD96 +CT=E7292B7D15E9311F242FACFAFC0B0B81 + +I=194 +KEY=CF5D42A4395B2FBEF4478EAA8E29A1A8 +PT=E7292B7D15E9311F242FACFAFC0B0B81 +CT=EA6DF86EEE09613104DB81B97B949AEC + +I=195 +KEY=2530BACAD7524E8FF09C0F13F5BD3B44 +PT=EA6DF86EEE09613104DB81B97B949AEC +CT=8FBCCDEBA43FE3FFDE4C3C279BDD4A27 + +I=196 +KEY=AA8C7721736DAD702ED033346E607163 +PT=8FBCCDEBA43FE3FFDE4C3C279BDD4A27 +CT=985971BE962C63B0F50D1004963E9BED + +I=197 +KEY=32D5069FE541CEC0DBDD2330F85EEA8E +PT=985971BE962C63B0F50D1004963E9BED +CT=F2CC0FF4B6D2F88766F1B8BE370FE463 + +I=198 +KEY=C019096B53933647BD2C9B8ECF510EED +PT=F2CC0FF4B6D2F88766F1B8BE370FE463 +CT=FE33F823B7B97FC017B35B6E22415D3E + +I=199 +KEY=3E2AF148E42A4987AA9FC0E0ED1053D3 +PT=FE33F823B7B97FC017B35B6E22415D3E +CT=465D804A6053EC2580B59F0CD645C060 + +I=200 +KEY=787771028479A5A22A2A5FEC3B5593B3 +PT=465D804A6053EC2580B59F0CD645C060 +CT=DE05AD28693E3D471B8F39BAD1803C0E + +I=201 +KEY=A672DC2AED4798E531A56656EAD5AFBD +PT=DE05AD28693E3D471B8F39BAD1803C0E +CT=61EB397D55A2FC3D78974C8A10200AC6 + +I=202 +KEY=C799E557B8E564D849322ADCFAF5A57B +PT=61EB397D55A2FC3D78974C8A10200AC6 +CT=BD95D742D81AD795AA4E10FB41F54294 + +I=203 +KEY=7A0C321560FFB34DE37C3A27BB00E7EF +PT=BD95D742D81AD795AA4E10FB41F54294 +CT=F43A1E8C6E057E68414D23DA6932DE2C + +I=204 +KEY=8E362C990EFACD25A23119FDD23239C3 +PT=F43A1E8C6E057E68414D23DA6932DE2C +CT=8EBB208032245988E851148B34B92F0E + +I=205 +KEY=008D0C193CDE94AD4A600D76E68B16CD +PT=8EBB208032245988E851148B34B92F0E +CT=2F18B4B14A360E06C50C89A4E6FE6C17 + +I=206 +KEY=2F95B8A876E89AAB8F6C84D200757ADA +PT=2F18B4B14A360E06C50C89A4E6FE6C17 +CT=681E131FA7EA5EBE10B59D3F16009582 + +I=207 +KEY=478BABB7D102C4159FD919ED1675EF58 +PT=681E131FA7EA5EBE10B59D3F16009582 +CT=376FA31CC9D18E756E96715D61403C5D + +I=208 +KEY=70E408AB18D34A60F14F68B07735D305 +PT=376FA31CC9D18E756E96715D61403C5D +CT=519E87E4A1AC61C376842F028D1BD75F + +I=209 +KEY=217A8F4FB97F2BA387CB47B2FA2E045A +PT=519E87E4A1AC61C376842F028D1BD75F +CT=BFAED9E9964967342808C6C332E02204 + +I=210 +KEY=9ED456A62F364C97AFC38171C8CE265E +PT=BFAED9E9964967342808C6C332E02204 +CT=5A9F55C61A03D6A3196FFD6879CBCA02 + +I=211 +KEY=C44B036035359A34B6AC7C19B105EC5C +PT=5A9F55C61A03D6A3196FFD6879CBCA02 +CT=0FD872478223CDE765A62036EDD6F42F + +I=212 +KEY=CB937127B71657D3D30A5C2F5CD31873 +PT=0FD872478223CDE765A62036EDD6F42F +CT=965ED2AF7D26CDA8A8B7E7B2F1ADA768 + +I=213 +KEY=5DCDA388CA309A7B7BBDBB9DAD7EBF1B +PT=965ED2AF7D26CDA8A8B7E7B2F1ADA768 +CT=05599B8D42D92457605A69200C6DC0AA + +I=214 +KEY=5894380588E9BE2C1BE7D2BDA1137FB1 +PT=05599B8D42D92457605A69200C6DC0AA +CT=3436A49EE590788F625A6FB44BF72FA3 + +I=215 +KEY=6CA29C9B6D79C6A379BDBD09EAE45012 +PT=3436A49EE590788F625A6FB44BF72FA3 +CT=DB181195EFF35E307167BADA138A837A + +I=216 +KEY=B7BA8D0E828A989308DA07D3F96ED368 +PT=DB181195EFF35E307167BADA138A837A +CT=45E06B534233447E3CB696C1DD179477 + +I=217 +KEY=F25AE65DC0B9DCED346C91122479471F +PT=45E06B534233447E3CB696C1DD179477 +CT=D2EDC4E2B4EDD671D984E8AA5BABAAD7 + +I=218 +KEY=20B722BF74540A9CEDE879B87FD2EDC8 +PT=D2EDC4E2B4EDD671D984E8AA5BABAAD7 +CT=DB92F4E9F2DD6A61E20A79CFC82CD061 + +I=219 +KEY=FB25D656868960FD0FE20077B7FE3DA9 +PT=DB92F4E9F2DD6A61E20A79CFC82CD061 +CT=79383629DF124FD94A1C36BECB711747 + +I=220 +KEY=821DE07F599B2F2445FE36C97C8F2AEE +PT=79383629DF124FD94A1C36BECB711747 +CT=3F3F592FB3DB51CF08B70E6F2174AB43 + +I=221 +KEY=BD22B950EA407EEB4D4938A65DFB81AD +PT=3F3F592FB3DB51CF08B70E6F2174AB43 +CT=D34FDA2917E9697118502CB7A6CAE07C + +I=222 +KEY=6E6D6379FDA9179A55191411FB3161D1 +PT=D34FDA2917E9697118502CB7A6CAE07C +CT=24D2C38E5C52A404DBE0D8BB6DA44AEE + +I=223 +KEY=4ABFA0F7A1FBB39E8EF9CCAA96952B3F +PT=24D2C38E5C52A404DBE0D8BB6DA44AEE +CT=2ED6A7503B3547C04E0B7B709218CD4A + +I=224 +KEY=646907A79ACEF45EC0F2B7DA048DE675 +PT=2ED6A7503B3547C04E0B7B709218CD4A +CT=4F11BE7A8B5D1A04AB82F60000BC7B50 + +I=225 +KEY=2B78B9DD1193EE5A6B7041DA04319D25 +PT=4F11BE7A8B5D1A04AB82F60000BC7B50 +CT=B98B51B76B262CB9ED157567A05770AF + +I=226 +KEY=92F3E86A7AB5C2E3866534BDA466ED8A +PT=B98B51B76B262CB9ED157567A05770AF +CT=D6CA5483F89D5AA01DBCFEBE30C26F5E + +I=227 +KEY=4439BCE9822898439BD9CA0394A482D4 +PT=D6CA5483F89D5AA01DBCFEBE30C26F5E +CT=7706922EBA53937E287084C8FDFEB33F + +I=228 +KEY=333F2EC7387B0B3DB3A94ECB695A31EB +PT=7706922EBA53937E287084C8FDFEB33F +CT=0F2DA3B8BFCB1046CA94EC9322320BF9 + +I=229 +KEY=3C128D7F87B01B7B793DA2584B683A12 +PT=0F2DA3B8BFCB1046CA94EC9322320BF9 +CT=29CAD5CDC5A2834A5D533335FED2EA81 + +I=230 +KEY=15D858B242129831246E916DB5BAD093 +PT=29CAD5CDC5A2834A5D533335FED2EA81 +CT=A48A2D319552BF02E84E4662E75884DB + +I=231 +KEY=B1527583D7402733CC20D70F52E25448 +PT=A48A2D319552BF02E84E4662E75884DB +CT=334560ECD22BB9F660BC4FFAB13891C9 + +I=232 +KEY=8217156F056B9EC5AC9C98F5E3DAC581 +PT=334560ECD22BB9F660BC4FFAB13891C9 +CT=DAAEB8436205DFB6688D9DE0A21A6B9D + +I=233 +KEY=58B9AD2C676E4173C411051541C0AE1C +PT=DAAEB8436205DFB6688D9DE0A21A6B9D +CT=E38798615C2158872704125A7CFC6540 + +I=234 +KEY=BB3E354D3B4F19F4E315174F3D3CCB5C +PT=E38798615C2158872704125A7CFC6540 +CT=BACB9EA5499A093F6595E8D1D5CF7E50 + +I=235 +KEY=01F5ABE872D510CB8680FF9EE8F3B50C +PT=BACB9EA5499A093F6595E8D1D5CF7E50 +CT=813B0D4AC4C2B8371A1A132927D24F62 + +I=236 +KEY=80CEA6A2B617A8FC9C9AECB7CF21FA6E +PT=813B0D4AC4C2B8371A1A132927D24F62 +CT=D1AD1AE650B377520EE19370D9E968A9 + +I=237 +KEY=5163BC44E6A4DFAE927B7FC716C892C7 +PT=D1AD1AE650B377520EE19370D9E968A9 +CT=3CEC25102A51A5A4C26E7391590D54ED + +I=238 +KEY=6D8F9954CCF57A0A50150C564FC5C62A +PT=3CEC25102A51A5A4C26E7391590D54ED +CT=505FD54017E89E9FAA6376E399F2FF09 + +I=239 +KEY=3DD04C14DB1DE495FA767AB5D6373923 +PT=505FD54017E89E9FAA6376E399F2FF09 +CT=1B45550B4E3AB908A2CC72FFFB38701A + +I=240 +KEY=2695191F95275D9D58BA084A2D0F4939 +PT=1B45550B4E3AB908A2CC72FFFB38701A +CT=E2469D9D2F91E3AA88DC7970C94E7237 + +I=241 +KEY=C4D38482BAB6BE37D066713AE4413B0E +PT=E2469D9D2F91E3AA88DC7970C94E7237 +CT=9352C72F2B5093D1AF52BA959963F59B + +I=242 +KEY=578143AD91E62DE67F34CBAF7D22CE95 +PT=9352C72F2B5093D1AF52BA959963F59B +CT=F26DE32F035B270BA42075574056564E + +I=243 +KEY=A5ECA08292BD0AEDDB14BEF83D7498DB +PT=F26DE32F035B270BA42075574056564E +CT=6AC08B3D91FC31A34B3A81F7C300587E + +I=244 +KEY=CF2C2BBF03413B4E902E3F0FFE74C0A5 +PT=6AC08B3D91FC31A34B3A81F7C300587E +CT=E5E6455304C3B5E2349E2372D6E4B0B8 + +I=245 +KEY=2ACA6EEC07828EACA4B01C7D2890701D +PT=E5E6455304C3B5E2349E2372D6E4B0B8 +CT=90524F27C63CCA1E4CA9674381786C30 + +I=246 +KEY=BA9821CBC1BE44B2E8197B3EA9E81C2D +PT=90524F27C63CCA1E4CA9674381786C30 +CT=44625D68290415039E2C6C05B4954896 + +I=247 +KEY=FEFA7CA3E8BA51B17635173B1D7D54BB +PT=44625D68290415039E2C6C05B4954896 +CT=EC401B0D3780FDB4A3952706B07F6CEF + +I=248 +KEY=12BA67AEDF3AAC05D5A0303DAD023854 +PT=EC401B0D3780FDB4A3952706B07F6CEF +CT=DCEDC88021F6FD1C61C08DAABF0E73BA + +I=249 +KEY=CE57AF2EFECC5119B460BD97120C4BEE +PT=DCEDC88021F6FD1C61C08DAABF0E73BA +CT=C15C85D8161B97DD61EB8B514CDCFFD5 + +I=250 +KEY=0F0B2AF6E8D7C6C4D58B36C65ED0B43B +PT=C15C85D8161B97DD61EB8B514CDCFFD5 +CT=B68B65E041C84433DEA4D9E15E9F98AB + +I=251 +KEY=B9804F16A91F82F70B2FEF27004F2C90 +PT=B68B65E041C84433DEA4D9E15E9F98AB +CT=8122505A5B6F8D985A8D9D7E9E2FF4F3 + +I=252 +KEY=38A21F4CF2700F6F51A272599E60D863 +PT=8122505A5B6F8D985A8D9D7E9E2FF4F3 +CT=8F72F8FFA71D24C900D2BBE8784B9C48 + +I=253 +KEY=B7D0E7B3556D2BA65170C9B1E62B442B +PT=8F72F8FFA71D24C900D2BBE8784B9C48 +CT=1D541D794774264680CF3689365CD845 + +I=254 +KEY=AA84FACA12190DE0D1BFFF38D0779C6E +PT=1D541D794774264680CF3689365CD845 +CT=CBAE9336C5C1F038176B5123CC205BF7 + +I=255 +KEY=612A69FCD7D8FDD8C6D4AE1B1C57C799 +PT=CBAE9336C5C1F038176B5123CC205BF7 +CT=C4CE2DC1BAE3028392BD8A005A360F56 + +I=256 +KEY=A5E4443D6D3BFF5B5469241B4661C8CF +PT=C4CE2DC1BAE3028392BD8A005A360F56 +CT=549B7075DE975B759A6DAE7D761CDC01 + +I=257 +KEY=F17F3448B3ACA42ECE048A66307D14CE +PT=549B7075DE975B759A6DAE7D761CDC01 +CT=2338FFEEE2A391B2DAFD1EBB0ECF19E3 + +I=258 +KEY=D247CBA6510F359C14F994DD3EB20D2D +PT=2338FFEEE2A391B2DAFD1EBB0ECF19E3 +CT=B27705C512C6849DE6012A490F834F36 + +I=259 +KEY=6030CE6343C9B101F2F8BE943131421B +PT=B27705C512C6849DE6012A490F834F36 +CT=33A239E0426921192F8C89C6FBCDD23C + +I=260 +KEY=5392F78301A09018DD743752CAFC9027 +PT=33A239E0426921192F8C89C6FBCDD23C +CT=90CCBE46338C7E9FB25409F82BF81234 + +I=261 +KEY=C35E49C5322CEE876F203EAAE1048213 +PT=90CCBE46338C7E9FB25409F82BF81234 +CT=873D1CAF1F2C2A56BEE419FE8A01489F + +I=262 +KEY=4463556A2D00C4D1D1C427546B05CA8C +PT=873D1CAF1F2C2A56BEE419FE8A01489F +CT=1E9ED35EB85ADD9AB88B6D85299FD8E7 + +I=263 +KEY=5AFD8634955A194B694F4AD1429A126B +PT=1E9ED35EB85ADD9AB88B6D85299FD8E7 +CT=36871F8BD629B27EEDE04E086FC539C4 + +I=264 +KEY=6C7A99BF4373AB3584AF04D92D5F2BAF +PT=36871F8BD629B27EEDE04E086FC539C4 +CT=10D10983F98D799235E8142BD67C1FD2 + +I=265 +KEY=7CAB903CBAFED2A7B14710F2FB23347D +PT=10D10983F98D799235E8142BD67C1FD2 +CT=193CEDEEE0410DE79F1B2FC077B14199 + +I=266 +KEY=65977DD25ABFDF402E5C3F328C9275E4 +PT=193CEDEEE0410DE79F1B2FC077B14199 +CT=1EC99AD6EEF155B6B5F61452D2E73A7D + +I=267 +KEY=7B5EE704B44E8AF69BAA2B605E754F99 +PT=1EC99AD6EEF155B6B5F61452D2E73A7D +CT=92DA7D1858210C87B32C6FEA1CC6A0E6 + +I=268 +KEY=E9849A1CEC6F86712886448A42B3EF7F +PT=92DA7D1858210C87B32C6FEA1CC6A0E6 +CT=A06C4ACCA35DE95CFAD365349969271D + +I=269 +KEY=49E8D0D04F326F2DD25521BEDBDAC862 +PT=A06C4ACCA35DE95CFAD365349969271D +CT=4B892CB63A35A3DED0F43BA4309CBB2E + +I=270 +KEY=0261FC667507CCF302A11A1AEB46734C +PT=4B892CB63A35A3DED0F43BA4309CBB2E +CT=E05F73446706A68A5099088279B58064 + +I=271 +KEY=E23E8F2212016A795238129892F3F328 +PT=E05F73446706A68A5099088279B58064 +CT=542D8314299AF433EC549EBFFCF2B3D9 + +I=272 +KEY=B6130C363B9B9E4ABE6C8C276E0140F1 +PT=542D8314299AF433EC549EBFFCF2B3D9 +CT=4935A91590E8A70D9F75489F6D5B70E7 + +I=273 +KEY=FF26A523AB7339472119C4B8035A3016 +PT=4935A91590E8A70D9F75489F6D5B70E7 +CT=C3A4940C6EC7D0E2F11C3CF60AB2C31D + +I=274 +KEY=3C82312FC5B4E9A5D005F84E09E8F30B +PT=C3A4940C6EC7D0E2F11C3CF60AB2C31D +CT=F109AC488D917B5FC28BA28C9720A46F + +I=275 +KEY=CD8B9D67482592FA128E5AC29EC85764 +PT=F109AC488D917B5FC28BA28C9720A46F +CT=65234934641FA21D8C3A3804D09208F3 + +I=276 +KEY=A8A8D4532C3A30E79EB462C64E5A5F97 +PT=65234934641FA21D8C3A3804D09208F3 +CT=DE015A71CB9C9A3B11C2C9B744B6B5ED + +I=277 +KEY=76A98E22E7A6AADC8F76AB710AECEA7A +PT=DE015A71CB9C9A3B11C2C9B744B6B5ED +CT=973D0C12D7826B45CC7824EF09D82BAB + +I=278 +KEY=E19482303024C199430E8F9E0334C1D1 +PT=973D0C12D7826B45CC7824EF09D82BAB +CT=EBD2D23B9D08F63385A0D21FF76FAC33 + +I=279 +KEY=0A46500BAD2C37AAC6AE5D81F45B6DE2 +PT=EBD2D23B9D08F63385A0D21FF76FAC33 +CT=A7A460A555E4C4E53457AE00FC0D9BA8 + +I=280 +KEY=ADE230AEF8C8F34FF2F9F3810856F64A +PT=A7A460A555E4C4E53457AE00FC0D9BA8 +CT=56F0329103B5238E03C781E2AB0E7A2D + +I=281 +KEY=FB12023FFB7DD0C1F13E7263A3588C67 +PT=56F0329103B5238E03C781E2AB0E7A2D +CT=0D5710472E980CF439109BAC3EAB19A8 + +I=282 +KEY=F6451278D5E5DC35C82EE9CF9DF395CF +PT=0D5710472E980CF439109BAC3EAB19A8 +CT=063CB786AD88ECADC4EAC8FE39A84286 + +I=283 +KEY=F079A5FE786D30980CC42131A45BD749 +PT=063CB786AD88ECADC4EAC8FE39A84286 +CT=825BD1E57F0E16D744C2A69233C8654B + +I=284 +KEY=7222741B0763264F480687A39793B202 +PT=825BD1E57F0E16D744C2A69233C8654B +CT=8EA54322F26DC051F831A5CBBD07A73C + +I=285 +KEY=FC873739F50EE61EB03722682A94153E +PT=8EA54322F26DC051F831A5CBBD07A73C +CT=803F3194726F4D5C5BD80D12D1284F0A + +I=286 +KEY=7CB806AD8761AB42EBEF2F7AFBBC5A34 +PT=803F3194726F4D5C5BD80D12D1284F0A +CT=5A1D90E682989AB1A84F01422CE69F82 + +I=287 +KEY=26A5964B05F931F343A02E38D75AC5B6 +PT=5A1D90E682989AB1A84F01422CE69F82 +CT=3F5AFCD41950EEFBC3D7CEF744F0C060 + +I=288 +KEY=19FF6A9F1CA9DF088077E0CF93AA05D6 +PT=3F5AFCD41950EEFBC3D7CEF744F0C060 +CT=2EE3691BD58D7645DA91CD4943F10157 + +I=289 +KEY=371C0384C924A94D5AE62D86D05B0481 +PT=2EE3691BD58D7645DA91CD4943F10157 +CT=BEF4B188364E87A9E49855CC68C02A50 + +I=290 +KEY=89E8B20CFF6A2EE4BE7E784AB89B2ED1 +PT=BEF4B188364E87A9E49855CC68C02A50 +CT=2263387A7A52AB73704774D07EA5AA69 + +I=291 +KEY=AB8B8A7685388597CE390C9AC63E84B8 +PT=2263387A7A52AB73704774D07EA5AA69 +CT=84E68DA3E9D999016D0B734DAE8C128B + +I=292 +KEY=2F6D07D56CE11C96A3327FD768B29633 +PT=84E68DA3E9D999016D0B734DAE8C128B +CT=978F5F49D7BA1189F16FC0635231DF5F + +I=293 +KEY=B8E2589CBB5B0D1F525DBFB43A83496C +PT=978F5F49D7BA1189F16FC0635231DF5F +CT=FE59B2F2BDE0AB5E1700A1771EDF8663 + +I=294 +KEY=46BBEA6E06BBA641455D1EC3245CCF0F +PT=FE59B2F2BDE0AB5E1700A1771EDF8663 +CT=A94B982DC50C338E25ABFB4113F904A8 + +I=295 +KEY=EFF07243C3B795CF60F6E58237A5CBA7 +PT=A94B982DC50C338E25ABFB4113F904A8 +CT=79A5BB282D8247192AC9F8A3DB431EA1 + +I=296 +KEY=9655C96BEE35D2D64A3F1D21ECE6D506 +PT=79A5BB282D8247192AC9F8A3DB431EA1 +CT=FC339DA0D4593CD79D407CD6F1E1E7ED + +I=297 +KEY=6A6654CB3A6CEE01D77F61F71D0732EB +PT=FC339DA0D4593CD79D407CD6F1E1E7ED +CT=08EAB51652B85C6E9BC07B718E57E144 + +I=298 +KEY=628CE1DD68D4B26F4CBF1A869350D3AF +PT=08EAB51652B85C6E9BC07B718E57E144 +CT=9EA63934609F947AAA926443D0D5BEFA + +I=299 +KEY=FC2AD8E9084B2615E62D7EC543856D55 +PT=9EA63934609F947AAA926443D0D5BEFA +CT=7FE121C45E158FF1F527BAFDDBEAE223 + +I=300 +KEY=83CBF92D565EA9E4130AC438986F8F76 +PT=7FE121C45E158FF1F527BAFDDBEAE223 +CT=B1B70D5AD08BE5DCB8126D8700F25969 + +I=301 +KEY=327CF47786D54C38AB18A9BF989DD61F +PT=B1B70D5AD08BE5DCB8126D8700F25969 +CT=389812FA2D4A6419380A2AC8961CCDA6 + +I=302 +KEY=0AE4E68DAB9F2821931283770E811BB9 +PT=389812FA2D4A6419380A2AC8961CCDA6 +CT=CEF20323EE53A2BA576F4DF86A7AC078 + +I=303 +KEY=C416E5AE45CC8A9BC47DCE8F64FBDBC1 +PT=CEF20323EE53A2BA576F4DF86A7AC078 +CT=A65611BF1901C940B883D746F1694278 + +I=304 +KEY=6240F4115CCD43DB7CFE19C9959299B9 +PT=A65611BF1901C940B883D746F1694278 +CT=7E43C2A99D11C656351B96CECD400E75 + +I=305 +KEY=1C0336B8C1DC858D49E58F0758D297CC +PT=7E43C2A99D11C656351B96CECD400E75 +CT=7DE74D06851AD329C60DD1934C34CBE4 + +I=306 +KEY=61E47BBE44C656A48FE85E9414E65C28 +PT=7DE74D06851AD329C60DD1934C34CBE4 +CT=A99B66FE5825C895DCC6BE718AB8BE34 + +I=307 +KEY=C87F1D401CE39E31532EE0E59E5EE21C +PT=A99B66FE5825C895DCC6BE718AB8BE34 +CT=4752E30DDA44BA393EF197270C111AB7 + +I=308 +KEY=8F2DFE4DC6A724086DDF77C2924FF8AB +PT=4752E30DDA44BA393EF197270C111AB7 +CT=5A3FC324D12AC30FE5BBE87FC4B655F0 + +I=309 +KEY=D5123D69178DE70788649FBD56F9AD5B +PT=5A3FC324D12AC30FE5BBE87FC4B655F0 +CT=79061587E9D9FEEF52F753AE9BCDC4B1 + +I=310 +KEY=AC1428EEFE5419E8DA93CC13CD3469EA +PT=79061587E9D9FEEF52F753AE9BCDC4B1 +CT=86C32E69874EAA0D103581199AFA813A + +I=311 +KEY=2AD70687791AB3E5CAA64D0A57CEE8D0 +PT=86C32E69874EAA0D103581199AFA813A +CT=82A924A5928570E29D18DE200F8558DD + +I=312 +KEY=A87E2222EB9FC30757BE932A584BB00D +PT=82A924A5928570E29D18DE200F8558DD +CT=2D3E0ECCC1FEA93736BD205A5217D830 + +I=313 +KEY=85402CEE2A616A306103B3700A5C683D +PT=2D3E0ECCC1FEA93736BD205A5217D830 +CT=52FA0FCF771191A4A4C4E48C7B11DC1F + +I=314 +KEY=D7BA23215D70FB94C5C757FC714DB422 +PT=52FA0FCF771191A4A4C4E48C7B11DC1F +CT=C2A47519AACA187B97C884D20ED1D825 + +I=315 +KEY=151E5638F7BAE3EF520FD32E7F9C6C07 +PT=C2A47519AACA187B97C884D20ED1D825 +CT=66F1D0799F3C473978C189F745695293 + +I=316 +KEY=73EF86416886A4D62ACE5AD93AF53E94 +PT=66F1D0799F3C473978C189F745695293 +CT=803361A1428EAC3E134B0726E5CF0754 + +I=317 +KEY=F3DCE7E02A0808E839855DFFDF3A39C0 +PT=803361A1428EAC3E134B0726E5CF0754 +CT=2CC85CEDEE03D7AB279D766D3F2BADF4 + +I=318 +KEY=DF14BB0DC40BDF431E182B92E0119434 +PT=2CC85CEDEE03D7AB279D766D3F2BADF4 +CT=706626C1CE6731DD4DBA263C4D7EAB67 + +I=319 +KEY=AF729DCC0A6CEE9E53A20DAEAD6F3F53 +PT=706626C1CE6731DD4DBA263C4D7EAB67 +CT=BD7A59659E3774B85465C91740017628 + +I=320 +KEY=1208C4A9945B9A2607C7C4B9ED6E497B +PT=BD7A59659E3774B85465C91740017628 +CT=F1778330059467556D08223682EC32AA + +I=321 +KEY=E37F479991CFFD736ACFE68F6F827BD1 +PT=F1778330059467556D08223682EC32AA +CT=7B3C6979DCEE500E3FBB2CF4E17B0A3B + +I=322 +KEY=98432EE04D21AD7D5574CA7B8EF971EA +PT=7B3C6979DCEE500E3FBB2CF4E17B0A3B +CT=AFEBC6E81B90C3D82ECE26D788AB2412 + +I=323 +KEY=37A8E80856B16EA57BBAECAC065255F8 +PT=AFEBC6E81B90C3D82ECE26D788AB2412 +CT=E4087042AB32B9C43128AADACB4F7FA6 + +I=324 +KEY=D3A0984AFD83D7614A924676CD1D2A5E +PT=E4087042AB32B9C43128AADACB4F7FA6 +CT=07E1230BC456A3DCE7DF8A4EF7265BC8 + +I=325 +KEY=D441BB4139D574BDAD4DCC383A3B7196 +PT=07E1230BC456A3DCE7DF8A4EF7265BC8 +CT=88F0C30172B9A0EA8CD657CE6847AC94 + +I=326 +KEY=5CB178404B6CD457219B9BF6527CDD02 +PT=88F0C30172B9A0EA8CD657CE6847AC94 +CT=710FE26B2DAB5A12D147D6446732B272 + +I=327 +KEY=2DBE9A2B66C78E45F0DC4DB2354E6F70 +PT=710FE26B2DAB5A12D147D6446732B272 +CT=9C30630A9ADF9B4EBF099452AB75D14A + +I=328 +KEY=B18EF921FC18150B4FD5D9E09E3BBE3A +PT=9C30630A9ADF9B4EBF099452AB75D14A +CT=77526DA4D9AE9FD4347AAC10EA4728AA + +I=329 +KEY=C6DC948525B68ADF7BAF75F0747C9690 +PT=77526DA4D9AE9FD4347AAC10EA4728AA +CT=A9EDBD1A190BC67AC91D27BB7F5A1BD1 + +I=330 +KEY=6F31299F3CBD4CA5B2B2524B0B268D41 +PT=A9EDBD1A190BC67AC91D27BB7F5A1BD1 +CT=B8700A2BAEABCB0C67251C26F82ACEF7 + +I=331 +KEY=D74123B4921687A9D5974E6DF30C43B6 +PT=B8700A2BAEABCB0C67251C26F82ACEF7 +CT=FF5F30BA14A8C49276B040B00864BE29 + +I=332 +KEY=281E130E86BE433BA3270EDDFB68FD9F +PT=FF5F30BA14A8C49276B040B00864BE29 +CT=B448E87BE1E1A41FF94353F6018929C8 + +I=333 +KEY=9C56FB75675FE7245A645D2BFAE1D457 +PT=B448E87BE1E1A41FF94353F6018929C8 +CT=9F59D422CB9265C17732E0B16DEF352A + +I=334 +KEY=030F2F57ACCD82E52D56BD9A970EE17D +PT=9F59D422CB9265C17732E0B16DEF352A +CT=06FD7DB54E62FAC3C511F4DE5C1E93B9 + +I=335 +KEY=05F252E2E2AF7826E8474944CB1072C4 +PT=06FD7DB54E62FAC3C511F4DE5C1E93B9 +CT=0DDA3E4AD600F8D3EA6B06AE465DF3BC + +I=336 +KEY=08286CA834AF80F5022C4FEA8D4D8178 +PT=0DDA3E4AD600F8D3EA6B06AE465DF3BC +CT=17305FA95D26FB72995165DA8A07FCDF + +I=337 +KEY=1F18330169897B879B7D2A30074A7DA7 +PT=17305FA95D26FB72995165DA8A07FCDF +CT=12B56FEBEE2773A2258FC6E0F9115728 + +I=338 +KEY=0DAD5CEA87AE0825BEF2ECD0FE5B2A8F +PT=12B56FEBEE2773A2258FC6E0F9115728 +CT=36440D1A561E8F77B89DF6EA3D8EC7F5 + +I=339 +KEY=3BE951F0D1B08752066F1A3AC3D5ED7A +PT=36440D1A561E8F77B89DF6EA3D8EC7F5 +CT=752C4D620413C0F4A313CF37EB34CFDD + +I=340 +KEY=4EC51C92D5A347A6A57CD50D28E122A7 +PT=752C4D620413C0F4A313CF37EB34CFDD +CT=B2A282D0B6A9EB8B7B7C962675AEC843 + +I=341 +KEY=FC679E42630AAC2DDE00432B5D4FEAE4 +PT=B2A282D0B6A9EB8B7B7C962675AEC843 +CT=D0C3D785B5507C1460DDC44B123ED5FE + +I=342 +KEY=2CA449C7D65AD039BEDD87604F713F1A +PT=D0C3D785B5507C1460DDC44B123ED5FE +CT=4DAE52B77F8001CBAB8D1949E73DD578 + +I=343 +KEY=610A1B70A9DAD1F215509E29A84CEA62 +PT=4DAE52B77F8001CBAB8D1949E73DD578 +CT=29AA82197E8158D88FFFE5BEAFC0C967 + +I=344 +KEY=48A09969D75B892A9AAF7B97078C2305 +PT=29AA82197E8158D88FFFE5BEAFC0C967 +CT=58C665AA97945F7D3AA23BE8B8DDA20D + +I=345 +KEY=1066FCC340CFD657A00D407FBF518108 +PT=58C665AA97945F7D3AA23BE8B8DDA20D +CT=5A104A7093DB3308EB4009829B5E26B1 + +I=346 +KEY=4A76B6B3D314E55F4B4D49FD240FA7B9 +PT=5A104A7093DB3308EB4009829B5E26B1 +CT=8C8EA0BEE4640F6BB6D906A7A6EA3810 + +I=347 +KEY=C6F8160D3770EA34FD944F5A82E59FA9 +PT=8C8EA0BEE4640F6BB6D906A7A6EA3810 +CT=1517ED0B6D4EC3B85479AB28DF48BFDB + +I=348 +KEY=D3EFFB065A3E298CA9EDE4725DAD2072 +PT=1517ED0B6D4EC3B85479AB28DF48BFDB +CT=9546CCBB8094E65E464C38E0809552E3 + +I=349 +KEY=46A937BDDAAACFD2EFA1DC92DD387291 +PT=9546CCBB8094E65E464C38E0809552E3 +CT=7D5AD8DEDB92F80D2B28C3458843AE84 + +I=350 +KEY=3BF3EF63013837DFC4891FD7557BDC15 +PT=7D5AD8DEDB92F80D2B28C3458843AE84 +CT=E62676E27ED61D0FD7DFE170E0938361 + +I=351 +KEY=DDD599817FEE2AD01356FEA7B5E85F74 +PT=E62676E27ED61D0FD7DFE170E0938361 +CT=DA9865198B9463681C66FB96C2C1DAA5 + +I=352 +KEY=074DFC98F47A49B80F300531772985D1 +PT=DA9865198B9463681C66FB96C2C1DAA5 +CT=62CD9DAA9487F34AF168E6E20A0684CF + +I=353 +KEY=6580613260FDBAF2FE58E3D37D2F011E +PT=62CD9DAA9487F34AF168E6E20A0684CF +CT=10BA978FDABA586691946145BE246D3C + +I=354 +KEY=753AF6BDBA47E2946FCC8296C30B6C22 +PT=10BA978FDABA586691946145BE246D3C +CT=13443CF524213B08776D7F5169B79C0F + +I=355 +KEY=667ECA489E66D99C18A1FDC7AABCF02D +PT=13443CF524213B08776D7F5169B79C0F +CT=6507336876ED4F6DB3E35D6CF5A89A2B + +I=356 +KEY=0379F920E88B96F1AB42A0AB5F146A06 +PT=6507336876ED4F6DB3E35D6CF5A89A2B +CT=B84902B5CBBC6DB8111CA45BC5F99991 + +I=357 +KEY=BB30FB952337FB49BA5E04F09AEDF397 +PT=B84902B5CBBC6DB8111CA45BC5F99991 +CT=20973140A999B8AD9982B9B706F7C32E + +I=358 +KEY=9BA7CAD58AAE43E423DCBD479C1A30B9 +PT=20973140A999B8AD9982B9B706F7C32E +CT=EE7FF1177C5E080AA03854A2A819565E + +I=359 +KEY=75D83BC2F6F04BEE83E4E9E5340366E7 +PT=EE7FF1177C5E080AA03854A2A819565E +CT=7A4F74EC2181269AC17D0E48A4DA2A88 + +I=360 +KEY=0F974F2ED7716D744299E7AD90D94C6F +PT=7A4F74EC2181269AC17D0E48A4DA2A88 +CT=5B7A7751F0FD91E203A14CE518838DD7 + +I=361 +KEY=54ED387F278CFC964138AB48885AC1B8 +PT=5B7A7751F0FD91E203A14CE518838DD7 +CT=71319FDDBACB038354A37A41F1910F94 + +I=362 +KEY=25DCA7A29D47FF15159BD10979CBCE2C +PT=71319FDDBACB038354A37A41F1910F94 +CT=81AC58FD503FC3AA78199168AE2C9085 + +I=363 +KEY=A470FF5FCD783CBF6D824061D7E75EA9 +PT=81AC58FD503FC3AA78199168AE2C9085 +CT=1F668F512038142C1155B950B0B040EC + +I=364 +KEY=BB16700EED4028937CD7F93167571E45 +PT=1F668F512038142C1155B950B0B040EC +CT=6B27D7791E9B14A5AC3D9582DBDBD929 + +I=365 +KEY=D031A777F3DB3C36D0EA6CB3BC8CC76C +PT=6B27D7791E9B14A5AC3D9582DBDBD929 +CT=9B7151FDC4E135EE93DAB2D9EB74D59C + +I=366 +KEY=4B40F68A373A09D84330DE6A57F812F0 +PT=9B7151FDC4E135EE93DAB2D9EB74D59C +CT=1F199945BCFA624B1AD3DCBBD95291B2 + +I=367 +KEY=54596FCF8BC06B9359E302D18EAA8342 +PT=1F199945BCFA624B1AD3DCBBD95291B2 +CT=E2C82FA8FE98F26283A6E0B75D0A58C6 + +I=368 +KEY=B6914067755899F1DA45E266D3A0DB84 +PT=E2C82FA8FE98F26283A6E0B75D0A58C6 +CT=5A240FFB99C3594C273B51CACF01B28B + +I=369 +KEY=ECB54F9CEC9BC0BDFD7EB3AC1CA1690F +PT=5A240FFB99C3594C273B51CACF01B28B +CT=D01847391534848FB102CA85C97749B1 + +I=370 +KEY=3CAD08A5F9AF44324C7C7929D5D620BE +PT=D01847391534848FB102CA85C97749B1 +CT=DC5CF60EBDF4A8DDDDF997E7ACA67515 + +I=371 +KEY=E0F1FEAB445BECEF9185EECE797055AB +PT=DC5CF60EBDF4A8DDDDF997E7ACA67515 +CT=749E3815FE305B307D9F4DB6A7E4658C + +I=372 +KEY=946FC6BEBA6BB7DFEC1AA378DE943027 +PT=749E3815FE305B307D9F4DB6A7E4658C +CT=8152C1E676A4FC8B0CD093FEB4B51615 + +I=373 +KEY=153D0758CCCF4B54E0CA30866A212632 +PT=8152C1E676A4FC8B0CD093FEB4B51615 +CT=0847044668710F6E5C93DD248AC921BA + +I=374 +KEY=1D7A031EA4BE443ABC59EDA2E0E80788 +PT=0847044668710F6E5C93DD248AC921BA +CT=1D6C3EFB413A59AB40F34CEFBFF25C17 + +I=375 +KEY=00163DE5E5841D91FCAAA14D5F1A5B9F +PT=1D6C3EFB413A59AB40F34CEFBFF25C17 +CT=5D7C206A79D61868FFE7AA28044996D3 + +I=376 +KEY=5D6A1D8F9C5205F9034D0B655B53CD4C +PT=5D7C206A79D61868FFE7AA28044996D3 +CT=78B4DE3B84D5D1010245CA3077A41BAC + +I=377 +KEY=25DEC3B41887D4F80108C1552CF7D6E0 +PT=78B4DE3B84D5D1010245CA3077A41BAC +CT=9E003AACEDECDBB077BDE832465F40C7 + +I=378 +KEY=BBDEF918F56B0F4876B529676AA89627 +PT=9E003AACEDECDBB077BDE832465F40C7 +CT=EEFF9E6C73E6DC5432AA446385AA1499 + +I=379 +KEY=55216774868DD31C441F6D04EF0282BE +PT=EEFF9E6C73E6DC5432AA446385AA1499 +CT=03252A19E37D9F040C56E4D712982798 + +I=380 +KEY=56044D6D65F04C18484989D3FD9AA526 +PT=03252A19E37D9F040C56E4D712982798 +CT=CF59A752BA0E14BE23AFD09437B39C65 + +I=381 +KEY=995DEA3FDFFE58A66BE65947CA293943 +PT=CF59A752BA0E14BE23AFD09437B39C65 +CT=8B08FB7974A77167DFB234F57C8DFFE1 + +I=382 +KEY=12551146AB5929C1B4546DB2B6A4C6A2 +PT=8B08FB7974A77167DFB234F57C8DFFE1 +CT=DD2A93C1106CFDAE4A1684EE02C82FE2 + +I=383 +KEY=CF7F8287BB35D46FFE42E95CB46CE940 +PT=DD2A93C1106CFDAE4A1684EE02C82FE2 +CT=38696128584F60636354E9F802590391 + +I=384 +KEY=F716E3AFE37AB40C9D1600A4B635EAD1 +PT=38696128584F60636354E9F802590391 +CT=7E552E3AD28729F642D590E3C289D598 + +I=385 +KEY=8943CD9531FD9DFADFC3904774BC3F49 +PT=7E552E3AD28729F642D590E3C289D598 +CT=17A40392AA00D7B5A6E9F59007E60C22 + +I=386 +KEY=9EE7CE079BFD4A4F792A65D7735A336B +PT=17A40392AA00D7B5A6E9F59007E60C22 +CT=A048D6755C2AD24DD8833DDCEB145BA6 + +I=387 +KEY=3EAF1872C7D79802A1A9580B984E68CD +PT=A048D6755C2AD24DD8833DDCEB145BA6 +CT=2F1CCE852396986EC4B2852E5F684CD2 + +I=388 +KEY=11B3D6F7E441006C651BDD25C726241F +PT=2F1CCE852396986EC4B2852E5F684CD2 +CT=2C28BD1E98DA63B95C0C81202BBCFE39 + +I=389 +KEY=3D9B6BE97C9B63D539175C05EC9ADA26 +PT=2C28BD1E98DA63B95C0C81202BBCFE39 +CT=6AE097A8E685B58BA2309B59D6A9EB2B + +I=390 +KEY=577BFC419A1ED65E9B27C75C3A33310D +PT=6AE097A8E685B58BA2309B59D6A9EB2B +CT=6EFC01751753999843A9BB6749097E0C + +I=391 +KEY=3987FD348D4D4FC6D88E7C3B733A4F01 +PT=6EFC01751753999843A9BB6749097E0C +CT=6B6B75F78016052E4F89C73EA826D2F2 + +I=392 +KEY=52EC88C30D5B4AE89707BB05DB1C9DF3 +PT=6B6B75F78016052E4F89C73EA826D2F2 +CT=1E9890E8F0AABCBFB8C4EDAEA0F563EF + +I=393 +KEY=4C74182BFDF1F6572FC356AB7BE9FE1C +PT=1E9890E8F0AABCBFB8C4EDAEA0F563EF +CT=143ED9FE6FD7DFB822C31DE8A3E868A9 + +I=394 +KEY=584AC1D5922629EF0D004B43D80196B5 +PT=143ED9FE6FD7DFB822C31DE8A3E868A9 +CT=9C2834AA5C95F2874DC6B267C0469E14 + +I=395 +KEY=C462F57FCEB3DB6840C6F924184708A1 +PT=9C2834AA5C95F2874DC6B267C0469E14 +CT=0720377F673352693EE2EF76D4FCFB0F + +I=396 +KEY=C342C200A98089017E241652CCBBF3AE +PT=0720377F673352693EE2EF76D4FCFB0F +CT=E83ED303F4B0ABF675C7BBC470B924FE + +I=397 +KEY=2B7C11035D3022F70BE3AD96BC02D750 +PT=E83ED303F4B0ABF675C7BBC470B924FE +CT=D87ADD68CBCAEA46DFFF99AE3723BC94 + +I=398 +KEY=F306CC6B96FAC8B1D41C34388B216BC4 +PT=D87ADD68CBCAEA46DFFF99AE3723BC94 +CT=2C290AE7C65B6E5BBAA32DE577DBA343 + +I=399 +KEY=DF2FC68C50A1A6EA6EBF19DDFCFAC887 +PT=2C290AE7C65B6E5BBAA32DE577DBA343 +CT=A04377ABE259B0D0B5BA2D40A501971B + +========================= + +KEYSIZE=192 + +I=0 +KEY=000000000000000000000000000000000000000000000000 +PT=00000000000000000000000000000000 +CT=F3F6752AE8D7831138F041560631B114 + +I=1 +KEY=AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114 +PT=F3F6752AE8D7831138F041560631B114 +CT=77BA00ED5412DFF27C8ED91F3C376172 + +I=2 +KEY=A92B07597B52873C844C75C7BCC55CE3447E98493A06D066 +PT=77BA00ED5412DFF27C8ED91F3C376172 +CT=2D92DE893574463412BD7D121A94952F + +I=3 +KEY=5FD632DA76165EDBA9DEAB4E89B11AD756C3E55B20924549 +PT=2D92DE893574463412BD7D121A94952F +CT=96650F835912F5E748422727802C6CE1 + +I=4 +KEY=984A4BEC5D3474103FBBA4CDD0A3EF301E81C27CA0BE29A8 +PT=96650F835912F5E748422727802C6CE1 +CT=5FCCD4B5F125ADC5B85A56DB32283732 + +I=5 +KEY=6B7EDEEAC755885F60777078218642F5A6DB94A792961E9A +PT=5FCCD4B5F125ADC5B85A56DB32283732 +CT=EA5B1DAE2E4F9FD254A2CC28E128EB9B + +I=6 +KEY=CA5585D8C9727F208A2C6DD60FC9DD27F279588F73BEF501 +PT=EA5B1DAE2E4F9FD254A2CC28E128EB9B +CT=BB87C0FF5DB4B2A593B93398407F823A + +I=7 +KEY=BADA7C0D4A0CDD4631ABAD29527D6F8261C06B1733C1773B +PT=BB87C0FF5DB4B2A593B93398407F823A +CT=D5AF7D56281F86E3E079BE6B9465DBB4 + +I=8 +KEY=FF98AB620A203FFCE404D07F7A62E96181B9D57CA7A4AC8F +PT=D5AF7D56281F86E3E079BE6B9465DBB4 +CT=511331CCA62B067CAC47475800EE33CD + +I=9 +KEY=1186A7F46656EA07B517E1B3DC49EF1D2DFE9224A74A9F42 +PT=511331CCA62B067CAC47475800EE33CD +CT=64ACDC3579D7871644DD585C582AF3A2 + +I=10 +KEY=313ADFF9712EABE4D1BB3D86A59E680B6923CA78FF606CE0 +PT=64ACDC3579D7871644DD585C582AF3A2 +CT=EA3C45FB8A6E548DAB14BAE07966246C + +I=11 +KEY=DDABAC02BE6C40493B87787D2FF03C86C23770988606488C +PT=EA3C45FB8A6E548DAB14BAE07966246C +CT=6BC276C465C9ADBE900049A5B58D2DCB + +I=12 +KEY=9A9F7E267C2BFCD150450EB94A3991385237393D338B6547 +PT=6BC276C465C9ADBE900049A5B58D2DCB +CT=E2F0FFA8D6DF327CA0FB80A325B21931 + +I=13 +KEY=80246B9FB6224226B2B5F1119CE6A344F2CCB99E16397C76 +PT=E2F0FFA8D6DF327CA0FB80A325B21931 +CT=ACEE4C9B8A00A7760DD9CD2F6C6DFA8C + +I=14 +KEY=60CDC3E8265B71E81E5BBD8A16E60432FF1574B17A5486FA +PT=ACEE4C9B8A00A7760DD9CD2F6C6DFA8C +CT=9579E43690FD2800FED810F7442D366B + +I=15 +KEY=9DEC584DB87D63F48B2259BC861B2C3201CD64463E79B091 +PT=9579E43690FD2800FED810F7442D366B +CT=72D4D064851A050D415FC94E3FBB6A1C + +I=16 +KEY=BBC1ED636907611EF9F689D80301293F4092AD0801C2DA8D +PT=72D4D064851A050D415FC94E3FBB6A1C +CT=0CCC3B9B35CE3584D7B78C14905BEE55 + +I=17 +KEY=AE398529289F7994F53AB24336CF1CBB9725211C919934D8 +PT=0CCC3B9B35CE3584D7B78C14905BEE55 +CT=66B6A61BF7BCC6392B8FEC12152E5363 + +I=18 +KEY=4617E60BD8AF29D5938C1458C173DA82BCAACD0E84B767BB +PT=66B6A61BF7BCC6392B8FEC12152E5363 +CT=6C2247EA3BC566A84A30BF0B30AB4EEC + +I=19 +KEY=6B762D1391AA17CBFFAE53B2FAB6BC2AF69A7205B41C2957 +PT=6C2247EA3BC566A84A30BF0B30AB4EEC +CT=C16FBCDFAE34E839BA449D697452550D + +I=20 +KEY=374499A8C09A60DA3EC1EF6D548254134CDEEF6CC04E7C5A +PT=C16FBCDFAE34E839BA449D697452550D +CT=C8B704B4AFE68AF5C91A810F2873F13F + +I=21 +KEY=09DCC638DD59F37CF676EBD9FB64DEE685C46E63E83D8D65 +PT=C8B704B4AFE68AF5C91A810F2873F13F +CT=FC9C31036B26234ED1CBA46E0BE944EE + +I=22 +KEY=CE2CEB8869D7EC160AEADADA9042FDA8540FCA0DE3D4C98B +PT=FC9C31036B26234ED1CBA46E0BE944EE +CT=DCF13203AD179CD008779F189EBC78F0 + +I=23 +KEY=505FBECF6B0B083CD61BE8D93D5561785C7855157D68B17B +PT=DCF13203AD179CD008779F189EBC78F0 +CT=24AEB937E259D44D352FF39C1A8A79E0 + +I=24 +KEY=1D1649FDB7484DD2F2B551EEDF0CB5356957A68967E2C89B +PT=24AEB937E259D44D352FF39C1A8A79E0 +CT=19016D033872CB7694A712A84DBC43F2 + +I=25 +KEY=9BE41771C0F74BDEEBB43CEDE77E7E43FDF0B4212A5E8B69 +PT=19016D033872CB7694A712A84DBC43F2 +CT=0536107FEA26AB6A4FE2667EF7FCF16A + +I=26 +KEY=FF3619AED9A1F724EE822C920D58D529B212D25FDDA27A03 +PT=0536107FEA26AB6A4FE2667EF7FCF16A +CT=5D35213390FCA53AD422DC2ED4BF674D + +I=27 +KEY=59D2F5AF4BB6F28BB3B70DA19DA4701366300E71091D1D4E +PT=5D35213390FCA53AD422DC2ED4BF674D +CT=04A6F9B1AE64AD03659C4E375A690852 + +I=28 +KEY=C8384D35CAF0074EB711F41033C0DD1003AC40465374151C +PT=04A6F9B1AE64AD03659C4E375A690852 +CT=18AB347EFC2F8F93655E16732BB509DE + +I=29 +KEY=910CE58F963B684EAFBAC06ECFEF528366F2563578C11CC2 +PT=18AB347EFC2F8F93655E16732BB509DE +CT=F6037C06C71793BD14A4FC89A05D918F + +I=30 +KEY=5D1EF94FBA1E098459B9BC6808F8C13E7256AABCD89C8D4D +PT=F6037C06C71793BD14A4FC89A05D918F +CT=75094DD9B2FDDAC96B49CAB676057288 + +I=31 +KEY=61FDA8DA3EF8949C2CB0F1B1BA051BF7191F600AAE99FFC5 +PT=75094DD9B2FDDAC96B49CAB676057288 +CT=346F9F9E70C05B53DCDAF736FE59749D + +I=32 +KEY=5C383CCC2DCAE66A18DF6E2FCAC540A4C5C5973C50C08B58 +PT=346F9F9E70C05B53DCDAF736FE59749D +CT=1DB82CC8EF5B736AAEFD1F1B9CE5B67D + +I=33 +KEY=1EC7FDBB8AE4FF05056742E7259E33CE6B388827CC253D25 +PT=1DB82CC8EF5B736AAEFD1F1B9CE5B67D +CT=31B5E80D946AE577268973AF865151EB + +I=34 +KEY=FFE21FDAB07E755034D2AAEAB1F4D6B94DB1FB884A746CCE +PT=31B5E80D946AE577268973AF865151EB +CT=9FD63EB3EC6A15FC149A4F058EDA7080 + +I=35 +KEY=7EC4053A63B2353BAB0494595D9EC345592BB48DC4AE1C4E +PT=9FD63EB3EC6A15FC149A4F058EDA7080 +CT=41730A9E9D197435AC36902C57B16588 + +I=36 +KEY=FB6D2FAFD47FE8D1EA779EC7C087B770F51D24A1931F79C6 +PT=41730A9E9D197435AC36902C57B16588 +CT=08AD282171F0772F85C0A43E8BACEC74 + +I=37 +KEY=9531B1BBE0863D44E2DAB6E6B177C05F70DD809F18B395B2 +PT=08AD282171F0772F85C0A43E8BACEC74 +CT=8561E508FA237E4170CECD3A8352CFA4 + +I=38 +KEY=0AB0CF2D1CA2957A67BB53EE4B54BE1E00134DA59BE15A16 +PT=8561E508FA237E4170CECD3A8352CFA4 +CT=4470EFA3C3172EBF64A064F59AE364A9 + +I=39 +KEY=291FD5C38E400CFA23CBBC4D884390A164B3295001023EBF +PT=4470EFA3C3172EBF64A064F59AE364A9 +CT=FCC5636DFE9E45CB7761DD14A1CF4773 + +I=40 +KEY=114E4DEF0447E1D5DF0EDF2076DDD56A13D2F444A0CD79CC +PT=FCC5636DFE9E45CB7761DD14A1CF4773 +CT=2130BA8736D4933678C3B536AEDBC500 + +I=41 +KEY=0C19F74860652278FE3E65A74009465C6B1141720E16BCCC +PT=2130BA8736D4933678C3B536AEDBC500 +CT=1725EECBA8F9A542E9956168390C82C2 + +I=42 +KEY=EF9E7E57576D8A3EE91B8B6CE8F0E31E8284201A371A3E0E +PT=1725EECBA8F9A542E9956168390C82C2 +CT=60912D3EEDC962D68A29AED73DDAA24D + +I=43 +KEY=CE6464925302B9F4898AA652053981C808AD8ECD0AC09C43 +PT=60912D3EEDC962D68A29AED73DDAA24D +CT=43A8B490BBC75DC8D2D2F060C8672E9E + +I=44 +KEY=8657F15C75C74469CA2212C2BEFEDC00DA7F7EADC2A7B2DD +PT=43A8B490BBC75DC8D2D2F060C8672E9E +CT=67D856AF692A4BA7DEC7C8C14A37BD50 + +I=45 +KEY=2D566517DCC2D4EBADFA446DD7D497A704B8B66C88900F8D +PT=67D856AF692A4BA7DEC7C8C14A37BD50 +CT=293C5A05F31E863C6CA26DB8018751CA + +I=46 +KEY=826DFA3FD5229B9B84C61E6824CA119B681ADBD489175E47 +PT=293C5A05F31E863C6CA26DB8018751CA +CT=9421BF2E7727F49C252D644B952C76C4 + +I=47 +KEY=A5A13E0D1C01D7CF10E7A14653EDE5074D37BF9F1C3B2883 +PT=9421BF2E7727F49C252D644B952C76C4 +CT=CEE8F6FCF7CAF1C5EA9F746C10BD405B + +I=48 +KEY=923D8EE015266BA8DE0F57BAA42714C2A7A8CBF30C8668D8 +PT=CEE8F6FCF7CAF1C5EA9F746C10BD405B +CT=403220B81E6E0837ACCEDA5ACB3730BE + +I=49 +KEY=B41FA03C1181401A9E3D7702BA491CF50B6611A9C7B15866 +PT=403220B81E6E0837ACCEDA5ACB3730BE +CT=8C5D05679F78F853CF83CB8E5BBEBA44 + +I=50 +KEY=00B6D7172075472F126072652531E4A6C4E5DA279C0FE222 +PT=8C5D05679F78F853CF83CB8E5BBEBA44 +CT=6F9C74C0BB40608AAD1A1202FCAF62EB + +I=51 +KEY=BEB1F890B29E8EFE7DFC06A59E71842C69FFC82560A080C9 +PT=6F9C74C0BB40608AAD1A1202FCAF62EB +CT=B812DB4E295951BB04B1636A9CE91DDB + +I=52 +KEY=9455ABC4AC495686C5EEDDEBB728D5976D4EAB4FFC499D12 +PT=B812DB4E295951BB04B1636A9CE91DDB +CT=B164574EAECAD5A06FFB4F3E6C607D61 + +I=53 +KEY=1E9CCB2A3541F810748A8AA519E2003702B5E4719029E073 +PT=B164574EAECAD5A06FFB4F3E6C607D61 +CT=1433D23C1500EDBA0EFFD03D96E18F20 + +I=54 +KEY=F4817B9409F1F1D160B958990CE2ED8D0C4A344C06C86F53 +PT=1433D23C1500EDBA0EFFD03D96E18F20 +CT=B81C889B6FAF5DA800AEBA561992853B + +I=55 +KEY=49F7CD1535080039D8A5D002634DB0250CE48E1A1F5AEA68 +PT=B81C889B6FAF5DA800AEBA561992853B +CT=5B558B7C5916CF14FA5BC9266CFE875F + +I=56 +KEY=FCD5479474EA721783F05B7E3A5B7F31F6BF473C73A46D37 +PT=5B558B7C5916CF14FA5BC9266CFE875F +CT=49BE310D74A9980E9A78B0A8BB3BA1AB + +I=57 +KEY=6A68208CC7D6782ECA4E6A734EF2E73F6CC7F794C89FCC9C +PT=49BE310D74A9980E9A78B0A8BB3BA1AB +CT=7BD5BABAD7F1EEAA56E17BF9B6678DC8 + +I=58 +KEY=38DE1A69C03EF9C1B19BD0C9990309953A268C6D7EF84154 +PT=7BD5BABAD7F1EEAA56E17BF9B6678DC8 +CT=62448A767C344E7E7CDB02112F475EFE + +I=59 +KEY=02634EC657B436A8D3DF5ABFE53747EB46FD8E7C51BF1FAA +PT=62448A767C344E7E7CDB02112F475EFE +CT=F490A20D8B5C53E34C4CF5B7B72A4591 + +I=60 +KEY=DCDAAB8CBD526850274FF8B26E6B14080AB17BCBE6955A3B +PT=F490A20D8B5C53E34C4CF5B7B72A4591 +CT=ACFFD7CD5C01B183AB92DBB62DC088F6 + +I=61 +KEY=51EB6B7172C22A248BB02F7F326AA58BA123A07DCB55D2CD +PT=ACFFD7CD5C01B183AB92DBB62DC088F6 +CT=0BEDDFA8E7A1AC84E3E164A59D599BAB + +I=62 +KEY=4796B5FA7B22626B805DF0D7D5CB090F42C2C4D8560C4966 +PT=0BEDDFA8E7A1AC84E3E164A59D599BAB +CT=9CC82E2B6B96254345C1FDBAD667275E + +I=63 +KEY=D8E112F9657BD2BF1C95DEFCBE5D2C4C07033962806B6E38 +PT=9CC82E2B6B96254345C1FDBAD667275E +CT=75926F4D3503411CD3C059DA4FFABD62 + +I=64 +KEY=A19B892107C4F8F86907B1B18B5E6D50D4C360B8CF91D35A +PT=75926F4D3503411CD3C059DA4FFABD62 +CT=1073561CF6BA28EC57F4B7E5073D27FA + +I=65 +KEY=AEFE35F52D8D54A27974E7AD7DE445BC8337D75DC8ACF4A0 +PT=1073561CF6BA28EC57F4B7E5073D27FA +CT=83E161BA51E6F3A4588C94F7A24BA81F + +I=66 +KEY=5E41A6382F88A350FA9586172C02B618DBBB43AA6AE75CBF +PT=83E161BA51E6F3A4588C94F7A24BA81F +CT=BD693B4C49378F17322D175932B87111 + +I=67 +KEY=A2D760EE839234F147FCBD5B6535390FE99654F3585F2DAE +PT=BD693B4C49378F17322D175932B87111 +CT=101A83CF8487BEDD2C93180BB5024EC9 + +I=68 +KEY=0F463C72AF8E4B5357E63E94E1B287D2C5054CF8ED5D6367 +PT=101A83CF8487BEDD2C93180BB5024EC9 +CT=757949BE62D3328D09E2F45DF2AD095A + +I=69 +KEY=C3C0A16686A5D66B229F772A8361B55FCCE7B8A51FF06A3D +PT=757949BE62D3328D09E2F45DF2AD095A +CT=63EBBF9E15BECEC1A0885BECB3D06BF8 + +I=70 +KEY=3A0B55738CF3B3E94174C8B496DF7B9E6C6FE349AC2001C5 +PT=63EBBF9E15BECEC1A0885BECB3D06BF8 +CT=E176B5C7AFCE06E8ED0C63A4CF7E3034 + +I=71 +KEY=450F848D964934DAA0027D7339117D76816380ED635E31F1 +PT=E176B5C7AFCE06E8ED0C63A4CF7E3034 +CT=97B91F0A898E5B3A77A0883140D477BC + +I=72 +KEY=F3AF781D6EA3529237BB6279B09F264CF6C308DC238A464D +PT=97B91F0A898E5B3A77A0883140D477BC +CT=346AD1C470309DFE6CB08DCC24E17470 + +I=73 +KEY=4E43AB584BF1F8C603D1B3BDC0AFBBB29A738510076B323D +PT=346AD1C470309DFE6CB08DCC24E17470 +CT=F8B462FB7D758B3AF2CDF7D9244B738F + +I=74 +KEY=5A1F023E8F0987B4FB65D146BDDA308868BE72C9232041B2 +PT=F8B462FB7D758B3AF2CDF7D9244B738F +CT=B44D090FD0B7F762146FF6301C6DBF54 + +I=75 +KEY=FFC4BB75031165DA4F28D8496D6DC7EA7CD184F93F4DFEE6 +PT=B44D090FD0B7F762146FF6301C6DBF54 +CT=15CB042313710F2CD1C3409B5F3AF419 + +I=76 +KEY=8107240E1FB855765AE3DC6A7E1CC8C6AD12C46260770AFF +PT=15CB042313710F2CD1C3409B5F3AF419 +CT=0AB01B03F415A58D52CF7A1E40856275 + +I=77 +KEY=4493743ADE27D1D85053C7698A096D4BFFDDBE7C20F2688A +PT=0AB01B03F415A58D52CF7A1E40856275 +CT=05BE037C28719B4C4EEBEA329FAC63D5 + +I=78 +KEY=F582EC062155016255EDC415A278F607B136544EBF5E0B5F +PT=05BE037C28719B4C4EEBEA329FAC63D5 +CT=74C3C4F42B3F575C6B8D5BAD9AF0191F + +I=79 +KEY=8FAF8EEAA5E2D76B212E00E18947A15BDABB0FE325AE1240 +PT=74C3C4F42B3F575C6B8D5BAD9AF0191F +CT=92CB4A3DF34E6711FB56391F26D949AD + +I=80 +KEY=1CAD393CC06BC104B3E54ADC7A09C64A21ED36FC03775BED +PT=92CB4A3DF34E6711FB56391F26D949AD +CT=3754BB3D8C3D7370EDBA842CDF17D5C0 + +I=81 +KEY=E3AB53BB36BDFBBB84B1F1E1F634B53ACC57B2D0DC608E2D +PT=3754BB3D8C3D7370EDBA842CDF17D5C0 +CT=94EAC7FD54D228619791BCCBF9F633F4 + +I=82 +KEY=480B1D923E853259105B361CA2E69D5B5BC60E1B2596BDD9 +PT=94EAC7FD54D228619791BCCBF9F633F4 +CT=CAB29222355968E9CF492D5BF08B0999 + +I=83 +KEY=D8F6791107FB3D26DAE9A43E97BFF5B2948F2340D51DB440 +PT=CAB29222355968E9CF492D5BF08B0999 +CT=00837C78B88005288DB39452F1EB8F13 + +I=84 +KEY=6521B6B771FE24B2DA6AD8462F3FF09A193CB71224F63B53 +PT=00837C78B88005288DB39452F1EB8F13 +CT=2082F77D48A63E223A79217CD4516854 + +I=85 +KEY=9D9F3198682E2476FAE82F3B6799CEB82345966EF0A75307 +PT=2082F77D48A63E223A79217CD4516854 +CT=C5074D4B3F455346B078DAFBC1327AB6 + +I=86 +KEY=61832291235DC7C33FEF627058DC9DFE933D4C95319529B1 +PT=C5074D4B3F455346B078DAFBC1327AB6 +CT=72EE56572A2B7CEC53FC4E4FC0293D63 + +I=87 +KEY=5C2877854338D45D4D01342772F7E112C0C102DAF1BC14D2 +PT=72EE56572A2B7CEC53FC4E4FC0293D63 +CT=7350039161DF9E8E45B360E6139E4226 + +I=88 +KEY=A8225CF65297BA953E5137B613287F9C8572623CE22256F4 +PT=7350039161DF9E8E45B360E6139E4226 +CT=4339288215BE1BB87E31AF8FB35DEDC1 + +I=89 +KEY=51649B52A8458F4B7D681F3406966424FB43CDB3517FBB35 +PT=4339288215BE1BB87E31AF8FB35DEDC1 +CT=4D7AB61CC2C930CBB0DF43EEE92EBA1F + +I=90 +KEY=750E4E7E9183E2FF3012A928C45F54EF4B9C8E5DB851012A +PT=4D7AB61CC2C930CBB0DF43EEE92EBA1F +CT=1090FE663EA77DC2EC30E8F89E662918 + +I=91 +KEY=B65FBDF702246E442082574EFAF8292DA7AC66A526372832 +PT=1090FE663EA77DC2EC30E8F89E662918 +CT=14307A2CC40BDFB0413DF10F961337CA + +I=92 +KEY=7BEC3480AA0A44FF34B22D623EF3F69DE69197AAB0241FF8 +PT=14307A2CC40BDFB0413DF10F961337CA +CT=8F378E272D82DE8E63EC418912EF8642 + +I=93 +KEY=63921E8700657D6ABB85A34513712813857DD623A2CB99BA +PT=8F378E272D82DE8E63EC418912EF8642 +CT=3947DDC00E3C4D958E508DF58AB4982A + +I=94 +KEY=754B2E8355FABCAF82C27E851D4D65860B2D5BD6287F0190 +PT=3947DDC00E3C4D958E508DF58AB4982A +CT=492DB375B3CC640DD8FEDBAF2C943535 + +I=95 +KEY=E8F8C2450F8597B3CBEFCDF0AE81018BD3D3807904EB34A5 +PT=492DB375B3CC640DD8FEDBAF2C943535 +CT=D74BD4118D448B674935B80E4B1BFB93 + +I=96 +KEY=34A2C5B010AE479A1CA419E123C58AEC9AE638774FF0CF36 +PT=D74BD4118D448B674935B80E4B1BFB93 +CT=E9742B41295BC3ED3AA66E80E8718665 + +I=97 +KEY=0E11D08AA9EC81A4F5D032A00A9E4901A04056F7A7814953 +PT=E9742B41295BC3ED3AA66E80E8718665 +CT=5FB17BFE146B410F90EC922B1385D0E4 + +I=98 +KEY=B15779E61FD27B02AA61495E1EF5080E30ACC4DCB40499B7 +PT=5FB17BFE146B410F90EC922B1385D0E4 +CT=1B0CCF643F19DDBC0E3ED0EEAE83ACC1 + +I=99 +KEY=861B580225193DD5B16D863A21ECD5B23E9214321A873576 +PT=1B0CCF643F19DDBC0E3ED0EEAE83ACC1 +CT=B3A7D434E30DC0CDEE4D17BBC27B855E + +I=100 +KEY=B6DF2A8726C31D6E02CA520EC2E1157FD0DF0389D8FCB028 +PT=B3A7D434E30DC0CDEE4D17BBC27B855E +CT=57DE2345D91E26A2AB7CA88AEA23A84F + +I=101 +KEY=6976D3780B5F01E25514714B1BFF33DD7BA3AB0332DF1867 +PT=57DE2345D91E26A2AB7CA88AEA23A84F +CT=7B03541D239B569FEE7ABD8980F1BD05 + +I=102 +KEY=734CAC477A2727542E1725563864654295D9168AB22EA562 +PT=7B03541D239B569FEE7ABD8980F1BD05 +CT=5CB7E72B2E6CFF8C18AEB026FE40C2FA + +I=103 +KEY=B59171BEBC7BFB8672A0C27D16089ACE8D77A6AC4C6E6798 +PT=5CB7E72B2E6CFF8C18AEB026FE40C2FA +CT=50B9186306DA92FE785D6EB9223E43A9 + +I=104 +KEY=E460BA8A2F82DBB72219DA1E10D20830F52AC8156E502431 +PT=50B9186306DA92FE785D6EB9223E43A9 +CT=B3D8CE8B04B99CF2F82571E1588C358B + +I=105 +KEY=CE7C790CD4B34C4791C11495146B94C20D0FB9F436DC11BA +PT=B3D8CE8B04B99CF2F82571E1588C358B +CT=9845F0A5681A40A6DC3D9BCA639FE786 + +I=106 +KEY=699FE59B482743180984E4307C71D464D132223E5543F63C +PT=9845F0A5681A40A6DC3D9BCA639FE786 +CT=C7EBF5CEAAD5652563A8550020EC7070 + +I=107 +KEY=FEBE2836F5099F53CE6F11FED6A4B141B29A773E75AF864C +PT=C7EBF5CEAAD5652563A8550020EC7070 +CT=DE94A376634FE9856A84E2EE6EED86E8 + +I=108 +KEY=22BCFFB0740FC30510FBB288B5EB58C4D81E95D01B4200A4 +PT=DE94A376634FE9856A84E2EE6EED86E8 +CT=64B9917E23328A4FE1F8FDB8AE43E7F3 + +I=109 +KEY=E8491AFDF41F0DFB744223F696D9D28B39E66868B501E757 +PT=64B9917E23328A4FE1F8FDB8AE43E7F3 +CT=2C59820184ABC99E82A7F51D4E3A86A8 + +I=110 +KEY=3BE5F390D72ABE6A581BA1F712721B15BB419D75FB3B61FF +PT=2C59820184ABC99E82A7F51D4E3A86A8 +CT=387ACD0BAD539773287C209A0876581F + +I=111 +KEY=B7388762F772C83560616CFCBF218C66933DBDEFF34D39E0 +PT=387ACD0BAD539773287C209A0876581F +CT=F12D3E1F21AFB9CACAB541EFB7334438 + +I=112 +KEY=FBD600191276FA5C914C52E39E8E35AC5988FC00447E7DD8 +PT=F12D3E1F21AFB9CACAB541EFB7334438 +CT=68D2FA1BB635D9D35E4BF440335CBD80 + +I=113 +KEY=1E2B19106450AA2FF99EA8F828BBEC7F07C308407722C058 +PT=68D2FA1BB635D9D35E4BF440335CBD80 +CT=4532507D5E0227054CB36CBD3C489D53 + +I=114 +KEY=C0B60F65BAD77DA4BCACF88576B9CB7A4B7064FD4B6A5D0B +PT=4532507D5E0227054CB36CBD3C489D53 +CT=6DB8FD7DE7924B7E92CF27BC0AD11D16 + +I=115 +KEY=451836B53318CC33D11405F8912B8004D9BF434141BB401D +PT=6DB8FD7DE7924B7E92CF27BC0AD11D16 +CT=A3D5F6A8D4372B66F8D3DD9FF945DECA + +I=116 +KEY=0E57235F9B527C5172C1F350451CAB62216C9EDEB8FE9ED7 +PT=A3D5F6A8D4372B66F8D3DD9FF945DECA +CT=BEDFF233AD31EEB9943EEBF52F66AABF + +I=117 +KEY=BB7E1C438E5F36A3CC1E0163E82D45DBB552752B97983468 +PT=BEDFF233AD31EEB9943EEBF52F66AABF +CT=4531EDEC06570582755199A0C4745EA5 + +I=118 +KEY=DE70EC87811AFD32892FEC8FEE7A4059C003EC8B53EC6ACD +PT=4531EDEC06570582755199A0C4745EA5 +CT=F3189383C202A472CE238571D187F8EB + +I=119 +KEY=CA2AE67397E9238A7A377F0C2C78E42B0E2069FA826B9226 +PT=F3189383C202A472CE238571D187F8EB +CT=B48952CBAC43D0114985A9035DFF0382 + +I=120 +KEY=335EF040D622E95BCEBE2DC7803B343A47A5C0F9DF9491A4 +PT=B48952CBAC43D0114985A9035DFF0382 +CT=9B71302FDFBC47DF6276AB73D4D0D8B3 + +I=121 +KEY=683CC10DFBC6C09C55CF1DE85F8773E525D36B8A0B444917 +PT=9B71302FDFBC47DF6276AB73D4D0D8B3 +CT=69EED4A0C5428005199DF12B338393E2 + +I=122 +KEY=B86C9A2F1A978E123C21C9489AC5F3E03C4E9AA138C7DAF5 +PT=69EED4A0C5428005199DF12B338393E2 +CT=D0C2ACA653E6D7D80D32F445B0DD2347 + +I=123 +KEY=EF7E3DCDF05FFA86ECE365EEC9232438317C6EE4881AF9B2 +PT=D0C2ACA653E6D7D80D32F445B0DD2347 +CT=F373D4DBD7ADAFEF582621EC8C7CD2A2 + +I=124 +KEY=B8059C7A6BA2273E1F90B1351E8E8BD7695A4F0804662B10 +PT=F373D4DBD7ADAFEF582621EC8C7CD2A2 +CT=0AD37AFC8C929513F9BDB976E69C7CF3 + +I=125 +KEY=F5C9ECCBB672D46F1543CBC9921C1EC490E7F67EE2FA57E3 +PT=0AD37AFC8C929513F9BDB976E69C7CF3 +CT=E80B118DFB34F11DB344B6AE34EDEBC8 + +I=126 +KEY=AA67DC18543A7A88FD48DA446928EFD923A340D0D617BC2B +PT=E80B118DFB34F11DB344B6AE34EDEBC8 +CT=628D5C42DDEBA9AE4983F51D339366B4 + +I=127 +KEY=BF0C30A039C0FEE89FC58606B4C346776A20B5CDE584DA9F +PT=628D5C42DDEBA9AE4983F51D339366B4 +CT=1BE2A5A8CCA8E065557F6982AF3E056F + +I=128 +KEY=A219F6B8E2FF1AA3842723AE786BA6123F5FDC4F4ABADFF0 +PT=1BE2A5A8CCA8E065557F6982AF3E056F +CT=5E1187D78AEB34780F07905A84D2EBBA + +I=129 +KEY=851DDD078D4B7802DA36A479F280926A30584C15CE68344A +PT=5E1187D78AEB34780F07905A84D2EBBA +CT=31EE3AC2EC79D14EBCA71E760326CD74 + +I=130 +KEY=E6741084FEDEEFFEEBD89EBB1EF943248CFF5263CD4EF93E +PT=31EE3AC2EC79D14EBCA71E760326CD74 +CT=298E3A00F280BBF8364CF8D6D44CF54E + +I=131 +KEY=8A41136FE9DB1FB5C256A4BBEC79F8DCBAB3AAB519020C70 +PT=298E3A00F280BBF8364CF8D6D44CF54E +CT=39B7A0416C1F9B19C7B99A1F6A70258C + +I=132 +KEY=E1F1B622EB8BC9B1FBE104FA806663C57D0A30AA737229FC +PT=39B7A0416C1F9B19C7B99A1F6A70258C +CT=B1655FA9AB2C4956E2C56F7A6C421BE5 + +I=133 +KEY=0EE0B7E1AF7093694A845B532B4A2A939FCF5FD01F303219 +PT=B1655FA9AB2C4956E2C56F7A6C421BE5 +CT=1AD9CBB1A28F7A2A6CBC7EC98EF483FC + +I=134 +KEY=180A2BD07F77D34E505D90E289C550B9F373211991C4B1E5 +PT=1AD9CBB1A28F7A2A6CBC7EC98EF483FC +CT=6363BE57D6D587EE3ABA9FE81F3D3A10 + +I=135 +KEY=848B7408CAACF02E333E2EB55F10D757C9C9BEF18EF98BF5 +PT=6363BE57D6D587EE3ABA9FE81F3D3A10 +CT=05618580D7915AA7398EF4DB7D1F1DE3 + +I=136 +KEY=E581D7B4F84F2860365FAB3588818DF0F0474A2AF3E69616 +PT=05618580D7915AA7398EF4DB7D1F1DE3 +CT=F8D0118087404FD729F96CA6551338AD + +I=137 +KEY=6C81D6873EFFF763CE8FBAB50FC1C227D9BE268CA6F5AEBB +PT=F8D0118087404FD729F96CA6551338AD +CT=784913B38D32A7395D73AF1378A0DC56 + +I=138 +KEY=D971137D872F606EB6C6A90682F3651E84CD899FDE5572ED +PT=784913B38D32A7395D73AF1378A0DC56 +CT=D07C418BD183457B6683AE99C457FC0B + +I=139 +KEY=196BBA79E35EEC7966BAE88D53702065E24E27061A028EE6 +PT=D07C418BD183457B6683AE99C457FC0B +CT=5595D16DF7668779825BC135D1408013 + +I=140 +KEY=6F140EC274635FA2332F39E0A416A71C6015E633CB420EF5 +PT=5595D16DF7668779825BC135D1408013 +CT=1AB9F5075E063403FEFD976044C89C95 + +I=141 +KEY=926F3A2AA0BD8C952996CCE7FA10931F9EE871538F8A9260 +PT=1AB9F5075E063403FEFD976044C89C95 +CT=6DF413E53FCEDA296D7ABA796179D600 + +I=142 +KEY=740F74BF0E0C38154462DF02C5DE4936F392CB2AEEF34460 +PT=6DF413E53FCEDA296D7ABA796179D600 +CT=0D0F499B0D51948A9CCBC4B6531A05F7 + +I=143 +KEY=2500C9B63042B24B496D9699C88FDDBC6F590F9CBDE94197 +PT=0D0F499B0D51948A9CCBC4B6531A05F7 +CT=85833A1072B6A0ED932D4D89D53A785A + +I=144 +KEY=FCB377C07622271FCCEEAC89BA397D51FC74421568D339CD +PT=85833A1072B6A0ED932D4D89D53A785A +CT=545EDE1A4B737F1E51CBDAE311E91D5C + +I=145 +KEY=BB108ABE391C394E98B07293F14A024FADBF98F6793A2491 +PT=545EDE1A4B737F1E51CBDAE311E91D5C +CT=DA8CC635CF1450685DDAAA5A56BC3BD9 + +I=146 +KEY=34F8623EC93A6C2A423CB4A63E5E5227F06532AC2F861F48 +PT=DA8CC635CF1450685DDAAA5A56BC3BD9 +CT=FE73162BF90B52DEE7D0EA9D73F8444D + +I=147 +KEY=5E3CB25583365D5EBC4FA28DC75500F917B5D8315C7E5B05 +PT=FE73162BF90B52DEE7D0EA9D73F8444D +CT=BC75D12F66C232E1979D0F6C3E1ED8F1 + +I=148 +KEY=EABE655116470AE1003A73A2A19732188028D75D626083F4 +PT=BC75D12F66C232E1979D0F6C3E1ED8F1 +CT=661A3FA0530BF47C266D609FE01DAF48 + +I=149 +KEY=97A1B8E97CF217C366204C02F29CC664A645B7C2827D2CBC +PT=661A3FA0530BF47C266D609FE01DAF48 +CT=791144514CF8E4CC15BC6ADE3291F9CD + +I=150 +KEY=5189DC6F535B5A091F310853BE6422A8B3F9DD1CB0ECD571 +PT=791144514CF8E4CC15BC6ADE3291F9CD +CT=4369FDB3626F399A6526C476373A52D4 + +I=151 +KEY=21CD36EDB27428AB5C58F5E0DC0B1B32D6DF196A87D687A5 +PT=4369FDB3626F399A6526C476373A52D4 +CT=4C8869494C044703CFDD09F83B2208AA + +I=152 +KEY=85C08C7D4667AE3710D09CA9900F5C3119021092BCF48F0F +PT=4C8869494C044703CFDD09F83B2208AA +CT=06BC45BDB38A7028CB2D189E9E0C3046 + +I=153 +KEY=807182BD7E1F29BE166CD91423852C19D22F080C22F8BF49 +PT=06BC45BDB38A7028CB2D189E9E0C3046 +CT=74AFD5F37F8F0712710585FB8DB22FF8 + +I=154 +KEY=1AF15D0DE00CEF3F62C30CE75C0A2B0BA32A8DF7AF4A90B1 +PT=74AFD5F37F8F0712710585FB8DB22FF8 +CT=B1A4EE894A12794E0C1A286DDBC01CFD + +I=155 +KEY=E0732BA619DCF2F5D367E26E16185245AF30A59A748A8C4C +PT=B1A4EE894A12794E0C1A286DDBC01CFD +CT=0EA90279135DFFC7F58DB959F9E8BFE1 + +I=156 +KEY=AE8779E669BFF77EDDCEE0170545AD825ABD1CC38D6233AD +PT=0EA90279135DFFC7F58DB959F9E8BFE1 +CT=3717C67E520D87778350E62525C01730 + +I=157 +KEY=79D13142BE9066A2EAD9266957482AF5D9EDFAE6A8A2249D +PT=3717C67E520D87778350E62525C01730 +CT=A8F96DA7AE81EF8810A317AB4C9B82A9 + +I=158 +KEY=597D70828E56003942204BCEF9C9C57DC94EED4DE439A634 +PT=A8F96DA7AE81EF8810A317AB4C9B82A9 +CT=8C373A065986BAC9E345475F5D83FBCF + +I=159 +KEY=96C8CF3884D5DA18CE1771C8A04F7FB42A0BAA12B9BA5DFB +PT=8C373A065986BAC9E345475F5D83FBCF +CT=8E4D562CBEDC360EFB25B857DD4C4FF2 + +I=160 +KEY=5A0A29B58F17F9F9405A27E41E9349BAD12E124564F61209 +PT=8E4D562CBEDC360EFB25B857DD4C4FF2 +CT=192CCD79E3B4C8F5617D1F55B789B7A3 + +I=161 +KEY=29A4692EDE3EAABE5976EA9DFD27814FB0530D10D37FA5AA +PT=192CCD79E3B4C8F5617D1F55B789B7A3 +CT=8A5F181E1748C98121D1C22204591B23 + +I=162 +KEY=5E5CA30210E78677D329F283EA6F48CE9182CF32D726BE89 +PT=8A5F181E1748C98121D1C22204591B23 +CT=14512A4997094A0536594E63ACC5EF4A + +I=163 +KEY=7DA5F9C99B68DFB0C778D8CA7D6602CBA7DB81517BE351C3 +PT=14512A4997094A0536594E63ACC5EF4A +CT=F91BA751D5E2ADC074FC6CC14476DE67 + +I=164 +KEY=658144C57CCFDAD83E637F9BA884AF0BD327ED903F958FA4 +PT=F91BA751D5E2ADC074FC6CC14476DE67 +CT=5F7FED22BABA25D48C95C4E2CAEDB3F4 + +I=165 +KEY=13C5D7A44396F6FD611C92B9123E8ADF5FB22972F5783C50 +PT=5F7FED22BABA25D48C95C4E2CAEDB3F4 +CT=0FCFB3CB93B2E7FDF7E156486929BD17 + +I=166 +KEY=99DBAC1D5D268DB06ED32172818C6D22A8537F3A9C518147 +PT=0FCFB3CB93B2E7FDF7E156486929BD17 +CT=3E16265A02271FF68AE6310A6BFDEE60 + +I=167 +KEY=A8876A49E2F1CC5250C5072883AB72D422B54E30F7AC6F27 +PT=3E16265A02271FF68AE6310A6BFDEE60 +CT=1657BF722B57D083D8864B6447317E05 + +I=168 +KEY=0A615A71BC2BE3E94692B85AA8FCA257FA330554B09D1122 +PT=1657BF722B57D083D8864B6447317E05 +CT=018B742E941E27C547451B9E41F245F5 + +I=169 +KEY=6AE11571E3D54C4B4719CC743CE28592BD761ECAF16F54D7 +PT=018B742E941E27C547451B9E41F245F5 +CT=8C5BB61774502B6A9C44BEE8D6C44A63 + +I=170 +KEY=DCE75079013F0865CB427A6348B2AEF82132A02227AB1EB4 +PT=8C5BB61774502B6A9C44BEE8D6C44A63 +CT=361D3B51C751298194CB1AA32C0A86EE + +I=171 +KEY=E73232D50D457866FD5F41328FE38779B5F9BA810BA1985A +PT=361D3B51C751298194CB1AA32C0A86EE +CT=7B734F34DD4F332CBE5CFC7659C390BF + +I=172 +KEY=BEEF9073227655EB862C0E0652ACB4550BA546F7526208E5 +PT=7B734F34DD4F332CBE5CFC7659C390BF +CT=63CCC9CE5DADA5B5AC68870E6C675943 + +I=173 +KEY=1E9078C198526C1DE5E0C7C80F0111E0A7CDC1F93E0551A6 +PT=63CCC9CE5DADA5B5AC68870E6C675943 +CT=7BBC6F7B62807CBE1C93CADB5E6CAE0A + +I=174 +KEY=AD26AC70784FF1B99E5CA8B36D816D5EBB5E0B226069FFAC +PT=7BBC6F7B62807CBE1C93CADB5E6CAE0A +CT=E95B0C766EF9049163D3A249E196DDB8 + +I=175 +KEY=E17835A277F1D1EE7707A4C5037869CFD88DA96B81FF2214 +PT=E95B0C766EF9049163D3A249E196DDB8 +CT=968263CBCDB4582FC9CDFD0C9FD0B4F0 + +I=176 +KEY=22F9EB31E67C62DBE185C70ECECC31E0114054671E2F96E4 +PT=968263CBCDB4582FC9CDFD0C9FD0B4F0 +CT=9F573A339DFA07B844E4034718A4FE88 + +I=177 +KEY=0FEC8766966A42DA7ED2FD3D5336365855A45720068B686C +PT=9F573A339DFA07B844E4034718A4FE88 +CT=A0809BA3A742C0EB1BDA613B7472F56A + +I=178 +KEY=98E655519C9A8A95DE52669EF474F6B34E7E361B72F99D06 +PT=A0809BA3A742C0EB1BDA613B7472F56A +CT=9BF1D85440818035FA6AC36E5A5F00A7 + +I=179 +KEY=A8D37BE0EB386F8045A3BECAB4F57686B414F57528A69DA1 +PT=9BF1D85440818035FA6AC36E5A5F00A7 +CT=924E309AC04A655C50980360914E9830 + +I=180 +KEY=7D89F156EA181E92D7ED8E5074BF13DAE48CF615B9E80591 +PT=924E309AC04A655C50980360914E9830 +CT=427819CDAE419A046D4586FF5A784A1C + +I=181 +KEY=B028A265666F69629595979DDAFE89DE89C970EAE3904F8D +PT=427819CDAE419A046D4586FF5A784A1C +CT=D8B51EEC0A6A6D17F1E476C922AD8548 + +I=182 +KEY=DF20B45B990C5E734D208971D094E4C9782D0623C13DCAC5 +PT=D8B51EEC0A6A6D17F1E476C922AD8548 +CT=7823F1BBA96105168195CDAC34AB5315 + +I=183 +KEY=AF4C64F7E4AA6DE2350378CA79F5E1DFF9B8CB8FF59699D0 +PT=7823F1BBA96105168195CDAC34AB5315 +CT=85DD0256BC29EAA867DB77C1A049574D + +I=184 +KEY=4047F74604E37A00B0DE7A9CC5DC0B779E63BC4E55DFCE9D +PT=85DD0256BC29EAA867DB77C1A049574D +CT=64C1880D34408CB1A92BBA354941D5B6 + +I=185 +KEY=9C3BF36E47110C08D41FF291F19C87C63748067B1C9E1B2B +PT=64C1880D34408CB1A92BBA354941D5B6 +CT=25B80866FE3198C775F64C412E734348 + +I=186 +KEY=FAE7368F99242159F1A7FAF70FAD1F0142BE4A3A32ED5863 +PT=25B80866FE3198C775F64C412E734348 +CT=8D3D7E9A195363C96334C48120BC343A + +I=187 +KEY=5F48BD86A9C4DC897C9A846D16FE7CC8218A8EBB12516C59 +PT=8D3D7E9A195363C96334C48120BC343A +CT=E886EEA0F2D556D693DC94FFC588D1F4 + +I=188 +KEY=B7406993C120EA20941C6ACDE42B2A1EB2561A44D7D9BDAD +PT=E886EEA0F2D556D693DC94FFC588D1F4 +CT=76CB89CBB935D422DED9784D4548A84F + +I=189 +KEY=4DB740C3FA55F4ABE2D7E3065D1EFE3C6C8F6209929115E2 +PT=76CB89CBB935D422DED9784D4548A84F +CT=93D7AC7B18A1196D5C166203C44A43D3 + +I=190 +KEY=353A0293DEFB648071004F7D45BFE7513099000A56DB5631 +PT=93D7AC7B18A1196D5C166203C44A43D3 +CT=8982BD77485524EE9E49769591E922CE + +I=191 +KEY=F6FC1F7E838CD8A7F882F20A0DEAC3BFAED0769FC73274FF +PT=8982BD77485524EE9E49769591E922CE +CT=89012A1E3F7669C76C5F5F4987108662 + +I=192 +KEY=A1AA84E01EBC3E837183D814329CAA78C28F29D64022F29D +PT=89012A1E3F7669C76C5F5F4987108662 +CT=139E37ADA17990054AF8EF5B717E884B + +I=193 +KEY=C631229E9871F2AC621DEFB993E53A7D8877C68D315C7AD6 +PT=139E37ADA17990054AF8EF5B717E884B +CT=CEC8F9C90B2E393BDA4602C2A83F953C + +I=194 +KEY=824604723CD82F95ACD5167098CB03465231C44F9963EFEA +PT=CEC8F9C90B2E393BDA4602C2A83F953C +CT=2A2E1344AE4C6BA40568E170BF67FD74 + +I=195 +KEY=2B17489FA71F683B86FB0534368768E25759253F2604129E +PT=2A2E1344AE4C6BA40568E170BF67FD74 +CT=7402AC6982DBB0BED678746E4523556C + +I=196 +KEY=DA9C0CF5A89D3D94F2F9A95DB45CD85C81215151632747F2 +PT=7402AC6982DBB0BED678746E4523556C +CT=36A36B5B55F950F00B9F3E31156BFD65 + +I=197 +KEY=543619886B56830BC45AC206E1A588AC8ABE6F60764CBA97 +PT=36A36B5B55F950F00B9F3E31156BFD65 +CT=D7B36A117E824A49A5944C37BEE27F06 + +I=198 +KEY=9494630598E7618213E9A8179F27C2E52F2A2357C8AEC591 +PT=D7B36A117E824A49A5944C37BEE27F06 +CT=2D60BC0BC950EEE7E36D50E971CF68D0 + +I=199 +KEY=B0328218DF523A0C3E89141C56772C02CC4773BEB961AD41 +PT=2D60BC0BC950EEE7E36D50E971CF68D0 +CT=49A4643E535F45A1ABDEF41ABABBE268 + +I=200 +KEY=5E3FD7ACD8EF334D772D7022052869A3679987A403DA4F29 +PT=49A4643E535F45A1ABDEF41ABABBE268 +CT=D5EEB5CC40AF8612708BAABE85685E4C + +I=201 +KEY=A232D0267D606002A2C3C5EE4587EFB117122D1A86B21165 +PT=D5EEB5CC40AF8612708BAABE85685E4C +CT=3F5B875DE202C5441165FE5C5CA2D258 + +I=202 +KEY=844ED6FAFA342BFE9D9842B3A7852AF50677D346DA10C33D +PT=3F5B875DE202C5441165FE5C5CA2D258 +CT=9B5F0210E0EC623C6ACF1C0BC06EBF51 + +I=203 +KEY=109F8CEC689E0F5306C740A3476948C96CB8CF4D1A7E7C6C +PT=9B5F0210E0EC623C6ACF1C0BC06EBF51 +CT=E57015FAB0006446E544704DB6629059 + +I=204 +KEY=D9ABCBAC4B271B04E3B75559F7692C8F89FCBF00AC1CEC35 +PT=E57015FAB0006446E544704DB6629059 +CT=85F0DF6B1ED933E87F6A9F609D516346 + +I=205 +KEY=09915869AE1F57F766478A32E9B01F67F6962060314D8F73 +PT=85F0DF6B1ED933E87F6A9F609D516346 +CT=471B931539C155478A1D4B9BA50DCE43 + +I=206 +KEY=BFB70AA6C4F05C1D215C1927D0714A207C8B6BFB94404130 +PT=471B931539C155478A1D4B9BA50DCE43 +CT=9AC55C1CC77E7B59CC9204898A38CEA7 + +I=207 +KEY=660972D79B056F14BB99453B170F3179B0196F721E788F97 +PT=9AC55C1CC77E7B59CC9204898A38CEA7 +CT=19B00FEB13145F9F356173B42184D516 + +I=208 +KEY=F09576EB17FB1A07A2294AD0041B6EE685781CC63FFC5A81 +PT=19B00FEB13145F9F356173B42184D516 +CT=5F1379E25F6DD8653B73F58E738D6243 + +I=209 +KEY=8D170BBC5E3662BEFD3A33325B76B683BE0BE9484C7138C2 +PT=5F1379E25F6DD8653B73F58E738D6243 +CT=AEF55C09E7AD76CC9BA7B83874A0A86B + +I=210 +KEY=1A7BD2572D3CDB8C53CF6F3BBCDBC04F25AC517038D190A9 +PT=AEF55C09E7AD76CC9BA7B83874A0A86B +CT=6BEF52E6D86DC15D2A03B5CB3EBAB130 + +I=211 +KEY=B4BC0603F59BE3D038203DDD64B601120FAFE4BB066B2199 +PT=6BEF52E6D86DC15D2A03B5CB3EBAB130 +CT=FDC093FFED096B7812E77E23AD9C7C71 + +I=212 +KEY=C00A0DDA74D55250C5E0AE2289BF6A6A1D489A98ABF75DE8 +PT=FDC093FFED096B7812E77E23AD9C7C71 +CT=072625CB0C022827E195DE8AB4FE7E0C + +I=213 +KEY=6534CBAB46880CE0C2C68BE985BD424DFCDD44121F0923E4 +PT=072625CB0C022827E195DE8AB4FE7E0C +CT=11AA47C5557437AEE8A8BE31A849A047 + +I=214 +KEY=C204AFE794D81224D36CCC2CD0C975E31475FA23B74083A3 +PT=11AA47C5557437AEE8A8BE31A849A047 +CT=4C91B3031567DFFC22829CBC3C419B6D + +I=215 +KEY=01A4820CC4D281B99FFD7F2FC5AEAA1F36F7669F8B0118CE +PT=4C91B3031567DFFC22829CBC3C419B6D +CT=54C0F95B0179CB753917A2592F58BD77 + +I=216 +KEY=B5C1DD77446C8FD1CB3D8674C4D7616A0FE0C4C6A459A5B9 +PT=54C0F95B0179CB753917A2592F58BD77 +CT=A2A19A98250E432131F9EF4AE473677F + +I=217 +KEY=9FDC1167AC2D1A51699C1CECE1D9224B3E192B8C402AC2C6 +PT=A2A19A98250E432131F9EF4AE473677F +CT=9B5780CA9669A92688F54887E303F2D3 + +I=218 +KEY=C734A73F4A32D311F2CB9C2677B08B6DB6EC630BA3293015 +PT=9B5780CA9669A92688F54887E303F2D3 +CT=F1750745D1E74E41A07B99482ECABAAA + +I=219 +KEY=1612B86730F487EF03BE9B63A657C52C1697FA438DE38ABF +PT=F1750745D1E74E41A07B99482ECABAAA +CT=30F510DBDDAEC6FC0D2504C11DF23CFA + +I=220 +KEY=D52E3B50F72B085D334B8BB87BF903D01BB2FE829011B645 +PT=30F510DBDDAEC6FC0D2504C11DF23CFA +CT=64998C3018185D722477A2DBFB84ABB8 + +I=221 +KEY=7F9F2A23D320792E57D2078863E15EA23FC55C596B951DFD +PT=64998C3018185D722477A2DBFB84ABB8 +CT=9293A4FF9ED5D57D81BB8A63381BF66A + +I=222 +KEY=B529B6E7080E0AE4C541A377FD348BDFBE7ED63A538EEB97 +PT=9293A4FF9ED5D57D81BB8A63381BF66A +CT=A389ABCF609B41F28CC3188B2C126915 + +I=223 +KEY=A5C4C3A89459F79566C808B89DAFCA2D32BDCEB17F9C8282 +PT=A389ABCF609B41F28CC3188B2C126915 +CT=5F4BC60608A3DF788631EBB66763E7DF + +I=224 +KEY=F59456291C6CF0C83983CEBE950C1555B48C250718FF655D +PT=5F4BC60608A3DF788631EBB66763E7DF +CT=EFDE2113118EDFD5A15D4DFA1C1E79B4 + +I=225 +KEY=9A4CD87E44EA7DEED65DEFAD8482CA8015D168FD04E11CE9 +PT=EFDE2113118EDFD5A15D4DFA1C1E79B4 +CT=2526BA56DA8A9F9A5799A9D2BE96AEBA + +I=226 +KEY=A19D5DFAEC1C9B9DF37B55FB5E08551A4248C12FBA77B253 +PT=2526BA56DA8A9F9A5799A9D2BE96AEBA +CT=83F237712EF89A7B1E84D69DEFC9B9B9 + +I=227 +KEY=C48B0103470544867089628A70F0CF615CCC17B255BE0BEA +PT=83F237712EF89A7B1E84D69DEFC9B9B9 +CT=13B7E26895FEEFE2356306D8D822DDD3 + +I=228 +KEY=B366B0FE6BB3DB17633E80E2E50E208369AF116A8D9CD639 +PT=13B7E26895FEEFE2356306D8D822DDD3 +CT=BF8C47559B230A3311543BEAA90D4DA1 + +I=229 +KEY=BE5A735484B72645DCB2C7B77E2D2AB078FB2A8024919B98 +PT=BF8C47559B230A3311543BEAA90D4DA1 +CT=D3C9AFCED64F46AC74FFF73302DE10EB + +I=230 +KEY=1DFD852FE9F131840F7B6879A8626C1C0C04DDB3264F8B73 +PT=D3C9AFCED64F46AC74FFF73302DE10EB +CT=004386EABD8F3C60971D34B5A5F220F8 + +I=231 +KEY=BB9831D80259A5A40F38EE9315ED507C9B19E90683BDAB8B +PT=004386EABD8F3C60971D34B5A5F220F8 +CT=119A244F6A3ED1947A764CFE96568213 + +I=232 +KEY=93B0F09E78E610741EA2CADC7FD381E8E16FA5F815EB2998 +PT=119A244F6A3ED1947A764CFE96568213 +CT=4C8D061BD62737E674DDCACEFC37DA11 + +I=233 +KEY=43E5036A09590404522FCCC7A9F4B60E95B26F36E9DCF389 +PT=4C8D061BD62737E674DDCACEFC37DA11 +CT=7B5EFE44536B5AB9CF75A457BB8C2417 + +I=234 +KEY=869CF7BF36FBB5D829713283FA9FECB75AC7CB615250D79E +PT=7B5EFE44536B5AB9CF75A457BB8C2417 +CT=25771915A1C0F8149634963E1C91BD26 + +I=235 +KEY=C9BD373897A760E30C062B965B5F14A3CCF35D5F4EC16AB8 +PT=25771915A1C0F8149634963E1C91BD26 +CT=8BB2BC7E7BAAEA1AAF7A9E285BEEB8F1 + +I=236 +KEY=D2EE543EACA1592687B497E820F5FEB96389C377152FD249 +PT=8BB2BC7E7BAAEA1AAF7A9E285BEEB8F1 +CT=05556B6AB68D2DABCDB32FB724D44F57 + +I=237 +KEY=9583438F7194754F82E1FC829678D312AE3AECC031FB9D1E +PT=05556B6AB68D2DABCDB32FB724D44F57 +CT=A4CE8197B0EAE6AD57D5A0630D0CABD0 + +I=238 +KEY=A5B96A3EFB2EF0C7262F7D15269235BFF9EF4CA33CF736CE +PT=A4CE8197B0EAE6AD57D5A0630D0CABD0 +CT=8E40F09865AA8EA114EA7F36E11815C3 + +I=239 +KEY=8E7A04E47969F5DBA86F8D8D4338BB1EED053395DDEF230D +PT=8E40F09865AA8EA114EA7F36E11815C3 +CT=194A76947319ED92D96D292684C29B5A + +I=240 +KEY=E52197304B446A01B125FB193021568C34681AB3592DB857 +PT=194A76947319ED92D96D292684C29B5A +CT=93526BBB6405BDEA68AC01F1C807EBF7 + +I=241 +KEY=DA4552EC2C076DC3227790A25424EB665CC41B42912A53A0 +PT=93526BBB6405BDEA68AC01F1C807EBF7 +CT=59860971F900B739B36CB97D35B082D1 + +I=242 +KEY=E7329ED9491CA8227BF199D3AD245C5FEFA8A23FA49AD171 +PT=59860971F900B739B36CB97D35B082D1 +CT=92F430D5B1F35B469ECDDFDCB2A110F5 + +I=243 +KEY=1ADC19560D9AEF09E905A9061CD7071971657DE3163BC184 +PT=92F430D5B1F35B469ECDDFDCB2A110F5 +CT=F81D2505FD9A569A71502B23894DA535 + +I=244 +KEY=6ED932F2BEBD486911188C03E14D5183003556C09F7664B1 +PT=F81D2505FD9A569A71502B23894DA535 +CT=93BACD72A0E761D34E8603FC44F6BA5E + +I=245 +KEY=F0A52339F0C68F5782A2417141AA30504EB3553CDB80DEEF +PT=93BACD72A0E761D34E8603FC44F6BA5E +CT=631DB808708B5EBB54A2DE6B62519235 + +I=246 +KEY=0B262E7EA7109C03E1BFF97931216EEB1A118B57B9D14CDA +PT=631DB808708B5EBB54A2DE6B62519235 +CT=C402023DA5F2F230FEEACE1C5F8B5390 + +I=247 +KEY=1E7EB042CA0EA74F25BDFB4494D39CDBE4FB454BE65A1F4A +PT=C402023DA5F2F230FEEACE1C5F8B5390 +CT=CAD88E79E0AB4A3B324F6D3ABBEA211C + +I=248 +KEY=215E3E970705BE3DEF65753D7478D6E0D6B428715DB03E56 +PT=CAD88E79E0AB4A3B324F6D3ABBEA211C +CT=1B2303C4FEB78105B5BF35BC1C5C2FF9 + +I=249 +KEY=512CE443B55593D9F44676F98ACF57E5630B1DCD41EC11AF +PT=1B2303C4FEB78105B5BF35BC1C5C2FF9 +CT=06CAE1EED611AF829C83216697F8AEFA + +I=250 +KEY=533251960972B2BFF28C97175CDEF867FF883CABD614BF55 +PT=06CAE1EED611AF829C83216697F8AEFA +CT=170194A7E4E85B0A339BF86460E5ABC6 + +I=251 +KEY=B484A158FBC3D31FE58D03B0B836A36DCC13C4CFB6F11493 +PT=170194A7E4E85B0A339BF86460E5ABC6 +CT=AF7014D972F55B0CD759CAFBC0D9483B + +I=252 +KEY=C470759A6962C1934AFD1769CAC3F8611B4A0E3476285CA8 +PT=AF7014D972F55B0CD759CAFBC0D9483B +CT=E8BD547419DADD980682B701CCEF3C7E + +I=253 +KEY=D27A5BF9DD3B6F61A240431DD31925F91DC8B935BAC760D6 +PT=E8BD547419DADD980682B701CCEF3C7E +CT=E8F9CFAA891A471EBBC5806F03E0E18A + +I=254 +KEY=041C2FF776BAF2334AB98CB75A0362E7A60D395AB927815C +PT=E8F9CFAA891A471EBBC5806F03E0E18A +CT=F90F888C03CEBFC9A807DF2100488B24 + +I=255 +KEY=9BB4307835C91BA4B3B6043B59CDDD2E0E0AE67BB96F0A78 +PT=F90F888C03CEBFC9A807DF2100488B24 +CT=7874C642B44810334C2CF572DA0DEF68 + +I=256 +KEY=56E742B84F293B68CBC2C279ED85CD1D422613096362E510 +PT=7874C642B44810334C2CF572DA0DEF68 +CT=064513BBD5E667B651B93502E86B6C43 + +I=257 +KEY=66E28C26E01570FCCD87D1C23863AAAB139F260B8B098953 +PT=064513BBD5E667B651B93502E86B6C43 +CT=D461A03D7D8669BBC32430D00D437E59 + +I=258 +KEY=5674831937969B7619E671FF45E5C310D0BB16DB864AF70A +PT=D461A03D7D8669BBC32430D00D437E59 +CT=0A07F858DBD1909FF970C95ED7287FB3 + +I=259 +KEY=D45BCD0FF3E14A7013E189A79E34538F29CBDF85516288B9 +PT=0A07F858DBD1909FF970C95ED7287FB3 +CT=C2E45D29C1DF02CB4D768682ADD73E6B + +I=260 +KEY=40F81EBEF03AAAABD105D48E5FEB514464BD5907FCB5B6D2 +PT=C2E45D29C1DF02CB4D768682ADD73E6B +CT=01E21E496061DAC195F24F6D1CF22B8A + +I=261 +KEY=99C8875EE8221C3FD0E7CAC73F8A8B85F14F166AE0479D58 +PT=01E21E496061DAC195F24F6D1CF22B8A +CT=71D1C35E1126F6907CDB5414B8C97E84 + +I=262 +KEY=F1582613B3466D7FA13609992EAC7D158D94427E588EE3DC +PT=71D1C35E1126F6907CDB5414B8C97E84 +CT=8B7BBAF63C993D4BBB098A22D00C5608 + +I=263 +KEY=4679A2F69656CFD32A4DB36F1235405E369DC85C8882B5D4 +PT=8B7BBAF63C993D4BBB098A22D00C5608 +CT=651B19F5C1B67FC52151E7C5F1246485 + +I=264 +KEY=A404FC3490DFC7244F56AA9AD3833F9B17CC2F9979A6D151 +PT=651B19F5C1B67FC52151E7C5F1246485 +CT=158F0AE36B5585868DFB998520318FEB + +I=265 +KEY=F7DCCA4394981F2D5AD9A079B8D6BA1D9A37B61C59975EBA +PT=158F0AE36B5585868DFB998520318FEB +CT=B62EC94231405F3FB0D160FBFF2DE27E + +I=266 +KEY=1F38711C9B6BD060ECF7693B8996E5222AE6D6E7A6BABCC4 +PT=B62EC94231405F3FB0D160FBFF2DE27E +CT=464AFFA35373CEE71523FF0AFBFB1F51 + +I=267 +KEY=6B846AAC0C448654AABD9698DAE52BC53FC529ED5D41A395 +PT=464AFFA35373CEE71523FF0AFBFB1F51 +CT=C729EA9A05D5482491CE31DBBC03CE24 + +I=268 +KEY=BD539A9B4001B6876D947C02DF3063E1AE0B1836E1426DB1 +PT=C729EA9A05D5482491CE31DBBC03CE24 +CT=C755C048ADAD22A628B077163097415F + +I=269 +KEY=18B524EEF606589DAAC1BC4A729D414786BB6F20D1D52CEE +PT=C755C048ADAD22A628B077163097415F +CT=2DADB8F8FC76D8C997627449E44D14B2 + +I=270 +KEY=3C2C6A047706E3DD876C04B28EEB998E11D91B693598385C +PT=2DADB8F8FC76D8C997627449E44D14B2 +CT=2D7109526C2F1B5D08DD356B163498D7 + +I=271 +KEY=40593D776B6C5920AA1D0DE0E2C482D319042E0223ACA08B +PT=2D7109526C2F1B5D08DD356B163498D7 +CT=D9C1D988ABD5C892B2E5BA7BF4F584D3 + +I=272 +KEY=72B53E4711B3DE9873DCD46849114A41ABE19479D7592458 +PT=D9C1D988ABD5C892B2E5BA7BF4F584D3 +CT=0A32E78440A8AE4A3FF74B20A3F5F7DE + +I=273 +KEY=C0BEF126899B305B79EE33EC09B9E40B9416DF5974ACD386 +PT=0A32E78440A8AE4A3FF74B20A3F5F7DE +CT=E7AA36688851D8E4E08E9EFE6987C571 + +I=274 +KEY=D16257EFEE63CC399E44058481E83CEF749841A71D2B16F7 +PT=E7AA36688851D8E4E08E9EFE6987C571 +CT=0E3E2E99FFA84F8A69CAA897017DD09C + +I=275 +KEY=3509E5A7A66648B9907A2B1D7E4073651D52E9301C56C66B +PT=0E3E2E99FFA84F8A69CAA897017DD09C +CT=96766B7F6E78537994466BDC62607C85 + +I=276 +KEY=46BC3EB6FA22C8AC060C40621038201C891482EC7E36BAEE +PT=96766B7F6E78537994466BDC62607C85 +CT=AA42980BBABA21DACE6D9FCD28A5B0BA + +I=277 +KEY=26FC66C5E5C6E585AC4ED869AA8201C647791D2156930A54 +PT=AA42980BBABA21DACE6D9FCD28A5B0BA +CT=EC057F10222EC91403E1B6CEFCE3556A + +I=278 +KEY=91FBDF7B24B0FEB4404BA77988ACC8D24498ABEFAA705F3E +PT=EC057F10222EC91403E1B6CEFCE3556A +CT=E6E91EC6B977C3547D08F717F6702E80 + +I=279 +KEY=5BD8360BB35CE209A6A2B9BF31DB0B8639905CF85C0071BE +PT=E6E91EC6B977C3547D08F717F6702E80 +CT=DF9BE6A5A61CC4B66C76447202CBFADA + +I=280 +KEY=E58D0EFAB72342BD79395F1A97C7CF3055E6188A5ECB8B64 +PT=DF9BE6A5A61CC4B66C76447202CBFADA +CT=8466FA526E1038CC14A2EC6D85FC4EDF + +I=281 +KEY=7EB51DD43B05BB26FD5FA548F9D7F7FC4144F4E7DB37C5BB +PT=8466FA526E1038CC14A2EC6D85FC4EDF +CT=5C5A965E386B16D50F3487D54C04AA6B + +I=282 +KEY=8F4BEBA429FE57C4A1053316C1BCE1294E70733297336FD0 +PT=5C5A965E386B16D50F3487D54C04AA6B +CT=BCD57B57FAA6E3F81660113345CD24F9 + +I=283 +KEY=4A5DA421D27E62821DD048413B1A02D158106201D2FE4B29 +PT=BCD57B57FAA6E3F81660113345CD24F9 +CT=7450D38B3A6D8C4987EE3F7F71C68FFC + +I=284 +KEY=77934AE2BB39BC4469809BCA01778E98DFFE5D7EA338C4D5 +PT=7450D38B3A6D8C4987EE3F7F71C68FFC +CT=A6D1D5A31BAB1CE9F027376539B2AAE2 + +I=285 +KEY=2C6FD4455E96F2F6CF514E691ADC92712FD96A1B9A8A6E37 +PT=A6D1D5A31BAB1CE9F027376539B2AAE2 +CT=10894E2E6275D172259D4C23332508B9 + +I=286 +KEY=2608AB9AA8CED631DFD8004778A943030A442638A9AF668E +PT=10894E2E6275D172259D4C23332508B9 +CT=53C2AB8E42B4EF7FF659D3FB251453C7 + +I=287 +KEY=68840BD9639AC3128C1AABC93A1DAC7CFC1DF5C38CBB3549 +PT=53C2AB8E42B4EF7FF659D3FB251453C7 +CT=3A9C38D026561B83B0F3E7B566C66CD2 + +I=288 +KEY=EFCDF07C0E70D051B68693191C4BB7FF4CEE1276EA7D599B +PT=3A9C38D026561B83B0F3E7B566C66CD2 +CT=B9F7E495B96BE7C0307D8F7A53200193 + +I=289 +KEY=87DFC62793B45EF60F71778CA520503F7C939D0CB95D5808 +PT=B9F7E495B96BE7C0307D8F7A53200193 +CT=2425FE8AAA7ED06A5FFEC11D7B289891 + +I=290 +KEY=5FD78DA64A9F50142B5489060F5E8055236D5C11C275C099 +PT=2425FE8AAA7ED06A5FFEC11D7B289891 +CT=93BC83BCF69DBB256C27AF250FDEFAEB + +I=291 +KEY=81C88579E065FD16B8E80ABAF9C33B704F4AF334CDAB3A72 +PT=93BC83BCF69DBB256C27AF250FDEFAEB +CT=A1AF953D4BD1A474B1173D4686EBB8CF + +I=292 +KEY=DEE7FFE9A3814D2B19479F87B2129F04FE5DCE724B4082BD +PT=A1AF953D4BD1A474B1173D4686EBB8CF +CT=00AAC1CD74952011A03714A6BB091653 + +I=293 +KEY=8331CC8136829F1E19ED5E4AC687BF155E6ADAD4F04994EE +PT=00AAC1CD74952011A03714A6BB091653 +CT=00B92CBFFC3589CEB3ECAA7D221C3F0B + +I=294 +KEY=FF862EBFECC11E93195472F53AB236DBED8670A9D255ABE5 +PT=00B92CBFFC3589CEB3ECAA7D221C3F0B +CT=2E07858E94AD300A35448EFA848A767A + +I=295 +KEY=18B8678C5497708E3753F77BAE1F06D1D8C2FE5356DFDD9F +PT=2E07858E94AD300A35448EFA848A767A +CT=B02F0C98F3B7BB7807F35F6DFD925238 + +I=296 +KEY=C90D1E18331CA38F877CFBE35DA8BDA9DF31A13EAB4D8FA7 +PT=B02F0C98F3B7BB7807F35F6DFD925238 +CT=EAACC8624146D29129ED8B904E89F04A + +I=297 +KEY=A08AD721EE869F2E6DD033811CEE6F38F6DC2AAEE5C47FED +PT=EAACC8624146D29129ED8B904E89F04A +CT=8949A5A4289B65A32C5116E8A4B55A50 + +I=298 +KEY=CED3055CB1AC48CAE499962534750A9BDA8D3C46417125BD +PT=8949A5A4289B65A32C5116E8A4B55A50 +CT=B632C5FD8EB9676B5504A8BA13E63E2D + +I=299 +KEY=AD1DA883EFFC2F3052AB53D8BACC6DF08F8994FC52971B90 +PT=B632C5FD8EB9676B5504A8BA13E63E2D +CT=EF28A1297C07A575686B3429AC9B62D1 + +I=300 +KEY=007F57339EC932CCBD83F2F1C6CBC885E7E2A0D5FE0C7941 +PT=EF28A1297C07A575686B3429AC9B62D1 +CT=C99F15E4000944120D1C3DD283D99BFF + +I=301 +KEY=3688FDD4FD7822F2741CE715C6C28C97EAFE9D077DD5E2BE +PT=C99F15E4000944120D1C3DD283D99BFF +CT=0AC0219E2BD43F9F19F3A0997FCB9FCD + +I=302 +KEY=AB54BF259C6F5CEE7EDCC68BED16B308F30D3D9E021E7D73 +PT=0AC0219E2BD43F9F19F3A0997FCB9FCD +CT=E27242BC80823BDC09C33C1BDB2EA3BE + +I=303 +KEY=9C88F101B483F8399CAE84376D9488D4FACE0185D930DECD +PT=E27242BC80823BDC09C33C1BDB2EA3BE +CT=7ABF9BD872F54E12FB7F0B11A6D10472 + +I=304 +KEY=971A26707E5B8BC2E6111FEF1F61C6C601B10A947FE1DABF +PT=7ABF9BD872F54E12FB7F0B11A6D10472 +CT=336653E5166F1B4146DBEAED74D72BB7 + +I=305 +KEY=1FFD085658F88F24D5774C0A090EDD87476AE0790B36F108 +PT=336653E5166F1B4146DBEAED74D72BB7 +CT=4849136D0509CE6C404E5685FBEEE9B8 + +I=306 +KEY=411DF55702805FE69D3E5F670C0713EB0724B6FCF0D818B0 +PT=4849136D0509CE6C404E5685FBEEE9B8 +CT=6CF8DCFD53E2ED214A449398D8BF0F6C + +I=307 +KEY=504BFF39E24E870FF1C6839A5FE5FECA4D602564286717DC +PT=6CF8DCFD53E2ED214A449398D8BF0F6C +CT=9C8326B89B3054A46ECA3BB76BC2F292 + +I=308 +KEY=E4F4B55125D2D1056D45A522C4D5AA6E23AA1ED343A5E54E +PT=9C8326B89B3054A46ECA3BB76BC2F292 +CT=C85479C9E038BA5495F67D6E8B2BEB64 + +I=309 +KEY=F2E9B605207E0FD4A511DCEB24ED103AB65C63BDC88E0E2A +PT=C85479C9E038BA5495F67D6E8B2BEB64 +CT=145607ACFFA06C08AB958DCB7BC0BDBC + +I=310 +KEY=CC0D3F478519145BB147DB47DB4D7C321DC9EE76B34EB396 +PT=145607ACFFA06C08AB958DCB7BC0BDBC +CT=ED7EE0DA132D9964BE5E7B2581C3C270 + +I=311 +KEY=EB3AFCDD9AAB59705C393B9DC860E556A3979553328D71E6 +PT=ED7EE0DA132D9964BE5E7B2581C3C270 +CT=6B576FD09F34ED38774AA383BB88B385 + +I=312 +KEY=866ECC1B3691532D376E544D5754086ED4DD36D08905C263 +PT=6B576FD09F34ED38774AA383BB88B385 +CT=E540518151453A18C29BE22B5DE84D5B + +I=313 +KEY=2B3BF12A0A10E6F9D22E05CC061132761646D4FBD4ED8F38 +PT=E540518151453A18C29BE22B5DE84D5B +CT=7865DE74099D486ECB584BE7890F3078 + +I=314 +KEY=3C6EA741634001E0AA4BDBB80F8C7A18DD1E9F1C5DE2BF40 +PT=7865DE74099D486ECB584BE7890F3078 +CT=5226B72FA16653187980D265EB6C7C6D + +I=315 +KEY=A32E19E0F06CB649F86D6C97AEEA2900A49E4D79B68EC32D +PT=5226B72FA16653187980D265EB6C7C6D +CT=CA0D39D92B042BECABF7A14115B3A307 + +I=316 +KEY=E48451707115D4A03260554E85EE02EC0F69EC38A33D602A +PT=CA0D39D92B042BECABF7A14115B3A307 +CT=EC1658D60F1D94EF514FA8EDADAB3C1D + +I=317 +KEY=89A589616229672BDE760D988AF396035E2644D50E965C37 +PT=EC1658D60F1D94EF514FA8EDADAB3C1D +CT=F278CD13BF2C6A1F2D9A9F0C1113205D + +I=318 +KEY=6013E84EFD076E402C0EC08B35DFFC1C73BCDBD91F857C6A +PT=F278CD13BF2C6A1F2D9A9F0C1113205D +CT=0B1A35F604DDB043BCD0573DC0850AF0 + +I=319 +KEY=68BCE1DC00C592E22714F57D31024C5FCF6C8CE4DF00769A +PT=0B1A35F604DDB043BCD0573DC0850AF0 +CT=EAC4FE6F8A04871AC434322CB06308E3 + +I=320 +KEY=1BE682363F216340CDD00B12BB06CB450B58BEC86F637E79 +PT=EAC4FE6F8A04871AC434322CB06308E3 +CT=64B6BA31C6B15BE040DC2C0A07FFE60F + +I=321 +KEY=2082C6C0D49B4DECA966B1237DB790A54B8492C2689C9876 +PT=64B6BA31C6B15BE040DC2C0A07FFE60F +CT=5ECDC37FEA4176145C6A308F91659D43 + +I=322 +KEY=23668EEA68987F8CF7AB725C97F6E6B117EEA24DF9F90535 +PT=5ECDC37FEA4176145C6A308F91659D43 +CT=BB25C81945A062A7D53531593D9910F6 + +I=323 +KEY=10B544566773DD5F4C8EBA45D2568416C2DB9314C46015C3 +PT=BB25C81945A062A7D53531593D9910F6 +CT=48D98FFFC4E378D42CFC785B53DFC38D + +I=324 +KEY=7F96DD27E1C0B7B7045735BA16B5FCC2EE27EB4F97BFD64E +PT=48D98FFFC4E378D42CFC785B53DFC38D +CT=7DCE20BAE8345CB68103461B4AFA9F09 + +I=325 +KEY=A73354FC47570B2679991500FE81A0746F24AD54DD454947 +PT=7DCE20BAE8345CB68103461B4AFA9F09 +CT=099B315B4DD55CAB5D02163154DA521C + +I=326 +KEY=92A57B873A1D292F7002245BB354FCDF3226BB65899F1B5B +PT=099B315B4DD55CAB5D02163154DA521C +CT=37207C17099989D3EA0D13DBD6DF7FEF + +I=327 +KEY=7048AF52E1763E8E4722584CBACD750CD82BA8BE5F4064B4 +PT=37207C17099989D3EA0D13DBD6DF7FEF +CT=7CE37081A6751A1518F03B70FBC1479D + +I=328 +KEY=24E37AF6A4BC72403BC128CD1CB86F19C0DB93CEA4812329 +PT=7CE37081A6751A1518F03B70FBC1479D +CT=201BBD8456F70ED0BB4E19A7AE36F1A6 + +I=329 +KEY=17E541A643CB8EE01BDA95494A4F61C97B958A690AB7D28F +PT=201BBD8456F70ED0BB4E19A7AE36F1A6 +CT=3384168E4F022049B0E3AD6899B71DC9 + +I=330 +KEY=31D5A160B61690A0285E83C7054D4180CB7627019300CF46 +PT=3384168E4F022049B0E3AD6899B71DC9 +CT=C83AA6AE617CB17E2977D394EBC4AD19 + +I=331 +KEY=6EBA775B83D704AAE06425696431F0FEE201F49578C4625F +PT=C83AA6AE617CB17E2977D394EBC4AD19 +CT=8AC467890AF8E729C7A86A471ADEB378 + +I=332 +KEY=C1237F715488582E6AA042E06EC917D725A99ED2621AD127 +PT=8AC467890AF8E729C7A86A471ADEB378 +CT=B89CE4F733A9D67C8E504BC4BC2F7664 + +I=333 +KEY=0A9E4BDAD3E856F1D23CA6175D60C1ABABF9D516DE35A743 +PT=B89CE4F733A9D67C8E504BC4BC2F7664 +CT=47B421469B794A5188255ACE84D89721 + +I=334 +KEY=4BE367B885F7AF9195888751C6198BFA23DC8FD85AED3062 +PT=47B421469B794A5188255ACE84D89721 +CT=B6B09DBF9E62C60951368C9C8B63A860 + +I=335 +KEY=CDFB62995E4C5D4E23381AEE587B4DF372EA0344D18E9802 +PT=B6B09DBF9E62C60951368C9C8B63A860 +CT=68933B4BD0BC23EB3178347DFE68E7F6 + +I=336 +KEY=8887EBF40DE51F064BAB21A588C76E18439237392FE67FF4 +PT=68933B4BD0BC23EB3178347DFE68E7F6 +CT=C6F16CDDF00C982A927609B559B0BCBD + +I=337 +KEY=221D949B8CA9F4C48D5A4D7878CBF632D1E43E8C7656C349 +PT=C6F16CDDF00C982A927609B559B0BCBD +CT=CBEE831F7623E3214E72AF57706525C7 + +I=338 +KEY=3D35666DACEFF3C846B4CE670EE815139F9691DB0633E68E +PT=CBEE831F7623E3214E72AF57706525C7 +CT=DFE0297AE9B69F0AD69D6189C1447333 + +I=339 +KEY=43370C9C958216DC9954E71DE75E8A19490BF052C77795BD +PT=DFE0297AE9B69F0AD69D6189C1447333 +CT=59C3B4D6055B9F73064B715CD5213C99 + +I=340 +KEY=DF43233D68EE5C4AC09753CBE205156A4F40810E1256A924 +PT=59C3B4D6055B9F73064B715CD5213C99 +CT=5373F13BB16B3653FCC138FC9A9E8A47 + +I=341 +KEY=472E0A65B06B4F4693E4A2F0536E2339B381B9F288C82363 +PT=5373F13BB16B3653FCC138FC9A9E8A47 +CT=9C7514B7FEDF2DC26B0C2C1954745077 + +I=342 +KEY=1409E4DF955583A00F91B647ADB10EFBD88D95EBDCBC7314 +PT=9C7514B7FEDF2DC26B0C2C1954745077 +CT=2480D7C35D6B0207D84A9CEFA1C2CFDC + +I=343 +KEY=458552CAB6B1A8AC2B116184F0DA0CFC00C709047D7EBCC8 +PT=2480D7C35D6B0207D84A9CEFA1C2CFDC +CT=46DE3E51F1355FA76652C8DA3642409B + +I=344 +KEY=2065D6F033E1EE2E6DCF5FD501EF535B6695C1DE4B3CFC53 +PT=46DE3E51F1355FA76652C8DA3642409B +CT=13F328173D057A64DA3917468528DB4F + +I=345 +KEY=6D30053E2C95BC5A7E3C77C23CEA293FBCACD698CE14271C +PT=13F328173D057A64DA3917468528DB4F +CT=33D71B6CD0A68B685C89C9F2D70FDFCE + +I=346 +KEY=59D69C2D25BFB6A34DEB6CAEEC4CA257E0251F6A191BF8D2 +PT=33D71B6CD0A68B685C89C9F2D70FDFCE +CT=8E9F57B5E945CD7DFC2B9FCD5AF96DFB + +I=347 +KEY=F41ABD021E5C144EC3743B1B05096F2A1C0E80A743E29529 +PT=8E9F57B5E945CD7DFC2B9FCD5AF96DFB +CT=71295B41B9E5872E1BD4D5C3C4C62D71 + +I=348 +KEY=41C1194732CD4654B25D605ABCECE80407DA55648724B858 +PT=71295B41B9E5872E1BD4D5C3C4C62D71 +CT=E704FBBAA917788CE906A54B2A56A232 + +I=349 +KEY=AF58932371569CE655599BE015FB9088EEDCF02FAD721A6A +PT=E704FBBAA917788CE906A54B2A56A232 +CT=8DBA56CF3E019B8EA80CCB772551CA5B + +I=350 +KEY=B1E68A05A144F4FAD8E3CD2F2BFA0B0646D03B588823D031 +PT=8DBA56CF3E019B8EA80CCB772551CA5B +CT=18F8A23F785AFEFC4ECD527AC6DBE609 + +I=351 +KEY=456D39FF40B1622BC01B6F1053A0F5FA081D69224EF83638 +PT=18F8A23F785AFEFC4ECD527AC6DBE609 +CT=073F93A707D6B9A82E99990CB13BD00E + +I=352 +KEY=1FF446993B6927C6C724FCB754764C522684F02EFFC3E636 +PT=073F93A707D6B9A82E99990CB13BD00E +CT=76723E1239356EDC37FB5E1EAFDF4678 + +I=353 +KEY=0DED89E36C3B06B9B156C2A56D43228E117FAE30501CA04E +PT=76723E1239356EDC37FB5E1EAFDF4678 +CT=1B57D35B4E2484D3945B82D59114A531 + +I=354 +KEY=E433448EB970D64FAA0111FE2367A65D85242CE5C108057F +PT=1B57D35B4E2484D3945B82D59114A531 +CT=4466DCB75F6B83885EE32D9FD533A902 + +I=355 +KEY=3751EC4737F029E3EE67CD497C0C25D5DBC7017A143BAC7D +PT=4466DCB75F6B83885EE32D9FD533A902 +CT=A8B62B9FCAA9331A3282899DB475AADE + +I=356 +KEY=6C1042FACD259CC346D1E6D6B6A516CFE94588E7A04E06A3 +PT=A8B62B9FCAA9331A3282899DB475AADE +CT=DFE1CB42B29F119E44F37F60A8C2BD7C + +I=357 +KEY=640D2DB3E708999A99302D94043A0751ADB6F787088CBBDF +PT=DFE1CB42B29F119E44F37F60A8C2BD7C +CT=891B211EE1BEA05AD7BA478FDFEBC507 + +I=358 +KEY=C434FF9BD02BDF6C102B0C8AE584A70B7A0CB008D7677ED8 +PT=891B211EE1BEA05AD7BA478FDFEBC507 +CT=16ABB92A1E0F433250C551F84AE177CF + +I=359 +KEY=22A76DAFC8A7748E0680B5A0FB8BE4392AC9E1F09D860917 +PT=16ABB92A1E0F433250C551F84AE177CF +CT=1A2F4BF6ED0CADB7FA3FC52F3C6AF191 + +I=360 +KEY=5DDEDF839CF5C0D11CAFFE561687498ED0F624DFA1ECF886 +PT=1A2F4BF6ED0CADB7FA3FC52F3C6AF191 +CT=16AE687EE38FB85C0F70E20F5585F750 + +I=361 +KEY=13D0157C6A30C26C0A019628F508F1D2DF86C6D0F4690FD6 +PT=16AE687EE38FB85C0F70E20F5585F750 +CT=6CD2D70F641B2A7814014177C4880107 + +I=362 +KEY=6DBFF188E61696C966D341279113DBAACB8787A730E10ED1 +PT=6CD2D70F641B2A7814014177C4880107 +CT=8CAD28041AE53AA64CE0173DBD9046C2 + +I=363 +KEY=44A13B269C44F018EA7E69238BF6E10C8767909A8D714813 +PT=8CAD28041AE53AA64CE0173DBD9046C2 +CT=FC8D4274BA1EF15CC39E750DD1848F7B + +I=364 +KEY=B7A8311B81A3B82C16F32B5731E8105044F9E5975CF5C768 +PT=FC8D4274BA1EF15CC39E750DD1848F7B +CT=01CBDAEAADE486CF655401D8F7F7E84E + +I=365 +KEY=A3AC668823C917DE1738F1BD9C0C969F21ADE44FAB022F26 +PT=01CBDAEAADE486CF655401D8F7F7E84E +CT=494C3219700E06EE9C4DCB61EF932FDF + +I=366 +KEY=05CC07DC3CBB1A4B5E74C3A4EC029071BDE02F2E449100F9 +PT=494C3219700E06EE9C4DCB61EF932FDF +CT=BB0E7D5CD93B1839DF5CAED7996F9560 + +I=367 +KEY=8768468EFC3CE954E57ABEF83539884862BC81F9DDFE9599 +PT=BB0E7D5CD93B1839DF5CAED7996F9560 +CT=CC1F9A504A67C24621ED127C63AE2A36 + +I=368 +KEY=470E251F98662CEC296524A87F5E4A0E43519385BE50BFAF +PT=CC1F9A504A67C24621ED127C63AE2A36 +CT=A48D3751956B71F925680073B35BC0A3 + +I=369 +KEY=533C67C061CE6B9E8DE813F9EA353BF7663993F60D0B7F0C +PT=A48D3751956B71F925680073B35BC0A3 +CT=80143AC021E94718146EBC7808A9DDD8 + +I=370 +KEY=0303563B9274349D0DFC2939CBDC7CEF72572F8E05A2A2D4 +PT=80143AC021E94718146EBC7808A9DDD8 +CT=B90AC6ADEE1B60228096D022EE5C681B + +I=371 +KEY=1E7D3A52CC112BDCB4F6EF9425C71CCDF2C1FFACEBFECACF +PT=B90AC6ADEE1B60228096D022EE5C681B +CT=CB8553B21250642107E824E8FB27CAEA + +I=372 +KEY=750A36009059323E7F73BC26379778ECF529DB4410D90025 +PT=CB8553B21250642107E824E8FB27CAEA +CT=9C86DA9646FCFEA7E778A5498F50E01E + +I=373 +KEY=6876C614C460B02CE3F566B0716B864B12517E0D9F89E03B +PT=9C86DA9646FCFEA7E778A5498F50E01E +CT=1481357AD5690762FD6F3809F1E5F219 + +I=374 +KEY=7CE6B00F6B651FAEF77453CAA4028129EF3E46046E6C1222 +PT=1481357AD5690762FD6F3809F1E5F219 +CT=39B64998D4370E0CB47C1DC23EDCDD03 + +I=375 +KEY=C3F72A84EF6F4A0CCEC21A5270358F255B425BC650B0CF21 +PT=39B64998D4370E0CB47C1DC23EDCDD03 +CT=EB1BA96272D7BB044A3381439BA4CD5B + +I=376 +KEY=C670185A26E7DA4A25D9B33002E234211171DA85CB14027A +PT=EB1BA96272D7BB044A3381439BA4CD5B +CT=F87EC3D7F55DA25790718E461BA2E194 + +I=377 +KEY=72ECF820AC459D8DDDA770E7F7BF9676810054C3D0B6E3EE +PT=F87EC3D7F55DA25790718E461BA2E194 +CT=AD7EA1621AD7FBA975D6BB0AB9AED116 + +I=378 +KEY=CE4ECAD1C7D17D1170D9D185ED686DDFF4D6EFC9691832F8 +PT=AD7EA1621AD7FBA975D6BB0AB9AED116 +CT=473B6484F6EAE1FC837A2710AE8D462F + +I=379 +KEY=3273752C9A8682F237E2B5011B828C2377ACC8D9C79574D7 +PT=473B6484F6EAE1FC837A2710AE8D462F +CT=0E3634529E49692762F4D80333738045 + +I=380 +KEY=8C2CFBB98A4E5E3839D4815385CBE504155810DAF4E6F492 +PT=0E3634529E49692762F4D80333738045 +CT=F8EFEBD78C115CC620F25AB66038F2A0 + +I=381 +KEY=0416DBCAFA0850D8C13B6A8409DAB9C235AA4A6C94DE0632 +PT=F8EFEBD78C115CC620F25AB66038F2A0 +CT=B4442C38E3B8E87D8AAE2C17A5571CE9 + +I=382 +KEY=7A7815A748696E99757F46BCEA6251BFBF04667B31891ADB +PT=B4442C38E3B8E87D8AAE2C17A5571CE9 +CT=576A20E194015AB069D769FCA7D842FC + +I=383 +KEY=3848903CD019B4572215665D7E630B0FD6D30F8796515827 +PT=576A20E194015AB069D769FCA7D842FC +CT=E253D9FB4075B021DF452B3AD51204D6 + +I=384 +KEY=3E468D281DF03284C046BFA63E16BB2E099624BD43435CF1 +PT=E253D9FB4075B021DF452B3AD51204D6 +CT=D9454AE62207E70A34F13B0063498A8F + +I=385 +KEY=860E4E60B132A8851903F5401C115C243D671FBD200AD67E +PT=D9454AE62207E70A34F13B0063498A8F +CT=A21F7DA8A298670D631F677D23504757 + +I=386 +KEY=27B82EDF5FFD15DDBB1C88E8BE893B295E7878C0035A9129 +PT=A21F7DA8A298670D631F677D23504757 +CT=1D239EFBABD09A029FE11C59A385C909 + +I=387 +KEY=631BCB74800FD13AA63F16131559A12BC1996499A0DF5820 +PT=1D239EFBABD09A029FE11C59A385C909 +CT=C87EB2AB019AFA608BE99CE77717B333 + +I=388 +KEY=EE1326871289985E6E41A4B814C35B4B4A70F87ED7C8EB13 +PT=C87EB2AB019AFA608BE99CE77717B333 +CT=528DBF70307431E33815D1AA44C30FA8 + +I=389 +KEY=F1D72A84C2FE044F3CCC1BC824B76AA8726529D4930BE4BB +PT=528DBF70307431E33815D1AA44C30FA8 +CT=6C8014B427ED6331A5C174CF2846B70A + +I=390 +KEY=A1610602C8DD2836504C0F7C035A0999D7A45D1BBB4D53B1 +PT=6C8014B427ED6331A5C174CF2846B70A +CT=3DF4C4BE003A13030E73026F7027ADB1 + +I=391 +KEY=B2418E725A1435DD6DB8CBC203601A9AD9D75F74CB6AFE00 +PT=3DF4C4BE003A13030E73026F7027ADB1 +CT=39C50365300DCC5B47F827054879C642 + +I=392 +KEY=761AF29E74671706547DC8A7336DD6C19E2F787183133842 +PT=39C50365300DCC5B47F827054879C642 +CT=847F488B3CEC2E1E4E1C6B9F37E4F631 + +I=393 +KEY=C912116E7B47169AD002802C0F81F8DFD03313EEB4F7CE73 +PT=847F488B3CEC2E1E4E1C6B9F37E4F631 +CT=9A581179C883C5E057CC560A3DF6CD34 + +I=394 +KEY=B08B1226353C6BD34A5A9155C7023D3F87FF45E489010347 +PT=9A581179C883C5E057CC560A3DF6CD34 +CT=799B437C3EF3663EFBD6F186EDFDF21A + +I=395 +KEY=1ECAE821E161A2C833C1D229F9F15B017C29B46264FCF15D +PT=799B437C3EF3663EFBD6F186EDFDF21A +CT=138A858B14FE28D9A47C76BB3FAE9AA1 + +I=396 +KEY=3AD2B951E451EEA8204B57A2ED0F73D8D855C2D95B526BFC +PT=138A858B14FE28D9A47C76BB3FAE9AA1 +CT=5E35BC76C5AC8765A6C396DFE5689579 + +I=397 +KEY=791E5F91477E986E7E7EEBD428A3F4BD7E965406BE3AFE85 +PT=5E35BC76C5AC8765A6C396DFE5689579 +CT=53F8361BF47A82EF27492322BA6F57AD + +I=398 +KEY=194A170B3D4FA6E62D86DDCFDCD9765259DF77240455A928 +PT=53F8361BF47A82EF27492322BA6F57AD +CT=FF626D77AE144C11480610EC1ABB5028 + +I=399 +KEY=C9DC82F000187721D2E4B0B872CD3A4311D967C81EEEF900 +PT=FF626D77AE144C11480610EC1ABB5028 +CT=4E46F8C5092B29E29A971A0CD1F610FB + +========================= + +KEYSIZE=256 + +I=0 +KEY=0000000000000000000000000000000000000000000000000000000000000000 +PT=00000000000000000000000000000000 +CT=8B79EECC93A0EE5DFF30B4EA21636DA4 + +I=1 +KEY=AD3965683E6FA98B5F38AC26653679288B79EECC93A0EE5DFF30B4EA21636DA4 +PT=8B79EECC93A0EE5DFF30B4EA21636DA4 +CT=C737317FE0846F132B23C8C2A672CE22 + +I=2 +KEY=28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386 +PT=C737317FE0846F132B23C8C2A672CE22 +CT=E58B82BFBA53C0040DC610C642121168 + +I=3 +KEY=0721E93EACF9DC6C870D8133376B7C0DA9C55D0CC977414AD9D56CEEC503B2EE +PT=E58B82BFBA53C0040DC610C642121168 +CT=10B296ABB40504995DB71DDA0B7E26FB + +I=4 +KEY=0ECE1E210ADA32EBC497AD50F516602EB977CBA77D7245D384627134CE7D9415 +PT=10B296ABB40504995DB71DDA0B7E26FB +CT=B7198D8E88BAA25234C18517E99BB70D + +I=5 +KEY=D31313ACD90A9BB7D6596DEAB752003F0E6E4629F5C8E781B0A3F42327E62318 +PT=B7198D8E88BAA25234C18517E99BB70D +CT=6125097DB5738C64513E125872EA436C + +I=6 +KEY=488B6A78D9AA23FEA7289E250928BDE36F4B4F5440BB6BE5E19DE67B550C6074 +PT=6125097DB5738C64513E125872EA436C +CT=07FF2ED24B522F1E31D46E94BE5C505B + +I=7 +KEY=03DDD56B142AD3B0E4FFD2BAC6568E5468B461860BE944FBD04988EFEB50302F +PT=07FF2ED24B522F1E31D46E94BE5C505B +CT=EB3C1E3328F840B110E934B0129F2F23 + +I=8 +KEY=20F9D92C65B2F00183464197B23BE5AF83887FB52311044AC0A0BC5FF9CF1F0C +PT=EB3C1E3328F840B110E934B0129F2F23 +CT=107CB7B403DC3F6F09EC30EC1718D183 + +I=9 +KEY=79CF0BCF8EFE3DE82E27778923D1AA1993F4C80120CD3B25C94C8CB3EED7CE8F +PT=107CB7B403DC3F6F09EC30EC1718D183 +CT=CE9DB77B1FAE0CFEC5341FA5AF4CDE8A + +I=10 +KEY=F50ADABA26525BFA7BF6EEF2402450785D697F7A3F6337DB0C789316419B1005 +PT=CE9DB77B1FAE0CFEC5341FA5AF4CDE8A +CT=157B5946862DA3E9A1A83E45857E207D + +I=11 +KEY=3B6947995411D0AE50645129D13BACC04812263CB94E9432ADD0AD53C4E53078 +PT=157B5946862DA3E9A1A83E45857E207D +CT=4AE3583491DF78918CAB3AC241286855 + +I=12 +KEY=AAD12F02F5E5681D16236B668EF2C46702F17E082891ECA3217B979185CD582D +PT=4AE3583491DF78918CAB3AC241286855 +CT=05400C32DC84F1AB486A9BADB1415B50 + +I=13 +KEY=EA02EB82D4B2112DD3BD64C1C908CEC307B1723AF4151D0869110C3C348C037D +PT=05400C32DC84F1AB486A9BADB1415B50 +CT=E4C0781A2EA68D142504739731EF396E + +I=14 +KEY=D51A1846DFEB738F0AF138F74C968DCCE3710A20DAB3901C4C157FAB05633A13 +PT=E4C0781A2EA68D142504739731EF396E +CT=44CC8A9C84E6AD66BD24F1EE1F925EC3 + +I=15 +KEY=B6401DFC35AF21E53CD254431CC639E9A7BD80BC5E553D7AF1318E451AF164D0 +PT=44CC8A9C84E6AD66BD24F1EE1F925EC3 +CT=20AF5FDDF65856D1A60ADC03567AE163 + +I=16 +KEY=D1D2E8B5644910077B3EDB245F029C0D8712DF61A80D6BAB573B52464C8B85B3 +PT=20AF5FDDF65856D1A60ADC03567AE163 +CT=CEB74DD6FBEAFDCEE54930D58AF22ACA + +I=17 +KEY=9F932DC2AB83FA5153E7081E7360ABB449A592B753E79665B2726293C679AF79 +PT=CEB74DD6FBEAFDCEE54930D58AF22ACA +CT=72FB3F7BBBDBA9C036C94531A32E937D + +I=18 +KEY=06AABCA83922297791C9D07AEB639BDD3B5EADCCE83C3FA584BB27A265573C04 +PT=72FB3F7BBBDBA9C036C94531A32E937D +CT=299B26D5D6DFA2C20824D8A84E98A244 + +I=19 +KEY=6124BC71768DE5E9C14D37915D90F1AE12C58B193EE39D678C9FFF0A2BCF9E40 +PT=299B26D5D6DFA2C20824D8A84E98A244 +CT=0A35C0D4170BDE0258D79B668C7C98F4 + +I=20 +KEY=282B067BD441670E11E576F26C4EA67D18F04BCD29E84365D448646CA7B306B4 +PT=0A35C0D4170BDE0258D79B668C7C98F4 +CT=F4E3E981FFC8B50FC9146B85A22E71D4 + +I=21 +KEY=2864E2A3986F99C55EC21C225E3498ECEC13A24CD620F66A1D5C0FE9059D7760 +PT=F4E3E981FFC8B50FC9146B85A22E71D4 +CT=130ACF4CEAFE3277DF057D4D170582ED + +I=22 +KEY=600FD4DFD03132B0DB7B2432DBE027C2FF196D003CDEC41DC25972A41298F58D +PT=130ACF4CEAFE3277DF057D4D170582ED +CT=50001D54F2EA5EAA3BE2206F3845D9A9 + +I=23 +KEY=C1CBE3A1679D6C1913EABE3400993100AF197054CE349AB7F9BB52CB2ADD2C24 +PT=50001D54F2EA5EAA3BE2206F3845D9A9 +CT=69F3EE4B230B2DB2492FE0E36B949154 + +I=24 +KEY=7C6C63E14606A0B09254A531CACB45A0C6EA9E1FED3FB705B094B2284149BD70 +PT=69F3EE4B230B2DB2492FE0E36B949154 +CT=CEEE40F3D2FD9A5521F44AD3AB55198D + +I=25 +KEY=22BB6E21BCA0450240DB117B028837AF0804DEEC3FC22D509160F8FBEA1CA4FD +PT=CEEE40F3D2FD9A5521F44AD3AB55198D +CT=1FA1F1AE7BF2A8C66A6ED6D5F276846B + +I=26 +KEY=7364D9AE40CBB0CCA6640B7E542DBA2617A52F4244308596FB0E2E2E186A2096 +PT=1FA1F1AE7BF2A8C66A6ED6D5F276846B +CT=6D5BD8391C73507D57B902AB3D58D228 + +I=27 +KEY=A2D8BF7602FCD22755ADA9979B2DD33B7AFEF77B5843D5EBACB72C852532F2BE +PT=6D5BD8391C73507D57B902AB3D58D228 +CT=15ACD05539318363F275C857FBC5D86C + +I=28 +KEY=3AD56A33CE89D8D3510C4152DEE734126F52272E617256885EC2E4D2DEF72AD2 +PT=15ACD05539318363F275C857FBC5D86C +CT=B54F8D944301A899A2A88440FE8AB631 + +I=29 +KEY=13ED08137C66C2000D3FE9E167387864DA1DAABA2273FE11FC6A6092207D9CE3 +PT=B54F8D944301A899A2A88440FE8AB631 +CT=23B4BF936BF383325F0DAF0548E32851 + +I=30 +KEY=3C2C53CCDB4721F44B6C057BF758361AF9A9152949807D23A367CF97689EB4B2 +PT=23B4BF936BF383325F0DAF0548E32851 +CT=8B4984C6F39C7FD543B4A8629EAC6740 + +I=31 +KEY=95E744B66044529E2DC2B06BF84FF3D672E091EFBA1C02F6E0D367F5F632D3F2 +PT=8B4984C6F39C7FD543B4A8629EAC6740 +CT=108834058381578E8AA7988E03942230 + +I=32 +KEY=E7715B09238876A93F9858D9548CBEA56268A5EA399D55786A74FF7BF5A6F1C2 +PT=108834058381578E8AA7988E03942230 +CT=EE3974A2ECEA5A1E6FC09535323BFF29 + +I=33 +KEY=08F25145082684F576933E4DF5C63DFE8C51D148D5770F6605B46A4EC79D0EEB +PT=EE3974A2ECEA5A1E6FC09535323BFF29 +CT=1AC80F42E3529BCA587D4EA828BD3631 + +I=34 +KEY=93D63C9069B415595934FA66C76A9CD09699DE0A362594AC5DC924E6EF2038DA +PT=1AC80F42E3529BCA587D4EA828BD3631 +CT=E196DF1E8A0DE844EBD3FD84B307EEB6 + +I=35 +KEY=0F5E4A3907A7BC56AAC2CB6F6871674C770F0114BC287CE8B61AD9625C27D66C +PT=E196DF1E8A0DE844EBD3FD84B307EEB6 +CT=917AC29C88967EE5C792E72B046A4399 + +I=36 +KEY=B935C42A3A93D1E45E94CBE1E232A135E675C38834BE020D71883E49584D95F5 +PT=917AC29C88967EE5C792E72B046A4399 +CT=9CE3D545895005F3EC432699F17FFDA2 + +I=37 +KEY=CC3C0DCF9E6E91BE48B7F7AE251D1CB37A9616CDBDEE07FE9DCB18D0A9326857 +PT=9CE3D545895005F3EC432699F17FFDA2 +CT=089F0D41397E27B04D3268834ADF932C + +I=38 +KEY=29AB63D0AB0E237BA75D250BC67E362472091B8C8490204ED0F97053E3EDFB7B +PT=089F0D41397E27B04D3268834ADF932C +CT=9C364B0CC209389C00824505226B8989 + +I=39 +KEY=7FB99ABACCC92D9C8B17CC0066F02F39EE3F5080469918D2D07B3556C18672F2 +PT=9C364B0CC209389C00824505226B8989 +CT=767FB14493BE17A29839FBF115B9B38B + +I=40 +KEY=DB08EEBD184AEEB002302A3C41E5595B9840E1C4D5270F704842CEA7D43FC179 +PT=767FB14493BE17A29839FBF115B9B38B +CT=CBEC5B7FB05D673C19EBF0F4B647CDB5 + +I=41 +KEY=F7C517C27F319857F1D9DA5D29B6B76353ACBABB657A684C51A93E5362780CCC +PT=CBEC5B7FB05D673C19EBF0F4B647CDB5 +CT=9721CB9555EF079ADD547D8DE09CC0C7 + +I=42 +KEY=47D5164E15743853C8B0E55ED3A965D6C48D712E30956FD68CFD43DE82E4CC0B +PT=9721CB9555EF079ADD547D8DE09CC0C7 +CT=5B16109122E874A08A2A48D5B5753256 + +I=43 +KEY=152E7EF1B0FAD417DA84B4FA0AB560DB9F9B61BF127D1B7606D70B0B3791FE5D +PT=5B16109122E874A08A2A48D5B5753256 +CT=198A9B7C41C225334176614A16F1D7CB + +I=44 +KEY=81BB271A9F0CE56E452C9FBE4CF09FF88611FAC353BF3E4547A16A4121602996 +PT=198A9B7C41C225334176614A16F1D7CB +CT=56E255DB999AFA713020C4E987F4433B + +I=45 +KEY=A654ABA71B351BCBFD1CB03B5F88CE1AD0F3AF18CA25C4347781AEA8A6946AAD +PT=56E255DB999AFA713020C4E987F4433B +CT=7BF8470233D197839D4FC1B365E79C8D + +I=46 +KEY=C700B39660C3C72E15E278B2D22DD528AB0BE81AF9F453B7EACE6F1BC373F620 +PT=7BF8470233D197839D4FC1B365E79C8D +CT=D7CDF94CBBE5E7EF7E47E4CE9BD5E073 + +I=47 +KEY=C49B1589810F1915998C8C79CA2382D87CC611564211B45894898BD558A61653 +PT=D7CDF94CBBE5E7EF7E47E4CE9BD5E073 +CT=A5617B71AF28E732A0B69BFA3B90F291 + +I=48 +KEY=D37A9390FD2C8D4D01704352BAFC2EE2D9A76A27ED39536A343F102F6336E4C2 +PT=A5617B71AF28E732A0B69BFA3B90F291 +CT=156D08F6A2AC3F7202DBEE15D53C8BCD + +I=49 +KEY=E4E2958608635DF83B8E39FD503356D5CCCA62D14F956C1836E4FE3AB60A6F0F +PT=156D08F6A2AC3F7202DBEE15D53C8BCD +CT=1790CB4B9B4E01F4CA3AAB588A3B7A51 + +I=50 +KEY=B0F77AF53FB1FAF66A421093111DC925DB5AA99AD4DB6DECFCDE55623C31155E +PT=1790CB4B9B4E01F4CA3AAB588A3B7A51 +CT=5E2DC515FE9BAE8F16188DC052C63A80 + +I=51 +KEY=487CA8ECBA3E2CAF61A16285005F01F685776C8F2A40C363EAC6D8A26EF72FDE +PT=5E2DC515FE9BAE8F16188DC052C63A80 +CT=A625E46D2DA293F536D25C9207090AA5 + +I=52 +KEY=410909F6119DDA628537B825D24E8DF9235288E207E25096DC14843069FE257B +PT=A625E46D2DA293F536D25C9207090AA5 +CT=FEFCF38ABD12EAAD37F3AE73BC4B4A8C + +I=53 +KEY=F1027D98B61D2F383BCF60A83D317D03DDAE7B68BAF0BA3BEBE72A43D5B56FF7 +PT=FEFCF38ABD12EAAD37F3AE73BC4B4A8C +CT=76D8221C2AAD44D226C769875A93CDA8 + +I=54 +KEY=DDA104019F122286887545C85F6B09B1AB765974905DFEE9CD2043C48F26A25F +PT=76D8221C2AAD44D226C769875A93CDA8 +CT=DE7FBEB010089D7EE0A1BD18F3461AEE + +I=55 +KEY=46CE686778BA955831B63F2ACFE397747509E7C4805563972D81FEDC7C60B8B1 +PT=DE7FBEB010089D7EE0A1BD18F3461AEE +CT=A8B0824BD1FC52D92AFA0B4B23ABDEBD + +I=56 +KEY=EF1408D365E549B808DADADE3D4CBCDADDB9658F51A9314E077BF5975FCB660C +PT=A8B0824BD1FC52D92AFA0B4B23ABDEBD +CT=93AC85EE8DE4091894F0E1800A0DF443 + +I=57 +KEY=8E8FC86B7F82A57799FE32DD1C748C8D4E15E061DC4D3856938B141755C6924F +PT=93AC85EE8DE4091894F0E1800A0DF443 +CT=0FAE963D9B74341316D7EA8862D0766F + +I=58 +KEY=D3900458ABB1ACCE0707A49565D27C4C41BB765C47390C45855CFE9F3716E420 +PT=0FAE963D9B74341316D7EA8862D0766F +CT=37930DFBC771510D0BBDCBFAB2A5852F + +I=59 +KEY=C55EE2F5633DE3E7EF3710C6C143AA7076287BA780485D488EE1356585B3610F +PT=37930DFBC771510D0BBDCBFAB2A5852F +CT=9C3B82D06CB9378F6CBBF6325B456A8B + +I=60 +KEY=AA16073435B24614EB1E9AE81FD921F0EA13F977ECF16AC7E25AC357DEF60B84 +PT=9C3B82D06CB9378F6CBBF6325B456A8B +CT=2DB135F2599323714B4D0E66562FAF48 + +I=61 +KEY=033F102BFB13F9F84A4E9FC0C6F52AC8C7A2CC85B56249B6A917CD3188D9A4CC +PT=2DB135F2599323714B4D0E66562FAF48 +CT=130D64DC60EE70F07F6A68F26A9B5E19 + +I=62 +KEY=60D36FD89196DB13031E829B54615707D4AFA859D58C3946D67DA5C3E242FAD5 +PT=130D64DC60EE70F07F6A68F26A9B5E19 +CT=E4E5C4A1E2A0DC99EEC583E311824371 + +I=63 +KEY=532BC273D1843EB5CC1DE01D28684454304A6CF8372CE5DF38B82620F3C0B9A4 +PT=E4E5C4A1E2A0DC99EEC583E311824371 +CT=72CCE240749A6BFD0A93CDCBE2589B41 + +I=64 +KEY=DAE91111E43D9DF4A0F44C27A6B1AB0842868EB843B68E22322BEBEB119822E5 +PT=72CCE240749A6BFD0A93CDCBE2589B41 +CT=300F85629B48F47444D2AA51EBAAD16C + +I=65 +KEY=5C7C95B43BEA70F20A5C490F9A9F716372890BDAD8FE7A5676F941BAFA32F389 +PT=300F85629B48F47444D2AA51EBAAD16C +CT=89278608A583E1243704B39AB9C0F30C + +I=66 +KEY=5B64FDB468399A031D5745325331C2E8FBAE8DD27D7D9B7241FDF22043F20085 +PT=89278608A583E1243704B39AB9C0F30C +CT=71B74D5FAA4558A59F3BC91AA564579A + +I=67 +KEY=0166230CCF036B4B22C63D36F71C3CF58A19C08DD738C3D7DEC63B3AE696571F +PT=71B74D5FAA4558A59F3BC91AA564579A +CT=7B433C70951E4BD140FF7A0CBF367429 + +I=68 +KEY=D7A12389D7DD5DE963841B344315ADF9F15AFCFD422688069E39413659A02336 +PT=7B433C70951E4BD140FF7A0CBF367429 +CT=B0BE67EBCD672549AF03D323AF026FFF + +I=69 +KEY=A3EC2E92C58FE150F708C6FAEB1F459E41E49B168F41AD4F313A9215F6A24CC9 +PT=B0BE67EBCD672549AF03D323AF026FFF +CT=99A829A7C5C7CD6A44C7EABA9A5421C7 + +I=70 +KEY=CC3F7485BF8460CB1EA0AA3C20553644D84CB2B14A86602575FD78AF6CF66D0E +PT=99A829A7C5C7CD6A44C7EABA9A5421C7 +CT=76E1A70AF79F89CFE68EAF15DC0E9BC5 + +I=71 +KEY=17DC64F06B3A2941A21AE58E2FFAB363AEAD15BBBD19E9EA9373D7BAB0F8F6CB +PT=76E1A70AF79F89CFE68EAF15DC0E9BC5 +CT=DB0805B5DCC1CA2CA7489C8E1237E7A2 + +I=72 +KEY=DC7128E894C9DA167D0ACED5888F846275A5100E61D823C6343B4B34A2CF1169 +PT=DB0805B5DCC1CA2CA7489C8E1237E7A2 +CT=935D409B87A85A2CFCC09DE3D2A9A294 + +I=73 +KEY=8073895C9316D299F4F32C602F2F2616E6F85095E67079EAC8FBD6D77066B3FD +PT=935D409B87A85A2CFCC09DE3D2A9A294 +CT=F22B73EFF24249CBCB31BDC7C126B735 + +I=74 +KEY=99E16793433652800ABAD7000638560914D3237A1432302103CA6B10B14004C8 +PT=F22B73EFF24249CBCB31BDC7C126B735 +CT=A16A380AE9B3F2B0AE39BB0E24BF7C0A + +I=75 +KEY=8F77C5E97DA567CC447B52F45175BC74B5B91B70FD81C291ADF3D01E95FF78C2 +PT=A16A380AE9B3F2B0AE39BB0E24BF7C0A +CT=9CF088DE60AE87687481C9F217E86A7C + +I=76 +KEY=DA1B3C2C424D2BC6A1C7A3D18D41C3F5294993AE9D2F45F9D97219EC821712BE +PT=9CF088DE60AE87687481C9F217E86A7C +CT=1C8B68951E65E32E77F1A31571351C1B + +I=77 +KEY=3D64F3D4BF8F585917273805AA43DCD735C2FB3B834AA6D7AE83BAF9F3220EA5 +PT=1C8B68951E65E32E77F1A31571351C1B +CT=4AD3F3B0C15D810F0EA0FF62C6B2D0FE + +I=78 +KEY=51D61FB1B31EB55C7AA2D918E7BE32A97F11088B421727D8A023459B3590DE5B +PT=4AD3F3B0C15D810F0EA0FF62C6B2D0FE +CT=0DFCF7CA661572E050C522AE554A4BF8 + +I=79 +KEY=B93510F7689FB9856194CF629EF63AAA72EDFF4124025538F0E6673560DA95A3 +PT=0DFCF7CA661572E050C522AE554A4BF8 +CT=7C185A5A68675DAC7A16C8DDE4B8CF8B + +I=80 +KEY=8496679D7598A1B91D2F221CF958F90B0EF5A51B4C6508948AF0AFE884625A28 +PT=7C185A5A68675DAC7A16C8DDE4B8CF8B +CT=88FDDDA7BC2B09E48598A94474C64DC7 + +I=81 +KEY=F27BCC0F919566675B129C526A4DC796860878BCF04E01700F6806ACF0A417EF +PT=88FDDDA7BC2B09E48598A94474C64DC7 +CT=35C5C98C9C774D0BE9EFFB55C90B2F9C + +I=82 +KEY=05F12B58DBF5602D31CFD0EB10313502B3CDB1306C394C7BE687FDF939AF3873 +PT=35C5C98C9C774D0BE9EFFB55C90B2F9C +CT=C3374B5C81646AC881F0F924C22A723B + +I=83 +KEY=FD05BE617555BC8184C2F46911C46B9E70FAFA6CED5D26B3677704DDFB854A48 +PT=C3374B5C81646AC881F0F924C22A723B +CT=0CE756792AF27525A088700DB66D4399 + +I=84 +KEY=3831345DFA5ADDF7CE8B5F76B5E1EBDE7C1DAC15C7AF5396C7FF74D04DE809D1 +PT=0CE756792AF27525A088700DB66D4399 +CT=401CD076E03C108A7FD79651407923E9 + +I=85 +KEY=B101FDD95C23BE560262D355E09FC39B3C017C632793431CB828E2810D912A38 +PT=401CD076E03C108A7FD79651407923E9 +CT=88614E46C416E5164F2A63CDA9DD7B89 + +I=86 +KEY=0B53859962A79D216E395830E36F8D45B4603225E385A60AF702814CA44C51B1 +PT=88614E46C416E5164F2A63CDA9DD7B89 +CT=7411856C8F14A2E5F6C5F1830302A66F + +I=87 +KEY=FE07E3B8961C2A1B3E34A50F8CFA1A45C071B7496C9104EF01C770CFA74EF7DE +PT=7411856C8F14A2E5F6C5F1830302A66F +CT=B0A815E93EBAC7A68F8BB420C8A5692D + +I=88 +KEY=9F2E0D3DB033B1929009D6C4C460B24F70D9A2A0522BC3498E4CC4EF6FEB9EF3 +PT=B0A815E93EBAC7A68F8BB420C8A5692D +CT=AA6D27BB26275F5CB3EC3D6A8AFB80BF + +I=89 +KEY=5E903EF160161E1CA79A26D28FE32175DAB4851B740C9C153DA0F985E5101E4C +PT=AA6D27BB26275F5CB3EC3D6A8AFB80BF +CT=EAF7941A7E5D3907B6F52C1106EED2CE + +I=90 +KEY=60284EF35A9246CC32002028E4969309304311010A51A5128B55D594E3FECC82 +PT=EAF7941A7E5D3907B6F52C1106EED2CE +CT=1178DD3DBDB1810E360E6FE09AA0D75C + +I=91 +KEY=300CB519F3203AD4589749651BD99AC7213BCC3CB7E0241CBD5BBA74795E1BDE +PT=1178DD3DBDB1810E360E6FE09AA0D75C +CT=584B48263DE541E93B29C6E570D4A6F4 + +I=92 +KEY=2F79EA55D0E3EAF1D0DBD364A7D64E2A7970841A8A0565F586727C91098ABD2A +PT=584B48263DE541E93B29C6E570D4A6F4 +CT=7B2EC27F2F1BC24EAD4FC0AA0519685C + +I=93 +KEY=8B46F59BF2C4B226523C203E8FD3936D025E4665A51EA7BB2B3DBC3B0C93D576 +PT=7B2EC27F2F1BC24EAD4FC0AA0519685C +CT=13404D003576493EBB36C07C6D16A1B6 + +I=94 +KEY=C7E75C30B0CE770A0075E3EBEB244811111E0B659068EE85900B7C47618574C0 +PT=13404D003576493EBB36C07C6D16A1B6 +CT=A083421A139DF68C8F863B337F3408BE + +I=95 +KEY=A957F876769BE9005DCEE4B7514FAC62B19D497F83F518091F8D47741EB17C7E +PT=A083421A139DF68C8F863B337F3408BE +CT=BF86650C9ECBD6C14B420FBE6B6E488B + +I=96 +KEY=FD4DE7532652D17C5ACCEA759C52A95C0E1B2C731D3ECEC854CF48CA75DF34F5 +PT=BF86650C9ECBD6C14B420FBE6B6E488B +CT=75CEFAE872574AB6F26B0CAF6F08D858 + +I=97 +KEY=54DBCDC0A57363DE6B3A032607E968C27BD5D69B6F69847EA6A444651AD7ECAD +PT=75CEFAE872574AB6F26B0CAF6F08D858 +CT=8A3F9C96598883E9D3760C8A8FE406C6 + +I=98 +KEY=AC10312E365401908F2C8AE371CB8C90F1EA4A0D36E1079775D248EF9533EA6B +PT=8A3F9C96598883E9D3760C8A8FE406C6 +CT=B8B372C0CC6D164F340DF26B8F832DF8 + +I=99 +KEY=64265CF02043C966C01DF5255F8D2867495938CDFA8C11D841DFBA841AB0C793 +PT=B8B372C0CC6D164F340DF26B8F832DF8 +CT=A7F6267A6F0CEB0EF7D07959EE065760 + +I=100 +KEY=CF6B88FB273B247B8D64B5A323EF5760EEAF1EB79580FAD6B60FC3DDF4B690F3 +PT=A7F6267A6F0CEB0EF7D07959EE065760 +CT=AD96ADAC9B786AB78B1B46D9E026C935 + +I=101 +KEY=4C8EEA35A90CB46AF32235997D2ADBBE4339B31B0EF890613D148504149059C6 +PT=AD96ADAC9B786AB78B1B46D9E026C935 +CT=FC7BAC9A5F64571AABF4B0A451C8D88D + +I=102 +KEY=0DD6D30191FABEC371CF0BA223BECF19BF421F81519CC77B96E035A04558814B +PT=FC7BAC9A5F64571AABF4B0A451C8D88D +CT=2B56E363834F27090FAC8061507A4787 + +I=103 +KEY=2E69324E634312611C33F695A137AFE49414FCE2D2D3E072994CB5C11522C6CC +PT=2B56E363834F27090FAC8061507A4787 +CT=FD37886E30CEFA28F8E8A5662A9EC5DC + +I=104 +KEY=8AFAC0C1507472CCB28B37CA88B7139D6923748CE21D1A5A61A410A73FBC0310 +PT=FD37886E30CEFA28F8E8A5662A9EC5DC +CT=F7F36142C000D5162F789C392971FCE7 + +I=105 +KEY=7DC5DA2A80219692F9F26C5934826DF29ED015CE221DCF4C4EDC8C9E16CDFFF7 +PT=F7F36142C000D5162F789C392971FCE7 +CT=D560607A0F0BE8320F2CEE56B155163F + +I=106 +KEY=3CC9AE3E3EB90B511C6D8CD74419D6944BB075B42D16277E41F062C8A798E9C8 +PT=D560607A0F0BE8320F2CEE56B155163F +CT=708133FEB47A226A616900D46FA85037 + +I=107 +KEY=8B84B7F96F9B3184D5B6402ECAE344CB3B31464A996C05142099621CC830B9FF +PT=708133FEB47A226A616900D46FA85037 +CT=1B2ED9348FC7A4E4AD8BFCE2A148D1AD + +I=108 +KEY=655CB7606D17582441247D23E222ECCF201F9F7E16ABA1F08D129EFE69786852 +PT=1B2ED9348FC7A4E4AD8BFCE2A148D1AD +CT=B2B726C8605A6F5CBA97F04E85A1F985 + +I=109 +KEY=E0BA77DAAD3E3502AB9A6CEBEC654D0492A8B9B676F1CEAC37856EB0ECD991D7 +PT=B2B726C8605A6F5CBA97F04E85A1F985 +CT=CD7F53BB4AEB364A1D8630E0B5C4A6A2 + +I=110 +KEY=1470D5E493B0E8212F02D4419C46A8CD5FD7EA0D3C1AF8E62A035E50591D3775 +PT=CD7F53BB4AEB364A1D8630E0B5C4A6A2 +CT=57271A960FE2170BA3F1987E694BBD16 + +I=111 +KEY=415408E88421573F93FDBE25DD4B90C208F0F09B33F8EFED89F2C62E30568A63 +PT=57271A960FE2170BA3F1987E694BBD16 +CT=E9D47C3E926475FFDB783624C3ADB17B + +I=112 +KEY=40B3017DC81EEE4BF652AE8BB8CEED1DE1248CA5A19C9A12528AF00AF3FB3B18 +PT=E9D47C3E926475FFDB783624C3ADB17B +CT=D78F96812BB55723E04BE8818C262485 + +I=113 +KEY=9EABE9B3608ACE61684BAD3F3FED5C9736AB1A248A29CD31B2C1188B7FDD1F9D +PT=D78F96812BB55723E04BE8818C262485 +CT=E2092227E1A3D2E525942090DA0A3F3E + +I=114 +KEY=B095E4F38E060016EBC4C42D3A4EFBD6D4A238036B8A1FD49755381BA5D720A3 +PT=E2092227E1A3D2E525942090DA0A3F3E +CT=95E9EE1F56A65FF85B752FC300F525AE + +I=115 +KEY=9B2841F44291552EA04DE13E4E78011B414BD61C3D2C402CCC2017D8A522050D +PT=95E9EE1F56A65FF85B752FC300F525AE +CT=32D8465F2E11A04F8984FEE8E710CD25 + +I=116 +KEY=67D8B10D0DDB61932E610EB077F0D85F73939043133DE06345A4E9304232C828 +PT=32D8465F2E11A04F8984FEE8E710CD25 +CT=2D9803ECFB95B2591FE56B3CBB4307F2 + +I=117 +KEY=B0C80A38EDE23A549EF08E5DC3CEA2F25E0B93AFE8A8523A5A41820CF971CFDA +PT=2D9803ECFB95B2591FE56B3CBB4307F2 +CT=4B19F9BCAFD471BF9014ADA19891E4E6 + +I=118 +KEY=85C6DF29F9AEBA6087E3746BA5CF6C1515126A13477C2385CA552FAD61E02B3C +PT=4B19F9BCAFD471BF9014ADA19891E4E6 +CT=53159BC4FBD06FD03ABAC028A536C4A0 + +I=119 +KEY=2D42BE0B33D92ECC40DF48CF0AE0CB764607F1D7BCAC4C55F0EFEF85C4D6EF9C +PT=53159BC4FBD06FD03ABAC028A536C4A0 +CT=BCDB1347ACD50D0084D588D4540420E3 + +I=120 +KEY=338A4DC6E729E6FCF71095BB4E6F52FEFADCE29010794155743A675190D2CF7F +PT=BCDB1347ACD50D0084D588D4540420E3 +CT=E12DC82E79554E1202DA471C3221A554 + +I=121 +KEY=47597486437CBCD33FC195C56FF972BB1BF12ABE692C0F4776E0204DA2F36A2B +PT=E12DC82E79554E1202DA471C3221A554 +CT=23A43E9D6F7C5A6C842233CCEC120EB9 + +I=122 +KEY=CEE8CF713EBF0C609E3429E5183014BB385514230650552BF2C213814EE16492 +PT=23A43E9D6F7C5A6C842233CCEC120EB9 +CT=9F3F4349BF98D3CC00DB167F0FFDC7AB + +I=123 +KEY=C9B3A1CAFA0D4F0DA942C17FFB75E333A76A576AB9C886E7F21905FE411CA339 +PT=9F3F4349BF98D3CC00DB167F0FFDC7AB +CT=C4D8B8EBEF311C11FE2404220EA65E99 + +I=124 +KEY=8360E6F464B61C4BAE31D3A72422128463B2EF8156F99AF60C3D01DC4FBAFDA0 +PT=C4D8B8EBEF311C11FE2404220EA65E99 +CT=47E3318C721E6C094763F0A18042911D + +I=125 +KEY=926B00B9767D0CAD5331CD6F0343C4A92451DE0D24E7F6FF4B5EF17DCFF86CBD +PT=47E3318C721E6C094763F0A18042911D +CT=D709FA9A1415B0FAC71B4CF52504791F + +I=126 +KEY=3F4349126EF6A51FD196742CB461D01EF358249730F246058C45BD88EAFC15A2 +PT=D709FA9A1415B0FAC71B4CF52504791F +CT=7937DD067DDB85F200A492E5824DA23C + +I=127 +KEY=4420ADF6906CFBF8421524E88517327C8A6FF9914D29C3F78CE12F6D68B1B79E +PT=7937DD067DDB85F200A492E5824DA23C +CT=B68617F1372847206BA088D7100334A4 + +I=128 +KEY=125BEB5234B89A376ABBB2185F24BDDE3CE9EE607A0184D7E741A7BA78B2833A +PT=B68617F1372847206BA088D7100334A4 +CT=390938BA9F2264484DE63D8003C15369 + +I=129 +KEY=A457831AB172D88111E87C3955D0C0F205E0D6DAE523E09FAAA79A3A7B73D053 +PT=390938BA9F2264484DE63D8003C15369 +CT=A69ED32FD728337A5C25FBC2230DC788 + +I=130 +KEY=CC7ED4183BFAE0FA0F9DD348B8E194F2A37E05F5320BD3E5F68261F8587E17DB +PT=A69ED32FD728337A5C25FBC2230DC788 +CT=EDB9D6099202FE4AE51EEC725478FB47 + +I=131 +KEY=686AB4F5C19296AED306ADEA4FD52D1A4EC7D3FCA0092DAF139C8D8A0C06EC9C +PT=EDB9D6099202FE4AE51EEC725478FB47 +CT=61059EA3BF0C953762CB37E50ED7081F + +I=132 +KEY=8115329FADEBA92AB2827BD7701A01442FC24D5F1F05B8987157BA6F02D1E483 +PT=61059EA3BF0C953762CB37E50ED7081F +CT=A683E36EF7CCDABDBCA683C2D6560D25 + +I=133 +KEY=49254E8904EED2766A6A1A615B63B97C8941AE31E8C96225CDF139ADD487E9A6 +PT=A683E36EF7CCDABDBCA683C2D6560D25 +CT=8EF424771561BFEC0058C7CAA5876EF6 + +I=134 +KEY=259194CE8701581012F5592B61BCA99507B58A46FDA8DDC9CDA9FE6771008750 +PT=8EF424771561BFEC0058C7CAA5876EF6 +CT=79AC024A7BA5FFE143D40D34F2E587A6 + +I=135 +KEY=CA0427FE28C77D0CA25D6851CCFE58C47E19880C860D22288E7DF35383E500F6 +PT=79AC024A7BA5FFE143D40D34F2E587A6 +CT=2258AB9F0E254CE21EB9B7F6EA690671 + +I=136 +KEY=DA9A4B566C9F670DF850F891A5274CC95C41239388286ECA90C444A5698C0687 +PT=2258AB9F0E254CE21EB9B7F6EA690671 +CT=55ACB73E8A45BF964BD040C799724DAD + +I=137 +KEY=9F177A6A6B524C75DB5CC0DBB6AD733209ED94AD026DD15CDB140462F0FE4B2A +PT=55ACB73E8A45BF964BD040C799724DAD +CT=3E904B15F2E5DDC934DABC25259CB3CF + +I=138 +KEY=2AD96F6874C1BA6A82C5EE80A9A2E8E5377DDFB8F0880C95EFCEB847D562F8E5 +PT=3E904B15F2E5DDC934DABC25259CB3CF +CT=3ACFF8D5B701A5BD1355DDA705D269CB + +I=139 +KEY=ADD59DF57CC01DE988C6D81E65B1D00E0DB2276D4789A928FC9B65E0D0B0912E +PT=3ACFF8D5B701A5BD1355DDA705D269CB +CT=3EF4AC14CC954FB4A9A808C7C00A2F1F + +I=140 +KEY=D3EBE43C4E9C96B37133F6AF8910A25F33468B798B1CE69C55336D2710BABE31 +PT=3EF4AC14CC954FB4A9A808C7C00A2F1F +CT=61C50D5C736AEDCF03C06FC310CC19D9 + +I=141 +KEY=FA45F434377F2E217C4A5B7A7526CC1952838625F8760B5356F302E40076A7E8 +PT=61C50D5C736AEDCF03C06FC310CC19D9 +CT=2BF543C6548ED0344262640AD95F95C9 + +I=142 +KEY=71EAD73C81ED5AE731D19B0B2B42F0E87976C5E3ACF8DB67149166EED9293221 +PT=2BF543C6548ED0344262640AD95F95C9 +CT=F8C1DBDD20317FEB1625634A451931B5 + +I=143 +KEY=3FD0019D000111D4300D2CEF39F53C0D81B71E3E8CC9A48C02B405A49C300394 +PT=F8C1DBDD20317FEB1625634A451931B5 +CT=DEDB54735B8B90C8EEC66EAECFB13ED6 + +I=144 +KEY=070976B2D3AA1E737BC24A8A794A21BE5F6C4A4DD7423444EC726B0A53813D42 +PT=DEDB54735B8B90C8EEC66EAECFB13ED6 +CT=75941A1ADA444115961E058E2D6C6396 + +I=145 +KEY=81AC2B7F073D0D06BA8A43D3381D3A3F2AF850570D0675517A6C6E847EED5ED4 +PT=75941A1ADA444115961E058E2D6C6396 +CT=7C66BE2B0354A6549E10489AF7A83424 + +I=146 +KEY=37BDD1946BB9B5616115F015E9162F5B569EEE7C0E52D305E47C261E89456AF0 +PT=7C66BE2B0354A6549E10489AF7A83424 +CT=F589769555BDEFD0B29E6A65313BD2E1 + +I=147 +KEY=CF27BD543BB4EED052B808D1EE350D35A31798E95BEF3CD556E24C7BB87EB811 +PT=F589769555BDEFD0B29E6A65313BD2E1 +CT=9B3215F70FBCC5ED9CC0D6D7E1E56F11 + +I=148 +KEY=43321308251C33234CCD9ED19E5E74AF38258D1E5453F938CA229AAC599BD700 +PT=9B3215F70FBCC5ED9CC0D6D7E1E56F11 +CT=705CCB60E0A6E997578DCC804D49D265 + +I=149 +KEY=F2152160EAD144776BA6BDED0AC49CD24879467EB4F510AF9DAF562C14D20565 +PT=705CCB60E0A6E997578DCC804D49D265 +CT=3DA4CEC68D47E55ECF21A1C5CDAFE4E6 + +I=150 +KEY=593B7EDAE946A5269EF33D088D1B297675DD88B839B2F5F1528EF7E9D97DE183 +PT=3DA4CEC68D47E55ECF21A1C5CDAFE4E6 +CT=32299EDBED49B66271107CA1822F179E + +I=151 +KEY=852E4554AD1459CE81DBA17D18DA96C447F41663D4FB4393239E8B485B52F61D +PT=32299EDBED49B66271107CA1822F179E +CT=45856FD2080FA9BBFA0857BCF7381823 + +I=152 +KEY=1D8F910508F9C08DB4DE4D5C465310F4027179B1DCF4EA28D996DCF4AC6AEE3E +PT=45856FD2080FA9BBFA0857BCF7381823 +CT=6A8C18595AF5D1E46F9F168C31566BAF + +I=153 +KEY=1A42C028C1ABA740D95A47ABD7B4F40D68FD61E886013BCCB609CA789D3C8591 +PT=6A8C18595AF5D1E46F9F168C31566BAF +CT=71A41A6B6BF9FB906B0617DCB76B4BA5 + +I=154 +KEY=3C408CB08BCAF34B2BCE6EF787A96D5219597B83EDF8C05CDD0FDDA42A57CE34 +PT=71A41A6B6BF9FB906B0617DCB76B4BA5 +CT=9105B8FC516E0B19AEDD003979F8C298 + +I=155 +KEY=804516E36B1B5E046B15CBE1D3F26EE9885CC37FBC96CB4573D2DD9D53AF0CAC +PT=9105B8FC516E0B19AEDD003979F8C298 +CT=27ACD01CC0403AD6DB45C7DF3E515EDE + +I=156 +KEY=CD8199690660BD4DBA38CE522D1A12CEAFF013637CD6F193A8971A426DFE5272 +PT=27ACD01CC0403AD6DB45C7DF3E515EDE +CT=86E2A23AC567C5F05F15A318E38360A7 + +I=157 +KEY=0AD8BB3D5B2A538DF0BDD50EB74CC1BA2912B159B9B13463F782B95A8E7D32D5 +PT=86E2A23AC567C5F05F15A318E38360A7 +CT=CB03EDA81BF211B5FE03D4A0879E9EDD + +I=158 +KEY=081040B60AE9E733243F4C39013EEDB5E2115CF1A24325D609816DFA09E3AC08 +PT=CB03EDA81BF211B5FE03D4A0879E9EDD +CT=6F1AD4AD727348DD593459E0D7661813 + +I=159 +KEY=A51E29D20BB0963DF854C898299E114A8D0B885CD0306D0B50B5341ADE85B41B +PT=6F1AD4AD727348DD593459E0D7661813 +CT=236B421E3103D4C17297D3F5C8BA1D17 + +I=160 +KEY=49D4EB9964431F42F0FC6494A47A50CCAE60CA42E133B9CA2222E7EF163FA90C +PT=236B421E3103D4C17297D3F5C8BA1D17 +CT=118AE5A5597E8DB200B26DBE11AC4BC8 + +I=161 +KEY=0F3F7298BE444450A0A07A4B73897720BFEA2FE7B84D347822908A510793E2C4 +PT=118AE5A5597E8DB200B26DBE11AC4BC8 +CT=DF02587F25CC4C59E6AECE98BCAACCB8 + +I=162 +KEY=7E30984A4C0B18D2F791858B83FC960960E877989D817821C43E44C9BB392E7C +PT=DF02587F25CC4C59E6AECE98BCAACCB8 +CT=3DA0F35FDAEF499ADBF602939FC748D4 + +I=163 +KEY=360A7168E056892E5BF0127EA3B58CAF5D4884C7476E31BB1FC8465A24FE66A8 +PT=3DA0F35FDAEF499ADBF602939FC748D4 +CT=FE462F878CEEDDDAA00855B85A81A14B + +I=164 +KEY=A75B3537E0EB98FC0F41C9E1306F6667A30EAB40CB80EC61BFC013E27E7FC7E3 +PT=FE462F878CEEDDDAA00855B85A81A14B +CT=47EA8AC561D7A9F99F64F41A9AD46E5C + +I=165 +KEY=219E71FC6D23A5103DE4DA9C5EDFA0AEE4E42185AA57459820A4E7F8E4ABA9BF +PT=47EA8AC561D7A9F99F64F41A9AD46E5C +CT=650FAE7F29A098D787F60CC3C0D77580 + +I=166 +KEY=038A888C6EA4E9502A15110832AE0DF081EB8FFA83F7DD4FA752EB3B247CDC3F +PT=650FAE7F29A098D787F60CC3C0D77580 +CT=0334BF8CA2835C71F2A283736D54E933 + +I=167 +KEY=714967419F9129B9649A13A9DA3291A582DF30762174813E55F068484928350C +PT=0334BF8CA2835C71F2A283736D54E933 +CT=1B3A09B325F3D833A3C83D941832B204 + +I=168 +KEY=BCDB12EAF8D3C95F821C0DD324FD36BB99E539C50487590DF63855DC511A8708 +PT=1B3A09B325F3D833A3C83D941832B204 +CT=CF980ED2619858290881314B7F0B9516 + +I=169 +KEY=B8FA32AE829E8AF3EF543A407E2D61BA567D3717651F0124FEB964972E11121E +PT=CF980ED2619858290881314B7F0B9516 +CT=98FF5ADA0739122DBBD241847D4A318D + +I=170 +KEY=D62592634F0ABD21AC98887A88845E2ECE826DCD62261309456B2513535B2393 +PT=98FF5ADA0739122DBBD241847D4A318D +CT=1824306B9F54BE4CE3F94F037B4B8569 + +I=171 +KEY=77005AE2FA1AD6D77D36566B9E988345D6A65DA6FD72AD45A6926A102810A6FA +PT=1824306B9F54BE4CE3F94F037B4B8569 +CT=25BA57B9035625DD268492282535960C + +I=172 +KEY=BE766696DC4458442056D89C96CAFDF0F31C0A1FFE2488988016F8380D2530F6 +PT=25BA57B9035625DD268492282535960C +CT=26AEAD4ED08CA78CE2A3358F36DA0E3F + +I=173 +KEY=1E1D3EBC714EE191EDB2A02B64EF2C23D5B2A7512EA82F1462B5CDB73BFF3EC9 +PT=26AEAD4ED08CA78CE2A3358F36DA0E3F +CT=10AB48E0CB1D72D82794E35DBDEF88F6 + +I=174 +KEY=D3EAD2DA40B4C94B506A0ED75210023BC519EFB1E5B55DCC45212EEA8610B63F +PT=10AB48E0CB1D72D82794E35DBDEF88F6 +CT=878BCAC367294B227533E1451F654960 + +I=175 +KEY=87D0B5D4A1314054EC37B67B4245BA8C42922572829C16EE3012CFAF9975FF5F +PT=878BCAC367294B227533E1451F654960 +CT=98CC3311EC8E8B75944503734DEAC00D + +I=176 +KEY=EF3FA3235BB42B1326DE67088C68E2BDDA5E16636E129D9BA457CCDCD49F3F52 +PT=98CC3311EC8E8B75944503734DEAC00D +CT=DAF5FB711E259B498918871933A2E1FD + +I=177 +KEY=2EBBBB1B070658DD43299478725AA88F00ABED12703706D22D4F4BC5E73DDEAF +PT=DAF5FB711E259B498918871933A2E1FD +CT=AACC545DEE8FF1F5C7A91A2EE3D25C1B + +I=178 +KEY=E15D1FC214F23FF93886D219B4DFCD45AA67B94F9EB8F727EAE651EB04EF82B4 +PT=AACC545DEE8FF1F5C7A91A2EE3D25C1B +CT=B844B67FBFD12E2712CCB66EBB4F7691 + +I=179 +KEY=CC3335B792121DE55FA04A4D6FEE57B012230F302169D900F82AE785BFA0F425 +PT=B844B67FBFD12E2712CCB66EBB4F7691 +CT=3E00C548BAEE6150FAA5B67986331FD5 + +I=180 +KEY=18DB585F810069C584251CA1E04A58382C23CA789B87B850028F51FC3993EBF0 +PT=3E00C548BAEE6150FAA5B67986331FD5 +CT=EB23DEEA8449E8FA0D828C12B98437AE + +I=181 +KEY=DFE08CA44B0BC4F51C43BE3631E20735C70014921FCE50AA0F0DDDEE8017DC5E +PT=EB23DEEA8449E8FA0D828C12B98437AE +CT=35BBE35CFC1D8FC40BC52F20D3FB35D5 + +I=182 +KEY=0F7DCC456D50A31AC9351794BFE6DD57F2BBF7CEE3D3DF6E04C8F2CE53ECE98B +PT=35BBE35CFC1D8FC40BC52F20D3FB35D5 +CT=DFFE7AEEAAF4762C7EB52453B1F61AD8 + +I=183 +KEY=D34FDEB3F04FB4563BC0FD204E8D459F2D458D204927A9427A7DD69DE21AF353 +PT=DFFE7AEEAAF4762C7EB52453B1F61AD8 +CT=C648DAF9EBFB4BC6166B15BF067E107F + +I=184 +KEY=5E90B747C9976A3F5050B0C51F116A81EB0D57D9A2DCE2846C16C322E464E32C +PT=C648DAF9EBFB4BC6166B15BF067E107F +CT=057258D07CAEE57807C396FAE651855A + +I=185 +KEY=52D3686BC0CD56B9DFF3A69F5073F30AEE7F0F09DE7207FC6BD555D802356676 +PT=057258D07CAEE57807C396FAE651855A +CT=B1109BE49E6E0F4C4190D8E0D717E8D0 + +I=186 +KEY=39C89286B658E006FBF97BAB1C4874025F6F94ED401C08B02A458D38D5228EA6 +PT=B1109BE49E6E0F4C4190D8E0D717E8D0 +CT=4DDE60FEEE40402058C988092603AB53 + +I=187 +KEY=562C9A004CBF05A4CA97994D48C0874C12B1F413AE5C4890728C0531F32125F5 +PT=4DDE60FEEE40402058C988092603AB53 +CT=3B18CBF83791E93D661EB269CFEAB1BE + +I=188 +KEY=F95206C4D3862E01A4DFE3676A2F297C29A93FEB99CDA1AD1492B7583CCB944B +PT=3B18CBF83791E93D661EB269CFEAB1BE +CT=0A3204DEE28B65E849136960949E4E5E + +I=189 +KEY=FEFDBE4294E46E22074E77B6BB7F964B239B3B357B46C4455D81DE38A855DA15 +PT=0A3204DEE28B65E849136960949E4E5E +CT=6C47ECB8B1478F0BBEDEF3A05A439776 + +I=190 +KEY=05858C957F861410187DD8CC2EE48E364FDCD78DCA014B4EE35F2D98F2164D63 +PT=6C47ECB8B1478F0BBEDEF3A05A439776 +CT=881188C2834B0496CB97F15F7A5C332A + +I=191 +KEY=A51CABC6D50BF9043E95CE2BC511D26DC7CD5F4F494A4FD828C8DCC7884A7E49 +PT=881188C2834B0496CB97F15F7A5C332A +CT=1FAE86251E2F615E3BFCAC545013CD12 + +I=192 +KEY=4EE1F6812CC35A16AA63F1CB39669ED7D863D96A57652E8613347093D859B35B +PT=1FAE86251E2F615E3BFCAC545013CD12 +CT=6017C6764080CB6D2BAC24C0F1BFF8F5 + +I=193 +KEY=F4F31D57DD72E6BF842D3834372AA60CB8741F1C17E5E5EB3898545329E64BAE +PT=6017C6764080CB6D2BAC24C0F1BFF8F5 +CT=10C8548253FB2BCD5D6F87CB28FAE7E7 + +I=194 +KEY=9DBB357DC99A95C240E750F1970C5C65A8BC4B9E441ECE2665F7D398011CAC49 +PT=10C8548253FB2BCD5D6F87CB28FAE7E7 +CT=20E253845A3DD51FFC16141FDAA20749 + +I=195 +KEY=A814CD8766E0BFFBD8530589D6202BE0885E181A1E231B3999E1C787DBBEAB00 +PT=20E253845A3DD51FFC16141FDAA20749 +CT=9383323218D891F9DCE7578FCD6A54A5 + +I=196 +KEY=C516C26E23E38C2B87346F759D8AEF881BDD2A2806FB8AC04506900816D4FFA5 +PT=9383323218D891F9DCE7578FCD6A54A5 +CT=9CFF8002D46EAFAAC7B035A788A37CF5 + +I=197 +KEY=9301F8120939D0E70C97F614F61F18648722AA2AD295256A82B6A5AF9E778350 +PT=9CFF8002D46EAFAAC7B035A788A37CF5 +CT=90C9F34994D5DA86406C7E82EDDD1009 + +I=198 +KEY=82B163831972D2CEF8F1780AA6B0707A17EB59634640FFECC2DADB2D73AA9359 +PT=90C9F34994D5DA86406C7E82EDDD1009 +CT=C8B5021EE84635EB7E7D0F5DBE967FD0 + +I=199 +KEY=F99FF8714EE5D822E0E25C499D7C96ACDF5E5B7DAE06CA07BCA7D470CD3CEC89 +PT=C8B5021EE84635EB7E7D0F5DBE967FD0 +CT=15CCB3C950764E24CA714707034DF9A7 + +I=200 +KEY=3529E6B83266BD558B7F33FC00AE4904CA92E8B4FE70842376D69377CE71152E +PT=15CCB3C950764E24CA714707034DF9A7 +CT=5FDA0EF6A2172D5DAA8E842F061A2E44 + +I=201 +KEY=2D77F95D8B556740CD9E2CC546CA45C99548E6425C67A97EDC581758C86B3B6A +PT=5FDA0EF6A2172D5DAA8E842F061A2E44 +CT=808781D0D10B3A02333E0A53E159287F + +I=202 +KEY=79298FD5F3C4B6378403CFAD05C3C96E15CF67928D6C937CEF661D0B29321315 +PT=808781D0D10B3A02333E0A53E159287F +CT=CC760400725FCFD37E757D99C6361B93 + +I=203 +KEY=69535F335F6AEBF452407F3F1C203410D9B96392FF335CAF91136092EF040886 +PT=CC760400725FCFD37E757D99C6361B93 +CT=247D3A6BB4C883C142C4000B085C3B79 + +I=204 +KEY=1A4F8FD7BD8DBCFB3677C708CDDDC7C4FDC459F94BFBDF6ED3D76099E75833FF +PT=247D3A6BB4C883C142C4000B085C3B79 +CT=47E4C802C61E6A1706BAE95AF75CA70D + +I=205 +KEY=A573989455A11CAD1E8642CD774806B1BA2091FB8DE5B579D56D89C3100494F2 +PT=47E4C802C61E6A1706BAE95AF75CA70D +CT=4297101350A5CE6C435FAD2725C22E46 + +I=206 +KEY=8D52414DD5600AA0CACD5AD399FD1B37F8B781E8DD407B15963224E435C6BAB4 +PT=4297101350A5CE6C435FAD2725C22E46 +CT=BEC56BF1F3B6BE60C0F4CB7AE77BF0F5 + +I=207 +KEY=49D4DF2FB3B561817F2BA6599B66C9244672EA192EF6C57556C6EF9ED2BD4A41 +PT=BEC56BF1F3B6BE60C0F4CB7AE77BF0F5 +CT=5B590F24D329BB6ED981938A4CDB9907 + +I=208 +KEY=68BD5721E2A51A184CDBAC3A035670701D2BE53DFDDF7E1B8F477C149E66D346 +PT=5B590F24D329BB6ED981938A4CDB9907 +CT=A8A15DBB79BB9B1131EF39C1E3FCFC9C + +I=209 +KEY=2CC71F1B9BE892100E8A340E61D0A128B58AB8868464E50ABEA845D57D9A2FDA +PT=A8A15DBB79BB9B1131EF39C1E3FCFC9C +CT=E8CBAB9E98D2866E779512AAC2FA2EA0 + +I=210 +KEY=EEF45CE1BB444A6BA5A029363FB9D4DB5D4113181CB66364C93D577FBF60017A +PT=E8CBAB9E98D2866E779512AAC2FA2EA0 +CT=7E4896F0A48A25FFE950B74B96F5F40E + +I=211 +KEY=151FE809785C11F8F19F31EA0246B416230985E8B83C469B206DE0342995F574 +PT=7E4896F0A48A25FFE950B74B96F5F40E +CT=E1C642B54B89822E73A695C851BC8EBE + +I=212 +KEY=14FE470CD366C580F124EA924B918BF5C2CFC75DF3B5C4B553CB75FC78297BCA +PT=E1C642B54B89822E73A695C851BC8EBE +CT=5FA2C6A2303ED7219984F30B78BE6B96 + +I=213 +KEY=92E61F4C495462354EF612492557D6AB9D6D01FFC38B1394CA4F86F70097105C +PT=5FA2C6A2303ED7219984F30B78BE6B96 +CT=3791959FBF178682A711623C2F91616C + +I=214 +KEY=6C0B6F23AC7526204C451A8ADE54D404AAFC94607C9C95166D5EE4CB2F067130 +PT=3791959FBF178682A711623C2F91616C +CT=E14FCACD5FD26FC2710776EE82317ABC + +I=215 +KEY=0DAE926E4172586817730DB9FDF2CE0B4BB35EAD234EFAD41C599225AD370B8C +PT=E14FCACD5FD26FC2710776EE82317ABC +CT=E576499EAF5365E7FE3B4961D9C74419 + +I=216 +KEY=DCD553F2977BD114B61F724ABC6AFE8EAEC517338C1D9F33E262DB4474F04F95 +PT=E576499EAF5365E7FE3B4961D9C74419 +CT=38567558119E72929F2932E6C289095E + +I=217 +KEY=6333DA8D5B655B5B5AABBCAF0B010BE89693626B9D83EDA17D4BE9A2B67946CB +PT=38567558119E72929F2932E6C289095E +CT=D20AD648F558E5507CC5C905E92CC268 + +I=218 +KEY=F9010180B464FBB8AD7C9D5E41B1E09A4499B42368DB08F1018E20A75F5584A3 +PT=D20AD648F558E5507CC5C905E92CC268 +CT=00C719F3757DDD2D2E64C3F2666FB2CB + +I=219 +KEY=8CE68ED02B4FFD9720B3D16FAE92D164445EADD01DA6D5DC2FEAE355393A3668 +PT=00C719F3757DDD2D2E64C3F2666FB2CB +CT=AEEAB9F50456CA3233A964219D2E7816 + +I=220 +KEY=57E26BA4DBD3549051B0D9436EB38D4FEAB4142519F01FEE1C438774A4144E7E +PT=AEEAB9F50456CA3233A964219D2E7816 +CT=3F02C97E127FD697AFD58BC66941F654 + +I=221 +KEY=4D0BC4A8796407C939797EF19D0CE7E3D5B6DD5B0B8FC979B3960CB2CD55B82A +PT=3F02C97E127FD697AFD58BC66941F654 +CT=BC4C0DDBCF0003B7814EEF1ABD22B6A8 + +I=222 +KEY=9C1FD1789544D2F3FF84574A216767CD69FAD080C48FCACE32D8E3A870770E82 +PT=BC4C0DDBCF0003B7814EEF1ABD22B6A8 +CT=D125D8C2920ADD3EA00103DC695A0D9D + +I=223 +KEY=ADBE97F99DBE61213892D9849B81B3FBB8DF0842568517F092D9E074192D031F +PT=D125D8C2920ADD3EA00103DC695A0D9D +CT=C0C57598639BA69E13C82E3AF24777C5 + +I=224 +KEY=A14DC5CF6CD0BD9AC9499317C509CCB4781A7DDA351EB16E8111CE4EEB6A74DA +PT=C0C57598639BA69E13C82E3AF24777C5 +CT=81E3B8F6A691BC30AA66AD70F0358881 + +I=225 +KEY=0EC479D8681AC8CA455D64A4BB34C86DF9F9C52C938F0D5E2B77633E1B5FFC5B +PT=81E3B8F6A691BC30AA66AD70F0358881 +CT=3CD03908D4ABA4B9885BCB1AC89D16C3 + +I=226 +KEY=E74102D814426E659732B303E6D44DB7C529FC244724A9E7A32CA824D3C2EA98 +PT=3CD03908D4ABA4B9885BCB1AC89D16C3 +CT=61662DD8EE676E17AE5CF2BABDC54A67 + +I=227 +KEY=EE4034F1A2EF16D7D848BB005CDA5E99A44FD1FCA943C7F00D705A9E6E07A0FF +PT=61662DD8EE676E17AE5CF2BABDC54A67 +CT=4E637432B0FF54FD665A902725B977EB + +I=228 +KEY=45E8F2DF7FC6E49FB0AF3B73788A1065EA2CA5CE19BC930D6B2ACAB94BBED714 +PT=4E637432B0FF54FD665A902725B977EB +CT=E53D1440407503B66530EEEEBBC9182B + +I=229 +KEY=0BEBC981186DEF84C01688CA16A061E00F11B18E59C990BB0E1A2457F077CF3F +PT=E53D1440407503B66530EEEEBBC9182B +CT=12134ADF5BB16D867B4EE9CE87EBE36D + +I=230 +KEY=6FADFDB92B0F888514730F17A37A81B61D02FB510278FD3D7554CD99779C2C52 +PT=12134ADF5BB16D867B4EE9CE87EBE36D +CT=310EACEF26A3EB5E4511437145DC30F9 + +I=231 +KEY=A565724F25EE29346543964864A0FFAA2C0C57BE24DB166330458EE832401CAB +PT=310EACEF26A3EB5E4511437145DC30F9 +CT=6848E5A618419EC6BACD9CD40BB42083 + +I=232 +KEY=1FAEBFE13AC7545DC742ED60241BC2E84444B2183C9A88A58A88123C39F43C28 +PT=6848E5A618419EC6BACD9CD40BB42083 +CT=C64DA25E7CB1A004E31CD37F9D4E1112 + +I=233 +KEY=A8EE2725373C48BAD9C0009C53C298A982091046402B28A16994C143A4BA2D3A +PT=C64DA25E7CB1A004E31CD37F9D4E1112 +CT=D02E6AE8FDD0C5813669080AA7B82527 + +I=234 +KEY=0770874A41ED1396940D75E6A5A09F5352277AAEBDFBED205FFDC9490302081D +PT=D02E6AE8FDD0C5813669080AA7B82527 +CT=5DDFBC75FE48D88E7D6F307E4A008BC7 + +I=235 +KEY=D7D098F85AB45E754629D2AB7DA2226C0FF8C6DB43B335AE2292F937490283DA +PT=5DDFBC75FE48D88E7D6F307E4A008BC7 +CT=E216C9AC28239E97237930079739ECE0 + +I=236 +KEY=5D6FAFF37EE7400691E504578251ECB1EDEE0F776B90AB3901EBC930DE3B6F3A +PT=E216C9AC28239E97237930079739ECE0 +CT=8D126659360D03548879000642E78029 + +I=237 +KEY=D75C5C64D94D0BC8566F568278B502D560FC692E5D9DA86D8992C9369CDCEF13 +PT=8D126659360D03548879000642E78029 +CT=9EA4C85D0F07AD618A2EBEBBE50D72B6 + +I=238 +KEY=D42BD9CDCD8BDA71E64817A2755C97C0FE58A173529A050C03BC778D79D19DA5 +PT=9EA4C85D0F07AD618A2EBEBBE50D72B6 +CT=1F525901AF1D94BA6CA3C7244E2CD885 + +I=239 +KEY=32DD1758D2EFC602EE85C58A66D0B080E10AF872FD8791B66F1FB0A937FD4520 +PT=1F525901AF1D94BA6CA3C7244E2CD885 +CT=E131C071BFA21FCE21D18DB87B522903 + +I=240 +KEY=BEC98C02D74E088458A668D0B6DDCF13003B380342258E784ECE3D114CAF6C23 +PT=E131C071BFA21FCE21D18DB87B522903 +CT=51F1B72C99C869BF73A6637D3A2E2278 + +I=241 +KEY=D368F7BE25A6A0C9AD2004E764F43A3551CA8F2FDBEDE7C73D685E6C76814E5B +PT=51F1B72C99C869BF73A6637D3A2E2278 +CT=0965CDD7A134672036F0C69774CFD380 + +I=242 +KEY=E5A7E12124540DBB4147A55C276A35B958AF42F87AD980E70B9898FB024E9DDB +PT=0965CDD7A134672036F0C69774CFD380 +CT=52ECEB721073FBF3D1BD5808351BEC5E + +I=243 +KEY=7D9702E2C8906805A580D5D85B03BBC60A43A98A6AAA7B14DA25C0F337557185 +PT=52ECEB721073FBF3D1BD5808351BEC5E +CT=493CE4E2B090DA3A2354C9DA7DB44D39 + +I=244 +KEY=8EFA5EC96F3AEF51AB38F4CCD969E5D5437F4D68DA3AA12EF97109294AE13CBC +PT=493CE4E2B090DA3A2354C9DA7DB44D39 +CT=DA64246FF65969995F9A4E8AE7C805CF + +I=245 +KEY=19C97957444E9931293047A647D7A19A991B69072C63C8B7A6EB47A3AD293973 +PT=DA64246FF65969995F9A4E8AE7C805CF +CT=CF85EBD76908CD8F8D3177E53DA3AD5E + +I=246 +KEY=7BDB3ED45BD78C131611FD9D54B8E9D2569E82D0456B05382BDA3046908A942D +PT=CF85EBD76908CD8F8D3177E53DA3AD5E +CT=45E1FDEFC98E62A841BD1D8D8236CEEF + +I=247 +KEY=19961521A42D96238D44F651E7E7D463137F7F3F8CE567906A672DCB12BC5AC2 +PT=45E1FDEFC98E62A841BD1D8D8236CEEF +CT=E056EF7B711A9CBDED8878EF74AF1671 + +I=248 +KEY=343360636E697E607319D4DCBC12B543F3299044FDFFFB2D87EF552466134CB3 +PT=E056EF7B711A9CBDED8878EF74AF1671 +CT=E4EFF77C6C3273393BE4814A16C3DF4A + +I=249 +KEY=B63D4D3D099F8E68F6A041D2EB1B1C1417C6673891CD8814BC0BD46E70D093F9 +PT=E4EFF77C6C3273393BE4814A16C3DF4A +CT=EC562E353DF8BA76699B01A6ACC8AD52 + +I=250 +KEY=EF500379EDE772968F1499F07B0B09CFFB90490DAC353262D590D5C8DC183EAB +PT=EC562E353DF8BA76699B01A6ACC8AD52 +CT=4473050ADC687112AACB86AA73CB6C6D + +I=251 +KEY=EA5CD4EDD99E64018AD3104026F0F528BFE34C07705D43707F5B5362AFD352C6 +PT=4473050ADC687112AACB86AA73CB6C6D +CT=6561A82EE86E4F18DF6965312F0C0984 + +I=252 +KEY=2ABF9529FC88D85FF68CF6D72B9A9CB5DA82E42998330C68A032365380DF5B42 +PT=6561A82EE86E4F18DF6965312F0C0984 +CT=47590CE1C90F3AC2C68B272B4A667F61 + +I=253 +KEY=A485B647790DBFF76F16C42A39F5F5559DDBE8C8513C36AA66B91178CAB92423 +PT=47590CE1C90F3AC2C68B272B4A667F61 +CT=4ED731A36BCB2672A810633E432D8922 + +I=254 +KEY=F0D0E858B597595A06458FF6C2259127D30CD96B3AF710D8CEA972468994AD01 +PT=4ED731A36BCB2672A810633E432D8922 +CT=4AC2F0D5F52762F77DB5D9EF53B76642 + +I=255 +KEY=EDDE80556ECA4CC51EFB33E23C43C04399CE29BECFD0722FB31CABA9DA23CB43 +PT=4AC2F0D5F52762F77DB5D9EF53B76642 +CT=A574FBE71E359A57D57A24A388FDF6EE + +I=256 +KEY=3C7C248C9FCE1D060D5B0664C0FF3F6B3CBAD259D1E5E87866668F0A52DE3DAD +PT=A574FBE71E359A57D57A24A388FDF6EE +CT=CCC3A011108469A7987F336C209BB84E + +I=257 +KEY=D43727570A809BE0D9EB78760FE4CDA9F0797248C16181DFFE19BC66724585E3 +PT=CCC3A011108469A7987F336C209BB84E +CT=686357D3013977390164834D4E5324DC + +I=258 +KEY=2F060E361977E544B98779AB55886D57981A259BC058F6E6FF7D3F2B3C16A13F +PT=686357D3013977390164834D4E5324DC +CT=DDDAD6FBDBF7C7BE7EBF3F036009A270 + +I=259 +KEY=A3630C05DC65905D37AFDB315B2AA4D945C0F3601BAF315881C200285C1F034F +PT=DDDAD6FBDBF7C7BE7EBF3F036009A270 +CT=237124FEDF28B4201B6D1584B93D5F7C + +I=260 +KEY=3E6ADAAEF53A36294CDEA0D94BE742C166B1D79EC48785789AAF15ACE5225C33 +PT=237124FEDF28B4201B6D1584B93D5F7C +CT=D1A9DDFB5662934AAD98B2861E50A871 + +I=261 +KEY=234615019E03C466AEA186112C4EB523B7180A6592E516323737A72AFB72F442 +PT=D1A9DDFB5662934AAD98B2861E50A871 +CT=CA18344F4C7A0F068398CA8137C056DD + +I=262 +KEY=22ED93581611798050E94CC70F6090BF7D003E2ADE9F1934B4AF6DABCCB2A29F +PT=CA18344F4C7A0F068398CA8137C056DD +CT=91FA4D62D10E852D9EDA42FAC8C34557 + +I=263 +KEY=A5981D9A37D6D3D948391D1D462B6DCFECFA73480F919C192A752F510471E7C8 +PT=91FA4D62D10E852D9EDA42FAC8C34557 +CT=B956221510135066B2B2552C4CB37642 + +I=264 +KEY=BF2E4397D0E93DFFA38D69B30F33835B55AC515D1F82CC7F98C77A7D48C2918A +PT=B956221510135066B2B2552C4CB37642 +CT=300CFCEAFED28E622CD08222D3A3B0B0 + +I=265 +KEY=55432143B807A628001F8D062CE0157265A0ADB7E150421DB417F85F9B61213A +PT=300CFCEAFED28E622CD08222D3A3B0B0 +CT=26681BCFDC630A21A684C60EF6A23747 + +I=266 +KEY=2966A6CB3BA9028583813B91FD72748D43C8B6783D33483C12933E516DC3167D +PT=26681BCFDC630A21A684C60EF6A23747 +CT=8EDD4B1B458D16841AD4525C01A8397E + +I=267 +KEY=1A22288AC28060F8E4B20C2AE0C82AEACD15FD6378BE5EB808476C0D6C6B2F03 +PT=8EDD4B1B458D16841AD4525C01A8397E +CT=BFDE412A7CAF0326AD1727996056A61C + +I=268 +KEY=C882E880508E92FF709E9BD4A555B30A72CBBC4904115D9EA5504B940C3D891F +PT=BFDE412A7CAF0326AD1727996056A61C +CT=88C039A0B395C5D08848C64DFC150C57 + +I=269 +KEY=298B3829EE60112C926E1FD583C9A2DEFA0B85E9B784984E2D188DD9F0288548 +PT=88C039A0B395C5D08848C64DFC150C57 +CT=ACDF23F2CB73FD8D3D814A79E3C94126 + +I=270 +KEY=2F2A3D0DDB2DBA8B8E3FF8A9DE765FE356D4A61B7CF765C31099C7A013E1C46E +PT=ACDF23F2CB73FD8D3D814A79E3C94126 +CT=A8BE26FE8780972650D5F384B744AC44 + +I=271 +KEY=F8CC20E8296CD38F1EF8BB2777EE1200FE6A80E5FB77F2E5404C3424A4A5682A +PT=A8BE26FE8780972650D5F384B744AC44 +CT=B5557CC20F64FCC576A6EC7BE324CE43 + +I=272 +KEY=678B5341F1BC13DB366B36D59ADADC7C4B3FFC27F4130E2036EAD85F4781A669 +PT=B5557CC20F64FCC576A6EC7BE324CE43 +CT=B59281EFF9C8D19E5D9C053CBE1F2F33 + +I=273 +KEY=E4701C9009693E38C455CE186A4B87DFFEAD7DC80DDBDFBE6B76DD63F99E895A +PT=B59281EFF9C8D19E5D9C053CBE1F2F33 +CT=7E8B1D4BFF81C5B9AA1FCA81DF8DE64F + +I=274 +KEY=C1F886CBCBF2BD920A0E68F30FCB8FCE80266083F25A1A07C16917E226136F15 +PT=7E8B1D4BFF81C5B9AA1FCA81DF8DE64F +CT=20841B35C77A109B528A1135E17D36EE + +I=275 +KEY=F05D61A9441B3C741D9D7489F2EE4A5EA0A27BB635200A9C93E306D7C76E59FB +PT=20841B35C77A109B528A1135E17D36EE +CT=C3195DC001FA1AD7C253DD3FE4A4BC7D + +I=276 +KEY=0C8E70943252DD5DC9819A9FDB375B3F63BB267634DA104B51B0DBE823CAE586 +PT=C3195DC001FA1AD7C253DD3FE4A4BC7D +CT=7E06BD1B3440DB4CA73AF1A05B33AD3F + +I=277 +KEY=84F1B5CF1AD11205E98ECD317AD670A11DBD9B6D009ACB07F68A2A4878F948B9 +PT=7E06BD1B3440DB4CA73AF1A05B33AD3F +CT=6224DBD71C1DC35A5C62777D2EA32C3E + +I=278 +KEY=E3465353AED687EF62CD1DA8D7DA3EEB7F9940BA1C87085DAAE85D35565A6487 +PT=6224DBD71C1DC35A5C62777D2EA32C3E +CT=1E4E51CD7BA1F7467AC69755F8894EF4 + +I=279 +KEY=31F715D1FFA116F58AB70E4A3EEF6E9561D711776726FF1BD02ECA60AED32A73 +PT=1E4E51CD7BA1F7467AC69755F8894EF4 +CT=4AB8AFEACB2A1B1AE9E74D647266E234 + +I=280 +KEY=487B6847CA14B04D429C81278332273F2B6FBE9DAC0CE40139C98704DCB5C847 +PT=4AB8AFEACB2A1B1AE9E74D647266E234 +CT=64C0BBA15382C142BBEE84B86B7D0BA0 + +I=281 +KEY=D1C9CA26B21945011B044EA6E29C9AD54FAF053CFF8E2543822703BCB7C8C3E7 +PT=64C0BBA15382C142BBEE84B86B7D0BA0 +CT=F82292AF614648EC6C1E9A1027167410 + +I=282 +KEY=3F585C00E187BE1B0C9E09781C9548A8B78D97939EC86DAFEE3999AC90DEB7F7 +PT=F82292AF614648EC6C1E9A1027167410 +CT=31C38ED5F207B412A14A51632D8805CE + +I=283 +KEY=340B8C115BAFF387400CD8F0EE8F8F6F864E19466CCFD9BD4F73C8CFBD56B239 +PT=31C38ED5F207B412A14A51632D8805CE +CT=3FC4CC8F4245BBBC5939A0C0A24A14DE + +I=284 +KEY=EA8EACF07402225D6C5181A8802DA515B98AD5C92E8A6201164A680F1F1CA6E7 +PT=3FC4CC8F4245BBBC5939A0C0A24A14DE +CT=23A98FA41D6C3D4CD9CFB9737A6D7872 + +I=285 +KEY=56EF7B73BF04F5F463E4D0EA0F6FC4DA9A235A6D33E65F4DCF85D17C6571DE95 +PT=23A98FA41D6C3D4CD9CFB9737A6D7872 +CT=82CC2D376B2772B7B988BEA17EFBB3D2 + +I=286 +KEY=C425E380DA91C34B73CE922C59B13C8818EF775A58C12DFA760D6FDD1B8A6D47 +PT=82CC2D376B2772B7B988BEA17EFBB3D2 +CT=5330F6218D528A32B24085EA496A05A9 + +I=287 +KEY=EA66C7FF9FCD2F9E76BCC5C6387E133E4BDF817BD593A7C8C44DEA3752E068EE +PT=5330F6218D528A32B24085EA496A05A9 +CT=7C1E082C2C89C90AD91AE81DF73F1F5F + +I=288 +KEY=C89CF336490832FB54BB536813AEE6EA37C18957F91A6EC21D57022AA5DF77B1 +PT=7C1E082C2C89C90AD91AE81DF73F1F5F +CT=2AB33673B654E2C49D6736D65A5F45C8 + +I=289 +KEY=7CC5409A9AE1F997774C3FEB74A6E9061D72BF244F4E8C06803034FCFF803279 +PT=2AB33673B654E2C49D6736D65A5F45C8 +CT=21BA6CADDCA5E0BE779D1A2651794C81 + +I=290 +KEY=E5E1873FDEE9DC066AF79C0E6027D0703CC8D38993EB6CB8F7AD2EDAAEF97EF8 +PT=21BA6CADDCA5E0BE779D1A2651794C81 +CT=8E2AF8BA54CF04812AE786C180FCFCA8 + +I=291 +KEY=844AA67914DE1C11677B5526D5B12765B2E22B33C7246839DD4AA81B2E058250 +PT=8E2AF8BA54CF04812AE786C180FCFCA8 +CT=E48A7CD35CA33B1D919B8A83ADF4C6BE + +I=292 +KEY=FE3248768ACB0AF9DBD639AF7B7EB944566857E09B8753244CD1229883F144EE +PT=E48A7CD35CA33B1D919B8A83ADF4C6BE +CT=C377A76CF43C27784CC54079744413D1 + +I=293 +KEY=709E7BC30A7DE8FADC071B3D04338FCA951FF08C6FBB745C001462E1F7B5573F +PT=C377A76CF43C27784CC54079744413D1 +CT=01D8083A9EA403A4754EF82CA29CDD5B + +I=294 +KEY=448B1AEC2F68D202679183D85C4A6D2194C7F8B6F11F77F8755A9ACD55298A64 +PT=01D8083A9EA403A4754EF82CA29CDD5B +CT=46ADC32EFF2C3EFF40B468E845EFC2E4 + +I=295 +KEY=529401616FA6193014D6A10BEF1A816FD26A3B980E33490735EEF22510C64880 +PT=46ADC32EFF2C3EFF40B468E845EFC2E4 +CT=FCC6594B1BBF40E28BE798ABC00163F1 + +I=296 +KEY=15A5E8BAF02EF91390AB7D35742CC5C12EAC62D3158C09E5BE096A8ED0C72B71 +PT=FCC6594B1BBF40E28BE798ABC00163F1 +CT=28D35B6E1140738ED1DF20FE11003B1E + +I=297 +KEY=589C04ECDF2B884807919A2018A93080067F39BD04CC7A6B6FD64A70C1C7106F +PT=28D35B6E1140738ED1DF20FE11003B1E +CT=3354C7962E19FB043FD4CD7B2C99E195 + +I=298 +KEY=A6987BEB541098C7173475B34568F36B352BFE2B2AD5816F5002870BED5EF1FA +PT=3354C7962E19FB043FD4CD7B2C99E195 +CT=EB76F282C9F10F507FACFCDEEC8BBBB8 + +I=299 +KEY=3732B395057761A8A2624F52354668CFDE5D0CA9E3248E3F2FAE7BD501D54A42 +PT=EB76F282C9F10F507FACFCDEEC8BBBB8 +CT=77A4DAE8406992C5018D6B0310195E0C + +I=300 +KEY=E24C9F98F43E840AE04ED4928133F65AA9F9D641A34D1CFA2E2310D611CC144E +PT=77A4DAE8406992C5018D6B0310195E0C +CT=655DEC1062EDB50B8B31A66071E236A2 + +I=301 +KEY=8BA207CA6E2B720810E66CCAB597E8DACCA43A51C1A0A9F1A512B6B6602E22EC +PT=655DEC1062EDB50B8B31A66071E236A2 +CT=28A22A069D8FF3DE359860B0A5B6FD1F + +I=302 +KEY=22C629C84758D553AFE4876AA739A1F0E40610575C2F5A2F908AD606C598DFF3 +PT=28A22A069D8FF3DE359860B0A5B6FD1F +CT=95DD88B4AFD0680E221C70422ADFFCD1 + +I=303 +KEY=F86A3C799AAB6884220196BF07E1643D71DB98E3F3FF3221B296A644EF472322 +PT=95DD88B4AFD0680E221C70422ADFFCD1 +CT=323475C634FD6845BAA9F371F29DC363 + +I=304 +KEY=83412E9600B279F76C93F171C469AD1943EFED25C7025A64083F55351DDAE041 +PT=323475C634FD6845BAA9F371F29DC363 +CT=61276AD535F9E73FCFB53DBF2D5D1F62 + +I=305 +KEY=01AD15137C4A572322660716B6B4EDCD22C887F0F2FBBD5BC78A688A3087FF23 +PT=61276AD535F9E73FCFB53DBF2D5D1F62 +CT=105ECB04A5CA32FC93987569A7CB46D7 + +I=306 +KEY=1CC639BA56CA0DF23E64BB3395C08BB332964CF457318FA754121DE3974CB9F4 +PT=105ECB04A5CA32FC93987569A7CB46D7 +CT=831DBB3F4BBD4343B94D54AA2B3E0620 + +I=307 +KEY=25ABCF5B8DB1A7CCB1FA49936E0AB3C8B18BF7CB1C8CCCE4ED5F4949BC72BFD4 +PT=831DBB3F4BBD4343B94D54AA2B3E0620 +CT=40B9D9C6201E639DC9A04E500BCD7F61 + +I=308 +KEY=75B34E0F371C4527732F22CF35AD923BF1322E0D3C92AF7924FF0719B7BFC0B5 +PT=40B9D9C6201E639DC9A04E500BCD7F61 +CT=A159BB0C751148C14D561E0407A9F6DB + +I=309 +KEY=1EB6E3491B431B7EFFCCC965C9041274506B95014983E7B869A9191DB016366E +PT=A159BB0C751148C14D561E0407A9F6DB +CT=2012E67815334AC48E5309DD129E0476 + +I=310 +KEY=F0BDAFB216613A6FB3819D08B17EFDC1707973795CB0AD7CE7FA10C0A2883218 +PT=2012E67815334AC48E5309DD129E0476 +CT=53E415BC0C9013F83B77298395FC9FEF + +I=311 +KEY=9C5A3B9C862E07159AB06D5B7FB585C5239D66C55020BE84DC8D39433774ADF7 +PT=53E415BC0C9013F83B77298395FC9FEF +CT=2B1EEAA13373494A2A56C15FD5ECA103 + +I=312 +KEY=9764AC349B8222394160F4896BA6761808838C646353F7CEF6DBF81CE2980CF4 +PT=2B1EEAA13373494A2A56C15FD5ECA103 +CT=2A00E873782853DC842427A03C30A81A + +I=313 +KEY=42A1614569C4DE66D6336BC082B3B9DD228364171B7BA41272FFDFBCDEA8A4EE +PT=2A00E873782853DC842427A03C30A81A +CT=5FEB74E489C4C8121A15C2BCF51046A5 + +I=314 +KEY=CED80BE0859A5863CFE41F0F2CE9F65B7D6810F392BF6C0068EA1D002BB8E24B +PT=5FEB74E489C4C8121A15C2BCF51046A5 +CT=948214D5DB68997C37A48927AA97B89A + +I=315 +KEY=178DAF533EBB695D5E57401E5345C3E8E9EA042649D7F57C5F4E9427812F5AD1 +PT=948214D5DB68997C37A48927AA97B89A +CT=AB8F3BB9917E4D1C8F1F2EDDB7070530 + +I=316 +KEY=66F4B8B5A0BD877514FDB4CD2DD04D8C42653F9FD8A9B860D051BAFA36285FE1 +PT=AB8F3BB9917E4D1C8F1F2EDDB7070530 +CT=CB5FB11C6DB1AB6BC189F0F3FB47A2A5 + +I=317 +KEY=9753278CFCEE8B059ECF573A2E0D65D6893A8E83B518130B11D84A09CD6FFD44 +PT=CB5FB11C6DB1AB6BC189F0F3FB47A2A5 +CT=F0CE65E6C5C263182E6C253F26460A1B + +I=318 +KEY=121A860A5B53C56E536DE56566F31E2079F4EB6570DA70133FB46F36EB29F75F +PT=F0CE65E6C5C263182E6C253F26460A1B +CT=9AA17B0F532814CA74FF0A046F377C48 + +I=319 +KEY=88F5E58E9522495BF7B68430946F7C0FE355906A23F264D94B4B6532841E8B17 +PT=9AA17B0F532814CA74FF0A046F377C48 +CT=52CAAEF16E55858487AEDBDBA822002D + +I=320 +KEY=D9A3D3547F215D44D80C6A5D3548D4D2B19F3E9B4DA7E15DCCE5BEE92C3C8B3A +PT=52CAAEF16E55858487AEDBDBA822002D +CT=2599545FD15C7F59A6F02CDCB95E6589 + +I=321 +KEY=6ACE86543B0F981C2D0FCB1408A42C3294066AC49CFB9E046A1592359562EEB3 +PT=2599545FD15C7F59A6F02CDCB95E6589 +CT=DC7A68313CE3E1963D31E5149CDBE22A + +I=322 +KEY=E9D6D08194DAFBB7B491124515118FA6487C02F5A0187F925724772109B90C99 +PT=DC7A68313CE3E1963D31E5149CDBE22A +CT=333B588A7354CB3229E43780AFE4738D + +I=323 +KEY=762FC93CEED1EE9C6EF702A4E3BBABD67B475A7FD34CB4A07EC040A1A65D7F14 +PT=333B588A7354CB3229E43780AFE4738D +CT=41727DC0D18725AFD2EF8FF51EAE1C2C + +I=324 +KEY=FF4EC1DF818E820424CFE5D09EE2E5423A3527BF02CB910FAC2FCF54B8F36338 +PT=41727DC0D18725AFD2EF8FF51EAE1C2C +CT=A7236B16D9937C84F37BF9D79D0251F9 + +I=325 +KEY=59BDAB706DEA2EC52AE05A2E4382A4169D164CA9DB58ED8B5F54368325F132C1 +PT=A7236B16D9937C84F37BF9D79D0251F9 +CT=B81D30EFDB86688F1DCA616EC771B9FD + +I=326 +KEY=4C008516CD614B6588A526FFE33C055B250B7C4600DE8504429E57EDE2808B3C +PT=B81D30EFDB86688F1DCA616EC771B9FD +CT=A5AD142C8F078ABF419B7CF5C86C9F83 + +I=327 +KEY=DB65698F99E4A27019ABE194A89E9BC680A6686A8FD90FBB03052B182AEC14BF +PT=A5AD142C8F078ABF419B7CF5C86C9F83 +CT=861B59E3B61A5D02F0D70DFF40EF7FF2 + +I=328 +KEY=0790C16C53A7826B4B309DDF99B5239006BD318939C352B9F3D226E76A036B4D +PT=861B59E3B61A5D02F0D70DFF40EF7FF2 +CT=B0F4C2C4D0D282BE3128AD78D34B1FA6 + +I=329 +KEY=AFE168F089E676A806DD191003777E6DB649F34DE911D007C2FA8B9FB94874EB +PT=B0F4C2C4D0D282BE3128AD78D34B1FA6 +CT=9DFCF5727851ADE8C37A9AA3AA77B20D + +I=330 +KEY=F261CDF199D9EF436C1A08EB9755A2112BB5063F91407DEF0180113C133FC6E6 +PT=9DFCF5727851ADE8C37A9AA3AA77B20D +CT=9268DBA972B72C9DEF15CF9B8041F23B + +I=331 +KEY=E0D6DCF3BA840720688456A43E849C5CB9DDDD96E3F75172EE95DEA7937E34DD +PT=9268DBA972B72C9DEF15CF9B8041F23B +CT=D45A8B321CB6D8F28167C857BC2900BF + +I=332 +KEY=B77CF3A880C2E9E66D0C98A4D88555F46D8756A4FF4189806FF216F02F573462 +PT=D45A8B321CB6D8F28167C857BC2900BF +CT=0124FE2D8BCB81E1286A18D2BABEA919 + +I=333 +KEY=7729E55EFA6B249E0207E06AAF6F09206CA3A889748A086147980E2295E99D7B +PT=0124FE2D8BCB81E1286A18D2BABEA919 +CT=A1BB0D975A50BE8BD8C2973D4BA7BF42 + +I=334 +KEY=102384784C54539084BC7181AA95F184CD18A51E2EDAB6EA9F5A991FDE4E2239 +PT=A1BB0D975A50BE8BD8C2973D4BA7BF42 +CT=15302D5DBFD8E407EADDE9896B42CB13 + +I=335 +KEY=9FF48EF1068BFC07DA38F7790D7418D2D8288843910252ED75877096B50CE92A +PT=15302D5DBFD8E407EADDE9896B42CB13 +CT=90D93B8F802CFAD3F6E682DD704B5F43 + +I=336 +KEY=84477EB9007ECDF8D1C4A6A976C76AB848F1B3CC112EA83E8361F24BC547B669 +PT=90D93B8F802CFAD3F6E682DD704B5F43 +CT=2DD7E0B91C5DDF0FD118F4CDD836A212 + +I=337 +KEY=F1CE87DE930567CE29DF313D8778358D652653750D737731527906861D71147B +PT=2DD7E0B91C5DDF0FD118F4CDD836A212 +CT=AC9D307EFF44703D6FDA621FFF8D077C + +I=338 +KEY=22D31C8F64CFB23620A70E7CD4A486D3C9BB630BF237070C3DA36499E2FC1307 +PT=AC9D307EFF44703D6FDA621FFF8D077C +CT=CC6772DE3B27CB1DB3E5A804843EB6FF + +I=339 +KEY=FC9057D2D2D28BFAC4D5E3654717188205DC11D5C910CC118E46CC9D66C2A5F8 +PT=CC6772DE3B27CB1DB3E5A804843EB6FF +CT=BDB021550FE0744090EAFEEBCF422061 + +I=340 +KEY=1EA032190E7E4CC45D2E1E138429658AB86C3080C6F0B8511EAC3276A9808599 +PT=BDB021550FE0744090EAFEEBCF422061 +CT=C6E21F9A1305C3969F2D70C11D58A1A7 + +I=341 +KEY=B633EDA212B952785755700FBDC91CA57E8E2F1AD5F57BC7818142B7B4D8243E +PT=C6E21F9A1305C3969F2D70C11D58A1A7 +CT=01BC936B7063CA9D28DB1FFCCB9C2048 + +I=342 +KEY=94A06984520AB40D74568F0D5286AEE37F32BC71A596B15AA95A5D4B7F440476 +PT=01BC936B7063CA9D28DB1FFCCB9C2048 +CT=88279D100DFA68CEBD9949F19C3333F4 + +I=343 +KEY=96A3BD621155F71A9EFB8E35F95238ACF7152161A86CD99414C314BAE3773782 +PT=88279D100DFA68CEBD9949F19C3333F4 +CT=41574A686596D4741BF5DE52B5183260 + +I=344 +KEY=185312E4301E5AADC373CEB3EBA66FB7B6426B09CDFA0DE00F36CAE8566F05E2 +PT=41574A686596D4741BF5DE52B5183260 +CT=BD9F5087C32A66A4797C7EE87355FF4A + +I=345 +KEY=BC5D60D256DCA48E88E52F05C349431A0BDD3B8E0ED06B44764AB400253AFAA8 +PT=BD9F5087C32A66A4797C7EE87355FF4A +CT=A88BC3FAF87D6C1D3F98A2884EF1D4DA + +I=346 +KEY=1485A9209167A6FA2ECD2CE6AA03DBA5A356F874F6AD075949D216886BCB2E72 +PT=A88BC3FAF87D6C1D3F98A2884EF1D4DA +CT=E514E6E34A050EB917F2382EDF92353A + +I=347 +KEY=2B62B0E29763FF09F53A2006B990E97746421E97BCA809E05E202EA6B4591B48 +PT=E514E6E34A050EB917F2382EDF92353A +CT=142EEBE72E0F56ABE5D67FCC28F957F6 + +I=348 +KEY=FC13067E362B7C9C39AA73B85F32011C526CF57092A75F4BBBF6516A9CA04CBE +PT=142EEBE72E0F56ABE5D67FCC28F957F6 +CT=24FDB7A03FE8A9288BFAA5AC2527D015 + +I=349 +KEY=8AC3B473244989EA74025FE98269BC17769142D0AD4FF663300CF4C6B9879CAB +PT=24FDB7A03FE8A9288BFAA5AC2527D015 +CT=649095ABA5F4006B7B89D20F10A37AE9 + +I=350 +KEY=FD0F4205DBFF0160203898EF02E9088E1201D77B08BBF6084B8526C9A924E642 +PT=649095ABA5F4006B7B89D20F10A37AE9 +CT=F5428E8BDDDC31FC8EF67BC7DB3201D3 + +I=351 +KEY=701AF95194FB0918BC2CA79AFD507336E74359F0D567C7F4C5735D0E7216E791 +PT=F5428E8BDDDC31FC8EF67BC7DB3201D3 +CT=A56B2014A4929373DC1F6FD5C0AC138C + +I=352 +KEY=633D0E72722E6443D4E219086D221939422879E471F55487196C32DBB2BAF41D +PT=A56B2014A4929373DC1F6FD5C0AC138C +CT=F35F9CD43144B358843A48B4D1C41882 + +I=353 +KEY=DCA79BA0184EC0A22A875E5057CA967AB177E53040B1E7DF9D567A6F637EEC9F +PT=F35F9CD43144B358843A48B4D1C41882 +CT=A572C1F98330A1C1FA91DFD5A5B76AB9 + +I=354 +KEY=A3D0FE4C3C1A1CE19CF66CF80135553D140524C9C381461E67C7A5BAC6C98626 +PT=A572C1F98330A1C1FA91DFD5A5B76AB9 +CT=23C56E065427F0409504053DD8A994CD + +I=355 +KEY=175C8D4085802768D20875CDBE6EFE2437C04ACF97A6B65EF2C3A0871E6012EB +PT=23C56E065427F0409504053DD8A994CD +CT=7E666724C1CAC0A582325381E9C98D73 + +I=356 +KEY=800EE65CA3DE8643371DA10FB0605AB649A62DEB566C76FB70F1F306F7A99F98 +PT=7E666724C1CAC0A582325381E9C98D73 +CT=B6C18D730A074196884CADF151CAC890 + +I=357 +KEY=F526E578E8978822944644B146154425FF67A0985C6B376DF8BD5EF7A6635708 +PT=B6C18D730A074196884CADF151CAC890 +CT=0068BB370419CD39748559C2DE206817 + +I=358 +KEY=7D144850BE03306F41A642442890EA20FF0F1BAF5872FA548C38073578433F1F +PT=0068BB370419CD39748559C2DE206817 +CT=56852D240F01729C4EAD0B1FFC3EDA1F + +I=359 +KEY=33B2189E3774B1A066BE522C07550F88A98A368B577388C8C2950C2A847DE500 +PT=56852D240F01729C4EAD0B1FFC3EDA1F +CT=458633A84E1F5737E9668A37388CF3C2 + +I=360 +KEY=CF53C76250347B0CC5CAC660D52199B1EC0C0523196CDFFF2BF3861DBCF116C2 +PT=458633A84E1F5737E9668A37388CF3C2 +CT=F96E181E03350F27106C8D24403A49DD + +I=361 +KEY=618676C1702531077565060B5DA0570B15621D3D1A59D0D83B9F0B39FCCB5F1F +PT=F96E181E03350F27106C8D24403A49DD +CT=B515584E252F703A4EB55E81EDA58E30 + +I=362 +KEY=D2C8CF9645CD741F67263845150FE649A07745733F76A0E2752A55B8116ED12F +PT=B515584E252F703A4EB55E81EDA58E30 +CT=54E7D10C236785AFE0A93B3971D6F237 + +I=363 +KEY=D0847F41C7940023491C2F83D02F8271F490947F1C11254D95836E8160B82318 +PT=54E7D10C236785AFE0A93B3971D6F237 +CT=937DFDE10E96030A0A8823EA3EF31B98 + +I=364 +KEY=17502FC3077EFD420D2268CE0FF26F4667ED699E128726479F0B4D6B5E4B3880 +PT=937DFDE10E96030A0A8823EA3EF31B98 +CT=93FDF0392A3391C74DBE4229792C9630 + +I=365 +KEY=4D6AA08A6C7EB7CA9CBE7AF4500C229EF41099A738B4B780D2B50F422767AEB0 +PT=93FDF0392A3391C74DBE4229792C9630 +CT=B9F80E1476658E6CE7FADBA215298958 + +I=366 +KEY=D8820A50934290C146AFE477D9D4A0224DE897B34ED139EC354FD4E0324E27E8 +PT=B9F80E1476658E6CE7FADBA215298958 +CT=87ACDCD1F1332B9961CC5E18F9009A39 + +I=367 +KEY=50E8959452DD52247A6F21A0C7BEDEB8CA444B62BFE2127554838AF8CB4EBDD1 +PT=87ACDCD1F1332B9961CC5E18F9009A39 +CT=3DD6249971FEC0FB4432236078D98D53 + +I=368 +KEY=7A1973C5B90748596A54C709D1598DA5F7926FFBCE1CD28E10B1A998B3973082 +PT=3DD6249971FEC0FB4432236078D98D53 +CT=D540F8BDE3442D17E88B524D00618309 + +I=369 +KEY=F9C08719A452CA931A62C5BD8F1D669D22D297462D58FF99F83AFBD5B3F6B38B +PT=D540F8BDE3442D17E88B524D00618309 +CT=7BB18B2DA9ED188BCE3B18C02C9B3F3B + +I=370 +KEY=5EBA35F7E58381DBE29EC4A1D9B5B9AD59631C6B84B5E7123601E3159F6D8CB0 +PT=7BB18B2DA9ED188BCE3B18C02C9B3F3B +CT=9A7380BAA169495B0FC29BB002D70E48 + +I=371 +KEY=E442442FE32FA6BDA63AF0A6AC5D5AB2C3109CD125DCAE4939C378A59DBA82F8 +PT=9A7380BAA169495B0FC29BB002D70E48 +CT=88F3FE65298F7498A788E4196F13FC80 + +I=372 +KEY=39079A8713E148703212A6F7FFD1B04D4BE362B40C53DAD19E4B9CBCF2A97E78 +PT=88F3FE65298F7498A788E4196F13FC80 +CT=A5E6361FBA6418CD9B2F50992B50A557 + +I=373 +KEY=A99A33F38B36E3EE4DEE59F8A4282A84EE0554ABB637C21C0564CC25D9F9DB2F +PT=A5E6361FBA6418CD9B2F50992B50A557 +CT=B1430F431ACC1C498FABF2D33B63CC67 + +I=374 +KEY=BC09FAC540F44949F3B8EDFE2444CA725F465BE8ACFBDE558ACF3EF6E29A1748 +PT=B1430F431ACC1C498FABF2D33B63CC67 +CT=A90D76642D8D7899DD4A85EB92C89382 + +I=375 +KEY=D26C1D07B51073C609030DC782FFAE93F64B2D8C8176A6CC5785BB1D705284CA +PT=A90D76642D8D7899DD4A85EB92C89382 +CT=57522F39211100EF248D4A34E35CE4CE + +I=376 +KEY=2D7ADCD18F615F814B8D8B07CE48B4A1A11902B5A067A6237308F129930E6004 +PT=57522F39211100EF248D4A34E35CE4CE +CT=87AED1E0C9F067C5F3F6D3D3BBCDE872 + +I=377 +KEY=CA206C3442FAEFF3CB1292C675F52C2426B7D3556997C1E680FE22FA28C38876 +PT=87AED1E0C9F067C5F3F6D3D3BBCDE872 +CT=05798F53DFAE4A78D7BEEC24BE775B55 + +I=378 +KEY=6ECC5BC346B18446D77FFBC44CCB0B1823CE5C06B6398B9E5740CEDE96B4D323 +PT=05798F53DFAE4A78D7BEEC24BE775B55 +CT=7677CE104395FFA15B51F81DAFBCAB1A + +I=379 +KEY=2E52C8E239CF1E959AB831307034FEF755B99216F5AC743F0C1136C339087839 +PT=7677CE104395FFA15B51F81DAFBCAB1A +CT=760DE53561246F944B3E6279B39373F1 + +I=380 +KEY=79B65B7D435E2134A1AB9A1CC1F08A8423B4772394881BAB472F54BA8A9B0BC8 +PT=760DE53561246F944B3E6279B39373F1 +CT=5B61CC978A9C808767C272432765EC0B + +I=381 +KEY=9EF57B89E7B8127348A9EF05E93DCC8D78D5BBB41E149B2C20ED26F9ADFEE7C3 +PT=5B61CC978A9C808767C272432765EC0B +CT=902CDF3BD5E869E9CCFF8F2A454E1D42 + +I=382 +KEY=15BB7B6BC685E4865BFA134C59CFC9C5E8F9648FCBFCF2C5EC12A9D3E8B0FA81 +PT=902CDF3BD5E869E9CCFF8F2A454E1D42 +CT=38264937B9372C316478BDF7AE578900 + +I=383 +KEY=735D93C1DDD54986ACC6C2B0DFCC5E8AD0DF2DB872CBDEF4886A142446E77381 +PT=38264937B9372C316478BDF7AE578900 +CT=3BFE31D3E909E6EC3112F88DB8FFCA45 + +I=384 +KEY=675B0E7FC5BCC3AF319B1D55C1F62CCAEB211C6B9BC23818B978ECA9FE18B9C4 +PT=3BFE31D3E909E6EC3112F88DB8FFCA45 +CT=2BFD5F6532BC1D2A8DA34481F9228B84 + +I=385 +KEY=0AB242F9783E75D04E98733E63458F53C0DC430EA97E253234DBA828073A3240 +PT=2BFD5F6532BC1D2A8DA34481F9228B84 +CT=161481003108BAEFCC02BFD335C6A89F + +I=386 +KEY=58457CB82A24222839CF20D837F168A8D6C8C20E98769FDDF8D917FB32FC9ADF +PT=161481003108BAEFCC02BFD335C6A89F +CT=8A50E98A1165C1B6137231E519EC137B + +I=387 +KEY=C2C52CEA5654AAC9BD60FA04068094EF5C982B8489135E6BEBAB261E2B1089A4 +PT=8A50E98A1165C1B6137231E519EC137B +CT=24ACAA0F045F5A6765D3B468550585B5 + +I=388 +KEY=816757A434D81AA348E0B2F4FC44F4387834818B8D4C040C8E7892767E150C11 +PT=24ACAA0F045F5A6765D3B468550585B5 +CT=9993F9CBDAD9CA98C74CCBDB3E079F50 + +I=389 +KEY=647A9F1E43B08FD15EFC17342EB8970AE1A778405795CE94493459AD40129341 +PT=9993F9CBDAD9CA98C74CCBDB3E079F50 +CT=F676785AEF58297C28035E8E065829FF + +I=390 +KEY=4BB8B5020862EA9228B663DEDB39336717D1001AB8CDE7E861370723464ABABE +PT=F676785AEF58297C28035E8E065829FF +CT=ED16C74BD4252F7B72AA37D11E198508 + +I=391 +KEY=5392AAED87CE40891A69F4690A8743FBFAC7C7516CE8C893139D30F258533FB6 +PT=ED16C74BD4252F7B72AA37D11E198508 +CT=3BE7B6A9E197598146E98B7A501A2226 + +I=392 +KEY=9D8BABE9C12E6BA3A18EB23A92205456C12071F88D7F91125574BB8808491D90 +PT=3BE7B6A9E197598146E98B7A501A2226 +CT=CC1163A3D9AF3307ED740591AB66BD81 + +I=393 +KEY=231B451E506AC98FF993A3C7AD9C37F70D31125B54D0A215B800BE19A32FA011 +PT=CC1163A3D9AF3307ED740591AB66BD81 +CT=43FB8B2B44C740956111DA816616771D + +I=394 +KEY=1699C517EE1713D02C6EA0957E4A00CE4ECA99701017E280D9116498C539D70C +PT=43FB8B2B44C740956111DA816616771D +CT=A511AEA01DB8E7E16E7C53931625BEC3 + +I=395 +KEY=2624CE7970CC5DAFAC73C881FDD5F6EBEBDB37D00DAF0561B76D370BD31C69CF +PT=A511AEA01DB8E7E16E7C53931625BEC3 +CT=82EF6D2A1FF1DBCDF39DC04BE523229F + +I=396 +KEY=60C9931E19ED0D095F8DF75AEA56689769345AFA125EDEAC44F0F740363F4B50 +PT=82EF6D2A1FF1DBCDF39DC04BE523229F +CT=A595C8AAAAAD80DD4F40693FF2D89A19 + +I=397 +KEY=D461E3605B0AD0E87F5A078ECFE25934CCA19250B8F35E710BB09E7FC4E7D149 +PT=A595C8AAAAAD80DD4F40693FF2D89A19 +CT=57B18DFEAD129795C3BB8D6C06764729 + +I=398 +KEY=0BE3FC6C21764F1C15782D52D92919A09B101FAE15E1C9E4C80B1313C2919660 +PT=57B18DFEAD129795C3BB8D6C06764729 +CT=6F8606BBA6CC03A5D0A64FE21E277B60 + +I=399 +KEY=982D617A0F737342E99123A5A573D266F4961915B32DCA4118AD5CF1DCB6ED00 +PT=6F8606BBA6CC03A5D0A64FE21E277B60 +CT=1F6763DF807A7E70960D4CD3118E601A + +=========== \ No newline at end of file diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_iv.readme b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_iv.readme new file mode 100644 index 00000000..c3721576 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_iv.readme @@ -0,0 +1,19 @@ +Description of the Intermediate Value Known Answer Test +-------------------------------------------------------- + +The test encrypts one plaintext with a variable number of rounds. +In ECB encryption mode, the output PTi is the output after the +initial key addition and i rounds (a round ends with a key +addition). + +As explained in the documentation, in ECB decryption mode +there are several definitions of a `round' possible. In order +to make visual inspection more intuitive, we output the +intermediate values that correspond with the output of the +encryption mode. +These values might actually not occur in a practical decryption, +especially in an optimised implementation, where various operations +of different rounds are interchanged. + +This explains also why the Java and the C code output different +files for this test. diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_iv.txt b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_iv.txt new file mode 100644 index 00000000..3f6608e4 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_iv.txt @@ -0,0 +1,123 @@ + +========================= + +FILENAME: "ecb_iv.txt" + +Electronic Codebook (ECB) Mode +Intermediate Value Known Answer Tests + +Algorithm Name: Rijndael +Principal Submitter: Joan Daemen + +========== + +KEYSIZE=128 +KEY=000102030405060708090A0B0C0D0E0F + +Intermediate Ciphertext Values (Encryption) + +PT=000102030405060708090A0B0C0D0E0F +CT1=B5C9179EB1CC1199B9C51B92B5C8159D +CT2=2B65F6374C427C5B2FE3A9256896755B +CT3=D1015FCBB4EF65679688462076B9D6AD +CT4=8E17064A2A35A183729FE59FF3A591F1 +CT5=D7557DD55999DB3259E2183D558DCDD2 +CT6=73A96A5D7799A5F3111D2B63684B1F7F +CT7=1B6B853069EEFC749AFEFD7B57A04CD1 +CT8=107EEADFB6F77933B5457A6F08F046B2 +CT9=8EC166481A677AA96A14FF6ECE88C010 +CT=0A940BB5416EF045F1C39458C653EA5A + +Intermediate Ciphertext Values (Decryption) + +CT=0A940BB5416EF045F1C39458C653EA5A +PT1=8EC166481A677AA96A14FF6ECE88C010 +PT2=107EEADFB6F77933B5457A6F08F046B2 +PT3=1B6B853069EEFC749AFEFD7B57A04CD1 +PT4=73A96A5D7799A5F3111D2B63684B1F7F +PT5=D7557DD55999DB3259E2183D558DCDD2 +PT6=8E17064A2A35A183729FE59FF3A591F1 +PT7=D1015FCBB4EF65679688462076B9D6AD +PT8=2B65F6374C427C5B2FE3A9256896755B +PT9=B5C9179EB1CC1199B9C51B92B5C8159D +PT=000102030405060708090A0B0C0D0E0F + +========== + +KEYSIZE=192 +KEY=000102030405060708090A0B0C0D0E0F1011121314151617 + +Intermediate Ciphertext Values (Encryption) + +PT=000102030405060708090A0B0C0D0E0F +CT1=73727170777675743B25919A3F20979D +CT2=C673B27A311EC2EB64AD47FF53B233D7 +CT3=0B5CC6BA34C807E6496D79B46826A1E8 +CT4=005B53A5B660E280307883487E4D1A4D +CT5=88A105F0DDD45F3674DBC3DE1A211B03 +CT6=EB5CD8B5FD8A3F33F03A70FB5C620C06 +CT7=909913B09BD2CC5A70B6C647931F0A1F +CT8=6EB6CA10E395AFD646B02C5E9E745A9F +CT9=2CFD2FC41AF82B8DFB80E9BD1C989ECE +CT10=31C5D5E27EAF073E5C21ADAAEAA969D4 +CT11=1DB94956A7268B0DE963D27E55868580 +CT=0060BFFE46834BB8DA5CF9A61FF220AE + +Intermediate Ciphertext Values (Decryption) + +CT=0060BFFE46834BB8DA5CF9A61FF220AE +PT1=1DB94956A7268B0DE963D27E55868580 +PT2=31C5D5E27EAF073E5C21ADAAEAA969D4 +PT3=2CFD2FC41AF82B8DFB80E9BD1C989ECE +PT4=6EB6CA10E395AFD646B02C5E9E745A9F +PT5=909913B09BD2CC5A70B6C647931F0A1F +PT6=EB5CD8B5FD8A3F33F03A70FB5C620C06 +PT7=88A105F0DDD45F3674DBC3DE1A211B03 +PT8=005B53A5B660E280307883487E4D1A4D +PT9=0B5CC6BA34C807E6496D79B46826A1E8 +PT10=C673B27A311EC2EB64AD47FF53B233D7 +PT11=73727170777675743B25919A3F20979D +PT=000102030405060708090A0B0C0D0E0F + +========== + +KEYSIZE=256 +KEY=000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F + +Intermediate Ciphertext Values (Encryption) + +PT=000102030405060708090A0B0C0D0E0F +CT1=73727170777675747B7A79787F7E7D7C +CT2=4E5D32BB8B67FD1BD4CFEC9FFB20AC4F +CT3=96A212E486341549C4AAF7C843F0277A +CT4=0F45F284CDD0CB16E3EA81ECC891A4E1 +CT5=E59BFC458A89063E0137BBE6DB63A058 +CT6=1D958D960EA3143383C17D5CD87BA327 +CT7=43843EF40D9219481935B77A586DB5DE +CT8=5AA5ABADBC40230CBA6124E9FAEEEFB5 +CT9=DAD61937BDFD582927F14C990C5FC761 +CT10=E8A48C5DEE5C0792AB6DFFF5B038529D +CT11=4B71E5A8BFB4E9A5312A18119E68E829 +CT12=DCBA75CEE6589DDC0D289A172E8415B5 +CT13=8A0E856B2074C1093104131D0628BFE8 +CT=5A6E045708FB7196F02E553D02C3A692 + +Intermediate Ciphertext Values (Decryption) + +CT=5A6E045708FB7196F02E553D02C3A692 +PT1=8A0E856B2074C1093104131D0628BFE8 +PT2=DCBA75CEE6589DDC0D289A172E8415B5 +PT3=4B71E5A8BFB4E9A5312A18119E68E829 +PT4=E8A48C5DEE5C0792AB6DFFF5B038529D +PT5=DAD61937BDFD582927F14C990C5FC761 +PT6=5AA5ABADBC40230CBA6124E9FAEEEFB5 +PT7=43843EF40D9219481935B77A586DB5DE +PT8=1D958D960EA3143383C17D5CD87BA327 +PT9=E59BFC458A89063E0137BBE6DB63A058 +PT10=0F45F284CDD0CB16E3EA81ECC891A4E1 +PT11=96A212E486341549C4AAF7C843F0277A +PT12=4E5D32BB8B67FD1BD4CFEC9FFB20AC4F +PT13=73727170777675747B7A79787F7E7D7C +PT=000102030405060708090A0B0C0D0E0F + +========== \ No newline at end of file diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_tbl.txt b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_tbl.txt new file mode 100644 index 00000000..f1eef530 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_tbl.txt @@ -0,0 +1,1955 @@ +/* Description of what tables are tested: + The provided implementations each use a different set of tables + - Java implementation: uses no tables + - reference C implementation: uses Logtable, Alogtable, S, Si, rcon + - fast C implementation: uses Logtable, Alogtable, rcon + and additionally, T1, T2, T3, T4, T5, T6, T7, T8 + and (for the inverse key schedule only) U1, U2, U3, U4. + All these tables are tested. + +========================= + +FILENAME: "ecb_tbl.txt" + +Electronic Codebook (ECB) Mode +Tables Known Answer Tests + +Algorithm Name: Rijndael +Principal Submitter: Joan Daemen + +========== + +KEYSIZE=128 + + +I=1 +KEY=00010203050607080A0B0C0D0F101112 +PT=506812A45F08C889B97F5980038B8359 +CT=D8F532538289EF7D06B506A4FD5BE9C9 + +I=2 +KEY=14151617191A1B1C1E1F202123242526 +PT=5C6D71CA30DE8B8B00549984D2EC7D4B +CT=59AB30F4D4EE6E4FF9907EF65B1FB68C + +I=3 +KEY=28292A2B2D2E2F30323334353738393A +PT=53F3F4C64F8616E4E7C56199F48F21F6 +CT=BF1ED2FCB2AF3FD41443B56D85025CB1 + +I=4 +KEY=3C3D3E3F41424344464748494B4C4D4E +PT=A1EB65A3487165FB0F1C27FF9959F703 +CT=7316632D5C32233EDCB0780560EAE8B2 + +I=5 +KEY=50515253555657585A5B5C5D5F606162 +PT=3553ECF0B1739558B08E350A98A39BFA +CT=408C073E3E2538072B72625E68B8364B + +I=6 +KEY=64656667696A6B6C6E6F707173747576 +PT=67429969490B9711AE2B01DC497AFDE8 +CT=E1F94DFA776597BEACA262F2F6366FEA + +I=7 +KEY=78797A7B7D7E7F80828384858788898A +PT=93385C1F2AEC8BED192F5A8E161DD508 +CT=F29E986C6A1C27D7B29FFD7EE92B75F1 + +I=8 +KEY=8C8D8E8F91929394969798999B9C9D9E +PT=B5BF946BE19BEB8DB3983B5F4C6E8DDB +CT=131C886A57F8C2E713ABA6955E2B55B5 + +I=9 +KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2 +PT=41321EE10E21BD907227C4450FF42324 +CT=D2AB7662DF9B8C740210E5EEB61C199D + +I=10 +KEY=B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6 +PT=00A82F59C91C8486D12C0A80124F6089 +CT=14C10554B2859C484CAB5869BBE7C470 + +I=11 +KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DA +PT=7CE0FD076754691B4BBD9FAF8A1372FE +CT=DB4D498F0A49CF55445D502C1F9AB3B5 + +I=12 +KEY=DCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE +PT=23605A8243D07764541BC5AD355B3129 +CT=6D96FEF7D66590A77A77BB2056667F7F + +I=13 +KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE010002 +PT=12A8CFA23EA764FD876232B4E842BC44 +CT=316FB68EDBA736C53E78477BF913725C + +I=14 +KEY=04050607090A0B0C0E0F101113141516 +PT=BCAF32415E8308B3723E5FDD853CCC80 +CT=6936F2B93AF8397FD3A771FC011C8C37 + +I=15 +KEY=2C2D2E2F31323334363738393B3C3D3E +PT=89AFAE685D801AD747ACE91FC49ADDE0 +CT=F3F92F7A9C59179C1FCC2C2BA0B082CD + +I=16 +KEY=40414243454647484A4B4C4D4F505152 +PT=F521D07B484357C4A69E76124A634216 +CT=6A95EA659EE3889158E7A9152FF04EBC + +I=17 +KEY=54555657595A5B5C5E5F606163646566 +PT=3E23B3BC065BCC152407E23896D77783 +CT=1959338344E945670678A5D432C90B93 + +I=18 +KEY=68696A6B6D6E6F70727374757778797A +PT=79F0FBA002BE1744670E7E99290D8F52 +CT=E49BDDD2369B83EE66E6C75A1161B394 + +I=19 +KEY=7C7D7E7F81828384868788898B8C8D8E +PT=DA23FE9D5BD63E1D72E3DAFBE21A6C2A +CT=D3388F19057FF704B70784164A74867D + +I=20 +KEY=A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6 +PT=E3F5698BA90B6A022EFD7DB2C7E6C823 +CT=23AA03E2D5E4CD24F3217E596480D1E1 + +I=21 +KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2 +PT=BDC2691D4F1B73D2700679C3BCBF9C6E +CT=C84113D68B666AB2A50A8BDB222E91B9 + +I=22 +KEY=08090A0B0D0E0F10121314151718191A +PT=BA74E02093217EE1BA1B42BD5624349A +CT=AC02403981CD4340B507963DB65CB7B6 + +I=23 +KEY=6C6D6E6F71727374767778797B7C7D7E +PT=B5C593B5851C57FBF8B3F57715E8F680 +CT=8D1299236223359474011F6BF5088414 + +I=24 +KEY=80818283858687888A8B8C8D8F909192 +PT=3DA9BD9CEC072381788F9387C3BBF4EE +CT=5A1D6AB8605505F7977E55B9A54D9B90 + +I=25 +KEY=94959697999A9B9C9E9FA0A1A3A4A5A6 +PT=4197F3051121702AB65D316B3C637374 +CT=72E9C2D519CF555E4208805AABE3B258 + +I=26 +KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BA +PT=9F46C62EC4F6EE3F6E8C62554BC48AB7 +CT=A8F3E81C4A23A39EF4D745DFFE026E80 + +I=27 +KEY=BCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE +PT=0220673FE9E699A4EBC8E0DBEB6979C8 +CT=546F646449D31458F9EB4EF5483AEE6C + +I=28 +KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2 +PT=B2B99171337DED9BC8C2C23FF6F18867 +CT=4DBE4BC84AC797C0EE4EFB7F1A07401C + +I=29 +KEY=E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6 +PT=A7FACF4E301E984E5EFEEFD645B23505 +CT=25E10BFB411BBD4D625AC8795C8CA3B3 + +I=30 +KEY=F8F9FAFBFDFEFE00020304050708090A +PT=F7C762E4A9819160FD7ACFB6C4EEDCDD +CT=315637405054EC803614E43DEF177579 + +I=31 +KEY=0C0D0E0F11121314161718191B1C1D1E +PT=9B64FC21EA08709F4915436FAA70F1BE +CT=60C5BC8A1410247295C6386C59E572A8 + +I=32 +KEY=20212223252627282A2B2C2D2F303132 +PT=52AF2C3DE07EE6777F55A4ABFC100B3F +CT=01366FC8CA52DFE055D6A00A76471BA6 + +I=33 +KEY=34353637393A3B3C3E3F404143444546 +PT=2FCA001224386C57AA3F968CBE2C816F +CT=ECC46595516EC612449C3F581E7D42FF + +I=34 +KEY=48494A4B4D4E4F50525354555758595A +PT=4149C73658A4A9C564342755EE2C132F +CT=6B7FFE4C602A154B06EE9C7DAB5331C9 + +I=35 +KEY=5C5D5E5F61626364666768696B6C6D6E +PT=AF60005A00A1772F7C07A48A923C23D2 +CT=7DA234C14039A240DD02DD0FBF84EB67 + +I=36 +KEY=70717273757677787A7B7C7D7F808182 +PT=6FCCBC28363759914B6F0280AFAF20C6 +CT=C7DC217D9E3604FFE7E91F080ECD5A3A + +I=37 +KEY=84858687898A8B8C8E8F909193949596 +PT=7D82A43DDF4FEFA2FC5947499884D386 +CT=37785901863F5C81260EA41E7580CDA5 + +I=38 +KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AA +PT=5D5A990EAAB9093AFE4CE254DFA49EF9 +CT=A07B9338E92ED105E6AD720FCCCE9FE4 + +I=39 +KEY=ACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE +PT=4CD1E2FD3F4434B553AAE453F0ED1A02 +CT=AE0FB9722418CC21A7DA816BBC61322C + +I=40 +KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2 +PT=5A2C9A9641D4299125FA1B9363104B5E +CT=C826A193080FF91FFB21F71D3373C877 + +I=41 +KEY=D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6 +PT=B517FE34C0FA217D341740BFD4FE8DD4 +CT=1181B11B0E494E8D8B0AA6B1D5AC2C48 + +I=42 +KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FA +PT=014BAF2278A69D331D5180103643E99A +CT=6743C3D1519AB4F2CD9A78AB09A511BD + +I=43 +KEY=FCFDFEFF01020304060708090B0C0D0E +PT=B529BD8164F20D0AA443D4932116841C +CT=DC55C076D52BACDF2EEFD952946A439D + +I=44 +KEY=10111213151617181A1B1C1D1F202122 +PT=2E596DCBB2F33D4216A1176D5BD1E456 +CT=711B17B590FFC72B5C8E342B601E8003 + +I=45 +KEY=24252627292A2B2C2E2F303133343536 +PT=7274A1EA2B7EE2424E9A0E4673689143 +CT=19983BB0950783A537E1339F4AA21C75 + +I=46 +KEY=38393A3B3D3E3F40424344454748494A +PT=AE20020BD4F13E9D90140BEE3B5D26AF +CT=3BA7762E15554169C0F4FA39164C410C + +I=47 +KEY=4C4D4E4F51525354565758595B5C5D5E +PT=BAAC065DA7AC26E855E79C8849D75A02 +CT=A0564C41245AFCA7AF8AA2E0E588EA89 + +I=48 +KEY=60616263656667686A6B6C6D6F707172 +PT=7C917D8D1D45FAB9E2540E28832540CC +CT=5E36A42A2E099F54AE85ECD92E2381ED + +I=49 +KEY=74757677797A7B7C7E7F808183848586 +PT=BDE6F89E16DAADB0E847A2A614566A91 +CT=770036F878CD0F6CA2268172F106F2FE + +I=50 +KEY=88898A8B8D8E8F90929394959798999A +PT=C9DE163725F1F5BE44EBB1DB51D07FBC +CT=7E4E03908B716116443CCF7C94E7C259 + +I=51 +KEY=9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE +PT=3AF57A58F0C07DFFA669572B521E2B92 +CT=482735A48C30613A242DD494C7F9185D + +I=52 +KEY=B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2 +PT=3D5EBAC306DDE4604F1B4FBBBFCDAE55 +CT=B4C0F6C9D4D7079ADDF9369FC081061D + +I=53 +KEY=C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6 +PT=C2DFA91BCEB76A1183C995020AC0B556 +CT=D5810FE0509AC53EDCD74F89962E6270 + +I=54 +KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EA +PT=C70F54305885E9A0746D01EC56C8596B +CT=03F17A16B3F91848269ECDD38EBB2165 + +I=55 +KEY=ECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE +PT=C4F81B610E98012CE000182050C0C2B2 +CT=DA1248C3180348BAD4A93B4D9856C9DF + +I=56 +KEY=00010203050607080A0B0C0D0F101112 +PT=EAAB86B1D02A95D7404EFF67489F97D4 +CT=3D10D7B63F3452C06CDF6CCE18BE0C2C + +I=57 +KEY=14151617191A1B1C1E1F202123242526 +PT=7C55BDB40B88870B52BEC3738DE82886 +CT=4AB823E7477DFDDC0E6789018FCB6258 + +I=58 +KEY=28292A2B2D2E2F30323334353738393A +PT=BA6EAA88371FF0A3BD875E3F2A975CE0 +CT=E6478BA56A77E70CFDAA5C843ABDE30E + +I=59 +KEY=3C3D3E3F41424344464748494B4C4D4E +PT=08059130C4C24BD30CF0575E4E0373DC +CT=1673064895FBEAF7F09C5429FF75772D + +I=60 +KEY=50515253555657585A5B5C5D5F606162 +PT=9A8EAB004EF53093DFCF96F57E7EDA82 +CT=4488033AE9F2EFD0CA9383BFCA1A94E9 + +I=61 +KEY=64656667696A6B6C6E6F707173747576 +PT=0745B589E2400C25F117B1D796C28129 +CT=978F3B8C8F9D6F46626CAC3C0BCB9217 + +I=62 +KEY=78797A7B7D7E7F80828384858788898A +PT=2F1777781216CEC3F044F134B1B92BBE +CT=E08C8A7E582E15E5527F1D9E2EECB236 + +I=63 +KEY=8C8D8E8F91929394969798999B9C9D9E +PT=353A779FFC541B3A3805D90CE17580FC +CT=CEC155B76AC5FFDA4CF4F9CA91E49A7A + +I=64 +KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2 +PT=1A1EAE4415CEFCF08C4AC1C8F68BEA8F +CT=D5AC7165763225DD2A38CDC6862C29AD + +I=65 +KEY=B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6 +PT=E6E7E4E5B0B3B2B5D4D5AAAB16111013 +CT=03680FE19F7CE7275452020BE70E8204 + +I=66 +KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DA +PT=F8F9FAFBFBF8F9E677767170EFE0E1E2 +CT=461DF740C9781C388E94BB861CEB54F6 + +I=67 +KEY=DCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE +PT=63626160A1A2A3A445444B4A75727370 +CT=451BD60367F96483042742219786A074 + +I=68 +KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE010002 +PT=717073720605040B2D2C2B2A05FAFBF9 +CT=E4DFA42671A02E57EF173B85C0EA9F2B + +I=69 +KEY=04050607090A0B0C0E0F101113141516 +PT=78797A7BEAE9E8EF3736292891969794 +CT=ED11B89E76274282227D854700A78B9E + +I=70 +KEY=18191A1B1D1E1F20222324252728292A +PT=838281803231300FDDDCDBDAA0AFAEAD +CT=433946EAA51EA47AF33895F2B90B3B75 + +I=71 +KEY=2C2D2E2F31323334363738393B3C3D3E +PT=18191A1BBFBCBDBA75747B7A7F78797A +CT=6BC6D616A5D7D0284A5910AB35022528 + +I=72 +KEY=40414243454647484A4B4C4D4F505152 +PT=848586879B989996A3A2A5A4849B9A99 +CT=D2A920ECFE919D354B5F49EAE9719C98 + +I=73 +KEY=54555657595A5B5C5E5F606163646566 +PT=0001020322212027CACBF4F551565754 +CT=3A061B17F6A92885EFBD0676985B373D + +I=74 +KEY=68696A6B6D6E6F70727374757778797A +PT=CECFCCCDAFACADB2515057564A454447 +CT=FADEEC16E33EA2F4688499D157E20D8F + +I=75 +KEY=7C7D7E7F81828384868788898B8C8D8E +PT=92939091CDCECFC813121D1C80878685 +CT=5CDEFEDE59601AA3C3CDA36FA6B1FA13 + +I=76 +KEY=90919293959697989A9B9C9D9FA0A1A2 +PT=D2D3D0D16F6C6D6259585F5ED1EEEFEC +CT=9574B00039844D92EBBA7EE8719265F8 + +I=77 +KEY=A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6 +PT=ACADAEAF878485820F0E1110D5D2D3D0 +CT=9A9CF33758671787E5006928188643FA + +I=78 +KEY=B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CA +PT=9091929364676619E6E7E0E1757A7B78 +CT=2CDDD634C846BA66BB46CBFEA4A674F9 + +I=79 +KEY=CCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE +PT=BABBB8B98A89888F74757A7B92959497 +CT=D28BAE029393C3E7E26E9FAFBBB4B98F + +I=80 +KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2 +PT=8D8C8F8E6E6D6C633B3A3D3CCAD5D4D7 +CT=EC27529B1BEE0A9AB6A0D73EBC82E9B7 + +I=81 +KEY=F4F5F6F7F9FAFBFCFEFE010103040506 +PT=86878485010203040808F7F767606162 +CT=3CB25C09472AFF6EE7E2B47CCD7CCB17 + +I=82 +KEY=08090A0B0D0E0F10121314151718191A +PT=8E8F8C8D656667788A8B8C8D010E0F0C +CT=DEE33103A7283370D725E44CA38F8FE5 + +I=83 +KEY=1C1D1E1F21222324262728292B2C2D2E +PT=C8C9CACB858687807A7B7475E7E0E1E2 +CT=27F9BCD1AAC64BFFC11E7815702C1A69 + +I=84 +KEY=30313233353637383A3B3C3D3F404142 +PT=6D6C6F6E5053525D8C8D8A8BADD2D3D0 +CT=5DF534FFAD4ED0749A9988E9849D0021 + +I=85 +KEY=44454647494A4B4C4E4F505153545556 +PT=28292A2B393A3B3C0607181903040506 +CT=A48BEE75DB04FB60CA2B80F752A8421B + +I=86 +KEY=58595A5B5D5E5F60626364656768696A +PT=A5A4A7A6B0B3B28DDBDADDDCBDB2B3B0 +CT=024C8CF70BC86EE5CE03678CB7AF45F9 + +I=87 +KEY=6C6D6E6F71727374767778797B7C7D7E +PT=323330316467666130313E3F2C2B2A29 +CT=3C19AC0F8A3A3862CE577831301E166B + +I=88 +KEY=80818283858687888A8B8C8D8F909192 +PT=27262524080B0A05171611100B141516 +CT=C5E355B796A57421D59CA6BE82E73BCA + +I=89 +KEY=94959697999A9B9C9E9FA0A1A3A4A5A6 +PT=040506074142434435340B0AA3A4A5A6 +CT=D94033276417ABFB05A69D15B6E386E2 + +I=90 +KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BA +PT=242526271112130C61606766BDB2B3B0 +CT=24B36559EA3A9B9B958FE6DA3E5B8D85 + +I=91 +KEY=BCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE +PT=4B4A4948252627209E9F9091CEC9C8CB +CT=20FD4FEAA0E8BF0CCE7861D74EF4CB72 + +I=92 +KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2 +PT=68696A6B6665646B9F9E9998D9E6E7E4 +CT=350E20D5174277B9EC314C501570A11D + +I=93 +KEY=E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6 +PT=34353637C5C6C7C0F0F1EEEF7C7B7A79 +CT=87A29D61B7C604D238FE73045A7EFD57 + +I=94 +KEY=F8F9FAFBFDFEFE00020304050708090A +PT=32333031C2C1C13F0D0C0B0A050A0B08 +CT=2C3164C1CC7D0064816BDC0FAA362C52 + +I=95 +KEY=0C0D0E0F11121314161718191B1C1D1E +PT=CDCCCFCEBEBDBCBBABAAA5A4181F1E1D +CT=195FE5E8A05A2ED594F6E4400EEE10B3 + +I=96 +KEY=20212223252627282A2B2C2D2F303132 +PT=212023223635343BA0A1A6A7445B5A59 +CT=E4663DF19B9A21A5A284C2BD7F905025 + +I=97 +KEY=34353637393A3B3C3E3F404143444546 +PT=0E0F0C0DA8ABAAAD2F2E515002050407 +CT=21B88714CFB4E2A933BD281A2C4743FD + +I=98 +KEY=48494A4B4D4E4F50525354555758595A +PT=070605042A2928378E8F8889BDB2B3B0 +CT=CBFC3980D704FD0FC54378AB84E17870 + +I=99 +KEY=5C5D5E5F61626364666768696B6C6D6E +PT=CBCAC9C893909196A9A8A7A6A5A2A3A0 +CT=BC5144BAA48BDEB8B63E22E03DA418EF + +I=100 +KEY=70717273757677787A7B7C7D7F808182 +PT=80818283C1C2C3CC9C9D9A9B0CF3F2F1 +CT=5A1DBAEF1EE2984B8395DA3BDFFA3CCC + +I=101 +KEY=84858687898A8B8C8E8F909193949596 +PT=1213101125262720FAFBE4E5B1B6B7B4 +CT=F0B11CD0729DFCC80CEC903D97159574 + +I=102 +KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AA +PT=7F7E7D7C3033320D97969190222D2C2F +CT=9F95314ACFDDC6D1914B7F19A9CC8209 + +I=103 +KEY=ACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE +PT=4E4F4C4D484B4A4D81808F8E53545556 +CT=595736F6F0F70914A94E9E007F022519 + +I=104 +KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2 +PT=DCDDDEDFB0B3B2BD15141312A1BEBFBC +CT=1F19F57892CAE586FCDFB4C694DEB183 + +I=105 +KEY=D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6 +PT=93929190282B2A2DC4C5FAFB92959497 +CT=540700EE1F6F3DAB0B3EDDF6CAEE1EF5 + +I=106 +KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FA +PT=F5F4F7F6C4C7C6D9373631307E717073 +CT=14A342A91019A331687A2254E6626CA2 + +I=107 +KEY=FCFDFEFF01020304060708090B0C0D0E +PT=93929190B6B5B4B364656A6B05020300 +CT=7B25F3C3B2EEA18D743EF283140F29FF + +I=108 +KEY=10111213151617181A1B1C1D1F202122 +PT=BABBB8B90D0E0F00A4A5A2A3043B3A39 +CT=46C2587D66E5E6FA7F7CA6411AD28047 + +I=109 +KEY=24252627292A2B2C2E2F303133343536 +PT=D8D9DADB7F7C7D7A10110E0F787F7E7D +CT=09470E72229D954ED5EE73886DFEEBA9 + +I=110 +KEY=38393A3B3D3E3F40424344454748494A +PT=FEFFFCFDEFECED923B3A3D3C6768696A +CT=D77C03DE92D4D0D79EF8D4824EF365EB + +I=111 +KEY=4C4D4E4F51525354565758595B5C5D5E +PT=D6D7D4D58A89888F96979899A5A2A3A0 +CT=1D190219F290E0F1715D152D41A23593 + +I=112 +KEY=60616263656667686A6B6C6D6F707172 +PT=18191A1BA8ABAAA5303136379B848586 +CT=A2CD332CE3A0818769616292E87F757B + +I=113 +KEY=74757677797A7B7C7E7F808183848586 +PT=6B6A6968A4A7A6A1D6D72829B0B7B6B5 +CT=D54AFA6CE60FBF9341A3690E21385102 + +I=114 +KEY=88898A8B8D8E8F90929394959798999A +PT=000102038A89889755545352A6A9A8AB +CT=06E5C364DED628A3F5E05E613E356F46 + +I=115 +KEY=9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE +PT=2D2C2F2EB3B0B1B6B6B7B8B9F2F5F4F7 +CT=EAE63C0E62556DAC85D221099896355A + +I=116 +KEY=B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2 +PT=979695943536373856575051E09F9E9D +CT=1FED060E2C6FC93EE764403A889985A2 + +I=117 +KEY=C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6 +PT=A4A5A6A7989B9A9DB1B0AFAE7A7D7C7F +CT=C25235C1A30FDEC1C7CB5C5737B2A588 + +I=118 +KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EA +PT=C1C0C3C2686B6A55A8A9AEAFEAE5E4E7 +CT=796DBEF95147D4D30873AD8B7B92EFC0 + +I=119 +KEY=ECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE +PT=C1C0C3C2141716118C8D828364636261 +CT=CBCF0FB34D98D0BD5C22CE37211A46BF + +I=120 +KEY=00010203050607080A0B0C0D0F101112 +PT=93929190CCCFCEC196979091E0FFFEFD +CT=94B44DA6466126CAFA7C7FD09063FC24 + +I=121 +KEY=14151617191A1B1C1E1F202123242526 +PT=B4B5B6B7F9FAFBFC25241B1A6E69686B +CT=D78C5B5EBF9B4DBDA6AE506C5074C8FE + +I=122 +KEY=28292A2B2D2E2F30323334353738393A +PT=868784850704051AC7C6C1C08788898A +CT=6C27444C27204B043812CF8CF95F9769 + +I=123 +KEY=3C3D3E3F41424344464748494B4C4D4E +PT=F4F5F6F7AAA9A8AFFDFCF3F277707172 +CT=BE94524EE5A2AA50BBA8B75F4C0AEBCF + +I=124 +KEY=50515253555657585A5B5C5D5F606162 +PT=D3D2D1D00605040BC3C2C5C43E010003 +CT=A0AEAAE91BA9F31F51AEB3588CF3A39E + +I=125 +KEY=64656667696A6B6C6E6F707173747576 +PT=73727170424140476A6B74750D0A0B08 +CT=275297779C28266EF9FE4C6A13C08488 + +I=126 +KEY=78797A7B7D7E7F80828384858788898A +PT=C2C3C0C10A0908F754555253A1AEAFAC +CT=86523D92BB8672CB01CF4A77FD725882 + +I=127 +KEY=8C8D8E8F91929394969798999B9C9D9E +PT=6D6C6F6EF8FBFAFD82838C8DF8FFFEFD +CT=4B8327640E9F33322A04DD96FCBF9A36 + +I=128 +KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2 +PT=F5F4F7F684878689A6A7A0A1D2CDCCCF +CT=CE52AF650D088CA559425223F4D32694 + +========== + +KEYSIZE=192 + + +I=1 +KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C +PT=2D33EEF2C0430A8A9EBF45E809C40BB6 +CT=DFF4945E0336DF4C1C56BC700EFF837F + +I=2 +KEY=1E1F20212324252628292A2B2D2E2F30323334353738393A +PT=6AA375D1FA155A61FB72353E0A5A8756 +CT=B6FDDEF4752765E347D5D2DC196D1252 + +I=3 +KEY=3C3D3E3F41424344464748494B4C4D4E5051525355565758 +PT=BC3736518B9490DCB8ED60EB26758ED4 +CT=D23684E3D963B3AFCF1A114ACA90CBD6 + +I=4 +KEY=5A5B5C5D5F60616264656667696A6B6C6E6F707173747576 +PT=AA214402B46CFFB9F761EC11263A311E +CT=3A7AC027753E2A18C2CEAB9E17C11FD0 + +I=5 +KEY=78797A7B7D7E7F80828384858788898A8C8D8E8F91929394 +PT=02AEA86E572EEAB66B2C3AF5E9A46FD6 +CT=8F6786BD007528BA26603C1601CDD0D8 + +I=6 +KEY=969798999B9C9D9EA0A1A2A3A5A6A7A8AAABACADAFB0B1B2 +PT=E2AEF6ACC33B965C4FA1F91C75FF6F36 +CT=D17D073B01E71502E28B47AB551168B3 + +I=7 +KEY=B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6C8C9CACBCDCECFD0 +PT=0659DF46427162B9434865DD9499F91D +CT=A469DA517119FAB95876F41D06D40FFA + +I=8 +KEY=D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE +PT=49A44239C748FEB456F59C276A5658DF +CT=6091AA3B695C11F5C0B6AD26D3D862FF + +I=9 +KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C +PT=66208F6E9D04525BDEDB2733B6A6BE37 +CT=70F9E67F9F8DF1294131662DC6E69364 + +I=10 +KEY=0E0F10111314151618191A1B1D1E1F20222324252728292A +PT=3393F8DFC729C97F5480B950BC9666B0 +CT=D154DCAFAD8B207FA5CBC95E9996B559 + +I=11 +KEY=2C2D2E2F31323334363738393B3C3D3E4041424345464748 +PT=606834C8CE063F3234CF1145325DBD71 +CT=4934D541E8B46FA339C805A7AEB9E5DA + +I=12 +KEY=4A4B4C4D4F50515254555657595A5B5C5E5F606163646566 +PT=FEC1C04F529BBD17D8CECFCC4718B17F +CT=62564C738F3EFE186E1A127A0C4D3C61 + +I=13 +KEY=68696A6B6D6E6F70727374757778797A7C7D7E7F81828384 +PT=32DF99B431ED5DC5ACF8CAF6DC6CE475 +CT=07805AA043986EB23693E23BEF8F3438 + +I=14 +KEY=868788898B8C8D8E90919293959697989A9B9C9D9FA0A1A2 +PT=7FDC2B746F3F665296943B83710D1F82 +CT=DF0B4931038BADE848DEE3B4B85AA44B + +I=15 +KEY=A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6B8B9BABBBDBEBFC0 +PT=8FBA1510A3C5B87E2EAA3F7A91455CA2 +CT=592D5FDED76582E4143C65099309477C + +I=16 +KEY=C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE +PT=2C9B468B1C2EED92578D41B0716B223B +CT=C9B8D6545580D3DFBCDD09B954ED4E92 + +I=17 +KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFC +PT=0A2BBF0EFC6BC0034F8A03433FCA1B1A +CT=5DCCD5D6EB7C1B42ACB008201DF707A0 + +I=18 +KEY=FEFE01010304050608090A0B0D0E0F10121314151718191A +PT=25260E1F31F4104D387222E70632504B +CT=A2A91682FFEB6ED1D34340946829E6F9 + +I=19 +KEY=1C1D1E1F21222324262728292B2C2D2E3031323335363738 +PT=C527D25A49F08A5228D338642AE65137 +CT=E45D185B797000348D9267960A68435D + +I=20 +KEY=3A3B3C3D3F40414244454647494A4B4C4E4F505153545556 +PT=3B49FC081432F5890D0E3D87E884A69E +CT=45E060DAE5901CDA8089E10D4F4C246B + +I=21 +KEY=58595A5B5D5E5F60626364656768696A6C6D6E6F71727374 +PT=D173F9ED1E57597E166931DF2754A083 +CT=F6951AFACC0079A369C71FDCFF45DF50 + +I=22 +KEY=767778797B7C7D7E80818283858687888A8B8C8D8F909192 +PT=8C2B7CAFA5AFE7F13562DAEAE1ADEDE0 +CT=9E95E00F351D5B3AC3D0E22E626DDAD6 + +I=23 +KEY=94959697999A9B9C9E9FA0A1A3A4A5A6A8A9AAABADAEAFB0 +PT=AAF4EC8C1A815AEB826CAB741339532C +CT=9CB566FF26D92DAD083B51FDC18C173C + +I=24 +KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBEC +PT=40BE8C5D9108E663F38F1A2395279ECF +CT=C9C82766176A9B228EB9A974A010B4FB + +I=25 +KEY=2A2B2C2D2F30313234353637393A3B3C3E3F404143444546 +PT=0C8AD9BC32D43E04716753AA4CFBE351 +CT=D8E26AA02945881D5137F1C1E1386E88 + +I=26 +KEY=48494A4B4D4E4F50525354555758595A5C5D5E5F61626364 +PT=1407B1D5F87D63357C8DC7EBBAEBBFEE +CT=C0E024CCD68FF5FFA4D139C355A77C55 + +I=27 +KEY=84858687898A8B8C8E8F90919394959698999A9B9D9E9FA0 +PT=E62734D1AE3378C4549E939E6F123416 +CT=0B18B3D16F491619DA338640DF391D43 + +I=28 +KEY=A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE +PT=5A752CFF2A176DB1A1DE77F2D2CDEE41 +CT=DBE09AC8F66027BF20CB6E434F252EFC + +I=29 +KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDC +PT=A9C8C3A4EABEDC80C64730DDD018CD88 +CT=6D04E5E43C5B9CBE05FEB9606B6480FE + +I=30 +KEY=1A1B1C1D1F20212224252627292A2B2C2E2F303133343536 +PT=EE9B3DBBDB86180072130834D305999A +CT=DD1D6553B96BE526D9FEE0FBD7176866 + +I=31 +KEY=38393A3B3D3E3F40424344454748494A4C4D4E4F51525354 +PT=A7FA8C3586B8EBDE7568EAD6F634A879 +CT=0260CA7E3F979FD015B0DD4690E16D2A + +I=32 +KEY=929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE +PT=37E0F4A87F127D45AC936FE7AD88C10A +CT=9893734DE10EDCC8A67C3B110B8B8CC6 + +I=33 +KEY=464748494B4C4D4E50515253555657585A5B5C5D5F606162 +PT=3F77D8B5D92BAC148E4E46F697A535C5 +CT=93B30B750516B2D18808D710C2EE84EF + +I=34 +KEY=828384858788898A8C8D8E8F91929394969798999B9C9D9E +PT=D25EBB686C40F7E2C4DA1014936571CA +CT=16F65FA47BE3CB5E6DFE7C6C37016C0E + +I=35 +KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBC +PT=4F1C769D1E5B0552C7ECA84DEA26A549 +CT=F3847210D5391E2360608E5ACB560581 + +I=36 +KEY=BEBFC0C1C3C4C5C6C8C9CACBCDCECFD0D2D3D4D5D7D8D9DA +PT=8548E2F882D7584D0FAFC54372B6633A +CT=8754462CD223366D0753913E6AF2643D + +I=37 +KEY=DCDDDEDFE1E2E3E4E6E7E8E9EBECEDEEF0F1F2F3F5F6F7F8 +PT=87D7A336CB476F177CD2A51AF2A62CDF +CT=1EA20617468D1B806A1FD58145462017 + +I=38 +KEY=FAFBFCFDFE01000204050607090A0B0C0E0F101113141516 +PT=03B1FEAC668C4E485C1065DFC22B44EE +CT=3B155D927355D737C6BE9DDA60136E2E + +I=39 +KEY=18191A1B1D1E1F20222324252728292A2C2D2E2F31323334 +PT=BDA15E66819FA72D653A6866AA287962 +CT=26144F7B66DAA91B6333DBD3850502B3 + +I=40 +KEY=363738393B3C3D3E40414243454647484A4B4C4D4F505152 +PT=4D0C7A0D2505B80BF8B62CEB12467F0A +CT=E4F9A4AB52CED8134C649BF319EBCC90 + +I=41 +KEY=54555657595A5B5C5E5F60616364656668696A6B6D6E6F70 +PT=626D34C9429B37211330986466B94E5F +CT=B9DDD29AC6128A6CAB121E34A4C62B36 + +I=42 +KEY=727374757778797A7C7D7E7F81828384868788898B8C8D8E +PT=333C3E6BF00656B088A17E5FF0E7F60A +CT=6FCDDAD898F2CE4EFF51294F5EAAF5C9 + +I=43 +KEY=90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABAC +PT=687ED0CDC0D2A2BC8C466D05EF9D2891 +CT=C9A6FE2BF4028080BEA6F7FC417BD7E3 + +I=44 +KEY=AEAFB0B1B3B4B5B6B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CA +PT=487830E78CC56C1693E64B2A6660C7B6 +CT=6A2026846D8609D60F298A9C0673127F + +I=45 +KEY=CCCDCECFD1D2D3D4D6D7D8D9DBDCDDDEE0E1E2E3E5E6E7E8 +PT=7A48D6B7B52B29392AA2072A32B66160 +CT=2CB25C005E26EFEA44336C4C97A4240B + +I=46 +KEY=EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506 +PT=907320E64C8C5314D10F8D7A11C8618D +CT=496967AB8680DDD73D09A0E4C7DCC8AA + +I=47 +KEY=08090A0B0D0E0F10121314151718191A1C1D1E1F21222324 +PT=B561F2CA2D6E65A4A98341F3ED9FF533 +CT=D5AF94DE93487D1F3A8C577CB84A66A4 + +I=48 +KEY=262728292B2C2D2E30313233353637383A3B3C3D3F404142 +PT=DF769380D212792D026F049E2E3E48EF +CT=84BDAC569CAE2828705F267CC8376E90 + +I=49 +KEY=44454647494A4B4C4E4F50515354555658595A5B5D5E5F60 +PT=79F374BC445BDABF8FCCB8843D6054C6 +CT=F7401DDA5AD5AB712B7EB5D10C6F99B6 + +I=50 +KEY=626364656768696A6C6D6E6F71727374767778797B7C7D7E +PT=4E02F1242FA56B05C68DBAE8FE44C9D6 +CT=1C9D54318539EBD4C3B5B7E37BF119F0 + +I=51 +KEY=80818283858687888A8B8C8D8F90919294959697999A9B9C +PT=CF73C93CBFF57AC635A6F4AD2A4A1545 +CT=ACA572D65FB2764CFFD4A6ECA090EA0D + +I=52 +KEY=9E9FA0A1A3A4A5A6A8A9AAABADAEAFB0B2B3B4B5B7B8B9BA +PT=9923548E2875750725B886566784C625 +CT=36D9C627B8C2A886A10CCB36EAE3DFBB + +I=53 +KEY=BCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCED0D1D2D3D5D6D7D8 +PT=4888336B723A022C9545320F836A4207 +CT=010EDBF5981E143A81D646E597A4A568 + +I=54 +KEY=DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6 +PT=F84D9A5561B0608B1160DEE000C41BA8 +CT=8DB44D538DC20CC2F40F3067FD298E60 + +I=55 +KEY=F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314 +PT=C23192A0418E30A19B45AE3E3625BF22 +CT=930EB53BC71E6AC4B82972BDCD5AAFB3 + +I=56 +KEY=161718191B1C1D1E20212223252627282A2B2C2D2F303132 +PT=B84E0690B28B0025381AD82A15E501A7 +CT=6C42A81EDCBC9517CCD89C30C95597B4 + +I=57 +KEY=34353637393A3B3C3E3F40414344454648494A4B4D4E4F50 +PT=ACEF5E5C108876C4F06269F865B8F0B0 +CT=DA389847AD06DF19D76EE119C71E1DD3 + +I=58 +KEY=525354555758595A5C5D5E5F61626364666768696B6C6D6E +PT=0F1B3603E0F5DDEA4548246153A5E064 +CT=E018FDAE13D3118F9A5D1A647A3F0462 + +I=59 +KEY=70717273757677787A7B7C7D7F80818284858687898A8B8C +PT=FBB63893450D42B58C6D88CD3C1809E3 +CT=2AA65DB36264239D3846180FABDFAD20 + +I=60 +KEY=8E8F90919394959698999A9B9D9E9FA0A2A3A4A5A7A8A9AA +PT=4BEF736DF150259DAE0C91354E8A5F92 +CT=1472163E9A4F780F1CEB44B07ECF4FDB + +I=61 +KEY=ACADAEAFB1B2B3B4B6B7B8B9BBBCBDBEC0C1C2C3C5C6C7C8 +PT=7D2D46242056EF13D3C3FC93C128F4C7 +CT=C8273FDC8F3A9F72E91097614B62397C + +I=62 +KEY=CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6 +PT=E9C1BA2DF415657A256EDB33934680FD +CT=66C8427DCD733AAF7B3470CB7D976E3F + +I=63 +KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304 +PT=E23EE277B0AA0A1DFB81F7527C3514F1 +CT=146131CB17F1424D4F8DA91E6F80C1D0 + +I=64 +KEY=060708090B0C0D0E10111213151617181A1B1C1D1F202122 +PT=3E7445B0B63CAAF75E4A911E12106B4C +CT=2610D0AD83659081AE085266A88770DC + +I=65 +KEY=24252627292A2B2C2E2F30313334353638393A3B3D3E3F40 +PT=767774752023222544455A5BE6E1E0E3 +CT=38A2B5A974B0575C5D733917FB0D4570 + +I=66 +KEY=424344454748494A4C4D4E4F51525354565758595B5C5D5E +PT=72737475717E7F7CE9E8EBEA696A6B6C +CT=E21D401EBC60DE20D6C486E4F39A588B + +I=67 +KEY=60616263656667686A6B6C6D6F70717274757677797A7B7C +PT=DFDEDDDC25262728C9C8CFCEF1EEEFEC +CT=E51D5F88C670B079C0CA1F0C2C4405A2 + +I=68 +KEY=7E7F80818384858688898A8B8D8E8F90929394959798999A +PT=FFFE0100707776755F5E5D5C7675746B +CT=246A94788A642FB3D1B823C8762380C8 + +I=69 +KEY=9C9D9E9FA1A2A3A4A6A7A8A9ABACADAEB0B1B2B3B5B6B7B8 +PT=E0E1E2E3424140479F9E9190292E2F2C +CT=B80C391C5C41A4C3B30C68E0E3D7550F + +I=70 +KEY=BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6 +PT=2120272690EFEEED3B3A39384E4D4C4B +CT=B77C4754FC64EB9A1154A9AF0BB1F21C + +I=71 +KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4 +PT=ECEDEEEF5350516EA1A0A7A6A3ACADAE +CT=FB554DE520D159A06BF219FC7F34A02F + +I=72 +KEY=F6F7F8F9FBFCFDFE00010203050607080A0B0C0D0F101112 +PT=32333C3D25222320E9E8EBEACECDCCC3 +CT=A89FBA152D76B4927BEED160DDB76C57 + +I=73 +KEY=14151617191A1B1C1E1F20212324252628292A2B2D2E2F30 +PT=40414243626160678A8BB4B511161714 +CT=5676EAB4A98D2E8473B3F3D46424247C + +I=74 +KEY=323334353738393A3C3D3E3F41424344464748494B4C4D4E +PT=94959293F5FAFBF81F1E1D1C7C7F7E79 +CT=4E8F068BD7EDE52A639036EC86C33568 + +I=75 +KEY=50515253555657585A5B5C5D5F60616264656667696A6B6C +PT=BEBFBCBD191A1B14CFCEC9C8546B6A69 +CT=F0193C4D7AFF1791EE4C07EB4A1824FC + +I=76 +KEY=6E6F70717374757678797A7B7D7E7F80828384858788898A +PT=2C2D3233898E8F8CBBBAB9B8333031CE +CT=AC8686EECA9BA761AFE82D67B928C33F + +I=77 +KEY=8C8D8E8F91929394969798999B9C9D9EA0A1A2A3A5A6A7A8 +PT=84858687BFBCBDBA37363938FDFAFBF8 +CT=5FAF8573E33B145B6A369CD3606AB2C9 + +I=78 +KEY=AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6 +PT=828384857669686B909192930B08090E +CT=31587E9944AB1C16B844ECAD0DF2E7DA + +I=79 +KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4 +PT=BEBFBCBD9695948B707176779E919093 +CT=D017FECD91148ABA37F6F3068AA67D8A + +I=80 +KEY=E6E7E8E9EBECEDEEF0F1F2F3F5F6F7F8FAFBFCFDFE010002 +PT=8B8A85846067666521202322D0D3D2DD +CT=788EF2F021A73CBA2794B616078A8500 + +I=81 +KEY=04050607090A0B0C0E0F10111314151618191A1B1D1E1F20 +PT=76777475F1F2F3F4F8F9E6E777707172 +CT=5D1EF20DCED6BCBC12131AC7C54788AA + +I=82 +KEY=222324252728292A2C2D2E2F31323334363738393B3C3D3E +PT=A4A5A2A34F404142B4B5B6B727242522 +CT=B3C8CF961FAF9EA05FDDE6D1E4D8F663 + +I=83 +KEY=40414243454647484A4B4C4D4F50515254555657595A5B5C +PT=94959697E1E2E3EC16171011839C9D9E +CT=143075C70605861C7FAC6526199E459F + +I=84 +KEY=5E5F60616364656668696A6B6D6E6F70727374757778797A +PT=03023D3C06010003DEDFDCDDFFFCFDE2 +CT=A5AE12EADE9A87268D898BFC8FC0252A + +I=85 +KEY=7C7D7E7F81828384868788898B8C8D8E9091929395969798 +PT=10111213F1F2F3F4CECFC0C1DBDCDDDE +CT=0924F7CF2E877A4819F5244A360DCEA9 + +I=86 +KEY=9A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6 +PT=67666160724D4C4F1D1C1F1E73707176 +CT=3D9E9635AFCC3E291CC7AB3F27D1C99A + +I=87 +KEY=B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4 +PT=E6E7E4E5A8ABAAD584858283909F9E9D +CT=9D80FEEBF87510E2B8FB98BB54FD788C + +I=88 +KEY=D6D7D8D9DBDCDDDEE0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2 +PT=71707F7E565150537D7C7F7E6162636C +CT=5F9D1A082A1A37985F174002ECA01309 + +I=89 +KEY=F4F5F6F7F9FAFBFCFEFE01010304050608090A0B0D0E0F10 +PT=64656667212223245555AAAA03040506 +CT=A390EBB1D1403930184A44B4876646E4 + +I=90 +KEY=121314151718191A1C1D1E1F21222324262728292B2C2D2E +PT=9E9F9899ABA4A5A6CFCECDCC2B28292E +CT=700FE918981C3195BB6C4BCB46B74E29 + +I=91 +KEY=30313233353637383A3B3C3D3F40414244454647494A4B4C +PT=C7C6C5C4D1D2D3DC626364653A454447 +CT=907984406F7BF2D17FB1EB15B673D747 + +I=92 +KEY=4E4F50515354555658595A5B5D5E5F60626364656768696A +PT=F6F7E8E9E0E7E6E51D1C1F1E5B585966 +CT=C32A956DCFC875C2AC7C7CC8B8CC26E1 + +I=93 +KEY=6C6D6E6F71727374767778797B7C7D7E8081828385868788 +PT=BCBDBEBF5D5E5F5868696667F4F3F2F1 +CT=02646E2EBFA9B820CF8424E9B9B6EB51 + +I=94 +KEY=8A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6 +PT=40414647B0AFAEAD9B9A99989B98999E +CT=621FDA3A5BBD54C6D3C685816BD4EAD8 + +I=95 +KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4 +PT=69686B6A0201001F0F0E0908B4BBBAB9 +CT=D4E216040426DFAF18B152469BC5AC2F + +I=96 +KEY=C6C7C8C9CBCCCDCED0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2 +PT=C7C6C9C8D8DFDEDD5A5B5859BEBDBCB3 +CT=9D0635B9D33B6CDBD71F5D246EA17CC8 + +I=97 +KEY=E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6F8F9FAFBFDFEFE00 +PT=DEDFDCDD787B7A7DFFFEE1E0B2B5B4B7 +CT=10ABAD1BD9BAE5448808765583A2CC1A + +I=98 +KEY=020304050708090A0C0D0E0F11121314161718191B1C1D1E +PT=4D4C4B4A606F6E6DD0D1D2D3FBF8F9FE +CT=6891889E16544E355FF65A793C39C9A8 + +I=99 +KEY=20212223252627282A2B2C2D2F30313234353637393A3B3C +PT=B7B6B5B4D7D4D5DAE5E4E3E2E1FEFFFC +CT=CC735582E68072C163CD9DDF46B91279 + +I=100 +KEY=3E3F40414344454648494A4B4D4E4F50525354555758595A +PT=CECFB0B1F7F0F1F2AEAFACAD3E3D3C23 +CT=C5C68B9AEEB7F878DF578EFA562F9574 + +I=101 +KEY=5C5D5E5F61626364666768696B6C6D6E7071727375767778 +PT=CACBC8C9CDCECFC812131C1D494E4F4C +CT=5F4764395A667A47D73452955D0D2CE8 + +I=102 +KEY=7A7B7C7D7F80818284858687898A8B8C8E8F909193949596 +PT=9D9C9B9AD22D2C2FB1B0B3B20C0F0E09 +CT=701448331F66106CEFDDF1EB8267C357 + +I=103 +KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4 +PT=7A7B787964676659959493924F404142 +CT=CB3EE56D2E14B4E1941666F13379D657 + +I=104 +KEY=B6B7B8B9BBBCBDBEC0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2 +PT=AAABA4A5CEC9C8CB1F1E1D1CABA8A9A6 +CT=9FE16EFD18AB6E1981191851FEDB0764 + +I=105 +KEY=D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6E8E9EAEBEDEEEFF0 +PT=93929190282B2A2DC4C5FAFB92959497 +CT=3DC9BA24E1B223589B147ADCEB4C8E48 + +I=106 +KEY=F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E +PT=EFEEE9E8DED1D0D339383B3A888B8A8D +CT=1C333032682E7D4DE5E5AFC05C3E483C + +I=107 +KEY=10111213151617181A1B1C1D1F20212224252627292A2B2C +PT=7F7E7D7CA2A1A0AF78797E7F112E2F2C +CT=D593CC99A95AFEF7E92038E05A59D00A + +I=108 +KEY=2E2F30313334353638393A3B3D3E3F40424344454748494A +PT=84859A9B2B2C2D2E868784852625245B +CT=51E7F96F53B4353923452C222134E1EC + +I=109 +KEY=4C4D4E4F51525354565758595B5C5D5E6061626365666768 +PT=B0B1B2B3070405026869666710171615 +CT=4075B357A1A2B473400C3B25F32F81A4 + +I=110 +KEY=6A6B6C6D6F70717274757677797A7B7C7E7F808183848586 +PT=ACADAAABBDA2A3A00D0C0F0E595A5B5C +CT=302E341A3EBCD74F0D55F61714570284 + +I=111 +KEY=88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4 +PT=121310115655544B5253545569666764 +CT=57ABDD8231280DA01C5042B78CF76522 + +I=112 +KEY=A6A7A8A9ABACADAEB0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2 +PT=DEDFD0D166616063EAEBE8E94142434C +CT=17F9EA7EEA17AC1ADF0E190FEF799E92 + +I=113 +KEY=C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6D8D9DADBDDDEDFE0 +PT=DBDAD9D81417161166677879E0E7E6E5 +CT=2E1BDD563DD87EE5C338DD6D098D0A7A + +I=114 +KEY=E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE +PT=6A6B6C6DE0EFEEED2B2A2928C0C3C2C5 +CT=EB869996E6F8BFB2BFDD9E0C4504DBB2 + +I=115 +KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C +PT=B1B0B3B21714151A1A1B1C1D5649484B +CT=C2E01549E9DECF317468B3E018C61BA8 + +I=116 +KEY=1E1F20212324252628292A2B2D2E2F30323334353738393A +PT=39380706A3A4A5A6C4C5C6C77271706F +CT=8DA875D033C01DD463B244A1770F4A22 + +I=117 +KEY=3C3D3E3F41424344464748494B4C4D4E5051525355565758 +PT=5C5D5E5F1013121539383736E2E5E4E7 +CT=8BA0DCF3A186844F026D022F8839D696 + +I=118 +KEY=5A5B5C5D5F60616264656667696A6B6C6E6F707173747576 +PT=43424544EAD5D4D72E2F2C2D64676661 +CT=E9691FF9A6CC6970E51670A0FD5B88C1 + +I=119 +KEY=78797A7B7D7E7F80828384858788898A8C8D8E8F91929394 +PT=55545756989B9A65F8F9FEFF18171615 +CT=F2BAEC06FAEED30F88EE63BA081A6E5B + +I=120 +KEY=969798999B9C9D9EA0A1A2A3A5A6A7A8AAABACADAFB0B1B2 +PT=05040B0A525554573C3D3E3F4A494847 +CT=9C39D4C459AE5753394D6094ADC21E78 + +I=121 +KEY=B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6C8C9CACBCDCECFD0 +PT=14151617595A5B5C8584FBFA8E89888B +CT=6345B532A11904502EA43BA99C6BD2B2 + +I=122 +KEY=D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE +PT=7C7D7A7BFDF2F3F029282B2A51525354 +CT=5FFAE3061A95172E4070CEDCE1E428C8 + +I=123 +KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C +PT=38393A3B1E1D1C1341404746C23D3C3E +CT=0A4566BE4CDF9ADCE5DEC865B5AB34CD + +I=124 +KEY=0E0F10111314151618191A1B1D1E1F20222324252728292A +PT=8D8C939240474645818083827C7F7E41 +CT=CA17FCCE79B7404F2559B22928F126FB + +I=125 +KEY=2C2D2E2F31323334363738393B3C3D3E4041424345464748 +PT=3B3A39381A19181F32333C3D45424340 +CT=97CA39B849ED73A6470A97C821D82F58 + +I=126 +KEY=4A4B4C4D4F50515254555657595A5B5C5E5F606163646566 +PT=F0F1F6F738272625828380817F7C7D7A +CT=8198CB06BC684C6D3E9B7989428DCF7A + +I=127 +KEY=68696A6B6D6E6F70727374757778797A7C7D7E7F81828384 +PT=89888B8A0407061966676061141B1A19 +CT=F53C464C705EE0F28D9A4C59374928BD + +I=128 +KEY=868788898B8C8D8E90919293959697989A9B9C9D9FA0A1A2 +PT=D3D2DDDCAAADACAF9C9D9E9FE8EBEAE5 +CT=9ADB3D4CCA559BB98C3E2ED73DBF1154 + +========== + +KEYSIZE=256 + + +I=1 +KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526 +PT=834EADFCCAC7E1B30664B1ABA44815AB +CT=1946DABF6A03A2A2C3D0B05080AED6FC + +I=2 +KEY=28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E +PT=D9DC4DBA3021B05D67C0518F72B62BF1 +CT=5ED301D747D3CC715445EBDEC62F2FB4 + +I=3 +KEY=50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576 +PT=A291D86301A4A739F7392173AA3C604C +CT=6585C8F43D13A6BEAB6419FC5935B9D0 + +I=4 +KEY=78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E +PT=4264B2696498DE4DF79788A9F83E9390 +CT=2A5B56A596680FCC0E05F5E0F151ECAE + +I=5 +KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6 +PT=EE9932B3721804D5A83EF5949245B6F6 +CT=F5D6FF414FD2C6181494D20C37F2B8C4 + +I=6 +KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE +PT=E6248F55C5FDCBCA9CBBB01C88A2EA77 +CT=85399C01F59FFFB5204F19F8482F00B8 + +I=7 +KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516 +PT=B8358E41B9DFF65FD461D55A99266247 +CT=92097B4C88A041DDF98144BC8D22E8E7 + +I=8 +KEY=18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E +PT=F0E2D72260AF58E21E015AB3A4C0D906 +CT=89BD5B73B356AB412AEF9F76CEA2D65C + +I=9 +KEY=40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566 +PT=475B8B823CE8893DB3C44A9F2A379FF7 +CT=2536969093C55FF9454692F2FAC2F530 + +I=10 +KEY=68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E +PT=688F5281945812862F5F3076CF80412F +CT=07FC76A872843F3F6E0081EE9396D637 + +I=11 +KEY=90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6 +PT=08D1D2BC750AF553365D35E75AFACEAA +CT=E38BA8EC2AA741358DCC93E8F141C491 + +I=12 +KEY=B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE +PT=8707121F47CC3EFCECA5F9A8474950A1 +CT=D028EE23E4A89075D0B03E868D7D3A42 + +I=13 +KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506 +PT=E51AA0B135DBA566939C3B6359A980C5 +CT=8CD9423DFC459E547155C5D1D522E540 + +I=14 +KEY=08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E +PT=069A007FC76A459F98BAF917FEDF9521 +CT=080E9517EB1677719ACF728086040AE3 + +I=15 +KEY=30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556 +PT=726165C1723FBCF6C026D7D00B091027 +CT=7C1700211A3991FC0ECDED0AB3E576B0 + +I=16 +KEY=58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E +PT=D7C544DE91D55CFCDE1F84CA382200CE +CT=DABCBCC855839251DB51E224FBE87435 + +I=17 +KEY=80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6 +PT=FED3C9A161B9B5B2BD611B41DC9DA357 +CT=68D56FAD0406947A4DD27A7448C10F1D + +I=18 +KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE +PT=4F634CDC6551043409F30B635832CF82 +CT=DA9A11479844D1FFEE24BBF3719A9925 + +I=19 +KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6 +PT=109CE98DB0DFB36734D9F3394711B4E6 +CT=5E4BA572F8D23E738DA9B05BA24B8D81 + +I=20 +KEY=70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596 +PT=4EA6DFABA2D8A02FFDFFA89835987242 +CT=A115A2065D667E3F0B883837A6E903F8 + +I=21 +KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE +PT=5AE094F54AF58E6E3CDBF976DAC6D9EF +CT=3E9E90DC33EAC2437D86AD30B137E66E + +I=22 +KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6 +PT=764D8E8E0F29926DBE5122E66354FDBE +CT=01CE82D8FBCDAE824CB3C48E495C3692 + +I=23 +KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E +PT=3F0418F888CDF29A982BF6B75410D6A9 +CT=0C9CFF163CE936FAAF083CFD3DEA3117 + +I=24 +KEY=10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536 +PT=E4A3E7CB12CDD56AA4A75197A9530220 +CT=5131BA9BD48F2BBA85560680DF504B52 + +I=25 +KEY=38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E +PT=211677684AAC1EC1A160F44C4EBF3F26 +CT=9DC503BBF09823AEC8A977A5AD26CCB2 + +I=26 +KEY=60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586 +PT=D21E439FF749AC8F18D6D4B105E03895 +CT=9A6DB0C0862E506A9E397225884041D7 + +I=27 +KEY=88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE +PT=D9F6FF44646C4725BD4C0103FF5552A7 +CT=430BF9570804185E1AB6365FC6A6860C + +I=28 +KEY=B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6 +PT=0B1256C2A00B976250CFC5B0C37ED382 +CT=3525EBC02F4886E6A5A3762813E8CE8A + +I=29 +KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE +PT=B056447FFC6DC4523A36CC2E972A3A79 +CT=07FA265C763779CCE224C7BAD671027B + +I=30 +KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526 +PT=5E25CA78F0DE55802524D38DA3FE4456 +CT=E8B72B4E8BE243438C9FFF1F0E205872 + +I=31 +KEY=28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E +PT=A5BCF4728FA5EAAD8567C0DC24675F83 +CT=109D4F999A0E11ACE1F05E6B22CBCB50 + +I=32 +KEY=50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576 +PT=814E59F97ED84646B78B2CA022E9CA43 +CT=45A5E8D4C3ED58403FF08D68A0CC4029 + +I=33 +KEY=78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E +PT=15478BEEC58F4775C7A7F5D4395514D7 +CT=196865964DB3D417B6BD4D586BCB7634 + +I=34 +KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6 +PT=253548FFCA461C67C8CBC78CD59F4756 +CT=60436AD45AC7D30D99195F815D98D2AE + +I=35 +KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE +PT=FD7AD8D73B9B0F8CC41600640F503D65 +CT=BB07A23F0B61014B197620C185E2CD75 + +I=36 +KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516 +PT=06199DE52C6CBF8AF954CD65830BCD56 +CT=5BC0B2850129C854423AFF0751FE343B + +I=37 +KEY=18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E +PT=F17C4FFE48E44C61BD891E257E725794 +CT=7541A78F96738E6417D2A24BD2BECA40 + +I=38 +KEY=40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566 +PT=9A5B4A402A3E8A59BE6BF5CD8154F029 +CT=B0A303054412882E464591F1546C5B9E + +I=39 +KEY=68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E +PT=79BD40B91A7E07DC939D441782AE6B17 +CT=778C06D8A355EEEE214FCEA14B4E0EEF + +I=40 +KEY=90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6 +PT=D8CEAAF8976E5FBE1012D8C84F323799 +CT=09614206D15CBACE63227D06DB6BEEBB + +I=41 +KEY=B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE +PT=3316E2751E2E388B083DA23DD6AC3FBE +CT=41B97FB20E427A9FDBBB358D9262255D + +I=42 +KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506 +PT=8B7CFBE37DE7DCA793521819242C5816 +CT=C1940F703D845F957652C2D64ABD7ADF + +I=43 +KEY=08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E +PT=F23F033C0EEBF8EC55752662FD58CE68 +CT=D2D44FCDAE5332343366DB297EFCF21B + +I=44 +KEY=30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556 +PT=59EB34F6C8BDBACC5FC6AD73A59A1301 +CT=EA8196B79DBE167B6AA9896E287EED2B + +I=45 +KEY=58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E +PT=DCDE8B6BD5CF7CC22D9505E3CE81261A +CT=D6B0B0C4BA6C7DBE5ED467A1E3F06C2D + +I=46 +KEY=80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6 +PT=E33CF7E524FED781E7042FF9F4B35DC7 +CT=EC51EB295250C22C2FB01816FB72BCAE + +I=47 +KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE +PT=27963C8FACDF73062867D164DF6D064C +CT=ADED6630A07CE9C7408A155D3BD0D36F + +I=48 +KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6 +PT=77B1CE386B551B995F2F2A1DA994EEF8 +CT=697C9245B9937F32F5D1C82319F0363A + +I=49 +KEY=F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314161718191B1C1D1E +PT=F083388B013679EFCF0BB9B15D52AE5C +CT=AAD5AD50C6262AAEC30541A1B7B5B19C + +I=50 +KEY=20212223252627282A2B2C2D2F30313234353637393A3B3C3E3F404143444546 +PT=C5009E0DAB55DB0ABDB636F2600290C8 +CT=7D34B893855341EC625BD6875AC18C0D + +I=51 +KEY=48494A4B4D4E4F50525354555758595A5C5D5E5F61626364666768696B6C6D6E +PT=7804881E26CD532D8514D3683F00F1B9 +CT=7EF05105440F83862F5D780E88F02B41 + +I=52 +KEY=70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596 +PT=46CDDCD73D1EB53E675CA012870A92A3 +CT=C377C06403382061AF2C9C93A8E70DF6 + +I=53 +KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE +PT=A9FB44062BB07FE130A8E8299EACB1AB +CT=1DBDB3FFDC052DACC83318853ABC6DE5 + +I=54 +KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6 +PT=2B6FF8D7A5CC3A28A22D5A6F221AF26B +CT=69A6EAB00432517D0BF483C91C0963C7 + +I=55 +KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E +PT=1A9527C29B8ADD4B0E3E656DBB2AF8B4 +CT=0797F41DC217C80446E1D514BD6AB197 + +I=56 +KEY=10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536 +PT=7F99CF2C75244DF015EB4B0C1050AEAE +CT=9DFD76575902A637C01343C58E011A03 + +I=57 +KEY=38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E +PT=E84FF85B0D9454071909C1381646C4ED +CT=ACF4328AE78F34B9FA9B459747CC2658 + +I=58 +KEY=60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586 +PT=89AFD40F99521280D5399B12404F6DB4 +CT=B0479AEA12BAC4FE2384CF98995150C6 + +I=59 +KEY=88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE +PT=A09EF32DBC5119A35AB7FA38656F0329 +CT=9DD52789EFE3FFB99F33B3DA5030109A + +I=60 +KEY=B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6 +PT=61773457F068C376C7829B93E696E716 +CT=ABBB755E4621EF8F1214C19F649FB9FD + +I=61 +KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE +PT=A34F0CAE726CCE41DD498747D891B967 +CT=DA27FB8174357BCE2BED0E7354F380F9 + +I=62 +KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526 +PT=856F59496C7388EE2D2B1A27B7697847 +CT=C59A0663F0993838F6E5856593BDC5EF + +I=63 +KEY=28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E +PT=CB090C593EF7720BD95908FB93B49DF4 +CT=ED60B264B5213E831607A99C0CE5E57E + +I=64 +KEY=50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576 +PT=A0AC75CD2F1923D460FC4D457AD95BAF +CT=E50548746846F3EB77B8C520640884ED + +I=65 +KEY=78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E +PT=2A2B282974777689E8E9EEEF525D5C5F +CT=28282CC7D21D6A2923641E52D188EF0C + +I=66 +KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6 +PT=909192939390919E0F0E09089788898A +CT=0DFA5B02ABB18E5A815305216D6D4F8E + +I=67 +KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE +PT=777675748D8E8F907170777649464744 +CT=7359635C0EECEFE31D673395FB46FB99 + +I=68 +KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516 +PT=717073720605040B2D2C2B2A05FAFBF9 +CT=73C679F7D5AEF2745C9737BB4C47FB36 + +I=69 +KEY=18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E +PT=64656667FEFDFCC31B1A1D1CA5AAABA8 +CT=B192BD472A4D2EAFB786E97458967626 + +I=70 +KEY=40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566 +PT=DBDAD9D86A696867B5B4B3B2C8D7D6D5 +CT=0EC327F6C8A2B147598CA3FDE61DC6A4 + +I=71 +KEY=68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E +PT=5C5D5E5FE3E0E1FE31303736333C3D3E +CT=FC418EB3C41B859B38D4B6F646629729 + +I=72 +KEY=90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6 +PT=545556574B48494673727574546B6A69 +CT=30249E5AC282B1C981EA64B609F3A154 + +I=73 +KEY=B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE +PT=ECEDEEEFC6C5C4BB56575051F5FAFBF8 +CT=5E6E08646D12150776BB43C2D78A9703 + +I=74 +KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506 +PT=464744452724252AC9C8CFCED2CDCCCF +CT=FAEB3D5DE652CD3447DCEB343F30394A + +I=75 +KEY=08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E +PT=E6E7E4E54142435C878681801C131211 +CT=A8E88706823F6993EF80D05C1C7B2CF0 + +I=76 +KEY=30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556 +PT=72737071CFCCCDC2F9F8FFFE710E0F0C +CT=8CED86677E6E00A1A1B15968F2D3CCE6 + +I=77 +KEY=58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E +PT=505152537370714EC3C2C5C4010E0F0C +CT=9FC7C23858BE03BDEBB84E90DB6786A9 + +I=78 +KEY=80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6 +PT=A8A9AAAB5C5F5E51AEAFA8A93D222320 +CT=B4FBD65B33F70D8CF7F1111AC4649C36 + +I=79 +KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE +PT=DEDFDCDDF6F5F4EB10111617FEF1F0F3 +CT=C5C32D5ED03C4B53CC8C1BD0EF0DBBF6 + +I=80 +KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6 +PT=BDBCBFBE5E5D5C530B0A0D0CFAC5C4C7 +CT=D1A7F03B773E5C212464B63709C6A891 + +I=81 +KEY=F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314161718191B1C1D1E +PT=8A8B8889050606F8F4F5F2F3636C6D6E +CT=6B7161D8745947AC6950438EA138D028 + +I=82 +KEY=20212223252627282A2B2C2D2F30313234353637393A3B3C3E3F404143444546 +PT=A6A7A4A54D4E4F40B2B3B4B539262724 +CT=FD47A9F7E366EE7A09BC508B00460661 + +I=83 +KEY=48494A4B4D4E4F50525354555758595A5C5D5E5F61626364666768696B6C6D6E +PT=9C9D9E9FE9EAEBF40E0F08099B949596 +CT=00D40B003DC3A0D9310B659B98C7E416 + +I=84 +KEY=70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596 +PT=2D2C2F2E1013121DCCCDCACBED121310 +CT=EEA4C79DCC8E2BDA691F20AC48BE0717 + +I=85 +KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE +PT=F4F5F6F7EDEEEFD0EAEBECEDF7F8F9FA +CT=E78F43B11C204403E5751F89D05A2509 + +I=86 +KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6 +PT=3D3C3F3E282B2A2573727574150A0B08 +CT=D0F0E3D1F1244BB979931E38DD1786EF + +I=87 +KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E +PT=B6B7B4B5F8FBFAE5B4B5B2B3A0AFAEAD +CT=042E639DC4E1E4DDE7B75B749EA6F765 + +I=88 +KEY=10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536 +PT=B7B6B5B4989B9A95878681809BA4A5A6 +CT=BC032FDD0EFE29503A980A7D07AB46A8 + +I=89 +KEY=38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E +PT=A8A9AAABE5E6E798E9E8EFEE4748494A +CT=0C93AC949C0DA6446EFFB86183B6C910 + +I=90 +KEY=60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586 +PT=ECEDEEEFD9DADBD4B9B8BFBE657A7B78 +CT=E0D343E14DA75C917B4A5CEC4810D7C2 + +I=91 +KEY=88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE +PT=7F7E7D7C696A6B74CACBCCCD929D9C9F +CT=0EAFB821748408279B937B626792E619 + +I=92 +KEY=B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6 +PT=08090A0B0605040BFFFEF9F8B9C6C7C4 +CT=FA1AC6E02D23B106A1FEF18B274A553F + +I=93 +KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE +PT=08090A0BF1F2F3CCFCFDFAFB68676665 +CT=0DADFE019CD12368075507DF33C1A1E9 + +I=94 +KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526 +PT=CACBC8C93A393837050403020D121310 +CT=3A0879B414465D9FFBAF86B33A63A1B9 + +I=95 +KEY=28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E +PT=E9E8EBEA8281809F8F8E8988343B3A39 +CT=62199FADC76D0BE1805D3BA0B7D914BF + +I=96 +KEY=50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576 +PT=515053524645444BD0D1D6D7340B0A09 +CT=1B06D6C5D333E742730130CF78E719B4 + +I=97 +KEY=78797A7B7D7E7F80828384858788898A8C8D8E8F91929394969798999B9C9D9E +PT=42434041ECEFEE1193929594C6C9C8CB +CT=F1F848824C32E9DCDCBF21580F069329 + +I=98 +KEY=A0A1A2A3A5A6A7A8AAABACADAFB0B1B2B4B5B6B7B9BABBBCBEBFC0C1C3C4C5C6 +PT=EFEEEDECC2C1C0CF76777071455A5B58 +CT=1A09050CBD684F784D8E965E0782F28A + +I=99 +KEY=C8C9CACBCDCECFD0D2D3D4D5D7D8D9DADCDDDEDFE1E2E3E4E6E7E8E9EBECEDEE +PT=5F5E5D5C3F3C3D221D1C1B1A19161714 +CT=79C2969E7DED2BA7D088F3F320692360 + +I=100 +KEY=F0F1F2F3F5F6F7F8FAFBFCFDFE01000204050607090A0B0C0E0F101113141516 +PT=000102034142434C1C1D1A1B8D727371 +CT=091A658A2F7444C16ACCB669450C7B63 + +I=101 +KEY=18191A1B1D1E1F20222324252728292A2C2D2E2F31323334363738393B3C3D3E +PT=8E8F8C8DB1B2B38C56575051050A0B08 +CT=97C1E3A72CCA65FA977D5ED0E8A7BBFC + +I=102 +KEY=40414243454647484A4B4C4D4F50515254555657595A5B5C5E5F606163646566 +PT=A7A6A5A4E8EBEAE57F7E7978CAD5D4D7 +CT=70C430C6DB9A17828937305A2DF91A2A + +I=103 +KEY=68696A6B6D6E6F70727374757778797A7C7D7E7F81828384868788898B8C8D8E +PT=8A8B888994979689454443429F909192 +CT=629553457FBE2479098571C7C903FDE8 + +I=104 +KEY=90919293959697989A9B9C9D9FA0A1A2A4A5A6A7A9AAABACAEAFB0B1B3B4B5B6 +PT=8C8D8E8FE0E3E2ED45444342F1CECFCC +CT=A25B25A61F612669E7D91265C7D476BA + +I=105 +KEY=B8B9BABBBDBEBFC0C2C3C4C5C7C8C9CACCCDCECFD1D2D3D4D6D7D8D9DBDCDDDE +PT=FFFEFDFC4C4F4E31D8D9DEDFB6B9B8BB +CT=EB7E4E49B8AE0F024570DDA293254FED + +I=106 +KEY=E0E1E2E3E5E6E7E8EAEBECEDEFF0F1F2F4F5F6F7F9FAFBFCFEFE010103040506 +PT=FDFCFFFECCCFCEC12F2E29286679787B +CT=38FE15D61CCA84516E924ADCE5014F67 + +I=107 +KEY=08090A0B0D0E0F10121314151718191A1C1D1E1F21222324262728292B2C2D2E +PT=67666564BAB9B8A77071767719161714 +CT=3AD208492249108C9F3EBEB167AD0583 + +I=108 +KEY=30313233353637383A3B3C3D3F40414244454647494A4B4C4E4F505153545556 +PT=9A9B98992D2E2F2084858283245B5A59 +CT=299BA9F9BF5AB05C3580FC26EDD1ED12 + +I=109 +KEY=58595A5B5D5E5F60626364656768696A6C6D6E6F71727374767778797B7C7D7E +PT=A4A5A6A70B0809365C5D5A5B2C232221 +CT=19DC705B857A60FB07717B2EA5717781 + +I=110 +KEY=80818283858687888A8B8C8D8F90919294959697999A9B9C9E9FA0A1A3A4A5A6 +PT=464744455754555AF3F2F5F4AFB0B1B2 +CT=FFC8AEB885B5EFCAD06B6DBEBF92E76B + +I=111 +KEY=A8A9AAABADAEAFB0B2B3B4B5B7B8B9BABCBDBEBFC1C2C3C4C6C7C8C9CBCCCDCE +PT=323330317675746B7273747549464744 +CT=F58900C5E0B385253FF2546250A0142B + +I=112 +KEY=D0D1D2D3D5D6D7D8DADBDCDDDFE0E1E2E4E5E6E7E9EAEBECEEEFF0F1F3F4F5F6 +PT=A8A9AAAB181B1A15808186872B141516 +CT=2EE67B56280BC462429CEE6E3370CBC1 + +I=113 +KEY=F8F9FAFBFDFEFE00020304050708090A0C0D0E0F11121314161718191B1C1D1E +PT=E7E6E5E4202323DDAAABACAD343B3A39 +CT=20DB650A9C8E9A84AB4D25F7EDC8F03F + +I=114 +KEY=20212223252627282A2B2C2D2F30313234353637393A3B3C3E3F404143444546 +PT=A8A9AAAB2221202FEDECEBEA1E010003 +CT=3C36DA169525CF818843805F25B78AE5 + +I=115 +KEY=48494A4B4D4E4F50525354555758595A5C5D5E5F61626364666768696B6C6D6E +PT=F9F8FBFA5F5C5D42424344450E010003 +CT=9A781D960DB9E45E37779042FEA51922 + +I=116 +KEY=70717273757677787A7B7C7D7F80818284858687898A8B8C8E8F909193949596 +PT=57565554F5F6F7F89697909120DFDEDD +CT=6560395EC269C672A3C288226EFDBA77 + +I=117 +KEY=98999A9B9D9E9FA0A2A3A4A5A7A8A9AAACADAEAFB1B2B3B4B6B7B8B9BBBCBDBE +PT=F8F9FAFBCCCFCEF1DDDCDBDA0E010003 +CT=8C772B7A189AC544453D5916EBB27B9A + +I=118 +KEY=C0C1C2C3C5C6C7C8CACBCCCDCFD0D1D2D4D5D6D7D9DADBDCDEDFE0E1E3E4E5E6 +PT=D9D8DBDA7073727D80818687C2DDDCDF +CT=77CA5468CC48E843D05F78EED9D6578F + +I=119 +KEY=E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FAFCFDFEFF01020304060708090B0C0D0E +PT=C5C4C7C6080B0A1588898E8F68676665 +CT=72CDCC71DC82C60D4429C9E2D8195BAA + +I=120 +KEY=10111213151617181A1B1C1D1F20212224252627292A2B2C2E2F303133343536 +PT=83828180DCDFDED186878081F0CFCECD +CT=8080D68CE60E94B40B5B8B69EEB35AFA + +I=121 +KEY=38393A3B3D3E3F40424344454748494A4C4D4E4F51525354565758595B5C5D5E +PT=98999A9BDDDEDFA079787F7E0A050407 +CT=44222D3CDE299C04369D58AC0EBA1E8E + +I=122 +KEY=60616263656667686A6B6C6D6F70717274757677797A7B7C7E7F808183848586 +PT=CECFCCCD4F4C4D429F9E9998DFC0C1C2 +CT=9B8721B0A8DFC691C5BC5885DBFCB27A + +I=123 +KEY=88898A8B8D8E8F90929394959798999A9C9D9E9FA1A2A3A4A6A7A8A9ABACADAE +PT=404142436665647B29282F2EABA4A5A6 +CT=0DC015CE9A3A3414B5E62EC643384183 + +I=124 +KEY=B0B1B2B3B5B6B7B8BABBBCBDBFC0C1C2C4C5C6C7C9CACBCCCECFD0D1D3D4D5D6 +PT=33323130E6E5E4EB23222524DEA1A0A3 +CT=705715448A8DA412025CE38345C2A148 + +I=125 +KEY=D8D9DADBDDDEDFE0E2E3E4E5E7E8E9EAECEDEEEFF1F2F3F4F6F7F8F9FBFCFDFE +PT=CFCECDCCF6F5F4CBE6E7E0E199969794 +CT=C32B5B0B6FBAE165266C569F4B6ECF0B + +I=126 +KEY=00010203050607080A0B0C0D0F10111214151617191A1B1C1E1F202123242526 +PT=BABBB8B97271707FDCDDDADB29363734 +CT=4DCA6C75192A01DDCA9476AF2A521E87 + +I=127 +KEY=28292A2B2D2E2F30323334353738393A3C3D3E3F41424344464748494B4C4D4E +PT=C9C8CBCA4447465926272021545B5A59 +CT=058691E627ECBC36AC07B6DB423BD698 + +I=128 +KEY=50515253555657585A5B5C5D5F60616264656667696A6B6C6E6F707173747576 +PT=050407067477767956575051221D1C1F +CT=7444527095838FE080FC2BCDD30847EB + +========== \ No newline at end of file diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_vk.txt b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_vk.txt new file mode 100644 index 00000000..5dfd6008 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_vk.txt @@ -0,0 +1,2334 @@ + +========================= + +FILENAME: "ecb_vk.txt" + +Electronic Codebook (ECB) Mode +Variable Key Known Answer Tests + +Algorithm Name: Rijndael +Principal Submitter: Joan Daemen + +========== + +KEYSIZE=128 + +PT=00000000000000000000000000000000 + +I=1 +KEY=80000000000000000000000000000000 +CT=0EDD33D3C621E546455BD8BA1418BEC8 + +I=2 +KEY=40000000000000000000000000000000 +CT=C0CC0C5DA5BD63ACD44A80774FAD5222 + +I=3 +KEY=20000000000000000000000000000000 +CT=2F0B4B71BC77851B9CA56D42EB8FF080 + +I=4 +KEY=10000000000000000000000000000000 +CT=6B1E2FFFE8A114009D8FE22F6DB5F876 + +I=5 +KEY=08000000000000000000000000000000 +CT=9AA042C315F94CBB97B62202F83358F5 + +I=6 +KEY=04000000000000000000000000000000 +CT=DBE01DE67E346A800C4C4B4880311DE4 + +I=7 +KEY=02000000000000000000000000000000 +CT=C117D2238D53836ACD92DDCDB85D6A21 + +I=8 +KEY=01000000000000000000000000000000 +CT=DC0ED85DF9611ABB7249CDD168C5467E + +I=9 +KEY=00800000000000000000000000000000 +CT=807D678FFF1F56FA92DE3381904842F2 + +I=10 +KEY=00400000000000000000000000000000 +CT=0E53B3FCAD8E4B130EF73AEB957FB402 + +I=11 +KEY=00200000000000000000000000000000 +CT=969FFD3B7C35439417E7BDE923035D65 + +I=12 +KEY=00100000000000000000000000000000 +CT=A99B512C19CA56070491166A1503BF15 + +I=13 +KEY=00080000000000000000000000000000 +CT=6E9985252126EE344D26AE369D2327E3 + +I=14 +KEY=00040000000000000000000000000000 +CT=B85F4809F904C275491FCDCD1610387E + +I=15 +KEY=00020000000000000000000000000000 +CT=ED365B8D7D20C1F5D53FB94DD211DF7B + +I=16 +KEY=00010000000000000000000000000000 +CT=B3A575E86A8DB4A7135D604C43304896 + +I=17 +KEY=00008000000000000000000000000000 +CT=89704BCB8E69F846259EB0ACCBC7F8A2 + +I=18 +KEY=00004000000000000000000000000000 +CT=C56EE7C92197861F10D7A92B90882055 + +I=19 +KEY=00002000000000000000000000000000 +CT=92F296F6846E0EAF9422A5A24A08B069 + +I=20 +KEY=00001000000000000000000000000000 +CT=E67E32BB8F11DEB8699318BEE9E91A60 + +I=21 +KEY=00000800000000000000000000000000 +CT=B08EEF85EAF626DD91B65C4C3A97D92B + +I=22 +KEY=00000400000000000000000000000000 +CT=661083A6ADDCE79BB4E0859AB5538013 + +I=23 +KEY=00000200000000000000000000000000 +CT=55DFE2941E0EB10AFC0B333BD34DE1FE + +I=24 +KEY=00000100000000000000000000000000 +CT=6BFE5945E715C9662609770F8846087A + +I=25 +KEY=00000080000000000000000000000000 +CT=79848E9C30C2F8CDA8B325F7FED2B139 + +I=26 +KEY=00000040000000000000000000000000 +CT=7A713A53B99FEF34AC04DEEF80965BD0 + +I=27 +KEY=00000020000000000000000000000000 +CT=18144A2B46620D32C3C32CE52D49257F + +I=28 +KEY=00000010000000000000000000000000 +CT=872E827C70887C80749F7B8BB1847C7E + +I=29 +KEY=00000008000000000000000000000000 +CT=6B86C6A4FE6A60C59B1A3102F8DE49F3 + +I=30 +KEY=00000004000000000000000000000000 +CT=9848BB3DFDF6F532F094679A4C231A20 + +I=31 +KEY=00000002000000000000000000000000 +CT=925AD528E852E329B2091CD3F1C2BCEE + +I=32 +KEY=00000001000000000000000000000000 +CT=80DF436544B0DD596722E46792A40CD8 + +I=33 +KEY=00000000800000000000000000000000 +CT=525DAF18F93E83E1E74BBBDDE4263BBA + +I=34 +KEY=00000000400000000000000000000000 +CT=F65C9D2EE485D24701FFA3313B9D5BE6 + +I=35 +KEY=00000000200000000000000000000000 +CT=E4FC8D8BCA06425BDF94AFA40FCC14BA + +I=36 +KEY=00000000100000000000000000000000 +CT=A53F0A5CA1E4E6440BB975FF320DE6F8 + +I=37 +KEY=00000000080000000000000000000000 +CT=D55313B9394080462E87E02899B553F0 + +I=38 +KEY=00000000040000000000000000000000 +CT=34A71D761F71BCD344384C7F97D27906 + +I=39 +KEY=00000000020000000000000000000000 +CT=233F3D819599612EBC89580245C996A8 + +I=40 +KEY=00000000010000000000000000000000 +CT=B4F1374E5268DBCB676E447529E53F89 + +I=41 +KEY=00000000008000000000000000000000 +CT=0816BD27861D2BA891D1044E39951E96 + +I=42 +KEY=00000000004000000000000000000000 +CT=F3BE9EA3F10C73CA64FDE5DB13A951D1 + +I=43 +KEY=00000000002000000000000000000000 +CT=2448086A8106FBD03048DDF857D3F1C8 + +I=44 +KEY=00000000001000000000000000000000 +CT=670756E65BEC8B68F03D77CDCDCE7B91 + +I=45 +KEY=00000000000800000000000000000000 +CT=EF968CF0D36FD6C6EFFD225F6FB44CA9 + +I=46 +KEY=00000000000400000000000000000000 +CT=2E8767157922E3826DDCEC1B0CC1E105 + +I=47 +KEY=00000000000200000000000000000000 +CT=78CE7EEC670E45A967BAB17E26A1AD36 + +I=48 +KEY=00000000000100000000000000000000 +CT=3C5CEE825655F098F6E81A2F417DA3FB + +I=49 +KEY=00000000000080000000000000000000 +CT=67BFDB431DCE1292200BC6F5207ADB12 + +I=50 +KEY=00000000000040000000000000000000 +CT=7540FD38E447C0779228548747843A6F + +I=51 +KEY=00000000000020000000000000000000 +CT=B85E513301F8A936EA9EC8A21A85B5E6 + +I=52 +KEY=00000000000010000000000000000000 +CT=04C67DBF16C11427D507A455DE2C9BC5 + +I=53 +KEY=00000000000008000000000000000000 +CT=03F75EB8959E55079CFFB4FF149A37B6 + +I=54 +KEY=00000000000004000000000000000000 +CT=74550287F666C63BB9BC7838433434B0 + +I=55 +KEY=00000000000002000000000000000000 +CT=7D537200195EBC3AEFD1EAAB1C385221 + +I=56 +KEY=00000000000001000000000000000000 +CT=CE24E4D40C68A82B535CBD3C8E21652A + +I=57 +KEY=00000000000000800000000000000000 +CT=AB20072405AA8FC40265C6F1F3DC8BC0 + +I=58 +KEY=00000000000000400000000000000000 +CT=6CFD2CF688F566B093F67B9B3839E80A + +I=59 +KEY=00000000000000200000000000000000 +CT=BD95977E6B7239D407A012C5544BF584 + +I=60 +KEY=00000000000000100000000000000000 +CT=DF9C0130AC77E7C72C997F587B46DBE0 + +I=61 +KEY=00000000000000080000000000000000 +CT=E7F1B82CADC53A648798945B34EFEFF2 + +I=62 +KEY=00000000000000040000000000000000 +CT=932C6DBF69255CF13EDCDB72233ACEA3 + +I=63 +KEY=00000000000000020000000000000000 +CT=5C76002BC7206560EFE550C80B8F12CC + +I=64 +KEY=00000000000000010000000000000000 +CT=F6B7BDD1CAEEBAB574683893C4475484 + +I=65 +KEY=00000000000000008000000000000000 +CT=A920E37CC6DC6B31DA8C0169569F5034 + +I=66 +KEY=00000000000000004000000000000000 +CT=919380ECD9C778BC513148B0C28D65FD + +I=67 +KEY=00000000000000002000000000000000 +CT=EE67308DD3F2D9E6C2170755E5784BE1 + +I=68 +KEY=00000000000000001000000000000000 +CT=3CC73E53B85609023A05E149B223AE09 + +I=69 +KEY=00000000000000000800000000000000 +CT=983E8AF7CF05EBB28D71EB841C9406E6 + +I=70 +KEY=00000000000000000400000000000000 +CT=0F3099B2D31FA5299EE5BF43193287FC + +I=71 +KEY=00000000000000000200000000000000 +CT=B763D84F38C27FE6931DCEB6715D4DB6 + +I=72 +KEY=00000000000000000100000000000000 +CT=5AE3C9B0E3CC29C0C61565CD01F8A248 + +I=73 +KEY=00000000000000000080000000000000 +CT=F58083572CD90981958565D48D2DEE25 + +I=74 +KEY=00000000000000000040000000000000 +CT=7E6255EEF8F70C0EF10337AAB1CCCEF8 + +I=75 +KEY=00000000000000000020000000000000 +CT=AAD4BAC34DB22821841CE2F631961902 + +I=76 +KEY=00000000000000000010000000000000 +CT=D7431C0409BB1441BA9C6858DC7D4E81 + +I=77 +KEY=00000000000000000008000000000000 +CT=EF9298C65E339F6E801A59C626456993 + +I=78 +KEY=00000000000000000004000000000000 +CT=53FE29F68FF541ABC3F0EF3350B72F7E + +I=79 +KEY=00000000000000000002000000000000 +CT=F6BBA5C10DB02529E2C2DA3FB582CC14 + +I=80 +KEY=00000000000000000001000000000000 +CT=E4239AA37FC531A386DAD1126FC0E9CD + +I=81 +KEY=00000000000000000000800000000000 +CT=8F7758F857D15BBE7BFD0E416404C365 + +I=82 +KEY=00000000000000000000400000000000 +CT=D273EB57C687BCD1B4EA7218A509E7B8 + +I=83 +KEY=00000000000000000000200000000000 +CT=65D64F8D76E8B3423FA25C4EB58A210A + +I=84 +KEY=00000000000000000000100000000000 +CT=623D802B4EC450D66A16625702FCDBE0 + +I=85 +KEY=00000000000000000000080000000000 +CT=7496460CB28E5791BAEAF9B68FB00022 + +I=86 +KEY=00000000000000000000040000000000 +CT=34EA600F18BB0694B41681A49D510C1D + +I=87 +KEY=00000000000000000000020000000000 +CT=5F8FF0D47D5766D29B5D6E8F46423BD8 + +I=88 +KEY=00000000000000000000010000000000 +CT=225F9286C5928BF09F84D3F93F541959 + +I=89 +KEY=00000000000000000000008000000000 +CT=B21E90D25DF383416A5F072CEBEB1FFB + +I=90 +KEY=00000000000000000000004000000000 +CT=4AEFCDA089318125453EB9E8EB5E492E + +I=91 +KEY=00000000000000000000002000000000 +CT=4D3E75C6CD40EC4869BC85158591ADB8 + +I=92 +KEY=00000000000000000000001000000000 +CT=63A8B904405436A1B99D7751866771B7 + +I=93 +KEY=00000000000000000000000800000000 +CT=64F0DAAE47529199792EAE172BA53293 + +I=94 +KEY=00000000000000000000000400000000 +CT=C3EEF84BEA18225D515A8C852A9047EE + +I=95 +KEY=00000000000000000000000200000000 +CT=A44AC422B47D47B81AF73B3E9AC9596E + +I=96 +KEY=00000000000000000000000100000000 +CT=D16E04A8FBC435094F8D53ADF25F5084 + +I=97 +KEY=00000000000000000000000080000000 +CT=EF13DC34BAB03E124EEAD8B6BF44B532 + +I=98 +KEY=00000000000000000000000040000000 +CT=D94799075C24DCC067AF0D392049250D + +I=99 +KEY=00000000000000000000000020000000 +CT=14F431771EDDCE4764C21A2254B5E3C8 + +I=100 +KEY=00000000000000000000000010000000 +CT=7039329F36F2ED682B02991F28D64679 + +I=101 +KEY=00000000000000000000000008000000 +CT=124EE24EDE5551639DB8B8B941F6141D + +I=102 +KEY=00000000000000000000000004000000 +CT=C2852879A34D5184E478EC918B993FEE + +I=103 +KEY=00000000000000000000000002000000 +CT=86A806A3525B93E432053C9AB5ABBEDF + +I=104 +KEY=00000000000000000000000001000000 +CT=C1609BF5A4F07E37C17A36366EC23ECC + +I=105 +KEY=00000000000000000000000000800000 +CT=7E81E7CB92159A51FFCEA331B1E8EA53 + +I=106 +KEY=00000000000000000000000000400000 +CT=37A7BE002856C5A59A6E03EAFCE7729A + +I=107 +KEY=00000000000000000000000000200000 +CT=BDF98A5A4F91E890C9A1D1E5FAAB138F + +I=108 +KEY=00000000000000000000000000100000 +CT=4E96ACB66E051F2BC739CC3D3E34A26B + +I=109 +KEY=00000000000000000000000000080000 +CT=EE996CDD120EB86E21ECFA49E8E1FCF1 + +I=110 +KEY=00000000000000000000000000040000 +CT=61B9E6B579DBF6070C351A1440DD85FF + +I=111 +KEY=00000000000000000000000000020000 +CT=AC369E484316440B40DFC83AA96E28E7 + +I=112 +KEY=00000000000000000000000000010000 +CT=0A2D16DE985C76D45C579C1159413BBE + +I=113 +KEY=00000000000000000000000000008000 +CT=DA3FDC38DA1D374FA4802CDA1A1C6B0F + +I=114 +KEY=00000000000000000000000000004000 +CT=B842523D4C41C2211AFE43A5800ADCE3 + +I=115 +KEY=00000000000000000000000000002000 +CT=9E2CDA90D8E992DBA6C73D8229567192 + +I=116 +KEY=00000000000000000000000000001000 +CT=D49583B781D9E20F5BE101415957FC49 + +I=117 +KEY=00000000000000000000000000000800 +CT=EF09DA5C12B376E458B9B8670032498E + +I=118 +KEY=00000000000000000000000000000400 +CT=A96BE0463DA774461A5E1D5A9DD1AC10 + +I=119 +KEY=00000000000000000000000000000200 +CT=32CEE3341060790D2D4B1362EF397090 + +I=120 +KEY=00000000000000000000000000000100 +CT=21CEA416A3D3359D2C4D58FB6A035F06 + +I=121 +KEY=00000000000000000000000000000080 +CT=172AEAB3D507678ECAF455C12587ADB7 + +I=122 +KEY=00000000000000000000000000000040 +CT=B6F897941EF8EBFF9FE80A567EF38478 + +I=123 +KEY=00000000000000000000000000000020 +CT=A9723259D94A7DC662FB0C782CA3F1DD + +I=124 +KEY=00000000000000000000000000000010 +CT=2F91C984B9A4839F30001B9F430493B4 + +I=125 +KEY=00000000000000000000000000000008 +CT=0472406345A610B048CB99EE0EF3FA0F + +I=126 +KEY=00000000000000000000000000000004 +CT=F5F39086646F8C05ED16EFA4B617957C + +I=127 +KEY=00000000000000000000000000000002 +CT=26D50F485A30408D5AF47A5736292450 + +I=128 +KEY=00000000000000000000000000000001 +CT=0545AAD56DA2A97C3663D1432A3D1C84 + +========== + +KEYSIZE=192 + +PT=00000000000000000000000000000000 + +I=1 +KEY=800000000000000000000000000000000000000000000000 +CT=DE885DC87F5A92594082D02CC1E1B42C + +I=2 +KEY=400000000000000000000000000000000000000000000000 +CT=C749194F94673F9DD2AA1932849630C1 + +I=3 +KEY=200000000000000000000000000000000000000000000000 +CT=0CEF643313912934D310297B90F56ECC + +I=4 +KEY=100000000000000000000000000000000000000000000000 +CT=C4495D39D4A553B225FBA02A7B1B87E1 + +I=5 +KEY=080000000000000000000000000000000000000000000000 +CT=636D10B1A0BCAB541D680A7970ADC830 + +I=6 +KEY=040000000000000000000000000000000000000000000000 +CT=07CF045786BD6AFCC147D99E45A901A7 + +I=7 +KEY=020000000000000000000000000000000000000000000000 +CT=6A8E3F425A7599348F95398448827976 + +I=8 +KEY=010000000000000000000000000000000000000000000000 +CT=5518276836148A00D91089A20D8BFF57 + +I=9 +KEY=008000000000000000000000000000000000000000000000 +CT=F267E07B5E87E3BC20B969C61D4FCB06 + +I=10 +KEY=004000000000000000000000000000000000000000000000 +CT=5A1CDE69571D401BFCD20DEBADA2212C + +I=11 +KEY=002000000000000000000000000000000000000000000000 +CT=70A9057263254701D12ADD7D74CD509E + +I=12 +KEY=001000000000000000000000000000000000000000000000 +CT=35713A7E108031279388A33A0FE2E190 + +I=13 +KEY=000800000000000000000000000000000000000000000000 +CT=E74EDE82B1254714F0C7B4B243108655 + +I=14 +KEY=000400000000000000000000000000000000000000000000 +CT=39272E3100FAA37B55B862320D1B3EB3 + +I=15 +KEY=000200000000000000000000000000000000000000000000 +CT=6D6E24C659FC5AEF712F77BCA19C9DD0 + +I=16 +KEY=000100000000000000000000000000000000000000000000 +CT=76D18212F972370D3CC2C6C372C6CF2F + +I=17 +KEY=000080000000000000000000000000000000000000000000 +CT=B21A1F0BAE39E55C7594ED570A7783EA + +I=18 +KEY=000040000000000000000000000000000000000000000000 +CT=77DE202111895AC48DD1C974B358B458 + +I=19 +KEY=000020000000000000000000000000000000000000000000 +CT=67810B311969012AAF7B504FFAF39FD1 + +I=20 +KEY=000010000000000000000000000000000000000000000000 +CT=C22EA2344D3E9417A6BA07843E713AEA + +I=21 +KEY=000008000000000000000000000000000000000000000000 +CT=C79CAF4B97BEE0BD0630AB354539D653 + +I=22 +KEY=000004000000000000000000000000000000000000000000 +CT=135FD1AF761D9AE23DF4AA6B86760DB4 + +I=23 +KEY=000002000000000000000000000000000000000000000000 +CT=D4659D0B06ACD4D56AB8D11A16FD83B9 + +I=24 +KEY=000001000000000000000000000000000000000000000000 +CT=F7D270028FC188E4E4F35A4AAA25D4D4 + +I=25 +KEY=000000800000000000000000000000000000000000000000 +CT=345CAE5A8C9620A9913D5473985852FF + +I=26 +KEY=000000400000000000000000000000000000000000000000 +CT=4E8980ADDE60B0E42C0B287FEA41E729 + +I=27 +KEY=000000200000000000000000000000000000000000000000 +CT=F11B6D74E1F15155633DC39743C1A527 + +I=28 +KEY=000000100000000000000000000000000000000000000000 +CT=9C87916C0180064F9D3179C6F5DD8C35 + +I=29 +KEY=000000080000000000000000000000000000000000000000 +CT=71AB186BCAEA518E461D4F7FAD230E6A + +I=30 +KEY=000000040000000000000000000000000000000000000000 +CT=C4A31BBC3DAAF742F9141C2A5001A49C + +I=31 +KEY=000000020000000000000000000000000000000000000000 +CT=E7C47B7B1D40F182A8928C8A55671D07 + +I=32 +KEY=000000010000000000000000000000000000000000000000 +CT=8E17F294B28FA373C6249538868A7EEF + +I=33 +KEY=000000008000000000000000000000000000000000000000 +CT=754404096A5CBC08AF09491BE249141A + +I=34 +KEY=000000004000000000000000000000000000000000000000 +CT=101CB56E55F05D86369B6D1069204F0A + +I=35 +KEY=000000002000000000000000000000000000000000000000 +CT=73F19BB6604205C6EE227B9759791E41 + +I=36 +KEY=000000001000000000000000000000000000000000000000 +CT=6270C0028F0D136C37A56B2CB64D24D6 + +I=37 +KEY=000000000800000000000000000000000000000000000000 +CT=A3BF7C2C38D1114A087ECF212E694346 + +I=38 +KEY=000000000400000000000000000000000000000000000000 +CT=49CABFF2CEF7D9F95F5EFB1F7A1A7DDE + +I=39 +KEY=000000000200000000000000000000000000000000000000 +CT=EC7F8A47CC59B849469255AD49F62752 + +I=40 +KEY=000000000100000000000000000000000000000000000000 +CT=68FAE55A13EFAF9B07B3552A8A0DC9D1 + +I=41 +KEY=000000000080000000000000000000000000000000000000 +CT=211E6B19C69FAEF481F64F24099CDA65 + +I=42 +KEY=000000000040000000000000000000000000000000000000 +CT=DBB918C75BC5732416F79FB0C8EE4C5C + +I=43 +KEY=000000000020000000000000000000000000000000000000 +CT=98D494E5D963A6C8B92536D3EC35E3FD + +I=44 +KEY=000000000010000000000000000000000000000000000000 +CT=C9A873404D403D6F074190851D67781A + +I=45 +KEY=000000000008000000000000000000000000000000000000 +CT=073AEF4A7C77D921928CB0DD9D27CAE7 + +I=46 +KEY=000000000004000000000000000000000000000000000000 +CT=89BDE25CEE36FDE769A10E52298CF90F + +I=47 +KEY=000000000002000000000000000000000000000000000000 +CT=26D0842D37EAD38557C65E0A5E5F122E + +I=48 +KEY=000000000001000000000000000000000000000000000000 +CT=F8294BA375AF46B3F22905BBAFFAB107 + +I=49 +KEY=000000000000800000000000000000000000000000000000 +CT=2AD63EB4D0D43813B979CF72B35BDB94 + +I=50 +KEY=000000000000400000000000000000000000000000000000 +CT=7710C171EE0F4EFA39BE4C995180181D + +I=51 +KEY=000000000000200000000000000000000000000000000000 +CT=C0CB2B40DBA7BE8C0698FAE1E4B80FF8 + +I=52 +KEY=000000000000100000000000000000000000000000000000 +CT=97970E505194622FD955CA1B80B784E9 + +I=53 +KEY=000000000000080000000000000000000000000000000000 +CT=7CB1824B29F850900DF2CAD9CF04C1CF + +I=54 +KEY=000000000000040000000000000000000000000000000000 +CT=FDF4F036BB988E42F2F62DE63FE19A64 + +I=55 +KEY=000000000000020000000000000000000000000000000000 +CT=08908CFE2C82606B2C15DF61B75CF3E2 + +I=56 +KEY=000000000000010000000000000000000000000000000000 +CT=B3AA689EF2D07FF365ACB9ADBA2AF07A + +I=57 +KEY=000000000000008000000000000000000000000000000000 +CT=F2672CD8EAA3B98776660D0263656F5C + +I=58 +KEY=000000000000004000000000000000000000000000000000 +CT=5BDEAC00E986687B9E1D94A0DA7BF452 + +I=59 +KEY=000000000000002000000000000000000000000000000000 +CT=E6D57BD66EA1627363EE0C4B711B0B21 + +I=60 +KEY=000000000000001000000000000000000000000000000000 +CT=03730DD6ACB4AD9996A63BE7765EC06F + +I=61 +KEY=000000000000000800000000000000000000000000000000 +CT=A470E361AA5437B2BE8586D2F78DE582 + +I=62 +KEY=000000000000000400000000000000000000000000000000 +CT=7567FEEFA559911FD479670246B484E3 + +I=63 +KEY=000000000000000200000000000000000000000000000000 +CT=29829DEA15A4E7A4C049045E7B106E29 + +I=64 +KEY=000000000000000100000000000000000000000000000000 +CT=A407834C3D89D48A2CB7A152208FA4ED + +I=65 +KEY=000000000000000080000000000000000000000000000000 +CT=68F948053F78FEF0D8F9FE7EF3A89819 + +I=66 +KEY=000000000000000040000000000000000000000000000000 +CT=B605174CAB13AD8FE3B20DA3AE7B0234 + +I=67 +KEY=000000000000000020000000000000000000000000000000 +CT=CCAB8F0AEBFF032893996D383CBFDBFA + +I=68 +KEY=000000000000000010000000000000000000000000000000 +CT=AF14BB8428C9730B7DC17B6C1CBEBCC8 + +I=69 +KEY=000000000000000008000000000000000000000000000000 +CT=5A41A21332040877EB7B89E8E80D19FE + +I=70 +KEY=000000000000000004000000000000000000000000000000 +CT=AC1BA52EFCDDE368B1596F2F0AD893A0 + +I=71 +KEY=000000000000000002000000000000000000000000000000 +CT=41B890E31B9045E6ECDC1BC3F2DB9BCC + +I=72 +KEY=000000000000000001000000000000000000000000000000 +CT=4D54A549728E55B19A23660424A0F146 + +I=73 +KEY=000000000000000000800000000000000000000000000000 +CT=A917581F41C47C7DDCFFD5285E2D6A61 + +I=74 +KEY=000000000000000000400000000000000000000000000000 +CT=604DF24BA6099B93A7405A524D764FCB + +I=75 +KEY=000000000000000000200000000000000000000000000000 +CT=78D9D156F28B190E232D1B7AE7FC730A + +I=76 +KEY=000000000000000000100000000000000000000000000000 +CT=5A12C39E442CD7F27B3CD77F5D029582 + +I=77 +KEY=000000000000000000080000000000000000000000000000 +CT=FF2BF2F47CF7B0F28EE25AF95DBF790D + +I=78 +KEY=000000000000000000040000000000000000000000000000 +CT=1863BB7D193BDA39DF090659EB8AE48B + +I=79 +KEY=000000000000000000020000000000000000000000000000 +CT=38178F2FB4CFCF31E87E1ABCDC023EB5 + +I=80 +KEY=000000000000000000010000000000000000000000000000 +CT=F5B13DC690CC0D541C6BA533023DC8C9 + +I=81 +KEY=000000000000000000008000000000000000000000000000 +CT=48EC05238D7375D126DC9D08884D4827 + +I=82 +KEY=000000000000000000004000000000000000000000000000 +CT=ACD0D81139691B310B92A6E377BACC87 + +I=83 +KEY=000000000000000000002000000000000000000000000000 +CT=9A4AA43578B55CE9CC178F0D2E162C79 + +I=84 +KEY=000000000000000000001000000000000000000000000000 +CT=08AD94BC737DB3C87D49B9E01B720D81 + +I=85 +KEY=000000000000000000000800000000000000000000000000 +CT=3BCFB2D5D210E8332900C5991D551A2A + +I=86 +KEY=000000000000000000000400000000000000000000000000 +CT=C5F0C6B9397ACB29635CE1A0DA2D8D96 + +I=87 +KEY=000000000000000000000200000000000000000000000000 +CT=844A29EFC693E2FA9900F87FBF5DCD5F + +I=88 +KEY=000000000000000000000100000000000000000000000000 +CT=5126A1C41051FEA158BE41200E1EA59D + +I=89 +KEY=000000000000000000000080000000000000000000000000 +CT=302123CA7B4F46D667FFFB0EB6AA7703 + +I=90 +KEY=000000000000000000000040000000000000000000000000 +CT=A9D16BCE7DB5C024277709EE2A88D91A + +I=91 +KEY=000000000000000000000020000000000000000000000000 +CT=F013C5EC123A26CFC34B598C992A996B + +I=92 +KEY=000000000000000000000010000000000000000000000000 +CT=E38A825CD971A1D2E56FB1DBA248F2A8 + +I=93 +KEY=000000000000000000000008000000000000000000000000 +CT=6E701773C0311E0BD4C5A097406D22B3 + +I=94 +KEY=000000000000000000000004000000000000000000000000 +CT=754262CEF0C64BE4C3E67C35ABE439F7 + +I=95 +KEY=000000000000000000000002000000000000000000000000 +CT=C9C2D4C47DF7D55CFA0EE5F1FE5070F4 + +I=96 +KEY=000000000000000000000001000000000000000000000000 +CT=6AB4BEA85B172573D8BD2D5F4329F13D + +I=97 +KEY=000000000000000000000000800000000000000000000000 +CT=11F03EF28E2CC9AE5165C587F7396C8C + +I=98 +KEY=000000000000000000000000400000000000000000000000 +CT=0682F2EB1A68BAC7949922C630DD27FA + +I=99 +KEY=000000000000000000000000200000000000000000000000 +CT=ABB0FEC0413D659AFE8E3DCF6BA873BB + +I=100 +KEY=000000000000000000000000100000000000000000000000 +CT=FE86A32E19F805D6569B2EFADD9C92AA + +I=101 +KEY=000000000000000000000000080000000000000000000000 +CT=E434E472275D1837D3D717F2EECC88C3 + +I=102 +KEY=000000000000000000000000040000000000000000000000 +CT=74E57DCD12A21D26EF8ADAFA5E60469A + +I=103 +KEY=000000000000000000000000020000000000000000000000 +CT=C275429D6DAD45DDD423FA63C816A9C1 + +I=104 +KEY=000000000000000000000000010000000000000000000000 +CT=7F6EC1A9AE729E86F7744AED4B8F4F07 + +I=105 +KEY=000000000000000000000000008000000000000000000000 +CT=48B5A71AB9292BD4F9E608EF102636B2 + +I=106 +KEY=000000000000000000000000004000000000000000000000 +CT=076FB95D5F536C78CBED3181BCCF3CF1 + +I=107 +KEY=000000000000000000000000002000000000000000000000 +CT=BFA76BEA1E684FD3BF9256119EE0BC0F + +I=108 +KEY=000000000000000000000000001000000000000000000000 +CT=7D395923D56577F3FF8670998F8C4A71 + +I=109 +KEY=000000000000000000000000000800000000000000000000 +CT=BA02C986E529AC18A882C34BA389625F + +I=110 +KEY=000000000000000000000000000400000000000000000000 +CT=3DFCF2D882AFE75D3A191193013A84B5 + +I=111 +KEY=000000000000000000000000000200000000000000000000 +CT=FAD1FDE1D0241784B63080D2C74D236C + +I=112 +KEY=000000000000000000000000000100000000000000000000 +CT=7D6C80D39E41F007A14FB9CD2B2C15CD + +I=113 +KEY=000000000000000000000000000080000000000000000000 +CT=7975F401FC10637BB33EA2DB058FF6EC + +I=114 +KEY=000000000000000000000000000040000000000000000000 +CT=657983865C55A818F02B7FCD52ED7E99 + +I=115 +KEY=000000000000000000000000000020000000000000000000 +CT=B32BEB1776F9827FF4C3AC9997E84B20 + +I=116 +KEY=000000000000000000000000000010000000000000000000 +CT=2AE2C7C374F0A41E3D46DBC3E66BB59F + +I=117 +KEY=000000000000000000000000000008000000000000000000 +CT=4D835E4ABDD4BDC6B88316A6E931A07F + +I=118 +KEY=000000000000000000000000000004000000000000000000 +CT=E07EFABFF1C353F7384EBB87B435A3F3 + +I=119 +KEY=000000000000000000000000000002000000000000000000 +CT=ED3088DC3FAF89AD87B4356FF1BB09C2 + +I=120 +KEY=000000000000000000000000000001000000000000000000 +CT=4324D01140C156FC898C2E32BA03FB05 + +I=121 +KEY=000000000000000000000000000000800000000000000000 +CT=BE15D016FACB5BAFBC24FA9289132166 + +I=122 +KEY=000000000000000000000000000000400000000000000000 +CT=AC9B7048EDB1ACF4D97A5B0B3F50884B + +I=123 +KEY=000000000000000000000000000000200000000000000000 +CT=448BECE1F86C7845DFA9A4BB2A016FB3 + +I=124 +KEY=000000000000000000000000000000100000000000000000 +CT=10DD445E87686EB46EA9B1ABC49257F0 + +I=125 +KEY=000000000000000000000000000000080000000000000000 +CT=B7FCCF7659FA756D4B7303EEA6C07458 + +I=126 +KEY=000000000000000000000000000000040000000000000000 +CT=289117115CA3513BAA7640B1004872C2 + +I=127 +KEY=000000000000000000000000000000020000000000000000 +CT=57CB42F7EE7186051F50B93FFA7B35BF + +I=128 +KEY=000000000000000000000000000000010000000000000000 +CT=F2741BFBFB81663B9136802FB9C3126A + +I=129 +KEY=000000000000000000000000000000008000000000000000 +CT=E32DDDC5C7398C096E3BD535B31DB5CE + +I=130 +KEY=000000000000000000000000000000004000000000000000 +CT=81D3C204E608AF9CC713EAEBCB72433F + +I=131 +KEY=000000000000000000000000000000002000000000000000 +CT=D4DEEF4BFC36AAA579496E6935F8F98E + +I=132 +KEY=000000000000000000000000000000001000000000000000 +CT=C356DB082B97802B038571C392C5C8F6 + +I=133 +KEY=000000000000000000000000000000000800000000000000 +CT=A3919ECD4861845F2527B77F06AC6A4E + +I=134 +KEY=000000000000000000000000000000000400000000000000 +CT=A53858E17A2F802A20E40D44494FFDA0 + +I=135 +KEY=000000000000000000000000000000000200000000000000 +CT=5D989E122B78C758921EDBEEB827F0C0 + +I=136 +KEY=000000000000000000000000000000000100000000000000 +CT=4B1C0C8F9E7830CC3C4BE7BD226FA8DE + +I=137 +KEY=000000000000000000000000000000000080000000000000 +CT=82C40C5FD897FBCA7B899C70713573A1 + +I=138 +KEY=000000000000000000000000000000000040000000000000 +CT=ED13EE2D45E00F75CCDB51EA8E3E36AD + +I=139 +KEY=000000000000000000000000000000000020000000000000 +CT=F121799EEFE8432423176A3CCF6462BB + +I=140 +KEY=000000000000000000000000000000000010000000000000 +CT=4FA0C06F07997E98271DD86F7B355C50 + +I=141 +KEY=000000000000000000000000000000000008000000000000 +CT=849EB364B4E81D058649DC5B1BF029B9 + +I=142 +KEY=000000000000000000000000000000000004000000000000 +CT=F48F9E0DE8DE7AD944A207809335D9B1 + +I=143 +KEY=000000000000000000000000000000000002000000000000 +CT=E59E9205B5A81A4FD26DFCF308966022 + +I=144 +KEY=000000000000000000000000000000000001000000000000 +CT=3A91A1BE14AAE9ED700BDF9D70018804 + +I=145 +KEY=000000000000000000000000000000000000800000000000 +CT=8ABAD78DCB79A48D79070E7DA89664EC + +I=146 +KEY=000000000000000000000000000000000000400000000000 +CT=B68377D98AAE6044938A7457F6C649D9 + +I=147 +KEY=000000000000000000000000000000000000200000000000 +CT=E4E1275C42F5F1B63D662C099D6CE33D + +I=148 +KEY=000000000000000000000000000000000000100000000000 +CT=7DEF32A34C6BE668F17DA1BB193B06EF + +I=149 +KEY=000000000000000000000000000000000000080000000000 +CT=78B6000CC3D30CB3A74B68D0EDBD2B53 + +I=150 +KEY=000000000000000000000000000000000000040000000000 +CT=0A47531DE88DD8AE5C23EAE4F7D1F2D5 + +I=151 +KEY=000000000000000000000000000000000000020000000000 +CT=667B24E8000CF68231EC484581D922E5 + +I=152 +KEY=000000000000000000000000000000000000010000000000 +CT=39DAA5EBD4AACAE130E9C33236C52024 + +I=153 +KEY=000000000000000000000000000000000000008000000000 +CT=E3C88760B3CB21360668A63E55BB45D1 + +I=154 +KEY=000000000000000000000000000000000000004000000000 +CT=F131EE903C1CDB49D416866FD5D8DE51 + +I=155 +KEY=000000000000000000000000000000000000002000000000 +CT=7A1916135B0447CF4033FC13047A583A + +I=156 +KEY=000000000000000000000000000000000000001000000000 +CT=F7D55FB27991143DCDFA90DDF0424FCB + +I=157 +KEY=000000000000000000000000000000000000000800000000 +CT=EA93E7D1CA1111DBD8F7EC111A848C0C + +I=158 +KEY=000000000000000000000000000000000000000400000000 +CT=2A689E39DFD3CBCBE221326E95888779 + +I=159 +KEY=000000000000000000000000000000000000000200000000 +CT=C1CE399CA762318AC2C40D1928B4C57D + +I=160 +KEY=000000000000000000000000000000000000000100000000 +CT=D43FB6F2B2879C8BFAF0092DA2CA63ED + +I=161 +KEY=000000000000000000000000000000000000000080000000 +CT=224563E617158DF97650AF5D130E78A5 + +I=162 +KEY=000000000000000000000000000000000000000040000000 +CT=6562FDF6833B7C4F7484AE6EBCC243DD + +I=163 +KEY=000000000000000000000000000000000000000020000000 +CT=93D58BA7BED22615D661D002885A7457 + +I=164 +KEY=000000000000000000000000000000000000000010000000 +CT=9A0EF559003AD9E52D3E09ED3C1D3320 + +I=165 +KEY=000000000000000000000000000000000000000008000000 +CT=96BAF5A7DC6F3DD27EB4C717A85D261C + +I=166 +KEY=000000000000000000000000000000000000000004000000 +CT=B8762E06884900E8452293190E19CCDB + +I=167 +KEY=000000000000000000000000000000000000000002000000 +CT=785416A22BD63CBABF4B1789355197D3 + +I=168 +KEY=000000000000000000000000000000000000000001000000 +CT=A0D20CE1489BAA69A3612DCE90F7ABF6 + +I=169 +KEY=000000000000000000000000000000000000000000800000 +CT=700244E93DC94230CC607FFBA0E48F32 + +I=170 +KEY=000000000000000000000000000000000000000000400000 +CT=85329E476829F872A2B4A7E59F91FF2D + +I=171 +KEY=000000000000000000000000000000000000000000200000 +CT=E4219B4935D988DB719B8B8B2B53D247 + +I=172 +KEY=000000000000000000000000000000000000000000100000 +CT=6ACDD04FD13D4DB4409FE8DD13FD737B + +I=173 +KEY=000000000000000000000000000000000000000000080000 +CT=9EB7A670AB59E15BE582378701C1EC14 + +I=174 +KEY=000000000000000000000000000000000000000000040000 +CT=29DF2D6935FE657763BC7A9F22D3D492 + +I=175 +KEY=000000000000000000000000000000000000000000020000 +CT=99303359D4A13AFDBE6C784028CE533A + +I=176 +KEY=000000000000000000000000000000000000000000010000 +CT=FF5C70A6334545F33B9DBF7BEA0417CA + +I=177 +KEY=000000000000000000000000000000000000000000008000 +CT=289F58A17E4C50EDA4269EFB3DF55815 + +I=178 +KEY=000000000000000000000000000000000000000000004000 +CT=EA35DCB416E9E1C2861D1682F062B5EB + +I=179 +KEY=000000000000000000000000000000000000000000002000 +CT=3A47BF354BE775383C50B0C0A83E3A58 + +I=180 +KEY=000000000000000000000000000000000000000000001000 +CT=BF6C1DC069FB95D05D43B01D8206D66B + +I=181 +KEY=000000000000000000000000000000000000000000000800 +CT=046D1D580D5898DA6595F32FD1F0C33D + +I=182 +KEY=000000000000000000000000000000000000000000000400 +CT=5F57803B7B82A110F7E9855D6A546082 + +I=183 +KEY=000000000000000000000000000000000000000000000200 +CT=25336ECF34E7BE97862CDFF715FF05A8 + +I=184 +KEY=000000000000000000000000000000000000000000000100 +CT=ACBAA2A943D8078022D693890E8C4FEF + +I=185 +KEY=000000000000000000000000000000000000000000000080 +CT=3947597879F6B58E4E2F0DF825A83A38 + +I=186 +KEY=000000000000000000000000000000000000000000000040 +CT=4EB8CC3335496130655BF3CA570A4FC0 + +I=187 +KEY=000000000000000000000000000000000000000000000020 +CT=BBDA7769AD1FDA425E18332D97868824 + +I=188 +KEY=000000000000000000000000000000000000000000000010 +CT=5E7532D22DDB0829A29C868198397154 + +I=189 +KEY=000000000000000000000000000000000000000000000008 +CT=E66DA67B630AB7AE3E682855E1A1698E + +I=190 +KEY=000000000000000000000000000000000000000000000004 +CT=4D93800F671B48559A64D1EA030A590A + +I=191 +KEY=000000000000000000000000000000000000000000000002 +CT=F33159FCC7D9AE30C062CD3B322AC764 + +I=192 +KEY=000000000000000000000000000000000000000000000001 +CT=8BAE4EFB70D33A9792EEA9BE70889D72 + +========== + +KEYSIZE=256 + +PT=00000000000000000000000000000000 + +I=1 +KEY=8000000000000000000000000000000000000000000000000000000000000000 +CT=E35A6DCB19B201A01EBCFA8AA22B5759 + +I=2 +KEY=4000000000000000000000000000000000000000000000000000000000000000 +CT=5075C2405B76F22F553488CAE47CE90B + +I=3 +KEY=2000000000000000000000000000000000000000000000000000000000000000 +CT=49DF95D844A0145A7DE01C91793302D3 + +I=4 +KEY=1000000000000000000000000000000000000000000000000000000000000000 +CT=E7396D778E940B8418A86120E5F421FE + +I=5 +KEY=0800000000000000000000000000000000000000000000000000000000000000 +CT=05F535C36FCEDE4657BE37F4087DB1EF + +I=6 +KEY=0400000000000000000000000000000000000000000000000000000000000000 +CT=D0C1DDDD10DA777C68AB36AF51F2C204 + +I=7 +KEY=0200000000000000000000000000000000000000000000000000000000000000 +CT=1C55FB811B5C6464C4E5DE1535A75514 + +I=8 +KEY=0100000000000000000000000000000000000000000000000000000000000000 +CT=52917F3AE957D5230D3A2AF57C7B5A71 + +I=9 +KEY=0080000000000000000000000000000000000000000000000000000000000000 +CT=C6E3D5501752DD5E9AEF086D6B45D705 + +I=10 +KEY=0040000000000000000000000000000000000000000000000000000000000000 +CT=A24A9C7AF1D9B1E17E1C9A3E711B3FA7 + +I=11 +KEY=0020000000000000000000000000000000000000000000000000000000000000 +CT=B881ECA724A6D43DBC6B96F6F59A0D20 + +I=12 +KEY=0010000000000000000000000000000000000000000000000000000000000000 +CT=EC524D9A24DFFF2A9639879B83B8E137 + +I=13 +KEY=0008000000000000000000000000000000000000000000000000000000000000 +CT=34C4F345F5466215A037F443635D6F75 + +I=14 +KEY=0004000000000000000000000000000000000000000000000000000000000000 +CT=5BA5055BEDB8895F672E29F2EB5A355D + +I=15 +KEY=0002000000000000000000000000000000000000000000000000000000000000 +CT=B3F692AA3A435259EBBEF9B51AD1E08D + +I=16 +KEY=0001000000000000000000000000000000000000000000000000000000000000 +CT=414FEB4376F2C64A5D2FBB2ED531BA7D + +I=17 +KEY=0000800000000000000000000000000000000000000000000000000000000000 +CT=A20D519E3BCA3303F07E81719F61605E + +I=18 +KEY=0000400000000000000000000000000000000000000000000000000000000000 +CT=A08D10E520AF811F45BD60A2DC0DC4B1 + +I=19 +KEY=0000200000000000000000000000000000000000000000000000000000000000 +CT=B06893A8C563C430E6F3858826EFBBE4 + +I=20 +KEY=0000100000000000000000000000000000000000000000000000000000000000 +CT=0FFEE26AE2D3929C6BD9C6BEDFF84409 + +I=21 +KEY=0000080000000000000000000000000000000000000000000000000000000000 +CT=4D0F5E906ED77801FC0EF53EDC5F9E2B + +I=22 +KEY=0000040000000000000000000000000000000000000000000000000000000000 +CT=8B6EC00119AD8B026DCE56EA7DEFE930 + +I=23 +KEY=0000020000000000000000000000000000000000000000000000000000000000 +CT=69026591D43363EE9D83B5007F0B484E + +I=24 +KEY=0000010000000000000000000000000000000000000000000000000000000000 +CT=27135D86950C6A2F86872706279A4761 + +I=25 +KEY=0000008000000000000000000000000000000000000000000000000000000000 +CT=35E6DB8723F281DA410C3AC8535ED77C + +I=26 +KEY=0000004000000000000000000000000000000000000000000000000000000000 +CT=57427CF214B8C28E4BBF487CCB8D0E09 + +I=27 +KEY=0000002000000000000000000000000000000000000000000000000000000000 +CT=6DF01BF56E5131AC87F96E99CAB86367 + +I=28 +KEY=0000001000000000000000000000000000000000000000000000000000000000 +CT=3856C5B55790B768BBF7D43031579BCF + +I=29 +KEY=0000000800000000000000000000000000000000000000000000000000000000 +CT=1E6ED8FB7C15BC4D2F63BA7037ED44D0 + +I=30 +KEY=0000000400000000000000000000000000000000000000000000000000000000 +CT=E1B2ED6CD8D93D455534E401156D4BCF + +I=31 +KEY=0000000200000000000000000000000000000000000000000000000000000000 +CT=EFBCCA5BDFDAD10E875F02336212CE36 + +I=32 +KEY=0000000100000000000000000000000000000000000000000000000000000000 +CT=0B777F02FD18DCE2646DCFE868DFAFAD + +I=33 +KEY=0000000080000000000000000000000000000000000000000000000000000000 +CT=C8A104B5693D1B14F5BF1F10100BF508 + +I=34 +KEY=0000000040000000000000000000000000000000000000000000000000000000 +CT=4CCE6615244AFCB38408FECE219962EA + +I=35 +KEY=0000000020000000000000000000000000000000000000000000000000000000 +CT=F99E7845D3A255B394C9C050CBA258B1 + +I=36 +KEY=0000000010000000000000000000000000000000000000000000000000000000 +CT=B4AFBB787F9BCFB7B55FDF447F611295 + +I=37 +KEY=0000000008000000000000000000000000000000000000000000000000000000 +CT=AE1C426A697FAF2808B7EF6ADDB5C020 + +I=38 +KEY=0000000004000000000000000000000000000000000000000000000000000000 +CT=7572F92811A85B9BDD38DEAD9945BCAE + +I=39 +KEY=0000000002000000000000000000000000000000000000000000000000000000 +CT=71BC7AA46E43FB95A181527D9F6A360F + +I=40 +KEY=0000000001000000000000000000000000000000000000000000000000000000 +CT=5542EF2923066F1EC8F546DD0D8E7CA8 + +I=41 +KEY=0000000000800000000000000000000000000000000000000000000000000000 +CT=6B92317C7D623790B748FDD7EFC42422 + +I=42 +KEY=0000000000400000000000000000000000000000000000000000000000000000 +CT=0FE7C097E899C71EF045360F8D6C25CF + +I=43 +KEY=0000000000200000000000000000000000000000000000000000000000000000 +CT=4ECE7EE107D0264D04693151C25B9DF6 + +I=44 +KEY=0000000000100000000000000000000000000000000000000000000000000000 +CT=FD6AE687CBFCA9E301045888D3BB9605 + +I=45 +KEY=0000000000080000000000000000000000000000000000000000000000000000 +CT=476B579C8556C7254424902CC1D6D36E + +I=46 +KEY=0000000000040000000000000000000000000000000000000000000000000000 +CT=4133CBCDFDD6B8860A1FC18665D6D71B + +I=47 +KEY=0000000000020000000000000000000000000000000000000000000000000000 +CT=3B36EC2664798C108B816812C65DFDC7 + +I=48 +KEY=0000000000010000000000000000000000000000000000000000000000000000 +CT=364E20A234FEA385D48DC5A09C9E70CF + +I=49 +KEY=0000000000008000000000000000000000000000000000000000000000000000 +CT=4A4BA25969DE3F5EE5642C71AAD0EFD1 + +I=50 +KEY=0000000000004000000000000000000000000000000000000000000000000000 +CT=E42CBAAE43297F67A76C1C501BB79E36 + +I=51 +KEY=0000000000002000000000000000000000000000000000000000000000000000 +CT=23CEDEDA4C15B4C037E8C61492217937 + +I=52 +KEY=0000000000001000000000000000000000000000000000000000000000000000 +CT=A1719147A1F4A1A1180BD16E8593DCDE + +I=53 +KEY=0000000000000800000000000000000000000000000000000000000000000000 +CT=AB82337E9FB0EC60D1F25A1D0014192C + +I=54 +KEY=0000000000000400000000000000000000000000000000000000000000000000 +CT=74BF2D8FC5A8388DF1A3A4D7D33FC164 + +I=55 +KEY=0000000000000200000000000000000000000000000000000000000000000000 +CT=D5B493317E6FBC6FFFD664B3C491368A + +I=56 +KEY=0000000000000100000000000000000000000000000000000000000000000000 +CT=BA767381586DA56A2A8D503D5F7ADA0B + +I=57 +KEY=0000000000000080000000000000000000000000000000000000000000000000 +CT=E8E6BC57DFE9CCADB0DECABF4E5CF91F + +I=58 +KEY=0000000000000040000000000000000000000000000000000000000000000000 +CT=3C8E5A5CDC9CEED90815D1F84BB2998C + +I=59 +KEY=0000000000000020000000000000000000000000000000000000000000000000 +CT=283843020BA38F056001B2FD585F7CC9 + +I=60 +KEY=0000000000000010000000000000000000000000000000000000000000000000 +CT=D8ADC7426F623ECE8741A70621D28870 + +I=61 +KEY=0000000000000008000000000000000000000000000000000000000000000000 +CT=D7C5C215592D06F00E6A80DA69A28EA9 + +I=62 +KEY=0000000000000004000000000000000000000000000000000000000000000000 +CT=52CF6FA433C3C870CAC70190358F7F16 + +I=63 +KEY=0000000000000002000000000000000000000000000000000000000000000000 +CT=F63D442A584DA71786ADEC9F3346DF75 + +I=64 +KEY=0000000000000001000000000000000000000000000000000000000000000000 +CT=549078F4B0CA7079B45F9A5ADAFAFD99 + +I=65 +KEY=0000000000000000800000000000000000000000000000000000000000000000 +CT=F2A5986EE4E9984BE2BAFB79EA8152FA + +I=66 +KEY=0000000000000000400000000000000000000000000000000000000000000000 +CT=8A74535017B4DB2776668A1FAE64384C + +I=67 +KEY=0000000000000000200000000000000000000000000000000000000000000000 +CT=E613342F57A97FD95DC088711A5D0ECD + +I=68 +KEY=0000000000000000100000000000000000000000000000000000000000000000 +CT=3FFAEBF6B22CF1DC82AE17CD48175B01 + +I=69 +KEY=0000000000000000080000000000000000000000000000000000000000000000 +CT=BAFD52EFA15C248CCBF9757735E6B1CE + +I=70 +KEY=0000000000000000040000000000000000000000000000000000000000000000 +CT=7AF94BC018D9DDD4539D2DD1C6F4000F + +I=71 +KEY=0000000000000000020000000000000000000000000000000000000000000000 +CT=FE177AD61CA0FDB281086FBA8FE76803 + +I=72 +KEY=0000000000000000010000000000000000000000000000000000000000000000 +CT=74DBEA15E2E9285BAD163D7D534251B6 + +I=73 +KEY=0000000000000000008000000000000000000000000000000000000000000000 +CT=23DD21331B3A92F200FE56FF050FFE74 + +I=74 +KEY=0000000000000000004000000000000000000000000000000000000000000000 +CT=A69C5AA34AB20A858CAFA766EACED6D8 + +I=75 +KEY=0000000000000000002000000000000000000000000000000000000000000000 +CT=3F72BB4DF2A4F941A4A09CB78F04B97A + +I=76 +KEY=0000000000000000001000000000000000000000000000000000000000000000 +CT=72CC43577E1FD5FD14622D24D97FCDCC + +I=77 +KEY=0000000000000000000800000000000000000000000000000000000000000000 +CT=D83AF8EBE93E0B6B99CAFADE224937D1 + +I=78 +KEY=0000000000000000000400000000000000000000000000000000000000000000 +CT=44042329128D56CAA8D084C8BD769D1E + +I=79 +KEY=0000000000000000000200000000000000000000000000000000000000000000 +CT=14102D72290DE4F2C430ADD1ED64BA1D + +I=80 +KEY=0000000000000000000100000000000000000000000000000000000000000000 +CT=449124097B1ECD0AE7065206DF06F03C + +I=81 +KEY=0000000000000000000080000000000000000000000000000000000000000000 +CT=D060A99F8CC153A42E11E5F97BD7584A + +I=82 +KEY=0000000000000000000040000000000000000000000000000000000000000000 +CT=65605B3EA9261488D53E48602ADEA299 + +I=83 +KEY=0000000000000000000020000000000000000000000000000000000000000000 +CT=C5E5CAD7A208DE8EA6BE049EFE5C7346 + +I=84 +KEY=0000000000000000000010000000000000000000000000000000000000000000 +CT=4C280C46D2181646048DD5BC0C0831A5 + +I=85 +KEY=0000000000000000000008000000000000000000000000000000000000000000 +CT=5DD65CF37F2A0929559AABAFDA08E730 + +I=86 +KEY=0000000000000000000004000000000000000000000000000000000000000000 +CT=31F2335CAAF264172F69A693225E6D22 + +I=87 +KEY=0000000000000000000002000000000000000000000000000000000000000000 +CT=3E28B35F99A72662590DA96426DD377F + +I=88 +KEY=0000000000000000000001000000000000000000000000000000000000000000 +CT=570F40F5D7B20441486578ED344343BE + +I=89 +KEY=0000000000000000000000800000000000000000000000000000000000000000 +CT=C54308AD1C9E3B19F8B7417873045A8C + +I=90 +KEY=0000000000000000000000400000000000000000000000000000000000000000 +CT=CBF335E39CE13ADE2B696179E8FD0CE1 + +I=91 +KEY=0000000000000000000000200000000000000000000000000000000000000000 +CT=9C2FBF422355D8293083D51F4A3C18A9 + +I=92 +KEY=0000000000000000000000100000000000000000000000000000000000000000 +CT=5ED8B5A31ECEFAB16C9AA6986DA67BCE + +I=93 +KEY=0000000000000000000000080000000000000000000000000000000000000000 +CT=627815DCFC814ABC75900041B1DD7B59 + +I=94 +KEY=0000000000000000000000040000000000000000000000000000000000000000 +CT=9EF3E82A50A59F166260494F7A7F2CC3 + +I=95 +KEY=0000000000000000000000020000000000000000000000000000000000000000 +CT=878CD0D8D920888B5935D6C351128737 + +I=96 +KEY=0000000000000000000000010000000000000000000000000000000000000000 +CT=E44429474D6FC3084EB2A6B8B46AF754 + +I=97 +KEY=0000000000000000000000008000000000000000000000000000000000000000 +CT=EBAACF9641D54E1FB18D0A2BE4F19BE5 + +I=98 +KEY=0000000000000000000000004000000000000000000000000000000000000000 +CT=13B3BF497CEE780E123C7E193DEA3A01 + +I=99 +KEY=0000000000000000000000002000000000000000000000000000000000000000 +CT=6E8F381DE00A41161F0DF03B4155BFD4 + +I=100 +KEY=0000000000000000000000001000000000000000000000000000000000000000 +CT=35E4F29BBA2BAE01144910783C3FEF49 + +I=101 +KEY=0000000000000000000000000800000000000000000000000000000000000000 +CT=55B17BD66788CEAC366398A31F289FFB + +I=102 +KEY=0000000000000000000000000400000000000000000000000000000000000000 +CT=11341F56C0D6D1008D28741DAA7679CE + +I=103 +KEY=0000000000000000000000000200000000000000000000000000000000000000 +CT=4DF7253DF421D83358BDBE924745D98C + +I=104 +KEY=0000000000000000000000000100000000000000000000000000000000000000 +CT=BAE2EE651116D93EDC8E83B5F3347BE1 + +I=105 +KEY=0000000000000000000000000080000000000000000000000000000000000000 +CT=F9721ABD06709157183AF3965A659D9D + +I=106 +KEY=0000000000000000000000000040000000000000000000000000000000000000 +CT=19A1C252A613FE2860A4AE6D75CE6FA3 + +I=107 +KEY=0000000000000000000000000020000000000000000000000000000000000000 +CT=B5DDB2F5D9752C949FBDE3FFF5556C6E + +I=108 +KEY=0000000000000000000000000010000000000000000000000000000000000000 +CT=81B044FCFFC78ECCFCD171AAD0405C66 + +I=109 +KEY=0000000000000000000000000008000000000000000000000000000000000000 +CT=C640566D3C06020EB2C42F1D62E56A9B + +I=110 +KEY=0000000000000000000000000004000000000000000000000000000000000000 +CT=EA6C4BCF425291679FDFFD26A424FBCC + +I=111 +KEY=0000000000000000000000000002000000000000000000000000000000000000 +CT=57F6901465D9440D9F15EE2CBA5A4090 + +I=112 +KEY=0000000000000000000000000001000000000000000000000000000000000000 +CT=FBCFA74CADC7406260F63D96C8AAB6B1 + +I=113 +KEY=0000000000000000000000000000800000000000000000000000000000000000 +CT=DFF4F096CEA211D4BBDACA033D0EC7D1 + +I=114 +KEY=0000000000000000000000000000400000000000000000000000000000000000 +CT=1EE5190D551F0F42F675227A381296A9 + +I=115 +KEY=0000000000000000000000000000200000000000000000000000000000000000 +CT=F98E1905012E580F097623C10B93054F + +I=116 +KEY=0000000000000000000000000000100000000000000000000000000000000000 +CT=E7D43743D21DD3C9F168C86856558B9A + +I=117 +KEY=0000000000000000000000000000080000000000000000000000000000000000 +CT=632A9DDA730DAB67593C5D08D8AC1059 + +I=118 +KEY=0000000000000000000000000000040000000000000000000000000000000000 +CT=E084317000715B9057BC9DE9F3AB6124 + +I=119 +KEY=0000000000000000000000000000020000000000000000000000000000000000 +CT=61F9EF33A0BB4E666C2ED99101919FAB + +I=120 +KEY=0000000000000000000000000000010000000000000000000000000000000000 +CT=6DC1D68A11834657D46703C22578D59A + +I=121 +KEY=0000000000000000000000000000008000000000000000000000000000000000 +CT=53AC1548863D3D16F1D4DC7242E05F2C + +I=122 +KEY=0000000000000000000000000000004000000000000000000000000000000000 +CT=E82CD587A408306AD78CEAE0916B9F8C + +I=123 +KEY=0000000000000000000000000000002000000000000000000000000000000000 +CT=0FD2D40EA6AD17A3A767F0A8600D6295 + +I=124 +KEY=0000000000000000000000000000001000000000000000000000000000000000 +CT=AD84CC8255ADB39DFCA23F92761AE7E9 + +I=125 +KEY=0000000000000000000000000000000800000000000000000000000000000000 +CT=F4F20CF7D51BEE7DA024A2B11A7ECA0B + +I=126 +KEY=0000000000000000000000000000000400000000000000000000000000000000 +CT=5057691B85D9CE93A193214DB0A016B6 + +I=127 +KEY=0000000000000000000000000000000200000000000000000000000000000000 +CT=0F58C960876390BDEF4BB6BE95CAA1EE + +I=128 +KEY=0000000000000000000000000000000100000000000000000000000000000000 +CT=9A3E66EEBC21BC0BD9430B341EF465FA + +I=129 +KEY=0000000000000000000000000000000080000000000000000000000000000000 +CT=20415035F34B8BCBCB28ABF07F78F0D4 + +I=130 +KEY=0000000000000000000000000000000040000000000000000000000000000000 +CT=AC89FC7BA10479EBF10DE65BCEF89B3C + +I=131 +KEY=0000000000000000000000000000000020000000000000000000000000000000 +CT=068FA75A30BE443171AF3F6FEB1A20D2 + +I=132 +KEY=0000000000000000000000000000000010000000000000000000000000000000 +CT=50E02F213246C525A8C27700CA34B502 + +I=133 +KEY=0000000000000000000000000000000008000000000000000000000000000000 +CT=227DA47D5A0906DB3AB042BB0A695FB6 + +I=134 +KEY=0000000000000000000000000000000004000000000000000000000000000000 +CT=8663AC30ED12514F1DE46777F4514BFC + +I=135 +KEY=0000000000000000000000000000000002000000000000000000000000000000 +CT=A987D4BC12E1DE9F4B6DF43567C34A8B + +I=136 +KEY=0000000000000000000000000000000001000000000000000000000000000000 +CT=6D5A0370F599ACA605F63B04E5143D0C + +I=137 +KEY=0000000000000000000000000000000000800000000000000000000000000000 +CT=9809266E378B07B7AFDB3BAA97B7E442 + +I=138 +KEY=0000000000000000000000000000000000400000000000000000000000000000 +CT=8F753252B30CCCACE12D9A301F4D5090 + +I=139 +KEY=0000000000000000000000000000000000200000000000000000000000000000 +CT=032465F6C0CE34D41962F561692A1AFF + +I=140 +KEY=0000000000000000000000000000000000100000000000000000000000000000 +CT=C50E9AD5BEB8F3B00821DD47FF8AC093 + +I=141 +KEY=0000000000000000000000000000000000080000000000000000000000000000 +CT=9C6FEA3D46268D54A6829B2AD25BB276 + +I=142 +KEY=0000000000000000000000000000000000040000000000000000000000000000 +CT=0FD8575E87706F561343D7B3A41E044A + +I=143 +KEY=0000000000000000000000000000000000020000000000000000000000000000 +CT=BEE9BEB3739540D88CBCE77925F0A114 + +I=144 +KEY=0000000000000000000000000000000000010000000000000000000000000000 +CT=D24EAEE7FFFBAC3D6F26C2DCE0DCDE28 + +I=145 +KEY=0000000000000000000000000000000000008000000000000000000000000000 +CT=47771A90398FF0F7FA821C2F8F5E1398 + +I=146 +KEY=0000000000000000000000000000000000004000000000000000000000000000 +CT=4639741B6F84B135AD118C8249B64ED0 + +I=147 +KEY=0000000000000000000000000000000000002000000000000000000000000000 +CT=8EE5505EC85567697A3306F250A27720 + +I=148 +KEY=0000000000000000000000000000000000001000000000000000000000000000 +CT=7C8A19AC1AEFBC5E0119D91A5F05D4C2 + +I=149 +KEY=0000000000000000000000000000000000000800000000000000000000000000 +CT=5141B9B672E54773B672E3A6C424887B + +I=150 +KEY=0000000000000000000000000000000000000400000000000000000000000000 +CT=B5A2D3CD206653C6402F34FB0AE3613D + +I=151 +KEY=0000000000000000000000000000000000000200000000000000000000000000 +CT=0F5BD9408738231D114B0A82753279A3 + +I=152 +KEY=0000000000000000000000000000000000000100000000000000000000000000 +CT=FEF033FF4268EA487FC74C5E43A45338 + +I=153 +KEY=0000000000000000000000000000000000000080000000000000000000000000 +CT=A3EDC09DCD529B113910D904AD855581 + +I=154 +KEY=0000000000000000000000000000000000000040000000000000000000000000 +CT=AB8FBB6F27A0AC7C55B59FDD36B72F1C + +I=155 +KEY=0000000000000000000000000000000000000020000000000000000000000000 +CT=EEA44D5ED4D769CC930CD83D8999EC46 + +I=156 +KEY=0000000000000000000000000000000000000010000000000000000000000000 +CT=6972276803AE9AA7C6F431AB10979C34 + +I=157 +KEY=0000000000000000000000000000000000000008000000000000000000000000 +CT=86DEAA9F39244101818178474D7DBDE9 + +I=158 +KEY=0000000000000000000000000000000000000004000000000000000000000000 +CT=88C6B466EA361D662D8D08CBF181F4FE + +I=159 +KEY=0000000000000000000000000000000000000002000000000000000000000000 +CT=91AB2C6B7C63FF59F7CBEEBF91B20B95 + +I=160 +KEY=0000000000000000000000000000000000000001000000000000000000000000 +CT=2DFE6C146AD5B3D8C3C1718F13B48E01 + +I=161 +KEY=0000000000000000000000000000000000000000800000000000000000000000 +CT=C7CFF1623451711391A302EEC3584AAA + +I=162 +KEY=0000000000000000000000000000000000000000400000000000000000000000 +CT=089FE845CC05011686C66019D18BE050 + +I=163 +KEY=0000000000000000000000000000000000000000200000000000000000000000 +CT=08C8410B9B427211A67124B0DCCEAD48 + +I=164 +KEY=0000000000000000000000000000000000000000100000000000000000000000 +CT=8D91592F5566085254784606334D7629 + +I=165 +KEY=0000000000000000000000000000000000000000080000000000000000000000 +CT=3298FEAAF2E1201D6299FF8846639C97 + +I=166 +KEY=0000000000000000000000000000000000000000040000000000000000000000 +CT=C497CB9F0BDFE0EFC8C2F3F90760AA72 + +I=167 +KEY=0000000000000000000000000000000000000000020000000000000000000000 +CT=2788AFD046E0309CBE4424690DA2AB89 + +I=168 +KEY=0000000000000000000000000000000000000000010000000000000000000000 +CT=E9891707F25EF29FEE372890D4258982 + +I=169 +KEY=0000000000000000000000000000000000000000008000000000000000000000 +CT=DB041D94A23D45D4D4DCED5A030CAF61 + +I=170 +KEY=0000000000000000000000000000000000000000004000000000000000000000 +CT=FFAFDBF0ECB18DF9EA02C27077448E6D + +I=171 +KEY=0000000000000000000000000000000000000000002000000000000000000000 +CT=2DAAA42A7D0A1D3B0E4761D99CF2150A + +I=172 +KEY=0000000000000000000000000000000000000000001000000000000000000000 +CT=3B7A54CB7CF30ABE263DD6ED5BFE8D63 + +I=173 +KEY=0000000000000000000000000000000000000000000800000000000000000000 +CT=EEFA090174C590C448A55D43648F534A + +I=174 +KEY=0000000000000000000000000000000000000000000400000000000000000000 +CT=9E15798731ED42F43EA2740A691DA872 + +I=175 +KEY=0000000000000000000000000000000000000000000200000000000000000000 +CT=31FBD661540A5DEAAD1017CFD3909EC8 + +I=176 +KEY=0000000000000000000000000000000000000000000100000000000000000000 +CT=CDA9AE05F224140E28CB951721B44D6A + +I=177 +KEY=0000000000000000000000000000000000000000000080000000000000000000 +CT=0C5BC512C60A1EAC3434EFB1A8FBB182 + +I=178 +KEY=0000000000000000000000000000000000000000000040000000000000000000 +CT=AA863610DEEEEB62D045E87EA30B59B5 + +I=179 +KEY=0000000000000000000000000000000000000000000020000000000000000000 +CT=6AC2448DE568D279C7EEBE1DF403920C + +I=180 +KEY=0000000000000000000000000000000000000000000010000000000000000000 +CT=E2011E3D292B26888AE801215FD0CB40 + +I=181 +KEY=0000000000000000000000000000000000000000000008000000000000000000 +CT=E06F3E15EE3A61672D1C99BADE5B9DBE + +I=182 +KEY=0000000000000000000000000000000000000000000004000000000000000000 +CT=BB7027F0548CF6712CEB4C7A4B28E178 + +I=183 +KEY=0000000000000000000000000000000000000000000002000000000000000000 +CT=061EC21FB70FADBDF87C3BD2AE23825B + +I=184 +KEY=0000000000000000000000000000000000000000000001000000000000000000 +CT=4C21F26FE94ABBAC381352375314C3EB + +I=185 +KEY=0000000000000000000000000000000000000000000000800000000000000000 +CT=F7CEE6DD99909C2B569EEDA61ED8942E + +I=186 +KEY=0000000000000000000000000000000000000000000000400000000000000000 +CT=CE98C4A876C65E4CCB261EBB1D9DF7F5 + +I=187 +KEY=0000000000000000000000000000000000000000000000200000000000000000 +CT=A5491881CF833C3604ABC08044F402AC + +I=188 +KEY=0000000000000000000000000000000000000000000000100000000000000000 +CT=A1BA16E64CCCB3087D57A768507B0BFC + +I=189 +KEY=0000000000000000000000000000000000000000000000080000000000000000 +CT=D55951E202D2949EBD3BE43120C738BF + +I=190 +KEY=0000000000000000000000000000000000000000000000040000000000000000 +CT=EBB8E43069E69F450EFEC65DCD52B7FD + +I=191 +KEY=0000000000000000000000000000000000000000000000020000000000000000 +CT=2B292135663B4AA5ABFE9423D57E7EE9 + +I=192 +KEY=0000000000000000000000000000000000000000000000010000000000000000 +CT=E91BF974B3BE3AD966249D8655292A85 + +I=193 +KEY=0000000000000000000000000000000000000000000000008000000000000000 +CT=384365998EAA9562236CC58F6ADF9610 + +I=194 +KEY=0000000000000000000000000000000000000000000000004000000000000000 +CT=C2E997012AA3D4D8D359C9A947CBE69F + +I=195 +KEY=0000000000000000000000000000000000000000000000002000000000000000 +CT=F49421204148BA213BE87E2D5C22B0BF + +I=196 +KEY=0000000000000000000000000000000000000000000000001000000000000000 +CT=82ED0ED9953AA92E4DF30929CA65C00F + +I=197 +KEY=0000000000000000000000000000000000000000000000000800000000000000 +CT=291EB1D11653C8479437C74A977F5106 + +I=198 +KEY=0000000000000000000000000000000000000000000000000400000000000000 +CT=BCB997B1939B8983ABD550D6025683E3 + +I=199 +KEY=0000000000000000000000000000000000000000000000000200000000000000 +CT=1FBA2592C6F489775CAADA71F9B983E9 + +I=200 +KEY=0000000000000000000000000000000000000000000000000100000000000000 +CT=969F66F217AF1A3DB9E41C1B29039824 + +I=201 +KEY=0000000000000000000000000000000000000000000000000080000000000000 +CT=A54BB7D6B17E423AC0A7744C19073CB8 + +I=202 +KEY=0000000000000000000000000000000000000000000000000040000000000000 +CT=B0AC6E6578D1021F47DCF9748A32EAD5 + +I=203 +KEY=0000000000000000000000000000000000000000000000000020000000000000 +CT=B87B361C3B7B194C77A4358D4669153E + +I=204 +KEY=0000000000000000000000000000000000000000000000000010000000000000 +CT=46A133847F96EAA8282A799DC8899D58 + +I=205 +KEY=0000000000000000000000000000000000000000000000000008000000000000 +CT=2265EC3A9F2D5C9547A091CC8CFB18EA + +I=206 +KEY=0000000000000000000000000000000000000000000000000004000000000000 +CT=54CBF3A6FC4FE56D426117AA1FFD1DDE + +I=207 +KEY=0000000000000000000000000000000000000000000000000002000000000000 +CT=5312877CCEAB6CFB0905394A370A8003 + +I=208 +KEY=0000000000000000000000000000000000000000000000000001000000000000 +CT=7190BD6EC613FE38B84ECFE28F702FE4 + +I=209 +KEY=0000000000000000000000000000000000000000000000000000800000000000 +CT=D1FA5B9CA89A43B04C05F0EF29EF68CD + +I=210 +KEY=0000000000000000000000000000000000000000000000000000400000000000 +CT=808285751548ED934FD1056D2D9AE8BA + +I=211 +KEY=0000000000000000000000000000000000000000000000000000200000000000 +CT=2758DEF3E7B95A9AE89777BE64D5A6CF + +I=212 +KEY=0000000000000000000000000000000000000000000000000000100000000000 +CT=07D81F87DB3E0ACC82B01E08FB22F3C1 + +I=213 +KEY=0000000000000000000000000000000000000000000000000000080000000000 +CT=8DA250E5553D650711A75EE1CB4FD1C7 + +I=214 +KEY=0000000000000000000000000000000000000000000000000000040000000000 +CT=A93D946BD0E87F32719DF5F158CEE669 + +I=215 +KEY=0000000000000000000000000000000000000000000000000000020000000000 +CT=03945236EC2A4D4EAF30B8ABEB54330D + +I=216 +KEY=0000000000000000000000000000000000000000000000000000010000000000 +CT=11CC35301F24B79DDE31AEA2D1354F88 + +I=217 +KEY=0000000000000000000000000000000000000000000000000000008000000000 +CT=E73715B3E8D9A290F44AE6FFBF247E5D + +I=218 +KEY=0000000000000000000000000000000000000000000000000000004000000000 +CT=7345E07732B71CB158BBF64CCA5C5B96 + +I=219 +KEY=0000000000000000000000000000000000000000000000000000002000000000 +CT=6E128F296D24705A1924FD9B70C4ED04 + +I=220 +KEY=0000000000000000000000000000000000000000000000000000001000000000 +CT=95A789776F036783FBD330947083F54F + +I=221 +KEY=0000000000000000000000000000000000000000000000000000000800000000 +CT=360DEC2533EA4AA2E3E54FD3DE2906EB + +I=222 +KEY=0000000000000000000000000000000000000000000000000000000400000000 +CT=E68EFD7FECF4D601EA22727BD764965B + +I=223 +KEY=0000000000000000000000000000000000000000000000000000000200000000 +CT=9065C64A8BFF44AC33EDBB611CF83D7B + +I=224 +KEY=0000000000000000000000000000000000000000000000000000000100000000 +CT=8F33C8DF2A7A51CE8090E8F123BC3723 + +I=225 +KEY=0000000000000000000000000000000000000000000000000000000080000000 +CT=807F391FFBA8291BA625623210F99018 + +I=226 +KEY=0000000000000000000000000000000000000000000000000000000040000000 +CT=5E8B3F3A701522CE5CAA761C929D6292 + +I=227 +KEY=0000000000000000000000000000000000000000000000000000000020000000 +CT=3BA404DC38735A78289E3809E8364835 + +I=228 +KEY=0000000000000000000000000000000000000000000000000000000010000000 +CT=D23BEDBAD229F8305DC425B6B759DCC9 + +I=229 +KEY=0000000000000000000000000000000000000000000000000000000008000000 +CT=44880F21CF5913040AE376AEE2A10AD8 + +I=230 +KEY=0000000000000000000000000000000000000000000000000000000004000000 +CT=9BC98E29D057C0E828C3B5CCE69256C1 + +I=231 +KEY=0000000000000000000000000000000000000000000000000000000002000000 +CT=B293CC7A975DA141A68279368057CC41 + +I=232 +KEY=0000000000000000000000000000000000000000000000000000000001000000 +CT=8D60FB87ACD91385B313BE5F1D7BD30F + +I=233 +KEY=0000000000000000000000000000000000000000000000000000000000800000 +CT=2C8E56132D70291B303C48FDF75543CD + +I=234 +KEY=0000000000000000000000000000000000000000000000000000000000400000 +CT=D1F80035B826791F6CE4E59B7DB1BB0D + +I=235 +KEY=0000000000000000000000000000000000000000000000000000000000200000 +CT=42CE6224FC36469339A133DD08173BD4 + +I=236 +KEY=0000000000000000000000000000000000000000000000000000000000100000 +CT=61817155EA41BCBA2AF7F06AE7CBF585 + +I=237 +KEY=0000000000000000000000000000000000000000000000000000000000080000 +CT=D1923A9866068D2EF5FB77D57C3315B6 + +I=238 +KEY=0000000000000000000000000000000000000000000000000000000000040000 +CT=B37CBDB5D719F49691CA968EF2E84140 + +I=239 +KEY=0000000000000000000000000000000000000000000000000000000000020000 +CT=EC974E653A055D7F8F22171030F68E1D + +I=240 +KEY=0000000000000000000000000000000000000000000000000000000000010000 +CT=DDE5D3B9AAD9C32213BB3675A822499C + +I=241 +KEY=0000000000000000000000000000000000000000000000000000000000008000 +CT=D3B6E9216EA1AE57EB1C628A3C38AB78 + +I=242 +KEY=0000000000000000000000000000000000000000000000000000000000004000 +CT=82C99ECC69472B7E96324B042AE8B87A + +I=243 +KEY=0000000000000000000000000000000000000000000000000000000000002000 +CT=97144DC5338C43600F84439C0AA0D147 + +I=244 +KEY=0000000000000000000000000000000000000000000000000000000000001000 +CT=400AC4A0BBADA1DB2121EB144C7E5209 + +I=245 +KEY=0000000000000000000000000000000000000000000000000000000000000800 +CT=EFD9D550EB419ED278F4885A490AB54C + +I=246 +KEY=0000000000000000000000000000000000000000000000000000000000000400 +CT=2AB7816E149B7C0404C88A8857793670 + +I=247 +KEY=0000000000000000000000000000000000000000000000000000000000000200 +CT=5B591DFF9E8DEE15BAD24C025DBCA481 + +I=248 +KEY=0000000000000000000000000000000000000000000000000000000000000100 +CT=0C06633E30721C3749F49AD8CBF2B754 + +I=249 +KEY=0000000000000000000000000000000000000000000000000000000000000080 +CT=96D6D31A41B5123B2035FD91A921D4CA + +I=250 +KEY=0000000000000000000000000000000000000000000000000000000000000040 +CT=E7F6C34D86668BC2805CA7793C5E86AD + +I=251 +KEY=0000000000000000000000000000000000000000000000000000000000000020 +CT=F46DFF5FF500D6879C4D3E45CF0CF0F3 + +I=252 +KEY=0000000000000000000000000000000000000000000000000000000000000010 +CT=60D842D9C61DA7495C116197B7CECBBE + +I=253 +KEY=0000000000000000000000000000000000000000000000000000000000000008 +CT=D45B24EDB673353EBDF248B8FA06B67A + +I=254 +KEY=0000000000000000000000000000000000000000000000000000000000000004 +CT=119EAEBCC165D0BD02C0D35DC82EF992 + +I=255 +KEY=0000000000000000000000000000000000000000000000000000000000000002 +CT=E673143680414ADA301D0ED34626B9FE + +I=256 +KEY=0000000000000000000000000000000000000000000000000000000000000001 +CT=6B6CFE160A6263631B292F879EEFF926 + +========== \ No newline at end of file diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_vt.txt b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_vt.txt new file mode 100644 index 00000000..6dea60fc --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/ecb_vt.txt @@ -0,0 +1,1566 @@ + +========================= + +FILENAME: "ecb_vt.txt" + +Electronic Codebook (ECB) Mode +Variable Text Known Answer Tests + +Algorithm Name: Rijndael +Principal Submitter: Joan Daemen + +========== + +KEYSIZE=128 + +KEY=00000000000000000000000000000000 + +I=1 +PT=80000000000000000000000000000000 +CT=3AD78E726C1EC02B7EBFE92B23D9EC34 + +I=2 +PT=40000000000000000000000000000000 +CT=45BC707D29E8204D88DFBA2F0B0CAD9B + +I=3 +PT=20000000000000000000000000000000 +CT=161556838018F52805CDBD6202002E3F + +I=4 +PT=10000000000000000000000000000000 +CT=F5569B3AB6A6D11EFDE1BF0A64C6854A + +I=5 +PT=08000000000000000000000000000000 +CT=64E82B50E501FBD7DD4116921159B83E + +I=6 +PT=04000000000000000000000000000000 +CT=BAAC12FB613A7DE11450375C74034041 + +I=7 +PT=02000000000000000000000000000000 +CT=BCF176A7EAAD8085EBACEA362462A281 + +I=8 +PT=01000000000000000000000000000000 +CT=47711816E91D6FF059BBBF2BF58E0FD3 + +I=9 +PT=00800000000000000000000000000000 +CT=B970DFBE40698AF1638FE38BD3DF3B2F + +I=10 +PT=00400000000000000000000000000000 +CT=F95B59A44F391E14CF20B74BDC32FCFF + +I=11 +PT=00200000000000000000000000000000 +CT=720F74AE04A2A435B9A7256E49378F5B + +I=12 +PT=00100000000000000000000000000000 +CT=2A0445F61D36BFA7E277070730CF76DA + +I=13 +PT=00080000000000000000000000000000 +CT=8D0536B997AEFEC1D94011BAB6699A03 + +I=14 +PT=00040000000000000000000000000000 +CT=674F002E19F6ED47EFF319E51FAD4498 + +I=15 +PT=00020000000000000000000000000000 +CT=292C02C5CB9163C80AC0F6CF1DD8E92D + +I=16 +PT=00010000000000000000000000000000 +CT=FA321CF18EF5FE727DD82A5C1E945141 + +I=17 +PT=00008000000000000000000000000000 +CT=A5A7AFE1034C39CCCEBE3C584BC0BE05 + +I=18 +PT=00004000000000000000000000000000 +CT=4FF5A52E697E77D081205DBDB21CEA39 + +I=19 +PT=00002000000000000000000000000000 +CT=209E88DC94C9003000CE0769AF7B7166 + +I=20 +PT=00001000000000000000000000000000 +CT=5DEE41AF864CB4B650E5F51551824D38 + +I=21 +PT=00000800000000000000000000000000 +CT=A79A63FA7E4503AE6D6E09F5F9053030 + +I=22 +PT=00000400000000000000000000000000 +CT=A48316749FAE7FAC7002031A6AFD8BA7 + +I=23 +PT=00000200000000000000000000000000 +CT=D6EEE8A7357A0E1D64262CA9C337AC42 + +I=24 +PT=00000100000000000000000000000000 +CT=B013CA8A62A858053E9FB667ED39829E + +I=25 +PT=00000080000000000000000000000000 +CT=DF6EA9E4538A45A52D5C1A43C88F4B55 + +I=26 +PT=00000040000000000000000000000000 +CT=7D03BA451371591D3FD5547D9165C73B + +I=27 +PT=00000020000000000000000000000000 +CT=0E0426281A6277E186499D365D5F49FF + +I=28 +PT=00000010000000000000000000000000 +CT=DBC02169DD2059E6CC4C57C1FEDF5AB4 + +I=29 +PT=00000008000000000000000000000000 +CT=826590E05D167DA6F00DCC75E22788EB + +I=30 +PT=00000004000000000000000000000000 +CT=34A73F21A04421D9786335FAAB49423A + +I=31 +PT=00000002000000000000000000000000 +CT=ED347D0E0128EE1A7392A1D36AB78AA9 + +I=32 +PT=00000001000000000000000000000000 +CT=EE944B2FE6E9FC888042608DA9615F75 + +I=33 +PT=00000000800000000000000000000000 +CT=9E7C85A909EF7218BA7947CFB4718F46 + +I=34 +PT=00000000400000000000000000000000 +CT=811AE07A0B2B1F816587FA73699AE77D + +I=35 +PT=00000000200000000000000000000000 +CT=68466FBF43C2FE13D4B18F7EC5EA745F + +I=36 +PT=00000000100000000000000000000000 +CT=D20B015C7191B219780956E6101F9354 + +I=37 +PT=00000000080000000000000000000000 +CT=5939D5C1BBF54EE1B3E326D757BDDE25 + +I=38 +PT=00000000040000000000000000000000 +CT=B1FDAFE9A0240E8FFEA19CE94B5105D3 + +I=39 +PT=00000000020000000000000000000000 +CT=D62962ECE02CDD68C06BDFEFB2F9495B + +I=40 +PT=00000000010000000000000000000000 +CT=B3BB2DE6F3C26587BA8BAC4F7AD9499A + +I=41 +PT=00000000008000000000000000000000 +CT=E0B1072D6D9FF703D6FBEF77852B0A6B + +I=42 +PT=00000000004000000000000000000000 +CT=D8DD51C907F478DE0228E83E61FD1758 + +I=43 +PT=00000000002000000000000000000000 +CT=A42DFFE6E7C1671C06A25236FDD10017 + +I=44 +PT=00000000001000000000000000000000 +CT=25ACF141550BFAB9EF451B6C6A5B2163 + +I=45 +PT=00000000000800000000000000000000 +CT=4DA7FCA3949B16E821DBC84F19581018 + +I=46 +PT=00000000000400000000000000000000 +CT=7D49B6347CBCC8919C7FA96A37A7A215 + +I=47 +PT=00000000000200000000000000000000 +CT=900024B29A08C6721B95BA3B753DDB4D + +I=48 +PT=00000000000100000000000000000000 +CT=6D2182FB283B6934D90BA7848CAB5E66 + +I=49 +PT=00000000000080000000000000000000 +CT=F73EF01B448D23A4D90DE8B2F9666E7A + +I=50 +PT=00000000000040000000000000000000 +CT=4AD9CDA2418643E9A3D926AF5E6B0412 + +I=51 +PT=00000000000020000000000000000000 +CT=7CAEC8E7E5953997D545B033201C8C5B + +I=52 +PT=00000000000010000000000000000000 +CT=3C43CA1F6B6864503E27B48D88230CF5 + +I=53 +PT=00000000000008000000000000000000 +CT=44F779B93108FE9FEEC880D79BA74488 + +I=54 +PT=00000000000004000000000000000000 +CT=9E50E8D9CFD3A682A78E527C9072A1CF + +I=55 +PT=00000000000002000000000000000000 +CT=68D000CBC838BBE3C505D6F814C01F28 + +I=56 +PT=00000000000001000000000000000000 +CT=2CB2A9FEC1ACD1D9B0FA05205E304F57 + +I=57 +PT=00000000000000800000000000000000 +CT=01EB2806606E46444520A5CC6180CD4B + +I=58 +PT=00000000000000400000000000000000 +CT=DAA9B25168CC702326F217F1A0C0B162 + +I=59 +PT=00000000000000200000000000000000 +CT=3E07E648975D9578D03555B1755807ED + +I=60 +PT=00000000000000100000000000000000 +CT=0B45F52E802C8B8DE09579425B80B711 + +I=61 +PT=00000000000000080000000000000000 +CT=659595DA0B68F6DF0DD6CA77202986E1 + +I=62 +PT=00000000000000040000000000000000 +CT=05FF42873893536E58C8FA98A45C73C4 + +I=63 +PT=00000000000000020000000000000000 +CT=B5B03421DE8BBFFC4EADEC767339A9BD + +I=64 +PT=00000000000000010000000000000000 +CT=788BCD111ECF73D4E78D2E21BEF55460 + +I=65 +PT=00000000000000008000000000000000 +CT=909CD9EC6790359F982DC6F2393D5315 + +I=66 +PT=00000000000000004000000000000000 +CT=332950F361535FF24EFAC8C76293F12C + +I=67 +PT=00000000000000002000000000000000 +CT=A68CCD4E330FFDA9D576DA436DB53D75 + +I=68 +PT=00000000000000001000000000000000 +CT=27C8A1CCFDB0B015D1ED5B3E77143791 + +I=69 +PT=00000000000000000800000000000000 +CT=D76A4B95887A77DF610DD3E1D3B20325 + +I=70 +PT=00000000000000000400000000000000 +CT=C068AB0DE71C66DAE83C361EF4B2D989 + +I=71 +PT=00000000000000000200000000000000 +CT=C2120BCD49EDA9A288B3B4BE79AC8158 + +I=72 +PT=00000000000000000100000000000000 +CT=0C546F62BF2773CD0F564FCECA7BA688 + +I=73 +PT=00000000000000000080000000000000 +CT=18F3462BEDE4920213CCB66DAB1640AA + +I=74 +PT=00000000000000000040000000000000 +CT=FE42F245EDD0E24B216AEBD8B392D690 + +I=75 +PT=00000000000000000020000000000000 +CT=3D3EEBC8D3D1558A194C2D00C337FF2B + +I=76 +PT=00000000000000000010000000000000 +CT=29AAEDF043E785DB42836F79BE6CBA28 + +I=77 +PT=00000000000000000008000000000000 +CT=215F90C6744E2944358E78619159A611 + +I=78 +PT=00000000000000000004000000000000 +CT=8606B1AA9E1D548E5442B06551E2C6DC + +I=79 +PT=00000000000000000002000000000000 +CT=987BB4B8740EC0EDE7FEA97DF033B5B1 + +I=80 +PT=00000000000000000001000000000000 +CT=C0A3500DA5B0AE07D2F450930BEEDF1B + +I=81 +PT=00000000000000000000800000000000 +CT=525FDF8312FE8F32C781481A8DAAAE37 + +I=82 +PT=00000000000000000000400000000000 +CT=BFD2C56AE5FB9C9DE33A6944572A6487 + +I=83 +PT=00000000000000000000200000000000 +CT=7975A57A425CDF5AA1FA929101F650B0 + +I=84 +PT=00000000000000000000100000000000 +CT=BF174BC49609A8709B2CD8366DAA79FE + +I=85 +PT=00000000000000000000080000000000 +CT=06C50C43222F56C874B1704E9F44BF7D + +I=86 +PT=00000000000000000000040000000000 +CT=0CEC48CD34043EA29CA3B8ED5278721E + +I=87 +PT=00000000000000000000020000000000 +CT=9548EA34A1560197B304D0ACB8A1698D + +I=88 +PT=00000000000000000000010000000000 +CT=22F9E9B1BD73B6B5B7D3062C986272F3 + +I=89 +PT=00000000000000000000008000000000 +CT=FEE8E934BD0873295059002230E298D4 + +I=90 +PT=00000000000000000000004000000000 +CT=1B08E2E3EB820D139CB4ABBDBE81D00D + +I=91 +PT=00000000000000000000002000000000 +CT=0021177681E4D90CEAF69DCED0145125 + +I=92 +PT=00000000000000000000001000000000 +CT=4A8E314452CA8A8A3619FC54BC423643 + +I=93 +PT=00000000000000000000000800000000 +CT=65047474F7222C94C6965425FF1BFD0A + +I=94 +PT=00000000000000000000000400000000 +CT=E123F551A9C4A8489622B16F961A9AA4 + +I=95 +PT=00000000000000000000000200000000 +CT=EF05530948B80915028BB2B6FE429380 + +I=96 +PT=00000000000000000000000100000000 +CT=72535B7FE0F0F777CEDCD55CD77E2DDF + +I=97 +PT=00000000000000000000000080000000 +CT=3423D8EFC31FA2F4C365C77D8F3B5C63 + +I=98 +PT=00000000000000000000000040000000 +CT=DE0E51C264663F3C5DBC59580A98D8E4 + +I=99 +PT=00000000000000000000000020000000 +CT=B2D9391166680947AB09264156719679 + +I=100 +PT=00000000000000000000000010000000 +CT=10DB79F23B06D263835C424AF749ADB7 + +I=101 +PT=00000000000000000000000008000000 +CT=DDF72D27E6B01EC107EA3E005B59563B + +I=102 +PT=00000000000000000000000004000000 +CT=8266B57485A5954A4236751DE07F6694 + +I=103 +PT=00000000000000000000000002000000 +CT=669A501E1F1ADE6E5523DE01D6DBC987 + +I=104 +PT=00000000000000000000000001000000 +CT=C20C48F2989725D461D1DB589DC0896E + +I=105 +PT=00000000000000000000000000800000 +CT=DE35158E7810ED1191825D2AA98FA97D + +I=106 +PT=00000000000000000000000000400000 +CT=4FE294F2C0F34D0671B693A237EBDDC8 + +I=107 +PT=00000000000000000000000000200000 +CT=087AE74B10CCBFDF6739FEB9559C01A4 + +I=108 +PT=00000000000000000000000000100000 +CT=5DC278970B7DEF77A5536C77AB59C207 + +I=109 +PT=00000000000000000000000000080000 +CT=7607F078C77085184EAA9B060C1FBFFF + +I=110 +PT=00000000000000000000000000040000 +CT=9DB841531BCBE7998DAD19993FB3CC00 + +I=111 +PT=00000000000000000000000000020000 +CT=D6A089B654854A94560BAE13298835B8 + +I=112 +PT=00000000000000000000000000010000 +CT=E1E223C4CF90CC5D195B370D65114622 + +I=113 +PT=00000000000000000000000000008000 +CT=1CBED73C50D053BDAD372CEEE54836A1 + +I=114 +PT=00000000000000000000000000004000 +CT=D309E69376D257ADF2BFDA152B26555F + +I=115 +PT=00000000000000000000000000002000 +CT=740F7649117F0DEE6EAA7789A9994C36 + +I=116 +PT=00000000000000000000000000001000 +CT=76AE64417C297184D668C5FD908B3CE5 + +I=117 +PT=00000000000000000000000000000800 +CT=6095FEA4AA8035591F1787A819C48787 + +I=118 +PT=00000000000000000000000000000400 +CT=D1FF4E7ACD1C79967FEBAB0F7465D450 + +I=119 +PT=00000000000000000000000000000200 +CT=5F5AD3C42B9489557BB63BF49ECF5F8A + +I=120 +PT=00000000000000000000000000000100 +CT=FB56CC09B680B1D07C5A52149E29F07C + +I=121 +PT=00000000000000000000000000000080 +CT=FF49B8DF4A97CBE03833E66197620DAD + +I=122 +PT=00000000000000000000000000000040 +CT=5E070ADE533D2E090ED0F5BE13BC0983 + +I=123 +PT=00000000000000000000000000000020 +CT=3AB4FB1D2B7BA376590A2C241D1F508D + +I=124 +PT=00000000000000000000000000000010 +CT=58B2431BC0BEDE02550F40238969EC78 + +I=125 +PT=00000000000000000000000000000008 +CT=0253786E126504F0DAB90C48A30321DE + +I=126 +PT=00000000000000000000000000000004 +CT=200211214E7394DA2089B6ACD093ABE0 + +I=127 +PT=00000000000000000000000000000002 +CT=0388DACE60B6A392F328C2B971B2FE78 + +I=128 +PT=00000000000000000000000000000001 +CT=58E2FCCEFA7E3061367F1D57A4E7455A + +========== + +KEYSIZE=192 + +KEY=000000000000000000000000000000000000000000000000 + +I=1 +PT=80000000000000000000000000000000 +CT=6CD02513E8D4DC986B4AFE087A60BD0C + +I=2 +PT=40000000000000000000000000000000 +CT=423D2772A0CA56DAABB48D2129062987 + +I=3 +PT=20000000000000000000000000000000 +CT=1021F2A8DA70EB2219DC16804445FF98 + +I=4 +PT=10000000000000000000000000000000 +CT=C636E35B402577F96974D8804295EBB8 + +I=5 +PT=08000000000000000000000000000000 +CT=1566D2E57E8393C19E29F892EA28A9A7 + +I=6 +PT=04000000000000000000000000000000 +CT=883C878FED70B36CC09D040F9619DD19 + +I=7 +PT=02000000000000000000000000000000 +CT=06734593A974965790E715594FC34AA9 + +I=8 +PT=01000000000000000000000000000000 +CT=F19B389948D9A45534E5BD36C984134A + +I=9 +PT=00800000000000000000000000000000 +CT=D8410DFC14FA6D175EC968EA8CAC514C + +I=10 +PT=00400000000000000000000000000000 +CT=7E6C6EBB4029A177CF7B2FDD9AC6BB7A + +I=11 +PT=00200000000000000000000000000000 +CT=4B51DD4850DC0A6C3A46D924003D2C27 + +I=12 +PT=00100000000000000000000000000000 +CT=2E510A9D917B15BE32A192B12A668F23 + +I=13 +PT=00080000000000000000000000000000 +CT=88F6F79962B0FB77FEA8E7C632D3108E + +I=14 +PT=00040000000000000000000000000000 +CT=A3A35AB1D88DAF07B52794A0F065383A + +I=15 +PT=00020000000000000000000000000000 +CT=DC6CC878433E2B3BB193049A4ECBFC53 + +I=16 +PT=00010000000000000000000000000000 +CT=EFCD3763EB7B1A415938248A9A5B4FD5 + +I=17 +PT=00008000000000000000000000000000 +CT=AB7E9FB9A66DBE5BB44854F07D9015EE + +I=18 +PT=00004000000000000000000000000000 +CT=8B8E9D3365F8F6743ECF7E33E99255A4 + +I=19 +PT=00002000000000000000000000000000 +CT=54D37B4F176FF3D8F6AFC866066D8572 + +I=20 +PT=00001000000000000000000000000000 +CT=E83310889480FBF3C00342E3126D0D02 + +I=21 +PT=00000800000000000000000000000000 +CT=D321AB2511F92F098174AA2DE6E85DA2 + +I=22 +PT=00000400000000000000000000000000 +CT=D8E3F40B1112D5149D58C481DFA9983F + +I=23 +PT=00000200000000000000000000000000 +CT=2454C4E0806639DDF19854D6C68054AD + +I=24 +PT=00000100000000000000000000000000 +CT=A5506D410F7CA32F3955DD79D9D09418 + +I=25 +PT=00000080000000000000000000000000 +CT=7908EE40677699568A7DC1AA317C7E4E + +I=26 +PT=00000040000000000000000000000000 +CT=B4B7B29DD43B2F5CF765E25192273982 + +I=27 +PT=00000020000000000000000000000000 +CT=92AFE9668159BEFFE2A86F8503260164 + +I=28 +PT=00000010000000000000000000000000 +CT=5C36A232FBA6D187A84657AD4028B18F + +I=29 +PT=00000008000000000000000000000000 +CT=A2E994DFAB3A798DF8F54F6DA87E58E2 + +I=30 +PT=00000004000000000000000000000000 +CT=6CDAB10A72ADF77D71D0765BAAE95631 + +I=31 +PT=00000002000000000000000000000000 +CT=9FE3C801BCAAF7BB800F2E6BF3278E21 + +I=32 +PT=00000001000000000000000000000000 +CT=B459D90D9A6C392E5493BC91CF5A0863 + +I=33 +PT=00000000800000000000000000000000 +CT=0518A9FA5007F6787E0FB4E5AC27D758 + +I=34 +PT=00000000400000000000000000000000 +CT=BED9795415D28599700ED7952384A963 + +I=35 +PT=00000000200000000000000000000000 +CT=F0140421173D60251EF6CAB0229B1B50 + +I=36 +PT=00000000100000000000000000000000 +CT=460EB4652B3F6779EA28CB11B37529ED + +I=37 +PT=00000000080000000000000000000000 +CT=C4283D351C960A6AC13CD19CCF03AE38 + +I=38 +PT=00000000040000000000000000000000 +CT=6815A10047B2C834A798EBDCC6786C75 + +I=39 +PT=00000000020000000000000000000000 +CT=99BA19F0CDD5990D0386B32CE56C9C4C + +I=40 +PT=00000000010000000000000000000000 +CT=DE76F62C61E07915162DA13E79679DEC + +I=41 +PT=00000000008000000000000000000000 +CT=DD0325D6854803D06D1D2277D5FB8D67 + +I=42 +PT=00000000004000000000000000000000 +CT=580B71A41DE37D6FAC83CCB0B3BB1C97 + +I=43 +PT=00000000002000000000000000000000 +CT=E9B1AB470A1B02EF0FF5E6754A092C96 + +I=44 +PT=00000000001000000000000000000000 +CT=8590620F5AF5993B7410282F4126BC1F + +I=45 +PT=00000000000800000000000000000000 +CT=8D4914D2F1B22B2E268E66E532D29D7C + +I=46 +PT=00000000000400000000000000000000 +CT=FD826CE48E62C5E30867044B86BA4B56 + +I=47 +PT=00000000000200000000000000000000 +CT=100E7B831C9F35FA1271F5F1316C6FCF + +I=48 +PT=00000000000100000000000000000000 +CT=0A2DD0C17F68B996AA96C007003D0B31 + +I=49 +PT=00000000000080000000000000000000 +CT=C95F68C57E06B0A2E1F623C83C5D80BF + +I=50 +PT=00000000000040000000000000000000 +CT=571CAFC92C7C8A5EC54C0741E186905C + +I=51 +PT=00000000000020000000000000000000 +CT=22514353E95312C112255E1EED0B2DF6 + +I=52 +PT=00000000000010000000000000000000 +CT=791A8BF462BD17580BD9152C6D11C6C5 + +I=53 +PT=00000000000008000000000000000000 +CT=5882A0178D548F84A165DB809C60DC28 + +I=54 +PT=00000000000004000000000000000000 +CT=3CE4A90EED4458CA6039E42DDADB71C3 + +I=55 +PT=00000000000002000000000000000000 +CT=D3CBAB261207A16BE2751E77044FD7C9 + +I=56 +PT=00000000000001000000000000000000 +CT=24E32B698A7B32217093628B01F424AB + +I=57 +PT=00000000000000800000000000000000 +CT=9F6AFC0AF27CF565110C77E3C24F4F5B + +I=58 +PT=00000000000000400000000000000000 +CT=E088AA5CDA20EF267BB039B00C72C45B + +I=59 +PT=00000000000000200000000000000000 +CT=5CF1018B7E0BA1775601C2E279900360 + +I=60 +PT=00000000000000100000000000000000 +CT=3B1A7388B89FB9416AD8753CF5AF35D2 + +I=61 +PT=00000000000000080000000000000000 +CT=137FA4ED00AFCD9F5D8BC0D14BD5837A + +I=62 +PT=00000000000000040000000000000000 +CT=806F5C9B663559BB56F234881E4A3E60 + +I=63 +PT=00000000000000020000000000000000 +CT=8069A449152292DF2DE8642992C632B6 + +I=64 +PT=00000000000000010000000000000000 +CT=37C6CF2A1ABD1B1F1922B46C7B4A280D + +I=65 +PT=00000000000000008000000000000000 +CT=7A2835260E5A0AA2B5DC301800EC8438 + +I=66 +PT=00000000000000004000000000000000 +CT=EE81FAF2F9058213FFCACF281CB8509E + +I=67 +PT=00000000000000002000000000000000 +CT=57F22D93C37129BA331FDBA38E005A1E + +I=68 +PT=00000000000000001000000000000000 +CT=EC798782E87B7D9F780CC3C3A46519B5 + +I=69 +PT=00000000000000000800000000000000 +CT=43EA28497F5D40E3A4744FA2EDAA42DE + +I=70 +PT=00000000000000000400000000000000 +CT=91F004E7DEBF41B3414DD8C5C317372C + +I=71 +PT=00000000000000000200000000000000 +CT=C249EAE54E7B4DF43B938C1B4CC28314 + +I=72 +PT=00000000000000000100000000000000 +CT=32C289D7EEFB99D2F17AD7B7D45FE1EC + +I=73 +PT=00000000000000000080000000000000 +CT=A675FB2E8DDBF810CEF01CF2B728CD2B + +I=74 +PT=00000000000000000040000000000000 +CT=A418AAAB6E6921CC731AA8A349386080 + +I=75 +PT=00000000000000000020000000000000 +CT=2E2B0F44863E67D9B0215C4ABD60417F + +I=76 +PT=00000000000000000010000000000000 +CT=F0AF7CB19E911D481F6426DAEFDD2240 + +I=77 +PT=00000000000000000008000000000000 +CT=CB1304DAAA2DF6878F56AC2E0F887E04 + +I=78 +PT=00000000000000000004000000000000 +CT=B1B70A7E6A0CD1916D9B78BEA19084AE + +I=79 +PT=00000000000000000002000000000000 +CT=0CDE9F9BE646A5FCE3436B794A9CFC65 + +I=80 +PT=00000000000000000001000000000000 +CT=68C7946D476A0A36674B36AFD7E5DF33 + +I=81 +PT=00000000000000000000800000000000 +CT=48770159A07DD8DFFF06C80105F8D57C + +I=82 +PT=00000000000000000000400000000000 +CT=665E62801B3260E3C45BD3BE34DFDEBE + +I=83 +PT=00000000000000000000200000000000 +CT=4159C1F686BFBE5B0E50BDB0DA532B69 + +I=84 +PT=00000000000000000000100000000000 +CT=6333100A5A4AD917DC2D4E78A04869A3 + +I=85 +PT=00000000000000000000080000000000 +CT=866A4519AB1D199F25886B89D0539ACC + +I=86 +PT=00000000000000000000040000000000 +CT=EC0CFD37E4CBC7E8BE385283F7AEA75A + +I=87 +PT=00000000000000000000020000000000 +CT=CA2F383AACCA0810AA13F3E710621422 + +I=88 +PT=00000000000000000000010000000000 +CT=1D0EEF6870444F950937831EC0A55D98 + +I=89 +PT=00000000000000000000008000000000 +CT=37839B35ED6801E7670496D479A95017 + +I=90 +PT=00000000000000000000004000000000 +CT=02317C8C7098C4F94AB867AC7A49DD8D + +I=91 +PT=00000000000000000000002000000000 +CT=FFB4CB4E3F7F8BF3367EBD43236518B4 + +I=92 +PT=00000000000000000000001000000000 +CT=36BEDEF1E4AA3E4A40A305741713FCBF + +I=93 +PT=00000000000000000000000800000000 +CT=B2DFE3C4870269C1E3FEEC39161540D9 + +I=94 +PT=00000000000000000000000400000000 +CT=147EF2518AD45DA0026056ECBF6A3DFA + +I=95 +PT=00000000000000000000000200000000 +CT=027A75E4DE635790E47ACE90D7928804 + +I=96 +PT=00000000000000000000000100000000 +CT=C4CF3CCB59BF87D0AFBD629F48CFBB7B + +I=97 +PT=00000000000000000000000080000000 +CT=35165C93F564C97E1C32EF97E8151A87 + +I=98 +PT=00000000000000000000000040000000 +CT=449DE37F7D5A1BBD628ABBE7E061701D + +I=99 +PT=00000000000000000000000020000000 +CT=B1D45EAF218F1799B149BAD677FE129F + +I=100 +PT=00000000000000000000000010000000 +CT=BE08AC6DB6BD0583AA9D2ABC71C73DCD + +I=101 +PT=00000000000000000000000008000000 +CT=BCC835BD3DF1A79E4C7C145B899A5C25 + +I=102 +PT=00000000000000000000000004000000 +CT=3D311EA611FF5AF371301C58A8E9912D + +I=103 +PT=00000000000000000000000002000000 +CT=A5A1BEA594ACC7CA80F09EA5ADDB5C71 + +I=104 +PT=00000000000000000000000001000000 +CT=0F09492429FE7222D6CD8190D9F2FFBF + +I=105 +PT=00000000000000000000000000800000 +CT=816D2220A16B8AAEE71364FD43636C6F + +I=106 +PT=00000000000000000000000000400000 +CT=D7E8702408419ED73191B107EAF75A0B + +I=107 +PT=00000000000000000000000000200000 +CT=9B170EFB1E235B433C78E276BEA082F0 + +I=108 +PT=00000000000000000000000000100000 +CT=03BBECC5598AE974430F29395522F096 + +I=109 +PT=00000000000000000000000000080000 +CT=DB53517766C0E8CF42059607CBA89380 + +I=110 +PT=00000000000000000000000000040000 +CT=2E2AF4B7931F0AEFFAC5471148A5BB97 + +I=111 +PT=00000000000000000000000000020000 +CT=C872C0408266403B984F635FF5683DE4 + +I=112 +PT=00000000000000000000000000010000 +CT=15DCF750B0E3A68AD1F4EFD07E8967B4 + +I=113 +PT=00000000000000000000000000008000 +CT=B41092048E9E6A749F6FD8CE515A23A3 + +I=114 +PT=00000000000000000000000000004000 +CT=4DA9267D62507994312BD5C99ADDE730 + +I=115 +PT=00000000000000000000000000002000 +CT=9E2FCA6D1D626E9C6A924EBF7DBF618A + +I=116 +PT=00000000000000000000000000001000 +CT=E092E8D7EF2C2465AEFB2493C3063590 + +I=117 +PT=00000000000000000000000000000800 +CT=1C0E58DA37D1068378A88DBE2EDE4E10 + +I=118 +PT=00000000000000000000000000000400 +CT=19063F854232B8509A6A3A6D46809959 + +I=119 +PT=00000000000000000000000000000200 +CT=447FB09E54EFA285F7530F25C4EA0022 + +I=120 +PT=00000000000000000000000000000100 +CT=F6ABE86321BE40E1FBFDAFED37CC1D9B + +I=121 +PT=00000000000000000000000000000080 +CT=4E8506CD006666341D6CF51F98B41F35 + +I=122 +PT=00000000000000000000000000000040 +CT=53995DE0009CA18BECAFB8307C54C14C + +I=123 +PT=00000000000000000000000000000020 +CT=2006BF99F4C58B6CC2627856593FAEEA + +I=124 +PT=00000000000000000000000000000010 +CT=2DA697D2737CB30B744A4644FA1CBC6E + +I=125 +PT=00000000000000000000000000000008 +CT=47A22ACDB60C3A986A8F76ECD0EA3433 + +I=126 +PT=00000000000000000000000000000004 +CT=FDAA17C2CDE20268FE36E164EA532151 + +I=127 +PT=00000000000000000000000000000002 +CT=98E7247C07F0FE411C267E4384B0F600 + +I=128 +PT=00000000000000000000000000000001 +CT=CD33B28AC773F74BA00ED1F312572435 + +========== + +KEYSIZE=256 + +KEY=0000000000000000000000000000000000000000000000000000000000000000 + +I=1 +PT=80000000000000000000000000000000 +CT=DDC6BF790C15760D8D9AEB6F9A75FD4E + +I=2 +PT=40000000000000000000000000000000 +CT=C7098C217C334D0C9BDF37EA13B0822C + +I=3 +PT=20000000000000000000000000000000 +CT=60F0FB0D4C56A8D4EEFEC5264204042D + +I=4 +PT=10000000000000000000000000000000 +CT=73376FBBF654D0686E0E84001477106B + +I=5 +PT=08000000000000000000000000000000 +CT=2F443B52BA5F0C6EA0602C7C4FD259B6 + +I=6 +PT=04000000000000000000000000000000 +CT=75D11B0E3A68C4223D88DBF017977DD7 + +I=7 +PT=02000000000000000000000000000000 +CT=779B38D15BFFB63D8D609D551A5CC98E + +I=8 +PT=01000000000000000000000000000000 +CT=5275F3D86B4FB8684593133EBFA53CD3 + +I=9 +PT=00800000000000000000000000000000 +CT=1CEF2074B336CEC62F12DEA2F6AB1481 + +I=10 +PT=00400000000000000000000000000000 +CT=1AEF5ABBAD9D7160874578DCD8BAE172 + +I=11 +PT=00200000000000000000000000000000 +CT=46C525DB17E72F26BF03216846B6F609 + +I=12 +PT=00100000000000000000000000000000 +CT=E24411F941BBE08788781E3EC52CBAA4 + +I=13 +PT=00080000000000000000000000000000 +CT=83A3DEDD1DD27018F6A6477E40527581 + +I=14 +PT=00040000000000000000000000000000 +CT=B68F8A2CDBAB0C923C67FC8F0F1087DE + +I=15 +PT=00020000000000000000000000000000 +CT=649944A70C32BF87A7409E7AE128FDE8 + +I=16 +PT=00010000000000000000000000000000 +CT=2846526D67387539C89314DE9E0C2D02 + +I=17 +PT=00008000000000000000000000000000 +CT=A9A0B8402E53C70DD1688054BA58DDFD + +I=18 +PT=00004000000000000000000000000000 +CT=4A72E6E1B79C83AC4BE3EBA5699EED48 + +I=19 +PT=00002000000000000000000000000000 +CT=B0E36B867BA4FF2B77D0614B0E364E4C + +I=20 +PT=00001000000000000000000000000000 +CT=49B57DE141F6418E3090F24DDD4014B6 + +I=21 +PT=00000800000000000000000000000000 +CT=A6C0D5B9797258E1987AC5F6CD20146D + +I=22 +PT=00000400000000000000000000000000 +CT=426CF4BDCAA369175965D26E7C71EEA2 + +I=23 +PT=00000200000000000000000000000000 +CT=E27F484CE54BC99BC1A52BDA3B518A26 + +I=24 +PT=00000100000000000000000000000000 +CT=D16D186284C7E6EE64B8104E0EF20BA5 + +I=25 +PT=00000080000000000000000000000000 +CT=6431F8538AD54E1E044A9F71F8EF556B + +I=26 +PT=00000040000000000000000000000000 +CT=ECD57CEB451D27EB96C55B2042257E8E + +I=27 +PT=00000020000000000000000000000000 +CT=4F0F188DC911B1954AFBC734C9F68872 + +I=28 +PT=00000010000000000000000000000000 +CT=B54DEF0337626B65614E81EDFDE620F3 + +I=29 +PT=00000008000000000000000000000000 +CT=6655D8074CAE0B90B0D3A3FE72D4D9DB + +I=30 +PT=00000004000000000000000000000000 +CT=C6B74B6B9EB4FC0C9A237DB1B616D09A + +I=31 +PT=00000002000000000000000000000000 +CT=D7B5D076EA56EC2B20791D7AD51CCF8F + +I=32 +PT=00000001000000000000000000000000 +CT=FE160C224BF003CE3BDDC90CB52ED22C + +I=33 +PT=00000000800000000000000000000000 +CT=5E00DA9BA94B5EC0D258D8A8002E0F6A + +I=34 +PT=00000000400000000000000000000000 +CT=09AC6DCFF4DACFF1651E2BA212A292A3 + +I=35 +PT=00000000200000000000000000000000 +CT=B283617E318D99AF83A05D9810BA89F7 + +I=36 +PT=00000000100000000000000000000000 +CT=0B5F70CCB40B0EF2538AE9B4A9770B35 + +I=37 +PT=00000000080000000000000000000000 +CT=43282BF180248FB517839B37F4DDAAE4 + +I=38 +PT=00000000040000000000000000000000 +CT=DDBD534C8B2E6D30A268F88C55AD765B + +I=39 +PT=00000000020000000000000000000000 +CT=A41A164E50EC2D9F175E752B755E0B5C + +I=40 +PT=00000000010000000000000000000000 +CT=37BFF99FF2F7AA97779E4ADF6F13FB10 + +I=41 +PT=00000000008000000000000000000000 +CT=9BA4F7BD298152903A683C4CEC669216 + +I=42 +PT=00000000004000000000000000000000 +CT=5FB750C7CE10DE7B4504248914D0DA06 + +I=43 +PT=00000000002000000000000000000000 +CT=3E748BFA108E086F51D56EC74A9E0FB9 + +I=44 +PT=00000000001000000000000000000000 +CT=31D4E56B99F5B73C1B8437DF332AFB98 + +I=45 +PT=00000000000800000000000000000000 +CT=9DC6717B84FC55D266E7B1D9B5C52A5F + +I=46 +PT=00000000000400000000000000000000 +CT=8EF8BA007F23C0A50FC120E07041BCCD + +I=47 +PT=00000000000200000000000000000000 +CT=C58F38E1839FC1918A12B8C9E88C66B6 + +I=48 +PT=00000000000100000000000000000000 +CT=B695D72A3FCF508C4050E12E40061C2D + +I=49 +PT=00000000000080000000000000000000 +CT=5D2736AD478A50583BC8C11BEFF16D7A + +I=50 +PT=00000000000040000000000000000000 +CT=DF0EACA8F17847AD41F9578F14C7B56B + +I=51 +PT=00000000000020000000000000000000 +CT=E5AA14AD48AD0A3C47CC35D5F8020E51 + +I=52 +PT=00000000000010000000000000000000 +CT=11BE6C8F58EBD8CEF1A53F591A68E8CE + +I=53 +PT=00000000000008000000000000000000 +CT=ECFE7BAFCBF42C1FEE015488770B3053 + +I=54 +PT=00000000000004000000000000000000 +CT=E552649F8D8EC4A1E1CD6DF50B6E6777 + +I=55 +PT=00000000000002000000000000000000 +CT=521C0629DE93B9119CDB1DDC5809DDEA + +I=56 +PT=00000000000001000000000000000000 +CT=CB38A62A0BAB1784156BA038CBA99BF6 + +I=57 +PT=00000000000000800000000000000000 +CT=76CCEE8AAACD394DE1EEF3DDA10CB54B + +I=58 +PT=00000000000000400000000000000000 +CT=6AFF910FA1D5673140E2DB59B8416049 + +I=59 +PT=00000000000000200000000000000000 +CT=064A12C0EF73FB386801BF4F35F3120D + +I=60 +PT=00000000000000100000000000000000 +CT=2240E374929D5B1BB8FF0FFDDDF640EC + +I=61 +PT=00000000000000080000000000000000 +CT=D4BA15C904C7692185DE85C02052E180 + +I=62 +PT=00000000000000040000000000000000 +CT=1714A315AB0166728A44CD91D4AE9018 + +I=63 +PT=00000000000000020000000000000000 +CT=6C970BDD9F0E222722EA31A1D12DD0AD + +I=64 +PT=00000000000000010000000000000000 +CT=F5956EDF02BD36A401BBB6CE77C3D3FB + +I=65 +PT=00000000000000008000000000000000 +CT=0CA11F122CCD7C259DC597EED3DF9BC4 + +I=66 +PT=00000000000000004000000000000000 +CT=50109AB4912AD2560B206F331B62EB6C + +I=67 +PT=00000000000000002000000000000000 +CT=DBE7C91A4175614889A2D4BEFD64845E + +I=68 +PT=00000000000000001000000000000000 +CT=0D3322853A571A6B46B79C0228E0DD25 + +I=69 +PT=00000000000000000800000000000000 +CT=96E4EE0BB9A11C6FB8522F285BADDEB6 + +I=70 +PT=00000000000000000400000000000000 +CT=96705C52D2CFCE82E630C93477C79C49 + +I=71 +PT=00000000000000000200000000000000 +CT=C50130AED6A126149D71F3888C83C232 + +I=72 +PT=00000000000000000100000000000000 +CT=4816EFE3DEB380566EBA0C17BF582090 + +I=73 +PT=00000000000000000080000000000000 +CT=0390857B4C8C98E4CF7A2B6F3394C507 + +I=74 +PT=00000000000000000040000000000000 +CT=422E73A02025EBE8B8B5D6E0FA24FCB2 + +I=75 +PT=00000000000000000020000000000000 +CT=3271AA7F4BF1D7C38050A43076D4FF76 + +I=76 +PT=00000000000000000010000000000000 +CT=D2074946F0D37B8975607BFC2E70234C + +I=77 +PT=00000000000000000008000000000000 +CT=1A509194C1270AB92E5A42D3A9F8D98B + +I=78 +PT=00000000000000000004000000000000 +CT=512438946360CCC4A5C6D73F6EED7130 + +I=79 +PT=00000000000000000002000000000000 +CT=98CFCDEC46EBEA1A286B3004F2746A0D + +I=80 +PT=00000000000000000001000000000000 +CT=A1CF369949677A3AF3D58E3EABF2741B + +I=81 +PT=00000000000000000000800000000000 +CT=D84C2E1A0E4A52166FA8FF6889D1E5E2 + +I=82 +PT=00000000000000000000400000000000 +CT=4AD91CCEEF60119B5078FD162D2735DE + +I=83 +PT=00000000000000000000200000000000 +CT=2860793D818E97AAFF1D339D7702438D + +I=84 +PT=00000000000000000000100000000000 +CT=6F9068BE73364AE250D89D78A6C9CE6F + +I=85 +PT=00000000000000000000080000000000 +CT=024FC3FEF4883FEB1A8DD005305FECCE + +I=86 +PT=00000000000000000000040000000000 +CT=08A61FE0816D75EA15EB3C9FB9CCDED6 + +I=87 +PT=00000000000000000000020000000000 +CT=449C86DFA13F260175CE39797686FFA4 + +I=88 +PT=00000000000000000000010000000000 +CT=4FFFFC29A59858E1133F2BFB1A8A4817 + +I=89 +PT=00000000000000000000008000000000 +CT=19425D1F6480B25096561295697DC2B7 + +I=90 +PT=00000000000000000000004000000000 +CT=31974727ECDD2C77C3A428FC3A8CB3FC + +I=91 +PT=00000000000000000000002000000000 +CT=A57CD704B3C95E744D08DF443458F2F5 + +I=92 +PT=00000000000000000000001000000000 +CT=486D8C193DB1ED73ACB17990442FC40B + +I=93 +PT=00000000000000000000000800000000 +CT=5E4DBF4E83AB3BC055B9FCC7A6B3A763 + +I=94 +PT=00000000000000000000000400000000 +CT=ACF2E0A693FBBCBA4D41B861E0D89E37 + +I=95 +PT=00000000000000000000000200000000 +CT=32A7CB2AE066A51D2B78FC4B4CFCB608 + +I=96 +PT=00000000000000000000000100000000 +CT=677D494DBB73CAF55C1990158DA12F14 + +I=97 +PT=00000000000000000000000080000000 +CT=082A0D2367512ADF0D75A151BFBE0A17 + +I=98 +PT=00000000000000000000000040000000 +CT=5E5BB7337923C482CE8CBA249E6A8C7D + +I=99 +PT=00000000000000000000000020000000 +CT=D3001BA7C7026EE3E5003179530AFCFC + +I=100 +PT=00000000000000000000000010000000 +CT=46EC44F8931E629FE8FD8961312EDDE1 + +I=101 +PT=00000000000000000000000008000000 +CT=C5F8ECD79C7B30E81D17E32079969310 + +I=102 +PT=00000000000000000000000004000000 +CT=5B8AD6919E24CAEBCC55401AEE0C9802 + +I=103 +PT=00000000000000000000000002000000 +CT=C2302B7E701B5CC7F8B29E3516DBBFA6 + +I=104 +PT=00000000000000000000000001000000 +CT=A1D04D6A76F9F7A94D49FAA64A87F244 + +I=105 +PT=00000000000000000000000000800000 +CT=7FB6F92D35B5CB6C631600EDB9E860BA + +I=106 +PT=00000000000000000000000000400000 +CT=B2EF7078BCFACE07AEEC3F9B48830EB3 + +I=107 +PT=00000000000000000000000000200000 +CT=F475A7493D24C7036E53390374C378B3 + +I=108 +PT=00000000000000000000000000100000 +CT=B36802AC987377A37BD8EADC97C57D60 + +I=109 +PT=00000000000000000000000000080000 +CT=ADDCD3D19689C4DDC738CE5F69DC9505 + +I=110 +PT=00000000000000000000000000040000 +CT=0DAF8CA22884915403C0F0BB1F4BD74F + +I=111 +PT=00000000000000000000000000020000 +CT=4AF36BAE2660503B3248E4685059FD05 + +I=112 +PT=00000000000000000000000000010000 +CT=7D5631814DD8E917D97A0D514C743971 + +I=113 +PT=00000000000000000000000000008000 +CT=BC3352500FC0CBB9DB5B5F6B491C1BE8 + +I=114 +PT=00000000000000000000000000004000 +CT=6A4A30BA87E87AF65C90AEB7AFEDC76B + +I=115 +PT=00000000000000000000000000002000 +CT=77E6125897668AC8E73E8C79A6FF8336 + +I=116 +PT=00000000000000000000000000001000 +CT=3FA9D39104EBB323C7AAAA248960DD1E + +I=117 +PT=00000000000000000000000000000800 +CT=FAD75AD76AB10ADC49036B250E229D39 + +I=118 +PT=00000000000000000000000000000400 +CT=2FACAA5FE35B228A16AC74088D702EC4 + +I=119 +PT=00000000000000000000000000000200 +CT=88B6CBCFDFEF8AD91720A1BB69A1F33E + +I=120 +PT=00000000000000000000000000000100 +CT=C7E9D250998632D444356242EF04058D + +I=121 +PT=00000000000000000000000000000080 +CT=B14DAD8D3D9153F46C0D3A1AD63C7A05 + +I=122 +PT=00000000000000000000000000000040 +CT=60ABA678A506608D0845966D29B5F790 + +I=123 +PT=00000000000000000000000000000020 +CT=482DC43F2388EF25D24144E144BD834E + +I=124 +PT=00000000000000000000000000000010 +CT=1490A05A7CEE43BDE98B56E309DC0126 + +I=125 +PT=00000000000000000000000000000008 +CT=ABFA77CD6E85DA245FB0BDC5E52CFC29 + +I=126 +PT=00000000000000000000000000000004 +CT=DD4AB1284D4AE17B41E85924470C36F7 + +I=127 +PT=00000000000000000000000000000002 +CT=CEA7403D4D606B6E074EC5D3BAF39D18 + +I=128 +PT=00000000000000000000000000000001 +CT=530F8AFBC74536B9A963B4F1C4CB738B + +========== \ No newline at end of file diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/test/katmct.pdf b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/katmct.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b494fb53716f92bdc6ca762cd5689493eb0bdc56 GIT binary patch literal 100812 zcmc%PRZv{P*C={)f@g3ixH~i00Kwhe0}SqNfdn1gU4y&3ySux4(BKJ#@rke%Slhy_-%|Qksp6otqL9jqc!Zb`cZpUnD@uN$F%}i-{&Ago(zX zXyIt(ZcWL>`7f*fuPtq3?{48r$)TvPBWVG3GPn45hlmI!nwz_;g{cE3S^zLIU_N}w zlARO6^b6DwQtBoytrgR-Uv5Pi}`75GSJ9=K84PQ19Y3p5Jzr$kNph>?&su;(TysnV6D z2mKXKweW^w)YXbW&ip`hOAR7L*$9`UXaJ2%bjv3OqUf6>z4r87b;=B^ z6PGHa8YtCs(%j{vsf5FL%m-VDB3dR#VVk!=wBJ~0b&jZ!G|BY z^6%(hOSq(w9J�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 +#include +#include +#include +#include "crypto_int.h" + +#define ASIZE(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0])) + +const char *whoami; + +static void printhex (size_t len, const char *p) +{ + while (len--) + printf ("%02x", 0xff & *p++); +} + +static void printstringhex (const char *p) { printhex (strlen (p), p); } + +static void printdata (krb5_data *d) { printhex (d->length, d->data); } + +static void printkey (krb5_keyblock *k) { printhex (k->length, k->contents); } + +static void test_nfold () +{ + int i; + static const struct { + char *input; + int n; + } tests[] = { + { "012345", 64, }, + { "password", 56, }, + { "Rough Consensus, and Running Code", 64, }, + { "password", 168, }, + { "MASSACHVSETTS INSTITVTE OF TECHNOLOGY", 192 }, + { "Q", 168 }, + { "ba", 168 }, + }; + unsigned char outbuf[192/8]; + + for (i = 0; i < ASIZE (tests); i++) { + char *p = tests[i].input; + assert (tests[i].n / 8 <= sizeof (outbuf)); + printf ("%d-fold(\"%s\") =\n", tests[i].n, p); + printf ("%d-fold(", tests[i].n); + printstringhex (p); + printf (") =\n\t"); + krb5int_nfold (8 * strlen (p), p, tests[i].n, outbuf); + printhex (tests[i].n / 8U, outbuf); + printf ("\n\n"); + } +} + +#define JURISIC "Juri\305\241i\304\207" /* hi Miro */ +#define ESZETT "\303\237" +#define GCLEF "\360\235\204\236" /* outside BMP, woo hoo! */ + +/* Some weak keys: + {0x1f,0x1f,0x1f,0x1f,0x0e,0x0e,0x0e,0x0e}, + {0xe0,0xe0,0xe0,0xe0,0xf1,0xf1,0xf1,0xf1}, + so try to generate them. */ + +static void +test_mit_des_s2k () +{ + static const struct { + const char *pass; + const char *salt; + } pairs[] = { + { "password", "ATHENA.MIT.EDUraeburn" }, + { "potatoe", "WHITEHOUSE.GOVdanny" }, + { "penny", "EXAMPLE.COMbuckaroo", }, + { GCLEF, "EXAMPLE.COMpianist" }, + { ESZETT, "ATHENA.MIT.EDU" JURISIC }, + /* These two trigger weak-key fixups. */ + { "11119999", "AAAAAAAA" }, + { "NNNN6666", "FFFFAAAA" }, + }; + int i; + + for (i = 0; i < ASIZE (pairs); i++) { + const char *p = pairs[i].pass; + const char *s = pairs[i].salt; + krb5_data pd; + krb5_data sd; + unsigned char key_contents[60]; + krb5_keyblock key; + krb5_error_code r; + char buf[80]; + + key.contents = key_contents; + + pd.length = strlen (p); + pd.data = (char *) p; + sd.length = strlen (s); + sd.data = (char *) s; + + assert (strlen (s) + 4 < sizeof (buf)); + snprintf (buf, sizeof (buf), "\"%s\"", s); + printf ( "salt: %-25s", buf); + printhex (strlen(s), s); + snprintf (buf, sizeof (buf), "\"%s\"", p); + printf ("\npassword: %-25s", buf); + printhex (strlen(p), p); + printf ("\n"); + r = krb5int_des_string_to_key (0, &pd, &sd, 0, &key); + printf ( "DES key: %-25s", ""); + printhex (key.length, key.contents); + printf ("\n\n"); + } +} + +static void +test_s2k (krb5_enctype enctype) +{ + static const struct { + const char *pass; + const char *salt; + } pairs[] = { + { "password", "ATHENA.MIT.EDUraeburn" }, + { "potatoe", "WHITEHOUSE.GOVdanny" }, + { "penny", "EXAMPLE.COMbuckaroo", }, + { ESZETT, "ATHENA.MIT.EDU" JURISIC }, + { GCLEF, "EXAMPLE.COMpianist" }, + }; + int i; + + for (i = 0; i < ASIZE (pairs); i++) { + const char *p = pairs[i].pass; + const char *s = pairs[i].salt; + krb5_data pd, sd; + unsigned char key_contents[60]; + krb5_keyblock key; + krb5_error_code r; + char buf[80]; + + pd.length = strlen (p); + pd.data = (char *) p; + sd.length = strlen (s); + sd.data = (char *) s; + key.contents = key_contents; + + assert (strlen (s) + 4 < sizeof (buf)); + snprintf (buf, sizeof(buf), "\"%s\"", s); + printf ( "salt:\t%s\n\t", buf); + printhex (strlen(s), s); + snprintf (buf, sizeof(buf), "\"%s\"", p); + printf ("\npasswd:\t%s\n\t", buf); + printhex (strlen(p), p); + printf ("\n"); + r = krb5_c_string_to_key (0, enctype, &pd, &sd, &key); + printf ( "key:\t"); + printhex (key.length, key.contents); + printf ("\n\n"); + } +} + +static void test_des3_s2k () { test_s2k (ENCTYPE_DES3_CBC_SHA1); } + +static void +keyToData (krb5_keyblock *k, krb5_data *d) +{ + d->length = k->length; + d->data = k->contents; +} + +void check_error (int r, int line) { + if (r != 0) { + fprintf (stderr, "%s:%d: %s\n", __FILE__, line, + error_message (r)); + exit (1); + } +} +#define CHECK check_error(r, __LINE__) + +extern struct krb5_enc_provider krb5int_enc_des3; +struct krb5_enc_provider *enc = &krb5int_enc_des3; +extern struct krb5_enc_provider krb5int_enc_aes128, krb5int_enc_aes256; + +void DK (krb5_keyblock *out, krb5_keyblock *in, const krb5_data *usage) { + krb5_error_code r; + r = krb5int_derive_key (enc, in, out, usage, DERIVE_RFC3961); + CHECK; +} + +void DR (krb5_data *out, krb5_keyblock *in, const krb5_data *usage) { + krb5_error_code r; + r = krb5int_derive_random (enc, in, out, usage, DERIVE_RFC3961); + CHECK; +} + +#define KEYBYTES 21 +#define KEYLENGTH 24 + +void test_dr_dk () +{ + static const struct { + unsigned char keydata[KEYLENGTH]; + int usage_len; + unsigned char usage[8]; + } derive_tests[] = { + { + { + 0xdc, 0xe0, 0x6b, 0x1f, 0x64, 0xc8, 0x57, 0xa1, + 0x1c, 0x3d, 0xb5, 0x7c, 0x51, 0x89, 0x9b, 0x2c, + 0xc1, 0x79, 0x10, 0x08, 0xce, 0x97, 0x3b, 0x92, + }, + 5, { 0x00, 0x00, 0x00, 0x01, 0x55 }, + }, + { + { + 0x5e, 0x13, 0xd3, 0x1c, 0x70, 0xef, 0x76, 0x57, + 0x46, 0x57, 0x85, 0x31, 0xcb, 0x51, 0xc1, 0x5b, + 0xf1, 0x1c, 0xa8, 0x2c, 0x97, 0xce, 0xe9, 0xf2, + }, + 5, { 0x00, 0x00, 0x00, 0x01, 0xaa }, + }, + { + { + 0x98, 0xe6, 0xfd, 0x8a, 0x04, 0xa4, 0xb6, 0x85, + 0x9b, 0x75, 0xa1, 0x76, 0x54, 0x0b, 0x97, 0x52, + 0xba, 0xd3, 0xec, 0xd6, 0x10, 0xa2, 0x52, 0xbc, + }, + 5, { 0x00, 0x00, 0x00, 0x01, 0x55 }, + }, + { + { + 0x62, 0x2a, 0xec, 0x25, 0xa2, 0xfe, 0x2c, 0xad, + 0x70, 0x94, 0x68, 0x0b, 0x7c, 0x64, 0x94, 0x02, + 0x80, 0x08, 0x4c, 0x1a, 0x7c, 0xec, 0x92, 0xb5, + }, + 5, { 0x00, 0x00, 0x00, 0x01, 0xaa }, + }, + { + { + 0xd3, 0xf8, 0x29, 0x8c, 0xcb, 0x16, 0x64, 0x38, + 0xdc, 0xb9, 0xb9, 0x3e, 0xe5, 0xa7, 0x62, 0x92, + 0x86, 0xa4, 0x91, 0xf8, 0x38, 0xf8, 0x02, 0xfb, + }, + 8, { 'k', 'e', 'r', 'b', 'e', 'r', 'o', 's' }, + }, + { + { + 0xb5, 0x5e, 0x98, 0x34, 0x67, 0xe5, 0x51, 0xb3, + 0xe5, 0xd0, 0xe5, 0xb6, 0xc8, 0x0d, 0x45, 0x76, + 0x94, 0x23, 0xa8, 0x73, 0xdc, 0x62, 0xb3, 0x0e, + }, + 7, { 'c', 'o', 'm', 'b', 'i', 'n', 'e', }, + }, + { + { + 0xc1, 0x08, 0x16, 0x49, 0xad, 0xa7, 0x43, 0x62, + 0xe6, 0xa1, 0x45, 0x9d, 0x01, 0xdf, 0xd3, 0x0d, + 0x67, 0xc2, 0x23, 0x4c, 0x94, 0x07, 0x04, 0xda, + }, + 5, { 0x00, 0x00, 0x00, 0x01, 0x55 }, + }, + { + { + 0x5d, 0x15, 0x4a, 0xf2, 0x38, 0xf4, 0x67, 0x13, + 0x15, 0x57, 0x19, 0xd5, 0x5e, 0x2f, 0x1f, 0x79, + 0x0d, 0xd6, 0x61, 0xf2, 0x79, 0xa7, 0x91, 0x7c, + }, + 5, { 0x00, 0x00, 0x00, 0x01, 0xaa }, + }, + { + { + 0x79, 0x85, 0x62, 0xe0, 0x49, 0x85, 0x2f, 0x57, + 0xdc, 0x8c, 0x34, 0x3b, 0xa1, 0x7f, 0x2c, 0xa1, + 0xd9, 0x73, 0x94, 0xef, 0xc8, 0xad, 0xc4, 0x43, + }, + 5, { 0x00, 0x00, 0x00, 0x01, 0x55 }, + }, + { + { + 0x26, 0xdc, 0xe3, 0x34, 0xb5, 0x45, 0x29, 0x2f, + 0x2f, 0xea, 0xb9, 0xa8, 0x70, 0x1a, 0x89, 0xa4, + 0xb9, 0x9e, 0xb9, 0x94, 0x2c, 0xec, 0xd0, 0x16, + }, + 5, { 0x00, 0x00, 0x00, 0x01, 0xaa }, + }, + }; + int i; + + for (i = 0; i < ASIZE(derive_tests); i++) { +#define D (derive_tests[i]) + krb5_keyblock key; + krb5_data usage; + + unsigned char drData[KEYBYTES]; + krb5_data dr; + unsigned char dkData[KEYLENGTH]; + krb5_keyblock dk; + + key.length = KEYLENGTH, key.contents = D.keydata; + usage.length = D.usage_len, usage.data = D.usage; + dr.length = KEYBYTES, dr.data = drData; + dk.length = KEYLENGTH, dk.contents = dkData; + + printf ("key:\t"); printkey (&key); printf ("\n"); + printf ("usage:\t"); printdata (&usage); printf ("\n"); + DR (&dr, &key, &usage); + printf ("DR:\t"); printdata (&dr); printf ("\n"); + DK (&dk, &key, &usage); + printf ("DK:\t"); printkey (&dk); printf ("\n\n"); + } +} + + +static void printd (const char *descr, krb5_data *d) { + int i, j; + const int r = 16; + + printf("%s:", descr); + + for (i = 0; i < d->length; i += r) { + printf("\n %04x: ", i); + for (j = i; j < i + r && j < d->length; j++) + printf(" %02x", 0xff & d->data[j]); + for (; j < i + r; j++) + printf(" "); + printf(" "); + for (j = i; j < i + r && j < d->length; j++) { + int c = 0xff & d->data[j]; + printf("%c", isprint(c) ? c : '.'); + } + } + printf("\n"); +} +static void printk(const char *descr, krb5_keyblock *k) { + krb5_data d; + d.data = k->contents; + d.length = k->length; + printd(descr, &d); +} + + +static void +test_pbkdf2() +{ + static struct { + int count; + char *pass; + char *salt; + } test[] = { + { 1, "password", "ATHENA.MIT.EDUraeburn" }, + { 2, "password", "ATHENA.MIT.EDUraeburn" }, + { 1200, "password", "ATHENA.MIT.EDUraeburn" }, + { 5, "password", "\x12\x34\x56\x78\x78\x56\x34\x12" }, + { 1200, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "pass phrase equals block size" }, + { 1200, + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", + "pass phrase exceeds block size" }, + { 50, "\xf0\x9d\x84\x9e", "EXAMPLE.COMpianist" }, + }; + unsigned char x[100]; + unsigned char x2[100]; + int j; + krb5_error_code err; + krb5_data d; + krb5_keyblock k, dk; + krb5_data usage, pass, salt; + + d.data = x; + dk.contents = x2; + + usage.data = "kerberos"; + usage.length = 8; + + for (j = 0; j < sizeof(test)/sizeof(test[0]); j++) { + printf("pkbdf2(count=%d, pass=\"%s\", salt=", + test[j].count, test[j].pass); + if (isprint(test[j].salt[0])) + printf("\"%s\")\n", test[j].salt); + else { + char *s = test[j].salt; + printf("0x"); + while (*s) + printf("%02X", 0xff & *s++); + printf(")\n"); + } + + d.length = 16; + pass.data = test[j].pass; + pass.length = strlen(pass.data); + salt.data = test[j].salt; + salt.length = strlen(salt.data); + err = krb5int_pbkdf2_hmac_sha1 (&d, test[j].count, &pass, &salt); + printd("128-bit PBKDF2 output", &d); + enc = &krb5int_enc_aes128; + k.contents = d.data; + k.length = d.length; + dk.length = d.length; + DK (&dk, &k, &usage); + printk("128-bit AES key",&dk); + + d.length = 32; + err = krb5int_pbkdf2_hmac_sha1 (&d, test[j].count, &pass, &salt); + printd("256-bit PBKDF2 output", &d); + enc = &krb5int_enc_aes256; + k.contents = d.data; + k.length = d.length; + dk.length = d.length; + DK (&dk, &k, &usage); + printk("256-bit AES key", &dk); + + printf("\n"); + } +} + +int main (int argc, char **argv) +{ + whoami = argv[0]; + test_nfold (); + test_pbkdf2(); + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/deps b/krb5-1.21.3/src/lib/crypto/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/lib/crypto/krb/Makefile.in b/krb5-1.21.3/src/lib/crypto/krb/Makefile.in new file mode 100644 index 00000000..cb2e40a3 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/Makefile.in @@ -0,0 +1,188 @@ +mydir=lib$(S)crypto$(S)krb +BUILDTOP=$(REL)..$(S)..$(S).. + +##DOS##BUILDTOP = ..\..\.. +##DOS##PREFIXDIR = krb +##DOS##OBJFILE = ..\$(OUTPRE)krb.lst + +STLIBOBJS=\ + aead.o \ + block_size.o \ + cf2.o \ + checksum_dk_cmac.o \ + checksum_dk_hmac.o \ + checksum_etm.o \ + checksum_hmac_md5.o \ + checksum_unkeyed.o \ + checksum_length.o \ + cksumtype_to_string.o \ + cksumtypes.o \ + coll_proof_cksum.o \ + crypto_length.o \ + default_state.o \ + decrypt.o \ + decrypt_iov.o \ + derive.o \ + encrypt.o \ + encrypt_iov.o \ + encrypt_length.o \ + enctype_util.o \ + enc_dk_cmac.o \ + enc_dk_hmac.o \ + enc_etm.o \ + enc_raw.o \ + enc_rc4.o \ + etypes.o \ + key.o \ + keyblocks.o \ + keyed_cksum.o \ + keyed_checksum_types.o \ + keylengths.o \ + make_checksum.o \ + make_checksum_iov.o \ + make_random_key.o \ + mandatory_sumtype.o \ + nfold.o \ + old_api_glue.o \ + prf.o \ + prf_aes2.o \ + prf_cmac.o \ + prf_des.o \ + prf_dk.o \ + prf_rc4.o \ + prng.o \ + random_to_key.o \ + s2k_pbkdf2.o \ + s2k_rc4.o \ + state.o \ + string_to_cksumtype.o \ + string_to_key.o \ + valid_cksumtype.o \ + verify_checksum.o \ + verify_checksum_iov.o + +OBJS=\ + $(OUTPRE)aead.$(OBJEXT) \ + $(OUTPRE)block_size.$(OBJEXT) \ + $(OUTPRE)cf2.$(OBJEXT) \ + $(OUTPRE)checksum_dk_cmac.$(OBJEXT) \ + $(OUTPRE)checksum_dk_hmac.$(OBJEXT) \ + $(OUTPRE)checksum_etm.$(OBJEXT) \ + $(OUTPRE)checksum_hmac_md5.$(OBJEXT) \ + $(OUTPRE)checksum_unkeyed.$(OBJEXT) \ + $(OUTPRE)checksum_length.$(OBJEXT) \ + $(OUTPRE)cksumtype_to_string.$(OBJEXT) \ + $(OUTPRE)cksumtypes.$(OBJEXT) \ + $(OUTPRE)coll_proof_cksum.$(OBJEXT) \ + $(OUTPRE)crypto_length.$(OBJEXT) \ + $(OUTPRE)default_state.$(OBJEXT) \ + $(OUTPRE)decrypt.$(OBJEXT) \ + $(OUTPRE)decrypt_iov.$(OBJEXT) \ + $(OUTPRE)derive.$(OBJEXT) \ + $(OUTPRE)encrypt.$(OBJEXT) \ + $(OUTPRE)encrypt_iov.$(OBJEXT) \ + $(OUTPRE)encrypt_length.$(OBJEXT) \ + $(OUTPRE)enctype_util.$(OBJEXT) \ + $(OUTPRE)enc_dk_cmac.$(OBJEXT) \ + $(OUTPRE)enc_dk_hmac.$(OBJEXT) \ + $(OUTPRE)enc_etm.$(OBJEXT) \ + $(OUTPRE)enc_raw.$(OBJEXT) \ + $(OUTPRE)enc_rc4.$(OBJEXT) \ + $(OUTPRE)etypes.$(OBJEXT) \ + $(OUTPRE)key.$(OBJEXT) \ + $(OUTPRE)keyblocks.$(OBJEXT) \ + $(OUTPRE)keyed_cksum.$(OBJEXT) \ + $(OUTPRE)keyed_checksum_types.$(OBJEXT) \ + $(OUTPRE)keylengths.$(OBJEXT) \ + $(OUTPRE)make_checksum.$(OBJEXT) \ + $(OUTPRE)make_checksum_iov.$(OBJEXT) \ + $(OUTPRE)make_random_key.$(OBJEXT) \ + $(OUTPRE)mandatory_sumtype.$(OBJEXT) \ + $(OUTPRE)nfold.$(OBJEXT) \ + $(OUTPRE)old_api_glue.$(OBJEXT) \ + $(OUTPRE)prf.$(OBJEXT) \ + $(OUTPRE)prf_aes2.$(OBJEXT) \ + $(OUTPRE)prf_cmac.$(OBJEXT) \ + $(OUTPRE)prf_des.$(OBJEXT) \ + $(OUTPRE)prf_dk.$(OBJEXT) \ + $(OUTPRE)prf_rc4.$(OBJEXT) \ + $(OUTPRE)prng.$(OBJEXT) \ + $(OUTPRE)random_to_key.$(OBJEXT) \ + $(OUTPRE)s2k_pbkdf2.$(OBJEXT) \ + $(OUTPRE)s2k_rc4.$(OBJEXT) \ + $(OUTPRE)state.$(OBJEXT) \ + $(OUTPRE)string_to_cksumtype.$(OBJEXT) \ + $(OUTPRE)string_to_key.$(OBJEXT) \ + $(OUTPRE)valid_cksumtype.$(OBJEXT) \ + $(OUTPRE)verify_checksum.$(OBJEXT) \ + $(OUTPRE)verify_checksum_iov.$(OBJEXT) + +SRCS=\ + $(srcdir)/aead.c \ + $(srcdir)/block_size.c \ + $(srcdir)/cf2.c \ + $(srcdir)/checksum_dk_cmac.c \ + $(srcdir)/checksum_dk_hmac.c \ + $(srcdir)/checksum_etm.c \ + $(srcdir)/checksum_hmac_md5.c \ + $(srcdir)/checksum_unkeyed.c \ + $(srcdir)/checksum_length.c \ + $(srcdir)/cksumtype_to_string.c \ + $(srcdir)/cksumtypes.c \ + $(srcdir)/coll_proof_cksum.c \ + $(srcdir)/crypto_length.c \ + $(srcdir)/default_state.c \ + $(srcdir)/decrypt.c \ + $(srcdir)/decrypt_iov.c \ + $(srcdir)/derive.c \ + $(srcdir)/encrypt.c \ + $(srcdir)/encrypt_iov.c \ + $(srcdir)/encrypt_length.c \ + $(srcdir)/enctype_util.c \ + $(srcdir)/enc_dk_cmac.c \ + $(srcdir)/enc_dk_hmac.c \ + $(srcdir)/enc_etm.c \ + $(srcdir)/enc_raw.c \ + $(srcdir)/enc_rc4.c \ + $(srcdir)/etypes.c \ + $(srcdir)/key.c \ + $(srcdir)/keyblocks.c \ + $(srcdir)/keyed_cksum.c \ + $(srcdir)/keyed_checksum_types.c\ + $(srcdir)/keylengths.c \ + $(srcdir)/make_checksum.c \ + $(srcdir)/make_checksum_iov.c \ + $(srcdir)/make_random_key.c \ + $(srcdir)/mandatory_sumtype.c \ + $(srcdir)/nfold.c \ + $(srcdir)/old_api_glue.c \ + $(srcdir)/prf.c \ + $(srcdir)/prf_aes2.c \ + $(srcdir)/prf_cmac.c \ + $(srcdir)/prf_des.c \ + $(srcdir)/prf_dk.c \ + $(srcdir)/prf_rc4.c \ + $(srcdir)/prng.c \ + $(srcdir)/cf2.c \ + $(srcdir)/random_to_key.c \ + $(srcdir)/s2k_pbkdf2.c \ + $(srcdir)/s2k_rc4.c \ + $(srcdir)/state.c \ + $(srcdir)/string_to_cksumtype.c \ + $(srcdir)/string_to_key.c \ + $(srcdir)/valid_cksumtype.c \ + $(srcdir)/verify_checksum.c \ + $(srcdir)/verify_checksum_iov.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs +includes: depend + +depend: $(SRCS) + +clean-unix:: clean-libobjs + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/krb/aead.c b/krb5-1.21.3/src/lib/crypto/krb/aead.c new file mode 100644 index 00000000..9d4e206a --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/aead.c @@ -0,0 +1,223 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/aead.c */ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_crypto_iov * +krb5int_c_locate_iov(krb5_crypto_iov *data, size_t num_data, + krb5_cryptotype type) +{ + size_t i; + krb5_crypto_iov *iov = NULL; + + if (data == NULL) + return NULL; + + for (i = 0; i < num_data; i++) { + if (data[i].flags == type) { + if (iov == NULL) + iov = &data[i]; + else + return NULL; /* can't appear twice */ + } + } + + return iov; +} + +krb5_error_code +krb5int_c_iov_decrypt_stream(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage keyusage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + krb5_error_code ret; + unsigned int header_len, trailer_len; + krb5_crypto_iov *iov; + krb5_crypto_iov *stream; + size_t i, j; + int got_data = 0; + + stream = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_STREAM); + assert(stream != NULL); + + header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER); + trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + + if (stream->data.length < header_len + trailer_len) + return KRB5_BAD_MSIZE; + + iov = calloc(num_data + 2, sizeof(krb5_crypto_iov)); + if (iov == NULL) + return ENOMEM; + + i = 0; + + iov[i].flags = KRB5_CRYPTO_TYPE_HEADER; /* takes place of STREAM */ + iov[i].data = make_data(stream->data.data, header_len); + i++; + + for (j = 0; j < num_data; j++) { + if (data[j].flags == KRB5_CRYPTO_TYPE_DATA) { + if (got_data) { + free(iov); + return KRB5_BAD_MSIZE; + } + + got_data++; + + data[j].data.data = stream->data.data + header_len; + data[j].data.length = stream->data.length - header_len + - trailer_len; + } + if (data[j].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY || + data[j].flags == KRB5_CRYPTO_TYPE_DATA) + iov[i++] = data[j]; + } + + /* Use empty padding since tokens don't indicate the padding length. */ + iov[i].flags = KRB5_CRYPTO_TYPE_PADDING; + iov[i].data = empty_data(); + i++; + + iov[i].flags = KRB5_CRYPTO_TYPE_TRAILER; + iov[i].data = make_data(stream->data.data + stream->data.length - + trailer_len, trailer_len); + i++; + + assert(i <= num_data + 2); + + ret = ktp->decrypt(ktp, key, keyusage, ivec, iov, i); + free(iov); + return ret; +} + +unsigned int +krb5int_c_padding_length(const struct krb5_keytypes *ktp, size_t data_length) +{ + unsigned int header, padding; + + /* + * Add in the header length since the header is encrypted along with the + * data. (arcfour violates this assumption since not all of the header is + * encrypted, but that's okay since it has no padding. If there is ever an + * enctype using a similar token format and a block cipher, we will have to + * move this logic into an enctype-dependent function.) + */ + header = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER); + data_length += header; + + padding = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING); + if (padding == 0 || (data_length % padding) == 0) + return 0; + else + return padding - (data_length % padding); +} + +/* Return the next iov (starting from ind) which cursor should process, or + * cursor->iov_count if there are none remaining. */ +static size_t +next_iov_to_process(struct iov_cursor *cursor, size_t ind) +{ + const krb5_crypto_iov *iov; + + for (; ind < cursor->iov_count; ind++) { + iov = &cursor->iov[ind]; + if (cursor->signing ? SIGN_IOV(iov) : ENCRYPT_IOV(iov)) + break; + } + return ind; +} + +void +k5_iov_cursor_init(struct iov_cursor *cursor, const krb5_crypto_iov *iov, + size_t count, size_t block_size, krb5_boolean signing) +{ + cursor->iov = iov; + cursor->iov_count = count; + cursor->block_size = block_size; + cursor->signing = signing; + cursor->in_iov = next_iov_to_process(cursor, 0); + cursor->out_iov = cursor->in_iov; + cursor->in_pos = cursor->out_pos = 0; +} + +/* Fetch one block from cursor's input position. */ +krb5_boolean +k5_iov_cursor_get(struct iov_cursor *cursor, unsigned char *block) +{ + size_t nbytes, bsz = cursor->block_size, remain = cursor->block_size; + const krb5_crypto_iov *iov; + + remain = cursor->block_size; + while (remain > 0 && cursor->in_iov < cursor->iov_count) { + iov = &cursor->iov[cursor->in_iov]; + + nbytes = iov->data.length - cursor->in_pos; + if (nbytes > remain) + nbytes = remain; + + memcpy(block + bsz - remain, iov->data.data + cursor->in_pos, nbytes); + cursor->in_pos += nbytes; + remain -= nbytes; + + if (cursor->in_pos == iov->data.length) { + cursor->in_iov = next_iov_to_process(cursor, cursor->in_iov + 1); + cursor->in_pos = 0; + } + } + + if (remain == bsz) + return FALSE; + if (remain > 0) + memset(block + bsz - remain, 0, remain); + return TRUE; +} + +/* Write a block to a cursor's output position. */ +void +k5_iov_cursor_put(struct iov_cursor *cursor, unsigned char *block) +{ + size_t nbytes, bsz = cursor->block_size, remain = cursor->block_size; + const krb5_crypto_iov *iov; + + remain = cursor->block_size; + while (remain > 0 && cursor->out_iov < cursor->iov_count) { + iov = &cursor->iov[cursor->out_iov]; + + nbytes = iov->data.length - cursor->out_pos; + if (nbytes > remain) + nbytes = remain; + + memcpy(iov->data.data + cursor->out_pos, block + bsz - remain, nbytes); + cursor->out_pos += nbytes; + remain -= nbytes; + + if (cursor->out_pos == iov->data.length) { + cursor->out_iov = next_iov_to_process(cursor, cursor->out_iov + 1); + cursor->out_pos = 0; + } + } +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/block_size.c b/krb5-1.21.3/src/lib/crypto/krb/block_size.c new file mode 100644 index 00000000..d50c9446 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/block_size.c @@ -0,0 +1,42 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_block_size(krb5_context context, krb5_enctype enctype, + size_t *blocksize) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + *blocksize = ktp->enc->block_size; + + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/cf2.c b/krb5-1.21.3/src/lib/crypto/krb/cf2.c new file mode 100644 index 00000000..2ee5aebd --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/cf2.c @@ -0,0 +1,176 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/cf2.c */ +/* + * Copyright (C) 2009, 2015 by the Massachusetts Institute of Technology. All + * rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Implement KRB_FX_CF2 function per draft-ietf-krb-wg-preauth-framework-09. + * Take two keys and two pepper strings as input and return a combined key. + */ + +#include "crypto_int.h" + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +krb5_error_code KRB5_CALLCONV +krb5_c_prfplus(krb5_context context, const krb5_keyblock *k, + const krb5_data *input, krb5_data *output) +{ + krb5_error_code ret; + krb5_data prf_in = empty_data(), prf_out = empty_data(); + size_t prflen, nblocks, i; + + /* Calculate the number of PRF invocations we will need. */ + ret = krb5_c_prf_length(context, k->enctype, &prflen); + if (ret) + return ret; + nblocks = (output->length + prflen - 1)/ prflen; + if (nblocks > 255) + return E2BIG; + + /* Allocate PRF input and output buffers. */ + ret = alloc_data(&prf_in, input->length + 1); + if (ret) + goto cleanup; + ret = alloc_data(&prf_out, prflen); + if (ret) + goto cleanup; + + /* Concatenate PRF(k, 1||input) || PRF(k, 2||input) || ... to produce the + * desired number of bytes. */ + memcpy(&prf_in.data[1], input->data, input->length); + for (i = 0; i < nblocks; i++) { + prf_in.data[0] = i + 1; + ret = krb5_c_prf(context, k, &prf_in, &prf_out); + if (ret) + goto cleanup; + + memcpy(&output->data[i * prflen], prf_out.data, + MIN(prflen, output->length - i * prflen)); + } + +cleanup: + zapfree(prf_out.data, prf_out.length); + zapfree(prf_in.data, prf_in.length); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_derive_prfplus(krb5_context context, const krb5_keyblock *k, + const krb5_data *input, krb5_enctype enctype, + krb5_keyblock **out) +{ + krb5_error_code ret; + const struct krb5_keytypes *ktp; + krb5_data rnd = empty_data(); + krb5_keyblock *kb = NULL; + + *out = NULL; + + ktp = find_enctype((enctype == ENCTYPE_NULL) ? k->enctype : enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + /* Generate enough pseudo-random bytes for the random-to-key function. */ + ret = alloc_data(&rnd, ktp->enc->keybytes); + if (ret) + goto cleanup; + ret = krb5_c_prfplus(context, k, input, &rnd); + if (ret) + goto cleanup; + + /* Generate a key from the pseudo-random bytes. */ + ret = krb5int_c_init_keyblock(context, ktp->etype, ktp->enc->keylength, + &kb); + if (ret) + goto cleanup; + ret = (*ktp->rand2key)(&rnd, kb); + if (ret) + goto cleanup; + + *out = kb; + kb = NULL; + +cleanup: + zapfree(rnd.data, rnd.length); + krb5int_c_free_keyblock(context, kb); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_fx_cf2_simple(krb5_context context, + const krb5_keyblock *k1, const char *pepper1, + const krb5_keyblock *k2, const char *pepper2, + krb5_keyblock **out) +{ + krb5_error_code ret; + const struct krb5_keytypes *ktp = NULL; + const krb5_data pepper1_data = string2data((char *)pepper1); + const krb5_data pepper2_data = string2data((char *)pepper2); + krb5_data prf1 = empty_data(), prf2 = empty_data(); + unsigned int i; + krb5_keyblock *kb = NULL; + + *out = NULL; + + ktp = find_enctype(k1->enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + /* Generate PRF+(k1, pepper1) and PRF+(k2, kepper2). */ + ret = alloc_data(&prf1, ktp->enc->keybytes); + if (ret) + goto cleanup; + ret = krb5_c_prfplus(context, k1, &pepper1_data, &prf1); + if (ret) + goto cleanup; + ret = alloc_data(&prf2, ktp->enc->keybytes); + if (ret) + goto cleanup; + ret = krb5_c_prfplus(context, k2, &pepper2_data, &prf2); + if (ret) + goto cleanup; + + /* Compute the XOR of the two PRF+ values and generate a key. */ + for (i = 0; i < prf1.length; i++) + prf1.data[i] ^= prf2.data[i]; + ret = krb5int_c_init_keyblock(context, ktp->etype, ktp->enc->keylength, + &kb); + if (ret) + goto cleanup; + ret = (*ktp->rand2key)(&prf1, kb); + if (ret) + goto cleanup; + + *out = kb; + kb = NULL; + +cleanup: + zapfree(prf2.data, prf2.length); + zapfree(prf1.data, prf1.length); + krb5int_c_free_keyblock(context, kb); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/checksum_dk_cmac.c b/krb5-1.21.3/src/lib/crypto/krb/checksum_dk_cmac.c new file mode 100644 index 00000000..809f9d72 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/checksum_dk_cmac.c @@ -0,0 +1,59 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/checksum_dk_cmac.c */ +/* + * Copyright 2010 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ + +krb5_error_code +krb5int_dk_cmac_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + const struct krb5_enc_provider *enc = ctp->enc; + krb5_error_code ret; + unsigned char constantdata[K5CLENGTH]; + krb5_data datain; + krb5_key kc; + + /* Derive the key. */ + datain = make_data(constantdata, K5CLENGTH); + store_32_be(usage, constantdata); + constantdata[4] = (char) 0x99; + ret = krb5int_derive_key(enc, NULL, key, &kc, &datain, + DERIVE_SP800_108_CMAC); + if (ret != 0) + return ret; + + /* Hash the data. */ + ret = krb5int_cmac_checksum(enc, kc, data, num_data, output); + if (ret != 0) + memset(output->data, 0, output->length); + + krb5_k_free_key(NULL, kc); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/checksum_dk_hmac.c b/krb5-1.21.3/src/lib/crypto/krb/checksum_dk_hmac.c new file mode 100644 index 00000000..64ab8993 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/checksum_dk_hmac.c @@ -0,0 +1,59 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ + +krb5_error_code +krb5int_dk_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + const struct krb5_enc_provider *enc = ctp->enc; + krb5_error_code ret; + unsigned char constantdata[K5CLENGTH]; + krb5_data datain; + krb5_key kc; + + /* Derive the key. */ + datain = make_data(constantdata, K5CLENGTH); + store_32_be(usage, constantdata); + constantdata[4] = (char) 0x99; + ret = krb5int_derive_key(enc, NULL, key, &kc, &datain, DERIVE_RFC3961); + if (ret) + return ret; + + /* Hash the data. */ + ret = krb5int_hmac(ctp->hash, kc, data, num_data, output); + if (ret) + memset(output->data, 0, output->length); + + krb5_k_free_key(NULL, kc); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/checksum_etm.c b/krb5-1.21.3/src/lib/crypto/krb/checksum_etm.c new file mode 100644 index 00000000..eaa85b2d --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/checksum_etm.c @@ -0,0 +1,65 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/checksum_etm.c - checksum for encrypt-then-mac enctypes */ +/* + * Copyright (C) 2015 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. + */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_etm_checksum(const struct krb5_cksumtypes *ctp, krb5_key key, + krb5_keyusage usage, const krb5_crypto_iov *data, + size_t num_data, krb5_data *output) +{ + krb5_error_code ret; + uint8_t label[5]; + krb5_data label_data = make_data(label, 5), kc = empty_data(); + krb5_keyblock kb = { 0 }; + + /* Derive the checksum key. */ + store_32_be(usage, label); + label[4] = 0x99; + label_data = make_data(label, 5); + ret = alloc_data(&kc, ctp->hash->hashsize / 2); + if (ret) + goto cleanup; + ret = krb5int_derive_random(ctp->enc, ctp->hash, key, &kc, &label_data, + DERIVE_SP800_108_HMAC); + if (ret) + goto cleanup; + + /* Compute an HMAC with kc over the data. */ + kb.length = kc.length; + kb.contents = (uint8_t *)kc.data; + ret = krb5int_hmac_keyblock(ctp->hash, &kb, data, num_data, output); + +cleanup: + zapfree(kc.data, kc.length); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/checksum_hmac_md5.c b/krb5-1.21.3/src/lib/crypto/krb/checksum_hmac_md5.c new file mode 100644 index 00000000..ec024f39 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/checksum_hmac_md5.c @@ -0,0 +1,94 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/checksum_hmac_md5.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Microsoft HMAC-MD5 and MD5-HMAC checksums (see RFC 4757): + * HMAC(KS, hash(msusage || input)) + * KS is HMAC(key, "signaturekey\0") for HMAC-MD5, or just the key for + * MD5-HMAC. + */ + +#include "crypto_int.h" + +krb5_error_code krb5int_hmacmd5_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output) +{ + krb5_keyusage ms_usage; + krb5_error_code ret; + krb5_keyblock ks, *keyblock; + krb5_crypto_iov *hash_iov = NULL, iov; + krb5_data ds = empty_data(), hashval = empty_data(); + char t[4]; + + if (key == NULL || key->keyblock.length > ctp->hash->blocksize) + return KRB5_BAD_ENCTYPE; + if (ctp->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR) { + /* Compute HMAC(key, "signaturekey\0") to get the signing key ks. */ + ret = alloc_data(&ds, ctp->hash->hashsize); + if (ret != 0) + goto cleanup; + + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data("signaturekey", 13); + ret = krb5int_hmac(ctp->hash, key, &iov, 1, &ds); + if (ret) + goto cleanup; + ks.length = ds.length; + ks.contents = (krb5_octet *) ds.data; + keyblock = &ks; + } else /* For md5-hmac, just use the key. */ + keyblock = &key->keyblock; + + /* Compute the MD5 value of the input. */ + ms_usage = krb5int_arcfour_translate_usage(usage); + store_32_le(ms_usage, t); + hash_iov = k5calloc(num_data + 1, sizeof(krb5_crypto_iov), &ret); + if (hash_iov == NULL) + goto cleanup; + hash_iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + hash_iov[0].data = make_data(t, 4); + memcpy(hash_iov + 1, data, num_data * sizeof(krb5_crypto_iov)); + ret = alloc_data(&hashval, ctp->hash->hashsize); + if (ret != 0) + goto cleanup; + ret = ctp->hash->hash(hash_iov, num_data + 1, &hashval); + if (ret != 0) + goto cleanup; + + /* Compute HMAC(ks, md5value). */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = hashval; + ret = krb5int_hmac_keyblock(ctp->hash, keyblock, &iov, 1, output); + +cleanup: + zapfree(ds.data, ds.length); + zapfree(hashval.data, hashval.length); + free(hash_iov); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/checksum_length.c b/krb5-1.21.3/src/lib/crypto/krb/checksum_length.c new file mode 100644 index 00000000..d4071e10 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/checksum_length.c @@ -0,0 +1,42 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_checksum_length(krb5_context context, krb5_cksumtype cksumtype, + size_t *length) +{ + const struct krb5_cksumtypes *ctp; + + ctp = find_cksumtype(cksumtype); + if (ctp == NULL) + return KRB5_BAD_ENCTYPE; + + *length = ctp->output_size; + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/checksum_unkeyed.c b/krb5-1.21.3/src/lib/crypto/krb/checksum_unkeyed.c new file mode 100644 index 00000000..ff4f2b46 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/checksum_unkeyed.c @@ -0,0 +1,36 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/checksum_unkeyed.c - Unkeyed checksum handler */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_unkeyed_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + return ctp->hash->hash(data, num_data, output); +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/cksumtype_to_string.c b/krb5-1.21.3/src/lib/crypto/krb/cksumtype_to_string.c new file mode 100644 index 00000000..758940a1 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/cksumtype_to_string.c @@ -0,0 +1,42 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_cksumtype_to_string(krb5_cksumtype cksumtype, char *buffer, size_t buflen) +{ + const struct krb5_cksumtypes *ctp; + + ctp = find_cksumtype(cksumtype); + if (ctp == NULL) + return KRB5_BAD_ENCTYPE; + + if (strlcpy(buffer, ctp->out_string, buflen) >= buflen) + return ENOMEM; + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/cksumtypes.c b/krb5-1.21.3/src/lib/crypto/krb/cksumtypes.c new file mode 100644 index 00000000..f7ba322f --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/cksumtypes.c @@ -0,0 +1,112 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +const struct krb5_cksumtypes krb5int_cksumtypes_list[] = { + { CKSUMTYPE_RSA_MD4, + "md4", { 0 }, "RSA-MD4", + NULL, &krb5int_hash_md4, + krb5int_unkeyed_checksum, NULL, + 16, 16, CKSUM_UNKEYED }, + + { CKSUMTYPE_RSA_MD5, + "md5", { 0 }, "RSA-MD5", + NULL, &krb5int_hash_md5, + krb5int_unkeyed_checksum, NULL, + 16, 16, CKSUM_UNKEYED }, + + { CKSUMTYPE_NIST_SHA, + "sha", { 0 }, "NIST-SHA", + NULL, &krb5int_hash_sha1, + krb5int_unkeyed_checksum, NULL, + 20, 20, CKSUM_UNKEYED }, + + { CKSUMTYPE_SHA1, + "sha", { 0 }, "SHA-1", + NULL, &krb5int_hash_sha1, + krb5int_unkeyed_checksum, NULL, + 20, 20, CKSUM_UNKEYED }, + + { CKSUMTYPE_HMAC_SHA1_DES3, + "hmac-sha1-des3", { "hmac-sha1-des3-kd" }, "HMAC-SHA1 DES3 key", + &krb5int_enc_des3, &krb5int_hash_sha1, + krb5int_dk_checksum, NULL, + 20, 20, 0 }, + + { CKSUMTYPE_HMAC_MD5_ARCFOUR, + "hmac-md5-rc4", { "hmac-md5-enc", "hmac-md5-earcfour" }, + "Microsoft HMAC MD5", + NULL, &krb5int_hash_md5, + krb5int_hmacmd5_checksum, NULL, + 16, 16, 0 }, + + { CKSUMTYPE_HMAC_SHA1_96_AES128, + "hmac-sha1-96-aes128", { 0 }, "HMAC-SHA1 AES128 key", + &krb5int_enc_aes128, &krb5int_hash_sha1, + krb5int_dk_checksum, NULL, + 20, 12, 0 }, + + { CKSUMTYPE_HMAC_SHA1_96_AES256, + "hmac-sha1-96-aes256", { 0 }, "HMAC-SHA1 AES256 key", + &krb5int_enc_aes256, &krb5int_hash_sha1, + krb5int_dk_checksum, NULL, + 20, 12, 0 }, + + { CKSUMTYPE_MD5_HMAC_ARCFOUR, + "md5-hmac-rc4", { 0 }, "Microsoft MD5 HMAC", + &krb5int_enc_arcfour, &krb5int_hash_md5, + krb5int_hmacmd5_checksum, NULL, + 16, 16, 0 }, + + { CKSUMTYPE_CMAC_CAMELLIA128, + "cmac-camellia128", { 0 }, "CMAC Camellia128 key", + &krb5int_enc_camellia128, NULL, + krb5int_dk_cmac_checksum, NULL, + 16, 16, 0 }, + + { CKSUMTYPE_CMAC_CAMELLIA256, + "cmac-camellia256", { 0 }, "CMAC Camellia256 key", + &krb5int_enc_camellia256, NULL, + krb5int_dk_cmac_checksum, NULL, + 16, 16, 0 }, + + { CKSUMTYPE_HMAC_SHA256_128_AES128, + "hmac-sha256-128-aes128", { 0 }, "HMAC-SHA256 AES128 key", + &krb5int_enc_aes128, &krb5int_hash_sha256, + krb5int_etm_checksum, NULL, + 32, 16, 0 }, + + { CKSUMTYPE_HMAC_SHA384_192_AES256, + "hmac-sha384-192-aes256", { 0 }, "HMAC-SHA384 AES256 key", + &krb5int_enc_aes256, &krb5int_hash_sha384, + krb5int_etm_checksum, NULL, + 48, 24, 0 }, +}; + +const size_t krb5int_cksumtypes_length = + sizeof(krb5int_cksumtypes_list) / sizeof(struct krb5_cksumtypes); diff --git a/krb5-1.21.3/src/lib/crypto/krb/coll_proof_cksum.c b/krb5-1.21.3/src/lib/crypto/krb/coll_proof_cksum.c new file mode 100644 index 00000000..13cb182a --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/coll_proof_cksum.c @@ -0,0 +1,37 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +krb5_boolean KRB5_CALLCONV +krb5_c_is_coll_proof_cksum(krb5_cksumtype ctype) +{ + const struct krb5_cksumtypes *ctp; + + ctp = find_cksumtype(ctype); + return (ctp != NULL && !(ctp->flags & CKSUM_NOT_COLL_PROOF)); +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/crypto_int.h b/krb5-1.21.3/src/lib/crypto/krb/crypto_int.h new file mode 100644 index 00000000..3629616d --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/crypto_int.h @@ -0,0 +1,674 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/crypto_int.h - Master libk5crypto internal header */ +/* + * Copyright (C) 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* This header is the entry point for libk5crypto sources, and also documents + * requirements for crypto modules. */ + +#ifndef CRYPTO_INT_H +#define CRYPTO_INT_H + +#include + +#if defined(CRYPTO_OPENSSL) + +#include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +/* + * OpenSSL 3.0 relegates MD4 and RC4 to the legacy provider, which must be + * explicitly loaded into a library context. Performing this loading within a + * library carries complications, so use the built-in implementations of these + * primitives instead. OpenSSL 3.0 also deprecates DES_set_odd_parity() with + * no replacement. + * + * OpenSSL 3.0 adds KDF implementations matching the ones we use to derive + * encryption and authentication keys from protocol keys. It also adds + * the EVP_MAC interface which can be used for CMAC. (We could use the CMAC + * interface with OpenSSL 1.1 but currently do not.) + */ +#define K5_BUILTIN_DES_KEY_PARITY +#define K5_BUILTIN_MD4 +#define K5_BUILTIN_RC4 +#define K5_OPENSSL_KDF +#define K5_OPENSSL_CMAC +#else +#define K5_OPENSSL_DES_KEY_PARITY +#define K5_OPENSSL_MD4 +#define K5_OPENSSL_RC4 +#define K5_BUILTIN_KDF +#define K5_BUILTIN_CMAC +#endif + +#define K5_OPENSSL_AES +#define K5_OPENSSL_CAMELLIA +#define K5_OPENSSL_DES +#define K5_OPENSSL_HMAC +#define K5_OPENSSL_MD5 +#define K5_OPENSSL_PBKDF2 +#define K5_OPENSSL_SHA1 +#define K5_OPENSSL_SHA2 + +#else + +#define K5_BUILTIN_AES +#define K5_BUILTIN_CAMELLIA +#define K5_BUILTIN_CMAC +#define K5_BUILTIN_DES +#define K5_BUILTIN_DES_KEY_PARITY +#define K5_BUILTIN_HMAC +#define K5_BUILTIN_KDF +#define K5_BUILTIN_MD4 +#define K5_BUILTIN_MD5 +#define K5_BUILTIN_PBKDF2 +#define K5_BUILTIN_RC4 +#define K5_BUILTIN_SHA1 +#define K5_BUILTIN_SHA2 + +#endif + +/* Enc providers and hash providers specify well-known ciphers and hashes to be + * implemented by the crypto module. */ + +struct krb5_enc_provider { + /* keybytes is the input size to make_key; + keylength is the output size */ + size_t block_size, keybytes, keylength; + + krb5_error_code (*encrypt)(krb5_key key, const krb5_data *cipher_state, + krb5_crypto_iov *data, size_t num_data); + + krb5_error_code (*decrypt)(krb5_key key, const krb5_data *cipher_state, + krb5_crypto_iov *data, size_t num_data); + + /* May be NULL if the cipher is not used for a cbc-mac checksum. */ + krb5_error_code (*cbc_mac)(krb5_key key, const krb5_crypto_iov *data, + size_t num_data, const krb5_data *ivec, + krb5_data *output); + + krb5_error_code (*init_state)(const krb5_keyblock *key, + krb5_keyusage keyusage, + krb5_data *out_state); + void (*free_state)(krb5_data *state); + + /* May be NULL if there is no key-derived data cached. */ + void (*key_cleanup)(krb5_key key); +}; + +struct krb5_hash_provider { + char hash_name[8]; + size_t hashsize, blocksize; + + krb5_error_code (*hash)(const krb5_crypto_iov *data, size_t num_data, + krb5_data *output); +}; + +/*** RFC 3961 enctypes table ***/ + +#define MAX_ETYPE_ALIASES 2 + +struct krb5_keytypes; + +typedef unsigned int (*crypto_length_func)(const struct krb5_keytypes *ktp, + krb5_cryptotype type); + +typedef krb5_error_code (*crypt_func)(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage keyusage, + const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); + +typedef krb5_error_code (*str2key_func)(const struct krb5_keytypes *ktp, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *parm, + krb5_keyblock *key); + +typedef krb5_error_code (*rand2key_func)(const krb5_data *randombits, + krb5_keyblock *key); + +typedef krb5_error_code (*prf_func)(const struct krb5_keytypes *ktp, + krb5_key key, + const krb5_data *in, krb5_data *out); + +struct krb5_keytypes { + krb5_enctype etype; + char *name; + char *aliases[MAX_ETYPE_ALIASES]; + char *out_string; + const struct krb5_enc_provider *enc; + const struct krb5_hash_provider *hash; + size_t prf_length; + crypto_length_func crypto_length; + crypt_func encrypt; + crypt_func decrypt; + str2key_func str2key; + rand2key_func rand2key; + prf_func prf; + krb5_cksumtype required_ctype; + krb5_flags flags; + unsigned int ssf; +}; + +/* + * "Weak" means the enctype is believed to be vulnerable to practical attacks, + * and will be disabled unless allow_weak_crypto is set to true. "Deprecated" + * means the enctype has been deprecated by the IETF, and affects display and + * logging. + */ +#define ETYPE_WEAK (1 << 0) +#define ETYPE_DEPRECATED (1 << 1) + +extern const struct krb5_keytypes krb5int_enctypes_list[]; +extern const int krb5int_enctypes_length; + +/*** RFC 3961 checksum types table ***/ + +struct krb5_cksumtypes; + +/* + * Compute a checksum over the header, data, padding, and sign-only fields of + * the iov array data (of size num_data). The output buffer will already be + * allocated with ctp->compute_size bytes available; the handler just needs to + * fill in the contents. If ctp->enc is not NULL, the handler can assume that + * key is a valid-length key of an enctype which uses that enc provider. + */ +typedef krb5_error_code (*checksum_func)(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output); + +/* + * Verify a checksum over the header, data, padding, and sign-only fields of + * the iov array data (of size num_data), and store the boolean result in + * *valid. The handler can assume that hash has length ctp->output_size. If + * ctp->enc is not NULL, the handler can assume that key a valid-length key of + * an enctype which uses that enc provider. + */ +typedef krb5_error_code (*verify_func)(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + const krb5_data *input, + krb5_boolean *valid); + +struct krb5_cksumtypes { + krb5_cksumtype ctype; + char *name; + char *aliases[2]; + char *out_string; + const struct krb5_enc_provider *enc; + const struct krb5_hash_provider *hash; + checksum_func checksum; + verify_func verify; /* NULL means recompute checksum and compare */ + unsigned int compute_size; /* Allocation size for checksum computation */ + unsigned int output_size; /* Possibly truncated output size */ + krb5_flags flags; +}; + +#define CKSUM_UNKEYED 0x0001 +#define CKSUM_NOT_COLL_PROOF 0x0002 + +extern const struct krb5_cksumtypes krb5int_cksumtypes_list[]; +extern const size_t krb5int_cksumtypes_length; + +/*** Prototypes for enctype table functions ***/ + +/* Length */ +unsigned int krb5int_raw_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); +unsigned int krb5int_arcfour_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); +unsigned int krb5int_dk_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); +unsigned int krb5int_aes_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); +unsigned int krb5int_camellia_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); +unsigned int krb5int_aes2_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type); + +/* Encrypt */ +krb5_error_code krb5int_raw_encrypt(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); +krb5_error_code krb5int_arcfour_encrypt(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data); +krb5_error_code krb5int_dk_encrypt(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); +krb5_error_code krb5int_dk_cmac_encrypt(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data); +krb5_error_code krb5int_etm_encrypt(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); + +/* Decrypt */ +krb5_error_code krb5int_raw_decrypt(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); +krb5_error_code krb5int_arcfour_decrypt(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data); +krb5_error_code krb5int_dk_decrypt(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); +krb5_error_code krb5int_dk_cmac_decrypt(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data); +krb5_error_code krb5int_etm_decrypt(const struct krb5_keytypes *ktp, + krb5_key key, krb5_keyusage usage, + const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); + +/* String to key */ +krb5_error_code krb5int_des_string_to_key(const struct krb5_keytypes *ktp, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key); +krb5_error_code krb5int_arcfour_string_to_key(const struct krb5_keytypes *ktp, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key); +krb5_error_code krb5int_dk_string_to_key(const struct krb5_keytypes *enc, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key); +krb5_error_code krb5int_aes_string_to_key(const struct krb5_keytypes *enc, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key); +krb5_error_code krb5int_camellia_string_to_key(const struct krb5_keytypes *enc, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key); +krb5_error_code krb5int_aes2_string_to_key(const struct krb5_keytypes *enc, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key); + +/* Random to key */ +krb5_error_code k5_rand2key_direct(const krb5_data *randombits, + krb5_keyblock *keyblock); +krb5_error_code k5_rand2key_des3(const krb5_data *randombits, + krb5_keyblock *keyblock); + +/* Pseudo-random function */ +krb5_error_code krb5int_des_prf(const struct krb5_keytypes *ktp, + krb5_key key, const krb5_data *in, + krb5_data *out); +krb5_error_code krb5int_arcfour_prf(const struct krb5_keytypes *ktp, + krb5_key key, const krb5_data *in, + krb5_data *out); +krb5_error_code krb5int_dk_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out); +krb5_error_code krb5int_dk_cmac_prf(const struct krb5_keytypes *ktp, + krb5_key key, const krb5_data *in, + krb5_data *out); +krb5_error_code krb5int_aes2_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out); + +/*** Prototypes for cksumtype handler functions ***/ + +krb5_error_code krb5int_unkeyed_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output); +krb5_error_code krb5int_hmacmd5_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_data *output); +krb5_error_code krb5int_dk_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, krb5_data *output); +krb5_error_code krb5int_dk_cmac_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, krb5_data *output); +krb5_error_code krb5int_etm_checksum(const struct krb5_cksumtypes *ctp, + krb5_key key, krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, krb5_data *output); + +/*** Key derivation functions ***/ + +enum deriv_alg { + DERIVE_RFC3961, /* RFC 3961 section 5.1 */ + DERIVE_SP800_108_CMAC, /* NIST SP 800-108 with CMAC as PRF */ + DERIVE_SP800_108_HMAC /* NIST SP 800-108 with HMAC as PRF */ +}; + +krb5_error_code krb5int_derive_keyblock(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_keyblock *outkey, + const krb5_data *in_constant, + enum deriv_alg alg); +krb5_error_code krb5int_derive_key(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_key *outkey, + const krb5_data *in_constant, + enum deriv_alg alg); +krb5_error_code krb5int_derive_random(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_data *outrnd, + const krb5_data *in_constant, + enum deriv_alg alg); + +/*** Miscellaneous prototypes ***/ + +/* nfold algorithm from RFC 3961 */ +void krb5int_nfold(unsigned int inbits, const unsigned char *in, + unsigned int outbits, unsigned char *out); + +/* Translate an RFC 3961 key usage to a Microsoft RC4 usage. */ +krb5_keyusage krb5int_arcfour_translate_usage(krb5_keyusage usage); + +/* Ensure library initialization has occurred. */ +int krb5int_crypto_init(void); + +/* DES default state initialization handler (used by module enc providers). */ +krb5_error_code krb5int_des_init_state(const krb5_keyblock *key, + krb5_keyusage keyusage, + krb5_data *state_out); + +/* Default state cleanup handler (used by module enc providers). */ +void krb5int_default_free_state(krb5_data *state); + +/*** Input/output vector processing declarations **/ + +#define ENCRYPT_CONF_IOV(_iov) ((_iov)->flags == KRB5_CRYPTO_TYPE_HEADER) + +#define ENCRYPT_DATA_IOV(_iov) ((_iov)->flags == KRB5_CRYPTO_TYPE_DATA || \ + (_iov)->flags == KRB5_CRYPTO_TYPE_PADDING) + +#define ENCRYPT_IOV(_iov) (ENCRYPT_CONF_IOV(_iov) || ENCRYPT_DATA_IOV(_iov)) + +#define SIGN_IOV(_iov) (ENCRYPT_IOV(_iov) || \ + (_iov)->flags == KRB5_CRYPTO_TYPE_SIGN_ONLY ) + +struct iov_cursor { + const krb5_crypto_iov *iov; /* iov array we are iterating over */ + size_t iov_count; /* size of iov array */ + size_t block_size; /* size of blocks we will be obtaining */ + krb5_boolean signing; /* should we process SIGN_ONLY blocks */ + size_t in_iov; /* read index into iov array */ + size_t in_pos; /* read index into iov contents */ + size_t out_iov; /* write index into iov array */ + size_t out_pos; /* write index into iov contents */ +}; + +krb5_crypto_iov *krb5int_c_locate_iov(krb5_crypto_iov *data, size_t num_data, + krb5_cryptotype type); + +krb5_error_code krb5int_c_iov_decrypt_stream(const struct krb5_keytypes *ktp, + krb5_key key, + krb5_keyusage keyusage, + const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data); + +unsigned int krb5int_c_padding_length(const struct krb5_keytypes *ktp, + size_t data_length); + +void k5_iov_cursor_init(struct iov_cursor *cursor, const krb5_crypto_iov *iov, + size_t count, size_t block_size, krb5_boolean signing); + +krb5_boolean k5_iov_cursor_get(struct iov_cursor *cursor, + unsigned char *block); + +void k5_iov_cursor_put(struct iov_cursor *cursor, unsigned char *block); + +/*** Crypto module declarations ***/ + +/* Modules must implement the k5_sha256() function prototyped in k5-int.h. */ + +/* Modules must implement the following enc_providers and hash_providers: */ +extern const struct krb5_enc_provider krb5int_enc_des3; +extern const struct krb5_enc_provider krb5int_enc_arcfour; +extern const struct krb5_enc_provider krb5int_enc_aes128; +extern const struct krb5_enc_provider krb5int_enc_aes256; +extern const struct krb5_enc_provider krb5int_enc_aes128_ctr; +extern const struct krb5_enc_provider krb5int_enc_aes256_ctr; +extern const struct krb5_enc_provider krb5int_enc_camellia128; +extern const struct krb5_enc_provider krb5int_enc_camellia256; + +extern const struct krb5_hash_provider krb5int_hash_md4; +extern const struct krb5_hash_provider krb5int_hash_md5; +extern const struct krb5_hash_provider krb5int_hash_sha1; +extern const struct krb5_hash_provider krb5int_hash_sha256; +extern const struct krb5_hash_provider krb5int_hash_sha384; + +/* Modules must implement the following functions. */ + +/* Set the parity bits to the correct values in keybits. */ +void k5_des_fixup_key_parity(unsigned char *keybits); + +/* Compute an HMAC using the provided hash function, key, and data, storing the + * result into output (caller-allocated). */ +krb5_error_code krb5int_hmac(const struct krb5_hash_provider *hash, + krb5_key key, const krb5_crypto_iov *data, + size_t num_data, krb5_data *output); + +/* Compute a CMAC checksum over data. */ +krb5_error_code krb5int_cmac_checksum(const struct krb5_enc_provider *enc, + krb5_key key, + const krb5_crypto_iov *data, + size_t num_data, krb5_data *output); + +/* As above, using a keyblock as the key input. */ +krb5_error_code krb5int_hmac_keyblock(const struct krb5_hash_provider *hash, + const krb5_keyblock *keyblock, + const krb5_crypto_iov *data, + size_t num_data, krb5_data *output); + +/* + * Compute the PBKDF2 (see RFC 2898) of password and salt, with the specified + * count, using HMAC with the specified hash as the pseudo-random function, + * storing the result into out (caller-allocated). + */ +krb5_error_code krb5int_pbkdf2_hmac(const struct krb5_hash_provider *hash, + const krb5_data *out, unsigned long count, + const krb5_data *password, + const krb5_data *salt); + +/* + * Compute the NIST SP800-108 KDF in counter mode (section 5.1) with the + * following parameters: + * - HMAC (with hash as the hash provider) is the PRF. + * - A block counter of four bytes is used. + * - Four bytes are used to encode the output length in the PRF input. + * + * There are no uses requiring more than a single PRF invocation. + */ +krb5_error_code +k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash, + krb5_key key, const krb5_data *label, + const krb5_data *context, krb5_data *rnd_out); + +/* + * Compute the NIST SP800-108 KDF in feedback mode (section 5.2) with the + * following parameters: + * - CMAC (with enc as the enc provider) is the PRF. + * - A block counter of four bytes is used. + * - Label is the key derivation constant. + * - Context is empty. + * - Four bytes are used to encode the output length in the PRF input. + */ +krb5_error_code +k5_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc, krb5_key key, + const krb5_data *label, krb5_data *rnd_out); + +/* Compute the RFC 3961 section 5.1 KDF (which uses n-fold) with enc as E, + * inkey as Key, and in_constant as Constant. */ +krb5_error_code +k5_derive_random_rfc3961(const struct krb5_enc_provider *enc, krb5_key key, + const krb5_data *constant, krb5_data *rnd_out); + +/* The following are used by test programs and are just handler functions from + * the AES and Camellia enc providers. */ +krb5_error_code krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); +krb5_error_code krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data); +krb5_error_code krb5int_camellia_encrypt(krb5_key key, const krb5_data *ivec, + krb5_crypto_iov *data, + size_t num_data); + +/*** Inline helper functions ***/ + +/* Find an enctype by number in the enctypes table. */ +static inline const struct krb5_keytypes * +find_enctype(krb5_enctype enctype) +{ + int i; + + for (i = 0; i < krb5int_enctypes_length; i++) { + if (krb5int_enctypes_list[i].etype == enctype) + break; + } + + if (i == krb5int_enctypes_length) + return NULL; + return &krb5int_enctypes_list[i]; +} + +/* Find a checksum type by number in the cksumtypes table. */ +static inline const struct krb5_cksumtypes * +find_cksumtype(krb5_cksumtype ctype) +{ + size_t i; + + for (i = 0; i < krb5int_cksumtypes_length; i++) { + if (krb5int_cksumtypes_list[i].ctype == ctype) + break; + } + + if (i == krb5int_cksumtypes_length) + return NULL; + return &krb5int_cksumtypes_list[i]; +} + +/* Verify that a key is appropriate for a checksum type. */ +static inline krb5_error_code +verify_key(const struct krb5_cksumtypes *ctp, krb5_key key) +{ + const struct krb5_keytypes *ktp; + + ktp = key ? find_enctype(key->keyblock.enctype) : NULL; + if (ctp->enc != NULL && (!ktp || ktp->enc != ctp->enc)) + return KRB5_BAD_ENCTYPE; + if (key && (!ktp || key->keyblock.length != ktp->enc->keylength)) + return KRB5_BAD_KEYSIZE; + return 0; +} + +/* Encrypt one block of plaintext in place, for block ciphers. */ +static inline krb5_error_code +encrypt_block(const struct krb5_enc_provider *enc, krb5_key key, + krb5_data *block) +{ + krb5_crypto_iov iov; + + /* Verify that this is a block cipher and block is the right length. */ + if (block->length != enc->block_size || enc->block_size == 1) + return EINVAL; + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *block; + if (enc->cbc_mac != NULL) /* One-block cbc-mac with no ivec. */ + return enc->cbc_mac(key, &iov, 1, NULL, block); + else /* Assume cbc-mode encrypt. */ + return enc->encrypt(key, 0, &iov, 1); +} + +/* Return the total length of the to-be-signed or to-be-encrypted buffers in an + * iov chain. */ +static inline size_t +iov_total_length(const krb5_crypto_iov *data, size_t num_data, + krb5_boolean signing) +{ + size_t i, total = 0; + + for (i = 0; i < num_data; i++) { + if (signing ? SIGN_IOV(&data[i]) : ENCRYPT_IOV(&data[i])) + total += data[i].data.length; + } + return total; +} + +/* + * Return the number of contiguous blocks available within the current input + * IOV of the cursor c, so that the caller can do in-place encryption. + * Do not call if c might be exhausted. + */ +static inline size_t +iov_cursor_contig_blocks(struct iov_cursor *c) +{ + return (c->iov[c->in_iov].data.length - c->in_pos) / c->block_size; +} + +/* Return the current input pointer within the cursor c. Do not call if c + * might be exhausted. */ +static inline unsigned char * +iov_cursor_ptr(struct iov_cursor *c) +{ + return (unsigned char *)&c->iov[c->in_iov].data.data[c->in_pos]; +} + +/* + * Advance the input and output pointers of c by nblocks blocks. nblocks must + * not be greater than the return value of iov_cursor_contig_blocks, and the + * input and output positions must be identical. + */ +static inline void +iov_cursor_advance(struct iov_cursor *c, size_t nblocks) +{ + c->in_pos += nblocks * c->block_size; + c->out_pos += nblocks * c->block_size; +} + +#endif /* CRYPTO_INT_H */ diff --git a/krb5-1.21.3/src/lib/crypto/krb/crypto_length.c b/krb5-1.21.3/src/lib/crypto/krb/crypto_length.c new file mode 100644 index 00000000..a621423a --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/crypto_length.c @@ -0,0 +1,125 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/crypto_length.c */ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_crypto_length(krb5_context context, krb5_enctype enctype, + krb5_cryptotype type, unsigned int *size) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + switch (type) { + case KRB5_CRYPTO_TYPE_EMPTY: + case KRB5_CRYPTO_TYPE_SIGN_ONLY: + *size = 0; + break; + case KRB5_CRYPTO_TYPE_DATA: + *size = (unsigned int)~0; /* match Heimdal */ + break; + case KRB5_CRYPTO_TYPE_HEADER: + case KRB5_CRYPTO_TYPE_PADDING: + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + *size = ktp->crypto_length(ktp, type); + break; + default: + return EINVAL; + } + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_padding_length(krb5_context context, krb5_enctype enctype, + size_t data_length, unsigned int *pad_length) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + *pad_length = krb5int_c_padding_length(ktp, data_length); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_crypto_length_iov(krb5_context context, krb5_enctype enctype, + krb5_crypto_iov *data, size_t num_data) +{ + size_t i; + const struct krb5_keytypes *ktp; + unsigned int data_length = 0, pad_length; + krb5_crypto_iov *padding = NULL; + + /* + * XXX need to rejig internal interface so we can accurately + * report variable header lengths. + */ + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + for (i = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + switch (iov->flags) { + case KRB5_CRYPTO_TYPE_DATA: + data_length += iov->data.length; + break; + case KRB5_CRYPTO_TYPE_PADDING: + if (padding != NULL) + return EINVAL; + + padding = iov; + break; + case KRB5_CRYPTO_TYPE_HEADER: + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + iov->data.length = ktp->crypto_length(ktp, iov->flags); + break; + case KRB5_CRYPTO_TYPE_EMPTY: + case KRB5_CRYPTO_TYPE_SIGN_ONLY: + default: + break; + } + } + + pad_length = krb5int_c_padding_length(ktp, data_length); + if (pad_length != 0 && padding == NULL) + return EINVAL; + + if (padding != NULL) + padding->data.length = pad_length; + + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/decrypt.c b/krb5-1.21.3/src/lib/crypto/krb/decrypt.c new file mode 100644 index 00000000..496d262e --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/decrypt.c @@ -0,0 +1,101 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_decrypt(krb5_context context, krb5_key key, + krb5_keyusage usage, const krb5_data *cipher_state, + const krb5_enc_data *input, krb5_data *output) +{ + const struct krb5_keytypes *ktp; + krb5_crypto_iov iov[4]; + krb5_error_code ret; + unsigned int header_len, trailer_len, plain_len; + char *scratch = NULL; + + ktp = find_enctype(key->keyblock.enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + if (input->enctype != ENCTYPE_UNKNOWN && ktp->etype != input->enctype) + return KRB5_BAD_ENCTYPE; + + /* Verify the input and output lengths. */ + header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER); + trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + if (input->ciphertext.length < header_len + trailer_len) + return KRB5_BAD_MSIZE; + plain_len = input->ciphertext.length - header_len - trailer_len; + if (output->length < plain_len) + return KRB5_BAD_MSIZE; + + scratch = k5alloc(header_len + trailer_len, &ret); + if (scratch == NULL) + return ret; + + iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; + iov[0].data = make_data(scratch, header_len); + memcpy(iov[0].data.data, input->ciphertext.data, header_len); + + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data = make_data(output->data, plain_len); + memcpy(iov[1].data.data, input->ciphertext.data + header_len, plain_len); + + /* Use empty padding since tokens don't indicate the padding length. */ + iov[2].flags = KRB5_CRYPTO_TYPE_PADDING; + iov[2].data = empty_data(); + + iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER; + iov[3].data = make_data(scratch + header_len, trailer_len); + memcpy(iov[3].data.data, input->ciphertext.data + header_len + plain_len, + trailer_len); + + ret = ktp->decrypt(ktp, key, usage, cipher_state, iov, 4); + if (ret != 0) + zap(output->data, plain_len); + else + output->length = plain_len; + zapfree(scratch, header_len + trailer_len); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_decrypt(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *cipher_state, + const krb5_enc_data *input, krb5_data *output) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_decrypt(context, key, usage, cipher_state, input, output); + krb5_k_free_key(context, key); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/decrypt_iov.c b/krb5-1.21.3/src/lib/crypto/krb/decrypt_iov.c new file mode 100644 index 00000000..8d43e8ff --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/decrypt_iov.c @@ -0,0 +1,64 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/decrypt_iov.c */ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_decrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage, + const krb5_data *cipher_state, krb5_crypto_iov *data, + size_t num_data) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(key->keyblock.enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + if (krb5int_c_locate_iov(data, num_data, + KRB5_CRYPTO_TYPE_STREAM) != NULL) { + return krb5int_c_iov_decrypt_stream(ktp, key, usage, cipher_state, + data, num_data); + } + + return ktp->decrypt(ktp, key, usage, cipher_state, data, num_data); +} + +krb5_error_code KRB5_CALLCONV +krb5_c_decrypt_iov(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *cipher_state, + krb5_crypto_iov *data, size_t num_data) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_decrypt_iov(context, key, usage, cipher_state, data, + num_data); + krb5_k_free_key(context, key); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/default_state.c b/krb5-1.21.3/src/lib/crypto/krb/default_state.c new file mode 100644 index 00000000..0757c8b0 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/default_state.c @@ -0,0 +1,50 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2001, 2014 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * Section 6 (Encryption) of the Kerberos revisions document defines + * cipher states to be used to chain encryptions and decryptions + * together. Examples of cipher states include initialization vectors + * for CBC encription. Most Kerberos encryption systems can share + * code for initializing and freeing cipher states. This file + * contains that default code. + */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_des_init_state(const krb5_keyblock *key, krb5_keyusage usage, + krb5_data *state_out) +{ + if (alloc_data(state_out, 8)) + return ENOMEM; + + return 0; +} + +void +krb5int_default_free_state(krb5_data *state) +{ + free(state->data); + *state = empty_data(); +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/deps b/krb5-1.21.3/src/lib/crypto/krb/deps new file mode 100644 index 00000000..92928572 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/deps @@ -0,0 +1,580 @@ +# +# Generated makefile dependencies follow. +# +aead.so aead.po $(OUTPRE)aead.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h aead.c crypto_int.h +block_size.so block_size.po $(OUTPRE)block_size.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + block_size.c crypto_int.h +cf2.so cf2.po $(OUTPRE)cf2.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cf2.c crypto_int.h +checksum_dk_cmac.so checksum_dk_cmac.po $(OUTPRE)checksum_dk_cmac.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + checksum_dk_cmac.c crypto_int.h +checksum_dk_hmac.so checksum_dk_hmac.po $(OUTPRE)checksum_dk_hmac.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + checksum_dk_hmac.c crypto_int.h +checksum_etm.so checksum_etm.po $(OUTPRE)checksum_etm.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + checksum_etm.c crypto_int.h +checksum_hmac_md5.so checksum_hmac_md5.po $(OUTPRE)checksum_hmac_md5.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + checksum_hmac_md5.c crypto_int.h +checksum_unkeyed.so checksum_unkeyed.po $(OUTPRE)checksum_unkeyed.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + checksum_unkeyed.c crypto_int.h +checksum_length.so checksum_length.po $(OUTPRE)checksum_length.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + checksum_length.c crypto_int.h +cksumtype_to_string.so cksumtype_to_string.po $(OUTPRE)cksumtype_to_string.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cksumtype_to_string.c crypto_int.h +cksumtypes.so cksumtypes.po $(OUTPRE)cksumtypes.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cksumtypes.c crypto_int.h +coll_proof_cksum.so coll_proof_cksum.po $(OUTPRE)coll_proof_cksum.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + coll_proof_cksum.c crypto_int.h +crypto_length.so crypto_length.po $(OUTPRE)crypto_length.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h crypto_length.c +default_state.so default_state.po $(OUTPRE)default_state.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h default_state.c +decrypt.so decrypt.po $(OUTPRE)decrypt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h decrypt.c +decrypt_iov.so decrypt_iov.po $(OUTPRE)decrypt_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h decrypt_iov.c +derive.so derive.po $(OUTPRE)derive.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h derive.c +encrypt.so encrypt.po $(OUTPRE)encrypt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h encrypt.c +encrypt_iov.so encrypt_iov.po $(OUTPRE)encrypt_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h encrypt_iov.c +encrypt_length.so encrypt_length.po $(OUTPRE)encrypt_length.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h encrypt_length.c +enctype_util.so enctype_util.po $(OUTPRE)enctype_util.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h enctype_util.c +enc_dk_cmac.so enc_dk_cmac.po $(OUTPRE)enc_dk_cmac.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h enc_dk_cmac.c +enc_dk_hmac.so enc_dk_hmac.po $(OUTPRE)enc_dk_hmac.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h enc_dk_hmac.c +enc_etm.so enc_etm.po $(OUTPRE)enc_etm.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h enc_etm.c +enc_raw.so enc_raw.po $(OUTPRE)enc_raw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h enc_raw.c +enc_rc4.so enc_rc4.po $(OUTPRE)enc_rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h enc_rc4.c +etypes.so etypes.po $(OUTPRE)etypes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h etypes.c +key.so key.po $(OUTPRE)key.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h key.c +keyblocks.so keyblocks.po $(OUTPRE)keyblocks.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h keyblocks.c +keyed_cksum.so keyed_cksum.po $(OUTPRE)keyed_cksum.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h keyed_cksum.c +keyed_checksum_types.so keyed_checksum_types.po $(OUTPRE)keyed_checksum_types.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h keyed_checksum_types.c +keylengths.so keylengths.po $(OUTPRE)keylengths.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h keylengths.c +make_checksum.so make_checksum.po $(OUTPRE)make_checksum.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h make_checksum.c +make_checksum_iov.so make_checksum_iov.po $(OUTPRE)make_checksum_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h make_checksum_iov.c +make_random_key.so make_random_key.po $(OUTPRE)make_random_key.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h make_random_key.c +mandatory_sumtype.so mandatory_sumtype.po $(OUTPRE)mandatory_sumtype.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h mandatory_sumtype.c +nfold.so nfold.po $(OUTPRE)nfold.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h nfold.c +old_api_glue.so old_api_glue.po $(OUTPRE)old_api_glue.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h old_api_glue.c +prf.so prf.po $(OUTPRE)prf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h prf.c +prf_aes2.so prf_aes2.po $(OUTPRE)prf_aes2.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h prf_aes2.c +prf_cmac.so prf_cmac.po $(OUTPRE)prf_cmac.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h prf_cmac.c +prf_des.so prf_des.po $(OUTPRE)prf_des.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h prf_des.c +prf_dk.so prf_dk.po $(OUTPRE)prf_dk.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h prf_dk.c +prf_rc4.so prf_rc4.po $(OUTPRE)prf_rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h prf_rc4.c +prng.so prng.po $(OUTPRE)prng.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h prng.c +random_to_key.so random_to_key.po $(OUTPRE)random_to_key.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h random_to_key.c +s2k_pbkdf2.so s2k_pbkdf2.po $(OUTPRE)s2k_pbkdf2.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h s2k_pbkdf2.c +s2k_rc4.so s2k_rc4.po $(OUTPRE)s2k_rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/k5-utf8.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h s2k_rc4.c +state.so state.po $(OUTPRE)state.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h crypto_int.h state.c +string_to_cksumtype.so string_to_cksumtype.po $(OUTPRE)string_to_cksumtype.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h string_to_cksumtype.c +string_to_key.so string_to_key.po $(OUTPRE)string_to_key.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h string_to_key.c +valid_cksumtype.so valid_cksumtype.po $(OUTPRE)valid_cksumtype.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h valid_cksumtype.c +verify_checksum.so verify_checksum.po $(OUTPRE)verify_checksum.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h verify_checksum.c +verify_checksum_iov.so verify_checksum_iov.po $(OUTPRE)verify_checksum_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + crypto_int.h verify_checksum_iov.c diff --git a/krb5-1.21.3/src/lib/crypto/krb/derive.c b/krb5-1.21.3/src/lib/crypto/krb/derive.c new file mode 100644 index 00000000..3e51a005 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/derive.c @@ -0,0 +1,174 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +static krb5_key +find_cached_dkey(struct derived_key *list, const krb5_data *constant) +{ + for (; list; list = list->next) { + if (data_eq(list->constant, *constant)) { + krb5_k_reference_key(NULL, list->dkey); + return list->dkey; + } + } + return NULL; +} + +static krb5_error_code +add_cached_dkey(krb5_key key, const krb5_data *constant, + const krb5_keyblock *dkeyblock, krb5_key *cached_dkey) +{ + krb5_key dkey; + krb5_error_code ret; + struct derived_key *dkent = NULL; + char *data = NULL; + + /* Allocate fields for the new entry. */ + dkent = malloc(sizeof(*dkent)); + if (dkent == NULL) + goto cleanup; + data = k5memdup(constant->data, constant->length, &ret); + if (data == NULL) + goto cleanup; + ret = krb5_k_create_key(NULL, dkeyblock, &dkey); + if (ret != 0) + goto cleanup; + + /* Add the new entry to the list. */ + dkent->dkey = dkey; + dkent->constant.data = data; + dkent->constant.length = constant->length; + dkent->next = key->derived; + key->derived = dkent; + + /* Return a "copy" of the cached key. */ + krb5_k_reference_key(NULL, dkey); + *cached_dkey = dkey; + return 0; + +cleanup: + free(dkent); + free(data); + return ENOMEM; +} + +krb5_error_code +krb5int_derive_random(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_data *outrnd, + const krb5_data *in_constant, enum deriv_alg alg) +{ + krb5_data empty = empty_data(); + + switch (alg) { + case DERIVE_RFC3961: + return k5_derive_random_rfc3961(enc, inkey, in_constant, outrnd); + case DERIVE_SP800_108_CMAC: + return k5_sp800_108_feedback_cmac(enc, inkey, in_constant, outrnd); + case DERIVE_SP800_108_HMAC: + return k5_sp800_108_counter_hmac(hash, inkey, in_constant, &empty, + outrnd); + default: + return EINVAL; + } +} + +/* + * Compute a derived key into the keyblock outkey. This variation on + * krb5int_derive_key does not cache the result, as it is only used + * directly in situations which are not expected to be repeated with + * the same inkey and constant. + */ +krb5_error_code +krb5int_derive_keyblock(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_keyblock *outkey, + const krb5_data *in_constant, enum deriv_alg alg) +{ + krb5_error_code ret; + krb5_data rawkey = empty_data(); + + /* Allocate a buffer for the raw key bytes. */ + ret = alloc_data(&rawkey, enc->keybytes); + if (ret) + goto cleanup; + + /* Derive pseudo-random data for the key bytes. */ + ret = krb5int_derive_random(enc, hash, inkey, &rawkey, in_constant, alg); + if (ret) + goto cleanup; + + /* Postprocess the key. */ + ret = krb5_c_random_to_key(NULL, inkey->keyblock.enctype, &rawkey, outkey); + +cleanup: + zapfree(rawkey.data, enc->keybytes); + return ret; +} + +krb5_error_code +krb5int_derive_key(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + krb5_key inkey, krb5_key *outkey, + const krb5_data *in_constant, enum deriv_alg alg) +{ + krb5_keyblock keyblock; + krb5_error_code ret; + krb5_key dkey; + + *outkey = NULL; + + /* Check for a cached result. */ + dkey = find_cached_dkey(inkey->derived, in_constant); + if (dkey != NULL) { + *outkey = dkey; + return 0; + } + + /* Derive into a temporary keyblock. */ + keyblock.length = enc->keylength; + keyblock.contents = malloc(keyblock.length); + keyblock.enctype = inkey->keyblock.enctype; + if (keyblock.contents == NULL) + return ENOMEM; + ret = krb5int_derive_keyblock(enc, hash, inkey, &keyblock, in_constant, + alg); + if (ret) + goto cleanup; + + /* Cache the derived key. */ + ret = add_cached_dkey(inkey, in_constant, &keyblock, &dkey); + if (ret != 0) + goto cleanup; + + *outkey = dkey; + +cleanup: + zapfree(keyblock.contents, keyblock.length); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/enc_dk_cmac.c b/krb5-1.21.3/src/lib/crypto/krb/enc_dk_cmac.c new file mode 100644 index 00000000..b65b9b70 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/enc_dk_cmac.c @@ -0,0 +1,182 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/enc_dk_cmac.c - Derived-key enctype functions using CMAC */ +/* + * Copyright 2008, 2009, 2010 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + + +#include "crypto_int.h" + +#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ + +/* AEAD */ + +unsigned int +krb5int_camellia_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_HEADER: + return ktp->enc->block_size; + case KRB5_CRYPTO_TYPE_PADDING: + return 0; + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + return ktp->enc->block_size; + default: + assert(0 && "bad type passed to krb5int_camellia_crypto_length"); + return 0; + } +} + +/* Derive encryption and integrity keys for CMAC-using enctypes. */ +static krb5_error_code +derive_keys(const struct krb5_enc_provider *enc, krb5_key key, + krb5_keyusage usage, krb5_key *ke_out, krb5_key *ki_out) +{ + krb5_error_code ret; + unsigned char buf[K5CLENGTH]; + krb5_data constant = make_data(buf, K5CLENGTH); + krb5_key ke, ki; + + *ke_out = *ki_out = NULL; + + /* Derive the encryption key. */ + store_32_be(usage, buf); + buf[4] = 0xAA; + ret = krb5int_derive_key(enc, NULL, key, &ke, &constant, + DERIVE_SP800_108_CMAC); + if (ret != 0) + return ret; + + /* Derive the integrity key. */ + buf[4] = 0x55; + ret = krb5int_derive_key(enc, NULL, key, &ki, &constant, + DERIVE_SP800_108_CMAC); + if (ret != 0) { + krb5_k_free_key(NULL, ke); + return ret; + } + + *ke_out = ke; + *ki_out = ki; + return 0; +} + +krb5_error_code +krb5int_dk_cmac_encrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + const struct krb5_enc_provider *enc = ktp->enc; + krb5_error_code ret; + krb5_crypto_iov *header, *trailer, *padding; + krb5_key ke = NULL, ki = NULL; + + /* E(Confounder | Plaintext | Pad) | Checksum */ + + /* Validate header and trailer lengths, and zero out padding length. */ + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length < enc->block_size) + return KRB5_BAD_MSIZE; + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length < enc->block_size) + return KRB5_BAD_MSIZE; + padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING); + if (padding != NULL) + padding->data.length = 0; + + /* Derive the encryption and integrity keys. */ + ret = derive_keys(enc, key, usage, &ke, &ki); + if (ret != 0) + goto cleanup; + + /* Generate confounder. */ + header->data.length = enc->block_size; + ret = krb5_c_random_make_octets(NULL, &header->data); + if (ret != 0) + goto cleanup; + + /* Checksum the plaintext. */ + ret = krb5int_cmac_checksum(enc, ki, data, num_data, &trailer->data); + if (ret != 0) + goto cleanup; + + /* Encrypt the plaintext (header | data | padding) */ + ret = enc->encrypt(ke, ivec, data, num_data); + if (ret != 0) + goto cleanup; + +cleanup: + krb5_k_free_key(NULL, ke); + krb5_k_free_key(NULL, ki); + return ret; +} + +krb5_error_code +krb5int_dk_cmac_decrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + const struct krb5_enc_provider *enc = ktp->enc; + krb5_error_code ret; + krb5_crypto_iov *header, *trailer; + krb5_data cksum = empty_data(); + krb5_key ke = NULL, ki = NULL; + + /* E(Confounder | Plaintext | Pad) | Checksum */ + + /* Validate header and trailer lengths. */ + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length != enc->block_size) + return KRB5_BAD_MSIZE; + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length != enc->block_size) + return KRB5_BAD_MSIZE; + + /* Derive the encryption and integrity keys. */ + ret = derive_keys(enc, key, usage, &ke, &ki); + if (ret != 0) + goto cleanup; + + /* Decrypt the plaintext (header | data | padding). */ + ret = enc->decrypt(ke, ivec, data, num_data); + if (ret != 0) + goto cleanup; + + /* Verify the hash. */ + ret = alloc_data(&cksum, enc->block_size); + if (ret != 0) + goto cleanup; + ret = krb5int_cmac_checksum(enc, ki, data, num_data, &cksum); + if (ret != 0) + goto cleanup; + if (k5_bcmp(cksum.data, trailer->data.data, enc->block_size) != 0) + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + +cleanup: + krb5_k_free_key(NULL, ke); + krb5_k_free_key(NULL, ki); + zapfree(cksum.data, cksum.length); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/enc_dk_hmac.c b/krb5-1.21.3/src/lib/crypto/krb/enc_dk_hmac.c new file mode 100644 index 00000000..713044c6 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/enc_dk_hmac.c @@ -0,0 +1,269 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/enc_dk_hmac.c */ +/* + * Copyright 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + + +#include "crypto_int.h" + +#define K5CLENGTH 5 /* 32 bit net byte order integer + one byte seed */ + +/* AEAD */ + +unsigned int +krb5int_dk_crypto_length(const struct krb5_keytypes *ktp, krb5_cryptotype type) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_HEADER: + case KRB5_CRYPTO_TYPE_PADDING: + return ktp->enc->block_size; + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + return ktp->hash->hashsize; + default: + assert(0 && "invalid cryptotype passed to krb5int_dk_crypto_length"); + return 0; + } +} + +unsigned int +krb5int_aes_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_HEADER: + return ktp->enc->block_size; + case KRB5_CRYPTO_TYPE_PADDING: + return 0; + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + return 96 / 8; + default: + assert(0 && "invalid cryptotype passed to krb5int_aes_crypto_length"); + return 0; + } +} + +krb5_error_code +krb5int_dk_encrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + const struct krb5_enc_provider *enc = ktp->enc; + const struct krb5_hash_provider *hash = ktp->hash; + krb5_error_code ret; + unsigned char constantdata[K5CLENGTH]; + krb5_data d1, d2; + krb5_crypto_iov *header, *trailer, *padding; + krb5_key ke = NULL, ki = NULL; + size_t i; + unsigned int blocksize, hmacsize, plainlen = 0, padsize = 0; + unsigned char *cksum = NULL; + + /* E(Confounder | Plaintext | Pad) | Checksum */ + + blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING); + hmacsize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + + for (i = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + if (iov->flags == KRB5_CRYPTO_TYPE_DATA) + plainlen += iov->data.length; + } + + /* Validate header and trailer lengths. */ + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length < enc->block_size) + return KRB5_BAD_MSIZE; + + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length < hmacsize) + return KRB5_BAD_MSIZE; + + if (blocksize != 0) { + /* Check that the input data is correctly padded. */ + if (plainlen % blocksize) + padsize = blocksize - (plainlen % blocksize); + } + + padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING); + if (padsize && (padding == NULL || padding->data.length < padsize)) + return KRB5_BAD_MSIZE; + + if (padding != NULL) { + memset(padding->data.data, 0, padsize); + padding->data.length = padsize; + } + + cksum = k5alloc(hash->hashsize, &ret); + if (ret != 0) + goto cleanup; + + /* Derive the keys. */ + + d1.data = (char *)constantdata; + d1.length = K5CLENGTH; + + store_32_be(usage, constantdata); + + d1.data[4] = 0xAA; + + ret = krb5int_derive_key(enc, NULL, key, &ke, &d1, DERIVE_RFC3961); + if (ret != 0) + goto cleanup; + + d1.data[4] = 0x55; + + ret = krb5int_derive_key(enc, NULL, key, &ki, &d1, DERIVE_RFC3961); + if (ret != 0) + goto cleanup; + + /* Generate confounder. */ + + header->data.length = enc->block_size; + + ret = krb5_c_random_make_octets(/* XXX */ NULL, &header->data); + if (ret != 0) + goto cleanup; + + /* Hash the plaintext. */ + d2.length = hash->hashsize; + d2.data = (char *)cksum; + + ret = krb5int_hmac(hash, ki, data, num_data, &d2); + if (ret != 0) + goto cleanup; + + /* Encrypt the plaintext (header | data | padding) */ + ret = enc->encrypt(ke, ivec, data, num_data); + if (ret != 0) + goto cleanup; + + /* Possibly truncate the hash */ + assert(hmacsize <= d2.length); + + memcpy(trailer->data.data, cksum, hmacsize); + trailer->data.length = hmacsize; + +cleanup: + krb5_k_free_key(NULL, ke); + krb5_k_free_key(NULL, ki); + free(cksum); + return ret; +} + +krb5_error_code +krb5int_dk_decrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + const struct krb5_enc_provider *enc = ktp->enc; + const struct krb5_hash_provider *hash = ktp->hash; + krb5_error_code ret; + unsigned char constantdata[K5CLENGTH]; + krb5_data d1; + krb5_crypto_iov *header, *trailer; + krb5_key ke = NULL, ki = NULL; + size_t i; + unsigned int blocksize; /* enc block size, not confounder len */ + unsigned int hmacsize, cipherlen = 0; + unsigned char *cksum = NULL; + + /* E(Confounder | Plaintext | Pad) | Checksum */ + + blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING); + hmacsize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + + if (blocksize != 0) { + /* Check that the input data is correctly padded. */ + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_DATA_IOV(iov)) + cipherlen += iov->data.length; + } + if (cipherlen % blocksize != 0) + return KRB5_BAD_MSIZE; + } + + /* Validate header and trailer lengths */ + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length != enc->block_size) + return KRB5_BAD_MSIZE; + + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length != hmacsize) + return KRB5_BAD_MSIZE; + + cksum = k5alloc(hash->hashsize, &ret); + if (ret != 0) + goto cleanup; + + /* Derive the keys. */ + + d1.data = (char *)constantdata; + d1.length = K5CLENGTH; + + store_32_be(usage, constantdata); + + d1.data[4] = 0xAA; + + ret = krb5int_derive_key(enc, NULL, key, &ke, &d1, DERIVE_RFC3961); + if (ret != 0) + goto cleanup; + + d1.data[4] = 0x55; + + ret = krb5int_derive_key(enc, NULL, key, &ki, &d1, DERIVE_RFC3961); + if (ret != 0) + goto cleanup; + + /* Decrypt the plaintext (header | data | padding). */ + ret = enc->decrypt(ke, ivec, data, num_data); + if (ret != 0) + goto cleanup; + + /* Verify the hash. */ + d1.length = hash->hashsize; /* non-truncated length */ + d1.data = (char *)cksum; + + ret = krb5int_hmac(hash, ki, data, num_data, &d1); + if (ret != 0) + goto cleanup; + + /* Compare only the possibly truncated length. */ + if (k5_bcmp(cksum, trailer->data.data, hmacsize) != 0) { + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + +cleanup: + krb5_k_free_key(NULL, ke); + krb5_k_free_key(NULL, ki); + free(cksum); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/enc_etm.c b/krb5-1.21.3/src/lib/crypto/krb/enc_etm.c new file mode 100644 index 00000000..3135dd5b --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/enc_etm.c @@ -0,0 +1,257 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/enc_etm.c - encrypt-then-mac construction for aes-sha2 */ +/* + * Copyright (C) 2015 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. + */ + +#include "crypto_int.h" + +unsigned int +krb5int_aes2_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_HEADER: + return ktp->enc->block_size; + case KRB5_CRYPTO_TYPE_PADDING: + return 0; + case KRB5_CRYPTO_TYPE_TRAILER: + case KRB5_CRYPTO_TYPE_CHECKSUM: + return ktp->hash->hashsize / 2; + default: + assert(0 && "invalid cryptotype passed to krb5int_aes2_crypto_length"); + return 0; + } +} + +/* Derive encryption and integrity keys for CMAC-using enctypes. */ +static krb5_error_code +derive_keys(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, krb5_key *ke_out, krb5_data *ki_out) +{ + krb5_error_code ret; + uint8_t label[5]; + krb5_data label_data = make_data(label, 5), ki = empty_data(); + krb5_key ke = NULL; + + *ke_out = NULL; + *ki_out = empty_data(); + + /* Derive the encryption key. */ + store_32_be(usage, label); + label[4] = 0xAA; + ret = krb5int_derive_key(ktp->enc, ktp->hash, key, &ke, &label_data, + DERIVE_SP800_108_HMAC); + if (ret) + goto cleanup; + + /* Derive the integrity key. */ + label[4] = 0x55; + ret = alloc_data(&ki, ktp->hash->hashsize / 2); + if (ret) + goto cleanup; + ret = krb5int_derive_random(NULL, ktp->hash, key, &ki, &label_data, + DERIVE_SP800_108_HMAC); + if (ret) + goto cleanup; + + *ke_out = ke; + ke = NULL; + *ki_out = ki; + ki = empty_data(); + +cleanup: + krb5_k_free_key(NULL, ke); + zapfree(ki.data, ki.length); + return ret; +} + +/* Compute an HMAC checksum over the cipher state and data. Allocate enough + * space in *out for the checksum. */ +static krb5_error_code +hmac_ivec_data(const struct krb5_keytypes *ktp, const krb5_data *ki, + const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data, + krb5_data *out) +{ + krb5_error_code ret; + krb5_data zeroivec = empty_data(); + krb5_crypto_iov *iovs = NULL; + krb5_keyblock kb = { 0 }; + + if (ivec == NULL) { + ret = ktp->enc->init_state(NULL, 0, &zeroivec); + if (ret) + goto cleanup; + ivec = &zeroivec; + } + + /* Make a copy of data with an extra iov at the beginning for the ivec. */ + iovs = k5calloc(num_data + 1, sizeof(*iovs), &ret); + if (iovs == NULL) + goto cleanup; + iovs[0].flags = KRB5_CRYPTO_TYPE_DATA; + iovs[0].data = *ivec; + memcpy(iovs + 1, data, num_data * sizeof(*iovs)); + + ret = alloc_data(out, ktp->hash->hashsize); + if (ret) + goto cleanup; + kb.length = ki->length; + kb.contents = (uint8_t *)ki->data; + ret = krb5int_hmac_keyblock(ktp->hash, &kb, iovs, num_data + 1, out); + +cleanup: + if (zeroivec.data != NULL) + ktp->enc->free_state(&zeroivec); + free(iovs); + return ret; +} + +krb5_error_code +krb5int_etm_encrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + const struct krb5_enc_provider *enc = ktp->enc; + krb5_error_code ret; + krb5_data ivcopy = empty_data(), cksum = empty_data(); + krb5_crypto_iov *header, *trailer, *padding; + krb5_key ke = NULL; + krb5_data ki = empty_data(); + unsigned int trailer_len; + + /* E(Confounder | Plaintext) | Checksum(IV | ciphertext) */ + + trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + + /* Validate header and trailer lengths, and zero out padding length. */ + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length < enc->block_size) + return KRB5_BAD_MSIZE; + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length < trailer_len) + return KRB5_BAD_MSIZE; + padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING); + if (padding != NULL) + padding->data.length = 0; + + if (ivec != NULL) { + ret = alloc_data(&ivcopy, ivec->length); + if (ret) + goto cleanup; + memcpy(ivcopy.data, ivec->data, ivec->length); + } + + /* Derive the encryption and integrity keys. */ + ret = derive_keys(ktp, key, usage, &ke, &ki); + if (ret) + goto cleanup; + + /* Generate confounder. */ + header->data.length = enc->block_size; + ret = krb5_c_random_make_octets(NULL, &header->data); + if (ret) + goto cleanup; + + /* Encrypt the plaintext (header | data). */ + ret = enc->encrypt(ke, (ivec == NULL) ? NULL : &ivcopy, data, num_data); + if (ret) + goto cleanup; + + /* HMAC the IV, confounder, and ciphertext with sign-only data. */ + ret = hmac_ivec_data(ktp, &ki, ivec, data, num_data, &cksum); + if (ret) + goto cleanup; + + /* Truncate the HMAC checksum to the trailer length. */ + assert(trailer_len <= cksum.length); + memcpy(trailer->data.data, cksum.data, trailer_len); + trailer->data.length = trailer_len; + + /* Copy out the updated ivec if desired. */ + if (ivec != NULL) + memcpy(ivec->data, ivcopy.data, ivcopy.length); + +cleanup: + krb5_k_free_key(NULL, ke); + zapfree(ki.data, ki.length); + free(cksum.data); + zapfree(ivcopy.data, ivcopy.length); + return ret; +} + +krb5_error_code +krb5int_etm_decrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + const struct krb5_enc_provider *enc = ktp->enc; + krb5_error_code ret; + krb5_data cksum = empty_data(); + krb5_crypto_iov *header, *trailer; + krb5_key ke = NULL; + krb5_data ki = empty_data(); + unsigned int trailer_len; + + trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + + /* Validate header and trailer lengths. */ + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || header->data.length != enc->block_size) + return KRB5_BAD_MSIZE; + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer == NULL || trailer->data.length != trailer_len) + return KRB5_BAD_MSIZE; + + /* Derive the encryption and integrity keys. */ + ret = derive_keys(ktp, key, usage, &ke, &ki); + if (ret) + goto cleanup; + + /* HMAC the IV, confounder, and ciphertext with sign-only data. */ + ret = hmac_ivec_data(ktp, &ki, ivec, data, num_data, &cksum); + if (ret) + goto cleanup; + + /* Compare only the possibly truncated length. */ + assert(trailer_len <= cksum.length); + if (k5_bcmp(cksum.data, trailer->data.data, trailer_len) != 0) { + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + + /* Decrypt the ciphertext (header | data | padding). */ + ret = enc->decrypt(ke, ivec, data, num_data); + +cleanup: + krb5_k_free_key(NULL, ke); + zapfree(ki.data, ki.length); + zapfree(cksum.data, cksum.length); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/enc_raw.c b/krb5-1.21.3/src/lib/crypto/krb/enc_raw.c new file mode 100644 index 00000000..554d5c4d --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/enc_raw.c @@ -0,0 +1,109 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/enc_raw.c */ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + + +#include "crypto_int.h" + +unsigned int +krb5int_raw_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_PADDING: + return ktp->enc->block_size; + default: + return 0; + } +} + +krb5_error_code +krb5int_raw_encrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + krb5_crypto_iov *padding; + size_t i; + unsigned int blocksize, plainlen = 0, padsize = 0; + + blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING); + + for (i = 0; i < num_data; i++) { + krb5_crypto_iov *iov = &data[i]; + + if (iov->flags == KRB5_CRYPTO_TYPE_DATA) + plainlen += iov->data.length; + } + + if (blocksize != 0) { + /* Check that the input data is correctly padded */ + if (plainlen % blocksize) + padsize = blocksize - (plainlen % blocksize); + } + + padding = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_PADDING); + if (padsize && (padding == NULL || padding->data.length < padsize)) + return KRB5_BAD_MSIZE; + + if (padding != NULL) { + memset(padding->data.data, 0, padsize); + padding->data.length = padsize; + } + + return ktp->enc->encrypt(key, ivec, data, num_data); +} + +krb5_error_code +krb5int_raw_decrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + size_t i; + unsigned int blocksize = 0; /* enc block size, not confounder len */ + unsigned int cipherlen = 0; + + /* E(Confounder | Plaintext | Pad) | Checksum */ + + blocksize = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_PADDING); + + for (i = 0; i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (ENCRYPT_DATA_IOV(iov)) + cipherlen += iov->data.length; + } + + if (blocksize == 0) { + /* Check for correct input length in CTS mode */ + if (ktp->enc->block_size != 0 && cipherlen < ktp->enc->block_size) + return KRB5_BAD_MSIZE; + } else { + /* Check that the input data is correctly padded */ + if (cipherlen % blocksize != 0) + return KRB5_BAD_MSIZE; + } + + return ktp->enc->decrypt(key, ivec, data, num_data); +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/enc_rc4.c b/krb5-1.21.3/src/lib/crypto/krb/enc_rc4.c new file mode 100644 index 00000000..aac8508b --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/enc_rc4.c @@ -0,0 +1,347 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + + ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95). + This cipher is widely believed and has been tested to be equivalent + with the RC4 cipher from RSA Data Security, Inc. (RC4 is a trademark + of RSA Data Security) + +*/ +#include "crypto_int.h" + +#define CONFOUNDERLENGTH 8 + +const char l40[] = "fortybits"; + +krb5_keyusage +krb5int_arcfour_translate_usage(krb5_keyusage usage) +{ + switch (usage) { + case 1: return 1; /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, */ + case 2: return 2; /* ticket from kdc */ + case 3: return 8; /* as-rep encrypted part */ + case 4: return 4; /* tgs-req authz data */ + case 5: return 5; /* tgs-req authz data in subkey */ + case 6: return 6; /* tgs-req authenticator cksum */ + case 7: return 7; /* tgs-req authenticator */ + case 8: return 8; + case 9: return 9; /* tgs-rep encrypted with subkey */ + case 10: return 10; /* ap-rep authentication cksum (never used by MS) */ + case 11: return 11; /* app-req authenticator */ + case 12: return 12; /* app-rep encrypted part */ + case 23: return 13; /* sign wrap token*/ + default: return usage; + } +} + +/* Derive a usage key from a session key and krb5 usage constant. */ +static krb5_error_code +usage_key(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *session_keyblock, krb5_keyusage usage, + krb5_keyblock *out) +{ + char salt_buf[14]; + unsigned int salt_len; + krb5_data out_data = make_data(out->contents, out->length); + krb5_crypto_iov iov; + krb5_keyusage ms_usage; + + /* Generate the salt. */ + ms_usage = krb5int_arcfour_translate_usage(usage); + if (session_keyblock->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + memcpy(salt_buf, l40, 10); + store_32_le(ms_usage, salt_buf + 10); + salt_len = 14; + } else { + store_32_le(ms_usage, salt_buf); + salt_len = 4; + } + + /* Compute HMAC(key, salt) to produce the usage key. */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data(salt_buf, salt_len); + return krb5int_hmac_keyblock(hash, session_keyblock, &iov, 1, &out_data); +} + +/* Derive an encryption key from a usage key and (typically) checksum. */ +static krb5_error_code +enc_key(const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *usage_keyblock, const krb5_data *checksum, + krb5_keyblock *out) +{ + krb5_keyblock *trunc_keyblock = NULL; + krb5_data out_data = make_data(out->contents, out->length); + krb5_crypto_iov iov; + krb5_error_code ret; + + /* Copy usage_keyblock to trunc_keyblock and truncate if exportable. */ + ret = krb5int_c_copy_keyblock(NULL, usage_keyblock, &trunc_keyblock); + if (ret != 0) + return ret; + if (trunc_keyblock->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + memset(trunc_keyblock->contents + 7, 0xab, 9); + + /* Compute HMAC(trunc_key, checksum) to produce the encryption key. */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *checksum; + ret = krb5int_hmac_keyblock(hash, trunc_keyblock, &iov, 1, &out_data); + krb5int_c_free_keyblock(NULL, trunc_keyblock); + return ret; +} + +unsigned int +krb5int_arcfour_crypto_length(const struct krb5_keytypes *ktp, + krb5_cryptotype type) +{ + switch (type) { + case KRB5_CRYPTO_TYPE_HEADER: + return ktp->hash->hashsize + CONFOUNDERLENGTH; + case KRB5_CRYPTO_TYPE_PADDING: + case KRB5_CRYPTO_TYPE_TRAILER: + return 0; + case KRB5_CRYPTO_TYPE_CHECKSUM: + return ktp->hash->hashsize; + default: + assert(0 && + "invalid cryptotype passed to krb5int_arcfour_crypto_length"); + return 0; + } +} + +/* Encrypt or decrypt using a keyblock. */ +static krb5_error_code +keyblock_crypt(const struct krb5_enc_provider *enc, krb5_keyblock *keyblock, + const krb5_data *ivec, krb5_crypto_iov *data, size_t num_data) +{ + krb5_error_code ret; + krb5_key key; + + ret = krb5_k_create_key(NULL, keyblock, &key); + if (ret != 0) + return ret; + /* Works for encryption or decryption since arcfour is a stream cipher. */ + ret = enc->encrypt(key, ivec, data, num_data); + krb5_k_free_key(NULL, key); + return ret; +} + +krb5_error_code +krb5int_arcfour_encrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + const struct krb5_enc_provider *enc = ktp->enc; + const struct krb5_hash_provider *hash = ktp->hash; + krb5_error_code ret; + krb5_crypto_iov *header, *trailer; + krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL; + krb5_data checksum, confounder, header_data; + size_t i; + + /* + * Caller must have provided space for the header, padding + * and trailer; per RFC 4757 we will arrange it as: + * + * Checksum | E(Confounder | Plaintext) + */ + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || + header->data.length < hash->hashsize + CONFOUNDERLENGTH) + return KRB5_BAD_MSIZE; + + header_data = header->data; + + /* Trailer may be absent. */ + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer != NULL) + trailer->data.length = 0; + + /* Ensure that there is no padding. */ + for (i = 0; i < num_data; i++) { + if (data[i].flags == KRB5_CRYPTO_TYPE_PADDING) + data[i].data.length = 0; + } + + ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes, + &usage_keyblock); + if (ret != 0) + goto cleanup; + ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes, + &enc_keyblock); + if (ret != 0) + goto cleanup; + + /* Derive a usage key from the session key and usage. */ + ret = usage_key(enc, hash, &key->keyblock, usage, usage_keyblock); + if (ret != 0) + goto cleanup; + + /* Generate a confounder in the header block, after the checksum. */ + header->data.length = hash->hashsize + CONFOUNDERLENGTH; + confounder = make_data(header->data.data + hash->hashsize, + CONFOUNDERLENGTH); + ret = krb5_c_random_make_octets(0, &confounder); + if (ret != 0) + goto cleanup; + checksum = make_data(header->data.data, hash->hashsize); + + /* Adjust pointers so confounder is at start of header. */ + header->data.length -= hash->hashsize; + header->data.data += hash->hashsize; + + /* Compute the checksum using the usage key. */ + ret = krb5int_hmac_keyblock(hash, usage_keyblock, data, num_data, + &checksum); + if (ret != 0) + goto cleanup; + + /* Derive the encryption key from the usage key and checksum. */ + ret = enc_key(enc, hash, usage_keyblock, &checksum, enc_keyblock); + if (ret) + goto cleanup; + + ret = keyblock_crypt(enc, enc_keyblock, ivec, data, num_data); + +cleanup: + header->data = header_data; /* Restore header pointers. */ + krb5int_c_free_keyblock(NULL, usage_keyblock); + krb5int_c_free_keyblock(NULL, enc_keyblock); + return ret; +} + +krb5_error_code +krb5int_arcfour_decrypt(const struct krb5_keytypes *ktp, krb5_key key, + krb5_keyusage usage, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + const struct krb5_enc_provider *enc = ktp->enc; + const struct krb5_hash_provider *hash = ktp->hash; + krb5_error_code ret; + krb5_crypto_iov *header, *trailer; + krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL; + krb5_data checksum, header_data, comp_checksum = empty_data(); + + header = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (header == NULL || + header->data.length != hash->hashsize + CONFOUNDERLENGTH) + return KRB5_BAD_MSIZE; + + header_data = header->data; + + trailer = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (trailer != NULL && trailer->data.length != 0) + return KRB5_BAD_MSIZE; + + /* Allocate buffers. */ + ret = alloc_data(&comp_checksum, hash->hashsize); + if (ret != 0) + goto cleanup; + ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes, + &usage_keyblock); + if (ret != 0) + goto cleanup; + ret = krb5int_c_init_keyblock(NULL, key->keyblock.enctype, enc->keybytes, + &enc_keyblock); + if (ret != 0) + goto cleanup; + + checksum = make_data(header->data.data, hash->hashsize); + + /* Adjust pointers so confounder is at start of header. */ + header->data.length -= hash->hashsize; + header->data.data += hash->hashsize; + + /* We may have to try two usage values; see below. */ + do { + /* Derive a usage key from the session key and usage. */ + ret = usage_key(enc, hash, &key->keyblock, usage, usage_keyblock); + if (ret != 0) + goto cleanup; + + /* Derive the encryption key from the usage key and checksum. */ + ret = enc_key(enc, hash, usage_keyblock, &checksum, enc_keyblock); + if (ret) + goto cleanup; + + /* Decrypt the ciphertext. */ + ret = keyblock_crypt(enc, enc_keyblock, ivec, data, num_data); + if (ret != 0) + goto cleanup; + + /* Compute HMAC(usage key, plaintext) to get the checksum. */ + ret = krb5int_hmac_keyblock(hash, usage_keyblock, data, num_data, + &comp_checksum); + if (ret != 0) + goto cleanup; + + if (k5_bcmp(checksum.data, comp_checksum.data, hash->hashsize) != 0) { + if (usage == 9) { + /* + * RFC 4757 specifies usage 8 for TGS-REP encrypted parts + * encrypted in a subkey, but the value used by MS is actually + * 9. We now use 9 to start with, but fall back to 8 on + * failure in case we are communicating with a KDC using the + * value from the RFC. ivec is always NULL in this case. + * We need to re-encrypt the data in the wrong key first. + */ + ret = keyblock_crypt(enc, enc_keyblock, NULL, data, num_data); + if (ret != 0) + goto cleanup; + usage = 8; + continue; + } + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto cleanup; + } + + break; + } while (1); + +cleanup: + header->data = header_data; /* Restore header pointers. */ + krb5int_c_free_keyblock(NULL, usage_keyblock); + krb5int_c_free_keyblock(NULL, enc_keyblock); + zapfree(comp_checksum.data, comp_checksum.length); + return ret; +} + +krb5_error_code +krb5int_arcfour_gsscrypt(const krb5_keyblock *keyblock, krb5_keyusage usage, + const krb5_data *kd_data, krb5_crypto_iov *data, + size_t num_data) +{ + const struct krb5_enc_provider *enc = &krb5int_enc_arcfour; + const struct krb5_hash_provider *hash = &krb5int_hash_md5; + krb5_keyblock *usage_keyblock = NULL, *enc_keyblock = NULL; + krb5_error_code ret; + + ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes, + &usage_keyblock); + if (ret != 0) + goto cleanup; + ret = krb5int_c_init_keyblock(NULL, keyblock->enctype, enc->keybytes, + &enc_keyblock); + if (ret != 0) + goto cleanup; + + /* Derive a usage key from the session key and usage. */ + ret = usage_key(enc, hash, keyblock, usage, usage_keyblock); + if (ret != 0) + goto cleanup; + + /* Derive the encryption key from the usage key and kd_data. */ + ret = enc_key(enc, hash, usage_keyblock, kd_data, enc_keyblock); + if (ret != 0) + goto cleanup; + + /* Encrypt or decrypt (encrypt_iov works for both) the input. */ + ret = keyblock_crypt(enc, enc_keyblock, 0, data, num_data); + +cleanup: + krb5int_c_free_keyblock(NULL, usage_keyblock); + krb5int_c_free_keyblock(NULL, enc_keyblock); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/encrypt.c b/krb5-1.21.3/src/lib/crypto/krb/encrypt.c new file mode 100644 index 00000000..d9d575a4 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/encrypt.c @@ -0,0 +1,94 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_encrypt(krb5_context context, krb5_key key, + krb5_keyusage usage, const krb5_data *cipher_state, + const krb5_data *input, krb5_enc_data *output) +{ + const struct krb5_keytypes *ktp; + krb5_crypto_iov iov[4]; + krb5_error_code ret; + unsigned int header_len, padding_len, trailer_len, total_len; + + ktp = find_enctype(key->keyblock.enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + output->magic = KV5M_ENC_DATA; + output->kvno = 0; + output->enctype = key->keyblock.enctype; + + /* Get the lengths of the token parts and compute the total. */ + header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER); + padding_len = krb5int_c_padding_length(ktp, input->length); + trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + total_len = header_len + input->length + padding_len + trailer_len; + if (output->ciphertext.length < total_len) + return KRB5_BAD_MSIZE; + + /* Set up the iov structures for the token parts. */ + iov[0].flags = KRB5_CRYPTO_TYPE_HEADER; + iov[0].data = make_data(output->ciphertext.data, header_len); + + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data = make_data(output->ciphertext.data + header_len, + input->length); + if (input->length > 0) + memcpy(iov[1].data.data, input->data, input->length); + + iov[2].flags = KRB5_CRYPTO_TYPE_PADDING; + iov[2].data = make_data(iov[1].data.data + input->length, padding_len); + + iov[3].flags = KRB5_CRYPTO_TYPE_TRAILER; + iov[3].data = make_data(iov[2].data.data + padding_len, trailer_len); + + ret = ktp->encrypt(ktp, key, usage, cipher_state, iov, 4); + if (ret != 0) + zap(iov[1].data.data, iov[1].data.length); + else + output->ciphertext.length = total_len; + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_encrypt(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *cipher_state, + const krb5_data *input, krb5_enc_data *output) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_encrypt(context, key, usage, cipher_state, input, output); + krb5_k_free_key(context, key); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/encrypt_iov.c b/krb5-1.21.3/src/lib/crypto/krb/encrypt_iov.c new file mode 100644 index 00000000..d66fcfa5 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/encrypt_iov.c @@ -0,0 +1,58 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/encrypt_iov.c */ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_encrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage, + const krb5_data *cipher_state, krb5_crypto_iov *data, + size_t num_data) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(key->keyblock.enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + return ktp->encrypt(ktp, key, usage, cipher_state, data, num_data); +} + +krb5_error_code KRB5_CALLCONV +krb5_c_encrypt_iov(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *cipher_state, + krb5_crypto_iov *data, size_t num_data) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_encrypt_iov(context, key, usage, cipher_state, data, + num_data); + krb5_k_free_key(context, key); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/encrypt_length.c b/krb5-1.21.3/src/lib/crypto/krb/encrypt_length.c new file mode 100644 index 00000000..5428e429 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/encrypt_length.c @@ -0,0 +1,47 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_encrypt_length(krb5_context context, krb5_enctype enctype, + size_t inputlen, size_t *length) +{ + const struct krb5_keytypes *ktp; + unsigned int header_len = 0, padding_len = 0, trailer_len = 0; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + header_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_HEADER); + padding_len = krb5int_c_padding_length(ktp, inputlen); + trailer_len = ktp->crypto_length(ktp, KRB5_CRYPTO_TYPE_TRAILER); + + *length = header_len + inputlen + padding_len + trailer_len; + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/enctype_util.c b/krb5-1.21.3/src/lib/crypto/krb/enctype_util.c new file mode 100644 index 00000000..1542d406 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/enctype_util.c @@ -0,0 +1,176 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/enctype_util.c */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * krb5int_c_valid_enctype() + * krb5int_c_weak_enctype() + * krb5_c_enctype_compare() + * krb5_string_to_enctype() + * krb5_enctype_to_string() + */ + +#include "crypto_int.h" + +struct { + krb5_enctype etype; + const char *name; +} unsupported_etypes[] = { + { ENCTYPE_DES_CBC_CRC, "des-cbc-crc" }, + { ENCTYPE_DES_CBC_MD4, "des-cbc-md4" }, + { ENCTYPE_DES_CBC_MD5, "des-cbc-md5" }, + { ENCTYPE_DES_CBC_RAW, "des-cbc-raw" }, + { ENCTYPE_DES_HMAC_SHA1, "des-hmac-sha1" }, + { ENCTYPE_NULL, NULL } +}; + +krb5_boolean KRB5_CALLCONV +krb5_c_valid_enctype(krb5_enctype etype) +{ + return (find_enctype(etype) != NULL); +} + +krb5_boolean KRB5_CALLCONV +krb5int_c_weak_enctype(krb5_enctype etype) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(etype); + return (ktp != NULL && (ktp->flags & ETYPE_WEAK) != 0); +} + +krb5_boolean KRB5_CALLCONV +krb5int_c_deprecated_enctype(krb5_enctype etype) +{ + const struct krb5_keytypes *ktp = find_enctype(etype); + return ktp == NULL || (ktp->flags & ETYPE_DEPRECATED) != 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_enctype_compare(krb5_context context, krb5_enctype e1, krb5_enctype e2, + krb5_boolean *similar) +{ + const struct krb5_keytypes *ktp1, *ktp2; + + ktp1 = find_enctype(e1); + ktp2 = find_enctype(e2); + if (ktp1 == NULL || ktp2 == NULL) + return KRB5_BAD_ENCTYPE; + + *similar = (ktp1->enc == ktp2->enc && ktp1->str2key == ktp2->str2key); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_string_to_enctype(char *string, krb5_enctype *enctypep) +{ + int i; + unsigned int j; + const char *alias; + const struct krb5_keytypes *ktp; + + for (i = 0; i < krb5int_enctypes_length; i++) { + ktp = &krb5int_enctypes_list[i]; + if (strcasecmp(ktp->name, string) == 0) { + *enctypep = ktp->etype; + return 0; + } + for (j = 0; j < MAX_ETYPE_ALIASES; j++) { + alias = ktp->aliases[j]; + if (alias == NULL) + break; + if (strcasecmp(alias, string) == 0) { + *enctypep = ktp->etype; + return 0; + } + } + } + + return EINVAL; +} + +krb5_error_code KRB5_CALLCONV +krb5_enctype_to_string(krb5_enctype enctype, char *buffer, size_t buflen) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return EINVAL; + if (strlcpy(buffer, ktp->out_string, buflen) >= buflen) + return ENOMEM; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_enctype_to_name(krb5_enctype enctype, krb5_boolean shortest, + char *buffer, size_t buflen) +{ + const struct krb5_keytypes *ktp; + const char *name; + int i; + + for (i = 0; unsupported_etypes[i].etype != ENCTYPE_NULL; i++) { + if (enctype == unsupported_etypes[i].etype) { + if (strlcpy(buffer, unsupported_etypes[i].name, buflen) >= buflen) + return ENOMEM; + return 0; + } + } + + ktp = find_enctype(enctype); + if (ktp == NULL) + return EINVAL; + name = ktp->name; + if (shortest) { + for (i = 0; i < MAX_ETYPE_ALIASES; i++) { + if (ktp->aliases[i] == NULL) + break; + if (strlen(ktp->aliases[i]) < strlen(name)) + name = ktp->aliases[i]; + } + } + if (strlcpy(buffer, name, buflen) >= buflen) + return ENOMEM; + return 0; +} + +/* The security of a mechanism cannot be summarized with a simple integer + * value, but we provide a per-enctype value for Cyrus SASL's SSF. */ +krb5_error_code +k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out) +{ + const struct krb5_keytypes *ktp; + + *ssf_out = 0; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return EINVAL; + *ssf_out = ktp->ssf; + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/etypes.c b/krb5-1.21.3/src/lib/crypto/krb/etypes.c new file mode 100644 index 00000000..fc278783 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/etypes.c @@ -0,0 +1,152 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +/* these will be linear searched. if they ever get big, a binary + search or hash table would be better, which means these would need + to be sorted. An array would be more efficient, but that assumes + that the keytypes are all near each other. I'd rather not make + that assumption. */ + +/* Deprecations come from RFC 6649 and RFC 8249. */ +const struct krb5_keytypes krb5int_enctypes_list[] = { + { ENCTYPE_DES3_CBC_RAW, + "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw", + &krb5int_enc_des3, NULL, + 16, + krb5int_raw_crypto_length, krb5int_raw_encrypt, krb5int_raw_decrypt, + krb5int_dk_string_to_key, k5_rand2key_des3, + NULL, /*PRF*/ + 0, + ETYPE_WEAK | ETYPE_DEPRECATED, 112 }, + + { ENCTYPE_DES3_CBC_SHA1, + "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" }, + "Triple DES cbc mode with HMAC/sha1", + &krb5int_enc_des3, &krb5int_hash_sha1, + 16, + krb5int_dk_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt, + krb5int_dk_string_to_key, k5_rand2key_des3, + krb5int_dk_prf, + CKSUMTYPE_HMAC_SHA1_DES3, + ETYPE_DEPRECATED, 112 }, + + /* rc4-hmac uses a 128-bit key, but due to weaknesses in the RC4 cipher, we + * consider its strength degraded and assign it an SSF value of 64. */ + { ENCTYPE_ARCFOUR_HMAC, + "arcfour-hmac", { "rc4-hmac", "arcfour-hmac-md5" }, + "ArcFour with HMAC/md5", + &krb5int_enc_arcfour, + &krb5int_hash_md5, + 20, + krb5int_arcfour_crypto_length, krb5int_arcfour_encrypt, + krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key, + k5_rand2key_direct, krb5int_arcfour_prf, + CKSUMTYPE_HMAC_MD5_ARCFOUR, + ETYPE_DEPRECATED, 64 }, + { ENCTYPE_ARCFOUR_HMAC_EXP, + "arcfour-hmac-exp", { "rc4-hmac-exp", "arcfour-hmac-md5-exp" }, + "Exportable ArcFour with HMAC/md5", + &krb5int_enc_arcfour, + &krb5int_hash_md5, + 20, + krb5int_arcfour_crypto_length, krb5int_arcfour_encrypt, + krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key, + k5_rand2key_direct, krb5int_arcfour_prf, + CKSUMTYPE_HMAC_MD5_ARCFOUR, + ETYPE_WEAK | ETYPE_DEPRECATED, 40 + }, + + { ENCTYPE_AES128_CTS_HMAC_SHA1_96, + "aes128-cts-hmac-sha1-96", { "aes128-cts", "aes128-sha1" }, + "AES-128 CTS mode with 96-bit SHA-1 HMAC", + &krb5int_enc_aes128, &krb5int_hash_sha1, + 16, + krb5int_aes_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt, + krb5int_aes_string_to_key, k5_rand2key_direct, + krb5int_dk_prf, + CKSUMTYPE_HMAC_SHA1_96_AES128, + 0 /*flags*/, 128 }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, + "aes256-cts-hmac-sha1-96", { "aes256-cts", "aes256-sha1" }, + "AES-256 CTS mode with 96-bit SHA-1 HMAC", + &krb5int_enc_aes256, &krb5int_hash_sha1, + 16, + krb5int_aes_crypto_length, krb5int_dk_encrypt, krb5int_dk_decrypt, + krb5int_aes_string_to_key, k5_rand2key_direct, + krb5int_dk_prf, + CKSUMTYPE_HMAC_SHA1_96_AES256, + 0 /*flags*/, 256 }, + + { ENCTYPE_CAMELLIA128_CTS_CMAC, + "camellia128-cts-cmac", { "camellia128-cts" }, + "Camellia-128 CTS mode with CMAC", + &krb5int_enc_camellia128, NULL, + 16, + krb5int_camellia_crypto_length, + krb5int_dk_cmac_encrypt, krb5int_dk_cmac_decrypt, + krb5int_camellia_string_to_key, k5_rand2key_direct, + krb5int_dk_cmac_prf, + CKSUMTYPE_CMAC_CAMELLIA128, + 0 /*flags*/, 128 }, + { ENCTYPE_CAMELLIA256_CTS_CMAC, + "camellia256-cts-cmac", { "camellia256-cts" }, + "Camellia-256 CTS mode with CMAC", + &krb5int_enc_camellia256, NULL, + 16, + krb5int_camellia_crypto_length, + krb5int_dk_cmac_encrypt, krb5int_dk_cmac_decrypt, + krb5int_camellia_string_to_key, k5_rand2key_direct, + krb5int_dk_cmac_prf, + CKSUMTYPE_CMAC_CAMELLIA256, + 0 /*flags */, 256 }, + + { ENCTYPE_AES128_CTS_HMAC_SHA256_128, + "aes128-cts-hmac-sha256-128", { "aes128-sha2" }, + "AES-128 CTS mode with 128-bit SHA-256 HMAC", + &krb5int_enc_aes128, &krb5int_hash_sha256, + 32, + krb5int_aes2_crypto_length, krb5int_etm_encrypt, krb5int_etm_decrypt, + krb5int_aes2_string_to_key, k5_rand2key_direct, + krb5int_aes2_prf, + CKSUMTYPE_HMAC_SHA256_128_AES128, + 0 /*flags*/, 128 }, + { ENCTYPE_AES256_CTS_HMAC_SHA384_192, + "aes256-cts-hmac-sha384-192", { "aes256-sha2" }, + "AES-256 CTS mode with 192-bit SHA-384 HMAC", + &krb5int_enc_aes256, &krb5int_hash_sha384, + 48, + krb5int_aes2_crypto_length, krb5int_etm_encrypt, krb5int_etm_decrypt, + krb5int_aes2_string_to_key, k5_rand2key_direct, + krb5int_aes2_prf, + CKSUMTYPE_HMAC_SHA384_192_AES256, + 0 /*flags*/, 256 }, +}; + +const int krb5int_enctypes_length = + sizeof(krb5int_enctypes_list) / sizeof(struct krb5_keytypes); diff --git a/krb5-1.21.3/src/lib/crypto/krb/key.c b/krb5-1.21.3/src/lib/crypto/krb/key.c new file mode 100644 index 00000000..550ac20d --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/key.c @@ -0,0 +1,110 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * Functions for manipulating krb5_key structures + */ + +#include "crypto_int.h" + +/* + * The krb5_key data type wraps an exposed keyblock in an opaque data + * structure, to allow for internal optimizations such as caching of + * derived keys. + */ + +/* Create a krb5_key from the enctype and key data in a keyblock. */ +krb5_error_code KRB5_CALLCONV +krb5_k_create_key(krb5_context context, const krb5_keyblock *key_data, + krb5_key *out) +{ + krb5_key key = NULL; + krb5_error_code code; + + *out = NULL; + + key = malloc(sizeof(*key)); + if (key == NULL) + return ENOMEM; + code = krb5int_c_copy_keyblock_contents(context, key_data, &key->keyblock); + if (code) + goto cleanup; + + key->refcount = 1; + key->derived = NULL; + key->cache = NULL; + *out = key; + return 0; + +cleanup: + free(key); + return code; +} + +void KRB5_CALLCONV +krb5_k_reference_key(krb5_context context, krb5_key key) +{ + if (key) + key->refcount++; +} + +/* Free the memory used by a krb5_key. */ +void KRB5_CALLCONV +krb5_k_free_key(krb5_context context, krb5_key key) +{ + struct derived_key *dk; + const struct krb5_keytypes *ktp; + + if (key == NULL || --key->refcount > 0) + return; + + /* Free the derived key cache. */ + while ((dk = key->derived) != NULL) { + key->derived = dk->next; + free(dk->constant.data); + krb5_k_free_key(context, dk->dkey); + free(dk); + } + krb5int_c_free_keyblock_contents(context, &key->keyblock); + if (key->cache) { + ktp = find_enctype(key->keyblock.enctype); + if (ktp && ktp->enc->key_cleanup) + ktp->enc->key_cleanup(key); + } + free(key); +} + +/* Retrieve a copy of the keyblock from a krb5_key. */ +krb5_error_code KRB5_CALLCONV +krb5_k_key_keyblock(krb5_context context, krb5_key key, + krb5_keyblock **key_data) +{ + return krb5int_c_copy_keyblock(context, &key->keyblock, key_data); +} + +/* Retrieve the enctype of a krb5_key. */ +krb5_enctype KRB5_CALLCONV +krb5_k_key_enctype(krb5_context context, krb5_key key) +{ + return key->keyblock.enctype; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/keyblocks.c b/krb5-1.21.3/src/lib/crypto/krb/keyblocks.c new file mode 100644 index 00000000..1126d0a0 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/keyblocks.c @@ -0,0 +1,108 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/keyblocks.c - Keyblock utility functions */ +/* + * Copyright (C) 2002, 2005 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_c_init_keyblock(krb5_context context, krb5_enctype enctype, + size_t length, krb5_keyblock **out) +{ + krb5_keyblock *kb; + + assert(out); + *out = NULL; + + kb = malloc(sizeof(krb5_keyblock)); + if (kb == NULL) + return ENOMEM; + kb->magic = KV5M_KEYBLOCK; + kb->enctype = enctype; + kb->length = length; + if (length) { + kb->contents = malloc(length); + if (!kb->contents) { + free(kb); + return ENOMEM; + } + } else { + kb->contents = NULL; + } + + *out = kb; + return 0; +} + +void +krb5int_c_free_keyblock(krb5_context context, krb5_keyblock *val) +{ + krb5int_c_free_keyblock_contents(context, val); + free(val); +} + +void +krb5int_c_free_keyblock_contents(krb5_context context, krb5_keyblock *key) +{ + if (key && key->contents) { + zapfree(key->contents, key->length); + key->contents = NULL; + key->length = 0; + } +} + +krb5_error_code +krb5int_c_copy_keyblock(krb5_context context, const krb5_keyblock *from, + krb5_keyblock **to) +{ + krb5_keyblock *new_key; + krb5_error_code code; + + *to = NULL; + new_key = malloc(sizeof(*new_key)); + if (!new_key) + return ENOMEM; + code = krb5int_c_copy_keyblock_contents(context, from, new_key); + if (code) { + free(new_key); + return code; + } + *to = new_key; + return 0; +} + +krb5_error_code +krb5int_c_copy_keyblock_contents(krb5_context context, + const krb5_keyblock *from, krb5_keyblock *to) +{ + *to = *from; + if (to->length) { + to->contents = malloc(to->length); + if (!to->contents) + return ENOMEM; + memcpy(to->contents, from->contents, to->length); + } else + to->contents = 0; + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/keyed_checksum_types.c b/krb5-1.21.3/src/lib/crypto/krb/keyed_checksum_types.c new file mode 100644 index 00000000..4b211fb4 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/keyed_checksum_types.c @@ -0,0 +1,82 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +static krb5_boolean +is_keyed_for(const struct krb5_cksumtypes *ctp, + const struct krb5_keytypes *ktp) +{ + if (ctp->flags & CKSUM_UNKEYED) + return FALSE; + return (!ctp->enc || ktp->enc == ctp->enc); +} + +krb5_error_code KRB5_CALLCONV +krb5_c_keyed_checksum_types(krb5_context context, krb5_enctype enctype, + unsigned int *count, krb5_cksumtype **cksumtypes) +{ + unsigned int i, c, nctypes; + krb5_cksumtype *ctypes; + const struct krb5_cksumtypes *ctp; + const struct krb5_keytypes *ktp; + + *count = 0; + *cksumtypes = NULL; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + nctypes = 0; + for (i = 0; i < krb5int_cksumtypes_length; i++) { + ctp = &krb5int_cksumtypes_list[i]; + if (is_keyed_for(ctp, ktp)) + nctypes++; + } + + ctypes = malloc(nctypes * sizeof(krb5_cksumtype)); + if (ctypes == NULL) + return ENOMEM; + + c = 0; + for (i = 0; i < krb5int_cksumtypes_length; i++) { + ctp = &krb5int_cksumtypes_list[i]; + if (is_keyed_for(ctp, ktp)) + ctypes[c++] = ctp->ctype; + } + + *count = nctypes; + *cksumtypes = ctypes; + return 0; +} + +void KRB5_CALLCONV +krb5_free_cksumtypes(krb5_context context, krb5_cksumtype *val) +{ + free(val); +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/keyed_cksum.c b/krb5-1.21.3/src/lib/crypto/krb/keyed_cksum.c new file mode 100644 index 00000000..d3db8f31 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/keyed_cksum.c @@ -0,0 +1,39 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +krb5_boolean KRB5_CALLCONV +krb5_c_is_keyed_cksum(krb5_cksumtype ctype) +{ + const struct krb5_cksumtypes *ctp; + + ctp = find_cksumtype(ctype); + if (ctp == NULL) + return FALSE; + return !(ctp->flags & CKSUM_UNKEYED); +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/keylengths.c b/krb5-1.21.3/src/lib/crypto/krb/keylengths.c new file mode 100644 index 00000000..2bbd1cc6 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/keylengths.c @@ -0,0 +1,57 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * COPYRIGHT (c) 2006 + * The Regents of the University of Michigan + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#include "crypto_int.h" + +/* + * keybytes is the number of bytes required as input to make a key, + * keylength is the length of the final key in bytes + */ +krb5_error_code KRB5_CALLCONV +krb5_c_keylengths(krb5_context context, krb5_enctype enctype, + size_t *keybytes, size_t *keylength) +{ + const struct krb5_keytypes *ktp; + + if (keybytes == NULL && keylength == NULL) + return EINVAL; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + if (keybytes) + *keybytes = ktp->enc->keybytes; + if (keylength) + *keylength = ktp->enc->keylength; + + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/make_checksum.c b/krb5-1.21.3/src/lib/crypto/krb/make_checksum.c new file mode 100644 index 00000000..398c84a8 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/make_checksum.c @@ -0,0 +1,99 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +/* A 0 checksum type means use the mandatory checksum. */ + +krb5_error_code KRB5_CALLCONV +krb5_k_make_checksum(krb5_context context, krb5_cksumtype cksumtype, + krb5_key key, krb5_keyusage usage, + const krb5_data *input, krb5_checksum *cksum) +{ + const struct krb5_cksumtypes *ctp; + krb5_crypto_iov iov; + krb5_data cksum_data; + krb5_octet *trunc; + krb5_error_code ret; + + if (cksumtype == 0) { + ret = krb5int_c_mandatory_cksumtype(context, key->keyblock.enctype, + &cksumtype); + if (ret != 0) + return ret; + } + ctp = find_cksumtype(cksumtype); + if (ctp == NULL) + return KRB5_BAD_ENCTYPE; + + ret = verify_key(ctp, key); + if (ret != 0) + return ret; + + ret = alloc_data(&cksum_data, ctp->compute_size); + if (ret != 0) + return ret; + + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *input; + ret = ctp->checksum(ctp, key, usage, &iov, 1, &cksum_data); + if (ret != 0) + goto cleanup; + + cksum->magic = KV5M_CHECKSUM; + cksum->checksum_type = cksumtype; + cksum->length = ctp->output_size; + cksum->contents = (krb5_octet *) cksum_data.data; + cksum_data.data = NULL; + if (ctp->output_size < ctp->compute_size) { + trunc = realloc(cksum->contents, ctp->output_size); + if (trunc != NULL) + cksum->contents = trunc; + } + +cleanup: + zapfree(cksum_data.data, ctp->compute_size); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_make_checksum(krb5_context context, krb5_cksumtype cksumtype, + const krb5_keyblock *keyblock, krb5_keyusage usage, + const krb5_data *input, krb5_checksum *cksum) +{ + krb5_key key = NULL; + krb5_error_code ret; + + if (keyblock != NULL) { + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + } + ret = krb5_k_make_checksum(context, cksumtype, key, usage, input, cksum); + krb5_k_free_key(context, key); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/make_checksum_iov.c b/krb5-1.21.3/src/lib/crypto/krb/make_checksum_iov.c new file mode 100644 index 00000000..549180df --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/make_checksum_iov.c @@ -0,0 +1,94 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/make_checksum_iov.c */ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_make_checksum_iov(krb5_context context, + krb5_cksumtype cksumtype, + krb5_key key, + krb5_keyusage usage, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_error_code ret; + krb5_data cksum_data; + krb5_crypto_iov *checksum; + const struct krb5_cksumtypes *ctp; + + if (cksumtype == 0) { + ret = krb5int_c_mandatory_cksumtype(context, key->keyblock.enctype, + &cksumtype); + if (ret != 0) + return ret; + } + ctp = find_cksumtype(cksumtype); + if (ctp == NULL) + return KRB5_BAD_ENCTYPE; + + ret = verify_key(ctp, key); + if (ret != 0) + return ret; + + checksum = krb5int_c_locate_iov(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM); + if (checksum == NULL || checksum->data.length < ctp->output_size) + return(KRB5_BAD_MSIZE); + + ret = alloc_data(&cksum_data, ctp->compute_size); + if (ret != 0) + return ret; + + ret = ctp->checksum(ctp, key, usage, data, num_data, &cksum_data); + if (ret != 0) + goto cleanup; + + memcpy(checksum->data.data, cksum_data.data, ctp->output_size); + checksum->data.length = ctp->output_size; + +cleanup: + zapfree(cksum_data.data, ctp->compute_size); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_make_checksum_iov(krb5_context context, + krb5_cksumtype cksumtype, + const krb5_keyblock *keyblock, + krb5_keyusage usage, + krb5_crypto_iov *data, + size_t num_data) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_make_checksum_iov(context, cksumtype, key, usage, + data, num_data); + krb5_k_free_key(context, key); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/make_random_key.c b/krb5-1.21.3/src/lib/crypto/krb/make_random_key.c new file mode 100644 index 00000000..f5af1878 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/make_random_key.c @@ -0,0 +1,76 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_make_random_key(krb5_context context, krb5_enctype enctype, + krb5_keyblock *random_key) +{ + krb5_error_code ret; + const struct krb5_keytypes *ktp; + const struct krb5_enc_provider *enc; + size_t keybytes, keylength; + krb5_data random_data; + unsigned char *bytes = NULL; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + enc = ktp->enc; + + keybytes = enc->keybytes; + keylength = enc->keylength; + + bytes = k5alloc(keybytes, &ret); + if (ret) + return ret; + random_key->contents = k5alloc(keylength, &ret); + if (ret) + goto cleanup; + + random_data.data = (char *) bytes; + random_data.length = keybytes; + + ret = krb5_c_random_make_octets(context, &random_data); + if (ret) + goto cleanup; + + random_key->magic = KV5M_KEYBLOCK; + random_key->enctype = enctype; + random_key->length = keylength; + + ret = (*ktp->rand2key)(&random_data, random_key); + +cleanup: + if (ret) { + zapfree(random_key->contents, keylength); + random_key->contents = NULL; + } + zapfree(bytes, keybytes); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/mandatory_sumtype.c b/krb5-1.21.3/src/lib/crypto/krb/mandatory_sumtype.c new file mode 100644 index 00000000..55ea81fa --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/mandatory_sumtype.c @@ -0,0 +1,39 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2003 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_c_mandatory_cksumtype(krb5_context ctx, krb5_enctype etype, + krb5_cksumtype *cksumtype) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(etype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + *cksumtype = ktp->required_ctype; + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/nfold.c b/krb5-1.21.3/src/lib/crypto/krb/nfold.c new file mode 100644 index 00000000..75bceaec --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/nfold.c @@ -0,0 +1,117 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +/* + * n-fold(k-bits): + * l = lcm(n,k) + * r = l/k + * s = k-bits | k-bits rot 13 | k-bits rot 13*2 | ... | k-bits rot 13*(r-1) + * compute the 1's complement sum: + * n-fold = s[0..n-1]+s[n..2n-1]+s[2n..3n-1]+..+s[(k-1)*n..k*n-1] + */ + +/* representation: msb first, assume n and k are multiples of 8, and + * that k>=16. this is the case of all the cryptosystems which are + * likely to be used. this function can be replaced if that + * assumption ever fails. */ + +/* input length is in bits */ + +void +krb5int_nfold(unsigned int inbits, const unsigned char *in, unsigned int outbits, + unsigned char *out) +{ + int a,b,c,lcm; + int byte, i, msbit; + + /* the code below is more readable if I make these bytes + instead of bits */ + + inbits >>= 3; + outbits >>= 3; + + /* first compute lcm(n,k) */ + + a = outbits; + b = inbits; + + while(b != 0) { + c = b; + b = a%b; + a = c; + } + + lcm = outbits*inbits/a; + + /* now do the real work */ + + memset(out, 0, outbits); + byte = 0; + + /* this will end up cycling through k lcm(k,n)/k times, which + is correct */ + for (i=lcm-1; i>=0; i--) { + /* compute the msbit in k which gets added into this byte */ + msbit = (/* first, start with the msbit in the first, unrotated + byte */ + ((inbits<<3)-1) + /* then, for each byte, shift to the right for each + repetition */ + +(((inbits<<3)+13)*(i/inbits)) + /* last, pick out the correct byte within that + shifted repetition */ + +((inbits-(i%inbits))<<3) + )%(inbits<<3); + + /* pull out the byte value itself */ + byte += (((in[((inbits-1)-(msbit>>3))%inbits]<<8)| + (in[((inbits)-(msbit>>3))%inbits])) + >>((msbit&7)+1))&0xff; + + /* do the addition */ + byte += out[i%outbits]; + out[i%outbits] = byte&0xff; + + /* keep around the carry bit, if any */ + byte >>= 8; + + } + + /* if there's a carry bit left over, add it back in */ + if (byte) { + for (i=outbits-1; i>=0; i--) { + /* do the addition */ + byte += out[i]; + out[i] = byte&0xff; + + /* keep around the carry bit, if any */ + byte >>= 8; + } + } +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/old_api_glue.c b/krb5-1.21.3/src/lib/crypto/krb/old_api_glue.c new file mode 100644 index 00000000..b5bb2808 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/old_api_glue.c @@ -0,0 +1,390 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +/* + * The following functions were removed from the API in krb5 1.3 but + * still need to be exported for ABI compatibility. The other + * functions defined in this file are still in the API (and thus + * prototyped in krb5.hin) but are deprecated. + */ +krb5_boolean KRB5_CALLCONV valid_enctype(krb5_enctype ktype); +krb5_boolean KRB5_CALLCONV valid_cksumtype(krb5_cksumtype ctype); +krb5_boolean KRB5_CALLCONV is_coll_proof_cksum(krb5_cksumtype ctype); +krb5_boolean KRB5_CALLCONV is_keyed_cksum(krb5_cksumtype ctype); +krb5_error_code KRB5_CALLCONV krb5_random_confounder(size_t, krb5_pointer); +krb5_error_code krb5_encrypt_data(krb5_context context, krb5_keyblock *key, + krb5_pointer ivec, krb5_data *data, + krb5_enc_data *enc_data); +krb5_error_code krb5_decrypt_data(krb5_context context, krb5_keyblock *key, + krb5_pointer ivec, krb5_enc_data *data, + krb5_data *enc_data); + +krb5_error_code KRB5_CALLCONV +krb5_encrypt(krb5_context context, krb5_const_pointer inptr, + krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock, + krb5_pointer ivec) +{ + krb5_data inputd, ivecd; + krb5_enc_data outputd; + size_t blocksize, outlen; + krb5_error_code ret; + + if (ivec) { + ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize); + if (ret) + return ret; + + ivecd = make_data(ivec, blocksize); + } + + /* size is the length of the input cleartext data. */ + inputd = make_data((void *) inptr, size); + + /* + * The size of the output buffer isn't part of the old api. Not too + * safe. So, we assume here that it's big enough. + */ + ret = krb5_c_encrypt_length(context, eblock->key->enctype, size, &outlen); + if (ret) + return ret; + + outputd.ciphertext = make_data(outptr, outlen); + + return krb5_c_encrypt(context, eblock->key, 0, ivec ? &ivecd : 0, + &inputd, &outputd); +} + +krb5_error_code KRB5_CALLCONV +krb5_decrypt(krb5_context context, krb5_const_pointer inptr, + krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock, + krb5_pointer ivec) +{ + krb5_enc_data inputd; + krb5_data outputd, ivecd; + size_t blocksize; + krb5_error_code ret; + + if (ivec) { + ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize); + if (ret) + return ret; + + ivecd = make_data(ivec, blocksize); + } + + /* size is the length of the input ciphertext data */ + inputd.enctype = eblock->key->enctype; + inputd.ciphertext = make_data((void *) inptr, size); + + /* we don't really know how big this is, but the code tends to assume + that the output buffer size should be the same as the input + buffer size */ + outputd = make_data(outptr, size); + + return krb5_c_decrypt(context, eblock->key, 0, ivec ? &ivecd : 0, + &inputd, &outputd); +} + +krb5_error_code KRB5_CALLCONV +krb5_process_key(krb5_context context, krb5_encrypt_block *eblock, + const krb5_keyblock *key) +{ + eblock->key = (krb5_keyblock *) key; + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_finish_key(krb5_context context, krb5_encrypt_block *eblock) +{ + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_string_to_key(krb5_context context, const krb5_encrypt_block *eblock, + krb5_keyblock *keyblock, const krb5_data *data, + const krb5_data *salt) +{ + return krb5_c_string_to_key(context, eblock->crypto_entry, data, salt, + keyblock); +} + +krb5_error_code KRB5_CALLCONV +krb5_init_random_key(krb5_context context, const krb5_encrypt_block *eblock, + const krb5_keyblock *keyblock, krb5_pointer *ptr) +{ + krb5_data data = make_data(keyblock->contents, keyblock->length); + + return krb5_c_random_seed(context, &data); +} + +krb5_error_code KRB5_CALLCONV +krb5_finish_random_key(krb5_context context, const krb5_encrypt_block *eblock, + krb5_pointer *ptr) +{ + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_random_key(krb5_context context, const krb5_encrypt_block *eblock, + krb5_pointer ptr, krb5_keyblock **keyblock) +{ + krb5_keyblock *key; + krb5_error_code ret; + + *keyblock = NULL; + + key = malloc(sizeof(krb5_keyblock)); + if (key == NULL) + return ENOMEM; + + ret = krb5_c_make_random_key(context, eblock->crypto_entry, key); + if (ret) { + free(key); + return ret; + } + + *keyblock = key; + return(ret); +} + +krb5_enctype KRB5_CALLCONV +krb5_eblock_enctype(krb5_context context, const krb5_encrypt_block *eblock) +{ + return eblock->crypto_entry; +} + +krb5_error_code KRB5_CALLCONV +krb5_use_enctype(krb5_context context, krb5_encrypt_block *eblock, + krb5_enctype enctype) +{ + eblock->crypto_entry = enctype; + + return 0; +} + +size_t KRB5_CALLCONV +krb5_encrypt_size(size_t length, krb5_enctype crypto) +{ + size_t ret; + + if (krb5_c_encrypt_length(NULL, crypto, length, &ret)) + return (size_t) -1; /* XXX */ + + return ret; +} + +size_t KRB5_CALLCONV +krb5_checksum_size(krb5_context context, krb5_cksumtype ctype) +{ + size_t ret; + + if (krb5_c_checksum_length(context, ctype, &ret)) + return (size_t) -1; /* XXX */ + + return ret; +} + +/* Guess the enctype for an untyped key used with checksum type ctype. */ +static krb5_enctype +guess_enctype(krb5_cksumtype ctype) +{ + const struct krb5_cksumtypes *ctp; + int i; + + if (ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR) + return ENCTYPE_ARCFOUR_HMAC; + ctp = find_cksumtype(ctype); + if (ctp == NULL || ctp->enc == NULL) + return 0; + for (i = 0; i < krb5int_enctypes_length; i++) { + if (krb5int_enctypes_list[i].enc == ctp->enc) + return i; + } + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_calculate_checksum(krb5_context context, krb5_cksumtype ctype, + krb5_const_pointer in, size_t in_length, + krb5_const_pointer seed, size_t seed_length, + krb5_checksum *outcksum) +{ + krb5_data input = make_data((void *) in, in_length); + krb5_keyblock keyblock, *kptr = NULL; + krb5_error_code ret; + krb5_checksum cksum; + + if (seed != NULL) { + keyblock.enctype = guess_enctype(ctype); + keyblock.length = seed_length; + keyblock.contents = (unsigned char *) seed; + kptr = &keyblock; + } + + ret = krb5_c_make_checksum(context, ctype, kptr, 0, &input, &cksum); + if (ret) + return ret; + + if (outcksum->length < cksum.length) { + memset(cksum.contents, 0, cksum.length); + free(cksum.contents); + return KRB5_BAD_MSIZE; + } + + outcksum->magic = cksum.magic; + outcksum->checksum_type = cksum.checksum_type; + memcpy(outcksum->contents, cksum.contents, cksum.length); + outcksum->length = cksum.length; + + free(cksum.contents); + + return(0); +} + +krb5_error_code KRB5_CALLCONV +krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype, + const krb5_checksum *cksum, krb5_const_pointer in, + size_t in_length, krb5_const_pointer seed, + size_t seed_length) +{ + krb5_data input = make_data((void *) in, in_length); + krb5_keyblock keyblock, *kptr = NULL; + krb5_error_code ret; + krb5_boolean valid; + + if (seed != NULL) { + keyblock.enctype = guess_enctype(ctype); + keyblock.length = seed_length; + keyblock.contents = (unsigned char *) seed; + kptr = &keyblock; + } + + ret = krb5_c_verify_checksum(context, kptr, 0, &input, cksum, &valid); + if (ret) + return ret; + + if (!valid) + return KRB5KRB_AP_ERR_BAD_INTEGRITY; + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_random_confounder(size_t size, krb5_pointer ptr) +{ + krb5_data random_data = make_data(ptr, size); + + return krb5_c_random_make_octets(NULL, &random_data); +} + +krb5_error_code krb5_encrypt_data(krb5_context context, krb5_keyblock *key, + krb5_pointer ivec, krb5_data *data, + krb5_enc_data *enc_data) +{ + krb5_error_code ret; + size_t enclen, blocksize; + krb5_data ivecd; + + ret = krb5_c_encrypt_length(context, key->enctype, data->length, &enclen); + if (ret) + return ret; + + if (ivec) { + ret = krb5_c_block_size(context, key->enctype, &blocksize); + if (ret) + return ret; + + ivecd = make_data(ivec, blocksize); + } + + enc_data->magic = KV5M_ENC_DATA; + enc_data->kvno = 0; + enc_data->enctype = key->enctype; + ret = alloc_data(&enc_data->ciphertext, enclen); + if (ret) + return ret; + + ret = krb5_c_encrypt(context, key, 0, ivec ? &ivecd : 0, data, enc_data); + if (ret) + free(enc_data->ciphertext.data); + + return ret; +} + +krb5_error_code krb5_decrypt_data(krb5_context context, krb5_keyblock *key, + krb5_pointer ivec, krb5_enc_data *enc_data, + krb5_data *data) +{ + krb5_error_code ret; + krb5_data ivecd; + size_t blocksize; + + if (ivec) { + ret = krb5_c_block_size(context, key->enctype, &blocksize); + if (ret) + return ret; + + ivecd = make_data(ivec, blocksize); + } + + ret = alloc_data(data, enc_data->ciphertext.length); + if (ret) + return ret; + + ret = krb5_c_decrypt(context, key, 0, ivec ? &ivecd : 0, enc_data, data); + if (ret) + free(data->data); + + return 0; +} + +krb5_boolean KRB5_CALLCONV +valid_cksumtype(krb5_cksumtype ctype) +{ + return krb5_c_valid_cksumtype(ctype); +} + +krb5_boolean KRB5_CALLCONV +is_keyed_cksum(krb5_cksumtype ctype) +{ + return krb5_c_is_keyed_cksum(ctype); +} + +krb5_boolean KRB5_CALLCONV +is_coll_proof_cksum(krb5_cksumtype ctype) +{ + return krb5_c_is_coll_proof_cksum(ctype); +} + +krb5_boolean KRB5_CALLCONV +valid_enctype(krb5_enctype etype) +{ + return krb5_c_valid_enctype(etype); +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/prf.c b/krb5-1.21.3/src/lib/crypto/krb/prf.c new file mode 100644 index 00000000..67b856a9 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/prf.c @@ -0,0 +1,84 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prf.c */ +/* + * Copyright (C) 2004 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This contains the implementation of krb5_c_prf, which will find the + * enctype-specific PRF and then generate pseudo-random data. This function + * yields krb5_c_prf_length bytes of output. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_prf_length(krb5_context context, krb5_enctype enctype, size_t *len) +{ + const struct krb5_keytypes *ktp; + + assert(len); + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + *len = ktp->prf_length; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_k_prf(krb5_context context, krb5_key key, + krb5_data *input, krb5_data *output) +{ + const struct krb5_keytypes *ktp; + krb5_error_code ret; + + assert(input && output); + assert(output->data); + + ktp = find_enctype(key->keyblock.enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + if (ktp->prf == NULL) + return KRB5_CRYPTO_INTERNAL; + + output->magic = KV5M_DATA; + if (ktp->prf_length != output->length) + return KRB5_CRYPTO_INTERNAL; + ret = ktp->prf(ktp, key, input, output); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_prf(krb5_context context, const krb5_keyblock *keyblock, + krb5_data *input, krb5_data *output) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_prf(context, key, input, output); + krb5_k_free_key(context, key); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/prf_aes2.c b/krb5-1.21.3/src/lib/crypto/krb/prf_aes2.c new file mode 100644 index 00000000..43612280 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/prf_aes2.c @@ -0,0 +1,42 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prf_aes2.c - PRF for aes-sha2 enctypes */ +/* + * Copyright (C) 2015 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. + */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_aes2_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out) +{ + krb5_data label = string2data("prf"); + + return k5_sp800_108_counter_hmac(ktp->hash, key, &label, in, out); +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/prf_cmac.c b/krb5-1.21.3/src/lib/crypto/krb/prf_cmac.c new file mode 100644 index 00000000..1d4cc4c3 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/prf_cmac.c @@ -0,0 +1,58 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prf_cmac.c - CMAC-based PRF */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_dk_cmac_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out) +{ + krb5_crypto_iov iov; + krb5_data prfconst = make_data("prf", 3); + krb5_key kp = NULL; + krb5_error_code ret; + + if (ktp->prf_length != ktp->enc->block_size) + return KRB5_BAD_MSIZE; + + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *in; + + /* Derive a key using the PRF constant. */ + ret = krb5int_derive_key(ktp->enc, NULL, key, &kp, &prfconst, + DERIVE_SP800_108_CMAC); + if (ret != 0) + goto cleanup; + + /* PRF is CMAC of input */ + ret = krb5int_cmac_checksum(ktp->enc, kp, &iov, 1, out); + if (ret != 0) + goto cleanup; + +cleanup: + krb5_k_free_key(NULL, kp); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/prf_des.c b/krb5-1.21.3/src/lib/crypto/krb/prf_des.c new file mode 100644 index 00000000..7a2d719c --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/prf_des.c @@ -0,0 +1,47 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prf_des.c - RFC 3961 DES-based PRF */ +/* + * Copyright (C) 2004, 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_des_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out) +{ + const struct krb5_hash_provider *hash = &krb5int_hash_md5; + krb5_crypto_iov iov; + krb5_error_code ret; + + /* Compute a hash of the input, storing into the output buffer. */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *in; + ret = hash->hash(&iov, 1, out); + if (ret != 0) + return ret; + + /* Encrypt the hash in place. */ + iov.data = *out; + return ktp->enc->encrypt(key, NULL, &iov, 1); +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/prf_dk.c b/krb5-1.21.3/src/lib/crypto/krb/prf_dk.c new file mode 100644 index 00000000..544418ba --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/prf_dk.c @@ -0,0 +1,70 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prf_dk.c - RFC 3961 simplified profile PRF */ +/* + * Copyright (C) 2004 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_dk_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out) +{ + const struct krb5_enc_provider *enc = ktp->enc; + const struct krb5_hash_provider *hash = ktp->hash; + krb5_crypto_iov iov; + krb5_data cksum = empty_data(), prfconst = make_data("prf", 3); + krb5_key kp = NULL; + krb5_error_code ret; + + /* Hash the input data into an allocated buffer. */ + ret = alloc_data(&cksum, hash->hashsize); + if (ret != 0) + goto cleanup; + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *in; + ret = hash->hash(&iov, 1, &cksum); + if (ret != 0) + goto cleanup; + + /* Derive a key using the PRF constant. */ + ret = krb5int_derive_key(ktp->enc, NULL, key, &kp, &prfconst, + DERIVE_RFC3961); + if (ret != 0) + goto cleanup; + + /* Truncate the hash to the closest multiple of the block size. */ + iov.data.data = cksum.data; + iov.data.length = (hash->hashsize / enc->block_size) * enc->block_size; + + /* Encrypt the truncated hash in the derived key to get the output. */ + ret = ktp->enc->encrypt(kp, NULL, &iov, 1); + if (ret != 0) + goto cleanup; + memcpy(out->data, iov.data.data, out->length); + +cleanup: + zapfree(cksum.data, hash->hashsize); + krb5_k_free_key(NULL, kp); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/prf_rc4.c b/krb5-1.21.3/src/lib/crypto/krb/prf_rc4.c new file mode 100644 index 00000000..09279532 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/prf_rc4.c @@ -0,0 +1,39 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/prf_rc4.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_error_code +krb5int_arcfour_prf(const struct krb5_keytypes *ktp, krb5_key key, + const krb5_data *in, krb5_data *out) +{ + krb5_crypto_iov iov; + + assert(out->length == 20); + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *in; + return krb5int_hmac(&krb5int_hash_sha1, key, &iov, 1, out); +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/prng.c b/krb5-1.21.3/src/lib/crypto/krb/prng.c new file mode 100644 index 00000000..d6b79e2d --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/prng.c @@ -0,0 +1,153 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2001, 2002, 2004, 2007, 2008, 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_random_seed(krb5_context context, krb5_data *data) +{ + return krb5_c_random_add_entropy(context, KRB5_C_RANDSOURCE_OLDAPI, data); +} + +/* Routines to get entropy from the OS. */ +#if defined(_WIN32) + +static krb5_boolean +get_os_entropy(unsigned char *buf, size_t len) +{ + krb5_boolean result; + HCRYPTPROV provider; + + if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) + return FALSE; + result = CryptGenRandom(provider, len, buf); + (void)CryptReleaseContext(provider, 0); + return result; +} + +#else /* not Windows */ +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef __linux__ +#include +#endif /* __linux__ */ + +/* Open device, ensure that it is not a regular file, and read entropy. Return + * true on success, false on failure. */ +static krb5_boolean +read_entropy_from_device(const char *device, unsigned char *buf, size_t len) +{ + struct stat sb; + int fd; + unsigned char *bp; + size_t left; + ssize_t count; + krb5_boolean result = FALSE; + + fd = open(device, O_RDONLY); + if (fd == -1) + return FALSE; + set_cloexec_fd(fd); + if (fstat(fd, &sb) == -1 || S_ISREG(sb.st_mode)) + goto cleanup; + + for (bp = buf, left = len; left > 0;) { + count = read(fd, bp, left); + if (count <= 0) + goto cleanup; + left -= count; + bp += count; + } + result = TRUE; + +cleanup: + close(fd); + return result; +} + +static krb5_boolean +get_os_entropy(unsigned char *buf, size_t len) +{ +#if defined(__linux__) && defined(SYS_getrandom) + int r; + + while (len > 0) { + /* + * Pull from the /dev/urandom pool, but require it to have been seeded. + * This ensures strong randomness while only blocking during first + * system boot. + * + * glibc does not currently provide a binding for getrandom: + * https://sourceware.org/bugzilla/show_bug.cgi?id=17252 + */ + errno = 0; + r = syscall(SYS_getrandom, buf, len, 0); + if (r <= 0) { + if (errno == EINTR) + continue; + + /* ENOSYS or other unrecoverable failure */ + break; + } + len -= r; + buf += r; + } + if (len == 0) + return TRUE; +#endif /* defined(__linux__) && defined(SYS_getrandom) */ + + return read_entropy_from_device("/dev/urandom", buf, len); +} + +#endif /* not Windows */ + +krb5_error_code KRB5_CALLCONV +krb5_c_random_make_octets(krb5_context context, krb5_data *outdata) +{ + krb5_boolean res; + + res = get_os_entropy((uint8_t *)outdata->data, outdata->length); + return res ? 0 : KRB5_CRYPTO_INTERNAL; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_random_add_entropy(krb5_context context, unsigned int randsource, + const krb5_data *indata) +{ + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_random_os_entropy(krb5_context context, int strong, int *success) +{ + *success = 0; + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/random_to_key.c b/krb5-1.21.3/src/lib/crypto/krb/random_to_key.c new file mode 100644 index 00000000..9394385a --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/random_to_key.c @@ -0,0 +1,101 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * COPYRIGHT (c) 2006 + * The Regents of the University of Michigan + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +/* + * Create a key given random data. It is assumed that random_key has + * already been initialized and random_key->contents have been allocated + * with the correct length. + */ +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_random_to_key(krb5_context context, krb5_enctype enctype, + krb5_data *random_data, krb5_keyblock *random_key) +{ + krb5_error_code ret; + const struct krb5_keytypes *ktp; + + if (random_data == NULL || random_key == NULL || + random_key->contents == NULL) + return EINVAL; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + + if (random_key->length != ktp->enc->keylength) + return KRB5_BAD_KEYSIZE; + + ret = ktp->rand2key(random_data, random_key); + if (ret) + zap(random_key->contents, random_key->length); + + return ret; +} + +krb5_error_code +k5_rand2key_direct(const krb5_data *randombits, krb5_keyblock *keyblock) +{ + if (randombits->length != keyblock->length) + return KRB5_CRYPTO_INTERNAL; + + keyblock->magic = KV5M_KEYBLOCK; + memcpy(keyblock->contents, randombits->data, randombits->length); + return 0; +} + +static inline void +eighth_byte(unsigned char *b) +{ + b[7] = (((b[0] & 1) << 1) | ((b[1] & 1) << 2) | ((b[2] & 1) << 3) | + ((b[3] & 1) << 4) | ((b[4] & 1) << 5) | ((b[5] & 1) << 6) | + ((b[6] & 1) << 7)); +} + +krb5_error_code +k5_rand2key_des3(const krb5_data *randombits, krb5_keyblock *keyblock) +{ + int i; + + if (randombits->length != 21) + return KRB5_CRYPTO_INTERNAL; + + keyblock->magic = KV5M_KEYBLOCK; + + /* Take the seven bytes, move them around into the top 7 bits of the + * 8 key bytes, then compute the parity bits. Do this three times. */ + for (i = 0; i < 3; i++) { + memcpy(&keyblock->contents[i * 8], &randombits->data[i * 7], 7); + eighth_byte(&keyblock->contents[i * 8]); + k5_des_fixup_key_parity(&keyblock->contents[i * 8]); + } + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/s2k_pbkdf2.c b/krb5-1.21.3/src/lib/crypto/krb/s2k_pbkdf2.c new file mode 100644 index 00000000..1fea0340 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/s2k_pbkdf2.c @@ -0,0 +1,216 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +static const unsigned char kerberos[] = "kerberos"; +#define kerberos_len (sizeof(kerberos)-1) + +krb5_error_code +krb5int_dk_string_to_key(const struct krb5_keytypes *ktp, + const krb5_data *string, const krb5_data *salt, + const krb5_data *parms, krb5_keyblock *keyblock) +{ + krb5_error_code ret; + size_t keybytes, keylength, concatlen; + unsigned char *concat = NULL, *foldstring = NULL, *foldkeydata = NULL; + krb5_data indata; + krb5_keyblock foldkeyblock; + krb5_key foldkey = NULL; + + /* keyblock->length is checked by krb5int_derive_key. */ + + keybytes = ktp->enc->keybytes; + keylength = ktp->enc->keylength; + + concatlen = string->length + salt->length; + + concat = k5alloc(concatlen, &ret); + if (ret != 0) + goto cleanup; + foldstring = k5alloc(keybytes, &ret); + if (ret != 0) + goto cleanup; + foldkeydata = k5alloc(keylength, &ret); + if (ret != 0) + goto cleanup; + + /* construct input string ( = string + salt), fold it, make_key it */ + + if (string->length > 0) + memcpy(concat, string->data, string->length); + if (salt->length > 0) + memcpy(concat + string->length, salt->data, salt->length); + + krb5int_nfold(concatlen*8, concat, keybytes*8, foldstring); + + indata.length = keybytes; + indata.data = (char *) foldstring; + foldkeyblock.length = keylength; + foldkeyblock.contents = foldkeydata; + foldkeyblock.enctype = ktp->etype; + + ret = ktp->rand2key(&indata, &foldkeyblock); + if (ret != 0) + goto cleanup; + + ret = krb5_k_create_key(NULL, &foldkeyblock, &foldkey); + if (ret != 0) + goto cleanup; + + /* now derive the key from this one */ + + indata.length = kerberos_len; + indata.data = (char *) kerberos; + + ret = krb5int_derive_keyblock(ktp->enc, NULL, foldkey, keyblock, &indata, + DERIVE_RFC3961); + if (ret != 0) + memset(keyblock->contents, 0, keyblock->length); + +cleanup: + zapfree(concat, concatlen); + zapfree(foldstring, keybytes); + zapfree(foldkeydata, keylength); + krb5_k_free_key(NULL, foldkey); + return ret; +} + + +#define MAX_ITERATION_COUNT 0x1000000L + +krb5_boolean k5_allow_weak_pbkdf2iter = FALSE; + +static krb5_error_code +pbkdf2_string_to_key(const struct krb5_keytypes *ktp, const krb5_data *string, + const krb5_data *salt, const krb5_data *pepper, + const krb5_data *params, krb5_keyblock *key, + enum deriv_alg deriv_alg, unsigned long def_iter_count) +{ + const struct krb5_hash_provider *hash; + unsigned long iter_count; + krb5_data out; + static const krb5_data usage = { KV5M_DATA, 8, "kerberos" }; + krb5_key tempkey = NULL; + krb5_error_code err; + krb5_data sandp = empty_data(); + + if (params) { + unsigned char *p = (unsigned char *) params->data; + if (params->length != 4) + return KRB5_ERR_BAD_S2K_PARAMS; + iter_count = load_32_be(p); + /* Zero means 2^32, which is way above what we will accept. Also don't + * accept values less than the default, unless we're running tests. */ + if (iter_count == 0 || + (!k5_allow_weak_pbkdf2iter && iter_count < def_iter_count)) + return KRB5_ERR_BAD_S2K_PARAMS; + + } else + iter_count = def_iter_count; + + /* This is not a protocol specification constraint; this is an + implementation limit, which should eventually be controlled by + a config file. */ + if (iter_count >= MAX_ITERATION_COUNT) + return KRB5_ERR_BAD_S2K_PARAMS; + + /* Use the output keyblock contents for temporary space. */ + out.data = (char *) key->contents; + out.length = key->length; + if (out.length != 16 && out.length != 32) + return KRB5_CRYPTO_INTERNAL; + + if (pepper != NULL) { + err = alloc_data(&sandp, pepper->length + 1 + salt->length); + if (err) + return err; + + if (pepper->length > 0) + memcpy(sandp.data, pepper->data, pepper->length); + sandp.data[pepper->length] = '\0'; + if (salt->length > 0) + memcpy(&sandp.data[pepper->length + 1], salt->data, salt->length); + + salt = &sandp; + } + + hash = (ktp->hash != NULL) ? ktp->hash : &krb5int_hash_sha1; + err = krb5int_pbkdf2_hmac(hash, &out, iter_count, string, salt); + if (err) + goto cleanup; + + err = krb5_k_create_key (NULL, key, &tempkey); + if (err) + goto cleanup; + + err = krb5int_derive_keyblock(ktp->enc, ktp->hash, tempkey, key, &usage, + deriv_alg); + +cleanup: + if (sandp.data) + free(sandp.data); + if (err) + memset (out.data, 0, out.length); + krb5_k_free_key (NULL, tempkey); + return err; +} + +krb5_error_code +krb5int_aes_string_to_key(const struct krb5_keytypes *ktp, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key) +{ + return pbkdf2_string_to_key(ktp, string, salt, NULL, params, key, + DERIVE_RFC3961, 4096); +} + +krb5_error_code +krb5int_camellia_string_to_key(const struct krb5_keytypes *ktp, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, + krb5_keyblock *key) +{ + krb5_data pepper = string2data(ktp->name); + + return pbkdf2_string_to_key(ktp, string, salt, &pepper, params, key, + DERIVE_SP800_108_CMAC, 32768); +} + +krb5_error_code +krb5int_aes2_string_to_key(const struct krb5_keytypes *ktp, + const krb5_data *string, const krb5_data *salt, + const krb5_data *params, krb5_keyblock *key) +{ + krb5_data pepper = string2data(ktp->name); + + return pbkdf2_string_to_key(ktp, string, salt, &pepper, params, key, + DERIVE_SP800_108_HMAC, 32768); +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/s2k_rc4.c b/krb5-1.21.3/src/lib/crypto/krb/s2k_rc4.c new file mode 100644 index 00000000..f7e699d6 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/s2k_rc4.c @@ -0,0 +1,41 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include "crypto_int.h" +#include "k5-utf8.h" + +krb5_error_code +krb5int_arcfour_string_to_key(const struct krb5_keytypes *ktp, + const krb5_data *string, const krb5_data *salt, + const krb5_data *params, krb5_keyblock *key) +{ + krb5_error_code err = 0; + krb5_crypto_iov iov; + krb5_data hash_out; + char *utf8; + unsigned char *copystr; + size_t copystrlen; + + if (params != NULL) + return KRB5_ERR_BAD_S2K_PARAMS; + + if (key->length != 16) + return (KRB5_BAD_MSIZE); + + /* We ignore salt per the Microsoft spec. */ + utf8 = k5memdup0(string->data, string->length, &err); + if (utf8 == NULL) + return err; + err = k5_utf8_to_utf16le(utf8, ©str, ©strlen); + zapfree(utf8, string->length); + if (err) + return err; + + /* the actual MD4 hash of the data */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data(copystr, copystrlen); + hash_out = make_data(key->contents, key->length); + err = krb5int_hash_md4.hash(&iov, 1, &hash_out); + + /* Zero out the data behind us */ + zapfree(copystr, copystrlen); + return err; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/state.c b/krb5-1.21.3/src/lib/crypto/krb/state.c new file mode 100644 index 00000000..a7fb020b --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/state.c @@ -0,0 +1,60 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/state.c */ +/* + * Copyright (C) 2001 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + + * + * + * + * * Section 6 (Encryption) of the Kerberos revisions document defines + * cipher states to be used to chain encryptions and decryptions + * together. Examples of cipher states include initialization vectors + * for CBC encription. This file contains implementations of + * krb5_c_init_state and krb5_c_free_state used by clients of the + * Kerberos crypto library. + */ +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_init_state (krb5_context context, const krb5_keyblock *key, + krb5_keyusage keyusage, krb5_data *new_state) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(key->enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + return ktp->enc->init_state(key, keyusage, new_state); +} + +krb5_error_code KRB5_CALLCONV +krb5_c_free_state(krb5_context context, const krb5_keyblock *key, + krb5_data *state) +{ + const struct krb5_keytypes *ktp; + + ktp = find_enctype(key->enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + ktp->enc->free_state(state); + return 0; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/string_to_cksumtype.c b/krb5-1.21.3/src/lib/crypto/krb/string_to_cksumtype.c new file mode 100644 index 00000000..3498d2a0 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/string_to_cksumtype.c @@ -0,0 +1,56 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_string_to_cksumtype(char *string, krb5_cksumtype *cksumtypep) +{ + unsigned int i, j; + const char *alias; + const struct krb5_cksumtypes *ctp; + + for (i=0; iname, string) == 0) { + *cksumtypep = ctp->ctype; + return 0; + } +#define MAX_ALIASES (sizeof(ctp->aliases) / sizeof(ctp->aliases[0])) + for (j = 0; j < MAX_ALIASES; j++) { + alias = ctp->aliases[j]; + if (alias == NULL) + break; + if (strcasecmp(alias, string) == 0) { + *cksumtypep = ctp->ctype; + return 0; + } + } + } + + return EINVAL; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/string_to_key.c b/krb5-1.21.3/src/lib/crypto/krb/string_to_key.c new file mode 100644 index 00000000..352a8e8d --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/string_to_key.c @@ -0,0 +1,79 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_c_string_to_key(krb5_context context, krb5_enctype enctype, + const krb5_data *string, const krb5_data *salt, + krb5_keyblock *key) +{ + return krb5_c_string_to_key_with_params(context, enctype, string, salt, + NULL, key); +} + +krb5_error_code KRB5_CALLCONV +krb5_c_string_to_key_with_params(krb5_context context, krb5_enctype enctype, + const krb5_data *string, + const krb5_data *salt, + const krb5_data *params, krb5_keyblock *key) +{ + krb5_error_code ret; + krb5_data empty = empty_data(); + const struct krb5_keytypes *ktp; + size_t keylength; + + ktp = find_enctype(enctype); + if (ktp == NULL) + return KRB5_BAD_ENCTYPE; + keylength = ktp->enc->keylength; + + /* For compatibility with past behavior, treat a null salt as empty. */ + if (salt == NULL) + salt = ∅ + + /* Fail gracefully if someone is using the old AFS string-to-key hack. */ + if (salt->length == SALT_TYPE_AFS_LENGTH) + return EINVAL; + + key->contents = malloc(keylength); + if (key->contents == NULL) + return ENOMEM; + + key->magic = KV5M_KEYBLOCK; + key->enctype = enctype; + key->length = keylength; + + ret = (*ktp->str2key)(ktp, string, salt, params, key); + if (ret) { + zapfree(key->contents, keylength); + key->length = 0; + key->contents = NULL; + } + + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/valid_cksumtype.c b/krb5-1.21.3/src/lib/crypto/krb/valid_cksumtype.c new file mode 100644 index 00000000..eb7807f7 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/valid_cksumtype.c @@ -0,0 +1,39 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +krb5_boolean KRB5_CALLCONV +krb5_c_valid_cksumtype(krb5_cksumtype ctype) +{ + const struct krb5_cksumtypes *ctp; + + ctp = find_cksumtype(ctype); + if (ctp == NULL) + return FALSE; + return TRUE; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/verify_checksum.c b/krb5-1.21.3/src/lib/crypto/krb/verify_checksum.c new file mode 100644 index 00000000..09425ea7 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/verify_checksum.c @@ -0,0 +1,98 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_verify_checksum(krb5_context context, krb5_key key, + krb5_keyusage usage, const krb5_data *data, + const krb5_checksum *cksum, krb5_boolean *valid) +{ + const struct krb5_cksumtypes *ctp; + krb5_cksumtype cksumtype; + krb5_crypto_iov iov; + krb5_error_code ret; + krb5_data cksum_data; + krb5_checksum computed; + + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = *data; + + /* A 0 checksum type means use the mandatory checksum. */ + cksumtype = cksum->checksum_type; + if (cksumtype == 0 && key != NULL) { + ret = krb5int_c_mandatory_cksumtype(context, key->keyblock.enctype, + &cksumtype); + if (ret) + return ret; + } + ctp = find_cksumtype(cksumtype); + if (ctp == NULL) + return KRB5_BAD_ENCTYPE; + + ret = verify_key(ctp, key); + if (ret != 0) + return ret; + + /* If there's actually a verify function, call it. */ + cksum_data = make_data(cksum->contents, cksum->length); + if (ctp->verify != NULL) + return ctp->verify(ctp, key, usage, &iov, 1, &cksum_data, valid); + + /* Otherwise, make the checksum again, and compare. */ + if (cksum->length != ctp->output_size) + return KRB5_BAD_MSIZE; + + ret = krb5_k_make_checksum(context, cksum->checksum_type, key, usage, + data, &computed); + if (ret) + return ret; + + *valid = (k5_bcmp(computed.contents, cksum->contents, + ctp->output_size) == 0); + + free(computed.contents); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *keyblock, + krb5_keyusage usage, const krb5_data *data, + const krb5_checksum *cksum, krb5_boolean *valid) +{ + krb5_key key = NULL; + krb5_error_code ret; + + if (keyblock != NULL) { + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + } + ret = krb5_k_verify_checksum(context, key, usage, data, cksum, valid); + krb5_k_free_key(context, key); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/krb/verify_checksum_iov.c b/krb5-1.21.3/src/lib/crypto/krb/verify_checksum_iov.c new file mode 100644 index 00000000..fc76c0e2 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/krb/verify_checksum_iov.c @@ -0,0 +1,101 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/krb/verify_checksum_iov.c */ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +krb5_error_code KRB5_CALLCONV +krb5_k_verify_checksum_iov(krb5_context context, + krb5_cksumtype checksum_type, + krb5_key key, + krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_boolean *valid) +{ + const struct krb5_cksumtypes *ctp; + krb5_error_code ret; + krb5_data computed; + krb5_crypto_iov *checksum; + + if (checksum_type == 0) { + ret = krb5int_c_mandatory_cksumtype(context, key->keyblock.enctype, + &checksum_type); + if (ret != 0) + return ret; + } + ctp = find_cksumtype(checksum_type); + if (ctp == NULL) + return KRB5_BAD_ENCTYPE; + + ret = verify_key(ctp, key); + if (ret != 0) + return ret; + + checksum = krb5int_c_locate_iov((krb5_crypto_iov *)data, num_data, + KRB5_CRYPTO_TYPE_CHECKSUM); + if (checksum == NULL || checksum->data.length != ctp->output_size) + return KRB5_BAD_MSIZE; + + /* If there's actually a verify function, call it. */ + if (ctp->verify != NULL) { + return ctp->verify(ctp, key, usage, data, num_data, &checksum->data, + valid); + } + + ret = alloc_data(&computed, ctp->compute_size); + if (ret != 0) + return ret; + + ret = ctp->checksum(ctp, key, usage, data, num_data, &computed); + if (ret == 0) { + *valid = (k5_bcmp(computed.data, checksum->data.data, + ctp->output_size) == 0); + } + + zapfree(computed.data, ctp->compute_size); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_c_verify_checksum_iov(krb5_context context, + krb5_cksumtype checksum_type, + const krb5_keyblock *keyblock, + krb5_keyusage usage, + const krb5_crypto_iov *data, + size_t num_data, + krb5_boolean *valid) +{ + krb5_key key; + krb5_error_code ret; + + ret = krb5_k_create_key(context, keyblock, &key); + if (ret != 0) + return ret; + ret = krb5_k_verify_checksum_iov(context, checksum_type, key, usage, data, + num_data, valid); + krb5_k_free_key(context, key); + return ret; +} diff --git a/krb5-1.21.3/src/lib/crypto/libk5crypto.exports b/krb5-1.21.3/src/lib/crypto/libk5crypto.exports new file mode 100644 index 00000000..052f4d4b --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/libk5crypto.exports @@ -0,0 +1,105 @@ +krb5_c_make_random_key +krb5_c_encrypt_length +krb5_process_key +krb5_string_to_cksumtype +krb5_c_valid_enctype +krb5_c_valid_cksumtype +krb5_string_to_key +krb5_c_encrypt_iov +krb5_c_checksum_length +is_keyed_cksum +krb5_c_padding_length +is_coll_proof_cksum +krb5_init_random_key +krb5_c_string_to_key_with_params +krb5_c_random_make_octets +krb5_c_random_os_entropy +krb5_c_decrypt +krb5_c_crypto_length +krb5_c_block_size +krb5_cksumtype_to_string +krb5_c_keyed_checksum_types +krb5_c_is_keyed_cksum +krb5_c_crypto_length_iov +valid_cksumtype +krb5_c_random_seed +krb5_c_random_to_key +krb5_verify_checksum +krb5_c_free_state +krb5_c_verify_checksum +krb5_c_random_add_entropy +krb5_c_decrypt_iov +krb5_c_make_checksum +krb5_checksum_size +krb5_free_cksumtypes +krb5_finish_key +krb5_encrypt_size +krb5_c_keylengths +krb5_c_prf +krb5_encrypt +krb5_string_to_enctype +krb5_c_is_coll_proof_cksum +krb5_c_init_state +krb5_eblock_enctype +krb5_decrypt +krb5_c_encrypt +krb5_c_enctype_compare +krb5_c_verify_checksum_iov +valid_enctype +krb5_enctype_to_string +krb5_enctype_to_name +krb5_c_make_checksum_iov +krb5_calculate_checksum +krb5_c_string_to_key +krb5_use_enctype +krb5_random_key +krb5_finish_random_key +krb5_c_prf_length +krb5int_c_mandatory_cksumtype +krb5_c_fx_cf2_simple +krb5int_c_weak_enctype +krb5_encrypt_data +krb5int_c_copy_keyblock +krb5int_c_copy_keyblock_contents +krb5int_c_free_keyblock_contents +krb5int_c_free_keyblock +krb5int_c_init_keyblock +krb5int_hash_md4 +krb5int_hash_md5 +krb5int_hash_sha256 +krb5int_hash_sha384 +krb5int_enc_arcfour +krb5int_hmac +krb5_k_create_key +krb5_k_decrypt +krb5_k_decrypt_iov +krb5_k_encrypt +krb5_k_encrypt_iov +krb5_k_free_key +krb5_k_key_enctype +krb5_k_key_keyblock +krb5_k_make_checksum +krb5_k_make_checksum_iov +krb5_k_prf +krb5_k_reference_key +krb5_k_verify_checksum +krb5_k_verify_checksum_iov +krb5int_aes_encrypt +krb5int_aes_decrypt +krb5int_enc_des3 +krb5int_arcfour_gsscrypt +krb5int_camellia_encrypt +krb5int_cmac_checksum +krb5int_enc_aes128 +krb5int_enc_aes256 +krb5int_enc_camellia128 +krb5int_enc_camellia256 +krb5int_derive_key +krb5int_derive_random +k5_sha256 +krb5int_nfold +k5_allow_weak_pbkdf2iter +krb5_c_prfplus +krb5_c_derive_prfplus +k5_enctype_to_ssf +krb5int_c_deprecated_enctype diff --git a/krb5-1.21.3/src/lib/crypto/openssl/Makefile.in b/krb5-1.21.3/src/lib/crypto/openssl/Makefile.in new file mode 100644 index 00000000..cf11f684 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/Makefile.in @@ -0,0 +1,44 @@ +mydir=lib$(S)crypto$(S)openssl +BUILDTOP=$(REL)..$(S)..$(S).. +SUBDIRS=des enc_provider hash_provider +LOCALINCLUDES=-I$(srcdir)/../krb $(CRYPTO_IMPL_CFLAGS) + +STLIBOBJS=\ + cmac.o \ + hmac.o \ + kdf.o \ + pbkdf2.o \ + sha256.o + +OBJS=\ + $(OUTPRE)cmac.$(OBJEXT) \ + $(OUTPRE)hmac.$(OBJEXT) \ + $(OUTPRE)kdf.$(OBJEXT) \ + $(OUTPRE)pbkdf2.$(OBJEXT) \ + $(OUTPRE)sha256.$(OBJEXT) + +SRCS=\ + $(srcdir)/cmac.c \ + $(srcdir)/hmac.c \ + $(srcdir)/kdf.c \ + $(srcdir)/pbkdf2.c \ + $(srcdir)/sha256.c + +SUBDIROBJLISTS= des/OBJS.ST md4/OBJS.ST \ + md5/OBJS.ST sha1/OBJS.ST sha2/OBJS.ST \ + enc_provider/OBJS.ST \ + hash_provider/OBJS.ST \ + aes/OBJS.ST + +STOBJLISTS= $(SUBDIROBJLISTS) OBJS.ST + +all-unix: all-libobjs +includes: depend + +depend: $(SRCS) + +clean-unix:: clean-libobjs + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/openssl/cmac.c b/krb5-1.21.3/src/lib/crypto/openssl/cmac.c new file mode 100644 index 00000000..8f2717b1 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/cmac.c @@ -0,0 +1,93 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/openssl/cmac.c - OpenSSL CMAC implementation */ +/* + * Copyright (C) 2021 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. + */ + +#include "crypto_int.h" + +#ifdef K5_OPENSSL_CMAC + +#include +#include +#include + +krb5_error_code +krb5int_cmac_checksum(const struct krb5_enc_provider *enc, krb5_key key, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + int ok; + EVP_MAC *mac = NULL; + EVP_MAC_CTX *ctx = NULL; + OSSL_PARAM params[2], *p = params; + size_t i = 0, md_len; + char *cipher; + + if (enc == &krb5int_enc_camellia128) + cipher = "CAMELLIA-128-CBC"; + else if (enc == &krb5int_enc_camellia256) + cipher = "CAMELLIA-256-CBC"; + else + return KRB5_CRYPTO_INTERNAL; + + mac = EVP_MAC_fetch(NULL, "CMAC", NULL); + if (mac == NULL) + return KRB5_CRYPTO_INTERNAL; + + ctx = EVP_MAC_CTX_new(mac); + if (ctx == NULL) { + ok = 0; + goto cleanup; + } + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_CIPHER, cipher, 0); + *p = OSSL_PARAM_construct_end(); + + ok = EVP_MAC_init(ctx, key->keyblock.contents, key->keyblock.length, + params); + for (i = 0; ok && i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + if (!SIGN_IOV(iov)) + continue; + ok = EVP_MAC_update(ctx, (uint8_t *)iov->data.data, iov->data.length); + } + ok = ok && EVP_MAC_final(ctx, (unsigned char *)output->data, &md_len, + output->length); + if (!ok) + goto cleanup; + output->length = md_len; + +cleanup: + EVP_MAC_free(mac); + EVP_MAC_CTX_free(ctx); + return ok ? 0 : KRB5_CRYPTO_INTERNAL; +} + +#endif /* K5_OPENSSL_CMAC */ diff --git a/krb5-1.21.3/src/lib/crypto/openssl/deps b/krb5-1.21.3/src/lib/crypto/openssl/deps new file mode 100644 index 00000000..3d276a4c --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/deps @@ -0,0 +1,58 @@ +# +# Generated makefile dependencies follow. +# +cmac.so cmac.po $(OUTPRE)cmac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cmac.c +hmac.so hmac.po $(OUTPRE)hmac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + hmac.c +kdf.so kdf.po $(OUTPRE)kdf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kdf.c +pbkdf2.so pbkdf2.po $(OUTPRE)pbkdf2.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + pbkdf2.c +sha256.so sha256.po $(OUTPRE)sha256.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + sha256.c diff --git a/krb5-1.21.3/src/lib/crypto/openssl/des/Makefile.in b/krb5-1.21.3/src/lib/crypto/openssl/des/Makefile.in new file mode 100644 index 00000000..a6cece1d --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/des/Makefile.in @@ -0,0 +1,20 @@ +mydir=lib$(S)crypto$(S)openssl$(S)des +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/../../krb $(CRYPTO_IMPL_CFLAGS) + +STLIBOBJS= des_keys.o + +OBJS= $(OUTPRE)des_keys.$(OBJEXT) + +SRCS= $(srcdir)/des_keys.c + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/openssl/des/deps b/krb5-1.21.3/src/lib/crypto/openssl/des/deps new file mode 100644 index 00000000..723c2680 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/des/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +des_keys.so des_keys.po $(OUTPRE)des_keys.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h des_keys.c diff --git a/krb5-1.21.3/src/lib/crypto/openssl/des/des_keys.c b/krb5-1.21.3/src/lib/crypto/openssl/des/des_keys.c new file mode 100644 index 00000000..83f1cbf2 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/des/des_keys.c @@ -0,0 +1,39 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/openssl/des/des_keys.c - Key functions used by Kerberos code */ +/* + * Copyright (C) 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +#ifdef K5_OPENSSL_DES_KEY_PARITY + +#include + +void +k5_des_fixup_key_parity(unsigned char *keybits) +{ + DES_set_odd_parity((DES_cblock *)keybits); +} + +#endif diff --git a/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/Makefile.in b/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/Makefile.in new file mode 100644 index 00000000..26827cfe --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/Makefile.in @@ -0,0 +1,31 @@ +mydir=lib$(S)crypto$(S)openssl$(S)enc_provider +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/../../krb $(CRYPTO_IMPL_CFLAGS) + +STLIBOBJS= \ + des3.o \ + rc4.o \ + aes.o \ + camellia.o + +OBJS= \ + $(OUTPRE)des3.$(OBJEXT) \ + $(OUTPRE)aes.$(OBJEXT) \ + $(OUTPRE)camellia.$(OBJEXT) \ + $(OUTPRE)rc4.$(OBJEXT) + +SRCS= \ + $(srcdir)/des3.c \ + $(srcdir)/aes.c \ + $(srcdir)/camellia.c \ + $(srcdir)/rc4.c + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) + +clean-unix:: clean-libobjs + +@libobj_frag@ diff --git a/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/aes.c b/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/aes.c new file mode 100644 index 00000000..4c6ef361 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/aes.c @@ -0,0 +1,398 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/openssl/enc_provider/aes.c */ +/* + * Copyright (C) 2003, 2007, 2008, 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +#ifdef K5_OPENSSL_AES + +#include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#else +#include +#include +#endif + +/* proto's */ +static krb5_error_code +cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data); +static krb5_error_code +cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data); +static krb5_error_code +cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen); +static krb5_error_code +cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen); + +#define BLOCK_SIZE 16 +#define NUM_BITS 8 +#define IV_CTS_BUF_SIZE 16 /* 16 - hardcoded in CRYPTO_cts128_en/decrypt */ + +static const EVP_CIPHER * +map_mode(unsigned int len) +{ + if (len==16) + return EVP_aes_128_cbc(); + if (len==32) + return EVP_aes_256_cbc(); + else + return NULL; +} + +/* Encrypt one block using CBC. */ +static krb5_error_code +cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + int ret, olen = BLOCK_SIZE; + unsigned char iblock[BLOCK_SIZE], oblock[BLOCK_SIZE]; + EVP_CIPHER_CTX *ctx; + struct iov_cursor cursor; + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return ENOMEM; + + ret = EVP_EncryptInit_ex(ctx, map_mode(key->keyblock.length), + NULL, key->keyblock.contents, (ivec) ? (unsigned char*)ivec->data : NULL); + if (ret == 0) { + EVP_CIPHER_CTX_free(ctx); + return KRB5_CRYPTO_INTERNAL; + } + + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE); + k5_iov_cursor_get(&cursor, iblock); + EVP_CIPHER_CTX_set_padding(ctx,0); + ret = EVP_EncryptUpdate(ctx, oblock, &olen, iblock, BLOCK_SIZE); + if (ret == 1) + k5_iov_cursor_put(&cursor, oblock); + EVP_CIPHER_CTX_free(ctx); + + zap(iblock, BLOCK_SIZE); + zap(oblock, BLOCK_SIZE); + return (ret == 1) ? 0 : KRB5_CRYPTO_INTERNAL; +} + +/* Decrypt one block using CBC. */ +static krb5_error_code +cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + int ret = 0, olen = BLOCK_SIZE; + unsigned char iblock[BLOCK_SIZE], oblock[BLOCK_SIZE]; + EVP_CIPHER_CTX *ctx; + struct iov_cursor cursor; + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return ENOMEM; + + ret = EVP_DecryptInit_ex(ctx, map_mode(key->keyblock.length), + NULL, key->keyblock.contents, (ivec) ? (unsigned char*)ivec->data : NULL); + if (ret == 0) { + EVP_CIPHER_CTX_free(ctx); + return KRB5_CRYPTO_INTERNAL; + } + + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE); + k5_iov_cursor_get(&cursor, iblock); + EVP_CIPHER_CTX_set_padding(ctx,0); + ret = EVP_DecryptUpdate(ctx, oblock, &olen, iblock, BLOCK_SIZE); + if (ret == 1) + k5_iov_cursor_put(&cursor, oblock); + EVP_CIPHER_CTX_free(ctx); + + zap(iblock, BLOCK_SIZE); + zap(oblock, BLOCK_SIZE); + return (ret == 1) ? 0 : KRB5_CRYPTO_INTERNAL; +} + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + +static krb5_error_code +do_cts(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen, int encrypt) +{ + krb5_error_code ret; + int outlen, len; + unsigned char *oblock = NULL, *dbuf = NULL; + unsigned char iv_cts[IV_CTS_BUF_SIZE]; + struct iov_cursor cursor; + OSSL_PARAM params[2], *p = params; + EVP_CIPHER_CTX *ctx = NULL; + EVP_CIPHER *cipher = NULL; + + memset(iv_cts, 0, sizeof(iv_cts)); + if (ivec != NULL && ivec->data != NULL){ + if (ivec->length != sizeof(iv_cts)) + return KRB5_CRYPTO_INTERNAL; + memcpy(iv_cts, ivec->data, ivec->length); + } + + if (key->keyblock.length == 16) + cipher = EVP_CIPHER_fetch(NULL, "AES-128-CBC-CTS", NULL); + else if (key->keyblock.length == 32) + cipher = EVP_CIPHER_fetch(NULL, "AES-256-CBC-CTS", NULL); + if (cipher == NULL) + return KRB5_CRYPTO_INTERNAL; + + oblock = OPENSSL_malloc(dlen); + dbuf = OPENSSL_malloc(dlen); + ctx = EVP_CIPHER_CTX_new(); + if (oblock == NULL || dbuf == NULL || ctx == NULL) { + ret = ENOMEM; + goto cleanup; + } + + k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE); + k5_iov_cursor_get(&cursor, dbuf); + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE, + "CS3", 0); + *p = OSSL_PARAM_construct_end(); + if (!EVP_CipherInit_ex2(ctx, cipher, key->keyblock.contents, iv_cts, + encrypt, params) || + !EVP_CipherUpdate(ctx, oblock, &outlen, dbuf, dlen) || + !EVP_CipherFinal_ex(ctx, oblock + outlen, &len)) { + ret = KRB5_CRYPTO_INTERNAL; + goto cleanup; + } + + if (ivec != NULL && ivec->data != NULL && + !EVP_CIPHER_CTX_get_updated_iv(ctx, ivec->data, sizeof(iv_cts))) { + ret = KRB5_CRYPTO_INTERNAL; + goto cleanup; + } + + k5_iov_cursor_put(&cursor, oblock); + + ret = 0; +cleanup: + OPENSSL_clear_free(oblock, dlen); + OPENSSL_clear_free(dbuf, dlen); + EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_free(cipher); + return ret; +} + +static inline krb5_error_code +cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen) +{ + return do_cts(key, ivec, data, num_data, dlen, 1); +} + +static inline krb5_error_code +cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen) +{ + return do_cts(key, ivec, data, num_data, dlen, 0); +} + +#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + +static krb5_error_code +cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen) +{ + int ret = 0; + size_t size = 0; + unsigned char *oblock = NULL, *dbuf = NULL; + unsigned char iv_cts[IV_CTS_BUF_SIZE]; + struct iov_cursor cursor; + AES_KEY enck; + + memset(iv_cts,0,sizeof(iv_cts)); + if (ivec && ivec->data){ + if (ivec->length != sizeof(iv_cts)) + return KRB5_CRYPTO_INTERNAL; + memcpy(iv_cts, ivec->data,ivec->length); + } + + oblock = OPENSSL_malloc(dlen); + if (!oblock){ + return ENOMEM; + } + dbuf = OPENSSL_malloc(dlen); + if (!dbuf){ + OPENSSL_free(oblock); + return ENOMEM; + } + + k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE); + k5_iov_cursor_get(&cursor, dbuf); + + AES_set_encrypt_key(key->keyblock.contents, + NUM_BITS * key->keyblock.length, &enck); + + size = CRYPTO_cts128_encrypt((unsigned char *)dbuf, oblock, dlen, &enck, + iv_cts, (cbc128_f)AES_cbc_encrypt); + if (size <= 0) + ret = KRB5_CRYPTO_INTERNAL; + else + k5_iov_cursor_put(&cursor, oblock); + + if (!ret && ivec && ivec->data) + memcpy(ivec->data, iv_cts, sizeof(iv_cts)); + + zap(oblock, dlen); + zap(dbuf, dlen); + OPENSSL_free(oblock); + OPENSSL_free(dbuf); + + return ret; +} + +static krb5_error_code +cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen) +{ + int ret = 0; + size_t size = 0; + unsigned char *oblock = NULL; + unsigned char *dbuf = NULL; + unsigned char iv_cts[IV_CTS_BUF_SIZE]; + struct iov_cursor cursor; + AES_KEY deck; + + memset(iv_cts,0,sizeof(iv_cts)); + if (ivec && ivec->data){ + if (ivec->length != sizeof(iv_cts)) + return KRB5_CRYPTO_INTERNAL; + memcpy(iv_cts, ivec->data,ivec->length); + } + + oblock = OPENSSL_malloc(dlen); + if (!oblock) + return ENOMEM; + dbuf = OPENSSL_malloc(dlen); + if (!dbuf){ + OPENSSL_free(oblock); + return ENOMEM; + } + + AES_set_decrypt_key(key->keyblock.contents, + NUM_BITS * key->keyblock.length, &deck); + + k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE); + k5_iov_cursor_get(&cursor, dbuf); + + size = CRYPTO_cts128_decrypt((unsigned char *)dbuf, oblock, + dlen, &deck, + iv_cts, (cbc128_f)AES_cbc_encrypt); + if (size <= 0) + ret = KRB5_CRYPTO_INTERNAL; + else + k5_iov_cursor_put(&cursor, oblock); + + if (!ret && ivec && ivec->data) + memcpy(ivec->data, iv_cts, sizeof(iv_cts)); + + zap(oblock, dlen); + zap(dbuf, dlen); + OPENSSL_free(oblock); + OPENSSL_free(dbuf); + + return ret; +} + +#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + +krb5_error_code +krb5int_aes_encrypt(krb5_key key, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + int ret = 0; + size_t input_length, nblocks; + + input_length = iov_total_length(data, num_data, FALSE); + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (nblocks == 1) { + if (input_length != BLOCK_SIZE) + return KRB5_BAD_MSIZE; + ret = cbc_enc(key, ivec, data, num_data); + } else if (nblocks > 1) { + ret = cts_encr(key, ivec, data, num_data, input_length); + } + + return ret; +} + +krb5_error_code +krb5int_aes_decrypt(krb5_key key, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + int ret = 0; + size_t input_length, nblocks; + + input_length = iov_total_length(data, num_data, FALSE); + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (nblocks == 1) { + if (input_length != BLOCK_SIZE) + return KRB5_BAD_MSIZE; + ret = cbc_decr(key, ivec, data, num_data); + } else if (nblocks > 1) { + ret = cts_decr(key, ivec, data, num_data, input_length); + } + + return ret; +} + +static krb5_error_code +krb5int_aes_init_state (const krb5_keyblock *key, krb5_keyusage usage, + krb5_data *state) +{ + state->length = 16; + state->data = (void *) malloc(16); + if (state->data == NULL) + return ENOMEM; + memset(state->data, 0, state->length); + return 0; +} +const struct krb5_enc_provider krb5int_enc_aes128 = { + 16, + 16, 16, + krb5int_aes_encrypt, + krb5int_aes_decrypt, + NULL, + krb5int_aes_init_state, + krb5int_default_free_state +}; + +const struct krb5_enc_provider krb5int_enc_aes256 = { + 16, + 32, 32, + krb5int_aes_encrypt, + krb5int_aes_decrypt, + NULL, + krb5int_aes_init_state, + krb5int_default_free_state +}; + +#endif /* K5_OPENSSL_AES */ diff --git a/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/camellia.c b/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/camellia.c new file mode 100644 index 00000000..01920e6c --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/camellia.c @@ -0,0 +1,448 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/openssl/enc_provider/camellia.c */ +/* + * Copyright (C) 2003, 2007, 2008, 2009, 2010 by the Massachusetts Institute of + * Technology. All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +#ifdef K5_OPENSSL_CAMELLIA + +#include +#include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#else +#include +#endif + +static krb5_error_code +cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data); +static krb5_error_code +cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data); +static krb5_error_code +cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen); +static krb5_error_code +cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen); + +#define BLOCK_SIZE 16 +#define NUM_BITS 8 +#define IV_CTS_BUF_SIZE 16 /* 16 - hardcoded in CRYPTO_cts128_en/decrypt */ + +static const EVP_CIPHER * +map_mode(unsigned int len) +{ + if (len==16) + return EVP_camellia_128_cbc(); + if (len==32) + return EVP_camellia_256_cbc(); + else + return NULL; +} + +/* Encrypt one block using CBC. */ +static krb5_error_code +cbc_enc(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + int ret, olen = BLOCK_SIZE; + unsigned char iblock[BLOCK_SIZE], oblock[BLOCK_SIZE]; + EVP_CIPHER_CTX *ctx; + struct iov_cursor cursor; + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return ENOMEM; + + ret = EVP_EncryptInit_ex(ctx, map_mode(key->keyblock.length), + NULL, key->keyblock.contents, (ivec) ? (unsigned char*)ivec->data : NULL); + if (ret == 0) { + EVP_CIPHER_CTX_free(ctx); + return KRB5_CRYPTO_INTERNAL; + } + + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE); + k5_iov_cursor_get(&cursor, iblock); + EVP_CIPHER_CTX_set_padding(ctx,0); + ret = EVP_EncryptUpdate(ctx, oblock, &olen, iblock, BLOCK_SIZE); + if (ret == 1) + k5_iov_cursor_put(&cursor, oblock); + EVP_CIPHER_CTX_free(ctx); + + zap(iblock, BLOCK_SIZE); + zap(oblock, BLOCK_SIZE); + return (ret == 1) ? 0 : KRB5_CRYPTO_INTERNAL; +} + +/* Decrypt one block using CBC. */ +static krb5_error_code +cbc_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + int ret = 0, olen = BLOCK_SIZE; + unsigned char iblock[BLOCK_SIZE], oblock[BLOCK_SIZE]; + EVP_CIPHER_CTX *ctx; + struct iov_cursor cursor; + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return ENOMEM; + + ret = EVP_DecryptInit_ex(ctx, map_mode(key->keyblock.length), + NULL, key->keyblock.contents, (ivec) ? (unsigned char*)ivec->data : NULL); + if (ret == 0) { + EVP_CIPHER_CTX_free(ctx); + return KRB5_CRYPTO_INTERNAL; + } + + k5_iov_cursor_init(&cursor, data, num_data, BLOCK_SIZE, FALSE); + k5_iov_cursor_get(&cursor, iblock); + EVP_CIPHER_CTX_set_padding(ctx,0); + ret = EVP_DecryptUpdate(ctx, oblock, &olen, iblock, BLOCK_SIZE); + if (ret == 1) + k5_iov_cursor_put(&cursor, oblock); + EVP_CIPHER_CTX_free(ctx); + + zap(iblock, BLOCK_SIZE); + zap(oblock, BLOCK_SIZE); + return (ret == 1) ? 0 : KRB5_CRYPTO_INTERNAL; +} + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + +static krb5_error_code +do_cts(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen, int encrypt) +{ + krb5_error_code ret; + int outlen, len; + unsigned char *oblock = NULL, *dbuf = NULL; + unsigned char iv_cts[IV_CTS_BUF_SIZE]; + struct iov_cursor cursor; + OSSL_PARAM params[2], *p = params; + EVP_CIPHER_CTX *ctx = NULL; + EVP_CIPHER *cipher = NULL; + + memset(iv_cts, 0, sizeof(iv_cts)); + if (ivec != NULL && ivec->data != NULL){ + if (ivec->length != sizeof(iv_cts)) + return KRB5_CRYPTO_INTERNAL; + memcpy(iv_cts, ivec->data, ivec->length); + } + + if (key->keyblock.length == 16) + cipher = EVP_CIPHER_fetch(NULL, "CAMELLIA-128-CBC-CTS", NULL); + else if (key->keyblock.length == 32) + cipher = EVP_CIPHER_fetch(NULL, "CAMELLIA-256-CBC-CTS", NULL); + if (cipher == NULL) + return KRB5_CRYPTO_INTERNAL; + + oblock = OPENSSL_malloc(dlen); + dbuf = OPENSSL_malloc(dlen); + ctx = EVP_CIPHER_CTX_new(); + if (oblock == NULL || dbuf == NULL || ctx == NULL) { + ret = ENOMEM; + goto cleanup; + } + + k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE); + k5_iov_cursor_get(&cursor, dbuf); + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE, + "CS3", 0); + *p = OSSL_PARAM_construct_end(); + if (!EVP_CipherInit_ex2(ctx, cipher, key->keyblock.contents, iv_cts, + encrypt, params) || + !EVP_CipherUpdate(ctx, oblock, &outlen, dbuf, dlen) || + !EVP_CipherFinal_ex(ctx, oblock + outlen, &len)) { + ret = KRB5_CRYPTO_INTERNAL; + goto cleanup; + } + + if (ivec != NULL && ivec->data != NULL && + !EVP_CIPHER_CTX_get_updated_iv(ctx, ivec->data, sizeof(iv_cts))) { + ret = KRB5_CRYPTO_INTERNAL; + goto cleanup; + } + + k5_iov_cursor_put(&cursor, oblock); + + ret = 0; +cleanup: + OPENSSL_clear_free(oblock, dlen); + OPENSSL_clear_free(dbuf, dlen); + EVP_CIPHER_CTX_free(ctx); + EVP_CIPHER_free(cipher); + return ret; +} + +static inline krb5_error_code +cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen) +{ + return do_cts(key, ivec, data, num_data, dlen, 1); +} + +static inline krb5_error_code +cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen) +{ + return do_cts(key, ivec, data, num_data, dlen, 0); +} + +#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + +static krb5_error_code +cts_encr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen) +{ + int ret = 0; + size_t size = 0; + unsigned char *oblock = NULL, *dbuf = NULL; + unsigned char iv_cts[IV_CTS_BUF_SIZE]; + struct iov_cursor cursor; + CAMELLIA_KEY enck; + + memset(iv_cts,0,sizeof(iv_cts)); + if (ivec && ivec->data){ + if (ivec->length != sizeof(iv_cts)) + return KRB5_CRYPTO_INTERNAL; + memcpy(iv_cts, ivec->data,ivec->length); + } + + oblock = OPENSSL_malloc(dlen); + if (!oblock){ + return ENOMEM; + } + dbuf = OPENSSL_malloc(dlen); + if (!dbuf){ + OPENSSL_free(oblock); + return ENOMEM; + } + + k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE); + k5_iov_cursor_get(&cursor, dbuf); + + Camellia_set_key(key->keyblock.contents, NUM_BITS * key->keyblock.length, + &enck); + + size = CRYPTO_cts128_encrypt((unsigned char *)dbuf, oblock, dlen, &enck, + iv_cts, (cbc128_f)Camellia_cbc_encrypt); + if (size <= 0) + ret = KRB5_CRYPTO_INTERNAL; + else + k5_iov_cursor_put(&cursor, oblock); + + if (!ret && ivec && ivec->data) + memcpy(ivec->data, iv_cts, sizeof(iv_cts)); + + zap(oblock, dlen); + zap(dbuf, dlen); + OPENSSL_free(oblock); + OPENSSL_free(dbuf); + + return ret; +} + +static krb5_error_code +cts_decr(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data, size_t dlen) +{ + int ret = 0; + size_t size = 0; + unsigned char *oblock = NULL; + unsigned char *dbuf = NULL; + unsigned char iv_cts[IV_CTS_BUF_SIZE]; + struct iov_cursor cursor; + CAMELLIA_KEY deck; + + memset(iv_cts,0,sizeof(iv_cts)); + if (ivec && ivec->data){ + if (ivec->length != sizeof(iv_cts)) + return KRB5_CRYPTO_INTERNAL; + memcpy(iv_cts, ivec->data,ivec->length); + } + + oblock = OPENSSL_malloc(dlen); + if (!oblock) + return ENOMEM; + dbuf = OPENSSL_malloc(dlen); + if (!dbuf){ + OPENSSL_free(oblock); + return ENOMEM; + } + + Camellia_set_key(key->keyblock.contents, NUM_BITS * key->keyblock.length, + &deck); + + k5_iov_cursor_init(&cursor, data, num_data, dlen, FALSE); + k5_iov_cursor_get(&cursor, dbuf); + + size = CRYPTO_cts128_decrypt((unsigned char *)dbuf, oblock, + dlen, &deck, + iv_cts, (cbc128_f)Camellia_cbc_encrypt); + if (size <= 0) + ret = KRB5_CRYPTO_INTERNAL; + else + k5_iov_cursor_put(&cursor, oblock); + + if (!ret && ivec && ivec->data) + memcpy(ivec->data, iv_cts, sizeof(iv_cts)); + + zap(oblock, dlen); + zap(dbuf, dlen); + OPENSSL_free(oblock); + OPENSSL_free(dbuf); + + return ret; +} + +#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + +krb5_error_code +krb5int_camellia_encrypt(krb5_key key, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + int ret = 0; + size_t input_length, nblocks; + + input_length = iov_total_length(data, num_data, FALSE); + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (nblocks == 1) { + if (input_length != BLOCK_SIZE) + return KRB5_BAD_MSIZE; + ret = cbc_enc(key, ivec, data, num_data); + } else if (nblocks > 1) { + ret = cts_encr(key, ivec, data, num_data, input_length); + } + + return ret; +} + +static krb5_error_code +krb5int_camellia_decrypt(krb5_key key, const krb5_data *ivec, + krb5_crypto_iov *data, size_t num_data) +{ + int ret = 0; + size_t input_length, nblocks; + + input_length = iov_total_length(data, num_data, FALSE); + nblocks = (input_length + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (nblocks == 1) { + if (input_length != BLOCK_SIZE) + return KRB5_BAD_MSIZE; + ret = cbc_decr(key, ivec, data, num_data); + } else if (nblocks > 1) { + ret = cts_decr(key, ivec, data, num_data, input_length); + } + + return ret; +} + +#ifdef K5_BUILTIN_CMAC + +static void +xorblock(uint8_t *out, const uint8_t *in) +{ + int z; + + for (z = 0; z < CAMELLIA_BLOCK_SIZE / 4; z++) { + uint8_t *outptr = &out[z * 4]; + const uint8_t *inptr = &in[z * 4]; + + store_32_n(load_32_n(outptr) ^ load_32_n(inptr), outptr); + } +} + +static krb5_error_code +krb5int_camellia_cbc_mac(krb5_key key, const krb5_crypto_iov *data, + size_t num_data, const krb5_data *iv, + krb5_data *output) +{ + CAMELLIA_KEY enck; + unsigned char blockY[CAMELLIA_BLOCK_SIZE], blockB[CAMELLIA_BLOCK_SIZE]; + struct iov_cursor cursor; + + if (output->length < CAMELLIA_BLOCK_SIZE) + return KRB5_BAD_MSIZE; + + Camellia_set_key(key->keyblock.contents, + NUM_BITS * key->keyblock.length, &enck); + + if (iv != NULL) + memcpy(blockY, iv->data, CAMELLIA_BLOCK_SIZE); + else + memset(blockY, 0, CAMELLIA_BLOCK_SIZE); + + k5_iov_cursor_init(&cursor, data, num_data, CAMELLIA_BLOCK_SIZE, FALSE); + while (k5_iov_cursor_get(&cursor, blockB)) { + xorblock(blockB, blockY); + Camellia_ecb_encrypt(blockB, blockY, &enck, 1); + } + + output->length = CAMELLIA_BLOCK_SIZE; + memcpy(output->data, blockY, CAMELLIA_BLOCK_SIZE); + + return 0; +} + +#else +#define krb5int_camellia_cbc_mac NULL +#endif + +static krb5_error_code +krb5int_camellia_init_state (const krb5_keyblock *key, krb5_keyusage usage, + krb5_data *state) +{ + state->length = 16; + state->data = (void *) malloc(16); + if (state->data == NULL) + return ENOMEM; + memset(state->data, 0, state->length); + return 0; +} +const struct krb5_enc_provider krb5int_enc_camellia128 = { + 16, + 16, 16, + krb5int_camellia_encrypt, + krb5int_camellia_decrypt, + krb5int_camellia_cbc_mac, /* NULL if K5_BUILTIN_CMAC not defined */ + krb5int_camellia_init_state, + krb5int_default_free_state +}; + +const struct krb5_enc_provider krb5int_enc_camellia256 = { + 16, + 32, 32, + krb5int_camellia_encrypt, + krb5int_camellia_decrypt, + krb5int_camellia_cbc_mac, /* NULL if K5_BUILTIN_CMAC not defined */ + krb5int_camellia_init_state, + krb5int_default_free_state +}; + +#endif /* K5_OPENSSL_CAMELLIA */ diff --git a/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/deps b/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/deps new file mode 100644 index 00000000..1c87a526 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/deps @@ -0,0 +1,47 @@ +# +# Generated makefile dependencies follow. +# +des3.so des3.po $(OUTPRE)des3.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + des3.c +aes.so aes.po $(OUTPRE)aes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + aes.c +camellia.so camellia.po $(OUTPRE)camellia.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h camellia.c +rc4.so rc4.po $(OUTPRE)rc4.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + rc4.c diff --git a/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/des3.c b/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/des3.c new file mode 100644 index 00000000..90fcf9ac --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/des3.c @@ -0,0 +1,188 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/openssl/enc_provider/des3.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "crypto_int.h" + +#ifdef K5_OPENSSL_DES + +#include + +#define DES3_BLOCK_SIZE 8 +#define DES3_KEY_SIZE 24 +#define DES3_KEY_BYTES 21 + +static krb5_error_code +validate(krb5_key key, const krb5_data *ivec, const krb5_crypto_iov *data, + size_t num_data, krb5_boolean *empty) +{ + size_t input_length = iov_total_length(data, num_data, FALSE); + + if (key->keyblock.length != DES3_KEY_SIZE) + return(KRB5_BAD_KEYSIZE); + if ((input_length%DES3_BLOCK_SIZE) != 0) + return(KRB5_BAD_MSIZE); + if (ivec && (ivec->length != 8)) + return(KRB5_BAD_MSIZE); + + *empty = (input_length == 0); + return 0; +} + +static krb5_error_code +k5_des3_encrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + int ret, olen = DES3_BLOCK_SIZE; + unsigned char iblock[DES3_BLOCK_SIZE], oblock[DES3_BLOCK_SIZE]; + struct iov_cursor cursor; + EVP_CIPHER_CTX *ctx; + krb5_boolean empty; + + ret = validate(key, ivec, data, num_data, &empty); + if (ret != 0 || empty) + return ret; + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return ENOMEM; + + ret = EVP_EncryptInit_ex(ctx, EVP_des_ede3_cbc(), NULL, + key->keyblock.contents, + (ivec) ? (unsigned char*)ivec->data : NULL); + if (!ret) { + EVP_CIPHER_CTX_free(ctx); + return KRB5_CRYPTO_INTERNAL; + } + + EVP_CIPHER_CTX_set_padding(ctx,0); + + k5_iov_cursor_init(&cursor, data, num_data, DES3_BLOCK_SIZE, FALSE); + while (k5_iov_cursor_get(&cursor, iblock)) { + ret = EVP_EncryptUpdate(ctx, oblock, &olen, iblock, DES3_BLOCK_SIZE); + if (!ret) + break; + k5_iov_cursor_put(&cursor, oblock); + } + + if (ivec != NULL) + memcpy(ivec->data, oblock, DES3_BLOCK_SIZE); + + EVP_CIPHER_CTX_free(ctx); + + zap(iblock, sizeof(iblock)); + zap(oblock, sizeof(oblock)); + + if (ret != 1) + return KRB5_CRYPTO_INTERNAL; + return 0; +} + +static krb5_error_code +k5_des3_decrypt(krb5_key key, const krb5_data *ivec, krb5_crypto_iov *data, + size_t num_data) +{ + int ret, olen = DES3_BLOCK_SIZE; + unsigned char iblock[DES3_BLOCK_SIZE], oblock[DES3_BLOCK_SIZE]; + struct iov_cursor cursor; + EVP_CIPHER_CTX *ctx; + krb5_boolean empty; + + ret = validate(key, ivec, data, num_data, &empty); + if (ret != 0 || empty) + return ret; + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return ENOMEM; + + ret = EVP_DecryptInit_ex(ctx, EVP_des_ede3_cbc(), NULL, + key->keyblock.contents, + (ivec) ? (unsigned char*)ivec->data : NULL); + if (!ret) { + EVP_CIPHER_CTX_free(ctx); + return KRB5_CRYPTO_INTERNAL; + } + + EVP_CIPHER_CTX_set_padding(ctx,0); + + k5_iov_cursor_init(&cursor, data, num_data, DES3_BLOCK_SIZE, FALSE); + while (k5_iov_cursor_get(&cursor, iblock)) { + ret = EVP_DecryptUpdate(ctx, oblock, &olen, + (unsigned char *)iblock, DES3_BLOCK_SIZE); + if (!ret) + break; + k5_iov_cursor_put(&cursor, oblock); + } + + if (ivec != NULL) + memcpy(ivec->data, iblock, DES3_BLOCK_SIZE); + + EVP_CIPHER_CTX_free(ctx); + + zap(iblock, sizeof(iblock)); + zap(oblock, sizeof(oblock)); + + if (ret != 1) + return KRB5_CRYPTO_INTERNAL; + return 0; +} + +const struct krb5_enc_provider krb5int_enc_des3 = { + DES3_BLOCK_SIZE, + DES3_KEY_BYTES, DES3_KEY_SIZE, + k5_des3_encrypt, + k5_des3_decrypt, + NULL, + krb5int_des_init_state, + krb5int_default_free_state +}; + +#endif /* K5_OPENSSL_DES */ diff --git a/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/rc4.c b/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/rc4.c new file mode 100644 index 00000000..448d5633 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/enc_provider/rc4.c @@ -0,0 +1,170 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/openssl/enc_provider/rc4.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Copyright (c) 2000 by Computer Science Laboratory, + * Rensselaer Polytechnic Institute + * + * #include STD_DISCLAIMER + */ + + +#include "crypto_int.h" + +#ifdef K5_OPENSSL_RC4 + +#include + +/* + * The loopback field is a pointer to the structure. If the application copies + * the state (not a valid operation, but one which happens to works with some + * other enc providers), we can detect it via the loopback field and return a + * sane error code. + */ +struct arcfour_state { + struct arcfour_state *loopback; + EVP_CIPHER_CTX *ctx; +}; + +#define RC4_KEY_SIZE 16 +#define RC4_BLOCK_SIZE 1 + +/* Interface layer to krb5 crypto layer */ + +/* The workhorse of the arcfour system, + * this implements the cipher + */ + +/* In-place IOV crypto */ +static krb5_error_code +k5_arcfour_docrypt(krb5_key key, const krb5_data *state, krb5_crypto_iov *data, + size_t num_data) +{ + size_t i; + int ret = 1, tmp_len = 0; + krb5_crypto_iov *iov = NULL; + EVP_CIPHER_CTX *ctx = NULL; + struct arcfour_state *arcstate; + + arcstate = (state != NULL) ? (void *)state->data : NULL; + if (arcstate != NULL) { + ctx = arcstate->ctx; + if (arcstate->loopback != arcstate) + return KRB5_CRYPTO_INTERNAL; + } + + if (ctx == NULL) { + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) + return ENOMEM; + + ret = EVP_EncryptInit_ex(ctx, EVP_rc4(), NULL, key->keyblock.contents, + NULL); + if (!ret) { + EVP_CIPHER_CTX_free(ctx); + return KRB5_CRYPTO_INTERNAL; + } + + if (arcstate != NULL) + arcstate->ctx = ctx; + } + + for (i = 0; i < num_data; i++) { + iov = &data[i]; + if (ENCRYPT_IOV(iov)) { + ret = EVP_EncryptUpdate(ctx, + (unsigned char *) iov->data.data, &tmp_len, + (unsigned char *) iov->data.data, + iov->data.length); + if (!ret) + break; + } + } + + if (arcstate == NULL) + EVP_CIPHER_CTX_free(ctx); + + if (!ret) + return KRB5_CRYPTO_INTERNAL; + + return 0; +} + +static void +k5_arcfour_free_state(krb5_data *state) +{ + struct arcfour_state *arcstate = (void *)state->data; + + EVP_CIPHER_CTX_free(arcstate->ctx); + free(arcstate); +} + +static krb5_error_code +k5_arcfour_init_state(const krb5_keyblock *key, + krb5_keyusage keyusage, krb5_data *new_state) +{ + struct arcfour_state *arcstate; + + /* + * The cipher state here is a saved pointer to a struct arcfour_state + * object, rather than a flat byte array as in most enc providers. The + * object includes a loopback pointer to detect if if the caller made a + * copy of the krb5_data value or otherwise assumed it was a simple byte + * array. When we cast the data pointer back, we need to go through void * + * to avoid increased alignment warnings. + */ + + /* Create a state structure with an uninitialized context. */ + arcstate = calloc(1, sizeof(*arcstate)); + if (arcstate == NULL) + return ENOMEM; + arcstate->loopback = arcstate; + arcstate->ctx = NULL; + new_state->data = (char *) arcstate; + new_state->length = sizeof(*arcstate); + return 0; +} + +/* Since the arcfour cipher is identical going forwards and backwards, + we just call "docrypt" directly +*/ +const struct krb5_enc_provider krb5int_enc_arcfour = { + /* This seems to work... although I am not sure what the + implications are in other places in the kerberos library */ + RC4_BLOCK_SIZE, + /* Keysize is arbitrary in arcfour, but the constraints of the + system, and to attempt to work with the MSFT system forces us + to 16byte/128bit. Since there is no parity in the key, the + byte and length are the same. */ + RC4_KEY_SIZE, RC4_KEY_SIZE, + k5_arcfour_docrypt, + k5_arcfour_docrypt, + NULL, + k5_arcfour_init_state, + k5_arcfour_free_state +}; + +#endif /* K5_OPENSSL_RC4 */ diff --git a/krb5-1.21.3/src/lib/crypto/openssl/hash_provider/Makefile.in b/krb5-1.21.3/src/lib/crypto/openssl/hash_provider/Makefile.in new file mode 100644 index 00000000..b696c4e9 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/hash_provider/Makefile.in @@ -0,0 +1,20 @@ +mydir=lib$(S)crypto$(S)openssl$(S)hash_provider +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/../../krb $(CRYPTO_IMPL_CFLAGS) + +STLIBOBJS= hash_evp.o + +OBJS= $(OUTPRE)hash_evp.$(OBJEXT) + +SRCS= $(srcdir)/hash_evp.c + +all-unix: all-libobjs + +includes: depend + +depend: $(SRCS) + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/crypto/openssl/hash_provider/deps b/krb5-1.21.3/src/lib/crypto/openssl/hash_provider/deps new file mode 100644 index 00000000..afc2e845 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/hash_provider/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +hash_evp.so hash_evp.po $(OUTPRE)hash_evp.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../krb/crypto_int.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h hash_evp.c diff --git a/krb5-1.21.3/src/lib/crypto/openssl/hash_provider/hash_evp.c b/krb5-1.21.3/src/lib/crypto/openssl/hash_provider/hash_evp.c new file mode 100644 index 00000000..f2fbffdb --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/hash_provider/hash_evp.c @@ -0,0 +1,133 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/openssl/hash_provider/hash_evp.c - OpenSSL hash providers */ +/* + * Copyright (C) 2015 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. + */ + +#include "crypto_int.h" + +#if defined(K5_OPENSSL_MD4) || defined(K5_OPENSSL_MD5) || \ + defined(K5_OPENSSL_SHA1) || defined(K5_OPENSSL_SHA2) + +#include + +/* 1.1 standardizes constructor and destructor names, renaming + * EVP_MD_CTX_create and EVP_MD_CTX_destroy. */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define EVP_MD_CTX_new EVP_MD_CTX_create +#define EVP_MD_CTX_free EVP_MD_CTX_destroy +#endif + +static krb5_error_code +hash_evp(const EVP_MD *type, const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + EVP_MD_CTX *ctx; + const krb5_data *d; + size_t i; + int ok; + + if (output->length != (unsigned int)EVP_MD_size(type)) + return KRB5_CRYPTO_INTERNAL; + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return ENOMEM; + + ok = EVP_DigestInit_ex(ctx, type, NULL); + for (i = 0; i < num_data; i++) { + if (!SIGN_IOV(&data[i])) + continue; + d = &data[i].data; + ok = ok && EVP_DigestUpdate(ctx, d->data, d->length); + } + ok = ok && EVP_DigestFinal_ex(ctx, (uint8_t *)output->data, NULL); + EVP_MD_CTX_free(ctx); + return ok ? 0 : KRB5_CRYPTO_INTERNAL; +} + +#endif + +#ifdef K5_OPENSSL_MD4 +static krb5_error_code +hash_md4(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + return hash_evp(EVP_md4(), data, num_data, output); +} + +const struct krb5_hash_provider krb5int_hash_md4 = { + "MD4", 16, 64, hash_md4 +}; +#endif + +#ifdef K5_OPENSSL_MD5 +static krb5_error_code +hash_md5(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + return hash_evp(EVP_md5(), data, num_data, output); +} + +const struct krb5_hash_provider krb5int_hash_md5 = { + "MD5", 16, 64, hash_md5 +}; +#endif + +#ifdef K5_OPENSSL_SHA1 +static krb5_error_code +hash_sha1(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + return hash_evp(EVP_sha1(), data, num_data, output); +} + +const struct krb5_hash_provider krb5int_hash_sha1 = { + "SHA1", 20, 64, hash_sha1 +}; +#endif + +#ifdef K5_OPENSSL_SHA2 +static krb5_error_code +hash_sha256(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + return hash_evp(EVP_sha256(), data, num_data, output); +} + +static krb5_error_code +hash_sha384(const krb5_crypto_iov *data, size_t num_data, krb5_data *output) +{ + return hash_evp(EVP_sha384(), data, num_data, output); +} + +const struct krb5_hash_provider krb5int_hash_sha256 = { + "SHA-256", 32, 64, hash_sha256 +}; + +const struct krb5_hash_provider krb5int_hash_sha384 = { + "SHA-384", 48, 128, hash_sha384 +}; +#endif diff --git a/krb5-1.21.3/src/lib/crypto/openssl/hmac.c b/krb5-1.21.3/src/lib/crypto/openssl/hmac.c new file mode 100644 index 00000000..bf12b8d6 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/hmac.c @@ -0,0 +1,231 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/openssl/hmac.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + + +#include "crypto_int.h" + +#ifdef K5_OPENSSL_HMAC + +#include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#include +#else +#include +#endif + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +/* OpenSSL 1.1 makes HMAC_CTX opaque, while 1.0 does not have pointer + * constructors or destructors. */ + +#define HMAC_CTX_new compat_hmac_ctx_new +static HMAC_CTX * +compat_hmac_ctx_new() +{ + HMAC_CTX *ctx; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx != NULL) + HMAC_CTX_init(ctx); + return ctx; +} + +#define HMAC_CTX_free compat_hmac_ctx_free +static void +compat_hmac_ctx_free(HMAC_CTX *ctx) +{ + HMAC_CTX_cleanup(ctx); + free(ctx); +} + +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ + +/* + * the HMAC transform looks like: + * + * H(K XOR opad, H(K XOR ipad, text)) + * + * where H is a cryptographic hash + * K is an n byte key + * ipad is the byte 0x36 repeated blocksize times + * opad is the byte 0x5c repeated blocksize times + * and text is the data being protected + */ + +static const EVP_MD * +map_digest(const struct krb5_hash_provider *hash) +{ + if (hash == &krb5int_hash_sha1) + return EVP_sha1(); + else if (hash == &krb5int_hash_sha256) + return EVP_sha256(); + else if (hash == &krb5int_hash_sha384) + return EVP_sha384(); + else if (hash == &krb5int_hash_md5) + return EVP_md5(); + else if (hash == &krb5int_hash_md4) + return EVP_md4(); + else + return NULL; +} + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + +krb5_error_code +krb5int_hmac_keyblock(const struct krb5_hash_provider *hash, + const krb5_keyblock *keyblock, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + int ok; + const EVP_MD *md = map_digest(hash); + EVP_MAC *mac = NULL; + EVP_MAC_CTX *ctx = NULL; + OSSL_PARAM params[2], *p = params; + size_t i = 0, md_len; + + if (md == NULL || keyblock->length > hash->blocksize) + return KRB5_CRYPTO_INTERNAL; + if (output->length < hash->hashsize) + return KRB5_BAD_MSIZE; + + mac = EVP_MAC_fetch(NULL, "HMAC", NULL); + if (mac == NULL) + return KRB5_CRYPTO_INTERNAL; + + ctx = EVP_MAC_CTX_new(mac); + if (ctx == NULL) { + ok = 0; + goto cleanup; + } + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_ALG_PARAM_DIGEST, + (char *)EVP_MD_get0_name(md), 0); + *p = OSSL_PARAM_construct_end(); + + ok = EVP_MAC_init(ctx, keyblock->contents, keyblock->length, params); + for (i = 0; ok && i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + if (!SIGN_IOV(iov)) + continue; + ok = EVP_MAC_update(ctx, (uint8_t *)iov->data.data, iov->data.length); + } + ok = ok && EVP_MAC_final(ctx, (uint8_t *)output->data, &md_len, + output->length); + if (!ok) + goto cleanup; + output->length = md_len; + +cleanup: + EVP_MAC_free(mac); + EVP_MAC_CTX_free(ctx); + return ok ? 0 : KRB5_CRYPTO_INTERNAL; +} + +#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + +krb5_error_code +krb5int_hmac_keyblock(const struct krb5_hash_provider *hash, + const krb5_keyblock *keyblock, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + unsigned int i = 0, md_len = 0, ok; + unsigned char md[EVP_MAX_MD_SIZE]; + HMAC_CTX *ctx; + size_t hashsize, blocksize; + + hashsize = hash->hashsize; + blocksize = hash->blocksize; + + if (keyblock->length > blocksize) + return(KRB5_CRYPTO_INTERNAL); + if (output->length < hashsize) + return(KRB5_BAD_MSIZE); + + if (!map_digest(hash)) + return(KRB5_CRYPTO_INTERNAL); // unsupported alg + + ctx = HMAC_CTX_new(); + if (ctx == NULL) + return ENOMEM; + + ok = HMAC_Init_ex(ctx, keyblock->contents, keyblock->length, + map_digest(hash), NULL); + for (i = 0; ok && i < num_data; i++) { + const krb5_crypto_iov *iov = &data[i]; + + if (SIGN_IOV(iov)) + ok = HMAC_Update(ctx, (uint8_t *)iov->data.data, iov->data.length); + } + if (ok) + ok = HMAC_Final(ctx, md, &md_len); + if (ok && md_len <= output->length) { + output->length = md_len; + memcpy(output->data, md, output->length); + } + HMAC_CTX_free(ctx); + return ok ? 0 : KRB5_CRYPTO_INTERNAL; +} + +#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + +krb5_error_code +krb5int_hmac(const struct krb5_hash_provider *hash, krb5_key key, + const krb5_crypto_iov *data, size_t num_data, + krb5_data *output) +{ + return krb5int_hmac_keyblock(hash, &key->keyblock, data, num_data, output); +} + +#endif /* K5_OPENSSL_HMAC */ diff --git a/krb5-1.21.3/src/lib/crypto/openssl/kdf.c b/krb5-1.21.3/src/lib/crypto/openssl/kdf.c new file mode 100644 index 00000000..41e845ea --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/kdf.c @@ -0,0 +1,237 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2021 by Red Hat, Inc. + * 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. + */ + +#include "crypto_int.h" + +#ifdef K5_OPENSSL_KDF + +#include +#include +#include + +static char * +hash_name(const struct krb5_hash_provider *hash) +{ + if (hash == &krb5int_hash_sha1) + return "SHA1"; + if (hash == &krb5int_hash_sha256) + return "SHA256"; + if (hash == &krb5int_hash_sha384) + return "SHA384"; + return NULL; +} + +static char * +enc_name(const struct krb5_enc_provider *enc) +{ + if (enc == &krb5int_enc_camellia128) + return "CAMELLIA-128-CBC"; + if (enc == &krb5int_enc_camellia256) + return "CAMELLIA-256-CBC"; + if (enc == &krb5int_enc_aes128) + return "AES-128-CBC"; + if (enc == &krb5int_enc_aes256) + return "AES-256-CBC"; + if (enc == &krb5int_enc_des3) + return "DES-EDE3-CBC"; + return NULL; +} + +krb5_error_code +k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash, + krb5_key key, const krb5_data *label, + const krb5_data *context, krb5_data *rnd_out) +{ + krb5_error_code ret; + EVP_KDF *kdf = NULL; + EVP_KDF_CTX *kctx = NULL; + OSSL_PARAM params[6], *p = params; + char *digest; + + digest = hash_name(hash); + if (digest == NULL) { + ret = KRB5_CRYPTO_INTERNAL; + goto done; + } + + kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL); + if (!kdf) { + ret = KRB5_CRYPTO_INTERNAL; + goto done; + } + + kctx = EVP_KDF_CTX_new(kdf); + if (!kctx) { + ret = KRB5_CRYPTO_INTERNAL; + goto done; + } + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, digest, 0); + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC, + OSSL_MAC_NAME_HMAC, 0); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, + key->keyblock.contents, + key->keyblock.length); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, + context->data, context->length); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, + label->data, label->length); + *p = OSSL_PARAM_construct_end(); + if (EVP_KDF_derive(kctx, (uint8_t *)rnd_out->data, rnd_out->length, + params) <= 0) { + ret = KRB5_CRYPTO_INTERNAL; + goto done; + } + + ret = 0; +done: + if (ret) + zap(rnd_out->data, rnd_out->length); + EVP_KDF_free(kdf); + EVP_KDF_CTX_free(kctx); + return ret; +} + +krb5_error_code +k5_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc, krb5_key key, + const krb5_data *label, krb5_data *rnd_out) +{ + krb5_error_code ret; + EVP_KDF *kdf = NULL; + EVP_KDF_CTX *kctx = NULL; + OSSL_PARAM params[7], *p = params; + char *cipher; + static uint8_t zeroes[16]; + + memset(zeroes, 0, sizeof(zeroes)); + + cipher = enc_name(enc); + if (cipher == NULL) { + ret = KRB5_CRYPTO_INTERNAL; + goto done; + } + + kdf = EVP_KDF_fetch(NULL, "KBKDF", NULL); + if (!kdf) { + ret = KRB5_CRYPTO_INTERNAL; + goto done; + } + + kctx = EVP_KDF_CTX_new(kdf); + if (!kctx) { + ret = KRB5_CRYPTO_INTERNAL; + goto done; + } + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE, + "FEEDBACK", 0); + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC, + OSSL_MAC_NAME_CMAC, 0); + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER, cipher, 0); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, + key->keyblock.contents, + key->keyblock.length); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, + label->data, label->length); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SEED, + zeroes, sizeof(zeroes)); + *p = OSSL_PARAM_construct_end(); + if (EVP_KDF_derive(kctx, (uint8_t *)rnd_out->data, rnd_out->length, + params) <= 0) { + ret = KRB5_CRYPTO_INTERNAL; + goto done; + } + + ret = 0; +done: + if (ret) + zap(rnd_out->data, rnd_out->length); + EVP_KDF_free(kdf); + EVP_KDF_CTX_free(kctx); + return ret; +} + +krb5_error_code +k5_derive_random_rfc3961(const struct krb5_enc_provider *enc, krb5_key key, + const krb5_data *constant, krb5_data *rnd_out) +{ + krb5_error_code ret; + EVP_KDF *kdf = NULL; + EVP_KDF_CTX *kctx = NULL; + OSSL_PARAM params[4], *p = params; + char *cipher; + + if (key->keyblock.length != enc->keylength || + rnd_out->length != enc->keybytes) { + return KRB5_CRYPTO_INTERNAL; + } + + cipher = enc_name(enc); + if (cipher == NULL) { + ret = KRB5_CRYPTO_INTERNAL; + goto done; + } + + kdf = EVP_KDF_fetch(NULL, "KRB5KDF", NULL); + if (kdf == NULL) { + ret = KRB5_CRYPTO_INTERNAL; + goto done; + } + + kctx = EVP_KDF_CTX_new(kdf); + if (kctx == NULL) { + ret = KRB5_CRYPTO_INTERNAL; + goto done; + } + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER, cipher, 0); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, + key->keyblock.contents, + key->keyblock.length); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_CONSTANT, + constant->data, constant->length); + *p = OSSL_PARAM_construct_end(); + if (EVP_KDF_derive(kctx, (uint8_t *)rnd_out->data, rnd_out->length, + params) <= 0) { + ret = KRB5_CRYPTO_INTERNAL; + goto done; + } + + ret = 0; +done: + if (ret) + zap(rnd_out->data, rnd_out->length); + EVP_KDF_free(kdf); + EVP_KDF_CTX_free(kctx); + return ret; +} + +#endif /* K5_OPENSSL_KDF */ diff --git a/krb5-1.21.3/src/lib/crypto/openssl/pbkdf2.c b/krb5-1.21.3/src/lib/crypto/openssl/pbkdf2.c new file mode 100644 index 00000000..b8c8de9e --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/pbkdf2.c @@ -0,0 +1,59 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/openssl/pbkdf2.c */ +/* + * Copyright 2002, 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "crypto_int.h" + +#ifdef K5_OPENSSL_HMAC + +#include +#include +#include + +krb5_error_code +krb5int_pbkdf2_hmac(const struct krb5_hash_provider *hash, + const krb5_data *out, unsigned long count, + const krb5_data *pass, const krb5_data *salt) +{ + const EVP_MD *md = NULL; + int ok; + + /* Get the message digest handle corresponding to the hash. */ + if (hash == &krb5int_hash_sha1) + md = EVP_sha1(); + else if (hash == &krb5int_hash_sha256) + md = EVP_sha256(); + else if (hash == &krb5int_hash_sha384) + md = EVP_sha384(); + if (md == NULL) + return KRB5_CRYPTO_INTERNAL; + + ok = PKCS5_PBKDF2_HMAC(pass->data, pass->length, + (unsigned char *)salt->data, salt->length, count, + md, out->length, (unsigned char *)out->data); + return ok ? 0 : KRB5_CRYPTO_INTERNAL; +} + +#endif /* K5_OPENSSL_HMAC */ diff --git a/krb5-1.21.3/src/lib/crypto/openssl/sha256.c b/krb5-1.21.3/src/lib/crypto/openssl/sha256.c new file mode 100644 index 00000000..855ebd7e --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/openssl/sha256.c @@ -0,0 +1,64 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/openssl/sha256.c - k5_sha256() implementation */ +/* + * Copyright (C) 2016 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. + */ + +#include "crypto_int.h" + +#ifdef K5_OPENSSL_SHA2 + +#include + +/* 1.1 standardizes constructor and destructor names, renaming + * EVP_MD_CTX_create and EVP_MD_CTX_destroy. */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define EVP_MD_CTX_new EVP_MD_CTX_create +#define EVP_MD_CTX_free EVP_MD_CTX_destroy +#endif + +krb5_error_code +k5_sha256(const krb5_data *in, size_t n, uint8_t out[K5_SHA256_HASHLEN]) +{ + EVP_MD_CTX *ctx; + size_t i; + int ok; + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return ENOMEM; + ok = EVP_DigestInit_ex(ctx, EVP_sha256(), NULL); + for (i = 0; i < n; i++) + ok = ok && EVP_DigestUpdate(ctx, in[i].data, in[i].length); + ok = ok && EVP_DigestFinal_ex(ctx, out, NULL); + EVP_MD_CTX_free(ctx); + return ok ? 0 : KRB5_CRYPTO_INTERNAL; +} + +#endif diff --git a/krb5-1.21.3/src/lib/deps b/krb5-1.21.3/src/lib/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/lib/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/lib/gssapi/LICENSE b/krb5-1.21.3/src/lib/gssapi/LICENSE new file mode 100644 index 00000000..612f8ad6 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/LICENSE @@ -0,0 +1,91 @@ +[ NOTE: MIT has only incorporated the mechglue and spnego change, and +not the incremental propagation changes. The filenames are different +between the Sun and MIT sources. The actual MIT filenames appear in +the top-level README file. Original text of Sun's LICENSE file +follows. ] + +Subject to the license set forth below, Sun Microsystems, Inc. donates +the attached files to MIT for the purpose of including these +modifications and additions in future versions of the Kerberos system. + +Many of the files attached are subject to licenses issued by other +entities, including OpenVision, MIT, and FundsXpress. See the +individual files, and/or related Readme files, for these licenses. + +In addition Sun requires that the license set forth below be +incorporated into any future version of the Kerberos system which +contains portions of the files attached. The following files must be +listed, in the top level Readme file, as being provided subject to such +license: + +cmd/krb5/iprop/iprop.x +cmd/krb5/iprop/iprop_hdr.h +cmd/krb5/kadmin/server/ipropd_svc.c +cmd/krb5/kproplog/kproplog.c +cmd/krb5/slave/kpropd_rpc.c +lib/gss_mechs/mech_krb5/et/kdb5_err.c +lib/gss_mechs/mech_spnego/mech/gssapiP_spnego.h +lib/gss_mechs/mech_spnego/mech/spnego_mech.c +lib/krb5/kadm5/kadm_host_srv_names.c +lib/krb5/kdb/kdb_convert.c +lib/krb5/kdb/kdb_hdr.h +lib/krb5/kdb/kdb_log.c +lib/krb5/kdb/kdb_log.h +lib/libgss/g_accept_sec_context.c +lib/libgss/g_acquire_cred.c +lib/libgss/g_canon_name.c +lib/libgss/g_compare_name.c +lib/libgss/g_context_time.c +lib/libgss/g_delete_sec_context.c +lib/libgss/g_dsp_name.c +lib/libgss/g_dsp_status.c +lib/libgss/g_dup_name.c +lib/libgss/g_exp_sec_context.c +lib/libgss/g_export_name.c +lib/libgss/g_glue.c +lib/libgss/g_imp_name.c +lib/libgss/g_imp_sec_context.c +lib/libgss/g_init_sec_context.c +lib/libgss/g_initialize.c +lib/libgss/g_inquire_context.c +lib/libgss/g_inquire_cred.c +lib/libgss/g_inquire_names.c +lib/libgss/g_process_context.c +lib/libgss/g_rel_buffer.c +lib/libgss/g_rel_cred.c +lib/libgss/g_rel_name.c +lib/libgss/g_rel_oid_set.c +lib/libgss/g_seal.c +lib/libgss/g_sign.c +lib/libgss/g_store_cred.c +lib/libgss/g_unseal.c +lib/libgss/g_userok.c +lib/libgss/g_utils.c +lib/libgss/g_verify.c +lib/libgss/gssd_pname_to_uid.c +uts/common/gssapi/include/gssapi_err_generic.h +uts/common/gssapi/include/mechglueP.h + +Sun's License is as follows: + +Copyright (c) 2004 Sun Microsystems, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/krb5-1.21.3/src/lib/gssapi/Makefile.in b/krb5-1.21.3/src/lib/gssapi/Makefile.in new file mode 100644 index 00000000..46a9a6bc --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/Makefile.in @@ -0,0 +1,104 @@ +mydir=lib$(S)gssapi +BUILDTOP=$(REL)..$(S).. +SUBDIRS= generic krb5 spnego mechglue +DEFINES=-D_GSS_STATIC_LINK=1 + +##DOSLIBNAME=$(OUTPRE)gssapi.lib +##DOSOBJFILELIST=@$(OUTPRE)mechglue.lst @$(OUTPRE)spnego.lst @$(OUTPRE)generic.lst @$(OUTPRE)krb5.lst # @$(OUTPRE)gssapi.lst +##DOSOBJFILEDEP=$(OUTPRE)mechglue.lst $(OUTPRE)spnego.lst $(OUTPRE)generic.lst $(OUTPRE)krb5.lst # $(OUTPRE)gssapi.lst + +###DOSOBJFILE=$(OUTPRE)gssapi.lst +##DOSLIBOBJS=$(OBJS) + +##DOS##DLL_EXP_TYPE=GSS + +LOCALINCLUDES = -Igeneric -I$(srcdir)/generic -Ikrb5 -I$(srcdir)/krb5 -I$(srcdir)/mechglue +STLIBOBJS= + +OBJS= +SRCS= + +LIBBASE=gssapi_krb5 +LIBMAJOR=2 +LIBMINOR=2 +#LIBINITFUNC=gssint_lib_init +#LIBFINIFUNC=gssint_lib_fini +SUBDIROBJLISTS=generic/OBJS.ST mechglue/OBJS.ST krb5/OBJS.ST spnego/OBJS.ST +STOBJLISTS=OBJS.ST $(SUBDIROBJLISTS) +SHLIB_EXPDEPS=\ + $(KRB5_DEPLIB) $(CRYPTO_DEPLIB) $(SUPPORT_DEPLIB) $(COM_ERR_DEPLIB) +SHLIB_EXPLIBS=-lkrb5 -lk5crypto $(COM_ERR_LIB) $(SUPPORT_LIB) $(DL_LIB) $(LIBS) +RELDIR=gssapi + +all-unix: all-liblinks @MAINT@ verify-calling-conventions-gssapi + +install-unix: install-libs + +clean-unix:: clean-liblinks clean-libs clean-libobjs clean-misc-unix + +clean-windows:: + $(RM) gssapi.lib gssapi.bak + +clean-misc-unix: clean-recurse + $(RM) merged-gssapi-header.h + $(RM) -r $(EHDRDIR) + +EHDRDIR=$(BUILDTOP)$(S)include$(S)gssapi +EXPORTED_HEADERS= \ + $(EHDRDIR)$(S)gssapi_krb5.h \ + $(EHDRDIR)$(S)gssapi_generic.h \ + $(EHDRDIR)$(S)gssapi.h \ + $(EHDRDIR)$(S)gssapi_alloc.h \ + $(EHDRDIR)$(S)gssapi_ext.h +merged-gssapi-header.h: $(EXPORTED_HEADERS) + cat $(EXPORTED_HEADERS) > merged.tmp + $(MV) merged.tmp merged-gssapi-header.h +verify-calling-conventions-gssapi: merged-gssapi-header.h + $(PERL) -w $(top_srcdir)/util/def-check.pl merged-gssapi-header.h $(srcdir)/../gssapi32.def + +# These rules are an attempt to handle several different problems: +# +# Certain files in subdirectories must be made current by the +# recursion step before we can build files in this directory that +# depend on them. Existing but out-of-date versions must not be used. +# +# In a parallel make, nothing should be built more than once. This +# effect can be exaggerated for testing by sticking "sleep 5" into the +# rules for generating the files in subdirectories. For example, in +# between testing for a directory and creating it -- do you then get +# mkdir complaining that the directory exists? Adding the sleep +# command may also exaggerate the build-with-outdated-headers problem, +# by causing the timestamp on the newly generated header to be several +# seconds newer than object files built with its old version, even on +# fast machines where the UNIX filesystem's one-second granularity +# would mask the problem. +# +# We must not cause these files to always be considered newly updated +# when it comes time to build the object files in this directory. +# Otherwise, we wind up recompiling some files every time we run make. + +# This set of rules fails the parallel make case; it can build +# gssapi-include and all-recurse at the same time, and both will +# create include/gssapi and gssapi.h. +#$(BUILDTOP)/include/gssapi/gssapi.h: generic/gssapi.h +# (cd generic && $(MAKE) gssapi-include) +#generic/gssapi.h: generic/gssapi.hin +# (cd generic && $(MAKE) gssapi.h) +#generic/gssapi_err_generic.h: generic/gssapi_err_generic.et +# (cd generic && $(MAKE) gssapi_err_generic.h) +#krb5/gssapi_err_krb5.h: krb5/gssapi_err_krb5.et +# (cd krb5 && $(MAKE) gssapi_err_krb5.h) + +# This version, without the no-op command to run, reportedly caused +# repeated rebuilds in certain cases. With the no-op command, it +# appears to be properly serializing the subdir processing and local +# compiles... so far. +##DOS##!if 0 +$(EXPORTED_HEADERS) generic/gssapi.h krb5/gssapi_err_krb5.h generic/gssapi_err_generic.h krb5/gssapi_krb5.h: all-recurse + : $@ updated by recursion rule +##DOS##!endif + + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/gssapi/README_SAMPLE_APP b/krb5-1.21.3/src/lib/gssapi/README_SAMPLE_APP new file mode 100644 index 00000000..c26bb09a --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/README_SAMPLE_APP @@ -0,0 +1,4 @@ +A sample GSS-API client and server application can be found in the +directory ./appl/gss-sample in this distribution. Read the file +./appl/gss-sample/README for information on how it works and how to +build it. diff --git a/krb5-1.21.3/src/lib/gssapi/deps b/krb5-1.21.3/src/lib/gssapi/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/lib/gssapi/generic/Makefile.in b/krb5-1.21.3/src/lib/gssapi/generic/Makefile.in new file mode 100644 index 00000000..1a95a7d3 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/Makefile.in @@ -0,0 +1,172 @@ +mydir=lib$(S)gssapi$(S)generic +BUILDTOP=$(REL)..$(S)..$(S).. +LOCALINCLUDES = -I. -I$(srcdir) -I$(srcdir)/.. + +##DOS##BUILDTOP = ..\..\.. +##DOS##PREFIXDIR=generic +##DOS##OBJFILE=..\$(OUTPRE)generic.lst + +##DOS##DLL_EXP_TYPE=GSS + +ETSRCS= gssapi_err_generic.c +ETOBJS= $(OUTPRE)gssapi_err_generic.$(OBJEXT) +ETHDRS= gssapi_err_generic.h + +EHDRDIR= $(BUILDTOP)$(S)include$(S)gssapi + +HDRS= $(EHDRDIR)$(S)gssapi.h \ + $(EHDRDIR)$(S)gssapi_generic.h \ + $(EHDRDIR)$(S)gssapi_alloc.h \ + $(EHDRDIR)$(S)gssapi_ext.h + +MK_EHDRDIR=if test -d $(EHDRDIR); then :; else (set -x; mkdir $(EHDRDIR)); fi +##DOS##MK_EHDRDIR=rem + +gssapi-include: $(EHDRDIR)$(S)gssapi.h + +$(EHDRDIR)$(S)gssapi.h: $(EHDRDIR)$(S)timestamp gssapi.h + $(CP) gssapi.h $@ +$(EHDRDIR)$(S)gssapi_generic.h: $(EHDRDIR)$(S)timestamp $(srcdir)$(S)gssapi_generic.h + $(CP) $(srcdir)$(S)gssapi_generic.h $@ +$(EHDRDIR)$(S)gssapi_alloc.h: $(EHDRDIR)$(S)timestamp $(srcdir)$(S)gssapi_alloc.h + $(CP) $(srcdir)$(S)gssapi_alloc.h $@ +$(EHDRDIR)$(S)gssapi_ext.h: $(EHDRDIR)$(S)timestamp $(srcdir)$(S)gssapi_ext.h + $(CP) $(srcdir)$(S)gssapi_ext.h $@ + +$(EHDRDIR)$(S)timestamp: + $(MK_EHDRDIR) + echo timestamp > $(EHDRDIR)$(S)timestamp + +$(OUTPRE)gssapi_err_generic.$(OBJEXT): gssapi_err_generic.c +gssapi_err_generic.h: gssapi_err_generic.et +gssapi_err_generic.c: gssapi_err_generic.et + +##DOS##!if 0 +include_xom=@include_xom@ +##DOS##include_xom=rem +gssapi.h: gssapi.hin + @echo "Creating gssapi.h" ; \ + h=gss$$$$; $(RM) $$h; \ + (echo "/* This is the gssapi.h prologue. */"; \ + $(include_xom) && \ + echo "/* End of gssapi.h prologue. */"&& \ + cat $(srcdir)/gssapi.hin )> $$h && \ + (set -x; $(MV) $$h $@) ; e=$$?; $(RM) $$h; exit $$e +##DOS##!endif +##DOS##gssapi.h: gssapi.hin +##DOS## $(CP) $** $@ + +SRCS = \ + $(srcdir)/disp_com_err_status.c \ + $(srcdir)/disp_major_status.c \ + $(srcdir)/gssapi_generic.c \ + $(srcdir)/oid_ops.c \ + $(srcdir)/rel_buffer.c \ + $(srcdir)/rel_oid_set.c \ + $(srcdir)/util_buffer.c \ + $(srcdir)/util_buffer_set.c \ + $(srcdir)/util_errmap.c \ + $(srcdir)/util_set.c \ + $(srcdir)/util_seqstate.c \ + $(srcdir)/util_token.c \ + gssapi_err_generic.c + +EXTRADEPSRCS = t_seqstate.c + +OBJS = \ + $(OUTPRE)disp_com_err_status.$(OBJEXT) \ + $(OUTPRE)disp_major_status.$(OBJEXT) \ + $(OUTPRE)gssapi_generic.$(OBJEXT) \ + $(OUTPRE)oid_ops.$(OBJEXT) \ + $(OUTPRE)rel_buffer.$(OBJEXT) \ + $(OUTPRE)rel_oid_set.$(OBJEXT) \ + $(OUTPRE)util_buffer.$(OBJEXT) \ + $(OUTPRE)util_buffer_set.$(OBJEXT) \ + $(OUTPRE)util_errmap.$(OBJEXT) \ + $(OUTPRE)util_set.$(OBJEXT) \ + $(OUTPRE)util_seqstate.$(OBJEXT) \ + $(OUTPRE)util_token.$(OBJEXT) \ + $(OUTPRE)gssapi_err_generic.$(OBJEXT) + +STLIBOBJS = \ + disp_com_err_status.o \ + disp_major_status.o \ + gssapi_generic.o \ + oid_ops.o \ + rel_buffer.o \ + rel_oid_set.o \ + util_buffer.o \ + util_buffer_set.o \ + util_errmap.o \ + util_set.o \ + util_seqstate.o \ + util_token.o \ + gssapi_err_generic.o + +EXPORTED_HEADERS= gssapi_generic.h gssapi_ext.h gssapi_alloc.h +EXPORTED_BUILT_HEADERS= gssapi.h + +$(OBJS): $(EXPORTED_HEADERS) $(ETHDRS) + +all-unix: $(EXPORTED_HEADERS) $(ETHDRS) $(HDRS) +all-unix: all-libobjs + +errmap.h: $(top_srcdir)/util/gen.pl $(top_srcdir)/util/t_array.pm \ + $(top_srcdir)/util/t_bimap.pm + $(PERL) -w -I$(top_srcdir)/util $(top_srcdir)/util/gen.pl bimap \ + errmap.h \ + NAME=mecherrmap LEFT=OM_uint32 RIGHT="struct mecherror" \ + LEFTPRINT=print_OM_uint32 RIGHTPRINT=mecherror_print \ + LEFTCMP=cmp_OM_uint32 RIGHTCMP=mecherror_cmp + +maptest.h: $(top_srcdir)/util/gen.pl $(top_srcdir)/util/t_array.pm \ + $(top_srcdir)/util/t_bimap.pm + $(PERL) -w -I$(top_srcdir)/util $(top_srcdir)/util/gen.pl bimap \ + maptest.h \ + NAME=foo LEFT=int RIGHT=elt LEFTPRINT=intprt \ + RIGHTPRINT=eltprt LEFTCMP=intcmp RIGHTCMP=eltcmp +maptest.o: maptest.c maptest.h +maptest: maptest.o + $(CC_LINK) -o maptest maptest.o + +##DOS##LIBOBJS = $(OBJS) + +all-windows: win-create-ehdrdir +all-windows: $(HDRS) + +win-create-ehdrdir: + if not exist $(EHDRDIR)\nul mkdir $(EHDRDIR) + +clean-unix:: clean-libobjs + $(RM) $(ETHDRS) $(ETSRCS) $(HDRS) $(EXPORTED_BUILT_HEADERS) \ + $(EHDRDIR)$(S)timestamp errmap.h maptest.h + $(RM) t_seqstate.o t_seqstate + +clean-windows:: + $(RM) $(HDRS) maptest.h + -if exist $(EHDRDIR)\nul rmdir $(EHDRDIR) + +t_seqstate: t_seqstate.o util_seqstate.o $(SUPPORT_DEPLIB) + $(CC_LINK) $(ALL_CFLAGS) -o $@ t_seqstate.o util_seqstate.o \ + $(SUPPORT_LIB) + +check-unix: t_seqstate + $(RUN_TEST) ./t_seqstate + +generate-files-mac: gssapi.h errmap.h + +# Krb5InstallHeaders($(EXPORTED_HEADERS), $(KRB5_INCDIR)/krb5) +install-headers-unix install: gssapi.h + @set -x; for f in $(EXPORTED_HEADERS) ; \ + do $(INSTALL_DATA) $(srcdir)/$$f \ + $(DESTDIR)$(KRB5_INCDIR)/gssapi/$$f ; \ + done + @set -x; for f in $(EXPORTED_BUILT_HEADERS) ; \ + do $(INSTALL_DATA) $$f \ + $(DESTDIR)$(KRB5_INCDIR)/gssapi/$$f ; \ + done + +depend: $(ETSRCS) $(ETHDRS) $(HDRS) errmap.h maptest.h + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/gssapi/generic/deps b/krb5-1.21.3/src/lib/gssapi/generic/deps new file mode 100644 index 00000000..0f090925 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/deps @@ -0,0 +1,97 @@ +# +# Generated makefile dependencies follow. +# +disp_com_err_status.so disp_com_err_status.po $(OUTPRE)disp_com_err_status.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h disp_com_err_status.c \ + gssapiP_generic.h gssapi_err_generic.h gssapi_ext.h \ + gssapi_generic.h +disp_major_status.so disp_major_status.po $(OUTPRE)disp_major_status.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h disp_major_status.c \ + gssapiP_generic.h gssapi_err_generic.h gssapi_ext.h \ + gssapi_generic.h +gssapi_generic.so gssapi_generic.po $(OUTPRE)gssapi_generic.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h gssapiP_generic.h \ + gssapi_err_generic.h gssapi_ext.h gssapi_generic.c \ + gssapi_generic.h +oid_ops.so oid_ops.po $(OUTPRE)oid_ops.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_generic.h $(COM_ERR_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h gssapiP_generic.h \ + gssapi_err_generic.h gssapi_ext.h gssapi_generic.h \ + oid_ops.c +rel_buffer.so rel_buffer.po $(OUTPRE)rel_buffer.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h gssapiP_generic.h \ + gssapi_err_generic.h gssapi_ext.h gssapi_generic.h \ + rel_buffer.c +rel_oid_set.so rel_oid_set.po $(OUTPRE)rel_oid_set.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h gssapiP_generic.h \ + gssapi_err_generic.h gssapi_ext.h gssapi_generic.h \ + rel_oid_set.c +util_buffer.so util_buffer.po $(OUTPRE)util_buffer.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h gssapiP_generic.h \ + gssapi_err_generic.h gssapi_ext.h gssapi_generic.h \ + util_buffer.c +util_buffer_set.so util_buffer_set.po $(OUTPRE)util_buffer_set.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h gssapiP_generic.h \ + gssapi_err_generic.h gssapi_ext.h gssapi_generic.h \ + util_buffer_set.c +util_errmap.so util_errmap.po $(OUTPRE)util_errmap.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ + errmap.h gssapiP_generic.h gssapi_err_generic.h gssapi_ext.h \ + gssapi_generic.h util_errmap.c +util_set.so util_set.po $(OUTPRE)util_set.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h gssapiP_generic.h \ + gssapi_err_generic.h gssapi_ext.h gssapi_generic.h \ + util_set.c +util_seqstate.so util_seqstate.po $(OUTPRE)util_seqstate.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h gssapiP_generic.h \ + gssapi_err_generic.h gssapi_ext.h gssapi_generic.h \ + util_seqstate.c +util_token.so util_token.po $(OUTPRE)util_token.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-der.h \ + $(top_srcdir)/include/k5-input.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h gssapiP_generic.h \ + gssapi_err_generic.h gssapi_ext.h gssapi_generic.h \ + util_token.c +gssapi_err_generic.so gssapi_err_generic.po $(OUTPRE)gssapi_err_generic.$(OBJEXT): \ + $(COM_ERR_DEPS) gssapi_err_generic.c +t_seqstate.so t_seqstate.po $(OUTPRE)t_seqstate.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h gssapiP_generic.h \ + gssapi_err_generic.h gssapi_ext.h gssapi_generic.h \ + t_seqstate.c diff --git a/krb5-1.21.3/src/lib/gssapi/generic/disp_com_err_status.c b/krb5-1.21.3/src/lib/gssapi/generic/disp_com_err_status.c new file mode 100644 index 00000000..bc416107 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/disp_com_err_status.c @@ -0,0 +1,62 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * $Id$ + */ + +#include "gssapiP_generic.h" +#include "com_err.h" + +/* XXXX internationalization!! */ + +/**/ + +static const char * const no_error = "No error"; + +/**/ + +/* if status_type == GSS_C_GSS_CODE, return up to three error messages, + for routine errors, call error, and status, in that order. + message_context == 0 : print the routine error + message_context == 1 : print the calling error + message_context > 2 : print supplementary info bit (message_context-2) + if status_type == GSS_C_MECH_CODE, return the output from error_message() +*/ + +OM_uint32 +g_display_com_err_status(OM_uint32 *minor_status, OM_uint32 status_value, + gss_buffer_t status_string) +{ + status_string->length = 0; + status_string->value = NULL; + + if (! g_make_string_buffer(((status_value == 0)?no_error: + error_message(status_value)), + status_string)) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + *minor_status = 0; + return(GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/generic/disp_major_status.c b/krb5-1.21.3/src/lib/gssapi/generic/disp_major_status.c new file mode 100644 index 00000000..848af8fa --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/disp_major_status.c @@ -0,0 +1,301 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "gssapiP_generic.h" +#include +#include + +/* + * $Id$ + */ + +/* This code has knowledge of the min and max errors of each type + within the gssapi major status */ + +#define GSS_ERROR_STR(value, array, select, min, max, num) \ + (((select(value) < (min)) || (select(value) > (max))) ? NULL : \ + _((array)[num(value)])) + +/**/ + +static const char * const calling_error_string[] = { + NULL, + N_("A required input parameter could not be read"), + N_("A required input parameter could not be written"), + N_("A parameter was malformed"), +}; + +static const char * const calling_error = N_("calling error"); + +#define GSS_CALLING_ERROR_STR(x) \ + GSS_ERROR_STR((x), calling_error_string, GSS_CALLING_ERROR, \ + GSS_S_CALL_INACCESSIBLE_READ, GSS_S_CALL_BAD_STRUCTURE, \ + GSS_CALLING_ERROR_FIELD) + +/**/ + +static const char * const routine_error_string[] = { + NULL, + N_("An unsupported mechanism was requested"), + N_("An invalid name was supplied"), + N_("A supplied name was of an unsupported type"), + N_("Incorrect channel bindings were supplied"), + N_("An invalid status code was supplied"), + N_("A token had an invalid signature"), + N_("No credentials were supplied"), + N_("No context has been established"), + N_("A token was invalid"), + N_("A credential was invalid"), + N_("The referenced credentials have expired"), + N_("The context has expired"), + N_("Miscellaneous failure"), + N_("The quality-of-protection requested could not be provided"), + N_("The operation is forbidden by the local security policy"), + N_("The operation or option is not available"), +}; + +static const char * const routine_error = N_("routine error"); + +#define GSS_ROUTINE_ERROR_STR(x) \ + GSS_ERROR_STR((x), routine_error_string, GSS_ROUTINE_ERROR, \ + GSS_S_BAD_MECH, GSS_S_FAILURE, \ + GSS_ROUTINE_ERROR_FIELD) + +/**/ + +/* this becomes overly gross after about 4 strings */ + +static const char * const sinfo_string[] = { + N_("The routine must be called again to complete its function"), + N_("The token was a duplicate of an earlier token"), + N_("The token's validity period has expired"), + N_("A later token has already been processed"), +}; + +static const char * const sinfo_code = N_("supplementary info code"); + +#define LSBGET(x) ((((x)^((x)-1))+1)>>1) +#define LSBMASK(n) ((1<<(n))^((1<<(n))-1)) + +#define GSS_SINFO_STR(x) \ + ((((1<<(x)) < GSS_S_CONTINUE_NEEDED) || ((1<<(x)) > GSS_S_UNSEQ_TOKEN)) ? \ + /**/NULL:sinfo_string[(x)]) + +/**/ + +static const char * const no_error = N_("No error"); +static const char * const unknown_error = N_("Unknown %s (field = %d)"); + +/**/ + +static int +display_unknown(const char *kind, OM_uint32 value, gss_buffer_t buffer) +{ + char *str; + + if (asprintf(&str, _(unknown_error), kind, value) < 0) + return(0); + + buffer->length = strlen(str); + buffer->value = str; + + return(1); +} + +/* code should be set to the calling error field */ + +static OM_uint32 +display_calling(OM_uint32 *minor_status, OM_uint32 code, + gss_buffer_t status_string) +{ + const char *str; + + if ((str = GSS_CALLING_ERROR_STR(code))) { + if (! g_make_string_buffer(str, status_string)) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + } else { + if (! display_unknown(_(calling_error), GSS_CALLING_ERROR_FIELD(code), + status_string)) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + } + *minor_status = 0; + return(GSS_S_COMPLETE); +} + +/* code should be set to the routine error field */ + +static OM_uint32 +display_routine(OM_uint32 *minor_status, OM_uint32 code, + gss_buffer_t status_string) +{ + const char *str; + + if ((str = GSS_ROUTINE_ERROR_STR(code))) { + if (! g_make_string_buffer(str, status_string)) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + } else { + if (! display_unknown(_(routine_error), GSS_ROUTINE_ERROR_FIELD(code), + status_string)) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + } + *minor_status = 0; + return(GSS_S_COMPLETE); +} + +/* code should be set to the bit offset (log_2) of a supplementary info bit */ + +static OM_uint32 +display_bit(OM_uint32 *minor_status, OM_uint32 code, + gss_buffer_t status_string) +{ + const char *str; + + if ((str = GSS_SINFO_STR(code))) { + if (! g_make_string_buffer(str, status_string)) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + } else { + if (! display_unknown(_(sinfo_code), 1< 2 : print supplementary info bit (message_context-2) +*/ + +OM_uint32 +g_display_major_status(OM_uint32 *minor_status, OM_uint32 status_value, + OM_uint32 *message_context, gss_buffer_t status_string) +{ + OM_uint32 ret, tmp; + int bit; + + /*** deal with no error at all specially */ + + if (status_value == 0) { + if (! g_make_string_buffer(no_error, status_string)) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + *message_context = 0; + *minor_status = 0; + return(GSS_S_COMPLETE); + } + + /*** do routine error */ + + if (*message_context == 0) { + if ((tmp = GSS_ROUTINE_ERROR(status_value))) { + status_value -= tmp; + if ((ret = display_routine(minor_status, tmp, status_string))) + return(ret); + *minor_status = 0; + if (status_value) { + (*message_context)++; + return(GSS_S_COMPLETE); + } else { + *message_context = 0; + return(GSS_S_COMPLETE); + } + } else { + (*message_context)++; + } + } else { + status_value -= GSS_ROUTINE_ERROR(status_value); + } + + /*** do calling error */ + + if (*message_context == 1) { + if ((tmp = GSS_CALLING_ERROR(status_value))) { + status_value -= tmp; + if ((ret = display_calling(minor_status, tmp, status_string))) + return(ret); + *minor_status = 0; + if (status_value) { + (*message_context)++; + return(GSS_S_COMPLETE); + } else { + *message_context = 0; + return(GSS_S_COMPLETE); + } + } else { + (*message_context)++; + } + } else { + status_value -= GSS_CALLING_ERROR(status_value); + } + + /*** do sinfo bits (*message_context == 2 + number of bits done) */ + + tmp = GSS_SUPPLEMENTARY_INFO_FIELD(status_value); + /* mask off the bits which have been done */ + if (*message_context > 2) { + tmp &= ~LSBMASK(*message_context-3); + status_value &= ~LSBMASK(*message_context-3); + } + + if (!tmp) { + /* bogon input - there should be something left */ + *minor_status = (OM_uint32) G_BAD_MSG_CTX; + return(GSS_S_FAILURE); + } + + /* compute the bit offset */ + /*SUPPRESS 570*/ + for (bit=0; (((OM_uint32) 1)< +# if TARGET_RT_MAC_CFM +# error "Use KfM 4.0 SDK headers for CFM compilation." +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)) +#pragma pack(push,2) +#endif + +#if defined(_MSDOS) || defined(_WIN32) +#include +#endif + +#ifndef KRB5_CALLCONV +#define KRB5_CALLCONV +#define KRB5_CALLCONV_C +#endif + +#include + +/* + * First, include stddef.h to get size_t defined. + */ +#include + +/* + * POSIX says that sys/types.h is where size_t is defined. + */ +#include + +/* + * $Id$ + */ + +/* + * First, define the three platform-dependent pointer types. + */ + +struct gss_name_struct; +typedef struct gss_name_struct * gss_name_t; + +struct gss_cred_id_struct; +typedef struct gss_cred_id_struct * gss_cred_id_t; + +struct gss_ctx_id_struct; +typedef struct gss_ctx_id_struct * gss_ctx_id_t; + +/* + * The following type must be defined as the smallest natural unsigned integer + * supported by the platform that has at least 32 bits of precision. + */ +typedef uint32_t gss_uint32; +typedef int32_t gss_int32; + +#ifdef OM_STRING +/* + * We have included the xom.h header file. Use the definition for + * OM_object identifier. + */ +typedef OM_object_identifier gss_OID_desc, *gss_OID; +#else /* OM_STRING */ +/* + * We can't use X/Open definitions, so roll our own. + */ +typedef gss_uint32 OM_uint32; + +typedef struct gss_OID_desc_struct { + OM_uint32 length; + void *elements; +} gss_OID_desc, *gss_OID; +#endif /* OM_STRING */ + +typedef struct gss_OID_set_desc_struct { + size_t count; + gss_OID elements; +} gss_OID_set_desc, *gss_OID_set; + +typedef struct gss_buffer_desc_struct { + size_t length; + void *value; +} gss_buffer_desc, *gss_buffer_t; + +typedef struct gss_channel_bindings_struct { + OM_uint32 initiator_addrtype; + gss_buffer_desc initiator_address; + OM_uint32 acceptor_addrtype; + gss_buffer_desc acceptor_address; + gss_buffer_desc application_data; +} *gss_channel_bindings_t; + +/* + * For now, define a QOP-type as an OM_uint32 (pending resolution of ongoing + * discussions). + */ +typedef OM_uint32 gss_qop_t; +typedef int gss_cred_usage_t; + +/* + * Flag bits for context-level services. + */ +#define GSS_C_DELEG_FLAG 1 +#define GSS_C_MUTUAL_FLAG 2 +#define GSS_C_REPLAY_FLAG 4 +#define GSS_C_SEQUENCE_FLAG 8 +#define GSS_C_CONF_FLAG 16 +#define GSS_C_INTEG_FLAG 32 +#define GSS_C_ANON_FLAG 64 +#define GSS_C_PROT_READY_FLAG 128 +#define GSS_C_TRANS_FLAG 256 +#define GSS_C_DELEG_POLICY_FLAG 32768 + +/* + * Credential usage options + */ +#define GSS_C_BOTH 0 +#define GSS_C_INITIATE 1 +#define GSS_C_ACCEPT 2 + +/* + * Status code types for gss_display_status + */ +#define GSS_C_GSS_CODE 1 +#define GSS_C_MECH_CODE 2 + +/* + * The constant definitions for channel-bindings address families + */ +#define GSS_C_AF_UNSPEC 0 +#define GSS_C_AF_LOCAL 1 +#define GSS_C_AF_INET 2 +#define GSS_C_AF_IMPLINK 3 +#define GSS_C_AF_PUP 4 +#define GSS_C_AF_CHAOS 5 +#define GSS_C_AF_NS 6 +#define GSS_C_AF_NBS 7 +#define GSS_C_AF_ECMA 8 +#define GSS_C_AF_DATAKIT 9 +#define GSS_C_AF_CCITT 10 +#define GSS_C_AF_SNA 11 +#define GSS_C_AF_DECnet 12 +#define GSS_C_AF_DLI 13 +#define GSS_C_AF_LAT 14 +#define GSS_C_AF_HYLINK 15 +#define GSS_C_AF_APPLETALK 16 +#define GSS_C_AF_BSC 17 +#define GSS_C_AF_DSS 18 +#define GSS_C_AF_OSI 19 +#define GSS_C_AF_NETBIOS 20 +#define GSS_C_AF_X25 21 + +#define GSS_C_AF_NULLADDR 255 + +/* + * Various Null values. + */ +#define GSS_C_NO_NAME ((gss_name_t) 0) +#define GSS_C_NO_BUFFER ((gss_buffer_t) 0) +#define GSS_C_NO_OID ((gss_OID) 0) +#define GSS_C_NO_OID_SET ((gss_OID_set) 0) +#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0) +#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0) +#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0) +#define GSS_C_EMPTY_BUFFER {0, NULL} + +/* + * Some alternate names for a couple of the above values. These are defined + * for V1 compatibility. + */ +#define GSS_C_NULL_OID GSS_C_NO_OID +#define GSS_C_NULL_OID_SET GSS_C_NO_OID_SET + +/* + * Define the default Quality of Protection for per-message services. Note + * that an implementation that offers multiple levels of QOP may either reserve + * a value (for example zero, as assumed here) to mean "default protection", or + * alternatively may simply equate GSS_C_QOP_DEFAULT to a specific explicit + * QOP value. However a value of 0 should always be interpreted by a GSSAPI + * implementation as a request for the default protection level. + */ +#define GSS_C_QOP_DEFAULT 0 + +/* + * Expiration time of 2^32-1 seconds means infinite lifetime for a + * credential or security context + */ +#define GSS_C_INDEFINITE ((OM_uint32) 0xfffffffful) + + +/* Major status codes */ + +#define GSS_S_COMPLETE 0 + +/* + * Some "helper" definitions to make the status code macros obvious. + */ +#define GSS_C_CALLING_ERROR_OFFSET 24 +#define GSS_C_ROUTINE_ERROR_OFFSET 16 +#define GSS_C_SUPPLEMENTARY_OFFSET 0 +#define GSS_C_CALLING_ERROR_MASK ((OM_uint32) 0377ul) +#define GSS_C_ROUTINE_ERROR_MASK ((OM_uint32) 0377ul) +#define GSS_C_SUPPLEMENTARY_MASK ((OM_uint32) 0177777ul) + +/* + * The macros that test status codes for error conditions. Note that the + * GSS_ERROR() macro has changed slightly from the V1 GSSAPI so that it now + * evaluates its argument only once. + */ +#define GSS_CALLING_ERROR(x) \ + ((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET)) +#define GSS_ROUTINE_ERROR(x) \ + ((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)) +#define GSS_SUPPLEMENTARY_INFO(x) \ + ((x) & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET)) +#define GSS_ERROR(x) \ + ((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \ + (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))) + +/* + * Now the actual status code definitions + */ + +/* + * Calling errors: + */ +#define GSS_S_CALL_INACCESSIBLE_READ \ + (((OM_uint32) 1ul) << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_INACCESSIBLE_WRITE \ + (((OM_uint32) 2ul) << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_BAD_STRUCTURE \ + (((OM_uint32) 3ul) << GSS_C_CALLING_ERROR_OFFSET) + +/* + * Routine errors: + */ +#define GSS_S_BAD_MECH (((OM_uint32) 1ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAME (((OM_uint32) 2ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAMETYPE (((OM_uint32) 3ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_BINDINGS (((OM_uint32) 4ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_STATUS (((OM_uint32) 5ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_SIG (((OM_uint32) 6ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_MIC GSS_S_BAD_SIG +#define GSS_S_NO_CRED (((OM_uint32) 7ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NO_CONTEXT (((OM_uint32) 8ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_TOKEN (((OM_uint32) 9ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_CREDENTIAL \ + (((OM_uint32) 10ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CREDENTIALS_EXPIRED \ + (((OM_uint32) 11ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CONTEXT_EXPIRED \ + (((OM_uint32) 12ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_FAILURE (((OM_uint32) 13ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_QOP (((OM_uint32) 14ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAUTHORIZED (((OM_uint32) 15ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAVAILABLE (((OM_uint32) 16ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DUPLICATE_ELEMENT \ + (((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NAME_NOT_MN \ + (((OM_uint32) 18ul) << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_MECH_ATTR \ + (((OM_uint32) 19ul) << GSS_C_ROUTINE_ERROR_OFFSET) + +/* + * Supplementary info bits: + */ +#define GSS_S_CONTINUE_NEEDED (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 0)) +#define GSS_S_DUPLICATE_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 1)) +#define GSS_S_OLD_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 2)) +#define GSS_S_UNSEQ_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 3)) +#define GSS_S_GAP_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4)) + + +/* + * Finally, function prototypes for the GSSAPI routines. + */ + +#if defined (_WIN32) && defined (_MSC_VER) +# ifdef GSS_DLL_FILE +# define GSS_DLLIMP __declspec(dllexport) +# else +# define GSS_DLLIMP __declspec(dllimport) +# endif +#else +# define GSS_DLLIMP +#endif + +/* Reserved static storage for GSS_oids. Comments are quotes from RFC 2744. + * + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) user_name(1)}. The constant + * GSS_C_NT_USER_NAME should be initialized to point + * to that gss_OID_desc. + */ +GSS_DLLIMP extern gss_OID GSS_C_NT_USER_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. + * The constant GSS_C_NT_MACHINE_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ +GSS_DLLIMP extern gss_OID GSS_C_NT_MACHINE_UID_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) string_uid_name(3)}. + * The constant GSS_C_NT_STRING_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ +GSS_DLLIMP extern gss_OID GSS_C_NT_STRING_UID_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x02"}, + * corresponding to an object-identifier value of + * {iso(1) org(3) dod(6) internet(1) security(5) + * nametypes(6) gss-host-based-services(2)). The constant + * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point + * to that gss_OID_desc. This is a deprecated OID value, and + * implementations wishing to support hostbased-service names + * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID, + * defined below, to identify such names; + * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym + * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input + * parameter, but should not be emitted by GSS-API + * implementations + */ +GSS_DLLIMP extern gss_OID GSS_C_NT_HOSTBASED_SERVICE_X; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x04"}, corresponding to an + * object-identifier value of {iso(1) member-body(2) + * Unites States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) service_name(4)}. The constant + * GSS_C_NT_HOSTBASED_SERVICE should be initialized + * to point to that gss_OID_desc. + */ +GSS_DLLIMP extern gss_OID GSS_C_NT_HOSTBASED_SERVICE; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\01\x05\x06\x03"}, + * corresponding to an object identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 3(gss-anonymous-name)}. The constant + * and GSS_C_NT_ANONYMOUS should be initialized to point + * to that gss_OID_desc. + */ +GSS_DLLIMP extern gss_OID GSS_C_NT_ANONYMOUS; + + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 4(gss-api-exported-name)}. The constant + * GSS_C_NT_EXPORT_NAME should be initialized to point + * to that gss_OID_desc. + */ +GSS_DLLIMP extern gss_OID GSS_C_NT_EXPORT_NAME; + +/* Function Prototypes */ + +OM_uint32 KRB5_CALLCONV +gss_acquire_cred( + OM_uint32 *, /* minor_status */ + gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *); /* time_rec */ + +OM_uint32 KRB5_CALLCONV +gss_release_cred( + OM_uint32 *, /* minor_status */ + gss_cred_id_t *); /* cred_handle */ + +OM_uint32 KRB5_CALLCONV +gss_init_sec_context( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* claimant_cred_handle */ + gss_ctx_id_t *, /* context_handle */ + gss_name_t, /* target_name */ + gss_OID, /* mech_type (used to be const) */ + OM_uint32, /* req_flags */ + OM_uint32, /* time_req */ + gss_channel_bindings_t, /* input_chan_bindings */ + gss_buffer_t, /* input_token */ + gss_OID *, /* actual_mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32 *, /* ret_flags */ + OM_uint32 *); /* time_rec */ + +OM_uint32 KRB5_CALLCONV +gss_accept_sec_context( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + gss_cred_id_t, /* acceptor_cred_handle */ + gss_buffer_t, /* input_token_buffer */ + gss_channel_bindings_t, /* input_chan_bindings */ + gss_name_t *, /* src_name */ + gss_OID *, /* mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32 *, /* ret_flags */ + OM_uint32 *, /* time_rec */ + gss_cred_id_t *); /* delegated_cred_handle */ + +OM_uint32 KRB5_CALLCONV +gss_process_context_token( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t); /* token_buffer */ + + +OM_uint32 KRB5_CALLCONV +gss_delete_sec_context( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + gss_buffer_t); /* output_token */ + + +OM_uint32 KRB5_CALLCONV +gss_context_time( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + OM_uint32 *); /* time_rec */ + + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_get_mic( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t, /* qop_req */ + gss_buffer_t, /* message_buffer */ + gss_buffer_t); /* message_token */ + + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_verify_mic(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t, /* message_buffer */ + gss_buffer_t, /* message_token */ + gss_qop_t * /* qop_state */ +); + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_wrap( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + gss_buffer_t, /* input_message_buffer */ + int *, /* conf_state */ + gss_buffer_t); /* output_message_buffer */ + + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_unwrap( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t, /* input_message_buffer */ + gss_buffer_t, /* output_message_buffer */ + int *, /* conf_state */ + gss_qop_t *); /* qop_state */ + + +OM_uint32 KRB5_CALLCONV +gss_display_status( + OM_uint32 *, /* minor_status */ + OM_uint32, /* status_value */ + int, /* status_type */ + gss_OID, /* mech_type (used to be const) */ + OM_uint32 *, /* message_context */ + gss_buffer_t); /* status_string */ + + +OM_uint32 KRB5_CALLCONV +gss_indicate_mechs( + OM_uint32 *, /* minor_status */ + gss_OID_set *); /* mech_set */ + + +OM_uint32 KRB5_CALLCONV +gss_compare_name( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name1 */ + gss_name_t, /* name2 */ + int *); /* name_equal */ + + +OM_uint32 KRB5_CALLCONV +gss_display_name( + OM_uint32 *, /* minor_status */ + gss_name_t, /* input_name */ + gss_buffer_t, /* output_name_buffer */ + gss_OID *); /* output_name_type */ + + +OM_uint32 KRB5_CALLCONV +gss_import_name( + OM_uint32 *, /* minor_status */ + gss_buffer_t, /* input_name_buffer */ + gss_OID, /* input_name_type(used to be const) */ + gss_name_t *); /* output_name */ + +OM_uint32 KRB5_CALLCONV +gss_release_name( + OM_uint32 *, /* minor_status */ + gss_name_t *); /* input_name */ + +OM_uint32 KRB5_CALLCONV +gss_release_buffer( + OM_uint32 *, /* minor_status */ + gss_buffer_t); /* buffer */ + +OM_uint32 KRB5_CALLCONV +gss_release_oid_set( + OM_uint32 *, /* minor_status */ + gss_OID_set *); /* set */ + +OM_uint32 KRB5_CALLCONV +gss_inquire_cred( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* cred_handle */ + gss_name_t *, /* name */ + OM_uint32 *, /* lifetime */ + gss_cred_usage_t *, /* cred_usage */ + gss_OID_set *); /* mechanisms */ + +/* Last argument new for V2 */ +OM_uint32 KRB5_CALLCONV +gss_inquire_context( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_name_t *, /* src_name */ + gss_name_t *, /* targ_name */ + OM_uint32 *, /* lifetime_rec */ + gss_OID *, /* mech_type */ + OM_uint32 *, /* ctx_flags */ + int *, /* locally_initiated */ + int *); /* open */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_wrap_size_limit( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + OM_uint32, /* req_output_size */ + OM_uint32 *); /* max_input_size */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_import_name_object( + OM_uint32 *, /* minor_status */ + void *, /* input_name */ + gss_OID, /* input_name_type */ + gss_name_t *); /* output_name */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_export_name_object( + OM_uint32 *, /* minor_status */ + gss_name_t, /* input_name */ + gss_OID, /* desired_name_type */ + void **); /* output_name */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_add_cred( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* input_cred_handle */ + gss_name_t, /* desired_name */ + gss_OID, /* desired_mech */ + gss_cred_usage_t, /* cred_usage */ + OM_uint32, /* initiator_time_req */ + OM_uint32, /* acceptor_time_req */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *, /* initiator_time_rec */ + OM_uint32 *); /* acceptor_time_rec */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_inquire_cred_by_mech( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* cred_handle */ + gss_OID, /* mech_type */ + gss_name_t *, /* name */ + OM_uint32 *, /* initiator_lifetime */ + OM_uint32 *, /* acceptor_lifetime */ + gss_cred_usage_t *); /* cred_usage */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_export_sec_context( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + gss_buffer_t); /* interprocess_token */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_import_sec_context( + OM_uint32 *, /* minor_status */ + gss_buffer_t, /* interprocess_token */ + gss_ctx_id_t *); /* context_handle */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_release_oid( + OM_uint32 *, /* minor_status */ + gss_OID *); /* oid */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_create_empty_oid_set( + OM_uint32 *, /* minor_status */ + gss_OID_set *); /* oid_set */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_add_oid_set_member( + OM_uint32 *, /* minor_status */ + gss_OID, /* member_oid */ + gss_OID_set *); /* oid_set */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_test_oid_set_member( + OM_uint32 *, /* minor_status */ + gss_OID, /* member */ + gss_OID_set, /* set */ + int *); /* present */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_str_to_oid( + OM_uint32 *, /* minor_status */ + gss_buffer_t, /* oid_str */ + gss_OID *); /* oid */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_oid_to_str( + OM_uint32 *, /* minor_status */ + gss_OID, /* oid */ + gss_buffer_t); /* oid_str */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_inquire_names_for_mech( + OM_uint32 *, /* minor_status */ + gss_OID, /* mechanism */ + gss_OID_set *); /* name_types */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_inquire_mechs_for_name( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* input_name */ + gss_OID_set *); /* mech_types */ + +/* + * The following routines are obsolete variants of gss_get_mic, gss_wrap, + * gss_verify_mic and gss_unwrap. They should be provided by GSSAPI V2 + * implementations for backwards compatibility with V1 applications. Distinct + * entrypoints (as opposed to #defines) should be provided, to allow GSSAPI + * V1 applications to link against GSSAPI V2 implementations. + */ +OM_uint32 KRB5_CALLCONV +gss_sign( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* qop_req */ + gss_buffer_t, /* message_buffer */ + gss_buffer_t); /* message_token */ + +OM_uint32 KRB5_CALLCONV +gss_verify( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t, /* message_buffer */ + gss_buffer_t, /* token_buffer */ + int *); /* qop_state */ + +OM_uint32 KRB5_CALLCONV +gss_seal( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + int, /* qop_req */ + gss_buffer_t, /* input_message_buffer */ + int *, /* conf_state */ + gss_buffer_t); /* output_message_buffer */ + +OM_uint32 KRB5_CALLCONV +gss_unseal( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t, /* input_message_buffer */ + gss_buffer_t, /* output_message_buffer */ + int *, /* conf_state */ + int *); /* qop_state */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_export_name( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* input_name */ + gss_buffer_t); /* exported_name */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_duplicate_name( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* input_name */ + gss_name_t *); /* dest_name */ + +/* New for V2 */ +OM_uint32 KRB5_CALLCONV +gss_canonicalize_name( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* input_name */ + const gss_OID, /* mech_type */ + gss_name_t *); /* output_name */ + +/* RFC 4401 */ + +#define GSS_C_PRF_KEY_FULL 0 +#define GSS_C_PRF_KEY_PARTIAL 1 + +OM_uint32 KRB5_CALLCONV +gss_pseudo_random( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context */ + int, /* prf_key */ + const gss_buffer_t, /* prf_in */ + ssize_t, /* desired_output_len */ + gss_buffer_t); /* prf_out */ + +OM_uint32 KRB5_CALLCONV +gss_store_cred( + OM_uint32 *, /* minor_status */ + const gss_cred_id_t,/* input_cred_handle */ + gss_cred_usage_t, /* input_usage */ + const gss_OID, /* desired_mech */ + OM_uint32, /* overwrite_cred */ + OM_uint32, /* default_cred */ + gss_OID_set *, /* elements_stored */ + gss_cred_usage_t *);/* cred_usage_stored */ + +OM_uint32 KRB5_CALLCONV +gss_set_neg_mechs( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* cred_handle */ + const gss_OID_set); /* mech_set */ + +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)) +#pragma pack(pop) +#endif + +#ifdef __cplusplus +} +#endif + +/* XXXX these are not part of the GSSAPI C bindings! (but should be) */ + +#define GSS_CALLING_ERROR_FIELD(x) \ + (((x) >> GSS_C_CALLING_ERROR_OFFSET) & GSS_C_CALLING_ERROR_MASK) +#define GSS_ROUTINE_ERROR_FIELD(x) \ + (((x) >> GSS_C_ROUTINE_ERROR_OFFSET) & GSS_C_ROUTINE_ERROR_MASK) +#define GSS_SUPPLEMENTARY_INFO_FIELD(x) \ + (((x) >> GSS_C_SUPPLEMENTARY_OFFSET) & GSS_C_SUPPLEMENTARY_MASK) + +/* XXXX This is a necessary evil until the spec is fixed */ +#define GSS_S_CRED_UNAVAIL GSS_S_FAILURE + +/* + * RFC 5587 + */ +typedef const gss_buffer_desc *gss_const_buffer_t; +typedef const struct gss_channel_bindings_struct *gss_const_channel_bindings_t; +typedef const struct gss_ctx_id_struct *gss_const_ctx_id_t; +typedef const struct gss_cred_id_struct *gss_const_cred_id_t; +typedef const struct gss_name_struct *gss_const_name_t; +typedef const gss_OID_desc *gss_const_OID; +typedef const gss_OID_set_desc *gss_const_OID_set; + +OM_uint32 KRB5_CALLCONV +gss_indicate_mechs_by_attrs( + OM_uint32 *, /* minor_status */ + gss_const_OID_set, /* desired_mech_attrs */ + gss_const_OID_set, /* except_mech_attrs */ + gss_const_OID_set, /* critical_mech_attrs */ + gss_OID_set *); /* mechs */ + +OM_uint32 KRB5_CALLCONV +gss_inquire_attrs_for_mech( + OM_uint32 *, /* minor_status */ + gss_const_OID, /* mech */ + gss_OID_set *, /* mech_attrs */ + gss_OID_set *); /* known_mech_attrs */ + +OM_uint32 KRB5_CALLCONV +gss_display_mech_attr( + OM_uint32 *, /* minor_status */ + gss_const_OID, /* mech_attr */ + gss_buffer_t, /* name */ + gss_buffer_t, /* short_desc */ + gss_buffer_t); /* long_desc */ + +GSS_DLLIMP extern gss_const_OID GSS_C_MA_MECH_CONCRETE; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_MECH_PSEUDO; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_MECH_COMPOSITE; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_MECH_NEGO; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_MECH_GLUE; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_NOT_MECH; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_DEPRECATED; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_NOT_DFLT_MECH; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_ITOK_FRAMED; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_AUTH_INIT; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_AUTH_TARG; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_AUTH_INIT_INIT; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_AUTH_TARG_INIT; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_AUTH_INIT_ANON; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_AUTH_TARG_ANON; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_DELEG_CRED; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_INTEG_PROT; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_CONF_PROT; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_MIC; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_WRAP; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_PROT_READY; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_REPLAY_DET; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_OOS_DET; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_CBINDINGS; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_PFS; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_COMPRESS; +GSS_DLLIMP extern gss_const_OID GSS_C_MA_CTX_TRANS; + +/* + * RFC 5801 + */ +OM_uint32 KRB5_CALLCONV +gss_inquire_saslname_for_mech( + OM_uint32 *, /* minor_status */ + const gss_OID, /* desired_mech */ + gss_buffer_t, /* sasl_mech_name */ + gss_buffer_t, /* mech_name */ + gss_buffer_t /* mech_description */ +); + +OM_uint32 KRB5_CALLCONV +gss_inquire_mech_for_saslname( + OM_uint32 *, /* minor_status */ + const gss_buffer_t, /* sasl_mech_name */ + gss_OID * /* mech_type */ +); + +#endif /* _GSSAPI_H_ */ diff --git a/krb5-1.21.3/src/lib/gssapi/generic/gssapiP_generic.h b/krb5-1.21.3/src/lib/gssapi/generic/gssapiP_generic.h new file mode 100644 index 00000000..3c6bfa53 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/gssapiP_generic.h @@ -0,0 +1,298 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _GSSAPIP_GENERIC_H_ +#define _GSSAPIP_GENERIC_H_ + +/* + * $Id$ + */ + +#if defined(_WIN32) +#include "k5-int.h" +#else +#include "autoconf.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#endif + +#include "k5-thread.h" + +#include "gssapi_generic.h" +#include "gssapi_ext.h" +#include +#include "gssapi_err_generic.h" +#include + +#include "k5-platform.h" +#include "k5-buf.h" + +/** helper macros **/ + +#define g_OID_equal(o1, o2) \ + (((o1)->length == (o2)->length) && \ + (memcmp((o1)->elements, (o2)->elements, (o1)->length) == 0)) + +/** malloc wrappers; these may actually do something later */ + +#define xmalloc(n) malloc(n) +#define xrealloc(p,n) realloc(p,n) +#ifdef xfree +#undef xfree +#endif +#define xfree(p) free(p) + +/** helper functions **/ + +/* hide names from applications, especially glib applications */ +#define g_set_init gssint_g_set_init +#define g_set_destroy gssint_g_set_destroy +#define g_set_entry_add gssint_g_set_entry_add +#define g_set_entry_delete gssint_g_set_entry_delete +#define g_set_entry_get gssint_g_set_entry_get +#define g_make_string_buffer gssint_g_make_string_buffer +#define g_token_size gssint_g_token_size +#define g_make_token_header gssint_g_make_token_header +#define g_verify_token_header gssint_g_verify_token_header +#define g_display_major_status gssint_g_display_major_status +#define g_display_com_err_status gssint_g_display_com_err_status +#define g_seqstate_init gssint_g_seqstate_init +#define g_seqstate_check gssint_g_seqstate_check +#define g_seqstate_free gssint_g_seqstate_free +#define g_seqstate_size gssint_g_seqstate_size +#define g_seqstate_externalize gssint_g_seqstate_externalize +#define g_seqstate_internalize gssint_g_seqstate_internalize +#define g_canonicalize_host gssint_g_canonicalize_host +#define g_local_host_name gssint_g_local_host_name +#define g_strdup gssint_g_strdup + +typedef struct _g_set_elt *g_set_elt; +typedef struct { + k5_mutex_t mutex; + void *data; +} g_set; +#define G_SET_INIT { K5_MUTEX_PARTIAL_INITIALIZER, 0 } + +typedef struct g_seqnum_state_st *g_seqnum_state; + +int g_set_init (g_set_elt *s); +int g_set_destroy (g_set_elt *s); +int g_set_entry_add (g_set_elt *s, void *key, void *value); +int g_set_entry_delete (g_set_elt *s, void *key); +int g_set_entry_get (g_set_elt *s, void *key, void **value); + +int g_save_name (g_set *vdb, gss_name_t name); +int g_save_cred_id (g_set *vdb, gss_cred_id_t cred); +int g_save_ctx_id (g_set *vdb, gss_ctx_id_t ctx); +int g_save_lucidctx_id (g_set *vdb, void *lctx); + +int g_validate_name (g_set *vdb, gss_name_t name); +int g_validate_cred_id (g_set *vdb, gss_cred_id_t cred); +int g_validate_ctx_id (g_set *vdb, gss_ctx_id_t ctx); +int g_validate_lucidctx_id (g_set *vdb, void *lctx); + +int g_delete_name (g_set *vdb, gss_name_t name); +int g_delete_cred_id (g_set *vdb, gss_cred_id_t cred); +int g_delete_ctx_id (g_set *vdb, gss_ctx_id_t ctx); +int g_delete_lucidctx_id (g_set *vdb, void *lctx); + +int g_make_string_buffer (const char *str, gss_buffer_t buffer); + +unsigned int g_token_size (const gss_OID_desc * mech, unsigned int body_size); + +void g_make_token_header (struct k5buf *buf, const gss_OID_desc *mech, + size_t body_size, int tok_type); + +/* flags for g_verify_token_header() */ +#define G_VFY_TOKEN_HDR_WRAPPER_REQUIRED 0x01 + +gss_int32 g_verify_token_header (const gss_OID_desc * mech, + unsigned int *body_size, + unsigned char **buf, int tok_type, + unsigned int toksize_in, + int flags); + +OM_uint32 g_display_major_status (OM_uint32 *minor_status, + OM_uint32 status_value, + OM_uint32 *message_context, + gss_buffer_t status_string); + +OM_uint32 g_display_com_err_status (OM_uint32 *minor_status, + OM_uint32 status_value, + gss_buffer_t status_string); + +long g_seqstate_init(g_seqnum_state *state_out, uint64_t seqnum, + int do_replay, int do_sequence, int wide); +OM_uint32 g_seqstate_check(g_seqnum_state state, uint64_t seqnum); +void g_seqstate_free(g_seqnum_state state); +void g_seqstate_size(g_seqnum_state state, size_t *sizep); +long g_seqstate_externalize(g_seqnum_state state, unsigned char **buf, + size_t *lenremain); +long g_seqstate_internalize(g_seqnum_state *state_out, unsigned char **buf, + size_t *lenremain); + +char *g_strdup (char *str); + +/** declarations of internal name mechanism functions **/ + +OM_uint32 +generic_gss_release_buffer( + OM_uint32 *, /* minor_status */ + gss_buffer_t); /* buffer */ + +OM_uint32 +generic_gss_release_oid_set( + OM_uint32 *, /* minor_status */ + gss_OID_set *); /* set */ + +OM_uint32 +generic_gss_release_oid( + OM_uint32 *, /* minor_status */ + gss_OID *); /* set */ + +OM_uint32 +generic_gss_copy_oid( + OM_uint32 *, /* minor_status */ + const gss_OID_desc * const, /* oid */ + gss_OID *); /* new_oid */ + +OM_uint32 +generic_gss_create_empty_oid_set( + OM_uint32 *, /* minor_status */ + gss_OID_set *); /* oid_set */ + +OM_uint32 +generic_gss_add_oid_set_member( + OM_uint32 *, /* minor_status */ + const gss_OID_desc * const, /* member_oid */ + gss_OID_set *); /* oid_set */ + +OM_uint32 +generic_gss_test_oid_set_member( + OM_uint32 *, /* minor_status */ + const gss_OID_desc * const, /* member */ + gss_OID_set, /* set */ + int *); /* present */ + +OM_uint32 +generic_gss_oid_to_str( + OM_uint32 *, /* minor_status */ + const gss_OID_desc * const, /* oid */ + gss_buffer_t); /* oid_str */ + +OM_uint32 +generic_gss_str_to_oid( + OM_uint32 *, /* minor_status */ + gss_buffer_t, /* oid_str */ + gss_OID *); /* oid */ + +OM_uint32 +generic_gss_oid_compose( + OM_uint32 *, /* minor_status */ + const char *, /* prefix */ + size_t, /* prefix_len */ + int, /* suffix */ + gss_OID_desc *); /* oid */ + +OM_uint32 +generic_gss_oid_decompose( + OM_uint32 *, /* minor_status */ + const char *, /*prefix */ + size_t, /* prefix_len */ + gss_OID_desc *, /* oid */ + int *); /* suffix */ + +int gssint_mecherrmap_init(void); +void gssint_mecherrmap_destroy(void); +OM_uint32 gssint_mecherrmap_map(OM_uint32 minor, const gss_OID_desc *oid); +int gssint_mecherrmap_get(OM_uint32 minor, gss_OID mech_oid, + OM_uint32 *mech_minor); +OM_uint32 gssint_mecherrmap_map_errcode(OM_uint32 errcode); + +/* + * Transfer contents of a k5buf to a gss_buffer and invalidate the source + * On unix, this is a simple pointer copy + * On windows, memory is reallocated and copied. + */ +static inline OM_uint32 +k5buf_to_gss(OM_uint32 *minor, + struct k5buf *input_k5buf, + gss_buffer_t output_buffer) +{ + OM_uint32 status = GSS_S_COMPLETE; + + if (k5_buf_status(input_k5buf) != 0) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + output_buffer->length = input_k5buf->len; +#if defined(_WIN32) || defined(DEBUG_GSSALLOC) + if (output_buffer->length > 0) { + output_buffer->value = gssalloc_malloc(output_buffer->length); + if (output_buffer->value) { + memcpy(output_buffer->value, input_k5buf->data, + output_buffer->length); + } else { + status = GSS_S_FAILURE; + *minor = ENOMEM; + } + } else { + output_buffer->value = NULL; + } + k5_buf_free(input_k5buf); +#else + output_buffer->value = input_k5buf->data; + memset(input_k5buf, 0, sizeof(*input_k5buf)); +#endif + return status; +} + +OM_uint32 generic_gss_create_empty_buffer_set +(OM_uint32 * /*minor_status*/, + gss_buffer_set_t * /*buffer_set*/); + +OM_uint32 generic_gss_add_buffer_set_member +(OM_uint32 * /*minor_status*/, + const gss_buffer_t /*member_buffer*/, + gss_buffer_set_t * /*buffer_set*/); + +OM_uint32 generic_gss_release_buffer_set +(OM_uint32 * /*minor_status*/, + gss_buffer_set_t * /*buffer_set*/); + +OM_uint32 generic_gss_copy_oid_set +(OM_uint32 *, /* minor_status */ + const gss_OID_set_desc * const /*oidset*/, + gss_OID_set * /*new_oidset*/); + +extern gss_OID_set gss_ma_known_attrs; + +OM_uint32 generic_gss_display_mech_attr( + OM_uint32 *minor_status, + gss_const_OID mech_attr, + gss_buffer_t name, + gss_buffer_t short_desc, + gss_buffer_t long_desc); + +#endif /* _GSSAPIP_GENERIC_H_ */ diff --git a/krb5-1.21.3/src/lib/gssapi/generic/gssapi_alloc.h b/krb5-1.21.3/src/lib/gssapi/generic/gssapi_alloc.h new file mode 100644 index 00000000..89ef3324 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/gssapi_alloc.h @@ -0,0 +1,131 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* To the extent possible under law, Painless Security, LLC has waived + * all copyright and related or neighboring rights to GSS-API Memory + * Management Header. This work is published from: United States. + */ + +#ifndef GSSAPI_ALLOC_H +#define GSSAPI_ALLOC_H + +#ifdef _WIN32 +#include "winbase.h" +#endif +#include + +#if defined(_WIN32) + +static inline void +gssalloc_free(void *value) +{ + if (value) + HeapFree(GetProcessHeap(), 0, value); +} + +static inline void * +gssalloc_malloc(size_t size) +{ + return HeapAlloc(GetProcessHeap(), 0, size); +} + +static inline void * +gssalloc_calloc(size_t count, size_t size) +{ + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * size); +} + +static inline void * +gssalloc_realloc(void *value, size_t size) +{ + /* Unlike realloc(), HeapReAlloc() does not work on null values. */ + if (value == NULL) + return HeapAlloc(GetProcessHeap(), 0, size); + return HeapReAlloc(GetProcessHeap(), 0, value, size); +} + +#elif defined(DEBUG_GSSALLOC) + +/* Be deliberately incompatible with malloc and free, to allow us to detect + * mismatched malloc/gssalloc usage on Unix. */ + +static inline void +gssalloc_free(void *value) +{ + char *p = (char *)value - 8; + + if (value == NULL) + return; + if (memcmp(p, "gssalloc", 8) != 0) + abort(); + free(p); +} + +static inline void * +gssalloc_malloc(size_t size) +{ + char *p = calloc(size + 8, 1); + + memcpy(p, "gssalloc", 8); + return p + 8; +} + +static inline void * +gssalloc_calloc(size_t count, size_t size) +{ + return gssalloc_malloc(count * size); +} + +static inline void * +gssalloc_realloc(void *value, size_t size) +{ + char *p = (char *)value - 8; + + if (value == NULL) + return gssalloc_malloc(size); + if (memcmp(p, "gssalloc", 8) != 0) + abort(); + return (char *)realloc(p, size + 8) + 8; +} + +#else /* not _WIN32 or DEBUG_GSSALLOC */ + +/* Normal Unix case, just use free/malloc/calloc/realloc. */ + +static inline void +gssalloc_free(void *value) +{ + free(value); +} + +static inline void * +gssalloc_malloc(size_t size) +{ + return malloc(size); +} + +static inline void * +gssalloc_calloc(size_t count, size_t size) +{ + return calloc(count, size); +} + +static inline void * +gssalloc_realloc(void *value, size_t size) +{ + return realloc(value, size); +} + +#endif /* not _WIN32 or DEBUG_GSSALLOC */ + +static inline char * +gssalloc_strdup(const char *str) +{ + size_t size = strlen(str)+1; + char *copy = gssalloc_malloc(size); + if (copy) { + memcpy(copy, str, size); + copy[size-1] = '\0'; + } + return copy; +} + +#endif diff --git a/krb5-1.21.3/src/lib/gssapi/generic/gssapi_err_generic.et b/krb5-1.21.3/src/lib/gssapi/generic/gssapi_err_generic.et new file mode 100644 index 00000000..3e976e3d --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/gssapi_err_generic.et @@ -0,0 +1,49 @@ +# +# Copyright 1993 by OpenVision Technologies, Inc. +# +# Permission to use, copy, modify, distribute, and sell this software +# and its documentation for any purpose is hereby granted without fee, +# provided that the above copyright notice appears in all copies and +# that both that copyright notice and this permission notice appear in +# supporting documentation, and that the name of OpenVision not be used +# in advertising or publicity pertaining to distribution of the software +# without specific, written prior permission. OpenVision makes no +# representations about the suitability of this software for any +# purpose. It is provided "as is" without express or implied warranty. +# +# OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# + +# +# $Id$ +# + +error_table ggss + +error_code G_BAD_SERVICE_NAME, "No @ in SERVICE-NAME name string" +error_code G_BAD_STRING_UID, "STRING-UID-NAME contains nondigits" +error_code G_NOUSER, "UID does not resolve to username" +error_code G_VALIDATE_FAILED, "Validation error" +error_code G_BUFFER_ALLOC, "Couldn't allocate gss_buffer_t data" +error_code G_BAD_MSG_CTX, "Message context invalid" +error_code G_WRONG_SIZE, "Buffer is the wrong size" +error_code G_BAD_USAGE, "Credential usage type is unknown" +error_code G_UNKNOWN_QOP, "Unknown quality of protection specified" +error_code G_NO_HOSTNAME, "Local host name could not be determined" +error_code G_BAD_HOSTNAME, "Hostname in SERVICE-NAME string could not be canonicalized" +error_code G_WRONG_MECH, "Mechanism is incorrect" +error_code G_BAD_TOK_HEADER, "Token header is malformed or corrupt" +error_code G_BAD_DIRECTION, "Packet was replayed in wrong direction" +error_code G_TOK_TRUNC, "Token is missing data" +error_code G_REFLECT, "Token was reflected" +error_code G_WRONG_TOKID, "Received token ID does not match expected token ID" +error_code G_CRED_USAGE_MISMATCH, "The given credential's usage does not match the requested usage" +error_code G_STORE_ACCEPTOR_CRED_NOSUPP, "Storing of acceptor credentials is not supported by the mechanism" +error_code G_STORE_NON_DEFAULT_CRED_NOSUPP, "Storing of non-default credentials is not supported by the mechanism" +end diff --git a/krb5-1.21.3/src/lib/gssapi/generic/gssapi_ext.h b/krb5-1.21.3/src/lib/gssapi/generic/gssapi_ext.h new file mode 100644 index 00000000..38e39616 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/gssapi_ext.h @@ -0,0 +1,650 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef GSSAPI_EXT_H_ +#define GSSAPI_EXT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * Solaris extensions + */ +#ifndef _WIN32 +OM_uint32 KRB5_CALLCONV +gss_pname_to_uid + (OM_uint32 *minor, + const gss_name_t name, + const gss_OID mech_type, + uid_t *uidOut); +#endif + +/** + * Provides a platform-specific name for a GSSAPI name as interpreted by a + * given mechanism. + * + * @param [out] minor Minor status code + * @param [in] name The gss name resulting from accept_sec_context + * @param [in] mech_type The mechanism that will be asked to map @a name to a + * local name + * @param [out] localname Caller-allocated buffer to be filled in with the + * local name on success + */ +OM_uint32 KRB5_CALLCONV +gss_localname + (OM_uint32 *minor, + const gss_name_t name, + gss_const_OID mech_type, + gss_buffer_t localname); + +/** + * Determine whether a mechanism name is authorized to act as a username. + * + * @param [in] name Mechanism name + * @param [in] username System username + * + * This is a simple wrapper around gss_authorize_localname(). It only supports + * system usernames as local names, and cannot distinguish between lack of + * authorization and other errors. + * + * @retval 1 @a name is authorized to act as @a username + * @retval 0 @a name is not authorized or an error occurred + */ +int KRB5_CALLCONV +gss_userok(const gss_name_t name, + const char *username); + +/** + * Determine whether a mechanism name is authorized to act as a local name. + * + * @param [out] minor Minor status code + * @param [in] name Mechanism name + * @param [in] user Local name + * + * @a name is a mechanism name, typically the result of a completed + * gss_accept_sec_context(). @a user is an internal name representing a local + * name, such as a name imported by gss_import_name() with an @a + * input_name_type of @c GSS_C_NT_USER_NAME. + * + * @return Return GSS_S_COMPLETE if @a name is authorized to act as @a user, + * GSS_S_UNAUTHORIZED if not, or an appropriate GSS error code if an error + * occurred. + * + * @sa gss_userok + */ +OM_uint32 KRB5_CALLCONV +gss_authorize_localname(OM_uint32 *minor, + const gss_name_t name, + const gss_name_t user); + +OM_uint32 KRB5_CALLCONV +gss_acquire_cred_with_password( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* desired_name */ + const gss_buffer_t, /* password */ + OM_uint32, /* time_req */ + const gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *); /* time_rec */ + +OM_uint32 KRB5_CALLCONV +gss_add_cred_with_password( + OM_uint32 *, /* minor_status */ + const gss_cred_id_t,/* input_cred_handle */ + const gss_name_t, /* desired_name */ + const gss_OID, /* desired_mech */ + const gss_buffer_t, /* password */ + gss_cred_usage_t, /* cred_usage */ + OM_uint32, /* initiator_time_req */ + OM_uint32, /* acceptor_time_req */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *, /* initiator_time_rec */ + OM_uint32 *); /* acceptor_time_rec */ + +/* + * GGF extensions + */ +typedef struct gss_buffer_set_desc_struct { + size_t count; + gss_buffer_desc *elements; +} gss_buffer_set_desc, *gss_buffer_set_t; + +#define GSS_C_NO_BUFFER_SET ((gss_buffer_set_t) 0) + +OM_uint32 KRB5_CALLCONV gss_create_empty_buffer_set + (OM_uint32 * /*minor_status*/, + gss_buffer_set_t * /*buffer_set*/); + +OM_uint32 KRB5_CALLCONV gss_add_buffer_set_member + (OM_uint32 * /*minor_status*/, + const gss_buffer_t /*member_buffer*/, + gss_buffer_set_t * /*buffer_set*/); + +OM_uint32 KRB5_CALLCONV gss_release_buffer_set + (OM_uint32 * /*minor_status*/, + gss_buffer_set_t * /*buffer_set*/); + +OM_uint32 KRB5_CALLCONV gss_inquire_sec_context_by_oid + (OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_OID /*desired_object*/, + gss_buffer_set_t * /*data_set*/); + +OM_uint32 KRB5_CALLCONV gss_inquire_cred_by_oid + (OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + const gss_OID /*desired_object*/, + gss_buffer_set_t * /*data_set*/); + +OM_uint32 KRB5_CALLCONV gss_set_sec_context_option + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*cred_handle*/, + const gss_OID /*desired_object*/, + const gss_buffer_t /*value*/); + +/* + * Export import cred extensions from GGF, but using Heimdal's signatures + */ +OM_uint32 KRB5_CALLCONV gss_export_cred + (OM_uint32 * /* minor_status */, + gss_cred_id_t /* cred_handle */, + gss_buffer_t /* token */); + +OM_uint32 KRB5_CALLCONV gss_import_cred + (OM_uint32 * /* minor_status */, + gss_buffer_t /* token */, + gss_cred_id_t * /* cred_handle */); + +/* + * Heimdal extension + */ +OM_uint32 KRB5_CALLCONV gss_set_cred_option + (OM_uint32 * /*minor_status*/, + gss_cred_id_t * /*cred*/, + const gss_OID /*desired_object*/, + const gss_buffer_t /*value*/); + +/* + * Call the given method on the given mechanism + */ +OM_uint32 KRB5_CALLCONV gssspi_mech_invoke + (OM_uint32 * /*minor_status*/, + const gss_OID /*desired_mech*/, + const gss_OID /*desired_object*/, + gss_buffer_t /*value*/); + +/* + * AEAD extensions + */ + +OM_uint32 KRB5_CALLCONV gss_wrap_aead + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + gss_buffer_t /*input_assoc_buffer*/, + gss_buffer_t /*input_payload_buffer*/, + int * /*conf_state*/, + gss_buffer_t /*output_message_buffer*/); + +OM_uint32 KRB5_CALLCONV gss_unwrap_aead + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*input_assoc_buffer*/, + gss_buffer_t /*output_payload_buffer*/, + int * /*conf_state*/, + gss_qop_t * /*qop_state*/); + +/* + * SSPI extensions + */ +#define GSS_C_DCE_STYLE 0x1000 +#define GSS_C_IDENTIFY_FLAG 0x2000 +#define GSS_C_EXTENDED_ERROR_FLAG 0x4000 + +/* + * Returns a buffer set with the first member containing the + * session key for SSPI compatibility. The optional second + * member contains an OID identifying the session key type. + */ +GSS_DLLIMP extern gss_OID GSS_C_INQ_SSPI_SESSION_KEY; + +/* + * Returns a buffer set with the first member containing the ticket session key + * for ODBC compatibility. The optional second member contains an OID + * identifying the session key type. + */ +GSS_DLLIMP extern gss_OID GSS_C_INQ_ODBC_SESSION_KEY; + +GSS_DLLIMP extern gss_OID GSS_C_INQ_NEGOEX_KEY; +GSS_DLLIMP extern gss_OID GSS_C_INQ_NEGOEX_VERIFY_KEY; + +OM_uint32 KRB5_CALLCONV gss_complete_auth_token + (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer); + +typedef struct gss_iov_buffer_desc_struct { + OM_uint32 type; + gss_buffer_desc buffer; +} gss_iov_buffer_desc, *gss_iov_buffer_t; + +#define GSS_C_NO_IOV_BUFFER ((gss_iov_buffer_t)0) + +#define GSS_IOV_BUFFER_TYPE_EMPTY 0 +#define GSS_IOV_BUFFER_TYPE_DATA 1 /* Packet data */ +#define GSS_IOV_BUFFER_TYPE_HEADER 2 /* Mechanism header */ +#define GSS_IOV_BUFFER_TYPE_MECH_PARAMS 3 /* Mechanism specific parameters */ +#define GSS_IOV_BUFFER_TYPE_TRAILER 7 /* Mechanism trailer */ +#define GSS_IOV_BUFFER_TYPE_PADDING 9 /* Padding */ +#define GSS_IOV_BUFFER_TYPE_STREAM 10 /* Complete wrap token */ +#define GSS_IOV_BUFFER_TYPE_SIGN_ONLY 11 /* Sign only packet data */ +#define GSS_IOV_BUFFER_TYPE_MIC_TOKEN 12 /* MIC token destination */ + +#define GSS_IOV_BUFFER_FLAG_MASK 0xFFFF0000 +#define GSS_IOV_BUFFER_FLAG_ALLOCATE 0x00010000 /* indicates GSS should allocate */ +#define GSS_IOV_BUFFER_FLAG_ALLOCATED 0x00020000 /* indicates caller should free */ + +#define GSS_IOV_BUFFER_TYPE(_type) ((_type) & ~(GSS_IOV_BUFFER_FLAG_MASK)) +#define GSS_IOV_BUFFER_FLAGS(_type) ((_type) & GSS_IOV_BUFFER_FLAG_MASK) + +/* + * Sign and optionally encrypt a sequence of buffers. The buffers + * shall be ordered HEADER | DATA | PADDING | TRAILER. Suitable + * space for the header, padding and trailer should be provided + * by calling gss_wrap_iov_length(), or the ALLOCATE flag should + * be set on those buffers. + * + * Encryption is in-place. SIGN_ONLY buffers are untouched. Only + * a single PADDING buffer should be provided. The order of the + * buffers in memory does not matter. Buffers in the IOV should + * be arranged in the order above, and in the case of multiple + * DATA buffers the sender and receiver should agree on the + * order. + * + * With GSS_C_DCE_STYLE it is acceptable to not provide PADDING + * and TRAILER, but the caller must guarantee the plaintext data + * being encrypted is correctly padded, otherwise an error will + * be returned. + * + * While applications that have knowledge of the underlying + * cryptosystem may request a specific configuration of data + * buffers, the only generally supported configurations are: + * + * HEADER | DATA | PADDING | TRAILER + * + * which will emit GSS_Wrap() compatible tokens, and: + * + * HEADER | SIGN_ONLY | DATA | PADDING | TRAILER + * + * for AEAD. + * + * The typical (special cased) usage for DCE is as follows: + * + * SIGN_ONLY_1 | DATA | SIGN_ONLY_2 | HEADER + */ +OM_uint32 KRB5_CALLCONV gss_wrap_iov +( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + int *, /* conf_state */ + gss_iov_buffer_desc *, /* iov */ + int); /* iov_count */ + +/* + * Verify and optionally decrypt a sequence of buffers. To process + * a GSS-API message without separate buffer, pass STREAM | DATA. + * Upon return DATA will contain the decrypted or integrity + * protected message. Only a single DATA buffer may be provided + * with this usage. DATA by default will point into STREAM, but if + * the ALLOCATE flag is set a copy will be returned. + * + * Otherwise, decryption is in-place. SIGN_ONLY buffers are + * untouched. + */ +OM_uint32 KRB5_CALLCONV gss_unwrap_iov +( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int *, /* conf_state */ + gss_qop_t *, /* qop_state */ + gss_iov_buffer_desc *, /* iov */ + int); /* iov_count */ + +/* + * Query HEADER, PADDING and TRAILER buffer lengths. DATA buffers + * should be provided so the correct padding length can be determined. + */ +OM_uint32 KRB5_CALLCONV gss_wrap_iov_length +( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + int *, /* conf_state */ + gss_iov_buffer_desc *, /* iov */ + int); /* iov_count */ + +/* + * Produce a GSSAPI MIC token for a sequence of buffers. All SIGN_ONLY and + * DATA buffers will be signed, in the order they appear. One MIC_TOKEN buffer + * must be included for the result. Suitable space should be provided for the + * MIC_TOKEN buffer by calling gss_get_mic_iov_length, or the ALLOCATE flag + * should be set on that buffer. If the ALLOCATE flag is used, use + * gss_release_iov_buffer to free the allocated buffer within the iov list when + * it is no longer needed. + */ +OM_uint32 KRB5_CALLCONV gss_get_mic_iov +( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t, /* qop_req */ + gss_iov_buffer_desc *, /* iov */ + int); /* iov_count */ + +/* + * Query the MIC_TOKEN buffer length within the iov list. + */ +OM_uint32 KRB5_CALLCONV gss_get_mic_iov_length( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t, /* qop_req */ + gss_iov_buffer_desc *, /* iov */ + int); /* iov_count */ + +/* + * Verify the MIC_TOKEN buffer within the iov list against the SIGN_ONLY and + * DATA buffers in the order they appear. Return values are the same as for + * gss_verify_mic. + */ +OM_uint32 KRB5_CALLCONV gss_verify_mic_iov +( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t *, /* qop_state */ + gss_iov_buffer_desc *, /* iov */ + int); /* iov_count */ + +/* + * Release buffers that have the ALLOCATED flag set. + */ +OM_uint32 KRB5_CALLCONV gss_release_iov_buffer +( + OM_uint32 *, /* minor_status */ + gss_iov_buffer_desc *, /* iov */ + int); /* iov_count */ + +/* + * Protocol transition + */ +OM_uint32 KRB5_CALLCONV +gss_acquire_cred_impersonate_name( + OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* impersonator_cred_handle */ + const gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + const gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *); /* time_rec */ + +OM_uint32 KRB5_CALLCONV +gss_add_cred_impersonate_name( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* input_cred_handle */ + const gss_cred_id_t, /* impersonator_cred_handle */ + const gss_name_t, /* desired_name */ + const gss_OID, /* desired_mech */ + gss_cred_usage_t, /* cred_usage */ + OM_uint32, /* initiator_time_req */ + OM_uint32, /* acceptor_time_req */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *, /* initiator_time_rec */ + OM_uint32 *); /* acceptor_time_rec */ + +/* + * Naming extensions + */ +GSS_DLLIMP extern gss_buffer_t GSS_C_ATTR_LOCAL_LOGIN_USER; +GSS_DLLIMP extern gss_OID GSS_C_NT_COMPOSITE_EXPORT; + +OM_uint32 KRB5_CALLCONV gss_display_name_ext +( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_OID, /* display_as_name_type */ + gss_buffer_t /* display_name */ +); + +OM_uint32 KRB5_CALLCONV gss_inquire_name +( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + int *, /* name_is_MN */ + gss_OID *, /* MN_mech */ + gss_buffer_set_t * /* attrs */ +); + +OM_uint32 KRB5_CALLCONV gss_get_name_attribute +( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t, /* attr */ + int *, /* authenticated */ + int *, /* complete */ + gss_buffer_t, /* value */ + gss_buffer_t, /* display_value */ + int * /* more */ +); + +OM_uint32 KRB5_CALLCONV gss_set_name_attribute +( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + int, /* complete */ + gss_buffer_t, /* attr */ + gss_buffer_t /* value */ +); + +OM_uint32 KRB5_CALLCONV gss_delete_name_attribute +( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t /* attr */ +); + +OM_uint32 KRB5_CALLCONV gss_export_name_composite +( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t /* exp_composite_name */ +); + +typedef struct gss_any *gss_any_t; + +OM_uint32 KRB5_CALLCONV gss_map_name_to_any +( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + int, /* authenticated */ + gss_buffer_t, /* type_id */ + gss_any_t * /* output */ +); + +OM_uint32 KRB5_CALLCONV gss_release_any_name_mapping +( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t, /* type_id */ + gss_any_t * /* input */ +); + +/* draft-josefsson-gss-capsulate */ +OM_uint32 KRB5_CALLCONV gss_encapsulate_token +( + gss_const_buffer_t, /* input_token */ + gss_const_OID, /* token_oid */ + gss_buffer_t /* output_token */ +); + +OM_uint32 KRB5_CALLCONV gss_decapsulate_token +( + gss_const_buffer_t, /* input_token */ + gss_const_OID, /* token_oid */ + gss_buffer_t /* output_token */ +); + +int KRB5_CALLCONV gss_oid_equal +( + gss_const_OID, /* first_oid */ + gss_const_OID /* second_oid */ +); + +/* Credential store extensions */ + +struct gss_key_value_element_struct { + const char *key; + const char *value; +}; +typedef struct gss_key_value_element_struct gss_key_value_element_desc; + +struct gss_key_value_set_struct { + OM_uint32 count; + gss_key_value_element_desc *elements; +}; +typedef struct gss_key_value_set_struct gss_key_value_set_desc; +typedef const gss_key_value_set_desc *gss_const_key_value_set_t; + +#define GSS_C_NO_CRED_STORE ((gss_const_key_value_set_t) 0) + +OM_uint32 KRB5_CALLCONV +gss_acquire_cred_from( + OM_uint32 *, /* minor_status */ + gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_const_key_value_set_t, /* cred_store */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *); /* time_rec */ + +OM_uint32 KRB5_CALLCONV +gss_add_cred_from( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* input_cred_handle */ + gss_name_t, /* desired_name */ + gss_OID, /* desired_mech */ + gss_cred_usage_t, /* cred_usage */ + OM_uint32, /* initiator_time_req */ + OM_uint32, /* acceptor_time_req */ + gss_const_key_value_set_t, /* cred_store */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *, /* initiator_time_rec */ + OM_uint32 *); /* acceptor_time_rec */ + +OM_uint32 KRB5_CALLCONV +gss_store_cred_into( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* input_cred_handle */ + gss_cred_usage_t, /* input_usage */ + gss_OID, /* desired_mech */ + OM_uint32, /* overwrite_cred */ + OM_uint32, /* default_cred */ + gss_const_key_value_set_t, /* cred_store */ + gss_OID_set *, /* elements_stored */ + gss_cred_usage_t *); /* cred_usage_stored */ + +/* + * A mech can make itself negotiable via NegoEx (draft-zhu-negoex) by + * implementing the following three SPIs, and also implementing + * gss_inquire_sec_context_by_oid() and answering the GSS_C_INQ_NEGOEX_KEY and + * GSS_C_INQ_NEGOEX_VERIFY_KEY OIDs. The answer must be in two buffers: the + * first contains the key contents, and the second contains the key enctype as + * a four-byte little-endian integer. + * + * By default, NegoEx mechanisms will not be directly negotiated via SPNEGO. + * If direct SPNEGO negotiation is required for interoperability, implement + * gss_inquire_attrs_for_mech() and assert the GSS_C_MA_NEGOEX_AND_SPNEGO + * attribute (along with any applicable RFC 5587 attributes). + */ + +#define GSS_C_CHANNEL_BOUND_FLAG 2048 /* 0x00000800 */ + +OM_uint32 KRB5_CALLCONV +gssspi_query_meta_data( + OM_uint32 *minor_status, + gss_const_OID mech_oid, + gss_cred_id_t cred_handle, + gss_ctx_id_t *context_handle, + const gss_name_t targ_name, + OM_uint32 req_flags, + gss_buffer_t meta_data); + +OM_uint32 KRB5_CALLCONV +gssspi_exchange_meta_data( + OM_uint32 *minor_status, + gss_const_OID mech_oid, + gss_cred_id_t cred_handle, + gss_ctx_id_t *context_handle, + const gss_name_t targ_name, + OM_uint32 req_flags, + gss_const_buffer_t meta_data); + +OM_uint32 KRB5_CALLCONV +gssspi_query_mechanism_info( + OM_uint32 *minor_status, + gss_const_OID mech_oid, + unsigned char auth_scheme[16]); + +GSS_DLLIMP extern gss_const_OID GSS_C_MA_NEGOEX_AND_SPNEGO; + +#ifdef __cplusplus +} +#endif + +/* + * When used with gss_inquire_sec_context_by_oid(), return a buffer set with + * the first member containing an unsigned 32-bit integer in network byte + * order. This is the Security Strength Factor (SSF) associated with the + * secure channel established by the security context. NOTE: This value is + * made available solely as an indication for use by APIs like Cyrus SASL that + * classify the strength of a secure channel via this number. The strength of + * a channel cannot necessarily be represented by a simple number. + */ +GSS_DLLIMP extern gss_OID GSS_C_SEC_CONTEXT_SASL_SSF; + +#endif /* GSSAPI_EXT_H_ */ diff --git a/krb5-1.21.3/src/lib/gssapi/generic/gssapi_generic.c b/krb5-1.21.3/src/lib/gssapi/generic/gssapi_generic.c new file mode 100644 index 00000000..7fbecbed --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/gssapi_generic.c @@ -0,0 +1,488 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * $Id$ + */ + +#include "gssapiP_generic.h" + +/* + * See krb5/gssapi_krb5.c for a description of the algorithm for + * encoding an object identifier. + */ + +/* Reserved static storage for GSS_oids. Comments are quotes from RFC 2744. */ + +#define oids ((gss_OID_desc *)const_oids) +static const gss_OID_desc const_oids[] = { + /* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value */ + {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01"}, + /* corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) user_name(1)}. The constant + * GSS_C_NT_USER_NAME should be initialized to point + * to that gss_OID_desc. + */ + + /* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value */ + {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"}, + /* corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. + * The constant GSS_C_NT_MACHINE_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ + + /* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value */ + {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03"}, + /* corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) string_uid_name(3)}. + * The constant GSS_C_NT_STRING_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ + + /* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value */ + {6, (void *)"\x2b\x06\x01\x05\x06\x02"}, + /* corresponding to an object-identifier value of + * {iso(1) org(3) dod(6) internet(1) security(5) + * nametypes(6) gss-host-based-services(2)). The constant + * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point + * to that gss_OID_desc. This is a deprecated OID value, and + * implementations wishing to support hostbased-service names + * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID, + * defined below, to identify such names; + * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym + * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input + * parameter, but should not be emitted by GSS-API + * implementations + */ + + /* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value */ + {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04"}, + /* corresponding to an object-identifier value of + * {iso(1) member-body(2) Unites States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) service_name(4)}. + * The constant GSS_C_NT_HOSTBASED_SERVICE should be + * initialized to point to that gss_OID_desc. + */ + + /* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value */ + {6, (void *)"\x2b\x06\01\x05\x06\x03"}, + /* corresponding to an object identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 3(gss-anonymous-name)}. The constant + * and GSS_C_NT_ANONYMOUS should be initialized to point + * to that gss_OID_desc. + */ + + /* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value */ + {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, + /* corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 4(gss-api-exported-name)}. The constant + * GSS_C_NT_EXPORT_NAME should be initialized to point + * to that gss_OID_desc. + */ + {6, (void *)"\x2b\x06\x01\x05\x06\x06"}, + /* corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 6(gss-composite-export)}. The constant + * GSS_C_NT_COMPOSITE_EXPORT should be initialized to point + * to that gss_OID_desc. + */ + /* GSS_C_INQ_SSPI_SESSION_KEY 1.2.840.113554.1.2.2.5.5 */ + {11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05"}, + /* GSS_C_INQ_NEGOEX_KEY 1.2.840.113554.1.2.2.5.16 */ + {11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x10"}, + /* GSS_C_INQ_NEGOEX_VERIFY_KEY 1.2.840.113554.1.2.2.5.17 */ + {11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x11"}, + + /* RFC 5587 attributes, see below */ + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x01"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x02"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x03"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x04"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x05"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x06"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x07"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x08"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x09"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x0a"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x0b"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x0c"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x0d"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x0e"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x0f"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x10"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x11"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x12"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x13"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x14"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x15"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x16"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x17"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x18"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x19"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x1a"}, + {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x1b"}, + /* GSS_C_MA_NEGOEX_AND_SPNEGO 1.2.840.113554.1.2.2.5.18 */ + {11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x12"}, + + /* + * GSS_SEC_CONTEXT_SASL_SSF_OID 1.2.840.113554.1.2.2.5.15 + * iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) krb5(2) krb5-gssapi-ext(5) sasl-ssf(15) + */ + {11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f"}, + + /* + * GSS_C_INQ_ODBC_SESSION_KEY 1.2.840.113554.1.2.2.5.19 + * iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) ssapi(2) krb5(2) krb5-gssapi-ext(5) + * inq-odbc-session-key(19) + */ + {11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05\13"}, +}; + +/* Here are the constants which point to the static structure above. + * + * Constants of the form GSS_C_NT_* are specified by rfc 2744. + * + * Constants of the form gss_nt_* are the original MIT krb5 names + * found in gssapi_generic.h. They are provided for compatibility. */ + +GSS_DLLIMP gss_OID GSS_C_NT_USER_NAME = oids+0; +GSS_DLLIMP gss_OID gss_nt_user_name = oids+0; + +GSS_DLLIMP gss_OID GSS_C_NT_MACHINE_UID_NAME = oids+1; +GSS_DLLIMP gss_OID gss_nt_machine_uid_name = oids+1; + +GSS_DLLIMP gss_OID GSS_C_NT_STRING_UID_NAME = oids+2; +GSS_DLLIMP gss_OID gss_nt_string_uid_name = oids+2; + +GSS_DLLIMP gss_OID GSS_C_NT_HOSTBASED_SERVICE_X = oids+3; +gss_OID gss_nt_service_name_v2 = oids+3; + +GSS_DLLIMP gss_OID GSS_C_NT_HOSTBASED_SERVICE = oids+4; +GSS_DLLIMP gss_OID gss_nt_service_name = oids+4; + +GSS_DLLIMP gss_OID GSS_C_NT_ANONYMOUS = oids+5; + +GSS_DLLIMP gss_OID GSS_C_NT_EXPORT_NAME = oids+6; +gss_OID gss_nt_exported_name = oids+6; + +GSS_DLLIMP gss_OID GSS_C_NT_COMPOSITE_EXPORT = oids+7; +GSS_DLLIMP gss_OID GSS_C_INQ_SSPI_SESSION_KEY = oids+8; +GSS_DLLIMP gss_OID GSS_C_INQ_NEGOEX_KEY = oids+9; +GSS_DLLIMP gss_OID GSS_C_INQ_NEGOEX_VERIFY_KEY = oids+10; + +GSS_DLLIMP gss_const_OID GSS_C_MA_MECH_CONCRETE = oids+11; +GSS_DLLIMP gss_const_OID GSS_C_MA_MECH_PSEUDO = oids+12; +GSS_DLLIMP gss_const_OID GSS_C_MA_MECH_COMPOSITE = oids+13; +GSS_DLLIMP gss_const_OID GSS_C_MA_MECH_NEGO = oids+14; +GSS_DLLIMP gss_const_OID GSS_C_MA_MECH_GLUE = oids+15; +GSS_DLLIMP gss_const_OID GSS_C_MA_NOT_MECH = oids+16; +GSS_DLLIMP gss_const_OID GSS_C_MA_DEPRECATED = oids+17; +GSS_DLLIMP gss_const_OID GSS_C_MA_NOT_DFLT_MECH = oids+18; +GSS_DLLIMP gss_const_OID GSS_C_MA_ITOK_FRAMED = oids+19; +GSS_DLLIMP gss_const_OID GSS_C_MA_AUTH_INIT = oids+20; +GSS_DLLIMP gss_const_OID GSS_C_MA_AUTH_TARG = oids+21; +GSS_DLLIMP gss_const_OID GSS_C_MA_AUTH_INIT_INIT = oids+22; +GSS_DLLIMP gss_const_OID GSS_C_MA_AUTH_TARG_INIT = oids+23; +GSS_DLLIMP gss_const_OID GSS_C_MA_AUTH_INIT_ANON = oids+24; +GSS_DLLIMP gss_const_OID GSS_C_MA_AUTH_TARG_ANON = oids+25; +GSS_DLLIMP gss_const_OID GSS_C_MA_DELEG_CRED = oids+26; +GSS_DLLIMP gss_const_OID GSS_C_MA_INTEG_PROT = oids+27; +GSS_DLLIMP gss_const_OID GSS_C_MA_CONF_PROT = oids+28; +GSS_DLLIMP gss_const_OID GSS_C_MA_MIC = oids+29; +GSS_DLLIMP gss_const_OID GSS_C_MA_WRAP = oids+30; +GSS_DLLIMP gss_const_OID GSS_C_MA_PROT_READY = oids+31; +GSS_DLLIMP gss_const_OID GSS_C_MA_REPLAY_DET = oids+32; +GSS_DLLIMP gss_const_OID GSS_C_MA_OOS_DET = oids+33; +GSS_DLLIMP gss_const_OID GSS_C_MA_CBINDINGS = oids+34; +GSS_DLLIMP gss_const_OID GSS_C_MA_PFS = oids+35; +GSS_DLLIMP gss_const_OID GSS_C_MA_COMPRESS = oids+36; +GSS_DLLIMP gss_const_OID GSS_C_MA_CTX_TRANS = oids+37; +GSS_DLLIMP gss_const_OID GSS_C_MA_NEGOEX_AND_SPNEGO = oids+38; + +GSS_DLLIMP gss_OID GSS_C_SEC_CONTEXT_SASL_SSF = oids+39; + +GSS_DLLIMP gss_OID GSS_C_INQ_ODBC_SESSION_KEY = oids+40; + +static gss_OID_set_desc gss_ma_known_attrs_desc = { 28, oids+11 }; + +gss_OID_set gss_ma_known_attrs = &gss_ma_known_attrs_desc; + +static struct mech_attr_info_desc { + gss_OID mech_attr; + const char *name; + const char *short_desc; + const char *long_desc; +} mech_attr_info[] = { + { + oids+11, + "GSS_C_MA_MECH_CONCRETE", + "concrete-mech", + "Mechanism is neither a pseudo-mechanism nor a composite mechanism.", + }, + { + oids+12, + "GSS_C_MA_MECH_PSEUDO", + "pseudo-mech", + "Mechanism is a pseudo-mechanism.", + }, + { + oids+13, + "GSS_C_MA_MECH_COMPOSITE", + "composite-mech", + "Mechanism is a composite of other mechanisms.", + }, + { + oids+14, + "GSS_C_MA_MECH_NEGO", + "mech-negotiation-mech", + "Mechanism negotiates other mechanisms.", + }, + { + oids+15, + "GSS_C_MA_MECH_GLUE", + "mech-glue", + "OID is not a mechanism but the GSS-API itself.", + }, + { + oids+16, + "GSS_C_MA_NOT_MECH", + "not-mech", + "Known OID but not a mechanism OID.", + }, + { + oids+17, + "GSS_C_MA_DEPRECATED", + "mech-deprecated", + "Mechanism is deprecated.", + }, + { + oids+18, + "GSS_C_MA_NOT_DFLT_MECH", + "mech-not-default", + "Mechanism must not be used as a default mechanism.", + }, + { + oids+19, + "GSS_C_MA_ITOK_FRAMED", + "initial-is-framed", + "Mechanism's initial contexts are properly framed.", + }, + { + oids+20, + "GSS_C_MA_AUTH_INIT", + "auth-init-princ", + "Mechanism supports authentication of initiator to acceptor.", + }, + { + oids+21, + "GSS_C_MA_AUTH_TARG", + "auth-targ-princ", + "Mechanism supports authentication of acceptor to initiator.", + }, + { + oids+22, + "GSS_C_MA_AUTH_INIT_INIT", + "auth-init-princ-initial", + "Mechanism supports authentication of initiator using " + "initial credentials.", + }, + { + oids+23, + "GSS_C_MA_AUTH_TARG_INIT", + "auth-target-princ-initial", + "Mechanism supports authentication of acceptor using " + "initial credentials.", + }, + { + oids+24, + "GSS_C_MA_AUTH_INIT_ANON", + "auth-init-princ-anon", + "Mechanism supports GSS_C_NT_ANONYMOUS as an initiator name.", + }, + { + oids+25, + "GSS_C_MA_AUTH_TARG_ANON", + "auth-targ-princ-anon", + "Mechanism supports GSS_C_NT_ANONYMOUS as an acceptor name.", + }, + { + oids+26, + "GSS_C_MA_DELEG_CRED", + "deleg-cred", + "Mechanism supports credential delegation.", + }, + { + oids+27, + "GSS_C_MA_INTEG_PROT", + "integ-prot", + "Mechanism supports per-message integrity protection.", + }, + { + oids+28, + "GSS_C_MA_CONF_PROT", + "conf-prot", + "Mechanism supports per-message confidentiality protection.", + }, + { + oids+29, + "GSS_C_MA_MIC", + "mic", + "Mechanism supports Message Integrity Code (MIC) tokens.", + }, + { + oids+30, + "GSS_C_MA_WRAP", + "wrap", + "Mechanism supports wrap tokens.", + }, + { + oids+31, + "GSS_C_MA_PROT_READY", + "prot-ready", + "Mechanism supports per-message proteciton prior to " + "full context establishment.", + }, + { + oids+32, + "GSS_C_MA_REPLAY_DET", + "replay-detection", + "Mechanism supports replay detection.", + }, + { + oids+33, + "GSS_C_MA_OOS_DET", + "oos-detection", + "Mechanism supports out-of-sequence detection.", + }, + { + oids+34, + "GSS_C_MA_CBINDINGS", + "channel-bindings", + "Mechanism supports channel bindings.", + }, + { + oids+35, + "GSS_C_MA_PFS", + "pfs", + "Mechanism supports Perfect Forward Security.", + }, + { + oids+36, + "GSS_C_MA_COMPRESS", + "compress", + "Mechanism supports compression of data inputs to gss_wrap().", + }, + { + oids+37, + "GSS_C_MA_CTX_TRANS", + "context-transfer", + "Mechanism supports security context export/import.", + }, + { + oids+38, + "GSS_C_MA_NEGOEX_AND_SPNEGO", + "negoex-only", + "NegoEx mechanism should also be negotiable through SPNEGO.", + }, +}; + +OM_uint32 +generic_gss_display_mech_attr( + OM_uint32 *minor_status, + gss_const_OID mech_attr, + gss_buffer_t name, + gss_buffer_t short_desc, + gss_buffer_t long_desc) +{ + size_t i; + + if (minor_status != NULL) + *minor_status = 0; + if (name != GSS_C_NO_BUFFER) { + name->length = 0; + name->value = NULL; + } + if (short_desc != GSS_C_NO_BUFFER) { + short_desc->length = 0; + short_desc->value = NULL; + } + if (long_desc != GSS_C_NO_BUFFER) { + long_desc->length = 0; + long_desc->value = NULL; + } + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + for (i = 0; i < sizeof(mech_attr_info)/sizeof(mech_attr_info[0]); i++) { + struct mech_attr_info_desc *mai = &mech_attr_info[i]; + + if (g_OID_equal(mech_attr, mai->mech_attr)) { + if (name != GSS_C_NO_BUFFER && + !g_make_string_buffer(mai->name, name)) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + if (short_desc != GSS_C_NO_BUFFER && + !g_make_string_buffer(mai->short_desc, short_desc)) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + if (long_desc != GSS_C_NO_BUFFER && + !g_make_string_buffer(mai->long_desc, long_desc)) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + return GSS_S_COMPLETE; + } + } + + return GSS_S_BAD_MECH_ATTR; +} + +static gss_buffer_desc const_attrs[] = { + { sizeof("local-login-user") - 1, + "local-login-user" }, +}; + +GSS_DLLIMP gss_buffer_t GSS_C_ATTR_LOCAL_LOGIN_USER = &const_attrs[0]; diff --git a/krb5-1.21.3/src/lib/gssapi/generic/gssapi_generic.h b/krb5-1.21.3/src/lib/gssapi/generic/gssapi_generic.h new file mode 100644 index 00000000..e11f938c --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/gssapi_generic.h @@ -0,0 +1,59 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _GSSAPI_GENERIC_H_ +#define _GSSAPI_GENERIC_H_ + +/* + * $Id$ + */ + +#include + +#if defined(__cplusplus) && !defined(GSSAPIGENERIC_BEGIN_DECLS) +#define GSSAPIGENERIC_BEGIN_DECLS extern "C" { +#define GSSAPIGENERIC_END_DECLS } +#else +#define GSSAPIGENERIC_BEGIN_DECLS +#define GSSAPIGENERIC_END_DECLS +#endif + +#define GSS_EMPTY_BUFFER(buf) ((buf) == NULL || \ + (buf)->value == NULL || (buf)->length == 0) + +GSSAPIGENERIC_BEGIN_DECLS + +/* Deprecated MIT krb5 oid names provided for compatibility. + * The correct oids (GSS_C_NT_USER_NAME, etc) from rfc 2744 + * are defined in gssapi.h. */ + +GSS_DLLIMP extern gss_OID gss_nt_user_name; +GSS_DLLIMP extern gss_OID gss_nt_machine_uid_name; +GSS_DLLIMP extern gss_OID gss_nt_string_uid_name; +extern gss_OID gss_nt_service_name_v2; +GSS_DLLIMP extern gss_OID gss_nt_service_name; +extern gss_OID gss_nt_exported_name; + +GSSAPIGENERIC_END_DECLS + +#endif /* _GSSAPI_GENERIC_H_ */ diff --git a/krb5-1.21.3/src/lib/gssapi/generic/maptest.c b/krb5-1.21.3/src/lib/gssapi/generic/maptest.c new file mode 100644 index 00000000..566d88c3 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/maptest.c @@ -0,0 +1,68 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include +#include +#include + +typedef struct { int a, b; } elt; +static int eltcp(elt *dest, elt src) +{ + *dest = src; + return 0; +} +static int eltcmp(elt left, elt right) +{ + if (left.a < right.a) + return -1; + if (left.a > right.a) + return 1; + if (left.b < right.b) + return -1; + if (left.b > right.b) + return 1; + return 0; +} +static void eltprt(elt v, FILE *f) +{ + fprintf(f, "{%d,%d}", v.a, v.b); +} +static int intcmp(int left, int right) +{ + if (left < right) + return -1; + if (left > right) + return 1; + return 0; +} +static void intprt(int v, FILE *f) +{ + fprintf(f, "%d", v); +} + +#include "maptest.h" + +foo foo1; + +int main () +{ + elt v1 = { 1, 2 }, v2 = { 3, 4 }; + const elt *vp; + const int *ip; + + assert(0 == foo_init(&foo1)); + vp = foo_findleft(&foo1, 47); + assert(vp == NULL); + assert(0 == foo_add(&foo1, 47, v1)); + vp = foo_findleft(&foo1, 47); + assert(vp != NULL); + assert(0 == eltcmp(*vp, v1)); + vp = foo_findleft(&foo1, 3); + assert(vp == NULL); + assert(0 == foo_add(&foo1, 93, v2)); + ip = foo_findright(&foo1, v1); + assert(ip != NULL); + assert(*ip == 47); + printf("Map content: "); + foo_printmap(&foo1, stdout); + printf("\n"); + return 0; +} diff --git a/krb5-1.21.3/src/lib/gssapi/generic/oid_ops.c b/krb5-1.21.3/src/lib/gssapi/generic/oid_ops.c new file mode 100644 index 00000000..253d6469 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/oid_ops.c @@ -0,0 +1,553 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/generic/oid_ops.c */ +/* + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* GSS-API V2 interfaces to manipulate OIDs */ + +#include "gssapiP_generic.h" +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include +#include + +/* + * The functions for allocating and releasing individual OIDs use malloc and + * free instead of the gssalloc wrappers, because the mechglue currently mixes + * generic_gss_copy_oid() with hand-freeing of OIDs. We do not need to free + * free OIDs allocated by mechanisms, so this should not be a problem. + */ + +OM_uint32 +generic_gss_release_oid(OM_uint32 *minor_status, gss_OID *oid) +{ + if (minor_status) + *minor_status = 0; + + if (oid == NULL || *oid == GSS_C_NO_OID) + return(GSS_S_COMPLETE); + + /* + * The V2 API says the following! + * + * gss_release_oid[()] will recognize any of the GSSAPI's own OID values, + * and will silently ignore attempts to free these OIDs; for other OIDs + * it will call the C free() routine for both the OID data and the + * descriptor. This allows applications to freely mix their own heap- + * allocated OID values with OIDs returned by GSS-API. + */ + + /* + * We use the official OID definitions instead of the unofficial OID + * definitions. But we continue to support the unofficial OID + * gss_nt_service_name just in case if some gss applications use + * the old OID. + */ + + if ((*oid != GSS_C_NT_USER_NAME) && + (*oid != GSS_C_NT_MACHINE_UID_NAME) && + (*oid != GSS_C_NT_STRING_UID_NAME) && + (*oid != GSS_C_NT_HOSTBASED_SERVICE) && + (*oid != GSS_C_NT_ANONYMOUS) && + (*oid != GSS_C_NT_EXPORT_NAME) && + (*oid != GSS_C_NT_COMPOSITE_EXPORT) && + (*oid != gss_nt_service_name)) { + free((*oid)->elements); + free(*oid); + } + *oid = GSS_C_NO_OID; + return(GSS_S_COMPLETE); +} + +OM_uint32 +generic_gss_copy_oid(OM_uint32 *minor_status, + const gss_OID_desc * const oid, + gss_OID *new_oid) +{ + gss_OID p; + + *minor_status = 0; + + p = (gss_OID) malloc(sizeof(gss_OID_desc)); + if (!p) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + p->length = oid->length; + p->elements = malloc(p->length); + if (!p->elements) { + free(p); + return GSS_S_FAILURE; + } + memcpy(p->elements, oid->elements, p->length); + *new_oid = p; + return(GSS_S_COMPLETE); +} + + +OM_uint32 +generic_gss_create_empty_oid_set(OM_uint32 *minor_status, gss_OID_set *oid_set) +{ + *minor_status = 0; + + if (oid_set == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if ((*oid_set = (gss_OID_set) gssalloc_malloc(sizeof(gss_OID_set_desc)))) { + memset(*oid_set, 0, sizeof(gss_OID_set_desc)); + return(GSS_S_COMPLETE); + } + else { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } +} + +OM_uint32 +generic_gss_add_oid_set_member(OM_uint32 *minor_status, + const gss_OID_desc * const member_oid, + gss_OID_set *oid_set) +{ + gss_OID elist; + gss_OID lastel; + + *minor_status = 0; + + if (member_oid == NULL || member_oid->length == 0 || + member_oid->elements == NULL) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (oid_set == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + elist = (*oid_set)->elements; + /* Get an enlarged copy of the array */ + if (((*oid_set)->elements = (gss_OID) gssalloc_malloc(((*oid_set)->count+1) * + sizeof(gss_OID_desc)))) { + /* Copy in the old junk */ + if (elist) + memcpy((*oid_set)->elements, + elist, + ((*oid_set)->count * sizeof(gss_OID_desc))); + + /* Duplicate the input element */ + lastel = &(*oid_set)->elements[(*oid_set)->count]; + if ((lastel->elements = + (void *) gssalloc_malloc((size_t) member_oid->length))) { + /* Success - copy elements */ + memcpy(lastel->elements, member_oid->elements, + (size_t) member_oid->length); + /* Set length */ + lastel->length = member_oid->length; + + /* Update count */ + (*oid_set)->count++; + if (elist) + gssalloc_free(elist); + *minor_status = 0; + return(GSS_S_COMPLETE); + } + else + gssalloc_free((*oid_set)->elements); + } + /* Failure - restore old contents of list */ + (*oid_set)->elements = elist; + *minor_status = ENOMEM; + return(GSS_S_FAILURE); +} + +OM_uint32 +generic_gss_test_oid_set_member(OM_uint32 *minor_status, + const gss_OID_desc * const member, + gss_OID_set set, + int * present) +{ + OM_uint32 i; + int result; + + *minor_status = 0; + + if (member == NULL || set == NULL) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (present == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + result = 0; + for (i=0; icount; i++) { + if ((set->elements[i].length == member->length) && + !memcmp(set->elements[i].elements, + member->elements, + (size_t) member->length)) { + result = 1; + break; + } + } + *present = result; + return(GSS_S_COMPLETE); +} + +OM_uint32 +generic_gss_oid_to_str(OM_uint32 *minor_status, + const gss_OID_desc * const oid, + gss_buffer_t oid_str) +{ + unsigned long number, n; + OM_uint32 i; + int first; + unsigned char *cp; + struct k5buf buf; + + if (minor_status != NULL) + *minor_status = 0; + + if (oid_str != GSS_C_NO_BUFFER) { + oid_str->length = 0; + oid_str->value = NULL; + } + + if (oid == NULL || oid->length == 0 || oid->elements == NULL) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (oid_str == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + /* Decoded according to krb5/gssapi_krb5.c */ + + cp = (unsigned char *) oid->elements; + number = (unsigned long) cp[0]; + k5_buf_init_dynamic(&buf); + k5_buf_add(&buf, "{ "); + number = 0; + cp = (unsigned char *) oid->elements; + first = 1; + for (i = 0; i < oid->length; i++) { + number = (number << 7) | (cp[i] & 0x7f); + if ((cp[i] & 0x80) == 0) { + if (first) { + n = (number < 40) ? 0 : (number < 80) ? 1 : 2; + k5_buf_add_fmt(&buf, "%lu %lu ", n, number - (n * 40)); + first = 0; + } else { + k5_buf_add_fmt(&buf, "%lu ", number); + } + number = 0; + } + } + k5_buf_add_len(&buf, "}\0", 2); + return k5buf_to_gss(minor_status, &buf, oid_str); +} + +/* Return the length of a DER OID subidentifier encoding. */ +static size_t +arc_encoded_length(unsigned long arc) +{ + size_t len = 1; + + for (arc >>= 7; arc; arc >>= 7) + len++; + return len; +} + +/* Encode a subidentifier into *bufp and advance it to the encoding's end. */ +static void +arc_encode(unsigned long arc, unsigned char **bufp) +{ + unsigned char *p; + + /* Advance to the end and encode backwards. */ + p = *bufp = *bufp + arc_encoded_length(arc); + *--p = arc & 0x7f; + for (arc >>= 7; arc; arc >>= 7) + *--p = (arc & 0x7f) | 0x80; +} + +/* Fetch an arc value from *bufp and advance past it and any following spaces + * or periods. Return 1 on success, 0 if *bufp is not at a valid arc value. */ +static int +get_arc(const unsigned char **bufp, const unsigned char *end, + unsigned long *arc_out) +{ + const unsigned char *p = *bufp; + unsigned long arc = 0, newval; + + if (p == end || !isdigit(*p)) + return 0; + for (; p < end && isdigit(*p); p++) { + newval = arc * 10 + (*p - '0'); + if (newval < arc) + return 0; + arc = newval; + } + while (p < end && (isspace(*p) || *p == '.')) + p++; + *bufp = p; + *arc_out = arc; + return 1; +} + +/* + * Convert a sequence of two or more decimal arc values into a DER-encoded OID. + * The values may be separated by any combination of whitespace and period + * characters, and may be optionally surrounded with braces. Leading + * whitespace and trailing garbage is allowed. The first arc value must be 0, + * 1, or 2, and the second value must be less than 40 if the first value is not + * 2. + */ +OM_uint32 +generic_gss_str_to_oid(OM_uint32 *minor_status, + gss_buffer_t oid_str, + gss_OID *oid_out) +{ + const unsigned char *p, *end, *arc3_start; + unsigned char *out; + unsigned long arc, arc1, arc2; + size_t nbytes; + int brace = 0; + gss_OID oid; + + if (minor_status != NULL) + *minor_status = 0; + + if (oid_out != NULL) + *oid_out = GSS_C_NO_OID; + + if (GSS_EMPTY_BUFFER(oid_str)) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (oid_out == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + /* Skip past initial spaces and, optionally, an open brace. */ + brace = 0; + p = oid_str->value; + end = p + oid_str->length; + while (p < end && isspace(*p)) + p++; + if (p < end && *p == '{') { + brace = 1; + p++; + } + while (p < end && isspace(*p)) + p++; + + /* Get the first two arc values, to be encoded as one subidentifier. */ + if (!get_arc(&p, end, &arc1) || !get_arc(&p, end, &arc2)) + return (GSS_S_FAILURE); + if (arc1 > 2 || (arc1 < 2 && arc2 > 39) || arc2 > ULONG_MAX - 80) + return (GSS_S_FAILURE); + arc3_start = p; + + /* Compute the total length of the encoding while checking syntax. */ + nbytes = arc_encoded_length(arc1 * 40 + arc2); + while (get_arc(&p, end, &arc)) + nbytes += arc_encoded_length(arc); + if (brace && (p == end || *p != '}')) + return (GSS_S_FAILURE); + + /* Allocate an oid structure. */ + oid = malloc(sizeof(*oid)); + if (oid == NULL) + return (GSS_S_FAILURE); + oid->elements = malloc(nbytes); + if (oid->elements == NULL) { + free(oid); + return (GSS_S_FAILURE); + } + oid->length = nbytes; + + out = oid->elements; + arc_encode(arc1 * 40 + arc2, &out); + p = arc3_start; + while (get_arc(&p, end, &arc)) + arc_encode(arc, &out); + assert(out - nbytes == oid->elements); + *oid_out = oid; + return(GSS_S_COMPLETE); +} + +/* Compose an OID of a prefix and an integer suffix */ +OM_uint32 +generic_gss_oid_compose(OM_uint32 *minor_status, + const char *prefix, + size_t prefix_len, + int suffix, + gss_OID_desc *oid) +{ + int osuffix, i; + size_t nbytes; + unsigned char *op; + + if (oid == GSS_C_NO_OID) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + if (oid->length < prefix_len) { + *minor_status = ERANGE; + return GSS_S_FAILURE; + } + + memcpy(oid->elements, prefix, prefix_len); + + nbytes = 0; + osuffix = suffix; + while (suffix) { + nbytes++; + suffix >>= 7; + } + suffix = osuffix; + + if (oid->length < prefix_len + nbytes) { + *minor_status = ERANGE; + return GSS_S_FAILURE; + } + + op = (unsigned char *) oid->elements + prefix_len + nbytes; + i = -1; + while (suffix) { + op[i] = (unsigned char)suffix & 0x7f; + if (i != -1) + op[i] |= 0x80; + i--; + suffix >>= 7; + } + + oid->length = prefix_len + nbytes; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +generic_gss_oid_decompose(OM_uint32 *minor_status, + const char *prefix, + size_t prefix_len, + gss_OID_desc *oid, + int *suffix) +{ + size_t i, slen; + unsigned char *op; + + if (oid->length < prefix_len || + memcmp(oid->elements, prefix, prefix_len) != 0) { + return GSS_S_BAD_MECH; + } + + op = (unsigned char *) oid->elements + prefix_len; + + *suffix = 0; + + slen = oid->length - prefix_len; + + for (i = 0; i < slen; i++) { + *suffix = (*suffix << 7) | (op[i] & 0x7f); + if (i + 1 != slen && (op[i] & 0x80) == 0) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +generic_gss_copy_oid_set(OM_uint32 *minor_status, + const gss_OID_set_desc * const oidset, + gss_OID_set *new_oidset) +{ + gss_OID_set_desc *copy; + OM_uint32 minor = 0; + OM_uint32 major = GSS_S_COMPLETE; + OM_uint32 i; + + if (minor_status != NULL) + *minor_status = 0; + + if (new_oidset != NULL) + *new_oidset = GSS_C_NO_OID_SET; + + if (oidset == GSS_C_NO_OID_SET) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (new_oidset == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if ((copy = (gss_OID_set_desc *) gssalloc_calloc(1, sizeof (*copy))) == NULL) { + major = GSS_S_FAILURE; + goto done; + } + + if ((copy->elements = (gss_OID_desc *) + gssalloc_calloc(oidset->count, sizeof (*copy->elements))) == NULL) { + major = GSS_S_FAILURE; + goto done; + } + copy->count = oidset->count; + + for (i = 0; i < copy->count; i++) { + gss_OID_desc *out = ©->elements[i]; + gss_OID_desc *in = &oidset->elements[i]; + + if ((out->elements = (void *) gssalloc_malloc(in->length)) == NULL) { + major = GSS_S_FAILURE; + goto done; + } + (void) memcpy(out->elements, in->elements, in->length); + out->length = in->length; + } + + *new_oidset = copy; +done: + if (major != GSS_S_COMPLETE) { + (void) generic_gss_release_oid_set(&minor, ©); + } + + return (major); +} diff --git a/krb5-1.21.3/src/lib/gssapi/generic/rel_buffer.c b/krb5-1.21.3/src/lib/gssapi/generic/rel_buffer.c new file mode 100644 index 00000000..44dc9815 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/rel_buffer.c @@ -0,0 +1,57 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* #ident "@(#)g_rel_buffer.c 1.2 96/02/06 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_release_buffer + */ + +#include "gssapiP_generic.h" + +#include +#ifdef HAVE_STDLIB_H +#include +#endif + +OM_uint32 +generic_gss_release_buffer( + OM_uint32 *minor_status, + gss_buffer_t buffer) +{ + if (minor_status) + *minor_status = 0; + + /* if buffer is NULL, return */ + + if (buffer == GSS_C_NO_BUFFER) + return(GSS_S_COMPLETE); + + if (buffer->value) { + gssalloc_free(buffer->value); + buffer->length = 0; + buffer->value = NULL; + } + + return (GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/generic/rel_oid_set.c b/krb5-1.21.3/src/lib/gssapi/generic/rel_oid_set.c new file mode 100644 index 00000000..954542e4 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/rel_oid_set.c @@ -0,0 +1,61 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* #ident "@(#)gss_release_oid_set.c 1.12 95/08/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_release_oid_set + */ + +#include "gssapiP_generic.h" + +#include +#ifdef HAVE_STDLIB_H +#include +#endif + +OM_uint32 +generic_gss_release_oid_set( + OM_uint32 *minor_status, + gss_OID_set *set) +{ + size_t i; + if (minor_status) + *minor_status = 0; + + if (set == NULL) + return(GSS_S_COMPLETE); + + if (*set == GSS_C_NULL_OID_SET) + return(GSS_S_COMPLETE); + + for (i=0; i<(*set)->count; i++) + gssalloc_free((*set)->elements[i].elements); + + gssalloc_free((*set)->elements); + gssalloc_free(*set); + + *set = GSS_C_NULL_OID_SET; + + return(GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/generic/t_seqstate.c b/krb5-1.21.3/src/lib/gssapi/generic/t_seqstate.c new file mode 100644 index 00000000..8f44fcf3 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/t_seqstate.c @@ -0,0 +1,197 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/generic/t_seqstate.c - Test program for sequence number state */ +/* + * Copyright (C) 2014 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. + */ + +#include "gssapiP_generic.h" + +enum resultcode { + NOERR = GSS_S_COMPLETE, + GAP = GSS_S_GAP_TOKEN, + UNSEQ = GSS_S_UNSEQ_TOKEN, + OLD = GSS_S_OLD_TOKEN, + REPLAY = GSS_S_DUPLICATE_TOKEN +}; + +enum replayflag { NO_REPLAY = 0, DO_REPLAY = 1 }; +enum sequenceflag { NO_SEQUENCE = 0, DO_SEQUENCE = 1 }; +enum width { NARROW = 0, WIDE = 1, BOTH = 2 }; + +struct test { + uint64_t initial; + enum replayflag do_replay; + enum sequenceflag do_sequence; + enum width wide_seqnums; + size_t nseqs; + struct { + uint64_t seqnum; + enum resultcode result; + } seqs[10]; +} tests[] = { + /* No replay or sequence checking. */ + { + 10, NO_REPLAY, NO_SEQUENCE, BOTH, + 4, { { 11, NOERR }, { 10, NOERR }, { 10, NOERR }, { 9, NOERR } } + }, + + /* Basic sequence checking, no wraparound. */ + { + 100, NO_REPLAY, DO_SEQUENCE, BOTH, + 4, { { 100, NOERR }, { 102, GAP }, { 103, NOERR }, { 101, UNSEQ } } + }, + + /* Initial gap sequence checking, no wraparound. */ + { + 200, NO_REPLAY, DO_SEQUENCE, BOTH, + 4, { { 201, GAP }, { 202, NOERR }, { 200, UNSEQ }, { 203, NOERR } } + }, + + /* Sequence checking with wraparound. */ + { + UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, NARROW, + 4, { { UINT32_MAX - 1, NOERR }, { UINT32_MAX, NOERR }, { 0, NOERR }, + { 1, NOERR } } + }, + { + UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, NARROW, + 4, { { UINT32_MAX - 1, NOERR }, { 0, GAP }, { UINT32_MAX, UNSEQ }, + { 1, NOERR } } + }, + { + UINT64_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE, + 4, { { UINT64_MAX - 1, NOERR }, { UINT64_MAX, NOERR }, { 0, NOERR }, + { 1, NOERR } } + }, + { + UINT64_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE, + 4, { { UINT64_MAX - 1, NOERR }, { 0, GAP }, { UINT64_MAX, UNSEQ }, + { 1, NOERR } } + }, + + /* 64-bit sequence checking beyond 32-bit range */ + { + UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE, + 4, { { UINT32_MAX - 1, NOERR }, + { UINT32_MAX, NOERR }, + { (uint64_t)UINT32_MAX + 1, NOERR }, + { (uint64_t)UINT32_MAX + 2, NOERR } } + }, + { + UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE, + 4, { { UINT32_MAX - 1, NOERR }, + { (uint64_t)UINT32_MAX + 1, GAP }, + { UINT32_MAX, UNSEQ }, + { (uint64_t)UINT32_MAX + 2, NOERR } } + }, + { + UINT32_MAX - 1, NO_REPLAY, DO_SEQUENCE, WIDE, + 3, { { UINT32_MAX - 1, NOERR }, { UINT32_MAX, NOERR }, { 0, GAP } } + }, + + /* Replay without the replay flag set. */ + { + 250, NO_REPLAY, DO_SEQUENCE, BOTH, + 2, { { 250, NOERR }, { 250, UNSEQ } } + }, + + /* Basic replay detection with and without sequence checking. */ + { + 0, DO_REPLAY, DO_SEQUENCE, BOTH, + 10, { { 5, GAP }, { 3, UNSEQ }, { 8, GAP }, { 3, REPLAY }, + { 0, UNSEQ }, { 0, REPLAY }, { 5, REPLAY }, { 3, REPLAY }, + { 8, REPLAY }, { 9, NOERR } } + }, + { + 0, DO_REPLAY, NO_SEQUENCE, BOTH, + 10, { { 5, NOERR }, { 3, NOERR }, { 8, NOERR }, { 3, REPLAY }, + { 0, NOERR }, { 0, REPLAY }, { 5, REPLAY }, { 3, REPLAY }, + { 8, REPLAY }, { 9, NOERR } } + }, + + /* Replay and sequence detection with wraparound. The last seqnum produces + * GAP because it is before the initial sequence number. */ + { + UINT64_MAX - 5, DO_REPLAY, DO_SEQUENCE, WIDE, + 10, { { UINT64_MAX, GAP }, { UINT64_MAX - 2, UNSEQ }, { 0, NOERR }, + { UINT64_MAX, REPLAY }, { UINT64_MAX, REPLAY }, + { 2, GAP }, { 0, REPLAY }, { 1, UNSEQ }, + { UINT64_MAX - 2, REPLAY }, { UINT64_MAX - 6, GAP } } + }, + { + UINT32_MAX - 5, DO_REPLAY, DO_SEQUENCE, NARROW, + 10, { { UINT32_MAX, GAP }, { UINT32_MAX - 2, UNSEQ }, { 0, NOERR }, + { UINT32_MAX, REPLAY }, { UINT32_MAX, REPLAY }, + { 2, GAP }, { 0, REPLAY }, { 1, UNSEQ }, + { UINT32_MAX - 2, REPLAY }, { UINT32_MAX - 6, GAP } } + }, + + /* Old token edge cases. The current code can detect replays up to 64 + * numbers behind the expected sequence number (1164 in this case). */ + { + 1000, DO_REPLAY, NO_SEQUENCE, BOTH, + 10, { { 1163, NOERR }, { 1100, NOERR }, { 1100, REPLAY }, + { 1163, REPLAY }, { 1099, OLD }, { 1100, REPLAY }, + { 1150, NOERR }, { 1150, REPLAY }, { 1000, OLD }, + { 999, NOERR } } + }, +}; + +int +main() +{ + size_t i, j; + enum width w; + struct test *t; + g_seqnum_state seqstate; + OM_uint32 status; + + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { + t = &tests[i]; + /* Try both widths if t->wide_seqnums is both, otherwise just one. */ + for (w = NARROW; w <= WIDE; w++) { + if (t->wide_seqnums != BOTH && t->wide_seqnums != w) + continue; + if (g_seqstate_init(&seqstate, t->initial, t->do_replay, + t->do_sequence, w)) + abort(); + for (j = 0; j < t->nseqs; j++) { + status = g_seqstate_check(seqstate, t->seqs[j].seqnum); + if (status != t->seqs[j].result) { + fprintf(stderr, "Test %d seq %d failed: %d != %d\n", + (int)i, (int)j, status, t->seqs[j].result); + return 1; + } + } + g_seqstate_free(seqstate); + } + } + + return 0; +} diff --git a/krb5-1.21.3/src/lib/gssapi/generic/util_buffer.c b/krb5-1.21.3/src/lib/gssapi/generic/util_buffer.c new file mode 100644 index 00000000..da2d8329 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/util_buffer.c @@ -0,0 +1,48 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * $Id$ + */ + +#include "gssapiP_generic.h" +#include + +/* return nonzero on success, 0 on failure + make sure that buffer is consistent (release'able) when this + function exits, no matter what the exit value */ + +int g_make_string_buffer(const char *str, gss_buffer_t buffer) +{ + if (buffer == GSS_C_NO_BUFFER) + return (1); + + buffer->length = strlen(str); + + if ((buffer->value = gssalloc_strdup(str)) == NULL) { + buffer->length = 0; + return(0); + } + + return(1); +} diff --git a/krb5-1.21.3/src/lib/gssapi/generic/util_buffer_set.c b/krb5-1.21.3/src/lib/gssapi/generic/util_buffer_set.c new file mode 100644 index 00000000..f7472a08 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/util_buffer_set.c @@ -0,0 +1,126 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +#include "gssapiP_generic.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +OM_uint32 +generic_gss_create_empty_buffer_set(OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + gss_buffer_set_t set; + + set = (gss_buffer_set_desc *) gssalloc_malloc(sizeof(*set)); + if (set == GSS_C_NO_BUFFER_SET) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + set->count = 0; + set->elements = NULL; + + *buffer_set = set; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +generic_gss_add_buffer_set_member(OM_uint32 * minor_status, + const gss_buffer_t member_buffer, + gss_buffer_set_t *buffer_set) +{ + gss_buffer_set_t set; + gss_buffer_t p; + OM_uint32 ret; + + if (*buffer_set == GSS_C_NO_BUFFER_SET) { + ret = generic_gss_create_empty_buffer_set(minor_status, + buffer_set); + if (ret) { + return ret; + } + } + + set = *buffer_set; + set->elements = (gss_buffer_desc *)gssalloc_realloc(set->elements, + (set->count + 1) * + sizeof(gss_buffer_desc)); + if (set->elements == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = &set->elements[set->count]; + + p->value = gssalloc_malloc(member_buffer->length); + if (p->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(p->value, member_buffer->value, member_buffer->length); + p->length = member_buffer->length; + + set->count++; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +generic_gss_release_buffer_set(OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + size_t i; + OM_uint32 minor; + + *minor_status = 0; + + if (*buffer_set == GSS_C_NO_BUFFER_SET) { + return GSS_S_COMPLETE; + } + + for (i = 0; i < (*buffer_set)->count; i++) { + generic_gss_release_buffer(&minor, &((*buffer_set)->elements[i])); + } + + if ((*buffer_set)->elements != NULL) { + gssalloc_free((*buffer_set)->elements); + (*buffer_set)->elements = NULL; + } + + (*buffer_set)->count = 0; + + gssalloc_free(*buffer_set); + *buffer_set = GSS_C_NO_BUFFER_SET; + + return GSS_S_COMPLETE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/generic/util_errmap.c b/krb5-1.21.3/src/lib/gssapi/generic/util_errmap.c new file mode 100644 index 00000000..628a455d --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/util_errmap.c @@ -0,0 +1,264 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +#include "gssapiP_generic.h" +#include +#ifndef _WIN32 +#include +#endif + +/* The mapping table is 0-based, but let's export codes that are + 1-based, keeping 0 for errors or unknown errors. + + The elements in the mapping table currently have separate copies of + each OID stored. This is a bit wasteful, but we are assuming the + table isn't likely to grow very large. */ + +struct mecherror { + gss_OID_desc mech; + OM_uint32 code; +}; + +static inline int +cmp_OM_uint32(OM_uint32 m1, OM_uint32 m2) +{ + if (m1 < m2) + return -1; + else if (m1 > m2) + return 1; + else + return 0; +} + +static inline int +mecherror_cmp(struct mecherror m1, struct mecherror m2) +{ + if (m1.code < m2.code) + return -1; + if (m1.code > m2.code) + return 1; + if (m1.mech.length < m2.mech.length) + return -1; + if (m1.mech.length > m2.mech.length) + return 1; + if (m1.mech.length == 0) + return 0; + return memcmp(m1.mech.elements, m2.mech.elements, m1.mech.length); +} + +static void +print_OM_uint32 (OM_uint32 value, FILE *f) +{ + fprintf(f, "%lu", (unsigned long) value); +} + +static inline int +mecherror_copy(struct mecherror *dest, struct mecherror src) +{ + *dest = src; + if (src.mech.length > 0) { + dest->mech.elements = malloc(src.mech.length); + if (dest->mech.elements == NULL) + return ENOMEM; + memcpy(dest->mech.elements, src.mech.elements, src.mech.length); + } else { + dest->mech.elements = NULL; + } + return 0; +} + +static void +mecherror_print(struct mecherror value, FILE *f) +{ + OM_uint32 minor; + gss_buffer_desc str; + static const struct { + const char *oidstr, *name; + } mechnames[] = { + { "{ 1 2 840 113554 1 2 2 }", "krb5-new" }, + { "{ 1 3 5 1 5 2 }", "krb5-old" }, + { "{ 1 2 840 48018 1 2 2 }", "krb5-microsoft" }, + { "{ 1 3 6 1 5 5 2 }", "spnego" }, + }; + unsigned int i; + + fprintf(f, "%lu@", (unsigned long) value.code); + + if (value.mech.length == 0) { + fprintf(f, "(com_err)"); + return; + } + fprintf(f, "%p=", value.mech.elements); + if (generic_gss_oid_to_str(&minor, &value.mech, &str)) { + fprintf(f, "(error in conversion)"); + return; + } + /* Note: generic_gss_oid_to_str returns a null-terminated string. */ + for (i = 0; i < sizeof(mechnames)/sizeof(mechnames[0]); i++) { + if (!strcmp(str.value, mechnames[i].oidstr) && mechnames[i].name != 0) { + fprintf(f, "%s", mechnames[i].name); + break; + } + } + if (i == sizeof(mechnames)/sizeof(mechnames[0])) + fprintf(f, "%s", (char *) str.value); + generic_gss_release_buffer(&minor, &str); +} + +#include "errmap.h" +#include "krb5.h" /* for KRB5KRB_AP_WRONG_PRINC */ + +static mecherrmap m; +static k5_mutex_t mutex = K5_MUTEX_PARTIAL_INITIALIZER; +static OM_uint32 next_fake = 100000; + +int gssint_mecherrmap_init(void) +{ + int err; + + err = mecherrmap_init(&m); + if (err) + return err; + err = k5_mutex_finish_init(&mutex); + if (err) { + mecherrmap_destroy(&m); + return err; + } + + return 0; +} + +/* Currently the enumeration template doesn't handle freeing + element storage when destroying the collection. */ +static int free_one(OM_uint32 i, struct mecherror value, void *p) +{ + free(value.mech.elements); + return 0; +} + +void gssint_mecherrmap_destroy(void) +{ + mecherrmap_foreach(&m, free_one, NULL); + mecherrmap_destroy(&m); + k5_mutex_destroy(&mutex); +} + +OM_uint32 gssint_mecherrmap_map(OM_uint32 minor, const gss_OID_desc * oid) +{ + const struct mecherror *mep; + struct mecherror me, me_copy; + const OM_uint32 *p; + int err; + OM_uint32 new_status; + +#ifdef DEBUG + FILE *f; + f = fopen("/dev/pts/9", "w+"); + if (f == NULL) + f = stderr; +#endif + + me.code = minor; + me.mech = *oid; + k5_mutex_lock(&mutex); + + /* Is this status+oid already mapped? */ + p = mecherrmap_findright(&m, me); + if (p != NULL) { + k5_mutex_unlock(&mutex); +#ifdef DEBUG + fprintf(f, "%s: found ", __FUNCTION__); + mecherror_print(me, f); + fprintf(f, " in map as %lu\n", (unsigned long) *p); + if (f != stderr) fclose(f); +#endif + return *p; + } + /* Is this status code already mapped to something else + mech-specific? */ + mep = mecherrmap_findleft(&m, minor); + if (mep == NULL) { + /* Map it to itself plus this mech-oid. */ + new_status = minor; + } else { + /* Already assigned. Pick a fake new value and map it. */ + /* There's a theoretical infinite loop risk here, if we fill + in 2**32 values. Also, returning 0 has a special + meaning. */ + do { + next_fake++; + new_status = next_fake; + if (new_status == 0) + /* ??? */; + } while (mecherrmap_findleft(&m, new_status) != NULL); + } + err = mecherror_copy(&me_copy, me); + if (err) { + k5_mutex_unlock(&mutex); + return err; + } + err = mecherrmap_add(&m, new_status, me_copy); + k5_mutex_unlock(&mutex); + if (err) + free(me_copy.mech.elements); +#ifdef DEBUG + fprintf(f, "%s: mapping ", __FUNCTION__); + mecherror_print(me, f); + fprintf(f, " to %lu: err=%d\nnew map: ", (unsigned long) new_status, err); + mecherrmap_printmap(&m, f); + fprintf(f, "\n"); + if (f != stderr) fclose(f); +#endif + if (err) + return 0; + else + return new_status; +} + +static gss_OID_desc no_oid = { 0, 0 }; +OM_uint32 gssint_mecherrmap_map_errcode(OM_uint32 errcode) +{ + return gssint_mecherrmap_map(errcode, &no_oid); +} + +int gssint_mecherrmap_get(OM_uint32 minor, gss_OID mech_oid, + OM_uint32 *mech_minor) +{ + const struct mecherror *p; + + if (minor == 0) { + return EINVAL; + } + k5_mutex_lock(&mutex); + p = mecherrmap_findleft(&m, minor); + k5_mutex_unlock(&mutex); + if (!p) { + return EINVAL; + } + *mech_oid = p->mech; + *mech_minor = p->code; + return 0; +} diff --git a/krb5-1.21.3/src/lib/gssapi/generic/util_seqstate.c b/krb5-1.21.3/src/lib/gssapi/generic/util_seqstate.c new file mode 100644 index 00000000..a0bc2cc1 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/util_seqstate.c @@ -0,0 +1,163 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/generic/util_seqstate.c - sequence number checking */ +/* + * Copyright (C) 2014 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. + */ + +#include "gssapiP_generic.h" +#include + +struct g_seqnum_state_st { + /* Flags to indicate whether we are supposed to check for replays or + * enforce strict sequencing. */ + int do_replay; + int do_sequence; + + /* UINT32_MAX for 32-bit sequence numbers, UINT64_MAX for 64-bit. Mask + * against this after arithmetic to stay within the correct range. */ + uint64_t seqmask; + + /* The initial sequence number for this context. This value will be + * subtracted from all received sequence numbers to simplify wraparound. */ + uint64_t base; + + /* The expected next sequence number (one more than the highest previously + * seen sequence number), relative to base. */ + uint64_t next; + + /* + * A bitmap for the 64 sequence numbers prior to next. If the 1<<(i-1) bit + * is set, then we have seen seqnum next-i relative to base. The least + * significant bit is always set if we have received any sequence numbers, + * and indicates the highest sequence number we have seen (next-1). When + * we advance next, we shift recvmap to the left. + */ + uint64_t recvmap; +}; + +long +g_seqstate_init(g_seqnum_state *state_out, uint64_t seqnum, int do_replay, + int do_sequence, int wide) +{ + g_seqnum_state state; + + *state_out = NULL; + state = malloc(sizeof(*state)); + if (state == NULL) + return ENOMEM; + state->do_replay = do_replay; + state->do_sequence = do_sequence; + state->seqmask = wide ? UINT64_MAX : UINT32_MAX; + state->base = seqnum; + state->next = state->recvmap = 0; + *state_out = state; + return 0; +} + +OM_uint32 +g_seqstate_check(g_seqnum_state state, uint64_t seqnum) +{ + uint64_t rel_seqnum, offset, bit; + + if (!state->do_replay && !state->do_sequence) + return GSS_S_COMPLETE; + + /* Use the difference from the base seqnum, to simplify wraparound. */ + rel_seqnum = (seqnum - state->base) & state->seqmask; + + if (rel_seqnum >= state->next) { + /* seqnum is the expected sequence number or in the future. Update the + * received bitmap and expected next sequence number. */ + offset = rel_seqnum - state->next; + state->recvmap = (state->recvmap << (offset + 1)) | 1; + state->next = (rel_seqnum + 1) & state->seqmask; + + return (offset > 0 && state->do_sequence) ? GSS_S_GAP_TOKEN : + GSS_S_COMPLETE; + } + + /* seqnum is in the past. Check if it's too old for replay detection. */ + offset = state->next - rel_seqnum; + if (offset > 64) + return state->do_sequence ? GSS_S_UNSEQ_TOKEN : GSS_S_OLD_TOKEN; + + /* Check for replay and mark as received. */ + bit = (uint64_t)1 << (offset - 1); + if (state->do_replay && (state->recvmap & bit)) + return GSS_S_DUPLICATE_TOKEN; + state->recvmap |= bit; + + return state->do_sequence ? GSS_S_UNSEQ_TOKEN : GSS_S_COMPLETE; +} + +void +g_seqstate_free(g_seqnum_state state) +{ + free(state); +} + +/* + * These support functions are for the serialization routines + */ +void +g_seqstate_size(g_seqnum_state state, size_t *sizep) +{ + *sizep += sizeof(*state); +} + +long +g_seqstate_externalize(g_seqnum_state state, unsigned char **buf, + size_t *lenremain) +{ + if (*lenremain < sizeof(*state)) + return ENOMEM; + memcpy(*buf, state, sizeof(*state)); + *buf += sizeof(*state); + *lenremain -= sizeof(*state); + return 0; +} + +long +g_seqstate_internalize(g_seqnum_state *state_out, unsigned char **buf, + size_t *lenremain) +{ + g_seqnum_state state; + + *state_out = NULL; + if (*lenremain < sizeof(*state)) + return EINVAL; + state = malloc(sizeof(*state)); + if (state == NULL) + return ENOMEM; + memcpy(state, *buf, sizeof(*state)); + *buf += sizeof(*state); + *lenremain -= sizeof(*state); + *state_out = state; + return 0; +} diff --git a/krb5-1.21.3/src/lib/gssapi/generic/util_set.c b/krb5-1.21.3/src/lib/gssapi/generic/util_set.c new file mode 100644 index 00000000..432a9ee0 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/util_set.c @@ -0,0 +1,91 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1995 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * $Id$ + */ + +#include "gssapiP_generic.h" + +struct _g_set_elt { + void *key; + void *value; + struct _g_set_elt *next; +}; + +int g_set_init(g_set_elt *s) +{ + *s = NULL; + + return(0); +} + +int g_set_entry_add(g_set_elt *s, void *key, void *value) +{ + g_set_elt first; + + if ((first = (struct _g_set_elt *) malloc(sizeof(struct _g_set_elt))) == NULL) + return(ENOMEM); + + first->key = key; + first->value = value; + first->next = *s; + + *s = first; + + return(0); +} + +int g_set_entry_delete(g_set_elt *s, void *key) +{ + g_set_elt *p; + + for (p=s; *p; p = &((*p)->next)) { + if ((*p)->key == key) { + g_set_elt next = (*p)->next; + free(*p); + *p = next; + + return(0); + } + } + + return(-1); +} + +int g_set_entry_get(g_set_elt *s, void *key, void **value) +{ + g_set_elt p; + + for (p = *s; p; p = p->next) { + if (p->key == key) { + *value = p->value; + + return(0); + } + } + + *value = NULL; + + return(-1); +} diff --git a/krb5-1.21.3/src/lib/gssapi/generic/util_token.c b/krb5-1.21.3/src/lib/gssapi/generic/util_token.c new file mode 100644 index 00000000..2369cae2 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/generic/util_token.c @@ -0,0 +1,108 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "gssapiP_generic.h" +#include "k5-der.h" +#ifdef HAVE_MEMORY_H +#include +#endif +#include + +/* + * $Id$ + */ + +/* Return the length of an RFC 4121 token with RFC 2743 token framing, given + * the mech oid and the body size (without the two-byte RFC 4121 token ID). */ +unsigned int +g_token_size(const gss_OID_desc * mech, unsigned int body_size) +{ + size_t mech_der_len = k5_der_value_len(mech->length); + + return k5_der_value_len(mech_der_len + 2 + body_size); +} + +/* + * Add RFC 2743 generic token framing to buf with room left for body_size bytes + * in the sequence to be added by the caller. If tok_type is not -1, add it as + * a two-byte RFC 4121 token identifier after the framing and include room for + * it in the sequence. + */ +void +g_make_token_header(struct k5buf *buf, const gss_OID_desc *mech, + size_t body_size, int tok_type) +{ + size_t tok_len = (tok_type == -1) ? 0 : 2; + size_t seq_len = k5_der_value_len(mech->length) + body_size + tok_len; + + k5_der_add_taglen(buf, 0x60, seq_len); + k5_der_add_value(buf, 0x06, mech->elements, mech->length); + if (tok_type != -1) + k5_buf_add_uint16_be(buf, tok_type); +} + +/* + * Given a buffer containing a token, reads and verifies the token, + * leaving buf advanced past the token header, and setting body_size + * to the number of remaining bytes. Returns 0 on success, + * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the + * mechanism in the token does not match the mech argument. buf and + * *body_size are left unmodified on error. + */ + +gss_int32 +g_verify_token_header( + const gss_OID_desc * mech, + unsigned int *body_size, + unsigned char **buf_in, + int tok_type, + unsigned int toksize_in, + int flags) +{ + struct k5input in, mech_der; + gss_OID_desc toid; + + k5_input_init(&in, *buf_in, toksize_in); + + if (k5_der_get_value(&in, 0x60, &in)) { + if (in.ptr + in.len != *buf_in + toksize_in) + return G_BAD_TOK_HEADER; + if (!k5_der_get_value(&in, 0x06, &mech_der)) + return G_BAD_TOK_HEADER; + toid.elements = (uint8_t *)mech_der.ptr; + toid.length = mech_der.len; + if (!g_OID_equal(&toid, mech)) + return G_WRONG_MECH; + } else if (flags & G_VFY_TOKEN_HDR_WRAPPER_REQUIRED) { + return G_BAD_TOK_HEADER; + } + + if (tok_type != -1) { + if (k5_input_get_uint16_be(&in) != tok_type) + return in.status ? G_BAD_TOK_HEADER : G_WRONG_TOKID; + } + + *buf_in = (uint8_t *)in.ptr; + *body_size = in.len; + return 0; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/Makefile.in b/krb5-1.21.3/src/lib/gssapi/krb5/Makefile.in new file mode 100644 index 00000000..be439956 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/Makefile.in @@ -0,0 +1,259 @@ +mydir=lib$(S)gssapi$(S)krb5 +BUILDTOP=$(REL)..$(S)..$(S).. +LOCALINCLUDES = -I. -I$(srcdir) -I$(srcdir)/.. -I../generic -I$(srcdir)/../generic -I../mechglue -I$(srcdir)/../mechglue +DEFINES=-D_GSS_STATIC_LINK=1 + +#MODULE_INSTALL_DIR = $(GSS_MODULE_DIR) +#LIBBASE=mech_krb5 +#LIBMAJOR=0 +#LIBMINOR=0 +#LIBINITFUNC=gss_krb5int_init +#LIBFINIFUNC=gss_krb5int_fini +#STOBJLISTS=../generic/OBJS.ST OBJS.ST +#SUBDIROBJLISTS=../generic/OBJS.ST +#SHLIB_EXPDEPS=$(KRB5_DEPLIB) $(CRYPTO_DEPLIB) $(SUPPORT_DEPLIB) $(COM_ERR_DEPLIB) +#SHLIB_EXPLIBS=-lkrb5 -lk5crypto $(COM_ERR_LIB) $(SUPPORT_LIB) $(DL_LIB) $(LIBS) +#RELDIR=gssapi/krb5 + +##DOS##BUILDTOP = ..\..\.. +##DOS##PREFIXDIR=krb5 +##DOS##OBJFILE = ..\$(OUTPRE)krb5.lst + +##DOS##DLL_EXP_TYPE=GSS + +ETSRCS= gssapi_err_krb5.c +ETOBJS= $(OUTPRE)gssapi_err_krb5.$(OBJEXT) +ETHDRS= gssapi_err_krb5.h + +$(OUTPRE)gssapi_err_krb5.$(OBJEXT): gssapi_err_krb5.c +gssapi_err_krb5.h: gssapi_err_krb5.et +gssapi_err_krb5.c: gssapi_err_krb5.et + +SRCS = \ + $(srcdir)/accept_sec_context.c \ + $(srcdir)/acquire_cred.c \ + $(srcdir)/canon_name.c \ + $(srcdir)/compare_name.c \ + $(srcdir)/context_time.c \ + $(srcdir)/copy_ccache.c \ + $(srcdir)/cred_store.c \ + $(srcdir)/delete_sec_context.c \ + $(srcdir)/disp_name.c \ + $(srcdir)/disp_status.c \ + $(srcdir)/duplicate_name.c \ + $(srcdir)/export_cred.c \ + $(srcdir)/export_name.c \ + $(srcdir)/export_sec_context.c \ + $(srcdir)/get_tkt_flags.c \ + $(srcdir)/gssapi_krb5.c \ + $(srcdir)/iakerb.c \ + $(srcdir)/import_cred.c \ + $(srcdir)/import_name.c \ + $(srcdir)/import_sec_context.c \ + $(srcdir)/indicate_mechs.c \ + $(srcdir)/init_sec_context.c \ + $(srcdir)/inq_context.c \ + $(srcdir)/inq_cred.c \ + $(srcdir)/inq_names.c \ + $(srcdir)/k5seal.c \ + $(srcdir)/k5sealiov.c \ + $(srcdir)/k5sealv3.c \ + $(srcdir)/k5sealv3iov.c \ + $(srcdir)/k5unseal.c \ + $(srcdir)/k5unsealiov.c \ + $(srcdir)/krb5_gss_glue.c \ + $(srcdir)/lucid_context.c \ + $(srcdir)/naming_exts.c \ + $(srcdir)/prf.c \ + $(srcdir)/process_context_token.c \ + $(srcdir)/rel_cred.c \ + $(srcdir)/rel_oid.c \ + $(srcdir)/rel_name.c \ + $(srcdir)/s4u_gss_glue.c \ + $(srcdir)/set_allowable_enctypes.c \ + $(srcdir)/ser_sctx.c \ + $(srcdir)/set_ccache.c \ + $(srcdir)/store_cred.c \ + $(srcdir)/util_cksum.c \ + $(srcdir)/util_crypt.c \ + $(srcdir)/util_seed.c \ + $(srcdir)/util_seqnum.c \ + $(srcdir)/val_cred.c \ + $(srcdir)/wrap_size_limit.c + + +OBJS = \ + $(OUTPRE)accept_sec_context.$(OBJEXT) \ + $(OUTPRE)acquire_cred.$(OBJEXT) \ + $(OUTPRE)canon_name.$(OBJEXT) \ + $(OUTPRE)compare_name.$(OBJEXT) \ + $(OUTPRE)context_time.$(OBJEXT) \ + $(OUTPRE)copy_ccache.$(OBJEXT) \ + $(OUTPRE)cred_store.$(OBJEXT) \ + $(OUTPRE)delete_sec_context.$(OBJEXT) \ + $(OUTPRE)disp_name.$(OBJEXT) \ + $(OUTPRE)disp_status.$(OBJEXT) \ + $(OUTPRE)duplicate_name.$(OBJEXT) \ + $(OUTPRE)export_cred.$(OBJEXT) \ + $(OUTPRE)export_name.$(OBJEXT) \ + $(OUTPRE)export_sec_context.$(OBJEXT) \ + $(OUTPRE)get_tkt_flags.$(OBJEXT) \ + $(OUTPRE)gssapi_krb5.$(OBJEXT) \ + $(OUTPRE)iakerb.$(OBJEXT) \ + $(OUTPRE)import_cred.$(OBJEXT) \ + $(OUTPRE)import_name.$(OBJEXT) \ + $(OUTPRE)import_sec_context.$(OBJEXT) \ + $(OUTPRE)indicate_mechs.$(OBJEXT) \ + $(OUTPRE)init_sec_context.$(OBJEXT) \ + $(OUTPRE)inq_context.$(OBJEXT) \ + $(OUTPRE)inq_cred.$(OBJEXT) \ + $(OUTPRE)inq_names.$(OBJEXT) \ + $(OUTPRE)k5seal.$(OBJEXT) \ + $(OUTPRE)k5sealiov.$(OBJEXT) \ + $(OUTPRE)k5sealv3.$(OBJEXT) \ + $(OUTPRE)k5sealv3iov.$(OBJEXT) \ + $(OUTPRE)k5unseal.$(OBJEXT) \ + $(OUTPRE)k5unsealiov.$(OBJEXT) \ + $(OUTPRE)krb5_gss_glue.$(OBJEXT) \ + $(OUTPRE)lucid_context.$(OBJEXT) \ + $(OUTPRE)naming_exts.$(OBJEXT) \ + $(OUTPRE)prf.$(OBJEXT) \ + $(OUTPRE)process_context_token.$(OBJEXT) \ + $(OUTPRE)rel_cred.$(OBJEXT) \ + $(OUTPRE)rel_oid.$(OBJEXT) \ + $(OUTPRE)rel_name.$(OBJEXT) \ + $(OUTPRE)s4u_gss_glue.$(OBJEXT) \ + $(OUTPRE)set_allowable_enctypes.$(OBJEXT) \ + $(OUTPRE)ser_sctx.$(OBJEXT) \ + $(OUTPRE)set_ccache.$(OBJEXT) \ + $(OUTPRE)store_cred.$(OBJEXT) \ + $(OUTPRE)util_cksum.$(OBJEXT) \ + $(OUTPRE)util_crypt.$(OBJEXT) \ + $(OUTPRE)util_seed.$(OBJEXT) \ + $(OUTPRE)util_seqnum.$(OBJEXT) \ + $(OUTPRE)val_cred.$(OBJEXT) \ + $(OUTPRE)wrap_size_limit.$(OBJEXT) \ + $(OUTPRE)gssapi_err_krb5.$(OBJEXT) + +# k5mech.$(OBJEXT) \ +# pname_to_uid.$(OBJEXT) + +STLIBOBJS = \ + accept_sec_context.o \ + acquire_cred.o \ + canon_name.o \ + compare_name.o \ + context_time.o \ + copy_ccache.o \ + cred_store.o \ + delete_sec_context.o \ + disp_name.o \ + disp_status.o \ + duplicate_name.o \ + export_cred.o \ + export_name.o \ + export_sec_context.o \ + get_tkt_flags.o \ + gssapi_krb5.o \ + iakerb.o \ + import_cred.o \ + import_name.o \ + import_sec_context.o \ + indicate_mechs.o \ + init_sec_context.o \ + inq_context.o \ + inq_cred.o \ + inq_names.o \ + k5seal.o \ + k5sealiov.o \ + k5sealv3.o \ + k5sealv3iov.o \ + k5unseal.o \ + k5unsealiov.o \ + krb5_gss_glue.o \ + lucid_context.o \ + naming_exts.o \ + prf.o \ + process_context_token.o \ + rel_cred.o \ + rel_oid.o \ + rel_name.o \ + s4u_gss_glue.o \ + set_allowable_enctypes.o \ + ser_sctx.o \ + set_ccache.o \ + store_cred.o \ + util_cksum.o \ + util_crypt.o \ + util_seed.o \ + util_seqnum.o \ + val_cred.o \ + wrap_size_limit.o \ + gssapi_err_krb5.o + +# k5mech.o \ +# pname_to_uid.o + +HDRS= $(ETHDRS) + +EHDRDIR=$(BUILDTOP)$(S)include$(S)gssapi +EXPORTED_HEADERS= gssapi_krb5.h + +##DOS##LIBOBJS = $(OBJS) + +GSSAPI_KRB5_HDR=$(EHDRDIR)$(S)gssapi_krb5.h + +all-windows: $(EHDRDIR) $(GSSAPI_KRB5_HDR) $(SRCS) $(HDRS) + +##DOS##$(EHDRDIR): +##DOS## mkdir $(EHDRDIR) + +MK_EHDRDIR=if test -d $(EHDRDIR); then :; else (set -x; mkdir $(EHDRDIR)); fi +##DOS##MK_EHDRDIR=rem + +$(GSSAPI_KRB5_HDR): $(srcdir)$(S)gssapi_krb5.h + @$(MK_EHDRDIR) + $(CP) $(srcdir)$(S)gssapi_krb5.h "$@" + +all-unix: $(SRCS) $(HDRS) $(GSSAPI_KRB5_HDR) +all-unix: all-libobjs + +error_map.h: $(top_srcdir)/util/gen-map.pl \ + $(top_srcdir)/util/ktemplate.pm Makefile + $(PERL) -I$(top_srcdir)/util $(top_srcdir)/util/gen-map.pl \ + -oerror_map.new \ + NAME=gsserrmap \ + KEY=OM_uint32 \ + VALUE="char *" \ + COMPARE=compare_OM_uint32 \ + FREEVALUE=free_string + $(RM) $@ + $(MV) error_map.new $@ + +clean-unix:: + $(RM) $(BUILDTOP)/include/gssapi/gssapi_krb5.h + -$(RM) error_map.h + +clean-unix:: clean-libobjs + $(RM) $(ETHDRS) $(ETSRCS) + +clean-windows:: + $(RM) $(EHDRDIR)\gssapi_krb5.h + $(RM) error_map.h + -if exist $(EHDRDIR)\nul rmdir $(EHDRDIR) + + +generate-files-mac: error_map.h + +install-headers-unix install: + @set -x; for f in $(EXPORTED_HEADERS) ; \ + do $(INSTALL_DATA) $(srcdir)/$$f \ + $(DESTDIR)$(KRB5_INCDIR)/gssapi/$$f ; \ + done + +depend: $(ETSRCS) $(ETHDRS) $(GSSAPI_KRB5_HDR) error_map.h + +install: + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/accept_sec_context.c b/krb5-1.21.3/src/lib/gssapi/krb5/accept_sec_context.c new file mode 100644 index 00000000..b35e11bf --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/accept_sec_context.c @@ -0,0 +1,1346 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2000, 2004, 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "k5-int.h" +#include "k5-input.h" +#include "gssapiP_krb5.h" +#ifdef HAVE_MEMORY_H +#include +#endif +#include + +#ifdef CFX_EXERCISE +#define CFX_ACCEPTOR_SUBKEY (time(0) & 1) +#else +#define CFX_ACCEPTOR_SUBKEY 1 +#endif + +#ifndef LEAN_CLIENT + +static OM_uint32 +create_constrained_deleg_creds(OM_uint32 *minor_status, + krb5_gss_cred_id_t verifier_cred_handle, + krb5_ticket *ticket, + krb5_gss_cred_id_t *out_cred, + krb5_context context) +{ + OM_uint32 major_status; + krb5_creds krb_creds; + krb5_data *data; + krb5_error_code code; + + assert(out_cred != NULL); + assert(verifier_cred_handle->usage == GSS_C_BOTH); + + memset(&krb_creds, 0, sizeof(krb_creds)); + krb_creds.client = ticket->enc_part2->client; + krb_creds.server = ticket->server; + krb_creds.keyblock = *(ticket->enc_part2->session); + krb_creds.ticket_flags = ticket->enc_part2->flags; + krb_creds.times = ticket->enc_part2->times; + krb_creds.magic = KV5M_CREDS; + krb_creds.authdata = NULL; + + code = encode_krb5_ticket(ticket, &data); + if (code) { + *minor_status = code; + return GSS_S_FAILURE; + } + + krb_creds.ticket = *data; + + major_status = kg_compose_deleg_cred(minor_status, + verifier_cred_handle, + &krb_creds, + GSS_C_INDEFINITE, + out_cred, + NULL, + context); + + krb5_free_data(context, data); + + return major_status; +} + +/* Decode, decrypt and store the forwarded creds in the local ccache. */ +static krb5_error_code +rd_and_store_for_creds(context, auth_context, inbuf, out_cred) + krb5_context context; + krb5_auth_context auth_context; + krb5_data *inbuf; + krb5_gss_cred_id_t *out_cred; +{ + krb5_creds ** creds = NULL; + krb5_error_code retval; + krb5_ccache ccache = NULL; + krb5_gss_cred_id_t cred = NULL; + krb5_auth_context new_auth_ctx = NULL; + krb5_int32 flags_org; + + if ((retval = krb5_auth_con_getflags(context, auth_context, &flags_org))) + return retval; + krb5_auth_con_setflags(context, auth_context, + 0); + + /* + * By the time krb5_rd_cred is called here (after krb5_rd_req has been + * called in krb5_gss_accept_sec_context), the "keyblock" field of + * auth_context contains a pointer to the session key, and the + * "recv_subkey" field might contain a session subkey. Either of + * these (the "recv_subkey" if it isn't NULL, otherwise the + * "keyblock") might have been used to encrypt the encrypted part of + * the KRB_CRED message that contains the forwarded credentials. (The + * Java Crypto and Security Implementation from the DSTC in Australia + * always uses the session key. But apparently it never negotiates a + * subkey, so this code works fine against a JCSI client.) Up to the + * present, though, GSSAPI clients linked against the MIT code (which + * is almost all GSSAPI clients) don't encrypt the KRB_CRED message at + * all -- at this level. So if the first call to krb5_rd_cred fails, + * we should call it a second time with another auth context freshly + * created by krb5_auth_con_init. All of its keyblock fields will be + * NULL, so krb5_rd_cred will assume that the KRB_CRED message is + * unencrypted. (The MIT code doesn't actually send the KRB_CRED + * message in the clear -- the "authenticator" whose "checksum" ends up + * containing the KRB_CRED message does get encrypted.) + */ + if (krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)) { + if ((retval = krb5_auth_con_init(context, &new_auth_ctx))) + goto cleanup; + krb5_auth_con_setflags(context, new_auth_ctx, 0); + if ((retval = krb5_rd_cred(context, new_auth_ctx, inbuf, + &creds, NULL))) + goto cleanup; + } + + if ((retval = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache))) { + ccache = NULL; + goto cleanup; + } + + if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client))) + goto cleanup; + + if ((retval = k5_cc_store_primary_cred(context, ccache, creds[0]))) + goto cleanup; + + /* generate a delegated credential handle */ + if (out_cred) { + /* allocate memory for a cred_t... */ + if (!(cred = + (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec)))) { + retval = ENOMEM; /* out of memory? */ + goto cleanup; + } + + /* zero it out... */ + memset(cred, 0, sizeof(krb5_gss_cred_id_rec)); + + retval = k5_mutex_init(&cred->lock); + if (retval) { + xfree(cred); + cred = NULL; + goto cleanup; + } + + /* copy the client principle into it... */ + if ((retval = + kg_init_name(context, creds[0]->client, NULL, NULL, NULL, 0, + &cred->name))) { + k5_mutex_destroy(&cred->lock); + retval = ENOMEM; /* out of memory? */ + xfree(cred); /* clean up memory on failure */ + cred = NULL; + goto cleanup; + } + + cred->usage = GSS_C_INITIATE; /* we can't accept with this */ + /* cred->name already set */ + cred->keytab = NULL; /* no keytab associated with this... */ + cred->expire = creds[0]->times.endtime; /* store the end time */ + cred->ccache = ccache; /* the ccache containing the credential */ + cred->destroy_ccache = 1; + ccache = NULL; /* cred takes ownership so don't destroy */ + } + + /* If there were errors, there might have been a memory leak + if (!cred) + if ((retval = krb5_cc_close(context, ccache))) + goto cleanup; + */ +cleanup: + if (creds) + krb5_free_tgt_creds(context, creds); + + if (ccache) + (void)krb5_cc_destroy(context, ccache); + + if (out_cred) + *out_cred = cred; /* return credential */ + + if (new_auth_ctx) + krb5_auth_con_free(context, new_auth_ctx); + + krb5_auth_con_setflags(context, auth_context, flags_org); + + return retval; +} + + +/* + * Performs third leg of DCE authentication + */ +static OM_uint32 +kg_accept_dce(minor_status, context_handle, verifier_cred_handle, + input_token, input_chan_bindings, src_name, mech_type, + output_token, ret_flags, time_rec, delegated_cred_handle) + OM_uint32 *minor_status; + gss_ctx_id_t *context_handle; + gss_cred_id_t verifier_cred_handle; + gss_buffer_t input_token; + gss_channel_bindings_t input_chan_bindings; + gss_name_t *src_name; + gss_OID *mech_type; + gss_buffer_t output_token; + OM_uint32 *ret_flags; + OM_uint32 *time_rec; + gss_cred_id_t *delegated_cred_handle; +{ + krb5_error_code code; + krb5_gss_ctx_id_rec *ctx = 0; + krb5_timestamp now; + krb5_gss_name_t name = NULL; + krb5_ui_4 nonce = 0; + krb5_data ap_rep; + OM_uint32 major_status = GSS_S_FAILURE; + + output_token->length = 0; + output_token->value = NULL; + + if (mech_type) + *mech_type = GSS_C_NULL_OID; + /* return a bogus cred handle */ + if (delegated_cred_handle) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + + ctx = (krb5_gss_ctx_id_rec *)*context_handle; + + code = krb5_timeofday(ctx->k5_context, &now); + if (code != 0) { + major_status = GSS_S_FAILURE; + goto fail; + } + + ap_rep.data = input_token->value; + ap_rep.length = input_token->length; + + code = krb5_rd_rep_dce(ctx->k5_context, + ctx->auth_context, + &ap_rep, + &nonce); + if (code != 0) { + major_status = GSS_S_FAILURE; + goto fail; + } + + ctx->established = 1; + + if (src_name) { + code = kg_duplicate_name(ctx->k5_context, ctx->there, &name); + if (code) { + major_status = GSS_S_FAILURE; + goto fail; + } + *src_name = (gss_name_t) name; + } + + if (mech_type) + *mech_type = ctx->mech_used; + + if (time_rec) { + *time_rec = ts_interval(ts_incr(now, -ctx->k5_context->clockskew), + ctx->krb_times.endtime); + } + + /* Never return GSS_C_DELEG_FLAG since we don't support DCE credential + * delegation yet. */ + if (ret_flags) + *ret_flags = (ctx->gss_flags & ~GSS_C_DELEG_FLAG); + + *minor_status = 0; + + return GSS_S_COMPLETE; + +fail: + /* real failure code follows */ + + (void) krb5_gss_delete_sec_context(minor_status, (gss_ctx_id_t *) &ctx, + NULL); + *context_handle = GSS_C_NO_CONTEXT; + *minor_status = code; + + return major_status; +} + +static krb5_error_code +kg_process_extension(krb5_context context, + krb5_auth_context auth_context, + int ext_type, + krb5_data *ext_data, + krb5_gss_ctx_ext_t exts) +{ + krb5_error_code code = 0; + + assert(exts != NULL); + + switch (ext_type) { + case KRB5_GSS_EXTS_IAKERB_FINISHED: + if (exts->iakerb.conv == NULL) { + code = KRB5KRB_AP_ERR_MSG_TYPE; /* XXX */ + } else { + krb5_key key; + + code = krb5_auth_con_getrecvsubkey_k(context, auth_context, &key); + if (code != 0) + break; + + code = iakerb_verify_finished(context, key, exts->iakerb.conv, + ext_data); + if (code == 0) + exts->iakerb.verified = 1; + + krb5_k_free_key(context, key); + } + break; + default: + break; + } + + return code; +} + +/* The length of the MD5 channel bindings in an 0x8003 checksum */ +#define CB_MD5_LEN 16 + +/* The minimum length of an 0x8003 checksum value (4-byte channel bindings + * length, 16-byte channel bindings, 4-byte flags) */ +#define MIN_8003_LEN (4 + CB_MD5_LEN + 4) + +/* The flags we accept from the initiator's authenticator checksum. */ +#define INITIATOR_FLAGS (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG | \ + GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | \ + GSS_C_SEQUENCE_FLAG | GSS_C_DCE_STYLE | \ + GSS_C_IDENTIFY_FLAG | GSS_C_EXTENDED_ERROR_FLAG) + +/* A zero-value channel binding, for comparison */ +static const uint8_t null_cb[CB_MD5_LEN]; + +/* Look for AP_OPTIONS in authdata. If present and the options include + * KERB_AP_OPTIONS_CBT, set *cbt_out to true. */ +static krb5_error_code +check_cbt(krb5_context context, krb5_authdata *const *authdata, + krb5_boolean *cbt_out) +{ + krb5_error_code code; + krb5_authdata **ad; + uint32_t ad_ap_options; + const uint32_t KERB_AP_OPTIONS_CBT = 0x4000; + + *cbt_out = FALSE; + + code = krb5_find_authdata(context, NULL, authdata, + KRB5_AUTHDATA_AP_OPTIONS, &ad); + if (code || ad == NULL) + return code; + if (ad[1] != NULL || ad[0]->length != 4) { + code = KRB5KRB_AP_ERR_MSG_TYPE; + } else { + ad_ap_options = load_32_le(ad[0]->contents); + if (ad_ap_options & KERB_AP_OPTIONS_CBT) + *cbt_out = TRUE; + } + + krb5_free_authdata(context, ad); + return code; +} + +/* + * The krb5 GSS mech appropriates the authenticator checksum field from RFC + * 4120 to store structured data instead of a checksum, indicated with checksum + * type 0x8003 (see RFC 4121 section 4.1.1). Some implementations instead send + * no checksum, or a regular checksum over empty data. + * + * Interpret the checksum. Read delegated creds into *deleg_out if it is not + * NULL. Set *flags_out to the allowed subset of token flags, plus + * GSS_C_DELEG_FLAG if a delegated credential was present and + * GSS_C_CHANNEL_BOUND_FLAG if matching channel bindings are present. Process + * any extensions found using exts. On error, set *code_out to a krb5_error + * code for use as a minor status value. + */ +static OM_uint32 +process_checksum(OM_uint32 *minor_status, krb5_context context, + gss_channel_bindings_t acceptor_cb, + krb5_auth_context auth_context, krb5_flags ap_req_options, + krb5_authenticator *authenticator, krb5_gss_ctx_ext_t exts, + krb5_gss_cred_id_t *deleg_out, krb5_ui_4 *flags_out, + krb5_error_code *code_out) +{ + krb5_error_code code = 0; + OM_uint32 status, option_id, token_flags; + size_t cb_len, option_len; + krb5_boolean valid, client_cbt, token_cb_present = FALSE, cb_match = FALSE; + krb5_key subkey; + krb5_data option, empty = empty_data(); + krb5_checksum cb_cksum; + const uint8_t *token_cb, *option_bytes; + struct k5input in; + const krb5_checksum *cksum = authenticator->checksum; + + cb_cksum.contents = NULL; + + if (cksum == NULL) { + /* + * Some SMB client implementations use handcrafted GSSAPI code that + * does not provide a checksum. MS-KILE documents that the Microsoft + * implementation considers a missing checksum acceptable; the server + * assumes all flags are unset in this case, and does not check channel + * bindings. + */ + *flags_out = 0; + } else if (cksum->checksum_type != CKSUMTYPE_KG_CB) { + /* Samba sends a regular checksum. */ + code = krb5_auth_con_getkey_k(context, auth_context, &subkey); + if (code) { + status = GSS_S_FAILURE; + goto fail; + } + + /* Verifying the checksum ensures that this authenticator wasn't + * replayed from one with a checksum over actual data. */ + code = krb5_k_verify_checksum(context, subkey, + KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM, &empty, + cksum, &valid); + krb5_k_free_key(context, subkey); + if (code || !valid) { + status = GSS_S_BAD_SIG; + goto fail; + } + + /* Use ap_options from the request to guess the mutual flag. */ + *flags_out = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + if (ap_req_options & AP_OPTS_MUTUAL_REQUIRED) + *flags_out |= GSS_C_MUTUAL_FLAG; + } else { + /* The checksum must contain at least a fixed 24-byte part. */ + if (cksum->length < MIN_8003_LEN) { + status = GSS_S_BAD_BINDINGS; + goto fail; + } + + k5_input_init(&in, cksum->contents, cksum->length); + cb_len = k5_input_get_uint32_le(&in); + if (cb_len != CB_MD5_LEN) { + code = KG_BAD_LENGTH; + status = GSS_S_FAILURE; + goto fail; + } + + token_cb = k5_input_get_bytes(&in, cb_len); + if (acceptor_cb != GSS_C_NO_CHANNEL_BINDINGS) { + code = kg_checksum_channel_bindings(context, acceptor_cb, + &cb_cksum); + if (code) { + status = GSS_S_BAD_BINDINGS; + goto fail; + } + assert(cb_cksum.length == cb_len); + token_cb_present = (k5_bcmp(token_cb, null_cb, cb_len) != 0); + cb_match = (k5_bcmp(token_cb, cb_cksum.contents, cb_len) == 0); + if (token_cb_present && !cb_match) { + status = GSS_S_BAD_BINDINGS; + goto fail; + } + } + + /* Read the token flags and accept some of them as context flags. */ + token_flags = k5_input_get_uint32_le(&in); + *flags_out = token_flags & INITIATOR_FLAGS; + if (cb_match) + *flags_out |= GSS_C_CHANNEL_BOUND_FLAG; + + /* Read the delegated credential if present. */ + if (in.len >= 4 && (token_flags & GSS_C_DELEG_FLAG)) { + option_id = k5_input_get_uint16_le(&in); + option_len = k5_input_get_uint16_le(&in); + option_bytes = k5_input_get_bytes(&in, option_len); + option = make_data((uint8_t *)option_bytes, option_len); + if (in.status) { + code = KG_BAD_LENGTH; + status = GSS_S_FAILURE; + goto fail; + } + if (option_id != KRB5_GSS_FOR_CREDS_OPTION) { + status = GSS_S_FAILURE; + goto fail; + } + + /* Store the delegated credential. */ + code = rd_and_store_for_creds(context, auth_context, &option, + deleg_out); + if (code) { + status = GSS_S_FAILURE; + goto fail; + } + *flags_out |= GSS_C_DELEG_FLAG; + } + + /* Process any extensions at the end of the checksum. Extensions use + * 4-byte big-endian tag and length instead of 2-byte little-endian. */ + while (in.len > 0) { + option_id = k5_input_get_uint32_be(&in); + option_len = k5_input_get_uint32_be(&in); + option_bytes = k5_input_get_bytes(&in, option_len); + option = make_data((uint8_t *)option_bytes, option_len); + if (in.status) { + code = KG_BAD_LENGTH; + status = GSS_S_FAILURE; + goto fail; + } + + code = kg_process_extension(context, auth_context, option_id, + &option, exts); + if (code) { + status = GSS_S_FAILURE; + goto fail; + } + } + } + + /* + * If the client asserts the KERB_AP_OPTIONS_CBT flag (from MS-KILE) in the + * authenticator authdata, and the acceptor passed channel bindings, + * require matching channel bindings from the client. The intent is to + * prevent an authenticator generated for use outside of a TLS channel from + * being used inside of one. + */ + code = check_cbt(context, authenticator->authorization_data, &client_cbt); + if (code) { + status = GSS_S_FAILURE; + goto fail; + } + if (client_cbt && acceptor_cb != GSS_C_NO_CHANNEL_BINDINGS && !cb_match) { + status = GSS_S_BAD_BINDINGS; + goto fail; + } + + status = GSS_S_COMPLETE; + +fail: + free(cb_cksum.contents); + *code_out = code; + return status; +} + +static OM_uint32 +kg_accept_krb5(minor_status, context_handle, + verifier_cred_handle, input_token, + input_chan_bindings, src_name, mech_type, + output_token, ret_flags, time_rec, + delegated_cred_handle, exts) + OM_uint32 *minor_status; + gss_ctx_id_t *context_handle; + gss_cred_id_t verifier_cred_handle; + gss_buffer_t input_token; + gss_channel_bindings_t input_chan_bindings; + gss_name_t *src_name; + gss_OID *mech_type; + gss_buffer_t output_token; + OM_uint32 *ret_flags; + OM_uint32 *time_rec; + gss_cred_id_t *delegated_cred_handle; + krb5_gss_ctx_ext_t exts; +{ + krb5_context context; + unsigned char *ptr; + krb5_gss_cred_id_t cred = 0; + krb5_data ap_rep, ap_req; + krb5_error_code code; + krb5_address addr, *paddr; + krb5_authenticator *authdat = 0; + krb5_gss_name_t name = NULL; + krb5_ui_4 gss_flags = 0; + krb5_gss_ctx_id_rec *ctx = NULL; + krb5_timestamp now; + gss_buffer_desc token; + krb5_auth_context auth_context = NULL; + krb5_ticket * ticket = NULL; + const gss_OID_desc *mech_used = NULL; + OM_uint32 major_status; + OM_uint32 tmp_minor_status; + krb5_error krb_error_data; + krb5_data scratch; + gss_cred_id_t defcred = GSS_C_NO_CREDENTIAL; + krb5_gss_cred_id_t deleg_cred = NULL; + krb5int_access kaccess; + int cred_rcache = 0; + int no_encap = 0; + krb5_flags ap_req_options = 0; + krb5_enctype negotiated_etype; + krb5_authdata_context ad_context = NULL; + krb5_ap_req *request = NULL; + struct k5buf buf; + + code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION); + if (code) { + *minor_status = code; + return(GSS_S_FAILURE); + } + + code = krb5_gss_init_context(&context); + if (code) { + *minor_status = code; + return GSS_S_FAILURE; + } + + /* set up returns to be freeable */ + + if (src_name) + *src_name = (gss_name_t) NULL; + output_token->length = 0; + output_token->value = NULL; + token.value = 0; + ap_req.data = 0; + ap_rep.data = 0; + + if (mech_type) + *mech_type = GSS_C_NULL_OID; + /* return a bogus cred handle */ + if (delegated_cred_handle) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + + /* handle default cred handle */ + if (verifier_cred_handle == GSS_C_NO_CREDENTIAL) { + major_status = krb5_gss_acquire_cred(minor_status, GSS_C_NO_NAME, + GSS_C_INDEFINITE, GSS_C_NO_OID_SET, + GSS_C_ACCEPT, &defcred, + NULL, NULL); + if (major_status != GSS_S_COMPLETE) { + code = *minor_status; + goto fail; + } + verifier_cred_handle = defcred; + } + + /* Resolve any initiator state in the verifier cred and lock it. */ + major_status = kg_cred_resolve(minor_status, context, verifier_cred_handle, + GSS_C_NO_NAME); + if (GSS_ERROR(major_status)) { + code = *minor_status; + goto fail; + } + cred = (krb5_gss_cred_id_t)verifier_cred_handle; + + /* make sure the supplied credentials are valid for accept */ + + if ((cred->usage != GSS_C_ACCEPT) && + (cred->usage != GSS_C_BOTH)) { + code = 0; + major_status = GSS_S_NO_CRED; + goto fail; + } + + /* verify the token's integrity, and leave the token in ap_req. + figure out which mech oid was used, and save it */ + + ptr = (unsigned char *) input_token->value; + + if (!(code = g_verify_token_header(gss_mech_krb5, + &(ap_req.length), + &ptr, KG_TOK_CTX_AP_REQ, + input_token->length, 1))) { + mech_used = gss_mech_krb5; + } else if ((code == G_WRONG_MECH) + &&!(code = g_verify_token_header((gss_OID) gss_mech_iakerb, + &(ap_req.length), + &ptr, KG_TOK_CTX_AP_REQ, + input_token->length, 1))) { + mech_used = gss_mech_iakerb; + } else if ((code == G_WRONG_MECH) + &&!(code = g_verify_token_header((gss_OID) gss_mech_krb5_wrong, + &(ap_req.length), + &ptr, KG_TOK_CTX_AP_REQ, + input_token->length, 1))) { + mech_used = gss_mech_krb5_wrong; + } else if ((code == G_WRONG_MECH) && + !(code = g_verify_token_header(gss_mech_krb5_old, + &(ap_req.length), + &ptr, KG_TOK_CTX_AP_REQ, + input_token->length, 1))) { + /* + * Previous versions of this library used the old mech_id + * and some broken behavior (wrong IV on checksum + * encryption). We support the old mech_id for + * compatibility, and use it to decide when to use the + * old behavior. + */ + mech_used = gss_mech_krb5_old; + } else if (code == G_WRONG_TOKID) { + major_status = GSS_S_CONTINUE_NEEDED; + code = KRB5KRB_AP_ERR_MSG_TYPE; + mech_used = gss_mech_krb5; + goto fail; + } else if (code == G_BAD_TOK_HEADER) { + /* DCE style not encapsulated */ + ap_req.length = input_token->length; + mech_used = gss_mech_krb5; + no_encap = 1; + } else { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto fail; + } + ap_req.data = (char *)ptr; + + /* construct the sender_addr */ + + if ((input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) && + (input_chan_bindings->initiator_addrtype == GSS_C_AF_INET)) { + /* XXX is this right? */ + addr.addrtype = ADDRTYPE_INET; + addr.length = input_chan_bindings->initiator_address.length; + addr.contents = input_chan_bindings->initiator_address.value; + + paddr = &addr; + } else { + paddr = NULL; + } + + /* decode the AP_REQ message */ + code = decode_krb5_ap_req(&ap_req, &request); + if (code) { + major_status = GSS_S_FAILURE; + goto done; + } + ticket = request->ticket; + + /* decode the message */ + + if ((code = krb5_auth_con_init(context, &auth_context))) { + major_status = GSS_S_FAILURE; + save_error_info((OM_uint32)code, context); + goto fail; + } + if (cred->rcache) { + cred_rcache = 1; + if ((code = krb5_auth_con_setrcache(context, auth_context, cred->rcache))) { + major_status = GSS_S_FAILURE; + goto fail; + } + } + if ((code = krb5_auth_con_setaddrs(context, auth_context, NULL, paddr))) { + major_status = GSS_S_FAILURE; + goto fail; + } + + /* Limit the encryption types negotiated (if requested). */ + if (cred->req_enctypes) { + if ((code = krb5_auth_con_setpermetypes(context, auth_context, + cred->req_enctypes))) { + major_status = GSS_S_FAILURE; + goto fail; + } + } + + code = krb5_rd_req_decoded(context, &auth_context, request, + cred->acceptor_mprinc, cred->keytab, + &ap_req_options, NULL); + if (code) { + major_status = GSS_S_FAILURE; + goto fail; + } + krb5_auth_con_setflags(context, auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE); + + krb5_auth_con_getauthenticator(context, auth_context, &authdat); + + major_status = process_checksum(minor_status, context, input_chan_bindings, + auth_context, ap_req_options, + authdat, exts, + delegated_cred_handle ? &deleg_cred : NULL, + &gss_flags, &code); + + if (major_status != GSS_S_COMPLETE) + goto fail; + + if (exts->iakerb.conv && !exts->iakerb.verified) { + major_status = GSS_S_BAD_SIG; + goto fail; + } + + /* only DCE_STYLE clients are allowed to send raw AP-REQs */ + if (no_encap != ((gss_flags & GSS_C_DCE_STYLE) != 0)) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto fail; + } + + /* create the ctx struct and start filling it in */ + + if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec))) + == NULL) { + code = ENOMEM; + major_status = GSS_S_FAILURE; + goto fail; + } + + memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec)); + ctx->magic = KG_CONTEXT; + ctx->mech_used = (gss_OID) mech_used; + ctx->auth_context = auth_context; + ctx->initiate = 0; + ctx->gss_flags = gss_flags | GSS_C_TRANS_FLAG; + ctx->seed_init = 0; + ctx->cred_rcache = cred_rcache; + + /* XXX move this into gss_name_t */ + if ( (code = krb5_merge_authdata(context, + ticket->enc_part2->authorization_data, + authdat->authorization_data, + &ctx->authdata))) { + major_status = GSS_S_FAILURE; + goto fail; + } + if ((code = kg_init_name(context, ticket->server, NULL, NULL, NULL, 0, + &ctx->here))) { + major_status = GSS_S_FAILURE; + goto fail; + } + if ((code = krb5_auth_con_get_authdata_context(context, auth_context, + &ad_context))) { + major_status = GSS_S_FAILURE; + goto fail; + } + if ((code = kg_init_name(context, authdat->client, NULL, NULL, + ad_context, KG_INIT_NAME_NO_COPY, &ctx->there))) { + major_status = GSS_S_FAILURE; + goto fail; + } + /* Now owned by ctx->there */ + authdat->client = NULL; + krb5_auth_con_set_authdata_context(context, auth_context, NULL); + + if ((code = krb5_auth_con_getrecvsubkey_k(context, auth_context, + &ctx->subkey))) { + major_status = GSS_S_FAILURE; + goto fail; + } + + /* use the session key if the subkey isn't present */ + + if (ctx->subkey == NULL) { + if ((code = krb5_auth_con_getkey_k(context, auth_context, + &ctx->subkey))) { + major_status = GSS_S_FAILURE; + goto fail; + } + } + + if (ctx->subkey == NULL) { + /* this isn't a very good error, but it's not clear to me this + can actually happen */ + major_status = GSS_S_FAILURE; + code = KRB5KDC_ERR_NULL_KEY; + goto fail; + } + + ctx->enc = NULL; + ctx->seq = NULL; + ctx->have_acceptor_subkey = 0; + /* DCE_STYLE implies acceptor_subkey */ + if ((ctx->gss_flags & GSS_C_DCE_STYLE) == 0) { + code = kg_setup_keys(context, ctx, ctx->subkey, &ctx->cksumtype); + if (code) { + major_status = GSS_S_FAILURE; + goto fail; + } + } + ctx->krb_times = ticket->enc_part2->times; /* struct copy */ + ctx->krb_flags = ticket->enc_part2->flags; + + if (delegated_cred_handle != NULL && + deleg_cred == NULL && /* no unconstrained delegation */ + cred->usage == GSS_C_BOTH) { + /* + * Now, we always fabricate a delegated credentials handle + * containing the service ticket to ourselves, which can be + * used for S4U2Proxy. + */ + major_status = create_constrained_deleg_creds(minor_status, cred, + ticket, &deleg_cred, + context); + if (GSS_ERROR(major_status)) + goto fail; + ctx->gss_flags |= GSS_C_DELEG_FLAG; + } + + { + krb5_int32 seq_temp; + krb5_auth_con_getremoteseqnumber(context, auth_context, &seq_temp); + ctx->seq_recv = (uint32_t)seq_temp; + } + + if ((code = krb5_timeofday(context, &now))) { + major_status = GSS_S_FAILURE; + goto fail; + } + + code = g_seqstate_init(&ctx->seqstate, ctx->seq_recv, + (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0, + (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, + ctx->proto); + if (code) { + major_status = GSS_S_FAILURE; + goto fail; + } + + /* DCE_STYLE implies mutual authentication */ + if (ctx->gss_flags & GSS_C_DCE_STYLE) + ctx->gss_flags |= GSS_C_MUTUAL_FLAG; + + /* at this point, the entire context structure is filled in, + so it can be released. */ + + /* generate an AP_REP if necessary */ + + if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) { + krb5_int32 seq_temp; + int cfx_generate_subkey; + + /* + * Do not generate a subkey per RFC 4537 unless we are upgrading to CFX, + * because pre-CFX tokens do not indicate which key to use. (Note that + * DCE_STYLE implies that we will use a subkey.) + */ + if (ctx->proto == 0 && + (ctx->gss_flags & GSS_C_DCE_STYLE) == 0 && + (ap_req_options & AP_OPTS_USE_SUBKEY)) { + code = (*kaccess.auth_con_get_subkey_enctype)(context, + auth_context, + &negotiated_etype); + if (code != 0) { + major_status = GSS_S_FAILURE; + goto fail; + } + + switch (negotiated_etype) { + case ENCTYPE_DES3_CBC_SHA1: + case ENCTYPE_ARCFOUR_HMAC: + case ENCTYPE_ARCFOUR_HMAC_EXP: + /* RFC 4121 accidentally omits RC4-HMAC-EXP as a "not-newer" + * enctype, even though RFC 4757 treats it as one. */ + ap_req_options &= ~(AP_OPTS_USE_SUBKEY); + break; + } + } + + if (ctx->proto == 1 || (ctx->gss_flags & GSS_C_DCE_STYLE) || + (ap_req_options & AP_OPTS_USE_SUBKEY)) + cfx_generate_subkey = CFX_ACCEPTOR_SUBKEY; + else + cfx_generate_subkey = 0; + + if (cfx_generate_subkey) { + krb5_int32 acflags; + code = krb5_auth_con_getflags(context, auth_context, &acflags); + if (code == 0) { + acflags |= KRB5_AUTH_CONTEXT_USE_SUBKEY; + code = krb5_auth_con_setflags(context, auth_context, acflags); + } + if (code) { + major_status = GSS_S_FAILURE; + goto fail; + } + } + + if ((code = krb5_mk_rep(context, auth_context, &ap_rep))) { + major_status = GSS_S_FAILURE; + goto fail; + } + + krb5_auth_con_getlocalseqnumber(context, auth_context, &seq_temp); + ctx->seq_send = (uint32_t)seq_temp; + + if (cfx_generate_subkey) { + /* Get the new acceptor subkey. With the code above, there + should always be one if we make it to this point. */ + code = krb5_auth_con_getsendsubkey_k(context, auth_context, + &ctx->acceptor_subkey); + if (code != 0) { + major_status = GSS_S_FAILURE; + goto fail; + } + ctx->have_acceptor_subkey = 1; + + code = kg_setup_keys(context, ctx, ctx->acceptor_subkey, + &ctx->acceptor_subkey_cksumtype); + if (code) { + major_status = GSS_S_FAILURE; + goto fail; + } + } + + /* the reply token hasn't been sent yet, but that's ok. */ + if (ctx->gss_flags & GSS_C_DCE_STYLE) { + assert(ctx->have_acceptor_subkey); + + /* in order to force acceptor subkey to be used, don't set PROT_READY */ + + /* Raw AP-REP is returned */ + code = data_to_gss(&ap_rep, output_token); + if (code) + { + major_status = GSS_S_FAILURE; + goto fail; + } + + ctx->established = 0; + + *context_handle = (gss_ctx_id_t)ctx; + *minor_status = 0; + major_status = GSS_S_CONTINUE_NEEDED; + + /* Only last leg should set return arguments */ + goto fail; + } else + ctx->gss_flags |= GSS_C_PROT_READY_FLAG; + + ctx->established = 1; + + token.length = g_token_size(mech_used, ap_rep.length); + token.value = gssalloc_malloc(token.length); + if (token.value == NULL) { + major_status = GSS_S_FAILURE; + code = ENOMEM; + goto fail; + } + k5_buf_init_fixed(&buf, token.value, token.length); + g_make_token_header(&buf, mech_used, ap_rep.length, KG_TOK_CTX_AP_REP); + k5_buf_add_len(&buf, ap_rep.data, ap_rep.length); + assert(buf.len == token.length); + + ctx->established = 1; + + } else { + token.length = 0; + token.value = NULL; + ctx->seq_send = ctx->seq_recv; + + ctx->established = 1; + } + + /* set the return arguments */ + + if (src_name) { + code = kg_duplicate_name(context, ctx->there, &name); + if (code) { + major_status = GSS_S_FAILURE; + goto fail; + } + } + + if (mech_type) + *mech_type = (gss_OID) mech_used; + + /* Add the maximum allowable clock skew as a grace period for context + * expiration, just as we do for the ticket. */ + if (time_rec) { + *time_rec = ts_interval(ts_incr(now, -context->clockskew), + ctx->krb_times.endtime); + } + + if (ret_flags) + *ret_flags = ctx->gss_flags; + + *context_handle = (gss_ctx_id_t)ctx; + *output_token = token; + + if (src_name) + *src_name = (gss_name_t) name; + + if (delegated_cred_handle) + *delegated_cred_handle = (gss_cred_id_t) deleg_cred; + + /* finally! */ + + *minor_status = 0; + major_status = GSS_S_COMPLETE; + +fail: + if (authdat) + krb5_free_authenticator(context, authdat); + /* The ctx structure has the handle of the auth_context */ + if (auth_context && !ctx) { + if (cred_rcache) + (void)krb5_auth_con_setrcache(context, auth_context, NULL); + + krb5_auth_con_free(context, auth_context); + } + if (ap_rep.data) + krb5_free_data_contents(context, &ap_rep); + if (major_status == GSS_S_COMPLETE || + (major_status == GSS_S_CONTINUE_NEEDED && code != KRB5KRB_AP_ERR_MSG_TYPE)) { + ctx->k5_context = context; + context = NULL; + goto done; + } + + /* from here on is the real "fail" code */ + + if (ctx) + (void) krb5_gss_delete_sec_context(&tmp_minor_status, + (gss_ctx_id_t *) &ctx, NULL); + if (deleg_cred) { /* free memory associated with the deleg credential */ + if (deleg_cred->ccache) + (void)krb5_cc_close(context, deleg_cred->ccache); + if (deleg_cred->name) + kg_release_name(context, &deleg_cred->name); + xfree(deleg_cred); + } + if (token.value) + xfree(token.value); + if (name) { + (void) kg_release_name(context, &name); + } + + *minor_status = code; + + /* We may have failed before being able to read the GSS flags from the + * authenticator, so also check the request AP options. */ + if (cred != NULL && request != NULL && + ((gss_flags & GSS_C_MUTUAL_FLAG) || + (request->ap_options & AP_OPTS_MUTUAL_REQUIRED) || + major_status == GSS_S_CONTINUE_NEEDED)) { + unsigned int tmsglen; + + /* + * The client is expecting a response, so we can send an + * error token back + */ + memset(&krb_error_data, 0, sizeof(krb_error_data)); + + code -= ERROR_TABLE_BASE_krb5; + if (code < 0 || code > KRB_ERR_MAX) + code = 60 /* KRB_ERR_GENERIC */; + + krb_error_data.error = code; + (void) krb5_us_timeofday(context, &krb_error_data.stime, + &krb_error_data.susec); + + krb_error_data.server = ticket->server; + code = krb5_mk_error(context, &krb_error_data, &scratch); + if (code) + goto done; + + tmsglen = scratch.length; + + token.length = g_token_size(mech_used, tmsglen); + token.value = gssalloc_malloc(token.length); + if (!token.value) + goto done; + k5_buf_init_fixed(&buf, token.value, token.length); + g_make_token_header(&buf, mech_used, tmsglen, KG_TOK_CTX_ERROR); + k5_buf_add_len(&buf, scratch.data, scratch.length); + assert(buf.len == token.length); + + krb5_free_data_contents(context, &scratch); + + *output_token = token; + } + +done: + krb5_free_ap_req(context, request); + if (cred) + k5_mutex_unlock(&cred->lock); + if (defcred) + krb5_gss_release_cred(&tmp_minor_status, &defcred); + if (context) { + if (major_status && *minor_status) + save_error_info(*minor_status, context); + krb5_free_context(context); + } + return (major_status); +} +#endif /* LEAN_CLIENT */ + +OM_uint32 KRB5_CALLCONV +krb5_gss_accept_sec_context_ext( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_cred_id_t verifier_cred_handle, + gss_buffer_t input_token, + gss_channel_bindings_t input_chan_bindings, + gss_name_t *src_name, + gss_OID *mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec, + gss_cred_id_t *delegated_cred_handle, + krb5_gss_ctx_ext_t exts) +{ + krb5_gss_ctx_id_rec *ctx = (krb5_gss_ctx_id_rec *)*context_handle; + + /* + * Context handle must be unspecified. Actually, it must be + * non-established, but currently, accept_sec_context never returns + * a non-established context handle. + */ + /*SUPPRESS 29*/ + if (ctx != NULL) { + if (ctx->established == 0 && (ctx->gss_flags & GSS_C_DCE_STYLE)) { + return kg_accept_dce(minor_status, context_handle, + verifier_cred_handle, input_token, + input_chan_bindings, src_name, mech_type, + output_token, ret_flags, time_rec, + delegated_cred_handle); + } else { + *minor_status = EINVAL; + save_error_string(EINVAL, "accept_sec_context called with existing context handle"); + return GSS_S_FAILURE; + } + } + + return kg_accept_krb5(minor_status, context_handle, + verifier_cred_handle, input_token, + input_chan_bindings, src_name, mech_type, + output_token, ret_flags, time_rec, + delegated_cred_handle, exts); +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_accept_sec_context(minor_status, context_handle, + verifier_cred_handle, input_token, + input_chan_bindings, src_name, mech_type, + output_token, ret_flags, time_rec, + delegated_cred_handle) + OM_uint32 *minor_status; + gss_ctx_id_t *context_handle; + gss_cred_id_t verifier_cred_handle; + gss_buffer_t input_token; + gss_channel_bindings_t input_chan_bindings; + gss_name_t *src_name; + gss_OID *mech_type; + gss_buffer_t output_token; + OM_uint32 *ret_flags; + OM_uint32 *time_rec; + gss_cred_id_t *delegated_cred_handle; +{ + krb5_gss_ctx_ext_rec exts; + + memset(&exts, 0, sizeof(exts)); + + return krb5_gss_accept_sec_context_ext(minor_status, + context_handle, + verifier_cred_handle, + input_token, + input_chan_bindings, + src_name, + mech_type, + output_token, + ret_flags, + time_rec, + delegated_cred_handle, + &exts); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/acquire_cred.c b/krb5-1.21.3/src/lib/gssapi/krb5/acquire_cred.c new file mode 100644 index 00000000..006eba11 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/acquire_cred.c @@ -0,0 +1,1369 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2000, 2007-2010 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" +#include "gssapiP_krb5.h" +#ifdef HAVE_STRING_H +#include +#else +#include +#endif + +#ifdef USE_LEASH +#ifdef _WIN64 +#define LEASH_DLL "leashw64.dll" +#else +#define LEASH_DLL "leashw32.dll" +#endif +static void (*pLeash_AcquireInitialTicketsIfNeeded)(krb5_context,krb5_principal,char*,int) = NULL; +static HANDLE hLeashDLL = INVALID_HANDLE_VALUE; +#endif + +#ifndef LEAN_CLIENT +k5_mutex_t gssint_krb5_keytab_lock = K5_MUTEX_PARTIAL_INITIALIZER; +static char *krb5_gss_keytab = NULL; + +/* Heimdal calls this gsskrb5_register_acceptor_identity. */ +OM_uint32 +gss_krb5int_register_acceptor_identity(OM_uint32 *minor_status, + const gss_OID desired_mech, + const gss_OID desired_object, + gss_buffer_t value) +{ + char *new = NULL, *old; + int err; + + err = gss_krb5int_initialize_library(); + if (err != 0) + return GSS_S_FAILURE; + + if (value->value != NULL) { + new = strdup((char *)value->value); + if (new == NULL) + return GSS_S_FAILURE; + } + + k5_mutex_lock(&gssint_krb5_keytab_lock); + old = krb5_gss_keytab; + krb5_gss_keytab = new; + k5_mutex_unlock(&gssint_krb5_keytab_lock); + free(old); + return GSS_S_COMPLETE; +} + +/* Try to verify that keytab contains at least one entry for name. Return 0 if + * it does, KRB5_KT_NOTFOUND if it doesn't, or another error as appropriate. */ +static krb5_error_code +check_keytab(krb5_context context, krb5_keytab kt, krb5_gss_name_t name, + krb5_principal mprinc) +{ + krb5_error_code code; + krb5_keytab_entry ent; + char *princname; + + if (name->service == NULL) { + code = krb5_kt_get_entry(context, kt, name->princ, 0, 0, &ent); + if (code == 0) + krb5_kt_free_entry(context, &ent); + return code; + } + + /* If we can't iterate through the keytab, skip this check. */ + if (kt->ops->start_seq_get == NULL) + return 0; + + /* Scan the keytab for host-based entries matching mprinc. */ + code = k5_kt_have_match(context, kt, mprinc); + if (code == KRB5_KT_NOTFOUND) { + if (krb5_unparse_name(context, mprinc, &princname) == 0) { + k5_setmsg(context, code, _("No key table entry found matching %s"), + princname); + free(princname); + } + } + return code; +} + +/* get credentials corresponding to a key in the krb5 keytab. + If successful, set the keytab-specific fields in cred +*/ + +static OM_uint32 +acquire_accept_cred(krb5_context context, OM_uint32 *minor_status, + krb5_keytab req_keytab, const char *rcname, + krb5_gss_cred_id_rec *cred) +{ + OM_uint32 major; + krb5_error_code code; + krb5_keytab kt = NULL; + krb5_rcache rc = NULL; + + assert(cred->keytab == NULL); + + /* If we have an explicit rcache name, open it. */ + if (rcname != NULL) { + code = k5_rc_resolve(context, rcname, &rc); + if (code) { + major = GSS_S_FAILURE; + goto cleanup; + } + } + + if (req_keytab != NULL) { + code = krb5_kt_dup(context, req_keytab, &kt); + } else { + k5_mutex_lock(&gssint_krb5_keytab_lock); + if (krb5_gss_keytab != NULL) { + code = krb5_kt_resolve(context, krb5_gss_keytab, &kt); + k5_mutex_unlock(&gssint_krb5_keytab_lock); + } else { + k5_mutex_unlock(&gssint_krb5_keytab_lock); + code = krb5_kt_default(context, &kt); + } + } + if (code) { + major = GSS_S_NO_CRED; + goto cleanup; + } + + if (cred->name != NULL) { + code = kg_acceptor_princ(context, cred->name, &cred->acceptor_mprinc); + if (code) { + major = GSS_S_FAILURE; + goto cleanup; + } + + /* Make sure we have keys matching the desired name in the keytab. */ + code = check_keytab(context, kt, cred->name, cred->acceptor_mprinc); + if (code) { + if (code == KRB5_KT_NOTFOUND) { + k5_change_error_message_code(context, code, KG_KEYTAB_NOMATCH); + code = KG_KEYTAB_NOMATCH; + } + major = GSS_S_NO_CRED; + goto cleanup; + } + + if (rc == NULL) { + /* Open the replay cache for this principal. */ + code = krb5_get_server_rcache(context, &cred->name->princ->data[0], + &rc); + if (code) { + major = GSS_S_FAILURE; + goto cleanup; + } + } + } else { + /* Make sure we have a keytab with keys in it. */ + code = krb5_kt_have_content(context, kt); + if (code) { + major = GSS_S_NO_CRED; + goto cleanup; + } + } + + cred->keytab = kt; + kt = NULL; + cred->rcache = rc; + rc = NULL; + major = GSS_S_COMPLETE; + +cleanup: + if (kt != NULL) + krb5_kt_close(context, kt); + if (rc != NULL) + k5_rc_close(context, rc); + *minor_status = code; + return major; +} +#endif /* LEAN_CLIENT */ + +#ifdef USE_LEASH +static krb5_error_code +get_ccache_leash(krb5_context context, krb5_principal desired_princ, + krb5_ccache *ccache_out) +{ + krb5_error_code code; + krb5_ccache ccache; + char ccname[256] = ""; + + *ccache_out = NULL; + + if (hLeashDLL == INVALID_HANDLE_VALUE) { + hLeashDLL = LoadLibrary(LEASH_DLL); + if (hLeashDLL != INVALID_HANDLE_VALUE) { + (FARPROC) pLeash_AcquireInitialTicketsIfNeeded = + GetProcAddress(hLeashDLL, "not_an_API_Leash_AcquireInitialTicketsIfNeeded"); + } + } + + if (pLeash_AcquireInitialTicketsIfNeeded) { + pLeash_AcquireInitialTicketsIfNeeded(context, desired_princ, ccname, + sizeof(ccname)); + if (!ccname[0]) + return KRB5_CC_NOTFOUND; + + code = krb5_cc_resolve(context, ccname, &ccache); + if (code) + return code; + } else { + /* leash dll not available, open the default credential cache. */ + code = krb5int_cc_default(context, &ccache); + if (code) + return code; + } + + *ccache_out = ccache; + return 0; +} +#endif /* USE_LEASH */ + +/* Set fields in cred according to a ccache config entry whose key (in + * principal form) is config_princ and whose value is value. */ +static krb5_error_code +scan_cc_config(krb5_context context, krb5_gss_cred_id_rec *cred, + krb5_const_principal config_princ, const krb5_data *value) +{ + krb5_error_code code; + krb5_data data0 = empty_data(); + + if (config_princ->length != 2) + return 0; + if (data_eq_string(config_princ->data[1], KRB5_CC_CONF_PROXY_IMPERSONATOR) + && cred->impersonator == NULL) { + code = krb5int_copy_data_contents_add0(context, value, &data0); + if (code) + return code; + code = krb5_parse_name(context, data0.data, &cred->impersonator); + krb5_free_data_contents(context, &data0); + if (code) + return code; + } else if (data_eq_string(config_princ->data[1], KRB5_CC_CONF_REFRESH_TIME) + && cred->refresh_time == 0) { + code = krb5int_copy_data_contents_add0(context, value, &data0); + if (code) + return code; + cred->refresh_time = atol(data0.data); + krb5_free_data_contents(context, &data0); + } + return 0; +} + +/* Return true if it appears that we can non-interactively get initial + * tickets for cred. */ +static krb5_boolean +can_get_initial_creds(krb5_context context, krb5_gss_cred_id_rec *cred) +{ + krb5_error_code code; + + if (cred->password != NULL) + return TRUE; + + if (cred->client_keytab == NULL) + return FALSE; + + /* If we don't know the client principal yet, check for any keytab keys. */ + if (cred->name == NULL) + return !krb5_kt_have_content(context, cred->client_keytab); + + /* + * Check if we have a keytab key for the client principal. This is a bit + * more permissive than we really want because krb5_kt_have_match() + * supports wildcarding and obeys ignore_acceptor_hostname, but that should + * generally be harmless. + */ + code = k5_kt_have_match(context, cred->client_keytab, cred->name->princ); + return code == 0; +} + +/* Scan cred->ccache for name, expiry time, impersonator, refresh time. If + * check_name is true, verify the cache name against the credential name. */ +static krb5_error_code +scan_ccache(krb5_context context, krb5_gss_cred_id_rec *cred, + krb5_boolean check_name) +{ + krb5_error_code code; + krb5_ccache ccache = cred->ccache; + krb5_principal ccache_princ = NULL, tgt_princ = NULL; + krb5_data *realm; + krb5_cc_cursor cursor; + krb5_creds creds; + krb5_timestamp endtime; + krb5_boolean is_tgt; + + /* Turn on NOTICKET, as we don't need session keys here. */ + code = krb5_cc_set_flags(context, ccache, KRB5_TC_NOTICKET); + if (code) + return code; + + code = krb5_cc_get_principal(context, ccache, &ccache_princ); + if (code != 0) + goto cleanup; + + if (cred->name == NULL) { + /* Save the ccache principal as the credential name. */ + code = kg_init_name(context, ccache_princ, NULL, NULL, NULL, + KG_INIT_NAME_NO_COPY, &cred->name); + if (code) + goto cleanup; + ccache_princ = NULL; + } else { + /* Check against the desired name if needed. */ + if (check_name) { + if (!k5_sname_compare(context, cred->name->princ, ccache_princ)) { + code = KG_CCACHE_NOMATCH; + goto cleanup; + } + } + + /* Replace the credential name principal with the canonical client + * principal, retaining acceptor_mprinc if set. */ + krb5_free_principal(context, cred->name->princ); + cred->name->princ = ccache_princ; + ccache_princ = NULL; + } + + assert(cred->name->princ != NULL); + realm = krb5_princ_realm(context, cred->name->princ); + code = krb5_build_principal_ext(context, &tgt_princ, + realm->length, realm->data, + KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, + realm->length, realm->data, + 0); + if (code) + return code; + + /* If there's a tgt for the principal's local realm in here, use its expiry + * time. Otherwise use the first key. */ + code = krb5_cc_start_seq_get(context, ccache, &cursor); + if (code) { + krb5_free_principal(context, tgt_princ); + return code; + } + while (!(code = krb5_cc_next_cred(context, ccache, &cursor, &creds))) { + if (krb5_is_config_principal(context, creds.server)) { + code = scan_cc_config(context, cred, creds.server, &creds.ticket); + krb5_free_cred_contents(context, &creds); + if (code) + break; + continue; + } + is_tgt = krb5_principal_compare(context, tgt_princ, creds.server); + endtime = creds.times.endtime; + krb5_free_cred_contents(context, &creds); + if (is_tgt) + cred->have_tgt = TRUE; + if (is_tgt || cred->expire == 0) + cred->expire = endtime; + } + krb5_cc_end_seq_get(context, ccache, &cursor); + if (code && code != KRB5_CC_END) + goto cleanup; + code = 0; + + if (cred->expire == 0 && !can_get_initial_creds(context, cred)) { + code = KG_EMPTY_CCACHE; + goto cleanup; + } + +cleanup: + (void)krb5_cc_set_flags(context, ccache, 0); + krb5_free_principal(context, ccache_princ); + krb5_free_principal(context, tgt_princ); + return code; +} + +/* Find an existing or destination ccache for cred->name. */ +static krb5_error_code +get_cache_for_name(krb5_context context, krb5_gss_cred_id_rec *cred) +{ + krb5_error_code code; + krb5_boolean can_get, have_collection; + krb5_ccache defcc = NULL; + krb5_principal princ = NULL; + const char *cctype; + + assert(cred->name != NULL && cred->ccache == NULL); +#ifdef USE_LEASH + code = get_ccache_leash(context, cred->name->princ, &cred->ccache); + return code ? code : scan_ccache(context, cred, TRUE); +#else + /* Check first whether we can acquire tickets, to avoid overwriting the + * extended error message from krb5_cc_cache_match. */ + can_get = can_get_initial_creds(context, cred); + + /* Look for an existing cache for the client principal. */ + code = krb5_cc_cache_match(context, cred->name->princ, &cred->ccache); + if (code == 0) + return scan_ccache(context, cred, FALSE); + if (code != KRB5_CC_NOTFOUND || !can_get) + return code; + krb5_clear_error_message(context); + + /* There is no existing ccache, but we can acquire credentials. Get the + * default ccache to help decide where we should put them. */ + code = krb5_cc_default(context, &defcc); + if (code) + return code; + cctype = krb5_cc_get_type(context, defcc); + have_collection = krb5_cc_support_switch(context, cctype); + + /* We can use an empty default ccache if we're using a password or if + * there's no collection. */ + if (cred->password != NULL || !have_collection) { + if (krb5_cc_get_principal(context, defcc, &princ) == KRB5_FCC_NOFILE) { + cred->ccache = defcc; + defcc = NULL; + } + krb5_clear_error_message(context); + } + + /* Otherwise, try to use a new cache in the collection. */ + if (cred->ccache == NULL) { + if (!have_collection) { + code = KG_CCACHE_NOMATCH; + goto cleanup; + } + code = krb5_cc_new_unique(context, cctype, NULL, &cred->ccache); + if (code) + goto cleanup; + } + +cleanup: + krb5_free_principal(context, princ); + if (defcc != NULL) + krb5_cc_close(context, defcc); + return code; +#endif /* not USE_LEASH */ +} + +/* Try to set cred->name using the client keytab. */ +static krb5_error_code +get_name_from_client_keytab(krb5_context context, krb5_gss_cred_id_rec *cred) +{ + krb5_error_code code; + krb5_principal princ; + + assert(cred->name == NULL); + + if (cred->client_keytab == NULL) + return KRB5_KT_NOTFOUND; + + code = k5_kt_get_principal(context, cred->client_keytab, &princ); + if (code) + return code; + code = kg_init_name(context, princ, NULL, NULL, NULL, KG_INIT_NAME_NO_COPY, + &cred->name); + if (code) { + krb5_free_principal(context, princ); + return code; + } + return 0; +} + +/* Make a note in ccache that we should attempt to refresh it from the client + * keytab at refresh_time. */ +static void +set_refresh_time(krb5_context context, krb5_ccache ccache, + krb5_timestamp refresh_time) +{ + char buf[128]; + krb5_data d; + + snprintf(buf, sizeof(buf), "%u", (unsigned int)ts2tt(refresh_time)); + d = string2data(buf); + (void)krb5_cc_set_config(context, ccache, NULL, KRB5_CC_CONF_REFRESH_TIME, + &d); + krb5_clear_error_message(context); +} + +/* Return true if it's time to refresh cred from the client keytab. If + * returning true, avoid retrying for 30 seconds. */ +krb5_boolean +kg_cred_time_to_refresh(krb5_context context, krb5_gss_cred_id_rec *cred) +{ + krb5_timestamp now, soon; + + if (krb5_timeofday(context, &now)) + return FALSE; + soon = ts_incr(now, 30); + if (cred->refresh_time != 0 && !ts_after(cred->refresh_time, now)) { + set_refresh_time(context, cred->ccache, soon); + return TRUE; + } + + /* If the creds will expire soon, try to refresh even if they weren't + * acquired with a client keytab. */ + if (ts_after(soon, cred->expire)) { + set_refresh_time(context, cred->ccache, soon); + return TRUE; + } + + return FALSE; +} + +/* If appropriate, make a note to refresh cred from the client keytab when it + * is halfway to expired. */ +void +kg_cred_set_initial_refresh(krb5_context context, krb5_gss_cred_id_rec *cred, + krb5_ticket_times *times) +{ + krb5_timestamp refresh; + + /* For now, we only mark keytab-acquired credentials for refresh. */ + if (cred->password != NULL) + return; + + /* Make a note to refresh these when they are halfway to expired. */ + refresh = ts_incr(times->starttime, + ts_delta(times->endtime, times->starttime) / 2); + set_refresh_time(context, cred->ccache, refresh); +} + +struct verify_params { + krb5_principal princ; + krb5_keytab keytab; +}; + +static krb5_error_code +verify_initial_cred(krb5_context context, krb5_creds *creds, + const struct verify_params *verify) +{ + krb5_verify_init_creds_opt vopts; + + krb5_verify_init_creds_opt_init(&vopts); + krb5_verify_init_creds_opt_set_ap_req_nofail(&vopts, TRUE); + return krb5_verify_init_creds(context, creds, verify->princ, + verify->keytab, NULL, &vopts); +} + +/* Get initial credentials using the supplied password or client keytab. */ +static krb5_error_code +get_initial_cred(krb5_context context, const struct verify_params *verify, + krb5_gss_cred_id_rec *cred) +{ + krb5_error_code code; + krb5_get_init_creds_opt *opt = NULL; + krb5_creds creds; + + code = krb5_get_init_creds_opt_alloc(context, &opt); + if (code) + return code; + code = krb5_get_init_creds_opt_set_out_ccache(context, opt, cred->ccache); + if (code) + goto cleanup; + if (cred->password != NULL) { + code = krb5_get_init_creds_password(context, &creds, cred->name->princ, + cred->password, NULL, NULL, 0, + NULL, opt); + } else if (cred->client_keytab != NULL) { + code = krb5_get_init_creds_keytab(context, &creds, cred->name->princ, + cred->client_keytab, 0, NULL, opt); + } else { + code = KRB5_KT_NOTFOUND; + } + if (code) + goto cleanup; + if (cred->password != NULL && verify != NULL) { + code = verify_initial_cred(context, &creds, verify); + if (code) + goto cleanup; + } + kg_cred_set_initial_refresh(context, cred, &creds.times); + cred->have_tgt = TRUE; + cred->expire = creds.times.endtime; + + /* Steal the canonical client principal name from creds and save it in the + * credential name, retaining acceptor_mprinc if set. */ + krb5_free_principal(context, cred->name->princ); + cred->name->princ = creds.client; + creds.client = NULL; + + krb5_free_cred_contents(context, &creds); +cleanup: + krb5_get_init_creds_opt_free(context, opt); + return code; +} + +/* Get initial credentials if we ought to and are able to. */ +static krb5_error_code +maybe_get_initial_cred(krb5_context context, + const struct verify_params *verify, + krb5_gss_cred_id_rec *cred) +{ + krb5_error_code code; + + /* Don't get creds if we don't know the name or are doing IAKERB. */ + if (cred->name == NULL || cred->iakerb_mech) + return 0; + + /* Get creds if we have none or if it's time to refresh. */ + if (cred->expire == 0 || kg_cred_time_to_refresh(context, cred)) { + code = get_initial_cred(context, verify, cred); + /* If we were trying to refresh and failed, we can keep going. */ + if (code && cred->expire == 0) + return code; + krb5_clear_error_message(context); + } + return 0; +} + +static OM_uint32 +acquire_init_cred(krb5_context context, OM_uint32 *minor_status, + krb5_ccache req_ccache, gss_buffer_t password, + krb5_keytab client_keytab, + const struct verify_params *verify, + krb5_gss_cred_id_rec *cred) +{ + krb5_error_code code; + krb5_data pwdata, pwcopy; + int caller_ccname = 0; + + /* Get ccache from caller if available. */ + if (GSS_ERROR(kg_sync_ccache_name(context, minor_status))) + return GSS_S_FAILURE; + if (GSS_ERROR(kg_caller_provided_ccache_name(minor_status, + &caller_ccname))) + return GSS_S_FAILURE; + + if (password != GSS_C_NO_BUFFER) { + pwdata = make_data(password->value, password->length); + code = krb5int_copy_data_contents_add0(context, &pwdata, &pwcopy); + if (code) + goto error; + cred->password = pwcopy.data; + + /* We will fetch the credential into a private memory ccache. */ + assert(req_ccache == NULL); + code = krb5_cc_new_unique(context, "MEMORY", NULL, &cred->ccache); + if (code) + goto error; + cred->destroy_ccache = 1; + } else if (req_ccache != NULL) { + code = krb5_cc_dup(context, req_ccache, &cred->ccache); + if (code) + goto error; + } else if (caller_ccname) { + /* Caller's ccache name has been set as the context default. */ + code = krb5int_cc_default(context, &cred->ccache); + if (code) + goto error; + } + + if (client_keytab != NULL) { + code = krb5_kt_dup(context, client_keytab, &cred->client_keytab); + } else { + code = krb5_kt_client_default(context, &cred->client_keytab); + if (code) { + /* Treat resolution failure similarly to a client keytab which + * resolves but doesn't exist or has no content. */ + TRACE_GSS_CLIENT_KEYTAB_FAIL(context, code); + krb5_clear_error_message(context); + code = 0; + } + } + if (code) + goto error; + + if (cred->ccache != NULL) { + /* The caller specified a ccache; check what's in it. */ + code = scan_ccache(context, cred, TRUE); + if (code == KRB5_FCC_NOFILE) { + /* See if we can get initial creds. If the caller didn't specify + * a name, pick one from the client keytab. */ + if (cred->name == NULL) { + if (!get_name_from_client_keytab(context, cred)) + code = 0; + } else if (can_get_initial_creds(context, cred)) { + code = 0; + } + } + if (code) + goto error; + } else if (cred->name != NULL) { + /* The caller specified a name but not a ccache; pick a cache. */ + code = get_cache_for_name(context, cred); + if (code) + goto error; + } + +#ifndef USE_LEASH + /* If we haven't picked a name, make sure we have or can get any creds, + * unless we're using Leash and might be able to get them interactively. */ + if (cred->name == NULL && !can_get_initial_creds(context, cred)) { + code = krb5_cccol_have_content(context); + if (code) + goto error; + } +#endif + + code = maybe_get_initial_cred(context, verify, cred); + if (code) + goto error; + + *minor_status = 0; + return GSS_S_COMPLETE; + +error: + *minor_status = code; + return GSS_S_NO_CRED; +} + +static OM_uint32 +acquire_cred_context(krb5_context context, OM_uint32 *minor_status, + gss_name_t desired_name, gss_buffer_t password, + OM_uint32 time_req, gss_cred_usage_t cred_usage, + krb5_ccache ccache, krb5_keytab client_keytab, + krb5_keytab keytab, const char *rcname, + const struct verify_params *verify, + krb5_boolean iakerb, gss_cred_id_t *output_cred_handle, + OM_uint32 *time_rec) +{ + krb5_gss_cred_id_t cred = NULL; + krb5_gss_name_t name = (krb5_gss_name_t)desired_name; + OM_uint32 ret; + krb5_error_code code = 0; + + /* make sure all outputs are valid */ + *output_cred_handle = GSS_C_NO_CREDENTIAL; + if (time_rec) + *time_rec = 0; + + /* create the gss cred structure */ + cred = k5alloc(sizeof(krb5_gss_cred_id_rec), &code); + if (cred == NULL) + goto krb_error_out; + + cred->usage = cred_usage; + cred->name = NULL; + cred->impersonator = NULL; + cred->iakerb_mech = iakerb; + cred->default_identity = (name == NULL); +#ifndef LEAN_CLIENT + cred->keytab = NULL; +#endif /* LEAN_CLIENT */ + cred->destroy_ccache = 0; + cred->suppress_ci_flags = 0; + cred->ccache = NULL; + + code = k5_mutex_init(&cred->lock); + if (code) + goto krb_error_out; + + switch (cred_usage) { + case GSS_C_INITIATE: + case GSS_C_ACCEPT: + case GSS_C_BOTH: + break; + default: + ret = GSS_S_FAILURE; + *minor_status = (OM_uint32) G_BAD_USAGE; + goto error_out; + } + + if (name != NULL) { + code = kg_duplicate_name(context, name, &cred->name); + if (code) + goto krb_error_out; + } + +#ifndef LEAN_CLIENT + /* + * If requested, acquire credentials for accepting. This will fill + * in cred->name if desired_princ is specified. + */ + if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) { + ret = acquire_accept_cred(context, minor_status, keytab, rcname, cred); + if (ret != GSS_S_COMPLETE) + goto error_out; + } +#endif /* LEAN_CLIENT */ + + /* + * If requested, acquire credentials for initiation. This will fill + * in cred->name if it wasn't set above. + */ + if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) { + ret = acquire_init_cred(context, minor_status, ccache, password, + client_keytab, verify, cred); + if (ret != GSS_S_COMPLETE) + goto error_out; + } + + assert(cred->default_identity || cred->name != NULL); + + /*** at this point, the cred structure has been completely created */ + + if (cred_usage == GSS_C_ACCEPT) { + if (time_rec) + *time_rec = GSS_C_INDEFINITE; + } else { + krb5_timestamp now; + + code = krb5_timeofday(context, &now); + if (code != 0) + goto krb_error_out; + + if (time_rec) { + /* Resolve cred now to determine the expiration time. */ + ret = kg_cred_resolve(minor_status, context, (gss_cred_id_t)cred, + GSS_C_NO_NAME); + if (GSS_ERROR(ret)) + goto error_out; + *time_rec = ts_interval(now, cred->expire); + k5_mutex_unlock(&cred->lock); + } + } + + *minor_status = 0; + *output_cred_handle = (gss_cred_id_t) cred; + + return GSS_S_COMPLETE; + +krb_error_out: + *minor_status = code; + ret = GSS_S_FAILURE; + +error_out: + if (cred != NULL) { + if (cred->ccache) { + if (cred->destroy_ccache) + krb5_cc_destroy(context, cred->ccache); + else + krb5_cc_close(context, cred->ccache); + } + if (cred->client_keytab) + krb5_kt_close(context, cred->client_keytab); +#ifndef LEAN_CLIENT + if (cred->keytab) + krb5_kt_close(context, cred->keytab); +#endif /* LEAN_CLIENT */ + if (cred->rcache) + k5_rc_close(context, cred->rcache); + if (cred->name) + kg_release_name(context, &cred->name); + krb5_free_principal(context, cred->impersonator); + zapfreestr(cred->password); + k5_mutex_destroy(&cred->lock); + xfree(cred); + } + save_error_info(*minor_status, context); + return ret; +} + +static OM_uint32 +acquire_cred(OM_uint32 *minor_status, gss_name_t desired_name, + gss_buffer_t password, OM_uint32 time_req, + gss_cred_usage_t cred_usage, krb5_ccache ccache, + krb5_keytab keytab, krb5_boolean iakerb, + gss_cred_id_t *output_cred_handle, OM_uint32 *time_rec) +{ + krb5_context context = NULL; + krb5_error_code code = 0; + OM_uint32 ret; + + code = gss_krb5int_initialize_library(); + if (code) { + *minor_status = code; + ret = GSS_S_FAILURE; + goto out; + } + + code = krb5_gss_init_context(&context); + if (code) { + *minor_status = code; + ret = GSS_S_FAILURE; + goto out; + } + + ret = acquire_cred_context(context, minor_status, desired_name, password, + time_req, cred_usage, ccache, NULL, keytab, + NULL, NULL, iakerb, output_cred_handle, + time_rec); + +out: + krb5_free_context(context); + return ret; +} + +/* + * Resolve the name and ccache for an initiator credential if it has not yet + * been done. If specified, use the target name to pick an appropriate ccache + * within the collection. Validates cred_handle and leaves it locked on + * success. + */ +OM_uint32 +kg_cred_resolve(OM_uint32 *minor_status, krb5_context context, + gss_cred_id_t cred_handle, gss_name_t target_name) +{ + OM_uint32 maj; + krb5_error_code code; + krb5_gss_cred_id_t cred = (krb5_gss_cred_id_t)cred_handle; + krb5_gss_name_t tname = (krb5_gss_name_t)target_name; + krb5_principal client_princ; + + *minor_status = 0; + + maj = krb5_gss_validate_cred_1(minor_status, cred_handle, context); + if (maj != 0) + return maj; + k5_mutex_assert_locked(&cred->lock); + + if (cred->usage == GSS_C_ACCEPT || cred->name != NULL) + return GSS_S_COMPLETE; + /* acquire_init_cred should have set both name and ccache, or neither. */ + assert(cred->ccache == NULL); + + if (tname != NULL) { + /* Use the target name to select an existing ccache or a principal. */ + code = krb5_cc_select(context, tname->princ, &cred->ccache, + &client_princ); + if (code && code != KRB5_CC_NOTFOUND) + goto kerr; + if (client_princ != NULL) { + code = kg_init_name(context, client_princ, NULL, NULL, NULL, + KG_INIT_NAME_NO_COPY, &cred->name); + if (code) { + krb5_free_principal(context, client_princ); + goto kerr; + } + } + if (cred->ccache != NULL) { + code = scan_ccache(context, cred, FALSE); + if (code) + goto kerr; + } + } + + /* If we still haven't picked a client principal, try using an existing + * default ccache. (On Windows, this may acquire initial creds.) */ + if (cred->name == NULL) { + code = krb5int_cc_default(context, &cred->ccache); + if (code) + goto kerr; + code = scan_ccache(context, cred, FALSE); + if (code == KRB5_FCC_NOFILE) { + /* Default ccache doesn't exist; fall through to client keytab. */ + krb5_cc_close(context, cred->ccache); + cred->ccache = NULL; + } else if (code) { + goto kerr; + } + } + + /* If that didn't work, try getting a name from the client keytab. */ + if (cred->name == NULL) { + code = get_name_from_client_keytab(context, cred); + if (code) { + code = KG_EMPTY_CCACHE; + goto kerr; + } + } + + if (cred->name != NULL && cred->ccache == NULL) { + /* Pick a cache for the name we chose (from krb5_cc_select or from the + * client keytab). */ + code = get_cache_for_name(context, cred); + if (code) + goto kerr; + } + + /* Resolve name to ccache and possibly get initial credentials. */ + code = maybe_get_initial_cred(context, NULL, cred); + if (code) + goto kerr; + + return GSS_S_COMPLETE; + +kerr: + k5_mutex_unlock(&cred->lock); + save_error_info(code, context); + *minor_status = code; + return GSS_S_NO_CRED; +} + +OM_uint32 +gss_krb5int_set_cred_rcache(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_oid, + const gss_buffer_t value) +{ + krb5_gss_cred_id_t cred; + krb5_error_code code; + krb5_context context; + krb5_rcache rcache; + + assert(value->length == sizeof(rcache)); + + if (value->length != sizeof(rcache)) + return GSS_S_FAILURE; + + rcache = (krb5_rcache)value->value; + + cred = (krb5_gss_cred_id_t)*cred_handle; + + code = krb5_gss_init_context(&context); + if (code) { + *minor_status = code; + return GSS_S_FAILURE; + } + if (cred->rcache != NULL) + k5_rc_close(context, cred->rcache); + + cred->rcache = rcache; + + krb5_free_context(context); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +/* + * krb5 and IAKERB mech API functions follow. The mechglue always passes null + * desired_mechs and actual_mechs, so we ignore those parameters. + */ + +OM_uint32 KRB5_CALLCONV +krb5_gss_acquire_cred(OM_uint32 *minor_status, gss_name_t desired_name, + OM_uint32 time_req, gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, OM_uint32 *time_rec) +{ + return acquire_cred(minor_status, desired_name, NULL, time_req, cred_usage, + NULL, NULL, FALSE, output_cred_handle, time_rec); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_acquire_cred(OM_uint32 *minor_status, gss_name_t desired_name, + OM_uint32 time_req, gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, OM_uint32 *time_rec) +{ + return acquire_cred(minor_status, desired_name, NULL, time_req, cred_usage, + NULL, NULL, TRUE, output_cred_handle, time_rec); +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_acquire_cred_with_password(OM_uint32 *minor_status, + const gss_name_t desired_name, + const gss_buffer_t password, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + int cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + return acquire_cred(minor_status, desired_name, password, time_req, + cred_usage, NULL, NULL, FALSE, output_cred_handle, + time_rec); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_acquire_cred_with_password(OM_uint32 *minor_status, + const gss_name_t desired_name, + const gss_buffer_t password, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + int cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + return acquire_cred(minor_status, desired_name, password, time_req, + cred_usage, NULL, NULL, TRUE, output_cred_handle, + time_rec); +} + +OM_uint32 +gss_krb5int_import_cred(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_oid, + const gss_buffer_t value) +{ + struct krb5_gss_import_cred_req *req; + krb5_gss_name_rec name; + OM_uint32 time_rec; + krb5_error_code code; + gss_cred_usage_t usage; + gss_name_t desired_name = GSS_C_NO_NAME; + + assert(value->length == sizeof(*req)); + + if (value->length != sizeof(*req)) + return GSS_S_FAILURE; + + req = (struct krb5_gss_import_cred_req *)value->value; + + if (req->id != NULL) { + usage = (req->keytab != NULL) ? GSS_C_BOTH : GSS_C_INITIATE; + } else if (req->keytab != NULL) { + usage = GSS_C_ACCEPT; + } else { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (req->keytab_principal != NULL) { + memset(&name, 0, sizeof(name)); + code = k5_mutex_init(&name.lock); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + name.princ = req->keytab_principal; + desired_name = (gss_name_t)&name; + } + + code = acquire_cred(minor_status, desired_name, NULL, GSS_C_INDEFINITE, + usage, req->id, req->keytab, FALSE, cred_handle, + &time_rec); + if (req->keytab_principal != NULL) + k5_mutex_destroy(&name.lock); + return code; +} + +static OM_uint32 +acquire_cred_from(OM_uint32 *minor_status, const gss_name_t desired_name, + OM_uint32 time_req, const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, krb5_boolean iakerb, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, OM_uint32 *time_rec) +{ + krb5_context context = NULL; + krb5_error_code code = 0; + krb5_keytab client_keytab = NULL; + krb5_keytab keytab = NULL; + krb5_ccache ccache = NULL; + krb5_principal verify_princ = NULL; + const char *rcname, *value; + struct verify_params vparams = { NULL }; + const struct verify_params *verify = NULL; + gss_buffer_desc pwbuf; + gss_buffer_t password = NULL; + OM_uint32 ret; + + code = gss_krb5int_initialize_library(); + if (code) { + *minor_status = code; + ret = GSS_S_FAILURE; + goto out; + } + + code = krb5_gss_init_context(&context); + if (code) { + *minor_status = code; + ret = GSS_S_FAILURE; + goto out; + } + + ret = kg_value_from_cred_store(cred_store, KRB5_CS_CCACHE_URN, &value); + if (GSS_ERROR(ret)) + goto out; + + if (value) { + code = krb5_cc_resolve(context, value, &ccache); + if (code != 0) { + *minor_status = code; + ret = GSS_S_NO_CRED; + goto out; + } + } + + ret = kg_value_from_cred_store(cred_store, KRB5_CS_CLI_KEYTAB_URN, &value); + if (GSS_ERROR(ret)) + goto out; + + if (value) { + code = krb5_kt_resolve(context, value, &client_keytab); + if (code != 0) { + *minor_status = code; + ret = GSS_S_NO_CRED; + goto out; + } + } + + ret = kg_value_from_cred_store(cred_store, KRB5_CS_KEYTAB_URN, &value); + if (GSS_ERROR(ret)) + goto out; + + if (value) { + code = krb5_kt_resolve(context, value, &keytab); + if (code != 0) { + *minor_status = code; + ret = GSS_S_NO_CRED; + goto out; + } + } + + ret = kg_value_from_cred_store(cred_store, KRB5_CS_RCACHE_URN, &rcname); + if (GSS_ERROR(ret)) + goto out; + + ret = kg_value_from_cred_store(cred_store, KRB5_CS_PASSWORD_URN, &value); + if (GSS_ERROR(ret)) + goto out; + + if (value) { + /* We must be acquiring an initiator cred with an explicit name. A + * password is mutually exclusive with a client keytab or ccache. */ + if (desired_name == GSS_C_NO_NAME) { + ret = GSS_S_BAD_NAME; + goto out; + } + if (cred_usage == GSS_C_ACCEPT || desired_name == GSS_C_NO_NAME || + ccache != NULL || client_keytab != NULL) { + *minor_status = (OM_uint32)G_BAD_USAGE; + ret = GSS_S_FAILURE; + goto out; + } + pwbuf.length = strlen(value); + pwbuf.value = (void *)value; + password = &pwbuf; + } + + ret = kg_value_from_cred_store(cred_store, KRB5_CS_VERIFY_URN, &value); + if (GSS_ERROR(ret)) + goto out; + if (value != NULL) { + if (iakerb || password == NULL) { + /* Only valid if acquiring cred with password, and not supported + * with IAKERB. */ + *minor_status = G_BAD_USAGE; + ret = GSS_S_FAILURE; + goto out; + } + if (*value != '\0') { + code = krb5_parse_name(context, value, &verify_princ); + if (code != 0) { + *minor_status = code; + ret = GSS_S_FAILURE; + goto out; + } + } + vparams.princ = verify_princ; + vparams.keytab = keytab; + verify = &vparams; + } + ret = acquire_cred_context(context, minor_status, desired_name, password, + time_req, cred_usage, ccache, client_keytab, + keytab, rcname, verify, iakerb, + output_cred_handle, time_rec); + +out: + if (ccache != NULL) + krb5_cc_close(context, ccache); + if (client_keytab != NULL) + krb5_kt_close(context, client_keytab); + if (keytab != NULL) + krb5_kt_close(context, keytab); + krb5_free_principal(context, verify_princ); + krb5_free_context(context); + return ret; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_acquire_cred_from(OM_uint32 *minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + return acquire_cred_from(minor_status, desired_name, time_req, + desired_mechs, cred_usage, cred_store, + FALSE, output_cred_handle, actual_mechs, + time_rec); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_acquire_cred_from(OM_uint32 *minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + return acquire_cred_from(minor_status, desired_name, time_req, + desired_mechs, cred_usage, cred_store, + TRUE, output_cred_handle, actual_mechs, + time_rec); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/canon_name.c b/krb5-1.21.3/src/lib/gssapi/krb5/canon_name.c new file mode 100644 index 00000000..81b08a53 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/canon_name.c @@ -0,0 +1,44 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/canon_name.c */ +/* + * Copyright 1997 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "gssapiP_krb5.h" + +/* This is trivial since we're a single mechanism implementation */ + +OM_uint32 krb5_gss_canonicalize_name(OM_uint32 *minor_status, + const gss_name_t input_name, + const gss_OID mech_type, + gss_name_t *output_name) +{ + if ((mech_type != GSS_C_NULL_OID) && + !g_OID_equal(gss_mech_krb5, mech_type) && + !g_OID_equal(gss_mech_krb5_old, mech_type)) { + *minor_status = 0; + return(GSS_S_BAD_MECH); + } + + return(krb5_gss_duplicate_name(minor_status, input_name, output_name)); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/compare_name.c b/krb5-1.21.3/src/lib/gssapi/krb5/compare_name.c new file mode 100644 index 00000000..3f3788d2 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/compare_name.c @@ -0,0 +1,52 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * $Id$ + */ + +#include "gssapiP_krb5.h" + +OM_uint32 KRB5_CALLCONV +krb5_gss_compare_name(minor_status, name1, name2, name_equal) + OM_uint32 *minor_status; + gss_name_t name1; + gss_name_t name2; + int *name_equal; +{ + krb5_context context; + krb5_error_code code; + + code = krb5_gss_init_context(&context); + if (code) { + *minor_status = code; + return GSS_S_FAILURE; + } + + *minor_status = 0; + *name_equal = kg_compare_name(context, + (krb5_gss_name_t)name1, + (krb5_gss_name_t)name2); + krb5_free_context(context); + return(GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/context_time.c b/krb5-1.21.3/src/lib/gssapi/krb5/context_time.c new file mode 100644 index 00000000..226de05f --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/context_time.c @@ -0,0 +1,58 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "gssapiP_krb5.h" + +/* + * $Id$ + */ + +OM_uint32 KRB5_CALLCONV +krb5_gss_context_time(minor_status, context_handle, time_rec) + OM_uint32 *minor_status; + gss_ctx_id_t context_handle; + OM_uint32 *time_rec; +{ + krb5_error_code code; + krb5_gss_ctx_id_rec *ctx; + krb5_timestamp now, start; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + + if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } + + if ((code = krb5_timeofday(ctx->k5_context, &now))) { + *minor_status = code; + save_error_info(*minor_status, ctx->k5_context); + return(GSS_S_FAILURE); + } + + /* Add the maximum allowable clock skew for acceptor contexts. */ + start = ctx->initiate ? now : ts_incr(now, -ctx->k5_context->clockskew); + *time_rec = ts_interval(start, ctx->krb_times.endtime); + *minor_status = 0; + return (*time_rec == 0) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/copy_ccache.c b/krb5-1.21.3/src/lib/gssapi/krb5/copy_ccache.c new file mode 100644 index 00000000..2b2806e7 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/copy_ccache.c @@ -0,0 +1,45 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include "gssapiP_krb5.h" + +OM_uint32 +gss_krb5int_copy_ccache(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + krb5_gss_cred_id_t k5creds; + krb5_error_code code; + krb5_context context = NULL; + krb5_ccache out_ccache; + + assert(value->length == sizeof(out_ccache)); + + if (value->length != sizeof(out_ccache)) + return GSS_S_FAILURE; + + out_ccache = (krb5_ccache)value->value; + + /* cred handle will have been validated by gssspi_set_cred_option() */ + k5creds = (krb5_gss_cred_id_t) *cred_handle; + k5_mutex_lock(&k5creds->lock); + if (k5creds->usage == GSS_C_ACCEPT) { + code = G_BAD_USAGE; + goto cleanup; + } + + code = krb5_gss_init_context(&context); + if (code) + goto cleanup; + + code = krb5_cc_copy_creds(context, k5creds->ccache, out_ccache); + +cleanup: + k5_mutex_unlock(&k5creds->lock); + *minor_status = code; + if (context != NULL) { + if (code) + save_error_info(*minor_status, context); + krb5_free_context(context); + } + return code ? GSS_S_FAILURE : GSS_S_COMPLETE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/cred_store.c b/krb5-1.21.3/src/lib/gssapi/krb5/cred_store.c new file mode 100644 index 00000000..008dd208 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/cred_store.c @@ -0,0 +1,50 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2011 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "gssapiP_krb5.h" + +OM_uint32 +kg_value_from_cred_store(gss_const_key_value_set_t cred_store, + const char *type, const char **value) +{ + OM_uint32 i; + + if (value == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + *value = NULL; + + if (cred_store == GSS_C_NO_CRED_STORE) + return GSS_S_COMPLETE; + + for (i = 0; i < cred_store->count; i++) { + if (strcmp(cred_store->elements[i].key, type) == 0) { + if (*value != NULL) + return GSS_S_DUPLICATE_ELEMENT; + *value = cred_store->elements[i].value; + } + } + + return GSS_S_COMPLETE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/delete_sec_context.c b/krb5-1.21.3/src/lib/gssapi/krb5/delete_sec_context.c new file mode 100644 index 00000000..4b9dfae0 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/delete_sec_context.c @@ -0,0 +1,99 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "gssapiP_krb5.h" + +/* + * $Id$ + */ + +OM_uint32 KRB5_CALLCONV +krb5_gss_delete_sec_context(minor_status, context_handle, output_token) + OM_uint32 *minor_status; + gss_ctx_id_t *context_handle; + gss_buffer_t output_token; +{ + krb5_context context; + krb5_gss_ctx_id_rec *ctx; + + if (output_token) { + output_token->length = 0; + output_token->value = NULL; + } + + /*SUPPRESS 29*/ + if (*context_handle == GSS_C_NO_CONTEXT) { + *minor_status = 0; + return(GSS_S_COMPLETE); + } + + ctx = (krb5_gss_ctx_id_t) *context_handle; + context = ctx->k5_context; + + /* free all the context state */ + + if (ctx->seqstate) + g_seqstate_free(ctx->seqstate); + + if (ctx->enc) + krb5_k_free_key(context, ctx->enc); + + if (ctx->seq) + krb5_k_free_key(context, ctx->seq); + + if (ctx->here) + kg_release_name(context, &ctx->here); + if (ctx->there) + kg_release_name(context, &ctx->there); + if (ctx->subkey) + krb5_k_free_key(context, ctx->subkey); + if (ctx->acceptor_subkey) + krb5_k_free_key(context, ctx->acceptor_subkey); + + if (ctx->auth_context) { + if (ctx->cred_rcache) + (void)krb5_auth_con_setrcache(context, ctx->auth_context, NULL); + + krb5_auth_con_free(context, ctx->auth_context); + } + + if (ctx->mech_used) + krb5_gss_release_oid(minor_status, &ctx->mech_used); + + if (ctx->authdata) + krb5_free_authdata(context, ctx->authdata); + + if (ctx->k5_context) + krb5_free_context(ctx->k5_context); + + /* Zero out context */ + zap(ctx, sizeof(*ctx)); + xfree(ctx); + + /* zero the handle itself */ + + *context_handle = GSS_C_NO_CONTEXT; + + *minor_status = 0; + return(GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/deps b/krb5-1.21.3/src/lib/gssapi/krb5/deps new file mode 100644 index 00000000..2d93c728 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/deps @@ -0,0 +1,759 @@ +# +# Generated makefile dependencies follow. +# +accept_sec_context.so accept_sec_context.po $(OUTPRE)accept_sec_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-input.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h ../generic/gssapi_err_generic.h \ + accept_sec_context.c gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h +acquire_cred.so acquire_cred.po $(OUTPRE)acquire_cred.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h acquire_cred.c gssapiP_krb5.h \ + gssapi_err_krb5.h gssapi_krb5.h +canon_name.so canon_name.po $(OUTPRE)canon_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h canon_name.c gssapiP_krb5.h \ + gssapi_err_krb5.h gssapi_krb5.h +compare_name.so compare_name.po $(OUTPRE)compare_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h compare_name.c gssapiP_krb5.h \ + gssapi_err_krb5.h gssapi_krb5.h +context_time.so context_time.po $(OUTPRE)context_time.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h context_time.c gssapiP_krb5.h \ + gssapi_err_krb5.h gssapi_krb5.h +copy_ccache.so copy_ccache.po $(OUTPRE)copy_ccache.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h copy_ccache.c gssapiP_krb5.h \ + gssapi_err_krb5.h gssapi_krb5.h +cred_store.so cred_store.po $(OUTPRE)cred_store.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h cred_store.c gssapiP_krb5.h \ + gssapi_err_krb5.h gssapi_krb5.h +delete_sec_context.so delete_sec_context.po $(OUTPRE)delete_sec_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h delete_sec_context.c \ + gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h +disp_name.so disp_name.po $(OUTPRE)disp_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h disp_name.c gssapiP_krb5.h \ + gssapi_err_krb5.h gssapi_krb5.h +disp_status.so disp_status.po $(OUTPRE)disp_status.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h disp_status.c error_map.h \ + gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h +duplicate_name.so duplicate_name.po $(OUTPRE)duplicate_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h duplicate_name.c gssapiP_krb5.h \ + gssapi_err_krb5.h gssapi_krb5.h +export_cred.so export_cred.po $(OUTPRE)export_cred.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-json.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h ../generic/gssapi_err_generic.h \ + export_cred.c gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h +export_name.so export_name.po $(OUTPRE)export_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h export_name.c gssapiP_krb5.h \ + gssapi_err_krb5.h gssapi_krb5.h +export_sec_context.so export_sec_context.po $(OUTPRE)export_sec_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h export_sec_context.c \ + gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h +get_tkt_flags.so get_tkt_flags.po $(OUTPRE)get_tkt_flags.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h get_tkt_flags.c gssapiP_krb5.h \ + gssapi_err_krb5.h gssapi_krb5.h +gssapi_krb5.so gssapi_krb5.po $(OUTPRE)gssapi_krb5.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(srcdir)/../mechglue/mechglue.h $(srcdir)/../mechglue/mglueP.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.c gssapi_krb5.h +iakerb.so iakerb.po $(OUTPRE)iakerb.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-der.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-input.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h iakerb.c +import_cred.so import_cred.po $(OUTPRE)import_cred.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-json.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h ../generic/gssapi_err_generic.h \ + gssapiP_krb5.h gssapi_err_krb5.h gssapi_krb5.h import_cred.c +import_name.so import_name.po $(OUTPRE)import_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h import_name.c +import_sec_context.so import_sec_context.po $(OUTPRE)import_sec_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h import_sec_context.c +indicate_mechs.so indicate_mechs.po $(OUTPRE)indicate_mechs.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(srcdir)/../mechglue/mechglue.h $(srcdir)/../mechglue/mglueP.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h indicate_mechs.c +init_sec_context.so init_sec_context.po $(OUTPRE)init_sec_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h init_sec_context.c +inq_context.so inq_context.po $(OUTPRE)inq_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h inq_context.c +inq_cred.so inq_cred.po $(OUTPRE)inq_cred.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h inq_cred.c +inq_names.so inq_names.po $(OUTPRE)inq_names.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h inq_names.c +k5seal.so k5seal.po $(OUTPRE)k5seal.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h k5seal.c +k5sealiov.so k5sealiov.po $(OUTPRE)k5sealiov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h k5sealiov.c +k5sealv3.so k5sealv3.po $(OUTPRE)k5sealv3.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h k5sealv3.c +k5sealv3iov.so k5sealv3iov.po $(OUTPRE)k5sealv3iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h k5sealv3iov.c +k5unseal.so k5unseal.po $(OUTPRE)k5unseal.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h k5unseal.c +k5unsealiov.so k5unsealiov.po $(OUTPRE)k5unsealiov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-der.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-input.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h k5unsealiov.c +krb5_gss_glue.so krb5_gss_glue.po $(OUTPRE)krb5_gss_glue.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h krb5_gss_glue.c +lucid_context.so lucid_context.po $(OUTPRE)lucid_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h lucid_context.c +naming_exts.so naming_exts.po $(OUTPRE)naming_exts.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h naming_exts.c +prf.so prf.po $(OUTPRE)prf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h prf.c +process_context_token.so process_context_token.po $(OUTPRE)process_context_token.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h process_context_token.c +rel_cred.so rel_cred.po $(OUTPRE)rel_cred.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h rel_cred.c +rel_oid.so rel_oid.po $(OUTPRE)rel_oid.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h rel_oid.c +rel_name.so rel_name.po $(OUTPRE)rel_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h rel_name.c +s4u_gss_glue.so s4u_gss_glue.po $(OUTPRE)s4u_gss_glue.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h s4u_gss_glue.c +set_allowable_enctypes.so set_allowable_enctypes.po \ + $(OUTPRE)set_allowable_enctypes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h set_allowable_enctypes.c +ser_sctx.so ser_sctx.po $(OUTPRE)ser_sctx.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h ser_sctx.c +set_ccache.so set_ccache.po $(OUTPRE)set_ccache.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h set_ccache.c +store_cred.so store_cred.po $(OUTPRE)store_cred.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h store_cred.c +util_cksum.so util_cksum.po $(OUTPRE)util_cksum.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h util_cksum.c +util_crypt.so util_crypt.po $(OUTPRE)util_crypt.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h util_crypt.c +util_seed.so util_seed.po $(OUTPRE)util_seed.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h util_seed.c +util_seqnum.so util_seqnum.po $(OUTPRE)util_seqnum.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h util_seqnum.c +val_cred.so val_cred.po $(OUTPRE)val_cred.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h val_cred.c +wrap_size_limit.so wrap_size_limit.po $(OUTPRE)wrap_size_limit.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_krb5.h gssapi_err_krb5.h \ + gssapi_krb5.h wrap_size_limit.c diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/disp_name.c b/krb5-1.21.3/src/lib/gssapi/krb5/disp_name.c new file mode 100644 index 00000000..b097bf0e --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/disp_name.c @@ -0,0 +1,81 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "gssapiP_krb5.h" + +OM_uint32 KRB5_CALLCONV +krb5_gss_display_name(minor_status, input_name, output_name_buffer, + output_name_type) + OM_uint32 *minor_status; + gss_name_t input_name; + gss_buffer_t output_name_buffer; + gss_OID *output_name_type; +{ + krb5_context context; + krb5_error_code code; + char *str; + krb5_gss_name_t k5name = (krb5_gss_name_t) input_name; + gss_OID nametype = (gss_OID) gss_nt_krb5_name; + + output_name_buffer->length = 0; + output_name_buffer->value = NULL; + if (output_name_type) + *output_name_type = GSS_C_NO_OID; + + code = krb5_gss_init_context(&context); + if (code) { + *minor_status = code; + return GSS_S_FAILURE; + } + + if (krb5_princ_type(context, k5name->princ) == KRB5_NT_WELLKNOWN) { + if (krb5_principal_compare(context, k5name->princ, + krb5_anonymous_principal())) + nametype = GSS_C_NT_ANONYMOUS; + } + + if ((code = krb5_unparse_name(context, + ((krb5_gss_name_t) input_name)->princ, + &str))) { + *minor_status = code; + save_error_info(*minor_status, context); + krb5_free_context(context); + return(GSS_S_FAILURE); + } + + if (! g_make_string_buffer(str, output_name_buffer)) { + krb5_free_unparsed_name(context, str); + krb5_free_context(context); + + *minor_status = (OM_uint32) G_BUFFER_ALLOC; + return(GSS_S_FAILURE); + } + + krb5_free_unparsed_name(context, str); + krb5_free_context(context); + + *minor_status = 0; + if (output_name_type) + *output_name_type = (gss_OID) nametype; + return(GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/disp_status.c b/krb5-1.21.3/src/lib/gssapi/krb5/disp_status.c new file mode 100644 index 00000000..6ff62a9d --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/disp_status.c @@ -0,0 +1,200 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "gssapiP_krb5.h" +#include "com_err.h" + +/* XXXX internationalization!! */ + +static inline int +compare_OM_uint32 (OM_uint32 a, OM_uint32 b) +{ + if (a < b) + return -1; + else if (a == b) + return 0; + else + return 1; +} +static inline void +free_string (char *s) +{ + free(s); +} +#include "error_map.h" +#include +char *get_error_message(OM_uint32 minor_code) +{ + gsserrmap *p = k5_getspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE); + char *msg = NULL; +#ifdef DEBUG + fprintf(stderr, "%s(%lu, p=%p)", __FUNCTION__, (unsigned long) minor_code, + (void *) p); +#endif + if (p) { + char **v = gsserrmap_find(p, minor_code); + if (v) { + msg = *v; +#ifdef DEBUG + fprintf(stderr, " FOUND!"); +#endif + } + } + if (msg == 0) + msg = (char *)error_message((krb5_error_code)minor_code); +#ifdef DEBUG + fprintf(stderr, " -> %p/%s\n", (void *) msg, msg); +#endif + return msg; +} +#define save_error_string_nocopy gss_krb5_save_error_string_nocopy +static int save_error_string_nocopy(OM_uint32 minor_code, char *msg) +{ + gsserrmap *p; + int ret; + +#ifdef DEBUG + fprintf(stderr, "%s(%lu, %s)", __FUNCTION__, (unsigned long) minor_code, msg); +#endif + p = k5_getspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE); + if (!p) { + p = malloc(sizeof(*p)); + if (p == NULL) { + ret = 1; + goto fail; + } + if (gsserrmap_init(p) != 0) { + free(p); + p = NULL; + ret = 1; + goto fail; + } + if (k5_setspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE, p) != 0) { + gsserrmap_destroy(p); + free(p); + p = NULL; + ret = 1; + goto fail; + } + } + ret = gsserrmap_replace_or_insert(p, minor_code, msg); +fail: +#ifdef DEBUG + fprintf(stderr, " p=%p %s\n", (void *)p, ret ? "FAIL" : "SUCCESS"); +#endif + return ret; +} +void save_error_string(OM_uint32 minor_code, char *msg) +{ + char *s = strdup(msg); + if (s) { + if (save_error_string_nocopy(minor_code, s) != 0) + free(s); + } +} +void save_error_message(OM_uint32 minor_code, const char *format, ...) +{ + char *s; + int n; + va_list ap; + + va_start(ap, format); + n = vasprintf(&s, format, ap); + va_end(ap); + if (n >= 0) { + if (save_error_string_nocopy(minor_code, s) != 0) + free(s); + } +} +void krb5_gss_save_error_info(OM_uint32 minor_code, krb5_context ctx) +{ + char *s; + +#ifdef DEBUG + fprintf(stderr, "%s(%lu, ctx=%p)\n", __FUNCTION__, + (unsigned long) minor_code, (void *)ctx); +#endif + s = (char *)krb5_get_error_message(ctx, (krb5_error_code)minor_code); +#ifdef DEBUG + fprintf(stderr, "%s(%lu, ctx=%p) saving: %s\n", __FUNCTION__, + (unsigned long) minor_code, (void *)ctx, s); +#endif + save_error_string(minor_code, s); + /* The get_error_message call above resets the error message in + ctx. Put it back, in case we make this call again *sigh*. */ + k5_setmsg(ctx, (krb5_error_code)minor_code, "%s", s); + krb5_free_error_message(ctx, s); +} +void krb5_gss_delete_error_info(void *p) +{ + gsserrmap_destroy(p); + free(p); +} + +/**/ + +OM_uint32 KRB5_CALLCONV +krb5_gss_display_status(minor_status, status_value, status_type, + mech_type, message_context, status_string) + OM_uint32 *minor_status; + OM_uint32 status_value; + int status_type; + gss_OID mech_type; + OM_uint32 *message_context; + gss_buffer_t status_string; +{ + status_string->length = 0; + status_string->value = NULL; + + if ((mech_type != GSS_C_NULL_OID) && + !g_OID_equal(gss_mech_krb5, mech_type) && + !g_OID_equal(gss_mech_krb5_old, mech_type) && + !g_OID_equal(gss_mech_iakerb, mech_type)) { + *minor_status = 0; + return(GSS_S_BAD_MECH); + } + + if (status_type == GSS_C_GSS_CODE) { + return(g_display_major_status(minor_status, status_value, + message_context, status_string)); + } else if (status_type == GSS_C_MECH_CODE) { + (void) gss_krb5int_initialize_library(); + + if (*message_context) { + *minor_status = (OM_uint32) G_BAD_MSG_CTX; + return(GSS_S_FAILURE); + } + + /* If this fails, there's not much we can do... */ + if (!g_make_string_buffer(krb5_gss_get_error_message(status_value), + status_string)) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + *minor_status = 0; + return(GSS_S_COMPLETE); + } else { + *minor_status = 0; + return(GSS_S_BAD_STATUS); + } +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/duplicate_name.c b/krb5-1.21.3/src/lib/gssapi/krb5/duplicate_name.c new file mode 100644 index 00000000..670b2b50 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/duplicate_name.c @@ -0,0 +1,57 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/duplicate_name.c */ +/* + * Copyright 1997,2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "gssapiP_krb5.h" + +OM_uint32 KRB5_CALLCONV +krb5_gss_duplicate_name(OM_uint32 *minor_status, const gss_name_t input_name, + gss_name_t *dest_name) +{ + krb5_context context; + krb5_error_code code; + krb5_gss_name_t princ, outprinc; + + *minor_status = 0; + + code = krb5_gss_init_context(&context); + if (code) { + *minor_status = code; + return GSS_S_FAILURE; + } + + princ = (krb5_gss_name_t)input_name; + code = kg_duplicate_name(context, princ, &outprinc); + if (code) { + *minor_status = code; + save_error_info(*minor_status, context); + krb5_free_context(context); + return(GSS_S_FAILURE); + } + krb5_free_context(context); + *dest_name = (gss_name_t) outprinc; + return(GSS_S_COMPLETE); + +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/export_cred.c b/krb5-1.21.3/src/lib/gssapi/krb5/export_cred.c new file mode 100644 index 00000000..96a408c2 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/export_cred.c @@ -0,0 +1,477 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/export_cred.c - krb5 export_cred implementation */ +/* + * Copyright (C) 2012 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. + */ + +#include "k5-int.h" +#include "k5-json.h" +#include "gssapiP_krb5.h" + +/* Return a JSON null or array value representing princ. */ +static krb5_error_code +json_principal(krb5_context context, krb5_principal princ, + k5_json_value *val_out) +{ + krb5_error_code ret; + k5_json_string str = NULL; + char *princname; + + *val_out = NULL; + if (princ == NULL) + return k5_json_null_create_val(val_out); + ret = krb5_unparse_name(context, princ, &princname); + if (ret) + return ret; + ret = k5_json_string_create(princname, &str); + krb5_free_unparsed_name(context, princname); + *val_out = str; + return ret; +} + +/* Return a json null or array value representing etypes. */ +static krb5_error_code +json_etypes(krb5_enctype *etypes, k5_json_value *val_out) +{ + krb5_error_code ret; + k5_json_number num; + k5_json_array array; + + *val_out = NULL; + if (etypes == NULL) + return k5_json_null_create_val(val_out); + ret = k5_json_array_create(&array); + if (ret) + return ret; + for (; *etypes != 0; etypes++) { + ret = k5_json_number_create(*etypes, &num); + if (ret) + goto err; + ret = k5_json_array_add(array, num); + k5_json_release(num); + if (ret) + goto err; + } + *val_out = array; + return 0; +err: + k5_json_release(array); + return ret; +} + +/* Return a JSON null or array value representing name. */ +static krb5_error_code +json_kgname(krb5_context context, krb5_gss_name_t name, k5_json_value *val_out) +{ + krb5_error_code ret; + k5_json_array array = NULL; + k5_json_value princ; + + *val_out = NULL; + if (name == NULL) + return k5_json_null_create_val(val_out); + ret = json_principal(context, name->princ, &princ); + if (ret) + return ret; + ret = k5_json_array_fmt(&array, "vss", princ, name->service, name->host); + k5_json_release(princ); + *val_out = array; + return ret; +} + +/* Return a JSON null or string value representing keytab. */ +static krb5_error_code +json_keytab(krb5_context context, krb5_keytab keytab, k5_json_value *val_out) +{ + krb5_error_code ret; + k5_json_string str; + char name[1024]; + + *val_out = NULL; + if (keytab == NULL) + return k5_json_null_create_val(val_out); + ret = krb5_kt_get_name(context, keytab, name, sizeof(name)); + if (ret) + return ret; + ret = k5_json_string_create(name, &str); + *val_out = str; + return ret; +} + +/* Return a JSON null or string value representing rcache. */ +static krb5_error_code +json_rcache(krb5_context context, krb5_rcache rcache, k5_json_value *val_out) +{ + krb5_error_code ret; + k5_json_string str = NULL; + + if (rcache == NULL) + return k5_json_null_create_val(val_out); + ret = k5_json_string_create(k5_rc_get_name(context, rcache), &str); + *val_out = str; + return ret; +} + +/* Return a JSON array value representing keyblock. */ +static krb5_error_code +json_keyblock(krb5_keyblock *kb, k5_json_value *val_out) +{ + krb5_error_code ret; + k5_json_array array; + + *val_out = NULL; + ret = k5_json_array_fmt(&array, "iB", kb->enctype, (void *)kb->contents, + (size_t)kb->length); + if (ret) + return ret; + *val_out = array; + return 0; +} + +/* Return a JSON array value representing addr. */ +static krb5_error_code +json_address(krb5_address *addr, k5_json_value *val_out) +{ + krb5_error_code ret; + k5_json_array array; + + *val_out = NULL; + ret = k5_json_array_fmt(&array, "iB", addr->addrtype, + (void *)addr->contents, (size_t)addr->length); + if (ret) + return ret; + *val_out = array; + return 0; +} + +/* Return a JSON null or array value representing addrs. */ +static krb5_error_code +json_addresses(krb5_address **addrs, k5_json_value *val_out) +{ + krb5_error_code ret; + k5_json_array array; + k5_json_value val; + + *val_out = NULL; + if (addrs == NULL) + return k5_json_null_create_val(val_out); + ret = k5_json_array_create(&array); + if (ret) + return ret; + for (; *addrs != NULL; addrs++) { + ret = json_address(*addrs, &val); + if (ret) + goto err; + ret = k5_json_array_add(array, val); + k5_json_release(val); + if (ret) + goto err; + } + *val_out = array; + return 0; +err: + k5_json_release(array); + return ret; +} + +/* Return a JSON array value representing ad. */ +static krb5_error_code +json_authdata_element(krb5_authdata *ad, k5_json_value *val_out) +{ + krb5_error_code ret; + k5_json_array array; + + *val_out = NULL; + ret = k5_json_array_fmt(&array, "iB", ad->ad_type, (void *)ad->contents, + (size_t)ad->length); + if (ret) + return ret; + *val_out = array; + return 0; +} + +/* Return a JSON null or array value representing authdata. */ +static krb5_error_code +json_authdata(krb5_authdata **authdata, k5_json_value *val_out) +{ + krb5_error_code ret; + k5_json_array array; + k5_json_value val; + + *val_out = NULL; + if (authdata == NULL) + return k5_json_null_create_val(val_out); + ret = k5_json_array_create(&array); + if (ret) + return ret; + for (; *authdata != NULL; authdata++) { + ret = json_authdata_element(*authdata, &val); + if (ret) + goto err; + ret = k5_json_array_add(array, val); + k5_json_release(val); + if (ret) + goto err; + } + *val_out = array; + return 0; +err: + k5_json_release(array); + return ret; +} + +/* Return a JSON array value representing creds. */ +static krb5_error_code +json_creds(krb5_context context, krb5_creds *creds, k5_json_value *val_out) +{ + krb5_error_code ret; + k5_json_array array; + k5_json_value client = NULL, server = NULL, keyblock = NULL, addrs = NULL; + k5_json_value authdata = NULL; + + *val_out = NULL; + ret = json_principal(context, creds->client, &client); + if (ret) + goto cleanup; + ret = json_principal(context, creds->server, &server); + if (ret) + goto cleanup; + ret = json_keyblock(&creds->keyblock, &keyblock); + if (ret) + goto cleanup; + ret = json_addresses(creds->addresses, &addrs); + if (ret) + goto cleanup; + ret = json_authdata(creds->authdata, &authdata); + if (ret) + goto cleanup; + + ret = k5_json_array_fmt(&array, "vvviiiibivBBv", client, server, keyblock, + creds->times.authtime, creds->times.starttime, + creds->times.endtime, creds->times.renew_till, + creds->is_skey, creds->ticket_flags, addrs, + (void *)creds->ticket.data, + (size_t)creds->ticket.length, + (void *)creds->second_ticket.data, + (size_t)creds->second_ticket.length, authdata); + if (ret) + goto cleanup; + *val_out = array; + +cleanup: + k5_json_release(client); + k5_json_release(server); + k5_json_release(keyblock); + k5_json_release(addrs); + k5_json_release(authdata); + return ret; +} + +/* Return a JSON array value representing the contents of ccache. */ +static krb5_error_code +json_ccache_contents(krb5_context context, krb5_ccache ccache, + k5_json_value *val_out) +{ + krb5_error_code ret; + krb5_principal princ; + krb5_cc_cursor cursor; + krb5_creds creds; + k5_json_array array; + k5_json_value val; + + *val_out = NULL; + ret = k5_json_array_create(&array); + if (ret) + return ret; + + /* Put the principal in the first array entry. */ + ret = krb5_cc_get_principal(context, ccache, &princ); + if (ret) + goto err; + ret = json_principal(context, princ, &val); + krb5_free_principal(context, princ); + if (ret) + goto err; + ret = k5_json_array_add(array, val); + k5_json_release(val); + if (ret) + goto err; + + /* Put credentials in the remaining array entries. */ + ret = krb5_cc_start_seq_get(context, ccache, &cursor); + if (ret) + goto err; + while ((ret = krb5_cc_next_cred(context, ccache, &cursor, &creds)) == 0) { + ret = json_creds(context, &creds, &val); + krb5_free_cred_contents(context, &creds); + if (ret) + break; + ret = k5_json_array_add(array, val); + k5_json_release(val); + if (ret) + break; + } + krb5_cc_end_seq_get(context, ccache, &cursor); + if (ret != KRB5_CC_END) + goto err; + *val_out = array; + return 0; + +err: + k5_json_release(array); + return ret; +} + +/* Return a JSON null, string, or array value representing ccache. */ +static krb5_error_code +json_ccache(krb5_context context, krb5_ccache ccache, k5_json_value *val_out) +{ + krb5_error_code ret; + k5_json_string str; + char *name; + + *val_out = NULL; + if (ccache == NULL) + return k5_json_null_create_val(val_out); + if (strcmp(krb5_cc_get_type(context, ccache), "MEMORY") == 0) { + return json_ccache_contents(context, ccache, val_out); + } else { + ret = krb5_cc_get_full_name(context, ccache, &name); + if (ret) + return ret; + ret = k5_json_string_create(name, &str); + free(name); + *val_out = str; + return ret; + } +} + +/* Return a JSON array value representing cred. */ +static krb5_error_code +json_kgcred(krb5_context context, krb5_gss_cred_id_t cred, + k5_json_value *val_out) +{ + krb5_error_code ret; + k5_json_array array; + k5_json_value name = NULL, imp = NULL, keytab = NULL, rcache = NULL; + k5_json_value ccache = NULL, ckeytab = NULL, etypes = NULL; + + *val_out = NULL; + ret = json_kgname(context, cred->name, &name); + if (ret) + goto cleanup; + ret = json_principal(context, cred->impersonator, &imp); + if (ret) + goto cleanup; + ret = json_keytab(context, cred->keytab, &keytab); + if (ret) + goto cleanup; + ret = json_rcache(context, cred->rcache, &rcache); + if (ret) + goto cleanup; + ret = json_ccache(context, cred->ccache, &ccache); + if (ret) + goto cleanup; + ret = json_keytab(context, cred->client_keytab, &ckeytab); + if (ret) + goto cleanup; + ret = json_etypes(cred->req_enctypes, &etypes); + if (ret) + goto cleanup; + + ret = k5_json_array_fmt(&array, "ivvbbvvvvbLLvs", cred->usage, name, imp, + cred->default_identity, cred->iakerb_mech, keytab, + rcache, ccache, ckeytab, cred->have_tgt, + (long long)ts2tt(cred->expire), + (long long)ts2tt(cred->refresh_time), etypes, + cred->password); + if (ret) + goto cleanup; + *val_out = array; + +cleanup: + k5_json_release(name); + k5_json_release(imp); + k5_json_release(keytab); + k5_json_release(rcache); + k5_json_release(ccache); + k5_json_release(ckeytab); + k5_json_release(etypes); + return ret; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_export_cred(OM_uint32 *minor_status, gss_cred_id_t cred_handle, + gss_buffer_t token) +{ + OM_uint32 status = GSS_S_COMPLETE; + krb5_context context; + krb5_error_code ret; + krb5_gss_cred_id_t cred; + k5_json_array array = NULL; + k5_json_value jcred = NULL; + char *str = NULL; + krb5_data d; + + ret = krb5_gss_init_context(&context); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* Validate and lock cred_handle. */ + status = krb5_gss_validate_cred_1(minor_status, cred_handle, context); + if (status != GSS_S_COMPLETE) + return status; + cred = (krb5_gss_cred_id_t)cred_handle; + + if (json_kgcred(context, cred, &jcred)) + goto oom; + if (k5_json_array_fmt(&array, "sv", CRED_EXPORT_MAGIC, jcred)) + goto oom; + if (k5_json_encode(array, &str)) + goto oom; + d = string2data(str); + if (data_to_gss(&d, token)) + goto oom; + str = NULL; + +cleanup: + free(str); + k5_mutex_unlock(&cred->lock); + k5_json_release(array); + k5_json_release(jcred); + krb5_free_context(context); + return status; + +oom: + *minor_status = ENOMEM; + status = GSS_S_FAILURE; + goto cleanup; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/export_name.c b/krb5-1.21.3/src/lib/gssapi/krb5/export_name.c new file mode 100644 index 00000000..485ebfb6 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/export_name.c @@ -0,0 +1,88 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/export_name.c */ +/* + * Copyright 1997, 2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "gssapiP_krb5.h" + +OM_uint32 KRB5_CALLCONV +krb5_gss_export_name(OM_uint32 *minor_status, const gss_name_t input_name, + gss_buffer_t exported_name) +{ + krb5_context context; + krb5_error_code code; + size_t length; + char *str; + unsigned char *cp; + + if (minor_status) + *minor_status = 0; + + code = krb5_gss_init_context(&context); + if (code) { + if (minor_status) + *minor_status = code; + return GSS_S_FAILURE; + } + + exported_name->length = 0; + exported_name->value = NULL; + + if ((code = krb5_unparse_name(context, ((krb5_gss_name_t) input_name)->princ, + &str))) { + if (minor_status) + *minor_status = code; + save_error_info((OM_uint32)code, context); + krb5_free_context(context); + return(GSS_S_FAILURE); + } + + krb5_free_context(context); + length = strlen(str); + exported_name->length = 10 + length + gss_mech_krb5->length; + exported_name->value = gssalloc_malloc(exported_name->length); + if (!exported_name->value) { + free(str); + if (minor_status) + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + cp = exported_name->value; + + /* Note: we assume the OID will be less than 128 bytes... */ + *cp++ = 0x04; *cp++ = 0x01; + store_16_be(gss_mech_krb5->length+2, cp); + cp += 2; + *cp++ = 0x06; + *cp++ = (gss_mech_krb5->length) & 0xFF; + memcpy(cp, gss_mech_krb5->elements, gss_mech_krb5->length); + cp += gss_mech_krb5->length; + store_32_be(length, cp); + cp += 4; + memcpy(cp, str, length); + + free(str); + + return(GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/export_sec_context.c b/krb5-1.21.3/src/lib/gssapi/krb5/export_sec_context.c new file mode 100644 index 00000000..44e50080 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/export_sec_context.c @@ -0,0 +1,96 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/export_sec_context.c - Externalize a security context */ +/* + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "gssapiP_krb5.h" +#ifndef LEAN_CLIENT +OM_uint32 KRB5_CALLCONV +krb5_gss_export_sec_context(minor_status, context_handle, interprocess_token) + OM_uint32 *minor_status; + gss_ctx_id_t *context_handle; + gss_buffer_t interprocess_token; +{ + krb5_context context = NULL; + krb5_error_code kret; + OM_uint32 retval; + size_t bufsize, blen; + krb5_gss_ctx_id_t ctx; + krb5_octet *obuffer, *obp; + + /* Assume a tragic failure */ + obuffer = (krb5_octet *) NULL; + retval = GSS_S_FAILURE; + *minor_status = 0; + + ctx = (krb5_gss_ctx_id_t) *context_handle; + if (ctx->terminated) { + *minor_status = KG_CTX_INCOMPLETE; + return (GSS_S_NO_CONTEXT); + } + + context = ctx->k5_context; + + /* Determine size needed for externalization of context */ + bufsize = 0; + if ((kret = kg_ctx_size(context, ctx, &bufsize))) + goto error_out; + + /* Allocate the buffer */ + if ((obuffer = gssalloc_malloc(bufsize)) == NULL) { + kret = ENOMEM; + goto error_out; + } + + obp = obuffer; + blen = bufsize; + /* Externalize the context */ + if ((kret = kg_ctx_externalize(context, ctx, &obp, &blen))) + goto error_out; + + /* Success! Return the buffer */ + interprocess_token->length = bufsize - blen; + interprocess_token->value = obuffer; + *minor_status = 0; + retval = GSS_S_COMPLETE; + + /* Now, clean up the context state */ + (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL); + *context_handle = GSS_C_NO_CONTEXT; + + return (GSS_S_COMPLETE); + +error_out: + if (retval != GSS_S_COMPLETE) + if (kret != 0 && context != 0) + save_error_info((OM_uint32)kret, context); + if (obuffer && bufsize) { + zap(obuffer, bufsize); + xfree(obuffer); + } + if (*minor_status == 0) + *minor_status = (OM_uint32) kret; + return(retval); +} +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/get_tkt_flags.c b/krb5-1.21.3/src/lib/gssapi/krb5/get_tkt_flags.c new file mode 100644 index 00000000..636fc04d --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/get_tkt_flags.c @@ -0,0 +1,45 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "gssapiP_krb5.h" + +/* + * $Id$ + */ + +OM_uint32 +gss_krb5int_get_tkt_flags(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_gss_ctx_id_rec *ctx; + gss_buffer_desc rep; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + + rep.value = &ctx->krb_flags; + rep.length = sizeof(ctx->krb_flags); + + return generic_gss_add_buffer_set_member(minor_status, &rep, data_set); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/gssapiP_krb5.h b/krb5-1.21.3/src/lib/gssapi/krb5/gssapiP_krb5.h new file mode 100644 index 00000000..73646071 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/gssapiP_krb5.h @@ -0,0 +1,1456 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2000, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _GSSAPIP_KRB5_H_ +#define _GSSAPIP_KRB5_H_ + +#include + +#ifdef HAVE_MEMORY_H +#include +#endif + +/* work around sunos braindamage */ +#ifdef major +#undef major +#endif +#ifdef minor +#undef minor +#endif + +#include "gssapiP_generic.h" + +/* The include of gssapi_krb5.h will dtrt with the above #defines in + * effect. + */ +#include "gssapi_krb5.h" +#include "gssapi_err_krb5.h" +#include "gssapi_ext.h" + +/* for debugging */ +#undef CFX_EXERCISE + +/** constants **/ + +#define GSS_MECH_KRB5_OID_LENGTH 9 +#define GSS_MECH_KRB5_OID "\052\206\110\206\367\022\001\002\002" + +#define GSS_MECH_KRB5_OLD_OID_LENGTH 5 +#define GSS_MECH_KRB5_OLD_OID "\053\005\001\005\002" + +/* Incorrect krb5 mech OID emitted by MS. */ +#define GSS_MECH_KRB5_WRONG_OID_LENGTH 9 +#define GSS_MECH_KRB5_WRONG_OID "\052\206\110\202\367\022\001\002\002" + +/* IAKERB variant */ +#define GSS_MECH_IAKERB_OID_LENGTH 6 +#define GSS_MECH_IAKERB_OID "\053\006\001\005\002\005" + +extern const gss_OID_set kg_all_mechs; + +#define CKSUMTYPE_KG_CB 0x8003 + +#define KG_TOK_CTX_AP_REQ 0x0100 +#define KG_TOK_CTX_AP_REP 0x0200 +#define KG_TOK_CTX_ERROR 0x0300 +#define KG_TOK_SIGN_MSG 0x0101 +#define KG_TOK_SEAL_MSG 0x0201 +#define KG_TOK_MIC_MSG 0x0101 +#define KG_TOK_WRAP_MSG 0x0201 +#define KG_TOK_DEL_CTX 0x0102 +#define KG2_TOK_MIC_MSG 0x0404 +#define KG2_TOK_WRAP_MSG 0x0504 +#define KG2_TOK_DEL_CTX 0x0405 +#define IAKERB_TOK_PROXY 0x0501 + +#define KRB5_GSS_FOR_CREDS_OPTION 1 + +#define KG2_RESP_FLAG_ERROR 0x0001 +#define KG2_RESP_FLAG_DELEG_OK 0x0002 + +/** CFX flags **/ +#define FLAG_SENDER_IS_ACCEPTOR 0x01 +#define FLAG_WRAP_CONFIDENTIAL 0x02 +#define FLAG_ACCEPTOR_SUBKEY 0x04 + +/* These are to be stored in little-endian order, i.e., des-mac is + stored as 02 00. */ +enum sgn_alg { + /* SGN_ALG_DES_MAC_MD5 = 0x0000, */ + /* SGN_ALG_MD2_5 = 0x0001, */ + /* SGN_ALG_DES_MAC = 0x0002, */ + /* SGN_ALG_3 = 0x0003, /\* not published *\/ */ + SGN_ALG_HMAC_MD5 = 0x0011, /* microsoft w2k; */ + SGN_ALG_HMAC_SHA1_DES3_KD = 0x0004 +}; +enum seal_alg { + SEAL_ALG_NONE = 0xffff, + /* SEAL_ALG_DES = 0x0000, */ + /* SEAL_ALG_1 = 0x0001, /\* not published *\/ */ + SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */ + SEAL_ALG_DES3KD = 0x0002 +}; + +/* for 3DES */ +#define KG_USAGE_SEAL 22 +#define KG_USAGE_SIGN 23 +#define KG_USAGE_SEQ 24 + +/* for draft-ietf-krb-wg-gssapi-cfx-01 */ +#define KG_USAGE_ACCEPTOR_SEAL 22 +#define KG_USAGE_ACCEPTOR_SIGN 23 +#define KG_USAGE_INITIATOR_SEAL 24 +#define KG_USAGE_INITIATOR_SIGN 25 + +enum qop { + /* GSS_KRB5_INTEG_C_QOP_MD5 = 0x0001, */ + /* GSS_KRB5_INTEG_C_QOP_DES_MD5 = 0x0002, */ + /* GSS_KRB5_INTEG_C_QOP_DES_MAC = 0x0003, */ + GSS_KRB5_INTEG_C_QOP_HMAC_SHA1 = 0x0004, + GSS_KRB5_INTEG_C_QOP_MASK = 0x00ff, + /* GSS_KRB5_CONF_C_QOP_DES = 0x0100, */ + GSS_KRB5_CONF_C_QOP_DES3_KD = 0x0200, + GSS_KRB5_CONF_C_QOP_MASK = 0xff00 +}; + +/** internal types **/ + +typedef struct _krb5_gss_name_rec { + krb5_principal princ; /* immutable */ + char *service; /* immutable */ + char *host; /* immutable */ + int is_cert; /* immutable */ + k5_mutex_t lock; /* protects ad_context only for now */ + krb5_authdata_context ad_context; +} krb5_gss_name_rec, *krb5_gss_name_t; + +typedef struct _krb5_gss_cred_id_rec { + /* protect against simultaneous accesses */ + k5_mutex_t lock; + + /* name/type of credential */ + gss_cred_usage_t usage; + krb5_gss_name_t name; + krb5_principal acceptor_mprinc; + krb5_principal impersonator; + unsigned int default_identity : 1; + unsigned int iakerb_mech : 1; + unsigned int destroy_ccache : 1; + unsigned int suppress_ci_flags : 1; + + /* keytab (accept) data */ + krb5_keytab keytab; + krb5_rcache rcache; + + /* ccache (init) data */ + krb5_ccache ccache; + krb5_keytab client_keytab; + krb5_boolean have_tgt; + krb5_timestamp expire; + krb5_timestamp refresh_time; + krb5_enctype *req_enctypes; /* limit negotiated enctypes to this list */ + char *password; +} krb5_gss_cred_id_rec, *krb5_gss_cred_id_t; + +typedef struct _krb5_gss_ctx_ext_rec { + struct { + krb5_data *conv; + int verified; + } iakerb; +} krb5_gss_ctx_ext_rec, *krb5_gss_ctx_ext_t; + +typedef struct _krb5_gss_ctx_id_rec { + krb5_magic magic; + unsigned int initiate : 1; /* nonzero if initiating, zero if accepting */ + unsigned int established : 1; + unsigned int have_acceptor_subkey : 1; + unsigned int seed_init : 1; /* XXX tested but never actually set */ + unsigned int terminated : 1; + OM_uint32 gss_flags; + unsigned char seed[16]; + krb5_gss_name_t here; + krb5_gss_name_t there; + krb5_key subkey; /* One of two potential keys to use with RFC 4121 + * packets; this key must always be set. */ + int signalg; + size_t cksum_size; + int sealalg; + krb5_key enc; /* RFC 1964 encryption key; seq xored with a constant + * for DES, seq for other RFC 1964 enctypes */ + krb5_key seq; /* RFC 1964 sequencing key */ + krb5_ticket_times krb_times; + krb5_flags krb_flags; + /* XXX these used to be signed. the old spec is inspecific, and + the new spec specifies unsigned. I don't believe that the change + affects the wire encoding. */ + uint64_t seq_send; + uint64_t seq_recv; + g_seqnum_state seqstate; + krb5_context k5_context; + krb5_auth_context auth_context; + gss_OID_desc *mech_used; + /* Protocol spec revision for sending packets + 0 => RFC 1964 with 3DES and RC4 enhancements + 1 => RFC 4121 + No others defined so far. It is always permitted to receive + tokens in RFC 4121 format. If enc is non-null, receiving RFC + 1964 tokens is permitted.*/ + int proto; + krb5_cksumtype cksumtype; /* for "main" subkey */ + krb5_key acceptor_subkey; /* CFX only */ + krb5_cksumtype acceptor_subkey_cksumtype; + int cred_rcache; /* did we get rcache from creds? */ + krb5_authdata **authdata; +} krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t; + +extern g_set kg_vdb; + +#ifndef LEAN_CLIENT +extern k5_mutex_t gssint_krb5_keytab_lock; +#endif /* LEAN_CLIENT */ + +/** helper functions **/ + +OM_uint32 kg_get_defcred +(OM_uint32 *minor_status, + gss_cred_id_t *cred); + +krb5_error_code kg_checksum_channel_bindings +(krb5_context context, gss_channel_bindings_t cb, + krb5_checksum *cksum); + +krb5_error_code kg_make_seq_num (krb5_context context, + krb5_key key, + int direction, krb5_ui_4 seqnum, unsigned char *cksum, + unsigned char *buf); + +krb5_error_code kg_get_seq_num (krb5_context context, + krb5_key key, + unsigned char *cksum, unsigned char *buf, int *direction, + krb5_ui_4 *seqnum); + +krb5_error_code kg_make_seed (krb5_context context, + krb5_key key, + unsigned char *seed); + +krb5_error_code +kg_setup_keys(krb5_context context, + krb5_gss_ctx_id_rec *ctx, + krb5_key subkey, + krb5_cksumtype *cksumtype); + +int kg_confounder_size (krb5_context context, krb5_enctype enctype); + +krb5_error_code kg_make_confounder (krb5_context context, + krb5_enctype enctype, unsigned char *buf); + +krb5_error_code kg_encrypt (krb5_context context, + krb5_key key, int usage, + krb5_pointer iv, + krb5_const_pointer in, + krb5_pointer out, + unsigned int length); + +/* Encrypt length bytes at ptr in place, with the given key and usage. If + * iv is not NULL, use it as the cipher state. */ +krb5_error_code kg_encrypt_inplace(krb5_context context, krb5_key key, + int usage, krb5_pointer iv, + krb5_pointer ptr, unsigned int length); + +krb5_error_code kg_encrypt_iov (krb5_context context, + int proto, int dce_style, + size_t ec, size_t rrc, + krb5_key key, int usage, + krb5_pointer iv, + gss_iov_buffer_desc *iov, + int iov_count); + +krb5_error_code +kg_arcfour_docrypt (const krb5_keyblock *keyblock, int usage, + const unsigned char *kd_data, size_t kd_data_len, + const unsigned char *input_buf, size_t input_len, + unsigned char *output_buf); + +krb5_error_code +kg_arcfour_docrypt_iov (krb5_context context, + const krb5_keyblock *keyblock, int usage, + const unsigned char *kd_data, size_t kd_data_len, + gss_iov_buffer_desc *iov, + int iov_count); + +krb5_error_code kg_decrypt (krb5_context context, + krb5_key key, int usage, + krb5_pointer iv, + krb5_const_pointer in, + krb5_pointer out, + unsigned int length); + +krb5_error_code kg_decrypt_iov (krb5_context context, + int proto, int dce_style, + size_t ec, size_t rrc, + krb5_key key, int usage, + krb5_pointer iv, + gss_iov_buffer_desc *iov, + int iov_count); + +OM_uint32 kg_seal (OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_message_buffer, + int *conf_state, + gss_buffer_t output_message_buffer, + int toktype); + +OM_uint32 kg_unseal (OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_token_buffer, + gss_buffer_t message_buffer, + int *conf_state, + gss_qop_t *qop_state, + int toktype); + +OM_uint32 kg_seal_size (OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 output_size, + OM_uint32 *input_size); + +krb5_error_code kg_ctx_size (krb5_context kcontext, + krb5_gss_ctx_id_t ctx, + size_t *sizep); + +krb5_error_code kg_ctx_externalize (krb5_context kcontext, + krb5_gss_ctx_id_t ctx, + krb5_octet **buffer, + size_t *lenremain); + +krb5_error_code kg_ctx_internalize (krb5_context kcontext, + krb5_gss_ctx_id_t *argp, + krb5_octet **buffer, + size_t *lenremain); + +OM_uint32 kg_sync_ccache_name (krb5_context context, OM_uint32 *minor_status); + +OM_uint32 kg_caller_provided_ccache_name (OM_uint32 *minor_status, + int *out_caller_provided_name); + +OM_uint32 kg_get_ccache_name (OM_uint32 *minor_status, char **out_name); + +OM_uint32 kg_set_ccache_name (OM_uint32 *minor_status, + const char *name); + +/* AEAD */ + +krb5_error_code gss_krb5int_make_seal_token_v3_iov(krb5_context context, + krb5_gss_ctx_id_rec *ctx, + int conf_req_flag, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype); + +OM_uint32 gss_krb5int_unseal_v3_iov(krb5_context context, + OM_uint32 *minor_status, + krb5_gss_ctx_id_rec *ctx, + gss_iov_buffer_desc *iov, + int iov_count, + int *conf_state, + gss_qop_t *qop_state, + int toktype); + +gss_iov_buffer_t kg_locate_iov (gss_iov_buffer_desc *iov, + int iov_count, + OM_uint32 type); + +gss_iov_buffer_t kg_locate_header_iov(gss_iov_buffer_desc *iov, int iov_count, + int toktype); + +void kg_iov_msglen(gss_iov_buffer_desc *iov, + int iov_count, + size_t *data_length, + size_t *assoc_data_length); + +void kg_release_iov(gss_iov_buffer_desc *iov, + int iov_count); + +krb5_error_code kg_make_checksum_iov_v1(krb5_context context, + krb5_cksumtype type, + size_t token_cksum_len, + krb5_key seq, + krb5_key enc, /* for conf len */ + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype, + krb5_checksum *checksum); + +krb5_error_code kg_make_checksum_iov_v3(krb5_context context, + krb5_cksumtype type, + size_t rrc, + krb5_key key, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype); + +krb5_error_code kg_verify_checksum_iov_v3(krb5_context context, + krb5_cksumtype type, + size_t rrc, + krb5_key key, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype, + krb5_boolean *valid); + +OM_uint32 kg_seal_iov (OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype); + +OM_uint32 kg_unseal_iov (OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype); + +OM_uint32 kg_seal_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype); + +krb5_cryptotype kg_translate_flag_iov(OM_uint32 type); + +OM_uint32 kg_fixup_padding_iov(OM_uint32 *minor_status, + gss_iov_buffer_desc *iov, + int iov_count); + +krb5_boolean kg_integ_only_iov(gss_iov_buffer_desc *iov, int iov_count); + +krb5_error_code kg_allocate_iov(gss_iov_buffer_t iov, size_t size); + +krb5_error_code +krb5_to_gss_cred(krb5_context context, + krb5_creds *creds, + krb5_gss_cred_id_t *out_cred); + +krb5_boolean +kg_cred_time_to_refresh(krb5_context context, krb5_gss_cred_id_rec *cred); + +void +kg_cred_set_initial_refresh(krb5_context context, krb5_gss_cred_id_rec *cred, + krb5_ticket_times *times); + +OM_uint32 +kg_cred_resolve(OM_uint32 *minor_status, krb5_context context, + gss_cred_id_t cred_handle, gss_name_t target_name); + +/** declarations of internal name mechanism functions **/ + +OM_uint32 KRB5_CALLCONV krb5_gss_acquire_cred +(OM_uint32*, /* minor_status */ + gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_cred_id_t*, /* output_cred_handle */ + gss_OID_set*, /* actual_mechs */ + OM_uint32* /* time_rec */ +); + +OM_uint32 KRB5_CALLCONV iakerb_gss_acquire_cred +(OM_uint32*, /* minor_status */ + gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_cred_id_t*, /* output_cred_handle */ + gss_OID_set*, /* actual_mechs */ + OM_uint32* /* time_rec */ +); + +OM_uint32 KRB5_CALLCONV +krb5_gss_acquire_cred_with_password( + OM_uint32 *minor_status, + const gss_name_t desired_name, + const gss_buffer_t password, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + int cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_acquire_cred_with_password( + OM_uint32 *minor_status, + const gss_name_t desired_name, + const gss_buffer_t password, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + int cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_acquire_cred_from(OM_uint32 *minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec); + +OM_uint32 KRB5_CALLCONV krb5_gss_release_cred +(OM_uint32*, /* minor_status */ + gss_cred_id_t* /* cred_handle */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_init_sec_context +(OM_uint32*, /* minor_status */ + gss_cred_id_t, /* claimant_cred_handle */ + gss_ctx_id_t*, /* context_handle */ + gss_name_t, /* target_name */ + gss_OID, /* mech_type */ + OM_uint32, /* req_flags */ + OM_uint32, /* time_req */ + gss_channel_bindings_t, + /* input_chan_bindings */ + gss_buffer_t, /* input_token */ + gss_OID*, /* actual_mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32*, /* ret_flags */ + OM_uint32* /* time_rec */ +); + +OM_uint32 krb5_gss_init_sec_context_ext +(OM_uint32*, /* minor_status */ + gss_cred_id_t, /* claimant_cred_handle */ + gss_ctx_id_t*, /* context_handle */ + gss_name_t, /* target_name */ + gss_OID, /* mech_type */ + OM_uint32, /* req_flags */ + OM_uint32, /* time_req */ + gss_channel_bindings_t, + /* input_chan_bindings */ + gss_buffer_t, /* input_token */ + gss_OID*, /* actual_mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32*, /* ret_flags */ + OM_uint32*, /* time_rec */ + krb5_gss_ctx_ext_t /* exts */ +); + +#ifndef LEAN_CLIENT +OM_uint32 KRB5_CALLCONV krb5_gss_accept_sec_context +(OM_uint32*, /* minor_status */ + gss_ctx_id_t*, /* context_handle */ + gss_cred_id_t, /* verifier_cred_handle */ + gss_buffer_t, /* input_token_buffer */ + gss_channel_bindings_t, + /* input_chan_bindings */ + gss_name_t*, /* src_name */ + gss_OID*, /* mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32*, /* ret_flags */ + OM_uint32*, /* time_rec */ + gss_cred_id_t* /* delegated_cred_handle */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_accept_sec_context_ext +(OM_uint32*, /* minor_status */ + gss_ctx_id_t*, /* context_handle */ + gss_cred_id_t, /* verifier_cred_handle */ + gss_buffer_t, /* input_token_buffer */ + gss_channel_bindings_t, + /* input_chan_bindings */ + gss_name_t*, /* src_name */ + gss_OID*, /* mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32*, /* ret_flags */ + OM_uint32*, /* time_rec */ + gss_cred_id_t*, /* delegated_cred_handle */ + krb5_gss_ctx_ext_t/*exts */ +); +#endif /* LEAN_CLIENT */ + +OM_uint32 KRB5_CALLCONV krb5_gss_inquire_sec_context_by_oid +(OM_uint32*, /* minor_status */ + const gss_ctx_id_t, + /* context_handle */ + const gss_OID, /* desired_object */ + gss_buffer_set_t* /* data_set */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_set_sec_context_option +(OM_uint32*, /* minor_status */ + gss_ctx_id_t*, /* context_handle */ + const gss_OID, /* desired_object */ + const gss_buffer_t/* value */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_process_context_token +(OM_uint32*, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t /* token_buffer */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_delete_sec_context +(OM_uint32*, /* minor_status */ + gss_ctx_id_t*, /* context_handle */ + gss_buffer_t /* output_token */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_context_time +(OM_uint32*, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + OM_uint32* /* time_rec */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_display_status +(OM_uint32*, /* minor_status */ + OM_uint32, /* status_value */ + int, /* status_type */ + gss_OID, /* mech_type */ + OM_uint32*, /* message_context */ + gss_buffer_t /* status_string */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_indicate_mechs +(OM_uint32*, /* minor_status */ + gss_OID_set* /* mech_set */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_compare_name +(OM_uint32*, /* minor_status */ + gss_name_t, /* name1 */ + gss_name_t, /* name2 */ + int* /* name_equal */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_display_name +(OM_uint32*, /* minor_status */ + gss_name_t, /* input_name */ + gss_buffer_t, /* output_name_buffer */ + gss_OID* /* output_name_type */ +); + + +OM_uint32 KRB5_CALLCONV krb5_gss_import_name +(OM_uint32*, /* minor_status */ + gss_buffer_t, /* input_name_buffer */ + gss_OID, /* input_name_type */ + gss_name_t* /* output_name */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_release_name +(OM_uint32*, /* minor_status */ + gss_name_t* /* input_name */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_inquire_cred +(OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* cred_handle */ + gss_name_t *, /* name */ + OM_uint32 *, /* lifetime */ + gss_cred_usage_t*,/* cred_usage */ + gss_OID_set * /* mechanisms */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_inquire_context +(OM_uint32*, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_name_t*, /* initiator_name */ + gss_name_t*, /* acceptor_name */ + OM_uint32*, /* lifetime_rec */ + gss_OID*, /* mech_type */ + OM_uint32*, /* ret_flags */ + int*, /* locally_initiated */ + int* /* open */ +); + +/* New V2 entry points */ +OM_uint32 KRB5_CALLCONV krb5_gss_get_mic +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t, /* qop_req */ + gss_buffer_t, /* message_buffer */ + gss_buffer_t /* message_token */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_get_mic_iov +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t, /* qop_req */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_get_mic_iov_length +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t, /* qop_req */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_verify_mic +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t, /* message_buffer */ + gss_buffer_t, /* message_token */ + gss_qop_t * /* qop_state */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_verify_mic_iov +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t *, /* qop_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_wrap +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + gss_buffer_t, /* input_message_buffer */ + int *, /* conf_state */ + gss_buffer_t /* output_message_buffer */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_wrap_iov +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + int *, /* conf_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_wrap_iov_length +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + int *, /* conf_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_unwrap +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t, /* input_message_buffer */ + gss_buffer_t, /* output_message_buffer */ + int *, /* conf_state */ + gss_qop_t * /* qop_state */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_unwrap_iov +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int *, /* conf_state */ + gss_qop_t *, /* qop_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_wrap_size_limit +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + OM_uint32, /* req_output_size */ + OM_uint32 * /* max_input_size */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_import_name_object +(OM_uint32 *, /* minor_status */ + void *, /* input_name */ + gss_OID, /* input_name_type */ + gss_name_t * /* output_name */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_export_name_object +(OM_uint32 *, /* minor_status */ + gss_name_t, /* input_name */ + gss_OID, /* desired_name_type */ + void * * /* output_name */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_inquire_cred_by_mech +(OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* cred_handle */ + gss_OID, /* mech_type */ + gss_name_t *, /* name */ + OM_uint32 *, /* initiator_lifetime */ + OM_uint32 *, /* acceptor_lifetime */ + gss_cred_usage_t * /* cred_usage */ +); +#ifndef LEAN_CLIENT +OM_uint32 KRB5_CALLCONV krb5_gss_export_sec_context +(OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + gss_buffer_t /* interprocess_token */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_import_sec_context +(OM_uint32 *, /* minor_status */ + gss_buffer_t, /* interprocess_token */ + gss_ctx_id_t * /* context_handle */ +); +#endif /* LEAN_CLIENT */ + +OM_uint32 krb5_gss_release_oid +(OM_uint32 *, /* minor_status */ + gss_OID * /* oid */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_internal_release_oid +(OM_uint32 *, /* minor_status */ + gss_OID * /* oid */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_inquire_names_for_mech +(OM_uint32 *, /* minor_status */ + gss_OID, /* mechanism */ + gss_OID_set * /* name_types */ +); + +OM_uint32 krb5_gss_canonicalize_name +(OM_uint32 *, /* minor_status */ + const gss_name_t, /* input_name */ + const gss_OID, /* mech_type */ + gss_name_t * /* output_name */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_export_name +(OM_uint32 *, /* minor_status */ + const gss_name_t, /* input_name */ + gss_buffer_t /* exported_name */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_duplicate_name +(OM_uint32 *, /* minor_status */ + const gss_name_t, /* input_name */ + gss_name_t * /* dest_name */ +); + +OM_uint32 krb5_gss_validate_cred +(OM_uint32 *, /* minor_status */ + gss_cred_id_t /* cred */ +); + +OM_uint32 KRB5_CALLCONV krb5_gss_acquire_cred_impersonate_name( + OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* impersonator_cred_handle */ + const gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + const gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *); /* time_rec */ + +OM_uint32 +krb5_gss_validate_cred_1(OM_uint32 * /* minor_status */, + gss_cred_id_t /* cred_handle */, + krb5_context /* context */); + +gss_OID krb5_gss_convert_static_mech_oid(gss_OID oid); + +krb5_error_code gss_krb5int_make_seal_token_v3(krb5_context, + krb5_gss_ctx_id_rec *, + const gss_buffer_desc *, + gss_buffer_t, + int, int); + +OM_uint32 gss_krb5int_unseal_token_v3(krb5_context *contextptr, + OM_uint32 *minor_status, + krb5_gss_ctx_id_rec *ctx, + unsigned char *ptr, + unsigned int bodysize, + gss_buffer_t message_buffer, + int *conf_state, gss_qop_t *qop_state, + int toktype); + +int gss_krb5int_rotate_left (void *ptr, size_t bufsiz, size_t rc); + +/* naming_exts.c */ +#define KG_INIT_NAME_NO_COPY 0x1 + +krb5_error_code +kg_init_name(krb5_context context, krb5_principal principal, + char *service, char *host, krb5_authdata_context ad_context, + krb5_flags flags, krb5_gss_name_t *name); + +krb5_error_code +kg_release_name(krb5_context context, krb5_gss_name_t *name); + +krb5_error_code +kg_duplicate_name(krb5_context context, const krb5_gss_name_t src, + krb5_gss_name_t *dst); + +krb5_boolean +kg_compare_name(krb5_context context, + krb5_gss_name_t name1, + krb5_gss_name_t name2); + +krb5_boolean +kg_acceptor_princ(krb5_context context, krb5_gss_name_t name, + krb5_principal *princ_out); + +OM_uint32 KRB5_CALLCONV +krb5_gss_display_name_ext(OM_uint32 *minor_status, + gss_name_t name, + gss_OID display_as_name_type, + gss_buffer_t display_name); + +OM_uint32 KRB5_CALLCONV +krb5_gss_inquire_name(OM_uint32 *minor_status, + gss_name_t name, + int *name_is_MN, + gss_OID *MN_mech, + gss_buffer_set_t *attrs); + +OM_uint32 KRB5_CALLCONV +krb5_gss_get_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more); + +OM_uint32 KRB5_CALLCONV +krb5_gss_set_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + int complete, + gss_buffer_t attr, + gss_buffer_t value); + +OM_uint32 KRB5_CALLCONV +krb5_gss_delete_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t attr); + +OM_uint32 KRB5_CALLCONV +krb5_gss_export_name_composite(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t exp_composite_name); + +OM_uint32 KRB5_CALLCONV +krb5_gss_map_name_to_any(OM_uint32 *minor_status, + gss_name_t name, + int authenticated, + gss_buffer_t type_id, + gss_any_t *output); + +OM_uint32 KRB5_CALLCONV +krb5_gss_release_any_name_mapping(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t type_id, + gss_any_t *input); + +OM_uint32 KRB5_CALLCONV +krb5_gss_pseudo_random(OM_uint32 *minor_status, + gss_ctx_id_t context, + int prf_key, + const gss_buffer_t prf_in, + ssize_t desired_output_len, + gss_buffer_t prf_out); + +OM_uint32 KRB5_CALLCONV +krb5_gss_store_cred(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + gss_cred_usage_t cred_usage, + const gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored); + +/* s4u_gss_glue.c */ +OM_uint32 +kg_compose_deleg_cred(OM_uint32 *minor_status, + krb5_gss_cred_id_t impersonator_cred, + krb5_creds *subject_creds, + OM_uint32 time_req, + krb5_gss_cred_id_t *output_cred, + OM_uint32 *time_rec, + krb5_context context); + +/* + * These take unglued krb5-mech-specific contexts. + */ + +#define GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH 11 +#define GSS_KRB5_GET_TKT_FLAGS_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x01" + +OM_uint32 gss_krb5int_get_tkt_flags +(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set); + +#define GSS_KRB5_COPY_CCACHE_OID_LENGTH 11 +#define GSS_KRB5_COPY_CCACHE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x02" + +OM_uint32 gss_krb5int_copy_ccache +(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_oid, + const gss_buffer_t value); + +#define GSS_KRB5_CCACHE_NAME_OID_LENGTH 11 +#define GSS_KRB5_CCACHE_NAME_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x03" + +struct krb5_gss_ccache_name_req { + const char *name; + const char **out_name; +}; + +OM_uint32 +gss_krb5int_ccache_name(OM_uint32 *minor_status, const gss_OID, const gss_OID, + const gss_buffer_t); + +#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11 +#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05" +#define GSS_KRB5_INQ_ODBC_SESSION_KEY_OID_LENGTH 11 +#define GSS_KRB5_INQ_ODBC_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x13" + +OM_uint32 +gss_krb5int_inq_sspi_session_key(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *); +OM_uint32 +gss_krb5int_inq_odbc_session_key(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *); + +#define GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID_LENGTH 11 +#define GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x04" + +struct krb5_gss_set_allowable_enctypes_req { + OM_uint32 num_ktypes; + krb5_enctype *ktypes; +}; + +OM_uint32 +gss_krb5int_set_allowable_enctypes(OM_uint32 *minor_status, + gss_cred_id_t *cred, + const gss_OID desired_oid, + const gss_buffer_t value); + +#define GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH 11 +#define GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x06" + +OM_uint32 +gss_krb5int_export_lucid_sec_context(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set); + +#define GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID_LENGTH 11 +#define GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x07" + +OM_uint32 +gss_krb5int_free_lucid_sec_context(OM_uint32 *, const gss_OID, + const gss_OID, gss_buffer_t); + +extern k5_mutex_t kg_kdc_flag_mutex; +krb5_error_code krb5_gss_init_context (krb5_context *ctxp); + +#define GSS_KRB5_USE_KDC_CONTEXT_OID_LENGTH 11 +#define GSS_KRB5_USE_KDC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x08" + +OM_uint32 krb5int_gss_use_kdc_context(OM_uint32 *, const gss_OID, + const gss_OID, gss_buffer_t); + +krb5_error_code krb5_gss_use_kdc_context(void); + +#define GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID_LENGTH 11 +#define GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x09" + +OM_uint32 +gss_krb5int_register_acceptor_identity(OM_uint32 *, const gss_OID, const gss_OID, gss_buffer_t); + +#define GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH 11 +#define GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0a" + +OM_uint32 +gss_krb5int_extract_authz_data_from_sec_context(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *ad_data); + +#define GSS_KRB5_SET_CRED_RCACHE_OID_LENGTH 11 +#define GSS_KRB5_SET_CRED_RCACHE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0b" + +OM_uint32 +gss_krb5int_set_cred_rcache(OM_uint32 *, gss_cred_id_t *, const gss_OID, const gss_buffer_t); + +#define GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH 11 +#define GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0c" + +OM_uint32 +gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *, + const gss_ctx_id_t, + const gss_OID, + gss_buffer_set_t *); + +#define GET_SEC_CONTEXT_SASL_SSF_OID_LENGTH 11 +#define GET_SEC_CONTEXT_SASL_SSF_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f" +OM_uint32 +gss_krb5int_sec_context_sasl_ssf(OM_uint32 *, const gss_ctx_id_t, + const gss_OID, gss_buffer_set_t *); + +#define GSS_KRB5_IMPORT_CRED_OID_LENGTH 11 +#define GSS_KRB5_IMPORT_CRED_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0d" + +struct krb5_gss_import_cred_req { + krb5_ccache id; + krb5_principal keytab_principal; + krb5_keytab keytab; +}; + +OM_uint32 +gss_krb5int_import_cred(OM_uint32 *minor_status, + gss_cred_id_t *cred, + const gss_OID desired_oid, + const gss_buffer_t value); + +#ifdef _GSS_STATIC_LINK +int gss_krb5int_lib_init(void); +void gss_krb5int_lib_fini(void); +#endif /* _GSS_STATIC_LINK */ + +OM_uint32 gss_krb5int_initialize_library(void); +void gss_krb5int_cleanup_library(void); + +/* For error message handling. */ +/* Returns a shared string, not a private copy! */ +extern char * +krb5_gss_get_error_message(OM_uint32 minor_code); +extern void +krb5_gss_save_error_string(OM_uint32 minor_code, char *msg); +extern void +krb5_gss_save_error_message(OM_uint32 minor_code, const char *format, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 3))) +#endif + ; + extern void + krb5_gss_save_error_info(OM_uint32 minor_code, krb5_context ctx); +#define get_error_message krb5_gss_get_error_message +#define save_error_string krb5_gss_save_error_string +#define save_error_message krb5_gss_save_error_message +#ifdef KRB5_KERNEL +/* Error messages aren't needed in the kernel, so reduce dependencies. */ +#define save_error_info(x,y) +#else +#define save_error_info krb5_gss_save_error_info +#endif +extern void krb5_gss_delete_error_info(void *p); + +/* Prefix concatenated with Kerberos encryption type */ +#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH 10 +#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04" + +/* IAKERB */ + +OM_uint32 KRB5_CALLCONV +iakerb_gss_init_sec_context(OM_uint32 *minor_status, + gss_cred_id_t claimant_cred_handle, + gss_ctx_id_t *context_handle, + gss_name_t target_name, + gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_OID *actual_mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_accept_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handler, + gss_cred_id_t verifier_cred_handle, + gss_buffer_t input_token, + gss_channel_bindings_t input_chan_bindings, + gss_name_t *src_name, + gss_OID *mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec, + gss_cred_id_t *delegated_cred_handle); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_delete_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token); + +krb5_error_code +iakerb_make_finished(krb5_context context, + krb5_key key, + const krb5_data *conv, + krb5_data **finished); + +krb5_error_code +iakerb_verify_finished(krb5_context context, + krb5_key key, + const krb5_data *conv, + const krb5_data *finished); + +/* + * Transfer contents of a krb5_data to a gss_buffer and invalidate the source + * On unix, this is a simple pointer copy + * On windows, memory is reallocated and copied. + */ +static inline krb5_error_code +data_to_gss(krb5_data *input_k5data, gss_buffer_t output_buffer) +{ + krb5_error_code code = 0; + output_buffer->length = input_k5data->length; +#if defined(_WIN32) || defined(DEBUG_GSSALLOC) + if (output_buffer->length > 0) { + output_buffer->value = gssalloc_malloc(output_buffer->length); + if (output_buffer->value) + memcpy(output_buffer->value, input_k5data->data, output_buffer->length); + else + code = ENOMEM; + } else { + output_buffer->value = NULL; + } + free(input_k5data->data); +#else + output_buffer->value = input_k5data->data; +#endif + *input_k5data = empty_data(); + return code; +} + +#define KRB5_GSS_EXTS_IAKERB_FINISHED 1 + + +/* Credential store extensions */ + +#define KRB5_CS_CLI_KEYTAB_URN "client_keytab" +#define KRB5_CS_KEYTAB_URN "keytab" +#define KRB5_CS_CCACHE_URN "ccache" +#define KRB5_CS_RCACHE_URN "rcache" +#define KRB5_CS_PASSWORD_URN "password" +#define KRB5_CS_VERIFY_URN "verify" + +OM_uint32 +kg_value_from_cred_store(gss_const_key_value_set_t cred_store, + const char *type, const char **value); + +OM_uint32 KRB5_CALLCONV +krb5_gss_acquire_cred_from( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + const gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_const_key_value_set_t, /* cred_store */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *); /* time_rec */ + +OM_uint32 KRB5_CALLCONV +krb5_gss_store_cred_into( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* input_cred_handle */ + gss_cred_usage_t, /* input_usage */ + const gss_OID, /* desired_mech */ + OM_uint32, /* overwrite_cred */ + OM_uint32, /* default_cred */ + gss_const_key_value_set_t, /* cred_store */ + gss_OID_set *, /* elements_stored */ + gss_cred_usage_t *); /* cred_usage_stored */ + +OM_uint32 KRB5_CALLCONV +krb5_gss_export_cred(OM_uint32 *minor_status, gss_cred_id_t cred_handle, + gss_buffer_t token); + +OM_uint32 KRB5_CALLCONV +krb5_gss_import_cred(OM_uint32 *minor_status, gss_buffer_t token, + gss_cred_id_t *cred_handle); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_process_context_token(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_buffer); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_context_time(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + OM_uint32 *time_rec); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_inquire_context(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, gss_name_t *src_name, + gss_name_t *targ_name, OM_uint32 *lifetime_rec, + gss_OID *mech_type, OM_uint32 *ctx_flags, + int *locally_initiated, int *opened); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_get_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_qop_t qop_req, gss_buffer_t message_buffer, + gss_buffer_t message_token); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_get_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_qop_t qop_req, gss_iov_buffer_desc *iov, + int iov_count); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_get_mic_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, gss_qop_t qop_req, + gss_iov_buffer_desc *iov, int iov_count); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_verify_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_buffer_t msg_buffer, gss_buffer_t token_buffer, + gss_qop_t *qop_state); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_verify_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_qop_t *qop_state, gss_iov_buffer_desc *iov, + int iov_count); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_wrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + int conf_req_flag, gss_qop_t qop_req, + gss_buffer_t input_message_buffer, int *conf_state, + gss_buffer_t output_message_buffer); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_wrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + int conf_req_flag, gss_qop_t qop_req, int *conf_state, + gss_iov_buffer_desc *iov, int iov_count); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_wrap_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, int conf_req_flag, + gss_qop_t qop_req, int *conf_state, + gss_iov_buffer_desc *iov, int iov_count); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_unwrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, int *conf_state, + gss_qop_t *qop_state); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_unwrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + int *conf_state, gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, int iov_count); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_wrap_size_limit(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, int conf_req_flag, + gss_qop_t qop_req, OM_uint32 req_output_size, + OM_uint32 *max_input_size); + +#ifndef LEAN_CLIENT +OM_uint32 KRB5_CALLCONV +iakerb_gss_export_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t interprocess_token); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_import_sec_context(OM_uint32 *minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle); +#endif /* LEAN_CLIENT */ + +OM_uint32 KRB5_CALLCONV +iakerb_gss_inquire_sec_context_by_oid(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_set_sec_context_option(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value); + +OM_uint32 KRB5_CALLCONV +iakerb_gss_pseudo_random(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + int prf_key, const gss_buffer_t prf_in, + ssize_t desired_output_len, gss_buffer_t prf_out); + +/* Magic string to identify exported krb5 GSS credentials. Increment this if + * the format changes. */ +#define CRED_EXPORT_MAGIC "K5C1" + +OM_uint32 +gss_krb5int_get_cred_impersonator(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set); + +#endif /* _GSSAPIP_KRB5_H_ */ diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/gssapi_err_krb5.et b/krb5-1.21.3/src/lib/gssapi/krb5/gssapi_err_krb5.et new file mode 100644 index 00000000..6396d590 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/gssapi_err_krb5.et @@ -0,0 +1,42 @@ +# +# Copyright 1993 by OpenVision Technologies, Inc. +# +# Permission to use, copy, modify, distribute, and sell this software +# and its documentation for any purpose is hereby granted without fee, +# provided that the above copyright notice appears in all copies and +# that both that copyright notice and this permission notice appear in +# supporting documentation, and that the name of OpenVision not be used +# in advertising or publicity pertaining to distribution of the software +# without specific, written prior permission. OpenVision makes no +# representations about the suitability of this software for any +# purpose. It is provided "as is" without express or implied warranty. +# +# OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# + +error_table k5g + +error_code KG_CCACHE_NOMATCH, "Principal in credential cache does not match desired name" +error_code KG_KEYTAB_NOMATCH, "No principal in keytab matches desired name" +error_code KG_TGT_MISSING, "Credential cache has no TGT" +error_code KG_NO_SUBKEY, "Authenticator has no subkey" +error_code KG_CONTEXT_ESTABLISHED, "Context is already fully established" +error_code KG_BAD_SIGN_TYPE, "Unknown signature type in token" +error_code KG_BAD_LENGTH, "Invalid field length in token" +error_code KG_CTX_INCOMPLETE, "Attempt to use incomplete security context" +error_code KG_CONTEXT, "Bad magic number for krb5_gss_ctx_id_t" +error_code KG_CRED, "Bad magic number for krb5_gss_cred_id_t" +error_code KG_ENC_DESC, "Bad magic number for krb5_gss_enc_desc" +error_code KG_BAD_SEQ, "Sequence number in token is corrupt" +error_code KG_EMPTY_CCACHE, "Credential cache is empty" +error_code KG_NO_CTYPES, "Acceptor and Initiator share no checksum types" +error_code KG_LUCID_VERSION, "Requested lucid context version not supported" +error_code KG_INPUT_TOO_LONG, "PRF input too long" +error_code KG_IAKERB_CONTEXT, "Bad magic number for iakerb_ctx_id_t" +end diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/gssapi_krb5.c b/krb5-1.21.3/src/lib/gssapi/krb5/gssapi_krb5.c new file mode 100644 index 00000000..1e62b07c --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/gssapi_krb5.c @@ -0,0 +1,1132 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +/* + * $Id$ + */ + + +#include "gssapiP_krb5.h" +#include "mglueP.h" + +#ifndef NO_PASSWORD +#include +#endif + +/** exported constants defined in gssapi_krb5{,_nx}.h **/ + +/* these are bogus, but will compile */ + +/* + * The OID of the draft krb5 mechanism, assigned by IETF, is: + * iso(1) org(3) dod(5) internet(1) security(5) + * kerberosv5(2) = 1.3.5.1.5.2 + * The OID of the krb5_name type is: + * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5_name(1) = 1.2.840.113554.1.2.2.1 + * The OID of the krb5_principal type is: + * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5_principal(2) = 1.2.840.113554.1.2.2.2 + * The OID of the proposed standard krb5 mechanism is: + * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) = 1.2.840.113554.1.2.2 + * The OID of the proposed standard krb5 v2 mechanism is: + * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) + * krb5v2(3) = 1.2.840.113554.1.2.3 + * Provisionally reserved for Kerberos session key algorithm + * identifiers is: + * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5_enctype(4) = 1.2.840.113554.1.2.2.4 + * Provisionally reserved for Kerberos mechanism-specific APIs: + * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5_gssapi_ext(5) = 1.2.840.113554.1.2.2.5 + */ + +/* + * Encoding rules: The first two values are encoded in one byte as 40 + * * value1 + value2. Subsequent values are encoded base 128, most + * significant digit first, with the high bit (\200) set on all octets + * except the last in each value's encoding. + */ + +#define NO_CI_FLAGS_X_OID_LENGTH 6 +#define NO_CI_FLAGS_X_OID "\x2a\x85\x70\x2b\x0d\x1d" +#define GET_CRED_IMPERSONATOR_OID_LENGTH 11 +#define GET_CRED_IMPERSONATOR_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0e" + +const gss_OID_desc krb5_gss_oid_array[] = { + /* this is the official, rfc-specified OID */ + {GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID}, + /* this pre-RFC mech OID */ + {GSS_MECH_KRB5_OLD_OID_LENGTH, GSS_MECH_KRB5_OLD_OID}, + /* this is the unofficial, incorrect mech OID emitted by MS */ + {GSS_MECH_KRB5_WRONG_OID_LENGTH, GSS_MECH_KRB5_WRONG_OID}, + /* IAKERB OID */ + {GSS_MECH_IAKERB_OID_LENGTH, GSS_MECH_IAKERB_OID}, + /* this is the v2 assigned OID */ + {9, "\052\206\110\206\367\022\001\002\003"}, + /* these two are name type OID's */ + /* 2.1.1. Kerberos Principal Name Form: (rfc 1964) + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5_name(1)}. The recommended symbolic name for this type + * is "GSS_KRB5_NT_PRINCIPAL_NAME". */ + {10, "\052\206\110\206\367\022\001\002\002\001"}, + /* gss_nt_krb5_principal. Object identifier for a krb5_principal. Do not use. */ + {10, "\052\206\110\206\367\022\001\002\002\002"}, + {NO_CI_FLAGS_X_OID_LENGTH, NO_CI_FLAGS_X_OID}, + /* this is an inquire cred OID */ + {GET_CRED_IMPERSONATOR_OID_LENGTH, GET_CRED_IMPERSONATOR_OID}, + /* GSS_KRB5_NT_ENTERPRISE_NAME */ + {10, "\052\206\110\206\367\022\001\002\002\006"}, + /* GSS_KRB5_NT_X509_CERT */ + {10, "\052\206\110\206\367\022\001\002\002\007"}, + { 0, 0 } +}; + +#define kg_oids ((gss_OID)krb5_gss_oid_array) + +const gss_OID gss_mech_krb5 = &kg_oids[0]; +const gss_OID gss_mech_krb5_old = &kg_oids[1]; +const gss_OID gss_mech_krb5_wrong = &kg_oids[2]; +const gss_OID gss_mech_iakerb = &kg_oids[3]; + + +const gss_OID gss_nt_krb5_name = &kg_oids[5]; +const gss_OID gss_nt_krb5_principal = &kg_oids[6]; +const gss_OID GSS_KRB5_NT_PRINCIPAL_NAME = &kg_oids[5]; + +const gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X = &kg_oids[7]; +const gss_OID GSS_KRB5_GET_CRED_IMPERSONATOR = &kg_oids[8]; +const gss_OID GSS_KRB5_NT_ENTERPRISE_NAME = &kg_oids[9]; +const gss_OID GSS_KRB5_NT_X509_CERT = &kg_oids[10]; + +static const gss_OID_set_desc oidsets[] = { + {1, &kg_oids[0]}, /* RFC OID */ + {1, &kg_oids[1]}, /* pre-RFC OID */ + {3, &kg_oids[0]}, /* all names for krb5 mech */ + {4, &kg_oids[0]}, /* all krb5 names and IAKERB */ +}; + +#define kg_oidsets ((gss_OID_set)oidsets) + +const gss_OID_set gss_mech_set_krb5 = &kg_oidsets[0]; +const gss_OID_set gss_mech_set_krb5_old = &kg_oidsets[1]; +const gss_OID_set gss_mech_set_krb5_both = &kg_oidsets[2]; +const gss_OID_set kg_all_mechs = &kg_oidsets[3]; + +g_set kg_vdb = G_SET_INIT; + +/** default credential support */ + +/* + * init_sec_context() will explicitly re-acquire default credentials, + * so handling the expiration/invalidation condition here isn't needed. + */ +OM_uint32 +kg_get_defcred(minor_status, cred) + OM_uint32 *minor_status; + gss_cred_id_t *cred; +{ + OM_uint32 major; + + if ((major = krb5_gss_acquire_cred(minor_status, + (gss_name_t) NULL, GSS_C_INDEFINITE, + GSS_C_NULL_OID_SET, GSS_C_INITIATE, + cred, NULL, NULL)) && GSS_ERROR(major)) { + return(major); + } + *minor_status = 0; + return(GSS_S_COMPLETE); +} + +OM_uint32 +kg_sync_ccache_name (krb5_context context, OM_uint32 *minor_status) +{ + OM_uint32 err = 0; + + /* + * Sync up the context ccache name with the GSSAPI ccache name. + * If kg_ccache_name is NULL -- normal unless someone has called + * gss_krb5_ccache_name() -- then the system default ccache will + * be picked up and used by resetting the context default ccache. + * This is needed for platforms which support multiple ccaches. + */ + + if (!err) { + /* if NULL, resets the context default ccache */ + err = krb5_cc_set_default_name(context, + (char *) k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME)); + } + + *minor_status = err; + return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +/* This function returns whether or not the caller set a cccache name. Used by + * gss_acquire_cred to figure out if the caller wants to only look at this + * ccache or search the cache collection for the desired name */ +OM_uint32 +kg_caller_provided_ccache_name (OM_uint32 *minor_status, + int *out_caller_provided_name) +{ + if (out_caller_provided_name) { + *out_caller_provided_name = + (k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME) != NULL); + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +kg_get_ccache_name(OM_uint32 *minor_status, char **out_name) +{ + char *kg_ccache_name; + const char *def_name; + OM_uint32 err; + krb5_context context; + + *out_name = NULL; + + kg_ccache_name = k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME); + if (kg_ccache_name != NULL) { + *out_name = strdup(kg_ccache_name); + err = (*out_name == NULL) ? ENOMEM : 0; + } else { + /* Use the default ccache name. */ + err = krb5_gss_init_context(&context); + if (err) + goto cleanup; + def_name = krb5_cc_default_name(context); + *out_name = (def_name != NULL) ? strdup(def_name) : NULL; + err = (*out_name == NULL) ? ENOMEM : 0; + krb5_free_context(context); + } + +cleanup: + *minor_status = err; + return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +OM_uint32 +kg_set_ccache_name (OM_uint32 *minor_status, const char *name) +{ + char *new_name = NULL; + char *swap = NULL; + char *kg_ccache_name; + krb5_error_code kerr; + + if (name) { + new_name = strdup(name); + if (new_name == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + } + + kg_ccache_name = k5_getspecific(K5_KEY_GSS_KRB5_CCACHE_NAME); + swap = kg_ccache_name; + kg_ccache_name = new_name; + new_name = swap; + kerr = k5_setspecific(K5_KEY_GSS_KRB5_CCACHE_NAME, kg_ccache_name); + if (kerr != 0) { + /* Can't store, so free up the storage. */ + free(kg_ccache_name); + /* ??? free(new_name); */ + *minor_status = kerr; + return GSS_S_FAILURE; + } + + free (new_name); + *minor_status = 0; + return GSS_S_COMPLETE; +} + +#define g_OID_prefix_equal(o1, o2) \ + (((o1)->length >= (o2)->length) && \ + (memcmp((o1)->elements, (o2)->elements, (o2)->length) == 0)) + +/* + * gss_inquire_sec_context_by_oid() methods + */ +static struct { + gss_OID_desc oid; + OM_uint32 (*func)(OM_uint32 *, const gss_ctx_id_t, const gss_OID, gss_buffer_set_t *); +} krb5_gss_inquire_sec_context_by_oid_ops[] = { + { + {GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH, GSS_KRB5_GET_TKT_FLAGS_OID}, + gss_krb5int_get_tkt_flags + }, + { + {GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID}, + gss_krb5int_extract_authz_data_from_sec_context + }, + { + {GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH, GSS_KRB5_INQ_SSPI_SESSION_KEY_OID}, + gss_krb5int_inq_sspi_session_key + }, + { + {GSS_KRB5_INQ_ODBC_SESSION_KEY_OID_LENGTH, GSS_KRB5_INQ_ODBC_SESSION_KEY_OID}, + gss_krb5int_inq_odbc_session_key + }, + { + {GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID}, + gss_krb5int_export_lucid_sec_context + }, + { + {GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID}, + gss_krb5int_extract_authtime_from_sec_context + }, + { + {GET_SEC_CONTEXT_SASL_SSF_OID_LENGTH, GET_SEC_CONTEXT_SASL_SSF_OID}, + gss_krb5int_sec_context_sasl_ssf + } +}; + +OM_uint32 KRB5_CALLCONV +krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_gss_ctx_id_rec *ctx; + size_t i; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + if (desired_object == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (data_set == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *data_set = GSS_C_NO_BUFFER_SET; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + + if (ctx->terminated || !ctx->established) + return GSS_S_NO_CONTEXT; + + for (i = 0; i < sizeof(krb5_gss_inquire_sec_context_by_oid_ops)/ + sizeof(krb5_gss_inquire_sec_context_by_oid_ops[0]); i++) { + if (g_OID_prefix_equal(desired_object, &krb5_gss_inquire_sec_context_by_oid_ops[i].oid)) { + return (*krb5_gss_inquire_sec_context_by_oid_ops[i].func)(minor_status, + context_handle, + desired_object, + data_set); + } + } + + *minor_status = EINVAL; + + return GSS_S_UNAVAILABLE; +} + +/* + * gss_inquire_cred_by_oid() methods + */ + +static struct { + gss_OID_desc oid; + OM_uint32 (*func)(OM_uint32 *, const gss_cred_id_t, const gss_OID, gss_buffer_set_t *); +} krb5_gss_inquire_cred_by_oid_ops[] = { + { + {GET_CRED_IMPERSONATOR_OID_LENGTH, GET_CRED_IMPERSONATOR_OID}, + gss_krb5int_get_cred_impersonator + } +}; + +static OM_uint32 KRB5_CALLCONV +krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + OM_uint32 major_status = GSS_S_FAILURE; + size_t i; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + if (desired_object == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (data_set == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *data_set = GSS_C_NO_BUFFER_SET; + if (cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = (OM_uint32)KRB5_NOCREDS_SUPPLIED; + return GSS_S_NO_CRED; + } + + major_status = krb5_gss_validate_cred(minor_status, cred_handle); + if (GSS_ERROR(major_status)) + return major_status; + + for (i = 0; i < sizeof(krb5_gss_inquire_cred_by_oid_ops)/ + sizeof(krb5_gss_inquire_cred_by_oid_ops[0]); i++) { + if (g_OID_prefix_equal(desired_object, &krb5_gss_inquire_cred_by_oid_ops[i].oid)) { + return (*krb5_gss_inquire_cred_by_oid_ops[i].func)(minor_status, + cred_handle, + desired_object, + data_set); + } + } + + *minor_status = EINVAL; + + return GSS_S_UNAVAILABLE; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_set_sec_context_option (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + if (context_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (desired_object == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + *minor_status = EINVAL; + + return GSS_S_UNAVAILABLE; +} + +static OM_uint32 +no_ci_flags(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_oid, + const gss_buffer_t value) +{ + krb5_gss_cred_id_t cred; + + cred = (krb5_gss_cred_id_t) *cred_handle; + cred->suppress_ci_flags = 1; + + *minor_status = 0; + return GSS_S_COMPLETE; +} +/* + * gssspi_set_cred_option() methods + */ +static struct { + gss_OID_desc oid; + OM_uint32 (*func)(OM_uint32 *, gss_cred_id_t *, const gss_OID, const gss_buffer_t); +} krb5_gssspi_set_cred_option_ops[] = { + { + {GSS_KRB5_COPY_CCACHE_OID_LENGTH, GSS_KRB5_COPY_CCACHE_OID}, + gss_krb5int_copy_ccache + }, + { + {GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID_LENGTH, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID}, + gss_krb5int_set_allowable_enctypes + }, + { + {GSS_KRB5_SET_CRED_RCACHE_OID_LENGTH, GSS_KRB5_SET_CRED_RCACHE_OID}, + gss_krb5int_set_cred_rcache + }, + { + {GSS_KRB5_IMPORT_CRED_OID_LENGTH, GSS_KRB5_IMPORT_CRED_OID}, + gss_krb5int_import_cred + }, + { + {NO_CI_FLAGS_X_OID_LENGTH, NO_CI_FLAGS_X_OID}, + no_ci_flags + }, +}; + +static OM_uint32 KRB5_CALLCONV +krb5_gssspi_set_cred_option(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + OM_uint32 major_status = GSS_S_FAILURE; + size_t i; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (cred_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + if (desired_object == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (*cred_handle != GSS_C_NO_CREDENTIAL) { + major_status = krb5_gss_validate_cred(minor_status, *cred_handle); + if (GSS_ERROR(major_status)) + return major_status; + } + + for (i = 0; i < sizeof(krb5_gssspi_set_cred_option_ops)/ + sizeof(krb5_gssspi_set_cred_option_ops[0]); i++) { + if (g_OID_prefix_equal(desired_object, &krb5_gssspi_set_cred_option_ops[i].oid)) { + return (*krb5_gssspi_set_cred_option_ops[i].func)(minor_status, + cred_handle, + desired_object, + value); + } + } + + *minor_status = EINVAL; + + return GSS_S_UNAVAILABLE; +} + +/* + * gssspi_mech_invoke() methods + */ +static struct { + gss_OID_desc oid; + OM_uint32 (*func)(OM_uint32 *, const gss_OID, const gss_OID, gss_buffer_t); +} krb5_gssspi_mech_invoke_ops[] = { + { + {GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID_LENGTH, GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID}, + gss_krb5int_register_acceptor_identity + }, + { + {GSS_KRB5_CCACHE_NAME_OID_LENGTH, GSS_KRB5_CCACHE_NAME_OID}, + gss_krb5int_ccache_name + }, + { + {GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID}, + gss_krb5int_free_lucid_sec_context + }, +#ifndef _WIN32 + { + {GSS_KRB5_USE_KDC_CONTEXT_OID_LENGTH, GSS_KRB5_USE_KDC_CONTEXT_OID}, + krb5int_gss_use_kdc_context + }, +#endif +}; + +static OM_uint32 KRB5_CALLCONV +krb5_gssspi_mech_invoke (OM_uint32 *minor_status, + const gss_OID desired_mech, + const gss_OID desired_object, + gss_buffer_t value) +{ + size_t i; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + if (desired_mech == GSS_C_NO_OID) + return GSS_S_BAD_MECH; + + if (desired_object == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + for (i = 0; i < sizeof(krb5_gssspi_mech_invoke_ops)/ + sizeof(krb5_gssspi_mech_invoke_ops[0]); i++) { + if (g_OID_prefix_equal(desired_object, &krb5_gssspi_mech_invoke_ops[i].oid)) { + return (*krb5_gssspi_mech_invoke_ops[i].func)(minor_status, + desired_mech, + desired_object, + value); + } + } + + *minor_status = EINVAL; + + return GSS_S_UNAVAILABLE; +} + +#define GS2_KRB5_SASL_NAME "GS2-KRB5" +#define GS2_KRB5_SASL_NAME_LEN (sizeof(GS2_KRB5_SASL_NAME) - 1) + +#define GS2_IAKERB_SASL_NAME "GS2-IAKERB" +#define GS2_IAKERB_SASL_NAME_LEN (sizeof(GS2_IAKERB_SASL_NAME) - 1) + +static OM_uint32 KRB5_CALLCONV +krb5_gss_inquire_mech_for_saslname(OM_uint32 *minor_status, + const gss_buffer_t sasl_mech_name, + gss_OID *mech_type) +{ + *minor_status = 0; + + if (sasl_mech_name->length == GS2_KRB5_SASL_NAME_LEN && + memcmp(sasl_mech_name->value, + GS2_KRB5_SASL_NAME, GS2_KRB5_SASL_NAME_LEN) == 0) { + if (mech_type != NULL) + *mech_type = (gss_OID)gss_mech_krb5; + return GSS_S_COMPLETE; + } else if (sasl_mech_name->length == GS2_IAKERB_SASL_NAME_LEN && + memcmp(sasl_mech_name->value, + GS2_IAKERB_SASL_NAME, GS2_IAKERB_SASL_NAME_LEN) == 0) { + if (mech_type != NULL) + *mech_type = (gss_OID)gss_mech_iakerb; + return GSS_S_COMPLETE; + } + + return GSS_S_BAD_MECH; +} + +static OM_uint32 KRB5_CALLCONV +krb5_gss_inquire_saslname_for_mech(OM_uint32 *minor_status, + const gss_OID desired_mech, + gss_buffer_t sasl_mech_name, + gss_buffer_t mech_name, + gss_buffer_t mech_description) +{ + if (g_OID_equal(desired_mech, gss_mech_iakerb)) { + if (!g_make_string_buffer(GS2_IAKERB_SASL_NAME, sasl_mech_name) || + !g_make_string_buffer("iakerb", mech_name) || + !g_make_string_buffer("Initial and Pass Through Authentication " + "Kerberos Mechanism (IAKERB)", + mech_description)) + goto fail; + } else { + if (!g_make_string_buffer(GS2_KRB5_SASL_NAME, sasl_mech_name) || + !g_make_string_buffer("krb5", mech_name) || + !g_make_string_buffer("Kerberos 5 GSS-API Mechanism", + mech_description)) + goto fail; + } + + *minor_status = 0; + return GSS_S_COMPLETE; + +fail: + *minor_status = ENOMEM; + return GSS_S_FAILURE; +} + +static OM_uint32 KRB5_CALLCONV +krb5_gss_inquire_attrs_for_mech(OM_uint32 *minor_status, + gss_const_OID mech, + gss_OID_set *mech_attrs, + gss_OID_set *known_mech_attrs) +{ + OM_uint32 major, tmpMinor; + + if (mech_attrs == NULL) { + *minor_status = 0; + return GSS_S_COMPLETE; + } + + major = gss_create_empty_oid_set(minor_status, mech_attrs); + if (GSS_ERROR(major)) + goto cleanup; + +#define MA_SUPPORTED(ma) do { \ + major = gss_add_oid_set_member(minor_status, (gss_OID)ma, \ + mech_attrs); \ + if (GSS_ERROR(major)) \ + goto cleanup; \ + } while (0) + + MA_SUPPORTED(GSS_C_MA_MECH_CONCRETE); + MA_SUPPORTED(GSS_C_MA_ITOK_FRAMED); + MA_SUPPORTED(GSS_C_MA_AUTH_INIT); + MA_SUPPORTED(GSS_C_MA_AUTH_TARG); + MA_SUPPORTED(GSS_C_MA_DELEG_CRED); + MA_SUPPORTED(GSS_C_MA_INTEG_PROT); + MA_SUPPORTED(GSS_C_MA_CONF_PROT); + MA_SUPPORTED(GSS_C_MA_MIC); + MA_SUPPORTED(GSS_C_MA_WRAP); + MA_SUPPORTED(GSS_C_MA_PROT_READY); + MA_SUPPORTED(GSS_C_MA_REPLAY_DET); + MA_SUPPORTED(GSS_C_MA_OOS_DET); + MA_SUPPORTED(GSS_C_MA_CBINDINGS); + MA_SUPPORTED(GSS_C_MA_CTX_TRANS); + + if (g_OID_equal(mech, gss_mech_iakerb)) { + MA_SUPPORTED(GSS_C_MA_AUTH_INIT_INIT); + MA_SUPPORTED(GSS_C_MA_NOT_DFLT_MECH); + } else if (!g_OID_equal(mech, gss_mech_krb5)) { + MA_SUPPORTED(GSS_C_MA_DEPRECATED); + } + +cleanup: + if (GSS_ERROR(major)) + gss_release_oid_set(&tmpMinor, mech_attrs); + + return major; +} + +static OM_uint32 KRB5_CALLCONV +krb5_gss_localname(OM_uint32 *minor, + const gss_name_t pname, + const gss_const_OID mech_type, + gss_buffer_t localname) +{ + krb5_context context; + krb5_error_code code; + krb5_gss_name_t kname; + char lname[BUFSIZ]; + + code = krb5_gss_init_context(&context); + if (code != 0) { + *minor = code; + return GSS_S_FAILURE; + } + + kname = (krb5_gss_name_t)pname; + + code = krb5_aname_to_localname(context, kname->princ, + sizeof(lname), lname); + if (code != 0) { + *minor = KRB5_NO_LOCALNAME; + krb5_free_context(context); + return GSS_S_FAILURE; + } + + + krb5_free_context(context); + localname->value = gssalloc_strdup(lname); + localname->length = strlen(lname); + + return GSS_S_COMPLETE; +} + + +static OM_uint32 KRB5_CALLCONV +krb5_gss_authorize_localname(OM_uint32 *minor, + const gss_name_t pname, + gss_const_buffer_t local_user, + gss_const_OID name_type) +{ + krb5_context context; + krb5_error_code code; + krb5_gss_name_t kname; + char *user; + int user_ok; + + if (name_type != GSS_C_NO_OID && + !g_OID_equal(name_type, GSS_C_NT_USER_NAME)) { + return GSS_S_BAD_NAMETYPE; + } + + kname = (krb5_gss_name_t)pname; + + code = krb5_gss_init_context(&context); + if (code != 0) { + *minor = code; + return GSS_S_FAILURE; + } + + user = k5memdup0(local_user->value, local_user->length, &code); + if (user == NULL) { + *minor = code; + krb5_free_context(context); + return GSS_S_FAILURE; + } + + user_ok = krb5_kuserok(context, kname->princ, user); + + free(user); + krb5_free_context(context); + + *minor = 0; + return user_ok ? GSS_S_COMPLETE : GSS_S_UNAUTHORIZED; +} + +static struct gss_config krb5_mechanism = { + { GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID }, + NULL, + krb5_gss_acquire_cred, + krb5_gss_release_cred, + krb5_gss_init_sec_context, +#ifdef LEAN_CLIENT + NULL, +#else + krb5_gss_accept_sec_context, +#endif + krb5_gss_process_context_token, + krb5_gss_delete_sec_context, + krb5_gss_context_time, + krb5_gss_get_mic, + krb5_gss_verify_mic, +#if defined(IOV_SHIM_EXERCISE_WRAP) || defined(IOV_SHIM_EXERCISE) + NULL, +#else + krb5_gss_wrap, +#endif +#if defined(IOV_SHIM_EXERCISE_UNWRAP) || defined(IOV_SHIM_EXERCISE) + NULL, +#else + krb5_gss_unwrap, +#endif + krb5_gss_display_status, + krb5_gss_indicate_mechs, + krb5_gss_compare_name, + krb5_gss_display_name, + krb5_gss_import_name, + krb5_gss_release_name, + krb5_gss_inquire_cred, + NULL, /* add_cred */ +#ifdef LEAN_CLIENT + NULL, + NULL, +#else + krb5_gss_export_sec_context, + krb5_gss_import_sec_context, +#endif + krb5_gss_inquire_cred_by_mech, + krb5_gss_inquire_names_for_mech, + krb5_gss_inquire_context, + krb5_gss_internal_release_oid, + krb5_gss_wrap_size_limit, + krb5_gss_localname, + + krb5_gss_authorize_localname, + krb5_gss_export_name, + krb5_gss_duplicate_name, + krb5_gss_store_cred, + krb5_gss_inquire_sec_context_by_oid, + krb5_gss_inquire_cred_by_oid, + krb5_gss_set_sec_context_option, + krb5_gssspi_set_cred_option, + krb5_gssspi_mech_invoke, + NULL, /* wrap_aead */ + NULL, /* unwrap_aead */ + krb5_gss_wrap_iov, + krb5_gss_unwrap_iov, + krb5_gss_wrap_iov_length, + NULL, /* complete_auth_token */ + krb5_gss_acquire_cred_impersonate_name, + NULL, /* krb5_gss_add_cred_impersonate_name */ + NULL, /* display_name_ext */ + krb5_gss_inquire_name, + krb5_gss_get_name_attribute, + krb5_gss_set_name_attribute, + krb5_gss_delete_name_attribute, + krb5_gss_export_name_composite, + krb5_gss_map_name_to_any, + krb5_gss_release_any_name_mapping, + krb5_gss_pseudo_random, + NULL, /* set_neg_mechs */ + krb5_gss_inquire_saslname_for_mech, + krb5_gss_inquire_mech_for_saslname, + krb5_gss_inquire_attrs_for_mech, + krb5_gss_acquire_cred_from, + krb5_gss_store_cred_into, + krb5_gss_acquire_cred_with_password, + krb5_gss_export_cred, + krb5_gss_import_cred, + NULL, /* import_sec_context_by_mech */ + NULL, /* import_name_by_mech */ + NULL, /* import_cred_by_mech */ + krb5_gss_get_mic_iov, + krb5_gss_verify_mic_iov, + krb5_gss_get_mic_iov_length, +}; + +/* Functions which use security contexts or acquire creds are IAKERB-specific; + * other functions can borrow from the krb5 mech. */ +static struct gss_config iakerb_mechanism = { + { GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID }, + NULL, + iakerb_gss_acquire_cred, + krb5_gss_release_cred, + iakerb_gss_init_sec_context, +#ifdef LEAN_CLIENT + NULL, +#else + iakerb_gss_accept_sec_context, +#endif + iakerb_gss_process_context_token, + iakerb_gss_delete_sec_context, + iakerb_gss_context_time, + iakerb_gss_get_mic, + iakerb_gss_verify_mic, +#if defined(IOV_SHIM_EXERCISE_WRAP) || defined(IOV_SHIM_EXERCISE) + NULL, +#else + iakerb_gss_wrap, +#endif +#if defined(IOV_SHIM_EXERCISE_UNWRAP) || defined(IOV_SHIM_EXERCISE) + NULL, +#else + iakerb_gss_unwrap, +#endif + krb5_gss_display_status, + krb5_gss_indicate_mechs, + krb5_gss_compare_name, + krb5_gss_display_name, + krb5_gss_import_name, + krb5_gss_release_name, + krb5_gss_inquire_cred, + NULL, /* add_cred */ +#ifdef LEAN_CLIENT + NULL, + NULL, +#else + iakerb_gss_export_sec_context, + iakerb_gss_import_sec_context, +#endif + krb5_gss_inquire_cred_by_mech, + krb5_gss_inquire_names_for_mech, + iakerb_gss_inquire_context, + krb5_gss_internal_release_oid, + iakerb_gss_wrap_size_limit, + krb5_gss_localname, + krb5_gss_authorize_localname, + krb5_gss_export_name, + krb5_gss_duplicate_name, + krb5_gss_store_cred, + iakerb_gss_inquire_sec_context_by_oid, + krb5_gss_inquire_cred_by_oid, + iakerb_gss_set_sec_context_option, + krb5_gssspi_set_cred_option, + krb5_gssspi_mech_invoke, + NULL, /* wrap_aead */ + NULL, /* unwrap_aead */ + iakerb_gss_wrap_iov, + iakerb_gss_unwrap_iov, + iakerb_gss_wrap_iov_length, + NULL, /* complete_auth_token */ + NULL, /* acquire_cred_impersonate_name */ + NULL, /* add_cred_impersonate_name */ + NULL, /* display_name_ext */ + krb5_gss_inquire_name, + krb5_gss_get_name_attribute, + krb5_gss_set_name_attribute, + krb5_gss_delete_name_attribute, + krb5_gss_export_name_composite, + krb5_gss_map_name_to_any, + krb5_gss_release_any_name_mapping, + iakerb_gss_pseudo_random, + NULL, /* set_neg_mechs */ + krb5_gss_inquire_saslname_for_mech, + krb5_gss_inquire_mech_for_saslname, + krb5_gss_inquire_attrs_for_mech, + iakerb_gss_acquire_cred_from, + krb5_gss_store_cred_into, + iakerb_gss_acquire_cred_with_password, + krb5_gss_export_cred, + krb5_gss_import_cred, + NULL, /* import_sec_context_by_mech */ + NULL, /* import_name_by_mech */ + NULL, /* import_cred_by_mech */ + iakerb_gss_get_mic_iov, + iakerb_gss_verify_mic_iov, + iakerb_gss_get_mic_iov_length, +}; + +#ifdef _GSS_STATIC_LINK +#include "mglueP.h" +static int gss_iakerbmechglue_init(void) +{ + struct gss_mech_config mech_iakerb; + + memset(&mech_iakerb, 0, sizeof(mech_iakerb)); + mech_iakerb.mech = &iakerb_mechanism; + + mech_iakerb.mechNameStr = "iakerb"; + mech_iakerb.mech_type = (gss_OID)gss_mech_iakerb; + gssint_register_mechinfo(&mech_iakerb); + + return 0; +} + +static int gss_krb5mechglue_init(void) +{ + struct gss_mech_config mech_krb5; + + memset(&mech_krb5, 0, sizeof(mech_krb5)); + mech_krb5.mech = &krb5_mechanism; + + mech_krb5.mechNameStr = "kerberos_v5"; + mech_krb5.mech_type = (gss_OID)gss_mech_krb5; + gssint_register_mechinfo(&mech_krb5); + + mech_krb5.mechNameStr = "kerberos_v5_old"; + mech_krb5.mech_type = (gss_OID)gss_mech_krb5_old; + gssint_register_mechinfo(&mech_krb5); + + mech_krb5.mechNameStr = "mskrb"; + mech_krb5.mech_type = (gss_OID)gss_mech_krb5_wrong; + gssint_register_mechinfo(&mech_krb5); + + return 0; +} +#else +MAKE_INIT_FUNCTION(gss_krb5int_lib_init); +MAKE_FINI_FUNCTION(gss_krb5int_lib_fini); + +gss_mechanism KRB5_CALLCONV +gss_mech_initialize(void) +{ + return &krb5_mechanism; +} +#endif /* _GSS_STATIC_LINK */ + +int gss_krb5int_lib_init(void) +{ + int err; + +#ifdef SHOW_INITFINI_FUNCS + printf("gss_krb5int_lib_init\n"); +#endif + + add_error_table(&et_k5g_error_table); + +#ifndef LEAN_CLIENT + err = k5_mutex_finish_init(&gssint_krb5_keytab_lock); + if (err) + return err; +#endif /* LEAN_CLIENT */ + err = k5_key_register(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME, free); + if (err) + return err; + err = k5_key_register(K5_KEY_GSS_KRB5_CCACHE_NAME, free); + if (err) + return err; + err = k5_key_register(K5_KEY_GSS_KRB5_ERROR_MESSAGE, + krb5_gss_delete_error_info); + if (err) + return err; +#ifndef _WIN32 + err = k5_mutex_finish_init(&kg_kdc_flag_mutex); + if (err) + return err; + err = k5_mutex_finish_init(&kg_vdb.mutex); + if (err) + return err; +#endif +#ifdef _GSS_STATIC_LINK + err = gss_krb5mechglue_init(); + if (err) + return err; + err = gss_iakerbmechglue_init(); + if (err) + return err; +#endif + + return 0; +} + +void gss_krb5int_lib_fini(void) +{ +#ifndef _GSS_STATIC_LINK + if (!INITIALIZER_RAN(gss_krb5int_lib_init) || PROGRAM_EXITING()) { +# ifdef SHOW_INITFINI_FUNCS + printf("gss_krb5int_lib_fini: skipping\n"); +# endif + return; + } +#endif +#ifdef SHOW_INITFINI_FUNCS + printf("gss_krb5int_lib_fini\n"); +#endif + remove_error_table(&et_k5g_error_table); + + k5_key_delete(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME); + k5_key_delete(K5_KEY_GSS_KRB5_CCACHE_NAME); + k5_key_delete(K5_KEY_GSS_KRB5_ERROR_MESSAGE); + k5_mutex_destroy(&kg_vdb.mutex); +#ifndef _WIN32 + k5_mutex_destroy(&kg_kdc_flag_mutex); +#endif +#ifndef LEAN_CLIENT + k5_mutex_destroy(&gssint_krb5_keytab_lock); +#endif /* LEAN_CLIENT */ +} + +#ifdef _GSS_STATIC_LINK +extern OM_uint32 gssint_lib_init(void); +#endif + +OM_uint32 gss_krb5int_initialize_library (void) +{ +#ifdef _GSS_STATIC_LINK + return gssint_mechglue_initialize_library(); +#else + return CALL_INIT_FUNCTION(gss_krb5int_lib_init); +#endif +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/gssapi_krb5.h b/krb5-1.21.3/src/lib/gssapi/krb5/gssapi_krb5.h new file mode 100644 index 00000000..8141f41d --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/gssapi_krb5.h @@ -0,0 +1,305 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _GSSAPI_KRB5_H_ +#define _GSSAPI_KRB5_H_ + +#include +#include +#include +#include + +/* C++ friendlyness */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Reserved static storage for GSS_oids. See rfc 1964 for more details. */ + +/* 2.1.1. Kerberos Principal Name Form: */ +GSS_DLLIMP extern const gss_OID GSS_KRB5_NT_PRINCIPAL_NAME; +/* This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5_name(1)}. The recommended symbolic name for this type + * is "GSS_KRB5_NT_PRINCIPAL_NAME". */ + +/* 2.1.2. Host-Based Service Name Form */ +#define GSS_KRB5_NT_HOSTBASED_SERVICE_NAME GSS_C_NT_HOSTBASED_SERVICE +/* This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) service_name(4)}. The previously recommended symbolic + * name for this type is "GSS_KRB5_NT_HOSTBASED_SERVICE_NAME". The + * currently preferred symbolic name for this type is + * "GSS_C_NT_HOSTBASED_SERVICE". */ + +/* 2.2.1. User Name Form */ +#define GSS_KRB5_NT_USER_NAME GSS_C_NT_USER_NAME +/* This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) user_name(1)}. The recommended symbolic name for this + * type is "GSS_KRB5_NT_USER_NAME". */ + +/* 2.2.2. Machine UID Form */ +#define GSS_KRB5_NT_MACHINE_UID_NAME GSS_C_NT_MACHINE_UID_NAME +/* This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) machine_uid_name(2)}. The recommended symbolic name for + * this type is "GSS_KRB5_NT_MACHINE_UID_NAME". */ + +/* 2.2.3. String UID Form */ +#define GSS_KRB5_NT_STRING_UID_NAME GSS_C_NT_STRING_UID_NAME +/* This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) string_uid_name(3)}. The recommended symbolic name for + * this type is "GSS_KRB5_NT_STRING_UID_NAME". */ + +/* Kerberos Enterprise Name Form (see RFC 6806 section 5): */ +GSS_DLLIMP extern const gss_OID GSS_KRB5_NT_ENTERPRISE_NAME; +/* {iso(1) member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5-enterprise-name(6)}. */ + +/* Kerberos X.509 DER-encoded certificate */ +GSS_DLLIMP extern const gss_OID GSS_KRB5_NT_X509_CERT; +/* {iso(1) member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5-x509-cert(7)}. */ + +GSS_DLLIMP extern const gss_OID gss_mech_krb5; +GSS_DLLIMP extern const gss_OID gss_mech_krb5_old; +GSS_DLLIMP extern const gss_OID gss_mech_krb5_wrong; +GSS_DLLIMP extern const gss_OID gss_mech_iakerb; +GSS_DLLIMP extern const gss_OID_set gss_mech_set_krb5; +GSS_DLLIMP extern const gss_OID_set gss_mech_set_krb5_old; +GSS_DLLIMP extern const gss_OID_set gss_mech_set_krb5_both; + +GSS_DLLIMP extern const gss_OID gss_nt_krb5_name; +GSS_DLLIMP extern const gss_OID gss_nt_krb5_principal; + +GSS_DLLIMP extern const gss_OID_desc krb5_gss_oid_array[]; + +/* + * This OID can be used with gss_set_cred_option() to suppress the + * confidentiality and integrity flags from being asserted in initial context + * tokens. + * + * iso(1) member-body(2) Sweden(752) Stockholm University(43) Heimdal GSS-API + * Extensions(13) no_ci_flags(29) + */ +GSS_DLLIMP extern const gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X; + +/* + * This OID can be used with gss_inquire_cred_by_oid(0 to retrieve the + * impersonator name (if any). + * + * iso(1) member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5-gssapi-ext(5) get-cred-impersonator(14) + */ +GSS_DLLIMP extern const gss_OID GSS_KRB5_GET_CRED_IMPERSONATOR; + +#define gss_krb5_nt_general_name gss_nt_krb5_name +#define gss_krb5_nt_principal gss_nt_krb5_principal +#define gss_krb5_nt_service_name gss_nt_service_name +#define gss_krb5_nt_user_name gss_nt_user_name +#define gss_krb5_nt_machine_uid_name gss_nt_machine_uid_name +#define gss_krb5_nt_string_uid_name gss_nt_string_uid_name + +typedef struct gss_krb5_lucid_key { + OM_uint32 type; /* key encryption type */ + OM_uint32 length; /* length of key data */ + void * data; /* actual key data */ +} gss_krb5_lucid_key_t; + +typedef struct gss_krb5_rfc1964_keydata { + OM_uint32 sign_alg; /* signing algorithm */ + OM_uint32 seal_alg; /* seal/encrypt algorithm */ + gss_krb5_lucid_key_t ctx_key; + /* Context key + (Kerberos session key or subkey) */ +} gss_krb5_rfc1964_keydata_t; + +typedef struct gss_krb5_cfx_keydata { + OM_uint32 have_acceptor_subkey; + /* 1 if there is an acceptor_subkey + present, 0 otherwise */ + gss_krb5_lucid_key_t ctx_key; + /* Context key + (Kerberos session key or subkey) */ + gss_krb5_lucid_key_t acceptor_subkey; + /* acceptor-asserted subkey or + 0's if no acceptor subkey */ +} gss_krb5_cfx_keydata_t; + +typedef struct gss_krb5_lucid_context_v1 { + OM_uint32 version; /* Structure version number (1) + MUST be at beginning of struct! */ + OM_uint32 initiate; /* Are we the initiator? */ + OM_uint32 endtime; /* expiration time of context */ + uint64_t send_seq; /* sender sequence number */ + uint64_t recv_seq; /* receive sequence number */ + OM_uint32 protocol; /* 0: rfc1964, + 1: draft-ietf-krb-wg-gssapi-cfx-07 */ + /* + * if (protocol == 0) rfc1964_kd should be used + * and cfx_kd contents are invalid and should be zero + * if (protocol == 1) cfx_kd should be used + * and rfc1964_kd contents are invalid and should be zero + */ + gss_krb5_rfc1964_keydata_t rfc1964_kd; + gss_krb5_cfx_keydata_t cfx_kd; +} gss_krb5_lucid_context_v1_t; + +/* + * Mask for determining the version of a lucid context structure. Callers + * should not require this. + */ +typedef struct gss_krb5_lucid_context_version { + OM_uint32 version; /* Structure version number */ +} gss_krb5_lucid_context_version_t; + + + + +/* Alias for Heimdal compat. */ +#define gsskrb5_register_acceptor_identity krb5_gss_register_acceptor_identity + +OM_uint32 KRB5_CALLCONV krb5_gss_register_acceptor_identity(const char *); + +OM_uint32 KRB5_CALLCONV gss_krb5_get_tkt_flags( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + krb5_flags *ticket_flags); + +/* + * Copy krb5 creds from cred_handle into out_ccache, which must already be + * initialized. Use gss_store_cred_into() (new in krb5 1.11) instead, if + * possible. + */ +OM_uint32 KRB5_CALLCONV gss_krb5_copy_ccache( + OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + krb5_ccache out_ccache); + +OM_uint32 KRB5_CALLCONV gss_krb5_ccache_name( + OM_uint32 *minor_status, const char *name, + const char **out_name); + +/* + * gss_krb5_set_allowable_enctypes + * + * This function may be called by a context initiator after calling + * gss_acquire_cred(), but before calling gss_init_sec_context(), + * to restrict the set of enctypes which will be negotiated during + * context establishment to those in the provided array. + * + * 'cred' must be a valid credential handle obtained via + * gss_acquire_cred(). It may not be GSS_C_NO_CREDENTIAL. + * gss_acquire_cred() may have been called to get a handle to + * the default credential. + * + * The purpose of this function is to limit the keys that may + * be exported via gss_krb5_export_lucid_sec_context(); thus it + * should limit the enctypes of all keys that will be needed + * after the security context has been established. + * (i.e. context establishment may use a session key with a + * stronger enctype than in the provided array, however a + * subkey must be established within the enctype limits + * established by this function.) + * + */ +OM_uint32 KRB5_CALLCONV +gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status, + gss_cred_id_t cred, + OM_uint32 num_ktypes, + krb5_enctype *ktypes); + +/* + * Returns a non-opaque (lucid) version of the internal context + * information. + * + * Note that context_handle must not be used again by the caller + * after this call. The GSS implementation is free to release any + * resources associated with the original context. It is up to the + * GSS implementation whether it returns pointers to existing data, + * or copies of the data. The caller should treat the returned + * lucid context as read-only. + * + * The caller must call gss_krb5_free_lucid_context() to free + * the context and allocated resources when it is finished with it. + * + * 'version' is an integer indicating the requested version of the lucid + * context. If the implementation does not understand the requested version, + * it will return an error. + * + * For example: + * void *return_ctx; + * gss_krb5_lucid_context_v1_t *ctx; + * OM_uint32 min_stat, maj_stat; + * OM_uint32 vers; + * gss_ctx_id_t *ctx_handle; + * + * maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, + * ctx_handle, 1, &return_ctx); + * // Verify success + * ctx = (gss_krb5_lucid_context_v1_t *) return_ctx; + */ + +OM_uint32 KRB5_CALLCONV +gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + OM_uint32 version, + void **kctx); + +/* + * Frees the allocated storage associated with an + * exported struct gss_krb5_lucid_context. + */ +OM_uint32 KRB5_CALLCONV +gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, + void *kctx); + + +OM_uint32 KRB5_CALLCONV +gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + int ad_type, + gss_buffer_t ad_data); + +OM_uint32 KRB5_CALLCONV +gss_krb5_set_cred_rcache(OM_uint32 *minor_status, + gss_cred_id_t cred, + krb5_rcache rcache); + +OM_uint32 KRB5_CALLCONV +gsskrb5_extract_authtime_from_sec_context(OM_uint32 *, gss_ctx_id_t, krb5_timestamp *); + +OM_uint32 KRB5_CALLCONV +gss_krb5_import_cred(OM_uint32 *minor_status, + krb5_ccache id, + krb5_principal keytab_principal, + krb5_keytab keytab, + gss_cred_id_t *cred); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _GSSAPI_KRB5_H_ */ diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/iakerb.c b/krb5-1.21.3/src/lib/gssapi/krb5/iakerb.c new file mode 100644 index 00000000..a0d298c4 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/iakerb.c @@ -0,0 +1,1310 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +#include "k5-int.h" +#include "k5-der.h" +#include "gssapiP_krb5.h" + +/* + * IAKERB implementation + */ + +enum iakerb_state { + IAKERB_AS_REQ, /* acquiring ticket with initial creds */ + IAKERB_TGS_REQ, /* acquiring ticket with TGT */ + IAKERB_AP_REQ /* hand-off to normal GSS AP-REQ exchange */ +}; + +struct _iakerb_ctx_id_rec { + krb5_magic magic; /* KG_IAKERB_CONTEXT */ + krb5_context k5c; + gss_cred_id_t defcred; /* Initiator only */ + enum iakerb_state state; /* Initiator only */ + krb5_init_creds_context icc; /* Initiator only */ + krb5_tkt_creds_context tcc; /* Initiator only */ + gss_ctx_id_t gssc; + krb5_data conv; /* conversation for checksumming */ + unsigned int count; /* number of round trips */ + int initiate; + int established; + krb5_get_init_creds_opt *gic_opts; +}; + +#define IAKERB_MAX_HOPS ( 16 /* MAX_IN_TKT_LOOPS */ + KRB5_REFERRAL_MAXHOPS ) + +typedef struct _iakerb_ctx_id_rec iakerb_ctx_id_rec; +typedef iakerb_ctx_id_rec *iakerb_ctx_id_t; + +/* + * Release an IAKERB context + */ +static void +iakerb_release_context(iakerb_ctx_id_t ctx) +{ + OM_uint32 tmp; + + if (ctx == NULL) + return; + + krb5_gss_release_cred(&tmp, &ctx->defcred); + krb5_init_creds_free(ctx->k5c, ctx->icc); + krb5_tkt_creds_free(ctx->k5c, ctx->tcc); + krb5_gss_delete_sec_context(&tmp, &ctx->gssc, NULL); + krb5_free_data_contents(ctx->k5c, &ctx->conv); + krb5_get_init_creds_opt_free(ctx->k5c, ctx->gic_opts); + krb5_free_context(ctx->k5c); + free(ctx); +} + +/* + * Create a IAKERB-FINISHED structure containing a checksum of + * the entire IAKERB exchange. + */ +krb5_error_code +iakerb_make_finished(krb5_context context, + krb5_key key, + const krb5_data *conv, + krb5_data **finished) +{ + krb5_error_code code; + krb5_iakerb_finished iaf; + + *finished = NULL; + + memset(&iaf, 0, sizeof(iaf)); + + if (key == NULL) + return KRB5KDC_ERR_NULL_KEY; + + code = krb5_k_make_checksum(context, 0, key, KRB5_KEYUSAGE_IAKERB_FINISHED, + conv, &iaf.checksum); + if (code != 0) + return code; + + code = encode_krb5_iakerb_finished(&iaf, finished); + + krb5_free_checksum_contents(context, &iaf.checksum); + + return code; +} + +/* + * Verify a IAKERB-FINISHED structure submitted by the initiator + */ +krb5_error_code +iakerb_verify_finished(krb5_context context, + krb5_key key, + const krb5_data *conv, + const krb5_data *finished) +{ + krb5_error_code code; + krb5_iakerb_finished *iaf; + krb5_boolean valid = FALSE; + + if (key == NULL) + return KRB5KDC_ERR_NULL_KEY; + + code = decode_krb5_iakerb_finished(finished, &iaf); + if (code != 0) + return code; + + code = krb5_k_verify_checksum(context, key, KRB5_KEYUSAGE_IAKERB_FINISHED, + conv, &iaf->checksum, &valid); + if (code == 0 && valid == FALSE) + code = KRB5KRB_AP_ERR_BAD_INTEGRITY; + + krb5_free_iakerb_finished(context, iaf); + + return code; +} + +/* + * Save a token for future checksumming. + */ +static krb5_error_code +iakerb_save_token(iakerb_ctx_id_t ctx, const gss_buffer_t token) +{ + char *p; + + p = realloc(ctx->conv.data, ctx->conv.length + token->length); + if (p == NULL) + return ENOMEM; + + memcpy(p + ctx->conv.length, token->value, token->length); + ctx->conv.data = p; + ctx->conv.length += token->length; + + return 0; +} + +/* + * Parse a token into IAKERB-HEADER and KRB-KDC-REQ/REP + */ +static krb5_error_code +iakerb_parse_token(iakerb_ctx_id_t ctx, + int initialContextToken, + const gss_buffer_t token, + krb5_data *realm, + krb5_data **cookie, + krb5_data *request) +{ + krb5_error_code code; + krb5_iakerb_header *iah = NULL; + unsigned int bodysize; + uint8_t *body; + int flags = 0; + krb5_data data; + struct k5input in, seq; + + if (token == GSS_C_NO_BUFFER || token->length == 0) { + code = KRB5_BAD_MSIZE; + goto cleanup; + } + + if (initialContextToken) + flags |= G_VFY_TOKEN_HDR_WRAPPER_REQUIRED; + + body = token->value; + code = g_verify_token_header(gss_mech_iakerb, &bodysize, &body, + IAKERB_TOK_PROXY, token->length, flags); + if (code != 0) + goto cleanup; + + /* Find the end of the DER sequence tag and decode it (with the tag) as the + * IAKERB jeader. */ + k5_input_init(&in, body, bodysize); + if (!k5_der_get_value(&in, 0x30, &seq)) { + code = ASN1_BAD_ID; + goto cleanup; + } + data = make_data(body, seq.ptr + seq.len - body); + code = decode_krb5_iakerb_header(&data, &iah); + if (code != 0) + goto cleanup; + + if (realm != NULL) { + *realm = iah->target_realm; + iah->target_realm.data = NULL; + } + + if (cookie != NULL) { + *cookie = iah->cookie; + iah->cookie = NULL; + } + + /* The remainder of the token body is the request. */ + *request = make_data((uint8_t *)in.ptr, in.len); + assert(request->data + request->length == + (char *)token->value + token->length); + +cleanup: + krb5_free_iakerb_header(ctx->k5c, iah); + + return code; +} + +/* + * Create a token from IAKERB-HEADER and KRB-KDC-REQ/REP + */ +static krb5_error_code +iakerb_make_token(iakerb_ctx_id_t ctx, + krb5_data *realm, + krb5_data *cookie, + krb5_data *request, + int initialContextToken, + gss_buffer_t token) +{ + krb5_error_code code; + krb5_iakerb_header iah; + krb5_data *data = NULL; + char *p; + unsigned int tokenSize; + struct k5buf buf; + + token->value = NULL; + token->length = 0; + + /* + * Assemble the IAKERB-HEADER from the realm and cookie + */ + iah.target_realm = *realm; + iah.cookie = cookie; + + code = encode_krb5_iakerb_header(&iah, &data); + if (code != 0) + goto cleanup; + + /* + * Concatenate Kerberos request. + */ + p = realloc(data->data, data->length + request->length); + if (p == NULL) { + code = ENOMEM; + goto cleanup; + } + data->data = p; + + if (request->length > 0) + memcpy(data->data + data->length, request->data, request->length); + data->length += request->length; + + if (initialContextToken) + tokenSize = g_token_size(gss_mech_iakerb, data->length); + else + tokenSize = 2 + data->length; + + token->value = gssalloc_malloc(tokenSize); + if (token->value == NULL) { + code = ENOMEM; + goto cleanup; + } + token->length = tokenSize; + k5_buf_init_fixed(&buf, token->value, token->length); + + if (initialContextToken) { + g_make_token_header(&buf, gss_mech_iakerb, data->length, + IAKERB_TOK_PROXY); + } else { + k5_buf_add_uint16_be(&buf, IAKERB_TOK_PROXY); + } + k5_buf_add_len(&buf, data->data, data->length); + assert(buf.len == token->length); + +cleanup: + krb5_free_data(ctx->k5c, data); + + return code; +} + +/* + * Parse the IAKERB token in input_token and send the contained KDC + * request to the KDC for the realm. + * + * Wrap the KDC reply in output_token. + */ +static krb5_error_code +iakerb_acceptor_step(iakerb_ctx_id_t ctx, + int initialContextToken, + const gss_buffer_t input_token, + gss_buffer_t output_token) +{ + krb5_error_code code; + krb5_data request = empty_data(), reply = empty_data(); + krb5_data realm = empty_data(); + OM_uint32 tmp; + int tcp_only, use_primary; + krb5_ui_4 kdc_code; + + output_token->length = 0; + output_token->value = NULL; + + if (ctx->count >= IAKERB_MAX_HOPS) { + code = KRB5_KDC_UNREACH; + goto cleanup; + } + + code = iakerb_parse_token(ctx, initialContextToken, input_token, &realm, + NULL, &request); + if (code != 0) + goto cleanup; + + if (realm.length == 0 || request.length == 0) { + code = KRB5_BAD_MSIZE; + goto cleanup; + } + + code = iakerb_save_token(ctx, input_token); + if (code != 0) + goto cleanup; + + for (tcp_only = 0; tcp_only <= 1; tcp_only++) { + use_primary = 0; + code = krb5_sendto_kdc(ctx->k5c, &request, &realm, + &reply, &use_primary, tcp_only); + if (code == 0 && krb5_is_krb_error(&reply)) { + krb5_error *error; + + code = decode_krb5_error(&reply, &error); + if (code != 0) + goto cleanup; + kdc_code = error->error; + krb5_free_error(ctx->k5c, error); + if (kdc_code == KRB_ERR_RESPONSE_TOO_BIG) { + krb5_free_data_contents(ctx->k5c, &reply); + reply = empty_data(); + continue; + } + } + break; + } + + if (code == KRB5_KDC_UNREACH || code == KRB5_REALM_UNKNOWN) { + krb5_error error; + + memset(&error, 0, sizeof(error)); + if (code == KRB5_KDC_UNREACH) + error.error = KRB_AP_ERR_IAKERB_KDC_NO_RESPONSE; + else if (code == KRB5_REALM_UNKNOWN) + error.error = KRB_AP_ERR_IAKERB_KDC_NOT_FOUND; + + code = krb5_mk_error(ctx->k5c, &error, &reply); + if (code != 0) + goto cleanup; + } else if (code != 0) + goto cleanup; + + code = iakerb_make_token(ctx, &realm, NULL, &reply, 0, output_token); + if (code != 0) + goto cleanup; + + code = iakerb_save_token(ctx, output_token); + if (code != 0) + goto cleanup; + + ctx->count++; + +cleanup: + if (code != 0) + gss_release_buffer(&tmp, output_token); + /* request is a pointer into input_token, no need to free */ + krb5_free_data_contents(ctx->k5c, &realm); + krb5_free_data_contents(ctx->k5c, &reply); + + return code; +} + +/* + * Initialise the krb5_init_creds context for the IAKERB context + */ +static krb5_error_code +iakerb_init_creds_ctx(iakerb_ctx_id_t ctx, + krb5_gss_cred_id_t cred, + OM_uint32 time_req) +{ + krb5_error_code code; + + if (cred->iakerb_mech == 0) { + code = EINVAL; + goto cleanup; + } + + assert(cred->name != NULL); + assert(cred->name->princ != NULL); + + code = krb5_get_init_creds_opt_alloc(ctx->k5c, &ctx->gic_opts); + if (code != 0) + goto cleanup; + + if (time_req != 0 && time_req != GSS_C_INDEFINITE) + krb5_get_init_creds_opt_set_tkt_life(ctx->gic_opts, time_req); + + code = krb5_get_init_creds_opt_set_out_ccache(ctx->k5c, ctx->gic_opts, + cred->ccache); + if (code != 0) + goto cleanup; + + code = krb5_init_creds_init(ctx->k5c, + cred->name->princ, + NULL, /* prompter */ + NULL, /* data */ + 0, /* start_time */ + ctx->gic_opts, + &ctx->icc); + if (code != 0) + goto cleanup; + + if (cred->password != NULL) { + code = krb5_init_creds_set_password(ctx->k5c, ctx->icc, + cred->password); + } else if (cred->client_keytab != NULL) { + code = krb5_init_creds_set_keytab(ctx->k5c, ctx->icc, + cred->client_keytab); + } else { + code = KRB5_KT_NOTFOUND; + } + if (code != 0) + goto cleanup; + +cleanup: + return code; +} + +/* + * Initialise the krb5_tkt_creds context for the IAKERB context + */ +static krb5_error_code +iakerb_tkt_creds_ctx(iakerb_ctx_id_t ctx, + krb5_gss_cred_id_t cred, + krb5_gss_name_t name, + OM_uint32 time_req) + +{ + krb5_error_code code; + krb5_creds creds; + krb5_timestamp now; + + assert(cred->name != NULL); + assert(cred->name->princ != NULL); + + memset(&creds, 0, sizeof(creds)); + + creds.client = cred->name->princ; + creds.server = name->princ; + + if (time_req != 0 && time_req != GSS_C_INDEFINITE) { + code = krb5_timeofday(ctx->k5c, &now); + if (code != 0) + goto cleanup; + + creds.times.endtime = ts_incr(now, time_req); + } + + if (cred->name->ad_context != NULL) { + code = krb5_authdata_export_authdata(ctx->k5c, + cred->name->ad_context, + AD_USAGE_TGS_REQ, + &creds.authdata); + if (code != 0) + goto cleanup; + } + + code = krb5_tkt_creds_init(ctx->k5c, cred->ccache, &creds, 0, &ctx->tcc); + if (code != 0) + goto cleanup; + +cleanup: + krb5_free_authdata(ctx->k5c, creds.authdata); + + return code; +} + +/* + * Parse the IAKERB token in input_token and process the KDC + * response. + * + * Emit the next KDC request, if any, in output_token. + */ +static krb5_error_code +iakerb_initiator_step(iakerb_ctx_id_t ctx, + krb5_gss_cred_id_t cred, + krb5_gss_name_t name, + OM_uint32 time_req, + const gss_buffer_t input_token, + gss_buffer_t output_token) +{ + krb5_error_code code = 0; + krb5_data in = empty_data(), out = empty_data(), realm = empty_data(); + krb5_data *cookie = NULL; + OM_uint32 tmp; + unsigned int flags = 0; + krb5_ticket_times times; + + output_token->length = 0; + output_token->value = NULL; + + if (input_token != GSS_C_NO_BUFFER) { + code = iakerb_parse_token(ctx, 0, input_token, NULL, &cookie, &in); + if (code != 0) + goto cleanup; + + code = iakerb_save_token(ctx, input_token); + if (code != 0) + goto cleanup; + } + + switch (ctx->state) { + case IAKERB_AS_REQ: + if (ctx->icc == NULL) { + code = iakerb_init_creds_ctx(ctx, cred, time_req); + if (code != 0) + goto cleanup; + } + + code = krb5_init_creds_step(ctx->k5c, ctx->icc, &in, &out, &realm, + &flags); + if (code != 0) { + if (cred->have_tgt) { + /* We were trying to refresh; keep going with current creds. */ + ctx->state = IAKERB_TGS_REQ; + krb5_clear_error_message(ctx->k5c); + } else { + goto cleanup; + } + } else if (!(flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE)) { + krb5_init_creds_get_times(ctx->k5c, ctx->icc, ×); + kg_cred_set_initial_refresh(ctx->k5c, cred, ×); + cred->expire = times.endtime; + + krb5_init_creds_free(ctx->k5c, ctx->icc); + ctx->icc = NULL; + + ctx->state = IAKERB_TGS_REQ; + } else + break; + in = empty_data(); + /* Done with AS request; fall through to TGS request. */ + case IAKERB_TGS_REQ: + if (ctx->tcc == NULL) { + code = iakerb_tkt_creds_ctx(ctx, cred, name, time_req); + if (code != 0) + goto cleanup; + } + + code = krb5_tkt_creds_step(ctx->k5c, ctx->tcc, &in, &out, &realm, + &flags); + if (code != 0) + goto cleanup; + if (!(flags & KRB5_TKT_CREDS_STEP_FLAG_CONTINUE)) { + krb5_tkt_creds_get_times(ctx->k5c, ctx->tcc, ×); + cred->expire = times.endtime; + + krb5_tkt_creds_free(ctx->k5c, ctx->tcc); + ctx->tcc = NULL; + + ctx->state = IAKERB_AP_REQ; + } else + break; + /* Done with TGS request; fall through to AP request. */ + case IAKERB_AP_REQ: + break; + } + + if (out.length != 0) { + assert(ctx->state != IAKERB_AP_REQ); + + code = iakerb_make_token(ctx, &realm, cookie, &out, + (input_token == GSS_C_NO_BUFFER), + output_token); + if (code != 0) + goto cleanup; + + /* Save the token for generating a future checksum */ + code = iakerb_save_token(ctx, output_token); + if (code != 0) + goto cleanup; + + ctx->count++; + } + +cleanup: + if (code != 0) + gss_release_buffer(&tmp, output_token); + krb5_free_data(ctx->k5c, cookie); + krb5_free_data_contents(ctx->k5c, &out); + krb5_free_data_contents(ctx->k5c, &realm); + + return code; +} + +/* + * Determine the starting IAKERB state for a context. If we already + * have a ticket, we may not need to do IAKERB at all. + */ +static krb5_error_code +iakerb_get_initial_state(iakerb_ctx_id_t ctx, + krb5_gss_cred_id_t cred, + krb5_gss_name_t target, + OM_uint32 time_req, + enum iakerb_state *state) +{ + krb5_creds in_creds, *out_creds = NULL; + krb5_error_code code; + + memset(&in_creds, 0, sizeof(in_creds)); + + in_creds.client = cred->name->princ; + in_creds.server = target->princ; + + if (cred->name->ad_context != NULL) { + code = krb5_authdata_export_authdata(ctx->k5c, + cred->name->ad_context, + AD_USAGE_TGS_REQ, + &in_creds.authdata); + if (code != 0) + goto cleanup; + } + + if (time_req != 0 && time_req != GSS_C_INDEFINITE) { + krb5_timestamp now; + + code = krb5_timeofday(ctx->k5c, &now); + if (code != 0) + goto cleanup; + + in_creds.times.endtime = ts_incr(now, time_req); + } + + /* Make an AS request if we have no creds or it's time to refresh them. */ + if (cred->expire == 0 || kg_cred_time_to_refresh(ctx->k5c, cred)) { + *state = IAKERB_AS_REQ; + code = 0; + goto cleanup; + } + + code = krb5_get_credentials(ctx->k5c, KRB5_GC_CACHED, cred->ccache, + &in_creds, &out_creds); + if (code == KRB5_CC_NOTFOUND || code == KRB5_CC_NOT_KTYPE) { + *state = cred->have_tgt ? IAKERB_TGS_REQ : IAKERB_AS_REQ; + code = 0; + } else if (code == 0) { + *state = IAKERB_AP_REQ; + krb5_free_creds(ctx->k5c, out_creds); + } + +cleanup: + krb5_free_authdata(ctx->k5c, in_creds.authdata); + + return code; +} + +/* + * Allocate and initialise an IAKERB context + */ +static krb5_error_code +iakerb_alloc_context(iakerb_ctx_id_t *pctx, int initiate) +{ + iakerb_ctx_id_t ctx; + krb5_error_code code; + + *pctx = NULL; + + ctx = k5alloc(sizeof(*ctx), &code); + if (ctx == NULL) + goto cleanup; + ctx->defcred = GSS_C_NO_CREDENTIAL; + ctx->magic = KG_IAKERB_CONTEXT; + ctx->state = IAKERB_AS_REQ; + ctx->count = 0; + ctx->initiate = initiate; + ctx->established = 0; + + code = krb5_gss_init_context(&ctx->k5c); + if (code != 0) + goto cleanup; + + *pctx = ctx; + +cleanup: + if (code != 0) + iakerb_release_context(ctx); + + return code; +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_delete_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token) +{ + iakerb_ctx_id_t iakerb_ctx = (iakerb_ctx_id_t)*context_handle; + + if (output_token != GSS_C_NO_BUFFER) { + output_token->length = 0; + output_token->value = NULL; + } + + *minor_status = 0; + *context_handle = GSS_C_NO_CONTEXT; + iakerb_release_context(iakerb_ctx); + + return GSS_S_COMPLETE; +} + +static krb5_boolean +iakerb_is_iakerb_token(const gss_buffer_t token) +{ + krb5_error_code code; + unsigned int bodysize = token->length; + unsigned char *ptr = token->value; + + code = g_verify_token_header(gss_mech_iakerb, + &bodysize, &ptr, + IAKERB_TOK_PROXY, + token->length, 0); + + return (code == 0); +} + +static void +iakerb_make_exts(iakerb_ctx_id_t ctx, krb5_gss_ctx_ext_rec *exts) +{ + memset(exts, 0, sizeof(*exts)); + + if (ctx->conv.length != 0) + exts->iakerb.conv = &ctx->conv; +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_accept_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_cred_id_t verifier_cred_handle, + gss_buffer_t input_token, + gss_channel_bindings_t input_chan_bindings, + gss_name_t *src_name, + gss_OID *mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec, + gss_cred_id_t *delegated_cred_handle) +{ + OM_uint32 major_status = GSS_S_FAILURE; + OM_uint32 code; + iakerb_ctx_id_t ctx; + int initialContextToken = (*context_handle == GSS_C_NO_CONTEXT); + + if (initialContextToken) { + code = iakerb_alloc_context(&ctx, 0); + if (code != 0) + goto cleanup; + + } else + ctx = (iakerb_ctx_id_t)*context_handle; + + if (iakerb_is_iakerb_token(input_token)) { + if (ctx->gssc != GSS_C_NO_CONTEXT) { + /* We shouldn't get an IAKERB token now. */ + code = G_WRONG_TOKID; + major_status = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + code = iakerb_acceptor_step(ctx, initialContextToken, + input_token, output_token); + if (code == (OM_uint32)KRB5_BAD_MSIZE) + major_status = GSS_S_DEFECTIVE_TOKEN; + if (code != 0) + goto cleanup; + if (initialContextToken) { + *context_handle = (gss_ctx_id_t)ctx; + ctx = NULL; + } + if (src_name != NULL) + *src_name = GSS_C_NO_NAME; + if (ret_flags != NULL) + *ret_flags = 0; + if (time_rec != NULL) + *time_rec = 0; + if (delegated_cred_handle != NULL) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + major_status = GSS_S_CONTINUE_NEEDED; + } else { + krb5_gss_ctx_ext_rec exts; + + iakerb_make_exts(ctx, &exts); + + major_status = krb5_gss_accept_sec_context_ext(&code, + &ctx->gssc, + verifier_cred_handle, + input_token, + input_chan_bindings, + src_name, + NULL, + output_token, + ret_flags, + time_rec, + delegated_cred_handle, + &exts); + if (major_status == GSS_S_COMPLETE) + ctx->established = 1; + } + + if (mech_type != NULL) + *mech_type = gss_mech_iakerb; + +cleanup: + if (initialContextToken && GSS_ERROR(major_status)) { + iakerb_release_context(ctx); + *context_handle = GSS_C_NO_CONTEXT; + } + + *minor_status = code; + return major_status; +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_init_sec_context(OM_uint32 *minor_status, + gss_cred_id_t claimant_cred_handle, + gss_ctx_id_t *context_handle, + gss_name_t target_name, + gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_OID *actual_mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec) +{ + OM_uint32 major_status = GSS_S_FAILURE; + krb5_error_code code; + iakerb_ctx_id_t ctx; + krb5_gss_cred_id_t kcred; + krb5_gss_name_t kname; + krb5_boolean cred_locked = FALSE; + int initialContextToken = (*context_handle == GSS_C_NO_CONTEXT); + + if (initialContextToken) { + code = iakerb_alloc_context(&ctx, 1); + if (code != 0) { + *minor_status = code; + goto cleanup; + } + if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) { + major_status = iakerb_gss_acquire_cred(minor_status, NULL, + GSS_C_INDEFINITE, + GSS_C_NULL_OID_SET, + GSS_C_INITIATE, + &ctx->defcred, NULL, NULL); + if (GSS_ERROR(major_status)) + goto cleanup; + claimant_cred_handle = ctx->defcred; + } + } else { + ctx = (iakerb_ctx_id_t)*context_handle; + if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) + claimant_cred_handle = ctx->defcred; + } + + kname = (krb5_gss_name_t)target_name; + + major_status = kg_cred_resolve(minor_status, ctx->k5c, + claimant_cred_handle, target_name); + if (GSS_ERROR(major_status)) + goto cleanup; + cred_locked = TRUE; + kcred = (krb5_gss_cred_id_t)claimant_cred_handle; + + major_status = GSS_S_FAILURE; + + if (initialContextToken) { + code = iakerb_get_initial_state(ctx, kcred, kname, time_req, + &ctx->state); + if (code != 0) { + *minor_status = code; + goto cleanup; + } + *context_handle = (gss_ctx_id_t)ctx; + } + + if (ctx->state != IAKERB_AP_REQ) { + /* We need to do IAKERB. */ + code = iakerb_initiator_step(ctx, + kcred, + kname, + time_req, + input_token, + output_token); + if (code == KRB5_BAD_MSIZE) + major_status = GSS_S_DEFECTIVE_TOKEN; + if (code != 0) { + *minor_status = code; + goto cleanup; + } + } + + if (ctx->state == IAKERB_AP_REQ) { + krb5_gss_ctx_ext_rec exts; + + if (cred_locked) { + k5_mutex_unlock(&kcred->lock); + cred_locked = FALSE; + } + + iakerb_make_exts(ctx, &exts); + + if (ctx->gssc == GSS_C_NO_CONTEXT) + input_token = GSS_C_NO_BUFFER; + + /* IAKERB is finished, or we skipped to Kerberos directly. */ + major_status = krb5_gss_init_sec_context_ext(minor_status, + (gss_cred_id_t) kcred, + &ctx->gssc, + target_name, + (gss_OID)gss_mech_iakerb, + req_flags, + time_req, + input_chan_bindings, + input_token, + NULL, + output_token, + ret_flags, + time_rec, + &exts); + if (major_status == GSS_S_COMPLETE) + ctx->established = 1; + } else { + if (ret_flags != NULL) + *ret_flags = 0; + if (time_rec != NULL) + *time_rec = 0; + major_status = GSS_S_CONTINUE_NEEDED; + } + + if (actual_mech_type != NULL) + *actual_mech_type = gss_mech_iakerb; + +cleanup: + if (cred_locked) + k5_mutex_unlock(&kcred->lock); + if (initialContextToken && GSS_ERROR(major_status)) { + iakerb_release_context(ctx); + *context_handle = GSS_C_NO_CONTEXT; + } + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_unwrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, int *conf_state, + gss_qop_t *qop_state) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return krb5_gss_unwrap(minor_status, ctx->gssc, input_message_buffer, + output_message_buffer, conf_state, qop_state); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_wrap(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + int conf_req_flag, gss_qop_t qop_req, + gss_buffer_t input_message_buffer, int *conf_state, + gss_buffer_t output_message_buffer) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return krb5_gss_wrap(minor_status, ctx->gssc, conf_req_flag, qop_req, + input_message_buffer, conf_state, + output_message_buffer); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_process_context_token(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_buffer) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_DEFECTIVE_TOKEN; + + return krb5_gss_process_context_token(minor_status, ctx->gssc, + token_buffer); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_context_time(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + OM_uint32 *time_rec) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return krb5_gss_context_time(minor_status, ctx->gssc, time_rec); +} + +#ifndef LEAN_CLIENT + +OM_uint32 KRB5_CALLCONV +iakerb_gss_export_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t interprocess_token) +{ + OM_uint32 maj; + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)*context_handle; + + /* We don't currently support exporting partially established contexts. */ + if (!ctx->established) + return GSS_S_UNAVAILABLE; + + maj = krb5_gss_export_sec_context(minor_status, &ctx->gssc, + interprocess_token); + if (ctx->gssc == GSS_C_NO_CONTEXT) { + iakerb_release_context(ctx); + *context_handle = GSS_C_NO_CONTEXT; + } + return maj; +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_import_sec_context(OM_uint32 *minor_status, + gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle) +{ + OM_uint32 maj, tmpmin; + krb5_error_code code; + gss_ctx_id_t gssc; + krb5_gss_ctx_id_t kctx; + iakerb_ctx_id_t ctx; + + maj = krb5_gss_import_sec_context(minor_status, interprocess_token, &gssc); + if (maj != GSS_S_COMPLETE) + return maj; + kctx = (krb5_gss_ctx_id_t)gssc; + + if (!kctx->established) { + /* We don't currently support importing partially established + * contexts. */ + krb5_gss_delete_sec_context(&tmpmin, &gssc, GSS_C_NO_BUFFER); + return GSS_S_FAILURE; + } + + code = iakerb_alloc_context(&ctx, kctx->initiate); + if (code != 0) { + krb5_gss_delete_sec_context(&tmpmin, &gssc, GSS_C_NO_BUFFER); + *minor_status = code; + return GSS_S_FAILURE; + } + + ctx->gssc = gssc; + ctx->established = 1; + *context_handle = (gss_ctx_id_t)ctx; + return GSS_S_COMPLETE; +} +#endif /* LEAN_CLIENT */ + +OM_uint32 KRB5_CALLCONV +iakerb_gss_inquire_context(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, gss_name_t *src_name, + gss_name_t *targ_name, OM_uint32 *lifetime_rec, + gss_OID *mech_type, OM_uint32 *ctx_flags, + int *initiate, int *opened) +{ + OM_uint32 ret; + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (src_name != NULL) + *src_name = GSS_C_NO_NAME; + if (targ_name != NULL) + *targ_name = GSS_C_NO_NAME; + if (lifetime_rec != NULL) + *lifetime_rec = 0; + if (mech_type != NULL) + *mech_type = (gss_OID)gss_mech_iakerb; + if (ctx_flags != NULL) + *ctx_flags = 0; + if (initiate != NULL) + *initiate = ctx->initiate; + if (opened != NULL) + *opened = ctx->established; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_COMPLETE; + + ret = krb5_gss_inquire_context(minor_status, ctx->gssc, src_name, + targ_name, lifetime_rec, mech_type, + ctx_flags, initiate, opened); + + if (!ctx->established) { + /* Report IAKERB as the mech OID until the context is established. */ + if (mech_type != NULL) + *mech_type = (gss_OID)gss_mech_iakerb; + + /* We don't support exporting partially-established contexts. */ + if (ctx_flags != NULL) + *ctx_flags &= ~GSS_C_TRANS_FLAG; + } + + return ret; +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_wrap_size_limit(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, int conf_req_flag, + gss_qop_t qop_req, OM_uint32 req_output_size, + OM_uint32 *max_input_size) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return krb5_gss_wrap_size_limit(minor_status, ctx->gssc, conf_req_flag, + qop_req, req_output_size, max_input_size); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_get_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_qop_t qop_req, gss_buffer_t message_buffer, + gss_buffer_t message_token) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return krb5_gss_get_mic(minor_status, ctx->gssc, qop_req, message_buffer, + message_token); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_verify_mic(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_buffer_t msg_buffer, gss_buffer_t token_buffer, + gss_qop_t *qop_state) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return krb5_gss_verify_mic(minor_status, ctx->gssc, msg_buffer, + token_buffer, qop_state); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_inquire_sec_context_by_oid(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_UNAVAILABLE; + + return krb5_gss_inquire_sec_context_by_oid(minor_status, ctx->gssc, + desired_object, data_set); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_set_sec_context_option(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)*context_handle; + + if (ctx == NULL || ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_UNAVAILABLE; + + return krb5_gss_set_sec_context_option(minor_status, &ctx->gssc, + desired_object, value); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_wrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + int conf_req_flag, gss_qop_t qop_req, int *conf_state, + gss_iov_buffer_desc *iov, int iov_count) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return krb5_gss_wrap_iov(minor_status, ctx->gssc, conf_req_flag, qop_req, + conf_state, iov, iov_count); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_unwrap_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + int *conf_state, gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, int iov_count) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return krb5_gss_unwrap_iov(minor_status, ctx->gssc, conf_state, qop_state, + iov, iov_count); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_wrap_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, int conf_req_flag, + gss_qop_t qop_req, int *conf_state, + gss_iov_buffer_desc *iov, int iov_count) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return krb5_gss_wrap_iov_length(minor_status, ctx->gssc, conf_req_flag, + qop_req, conf_state, iov, iov_count); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_pseudo_random(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + int prf_key, const gss_buffer_t prf_in, + ssize_t desired_output_len, gss_buffer_t prf_out) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return krb5_gss_pseudo_random(minor_status, ctx->gssc, prf_key, prf_in, + desired_output_len, prf_out); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_get_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_qop_t qop_req, gss_iov_buffer_desc *iov, + int iov_count) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return krb5_gss_get_mic_iov(minor_status, ctx->gssc, qop_req, iov, + iov_count); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_verify_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_qop_t *qop_state, gss_iov_buffer_desc *iov, + int iov_count) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return krb5_gss_verify_mic_iov(minor_status, ctx->gssc, qop_state, iov, + iov_count); +} + +OM_uint32 KRB5_CALLCONV +iakerb_gss_get_mic_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, gss_qop_t qop_req, + gss_iov_buffer_desc *iov, int iov_count) +{ + iakerb_ctx_id_t ctx = (iakerb_ctx_id_t)context_handle; + + if (ctx->gssc == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + return krb5_gss_get_mic_iov_length(minor_status, ctx->gssc, qop_req, iov, + iov_count); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/import_cred.c b/krb5-1.21.3/src/lib/gssapi/krb5/import_cred.c new file mode 100644 index 00000000..0bea5e6c --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/import_cred.c @@ -0,0 +1,644 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/import_cred.c - krb5 import_cred implementation */ +/* + * Copyright (C) 2012 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. + */ + +#include "k5-int.h" +#include "k5-json.h" +#include "gssapiP_krb5.h" + +/* Return the idx element of array if it is of type tid; otherwise return + * NULL. The caller is responsible for checking the array length. */ +static k5_json_value +check_element(k5_json_array array, size_t idx, k5_json_tid tid) +{ + k5_json_value v; + + v = k5_json_array_get(array, idx); + return (k5_json_get_tid(v) == tid) ? v : NULL; +} + +/* All of the json_to_x functions return 0 on success, -1 on failure (either + * from running out of memory or from defective input). */ + +/* Convert a JSON value to a C string or to NULL. */ +static int +json_to_optional_string(k5_json_value v, char **string_out) +{ + *string_out = NULL; + if (k5_json_get_tid(v) == K5_JSON_TID_NULL) + return 0; + if (k5_json_get_tid(v) != K5_JSON_TID_STRING) + return -1; + *string_out = strdup(k5_json_string_utf8(v)); + return (*string_out == NULL) ? -1 : 0; +} + +/* Convert a JSON value to a principal or to NULL. */ +static int +json_to_principal(krb5_context context, k5_json_value v, + krb5_principal *princ_out) +{ + *princ_out = NULL; + if (k5_json_get_tid(v) == K5_JSON_TID_NULL) + return 0; + if (k5_json_get_tid(v) != K5_JSON_TID_STRING) + return -1; + if (krb5_parse_name(context, k5_json_string_utf8(v), princ_out)) + return -1; + return 0; +} + +/* Convert a JSON value to a zero-terminated enctypes list or to NULL. */ +static int +json_to_etypes(k5_json_value v, krb5_enctype **etypes_out) +{ + krb5_enctype *etypes = NULL; + k5_json_array array; + k5_json_number n; + size_t len, i; + + *etypes_out = NULL; + if (k5_json_get_tid(v) == K5_JSON_TID_NULL) + return 0; + if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) + return -1; + array = v; + len = k5_json_array_length(array); + etypes = calloc(len + 1, sizeof(*etypes)); + for (i = 0; i < len; i++) { + n = check_element(array, i, K5_JSON_TID_NUMBER); + if (n == NULL) + goto invalid; + etypes[i] = k5_json_number_value(n); + } + *etypes_out = etypes; + return 0; + +invalid: + free(etypes); + return -1; +} + +/* Convert a JSON value to a krb5 GSS name or to NULL. */ +static int +json_to_kgname(krb5_context context, k5_json_value v, + krb5_gss_name_t *name_out) +{ + k5_json_array array; + krb5_gss_name_t name = NULL; + + *name_out = NULL; + if (k5_json_get_tid(v) == K5_JSON_TID_NULL) + return 0; + if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) + return -1; + array = v; + if (k5_json_array_length(array) != 3) + return -1; + name = calloc(1, sizeof(*name)); + if (name == NULL) + return -1; + if (k5_mutex_init(&name->lock)) { + free(name); + return -1; + } + + if (json_to_principal(context, k5_json_array_get(array, 0), &name->princ)) + goto invalid; + if (json_to_optional_string(k5_json_array_get(array, 1), &name->service)) + goto invalid; + if (json_to_optional_string(k5_json_array_get(array, 2), &name->host)) + goto invalid; + + *name_out = name; + return 0; + +invalid: + kg_release_name(context, &name); + return -1; +} + +/* Convert a JSON value to a keytab handle or to NULL. */ +static int +json_to_keytab(krb5_context context, k5_json_value v, krb5_keytab *keytab_out) +{ + *keytab_out = NULL; + if (k5_json_get_tid(v) == K5_JSON_TID_NULL) + return 0; + if (k5_json_get_tid(v) != K5_JSON_TID_STRING) + return -1; + if (krb5_kt_resolve(context, k5_json_string_utf8(v), keytab_out)) + return -1; + return 0; +} + +/* Convert a JSON value to an rcache handle or to NULL. */ +static int +json_to_rcache(krb5_context context, k5_json_value v, krb5_rcache *rcache_out) +{ + krb5_rcache rcache; + + *rcache_out = NULL; + if (k5_json_get_tid(v) == K5_JSON_TID_NULL) + return 0; + if (k5_json_get_tid(v) != K5_JSON_TID_STRING) + return -1; + if (k5_rc_resolve(context, (char *)k5_json_string_utf8(v), &rcache)) + return -1; + *rcache_out = rcache; + return 0; +} + +/* Convert a JSON value to a keyblock, filling in keyblock. */ +static int +json_to_keyblock(k5_json_value v, krb5_keyblock *keyblock) +{ + k5_json_array array; + k5_json_number n; + k5_json_string s; + size_t len; + + memset(keyblock, 0, sizeof(*keyblock)); + if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) + return -1; + array = v; + if (k5_json_array_length(array) != 2) + return -1; + + n = check_element(array, 0, K5_JSON_TID_NUMBER); + if (n == NULL) + return -1; + keyblock->enctype = k5_json_number_value(n); + + s = check_element(array, 1, K5_JSON_TID_STRING); + if (s == NULL) + return -1; + if (k5_json_string_unbase64(s, &keyblock->contents, &len)) + return -1; + keyblock->length = len; + keyblock->magic = KV5M_KEYBLOCK; + return 0; +} + +/* Convert a JSON value to a krb5 address. */ +static int +json_to_address(k5_json_value v, krb5_address **addr_out) +{ + k5_json_array array; + krb5_address *addr = NULL; + k5_json_number n; + k5_json_string s; + size_t len; + + *addr_out = NULL; + if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) + return -1; + array = v; + if (k5_json_array_length(array) != 2) + return -1; + + n = check_element(array, 0, K5_JSON_TID_NUMBER); + if (n == NULL) + return -1; + s = check_element(array, 1, K5_JSON_TID_STRING); + if (s == NULL) + return -1; + + addr = malloc(sizeof(*addr)); + if (addr == NULL) + return -1; + addr->addrtype = k5_json_number_value(n); + if (k5_json_string_unbase64(s, &addr->contents, &len)) { + free(addr); + return -1; + } + addr->length = len; + addr->magic = KV5M_ADDRESS; + *addr_out = addr; + return 0; +} + +/* Convert a JSON value to a null-terminated list of krb5 addresses or to + * NULL. */ +static int +json_to_addresses(krb5_context context, k5_json_value v, + krb5_address ***addresses_out) +{ + k5_json_array array; + krb5_address **addrs = NULL; + size_t len, i; + + *addresses_out = NULL; + if (k5_json_get_tid(v) == K5_JSON_TID_NULL) + return 0; + if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) + return -1; + array = v; + len = k5_json_array_length(array); + addrs = calloc(len + 1, sizeof(*addrs)); + for (i = 0; i < len; i++) { + if (json_to_address(k5_json_array_get(array, i), &addrs[i])) + goto invalid; + } + addrs[i] = NULL; + *addresses_out = addrs; + return 0; + +invalid: + krb5_free_addresses(context, addrs); + return -1; +} + +/* Convert a JSON value to an authdata element. */ +static int +json_to_authdata_element(k5_json_value v, krb5_authdata **ad_out) +{ + k5_json_array array; + krb5_authdata *ad = NULL; + k5_json_number n; + k5_json_string s; + size_t len; + + *ad_out = NULL; + if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) + return -1; + array = v; + if (k5_json_array_length(array) != 2) + return -1; + + n = check_element(array, 0, K5_JSON_TID_NUMBER); + if (n == NULL) + return -1; + s = check_element(array, 1, K5_JSON_TID_STRING); + if (s == NULL) + return -1; + + ad = malloc(sizeof(*ad)); + if (ad == NULL) + return -1; + ad->ad_type = k5_json_number_value(n); + if (k5_json_string_unbase64(s, &ad->contents, &len)) { + free(ad); + return -1; + } + ad->length = len; + ad->magic = KV5M_AUTHDATA; + *ad_out = ad; + return 0; +} + +/* Convert a JSON value to a null-terminated authdata list or to NULL. */ +static int +json_to_authdata(krb5_context context, k5_json_value v, + krb5_authdata ***authdata_out) +{ + k5_json_array array; + krb5_authdata **authdata = NULL; + size_t len, i; + + *authdata_out = NULL; + if (k5_json_get_tid(v) == K5_JSON_TID_NULL) + return 0; + if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) + return -1; + array = v; + len = k5_json_array_length(array); + authdata = calloc(len + 1, sizeof(*authdata)); + for (i = 0; i < len; i++) { + if (json_to_authdata_element(k5_json_array_get(array, i), + &authdata[i])) + goto invalid; + } + authdata[i] = NULL; + *authdata_out = authdata; + return 0; + +invalid: + krb5_free_authdata(context, authdata); + return -1; +} + +/* Convert a JSON value to a krb5 credential structure, filling in creds. */ +static int +json_to_creds(krb5_context context, k5_json_value v, krb5_creds *creds) +{ + k5_json_array array; + k5_json_number n; + k5_json_bool b; + k5_json_string s; + unsigned char *data; + size_t len; + + memset(creds, 0, sizeof(*creds)); + if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) + return -1; + array = v; + if (k5_json_array_length(array) != 13) + return -1; + + if (json_to_principal(context, k5_json_array_get(array, 0), + &creds->client)) + goto invalid; + + if (json_to_principal(context, k5_json_array_get(array, 1), + &creds->server)) + goto invalid; + + if (json_to_keyblock(k5_json_array_get(array, 2), &creds->keyblock)) + goto invalid; + + n = check_element(array, 3, K5_JSON_TID_NUMBER); + if (n == NULL) + goto invalid; + creds->times.authtime = k5_json_number_value(n); + + n = check_element(array, 4, K5_JSON_TID_NUMBER); + if (n == NULL) + goto invalid; + creds->times.starttime = k5_json_number_value(n); + + n = check_element(array, 5, K5_JSON_TID_NUMBER); + if (n == NULL) + goto invalid; + creds->times.endtime = k5_json_number_value(n); + + n = check_element(array, 6, K5_JSON_TID_NUMBER); + if (n == NULL) + goto invalid; + creds->times.renew_till = k5_json_number_value(n); + + b = check_element(array, 7, K5_JSON_TID_BOOL); + if (b == NULL) + goto invalid; + creds->is_skey = k5_json_bool_value(b); + + n = check_element(array, 8, K5_JSON_TID_NUMBER); + if (n == NULL) + goto invalid; + creds->ticket_flags = k5_json_number_value(n); + + if (json_to_addresses(context, k5_json_array_get(array, 9), + &creds->addresses)) + goto invalid; + + s = check_element(array, 10, K5_JSON_TID_STRING); + if (s == NULL) + goto invalid; + if (k5_json_string_unbase64(s, &data, &len)) + goto invalid; + creds->ticket.data = (char *)data; + creds->ticket.length = len; + + s = check_element(array, 11, K5_JSON_TID_STRING); + if (s == NULL) + goto invalid; + if (k5_json_string_unbase64(s, &data, &len)) + goto invalid; + creds->second_ticket.data = (char *)data; + creds->second_ticket.length = len; + + if (json_to_authdata(context, k5_json_array_get(array, 12), + &creds->authdata)) + goto invalid; + + creds->magic = KV5M_CREDS; + return 0; + +invalid: + krb5_free_cred_contents(context, creds); + memset(creds, 0, sizeof(*creds)); + return -1; +} + +/* Convert a JSON value to a ccache handle or to NULL. Set *new_out to true if + * the ccache handle is a newly created memory ccache, false otherwise. */ +static int +json_to_ccache(krb5_context context, k5_json_value v, krb5_ccache *ccache_out, + krb5_boolean *new_out) +{ + krb5_error_code ret; + krb5_ccache ccache = NULL; + krb5_principal princ; + krb5_creds creds; + k5_json_array array; + size_t i, len; + + *ccache_out = NULL; + *new_out = FALSE; + if (k5_json_get_tid(v) == K5_JSON_TID_NULL) + return 0; + if (k5_json_get_tid(v) == K5_JSON_TID_STRING) { + /* We got a reference to an external ccache; just resolve it. */ + return krb5_cc_resolve(context, k5_json_string_utf8(v), ccache_out) ? + -1 : 0; + } + + /* We got the contents of a memory ccache. */ + if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) + return -1; + array = v; + len = k5_json_array_length(array); + if (len < 1) + return -1; + + /* Initialize a new memory ccache using the principal in the first array + * entry.*/ + if (krb5_cc_new_unique(context, "MEMORY", NULL, &ccache)) + return -1; + if (json_to_principal(context, k5_json_array_get(array, 0), &princ)) + goto invalid; + ret = krb5_cc_initialize(context, ccache, princ); + krb5_free_principal(context, princ); + if (ret) + goto invalid; + + /* Add remaining array entries to the ccache as credentials. */ + for (i = 1; i < len; i++) { + if (json_to_creds(context, k5_json_array_get(array, i), &creds)) + goto invalid; + ret = krb5_cc_store_cred(context, ccache, &creds); + krb5_free_cred_contents(context, &creds); + if (ret) + goto invalid; + } + + *ccache_out = ccache; + *new_out = TRUE; + return 0; + +invalid: + (void)krb5_cc_destroy(context, ccache); + return -1; +} + +/* Convert a JSON array value to a krb5 GSS credential. */ +static int +json_to_kgcred(krb5_context context, k5_json_array array, + krb5_gss_cred_id_t *cred_out) +{ + krb5_gss_cred_id_t cred; + k5_json_number n; + k5_json_bool b; + krb5_boolean is_new; + OM_uint32 tmp; + + *cred_out = NULL; + if (k5_json_array_length(array) != 14) + return -1; + + cred = calloc(1, sizeof(*cred)); + if (cred == NULL) + return -1; + if (k5_mutex_init(&cred->lock)) { + free(cred); + return -1; + } + + n = check_element(array, 0, K5_JSON_TID_NUMBER); + if (n == NULL) + goto invalid; + cred->usage = k5_json_number_value(n); + + if (json_to_kgname(context, k5_json_array_get(array, 1), &cred->name)) + goto invalid; + + if (json_to_principal(context, k5_json_array_get(array, 2), + &cred->impersonator)) + goto invalid; + + b = check_element(array, 3, K5_JSON_TID_BOOL); + if (b == NULL) + goto invalid; + cred->default_identity = k5_json_bool_value(b); + + b = check_element(array, 4, K5_JSON_TID_BOOL); + if (b == NULL) + goto invalid; + cred->iakerb_mech = k5_json_bool_value(b); + + if (json_to_keytab(context, k5_json_array_get(array, 5), &cred->keytab)) + goto invalid; + + if (json_to_rcache(context, k5_json_array_get(array, 6), &cred->rcache)) + goto invalid; + + if (json_to_ccache(context, k5_json_array_get(array, 7), &cred->ccache, + &is_new)) + goto invalid; + cred->destroy_ccache = is_new; + + if (json_to_keytab(context, k5_json_array_get(array, 8), + &cred->client_keytab)) + goto invalid; + + b = check_element(array, 9, K5_JSON_TID_BOOL); + if (b == NULL) + goto invalid; + cred->have_tgt = k5_json_bool_value(b); + + n = check_element(array, 10, K5_JSON_TID_NUMBER); + if (n == NULL) + goto invalid; + cred->expire = k5_json_number_value(n); + + n = check_element(array, 11, K5_JSON_TID_NUMBER); + if (n == NULL) + goto invalid; + cred->refresh_time = k5_json_number_value(n); + + if (json_to_etypes(k5_json_array_get(array, 12), &cred->req_enctypes)) + goto invalid; + + if (json_to_optional_string(k5_json_array_get(array, 13), &cred->password)) + goto invalid; + + *cred_out = cred; + return 0; + +invalid: + (void)krb5_gss_release_cred(&tmp, (gss_cred_id_t *)&cred); + return -1; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_import_cred(OM_uint32 *minor_status, gss_buffer_t token, + gss_cred_id_t *cred_handle) +{ + OM_uint32 status = GSS_S_COMPLETE; + krb5_context context; + krb5_error_code ret; + krb5_gss_cred_id_t cred; + k5_json_value v = NULL; + k5_json_array array; + k5_json_string str; + char *copy = NULL; + + ret = krb5_gss_init_context(&context); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + /* Decode token. */ + copy = k5memdup0(token->value, token->length, &ret); + if (copy == NULL) { + status = GSS_S_FAILURE; + *minor_status = ret; + goto cleanup; + } + if (k5_json_decode(copy, &v)) + goto invalid; + + /* Decode the CRED_EXPORT_MAGIC array wrapper. */ + if (k5_json_get_tid(v) != K5_JSON_TID_ARRAY) + goto invalid; + array = v; + if (k5_json_array_length(array) != 2) + goto invalid; + str = check_element(array, 0, K5_JSON_TID_STRING); + if (str == NULL || + strcmp(k5_json_string_utf8(str), CRED_EXPORT_MAGIC) != 0) + goto invalid; + if (json_to_kgcred(context, k5_json_array_get(array, 1), &cred)) + goto invalid; + + *cred_handle = (gss_cred_id_t)cred; + +cleanup: + free(copy); + k5_json_release(v); + krb5_free_context(context); + return status; + +invalid: + status = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/import_name.c b/krb5-1.21.3/src/lib/gssapi/krb5/import_name.c new file mode 100644 index 00000000..f64635a2 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/import_name.c @@ -0,0 +1,346 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * $Id$ + */ + +#include "gssapiP_krb5.h" + +#ifndef NO_PASSWORD +#include +#include +#endif + +#ifdef HAVE_STRING_H +#include +#else +#include +#endif + +/* + * errors: + * GSS_S_BAD_NAMETYPE if the type is bogus + * GSS_S_BAD_NAME if the type is good but the name is bogus + * GSS_S_FAILURE if memory allocation fails + */ + +/* + * Import serialized authdata context + */ +static krb5_error_code +import_name_composite(krb5_context context, + unsigned char *enc_data, size_t enc_length, + krb5_authdata_context *pad_context) +{ + krb5_authdata_context ad_context; + krb5_error_code code; + krb5_data data; + + if (enc_length == 0) + return 0; + + code = krb5_authdata_context_init(context, &ad_context); + if (code != 0) + return code; + + data.data = (char *)enc_data; + data.length = enc_length; + + code = krb5_authdata_import_attributes(context, + ad_context, + AD_USAGE_MASK, + &data); + if (code != 0) { + krb5_authdata_context_free(context, ad_context); + return code; + } + + *pad_context = ad_context; + + return 0; +} + +/* Split a host-based name "service[@host]" into allocated strings + * placed in *service_out and *host_out (possibly NULL). */ +static krb5_error_code +parse_hostbased(const char *str, size_t len, + char **service_out, char **host_out) +{ + const char *at; + size_t servicelen, hostlen; + char *service, *host = NULL; + + *service_out = *host_out = NULL; + + /* Find the bound of the service name and copy it. */ + at = memchr(str, '@', len); + servicelen = (at == NULL) ? len : (size_t)(at - str); + service = xmalloc(servicelen + 1); + if (service == NULL) + return ENOMEM; + memcpy(service, str, servicelen); + service[servicelen] = '\0'; + + /* Copy the hostname if present (at least one character after '@'). */ + if (len - servicelen > 1) { + hostlen = len - servicelen - 1; + host = malloc(hostlen + 1); + if (host == NULL) { + free(service); + return ENOMEM; + } + memcpy(host, at + 1, hostlen); + host[hostlen] = '\0'; + } + + *service_out = service; + *host_out = host; + return 0; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_import_name(minor_status, input_name_buffer, + input_name_type, output_name) + OM_uint32 *minor_status; + gss_buffer_t input_name_buffer; + gss_OID input_name_type; + gss_name_t *output_name; +{ + krb5_context context; + krb5_principal princ = NULL; + krb5_error_code code; + unsigned char *cp, *end; + char *tmp = NULL, *tmp2 = NULL, *service = NULL, *host = NULL, *stringrep; + ssize_t length; +#ifndef NO_PASSWORD + struct passwd *pw; +#endif + int is_composite = 0, is_cert = 0; + krb5_authdata_context ad_context = NULL; + OM_uint32 status = GSS_S_FAILURE; + krb5_gss_name_t name; + int flags = 0; + + *output_name = NULL; + *minor_status = 0; + + code = krb5_gss_init_context(&context); + if (code) + goto cleanup; + + if ((input_name_type != GSS_C_NULL_OID) && + (g_OID_equal(input_name_type, gss_nt_service_name) || + g_OID_equal(input_name_type, gss_nt_service_name_v2))) { + /* Split the name into service and host (or NULL). */ + code = parse_hostbased(input_name_buffer->value, + input_name_buffer->length, &service, &host); + if (code) + goto cleanup; + + /* + * Compute the initiator target name. In some cases this is a waste of + * getaddrinfo/getnameinfo queries, but computing the name when we need + * it would require a lot of code changes. + */ + code = krb5_sname_to_principal(context, host, service, KRB5_NT_SRV_HST, + &princ); + if (code) + goto cleanup; + } else if ((input_name_type != GSS_C_NULL_OID) && + (g_OID_equal(input_name_type, gss_nt_krb5_principal))) { + krb5_principal input; + + if (input_name_buffer->length != sizeof(krb5_principal)) { + code = G_WRONG_SIZE; + status = GSS_S_BAD_NAME; + goto cleanup; + } + + input = *((krb5_principal *) input_name_buffer->value); + + code = krb5_copy_principal(context, input, &princ); + if (code) + goto cleanup; + } else if ((input_name_type != NULL) && + g_OID_equal(input_name_type, GSS_C_NT_ANONYMOUS)) { + code = krb5_copy_principal(context, krb5_anonymous_principal(), + &princ); + if (code) + goto cleanup; + } else if ((input_name_type != NULL) && + g_OID_equal(input_name_type, GSS_KRB5_NT_X509_CERT)) { + code = krb5_build_principal_ext(context, &princ, 0, NULL, + input_name_buffer->length, + input_name_buffer->value, 0); + if (code) + goto cleanup; + is_cert = 1; + } else { +#ifndef NO_PASSWORD + uid_t uid; + struct passwd pwx; + char pwbuf[BUFSIZ]; +#endif + + stringrep = NULL; + + tmp = k5memdup0(input_name_buffer->value, input_name_buffer->length, + &code); + if (tmp == NULL) + goto cleanup; + tmp2 = NULL; + + /* Find the appropriate string rep to pass into parse_name. */ + if ((input_name_type == GSS_C_NULL_OID) || + g_OID_equal(input_name_type, gss_nt_krb5_name) || + g_OID_equal(input_name_type, gss_nt_user_name)) { + stringrep = tmp; + } else if (g_OID_equal(input_name_type, GSS_KRB5_NT_ENTERPRISE_NAME)) { + stringrep = tmp; + flags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE; +#ifndef NO_PASSWORD + } else if (g_OID_equal(input_name_type, gss_nt_machine_uid_name)) { + uid = *(uid_t *) input_name_buffer->value; + do_getpwuid: + if (k5_getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw) == 0) + stringrep = pw->pw_name; + else + code = G_NOUSER; + } else if (g_OID_equal(input_name_type, gss_nt_string_uid_name)) { + uid = atoi(tmp); + goto do_getpwuid; +#endif + } else if (g_OID_equal(input_name_type, gss_nt_exported_name) || + g_OID_equal(input_name_type, GSS_C_NT_COMPOSITE_EXPORT)) { +#define BOUNDS_CHECK(cp, end, n) \ + do { if ((end) - (cp) < (n)) goto fail_name; } while (0) + cp = (unsigned char *)tmp; + end = cp + input_name_buffer->length; + + BOUNDS_CHECK(cp, end, 2); + if (*cp++ != 0x04) + goto fail_name; + switch (*cp++) { + case 0x01: + break; + case 0x02: + is_composite++; + break; + default: + goto fail_name; + } + + BOUNDS_CHECK(cp, end, 2); + if (*cp++ != 0x00) + goto fail_name; + length = *cp++; + if (length != (ssize_t)gss_mech_krb5->length+2) + goto fail_name; + + BOUNDS_CHECK(cp, end, 2); + if (*cp++ != 0x06) + goto fail_name; + length = *cp++; + if (length != (ssize_t)gss_mech_krb5->length) + goto fail_name; + + BOUNDS_CHECK(cp, end, length); + if (memcmp(cp, gss_mech_krb5->elements, length) != 0) + goto fail_name; + cp += length; + + BOUNDS_CHECK(cp, end, 4); + length = *cp++; + length = (length << 8) | *cp++; + length = (length << 8) | *cp++; + length = (length << 8) | *cp++; + + BOUNDS_CHECK(cp, end, length); + tmp2 = k5alloc(length + 1, &code); + if (tmp2 == NULL) + goto cleanup; + strncpy(tmp2, (char *)cp, length); + tmp2[length] = 0; + stringrep = tmp2; + cp += length; + + if (is_composite) { + BOUNDS_CHECK(cp, end, 4); + length = *cp++; + length = (length << 8) | *cp++; + length = (length << 8) | *cp++; + length = (length << 8) | *cp++; + + BOUNDS_CHECK(cp, end, length); + code = import_name_composite(context, + cp, length, + &ad_context); + if (code != 0) + goto fail_name; + cp += length; + } + assert(cp == end); + } else { + status = GSS_S_BAD_NAMETYPE; + goto cleanup; + } + + /* At this point, stringrep is set, or if not, code is. */ + if (stringrep) { + code = krb5_parse_name_flags(context, stringrep, flags, &princ); + if (code) + goto cleanup; + } else { + fail_name: + status = GSS_S_BAD_NAME; + goto cleanup; + } + } + + /* Create a name and save it in the validation database. */ + code = kg_init_name(context, princ, service, host, ad_context, + KG_INIT_NAME_NO_COPY, &name); + if (code) + goto cleanup; + name->is_cert = is_cert; + + princ = NULL; + ad_context = NULL; + service = host = NULL; + *output_name = (gss_name_t)name; + status = GSS_S_COMPLETE; + +cleanup: + *minor_status = (OM_uint32)code; + if (*minor_status) + save_error_info(*minor_status, context); + krb5_free_principal(context, princ); + krb5_authdata_context_free(context, ad_context); + krb5_free_context(context); + free(tmp); + free(tmp2); + free(service); + free(host); + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/import_sec_context.c b/krb5-1.21.3/src/lib/gssapi/krb5/import_sec_context.c new file mode 100644 index 00000000..7d26f4df --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/import_sec_context.c @@ -0,0 +1,95 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/import_sec_context.c - Internalize the security context */ +/* + * Copyright 1995,2004,2007,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "gssapiP_krb5.h" +/* for serialization initialization functions */ +#include "k5-int.h" + +/* + * Fix up the OID of the mechanism so that uses the static version of + * the OID if possible. + */ +gss_OID krb5_gss_convert_static_mech_oid(oid) + gss_OID oid; +{ + const gss_OID_desc *p; + OM_uint32 minor_status; + + for (p = krb5_gss_oid_array; p->length; p++) { + if ((oid->length == p->length) && + (memcmp(oid->elements, p->elements, p->length) == 0)) { + generic_gss_release_oid(&minor_status, &oid); + return (gss_OID) p; + } + } + return oid; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_import_sec_context(minor_status, interprocess_token, context_handle) + OM_uint32 *minor_status; + gss_buffer_t interprocess_token; + gss_ctx_id_t *context_handle; +{ + krb5_context context; + krb5_error_code kret = 0; + size_t blen; + krb5_gss_ctx_id_t ctx; + krb5_octet *ibp; + + /* This is a bit screwy. We create a krb5 context because we need + one when calling the serialization code. However, one of the + objects we're unpacking is a krb5 context, so when we finish, + we can throw this one away. */ + kret = krb5_gss_init_context(&context); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + /* Assume a tragic failure */ + ctx = (krb5_gss_ctx_id_t) NULL; + *minor_status = 0; + + /* Internalize the context */ + ibp = (krb5_octet *) interprocess_token->value; + blen = (size_t) interprocess_token->length; + kret = kg_ctx_internalize(context, &ctx, &ibp, &blen); + if (kret) { + *minor_status = (OM_uint32) kret; + save_error_info(*minor_status, context); + krb5_free_context(context); + return(GSS_S_FAILURE); + } + krb5_free_context(context); + + ctx->mech_used = krb5_gss_convert_static_mech_oid(ctx->mech_used); + + *context_handle = (gss_ctx_id_t) ctx; + + *minor_status = 0; + return (GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/indicate_mechs.c b/krb5-1.21.3/src/lib/gssapi/krb5/indicate_mechs.c new file mode 100644 index 00000000..45538cb7 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/indicate_mechs.c @@ -0,0 +1,37 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * $Id$ + */ + +#include "gssapiP_krb5.h" +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +krb5_gss_indicate_mechs(minor_status, mech_set) + OM_uint32 *minor_status; + gss_OID_set *mech_set; +{ + return generic_gss_copy_oid_set(minor_status, kg_all_mechs, mech_set); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/init_sec_context.c b/krb5-1.21.3/src/lib/gssapi/krb5/init_sec_context.c new file mode 100644 index 00000000..5748b843 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/init_sec_context.c @@ -0,0 +1,1088 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2000, 2002, 2003, 2007, 2008 by the Massachusetts Institute of + * Technology. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "k5-int.h" +#include "gssapiP_krb5.h" +#ifdef HAVE_MEMORY_H +#include +#endif +#include +#include + +/* + * $Id$ + */ + +/* XXX This is for debugging only!!! Should become a real bitfield + at some point */ +int krb5_gss_dbg_client_expcreds = 0; + +/* + * Common code which fetches the correct krb5 credentials from the + * ccache. + */ +static krb5_error_code get_credentials(context, cred, server, now, + endtime, out_creds) + krb5_context context; + krb5_gss_cred_id_t cred; + krb5_gss_name_t server; + krb5_timestamp now; + krb5_timestamp endtime; + krb5_creds **out_creds; +{ + krb5_error_code code; + krb5_creds in_creds, evidence_creds, mcreds, *result_creds = NULL; + krb5_flags flags = 0; + krb5_principal_data server_data; + + *out_creds = NULL; + + k5_mutex_assert_locked(&cred->lock); + memset(&in_creds, 0, sizeof(krb5_creds)); + memset(&evidence_creds, 0, sizeof(krb5_creds)); + in_creds.client = in_creds.server = NULL; + + assert(cred->name != NULL); + + /* Remove assumed realm from host-based S4U2Proxy requests as they must + * start in the client realm. */ + server_data = *server->princ; + if (cred->impersonator != NULL && server_data.type == KRB5_NT_SRV_HST) + server_data.realm = empty_data(); + in_creds.server = &server_data; + + in_creds.client = cred->name->princ; + in_creds.times.endtime = endtime; + in_creds.authdata = NULL; + in_creds.keyblock.enctype = 0; + + /* + * cred->name is immutable, so there is no need to acquire + * cred->name->lock. + */ + if (cred->name->ad_context != NULL) { + code = krb5_authdata_export_authdata(context, + cred->name->ad_context, + AD_USAGE_TGS_REQ, + &in_creds.authdata); + if (code != 0) + goto cleanup; + } + + /* Try constrained delegation if we have proxy credentials. */ + if (cred->impersonator != NULL) { + /* If we are trying to get a ticket to ourselves, we should use the + * the evidence ticket directly from cache. */ + if (krb5_principal_compare(context, cred->impersonator, + server->princ)) { + flags |= KRB5_GC_CACHED; + } else { + memset(&mcreds, 0, sizeof(mcreds)); + mcreds.magic = KV5M_CREDS; + mcreds.server = cred->impersonator; + mcreds.client = cred->name->princ; + code = krb5_cc_retrieve_cred(context, cred->ccache, + KRB5_TC_MATCH_AUTHDATA, &mcreds, + &evidence_creds); + if (code) + goto cleanup; + + in_creds.client = cred->impersonator; + in_creds.second_ticket = evidence_creds.ticket; + flags = KRB5_GC_CANONICALIZE | KRB5_GC_CONSTRAINED_DELEGATION; + } + } + + /* For IAKERB, only check the cache in this step. We will ask the server + * to make any necessary TGS requests. */ + if (cred->iakerb_mech) + flags |= KRB5_GC_CACHED; + + code = krb5_get_credentials(context, flags, cred->ccache, + &in_creds, &result_creds); + if (code) + goto cleanup; + + if (flags & KRB5_GC_CONSTRAINED_DELEGATION) { + if (!krb5_principal_compare(context, cred->name->princ, + result_creds->client)) { + /* server did not support constrained delegation */ + code = KRB5_KDCREP_MODIFIED; + goto cleanup; + } + } + + /* + * Enforce a stricter limit (without timeskew forgiveness at the + * boundaries) because accept_sec_context code is also similarly + * non-forgiving. + */ + if (!krb5_gss_dbg_client_expcreds && + ts_after(now, result_creds->times.endtime)) { + code = KRB5KRB_AP_ERR_TKT_EXPIRED; + goto cleanup; + } + + *out_creds = result_creds; + result_creds = NULL; + +cleanup: + krb5_free_authdata(context, in_creds.authdata); + krb5_free_cred_contents(context, &evidence_creds); + krb5_free_creds(context, result_creds); + + return code; +} +struct gss_checksum_data { + krb5_gss_ctx_id_rec *ctx; + krb5_gss_cred_id_t cred; + krb5_checksum md5; + krb5_data checksum_data; + krb5_gss_ctx_ext_t exts; +}; + +#ifdef CFX_EXERCISE +#include "../../krb5/krb/auth_con.h" +#endif +static krb5_error_code KRB5_CALLCONV +make_gss_checksum (krb5_context context, krb5_auth_context auth_context, + void *cksum_data, krb5_data **out) +{ + krb5_error_code code; + krb5_int32 con_flags; + struct gss_checksum_data *data = cksum_data; + krb5_data credmsg; + unsigned int junk; + krb5_data *finished = NULL; + krb5_key send_subkey; + struct k5buf buf; + + data->checksum_data = empty_data(); + credmsg.data = 0; + /* build the checksum field */ + + if (data->ctx->gss_flags & GSS_C_DELEG_FLAG) { + /* first get KRB_CRED message, so we know its length */ + + /* clear the time check flag that was set in krb5_auth_con_init() */ + krb5_auth_con_getflags(context, auth_context, &con_flags); + krb5_auth_con_setflags(context, auth_context, + con_flags & ~KRB5_AUTH_CONTEXT_DO_TIME); + + assert(data->cred->name != NULL); + + /* + * RFC 4121 4.1.1 specifies forwarded credentials must be encrypted in + * the session key, but krb5_fwd_tgt_creds will use the send subkey if + * it's set in the auth context. Suppress the send subkey + * temporarily. + */ + krb5_auth_con_getsendsubkey_k(context, auth_context, &send_subkey); + krb5_auth_con_setsendsubkey_k(context, auth_context, NULL); + + code = krb5_fwd_tgt_creds(context, auth_context, 0, + data->cred->name->princ, data->ctx->there->princ, + data->cred->ccache, 1, + &credmsg); + + /* Turn KRB5_AUTH_CONTEXT_DO_TIME back on and reset the send subkey. */ + krb5_auth_con_setflags(context, auth_context, con_flags); + krb5_auth_con_setsendsubkey_k(context, auth_context, send_subkey); + krb5_k_free_key(context, send_subkey); + + if (code) { + /* don't fail here; just don't accept/do the delegation + request */ + data->ctx->gss_flags &= ~(GSS_C_DELEG_FLAG | + GSS_C_DELEG_POLICY_FLAG); + } else { + if (credmsg.length+28 > KRB5_INT16_MAX) { + code = KRB5KRB_ERR_FIELD_TOOLONG; + goto cleanup; + } + } + } +#ifdef CFX_EXERCISE + if (data->ctx->auth_context->keyblock != NULL + && data->ctx->auth_context->keyblock->enctype == 18) { + srand(time(0) ^ getpid()); + /* Our ftp client code stupidly assumes a base64-encoded + version of the token will fit in 10K, so don't make this + too big. */ + junk = rand() & 0xff; + } else + junk = 0; +#else + junk = 0; +#endif + + assert(data->exts != NULL); + + if (data->exts->iakerb.conv) { + krb5_key key; + + code = krb5_auth_con_getsendsubkey_k(context, auth_context, &key); + if (code != 0) + goto cleanup; + + code = iakerb_make_finished(context, key, data->exts->iakerb.conv, + &finished); + if (code != 0) { + krb5_k_free_key(context, key); + goto cleanup; + } + + krb5_k_free_key(context, key); + } + + /* now allocate a buffer to hold the checksum data and + (maybe) KRB_CRED msg */ + k5_buf_init_dynamic(&buf); + k5_buf_add_uint32_le(&buf, data->md5.length); + k5_buf_add_len(&buf, data->md5.contents, data->md5.length); + k5_buf_add_uint32_le(&buf, data->ctx->gss_flags); + if (credmsg.data != NULL) { + k5_buf_add_uint16_le(&buf, KRB5_GSS_FOR_CREDS_OPTION); + k5_buf_add_uint16_le(&buf, credmsg.length); + k5_buf_add_len(&buf, credmsg.data, credmsg.length); + } + if (data->exts->iakerb.conv != NULL) { + k5_buf_add_uint32_be(&buf, KRB5_GSS_EXTS_IAKERB_FINISHED); + k5_buf_add_uint32_be(&buf, finished->length); + k5_buf_add_len(&buf, finished->data, finished->length); + } + while (junk--) + k5_buf_add_byte(&buf, 'i'); + + code = k5_buf_status(&buf); + if (code) + goto cleanup; + + data->checksum_data = make_data(buf.data, buf.len); + *out = &data->checksum_data; + code = 0; + +cleanup: + krb5_free_data_contents(context, &credmsg); + krb5_free_data(context, finished); + return code; +} + +static krb5_error_code +make_ap_req_v1(context, ctx, cred, k_cred, ad_context, + chan_bindings, mech_type, token, exts) + krb5_context context; + krb5_gss_ctx_id_rec *ctx; + krb5_gss_cred_id_t cred; + krb5_creds *k_cred; + krb5_authdata_context ad_context; + gss_channel_bindings_t chan_bindings; + gss_OID mech_type; + gss_buffer_t token; + krb5_gss_ctx_ext_t exts; +{ + krb5_flags mk_req_flags = 0; + krb5_error_code code; + struct gss_checksum_data cksum_struct; + krb5_checksum md5; + krb5_data ap_req; + unsigned char *t; + unsigned int tlen; + struct k5buf buf; + + k5_mutex_assert_locked(&cred->lock); + ap_req.data = 0; + + /* compute the hash of the channel bindings */ + + if ((code = kg_checksum_channel_bindings(context, chan_bindings, &md5))) + return(code); + + krb5_auth_con_set_req_cksumtype(context, ctx->auth_context, + CKSUMTYPE_KG_CB); + cksum_struct.md5 = md5; + cksum_struct.ctx = ctx; + cksum_struct.cred = cred; + cksum_struct.checksum_data.data = NULL; + cksum_struct.exts = exts; + krb5_auth_con_set_checksum_func(context, ctx->auth_context, + make_gss_checksum, &cksum_struct); + + /* call mk_req. subkey and ap_req need to be used or destroyed */ + + mk_req_flags = AP_OPTS_USE_SUBKEY; + + if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) + mk_req_flags |= AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_ETYPE_NEGOTIATION; + + krb5_auth_con_set_authdata_context(context, ctx->auth_context, ad_context); + code = krb5_mk_req_extended(context, &ctx->auth_context, mk_req_flags, + NULL, k_cred, &ap_req); + krb5_auth_con_set_authdata_context(context, ctx->auth_context, NULL); + krb5_free_checksum_contents(context, &cksum_struct.md5); + krb5_free_data_contents(context, &cksum_struct.checksum_data); + if (code) + goto cleanup; + + /* store the interesting stuff from creds and authent */ + ctx->krb_times = k_cred->times; + ctx->krb_flags = k_cred->ticket_flags; + + /* build up the token */ + if (ctx->gss_flags & GSS_C_DCE_STYLE) { + /* + * For DCE RPC, do not encapsulate the AP-REQ in the + * typical GSS wrapping. + */ + code = data_to_gss(&ap_req, token); + if (code) + goto cleanup; + } else { + /* allocate space for the token */ + tlen = g_token_size((gss_OID) mech_type, ap_req.length); + t = gssalloc_malloc(tlen); + if (t == NULL) { + code = ENOMEM; + goto cleanup; + } + k5_buf_init_fixed(&buf, t, tlen); + g_make_token_header(&buf, mech_type, ap_req.length, KG_TOK_CTX_AP_REQ); + k5_buf_add_len(&buf, ap_req.data, ap_req.length); + assert(buf.len == tlen); + + /* pass it back */ + + token->length = tlen; + token->value = (void *) t; + } + + code = 0; + +cleanup: + if (ap_req.data) + krb5_free_data_contents(context, &ap_req); + + return (code); +} + +/* + * new_connection + * + * Do the grunt work of setting up a new context. + */ +static OM_uint32 +kg_new_connection( + OM_uint32 *minor_status, + krb5_gss_cred_id_t cred, + gss_ctx_id_t *context_handle, + gss_name_t target_name, + gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_OID *actual_mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec, + krb5_context context, + krb5_gss_ctx_ext_t exts) +{ + OM_uint32 major_status; + krb5_error_code code; + krb5_creds *k_cred = NULL; + krb5_gss_ctx_id_rec *ctx, *ctx_free; + krb5_timestamp now; + gss_buffer_desc token; + krb5_keyblock *keyblock; + + k5_mutex_assert_locked(&cred->lock); + major_status = GSS_S_FAILURE; + token.length = 0; + token.value = NULL; + + /* make sure the cred is usable for init */ + + if ((cred->usage != GSS_C_INITIATE) && + (cred->usage != GSS_C_BOTH)) { + *minor_status = 0; + return(GSS_S_NO_CRED); + } + + /* complain if the input token is non-null */ + + if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) { + *minor_status = 0; + return(GSS_S_DEFECTIVE_TOKEN); + } + + /* create the ctx */ + + if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec))) + == NULL) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + + /* fill in the ctx */ + memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec)); + ctx->magic = KG_CONTEXT; + ctx_free = ctx; + if ((code = krb5_auth_con_init(context, &ctx->auth_context))) + goto cleanup; + krb5_auth_con_setflags(context, ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE); + + /* limit the encryption types negotiated (if requested) */ + if (cred->req_enctypes) { + if ((code = krb5_set_default_tgs_enctypes(context, + cred->req_enctypes))) { + goto cleanup; + } + } + + ctx->initiate = 1; + ctx->seed_init = 0; + ctx->seqstate = 0; + + /* enforce_ok_as_delegate causes GSS_C_DELEG_FLAG to be treated as + * GSS_C_DELEG_POLICY_FLAG (so ok-as-delegate is always enforced). */ + if (context->enforce_ok_as_delegate && (req_flags & GSS_C_DELEG_FLAG)) { + req_flags &= ~GSS_C_DELEG_FLAG; + req_flags |= GSS_C_DELEG_POLICY_FLAG; + } + + ctx->gss_flags = req_flags & (GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | + GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | + GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG | + GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG | + GSS_C_EXTENDED_ERROR_FLAG); + ctx->gss_flags |= GSS_C_TRANS_FLAG; + if (!cred->suppress_ci_flags) + ctx->gss_flags |= (GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG); + if (req_flags & GSS_C_DCE_STYLE) + ctx->gss_flags |= GSS_C_MUTUAL_FLAG; + + if ((code = krb5_timeofday(context, &now))) + goto cleanup; + + if (time_req == 0 || time_req == GSS_C_INDEFINITE) { + ctx->krb_times.endtime = 0; + } else { + ctx->krb_times.endtime = ts_incr(now, time_req); + } + + if ((code = kg_duplicate_name(context, cred->name, &ctx->here))) + goto cleanup; + + if ((code = kg_duplicate_name(context, (krb5_gss_name_t)target_name, + &ctx->there))) + goto cleanup; + + code = get_credentials(context, cred, ctx->there, now, + ctx->krb_times.endtime, &k_cred); + if (code) + goto cleanup; + + ctx->krb_times = k_cred->times; + + /* + * GSS_C_DELEG_POLICY_FLAG means to delegate only if the + * ok-as-delegate ticket flag is set. + */ + if ((req_flags & GSS_C_DELEG_POLICY_FLAG) + && (k_cred->ticket_flags & TKT_FLG_OK_AS_DELEGATE)) + ctx->gss_flags |= GSS_C_DELEG_FLAG | GSS_C_DELEG_POLICY_FLAG; + + if (generic_gss_copy_oid(minor_status, mech_type, &ctx->mech_used) + != GSS_S_COMPLETE) { + code = *minor_status; + goto cleanup; + } + /* + * Now try to make it static if at all possible.... + */ + ctx->mech_used = krb5_gss_convert_static_mech_oid(ctx->mech_used); + + { + /* gsskrb5 v1 */ + krb5_int32 seq_temp; + if ((code = make_ap_req_v1(context, ctx, + cred, k_cred, ctx->here->ad_context, + input_chan_bindings, + mech_type, &token, exts))) { + if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) || + (code == KG_EMPTY_CCACHE)) + major_status = GSS_S_NO_CRED; + if (code == KRB5KRB_AP_ERR_TKT_EXPIRED) + major_status = GSS_S_CREDENTIALS_EXPIRED; + goto cleanup; + } + + krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, &seq_temp); + ctx->seq_send = (uint32_t)seq_temp; + code = krb5_auth_con_getsendsubkey(context, ctx->auth_context, + &keyblock); + if (code != 0) + goto cleanup; + code = krb5_k_create_key(context, keyblock, &ctx->subkey); + krb5_free_keyblock(context, keyblock); + if (code != 0) + goto cleanup; + } + + ctx->enc = NULL; + ctx->seq = NULL; + ctx->have_acceptor_subkey = 0; + code = kg_setup_keys(context, ctx, ctx->subkey, &ctx->cksumtype); + if (code != 0) + goto cleanup; + + if (!(ctx->gss_flags & GSS_C_MUTUAL_FLAG)) { + /* There will be no AP-REP, so set up sequence state now. */ + ctx->seq_recv = ctx->seq_send; + code = g_seqstate_init(&ctx->seqstate, ctx->seq_recv, + (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0, + (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, + ctx->proto); + if (code != 0) + goto cleanup; + } + + /* compute time_rec */ + if (time_rec) { + if ((code = krb5_timeofday(context, &now))) + goto cleanup; + *time_rec = ts_interval(now, ctx->krb_times.endtime); + } + + /* set the other returns */ + *output_token = token; + + if (ret_flags) + *ret_flags = ctx->gss_flags; + + if (actual_mech_type) + *actual_mech_type = mech_type; + + /* return successfully */ + + *context_handle = (gss_ctx_id_t) ctx; + ctx_free = NULL; + if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) { + ctx->established = 0; + major_status = GSS_S_CONTINUE_NEEDED; + } else { + ctx->gss_flags |= GSS_C_PROT_READY_FLAG; + ctx->established = 1; + major_status = GSS_S_COMPLETE; + } + +cleanup: + krb5_free_creds(context, k_cred); + if (ctx_free) { + if (ctx_free->auth_context) + krb5_auth_con_free(context, ctx_free->auth_context); + if (ctx_free->here) + kg_release_name(context, &ctx_free->here); + if (ctx_free->there) + kg_release_name(context, &ctx_free->there); + if (ctx_free->subkey) + krb5_k_free_key(context, ctx_free->subkey); + xfree(ctx_free); + } + + *minor_status = code; + return (major_status); +} + +/* + * mutual_auth + * + * Handle the reply from the acceptor, if we're doing mutual auth. + */ +static OM_uint32 +mutual_auth( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_name_t target_name, + gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_OID *actual_mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec, + krb5_context context) +{ + OM_uint32 major_status; + unsigned char *ptr; + krb5_data ap_rep; + krb5_ap_rep_enc_part *ap_rep_data; + krb5_timestamp now; + krb5_gss_ctx_id_rec *ctx; + krb5_error *krb_error; + krb5_error_code code; + krb5int_access kaccess; + + major_status = GSS_S_FAILURE; + + code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION); + if (code) + goto fail; + + ctx = (krb5_gss_ctx_id_t) *context_handle; + + /* make sure the context is non-established, and that certain + arguments are unchanged */ + + if ((ctx->established) || + ((ctx->gss_flags & GSS_C_MUTUAL_FLAG) == 0)) { + code = KG_CONTEXT_ESTABLISHED; + goto fail; + } + + if (! kg_compare_name(context, ctx->there, (krb5_gss_name_t)target_name)) { + (void)krb5_gss_delete_sec_context(minor_status, + context_handle, NULL); + code = 0; + major_status = GSS_S_BAD_NAME; + goto fail; + } + + /* verify the token and leave the AP_REP message in ap_rep */ + + if (input_token == GSS_C_NO_BUFFER) { + (void)krb5_gss_delete_sec_context(minor_status, + context_handle, NULL); + code = 0; + major_status = GSS_S_DEFECTIVE_TOKEN; + goto fail; + } + + ptr = (unsigned char *) input_token->value; + + if (ctx->gss_flags & GSS_C_DCE_STYLE) { + /* Raw AP-REP */ + ap_rep.length = input_token->length; + } else if (g_verify_token_header(ctx->mech_used, + &(ap_rep.length), + &ptr, KG_TOK_CTX_AP_REP, + input_token->length, 1)) { + if (g_verify_token_header((gss_OID) ctx->mech_used, + &(ap_rep.length), + &ptr, KG_TOK_CTX_ERROR, + input_token->length, 1) == 0) { + + /* Handle a KRB_ERROR message from the server */ + + ap_rep.data = (char *)ptr; + code = krb5_rd_error(context, &ap_rep, &krb_error); + if (code) + goto fail; + if (krb_error->error) + code = (krb5_error_code)krb_error->error + ERROR_TABLE_BASE_krb5; + else + code = 0; + krb5_free_error(context, krb_error); + goto fail; + } else { + *minor_status = 0; + return(GSS_S_DEFECTIVE_TOKEN); + } + } + ap_rep.data = (char *)ptr; + + /* decode the ap_rep */ + if ((code = krb5_rd_rep(context, ctx->auth_context, &ap_rep, + &ap_rep_data))) { + /* + * XXX A hack for backwards compatibility. + * To be removed in 1999 -- proven + */ + krb5_auth_con_setuseruserkey(context, ctx->auth_context, + &ctx->subkey->keyblock); + if ((krb5_rd_rep(context, ctx->auth_context, &ap_rep, + &ap_rep_data))) + goto fail; + } + + /* store away the sequence number */ + ctx->seq_recv = ap_rep_data->seq_number; + code = g_seqstate_init(&ctx->seqstate, ctx->seq_recv, + (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0, + (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, + ctx->proto); + if (code) { + krb5_free_ap_rep_enc_part(context, ap_rep_data); + goto fail; + } + + if (ap_rep_data->subkey != NULL && + (ctx->proto == 1 || (ctx->gss_flags & GSS_C_DCE_STYLE) || + ap_rep_data->subkey->enctype != ctx->subkey->keyblock.enctype)) { + /* Keep acceptor's subkey. */ + ctx->have_acceptor_subkey = 1; + code = krb5_k_create_key(context, ap_rep_data->subkey, + &ctx->acceptor_subkey); + if (code) { + krb5_free_ap_rep_enc_part(context, ap_rep_data); + goto fail; + } + code = kg_setup_keys(context, ctx, ctx->acceptor_subkey, + &ctx->acceptor_subkey_cksumtype); + if (code) { + krb5_free_ap_rep_enc_part(context, ap_rep_data); + goto fail; + } + } + /* free the ap_rep_data */ + krb5_free_ap_rep_enc_part(context, ap_rep_data); + + if (ctx->gss_flags & GSS_C_DCE_STYLE) { + krb5_data outbuf; + + code = krb5_mk_rep_dce(context, ctx->auth_context, &outbuf); + if (code) + goto fail; + + code = data_to_gss(&outbuf, output_token); + if (code) + goto fail; + } + + /* set established */ + ctx->established = 1; + + /* set returns */ + + if (time_rec) { + if ((code = krb5_timeofday(context, &now))) + goto fail; + *time_rec = ts_interval(now, ctx->krb_times.endtime); + } + + if (ret_flags) + *ret_flags = ctx->gss_flags; + + if (actual_mech_type) + *actual_mech_type = mech_type; + + /* success */ + + *minor_status = 0; + return GSS_S_COMPLETE; + +fail: + (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL); + + *minor_status = code; + return (major_status); +} + +OM_uint32 +krb5_gss_init_sec_context_ext( + OM_uint32 *minor_status, + gss_cred_id_t claimant_cred_handle, + gss_ctx_id_t *context_handle, + gss_name_t target_name, + gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_OID *actual_mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec, + krb5_gss_ctx_ext_t exts) +{ + krb5_context context; + gss_cred_id_t defcred = GSS_C_NO_CREDENTIAL; + krb5_gss_cred_id_t cred; + krb5_error_code kerr; + OM_uint32 major_status; + OM_uint32 tmp_min_stat; + + if (*context_handle == GSS_C_NO_CONTEXT) { + kerr = krb5_gss_init_context(&context); + if (kerr) { + *minor_status = kerr; + return GSS_S_FAILURE; + } + if (GSS_ERROR(kg_sync_ccache_name(context, minor_status))) { + save_error_info(*minor_status, context); + krb5_free_context(context); + return GSS_S_FAILURE; + } + } else { + context = ((krb5_gss_ctx_id_rec *)*context_handle)->k5_context; + } + + /* set up return values so they can be "freed" successfully */ + + major_status = GSS_S_FAILURE; /* Default major code */ + output_token->length = 0; + output_token->value = NULL; + if (actual_mech_type) + *actual_mech_type = NULL; + + /* verify the mech_type */ + + if (mech_type == GSS_C_NULL_OID || g_OID_equal(mech_type, gss_mech_krb5)) { + mech_type = (gss_OID) gss_mech_krb5; + } else if (g_OID_equal(mech_type, gss_mech_krb5_old)) { + mech_type = (gss_OID) gss_mech_krb5_old; + } else if (g_OID_equal(mech_type, gss_mech_krb5_wrong)) { + mech_type = (gss_OID) gss_mech_krb5_wrong; + } else if (g_OID_equal(mech_type, gss_mech_iakerb)) { + mech_type = (gss_OID) gss_mech_iakerb; + } else { + *minor_status = 0; + if (*context_handle == GSS_C_NO_CONTEXT) + krb5_free_context(context); + return(GSS_S_BAD_MECH); + } + + /* is this a new connection or not? */ + + /*SUPPRESS 29*/ + if (*context_handle == GSS_C_NO_CONTEXT) { + /* verify the credential, or use the default */ + /*SUPPRESS 29*/ + if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) { + major_status = kg_get_defcred(minor_status, &defcred); + if (major_status && GSS_ERROR(major_status)) { + if (*context_handle == GSS_C_NO_CONTEXT) + krb5_free_context(context); + return(major_status); + } + claimant_cred_handle = defcred; + } + + major_status = kg_cred_resolve(minor_status, context, + claimant_cred_handle, target_name); + if (GSS_ERROR(major_status)) { + save_error_info(*minor_status, context); + krb5_gss_release_cred(&tmp_min_stat, &defcred); + if (*context_handle == GSS_C_NO_CONTEXT) + krb5_free_context(context); + return(major_status); + } + cred = (krb5_gss_cred_id_t)claimant_cred_handle; + + major_status = kg_new_connection(minor_status, cred, context_handle, + target_name, mech_type, req_flags, + time_req, input_chan_bindings, + input_token, actual_mech_type, + output_token, ret_flags, time_rec, + context, exts); + k5_mutex_unlock(&cred->lock); + krb5_gss_release_cred(&tmp_min_stat, &defcred); + if (*context_handle == GSS_C_NO_CONTEXT) { + save_error_info (*minor_status, context); + krb5_free_context(context); + } else + ((krb5_gss_ctx_id_rec *) *context_handle)->k5_context = context; + } else { + /* mutual_auth doesn't care about the credentials */ + major_status = mutual_auth(minor_status, context_handle, + target_name, mech_type, req_flags, + time_req, input_chan_bindings, + input_token, actual_mech_type, + output_token, ret_flags, time_rec, + context); + /* If context_handle is now NO_CONTEXT, mutual_auth called + delete_sec_context, which would've zapped the krb5 context + too. */ + } + + return(major_status); +} + +#ifndef _WIN32 +k5_mutex_t kg_kdc_flag_mutex = K5_MUTEX_PARTIAL_INITIALIZER; +static int kdc_flag = 0; +#endif + +krb5_error_code +krb5_gss_init_context (krb5_context *ctxp) +{ + krb5_error_code err; +#ifndef _WIN32 + int is_kdc; +#endif + + err = gss_krb5int_initialize_library(); + if (err) + return err; +#ifndef _WIN32 + k5_mutex_lock(&kg_kdc_flag_mutex); + is_kdc = kdc_flag; + k5_mutex_unlock(&kg_kdc_flag_mutex); + + if (is_kdc) + return krb5int_init_context_kdc(ctxp); +#endif + + return krb5_init_context(ctxp); +} + +#ifndef _WIN32 +OM_uint32 +krb5int_gss_use_kdc_context(OM_uint32 *minor_status, + const gss_OID desired_mech, + const gss_OID desired_object, + gss_buffer_t value) +{ + OM_uint32 err; + + *minor_status = 0; + + err = gss_krb5int_initialize_library(); + if (err) + return err; + k5_mutex_lock(&kg_kdc_flag_mutex); + kdc_flag = 1; + k5_mutex_unlock(&kg_kdc_flag_mutex); + return GSS_S_COMPLETE; +} +#endif + +OM_uint32 KRB5_CALLCONV +krb5_gss_init_sec_context(minor_status, claimant_cred_handle, + context_handle, target_name, mech_type, + req_flags, time_req, input_chan_bindings, + input_token, actual_mech_type, output_token, + ret_flags, time_rec) + OM_uint32 *minor_status; + gss_cred_id_t claimant_cred_handle; + gss_ctx_id_t *context_handle; + gss_name_t target_name; + gss_OID mech_type; + OM_uint32 req_flags; + OM_uint32 time_req; + gss_channel_bindings_t input_chan_bindings; + gss_buffer_t input_token; + gss_OID *actual_mech_type; + gss_buffer_t output_token; + OM_uint32 *ret_flags; + OM_uint32 *time_rec; +{ + krb5_gss_ctx_ext_rec exts; + + memset(&exts, 0, sizeof(exts)); + + return krb5_gss_init_sec_context_ext(minor_status, + claimant_cred_handle, + context_handle, + target_name, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec, + &exts); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/inq_context.c b/krb5-1.21.3/src/lib/gssapi/krb5/inq_context.c new file mode 100644 index 00000000..97678e3e --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/inq_context.c @@ -0,0 +1,373 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "gssapiP_krb5.h" + +OM_uint32 KRB5_CALLCONV +krb5_gss_inquire_context(minor_status, context_handle, initiator_name, + acceptor_name, lifetime_rec, mech_type, ret_flags, + locally_initiated, opened) + OM_uint32 *minor_status; + gss_ctx_id_t context_handle; + gss_name_t *initiator_name; + gss_name_t *acceptor_name; + OM_uint32 *lifetime_rec; + gss_OID *mech_type; + OM_uint32 *ret_flags; + int *locally_initiated; + int *opened; +{ + krb5_context context; + krb5_error_code code; + krb5_gss_ctx_id_rec *ctx; + krb5_gss_name_t initiator, acceptor; + krb5_timestamp now, start; + OM_uint32 lifetime; + + if (initiator_name) + *initiator_name = (gss_name_t) NULL; + if (acceptor_name) + *acceptor_name = (gss_name_t) NULL; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + context = ctx->k5_context; + + /* RFC 2743 states that a partially completed context must return + * flags, locally_initiated, and open, and *may* return mech_type. */ + if (ctx->established) { + initiator = NULL; + acceptor = NULL; + + if ((code = krb5_timeofday(context, &now))) { + *minor_status = code; + save_error_info(*minor_status, context); + return(GSS_S_FAILURE); + } + + /* Add the maximum allowable clock skew as a grace period for context + * expiration, just as we do for the ticket during authentication. */ + start = ctx->initiate ? now : ts_incr(now, -context->clockskew); + lifetime = ts_interval(start, ctx->krb_times.endtime); + + if (initiator_name) { + code = kg_duplicate_name(context, + ctx->initiate ? ctx->here : ctx->there, + &initiator); + if (code) { + *minor_status = code; + save_error_info(*minor_status, context); + return(GSS_S_FAILURE); + } + } + + if (acceptor_name) { + code = kg_duplicate_name(context, + ctx->initiate ? ctx->there : ctx->here, + &acceptor); + if (code) { + if (initiator) + kg_release_name(context, &initiator); + *minor_status = code; + save_error_info(*minor_status, context); + return(GSS_S_FAILURE); + } + } + + if (initiator_name) + *initiator_name = (gss_name_t) initiator; + + if (acceptor_name) + *acceptor_name = (gss_name_t) acceptor; + + if (lifetime_rec) + *lifetime_rec = lifetime; + } else { + lifetime = 0; + if (initiator_name) + *initiator_name = GSS_C_NO_NAME; + + if (acceptor_name) + *acceptor_name = GSS_C_NO_NAME; + + if (lifetime_rec) + *lifetime_rec = 0; + } + + if (mech_type) + *mech_type = (gss_OID) ctx->mech_used; + + if (ret_flags) + *ret_flags = ctx->gss_flags; + + if (locally_initiated) + *locally_initiated = ctx->initiate; + + if (opened) + *opened = ctx->established; + + *minor_status = 0; + if (ctx->established) + return((lifetime == 0)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE); + else + return GSS_S_COMPLETE; +} + +/* Add two buffers to data_set giving the contents and enctype of key. */ +static OM_uint32 +inq_session_key_result(OM_uint32 *minor_status, krb5_key key, + gss_buffer_set_t *data_set) +{ + gss_buffer_desc keyvalue, keyinfo; + OM_uint32 major, tmpmin; + unsigned char oid_buf[GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH + 6]; + gss_OID_desc oid; + + keyvalue.value = key->keyblock.contents; + keyvalue.length = key->keyblock.length; + major = generic_gss_add_buffer_set_member(minor_status, &keyvalue, + data_set); + if (GSS_ERROR(major)) + goto cleanup; + + oid.elements = oid_buf; + oid.length = sizeof(oid_buf); + major = generic_gss_oid_compose(minor_status, + GSS_KRB5_SESSION_KEY_ENCTYPE_OID, + GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH, + key->keyblock.enctype, &oid); + if (GSS_ERROR(major)) + goto cleanup; + + keyinfo.value = oid.elements; + keyinfo.length = oid.length; + major = generic_gss_add_buffer_set_member(minor_status, &keyinfo, + data_set); + if (GSS_ERROR(major)) + goto cleanup; + + return GSS_S_COMPLETE; + +cleanup: + if (*data_set != GSS_C_NO_BUFFER_SET) { + if ((*data_set)->count != 0) { + zap((*data_set)->elements[0].value, + (*data_set)->elements[0].length); + } + gss_release_buffer_set(&tmpmin, data_set); + } + + return major; +} + +OM_uint32 +gss_krb5int_inq_sspi_session_key(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_gss_ctx_id_t ctx = (krb5_gss_ctx_id_t)context_handle; + krb5_key key; + + if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + key = ctx->have_acceptor_subkey ? ctx->acceptor_subkey : ctx->subkey; + return inq_session_key_result(minor_status, key, data_set); +} + +OM_uint32 +gss_krb5int_inq_odbc_session_key(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + OM_uint32 major; + krb5_error_code ret; + krb5_gss_ctx_id_t ctx = (krb5_gss_ctx_id_t)context_handle; + krb5_key key; + + if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + ret = krb5_auth_con_getkey_k(ctx->k5_context, ctx->auth_context, &key); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + major = inq_session_key_result(minor_status, key, data_set); + krb5_k_free_key(ctx->k5_context, key); + return major; +} + +OM_uint32 +gss_krb5int_extract_authz_data_from_sec_context( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + OM_uint32 major_status; + krb5_gss_ctx_id_rec *ctx; + int ad_type = 0; + size_t i; + + *data_set = GSS_C_NO_BUFFER_SET; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + + major_status = generic_gss_oid_decompose(minor_status, + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID, + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH, + desired_object, + &ad_type); + if (major_status != GSS_S_COMPLETE || ad_type == 0) { + *minor_status = ENOENT; + return GSS_S_FAILURE; + } + + if (ctx->authdata != NULL) { + for (i = 0; ctx->authdata[i] != NULL; i++) { + if (ctx->authdata[i]->ad_type == ad_type) { + gss_buffer_desc ad_data; + + ad_data.length = ctx->authdata[i]->length; + ad_data.value = ctx->authdata[i]->contents; + + major_status = generic_gss_add_buffer_set_member(minor_status, + &ad_data, data_set); + if (GSS_ERROR(major_status)) + break; + } + } + } + + if (GSS_ERROR(major_status)) { + OM_uint32 tmp; + + generic_gss_release_buffer_set(&tmp, data_set); + } + + return major_status; +} + +OM_uint32 +gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_oid, + gss_buffer_set_t *data_set) +{ + krb5_gss_ctx_id_rec *ctx; + gss_buffer_desc rep; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + + rep.value = &ctx->krb_times.authtime; + rep.length = sizeof(ctx->krb_times.authtime); + + return generic_gss_add_buffer_set_member(minor_status, &rep, data_set); +} + +OM_uint32 +gss_krb5int_sec_context_sasl_ssf(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_gss_ctx_id_rec *ctx; + krb5_key key; + krb5_error_code code; + gss_buffer_desc ssfbuf; + unsigned int ssf; + uint8_t buf[4]; + + ctx = (krb5_gss_ctx_id_rec *)context_handle; + key = ctx->have_acceptor_subkey ? ctx->acceptor_subkey : ctx->subkey; + + code = k5_enctype_to_ssf(key->keyblock.enctype, &ssf); + if (code) + return GSS_S_FAILURE; + + store_32_be(ssf, buf); + ssfbuf.value = buf; + ssfbuf.length = sizeof(buf); + + return generic_gss_add_buffer_set_member(minor_status, &ssfbuf, data_set); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/inq_cred.c b/krb5-1.21.3/src/lib/gssapi/krb5/inq_cred.c new file mode 100644 index 00000000..0e675959 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/inq_cred.c @@ -0,0 +1,288 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2000, 2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "gssapiP_krb5.h" + +OM_uint32 KRB5_CALLCONV +krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret, + cred_usage, mechanisms) + OM_uint32 *minor_status; + gss_cred_id_t cred_handle; + gss_name_t *name; + OM_uint32 *lifetime_ret; + gss_cred_usage_t *cred_usage; + gss_OID_set *mechanisms; +{ + krb5_context context; + gss_cred_id_t defcred = GSS_C_NO_CREDENTIAL; + krb5_gss_cred_id_t cred = NULL; + krb5_error_code code; + krb5_timestamp now; + krb5_deltat lifetime; + krb5_gss_name_t ret_name; + krb5_principal princ; + gss_OID_set mechs = GSS_C_NO_OID_SET; + OM_uint32 major, tmpmin, ret; + + ret = GSS_S_FAILURE; + ret_name = NULL; + + code = krb5_gss_init_context(&context); + if (code) { + *minor_status = code; + return GSS_S_FAILURE; + } + + if (name) *name = NULL; + if (mechanisms) *mechanisms = NULL; + + /* check for default credential */ + /*SUPPRESS 29*/ + if (cred_handle == GSS_C_NO_CREDENTIAL) { + major = kg_get_defcred(minor_status, &defcred); + if (GSS_ERROR(major)) { + krb5_free_context(context); + return(major); + } + cred_handle = defcred; + } + + major = kg_cred_resolve(minor_status, context, cred_handle, GSS_C_NO_NAME); + if (GSS_ERROR(major)) { + krb5_gss_release_cred(minor_status, &defcred); + krb5_free_context(context); + return(major); + } + cred = (krb5_gss_cred_id_t)cred_handle; + + if ((code = krb5_timeofday(context, &now))) { + *minor_status = code; + ret = GSS_S_FAILURE; + goto cleanup; + } + + if (cred->expire != 0) { + lifetime = ts_interval(now, cred->expire); + if (lifetime < 0) + lifetime = 0; + } + else + lifetime = GSS_C_INDEFINITE; + + if (name) { + if (cred->name) { + code = kg_duplicate_name(context, cred->name, &ret_name); + } else if ((cred->usage == GSS_C_ACCEPT || cred->usage == GSS_C_BOTH) + && cred->keytab != NULL) { + /* This is a default acceptor cred; use a name from the keytab if + * we can. */ + code = k5_kt_get_principal(context, cred->keytab, &princ); + if (code == 0) { + code = kg_init_name(context, princ, NULL, NULL, NULL, + KG_INIT_NAME_NO_COPY, &ret_name); + if (code) + krb5_free_principal(context, princ); + } else if (code == KRB5_KT_NOTFOUND) + code = 0; + } + if (code) { + *minor_status = code; + save_error_info(*minor_status, context); + ret = GSS_S_FAILURE; + goto cleanup; + } + } + + if (mechanisms) { + if (GSS_ERROR(ret = generic_gss_create_empty_oid_set(minor_status, + &mechs)) || + GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status, + gss_mech_krb5_old, + &mechs)) || + GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status, + gss_mech_krb5, + &mechs))) { + if (ret_name) + kg_release_name(context, &ret_name); + /* *minor_status set above */ + goto cleanup; + } + } + + if (name) { + if (ret_name != NULL) + *name = (gss_name_t) ret_name; + else + *name = GSS_C_NO_NAME; + } + + if (lifetime_ret) + *lifetime_ret = lifetime; + + if (cred_usage) + *cred_usage = cred->usage; + + if (mechanisms) { + *mechanisms = mechs; + mechs = GSS_C_NO_OID_SET; + } + + *minor_status = 0; + ret = (lifetime == 0) ? GSS_S_CREDENTIALS_EXPIRED : GSS_S_COMPLETE; + +cleanup: + k5_mutex_unlock(&cred->lock); + krb5_gss_release_cred(&tmpmin, &defcred); + krb5_free_context(context); + (void)generic_gss_release_oid_set(&tmpmin, &mechs); + return ret; +} + +/* V2 interface */ +OM_uint32 KRB5_CALLCONV +krb5_gss_inquire_cred_by_mech(minor_status, cred_handle, + mech_type, name, initiator_lifetime, + acceptor_lifetime, cred_usage) + OM_uint32 *minor_status; + gss_cred_id_t cred_handle; + gss_OID mech_type; + gss_name_t *name; + OM_uint32 *initiator_lifetime; + OM_uint32 *acceptor_lifetime; + gss_cred_usage_t *cred_usage; +{ + krb5_gss_cred_id_t cred; + OM_uint32 lifetime; + OM_uint32 mstat; + + cred = (krb5_gss_cred_id_t) cred_handle; + mstat = krb5_gss_inquire_cred(minor_status, + cred_handle, + name, + &lifetime, + cred_usage, + (gss_OID_set *) NULL); + if (mstat == GSS_S_COMPLETE) { + if (cred && + ((cred->usage == GSS_C_INITIATE) || + (cred->usage == GSS_C_BOTH)) && + initiator_lifetime) + *initiator_lifetime = lifetime; + if (cred && + ((cred->usage == GSS_C_ACCEPT) || + (cred->usage == GSS_C_BOTH)) && + acceptor_lifetime) + *acceptor_lifetime = lifetime; + } + return(mstat); +} + +OM_uint32 +gss_krb5int_get_cred_impersonator(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_gss_cred_id_t cred = (krb5_gss_cred_id_t)cred_handle; + gss_buffer_desc rep = GSS_C_EMPTY_BUFFER; + krb5_context context = NULL; + char *impersonator = NULL; + krb5_error_code ret; + OM_uint32 major; + + *data_set = GSS_C_NO_BUFFER_SET; + + /* Return an empty buffer set if no impersonator is present */ + if (cred->impersonator == NULL) + return generic_gss_create_empty_buffer_set(minor_status, data_set); + + ret = krb5_gss_init_context(&context); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = krb5_unparse_name(context, cred->impersonator, &impersonator); + if (ret) { + krb5_free_context(context); + *minor_status = ret; + return GSS_S_FAILURE; + } + + rep.value = impersonator; + rep.length = strlen(impersonator); + major = generic_gss_add_buffer_set_member(minor_status, &rep, data_set); + + krb5_free_unparsed_name(context, impersonator); + krb5_free_context(context); + return major; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/inq_names.c b/krb5-1.21.3/src/lib/gssapi/krb5/inq_names.c new file mode 100644 index 00000000..b326adbb --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/inq_names.c @@ -0,0 +1,100 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/inq_names.c - Return nametypes supported by krb5 mech */ +/* + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "gssapiP_krb5.h" + +OM_uint32 KRB5_CALLCONV +krb5_gss_inquire_names_for_mech(minor_status, mechanism, name_types) + OM_uint32 *minor_status; + gss_OID mechanism; + gss_OID_set *name_types; +{ + OM_uint32 major, minor; + + /* + * We only know how to handle our own mechanism. + */ + if ((mechanism != GSS_C_NULL_OID) && + !g_OID_equal(gss_mech_krb5, mechanism) && + !g_OID_equal(gss_mech_krb5_old, mechanism) && + !g_OID_equal(gss_mech_krb5_wrong, mechanism) && + !g_OID_equal(gss_mech_iakerb, mechanism)) { + *minor_status = 0; + return(GSS_S_BAD_MECH); + } + + /* We're okay. Create an empty OID set */ + major = generic_gss_create_empty_oid_set(minor_status, name_types); + if (major == GSS_S_COMPLETE) { + /* Now add our members. */ + if ( + ((major = generic_gss_add_oid_set_member(minor_status, + gss_nt_user_name, + name_types) + ) == GSS_S_COMPLETE) && + ((major = generic_gss_add_oid_set_member(minor_status, + gss_nt_machine_uid_name, + name_types) + ) == GSS_S_COMPLETE) && + ((major = generic_gss_add_oid_set_member(minor_status, + gss_nt_string_uid_name, + name_types) + ) == GSS_S_COMPLETE) && + ((major = generic_gss_add_oid_set_member(minor_status, + gss_nt_service_name, + name_types) + ) == GSS_S_COMPLETE) && + ((major = generic_gss_add_oid_set_member(minor_status, + gss_nt_service_name_v2, + name_types) + ) == GSS_S_COMPLETE) && + ((major = generic_gss_add_oid_set_member(minor_status, + gss_nt_exported_name, + name_types) + ) == GSS_S_COMPLETE) && + ((major = generic_gss_add_oid_set_member(minor_status, + gss_nt_krb5_name, + name_types) + ) == GSS_S_COMPLETE) && + ((major = generic_gss_add_oid_set_member(minor_status, + GSS_C_NT_COMPOSITE_EXPORT, + name_types) + ) == GSS_S_COMPLETE) + ) { + major = generic_gss_add_oid_set_member(minor_status, + gss_nt_krb5_principal, + name_types); + } + + /* + * If we choked, then release the set, but don't overwrite the minor + * status with the release call. + */ + if (major != GSS_S_COMPLETE) + (void) generic_gss_release_oid_set(&minor, name_types); + } + return(major); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/k5seal.c b/krb5-1.21.3/src/lib/gssapi/krb5/k5seal.c new file mode 100644 index 00000000..99275be5 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/k5seal.c @@ -0,0 +1,392 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "gssapiP_krb5.h" + +#include + +static krb5_error_code +make_seal_token_v1 (krb5_context context, + krb5_key enc, + krb5_key seq, + uint64_t *seqnum, + int direction, + gss_buffer_t text, + gss_buffer_t token, + int signalg, + size_t cksum_size, + int sealalg, + int do_encrypt, + int toktype, + gss_OID oid) +{ + krb5_error_code code; + size_t sumlen; + char *data_ptr; + krb5_data plaind; + krb5_checksum md5cksum; + /* msglen contains the message length + * we are signing/encrypting. tmsglen + * contains the length of the message + * we plan to write out to the token. + * tlen is the length of the token + * including header. */ + unsigned int conflen=0, tmsglen, tlen, msglen; + unsigned char *t, *metadata, *checksum, *payload; + unsigned char *plain; + unsigned char pad; + krb5_keyusage sign_usage = KG_USAGE_SIGN; + struct k5buf buf; + + assert((!do_encrypt) || (toktype == KG_TOK_SEAL_MSG)); + /* create the token buffer */ + /* Do we need confounder? */ + if (do_encrypt || toktype == KG_TOK_SEAL_MSG) + conflen = kg_confounder_size(context, enc->keyblock.enctype); + else conflen = 0; + + if (toktype == KG_TOK_SEAL_MSG) { + switch (sealalg) { + case SEAL_ALG_MICROSOFT_RC4: + msglen = conflen + text->length+1; + pad = 1; + break; + default: + /* XXX knows that des block size is 8 */ + msglen = (conflen+text->length+8)&(~7); + pad = 8-(text->length%8); + } + tmsglen = msglen; + } else { + tmsglen = 0; + msglen = text->length; + pad = 0; + } + + tlen = g_token_size(oid, 14 + cksum_size + tmsglen); + t = gssalloc_malloc(tlen); + if (t == NULL) + return(ENOMEM); + k5_buf_init_fixed(&buf, t, tlen); + + /*** fill in the token */ + + g_make_token_header(&buf, oid, 14 + cksum_size + tmsglen, toktype); + metadata = k5_buf_get_space(&buf, 14); + checksum = k5_buf_get_space(&buf, cksum_size); + payload = k5_buf_get_space(&buf, tmsglen); + assert(metadata != NULL && checksum != NULL && payload != NULL); + assert(buf.len == tlen); + + /* 0..1 SIGN_ALG */ + store_16_le(signalg, &metadata[0]); + + /* 2..3 SEAL_ALG or Filler */ + if ((toktype == KG_TOK_SEAL_MSG) && do_encrypt) { + store_16_le(sealalg, &metadata[2]); + } else { + /* No seal */ + metadata[2] = 0xFF; + metadata[3] = 0xFF; + } + + /* 4..5 Filler */ + metadata[4] = 0xFF; + metadata[5] = 0xFF; + + /* pad the plaintext, encrypt if needed, and stick it in the token */ + + /* initialize the the checksum */ + switch (signalg) { + case SGN_ALG_HMAC_SHA1_DES3_KD: + md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; + break; + case SGN_ALG_HMAC_MD5: + md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; + if (toktype != KG_TOK_SEAL_MSG) + sign_usage = 15; + break; + default: + abort (); + } + + code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen); + if (code) { + gssalloc_free(t); + return(code); + } + md5cksum.length = sumlen; + + + if ((plain = (unsigned char *) xmalloc(msglen ? msglen : 1)) == NULL) { + gssalloc_free(t); + return(ENOMEM); + } + + if (conflen) { + if ((code = kg_make_confounder(context, enc->keyblock.enctype, + plain))) { + xfree(plain); + gssalloc_free(t); + return(code); + } + } + + memcpy(plain+conflen, text->value, text->length); + if (pad) memset(plain+conflen+text->length, pad, pad); + + /* compute the checksum */ + + /* 8 = head of token body as specified by mech spec */ + if (! (data_ptr = xmalloc(8 + msglen))) { + xfree(plain); + gssalloc_free(t); + return(ENOMEM); + } + /* Checksum over the token ID, metadata bytes, and plaintext. */ + memcpy(data_ptr, metadata - 2, 8); + memcpy(data_ptr + 8, plain, msglen); + plaind.length = 8 + msglen; + plaind.data = data_ptr; + code = krb5_k_make_checksum(context, md5cksum.checksum_type, seq, + sign_usage, &plaind, &md5cksum); + xfree(data_ptr); + + if (code) { + xfree(plain); + gssalloc_free(t); + return(code); + } + switch(signalg) { + case SGN_ALG_HMAC_SHA1_DES3_KD: + /* + * Using key derivation, the call to krb5_c_make_checksum + * already dealt with encrypting. + */ + if (md5cksum.length != cksum_size) + abort (); + memcpy(checksum, md5cksum.contents, md5cksum.length); + break; + case SGN_ALG_HMAC_MD5: + memcpy(checksum, md5cksum.contents, cksum_size); + break; + } + + krb5_free_checksum_contents(context, &md5cksum); + + /* create the seq_num */ + + code = kg_make_seq_num(context, seq, direction?0:0xff, + (krb5_ui_4)*seqnum, checksum, metadata + 6); + if (code) { + xfree (plain); + gssalloc_free(t); + return(code); + } + + if (do_encrypt) { + switch(sealalg) { + case SEAL_ALG_MICROSOFT_RC4: + { + unsigned char bigend_seqnum[4]; + krb5_keyblock *enc_key; + int i; + store_32_be(*seqnum, bigend_seqnum); + code = krb5_k_key_keyblock(context, enc, &enc_key); + if (code) + { + xfree(plain); + gssalloc_free(t); + return(code); + } + assert (enc_key->length == 16); + for (i = 0; i <= 15; i++) + ((char *) enc_key->contents)[i] ^=0xf0; + code = kg_arcfour_docrypt(enc_key, 0, bigend_seqnum, 4, plain, + tmsglen, payload); + krb5_free_keyblock (context, enc_key); + if (code) + { + xfree(plain); + gssalloc_free(t); + return(code); + } + } + break; + default: + code = kg_encrypt(context, enc, KG_USAGE_SEAL, NULL, plain, + payload, tmsglen); + if (code) { + xfree(plain); + gssalloc_free(t); + return(code); + } + } + }else { + if (tmsglen) + memcpy(payload, plain, tmsglen); + } + xfree(plain); + + + /* that's it. return the token */ + + (*seqnum)++; + *seqnum &= 0xffffffffL; + + token->length = tlen; + token->value = (void *) t; + + return(0); +} + +/* if signonly is true, ignore conf_req, conf_state, + and do not encode the ENC_TYPE, MSG_LENGTH, or MSG_TEXT fields */ + +OM_uint32 +kg_seal(minor_status, context_handle, conf_req_flag, qop_req, + input_message_buffer, conf_state, output_message_buffer, toktype) + OM_uint32 *minor_status; + gss_ctx_id_t context_handle; + int conf_req_flag; + gss_qop_t qop_req; + gss_buffer_t input_message_buffer; + int *conf_state; + gss_buffer_t output_message_buffer; + int toktype; +{ + krb5_gss_ctx_id_rec *ctx; + krb5_error_code code; + krb5_context context; + + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + + /* Only default qop or matching established cryptosystem is allowed. + + There are NO EXTENSIONS to this set for AES and friends! The + new spec says "just use 0". The old spec plus extensions would + actually allow for certain non-zero values. Fix this to handle + them later. */ + if (qop_req != 0) { + *minor_status = (OM_uint32) G_UNKNOWN_QOP; + return GSS_S_BAD_QOP; + } + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + + if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } + + context = ctx->k5_context; + switch (ctx->proto) + { + case 0: + code = make_seal_token_v1(context, ctx->enc, ctx->seq, + &ctx->seq_send, ctx->initiate, + input_message_buffer, output_message_buffer, + ctx->signalg, ctx->cksum_size, ctx->sealalg, + conf_req_flag, toktype, ctx->mech_used); + break; + case 1: + code = gss_krb5int_make_seal_token_v3(context, ctx, + input_message_buffer, + output_message_buffer, + conf_req_flag, toktype); + break; + default: + code = G_UNKNOWN_QOP; /* XXX */ + break; + } + + if (code) { + *minor_status = code; + save_error_info(*minor_status, context); + return(GSS_S_FAILURE); + } + + if (conf_state) + *conf_state = conf_req_flag; + + *minor_status = 0; + return(GSS_S_COMPLETE); +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_wrap(minor_status, context_handle, conf_req_flag, + qop_req, input_message_buffer, conf_state, + output_message_buffer) + OM_uint32 *minor_status; + gss_ctx_id_t context_handle; + int conf_req_flag; + gss_qop_t qop_req; + gss_buffer_t input_message_buffer; + int *conf_state; + gss_buffer_t output_message_buffer; +{ + return(kg_seal(minor_status, context_handle, conf_req_flag, + qop_req, input_message_buffer, conf_state, + output_message_buffer, KG_TOK_WRAP_MSG)); +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_get_mic(minor_status, context_handle, qop_req, + message_buffer, message_token) + OM_uint32 *minor_status; + gss_ctx_id_t context_handle; + gss_qop_t qop_req; + gss_buffer_t message_buffer; + gss_buffer_t message_token; +{ + return(kg_seal(minor_status, context_handle, 0, + qop_req, message_buffer, NULL, + message_token, KG_TOK_MIC_MSG)); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/k5sealiov.c b/krb5-1.21.3/src/lib/gssapi/krb5/k5sealiov.c new file mode 100644 index 00000000..7bf7609a --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/k5sealiov.c @@ -0,0 +1,542 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/k5sealiov.c */ +/* + * Copyright 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "gssapiP_krb5.h" + +static krb5_error_code +make_seal_token_v1_iov(krb5_context context, + krb5_gss_ctx_id_rec *ctx, + int conf_req_flag, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + krb5_error_code code = 0; + gss_iov_buffer_t header; + gss_iov_buffer_t padding; + gss_iov_buffer_t trailer; + krb5_checksum md5cksum; + krb5_checksum cksum; + size_t k5_headerlen = 0, k5_trailerlen = 0; + size_t data_length = 0, assoc_data_length = 0; + size_t tmsglen = 0, cnflen = 0, tlen; + uint8_t *metadata, *checksum, *confounder; + krb5_keyusage sign_usage = KG_USAGE_SIGN; + struct k5buf buf; + + md5cksum.length = cksum.length = 0; + md5cksum.contents = cksum.contents = NULL; + + header = kg_locate_header_iov(iov, iov_count, toktype); + if (header == NULL) + return EINVAL; + + padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + if (padding == NULL && toktype == KG_TOK_WRAP_MSG && + (ctx->gss_flags & GSS_C_DCE_STYLE) == 0) + return EINVAL; + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + if (trailer != NULL) + trailer->buffer.length = 0; + + /* Determine confounder length */ + if (toktype == KG_TOK_WRAP_MSG) { + size_t k5_padlen = (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) ? 1 : 8; + size_t gss_padlen; + size_t conf_data_length; + + cnflen = kg_confounder_size(context, ctx->enc->keyblock.enctype); + + kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length); + conf_data_length = cnflen + data_length - assoc_data_length; + + if (k5_padlen == 1) + gss_padlen = 1; /* one byte to indicate one byte of padding */ + else + gss_padlen = k5_padlen - (conf_data_length % k5_padlen); + + if (ctx->gss_flags & GSS_C_DCE_STYLE) { + /* DCE will pad the actual data itself; padding buffer optional and will be zeroed */ + gss_padlen = 0; + + if (conf_data_length % k5_padlen) + code = KRB5_BAD_MSIZE; + } else if (padding->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) { + code = kg_allocate_iov(padding, gss_padlen); + } else if (padding->buffer.length < gss_padlen) { + code = KRB5_BAD_MSIZE; + } + if (code != 0) + goto cleanup; + + /* Initialize padding buffer to pad itself */ + if (padding != NULL) { + padding->buffer.length = gss_padlen; + memset(padding->buffer.value, (int)gss_padlen, gss_padlen); + } + + if (ctx->gss_flags & GSS_C_DCE_STYLE) + tmsglen = cnflen; /* confounder length */ + else + tmsglen = conf_data_length + padding->buffer.length; + } + + /* Determine token size */ + tlen = g_token_size(ctx->mech_used, 14 + ctx->cksum_size + tmsglen); + + k5_headerlen = cnflen + tlen - tmsglen; + + if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) + code = kg_allocate_iov(header, k5_headerlen); + else if (header->buffer.length < k5_headerlen) + code = KRB5_BAD_MSIZE; + if (code != 0) + goto cleanup; + + header->buffer.length = k5_headerlen; + + k5_buf_init_fixed(&buf, header->buffer.value, k5_headerlen); + g_make_token_header(&buf, ctx->mech_used, 14 + ctx->cksum_size + tmsglen, + toktype); + metadata = k5_buf_get_space(&buf, 14); + checksum = k5_buf_get_space(&buf, ctx->cksum_size); + assert(metadata != NULL && checksum != NULL); + + /* 0..1 SIGN_ALG */ + store_16_le(ctx->signalg, &metadata[0]); + + /* 2..3 SEAL_ALG or Filler */ + if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) { + store_16_le(ctx->sealalg, &metadata[2]); + } else { + /* No seal */ + metadata[2] = 0xFF; + metadata[3] = 0xFF; + } + + /* 4..5 Filler */ + metadata[4] = 0xFF; + metadata[5] = 0xFF; + + /* pad the plaintext, encrypt if needed, and stick it in the token */ + + /* initialize the checksum */ + switch (ctx->signalg) { + case SGN_ALG_HMAC_SHA1_DES3_KD: + md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; + break; + case SGN_ALG_HMAC_MD5: + md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; + if (toktype != KG_TOK_WRAP_MSG) + sign_usage = 15; + break; + default: + abort (); + } + + code = krb5_c_checksum_length(context, md5cksum.checksum_type, &k5_trailerlen); + if (code != 0) + goto cleanup; + md5cksum.length = k5_trailerlen; + + if (k5_headerlen != 0 && toktype == KG_TOK_WRAP_MSG) { + confounder = k5_buf_get_space(&buf, cnflen); + assert(confounder != NULL); + code = kg_make_confounder(context, ctx->enc->keyblock.enctype, + confounder); + if (code != 0) + goto cleanup; + } + + /* compute the checksum */ + code = kg_make_checksum_iov_v1(context, md5cksum.checksum_type, + ctx->cksum_size, ctx->seq, ctx->enc, + sign_usage, iov, iov_count, toktype, + &md5cksum); + if (code != 0) + goto cleanup; + + switch (ctx->signalg) { + case SGN_ALG_HMAC_SHA1_DES3_KD: + assert(md5cksum.length == ctx->cksum_size); + memcpy(checksum, md5cksum.contents, md5cksum.length); + break; + case SGN_ALG_HMAC_MD5: + memcpy(checksum, md5cksum.contents, ctx->cksum_size); + break; + } + + /* create the seq_num */ + code = kg_make_seq_num(context, ctx->seq, ctx->initiate ? 0 : 0xFF, + (OM_uint32)ctx->seq_send, checksum, metadata + 6); + if (code != 0) + goto cleanup; + + if (conf_req_flag) { + if (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) { + unsigned char bigend_seqnum[4]; + krb5_keyblock *enc_key; + size_t i; + + store_32_be(ctx->seq_send, bigend_seqnum); + + code = krb5_k_key_keyblock(context, ctx->enc, &enc_key); + if (code != 0) + goto cleanup; + + assert(enc_key->length == 16); + + for (i = 0; i < enc_key->length; i++) + ((char *)enc_key->contents)[i] ^= 0xF0; + + code = kg_arcfour_docrypt_iov(context, enc_key, 0, + bigend_seqnum, 4, + iov, iov_count); + krb5_free_keyblock(context, enc_key); + } else { + code = kg_encrypt_iov(context, ctx->proto, + ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0), + 0 /*EC*/, 0 /*RRC*/, + ctx->enc, KG_USAGE_SEAL, NULL, + iov, iov_count); + } + if (code != 0) + goto cleanup; + } + + ctx->seq_send++; + ctx->seq_send &= 0xFFFFFFFFL; + + code = 0; + + if (conf_state != NULL) + *conf_state = conf_req_flag; + +cleanup: + if (code != 0) + kg_release_iov(iov, iov_count); + krb5_free_checksum_contents(context, &md5cksum); + + return code; +} + +OM_uint32 +kg_seal_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + krb5_gss_ctx_id_rec *ctx; + krb5_error_code code; + krb5_context context; + + if (qop_req != 0) { + *minor_status = (OM_uint32)G_UNKNOWN_QOP; + return GSS_S_BAD_QOP; + } + + ctx = (krb5_gss_ctx_id_rec *)context_handle; + if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + if (conf_req_flag && kg_integ_only_iov(iov, iov_count)) { + /* may be more sensible to return an error here */ + conf_req_flag = FALSE; + } + + context = ctx->k5_context; + switch (ctx->proto) { + case 0: + code = make_seal_token_v1_iov(context, ctx, conf_req_flag, + conf_state, iov, iov_count, toktype); + break; + case 1: + code = gss_krb5int_make_seal_token_v3_iov(context, ctx, conf_req_flag, + conf_state, iov, iov_count, toktype); + break; + default: + code = G_UNKNOWN_QOP; + break; + } + + if (code != 0) { + *minor_status = code; + save_error_info(*minor_status, context); + return GSS_S_FAILURE; + } + + *minor_status = 0; + + return GSS_S_COMPLETE; +} + +#define INIT_IOV_DATA(_iov) do { (_iov)->buffer.value = NULL; \ + (_iov)->buffer.length = 0; } \ + while (0) + +OM_uint32 +kg_seal_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + krb5_gss_ctx_id_rec *ctx; + gss_iov_buffer_t header, trailer, padding; + size_t data_length, assoc_data_length; + size_t gss_headerlen, gss_padlen, gss_trailerlen; + unsigned int k5_headerlen = 0, k5_trailerlen = 0, k5_padlen = 0; + krb5_error_code code; + krb5_context context; + int dce_or_mic; + + if (qop_req != GSS_C_QOP_DEFAULT) { + *minor_status = (OM_uint32)G_UNKNOWN_QOP; + return GSS_S_BAD_QOP; + } + + ctx = (krb5_gss_ctx_id_rec *)context_handle; + if (!ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + header = kg_locate_header_iov(iov, iov_count, toktype); + if (header == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + INIT_IOV_DATA(header); + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + if (trailer != NULL) { + INIT_IOV_DATA(trailer); + } + + /* MIC tokens and DCE-style wrap tokens have similar length considerations: + * no padding, and the framing surrounds the header only, not the data. */ + dce_or_mic = ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0 || + toktype == KG_TOK_MIC_MSG); + + /* For CFX, EC is used instead of padding, and is placed in header or trailer */ + padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + if (padding == NULL) { + if (conf_req_flag && ctx->proto == 0 && !dce_or_mic) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + } else { + INIT_IOV_DATA(padding); + } + + kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length); + + if (conf_req_flag && kg_integ_only_iov(iov, iov_count)) + conf_req_flag = FALSE; + + context = ctx->k5_context; + + gss_headerlen = gss_padlen = gss_trailerlen = 0; + + if (ctx->proto == 1) { + krb5_key key; + krb5_enctype enctype; + size_t ec; + + key = (ctx->have_acceptor_subkey) ? ctx->acceptor_subkey : ctx->subkey; + enctype = key->keyblock.enctype; + + code = krb5_c_crypto_length(context, enctype, + conf_req_flag ? + KRB5_CRYPTO_TYPE_TRAILER : KRB5_CRYPTO_TYPE_CHECKSUM, + &k5_trailerlen); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + if (conf_req_flag) { + code = krb5_c_crypto_length(context, enctype, KRB5_CRYPTO_TYPE_HEADER, &k5_headerlen); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + } + + gss_headerlen = 16; /* Header */ + if (conf_req_flag) { + gss_headerlen += k5_headerlen; /* Kerb-Header */ + gss_trailerlen = 16 /* E(Header) */ + k5_trailerlen; /* Kerb-Trailer */ + + code = krb5_c_padding_length(context, enctype, + data_length - assoc_data_length + 16 /* E(Header) */, &k5_padlen); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + if (k5_padlen == 0 && dce_or_mic) { + /* Windows rejects AEAD tokens with non-zero EC */ + code = krb5_c_block_size(context, enctype, &ec); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + } else + ec = k5_padlen; + + gss_trailerlen += ec; + } else { + gss_trailerlen = k5_trailerlen; /* Kerb-Checksum */ + } + } else if (!dce_or_mic) { + k5_padlen = (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) ? 1 : 8; + + if (k5_padlen == 1) + gss_padlen = 1; + else + gss_padlen = k5_padlen - ((data_length - assoc_data_length) % k5_padlen); + } + + data_length += gss_padlen; + + if (ctx->proto == 0) { + /* Header | Checksum | Confounder | Data | Pad */ + size_t data_size; + + k5_headerlen = kg_confounder_size(context, ctx->enc->keyblock.enctype); + + data_size = 14 /* Header */ + ctx->cksum_size + k5_headerlen; + + if (!dce_or_mic) + data_size += data_length; + + gss_headerlen = g_token_size(ctx->mech_used, data_size); + + /* g_token_size() will include data_size as well as the overhead, so + * subtract data_length just to get the overhead (ie. token size) */ + if (!dce_or_mic) + gss_headerlen -= data_length; + } + + if (minor_status != NULL) + *minor_status = 0; + + if (trailer == NULL) + gss_headerlen += gss_trailerlen; + else + trailer->buffer.length = gss_trailerlen; + + assert(gss_padlen == 0 || padding != NULL); + + if (padding != NULL) + padding->buffer.length = gss_padlen; + + header->buffer.length = gss_headerlen; + + if (conf_state != NULL) + *conf_state = conf_req_flag; + + return GSS_S_COMPLETE; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_wrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + + major_status = kg_seal_iov(minor_status, context_handle, conf_req_flag, + qop_req, conf_state, + iov, iov_count, KG_TOK_WRAP_MSG); + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_wrap_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + + major_status = kg_seal_iov_length(minor_status, context_handle, + conf_req_flag, qop_req, conf_state, iov, + iov_count, KG_TOK_WRAP_MSG); + return major_status; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_get_mic_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t qop_req, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + + major_status = kg_seal_iov(minor_status, context_handle, FALSE, + qop_req, NULL, + iov, iov_count, KG_TOK_MIC_MSG); + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_get_mic_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t qop_req, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + + major_status = kg_seal_iov_length(minor_status, context_handle, FALSE, + qop_req, NULL, iov, iov_count, + KG_TOK_MIC_MSG); + return major_status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/k5sealv3.c b/krb5-1.21.3/src/lib/gssapi/krb5/k5sealv3.c new file mode 100644 index 00000000..1fcbdfbb --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/k5sealv3.c @@ -0,0 +1,522 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/k5sealv3.c */ +/* + * Copyright 2003,2004,2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* draft-ietf-krb-wg-gssapi-cfx-05 */ + +#include "k5-int.h" +#include "gssapiP_krb5.h" + +int +gss_krb5int_rotate_left (void *ptr, size_t bufsiz, size_t rc) +{ + /* Optimize for receiving. After some debugging is done, the MIT + implementation won't do any rotates on sending, and while + debugging, they'll be randomly chosen. + + Return 1 for success, 0 for failure (ENOMEM). */ + void *tbuf; + + if (bufsiz == 0) + return 1; + rc = rc % bufsiz; + if (rc == 0) + return 1; + + tbuf = malloc(rc); + if (tbuf == 0) + return 0; + memcpy(tbuf, ptr, rc); + memmove(ptr, (char *)ptr + rc, bufsiz - rc); + memcpy((char *)ptr + bufsiz - rc, tbuf, rc); + free(tbuf); + return 1; +} + +static const gss_buffer_desc empty_message = { 0, 0 }; + +krb5_error_code +gss_krb5int_make_seal_token_v3 (krb5_context context, + krb5_gss_ctx_id_rec *ctx, + const gss_buffer_desc * message, + gss_buffer_t token, + int conf_req_flag, int toktype) +{ + size_t bufsize = 16; + unsigned char *outbuf = 0; + krb5_error_code err; + int key_usage; + unsigned char acceptor_flag; + const gss_buffer_desc *message2 = message; +#ifdef CFX_EXERCISE + size_t rrc; +#endif + size_t ec; + unsigned short tok_id; + krb5_checksum sum; + krb5_key key; + krb5_cksumtype cksumtype; + + acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR; + key_usage = (toktype == KG_TOK_WRAP_MSG + ? (ctx->initiate + ? KG_USAGE_INITIATOR_SEAL + : KG_USAGE_ACCEPTOR_SEAL) + : (ctx->initiate + ? KG_USAGE_INITIATOR_SIGN + : KG_USAGE_ACCEPTOR_SIGN)); + if (ctx->have_acceptor_subkey) { + key = ctx->acceptor_subkey; + cksumtype = ctx->acceptor_subkey_cksumtype; + } else { + key = ctx->subkey; + cksumtype = ctx->cksumtype; + } + assert(key != NULL); + +#ifdef CFX_EXERCISE + { + static int initialized = 0; + if (!initialized) { + srand(time(0)); + initialized = 1; + } + } +#endif + + if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) { + krb5_data plain; + krb5_enc_data cipher; + size_t ec_max; + size_t encrypt_size; + + /* 300: Adds some slop. */ + if (SIZE_MAX - 300 < message->length) + return ENOMEM; + ec_max = SIZE_MAX - message->length - 300; + if (ec_max > 0xffff) + ec_max = 0xffff; +#ifdef CFX_EXERCISE + /* For testing only. For performance, always set ec = 0. */ + ec = ec_max & rand(); +#else + ec = 0; +#endif + err = alloc_data(&plain, message->length + 16 + ec); + if (err) + return err; + + /* Get size of ciphertext. */ + encrypt_size = krb5_encrypt_size(plain.length, key->keyblock.enctype); + if (encrypt_size > SIZE_MAX / 2) { + err = ENOMEM; + goto error; + } + bufsize = 16 + encrypt_size; + /* Allocate space for header plus encrypted data. */ + outbuf = gssalloc_malloc(bufsize); + if (outbuf == NULL) { + free(plain.data); + return ENOMEM; + } + + /* TOK_ID */ + store_16_be(KG2_TOK_WRAP_MSG, outbuf); + /* flags */ + outbuf[2] = (acceptor_flag | FLAG_WRAP_CONFIDENTIAL | + (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0)); + /* filler */ + outbuf[3] = 0xff; + /* EC */ + store_16_be(ec, outbuf+4); + /* RRC */ + store_16_be(0, outbuf+6); + store_64_be(ctx->seq_send, outbuf+8); + + memcpy(plain.data, message->value, message->length); + if (ec != 0) + memset(plain.data + message->length, 'x', ec); + memcpy(plain.data + message->length + ec, outbuf, 16); + + cipher.ciphertext.data = (char *)outbuf + 16; + cipher.ciphertext.length = bufsize - 16; + cipher.enctype = key->keyblock.enctype; + err = krb5_k_encrypt(context, key, key_usage, 0, &plain, &cipher); + zap(plain.data, plain.length); + free(plain.data); + plain.data = 0; + if (err) + goto error; + + /* Now that we know we're returning a valid token.... */ + ctx->seq_send++; + +#ifdef CFX_EXERCISE + rrc = rand() & 0xffff; + if (gss_krb5int_rotate_left(outbuf+16, bufsize-16, + (bufsize-16) - (rrc % (bufsize - 16)))) + store_16_be(rrc, outbuf+6); + /* If the rotate fails, don't worry about it. */ +#endif + } else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) { + krb5_data plain; + size_t cksumsize; + + /* Here, message is the application-supplied data; message2 is + what goes into the output token. They may be the same, or + message2 may be empty (for MIC). */ + + tok_id = KG2_TOK_WRAP_MSG; + + wrap_with_checksum: + err = alloc_data(&plain, message->length + 16); + if (err) + return err; + + err = krb5_c_checksum_length(context, cksumtype, &cksumsize); + if (err) + goto error; + + assert(cksumsize <= 0xffff); + + bufsize = 16 + message2->length + cksumsize; + outbuf = gssalloc_malloc(bufsize); + if (outbuf == NULL) { + free(plain.data); + plain.data = 0; + err = ENOMEM; + goto error; + } + + /* TOK_ID */ + store_16_be(tok_id, outbuf); + /* flags */ + outbuf[2] = (acceptor_flag + | (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0)); + /* filler */ + outbuf[3] = 0xff; + if (toktype == KG_TOK_WRAP_MSG) { + /* Use 0 for checksum calculation, substitute + checksum length later. */ + /* EC */ + store_16_be(0, outbuf+4); + /* RRC */ + store_16_be(0, outbuf+6); + } else { + /* MIC and DEL store 0xFF in EC and RRC. */ + store_16_be(0xffff, outbuf+4); + store_16_be(0xffff, outbuf+6); + } + store_64_be(ctx->seq_send, outbuf+8); + + memcpy(plain.data, message->value, message->length); + memcpy(plain.data + message->length, outbuf, 16); + + /* Fill in the output token -- data contents, if any, and + space for the checksum. */ + if (message2->length) + memcpy(outbuf + 16, message2->value, message2->length); + + sum.contents = outbuf + 16 + message2->length; + sum.length = cksumsize; + + err = krb5_k_make_checksum(context, cksumtype, key, + key_usage, &plain, &sum); + zap(plain.data, plain.length); + free(plain.data); + plain.data = 0; + if (err) { + zap(outbuf,bufsize); + goto error; + } + if (sum.length != cksumsize) + abort(); + memcpy(outbuf + 16 + message2->length, sum.contents, cksumsize); + krb5_free_checksum_contents(context, &sum); + sum.contents = 0; + /* Now that we know we're actually generating the token... */ + ctx->seq_send++; + + if (toktype == KG_TOK_WRAP_MSG) { +#ifdef CFX_EXERCISE + rrc = rand() & 0xffff; + /* If the rotate fails, don't worry about it. */ + if (gss_krb5int_rotate_left(outbuf+16, bufsize-16, + (bufsize-16) - (rrc % (bufsize - 16)))) + store_16_be(rrc, outbuf+6); +#endif + /* Fix up EC field. */ + store_16_be(cksumsize, outbuf+4); + } else { + store_16_be(0xffff, outbuf+6); + } + } else if (toktype == KG_TOK_MIC_MSG) { + tok_id = KG2_TOK_MIC_MSG; + message2 = &empty_message; + goto wrap_with_checksum; + } else if (toktype == KG_TOK_DEL_CTX) { + tok_id = KG2_TOK_DEL_CTX; + message = message2 = &empty_message; + goto wrap_with_checksum; + } else + abort(); + + token->value = outbuf; + token->length = bufsize; + return 0; + +error: + gssalloc_free(outbuf); + token->value = NULL; + token->length = 0; + return err; +} + +/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX + conf_state is only valid if SEAL. */ + +OM_uint32 +gss_krb5int_unseal_token_v3(krb5_context *contextptr, + OM_uint32 *minor_status, + krb5_gss_ctx_id_rec *ctx, + unsigned char *ptr, unsigned int bodysize, + gss_buffer_t message_buffer, + int *conf_state, gss_qop_t *qop_state, int toktype) +{ + krb5_context context = *contextptr; + krb5_data plain = empty_data(); + uint64_t seqnum; + size_t ec, rrc; + int key_usage; + unsigned char acceptor_flag; + krb5_checksum sum; + krb5_error_code err; + krb5_boolean valid; + krb5_key key; + krb5_cksumtype cksumtype; + + if (qop_state) + *qop_state = GSS_C_QOP_DEFAULT; + + acceptor_flag = ctx->initiate ? FLAG_SENDER_IS_ACCEPTOR : 0; + key_usage = (toktype == KG_TOK_WRAP_MSG + ? (!ctx->initiate + ? KG_USAGE_INITIATOR_SEAL + : KG_USAGE_ACCEPTOR_SEAL) + : (!ctx->initiate + ? KG_USAGE_INITIATOR_SIGN + : KG_USAGE_ACCEPTOR_SIGN)); + + /* Oops. I wrote this code assuming ptr would be at the start of + the token header. */ + ptr -= 2; + bodysize += 2; + + if (bodysize < 16) { + defective: + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + if ((ptr[2] & FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) { + *minor_status = (OM_uint32)G_BAD_DIRECTION; + return GSS_S_BAD_SIG; + } + + /* Two things to note here. + + First, we can't really enforce the use of the acceptor's subkey, + if we're the acceptor; the initiator may have sent messages + before getting the subkey. We could probably enforce it if + we're the initiator. + + Second, if someone tweaks the code to not set the flag telling + the krb5 library to generate a new subkey in the AP-REP + message, the MIT library may include a subkey anyways -- + namely, a copy of the AP-REQ subkey, if it was provided. So + the initiator may think we wanted a subkey, and set the flag, + even though we weren't trying to set the subkey. The "other" + key, the one not asserted by the acceptor, will have the same + value in that case, though, so we can just ignore the flag. */ + if (ctx->have_acceptor_subkey && (ptr[2] & FLAG_ACCEPTOR_SUBKEY)) { + key = ctx->acceptor_subkey; + cksumtype = ctx->acceptor_subkey_cksumtype; + } else { + key = ctx->subkey; + cksumtype = ctx->cksumtype; + } + assert(key != NULL); + + if (toktype == KG_TOK_WRAP_MSG) { + if (load_16_be(ptr) != KG2_TOK_WRAP_MSG) + goto defective; + if (ptr[3] != 0xff) + goto defective; + ec = load_16_be(ptr+4); + rrc = load_16_be(ptr+6); + seqnum = load_64_be(ptr+8); + if (!gss_krb5int_rotate_left(ptr+16, bodysize-16, rrc)) { + no_mem: + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + if (ptr[2] & FLAG_WRAP_CONFIDENTIAL) { + /* confidentiality */ + krb5_enc_data cipher; + unsigned char *althdr; + + if (conf_state) + *conf_state = 1; + /* Do we have no decrypt_size function? + + For all current cryptosystems, the ciphertext size will + be larger than the plaintext size. */ + cipher.enctype = key->keyblock.enctype; + cipher.ciphertext.length = bodysize - 16; + cipher.ciphertext.data = (char *)ptr + 16; + plain.length = bodysize - 16; + plain.data = gssalloc_malloc(plain.length); + if (plain.data == NULL) + goto no_mem; + err = krb5_k_decrypt(context, key, key_usage, 0, + &cipher, &plain); + if (err) { + gssalloc_free(plain.data); + goto error; + } + /* Don't use bodysize here! Use the fact that + cipher.ciphertext.length has been adjusted to the + correct length. */ + if (plain.length < 16 + ec) { + free(plain.data); + goto defective; + } + althdr = (unsigned char *)plain.data + plain.length - 16; + if (load_16_be(althdr) != KG2_TOK_WRAP_MSG + || althdr[2] != ptr[2] + || althdr[3] != ptr[3] + || load_16_be(althdr+4) != ec + || memcmp(althdr+8, ptr+8, 8)) { + free(plain.data); + goto defective; + } + message_buffer->value = plain.data; + message_buffer->length = plain.length - ec - 16; + if(message_buffer->length == 0) { + gssalloc_free(message_buffer->value); + message_buffer->value = NULL; + } + } else { + size_t cksumsize; + + err = krb5_c_checksum_length(context, cksumtype, &cksumsize); + if (err) + goto error; + + /* no confidentiality */ + if (conf_state) + *conf_state = 0; + if (ec + 16 < ec) + /* overflow check */ + goto defective; + if (ec + 16 > bodysize) + goto defective; + /* We have: header | msg | cksum. + We need cksum(msg | header). + Rotate the first two. */ + store_16_be(0, ptr+4); + store_16_be(0, ptr+6); + plain = make_data(ptr, bodysize - ec); + if (!gss_krb5int_rotate_left(ptr, bodysize-ec, 16)) + goto no_mem; + sum.length = ec; + if (sum.length != cksumsize) { + *minor_status = 0; + return GSS_S_BAD_SIG; + } + sum.contents = ptr+bodysize-ec; + sum.checksum_type = cksumtype; + err = krb5_k_verify_checksum(context, key, key_usage, + &plain, &sum, &valid); + if (err) + goto error; + if (!valid) { + *minor_status = 0; + return GSS_S_BAD_SIG; + } + message_buffer->length = plain.length - 16; + message_buffer->value = gssalloc_malloc(message_buffer->length); + if (message_buffer->value == NULL) + goto no_mem; + memcpy(message_buffer->value, plain.data, message_buffer->length); + } + err = g_seqstate_check(ctx->seqstate, seqnum); + *minor_status = 0; + return err; + } else if (toktype == KG_TOK_MIC_MSG) { + /* wrap token, no confidentiality */ + if (load_16_be(ptr) != KG2_TOK_MIC_MSG) + goto defective; + verify_mic_1: + if (ptr[3] != 0xff) + goto defective; + if (load_32_be(ptr+4) != 0xffffffffL) + goto defective; + seqnum = load_64_be(ptr+8); + plain.length = message_buffer->length + 16; + plain.data = malloc(plain.length); + if (plain.data == NULL) + goto no_mem; + if (message_buffer->length) + memcpy(plain.data, message_buffer->value, message_buffer->length); + memcpy(plain.data + message_buffer->length, ptr, 16); + sum.length = bodysize - 16; + sum.contents = ptr + 16; + sum.checksum_type = cksumtype; + err = krb5_k_verify_checksum(context, key, key_usage, + &plain, &sum, &valid); + free(plain.data); + plain.data = NULL; + if (err) { + error: + *minor_status = err; + save_error_info(*minor_status, context); + return GSS_S_BAD_SIG; /* XXX */ + } + if (!valid) { + *minor_status = 0; + return GSS_S_BAD_SIG; + } + err = g_seqstate_check(ctx->seqstate, seqnum); + *minor_status = 0; + return err; + } else if (toktype == KG_TOK_DEL_CTX) { + if (load_16_be(ptr) != KG2_TOK_DEL_CTX) + goto defective; + message_buffer = (gss_buffer_t)&empty_message; + goto verify_mic_1; + } else { + goto defective; + } +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/k5sealv3iov.c b/krb5-1.21.3/src/lib/gssapi/krb5/k5sealv3iov.c new file mode 100644 index 00000000..f8e90c35 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/k5sealv3iov.c @@ -0,0 +1,468 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/k5sealv3iov.c */ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "gssapiP_krb5.h" + +krb5_error_code +gss_krb5int_make_seal_token_v3_iov(krb5_context context, + krb5_gss_ctx_id_rec *ctx, + int conf_req_flag, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + krb5_error_code code = 0; + gss_iov_buffer_t header; + gss_iov_buffer_t padding; + gss_iov_buffer_t trailer; + unsigned char acceptor_flag; + unsigned short tok_id; + unsigned char *outbuf = NULL; + unsigned char *tbuf = NULL; + int key_usage; + size_t rrc = 0; + unsigned int gss_headerlen, gss_trailerlen; + krb5_key key; + krb5_cksumtype cksumtype; + size_t data_length, assoc_data_length; + + assert(ctx->proto == 1); + + acceptor_flag = ctx->initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR; + key_usage = (toktype == KG_TOK_WRAP_MSG + ? (ctx->initiate + ? KG_USAGE_INITIATOR_SEAL + : KG_USAGE_ACCEPTOR_SEAL) + : (ctx->initiate + ? KG_USAGE_INITIATOR_SIGN + : KG_USAGE_ACCEPTOR_SIGN)); + if (ctx->have_acceptor_subkey) { + key = ctx->acceptor_subkey; + cksumtype = ctx->acceptor_subkey_cksumtype; + } else { + key = ctx->subkey; + cksumtype = ctx->cksumtype; + } + assert(key != NULL); + assert(cksumtype != 0); + + kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length); + + header = kg_locate_header_iov(iov, iov_count, toktype); + if (header == NULL) + return EINVAL; + + padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + if (padding != NULL) + padding->buffer.length = 0; + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + + if (toktype == KG_TOK_WRAP_MSG && conf_req_flag) { + unsigned int k5_headerlen, k5_trailerlen, k5_padlen; + size_t ec = 0; + size_t conf_data_length = data_length - assoc_data_length; + + code = krb5_c_crypto_length(context, key->keyblock.enctype, + KRB5_CRYPTO_TYPE_HEADER, &k5_headerlen); + if (code != 0) + goto cleanup; + + code = krb5_c_padding_length(context, key->keyblock.enctype, + conf_data_length + 16 /* E(Header) */, &k5_padlen); + if (code != 0) + goto cleanup; + + if (k5_padlen == 0 && (ctx->gss_flags & GSS_C_DCE_STYLE)) { + /* Windows rejects AEAD tokens with non-zero EC */ + code = krb5_c_block_size(context, key->keyblock.enctype, &ec); + if (code != 0) + goto cleanup; + } else + ec = k5_padlen; + + code = krb5_c_crypto_length(context, key->keyblock.enctype, + KRB5_CRYPTO_TYPE_TRAILER, &k5_trailerlen); + if (code != 0) + goto cleanup; + + gss_headerlen = 16 /* Header */ + k5_headerlen; + gss_trailerlen = ec + 16 /* E(Header) */ + k5_trailerlen; + + if (trailer == NULL) { + rrc = gss_trailerlen; + /* Workaround for Windows bug where it rotates by EC + RRC */ + if (ctx->gss_flags & GSS_C_DCE_STYLE) + rrc -= ec; + gss_headerlen += gss_trailerlen; + } + + if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) { + code = kg_allocate_iov(header, (size_t) gss_headerlen); + } else if (header->buffer.length < gss_headerlen) + code = KRB5_BAD_MSIZE; + if (code != 0) + goto cleanup; + outbuf = (unsigned char *)header->buffer.value; + header->buffer.length = (size_t) gss_headerlen; + + if (trailer != NULL) { + if (trailer->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) + code = kg_allocate_iov(trailer, (size_t) gss_trailerlen); + else if (trailer->buffer.length < gss_trailerlen) + code = KRB5_BAD_MSIZE; + if (code != 0) + goto cleanup; + trailer->buffer.length = (size_t) gss_trailerlen; + } + + /* TOK_ID */ + store_16_be(KG2_TOK_WRAP_MSG, outbuf); + /* flags */ + outbuf[2] = (acceptor_flag | FLAG_WRAP_CONFIDENTIAL | + (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0)); + /* filler */ + outbuf[3] = 0xFF; + /* EC */ + store_16_be(ec, outbuf + 4); + /* RRC */ + store_16_be(0, outbuf + 6); + store_64_be(ctx->seq_send, outbuf + 8); + + /* EC | copy of header to be encrypted, located in (possibly rotated) trailer */ + if (trailer == NULL) + tbuf = (unsigned char *)header->buffer.value + 16; /* Header */ + else + tbuf = (unsigned char *)trailer->buffer.value; + + memset(tbuf, 0xFF, ec); + memcpy(tbuf + ec, header->buffer.value, 16); + + code = kg_encrypt_iov(context, ctx->proto, + ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0), + ec, rrc, key, key_usage, 0, iov, iov_count); + if (code != 0) + goto cleanup; + + /* RRC */ + store_16_be(rrc, outbuf + 6); + + ctx->seq_send++; + } else if (toktype == KG_TOK_WRAP_MSG && !conf_req_flag) { + tok_id = KG2_TOK_WRAP_MSG; + + wrap_with_checksum: + + gss_headerlen = 16; + + code = krb5_c_crypto_length(context, key->keyblock.enctype, + KRB5_CRYPTO_TYPE_CHECKSUM, + &gss_trailerlen); + if (code != 0) + goto cleanup; + + assert(gss_trailerlen <= 0xFFFF); + + if (trailer == NULL) { + rrc = gss_trailerlen; + gss_headerlen += gss_trailerlen; + } + + if (header->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) + code = kg_allocate_iov(header, (size_t) gss_headerlen); + else if (header->buffer.length < gss_headerlen) + code = KRB5_BAD_MSIZE; + if (code != 0) + goto cleanup; + outbuf = (unsigned char *)header->buffer.value; + header->buffer.length = (size_t) gss_headerlen; + + if (trailer != NULL) { + if (trailer->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) + code = kg_allocate_iov(trailer, (size_t) gss_trailerlen); + else if (trailer->buffer.length < gss_trailerlen) + code = KRB5_BAD_MSIZE; + if (code != 0) + goto cleanup; + trailer->buffer.length = (size_t) gss_trailerlen; + } + + /* TOK_ID */ + store_16_be(tok_id, outbuf); + /* flags */ + outbuf[2] = (acceptor_flag + | (ctx->have_acceptor_subkey ? FLAG_ACCEPTOR_SUBKEY : 0)); + /* filler */ + outbuf[3] = 0xFF; + if (toktype == KG_TOK_WRAP_MSG) { + /* Use 0 for checksum calculation, substitute + * checksum length later. + */ + /* EC */ + store_16_be(0, outbuf + 4); + /* RRC */ + store_16_be(0, outbuf + 6); + } else { + /* MIC and DEL store 0xFF in EC and RRC */ + store_16_be(0xFFFF, outbuf + 4); + store_16_be(0xFFFF, outbuf + 6); + } + store_64_be(ctx->seq_send, outbuf + 8); + + code = kg_make_checksum_iov_v3(context, cksumtype, + rrc, key, key_usage, + iov, iov_count, toktype); + if (code != 0) + goto cleanup; + + ctx->seq_send++; + + if (toktype == KG_TOK_WRAP_MSG) { + /* Fix up EC field */ + store_16_be(gss_trailerlen, outbuf + 4); + /* Fix up RRC field */ + store_16_be(rrc, outbuf + 6); + } + } else if (toktype == KG_TOK_MIC_MSG) { + tok_id = KG2_TOK_MIC_MSG; + trailer = NULL; + goto wrap_with_checksum; + } else if (toktype == KG_TOK_DEL_CTX) { + tok_id = KG2_TOK_DEL_CTX; + goto wrap_with_checksum; + } else { + abort(); + } + + code = 0; + if (conf_state != NULL) + *conf_state = conf_req_flag; + +cleanup: + if (code != 0) + kg_release_iov(iov, iov_count); + + return code; +} + +OM_uint32 +gss_krb5int_unseal_v3_iov(krb5_context context, + OM_uint32 *minor_status, + krb5_gss_ctx_id_rec *ctx, + gss_iov_buffer_desc *iov, + int iov_count, + int *conf_state, + gss_qop_t *qop_state, + int toktype) +{ + OM_uint32 code; + gss_iov_buffer_t header; + gss_iov_buffer_t padding; + gss_iov_buffer_t trailer; + unsigned char acceptor_flag; + unsigned char *ptr = NULL; + int key_usage; + size_t rrc, ec; + size_t data_length, assoc_data_length; + krb5_key key; + uint64_t seqnum; + krb5_boolean valid; + krb5_cksumtype cksumtype; + int conf_flag = 0; + + if (qop_state != NULL) + *qop_state = GSS_C_QOP_DEFAULT; + + header = kg_locate_header_iov(iov, iov_count, toktype); + assert(header != NULL); + + padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + if (padding != NULL && padding->buffer.length != 0) + return GSS_S_DEFECTIVE_TOKEN; + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + + acceptor_flag = ctx->initiate ? FLAG_SENDER_IS_ACCEPTOR : 0; + key_usage = (toktype == KG_TOK_WRAP_MSG + ? (!ctx->initiate + ? KG_USAGE_INITIATOR_SEAL + : KG_USAGE_ACCEPTOR_SEAL) + : (!ctx->initiate + ? KG_USAGE_INITIATOR_SIGN + : KG_USAGE_ACCEPTOR_SIGN)); + + kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length); + + ptr = (unsigned char *)header->buffer.value; + + if (header->buffer.length < 16) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + if ((ptr[2] & FLAG_SENDER_IS_ACCEPTOR) != acceptor_flag) { + *minor_status = (OM_uint32)G_BAD_DIRECTION; + return GSS_S_BAD_SIG; + } + + if (ctx->have_acceptor_subkey && (ptr[2] & FLAG_ACCEPTOR_SUBKEY)) { + key = ctx->acceptor_subkey; + cksumtype = ctx->acceptor_subkey_cksumtype; + } else { + key = ctx->subkey; + cksumtype = ctx->cksumtype; + } + assert(key != NULL); + + + if (toktype == KG_TOK_WRAP_MSG) { + unsigned int k5_trailerlen; + + if (load_16_be(ptr) != KG2_TOK_WRAP_MSG) + goto defective; + conf_flag = ((ptr[2] & FLAG_WRAP_CONFIDENTIAL) != 0); + if (ptr[3] != 0xFF) + goto defective; + ec = load_16_be(ptr + 4); + rrc = load_16_be(ptr + 6); + seqnum = load_64_be(ptr + 8); + + code = krb5_c_crypto_length(context, key->keyblock.enctype, + conf_flag ? KRB5_CRYPTO_TYPE_TRAILER : + KRB5_CRYPTO_TYPE_CHECKSUM, + &k5_trailerlen); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + /* Deal with RRC */ + if (trailer == NULL) { + size_t desired_rrc = k5_trailerlen; + + if (conf_flag) { + desired_rrc += 16; /* E(Header) */ + + if ((ctx->gss_flags & GSS_C_DCE_STYLE) == 0) + desired_rrc += ec; + } + + /* According to MS, we only need to deal with a fixed RRC for DCE */ + if (rrc != desired_rrc) + goto defective; + } else if (rrc != 0) { + /* Should have been rotated by kg_unseal_stream_iov() */ + goto defective; + } + + if (conf_flag) { + unsigned char *althdr; + + /* Decrypt */ + code = kg_decrypt_iov(context, ctx->proto, + ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0), + ec, rrc, + key, key_usage, 0, iov, iov_count); + if (code != 0) { + *minor_status = code; + return GSS_S_BAD_SIG; + } + + /* Validate header integrity */ + if (trailer == NULL) + althdr = (unsigned char *)header->buffer.value + 16 + ec; + else + althdr = (unsigned char *)trailer->buffer.value + ec; + + if (load_16_be(althdr) != KG2_TOK_WRAP_MSG + || althdr[2] != ptr[2] + || althdr[3] != ptr[3] + || load_16_be(althdr + 4) != ec + || memcmp(althdr + 8, ptr + 8, 8) != 0) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + } else { + /* Verify checksum: note EC is checksum size here, not padding */ + if (ec != k5_trailerlen) + goto defective; + + /* Zero EC, RRC before computing checksum */ + store_16_be(0, ptr + 4); + store_16_be(0, ptr + 6); + + code = kg_verify_checksum_iov_v3(context, cksumtype, rrc, + key, key_usage, + iov, iov_count, toktype, &valid); + if (code != 0 || valid == FALSE) { + *minor_status = code; + return GSS_S_BAD_SIG; + } + } + + code = g_seqstate_check(ctx->seqstate, seqnum); + } else if (toktype == KG_TOK_MIC_MSG) { + if (load_16_be(ptr) != KG2_TOK_MIC_MSG) + goto defective; + + verify_mic_1: + if (ptr[3] != 0xFF) + goto defective; + seqnum = load_64_be(ptr + 8); + + /* For MIC tokens, the GSS header and checksum are in the same buffer. + * Fake up an RRC so that the checksum is expected in the header. */ + rrc = (trailer != NULL) ? 0 : header->buffer.length - 16; + code = kg_verify_checksum_iov_v3(context, cksumtype, rrc, + key, key_usage, + iov, iov_count, toktype, &valid); + if (code != 0 || valid == FALSE) { + *minor_status = code; + return GSS_S_BAD_SIG; + } + code = g_seqstate_check(ctx->seqstate, seqnum); + } else if (toktype == KG_TOK_DEL_CTX) { + if (load_16_be(ptr) != KG2_TOK_DEL_CTX) + goto defective; + goto verify_mic_1; + } else { + goto defective; + } + + *minor_status = 0; + + if (conf_state != NULL) + *conf_state = conf_flag; + + return code; + +defective: + *minor_status = 0; + + return GSS_S_DEFECTIVE_TOKEN; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/k5unseal.c b/krb5-1.21.3/src/lib/gssapi/krb5/k5unseal.c new file mode 100644 index 00000000..9b183bc3 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/k5unseal.c @@ -0,0 +1,476 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2001, 2007 by the Massachusetts Institute of Technology. + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "gssapiP_krb5.h" +#ifdef HAVE_MEMORY_H +#include +#endif +#include + +/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX + conf_state is only valid if SEAL. */ + +static OM_uint32 +kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer, + conf_state, qop_state, toktype) + krb5_context context; + OM_uint32 *minor_status; + krb5_gss_ctx_id_rec *ctx; + unsigned char *ptr; + int bodysize; + gss_buffer_t message_buffer; + int *conf_state; + gss_qop_t *qop_state; + int toktype; +{ + krb5_error_code code; + int conflen = 0; + int signalg; + int sealalg; + int bad_pad = 0; + gss_buffer_desc token; + krb5_checksum md5cksum; + krb5_data plaind; + char *data_ptr; + unsigned char *plain; + unsigned int cksum_len = 0; + size_t plainlen; + int direction; + krb5_ui_4 seqnum; + OM_uint32 retval; + size_t sumlen; + size_t padlen; + krb5_keyusage sign_usage = KG_USAGE_SIGN; + + if (toktype == KG_TOK_SEAL_MSG) { + message_buffer->length = 0; + message_buffer->value = NULL; + } + + /* Sanity checks */ + + if (ctx->seq == NULL) { + /* ctx was established using a newer enctype, and cannot process RFC + * 1964 tokens. */ + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + if ((bodysize < 22) || (ptr[4] != 0xff) || (ptr[5] != 0xff)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + signalg = ptr[0] + (ptr[1]<<8); + sealalg = ptr[2] + (ptr[3]<<8); + + if ((toktype != KG_TOK_SEAL_MSG) && + (sealalg != 0xffff)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + /* in the current spec, there is only one valid seal algorithm per + key type, so a simple comparison is ok */ + + if ((toktype == KG_TOK_SEAL_MSG) && + !((sealalg == 0xffff) || + (sealalg == ctx->sealalg))) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + /* there are several mappings of seal algorithms to sign algorithms, + but few enough that we can try them all. */ + + if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) || + (ctx->sealalg == SEAL_ALG_DES3KD && + signalg != SGN_ALG_HMAC_SHA1_DES3_KD)|| + (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4 && + signalg != SGN_ALG_HMAC_MD5)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + switch (signalg) { + case SGN_ALG_HMAC_MD5: + cksum_len = 8; + if (toktype != KG_TOK_SEAL_MSG) + sign_usage = 15; + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + cksum_len = 20; + break; + default: + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + if ((size_t)bodysize < 14 + cksum_len) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + /* get the token parameters */ + + if ((code = kg_get_seq_num(context, ctx->seq, ptr+14, ptr+6, &direction, + &seqnum))) { + *minor_status = code; + return(GSS_S_BAD_SIG); + } + + /* decode the message, if SEAL */ + + if (toktype == KG_TOK_SEAL_MSG) { + size_t tmsglen = bodysize-(14+cksum_len); + if (sealalg != 0xffff) { + if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) { + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + if (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) { + unsigned char bigend_seqnum[4]; + krb5_keyblock *enc_key; + int i; + store_32_be(seqnum, bigend_seqnum); + code = krb5_k_key_keyblock(context, ctx->enc, &enc_key); + if (code) + { + xfree(plain); + *minor_status = code; + return(GSS_S_FAILURE); + } + + assert (enc_key->length == 16); + for (i = 0; i <= 15; i++) + ((char *) enc_key->contents)[i] ^=0xf0; + code = kg_arcfour_docrypt (enc_key, 0, + &bigend_seqnum[0], 4, + ptr+14+cksum_len, tmsglen, + plain); + krb5_free_keyblock (context, enc_key); + } else { + code = kg_decrypt(context, ctx->enc, KG_USAGE_SEAL, NULL, + ptr+14+cksum_len, plain, tmsglen); + } + if (code) { + xfree(plain); + *minor_status = code; + return(GSS_S_FAILURE); + } + } else { + plain = ptr+14+cksum_len; + } + + plainlen = tmsglen; + + conflen = kg_confounder_size(context, ctx->enc->keyblock.enctype); + if (tmsglen < (size_t)conflen) { + if (sealalg != 0xffff) + xfree(plain); + *minor_status = 0; + return(GSS_S_DEFECTIVE_TOKEN); + } + padlen = plain[tmsglen - 1]; + if (tmsglen - conflen < padlen) { + /* Don't error out yet, to avoid padding oracle attacks. We will + * treat this as a checksum failure later on. */ + padlen = 0; + bad_pad = 1; + } + token.length = tmsglen - conflen - padlen; + + if (token.length) { + if ((token.value = (void *) gssalloc_malloc(token.length)) == NULL) { + if (sealalg != 0xffff) + xfree(plain); + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + memcpy(token.value, plain+conflen, token.length); + } else { + token.value = NULL; + } + } else if (toktype == KG_TOK_SIGN_MSG) { + token = *message_buffer; + plain = token.value; + plainlen = token.length; + } else { + token.length = 0; + token.value = NULL; + plain = token.value; + plainlen = token.length; + } + + /* compute the checksum of the message */ + + /* initialize the the cksum */ + switch (signalg) { + case SGN_ALG_HMAC_MD5: + md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; + break; + default: + abort (); + } + + code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen); + if (code) + return(code); + md5cksum.length = sumlen; + + switch (signalg) { + default: + *minor_status = 0; + return(GSS_S_DEFECTIVE_TOKEN); + + case SGN_ALG_HMAC_SHA1_DES3_KD: + case SGN_ALG_HMAC_MD5: + /* compute the checksum of the message */ + + /* 8 = bytes of token body to be checksummed according to spec */ + + if (! (data_ptr = xmalloc(8 + plainlen))) { + if (sealalg != 0xffff) + xfree(plain); + if (toktype == KG_TOK_SEAL_MSG) + gssalloc_free(token.value); + *minor_status = ENOMEM; + return(GSS_S_FAILURE); + } + + (void) memcpy(data_ptr, ptr-2, 8); + + (void) memcpy(data_ptr+8, plain, plainlen); + + plaind.length = 8 + plainlen; + plaind.data = data_ptr; + code = krb5_k_make_checksum(context, md5cksum.checksum_type, + ctx->seq, sign_usage, + &plaind, &md5cksum); + xfree(data_ptr); + + if (code) { + if (toktype == KG_TOK_SEAL_MSG) + gssalloc_free(token.value); + *minor_status = code; + return(GSS_S_FAILURE); + } + + code = k5_bcmp(md5cksum.contents, ptr + 14, cksum_len); + break; + } + + krb5_free_checksum_contents(context, &md5cksum); + if (sealalg != 0xffff) + xfree(plain); + + /* compare the computed checksum against the transmitted checksum */ + + if (code || bad_pad) { + if (toktype == KG_TOK_SEAL_MSG) + gssalloc_free(token.value); + *minor_status = 0; + return(GSS_S_BAD_SIG); + } + + + /* It got through unscathed. Make sure the context is unexpired. */ + + if (toktype == KG_TOK_SEAL_MSG) + *message_buffer = token; + + if (conf_state) + *conf_state = (sealalg != 0xffff); + + if (qop_state) + *qop_state = GSS_C_QOP_DEFAULT; + + /* do sequencing checks */ + + if ((ctx->initiate && direction != 0xff) || + (!ctx->initiate && direction != 0)) { + if (toktype == KG_TOK_SEAL_MSG) { + gssalloc_free(token.value); + message_buffer->value = NULL; + message_buffer->length = 0; + } + *minor_status = (OM_uint32)G_BAD_DIRECTION; + return(GSS_S_BAD_SIG); + } + + retval = g_seqstate_check(ctx->seqstate, (uint64_t)seqnum); + + /* success or ordering violation */ + + *minor_status = 0; + return(retval); +} + +/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX + conf_state is only valid if SEAL. */ + +OM_uint32 +kg_unseal(minor_status, context_handle, input_token_buffer, + message_buffer, conf_state, qop_state, toktype) + OM_uint32 *minor_status; + gss_ctx_id_t context_handle; + gss_buffer_t input_token_buffer; + gss_buffer_t message_buffer; + int *conf_state; + gss_qop_t *qop_state; + int toktype; +{ + krb5_gss_ctx_id_rec *ctx; + unsigned char *ptr; + unsigned int bodysize; + int err; + int toktype2; + int vfyflags = 0; + OM_uint32 ret; + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + + if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } + + /* parse the token, leave the data in message_buffer, setting conf_state */ + + /* verify the header */ + + ptr = (unsigned char *) input_token_buffer->value; + + + err = g_verify_token_header(ctx->mech_used, + &bodysize, &ptr, -1, + input_token_buffer->length, + vfyflags); + if (err) { + *minor_status = err; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (bodysize < 2) { + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + return GSS_S_DEFECTIVE_TOKEN; + } + + toktype2 = load_16_be(ptr); + + ptr += 2; + bodysize -= 2; + + switch (toktype2) { + case KG2_TOK_MIC_MSG: + case KG2_TOK_WRAP_MSG: + case KG2_TOK_DEL_CTX: + ret = gss_krb5int_unseal_token_v3(&ctx->k5_context, minor_status, ctx, + ptr, bodysize, message_buffer, + conf_state, qop_state, toktype); + break; + case KG_TOK_MIC_MSG: + case KG_TOK_WRAP_MSG: + case KG_TOK_DEL_CTX: + ret = kg_unseal_v1(ctx->k5_context, minor_status, ctx, ptr, bodysize, + message_buffer, conf_state, qop_state, + toktype); + break; + default: + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + ret = GSS_S_DEFECTIVE_TOKEN; + break; + } + + if (ret != 0) + save_error_info (*minor_status, ctx->k5_context); + + return ret; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_unwrap(minor_status, context_handle, + input_message_buffer, output_message_buffer, + conf_state, qop_state) + OM_uint32 *minor_status; + gss_ctx_id_t context_handle; + gss_buffer_t input_message_buffer; + gss_buffer_t output_message_buffer; + int *conf_state; + gss_qop_t *qop_state; +{ + OM_uint32 rstat; + + rstat = kg_unseal(minor_status, context_handle, + input_message_buffer, output_message_buffer, + conf_state, qop_state, KG_TOK_WRAP_MSG); + return(rstat); +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_verify_mic(minor_status, context_handle, + message_buffer, token_buffer, + qop_state) + OM_uint32 *minor_status; + gss_ctx_id_t context_handle; + gss_buffer_t message_buffer; + gss_buffer_t token_buffer; + gss_qop_t *qop_state; +{ + OM_uint32 rstat; + + rstat = kg_unseal(minor_status, context_handle, + token_buffer, message_buffer, + NULL, qop_state, KG_TOK_MIC_MSG); + return(rstat); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/k5unsealiov.c b/krb5-1.21.3/src/lib/gssapi/krb5/k5unsealiov.c new file mode 100644 index 00000000..21b50173 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/k5unsealiov.c @@ -0,0 +1,712 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/k5unsealiov.c */ +/* + * Copyright 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "k5-der.h" +#include "gssapiP_krb5.h" + +static OM_uint32 +kg_unseal_v1_iov(krb5_context context, + OM_uint32 *minor_status, + krb5_gss_ctx_id_rec *ctx, + gss_iov_buffer_desc *iov, + int iov_count, + size_t token_wrapper_len, + int *conf_state, + gss_qop_t *qop_state, + int toktype) +{ + OM_uint32 code; + gss_iov_buffer_t header; + gss_iov_buffer_t trailer; + unsigned char *ptr; + int sealalg; + int signalg; + krb5_checksum md5cksum; + size_t cksum_len = 0; + size_t conflen = 0; + int direction; + krb5_ui_4 seqnum; + OM_uint32 retval; + size_t sumlen; + krb5_keyusage sign_usage = KG_USAGE_SIGN; + + md5cksum.length = 0; + md5cksum.contents = NULL; + + header = kg_locate_header_iov(iov, iov_count, toktype); + assert(header != NULL); + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + if (trailer != NULL && trailer->buffer.length != 0) { + *minor_status = (OM_uint32)KRB5_BAD_MSIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (ctx->seq == NULL) { + /* ctx was established using a newer enctype, and cannot process RFC + * 1964 tokens. */ + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (header->buffer.length < token_wrapper_len + 22) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + ptr = (unsigned char *)header->buffer.value + token_wrapper_len; + + signalg = ptr[0]; + signalg |= ptr[1] << 8; + + sealalg = ptr[2]; + sealalg |= ptr[3] << 8; + + if (ptr[4] != 0xFF || ptr[5] != 0xFF) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (toktype != KG_TOK_WRAP_MSG && sealalg != 0xFFFF) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (toktype == KG_TOK_WRAP_MSG && + !(sealalg == 0xFFFF || sealalg == ctx->sealalg)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) || + (ctx->sealalg == SEAL_ALG_DES3KD && + signalg != SGN_ALG_HMAC_SHA1_DES3_KD)|| + (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4 && + signalg != SGN_ALG_HMAC_MD5)) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + switch (signalg) { + case SGN_ALG_HMAC_MD5: + cksum_len = 8; + if (toktype != KG_TOK_WRAP_MSG) + sign_usage = 15; + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + cksum_len = 20; + break; + default: + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + /* get the token parameters */ + code = kg_get_seq_num(context, ctx->seq, ptr + 14, ptr + 6, &direction, + &seqnum); + if (code != 0) { + *minor_status = code; + return GSS_S_BAD_SIG; + } + + /* decode the message, if SEAL */ + if (toktype == KG_TOK_WRAP_MSG) { + if (sealalg != 0xFFFF) { + if (ctx->sealalg == SEAL_ALG_MICROSOFT_RC4) { + unsigned char bigend_seqnum[4]; + krb5_keyblock *enc_key; + size_t i; + + store_32_be(seqnum, bigend_seqnum); + + code = krb5_k_key_keyblock(context, ctx->enc, &enc_key); + if (code != 0) { + retval = GSS_S_FAILURE; + goto cleanup; + } + + assert(enc_key->length == 16); + + for (i = 0; i < enc_key->length; i++) + ((char *)enc_key->contents)[i] ^= 0xF0; + + code = kg_arcfour_docrypt_iov(context, enc_key, 0, + &bigend_seqnum[0], 4, + iov, iov_count); + krb5_free_keyblock(context, enc_key); + } else { + code = kg_decrypt_iov(context, 0, + ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0), + 0 /*EC*/, 0 /*RRC*/, + ctx->enc, KG_USAGE_SEAL, NULL, + iov, iov_count); + } + if (code != 0) { + retval = GSS_S_FAILURE; + goto cleanup; + } + } + conflen = kg_confounder_size(context, ctx->enc->keyblock.enctype); + } + + if (header->buffer.length != token_wrapper_len + 14 + cksum_len + conflen) { + retval = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + + /* compute the checksum of the message */ + + /* initialize the checksum */ + + switch (signalg) { + case SGN_ALG_HMAC_MD5: + md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR; + break; + case SGN_ALG_HMAC_SHA1_DES3_KD: + md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3; + break; + default: + abort(); + } + + code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen); + if (code != 0) { + retval = GSS_S_FAILURE; + goto cleanup; + } + md5cksum.length = sumlen; + + /* compute the checksum of the message */ + code = kg_make_checksum_iov_v1(context, md5cksum.checksum_type, + cksum_len, ctx->seq, ctx->enc, + sign_usage, iov, iov_count, toktype, + &md5cksum); + if (code != 0) { + retval = GSS_S_FAILURE; + goto cleanup; + } + + switch (signalg) { + case SGN_ALG_HMAC_SHA1_DES3_KD: + case SGN_ALG_HMAC_MD5: + code = k5_bcmp(md5cksum.contents, ptr + 14, cksum_len); + break; + default: + code = 0; + retval = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + break; + } + + if (code != 0) { + code = 0; + retval = GSS_S_BAD_SIG; + goto cleanup; + } + + /* + * For GSS_C_DCE_STYLE, the caller manages the padding, because the + * pad length is in the RPC PDU. The value of the padding may be + * uninitialized. For normal GSS, the last bytes of the decrypted + * data contain the pad length. kg_fixup_padding_iov() will find + * this and fixup the last data IOV appropriately. + */ + if (toktype == KG_TOK_WRAP_MSG && + (ctx->gss_flags & GSS_C_DCE_STYLE) == 0) { + retval = kg_fixup_padding_iov(&code, iov, iov_count); + if (retval != GSS_S_COMPLETE) + goto cleanup; + } + + if (conf_state != NULL) + *conf_state = (sealalg != 0xFFFF); + + if (qop_state != NULL) + *qop_state = GSS_C_QOP_DEFAULT; + + if ((ctx->initiate && direction != 0xff) || + (!ctx->initiate && direction != 0)) { + *minor_status = (OM_uint32)G_BAD_DIRECTION; + retval = GSS_S_BAD_SIG; + goto cleanup; + } + + code = 0; + retval = g_seqstate_check(ctx->seqstate, (uint64_t)seqnum); + +cleanup: + krb5_free_checksum_contents(context, &md5cksum); + + *minor_status = code; + + return retval; +} + +/* Similar to k5_der_get_value(), but output an unchecked content length + * instead of a k5input containing the contents. */ +static inline bool +get_der_tag(struct k5input *in, uint8_t idbyte, size_t *len_out) +{ + uint8_t lenbyte, i; + size_t len; + + /* Do nothing if in is empty or the next byte doesn't match idbyte. */ + if (in->status || in->len == 0 || *in->ptr != idbyte) + return false; + + /* Advance past the identifier byte and decode the length. */ + (void)k5_input_get_byte(in); + lenbyte = k5_input_get_byte(in); + if (lenbyte < 128) { + len = lenbyte; + } else { + len = 0; + for (i = 0; i < (lenbyte & 0x7F); i++) { + if (len > (SIZE_MAX >> 8)) { + k5_input_set_status(in, EOVERFLOW); + return false; + } + len = (len << 8) | k5_input_get_byte(in); + } + } + + if (in->status) + return false; + + *len_out = len; + return true; +} + +/* + * Similar to g_verify_token_header() without toktype or flags, but do not read + * more than *header_len bytes of ASN.1 wrapper, and on output set *header_len + * to the remaining number of header bytes. Verify the outer DER tag's length + * against token_len, which may be larger (but not smaller) than *header_len. + */ +static gss_int32 +verify_detached_wrapper(const gss_OID_desc *mech, size_t *header_len, + uint8_t **header_in, size_t token_len) +{ + struct k5input in, mech_der; + gss_OID_desc toid; + size_t len; + + k5_input_init(&in, *header_in, *header_len); + + if (get_der_tag(&in, 0x60, &len)) { + if (len != token_len - (in.ptr - *header_in)) + return G_BAD_TOK_HEADER; + if (!k5_der_get_value(&in, 0x06, &mech_der)) + return G_BAD_TOK_HEADER; + toid.elements = (uint8_t *)mech_der.ptr; + toid.length = mech_der.len; + if (!g_OID_equal(&toid, mech)) + return G_WRONG_MECH; + } + + *header_in = (uint8_t *)in.ptr; + *header_len = in.len; + return 0; +} + +/* + * Caller must provide TOKEN | DATA | PADDING | TRAILER, except + * for DCE in which case it can just provide TOKEN | DATA (must + * guarantee that DATA is padded) + */ +static OM_uint32 +kg_unseal_iov_token(OM_uint32 *minor_status, + krb5_gss_ctx_id_rec *ctx, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + krb5_error_code code; + krb5_context context = ctx->k5_context; + unsigned char *ptr; + gss_iov_buffer_t header; + gss_iov_buffer_t padding; + gss_iov_buffer_t trailer; + size_t input_length, hlen; + int toktype2; + + header = kg_locate_header_iov(iov, iov_count, toktype); + if (header == NULL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + + ptr = (unsigned char *)header->buffer.value; + input_length = header->buffer.length; + + if ((ctx->gss_flags & GSS_C_DCE_STYLE) == 0 && + toktype == KG_TOK_WRAP_MSG) { + size_t data_length, assoc_data_length; + + kg_iov_msglen(iov, iov_count, &data_length, &assoc_data_length); + + input_length += data_length - assoc_data_length; + + if (padding != NULL) + input_length += padding->buffer.length; + + if (trailer != NULL) + input_length += trailer->buffer.length; + } + + hlen = header->buffer.length; + code = verify_detached_wrapper(ctx->mech_used, &hlen, &ptr, input_length); + if (code != 0) { + *minor_status = code; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (hlen < 2) { + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + return GSS_S_DEFECTIVE_TOKEN; + } + + toktype2 = load_16_be(ptr); + + ptr += 2; + hlen -= 2; + + switch (toktype2) { + case KG2_TOK_MIC_MSG: + case KG2_TOK_WRAP_MSG: + case KG2_TOK_DEL_CTX: + code = gss_krb5int_unseal_v3_iov(context, minor_status, ctx, iov, iov_count, + conf_state, qop_state, toktype); + break; + case KG_TOK_MIC_MSG: + case KG_TOK_WRAP_MSG: + case KG_TOK_DEL_CTX: + code = kg_unseal_v1_iov(context, minor_status, ctx, iov, iov_count, + (size_t)(ptr - (unsigned char *)header->buffer.value), + conf_state, qop_state, toktype); + break; + default: + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + code = GSS_S_DEFECTIVE_TOKEN; + break; + } + + if (code != 0) + save_error_info(*minor_status, context); + + return code; +} + +/* + * Split a STREAM | SIGN_DATA | DATA into + * HEADER | SIGN_DATA | DATA | PADDING | TRAILER + */ +static OM_uint32 +kg_unseal_stream_iov(OM_uint32 *minor_status, + krb5_gss_ctx_id_rec *ctx, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + unsigned char *ptr; + unsigned int bodysize; + OM_uint32 code = 0, major_status = GSS_S_FAILURE; + krb5_context context = ctx->k5_context; + int conf_req_flag, toktype2; + int i = 0, j; + gss_iov_buffer_desc *tiov = NULL; + gss_iov_buffer_t stream, data = NULL; + gss_iov_buffer_t theader, tdata = NULL, tpadding, ttrailer; + + assert(toktype == KG_TOK_WRAP_MSG); + + if (toktype != KG_TOK_WRAP_MSG || (ctx->gss_flags & GSS_C_DCE_STYLE)) { + code = EINVAL; + goto cleanup; + } + + stream = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM); + assert(stream != NULL); + + ptr = (unsigned char *)stream->buffer.value; + + code = g_verify_token_header(ctx->mech_used, + &bodysize, &ptr, -1, + stream->buffer.length, 0); + if (code != 0) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + + if (bodysize < 2) { + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + return GSS_S_DEFECTIVE_TOKEN; + } + + toktype2 = load_16_be(ptr); + + ptr += 2; + bodysize -= 2; + + tiov = (gss_iov_buffer_desc *)calloc((size_t)iov_count + 2, sizeof(gss_iov_buffer_desc)); + if (tiov == NULL) { + code = ENOMEM; + goto cleanup; + } + + /* HEADER */ + theader = &tiov[i++]; + theader->type = GSS_IOV_BUFFER_TYPE_HEADER; + theader->buffer.value = stream->buffer.value; + theader->buffer.length = ptr - (unsigned char *)stream->buffer.value; + if (bodysize < 14 || + stream->buffer.length != theader->buffer.length + bodysize) { + major_status = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + theader->buffer.length += 14; + + /* n[SIGN_DATA] | DATA | m[SIGN_DATA] */ + for (j = 0; j < iov_count; j++) { + OM_uint32 type = GSS_IOV_BUFFER_TYPE(iov[j].type); + + if (type == GSS_IOV_BUFFER_TYPE_DATA) { + if (data != NULL) { + /* only a single DATA buffer can appear */ + code = EINVAL; + goto cleanup; + } + + data = &iov[j]; + tdata = &tiov[i]; + } + if (type == GSS_IOV_BUFFER_TYPE_DATA || + type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY) + tiov[i++] = iov[j]; + } + + if (data == NULL) { + /* a single DATA buffer must be present */ + code = EINVAL; + goto cleanup; + } + + /* PADDING | TRAILER */ + tpadding = &tiov[i++]; + tpadding->type = GSS_IOV_BUFFER_TYPE_PADDING; + tpadding->buffer.length = 0; + tpadding->buffer.value = NULL; + + ttrailer = &tiov[i++]; + ttrailer->type = GSS_IOV_BUFFER_TYPE_TRAILER; + + switch (toktype2) { + case KG2_TOK_MIC_MSG: + case KG2_TOK_WRAP_MSG: + case KG2_TOK_DEL_CTX: { + size_t ec, rrc; + krb5_enctype enctype; + unsigned int k5_headerlen = 0; + unsigned int k5_trailerlen = 0; + + if (ctx->have_acceptor_subkey) + enctype = ctx->acceptor_subkey->keyblock.enctype; + else + enctype = ctx->subkey->keyblock.enctype; + conf_req_flag = ((ptr[0] & FLAG_WRAP_CONFIDENTIAL) != 0); + ec = conf_req_flag ? load_16_be(ptr + 2) : 0; + rrc = load_16_be(ptr + 4); + + if (rrc != 0) { + if (!gss_krb5int_rotate_left((unsigned char *)stream->buffer.value + 16, + stream->buffer.length - 16, rrc)) { + code = ENOMEM; + goto cleanup; + } + store_16_be(0, ptr + 4); /* set RRC to zero */ + } + + if (conf_req_flag) { + code = krb5_c_crypto_length(context, enctype, KRB5_CRYPTO_TYPE_HEADER, &k5_headerlen); + if (code != 0) + goto cleanup; + theader->buffer.length += k5_headerlen; /* length validated later */ + } + + /* no PADDING for CFX, EC is used instead */ + code = krb5_c_crypto_length(context, enctype, + conf_req_flag ? KRB5_CRYPTO_TYPE_TRAILER : KRB5_CRYPTO_TYPE_CHECKSUM, + &k5_trailerlen); + if (code != 0) + goto cleanup; + + ttrailer->buffer.length = ec + (conf_req_flag ? 16 : 0 /* E(Header) */) + k5_trailerlen; + ttrailer->buffer.value = (unsigned char *)stream->buffer.value + + stream->buffer.length - ttrailer->buffer.length; + break; + } + case KG_TOK_MIC_MSG: + case KG_TOK_WRAP_MSG: + case KG_TOK_DEL_CTX: + theader->buffer.length += ctx->cksum_size + + kg_confounder_size(context, ctx->enc->keyblock.enctype); + + /* + * we can't set the padding accurately until decryption; + * kg_fixup_padding_iov() will take care of this + */ + tpadding->buffer.length = 1; + tpadding->buffer.value = (unsigned char *)stream->buffer.value + stream->buffer.length - 1; + + /* no TRAILER for pre-CFX */ + ttrailer->buffer.length = 0; + ttrailer->buffer.value = NULL; + + break; + default: + code = (OM_uint32)G_BAD_TOK_HEADER; + major_status = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + break; + } + + /* IOV: -----------0-------------+---1---+--2--+----------------3--------------*/ + /* Old: GSS-Header | Conf | Data | Pad | */ + /* CFX: GSS-Header | Kerb-Header | Data | | EC | E(Header) | Kerb-Trailer */ + /* GSS: -------GSS-HEADER--------+-DATA--+-PAD-+----------GSS-TRAILER----------*/ + + /* validate lengths */ + if (stream->buffer.length < theader->buffer.length + + tpadding->buffer.length + + ttrailer->buffer.length) + { + code = (OM_uint32)KRB5_BAD_MSIZE; + major_status = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + + /* setup data */ + tdata->buffer.length = stream->buffer.length - ttrailer->buffer.length - + tpadding->buffer.length - theader->buffer.length; + + assert(data != NULL); + + if (data->type & GSS_IOV_BUFFER_FLAG_ALLOCATE) { + code = kg_allocate_iov(tdata, tdata->buffer.length); + if (code != 0) + goto cleanup; + memcpy(tdata->buffer.value, + (unsigned char *)stream->buffer.value + theader->buffer.length, tdata->buffer.length); + } else + tdata->buffer.value = (unsigned char *)stream->buffer.value + theader->buffer.length; + + assert(i <= iov_count + 2); + + major_status = kg_unseal_iov_token(&code, ctx, conf_state, qop_state, + tiov, i, toktype); + if (major_status == GSS_S_COMPLETE) + *data = *tdata; + else + kg_release_iov(tdata, 1); + +cleanup: + if (tiov != NULL) + free(tiov); + + *minor_status = code; + + return major_status; +} + +OM_uint32 +kg_unseal_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + krb5_gss_ctx_id_rec *ctx; + OM_uint32 code; + + ctx = (krb5_gss_ctx_id_rec *)context_handle; + if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + if (kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM) != NULL) { + code = kg_unseal_stream_iov(minor_status, ctx, conf_state, qop_state, + iov, iov_count, toktype); + } else { + code = kg_unseal_iov_token(minor_status, ctx, conf_state, qop_state, + iov, iov_count, toktype); + } + + return code; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_unwrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + + major_status = kg_unseal_iov(minor_status, context_handle, + conf_state, qop_state, + iov, iov_count, KG_TOK_WRAP_MSG); + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_verify_mic_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 major_status; + + major_status = kg_unseal_iov(minor_status, context_handle, + NULL, qop_state, + iov, iov_count, KG_TOK_MIC_MSG); + + return major_status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/krb5_gss_glue.c b/krb5-1.21.3/src/lib/gssapi/krb5/krb5_gss_glue.c new file mode 100644 index 00000000..b35a2152 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/krb5_gss_glue.c @@ -0,0 +1,445 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +/* + * $Id$ + */ + +#include "gssapiP_krb5.h" + +OM_uint32 KRB5_CALLCONV +gss_krb5_get_tkt_flags(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + krb5_flags *ticket_flags) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_GET_TKT_FLAGS_OID_LENGTH, + GSS_KRB5_GET_TKT_FLAGS_OID }; + OM_uint32 major_status; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + + if (ticket_flags == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + major_status = gss_inquire_sec_context_by_oid(minor_status, + context_handle, + (gss_OID)&req_oid, + &data_set); + if (major_status != GSS_S_COMPLETE) + return major_status; + + if (data_set == GSS_C_NO_BUFFER_SET || + data_set->count != 1 || + data_set->elements[0].length != sizeof(*ticket_flags)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + *ticket_flags = *((krb5_flags *)data_set->elements[0].value); + + gss_release_buffer_set(minor_status, &data_set); + + *minor_status = 0; + + return GSS_S_COMPLETE; +} + +OM_uint32 KRB5_CALLCONV +gss_krb5_copy_ccache(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + krb5_ccache out_ccache) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_COPY_CCACHE_OID_LENGTH, + GSS_KRB5_COPY_CCACHE_OID }; + OM_uint32 major_status; + gss_buffer_desc req_buffer; + + if (out_ccache == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + req_buffer.value = out_ccache; + req_buffer.length = sizeof(out_ccache); + + major_status = gss_set_cred_option(minor_status, + &cred_handle, + (gss_OID)&req_oid, + &req_buffer); + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +gss_krb5_import_cred(OM_uint32 *minor_status, + krb5_ccache id, + krb5_principal keytab_principal, + krb5_keytab keytab, + gss_cred_id_t *cred) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_IMPORT_CRED_OID_LENGTH, + GSS_KRB5_IMPORT_CRED_OID }; + OM_uint32 major_status; + struct krb5_gss_import_cred_req req; + gss_buffer_desc req_buffer; + + if (cred == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *cred = GSS_C_NO_CREDENTIAL; + + req.id = id; + req.keytab_principal = keytab_principal; + req.keytab = keytab; + + req_buffer.value = &req; + req_buffer.length = sizeof(req); + + major_status = gss_set_cred_option(minor_status, + cred, + (gss_OID)&req_oid, + &req_buffer); + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + OM_uint32 version, + void **kctx) +{ + unsigned char oid_buf[GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH + 6]; + gss_OID_desc req_oid; + OM_uint32 major_status, minor; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + + if (kctx == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *kctx = NULL; + + req_oid.elements = oid_buf; + req_oid.length = sizeof(oid_buf); + + major_status = generic_gss_oid_compose(minor_status, + GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID, + GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH, + (int)version, + &req_oid); + if (GSS_ERROR(major_status)) + return major_status; + + major_status = gss_inquire_sec_context_by_oid(minor_status, + *context_handle, + &req_oid, + &data_set); + if (GSS_ERROR(major_status)) + return major_status; + + if (data_set == GSS_C_NO_BUFFER_SET || + data_set->count != 1 || + data_set->elements[0].length != sizeof(void *)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + *kctx = *((void **)data_set->elements[0].value); + + /* Clean up the context state (it is an error for + * someone to attempt to use this context again) + */ + (void)gss_delete_sec_context(minor_status, context_handle, NULL); + *context_handle = GSS_C_NO_CONTEXT; + + generic_gss_release_buffer_set(&minor, &data_set); + + return GSS_S_COMPLETE; +} + +OM_uint32 KRB5_CALLCONV +gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status, + gss_cred_id_t cred, + OM_uint32 num_ktypes, + krb5_enctype *ktypes) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID_LENGTH, + GSS_KRB5_SET_ALLOWABLE_ENCTYPES_OID }; + OM_uint32 major_status; + struct krb5_gss_set_allowable_enctypes_req req; + gss_buffer_desc req_buffer; + + req.num_ktypes = num_ktypes; + req.ktypes = ktypes; + + req_buffer.length = sizeof(req); + req_buffer.value = &req; + + major_status = gss_set_cred_option(minor_status, + &cred, + (gss_OID)&req_oid, + &req_buffer); + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +gss_krb5_ccache_name(OM_uint32 *minor_status, + const char *name, + const char **out_name) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_CCACHE_NAME_OID_LENGTH, + GSS_KRB5_CCACHE_NAME_OID }; + OM_uint32 major_status; + struct krb5_gss_ccache_name_req req; + gss_buffer_desc req_buffer; + + req.name = name; + req.out_name = out_name; + + req_buffer.length = sizeof(req); + req_buffer.value = &req; + + major_status = gssspi_mech_invoke(minor_status, + (gss_OID)gss_mech_krb5, + (gss_OID)&req_oid, + &req_buffer); + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *kctx) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID_LENGTH, + GSS_KRB5_FREE_LUCID_SEC_CONTEXT_OID }; + OM_uint32 major_status; + gss_buffer_desc req_buffer; + + req_buffer.length = sizeof(kctx); + req_buffer.value = kctx; + + major_status = gssspi_mech_invoke(minor_status, + (gss_OID)gss_mech_krb5, + (gss_OID)&req_oid, + &req_buffer); + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_register_acceptor_identity(const char *keytab) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID_LENGTH, + GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_OID }; + OM_uint32 major_status; + OM_uint32 minor_status; + gss_buffer_desc req_buffer; + + req_buffer.length = (keytab == NULL) ? 0 : strlen(keytab); + req_buffer.value = (char *)keytab; + + major_status = gssspi_mech_invoke(&minor_status, + (gss_OID)gss_mech_krb5, + (gss_OID)&req_oid, + &req_buffer); + + return major_status; +} + +#ifndef _WIN32 +krb5_error_code +krb5_gss_use_kdc_context(void) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_USE_KDC_CONTEXT_OID_LENGTH, + GSS_KRB5_USE_KDC_CONTEXT_OID }; + OM_uint32 major_status; + OM_uint32 minor_status; + gss_buffer_desc req_buffer; + krb5_error_code ret; + + req_buffer.length = 0; + req_buffer.value = NULL; + + major_status = gssspi_mech_invoke(&minor_status, + (gss_OID)gss_mech_krb5, + (gss_OID)&req_oid, + &req_buffer); + + if (major_status != GSS_S_COMPLETE) { + if (minor_status != 0) + ret = (krb5_error_code)minor_status; + else + ret = KRB5KRB_ERR_GENERIC; + } else + ret = 0; + + return ret; +} +#endif + +/* + * This API should go away and be replaced with an accessor + * into a gss_name_t. + */ +OM_uint32 KRB5_CALLCONV +gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + int ad_type, + gss_buffer_t ad_data) +{ + gss_OID_desc req_oid; + unsigned char oid_buf[GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH + 6]; + OM_uint32 major_status; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + + if (ad_data == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + req_oid.elements = oid_buf; + req_oid.length = sizeof(oid_buf); + + major_status = generic_gss_oid_compose(minor_status, + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID, + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH, + ad_type, + &req_oid); + if (GSS_ERROR(major_status)) + return major_status; + + major_status = gss_inquire_sec_context_by_oid(minor_status, + context_handle, + (gss_OID)&req_oid, + &data_set); + if (major_status != GSS_S_COMPLETE) { + return major_status; + } + + if (data_set == GSS_C_NO_BUFFER_SET || + data_set->count != 1) { + return GSS_S_FAILURE; + } + + ad_data->length = data_set->elements[0].length; + ad_data->value = data_set->elements[0].value; + + data_set->elements[0].length = 0; + data_set->elements[0].value = NULL; + + data_set->count = 0; + + gss_release_buffer_set(minor_status, &data_set); + + return GSS_S_COMPLETE; +} + +OM_uint32 KRB5_CALLCONV +gss_krb5_set_cred_rcache(OM_uint32 *minor_status, + gss_cred_id_t cred, + krb5_rcache rcache) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_SET_CRED_RCACHE_OID_LENGTH, + GSS_KRB5_SET_CRED_RCACHE_OID }; + OM_uint32 major_status; + gss_buffer_desc req_buffer; + + req_buffer.length = sizeof(rcache); + req_buffer.value = rcache; + + major_status = gss_set_cred_option(minor_status, + &cred, + (gss_OID)&req_oid, + &req_buffer); + + return major_status; +} + +OM_uint32 KRB5_CALLCONV +gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + krb5_timestamp *authtime) +{ + static const gss_OID_desc req_oid = { + GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH, + GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID }; + OM_uint32 major_status; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + + if (authtime == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + major_status = gss_inquire_sec_context_by_oid(minor_status, + context_handle, + (gss_OID)&req_oid, + &data_set); + if (major_status != GSS_S_COMPLETE) + return major_status; + + if (data_set == GSS_C_NO_BUFFER_SET || + data_set->count != 1 || + data_set->elements[0].length != sizeof(*authtime)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + *authtime = *((krb5_timestamp *)data_set->elements[0].value); + + gss_release_buffer_set(minor_status, &data_set); + + *minor_status = 0; + + return GSS_S_COMPLETE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/lucid_context.c b/krb5-1.21.3/src/lib/gssapi/krb5/lucid_context.c new file mode 100644 index 00000000..a894f0e7 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/lucid_context.c @@ -0,0 +1,292 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/lucid_context.c */ +/* + * Copyright 2004, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Externalize a "lucid" security context from a krb5_gss_ctx_id_rec + * structure. */ +#include "gssapiP_krb5.h" +#include "gssapi_krb5.h" + +/* + * Local routine prototypes + */ +static void +free_external_lucid_ctx_v1( + gss_krb5_lucid_context_v1_t *ctx); + +static void +free_lucid_key_data( + gss_krb5_lucid_key_t *key); + +static krb5_error_code +copy_keyblock_to_lucid_key( + krb5_keyblock *k5key, + gss_krb5_lucid_key_t *lkey); + +static krb5_error_code +make_external_lucid_ctx_v1( + krb5_gss_ctx_id_rec * gctx, + int version, + void **out_ptr); + + +/* + * Exported routines + */ + +OM_uint32 +gss_krb5int_export_lucid_sec_context( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + krb5_error_code kret = 0; + OM_uint32 retval; + krb5_gss_ctx_id_t ctx = (krb5_gss_ctx_id_t)context_handle; + void *lctx = NULL; + int version = 0; + gss_buffer_desc rep; + + /* Assume failure */ + retval = GSS_S_FAILURE; + *minor_status = 0; + *data_set = GSS_C_NO_BUFFER_SET; + + if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + retval = generic_gss_oid_decompose(minor_status, + GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID, + GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH, + desired_object, + &version); + if (GSS_ERROR(retval)) + return retval; + + /* Externalize a structure of the right version */ + switch (version) { + case 1: + kret = make_external_lucid_ctx_v1((krb5_pointer)ctx, + version, &lctx); + break; + default: + kret = (OM_uint32) KG_LUCID_VERSION; + break; + } + + if (kret) + goto error_out; + + rep.value = &lctx; + rep.length = sizeof(lctx); + + retval = generic_gss_add_buffer_set_member(minor_status, &rep, data_set); + if (GSS_ERROR(retval)) + goto error_out; + +error_out: + if (*minor_status == 0) + *minor_status = (OM_uint32) kret; + return(retval); +} + +/* + * Frees the storage associated with an + * exported lucid context structure. + */ +OM_uint32 +gss_krb5int_free_lucid_sec_context( + OM_uint32 *minor_status, + const gss_OID desired_mech, + const gss_OID desired_object, + gss_buffer_t value) +{ + OM_uint32 retval; + krb5_error_code kret = 0; + int version; + void *kctx; + + /* Assume failure */ + retval = GSS_S_FAILURE; + *minor_status = 0; + + kctx = value->value; + if (!kctx) { + kret = EINVAL; + goto error_out; + } + + /* Determine version and call correct free routine */ + version = ((gss_krb5_lucid_context_version_t *)kctx)->version; + switch (version) { + case 1: + free_external_lucid_ctx_v1((gss_krb5_lucid_context_v1_t*) kctx); + break; + default: + kret = EINVAL; + break; + } + + if (kret) + goto error_out; + + /* Success! */ + *minor_status = 0; + retval = GSS_S_COMPLETE; + + return (retval); + +error_out: + if (*minor_status == 0) + *minor_status = (OM_uint32) kret; + return(retval); +} + +/* + * Local routines + */ + +static krb5_error_code +make_external_lucid_ctx_v1( + krb5_gss_ctx_id_rec * gctx, + int version, + void **out_ptr) +{ + gss_krb5_lucid_context_v1_t *lctx = NULL; + unsigned int bufsize = sizeof(gss_krb5_lucid_context_v1_t); + krb5_error_code retval; + + /* Allocate the structure */ + if ((lctx = xmalloc(bufsize)) == NULL) { + retval = ENOMEM; + goto error_out; + } + + memset(lctx, 0, bufsize); + + lctx->version = 1; + lctx->initiate = gctx->initiate ? 1 : 0; + lctx->endtime = gctx->krb_times.endtime; + lctx->send_seq = gctx->seq_send; + lctx->recv_seq = gctx->seq_recv; + lctx->protocol = gctx->proto; + /* gctx->proto == 0 ==> rfc1964-style key information + gctx->proto == 1 ==> cfx-style (draft-ietf-krb-wg-gssapi-cfx-07) keys */ + if (gctx->proto == 0) { + lctx->rfc1964_kd.sign_alg = gctx->signalg; + lctx->rfc1964_kd.seal_alg = gctx->sealalg; + /* Copy key */ + if ((retval = copy_keyblock_to_lucid_key(&gctx->seq->keyblock, + &lctx->rfc1964_kd.ctx_key))) + goto error_out; + } + else if (gctx->proto == 1) { + /* Copy keys */ + /* (subkey is always present, either a copy of the kerberos + session key or a subkey) */ + if ((retval = copy_keyblock_to_lucid_key(&gctx->subkey->keyblock, + &lctx->cfx_kd.ctx_key))) + goto error_out; + if (gctx->have_acceptor_subkey) { + if ((retval = copy_keyblock_to_lucid_key(&gctx->acceptor_subkey->keyblock, + &lctx->cfx_kd.acceptor_subkey))) + goto error_out; + lctx->cfx_kd.have_acceptor_subkey = 1; + } + } + else { + xfree(lctx); + return EINVAL; /* XXX better error code? */ + } + + /* Success! */ + *out_ptr = lctx; + return 0; + +error_out: + if (lctx) { + free_external_lucid_ctx_v1(lctx); + } + return retval; + +} + +/* Copy the contents of a krb5_keyblock to a gss_krb5_lucid_key_t structure */ +static krb5_error_code +copy_keyblock_to_lucid_key( + krb5_keyblock *k5key, + gss_krb5_lucid_key_t *lkey) +{ + if (!k5key || !k5key->contents || k5key->length == 0) + return EINVAL; + + memset(lkey, 0, sizeof(gss_krb5_lucid_key_t)); + + /* Allocate storage for the key data */ + if ((lkey->data = xmalloc(k5key->length)) == NULL) { + return ENOMEM; + } + memcpy(lkey->data, k5key->contents, k5key->length); + lkey->length = k5key->length; + lkey->type = k5key->enctype; + + return 0; +} + + +/* Free any storage associated with a gss_krb5_lucid_key_t structure */ +static void +free_lucid_key_data( + gss_krb5_lucid_key_t *key) +{ + if (key) { + if (key->data && key->length) { + zap(key->data, key->length); + xfree(key->data); + zap(key, sizeof(gss_krb5_lucid_key_t)); + } + } +} +/* Free any storage associated with a gss_krb5_lucid_context_v1 structure */ +static void +free_external_lucid_ctx_v1( + gss_krb5_lucid_context_v1_t *ctx) +{ + if (ctx) { + if (ctx->protocol == 0) { + free_lucid_key_data(&ctx->rfc1964_kd.ctx_key); + } + if (ctx->protocol == 1) { + free_lucid_key_data(&ctx->cfx_kd.ctx_key); + if (ctx->cfx_kd.have_acceptor_subkey) + free_lucid_key_data(&ctx->cfx_kd.acceptor_subkey); + } + xfree(ctx); + ctx = NULL; + } +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/naming_exts.c b/krb5-1.21.3/src/lib/gssapi/krb5/naming_exts.c new file mode 100644 index 00000000..2ac1aba3 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/naming_exts.c @@ -0,0 +1,666 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/naming_exts.c */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "gssapiP_krb5.h" + +krb5_error_code +kg_init_name(krb5_context context, krb5_principal principal, + char *service, char *host, krb5_authdata_context ad_context, + krb5_flags flags, krb5_gss_name_t *ret_name) +{ + krb5_error_code code; + krb5_gss_name_t name; + + *ret_name = NULL; + + assert(principal != NULL); + + if (principal == NULL) + return EINVAL; + + name = xmalloc(sizeof(krb5_gss_name_rec)); + if (name == NULL) + return ENOMEM; + + memset(name, 0, sizeof(krb5_gss_name_rec)); + + code = k5_mutex_init(&name->lock); + if (code != 0) + goto cleanup; + + if ((flags & KG_INIT_NAME_NO_COPY) == 0) { + code = krb5_copy_principal(context, principal, &name->princ); + if (code != 0) + goto cleanup; + + if (ad_context != NULL) { + code = krb5_authdata_context_copy(context, + ad_context, + &name->ad_context); + if (code != 0) + goto cleanup; + } + + code = ENOMEM; + if (service != NULL) { + name->service = strdup(service); + if (name->service == NULL) + goto cleanup; + } + if (host != NULL) { + name->host = strdup(host); + if (name->host == NULL) + goto cleanup; + } + code = 0; + } else { + name->princ = principal; + name->service = service; + name->host = host; + name->ad_context = ad_context; + } + + *ret_name = name; + +cleanup: + if (code != 0) + kg_release_name(context, &name); + + return code; +} + +krb5_error_code +kg_release_name(krb5_context context, + krb5_gss_name_t *name) +{ + if (*name != NULL) { + krb5_free_principal(context, (*name)->princ); + free((*name)->service); + free((*name)->host); + krb5_authdata_context_free(context, (*name)->ad_context); + k5_mutex_destroy(&(*name)->lock); + free(*name); + *name = NULL; + } + + return 0; +} + +krb5_error_code +kg_duplicate_name(krb5_context context, + const krb5_gss_name_t src, + krb5_gss_name_t *dst) +{ + krb5_error_code code; + + k5_mutex_lock(&src->lock); + code = kg_init_name(context, src->princ, src->service, src->host, + src->ad_context, 0, dst); + k5_mutex_unlock(&src->lock); + return code; +} + + +krb5_boolean +kg_compare_name(krb5_context context, + krb5_gss_name_t name1, + krb5_gss_name_t name2) +{ + return krb5_principal_compare(context, name1->princ, name2->princ); +} + +/* Determine the principal to use for an acceptor name, which is different from + * name->princ for host-based names. */ +krb5_boolean +kg_acceptor_princ(krb5_context context, krb5_gss_name_t name, + krb5_principal *princ_out) +{ + krb5_error_code code; + const char *host; + char *tmp = NULL; + + *princ_out = NULL; + if (name == NULL) + return 0; + + /* If it's not a host-based name, just copy name->princ. */ + if (name->service == NULL) + return krb5_copy_principal(context, name->princ, princ_out); + + if (name->host != NULL && name->princ->length == 2) { + /* If a host was given, we have to use the canonicalized form of it (as + * given by krb5_sname_to_principal) for backward compatibility. */ + const krb5_data *d = &name->princ->data[1]; + tmp = k5memdup0(d->data, d->length, &code); + if (tmp == NULL) + return ENOMEM; + host = tmp; + } else /* No host was given; use an empty string. */ + host = ""; + + code = krb5_build_principal(context, princ_out, 0, "", name->service, host, + (char *)NULL); + if (*princ_out != NULL) + (*princ_out)->type = KRB5_NT_SRV_HST; + free(tmp); + return code; +} + +static OM_uint32 +kg_map_name_error(OM_uint32 *minor_status, krb5_error_code code) +{ + OM_uint32 major_status; + + switch (code) { + case 0: + major_status = GSS_S_COMPLETE; + break; + case ENOENT: + case EPERM: + major_status = GSS_S_UNAVAILABLE; + break; + default: + major_status = GSS_S_FAILURE; + break; + } + + *minor_status = code; + + return major_status; +} + +/* Owns data on success */ +static krb5_error_code +data_list_to_buffer_set(krb5_context context, + krb5_data *data, + gss_buffer_set_t *buffer_set) +{ + gss_buffer_set_t set = GSS_C_NO_BUFFER_SET; + OM_uint32 minor_status; + int i; + krb5_error_code code = 0; + + if (data == NULL) + goto cleanup; + + if (buffer_set == NULL) + goto cleanup; + + if (GSS_ERROR(gss_create_empty_buffer_set(&minor_status, + &set))) { + assert(minor_status != 0); + code = minor_status; + goto cleanup; + } + + for (i = 0; data[i].data != NULL; i++) + ; + + set->count = i; + set->elements = gssalloc_calloc(i, sizeof(gss_buffer_desc)); + if (set->elements == NULL) { + gss_release_buffer_set(&minor_status, &set); + code = ENOMEM; + goto cleanup; + } + + /* + * Copy last element first so data remains properly + * NULL-terminated in case of allocation failure + * in data_to_gss() on windows. + */ + for (i = set->count-1; i >= 0; i--) { + if (data_to_gss(&data[i], &set->elements[i])) { + gss_release_buffer_set(&minor_status, &set); + code = ENOMEM; + goto cleanup; + } + } +cleanup: + krb5int_free_data_list(context, data); + + if (buffer_set != NULL) + *buffer_set = set; + + return code; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_inquire_name(OM_uint32 *minor_status, + gss_name_t name, + int *name_is_MN, + gss_OID *MN_mech, + gss_buffer_set_t *attrs) +{ + krb5_context context; + krb5_error_code code; + krb5_gss_name_t kname; + krb5_data *kattrs = NULL; + + *minor_status = 0; + + if (attrs != NULL) + *attrs = GSS_C_NO_BUFFER_SET; + + code = krb5_gss_init_context(&context); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + kname = (krb5_gss_name_t)name; + + k5_mutex_lock(&kname->lock); + + if (kname->ad_context == NULL) { + code = krb5_authdata_context_init(context, &kname->ad_context); + if (code != 0) + goto cleanup; + } + + code = krb5_authdata_get_attribute_types(context, + kname->ad_context, + &kattrs); + if (code != 0) + goto cleanup; + + code = data_list_to_buffer_set(context, kattrs, attrs); + kattrs = NULL; + if (code != 0) + goto cleanup; + +cleanup: + k5_mutex_unlock(&kname->lock); + krb5int_free_data_list(context, kattrs); + + krb5_free_context(context); + + return kg_map_name_error(minor_status, code); +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_get_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + krb5_context context; + krb5_error_code code; + krb5_gss_name_t kname; + krb5_data kattr; + krb5_boolean kauthenticated; + krb5_boolean kcomplete; + krb5_data kvalue = empty_data(); + krb5_data kdisplay_value = empty_data(); + + *minor_status = 0; + + code = krb5_gss_init_context(&context); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + kname = (krb5_gss_name_t)name; + k5_mutex_lock(&kname->lock); + + if (kname->ad_context == NULL) { + code = krb5_authdata_context_init(context, &kname->ad_context); + if (code != 0) { + *minor_status = code; + k5_mutex_unlock(&kname->lock); + krb5_free_context(context); + return GSS_S_UNAVAILABLE; + } + } + + kattr.data = (char *)attr->value; + kattr.length = attr->length; + + kauthenticated = FALSE; + kcomplete = FALSE; + + code = krb5_authdata_get_attribute(context, + kname->ad_context, + &kattr, + &kauthenticated, + &kcomplete, + &kvalue, + &kdisplay_value, + more); + if (code == 0) { + if (value != NULL) + code = data_to_gss(&kvalue, value); + + if (authenticated != NULL) + *authenticated = kauthenticated; + if (complete != NULL) + *complete = kcomplete; + + if (display_value != NULL && code == 0) + code = data_to_gss(&kdisplay_value, display_value); + } + + free(kdisplay_value.data); + free(kvalue.data); + + k5_mutex_unlock(&kname->lock); + krb5_free_context(context); + + return kg_map_name_error(minor_status, code); +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_set_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + int complete, + gss_buffer_t attr, + gss_buffer_t value) +{ + krb5_context context; + krb5_error_code code; + krb5_gss_name_t kname; + krb5_data kattr; + krb5_data kvalue; + + *minor_status = 0; + + code = krb5_gss_init_context(&context); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + kname = (krb5_gss_name_t)name; + k5_mutex_lock(&kname->lock); + + if (kname->ad_context == NULL) { + code = krb5_authdata_context_init(context, &kname->ad_context); + if (code != 0) { + *minor_status = code; + k5_mutex_unlock(&kname->lock); + krb5_free_context(context); + return GSS_S_UNAVAILABLE; + } + } + + kattr.data = (char *)attr->value; + kattr.length = attr->length; + + kvalue.data = (char *)value->value; + kvalue.length = value->length; + + code = krb5_authdata_set_attribute(context, + kname->ad_context, + complete, + &kattr, + &kvalue); + + k5_mutex_unlock(&kname->lock); + krb5_free_context(context); + + return kg_map_name_error(minor_status, code); +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_delete_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t attr) +{ + krb5_context context; + krb5_error_code code; + krb5_gss_name_t kname; + krb5_data kattr; + + *minor_status = 0; + + code = krb5_gss_init_context(&context); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + kname = (krb5_gss_name_t)name; + k5_mutex_lock(&kname->lock); + + if (kname->ad_context == NULL) { + code = krb5_authdata_context_init(context, &kname->ad_context); + if (code != 0) { + *minor_status = code; + k5_mutex_unlock(&kname->lock); + krb5_free_context(context); + return GSS_S_UNAVAILABLE; + } + } + + kattr.data = (char *)attr->value; + kattr.length = attr->length; + + code = krb5_authdata_delete_attribute(context, + kname->ad_context, + &kattr); + + k5_mutex_unlock(&kname->lock); + krb5_free_context(context); + + return kg_map_name_error(minor_status, code); +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_map_name_to_any(OM_uint32 *minor_status, + gss_name_t name, + int authenticated, + gss_buffer_t type_id, + gss_any_t *output) +{ + krb5_context context; + krb5_error_code code; + krb5_gss_name_t kname; + char *kmodule; + + *minor_status = 0; + + code = krb5_gss_init_context(&context); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + kname = (krb5_gss_name_t)name; + k5_mutex_lock(&kname->lock); + + if (kname->ad_context == NULL) { + code = krb5_authdata_context_init(context, &kname->ad_context); + if (code != 0) { + *minor_status = code; + k5_mutex_unlock(&kname->lock); + krb5_free_context(context); + return GSS_S_UNAVAILABLE; + } + } + + kmodule = (char *)type_id->value; + if (kmodule[type_id->length] != '\0') { + k5_mutex_unlock(&kname->lock); + krb5_free_context(context); + return GSS_S_UNAVAILABLE; + } + + code = krb5_authdata_export_internal(context, + kname->ad_context, + authenticated, + kmodule, + (void **)output); + + k5_mutex_unlock(&kname->lock); + krb5_free_context(context); + + return kg_map_name_error(minor_status, code); +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_release_any_name_mapping(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t type_id, + gss_any_t *input) +{ + krb5_context context; + krb5_error_code code; + krb5_gss_name_t kname; + char *kmodule; + + *minor_status = 0; + + code = krb5_gss_init_context(&context); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + kname = (krb5_gss_name_t)name; + k5_mutex_lock(&kname->lock); + + if (kname->ad_context == NULL) { + code = krb5_authdata_context_init(context, &kname->ad_context); + if (code != 0) { + *minor_status = code; + k5_mutex_unlock(&kname->lock); + krb5_free_context(context); + return GSS_S_UNAVAILABLE; + } + } + + kmodule = (char *)type_id->value; + if (kmodule[type_id->length] != '\0') { + k5_mutex_unlock(&kname->lock); + krb5_free_context(context); + return GSS_S_UNAVAILABLE; + } + + code = krb5_authdata_free_internal(context, + kname->ad_context, + kmodule, + *input); + if (code == 0) + *input = NULL; + + k5_mutex_unlock(&kname->lock); + krb5_free_context(context); + + return kg_map_name_error(minor_status, code); + +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_export_name_composite(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t exp_composite_name) +{ + krb5_context context; + krb5_error_code code; + krb5_gss_name_t kname; + krb5_data *attrs = NULL; + char *princstr = NULL; + unsigned char *cp; + size_t princlen; + + *minor_status = 0; + + code = krb5_gss_init_context(&context); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + kname = (krb5_gss_name_t)name; + k5_mutex_lock(&kname->lock); + + code = krb5_unparse_name(context, kname->princ, &princstr); + if (code != 0) + goto cleanup; + + princlen = strlen(princstr); + + if (kname->ad_context != NULL) { + code = krb5_authdata_export_attributes(context, + kname->ad_context, + AD_USAGE_MASK, + &attrs); + if (code != 0) + goto cleanup; + } + + /* 04 02 OID Name AuthData */ + + exp_composite_name->length = 10 + gss_mech_krb5->length + princlen; + exp_composite_name->length += 4; /* length of encoded attributes */ + if (attrs != NULL) + exp_composite_name->length += attrs->length; + exp_composite_name->value = gssalloc_malloc(exp_composite_name->length); + if (exp_composite_name->value == NULL) { + code = ENOMEM; + goto cleanup; + } + + cp = exp_composite_name->value; + + /* Note: we assume the OID will be less than 128 bytes... */ + *cp++ = 0x04; + *cp++ = 0x02; + + store_16_be(gss_mech_krb5->length + 2, cp); + cp += 2; + *cp++ = 0x06; + *cp++ = (gss_mech_krb5->length) & 0xFF; + memcpy(cp, gss_mech_krb5->elements, gss_mech_krb5->length); + cp += gss_mech_krb5->length; + + store_32_be(princlen, cp); + cp += 4; + memcpy(cp, princstr, princlen); + cp += princlen; + + store_32_be(attrs != NULL ? attrs->length : 0, cp); + cp += 4; + + if (attrs != NULL) { + memcpy(cp, attrs->data, attrs->length); + cp += attrs->length; + } + +cleanup: + krb5_free_unparsed_name(context, princstr); + krb5_free_data(context, attrs); + k5_mutex_unlock(&kname->lock); + krb5_free_context(context); + + return kg_map_name_error(minor_status, code); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/prf.c b/krb5-1.21.3/src/lib/gssapi/krb5/prf.c new file mode 100644 index 00000000..f87957bd --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/prf.c @@ -0,0 +1,139 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/prf.c */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "gssapiP_krb5.h" + +#ifndef MIN /* Usually found in . */ +#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) +#endif + +OM_uint32 KRB5_CALLCONV +krb5_gss_pseudo_random(OM_uint32 *minor_status, + gss_ctx_id_t context, + int prf_key, + const gss_buffer_t prf_in, + ssize_t desired_output_len, + gss_buffer_t prf_out) +{ + krb5_error_code code; + krb5_key key = NULL; + krb5_gss_ctx_id_t ctx; + int i; + OM_uint32 minor; + size_t prflen; + krb5_data t, ns; + unsigned char *p; + + prf_out->length = 0; + prf_out->value = NULL; + + t.length = 0; + t.data = NULL; + + ns.length = 0; + ns.data = NULL; + + ctx = (krb5_gss_ctx_id_t)context; + if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return GSS_S_NO_CONTEXT; + } + + switch (prf_key) { + case GSS_C_PRF_KEY_FULL: + if (ctx->have_acceptor_subkey) { + key = ctx->acceptor_subkey; + break; + } + /* fallthrough */ + case GSS_C_PRF_KEY_PARTIAL: + key = ctx->subkey; + break; + default: + code = EINVAL; + goto cleanup; + } + + if (key == NULL) { + code = EINVAL; + goto cleanup; + } + + if (desired_output_len == 0) + return GSS_S_COMPLETE; + + prf_out->value = gssalloc_malloc(desired_output_len); + if (prf_out->value == NULL) { + code = KG_INPUT_TOO_LONG; + goto cleanup; + } + prf_out->length = desired_output_len; + + code = krb5_c_prf_length(ctx->k5_context, + krb5_k_key_enctype(ctx->k5_context, key), + &prflen); + if (code != 0) + goto cleanup; + + ns.length = 4 + prf_in->length; + ns.data = k5alloc(ns.length, &code); + if (ns.data == NULL) { + code = KG_INPUT_TOO_LONG; + goto cleanup; + } + + t.length = prflen; + t.data = k5alloc(t.length, &code); + if (t.data == NULL) + goto cleanup; + + memcpy(ns.data + 4, prf_in->value, prf_in->length); + i = 0; + p = (unsigned char *)prf_out->value; + while (desired_output_len > 0) { + store_32_be(i, ns.data); + + code = krb5_k_prf(ctx->k5_context, key, &ns, &t); + if (code != 0) + goto cleanup; + + memcpy(p, t.data, MIN(t.length, desired_output_len)); + + p += t.length; + desired_output_len -= t.length; + i++; + } + +cleanup: + if (code != 0) + gss_release_buffer(&minor, prf_out); + krb5_free_data_contents(ctx->k5_context, &ns); + krb5_free_data_contents(ctx->k5_context, &t); + + *minor_status = (OM_uint32)code; + return (code == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/process_context_token.c b/krb5-1.21.3/src/lib/gssapi/krb5/process_context_token.c new file mode 100644 index 00000000..a672f48c --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/process_context_token.c @@ -0,0 +1,66 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "gssapiP_krb5.h" + +/* + * $Id$ + */ + +OM_uint32 KRB5_CALLCONV +krb5_gss_process_context_token(minor_status, context_handle, + token_buffer) + OM_uint32 *minor_status; + gss_ctx_id_t context_handle; + gss_buffer_t token_buffer; +{ + krb5_gss_ctx_id_rec *ctx; + OM_uint32 majerr; + + ctx = (krb5_gss_ctx_id_t) context_handle; + + if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } + + /* We only support context deletion tokens for now, and RFC 4121 does not + * define a context deletion token. */ + if (ctx->proto) { + *minor_status = 0; + return(GSS_S_DEFECTIVE_TOKEN); + } + + /* "unseal" the token */ + + if (GSS_ERROR(majerr = kg_unseal(minor_status, context_handle, + token_buffer, + GSS_C_NO_BUFFER, NULL, NULL, + KG_TOK_DEL_CTX))) + return(majerr); + + /* Mark the context as terminated, but do not delete it (as that would + * leave the caller with a dangling context handle). */ + ctx->terminated = 1; + return(GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/rel_cred.c b/krb5-1.21.3/src/lib/gssapi/krb5/rel_cred.c new file mode 100644 index 00000000..0da6c1b9 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/rel_cred.c @@ -0,0 +1,98 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "gssapiP_krb5.h" + +OM_uint32 KRB5_CALLCONV +krb5_gss_release_cred(minor_status, cred_handle) + OM_uint32 *minor_status; + gss_cred_id_t *cred_handle; +{ + krb5_context context; + krb5_gss_cred_id_t cred; + krb5_error_code code1, code2; + + code1 = krb5_gss_init_context(&context); + if (code1) { + *minor_status = code1; + return GSS_S_FAILURE; + } + + if (*cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + krb5_free_context(context); + return(GSS_S_COMPLETE); + } + + cred = (krb5_gss_cred_id_t)*cred_handle; + + k5_mutex_destroy(&cred->lock); + /* ignore error destroying mutex */ + + if (cred->ccache) { + if (cred->destroy_ccache) + code1 = krb5_cc_destroy(context, cred->ccache); + else + code1 = krb5_cc_close(context, cred->ccache); + } else + code1 = 0; + + if (cred->client_keytab) + krb5_kt_close(context, cred->client_keytab); + +#ifndef LEAN_CLIENT + if (cred->keytab) + code2 = krb5_kt_close(context, cred->keytab); + else +#endif /* LEAN_CLIENT */ + code2 = 0; + + if (cred->rcache) + k5_rc_close(context, cred->rcache); + if (cred->name) + kg_release_name(context, &cred->name); + + krb5_free_principal(context, cred->acceptor_mprinc); + krb5_free_principal(context, cred->impersonator); + + if (cred->req_enctypes) + free(cred->req_enctypes); + + if (cred->password != NULL) + zapfree(cred->password, strlen(cred->password)); + + xfree(cred); + + *cred_handle = NULL; + + *minor_status = 0; + if (code1) + *minor_status = code1; + if (code2) + *minor_status = code2; + + if (*minor_status) + save_error_info(*minor_status, context); + krb5_free_context(context); + return(*minor_status?GSS_S_FAILURE:GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/rel_name.c b/krb5-1.21.3/src/lib/gssapi/krb5/rel_name.c new file mode 100644 index 00000000..3dabe32f --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/rel_name.c @@ -0,0 +1,47 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "gssapiP_krb5.h" + +OM_uint32 KRB5_CALLCONV +krb5_gss_release_name(minor_status, input_name) + OM_uint32 *minor_status; + gss_name_t *input_name; +{ + krb5_context context; + krb5_error_code code; + + code = krb5_gss_init_context(&context); + if (code) { + *minor_status = code; + return GSS_S_FAILURE; + } + + kg_release_name(context, (krb5_gss_name_t *)input_name); + krb5_free_context(context); + + *input_name = (gss_name_t) NULL; + + *minor_status = 0; + return(GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/rel_oid.c b/krb5-1.21.3/src/lib/gssapi/krb5/rel_oid.c new file mode 100644 index 00000000..739efe46 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/rel_oid.c @@ -0,0 +1,78 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/rel_oid.c - Release an OID */ +/* + * Copyright 1995, 2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "gssapiP_krb5.h" + +OM_uint32 +krb5_gss_release_oid(minor_status, oid) + OM_uint32 *minor_status; + gss_OID *oid; +{ + /* + * The V2 API says the following! + * + * gss_release_oid[()] will recognize any of the GSSAPI's own OID values, + * and will silently ignore attempts to free these OIDs; for other OIDs + * it will call the C free() routine for both the OID data and the + * descriptor. This allows applications to freely mix their own heap- + * allocated OID values with OIDs returned by GSS-API. + */ + if (krb5_gss_internal_release_oid(minor_status, oid) != GSS_S_COMPLETE) { + /* Pawn it off on the generic routine */ + return(generic_gss_release_oid(minor_status, oid)); + } + else { + *oid = GSS_C_NO_OID; + *minor_status = 0; + return(GSS_S_COMPLETE); + } +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_internal_release_oid(minor_status, oid) + OM_uint32 *minor_status; + gss_OID *oid; +{ + /* + * This function only knows how to release internal OIDs. It will + * return GSS_S_CONTINUE_NEEDED for any OIDs it does not recognize. + */ + + *minor_status = 0; + if ((*oid != gss_mech_krb5) && + (*oid != gss_mech_krb5_old) && + (*oid != gss_mech_krb5_wrong) && + (*oid != gss_mech_iakerb) && + (*oid != gss_nt_krb5_name) && + (*oid != gss_nt_krb5_principal)) { + /* We don't know about this OID */ + return(GSS_S_CONTINUE_NEEDED); + } + else { + *oid = GSS_C_NO_OID; + return(GSS_S_COMPLETE); + } +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/s4u_gss_glue.c b/krb5-1.21.3/src/lib/gssapi/krb5/s4u_gss_glue.c new file mode 100644 index 00000000..fa7f980a --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/s4u_gss_glue.c @@ -0,0 +1,303 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +#include "k5-int.h" +#include "gssapiP_krb5.h" +#ifdef HAVE_MEMORY_H +#include +#endif +#include + +static int +kg_is_initiator_cred(krb5_gss_cred_id_t cred) +{ + return (cred->usage == GSS_C_INITIATE || cred->usage == GSS_C_BOTH) && + (cred->ccache != NULL); +} + +static OM_uint32 +kg_impersonate_name(OM_uint32 *minor_status, + const krb5_gss_cred_id_t impersonator_cred, + const krb5_gss_name_t user, + OM_uint32 time_req, + krb5_gss_cred_id_t *output_cred, + OM_uint32 *time_rec, + krb5_context context) +{ + OM_uint32 major_status; + krb5_error_code code; + krb5_creds in_creds, *out_creds = NULL; + krb5_data *subject_cert = NULL; + + *output_cred = NULL; + memset(&in_creds, 0, sizeof(in_creds)); + + if (user->is_cert) + subject_cert = user->princ->data; + else + in_creds.client = user->princ; + in_creds.server = impersonator_cred->name->princ; + + if (impersonator_cred->req_enctypes != NULL) + in_creds.keyblock.enctype = impersonator_cred->req_enctypes[0]; + + k5_mutex_lock(&user->lock); + + if (user->ad_context != NULL) { + code = krb5_authdata_export_authdata(context, + user->ad_context, + AD_USAGE_TGS_REQ, + &in_creds.authdata); + if (code != 0) { + k5_mutex_unlock(&user->lock); + *minor_status = code; + return GSS_S_FAILURE; + } + } + + k5_mutex_unlock(&user->lock); + + code = krb5_get_credentials_for_user(context, + KRB5_GC_CANONICALIZE | KRB5_GC_NO_STORE, + impersonator_cred->ccache, + &in_creds, subject_cert, &out_creds); + if (code != 0) { + krb5_free_authdata(context, in_creds.authdata); + *minor_status = code; + return GSS_S_FAILURE; + } + + major_status = kg_compose_deleg_cred(minor_status, + impersonator_cred, + out_creds, + time_req, + output_cred, + time_rec, + context); + + krb5_free_authdata(context, in_creds.authdata); + krb5_free_creds(context, out_creds); + + return major_status; +} + +/* The mechglue always passes null desired_mechs and actual_mechs. */ +OM_uint32 KRB5_CALLCONV +krb5_gss_acquire_cred_impersonate_name(OM_uint32 *minor_status, + const gss_cred_id_t impersonator_cred_handle, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + OM_uint32 major_status; + krb5_error_code code; + krb5_gss_cred_id_t imp_cred = (krb5_gss_cred_id_t)impersonator_cred_handle; + krb5_gss_cred_id_t cred; + krb5_context context; + + if (impersonator_cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (desired_name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (output_cred_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (cred_usage != GSS_C_INITIATE) { + *minor_status = (OM_uint32)G_BAD_USAGE; + return GSS_S_FAILURE; + } + + if (imp_cred->usage != GSS_C_INITIATE && imp_cred->usage != GSS_C_BOTH) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + + *output_cred_handle = GSS_C_NO_CREDENTIAL; + if (time_rec != NULL) + *time_rec = 0; + + code = krb5_gss_init_context(&context); + if (code != 0) { + *minor_status = code; + return GSS_S_FAILURE; + } + + major_status = kg_cred_resolve(minor_status, context, + impersonator_cred_handle, NULL); + if (GSS_ERROR(major_status)) { + krb5_free_context(context); + return major_status; + } + + major_status = kg_impersonate_name(minor_status, + imp_cred, + (krb5_gss_name_t)desired_name, + time_req, + &cred, + time_rec, + context); + + if (!GSS_ERROR(major_status)) + *output_cred_handle = (gss_cred_id_t)cred; + + k5_mutex_unlock(&imp_cred->lock); + krb5_free_context(context); + + return major_status; + +} + +/* + * Set up cred to be an S4U2Proxy credential by copying in the impersonator's + * creds, setting a cache config variable with the impersonator principal name, + * and saving the impersonator principal name in the cred structure. + */ +static krb5_error_code +make_proxy_cred(krb5_context context, krb5_gss_cred_id_t cred, + krb5_gss_cred_id_t impersonator_cred) +{ + krb5_error_code code; + krb5_data data; + char *str; + + code = krb5_cc_copy_creds(context, impersonator_cred->ccache, + cred->ccache); + if (code) + return code; + + code = krb5_unparse_name(context, impersonator_cred->name->princ, &str); + if (code) + return code; + + data = string2data(str); + code = krb5_cc_set_config(context, cred->ccache, NULL, + KRB5_CC_CONF_PROXY_IMPERSONATOR, &data); + krb5_free_unparsed_name(context, str); + if (code) + return code; + + return krb5_copy_principal(context, impersonator_cred->name->princ, + &cred->impersonator); +} + +OM_uint32 +kg_compose_deleg_cred(OM_uint32 *minor_status, + krb5_gss_cred_id_t impersonator_cred, + krb5_creds *subject_creds, + OM_uint32 time_req, + krb5_gss_cred_id_t *output_cred, + OM_uint32 *time_rec, + krb5_context context) +{ + OM_uint32 major_status; + krb5_error_code code; + krb5_gss_cred_id_t cred = NULL; + + *output_cred = NULL; + k5_mutex_assert_locked(&impersonator_cred->lock); + + if (!kg_is_initiator_cred(impersonator_cred) || + impersonator_cred->name == NULL || + impersonator_cred->impersonator != NULL) { + code = G_BAD_USAGE; + goto cleanup; + } + + assert(impersonator_cred->name->princ != NULL); + + assert(subject_creds != NULL); + assert(subject_creds->client != NULL); + + cred = xmalloc(sizeof(*cred)); + if (cred == NULL) { + code = ENOMEM; + goto cleanup; + } + memset(cred, 0, sizeof(*cred)); + + code = k5_mutex_init(&cred->lock); + if (code != 0) + goto cleanup; + + cred->usage = GSS_C_INITIATE; + + cred->expire = subject_creds->times.endtime; + + code = kg_init_name(context, subject_creds->client, NULL, NULL, NULL, 0, + &cred->name); + if (code != 0) + goto cleanup; + + code = krb5_cc_new_unique(context, "MEMORY", NULL, &cred->ccache); + if (code != 0) + goto cleanup; + cred->destroy_ccache = 1; + + code = krb5_cc_initialize(context, cred->ccache, subject_creds->client); + if (code != 0) + goto cleanup; + + code = make_proxy_cred(context, cred, impersonator_cred); + if (code != 0) + goto cleanup; + + code = krb5_cc_store_cred(context, cred->ccache, subject_creds); + if (code != 0) + goto cleanup; + + if (time_rec != NULL) { + krb5_timestamp now; + + code = krb5_timeofday(context, &now); + if (code != 0) + goto cleanup; + + *time_rec = ts_interval(now, cred->expire); + } + + major_status = GSS_S_COMPLETE; + *minor_status = 0; + *output_cred = cred; + +cleanup: + if (code != 0) { + *minor_status = code; + major_status = GSS_S_FAILURE; + } + + if (GSS_ERROR(major_status) && cred != NULL) { + k5_mutex_destroy(&cred->lock); + krb5_cc_destroy(context, cred->ccache); + kg_release_name(context, &cred->name); + xfree(cred); + } + + return major_status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/ser_sctx.c b/krb5-1.21.3/src/lib/gssapi/krb5/ser_sctx.c new file mode 100644 index 00000000..9e2d32e9 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/ser_sctx.c @@ -0,0 +1,698 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/ser_sctx.c - [De]serialization of security context */ +/* + * Copyright 1995, 2004, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "gssapiP_krb5.h" + +/* + * This module contains routines to [de]serialize + * krb5_gss_enc_desc and krb5_gss_ctx_id_t. + * XXX This whole serialization abstraction is unnecessary in a + * non-messaging environment, which krb5 is. Someday, this should + * all get redone without the extra level of indirection. I've done + * some of this work here, since adding new serializers is an internal + * krb5 interface, and I won't use those. There is some more + * deobfuscation (no longer anonymizing pointers, mostly) which could + * still be done. --marc + */ + +static krb5_error_code +kg_oid_externalize(gss_OID oid, krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code err; + + err = krb5_ser_pack_int32(KV5M_GSS_OID, buffer, lenremain); + if (err) + return err; + err = krb5_ser_pack_int32((krb5_int32) oid->length, + buffer, lenremain); + if (err) + return err; + err = krb5_ser_pack_bytes((krb5_octet *) oid->elements, + oid->length, buffer, lenremain); + if (err) + return err; + err = krb5_ser_pack_int32(KV5M_GSS_OID, buffer, lenremain); + return err; +} + +static krb5_error_code +kg_oid_internalize(gss_OID *argp, krb5_octet **buffer, size_t *lenremain) +{ + gss_OID oid; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + + bp = *buffer; + remain = *lenremain; + + /* Read in and check our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) + return (EINVAL); + + if (ibuf != KV5M_GSS_OID) + return (EINVAL); + + oid = (gss_OID) malloc(sizeof(gss_OID_desc)); + if (oid == NULL) + return ENOMEM; + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) { + free(oid); + return EINVAL; + } + oid->length = ibuf; + oid->elements = malloc((size_t)ibuf); + if (oid->elements == 0) { + free(oid); + return ENOMEM; + } + if (krb5_ser_unpack_bytes((krb5_octet *) oid->elements, + oid->length, &bp, &remain)) { + free(oid->elements); + free(oid); + return EINVAL; + } + + /* Read in and check our trailing magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) { + free(oid->elements); + free(oid); + return (EINVAL); + } + + if (ibuf != KV5M_GSS_OID) { + free(oid->elements); + free(oid); + return (EINVAL); + } + + *buffer = bp; + *lenremain = remain; + *argp = oid; + return 0; +} + +static krb5_error_code +kg_oid_size(gss_OID oid, size_t *sizep) +{ + krb5_error_code kret; + size_t required; + + kret = EINVAL; + if (oid != NULL) { + required = 2*sizeof(krb5_int32); /* For the header and trailer */ + required += sizeof(krb5_int32); + required += oid->length; + + kret = 0; + + *sizep += required; + } + + return(kret); +} + +static krb5_error_code +kg_seqstate_externalize(arg, buffer, lenremain) + g_seqnum_state arg; + krb5_octet **buffer; + size_t *lenremain; +{ + krb5_error_code err; + err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain); + if (err == 0) + err = g_seqstate_externalize(arg, buffer, lenremain); + if (err == 0) + err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain); + return err; +} + +static krb5_error_code +kg_seqstate_internalize(argp, buffer, lenremain) + g_seqnum_state *argp; + krb5_octet **buffer; + size_t *lenremain; +{ + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + krb5_error_code err; + + bp = *buffer; + remain = *lenremain; + + /* Read in and check our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) + return (EINVAL); + + if (ibuf != KV5M_GSS_QUEUE) + return (EINVAL); + + err = g_seqstate_internalize(argp, &bp, &remain); + if (err) + return err; + + /* Read in and check our trailing magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) { + g_seqstate_free(*argp); + return (EINVAL); + } + + if (ibuf != KV5M_GSS_QUEUE) { + g_seqstate_free(*argp); + return (EINVAL); + } + + *buffer = bp; + *lenremain = remain; + return 0; +} + +static krb5_error_code +kg_seqstate_size(arg, sizep) + g_seqnum_state arg; + size_t *sizep; +{ + krb5_error_code kret; + size_t required; + + kret = EINVAL; + if (arg) { + required = 2*sizeof(krb5_int32); /* For the header and trailer */ + g_seqstate_size(arg, &required); + + kret = 0; + *sizep += required; + } + return(kret); +} + +/* + * Determine the size required for this krb5_gss_ctx_id_rec. + */ +krb5_error_code +kg_ctx_size(krb5_context kcontext, krb5_gss_ctx_id_t ctx, size_t *sizep) +{ + krb5_error_code kret; + size_t required; + + /* + * krb5_gss_ctx_id_rec requires: + * krb5_int32 for KG_CONTEXT + * krb5_int32 for initiate. + * krb5_int32 for established. + * krb5_int32 for have_acceptor_subkey. + * krb5_int32 for seed_init. + * krb5_int32 for gss_flags. + * sizeof(seed) for seed + * ... for here + * ... for there + * ... for subkey + * krb5_int32 for signalg. + * krb5_int32 for cksum_size. + * krb5_int32 for sealalg. + * ... for enc + * ... for seq + * krb5_int32 for authtime. + * krb5_int32 for starttime. + * krb5_int32 for endtime. + * krb5_int32 for renew_till. + * krb5_int32 for flags. + * int64_t for seq_send. + * int64_t for seq_recv. + * ... for seqstate + * ... for auth_context + * ... for mech_used + * krb5_int32 for proto + * krb5_int32 for cksumtype + * ... for acceptor_subkey + * krb5_int32 for acceptor_key_cksumtype + * krb5_int32 for cred_rcache + * krb5_int32 for number of elements in authdata array + * ... for authdata array + * krb5_int32 for trailer. + */ + kret = EINVAL; + if (ctx != NULL) { + required = 21*sizeof(krb5_int32); + required += 2*sizeof(int64_t); + required += sizeof(ctx->seed); + + kret = 0; + if (!kret && ctx->here) + kret = k5_size_principal(ctx->here->princ, &required); + + if (!kret && ctx->there) + kret = k5_size_principal(ctx->there->princ, &required); + + if (!kret && ctx->subkey) + kret = k5_size_keyblock(&ctx->subkey->keyblock, &required); + + if (!kret && ctx->enc) + kret = k5_size_keyblock(&ctx->enc->keyblock, &required); + + if (!kret && ctx->seq) + kret = k5_size_keyblock(&ctx->seq->keyblock, &required); + + if (!kret) + kret = kg_oid_size(ctx->mech_used, &required); + + if (!kret && ctx->seqstate) + kret = kg_seqstate_size(ctx->seqstate, &required); + + if (!kret) + kret = k5_size_context(ctx->k5_context, &required); + if (!kret) + kret = k5_size_auth_context(ctx->auth_context, &required); + if (!kret && ctx->acceptor_subkey) + kret = k5_size_keyblock(&ctx->acceptor_subkey->keyblock, + &required); + if (!kret && ctx->authdata) { + krb5_int32 i; + + for (i = 0; !kret && ctx->authdata[i]; i++) + kret = k5_size_authdata(ctx->authdata[i], &required); + } + if (!kret) { + krb5_gss_name_t initiator_name; + + initiator_name = ctx->initiate ? ctx->here : ctx->there; + + if (initiator_name && initiator_name->ad_context) { + kret = k5_size_authdata_context(kcontext, + initiator_name->ad_context, + &required); + } + } + *sizep += required; + } + return(kret); +} + +/* + * Externalize this krb5_gss_ctx_id_ret. + */ +krb5_error_code +kg_ctx_externalize(krb5_context kcontext, krb5_gss_ctx_id_t ctx, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + size_t required; + krb5_octet *bp; + size_t remain; + krb5int_access kaccess; + + kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION); + if (kret) + return(kret); + + required = 0; + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + if (ctx != NULL) { + kret = ENOMEM; + if (!kg_ctx_size(kcontext, ctx, &required) && + (required <= remain)) { + /* Our identifier */ + (void) krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain); + + /* Now static data */ + (void) krb5_ser_pack_int32((krb5_int32) ctx->initiate, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->established, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->have_acceptor_subkey, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->seed_init, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->gss_flags, + &bp, &remain); + (void) krb5_ser_pack_bytes((krb5_octet *) ctx->seed, + sizeof(ctx->seed), + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->signalg, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->cksum_size, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->sealalg, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.authtime, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.starttime, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.endtime, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_times.renew_till, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) ctx->krb_flags, + &bp, &remain); + (void) (*kaccess.ser_pack_int64)((int64_t) ctx->seq_send, + &bp, &remain); + (void) (*kaccess.ser_pack_int64)((int64_t) ctx->seq_recv, + &bp, &remain); + + /* Now dynamic data */ + kret = 0; + + if (!kret && ctx->mech_used) + kret = kg_oid_externalize(ctx->mech_used, &bp, &remain); + + if (!kret && ctx->here) + kret = k5_externalize_principal(ctx->here->princ, + &bp, &remain); + + if (!kret && ctx->there) + kret = k5_externalize_principal(ctx->there->princ, + &bp, &remain); + + if (!kret && ctx->subkey) + kret = k5_externalize_keyblock(&ctx->subkey->keyblock, + &bp, &remain); + + if (!kret && ctx->enc) + kret = k5_externalize_keyblock(&ctx->enc->keyblock, + &bp, &remain); + + if (!kret && ctx->seq) + kret = k5_externalize_keyblock(&ctx->seq->keyblock, + &bp, &remain); + + if (!kret && ctx->seqstate) + kret = kg_seqstate_externalize(ctx->seqstate, &bp, &remain); + + if (!kret) + kret = k5_externalize_context(ctx->k5_context, &bp, &remain); + + if (!kret) + kret = k5_externalize_auth_context(ctx->auth_context, + &bp, &remain); + + if (!kret) + kret = krb5_ser_pack_int32((krb5_int32) ctx->proto, + &bp, &remain); + if (!kret) + kret = krb5_ser_pack_int32((krb5_int32) ctx->cksumtype, + &bp, &remain); + if (!kret && ctx->acceptor_subkey) + kret = k5_externalize_keyblock(&ctx->acceptor_subkey->keyblock, + &bp, &remain); + if (!kret) + kret = krb5_ser_pack_int32((krb5_int32) ctx->acceptor_subkey_cksumtype, + &bp, &remain); + + if (!kret) + kret = krb5_ser_pack_int32((krb5_int32) ctx->cred_rcache, + &bp, &remain); + if (!kret) { + krb5_int32 i = 0; + + if (ctx->authdata) { + for (; ctx->authdata[i]; i++) + ; + } + /* authdata count */ + kret = krb5_ser_pack_int32(i, &bp, &remain); + if (!kret && ctx->authdata) { + /* authdata */ + for (i = 0; !kret && ctx->authdata[i]; i++) + kret = k5_externalize_authdata(ctx->authdata[i], + &bp, &remain); + } + } + /* authdata context */ + if (!kret) { + krb5_gss_name_t initiator_name; + + initiator_name = ctx->initiate ? ctx->here : ctx->there; + + if (initiator_name && initiator_name->ad_context) { + kret = k5_externalize_authdata_context(kcontext, + initiator_name-> + ad_context, + &bp, &remain); + } + } + /* trailer */ + if (!kret) + kret = krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain); + if (!kret) { + *buffer = bp; + *lenremain = remain; + } + } + } + return(kret); +} + +/* Internalize a keyblock and convert it to a key. */ +static krb5_error_code +intern_key(krb5_key *key, krb5_octet **bp, size_t *sp) +{ + krb5_keyblock *keyblock; + krb5_error_code ret; + + ret = k5_internalize_keyblock(&keyblock, bp, sp); + if (ret != 0) + return ret; + ret = krb5_k_create_key(NULL, keyblock, key); + krb5_free_keyblock(NULL, keyblock); + return ret; +} + +/* + * Internalize this krb5_gss_ctx_id_t. + */ +krb5_error_code +kg_ctx_internalize(krb5_context kcontext, krb5_gss_ctx_id_t *argp, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + krb5_gss_ctx_id_rec *ctx; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + krb5int_access kaccess; + krb5_principal princ; + + kret = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION); + if (kret) + return(kret); + + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + princ = NULL; + /* Read our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) + ibuf = 0; + if (ibuf == KG_CONTEXT) { + kret = ENOMEM; + + /* Get a context */ + if ((remain >= (17*sizeof(krb5_int32) + + 2*sizeof(int64_t) + + sizeof(ctx->seed))) && + (ctx = (krb5_gss_ctx_id_rec *) + xmalloc(sizeof(krb5_gss_ctx_id_rec)))) { + memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec)); + + ctx->magic = ibuf; + + /* Get static data */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->initiate = (int) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->established = (int) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->have_acceptor_subkey = (int) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->seed_init = (int) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->gss_flags = (int) ibuf; + (void) krb5_ser_unpack_bytes((krb5_octet *) ctx->seed, + sizeof(ctx->seed), + &bp, &remain); + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->signalg = (int) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->cksum_size = (int) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->sealalg = (int) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->krb_times.authtime = (krb5_timestamp) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->krb_times.starttime = (krb5_timestamp) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->krb_times.endtime = (krb5_timestamp) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->krb_times.renew_till = (krb5_timestamp) ibuf; + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->krb_flags = (krb5_flags) ibuf; + (void) (*kaccess.ser_unpack_int64)((int64_t *)&ctx->seq_send, + &bp, &remain); + kret = (*kaccess.ser_unpack_int64)((int64_t *)&ctx->seq_recv, + &bp, &remain); + if (kret) { + free(ctx); + return kret; + } + + { + gss_OID tmp; + kret = kg_oid_internalize(&tmp, &bp, &remain); + if (kret == 0) + ctx->mech_used = tmp; + else if (kret == EINVAL) + kret = 0; + } + /* Now get substructure data */ + kret = k5_internalize_principal(&princ, &bp, &remain); + if (kret == 0) { + kret = kg_init_name(kcontext, princ, NULL, NULL, NULL, + KG_INIT_NAME_NO_COPY, &ctx->here); + if (kret) + krb5_free_principal(kcontext, princ); + } else if (kret == EINVAL) + kret = 0; + if (!kret) { + kret = k5_internalize_principal(&princ, &bp, &remain); + if (kret == 0) { + kret = kg_init_name(kcontext, princ, NULL, NULL, NULL, + KG_INIT_NAME_NO_COPY, &ctx->there); + if (kret) + krb5_free_principal(kcontext, princ); + } else if (kret == EINVAL) + kret = 0; + } + if (!kret && + (kret = intern_key(&ctx->subkey, &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + if (!kret && + (kret = intern_key(&ctx->enc, &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + if (!kret && + (kret = intern_key(&ctx->seq, &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + + if (!kret) { + kret = kg_seqstate_internalize(&ctx->seqstate, &bp, &remain); + if (kret == EINVAL) + kret = 0; + } + + if (!kret) + kret = k5_internalize_context(&ctx->k5_context, &bp, &remain); + + if (!kret) + kret = k5_internalize_auth_context(&ctx->auth_context, + &bp, &remain); + + if (!kret) + kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->proto = ibuf; + if (!kret) + kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->cksumtype = ibuf; + if (!kret && + (kret = intern_key(&ctx->acceptor_subkey, &bp, &remain))) { + if (kret == EINVAL) + kret = 0; + } + if (!kret) + kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->acceptor_subkey_cksumtype = ibuf; + if (!kret) + kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + ctx->cred_rcache = ibuf; + /* authdata */ + if (!kret) + kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + if (!kret) { + krb5_int32 nadata = ibuf, i; + + if (nadata > 0) { + ctx->authdata = (krb5_authdata **)calloc((size_t)nadata + 1, + sizeof(krb5_authdata *)); + if (ctx->authdata == NULL) { + kret = ENOMEM; + } else { + for (i = 0; !kret && i < nadata; i++) + kret = k5_internalize_authdata(&ctx->authdata[i], + &bp, &remain); + } + } + } + /* authdata context */ + if (!kret) { + krb5_gss_name_t initiator_name; + + initiator_name = ctx->initiate ? ctx->here : ctx->there; + if (initiator_name == NULL) { + kret = EINVAL; + } else { + kret = k5_internalize_authdata_context(kcontext, + &initiator_name-> + ad_context, + &bp, &remain); + if (kret == EINVAL) + kret = 0; + } + } + /* Get trailer */ + if (!kret) + kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + if (!kret && ibuf != KG_CONTEXT) + kret = EINVAL; + + if (!kret) { + *buffer = bp; + *lenremain = remain; + *argp = ctx; + } else { + if (ctx->seq) + krb5_k_free_key(kcontext, ctx->seq); + if (ctx->enc) + krb5_k_free_key(kcontext, ctx->enc); + if (ctx->subkey) + krb5_k_free_key(kcontext, ctx->subkey); + if (ctx->there) + kg_release_name(kcontext, &ctx->there); + if (ctx->here) + kg_release_name(kcontext, &ctx->here); + xfree(ctx); + } + } + } + return(kret); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/set_allowable_enctypes.c b/krb5-1.21.3/src/lib/gssapi/krb5/set_allowable_enctypes.c new file mode 100644 index 00000000..a74b161c --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/set_allowable_enctypes.c @@ -0,0 +1,122 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/set_allowable_enctypes.c */ +/* + * Copyright 2004 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * krb5_gss_set_allowable_enctypes() + */ + +/* + * gss_krb5_set_allowable_enctypes + * + * This function may be called by a context initiator after calling + * gss_acquire_cred(), but before calling gss_init_sec_context(), + * to restrict the set of enctypes which will be negotiated during + * context establishment to those in the provided array. + * + * 'cred_handle' must be a valid credential handle obtained via + * gss_acquire_cred(). It may not be GSS_C_NO_CREDENTIAL. + * gss_acquire_cred() may be called with GSS_C_NO_CREDENTIAL + * to get a handle to the default credential. + * + * The purpose of this function is to limit the keys that may + * be exported via gss_krb5_export_lucid_sec_context(); thus it + * should limit the enctypes of all keys that will be needed + * after the security context has been established. + * (i.e. context establishment may use a session key with a + * stronger enctype than in the provided array, however a + * subkey must be established within the enctype limits + * established by this function.) + * + */ + +#include "gssapiP_krb5.h" +#ifdef HAVE_STRING_H +#include +#else +#include +#endif +#include "gssapi_krb5.h" + +OM_uint32 +gss_krb5int_set_allowable_enctypes(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_oid, + const gss_buffer_t value) +{ + unsigned int i, j; + krb5_enctype * new_ktypes; + OM_uint32 major_status; + krb5_gss_cred_id_t cred; + krb5_error_code kerr = 0; + struct krb5_gss_set_allowable_enctypes_req *req; + + /* Assume a failure */ + *minor_status = 0; + major_status = GSS_S_FAILURE; + + assert(value->length == sizeof(*req)); + req = (struct krb5_gss_set_allowable_enctypes_req *)value->value; + + /* verify and valildate cred handle */ + cred = (krb5_gss_cred_id_t) *cred_handle; + + if (req->ktypes == NULL) { + k5_mutex_lock(&cred->lock); + if (cred->req_enctypes) + free(cred->req_enctypes); + cred->req_enctypes = NULL; + k5_mutex_unlock(&cred->lock); + return GSS_S_COMPLETE; + } + + /* Copy the requested enctypes into the cred structure. Filter out the + * ones we don't consider valid. Error out if no enctypes are valid. */ + new_ktypes = k5calloc(req->num_ktypes + 1, sizeof(*new_ktypes), &kerr); + if (new_ktypes == NULL) + goto error_out; + for (i = 0, j = 0; i < req->num_ktypes && req->ktypes[i]; i++) { + if (krb5_c_valid_enctype(req->ktypes[i])) + new_ktypes[j++] = req->ktypes[i]; + } + new_ktypes[j] = 0; + if (j == 0) { + free(new_ktypes); + kerr = KRB5_PROG_ETYPE_NOSUPP; + goto error_out; + } + k5_mutex_lock(&cred->lock); + if (cred->req_enctypes) + free(cred->req_enctypes); + cred->req_enctypes = new_ktypes; + k5_mutex_unlock(&cred->lock); + + /* Success! */ + return GSS_S_COMPLETE; + +error_out: + *minor_status = kerr; + return(major_status); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/set_ccache.c b/krb5-1.21.3/src/lib/gssapi/krb5/set_ccache.c new file mode 100644 index 00000000..91c3462b --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/set_ccache.c @@ -0,0 +1,87 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/set_ccache.c */ +/* + * Copyright 1999, 2003 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Set ccache name used by gssapi, and optionally obtain old ccache + * name. Caller must not free returned name. + */ + +#include +#include "gssapiP_krb5.h" + +OM_uint32 +gss_krb5int_ccache_name(OM_uint32 *minor_status, + const gss_OID desired_mech, + const gss_OID desired_object, + const gss_buffer_t value) +{ + OM_uint32 err = 0; + struct krb5_gss_ccache_name_req *req; + char *old_name, *cur_name = NULL; + + err = gss_krb5int_initialize_library(); + if (err) { + *minor_status = err; + return GSS_S_FAILURE; + } + + assert(value->length == sizeof(*req)); + + if (value->length != sizeof(*req)) + return GSS_S_FAILURE; + + req = (struct krb5_gss_ccache_name_req *)value->value; + + /* Our job is simple if the caller doesn't want the current name. */ + if (req->out_name == NULL) + return kg_set_ccache_name(minor_status, req->name); + + /* Fetch the current name and change it. */ + kg_get_ccache_name(&err, &cur_name); + if (err) + goto cleanup; + kg_set_ccache_name(&err, req->name); + if (err) + goto cleanup; + + /* Store the current name in a thread-specific variable. Free that + * variable's previous contents. */ + old_name = k5_getspecific(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME); + err = k5_setspecific(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME, cur_name); + if (err) + goto cleanup; + free(old_name); + + /* Give the caller an alias to the stored value. */ + *req->out_name = cur_name; + cur_name = NULL; + err = 0; + +cleanup: + free(cur_name); + *minor_status = err; + return (*minor_status == 0) ? GSS_S_COMPLETE : GSS_S_FAILURE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/store_cred.c b/krb5-1.21.3/src/lib/gssapi/krb5/store_cred.c new file mode 100644 index 00000000..1e168bc5 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/store_cred.c @@ -0,0 +1,223 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/krb5/store_cred.c */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "gssapiP_krb5.h" + +static OM_uint32 +copy_initiator_creds(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + const gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_const_key_value_set_t cred_store) +{ + OM_uint32 major_status; + krb5_error_code ret; + krb5_gss_cred_id_t kcred = NULL; + krb5_context context = NULL; + krb5_ccache cache = NULL, defcache = NULL, mcc = NULL; + krb5_principal princ = NULL; + krb5_boolean switch_to_cache = FALSE; + const char *ccache_name, *deftype; + + *minor_status = 0; + + ret = krb5_gss_init_context(&context); + if (ret) + goto kerr_cleanup; + + major_status = krb5_gss_validate_cred_1(minor_status, + input_cred_handle, + context); + if (GSS_ERROR(major_status)) + goto cleanup; + + kcred = (krb5_gss_cred_id_t)input_cred_handle; + + if (kcred->ccache == NULL) { + *minor_status = KG_CCACHE_NOMATCH; + major_status = GSS_S_DEFECTIVE_CREDENTIAL; + goto cleanup; + } + + major_status = kg_value_from_cred_store(cred_store, + KRB5_CS_CCACHE_URN, &ccache_name); + if (GSS_ERROR(major_status)) + goto cleanup; + + if (ccache_name != NULL) { + ret = krb5_cc_set_default_name(context, ccache_name); + if (ret) + goto kerr_cleanup; + } else { + major_status = kg_sync_ccache_name(context, minor_status); + if (major_status != GSS_S_COMPLETE) + goto cleanup; + } + + /* Resolve the default ccache and get its type. */ + ret = krb5_cc_default(context, &defcache); + if (ret) + goto kerr_cleanup; + deftype = krb5_cc_get_type(context, defcache); + + if (krb5_cc_support_switch(context, deftype)) { + /* Use an existing or new cache within the collection. */ + ret = krb5_cc_cache_match(context, kcred->name->princ, &cache); + if (!ret && !overwrite_cred) { + major_status = GSS_S_DUPLICATE_ELEMENT; + goto cleanup; + } + if (ret == KRB5_CC_NOTFOUND) + ret = krb5_cc_new_unique(context, deftype, NULL, &cache); + if (ret) + goto kerr_cleanup; + switch_to_cache = default_cred; + } else { + /* Use the default cache. */ + cache = defcache; + defcache = NULL; + ret = krb5_cc_get_principal(context, cache, &princ); + krb5_free_principal(context, princ); + if (!ret && !overwrite_cred) { + major_status = GSS_S_DUPLICATE_ELEMENT; + goto cleanup; + } + } + + ret = krb5_cc_new_unique(context, "MEMORY", NULL, &mcc); + if (ret) + goto kerr_cleanup; + ret = krb5_cc_initialize(context, mcc, kcred->name->princ); + if (ret) + goto kerr_cleanup; + ret = krb5_cc_copy_creds(context, kcred->ccache, mcc); + if (ret) + goto kerr_cleanup; + ret = krb5_cc_move(context, mcc, cache); + if (ret) + goto kerr_cleanup; + mcc = NULL; + + if (switch_to_cache) { + ret = krb5_cc_switch(context, cache); + if (ret) + goto kerr_cleanup; + } + + *minor_status = 0; + major_status = GSS_S_COMPLETE; + +cleanup: + if (kcred != NULL) + k5_mutex_unlock(&kcred->lock); + if (defcache != NULL) + krb5_cc_close(context, defcache); + if (cache != NULL) + krb5_cc_close(context, cache); + if (mcc != NULL) + krb5_cc_destroy(context, mcc); + krb5_free_context(context); + + return major_status; + +kerr_cleanup: + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto cleanup; +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_store_cred(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + gss_cred_usage_t cred_usage, + const gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored) +{ + return krb5_gss_store_cred_into(minor_status, input_cred_handle, + cred_usage, desired_mech, + overwrite_cred, default_cred, + GSS_C_NO_CRED_STORE, + elements_stored, cred_usage_stored); +} + +OM_uint32 KRB5_CALLCONV +krb5_gss_store_cred_into(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + gss_cred_usage_t cred_usage, + const gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_const_key_value_set_t cred_store, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored) +{ + OM_uint32 major_status; + gss_cred_usage_t actual_usage; + OM_uint32 lifetime; + + if (input_cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_NO_CRED; + + major_status = GSS_S_FAILURE; + + if (cred_usage == GSS_C_ACCEPT) { + *minor_status = G_STORE_ACCEPTOR_CRED_NOSUPP; + return GSS_S_FAILURE; + } else if (cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) { + *minor_status = G_BAD_USAGE; + return GSS_S_FAILURE; + } + + major_status = krb5_gss_inquire_cred(minor_status, input_cred_handle, + NULL, &lifetime, + &actual_usage, elements_stored); + if (GSS_ERROR(major_status)) + return major_status; + + if (lifetime == 0) + return GSS_S_CREDENTIALS_EXPIRED; + + if (actual_usage != GSS_C_INITIATE && actual_usage != GSS_C_BOTH) { + *minor_status = G_STORE_ACCEPTOR_CRED_NOSUPP; + return GSS_S_FAILURE; + } + + major_status = copy_initiator_creds(minor_status, input_cred_handle, + desired_mech, overwrite_cred, + default_cred, cred_store); + if (GSS_ERROR(major_status)) + return major_status; + + if (cred_usage_stored != NULL) + *cred_usage_stored = GSS_C_INITIATE; + + return GSS_S_COMPLETE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/util_cksum.c b/krb5-1.21.3/src/lib/gssapi/krb5/util_cksum.c new file mode 100644 index 00000000..5b879563 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/util_cksum.c @@ -0,0 +1,270 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "gssapiP_krb5.h" +#ifdef HAVE_MEMORY_H +#include +#endif + +/* Checksumming the channel bindings always uses plain MD5. */ +krb5_error_code +kg_checksum_channel_bindings(context, cb, cksum) + krb5_context context; + gss_channel_bindings_t cb; + krb5_checksum *cksum; +{ + struct k5buf buf; + size_t sumlen; + krb5_data plaind; + krb5_error_code code; + + /* initialize the the cksum */ + code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &sumlen); + if (code) + return(code); + + cksum->checksum_type = CKSUMTYPE_RSA_MD5; + cksum->length = sumlen; + cksum->magic = KV5M_CHECKSUM; + + /* generate a buffer full of zeros if no cb specified */ + + if (cb == GSS_C_NO_CHANNEL_BINDINGS) { + if ((cksum->contents = (krb5_octet *) xmalloc(cksum->length)) == NULL) { + return(ENOMEM); + } + memset(cksum->contents, '\0', cksum->length); + return(0); + } + + k5_buf_init_dynamic(&buf); + k5_buf_add_uint32_le(&buf, cb->initiator_addrtype); + k5_buf_add_uint32_le(&buf, cb->initiator_address.length); + k5_buf_add_len(&buf, cb->initiator_address.value, + cb->initiator_address.length); + k5_buf_add_uint32_le(&buf, cb->acceptor_addrtype); + k5_buf_add_uint32_le(&buf, cb->acceptor_address.length); + k5_buf_add_len(&buf, cb->acceptor_address.value, + cb->acceptor_address.length); + k5_buf_add_uint32_le(&buf, cb->application_data.length); + k5_buf_add_len(&buf, cb->application_data.value, + cb->application_data.length); + code = k5_buf_status(&buf); + if (code) + return code; + + /* checksum the data */ + + plaind = make_data(buf.data, buf.len); + code = krb5_c_make_checksum(context, CKSUMTYPE_RSA_MD5, 0, 0, + &plaind, cksum); + k5_buf_free(&buf); + return code; +} + +krb5_error_code +kg_make_checksum_iov_v1(krb5_context context, + krb5_cksumtype type, + size_t cksum_len, + krb5_key seq, + krb5_key enc, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype, + krb5_checksum *checksum) +{ + krb5_error_code code; + gss_iov_buffer_desc *header; + krb5_crypto_iov *kiov; + int i = 0, j; + size_t conf_len = 0, token_header_len; + + header = kg_locate_header_iov(iov, iov_count, toktype); + assert(header != NULL); + + kiov = calloc(iov_count + 3, sizeof(krb5_crypto_iov)); + if (kiov == NULL) + return ENOMEM; + + /* Checksum over ( Header | Confounder | Data | Pad ) */ + if (toktype == KG_TOK_WRAP_MSG) + conf_len = kg_confounder_size(context, enc->keyblock.enctype); + + /* Checksum output */ + kiov[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + kiov[i].data.length = checksum->length; + kiov[i].data.data = xmalloc(checksum->length); + if (kiov[i].data.data == NULL) { + xfree(kiov); + return ENOMEM; + } + i++; + + /* Header | SND_SEQ | SGN_CKSUM | Confounder */ + token_header_len = 16 + cksum_len + conf_len; + + /* Header (calculate from end because of variable length ASN.1 header) */ + kiov[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + kiov[i].data.length = 8; + kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - token_header_len; + i++; + + /* Confounder */ + if (toktype == KG_TOK_WRAP_MSG) { + kiov[i].flags = KRB5_CRYPTO_TYPE_DATA; + kiov[i].data.length = conf_len; + kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - conf_len; + i++; + } + + for (j = 0; j < iov_count; j++) { + kiov[i].flags = kg_translate_flag_iov(iov[j].type); + kiov[i].data.length = iov[j].buffer.length; + kiov[i].data.data = (char *)iov[j].buffer.value; + i++; + } + + code = krb5_k_make_checksum_iov(context, type, seq, sign_usage, kiov, i); + if (code == 0) { + checksum->length = kiov[0].data.length; + checksum->contents = (unsigned char *)kiov[0].data.data; + } else + free(kiov[0].data.data); + + xfree(kiov); + + return code; +} + +static krb5_error_code +checksum_iov_v3(krb5_context context, + krb5_cksumtype type, + size_t rrc, + krb5_key key, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype, + krb5_boolean verify, + krb5_boolean *valid) +{ + krb5_error_code code; + gss_iov_buffer_desc *header; + gss_iov_buffer_desc *trailer; + krb5_crypto_iov *kiov; + size_t kiov_count; + int i = 0, j; + unsigned int k5_checksumlen; + + if (verify) + *valid = FALSE; + + code = krb5_c_crypto_length(context, key->keyblock.enctype, KRB5_CRYPTO_TYPE_CHECKSUM, &k5_checksumlen); + if (code != 0) + return code; + + header = kg_locate_header_iov(iov, iov_count, toktype); + assert(header != NULL); + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + assert(rrc != 0 || trailer != NULL); + + if (trailer == NULL) { + if (rrc != k5_checksumlen) + return KRB5_BAD_MSIZE; + if (header->buffer.length != 16 + k5_checksumlen) + return KRB5_BAD_MSIZE; + } else if (trailer->buffer.length != k5_checksumlen) + return KRB5_BAD_MSIZE; + + kiov_count = 2 + iov_count; + kiov = (krb5_crypto_iov *)xmalloc(kiov_count * sizeof(krb5_crypto_iov)); + if (kiov == NULL) + return ENOMEM; + + /* Checksum over ( Data | Header ) */ + + /* Data */ + for (j = 0; j < iov_count; j++) { + kiov[i].flags = kg_translate_flag_iov(iov[j].type); + kiov[i].data.length = iov[j].buffer.length; + kiov[i].data.data = (char *)iov[j].buffer.value; + i++; + } + + /* Header */ + kiov[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + kiov[i].data.length = 16; + kiov[i].data.data = (char *)header->buffer.value; + i++; + + /* Checksum */ + kiov[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + if (trailer == NULL) { + kiov[i].data.length = header->buffer.length - 16; + kiov[i].data.data = (char *)header->buffer.value + 16; + } else { + kiov[i].data.length = trailer->buffer.length; + kiov[i].data.data = (char *)trailer->buffer.value; + } + i++; + + if (verify) + code = krb5_k_verify_checksum_iov(context, type, key, sign_usage, kiov, kiov_count, valid); + else + code = krb5_k_make_checksum_iov(context, type, key, sign_usage, kiov, kiov_count); + + xfree(kiov); + + return code; +} + +krb5_error_code +kg_make_checksum_iov_v3(krb5_context context, + krb5_cksumtype type, + size_t rrc, + krb5_key key, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype) +{ + return checksum_iov_v3(context, type, rrc, key, + sign_usage, iov, iov_count, toktype, 0, NULL); +} + +krb5_error_code +kg_verify_checksum_iov_v3(krb5_context context, + krb5_cksumtype type, + size_t rrc, + krb5_key key, + krb5_keyusage sign_usage, + gss_iov_buffer_desc *iov, + int iov_count, + int toktype, + krb5_boolean *valid) +{ + return checksum_iov_v3(context, type, rrc, key, + sign_usage, iov, iov_count, toktype, 1, valid); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/util_crypt.c b/krb5-1.21.3/src/lib/gssapi/krb5/util_crypt.c new file mode 100644 index 00000000..84f19498 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/util_crypt.c @@ -0,0 +1,738 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2001, 2008 by the Massachusetts Institute of Technology. + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" +#include "gssapiP_krb5.h" +#ifdef HAVE_MEMORY_H +#include +#endif + +static krb5_error_code +kg_copy_keys(krb5_context context, krb5_gss_ctx_id_rec *ctx, krb5_key subkey) +{ + krb5_error_code code; + + krb5_k_free_key(context, ctx->enc); + ctx->enc = NULL; + code = krb5_k_create_key(context, &subkey->keyblock, &ctx->enc); + if (code != 0) + return code; + + krb5_k_free_key(context, ctx->seq); + ctx->seq = NULL; + code = krb5_k_create_key(context, &subkey->keyblock, &ctx->seq); + if (code != 0) + return code; + + return 0; +} + +krb5_error_code +kg_setup_keys(krb5_context context, krb5_gss_ctx_id_rec *ctx, krb5_key subkey, + krb5_cksumtype *cksumtype) +{ + krb5_error_code code; + + assert(ctx != NULL); + assert(subkey != NULL); + + *cksumtype = 0; + ctx->proto = 0; + + if (ctx->enc == NULL) { + ctx->signalg = -1; + ctx->sealalg = -1; + } + + code = krb5int_c_mandatory_cksumtype(context, subkey->keyblock.enctype, + cksumtype); + if (code != 0) + return code; + + switch (subkey->keyblock.enctype) { + case ENCTYPE_DES3_CBC_SHA1: + code = kg_copy_keys(context, ctx, subkey); + if (code != 0) + return code; + + ctx->enc->keyblock.enctype = ENCTYPE_DES3_CBC_RAW; + ctx->seq->keyblock.enctype = ENCTYPE_DES3_CBC_RAW; + ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD; + ctx->cksum_size = 20; + ctx->sealalg = SEAL_ALG_DES3KD; + break; + case ENCTYPE_ARCFOUR_HMAC: + case ENCTYPE_ARCFOUR_HMAC_EXP: + /* RFC 4121 accidentally omits RC4-HMAC-EXP as a "not-newer" enctype, + * even though RFC 4757 treats it as one. */ + code = kg_copy_keys(context, ctx, subkey); + if (code != 0) + return code; + + ctx->signalg = SGN_ALG_HMAC_MD5; + ctx->cksum_size = 8; + ctx->sealalg = SEAL_ALG_MICROSOFT_RC4; + break; + default: + ctx->proto = 1; + break; + } + + return 0; +} + +int +kg_confounder_size(krb5_context context, krb5_enctype enctype) +{ + krb5_error_code code; + size_t blocksize; + /* We special case rc4*/ + if (enctype == ENCTYPE_ARCFOUR_HMAC || enctype == ENCTYPE_ARCFOUR_HMAC_EXP) + return 8; + code = krb5_c_block_size(context, enctype, &blocksize); + if (code) + return(-1); /* XXX */ + + return(blocksize); +} + +krb5_error_code +kg_make_confounder(krb5_context context, krb5_enctype enctype, + unsigned char *buf) +{ + int confsize; + krb5_data lrandom; + + confsize = kg_confounder_size(context, enctype); + if (confsize < 0) + return KRB5_BAD_MSIZE; + + lrandom.length = confsize; + lrandom.data = (char *)buf; + + return(krb5_c_random_make_octets(context, &lrandom)); +} + +/* Set *data_out to a krb5_data structure containing iv, or to NULL if iv is + * NULL. */ +static krb5_error_code +iv_to_state(krb5_context context, krb5_key key, krb5_pointer iv, + krb5_data **data_out) +{ + krb5_error_code code; + krb5_data *data; + size_t blocksize; + + *data_out = NULL; + if (iv == NULL) + return 0; + + code = krb5_c_block_size(context, key->keyblock.enctype, &blocksize); + if (code) + return code; + + data = k5alloc(sizeof(*data), &code); + if (data == NULL) + return code; + code = alloc_data(data, blocksize); + if (code) { + free(data); + return code; + } + memcpy(data->data, iv, blocksize); + *data_out = data; + return 0; +} + +krb5_error_code +kg_encrypt(krb5_context context, krb5_key key, int usage, krb5_pointer iv, + krb5_const_pointer in, krb5_pointer out, unsigned int length) +{ + krb5_error_code code; + krb5_data *state, inputd; + krb5_enc_data outputd; + + code = iv_to_state(context, key, iv, &state); + if (code) + return code; + + inputd.length = length; + inputd.data = (char *)in; + + outputd.ciphertext.length = length; + outputd.ciphertext.data = out; + + code = krb5_k_encrypt(context, key, usage, state, &inputd, &outputd); + krb5_free_data(context, state); + return code; +} + +krb5_error_code +kg_encrypt_inplace(krb5_context context, krb5_key key, int usage, + krb5_pointer iv, krb5_pointer ptr, unsigned int length) +{ + krb5_error_code code; + krb5_crypto_iov iov; + krb5_data *state; + + code = iv_to_state(context, key, iv, &state); + if (code) + return code; + + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data((void *)ptr, length); + code = krb5_k_encrypt_iov(context, key, usage, state, &iov, 1); + krb5_free_data(context, state); + return code; +} + +/* length is the length of the cleartext. */ + +krb5_error_code +kg_decrypt(krb5_context context, krb5_key key, int usage, krb5_pointer iv, + krb5_const_pointer in, krb5_pointer out, unsigned int length) +{ + krb5_error_code code; + krb5_data *state, outputd; + krb5_enc_data inputd; + + code = iv_to_state(context, key, iv, &state); + if (code) + return code; + + inputd.enctype = ENCTYPE_UNKNOWN; + inputd.ciphertext.length = length; + inputd.ciphertext.data = (char *)in; + + outputd.length = length; + outputd.data = out; + + code = krb5_k_decrypt(context, key, usage, state, &inputd, &outputd); + krb5_free_data(context, state); + return code; +} + +krb5_error_code +kg_arcfour_docrypt(const krb5_keyblock *keyblock, int usage, + const unsigned char *kd_data, size_t kd_data_len, + const unsigned char *input_buf, size_t input_len, + unsigned char *output_buf) +{ + krb5_data kd = make_data((char *) kd_data, kd_data_len); + krb5_crypto_iov kiov; + + memcpy(output_buf, input_buf, input_len); + kiov.flags = KRB5_CRYPTO_TYPE_DATA; + kiov.data = make_data(output_buf, input_len); + return krb5int_arcfour_gsscrypt(keyblock, usage, &kd, &kiov, 1); +} + +/* AEAD */ +static krb5_error_code +kg_translate_iov_v1(krb5_context context, krb5_enctype enctype, + gss_iov_buffer_desc *iov, int iov_count, + krb5_crypto_iov **pkiov, size_t *pkiov_count) +{ + gss_iov_buffer_desc *header; + gss_iov_buffer_desc *trailer; + int i = 0, j; + size_t kiov_count; + krb5_crypto_iov *kiov; + size_t conf_len; + + *pkiov = NULL; + *pkiov_count = 0; + + conf_len = kg_confounder_size(context, enctype); + + header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + assert(header != NULL); + + if (header->buffer.length < conf_len) + return KRB5_BAD_MSIZE; + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + assert(trailer == NULL || trailer->buffer.length == 0); + + kiov_count = 3 + iov_count; + kiov = (krb5_crypto_iov *)malloc(kiov_count * sizeof(krb5_crypto_iov)); + if (kiov == NULL) + return ENOMEM; + + /* For pre-CFX (raw enctypes) there is no krb5 header */ + kiov[i].flags = KRB5_CRYPTO_TYPE_HEADER; + kiov[i].data.length = 0; + kiov[i].data.data = NULL; + i++; + + /* For pre-CFX, the confounder is at the end of the GSS header */ + kiov[i].flags = KRB5_CRYPTO_TYPE_DATA; + kiov[i].data.length = conf_len; + kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - conf_len; + i++; + + for (j = 0; j < iov_count; j++) { + kiov[i].flags = kg_translate_flag_iov(iov[j].type); + if (kiov[i].flags == KRB5_CRYPTO_TYPE_EMPTY) + continue; + + kiov[i].data.length = iov[j].buffer.length; + kiov[i].data.data = (char *)iov[j].buffer.value; + i++; + } + + kiov[i].flags = KRB5_CRYPTO_TYPE_TRAILER; + kiov[i].data.length = 0; + kiov[i].data.data = NULL; + i++; + + *pkiov = kiov; + *pkiov_count = i; + + return 0; +} + +/* + * DCE_STYLE indicates actual RRC is EC + RRC + * EC is extra rotate count for DCE_STYLE, pad length otherwise + * RRC is rotate count. + */ +static krb5_error_code +kg_translate_iov_v3(krb5_context context, int dce_style, size_t ec, size_t rrc, + krb5_enctype enctype, gss_iov_buffer_desc *iov, + int iov_count, krb5_crypto_iov **pkiov, + size_t *pkiov_count) +{ + gss_iov_buffer_t header; + gss_iov_buffer_t trailer; + int i = 0, j; + size_t kiov_count; + krb5_crypto_iov *kiov; + unsigned int k5_headerlen = 0, k5_trailerlen = 0; + size_t gss_headerlen, gss_trailerlen; + krb5_error_code code; + + *pkiov = NULL; + *pkiov_count = 0; + + header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); + assert(header != NULL); + + trailer = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER); + assert(trailer == NULL || rrc == 0); + + code = krb5_c_crypto_length(context, enctype, KRB5_CRYPTO_TYPE_HEADER, + &k5_headerlen); + if (code != 0) + return code; + + code = krb5_c_crypto_length(context, enctype, KRB5_CRYPTO_TYPE_TRAILER, + &k5_trailerlen); + if (code != 0) + return code; + + /* Check header and trailer sizes */ + gss_headerlen = 16 /* GSS-Header */ + k5_headerlen; /* Kerb-Header */ + gss_trailerlen = ec + 16 /* E(GSS-Header) */ + k5_trailerlen; /* Kerb-Trailer */ + + /* If we're caller without a trailer, we must rotate by trailer length */ + if (trailer == NULL) { + size_t actual_rrc = rrc; + + if (dce_style) + actual_rrc += ec; /* compensate for Windows bug */ + + if (actual_rrc != gss_trailerlen) + return KRB5_BAD_MSIZE; + + gss_headerlen += gss_trailerlen; + gss_trailerlen = 0; + } else { + if (trailer->buffer.length != gss_trailerlen) + return KRB5_BAD_MSIZE; + } + + if (header->buffer.length != gss_headerlen) + return KRB5_BAD_MSIZE; + + kiov_count = 3 + iov_count; + kiov = (krb5_crypto_iov *)malloc(kiov_count * sizeof(krb5_crypto_iov)); + if (kiov == NULL) + return ENOMEM; + + /* + * The krb5 header is located at the end of the GSS header. + */ + kiov[i].flags = KRB5_CRYPTO_TYPE_HEADER; + kiov[i].data.length = k5_headerlen; + kiov[i].data.data = (char *)header->buffer.value + header->buffer.length - k5_headerlen; + i++; + + for (j = 0; j < iov_count; j++) { + kiov[i].flags = kg_translate_flag_iov(iov[j].type); + if (kiov[i].flags == KRB5_CRYPTO_TYPE_EMPTY) + continue; + + kiov[i].data.length = iov[j].buffer.length; + kiov[i].data.data = (char *)iov[j].buffer.value; + i++; + } + + /* + * The EC and encrypted GSS header are placed in the trailer, which may + * be rotated directly after the plaintext header if no trailer buffer + * is provided. + */ + kiov[i].flags = KRB5_CRYPTO_TYPE_DATA; + kiov[i].data.length = ec + 16; /* E(Header) */ + if (trailer == NULL) + kiov[i].data.data = (char *)header->buffer.value + 16; + else + kiov[i].data.data = (char *)trailer->buffer.value; + i++; + + /* + * The krb5 trailer is placed after the encrypted copy of the + * krb5 header (which may be in the GSS header or trailer). + */ + kiov[i].flags = KRB5_CRYPTO_TYPE_TRAILER; + kiov[i].data.length = k5_trailerlen; + kiov[i].data.data = kiov[i - 1].data.data + ec + 16; /* E(Header) */ + i++; + + *pkiov = kiov; + *pkiov_count = i; + + return 0; +} + +/* PROTO is 1 if CFX, 0 if pre-CFX */ +static krb5_error_code +kg_translate_iov(krb5_context context, int proto, int dce_style, size_t ec, + size_t rrc, krb5_enctype enctype, gss_iov_buffer_desc *iov, + int iov_count, krb5_crypto_iov **pkiov, size_t *pkiov_count) +{ + return proto ? + kg_translate_iov_v3(context, dce_style, ec, rrc, enctype, + iov, iov_count, pkiov, pkiov_count) : + kg_translate_iov_v1(context, enctype, iov, iov_count, + pkiov, pkiov_count); +} + +krb5_error_code +kg_encrypt_iov(krb5_context context, int proto, int dce_style, size_t ec, + size_t rrc, krb5_key key, int usage, krb5_pointer iv, + gss_iov_buffer_desc *iov, int iov_count) +{ + krb5_error_code code; + krb5_data *state; + size_t kiov_len; + krb5_crypto_iov *kiov; + + code = iv_to_state(context, key, iv, &state); + if (code) + return code; + + code = kg_translate_iov(context, proto, dce_style, ec, rrc, + key->keyblock.enctype, iov, iov_count, + &kiov, &kiov_len); + if (code == 0) { + code = krb5_k_encrypt_iov(context, key, usage, state, kiov, kiov_len); + free(kiov); + } + + krb5_free_data(context, state); + return code; +} + +/* length is the length of the cleartext. */ + +krb5_error_code +kg_decrypt_iov(krb5_context context, int proto, int dce_style, size_t ec, + size_t rrc, krb5_key key, int usage, krb5_pointer iv, + gss_iov_buffer_desc *iov, int iov_count) +{ + krb5_error_code code; + krb5_data *state; + size_t kiov_len; + krb5_crypto_iov *kiov; + + code = iv_to_state(context, key, iv, &state); + if (code) + return code; + + code = kg_translate_iov(context, proto, dce_style, ec, rrc, + key->keyblock.enctype, iov, iov_count, + &kiov, &kiov_len); + if (code == 0) { + code = krb5_k_decrypt_iov(context, key, usage, state, kiov, kiov_len); + free(kiov); + } + + krb5_free_data(context, state); + return code; +} + +krb5_error_code +kg_arcfour_docrypt_iov(krb5_context context, const krb5_keyblock *keyblock, + int usage, const unsigned char *kd_data, + size_t kd_data_len, gss_iov_buffer_desc *iov, + int iov_count) +{ + krb5_error_code code; + krb5_data kd = make_data((char *) kd_data, kd_data_len); + krb5_crypto_iov *kiov = NULL; + size_t kiov_len = 0; + + code = kg_translate_iov(context, 0 /* proto */, 0 /* dce_style */, + 0 /* ec */, 0 /* rrc */, keyblock->enctype, + iov, iov_count, &kiov, &kiov_len); + if (code) + return code; + code = krb5int_arcfour_gsscrypt(keyblock, usage, &kd, kiov, kiov_len); + free(kiov); + return code; +} + +krb5_cryptotype +kg_translate_flag_iov(OM_uint32 type) +{ + krb5_cryptotype ktype; + + switch (GSS_IOV_BUFFER_TYPE(type)) { + case GSS_IOV_BUFFER_TYPE_DATA: + case GSS_IOV_BUFFER_TYPE_PADDING: + ktype = KRB5_CRYPTO_TYPE_DATA; + break; + case GSS_IOV_BUFFER_TYPE_SIGN_ONLY: + ktype = KRB5_CRYPTO_TYPE_SIGN_ONLY; + break; + default: + ktype = KRB5_CRYPTO_TYPE_EMPTY; + break; + } + + return ktype; +} + +gss_iov_buffer_t +kg_locate_iov(gss_iov_buffer_desc *iov, int iov_count, OM_uint32 type) +{ + int i; + gss_iov_buffer_t p = GSS_C_NO_IOV_BUFFER; + + if (iov == GSS_C_NO_IOV_BUFFER) + return GSS_C_NO_IOV_BUFFER; + + for (i = iov_count - 1; i >= 0; i--) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == type) { + if (p == GSS_C_NO_IOV_BUFFER) + p = &iov[i]; + else + return GSS_C_NO_IOV_BUFFER; + } + } + + return p; +} + +/* Return the IOV where the GSSAPI token header should be placed (and possibly + * the checksum as well, depending on the token type). */ +gss_iov_buffer_t +kg_locate_header_iov(gss_iov_buffer_desc *iov, int iov_count, int toktype) +{ + if (toktype == KG_TOK_MIC_MSG) + return kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_MIC_TOKEN); + else + return kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); +} + +void +kg_iov_msglen(gss_iov_buffer_desc *iov, int iov_count, size_t *data_length_p, + size_t *assoc_data_length_p) +{ + int i; + size_t data_length = 0, assoc_data_length = 0; + + assert(iov != GSS_C_NO_IOV_BUFFER); + + *data_length_p = *assoc_data_length_p = 0; + + for (i = 0; i < iov_count; i++) { + OM_uint32 type = GSS_IOV_BUFFER_TYPE(iov[i].type); + + if (type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY) + assoc_data_length += iov[i].buffer.length; + + if (type == GSS_IOV_BUFFER_TYPE_DATA || + type == GSS_IOV_BUFFER_TYPE_SIGN_ONLY) + data_length += iov[i].buffer.length; + } + + *data_length_p = data_length; + *assoc_data_length_p = assoc_data_length; +} + +void +kg_release_iov(gss_iov_buffer_desc *iov, int iov_count) +{ + int i; + + assert(iov != GSS_C_NO_IOV_BUFFER); + + for (i = 0; i < iov_count; i++) { + if (iov[i].type & GSS_IOV_BUFFER_FLAG_ALLOCATED) { + gssalloc_free(iov[i].buffer.value); + iov[i].buffer.length = 0; + iov[i].buffer.value = NULL; + iov[i].type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED); + } + } +} + +OM_uint32 +kg_fixup_padding_iov(OM_uint32 *minor_status, gss_iov_buffer_desc *iov, + int iov_count) +{ + gss_iov_buffer_t padding = NULL; + gss_iov_buffer_t data = NULL; + size_t padlength, relative_padlength; + unsigned char *p; + + data = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_DATA); + padding = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING); + + /* Do nothing if padding is absent or empty, to allow unwrapping of WinRM + * unpadded RC4 tokens using an explicit IOV array. */ + if (data == NULL || padding == NULL || padding->buffer.length == 0) { + *minor_status = 0; + return GSS_S_COMPLETE; + } + + p = (unsigned char *)padding->buffer.value; + padlength = p[padding->buffer.length - 1]; + + if (data->buffer.length + padding->buffer.length < padlength || + padlength == 0) { + *minor_status = (OM_uint32)KRB5_BAD_MSIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + /* + * kg_unseal_stream_iov() will place one byte of padding in the + * padding buffer; its true value is unknown until after decryption. + * + * relative_padlength contains the number of bytes to compensate the + * padding and data buffers by; it will be zero if the caller manages + * the padding length. + * + * If the caller manages the padding length, then relative_padlength + * will be zero. + * + * eg. if the buffers are structured as follows: + * + * +---DATA---+-PAD-+ + * | ABCDE444 | 4 | + * +----------+-----+ + * + * after compensation they would look like: + * + * +-DATA--+-PAD--+ + * | ABCDE | NULL | + * +-------+------+ + */ + relative_padlength = padlength - padding->buffer.length; + + assert(data->buffer.length >= relative_padlength); + + data->buffer.length -= relative_padlength; + + kg_release_iov(padding, 1); + padding->buffer.length = 0; + padding->buffer.value = NULL; + + return GSS_S_COMPLETE; +} + +krb5_boolean +kg_integ_only_iov(gss_iov_buffer_desc *iov, int iov_count) +{ + int i; + krb5_boolean has_conf_data = FALSE; + + assert(iov != GSS_C_NO_IOV_BUFFER); + + for (i = 0; i < iov_count; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA) { + has_conf_data = TRUE; + break; + } + } + + return (has_conf_data == FALSE); +} + +krb5_error_code +kg_allocate_iov(gss_iov_buffer_t iov, size_t size) +{ + assert(iov != GSS_C_NO_IOV_BUFFER); + assert(iov->type & GSS_IOV_BUFFER_FLAG_ALLOCATE); + + iov->buffer.length = size; + iov->buffer.value = gssalloc_malloc(size); + if (iov->buffer.value == NULL) { + iov->buffer.length = 0; + return ENOMEM; + } + + iov->type |= GSS_IOV_BUFFER_FLAG_ALLOCATED; + + return 0; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/util_seed.c b/krb5-1.21.3/src/lib/gssapi/krb5/util_seed.c new file mode 100644 index 00000000..6e1c9ac8 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/util_seed.c @@ -0,0 +1,61 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "gssapiP_krb5.h" +#ifdef HAVE_MEMORY_H +#include +#endif + +static const unsigned char zeros[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; + +krb5_error_code +kg_make_seed(context, key, seed) + krb5_context context; + krb5_key key; + unsigned char *seed; +{ + krb5_error_code code; + krb5_key rkey = NULL; + krb5_keyblock *tmpkey, *kb; + unsigned int i; + + code = krb5_k_key_keyblock(context, key, &tmpkey); + if (code) + return(code); + + /* reverse the key bytes, as per spec */ + kb = &key->keyblock; + for (i=0; ilength; i++) + tmpkey->contents[i] = kb->contents[kb->length - 1 - i]; + + code = krb5_k_create_key(context, tmpkey, &rkey); + if (code) + goto cleanup; + + code = kg_encrypt(context, rkey, KG_USAGE_SEAL, NULL, zeros, seed, 16); + +cleanup: + krb5_free_keyblock(context, tmpkey); + krb5_k_free_key(context, rkey); + return(code); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/util_seqnum.c b/krb5-1.21.3/src/lib/gssapi/krb5/util_seqnum.c new file mode 100644 index 00000000..bef631da --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/util_seqnum.c @@ -0,0 +1,102 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2001, 2009 by the Massachusetts Institute of Technology. + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "gssapiP_krb5.h" +#include "k5-int.h" + +/* + * $Id$ + */ + +krb5_error_code +kg_make_seq_num(context, key, direction, seqnum, cksum, buf) + krb5_context context; + krb5_key key; + int direction; + krb5_ui_4 seqnum; + unsigned char *cksum; + unsigned char *buf; +{ + unsigned char plain[8]; + + plain[4] = direction; + plain[5] = direction; + plain[6] = direction; + plain[7] = direction; + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC || + key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + /* Yes, Microsoft used big-endian sequence number.*/ + store_32_be(seqnum, plain); + return kg_arcfour_docrypt (&key->keyblock, 0, + cksum, 8, + &plain[0], 8, + buf); + + } + + store_32_le(seqnum, plain); + return(kg_encrypt(context, key, KG_USAGE_SEQ, cksum, plain, buf, 8)); +} + +krb5_error_code kg_get_seq_num(context, key, cksum, buf, direction, seqnum) + krb5_context context; + krb5_key key; + unsigned char *cksum; + unsigned char *buf; + int *direction; + krb5_ui_4 *seqnum; +{ + krb5_error_code code; + unsigned char plain[8]; + + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC || + key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + code = kg_arcfour_docrypt (&key->keyblock, 0, + cksum, 8, + buf, 8, + plain); + } else { + code = kg_decrypt(context, key, KG_USAGE_SEQ, cksum, buf, plain, 8); + } + if (code) + return(code); + + if ((plain[4] != plain[5]) || + (plain[4] != plain[6]) || + (plain[4] != plain[7])) + return((krb5_error_code) KG_BAD_SEQ); + + *direction = plain[4]; + if (key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC || + key->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + *seqnum = (plain[3]|(plain[2]<<8) | (plain[1]<<16)| (plain[0]<<24)); + } else { + *seqnum = ((plain[0]) | + (plain[1]<<8) | + (plain[2]<<16) | + (plain[3]<<24)); + } + + return(0); +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/val_cred.c b/krb5-1.21.3/src/lib/gssapi/krb5/val_cred.c new file mode 100644 index 00000000..cb1cb939 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/val_cred.c @@ -0,0 +1,83 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1997, 2007 by Massachusetts Institute of Technology + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "gssapiP_krb5.h" + +/* Check to see whether or not a GSSAPI krb5 credential is valid. If + * it is not, return an error. */ + +OM_uint32 +krb5_gss_validate_cred_1(OM_uint32 *minor_status, gss_cred_id_t cred_handle, + krb5_context context) +{ + krb5_gss_cred_id_t cred; + krb5_error_code code; + krb5_principal princ; + + cred = (krb5_gss_cred_id_t) cred_handle; + k5_mutex_lock(&cred->lock); + + if (cred->ccache && cred->expire != 0) { + if ((code = krb5_cc_get_principal(context, cred->ccache, &princ))) { + k5_mutex_unlock(&cred->lock); + *minor_status = code; + return(GSS_S_DEFECTIVE_CREDENTIAL); + } + if (!krb5_principal_compare(context, princ, cred->name->princ)) { + k5_mutex_unlock(&cred->lock); + *minor_status = KG_CCACHE_NOMATCH; + return(GSS_S_DEFECTIVE_CREDENTIAL); + } + (void)krb5_free_principal(context, princ); + } + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +krb5_gss_validate_cred(minor_status, cred_handle) + OM_uint32 *minor_status; + gss_cred_id_t cred_handle; +{ + krb5_context context; + krb5_error_code code; + OM_uint32 maj; + + code = krb5_gss_init_context(&context); + if (code) { + *minor_status = code; + return GSS_S_FAILURE; + } + + maj = krb5_gss_validate_cred_1(minor_status, cred_handle, context); + if (maj == 0) { + krb5_gss_cred_id_t cred = (krb5_gss_cred_id_t) cred_handle; + k5_mutex_assert_locked(&cred->lock); + k5_mutex_unlock(&cred->lock); + } + save_error_info(*minor_status, context); + krb5_free_context(context); + return maj; +} diff --git a/krb5-1.21.3/src/lib/gssapi/krb5/wrap_size_limit.c b/krb5-1.21.3/src/lib/gssapi/krb5/wrap_size_limit.c new file mode 100644 index 00000000..7959f424 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/krb5/wrap_size_limit.c @@ -0,0 +1,178 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "gssapiP_krb5.h" + +/* V2 interface */ +OM_uint32 KRB5_CALLCONV +krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag, + qop_req, req_output_size, max_input_size) + OM_uint32 *minor_status; + gss_ctx_id_t context_handle; + int conf_req_flag; + gss_qop_t qop_req; + OM_uint32 req_output_size; + OM_uint32 *max_input_size; +{ + krb5_gss_ctx_id_rec *ctx; + OM_uint32 data_size, conflen; + OM_uint32 ohlen; + int overhead; + + /* only default qop is allowed */ + if (qop_req != GSS_C_QOP_DEFAULT) { + *minor_status = (OM_uint32) G_UNKNOWN_QOP; + return GSS_S_BAD_QOP; + } + + ctx = (krb5_gss_ctx_id_rec *) context_handle; + if (ctx->terminated || !ctx->established) { + *minor_status = KG_CTX_INCOMPLETE; + return(GSS_S_NO_CONTEXT); + } + + if (ctx->proto == 1) { + /* No pseudo-ASN.1 wrapper overhead, so no sequence length and + OID. */ + OM_uint32 sz = req_output_size; + + /* Token header: 16 octets. */ + if (conf_req_flag) { + krb5_key key; + krb5_enctype enctype; + + key = ctx->have_acceptor_subkey ? ctx->acceptor_subkey + : ctx->subkey; + enctype = key->keyblock.enctype; + + while (sz > 0 && krb5_encrypt_size(sz, enctype) + 16 > req_output_size) + sz--; + /* Allow for encrypted copy of header. */ + if (sz > 16) + sz -= 16; + else + sz = 0; +#ifdef CFX_EXERCISE + /* Allow for EC padding. In the MIT implementation, only + added while testing. */ + if (sz > 65535) + sz -= 65535; + else + sz = 0; +#endif + } else { + krb5_cksumtype cksumtype; + krb5_error_code err; + size_t cksumsize; + + cksumtype = ctx->have_acceptor_subkey ? ctx->acceptor_subkey_cksumtype + : ctx->cksumtype; + + err = krb5_c_checksum_length(ctx->k5_context, cksumtype, &cksumsize); + if (err) { + *minor_status = err; + return GSS_S_FAILURE; + } + + /* Allow for token header and checksum. */ + if (sz < 16 + cksumsize) + sz = 0; + else + sz -= (16 + cksumsize); + } + + *max_input_size = sz; + *minor_status = 0; + return GSS_S_COMPLETE; + } + + /* Calculate the token size and subtract that from the output size */ + overhead = 7 + ctx->mech_used->length; + data_size = req_output_size; + conflen = kg_confounder_size(ctx->k5_context, ctx->enc->keyblock.enctype); + data_size = (conflen + data_size + 8) & (~(OM_uint32)7); + ohlen = g_token_size(ctx->mech_used, + (unsigned int) (data_size + ctx->cksum_size + 14)) + - req_output_size; + + if (ohlen+overhead < req_output_size) + /* + * Cannot have trailer length that will cause us to pad over our + * length. + */ + *max_input_size = (req_output_size - ohlen - overhead) & (~(OM_uint32)7); + else + *max_input_size = 0; + + *minor_status = 0; + return(GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/libgssapi_krb5.exports b/krb5-1.21.3/src/lib/gssapi/libgssapi_krb5.exports new file mode 100644 index 00000000..fd4fced8 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/libgssapi_krb5.exports @@ -0,0 +1,169 @@ +GSS_C_ATTR_LOCAL_LOGIN_USER +GSS_C_INQ_SSPI_SESSION_KEY +GSS_C_INQ_NEGOEX_KEY +GSS_C_INQ_NEGOEX_VERIFY_KEY +GSS_C_NT_ANONYMOUS +GSS_C_NT_COMPOSITE_EXPORT +GSS_C_NT_EXPORT_NAME +GSS_C_NT_HOSTBASED_SERVICE +GSS_C_NT_HOSTBASED_SERVICE_X +GSS_C_NT_MACHINE_UID_NAME +GSS_C_NT_STRING_UID_NAME +GSS_C_NT_USER_NAME +GSS_KRB5_NT_PRINCIPAL_NAME +GSS_KRB5_NT_ENTERPRISE_NAME +GSS_KRB5_NT_X509_CERT +GSS_KRB5_CRED_NO_CI_FLAGS_X +GSS_KRB5_GET_CRED_IMPERSONATOR +GSS_C_MA_MECH_CONCRETE +GSS_C_MA_MECH_PSEUDO +GSS_C_MA_MECH_COMPOSITE +GSS_C_MA_MECH_NEGO +GSS_C_MA_MECH_GLUE +GSS_C_MA_NOT_MECH +GSS_C_MA_DEPRECATED +GSS_C_MA_NOT_DFLT_MECH +GSS_C_MA_ITOK_FRAMED +GSS_C_MA_AUTH_INIT +GSS_C_MA_AUTH_TARG +GSS_C_MA_AUTH_INIT_INIT +GSS_C_MA_AUTH_TARG_INIT +GSS_C_MA_AUTH_INIT_ANON +GSS_C_MA_AUTH_TARG_ANON +GSS_C_MA_DELEG_CRED +GSS_C_MA_INTEG_PROT +GSS_C_MA_CONF_PROT +GSS_C_MA_MIC +GSS_C_MA_WRAP +GSS_C_MA_PROT_READY +GSS_C_MA_REPLAY_DET +GSS_C_MA_OOS_DET +GSS_C_MA_CBINDINGS +GSS_C_MA_PFS +GSS_C_MA_COMPRESS +GSS_C_MA_CTX_TRANS +GSS_C_MA_NEGOEX_AND_SPNEGO +GSS_C_SEC_CONTEXT_SASL_SSF +gss_accept_sec_context +gss_acquire_cred +gss_acquire_cred_with_password +gss_acquire_cred_impersonate_name +gss_add_buffer_set_member +gss_add_cred +gss_add_cred_impersonate_name +gss_add_cred_with_password +gss_add_oid_set_member +gss_authorize_localname +gss_canonicalize_name +gss_compare_name +gss_complete_auth_token +gss_context_time +gss_create_empty_buffer_set +gss_create_empty_oid_set +gss_decapsulate_token +gss_delete_name_attribute +gss_delete_sec_context +gss_display_mech_attr +gss_display_name +gss_display_name_ext +gss_display_status +gss_duplicate_name +gss_encapsulate_token +gss_export_cred +gss_export_name +gss_export_name_composite +gss_export_sec_context +gss_get_mic +gss_get_mic_iov +gss_get_mic_iov_length +gss_get_name_attribute +gss_import_cred +gss_import_name +gss_import_sec_context +gss_indicate_mechs +gss_init_sec_context +gss_indicate_mechs_by_attrs +gss_inquire_attrs_for_mech +gss_inquire_context +gss_inquire_cred +gss_inquire_cred_by_mech +gss_inquire_cred_by_oid +gss_inquire_mech_for_saslname +gss_inquire_mechs_for_name +gss_inquire_names_for_mech +gss_inquire_saslname_for_mech +gss_inquire_sec_context_by_oid +gss_krb5_ccache_name +gss_krb5_copy_ccache +gss_krb5_export_lucid_sec_context +gss_krb5_free_lucid_sec_context +gss_krb5_get_tkt_flags +gss_krb5_import_cred +gss_krb5_set_allowable_enctypes +gss_krb5_set_cred_rcache +gss_krb5int_make_seal_token_v3 +gss_krb5int_unseal_token_v3 +gsskrb5_extract_authtime_from_sec_context +gsskrb5_extract_authz_data_from_sec_context +gss_localname +gss_map_name_to_any +gss_mech_iakerb +gss_mech_krb5 +gss_mech_krb5_old +gss_mech_krb5_wrong +gss_mech_set_krb5 +gss_mech_set_krb5_both +gss_mech_set_krb5_old +gss_nt_exported_name +gss_nt_krb5_name +gss_nt_krb5_principal +gss_nt_machine_uid_name +gss_nt_service_name +gss_nt_service_name_v2 +gss_nt_string_uid_name +gss_nt_user_name +gss_oid_equal +gss_oid_to_str +gss_pname_to_uid +gss_pseudo_random +gss_process_context_token +gss_release_any_name_mapping +gss_release_buffer_set +gss_release_buffer +gss_release_cred +gss_release_iov_buffer +gss_release_name +gss_release_oid +gss_release_oid_set +gss_seal +gss_set_name_attribute +gss_set_neg_mechs +gss_set_sec_context_option +gss_sign +gss_store_cred +gss_str_to_oid +gss_test_oid_set_member +gss_unseal +gss_unwrap +gss_unwrap_aead +gss_unwrap_iov +gss_userok +gss_verify +gss_verify_mic +gss_verify_mic_iov +gss_wrap +gss_wrap_aead +gss_wrap_iov +gss_wrap_iov_length +gss_wrap_size_limit +gss_set_cred_option +gssspi_set_cred_option +gssspi_mech_invoke +krb5_gss_dbg_client_expcreds +krb5_gss_register_acceptor_identity +krb5_gss_use_kdc_context +gss_inquire_name +gss_acquire_cred_from +gss_add_cred_from +gss_store_cred_into +gssint_g_seqstate_init diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/Makefile.in b/krb5-1.21.3/src/lib/gssapi/mechglue/Makefile.in new file mode 100644 index 00000000..33d93193 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/Makefile.in @@ -0,0 +1,228 @@ +mydir=lib$(S)gssapi$(S)mechglue +BUILDTOP=$(REL)..$(S)..$(S).. +LOCALINCLUDES = -I. -I$(srcdir) -I$(srcdir)/.. -I../generic -I$(srcdir)/../generic -I../krb5 -I$(srcdir)/../krb5 -I../spnego -I$(srcdir)/../spnego + +DEFINES=-D_GSS_STATIC_LINK=1 + +##DOSBUILDTOP = ..\..\.. +##DOS##PREFIXDIR=mechglue +##DOS##OBJFILE=..\$(OUTPRE)mechglue.lst + +##DOS##DLL_EXP_TYPE=GSS + +SRCS = \ + $(srcdir)/g_accept_sec_context.c \ + $(srcdir)/g_acquire_cred.c \ + $(srcdir)/g_acquire_cred_with_pw.c \ + $(srcdir)/g_acquire_cred_imp_name.c \ + $(srcdir)/g_authorize_localname.c \ + $(srcdir)/g_buffer_set.c \ + $(srcdir)/g_canon_name.c \ + $(srcdir)/g_compare_name.c \ + $(srcdir)/g_complete_auth_token.c \ + $(srcdir)/g_context_time.c \ + $(srcdir)/g_decapsulate_token.c \ + $(srcdir)/g_delete_sec_context.c \ + $(srcdir)/g_del_name_attr.c \ + $(srcdir)/g_dsp_name.c \ + $(srcdir)/g_dsp_name_ext.c \ + $(srcdir)/g_dsp_status.c \ + $(srcdir)/g_dup_name.c \ + $(srcdir)/g_encapsulate_token.c \ + $(srcdir)/g_exp_sec_context.c \ + $(srcdir)/g_export_cred.c \ + $(srcdir)/g_export_name.c \ + $(srcdir)/g_export_name_comp.c \ + $(srcdir)/g_get_name_attr.c \ + $(srcdir)/g_glue.c \ + $(srcdir)/g_imp_cred.c \ + $(srcdir)/g_imp_name.c \ + $(srcdir)/g_imp_sec_context.c \ + $(srcdir)/g_init_sec_context.c \ + $(srcdir)/g_initialize.c \ + $(srcdir)/g_inq_context.c \ + $(srcdir)/g_inq_context_oid.c \ + $(srcdir)/g_inq_cred.c \ + $(srcdir)/g_inq_cred_oid.c \ + $(srcdir)/g_inq_name.c \ + $(srcdir)/g_inq_names.c \ + $(srcdir)/g_map_name_to_any.c \ + $(srcdir)/g_mech_invoke.c \ + $(srcdir)/g_mechattr.c \ + $(srcdir)/g_mechname.c \ + $(srcdir)/g_negoex.c \ + $(srcdir)/g_oid_ops.c \ + $(srcdir)/g_prf.c \ + $(srcdir)/g_process_context.c \ + $(srcdir)/g_rel_buffer.c \ + $(srcdir)/g_rel_cred.c \ + $(srcdir)/g_rel_name.c \ + $(srcdir)/g_rel_name_mapping.c \ + $(srcdir)/g_rel_oid_set.c \ + $(srcdir)/g_saslname.c \ + $(srcdir)/g_seal.c \ + $(srcdir)/g_set_context_option.c \ + $(srcdir)/g_set_cred_option.c \ + $(srcdir)/g_set_name_attr.c \ + $(srcdir)/g_set_neg_mechs.c \ + $(srcdir)/g_sign.c \ + $(srcdir)/g_store_cred.c \ + $(srcdir)/g_unseal.c \ + $(srcdir)/g_unwrap_aead.c \ + $(srcdir)/g_unwrap_iov.c \ + $(srcdir)/g_verify.c \ + $(srcdir)/g_wrap_aead.c \ + $(srcdir)/g_wrap_iov.c \ + $(srcdir)/gssd_pname_to_uid.c + +OBJS = \ + $(OUTPRE)g_accept_sec_context.$(OBJEXT) \ + $(OUTPRE)g_acquire_cred.$(OBJEXT) \ + $(OUTPRE)g_acquire_cred_with_pw.$(OBJEXT) \ + $(OUTPRE)g_acquire_cred_imp_name.$(OBJEXT) \ + $(OUTPRE)g_authorize_localname.$(OBJEXT) \ + $(OUTPRE)g_buffer_set.$(OBJEXT) \ + $(OUTPRE)g_canon_name.$(OBJEXT) \ + $(OUTPRE)g_compare_name.$(OBJEXT) \ + $(OUTPRE)g_complete_auth_token.$(OBJEXT) \ + $(OUTPRE)g_context_time.$(OBJEXT) \ + $(OUTPRE)g_decapsulate_token.$(OBJEXT) \ + $(OUTPRE)g_delete_sec_context.$(OBJEXT) \ + $(OUTPRE)g_del_name_attr.$(OBJEXT) \ + $(OUTPRE)g_dsp_name.$(OBJEXT) \ + $(OUTPRE)g_dsp_name_ext.$(OBJEXT) \ + $(OUTPRE)g_dsp_status.$(OBJEXT) \ + $(OUTPRE)g_dup_name.$(OBJEXT) \ + $(OUTPRE)g_encapsulate_token.$(OBJEXT) \ + $(OUTPRE)g_exp_sec_context.$(OBJEXT) \ + $(OUTPRE)g_export_cred.$(OBJEXT) \ + $(OUTPRE)g_export_name.$(OBJEXT) \ + $(OUTPRE)g_export_name_comp.$(OBJEXT) \ + $(OUTPRE)g_get_name_attr.$(OBJEXT) \ + $(OUTPRE)g_glue.$(OBJEXT) \ + $(OUTPRE)g_imp_cred.$(OBJEXT) \ + $(OUTPRE)g_imp_name.$(OBJEXT) \ + $(OUTPRE)g_imp_sec_context.$(OBJEXT) \ + $(OUTPRE)g_init_sec_context.$(OBJEXT) \ + $(OUTPRE)g_initialize.$(OBJEXT) \ + $(OUTPRE)g_inq_context.$(OBJEXT) \ + $(OUTPRE)g_inq_context_oid.$(OBJEXT) \ + $(OUTPRE)g_inq_cred.$(OBJEXT) \ + $(OUTPRE)g_inq_cred_oid.$(OBJEXT) \ + $(OUTPRE)g_inq_name.$(OBJEXT) \ + $(OUTPRE)g_inq_names.$(OBJEXT) \ + $(OUTPRE)g_map_name_to_any.$(OBJEXT) \ + $(OUTPRE)g_mech_invoke.$(OBJEXT) \ + $(OUTPRE)g_mechattr.$(OBJEXT) \ + $(OUTPRE)g_mechname.$(OBJEXT) \ + $(OUTPRE)g_negoex.$(OBJEXT) \ + $(OUTPRE)g_oid_ops.$(OBJEXT) \ + $(OUTPRE)g_prf.$(OBJEXT) \ + $(OUTPRE)g_process_context.$(OBJEXT) \ + $(OUTPRE)g_rel_buffer.$(OBJEXT) \ + $(OUTPRE)g_rel_cred.$(OBJEXT) \ + $(OUTPRE)g_rel_name.$(OBJEXT) \ + $(OUTPRE)g_rel_name_mapping.$(OBJEXT) \ + $(OUTPRE)g_rel_oid_set.$(OBJEXT) \ + $(OUTPRE)g_saslname.$(OBJEXT) \ + $(OUTPRE)g_seal.$(OBJEXT) \ + $(OUTPRE)g_set_context_option.$(OBJEXT) \ + $(OUTPRE)g_set_cred_option.$(OBJEXT) \ + $(OUTPRE)g_set_name_attr.$(OBJEXT) \ + $(OUTPRE)g_set_neg_mechs.$(OBJEXT) \ + $(OUTPRE)g_sign.$(OBJEXT) \ + $(OUTPRE)g_store_cred.$(OBJEXT) \ + $(OUTPRE)g_unseal.$(OBJEXT) \ + $(OUTPRE)g_unwrap_aead.$(OBJEXT) \ + $(OUTPRE)g_unwrap_iov.$(OBJEXT) \ + $(OUTPRE)g_verify.$(OBJEXT) \ + $(OUTPRE)g_wrap_aead.$(OBJEXT) \ + $(OUTPRE)g_wrap_iov.$(OBJEXT) \ + $(OUTPRE)gssd_pname_to_uid.$(OBJEXT) + +STLIBOBJS = \ + g_accept_sec_context.o \ + g_acquire_cred.o \ + g_acquire_cred_with_pw.o \ + g_acquire_cred_imp_name.o \ + g_authorize_localname.o \ + g_buffer_set.o \ + g_canon_name.o \ + g_compare_name.o \ + g_complete_auth_token.o \ + g_context_time.o \ + g_decapsulate_token.o \ + g_delete_sec_context.o \ + g_del_name_attr.o \ + g_dsp_name.o \ + g_dsp_name_ext.o \ + g_dsp_status.o \ + g_dup_name.o \ + g_encapsulate_token.o \ + g_exp_sec_context.o \ + g_export_cred.o \ + g_export_name.o \ + g_export_name_comp.o \ + g_get_name_attr.o \ + g_glue.o \ + g_imp_cred.o \ + g_imp_name.o \ + g_imp_sec_context.o \ + g_init_sec_context.o \ + g_initialize.o \ + g_inq_context.o \ + g_inq_context_oid.o \ + g_inq_cred.o \ + g_inq_cred_oid.o \ + g_inq_name.o \ + g_inq_names.o \ + g_map_name_to_any.o \ + g_mech_invoke.o \ + g_mechattr.o \ + g_mechname.o \ + g_negoex.o \ + g_oid_ops.o \ + g_prf.o \ + g_process_context.o \ + g_rel_buffer.o \ + g_rel_cred.o \ + g_rel_name.o \ + g_rel_name_mapping.o \ + g_rel_oid_set.o \ + g_saslname.o \ + g_seal.o \ + g_set_context_option.o \ + g_set_cred_option.o \ + g_set_name_attr.o \ + g_set_neg_mechs.o \ + g_sign.o \ + g_store_cred.o \ + g_unseal.o \ + g_unwrap_aead.o \ + g_unwrap_iov.o \ + g_verify.o \ + g_wrap_aead.o \ + g_wrap_iov.o \ + gssd_pname_to_uid.o + +EHDRDIR= $(BUILDTOP)$(S)include$(S)gssapi +EXPORTED_HEADERS = mechglue.h + +$(OBJS): $(EXPORTED_HEADERS) + +all-unix: all-libobjs + +##DOS##LIBOBJS = $(OBJS) + +clean-unix:: clean-libobjs + +# Krb5InstallHeaders($(EXPORTED_HEADERS), $(KRB5_INCDIR)/krb5) +install: + @set -x; for f in $(EXPORTED_HEADERS) ; \ + do $(INSTALL_DATA) $(srcdir)$(S)$$f \ + $(DESTDIR)$(KRB5_INCDIR)$(S)gssapi$(S)$$f ; \ + done + +includes: + +@libobj_frag@ diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/deps b/krb5-1.21.3/src/lib/gssapi/mechglue/deps new file mode 100644 index 00000000..d2125d20 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/deps @@ -0,0 +1,521 @@ +# +# Generated makefile dependencies follow. +# +g_accept_sec_context.so g_accept_sec_context.po $(OUTPRE)g_accept_sec_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_accept_sec_context.c mechglue.h mglueP.h +g_acquire_cred.so g_acquire_cred.po $(OUTPRE)g_acquire_cred.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_acquire_cred.c mechglue.h mglueP.h +g_acquire_cred_with_pw.so g_acquire_cred_with_pw.po \ + $(OUTPRE)g_acquire_cred_with_pw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_ext.h \ + $(srcdir)/../generic/gssapi_generic.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + ../generic/gssapi_err_generic.h g_acquire_cred_with_pw.c \ + mechglue.h mglueP.h +g_acquire_cred_imp_name.so g_acquire_cred_imp_name.po \ + $(OUTPRE)g_acquire_cred_imp_name.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_ext.h \ + $(srcdir)/../generic/gssapi_generic.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + ../generic/gssapi_err_generic.h g_acquire_cred_imp_name.c \ + mechglue.h mglueP.h +g_authorize_localname.so g_authorize_localname.po $(OUTPRE)g_authorize_localname.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_authorize_localname.c mechglue.h mglueP.h +g_buffer_set.so g_buffer_set.po $(OUTPRE)g_buffer_set.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_buffer_set.c mechglue.h mglueP.h +g_canon_name.so g_canon_name.po $(OUTPRE)g_canon_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_canon_name.c mechglue.h mglueP.h +g_compare_name.so g_compare_name.po $(OUTPRE)g_compare_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_compare_name.c mechglue.h mglueP.h +g_complete_auth_token.so g_complete_auth_token.po $(OUTPRE)g_complete_auth_token.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_complete_auth_token.c mechglue.h mglueP.h +g_context_time.so g_context_time.po $(OUTPRE)g_context_time.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_context_time.c mechglue.h mglueP.h +g_decapsulate_token.so g_decapsulate_token.po $(OUTPRE)g_decapsulate_token.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_decapsulate_token.c mechglue.h mglueP.h +g_delete_sec_context.so g_delete_sec_context.po $(OUTPRE)g_delete_sec_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_delete_sec_context.c mechglue.h mglueP.h +g_del_name_attr.so g_del_name_attr.po $(OUTPRE)g_del_name_attr.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_del_name_attr.c mechglue.h mglueP.h +g_dsp_name.so g_dsp_name.po $(OUTPRE)g_dsp_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_dsp_name.c mechglue.h mglueP.h +g_dsp_name_ext.so g_dsp_name_ext.po $(OUTPRE)g_dsp_name_ext.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_dsp_name_ext.c mechglue.h mglueP.h +g_dsp_status.so g_dsp_status.po $(OUTPRE)g_dsp_status.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_dsp_status.c mechglue.h mglueP.h +g_dup_name.so g_dup_name.po $(OUTPRE)g_dup_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_dup_name.c mechglue.h mglueP.h +g_encapsulate_token.so g_encapsulate_token.po $(OUTPRE)g_encapsulate_token.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_encapsulate_token.c mechglue.h mglueP.h +g_exp_sec_context.so g_exp_sec_context.po $(OUTPRE)g_exp_sec_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_exp_sec_context.c mechglue.h mglueP.h +g_export_cred.so g_export_cred.po $(OUTPRE)g_export_cred.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_export_cred.c mechglue.h mglueP.h +g_export_name.so g_export_name.po $(OUTPRE)g_export_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_export_name.c mechglue.h mglueP.h +g_export_name_comp.so g_export_name_comp.po $(OUTPRE)g_export_name_comp.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_export_name_comp.c mechglue.h mglueP.h +g_get_name_attr.so g_get_name_attr.po $(OUTPRE)g_get_name_attr.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_get_name_attr.c mechglue.h mglueP.h +g_glue.so g_glue.po $(OUTPRE)g_glue.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_ext.h \ + $(srcdir)/../generic/gssapi_generic.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-der.h $(top_srcdir)/include/k5-input.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + ../generic/gssapi_err_generic.h g_glue.c mechglue.h \ + mglueP.h +g_imp_cred.so g_imp_cred.po $(OUTPRE)g_imp_cred.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_imp_cred.c mechglue.h mglueP.h +g_imp_name.so g_imp_name.po $(OUTPRE)g_imp_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-der.h \ + $(top_srcdir)/include/k5-input.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_imp_name.c mechglue.h mglueP.h +g_imp_sec_context.so g_imp_sec_context.po $(OUTPRE)g_imp_sec_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_imp_sec_context.c mechglue.h mglueP.h +g_init_sec_context.so g_init_sec_context.po $(OUTPRE)g_init_sec_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_init_sec_context.c mechglue.h mglueP.h +g_initialize.so g_initialize.po $(OUTPRE)g_initialize.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(srcdir)/../krb5/gssapiP_krb5.h $(srcdir)/../krb5/gssapi_krb5.h \ + $(srcdir)/../spnego/gssapiP_negoex.h $(srcdir)/../spnego/gssapiP_spnego.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-queue.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h ../generic/gssapi_err_generic.h \ + ../krb5/gssapi_err_krb5.h g_initialize.c mechglue.h \ + mglueP.h +g_inq_context.so g_inq_context.po $(OUTPRE)g_inq_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_inq_context.c mechglue.h mglueP.h +g_inq_context_oid.so g_inq_context_oid.po $(OUTPRE)g_inq_context_oid.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_inq_context_oid.c mechglue.h mglueP.h +g_inq_cred.so g_inq_cred.po $(OUTPRE)g_inq_cred.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_inq_cred.c mechglue.h mglueP.h +g_inq_cred_oid.so g_inq_cred_oid.po $(OUTPRE)g_inq_cred_oid.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_inq_cred_oid.c mechglue.h mglueP.h +g_inq_name.so g_inq_name.po $(OUTPRE)g_inq_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_inq_name.c mechglue.h mglueP.h +g_inq_names.so g_inq_names.po $(OUTPRE)g_inq_names.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_inq_names.c mechglue.h mglueP.h +g_map_name_to_any.so g_map_name_to_any.po $(OUTPRE)g_map_name_to_any.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_map_name_to_any.c mechglue.h mglueP.h +g_mech_invoke.so g_mech_invoke.po $(OUTPRE)g_mech_invoke.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_mech_invoke.c mechglue.h mglueP.h +g_mechattr.so g_mechattr.po $(OUTPRE)g_mechattr.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_mechattr.c mechglue.h mglueP.h +g_mechname.so g_mechname.po $(OUTPRE)g_mechname.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_mechname.c mechglue.h mglueP.h +g_negoex.so g_negoex.po $(OUTPRE)g_negoex.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_negoex.c mechglue.h mglueP.h +g_oid_ops.so g_oid_ops.po $(OUTPRE)g_oid_ops.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_oid_ops.c mechglue.h mglueP.h +g_prf.so g_prf.po $(OUTPRE)g_prf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_ext.h \ + $(srcdir)/../generic/gssapi_generic.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + ../generic/gssapi_err_generic.h g_prf.c mechglue.h \ + mglueP.h +g_process_context.so g_process_context.po $(OUTPRE)g_process_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_process_context.c mechglue.h mglueP.h +g_rel_buffer.so g_rel_buffer.po $(OUTPRE)g_rel_buffer.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_rel_buffer.c mechglue.h mglueP.h +g_rel_cred.so g_rel_cred.po $(OUTPRE)g_rel_cred.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_rel_cred.c mechglue.h mglueP.h +g_rel_name.so g_rel_name.po $(OUTPRE)g_rel_name.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_rel_name.c mechglue.h mglueP.h +g_rel_name_mapping.so g_rel_name_mapping.po $(OUTPRE)g_rel_name_mapping.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_rel_name_mapping.c mechglue.h mglueP.h +g_rel_oid_set.so g_rel_oid_set.po $(OUTPRE)g_rel_oid_set.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_rel_oid_set.c mechglue.h mglueP.h +g_saslname.so g_saslname.po $(OUTPRE)g_saslname.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_saslname.c mechglue.h mglueP.h +g_seal.so g_seal.po $(OUTPRE)g_seal.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_ext.h \ + $(srcdir)/../generic/gssapi_generic.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + ../generic/gssapi_err_generic.h g_seal.c mechglue.h \ + mglueP.h +g_set_context_option.so g_set_context_option.po $(OUTPRE)g_set_context_option.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_set_context_option.c mechglue.h mglueP.h +g_set_cred_option.so g_set_cred_option.po $(OUTPRE)g_set_cred_option.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_set_cred_option.c mechglue.h mglueP.h +g_set_name_attr.so g_set_name_attr.po $(OUTPRE)g_set_name_attr.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_set_name_attr.c mechglue.h mglueP.h +g_set_neg_mechs.so g_set_neg_mechs.po $(OUTPRE)g_set_neg_mechs.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_set_neg_mechs.c mechglue.h mglueP.h +g_sign.so g_sign.po $(OUTPRE)g_sign.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ + $(srcdir)/../generic/gssapiP_generic.h $(srcdir)/../generic/gssapi_ext.h \ + $(srcdir)/../generic/gssapi_generic.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + ../generic/gssapi_err_generic.h g_sign.c mechglue.h \ + mglueP.h +g_store_cred.so g_store_cred.po $(OUTPRE)g_store_cred.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_store_cred.c mechglue.h mglueP.h +g_unseal.so g_unseal.po $(OUTPRE)g_unseal.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_unseal.c mechglue.h mglueP.h +g_unwrap_aead.so g_unwrap_aead.po $(OUTPRE)g_unwrap_aead.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_unwrap_aead.c mechglue.h mglueP.h +g_unwrap_iov.so g_unwrap_iov.po $(OUTPRE)g_unwrap_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_unwrap_iov.c mechglue.h mglueP.h +g_verify.so g_verify.po $(OUTPRE)g_verify.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_verify.c mechglue.h mglueP.h +g_wrap_aead.so g_wrap_aead.po $(OUTPRE)g_wrap_aead.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_wrap_aead.c mechglue.h mglueP.h +g_wrap_iov.so g_wrap_iov.po $(OUTPRE)g_wrap_iov.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + g_wrap_iov.c mechglue.h mglueP.h +gssd_pname_to_uid.so gssd_pname_to_uid.po $(OUTPRE)gssd_pname_to_uid.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h ../generic/gssapi_err_generic.h \ + gssd_pname_to_uid.c mechglue.h mglueP.h diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_accept_sec_context.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_accept_sec_context.c new file mode 100644 index 00000000..4f2a66e2 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_accept_sec_context.c @@ -0,0 +1,407 @@ +/* #pragma ident "@(#)g_accept_sec_context.c 1.19 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_accept_sec_context + */ + +#include "mglueP.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include + +#ifndef LEAN_CLIENT +static OM_uint32 +val_acc_sec_ctx_args( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_cred_id_t verifier_cred_handle, + gss_buffer_t input_token_buffer, + gss_channel_bindings_t input_chan_bindings, + gss_name_t *src_name, + gss_OID *mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec, + gss_cred_id_t *d_cred) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (src_name != NULL) + *src_name = GSS_C_NO_NAME; + + if (mech_type != NULL) + *mech_type = GSS_C_NO_OID; + + if (output_token != GSS_C_NO_BUFFER) { + output_token->length = 0; + output_token->value = NULL; + } + + if (ret_flags != NULL) + *ret_flags = 0; + + if (time_rec != NULL) + *time_rec = 0; + + if (d_cred != NULL) + *d_cred = GSS_C_NO_CREDENTIAL; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (input_token_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (output_token == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + return (GSS_S_COMPLETE); +} + +/* Return true if mech should be accepted with no acceptor credential. */ +static int +allow_mech_by_default(gss_OID mech) +{ + OM_uint32 status, minor; + gss_OID_set attrs; + int reject = 0, p; + + /* Whether we accept an interposer mech depends on whether we accept the + * mech it interposes. */ + mech = gssint_get_public_oid(mech); + if (mech == GSS_C_NO_OID) + return 0; + + status = gss_inquire_attrs_for_mech(&minor, mech, &attrs, NULL); + if (status) + return 0; + + /* If the mechanism doesn't support RFC 5587, don't exclude it. */ + if (attrs == GSS_C_NO_OID_SET) + return 1; + + /* Check for each attribute which would cause us to exclude this mech from + * the default credential. */ + if (generic_gss_test_oid_set_member(&minor, GSS_C_MA_DEPRECATED, + attrs, &p) != GSS_S_COMPLETE || p) + reject = 1; + else if (generic_gss_test_oid_set_member(&minor, GSS_C_MA_NOT_DFLT_MECH, + attrs, &p) != GSS_S_COMPLETE || p) + reject = 1; + + (void) gss_release_oid_set(&minor, &attrs); + return !reject; +} + +OM_uint32 KRB5_CALLCONV +gss_accept_sec_context (minor_status, + context_handle, + verifier_cred_handle, + input_token_buffer, + input_chan_bindings, + src_name, + mech_type, + output_token, + ret_flags, + time_rec, + d_cred) + +OM_uint32 * minor_status; +gss_ctx_id_t * context_handle; +gss_cred_id_t verifier_cred_handle; +gss_buffer_t input_token_buffer; +gss_channel_bindings_t input_chan_bindings; +gss_name_t * src_name; +gss_OID * mech_type; +gss_buffer_t output_token; +OM_uint32 * ret_flags; +OM_uint32 * time_rec; +gss_cred_id_t * d_cred; + +{ + OM_uint32 status, temp_status, temp_minor_status; + OM_uint32 temp_ret_flags = 0; + gss_union_ctx_id_t union_ctx_id = NULL; + gss_cred_id_t input_cred_handle = GSS_C_NO_CREDENTIAL; + gss_cred_id_t tmp_d_cred = GSS_C_NO_CREDENTIAL; + gss_name_t internal_name = GSS_C_NO_NAME; + gss_name_t tmp_src_name = GSS_C_NO_NAME; + gss_OID_desc token_mech_type_desc; + gss_OID token_mech_type = &token_mech_type_desc; + gss_OID actual_mech = GSS_C_NO_OID; + gss_OID selected_mech = GSS_C_NO_OID; + gss_OID public_mech; + gss_mechanism mech = NULL; + gss_union_cred_t uc; + int i; + + status = val_acc_sec_ctx_args(minor_status, + context_handle, + verifier_cred_handle, + input_token_buffer, + input_chan_bindings, + src_name, + mech_type, + output_token, + ret_flags, + time_rec, + d_cred); + if (status != GSS_S_COMPLETE) + return (status); + + /* + * if context_handle is GSS_C_NO_CONTEXT, allocate a union context + * descriptor to hold the mech type information as well as the + * underlying mechanism context handle. Otherwise, cast the + * value of *context_handle to the union context variable. + */ + + if(*context_handle == GSS_C_NO_CONTEXT) { + + if (input_token_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ); + + /* Get the token mech type */ + status = gssint_get_mech_type(token_mech_type, input_token_buffer); + if (status) + return status; + + /* + * An interposer calling back into the mechglue can't pass in a special + * mech, so we have to recognize it using verifier_cred_handle. Use + * the mechanism for which we have matching creds, if available. + */ + if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) { + uc = (gss_union_cred_t)verifier_cred_handle; + for (i = 0; i < uc->count; i++) { + public_mech = gssint_get_public_oid(&uc->mechs_array[i]); + if (public_mech && g_OID_equal(token_mech_type, public_mech)) { + selected_mech = &uc->mechs_array[i]; + break; + } + } + } + + if (selected_mech == GSS_C_NO_OID) { + status = gssint_select_mech_type(minor_status, token_mech_type, + &selected_mech); + if (status) + return status; + } + + } else { + union_ctx_id = (gss_union_ctx_id_t)*context_handle; + selected_mech = union_ctx_id->mech_type; + if (union_ctx_id->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + } + + /* Now create a new context if we didn't get one. */ + if (*context_handle == GSS_C_NO_CONTEXT) { + status = gssint_create_union_context(minor_status, selected_mech, + &union_ctx_id); + if (status != GSS_S_COMPLETE) + return (status); + } + + /* + * get the appropriate cred handle from the union cred struct. + */ + if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) { + input_cred_handle = + gssint_get_mechanism_cred((gss_union_cred_t)verifier_cred_handle, + selected_mech); + if (input_cred_handle == GSS_C_NO_CREDENTIAL) { + /* verifier credential specified but no acceptor credential found */ + status = GSS_S_NO_CRED; + goto error_out; + } + } else if (!allow_mech_by_default(selected_mech)) { + status = GSS_S_NO_CRED; + goto error_out; + } + + /* + * now select the approprate underlying mechanism routine and + * call it. + */ + + mech = gssint_get_mechanism(selected_mech); + if (mech && mech->gss_accept_sec_context) { + + status = mech->gss_accept_sec_context(minor_status, + &union_ctx_id->internal_ctx_id, + input_cred_handle, + input_token_buffer, + input_chan_bindings, + src_name ? &internal_name : NULL, + &actual_mech, + output_token, + &temp_ret_flags, + time_rec, + d_cred ? &tmp_d_cred : NULL); + + /* If there's more work to do, keep going... */ + if (status == GSS_S_CONTINUE_NEEDED) { + *context_handle = (gss_ctx_id_t)union_ctx_id; + return GSS_S_CONTINUE_NEEDED; + } + + /* if the call failed, return with failure */ + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + goto error_out; + } + + /* + * if src_name is non-NULL, + * convert internal_name into a union name equivalent + * First call the mechanism specific display_name() + * then call gss_import_name() to create + * the union name struct cast to src_name + */ + if (src_name != NULL) { + if (internal_name != GSS_C_NO_NAME) { + /* consumes internal_name regardless of success */ + temp_status = gssint_convert_name_to_union_name( + &temp_minor_status, mech, + internal_name, &tmp_src_name); + if (temp_status != GSS_S_COMPLETE) { + status = temp_status; + *minor_status = temp_minor_status; + map_error(minor_status, mech); + if (output_token->length) + (void) gss_release_buffer(&temp_minor_status, + output_token); + goto error_out; + } + *src_name = tmp_src_name; + } else + *src_name = GSS_C_NO_NAME; + } + +#define g_OID_prefix_equal(o1, o2) \ + (((o1)->length >= (o2)->length) && \ + (memcmp((o1)->elements, (o2)->elements, (o2)->length) == 0)) + + /* Ensure we're returning correct creds format */ + if ((temp_ret_flags & GSS_C_DELEG_FLAG) && + tmp_d_cred != GSS_C_NO_CREDENTIAL) { + public_mech = gssint_get_public_oid(selected_mech); + if (actual_mech != GSS_C_NO_OID && + public_mech != GSS_C_NO_OID && + !g_OID_prefix_equal(actual_mech, public_mech)) { + *d_cred = tmp_d_cred; /* unwrapped pseudo-mech */ + } else { + gss_union_cred_t d_u_cred = NULL; + + d_u_cred = malloc(sizeof (gss_union_cred_desc)); + if (d_u_cred == NULL) { + status = GSS_S_FAILURE; + goto error_out; + } + (void) memset(d_u_cred, 0, sizeof (gss_union_cred_desc)); + + d_u_cred->count = 1; + + status = generic_gss_copy_oid(&temp_minor_status, + selected_mech, + &d_u_cred->mechs_array); + + if (status != GSS_S_COMPLETE) { + free(d_u_cred); + goto error_out; + } + + d_u_cred->cred_array = malloc(sizeof(gss_cred_id_t)); + if (d_u_cred->cred_array != NULL) { + d_u_cred->cred_array[0] = tmp_d_cred; + } else { + free(d_u_cred); + status = GSS_S_FAILURE; + goto error_out; + } + + d_u_cred->loopback = d_u_cred; + *d_cred = (gss_cred_id_t)d_u_cred; + } + } + + if (mech_type != NULL) + *mech_type = gssint_get_public_oid(actual_mech); + if (ret_flags != NULL) + *ret_flags = temp_ret_flags; + *context_handle = (gss_ctx_id_t)union_ctx_id; + return GSS_S_COMPLETE; + } else { + + status = GSS_S_BAD_MECH; + } + +error_out: + /* + * RFC 2744 5.1 requires that we not create a context on a failed first + * call to accept, and recommends that on a failed subsequent call we + * make the caller responsible for calling gss_delete_sec_context. + * Even if the mech deleted its context, keep the union context around + * for the caller to delete. + */ + if (union_ctx_id && *context_handle == GSS_C_NO_CONTEXT) { + if (union_ctx_id->mech_type) { + if (union_ctx_id->mech_type->elements) + free(union_ctx_id->mech_type->elements); + free(union_ctx_id->mech_type); + } + if (union_ctx_id->internal_ctx_id && mech && + mech->gss_delete_sec_context) { + mech->gss_delete_sec_context(&temp_minor_status, + &union_ctx_id->internal_ctx_id, + GSS_C_NO_BUFFER); + } + free(union_ctx_id); + } + + if (src_name) + *src_name = GSS_C_NO_NAME; + + if (tmp_src_name != GSS_C_NO_NAME) + (void) gss_release_buffer(&temp_minor_status, + (gss_buffer_t)tmp_src_name); + + return (status); +} +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_acquire_cred.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_acquire_cred.c new file mode 100644 index 00000000..c885f562 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_acquire_cred.c @@ -0,0 +1,633 @@ +/* #pragma ident "@(#)g_acquire_cred.c 1.22 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_acquire_cred + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include + +static OM_uint32 +val_acq_cred_args( + OM_uint32 *minor_status, + gss_name_t desired_name, + OM_uint32 time_req, + gss_OID_set desired_mechs, + int cred_usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_cred_handle != NULL) + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + if (actual_mechs != NULL) + *actual_mechs = GSS_C_NULL_OID_SET; + + if (time_rec != NULL) + *time_rec = 0; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (output_cred_handle == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (cred_usage != GSS_C_ACCEPT + && cred_usage != GSS_C_INITIATE + && cred_usage != GSS_C_BOTH) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_acquire_cred(minor_status, + desired_name, + time_req, + desired_mechs, + cred_usage, + output_cred_handle, + actual_mechs, + time_rec) + +OM_uint32 * minor_status; +gss_name_t desired_name; +OM_uint32 time_req; +gss_OID_set desired_mechs; +int cred_usage; +gss_cred_id_t * output_cred_handle; +gss_OID_set * actual_mechs; +OM_uint32 * time_rec; + +{ + return gss_acquire_cred_from(minor_status, desired_name, time_req, + desired_mechs, cred_usage, NULL, + output_cred_handle, actual_mechs, time_rec); +} + +OM_uint32 KRB5_CALLCONV +gss_acquire_cred_from(minor_status, + desired_name, + time_req, + desired_mechs, + cred_usage, + cred_store, + output_cred_handle, + actual_mechs, + time_rec) + +OM_uint32 * minor_status; +gss_name_t desired_name; +OM_uint32 time_req; +gss_OID_set desired_mechs; +int cred_usage; +gss_const_key_value_set_t cred_store; +gss_cred_id_t * output_cred_handle; +gss_OID_set * actual_mechs; +OM_uint32 * time_rec; + +{ + OM_uint32 major = GSS_S_FAILURE, tmpMinor; + OM_uint32 first_major = GSS_S_COMPLETE, first_minor = 0; + OM_uint32 initTimeOut = 0, acceptTimeOut = 0, outTime = GSS_C_INDEFINITE; + gss_OID_set mechs = GSS_C_NO_OID_SET; + gss_OID_set_desc except_attrs; + gss_OID_desc attr_oids[2]; + unsigned int i; + gss_union_cred_t creds = NULL; + + major = val_acq_cred_args(minor_status, + desired_name, + time_req, + desired_mechs, + cred_usage, + cred_store, + output_cred_handle, + actual_mechs, + time_rec); + if (major != GSS_S_COMPLETE) + goto cleanup; + + /* + * if desired_mechs equals GSS_C_NULL_OID_SET, then try to + * acquire credentials for all non-deprecated mechanisms. + */ + if (desired_mechs == GSS_C_NULL_OID_SET) { + attr_oids[0] = *GSS_C_MA_DEPRECATED; + attr_oids[1] = *GSS_C_MA_NOT_DFLT_MECH; + except_attrs.count = 2; + except_attrs.elements = attr_oids; + major = gss_indicate_mechs_by_attrs(minor_status, GSS_C_NO_OID_SET, + &except_attrs, GSS_C_NO_OID_SET, + &mechs); + if (major != GSS_S_COMPLETE) + goto cleanup; + } else + mechs = desired_mechs; + + if (mechs->count == 0) { + major = GSS_S_BAD_MECH; + goto cleanup; + } + + /* allocate the output credential structure */ + creds = (gss_union_cred_t)calloc(1, sizeof (gss_union_cred_desc)); + if (creds == NULL) { + major = GSS_S_FAILURE; + *minor_status = ENOMEM; + goto cleanup; + } + + creds->count = 0; + creds->loopback = creds; + + /* for each requested mech attempt to obtain a credential */ + for (i = 0, major = GSS_S_UNAVAILABLE; i < mechs->count; i++) { + major = gss_add_cred_from(&tmpMinor, (gss_cred_id_t)creds, + desired_name, &mechs->elements[i], + cred_usage, time_req, time_req, + cred_store, NULL, NULL, + time_rec ? &initTimeOut : NULL, + time_rec ? &acceptTimeOut : NULL); + if (major == GSS_S_COMPLETE) { + /* update the credential's time */ + if (cred_usage == GSS_C_ACCEPT) { + if (outTime > acceptTimeOut) + outTime = acceptTimeOut; + } else if (cred_usage == GSS_C_INITIATE) { + if (outTime > initTimeOut) + outTime = initTimeOut; + } else { + /* + * time_rec is the lesser of the + * init/accept times + */ + if (initTimeOut > acceptTimeOut) + outTime = (outTime > acceptTimeOut) ? + acceptTimeOut : outTime; + else + outTime = (outTime > initTimeOut) ? + initTimeOut : outTime; + } + } else if (first_major == GSS_S_COMPLETE) { + first_major = major; + first_minor = tmpMinor; + } + } /* for */ + + /* If we didn't get any creds, return the error status from the first mech + * (which is often the preferred one). */ + if (creds->count < 1) { + major = first_major; + *minor_status = first_minor; + goto cleanup; + } + major = GSS_S_COMPLETE; + + /* + * fill in output parameters + * setup the actual mechs output parameter + */ + if (actual_mechs != NULL) { + major = gssint_make_public_oid_set(minor_status, creds->mechs_array, + creds->count, actual_mechs); + if (GSS_ERROR(major)) + goto cleanup; + } + + if (time_rec) + *time_rec = outTime; + + *output_cred_handle = (gss_cred_id_t)creds; + +cleanup: + if (GSS_ERROR(major)) + gss_release_cred(&tmpMinor, (gss_cred_id_t *)&creds); + if (desired_mechs == GSS_C_NO_OID_SET) + generic_gss_release_oid_set(&tmpMinor, &mechs); + + return (major); +} + +static OM_uint32 +val_add_cred_args( + OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + gss_name_t desired_name, + gss_OID desired_mech, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_cred_handle != NULL) + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + if (actual_mechs != NULL) + *actual_mechs = GSS_C_NO_OID_SET; + + if (acceptor_time_rec != NULL) + *acceptor_time_rec = 0; + + if (initiator_time_rec != NULL) + *initiator_time_rec = 0; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (input_cred_handle == GSS_C_NO_CREDENTIAL && + output_cred_handle == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED); + + if (cred_usage != GSS_C_ACCEPT + && cred_usage != GSS_C_INITIATE + && cred_usage != GSS_C_BOTH) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + return (GSS_S_COMPLETE); +} + +/* Copy a mechanism credential (with the mechanism given by mech_oid) as + * faithfully as possible. */ +static OM_uint32 +copy_mech_cred(OM_uint32 *minor_status, gss_cred_id_t cred_in, + gss_OID mech_oid, gss_cred_id_t *cred_out) +{ + OM_uint32 status, tmpmin; + gss_mechanism mech; + gss_buffer_desc buf; + gss_name_t name; + OM_uint32 life; + gss_cred_usage_t usage; + gss_OID_set_desc oidset; + + mech = gssint_get_mechanism(mech_oid); + if (mech == NULL) + return (GSS_S_BAD_MECH); + if (mech->gss_export_cred != NULL && mech->gss_import_cred != NULL) { + status = mech->gss_export_cred(minor_status, cred_in, &buf); + if (status != GSS_S_COMPLETE) + return (status); + status = mech->gss_import_cred(minor_status, &buf, cred_out); + (void) gss_release_buffer(&tmpmin, &buf); + } else if (mech->gss_inquire_cred != NULL && + mech->gss_acquire_cred != NULL) { + status = mech->gss_inquire_cred(minor_status, cred_in, &name, &life, + &usage, NULL); + if (status != GSS_S_COMPLETE) + return (status); + oidset.count = 1; + oidset.elements = gssint_get_public_oid(mech_oid); + status = mech->gss_acquire_cred(minor_status, name, life, &oidset, + usage, cred_out, NULL, NULL); + gss_release_name(&tmpmin, &name); + } else { + status = GSS_S_UNAVAILABLE; + } + return (status); +} + +/* Copy a union credential from cred_in to *cred_out. */ +static OM_uint32 +copy_union_cred(OM_uint32 *minor_status, gss_cred_id_t cred_in, + gss_union_cred_t *cred_out) +{ + OM_uint32 status, tmpmin; + gss_union_cred_t cred = (gss_union_cred_t)cred_in; + gss_union_cred_t ncred = NULL; + gss_cred_id_t tmpcred; + int i; + + ncred = calloc(1, sizeof (*ncred)); + if (ncred == NULL) + goto oom; + ncred->mechs_array = calloc(cred->count, sizeof (*ncred->mechs_array)); + ncred->cred_array = calloc(cred->count, sizeof (*ncred->cred_array)); + if (ncred->mechs_array == NULL || ncred->cred_array == NULL) + goto oom; + ncred->count = cred->count; + + for (i = 0; i < cred->count; i++) { + /* Copy this element's mechanism OID. */ + ncred->mechs_array[i].elements = malloc(cred->mechs_array[i].length); + if (ncred->mechs_array[i].elements == NULL) + goto oom; + g_OID_copy(&ncred->mechs_array[i], &cred->mechs_array[i]); + + /* Copy this element's mechanism cred. */ + status = copy_mech_cred(minor_status, cred->cred_array[i], + &cred->mechs_array[i], &ncred->cred_array[i]); + if (status != GSS_S_COMPLETE) + goto error; + } + + ncred->loopback = ncred; + *cred_out = ncred; + return GSS_S_COMPLETE; + +oom: + status = GSS_S_FAILURE; + *minor_status = ENOMEM; +error: + tmpcred = (gss_cred_id_t)ncred; + (void) gss_release_cred(&tmpmin, &tmpcred); + return status; +} + +/* V2 KRB5_CALLCONV */ +OM_uint32 KRB5_CALLCONV +gss_add_cred(minor_status, input_cred_handle, + desired_name, desired_mech, cred_usage, + initiator_time_req, acceptor_time_req, + output_cred_handle, actual_mechs, + initiator_time_rec, acceptor_time_rec) + OM_uint32 *minor_status; + gss_cred_id_t input_cred_handle; + gss_name_t desired_name; + gss_OID desired_mech; + gss_cred_usage_t cred_usage; + OM_uint32 initiator_time_req; + OM_uint32 acceptor_time_req; + gss_cred_id_t *output_cred_handle; + gss_OID_set *actual_mechs; + OM_uint32 *initiator_time_rec; + OM_uint32 *acceptor_time_rec; +{ + return gss_add_cred_from(minor_status, input_cred_handle, desired_name, + desired_mech, cred_usage, initiator_time_req, + acceptor_time_req, NULL, output_cred_handle, + actual_mechs, initiator_time_rec, + acceptor_time_rec); +} + +OM_uint32 KRB5_CALLCONV +gss_add_cred_from(minor_status, input_cred_handle, + desired_name, desired_mech, + cred_usage, + initiator_time_req, acceptor_time_req, + cred_store, + output_cred_handle, actual_mechs, + initiator_time_rec, acceptor_time_rec) + OM_uint32 *minor_status; + gss_cred_id_t input_cred_handle; + gss_name_t desired_name; + gss_OID desired_mech; + gss_cred_usage_t cred_usage; + OM_uint32 initiator_time_req; + OM_uint32 acceptor_time_req; + gss_const_key_value_set_t cred_store; + gss_cred_id_t *output_cred_handle; + gss_OID_set *actual_mechs; + OM_uint32 *initiator_time_rec; + OM_uint32 *acceptor_time_rec; +{ + OM_uint32 status, temp_minor_status; + OM_uint32 time_req, time_rec = 0, *time_recp = NULL; + gss_union_name_t union_name; + gss_union_cred_t union_cred; + gss_name_t internal_name = GSS_C_NO_NAME; + gss_name_t allocated_name = GSS_C_NO_NAME; + gss_mechanism mech; + gss_cred_id_t cred = NULL, tmpcred; + void *newptr, *oidbuf = NULL; + gss_OID_set_desc target_mechs; + gss_OID selected_mech = GSS_C_NO_OID; + + status = val_add_cred_args(minor_status, + input_cred_handle, + desired_name, + desired_mech, + cred_usage, + cred_store, + initiator_time_req, + acceptor_time_req, + output_cred_handle, + actual_mechs, + initiator_time_rec, + acceptor_time_rec); + if (status != GSS_S_COMPLETE) + return (status); + + status = gssint_select_mech_type(minor_status, desired_mech, + &selected_mech); + if (status != GSS_S_COMPLETE) + return (status); + + mech = gssint_get_mechanism(selected_mech); + if (!mech) + return GSS_S_BAD_MECH; + else if (!mech->gss_acquire_cred) + return (GSS_S_UNAVAILABLE); + + union_cred = (gss_union_cred_t)input_cred_handle; + if (union_cred != NULL && + gssint_get_mechanism_cred(union_cred, + selected_mech) != GSS_C_NO_CREDENTIAL) + return (GSS_S_DUPLICATE_ELEMENT); + + if (union_cred == NULL) { + /* Create a new credential handle. */ + union_cred = malloc(sizeof (gss_union_cred_desc)); + if (union_cred == NULL) + return (GSS_S_FAILURE); + + (void) memset(union_cred, 0, sizeof (gss_union_cred_desc)); + union_cred->loopback = union_cred; + } else if (output_cred_handle != NULL) { + /* Create a new credential handle with the mechanism credentials of the + * input handle plus the acquired mechanism credential. */ + status = copy_union_cred(minor_status, input_cred_handle, &union_cred); + if (status != GSS_S_COMPLETE) + return (status); + } + + /* We may need to create a mechanism specific name. */ + if (desired_name != GSS_C_NO_NAME) { + union_name = (gss_union_name_t)desired_name; + if (union_name->mech_type && + g_OID_equal(union_name->mech_type, selected_mech)) { + internal_name = union_name->mech_name; + } else { + if (gssint_import_internal_name(minor_status, selected_mech, + union_name, &allocated_name) != + GSS_S_COMPLETE) { + status = GSS_S_BAD_NAME; + goto errout; + } + internal_name = allocated_name; + } + } + + + if (cred_usage == GSS_C_ACCEPT) + time_req = acceptor_time_req; + else if (cred_usage == GSS_C_INITIATE) + time_req = initiator_time_req; + else if (cred_usage == GSS_C_BOTH) + time_req = (acceptor_time_req > initiator_time_req) ? + acceptor_time_req : initiator_time_req; + else + time_req = 0; + + target_mechs.count = 1; + target_mechs.elements = gssint_get_public_oid(selected_mech); + if (target_mechs.elements == NULL) { + status = GSS_S_FAILURE; + goto errout; + } + + if (initiator_time_rec != NULL || acceptor_time_rec != NULL) + time_recp = &time_rec; + + if (mech->gss_acquire_cred_from) { + status = mech->gss_acquire_cred_from(minor_status, internal_name, + time_req, &target_mechs, + cred_usage, cred_store, &cred, + NULL, time_recp); + } else if (cred_store == GSS_C_NO_CRED_STORE) { + status = mech->gss_acquire_cred(minor_status, internal_name, time_req, + &target_mechs, cred_usage, &cred, NULL, + time_recp); + } else { + status = GSS_S_UNAVAILABLE; + goto errout; + } + + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + goto errout; + } + + /* Extend the arrays in the union cred. */ + + newptr = realloc(union_cred->mechs_array, + (union_cred->count + 1) * sizeof (gss_OID_desc)); + if (newptr == NULL) { + status = GSS_S_FAILURE; + goto errout; + } + union_cred->mechs_array = newptr; + + newptr = realloc(union_cred->cred_array, + (union_cred->count + 1) * sizeof (gss_cred_id_t)); + if (newptr == NULL) { + status = GSS_S_FAILURE; + goto errout; + } + union_cred->cred_array = newptr; + + if (acceptor_time_rec) + if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) + *acceptor_time_rec = time_rec; + if (initiator_time_rec) + if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) + *initiator_time_rec = time_rec; + + oidbuf = malloc(selected_mech->length); + if (oidbuf == NULL) + goto errout; + union_cred->mechs_array[union_cred->count].elements = oidbuf; + g_OID_copy(&union_cred->mechs_array[union_cred->count], selected_mech); + + if (actual_mechs != NULL) { + status = gssint_make_public_oid_set(minor_status, + union_cred->mechs_array, + union_cred->count + 1, + actual_mechs); + if (GSS_ERROR(status)) + goto errout; + } + + union_cred->cred_array[union_cred->count] = cred; + union_cred->count++; + if (output_cred_handle != NULL) + *output_cred_handle = (gss_cred_id_t)union_cred; + + /* We're done with the internal name. Free it if we allocated it. */ + + if (allocated_name) + (void) gssint_release_internal_name(&temp_minor_status, + selected_mech, + &allocated_name); + + return (GSS_S_COMPLETE); + +errout: + if (cred != NULL && mech->gss_release_cred) + mech->gss_release_cred(&temp_minor_status, &cred); + + if (allocated_name) + (void) gssint_release_internal_name(&temp_minor_status, + selected_mech, + &allocated_name); + + if (output_cred_handle != NULL && union_cred != NULL) { + tmpcred = union_cred; + (void) gss_release_cred(&temp_minor_status, &tmpcred); + } + + free(oidbuf); + + return (status); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c new file mode 100644 index 00000000..6ba170d8 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_acquire_cred_imp_name.c @@ -0,0 +1,529 @@ +/* #pragma ident "@(#)g_acquire_cred.c 1.22 04/02/23 SMI" */ + +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* Glue routine for gss_acquire_cred_impersonate_name */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include + +static OM_uint32 +val_acq_cred_impersonate_name_args( + OM_uint32 *minor_status, + const gss_cred_id_t impersonator_cred_handle, + const gss_name_t desired_name, + OM_uint32 time_req, + gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_cred_handle != NULL) + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + if (actual_mechs != NULL) + *actual_mechs = GSS_C_NULL_OID_SET; + + if (time_rec != NULL) + *time_rec = 0; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (impersonator_cred_handle == GSS_C_NO_CREDENTIAL) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED); + + if (desired_name == GSS_C_NO_NAME) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); + + if (output_cred_handle == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (cred_usage != GSS_C_ACCEPT + && cred_usage != GSS_C_INITIATE + && cred_usage != GSS_C_BOTH) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_acquire_cred_impersonate_name(OM_uint32 *minor_status, + const gss_cred_id_t impersonator_cred_handle, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + OM_uint32 major = GSS_S_FAILURE; + OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE; + gss_OID_set_desc default_OID_set; + gss_OID_set mechs; + gss_OID_desc default_OID; + gss_mechanism mech; + unsigned int i; + gss_union_cred_t creds; + + major = val_acq_cred_impersonate_name_args(minor_status, + impersonator_cred_handle, + desired_name, + time_req, + desired_mechs, + cred_usage, + output_cred_handle, + actual_mechs, + time_rec); + if (major != GSS_S_COMPLETE) + return (major); + + /* Initial value needed below. */ + major = GSS_S_FAILURE; + + /* + * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an + * appropriate default. We use the first mechanism in the + * mechanism list as the default. This set is created with + * statics thus needs not be freed + */ + if(desired_mechs == GSS_C_NULL_OID_SET) { + mech = gssint_get_mechanism(NULL); + if (mech == NULL) + return (GSS_S_BAD_MECH); + + mechs = &default_OID_set; + default_OID_set.count = 1; + default_OID_set.elements = &default_OID; + default_OID.length = mech->mech_type.length; + default_OID.elements = mech->mech_type.elements; + } else + mechs = desired_mechs; + + if (mechs->count == 0) + return (GSS_S_BAD_MECH); + + /* allocate the output credential structure */ + creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc)); + if (creds == NULL) + return (GSS_S_FAILURE); + + /* initialize to 0s */ + (void) memset(creds, 0, sizeof (gss_union_cred_desc)); + creds->loopback = creds; + + /* for each requested mech attempt to obtain a credential */ + for (i = 0; i < mechs->count; i++) { + major = gss_add_cred_impersonate_name(minor_status, + (gss_cred_id_t)creds, + impersonator_cred_handle, + desired_name, + &mechs->elements[i], + cred_usage, + time_req, + time_req, NULL, + NULL, + &initTimeOut, + &acceptTimeOut); + if (major == GSS_S_COMPLETE) { + /* update the credential's time */ + if (cred_usage == GSS_C_ACCEPT) { + if (outTime > acceptTimeOut) + outTime = acceptTimeOut; + } else if (cred_usage == GSS_C_INITIATE) { + if (outTime > initTimeOut) + outTime = initTimeOut; + } else { + /* + * time_rec is the lesser of the + * init/accept times + */ + if (initTimeOut > acceptTimeOut) + outTime = (outTime > acceptTimeOut) ? + acceptTimeOut : outTime; + else + outTime = (outTime > initTimeOut) ? + initTimeOut : outTime; + } + } + } /* for */ + + /* ensure that we have at least one credential element */ + if (creds->count < 1) { + free(creds); + return (major); + } + + /* + * fill in output parameters + * setup the actual mechs output parameter + */ + if (actual_mechs != NULL) { + gss_OID_set_desc oids; + + oids.count = creds->count; + oids.elements = creds->mechs_array; + + major = generic_gss_copy_oid_set(minor_status, &oids, actual_mechs); + if (GSS_ERROR(major)) { + (void) gss_release_cred(minor_status, + (gss_cred_id_t *)&creds); + return (major); + } + } + + if (time_rec) + *time_rec = outTime; + + + creds->loopback = creds; + *output_cred_handle = (gss_cred_id_t)creds; + return (GSS_S_COMPLETE); +} + +static OM_uint32 +val_add_cred_impersonate_name_args( + OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + const gss_cred_id_t impersonator_cred_handle, + gss_name_t desired_name, + gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_cred_handle != NULL) + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + if (actual_mechs != NULL) + *actual_mechs = GSS_C_NO_OID_SET; + + if (acceptor_time_rec != NULL) + *acceptor_time_rec = 0; + + if (initiator_time_rec != NULL) + *initiator_time_rec = 0; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (impersonator_cred_handle == GSS_C_NO_CREDENTIAL) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED); + + if (desired_name == GSS_C_NO_NAME) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); + + if (input_cred_handle == GSS_C_NO_CREDENTIAL && + output_cred_handle == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED); + + if (cred_usage != GSS_C_ACCEPT + && cred_usage != GSS_C_INITIATE + && cred_usage != GSS_C_BOTH) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + return (GSS_S_COMPLETE); +} + + +/* V2 KRB5_CALLCONV */ +OM_uint32 KRB5_CALLCONV +gss_add_cred_impersonate_name(OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + const gss_cred_id_t impersonator_cred_handle, + const gss_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + OM_uint32 status, temp_minor_status; + OM_uint32 time_req, time_rec; + gss_union_name_t union_name; + gss_union_cred_t new_union_cred, union_cred; + gss_cred_id_t mech_impersonator_cred; + gss_name_t internal_name = GSS_C_NO_NAME; + gss_name_t allocated_name = GSS_C_NO_NAME; + gss_mechanism mech; + gss_cred_id_t cred = NULL; + gss_OID new_mechs_array = NULL; + gss_cred_id_t * new_cred_array = NULL; + gss_OID_set target_mechs = GSS_C_NO_OID_SET; + gss_OID selected_mech = GSS_C_NO_OID; + + status = val_add_cred_impersonate_name_args(minor_status, + input_cred_handle, + impersonator_cred_handle, + desired_name, + desired_mech, + cred_usage, + initiator_time_req, + acceptor_time_req, + output_cred_handle, + actual_mechs, + initiator_time_rec, + acceptor_time_rec); + if (status != GSS_S_COMPLETE) + return (status); + + status = gssint_select_mech_type(minor_status, desired_mech, + &selected_mech); + if (status != GSS_S_COMPLETE) + return status; + + mech = gssint_get_mechanism(selected_mech); + if (!mech) + return GSS_S_BAD_MECH; + else if (!mech->gss_acquire_cred_impersonate_name) + return (GSS_S_UNAVAILABLE); + + if (input_cred_handle == GSS_C_NO_CREDENTIAL) { + union_cred = malloc(sizeof (gss_union_cred_desc)); + if (union_cred == NULL) + return (GSS_S_FAILURE); + + (void) memset(union_cred, 0, sizeof (gss_union_cred_desc)); + + /* for default credentials we will use GSS_C_NO_NAME */ + internal_name = GSS_C_NO_NAME; + } else { + union_cred = (gss_union_cred_t)input_cred_handle; + if (gssint_get_mechanism_cred(union_cred, selected_mech) != + GSS_C_NO_CREDENTIAL) + return (GSS_S_DUPLICATE_ELEMENT); + } + + mech_impersonator_cred = + gssint_get_mechanism_cred((gss_union_cred_t)impersonator_cred_handle, + selected_mech); + if (mech_impersonator_cred == GSS_C_NO_CREDENTIAL) + return (GSS_S_NO_CRED); + + /* may need to create a mechanism specific name */ + union_name = (gss_union_name_t)desired_name; + if (union_name->mech_type && + g_OID_equal(union_name->mech_type, selected_mech)) + internal_name = union_name->mech_name; + else { + if (gssint_import_internal_name(minor_status, + selected_mech, union_name, + &allocated_name) != GSS_S_COMPLETE) + return (GSS_S_BAD_NAME); + internal_name = allocated_name; + } + + if (cred_usage == GSS_C_ACCEPT) + time_req = acceptor_time_req; + else if (cred_usage == GSS_C_INITIATE) + time_req = initiator_time_req; + else if (cred_usage == GSS_C_BOTH) + time_req = (acceptor_time_req > initiator_time_req) ? + acceptor_time_req : initiator_time_req; + else + time_req = 0; + + status = gss_create_empty_oid_set(minor_status, &target_mechs); + if (status != GSS_S_COMPLETE) + goto errout; + + status = gss_add_oid_set_member(minor_status, + gssint_get_public_oid(selected_mech), + &target_mechs); + if (status != GSS_S_COMPLETE) + goto errout; + + status = mech->gss_acquire_cred_impersonate_name(minor_status, + mech_impersonator_cred, + internal_name, + time_req, + target_mechs, + cred_usage, + &cred, + NULL, + &time_rec); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + goto errout; + } + + /* now add the new credential elements */ + new_mechs_array = (gss_OID) + malloc(sizeof (gss_OID_desc) * (union_cred->count+1)); + + new_cred_array = (gss_cred_id_t *) + malloc(sizeof (gss_cred_id_t) * (union_cred->count+1)); + + if (!new_mechs_array || !new_cred_array) { + status = GSS_S_FAILURE; + goto errout; + } + + if (acceptor_time_rec) + if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) + *acceptor_time_rec = time_rec; + if (initiator_time_rec) + if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) + *initiator_time_rec = time_rec; + + /* + * OK, expand the mechanism array and the credential array + */ + (void) memcpy(new_mechs_array, union_cred->mechs_array, + sizeof (gss_OID_desc) * union_cred->count); + (void) memcpy(new_cred_array, union_cred->cred_array, + sizeof (gss_cred_id_t) * union_cred->count); + + new_cred_array[union_cred->count] = cred; + if ((new_mechs_array[union_cred->count].elements = + malloc(selected_mech->length)) == NULL) + goto errout; + + g_OID_copy(&new_mechs_array[union_cred->count], selected_mech); + + if (actual_mechs != NULL) { + status = gssint_make_public_oid_set(minor_status, new_mechs_array, + union_cred->count + 1, + actual_mechs); + if (GSS_ERROR(status)) { + free(new_mechs_array[union_cred->count].elements); + goto errout; + } + } + + if (output_cred_handle == NULL) { + free(union_cred->mechs_array); + free(union_cred->cred_array); + new_union_cred = union_cred; + } else { + new_union_cred = malloc(sizeof (gss_union_cred_desc)); + if (new_union_cred == NULL) { + free(new_mechs_array[union_cred->count].elements); + goto errout; + } + *new_union_cred = *union_cred; + *output_cred_handle = (gss_cred_id_t)new_union_cred; + } + + new_union_cred->mechs_array = new_mechs_array; + new_union_cred->cred_array = new_cred_array; + new_union_cred->count++; + new_union_cred->loopback = new_union_cred; + + /* We're done with the internal name. Free it if we allocated it. */ + + if (allocated_name) + (void) gssint_release_internal_name(&temp_minor_status, selected_mech, + &allocated_name); + + if (target_mechs) + (void) gss_release_oid_set(&temp_minor_status, &target_mechs); + + return (GSS_S_COMPLETE); + +errout: + if (new_mechs_array) + free(new_mechs_array); + if (new_cred_array) + free(new_cred_array); + + if (cred != NULL && mech->gss_release_cred) + mech->gss_release_cred(&temp_minor_status, &cred); + + if (allocated_name) + (void) gssint_release_internal_name(&temp_minor_status, + selected_mech, &allocated_name); + + if (target_mechs) + (void) gss_release_oid_set(&temp_minor_status, &target_mechs); + + if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) + free(union_cred); + + return (status); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_acquire_cred_with_pw.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_acquire_cred_with_pw.c new file mode 100644 index 00000000..cc34acc2 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_acquire_cred_with_pw.c @@ -0,0 +1,524 @@ +/* #pragma ident "@(#)g_acquire_cred.c 1.22 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_acquire_cred_with_password + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include +#include + +static OM_uint32 +val_acq_cred_pw_args( + OM_uint32 *minor_status, + const gss_name_t desired_name, + const gss_buffer_t password, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + int cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_cred_handle != NULL) + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + if (actual_mechs != NULL) + *actual_mechs = GSS_C_NULL_OID_SET; + + if (time_rec != NULL) + *time_rec = 0; + + /* Validate arguments. */ + + if (desired_name == GSS_C_NO_NAME) + return (GSS_S_BAD_NAME); + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (output_cred_handle == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (cred_usage != GSS_C_ACCEPT + && cred_usage != GSS_C_INITIATE + && cred_usage != GSS_C_BOTH) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + if (password == GSS_C_NO_BUFFER || + password->length == 0 || + password->value == NULL) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_acquire_cred_with_password( + minor_status, + desired_name, + password, + time_req, + desired_mechs, + cred_usage, + output_cred_handle, + actual_mechs, + time_rec) + +OM_uint32 * minor_status; +const gss_name_t desired_name; +const gss_buffer_t password; +OM_uint32 time_req; +const gss_OID_set desired_mechs; +int cred_usage; +gss_cred_id_t * output_cred_handle; +gss_OID_set * actual_mechs; +OM_uint32 * time_rec; +{ + OM_uint32 major = GSS_S_FAILURE; + OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE; + gss_OID_set_desc default_OID_set; + gss_OID_set mechs; + gss_OID_desc default_OID; + gss_mechanism mech; + unsigned int i; + gss_union_cred_t creds; + + major = val_acq_cred_pw_args(minor_status, + desired_name, + password, + time_req, + desired_mechs, + cred_usage, + output_cred_handle, + actual_mechs, + time_rec); + if (major != GSS_S_COMPLETE) + return (major); + + /* Initial value needed below. */ + major = GSS_S_FAILURE; + + /* + * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an + * appropriate default. We use the first mechanism in the + * mechanism list as the default. This set is created with + * statics thus needs not be freed + */ + if(desired_mechs == GSS_C_NULL_OID_SET) { + mech = gssint_get_mechanism(NULL); + if (mech == NULL) + return (GSS_S_BAD_MECH); + + mechs = &default_OID_set; + default_OID_set.count = 1; + default_OID_set.elements = &default_OID; + default_OID.length = mech->mech_type.length; + default_OID.elements = mech->mech_type.elements; + } else + mechs = desired_mechs; + + if (mechs->count == 0) + return (GSS_S_BAD_MECH); + + /* allocate the output credential structure */ + creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc)); + if (creds == NULL) + return (GSS_S_FAILURE); + + /* initialize to 0s */ + (void) memset(creds, 0, sizeof (gss_union_cred_desc)); + creds->loopback = creds; + + /* for each requested mech attempt to obtain a credential */ + for (i = 0; i < mechs->count; i++) { + major = gss_add_cred_with_password(minor_status, (gss_cred_id_t)creds, + desired_name, + &mechs->elements[i], + password, + cred_usage, time_req, time_req, NULL, + NULL, &initTimeOut, &acceptTimeOut); + if (major == GSS_S_COMPLETE) { + /* update the credential's time */ + if (cred_usage == GSS_C_ACCEPT) { + if (outTime > acceptTimeOut) + outTime = acceptTimeOut; + } else if (cred_usage == GSS_C_INITIATE) { + if (outTime > initTimeOut) + outTime = initTimeOut; + } else { + /* + * time_rec is the lesser of the + * init/accept times + */ + if (initTimeOut > acceptTimeOut) + outTime = (outTime > acceptTimeOut) ? + acceptTimeOut : outTime; + else + outTime = (outTime > initTimeOut) ? + initTimeOut : outTime; + } + } + } /* for */ + + /* ensure that we have at least one credential element */ + if (creds->count < 1) { + free(creds); + return (major); + } + + /* + * fill in output parameters + * setup the actual mechs output parameter + */ + if (actual_mechs != NULL) { + major = gssint_make_public_oid_set(minor_status, creds->mechs_array, + creds->count, actual_mechs); + if (GSS_ERROR(major)) { + (void) gss_release_cred(minor_status, + (gss_cred_id_t *)&creds); + return (major); + } + } + + if (time_rec) + *time_rec = outTime; + + + creds->loopback = creds; + *output_cred_handle = (gss_cred_id_t)creds; + return (GSS_S_COMPLETE); +} + +static OM_uint32 +val_add_cred_pw_args( + OM_uint32 *minor_status, + gss_cred_id_t input_cred_handle, + const gss_name_t desired_name, + const gss_OID desired_mech, + const gss_buffer_t password, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_cred_handle != NULL) + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + if (actual_mechs != NULL) + *actual_mechs = GSS_C_NO_OID_SET; + + if (acceptor_time_rec != NULL) + *acceptor_time_rec = 0; + + if (initiator_time_rec != NULL) + *initiator_time_rec = 0; + + /* Validate arguments. */ + + if (desired_name == GSS_C_NO_NAME) + return (GSS_S_BAD_NAME); + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (input_cred_handle == GSS_C_NO_CREDENTIAL && + output_cred_handle == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED); + + if (cred_usage != GSS_C_ACCEPT + && cred_usage != GSS_C_INITIATE + && cred_usage != GSS_C_BOTH) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + if (password == GSS_C_NO_BUFFER || + password->length == 0 || + password->value == NULL) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + + return (GSS_S_COMPLETE); +} + + +/* V2 KRB5_CALLCONV */ +OM_uint32 KRB5_CALLCONV +gss_add_cred_with_password(minor_status, input_cred_handle, + desired_name, desired_mech, password, cred_usage, + initiator_time_req, acceptor_time_req, + output_cred_handle, actual_mechs, + initiator_time_rec, acceptor_time_rec) + OM_uint32 *minor_status; + const gss_cred_id_t input_cred_handle; + const gss_name_t desired_name; + const gss_OID desired_mech; + const gss_buffer_t password; + gss_cred_usage_t cred_usage; + OM_uint32 initiator_time_req; + OM_uint32 acceptor_time_req; + gss_cred_id_t *output_cred_handle; + gss_OID_set *actual_mechs; + OM_uint32 *initiator_time_rec; + OM_uint32 *acceptor_time_rec; +{ + OM_uint32 status, temp_minor_status; + OM_uint32 time_req, time_rec; + gss_union_name_t union_name; + gss_union_cred_t new_union_cred, union_cred; + gss_name_t internal_name = GSS_C_NO_NAME; + gss_name_t allocated_name = GSS_C_NO_NAME; + gss_mechanism mech; + gss_cred_id_t cred = NULL; + gss_OID new_mechs_array = NULL; + gss_cred_id_t * new_cred_array = NULL; + gss_OID_set target_mechs = GSS_C_NO_OID_SET; + gss_OID selected_mech = GSS_C_NO_OID; + + status = val_add_cred_pw_args(minor_status, + input_cred_handle, + desired_name, + desired_mech, + password, + cred_usage, + initiator_time_req, + acceptor_time_req, + output_cred_handle, + actual_mechs, + initiator_time_rec, + acceptor_time_rec); + if (status != GSS_S_COMPLETE) + return (status); + + status = gssint_select_mech_type(minor_status, desired_mech, + &selected_mech); + if (status != GSS_S_COMPLETE) + return (status); + + mech = gssint_get_mechanism(selected_mech); + if (!mech) + return GSS_S_BAD_MECH; + if (!mech->gssspi_acquire_cred_with_password) + return GSS_S_UNAVAILABLE; + + if (input_cred_handle == GSS_C_NO_CREDENTIAL) { + union_cred = malloc(sizeof (gss_union_cred_desc)); + if (union_cred == NULL) + return (GSS_S_FAILURE); + + (void) memset(union_cred, 0, sizeof (gss_union_cred_desc)); + + /* for default credentials we will use GSS_C_NO_NAME */ + internal_name = GSS_C_NO_NAME; + } else { + union_cred = (gss_union_cred_t)input_cred_handle; + if (gssint_get_mechanism_cred(union_cred, selected_mech) != + GSS_C_NO_CREDENTIAL) + return (GSS_S_DUPLICATE_ELEMENT); + } + + /* may need to create a mechanism specific name */ + union_name = (gss_union_name_t)desired_name; + if (union_name->mech_type && + g_OID_equal(union_name->mech_type, selected_mech)) + internal_name = union_name->mech_name; + else { + if (gssint_import_internal_name(minor_status, + selected_mech, union_name, + &allocated_name) != GSS_S_COMPLETE) + return (GSS_S_BAD_NAME); + internal_name = allocated_name; + } + + if (cred_usage == GSS_C_ACCEPT) + time_req = acceptor_time_req; + else if (cred_usage == GSS_C_INITIATE) + time_req = initiator_time_req; + else if (cred_usage == GSS_C_BOTH) + time_req = (acceptor_time_req > initiator_time_req) ? + acceptor_time_req : initiator_time_req; + else + time_req = 0; + + status = gss_create_empty_oid_set(minor_status, &target_mechs); + if (status != GSS_S_COMPLETE) + goto errout; + + status = gss_add_oid_set_member(minor_status, + gssint_get_public_oid(selected_mech), + &target_mechs); + if (status != GSS_S_COMPLETE) + goto errout; + + status = mech->gssspi_acquire_cred_with_password(minor_status, + internal_name, + password, + time_req, + target_mechs, + cred_usage, + &cred, + NULL, + &time_rec); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + goto errout; + } + + /* now add the new credential elements */ + new_mechs_array = (gss_OID) + malloc(sizeof (gss_OID_desc) * (union_cred->count+1)); + + new_cred_array = (gss_cred_id_t *) + malloc(sizeof (gss_cred_id_t) * (union_cred->count+1)); + + if (!new_mechs_array || !new_cred_array) { + status = GSS_S_FAILURE; + goto errout; + } + + if (acceptor_time_rec) + if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) + *acceptor_time_rec = time_rec; + if (initiator_time_rec) + if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) + *initiator_time_rec = time_rec; + + /* + * OK, expand the mechanism array and the credential array + */ + (void) memcpy(new_mechs_array, union_cred->mechs_array, + sizeof (gss_OID_desc) * union_cred->count); + (void) memcpy(new_cred_array, union_cred->cred_array, + sizeof (gss_cred_id_t) * union_cred->count); + + new_cred_array[union_cred->count] = cred; + if ((new_mechs_array[union_cred->count].elements = + malloc(selected_mech->length)) == NULL) + goto errout; + + g_OID_copy(&new_mechs_array[union_cred->count], selected_mech); + + if (actual_mechs != NULL) { + status = gssint_make_public_oid_set(minor_status, new_mechs_array, + union_cred->count + 1, + actual_mechs); + if (GSS_ERROR(status)) { + free(new_mechs_array[union_cred->count].elements); + goto errout; + } + } + + if (output_cred_handle == NULL) { + free(union_cred->mechs_array); + free(union_cred->cred_array); + new_union_cred = union_cred; + } else { + new_union_cred = malloc(sizeof (gss_union_cred_desc)); + if (new_union_cred == NULL) { + free(new_mechs_array[union_cred->count].elements); + goto errout; + } + *new_union_cred = *union_cred; + *output_cred_handle = (gss_cred_id_t)new_union_cred; + } + + new_union_cred->mechs_array = new_mechs_array; + new_union_cred->cred_array = new_cred_array; + new_union_cred->count++; + new_union_cred->loopback = new_union_cred; + + /* We're done with the internal name. Free it if we allocated it. */ + + if (allocated_name) + (void) gssint_release_internal_name(&temp_minor_status, + selected_mech, + &allocated_name); + + if (target_mechs) + (void)gss_release_oid_set(&temp_minor_status, &target_mechs); + + return (GSS_S_COMPLETE); + +errout: + if (new_mechs_array) + free(new_mechs_array); + if (new_cred_array) + free(new_cred_array); + + if (cred != NULL && mech->gss_release_cred) + mech->gss_release_cred(&temp_minor_status, &cred); + + if (allocated_name) + (void) gssint_release_internal_name(&temp_minor_status, + selected_mech, &allocated_name); + + if (target_mechs) + (void)gss_release_oid_set(&temp_minor_status, &target_mechs); + + if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) + free(union_cred); + + return (status); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_authorize_localname.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_authorize_localname.c new file mode 100644 index 00000000..b6fc54da --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_authorize_localname.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2011, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* #pragma ident "@(#)g_userok.c 1.1 04/03/25 SMI" */ + +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +static OM_uint32 +mech_authorize_localname(OM_uint32 *minor, + const gss_union_name_t unionName, + const gss_union_name_t unionUser) +{ + OM_uint32 major = GSS_S_UNAVAILABLE; + gss_mechanism mech; + + if (unionName->mech_type == GSS_C_NO_OID) + return (GSS_S_NAME_NOT_MN); + + mech = gssint_get_mechanism(unionName->mech_type); + if (mech == NULL) + return (GSS_S_UNAVAILABLE); + + if (mech->gssspi_authorize_localname != NULL) { + major = mech->gssspi_authorize_localname(minor, + unionName->mech_name, + unionUser->external_name, + unionUser->name_type); + if (major != GSS_S_COMPLETE) + map_error(minor, mech); + } + + return (major); +} + +/* + * Naming extensions based local login authorization. + */ +static OM_uint32 +attr_authorize_localname(OM_uint32 *minor, + const gss_name_t name, + const gss_union_name_t unionUser) +{ + OM_uint32 major = GSS_S_UNAVAILABLE; /* attribute not present */ + gss_buffer_t externalName; + int more = -1; + + if (unionUser->name_type != GSS_C_NO_OID && + !g_OID_equal(unionUser->name_type, GSS_C_NT_USER_NAME)) + return (GSS_S_BAD_NAMETYPE); + + externalName = unionUser->external_name; + assert(externalName != GSS_C_NO_BUFFER); + + while (more != 0 && major != GSS_S_COMPLETE) { + OM_uint32 tmpMajor, tmpMinor; + gss_buffer_desc value; + gss_buffer_desc display_value; + int authenticated = 0, complete = 0; + + tmpMajor = gss_get_name_attribute(minor, + name, + GSS_C_ATTR_LOCAL_LOGIN_USER, + &authenticated, + &complete, + &value, + &display_value, + &more); + if (GSS_ERROR(tmpMajor)) { + major = tmpMajor; + break; + } + + if (authenticated && + value.length == externalName->length && + memcmp(value.value, externalName->value, externalName->length) == 0) + major = GSS_S_COMPLETE; + else + major = GSS_S_UNAUTHORIZED; + + gss_release_buffer(&tmpMinor, &value); + gss_release_buffer(&tmpMinor, &display_value); + } + + return (major); +} + +/* + * Equality based local login authorization. + */ +static OM_uint32 +compare_names_authorize_localname(OM_uint32 *minor, + const gss_union_name_t unionName, + const gss_name_t user) +{ + + OM_uint32 status, tmpMinor; + gss_name_t canonName; + int match = 0; + + status = gss_canonicalize_name(minor, + user, + unionName->mech_type, + &canonName); + if (status != GSS_S_COMPLETE) + return (status); + + status = gss_compare_name(minor, + (gss_name_t)unionName, + canonName, + &match); + if (status == GSS_S_COMPLETE && match == 0) + status = GSS_S_UNAUTHORIZED; + + (void) gss_release_name(&tmpMinor, &canonName); + + return (status); +} + +OM_uint32 KRB5_CALLCONV +gss_authorize_localname(OM_uint32 *minor, + const gss_name_t name, + const gss_name_t user) + +{ + OM_uint32 major; + gss_union_name_t unionName; + gss_union_name_t unionUser; + int mechAvailable = 0; + + if (minor == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + *minor = 0; + + if (name == GSS_C_NO_NAME || user == GSS_C_NO_NAME) + return (GSS_S_CALL_INACCESSIBLE_READ); + + unionName = (gss_union_name_t)name; + unionUser = (gss_union_name_t)user; + + if (unionUser->mech_type != GSS_C_NO_OID) + return (GSS_S_BAD_NAME); + + /* If mech returns yes, we return yes */ + major = mech_authorize_localname(minor, unionName, unionUser); + if (major == GSS_S_COMPLETE) + return (GSS_S_COMPLETE); + else if (major != GSS_S_UNAVAILABLE) + mechAvailable = 1; + + /* If attribute exists, we evaluate attribute */ + major = attr_authorize_localname(minor, unionName, unionUser); + if (major == GSS_S_COMPLETE || major == GSS_S_UNAUTHORIZED) + return (major); + + /* If mech did not implement SPI, compare the local name */ + if (mechAvailable == 0 && + unionName->mech_type != GSS_C_NO_OID) { + major = compare_names_authorize_localname(minor, + unionName, + unionUser); + } + + return (major); +} + +int KRB5_CALLCONV +gss_userok(const gss_name_t name, + const char *user) +{ + OM_uint32 major, minor; + gss_buffer_desc userBuf; + gss_name_t userName; + + userBuf.value = (void *)user; + userBuf.length = strlen(user); + + major = gss_import_name(&minor, &userBuf, GSS_C_NT_USER_NAME, &userName); + if (GSS_ERROR(major)) + return (0); + + major = gss_authorize_localname(&minor, name, userName); + + (void) gss_release_name(&minor, &userName); + + return (major == GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_buffer_set.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_buffer_set.c new file mode 100644 index 00000000..9310ddb4 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_buffer_set.c @@ -0,0 +1,55 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +OM_uint32 KRB5_CALLCONV gss_create_empty_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + return generic_gss_create_empty_buffer_set(minor_status, buffer_set); +} + +OM_uint32 KRB5_CALLCONV gss_add_buffer_set_member + (OM_uint32 * minor_status, + const gss_buffer_t member_buffer, + gss_buffer_set_t *buffer_set) +{ + return generic_gss_add_buffer_set_member(minor_status, + member_buffer, + buffer_set); +} + +OM_uint32 KRB5_CALLCONV gss_release_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + return generic_gss_release_buffer_set(minor_status, buffer_set); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_canon_name.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_canon_name.c new file mode 100644 index 00000000..61f657f9 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_canon_name.c @@ -0,0 +1,176 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* #pragma ident "@(#)g_canon_name.c 1.15 04/02/23 SMI" */ + +/* + * routine gss_canonicalize_name + * + * This routine is used to produce a mechanism specific + * representation of name that has been previously + * imported with gss_import_name. The routine uses the mechanism + * specific implementation of gss_import_name to implement this + * function. + * + * We allow a NULL output_name, in which case we modify the + * input_name to include the mechanism specific name. + */ + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +static OM_uint32 +val_canon_name_args( + OM_uint32 *minor_status, + const gss_name_t input_name, + const gss_OID mech_type, + gss_name_t *output_name) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_name != NULL) + *output_name = GSS_C_NO_NAME; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (input_name == GSS_C_NO_NAME || mech_type == GSS_C_NULL_OID) + return (GSS_S_CALL_INACCESSIBLE_READ); + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_canonicalize_name(minor_status, + input_name, + mech_type, + output_name) +OM_uint32 *minor_status; +const gss_name_t input_name; +const gss_OID mech_type; +gss_name_t *output_name; +{ + gss_union_name_t in_union, out_union = NULL, dest_union = NULL; + OM_uint32 major_status = GSS_S_FAILURE, tmpmin; + gss_OID selected_mech; + + major_status = val_canon_name_args(minor_status, + input_name, + mech_type, + output_name); + if (major_status != GSS_S_COMPLETE) + return (major_status); + + major_status = gssint_select_mech_type(minor_status, mech_type, + &selected_mech); + if (major_status != GSS_S_COMPLETE) + return (major_status); + + /* Initial value needed below. */ + major_status = GSS_S_FAILURE; + + in_union = (gss_union_name_t)input_name; + /* + * If the caller wants to reuse the name, and the name has already + * been converted, then there is nothing for us to do. + */ + if (!output_name && in_union->mech_type && + g_OID_equal(in_union->mech_type, selected_mech)) + return (GSS_S_COMPLETE); + + /* ok, then we need to do something - start by creating data struct */ + if (output_name) { + out_union = + (gss_union_name_t)malloc(sizeof (gss_union_name_desc)); + if (!out_union) + goto allocation_failure; + + out_union->mech_type = 0; + out_union->mech_name = 0; + out_union->name_type = 0; + out_union->external_name = 0; + out_union->loopback = out_union; + + /* Allocate the buffer for the user specified representation */ + if (gssint_create_copy_buffer(in_union->external_name, + &out_union->external_name, 1)) + goto allocation_failure; + + if (in_union->name_type != GSS_C_NULL_OID) { + major_status = generic_gss_copy_oid(minor_status, + in_union->name_type, + &out_union->name_type); + if (major_status) { + map_errcode(minor_status); + goto allocation_failure; + } + } + + } + + /* + * might need to delete any old mechanism names if we are + * reusing the buffer. + */ + if (!output_name) { + if (in_union->mech_type) { + (void) gssint_release_internal_name(minor_status, + in_union->mech_type, + &in_union->mech_name); + (void) gss_release_oid(minor_status, + &in_union->mech_type); + in_union->mech_type = 0; + } + dest_union = in_union; + } else + dest_union = out_union; + + /* now let's create the new mech name */ + if ((major_status = generic_gss_copy_oid(minor_status, selected_mech, + &dest_union->mech_type))) { + map_errcode(minor_status); + goto allocation_failure; + } + + if ((major_status = + gssint_import_internal_name(minor_status, selected_mech, + in_union, + &dest_union->mech_name))) + goto allocation_failure; + + if (output_name) + *output_name = (gss_name_t)dest_union; + + return (GSS_S_COMPLETE); + +allocation_failure: + if (out_union) { + /* Release the partly constructed out_union. */ + gss_name_t name = (gss_name_t)out_union; + (void) gss_release_name(&tmpmin, &name); + } else if (!output_name) { + /* Release only the mech name fields in in_union. */ + if (in_union->mech_name) { + (void) gssint_release_internal_name(&tmpmin, + dest_union->mech_type, + &dest_union->mech_name); + } + if (in_union->mech_type) + (void) gss_release_oid(&tmpmin, &dest_union->mech_type); + } + + return (major_status); +} /********** gss_canonicalize_name ********/ diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_compare_name.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_compare_name.c new file mode 100644 index 00000000..af2e76bb --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_compare_name.c @@ -0,0 +1,210 @@ +/* #pragma ident "@(#)g_compare_name.c 1.16 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_compare_name + * + */ + +#include "mglueP.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +static OM_uint32 +val_comp_name_args( + OM_uint32 *minor_status, + gss_name_t name1, + gss_name_t name2, + int *name_equal) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + /* Validate arguments. */ + + if (name1 == GSS_C_NO_NAME || name2 == GSS_C_NO_NAME) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); + + if (name_equal == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_compare_name (minor_status, + name1, + name2, + name_equal) + +OM_uint32 * minor_status; +gss_name_t name1; +gss_name_t name2; +int * name_equal; + +{ + OM_uint32 major_status, temp_minor; + gss_union_name_t union_name1, union_name2; + gss_mechanism mech = NULL; + gss_name_t internal_name; + + major_status = val_comp_name_args(minor_status, + name1, name2, name_equal); + if (major_status != GSS_S_COMPLETE) + return (major_status); + + union_name1 = (gss_union_name_t) name1; + union_name2 = (gss_union_name_t) name2; + /* + * Try our hardest to make union_name1 be the mechanism-specific + * name. (Of course we can't if both names aren't + * mechanism-specific.) + */ + if (union_name1->mech_type == 0) { + union_name1 = (gss_union_name_t) name2; + union_name2 = (gss_union_name_t) name1; + } + /* + * If union_name1 is mechanism specific, then fetch its mechanism + * information. + */ + if (union_name1->mech_type) { + mech = gssint_get_mechanism (union_name1->mech_type); + if (!mech) + return (GSS_S_BAD_MECH); + if (!mech->gss_compare_name) + return (GSS_S_UNAVAILABLE); + } + + *name_equal = 0; /* Default to *not* equal.... */ + + /* + * First case... both names are mechanism-specific + */ + if (union_name1->mech_type && union_name2->mech_type) { + if (!g_OID_equal(union_name1->mech_type, union_name2->mech_type)) + return (GSS_S_COMPLETE); + if ((union_name1->mech_name == 0) || (union_name2->mech_name == 0)) + /* should never happen */ + return (GSS_S_BAD_NAME); + if (!mech) + return (GSS_S_BAD_MECH); + if (!mech->gss_compare_name) + return (GSS_S_UNAVAILABLE); + major_status = mech->gss_compare_name(minor_status, + union_name1->mech_name, + union_name2->mech_name, + name_equal); + if (major_status != GSS_S_COMPLETE) + map_error(minor_status, mech); + return major_status; + } + + /* + * Second case... both names are NOT mechanism specific. + * + * All we do here is make sure the two name_types are equal and then + * that the external_names are equal. Note the we do not take care + * of the case where two different external names map to the same + * internal name. We cannot determine this, since we as yet do not + * know what mechanism to use for calling the underlying + * gss_import_name(). + */ + if (!union_name1->mech_type && !union_name2->mech_type) { + /* + * Second case, first sub-case... one name has null + * name_type, the other doesn't. + * + * Not knowing a mech_type we can't import the name with + * null name_type so we can't compare. + */ + if ((union_name1->name_type == GSS_C_NULL_OID && + union_name2->name_type != GSS_C_NULL_OID) || + (union_name1->name_type != GSS_C_NULL_OID && + union_name2->name_type == GSS_C_NULL_OID)) + return (GSS_S_COMPLETE); + /* + * Second case, second sub-case... both names have + * name_types, but they are different. + */ + if ((union_name1->name_type != GSS_C_NULL_OID && + union_name2->name_type != GSS_C_NULL_OID) && + !g_OID_equal(union_name1->name_type, + union_name2->name_type)) + return (GSS_S_COMPLETE); + /* + * Second case, third sub-case... both names have equal + * name_types (and both have no mech_types) so we just + * compare the external_names. + */ + if ((union_name1->external_name->length != + union_name2->external_name->length) || + (memcmp(union_name1->external_name->value, + union_name2->external_name->value, + union_name1->external_name->length) != 0)) + return (GSS_S_COMPLETE); + *name_equal = 1; + return (GSS_S_COMPLETE); + } + + /* + * Final case... one name is mechanism specific, the other isn't. + * + * We attempt to convert the general name to the mechanism type of + * the mechanism-specific name, and then do the compare. If we + * can't import the general name, then we return that the name is + * _NOT_ equal. + */ + if (union_name2->mech_type) { + /* We make union_name1 the mechanism specific name. */ + union_name1 = (gss_union_name_t) name2; + union_name2 = (gss_union_name_t) name1; + } + major_status = gssint_import_internal_name(minor_status, + union_name1->mech_type, + union_name2, + &internal_name); + if (major_status != GSS_S_COMPLETE) + return (GSS_S_COMPLETE); /* return complete, but not equal */ + + if (!mech) + return (GSS_S_BAD_MECH); + if (!mech->gss_compare_name) + return (GSS_S_UNAVAILABLE); + major_status = mech->gss_compare_name(minor_status, + union_name1->mech_name, + internal_name, name_equal); + if (major_status != GSS_S_COMPLETE) + map_error(minor_status, mech); + gssint_release_internal_name(&temp_minor, union_name1->mech_type, + &internal_name); + return (major_status); + +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_complete_auth_token.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_complete_auth_token.c new file mode 100644 index 00000000..4f028a77 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_complete_auth_token.c @@ -0,0 +1,77 @@ +/* #ident "@(#)gss_seal.c 1.10 95/08/07 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_complete_auth_token + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +OM_uint32 KRB5_CALLCONV +gss_complete_auth_token (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer) +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + *minor_status = 0; + if (input_message_buffer == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_READ; + if (context_handle == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + mech = gssint_get_mechanism (ctx->mech_type); + + if (mech != NULL) { + if (mech->gss_complete_auth_token != NULL) { + status = mech->gss_complete_auth_token(minor_status, + ctx->internal_ctx_id, + input_message_buffer); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_COMPLETE; + } else + status = GSS_S_BAD_MECH; + + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_context_time.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_context_time.c new file mode 100644 index 00000000..c947e764 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_context_time.c @@ -0,0 +1,81 @@ +/* #pragma ident "@(#)g_context_time.c 1.12 98/01/22 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routines for gss_context_time + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_context_time (minor_status, + context_handle, + time_rec) + +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +OM_uint32 * time_rec; + +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + *minor_status = 0; + + if (time_rec == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + + if (mech) { + + if (mech->gss_context_time) { + status = mech->gss_context_time( + minor_status, + ctx->internal_ctx_id, + time_rec); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + + return (GSS_S_BAD_MECH); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_decapsulate_token.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_decapsulate_token.c new file mode 100644 index 00000000..1c04e2f2 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_decapsulate_token.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2011, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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 "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_decapsulate_token(gss_const_buffer_t input_token, + gss_const_OID token_oid, + gss_buffer_t output_token) +{ + OM_uint32 minor; + unsigned int body_size = 0; + unsigned char *buf_in; + + if (input_token == GSS_C_NO_BUFFER || token_oid == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (output_token == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + buf_in = input_token->value; + + minor = g_verify_token_header(token_oid, &body_size, &buf_in, + -1, input_token->length, + G_VFY_TOKEN_HDR_WRAPPER_REQUIRED); + if (minor != 0) + return GSS_S_DEFECTIVE_TOKEN; + + output_token->value = gssalloc_malloc(body_size); + if (output_token->value == NULL) + return GSS_S_FAILURE; + + memcpy(output_token->value, buf_in, body_size); + output_token->length = body_size; + + return GSS_S_COMPLETE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_del_name_attr.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_del_name_attr.c new file mode 100644 index 00000000..21f15681 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_del_name_attr.c @@ -0,0 +1,65 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Glue routine for gss_delete_name_attribute */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_delete_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t attr) +{ + OM_uint32 status; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + *minor_status = 0; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) + return GSS_S_UNAVAILABLE; + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) + return GSS_S_BAD_NAME; + + if (mech->gss_delete_name_attribute == NULL) + return GSS_S_UNAVAILABLE; + + status = (*mech->gss_delete_name_attribute)(minor_status, + union_name->mech_name, + attr); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_delete_sec_context.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_delete_sec_context.c new file mode 100644 index 00000000..574ff029 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_delete_sec_context.c @@ -0,0 +1,106 @@ +/* #pragma ident "@(#)g_delete_sec_context.c 1.11 97/11/09 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_delete_sec_context + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif + +static OM_uint32 +val_del_sec_ctx_args( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_token != GSS_C_NO_BUFFER) { + output_token->length = 0; + output_token->value = NULL; + } + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CONTEXT); + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_delete_sec_context (minor_status, + context_handle, + output_token) + +OM_uint32 * minor_status; +gss_ctx_id_t * context_handle; +gss_buffer_t output_token; + +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + + status = val_del_sec_ctx_args(minor_status, context_handle, output_token); + if (status != GSS_S_COMPLETE) + return (status); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) *context_handle; + if (GSSINT_CHK_LOOP(ctx)) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + if (ctx->internal_ctx_id != GSS_C_NO_CONTEXT) { + status = gssint_delete_internal_sec_context(minor_status, + ctx->mech_type, + &ctx->internal_ctx_id, + output_token); + if (status) + return status; + } + + /* now free up the space for the union context structure */ + free(ctx->mech_type->elements); + free(ctx->mech_type); + free(*context_handle); + *context_handle = GSS_C_NO_CONTEXT; + + return (GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_dsp_name.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_dsp_name.c new file mode 100644 index 00000000..21867c81 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_dsp_name.c @@ -0,0 +1,118 @@ +/* #pragma ident "@(#)g_dsp_name.c 1.13 04/02/23 SMI" */ +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_display_name() + * + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +static OM_uint32 +val_dsp_name_args( + OM_uint32 *minor_status, + gss_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID *output_name_type) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_name_buffer != GSS_C_NO_BUFFER) { + output_name_buffer->length = 0; + output_name_buffer->value = NULL; + } + + if (output_name_type != NULL) + *output_name_type = GSS_C_NO_OID; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (output_name_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (input_name == GSS_C_NO_NAME) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_display_name (minor_status, + input_name, + output_name_buffer, + output_name_type) + +OM_uint32 * minor_status; +gss_name_t input_name; +gss_buffer_t output_name_buffer; +gss_OID * output_name_type; + +{ + OM_uint32 major_status; + gss_union_name_t union_name; + + major_status = val_dsp_name_args(minor_status, input_name, + output_name_buffer, output_name_type); + if (major_status != GSS_S_COMPLETE) + return (major_status); + + union_name = (gss_union_name_t) input_name; + + if (union_name->mech_type) { + /* + * OK, we have a mechanism-specific name; let's use it! + */ + return (gssint_display_internal_name(minor_status, + union_name->mech_type, + union_name->mech_name, + output_name_buffer, + output_name_type)); + } + + if ((output_name_buffer->value = + gssalloc_malloc(union_name->external_name->length + 1)) == NULL) + return (GSS_S_FAILURE); + output_name_buffer->length = union_name->external_name->length; + (void) memcpy(output_name_buffer->value, + union_name->external_name->value, + union_name->external_name->length); + ((char *)output_name_buffer->value)[output_name_buffer->length] = '\0'; + + if (output_name_type != NULL) + *output_name_type = union_name->name_type; + + return(GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_dsp_name_ext.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_dsp_name_ext.c new file mode 100644 index 00000000..be08dd16 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_dsp_name_ext.c @@ -0,0 +1,133 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_display_name_ext() + * + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +static OM_uint32 +val_dsp_name_ext_args( + OM_uint32 *minor_status, + gss_name_t input_name, + gss_OID display_as_name_type, + gss_buffer_t output_name_buffer) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_name_buffer != GSS_C_NO_BUFFER) { + output_name_buffer->length = 0; + output_name_buffer->value = NULL; + } + + /* Validate arguments. */ + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (output_name_buffer == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (input_name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + if (display_as_name_type == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAMETYPE; + + return GSS_S_COMPLETE; +} + + +OM_uint32 KRB5_CALLCONV +gss_display_name_ext (OM_uint32 *minor_status, + gss_name_t input_name, + gss_OID display_as_name_type, + gss_buffer_t output_name_buffer) +{ + OM_uint32 status; + gss_union_name_t union_name; + gss_mechanism mech; + + status = val_dsp_name_ext_args(minor_status, + input_name, + display_as_name_type, + output_name_buffer); + if (status != GSS_S_COMPLETE) + return status; + + union_name = (gss_union_name_t) input_name; + + if (union_name->mech_type) { + mech = gssint_get_mechanism(union_name->mech_type); + if (mech == NULL) + status = GSS_S_BAD_NAME; + else if (mech->gss_display_name_ext == NULL) { + if (mech->gss_display_name != NULL && + union_name->name_type != GSS_C_NO_OID && + g_OID_equal(display_as_name_type, union_name->name_type)) { + status = (*mech->gss_display_name)(minor_status, + union_name->mech_name, + output_name_buffer, + NULL); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + } else { + status = (*mech->gss_display_name_ext)(minor_status, + union_name->mech_name, + display_as_name_type, + output_name_buffer); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } + return status; + } + + if (union_name->name_type == GSS_C_NO_OID || + !g_OID_equal(display_as_name_type, union_name->name_type)) + return GSS_S_UNAVAILABLE; + + if ((output_name_buffer->value = + malloc(union_name->external_name->length + 1)) == NULL) { + return GSS_S_FAILURE; + } + output_name_buffer->length = union_name->external_name->length; + (void) memcpy(output_name_buffer->value, + union_name->external_name->value, + union_name->external_name->length); + ((char *)output_name_buffer->value)[output_name_buffer->length] = '\0'; + + return GSS_S_COMPLETE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_dsp_status.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_dsp_status.c new file mode 100644 index 00000000..70e84926 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_dsp_status.c @@ -0,0 +1,363 @@ +/* #pragma ident "@(#)g_dsp_status.c 1.17 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine gss_display_status + * + */ + +#include "mglueP.h" +#include +#include +#include + +/* local function */ +static OM_uint32 displayMajor(OM_uint32, OM_uint32 *, gss_buffer_t); + +OM_uint32 KRB5_CALLCONV +gss_display_status (minor_status, + status_value, + status_type, + req_mech_type, + message_context, + status_string) + +OM_uint32 * minor_status; +OM_uint32 status_value; +int status_type; +gss_OID req_mech_type; +OM_uint32 * message_context; +gss_buffer_t status_string; + +{ + gss_OID mech_type = (gss_OID) req_mech_type; + gss_mechanism mech; + gss_OID_desc m_oid = { 0, 0 }; + + if (minor_status != NULL) + *minor_status = 0; + + if (status_string != GSS_C_NO_BUFFER) { + status_string->length = 0; + status_string->value = NULL; + } + + if (minor_status == NULL || + message_context == NULL || + status_string == GSS_C_NO_BUFFER) + + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + /* we handle major status codes, and the mechs do the minor */ + if (status_type == GSS_C_GSS_CODE) + return (displayMajor(status_value, message_context, + status_string)); + + /* + * must be the minor status - let mechs do the work + * select the appropriate underlying mechanism routine and + * call it. + */ + + /* In this version, we only handle status codes that have been + mapped to a flat numbering space. Look up the value we got + passed. If it's not found, complain. */ + if (status_value == 0) { + status_string->value = gssalloc_strdup("Unknown error"); + if (status_string->value == NULL) { + *minor_status = ENOMEM; + map_errcode(minor_status); + return GSS_S_FAILURE; + } + status_string->length = strlen(status_string->value); + *message_context = 0; + *minor_status = 0; + return GSS_S_COMPLETE; + } + { + int err; + OM_uint32 m_status = 0, status; + + err = gssint_mecherrmap_get(status_value, &m_oid, &m_status); + if (err) { + *minor_status = err; + map_errcode(minor_status); + return GSS_S_BAD_STATUS; + } + if (m_oid.length == 0) { + /* Magic flag for com_err values. */ + status = g_display_com_err_status(minor_status, m_status, status_string); + if (status != GSS_S_COMPLETE) + map_errcode(minor_status); + return status; + } + mech_type = &m_oid; + status_value = m_status; + } + + mech = gssint_get_mechanism (mech_type); + + if (mech && mech->gss_display_status) { + OM_uint32 r; + + r = mech->gss_display_status(minor_status, + status_value, status_type, mech_type, + message_context, status_string); + /* How's this for weird? If we get an error returning the + mechanism-specific error code, we save away the + mechanism-specific error code describing the error. */ + if (r != GSS_S_COMPLETE) + map_error(minor_status, mech); + return r; + } + + if (!mech) + return (GSS_S_BAD_MECH); + + return (GSS_S_UNAVAILABLE); +} + +/* + * function to map the major error codes + * it uses case statements so that the strings could be wrapped by gettext + * msgCtxt is interpreted as: + * 0 - first call + * 1 - routine error + * >= 2 - the supplementary error code bit shifted by 1 + */ +static OM_uint32 +displayMajor(status, msgCtxt, outStr) +OM_uint32 status; +OM_uint32 *msgCtxt; +gss_buffer_t outStr; +{ + OM_uint32 oneVal, mask = 0x1, currErr; + char *errStr = NULL; + int i, haveErr = 0; + + /* take care of the success value first */ + if (status == GSS_S_COMPLETE) + errStr = _("The routine completed successfully"); + else if (*msgCtxt == 0 && (oneVal = GSS_CALLING_ERROR(status))) { + switch (oneVal) { + case GSS_S_CALL_INACCESSIBLE_READ: + errStr = _("A required input parameter could not be " + "read"); + break; + + case GSS_S_CALL_INACCESSIBLE_WRITE: + errStr = _("A required output parameter could not be " + "written"); + break; + + case GSS_S_CALL_BAD_STRUCTURE: + errStr = _("A parameter was malformed"); + break; + + default: + errStr = _("An invalid status code was supplied"); + break; + } + + /* we now need to determine new value of msgCtxt */ + if (GSS_ROUTINE_ERROR(status)) + *msgCtxt = 1; + else if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0) + *msgCtxt = (OM_uint32)(oneVal << 1); + else + *msgCtxt = 0; + + } else if ((*msgCtxt == 0 || *msgCtxt == 1) && + (oneVal = GSS_ROUTINE_ERROR(status))) { + switch (oneVal) { + case GSS_S_BAD_MECH: + errStr = _("An unsupported mechanism was requested"); + break; + + case GSS_S_BAD_NAME: + errStr = _("An invalid name was supplied"); + break; + + case GSS_S_BAD_NAMETYPE: + errStr = _("A supplied name was of an unsupported " + "type"); + break; + + case GSS_S_BAD_BINDINGS: + errStr = _("Incorrect channel bindings were supplied"); + break; + + case GSS_S_BAD_SIG: /* same as GSS_S_BAD_MIC: */ + errStr = _("A token had an invalid Message Integrity " + "Check (MIC)"); + break; + + case GSS_S_NO_CRED: + errStr = _("No credentials were supplied, or the " + "credentials were unavailable or " + "inaccessible"); + break; + + case GSS_S_NO_CONTEXT: + errStr = _("No context has been established"); + break; + + case GSS_S_DEFECTIVE_TOKEN: + errStr = _("Invalid token was supplied"); + break; + + case GSS_S_DEFECTIVE_CREDENTIAL: + errStr = _("Invalid credential was supplied"); + break; + + case GSS_S_CREDENTIALS_EXPIRED: + errStr = _("The referenced credential has expired"); + break; + + case GSS_S_CONTEXT_EXPIRED: + errStr = _("The referenced context has expired"); + break; + + case GSS_S_FAILURE: + errStr = _("Unspecified GSS failure. Minor code " + "may provide more information"); + break; + + case GSS_S_BAD_QOP: + errStr = _("The quality-of-protection (QOP) " + "requested could not be provided"); + break; + + case GSS_S_UNAUTHORIZED: + errStr = _("The operation is forbidden by local " + "security policy"); + break; + + case GSS_S_UNAVAILABLE: + errStr = _("The operation or option is not " + "available or unsupported"); + break; + + case GSS_S_DUPLICATE_ELEMENT: + errStr = _("The requested credential element " + "already exists"); + break; + + case GSS_S_NAME_NOT_MN: + errStr = _("The provided name was not mechanism " + "specific (MN)"); + break; + + case GSS_S_BAD_STATUS: + default: + errStr = _("An invalid status code was supplied"); + } + + /* we must determine if the caller should call us again */ + if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0) + *msgCtxt = (OM_uint32)(oneVal << 1); + else + *msgCtxt = 0; + + } else if ((*msgCtxt == 0 || *msgCtxt >= 2) && + (oneVal = GSS_SUPPLEMENTARY_INFO(status))) { + /* + * if msgCtxt is not 0, then it should encode + * the supplementary error code we should be printing + */ + if (*msgCtxt >= 2) + oneVal = (OM_uint32) (*msgCtxt) >> 1; + else + oneVal = GSS_SUPPLEMENTARY_INFO(status); + + /* we display the errors LSB first */ + for (i = 0; i < 16; i++) { + if (oneVal & mask) { + haveErr = 1; + break; + } + mask <<= 1; + } + + /* isolate the bit or if not found set to illegal value */ + if (haveErr) + currErr = oneVal & mask; + else + currErr = 1 << 17; /* illegal value */ + + switch (currErr) { + case GSS_S_CONTINUE_NEEDED: + errStr = _("The routine must be called again to " + "complete its function"); + break; + + case GSS_S_DUPLICATE_TOKEN: + errStr = _("The token was a duplicate of an earlier " + "token"); + break; + + case GSS_S_OLD_TOKEN: + errStr = _("The token's validity period has expired"); + break; + + case GSS_S_UNSEQ_TOKEN: + errStr = _("A later token has already been processed"); + break; + + case GSS_S_GAP_TOKEN: + errStr = _("An expected per-message token was not " + "received"); + break; + + default: + errStr = _("An invalid status code was supplied"); + } + + /* + * we must check if there is any other supplementary errors + * if found, then turn off current bit, and store next value + * in msgCtxt shifted by 1 bit + */ + if (!haveErr) + *msgCtxt = 0; + else if (GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask) + *msgCtxt = (OM_uint32) + ((GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask) << 1); + else + *msgCtxt = 0; + } + + if (errStr == NULL) + errStr = "An invalid status code was supplied"; + + /* now copy the status code and return to caller */ + outStr->length = strlen(errStr); + outStr->value = gssalloc_strdup(errStr); + if (outStr->value == NULL) { + outStr->length = 0; + return (GSS_S_FAILURE); + } + + return (GSS_S_COMPLETE); +} /* displayMajor */ diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_dup_name.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_dup_name.c new file mode 100644 index 00000000..ff01db27 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_dup_name.c @@ -0,0 +1,144 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* #pragma ident "@(#)g_dup_name.c 1.14 04/02/23 SMI" */ + +/* + * routine gss_duplicate_name + * + * This routine does not rely on mechanism implementation of this + * name, but instead uses mechanism specific gss_import_name routine. + */ + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +static OM_uint32 +val_dup_name_args( + OM_uint32 *minor_status, + const gss_name_t src_name, + gss_name_t *dest_name) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (dest_name != NULL) + *dest_name = GSS_C_NO_NAME; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + /* if output_name is NULL, simply return */ + if (dest_name == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (src_name == GSS_C_NO_NAME) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_duplicate_name(minor_status, + src_name, + dest_name) +OM_uint32 *minor_status; +const gss_name_t src_name; +gss_name_t *dest_name; +{ + gss_union_name_t src_union, dest_union; + OM_uint32 major_status = GSS_S_FAILURE; + + major_status = val_dup_name_args(minor_status, src_name, dest_name); + if (major_status != GSS_S_COMPLETE) + return (major_status); + + src_union = (gss_union_name_t)src_name; + + /* + * First create the union name struct that will hold the external + * name and the name type. + */ + dest_union = (gss_union_name_t)malloc(sizeof (gss_union_name_desc)); + if (!dest_union) + goto allocation_failure; + + dest_union->loopback = 0; + dest_union->mech_type = 0; + dest_union->mech_name = 0; + dest_union->name_type = 0; + dest_union->external_name = 0; + + /* Now copy the external representation. */ + if (gssint_create_copy_buffer(src_union->external_name, + &dest_union->external_name, 0)) + goto allocation_failure; + + if (src_union->name_type != GSS_C_NULL_OID) { + major_status = generic_gss_copy_oid(minor_status, + src_union->name_type, + &dest_union->name_type); + if (major_status != GSS_S_COMPLETE) { + map_errcode(minor_status); + goto allocation_failure; + } + } + + /* + * See if source name is mechanim specific, if so then need to import it + */ + if (src_union->mech_type) { + major_status = generic_gss_copy_oid(minor_status, + src_union->mech_type, + &dest_union->mech_type); + if (major_status != GSS_S_COMPLETE) { + map_errcode(minor_status); + goto allocation_failure; + } + + major_status = gssint_import_internal_name(minor_status, + src_union->mech_type, + src_union, + &dest_union->mech_name); + if (major_status != GSS_S_COMPLETE) + goto allocation_failure; + } + + + dest_union->loopback = dest_union; + *dest_name = (gss_name_t)dest_union; + return (GSS_S_COMPLETE); + +allocation_failure: + if (dest_union) { + if (dest_union->external_name) { + if (dest_union->external_name->value) + free(dest_union->external_name->value); + free(dest_union->external_name); + } + if (dest_union->name_type) + (void) generic_gss_release_oid(minor_status, + &dest_union->name_type); + if (dest_union->mech_name) + (void) gssint_release_internal_name(minor_status, + dest_union->mech_type, + &dest_union->mech_name); + if (dest_union->mech_type) + (void) generic_gss_release_oid(minor_status, + &dest_union->mech_type); + free(dest_union); + } + return (major_status); +} /* gss_duplicate_name */ diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_encapsulate_token.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_encapsulate_token.c new file mode 100644 index 00000000..1ccd3cd7 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_encapsulate_token.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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 "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_encapsulate_token(gss_const_buffer_t input_token, + gss_const_OID token_oid, + gss_buffer_t output_token) +{ + unsigned int tokenSize; + struct k5buf buf; + + if (input_token == GSS_C_NO_BUFFER || token_oid == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (output_token == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + tokenSize = g_token_size(token_oid, input_token->length); + + assert(tokenSize > 2); + tokenSize -= 2; /* TOK_ID */ + + output_token->value = gssalloc_malloc(tokenSize); + if (output_token->value == NULL) + return GSS_S_FAILURE; + + k5_buf_init_fixed(&buf, output_token->value, tokenSize); + g_make_token_header(&buf, token_oid, input_token->length, -1); + k5_buf_add_len(&buf, input_token->value, input_token->length); + assert(buf.len == tokenSize); + output_token->length = tokenSize; + + return GSS_S_COMPLETE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_exp_sec_context.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_exp_sec_context.c new file mode 100644 index 00000000..a04afe3d --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_exp_sec_context.c @@ -0,0 +1,146 @@ +/* #pragma ident "@(#)g_exp_sec_context.c 1.14 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_export_sec_context + */ +#ifndef LEAN_CLIENT + +#include "mglueP.h" +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +static OM_uint32 +val_exp_sec_ctx_args( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t interprocess_token) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (interprocess_token != GSS_C_NO_BUFFER) { + interprocess_token->length = 0; + interprocess_token->value = NULL; + } + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + if (interprocess_token == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_export_sec_context(minor_status, + context_handle, + interprocess_token) + +OM_uint32 * minor_status; +gss_ctx_id_t * context_handle; +gss_buffer_t interprocess_token; + +{ + OM_uint32 status; + OM_uint32 length; + gss_union_ctx_id_t ctx = NULL; + gss_mechanism mech; + gss_buffer_desc token = GSS_C_EMPTY_BUFFER; + char *buf; + + status = val_exp_sec_ctx_args(minor_status, + context_handle, interprocess_token); + if (status != GSS_S_COMPLETE) + return (status); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) *context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + if (!mech) + return GSS_S_BAD_MECH; + if (!mech->gss_export_sec_context) + return (GSS_S_UNAVAILABLE); + + status = mech->gss_export_sec_context(minor_status, + &ctx->internal_ctx_id, &token); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + goto cleanup; + } + + length = token.length + 4 + ctx->mech_type->length; + interprocess_token->length = length; + interprocess_token->value = gssalloc_malloc(length); + if (interprocess_token->value == 0) { + *minor_status = ENOMEM; + status = GSS_S_FAILURE; + goto cleanup; + } + buf = interprocess_token->value; + length = ctx->mech_type->length; + buf[3] = (unsigned char) (length & 0xFF); + length >>= 8; + buf[2] = (unsigned char) (length & 0xFF); + length >>= 8; + buf[1] = (unsigned char) (length & 0xFF); + length >>= 8; + buf[0] = (unsigned char) (length & 0xFF); + memcpy(buf+4, ctx->mech_type->elements, (size_t) ctx->mech_type->length); + memcpy(buf+4+ctx->mech_type->length, token.value, token.length); + + status = GSS_S_COMPLETE; + +cleanup: + (void) gss_release_buffer(minor_status, &token); + if (ctx != NULL && ctx->internal_ctx_id == GSS_C_NO_CONTEXT) { + /* If the mech deleted its context, delete the union context. */ + free(ctx->mech_type->elements); + free(ctx->mech_type); + free(ctx); + *context_handle = GSS_C_NO_CONTEXT; + } + return status; +} +#endif /*LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_export_cred.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_export_cred.c new file mode 100644 index 00000000..9678c6de --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_export_cred.c @@ -0,0 +1,111 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/mechglue/g_export_cred.c - gss_export_cred definition */ +/* + * Copyright (C) 2012 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. + */ + +#include "mglueP.h" + +static OM_uint32 +val_exp_cred_args(OM_uint32 *minor_status, gss_cred_id_t cred_handle, + gss_buffer_t token) +{ + + /* Initialize outputs. */ + if (minor_status != NULL) + *minor_status = 0; + if (token != GSS_C_NO_BUFFER) { + token->length = 0; + token->value = NULL; + } + + /* Validate arguments. */ + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + if (cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED; + if (token == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_WRITE; + return GSS_S_COMPLETE; +} + +OM_uint32 KRB5_CALLCONV +gss_export_cred(OM_uint32 * minor_status, gss_cred_id_t cred_handle, + gss_buffer_t token) +{ + OM_uint32 status, tmpmin; + gss_union_cred_t cred; + gss_OID mech_oid; + gss_OID public_oid; + gss_mechanism mech; + gss_buffer_desc mech_token; + struct k5buf buf; + int i; + + status = val_exp_cred_args(minor_status, cred_handle, token); + if (status != GSS_S_COMPLETE) + return status; + + k5_buf_init_dynamic(&buf); + + cred = (gss_union_cred_t) cred_handle; + for (i = 0; i < cred->count; i++) { + /* Get an export token for this mechanism. */ + mech_oid = &cred->mechs_array[i]; + public_oid = gssint_get_public_oid(mech_oid); + mech = gssint_get_mechanism(mech_oid); + if (public_oid == GSS_C_NO_OID || mech == NULL) { + status = GSS_S_DEFECTIVE_CREDENTIAL; + goto error; + } + if (mech->gss_export_cred == NULL) { + status = GSS_S_UNAVAILABLE; + goto error; + } + status = mech->gss_export_cred(minor_status, cred->cred_array[i], + &mech_token); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + goto error; + } + + /* Append the mech OID and token to buf. */ + k5_buf_add_uint32_be(&buf, public_oid->length); + k5_buf_add_len(&buf, public_oid->elements, public_oid->length); + k5_buf_add_uint32_be(&buf, mech_token.length); + k5_buf_add_len(&buf, mech_token.value, mech_token.length); + gss_release_buffer(&tmpmin, &mech_token); + } + + return k5buf_to_gss(minor_status, &buf, token); + +error: + k5_buf_free(&buf); + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_export_name.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_export_name.c new file mode 100644 index 00000000..c845f8ca --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_export_name.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1996,1997, by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* #pragma ident "@(#)g_export_name.c 1.11 00/07/17 SMI" */ + +/* + * glue routine gss_export_name + * + * Will either call the mechanism defined gss_export_name, or if one is + * not defined will call a generic_gss_export_name routine. + */ + +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +OM_uint32 KRB5_CALLCONV +gss_export_name(minor_status, + input_name, + exported_name) +OM_uint32 * minor_status; +const gss_name_t input_name; +gss_buffer_t exported_name; +{ + gss_union_name_t union_name; + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (exported_name != GSS_C_NO_BUFFER) { + exported_name->value = NULL; + exported_name->length = 0; + } + + /* Validate arguments. */ + + if (minor_status == NULL || exported_name == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (input_name == GSS_C_NO_NAME) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); + + union_name = (gss_union_name_t)input_name; + + /* the name must be in mechanism specific format */ + if (!union_name->mech_type) + return (GSS_S_NAME_NOT_MN); + + return gssint_export_internal_name(minor_status, union_name->mech_type, + union_name->mech_name, exported_name); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_export_name_comp.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_export_name_comp.c new file mode 100644 index 00000000..0a2bac41 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_export_name_comp.c @@ -0,0 +1,78 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +/* + * glue routine for gss_export_name_composite + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_export_name_composite(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t exp_composite_name) +{ + OM_uint32 status; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status != NULL) + *minor_status = 0; + + if (exp_composite_name != GSS_C_NO_BUFFER) { + exp_composite_name->value = NULL; + exp_composite_name->length = 0; + } + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + if (exp_composite_name == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) + return GSS_S_UNAVAILABLE; + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) + return GSS_S_BAD_NAME; + + if (mech->gss_export_name_composite == NULL) + return GSS_S_UNAVAILABLE; + + status = (*mech->gss_export_name_composite)(minor_status, + union_name->mech_name, + exp_composite_name); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_get_name_attr.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_get_name_attr.c new file mode 100644 index 00000000..2108beb3 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_get_name_attr.c @@ -0,0 +1,93 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Glue routine for gss_get_name_attribute */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_get_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + OM_uint32 status; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status != NULL) + *minor_status = 0; + if (authenticated != NULL) + *authenticated = 0; + if (complete != NULL) + *complete = 0; + if (value != GSS_C_NO_BUFFER) { + value->value = NULL; + value->length = 0; + } + if (display_value != GSS_C_NO_BUFFER) { + display_value->value = NULL; + display_value->length = 0; + } + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + if (attr == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_READ; + if (more == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) + return GSS_S_UNAVAILABLE; + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) + return GSS_S_BAD_NAME; + + if (mech->gss_get_name_attribute == NULL) + return GSS_S_UNAVAILABLE; + + status = (*mech->gss_get_name_attribute)(minor_status, + union_name->mech_name, + attr, + authenticated, + complete, + value, + display_value, + more); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_glue.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_glue.c new file mode 100644 index 00000000..176fbe63 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_glue.c @@ -0,0 +1,562 @@ +/* #pragma ident "@(#)g_glue.c 1.25 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "mglueP.h" +#include "k5-der.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +#define MSO_BIT (8*(sizeof (int) - 1)) /* Most significant octet bit */ + +extern gss_mechanism *gssint_mechs_array; + +/* + * This file contains the support routines for the glue layer. + */ + +/* Retrieve the mechanism OID from an RFC 2743 InitialContextToken. Place + * the result into *oid_out, aliasing memory from token. */ +OM_uint32 gssint_get_mech_type_oid(gss_OID oid_out, gss_buffer_t token) +{ + struct k5input in; + + if (oid_out == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + if (token == NULL || token->value == NULL) + return (GSS_S_DEFECTIVE_TOKEN); + + k5_input_init(&in, token->value, token->length); + if (!k5_der_get_value(&in, 0x60, &in)) + return (GSS_S_DEFECTIVE_TOKEN); + if (!k5_der_get_value(&in, 0x06, &in)) + return (GSS_S_DEFECTIVE_TOKEN); + oid_out->length = in.len; + oid_out->elements = (uint8_t *)in.ptr; + return (GSS_S_COMPLETE); +} + +/* + * The following mechanisms do not always identify themselves + * per the GSS-API specification, when interoperating with MS + * peers. We include the OIDs here so we do not have to ilnk + * with the mechanism. + */ +static gss_OID_desc gss_ntlm_mechanism_oid_desc = + {10, (void *)"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"}; +static gss_OID_desc gss_spnego_mechanism_oid_desc = + {6, (void *)"\x2b\x06\x01\x05\x05\x02"}; +static gss_OID_desc gss_krb5_mechanism_oid_desc = + {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; + +#define NTLMSSP_SIGNATURE "NTLMSSP" + +OM_uint32 gssint_get_mech_type(OID, token) + gss_OID OID; + gss_buffer_t token; +{ + /* Check for interoperability exceptions */ + if (token->length >= sizeof(NTLMSSP_SIGNATURE) && + memcmp(token->value, NTLMSSP_SIGNATURE, + sizeof(NTLMSSP_SIGNATURE)) == 0) { + *OID = gss_ntlm_mechanism_oid_desc; + } else if (token->length != 0 && + ((char *)token->value)[0] == 0x6E) { + /* Could be a raw AP-REQ (check for APPLICATION tag) */ + *OID = gss_krb5_mechanism_oid_desc; + } else if (token->length == 0) { + *OID = gss_spnego_mechanism_oid_desc; + } else { + return gssint_get_mech_type_oid(OID, token); + } + + return (GSS_S_COMPLETE); +} + +static OM_uint32 +import_internal_attributes(OM_uint32 *minor, + gss_mechanism dmech, + gss_union_name_t sname, + gss_name_t dname) +{ + OM_uint32 major, tmpMinor; + gss_mechanism smech; + gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET; + size_t i; + + if (sname->mech_name == GSS_C_NO_NAME) + return (GSS_S_UNAVAILABLE); + + smech = gssint_get_mechanism (sname->mech_type); + if (smech == NULL) + return (GSS_S_BAD_MECH); + + if (smech->gss_inquire_name == NULL || + smech->gss_get_name_attribute == NULL) + return (GSS_S_UNAVAILABLE); + + if (dmech->gss_set_name_attribute == NULL) + return (GSS_S_UNAVAILABLE); + + major = smech->gss_inquire_name(minor, sname->mech_name, + NULL, NULL, &attrs); + if (GSS_ERROR(major) || attrs == GSS_C_NO_BUFFER_SET) { + gss_release_buffer_set(&tmpMinor, &attrs); + return (major); + } + + for (i = 0; i < attrs->count; i++) { + int more = -1; + + while (more != 0) { + gss_buffer_desc value, display_value; + int authenticated, complete; + + major = smech->gss_get_name_attribute(minor, sname->mech_name, + &attrs->elements[i], + &authenticated, &complete, + &value, &display_value, + &more); + if (GSS_ERROR(major)) + continue; + + if (authenticated) { + dmech->gss_set_name_attribute(minor, dname, complete, + &attrs->elements[i], &value); + } + + gss_release_buffer(&tmpMinor, &value); + gss_release_buffer(&tmpMinor, &display_value); + } + } + + gss_release_buffer_set(&tmpMinor, &attrs); + + return (GSS_S_COMPLETE); +} + +/* + * Internal routines to get and release an internal mechanism name + */ + +OM_uint32 gssint_import_internal_name (minor_status, mech_type, union_name, + internal_name) +OM_uint32 *minor_status; +gss_OID mech_type; +gss_union_name_t union_name; +gss_name_t *internal_name; +{ + OM_uint32 status, tmpMinor; + gss_mechanism mech; + gss_OID public_mech; + + mech = gssint_get_mechanism (mech_type); + if (mech == NULL) + return (GSS_S_BAD_MECH); + + /* + * If we are importing a name for the same mechanism, and the + * mechanism implements gss_duplicate_name, then use that. + */ + if (union_name->mech_type != GSS_C_NO_OID && + union_name->mech_name != GSS_C_NO_NAME && + g_OID_equal(union_name->mech_type, mech_type) && + mech->gss_duplicate_name != NULL) { + status = mech->gss_duplicate_name(minor_status, + union_name->mech_name, + internal_name); + if (status != GSS_S_UNAVAILABLE) { + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + return (status); + } + } + + if (mech->gssspi_import_name_by_mech) { + public_mech = gssint_get_public_oid(mech_type); + status = mech->gssspi_import_name_by_mech(minor_status, public_mech, + union_name->external_name, + union_name->name_type, + internal_name); + } else if (mech->gss_import_name) { + status = mech->gss_import_name(minor_status, union_name->external_name, + union_name->name_type, internal_name); + } else { + return (GSS_S_UNAVAILABLE); + } + + if (status == GSS_S_COMPLETE) { + /* Attempt to round-trip attributes */ + (void) import_internal_attributes(&tmpMinor, mech, + union_name, *internal_name); + } else { + map_error(minor_status, mech); + } + + return (status); +} + +OM_uint32 gssint_export_internal_name(minor_status, mech_type, + internal_name, name_buf) + OM_uint32 *minor_status; + const gss_OID mech_type; + const gss_name_t internal_name; + gss_buffer_t name_buf; +{ + OM_uint32 status; + gss_mechanism mech; + gss_buffer_desc dispName; + gss_OID nameOid; + int mech_der_len = 0; + struct k5buf buf; + + mech = gssint_get_mechanism(mech_type); + if (!mech) + return (GSS_S_BAD_MECH); + + if (mech->gss_export_name) { + status = mech->gss_export_name(minor_status, + internal_name, + name_buf); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + return status; + } + + /* + * if we are here it is because the mechanism does not provide + * a gss_export_name so we will use our implementation. We + * do required that the mechanism define a gss_display_name. + */ + if (!mech->gss_display_name) + return (GSS_S_UNAVAILABLE); + + /* + * NOTE: RFC2743 (section 3.2) governs the format of the outer + * wrapper of exported names; the mechanisms' specs govern + * the format of the inner portion of the exported name + * and, for some (e.g., RFC1964, the Kerberos V mech), a + * generic default as implemented here will do. + * + * The outer wrapper of an exported MN is: 2-octet tok Id + * (0x0401) + 2-octet network-byte order mech OID length + mech + * oid (in DER format, including DER tag and DER length) + + * 4-octet network-byte order length of inner portion + inner + * portion. + * + * For the Kerberos V mechanism the inner portion of an exported + * MN is the display name string and ignores the name type OID + * altogether. And we hope this will be so for any future + * mechanisms also, so that factoring name export/import out of + * the mech and into libgss pays off. + */ + if ((status = mech->gss_display_name(minor_status, + internal_name, + &dispName, + &nameOid)) + != GSS_S_COMPLETE) { + map_error(minor_status, mech); + return (status); + } + + /* Allocate space and prepare a buffer. */ + mech_der_len = k5_der_value_len(mech_type->length); + name_buf->length = 2 + 2 + mech_der_len + 4 + dispName.length; + name_buf->value = gssalloc_malloc(name_buf->length); + if (name_buf->value == NULL) { + name_buf->length = 0; + (void) gss_release_buffer(&status, &dispName); + return (GSS_S_FAILURE); + } + k5_buf_init_fixed(&buf, name_buf->value, name_buf->length); + + /* Assemble the name. */ + k5_buf_add_len(&buf, "\x04\x01", 2); + k5_buf_add_uint16_be(&buf, mech_der_len); + k5_der_add_value(&buf, 0x06, mech_type->elements, mech_type->length); + k5_buf_add_uint32_be(&buf, dispName.length); + k5_buf_add_len(&buf, dispName.value, dispName.length); + assert(buf.len == name_buf->length); + + /* release the buffer obtained from gss_display_name */ + (void) gss_release_buffer(minor_status, &dispName); + return (GSS_S_COMPLETE); +} /* gssint_export_internal_name */ + +OM_uint32 gssint_display_internal_name (minor_status, mech_type, internal_name, + external_name, name_type) +OM_uint32 *minor_status; +gss_OID mech_type; +gss_name_t internal_name; +gss_buffer_t external_name; +gss_OID *name_type; +{ + OM_uint32 status; + gss_mechanism mech; + + mech = gssint_get_mechanism (mech_type); + if (mech) { + if (mech->gss_display_name) { + status = mech->gss_display_name ( + minor_status, + internal_name, + external_name, + name_type); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return (status); + } + + return (GSS_S_BAD_MECH); +} + +OM_uint32 gssint_release_internal_name (minor_status, mech_type, internal_name) +OM_uint32 *minor_status; +gss_OID mech_type; +gss_name_t *internal_name; +{ + OM_uint32 status; + gss_mechanism mech; + + mech = gssint_get_mechanism (mech_type); + if (mech) { + if (mech->gss_release_name) { + status = mech->gss_release_name ( + minor_status, + internal_name); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return (status); + } + + return (GSS_S_BAD_MECH); +} + +OM_uint32 gssint_delete_internal_sec_context (minor_status, + mech_type, + internal_ctx, + output_token) +OM_uint32 *minor_status; +gss_OID mech_type; +gss_ctx_id_t *internal_ctx; +gss_buffer_t output_token; +{ + OM_uint32 status; + gss_mechanism mech; + + mech = gssint_get_mechanism (mech_type); + if (mech) { + if (mech->gss_delete_sec_context) + status = mech->gss_delete_sec_context (minor_status, + internal_ctx, + output_token); + else + status = GSS_S_UNAVAILABLE; + + return (status); + } + + return (GSS_S_BAD_MECH); +} + +/* + * This function converts an internal gssapi name to a union gssapi + * name. Note that internal_name should be considered "consumed" by + * this call, whether or not we return an error. + */ +OM_uint32 gssint_convert_name_to_union_name(minor_status, mech, + internal_name, external_name) + OM_uint32 *minor_status; + gss_mechanism mech; + gss_name_t internal_name; + gss_name_t *external_name; +{ + OM_uint32 major_status,tmp; + gss_union_name_t union_name; + + union_name = (gss_union_name_t) malloc (sizeof(gss_union_name_desc)); + if (!union_name) { + major_status = GSS_S_FAILURE; + *minor_status = ENOMEM; + map_errcode(minor_status); + goto allocation_failure; + } + union_name->mech_type = 0; + union_name->mech_name = internal_name; + union_name->name_type = 0; + union_name->external_name = 0; + + major_status = generic_gss_copy_oid(minor_status, &mech->mech_type, + &union_name->mech_type); + if (major_status != GSS_S_COMPLETE) { + map_errcode(minor_status); + goto allocation_failure; + } + + union_name->external_name = + (gss_buffer_t) malloc(sizeof(gss_buffer_desc)); + if (!union_name->external_name) { + major_status = GSS_S_FAILURE; + goto allocation_failure; + } + union_name->external_name->length = 0; + union_name->external_name->value = NULL; + + major_status = mech->gss_display_name(minor_status, + internal_name, + union_name->external_name, + &union_name->name_type); + if (major_status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + goto allocation_failure; + } + + union_name->loopback = union_name; + *external_name = /*(gss_name_t) CHECK */union_name; + return (GSS_S_COMPLETE); + +allocation_failure: + if (union_name) { + if (union_name->external_name) { + if (union_name->external_name->value) + free(union_name->external_name->value); + free(union_name->external_name); + } + if (union_name->name_type) + gss_release_oid(&tmp, &union_name->name_type); + if (union_name->mech_type) + gss_release_oid(&tmp, &union_name->mech_type); + free(union_name); + } + /* + * do as the top comment says - since we are now owners of + * internal_name, we must clean it up + */ + if (internal_name) + (void) gssint_release_internal_name(&tmp, &mech->mech_type, + &internal_name); + return (major_status); +} + +/* + * Glue routine for returning the mechanism-specific credential from a + * external union credential. + */ +gss_cred_id_t +gssint_get_mechanism_cred(union_cred, mech_type) + gss_union_cred_t union_cred; + gss_OID mech_type; +{ + int i; + + if (union_cred == GSS_C_NO_CREDENTIAL) + return GSS_C_NO_CREDENTIAL; + + for (i=0; i < union_cred->count; i++) { + if (g_OID_equal(mech_type, &union_cred->mechs_array[i])) + return union_cred->cred_array[i]; + } + return GSS_C_NO_CREDENTIAL; +} + +/* + * Routine to create and copy the gss_buffer_desc structure. + * Both space for the structure and the data is allocated. + */ +OM_uint32 +gssint_create_copy_buffer(srcBuf, destBuf, addNullChar) + const gss_buffer_t srcBuf; + gss_buffer_t *destBuf; + int addNullChar; +{ + gss_buffer_t aBuf; + unsigned int len; + + if (destBuf == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + *destBuf = 0; + + aBuf = (gss_buffer_t)malloc(sizeof (gss_buffer_desc)); + if (!aBuf) + return (GSS_S_FAILURE); + + if (addNullChar) + len = srcBuf->length + 1; + else + len = srcBuf->length; + + if (!(aBuf->value = (void*)gssalloc_malloc(len))) { + free(aBuf); + return (GSS_S_FAILURE); + } + + + (void) memcpy(aBuf->value, srcBuf->value, srcBuf->length); + aBuf->length = srcBuf->length; + *destBuf = aBuf; + + /* optionally add a NULL character */ + if (addNullChar) + ((char *)aBuf->value)[aBuf->length] = '\0'; + + return (GSS_S_COMPLETE); +} /* ****** gssint_create_copy_buffer ****** */ + +OM_uint32 +gssint_create_union_context(OM_uint32 *minor, gss_const_OID mech_oid, + gss_union_ctx_id_t *ctx_out) +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + + *ctx_out = NULL; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + status = generic_gss_copy_oid(minor, mech_oid, &ctx->mech_type); + if (status != GSS_S_COMPLETE) { + free(ctx); + return status; + } + + ctx->loopback = ctx; + ctx->internal_ctx_id = GSS_C_NO_CONTEXT; + + *ctx_out = ctx; + return GSS_S_COMPLETE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_imp_cred.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_imp_cred.c new file mode 100644 index 00000000..77e2ff55 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_imp_cred.c @@ -0,0 +1,177 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/mechglue/g_imp_cred.c - gss_import_cred definition */ +/* + * Copyright (C) 2012 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. + */ + +#include "mglueP.h" + +static OM_uint32 +val_imp_cred_args(OM_uint32 *minor_status, gss_buffer_t token, + gss_cred_id_t *cred_handle) +{ + /* Initialize outputs. */ + if (minor_status != NULL) + *minor_status = 0; + if (cred_handle != NULL) + *cred_handle = GSS_C_NO_CREDENTIAL; + + /* Validate arguments. */ + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + if (cred_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + if (token == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_DEFECTIVE_TOKEN; + if (GSS_EMPTY_BUFFER(token)) + return GSS_S_DEFECTIVE_TOKEN; + return GSS_S_COMPLETE; +} + +/* Populate mech_oid and mech_token with the next entry in token, using aliased + * memory from token. Advance token by the amount consumed. */ +static OM_uint32 +get_entry(OM_uint32 *minor_status, gss_buffer_t token, gss_OID mech_oid, + gss_buffer_t mech_token) +{ + OM_uint32 len; + + /* Get the mechanism OID. */ + if (token->length < 4) + return GSS_S_DEFECTIVE_TOKEN; + len = load_32_be(token->value); + if (token->length - 4 < len) + return GSS_S_DEFECTIVE_TOKEN; + mech_oid->length = len; + mech_oid->elements = (char *)token->value + 4; + token->value = (char *)token->value + 4 + len; + token->length -= 4 + len; + + /* Get the mechanism token. */ + if (token->length < 4) + return GSS_S_DEFECTIVE_TOKEN; + len = load_32_be(token->value); + if (token->length - 4 < len) + return GSS_S_DEFECTIVE_TOKEN; + mech_token->length = len; + mech_token->value = (char *)token->value + 4; + token->value = (char *)token->value + 4 + len; + token->length -= 4 + len; + + return GSS_S_COMPLETE; +} + +OM_uint32 KRB5_CALLCONV +gss_import_cred(OM_uint32 *minor_status, gss_buffer_t token, + gss_cred_id_t *cred_handle) +{ + OM_uint32 status, tmpmin, count; + gss_union_cred_t cred = NULL; + gss_mechanism mech; + gss_buffer_desc tok, mech_token; + gss_OID_desc mech_oid; + gss_OID selected_mech; + gss_cred_id_t mech_cred; + void *elemcopy; + + status = val_imp_cred_args(minor_status, token, cred_handle); + if (status != GSS_S_COMPLETE) + return status; + + /* Count the entries in token. */ + for (tok = *token, count = 0; tok.length > 0; count++) { + status = get_entry(minor_status, &tok, &mech_oid, &mech_token); + if (status != GSS_S_COMPLETE) + return status; + } + + /* Allocate a union credential. */ + cred = calloc(1, sizeof(*cred)); + if (cred == NULL) + goto oom; + cred->loopback = cred; + cred->count = 0; + cred->mechs_array = calloc(count, sizeof(*cred->mechs_array)); + if (cred->mechs_array == NULL) + goto oom; + cred->cred_array = calloc(count, sizeof(*cred->cred_array)); + if (cred->cred_array == NULL) + goto oom; + + tok = *token; + while (tok.length > 0) { + (void)get_entry(minor_status, &tok, &mech_oid, &mech_token); + + /* Import this entry's mechanism token. */ + status = gssint_select_mech_type(minor_status, &mech_oid, + &selected_mech); + if (status != GSS_S_COMPLETE) + goto error; + mech = gssint_get_mechanism(selected_mech); + if (mech == NULL || (mech->gss_import_cred == NULL && + mech->gssspi_import_cred_by_mech == NULL)) { + status = GSS_S_DEFECTIVE_TOKEN; + goto error; + } + if (mech->gssspi_import_cred_by_mech) { + status = mech->gssspi_import_cred_by_mech(minor_status, + gssint_get_public_oid(selected_mech), + &mech_token, &mech_cred); + } else { + status = mech->gss_import_cred(minor_status, &mech_token, + &mech_cred); + } + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + goto error; + } + + /* Add the resulting mechanism cred to the union cred. */ + elemcopy = malloc(selected_mech->length); + if (elemcopy == NULL) { + if (mech->gss_release_cred != NULL) + mech->gss_release_cred(&tmpmin, &mech_cred); + goto oom; + } + memcpy(elemcopy, selected_mech->elements, selected_mech->length); + cred->mechs_array[cred->count].length = selected_mech->length; + cred->mechs_array[cred->count].elements = elemcopy; + cred->cred_array[cred->count++] = mech_cred; + } + + *cred_handle = cred; + return GSS_S_COMPLETE; + +oom: + status = GSS_S_FAILURE; + *minor_status = ENOMEM; +error: + (void)gss_release_cred(&tmpmin, &cred); + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_imp_name.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_imp_name.c new file mode 100644 index 00000000..a805078a --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_imp_name.c @@ -0,0 +1,333 @@ +/* #pragma ident "@(#)g_imp_name.c 1.26 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine gss_import_name + * + */ + +#include "mglueP.h" +#include "k5-der.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +/* local function to import GSS_C_EXPORT_NAME names */ +static OM_uint32 importExportName(OM_uint32 *, gss_union_name_t, gss_OID); + +static OM_uint32 +val_imp_name_args( + OM_uint32 *minor_status, + gss_buffer_t input_name_buffer, + gss_OID input_name_type, + gss_name_t *output_name) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_name != NULL) + *output_name = GSS_C_NO_NAME; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (output_name == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (input_name_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); + + if (input_name_type == GSS_C_NO_OID || + !g_OID_equal(input_name_type, GSS_C_NT_ANONYMOUS)) { + if (input_name_buffer->length == 0) + return (GSS_S_BAD_NAME); + + if (input_name_buffer->value == NULL) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); + } + + return (GSS_S_COMPLETE); +} + +static gss_buffer_desc emptyNameBuffer; + +OM_uint32 KRB5_CALLCONV +gss_import_name(minor_status, + input_name_buffer, + input_name_type, + output_name) + +OM_uint32 * minor_status; +gss_buffer_t input_name_buffer; +gss_OID input_name_type; +gss_name_t * output_name; + +{ + gss_union_name_t union_name; + OM_uint32 tmp, major_status = GSS_S_FAILURE; + + if (input_name_buffer == GSS_C_NO_BUFFER) + input_name_buffer = &emptyNameBuffer; + + major_status = val_imp_name_args(minor_status, + input_name_buffer, input_name_type, + output_name); + if (major_status != GSS_S_COMPLETE) + return (major_status); + + /* + * First create the union name struct that will hold the external + * name and the name type. + */ + union_name = (gss_union_name_t) malloc (sizeof(gss_union_name_desc)); + if (!union_name) + return (GSS_S_FAILURE); + + union_name->loopback = 0; + union_name->mech_type = 0; + union_name->mech_name = 0; + union_name->name_type = 0; + union_name->external_name = 0; + + /* + * All we do here is record the external name and name_type. + * When the name is actually used, the underlying gss_import_name() + * is called for the appropriate mechanism. The exception to this + * rule is when the name of GSS_C_NT_EXPORT_NAME type. If that is + * the case, then we make it MN in this call. + */ + major_status = gssint_create_copy_buffer(input_name_buffer, + &union_name->external_name, 0); + if (major_status != GSS_S_COMPLETE) { + free(union_name); + return (major_status); + } + + if (input_name_type != GSS_C_NULL_OID) { + major_status = generic_gss_copy_oid(minor_status, + input_name_type, + &union_name->name_type); + if (major_status != GSS_S_COMPLETE) { + map_errcode(minor_status); + goto allocation_failure; + } + } + + /* + * In MIT Distribution the mechanism is determined from the nametype; + * This is not a good idea - first mechanism that supports a given + * name type is picked up; later on the caller can request a + * different mechanism. So we don't determine the mechanism here. Now + * the user level and kernel level import_name routine looks similar + * except the kernel routine makes a copy of the nametype structure. We + * do however make this an MN for names of GSS_C_NT_EXPORT_NAME type. + */ + if (input_name_type != GSS_C_NULL_OID && + (g_OID_equal(input_name_type, GSS_C_NT_EXPORT_NAME) || + g_OID_equal(input_name_type, GSS_C_NT_COMPOSITE_EXPORT))) { + major_status = importExportName(minor_status, union_name, input_name_type); + if (major_status != GSS_S_COMPLETE) + goto allocation_failure; + } + + union_name->loopback = union_name; + *output_name = (gss_name_t)union_name; + return (GSS_S_COMPLETE); + +allocation_failure: + if (union_name) { + if (union_name->external_name) { + if (union_name->external_name->value) + free(union_name->external_name->value); + free(union_name->external_name); + } + if (union_name->name_type) + generic_gss_release_oid(&tmp, &union_name->name_type); + if (union_name->mech_name) + gssint_release_internal_name(minor_status, union_name->mech_type, + &union_name->mech_name); + if (union_name->mech_type) + generic_gss_release_oid(&tmp, &union_name->mech_type); + free(union_name); + } + return (major_status); +} + +static OM_uint32 +importExportName(minor, unionName, inputNameType) + OM_uint32 *minor; + gss_union_name_t unionName; + gss_OID inputNameType; +{ + gss_OID_desc mechOid; + gss_buffer_desc expName; + gss_mechanism mech; + OM_uint32 major, mechOidLen, nameLen; + uint8_t b2; + const uint8_t *name; + struct k5input in, oid, old_format; + + expName.value = unionName->external_name->value; + expName.length = unionName->external_name->length; + k5_input_init(&in, expName.value, expName.length); + + if (k5_input_get_byte(&in) != 0x04) + return (GSS_S_DEFECTIVE_TOKEN); + b2 = k5_input_get_byte(&in); + if (b2 != 0x01 && b2 != 0x02) /* allow composite names */ + return (GSS_S_DEFECTIVE_TOKEN); + + mechOidLen = k5_input_get_uint16_be(&in); + + if (!k5_der_get_value(&in, 0x06, &oid)) + return (GSS_S_DEFECTIVE_TOKEN); + /* Verify that mechOidLen is consistent with the DER OID length. */ + if (mechOidLen != k5_der_value_len(oid.len)) + return (GSS_S_DEFECTIVE_TOKEN); + mechOid.length = oid.len; + mechOid.elements = (uint8_t *)oid.ptr; + if ((mech = gssint_get_mechanism(&mechOid)) == NULL) + return (GSS_S_BAD_MECH); + + if (mech->gssspi_import_name_by_mech == NULL && + mech->gss_import_name == NULL) + return (GSS_S_UNAVAILABLE); + + /* + * we must now determine if we should unwrap the name ourselves + * or make the mechanism do it - we should only unwrap it + * if we create it; so if mech->gss_export_name == NULL, we must + * have created it. + */ + if (mech->gss_export_name) { + if (mech->gssspi_import_name_by_mech) { + major = mech->gssspi_import_name_by_mech(minor, &mechOid, &expName, + inputNameType, + &unionName->mech_name); + } else { + major = mech->gss_import_name(minor, &expName, inputNameType, + &unionName->mech_name); + } + if (major != GSS_S_COMPLETE) + map_error(minor, mech); + else { + major = generic_gss_copy_oid(minor, &mechOid, + &unionName->mech_type); + if (major != GSS_S_COMPLETE) + map_errcode(minor); + } + return (major); + } + /* + * we must have exported the name - so we now need to reconstruct it + * and call the mechanism to create it + * + * WARNING: Older versions of gssint_export_internal_name() did + * not export names correctly, but now it does. In + * order to stay compatible with existing exported + * names we must support names exported the broken + * way. + * + * Specifically, gssint_export_internal_name() used to include + * the name type OID in the encoding of the exported MN. + * Additionally, the Kerberos V mech used to make display names + * that included a null terminator which was counted in the + * display name gss_buffer_desc. + */ + + /* next 4 bytes in the name are the name length */ + nameLen = k5_input_get_uint32_be(&in); + name = k5_input_get_bytes(&in, nameLen); + if (name == NULL) + return (GSS_S_DEFECTIVE_TOKEN); + + /* + * We detect broken exported names here: they always start with + * a two-octet network-byte order OID length, which is always + * less than 256 bytes, so the first octet of the length is + * always '\0', which is not allowed in GSS-API display names + * (or never occurs in them anyways). Of course, the OID + * shouldn't be there, but it is. After the OID (sans DER tag + * and length) there's the name itself, though null-terminated; + * this null terminator should also not be there, but it is. + */ + if (nameLen > 0 && *name == '\0') { + OM_uint32 nameTypeLen; + + /* Skip the name type. */ + k5_input_init(&old_format, name, nameLen); + nameTypeLen = k5_input_get_uint16_be(&old_format); + if (k5_input_get_bytes(&old_format, nameTypeLen) == NULL) + return (GSS_S_DEFECTIVE_TOKEN); + /* Remove a null terminator if one is present. */ + if (old_format.len > 0 && old_format.ptr[old_format.len - 1] == 0) + old_format.len--; + name = old_format.ptr; + nameLen = old_format.len; + } + + /* + * Can a name be null? Let the mech decide. + * + * NOTE: We use GSS_C_NULL_OID as the name type when importing + * the unwrapped name. Presumably the exported name had, + * prior to being exported been obtained in such a way + * that it has been properly perpared ("canonicalized," in + * GSS-API terms) according to some name type; we cannot + * tell what that name type was now, but the name should + * need no further preparation other than the lowest + * common denominator afforded by the mech to names + * imported with GSS_C_NULL_OID. For the Kerberos V mech + * this means doing less busywork too (particularly once + * IDN is thrown in with Kerberos V extensions). + */ + expName.length = nameLen; + expName.value = nameLen ? (uint8_t *)name : NULL; + if (mech->gssspi_import_name_by_mech) { + major = mech->gssspi_import_name_by_mech(minor, &mechOid, &expName, + GSS_C_NULL_OID, + &unionName->mech_name); + } else { + major = mech->gss_import_name(minor, &expName, + GSS_C_NULL_OID, &unionName->mech_name); + } + if (major != GSS_S_COMPLETE) { + map_error(minor, mech); + return (major); + } + + major = generic_gss_copy_oid(minor, &mechOid, &unionName->mech_type); + if (major != GSS_S_COMPLETE) { + map_errcode(minor); + } + return major; +} /* importExportName */ diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_imp_sec_context.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_imp_sec_context.c new file mode 100644 index 00000000..6315201a --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_imp_sec_context.c @@ -0,0 +1,161 @@ +/* #pragma ident "@(#)g_imp_sec_context.c 1.18 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine gss_export_sec_context + */ + +#ifndef LEAN_CLIENT + +#include "mglueP.h" +#include +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +static OM_uint32 +val_imp_sec_ctx_args( + OM_uint32 *minor_status, + gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle) +{ + + /* Initialize outputs. */ + if (minor_status != NULL) + *minor_status = 0; + + if (context_handle != NULL) + *context_handle = GSS_C_NO_CONTEXT; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (interprocess_token == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_DEFECTIVE_TOKEN); + + if (GSS_EMPTY_BUFFER(interprocess_token)) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_DEFECTIVE_TOKEN); + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_import_sec_context(minor_status, + interprocess_token, + context_handle) + +OM_uint32 * minor_status; +gss_buffer_t interprocess_token; +gss_ctx_id_t * context_handle; + +{ + OM_uint32 length = 0; + OM_uint32 status; + char *p; + gss_union_ctx_id_t ctx; + gss_ctx_id_t mctx; + gss_buffer_desc token; + gss_OID_desc token_mech; + gss_OID selected_mech = GSS_C_NO_OID; + gss_OID public_mech; + gss_mechanism mech; + + status = val_imp_sec_ctx_args(minor_status, + interprocess_token, context_handle); + if (status != GSS_S_COMPLETE) + return (status); + + /* Initial value needed below. */ + status = GSS_S_FAILURE; + + if (interprocess_token->length >= sizeof (OM_uint32)) { + p = interprocess_token->value; + length = (OM_uint32)*p++; + length = (OM_uint32)(length << 8) + *p++; + length = (OM_uint32)(length << 8) + *p++; + length = (OM_uint32)(length << 8) + *p++; + } + + if (length == 0 || + length > (interprocess_token->length - sizeof (OM_uint32))) { + return (GSS_S_CALL_BAD_STRUCTURE | GSS_S_DEFECTIVE_TOKEN); + } + + token_mech.length = length; + token_mech.elements = p; + + p += length; + + token.length = interprocess_token->length - sizeof (OM_uint32) - length; + token.value = p; + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + status = gssint_select_mech_type(minor_status, &token_mech, + &selected_mech); + if (status != GSS_S_COMPLETE) + return status; + + mech = gssint_get_mechanism(selected_mech); + if (!mech) + return GSS_S_BAD_MECH; + if (!mech->gssspi_import_sec_context_by_mech && + !mech->gss_import_sec_context) + return GSS_S_UNAVAILABLE; + + status = gssint_create_union_context(minor_status, selected_mech, &ctx); + if (status != GSS_S_COMPLETE) + return status; + + if (mech->gssspi_import_sec_context_by_mech) { + public_mech = gssint_get_public_oid(selected_mech); + status = mech->gssspi_import_sec_context_by_mech(minor_status, + public_mech, + &token, &mctx); + } else { + status = mech->gss_import_sec_context(minor_status, &token, &mctx); + } + if (status == GSS_S_COMPLETE) { + ctx->internal_ctx_id = mctx; + *context_handle = (gss_ctx_id_t)ctx; + return (GSS_S_COMPLETE); + } + map_error(minor_status, mech); + free(ctx->mech_type->elements); + free(ctx->mech_type); + free(ctx); + return status; +} +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_init_sec_context.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_init_sec_context.c new file mode 100644 index 00000000..a58074c0 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_init_sec_context.c @@ -0,0 +1,252 @@ +/* #pragma ident "@(#)g_init_sec_context.c 1.20 03/10/24 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_init_sec_context + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +static OM_uint32 +val_init_sec_ctx_args( + OM_uint32 *minor_status, + gss_cred_id_t claimant_cred_handle, + gss_ctx_id_t *context_handle, + gss_name_t target_name, + gss_OID req_mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + gss_channel_bindings_t input_chan_bindings, + gss_buffer_t input_token, + gss_OID *actual_mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (actual_mech_type != NULL) + *actual_mech_type = GSS_C_NO_OID; + + if (output_token != GSS_C_NO_BUFFER) { + output_token->length = 0; + output_token->value = NULL; + } + + if (ret_flags != NULL) + *ret_flags = 0; + + if (time_rec != NULL) + *time_rec = 0; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CONTEXT); + + if (target_name == NULL) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); + + if (output_token == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_init_sec_context (minor_status, + claimant_cred_handle, + context_handle, + target_name, + req_mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec) + +OM_uint32 * minor_status; +gss_cred_id_t claimant_cred_handle; +gss_ctx_id_t * context_handle; +gss_name_t target_name; +gss_OID req_mech_type; +OM_uint32 req_flags; +OM_uint32 time_req; +gss_channel_bindings_t input_chan_bindings; +gss_buffer_t input_token; +gss_OID * actual_mech_type; +gss_buffer_t output_token; +OM_uint32 * ret_flags; +OM_uint32 * time_rec; + +{ + OM_uint32 status, temp_minor_status; + gss_union_name_t union_name; + gss_union_cred_t union_cred; + gss_name_t internal_name; + gss_union_ctx_id_t union_ctx_id; + gss_OID selected_mech; + gss_mechanism mech; + gss_cred_id_t input_cred_handle; + + status = val_init_sec_ctx_args(minor_status, + claimant_cred_handle, + context_handle, + target_name, + req_mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + if (status != GSS_S_COMPLETE) + return (status); + + status = gssint_select_mech_type(minor_status, req_mech_type, + &selected_mech); + if (status != GSS_S_COMPLETE) + return (status); + + union_name = (gss_union_name_t)target_name; + + /* + * obtain the gss mechanism information for the requested + * mechanism. If mech_type is NULL, set it to the resultant + * mechanism + */ + mech = gssint_get_mechanism(selected_mech); + if (mech == NULL) + return (GSS_S_BAD_MECH); + + if (mech->gss_init_sec_context == NULL) + return (GSS_S_UNAVAILABLE); + + /* + * If target_name is mechanism_specific, then it must match the + * mech_type that we're about to use. Otherwise, do an import on + * the external_name form of the target name. + */ + if (union_name->mech_type && + g_OID_equal(union_name->mech_type, selected_mech)) { + internal_name = union_name->mech_name; + } else { + if ((status = gssint_import_internal_name(minor_status, selected_mech, + union_name, + &internal_name)) != GSS_S_COMPLETE) + return (status); + } + + /* + * if context_handle is GSS_C_NO_CONTEXT, allocate a union context + * descriptor to hold the mech type information as well as the + * underlying mechanism context handle. Otherwise, cast the + * value of *context_handle to the union context variable. + */ + + if(*context_handle == GSS_C_NO_CONTEXT) { + status = gssint_create_union_context(minor_status, selected_mech, + &union_ctx_id); + if (status != GSS_S_COMPLETE) + goto end; + } else { + union_ctx_id = (gss_union_ctx_id_t)*context_handle; + if (union_ctx_id->internal_ctx_id == GSS_C_NO_CONTEXT) { + status = GSS_S_NO_CONTEXT; + goto end; + } + } + + /* + * get the appropriate cred handle from the union cred struct. + * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will + * use the default credential. + */ + union_cred = (gss_union_cred_t) claimant_cred_handle; + input_cred_handle = gssint_get_mechanism_cred(union_cred, selected_mech); + + /* + * now call the approprate underlying mechanism routine + */ + + status = mech->gss_init_sec_context( + minor_status, + input_cred_handle, + &union_ctx_id->internal_ctx_id, + internal_name, + gssint_get_public_oid(selected_mech), + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + + if (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) { + /* + * RFC 2744 5.19 requires that we not create a context on a failed + * first call to init, and recommends that on a failed subsequent call + * we make the caller responsible for calling gss_delete_sec_context. + * Even if the mech deleted its context, keep the union context around + * for the caller to delete. + */ + map_error(minor_status, mech); + if (*context_handle == GSS_C_NO_CONTEXT) { + free(union_ctx_id->mech_type->elements); + free(union_ctx_id->mech_type); + free(union_ctx_id); + } + } else if (*context_handle == GSS_C_NO_CONTEXT) { + *context_handle = (gss_ctx_id_t)union_ctx_id; + } + +end: + if (union_name->mech_name == NULL || + union_name->mech_name != internal_name) { + (void) gssint_release_internal_name(&temp_minor_status, + selected_mech, &internal_name); + } + + return(status); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_initialize.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_initialize.c new file mode 100644 index 00000000..22f6c615 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_initialize.c @@ -0,0 +1,1623 @@ +/* #pragma ident "@(#)g_initialize.c 1.36 05/02/02 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This function will initialize the gssapi mechglue library + */ + +#include "mglueP.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#include +#include +#include +#include +#ifndef _WIN32 +#include +#endif + +#define M_DEFAULT "default" + +#include "k5-thread.h" +#include "k5-plugin.h" +#include "osconf.h" +#ifdef _GSS_STATIC_LINK +#include "gssapiP_krb5.h" +#include "gssapiP_spnego.h" +#endif + +#define MECH_SYM "gss_mech_initialize" +#define MECH_INTERPOSER_SYM "gss_mech_interposer" + +#ifndef MECH_CONF +#define MECH_CONF "/etc/gss/mech" +#endif +#define MECH_CONF_PATTERN MECH_CONF ".d/*.conf" + +/* Local functions */ +static void addConfigEntry(const char *oidStr, const char *oid, + const char *sharedLib, const char *kernMod, + const char *modOptions, const char *modType); +static gss_mech_info searchMechList(gss_const_OID); +static void loadConfigFile(const char *); +#if defined(_WIN32) +#ifndef MECH_KEY +#define MECH_KEY "SOFTWARE\\gss\\mech" +#endif +static time_t getRegKeyModTime(HKEY hBaseKey, const char *keyPath); +static time_t getRegConfigModTime(const char *keyPath); +static void getRegKeyValue(HKEY key, const char *keyPath, const char *valueName, void **data, DWORD *dataLen); +static void loadConfigFromRegistry(HKEY keyBase, const char *keyPath); +#endif +static void updateMechList(void); +static void initMechList(void); +static void loadInterMech(gss_mech_info aMech); +static void freeMechList(void); + +static OM_uint32 build_mechSet(void); +static void free_mechSet(void); + +/* + * list of mechanism libraries and their entry points. + * the list also maintains state of the mech libraries (loaded or not). + */ +static gss_mech_info g_mechList = NULL; +static gss_mech_info g_mechListTail = NULL; +static k5_mutex_t g_mechListLock = K5_MUTEX_PARTIAL_INITIALIZER; +static time_t g_confFileModTime = (time_t)-1; +static time_t g_confLastCall = (time_t)0; + +static gss_OID_set_desc g_mechSet = { 0, NULL }; +static k5_mutex_t g_mechSetLock = K5_MUTEX_PARTIAL_INITIALIZER; + +MAKE_INIT_FUNCTION(gssint_mechglue_init); +MAKE_FINI_FUNCTION(gssint_mechglue_fini); + +int +gssint_mechglue_init(void) +{ + int err; + +#ifdef SHOW_INITFINI_FUNCS + printf("gssint_mechglue_init\n"); +#endif + + add_error_table(&et_ggss_error_table); + + err = k5_mutex_finish_init(&g_mechSetLock); + if (err) + return err; + err = k5_mutex_finish_init(&g_mechListLock); + if (err) + return err; + +#ifdef _GSS_STATIC_LINK + err = gss_krb5int_lib_init(); + if (err) + return err; + err = gss_spnegoint_lib_init(); + if (err) + return err; +#endif + + err = gssint_mecherrmap_init(); + return err; +} + +void +gssint_mechglue_fini(void) +{ + if (!INITIALIZER_RAN(gssint_mechglue_init) || PROGRAM_EXITING()) { +#ifdef SHOW_INITFINI_FUNCS + printf("gssint_mechglue_fini: skipping\n"); +#endif + return; + } + +#ifdef SHOW_INITFINI_FUNCS + printf("gssint_mechglue_fini\n"); +#endif +#ifdef _GSS_STATIC_LINK + gss_spnegoint_lib_fini(); + gss_krb5int_lib_fini(); +#endif + k5_mutex_destroy(&g_mechSetLock); + k5_mutex_destroy(&g_mechListLock); + free_mechSet(); + freeMechList(); + remove_error_table(&et_ggss_error_table); + gssint_mecherrmap_destroy(); +} + +int +gssint_mechglue_initialize_library(void) +{ + return CALL_INIT_FUNCTION(gssint_mechglue_init); +} + +/* + * function used to reclaim the memory used by a gss_OID structure. + * This routine requires direct access to the mechList. + */ +OM_uint32 KRB5_CALLCONV +gss_release_oid(minor_status, oid) +OM_uint32 *minor_status; +gss_OID *oid; +{ + OM_uint32 major; + gss_mech_info aMech; + + if (minor_status != NULL) + *minor_status = 0; + + if (minor_status == NULL || oid == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + *minor_status = gssint_mechglue_initialize_library(); + if (*minor_status != 0) + return (GSS_S_FAILURE); + + k5_mutex_lock(&g_mechListLock); + aMech = g_mechList; + while (aMech != NULL) { + + /* + * look through the loaded mechanism libraries for + * gss_internal_release_oid until one returns success. + * gss_internal_release_oid will only return success when + * the OID was recognized as an internal mechanism OID. if no + * mechanisms recognize the OID, then call the generic version. + */ + if (aMech->mech && aMech->mech->gss_internal_release_oid) { + major = aMech->mech->gss_internal_release_oid( + minor_status, oid); + if (major == GSS_S_COMPLETE) { + k5_mutex_unlock(&g_mechListLock); + return (GSS_S_COMPLETE); + } + map_error(minor_status, aMech->mech); + } + aMech = aMech->next; + } /* while */ + k5_mutex_unlock(&g_mechListLock); + + return (generic_gss_release_oid(minor_status, oid)); +} /* gss_release_oid */ + +/* + * Wrapper around inquire_attrs_for_mech to determine whether a mechanism has + * the deprecated attribute. Must be called without g_mechSetLock since it + * will call into the mechglue. + */ +static int +is_deprecated(gss_OID element) +{ + OM_uint32 major, minor; + gss_OID_set mech_attrs = GSS_C_NO_OID_SET; + int deprecated = 0; + + major = gss_inquire_attrs_for_mech(&minor, element, &mech_attrs, NULL); + if (major == GSS_S_COMPLETE) { + gss_test_oid_set_member(&minor, (gss_OID)GSS_C_MA_DEPRECATED, + mech_attrs, &deprecated); + } + + if (mech_attrs != GSS_C_NO_OID_SET) + gss_release_oid_set(&minor, &mech_attrs); + + return deprecated; +} + +/* + * Removes mechs with the deprecated attribute from an OID set. Must be + * called without g_mechSetLock held since it calls into the mechglue. + */ +static void +prune_deprecated(gss_OID_set mech_set) +{ + OM_uint32 i, j; + + j = 0; + for (i = 0; i < mech_set->count; i++) { + if (!is_deprecated(&mech_set->elements[i])) + mech_set->elements[j++] = mech_set->elements[i]; + else + gssalloc_free(mech_set->elements[i].elements); + } + mech_set->count = j; +} + +/* + * this function will return an oid set indicating available mechanisms. + * The set returned is based on configuration file entries and + * NOT on the loaded mechanisms. This function does not check if any + * of these can actually be loaded. + * Deprecated mechanisms will not be returned. + * This routine needs direct access to the mechanism list. + * To avoid reading the configuration file each call, we will save a + * a mech oid set, and only update it once the file has changed. + */ +OM_uint32 KRB5_CALLCONV +gss_indicate_mechs(minorStatus, mechSet_out) +OM_uint32 *minorStatus; +gss_OID_set *mechSet_out; +{ + OM_uint32 status; + + /* Initialize outputs. */ + + if (minorStatus != NULL) + *minorStatus = 0; + + if (mechSet_out != NULL) + *mechSet_out = GSS_C_NO_OID_SET; + + /* Validate arguments. */ + if (minorStatus == NULL || mechSet_out == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + *minorStatus = gssint_mechglue_initialize_library(); + if (*minorStatus != 0) + return (GSS_S_FAILURE); + + if (build_mechSet()) + return GSS_S_FAILURE; + + /* + * need to lock the g_mechSet in case someone tries to update it while + * I'm copying it. + */ + k5_mutex_lock(&g_mechSetLock); + status = generic_gss_copy_oid_set(minorStatus, &g_mechSet, mechSet_out); + k5_mutex_unlock(&g_mechSetLock); + + if (*mechSet_out != GSS_C_NO_OID_SET) + prune_deprecated(*mechSet_out); + + return (status); +} /* gss_indicate_mechs */ + + +/* Call with g_mechSetLock held, or during final cleanup. */ +static void +free_mechSet(void) +{ + unsigned int i; + + if (g_mechSet.count != 0) { + for (i = 0; i < g_mechSet.count; i++) + free(g_mechSet.elements[i].elements); + free(g_mechSet.elements); + g_mechSet.elements = NULL; + g_mechSet.count = 0; + } +} + +static OM_uint32 +build_mechSet(void) +{ + gss_mech_info mList; + size_t i; + size_t count; + gss_OID curItem; + + /* + * lock the mutex since we will be updating + * the mechList structure + * we need to keep the lock while we build the mechanism list + * since we are accessing parts of the mechList which could be + * modified. + */ + k5_mutex_lock(&g_mechListLock); + + updateMechList(); + + /* + * we need to lock the mech set so that no one else will + * try to read it as we are re-creating it + */ + k5_mutex_lock(&g_mechSetLock); + + /* if the oid list already exists we must free it first */ + free_mechSet(); + + /* determine how many elements to have in the list */ + mList = g_mechList; + count = 0; + while (mList != NULL) { + count++; + mList = mList->next; + } + + /* this should always be true, but.... */ + if (count > 0) { + g_mechSet.elements = + (gss_OID) calloc(count, sizeof (gss_OID_desc)); + if (g_mechSet.elements == NULL) { + k5_mutex_unlock(&g_mechSetLock); + k5_mutex_unlock(&g_mechListLock); + return (GSS_S_FAILURE); + } + + (void) memset(g_mechSet.elements, 0, + count * sizeof (gss_OID_desc)); + + /* now copy each oid element */ + count = 0; + for (mList = g_mechList; mList != NULL; mList = mList->next) { + /* Don't expose interposer mechanisms. */ + if (mList->is_interposer) + continue; + curItem = &(g_mechSet.elements[count]); + curItem->elements = (void*) + malloc(mList->mech_type->length); + if (curItem->elements == NULL) { + /* + * this is nasty - we must delete the + * part of the array already copied + */ + for (i = 0; i < count; i++) { + free(g_mechSet.elements[i]. + elements); + } + free(g_mechSet.elements); + g_mechSet.count = 0; + g_mechSet.elements = NULL; + k5_mutex_unlock(&g_mechSetLock); + k5_mutex_unlock(&g_mechListLock); + return (GSS_S_FAILURE); + } + g_OID_copy(curItem, mList->mech_type); + count++; + } + g_mechSet.count = count; + } + + k5_mutex_unlock(&g_mechSetLock); + k5_mutex_unlock(&g_mechListLock); + + return GSS_S_COMPLETE; +} + + +/* + * this function has been added for use by modules that need to + * know what (if any) optional parameters are supplied in the + * config file (MECH_CONF). + * It will return the option string for a specified mechanism. + * caller is responsible for freeing the memory + */ +char * +gssint_get_modOptions(oid) +const gss_OID oid; +{ + gss_mech_info aMech; + char *modOptions = NULL; + + if (gssint_mechglue_initialize_library() != 0) + return (NULL); + + /* make sure we have fresh data */ + k5_mutex_lock(&g_mechListLock); + updateMechList(); + + if ((aMech = searchMechList(oid)) == NULL || + aMech->optionStr == NULL) { + k5_mutex_unlock(&g_mechListLock); + return (NULL); + } + + if (aMech->optionStr) + modOptions = strdup(aMech->optionStr); + k5_mutex_unlock(&g_mechListLock); + + return (modOptions); +} /* gssint_get_modOptions */ + +/* Return the mtime of filename or its eventual symlink target (if it is a + * symlink), whichever is larger. Return (time_t)-1 if lstat or stat fails. */ +static time_t +check_link_mtime(const char *filename, time_t *mtime_out) +{ + struct stat st1, st2; + + if (lstat(filename, &st1) != 0) + return (time_t)-1; + if (!S_ISLNK(st1.st_mode)) + return st1.st_mtime; + if (stat(filename, &st2) != 0) + return (time_t)-1; + return (st1.st_mtime > st2.st_mtime) ? st1.st_mtime : st2.st_mtime; +} + +/* Load pathname if it is newer than last. Update *highest to the maximum of + * its current value and pathname's mod time. */ +static void +load_if_changed(const char *pathname, time_t last, time_t *highest) +{ + time_t mtime; + + mtime = check_link_mtime(pathname, &mtime); + if (mtime == (time_t)-1) + return; + if (mtime > *highest || *highest == (time_t)-1) + *highest = mtime; + if (mtime > last || last == (time_t)-1) + loadConfigFile(pathname); +} + +#ifndef _WIN32 +/* Try to load any config files which have changed since the last call. Config + * files are MECH_CONF and any files matching MECH_CONF_PATTERN. */ +static void +loadConfigFiles() +{ + glob_t globbuf; + time_t highest = (time_t)-1, now; + char **path; + const char *val; + + /* Don't glob and stat more than once per second. */ + if (time(&now) == (time_t)-1 || now == g_confLastCall) + return; + g_confLastCall = now; + + val = secure_getenv("GSS_MECH_CONFIG"); + if (val != NULL) { + load_if_changed(val, g_confFileModTime, &g_confFileModTime); + return; + } + + load_if_changed(MECH_CONF, g_confFileModTime, &highest); + + memset(&globbuf, 0, sizeof(globbuf)); + if (glob(MECH_CONF_PATTERN, 0, NULL, &globbuf) == 0) { + for (path = globbuf.gl_pathv; *path != NULL; path++) + load_if_changed(*path, g_confFileModTime, &highest); + } + globfree(&globbuf); + + g_confFileModTime = highest; +} +#endif + +/* + * determines if the mechList needs to be updated from file + * and performs the update. + * this functions must be called with a lock of g_mechListLock + */ +static void +updateMechList(void) +{ + gss_mech_info minfo; + +#if defined(_WIN32) + time_t lastConfModTime = getRegConfigModTime(MECH_KEY); + if (g_confFileModTime >= lastConfModTime && + g_confFileModTime != (time_t)-1) + return; + g_confFileModTime = lastConfModTime; + loadConfigFromRegistry(HKEY_CURRENT_USER, MECH_KEY); + loadConfigFromRegistry(HKEY_LOCAL_MACHINE, MECH_KEY); +#else /* _WIN32 */ + loadConfigFiles(); +#endif /* !_WIN32 */ + + /* Load any unloaded interposer mechanisms immediately, to make sure we + * interpose other mechanisms before they are used. */ + for (minfo = g_mechList; minfo != NULL; minfo = minfo->next) { + if (minfo->is_interposer && minfo->mech == NULL) + loadInterMech(minfo); + } +} /* updateMechList */ + +/* Update the mech list from system configuration if we have never done so. + * Must be invoked with the g_mechListLock mutex held. */ +static void +initMechList(void) +{ + static int lazy_init = 0; + + if (lazy_init == 0) { + updateMechList(); + lazy_init = 1; + } +} + +static void +releaseMechInfo(gss_mech_info *pCf) +{ + gss_mech_info cf; + OM_uint32 minor_status; + + if (*pCf == NULL) { + return; + } + + cf = *pCf; + + if (cf->kmodName != NULL) + free(cf->kmodName); + if (cf->uLibName != NULL) + free(cf->uLibName); + if (cf->mechNameStr != NULL) + free(cf->mechNameStr); + if (cf->optionStr != NULL) + free(cf->optionStr); + if (cf->mech_type != GSS_C_NO_OID && + cf->mech_type != &cf->mech->mech_type) + generic_gss_release_oid(&minor_status, &cf->mech_type); + if (cf->freeMech) + zapfree(cf->mech, sizeof(*cf->mech)); + if (cf->dl_handle != NULL) + krb5int_close_plugin(cf->dl_handle); + if (cf->int_mech_type != GSS_C_NO_OID) + generic_gss_release_oid(&minor_status, &cf->int_mech_type); + + memset(cf, 0, sizeof(*cf)); + free(cf); + + *pCf = NULL; +} + +#ifdef _GSS_STATIC_LINK +/* + * Register a mechanism. Called with g_mechListLock held. + */ +int +gssint_register_mechinfo(gss_mech_info template) +{ + gss_mech_info cf, new_cf; + + new_cf = calloc(1, sizeof(*new_cf)); + if (new_cf == NULL) { + return ENOMEM; + } + + new_cf->dl_handle = template->dl_handle; + /* copy mech so we can rewrite canonical mechanism OID */ + new_cf->mech = (gss_mechanism)calloc(1, sizeof(struct gss_config)); + if (new_cf->mech == NULL) { + releaseMechInfo(&new_cf); + return ENOMEM; + } + *new_cf->mech = *template->mech; + if (template->mech_type != NULL) + new_cf->mech->mech_type = *(template->mech_type); + new_cf->mech_type = &new_cf->mech->mech_type; + new_cf->priority = template->priority; + new_cf->freeMech = 1; + new_cf->next = NULL; + + if (template->kmodName != NULL) { + new_cf->kmodName = strdup(template->kmodName); + if (new_cf->kmodName == NULL) { + releaseMechInfo(&new_cf); + return ENOMEM; + } + } + if (template->uLibName != NULL) { + new_cf->uLibName = strdup(template->uLibName); + if (new_cf->uLibName == NULL) { + releaseMechInfo(&new_cf); + return ENOMEM; + } + } + if (template->mechNameStr != NULL) { + new_cf->mechNameStr = strdup(template->mechNameStr); + if (new_cf->mechNameStr == NULL) { + releaseMechInfo(&new_cf); + return ENOMEM; + } + } + if (template->optionStr != NULL) { + new_cf->optionStr = strdup(template->optionStr); + if (new_cf->optionStr == NULL) { + releaseMechInfo(&new_cf); + return ENOMEM; + } + } + if (g_mechList == NULL) { + g_mechList = new_cf; + g_mechListTail = new_cf; + return 0; + } else if (new_cf->priority < g_mechList->priority) { + new_cf->next = g_mechList; + g_mechList = new_cf; + return 0; + } + + for (cf = g_mechList; cf != NULL; cf = cf->next) { + if (cf->next == NULL || + new_cf->priority < cf->next->priority) { + new_cf->next = cf->next; + cf->next = new_cf; + if (g_mechListTail == cf) { + g_mechListTail = new_cf; + } + break; + } + } + + return 0; +} +#endif /* _GSS_STATIC_LINK */ + +#define GSS_ADD_DYNAMIC_METHOD(_dl, _mech, _symbol) \ + do { \ + struct errinfo errinfo; \ + \ + memset(&errinfo, 0, sizeof(errinfo)); \ + if (krb5int_get_plugin_func(_dl, \ + #_symbol, \ + (void (**)())&(_mech)->_symbol, \ + &errinfo) || errinfo.code) { \ + (_mech)->_symbol = NULL; \ + k5_clear_error(&errinfo); \ + } \ + } while (0) + +/* + * If _symbol is undefined in the shared object but the shared object + * is linked against the mechanism glue, it's possible for dlsym() to + * return the mechanism glue implementation. Guard against that. + */ +#define GSS_ADD_DYNAMIC_METHOD_NOLOOP(_dl, _mech, _symbol) \ + do { \ + GSS_ADD_DYNAMIC_METHOD(_dl, _mech, _symbol); \ + if ((_mech)->_symbol == _symbol) \ + (_mech)->_symbol = NULL; \ + } while (0) + +static gss_mechanism +build_dynamicMech(void *dl, const gss_OID mech_type) +{ + gss_mechanism mech; + + mech = (gss_mechanism)calloc(1, sizeof(*mech)); + if (mech == NULL) { + return NULL; + } + + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_acquire_cred); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_release_cred); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_init_sec_context); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_accept_sec_context); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_process_context_token); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_delete_sec_context); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_context_time); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_get_mic); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_verify_mic); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_unwrap); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_display_status); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_indicate_mechs); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_compare_name); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_display_name); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_import_name); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_release_name); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_cred); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_add_cred); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_sec_context); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_import_sec_context); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_cred_by_mech); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_names_for_mech); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_context); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_internal_release_oid); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap_size_limit); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_localname); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_authorize_localname); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_name); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_duplicate_name); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_store_cred); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_sec_context_by_oid); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_cred_by_oid); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_set_sec_context_option); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_set_cred_option); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gssspi_mech_invoke); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap_aead); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_unwrap_aead); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap_iov); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_unwrap_iov); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap_iov_length); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_complete_auth_token); + /* Services4User (introduced in 1.8) */ + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_acquire_cred_impersonate_name); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_add_cred_impersonate_name); + /* Naming extensions (introduced in 1.8) */ + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_display_name_ext); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_name); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_get_name_attribute); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_set_name_attribute); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_delete_name_attribute); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_name_composite); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_map_name_to_any); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_release_any_name_mapping); + /* RFC 4401 (introduced in 1.8) */ + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_pseudo_random); + /* RFC 4178 (introduced in 1.8; gss_get_neg_mechs not implemented) */ + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_set_neg_mechs); + /* draft-ietf-sasl-gs2 */ + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_saslname_for_mech); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_mech_for_saslname); + /* RFC 5587 */ + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_inquire_attrs_for_mech); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_acquire_cred_from); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_store_cred_into); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_acquire_cred_with_password); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_cred); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_import_cred); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_import_sec_context_by_mech); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_import_name_by_mech); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_import_cred_by_mech); + /* draft-zhu-negoex */ + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gssspi_query_meta_data); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gssspi_exchange_meta_data); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gssspi_query_mechanism_info); + /* gss_get_mic_iov extensions (added 1.12, implementable 1.20) */ + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_get_mic_iov); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_verify_mic_iov); + GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_get_mic_iov_length); + + assert(mech_type != GSS_C_NO_OID); + + mech->mech_type = *(mech_type); + + return mech; +} + +#define RESOLVE_GSSI_SYMBOL(_dl, _mech, _psym, _nsym) \ + do { \ + struct errinfo errinfo; \ + memset(&errinfo, 0, sizeof(errinfo)); \ + if (krb5int_get_plugin_func(_dl, \ + "gssi" #_nsym, \ + (void (**)())&(_mech)->_psym \ + ## _nsym, \ + &errinfo) || errinfo.code) { \ + (_mech)->_psym ## _nsym = NULL; \ + k5_clear_error(&errinfo); \ + } \ + } while (0) + +/* Build an interposer mechanism function table from dl. */ +static gss_mechanism +build_interMech(void *dl, const gss_OID mech_type) +{ + gss_mechanism mech; + + mech = calloc(1, sizeof(*mech)); + if (mech == NULL) { + return NULL; + } + + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _acquire_cred); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _release_cred); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _init_sec_context); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _accept_sec_context); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _process_context_token); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _delete_sec_context); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _context_time); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _get_mic); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _verify_mic); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _wrap); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _unwrap); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _display_status); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _indicate_mechs); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _compare_name); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _display_name); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _import_name); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _release_name); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_cred); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _add_cred); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _export_sec_context); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _import_sec_context); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_cred_by_mech); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_names_for_mech); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_context); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _internal_release_oid); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _wrap_size_limit); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _localname); + RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _authorize_localname); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _export_name); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _duplicate_name); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _store_cred); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_sec_context_by_oid); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_cred_by_oid); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _set_sec_context_option); + RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _set_cred_option); + RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _mech_invoke); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _wrap_aead); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _unwrap_aead); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _wrap_iov); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _unwrap_iov); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _wrap_iov_length); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _complete_auth_token); + /* Services4User (introduced in 1.8) */ + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _acquire_cred_impersonate_name); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _add_cred_impersonate_name); + /* Naming extensions (introduced in 1.8) */ + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _display_name_ext); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_name); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _get_name_attribute); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _set_name_attribute); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _delete_name_attribute); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _export_name_composite); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _map_name_to_any); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _release_any_name_mapping); + /* RFC 4401 (introduced in 1.8) */ + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _pseudo_random); + /* RFC 4178 (introduced in 1.8; get_neg_mechs not implemented) */ + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _set_neg_mechs); + /* draft-ietf-sasl-gs2 */ + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_saslname_for_mech); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_mech_for_saslname); + /* RFC 5587 */ + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _inquire_attrs_for_mech); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _acquire_cred_from); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _store_cred_into); + RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _acquire_cred_with_password); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _export_cred); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _import_cred); + RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _import_sec_context_by_mech); + RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _import_name_by_mech); + RESOLVE_GSSI_SYMBOL(dl, mech, gssspi, _import_cred_by_mech); + /* gss_get_mic_iov extensions (added 1.12, implementable 1.20) */ + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _get_mic_iov); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _verify_mic_iov); + RESOLVE_GSSI_SYMBOL(dl, mech, gss, _get_mic_iov_length); + + mech->mech_type = *mech_type; + return mech; +} + +/* + * Concatenate an interposer mech OID and a real mech OID to create an + * identifier for the interposed mech. (The concatenation will not be a valid + * DER OID encoding, but the OID is only used internally.) + */ +static gss_OID +interposed_oid(gss_OID pre, gss_OID real) +{ + gss_OID o; + + o = (gss_OID)malloc(sizeof(gss_OID_desc)); + if (!o) + return NULL; + + o->length = pre->length + real->length; + o->elements = malloc(o->length); + if (!o->elements) { + free(o); + return NULL; + } + + memcpy(o->elements, pre->elements, pre->length); + memcpy((char *)o->elements + pre->length, real->elements, + real->length); + + return o; +} + +static void +loadInterMech(gss_mech_info minfo) +{ + struct plugin_file_handle *dl = NULL; + struct errinfo errinfo; + gss_OID_set (*isym)(const gss_OID); + gss_OID_set list; + gss_OID oid; + OM_uint32 min; + gss_mech_info mi; + size_t i; + + memset(&errinfo, 0, sizeof(errinfo)); + + if (krb5int_open_plugin(minfo->uLibName, &dl, &errinfo) != 0 || + errinfo.code != 0) { + return; + } + + if (krb5int_get_plugin_func(dl, MECH_INTERPOSER_SYM, + (void (**)())&isym, &errinfo) != 0) + goto cleanup; + + /* Get a list of mechs to interpose. */ + list = (*isym)(minfo->mech_type); + if (!list) + goto cleanup; + minfo->mech = build_interMech(dl, minfo->mech_type); + if (minfo->mech == NULL) + goto cleanup; + minfo->freeMech = 1; + + /* Add interposer fields for each interposed mech. */ + for (i = 0; i < list->count; i++) { + /* Skip this mech if it doesn't exist or is already + * interposed. */ + oid = &list->elements[i]; + mi = searchMechList(oid); + if (mi == NULL || mi->int_mech_type != NULL) + continue; + + /* Construct a special OID to represent the interposed mech. */ + mi->int_mech_type = interposed_oid(minfo->mech_type, oid); + if (mi->int_mech_type == NULL) + continue; + + /* Save an alias to the interposer's function table. */ + mi->int_mech = minfo->mech; + } + (void)gss_release_oid_set(&min, &list); + + minfo->dl_handle = dl; + dl = NULL; + +cleanup: + if (dl != NULL) + krb5int_close_plugin(dl); + k5_clear_error(&errinfo); +} + +static void +freeMechList(void) +{ + gss_mech_info cf, next_cf; + + for (cf = g_mechList; cf != NULL; cf = next_cf) { + next_cf = cf->next; + releaseMechInfo(&cf); + } +} + +/* + * Determine the mechanism to use for a caller-specified mech OID. For the + * real mech OID of an interposed mech, return the interposed OID. For an + * interposed mech OID (which an interposer mech uses when re-entering the + * mechglue), return the real mech OID. The returned OID is an alias and + * should not be modified or freed. + */ +OM_uint32 +gssint_select_mech_type(OM_uint32 *minor, gss_const_OID oid, + gss_OID *selected_oid) +{ + gss_mech_info minfo; + OM_uint32 status; + + *selected_oid = GSS_C_NO_OID; + + if (gssint_mechglue_initialize_library() != 0) + return GSS_S_FAILURE; + + k5_mutex_lock(&g_mechListLock); + + /* Read conf file at least once so that interposer plugins have a + * chance of getting initialized. */ + initMechList(); + + minfo = g_mechList; + if (oid == GSS_C_NULL_OID) + oid = minfo->mech_type; + while (minfo != NULL) { + if (g_OID_equal(minfo->mech_type, oid)) { + if (minfo->int_mech_type != GSS_C_NO_OID) + *selected_oid = minfo->int_mech_type; + else + *selected_oid = minfo->mech_type; + status = GSS_S_COMPLETE; + goto done; + } else if ((minfo->int_mech_type != GSS_C_NO_OID) && + (g_OID_equal(minfo->int_mech_type, oid))) { + *selected_oid = minfo->mech_type; + status = GSS_S_COMPLETE; + goto done; + } + minfo = minfo->next; + } + status = GSS_S_BAD_MECH; + +done: + k5_mutex_unlock(&g_mechListLock); + return status; +} + +/* If oid is an interposed OID, return the corresponding real mech OID. If + * it's a real mech OID, return it unmodified. Otherwised return null. */ +gss_OID +gssint_get_public_oid(gss_const_OID oid) +{ + gss_mech_info minfo; + gss_OID public_oid = GSS_C_NO_OID; + + /* if oid is null -> then get default which is the first in the list */ + if (oid == GSS_C_NO_OID) + return GSS_C_NO_OID; + + if (gssint_mechglue_initialize_library() != 0) + return GSS_C_NO_OID; + + k5_mutex_lock(&g_mechListLock); + + for (minfo = g_mechList; minfo != NULL; minfo = minfo->next) { + if (minfo->is_interposer) + continue; + if (g_OID_equal(minfo->mech_type, oid) || + ((minfo->int_mech_type != GSS_C_NO_OID) && + (g_OID_equal(minfo->int_mech_type, oid)))) { + public_oid = minfo->mech_type; + break; + } + } + + k5_mutex_unlock(&g_mechListLock); + return public_oid; +} + +/* Translate a vector of oids (as from a union cred struct) into a set of + * public OIDs using gssint_get_public_oid. */ +OM_uint32 +gssint_make_public_oid_set(OM_uint32 *minor_status, gss_OID oids, int count, + gss_OID_set *public_set) +{ + OM_uint32 status, tmpmin; + gss_OID_set set; + gss_OID public_oid; + int i; + + *public_set = GSS_C_NO_OID_SET; + + status = generic_gss_create_empty_oid_set(minor_status, &set); + if (GSS_ERROR(status)) + return status; + + for (i = 0; i < count; i++) { + public_oid = gssint_get_public_oid(&oids[i]); + if (public_oid == GSS_C_NO_OID) + continue; + status = generic_gss_add_oid_set_member(minor_status, + public_oid, &set); + if (GSS_ERROR(status)) { + (void) generic_gss_release_oid_set(&tmpmin, &set); + return status; + } + } + + *public_set = set; + return GSS_S_COMPLETE; +} + +/* + * Register a mechanism. Called with g_mechListLock held. + */ + +/* + * given the mechanism type, return the mechanism structure + * containing the mechanism library entry points. + * will return NULL if mech type is not found + * This function will also trigger the loading of the mechanism + * module if it has not been already loaded. + */ +gss_mechanism +gssint_get_mechanism(gss_const_OID oid) +{ + gss_mech_info aMech; + gss_mechanism (*sym)(const gss_OID); + struct plugin_file_handle *dl; + struct errinfo errinfo; + + if (gssint_mechglue_initialize_library() != 0) + return (NULL); + + k5_mutex_lock(&g_mechListLock); + + /* Check if the mechanism is already loaded. */ + aMech = g_mechList; + if (oid == GSS_C_NULL_OID) + oid = aMech->mech_type; + while (aMech != NULL) { + if (g_OID_equal(aMech->mech_type, oid) && aMech->mech) { + k5_mutex_unlock(&g_mechListLock); + return aMech->mech; + } else if (aMech->int_mech_type != GSS_C_NO_OID && + g_OID_equal(aMech->int_mech_type, oid)) { + k5_mutex_unlock(&g_mechListLock); + return aMech->int_mech; + } + aMech = aMech->next; + } + + /* + * might need to re-read the configuration file before loading + * the mechanism to ensure we have the latest info. + */ + updateMechList(); + + aMech = searchMechList(oid); + + /* is the mechanism present in the list ? */ + if (aMech == NULL) { + k5_mutex_unlock(&g_mechListLock); + return ((gss_mechanism)NULL); + } + + /* has another thread loaded the mech */ + if (aMech->mech) { + k5_mutex_unlock(&g_mechListLock); + return (aMech->mech); + } + + memset(&errinfo, 0, sizeof(errinfo)); + + if (krb5int_open_plugin(aMech->uLibName, &dl, &errinfo) != 0 || + errinfo.code != 0) { + k5_clear_error(&errinfo); + k5_mutex_unlock(&g_mechListLock); + return ((gss_mechanism)NULL); + } + + if (krb5int_get_plugin_func(dl, MECH_SYM, (void (**)())&sym, + &errinfo) == 0) { + /* Call the symbol to get the mechanism table */ + aMech->mech = (*sym)(aMech->mech_type); + } else { + /* Try dynamic dispatch table */ + k5_clear_error(&errinfo); + aMech->mech = build_dynamicMech(dl, aMech->mech_type); + aMech->freeMech = 1; + } + if (aMech->mech == NULL) { + (void) krb5int_close_plugin(dl); + k5_mutex_unlock(&g_mechListLock); + return ((gss_mechanism)NULL); + } + + aMech->dl_handle = dl; + + k5_mutex_unlock(&g_mechListLock); + return (aMech->mech); +} /* gssint_get_mechanism */ + +/* + * this routine is used for searching the list of mechanism data. + * + * this needs to be called with g_mechListLock held. + */ +static gss_mech_info searchMechList(gss_const_OID oid) +{ + gss_mech_info aMech = g_mechList; + + /* if oid is null -> then get default which is the first in the list */ + if (oid == GSS_C_NULL_OID) + return (aMech); + + while (aMech != NULL) { + if (g_OID_equal(aMech->mech_type, oid)) + return (aMech); + aMech = aMech->next; + } + + /* none found */ + return ((gss_mech_info) NULL); +} /* searchMechList */ + +/* Return the first non-whitespace character starting from str. */ +static char * +skip_whitespace(char *str) +{ + while (isspace(*str)) + str++; + return str; +} + +/* Truncate str at the first whitespace character and return the first + * non-whitespace character after that point. */ +static char * +delimit_ws(char *str) +{ + while (*str != '\0' && !isspace(*str)) + str++; + if (*str != '\0') + *str++ = '\0'; + return skip_whitespace(str); +} + +/* Truncate str at the first occurrence of delimiter and return the first + * non-whitespace character after that point. */ +static char * +delimit(char *str, char delimiter) +{ + while (*str != '\0' && *str != delimiter) + str++; + if (*str != '\0') + *str++ = '\0'; + return skip_whitespace(str); +} + +/* + * loads the configuration file + * this is called while having a mutex lock on the mechanism list + * entries for libraries that have been loaded can't be modified + * mechNameStr and mech_type fields are not updated during updates + */ +static void +loadConfigFile(const char *fileName) +{ + char *sharedLib, *kernMod, *modOptions, *modType, *oid, *next; + char buffer[BUFSIZ], *oidStr; + FILE *confFile; + + if ((confFile = fopen(fileName, "r")) == NULL) { + return; + } + + (void) memset(buffer, 0, sizeof (buffer)); + while (fgets(buffer, BUFSIZ, confFile) != NULL) { + + /* ignore lines beginning with # */ + if (*buffer == '#') + continue; + + /* Parse out the name, oid, and shared library path. */ + oidStr = buffer; + oid = delimit_ws(oidStr); + if (*oid == '\0') + continue; + sharedLib = delimit_ws(oid); + if (*sharedLib == '\0') + continue; + next = delimit_ws(sharedLib); + + /* Parse out the kernel module name if present. */ + if (*next != '\0' && *next != '[' && *next != '<') { + kernMod = next; + next = delimit_ws(kernMod); + } else { + kernMod = NULL; + } + + /* Parse out the module options if present. */ + if (*next == '[') { + modOptions = next + 1; + next = delimit(modOptions, ']'); + } else { + modOptions = NULL; + } + + /* Parse out the module type if present. */ + if (*next == '<') { + modType = next + 1; + (void)delimit(modType, '>'); + } else { + modType = NULL; + } + + addConfigEntry(oidStr, oid, sharedLib, kernMod, modOptions, + modType); + } /* while */ + (void) fclose(confFile); +} /* loadConfigFile */ + +#if defined(_WIN32) + +static time_t +filetimeToTimet(const FILETIME *ft) +{ + ULARGE_INTEGER ull; + + ull.LowPart = ft->dwLowDateTime; + ull.HighPart = ft->dwHighDateTime; + return (time_t)(ull.QuadPart / 10000000ULL - 11644473600ULL); +} + +static time_t +getRegConfigModTime(const char *keyPath) +{ + time_t currentUserModTime = getRegKeyModTime(HKEY_CURRENT_USER, + keyPath); + time_t localMachineModTime = getRegKeyModTime(HKEY_LOCAL_MACHINE, + keyPath); + + return currentUserModTime > localMachineModTime ? currentUserModTime : + localMachineModTime; +} + +static time_t +getRegKeyModTime(HKEY hBaseKey, const char *keyPath) +{ + HKEY hConfigKey; + HRESULT rc; + int iSubKey = 0; + time_t modTime = 0, keyModTime; + FILETIME keyLastWriteTime; + char subKeyName[256]; + + if ((rc = RegOpenKeyEx(hBaseKey, keyPath, 0, KEY_ENUMERATE_SUB_KEYS, + &hConfigKey)) != ERROR_SUCCESS) { + /* TODO: log error message */ + return 0; + } + do { + int subKeyNameSize=sizeof(subKeyName)/sizeof(subKeyName[0]); + if ((rc = RegEnumKeyEx(hConfigKey, iSubKey++, subKeyName, + &subKeyNameSize, NULL, NULL, NULL, + &keyLastWriteTime)) != ERROR_SUCCESS) { + break; + } + keyModTime = filetimeToTimet(&keyLastWriteTime); + if (modTime < keyModTime) { + modTime = keyModTime; + } + } while (1); + RegCloseKey(hConfigKey); + return modTime; +} + +static void +getRegKeyValue(HKEY hKey, const char *keyPath, const char *valueName, + void **data, DWORD* dataLen) +{ + DWORD sizeRequired=*dataLen; + HRESULT hr; + /* Get data length required */ + if ((hr = RegGetValue(hKey, keyPath, valueName, RRF_RT_REG_SZ, NULL, + NULL, &sizeRequired)) != ERROR_SUCCESS) { + /* TODO: LOG registry error */ + return; + } + /* adjust data buffer size if necessary */ + if (*dataLen < sizeRequired) { + *dataLen = sizeRequired; + *data = realloc(*data, sizeRequired); + if (!*data) { + *dataLen = 0; + /* TODO: LOG OOM ERROR! */ + return; + } + } + /* get data */ + if ((hr = RegGetValue(hKey, keyPath, valueName, RRF_RT_REG_SZ, NULL, + *data, &sizeRequired)) != ERROR_SUCCESS) { + /* LOG registry error */ + return; + } +} + +static void +loadConfigFromRegistry(HKEY hBaseKey, const char *keyPath) +{ + HKEY hConfigKey; + DWORD iSubKey, nSubKeys, maxSubKeyNameLen, modTypeLen; + char *oidStr = NULL, *oid = NULL, *sharedLib = NULL, *kernMod = NULL; + char *modOptions = NULL, *modType = NULL; + DWORD oidStrLen = 0, oidLen = 0, sharedLibLen = 0, kernModLen = 0; + DWORD modOptionsLen = 0; + HRESULT rc; + + if ((rc = RegOpenKeyEx(hBaseKey, keyPath, 0, + KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE, + &hConfigKey)) != ERROR_SUCCESS) { + /* TODO: log registry error */ + return; + } + + if ((rc = RegQueryInfoKey(hConfigKey, + NULL, /* lpClass */ + NULL, /* lpcClass */ + NULL, /* lpReserved */ + &nSubKeys, + &maxSubKeyNameLen, + NULL, /* lpcMaxClassLen */ + NULL, /* lpcValues */ + NULL, /* lpcMaxValueNameLen */ + NULL, /* lpcMaxValueLen */ + NULL, /* lpcbSecurityDescriptor */ + NULL /* lpftLastWriteTime */ )) != ERROR_SUCCESS) { + goto cleanup; + } + oidStr = malloc(++maxSubKeyNameLen); + if (!oidStr) { + goto cleanup; + } + for (iSubKey=0; iSubKeymech) { + generic_gss_release_oid(&minor, &mechOid); + return; + } + + /* + * If that's all, then this is a corrupt entry. Skip it. + */ + if (! *sharedLib) { + generic_gss_release_oid(&minor, &mechOid); + return; + } +#if defined(_WIN32) + sharedPath = sharedLib; +#else + if (sharedLib[0] == '/') + snprintf(sharedPath, sizeof(sharedPath), "%s", sharedLib); + else + snprintf(sharedPath, sizeof(sharedPath), "%s%s", + MECH_LIB_PREFIX, sharedLib); +#endif + /* + * are we creating a new mechanism entry or + * just modifying existing (non loaded) mechanism entry + */ + if (aMech) { + /* + * delete any old values and set new + * mechNameStr and mech_type are not modified + */ + if (aMech->kmodName) { + free(aMech->kmodName); + aMech->kmodName = NULL; + } + + if (aMech->optionStr) { + free(aMech->optionStr); + aMech->optionStr = NULL; + } + + if ((tmpStr = strdup(sharedPath)) != NULL) { + if (aMech->uLibName) + free(aMech->uLibName); + aMech->uLibName = tmpStr; + } + + if (kernMod) /* this is an optional parameter */ + aMech->kmodName = strdup(kernMod); + + if (modOptions) /* optional module options */ + aMech->optionStr = strdup(modOptions); + + /* the oid is already set */ + generic_gss_release_oid(&minor, &mechOid); + return; + } + + /* adding a new entry */ + aMech = calloc(1, sizeof (struct gss_mech_config)); + if (aMech == NULL) { + generic_gss_release_oid(&minor, &mechOid); + return; + } + aMech->mech_type = mechOid; + aMech->uLibName = strdup(sharedPath); + aMech->mechNameStr = strdup(oidStr); + aMech->freeMech = 0; + + /* check if any memory allocations failed - bad news */ + if (aMech->uLibName == NULL || aMech->mechNameStr == NULL) { + if (aMech->uLibName) + free(aMech->uLibName); + if (aMech->mechNameStr) + free(aMech->mechNameStr); + generic_gss_release_oid(&minor, &mechOid); + free(aMech); + return; + } + if (kernMod) /* this is an optional parameter */ + aMech->kmodName = strdup(kernMod); + + if (modOptions) + aMech->optionStr = strdup(modOptions); + + if (modType && strcmp(modType, "interposer") == 0) + aMech->is_interposer = 1; + + /* + * add the new entry to the end of the list - make sure + * that only complete entries are added because other + * threads might currently be searching the list. + */ + tmp = g_mechListTail; + g_mechListTail = aMech; + + if (tmp != NULL) + tmp->next = aMech; + + if (g_mechList == NULL) + g_mechList = aMech; +} + diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_context.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_context.c new file mode 100644 index 00000000..6c0d98dd --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_context.c @@ -0,0 +1,170 @@ +/* #pragma ident "@(#)g_inquire_context.c 1.15 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_inquire_context + */ + +#include "mglueP.h" +#ifdef HAVE_STDLIB_H +#include +#endif + +static OM_uint32 +val_inq_ctx_args( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_name_t *src_name, + gss_name_t *targ_name, + OM_uint32 *lifetime_rec, + gss_OID *mech_type, + OM_uint32 *ctx_flags, + int *locally_initiated, + int *opened) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (src_name != NULL) + *src_name = GSS_C_NO_NAME; + + if (targ_name != NULL) + *targ_name = GSS_C_NO_NAME; + + if (mech_type != NULL) + *mech_type = GSS_C_NO_OID; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + return (GSS_S_COMPLETE); +} + + +/* Last argument new for V2 */ +OM_uint32 KRB5_CALLCONV +gss_inquire_context( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_name_t *src_name, + gss_name_t *targ_name, + OM_uint32 *lifetime_rec, + gss_OID *mech_type, + OM_uint32 *ctx_flags, + int *locally_initiated, + int *opened) +{ + gss_union_ctx_id_t ctx; + gss_mechanism mech; + OM_uint32 status, temp_minor; + gss_OID actual_mech; + gss_name_t localTargName = NULL, localSourceName = NULL; + + status = val_inq_ctx_args(minor_status, + context_handle, + src_name, targ_name, + lifetime_rec, + mech_type, ctx_flags, + locally_initiated, opened); + if (status != GSS_S_COMPLETE) + return (status); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + + if (!mech || !mech->gss_inquire_context || !mech->gss_display_name || + !mech->gss_release_name) { + return (GSS_S_UNAVAILABLE); + } + + status = mech->gss_inquire_context( + minor_status, + ctx->internal_ctx_id, + (src_name ? &localSourceName : NULL), + (targ_name ? &localTargName : NULL), + lifetime_rec, + &actual_mech, + ctx_flags, + locally_initiated, + opened); + + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + return status; + } + + /* need to convert names */ + + if (src_name) { + if (localSourceName) { + status = gssint_convert_name_to_union_name(minor_status, mech, + localSourceName, src_name); + + if (status != GSS_S_COMPLETE) { + if (localTargName) + mech->gss_release_name(&temp_minor, &localTargName); + return (status); + } + } else { + *src_name = GSS_C_NO_NAME; + } + } + + if (targ_name) { + if (localTargName) { + status = gssint_convert_name_to_union_name(minor_status, mech, + localTargName, targ_name); + + if (status != GSS_S_COMPLETE) { + if (src_name) + (void) gss_release_name(&temp_minor, src_name); + + return (status); + } + } + else { + *targ_name = GSS_C_NO_NAME; + } + } + + if (mech_type) + *mech_type = gssint_get_public_oid(actual_mech); + + return(GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_context_oid.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_context_oid.c new file mode 100644 index 00000000..d375cfc7 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_context_oid.c @@ -0,0 +1,74 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Glue routine for gss_inquire_sec_context_by_oid */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + if (minor_status != NULL) + *minor_status = 0; + + if (data_set != NULL) + *data_set = GSS_C_NO_BUFFER_SET; + + if (minor_status == NULL || data_set == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (context_handle == GSS_C_NO_CONTEXT) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT; + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) context_handle; + mech = gssint_get_mechanism (ctx->mech_type); + + if (mech != NULL) { + if (mech->gss_inquire_sec_context_by_oid != NULL) { + status = mech->gss_inquire_sec_context_by_oid(minor_status, + ctx->internal_ctx_id, + desired_object, + data_set); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return status; + } + + return GSS_S_BAD_MECH; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_cred.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_cred.c new file mode 100644 index 00000000..4ed7774f --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_cred.c @@ -0,0 +1,230 @@ +/* #pragma ident "@(#)g_inquire_cred.c 1.16 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_inquire_cred + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +OM_uint32 KRB5_CALLCONV +gss_inquire_cred(minor_status, + cred_handle, + name, + lifetime, + cred_usage, + mechanisms) + +OM_uint32 * minor_status; +gss_cred_id_t cred_handle; +gss_name_t * name; +OM_uint32 * lifetime; +int * cred_usage; +gss_OID_set * mechanisms; + +{ + OM_uint32 status, temp_minor_status; + gss_union_cred_t union_cred; + gss_mechanism mech; + gss_cred_id_t mech_cred; + gss_name_t mech_name; + gss_OID_set mechs = NULL; + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (name != NULL) + *name = GSS_C_NO_NAME; + + if (mechanisms != NULL) + *mechanisms = GSS_C_NO_OID_SET; + + /* Validate arguments. */ + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + /* + * XXX We should iterate over all mechanisms in the credential and + * aggregate the results. This requires a union name structure containing + * multiple mechanism names, which we don't currently have. For now, + * inquire the first mechanism in the credential; this is consistent with + * our historical behavior. + */ + + /* Determine mechanism and mechanism credential. */ + if (cred_handle != GSS_C_NO_CREDENTIAL) { + union_cred = (gss_union_cred_t) cred_handle; + if (union_cred->count <= 0) + return (GSS_S_DEFECTIVE_CREDENTIAL); + mech_cred = union_cred->cred_array[0]; + mech = gssint_get_mechanism(&union_cred->mechs_array[0]); + } else { + union_cred = NULL; + mech_cred = GSS_C_NO_CREDENTIAL; + mech = gssint_get_mechanism(GSS_C_NULL_OID); + } + + /* Skip the call into the mech if the caller doesn't care about any of the + * values we would ask for. */ + if (name != NULL || lifetime != NULL || cred_usage != NULL) { + if (mech == NULL) + return (GSS_S_DEFECTIVE_CREDENTIAL); + if (!mech->gss_inquire_cred) + return (GSS_S_UNAVAILABLE); + + status = mech->gss_inquire_cred(minor_status, mech_cred, + name ? &mech_name : NULL, + lifetime, cred_usage, NULL); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + return(status); + } + + if (name) { + /* Convert mech_name into a union_name equivalent. */ + status = gssint_convert_name_to_union_name(&temp_minor_status, + mech, mech_name, name); + if (status != GSS_S_COMPLETE) { + *minor_status = temp_minor_status; + map_error(minor_status, mech); + return (status); + } + } + } + + /* + * copy the mechanism set in union_cred into an OID set and return in + * the mechanisms parameter. + */ + + if(mechanisms != NULL) { + if (union_cred) { + status = gssint_make_public_oid_set(minor_status, + union_cred->mechs_array, + union_cred->count, &mechs); + if (GSS_ERROR(status)) + goto error; + } else { + status = gss_create_empty_oid_set(minor_status, &mechs); + if (GSS_ERROR(status)) + goto error; + + status = gss_add_oid_set_member(minor_status, + &mech->mech_type, &mechs); + if (GSS_ERROR(status)) + goto error; + } + *mechanisms = mechs; + } + + return(GSS_S_COMPLETE); + +error: + if (mechs != NULL) + (void) gss_release_oid_set(&temp_minor_status, &mechs); + + if (name && *name != NULL) + (void) gss_release_name(&temp_minor_status, name); + + return (status); +} + +OM_uint32 KRB5_CALLCONV +gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name, + initiator_lifetime, acceptor_lifetime, cred_usage) + OM_uint32 *minor_status; + gss_cred_id_t cred_handle; + gss_OID mech_type; + gss_name_t *name; + OM_uint32 *initiator_lifetime; + OM_uint32 *acceptor_lifetime; + gss_cred_usage_t *cred_usage; +{ + gss_union_cred_t union_cred; + gss_cred_id_t mech_cred; + gss_mechanism mech; + OM_uint32 status, temp_minor_status; + gss_name_t internal_name; + gss_OID selected_mech, public_mech; + + if (minor_status != NULL) + *minor_status = 0; + + if (name != NULL) + *name = GSS_C_NO_NAME; + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + status = gssint_select_mech_type(minor_status, mech_type, &selected_mech); + if (status != GSS_S_COMPLETE) + return (status); + + mech = gssint_get_mechanism(selected_mech); + if (!mech) + return (GSS_S_BAD_MECH); + if (!mech->gss_inquire_cred_by_mech) + return (GSS_S_BAD_BINDINGS); + + union_cred = (gss_union_cred_t) cred_handle; + mech_cred = gssint_get_mechanism_cred(union_cred, selected_mech); + if (cred_handle != GSS_C_NO_CREDENTIAL && mech_cred == GSS_C_NO_CREDENTIAL) + return (GSS_S_NO_CRED); + + public_mech = gssint_get_public_oid(selected_mech); + status = mech->gss_inquire_cred_by_mech(minor_status, + mech_cred, public_mech, + name ? &internal_name : NULL, + initiator_lifetime, + acceptor_lifetime, cred_usage); + + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + return (status); + } + + if (name) { + /* + * Convert internal_name into a union_name equivalent. + */ + status = gssint_convert_name_to_union_name( + &temp_minor_status, mech, + internal_name, name); + if (status != GSS_S_COMPLETE) { + *minor_status = temp_minor_status; + map_error(minor_status, mech); + return (status); + } + } + + return (GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_cred_oid.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_cred_oid.c new file mode 100644 index 00000000..6d8594d1 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_cred_oid.c @@ -0,0 +1,134 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Glue routine for gss_inquire_cred_by_oid */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +static OM_uint32 append_to_buffer_set(OM_uint32 *minor_status, + gss_buffer_set_t *dst, + const gss_buffer_set_t src) +{ + size_t i; + OM_uint32 status; + + if (src == GSS_C_NO_BUFFER_SET) + return GSS_S_COMPLETE; + + if (*dst == GSS_C_NO_BUFFER_SET) { + status = gss_create_empty_buffer_set(minor_status, dst); + if (status != GSS_S_COMPLETE) + return status; + } + + status = GSS_S_COMPLETE; + + for (i = 0; i < src->count; i++) { + status = gss_add_buffer_set_member(minor_status, + &src->elements[i], + dst); + if (status != GSS_S_COMPLETE) + break; + } + + return status; +} + +OM_uint32 KRB5_CALLCONV +gss_inquire_cred_by_oid(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + gss_union_cred_t union_cred; + gss_mechanism mech; + int i; + gss_buffer_set_t union_set = GSS_C_NO_BUFFER_SET; + gss_buffer_set_t ret_set = GSS_C_NO_BUFFER_SET; + OM_uint32 status, minor; + + if (minor_status != NULL) + *minor_status = 0; + + if (data_set != NULL) + *data_set = GSS_C_NO_BUFFER_SET; + + if (minor_status == NULL || data_set == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED; + + if (desired_object == GSS_C_NO_OID) + return GSS_S_CALL_INACCESSIBLE_READ; + + union_cred = (gss_union_cred_t) cred_handle; + + status = GSS_S_UNAVAILABLE; + + for (i = 0; i < union_cred->count; i++) { + mech = gssint_get_mechanism(&union_cred->mechs_array[i]); + if (mech == NULL) { + status = GSS_S_BAD_MECH; + break; + } + + if (mech->gss_inquire_cred_by_oid == NULL) { + status = GSS_S_UNAVAILABLE; + continue; + } + + status = (mech->gss_inquire_cred_by_oid)(minor_status, + union_cred->cred_array[i], + desired_object, + &ret_set); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + continue; + } + + if (union_cred->count == 1) { + union_set = ret_set; + break; + } + + status = append_to_buffer_set(minor_status, &union_set, ret_set); + gss_release_buffer_set(&minor, &ret_set); + if (status != GSS_S_COMPLETE) + break; + } + + if (status != GSS_S_COMPLETE) + gss_release_buffer_set(&minor, &union_set); + + *data_set = union_set; + + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_name.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_name.c new file mode 100644 index 00000000..cd1cbe5d --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_name.c @@ -0,0 +1,99 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Glue routine for gss_inquire_name */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_inquire_name(OM_uint32 *minor_status, + gss_name_t name, + int *name_is_MN, + gss_OID *MN_mech, + gss_buffer_set_t *attrs) +{ + OM_uint32 status, tmp; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status != NULL) + *minor_status = 0; + + if (MN_mech != NULL) + *MN_mech = GSS_C_NO_OID; + + if (attrs != NULL) + *attrs = GSS_C_NO_BUFFER_SET; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) { + /* We don't yet support non-mechanism attributes */ + if (name_is_MN != NULL) + *name_is_MN = 0; + *minor_status = 0; + return GSS_S_COMPLETE; + } + + if (name_is_MN != NULL) + *name_is_MN = 1; + + if (MN_mech != NULL) { + status = generic_gss_copy_oid(minor_status, + union_name->mech_type, + MN_mech); + if (GSS_ERROR(status)) + return status; + } + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) { + gss_release_oid(&tmp, MN_mech); + return GSS_S_BAD_NAME; + } + + if (mech->gss_inquire_name == NULL) { + gss_release_oid(&tmp, MN_mech); + return GSS_S_UNAVAILABLE; + } + + status = (*mech->gss_inquire_name)(minor_status, + union_name->mech_name, + NULL, + NULL, + attrs); + if (status != GSS_S_COMPLETE) { + generic_gss_release_oid(&tmp, MN_mech); + map_error(minor_status, mech); + } + + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_names.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_names.c new file mode 100644 index 00000000..d22af8bc --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_inq_names.c @@ -0,0 +1,168 @@ +/* #pragma ident "@(#)g_inquire_names.c 1.16 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_inquire_context + */ + +#include "mglueP.h" + +#define MAX_MECH_OID_PAIRS 32 + +/* Last argument new for V2 */ +OM_uint32 KRB5_CALLCONV +gss_inquire_names_for_mech(minor_status, mechanism, name_types) + +OM_uint32 * minor_status; +gss_OID mechanism; +gss_OID_set * name_types; + +{ + OM_uint32 status; + gss_OID selected_mech = GSS_C_NO_OID, public_mech; + gss_mechanism mech; + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (name_types != NULL) + *name_types = GSS_C_NO_OID_SET; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (name_types == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + status = gssint_select_mech_type(minor_status, mechanism, + &selected_mech); + if (status != GSS_S_COMPLETE) + return (status); + + mech = gssint_get_mechanism(selected_mech); + if (mech == NULL) + return GSS_S_BAD_MECH; + else if (mech->gss_inquire_names_for_mech == NULL) + return GSS_S_UNAVAILABLE; + public_mech = gssint_get_public_oid(selected_mech); + status = mech->gss_inquire_names_for_mech(minor_status, public_mech, + name_types); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} + +static OM_uint32 +val_inq_mechs4name_args( + OM_uint32 *minor_status, + const gss_name_t input_name, + gss_OID_set *mech_set) +{ + + /* Initialize outputs. */ + if (minor_status != NULL) + *minor_status = 0; + + if (mech_set != NULL) + *mech_set = GSS_C_NO_OID_SET; + + /* Validate arguments.e + */ + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (input_name == GSS_C_NO_NAME) + return (GSS_S_BAD_NAME); + + return (GSS_S_COMPLETE); +} + +static int +mech_supports_nametype(gss_OID mech_oid, gss_OID name_type) +{ + OM_uint32 status, minor; + gss_OID_set types = GSS_C_NO_OID_SET; + int present; + + status = gss_inquire_names_for_mech(&minor, mech_oid, &types); + if (status != GSS_S_COMPLETE) + return (0); + status = gss_test_oid_set_member(&minor, name_type, types, &present); + (void) gss_release_oid_set(&minor, &types); + return (status == GSS_S_COMPLETE && present); +} + +OM_uint32 KRB5_CALLCONV +gss_inquire_mechs_for_name(OM_uint32 *minor_status, + const gss_name_t input_name, gss_OID_set *mech_set) +{ + OM_uint32 status, tmpmin; + gss_OID_set all_mechs = GSS_C_NO_OID_SET; + gss_OID_set mechs = GSS_C_NO_OID_SET; + gss_OID mech_oid, name_type; + gss_buffer_desc name_buffer = GSS_C_EMPTY_BUFFER; + size_t i; + + status = val_inq_mechs4name_args(minor_status, input_name, mech_set); + if (status != GSS_S_COMPLETE) + return (status); + + status = gss_display_name(minor_status, input_name, &name_buffer, + &name_type); + if (status != GSS_S_COMPLETE) + goto cleanup; + status = gss_indicate_mechs(minor_status, &all_mechs); + if (status != GSS_S_COMPLETE) + goto cleanup; + status = gss_create_empty_oid_set(minor_status, &mechs); + if (status != GSS_S_COMPLETE) + goto cleanup; + for (i = 0; i < all_mechs->count; i++) { + mech_oid = &all_mechs->elements[i]; + if (mech_supports_nametype(mech_oid, name_type)) { + status = gss_add_oid_set_member(minor_status, mech_oid, &mechs); + if (status != GSS_S_COMPLETE) + goto cleanup; + } + } + + *mech_set = mechs; + mechs = GSS_C_NO_OID_SET; + +cleanup: + (void) gss_release_buffer(&tmpmin, &name_buffer); + (void) gss_release_oid_set(&tmpmin, &all_mechs); + (void) gss_release_oid_set(&tmpmin, &mechs); + return (status); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_map_name_to_any.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_map_name_to_any.c new file mode 100644 index 00000000..0e5490be --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_map_name_to_any.c @@ -0,0 +1,77 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Glue routine for gss_map_name_to_any */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_map_name_to_any(OM_uint32 *minor_status, + gss_name_t name, + int authenticated, + gss_buffer_t type_id, + gss_any_t *output) +{ + OM_uint32 status; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status != NULL) + *minor_status = 0; + + if (output != NULL) + *output = NULL; + + if (minor_status == NULL || output == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + if (type_id == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_READ; + + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) + return GSS_S_UNAVAILABLE; + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) + return GSS_S_BAD_NAME; + + if (mech->gss_map_name_to_any == NULL) + return GSS_S_UNAVAILABLE; + + status = (*mech->gss_map_name_to_any)(minor_status, + union_name->mech_name, + authenticated, + type_id, + output); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_mech_invoke.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_mech_invoke.c new file mode 100644 index 00000000..0647cda9 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_mech_invoke.c @@ -0,0 +1,72 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Glue routine for gssspi_mech_invoke */ + +#include "mglueP.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +OM_uint32 KRB5_CALLCONV +gssspi_mech_invoke (OM_uint32 *minor_status, + const gss_OID desired_mech, + const gss_OID desired_object, + gss_buffer_t value) +{ + OM_uint32 status; + gss_OID selected_mech = GSS_C_NO_OID; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + status = gssint_select_mech_type(minor_status, desired_mech, + &selected_mech); + if (status != GSS_S_COMPLETE) + return status; + + mech = gssint_get_mechanism(selected_mech); + if (mech == NULL || mech->gssspi_mech_invoke == NULL) { + return GSS_S_BAD_MECH; + } + + status = mech->gssspi_mech_invoke(minor_status, + gssint_get_public_oid(selected_mech), + desired_object, + value); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_mechattr.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_mechattr.c new file mode 100644 index 00000000..5d3e3f18 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_mechattr.c @@ -0,0 +1,222 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/mechglue/g_mechattr.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "mglueP.h" + +static int +testMechAttr(gss_const_OID attr, + gss_const_OID_set against) +{ + int present = 0; + OM_uint32 minor; + + if (GSS_ERROR(generic_gss_test_oid_set_member(&minor, attr, + (gss_OID_set)against, + &present))) + return 0; + + return present; +} + +/* + * Return TRUE iff all the elements of desired and none of the elements + * of except exist in available. + */ +static int +testMechAttrsOffered(gss_const_OID_set desired, + gss_const_OID_set except, + gss_const_OID_set available) +{ + size_t i; + + if (desired != GSS_C_NO_OID_SET) { + for (i = 0; i < desired->count; i++) { + if (!testMechAttr(&desired->elements[i], available)) + return 0; + } + } + + if (except != GSS_C_NO_OID_SET) { + for (i = 0; i < except->count; i++) { + if (testMechAttr(&except->elements[i], available)) + return 0; + } + } + + return 1; +} + +/* + * Return TRUE iff all the elements of critical exist in known. + */ +static int +testMechAttrsKnown(gss_const_OID_set critical, + gss_const_OID_set known) +{ + size_t i; + + if (critical != GSS_C_NO_OID_SET) { + for (i = 0; i < critical->count; i++) { + if (!testMechAttr(&critical->elements[i], known)) + return 0; + } + } + + return 1; +} + +OM_uint32 KRB5_CALLCONV +gss_indicate_mechs_by_attrs( + OM_uint32 *minor, + gss_const_OID_set desired_mech_attrs, + gss_const_OID_set except_mech_attrs, + gss_const_OID_set critical_mech_attrs, + gss_OID_set *mechs) +{ + OM_uint32 status, tmpMinor; + gss_OID_set allMechs = GSS_C_NO_OID_SET; + size_t i; + + if (minor != NULL) + *minor = 0; + + if (mechs != NULL) + *mechs = GSS_C_NO_OID_SET; + + if (minor == NULL || mechs == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + status = gss_indicate_mechs(minor, &allMechs); + if (GSS_ERROR(status)) + goto cleanup; + + status = generic_gss_create_empty_oid_set(minor, mechs); + if (GSS_ERROR(status)) + goto cleanup; + + for (i = 0; i < allMechs->count; i++) { + gss_OID_set supportedAttrs = GSS_C_NO_OID_SET; + gss_OID_set knownAttrs = GSS_C_NO_OID_SET; + + status = gss_inquire_attrs_for_mech(minor, &allMechs->elements[i], + &supportedAttrs, &knownAttrs); + if (GSS_ERROR(status)) + continue; + + if (testMechAttrsOffered(desired_mech_attrs, + except_mech_attrs, supportedAttrs) && + testMechAttrsKnown(critical_mech_attrs, knownAttrs)) { + status = gss_add_oid_set_member(minor, &allMechs->elements[i], + mechs); + if (GSS_ERROR(status)) { + gss_release_oid_set(&tmpMinor, &supportedAttrs); + gss_release_oid_set(&tmpMinor, &knownAttrs); + goto cleanup; + } + } + + gss_release_oid_set(&tmpMinor, &supportedAttrs); + gss_release_oid_set(&tmpMinor, &knownAttrs); + } + + *minor = 0; + status = GSS_S_COMPLETE; + +cleanup: + gss_release_oid_set(&tmpMinor, &allMechs); + + return status; +} + +OM_uint32 KRB5_CALLCONV +gss_inquire_attrs_for_mech( + OM_uint32 *minor, + gss_const_OID mech_oid, + gss_OID_set *mech_attrs, + gss_OID_set *known_mech_attrs) +{ + OM_uint32 status, tmpMinor; + gss_OID selected_mech, public_mech; + gss_mechanism mech; + + if (minor != NULL) + *minor = 0; + + if (mech_attrs != NULL) + *mech_attrs = GSS_C_NO_OID_SET; + + if (known_mech_attrs != NULL) + *known_mech_attrs = GSS_C_NO_OID_SET; + + if (minor == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + status = gssint_select_mech_type(minor, mech_oid, &selected_mech); + if (status != GSS_S_COMPLETE) + return status; + + mech = gssint_get_mechanism(selected_mech); + if (mech == NULL) + return GSS_S_BAD_MECH; + + /* If the mech does not implement RFC 5587, return success with an empty + * mech_attrs and known_mech_attrs. */ + if (mech->gss_inquire_attrs_for_mech == NULL) + return GSS_S_COMPLETE; + + public_mech = gssint_get_public_oid(selected_mech); + status = mech->gss_inquire_attrs_for_mech(minor, public_mech, mech_attrs, + known_mech_attrs); + if (GSS_ERROR(status)) { + map_error(minor, mech); + return status; + } + + if (known_mech_attrs != NULL && *known_mech_attrs == GSS_C_NO_OID_SET) { + status = generic_gss_copy_oid_set(minor, + gss_ma_known_attrs, + known_mech_attrs); + if (GSS_ERROR(status)) { + gss_release_oid_set(&tmpMinor, mech_attrs); + if (mech_attrs != NULL) + *mech_attrs = GSS_C_NO_OID_SET; + } + } + + return GSS_S_COMPLETE; +} + +OM_uint32 KRB5_CALLCONV +gss_display_mech_attr( + OM_uint32 *minor, + gss_const_OID mech_attr, + gss_buffer_t name, + gss_buffer_t short_desc, + gss_buffer_t long_desc) +{ + return generic_gss_display_mech_attr(minor, mech_attr, + name, short_desc, long_desc); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_mechname.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_mechname.c new file mode 100644 index 00000000..cfb0a0d2 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_mechname.c @@ -0,0 +1,116 @@ +/* + * g_mechname.c --- registry of mechanism-specific name types + * + * This file contains a registry of mechanism-specific name types. It + * is used to determine which name types not should be lazy evaluated, + * but rather evaluated on the spot. + */ + +#include "mglueP.h" +#ifdef HAVE_STDLIB_H +#include +#endif + +#include +#include +#include + +static gss_mech_spec_name name_list = NULL; + +/* + * generic searching helper function. + */ +static gss_mech_spec_name search_mech_spec(name_type) + gss_OID name_type; +{ + gss_mech_spec_name p; + + for (p = name_list; p; p = p->next) { + if (g_OID_equal(name_type, p->name_type)) + return p; + } + return NULL; +} + +/* + * Given a name_type, if it is specific to a mechanism, return the + * mechanism OID. Otherwise, return NULL. + */ +gss_OID gss_find_mechanism_from_name_type(name_type) + gss_OID name_type; +{ + gss_mech_spec_name p; + + p = search_mech_spec(name_type); + if (!p) + return NULL; + return p->mech; +} + +/* + * This function adds a (name_type, mechanism) pair to the + * mechanism-specific name type registry. If an entry for the + * name_type already exists, then zero out the mechanism entry. + * Otherwise, enter the pair into the registry. + */ +OM_uint32 +gss_add_mech_name_type(minor_status, name_type, mech) + OM_uint32 *minor_status; + gss_OID name_type; + gss_OID mech; +{ + OM_uint32 major_status, tmp; + gss_mech_spec_name p; + + p = search_mech_spec(name_type); + if (p) { + /* + * We found an entry for this name type; mark it as not being + * a mechanism-specific name type. + */ + if (p->mech) { + if (!g_OID_equal(mech, p->mech)) { + generic_gss_release_oid(minor_status, &p->mech); + p->mech = 0; + } + } + return GSS_S_COMPLETE; + } + p = malloc(sizeof(gss_mech_spec_name_desc)); + if (!p) { + *minor_status = ENOMEM; + map_errcode(minor_status); + goto allocation_failure; + } + p->name_type = 0; + p->mech = 0; + + major_status = generic_gss_copy_oid(minor_status, name_type, + &p->name_type); + if (major_status) { + map_errcode(minor_status); + goto allocation_failure; + } + major_status = generic_gss_copy_oid(minor_status, mech, + &p->mech); + if (major_status) { + map_errcode(minor_status); + goto allocation_failure; + } + + p->next = name_list; + p->prev = 0; + name_list = p; + + return GSS_S_COMPLETE; + +allocation_failure: + if (p) { + if (p->mech) + generic_gss_release_oid(&tmp, &p->mech); + if (p->name_type) + generic_gss_release_oid(&tmp, &p->name_type); + free(p); + } + return GSS_S_FAILURE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_negoex.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_negoex.c new file mode 100644 index 00000000..9360fa4b --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_negoex.c @@ -0,0 +1,237 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2011 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. + */ + +/* + * This file contains dispatch functions for the three GSSAPI extensions + * described in draft-zhu-negoex-04, renamed to use the gssspi_ prefix. Since + * the only caller of these functions is SPNEGO, argument validation is + * omitted. + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gssspi_query_meta_data(OM_uint32 *minor_status, gss_const_OID mech_oid, + gss_cred_id_t cred_handle, gss_ctx_id_t *context_handle, + const gss_name_t targ_name, OM_uint32 req_flags, + gss_buffer_t meta_data) +{ + OM_uint32 status, minor; + gss_union_ctx_id_t ctx = (gss_union_ctx_id_t)*context_handle; + gss_union_cred_t cred = (gss_union_cred_t)cred_handle; + gss_union_name_t union_name = (gss_union_name_t)targ_name; + gss_mechanism mech; + gss_OID selected_mech, public_mech; + gss_cred_id_t internal_cred = GSS_C_NO_CREDENTIAL; + gss_name_t internal_name = GSS_C_NO_NAME, imported_name = GSS_C_NO_NAME; + gss_ctx_id_t new_ctx = GSS_C_NO_CONTEXT, *internal_ctx; + + *minor_status = 0; + meta_data->length = 0; + meta_data->value = NULL; + + status = gssint_select_mech_type(minor_status, mech_oid, &selected_mech); + if (status != GSS_S_COMPLETE) + return status; + public_mech = gssint_get_public_oid(selected_mech); + + mech = gssint_get_mechanism(selected_mech); + if (mech == NULL) + return GSS_S_BAD_MECH; + if (mech->gssspi_query_meta_data == NULL) + return GSS_S_UNAVAILABLE; + + if (cred != NULL) { + internal_cred = gssint_get_mechanism_cred(cred, selected_mech); + if (internal_cred == GSS_C_NO_CREDENTIAL) + return GSS_S_NO_CRED; + } + + if (union_name != NULL) { + if (union_name->mech_type != GSS_C_NO_OID && + g_OID_equal(union_name->mech_type, selected_mech)) { + internal_name = union_name->mech_name; + } else { + status = gssint_import_internal_name(minor_status, selected_mech, + union_name, &imported_name); + if (status != GSS_S_COMPLETE) + goto cleanup; + internal_name = imported_name; + } + } + + internal_ctx = (ctx != NULL) ? &ctx->internal_ctx_id : &new_ctx; + status = mech->gssspi_query_meta_data(minor_status, public_mech, + internal_cred, internal_ctx, + internal_name, req_flags, meta_data); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + goto cleanup; + } + + /* If the mech created a context, wrap it in a union context. */ + if (new_ctx != GSS_C_NO_CONTEXT) { + assert(ctx == NULL); + status = gssint_create_union_context(minor_status, selected_mech, + &ctx); + if (status != GSS_S_COMPLETE) + goto cleanup; + + ctx->internal_ctx_id = new_ctx; + new_ctx = GSS_C_NO_CONTEXT; + *context_handle = (gss_ctx_id_t)ctx; + } + +cleanup: + if (imported_name != GSS_C_NO_NAME) { + (void)gssint_release_internal_name(&minor, selected_mech, + &imported_name); + } + if (new_ctx != GSS_C_NO_CONTEXT) { + (void)gssint_delete_internal_sec_context(&minor, &mech->mech_type, + &new_ctx, GSS_C_NO_BUFFER); + } + return status; +} + +OM_uint32 KRB5_CALLCONV +gssspi_exchange_meta_data(OM_uint32 *minor_status, gss_const_OID mech_oid, + gss_cred_id_t cred_handle, + gss_ctx_id_t *context_handle, + const gss_name_t targ_name, OM_uint32 req_flags, + gss_const_buffer_t meta_data) +{ + OM_uint32 status, minor; + gss_union_ctx_id_t ctx = (gss_union_ctx_id_t)*context_handle; + gss_union_cred_t cred = (gss_union_cred_t)cred_handle; + gss_union_name_t union_name = (gss_union_name_t)targ_name; + gss_mechanism mech; + gss_OID selected_mech, public_mech; + gss_cred_id_t internal_cred = GSS_C_NO_CREDENTIAL; + gss_name_t internal_name = GSS_C_NO_NAME, imported_name = GSS_C_NO_NAME; + gss_ctx_id_t new_ctx = GSS_C_NO_CONTEXT, *internal_ctx; + + *minor_status = 0; + + status = gssint_select_mech_type(minor_status, mech_oid, &selected_mech); + if (status != GSS_S_COMPLETE) + return status; + public_mech = gssint_get_public_oid(selected_mech); + + mech = gssint_get_mechanism(selected_mech); + if (mech == NULL) + return GSS_S_BAD_MECH; + if (mech->gssspi_exchange_meta_data == NULL) + return GSS_S_UNAVAILABLE; + + if (cred != NULL) { + internal_cred = gssint_get_mechanism_cred(cred, selected_mech); + if (internal_cred == GSS_C_NO_CREDENTIAL) + return GSS_S_NO_CRED; + } + + if (union_name != NULL) { + if (union_name->mech_type != GSS_C_NO_OID && + g_OID_equal(union_name->mech_type, selected_mech)) { + internal_name = union_name->mech_name; + } else { + status = gssint_import_internal_name(minor_status, selected_mech, + union_name, &imported_name); + if (GSS_ERROR(status)) + return status; + internal_name = imported_name; + } + } + + internal_ctx = (ctx != NULL) ? &ctx->internal_ctx_id : &new_ctx; + status = mech->gssspi_exchange_meta_data(minor_status, public_mech, + internal_cred, internal_ctx, + internal_name, req_flags, + meta_data); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + goto cleanup; + } + + /* If the mech created a context, wrap it in a union context. */ + if (new_ctx != GSS_C_NO_CONTEXT) { + assert(ctx == NULL); + status = gssint_create_union_context(minor_status, selected_mech, + &ctx); + if (status != GSS_S_COMPLETE) + goto cleanup; + + ctx->internal_ctx_id = new_ctx; + new_ctx = GSS_C_NO_CONTEXT; + *context_handle = (gss_ctx_id_t)ctx; + } + +cleanup: + if (imported_name != GSS_C_NO_NAME) { + (void)gssint_release_internal_name(&minor, selected_mech, + &imported_name); + } + if (new_ctx != GSS_C_NO_CONTEXT) { + (void)gssint_delete_internal_sec_context(&minor, &mech->mech_type, + &new_ctx, GSS_C_NO_BUFFER); + } + return status; +} + +OM_uint32 KRB5_CALLCONV +gssspi_query_mechanism_info(OM_uint32 *minor_status, gss_const_OID mech_oid, + unsigned char auth_scheme[16]) +{ + OM_uint32 status; + gss_OID selected_mech, public_mech; + gss_mechanism mech; + + *minor_status = 0; + memset(auth_scheme, 0, 16); + + status = gssint_select_mech_type(minor_status, mech_oid, &selected_mech); + if (status != GSS_S_COMPLETE) + return status; + public_mech = gssint_get_public_oid(selected_mech); + + mech = gssint_get_mechanism(selected_mech); + if (mech == NULL) + return GSS_S_BAD_MECH; + if (mech->gssspi_query_mechanism_info == NULL) + return GSS_S_UNAVAILABLE; + + status = mech->gssspi_query_mechanism_info(minor_status, public_mech, + auth_scheme); + if (GSS_ERROR(status)) + map_error(minor_status, mech); + + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_oid_ops.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_oid_ops.c new file mode 100644 index 00000000..1d7970c5 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_oid_ops.c @@ -0,0 +1,112 @@ +/* #pragma ident "@(#)g_oid_ops.c 1.11 98/01/22 SMI" */ +/* lib/gssapi/mechglue/g_oid_ops.c - GSSAPI V2 interfaces to manipulate OIDs */ +/* + * Copyright 1995, 2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "mglueP.h" + +/* + * gss_release_oid has been moved to g_initialize, because it requires access + * to the mechanism list. All functions requiring direct access to the + * mechanism list are now in g_initialize.c + */ + +OM_uint32 KRB5_CALLCONV +gss_create_empty_oid_set(minor_status, oid_set) + OM_uint32 *minor_status; + gss_OID_set *oid_set; +{ + OM_uint32 status; + status = generic_gss_create_empty_oid_set(minor_status, oid_set); + if (status != GSS_S_COMPLETE) + map_errcode(minor_status); + return status; +} + +OM_uint32 KRB5_CALLCONV +gss_add_oid_set_member(minor_status, member_oid, oid_set) + OM_uint32 *minor_status; + gss_OID member_oid; + gss_OID_set *oid_set; +{ + OM_uint32 status; + status = generic_gss_add_oid_set_member(minor_status, member_oid, oid_set); + if (status != GSS_S_COMPLETE) + map_errcode(minor_status); + return status; +} + +OM_uint32 KRB5_CALLCONV +gss_test_oid_set_member(minor_status, member, set, present) + OM_uint32 *minor_status; + gss_OID member; + gss_OID_set set; + int *present; +{ + return generic_gss_test_oid_set_member(minor_status, member, set, present); +} + +OM_uint32 KRB5_CALLCONV +gss_oid_to_str(minor_status, oid, oid_str) + OM_uint32 *minor_status; + gss_OID oid; + gss_buffer_t oid_str; +{ + OM_uint32 status = generic_gss_oid_to_str(minor_status, oid, oid_str); + if (status != GSS_S_COMPLETE) + map_errcode(minor_status); + return status; +} + +OM_uint32 KRB5_CALLCONV +gss_str_to_oid(minor_status, oid_str, oid) + OM_uint32 *minor_status; + gss_buffer_t oid_str; + gss_OID *oid; +{ + OM_uint32 status = generic_gss_str_to_oid(minor_status, oid_str, oid); + if (status != GSS_S_COMPLETE) + map_errcode(minor_status); + return status; +} + +OM_uint32 +gssint_copy_oid_set( + OM_uint32 *minor_status, + const gss_OID_set_desc * const oidset, + gss_OID_set *new_oidset) +{ + return generic_gss_copy_oid_set(minor_status, oidset, new_oidset); +} + +int KRB5_CALLCONV +gss_oid_equal( + gss_const_OID first_oid, + gss_const_OID second_oid) +{ + /* GSS_C_NO_OID doesn't match itself, per draft-josefsson-gss-capsulate. */ + if (first_oid == GSS_C_NO_OID || second_oid == GSS_C_NO_OID) + return 0; + return g_OID_equal(first_oid, second_oid); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_prf.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_prf.c new file mode 100644 index 00000000..96f2facf --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_prf.c @@ -0,0 +1,91 @@ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Glue routine for gss_pseudo_random */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_pseudo_random (OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int prf_key, + const gss_buffer_t prf_in, + ssize_t desired_output_len, + gss_buffer_t prf_out) +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + if (minor_status != NULL) + *minor_status = 0; + + if (prf_out != GSS_C_NO_BUFFER) { + prf_out->length = 0; + prf_out->value = NULL; + } + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (context_handle == GSS_C_NO_CONTEXT) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT; + + if (prf_in == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (prf_out == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + prf_out->length = 0; + prf_out->value = NULL; + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + mech = gssint_get_mechanism (ctx->mech_type); + + if (mech != NULL) { + if (mech->gss_pseudo_random != NULL) { + status = mech->gss_pseudo_random(minor_status, + ctx->internal_ctx_id, + prf_key, + prf_in, + desired_output_len, + prf_out); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return status; + } + + return GSS_S_BAD_MECH; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_process_context.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_process_context.c new file mode 100644 index 00000000..3968b5d9 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_process_context.c @@ -0,0 +1,84 @@ +/* #pragma ident "@(#)g_process_context.c 1.12 98/01/22 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine gss_process_context + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_process_context_token (minor_status, + context_handle, + token_buffer) + +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +gss_buffer_t token_buffer; + +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + if (token_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (GSS_EMPTY_BUFFER(token_buffer)) + return (GSS_S_CALL_INACCESSIBLE_READ); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + + if (mech) { + + if (mech->gss_process_context_token) { + status = mech->gss_process_context_token( + minor_status, + ctx->internal_ctx_id, + token_buffer); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + + return (GSS_S_BAD_MECH); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_buffer.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_buffer.c new file mode 100644 index 00000000..8c3328ac --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_buffer.c @@ -0,0 +1,58 @@ +/* #ident "@(#)g_rel_buffer.c 1.2 96/02/06 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_release_buffer + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif + +OM_uint32 KRB5_CALLCONV +gss_release_buffer (minor_status, + buffer) + +OM_uint32 * minor_status; +gss_buffer_t buffer; +{ + if (minor_status) + *minor_status = 0; + + /* if buffer is NULL, return */ + + if(buffer == GSS_C_NO_BUFFER) + return(GSS_S_COMPLETE); + + if ((buffer->length) && + (buffer->value)) { + gssalloc_free(buffer->value); + buffer->length = 0; + buffer->value = NULL; + } + + return (GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_cred.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_cred.c new file mode 100644 index 00000000..ccdee05a --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_cred.c @@ -0,0 +1,99 @@ +/* #pragma ident "@(#)g_rel_cred.c 1.14 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* Glue routine for gss_release_cred */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif + +OM_uint32 KRB5_CALLCONV +gss_release_cred(minor_status, + cred_handle) + +OM_uint32 * minor_status; +gss_cred_id_t * cred_handle; + +{ + OM_uint32 status, temp_status; + int j; + gss_union_cred_t union_cred; + gss_mechanism mech; + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + *minor_status = 0; + + if (cred_handle == NULL) + return (GSS_S_NO_CRED | GSS_S_CALL_INACCESSIBLE_READ); + + /* + * Loop through the union_cred struct, selecting the approprate + * underlying mechanism routine and calling it. At the end, + * release all of the storage taken by the union_cred struct. + */ + + union_cred = (gss_union_cred_t) *cred_handle; + if (union_cred == (gss_union_cred_t)GSS_C_NO_CREDENTIAL) + return (GSS_S_COMPLETE); + + if (GSSINT_CHK_LOOP(union_cred)) + return (GSS_S_NO_CRED | GSS_S_CALL_INACCESSIBLE_READ); + *cred_handle = NULL; + + status = GSS_S_COMPLETE; + + for(j=0; j < union_cred->count; j++) { + + mech = gssint_get_mechanism (&union_cred->mechs_array[j]); + + if (union_cred->mechs_array[j].elements) + free(union_cred->mechs_array[j].elements); + if (mech) { + if (mech->gss_release_cred) { + temp_status = mech->gss_release_cred + ( + minor_status, + &union_cred->cred_array[j]); + + if (temp_status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + status = GSS_S_NO_CRED; + } + + } else + status = GSS_S_UNAVAILABLE; + } else + status = GSS_S_DEFECTIVE_CREDENTIAL; + } + + free(union_cred->cred_array); + free(union_cred->mechs_array); + free(union_cred); + + return(status); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_name.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_name.c new file mode 100644 index 00000000..e0086923 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_name.c @@ -0,0 +1,86 @@ +/* #pragma ident "@(#)g_rel_name.c 1.11 04/02/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_release_name + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include + +OM_uint32 KRB5_CALLCONV +gss_release_name (minor_status, + input_name) + +OM_uint32 * minor_status; +gss_name_t * input_name; + +{ + gss_union_name_t union_name; + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + *minor_status = 0; + + /* if input_name is NULL, return error */ + if (input_name == NULL) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); + + if (*input_name == GSS_C_NO_NAME) + return GSS_S_COMPLETE; + + /* + * free up the space for the external_name and then + * free the union_name descriptor + */ + + union_name = (gss_union_name_t) *input_name; + if (GSSINT_CHK_LOOP(union_name)) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); + *input_name = 0; + *minor_status = 0; + + if (union_name->name_type != GSS_C_NO_OID) + gss_release_oid(minor_status, &union_name->name_type); + + if (union_name->external_name != GSS_C_NO_BUFFER) { + if (union_name->external_name->value != NULL) + gssalloc_free(union_name->external_name->value); + free(union_name->external_name); + } + + if (union_name->mech_type) { + gssint_release_internal_name(minor_status, union_name->mech_type, + &union_name->mech_name); + gss_release_oid(minor_status, &union_name->mech_type); + } + + free(union_name); + + return(GSS_S_COMPLETE); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_name_mapping.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_name_mapping.c new file mode 100644 index 00000000..03631782 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_name_mapping.c @@ -0,0 +1,73 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Glue routine for gss_release_any_name_mapping */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_release_any_name_mapping(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t type_id, + gss_any_t *input) +{ + OM_uint32 status; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + *minor_status = 0; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + if (type_id == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (input == NULL) + return GSS_S_CALL_INACCESSIBLE_READ; + + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) + return GSS_S_UNAVAILABLE; + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) + return GSS_S_BAD_NAME; + + if (mech->gss_release_any_name_mapping == NULL) + return GSS_S_UNAVAILABLE; + + status = (*mech->gss_release_any_name_mapping)(minor_status, + union_name->mech_name, + type_id, + input); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_oid_set.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_oid_set.c new file mode 100644 index 00000000..fa008d6b --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_rel_oid_set.c @@ -0,0 +1,43 @@ +/* #pragma ident "@(#)g_rel_oid_set.c 1.12 97/11/11 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_release_oid_set + */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif + +OM_uint32 KRB5_CALLCONV +gss_release_oid_set (minor_status, + set) + +OM_uint32 * minor_status; +gss_OID_set * set; +{ + return generic_gss_release_oid_set(minor_status, set); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_saslname.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_saslname.c new file mode 100644 index 00000000..2be0c8a6 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_saslname.c @@ -0,0 +1,220 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/gssapi/mechglue/g_saslname.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "mglueP.h" +#include + +static char basis_32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; + +#define OID_SASL_NAME_LENGTH (sizeof("GS2-XXXXXXXXXXX") - 1) + +static OM_uint32 +oidToSaslName(OM_uint32 *minor, const gss_OID mech, + char sasl_name[OID_SASL_NAME_LENGTH + 1]) +{ + unsigned char derBuf[2]; + krb5_crypto_iov iov[3]; + unsigned char cksumBuf[20], *q = cksumBuf; + char *p = sasl_name; + + if (mech->length > 127) { + *minor = ERANGE; + return GSS_S_BAD_MECH; + } + + derBuf[0] = 0x06; + derBuf[1] = (unsigned char)mech->length; + + iov[0].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + iov[0].data.length = 2; + iov[0].data.data = (char *)derBuf; + iov[1].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY; + iov[1].data.length = mech->length; + iov[1].data.data = (char *)mech->elements; + iov[2].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + iov[2].data.length = sizeof(cksumBuf); + iov[2].data.data = (char *)cksumBuf; + + *minor = krb5_k_make_checksum_iov(NULL, CKSUMTYPE_SHA1, NULL, 0, iov, 3); + if (*minor != 0) + return GSS_S_FAILURE; + + memcpy(p, "GS2-", 4); + p += 4; + + *p++ = basis_32[q[0] >> 3]; + *p++ = basis_32[((q[0] & 7) << 2) | (q[1] >> 6)]; + *p++ = basis_32[(q[1] & 0x3f) >> 1]; + *p++ = basis_32[((q[1] & 1) << 4) | (q[2] >> 4)]; + *p++ = basis_32[((q[2] & 0xf) << 1) | (q[3] >> 7)]; + *p++ = basis_32[(q[3] & 0x7f) >> 2]; + *p++ = basis_32[((q[3] & 3) << 3) | (q[4] >> 5)]; + *p++ = basis_32[(q[4] & 0x1f)]; + *p++ = basis_32[q[5] >> 3]; + *p++ = basis_32[((q[5] & 7) << 2) | (q[6] >> 6)]; + *p++ = basis_32[(q[6] & 0x3f) >> 1]; + + *p++ = '\0'; + + *minor = 0; + return GSS_S_COMPLETE; +} + +static OM_uint32 +oidToSaslNameAlloc(OM_uint32 *minor, const gss_OID mech, + gss_buffer_t sasl_name) +{ + OM_uint32 status, tmpMinor; + + sasl_name->value = malloc(OID_SASL_NAME_LENGTH + 1); + if (sasl_name->value == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + sasl_name->length = OID_SASL_NAME_LENGTH; + + status = oidToSaslName(minor, mech, (char *)sasl_name->value); + if (GSS_ERROR(status)) { + gss_release_buffer(&tmpMinor, sasl_name); + return status; + } + + return GSS_S_COMPLETE; +} + +OM_uint32 KRB5_CALLCONV gss_inquire_saslname_for_mech( + OM_uint32 *minor_status, + const gss_OID desired_mech, + gss_buffer_t sasl_mech_name, + gss_buffer_t mech_name, + gss_buffer_t mech_description) +{ + OM_uint32 status; + gss_OID selected_mech, public_mech; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor_status = 0; + + if (sasl_mech_name != GSS_C_NO_BUFFER) { + sasl_mech_name->length = 0; + sasl_mech_name->value = NULL; + } + + if (mech_name != GSS_C_NO_BUFFER) { + mech_name->length = 0; + mech_name->value = NULL; + } + + if (mech_description != GSS_C_NO_BUFFER) { + mech_description->length = 0; + mech_description->value = NULL; + } + + status = gssint_select_mech_type(minor_status, desired_mech, + &selected_mech); + if (status != GSS_S_COMPLETE) + return status; + + mech = gssint_get_mechanism(desired_mech); + if (mech == NULL) { + return GSS_S_BAD_MECH; + } else if (mech->gss_inquire_saslname_for_mech == NULL) { + status = GSS_S_UNAVAILABLE; + } else { + public_mech = gssint_get_public_oid(selected_mech); + status = mech->gss_inquire_saslname_for_mech(minor_status, public_mech, + sasl_mech_name, mech_name, + mech_description); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } + + if (status == GSS_S_UNAVAILABLE) { + if (sasl_mech_name != GSS_C_NO_BUFFER) + status = oidToSaslNameAlloc(minor_status, desired_mech, + sasl_mech_name); + else + status = GSS_S_COMPLETE; + } + + return status; +} + +/* We cannot interpose this function as mech_type is an output parameter. */ +OM_uint32 KRB5_CALLCONV gss_inquire_mech_for_saslname( + OM_uint32 *minor_status, + const gss_buffer_t sasl_mech_name, + gss_OID *mech_type) +{ + OM_uint32 status, tmpMinor; + gss_OID_set mechSet = GSS_C_NO_OID_SET; + size_t i; + + if (minor_status != NULL) + *minor_status = 0; + + if (mech_type != NULL) + *mech_type = GSS_C_NO_OID; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + status = gss_indicate_mechs(minor_status, &mechSet); + if (status != GSS_S_COMPLETE) + return status; + + for (i = 0, status = GSS_S_BAD_MECH; i < mechSet->count; i++) { + gss_mechanism mech; + char mappedName[OID_SASL_NAME_LENGTH + 1]; + + mech = gssint_get_mechanism(&mechSet->elements[i]); + if (mech != NULL && mech->gss_inquire_mech_for_saslname != NULL) { + status = mech->gss_inquire_mech_for_saslname(minor_status, + sasl_mech_name, + mech_type); + if (status == GSS_S_COMPLETE) + break; + } + if (status == GSS_S_BAD_MECH && + sasl_mech_name->length == OID_SASL_NAME_LENGTH && + oidToSaslName(&tmpMinor, &mechSet->elements[i], + mappedName) == GSS_S_COMPLETE && + memcmp(sasl_mech_name->value, mappedName, + OID_SASL_NAME_LENGTH) == 0) { + if (mech_type != NULL) + *mech_type = &mech->mech_type; + status = GSS_S_COMPLETE; + break; + } + } + + gss_release_oid_set(&tmpMinor, &mechSet); + + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_seal.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_seal.c new file mode 100644 index 00000000..3db1ee09 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_seal.c @@ -0,0 +1,253 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_wrap + */ + +#include "mglueP.h" + +static OM_uint32 +val_wrap_args(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_message_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (output_message_buffer != GSS_C_NO_BUFFER) { + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + } + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + if (input_message_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (output_message_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + return (GSS_S_COMPLETE); +} + +OM_uint32 KRB5_CALLCONV +gss_wrap( OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_message_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + + /* EXPORT DELETE START */ + + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_wrap_args(minor_status, context_handle, + conf_req_flag, qop_req, + input_message_buffer, conf_state, + output_message_buffer); + if (status != GSS_S_COMPLETE) + return (status); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + + if (mech) { + if (mech->gss_wrap) { + status = mech->gss_wrap(minor_status, + ctx->internal_ctx_id, + conf_req_flag, + qop_req, + input_message_buffer, + conf_state, + output_message_buffer); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else if (mech->gss_wrap_aead || + (mech->gss_wrap_iov && mech->gss_wrap_iov_length)) { + status = gssint_wrap_aead(mech, + minor_status, + ctx, + conf_req_flag, + (gss_qop_t)qop_req, + GSS_C_NO_BUFFER, + input_message_buffer, + conf_state, + output_message_buffer); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + /* EXPORT DELETE END */ + + return (GSS_S_BAD_MECH); +} + +OM_uint32 KRB5_CALLCONV +gss_seal(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + int qop_req, + gss_buffer_t input_message_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + + return gss_wrap(minor_status, context_handle, + conf_req_flag, (gss_qop_t) qop_req, + input_message_buffer, conf_state, + output_message_buffer); +} + +/* + * It is only possible to implement gss_wrap_size_limit() on top + * of gss_wrap_iov_length() for mechanisms that do not use any + * padding and have fixed length headers/trailers. + */ +static OM_uint32 +gssint_wrap_size_limit_iov_shim(gss_mechanism mech, + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size) +{ + gss_iov_buffer_desc iov[4]; + OM_uint32 status; + OM_uint32 ohlen; + + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[0].buffer.value = NULL; + iov[0].buffer.length = 0; + + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[1].buffer.length = req_output_size; + iov[1].buffer.value = NULL; + + iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING; + iov[2].buffer.value = NULL; + iov[2].buffer.length = 0; + + iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER; + iov[3].buffer.value = NULL; + iov[3].buffer.length = 0; + + assert(mech->gss_wrap_iov_length); + + status = mech->gss_wrap_iov_length(minor_status, context_handle, + conf_req_flag, qop_req, + NULL, iov, + sizeof(iov)/sizeof(iov[0])); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + return status; + } + + ohlen = iov[0].buffer.length + iov[3].buffer.length; + + if (iov[2].buffer.length == 0 && ohlen < req_output_size) + *max_input_size = req_output_size - ohlen; + else + *max_input_size = 0; + + return GSS_S_COMPLETE; +} + +/* + * New for V2 + */ +OM_uint32 KRB5_CALLCONV +gss_wrap_size_limit(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, OM_uint32 req_output_size, OM_uint32 *max_input_size) +{ + gss_union_ctx_id_t ctx; + gss_mechanism mech; + OM_uint32 major_status; + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + if (max_input_size == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + + if (!mech) + return (GSS_S_BAD_MECH); + + if (mech->gss_wrap_size_limit) + major_status = mech->gss_wrap_size_limit(minor_status, + ctx->internal_ctx_id, + conf_req_flag, qop_req, + req_output_size, max_input_size); + else if (mech->gss_wrap_iov_length) + major_status = gssint_wrap_size_limit_iov_shim(mech, minor_status, + ctx->internal_ctx_id, + conf_req_flag, qop_req, + req_output_size, max_input_size); + else + major_status = GSS_S_UNAVAILABLE; + if (major_status != GSS_S_COMPLETE) + map_error(minor_status, mech); + return major_status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_set_context_option.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_set_context_option.c new file mode 100644 index 00000000..eb67a9eb --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_set_context_option.c @@ -0,0 +1,93 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Glue routine for gss_set_sec_context_option */ + +#include "mglueP.h" +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +OM_uint32 KRB5_CALLCONV +gss_set_sec_context_option (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + OM_uint32 status, minor; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + gss_ctx_id_t internal_ctx = GSS_C_NO_CONTEXT; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + *minor_status = 0; + + if (context_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) *context_handle; + if (ctx == NULL) { + mech = gssint_get_mechanism (GSS_C_NO_OID); + } else { + mech = gssint_get_mechanism (ctx->mech_type); + } + + if (mech == NULL) + return GSS_S_BAD_MECH; + if (mech->gss_set_sec_context_option == NULL) + return GSS_S_UNAVAILABLE; + + status = mech->gss_set_sec_context_option(minor_status, + ctx ? &ctx->internal_ctx_id : + &internal_ctx, + desired_object, + value); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + return status; + } + + if (ctx == NULL && internal_ctx != GSS_C_NO_CONTEXT) { + status = gssint_create_union_context(minor_status, &mech->mech_type, + &ctx); + if (status != GSS_S_COMPLETE) { + gssint_delete_internal_sec_context(&minor, ctx->mech_type, + &internal_ctx, GSS_C_NO_BUFFER); + return status; + } + + ctx->internal_ctx_id = internal_ctx; + *context_handle = (gss_ctx_id_t)ctx; + } + + return GSS_S_COMPLETE; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_set_cred_option.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_set_cred_option.c new file mode 100644 index 00000000..5c9d21db --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_set_cred_option.c @@ -0,0 +1,197 @@ +/* + * Copyright 2008-2010 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Glue routine for gssspi_set_cred_option */ + +#include "mglueP.h" +#include +#ifdef HAVE_STDLIB_H +#include +#endif +#include +#include + +static OM_uint32 +alloc_union_cred(OM_uint32 *minor_status, + gss_mechanism mech, + gss_cred_id_t mech_cred, + gss_union_cred_t *pcred) +{ + OM_uint32 status; + OM_uint32 temp_minor_status; + gss_union_cred_t cred = NULL; + + *pcred = NULL; + + status = GSS_S_FAILURE; + + cred = calloc(1, sizeof(*cred)); + if (cred == NULL) { + *minor_status = ENOMEM; + goto cleanup; + } + + cred->loopback = cred; + cred->count = 1; + + cred->cred_array = calloc(cred->count, sizeof(gss_cred_id_t)); + if (cred->cred_array == NULL) { + *minor_status = ENOMEM; + goto cleanup; + } + cred->cred_array[0] = mech_cred; + + status = generic_gss_copy_oid(minor_status, + &mech->mech_type, + &cred->mechs_array); + if (status != GSS_S_COMPLETE) + goto cleanup; + + status = GSS_S_COMPLETE; + *pcred = cred; + +cleanup: + if (status != GSS_S_COMPLETE) + gss_release_cred(&temp_minor_status, (gss_cred_id_t *)&cred); + + return status; +} + +/* + * This differs from gssspi_set_cred_option() as shipped in 1.7, in that + * it can return a cred handle. To denote this change we have changed the + * name of the function from gssspi_set_cred_option() to gss_set_cred_option(). + * However, the dlsym() entry point is still gssspi_set_cred_option(). This + * fixes a separate issue, namely that a dynamically loaded mechanism could + * not itself call set_cred_option() without calling its own implementation + * instead of the mechanism glue's. (This is useful where a mechanism wishes + * to export a mechanism-specific API that is a wrapper around this function.) + */ +OM_uint32 KRB5_CALLCONV +gss_set_cred_option(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + gss_union_cred_t union_cred; + gss_mechanism mech; + int i; + OM_uint32 status; + OM_uint32 mech_status; + OM_uint32 mech_minor_status; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + *minor_status = 0; + + if (cred_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + status = GSS_S_UNAVAILABLE; + + if (*cred_handle == GSS_C_NO_CREDENTIAL) { + gss_cred_id_t mech_cred = GSS_C_NO_CREDENTIAL; + + /* + * We need to give a mechanism the opportunity to allocate a + * credentials handle. Unfortunately this does mean that only + * the default mechanism can allocate a credentials handle. + */ + mech = gssint_get_mechanism(NULL); + if (mech == NULL) + return GSS_S_BAD_MECH; + + if (mech->gssspi_set_cred_option == NULL) + return GSS_S_UNAVAILABLE; + + status = mech->gssspi_set_cred_option(minor_status, + &mech_cred, + desired_object, + value); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + return status; + } + + if (mech_cred != GSS_C_NO_CREDENTIAL) { + status = alloc_union_cred(minor_status, + mech, + mech_cred, + &union_cred); + if (status != GSS_S_COMPLETE) + return status; + *cred_handle = (gss_cred_id_t)union_cred; + } + } else { + union_cred = (gss_union_cred_t)*cred_handle; + + for (i = 0; i < union_cred->count; i++) { + mech = gssint_get_mechanism(&union_cred->mechs_array[i]); + if (mech == NULL) { + status = GSS_S_BAD_MECH; + break; + } + + if (mech->gssspi_set_cred_option == NULL) + continue; + + mech_status = mech->gssspi_set_cred_option(&mech_minor_status, + &union_cred->cred_array[i], + desired_object, + value); + if (mech_status == GSS_S_UNAVAILABLE) + continue; + else { + status = mech_status; + *minor_status = mech_minor_status; + } + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + break; + } + } + } + + return status; +} + +/* + * Provide this for backward ABI compatibility, but remove it from the + * header. + */ +OM_uint32 KRB5_CALLCONV +gssspi_set_cred_option(OM_uint32 *minor_status, + gss_cred_id_t cred, + const gss_OID desired_object, + const gss_buffer_t value); + +OM_uint32 KRB5_CALLCONV +gssspi_set_cred_option(OM_uint32 *minor_status, + gss_cred_id_t cred, + const gss_OID desired_object, + const gss_buffer_t value) +{ + return gss_set_cred_option(minor_status, &cred, + desired_object, value); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_set_name_attr.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_set_name_attr.c new file mode 100644 index 00000000..42bde490 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_set_name_attr.c @@ -0,0 +1,69 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Glue routine for gss_set_name_attribute */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_set_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + int complete, + gss_buffer_t attr, + gss_buffer_t value) +{ + OM_uint32 status; + gss_union_name_t union_name; + gss_mechanism mech; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + *minor_status = 0; + + if (name == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; + + union_name = (gss_union_name_t)name; + + if (union_name->mech_type == GSS_C_NO_OID) + return GSS_S_UNAVAILABLE; + + mech = gssint_get_mechanism(name->mech_type); + if (mech == NULL) + return GSS_S_BAD_NAME; + + if (mech->gss_set_name_attribute == NULL) + return GSS_S_UNAVAILABLE; + + status = (*mech->gss_set_name_attribute)(minor_status, + union_name->mech_name, + complete, + attr, + value); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_set_neg_mechs.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_set_neg_mechs.c new file mode 100644 index 00000000..9b04ec9d --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_set_neg_mechs.c @@ -0,0 +1,72 @@ +/* lib/gssapi/mechglue/g_set_neg_mechs.c - Glue for gss_set_neg_mechs */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_set_neg_mechs(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + const gss_OID_set mech_set) +{ + gss_union_cred_t union_cred; + gss_mechanism mech; + int i, avail; + OM_uint32 status; + + if (minor_status == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + *minor_status = 0; + + if (cred_handle == GSS_C_NO_CREDENTIAL) + return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED; + + union_cred = (gss_union_cred_t) cred_handle; + + avail = 0; + status = GSS_S_COMPLETE; + for (i = 0; i < union_cred->count; i++) { + mech = gssint_get_mechanism(&union_cred->mechs_array[i]); + if (mech == NULL) { + status = GSS_S_BAD_MECH; + break; + } + + if (mech->gss_set_neg_mechs == NULL) + continue; + + avail = 1; + status = (mech->gss_set_neg_mechs)(minor_status, + union_cred->cred_array[i], + mech_set); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + break; + } + } + + if (status == GSS_S_COMPLETE && !avail) + return GSS_S_UNAVAILABLE; + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_sign.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_sign.c new file mode 100644 index 00000000..03fbd8c0 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_sign.c @@ -0,0 +1,136 @@ +/* #pragma ident "@(#)g_sign.c 1.14 98/04/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine gss_get_mic + */ + +#include "mglueP.h" + +static OM_uint32 +val_get_mic_args( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t qop_req, + gss_buffer_t message_buffer, + gss_buffer_t msg_token) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (msg_token != GSS_C_NO_BUFFER) { + msg_token->value = NULL; + msg_token->length = 0; + } + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + if (message_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (msg_token == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_get_mic (minor_status, + context_handle, + qop_req, + message_buffer, + msg_token) + +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +gss_qop_t qop_req; +gss_buffer_t message_buffer; +gss_buffer_t msg_token; + +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_get_mic_args(minor_status, context_handle, + qop_req, message_buffer, msg_token); + if (status != GSS_S_COMPLETE) + return (status); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + + if (mech) { + if (mech->gss_get_mic) { + status = mech->gss_get_mic( + minor_status, + ctx->internal_ctx_id, + qop_req, + message_buffer, + msg_token); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + + return (GSS_S_BAD_MECH); +} + +OM_uint32 KRB5_CALLCONV +gss_sign (minor_status, + context_handle, + qop_req, + message_buffer, + msg_token) + +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +int qop_req; +gss_buffer_t message_buffer; +gss_buffer_t msg_token; + +{ + return (gss_get_mic(minor_status, context_handle, (gss_qop_t) qop_req, + message_buffer, msg_token)); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_store_cred.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_store_cred.c new file mode 100644 index 00000000..c2b6ddf3 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_store_cred.c @@ -0,0 +1,266 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* #pragma ident "@(#)g_store_cred.c 1.2 04/04/05 SMI" */ + +/* + * glue routine for gss_store_cred + */ + +#include + +static OM_uint32 +store_cred_fallback( + OM_uint32 *minor_status, + gss_mechanism mech, + gss_cred_id_t mech_cred, + gss_cred_usage_t cred_usage, + gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_const_key_value_set_t cred_store, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored) +{ + gss_OID public_mech = gssint_get_public_oid(desired_mech); + + if (mech->gss_store_cred_into != NULL) { + return mech->gss_store_cred_into(minor_status, mech_cred, + cred_usage, public_mech, + overwrite_cred, default_cred, + cred_store, elements_stored, + cred_usage_stored); + } else if (cred_store == GSS_C_NO_CRED_STORE) { + return mech->gss_store_cred(minor_status, mech_cred, + cred_usage, public_mech, + overwrite_cred, default_cred, + elements_stored, + cred_usage_stored); + } else { + return GSS_S_UNAVAILABLE; + } +} + +static OM_uint32 +val_store_cred_args( + OM_uint32 *minor_status, + const gss_cred_id_t input_cred_handle, + gss_cred_usage_t cred_usage, + const gss_OID desired_mech, + OM_uint32 overwrite_cred, + OM_uint32 default_cred, + gss_const_key_value_set_t cred_store, + gss_OID_set *elements_stored, + gss_cred_usage_t *cred_usage_stored) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + if (elements_stored != NULL) + *elements_stored = GSS_C_NULL_OID_SET; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (input_cred_handle == GSS_C_NO_CREDENTIAL) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CRED); + + if (cred_usage != GSS_C_ACCEPT + && cred_usage != GSS_C_INITIATE + && cred_usage != GSS_C_BOTH) { + if (minor_status) { + *minor_status = EINVAL; + map_errcode(minor_status); + } + return GSS_S_FAILURE; + } + + if (cred_store != NULL && cred_store->count == 0) { + *minor_status = EINVAL; + map_errcode(minor_status); + return GSS_S_FAILURE; + } + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_store_cred(minor_status, + input_cred_handle, + cred_usage, + desired_mech, + overwrite_cred, + default_cred, + elements_stored, + cred_usage_stored) + +OM_uint32 *minor_status; +gss_cred_id_t input_cred_handle; +gss_cred_usage_t cred_usage; +const gss_OID desired_mech; +OM_uint32 overwrite_cred; +OM_uint32 default_cred; +gss_OID_set *elements_stored; +gss_cred_usage_t *cred_usage_stored; + +{ + return gss_store_cred_into(minor_status, input_cred_handle, cred_usage, + desired_mech, overwrite_cred, default_cred, + GSS_C_NO_CRED_STORE, elements_stored, + cred_usage_stored); +} + +OM_uint32 KRB5_CALLCONV +gss_store_cred_into(minor_status, + input_cred_handle, + cred_usage, + desired_mech, + overwrite_cred, + default_cred, + cred_store, + elements_stored, + cred_usage_stored) + +OM_uint32 *minor_status; +gss_cred_id_t input_cred_handle; +gss_cred_usage_t cred_usage; +gss_OID desired_mech; +OM_uint32 overwrite_cred; +OM_uint32 default_cred; +gss_const_key_value_set_t cred_store; +gss_OID_set *elements_stored; +gss_cred_usage_t *cred_usage_stored; + +{ + OM_uint32 major_status = GSS_S_FAILURE; + gss_union_cred_t union_cred; + gss_cred_id_t mech_cred; + gss_mechanism mech; + gss_OID dmech; + gss_OID selected_mech; + int i; + + major_status = val_store_cred_args(minor_status, + input_cred_handle, + cred_usage, + desired_mech, + overwrite_cred, + default_cred, + cred_store, + elements_stored, + cred_usage_stored); + if (major_status != GSS_S_COMPLETE) + return (major_status); + + /* Initial value needed below. */ + major_status = GSS_S_FAILURE; + + if (cred_usage_stored != NULL) + *cred_usage_stored = GSS_C_BOTH; /* there's no GSS_C_NEITHER */ + + union_cred = (gss_union_cred_t)input_cred_handle; + + /* desired_mech != GSS_C_NULL_OID -> store one element */ + if (desired_mech != GSS_C_NULL_OID) { + major_status = gssint_select_mech_type(minor_status, + desired_mech, + &selected_mech); + if (major_status != GSS_S_COMPLETE) + return (major_status); + + mech = gssint_get_mechanism(selected_mech); + if (mech == NULL) + return (GSS_S_BAD_MECH); + + if (mech->gss_store_cred_into == NULL && + cred_store != GSS_C_NO_CRED_STORE) + return (major_status); + + if (mech->gss_store_cred == NULL && + mech->gss_store_cred_into == NULL) + return (major_status); + + mech_cred = gssint_get_mechanism_cred(union_cred, selected_mech); + if (mech_cred == GSS_C_NO_CREDENTIAL) + return (GSS_S_NO_CRED); + + major_status = store_cred_fallback(minor_status, mech, + mech_cred, cred_usage, + selected_mech, + overwrite_cred, + default_cred, cred_store, + elements_stored, + cred_usage_stored); + if (major_status != GSS_S_COMPLETE) + map_error(minor_status, mech); + return major_status; + } + + /* desired_mech == GSS_C_NULL_OID -> store all elements */ + + *minor_status = 0; + + for (i = 0; i < union_cred->count; i++) { + /* Get mech and cred element */ + dmech = &union_cred->mechs_array[i]; + mech = gssint_get_mechanism(dmech); + if (mech == NULL) + continue; + + if (mech->gss_store_cred_into == NULL && + cred_store != GSS_C_NO_CRED_STORE) + continue; + + if (mech->gss_store_cred == NULL && + mech->gss_store_cred_into == NULL) + continue; + + mech_cred = gssint_get_mechanism_cred(union_cred, dmech); + if (mech_cred == GSS_C_NO_CREDENTIAL) + continue; /* can't happen, but safe to ignore */ + + major_status = store_cred_fallback(minor_status, mech, + mech_cred, cred_usage, + dmech, overwrite_cred, + default_cred, cred_store, + NULL, cred_usage_stored); + if (major_status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + continue; + } + + /* Succeeded for at least one mech */ + + if (elements_stored == NULL) + continue; + + if (*elements_stored == GSS_C_NULL_OID_SET) { + major_status = gss_create_empty_oid_set(minor_status, + elements_stored); + + if (GSS_ERROR(major_status)) + return (major_status); + } + + major_status = gss_add_oid_set_member(minor_status, dmech, + elements_stored); + + /* The caller should clean up elements_stored */ + if (GSS_ERROR(major_status)) + return (major_status); + } + + /* + * Success with some mechs may mask failure with others, but + * that's what elements_stored is for. + */ + return (major_status); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_unseal.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_unseal.c new file mode 100644 index 00000000..c208635b --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_unseal.c @@ -0,0 +1,132 @@ +/* #pragma ident "@(#)g_unseal.c 1.13 98/01/22 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine gss_unwrap + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_unwrap (minor_status, + context_handle, + input_message_buffer, + output_message_buffer, + conf_state, + qop_state) + +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +gss_buffer_t input_message_buffer; +gss_buffer_t output_message_buffer; +int * conf_state; +gss_qop_t * qop_state; + +{ +/* EXPORT DELETE START */ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + if (minor_status != NULL) + *minor_status = 0; + + if (output_message_buffer != GSS_C_NO_BUFFER) { + output_message_buffer->length = 0; + output_message_buffer->value = NULL; + } + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + if (input_message_buffer == GSS_C_NO_BUFFER || + GSS_EMPTY_BUFFER(input_message_buffer)) + + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (output_message_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + + if (mech) { + if (mech->gss_unwrap) { + status = mech->gss_unwrap(minor_status, + ctx->internal_ctx_id, + input_message_buffer, + output_message_buffer, + conf_state, + qop_state); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else if (mech->gss_unwrap_aead || mech->gss_unwrap_iov) { + status = gssint_unwrap_aead(mech, + minor_status, + ctx, + input_message_buffer, + GSS_C_NO_BUFFER, + output_message_buffer, + conf_state, + (gss_qop_t *)qop_state); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + +/* EXPORT DELETE END */ + + return (GSS_S_BAD_MECH); +} + +OM_uint32 KRB5_CALLCONV +gss_unseal (minor_status, + context_handle, + input_message_buffer, + output_message_buffer, + conf_state, + qop_state) + +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +gss_buffer_t input_message_buffer; +gss_buffer_t output_message_buffer; +int * conf_state; +int * qop_state; + +{ + return (gss_unwrap(minor_status, context_handle, + input_message_buffer, + output_message_buffer, conf_state, (gss_qop_t *) qop_state)); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_unwrap_aead.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_unwrap_aead.c new file mode 100644 index 00000000..0682bd89 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_unwrap_aead.c @@ -0,0 +1,199 @@ +/* #pragma ident "@(#)g_seal.c 1.19 98/04/21 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_unwrap_aead + */ + +#include "mglueP.h" + +static OM_uint32 +val_unwrap_aead_args( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t input_assoc_buffer, + gss_buffer_t output_payload_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + if (input_message_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (output_payload_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + return (GSS_S_COMPLETE); +} + +static OM_uint32 +gssint_unwrap_aead_iov_shim(gss_mechanism mech, + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t input_assoc_buffer, + gss_buffer_t output_payload_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + OM_uint32 status; + gss_iov_buffer_desc iov[3]; + int i = 0; + + iov[i].type = GSS_IOV_BUFFER_TYPE_STREAM; + iov[i].buffer = *input_message_buffer; + i++; + + if (input_assoc_buffer != NULL) { + iov[i].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[i].buffer = *input_assoc_buffer; + i++; + } + + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE; + iov[i].buffer.value = NULL; + iov[i].buffer.length = 0; + i++; + + assert(mech->gss_unwrap_iov); + + status = mech->gss_unwrap_iov(minor_status, context_handle, conf_state, + qop_state, iov, i); + if (status == GSS_S_COMPLETE) { + *output_payload_buffer = iov[i - 1].buffer; + } else { + OM_uint32 minor; + + map_error(minor_status, mech); + + if (iov[i - 1].type & GSS_IOV_BUFFER_FLAG_ALLOCATED) { + gss_release_buffer(&minor, &iov[i - 1].buffer); + iov[i - 1].type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED); + } + } + + return status; +} + +OM_uint32 +gssint_unwrap_aead (gss_mechanism mech, + OM_uint32 *minor_status, + gss_union_ctx_id_t ctx, + gss_buffer_t input_message_buffer, + gss_buffer_t input_assoc_buffer, + gss_buffer_t output_payload_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + OM_uint32 status; + + assert(mech != NULL); + assert(ctx != NULL); + + /* EXPORT DELETE START */ + + if (mech->gss_unwrap_aead) { + status = mech->gss_unwrap_aead(minor_status, + ctx->internal_ctx_id, + input_message_buffer, + input_assoc_buffer, + output_payload_buffer, + conf_state, + qop_state); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else if (mech->gss_unwrap_iov) { + status = gssint_unwrap_aead_iov_shim(mech, + minor_status, + ctx->internal_ctx_id, + input_message_buffer, + input_assoc_buffer, + output_payload_buffer, + conf_state, + qop_state); + } else + status = GSS_S_UNAVAILABLE; + /* EXPORT DELETE END */ + + return (status); +} + +OM_uint32 KRB5_CALLCONV +gss_unwrap_aead (minor_status, + context_handle, + input_message_buffer, + input_assoc_buffer, + output_payload_buffer, + conf_state, + qop_state) +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +gss_buffer_t input_message_buffer; +gss_buffer_t input_assoc_buffer; +gss_buffer_t output_payload_buffer; +int *conf_state; +gss_qop_t *qop_state; +{ + + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_unwrap_aead_args(minor_status, context_handle, + input_message_buffer, input_assoc_buffer, + output_payload_buffer, + conf_state, qop_state); + if (status != GSS_S_COMPLETE) + return (status); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + + if (!mech) + return (GSS_S_BAD_MECH); + + return gssint_unwrap_aead(mech, minor_status, ctx, + input_message_buffer, input_assoc_buffer, + output_payload_buffer, conf_state, qop_state); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_unwrap_iov.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_unwrap_iov.c new file mode 100644 index 00000000..599be2c7 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_unwrap_iov.c @@ -0,0 +1,145 @@ +/* #pragma ident "@(#)g_seal.c 1.19 98/04/21 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_unwrap_iov + */ + +#include "mglueP.h" + +static OM_uint32 +val_unwrap_iov_args( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + if (iov == GSS_C_NO_IOV_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ); + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_unwrap_iov (minor_status, + context_handle, + conf_state, + qop_state, + iov, + iov_count) +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +int * conf_state; +gss_qop_t *qop_state; +gss_iov_buffer_desc * iov; +int iov_count; +{ + /* EXPORT DELETE START */ + + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_unwrap_iov_args(minor_status, context_handle, + conf_state, qop_state, iov, iov_count); + if (status != GSS_S_COMPLETE) + return (status); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + + if (mech) { + if (mech->gss_unwrap_iov) { + status = mech->gss_unwrap_iov( + minor_status, + ctx->internal_ctx_id, + conf_state, + qop_state, + iov, + iov_count); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + /* EXPORT DELETE END */ + + return (GSS_S_BAD_MECH); +} + +OM_uint32 KRB5_CALLCONV +gss_verify_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_qop_t *qop_state, gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_unwrap_iov_args(minor_status, context_handle, NULL, + qop_state, iov, iov_count); + if (status != GSS_S_COMPLETE) + return status; + + /* Select the approprate underlying mechanism routine and call it. */ + ctx = (gss_union_ctx_id_t)context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + mech = gssint_get_mechanism(ctx->mech_type); + if (mech == NULL) + return GSS_S_BAD_MECH; + if (mech->gss_verify_mic_iov == NULL) + return GSS_S_UNAVAILABLE; + status = mech->gss_verify_mic_iov(minor_status, ctx->internal_ctx_id, + qop_state, iov, iov_count); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_verify.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_verify.c new file mode 100644 index 00000000..8996fce8 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_verify.c @@ -0,0 +1,108 @@ +/* #pragma ident "@(#)g_verify.c 1.13 98/04/23 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_verify_mic + */ + +#include "mglueP.h" + +OM_uint32 KRB5_CALLCONV +gss_verify_mic (minor_status, + context_handle, + message_buffer, + token_buffer, + qop_state) + +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +gss_buffer_t message_buffer; +gss_buffer_t token_buffer; +gss_qop_t * qop_state; + +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + if ((message_buffer == GSS_C_NO_BUFFER) || + GSS_EMPTY_BUFFER(token_buffer)) + + return (GSS_S_CALL_INACCESSIBLE_READ); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + + if (mech) { + if (mech->gss_verify_mic) { + status = mech->gss_verify_mic( + minor_status, + ctx->internal_ctx_id, + message_buffer, + token_buffer, + qop_state); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + + return (GSS_S_BAD_MECH); +} + +OM_uint32 KRB5_CALLCONV +gss_verify (minor_status, + context_handle, + message_buffer, + token_buffer, + qop_state) + +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +gss_buffer_t message_buffer; +gss_buffer_t token_buffer; +int * qop_state; + +{ + return (gss_verify_mic(minor_status, context_handle, + message_buffer, token_buffer, + (gss_qop_t *) qop_state)); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_wrap_aead.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_wrap_aead.c new file mode 100644 index 00000000..7fe3b7b3 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_wrap_aead.c @@ -0,0 +1,269 @@ +/* #pragma ident "@(#)g_seal.c 1.19 98/04/21 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_wrap_aead + */ + +#include "mglueP.h" + +static OM_uint32 +val_wrap_aead_args( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_assoc_buffer, + gss_buffer_t input_payload_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + if (input_payload_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ); + + if (output_message_buffer == GSS_C_NO_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + return (GSS_S_COMPLETE); +} + +static OM_uint32 +gssint_wrap_aead_iov_shim(gss_mechanism mech, + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_assoc_buffer, + gss_buffer_t input_payload_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + gss_iov_buffer_desc iov[5]; + OM_uint32 status; + size_t offset; + int i = 0, iov_count; + + /* HEADER | SIGN_ONLY_DATA | DATA | PADDING | TRAILER */ + + iov[i].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[i].buffer.value = NULL; + iov[i].buffer.length = 0; + i++; + + if (input_assoc_buffer != GSS_C_NO_BUFFER) { + iov[i].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[i].buffer = *input_assoc_buffer; + i++; + } + + iov[i].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[i].buffer = *input_payload_buffer; + i++; + + iov[i].type = GSS_IOV_BUFFER_TYPE_PADDING; + iov[i].buffer.value = NULL; + iov[i].buffer.length = 0; + i++; + + iov[i].type = GSS_IOV_BUFFER_TYPE_TRAILER; + iov[i].buffer.value = NULL; + iov[i].buffer.length = 0; + i++; + + iov_count = i; + + assert(mech->gss_wrap_iov_length); + + status = mech->gss_wrap_iov_length(minor_status, context_handle, + conf_req_flag, qop_req, + NULL, iov, iov_count); + if (status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + return status; + } + + /* Format output token (does not include associated data) */ + for (i = 0, output_message_buffer->length = 0; i < iov_count; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_SIGN_ONLY) + continue; + + output_message_buffer->length += iov[i].buffer.length; + } + + output_message_buffer->value = gssalloc_malloc(output_message_buffer->length); + if (output_message_buffer->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + i = 0, offset = 0; + + /* HEADER */ + iov[i].buffer.value = (unsigned char *)output_message_buffer->value + offset; + offset += iov[i].buffer.length; + i++; + + /* SIGN_ONLY_DATA */ + if (input_assoc_buffer != GSS_C_NO_BUFFER) + i++; + + /* DATA */ + iov[i].buffer.value = (unsigned char *)output_message_buffer->value + offset; + offset += iov[i].buffer.length; + + memcpy(iov[i].buffer.value, input_payload_buffer->value, iov[i].buffer.length); + i++; + + /* PADDING */ + iov[i].buffer.value = (unsigned char *)output_message_buffer->value + offset; + offset += iov[i].buffer.length; + i++; + + /* TRAILER */ + iov[i].buffer.value = (unsigned char *)output_message_buffer->value + offset; + offset += iov[i].buffer.length; + i++; + + assert(offset == output_message_buffer->length); + + assert(mech->gss_wrap_iov); + + status = mech->gss_wrap_iov(minor_status, context_handle, + conf_req_flag, qop_req, + conf_state, iov, iov_count); + if (status != GSS_S_COMPLETE) { + OM_uint32 minor; + + map_error(minor_status, mech); + gss_release_buffer(&minor, output_message_buffer); + } + + return status; +} + +OM_uint32 +gssint_wrap_aead (gss_mechanism mech, + OM_uint32 *minor_status, + gss_union_ctx_id_t ctx, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_assoc_buffer, + gss_buffer_t input_payload_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + /* EXPORT DELETE START */ + OM_uint32 status; + + assert(ctx != NULL); + assert(mech != NULL); + + if (mech->gss_wrap_aead) { + status = mech->gss_wrap_aead(minor_status, + ctx->internal_ctx_id, + conf_req_flag, + qop_req, + input_assoc_buffer, + input_payload_buffer, + conf_state, + output_message_buffer); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else if (mech->gss_wrap_iov && mech->gss_wrap_iov_length) { + status = gssint_wrap_aead_iov_shim(mech, + minor_status, + ctx->internal_ctx_id, + conf_req_flag, + qop_req, + input_assoc_buffer, + input_payload_buffer, + conf_state, + output_message_buffer); + } else + status = GSS_S_UNAVAILABLE; + + /* EXPORT DELETE END */ + + return status; +} + +OM_uint32 KRB5_CALLCONV +gss_wrap_aead (minor_status, + context_handle, + conf_req_flag, + qop_req, + input_assoc_buffer, + input_payload_buffer, + conf_state, + output_message_buffer) +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +int conf_req_flag; +gss_qop_t qop_req; +gss_buffer_t input_assoc_buffer; +gss_buffer_t input_payload_buffer; +int * conf_state; +gss_buffer_t output_message_buffer; +{ + OM_uint32 status; + gss_mechanism mech; + gss_union_ctx_id_t ctx; + + status = val_wrap_aead_args(minor_status, context_handle, + conf_req_flag, qop_req, + input_assoc_buffer, input_payload_buffer, + conf_state, output_message_buffer); + if (status != GSS_S_COMPLETE) + return (status); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + ctx = (gss_union_ctx_id_t)context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + if (!mech) + return (GSS_S_BAD_MECH); + + return gssint_wrap_aead(mech, minor_status, ctx, + conf_req_flag, qop_req, + input_assoc_buffer, input_payload_buffer, + conf_state, output_message_buffer); +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/g_wrap_iov.c b/krb5-1.21.3/src/lib/gssapi/mechglue/g_wrap_iov.c new file mode 100644 index 00000000..14447c4e --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/g_wrap_iov.c @@ -0,0 +1,269 @@ +/* #pragma ident "@(#)g_seal.c 1.19 98/04/21 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routine for gss_wrap_iov + */ + +#include "mglueP.h" + +static OM_uint32 +val_wrap_iov_args( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + + /* Initialize outputs. */ + + if (minor_status != NULL) + *minor_status = 0; + + /* Validate arguments. */ + + if (minor_status == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (context_handle == GSS_C_NO_CONTEXT) + return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT); + + if (iov == GSS_C_NO_IOV_BUFFER) + return (GSS_S_CALL_INACCESSIBLE_READ); + + return (GSS_S_COMPLETE); +} + + +OM_uint32 KRB5_CALLCONV +gss_wrap_iov (minor_status, + context_handle, + conf_req_flag, + qop_req, + conf_state, + iov, + iov_count) +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +int conf_req_flag; +gss_qop_t qop_req; +int * conf_state; +gss_iov_buffer_desc * iov; +int iov_count; +{ + /* EXPORT DELETE START */ + + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_wrap_iov_args(minor_status, context_handle, + conf_req_flag, qop_req, + conf_state, iov, iov_count); + if (status != GSS_S_COMPLETE) + return (status); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + + if (mech) { + if (mech->gss_wrap_iov) { + status = mech->gss_wrap_iov( + minor_status, + ctx->internal_ctx_id, + conf_req_flag, + qop_req, + conf_state, + iov, + iov_count); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + /* EXPORT DELETE END */ + + return (GSS_S_BAD_MECH); +} + +OM_uint32 KRB5_CALLCONV +gss_wrap_iov_length (minor_status, + context_handle, + conf_req_flag, + qop_req, + conf_state, + iov, + iov_count) +OM_uint32 * minor_status; +gss_ctx_id_t context_handle; +int conf_req_flag; +gss_qop_t qop_req; +int * conf_state; +gss_iov_buffer_desc * iov; +int iov_count; +{ + /* EXPORT DELETE START */ + + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_wrap_iov_args(minor_status, context_handle, + conf_req_flag, qop_req, + conf_state, iov, iov_count); + if (status != GSS_S_COMPLETE) + return (status); + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + ctx = (gss_union_ctx_id_t) context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + mech = gssint_get_mechanism (ctx->mech_type); + + if (mech) { + if (mech->gss_wrap_iov_length) { + status = mech->gss_wrap_iov_length( + minor_status, + ctx->internal_ctx_id, + conf_req_flag, + qop_req, + conf_state, + iov, + iov_count); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return(status); + } + /* EXPORT DELETE END */ + + return (GSS_S_BAD_MECH); +} + +OM_uint32 KRB5_CALLCONV +gss_get_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_qop_t qop_req, gss_iov_buffer_desc *iov, int iov_count) +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_wrap_iov_args(minor_status, context_handle, 0, qop_req, NULL, + iov, iov_count); + if (status != GSS_S_COMPLETE) + return status; + + /* Select the approprate underlying mechanism routine and call it. */ + ctx = (gss_union_ctx_id_t)context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + mech = gssint_get_mechanism(ctx->mech_type); + if (mech == NULL) + return GSS_S_BAD_MECH; + if (mech->gss_get_mic_iov == NULL) + return GSS_S_UNAVAILABLE; + status = mech->gss_get_mic_iov(minor_status, ctx->internal_ctx_id, qop_req, + iov, iov_count); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + return status; +} + +OM_uint32 KRB5_CALLCONV +gss_get_mic_iov_length(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_qop_t qop_req, gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + status = val_wrap_iov_args(minor_status, context_handle, 0, qop_req, NULL, + iov, iov_count); + if (status != GSS_S_COMPLETE) + return status; + + /* Select the approprate underlying mechanism routine and call it. */ + ctx = (gss_union_ctx_id_t)context_handle; + if (ctx->internal_ctx_id == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + mech = gssint_get_mechanism(ctx->mech_type); + if (mech == NULL) + return GSS_S_BAD_MECH; + if (mech->gss_get_mic_iov_length == NULL) + return GSS_S_UNAVAILABLE; + status = mech->gss_get_mic_iov_length(minor_status, ctx->internal_ctx_id, + qop_req, iov, iov_count); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + return status; +} + +OM_uint32 KRB5_CALLCONV +gss_release_iov_buffer (minor_status, + iov, + iov_count) +OM_uint32 * minor_status; +gss_iov_buffer_desc * iov; +int iov_count; +{ + OM_uint32 status = GSS_S_COMPLETE; + int i; + + if (minor_status) + *minor_status = 0; + + if (iov == GSS_C_NO_IOV_BUFFER) + return GSS_S_COMPLETE; + + for (i = 0; i < iov_count; i++) { + if (iov[i].type & GSS_IOV_BUFFER_FLAG_ALLOCATED) { + status = gss_release_buffer(minor_status, &iov[i].buffer); + if (status != GSS_S_COMPLETE) + break; + + iov[i].type &= ~(GSS_IOV_BUFFER_FLAG_ALLOCATED); + } + } + + return status; +} diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/gssd_pname_to_uid.c b/krb5-1.21.3/src/lib/gssapi/mechglue/gssd_pname_to_uid.c new file mode 100644 index 00000000..4caa7516 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/gssd_pname_to_uid.c @@ -0,0 +1,226 @@ +/* #pragma ident "@(#)gssd_pname_to_uid.c 1.18 04/02/23 SMI" */ +/* + * Copyright (c) 2011, PADL Software Pty Ltd. + * 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 PADL Software 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 PADL SOFTWARE 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 PADL SOFTWARE 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. + */ +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * glue routines that test the mech id either passed in to + * gss_init_sec_contex() or gss_accept_sec_context() or within the glue + * routine supported version of the security context and then call + * the appropriate underlying mechanism library procedure. + * + */ + +#include "mglueP.h" + +#ifndef NO_PASSWORD +#include +#endif + +static OM_uint32 +attr_localname(OM_uint32 *minor, + const gss_mechanism mech, + const gss_name_t mech_name, + gss_buffer_t localname) +{ + OM_uint32 major = GSS_S_UNAVAILABLE; + OM_uint32 tmpMinor; + int more = -1; + gss_buffer_desc value; + gss_buffer_desc display_value; + int authenticated = 0, complete = 0; + + value.value = NULL; + display_value.value = NULL; + if (mech->gss_get_name_attribute == NULL) + return GSS_S_UNAVAILABLE; + + major = mech->gss_get_name_attribute(minor, + mech_name, + GSS_C_ATTR_LOCAL_LOGIN_USER, + &authenticated, + &complete, + &value, + &display_value, + &more); + if (GSS_ERROR(major)) { + map_error(minor, mech); + goto cleanup; + } + + if (!authenticated) + major = GSS_S_UNAVAILABLE; + else { + localname->value = value.value; + localname->length = value.length; + value.value = NULL; + } + +cleanup: + if (display_value.value) + gss_release_buffer(&tmpMinor, &display_value); + if (value.value) + gss_release_buffer(&tmpMinor, &value); + return major; +} + +OM_uint32 KRB5_CALLCONV +gss_localname(OM_uint32 *minor, + const gss_name_t pname, + gss_const_OID mech_type, + gss_buffer_t localname) +{ + OM_uint32 major, tmpMinor; + gss_mechanism mech; + gss_union_name_t unionName; + gss_name_t mechName = GSS_C_NO_NAME, mechNameP; + gss_OID selected_mech = GSS_C_NO_OID, public_mech; + + if (localname != GSS_C_NO_BUFFER) { + localname->length = 0; + localname->value = NULL; + } + + if (minor == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + *minor = 0; + + if (pname == GSS_C_NO_NAME) + return GSS_S_CALL_INACCESSIBLE_READ; + + if (localname == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + unionName = (gss_union_name_t)pname; + + if (mech_type != GSS_C_NO_OID) { + major = gssint_select_mech_type(minor, mech_type, &selected_mech); + if (major != GSS_S_COMPLETE) + return major; + mech = gssint_get_mechanism(selected_mech); + } else + mech = gssint_get_mechanism(unionName->mech_type); + + if (mech == NULL) + return GSS_S_BAD_MECH; + + /* may need to create a mechanism specific name */ + if (unionName->mech_type == GSS_C_NO_OID || + (unionName->mech_type != GSS_C_NO_OID && + !g_OID_equal(unionName->mech_type, &mech->mech_type))) { + major = gssint_import_internal_name(minor, &mech->mech_type, + unionName, &mechName); + if (GSS_ERROR(major)) + return major; + + mechNameP = mechName; + } else + mechNameP = unionName->mech_name; + + major = GSS_S_UNAVAILABLE; + + if (mech->gss_localname != NULL) { + public_mech = gssint_get_public_oid(selected_mech); + major = mech->gss_localname(minor, mechNameP, public_mech, localname); + if (GSS_ERROR(major)) + map_error(minor, mech); + } + + if (GSS_ERROR(major)) + major = attr_localname(minor, mech, mechNameP, localname); + + if (mechName != GSS_C_NO_NAME) + gssint_release_internal_name(&tmpMinor, &mech->mech_type, &mechName); + + return major; +} + +#ifndef _WIN32 +OM_uint32 KRB5_CALLCONV +gss_pname_to_uid(OM_uint32 *minor, + const gss_name_t name, + const gss_OID mech_type, + uid_t *uidOut) +{ + OM_uint32 major = GSS_S_UNAVAILABLE, tmpminor; +#ifndef NO_PASSWORD + gss_buffer_desc localname; + char pwbuf[BUFSIZ]; + char *localuser = NULL; + struct passwd *pwd = NULL; + struct passwd pw; + int code = 0; + + localname.value = NULL; + major = gss_localname(minor, name, mech_type, &localname); + if (!GSS_ERROR(major) && localname.value) { + localuser = malloc(localname.length + 1); + if (localuser == NULL) + code = ENOMEM; + if (code == 0) { + memcpy(localuser, localname.value, localname.length); + localuser[localname.length] = '\0'; + code = k5_getpwnam_r(localuser, &pw, pwbuf, sizeof(pwbuf), &pwd); + } + if ((code == 0) && pwd) + *uidOut = pwd->pw_uid; + else + major = GSS_S_FAILURE; + } + free(localuser); + if (localname.value) + gss_release_buffer(&tmpminor, &localname); +#endif /*NO_PASSWORD*/ + return major; +} +#endif /*_WIN32*/ diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/mechglue.h b/krb5-1.21.3/src/lib/gssapi/mechglue/mechglue.h new file mode 100644 index 00000000..85983694 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/mechglue.h @@ -0,0 +1,42 @@ +/* #ident "@(#)mechglue.h 1.13 95/08/07 SMI" */ + +/* + * Copyright 1996 by Sun Microsystems, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Sun Microsystems not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Sun Microsystems makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This header contains the mechglue definitions. + */ + +#ifndef _GSS_MECHGLUE_H +#define _GSS_MECHGLUE_H + +#include + +/********************************************************/ +/* GSSAPI Extension functions -- these functions aren't */ +/* in the GSSAPI, but they are provided in this library */ + +#include + +void KRB5_CALLCONV gss_initialize(void); + +#endif /* _GSS_MECHGLUE_H */ diff --git a/krb5-1.21.3/src/lib/gssapi/mechglue/mglueP.h b/krb5-1.21.3/src/lib/gssapi/mechglue/mglueP.h new file mode 100644 index 00000000..7f836fbb --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/mechglue/mglueP.h @@ -0,0 +1,864 @@ +/* lib/gssapi/mechglue/mglueP.h */ + +/* + * Copyright (c) 1995, by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* This header contains the private mechglue definitions. */ + +#ifndef _GSS_MECHGLUEP_H +#define _GSS_MECHGLUEP_H + +#include "autoconf.h" +#include "mechglue.h" +#include "gssapiP_generic.h" + +#define g_OID_copy(o1, o2) \ +do { \ + memcpy((o1)->elements, (o2)->elements, (o2)->length); \ + (o1)->length = (o2)->length; \ +} while (0) + +/* + * Array of context IDs typed by mechanism OID + */ +typedef struct gss_union_ctx_id_struct { + struct gss_union_ctx_id_struct *loopback; + gss_OID mech_type; + gss_ctx_id_t internal_ctx_id; +} gss_union_ctx_id_desc, *gss_union_ctx_id_t; + +/* + * Generic GSSAPI names. A name can either be a generic name, or a + * mechanism specific name.... + */ +typedef struct gss_name_struct { + struct gss_name_struct *loopback; + gss_OID name_type; + gss_buffer_t external_name; + /* + * These last two fields are only filled in for mechanism + * names. + */ + gss_OID mech_type; + gss_name_t mech_name; +} gss_union_name_desc, *gss_union_name_t; + +/* + * Structure for holding list of mechanism-specific name types + */ +typedef struct gss_mech_spec_name_t { + gss_OID name_type; + gss_OID mech; + struct gss_mech_spec_name_t *next, *prev; +} gss_mech_spec_name_desc, *gss_mech_spec_name; + +/* + * Set of Credentials typed on mechanism OID + */ +typedef struct gss_cred_id_struct { + struct gss_cred_id_struct *loopback; + int count; + gss_OID mechs_array; + gss_cred_id_t *cred_array; +} gss_union_cred_desc, *gss_union_cred_t; + +/* + * Rudimentary pointer validation macro to check whether the + * "loopback" field of an opaque struct points back to itself. This + * field also catches some programming errors where an opaque pointer + * is passed to a function expecting the address of the opaque + * pointer. + */ +#define GSSINT_CHK_LOOP(p) (!((p) != NULL && (p)->loopback == (p))) + +/********************************************************/ +/* The Mechanism Dispatch Table -- a mechanism needs to */ +/* define one of these and provide a function to return */ +/* it to initialize the GSSAPI library */ +int gssint_mechglue_initialize_library(void); + +OM_uint32 gssint_get_mech_type_oid(gss_OID OID, gss_buffer_t token); + +/* + * This table is used to access mechanism-specific versions of the GSSAPI + * functions. It contains all of the functions defined in gssapi.h except for + * gss_release_buffer() and gss_release_oid_set(), which are assumed to be + * identical across mechanisms. + */ +typedef struct gss_config { + gss_OID_desc mech_type; + void * context; + OM_uint32 (KRB5_CALLCONV *gss_acquire_cred) + ( + OM_uint32*, /* minor_status */ + gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + gss_OID_set, /* desired_mechs */ + int, /* cred_usage */ + gss_cred_id_t*, /* output_cred_handle */ + gss_OID_set*, /* actual_mechs */ + OM_uint32* /* time_rec */ + ); + OM_uint32 (KRB5_CALLCONV *gss_release_cred) + ( + OM_uint32*, /* minor_status */ + gss_cred_id_t* /* cred_handle */ + ); + OM_uint32 (KRB5_CALLCONV *gss_init_sec_context) + ( + OM_uint32*, /* minor_status */ + gss_cred_id_t, /* claimant_cred_handle */ + gss_ctx_id_t*, /* context_handle */ + gss_name_t, /* target_name */ + gss_OID, /* mech_type */ + OM_uint32, /* req_flags */ + OM_uint32, /* time_req */ + gss_channel_bindings_t, /* input_chan_bindings */ + gss_buffer_t, /* input_token */ + gss_OID*, /* actual_mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32*, /* ret_flags */ + OM_uint32* /* time_rec */ + ); + OM_uint32 (KRB5_CALLCONV *gss_accept_sec_context) + ( + OM_uint32*, /* minor_status */ + gss_ctx_id_t*, /* context_handle */ + gss_cred_id_t, /* verifier_cred_handle */ + gss_buffer_t, /* input_token_buffer */ + gss_channel_bindings_t, /* input_chan_bindings */ + gss_name_t*, /* src_name */ + gss_OID*, /* mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32*, /* ret_flags */ + OM_uint32*, /* time_rec */ + gss_cred_id_t* /* delegated_cred_handle */ + ); + OM_uint32 (KRB5_CALLCONV *gss_process_context_token) + ( + OM_uint32*, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t /* token_buffer */ + ); + OM_uint32 (KRB5_CALLCONV *gss_delete_sec_context) + ( + OM_uint32*, /* minor_status */ + gss_ctx_id_t*, /* context_handle */ + gss_buffer_t /* output_token */ + ); + OM_uint32 (KRB5_CALLCONV *gss_context_time) + ( + OM_uint32*, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + OM_uint32* /* time_rec */ + ); + OM_uint32 (KRB5_CALLCONV *gss_get_mic) + ( + OM_uint32*, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t, /* qop_req */ + gss_buffer_t, /* message_buffer */ + gss_buffer_t /* message_token */ + ); + OM_uint32 (KRB5_CALLCONV *gss_verify_mic) + ( + OM_uint32*, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t, /* message_buffer */ + gss_buffer_t, /* token_buffer */ + gss_qop_t* /* qop_state */ + ); + OM_uint32 (KRB5_CALLCONV *gss_wrap) + ( + OM_uint32*, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + gss_buffer_t, /* input_message_buffer */ + int*, /* conf_state */ + gss_buffer_t /* output_message_buffer */ + ); + OM_uint32 (KRB5_CALLCONV *gss_unwrap) + ( + OM_uint32*, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t, /* input_message_buffer */ + gss_buffer_t, /* output_message_buffer */ + int*, /* conf_state */ + gss_qop_t* /* qop_state */ + ); + OM_uint32 (KRB5_CALLCONV *gss_display_status) + ( + OM_uint32*, /* minor_status */ + OM_uint32, /* status_value */ + int, /* status_type */ + gss_OID, /* mech_type */ + OM_uint32*, /* message_context */ + gss_buffer_t /* status_string */ + ); + OM_uint32 (KRB5_CALLCONV *gss_indicate_mechs) + ( + OM_uint32*, /* minor_status */ + gss_OID_set* /* mech_set */ + ); + OM_uint32 (KRB5_CALLCONV *gss_compare_name) + ( + OM_uint32*, /* minor_status */ + gss_name_t, /* name1 */ + gss_name_t, /* name2 */ + int* /* name_equal */ + ); + OM_uint32 (KRB5_CALLCONV *gss_display_name) + ( + OM_uint32*, /* minor_status */ + gss_name_t, /* input_name */ + gss_buffer_t, /* output_name_buffer */ + gss_OID* /* output_name_type */ + ); + OM_uint32 (KRB5_CALLCONV *gss_import_name) + ( + OM_uint32*, /* minor_status */ + gss_buffer_t, /* input_name_buffer */ + gss_OID, /* input_name_type */ + gss_name_t* /* output_name */ + ); + OM_uint32 (KRB5_CALLCONV *gss_release_name) + ( + OM_uint32*, /* minor_status */ + gss_name_t* /* input_name */ + ); + OM_uint32 (KRB5_CALLCONV *gss_inquire_cred) + ( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* cred_handle */ + gss_name_t *, /* name */ + OM_uint32 *, /* lifetime */ + int *, /* cred_usage */ + gss_OID_set * /* mechanisms */ + ); + OM_uint32 (KRB5_CALLCONV *gss_add_cred) + ( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* input_cred_handle */ + gss_name_t, /* desired_name */ + gss_OID, /* desired_mech */ + gss_cred_usage_t, /* cred_usage */ + OM_uint32, /* initiator_time_req */ + OM_uint32, /* acceptor_time_req */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *, /* initiator_time_rec */ + OM_uint32 * /* acceptor_time_rec */ + ); + OM_uint32 (KRB5_CALLCONV *gss_export_sec_context) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + gss_buffer_t /* interprocess_token */ + ); + OM_uint32 (KRB5_CALLCONV *gss_import_sec_context) + ( + OM_uint32 *, /* minor_status */ + gss_buffer_t, /* interprocess_token */ + gss_ctx_id_t * /* context_handle */ + ); + OM_uint32 (KRB5_CALLCONV *gss_inquire_cred_by_mech) + ( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* cred_handle */ + gss_OID, /* mech_type */ + gss_name_t *, /* name */ + OM_uint32 *, /* initiator_lifetime */ + OM_uint32 *, /* acceptor_lifetime */ + gss_cred_usage_t * /* cred_usage */ + ); + OM_uint32 (KRB5_CALLCONV *gss_inquire_names_for_mech) + ( + OM_uint32 *, /* minor_status */ + gss_OID, /* mechanism */ + gss_OID_set * /* name_types */ + ); + OM_uint32 (KRB5_CALLCONV *gss_inquire_context) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_name_t *, /* src_name */ + gss_name_t *, /* targ_name */ + OM_uint32 *, /* lifetime_rec */ + gss_OID *, /* mech_type */ + OM_uint32 *, /* ctx_flags */ + int *, /* locally_initiated */ + int * /* open */ + ); + OM_uint32 (KRB5_CALLCONV *gss_internal_release_oid) + ( + OM_uint32 *, /* minor_status */ + gss_OID * /* OID */ + ); + OM_uint32 (KRB5_CALLCONV *gss_wrap_size_limit) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + OM_uint32, /* req_output_size */ + OM_uint32 * /* max_input_size */ + ); + OM_uint32 (KRB5_CALLCONV *gss_localname) + ( + OM_uint32 *, /* minor */ + const gss_name_t, /* name */ + gss_const_OID, /* mech_type */ + gss_buffer_t /* localname */ + ); + OM_uint32 (KRB5_CALLCONV *gssspi_authorize_localname) + ( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* pname */ + gss_const_buffer_t, /* local user */ + gss_const_OID /* local nametype */ + /* */); + OM_uint32 (KRB5_CALLCONV *gss_export_name) + ( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* input_name */ + gss_buffer_t /* exported_name */ + /* */); + OM_uint32 (KRB5_CALLCONV *gss_duplicate_name) + ( + OM_uint32*, /* minor_status */ + const gss_name_t, /* input_name */ + gss_name_t * /* output_name */ + /* */); + OM_uint32 (KRB5_CALLCONV *gss_store_cred) + ( + OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* input_cred */ + gss_cred_usage_t, /* cred_usage */ + const gss_OID, /* desired_mech */ + OM_uint32, /* overwrite_cred */ + OM_uint32, /* default_cred */ + gss_OID_set *, /* elements_stored */ + gss_cred_usage_t * /* cred_usage_stored */ + /* */); + + + /* GGF extensions */ + + OM_uint32 (KRB5_CALLCONV *gss_inquire_sec_context_by_oid) + ( + OM_uint32 *, /* minor_status */ + const gss_ctx_id_t, /* context_handle */ + const gss_OID, /* OID */ + gss_buffer_set_t * /* data_set */ + ); + OM_uint32 (KRB5_CALLCONV *gss_inquire_cred_by_oid) + ( + OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* cred_handle */ + const gss_OID, /* OID */ + gss_buffer_set_t * /* data_set */ + ); + OM_uint32 (KRB5_CALLCONV *gss_set_sec_context_option) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + const gss_OID, /* OID */ + const gss_buffer_t /* value */ + ); + OM_uint32 (KRB5_CALLCONV *gssspi_set_cred_option) + ( + OM_uint32 *, /* minor_status */ + gss_cred_id_t *, /* cred_handle */ + const gss_OID, /* OID */ + const gss_buffer_t /* value */ + ); + OM_uint32 (KRB5_CALLCONV *gssspi_mech_invoke) + ( + OM_uint32*, /* minor_status */ + const gss_OID, /* mech OID */ + const gss_OID, /* OID */ + gss_buffer_t /* value */ + ); + + /* AEAD extensions */ + OM_uint32 (KRB5_CALLCONV *gss_wrap_aead) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + gss_buffer_t, /* input_assoc_buffer */ + gss_buffer_t, /* input_payload_buffer */ + int *, /* conf_state */ + gss_buffer_t /* output_message_buffer */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_unwrap_aead) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_buffer_t, /* input_message_buffer */ + gss_buffer_t, /* input_assoc_buffer */ + gss_buffer_t, /* output_payload_buffer */ + int *, /* conf_state */ + gss_qop_t * /* qop_state */ + /* */); + + /* SSPI extensions */ + OM_uint32 (KRB5_CALLCONV *gss_wrap_iov) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + int *, /* conf_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_unwrap_iov) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int *, /* conf_state */ + gss_qop_t *, /* qop_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_wrap_iov_length) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag*/ + gss_qop_t, /* qop_req */ + int *, /* conf_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_complete_auth_token) + ( + OM_uint32*, /* minor_status */ + const gss_ctx_id_t, /* context_handle */ + gss_buffer_t /* input_message_buffer */ + ); + + /* New for 1.8 */ + + OM_uint32 (KRB5_CALLCONV *gss_acquire_cred_impersonate_name) + ( + OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* impersonator_cred_handle */ + const gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + const gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 * /* time_rec */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_add_cred_impersonate_name) + ( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* input_cred_handle */ + const gss_cred_id_t, /* impersonator_cred_handle */ + const gss_name_t, /* desired_name */ + const gss_OID, /* desired_mech */ + gss_cred_usage_t, /* cred_usage */ + OM_uint32, /* initiator_time_req */ + OM_uint32, /* acceptor_time_req */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *, /* initiator_time_rec */ + OM_uint32 * /* acceptor_time_rec */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_display_name_ext) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_OID, /* display_as_name_type */ + gss_buffer_t /* display_name */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_inquire_name) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + int *, /* name_is_MN */ + gss_OID *, /* MN_mech */ + gss_buffer_set_t * /* attrs */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_get_name_attribute) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t, /* attr */ + int *, /* authenticated */ + int *, /* complete */ + gss_buffer_t, /* value */ + gss_buffer_t, /* display_value */ + int * /* more */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_set_name_attribute) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + int, /* complete */ + gss_buffer_t, /* attr */ + gss_buffer_t /* value */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_delete_name_attribute) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t /* attr */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_export_name_composite) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t /* exp_composite_name */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_map_name_to_any) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + int, /* authenticated */ + gss_buffer_t, /* type_id */ + gss_any_t * /* output */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_release_any_name_mapping) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* name */ + gss_buffer_t, /* type_id */ + gss_any_t * /* input */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_pseudo_random) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context */ + int, /* prf_key */ + const gss_buffer_t, /* prf_in */ + ssize_t, /* desired_output_len */ + gss_buffer_t /* prf_out */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_set_neg_mechs) + ( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* cred_handle */ + const gss_OID_set /* mech_set */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_inquire_saslname_for_mech) + ( + OM_uint32 *, /* minor_status */ + const gss_OID, /* desired_mech */ + gss_buffer_t, /* sasl_mech_name */ + gss_buffer_t, /* mech_name */ + gss_buffer_t /* mech_description */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_inquire_mech_for_saslname) + ( + OM_uint32 *, /* minor_status */ + const gss_buffer_t, /* sasl_mech_name */ + gss_OID * /* mech_type */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_inquire_attrs_for_mech) + ( + OM_uint32 *, /* minor_status */ + gss_const_OID, /* mech */ + gss_OID_set *, /* mech_attrs */ + gss_OID_set * /* known_mech_attrs */ + /* */); + + /* Credential store extensions */ + + OM_uint32 (KRB5_CALLCONV *gss_acquire_cred_from) + ( + OM_uint32 *, /* minor_status */ + gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_const_key_value_set_t, /* cred_store */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 * /* time_rec */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_store_cred_into) + ( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* input_cred_handle */ + gss_cred_usage_t, /* input_usage */ + gss_OID, /* desired_mech */ + OM_uint32, /* overwrite_cred */ + OM_uint32, /* default_cred */ + gss_const_key_value_set_t, /* cred_store */ + gss_OID_set *, /* elements_stored */ + gss_cred_usage_t * /* cred_usage_stored */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gssspi_acquire_cred_with_password) + ( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* desired_name */ + const gss_buffer_t, /* password */ + OM_uint32, /* time_req */ + const gss_OID_set, /* desired_mechs */ + int, /* cred_usage */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 * /* time_rec */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_export_cred) + ( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* cred_handle */ + gss_buffer_t /* token */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gss_import_cred) + ( + OM_uint32 *, /* minor_status */ + gss_buffer_t, /* token */ + gss_cred_id_t * /* cred_handle */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gssspi_import_sec_context_by_mech) + ( + OM_uint32 *, /* minor_status */ + gss_OID, /* desired_mech */ + gss_buffer_t, /* interprocess_token */ + gss_ctx_id_t * /* context_handle */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gssspi_import_name_by_mech) + ( + OM_uint32 *, /* minor_status */ + gss_OID, /* mech_type */ + gss_buffer_t, /* input_name_buffer */ + gss_OID, /* input_name_type */ + gss_name_t* /* output_name */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gssspi_import_cred_by_mech) + ( + OM_uint32 *, /* minor_status */ + gss_OID, /* mech_type */ + gss_buffer_t, /* token */ + gss_cred_id_t * /* cred_handle */ + /* */); + + /* get_mic_iov extensions, added in 1.12 */ + + OM_uint32 (KRB5_CALLCONV *gss_get_mic_iov) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t, /* qop_req */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ + ); + + OM_uint32 (KRB5_CALLCONV *gss_verify_mic_iov) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t *, /* qop_state */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ + ); + + OM_uint32 (KRB5_CALLCONV *gss_get_mic_iov_length) + ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t, /* context_handle */ + gss_qop_t, /* qop_req */ + gss_iov_buffer_desc *, /* iov */ + int /* iov_count */ + ); + + /* NegoEx extensions added in 1.18 */ + + OM_uint32 (KRB5_CALLCONV *gssspi_query_meta_data) + ( + OM_uint32 *, /* minor_status */ + gss_const_OID, /* mech_oid */ + gss_cred_id_t, /* cred_handle */ + gss_ctx_id_t *, /* context_handle */ + const gss_name_t, /* targ_name */ + OM_uint32, /* req_flags */ + gss_buffer_t /* meta_data */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gssspi_exchange_meta_data) + ( + OM_uint32 *, /* minor_status */ + gss_const_OID, /* mech_oid */ + gss_cred_id_t, /* cred_handle */ + gss_ctx_id_t *, /* context_handle */ + const gss_name_t, /* targ_name */ + OM_uint32, /* req_flags */ + gss_const_buffer_t /* meta_data */ + /* */); + + OM_uint32 (KRB5_CALLCONV *gssspi_query_mechanism_info) + ( + OM_uint32 *, /* minor_status */ + gss_const_OID, /* mech_oid */ + unsigned char[16] /* auth_scheme */ + /* */); + +} *gss_mechanism; + +/* + * In the user space we use a wrapper structure to encompass the + * mechanism entry points. The wrapper contain the mechanism + * entry points and other data which is only relevant to the gss-api + * layer. In the kernel we use only the gss_config structure because + * the kernel does not cantain any of the extra gss-api specific data. + */ +typedef struct gss_mech_config { + char *kmodName; /* kernel module name */ + char *uLibName; /* user library name */ + char *mechNameStr; /* mechanism string name */ + char *optionStr; /* optional mech parameters */ + void *dl_handle; /* RTLD object handle for the mech */ + gss_OID mech_type; /* mechanism oid */ + gss_mechanism mech; /* mechanism initialization struct */ + int priority; /* mechanism preference order */ + int freeMech; /* free mech table */ + int is_interposer; /* interposer mechanism flag */ + gss_OID int_mech_type; /* points to the interposer OID */ + gss_mechanism int_mech; /* points to the interposer mech */ + struct gss_mech_config *next; /* next element in the list */ +} *gss_mech_info; + +/********************************************************/ +/* Internal mechglue routines */ + +OM_uint32 gssint_select_mech_type(OM_uint32 *minor, gss_const_OID in_oid, + gss_OID *selected_oid); +gss_OID gssint_get_public_oid(gss_const_OID internal_oid); +OM_uint32 gssint_make_public_oid_set(OM_uint32 *minor_status, gss_OID oids, + int count, gss_OID_set *public_set); +gss_mechanism gssint_get_mechanism (gss_const_OID); +OM_uint32 gssint_get_mech_type (gss_OID, gss_buffer_t); +char *gssint_get_kmodName(const gss_OID); +char *gssint_get_modOptions(const gss_OID); +OM_uint32 gssint_import_internal_name (OM_uint32 *, gss_OID, gss_union_name_t, + gss_name_t *); +OM_uint32 gssint_export_internal_name(OM_uint32 *, const gss_OID, + const gss_name_t, gss_buffer_t); +OM_uint32 gssint_display_internal_name (OM_uint32 *, gss_OID, gss_name_t, + gss_buffer_t, gss_OID *); +OM_uint32 gssint_release_internal_name (OM_uint32 *, gss_OID, gss_name_t *); +OM_uint32 gssint_delete_internal_sec_context (OM_uint32 *, gss_OID, + gss_ctx_id_t *, gss_buffer_t); +#ifdef _GSS_STATIC_LINK +int gssint_register_mechinfo(gss_mech_info template); +#endif + +OM_uint32 gssint_convert_name_to_union_name + (OM_uint32 *, /* minor_status */ + gss_mechanism, /* mech */ + gss_name_t, /* internal_name */ + gss_name_t * /* external_name */ + ); +gss_cred_id_t gssint_get_mechanism_cred + (gss_union_cred_t, /* union_cred */ + gss_OID /* mech_type */ + ); + +OM_uint32 gssint_create_copy_buffer( + const gss_buffer_t, /* src buffer */ + gss_buffer_t *, /* destination buffer */ + int /* NULL terminate buffer ? */ +); + +OM_uint32 gssint_create_union_context( + OM_uint32 *minor, /* minor_status */ + gss_const_OID, /* mech_oid */ + gss_union_ctx_id_t * /* ctx_out */ +); + +OM_uint32 gssint_copy_oid_set( + OM_uint32 *, /* minor_status */ + const gss_OID_set_desc * const, /* oid set */ + gss_OID_set * /* new oid set */ +); + +gss_OID gss_find_mechanism_from_name_type (gss_OID); /* name_type */ + +OM_uint32 gss_add_mech_name_type + (OM_uint32 *, /* minor_status */ + gss_OID, /* name_type */ + gss_OID /* mech */ + ); + +/* + * Sun extensions to GSS-API v2 + */ + +OM_uint32 +gssint_wrap_aead (gss_mechanism, /* mech */ + OM_uint32 *, /* minor_status */ + gss_union_ctx_id_t, /* ctx */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req_flag */ + gss_buffer_t, /* input_assoc_buffer */ + gss_buffer_t, /* input_payload_buffer */ + int *, /* conf_state */ + gss_buffer_t); /* output_message_buffer */ +OM_uint32 +gssint_unwrap_aead (gss_mechanism, /* mech */ + OM_uint32 *, /* minor_status */ + gss_union_ctx_id_t, /* ctx */ + gss_buffer_t, /* input_message_buffer */ + gss_buffer_t, /* input_assoc_buffer */ + gss_buffer_t, /* output_payload_buffer */ + int *, /* conf_state */ + gss_qop_t *); /* qop_state */ + + +/* Use this to map an error code that was returned from a mech + operation; the mech will be asked to produce the associated error + messages. + + Remember that if the minor status code cannot be returned to the + caller (e.g., if it's stuffed in an automatic variable and then + ignored), then we don't care about producing a mapping. */ +#define map_error(MINORP, MECH) \ + (*(MINORP) = gssint_mecherrmap_map(*(MINORP), &(MECH)->mech_type)) +#define map_error_oid(MINORP, MECHOID) \ + (*(MINORP) = gssint_mecherrmap_map(*(MINORP), (MECHOID))) + +/* Use this to map an errno value or com_err error code being + generated within the mechglue code (e.g., by calling generic oid + ops). Any errno or com_err values produced by mech operations + should be processed with map_error. This means they'll be stored + separately even if the mech uses com_err, because we can't assume + that it will use com_err. */ +#define map_errcode(MINORP) \ + (*(MINORP) = gssint_mecherrmap_map_errcode(*(MINORP))) + +#endif /* _GSS_MECHGLUEP_H */ diff --git a/krb5-1.21.3/src/lib/gssapi/spnego/Makefile.in b/krb5-1.21.3/src/lib/gssapi/spnego/Makefile.in new file mode 100644 index 00000000..b44ad0e0 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/spnego/Makefile.in @@ -0,0 +1,25 @@ +mydir=lib$(S)gssapi$(S)spnego +BUILDTOP=$(REL)..$(S)..$(S).. +LOCALINCLUDES = -I. -I$(srcdir) -I$(srcdir)/.. -I../generic -I$(srcdir)/../generic -I../mechglue -I$(srcdir)/../mechglue +DEFINES=-D_GSS_STATIC_LINK=1 + +##DOS##BUILDTOP = ..\..\.. +##DOS##PREFIXDIR=spnego +##DOS##OBJFILE = ..\$(OUTPRE)spnego.lst + +##DOS##DLL_EXP_TYPE=GSS + +SRCS = $(srcdir)/spnego_mech.c $(srcdir)/negoex_ctx.c $(srcdir)/negoex_util.c + +OBJS = $(OUTPRE)spnego_mech.$(OBJEXT) $(OUTPRE)negoex_ctx.$(OBJEXT) \ + $(OUTPRE)negoex_util.$(OBJEXT) + +STLIBOBJS = spnego_mech.o negoex_ctx.o negoex_util.o + +all-unix: all-libobjs + +##DOS##LIBOBJS = $(OBJS) + +clean-unix:: clean-libobjs + +@libobj_frag@ diff --git a/krb5-1.21.3/src/lib/gssapi/spnego/deps b/krb5-1.21.3/src/lib/gssapi/spnego/deps new file mode 100644 index 00000000..0d3d25a5 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/spnego/deps @@ -0,0 +1,51 @@ +# +# Generated makefile dependencies follow. +# +spnego_mech.so spnego_mech.po $(OUTPRE)spnego_mech.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(srcdir)/../mechglue/mechglue.h $(srcdir)/../mechglue/mglueP.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-der.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-input.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-queue.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h ../generic/gssapi_err_generic.h \ + gssapiP_negoex.h gssapiP_spnego.h spnego_mech.c +negoex_ctx.so negoex_ctx.po $(OUTPRE)negoex_ctx.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-queue.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h ../generic/gssapi_err_generic.h \ + gssapiP_negoex.h gssapiP_spnego.h negoex_ctx.c +negoex_util.so negoex_util.po $(OUTPRE)negoex_util.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../generic/gssapiP_generic.h \ + $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-input.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-queue.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ../generic/gssapi_err_generic.h gssapiP_negoex.h gssapiP_spnego.h \ + negoex_util.c diff --git a/krb5-1.21.3/src/lib/gssapi/spnego/gssapiP_negoex.h b/krb5-1.21.3/src/lib/gssapi/spnego/gssapiP_negoex.h new file mode 100644 index 00000000..489ab7c4 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/spnego/gssapiP_negoex.h @@ -0,0 +1,210 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2011-2018 PADL Software Pty Ltd. + * 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. + */ + +#include "k5-int.h" + +/* + * { iso(1) identified-organization(3) dod(6) internet(1) private(4) + * enterprise(1) microsoft (311) security(2) mechanisms(2) negoex(30) } + */ +#define NEGOEX_OID_LENGTH 10 +#define NEGOEX_OID "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x1e" + +#define MESSAGE_SIGNATURE 0x535458454F47454EULL + +#define EXTENSION_LENGTH 12 + +#define EXTENSION_FLAG_CRITICAL 0x80000000 + +#define CHECKSUM_SCHEME_RFC3961 1 + +#define NEGOEX_KEYUSAGE_INITIATOR_CHECKSUM 23 +#define NEGOEX_KEYUSAGE_ACCEPTOR_CHECKSUM 25 + +#define CHECKSUM_HEADER_LENGTH 20 + +#define GUID_LENGTH 16 + +typedef uint8_t auth_scheme[GUID_LENGTH]; +typedef uint8_t conversation_id[GUID_LENGTH]; +#define GUID_EQ(a, b) (memcmp(a, b, GUID_LENGTH) == 0) + +#define NEGO_MESSAGE_HEADER_LENGTH 96 +#define EXCHANGE_MESSAGE_HEADER_LENGTH 64 +#define VERIFY_MESSAGE_HEADER_LENGTH 80 +#define ALERT_MESSAGE_HEADER_LENGTH 72 +#define ALERT_LENGTH 12 +#define ALERT_PULSE_LENGTH 8 + +#define ALERT_TYPE_PULSE 1 +#define ALERT_VERIFY_NO_KEY 1 + +enum message_type { + INITIATOR_NEGO = 0, /* NEGO_MESSAGE */ + ACCEPTOR_NEGO, /* NEGO_MESSAGE */ + INITIATOR_META_DATA, /* EXCHANGE_MESSAGE */ + ACCEPTOR_META_DATA, /* EXCHANGE_MESSAGE */ + CHALLENGE, /* EXCHANGE_MESSAGE */ + AP_REQUEST, /* EXCHANGE_MESSAGE */ + VERIFY, /* VERIFY_MESSAGE */ + ALERT, /* ALERT */ +}; + +struct nego_message { + uint8_t random[32]; + const uint8_t *schemes; + uint16_t nschemes; +}; + +struct exchange_message { + auth_scheme scheme; + gss_buffer_desc token; +}; + +struct verify_message { + auth_scheme scheme; + uint32_t cksum_type; + const uint8_t *cksum; + size_t cksum_len; + size_t offset_in_token; +}; + +struct alert_message { + auth_scheme scheme; + int verify_no_key; +}; + +struct negoex_message { + uint32_t type; + union { + struct nego_message n; + struct exchange_message e; + struct verify_message v; + struct alert_message a; + } u; +}; + +struct negoex_auth_mech { + K5_TAILQ_ENTRY(negoex_auth_mech) links; + gss_OID oid; + auth_scheme scheme; + gss_ctx_id_t mech_context; + gss_buffer_desc metadata; + krb5_keyblock key; + krb5_keyblock verify_key; + int complete; + int sent_checksum; + int verified_checksum; +}; + +/* negoex_util.c */ + +OM_uint32 +negoex_parse_token(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + gss_const_buffer_t token, + struct negoex_message **messages_out, size_t *count_out); + + +struct nego_message * +negoex_locate_nego_message(struct negoex_message *messages, size_t nmessages, + enum message_type type); +struct exchange_message * +negoex_locate_exchange_message(struct negoex_message *messages, + size_t nmessages, enum message_type type); +struct verify_message * +negoex_locate_verify_message(struct negoex_message *messages, + size_t nmessages); +struct alert_message * +negoex_locate_alert_message(struct negoex_message *messages, size_t nmessages); + +void +negoex_add_nego_message(spnego_gss_ctx_id_t ctx, enum message_type type, + uint8_t random[32]); +void +negoex_add_exchange_message(spnego_gss_ctx_id_t ctx, enum message_type type, + const auth_scheme scheme, gss_buffer_t token); +void +negoex_add_verify_message(spnego_gss_ctx_id_t ctx, const auth_scheme scheme, + uint32_t cksum_type, const uint8_t *cksum, + uint32_t cksum_len); + +void +negoex_add_verify_no_key_alert(spnego_gss_ctx_id_t ctx, + const auth_scheme scheme); + +OM_uint32 +negoex_random(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + unsigned char *data, size_t length); + +void +negoex_prep_context_for_spnego(spnego_gss_ctx_id_t ctx); + +OM_uint32 +negoex_prep_context_for_negoex(OM_uint32 *minor, spnego_gss_ctx_id_t ctx); + +void +negoex_release_context(spnego_gss_ctx_id_t ctx); + +OM_uint32 +negoex_add_auth_mech(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + gss_const_OID oid, auth_scheme scheme); + +void +negoex_delete_auth_mech(spnego_gss_ctx_id_t ctx, + struct negoex_auth_mech *mech); + +void +negoex_select_auth_mech(spnego_gss_ctx_id_t ctx, + struct negoex_auth_mech *mech); + +struct negoex_auth_mech * +negoex_locate_auth_scheme(spnego_gss_ctx_id_t ctx, const auth_scheme scheme); + +void +negoex_common_auth_schemes(spnego_gss_ctx_id_t ctx, + const uint8_t *schemes, uint16_t nschemes); + +void +negoex_restrict_auth_schemes(spnego_gss_ctx_id_t ctx, + const uint8_t *schemes, uint16_t nschemes); + +/* negoex_ctx.c */ + +OM_uint32 +negoex_init(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + gss_name_t target_name, OM_uint32 req_flags, OM_uint32 time_req, + gss_buffer_t input_token, gss_channel_bindings_t bindings, + gss_buffer_t output_token, OM_uint32 *time_rec); + +OM_uint32 +negoex_accept(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + gss_buffer_t input_token, gss_channel_bindings_t bindings, + gss_buffer_t output_token, OM_uint32 *time_rec); diff --git a/krb5-1.21.3/src/lib/gssapi/spnego/gssapiP_spnego.h b/krb5-1.21.3/src/lib/gssapi/spnego/gssapiP_spnego.h new file mode 100644 index 00000000..066ec736 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/spnego/gssapiP_spnego.h @@ -0,0 +1,698 @@ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _GSSAPIP_SPNEGO_H_ +#define _GSSAPIP_SPNEGO_H_ + +/* #pragma ident "@(#)gssapiP_spnego.h 1.3 03/09/18 SMI" */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct spnego_ctx_st *spnego_gss_ctx_id_t; + +#include +#include +#include +#include "gssapiP_negoex.h" + +#define SEC_CONTEXT_TOKEN 1 +#define SPNEGO_SIZE_OF_INT 4 + +#define ACCEPT_COMPLETE 0 +#define ACCEPT_INCOMPLETE 1 +#define REJECT 2 +#define REQUEST_MIC 3 +#define UNSPECIFIED 0xffffffffUL + +/* + * constants for der encoding/decoding routines. + */ + +#define MECH_OID 0x06 +#define OCTET_STRING 0x04 +#define CONTEXT 0xa0 +#define SEQUENCE 0x30 +#define SEQUENCE_OF 0x30 +#define BIT_STRING 0x03 +#define BIT_STRING_LENGTH 0x02 +#define BIT_STRING_PADDING 0x01 +#define ENUMERATED 0x0a +#define ENUMERATION_LENGTH 1 +#define HEADER_ID 0x60 +#define GENERAL_STRING 0x1b + +/* + * SPNEGO and NegoEx minor status codes + */ +#define ERR_SPNEGO_NO_MECHS_AVAILABLE 0x20000001 +#define ERR_SPNEGO_NO_CREDS_ACQUIRED 0x20000002 +#define ERR_SPNEGO_NO_MECH_FROM_ACCEPTOR 0x20000003 +#define ERR_SPNEGO_NEGOTIATION_FAILED 0x20000004 +#define ERR_SPNEGO_NO_TOKEN_FROM_ACCEPTOR 0x20000005 +#define ERR_NEGOEX_INVALID_MESSAGE_SIGNATURE 0x20000006 +#define ERR_NEGOEX_INVALID_MESSAGE_TYPE 0x20000007 +#define ERR_NEGOEX_INVALID_MESSAGE_SIZE 0x20000008 +#define ERR_NEGOEX_INVALID_CONVERSATION_ID 0x20000009 +#define ERR_NEGOEX_AUTH_SCHEME_NOT_FOUND 0x20000010 +#define ERR_NEGOEX_MISSING_NEGO_MESSAGE 0x20000011 +#define ERR_NEGOEX_MISSING_AP_REQUEST_MESSAGE 0x20000012 +#define ERR_NEGOEX_NO_AVAILABLE_MECHS 0x20000013 +#define ERR_NEGOEX_NO_VERIFY_KEY 0x20000014 +#define ERR_NEGOEX_UNKNOWN_CHECKSUM_SCHEME 0x20000015 +#define ERR_NEGOEX_INVALID_CHECKSUM 0x20000016 +#define ERR_NEGOEX_UNSUPPORTED_CRITICAL_EXTENSION 0x20000017 +#define ERR_NEGOEX_UNSUPPORTED_VERSION 0x20000018 +#define ERR_NEGOEX_MESSAGE_OUT_OF_SEQUENCE 0x20000019 + +/* + * send_token_flag is used to indicate in later steps what type + * of token, if any should be sent or processed. + * NO_TOKEN_SEND = no token should be sent + * INIT_TOKEN_SEND = initial token will be sent + * CONT_TOKEN_SEND = continuing tokens to be sent + * CHECK_MIC = no token to be sent, but have a MIC to check. + * ERROR_TOKEN_SEND = error token from peer needs to be sent. + */ + +typedef enum {NO_TOKEN_SEND, INIT_TOKEN_SEND, CONT_TOKEN_SEND, + CHECK_MIC, ERROR_TOKEN_SEND} send_token_flag; + +/* + * The Mech OID: + * { iso(1) org(3) dod(6) internet(1) security(5) + * mechanism(5) spnego(2) } + */ + +#define SPNEGO_OID_LENGTH 6 +#define SPNEGO_OID "\053\006\001\005\005\002" + +typedef void *spnego_token_t; + +/* spnego name structure for internal representation. */ +typedef struct { + gss_OID type; + gss_buffer_t buffer; + gss_OID mech_type; + gss_name_t mech_name; +} spnego_name_desc, *spnego_name_t; + +/* Structure for credential */ +typedef struct { + gss_cred_id_t mcred; /* mechglue union of obtainable creds */ + gss_OID_set neg_mechs; /* app-specified list of allowable mechs */ + int no_ask_integ; /* do not request integ from mechs */ +} spnego_gss_cred_id_rec, *spnego_gss_cred_id_t; + +/* Structure for context handle */ +struct spnego_ctx_st { + OM_uint32 magic_num; + gss_buffer_desc DER_mechTypes; + gss_OID_set mech_set; + gss_OID internal_mech; /* alias into mech_set->elements */ + gss_ctx_id_t ctx_handle; + int mic_reqd; + int mic_sent; + int mic_rcvd; + int firstpass; + int mech_complete; + int nego_done; + int initiate; + int opened; + OM_uint32 ctx_flags; + gss_name_t internal_name; + gss_OID actual_mech; + gss_cred_id_t deleg_cred; + int negoex_step; + struct k5buf negoex_transcript; + uint32_t negoex_seqnum; + conversation_id negoex_conv_id; + K5_TAILQ_HEAD(negoex_mech_list, negoex_auth_mech) negoex_mechs; + krb5_context kctx; +}; + +/* + * The magic number must be less than a standard pagesize + * to avoid a possible collision with a real address. + */ +#define SPNEGO_MAGIC_ID 0x00000fed + +/* SPNEGO oid declarations */ +extern const gss_OID_desc * const gss_mech_spnego; +extern const gss_OID_set_desc * const gss_mech_set_spnego; + +#if defined(DEBUG) && defined(HAVE_SYSLOG_H) +#include +#define dsyslog(a) syslog(LOG_DEBUG, a) +#else +#define dsyslog(a) +#define SPNEGO_STATIC +#endif /* DEBUG */ + +/* + * declarations of internal name mechanism functions + */ + +OM_uint32 KRB5_CALLCONV spnego_gss_acquire_cred +( + OM_uint32 *, /* minor_status */ + gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 * /* time_rec */ +); + +OM_uint32 KRB5_CALLCONV spnego_gss_release_cred +( + OM_uint32 *, /* minor_status */ + /* CSTYLED */ + gss_cred_id_t * /* cred_handle */ +); + +OM_uint32 KRB5_CALLCONV spnego_gss_init_sec_context +( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* claimant_cred_handle */ + gss_ctx_id_t *, /* context_handle */ + gss_name_t, /* target_name */ + gss_OID, /* mech_type */ + OM_uint32, /* req_flags */ + OM_uint32, /* time_req */ + gss_channel_bindings_t, /* input_chan_bindings */ + gss_buffer_t, /* input_token */ + gss_OID *, /* actual_mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32 *, /* ret_flags */ + OM_uint32 * /* time_rec */ +); + +#ifndef LEAN_CLIENT +OM_uint32 KRB5_CALLCONV spnego_gss_accept_sec_context +( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + gss_cred_id_t, /* verifier_cred_handle */ + gss_buffer_t, /* input_token_buffer */ + gss_channel_bindings_t, /* input_chan_bindings */ + gss_name_t *, /* src_name */ + gss_OID *, /* mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32 *, /* ret_flags */ + OM_uint32 *, /* time_rec */ + /* CSTYLED */ + gss_cred_id_t * /* delegated_cred_handle */ +); +#endif /* LEAN_CLIENT */ + +OM_uint32 KRB5_CALLCONV spnego_gss_compare_name +( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* name1 */ + const gss_name_t, /* name2 */ + int * /* name_equal */ +); + +OM_uint32 KRB5_CALLCONV spnego_gss_display_name +( + OM_uint32 *, /* minor_status */ + gss_name_t, /* input_name */ + gss_buffer_t, /* output_name_buffer */ + gss_OID * /* output_name_type */ +); + +OM_uint32 KRB5_CALLCONV spnego_gss_display_status +( + OM_uint32 *, /* minor_status */ + OM_uint32, /* status_value */ + int, /* status_type */ + gss_OID, /* mech_type */ + OM_uint32 *, /* message_context */ + gss_buffer_t /* status_string */ +); + +OM_uint32 KRB5_CALLCONV spnego_gss_import_name +( + OM_uint32 *, /* minor_status */ + gss_buffer_t, /* input_name_buffer */ + gss_OID, /* input_name_type */ + /* CSTYLED */ + gss_name_t * /* output_name */ +); + +OM_uint32 KRB5_CALLCONV spnego_gss_release_name +( + OM_uint32 *, /* minor_status */ + /* CSTYLED */ + gss_name_t * /* input_name */ +); + +OM_uint32 KRB5_CALLCONV spnego_gss_duplicate_name +( + OM_uint32 *, /* minor_status */ + /* CSTYLED */ + const gss_name_t, /* input_name */ + gss_name_t * /* output_name */ +); + +OM_uint32 KRB5_CALLCONV spnego_gss_inquire_cred +( + OM_uint32 *, /* minor_status */ + gss_cred_id_t, /* cred_handle */ + gss_name_t *, /* name */ + OM_uint32 *, /* lifetime */ + int *, /* cred_usage */ + gss_OID_set * /* mechanisms */ +); + +OM_uint32 KRB5_CALLCONV spnego_gss_inquire_names_for_mech +( + OM_uint32 *, /* minor_status */ + gss_OID, /* mechanism */ + gss_OID_set * /* name_types */ +); + +OM_uint32 KRB5_CALLCONV spnego_gss_unwrap +( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int *conf_state, + gss_qop_t *qop_state +); + +OM_uint32 KRB5_CALLCONV spnego_gss_wrap +( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_message_buffer, + int *conf_state, + gss_buffer_t output_message_buffer +); + +OM_uint32 KRB5_CALLCONV spnego_gss_process_context_token +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_buffer +); + +OM_uint32 KRB5_CALLCONV spnego_gss_delete_sec_context +( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token +); + +OM_uint32 KRB5_CALLCONV spnego_gss_context_time +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + OM_uint32 *time_rec +); +#ifndef LEAN_CLIENT +OM_uint32 KRB5_CALLCONV spnego_gss_export_sec_context +( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t interprocess_token +); + +OM_uint32 KRB5_CALLCONV spnego_gss_import_sec_context +( + OM_uint32 *minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle +); +#endif /* LEAN_CLIENT */ + +OM_uint32 KRB5_CALLCONV spnego_gss_inquire_context +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_name_t *src_name, + gss_name_t *targ_name, + OM_uint32 *lifetime_rec, + gss_OID *mech_type, + OM_uint32 *ctx_flags, + int *locally_initiated, + int *opened +); + +OM_uint32 KRB5_CALLCONV spnego_gss_wrap_size_limit +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size +); + +OM_uint32 KRB5_CALLCONV spnego_gss_localname +( + OM_uint32 *minor_status, + const gss_name_t pname, + const gss_const_OID mech_type, + gss_buffer_t localname +); + +OM_uint32 KRB5_CALLCONV spnego_gss_get_mic +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token +); + +OM_uint32 KRB5_CALLCONV spnego_gss_verify_mic +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t msg_buffer, + const gss_buffer_t token_buffer, + gss_qop_t *qop_state +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_sec_context_by_oid +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_cred_by_oid +( + OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_set_cred_option +( + OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_object, + const gss_buffer_t value +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_set_sec_context_option +( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value +); + +#ifdef _GSS_STATIC_LINK +int gss_spnegoint_lib_init(void); +void gss_spnegoint_lib_fini(void); +#else +gss_mechanism KRB5_CALLCONV gss_mech_initialize(void); +#endif /* _GSS_STATIC_LINK */ + +OM_uint32 KRB5_CALLCONV spnego_gss_wrap_aead +( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_assoc_buffer, + gss_buffer_t input_payload_buffer, + int *conf_state, + gss_buffer_t output_message_buffer +); + +OM_uint32 KRB5_CALLCONV spnego_gss_unwrap_aead +( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t input_assoc_buffer, + gss_buffer_t output_payload_buffer, + int *conf_state, + gss_qop_t *qop_state +); + +OM_uint32 KRB5_CALLCONV spnego_gss_wrap_iov +( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count +); + +OM_uint32 KRB5_CALLCONV spnego_gss_unwrap_iov +( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count +); + +OM_uint32 KRB5_CALLCONV spnego_gss_wrap_iov_length +( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_complete_auth_token +( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_acquire_cred_impersonate_name( + OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* impersonator_cred_handle */ + const gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + const gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *); /* time_rec */ + +OM_uint32 KRB5_CALLCONV +spnego_gss_acquire_cred_with_password( + OM_uint32 *minor_status, + const gss_name_t desired_name, + const gss_buffer_t password, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec); + +OM_uint32 KRB5_CALLCONV +spnego_gss_display_name_ext +( + OM_uint32 *minor_status, + gss_name_t name, + gss_OID display_as_name_type, + gss_buffer_t display_name +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_name +( + OM_uint32 *minor_status, + gss_name_t name, + int *name_is_MN, + gss_OID *MN_mech, + gss_buffer_set_t *attrs +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_get_name_attribute +( + OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_set_name_attribute +( + OM_uint32 *minor_status, + gss_name_t name, + int complete, + gss_buffer_t attr, + gss_buffer_t value +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_delete_name_attribute +( + OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t attr +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_export_name_composite +( + OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t exp_composite_name +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_map_name_to_any +( + OM_uint32 *minor_status, + gss_name_t name, + int authenticated, + gss_buffer_t type_id, + gss_any_t *output +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_release_any_name_mapping +( + OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t type_id, + gss_any_t *input +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_pseudo_random +( + OM_uint32 *minor_status, + gss_ctx_id_t context, + int prf_key, + const gss_buffer_t prf_in, + ssize_t desired_output_len, + gss_buffer_t prf_out +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_set_neg_mechs +( + OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + const gss_OID_set mech_list +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_mech_for_saslname +( + OM_uint32 *minor_status, + const gss_buffer_t sasl_mech_name, + gss_OID *mech_type +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_saslname_for_mech +( + OM_uint32 *minor_status, + const gss_OID desired_mech, + gss_buffer_t sasl_mech_name, + gss_buffer_t mech_name, + gss_buffer_t mech_description +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_attrs_for_mech +( + OM_uint32 *minor_status, + gss_const_OID mech, + gss_OID_set *mech_attrs, + gss_OID_set *known_mech_attrs +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_acquire_cred_from +( + OM_uint32 *minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_export_cred( + OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + gss_buffer_t token +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_import_cred( + OM_uint32 *minor_status, + gss_buffer_t token, + gss_cred_id_t *cred_handle +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_get_mic_iov( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t qop_req, + gss_iov_buffer_desc *iov, + int iov_count +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_verify_mic_iov( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count +); + +OM_uint32 KRB5_CALLCONV +spnego_gss_get_mic_iov_length( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_qop_t qop_req, + gss_iov_buffer_desc *iov, + int iov_count +); + +#ifdef __cplusplus +} +#endif + +#endif /* _GSSAPIP_SPNEGO_H_ */ diff --git a/krb5-1.21.3/src/lib/gssapi/spnego/mech_spnego.exports b/krb5-1.21.3/src/lib/gssapi/spnego/mech_spnego.exports new file mode 100644 index 00000000..9d570e5c --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/spnego/mech_spnego.exports @@ -0,0 +1 @@ +gss_mech_initialize diff --git a/krb5-1.21.3/src/lib/gssapi/spnego/negoex_ctx.c b/krb5-1.21.3/src/lib/gssapi/spnego/negoex_ctx.c new file mode 100644 index 00000000..8848ee4d --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/spnego/negoex_ctx.c @@ -0,0 +1,788 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2011-2018 PADL Software Pty Ltd. + * 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. + */ + +#include "k5-platform.h" +#include "gssapiP_spnego.h" +#include + +/* + * The initial context token emitted by the initiator is a INITIATOR_NEGO + * message followed by zero or more INITIATOR_META_DATA tokens, and zero + * or one AP_REQUEST tokens. + * + * Upon receiving this, the acceptor computes the list of mutually supported + * authentication mechanisms and performs the metadata exchange. The output + * token is ACCEPTOR_NEGO followed by zero or more ACCEPTOR_META_DATA tokens, + * and zero or one CHALLENGE tokens. + * + * Once the metadata exchange is complete and a mechanism is selected, the + * selected mechanism's context token exchange continues with AP_REQUEST and + * CHALLENGE messages. + * + * Once the context token exchange is complete, VERIFY messages are sent to + * authenticate the entire exchange. + */ + +static void +zero_and_release_buffer_set(gss_buffer_set_t *pbuffers) +{ + OM_uint32 tmpmin; + gss_buffer_set_t buffers = *pbuffers; + uint32_t i; + + if (buffers != GSS_C_NO_BUFFER_SET) { + for (i = 0; i < buffers->count; i++) + zap(buffers->elements[i].value, buffers->elements[i].length); + + gss_release_buffer_set(&tmpmin, &buffers); + } + + *pbuffers = GSS_C_NO_BUFFER_SET; +} + +static OM_uint32 +buffer_set_to_key(OM_uint32 *minor, gss_buffer_set_t buffers, + krb5_keyblock *key) +{ + krb5_error_code ret; + + /* Returned keys must be in two buffers, with the key contents in the first + * and the enctype as a 32-bit little-endian integer in the second. */ + if (buffers->count != 2 || buffers->elements[1].length != 4) { + *minor = ERR_NEGOEX_NO_VERIFY_KEY; + return GSS_S_FAILURE; + } + + krb5_free_keyblock_contents(NULL, key); + + key->contents = k5memdup(buffers->elements[0].value, + buffers->elements[0].length, &ret); + if (key->contents == NULL) { + *minor = ret; + return GSS_S_FAILURE; + } + key->length = buffers->elements[0].length; + key->enctype = load_32_le(buffers->elements[1].value); + + return GSS_S_COMPLETE; +} + +static OM_uint32 +get_session_keys(OM_uint32 *minor, struct negoex_auth_mech *mech) +{ + OM_uint32 major, tmpmin; + gss_buffer_set_t buffers = GSS_C_NO_BUFFER_SET; + + major = gss_inquire_sec_context_by_oid(&tmpmin, mech->mech_context, + GSS_C_INQ_NEGOEX_KEY, &buffers); + if (major == GSS_S_COMPLETE) { + major = buffer_set_to_key(minor, buffers, &mech->key); + zero_and_release_buffer_set(&buffers); + if (major != GSS_S_COMPLETE) + return major; + } + + major = gss_inquire_sec_context_by_oid(&tmpmin, mech->mech_context, + GSS_C_INQ_NEGOEX_VERIFY_KEY, + &buffers); + if (major == GSS_S_COMPLETE) { + major = buffer_set_to_key(minor, buffers, &mech->verify_key); + zero_and_release_buffer_set(&buffers); + if (major != GSS_S_COMPLETE) + return major; + } + + return GSS_S_COMPLETE; +} + +static OM_uint32 +emit_initiator_nego(OM_uint32 *minor, spnego_gss_ctx_id_t ctx) +{ + OM_uint32 major; + uint8_t random[32]; + + major = negoex_random(minor, ctx, random, 32); + if (major != GSS_S_COMPLETE) + return major; + + negoex_add_nego_message(ctx, INITIATOR_NEGO, random); + return GSS_S_COMPLETE; +} + +static OM_uint32 +process_initiator_nego(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + struct negoex_message *messages, size_t nmessages) +{ + struct nego_message *msg; + + assert(!ctx->initiate && ctx->negoex_step == 1); + + msg = negoex_locate_nego_message(messages, nmessages, INITIATOR_NEGO); + if (msg == NULL) { + *minor = ERR_NEGOEX_MISSING_NEGO_MESSAGE; + return GSS_S_DEFECTIVE_TOKEN; + } + + negoex_restrict_auth_schemes(ctx, msg->schemes, msg->nschemes); + return GSS_S_COMPLETE; +} + +static OM_uint32 +emit_acceptor_nego(OM_uint32 *minor, spnego_gss_ctx_id_t ctx) +{ + OM_uint32 major; + uint8_t random[32]; + + major = negoex_random(minor, ctx, random, 32); + if (major != GSS_S_COMPLETE) + return major; + + negoex_add_nego_message(ctx, ACCEPTOR_NEGO, random); + return GSS_S_COMPLETE; +} + +static OM_uint32 +process_acceptor_nego(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + struct negoex_message *messages, size_t nmessages) +{ + struct nego_message *msg; + + msg = negoex_locate_nego_message(messages, nmessages, ACCEPTOR_NEGO); + if (msg == NULL) { + *minor = ERR_NEGOEX_MISSING_NEGO_MESSAGE; + return GSS_S_DEFECTIVE_TOKEN; + } + + /* Reorder and prune our mech list to match the acceptor's list (or a + * subset of it). */ + negoex_common_auth_schemes(ctx, msg->schemes, msg->nschemes); + + return GSS_S_COMPLETE; +} + +static void +query_meta_data(spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + gss_name_t target, OM_uint32 req_flags) +{ + OM_uint32 major, minor; + struct negoex_auth_mech *p, *next; + + K5_TAILQ_FOREACH_SAFE(p, &ctx->negoex_mechs, links, next) { + major = gssspi_query_meta_data(&minor, p->oid, cred, &p->mech_context, + target, req_flags, &p->metadata); + /* GSS_Query_meta_data failure removes mechanism from list. */ + if (major != GSS_S_COMPLETE) + negoex_delete_auth_mech(ctx, p); + } +} + +static void +exchange_meta_data(spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + gss_name_t target, OM_uint32 req_flags, + struct negoex_message *messages, size_t nmessages) +{ + OM_uint32 major, minor; + struct negoex_auth_mech *mech; + enum message_type type; + struct exchange_message *msg; + uint32_t i; + + type = ctx->initiate ? ACCEPTOR_META_DATA : INITIATOR_META_DATA; + + for (i = 0; i < nmessages; i++) { + if (messages[i].type != type) + continue; + msg = &messages[i].u.e; + + mech = negoex_locate_auth_scheme(ctx, msg->scheme); + if (mech == NULL) + continue; + + major = gssspi_exchange_meta_data(&minor, mech->oid, cred, + &mech->mech_context, target, + req_flags, &msg->token); + /* GSS_Exchange_meta_data failure removes mechanism from list. */ + if (major != GSS_S_COMPLETE) + negoex_delete_auth_mech(ctx, mech); + } +} + +/* + * In the initiator, if we are processing the acceptor's first reply, discard + * the optimistic context if the acceptor ignored the optimistic token. If the + * acceptor continued the optimistic mech, discard all other mechs. + */ +static void +check_optimistic_result(spnego_gss_ctx_id_t ctx, + struct negoex_message *messages, size_t nmessages) +{ + struct negoex_auth_mech *mech; + OM_uint32 tmpmin; + + assert(ctx->initiate && ctx->negoex_step == 2); + + /* Do nothing if we didn't make an optimistic context. */ + mech = K5_TAILQ_FIRST(&ctx->negoex_mechs); + if (mech == NULL || mech->mech_context == GSS_C_NO_CONTEXT) + return; + + /* If the acceptor used the optimistic token, it will send an acceptor + * token or a checksum (or both) in its first reply. */ + if (negoex_locate_exchange_message(messages, nmessages, + CHALLENGE) != NULL || + negoex_locate_verify_message(messages, nmessages) != NULL) { + /* The acceptor continued the optimistic mech, and metadata exchange + * didn't remove it. Commit to this mechanism. */ + negoex_select_auth_mech(ctx, mech); + } else { + /* The acceptor ignored the optimistic token. Restart the mech. */ + (void)gss_delete_sec_context(&tmpmin, &mech->mech_context, NULL); + krb5_free_keyblock_contents(NULL, &mech->key); + krb5_free_keyblock_contents(NULL, &mech->verify_key); + mech->complete = mech->sent_checksum = FALSE; + } +} + +/* Perform an initiator step of the underlying mechanism exchange. */ +static OM_uint32 +mech_init(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + gss_name_t target, OM_uint32 req_flags, OM_uint32 time_req, + struct negoex_message *messages, size_t nmessages, + gss_channel_bindings_t bindings, gss_buffer_t output_token, + OM_uint32 *time_rec) +{ + OM_uint32 major, first_major = 0, first_minor = 0; + struct negoex_auth_mech *mech = NULL; + gss_buffer_t input_token = GSS_C_NO_BUFFER; + struct exchange_message *msg; + int first_mech; + + output_token->value = NULL; + output_token->length = 0; + + /* Allow disabling of optimistic token for testing. */ + if (ctx->negoex_step == 1 && + secure_getenv("NEGOEX_NO_OPTIMISTIC_TOKEN") != NULL) + return GSS_S_COMPLETE; + + if (K5_TAILQ_EMPTY(&ctx->negoex_mechs)) { + *minor = ERR_NEGOEX_NO_AVAILABLE_MECHS; + return GSS_S_FAILURE; + } + + /* + * Get the input token. The challenge could be for the optimistic mech, + * which we might have discarded in metadata exchange, so ignore the + * challenge if it doesn't match the first auth mech. + */ + mech = K5_TAILQ_FIRST(&ctx->negoex_mechs); + msg = negoex_locate_exchange_message(messages, nmessages, CHALLENGE); + if (msg != NULL && GUID_EQ(msg->scheme, mech->scheme)) + input_token = &msg->token; + + if (mech->complete) + return GSS_S_COMPLETE; + + first_mech = TRUE; + + while (!K5_TAILQ_EMPTY(&ctx->negoex_mechs)) { + mech = K5_TAILQ_FIRST(&ctx->negoex_mechs); + + major = gss_init_sec_context(minor, cred, &mech->mech_context, target, + mech->oid, req_flags, time_req, bindings, + input_token, &ctx->actual_mech, + output_token, &ctx->ctx_flags, time_rec); + + if (major == GSS_S_COMPLETE) + mech->complete = 1; + + if (!GSS_ERROR(major)) + return get_session_keys(minor, mech); + + /* Remember the error we got from the first mech. */ + if (first_mech) { + first_major = major; + first_minor = *minor; + } + + /* If we still have multiple mechs to try, move on to the next one. */ + negoex_delete_auth_mech(ctx, mech); + first_mech = FALSE; + input_token = GSS_C_NO_BUFFER; + } + + if (K5_TAILQ_EMPTY(&ctx->negoex_mechs)) { + major = first_major; + *minor = first_minor; + } + + return major; +} + +/* Perform an acceptor step of the underlying mechanism exchange. */ +static OM_uint32 +mech_accept(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + gss_cred_id_t cred, struct negoex_message *messages, + size_t nmessages, gss_channel_bindings_t bindings, + gss_buffer_t output_token, OM_uint32 *time_rec) +{ + OM_uint32 major, tmpmin; + struct negoex_auth_mech *mech; + struct exchange_message *msg; + + assert(!ctx->initiate && !K5_TAILQ_EMPTY(&ctx->negoex_mechs)); + + msg = negoex_locate_exchange_message(messages, nmessages, AP_REQUEST); + if (msg == NULL) { + /* No input token is okay on the first request or if the mech is + * complete. */ + if (ctx->negoex_step == 1 || + K5_TAILQ_FIRST(&ctx->negoex_mechs)->complete) + return GSS_S_COMPLETE; + *minor = ERR_NEGOEX_MISSING_AP_REQUEST_MESSAGE; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (ctx->negoex_step == 1) { + /* Ignore the optimistic token if it isn't for our most preferred + * mech. */ + mech = K5_TAILQ_FIRST(&ctx->negoex_mechs); + if (!GUID_EQ(msg->scheme, mech->scheme)) + return GSS_S_COMPLETE; + } else { + /* The initiator has selected a mech; discard other entries. */ + mech = negoex_locate_auth_scheme(ctx, msg->scheme); + if (mech == NULL) { + *minor = ERR_NEGOEX_NO_AVAILABLE_MECHS; + return GSS_S_FAILURE; + } + negoex_select_auth_mech(ctx, mech); + } + + if (mech->complete) + return GSS_S_COMPLETE; + + if (ctx->internal_name != GSS_C_NO_NAME) + gss_release_name(&tmpmin, &ctx->internal_name); + if (ctx->deleg_cred != GSS_C_NO_CREDENTIAL) + gss_release_cred(&tmpmin, &ctx->deleg_cred); + + major = gss_accept_sec_context(minor, &mech->mech_context, cred, + &msg->token, bindings, &ctx->internal_name, + &ctx->actual_mech, output_token, + &ctx->ctx_flags, time_rec, + &ctx->deleg_cred); + + if (major == GSS_S_COMPLETE) + mech->complete = 1; + + if (!GSS_ERROR(major)) { + major = get_session_keys(minor, mech); + } else if (ctx->negoex_step == 1) { + /* This was an optimistic token; pretend this never happened. */ + major = GSS_S_COMPLETE; + *minor = 0; + gss_release_buffer(&tmpmin, output_token); + gss_delete_sec_context(&tmpmin, &mech->mech_context, GSS_C_NO_BUFFER); + } + + return major; +} + +static krb5_keyusage +verify_keyusage(spnego_gss_ctx_id_t ctx, int make_checksum) +{ + /* Of course, these are the wrong way around in the spec. */ + return (ctx->initiate ^ !make_checksum) ? + NEGOEX_KEYUSAGE_ACCEPTOR_CHECKSUM : NEGOEX_KEYUSAGE_INITIATOR_CHECKSUM; +} + +static OM_uint32 +verify_checksum(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + struct negoex_message *messages, size_t nmessages, + gss_buffer_t input_token, int *send_alert_out) +{ + krb5_error_code ret; + struct negoex_auth_mech *mech = K5_TAILQ_FIRST(&ctx->negoex_mechs); + struct verify_message *msg; + krb5_crypto_iov iov[3]; + krb5_keyusage usage = verify_keyusage(ctx, FALSE); + krb5_boolean valid; + + *send_alert_out = FALSE; + assert(mech != NULL); + + /* The other party may not be ready to send a verify token yet, or (in the + * first initiator step) may send one for a mechanism we don't support. */ + msg = negoex_locate_verify_message(messages, nmessages); + if (msg == NULL || !GUID_EQ(msg->scheme, mech->scheme)) + return GSS_S_COMPLETE; + + /* A recoverable error may cause us to be unable to verify a token from the + * other party. In this case we should send an alert. */ + if (mech->verify_key.enctype == ENCTYPE_NULL) { + *send_alert_out = TRUE; + return GSS_S_COMPLETE; + } + + /* Verify the checksum over the existing transcript and the portion of the + * input token leading up to the verify message. */ + assert(input_token != NULL); + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = make_data(ctx->negoex_transcript.data, + ctx->negoex_transcript.len); + iov[1].flags = KRB5_CRYPTO_TYPE_DATA; + iov[1].data = make_data(input_token->value, msg->offset_in_token); + iov[2].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + iov[2].data = make_data((uint8_t *)msg->cksum, msg->cksum_len); + + ret = krb5_c_verify_checksum_iov(ctx->kctx, msg->cksum_type, + &mech->verify_key, usage, iov, 3, &valid); + if (ret) { + *minor = ret; + return GSS_S_FAILURE; + } + if (!valid || !krb5_c_is_keyed_cksum(msg->cksum_type)) { + *minor = ERR_NEGOEX_INVALID_CHECKSUM; + return GSS_S_BAD_SIG; + } + + mech->verified_checksum = TRUE; + return GSS_S_COMPLETE; +} + +static OM_uint32 +make_checksum(OM_uint32 *minor, spnego_gss_ctx_id_t ctx) +{ + krb5_error_code ret; + krb5_data d; + krb5_keyusage usage = verify_keyusage(ctx, TRUE); + krb5_checksum cksum; + struct negoex_auth_mech *mech = K5_TAILQ_FIRST(&ctx->negoex_mechs); + + assert(mech != NULL); + + if (mech->key.enctype == ENCTYPE_NULL) { + if (mech->complete) { + *minor = ERR_NEGOEX_NO_VERIFY_KEY; + return GSS_S_UNAVAILABLE; + } else { + return GSS_S_COMPLETE; + } + } + + d = make_data(ctx->negoex_transcript.data, ctx->negoex_transcript.len); + ret = krb5_c_make_checksum(ctx->kctx, 0, &mech->key, usage, &d, &cksum); + if (ret) { + *minor = ret; + return GSS_S_FAILURE; + } + + negoex_add_verify_message(ctx, mech->scheme, cksum.checksum_type, + cksum.contents, cksum.length); + + mech->sent_checksum = TRUE; + krb5_free_checksum_contents(ctx->kctx, &cksum); + return GSS_S_COMPLETE; +} + +/* If the other side sent a VERIFY_NO_KEY pulse alert, clear the checksum state + * on the mechanism so that we send another VERIFY message. */ +static void +process_alerts(spnego_gss_ctx_id_t ctx, + struct negoex_message *messages, uint32_t nmessages) +{ + struct alert_message *msg; + struct negoex_auth_mech *mech; + + msg = negoex_locate_alert_message(messages, nmessages); + if (msg != NULL && msg->verify_no_key) { + mech = negoex_locate_auth_scheme(ctx, msg->scheme); + if (mech != NULL) { + mech->sent_checksum = FALSE; + krb5_free_keyblock_contents(NULL, &mech->key); + krb5_free_keyblock_contents(NULL, &mech->verify_key); + } + } +} + +static OM_uint32 +make_output_token(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + gss_buffer_t mech_output_token, int send_alert, + gss_buffer_t output_token) +{ + OM_uint32 major; + struct negoex_auth_mech *mech; + enum message_type type; + size_t old_transcript_len = ctx->negoex_transcript.len; + + output_token->length = 0; + output_token->value = NULL; + + /* If the mech is complete and we previously sent a checksum, we just + * processed the last leg and don't need to send another token. */ + if (mech_output_token->length == 0 && + K5_TAILQ_FIRST(&ctx->negoex_mechs)->sent_checksum) + return GSS_S_COMPLETE; + + if (ctx->negoex_step == 1) { + if (ctx->initiate) + major = emit_initiator_nego(minor, ctx); + else + major = emit_acceptor_nego(minor, ctx); + if (major != GSS_S_COMPLETE) + return major; + + type = ctx->initiate ? INITIATOR_META_DATA : ACCEPTOR_META_DATA; + K5_TAILQ_FOREACH(mech, &ctx->negoex_mechs, links) { + if (mech->metadata.length > 0) { + negoex_add_exchange_message(ctx, type, mech->scheme, + &mech->metadata); + } + } + } + + mech = K5_TAILQ_FIRST(&ctx->negoex_mechs); + + if (mech_output_token->length > 0) { + type = ctx->initiate ? AP_REQUEST : CHALLENGE; + negoex_add_exchange_message(ctx, type, mech->scheme, + mech_output_token); + } + + if (send_alert) + negoex_add_verify_no_key_alert(ctx, mech->scheme); + + /* Try to add a VERIFY message if we haven't already done so. */ + if (!mech->sent_checksum) { + major = make_checksum(minor, ctx); + if (major != GSS_S_COMPLETE) + return major; + } + + if (ctx->negoex_transcript.data == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + /* Copy what we added to the transcript into the output token. */ + output_token->length = ctx->negoex_transcript.len - old_transcript_len; + output_token->value = gssalloc_malloc(output_token->length); + if (output_token->value == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(output_token->value, + (uint8_t *)ctx->negoex_transcript.data + old_transcript_len, + output_token->length); + + return GSS_S_COMPLETE; +} + +OM_uint32 +negoex_init(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + gss_name_t target_name, OM_uint32 req_flags, OM_uint32 time_req, + gss_buffer_t input_token, gss_channel_bindings_t bindings, + gss_buffer_t output_token, OM_uint32 *time_rec) +{ + OM_uint32 major, tmpmin; + gss_buffer_desc mech_output_token = GSS_C_EMPTY_BUFFER; + struct negoex_message *messages = NULL; + struct negoex_auth_mech *mech; + size_t nmessages = 0; + int send_alert = FALSE; + + if (ctx->negoex_step == 0 && input_token != GSS_C_NO_BUFFER && + input_token->length != 0) + return GSS_S_DEFECTIVE_TOKEN; + + major = negoex_prep_context_for_negoex(minor, ctx); + if (major != GSS_S_COMPLETE) + goto cleanup; + + ctx->negoex_step++; + + if (input_token != GSS_C_NO_BUFFER && input_token->length > 0) { + major = negoex_parse_token(minor, ctx, input_token, &messages, + &nmessages); + if (major != GSS_S_COMPLETE) + goto cleanup; + } + + process_alerts(ctx, messages, nmessages); + + if (ctx->negoex_step == 1) { + /* Choose a random conversation ID. */ + major = negoex_random(minor, ctx, ctx->negoex_conv_id, GUID_LENGTH); + if (major != GSS_S_COMPLETE) + goto cleanup; + + /* Query each mech for its metadata (this may prune the mech list). */ + query_meta_data(ctx, cred, target_name, req_flags); + } else if (ctx->negoex_step == 2) { + /* See if the mech processed the optimistic token. */ + check_optimistic_result(ctx, messages, nmessages); + + /* Pass the acceptor metadata to each mech to prune the list. */ + exchange_meta_data(ctx, cred, target_name, req_flags, + messages, nmessages); + + /* Process the ACCEPTOR_NEGO message. */ + major = process_acceptor_nego(minor, ctx, messages, nmessages); + if (major != GSS_S_COMPLETE) + goto cleanup; + } + + /* Process the input token and/or produce an output token. This may prune + * the mech list, but on success there will be at least one mech entry. */ + major = mech_init(minor, ctx, cred, target_name, req_flags, time_req, + messages, nmessages, bindings, &mech_output_token, + time_rec); + if (major != GSS_S_COMPLETE) + goto cleanup; + assert(!K5_TAILQ_EMPTY(&ctx->negoex_mechs)); + + /* At this point in step 2 we have performed the metadata exchange and + * chosen a mech we can use, so discard any fallback mech entries. */ + if (ctx->negoex_step == 2) + negoex_select_auth_mech(ctx, K5_TAILQ_FIRST(&ctx->negoex_mechs)); + + major = verify_checksum(minor, ctx, messages, nmessages, input_token, + &send_alert); + if (major != GSS_S_COMPLETE) + goto cleanup; + + if (input_token != GSS_C_NO_BUFFER) { + k5_buf_add_len(&ctx->negoex_transcript, input_token->value, + input_token->length); + } + + major = make_output_token(minor, ctx, &mech_output_token, send_alert, + output_token); + if (major != GSS_S_COMPLETE) + goto cleanup; + + mech = K5_TAILQ_FIRST(&ctx->negoex_mechs); + major = (mech->complete && mech->verified_checksum) ? GSS_S_COMPLETE : + GSS_S_CONTINUE_NEEDED; + +cleanup: + free(messages); + gss_release_buffer(&tmpmin, &mech_output_token); + negoex_prep_context_for_spnego(ctx); + return major; +} + +OM_uint32 +negoex_accept(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, gss_cred_id_t cred, + gss_buffer_t input_token, gss_channel_bindings_t bindings, + gss_buffer_t output_token, OM_uint32 *time_rec) +{ + OM_uint32 major, tmpmin; + gss_buffer_desc mech_output_token = GSS_C_EMPTY_BUFFER; + struct negoex_message *messages = NULL; + struct negoex_auth_mech *mech; + size_t nmessages; + int send_alert = FALSE; + + if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) { + major = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + + major = negoex_prep_context_for_negoex(minor, ctx); + if (major != GSS_S_COMPLETE) + goto cleanup; + + ctx->negoex_step++; + + major = negoex_parse_token(minor, ctx, input_token, &messages, &nmessages); + if (major != GSS_S_COMPLETE) + goto cleanup; + + process_alerts(ctx, messages, nmessages); + + if (ctx->negoex_step == 1) { + /* Read the INITIATOR_NEGO message to prune the candidate mech list. */ + major = process_initiator_nego(minor, ctx, messages, nmessages); + if (major != GSS_S_COMPLETE) + goto cleanup; + + /* + * Pass the initiator metadata to each mech to prune the list, and + * query each mech for its acceptor metadata (which may also prune the + * list). + */ + exchange_meta_data(ctx, cred, GSS_C_NO_NAME, 0, messages, nmessages); + query_meta_data(ctx, cred, GSS_C_NO_NAME, 0); + + if (K5_TAILQ_EMPTY(&ctx->negoex_mechs)) { + *minor = ERR_NEGOEX_NO_AVAILABLE_MECHS; + major = GSS_S_FAILURE; + goto cleanup; + } + } + + /* + * Process the input token and possibly produce an output token. This may + * prune the list to a single mech. Continue on error if an output token + * is generated, so that we send the token to the initiator. + */ + major = mech_accept(minor, ctx, cred, messages, nmessages, bindings, + &mech_output_token, time_rec); + if (major != GSS_S_COMPLETE && mech_output_token.length == 0) + goto cleanup; + + if (major == GSS_S_COMPLETE) { + major = verify_checksum(minor, ctx, messages, nmessages, input_token, + &send_alert); + if (major != GSS_S_COMPLETE) + goto cleanup; + } + + k5_buf_add_len(&ctx->negoex_transcript, + input_token->value, input_token->length); + + major = make_output_token(minor, ctx, &mech_output_token, send_alert, + output_token); + if (major != GSS_S_COMPLETE) + goto cleanup; + + mech = K5_TAILQ_FIRST(&ctx->negoex_mechs); + major = (mech->complete && mech->verified_checksum) ? GSS_S_COMPLETE : + GSS_S_CONTINUE_NEEDED; + +cleanup: + free(messages); + gss_release_buffer(&tmpmin, &mech_output_token); + negoex_prep_context_for_spnego(ctx); + return major; +} diff --git a/krb5-1.21.3/src/lib/gssapi/spnego/negoex_trace.c b/krb5-1.21.3/src/lib/gssapi/spnego/negoex_trace.c new file mode 100644 index 00000000..04ed992b --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/spnego/negoex_trace.c @@ -0,0 +1,121 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2011-2018 PADL Software Pty Ltd. + * 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. + */ + +#include "gssapiP_spnego.h" + +static int +guid_to_string(const uint8_t guid[16], char *buffer, size_t bufsiz) +{ + uint32_t data1; + uint16_t data2, data3; + + data1 = load_32_le(guid); + data2 = load_16_le(guid + 4); + data3 = load_16_le(guid + 6); + + return snprintf(buffer, bufsiz, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + data1, data2, data3, guid[8], guid[9], guid[10], guid[11], + guid[12], guid[13], guid[14], guid[15]); +} + +static void +trace_auth_scheme(spnego_gss_ctx_id_t ctx, const char *prefix, int ind, + const auth_scheme scheme) +{ + char trace_msg[128]; + char szAuthScheme[37]; + + guid_to_string(scheme, szAuthScheme, sizeof(szAuthScheme)); + + snprintf(trace_msg, sizeof(trace_msg), + "NEGOEXTS: %20s[%02u] -- AuthScheme %s", + prefix, ind, szAuthScheme); + TRACE_NEGOEX_AUTH_SCHEMES(ctx->kctx, trace_msg); +} + +void +negoex_trace_auth_schemes(spnego_gss_ctx_id_t ctx, const char *prefix, + const uint8_t *schemes, uint16_t nschemes) +{ + uint16_t i; + + for (i = 0; i < nschemes; i++) + trace_auth_scheme(ctx, prefix, i, schemes + i * GUID_LENGTH); +} + +void +negoex_trace_ctx_auth_schemes(spnego_gss_ctx_id_t ctx, const char *prefix) +{ + negoex_auth_mech_t mech; + int ind = 0; + + K5_TAILQ_FOREACH(mech, &ctx->negoex_mechs, links) + trace_auth_scheme(ctx, prefix, ind++, mech->scheme); +} + +void +negoex_trace_message(spnego_gss_ctx_id_t ctx, int direction, + enum message_type type, const conversation_id conv_id, + unsigned int seqnum, unsigned int header_len, + unsigned int msg_len) +{ + char trace_msg[128]; + char conv_str[37]; + char *typestr; + + if (type == INITIATOR_NEGO) + typestr = "INITIATOR_NEGO"; + else if (type == ACCEPTOR_NEGO) + typestr = "ACCEPTOR_NEGO"; + else if (type == INITIATOR_META_DATA) + typestr = "INITIATOR_META_DATA"; + else if (type == ACCEPTOR_META_DATA) + typestr = "ACCEPTOR_META_DATA"; + else if (type == CHALLENGE) + typestr = "CHALLENGE"; + else if (type == AP_REQUEST) + typestr = "AP_REQUEST"; + else if (type == VERIFY) + typestr = "VERIFY"; + else if (type == ALERT) + typestr = "ALERT"; + else + typestr = "UNKNOWN"; + + guid_to_string(conv_id, conv_str, sizeof(conv_str)); + snprintf(trace_msg, sizeof(trace_msg), + "NEGOEXTS%c %20s[%02u] -- ConvId %s HdrLength %u MsgLength %u", + direction ? '<' : '>', typestr, seqnum, conv_str, header_len, + msg_len); + + TRACE_NEGOEX_MESSAGE(ctx->kctx, trace_msg); +} diff --git a/krb5-1.21.3/src/lib/gssapi/spnego/negoex_util.c b/krb5-1.21.3/src/lib/gssapi/spnego/negoex_util.c new file mode 100644 index 00000000..edc5462e --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/spnego/negoex_util.c @@ -0,0 +1,813 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2011-2018 PADL Software Pty Ltd. + * 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. + */ + +#include "gssapiP_spnego.h" +#include +#include "k5-input.h" + +static void +release_auth_mech(struct negoex_auth_mech *mech); + +OM_uint32 +negoex_random(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + uint8_t *data, size_t length) +{ + krb5_data d = make_data(data, length); + + *minor = krb5_c_random_make_octets(ctx->kctx, &d); + return *minor ? GSS_S_FAILURE : GSS_S_COMPLETE; +} + +/* + * SPNEGO functions expect to find the active mech context in ctx->ctx_handle, + * but the metadata exchange APIs force us to have one mech context per mech + * entry. To address this mismatch, move the active mech context (if we have + * one) to ctx->ctx_handle at the end of NegoEx processing. + */ +void +negoex_prep_context_for_spnego(spnego_gss_ctx_id_t ctx) +{ + struct negoex_auth_mech *mech; + + mech = K5_TAILQ_FIRST(&ctx->negoex_mechs); + if (mech == NULL || mech->mech_context == GSS_C_NO_CONTEXT) + return; + + assert(ctx->ctx_handle == GSS_C_NO_CONTEXT); + ctx->ctx_handle = mech->mech_context; + mech->mech_context = GSS_C_NO_CONTEXT; +} + +OM_uint32 +negoex_prep_context_for_negoex(OM_uint32 *minor, spnego_gss_ctx_id_t ctx) +{ + krb5_error_code ret; + struct negoex_auth_mech *mech; + + if (ctx->kctx != NULL) { + /* The context is already initialized for NegoEx. Undo what + * negoex_prep_for_spnego() did, if applicable. */ + if (ctx->ctx_handle != GSS_C_NO_CONTEXT) { + mech = K5_TAILQ_FIRST(&ctx->negoex_mechs); + assert(mech != NULL && mech->mech_context == GSS_C_NO_CONTEXT); + mech->mech_context = ctx->ctx_handle; + ctx->ctx_handle = GSS_C_NO_CONTEXT; + } + return GSS_S_COMPLETE; + } + + /* Initialize the NegoEX context fields. (negoex_mechs is already set up + * by SPNEGO.) */ + ret = krb5_init_context(&ctx->kctx); + if (ret) { + *minor = ret; + return GSS_S_FAILURE; + } + + k5_buf_init_dynamic(&ctx->negoex_transcript); + + return GSS_S_COMPLETE; +} + +static void +release_all_mechs(spnego_gss_ctx_id_t ctx) +{ + struct negoex_auth_mech *mech, *next; + + K5_TAILQ_FOREACH_SAFE(mech, &ctx->negoex_mechs, links, next) + release_auth_mech(mech); + K5_TAILQ_INIT(&ctx->negoex_mechs); +} + +void +negoex_release_context(spnego_gss_ctx_id_t ctx) +{ + k5_buf_free(&ctx->negoex_transcript); + release_all_mechs(ctx); + krb5_free_context(ctx->kctx); + ctx->kctx = NULL; +} + +static const char * +typestr(enum message_type type) +{ + if (type == INITIATOR_NEGO) + return "INITIATOR_NEGO"; + else if (type == ACCEPTOR_NEGO) + return "ACCEPTOR_NEGO"; + else if (type == INITIATOR_META_DATA) + return "INITIATOR_META_DATA"; + else if (type == ACCEPTOR_META_DATA) + return "ACCEPTOR_META_DATA"; + else if (type == CHALLENGE) + return "CHALLENGE"; + else if (type == AP_REQUEST) + return "AP_REQUEST"; + else if (type == VERIFY) + return "VERIFY"; + else if (type == ALERT) + return "ALERT"; + else + return "UNKNOWN"; +} + +static void +add_guid(struct k5buf *buf, const uint8_t guid[GUID_LENGTH]) +{ + uint32_t data1 = load_32_le(guid); + uint16_t data2 = load_16_le(guid + 4), data3 = load_16_le(guid + 6); + + k5_buf_add_fmt(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + data1, data2, data3, guid[8], guid[9], guid[10], guid[11], + guid[12], guid[13], guid[14], guid[15]); +} + +static char * +guid_to_string(const uint8_t guid[GUID_LENGTH]) +{ + struct k5buf buf; + + k5_buf_init_dynamic(&buf); + add_guid(&buf, guid); + return k5_buf_cstring(&buf); +} + +/* Check that the described vector lies within the message, and return a + * pointer to its first element. */ +static inline const uint8_t * +vector_base(size_t offset, size_t count, size_t width, + const uint8_t *msg_base, size_t msg_len) +{ + if (offset > msg_len || count > (msg_len - offset) / width) + return NULL; + return msg_base + offset; +} + +/* Trace a received message. Call after the context sequence number is + * incremented. */ +static void +trace_received_message(spnego_gss_ctx_id_t ctx, + const struct negoex_message *msg) +{ + struct k5buf buf; + uint16_t i; + char *info = NULL; + + if (msg->type == INITIATOR_NEGO || msg->type == ACCEPTOR_NEGO) { + k5_buf_init_dynamic(&buf); + for (i = 0; i < msg->u.n.nschemes; i++) { + add_guid(&buf, msg->u.n.schemes + i * GUID_LENGTH); + if (i + 1 < msg->u.n.nschemes) + k5_buf_add(&buf, " "); + } + info = k5_buf_cstring(&buf); + } else if (msg->type == INITIATOR_META_DATA || + msg->type == ACCEPTOR_META_DATA || + msg->type == CHALLENGE || msg->type == AP_REQUEST) { + info = guid_to_string(msg->u.e.scheme); + } else if (msg->type == VERIFY) { + info = guid_to_string(msg->u.v.scheme); + } else if (msg->type == ALERT) { + info = guid_to_string(msg->u.a.scheme); + } + + if (info == NULL) + return; + + TRACE_NEGOEX_INCOMING(ctx->kctx, ctx->negoex_seqnum - 1, + typestr(msg->type), info); + free(info); +} + +/* Trace an outgoing message with a GUID info string. Call after the context + * sequence number is incremented. */ +static void +trace_outgoing_message(spnego_gss_ctx_id_t ctx, enum message_type type, + const uint8_t guid[GUID_LENGTH]) +{ + char *info = guid_to_string(guid); + + if (info == NULL) + return; + TRACE_NEGOEX_OUTGOING(ctx->kctx, ctx->negoex_seqnum - 1, typestr(type), + info); + free(info); +} + +static OM_uint32 +parse_nego_message(OM_uint32 *minor, struct k5input *in, + const uint8_t *msg_base, size_t msg_len, + struct nego_message *msg) +{ + const uint8_t *p; + uint64_t protocol_version; + uint32_t extension_type; + size_t offset, count, i; + + p = k5_input_get_bytes(in, sizeof(msg->random)); + if (p != NULL) + memcpy(msg->random, p, sizeof(msg->random)); + protocol_version = k5_input_get_uint64_le(in); + if (protocol_version != 0) { + *minor = ERR_NEGOEX_UNSUPPORTED_VERSION; + return GSS_S_UNAVAILABLE; + } + + offset = k5_input_get_uint32_le(in); + count = k5_input_get_uint16_le(in); + msg->schemes = vector_base(offset, count, GUID_LENGTH, msg_base, msg_len); + msg->nschemes = count; + if (msg->schemes == NULL) { + *minor = ERR_NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + offset = k5_input_get_uint32_le(in); + count = k5_input_get_uint16_le(in); + p = vector_base(offset, count, EXTENSION_LENGTH, msg_base, msg_len); + for (i = 0; i < count; i++) { + extension_type = load_32_le(p + i * EXTENSION_LENGTH); + if (extension_type & EXTENSION_FLAG_CRITICAL) { + *minor = ERR_NEGOEX_UNSUPPORTED_CRITICAL_EXTENSION; + return GSS_S_UNAVAILABLE; + } + } + + return GSS_S_COMPLETE; +} + +static OM_uint32 +parse_exchange_message(OM_uint32 *minor, struct k5input *in, + const uint8_t *msg_base, size_t msg_len, + struct exchange_message *msg) +{ + const uint8_t *p; + size_t offset, len; + + p = k5_input_get_bytes(in, GUID_LENGTH); + if (p != NULL) + memcpy(msg->scheme, p, GUID_LENGTH); + + offset = k5_input_get_uint32_le(in); + len = k5_input_get_uint32_le(in); + p = vector_base(offset, len, 1, msg_base, msg_len); + if (p == NULL) { + *minor = ERR_NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + msg->token.value = (void *)p; + msg->token.length = len; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +parse_verify_message(OM_uint32 *minor, struct k5input *in, + const uint8_t *msg_base, size_t msg_len, + size_t token_offset, struct verify_message *msg) +{ + const uint8_t *p; + size_t offset, len; + uint32_t hdrlen, cksum_scheme; + + p = k5_input_get_bytes(in, GUID_LENGTH); + if (p != NULL) + memcpy(msg->scheme, p, GUID_LENGTH); + + hdrlen = k5_input_get_uint32_le(in); + if (hdrlen != CHECKSUM_HEADER_LENGTH) { + *minor = ERR_NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + cksum_scheme = k5_input_get_uint32_le(in); + if (cksum_scheme != CHECKSUM_SCHEME_RFC3961) { + *minor = ERR_NEGOEX_UNKNOWN_CHECKSUM_SCHEME; + return GSS_S_UNAVAILABLE; + } + msg->cksum_type = k5_input_get_uint32_le(in); + + offset = k5_input_get_uint32_le(in); + len = k5_input_get_uint32_le(in); + msg->cksum = vector_base(offset, len, 1, msg_base, msg_len); + msg->cksum_len = len; + if (msg->cksum == NULL) { + *minor = ERR_NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + msg->offset_in_token = token_offset; + return GSS_S_COMPLETE; +} + +static OM_uint32 +parse_alert_message(OM_uint32 *minor, struct k5input *in, + const uint8_t *msg_base, size_t msg_len, + struct alert_message *msg) +{ + const uint8_t *p; + uint32_t atype, reason; + size_t alerts_offset, nalerts, value_offset, value_len, i; + struct k5input alerts_in, pulse_in; + + p = k5_input_get_bytes(in, GUID_LENGTH); + if (p != NULL) + memcpy(msg->scheme, p, GUID_LENGTH); + (void)k5_input_get_uint32_le(in); /* skip over ErrorCode */ + alerts_offset = k5_input_get_uint32_le(in); + nalerts = k5_input_get_uint32_le(in); + p = vector_base(alerts_offset, nalerts, ALERT_LENGTH, msg_base, msg_len); + if (p == NULL) { + *minor = ERR_NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + /* Look for a VERIFY_NO_KEY pulse alert in the alerts vector. */ + msg->verify_no_key = FALSE; + k5_input_init(&alerts_in, p, nalerts * ALERT_LENGTH); + for (i = 0; i < nalerts; i++) { + atype = k5_input_get_uint32_le(&alerts_in); + value_offset = k5_input_get_uint32_le(&alerts_in); + value_len = k5_input_get_uint32_le(&alerts_in); + p = vector_base(value_offset, value_len, 1, msg_base, msg_len); + if (p == NULL) { + *minor = ERR_NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (atype == ALERT_TYPE_PULSE && value_len >= ALERT_PULSE_LENGTH) { + k5_input_init(&pulse_in, p, value_len); + (void)k5_input_get_uint32_le(&pulse_in); /* skip header length */ + reason = k5_input_get_uint32_le(&pulse_in); + if (reason == ALERT_VERIFY_NO_KEY) + msg->verify_no_key = TRUE; + } + } + + return GSS_S_COMPLETE; +} + +static OM_uint32 +parse_message(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, struct k5input *in, + const uint8_t *token_base, struct negoex_message *msg) +{ + OM_uint32 major; + const uint8_t *msg_base = in->ptr, *conv_id; + size_t token_remaining = in->len, header_len, msg_len; + uint64_t signature; + uint32_t type, seqnum; + + signature = k5_input_get_uint64_le(in); + type = k5_input_get_uint32_le(in); + seqnum = k5_input_get_uint32_le(in); + header_len = k5_input_get_uint32_le(in); + msg_len = k5_input_get_uint32_le(in); + conv_id = k5_input_get_bytes(in, GUID_LENGTH); + + if (in->status || msg_len > token_remaining || header_len > msg_len) { + *minor = ERR_NEGOEX_INVALID_MESSAGE_SIZE; + return GSS_S_DEFECTIVE_TOKEN; + } + if (signature != MESSAGE_SIGNATURE) { + *minor = ERR_NEGOEX_INVALID_MESSAGE_SIGNATURE; + return GSS_S_DEFECTIVE_TOKEN; + } + if (seqnum != ctx->negoex_seqnum) { + *minor = ERR_NEGOEX_MESSAGE_OUT_OF_SEQUENCE; + return GSS_S_DEFECTIVE_TOKEN; + } + if (seqnum == 0) { + memcpy(ctx->negoex_conv_id, conv_id, GUID_LENGTH); + } else if (!GUID_EQ(conv_id, ctx->negoex_conv_id)) { + *minor = ERR_NEGOEX_INVALID_CONVERSATION_ID; + return GSS_S_DEFECTIVE_TOKEN; + } + + /* Restrict the input region to the header. */ + in->len = header_len - (in->ptr - msg_base); + + msg->type = type; + if (type == INITIATOR_NEGO || type == ACCEPTOR_NEGO) { + major = parse_nego_message(minor, in, msg_base, msg_len, &msg->u.n); + } else if (type == INITIATOR_META_DATA || type == ACCEPTOR_META_DATA || + type == CHALLENGE || type == AP_REQUEST) { + major = parse_exchange_message(minor, in, msg_base, msg_len, + &msg->u.e); + } else if (type == VERIFY) { + major = parse_verify_message(minor, in, msg_base, msg_len, + msg_base - token_base, &msg->u.v); + } else if (type == ALERT) { + major = parse_alert_message(minor, in, msg_base, msg_len, &msg->u.a); + } else { + *minor = ERR_NEGOEX_INVALID_MESSAGE_TYPE; + return GSS_S_DEFECTIVE_TOKEN; + } + if (major != GSS_S_COMPLETE) + return major; + + /* Reset the input buffer to the remainder of the token. */ + if (!in->status) + k5_input_init(in, msg_base + msg_len, token_remaining - msg_len); + + ctx->negoex_seqnum++; + trace_received_message(ctx, msg); + return GSS_S_COMPLETE; +} + +/* + * Parse token into an array of negoex_message structures. All pointer fields + * within the parsed messages are aliases into token, so the result can be + * freed with free(). An unknown protocol version, a critical extension, or an + * unknown checksum scheme will cause a parsing failure. Increment the + * sequence number in ctx for each message, and record and check the + * conversation ID in ctx as appropriate. + */ +OM_uint32 +negoex_parse_token(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + gss_const_buffer_t token, + struct negoex_message **messages_out, size_t *count_out) +{ + OM_uint32 major = GSS_S_COMPLETE; + size_t count = 0; + struct k5input in; + struct negoex_message *messages = NULL, *newptr; + + *messages_out = NULL; + *count_out = 0; + assert(token != GSS_C_NO_BUFFER); + k5_input_init(&in, token->value, token->length); + + while (in.status == 0 && in.len > 0) { + newptr = realloc(messages, (count + 1) * sizeof(*newptr)); + if (newptr == NULL) { + free(messages); + *minor = ENOMEM; + return GSS_S_FAILURE; + } + messages = newptr; + + major = parse_message(minor, ctx, &in, token->value, &messages[count]); + if (major != GSS_S_COMPLETE) + break; + + count++; + } + + if (in.status) { + *minor = ERR_NEGOEX_INVALID_MESSAGE_SIZE; + major = GSS_S_DEFECTIVE_TOKEN; + } + if (major != GSS_S_COMPLETE) { + free(messages); + return major; + } + + *messages_out = messages; + *count_out = count; + return GSS_S_COMPLETE; +} + +static struct negoex_message * +locate_message(struct negoex_message *messages, size_t nmessages, + enum message_type type) +{ + uint32_t i; + + for (i = 0; i < nmessages; i++) { + if (messages[i].type == type) + return &messages[i]; + } + + return NULL; +} + +struct nego_message * +negoex_locate_nego_message(struct negoex_message *messages, size_t nmessages, + enum message_type type) +{ + struct negoex_message *msg = locate_message(messages, nmessages, type); + + return (msg == NULL) ? NULL : &msg->u.n; +} + +struct exchange_message * +negoex_locate_exchange_message(struct negoex_message *messages, + size_t nmessages, enum message_type type) +{ + struct negoex_message *msg = locate_message(messages, nmessages, type); + + return (msg == NULL) ? NULL : &msg->u.e; +} + +struct verify_message * +negoex_locate_verify_message(struct negoex_message *messages, + size_t nmessages) +{ + struct negoex_message *msg = locate_message(messages, nmessages, VERIFY); + + return (msg == NULL) ? NULL : &msg->u.v; +} + +struct alert_message * +negoex_locate_alert_message(struct negoex_message *messages, size_t nmessages) +{ + struct negoex_message *msg = locate_message(messages, nmessages, ALERT); + + return (msg == NULL) ? NULL : &msg->u.a; +} + +/* + * Add the encoding of a MESSAGE_HEADER structure to buf, given the number of + * bytes of the payload following the full header. Increment the sequence + * number in ctx. Set *payload_start_out to the position of the payload within + * the message. + */ +static void +put_message_header(spnego_gss_ctx_id_t ctx, enum message_type type, + uint32_t payload_len, uint32_t *payload_start_out) +{ + size_t header_len; + + if (type == INITIATOR_NEGO || type == ACCEPTOR_NEGO) + header_len = NEGO_MESSAGE_HEADER_LENGTH; + else if (type == INITIATOR_META_DATA || type == ACCEPTOR_META_DATA || + type == CHALLENGE || type == AP_REQUEST) + header_len = EXCHANGE_MESSAGE_HEADER_LENGTH; + else if (type == VERIFY) + header_len = VERIFY_MESSAGE_HEADER_LENGTH; + else if (type == ALERT) + header_len = ALERT_MESSAGE_HEADER_LENGTH; + else + abort(); + + k5_buf_add_uint64_le(&ctx->negoex_transcript, MESSAGE_SIGNATURE); + k5_buf_add_uint32_le(&ctx->negoex_transcript, type); + k5_buf_add_uint32_le(&ctx->negoex_transcript, ctx->negoex_seqnum++); + k5_buf_add_uint32_le(&ctx->negoex_transcript, header_len); + k5_buf_add_uint32_le(&ctx->negoex_transcript, header_len + payload_len); + k5_buf_add_len(&ctx->negoex_transcript, ctx->negoex_conv_id, GUID_LENGTH); + + *payload_start_out = header_len; +} + +void +negoex_add_nego_message(spnego_gss_ctx_id_t ctx, enum message_type type, + uint8_t random[32]) +{ + struct negoex_auth_mech *mech; + uint32_t payload_start, seqnum = ctx->negoex_seqnum; + uint16_t nschemes; + struct k5buf buf; + + nschemes = 0; + K5_TAILQ_FOREACH(mech, &ctx->negoex_mechs, links) + nschemes++; + + put_message_header(ctx, type, nschemes * GUID_LENGTH, &payload_start); + k5_buf_add_len(&ctx->negoex_transcript, random, 32); + /* ProtocolVersion */ + k5_buf_add_uint64_le(&ctx->negoex_transcript, 0); + /* AuthSchemes vector */ + k5_buf_add_uint32_le(&ctx->negoex_transcript, payload_start); + k5_buf_add_uint16_le(&ctx->negoex_transcript, nschemes); + /* Extensions vector */ + k5_buf_add_uint32_le(&ctx->negoex_transcript, payload_start); + k5_buf_add_uint16_le(&ctx->negoex_transcript, 0); + /* Four bytes of padding to reach a multiple of 8 bytes. */ + k5_buf_add_len(&ctx->negoex_transcript, "\0\0\0\0", 4); + + /* Payload (auth schemes); also build guid string for tracing. */ + k5_buf_init_dynamic(&buf); + K5_TAILQ_FOREACH(mech, &ctx->negoex_mechs, links) { + k5_buf_add_len(&ctx->negoex_transcript, mech->scheme, GUID_LENGTH); + add_guid(&buf, mech->scheme); + k5_buf_add(&buf, " "); + } + + if (buf.len > 0) { + k5_buf_truncate(&buf, buf.len - 1); + TRACE_NEGOEX_OUTGOING(ctx->kctx, seqnum, typestr(type), + k5_buf_cstring(&buf)); + k5_buf_free(&buf); + } +} + +void +negoex_add_exchange_message(spnego_gss_ctx_id_t ctx, enum message_type type, + const auth_scheme scheme, gss_buffer_t token) +{ + uint32_t payload_start; + + put_message_header(ctx, type, token->length, &payload_start); + k5_buf_add_len(&ctx->negoex_transcript, scheme, GUID_LENGTH); + /* Exchange byte vector */ + k5_buf_add_uint32_le(&ctx->negoex_transcript, payload_start); + k5_buf_add_uint32_le(&ctx->negoex_transcript, token->length); + /* Payload (token) */ + k5_buf_add_len(&ctx->negoex_transcript, token->value, token->length); + + trace_outgoing_message(ctx, type, scheme); +} + +void +negoex_add_verify_message(spnego_gss_ctx_id_t ctx, const auth_scheme scheme, + uint32_t cksum_type, const uint8_t *cksum, + uint32_t cksum_len) +{ + uint32_t payload_start; + + put_message_header(ctx, VERIFY, cksum_len, &payload_start); + k5_buf_add_len(&ctx->negoex_transcript, scheme, GUID_LENGTH); + k5_buf_add_uint32_le(&ctx->negoex_transcript, CHECKSUM_HEADER_LENGTH); + k5_buf_add_uint32_le(&ctx->negoex_transcript, CHECKSUM_SCHEME_RFC3961); + k5_buf_add_uint32_le(&ctx->negoex_transcript, cksum_type); + /* ChecksumValue vector */ + k5_buf_add_uint32_le(&ctx->negoex_transcript, payload_start); + k5_buf_add_uint32_le(&ctx->negoex_transcript, cksum_len); + /* Four bytes of padding to reach a multiple of 8 bytes. */ + k5_buf_add_len(&ctx->negoex_transcript, "\0\0\0\0", 4); + /* Payload (checksum contents) */ + k5_buf_add_len(&ctx->negoex_transcript, cksum, cksum_len); + + trace_outgoing_message(ctx, VERIFY, scheme); +} + +/* Add an ALERT_MESSAGE containing a single ALERT_TYPE_PULSE alert with the + * reason ALERT_VERIFY_NO_KEY. */ +void +negoex_add_verify_no_key_alert(spnego_gss_ctx_id_t ctx, + const auth_scheme scheme) +{ + uint32_t payload_start; + + put_message_header(ctx, ALERT, ALERT_LENGTH + ALERT_PULSE_LENGTH, + &payload_start); + k5_buf_add_len(&ctx->negoex_transcript, scheme, GUID_LENGTH); + /* ErrorCode */ + k5_buf_add_uint32_le(&ctx->negoex_transcript, 0); + /* Alerts vector */ + k5_buf_add_uint32_le(&ctx->negoex_transcript, payload_start); + k5_buf_add_uint16_le(&ctx->negoex_transcript, 1); + /* Six bytes of padding to reach a multiple of 8 bytes. */ + k5_buf_add_len(&ctx->negoex_transcript, "\0\0\0\0\0\0", 6); + /* Payload part 1: a single ALERT element */ + k5_buf_add_uint32_le(&ctx->negoex_transcript, ALERT_TYPE_PULSE); + k5_buf_add_uint32_le(&ctx->negoex_transcript, + payload_start + ALERT_LENGTH); + k5_buf_add_uint32_le(&ctx->negoex_transcript, ALERT_PULSE_LENGTH); + /* Payload part 2: ALERT_PULSE */ + k5_buf_add_uint32_le(&ctx->negoex_transcript, ALERT_PULSE_LENGTH); + k5_buf_add_uint32_le(&ctx->negoex_transcript, ALERT_VERIFY_NO_KEY); + + trace_outgoing_message(ctx, ALERT, scheme); +} + +static void +release_auth_mech(struct negoex_auth_mech *mech) +{ + OM_uint32 tmpmin; + + if (mech == NULL) + return; + + gss_delete_sec_context(&tmpmin, &mech->mech_context, NULL); + generic_gss_release_oid(&tmpmin, &mech->oid); + gss_release_buffer(&tmpmin, &mech->metadata); + krb5_free_keyblock_contents(NULL, &mech->key); + krb5_free_keyblock_contents(NULL, &mech->verify_key); + + free(mech); +} + +void +negoex_delete_auth_mech(spnego_gss_ctx_id_t ctx, + struct negoex_auth_mech *mech) +{ + K5_TAILQ_REMOVE(&ctx->negoex_mechs, mech, links); + release_auth_mech(mech); +} + +/* Remove all auth mech entries except for mech from ctx->mechs. */ +void +negoex_select_auth_mech(spnego_gss_ctx_id_t ctx, + struct negoex_auth_mech *mech) +{ + assert(mech != NULL); + K5_TAILQ_REMOVE(&ctx->negoex_mechs, mech, links); + release_all_mechs(ctx); + K5_TAILQ_INSERT_HEAD(&ctx->negoex_mechs, mech, links); +} + +OM_uint32 +negoex_add_auth_mech(OM_uint32 *minor, spnego_gss_ctx_id_t ctx, + gss_const_OID oid, auth_scheme scheme) +{ + OM_uint32 major; + struct negoex_auth_mech *mech; + + mech = calloc(1, sizeof(*mech)); + if (mech == NULL) { + *minor = ENOMEM; + return GSS_S_FAILURE; + } + + major = generic_gss_copy_oid(minor, (gss_OID)oid, &mech->oid); + if (major != GSS_S_COMPLETE) { + free(mech); + return major; + } + + memcpy(mech->scheme, scheme, GUID_LENGTH); + + K5_TAILQ_INSERT_TAIL(&ctx->negoex_mechs, mech, links); + + *minor = 0; + return GSS_S_COMPLETE; +} + +struct negoex_auth_mech * +negoex_locate_auth_scheme(spnego_gss_ctx_id_t ctx, const auth_scheme scheme) +{ + struct negoex_auth_mech *mech; + + K5_TAILQ_FOREACH(mech, &ctx->negoex_mechs, links) { + if (GUID_EQ(mech->scheme, scheme)) + return mech; + } + + return NULL; +} + +/* Prune ctx->mechs to the schemes present in schemes, and reorder them to + * match its order. */ +void +negoex_common_auth_schemes(spnego_gss_ctx_id_t ctx, + const uint8_t *schemes, uint16_t nschemes) +{ + struct negoex_mech_list list; + struct negoex_auth_mech *mech; + uint16_t i; + + /* Construct a new list in the order of schemes. */ + K5_TAILQ_INIT(&list); + for (i = 0; i < nschemes; i++) { + mech = negoex_locate_auth_scheme(ctx, schemes + i * GUID_LENGTH); + if (mech == NULL) + continue; + K5_TAILQ_REMOVE(&ctx->negoex_mechs, mech, links); + K5_TAILQ_INSERT_TAIL(&list, mech, links); + } + + /* Release any leftover entries and replace the context list. */ + release_all_mechs(ctx); + K5_TAILQ_CONCAT(&ctx->negoex_mechs, &list, links); +} + +/* Prune ctx->mechs to the schemes present in schemes, but do not change + * their order. */ +void +negoex_restrict_auth_schemes(spnego_gss_ctx_id_t ctx, + const uint8_t *schemes, uint16_t nschemes) +{ + struct negoex_auth_mech *mech, *next; + uint16_t i; + int found; + + K5_TAILQ_FOREACH_SAFE(mech, &ctx->negoex_mechs, links, next) { + found = FALSE; + for (i = 0; i < nschemes && !found; i++) { + if (GUID_EQ(mech->scheme, schemes + i * GUID_LENGTH)) + found = TRUE; + } + + if (!found) + negoex_delete_auth_mech(ctx, mech); + } +} diff --git a/krb5-1.21.3/src/lib/gssapi/spnego/spnego_mech.c b/krb5-1.21.3/src/lib/gssapi/spnego/spnego_mech.c new file mode 100644 index 00000000..5923c880 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi/spnego/spnego_mech.c @@ -0,0 +1,3824 @@ +/* + * Copyright (C) 2006,2008 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * A module that implements the spnego security mechanism. + * It is used to negotiate the security mechanism between + * peers using the GSS-API. SPNEGO is specified in RFC 4178. + * + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ +/* #pragma ident "@(#)spnego_mech.c 1.7 04/09/28 SMI" */ + +#include +#include +#include +#include +#include "gssapiP_spnego.h" +#include + + +#define HARD_ERROR(v) ((v) != GSS_S_COMPLETE && (v) != GSS_S_CONTINUE_NEEDED) +typedef const gss_OID_desc *gss_OID_const; + +/* private routines for spnego_mechanism */ +static spnego_token_t make_spnego_token(const char *); +static gss_buffer_desc make_err_msg(const char *); +static int verify_token_header(struct k5input *, gss_OID_const); +static gss_OID get_mech_oid(OM_uint32 *minor_status, struct k5input *); +static gss_buffer_t get_octet_string(struct k5input *); +static gss_OID_set get_mech_set(OM_uint32 *, struct k5input *); +static OM_uint32 get_req_flags(struct k5input *, OM_uint32 *); +static OM_uint32 get_available_mechs(OM_uint32 *, gss_name_t, gss_cred_usage_t, + gss_const_key_value_set_t, + gss_cred_id_t *, gss_OID_set *, + OM_uint32 *); +static OM_uint32 get_negotiable_mechs(OM_uint32 *, spnego_gss_ctx_id_t, + spnego_gss_cred_id_t, gss_cred_usage_t); +static void release_spnego_ctx(spnego_gss_ctx_id_t *); +static spnego_gss_ctx_id_t create_spnego_ctx(int); +static int put_mech_set(gss_OID_set mechSet, gss_buffer_t buf); + +static OM_uint32 +process_mic(OM_uint32 *, gss_buffer_t, spnego_gss_ctx_id_t, + gss_buffer_t *, OM_uint32 *, send_token_flag *); +static OM_uint32 +handle_mic(OM_uint32 *, gss_buffer_t, int, spnego_gss_ctx_id_t, + gss_buffer_t *, OM_uint32 *, send_token_flag *); + +static OM_uint32 +init_ctx_new(OM_uint32 *, spnego_gss_cred_id_t, send_token_flag *, + spnego_gss_ctx_id_t *); +static OM_uint32 +init_ctx_nego(OM_uint32 *, spnego_gss_ctx_id_t, OM_uint32, gss_OID, + gss_buffer_t *, gss_buffer_t *, send_token_flag *); +static OM_uint32 +init_ctx_cont(OM_uint32 *, spnego_gss_ctx_id_t, gss_buffer_t, + gss_buffer_t *, gss_buffer_t *, + OM_uint32 *, send_token_flag *); +static OM_uint32 +init_ctx_reselect(OM_uint32 *, spnego_gss_ctx_id_t, OM_uint32, + gss_OID, gss_buffer_t *, gss_buffer_t *, send_token_flag *); +static OM_uint32 +init_ctx_call_init(OM_uint32 *, spnego_gss_ctx_id_t, spnego_gss_cred_id_t, + OM_uint32, gss_name_t, OM_uint32, OM_uint32, gss_buffer_t, + gss_channel_bindings_t, + gss_buffer_t, OM_uint32 *, send_token_flag *); + +static OM_uint32 +acc_ctx_new(OM_uint32 *, gss_buffer_t, spnego_gss_cred_id_t, gss_buffer_t *, + gss_buffer_t *, OM_uint32 *, send_token_flag *, + spnego_gss_ctx_id_t *); +static OM_uint32 +acc_ctx_cont(OM_uint32 *, gss_buffer_t, spnego_gss_ctx_id_t, gss_buffer_t *, + gss_buffer_t *, OM_uint32 *, send_token_flag *); +static OM_uint32 +acc_ctx_vfy_oid(OM_uint32 *, spnego_gss_ctx_id_t, gss_OID, + OM_uint32 *, send_token_flag *); +static OM_uint32 +acc_ctx_call_acc(OM_uint32 *, spnego_gss_ctx_id_t, spnego_gss_cred_id_t, + gss_buffer_t, gss_channel_bindings_t, gss_buffer_t, + OM_uint32 *, OM_uint32 *, send_token_flag *); + +static gss_OID +negotiate_mech(spnego_gss_ctx_id_t, gss_OID_set, OM_uint32 *); + +static int +make_spnego_tokenInit_msg(spnego_gss_ctx_id_t, + int, + gss_buffer_t, + OM_uint32, gss_buffer_t, send_token_flag, + gss_buffer_t); +static OM_uint32 +make_spnego_tokenTarg_msg(uint8_t, gss_OID, gss_buffer_t, + gss_buffer_t, send_token_flag, + gss_buffer_t); + +static OM_uint32 +get_negTokenInit(OM_uint32 *, gss_buffer_t, gss_buffer_t, + gss_OID_set *, OM_uint32 *, gss_buffer_t *, + gss_buffer_t *); +static OM_uint32 +get_negTokenResp(OM_uint32 *, struct k5input *, OM_uint32 *, gss_OID *, + gss_buffer_t *, gss_buffer_t *); + +static int +is_kerb_mech(gss_OID oid); + +/* SPNEGO oid structure */ +static const gss_OID_desc spnego_oids[] = { + {SPNEGO_OID_LENGTH, SPNEGO_OID}, +}; + +const gss_OID_desc * const gss_mech_spnego = spnego_oids+0; +static const gss_OID_set_desc spnego_oidsets[] = { + {1, (gss_OID) spnego_oids+0}, +}; +const gss_OID_set_desc * const gss_mech_set_spnego = spnego_oidsets+0; + +static gss_OID_desc negoex_mech = { NEGOEX_OID_LENGTH, NEGOEX_OID }; + +static int make_NegHints(OM_uint32 *, gss_buffer_t *); +static OM_uint32 +acc_ctx_hints(OM_uint32 *, spnego_gss_cred_id_t, gss_buffer_t *, OM_uint32 *, + send_token_flag *, spnego_gss_ctx_id_t *); + +/* + * The Mech OID for SPNEGO: + * { iso(1) org(3) dod(6) internet(1) security(5) + * mechanism(5) spnego(2) } + */ +static struct gss_config spnego_mechanism = +{ + {SPNEGO_OID_LENGTH, SPNEGO_OID}, + NULL, + spnego_gss_acquire_cred, + spnego_gss_release_cred, + spnego_gss_init_sec_context, +#ifndef LEAN_CLIENT + spnego_gss_accept_sec_context, +#else + NULL, +#endif /* LEAN_CLIENT */ + NULL, /* gss_process_context_token */ + spnego_gss_delete_sec_context, /* gss_delete_sec_context */ + spnego_gss_context_time, /* gss_context_time */ + spnego_gss_get_mic, /* gss_get_mic */ + spnego_gss_verify_mic, /* gss_verify_mic */ + spnego_gss_wrap, /* gss_wrap */ + spnego_gss_unwrap, /* gss_unwrap */ + spnego_gss_display_status, + NULL, /* gss_indicate_mechs */ + spnego_gss_compare_name, + spnego_gss_display_name, + spnego_gss_import_name, + spnego_gss_release_name, + spnego_gss_inquire_cred, /* gss_inquire_cred */ + NULL, /* gss_add_cred */ +#ifndef LEAN_CLIENT + spnego_gss_export_sec_context, /* gss_export_sec_context */ + spnego_gss_import_sec_context, /* gss_import_sec_context */ +#else + NULL, /* gss_export_sec_context */ + NULL, /* gss_import_sec_context */ +#endif /* LEAN_CLIENT */ + NULL, /* gss_inquire_cred_by_mech */ + spnego_gss_inquire_names_for_mech, + spnego_gss_inquire_context, /* gss_inquire_context */ + NULL, /* gss_internal_release_oid */ + spnego_gss_wrap_size_limit, /* gss_wrap_size_limit */ + spnego_gss_localname, + NULL, /* gss_userok */ + NULL, /* gss_export_name */ + spnego_gss_duplicate_name, /* gss_duplicate_name */ + NULL, /* gss_store_cred */ + spnego_gss_inquire_sec_context_by_oid, /* gss_inquire_sec_context_by_oid */ + spnego_gss_inquire_cred_by_oid, /* gss_inquire_cred_by_oid */ + spnego_gss_set_sec_context_option, /* gss_set_sec_context_option */ + spnego_gss_set_cred_option, /* gssspi_set_cred_option */ + NULL, /* gssspi_mech_invoke */ + spnego_gss_wrap_aead, + spnego_gss_unwrap_aead, + spnego_gss_wrap_iov, + spnego_gss_unwrap_iov, + spnego_gss_wrap_iov_length, + spnego_gss_complete_auth_token, + spnego_gss_acquire_cred_impersonate_name, + NULL, /* gss_add_cred_impersonate_name */ + spnego_gss_display_name_ext, + spnego_gss_inquire_name, + spnego_gss_get_name_attribute, + spnego_gss_set_name_attribute, + spnego_gss_delete_name_attribute, + spnego_gss_export_name_composite, + spnego_gss_map_name_to_any, + spnego_gss_release_any_name_mapping, + spnego_gss_pseudo_random, + spnego_gss_set_neg_mechs, + spnego_gss_inquire_saslname_for_mech, + spnego_gss_inquire_mech_for_saslname, + spnego_gss_inquire_attrs_for_mech, + spnego_gss_acquire_cred_from, + NULL, /* gss_store_cred_into */ + spnego_gss_acquire_cred_with_password, + spnego_gss_export_cred, + spnego_gss_import_cred, + NULL, /* gssspi_import_sec_context_by_mech */ + NULL, /* gssspi_import_name_by_mech */ + NULL, /* gssspi_import_cred_by_mech */ + spnego_gss_get_mic_iov, + spnego_gss_verify_mic_iov, + spnego_gss_get_mic_iov_length +}; + +#ifdef _GSS_STATIC_LINK +#include "mglueP.h" + +static int gss_spnegomechglue_init(void) +{ + struct gss_mech_config mech_spnego; + + memset(&mech_spnego, 0, sizeof(mech_spnego)); + mech_spnego.mech = &spnego_mechanism; + mech_spnego.mechNameStr = "spnego"; + mech_spnego.mech_type = GSS_C_NO_OID; + + return gssint_register_mechinfo(&mech_spnego); +} +#else +gss_mechanism KRB5_CALLCONV +gss_mech_initialize(void) +{ + return (&spnego_mechanism); +} + +MAKE_INIT_FUNCTION(gss_krb5int_lib_init); +MAKE_FINI_FUNCTION(gss_krb5int_lib_fini); +int gss_krb5int_lib_init(void); +#endif /* _GSS_STATIC_LINK */ + +int gss_spnegoint_lib_init(void) +{ + int err; + + err = k5_key_register(K5_KEY_GSS_SPNEGO_STATUS, NULL); + if (err) + return err; + +#ifdef _GSS_STATIC_LINK + return gss_spnegomechglue_init(); +#else + return 0; +#endif +} + +void gss_spnegoint_lib_fini(void) +{ + k5_key_delete(K5_KEY_GSS_SPNEGO_STATUS); +} + +static OM_uint32 +create_spnego_cred(OM_uint32 *minor_status, gss_cred_id_t mcred, + spnego_gss_cred_id_t *cred_out) +{ + spnego_gss_cred_id_t spcred; + + *cred_out = NULL; + spcred = calloc(1, sizeof(*spcred)); + if (spcred == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + spcred->mcred = mcred; + *cred_out = spcred; + return GSS_S_COMPLETE; +} + +/*ARGSUSED*/ +OM_uint32 KRB5_CALLCONV +spnego_gss_acquire_cred(OM_uint32 *minor_status, + gss_name_t desired_name, + OM_uint32 time_req, + gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + return spnego_gss_acquire_cred_from(minor_status, desired_name, time_req, + desired_mechs, cred_usage, NULL, + output_cred_handle, actual_mechs, + time_rec); +} + +/*ARGSUSED*/ +OM_uint32 KRB5_CALLCONV +spnego_gss_acquire_cred_from(OM_uint32 *minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + OM_uint32 status, tmpmin; + gss_OID_set amechs; + gss_cred_id_t mcred = NULL; + spnego_gss_cred_id_t spcred = NULL; + dsyslog("Entering spnego_gss_acquire_cred\n"); + + if (actual_mechs) + *actual_mechs = NULL; + + if (time_rec) + *time_rec = 0; + + /* We will obtain a mechglue credential and wrap it in a + * spnego_gss_cred_id_rec structure. Allocate the wrapper. */ + status = create_spnego_cred(minor_status, mcred, &spcred); + if (status != GSS_S_COMPLETE) + return (status); + + /* + * Always use get_available_mechs to collect a list of + * mechs for which creds are available. + */ + status = get_available_mechs(minor_status, desired_name, + cred_usage, cred_store, &mcred, + &amechs, time_rec); + + if (actual_mechs && amechs != GSS_C_NULL_OID_SET) { + (void) gssint_copy_oid_set(&tmpmin, amechs, actual_mechs); + } + (void) gss_release_oid_set(&tmpmin, &amechs); + + if (status == GSS_S_COMPLETE) { + spcred->mcred = mcred; + *output_cred_handle = (gss_cred_id_t)spcred; + } else { + free(spcred); + *output_cred_handle = GSS_C_NO_CREDENTIAL; + } + + dsyslog("Leaving spnego_gss_acquire_cred\n"); + return (status); +} + +/*ARGSUSED*/ +OM_uint32 KRB5_CALLCONV +spnego_gss_release_cred(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle) +{ + spnego_gss_cred_id_t spcred = NULL; + + dsyslog("Entering spnego_gss_release_cred\n"); + + if (minor_status == NULL || cred_handle == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + *minor_status = 0; + + if (*cred_handle == GSS_C_NO_CREDENTIAL) + return (GSS_S_COMPLETE); + + spcred = (spnego_gss_cred_id_t)*cred_handle; + *cred_handle = GSS_C_NO_CREDENTIAL; + gss_release_oid_set(minor_status, &spcred->neg_mechs); + gss_release_cred(minor_status, &spcred->mcred); + free(spcred); + + dsyslog("Leaving spnego_gss_release_cred\n"); + return (GSS_S_COMPLETE); +} + +static spnego_gss_ctx_id_t +create_spnego_ctx(int initiate) +{ + spnego_gss_ctx_id_t spnego_ctx = NULL; + + spnego_ctx = malloc(sizeof(*spnego_ctx)); + if (spnego_ctx == NULL) { + return (NULL); + } + + spnego_ctx->magic_num = SPNEGO_MAGIC_ID; + spnego_ctx->ctx_handle = GSS_C_NO_CONTEXT; + spnego_ctx->mech_set = NULL; + spnego_ctx->internal_mech = NULL; + spnego_ctx->DER_mechTypes.length = 0; + spnego_ctx->DER_mechTypes.value = NULL; + spnego_ctx->mic_reqd = 0; + spnego_ctx->mic_sent = 0; + spnego_ctx->mic_rcvd = 0; + spnego_ctx->mech_complete = 0; + spnego_ctx->nego_done = 0; + spnego_ctx->opened = 0; + spnego_ctx->initiate = initiate; + spnego_ctx->internal_name = GSS_C_NO_NAME; + spnego_ctx->actual_mech = GSS_C_NO_OID; + spnego_ctx->deleg_cred = GSS_C_NO_CREDENTIAL; + spnego_ctx->negoex_step = 0; + memset(&spnego_ctx->negoex_transcript, 0, sizeof(struct k5buf)); + spnego_ctx->negoex_seqnum = 0; + K5_TAILQ_INIT(&spnego_ctx->negoex_mechs); + spnego_ctx->kctx = NULL; + memset(spnego_ctx->negoex_conv_id, 0, GUID_LENGTH); + + return (spnego_ctx); +} + +/* iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) samba(7165) + * gssntlmssp(655) controls(1) spnego_req_mechlistMIC(2) */ +static const gss_OID_desc spnego_req_mechlistMIC_oid = + { 11, "\x2B\x06\x01\x04\x01\xB7\x7D\x85\x0F\x01\x02" }; + +/* + * Return nonzero if the mechanism has reason to believe that a mechlistMIC + * exchange will be required. Microsoft servers erroneously require SPNEGO + * mechlistMIC if they see an internal MIC within an NTLMSSP Authenticate + * message, even if NTLMSSP was the preferred mechanism. + */ +static int +mech_requires_mechlistMIC(spnego_gss_ctx_id_t sc) +{ + OM_uint32 major, minor; + gss_ctx_id_t ctx = sc->ctx_handle; + gss_OID oid = (gss_OID)&spnego_req_mechlistMIC_oid; + gss_buffer_set_t bufs; + int result; + + major = gss_inquire_sec_context_by_oid(&minor, ctx, oid, &bufs); + if (major != GSS_S_COMPLETE) + return 0; + + /* Report true if the mech returns a single buffer containing a single + * byte with value 1. */ + result = (bufs != NULL && bufs->count == 1 && + bufs->elements[0].length == 1 && + memcmp(bufs->elements[0].value, "\1", 1) == 0); + (void) gss_release_buffer_set(&minor, &bufs); + return result; +} + +/* iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) Microsoft(311) + * security(2) mechanisms(2) NTLM(10) */ +static const gss_OID_desc gss_mech_ntlmssp_oid = + { 10, "\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a" }; + +/* iso(1) org(3) dod(6) internet(1) private(4) enterprises(1) samba(7165) + * gssntlmssp(655) controls(1) ntlmssp_reset_crypto(3) */ +static const gss_OID_desc ntlmssp_reset_crypto_oid = + { 11, "\x2B\x06\x01\x04\x01\xB7\x7D\x85\x0F\x01\x03" }; + +/* + * MS-SPNG section 3.3.5.1 warns that the NTLM mechanism requires special + * handling of the crypto state to interop with Windows. If the mechanism for + * sc is SPNEGO, invoke a mechanism-specific operation on the context to reset + * the RC4 state after producing or verifying a MIC. Ignore a result of + * GSS_S_UNAVAILABLE for compatibility with older versions of the mechanism + * that do not support this functionality. + */ +static OM_uint32 +ntlmssp_reset_crypto_state(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc, + OM_uint32 verify) +{ + OM_uint32 major, minor; + gss_buffer_desc value; + + if (!g_OID_equal(sc->internal_mech, &gss_mech_ntlmssp_oid)) + return GSS_S_COMPLETE; + + value.length = sizeof(verify); + value.value = &verify; + major = gss_set_sec_context_option(&minor, &sc->ctx_handle, + (gss_OID)&ntlmssp_reset_crypto_oid, + &value); + if (major == GSS_S_UNAVAILABLE) + return GSS_S_COMPLETE; + *minor_status = minor; + return major; +} + +/* + * Both initiator and acceptor call here to verify and/or create mechListMIC, + * and to consistency-check the MIC state. handle_mic is invoked only if the + * negotiated mech has completed and supports MICs. + */ +static OM_uint32 +handle_mic(OM_uint32 *minor_status, gss_buffer_t mic_in, + int send_mechtok, spnego_gss_ctx_id_t sc, + gss_buffer_t *mic_out, + OM_uint32 *negState, send_token_flag *tokflag) +{ + OM_uint32 ret; + + ret = GSS_S_FAILURE; + *mic_out = GSS_C_NO_BUFFER; + if (mic_in != GSS_C_NO_BUFFER) { + if (sc->mic_rcvd) { + /* Reject MIC if we've already received a MIC. */ + *negState = REJECT; + *tokflag = ERROR_TOKEN_SEND; + return GSS_S_DEFECTIVE_TOKEN; + } + } else if (sc->mic_reqd && !send_mechtok) { + /* + * If the peer sends the final mechanism token, it + * must send the MIC with that token if the + * negotiation requires MICs. + */ + *negState = REJECT; + *tokflag = ERROR_TOKEN_SEND; + return GSS_S_DEFECTIVE_TOKEN; + } + ret = process_mic(minor_status, mic_in, sc, mic_out, + negState, tokflag); + if (ret != GSS_S_COMPLETE) { + return ret; + } + if (sc->mic_reqd) { + assert(sc->mic_sent || sc->mic_rcvd); + } + if (sc->mic_sent && sc->mic_rcvd) { + ret = GSS_S_COMPLETE; + *negState = ACCEPT_COMPLETE; + if (*mic_out == GSS_C_NO_BUFFER) { + /* + * We sent a MIC on the previous pass; we + * shouldn't be sending a mechanism token. + */ + assert(!send_mechtok); + *tokflag = NO_TOKEN_SEND; + } else { + *tokflag = CONT_TOKEN_SEND; + } + } else if (sc->mic_reqd) { + *negState = ACCEPT_INCOMPLETE; + ret = GSS_S_CONTINUE_NEEDED; + } else if (*negState == ACCEPT_COMPLETE) { + ret = GSS_S_COMPLETE; + } else { + ret = GSS_S_CONTINUE_NEEDED; + } + return ret; +} + +/* + * Perform the actual verification and/or generation of mechListMIC. + */ +static OM_uint32 +process_mic(OM_uint32 *minor_status, gss_buffer_t mic_in, + spnego_gss_ctx_id_t sc, gss_buffer_t *mic_out, + OM_uint32 *negState, send_token_flag *tokflag) +{ + OM_uint32 ret, tmpmin; + gss_qop_t qop_state; + gss_buffer_desc tmpmic = GSS_C_EMPTY_BUFFER; + + ret = GSS_S_FAILURE; + if (mic_in != GSS_C_NO_BUFFER) { + ret = gss_verify_mic(minor_status, sc->ctx_handle, + &sc->DER_mechTypes, + mic_in, &qop_state); + if (ret == GSS_S_COMPLETE) + ret = ntlmssp_reset_crypto_state(minor_status, sc, 1); + if (ret != GSS_S_COMPLETE) { + *negState = REJECT; + *tokflag = ERROR_TOKEN_SEND; + return ret; + } + /* If we got a MIC, we must send a MIC. */ + sc->mic_reqd = 1; + sc->mic_rcvd = 1; + } + if (sc->mic_reqd && !sc->mic_sent) { + ret = gss_get_mic(minor_status, sc->ctx_handle, + GSS_C_QOP_DEFAULT, + &sc->DER_mechTypes, + &tmpmic); + if (ret == GSS_S_COMPLETE) + ret = ntlmssp_reset_crypto_state(minor_status, sc, 0); + if (ret != GSS_S_COMPLETE) { + gss_release_buffer(&tmpmin, &tmpmic); + *tokflag = NO_TOKEN_SEND; + return ret; + } + *mic_out = malloc(sizeof(gss_buffer_desc)); + if (*mic_out == GSS_C_NO_BUFFER) { + gss_release_buffer(&tmpmin, &tmpmic); + *tokflag = NO_TOKEN_SEND; + return GSS_S_FAILURE; + } + **mic_out = tmpmic; + sc->mic_sent = 1; + } + return GSS_S_COMPLETE; +} + +/* Create a new SPNEGO context handle for the initial call to + * spnego_gss_init_sec_context(). */ +static OM_uint32 +init_ctx_new(OM_uint32 *minor_status, + spnego_gss_cred_id_t spcred, + send_token_flag *tokflag, + spnego_gss_ctx_id_t *sc_out) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = NULL; + + *sc_out = NULL; + + sc = create_spnego_ctx(1); + if (sc == NULL) + return GSS_S_FAILURE; + + /* determine negotiation mech set */ + ret = get_negotiable_mechs(minor_status, sc, spcred, GSS_C_INITIATE); + if (ret != GSS_S_COMPLETE) + goto cleanup; + + /* Set an initial internal mech to make the first context token. */ + sc->internal_mech = &sc->mech_set->elements[0]; + + if (put_mech_set(sc->mech_set, &sc->DER_mechTypes) < 0) { + ret = GSS_S_FAILURE; + goto cleanup; + } + + sc->ctx_handle = GSS_C_NO_CONTEXT; + *sc_out = sc; + sc = NULL; + *tokflag = INIT_TOKEN_SEND; + ret = GSS_S_COMPLETE; + +cleanup: + release_spnego_ctx(&sc); + return ret; +} + +/* + * Called by second and later calls to spnego_gss_init_sec_context() + * to decode reply and update state. + */ +static OM_uint32 +init_ctx_cont(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc, + gss_buffer_t buf, gss_buffer_t *responseToken, + gss_buffer_t *mechListMIC, OM_uint32 *acc_negState, + send_token_flag *tokflag) +{ + OM_uint32 ret, tmpmin; + gss_OID supportedMech = GSS_C_NO_OID; + struct k5input in; + + *acc_negState = UNSPECIFIED; + *tokflag = ERROR_TOKEN_SEND; + + k5_input_init(&in, buf->value, buf->length); + ret = get_negTokenResp(minor_status, &in, acc_negState, &supportedMech, + responseToken, mechListMIC); + if (ret != GSS_S_COMPLETE) + goto cleanup; + + /* Bail out now on a reject with no error token. If we have an error + * token, keep going and get a better error status from the mech. */ + if (*acc_negState == REJECT && *responseToken == GSS_C_NO_BUFFER) { + if (!sc->nego_done) { + /* RFC 4178 says to return GSS_S_BAD_MECH on a + * mechanism negotiation failure. */ + *minor_status = ERR_SPNEGO_NEGOTIATION_FAILED; + map_errcode(minor_status); + ret = GSS_S_BAD_MECH; + } else { + ret = GSS_S_FAILURE; + } + *tokflag = NO_TOKEN_SEND; + goto cleanup; + } + /* + * nego_done is false for the first call to init_ctx_cont() + */ + if (!sc->nego_done) { + ret = init_ctx_nego(minor_status, sc, *acc_negState, + supportedMech, responseToken, mechListMIC, + tokflag); + } else if ((!sc->mech_complete && *responseToken == GSS_C_NO_BUFFER) || + (sc->mech_complete && *responseToken != GSS_C_NO_BUFFER)) { + /* Missing or spurious token from acceptor. */ + ret = GSS_S_DEFECTIVE_TOKEN; + } else if (!sc->mech_complete || + (sc->mic_reqd && + (sc->ctx_flags & GSS_C_INTEG_FLAG))) { + /* Not obviously done; we may decide we're done later in + * init_ctx_call_init or handle_mic. */ + *tokflag = CONT_TOKEN_SEND; + ret = GSS_S_COMPLETE; + } else { + /* mech finished on last pass and no MIC required, so done. */ + *tokflag = NO_TOKEN_SEND; + ret = GSS_S_COMPLETE; + } +cleanup: + if (supportedMech != GSS_C_NO_OID) + generic_gss_release_oid(&tmpmin, &supportedMech); + return ret; +} + +/* + * Consistency checking and mechanism negotiation handling for second + * call of spnego_gss_init_sec_context(). Call init_ctx_reselect() to + * update internal state if acceptor has counter-proposed. + */ +static OM_uint32 +init_ctx_nego(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc, + OM_uint32 acc_negState, gss_OID supportedMech, + gss_buffer_t *responseToken, gss_buffer_t *mechListMIC, + send_token_flag *tokflag) +{ + OM_uint32 ret; + + *tokflag = ERROR_TOKEN_SEND; + ret = GSS_S_DEFECTIVE_TOKEN; + + /* + * According to RFC 4178, both supportedMech and negState must be + * present in the first acceptor token. However, some Java + * implementations include only a responseToken in the first + * NegTokenResp. In this case we can use sc->internal_mech as the + * negotiated mechanism. (We do not currently look at acc_negState + * when continuing with the optimistic mechanism.) + */ + if (supportedMech == GSS_C_NO_OID) + supportedMech = sc->internal_mech; + + /* + * If the mechanism we sent is not the mechanism returned from + * the server, we need to handle the server's counter + * proposal. There is a bug in SAMBA servers that always send + * the old Kerberos mech OID, even though we sent the new one. + * So we will treat all the Kerberos mech OIDS as the same. + */ + if (!(is_kerb_mech(supportedMech) && + is_kerb_mech(sc->internal_mech)) && + !g_OID_equal(supportedMech, sc->internal_mech)) { + ret = init_ctx_reselect(minor_status, sc, + acc_negState, supportedMech, + responseToken, mechListMIC, tokflag); + + } else if (*responseToken == GSS_C_NO_BUFFER) { + if (sc->mech_complete) { + /* + * Mech completed on first call to its + * init_sec_context(). Acceptor sends no mech + * token. + */ + *tokflag = NO_TOKEN_SEND; + ret = GSS_S_COMPLETE; + } else { + /* + * Reject missing mech token when optimistic + * mech selected. + */ + *minor_status = ERR_SPNEGO_NO_TOKEN_FROM_ACCEPTOR; + map_errcode(minor_status); + ret = GSS_S_DEFECTIVE_TOKEN; + } + } else if ((*responseToken)->length == 0 && sc->mech_complete) { + /* Handle old IIS servers returning empty token instead of + * null tokens in the non-mutual auth case. */ + *tokflag = NO_TOKEN_SEND; + ret = GSS_S_COMPLETE; + } else if (sc->mech_complete) { + /* Reject spurious mech token. */ + ret = GSS_S_DEFECTIVE_TOKEN; + } else { + *tokflag = CONT_TOKEN_SEND; + ret = GSS_S_COMPLETE; + } + sc->nego_done = 1; + return ret; +} + +/* + * Handle acceptor's counter-proposal of an alternative mechanism. + */ +static OM_uint32 +init_ctx_reselect(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc, + OM_uint32 acc_negState, gss_OID supportedMech, + gss_buffer_t *responseToken, gss_buffer_t *mechListMIC, + send_token_flag *tokflag) +{ + OM_uint32 tmpmin; + size_t i; + + gss_delete_sec_context(&tmpmin, &sc->ctx_handle, + GSS_C_NO_BUFFER); + + /* Find supportedMech in sc->mech_set. */ + for (i = 0; i < sc->mech_set->count; i++) { + if (g_OID_equal(supportedMech, &sc->mech_set->elements[i])) + break; + } + if (i == sc->mech_set->count) + return GSS_S_DEFECTIVE_TOKEN; + sc->internal_mech = &sc->mech_set->elements[i]; + + /* + * A server conforming to RFC4178 MUST set REQUEST_MIC here, but + * Windows Server 2003 and earlier implement (roughly) RFC2478 instead, + * and send ACCEPT_INCOMPLETE. Tolerate that only if we are falling + * back to NTLMSSP. + */ + if (acc_negState == ACCEPT_INCOMPLETE) { + if (!g_OID_equal(supportedMech, &gss_mech_ntlmssp_oid)) + return GSS_S_DEFECTIVE_TOKEN; + } else if (acc_negState != REQUEST_MIC) { + return GSS_S_DEFECTIVE_TOKEN; + } + + sc->mech_complete = 0; + sc->mic_reqd = (acc_negState == REQUEST_MIC); + *tokflag = CONT_TOKEN_SEND; + return GSS_S_COMPLETE; +} + +/* + * Wrap call to mechanism gss_init_sec_context() and update state + * accordingly. + */ +static OM_uint32 +init_ctx_call_init(OM_uint32 *minor_status, + spnego_gss_ctx_id_t sc, + spnego_gss_cred_id_t spcred, + OM_uint32 acc_negState, + gss_name_t target_name, + OM_uint32 req_flags, + OM_uint32 time_req, + gss_buffer_t mechtok_in, + gss_channel_bindings_t bindings, + gss_buffer_t mechtok_out, + OM_uint32 *time_rec, + send_token_flag *send_token) +{ + OM_uint32 ret, tmpret, tmpmin, mech_req_flags; + gss_cred_id_t mcred; + + mcred = (spcred == NULL) ? GSS_C_NO_CREDENTIAL : spcred->mcred; + + mech_req_flags = req_flags; + if (spcred == NULL || !spcred->no_ask_integ) + mech_req_flags |= GSS_C_INTEG_FLAG; + + if (gss_oid_equal(sc->internal_mech, &negoex_mech)) { + ret = negoex_init(minor_status, sc, mcred, target_name, + mech_req_flags, time_req, mechtok_in, + bindings, mechtok_out, time_rec); + } else { + ret = gss_init_sec_context(minor_status, mcred, + &sc->ctx_handle, target_name, + sc->internal_mech, mech_req_flags, + time_req, bindings, mechtok_in, + &sc->actual_mech, mechtok_out, + &sc->ctx_flags, time_rec); + } + + /* Bail out if the acceptor gave us an error token but the mech didn't + * see it as an error. */ + if (acc_negState == REJECT && !GSS_ERROR(ret)) { + ret = GSS_S_DEFECTIVE_TOKEN; + goto fail; + } + + if (ret == GSS_S_COMPLETE) { + sc->mech_complete = 1; + /* + * Microsoft SPNEGO implementations expect an even number of + * token exchanges. So if we're sending a final token, ask for + * a zero-length token back from the server. Also ask for a + * token back if this is the first token or if a MIC exchange + * is required. + */ + if (*send_token == CONT_TOKEN_SEND && + mechtok_out->length == 0 && + (!sc->mic_reqd || !(sc->ctx_flags & GSS_C_INTEG_FLAG))) + *send_token = NO_TOKEN_SEND; + + return GSS_S_COMPLETE; + } + + if (ret == GSS_S_CONTINUE_NEEDED) + return GSS_S_COMPLETE; + + if (*send_token != INIT_TOKEN_SEND) { + *send_token = ERROR_TOKEN_SEND; + return ret; + } + + /* + * Since this is the first token, we can fall back to later mechanisms + * in the list. Since the mechanism list is expected to be short, we + * can do this with recursion. If all mechanisms produce errors, the + * caller should get the error from the first mech in the list. + */ + gssalloc_free(sc->mech_set->elements->elements); + memmove(sc->mech_set->elements, sc->mech_set->elements + 1, + --sc->mech_set->count * sizeof(*sc->mech_set->elements)); + if (sc->mech_set->count == 0) + goto fail; + gss_release_buffer(&tmpmin, &sc->DER_mechTypes); + if (put_mech_set(sc->mech_set, &sc->DER_mechTypes) < 0) + goto fail; + gss_delete_sec_context(&tmpmin, &sc->ctx_handle, GSS_C_NO_BUFFER); + tmpret = init_ctx_call_init(&tmpmin, sc, spcred, acc_negState, + target_name, req_flags, time_req, + mechtok_in, bindings, mechtok_out, + time_rec, send_token); + if (HARD_ERROR(tmpret)) + goto fail; + *minor_status = tmpmin; + return tmpret; + +fail: + /* Don't output token on error from first call. */ + *send_token = NO_TOKEN_SEND; + return ret; +} + +/*ARGSUSED*/ +OM_uint32 KRB5_CALLCONV +spnego_gss_init_sec_context( + OM_uint32 *minor_status, + gss_cred_id_t claimant_cred_handle, + gss_ctx_id_t *context_handle, + gss_name_t target_name, + gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + gss_channel_bindings_t bindings, + gss_buffer_t input_token, + gss_OID *actual_mech, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec) +{ + send_token_flag send_token = NO_TOKEN_SEND; + OM_uint32 tmpmin, ret, negState = UNSPECIFIED, acc_negState; + gss_buffer_t mechtok_in, mechListMIC_in, mechListMIC_out; + gss_buffer_desc mechtok_out = GSS_C_EMPTY_BUFFER; + spnego_gss_cred_id_t spcred = NULL; + spnego_gss_ctx_id_t spnego_ctx = NULL; + + dsyslog("Entering init_sec_context\n"); + + mechtok_in = mechListMIC_out = mechListMIC_in = GSS_C_NO_BUFFER; + + /* + * This function works in three steps: + * + * 1. Perform mechanism negotiation. + * 2. Invoke the negotiated or optimistic mech's gss_init_sec_context + * function and examine the results. + * 3. Process or generate MICs if necessary. + * + * The three steps share responsibility for determining when the + * exchange is complete. If the selected mech completed in a previous + * call and no MIC exchange is expected, then step 1 will decide. If + * the selected mech completes in this call and no MIC exchange is + * expected, then step 2 will decide. If a MIC exchange is expected, + * then step 3 will decide. If an error occurs in any step, the + * exchange will be aborted, possibly with an error token. + * + * negState determines the state of the negotiation, and is + * communicated to the acceptor if a continuing token is sent. + * send_token is used to indicate what type of token, if any, should be + * generated. + */ + + /* Validate arguments. */ + if (minor_status != NULL) + *minor_status = 0; + if (output_token != GSS_C_NO_BUFFER) { + output_token->length = 0; + output_token->value = NULL; + } + if (minor_status == NULL || + output_token == GSS_C_NO_BUFFER || + context_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (actual_mech != NULL) + *actual_mech = GSS_C_NO_OID; + if (time_rec != NULL) + *time_rec = 0; + + /* Step 1: perform mechanism negotiation. */ + spcred = (spnego_gss_cred_id_t)claimant_cred_handle; + spnego_ctx = (spnego_gss_ctx_id_t)*context_handle; + if (spnego_ctx == NULL) { + ret = init_ctx_new(minor_status, spcred, &send_token, + &spnego_ctx); + if (ret != GSS_S_COMPLETE) + goto cleanup; + *context_handle = (gss_ctx_id_t)spnego_ctx; + acc_negState = UNSPECIFIED; + } else { + ret = init_ctx_cont(minor_status, spnego_ctx, input_token, + &mechtok_in, &mechListMIC_in, + &acc_negState, &send_token); + if (ret != GSS_S_COMPLETE) + goto cleanup; + } + + /* Step 2: invoke the selected or optimistic mechanism's + * gss_init_sec_context function, if it didn't complete previously. */ + if (!spnego_ctx->mech_complete) { + ret = init_ctx_call_init(minor_status, spnego_ctx, spcred, + acc_negState, target_name, req_flags, + time_req, mechtok_in, bindings, + &mechtok_out, time_rec, &send_token); + if (ret != GSS_S_COMPLETE) + goto cleanup; + + /* Give the mechanism a chance to force a mechlistMIC. */ + if (mech_requires_mechlistMIC(spnego_ctx)) + spnego_ctx->mic_reqd = 1; + } + + /* Step 3: process or generate the MIC, if the negotiated mech is + * complete and supports MICs. Also decide the outgoing negState. */ + negState = ACCEPT_INCOMPLETE; + if (spnego_ctx->mech_complete && + (spnego_ctx->ctx_flags & GSS_C_INTEG_FLAG)) { + + ret = handle_mic(minor_status, + mechListMIC_in, + (mechtok_out.length != 0), + spnego_ctx, &mechListMIC_out, + &negState, &send_token); + if (HARD_ERROR(ret)) + goto cleanup; + } + + if (ret_flags != NULL) + *ret_flags = spnego_ctx->ctx_flags & ~GSS_C_PROT_READY_FLAG; + + ret = (send_token == NO_TOKEN_SEND || negState == ACCEPT_COMPLETE) ? + GSS_S_COMPLETE : GSS_S_CONTINUE_NEEDED; + +cleanup: + if (send_token == INIT_TOKEN_SEND) { + if (make_spnego_tokenInit_msg(spnego_ctx, + 0, + mechListMIC_out, + req_flags, + &mechtok_out, send_token, + output_token) < 0) { + ret = GSS_S_FAILURE; + } + } else if (send_token != NO_TOKEN_SEND) { + if (send_token == ERROR_TOKEN_SEND) + negState = REJECT; + if (make_spnego_tokenTarg_msg(negState, GSS_C_NO_OID, + &mechtok_out, mechListMIC_out, + send_token, + output_token) < 0) { + ret = GSS_S_FAILURE; + } + } + gss_release_buffer(&tmpmin, &mechtok_out); + if (ret == GSS_S_COMPLETE) { + spnego_ctx->opened = 1; + if (actual_mech != NULL) + *actual_mech = spnego_ctx->actual_mech; + /* Get an updated lifetime if we didn't call into the mech. */ + if (time_rec != NULL && *time_rec == 0) { + (void) gss_context_time(&tmpmin, + spnego_ctx->ctx_handle, + time_rec); + } + } else if (ret != GSS_S_CONTINUE_NEEDED) { + if (spnego_ctx != NULL) { + gss_delete_sec_context(&tmpmin, + &spnego_ctx->ctx_handle, + GSS_C_NO_BUFFER); + release_spnego_ctx(&spnego_ctx); + } + *context_handle = GSS_C_NO_CONTEXT; + } + if (mechtok_in != GSS_C_NO_BUFFER) { + gss_release_buffer(&tmpmin, mechtok_in); + free(mechtok_in); + } + if (mechListMIC_in != GSS_C_NO_BUFFER) { + gss_release_buffer(&tmpmin, mechListMIC_in); + free(mechListMIC_in); + } + if (mechListMIC_out != GSS_C_NO_BUFFER) { + gss_release_buffer(&tmpmin, mechListMIC_out); + free(mechListMIC_out); + } + return ret; +} /* init_sec_context */ + +/* We don't want to import KRB5 headers here */ +static const gss_OID_desc gss_mech_krb5_oid = + { 9, "\052\206\110\206\367\022\001\002\002" }; +static const gss_OID_desc gss_mech_krb5_wrong_oid = + { 9, "\052\206\110\202\367\022\001\002\002" }; + +/* + * NegHints ::= SEQUENCE { + * hintName [0] GeneralString OPTIONAL, + * hintAddress [1] OCTET STRING OPTIONAL + * } + */ + +#define HOST_PREFIX "host@" +#define HOST_PREFIX_LEN (sizeof(HOST_PREFIX) - 1) + +/* Encode the dummy hintname string (as specified in [MS-SPNG]) into a + * DER-encoded [0] tagged GeneralString, and place the result in *outbuf. */ +static int +make_NegHints(OM_uint32 *minor_status, gss_buffer_t *outbuf) +{ + OM_uint32 major_status; + size_t hint_len, tlen; + uint8_t *t; + const char *hintname = "not_defined_in_RFC4178@please_ignore"; + const size_t hintname_len = strlen(hintname); + struct k5buf buf; + + *outbuf = GSS_C_NO_BUFFER; + major_status = GSS_S_FAILURE; + + hint_len = k5_der_value_len(hintname_len); + tlen = k5_der_value_len(hint_len); + + t = gssalloc_malloc(tlen); + if (t == NULL) { + *minor_status = ENOMEM; + goto errout; + } + k5_buf_init_fixed(&buf, t, tlen); + + k5_der_add_taglen(&buf, CONTEXT | 0x00, hint_len); + k5_der_add_value(&buf, GENERAL_STRING, hintname, hintname_len); + assert(buf.len == tlen); + + *outbuf = (gss_buffer_t)malloc(sizeof(gss_buffer_desc)); + if (*outbuf == NULL) { + *minor_status = ENOMEM; + goto errout; + } + (*outbuf)->value = (void *)t; + (*outbuf)->length = tlen; + + t = NULL; /* don't free */ + + *minor_status = 0; + major_status = GSS_S_COMPLETE; + +errout: + if (t != NULL) { + free(t); + } + + return (major_status); +} + +/* + * Create a new SPNEGO context handle for the initial call to + * spnego_gss_accept_sec_context() when the request is empty. For empty + * requests, we implement the Microsoft NegHints extension to SPNEGO for + * compatibility with some versions of Samba. See: + * https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-spng/8e71cf53-e867-4b79-b5b5-38c92be3d472 + */ +static OM_uint32 +acc_ctx_hints(OM_uint32 *minor_status, + spnego_gss_cred_id_t spcred, + gss_buffer_t *mechListMIC, + OM_uint32 *negState, + send_token_flag *return_token, + spnego_gss_ctx_id_t *sc_out) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = NULL; + + *mechListMIC = GSS_C_NO_BUFFER; + *return_token = NO_TOKEN_SEND; + *negState = REJECT; + *minor_status = 0; + *sc_out = NULL; + + ret = make_NegHints(minor_status, mechListMIC); + if (ret != GSS_S_COMPLETE) + goto cleanup; + + sc = create_spnego_ctx(0); + if (sc == NULL) { + ret = GSS_S_FAILURE; + goto cleanup; + } + + ret = get_negotiable_mechs(minor_status, sc, spcred, GSS_C_ACCEPT); + if (ret != GSS_S_COMPLETE) + goto cleanup; + + if (put_mech_set(sc->mech_set, &sc->DER_mechTypes) < 0) { + ret = GSS_S_FAILURE; + goto cleanup; + } + sc->internal_mech = GSS_C_NO_OID; + + *negState = ACCEPT_INCOMPLETE; + *return_token = INIT_TOKEN_SEND; + sc->firstpass = 1; + *sc_out = sc; + sc = NULL; + ret = GSS_S_COMPLETE; + +cleanup: + release_spnego_ctx(&sc); + + return ret; +} + +/* + * Create a new SPNEGO context handle for the initial call to + * spnego_gss_accept_sec_context(). Set negState to REJECT if the token is + * defective, else ACCEPT_INCOMPLETE or REQUEST_MIC, depending on whether + * the initiator's preferred mechanism is supported. + */ +static OM_uint32 +acc_ctx_new(OM_uint32 *minor_status, + gss_buffer_t buf, + spnego_gss_cred_id_t spcred, + gss_buffer_t *mechToken, + gss_buffer_t *mechListMIC, + OM_uint32 *negState, + send_token_flag *return_token, + spnego_gss_ctx_id_t *sc_out) +{ + OM_uint32 tmpmin, ret, req_flags; + gss_OID_set mechTypes; + gss_buffer_desc der_mechTypes; + gss_OID mech_wanted; + spnego_gss_ctx_id_t sc = NULL; + + ret = GSS_S_DEFECTIVE_TOKEN; + der_mechTypes.length = 0; + der_mechTypes.value = NULL; + *mechToken = *mechListMIC = GSS_C_NO_BUFFER; + mechTypes = GSS_C_NO_OID_SET; + *return_token = ERROR_TOKEN_SEND; + *negState = REJECT; + *minor_status = 0; + + ret = get_negTokenInit(minor_status, buf, &der_mechTypes, + &mechTypes, &req_flags, + mechToken, mechListMIC); + if (ret != GSS_S_COMPLETE) { + goto cleanup; + } + + sc = create_spnego_ctx(0); + if (sc == NULL) { + ret = GSS_S_FAILURE; + *return_token = NO_TOKEN_SEND; + goto cleanup; + } + + ret = get_negotiable_mechs(minor_status, sc, spcred, GSS_C_ACCEPT); + if (ret != GSS_S_COMPLETE) { + *return_token = NO_TOKEN_SEND; + goto cleanup; + } + /* + * Select the best match between the list of mechs + * that the initiator requested and the list that + * the acceptor will support. + */ + mech_wanted = negotiate_mech(sc, mechTypes, negState); + if (*negState == REJECT) { + ret = GSS_S_BAD_MECH; + goto cleanup; + } + + sc->internal_mech = mech_wanted; + sc->DER_mechTypes = der_mechTypes; + der_mechTypes.length = 0; + der_mechTypes.value = NULL; + + if (*negState == REQUEST_MIC) + sc->mic_reqd = 1; + + *return_token = INIT_TOKEN_SEND; + sc->firstpass = 1; + *sc_out = sc; + sc = NULL; + ret = GSS_S_COMPLETE; + +cleanup: + release_spnego_ctx(&sc); + gss_release_oid_set(&tmpmin, &mechTypes); + if (der_mechTypes.length != 0) + gss_release_buffer(&tmpmin, &der_mechTypes); + + return ret; +} + +static OM_uint32 +acc_ctx_cont(OM_uint32 *minstat, + gss_buffer_t buf, + spnego_gss_ctx_id_t sc, + gss_buffer_t *responseToken, + gss_buffer_t *mechListMIC, + OM_uint32 *negState, + send_token_flag *return_token) +{ + OM_uint32 ret, tmpmin; + gss_OID supportedMech; + struct k5input in; + + ret = GSS_S_DEFECTIVE_TOKEN; + *negState = REJECT; + *minstat = 0; + supportedMech = GSS_C_NO_OID; + *return_token = ERROR_TOKEN_SEND; + *responseToken = *mechListMIC = GSS_C_NO_BUFFER; + + k5_input_init(&in, buf->value, buf->length); + + /* Attempt to work with old Sun SPNEGO. */ + if (in.len > 0 && *in.ptr == HEADER_ID) { + ret = verify_token_header(&in, gss_mech_spnego); + if (ret) { + *minstat = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + } + + ret = get_negTokenResp(minstat, &in, negState, &supportedMech, + responseToken, mechListMIC); + if (ret != GSS_S_COMPLETE) + goto cleanup; + + if (*responseToken == GSS_C_NO_BUFFER && + *mechListMIC == GSS_C_NO_BUFFER) { + + ret = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + if (supportedMech != GSS_C_NO_OID) { + ret = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + } + sc->firstpass = 0; + *negState = ACCEPT_INCOMPLETE; + *return_token = CONT_TOKEN_SEND; +cleanup: + if (supportedMech != GSS_C_NO_OID) { + generic_gss_release_oid(&tmpmin, &supportedMech); + } + return ret; +} + +/* + * Verify that mech OID is either exactly the same as the negotiated + * mech OID, or is a mech OID supported by the negotiated mech. MS + * implementations can list a most preferred mech using an incorrect + * krb5 OID while emitting a krb5 initiator mech token having the + * correct krb5 mech OID. + */ +static OM_uint32 +acc_ctx_vfy_oid(OM_uint32 *minor_status, + spnego_gss_ctx_id_t sc, gss_OID mechoid, + OM_uint32 *negState, send_token_flag *tokflag) +{ + OM_uint32 ret, tmpmin; + gss_mechanism mech = NULL; + gss_OID_set mech_set = GSS_C_NO_OID_SET; + int present = 0; + + if (g_OID_equal(sc->internal_mech, mechoid)) + return GSS_S_COMPLETE; + + mech = gssint_get_mechanism(sc->internal_mech); + if (mech == NULL || mech->gss_indicate_mechs == NULL) { + *minor_status = ERR_SPNEGO_NEGOTIATION_FAILED; + map_errcode(minor_status); + *negState = REJECT; + *tokflag = ERROR_TOKEN_SEND; + return GSS_S_BAD_MECH; + } + ret = mech->gss_indicate_mechs(minor_status, &mech_set); + if (ret != GSS_S_COMPLETE) { + *tokflag = NO_TOKEN_SEND; + map_error(minor_status, mech); + goto cleanup; + } + ret = gss_test_oid_set_member(minor_status, mechoid, + mech_set, &present); + if (ret != GSS_S_COMPLETE) + goto cleanup; + if (!present) { + *minor_status = ERR_SPNEGO_NEGOTIATION_FAILED; + map_errcode(minor_status); + *negState = REJECT; + *tokflag = ERROR_TOKEN_SEND; + ret = GSS_S_BAD_MECH; + } +cleanup: + gss_release_oid_set(&tmpmin, &mech_set); + return ret; +} +#ifndef LEAN_CLIENT +/* + * Wrap call to gss_accept_sec_context() and update state + * accordingly. + */ +static OM_uint32 +acc_ctx_call_acc(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc, + spnego_gss_cred_id_t spcred, gss_buffer_t mechtok_in, + gss_channel_bindings_t bindings, gss_buffer_t mechtok_out, + OM_uint32 *time_rec, OM_uint32 *negState, + send_token_flag *tokflag) +{ + OM_uint32 ret, tmpmin; + gss_OID_desc mechoid; + gss_cred_id_t mcred; + int negoex = gss_oid_equal(sc->internal_mech, &negoex_mech); + + if (sc->ctx_handle == GSS_C_NO_CONTEXT && !negoex) { + /* + * mechoid is an alias; don't free it. + */ + ret = gssint_get_mech_type(&mechoid, mechtok_in); + if (ret != GSS_S_COMPLETE) { + *tokflag = NO_TOKEN_SEND; + return ret; + } + ret = acc_ctx_vfy_oid(minor_status, sc, &mechoid, + negState, tokflag); + if (ret != GSS_S_COMPLETE) + return ret; + } + + mcred = (spcred == NULL) ? GSS_C_NO_CREDENTIAL : spcred->mcred; + if (negoex) { + ret = negoex_accept(minor_status, sc, mcred, mechtok_in, + bindings, mechtok_out, time_rec); + } else { + (void) gss_release_name(&tmpmin, &sc->internal_name); + (void) gss_release_cred(&tmpmin, &sc->deleg_cred); + ret = gss_accept_sec_context(minor_status, &sc->ctx_handle, + mcred, mechtok_in, bindings, + &sc->internal_name, + &sc->actual_mech, mechtok_out, + &sc->ctx_flags, time_rec, + &sc->deleg_cred); + } + if (ret == GSS_S_COMPLETE) { +#ifdef MS_BUG_TEST + /* + * Force MIC to be not required even if we previously + * requested a MIC. + */ + char *envstr = getenv("MS_FORCE_NO_MIC"); + + if (envstr != NULL && strcmp(envstr, "1") == 0 && + !(sc->ctx_flags & GSS_C_MUTUAL_FLAG) && + sc->mic_reqd) { + + sc->mic_reqd = 0; + } +#endif + sc->mech_complete = 1; + + if (!sc->mic_reqd || + !(sc->ctx_flags & GSS_C_INTEG_FLAG)) { + /* No MIC exchange required, so we're done. */ + *negState = ACCEPT_COMPLETE; + ret = GSS_S_COMPLETE; + } else { + /* handle_mic will decide if we're done. */ + ret = GSS_S_CONTINUE_NEEDED; + } + } else if (ret != GSS_S_CONTINUE_NEEDED) { + *negState = REJECT; + *tokflag = ERROR_TOKEN_SEND; + } + return ret; +} + +/*ARGSUSED*/ +OM_uint32 KRB5_CALLCONV +spnego_gss_accept_sec_context( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_cred_id_t verifier_cred_handle, + gss_buffer_t input_token, + gss_channel_bindings_t bindings, + gss_name_t *src_name, + gss_OID *mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec, + gss_cred_id_t *delegated_cred_handle) +{ + OM_uint32 ret, tmpmin, negState; + send_token_flag return_token; + gss_buffer_t mechtok_in, mic_in, mic_out; + gss_buffer_desc mechtok_out = GSS_C_EMPTY_BUFFER; + spnego_gss_ctx_id_t sc = NULL; + spnego_gss_cred_id_t spcred = NULL; + int sendTokenInit = 0, tmpret; + + mechtok_in = mic_in = mic_out = GSS_C_NO_BUFFER; + + /* + * This function works in three steps: + * + * 1. Perform mechanism negotiation. + * 2. Invoke the negotiated mech's gss_accept_sec_context function + * and examine the results. + * 3. Process or generate MICs if necessary. + * + * Step one determines whether the negotiation requires a MIC exchange, + * while steps two and three share responsibility for determining when + * the exchange is complete. If the selected mech completes in this + * call and no MIC exchange is expected, then step 2 will decide. If a + * MIC exchange is expected, then step 3 will decide. If an error + * occurs in any step, the exchange will be aborted, possibly with an + * error token. + * + * negState determines the state of the negotiation, and is + * communicated to the acceptor if a continuing token is sent. + * return_token is used to indicate what type of token, if any, should + * be generated. + */ + + /* Validate arguments. */ + if (minor_status != NULL) + *minor_status = 0; + if (output_token != GSS_C_NO_BUFFER) { + output_token->length = 0; + output_token->value = NULL; + } + if (src_name != NULL) + *src_name = GSS_C_NO_NAME; + if (mech_type != NULL) + *mech_type = GSS_C_NO_OID; + if (time_rec != NULL) + *time_rec = 0; + if (ret_flags != NULL) + *ret_flags = 0; + if (delegated_cred_handle != NULL) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + + if (minor_status == NULL || + output_token == GSS_C_NO_BUFFER || + context_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_WRITE; + + if (input_token == GSS_C_NO_BUFFER) + return GSS_S_CALL_INACCESSIBLE_READ; + + /* Step 1: Perform mechanism negotiation. */ + sc = (spnego_gss_ctx_id_t)*context_handle; + spcred = (spnego_gss_cred_id_t)verifier_cred_handle; + if (sc == NULL && input_token->length == 0) { + /* Process a request for NegHints. */ + ret = acc_ctx_hints(minor_status, spcred, &mic_out, &negState, + &return_token, &sc); + if (ret != GSS_S_COMPLETE) + goto cleanup; + *context_handle = (gss_ctx_id_t)sc; + sendTokenInit = 1; + ret = GSS_S_CONTINUE_NEEDED; + } else if (sc == NULL || sc->internal_mech == GSS_C_NO_OID) { + if (sc != NULL) { + /* Discard the context from the NegHints request. */ + release_spnego_ctx(&sc); + *context_handle = GSS_C_NO_CONTEXT; + } + /* Process an initial token; can set negState to + * REQUEST_MIC. */ + ret = acc_ctx_new(minor_status, input_token, spcred, + &mechtok_in, &mic_in, &negState, + &return_token, &sc); + if (ret != GSS_S_COMPLETE) + goto cleanup; + *context_handle = (gss_ctx_id_t)sc; + ret = GSS_S_CONTINUE_NEEDED; + } else { + /* Process a response token. Can set negState to + * ACCEPT_INCOMPLETE. */ + ret = acc_ctx_cont(minor_status, input_token, sc, &mechtok_in, + &mic_in, &negState, &return_token); + if (ret != GSS_S_COMPLETE) + goto cleanup; + ret = GSS_S_CONTINUE_NEEDED; + } + + /* Step 2: invoke the negotiated mechanism's gss_accept_sec_context + * function. */ + /* + * Handle mechtok_in and mic_in only if they are + * present in input_token. If neither is present, whether + * this is an error depends on whether this is the first + * round-trip. RET is set to a default value according to + * whether it is the first round-trip. + */ + if (negState != REQUEST_MIC && mechtok_in != GSS_C_NO_BUFFER) { + ret = acc_ctx_call_acc(minor_status, sc, spcred, mechtok_in, + bindings, &mechtok_out, time_rec, + &negState, &return_token); + } + + /* Step 3: process or generate the MIC, if the negotiated mech is + * complete and supports MICs. */ + if (!HARD_ERROR(ret) && sc->mech_complete && + (sc->ctx_flags & GSS_C_INTEG_FLAG)) { + + ret = handle_mic(minor_status, mic_in, + (mechtok_out.length != 0), + sc, &mic_out, + &negState, &return_token); + } + + if (!HARD_ERROR(ret) && ret_flags != NULL) + *ret_flags = sc->ctx_flags & ~GSS_C_PROT_READY_FLAG; + +cleanup: + if (return_token == INIT_TOKEN_SEND && sendTokenInit) { + assert(sc != NULL); + tmpret = make_spnego_tokenInit_msg(sc, 1, mic_out, 0, + GSS_C_NO_BUFFER, + return_token, output_token); + if (tmpret < 0) + ret = GSS_S_FAILURE; + } else if (return_token != NO_TOKEN_SEND && + return_token != CHECK_MIC) { + tmpret = make_spnego_tokenTarg_msg(negState, + sc ? sc->internal_mech : + GSS_C_NO_OID, + &mechtok_out, mic_out, + return_token, + output_token); + if (tmpret < 0) + ret = GSS_S_FAILURE; + } + if (ret == GSS_S_COMPLETE) { + sc->opened = 1; + if (sc->internal_name != GSS_C_NO_NAME && + src_name != NULL) { + *src_name = sc->internal_name; + sc->internal_name = GSS_C_NO_NAME; + } + if (mech_type != NULL) + *mech_type = sc->actual_mech; + /* Get an updated lifetime if we didn't call into the mech. */ + if (time_rec != NULL && *time_rec == 0) { + (void) gss_context_time(&tmpmin, sc->ctx_handle, + time_rec); + } + if (delegated_cred_handle != NULL) { + *delegated_cred_handle = sc->deleg_cred; + sc->deleg_cred = GSS_C_NO_CREDENTIAL; + } + } else if (ret != GSS_S_CONTINUE_NEEDED) { + if (sc != NULL) { + gss_delete_sec_context(&tmpmin, &sc->ctx_handle, + GSS_C_NO_BUFFER); + release_spnego_ctx(&sc); + } + *context_handle = GSS_C_NO_CONTEXT; + } + gss_release_buffer(&tmpmin, &mechtok_out); + if (mechtok_in != GSS_C_NO_BUFFER) { + gss_release_buffer(&tmpmin, mechtok_in); + free(mechtok_in); + } + if (mic_in != GSS_C_NO_BUFFER) { + gss_release_buffer(&tmpmin, mic_in); + free(mic_in); + } + if (mic_out != GSS_C_NO_BUFFER) { + gss_release_buffer(&tmpmin, mic_out); + free(mic_out); + } + return ret; +} +#endif /* LEAN_CLIENT */ + +static struct { + OM_uint32 status; + const char *msg; +} msg_table[] = { + { ERR_SPNEGO_NO_MECHS_AVAILABLE, + N_("SPNEGO cannot find mechanisms to negotiate") }, + { ERR_SPNEGO_NO_CREDS_ACQUIRED, + N_("SPNEGO failed to acquire creds") }, + { ERR_SPNEGO_NO_MECH_FROM_ACCEPTOR, + N_("SPNEGO acceptor did not select a mechanism") }, + { ERR_SPNEGO_NEGOTIATION_FAILED, + N_("SPNEGO failed to negotiate a mechanism") }, + { ERR_SPNEGO_NO_TOKEN_FROM_ACCEPTOR, + N_("SPNEGO acceptor did not return a valid token") }, + { ERR_NEGOEX_INVALID_MESSAGE_SIGNATURE, + N_("Invalid NegoEx signature") }, + { ERR_NEGOEX_INVALID_MESSAGE_TYPE, + N_("Invalid NegoEx message type") }, + { ERR_NEGOEX_INVALID_MESSAGE_SIZE, + N_("Invalid NegoEx message size") }, + { ERR_NEGOEX_INVALID_CONVERSATION_ID, + N_("Invalid NegoEx conversation ID") }, + { ERR_NEGOEX_AUTH_SCHEME_NOT_FOUND, + N_("NegoEx authentication scheme not found") }, + { ERR_NEGOEX_MISSING_NEGO_MESSAGE, + N_("Missing NegoEx negotiate message") }, + { ERR_NEGOEX_MISSING_AP_REQUEST_MESSAGE, + N_("Missing NegoEx authentication protocol request message") }, + { ERR_NEGOEX_NO_AVAILABLE_MECHS, + N_("No mutually supported NegoEx authentication schemes") }, + { ERR_NEGOEX_NO_VERIFY_KEY, + N_("No NegoEx verify key") }, + { ERR_NEGOEX_UNKNOWN_CHECKSUM_SCHEME, + N_("Unknown NegoEx checksum scheme") }, + { ERR_NEGOEX_INVALID_CHECKSUM, + N_("Invalid NegoEx checksum") }, + { ERR_NEGOEX_UNSUPPORTED_CRITICAL_EXTENSION, + N_("Unsupported critical NegoEx extension") }, + { ERR_NEGOEX_UNSUPPORTED_VERSION, + N_("Unsupported NegoEx version") }, + { ERR_NEGOEX_MESSAGE_OUT_OF_SEQUENCE, + N_("NegoEx message out of sequence") }, +}; + +/*ARGSUSED*/ +OM_uint32 KRB5_CALLCONV +spnego_gss_display_status( + OM_uint32 *minor_status, + OM_uint32 status_value, + int status_type, + gss_OID mech_type, + OM_uint32 *message_context, + gss_buffer_t status_string) +{ + OM_uint32 maj = GSS_S_COMPLETE; + const char *msg; + size_t i; + int ret; + + *message_context = 0; + for (i = 0; i < sizeof(msg_table) / sizeof(*msg_table); i++) { + if (status_value == msg_table[i].status) { + msg = dgettext(KRB5_TEXTDOMAIN, msg_table[i].msg); + *status_string = make_err_msg(msg); + return GSS_S_COMPLETE; + } + } + + /* Not one of our minor codes; might be from a mech. Call back + * to gss_display_status, but first check for recursion. */ + if (k5_getspecific(K5_KEY_GSS_SPNEGO_STATUS) != NULL) { + /* Perhaps we returned a com_err code like ENOMEM. */ + const char *err = error_message(status_value); + *status_string = make_err_msg(err); + return GSS_S_COMPLETE; + } + /* Set a non-null pointer value; doesn't matter which one. */ + ret = k5_setspecific(K5_KEY_GSS_SPNEGO_STATUS, &ret); + if (ret != 0) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + maj = gss_display_status(minor_status, status_value, + status_type, mech_type, + message_context, status_string); + /* This is unlikely to fail; not much we can do if it does. */ + (void)k5_setspecific(K5_KEY_GSS_SPNEGO_STATUS, NULL); + + return maj; +} + + +/*ARGSUSED*/ +OM_uint32 KRB5_CALLCONV +spnego_gss_import_name( + OM_uint32 *minor_status, + gss_buffer_t input_name_buffer, + gss_OID input_name_type, + gss_name_t *output_name) +{ + OM_uint32 status; + + dsyslog("Entering import_name\n"); + + status = gss_import_name(minor_status, input_name_buffer, + input_name_type, output_name); + + dsyslog("Leaving import_name\n"); + return (status); +} + +/*ARGSUSED*/ +OM_uint32 KRB5_CALLCONV +spnego_gss_release_name( + OM_uint32 *minor_status, + gss_name_t *input_name) +{ + OM_uint32 status; + + dsyslog("Entering release_name\n"); + + status = gss_release_name(minor_status, input_name); + + dsyslog("Leaving release_name\n"); + return (status); +} + +/*ARGSUSED*/ +OM_uint32 KRB5_CALLCONV +spnego_gss_duplicate_name( + OM_uint32 *minor_status, + const gss_name_t input_name, + gss_name_t *output_name) +{ + OM_uint32 status; + + dsyslog("Entering duplicate_name\n"); + + status = gss_duplicate_name(minor_status, input_name, output_name); + + dsyslog("Leaving duplicate_name\n"); + return (status); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_cred( + OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + gss_name_t *name, + OM_uint32 *lifetime, + int *cred_usage, + gss_OID_set *mechanisms) +{ + OM_uint32 status; + spnego_gss_cred_id_t spcred = NULL; + gss_cred_id_t creds = GSS_C_NO_CREDENTIAL; + OM_uint32 tmp_minor_status; + OM_uint32 initiator_lifetime, acceptor_lifetime; + + dsyslog("Entering inquire_cred\n"); + + /* + * To avoid infinite recursion, if GSS_C_NO_CREDENTIAL is + * supplied we call gss_inquire_cred_by_mech() on the + * first non-SPNEGO mechanism. + */ + spcred = (spnego_gss_cred_id_t)cred_handle; + if (spcred == NULL) { + status = get_available_mechs(minor_status, + GSS_C_NO_NAME, + GSS_C_BOTH, + GSS_C_NO_CRED_STORE, + &creds, + mechanisms, NULL); + if (status != GSS_S_COMPLETE) { + dsyslog("Leaving inquire_cred\n"); + return (status); + } + + if ((*mechanisms)->count == 0) { + gss_release_cred(&tmp_minor_status, &creds); + gss_release_oid_set(&tmp_minor_status, mechanisms); + dsyslog("Leaving inquire_cred\n"); + return (GSS_S_DEFECTIVE_CREDENTIAL); + } + + assert((*mechanisms)->elements != NULL); + + status = gss_inquire_cred_by_mech(minor_status, + creds, + &(*mechanisms)->elements[0], + name, + &initiator_lifetime, + &acceptor_lifetime, + cred_usage); + if (status != GSS_S_COMPLETE) { + gss_release_cred(&tmp_minor_status, &creds); + dsyslog("Leaving inquire_cred\n"); + return (status); + } + + if (lifetime != NULL) + *lifetime = (*cred_usage == GSS_C_ACCEPT) ? + acceptor_lifetime : initiator_lifetime; + + gss_release_cred(&tmp_minor_status, &creds); + } else { + status = gss_inquire_cred(minor_status, spcred->mcred, + name, lifetime, + cred_usage, mechanisms); + } + + dsyslog("Leaving inquire_cred\n"); + + return (status); +} + +/*ARGSUSED*/ +OM_uint32 KRB5_CALLCONV +spnego_gss_compare_name( + OM_uint32 *minor_status, + const gss_name_t name1, + const gss_name_t name2, + int *name_equal) +{ + OM_uint32 status = GSS_S_COMPLETE; + dsyslog("Entering compare_name\n"); + + status = gss_compare_name(minor_status, name1, name2, name_equal); + + dsyslog("Leaving compare_name\n"); + return (status); +} + +/*ARGSUSED*/ +/*ARGSUSED*/ +OM_uint32 KRB5_CALLCONV +spnego_gss_display_name( + OM_uint32 *minor_status, + gss_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID *output_name_type) +{ + OM_uint32 status = GSS_S_COMPLETE; + dsyslog("Entering display_name\n"); + + status = gss_display_name(minor_status, input_name, + output_name_buffer, output_name_type); + + dsyslog("Leaving display_name\n"); + return (status); +} + + +/*ARGSUSED*/ +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_names_for_mech( + OM_uint32 *minor_status, + gss_OID mechanism, + gss_OID_set *name_types) +{ + OM_uint32 major, minor; + + dsyslog("Entering inquire_names_for_mech\n"); + /* + * We only know how to handle our own mechanism. + */ + if ((mechanism != GSS_C_NULL_OID) && + !g_OID_equal(gss_mech_spnego, mechanism)) { + *minor_status = 0; + return (GSS_S_FAILURE); + } + + major = gss_create_empty_oid_set(minor_status, name_types); + if (major == GSS_S_COMPLETE) { + /* Now add our members. */ + if (((major = gss_add_oid_set_member(minor_status, + (gss_OID) GSS_C_NT_USER_NAME, + name_types)) == GSS_S_COMPLETE) && + ((major = gss_add_oid_set_member(minor_status, + (gss_OID) GSS_C_NT_MACHINE_UID_NAME, + name_types)) == GSS_S_COMPLETE) && + ((major = gss_add_oid_set_member(minor_status, + (gss_OID) GSS_C_NT_STRING_UID_NAME, + name_types)) == GSS_S_COMPLETE)) { + major = gss_add_oid_set_member(minor_status, + (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, + name_types); + } + + if (major != GSS_S_COMPLETE) + (void) gss_release_oid_set(&minor, name_types); + } + + dsyslog("Leaving inquire_names_for_mech\n"); + return (major); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_unwrap( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + ret = gss_unwrap(minor_status, + sc->ctx_handle, + input_message_buffer, + output_message_buffer, + conf_state, + qop_state); + + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_wrap( + OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_message_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + ret = gss_wrap(minor_status, + sc->ctx_handle, + conf_req_flag, + qop_req, + input_message_buffer, + conf_state, + output_message_buffer); + + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_process_context_token( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_buffer) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + /* SPNEGO doesn't have its own context tokens. */ + if (!sc->opened) + return (GSS_S_DEFECTIVE_TOKEN); + + ret = gss_process_context_token(minor_status, + sc->ctx_handle, + token_buffer); + + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_delete_sec_context( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token) +{ + OM_uint32 ret = GSS_S_COMPLETE; + spnego_gss_ctx_id_t *ctx = + (spnego_gss_ctx_id_t *)context_handle; + + *minor_status = 0; + + if (context_handle == NULL) + return (GSS_S_FAILURE); + + if (*ctx == NULL) + return (GSS_S_COMPLETE); + + (void) gss_delete_sec_context(minor_status, &(*ctx)->ctx_handle, + output_token); + (void) release_spnego_ctx(ctx); + + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_context_time( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + OM_uint32 *time_rec) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + ret = gss_context_time(minor_status, + sc->ctx_handle, + time_rec); + return (ret); +} +#ifndef LEAN_CLIENT +OM_uint32 KRB5_CALLCONV +spnego_gss_export_sec_context( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t interprocess_token) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = *(spnego_gss_ctx_id_t *)context_handle; + + /* We don't currently support exporting partially established + * contexts. */ + if (!sc->opened) + return GSS_S_UNAVAILABLE; + + ret = gss_export_sec_context(minor_status, + &sc->ctx_handle, + interprocess_token); + if (sc->ctx_handle == GSS_C_NO_CONTEXT) { + release_spnego_ctx(&sc); + *context_handle = GSS_C_NO_CONTEXT; + } + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_import_sec_context( + OM_uint32 *minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle) +{ + OM_uint32 ret, tmpmin; + gss_ctx_id_t mctx; + spnego_gss_ctx_id_t sc; + int initiate, opened; + + ret = gss_import_sec_context(minor_status, interprocess_token, &mctx); + if (ret != GSS_S_COMPLETE) + return ret; + + ret = gss_inquire_context(&tmpmin, mctx, NULL, NULL, NULL, NULL, NULL, + &initiate, &opened); + if (ret != GSS_S_COMPLETE || !opened) { + /* We don't currently support importing partially established + * contexts. */ + (void) gss_delete_sec_context(&tmpmin, &mctx, GSS_C_NO_BUFFER); + return GSS_S_FAILURE; + } + + sc = create_spnego_ctx(initiate); + if (sc == NULL) { + (void) gss_delete_sec_context(&tmpmin, &mctx, GSS_C_NO_BUFFER); + return GSS_S_FAILURE; + } + sc->ctx_handle = mctx; + sc->opened = 1; + *context_handle = (gss_ctx_id_t)sc; + return GSS_S_COMPLETE; +} +#endif /* LEAN_CLIENT */ + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_context( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_name_t *src_name, + gss_name_t *targ_name, + OM_uint32 *lifetime_rec, + gss_OID *mech_type, + OM_uint32 *ctx_flags, + int *locally_initiated, + int *opened) +{ + OM_uint32 ret = GSS_S_COMPLETE; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (src_name != NULL) + *src_name = GSS_C_NO_NAME; + if (targ_name != NULL) + *targ_name = GSS_C_NO_NAME; + if (lifetime_rec != NULL) + *lifetime_rec = 0; + if (mech_type != NULL) + *mech_type = (gss_OID)gss_mech_spnego; + if (ctx_flags != NULL) + *ctx_flags = 0; + if (locally_initiated != NULL) + *locally_initiated = sc->initiate; + if (opened != NULL) + *opened = sc->opened; + + if (sc->ctx_handle != GSS_C_NO_CONTEXT) { + ret = gss_inquire_context(minor_status, sc->ctx_handle, + src_name, targ_name, lifetime_rec, + mech_type, ctx_flags, NULL, NULL); + } + + if (!sc->opened) { + /* + * We are still doing SPNEGO negotiation, so report SPNEGO as + * the OID. After negotiation is complete we will report the + * underlying mechanism OID. + */ + if (mech_type != NULL) + *mech_type = (gss_OID)gss_mech_spnego; + + /* + * Remove flags we don't support with partially-established + * contexts. (Change this to keep GSS_C_TRANS_FLAG if we add + * support for exporting partial SPNEGO contexts.) + */ + if (ctx_flags != NULL) { + *ctx_flags &= ~GSS_C_PROT_READY_FLAG; + *ctx_flags &= ~GSS_C_TRANS_FLAG; + } + } + + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_wrap_size_limit( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + ret = gss_wrap_size_limit(minor_status, + sc->ctx_handle, + conf_req_flag, + qop_req, + req_output_size, + max_input_size); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_localname(OM_uint32 *minor_status, const gss_name_t pname, + const gss_const_OID mech_type, gss_buffer_t localname) +{ + return gss_localname(minor_status, pname, GSS_C_NO_OID, localname); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_get_mic( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + ret = gss_get_mic(minor_status, + sc->ctx_handle, + qop_req, + message_buffer, + message_token); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_verify_mic( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t msg_buffer, + const gss_buffer_t token_buffer, + gss_qop_t *qop_state) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + ret = gss_verify_mic(minor_status, + sc->ctx_handle, + msg_buffer, + token_buffer, + qop_state); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_sec_context_by_oid( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + /* There are no SPNEGO-specific OIDs for this function. */ + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_UNAVAILABLE); + + ret = gss_inquire_sec_context_by_oid(minor_status, + sc->ctx_handle, + desired_object, + data_set); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_cred_by_oid( + OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + OM_uint32 ret; + spnego_gss_cred_id_t spcred = (spnego_gss_cred_id_t)cred_handle; + gss_cred_id_t mcred; + mcred = (spcred == NULL) ? GSS_C_NO_CREDENTIAL : spcred->mcred; + ret = gss_inquire_cred_by_oid(minor_status, + mcred, + desired_object, + data_set); + return (ret); +} + +/* This is the same OID as KRB5_NO_CI_FLAGS_X_OID. */ +#define NO_CI_FLAGS_X_OID_LENGTH 6 +#define NO_CI_FLAGS_X_OID "\x2a\x85\x70\x2b\x0d\x1d" +static const gss_OID_desc no_ci_flags_oid[] = { + {NO_CI_FLAGS_X_OID_LENGTH, NO_CI_FLAGS_X_OID}, +}; + +OM_uint32 KRB5_CALLCONV +spnego_gss_set_cred_option( + OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + OM_uint32 ret; + OM_uint32 tmp_minor_status; + spnego_gss_cred_id_t spcred = (spnego_gss_cred_id_t)*cred_handle; + gss_cred_id_t mcred; + + mcred = (spcred == NULL) ? GSS_C_NO_CREDENTIAL : spcred->mcred; + ret = gss_set_cred_option(minor_status, + &mcred, + desired_object, + value); + if (ret == GSS_S_COMPLETE && spcred == NULL) { + /* + * If the mechanism allocated a new credential handle, then + * we need to wrap it up in an SPNEGO credential handle. + */ + + ret = create_spnego_cred(minor_status, mcred, &spcred); + if (ret != GSS_S_COMPLETE) { + gss_release_cred(&tmp_minor_status, &mcred); + return (ret); + } + *cred_handle = (gss_cred_id_t)spcred; + } + + if (ret != GSS_S_COMPLETE) + return (ret); + + /* Recognize KRB5_NO_CI_FLAGS_X_OID and avoid asking for integrity. */ + if (g_OID_equal(desired_object, no_ci_flags_oid)) + spcred->no_ask_integ = 1; + + return (GSS_S_COMPLETE); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_set_sec_context_option( + OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)*context_handle; + + /* There are no SPNEGO-specific OIDs for this function, and we cannot + * construct an empty SPNEGO context with it. */ + if (sc == NULL || sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_UNAVAILABLE); + + ret = gss_set_sec_context_option(minor_status, + &sc->ctx_handle, + desired_object, + value); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_wrap_aead(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + gss_buffer_t input_assoc_buffer, + gss_buffer_t input_payload_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + ret = gss_wrap_aead(minor_status, + sc->ctx_handle, + conf_req_flag, + qop_req, + input_assoc_buffer, + input_payload_buffer, + conf_state, + output_message_buffer); + + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_unwrap_aead(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t input_assoc_buffer, + gss_buffer_t output_payload_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + ret = gss_unwrap_aead(minor_status, + sc->ctx_handle, + input_message_buffer, + input_assoc_buffer, + output_payload_buffer, + conf_state, + qop_state); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_wrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + ret = gss_wrap_iov(minor_status, + sc->ctx_handle, + conf_req_flag, + qop_req, + conf_state, + iov, + iov_count); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_unwrap_iov(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int *conf_state, + gss_qop_t *qop_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + ret = gss_unwrap_iov(minor_status, + sc->ctx_handle, + conf_state, + qop_state, + iov, + iov_count); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_wrap_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + int *conf_state, + gss_iov_buffer_desc *iov, + int iov_count) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + ret = gss_wrap_iov_length(minor_status, + sc->ctx_handle, + conf_req_flag, + qop_req, + conf_state, + iov, + iov_count); + return (ret); +} + + +OM_uint32 KRB5_CALLCONV +spnego_gss_complete_auth_token( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_UNAVAILABLE); + + ret = gss_complete_auth_token(minor_status, + sc->ctx_handle, + input_message_buffer); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_acquire_cred_impersonate_name(OM_uint32 *minor_status, + const gss_cred_id_t impersonator_cred_handle, + const gss_name_t desired_name, + OM_uint32 time_req, + gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + OM_uint32 status, tmpmin; + gss_OID_set amechs = GSS_C_NULL_OID_SET; + spnego_gss_cred_id_t imp_spcred = NULL, out_spcred = NULL; + gss_cred_id_t imp_mcred, out_mcred = GSS_C_NO_CREDENTIAL; + + dsyslog("Entering spnego_gss_acquire_cred_impersonate_name\n"); + + if (actual_mechs) + *actual_mechs = NULL; + + if (time_rec) + *time_rec = 0; + + imp_spcred = (spnego_gss_cred_id_t)impersonator_cred_handle; + imp_mcred = imp_spcred ? imp_spcred->mcred : GSS_C_NO_CREDENTIAL; + status = gss_inquire_cred(minor_status, imp_mcred, NULL, NULL, + NULL, &amechs); + if (status != GSS_S_COMPLETE) + return status; + + status = gss_acquire_cred_impersonate_name(minor_status, imp_mcred, + desired_name, time_req, + amechs, cred_usage, + &out_mcred, actual_mechs, + time_rec); + if (status != GSS_S_COMPLETE) + goto cleanup; + + status = create_spnego_cred(minor_status, out_mcred, &out_spcred); + if (status != GSS_S_COMPLETE) + goto cleanup; + + out_mcred = GSS_C_NO_CREDENTIAL; + *output_cred_handle = (gss_cred_id_t)out_spcred; + +cleanup: + (void) gss_release_oid_set(&tmpmin, &amechs); + (void) gss_release_cred(&tmpmin, &out_mcred); + + dsyslog("Leaving spnego_gss_acquire_cred_impersonate_name\n"); + return (status); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_acquire_cred_with_password(OM_uint32 *minor_status, + const gss_name_t desired_name, + const gss_buffer_t password, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + OM_uint32 status, tmpmin; + gss_OID_set amechs = GSS_C_NULL_OID_SET; + gss_cred_id_t mcred = NULL; + spnego_gss_cred_id_t spcred = NULL; + + dsyslog("Entering spnego_gss_acquire_cred_with_password\n"); + + if (actual_mechs) + *actual_mechs = NULL; + + if (time_rec) + *time_rec = 0; + + status = get_available_mechs(minor_status, desired_name, + cred_usage, GSS_C_NO_CRED_STORE, + NULL, &amechs, NULL); + if (status != GSS_S_COMPLETE) + goto cleanup; + + status = gss_acquire_cred_with_password(minor_status, desired_name, + password, time_req, amechs, + cred_usage, &mcred, + actual_mechs, time_rec); + if (status != GSS_S_COMPLETE) + goto cleanup; + + status = create_spnego_cred(minor_status, mcred, &spcred); + if (status != GSS_S_COMPLETE) + goto cleanup; + + mcred = GSS_C_NO_CREDENTIAL; + *output_cred_handle = (gss_cred_id_t)spcred; + +cleanup: + + (void) gss_release_oid_set(&tmpmin, &amechs); + (void) gss_release_cred(&tmpmin, &mcred); + + dsyslog("Leaving spnego_gss_acquire_cred_with_password\n"); + return (status); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_display_name_ext(OM_uint32 *minor_status, + gss_name_t name, + gss_OID display_as_name_type, + gss_buffer_t display_name) +{ + OM_uint32 ret; + ret = gss_display_name_ext(minor_status, + name, + display_as_name_type, + display_name); + return (ret); +} + + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_name(OM_uint32 *minor_status, + gss_name_t name, + int *name_is_MN, + gss_OID *MN_mech, + gss_buffer_set_t *attrs) +{ + OM_uint32 ret; + ret = gss_inquire_name(minor_status, + name, + name_is_MN, + MN_mech, + attrs); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_get_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t attr, + int *authenticated, + int *complete, + gss_buffer_t value, + gss_buffer_t display_value, + int *more) +{ + OM_uint32 ret; + ret = gss_get_name_attribute(minor_status, + name, + attr, + authenticated, + complete, + value, + display_value, + more); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_set_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + int complete, + gss_buffer_t attr, + gss_buffer_t value) +{ + OM_uint32 ret; + ret = gss_set_name_attribute(minor_status, + name, + complete, + attr, + value); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_delete_name_attribute(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t attr) +{ + OM_uint32 ret; + ret = gss_delete_name_attribute(minor_status, + name, + attr); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_export_name_composite(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t exp_composite_name) +{ + OM_uint32 ret; + ret = gss_export_name_composite(minor_status, + name, + exp_composite_name); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_map_name_to_any(OM_uint32 *minor_status, + gss_name_t name, + int authenticated, + gss_buffer_t type_id, + gss_any_t *output) +{ + OM_uint32 ret; + ret = gss_map_name_to_any(minor_status, + name, + authenticated, + type_id, + output); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_release_any_name_mapping(OM_uint32 *minor_status, + gss_name_t name, + gss_buffer_t type_id, + gss_any_t *input) +{ + OM_uint32 ret; + ret = gss_release_any_name_mapping(minor_status, + name, + type_id, + input); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_pseudo_random(OM_uint32 *minor_status, + gss_ctx_id_t context, + int prf_key, + const gss_buffer_t prf_in, + ssize_t desired_output_len, + gss_buffer_t prf_out) +{ + OM_uint32 ret; + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + ret = gss_pseudo_random(minor_status, + sc->ctx_handle, + prf_key, + prf_in, + desired_output_len, + prf_out); + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_set_neg_mechs(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + const gss_OID_set mech_list) +{ + OM_uint32 ret; + spnego_gss_cred_id_t spcred = (spnego_gss_cred_id_t)cred_handle; + + /* Store mech_list in spcred for use in negotiation logic. */ + gss_release_oid_set(minor_status, &spcred->neg_mechs); + ret = generic_gss_copy_oid_set(minor_status, mech_list, + &spcred->neg_mechs); + if (ret == GSS_S_COMPLETE) { + (void) gss_set_neg_mechs(minor_status, + spcred->mcred, + spcred->neg_mechs); + } + + return (ret); +} + +#define SPNEGO_SASL_NAME "SPNEGO" +#define SPNEGO_SASL_NAME_LEN (sizeof(SPNEGO_SASL_NAME) - 1) + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_mech_for_saslname(OM_uint32 *minor_status, + const gss_buffer_t sasl_mech_name, + gss_OID *mech_type) +{ + if (sasl_mech_name->length == SPNEGO_SASL_NAME_LEN && + memcmp(sasl_mech_name->value, SPNEGO_SASL_NAME, + SPNEGO_SASL_NAME_LEN) == 0) { + if (mech_type != NULL) + *mech_type = (gss_OID)gss_mech_spnego; + return (GSS_S_COMPLETE); + } + + return (GSS_S_BAD_MECH); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_saslname_for_mech(OM_uint32 *minor_status, + const gss_OID desired_mech, + gss_buffer_t sasl_mech_name, + gss_buffer_t mech_name, + gss_buffer_t mech_description) +{ + *minor_status = 0; + + if (!g_OID_equal(desired_mech, gss_mech_spnego)) + return (GSS_S_BAD_MECH); + + if (!g_make_string_buffer(SPNEGO_SASL_NAME, sasl_mech_name) || + !g_make_string_buffer("spnego", mech_name) || + !g_make_string_buffer("Simple and Protected GSS-API " + "Negotiation Mechanism", mech_description)) + goto fail; + + return (GSS_S_COMPLETE); + +fail: + *minor_status = ENOMEM; + return (GSS_S_FAILURE); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_inquire_attrs_for_mech(OM_uint32 *minor_status, + gss_const_OID mech, + gss_OID_set *mech_attrs, + gss_OID_set *known_mech_attrs) +{ + OM_uint32 major, tmpMinor; + + /* known_mech_attrs is handled by mechglue */ + *minor_status = 0; + + if (mech_attrs == NULL) + return (GSS_S_COMPLETE); + + major = gss_create_empty_oid_set(minor_status, mech_attrs); + if (GSS_ERROR(major)) + goto cleanup; + +#define MA_SUPPORTED(ma) do { \ + major = gss_add_oid_set_member(minor_status, \ + (gss_OID)ma, mech_attrs); \ + if (GSS_ERROR(major)) \ + goto cleanup; \ + } while (0) + + MA_SUPPORTED(GSS_C_MA_MECH_NEGO); + MA_SUPPORTED(GSS_C_MA_ITOK_FRAMED); + +cleanup: + if (GSS_ERROR(major)) + gss_release_oid_set(&tmpMinor, mech_attrs); + + return (major); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_export_cred(OM_uint32 *minor_status, + gss_cred_id_t cred_handle, + gss_buffer_t token) +{ + spnego_gss_cred_id_t spcred = (spnego_gss_cred_id_t)cred_handle; + + return (gss_export_cred(minor_status, spcred->mcred, token)); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_import_cred(OM_uint32 *minor_status, + gss_buffer_t token, + gss_cred_id_t *cred_handle) +{ + OM_uint32 ret; + spnego_gss_cred_id_t spcred; + gss_cred_id_t mcred; + + ret = gss_import_cred(minor_status, token, &mcred); + if (GSS_ERROR(ret)) + return (ret); + + ret = create_spnego_cred(minor_status, mcred, &spcred); + if (GSS_ERROR(ret)) + return (ret); + + *cred_handle = (gss_cred_id_t)spcred; + return (ret); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_get_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_qop_t qop_req, gss_iov_buffer_desc *iov, + int iov_count) +{ + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + return gss_get_mic_iov(minor_status, sc->ctx_handle, qop_req, iov, + iov_count); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_verify_mic_iov(OM_uint32 *minor_status, gss_ctx_id_t context_handle, + gss_qop_t *qop_state, gss_iov_buffer_desc *iov, + int iov_count) +{ + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + return gss_verify_mic_iov(minor_status, sc->ctx_handle, qop_state, iov, + iov_count); +} + +OM_uint32 KRB5_CALLCONV +spnego_gss_get_mic_iov_length(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, gss_qop_t qop_req, + gss_iov_buffer_desc *iov, int iov_count) +{ + spnego_gss_ctx_id_t sc = (spnego_gss_ctx_id_t)context_handle; + + if (sc->ctx_handle == GSS_C_NO_CONTEXT) + return (GSS_S_NO_CONTEXT); + + return gss_get_mic_iov_length(minor_status, sc->ctx_handle, qop_req, iov, + iov_count); +} + +/* + * We will release everything but the ctx_handle so that it + * can be passed back to init/accept context. This routine should + * not be called until after the ctx_handle memory is assigned to + * the supplied context handle from init/accept context. + */ +static void +release_spnego_ctx(spnego_gss_ctx_id_t *ctx) +{ + spnego_gss_ctx_id_t context; + OM_uint32 minor_stat; + context = *ctx; + + if (context != NULL) { + (void) gss_release_buffer(&minor_stat, + &context->DER_mechTypes); + + (void) gss_release_oid_set(&minor_stat, &context->mech_set); + + (void) gss_release_name(&minor_stat, &context->internal_name); + (void) gss_release_cred(&minor_stat, &context->deleg_cred); + + negoex_release_context(context); + + free(context); + *ctx = NULL; + } +} + +/* + * Can't use gss_indicate_mechs by itself to get available mechs for + * SPNEGO because it will also return the SPNEGO mech and we do not + * want to consider SPNEGO as an available security mech for + * negotiation. For this reason, get_available_mechs will return + * all available, non-deprecated mechs except SPNEGO and NegoEx- + * only mechanisms. + * + * Note that gss_acquire_cred_from(GSS_C_NO_OID_SET) will filter + * out hidden (GSS_C_MA_NOT_INDICATED) mechanisms such as NegoEx, so + * calling gss_indicate_mechs_by_attrs() also works around that. + * + * If a ptr to a creds list is given, this function will attempt + * to acquire creds for the creds given and trim the list of + * returned mechanisms to only those for which creds are valid. + * + */ +static OM_uint32 +get_available_mechs(OM_uint32 *minor_status, + gss_name_t name, gss_cred_usage_t usage, + gss_const_key_value_set_t cred_store, + gss_cred_id_t *creds, gss_OID_set *rmechs, OM_uint32 *time_rec) +{ + OM_uint32 major_status = GSS_S_COMPLETE, tmpmin; + gss_OID_set mechs, goodmechs; + gss_OID_set_desc except_attrs; + gss_OID_desc attr_oids[3]; + + *rmechs = GSS_C_NO_OID_SET; + + attr_oids[0] = *GSS_C_MA_DEPRECATED; + attr_oids[1] = *GSS_C_MA_NOT_DFLT_MECH; + attr_oids[2] = *GSS_C_MA_MECH_NEGO; /* Exclude ourselves */ + except_attrs.count = sizeof(attr_oids) / sizeof(attr_oids[0]); + except_attrs.elements = attr_oids; + major_status = gss_indicate_mechs_by_attrs(minor_status, + GSS_C_NO_OID_SET, + &except_attrs, + GSS_C_NO_OID_SET, &mechs); + + /* + * If the caller wanted a list of creds returned, + * trim the list of mechanisms down to only those + * for which the creds are valid. + */ + if (mechs->count > 0 && major_status == GSS_S_COMPLETE && + creds != NULL) { + major_status = gss_acquire_cred_from(minor_status, name, + GSS_C_INDEFINITE, + mechs, usage, + cred_store, creds, + &goodmechs, time_rec); + + /* + * Drop the old list in favor of the new + * "trimmed" list. + */ + if (major_status == GSS_S_COMPLETE) { + (void) gss_release_oid_set(&tmpmin, &mechs); + mechs = goodmechs; + } + } + + if (mechs->count > 0 && major_status == GSS_S_COMPLETE) { + *rmechs = mechs; + } else { + (void) gss_release_oid_set(&tmpmin, &mechs); + *minor_status = ERR_SPNEGO_NO_MECHS_AVAILABLE; + map_errcode(minor_status); + if (major_status == GSS_S_COMPLETE) + major_status = GSS_S_FAILURE; + } + + return (major_status); +} + +/* Return true if mech asserts the GSS_C_MA_NEGOEX_AND_SPNEGO attribute. */ +static int +negoex_and_spnego(gss_OID mech) +{ + OM_uint32 ret, minor; + gss_OID_set attrs; + int present; + + ret = gss_inquire_attrs_for_mech(&minor, mech, &attrs, NULL); + if (ret != GSS_S_COMPLETE || attrs == GSS_C_NO_OID_SET) + return 0; + + (void) generic_gss_test_oid_set_member(&minor, + GSS_C_MA_NEGOEX_AND_SPNEGO, + attrs, &present); + (void) gss_release_oid_set(&minor, &attrs); + return present; +} + +/* + * Fill sc->mech_set with the SPNEGO-negotiable mechanism OIDs, and + * sc->negoex_mechs with an entry for each NegoEx-negotiable mechanism. Take + * into account the mech set provided with gss_set_neg_mechs() if it exists. + */ +static OM_uint32 +get_negotiable_mechs(OM_uint32 *minor_status, spnego_gss_ctx_id_t sc, + spnego_gss_cred_id_t spcred, gss_cred_usage_t usage) +{ + OM_uint32 ret, tmpmin; + gss_cred_id_t creds = GSS_C_NO_CREDENTIAL; + gss_OID_set cred_mechs = GSS_C_NULL_OID_SET, mechs; + unsigned int i; + int present, added_negoex = 0; + auth_scheme scheme; + + if (spcred != NULL) { + /* Get the list of mechs in the mechglue cred. */ + ret = gss_inquire_cred(minor_status, spcred->mcred, NULL, + NULL, NULL, &cred_mechs); + if (ret != GSS_S_COMPLETE) + return (ret); + } else { + /* Start with the list of available mechs. */ + ret = get_available_mechs(minor_status, GSS_C_NO_NAME, usage, + GSS_C_NO_CRED_STORE, &creds, + &cred_mechs, NULL); + if (ret != GSS_S_COMPLETE) + return (ret); + gss_release_cred(&tmpmin, &creds); + } + + /* If gss_set_neg_mechs() was called, use that to determine the + * iteration order. Otherwise iterate over the credential mechs. */ + mechs = (spcred != NULL && spcred->neg_mechs != GSS_C_NULL_OID_SET) ? + spcred->neg_mechs : cred_mechs; + + ret = gss_create_empty_oid_set(minor_status, &sc->mech_set); + if (ret != GSS_S_COMPLETE) + goto cleanup; + + for (i = 0; i < mechs->count; i++) { + if (mechs != cred_mechs) { + /* Intersect neg_mechs with cred_mechs. */ + gss_test_oid_set_member(&tmpmin, &mechs->elements[i], + cred_mechs, &present); + if (!present) + continue; + } + + /* Query the auth scheme to see if this is a NegoEx mech. */ + ret = gssspi_query_mechanism_info(&tmpmin, &mechs->elements[i], + scheme); + if (ret == GSS_S_COMPLETE) { + /* Add an entry for this mech to the NegoEx list. */ + ret = negoex_add_auth_mech(minor_status, sc, + &mechs->elements[i], + scheme); + if (ret != GSS_S_COMPLETE) + goto cleanup; + + /* Add the NegoEx OID to the SPNEGO list at the + * position of the first NegoEx mechanism. */ + if (!added_negoex) { + ret = gss_add_oid_set_member(minor_status, + &negoex_mech, + &sc->mech_set); + if (ret != GSS_S_COMPLETE) + goto cleanup; + added_negoex = 1; + } + + /* Skip this mech in the SPNEGO list unless it asks for + * direct SPNEGO negotiation. */ + if (!negoex_and_spnego(&mechs->elements[i])) + continue; + } + + /* Add this mech to the SPNEGO list. */ + ret = gss_add_oid_set_member(minor_status, &mechs->elements[i], + &sc->mech_set); + if (ret != GSS_S_COMPLETE) + goto cleanup; + } + + *minor_status = 0; + +cleanup: + if (ret != GSS_S_COMPLETE || sc->mech_set->count == 0) { + *minor_status = ERR_SPNEGO_NO_MECHS_AVAILABLE; + map_errcode(minor_status); + ret = GSS_S_FAILURE; + } + + gss_release_oid_set(&tmpmin, &cred_mechs); + return (ret); +} + +/* following are token creation and reading routines */ + +/* + * If in contains a tagged OID encoding, return a copy of the contents as a + * gss_OID and advance in past the encoding. Otherwise return NULL and do not + * advance in. + */ +static gss_OID +get_mech_oid(OM_uint32 *minor_status, struct k5input *in) +{ + struct k5input oidrep; + OM_uint32 status; + gss_OID_desc oid; + gss_OID mech_out = NULL; + + if (!k5_der_get_value(in, MECH_OID, &oidrep)) + return (NULL); + + oid.length = oidrep.len; + oid.elements = (uint8_t *)oidrep.ptr; + status = generic_gss_copy_oid(minor_status, &oid, &mech_out); + if (status != GSS_S_COMPLETE) { + map_errcode(minor_status); + mech_out = NULL; + } + + return (mech_out); +} + +/* + * If in contains a tagged octet string encoding, return a copy of the contents + * as a gss_buffer_t and advance in past the encoding. Otherwise return NULL + * and do not advance in. + */ +static gss_buffer_t +get_octet_string(struct k5input *in) +{ + gss_buffer_t input_token; + struct k5input ostr; + + if (!k5_der_get_value(in, OCTET_STRING, &ostr)) + return (NULL); + + input_token = (gss_buffer_t)malloc(sizeof (gss_buffer_desc)); + if (input_token == NULL) + return (NULL); + + input_token->length = ostr.len; + if (input_token->length > 0) { + input_token->value = gssalloc_malloc(input_token->length); + if (input_token->value == NULL) { + free(input_token); + return (NULL); + } + + memcpy(input_token->value, ostr.ptr, input_token->length); + } else { + input_token->value = NULL; + } + return (input_token); +} + +/* + * verify that buff_in points to a sequence of der encoding. The mech + * set is the only sequence of encoded object in the token, so if it is + * a sequence of encoding, decode the mechset into a gss_OID_set and + * return it, advancing the buffer pointer. + */ +static gss_OID_set +get_mech_set(OM_uint32 *minor_status, struct k5input *in) +{ + gss_OID_set returned_mechSet; + OM_uint32 major_status, tmpmin; + struct k5input seq; + + if (!k5_der_get_value(in, SEQUENCE_OF, &seq)) + return (NULL); + + major_status = gss_create_empty_oid_set(minor_status, + &returned_mechSet); + if (major_status != GSS_S_COMPLETE) + return (NULL); + + while (!seq.status && seq.len > 0) { + gss_OID_desc *oid = get_mech_oid(minor_status, &seq); + + if (oid == NULL) { + gss_release_oid_set(&tmpmin, &returned_mechSet); + return (NULL); + } + + major_status = gss_add_oid_set_member(minor_status, + oid, &returned_mechSet); + generic_gss_release_oid(minor_status, &oid); + if (major_status != GSS_S_COMPLETE) { + gss_release_oid_set(&tmpmin, &returned_mechSet); + return (NULL); + } + } + + return (returned_mechSet); +} + +/* + * Encode mechSet into buf. + */ +static int +put_mech_set(gss_OID_set mechSet, gss_buffer_t buffer_out) +{ + uint8_t *ptr; + size_t ilen, tlen, i; + struct k5buf buf; + + ilen = 0; + for (i = 0; i < mechSet->count; i++) + ilen += k5_der_value_len(mechSet->elements[i].length); + tlen = k5_der_value_len(ilen); + + ptr = gssalloc_malloc(tlen); + if (ptr == NULL) + return -1; + k5_buf_init_fixed(&buf, ptr, tlen); + + k5_der_add_taglen(&buf, SEQUENCE_OF, ilen); + for (i = 0; i < mechSet->count; i++) { + k5_der_add_value(&buf, MECH_OID, + mechSet->elements[i].elements, + mechSet->elements[i].length); + } + assert(buf.len == tlen); + + buffer_out->value = ptr; + buffer_out->length = tlen; + return 0; +} + +/* Decode SPNEGO request flags from the DER encoding of a bit string and set + * them in *ret_flags. */ +static OM_uint32 +get_req_flags(struct k5input *in, OM_uint32 *req_flags) +{ + if (in->status || in->len != 4 || + k5_input_get_byte(in) != BIT_STRING || + k5_input_get_byte(in) != BIT_STRING_LENGTH || + k5_input_get_byte(in) != BIT_STRING_PADDING) + return GSS_S_DEFECTIVE_TOKEN; + + *req_flags = k5_input_get_byte(in) >> 1; + return GSS_S_COMPLETE; +} + +static OM_uint32 +get_negTokenInit(OM_uint32 *minor_status, + gss_buffer_t buf, + gss_buffer_t der_mechSet, + gss_OID_set *mechSet, + OM_uint32 *req_flags, + gss_buffer_t *mechtok, + gss_buffer_t *mechListMIC) +{ + OM_uint32 err; + struct k5input in, seq, field; + + *minor_status = 0; + der_mechSet->length = 0; + der_mechSet->value = NULL; + *mechSet = GSS_C_NO_OID_SET; + *req_flags = 0; + *mechtok = *mechListMIC = GSS_C_NO_BUFFER; + + k5_input_init(&in, buf->value, buf->length); + + /* Advance past the framing header. */ + err = verify_token_header(&in, gss_mech_spnego); + if (err) + return GSS_S_DEFECTIVE_TOKEN; + + /* Advance past the [0] tag for the NegotiationToken choice. */ + if (!k5_der_get_value(&in, CONTEXT, &seq)) + return GSS_S_DEFECTIVE_TOKEN; + + /* Advance past the SEQUENCE tag. */ + if (!k5_der_get_value(&seq, SEQUENCE, &seq)) + return GSS_S_DEFECTIVE_TOKEN; + + /* Get the contents of the mechTypes field. Reject an empty field here + * since we musn't allocate a zero-length buffer in the next step. */ + if (!k5_der_get_value(&seq, CONTEXT, &field) || field.len == 0) + return GSS_S_DEFECTIVE_TOKEN; + + /* Store a copy of the contents for MIC computation. */ + der_mechSet->value = gssalloc_malloc(field.len); + if (der_mechSet->value == NULL) + return GSS_S_FAILURE; + memcpy(der_mechSet->value, field.ptr, field.len); + der_mechSet->length = field.len; + + /* Decode the contents into an OID set. */ + *mechSet = get_mech_set(minor_status, &field); + if (*mechSet == NULL) + return GSS_S_FAILURE; + + if (k5_der_get_value(&seq, CONTEXT | 0x01, &field)) { + err = get_req_flags(&field, req_flags); + if (err != GSS_S_COMPLETE) + return err; + } + + if (k5_der_get_value(&seq, CONTEXT | 0x02, &field)) { + *mechtok = get_octet_string(&field); + if (*mechtok == GSS_C_NO_BUFFER) + return GSS_S_FAILURE; + } + + if (k5_der_get_value(&seq, CONTEXT | 0x03, &field)) { + *mechListMIC = get_octet_string(&field); + if (*mechListMIC == GSS_C_NO_BUFFER) + return GSS_S_FAILURE; + } + + return seq.status ? GSS_S_DEFECTIVE_TOKEN : GSS_S_COMPLETE; +} + +/* Decode a NegotiationToken of type negTokenResp. */ +static OM_uint32 +get_negTokenResp(OM_uint32 *minor_status, struct k5input *in, + OM_uint32 *negState, gss_OID *supportedMech, + gss_buffer_t *responseToken, gss_buffer_t *mechListMIC) +{ + struct k5input seq, field, en; + + *negState = UNSPECIFIED; + *supportedMech = GSS_C_NO_OID; + *responseToken = *mechListMIC = GSS_C_NO_BUFFER; + + /* Advance past the [1] tag for the NegotiationToken choice. */ + if (!k5_der_get_value(in, CONTEXT | 0x01, &seq)) + return GSS_S_DEFECTIVE_TOKEN; + + /* Advance seq past the SEQUENCE tag (historically this code allows the + * tag to be missing). */ + (void)k5_der_get_value(&seq, SEQUENCE, &seq); + + if (k5_der_get_value(&seq, CONTEXT, &field)) { + if (!k5_der_get_value(&field, ENUMERATED, &en)) + return GSS_S_DEFECTIVE_TOKEN; + if (en.len != ENUMERATION_LENGTH) + return GSS_S_DEFECTIVE_TOKEN; + *negState = *en.ptr; + } + + if (k5_der_get_value(&seq, CONTEXT | 0x01, &field)) { + *supportedMech = get_mech_oid(minor_status, &field); + if (*supportedMech == GSS_C_NO_OID) + return GSS_S_DEFECTIVE_TOKEN; + } + + if (k5_der_get_value(&seq, CONTEXT | 0x02, &field)) { + *responseToken = get_octet_string(&field); + if (*responseToken == GSS_C_NO_BUFFER) + return GSS_S_DEFECTIVE_TOKEN; + } + + if (k5_der_get_value(&seq, CONTEXT | 0x04, &field)) { + *mechListMIC = get_octet_string(&field); + + /* Handle Windows 2000 duplicate response token */ + if (*responseToken && + ((*responseToken)->length == (*mechListMIC)->length) && + !memcmp((*responseToken)->value, (*mechListMIC)->value, + (*responseToken)->length)) { + OM_uint32 tmpmin; + + gss_release_buffer(&tmpmin, *mechListMIC); + free(*mechListMIC); + *mechListMIC = NULL; + } + } + + return seq.status ? GSS_S_DEFECTIVE_TOKEN : GSS_S_COMPLETE; +} + +/* + * This routine compares the received mechset to the mechset that + * this server can support. It looks sequentially through the mechset + * and the first one that matches what the server can support is + * chosen as the negotiated mechanism. If one is found, negResult + * is set to ACCEPT_INCOMPLETE if it's the first mech, REQUEST_MIC if + * it's not the first mech, otherwise we return NULL and negResult + * is set to REJECT. The returned pointer is an alias into + * received->elements and should not be freed. + * + * NOTE: There is currently no way to specify a preference order of + * mechanisms supported by the acceptor. + */ +static gss_OID +negotiate_mech(spnego_gss_ctx_id_t ctx, gss_OID_set received, + OM_uint32 *negResult) +{ + size_t i, j; + int wrong_krb5_oid; + + for (i = 0; i < received->count; i++) { + gss_OID mech_oid = &received->elements[i]; + + /* Accept wrong mechanism OID from MS clients */ + wrong_krb5_oid = 0; + if (g_OID_equal(mech_oid, &gss_mech_krb5_wrong_oid)) { + mech_oid = (gss_OID)&gss_mech_krb5_oid; + wrong_krb5_oid = 1; + } + + for (j = 0; j < ctx->mech_set->count; j++) { + if (g_OID_equal(mech_oid, + &ctx->mech_set->elements[j])) { + *negResult = (i == 0) ? ACCEPT_INCOMPLETE : + REQUEST_MIC; + return wrong_krb5_oid ? + (gss_OID)&gss_mech_krb5_wrong_oid : + &ctx->mech_set->elements[j]; + } + } + } + *negResult = REJECT; + return (NULL); +} + +/* + * the next two routines make a token buffer suitable for + * spnego_gss_display_status. These currently take the string + * in name and place it in the token. Eventually, if + * spnego_gss_display_status returns valid error messages, + * these routines will be changes to return the error string. + */ +static spnego_token_t +make_spnego_token(const char *name) +{ + return (spnego_token_t)gssalloc_strdup(name); +} + +static gss_buffer_desc +make_err_msg(const char *name) +{ + gss_buffer_desc buffer; + + if (name == NULL) { + buffer.length = 0; + buffer.value = NULL; + } else { + buffer.length = strlen(name)+1; + buffer.value = make_spnego_token(name); + } + + return (buffer); +} + +/* + * Create the client side spnego token passed back to gss_init_sec_context + * and eventually up to the application program and over to the server. + * + * Use DER rules, definite length method per RFC 2478 + */ +static int +make_spnego_tokenInit_msg(spnego_gss_ctx_id_t spnego_ctx, int negHintsCompat, + gss_buffer_t mic, OM_uint32 req_flags, + gss_buffer_t token, send_token_flag sendtoken, + gss_buffer_t outbuf) +{ + size_t f0len, f2len, f3len, fields_len, seq_len, choice_len; + size_t mech_len, framed_len; + uint8_t *t; + struct k5buf buf; + + if (outbuf == GSS_C_NO_BUFFER) + return (-1); + + outbuf->length = 0; + outbuf->value = NULL; + + /* Calculate the length of each field and the total fields length. */ + fields_len = 0; + /* mechTypes [0] MechTypeList, previously assembled in spnego_ctx */ + f0len = spnego_ctx->DER_mechTypes.length; + fields_len += k5_der_value_len(f0len); + if (token != NULL) { + /* mechToken [2] OCTET STRING OPTIONAL */ + f2len = k5_der_value_len(token->length); + fields_len += k5_der_value_len(f2len); + } + if (mic != GSS_C_NO_BUFFER) { + /* mechListMIC [3] OCTET STRING OPTIONAL */ + f3len = k5_der_value_len(mic->length); + fields_len += k5_der_value_len(f3len); + } + + /* Calculate the length of the sequence and choice. */ + seq_len = k5_der_value_len(fields_len); + choice_len = k5_der_value_len(seq_len); + + /* Calculate the framed token length. */ + mech_len = k5_der_value_len(gss_mech_spnego->length); + framed_len = k5_der_value_len(mech_len + choice_len); + + /* Allocate space and prepare a buffer. */ + t = gssalloc_malloc(framed_len); + if (t == NULL) + return (-1); + k5_buf_init_fixed(&buf, t, framed_len); + + /* Add generic token framing. */ + k5_der_add_taglen(&buf, HEADER_ID, mech_len + choice_len); + k5_der_add_value(&buf, MECH_OID, gss_mech_spnego->elements, + gss_mech_spnego->length); + + /* Add NegotiationToken choice tag and NegTokenInit sequence tag. */ + k5_der_add_taglen(&buf, CONTEXT | 0x00, seq_len); + k5_der_add_taglen(&buf, SEQUENCE, fields_len); + + /* Add the already-encoded mechanism list as mechTypes. */ + k5_der_add_value(&buf, CONTEXT | 0x00, spnego_ctx->DER_mechTypes.value, + spnego_ctx->DER_mechTypes.length); + + if (token != NULL) { + k5_der_add_taglen(&buf, CONTEXT | 0x02, f2len); + k5_der_add_value(&buf, OCTET_STRING, token->value, + token->length); + } + + if (mic != GSS_C_NO_BUFFER) { + uint8_t id = negHintsCompat ? SEQUENCE : OCTET_STRING; + k5_der_add_taglen(&buf, CONTEXT | 0x03, f3len); + k5_der_add_value(&buf, id, mic->value, mic->length); + } + + assert(buf.len == framed_len); + outbuf->length = framed_len; + outbuf->value = t; + + return (0); +} + +/* + * create the server side spnego token passed back to + * gss_accept_sec_context and eventually up to the application program + * and over to the client. + */ +static OM_uint32 +make_spnego_tokenTarg_msg(uint8_t status, gss_OID mech_wanted, + gss_buffer_t token, gss_buffer_t mic, + send_token_flag sendtoken, + gss_buffer_t outbuf) +{ + size_t f0len, f1len, f2len, f3len, fields_len, seq_len, choice_len; + uint8_t *t; + struct k5buf buf; + + if (outbuf == GSS_C_NO_BUFFER) + return (GSS_S_DEFECTIVE_TOKEN); + if (sendtoken == INIT_TOKEN_SEND && mech_wanted == GSS_C_NO_OID) + return (GSS_S_DEFECTIVE_TOKEN); + + outbuf->length = 0; + outbuf->value = NULL; + + /* Calculate the length of each field and the total fields length. */ + fields_len = 0; + /* negState [0] ENUMERATED { ... } OPTIONAL */ + f0len = k5_der_value_len(1); + fields_len += k5_der_value_len(f0len); + if (sendtoken == INIT_TOKEN_SEND) { + /* supportedMech [1] MechType OPTIONAL */ + f1len = k5_der_value_len(mech_wanted->length); + fields_len += k5_der_value_len(f1len); + } + if (token != NULL && token->length > 0) { + /* mechToken [2] OCTET STRING OPTIONAL */ + f2len = k5_der_value_len(token->length); + fields_len += k5_der_value_len(f2len); + } + if (mic != NULL) { + /* mechListMIC [3] OCTET STRING OPTIONAL */ + f3len = k5_der_value_len(mic->length); + fields_len += k5_der_value_len(f3len); + } + + /* Calculate the length of the sequence and choice. */ + seq_len = k5_der_value_len(fields_len); + choice_len = k5_der_value_len(seq_len); + + /* Allocate space and prepare a buffer. */ + t = gssalloc_malloc(choice_len); + if (t == NULL) + return (GSS_S_DEFECTIVE_TOKEN); + k5_buf_init_fixed(&buf, t, choice_len); + + /* Add the choice tag and begin the sequence. */ + k5_der_add_taglen(&buf, CONTEXT | 0x01, seq_len); + k5_der_add_taglen(&buf, SEQUENCE, fields_len); + + /* Add the negState field. */ + k5_der_add_taglen(&buf, CONTEXT | 0x00, f0len); + k5_der_add_value(&buf, ENUMERATED, &status, 1); + + if (sendtoken == INIT_TOKEN_SEND) { + /* Add the supportedMech field. */ + k5_der_add_taglen(&buf, CONTEXT | 0x01, f1len); + k5_der_add_value(&buf, MECH_OID, mech_wanted->elements, + mech_wanted->length); + } + + if (token != NULL && token->length > 0) { + /* Add the mechToken field. */ + k5_der_add_taglen(&buf, CONTEXT | 0x02, f2len); + k5_der_add_value(&buf, OCTET_STRING, token->value, + token->length); + } + + if (mic != NULL) { + /* Add the mechListMIC field. */ + k5_der_add_taglen(&buf, CONTEXT | 0x03, f3len); + k5_der_add_value(&buf, OCTET_STRING, mic->value, mic->length); + } + + assert(buf.len == choice_len); + outbuf->length = choice_len; + outbuf->value = t; + + return (0); +} + +/* Advance in past the [APPLICATION 0] tag and thisMech field of an + * InitialContextToken encoding, checking that thisMech matches mech. */ +static int +verify_token_header(struct k5input *in, gss_OID_const mech) +{ + gss_OID_desc oid; + struct k5input field; + + if (!k5_der_get_value(in, HEADER_ID, in)) + return (G_BAD_TOK_HEADER); + if (!k5_der_get_value(in, MECH_OID, &field)) + return (G_BAD_TOK_HEADER); + + oid.length = field.len; + oid.elements = (uint8_t *)field.ptr; + return g_OID_equal(&oid, mech) ? 0 : G_WRONG_MECH; +} + +/* + * Return non-zero if the oid is one of the kerberos mech oids, + * otherwise return zero. + * + * N.B. There are 3 oids that represent the kerberos mech: + * RFC-specified GSS_MECH_KRB5_OID, + * Old pre-RFC GSS_MECH_KRB5_OLD_OID, + * Incorrect MS GSS_MECH_KRB5_WRONG_OID + */ + +static int +is_kerb_mech(gss_OID oid) +{ + int answer = 0; + OM_uint32 minor; + extern const gss_OID_set_desc * const gss_mech_set_krb5_both; + + (void) gss_test_oid_set_member(&minor, + oid, (gss_OID_set)gss_mech_set_krb5_both, &answer); + + return (answer); +} diff --git a/krb5-1.21.3/src/lib/gssapi32.def b/krb5-1.21.3/src/lib/gssapi32.def new file mode 100644 index 00000000..a5a1e4a9 --- /dev/null +++ b/krb5-1.21.3/src/lib/gssapi32.def @@ -0,0 +1,191 @@ +;---------------------------------------------------- +; GSSAPI32.DEF - GSSAPI32.DLL module definition file +;---------------------------------------------------- + +;LIBRARY GSSAPI32 +DESCRIPTION 'Base Generic Security Service API' +HEAPSIZE 8192 + +EXPORTS + gss_acquire_cred @10 + gss_release_cred @54 + gss_init_sec_context @27 + gss_accept_sec_context @9 + gss_process_context_token @52 + gss_delete_sec_context @17 + gss_context_time @15 + gss_sign @59 + gss_verify @64 + gss_seal @58 + gss_unseal @62 + gss_display_status @19 + gss_indicate_mechs @26 + gss_compare_name @14 + gss_display_name @18 + gss_import_name @24 + gss_release_name @55 + gss_release_buffer @53 + gss_release_oid_set @57 + gss_inquire_cred @29 +; +; GSS-API v2 additional credential calls +; + gss_add_cred @11 + gss_inquire_cred_by_mech @30 +; +; GSS-API v2 additional context-level calls +; + gss_inquire_context @28 + gss_wrap_size_limit @67 + gss_export_sec_context @22 + gss_import_sec_context @25 +; +; GSS-API v2 additional calls for OID and OID_set operations +; + gss_release_oid + gss_create_empty_oid_set @16 + gss_add_oid_set_member @12 + gss_test_oid_set_member @61 + gss_oid_to_str @51 + gss_str_to_oid @60 +; +; GSS-API v2 renamed message protection calls +; + gss_wrap @66 + gss_unwrap @63 + gss_get_mic @23 + gss_verify_mic @65 +; +; GSS-API v2 future extensions +; + gss_inquire_names_for_mech @32 + gss_inquire_mechs_for_name @31 + gss_canonicalize_name @13 + gss_export_name @21 + gss_duplicate_name @20 +; +; Krb5 specific function extensions +; + gss_krb5_get_tkt_flags @37 + gss_krb5_copy_ccache @34 + gss_krb5_ccache_name @33 + gss_krb5_set_allowable_enctypes @38 + gss_krb5_export_lucid_sec_context @35 + gss_krb5_free_lucid_sec_context @36 + krb5_gss_register_acceptor_identity @69 +; +; GSS-API variables +; + gss_nt_krb5_name @45 DATA + gss_nt_krb5_principal @46 DATA + gss_nt_user_name @50 DATA + gss_nt_machine_uid_name @47 DATA + gss_nt_string_uid_name @49 DATA + gss_nt_service_name @48 DATA + GSS_C_NT_USER_NAME @7 DATA + GSS_C_NT_MACHINE_UID_NAME @5 DATA + GSS_C_NT_STRING_UID_NAME @6 DATA + GSS_C_NT_HOSTBASED_SERVICE @3 DATA + GSS_C_NT_HOSTBASED_SERVICE_X @4 DATA + GSS_C_NT_ANONYMOUS @1 DATA + GSS_C_NT_EXPORT_NAME @2 DATA + krb5_gss_oid_array @68 DATA + gss_mech_krb5 @39 DATA + gss_mech_krb5_old @40 DATA + gss_mech_set_krb5 @42 DATA + gss_mech_set_krb5_old @44 DATA + gss_mech_set_krb5_both @43 DATA + GSS_KRB5_NT_PRINCIPAL_NAME @8 DATA + gss_mech_krb5_wrong @41 DATA + +; Added in krb5 1.7-1.9 + gss_acquire_cred_impersonate_name @70 + gss_acquire_cred_with_password @71 + gss_add_buffer_set_member @72 + gss_add_cred_impersonate_name @73 + gss_complete_auth_token @74 + gss_create_empty_buffer_set @75 + gss_delete_name_attribute @76 + gss_display_mech_attr @77 + gss_display_name_ext @78 + gss_export_name_composite @79 + gss_get_name_attribute @80 + gss_indicate_mechs_by_attrs @81 + gss_inquire_attrs_for_mech @82 + gss_inquire_cred_by_oid @83 + gss_inquire_mech_for_saslname @84 + gss_inquire_name @85 + gss_inquire_saslname_for_mech @86 + gss_inquire_sec_context_by_oid @87 + gsskrb5_extract_authtime_from_sec_context @88 + gsskrb5_extract_authz_data_from_sec_context @89 + gss_krb5_import_cred @90 + gss_krb5_set_cred_rcache @91 + gss_map_name_to_any @92 + gss_pseudo_random @93 + gss_release_any_name_mapping @94 + gss_release_buffer_set @95 + gss_release_iov_buffer @96 + gss_set_cred_option @97 + gss_set_name_attribute @98 + gss_set_neg_mechs @99 + gss_set_sec_context_option @100 + gss_store_cred @101 + gss_unwrap_aead @102 + gss_unwrap_iov @103 + gss_wrap_aead @104 + gss_wrap_iov @105 + gss_wrap_iov_length @106 + + GSS_C_INQ_SSPI_SESSION_KEY @107 DATA + GSS_C_MA_AUTH_INIT @108 DATA + GSS_C_MA_AUTH_INIT_ANON @109 DATA + GSS_C_MA_AUTH_INIT_INIT @110 DATA + GSS_C_MA_AUTH_TARG @111 DATA + GSS_C_MA_AUTH_TARG_ANON @112 DATA + GSS_C_MA_AUTH_TARG_INIT @113 DATA + GSS_C_MA_CBINDINGS @114 DATA + GSS_C_MA_COMPRESS @115 DATA + GSS_C_MA_CONF_PROT @116 DATA + GSS_C_MA_CTX_TRANS @117 DATA + GSS_C_MA_DELEG_CRED @118 DATA + GSS_C_MA_DEPRECATED @119 DATA + GSS_C_MA_INTEG_PROT @120 DATA + GSS_C_MA_ITOK_FRAMED @121 DATA + GSS_C_MA_MECH_COMPOSITE @122 DATA + GSS_C_MA_MECH_CONCRETE @123 DATA + GSS_C_MA_MECH_GLUE @124 DATA + GSS_C_MA_MECH_NEGO @125 DATA + GSS_C_MA_MECH_PSEUDO @126 DATA + GSS_C_MA_MIC @127 DATA + GSS_C_MA_NOT_DFLT_MECH @128 DATA + GSS_C_MA_NOT_MECH @129 DATA + GSS_C_MA_OOS_DET @130 DATA + GSS_C_MA_PFS @131 DATA + GSS_C_MA_PROT_READY @132 DATA + GSS_C_MA_REPLAY_DET @133 DATA + GSS_C_MA_WRAP @134 DATA + gss_mech_iakerb @135 DATA + gss_nt_exported_name @136 DATA + gss_nt_service_name_v2 @137 DATA +; Added in 1.10 + gss_localname @138 +; Added in 1.11 + gss_acquire_cred_from @139 + gss_add_cred_from @140 + gss_store_cred_into @141 + gss_export_cred @142 + gss_import_cred @143 +; Added in 1.12 + gss_get_mic_iov @144 + gss_get_mic_iov_length @145 + gss_verify_mic_iov @146 +; Added in 1.14 + GSS_KRB5_CRED_NO_CI_FLAGS_X @147 DATA +; Added in 1.16 + GSS_KRB5_GET_CRED_IMPERSONATOR @148 DATA + GSS_C_SEC_CONTEXT_SASL_SSF @149 DATA +; Added in 1.17 + GSS_KRB5_NT_ENTERPRISE_NAME @150 DATA +; Added in 1.19 + GSS_KRB5_NT_X509_CERT @151 DATA diff --git a/krb5-1.21.3/src/lib/kadm5/Makefile.in b/krb5-1.21.3/src/lib/kadm5/Makefile.in new file mode 100644 index 00000000..3ff71c42 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/Makefile.in @@ -0,0 +1,113 @@ +mydir=lib$(S)kadm5 +BUILDTOP=$(REL)..$(S).. +SUBDIRS = clnt srv + +##DOSBUILDTOP = ..\.. + +kadm_err.$(OBJEXT): kadm_err.c +chpass_util_strings.$(OBJEXT): chpass_util_strings.c + +kadm_err.c kadm_err.h: $(srcdir)/kadm_err.et +chpass_util_strings.c chpass_util_strings.h: $(srcdir)/chpass_util_strings.et + +clean: + $(RM) kadm_err.c kadm_err.h kadm_err.o + $(RM) chpass_util_strings.c chpass_util_strings.h chpass_util_strings.o + +SRCS = kadm_err.c \ + chpass_util_strings.c \ + $(srcdir)/misc_free.c \ + $(srcdir)/kadm_rpc_xdr.c \ + $(srcdir)/chpass_util.c \ + $(srcdir)/alt_prof.c \ + $(srcdir)/str_conv.c \ + $(srcdir)/logger.c + +OBJS = kadm_err.$(OBJEXT) \ + chpass_util_strings.$(OBJEXT) \ + misc_free.$(OBJEXT) \ + kadm_rpc_xdr.$(OBJEXT) \ + chpass_util.$(OBJEXT) \ + alt_prof.$(OBJEXT) \ + str_conv.$(OBJEXT) \ + logger.$(OBJEXT) + +STLIBOBJS = \ + kadm_err.o \ + chpass_util_strings.o \ + misc_free.o \ + kadm_rpc_xdr.o \ + chpass_util.o \ + alt_prof.o \ + str_conv.o \ + logger.o + +HDRDIR=$(BUILDTOP)/include/kadm5 +HDRS = $(HDRDIR)/admin.h \ + $(HDRDIR)/admin_internal.h \ + $(HDRDIR)/admin_xdr.h \ + $(HDRDIR)/kadm_rpc.h \ + $(HDRDIR)/server_internal.h \ + $(HDRDIR)/chpass_util_strings.h \ + $(HDRDIR)/kadm_err.h + +BUILD_HDRS = chpass_util_strings.h kadm_err.h +SRC_HDRS = admin.h admin_internal.h admin_xdr.h kadm_rpc.h \ + server_internal.h + +$(HDRS): includes + +includes: $(SRC_HDRS) $(BUILD_HDRS) + if [ -d $(HDRDIR) ]; then :; else mkdir -p $(HDRDIR); fi + for i in $(SRC_HDRS) ; do \ + i=`basename $$i`; \ + if cmp $(srcdir)/$$i $(HDRDIR)/$$i >/dev/null 2>&1; then :; \ + else \ + (set -x; $(RM) $(HDRDIR)/$$i; \ + $(CP) $(srcdir)/$$i $(HDRDIR)/$$i) ; \ + fi ; \ + done + for i in $(BUILD_HDRS) ; do \ + i=`basename $$i`; \ + if cmp $$i $(HDRDIR)/$$i >/dev/null 2>&1; then :; \ + else \ + (set -x; $(RM) $(HDRDIR)/$$i; \ + $(CP) $$i $(HDRDIR)/$$i) ; \ + fi ; \ + done + +clean-unix:: + $(RM) -r $(HDRDIR) + +all-prerecurse: includes +all-prerecurse: all-libobjs + +all-windows: $(OBJS) + +t_kadm5clnt: t_kadm5.o $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_kadm5.o $(KADMCLNT_LIBS) $(KRB5_BASE_LIBS) + +t_kadm5srv: t_kadm5.o $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_kadm5.o $(KADMSRV_LIBS) $(KRB5_BASE_LIBS) + +check-pytests: t_kadm5clnt t_kadm5srv + $(RUNPYTEST) $(srcdir)/t_kadm5.py $(PYTESTFLAGS) + +generate-files-mac-prerecurse: includes + +check-windows: + +clean-unix:: clean-libobjs + $(RM) t_kadm5clnt t_kadm5srv t_kadm5.o + +clean-windows:: + +install-headers-unix install: $(BUILD_HDRS) + $(INSTALL_DATA) $(srcdir)/admin.h $(DESTDIR)$(KRB5_INCDIR)$(S)kadm5$(S)admin.h + $(INSTALL_DATA) chpass_util_strings.h $(DESTDIR)$(KRB5_INCDIR)$(S)kadm5$(S)chpass_util_strings.h + $(INSTALL_DATA) kadm_err.h $(DESTDIR)$(KRB5_INCDIR)$(S)kadm5$(S)kadm_err.h + +depend: includes + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/kadm5/admin.h b/krb5-1.21.3/src/lib/kadm5/admin.h new file mode 100644 index 00000000..296c86fa --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/admin.h @@ -0,0 +1,500 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kadm5/admin.h */ +/* + * Copyright 2001, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ + +/* + * This API is not considered as stable as the main krb5 API. + * + * - We may make arbitrary incompatible changes between feature + * releases (e.g. from 1.7 to 1.8). + * - We will make some effort to avoid making incompatible changes for + * bugfix releases, but will make them if necessary. + */ + +#ifndef __KADM5_ADMIN_H__ +#define __KADM5_ADMIN_H__ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef KADM5INT_BEGIN_DECLS +#if defined(__cplusplus) +#define KADM5INT_BEGIN_DECLS extern "C" { +#define KADM5INT_END_DECLS } +#else +#define KADM5INT_BEGIN_DECLS +#define KADM5INT_END_DECLS +#endif +#endif + +KADM5INT_BEGIN_DECLS + +#define KADM5_ADMIN_SERVICE "kadmin/admin" +#define KADM5_CHANGEPW_SERVICE "kadmin/changepw" +#define KADM5_HIST_PRINCIPAL "kadmin/history" +#define KADM5_KIPROP_HOST_SERVICE "kiprop" + +typedef krb5_principal kadm5_princ_t; +typedef char *kadm5_policy_t; +typedef long kadm5_ret_t; + +#define KADM5_PW_FIRST_PROMPT \ + (error_message(CHPASS_UTIL_NEW_PASSWORD_PROMPT)) +#define KADM5_PW_SECOND_PROMPT \ + (error_message(CHPASS_UTIL_NEW_PASSWORD_AGAIN_PROMPT)) + +/* + * Successful return code + */ +#define KADM5_OK 0 + +/* + * Field masks + */ + +/* kadm5_principal_ent_t */ +#define KADM5_PRINCIPAL 0x000001 +#define KADM5_PRINC_EXPIRE_TIME 0x000002 +#define KADM5_PW_EXPIRATION 0x000004 +#define KADM5_LAST_PWD_CHANGE 0x000008 +#define KADM5_ATTRIBUTES 0x000010 +#define KADM5_MAX_LIFE 0x000020 +#define KADM5_MOD_TIME 0x000040 +#define KADM5_MOD_NAME 0x000080 +#define KADM5_KVNO 0x000100 +#define KADM5_MKVNO 0x000200 +#define KADM5_AUX_ATTRIBUTES 0x000400 +#define KADM5_POLICY 0x000800 +#define KADM5_POLICY_CLR 0x001000 +/* version 2 masks */ +#define KADM5_MAX_RLIFE 0x002000 +#define KADM5_LAST_SUCCESS 0x004000 +#define KADM5_LAST_FAILED 0x008000 +#define KADM5_FAIL_AUTH_COUNT 0x010000 +#define KADM5_KEY_DATA 0x020000 +#define KADM5_TL_DATA 0x040000 +#ifdef notyet /* Novell */ +#define KADM5_CPW_FUNCTION 0x080000 +#define KADM5_RANDKEY_USED 0x100000 +#endif +#define KADM5_LOAD 0x200000 +#define KADM5_KEY_HIST 0x400000 + +/* all but KEY_DATA, TL_DATA, LOAD */ +#define KADM5_PRINCIPAL_NORMAL_MASK 0x41ffff + + +/* kadm5_policy_ent_t */ +#define KADM5_PW_MAX_LIFE 0x00004000 +#define KADM5_PW_MIN_LIFE 0x00008000 +#define KADM5_PW_MIN_LENGTH 0x00010000 +#define KADM5_PW_MIN_CLASSES 0x00020000 +#define KADM5_PW_HISTORY_NUM 0x00040000 +#define KADM5_REF_COUNT 0x00080000 +#define KADM5_PW_MAX_FAILURE 0x00100000 +#define KADM5_PW_FAILURE_COUNT_INTERVAL 0x00200000 +#define KADM5_PW_LOCKOUT_DURATION 0x00400000 +#define KADM5_POLICY_ATTRIBUTES 0x00800000 +#define KADM5_POLICY_MAX_LIFE 0x01000000 +#define KADM5_POLICY_MAX_RLIFE 0x02000000 +#define KADM5_POLICY_ALLOWED_KEYSALTS 0x04000000 +#define KADM5_POLICY_TL_DATA 0x08000000 + +/* kadm5_config_params */ +#define KADM5_CONFIG_REALM 0x00000001 +#define KADM5_CONFIG_DBNAME 0x00000002 +#define KADM5_CONFIG_MKEY_NAME 0x00000004 +#define KADM5_CONFIG_MAX_LIFE 0x00000008 +#define KADM5_CONFIG_MAX_RLIFE 0x00000010 +#define KADM5_CONFIG_EXPIRATION 0x00000020 +#define KADM5_CONFIG_FLAGS 0x00000040 +/*#define KADM5_CONFIG_ADMIN_KEYTAB 0x00000080*/ +#define KADM5_CONFIG_STASH_FILE 0x00000100 +#define KADM5_CONFIG_ENCTYPE 0x00000200 +#define KADM5_CONFIG_ADBNAME 0x00000400 +#define KADM5_CONFIG_ADB_LOCKFILE 0x00000800 +#define KADM5_CONFIG_KADMIND_LISTEN 0x00001000 +#define KADM5_CONFIG_ACL_FILE 0x00002000 +#define KADM5_CONFIG_KADMIND_PORT 0x00004000 +#define KADM5_CONFIG_ENCTYPES 0x00008000 +#define KADM5_CONFIG_ADMIN_SERVER 0x00010000 +#define KADM5_CONFIG_DICT_FILE 0x00020000 +#define KADM5_CONFIG_MKEY_FROM_KBD 0x00040000 +#define KADM5_CONFIG_KPASSWD_PORT 0x00080000 +#define KADM5_CONFIG_OLD_AUTH_GSSAPI 0x00100000 +#define KADM5_CONFIG_NO_AUTH 0x00200000 +#define KADM5_CONFIG_AUTH_NOFALLBACK 0x00400000 +#define KADM5_CONFIG_KPASSWD_LISTEN 0x00800000 +#define KADM5_CONFIG_IPROP_ENABLED 0x01000000 +#define KADM5_CONFIG_ULOG_SIZE 0x02000000 +#define KADM5_CONFIG_POLL_TIME 0x04000000 +#define KADM5_CONFIG_IPROP_LOGFILE 0x08000000 +#define KADM5_CONFIG_IPROP_PORT 0x10000000 +#define KADM5_CONFIG_KVNO 0x20000000 +#define KADM5_CONFIG_IPROP_RESYNC_TIMEOUT 0x40000000 +#define KADM5_CONFIG_IPROP_LISTEN 0x80000000 +/* + * permission bits + */ +#define KADM5_PRIV_GET 0x01 +#define KADM5_PRIV_ADD 0x02 +#define KADM5_PRIV_MODIFY 0x04 +#define KADM5_PRIV_DELETE 0x08 + +/* + * API versioning constants + */ +#define KADM5_MASK_BITS 0xffffff00 + +#define KADM5_STRUCT_VERSION_MASK 0x12345600 +#define KADM5_STRUCT_VERSION_1 (KADM5_STRUCT_VERSION_MASK|0x01) +#define KADM5_STRUCT_VERSION KADM5_STRUCT_VERSION_1 + +#define KADM5_API_VERSION_MASK 0x12345700 +#define KADM5_API_VERSION_2 (KADM5_API_VERSION_MASK|0x02) +#define KADM5_API_VERSION_3 (KADM5_API_VERSION_MASK|0x03) +#define KADM5_API_VERSION_4 (KADM5_API_VERSION_MASK|0x04) + +typedef struct _kadm5_principal_ent_t { + krb5_principal principal; + krb5_timestamp princ_expire_time; + krb5_timestamp last_pwd_change; + krb5_timestamp pw_expiration; + krb5_deltat max_life; + krb5_principal mod_name; + krb5_timestamp mod_date; + krb5_flags attributes; + krb5_kvno kvno; + krb5_kvno mkvno; + char *policy; + long aux_attributes; + + /* version 2 fields */ + krb5_deltat max_renewable_life; + krb5_timestamp last_success; + krb5_timestamp last_failed; + krb5_kvno fail_auth_count; + krb5_int16 n_key_data; + krb5_int16 n_tl_data; + krb5_tl_data *tl_data; + krb5_key_data *key_data; +} kadm5_principal_ent_rec, *kadm5_principal_ent_t; + +typedef struct _kadm5_policy_ent_t { + char *policy; + long pw_min_life; + long pw_max_life; + long pw_min_length; + long pw_min_classes; + long pw_history_num; + long policy_refcnt; /* no longer used */ + + /* version 3 fields */ + krb5_kvno pw_max_fail; + krb5_deltat pw_failcnt_interval; + krb5_deltat pw_lockout_duration; + + /* version 4 fields */ + krb5_flags attributes; + krb5_deltat max_life; + krb5_deltat max_renewable_life; + char *allowed_keysalts; + krb5_int16 n_tl_data; + krb5_tl_data *tl_data; +} kadm5_policy_ent_rec, *kadm5_policy_ent_t; + +/* + * Data structure returned by kadm5_get_config_params() + */ +typedef struct _kadm5_config_params { + long mask; + char * realm; + int kadmind_port; + int kpasswd_port; + + char * admin_server; +#ifdef notyet /* Novell */ /* ABI change? */ + char * kpasswd_server; +#endif + + /* Deprecated except for db2 backwards compatibility. Don't add + new uses except as fallbacks for parameters that should be + specified in the database module section of the config + file. */ + char * dbname; + + char * acl_file; + char * dict_file; + + int mkey_from_kbd; + char * stash_file; + char * mkey_name; + krb5_enctype enctype; + krb5_deltat max_life; + krb5_deltat max_rlife; + krb5_timestamp expiration; + krb5_flags flags; + krb5_key_salt_tuple *keysalts; + krb5_int32 num_keysalts; + krb5_kvno kvno; + bool_t iprop_enabled; + uint32_t iprop_ulogsize; + krb5_deltat iprop_poll_time; + char * iprop_logfile; +/* char * iprop_server;*/ + int iprop_port; + int iprop_resync_timeout; + char * kadmind_listen; + char * kpasswd_listen; + char * iprop_listen; +} kadm5_config_params; + +typedef struct _kadm5_key_data { + krb5_kvno kvno; + krb5_keyblock key; + krb5_keysalt salt; +} kadm5_key_data; + +/* + * functions + */ + +/* The use_kdc_config parameter is no longer used, as configuration is + * retrieved from the context profile. */ +krb5_error_code kadm5_get_config_params(krb5_context context, + int use_kdc_config, + kadm5_config_params *params_in, + kadm5_config_params *params_out); + +krb5_error_code kadm5_free_config_params(krb5_context context, + kadm5_config_params *params); + +krb5_error_code kadm5_get_admin_service_name(krb5_context, char *, + char *, size_t); + +/* + * For all initialization functions, the caller must first initialize + * a context with kadm5_init_krb5_context which will survive as long + * as the resulting handle. The caller should free the context with + * krb5_free_context. + */ + +kadm5_ret_t kadm5_init(krb5_context context, char *client_name, + char *pass, char *service_name, + kadm5_config_params *params, + krb5_ui_4 struct_version, + krb5_ui_4 api_version, + char **db_args, + void **server_handle); +kadm5_ret_t kadm5_init_anonymous(krb5_context context, char *client_name, + char *service_name, + kadm5_config_params *params, + krb5_ui_4 struct_version, + krb5_ui_4 api_version, + char **db_args, + void **server_handle); +kadm5_ret_t kadm5_init_with_password(krb5_context context, + char *client_name, + char *pass, + char *service_name, + kadm5_config_params *params, + krb5_ui_4 struct_version, + krb5_ui_4 api_version, + char **db_args, + void **server_handle); +kadm5_ret_t kadm5_init_with_skey(krb5_context context, + char *client_name, + char *keytab, + char *service_name, + kadm5_config_params *params, + krb5_ui_4 struct_version, + krb5_ui_4 api_version, + char **db_args, + void **server_handle); +kadm5_ret_t kadm5_init_with_creds(krb5_context context, + char *client_name, + krb5_ccache cc, + char *service_name, + kadm5_config_params *params, + krb5_ui_4 struct_version, + krb5_ui_4 api_version, + char **db_args, + void **server_handle); +kadm5_ret_t kadm5_lock(void *server_handle); +kadm5_ret_t kadm5_unlock(void *server_handle); +kadm5_ret_t kadm5_flush(void *server_handle); +kadm5_ret_t kadm5_destroy(void *server_handle); +kadm5_ret_t kadm5_create_principal(void *server_handle, + kadm5_principal_ent_t ent, + long mask, char *pass); +kadm5_ret_t kadm5_create_principal_3(void *server_handle, + kadm5_principal_ent_t ent, + long mask, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + char *pass); +kadm5_ret_t kadm5_delete_principal(void *server_handle, + krb5_principal principal); +kadm5_ret_t kadm5_modify_principal(void *server_handle, + kadm5_principal_ent_t ent, + long mask); +kadm5_ret_t kadm5_rename_principal(void *server_handle, + krb5_principal,krb5_principal); +kadm5_ret_t kadm5_get_principal(void *server_handle, + krb5_principal principal, + kadm5_principal_ent_t ent, + long mask); +kadm5_ret_t kadm5_chpass_principal(void *server_handle, + krb5_principal principal, + char *pass); +kadm5_ret_t kadm5_chpass_principal_3(void *server_handle, + krb5_principal principal, + krb5_boolean keepold, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + char *pass); +kadm5_ret_t kadm5_randkey_principal(void *server_handle, + krb5_principal principal, + krb5_keyblock **keyblocks, + int *n_keys); +kadm5_ret_t kadm5_randkey_principal_3(void *server_handle, + krb5_principal principal, + krb5_boolean keepold, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + krb5_keyblock **keyblocks, + int *n_keys); + +kadm5_ret_t kadm5_setkey_principal(void *server_handle, + krb5_principal principal, + krb5_keyblock *keyblocks, + int n_keys); + +kadm5_ret_t kadm5_setkey_principal_3(void *server_handle, + krb5_principal principal, + krb5_boolean keepold, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + krb5_keyblock *keyblocks, + int n_keys); + +kadm5_ret_t kadm5_setkey_principal_4(void *server_handle, + krb5_principal principal, + krb5_boolean keepold, + kadm5_key_data *key_data, + int n_key_data); + +kadm5_ret_t kadm5_decrypt_key(void *server_handle, + kadm5_principal_ent_t entry, krb5_int32 + ktype, krb5_int32 stype, krb5_int32 + kvno, krb5_keyblock *keyblock, + krb5_keysalt *keysalt, int *kvnop); + +kadm5_ret_t kadm5_create_policy(void *server_handle, + kadm5_policy_ent_t ent, + long mask); +kadm5_ret_t kadm5_delete_policy(void *server_handle, + kadm5_policy_t policy); +kadm5_ret_t kadm5_modify_policy(void *server_handle, + kadm5_policy_ent_t ent, + long mask); +kadm5_ret_t kadm5_get_policy(void *server_handle, + kadm5_policy_t policy, + kadm5_policy_ent_t ent); +kadm5_ret_t kadm5_get_privs(void *server_handle, + long *privs); + +kadm5_ret_t kadm5_chpass_principal_util(void *server_handle, + krb5_principal princ, + char *new_pw, + char **ret_pw, + char *msg_ret, + unsigned int msg_len); + +kadm5_ret_t kadm5_free_principal_ent(void *server_handle, + kadm5_principal_ent_t + ent); +kadm5_ret_t kadm5_free_policy_ent(void *server_handle, + kadm5_policy_ent_t ent); + +kadm5_ret_t kadm5_get_principals(void *server_handle, + char *exp, char ***princs, + int *count); + +kadm5_ret_t kadm5_get_policies(void *server_handle, + char *exp, char ***pols, + int *count); + +kadm5_ret_t kadm5_free_key_data(void *server_handle, + krb5_int16 *n_key_data, + krb5_key_data *key_data); + +kadm5_ret_t kadm5_free_name_list(void *server_handle, char **names, + int count); + +krb5_error_code kadm5_init_krb5_context (krb5_context *); + +krb5_error_code kadm5_init_iprop(void *server_handle, char **db_args); + +kadm5_ret_t kadm5_get_principal_keys(void *server_handle, + krb5_principal principal, + krb5_kvno kvno, + kadm5_key_data **key_data, + int *n_key_data); + +kadm5_ret_t kadm5_purgekeys(void *server_handle, + krb5_principal principal, + int keepkvno); + +kadm5_ret_t kadm5_get_strings(void *server_handle, + krb5_principal principal, + krb5_string_attr **strings_out, + int *count_out); + +kadm5_ret_t kadm5_set_string(void *server_handle, + krb5_principal principal, + const char *key, + const char *value); + +kadm5_ret_t kadm5_free_strings(void *server_handle, + krb5_string_attr *strings, + int count); + +kadm5_ret_t kadm5_free_kadm5_key_data(krb5_context context, int n_key_data, + kadm5_key_data *key_data); + +KADM5INT_END_DECLS + +#endif /* __KADM5_ADMIN_H__ */ diff --git a/krb5-1.21.3/src/lib/kadm5/admin_internal.h b/krb5-1.21.3/src/lib/kadm5/admin_internal.h new file mode 100644 index 00000000..9be53883 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/admin_internal.h @@ -0,0 +1,80 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + */ + +#ifndef __KADM5_ADMIN_INTERNAL_H__ +#define __KADM5_ADMIN_INTERNAL_H__ + +#include + +#define KADM5_SERVER_HANDLE_MAGIC 0x12345800 + +#define CHECK_VERSIONS(struct_version, api_version, old_api_err, new_api_err) \ + { \ + if ((struct_version & KADM5_MASK_BITS) != KADM5_STRUCT_VERSION_MASK) \ + return KADM5_BAD_STRUCT_VERSION; \ + if (struct_version < KADM5_STRUCT_VERSION_1) \ + return KADM5_OLD_STRUCT_VERSION; \ + if (struct_version > KADM5_STRUCT_VERSION_1) \ + return KADM5_NEW_STRUCT_VERSION; \ + if ((api_version & KADM5_MASK_BITS) != KADM5_API_VERSION_MASK) \ + return KADM5_BAD_API_VERSION; \ + if (api_version < KADM5_API_VERSION_2) \ + return old_api_err; \ + if (api_version > KADM5_API_VERSION_4) \ + return new_api_err; \ + } + +#define GENERIC_CHECK_HANDLE(handle, old_api_err, new_api_err) \ + { \ + kadm5_server_handle_t srvr = handle; \ + \ + if (srvr == NULL) \ + return KADM5_BAD_SERVER_HANDLE; \ + if (srvr->magic_number != KADM5_SERVER_HANDLE_MAGIC) \ + return KADM5_BAD_SERVER_HANDLE; \ + CHECK_VERSIONS(srvr->struct_version, srvr->api_version, \ + old_api_err, new_api_err); \ + } + +/* + * _KADM5_CHECK_HANDLE calls the function _kadm5_check_handle and + * returns any non-zero error code that function returns. + * _kadm5_check_handle, in client_handle.c and server_handle.c, exists + * in both the server- and client- side libraries. In each library, + * it calls CHECK_HANDLE, which is defined by the appropriate + * _internal.h header file to call GENERIC_CHECK_HANDLE as well as + * CLIENT_CHECK_HANDLE and SERVER_CHECK_HANDLE. + * + * _KADM5_CHECK_HANDLE should be used by a function that needs to + * check the handle but wants to be the same code in both the client + * and server library; it makes a function call to the right handle + * checker. Code that only exists in one library can call the + * CHECK_HANDLE macro, which inlines the test instead of making + * another function call. + * + * Got that? + */ +#define _KADM5_CHECK_HANDLE(handle) \ + { int ecode; if ((ecode = _kadm5_check_handle((void *)handle))) return ecode;} + +int _kadm5_check_handle(void *handle); +kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle, + void *lhandle, + krb5_principal princ, + char *new_pw, + char **ret_pw, + char *msg_ret, + unsigned int msg_len); + +/* this is needed by the alt_prof code I stole. The functions + maybe shouldn't be named krb5_*, but they are. */ + +krb5_error_code +krb5_string_to_keysalts(const char *string, const char *tupleseps, + const char *ksaltseps, krb5_boolean dups, + krb5_key_salt_tuple **ksaltp, krb5_int32 *nksaltp); + +#endif /* __KADM5_ADMIN_INTERNAL_H__ */ diff --git a/krb5-1.21.3/src/lib/kadm5/admin_xdr.h b/krb5-1.21.3/src/lib/kadm5/admin_xdr.h new file mode 100644 index 00000000..9da98451 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/admin_xdr.h @@ -0,0 +1,73 @@ +/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + * + */ + +#include +#include "kadm_rpc.h" +#include "server_internal.h" + +bool_t xdr_ui_4(XDR *xdrs, krb5_ui_4 *objp); +bool_t xdr_nullstring(XDR *xdrs, char **objp); +bool_t xdr_nulltype(XDR *xdrs, void **objp, xdrproc_t proc); +bool_t xdr_krb5_timestamp(XDR *xdrs, krb5_timestamp *objp); +bool_t xdr_krb5_kvno(XDR *xdrs, krb5_kvno *objp); +bool_t xdr_krb5_deltat(XDR *xdrs, krb5_deltat *objp); +bool_t xdr_krb5_flags(XDR *xdrs, krb5_flags *objp); +bool_t xdr_krb5_ui_4(XDR *xdrs, krb5_ui_4 *objp); +bool_t xdr_krb5_int16(XDR *xdrs, krb5_int16 *objp); +bool_t xdr_krb5_ui_2(XDR *xdrs, krb5_ui_2 *objp); +bool_t xdr_krb5_key_data_nocontents(XDR *xdrs, krb5_key_data *objp); +bool_t xdr_krb5_key_salt_tuple(XDR *xdrs, krb5_key_salt_tuple *objp); +bool_t xdr_krb5_tl_data(XDR *xdrs, krb5_tl_data **tl_data_head); +bool_t xdr_kadm5_ret_t(XDR *xdrs, kadm5_ret_t *objp); +bool_t xdr_kadm5_principal_ent_rec_v1(XDR *xdrs, kadm5_principal_ent_rec *objp); +bool_t xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp); +bool_t xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp); +bool_t xdr_kadm5_policy_ent_t(XDR *xdrs, kadm5_policy_ent_t *objp); +bool_t xdr_kadm5_principal_ent_t(XDR *xdrs, kadm5_principal_ent_t *objp); +bool_t xdr_cprinc_arg(XDR *xdrs, cprinc_arg *objp); +bool_t xdr_cprinc3_arg(XDR *xdrs, cprinc3_arg *objp); +bool_t xdr_generic_ret(XDR *xdrs, generic_ret *objp); +bool_t xdr_dprinc_arg(XDR *xdrs, dprinc_arg *objp); +bool_t xdr_mprinc_arg(XDR *xdrs, mprinc_arg *objp); +bool_t xdr_rprinc_arg(XDR *xdrs, rprinc_arg *objp); +bool_t xdr_chpass_arg(XDR *xdrs, chpass_arg *objp); +bool_t xdr_chpass3_arg(XDR *xdrs, chpass3_arg *objp); +bool_t xdr_setkey_arg(XDR *xdrs, setkey_arg *objp); +bool_t xdr_setkey3_arg(XDR *xdrs, setkey3_arg *objp); +bool_t xdr_setkey4_arg(XDR *xdrs, setkey4_arg *objp); +bool_t xdr_chrand_arg(XDR *xdrs, chrand_arg *objp); +bool_t xdr_chrand3_arg(XDR *xdrs, chrand3_arg *objp); +bool_t xdr_chrand_ret(XDR *xdrs, chrand_ret *objp); +bool_t xdr_gprinc_arg(XDR *xdrs, gprinc_arg *objp); +bool_t xdr_gprinc_ret(XDR *xdrs, gprinc_ret *objp); +bool_t xdr_gprincs_arg(XDR *xdrs, gprincs_arg *objp); +bool_t xdr_gprincs_ret(XDR *xdrs, gprincs_ret *objp); +bool_t xdr_cpol_arg(XDR *xdrs, cpol_arg *objp); +bool_t xdr_dpol_arg(XDR *xdrs, dpol_arg *objp); +bool_t xdr_mpol_arg(XDR *xdrs, mpol_arg *objp); +bool_t xdr_gpol_arg(XDR *xdrs, gpol_arg *objp); +bool_t xdr_gpol_ret(XDR *xdrs, gpol_ret *objp); +bool_t xdr_gpols_arg(XDR *xdrs, gpols_arg *objp); +bool_t xdr_gpols_ret(XDR *xdrs, gpols_ret *objp); +bool_t xdr_getprivs_ret(XDR *xdrs, getprivs_ret *objp); +bool_t xdr_purgekeys_arg(XDR *xdrs, purgekeys_arg *objp); +bool_t xdr_gstrings_arg(XDR *xdrs, gstrings_arg *objp); +bool_t xdr_gstrings_ret(XDR *xdrs, gstrings_ret *objp); +bool_t xdr_sstring_arg(XDR *xdrs, sstring_arg *objp); +bool_t xdr_krb5_principal(XDR *xdrs, krb5_principal *objp); +bool_t xdr_krb5_octet(XDR *xdrs, krb5_octet *objp); +bool_t xdr_krb5_int32(XDR *xdrs, krb5_int32 *objp); +bool_t xdr_krb5_enctype(XDR *xdrs, krb5_enctype *objp); +bool_t xdr_krb5_salttype(XDR *xdrs, krb5_int32 *objp); +bool_t xdr_krb5_keyblock(XDR *xdrs, krb5_keyblock *objp); +bool_t xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp); +bool_t xdr_krb5_string_attr(XDR *xdrs, krb5_string_attr *objp); +bool_t xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp); +bool_t xdr_kadm5_key_data(XDR *xdrs, kadm5_key_data *objp); +bool_t xdr_getpkeys_arg(XDR *xdrs, getpkeys_arg *objp); +bool_t xdr_getpkeys_ret(XDR *xdrs, getpkeys_ret *objp); diff --git a/krb5-1.21.3/src/lib/kadm5/alt_prof.c b/krb5-1.21.3/src/lib/kadm5/alt_prof.c new file mode 100644 index 00000000..e8c1f51c --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/alt_prof.c @@ -0,0 +1,799 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kadm5/alt_prof.c */ +/* + * Copyright 1995,2001,2008,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* Implement alternate profile file handling. */ +#include "k5-int.h" +#include "fake-addrinfo.h" +#include +#include "adm_proto.h" +#include +#include +#include + +static krb5_key_salt_tuple * +copy_key_salt_tuple(krb5_key_salt_tuple *ksalt, krb5_int32 len) +{ + krb5_key_salt_tuple *knew; + + knew = calloc(len, sizeof(krb5_key_salt_tuple)); + if (knew == NULL) + return NULL; + memcpy(knew, ksalt, len * sizeof(krb5_key_salt_tuple)); + return knew; +} + +/* + * krb5_aprof_getvals() - Get values from alternate profile. + * + * Parameters: + * acontext - opaque context for alternate profile. + * hierarchy - hierarchy of value to retrieve. + * retdata - Returned data values. + * + * Returns: + * error codes from profile_get_values() + */ +krb5_error_code +krb5_aprof_getvals(krb5_pointer acontext, const char **hierarchy, + char ***retdata) +{ + return profile_get_values(acontext, hierarchy, retdata); +} + +/* + * krb5_aprof_get_boolean() + * + * Parameters: + * acontext - opaque context for alternate profile + * hierarchy - hierarchy of value to retrieve + * retdata - Returned data value + * Returns: + * error codes + */ + +static krb5_error_code +string_to_boolean(const char *string, krb5_boolean *out) +{ + static const char *const yes[] = { "y", "yes", "true", "t", "1", "on" }; + static const char *const no[] = { "n", "no", "false", "f", "nil", "0", + "off" }; + unsigned int i; + + for (i = 0; i < sizeof(yes) / sizeof(yes[0]); i++) { + if (!strcasecmp(string, yes[i])) { + *out = TRUE; + return 0; + } + } + for (i = 0; i < sizeof(no) / sizeof(no[0]); i++) { + if (!strcasecmp(string, no[i])) { + *out = FALSE; + return 0; + } + } + return PROF_BAD_BOOLEAN; +} + +krb5_error_code +krb5_aprof_get_boolean(krb5_pointer acontext, const char **hierarchy, + int uselast, krb5_boolean *retdata) +{ + krb5_error_code ret; + char **values, *valp; + int idx; + krb5_boolean val; + + ret = krb5_aprof_getvals(acontext, hierarchy, &values); + if (ret) + return ret; + idx = 0; + if (uselast) { + while (values[idx] != NULL) + idx++; + idx--; + } + valp = values[idx]; + ret = string_to_boolean(valp, &val); + profile_free_list(values); + if (ret) + return ret; + *retdata = val; + return 0; +} + +/* + * krb5_aprof_get_deltat() - Get a delta time value from the alternate + * profile. + * + * Parameters: + * acontext - opaque context for alternate profile. + * hierarchy - hierarchy of value to retrieve. + * uselast - if true, use last value, otherwise use first + * value found. + * deltatp - returned delta time value. + * + * Returns: + * error codes from profile_get_values() + * error codes from krb5_string_to_deltat() + */ +krb5_error_code +krb5_aprof_get_deltat(krb5_pointer acontext, const char **hierarchy, + krb5_boolean uselast, krb5_deltat *deltatp) +{ + krb5_error_code ret; + char **values, *valp; + int idx; + + ret = krb5_aprof_getvals(acontext, hierarchy, &values); + if (ret) + return ret; + + idx = 0; + if (uselast) { + for (idx = 0; values[idx] != NULL; idx++); + idx--; + } + valp = values[idx]; + + ret = krb5_string_to_deltat(valp, deltatp); + profile_free_list(values); + return ret; +} + +/* + * krb5_aprof_get_string() - Get a string value from the alternate profile. + * + * Parameters: + * acontext - opaque context for alternate profile. + * hierarchy - hierarchy of value to retrieve. + * uselast - if true, use last value, otherwise use first + * value found. + * stringp - returned string value. + * + * Returns: + * error codes from profile_get_values() + */ +krb5_error_code +krb5_aprof_get_string(krb5_pointer acontext, const char **hierarchy, + krb5_boolean uselast, char **stringp) +{ + krb5_error_code ret; + char **values; + int lastidx; + + ret = krb5_aprof_getvals(acontext, hierarchy, &values); + if (ret) + return ret; + + for (lastidx = 0; values[lastidx] != NULL; lastidx++); + lastidx--; + + /* Excise the entry we want from the null-terminated list, + * and free up the rest. */ + if (uselast) { + *stringp = values[lastidx]; + values[lastidx] = NULL; + } else { + *stringp = values[0]; + values[0] = values[lastidx]; + values[lastidx] = NULL; + } + + profile_free_list(values); + return 0; +} + +/* + * krb5_aprof_get_string_all() - When the attr identified by "hierarchy" is + * specified multiple times, concatenate all of + * its string values from the alternate profile, + * separated with spaces. + * + * Parameters: + * acontext - opaque context for alternate profile. + * hierarchy - hierarchy of value to retrieve. + * stringp - Returned string value. + * + * Returns: + * error codes from profile_get_values() or ENOMEM + * Caller is responsible for deallocating stringp buffer + */ +krb5_error_code +krb5_aprof_get_string_all(krb5_pointer acontext, const char **hierarchy, + char **stringp) +{ + krb5_error_code ret; + char **values; + int idx = 0; + size_t buf_size = 0; + + ret = krb5_aprof_getvals(acontext, hierarchy, &values); + if (ret) + return ret; + + buf_size = strlen(values[0]) + 3; + for (idx = 1; values[idx] != NULL; idx++) + buf_size += strlen(values[idx]) + 3; + + *stringp = calloc(1, buf_size); + if (*stringp == NULL) { + profile_free_list(values); + return ENOMEM; + } + strlcpy(*stringp, values[0], buf_size); + for (idx = 1; values[idx] != NULL; idx++) { + strlcat(*stringp, " ", buf_size); + strlcat(*stringp, values[idx], buf_size); + } + + profile_free_list(values); + return 0; +} + + +/* + * krb5_aprof_get_int32() - Get a 32-bit integer value from the alternate + * profile. + * + * Parameters: + * acontext - opaque context for alternate profile. + * hierarchy - hierarchy of value to retrieve. + * uselast - if true, use last value, otherwise use first + * value found. + * intp - returned 32-bit integer value. + * + * Returns: + * error codes from profile_get_values() + * EINVAL - value is not an integer + */ +krb5_error_code +krb5_aprof_get_int32(krb5_pointer acontext, const char **hierarchy, + krb5_boolean uselast, krb5_int32 *intp) +{ + krb5_error_code ret; + char **values; + int idx; + + ret = krb5_aprof_getvals(acontext, hierarchy, &values); + if (ret) + return ret; + + idx = 0; + if (uselast) { + for (idx = 0; values[idx] != NULL; idx++); + idx--; + } + + if (sscanf(values[idx], "%d", intp) != 1) + ret = EINVAL; + + profile_free_list(values); + return ret; +} + +/* + * Returns nonzero if it found something to copy; the caller may still need to + * check the output field or mask to see if the copy (allocation) was + * successful. Returns zero if nothing was found to copy, and thus the caller + * may want to apply some default heuristic. If the default action is just to + * use a fixed, compiled-in string, supply it as the default value here and + * ignore the return value. + */ +static int +get_string_param(char **param_out, char *param_in, long *mask_out, + long mask_in, long mask_bit, krb5_pointer aprofile, + const char **hierarchy, const char *config_name, + const char *default_value) +{ + char *svalue; + + hierarchy[2] = config_name; + if (mask_in & mask_bit) { + *param_out = strdup(param_in); + if (*param_out) + *mask_out |= mask_bit; + return 1; + } else if (aprofile != NULL && + !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { + *param_out = svalue; + *mask_out |= mask_bit; + return 1; + } else if (default_value) { + *param_out = strdup(default_value); + if (*param_out) + *mask_out |= mask_bit; + return 1; + } else { + return 0; + } +} +/* + * Similar, for (host-order) port number, if not already set in the output + * field; default_value == 0 means no default. + */ +static void +get_port_param(int *param_out, int param_in, long *mask_out, long mask_in, + long mask_bit, krb5_pointer aprofile, const char **hierarchy, + const char *config_name, int default_value) +{ + krb5_int32 ivalue; + + if (*mask_out & mask_bit) + return; + hierarchy[2] = config_name; + if (mask_in & mask_bit) { + *mask_out |= mask_bit; + *param_out = param_in; + } else if (aprofile != NULL && + !krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue)) { + *param_out = ivalue; + *mask_out |= mask_bit; + } else if (default_value) { + *param_out = default_value; + *mask_out |= mask_bit; + } +} + +/* + * Similar, for delta_t; default is required. + */ +static void +get_deltat_param(krb5_deltat *param_out, krb5_deltat param_in, long *mask_out, + long mask_in, long mask_bit, krb5_pointer aprofile, + const char **hierarchy, const char *config_name, + krb5_deltat default_value) +{ + krb5_deltat dtvalue; + + hierarchy[2] = config_name; + if (mask_in & mask_bit) { + *mask_out |= mask_bit; + *param_out = param_in; + } else if (aprofile && + !krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) { + *param_out = dtvalue; + *mask_out |= mask_bit; + } else { + *param_out = default_value; + *mask_out |= mask_bit; + } +} + +/* + * Parse out the port number from an admin_server setting. Modify server to + * contain just the hostname or address. If a port is given, set *port, and + * set the appropriate bit in *mask. + */ +static void +parse_admin_server_port(char *server, int *port, long *mask) +{ + char *end, *portstr; + + /* Allow the name or addr to be enclosed in brackets, for IPv6 addrs. */ + if (*server == '[' && (end = strchr(server + 1, ']')) != NULL) { + portstr = (*(end + 1) == ':') ? end + 2 : NULL; + /* Shift the bracketed name or address back into server. */ + memmove(server, server + 1, end - (server + 1)); + *(end - 1) = '\0'; + } else { + /* Terminate the name at the colon, if any. */ + end = server + strcspn(server, ":"); + portstr = (*end == ':') ? end + 1 : NULL; + *end = '\0'; + } + + /* If we found a port string, parse it and set the appropriate bit. */ + if (portstr) { + *port = atoi(portstr); + *mask |= KADM5_CONFIG_KADMIND_PORT; + } +} + +/* + * Function: kadm5_get_config_params + * + * Purpose: Merge configuration parameters provided by the caller with values + * specified in configuration files and with default values. + * + * Arguments: + * + * context (r) krb5_context to use + * profile (r) profile file to use + * envname (r) envname that contains a profile name to + * override profile + * params_in (r) params structure containing user-supplied + * values, or NULL + * params_out (w) params structure to be filled in + * + * Effects: + * + * The fields and mask of params_out are filled in with values obtained from + * params_in, the specified profile, and default values. Only and all fields + * specified in params_out->mask are set. The context of params_out must be + * freed with kadm5_free_config_params. + * + * params_in and params_out may be the same pointer. However, all pointers in + * params_in for which the mask is set will be re-assigned to newly copied + * versions, overwriting the old pointer value. + */ +krb5_error_code kadm5_get_config_params(krb5_context context, + int use_kdc_config, + kadm5_config_params *params_in, + kadm5_config_params *params_out) +{ + char *lrealm, *svalue, *sp, *ep, *tp; + krb5_pointer aprofile = context->profile; + const char *hierarchy[4]; + krb5_int32 ivalue; + kadm5_config_params params, empty_params; + krb5_boolean bvalue; + krb5_error_code ret = 0; + + memset(¶ms, 0, sizeof(params)); + memset(&empty_params, 0, sizeof(empty_params)); + + if (params_in == NULL) + params_in = &empty_params; + + if (params_in->mask & KADM5_CONFIG_REALM) { + lrealm = params.realm = strdup(params_in->realm); + if (params.realm == NULL) { + ret = ENOMEM; + goto cleanup; + } + params.mask |= KADM5_CONFIG_REALM; + } else { + ret = krb5_get_default_realm(context, &lrealm); + if (ret) + goto cleanup; + params.realm = lrealm; + params.mask |= KADM5_CONFIG_REALM; + } + + if (params_in->mask & KADM5_CONFIG_KVNO) { + params.kvno = params_in->kvno; + params.mask |= KADM5_CONFIG_KVNO; + } + + /* Initialize realm parameters. */ + hierarchy[0] = KRB5_CONF_REALMS; + hierarchy[1] = lrealm; + hierarchy[3] = NULL; + +#define GET_STRING_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \ + get_string_param(¶ms.FIELD, params_in->FIELD, \ + ¶ms.mask, params_in->mask, BIT, \ + aprofile, hierarchy, CONFTAG, DEFAULT) + + /* Get the value for the admin server. */ + GET_STRING_PARAM(admin_server, KADM5_CONFIG_ADMIN_SERVER, + KRB5_CONF_ADMIN_SERVER, NULL); + + if (params.mask & KADM5_CONFIG_ADMIN_SERVER) { + parse_admin_server_port(params.admin_server, ¶ms.kadmind_port, + ¶ms.mask); + } + + /* Get the value for the database. */ + GET_STRING_PARAM(dbname, KADM5_CONFIG_DBNAME, KRB5_CONF_DATABASE_NAME, + DEFAULT_KDB_FILE); + + /* Get the name of the acl file. */ + GET_STRING_PARAM(acl_file, KADM5_CONFIG_ACL_FILE, KRB5_CONF_ACL_FILE, + DEFAULT_KADM5_ACL_FILE); + + /* Get the name of the dict file. */ + GET_STRING_PARAM(dict_file, KADM5_CONFIG_DICT_FILE, KRB5_CONF_DICT_FILE, + NULL); + + /* Get the kadmind listen addresses. */ + GET_STRING_PARAM(kadmind_listen, KADM5_CONFIG_KADMIND_LISTEN, + KRB5_CONF_KADMIND_LISTEN, NULL); + GET_STRING_PARAM(kpasswd_listen, KADM5_CONFIG_KPASSWD_LISTEN, + KRB5_CONF_KPASSWD_LISTEN, NULL); + GET_STRING_PARAM(iprop_listen, KADM5_CONFIG_IPROP_LISTEN, + KRB5_CONF_IPROP_LISTEN, NULL); + +#define GET_PORT_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \ + get_port_param(¶ms.FIELD, params_in->FIELD, \ + ¶ms.mask, params_in->mask, BIT, \ + aprofile, hierarchy, CONFTAG, DEFAULT) + + /* Get the value for the kadmind port. */ + GET_PORT_PARAM(kadmind_port, KADM5_CONFIG_KADMIND_PORT, + KRB5_CONF_KADMIND_PORT, DEFAULT_KADM5_PORT); + + /* Get the value for the kpasswd port. */ + GET_PORT_PARAM(kpasswd_port, KADM5_CONFIG_KPASSWD_PORT, + KRB5_CONF_KPASSWD_PORT, DEFAULT_KPASSWD_PORT); + + /* Get the value for the master key name. */ + GET_STRING_PARAM(mkey_name, KADM5_CONFIG_MKEY_NAME, + KRB5_CONF_MASTER_KEY_NAME, NULL); + + /* Get the value for the master key type. */ + hierarchy[2] = KRB5_CONF_MASTER_KEY_TYPE; + if (params_in->mask & KADM5_CONFIG_ENCTYPE) { + params.mask |= KADM5_CONFIG_ENCTYPE; + params.enctype = params_in->enctype; + } else if (aprofile != NULL && + !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { + if (!krb5_string_to_enctype(svalue, ¶ms.enctype)) { + params.mask |= KADM5_CONFIG_ENCTYPE; + free(svalue); + } + } else { + params.mask |= KADM5_CONFIG_ENCTYPE; + params.enctype = DEFAULT_KDC_ENCTYPE; + } + + /* Get the value for mkey_from_kbd. */ + if (params_in->mask & KADM5_CONFIG_MKEY_FROM_KBD) { + params.mask |= KADM5_CONFIG_MKEY_FROM_KBD; + params.mkey_from_kbd = params_in->mkey_from_kbd; + } + + /* Get the value for the stashfile. */ + GET_STRING_PARAM(stash_file, KADM5_CONFIG_STASH_FILE, + KRB5_CONF_KEY_STASH_FILE, NULL); + + /* Get the value for maximum ticket lifetime. */ +#define GET_DELTAT_PARAM(FIELD, BIT, CONFTAG, DEFAULT) \ + get_deltat_param(¶ms.FIELD, params_in->FIELD, \ + ¶ms.mask, params_in->mask, BIT, \ + aprofile, hierarchy, CONFTAG, DEFAULT) + + GET_DELTAT_PARAM(max_life, KADM5_CONFIG_MAX_LIFE, KRB5_CONF_MAX_LIFE, + 24 * 60 * 60); /* 1 day */ + + /* Get the value for maximum renewable ticket lifetime. */ + GET_DELTAT_PARAM(max_rlife, KADM5_CONFIG_MAX_RLIFE, + KRB5_CONF_MAX_RENEWABLE_LIFE, 0); + + /* Get the value for the default principal expiration */ + hierarchy[2] = KRB5_CONF_DEFAULT_PRINCIPAL_EXPIRATION; + if (params_in->mask & KADM5_CONFIG_EXPIRATION) { + params.mask |= KADM5_CONFIG_EXPIRATION; + params.expiration = params_in->expiration; + } else if (aprofile && + !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { + if (!krb5_string_to_timestamp(svalue, ¶ms.expiration)) { + params.mask |= KADM5_CONFIG_EXPIRATION; + free(svalue); + } + } else { + params.mask |= KADM5_CONFIG_EXPIRATION; + params.expiration = 0; + } + + /* Get the value for the default principal flags */ + hierarchy[2] = KRB5_CONF_DEFAULT_PRINCIPAL_FLAGS; + if (params_in->mask & KADM5_CONFIG_FLAGS) { + params.mask |= KADM5_CONFIG_FLAGS; + params.flags = params_in->flags; + } else if (aprofile != NULL && + !krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) { + sp = svalue; + params.flags = 0; + while (sp != NULL) { + if ((ep = strchr(sp, ',')) != NULL || + (ep = strchr(sp, ' ')) != NULL || + (ep = strchr(sp, '\t')) != NULL) { + /* Fill in trailing whitespace of sp. */ + tp = ep - 1; + while (isspace((unsigned char)*tp) && tp > sp) { + *tp = '\0'; + tp--; + } + *ep = '\0'; + ep++; + /* Skip over trailing whitespace of ep. */ + while (isspace((unsigned char)*ep) && *ep != '\0') + ep++; + } + /* Convert this flag. */ + if (krb5_flagspec_to_mask(sp, ¶ms.flags, ¶ms.flags)) + break; + sp = ep; + } + if (sp == NULL) + params.mask |= KADM5_CONFIG_FLAGS; + free(svalue); + } else { + params.mask |= KADM5_CONFIG_FLAGS; + params.flags = KRB5_KDB_DEF_FLAGS; + } + + /* Get the value for the supported enctype/salttype matrix. */ + hierarchy[2] = KRB5_CONF_SUPPORTED_ENCTYPES; + if (params_in->mask & KADM5_CONFIG_ENCTYPES) { + if (params_in->keysalts) { + params.keysalts = copy_key_salt_tuple(params_in->keysalts, + params_in->num_keysalts); + if (params.keysalts) { + params.mask |= KADM5_CONFIG_ENCTYPES; + params.num_keysalts = params_in->num_keysalts; + } + } else { + params.mask |= KADM5_CONFIG_ENCTYPES; + params.keysalts = NULL; + params.num_keysalts = params_in->num_keysalts; + } + } else { + svalue = NULL; + if (aprofile != NULL) + krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue); + if (svalue == NULL) + svalue = strdup(KRB5_DEFAULT_SUPPORTED_ENCTYPES); + if (svalue == NULL) { + ret = ENOMEM; + goto cleanup; + } + + params.keysalts = NULL; + params.num_keysalts = 0; + krb5_string_to_keysalts(svalue, + NULL, /* Tuple separators */ + NULL, /* Key/salt separators */ + 0, /* No duplicates */ + ¶ms.keysalts, + ¶ms.num_keysalts); + if (params.num_keysalts) + params.mask |= KADM5_CONFIG_ENCTYPES; + + free(svalue); + } + + hierarchy[2] = KRB5_CONF_IPROP_ENABLE; + + params.iprop_enabled = FALSE; + params.mask |= KADM5_CONFIG_IPROP_ENABLED; + + if (params_in->mask & KADM5_CONFIG_IPROP_ENABLED) { + params.mask |= KADM5_CONFIG_IPROP_ENABLED; + params.iprop_enabled = params_in->iprop_enabled; + } else { + if (aprofile && + !krb5_aprof_get_boolean(aprofile, hierarchy, TRUE, &bvalue)) { + params.iprop_enabled = bvalue; + params.mask |= KADM5_CONFIG_IPROP_ENABLED; + } + } + + if (!GET_STRING_PARAM(iprop_logfile, KADM5_CONFIG_IPROP_LOGFILE, + KRB5_CONF_IPROP_LOGFILE, NULL)) { + if (params.mask & KADM5_CONFIG_DBNAME) { + if (asprintf(¶ms.iprop_logfile, "%s.ulog", + params.dbname) >= 0) + params.mask |= KADM5_CONFIG_IPROP_LOGFILE; + } + } + + GET_PORT_PARAM(iprop_port, KADM5_CONFIG_IPROP_PORT, KRB5_CONF_IPROP_PORT, + 0); + + /* 5 min for large KDBs */ + GET_DELTAT_PARAM(iprop_resync_timeout, KADM5_CONFIG_IPROP_RESYNC_TIMEOUT, + KRB5_CONF_IPROP_RESYNC_TIMEOUT, 60 * 5); + + if (params_in->mask & KADM5_CONFIG_ULOG_SIZE) { + params.mask |= KADM5_CONFIG_ULOG_SIZE; + params.iprop_ulogsize = params_in->iprop_ulogsize; + } else { + params.iprop_ulogsize = 0; + hierarchy[2] = KRB5_CONF_IPROP_ULOGSIZE; + if (aprofile != NULL && + !krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue) && + ivalue > 0) + params.iprop_ulogsize = ivalue; + hierarchy[2] = KRB5_CONF_IPROP_MASTER_ULOGSIZE; + if (params.iprop_ulogsize == 0 && aprofile != NULL && + !krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue) && + ivalue > 0) + params.iprop_ulogsize = ivalue; + if (params.iprop_ulogsize == 0) + params.iprop_ulogsize = DEF_ULOGENTRIES; + } + params.mask |= KADM5_CONFIG_ULOG_SIZE; + + GET_DELTAT_PARAM(iprop_poll_time, KADM5_CONFIG_POLL_TIME, + KRB5_CONF_IPROP_REPLICA_POLL, -1); + if (params.iprop_poll_time == -1) { + GET_DELTAT_PARAM(iprop_poll_time, KADM5_CONFIG_POLL_TIME, + KRB5_CONF_IPROP_SLAVE_POLL, 2 * 60); + } + + *params_out = params; + +cleanup: + if (ret) { + kadm5_free_config_params(context, ¶ms); + params_out->mask = 0; + } + return ret; +} + +/* + * kadm5_free_config_params() - Free data allocated by above. + */ +krb5_error_code +kadm5_free_config_params(krb5_context context, kadm5_config_params *params) +{ + if (params == NULL) + return 0; + free(params->dbname); + free(params->mkey_name); + free(params->stash_file); + free(params->keysalts); + free(params->admin_server); + free(params->dict_file); + free(params->acl_file); + free(params->realm); + free(params->iprop_logfile); + return 0; +} + +krb5_error_code +kadm5_get_admin_service_name(krb5_context ctx, char *realm_in, + char *admin_name, size_t maxlen) +{ + krb5_error_code ret; + kadm5_config_params params_in, params_out; + char *canonhost = NULL; + + memset(¶ms_in, 0, sizeof(params_in)); + memset(¶ms_out, 0, sizeof(params_out)); + + params_in.mask |= KADM5_CONFIG_REALM; + params_in.realm = realm_in; + ret = kadm5_get_config_params(ctx, 0, ¶ms_in, ¶ms_out); + if (ret) + return ret; + + if (!(params_out.mask & KADM5_CONFIG_ADMIN_SERVER)) { + ret = KADM5_MISSING_KRB5_CONF_PARAMS; + goto err_params; + } + + ret = krb5_expand_hostname(ctx, params_out.admin_server, &canonhost); + if (ret) + goto err_params; + + if (strlen(canonhost) + sizeof("kadmin/") > maxlen) { + ret = ENOMEM; + goto err_params; + } + snprintf(admin_name, maxlen, "kadmin/%s", canonhost); + +err_params: + krb5_free_string(ctx, canonhost); + kadm5_free_config_params(ctx, ¶ms_out); + return ret; +} diff --git a/krb5-1.21.3/src/lib/kadm5/chpass_util.c b/krb5-1.21.3/src/lib/kadm5/chpass_util.c new file mode 100644 index 00000000..9a1d62d9 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/chpass_util.c @@ -0,0 +1,240 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + */ + + +#include "k5-int.h" + +#include +#include "admin_internal.h" + + +#define string_text error_message + +/* + * Function: kadm5_chpass_principal_util + * + * Purpose: Wrapper around chpass_principal. We can read new pw, change pw and return useful messages + * + * Arguments: + * + * princ (input) a krb5b_principal structure for the + * principal whose password we should change. + * + * new_password (input) NULL or a null terminated string with the + * the principal's desired new password. If new_password + * is NULL then this routine will read a new password. + * + * pw_ret (output) if non-NULL, points to a static buffer + * containing the new password (if password is prompted + * internally), or to the new_password argument (if + * that is non-NULL). If the former, then the buffer + * is only valid until the next call to the function, + * and the caller should be sure to zero it when + * it is no longer needed. + * + * msg_ret (output) a useful message is copied here. + * + * exit status of 0 for success, else the com err code + * for the last significant routine called. + * + * Requires: + * + * A msg_ret should point to a buffer large enough for the messasge. + * + * Effects: + * + * Modifies: + * + * + */ + +kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle, + void *lhandle, + krb5_principal princ, + char *new_pw, + char **ret_pw, + char *msg_ret, + unsigned int msg_len) +{ + int code, code2; + unsigned int pwsize; + static char buffer[255]; + char *new_password; + kadm5_principal_ent_rec princ_ent; + kadm5_policy_ent_rec policy_ent; + + _KADM5_CHECK_HANDLE(server_handle); + + if (ret_pw) + *ret_pw = NULL; + + if (new_pw != NULL) { + new_password = new_pw; + } else { /* read the password */ + krb5_context context; + + if ((code = (int) kadm5_init_krb5_context(&context)) == 0) { + pwsize = sizeof(buffer); + code = krb5_read_password(context, KADM5_PW_FIRST_PROMPT, + KADM5_PW_SECOND_PROMPT, + buffer, &pwsize); + krb5_free_context(context); + } + + if (code == 0) + new_password = buffer; + else { +#ifdef ZEROPASSWD + memset(buffer, 0, sizeof(buffer)); +#endif + if (code == KRB5_LIBOS_BADPWDMATCH) { + strncpy(msg_ret, string_text(CHPASS_UTIL_NEW_PASSWORD_MISMATCH), + msg_len - 1); + msg_ret[msg_len - 1] = '\0'; + return(code); + } else { + snprintf(msg_ret, msg_len, "%s %s\n\n%s", + error_message(code), + string_text(CHPASS_UTIL_WHILE_READING_PASSWORD), + string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED)); + msg_ret[msg_len - 1] = '\0'; + return(code); + } + } + if (pwsize == 0) { +#ifdef ZEROPASSWD + memset(buffer, 0, sizeof(buffer)); +#endif + strncpy(msg_ret, string_text(CHPASS_UTIL_NO_PASSWORD_READ), msg_len - 1); + msg_ret[msg_len - 1] = '\0'; + return(KRB5_LIBOS_CANTREADPWD); /* could do better */ + } + } + + if (ret_pw) + *ret_pw = new_password; + + code = kadm5_chpass_principal(server_handle, princ, new_password); + +#ifdef ZEROPASSWD + if (!ret_pw) + memset(buffer, 0, sizeof(buffer)); /* in case we read a new password */ +#endif + + if (code == KADM5_OK) { + strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_CHANGED), msg_len - 1); + msg_ret[msg_len - 1] = '\0'; + return(0); + } + + if ((code != KADM5_PASS_Q_TOOSHORT) && + (code != KADM5_PASS_REUSE) &&(code != KADM5_PASS_Q_CLASS) && + (code != KADM5_PASS_Q_DICT) && (code != KADM5_PASS_TOOSOON)) { + /* Can't get more info for other errors */ + snprintf(msg_ret, msg_len, "%s\n%s %s\n", + string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED), + error_message(code), + string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE)); + return(code); + } + + /* Ok, we have a password quality error. Return a good message */ + + if (code == KADM5_PASS_REUSE) { + strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_REUSE), msg_len - 1); + msg_ret[msg_len - 1] = '\0'; + return(code); + } + + if (code == KADM5_PASS_Q_DICT) { + strncpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_IN_DICTIONARY), + msg_len - 1); + msg_ret[msg_len - 1] = '\0'; + return(code); + } + + /* Look up policy for the remaining messages */ + + code2 = kadm5_get_principal (lhandle, princ, &princ_ent, + KADM5_PRINCIPAL_NORMAL_MASK); + if (code2 != 0) { + snprintf(msg_ret, msg_len, "%s %s\n%s %s\n\n%s\n", + error_message(code2), + string_text(CHPASS_UTIL_GET_PRINC_INFO), + error_message(code), + string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE), + string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED)); + msg_ret[msg_len - 1] = '\0'; + return(code); + } + + if ((princ_ent.aux_attributes & KADM5_POLICY) == 0) { + /* Some module implements its own password policy. */ + snprintf(msg_ret, msg_len, "%s\n\n%s", + error_message(code), + string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED)); + msg_ret[msg_len - 1] = '\0'; + (void) kadm5_free_principal_ent(lhandle, &princ_ent); + return(code); + } + + code2 = kadm5_get_policy(lhandle, princ_ent.policy, + &policy_ent); + if (code2 != 0) { + snprintf(msg_ret, msg_len, "%s %s\n%s %s\n\n%s\n ", error_message(code2), + string_text(CHPASS_UTIL_GET_POLICY_INFO), + error_message(code), + string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE), + string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED)); + (void) kadm5_free_principal_ent(lhandle, &princ_ent); + return(code); + } + + if (code == KADM5_PASS_Q_TOOSHORT) { + snprintf(msg_ret, msg_len, string_text(CHPASS_UTIL_PASSWORD_TOO_SHORT), + policy_ent.pw_min_length); + (void) kadm5_free_principal_ent(lhandle, &princ_ent); + (void) kadm5_free_policy_ent(lhandle, &policy_ent); + return(code); + } + +/* Can't get more info for other errors */ + + if (code == KADM5_PASS_Q_CLASS) { + snprintf(msg_ret, msg_len, string_text(CHPASS_UTIL_TOO_FEW_CLASSES), + policy_ent.pw_min_classes); + (void) kadm5_free_principal_ent(lhandle, &princ_ent); + (void) kadm5_free_policy_ent(lhandle, &policy_ent); + return(code); + } + + if (code == KADM5_PASS_TOOSOON) { + time_t until; + char *time_string, *ptr; + + until = ts_incr(princ_ent.last_pwd_change, policy_ent.pw_min_life); + + time_string = ctime(&until); + if (time_string == NULL) + time_string = "(error)"; + else if (*(ptr = &time_string[strlen(time_string)-1]) == '\n') + *ptr = '\0'; + + snprintf(msg_ret, msg_len, string_text(CHPASS_UTIL_PASSWORD_TOO_SOON), + time_string); + (void) kadm5_free_principal_ent(lhandle, &princ_ent); + (void) kadm5_free_policy_ent(lhandle, &policy_ent); + return(code); + } + + /* We should never get here, but just in case ... */ + snprintf(msg_ret, msg_len, "%s\n%s %s\n", + string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED), + error_message(code), + string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE)); + (void) kadm5_free_principal_ent(lhandle, &princ_ent); + (void) kadm5_free_policy_ent(lhandle, &policy_ent); + return(code); +} diff --git a/krb5-1.21.3/src/lib/kadm5/chpass_util_strings.et b/krb5-1.21.3/src/lib/kadm5/chpass_util_strings.et new file mode 100644 index 00000000..d2c4c3d1 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/chpass_util_strings.et @@ -0,0 +1,58 @@ +# this is really a string table for chpass_principal_util + +error_table ovku + +error_code CHPASS_UTIL_GET_POLICY_INFO, "while getting policy info." +error_code CHPASS_UTIL_GET_PRINC_INFO, "while getting principal info." +error_code CHPASS_UTIL_NEW_PASSWORD_MISMATCH, + "New passwords do not match - password not changed.\n" + +error_code CHPASS_UTIL_NEW_PASSWORD_PROMPT, "New password" +error_code CHPASS_UTIL_NEW_PASSWORD_AGAIN_PROMPT, "New password (again)" +error_code CHPASS_UTIL_NO_PASSWORD_READ, "You must type a password. Passwords must be at least one character long.\n" +error_code CHPASS_UTIL_NO_POLICY_YET_Q_ERROR, +"yet no policy set! Contact your system security administrator." + +error_code CHPASS_UTIL_PASSWORD_CHANGED, "Password changed.\n" + +error_code CHPASS_UTIL_PASSWORD_IN_DICTIONARY, +"New password was found in a dictionary of possible passwords and\n\ +therefore may be easily guessed. Please choose another password.\n\ +See the kpasswd man page for help in choosing a good password." + +error_code CHPASS_UTIL_PASSWORD_NOT_CHANGED, "Password not changed." + +error_code CHPASS_UTIL_PASSWORD_TOO_SHORT, +"New password is too short.\n\ +Please choose a password which is at least %d characters long." +# /* */ + +error_code CHPASS_UTIL_TOO_FEW_CLASSES, +"New password does not have enough character classes.\n\ +The character classes are:\n\ + - lower-case letters,\n\ + - upper-case letters,\n\ + - digits,\n\ + - punctuation, and\n\ + - all other characters (e.g., control characters).\n\ +Please choose a password with at least %d character classes." +# /* */ + + +error_code CHPASS_UTIL_PASSWORD_TOO_SOON, +"Password cannot be changed because it was changed too recently.\n\ +Please wait until %s before you change it.\n\ +If you need to change your password before then, contact your system\n\ +security administrator." +# /* */ + +error_code CHPASS_UTIL_PASSWORD_REUSE, +"New password was used previously. Please choose a different password." + +error_code CHPASS_UTIL_WHILE_TRYING_TO_CHANGE, +"while trying to change password." + +error_code CHPASS_UTIL_WHILE_READING_PASSWORD, "while reading new password." + +end + diff --git a/krb5-1.21.3/src/lib/kadm5/clnt/Makefile.in b/krb5-1.21.3/src/lib/kadm5/clnt/Makefile.in new file mode 100644 index 00000000..800f9387 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/clnt/Makefile.in @@ -0,0 +1,79 @@ +mydir=lib$(S)kadm5$(S)clnt +BUILDTOP=$(REL)..$(S)..$(S).. +LOCALINCLUDES = -I$(BUILDTOP)/include/kadm5 + +LIBBASE=kadm5clnt_mit +LIBMAJOR=12 +LIBMINOR=0 +STOBJLISTS=../OBJS.ST OBJS.ST +SHLIB_EXPDEPS=\ + $(TOPLIBD)/libgssrpc$(SHLIBEXT) \ + $(TOPLIBD)/libgssapi_krb5$(SHLIBEXT) \ + $(TOPLIBD)/libkrb5$(SHLIBEXT) \ + $(TOPLIBD)/libk5crypto$(SHLIBEXT) \ + $(COM_ERR_DEPLIB) $(SUPPORT_LIBDEP) +SHLIB_EXPLIBS=-lgssrpc -lgssapi_krb5 -lkrb5 -lk5crypto $(SUPPORT_LIB) $(COM_ERR_LIB) $(LIBS) +RELDIR=kadm5/clnt + +##DOSBUILDTOP = ..\..\.. +##DOSLIBNAME = libkadm5clnt.lib + +SRCS = $(srcdir)/clnt_policy.c \ + $(srcdir)/client_rpc.c \ + $(srcdir)/client_principal.c \ + $(srcdir)/client_init.c \ + $(srcdir)/clnt_privs.c \ + $(srcdir)/clnt_chpass_util.c + +OBJS = \ + clnt_policy.$(OBJEXT) \ + client_rpc.$(OBJEXT) \ + client_principal.$(OBJEXT) \ + client_init.$(OBJEXT) \ + clnt_privs.$(OBJEXT) \ + clnt_chpass_util.$(OBJEXT) + +STLIBOBJS = \ + clnt_policy.o \ + client_rpc.o \ + client_principal.o \ + client_init.o \ + clnt_privs.o \ + clnt_chpass_util.o + +all-unix: includes +all-unix: all-liblinks +all-windows: $(OBJS) + +generate-files-mac: includes darwin.exports + +includes: client_internal.h + if cmp $(srcdir)/client_internal.h \ + $(BUILDTOP)/include/kadm5/client_internal.h >/dev/null 2>&1; then :; \ + else \ + (set -x; $(RM) $(BUILDTOP)/include/kadm5/client_internal.h; \ + $(CP) $(srcdir)/client_internal.h \ + $(BUILDTOP)/include/kadm5/client_internal.h) ; \ + fi + +clean-unix:: + $(RM) $(BUILDTOP)/include/kadm5/client_internal.h + +check-windows: + +clean-windows:: + +clean-unix:: clean-liblinks clean-libs clean-libobjs + +install: install-libs + +install-unix: + $(RM) $(DESTDIR)$(KRB5_LIBDIR)/libkadm5clnt$(DEPLIBEXT) + (cd $(DESTDIR)$(KRB5_LIBDIR) && $(LN_S) lib$(LIBBASE)$(DEPLIBEXT) \ + libkadm5clnt$(DEPLIBEXT)) + +depend: includes + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/kadm5/clnt/client_handle.c b/krb5-1.21.3/src/lib/kadm5/clnt/client_handle.c new file mode 100644 index 00000000..48b76707 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/clnt/client_handle.c @@ -0,0 +1,10 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include +#include +#include "client_internal.h" + +int _kadm5_check_handle(void *handle) +{ + CHECK_HANDLE(handle); + return 0; +} diff --git a/krb5-1.21.3/src/lib/kadm5/clnt/client_init.c b/krb5-1.21.3/src/lib/kadm5/clnt/client_init.c new file mode 100644 index 00000000..d4fd5e17 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/clnt/client_init.c @@ -0,0 +1,727 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "client_internal.h" +#include +#include "iprop.h" + +#include +#include +#include +#include + +#define ADM_CCACHE "/tmp/ovsec_adm.XXXXXX" + +enum init_type { INIT_PASS, INIT_SKEY, INIT_CREDS, INIT_ANONYMOUS }; + +static kadm5_ret_t +init_any(krb5_context context, char *client_name, enum init_type init_type, + char *pass, krb5_ccache ccache_in, char *service_name, + kadm5_config_params *params, krb5_ui_4 struct_version, + krb5_ui_4 api_version, char **db_args, void **server_handle); + +static kadm5_ret_t +get_init_creds(kadm5_server_handle_t handle, krb5_principal client, + enum init_type init_type, char *pass, krb5_ccache ccache_in, + char *svcname_in, char *realm, krb5_principal *server_out); + +static kadm5_ret_t +gic_iter(kadm5_server_handle_t handle, enum init_type init_type, + krb5_ccache ccache, krb5_principal client, char *pass, + char *svcname, char *realm, krb5_principal *server_out); + +static kadm5_ret_t +connect_to_server(const char *hostname, int port, int *fd); + +static kadm5_ret_t +setup_gss(kadm5_server_handle_t handle, kadm5_config_params *params_in, + krb5_principal client, krb5_principal server); + +static void +rpc_auth(kadm5_server_handle_t handle, kadm5_config_params *params_in, + gss_cred_id_t gss_client_creds, gss_name_t gss_target); + +kadm5_ret_t +kadm5_init_with_creds(krb5_context context, char *client_name, + krb5_ccache ccache, char *service_name, + kadm5_config_params *params, krb5_ui_4 struct_version, + krb5_ui_4 api_version, char **db_args, + void **server_handle) +{ + return init_any(context, client_name, INIT_CREDS, NULL, ccache, + service_name, params, struct_version, api_version, db_args, + server_handle); +} + +kadm5_ret_t +kadm5_init_with_password(krb5_context context, char *client_name, + char *pass, char *service_name, + kadm5_config_params *params, krb5_ui_4 struct_version, + krb5_ui_4 api_version, char **db_args, + void **server_handle) +{ + return init_any(context, client_name, INIT_PASS, pass, NULL, service_name, + params, struct_version, api_version, db_args, + server_handle); +} + +kadm5_ret_t +kadm5_init_anonymous(krb5_context context, char *client_name, + char *service_name, kadm5_config_params *params, + krb5_ui_4 struct_version, krb5_ui_4 api_version, + char **db_args, void **server_handle) +{ + return init_any(context, client_name, INIT_ANONYMOUS, NULL, NULL, + service_name, params, struct_version, api_version, + db_args, server_handle); +} + +kadm5_ret_t +kadm5_init(krb5_context context, char *client_name, char *pass, + char *service_name, kadm5_config_params *params, + krb5_ui_4 struct_version, krb5_ui_4 api_version, char **db_args, + void **server_handle) +{ + return init_any(context, client_name, INIT_PASS, pass, NULL, service_name, + params, struct_version, api_version, db_args, + server_handle); +} + +kadm5_ret_t +kadm5_init_with_skey(krb5_context context, char *client_name, + char *keytab, char *service_name, + kadm5_config_params *params, krb5_ui_4 struct_version, + krb5_ui_4 api_version, char **db_args, + void **server_handle) +{ + return init_any(context, client_name, INIT_SKEY, keytab, NULL, + service_name, params, struct_version, api_version, db_args, + server_handle); +} + +static kadm5_ret_t +free_handle(kadm5_server_handle_t handle) +{ + kadm5_ret_t ret = 0; + OM_uint32 minor_stat; + krb5_ccache ccache; + + if (handle == NULL) + return 0; + + if (handle->destroy_cache && handle->cache_name != NULL) { + ret = krb5_cc_resolve(handle->context, handle->cache_name, &ccache); + if (!ret) + ret = krb5_cc_destroy(handle->context, ccache); + } + free(handle->cache_name); + (void)gss_release_cred(&minor_stat, &handle->cred); + if (handle->clnt != NULL && handle->clnt->cl_auth != NULL) + AUTH_DESTROY(handle->clnt->cl_auth); + if (handle->clnt != NULL) + clnt_destroy(handle->clnt); + if (handle->client_socket != -1) + close(handle->client_socket); + free(handle->lhandle); + kadm5_free_config_params(handle->context, &handle->params); + free(handle); + + return ret; +} + +static kadm5_ret_t +init_any(krb5_context context, char *client_name, enum init_type init_type, + char *pass, krb5_ccache ccache_in, char *service_name, + kadm5_config_params *params_in, krb5_ui_4 struct_version, + krb5_ui_4 api_version, char **db_args, void **server_handle) +{ + int fd = -1; + krb5_boolean iprop_enable; + int port; + rpcprog_t rpc_prog; + rpcvers_t rpc_vers; + krb5_principal client = NULL, server = NULL; + struct timeval timeout; + + kadm5_server_handle_t handle = NULL; + kadm5_config_params params_local; + + krb5_error_code code; + generic_ret r = { 0, 0 }; + + initialize_ovk_error_table(); + initialize_ovku_error_table(); + + if (server_handle == NULL || client_name == NULL) + return EINVAL; + + CHECK_VERSIONS(struct_version, api_version, KADM5_OLD_LIB_API_VERSION, + KADM5_NEW_LIB_API_VERSION); + + handle = k5alloc(sizeof(*handle), &code); + if (handle == NULL) + goto cleanup; + handle->lhandle = k5alloc(sizeof(*handle), &code); + if (handle->lhandle == NULL) + goto cleanup; + + handle->magic_number = KADM5_SERVER_HANDLE_MAGIC; + handle->struct_version = struct_version; + handle->api_version = api_version; + handle->clnt = 0; + handle->client_socket = -1; + handle->cache_name = 0; + handle->destroy_cache = 0; + handle->context = 0; + handle->cred = GSS_C_NO_CREDENTIAL; + *handle->lhandle = *handle; + handle->lhandle->api_version = KADM5_API_VERSION_4; + handle->lhandle->struct_version = KADM5_STRUCT_VERSION; + handle->lhandle->lhandle = handle->lhandle; + + handle->context = context; + + memset(¶ms_local, 0, sizeof(params_local)); + + code = kadm5_get_config_params(handle->context, 0, params_in, + &handle->params); + if (code) + goto cleanup; + +#define REQUIRED_PARAMS (KADM5_CONFIG_REALM | \ + KADM5_CONFIG_ADMIN_SERVER | \ + KADM5_CONFIG_KADMIND_PORT) + + if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) { + code = KADM5_MISSING_KRB5_CONF_PARAMS; + goto cleanup; + } + + /* + * Parse the client name. If it has an empty realm, it is almost certainly + * a host-based principal using DNS fallback processing or the referral + * realm, so give it the appropriate name type for canonicalization. Also + * check for iprop client principals as kpropd sets the realm on the + * sn2princ result. + */ + code = krb5_parse_name(handle->context, client_name, &client); + if (code) + goto cleanup; + if ((init_type == INIT_SKEY && client->realm.length == 0) || + (client->length == 2 && + data_eq_string(client->data[0], KIPROP_SVC_NAME))) + client->type = KRB5_NT_SRV_HST; + + /* + * Get credentials. Also does some fallbacks in case kadmin/fqdn + * principal doesn't exist. + */ + code = get_init_creds(handle, client, init_type, pass, ccache_in, + service_name, handle->params.realm, &server); + if (code) + goto cleanup; + + /* If the service_name and client_name are iprop-centric, use the iprop + * port and RPC identifiers. */ + iprop_enable = (service_name != NULL && + strstr(service_name, KIPROP_SVC_NAME) != NULL && + strstr(client_name, KIPROP_SVC_NAME) != NULL); + if (iprop_enable) { + port = handle->params.iprop_port; + rpc_prog = KRB5_IPROP_PROG; + rpc_vers = KRB5_IPROP_VERS; + } else { + port = handle->params.kadmind_port; + rpc_prog = KADM; + rpc_vers = KADMVERS; + } + + code = connect_to_server(handle->params.admin_server, port, &fd); + if (code) + goto cleanup; + + handle->clnt = clnttcp_create(NULL, rpc_prog, rpc_vers, &fd, 0, 0); + if (handle->clnt == NULL) { + code = KADM5_RPC_ERROR; +#ifdef DEBUG + clnt_pcreateerror("clnttcp_create"); +#endif + goto cleanup; + } + + /* Set a one-hour timeout. */ + timeout.tv_sec = 3600; + timeout.tv_usec = 0; + (void)clnt_control(handle->clnt, CLSET_TIMEOUT, &timeout); + + handle->client_socket = fd; + handle->lhandle->clnt = handle->clnt; + handle->lhandle->client_socket = fd; + + /* + * The RPC connection is open; establish the GSS-API + * authentication context. + */ + code = setup_gss(handle, params_in, + (init_type == INIT_CREDS) ? client : NULL, server); + if (code) + goto cleanup; + + /* + * Bypass the remainder of the code and return straight away + * if the gss service requested is kiprop + */ + if (iprop_enable) { + code = 0; + *server_handle = handle; + handle = NULL; + goto cleanup; + } + + if (init_2(&handle->api_version, &r, handle->clnt)) { + code = KADM5_RPC_ERROR; +#ifdef DEBUG + clnt_perror(handle->clnt, "init_2 null resp"); +#endif + goto cleanup; + } + /* Drop down to v3 wire protocol if server does not support v4 */ + if (r.code == KADM5_NEW_SERVER_API_VERSION && + handle->api_version == KADM5_API_VERSION_4) { + handle->api_version = KADM5_API_VERSION_3; + memset(&r, 0, sizeof(generic_ret)); + if (init_2(&handle->api_version, &r, handle->clnt)) { + code = KADM5_RPC_ERROR; + goto cleanup; + } + } + /* Drop down to v2 wire protocol if server does not support v3 */ + if (r.code == KADM5_NEW_SERVER_API_VERSION && + handle->api_version == KADM5_API_VERSION_3) { + handle->api_version = KADM5_API_VERSION_2; + memset(&r, 0, sizeof(generic_ret)); + if (init_2(&handle->api_version, &r, handle->clnt)) { + code = KADM5_RPC_ERROR; + goto cleanup; + } + } + if (r.code) { + code = r.code; + goto cleanup; + } + + *server_handle = handle; + handle = NULL; + +cleanup: + krb5_free_principal(context, client); + krb5_free_principal(context, server); + (void)free_handle(handle); + + return code; +} + +/* Get initial credentials for authenticating to server. Perform fallback from + * kadmin/fqdn to kadmin/admin if svcname_in is NULL. */ +static kadm5_ret_t +get_init_creds(kadm5_server_handle_t handle, krb5_principal client, + enum init_type init_type, char *pass, krb5_ccache ccache_in, + char *svcname_in, char *realm, krb5_principal *server_out) +{ + kadm5_ret_t code; + krb5_ccache ccache = NULL; + char *svcname, svcbuf[BUFSIZ]; + + *server_out = NULL; + + /* + * Acquire a service ticket for svcname@realm for client, using password + * pass (which could be NULL), and create a ccache to store them in. If + * INIT_CREDS, use the ccache we were provided instead. + */ + if (init_type == INIT_CREDS) { + ccache = ccache_in; + if (asprintf(&handle->cache_name, "%s:%s", + krb5_cc_get_type(handle->context, ccache), + krb5_cc_get_name(handle->context, ccache)) < 0) { + handle->cache_name = NULL; + code = ENOMEM; + goto error; + } + } else { + static int counter = 0; + + if (asprintf(&handle->cache_name, "MEMORY:kadm5_%u", counter++) < 0) { + handle->cache_name = NULL; + code = ENOMEM; + goto error; + } + code = krb5_cc_resolve(handle->context, handle->cache_name, + &ccache); + if (code) + goto error; + + code = krb5_cc_initialize (handle->context, ccache, client); + if (code) + goto error; + + handle->destroy_cache = 1; + } + handle->lhandle->cache_name = handle->cache_name; + + svcname = (svcname_in != NULL) ? svcname_in : KADM5_ADMIN_SERVICE; + code = gic_iter(handle, init_type, ccache, client, pass, svcname, realm, + server_out); + if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN + || code == KRB5_CC_NOTFOUND) && svcname_in == NULL) { + /* Retry with host-based service principal. */ + code = kadm5_get_admin_service_name(handle->context, + handle->params.realm, + svcbuf, sizeof(svcbuf)); + if (code) + goto error; + code = gic_iter(handle, init_type, ccache, client, pass, svcbuf, realm, + server_out); + } + /* Improved error messages */ + if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) code = KADM5_BAD_PASSWORD; + if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) + code = KADM5_SECURE_PRINC_MISSING; + +error: + if (ccache != NULL && init_type != INIT_CREDS) + krb5_cc_close(handle->context, ccache); + return code; +} + +/* Perform one iteration of attempting to get credentials. This includes + * searching existing ccache for requested service if INIT_CREDS. */ +static kadm5_ret_t +gic_iter(kadm5_server_handle_t handle, enum init_type init_type, + krb5_ccache ccache, krb5_principal client, char *pass, char *svcname, + char *realm, krb5_principal *server_out) +{ + kadm5_ret_t code; + krb5_context ctx; + krb5_keytab kt; + krb5_get_init_creds_opt *opt = NULL; + krb5_creds mcreds, outcreds; + + *server_out = NULL; + ctx = handle->context; + kt = NULL; + memset(&opt, 0, sizeof(opt)); + memset(&mcreds, 0, sizeof(mcreds)); + memset(&outcreds, 0, sizeof(outcreds)); + + /* Credentials for kadmin don't need to be forwardable or proxiable. */ + if (init_type != INIT_CREDS) { + code = krb5_get_init_creds_opt_alloc(ctx, &opt); + if (code) + goto error; + + krb5_get_init_creds_opt_set_forwardable(opt, 0); + krb5_get_init_creds_opt_set_proxiable(opt, 0); + krb5_get_init_creds_opt_set_out_ccache(ctx, opt, ccache); + if (init_type == INIT_ANONYMOUS) + krb5_get_init_creds_opt_set_anonymous(opt, 1); + } + + if (init_type == INIT_PASS || init_type == INIT_ANONYMOUS) { + code = krb5_get_init_creds_password(ctx, &outcreds, client, pass, + krb5_prompter_posix, + NULL, 0, svcname, opt); + if (code) + goto error; + } else if (init_type == INIT_SKEY) { + if (pass) { + code = krb5_kt_resolve(ctx, pass, &kt); + if (code) + goto error; + } + code = krb5_get_init_creds_keytab(ctx, &outcreds, client, kt, + 0, svcname, opt); + if (pass) + krb5_kt_close(ctx, kt); + if (code) + goto error; + } else if (init_type == INIT_CREDS) { + mcreds.client = client; + code = krb5_parse_name_flags(ctx, svcname, + KRB5_PRINCIPAL_PARSE_IGNORE_REALM, + &mcreds.server); + if (code) + goto error; + code = krb5_set_principal_realm(ctx, mcreds.server, realm); + if (code) + goto error; + code = krb5_cc_retrieve_cred(ctx, ccache, 0, + &mcreds, &outcreds); + krb5_free_principal(ctx, mcreds.server); + if (code) + goto error; + } else { + code = EINVAL; + goto error; + } + + /* Steal the server principal of the creds we acquired and return it to the + * caller, which needs to knows what service to authenticate to. */ + *server_out = outcreds.server; + outcreds.server = NULL; + +error: + krb5_free_cred_contents(ctx, &outcreds); + if (opt) + krb5_get_init_creds_opt_free(ctx, opt); + return code; +} + +/* Set *fd to a socket connected to hostname and port. */ +static kadm5_ret_t +connect_to_server(const char *hostname, int port, int *fd) +{ + struct addrinfo hint, *addrs, *a; + char portbuf[32]; + int err, s; + kadm5_ret_t code; + + /* Look up the server's addresses. */ + (void) snprintf(portbuf, sizeof(portbuf), "%d", port); + memset(&hint, 0, sizeof(hint)); + hint.ai_socktype = SOCK_STREAM; + hint.ai_flags = AI_ADDRCONFIG; +#ifdef AI_NUMERICSERV + hint.ai_flags |= AI_NUMERICSERV; +#endif + err = getaddrinfo(hostname, portbuf, &hint, &addrs); + if (err != 0) + return KADM5_CANT_RESOLVE; + + /* Try to connect to each address until we succeed. */ + for (a = addrs; a != NULL; a = a->ai_next) { + s = socket(a->ai_family, a->ai_socktype, 0); + if (s == -1) { + code = KADM5_FAILURE; + goto cleanup; + } + err = connect(s, a->ai_addr, a->ai_addrlen); + if (err == 0) { + *fd = s; + code = 0; + goto cleanup; + } + close(s); + } + + /* We didn't succeed on any address. */ + code = KADM5_RPC_ERROR; +cleanup: + freeaddrinfo(addrs); + return code; +} + +/* Acquire GSSAPI credentials and set up RPC auth flavor. */ +static kadm5_ret_t +setup_gss(kadm5_server_handle_t handle, kadm5_config_params *params_in, + krb5_principal client, krb5_principal server) +{ + OM_uint32 gssstat, minor_stat; + gss_buffer_desc buf; + gss_name_t gss_client; + gss_name_t gss_target; + const char *c_ccname_orig; + char *ccname_orig; + + ccname_orig = NULL; + gss_client = gss_target = GSS_C_NO_NAME; + + /* Temporarily use the kadm5 cache. */ + gssstat = gss_krb5_ccache_name(&minor_stat, handle->cache_name, + &c_ccname_orig); + if (gssstat != GSS_S_COMPLETE) + goto error; + if (c_ccname_orig) + ccname_orig = strdup(c_ccname_orig); + else + ccname_orig = 0; + + buf.value = &server; + buf.length = sizeof(server); + gssstat = gss_import_name(&minor_stat, &buf, + (gss_OID)gss_nt_krb5_principal, &gss_target); + if (gssstat != GSS_S_COMPLETE) + goto error; + + if (client != NULL) { + buf.value = &client; + buf.length = sizeof(client); + gssstat = gss_import_name(&minor_stat, &buf, + (gss_OID)gss_nt_krb5_principal, &gss_client); + } else gss_client = GSS_C_NO_NAME; + + if (gssstat != GSS_S_COMPLETE) + goto error; + + gssstat = gss_acquire_cred(&minor_stat, gss_client, 0, + GSS_C_NULL_OID_SET, GSS_C_INITIATE, + &handle->cred, NULL, NULL); + if (gssstat != GSS_S_COMPLETE) + goto error; + + /* + * Do actual creation of RPC auth handle. Implements auth flavor + * fallback. + */ + rpc_auth(handle, params_in, handle->cred, gss_target); + +error: + if (gss_client) + gss_release_name(&minor_stat, &gss_client); + if (gss_target) + gss_release_name(&minor_stat, &gss_target); + + /* Revert to prior gss_krb5 ccache. */ + if (ccname_orig) { + gssstat = gss_krb5_ccache_name(&minor_stat, ccname_orig, NULL); + if (gssstat) { + return KADM5_GSS_ERROR; + } + free(ccname_orig); + } else { + gssstat = gss_krb5_ccache_name(&minor_stat, NULL, NULL); + if (gssstat) { + return KADM5_GSS_ERROR; + } + } + + if (handle->clnt->cl_auth == NULL) { + return KADM5_GSS_ERROR; + } + return 0; +} + +/* Create RPC auth handle. Do auth flavor fallback if needed. */ +static void +rpc_auth(kadm5_server_handle_t handle, kadm5_config_params *params_in, + gss_cred_id_t gss_client_creds, gss_name_t gss_target) +{ + OM_uint32 gssstat, minor_stat; + struct rpc_gss_sec sec; + + /* Allow unauthenticated option for testing. */ + if (params_in != NULL && (params_in->mask & KADM5_CONFIG_NO_AUTH)) + return; + + /* Use RPCSEC_GSS by default. */ + if (params_in == NULL || + !(params_in->mask & KADM5_CONFIG_OLD_AUTH_GSSAPI)) { + sec.mech = (gss_OID)gss_mech_krb5; + sec.qop = GSS_C_QOP_DEFAULT; + sec.svc = RPCSEC_GSS_SVC_PRIVACY; + sec.cred = gss_client_creds; + sec.req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG; + + handle->clnt->cl_auth = authgss_create(handle->clnt, + gss_target, &sec); + if (handle->clnt->cl_auth != NULL) + return; + } + + if (params_in != NULL && (params_in->mask & KADM5_CONFIG_AUTH_NOFALLBACK)) + return; + + /* Fall back to old AUTH_GSSAPI. */ + handle->clnt->cl_auth = auth_gssapi_create(handle->clnt, + &gssstat, + &minor_stat, + gss_client_creds, + gss_target, + (gss_OID) gss_mech_krb5, + GSS_C_MUTUAL_FLAG + | GSS_C_REPLAY_FLAG, + 0, NULL, NULL, NULL); +} + +kadm5_ret_t +kadm5_destroy(void *server_handle) +{ + CHECK_HANDLE(server_handle); + return free_handle(server_handle); +} +/* not supported on client */ +kadm5_ret_t kadm5_lock(void *server_handle) +{ + return EINVAL; +} + +/* not supported on client */ +kadm5_ret_t kadm5_unlock(void *server_handle) +{ + return EINVAL; +} + +kadm5_ret_t kadm5_flush(void *server_handle) +{ + return KADM5_OK; +} + +int _kadm5_check_handle(void *handle) +{ + CHECK_HANDLE(handle); + return 0; +} + +krb5_error_code kadm5_init_krb5_context (krb5_context *ctx) +{ + return krb5_init_context(ctx); +} + +/* + * Stub function for kadmin. It was created to eliminate the dependency on + * libkdb's ulog functions. The srv equivalent makes the actual calls. + */ +krb5_error_code +kadm5_init_iprop(void *handle, char **db_args) +{ + return (0); +} diff --git a/krb5-1.21.3/src/lib/kadm5/clnt/client_internal.h b/krb5-1.21.3/src/lib/kadm5/clnt/client_internal.h new file mode 100644 index 00000000..fca7a7dc --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/clnt/client_internal.h @@ -0,0 +1,100 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + * + * $Log$ + * Revision 1.1 1996/07/24 22:22:43 tlyu + * * Makefile.in, configure.in: break out client lib into a + * subdirectory + * + * Revision 1.11 1996/07/22 20:35:46 marc + * this commit includes all the changes on the OV_9510_INTEGRATION and + * OV_MERGE branches. This includes, but is not limited to, the new openvision + * admin system, and major changes to gssapi to add functionality, and bring + * the implementation in line with rfc1964. before committing, the + * code was built and tested for netbsd and solaris. + * + * Revision 1.10.4.1 1996/07/18 03:08:37 marc + * merged in changes from OV_9510_BP to OV_9510_FINAL1 + * + * Revision 1.10.2.1 1996/06/20 02:16:46 marc + * File added to the repository on a branch + * + * Revision 1.10 1996/06/06 20:09:16 bjaspan + * add destroy_cache, for kadm5_init_with_creds + * + * Revision 1.9 1996/05/30 21:04:42 bjaspan + * add lhandle to handle + * + * Revision 1.8 1996/05/28 20:33:49 bjaspan + * rework kadm5_config + * + * Revision 1.7 1996/05/17 21:36:59 bjaspan + * rename to kadm5, begin implementing version 2 + * + * Revision 1.6 1996/05/16 21:45:07 bjaspan + * add context + * + * Revision 1.5 1996/05/08 21:10:23 bjaspan + * marc's changes + * + * Revision 1.4 1996/01/16 20:54:30 grier + * secure/3570 use krb5_ui_4 not unsigned int + * + * Revision 1.3 1995/11/14 17:48:57 grier + * long to int + * + * Revision 1.2 1994/08/16 18:53:47 jik + * Versioning stuff. + * + * Revision 1.1 1994/08/09 21:14:38 jik + * Initial revision + * + */ + +/* + * This header file is used internally by the Admin API client + * libraries. IF YOU THINK YOU NEED TO USE THIS FILE FOR ANYTHING, + * YOU'RE ALMOST CERTAINLY WRONG. + */ + +#ifndef __KADM5_CLIENT_INTERNAL_H__ +#define __KADM5_CLIENT_INTERNAL_H__ + +#include "admin_internal.h" + +typedef struct _kadm5_server_handle_t { + krb5_ui_4 magic_number; + krb5_ui_4 struct_version; + krb5_ui_4 api_version; + char * cache_name; + int destroy_cache; + CLIENT * clnt; + int client_socket; + krb5_context context; + gss_cred_id_t cred; + kadm5_config_params params; + struct _kadm5_server_handle_t *lhandle; +} kadm5_server_handle_rec, *kadm5_server_handle_t; + +#define CLIENT_CHECK_HANDLE(handle) \ + { \ + kadm5_server_handle_t srvr = \ + (kadm5_server_handle_t) handle; \ + \ + if (! srvr->clnt) \ + return KADM5_BAD_SERVER_HANDLE; \ + if (! srvr->cache_name) \ + return KADM5_BAD_SERVER_HANDLE; \ + if (! srvr->lhandle) \ + return KADM5_BAD_SERVER_HANDLE; \ + } + +#define CHECK_HANDLE(handle) \ + GENERIC_CHECK_HANDLE(handle, KADM5_OLD_LIB_API_VERSION, \ + KADM5_NEW_LIB_API_VERSION) \ + CLIENT_CHECK_HANDLE(handle) + +#endif /* __KADM5_CLIENT_INTERNAL_H__ */ diff --git a/krb5-1.21.3/src/lib/kadm5/clnt/client_principal.c b/krb5-1.21.3/src/lib/kadm5/clnt/client_principal.c new file mode 100644 index 00000000..96d9d193 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/clnt/client_principal.c @@ -0,0 +1,528 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ + +#include +#include +#include +#ifdef HAVE_MEMORY_H +#include +#endif +#include +#include +#include "client_internal.h" + +#ifdef DEBUG +#define eret() do { clnt_perror(handle->clnt, "null ret"); return KADM5_RPC_ERROR; } while (0) +#else +#define eret() do { return KADM5_RPC_ERROR; } while (0) +#endif + +kadm5_ret_t +kadm5_create_principal(void *server_handle, + kadm5_principal_ent_t princ, long mask, + char *pw) +{ + generic_ret r = { 0, 0 }; + cprinc_arg arg; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + memset(&arg, 0, sizeof(arg)); + arg.mask = mask; + arg.passwd = pw; + arg.api_version = handle->api_version; + + if(princ == NULL) + return EINVAL; + + memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec)); + arg.rec.mod_name = NULL; + + if(!(mask & KADM5_POLICY)) + arg.rec.policy = NULL; + if (! (mask & KADM5_KEY_DATA)) { + arg.rec.n_key_data = 0; + arg.rec.key_data = NULL; + } + if (! (mask & KADM5_TL_DATA)) { + arg.rec.n_tl_data = 0; + arg.rec.tl_data = NULL; + } + + if (create_principal_2(&arg, &r, handle->clnt)) + eret(); + return r.code; +} + +kadm5_ret_t +kadm5_create_principal_3(void *server_handle, + kadm5_principal_ent_t princ, long mask, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + char *pw) +{ + generic_ret r = { 0, 0 }; + cprinc3_arg arg; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + memset(&arg, 0, sizeof(arg)); + arg.mask = mask; + arg.passwd = pw; + arg.api_version = handle->api_version; + arg.n_ks_tuple = n_ks_tuple; + arg.ks_tuple = ks_tuple; + + if(princ == NULL) + return EINVAL; + + memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec)); + arg.rec.mod_name = NULL; + + if(!(mask & KADM5_POLICY)) + arg.rec.policy = NULL; + if (! (mask & KADM5_KEY_DATA)) { + arg.rec.n_key_data = 0; + arg.rec.key_data = NULL; + } + if (! (mask & KADM5_TL_DATA)) { + arg.rec.n_tl_data = 0; + arg.rec.tl_data = NULL; + } + + if (create_principal3_2(&arg, &r, handle->clnt)) + eret(); + return r.code; +} + +kadm5_ret_t +kadm5_delete_principal(void *server_handle, krb5_principal principal) +{ + dprinc_arg arg; + generic_ret r = { 0, 0 }; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + if(principal == NULL) + return EINVAL; + arg.princ = principal; + arg.api_version = handle->api_version; + if (delete_principal_2(&arg, &r, handle->clnt)) + eret(); + return r.code; +} + +kadm5_ret_t +kadm5_modify_principal(void *server_handle, + kadm5_principal_ent_t princ, long mask) +{ + mprinc_arg arg; + generic_ret r = { 0, 0 }; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + memset(&arg, 0, sizeof(arg)); + arg.mask = mask; + arg.api_version = handle->api_version; + if(princ == NULL) + return EINVAL; + memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec)); + if(!(mask & KADM5_POLICY)) + arg.rec.policy = NULL; + if (! (mask & KADM5_KEY_DATA)) { + arg.rec.n_key_data = 0; + arg.rec.key_data = NULL; + } + if (! (mask & KADM5_TL_DATA)) { + arg.rec.n_tl_data = 0; + arg.rec.tl_data = NULL; + } + + arg.rec.mod_name = NULL; + + if (modify_principal_2(&arg, &r, handle->clnt)) + eret(); + return r.code; +} + +kadm5_ret_t +kadm5_get_principal(void *server_handle, + krb5_principal princ, kadm5_principal_ent_t ent, + long mask) +{ + gprinc_arg arg; + gprinc_ret r; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + if(princ == NULL) + return EINVAL; + arg.princ = princ; + arg.mask = mask; + arg.api_version = handle->api_version; + memset(&r, 0, sizeof(gprinc_ret)); + if (get_principal_2(&arg, &r, handle->clnt)) + eret(); + if (r.code == 0) + memcpy(ent, &r.rec, sizeof(r.rec)); + + return r.code; +} + +kadm5_ret_t +kadm5_get_principals(void *server_handle, + char *exp, char ***princs, int *count) +{ + gprincs_arg arg; + gprincs_ret r; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + if(princs == NULL || count == NULL) + return EINVAL; + arg.exp = exp; + arg.api_version = handle->api_version; + memset(&r, 0, sizeof(gprincs_ret)); + if (get_princs_2(&arg, &r, handle->clnt)) + eret(); + if (r.code == 0) { + *count = r.count; + *princs = r.princs; + } else { + *count = 0; + *princs = NULL; + } + + return r.code; +} + +kadm5_ret_t +kadm5_rename_principal(void *server_handle, + krb5_principal source, krb5_principal dest) +{ + rprinc_arg arg; + generic_ret r = { 0, 0 }; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + arg.src = source; + arg.dest = dest; + arg.api_version = handle->api_version; + if (source == NULL || dest == NULL) + return EINVAL; + if (rename_principal_2(&arg, &r, handle->clnt)) + eret(); + return r.code; +} + +kadm5_ret_t +kadm5_chpass_principal(void *server_handle, + krb5_principal princ, char *password) +{ + chpass_arg arg; + generic_ret r = { 0, 0 }; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + arg.princ = princ; + arg.pass = password; + arg.api_version = handle->api_version; + + if(princ == NULL) + return EINVAL; + if (chpass_principal_2(&arg, &r, handle->clnt)) + eret(); + return r.code; +} + +kadm5_ret_t +kadm5_chpass_principal_3(void *server_handle, + krb5_principal princ, krb5_boolean keepold, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, + char *password) +{ + chpass3_arg arg; + generic_ret r = { 0, 0 }; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + arg.princ = princ; + arg.pass = password; + arg.api_version = handle->api_version; + arg.keepold = keepold; + arg.n_ks_tuple = n_ks_tuple; + arg.ks_tuple = ks_tuple; + + if(princ == NULL) + return EINVAL; + if (chpass_principal3_2(&arg, &r, handle->clnt)) + eret(); + return r.code; +} + +kadm5_ret_t +kadm5_setkey_principal(void *server_handle, + krb5_principal princ, + krb5_keyblock *keyblocks, + int n_keys) +{ + setkey_arg arg; + generic_ret r = { 0, 0 }; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + arg.princ = princ; + arg.keyblocks = keyblocks; + arg.n_keys = n_keys; + arg.api_version = handle->api_version; + + if(princ == NULL || keyblocks == NULL) + return EINVAL; + if (setkey_principal_2(&arg, &r, handle->clnt)) + eret(); + return r.code; +} + +kadm5_ret_t +kadm5_setkey_principal_3(void *server_handle, + krb5_principal princ, + krb5_boolean keepold, int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + krb5_keyblock *keyblocks, + int n_keys) +{ + setkey3_arg arg; + generic_ret r = { 0, 0 }; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + arg.princ = princ; + arg.keyblocks = keyblocks; + arg.n_keys = n_keys; + arg.api_version = handle->api_version; + arg.keepold = keepold; + arg.n_ks_tuple = n_ks_tuple; + arg.ks_tuple = ks_tuple; + + if(princ == NULL || keyblocks == NULL) + return EINVAL; + if (setkey_principal3_2(&arg, &r, handle->clnt)) + eret(); + return r.code; +} + +kadm5_ret_t +kadm5_setkey_principal_4(void *server_handle, + krb5_principal princ, + krb5_boolean keepold, + kadm5_key_data *key_data, + int n_key_data) +{ + setkey4_arg arg; + generic_ret r = { 0, 0 }; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + arg.api_version = handle->api_version; + arg.princ = princ; + arg.keepold = keepold; + arg.key_data = key_data; + arg.n_key_data = n_key_data; + + if (princ == NULL || key_data == NULL || n_key_data == 0) + return EINVAL; + if (setkey_principal4_2(&arg, &r, handle->clnt)) + eret(); + return r.code; +} + +kadm5_ret_t +kadm5_randkey_principal_3(void *server_handle, + krb5_principal princ, + krb5_boolean keepold, int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + krb5_keyblock **key, int *n_keys) +{ + chrand3_arg arg; + chrand_ret r; + kadm5_server_handle_t handle = server_handle; + int i; + + CHECK_HANDLE(server_handle); + + arg.princ = princ; + arg.api_version = handle->api_version; + arg.keepold = keepold; + arg.n_ks_tuple = n_ks_tuple; + arg.ks_tuple = ks_tuple; + + if(princ == NULL) + return EINVAL; + memset(&r, 0, sizeof(chrand_ret)); + if (chrand_principal3_2(&arg, &r, handle->clnt)) + eret(); + if (n_keys) + *n_keys = r.n_keys; + if (key) { + *key = r.keys; + } else { + for (i = 0; i < r.n_keys; i++) + krb5_free_keyblock_contents(handle->context, &r.keys[i]); + free(r.keys); + } + return r.code; +} + +kadm5_ret_t +kadm5_randkey_principal(void *server_handle, + krb5_principal princ, + krb5_keyblock **key, int *n_keys) +{ + chrand_arg arg; + chrand_ret r; + kadm5_server_handle_t handle = server_handle; + int i; + + CHECK_HANDLE(server_handle); + + arg.princ = princ; + arg.api_version = handle->api_version; + + if(princ == NULL) + return EINVAL; + memset(&r, 0, sizeof(chrand_ret)); + if (chrand_principal_2(&arg, &r, handle->clnt)) + eret(); + if (n_keys) + *n_keys = r.n_keys; + if (key) { + *key = r.keys; + } else { + for (i = 0; i < r.n_keys; i++) + krb5_free_keyblock_contents(handle->context, &r.keys[i]); + free(r.keys); + } + return r.code; +} + +/* not supported on client side */ +kadm5_ret_t kadm5_decrypt_key(void *server_handle, + kadm5_principal_ent_t entry, krb5_int32 + ktype, krb5_int32 stype, krb5_int32 + kvno, krb5_keyblock *keyblock, + krb5_keysalt *keysalt, int *kvnop) +{ + return EINVAL; +} + +kadm5_ret_t +kadm5_purgekeys(void *server_handle, + krb5_principal princ, + int keepkvno) +{ + purgekeys_arg arg; + generic_ret r = { 0, 0 }; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + arg.princ = princ; + arg.keepkvno = keepkvno; + arg.api_version = handle->api_version; + + if (princ == NULL) + return EINVAL; + if (purgekeys_2(&arg, &r, handle->clnt)) + eret(); + return r.code; +} + +kadm5_ret_t +kadm5_get_strings(void *server_handle, krb5_principal principal, + krb5_string_attr **strings_out, int *count_out) +{ + gstrings_arg arg; + gstrings_ret r; + kadm5_server_handle_t handle = server_handle; + + *strings_out = NULL; + *count_out = 0; + CHECK_HANDLE(server_handle); + if (principal == NULL) + return EINVAL; + + arg.princ = principal; + arg.api_version = handle->api_version; + memset(&r, 0, sizeof(gstrings_ret)); + if (get_strings_2(&arg, &r, handle->clnt)) + eret(); + if (r.code == 0) { + *strings_out = r.strings; + *count_out = r.count; + } + return r.code; +} + +kadm5_ret_t +kadm5_set_string(void *server_handle, krb5_principal principal, + const char *key, const char *value) +{ + sstring_arg arg; + generic_ret r = { 0, 0 }; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + if (principal == NULL || key == NULL) + return EINVAL; + + arg.princ = principal; + arg.key = (char *)key; + arg.value = (char *)value; + arg.api_version = handle->api_version; + if (set_string_2(&arg, &r, handle->clnt)) + eret(); + return r.code; +} + +kadm5_ret_t +kadm5_get_principal_keys(void *server_handle, krb5_principal princ, + krb5_kvno kvno, kadm5_key_data **key_data, + int *n_key_data) +{ + getpkeys_arg arg; + getpkeys_ret r; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + arg.api_version = handle->api_version; + arg.princ = princ; + arg.kvno = kvno; + + if (princ == NULL || key_data == NULL || n_key_data == 0) + return EINVAL; + memset(&r, 0, sizeof(getpkeys_ret)); + if (get_principal_keys_2(&arg, &r, handle->clnt)) + eret(); + if (r.code == 0) { + *key_data = r.key_data; + *n_key_data = r.n_key_data; + } + return r.code; +} diff --git a/krb5-1.21.3/src/lib/kadm5/clnt/client_rpc.c b/krb5-1.21.3/src/lib/kadm5/clnt/client_rpc.c new file mode 100644 index 00000000..d84d158b --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/clnt/client_rpc.c @@ -0,0 +1,213 @@ +/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t -*- */ +#include +#include +#include +#include +#include /* for memset prototype */ + +#ifdef HAVE_MEMORY_H +#include +#endif + +/* Default timeout can be changed using clnt_control() */ +static struct timeval TIMEOUT = { 25, 0 }; + +enum clnt_stat +create_principal_2(cprinc_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, CREATE_PRINCIPAL, + (xdrproc_t)xdr_cprinc_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +create_principal3_2(cprinc3_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, CREATE_PRINCIPAL3, + (xdrproc_t)xdr_cprinc3_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +delete_principal_2(dprinc_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, DELETE_PRINCIPAL, + (xdrproc_t)xdr_dprinc_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +modify_principal_2(mprinc_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, MODIFY_PRINCIPAL, + (xdrproc_t)xdr_mprinc_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +rename_principal_2(rprinc_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, RENAME_PRINCIPAL, + (xdrproc_t)xdr_rprinc_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +get_principal_2(gprinc_arg *argp, gprinc_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, GET_PRINCIPAL, + (xdrproc_t)xdr_gprinc_arg, (caddr_t)argp, + (xdrproc_t)xdr_gprinc_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +get_princs_2(gprincs_arg *argp, gprincs_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, GET_PRINCS, + (xdrproc_t)xdr_gprincs_arg, (caddr_t)argp, + (xdrproc_t)xdr_gprincs_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +chpass_principal_2(chpass_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, CHPASS_PRINCIPAL, + (xdrproc_t)xdr_chpass_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +chpass_principal3_2(chpass3_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, CHPASS_PRINCIPAL3, + (xdrproc_t)xdr_chpass3_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +setkey_principal_2(setkey_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, SETKEY_PRINCIPAL, + (xdrproc_t)xdr_setkey_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +setkey_principal3_2(setkey3_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, SETKEY_PRINCIPAL3, + (xdrproc_t)xdr_setkey3_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +setkey_principal4_2(setkey4_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, SETKEY_PRINCIPAL4, + (xdrproc_t)xdr_setkey4_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +chrand_principal_2(chrand_arg *argp, chrand_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, CHRAND_PRINCIPAL, + (xdrproc_t)xdr_chrand_arg, (caddr_t)argp, + (xdrproc_t)xdr_chrand_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +chrand_principal3_2(chrand3_arg *argp, chrand_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, CHRAND_PRINCIPAL3, + (xdrproc_t)xdr_chrand3_arg, (caddr_t)argp, + (xdrproc_t)xdr_chrand_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +create_policy_2(cpol_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, CREATE_POLICY, + (xdrproc_t)xdr_cpol_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +delete_policy_2(dpol_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, DELETE_POLICY, + (xdrproc_t)xdr_dpol_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +modify_policy_2(mpol_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, MODIFY_POLICY, + (xdrproc_t)xdr_mpol_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +get_policy_2(gpol_arg *argp, gpol_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, GET_POLICY, + (xdrproc_t)xdr_gpol_arg, (caddr_t)argp, + (xdrproc_t)xdr_gpol_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +get_pols_2(gpols_arg *argp, gpols_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, GET_POLS, + (xdrproc_t)xdr_gpols_arg, (caddr_t)argp, + (xdrproc_t)xdr_gpols_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +get_privs_2(void *argp, getprivs_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, GET_PRIVS, + (xdrproc_t)xdr_u_int32, (caddr_t)argp, + (xdrproc_t)xdr_getprivs_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +init_2(void *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, INIT, + (xdrproc_t)xdr_u_int32, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +purgekeys_2(purgekeys_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, PURGEKEYS, + (xdrproc_t)xdr_purgekeys_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +get_strings_2(gstrings_arg *argp, gstrings_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, GET_STRINGS, + (xdrproc_t)xdr_gstrings_arg, (caddr_t)argp, + (xdrproc_t)xdr_gstrings_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +set_string_2(sstring_arg *argp, generic_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, SET_STRING, + (xdrproc_t)xdr_sstring_arg, (caddr_t)argp, + (xdrproc_t)xdr_generic_ret, (caddr_t)res, TIMEOUT); +} + +enum clnt_stat +get_principal_keys_2(getpkeys_arg *argp, getpkeys_ret *res, CLIENT *clnt) +{ + return clnt_call(clnt, EXTRACT_KEYS, + (xdrproc_t)xdr_getpkeys_arg, (caddr_t)argp, + (xdrproc_t)xdr_getpkeys_ret, (caddr_t)res, TIMEOUT); +} diff --git a/krb5-1.21.3/src/lib/kadm5/clnt/clnt_chpass_util.c b/krb5-1.21.3/src/lib/kadm5/clnt/clnt_chpass_util.c new file mode 100644 index 00000000..618efda9 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/clnt/clnt_chpass_util.c @@ -0,0 +1,17 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include +#include "client_internal.h" + +kadm5_ret_t kadm5_chpass_principal_util(void *server_handle, + krb5_principal princ, + char *new_pw, + char **ret_pw, + char *msg_ret, + unsigned int msg_len) +{ + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + return _kadm5_chpass_principal_util(handle, handle->lhandle, princ, + new_pw, ret_pw, msg_ret, msg_len); +} diff --git a/krb5-1.21.3/src/lib/kadm5/clnt/clnt_policy.c b/krb5-1.21.3/src/lib/kadm5/clnt/clnt_policy.c new file mode 100644 index 00000000..42ba86f9 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/clnt/clnt_policy.c @@ -0,0 +1,130 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ + +#include +#include +#include +#include "client_internal.h" +#include +#include +#include + +kadm5_ret_t +kadm5_create_policy(void *server_handle, + kadm5_policy_ent_t policy, long mask) +{ + cpol_arg arg; + generic_ret r = { 0, 0 }; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + if(policy == (kadm5_policy_ent_t) NULL) + return EINVAL; + + arg.mask = mask; + arg.api_version = handle->api_version; + memcpy(&arg.rec, policy, sizeof(kadm5_policy_ent_rec)); + if (create_policy_2(&arg, &r, handle->clnt)) + return KADM5_RPC_ERROR; + return r.code; +} + +kadm5_ret_t +kadm5_delete_policy(void *server_handle, char *name) +{ + dpol_arg arg; + generic_ret r = { 0, 0 }; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + if(name == NULL) + return EINVAL; + + arg.name = name; + arg.api_version = handle->api_version; + + if (delete_policy_2(&arg, &r, handle->clnt)) + return KADM5_RPC_ERROR; + return r.code; +} + +kadm5_ret_t +kadm5_modify_policy(void *server_handle, + kadm5_policy_ent_t policy, long mask) +{ + mpol_arg arg; + generic_ret r = { 0, 0 }; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + if(policy == (kadm5_policy_ent_t) NULL) + return EINVAL; + + arg.mask = mask; + arg.api_version = handle->api_version; + + memcpy(&arg.rec, policy, sizeof(kadm5_policy_ent_rec)); + if (modify_policy_2(&arg, &r, handle->clnt)) + return KADM5_RPC_ERROR; + return r.code; +} + +kadm5_ret_t +kadm5_get_policy(void *server_handle, char *name, kadm5_policy_ent_t ent) +{ + gpol_arg arg; + gpol_ret r; + kadm5_server_handle_t handle = server_handle; + + memset(ent, 0, sizeof(*ent)); + + CHECK_HANDLE(server_handle); + + arg.name = name; + arg.api_version = handle->api_version; + + if(name == NULL) + return EINVAL; + + memset(&r, 0, sizeof(gpol_ret)); + if (get_policy_2(&arg, &r, handle->clnt)) + return KADM5_RPC_ERROR; + if (r.code == 0) + memcpy(ent, &r.rec, sizeof(r.rec)); + return r.code; +} + +kadm5_ret_t +kadm5_get_policies(void *server_handle, + char *exp, char ***pols, int *count) +{ + gpols_arg arg; + gpols_ret r; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + if(pols == NULL || count == NULL) + return EINVAL; + arg.exp = exp; + arg.api_version = handle->api_version; + memset(&r, 0, sizeof(gpols_ret)); + if (get_pols_2(&arg, &r, handle->clnt)) + return KADM5_RPC_ERROR; + if (r.code == 0) { + *count = r.count; + *pols = r.pols; + } else { + *count = 0; + *pols = NULL; + } + + return r.code; +} diff --git a/krb5-1.21.3/src/lib/kadm5/clnt/clnt_privs.c b/krb5-1.21.3/src/lib/kadm5/clnt/clnt_privs.c new file mode 100644 index 00000000..0627d72a --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/clnt/clnt_privs.c @@ -0,0 +1,28 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + * + * $Id$ + * $Source$ + * + */ + +#include +#include +#include +#include "client_internal.h" +#include + +kadm5_ret_t kadm5_get_privs(void *server_handle, long *privs) +{ + getprivs_ret r; + kadm5_server_handle_t handle = server_handle; + + memset(&r, 0, sizeof(getprivs_ret)); + if (get_privs_2(&handle->api_version, &r, handle->clnt)) + return KADM5_RPC_ERROR; + else if (r.code == KADM5_OK) + *privs = r.privs; + + return r.code; +} diff --git a/krb5-1.21.3/src/lib/kadm5/clnt/deps b/krb5-1.21.3/src/lib/kadm5/clnt/deps new file mode 100644 index 00000000..f2a0b28c --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/clnt/deps @@ -0,0 +1,84 @@ +# +# Generated makefile dependencies follow. +# +clnt_policy.so clnt_policy.po $(OUTPRE)clnt_policy.$(OBJEXT): \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h client_internal.h clnt_policy.c +client_rpc.so client_rpc.po $(OUTPRE)client_rpc.$(OBJEXT): \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/kadm_rpc.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h client_rpc.c +client_principal.so client_principal.po $(OUTPRE)client_principal.$(OBJEXT): \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h client_internal.h client_principal.c +client_init.so client_init.po $(OUTPRE)client_init.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/kadm_rpc.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/fake-addrinfo.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_gssapi.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + client_init.c client_internal.h +clnt_privs.so clnt_privs.po $(OUTPRE)clnt_privs.$(OBJEXT): \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h client_internal.h clnt_privs.c +clnt_chpass_util.so clnt_chpass_util.po $(OUTPRE)clnt_chpass_util.$(OBJEXT): \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h client_internal.h clnt_chpass_util.c diff --git a/krb5-1.21.3/src/lib/kadm5/clnt/libkadm5clnt_mit.exports b/krb5-1.21.3/src/lib/kadm5/clnt/libkadm5clnt_mit.exports new file mode 100644 index 00000000..9ed7d52d --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/clnt/libkadm5clnt_mit.exports @@ -0,0 +1,115 @@ +_kadm5_check_handle +_kadm5_chpass_principal_util +kadm5_chpass_principal +kadm5_chpass_principal_3 +kadm5_chpass_principal_util +kadm5_create_policy +kadm5_create_principal +kadm5_create_principal_3 +kadm5_decrypt_key +kadm5_delete_policy +kadm5_delete_principal +kadm5_destroy +kadm5_flush +kadm5_free_config_params +kadm5_free_kadm5_key_data +kadm5_free_key_data +kadm5_free_name_list +kadm5_free_policy_ent +kadm5_free_principal_ent +kadm5_free_strings +kadm5_get_admin_service_name +kadm5_get_config_params +kadm5_get_policies +kadm5_get_policy +kadm5_get_principal +kadm5_get_principal_keys +kadm5_get_principals +kadm5_get_privs +kadm5_get_strings +kadm5_init +kadm5_init_anonymous +kadm5_init_krb5_context +kadm5_init_with_creds +kadm5_init_with_password +kadm5_init_with_skey +kadm5_lock +kadm5_modify_policy +kadm5_modify_principal +kadm5_purgekeys +kadm5_randkey_principal +kadm5_randkey_principal_3 +kadm5_rename_principal +kadm5_set_string +kadm5_setkey_principal +kadm5_setkey_principal_3 +kadm5_setkey_principal_4 +kadm5_unlock +krb5_aprof_get_boolean +krb5_aprof_get_deltat +krb5_aprof_get_int32 +krb5_aprof_get_string +krb5_aprof_getvals +krb5_flagnum_to_string +krb5_flagspec_to_mask +krb5_flags_to_strings +krb5_free_key_data_contents +krb5_keysalt_is_present +krb5_keysalt_iterate +krb5_klog_close +krb5_klog_init +krb5_klog_reopen +krb5_klog_set_context +krb5_klog_syslog +krb5_string_to_keysalts +xdr_chpass3_arg +xdr_chpass_arg +xdr_chrand3_arg +xdr_chrand_arg +xdr_chrand_ret +xdr_cpol_arg +xdr_cprinc3_arg +xdr_cprinc_arg +xdr_dpol_arg +xdr_dprinc_arg +xdr_generic_ret +xdr_getpkeys_arg +xdr_getpkeys_ret +xdr_getprivs_ret +xdr_gpol_arg +xdr_gpol_ret +xdr_gpols_arg +xdr_gpols_ret +xdr_gprinc_arg +xdr_gprinc_ret +xdr_gprincs_arg +xdr_gprincs_ret +xdr_kadm5_key_data +xdr_kadm5_policy_ent_rec +xdr_kadm5_principal_ent_rec +xdr_kadm5_ret_t +xdr_krb5_deltat +xdr_krb5_enctype +xdr_krb5_flags +xdr_krb5_int16 +xdr_krb5_key_data_nocontents +xdr_krb5_key_salt_tuple +xdr_krb5_keyblock +xdr_krb5_kvno +xdr_krb5_octet +xdr_krb5_principal +xdr_krb5_salttype +xdr_krb5_timestamp +xdr_krb5_tl_data +xdr_krb5_ui_2 +xdr_krb5_ui_4 +xdr_mpol_arg +xdr_mprinc_arg +xdr_nullstring +xdr_nulltype +xdr_rprinc_arg +xdr_setkey3_arg +xdr_setkey4_arg +xdr_setkey_arg +xdr_ui_4 +kadm5_init_iprop diff --git a/krb5-1.21.3/src/lib/kadm5/deps b/krb5-1.21.3/src/lib/kadm5/deps new file mode 100644 index 00000000..3585f08f --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/deps @@ -0,0 +1,111 @@ +# +# Generated makefile dependencies follow. +# +kadm_err.so kadm_err.po $(OUTPRE)kadm_err.$(OBJEXT): \ + $(COM_ERR_DEPS) kadm_err.c +chpass_util_strings.so chpass_util_strings.po $(OUTPRE)chpass_util_strings.$(OBJEXT): \ + $(COM_ERR_DEPS) chpass_util_strings.c +misc_free.so misc_free.po $(OUTPRE)misc_free.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + admin_internal.h misc_free.c server_internal.h +kadm_rpc_xdr.so kadm_rpc_xdr.po $(OUTPRE)kadm_rpc_xdr.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/admin_xdr.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/kadm_rpc.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/plugin.h \ + kadm_rpc_xdr.c +chpass_util.so chpass_util.po $(OUTPRE)chpass_util.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + admin_internal.h chpass_util.c +alt_prof.so alt_prof.po $(OUTPRE)alt_prof.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/fake-addrinfo.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h alt_prof.c +str_conv.so str_conv.po $(OUTPRE)str_conv.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h admin_internal.h \ + str_conv.c +logger.so logger.po $(OUTPRE)logger.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + logger.c diff --git a/krb5-1.21.3/src/lib/kadm5/kadm_err.et b/krb5-1.21.3/src/lib/kadm5/kadm_err.et new file mode 100644 index 00000000..fbe2e763 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/kadm_err.et @@ -0,0 +1,70 @@ +# This is the KADM5 error table. The order of error codes +# defined in this file MUST match that specified in the API +# functionality specification, which is the master version. +# +error_table ovk +# vv 0 +error_code KADM5_FAILURE, "Operation failed for unspecified reason" +error_code KADM5_AUTH_GET, "Operation requires ``get'' privilege" +error_code KADM5_AUTH_ADD, "Operation requires ``add'' privilege" +error_code KADM5_AUTH_MODIFY, "Operation requires ``modify'' privilege" +error_code KADM5_AUTH_DELETE, "Operation requires ``delete'' privilege" +error_code KADM5_AUTH_INSUFFICIENT, "Insufficient authorization for operation" +error_code KADM5_BAD_DB, "Database inconsistency detected" +error_code KADM5_DUP, "Principal or policy already exists" +error_code KADM5_RPC_ERROR, "Communication failure with server" +error_code KADM5_NO_SRV, "No administration server found for realm" +error_code KADM5_BAD_HIST_KEY, "Password history principal key version mismatch" +error_code KADM5_NOT_INIT, "Connection to server not initialized" +error_code KADM5_UNK_PRINC, "Principal does not exist" +error_code KADM5_UNK_POLICY, "Policy does not exist" +error_code KADM5_BAD_MASK, "Invalid field mask for operation" +error_code KADM5_BAD_CLASS, "Invalid number of character classes" +error_code KADM5_BAD_LENGTH, "Invalid password length" +error_code KADM5_BAD_POLICY, "Illegal policy name" +error_code KADM5_BAD_PRINCIPAL, "Illegal principal name" +error_code KADM5_BAD_AUX_ATTR, "Invalid auxiliary attributes" +error_code KADM5_BAD_HISTORY, "Invalid password history count" +error_code KADM5_BAD_MIN_PASS_LIFE, "Password minimum life is greater than password maximum life" +error_code KADM5_PASS_Q_TOOSHORT, "Password is too short" +error_code KADM5_PASS_Q_CLASS, "Password does not contain enough character classes" +error_code KADM5_PASS_Q_DICT, "Password is in the password dictionary" +error_code KADM5_PASS_REUSE, "Cannot reuse password" +error_code KADM5_PASS_TOOSOON, "Current password's minimum life has not expired" +error_code KADM5_POLICY_REF, "Policy is in use" +error_code KADM5_INIT, "Connection to server already initialized" +error_code KADM5_BAD_PASSWORD, "Incorrect password" +error_code KADM5_PROTECT_PRINCIPAL, "Cannot change protected principal" +error_code KADM5_BAD_SERVER_HANDLE, "Programmer error! Bad Admin server handle" +error_code KADM5_BAD_STRUCT_VERSION, "Programmer error! Bad API structure version" +error_code KADM5_OLD_STRUCT_VERSION, "API structure version specified by application is no longer supported (to fix, recompile application against current KADM5 API header files and libraries)" +error_code KADM5_NEW_STRUCT_VERSION, "API structure version specified by application is unknown to libraries (to fix, obtain current KADM5 API header files and libraries and recompile application)" +error_code KADM5_BAD_API_VERSION, "Programmer error! Bad API version" +error_code KADM5_OLD_LIB_API_VERSION, "API version specified by application is no longer supported by libraries (to fix, update application to adhere to current API version and recompile)" +error_code KADM5_OLD_SERVER_API_VERSION, "API version specified by application is no longer supported by server (to fix, update application to adhere to current API version and recompile)" +error_code KADM5_NEW_LIB_API_VERSION, "API version specified by application is unknown to libraries (to fix, obtain current KADM5 API header files and libraries and recompile application)" +error_code KADM5_NEW_SERVER_API_VERSION, "API version specified by application is unknown to server (to fix, obtain and install newest KADM5 Admin Server)" +error_code KADM5_SECURE_PRINC_MISSING, "Database error! Required KADM5 principal missing" +error_code KADM5_NO_RENAME_SALT, "The salt type of the specified principal does not support renaming" +error_code KADM5_BAD_CLIENT_PARAMS, "Illegal configuration parameter for remote KADM5 client" +error_code KADM5_BAD_SERVER_PARAMS, "Illegal configuration parameter for local KADM5 client" +error_code KADM5_AUTH_LIST, "Operation requires ``list'' privilege" +error_code KADM5_AUTH_CHANGEPW, "Operation requires ``change-password'' privilege" +error_code KADM5_GSS_ERROR, "GSS-API (or Kerberos) error" +error_code KADM5_BAD_TL_TYPE, "Programmer error! Illegal tagged data list type" +error_code KADM5_MISSING_CONF_PARAMS, "Required parameters in kdc.conf missing" +error_code KADM5_BAD_SERVER_NAME, "Bad krb5 admin server hostname" +error_code KADM5_AUTH_SETKEY, "Operation requires ``set-key'' privilege" +error_code KADM5_SETKEY_DUP_ENCTYPES, "Multiple values for single or folded enctype" +error_code KADM5_SETV4KEY_INVAL_ENCTYPE, "Invalid enctype for setv4key" +error_code KADM5_SETKEY3_ETYPE_MISMATCH, "Mismatched enctypes for setkey3" +error_code KADM5_MISSING_KRB5_CONF_PARAMS, "Missing parameters in krb5.conf required for kadmin client" +error_code KADM5_XDR_FAILURE, "XDR encoding error" +error_code KADM5_CANT_RESOLVE, "Cannot resolve network address for admin server in requested realm" +error_code KADM5_PASS_Q_GENERIC, "Unspecified password quality failure" +error_code KADM5_BAD_KEYSALTS, "Invalid key/salt tuples" +error_code KADM5_SETKEY_BAD_KVNO, "Invalid multiple or duplicate kvnos in setkey operation" +error_code KADM5_AUTH_EXTRACT, "Operation requires ``extract-keys'' privilege" +error_code KADM5_PROTECT_KEYS, "Principal keys are locked down" +error_code KADM5_AUTH_INITIAL, "Operation requires initial ticket" +end diff --git a/krb5-1.21.3/src/lib/kadm5/kadm_rpc.h b/krb5-1.21.3/src/lib/kadm5/kadm_rpc.h new file mode 100644 index 00000000..5099c6c1 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/kadm_rpc.h @@ -0,0 +1,408 @@ +/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t -*- */ +#ifndef __KADM_RPC_H__ +#define __KADM_RPC_H__ + +#include + +#include +#include + +struct cprinc_arg { + krb5_ui_4 api_version; + kadm5_principal_ent_rec rec; + long mask; + char *passwd; +}; +typedef struct cprinc_arg cprinc_arg; + +struct cprinc3_arg { + krb5_ui_4 api_version; + kadm5_principal_ent_rec rec; + long mask; + int n_ks_tuple; + krb5_key_salt_tuple *ks_tuple; + char *passwd; +}; +typedef struct cprinc3_arg cprinc3_arg; + +struct generic_ret { + krb5_ui_4 api_version; + kadm5_ret_t code; +}; +typedef struct generic_ret generic_ret; + +struct dprinc_arg { + krb5_ui_4 api_version; + krb5_principal princ; +}; +typedef struct dprinc_arg dprinc_arg; + +struct mprinc_arg { + krb5_ui_4 api_version; + kadm5_principal_ent_rec rec; + long mask; +}; +typedef struct mprinc_arg mprinc_arg; + +struct rprinc_arg { + krb5_ui_4 api_version; + krb5_principal src; + krb5_principal dest; +}; +typedef struct rprinc_arg rprinc_arg; + +struct gprincs_arg { + krb5_ui_4 api_version; + char *exp; +}; +typedef struct gprincs_arg gprincs_arg; + +struct gprincs_ret { + krb5_ui_4 api_version; + kadm5_ret_t code; + char **princs; + int count; +}; +typedef struct gprincs_ret gprincs_ret; + +struct chpass_arg { + krb5_ui_4 api_version; + krb5_principal princ; + char *pass; +}; +typedef struct chpass_arg chpass_arg; + +struct chpass3_arg { + krb5_ui_4 api_version; + krb5_principal princ; + krb5_boolean keepold; + int n_ks_tuple; + krb5_key_salt_tuple *ks_tuple; + char *pass; +}; +typedef struct chpass3_arg chpass3_arg; + +struct setkey_arg { + krb5_ui_4 api_version; + krb5_principal princ; + krb5_keyblock *keyblocks; + int n_keys; +}; +typedef struct setkey_arg setkey_arg; + +struct setkey3_arg { + krb5_ui_4 api_version; + krb5_principal princ; + krb5_boolean keepold; + int n_ks_tuple; + krb5_key_salt_tuple *ks_tuple; + krb5_keyblock *keyblocks; + int n_keys; +}; +typedef struct setkey3_arg setkey3_arg; + +struct setkey4_arg { + krb5_ui_4 api_version; + krb5_principal princ; + krb5_boolean keepold; + kadm5_key_data *key_data; + int n_key_data; +}; +typedef struct setkey4_arg setkey4_arg; + +struct chrand_arg { + krb5_ui_4 api_version; + krb5_principal princ; +}; +typedef struct chrand_arg chrand_arg; + +struct chrand3_arg { + krb5_ui_4 api_version; + krb5_principal princ; + krb5_boolean keepold; + int n_ks_tuple; + krb5_key_salt_tuple *ks_tuple; +}; +typedef struct chrand3_arg chrand3_arg; + +struct chrand_ret { + krb5_ui_4 api_version; + kadm5_ret_t code; + krb5_keyblock key; + krb5_keyblock *keys; + int n_keys; +}; +typedef struct chrand_ret chrand_ret; + +struct gprinc_arg { + krb5_ui_4 api_version; + krb5_principal princ; + long mask; +}; +typedef struct gprinc_arg gprinc_arg; + +struct gprinc_ret { + krb5_ui_4 api_version; + kadm5_ret_t code; + kadm5_principal_ent_rec rec; +}; +typedef struct gprinc_ret gprinc_ret; + +struct cpol_arg { + krb5_ui_4 api_version; + kadm5_policy_ent_rec rec; + long mask; +}; +typedef struct cpol_arg cpol_arg; + +struct dpol_arg { + krb5_ui_4 api_version; + char *name; +}; +typedef struct dpol_arg dpol_arg; + +struct mpol_arg { + krb5_ui_4 api_version; + kadm5_policy_ent_rec rec; + long mask; +}; +typedef struct mpol_arg mpol_arg; + +struct gpol_arg { + krb5_ui_4 api_version; + char *name; +}; +typedef struct gpol_arg gpol_arg; + +struct gpol_ret { + krb5_ui_4 api_version; + kadm5_ret_t code; + kadm5_policy_ent_rec rec; +}; +typedef struct gpol_ret gpol_ret; + +struct gpols_arg { + krb5_ui_4 api_version; + char *exp; +}; +typedef struct gpols_arg gpols_arg; + +struct gpols_ret { + krb5_ui_4 api_version; + kadm5_ret_t code; + char **pols; + int count; +}; +typedef struct gpols_ret gpols_ret; + +struct getprivs_ret { + krb5_ui_4 api_version; + kadm5_ret_t code; + long privs; +}; +typedef struct getprivs_ret getprivs_ret; + +struct purgekeys_arg { + krb5_ui_4 api_version; + krb5_principal princ; + int keepkvno; +}; +typedef struct purgekeys_arg purgekeys_arg; + +struct gstrings_arg { + krb5_ui_4 api_version; + krb5_principal princ; +}; +typedef struct gstrings_arg gstrings_arg; + +struct gstrings_ret { + krb5_ui_4 api_version; + kadm5_ret_t code; + krb5_string_attr *strings; + int count; +}; +typedef struct gstrings_ret gstrings_ret; + +struct sstring_arg { + krb5_ui_4 api_version; + krb5_principal princ; + char *key; + char *value; +}; +typedef struct sstring_arg sstring_arg; + +struct getpkeys_arg { + krb5_ui_4 api_version; + krb5_principal princ; + krb5_kvno kvno; +}; +typedef struct getpkeys_arg getpkeys_arg; + +struct getpkeys_ret { + krb5_ui_4 api_version; + kadm5_ret_t code; + kadm5_key_data *key_data; + int n_key_data; +}; +typedef struct getpkeys_ret getpkeys_ret; + +#define KADM 2112 +#define KADMVERS 2 +#define CREATE_PRINCIPAL 1 +extern enum clnt_stat create_principal_2(cprinc_arg *, generic_ret *, + CLIENT *); +extern bool_t create_principal_2_svc(cprinc_arg *, generic_ret *, + struct svc_req *); +#define DELETE_PRINCIPAL 2 +extern enum clnt_stat delete_principal_2(dprinc_arg *, generic_ret *, + CLIENT *); +extern bool_t delete_principal_2_svc(dprinc_arg *, generic_ret *, + struct svc_req *); +#define MODIFY_PRINCIPAL 3 +extern enum clnt_stat modify_principal_2(mprinc_arg *, generic_ret *, + CLIENT *); +extern bool_t modify_principal_2_svc(mprinc_arg *, generic_ret *, + struct svc_req *); +#define RENAME_PRINCIPAL 4 +extern enum clnt_stat rename_principal_2(rprinc_arg *, generic_ret *, + CLIENT *); +extern bool_t rename_principal_2_svc(rprinc_arg *, generic_ret *, + struct svc_req *); +#define GET_PRINCIPAL 5 +extern enum clnt_stat get_principal_2(gprinc_arg *, gprinc_ret *, CLIENT *); +extern bool_t get_principal_2_svc(gprinc_arg *, gprinc_ret *, + struct svc_req *); +#define CHPASS_PRINCIPAL 6 +extern enum clnt_stat chpass_principal_2(chpass_arg *, generic_ret *, + CLIENT *); +extern bool_t chpass_principal_2_svc(chpass_arg *, generic_ret *, + struct svc_req *); +#define CHRAND_PRINCIPAL 7 +extern enum clnt_stat chrand_principal_2(chrand_arg *, chrand_ret *, + CLIENT *); +extern bool_t chrand_principal_2_svc(chrand_arg *, chrand_ret *, + struct svc_req *); +#define CREATE_POLICY 8 +extern enum clnt_stat create_policy_2(cpol_arg *, generic_ret *, CLIENT *); +extern bool_t create_policy_2_svc(cpol_arg *, generic_ret *, + struct svc_req *); +#define DELETE_POLICY 9 +extern enum clnt_stat delete_policy_2(dpol_arg *, generic_ret *, CLIENT *); +extern bool_t delete_policy_2_svc(dpol_arg *, generic_ret *, + struct svc_req *); +#define MODIFY_POLICY 10 +extern enum clnt_stat modify_policy_2(mpol_arg *, generic_ret *, CLIENT *); +extern bool_t modify_policy_2_svc(mpol_arg *, generic_ret *, + struct svc_req *); +#define GET_POLICY 11 +extern enum clnt_stat get_policy_2(gpol_arg *, gpol_ret *, CLIENT *); +extern bool_t get_policy_2_svc(gpol_arg *, gpol_ret *, struct svc_req *); +#define GET_PRIVS 12 +extern enum clnt_stat get_privs_2(void *, getprivs_ret *, CLIENT *); +extern bool_t get_privs_2_svc(krb5_ui_4 *, getprivs_ret *, struct svc_req *); +#define INIT 13 +extern enum clnt_stat init_2(void *, generic_ret *, CLIENT *); +extern bool_t init_2_svc(krb5_ui_4 *, generic_ret *, struct svc_req *); +#define GET_PRINCS 14 +extern enum clnt_stat get_princs_2(gprincs_arg *, gprincs_ret *, CLIENT *); +extern bool_t get_princs_2_svc(gprincs_arg *, gprincs_ret *, + struct svc_req *); +#define GET_POLS 15 +extern enum clnt_stat get_pols_2(gpols_arg *, gpols_ret *, CLIENT *); +extern bool_t get_pols_2_svc(gpols_arg *, gpols_ret *, struct svc_req *); +#define SETKEY_PRINCIPAL 16 +extern enum clnt_stat setkey_principal_2(setkey_arg *, generic_ret *, + CLIENT *); +extern bool_t setkey_principal_2_svc(setkey_arg *, generic_ret *, + struct svc_req *); + +/* 17 was SETV4KEY_PRINCIPAL (removed in 1.18). */ + +#define CREATE_PRINCIPAL3 18 +extern enum clnt_stat create_principal3_2(cprinc3_arg *, generic_ret *, + CLIENT *); +extern bool_t create_principal3_2_svc(cprinc3_arg *, generic_ret *, + struct svc_req *); +#define CHPASS_PRINCIPAL3 19 +extern enum clnt_stat chpass_principal3_2(chpass3_arg *, generic_ret *, + CLIENT *); +extern bool_t chpass_principal3_2_svc(chpass3_arg *, generic_ret *, + struct svc_req *); +#define CHRAND_PRINCIPAL3 20 +extern enum clnt_stat chrand_principal3_2(chrand3_arg *, chrand_ret *, + CLIENT *); +extern bool_t chrand_principal3_2_svc(chrand3_arg *, chrand_ret *, + struct svc_req *); +#define SETKEY_PRINCIPAL3 21 +extern enum clnt_stat setkey_principal3_2(setkey3_arg *, generic_ret *, + CLIENT *); +extern bool_t setkey_principal3_2_svc(setkey3_arg *, generic_ret *, + struct svc_req *); +#define PURGEKEYS 22 +extern enum clnt_stat purgekeys_2(purgekeys_arg *, generic_ret *, CLIENT *); +extern bool_t purgekeys_2_svc(purgekeys_arg *, generic_ret *, + struct svc_req *); +#define GET_STRINGS 23 +extern enum clnt_stat get_strings_2(gstrings_arg *, gstrings_ret *, CLIENT *); +extern bool_t get_strings_2_svc(gstrings_arg *, gstrings_ret *, + struct svc_req *); +#define SET_STRING 24 +extern enum clnt_stat set_string_2(sstring_arg *, generic_ret *, CLIENT *); +extern bool_t set_string_2_svc(sstring_arg *, generic_ret *, + struct svc_req *); +#define SETKEY_PRINCIPAL4 25 +extern enum clnt_stat setkey_principal4_2(setkey4_arg *, generic_ret *, + CLIENT *); +extern bool_t setkey_principal4_2_svc(setkey4_arg *, generic_ret *, + struct svc_req *); +#define EXTRACT_KEYS 26 +extern enum clnt_stat get_principal_keys_2(getpkeys_arg *, getpkeys_ret *, + CLIENT *); +extern bool_t get_principal_keys_2_svc(getpkeys_arg *, getpkeys_ret *, + struct svc_req *); + +extern bool_t xdr_cprinc_arg (); +extern bool_t xdr_cprinc3_arg (); +extern bool_t xdr_generic_ret (); +extern bool_t xdr_dprinc_arg (); +extern bool_t xdr_mprinc_arg (); +extern bool_t xdr_rprinc_arg (); +extern bool_t xdr_gprincs_arg (); +extern bool_t xdr_gprincs_ret (); +extern bool_t xdr_chpass_arg (); +extern bool_t xdr_chpass3_arg (); +extern bool_t xdr_setkey_arg (); +extern bool_t xdr_setkey3_arg (); +extern bool_t xdr_setkey4_arg (); +extern bool_t xdr_chrand_arg (); +extern bool_t xdr_chrand3_arg (); +extern bool_t xdr_chrand_ret (); +extern bool_t xdr_gprinc_arg (); +extern bool_t xdr_gprinc_ret (); +extern bool_t xdr_kadm5_ret_t (); +extern bool_t xdr_kadm5_principal_ent_rec (); +extern bool_t xdr_kadm5_policy_ent_rec (); +extern bool_t xdr_krb5_keyblock (); +extern bool_t xdr_krb5_principal (); +extern bool_t xdr_krb5_enctype (); +extern bool_t xdr_krb5_octet (); +extern bool_t xdr_krb5_int32 (); +extern bool_t xdr_u_int32 (); +extern bool_t xdr_cpol_arg (); +extern bool_t xdr_dpol_arg (); +extern bool_t xdr_mpol_arg (); +extern bool_t xdr_gpol_arg (); +extern bool_t xdr_gpol_ret (); +extern bool_t xdr_gpols_arg (); +extern bool_t xdr_gpols_ret (); +extern bool_t xdr_getprivs_ret (); +extern bool_t xdr_purgekeys_arg (); +extern bool_t xdr_gstrings_arg (); +extern bool_t xdr_gstrings_ret (); +extern bool_t xdr_sstring_arg (); +extern bool_t xdr_krb5_string_attr (); +extern bool_t xdr_kadm5_key_data (); +extern bool_t xdr_getpkeys_arg (); +extern bool_t xdr_getpkeys_ret (); + +#endif /* __KADM_RPC_H__ */ diff --git a/krb5-1.21.3/src/lib/kadm5/kadm_rpc_xdr.c b/krb5-1.21.3/src/lib/kadm5/kadm_rpc_xdr.c new file mode 100644 index 00000000..287cae75 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/kadm_rpc_xdr.c @@ -0,0 +1,1206 @@ +/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static bool_t +_xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp, + int v); +static bool_t +_xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp, int vers); + +/* + * Function: xdr_ui_4 + * + * Purpose: XDR function which serves as a wrapper for xdr_u_int32, + * to prevent compiler warnings about type clashes between u_int32 + * and krb5_ui_4. + */ +bool_t xdr_ui_4(XDR *xdrs, krb5_ui_4 *objp) +{ + /* Assumes that krb5_ui_4 and u_int32 are both four bytes long. + This should not be a harmful assumption. */ + return xdr_u_int32(xdrs, (uint32_t *) objp); +} + + +/* + * Function: xdr_nullstring + * + * Purpose: XDR function for "strings" that are either NULL-terminated + * or NULL. + */ +bool_t xdr_nullstring(XDR *xdrs, char **objp) +{ + u_int size; + + if (xdrs->x_op == XDR_ENCODE) { + if (*objp == NULL) + size = 0; + else + size = strlen(*objp) + 1; + } + if (! xdr_u_int(xdrs, &size)) { + return FALSE; + } + switch (xdrs->x_op) { + case XDR_DECODE: + if (size == 0) { + *objp = NULL; + return TRUE; + } else if (*objp == NULL) { + *objp = (char *) mem_alloc(size); + if (*objp == NULL) { + errno = ENOMEM; + return FALSE; + } + } + if (!xdr_opaque(xdrs, *objp, size)) + return FALSE; + /* Check that the unmarshalled bytes are a C string. */ + if ((*objp)[size - 1] != '\0') + return FALSE; + if (memchr(*objp, '\0', size - 1) != NULL) + return FALSE; + return TRUE; + + case XDR_ENCODE: + if (size != 0) + return (xdr_opaque(xdrs, *objp, size)); + return TRUE; + + case XDR_FREE: + if (*objp != NULL) + mem_free(*objp, size); + *objp = NULL; + return TRUE; + } + + return FALSE; +} + +/* + * Function: xdr_nulltype + * + * Purpose: XDR function for arbitrary pointer types that are either + * NULL or contain data. + */ +bool_t xdr_nulltype(XDR *xdrs, void **objp, xdrproc_t proc) +{ + bool_t null; + + switch (xdrs->x_op) { + case XDR_DECODE: + if (!xdr_bool(xdrs, &null)) + return FALSE; + if (null) { + *objp = NULL; + return TRUE; + } + return (*proc)(xdrs, objp); + + case XDR_ENCODE: + if (*objp == NULL) + null = TRUE; + else + null = FALSE; + if (!xdr_bool(xdrs, &null)) + return FALSE; + if (null == FALSE) + return (*proc)(xdrs, objp); + return TRUE; + + case XDR_FREE: + if (*objp) + return (*proc)(xdrs, objp); + return TRUE; + } + + return FALSE; +} + +bool_t +xdr_krb5_timestamp(XDR *xdrs, krb5_timestamp *objp) +{ + /* This assumes that int32 and krb5_timestamp are the same size. + This shouldn't be a problem, since we've got a unit test which + checks for this. */ + if (!xdr_int32(xdrs, (int32_t *) objp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_krb5_kvno(XDR *xdrs, krb5_kvno *objp) +{ + return xdr_u_int(xdrs, objp); +} + +bool_t +xdr_krb5_deltat(XDR *xdrs, krb5_deltat *objp) +{ + /* This assumes that int32 and krb5_deltat are the same size. + This shouldn't be a problem, since we've got a unit test which + checks for this. */ + if (!xdr_int32(xdrs, (int32_t *) objp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_krb5_flags(XDR *xdrs, krb5_flags *objp) +{ + /* This assumes that int32 and krb5_flags are the same size. + This shouldn't be a problem, since we've got a unit test which + checks for this. */ + if (!xdr_int32(xdrs, (int32_t *) objp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_krb5_ui_4(XDR *xdrs, krb5_ui_4 *objp) +{ + if (!xdr_u_int32(xdrs, (uint32_t *) objp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_krb5_int16(XDR *xdrs, krb5_int16 *objp) +{ + int tmp; + + tmp = (int) *objp; + + if (!xdr_int(xdrs, &tmp)) + return(FALSE); + + *objp = (krb5_int16) tmp; + + return(TRUE); +} + +/* + * Function: xdr_krb5_ui_2 + * + * Purpose: XDR function which serves as a wrapper for xdr_u_int, + * to prevent compiler warnings about type clashes between u_int + * and krb5_ui_2. + */ +bool_t +xdr_krb5_ui_2(XDR *xdrs, krb5_ui_2 *objp) +{ + unsigned int tmp; + + tmp = (unsigned int) *objp; + + if (!xdr_u_int(xdrs, &tmp)) + return(FALSE); + + *objp = (krb5_ui_2) tmp; + + return(TRUE); +} + + + +static bool_t xdr_krb5_boolean(XDR *xdrs, krb5_boolean *kbool) +{ + bool_t val; + + switch (xdrs->x_op) { + case XDR_DECODE: + if (!xdr_bool(xdrs, &val)) + return FALSE; + + *kbool = (val == FALSE) ? FALSE : TRUE; + return TRUE; + + case XDR_ENCODE: + val = *kbool ? TRUE : FALSE; + return xdr_bool(xdrs, &val); + + case XDR_FREE: + return TRUE; + } + + return FALSE; +} + +bool_t xdr_krb5_key_data_nocontents(XDR *xdrs, krb5_key_data *objp) +{ + /* + * Note that this function intentionally DOES NOT transfer key + * length or contents! xdr_krb5_key_data in adb_xdr.c does, but + * that is only for use within the server-side library. + */ + unsigned int tmp; + + if (xdrs->x_op == XDR_DECODE) + memset(objp, 0, sizeof(krb5_key_data)); + + if (!xdr_krb5_int16(xdrs, &objp->key_data_ver)) { + return (FALSE); + } + if (!xdr_krb5_ui_2(xdrs, &objp->key_data_kvno)) { + return (FALSE); + } + if (!xdr_krb5_int16(xdrs, &objp->key_data_type[0])) { + return (FALSE); + } + if (objp->key_data_ver > 1) { + if (!xdr_krb5_int16(xdrs, &objp->key_data_type[1])) { + return (FALSE); + } + } + /* + * kadm5_get_principal on the server side allocates and returns + * key contents when asked. Even though this function refuses to + * transmit that data, it still has to *free* the data at the + * appropriate time to avoid a memory leak. + */ + if (xdrs->x_op == XDR_FREE) { + tmp = (unsigned int) objp->key_data_length[0]; + if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[0], + &tmp, ~0)) + return FALSE; + + tmp = (unsigned int) objp->key_data_length[1]; + if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[1], + &tmp, ~0)) + return FALSE; + } + + return (TRUE); +} + + +bool_t +xdr_krb5_key_salt_tuple(XDR *xdrs, krb5_key_salt_tuple *objp) +{ + if (!xdr_krb5_enctype(xdrs, &objp->ks_enctype)) + return FALSE; + if (!xdr_krb5_salttype(xdrs, &objp->ks_salttype)) + return FALSE; + return TRUE; +} + +bool_t xdr_krb5_tl_data(XDR *xdrs, krb5_tl_data **tl_data_head) +{ + krb5_tl_data *tl, *tl2; + bool_t more; + unsigned int len; + + switch (xdrs->x_op) { + case XDR_FREE: + tl = tl2 = *tl_data_head; + while (tl) { + tl2 = tl->tl_data_next; + free(tl->tl_data_contents); + free(tl); + tl = tl2; + } + *tl_data_head = NULL; + break; + + case XDR_ENCODE: + tl = *tl_data_head; + while (1) { + more = (tl != NULL); + if (!xdr_bool(xdrs, &more)) + return FALSE; + if (tl == NULL) + break; + if (!xdr_krb5_int16(xdrs, &tl->tl_data_type)) + return FALSE; + len = tl->tl_data_length; + if (!xdr_bytes(xdrs, (char **) &tl->tl_data_contents, &len, ~0)) + return FALSE; + tl = tl->tl_data_next; + } + break; + + case XDR_DECODE: + tl = NULL; + while (1) { + if (!xdr_bool(xdrs, &more)) + return FALSE; + if (more == FALSE) + break; + tl2 = (krb5_tl_data *) malloc(sizeof(krb5_tl_data)); + if (tl2 == NULL) + return FALSE; + memset(tl2, 0, sizeof(krb5_tl_data)); + if (!xdr_krb5_int16(xdrs, &tl2->tl_data_type)) + return FALSE; + if (!xdr_bytes(xdrs, (char **)&tl2->tl_data_contents, &len, ~0)) + return FALSE; + tl2->tl_data_length = len; + + tl2->tl_data_next = tl; + tl = tl2; + } + + *tl_data_head = tl; + break; + } + + return TRUE; +} + +bool_t +xdr_kadm5_ret_t(XDR *xdrs, kadm5_ret_t *objp) +{ + uint32_t tmp; + + if (xdrs->x_op == XDR_ENCODE) + tmp = (uint32_t) *objp; + + if (!xdr_u_int32(xdrs, &tmp)) + return (FALSE); + + if (xdrs->x_op == XDR_DECODE) + *objp = (kadm5_ret_t) tmp; + + return (TRUE); +} + +bool_t xdr_kadm5_principal_ent_rec(XDR *xdrs, + kadm5_principal_ent_rec *objp) +{ + return _xdr_kadm5_principal_ent_rec(xdrs, objp, KADM5_API_VERSION_3); +} + +static bool_t +_xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp, + int v) +{ + unsigned int n; + bool_t r; + + if (!xdr_krb5_principal(xdrs, &objp->principal)) { + return (FALSE); + } + if (!xdr_krb5_timestamp(xdrs, &objp->princ_expire_time)) { + return (FALSE); + } + if (!xdr_krb5_timestamp(xdrs, &objp->last_pwd_change)) { + return (FALSE); + } + if (!xdr_krb5_timestamp(xdrs, &objp->pw_expiration)) { + return (FALSE); + } + if (!xdr_krb5_deltat(xdrs, &objp->max_life)) { + return (FALSE); + } + if (!xdr_nulltype(xdrs, (void **) &objp->mod_name, + xdr_krb5_principal)) { + return (FALSE); + } + if (!xdr_krb5_timestamp(xdrs, &objp->mod_date)) { + return (FALSE); + } + if (!xdr_krb5_flags(xdrs, &objp->attributes)) { + return (FALSE); + } + if (!xdr_krb5_kvno(xdrs, &objp->kvno)) { + return (FALSE); + } + if (!xdr_krb5_kvno(xdrs, &objp->mkvno)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->policy)) { + return (FALSE); + } + if (!xdr_long(xdrs, &objp->aux_attributes)) { + return (FALSE); + } + if (!xdr_krb5_deltat(xdrs, &objp->max_renewable_life)) { + return (FALSE); + } + if (!xdr_krb5_timestamp(xdrs, &objp->last_success)) { + return (FALSE); + } + if (!xdr_krb5_timestamp(xdrs, &objp->last_failed)) { + return (FALSE); + } + if (!xdr_krb5_kvno(xdrs, &objp->fail_auth_count)) { + return (FALSE); + } + if (!xdr_krb5_int16(xdrs, &objp->n_key_data)) { + return (FALSE); + } + if (xdrs->x_op == XDR_DECODE && objp->n_key_data < 0) { + return (FALSE); + } + if (!xdr_krb5_int16(xdrs, &objp->n_tl_data)) { + return (FALSE); + } + if (!xdr_nulltype(xdrs, (void **) &objp->tl_data, + xdr_krb5_tl_data)) { + return FALSE; + } + n = objp->n_key_data; + r = xdr_array(xdrs, (caddr_t *) &objp->key_data, &n, objp->n_key_data, + sizeof(krb5_key_data), xdr_krb5_key_data_nocontents); + objp->n_key_data = n; + if (!r) { + return (FALSE); + } + + return (TRUE); +} + +static bool_t +_xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp, int vers) +{ + if (!xdr_nullstring(xdrs, &objp->policy)) { + return (FALSE); + } + /* these all used to be u_int32, but it's stupid for sized types + to be exposed at the api, and they're the same as longs on the + wire. */ + if (!xdr_long(xdrs, &objp->pw_min_life)) { + return (FALSE); + } + if (!xdr_long(xdrs, &objp->pw_max_life)) { + return (FALSE); + } + if (!xdr_long(xdrs, &objp->pw_min_length)) { + return (FALSE); + } + if (!xdr_long(xdrs, &objp->pw_min_classes)) { + return (FALSE); + } + if (!xdr_long(xdrs, &objp->pw_history_num)) { + return (FALSE); + } + if (!xdr_long(xdrs, &objp->policy_refcnt)) { + return (FALSE); + } + if (xdrs->x_op == XDR_DECODE) { + objp->pw_max_fail = 0; + objp->pw_failcnt_interval = 0; + objp->pw_lockout_duration = 0; + objp->attributes = 0; + objp->max_life = 0; + objp->max_renewable_life = 0; + objp->allowed_keysalts = NULL; + objp->n_tl_data = 0; + objp->tl_data = NULL; + } + if (vers >= KADM5_API_VERSION_3) { + if (!xdr_krb5_kvno(xdrs, &objp->pw_max_fail)) + return (FALSE); + if (!xdr_krb5_deltat(xdrs, &objp->pw_failcnt_interval)) + return (FALSE); + if (!xdr_krb5_deltat(xdrs, &objp->pw_lockout_duration)) + return (FALSE); + } + if (vers >= KADM5_API_VERSION_4) { + if (!xdr_krb5_flags(xdrs, &objp->attributes)) { + return (FALSE); + } + if (!xdr_krb5_deltat(xdrs, &objp->max_life)) { + return (FALSE); + } + if (!xdr_krb5_deltat(xdrs, &objp->max_renewable_life)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->allowed_keysalts)) { + return (FALSE); + } + if (!xdr_krb5_int16(xdrs, &objp->n_tl_data)) { + return (FALSE); + } + if (!xdr_nulltype(xdrs, (void **) &objp->tl_data, + xdr_krb5_tl_data)) { + return FALSE; + } + } + return (TRUE); +} + +bool_t +xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp) +{ + return _xdr_kadm5_policy_ent_rec(xdrs, objp, KADM5_API_VERSION_4); +} + +bool_t +xdr_cprinc_arg(XDR *xdrs, cprinc_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!_xdr_kadm5_principal_ent_rec(xdrs, &objp->rec, + objp->api_version)) { + return (FALSE); + } + if (!xdr_long(xdrs, &objp->mask)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->passwd)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_cprinc3_arg(XDR *xdrs, cprinc3_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!_xdr_kadm5_principal_ent_rec(xdrs, &objp->rec, + objp->api_version)) { + return (FALSE); + } + if (!xdr_long(xdrs, &objp->mask)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple, + (unsigned int *)&objp->n_ks_tuple, ~0, + sizeof(krb5_key_salt_tuple), + xdr_krb5_key_salt_tuple)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->passwd)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_generic_ret(XDR *xdrs, generic_ret *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_kadm5_ret_t(xdrs, &objp->code)) { + return (FALSE); + } + + return(TRUE); +} + +bool_t +xdr_dprinc_arg(XDR *xdrs, dprinc_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_mprinc_arg(XDR *xdrs, mprinc_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!_xdr_kadm5_principal_ent_rec(xdrs, &objp->rec, + objp->api_version)) { + return (FALSE); + } + if (!xdr_long(xdrs, &objp->mask)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_rprinc_arg(XDR *xdrs, rprinc_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->src)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->dest)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_gprincs_arg(XDR *xdrs, gprincs_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->exp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_gprincs_ret(XDR *xdrs, gprincs_ret *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_kadm5_ret_t(xdrs, &objp->code)) { + return (FALSE); + } + if (objp->code == KADM5_OK) { + if (!xdr_int(xdrs, &objp->count)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *) &objp->princs, + (unsigned int *) &objp->count, ~0, + sizeof(char *), xdr_nullstring)) { + return (FALSE); + } + } + + return (TRUE); +} + +bool_t +xdr_chpass_arg(XDR *xdrs, chpass_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->pass)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_chpass3_arg(XDR *xdrs, chpass3_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + if (!xdr_krb5_boolean(xdrs, &objp->keepold)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple, + (unsigned int*)&objp->n_ks_tuple, ~0, + sizeof(krb5_key_salt_tuple), + xdr_krb5_key_salt_tuple)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->pass)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_setkey_arg(XDR *xdrs, setkey_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *) &objp->keyblocks, + (unsigned int *) &objp->n_keys, ~0, + sizeof(krb5_keyblock), xdr_krb5_keyblock)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_setkey3_arg(XDR *xdrs, setkey3_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + if (!xdr_krb5_boolean(xdrs, &objp->keepold)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *) &objp->ks_tuple, + (unsigned int *) &objp->n_ks_tuple, ~0, + sizeof(krb5_key_salt_tuple), xdr_krb5_key_salt_tuple)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *) &objp->keyblocks, + (unsigned int *) &objp->n_keys, ~0, + sizeof(krb5_keyblock), xdr_krb5_keyblock)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_setkey4_arg(XDR *xdrs, setkey4_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return FALSE; + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return FALSE; + } + if (!xdr_krb5_boolean(xdrs, &objp->keepold)) { + return FALSE; + } + if (!xdr_array(xdrs, (caddr_t *) &objp->key_data, + (unsigned int *) &objp->n_key_data, ~0, + sizeof(kadm5_key_data), xdr_kadm5_key_data)) { + return FALSE; + } + return TRUE; +} + +bool_t +xdr_chrand_arg(XDR *xdrs, chrand_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_chrand3_arg(XDR *xdrs, chrand3_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + if (!xdr_krb5_boolean(xdrs, &objp->keepold)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *)&objp->ks_tuple, + (unsigned int*)&objp->n_ks_tuple, ~0, + sizeof(krb5_key_salt_tuple), + xdr_krb5_key_salt_tuple)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_chrand_ret(XDR *xdrs, chrand_ret *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_kadm5_ret_t(xdrs, &objp->code)) { + return (FALSE); + } + if (objp->code == KADM5_OK) { + if (!xdr_array(xdrs, (char **)&objp->keys, + (unsigned int *)&objp->n_keys, ~0, + sizeof(krb5_keyblock), xdr_krb5_keyblock)) + return FALSE; + } + + return (TRUE); +} + +bool_t +xdr_gprinc_arg(XDR *xdrs, gprinc_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + if (!xdr_long(xdrs, &objp->mask)) { + return FALSE; + } + + return (TRUE); +} + +bool_t +xdr_gprinc_ret(XDR *xdrs, gprinc_ret *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_kadm5_ret_t(xdrs, &objp->code)) { + return (FALSE); + } + if(objp->code == KADM5_OK) { + if (!_xdr_kadm5_principal_ent_rec(xdrs, &objp->rec, + objp->api_version)) { + return (FALSE); + } + } + + return (TRUE); +} + +bool_t +xdr_cpol_arg(XDR *xdrs, cpol_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!_xdr_kadm5_policy_ent_rec(xdrs, &objp->rec, + objp->api_version)) { + return (FALSE); + } + if (!xdr_long(xdrs, &objp->mask)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_dpol_arg(XDR *xdrs, dpol_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->name)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_mpol_arg(XDR *xdrs, mpol_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!_xdr_kadm5_policy_ent_rec(xdrs, &objp->rec, + objp->api_version)) { + return (FALSE); + } + if (!xdr_long(xdrs, &objp->mask)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_gpol_arg(XDR *xdrs, gpol_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->name)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_gpol_ret(XDR *xdrs, gpol_ret *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_kadm5_ret_t(xdrs, &objp->code)) { + return (FALSE); + } + if(objp->code == KADM5_OK) { + if (!_xdr_kadm5_policy_ent_rec(xdrs, &objp->rec, + objp->api_version)) + return (FALSE); + } + + return (TRUE); +} + +bool_t +xdr_gpols_arg(XDR *xdrs, gpols_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->exp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_gpols_ret(XDR *xdrs, gpols_ret *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_kadm5_ret_t(xdrs, &objp->code)) { + return (FALSE); + } + if (objp->code == KADM5_OK) { + if (!xdr_int(xdrs, &objp->count)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *) &objp->pols, + (unsigned int *) &objp->count, ~0, + sizeof(char *), xdr_nullstring)) { + return (FALSE); + } + } + + return (TRUE); +} + +bool_t xdr_getprivs_ret(XDR *xdrs, getprivs_ret *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (! xdr_kadm5_ret_t(xdrs, &objp->code) || + ! xdr_long(xdrs, &objp->privs)) + return FALSE; + + return TRUE; +} + +bool_t +xdr_purgekeys_arg(XDR *xdrs, purgekeys_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + if (!xdr_int(xdrs, &objp->keepkvno)) { + return FALSE; + } + + return (TRUE); +} + +bool_t +xdr_gstrings_arg(XDR *xdrs, gstrings_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + + return (TRUE); +} + +bool_t +xdr_gstrings_ret(XDR *xdrs, gstrings_ret *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_kadm5_ret_t(xdrs, &objp->code)) { + return (FALSE); + } + if (objp->code == KADM5_OK) { + if (!xdr_int(xdrs, &objp->count)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *) &objp->strings, + (unsigned int *) &objp->count, ~0, + sizeof(krb5_string_attr), + xdr_krb5_string_attr)) { + return (FALSE); + } + } + + return (TRUE); +} + +bool_t +xdr_sstring_arg(XDR *xdrs, sstring_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->key)) { + return (FALSE); + } + if (!xdr_nullstring(xdrs, &objp->value)) { + return (FALSE); + } + + return (TRUE); +} + +bool_t +xdr_krb5_principal(XDR *xdrs, krb5_principal *objp) +{ + int ret; + char *p = NULL; + krb5_principal pr = NULL; + static krb5_context context = NULL; + + /* using a static context here is ugly, but should work + ok, and the other solutions are even uglier */ + + if (!context && + kadm5_init_krb5_context(&context)) + return(FALSE); + + switch(xdrs->x_op) { + case XDR_ENCODE: + if (*objp) { + if((ret = krb5_unparse_name(context, *objp, &p)) != 0) + return FALSE; + } + if(!xdr_nullstring(xdrs, &p)) + return FALSE; + if (p) free(p); + break; + case XDR_DECODE: + if(!xdr_nullstring(xdrs, &p)) + return FALSE; + if (p) { + ret = krb5_parse_name(context, p, &pr); + if(ret != 0) + return FALSE; + *objp = pr; + free(p); + } else + *objp = NULL; + break; + case XDR_FREE: + if(*objp != NULL) + krb5_free_principal(context, *objp); + *objp = NULL; + break; + } + return TRUE; +} + +bool_t +xdr_krb5_octet(XDR *xdrs, krb5_octet *objp) +{ + if (!xdr_u_char(xdrs, objp)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_krb5_enctype(XDR *xdrs, krb5_enctype *objp) +{ + if (!xdr_int32(xdrs, (int32_t *) objp)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_krb5_salttype(XDR *xdrs, krb5_int32 *objp) +{ + if (!xdr_int32(xdrs, (int32_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_krb5_keyblock(XDR *xdrs, krb5_keyblock *objp) +{ + char *cp; + + /* XXX This only works because free_keyblock assumes ->contents + is allocated by malloc() */ + if(!xdr_krb5_enctype(xdrs, &objp->enctype)) + return FALSE; + cp = (char *)objp->contents; + if(!xdr_bytes(xdrs, &cp, &objp->length, ~0)) + return FALSE; + objp->contents = (uint8_t *)cp; + return TRUE; +} + +bool_t +xdr_krb5_string_attr(XDR *xdrs, krb5_string_attr *objp) +{ + if (!xdr_nullstring(xdrs, &objp->key)) + return FALSE; + if (!xdr_nullstring(xdrs, &objp->value)) + return FALSE; + if (xdrs->x_op == XDR_DECODE && + (objp->key == NULL || objp->value == NULL)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kadm5_key_data(XDR *xdrs, kadm5_key_data *objp) +{ + if (!xdr_krb5_kvno(xdrs, &objp->kvno)) + return FALSE; + if (!xdr_krb5_keyblock(xdrs, &objp->key)) + return FALSE; + if (!xdr_krb5_int16(xdrs, &objp->salt.type)) + return FALSE; + if (!xdr_bytes(xdrs, &objp->salt.data.data, + &objp->salt.data.length, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_getpkeys_arg(XDR *xdrs, getpkeys_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return FALSE; + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return FALSE; + } + if (!xdr_krb5_kvno(xdrs, &objp->kvno)) { + return FALSE; + } + return TRUE; +} + +bool_t +xdr_getpkeys_ret(XDR *xdrs, getpkeys_ret *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return FALSE; + } + if (!xdr_kadm5_ret_t(xdrs, &objp->code)) { + return FALSE; + } + if (objp->code == KADM5_OK) { + if (!xdr_array(xdrs, (caddr_t *) &objp->key_data, + (unsigned int *) &objp->n_key_data, ~0, + sizeof(kadm5_key_data), xdr_kadm5_key_data)) { + return FALSE; + } + } + return TRUE; +} diff --git a/krb5-1.21.3/src/lib/kadm5/logger.c b/krb5-1.21.3/src/lib/kadm5/logger.c new file mode 100644 index 00000000..e14da537 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/logger.c @@ -0,0 +1,791 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kadm5/logger.c */ +/* + * Copyright 1995, 2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* KADM5 wants non-syslog log files to contain syslog-like entries */ +#define VERBOSE_LOGS + +/* + * logger.c - Handle logging functions for those who want it. + */ +#include "k5-int.h" +#include "adm_proto.h" +#include "com_err.h" +#include +#include +#include +#include + +#define KRB5_KLOG_MAX_ERRMSG_SIZE 2048 +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif /* MAXHOSTNAMELEN */ + +/* This is to assure that we have at least one match in the syslog stuff */ +#ifndef LOG_AUTH +#define LOG_AUTH 0 +#endif /* LOG_AUTH */ +#ifndef LOG_ERR +#define LOG_ERR 0 +#endif /* LOG_ERR */ + +#define lspec_parse_err_1 _("%s: cannot parse <%s>\n") +#define lspec_parse_err_2 _("%s: warning - logging entry syntax error\n") +#define log_file_err _("%s: error writing to %s\n") +#define log_device_err _("%s: error writing to %s device\n") +#define log_ufo_string "?\?\?" /* nb: avoid trigraphs */ +#define log_emerg_string _("EMERGENCY") +#define log_alert_string _("ALERT") +#define log_crit_string _("CRITICAL") +#define log_err_string _("Error") +#define log_warning_string _("Warning") +#define log_notice_string _("Notice") +#define log_info_string _("info") +#define log_debug_string _("debug") + +/* + * Output logging. + * + * Output logging is now controlled by the configuration file. We can specify + * the following syntaxes under the [logging]->entity specification. + * FILE + * SYSLOG[=[:]] + * STDERR + * CONSOLE + * DEVICE= + * + * Where: + * is ":" for open/append, "=" for open/create. + * is a valid path name. + * is one of: (default = ERR) + * EMERG + * ALERT + * CRIT + * ERR + * WARNING + * NOTICE + * INFO + * DEBUG + * is one of: (default = AUTH) + * KERN + * USER + * MAIL + * DAEMON + * AUTH + * LPR + * NEWS + * UUCP + * CRON + * LOCAL0..LOCAL7 + * is a valid device specification. + */ +struct log_entry { + enum log_type { K_LOG_FILE, + K_LOG_SYSLOG, + K_LOG_STDERR, + K_LOG_CONSOLE, + K_LOG_DEVICE, + K_LOG_NONE } log_type; + krb5_pointer log_2free; + union log_union { + struct log_file { + FILE *lf_filep; + char *lf_fname; + } log_file; + struct log_syslog { + int ls_facility; + } log_syslog; + struct log_device { + FILE *ld_filep; + char *ld_devname; + } log_device; + } log_union; +}; +#define lfu_filep log_union.log_file.lf_filep +#define lfu_fname log_union.log_file.lf_fname +#define lsu_facility log_union.log_syslog.ls_facility +#define ldu_filep log_union.log_device.ld_filep +#define ldu_devname log_union.log_device.ld_devname + +struct log_control { + struct log_entry *log_entries; + int log_nentries; + char *log_whoami; + char *log_hostname; + krb5_boolean log_opened; + krb5_boolean log_debug; +}; + +static struct log_control log_control = { + (struct log_entry *) NULL, + 0, + (char *) NULL, + (char *) NULL, + 0 +}; +static struct log_entry def_log_entry; + +/* + * These macros define any special processing that needs to happen for + * devices. For unix, of course, this is hardly anything. + */ +#define DEVICE_OPEN(d, m) fopen(d, m) +#define CONSOLE_OPEN(m) fopen("/dev/console", m) +#define DEVICE_PRINT(f, m) ((fprintf(f, "%s\r\n", m) >= 0) ? \ + (fflush(f), 0) : \ + -1) +#define DEVICE_CLOSE(d) fclose(d) + +/* + * klog_com_err_proc() - Handle com_err(3) messages as specified by the + * profile. + */ +static krb5_context err_context; + +static void +klog_com_err_proc(const char *whoami, long int code, const char *format, va_list ap) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 0))) +#endif + ; + +/* + * Write com_err() messages to the configured logging devices. Ignore whoami, + * as krb5_klog_init() already received a whoami value. If code is nonzero, + * log its error message (retrieved using err_context) and the formatted + * message at error severity. If code is zero, log the formatted message at + * informational severity. + */ +static void +klog_com_err_proc(const char *whoami, long int code, const char *format, va_list ap) +{ + struct k5buf buf; + const char *emsg, *msg; + + if (format == NULL) + return; + + k5_buf_init_dynamic(&buf); + + if (code) { + /* Start with the error message and a separator. */ + emsg = krb5_get_error_message(err_context, code); + k5_buf_add(&buf, emsg); + krb5_free_error_message(err_context, emsg); + k5_buf_add(&buf, " - "); + } + + /* Add the formatted message. */ + k5_buf_add_vfmt(&buf, format, ap); + + msg = k5_buf_cstring(&buf); + if (msg != NULL) + krb5_klog_syslog(code ? LOG_ERR : LOG_INFO, "%s", msg); + + k5_buf_free(&buf); +} + +/* + * krb5_klog_init() - Initialize logging. + * + * This routine parses the syntax described above to specify destinations for + * com_err(3) or krb5_klog_syslog() messages generated by the caller. + * + * Parameters: + * kcontext - Kerberos context. + * ename - Entity name as it is to appear in the profile. + * whoami - Entity name as it is to appear in error output. + * do_com_err - Take over com_err(3) processing. + * + * Implicit inputs: + * stderr - This is where STDERR output goes. + * + * Implicit outputs: + * log_nentries - Number of log entries, both valid and invalid. + * log_control - List of entries (log_nentries long) which contains + * data for klog_com_err_proc() to use to determine + * where/how to send output. + */ +krb5_error_code +krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do_com_err) +{ + const char *logging_profent[3]; + const char *logging_defent[3]; + char **logging_specs; + int i, ngood, fd, append; + char *cp, *cp2; + char savec = '\0'; + int error, debug; + int do_openlog, log_facility; + FILE *f = NULL; + + /* Initialize */ + do_openlog = 0; + log_facility = 0; + + err_context = kcontext; + + /* Look up [logging]->debug in the profile to see if we should include + * debug messages for types other than syslog. Default to false. */ + if (!profile_get_boolean(kcontext->profile, KRB5_CONF_LOGGING, + KRB5_CONF_DEBUG, NULL, 0, &debug)) + log_control.log_debug = debug; + + /* + * Look up [logging]-> in the profile. If that doesn't + * succeed, then look for [logging]->default. + */ + logging_profent[0] = KRB5_CONF_LOGGING; + logging_profent[1] = ename; + logging_profent[2] = (char *) NULL; + logging_defent[0] = KRB5_CONF_LOGGING; + logging_defent[1] = KRB5_CONF_DEFAULT; + logging_defent[2] = (char *) NULL; + logging_specs = (char **) NULL; + ngood = 0; + log_control.log_nentries = 0; + if (!profile_get_values(kcontext->profile, + logging_profent, + &logging_specs) || + !profile_get_values(kcontext->profile, + logging_defent, + &logging_specs)) { + /* + * We have a match, so we first count the number of elements + */ + for (log_control.log_nentries = 0; + logging_specs[log_control.log_nentries]; + log_control.log_nentries++); + + /* + * Now allocate our structure. + */ + log_control.log_entries = (struct log_entry *) + malloc(log_control.log_nentries * sizeof(struct log_entry)); + if (log_control.log_entries) { + /* + * Scan through the list. + */ + for (i=0; i + * so, trim off the leading and trailing whitespace here. + */ + for (cp = logging_specs[i]; isspace((int) *cp); cp++); + for (cp2 = &logging_specs[i][strlen(logging_specs[i])-1]; + isspace((int) *cp2); cp2--); + cp2++; + *cp2 = '\0'; + /* + * Is this a file? + */ + if (!strncasecmp(cp, "FILE", 4)) { + /* + * Check for append/overwrite, then open the file. + */ + append = (cp[4] == ':') ? O_APPEND : 0; + if (append || cp[4] == '=') { + fd = open(&cp[5], O_CREAT | O_WRONLY | append, + S_IRUSR | S_IWUSR | S_IRGRP); + if (fd != -1) + f = fdopen(fd, append ? "a" : "w"); + if (fd == -1 || f == NULL) { + fprintf(stderr,"Couldn't open log file %s: %s\n", + &cp[5], error_message(errno)); + continue; + } + set_cloexec_file(f); + log_control.log_entries[i].lfu_filep = f; + log_control.log_entries[i].log_type = K_LOG_FILE; + log_control.log_entries[i].lfu_fname = &cp[5]; + } + } + /* + * Is this a syslog? + */ + else if (!strncasecmp(cp, "SYSLOG", 6)) { + error = 0; + log_control.log_entries[i].lsu_facility = LOG_AUTH; + /* + * Is there a severify (which is now ignored) specified? + */ + if (cp[6] == ':') { + /* + * Find the end of the severity. + */ + cp2 = strchr(&cp[7], ':'); + if (cp2) { + savec = *cp2; + *cp2 = '\0'; + cp2++; + } + + /* + * If there is a facility present, then parse that. + */ + if (cp2) { + static const struct { + const char *name; + int value; + } facilities[] = { + { "AUTH", LOG_AUTH }, +#ifdef LOG_AUTHPRIV + { "AUTHPRIV", LOG_AUTHPRIV }, +#endif /* LOG_AUTHPRIV */ +#ifdef LOG_KERN + { "KERN", LOG_KERN }, +#endif /* LOG_KERN */ +#ifdef LOG_USER + { "USER", LOG_USER }, +#endif /* LOG_USER */ +#ifdef LOG_MAIL + { "MAIL", LOG_MAIL }, +#endif /* LOG_MAIL */ +#ifdef LOG_DAEMON + { "DAEMON", LOG_DAEMON }, +#endif /* LOG_DAEMON */ +#ifdef LOG_FTP + { "FTP", LOG_FTP }, +#endif /* LOG_FTP */ +#ifdef LOG_LPR + { "LPR", LOG_LPR }, +#endif /* LOG_LPR */ +#ifdef LOG_NEWS + { "NEWS", LOG_NEWS }, +#endif /* LOG_NEWS */ +#ifdef LOG_UUCP + { "UUCP", LOG_UUCP }, +#endif /* LOG_UUCP */ +#ifdef LOG_CRON + { "CRON", LOG_CRON }, +#endif /* LOG_CRON */ +#ifdef LOG_LOCAL0 + { "LOCAL0", LOG_LOCAL0 }, +#endif /* LOG_LOCAL0 */ +#ifdef LOG_LOCAL1 + { "LOCAL1", LOG_LOCAL1 }, +#endif /* LOG_LOCAL1 */ +#ifdef LOG_LOCAL2 + { "LOCAL2", LOG_LOCAL2 }, +#endif /* LOG_LOCAL2 */ +#ifdef LOG_LOCAL3 + { "LOCAL3", LOG_LOCAL3 }, +#endif /* LOG_LOCAL3 */ +#ifdef LOG_LOCAL4 + { "LOCAL4", LOG_LOCAL4 }, +#endif /* LOG_LOCAL4 */ +#ifdef LOG_LOCAL5 + { "LOCAL5", LOG_LOCAL5 }, +#endif /* LOG_LOCAL5 */ +#ifdef LOG_LOCAL6 + { "LOCAL6", LOG_LOCAL6 }, +#endif /* LOG_LOCAL6 */ +#ifdef LOG_LOCAL7 + { "LOCAL7", LOG_LOCAL7 }, +#endif /* LOG_LOCAL7 */ + }; + unsigned int j; + + for (j = 0; j < sizeof(facilities)/sizeof(facilities[0]); j++) + if (!strcasecmp(cp2, facilities[j].name)) { + log_control.log_entries[i].lsu_facility = facilities[j].value; + break; + } + cp2--; + *cp2 = savec; + } + } + if (!error) { + log_control.log_entries[i].log_type = K_LOG_SYSLOG; + do_openlog = 1; + log_facility = log_control.log_entries[i].lsu_facility; + } + } + /* + * Is this a standard error specification? + */ + else if (!strcasecmp(cp, "STDERR")) { + log_control.log_entries[i].lfu_filep = + fdopen(fileno(stderr), "w"); + if (log_control.log_entries[i].lfu_filep) { + log_control.log_entries[i].log_type = K_LOG_STDERR; + log_control.log_entries[i].lfu_fname = + "standard error"; + } + } + /* + * Is this a specification of the console? + */ + else if (!strcasecmp(cp, "CONSOLE")) { + log_control.log_entries[i].ldu_filep = + CONSOLE_OPEN("a+"); + if (log_control.log_entries[i].ldu_filep) { + set_cloexec_file(log_control.log_entries[i].ldu_filep); + log_control.log_entries[i].log_type = K_LOG_CONSOLE; + log_control.log_entries[i].ldu_devname = "console"; + } + } + /* + * Is this a specification of a device? + */ + else if (!strncasecmp(cp, "DEVICE", 6)) { + /* + * We handle devices very similarly to files. + */ + if (cp[6] == '=') { + log_control.log_entries[i].ldu_filep = + DEVICE_OPEN(&cp[7], "w"); + if (log_control.log_entries[i].ldu_filep) { + set_cloexec_file(log_control.log_entries[i].ldu_filep); + log_control.log_entries[i].log_type = K_LOG_DEVICE; + log_control.log_entries[i].ldu_devname = &cp[7]; + } + } + } + /* + * See if we successfully parsed this specification. + */ + if (log_control.log_entries[i].log_type == K_LOG_NONE) { + fprintf(stderr, lspec_parse_err_1, whoami, cp); + fprintf(stderr, lspec_parse_err_2, whoami); + } + else + ngood++; + } + } + /* + * If we didn't find anything, then free our lists. + */ + if (ngood == 0) { + for (i=0; ilog_type = K_LOG_SYSLOG; + log_control.log_entries->log_2free = (krb5_pointer) NULL; + log_facility = log_control.log_entries->lsu_facility = LOG_AUTH; + do_openlog = 1; + log_control.log_nentries = 1; + } + if (log_control.log_nentries) { + log_control.log_whoami = strdup(whoami); + log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN + 1); + if (log_control.log_hostname) { + if (gethostname(log_control.log_hostname, MAXHOSTNAMELEN) == -1) { + free(log_control.log_hostname); + log_control.log_hostname = NULL; + } else + log_control.log_hostname[MAXHOSTNAMELEN] = '\0'; + } + if (do_openlog) { + openlog(whoami, LOG_NDELAY|LOG_PID, log_facility); + log_control.log_opened = 1; + } + if (do_com_err) + (void) set_com_err_hook(klog_com_err_proc); + } + return((log_control.log_nentries) ? 0 : ENOENT); +} + +/* Reset the context used by the com_err hook to retrieve error messages. */ +void +krb5_klog_set_context(krb5_context kcontext) +{ + err_context = kcontext; +} + +/* + * krb5_klog_close() - Close the logging context and free all data. + */ +void +krb5_klog_close(krb5_context kcontext) +{ + int lindex; + (void) reset_com_err_hook(); + for (lindex = 0; lindex < log_control.log_nentries; lindex++) { + switch (log_control.log_entries[lindex].log_type) { + case K_LOG_FILE: + case K_LOG_STDERR: + /* + * Files/standard error. + */ + fclose(log_control.log_entries[lindex].lfu_filep); + break; + case K_LOG_CONSOLE: + case K_LOG_DEVICE: + /* + * Devices (may need special handling) + */ + DEVICE_CLOSE(log_control.log_entries[lindex].ldu_filep); + break; + case K_LOG_SYSLOG: + /* + * System log. + */ + break; + default: + break; + } + if (log_control.log_entries[lindex].log_2free) + free(log_control.log_entries[lindex].log_2free); + } + if (log_control.log_entries != &def_log_entry) + free(log_control.log_entries); + log_control.log_entries = (struct log_entry *) NULL; + log_control.log_nentries = 0; + if (log_control.log_whoami) + free(log_control.log_whoami); + log_control.log_whoami = (char *) NULL; + if (log_control.log_hostname) + free(log_control.log_hostname); + log_control.log_hostname = (char *) NULL; + if (log_control.log_opened) + closelog(); +} + +/* + * severity2string() - Convert a severity to a string. + */ +static const char * +severity2string(int severity) +{ + int s; + const char *ss; + + s = severity & LOG_PRIMASK; + ss = log_ufo_string; + switch (s) { + case LOG_EMERG: + ss = log_emerg_string; + break; + case LOG_ALERT: + ss = log_alert_string; + break; + case LOG_CRIT: + ss = log_crit_string; + break; + case LOG_ERR: + ss = log_err_string; + break; + case LOG_WARNING: + ss = log_warning_string; + break; + case LOG_NOTICE: + ss = log_notice_string; + break; + case LOG_INFO: + ss = log_info_string; + break; + case LOG_DEBUG: + ss = log_debug_string; + break; + } + return(ss); +} + +/* + * krb5_klog_syslog() - Simulate the calling sequence of syslog(3), while + * also performing the logging redirection as specified + * by krb5_klog_init(). + */ +static int +klog_vsyslog(int priority, const char *format, va_list arglist) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 2, 0))) +#endif + ; + +static int +klog_vsyslog(int priority, const char *format, va_list arglist) +{ + char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE]; + int lindex; + char *syslogp; + char *cp; + time_t now; + size_t soff; + struct tm *tm; + + /* + * Format a syslog-esque message of the format: + * + * (verbose form) + * [](): + * + * (short form) + * + */ + cp = outbuf; + (void) time(&now); + + /* + * Format the date: mon dd hh:mm:ss + */ + tm = localtime(&now); + if (tm == NULL) + return(-1); + soff = strftime(outbuf, sizeof(outbuf), "%b %d %H:%M:%S", tm); + if (soff > 0) + cp += soff; + else + return(-1); + +#ifdef VERBOSE_LOGS + snprintf(cp, sizeof(outbuf) - (cp-outbuf), " %s %s[%ld](%s): ", + log_control.log_hostname ? log_control.log_hostname : "", + log_control.log_whoami ? log_control.log_whoami : "", + (long) getpid(), + severity2string(priority)); +#else + snprintf(cp, sizeof(outbuf) - (cp-outbuf), " "); +#endif + syslogp = &outbuf[strlen(outbuf)]; + + /* Now format the actual message */ + vsnprintf(syslogp, sizeof(outbuf) - (syslogp - outbuf), format, arglist); + + /* + * If the user did not use krb5_klog_init() instead of dropping + * the request on the floor, syslog it - if it exists + */ + if (log_control.log_nentries == 0) { + /* Log the message with our header trimmed off */ + syslog(priority, "%s", syslogp); + } + + /* + * Now that we have the message formatted, perform the output to each + * logging specification. + */ + for (lindex = 0; lindex < log_control.log_nentries; lindex++) { + /* Omit LOG_DEBUG messages for non-syslog outputs unless we are + * configured to include them. */ + if (priority == LOG_DEBUG && !log_control.log_debug && + log_control.log_entries[lindex].log_type != K_LOG_SYSLOG) + continue; + + switch (log_control.log_entries[lindex].log_type) { + case K_LOG_FILE: + case K_LOG_STDERR: + /* + * Files/standard error. + */ + if (fprintf(log_control.log_entries[lindex].lfu_filep, "%s\n", + outbuf) < 0) { + /* Attempt to report error */ + fprintf(stderr, log_file_err, log_control.log_whoami, + log_control.log_entries[lindex].lfu_fname); + } + else { + fflush(log_control.log_entries[lindex].lfu_filep); + } + break; + case K_LOG_CONSOLE: + case K_LOG_DEVICE: + /* + * Devices (may need special handling) + */ + if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep, + outbuf) < 0) { + /* Attempt to report error */ + fprintf(stderr, log_device_err, log_control.log_whoami, + log_control.log_entries[lindex].ldu_devname); + } + break; + case K_LOG_SYSLOG: + /* + * System log. + */ + + /* Log the message with our header trimmed off */ + syslog(priority, "%s", syslogp); + break; + default: + break; + } + } + return(0); +} + +int +krb5_klog_syslog(int priority, const char *format, ...) +{ + int retval; + va_list pvar; + + va_start(pvar, format); + retval = klog_vsyslog(priority, format, pvar); + va_end(pvar); + return(retval); +} + +/* + * krb5_klog_reopen() - Close and reopen any open (non-syslog) log files. + * This function is called when a SIGHUP is received + * so that external log-archival utilities may + * alert the Kerberos daemons that they should get + * a new file descriptor for the give filename. + */ +void +krb5_klog_reopen(krb5_context kcontext) +{ + int lindex; + FILE *f; + + /* + * Only logs which are actually files need to be closed + * and reopened in response to a SIGHUP + */ + for (lindex = 0; lindex < log_control.log_nentries; lindex++) { + if (log_control.log_entries[lindex].log_type == K_LOG_FILE) { + fclose(log_control.log_entries[lindex].lfu_filep); + /* + * In case the old logfile did not get moved out of the + * way, open for append to prevent squashing the old logs. + */ + f = fopen(log_control.log_entries[lindex].lfu_fname, "a+"); + if (f) { + set_cloexec_file(f); + log_control.log_entries[lindex].lfu_filep = f; + } else { + fprintf(stderr, _("Couldn't open log file %s: %s\n"), + log_control.log_entries[lindex].lfu_fname, + error_message(errno)); + } + } + } +} diff --git a/krb5-1.21.3/src/lib/kadm5/misc_free.c b/krb5-1.21.3/src/lib/kadm5/misc_free.c new file mode 100644 index 00000000..74d23760 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/misc_free.c @@ -0,0 +1,139 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + */ + +#include "k5-int.h" +#include +#include +#include "server_internal.h" + +kadm5_ret_t +kadm5_free_policy_ent(void *server_handle, kadm5_policy_ent_t val) +{ + krb5_tl_data *tl_next; + + _KADM5_CHECK_HANDLE(server_handle); + + if (val == NULL) + return KADM5_OK; + + free(val->policy); + free(val->allowed_keysalts); + for (; val->tl_data; val->tl_data = tl_next) { + tl_next = val->tl_data->tl_data_next; + free(val->tl_data->tl_data_contents); + free(val->tl_data); + } + memset(val, 0, sizeof(*val)); + return KADM5_OK; +} + +kadm5_ret_t +kadm5_free_name_list(void *server_handle, char **names, int count) +{ + _KADM5_CHECK_HANDLE(server_handle); + + while (count--) + free(names[count]); + free(names); + return KADM5_OK; +} + +/* XXX this ought to be in libkrb5.a, but isn't */ +kadm5_ret_t krb5_free_key_data_contents(context, key) + krb5_context context; + krb5_key_data *key; +{ + int i, idx; + + idx = (key->key_data_ver == 1 ? 1 : 2); + for (i = 0; i < idx; i++) + zapfree(key->key_data_contents[i], key->key_data_length[i]); + return KADM5_OK; +} + +kadm5_ret_t kadm5_free_key_data(void *server_handle, + krb5_int16 *n_key_data, + krb5_key_data *key_data) +{ + kadm5_server_handle_t handle = server_handle; + int i, nkeys = (int) *n_key_data; + + _KADM5_CHECK_HANDLE(server_handle); + + if (key_data == NULL) + return KADM5_OK; + + for (i = 0; i < nkeys; i++) + krb5_free_key_data_contents(handle->context, &key_data[i]); + free(key_data); + return KADM5_OK; +} + +kadm5_ret_t +kadm5_free_principal_ent(void *server_handle, kadm5_principal_ent_t val) +{ + kadm5_server_handle_t handle = server_handle; + krb5_tl_data *tl; + int i; + + _KADM5_CHECK_HANDLE(server_handle); + + if (!val) + return KADM5_OK; + + krb5_free_principal(handle->context, val->principal); + krb5_free_principal(handle->context, val->mod_name); + free(val->policy); + if (val->n_key_data) { + for (i = 0; i < val->n_key_data; i++) + krb5_free_key_data_contents(handle->context, &val->key_data[i]); + free(val->key_data); + } + + while (val->tl_data) { + tl = val->tl_data->tl_data_next; + free(val->tl_data->tl_data_contents); + free(val->tl_data); + val->tl_data = tl; + } + return KADM5_OK; +} + +kadm5_ret_t +kadm5_free_strings(void *server_handle, krb5_string_attr *strings, + int count) +{ + int i; + + _KADM5_CHECK_HANDLE(server_handle); + + if (!strings) + return KADM5_OK; + + for (i = 0; i < count; i++) { + free(strings[i].key); + free(strings[i].value); + } + free(strings); + return KADM5_OK; +} + +kadm5_ret_t +kadm5_free_kadm5_key_data(krb5_context context, int n_key_data, + kadm5_key_data *key_data) +{ + int i; + + if (key_data == NULL) + return KADM5_OK; + + for (i = 0; i < n_key_data; i++) { + krb5_free_keyblock_contents(context, &key_data[i].key); + krb5_free_data_contents(context, &key_data[i].salt.data); + } + free(key_data); + + return KADM5_OK; +} diff --git a/krb5-1.21.3/src/lib/kadm5/server_internal.h b/krb5-1.21.3/src/lib/kadm5/server_internal.h new file mode 100644 index 00000000..433f4915 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/server_internal.h @@ -0,0 +1,269 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ + +/* + * This header file is used internally by the Admin API server + * libraries and Admin server. IF YOU THINK YOU NEED TO USE THIS FILE + * FOR ANYTHING, YOU'RE ALMOST CERTAINLY WRONG. + */ + +#ifndef __KADM5_SERVER_INTERNAL_H__ +#define __KADM5_SERVER_INTERNAL_H__ + +#include "autoconf.h" +#ifdef HAVE_MEMORY_H +#include +#endif +#include +#include +#include +#include +#include +#include "admin_internal.h" + +/* + * This is the history key version for a newly created DB. We use this value + * for principals which have no password history yet to avoid having to look up + * the history key. Values other than 2 will cause compatibility issues with + * pre-1.8 libkadm5 code; the older code will reject key changes when it sees + * an unexpected value of admin_history_kvno. + */ +#define INITIAL_HIST_KVNO 2 + +/* A pwqual_handle represents a password quality plugin module. */ +typedef struct pwqual_handle_st *pwqual_handle; + +typedef struct kadm5_hook_handle_st *kadm5_hook_handle; + +typedef struct _kadm5_server_handle_t { + krb5_ui_4 magic_number; + krb5_ui_4 struct_version; + krb5_ui_4 api_version; + krb5_context context; + krb5_principal current_caller; + kadm5_config_params params; + struct _kadm5_server_handle_t *lhandle; + char **db_args; + pwqual_handle *qual_handles; + kadm5_hook_handle *hook_handles; +} kadm5_server_handle_rec, *kadm5_server_handle_t; + +#define OSA_ADB_PRINC_VERSION_1 0x12345C01 + +typedef struct _osa_pw_hist_t { + int n_key_data; + krb5_key_data *key_data; +} osa_pw_hist_ent, *osa_pw_hist_t; + +typedef struct _osa_princ_ent_t { + int version; + char *policy; + long aux_attributes; + unsigned int old_key_len; + unsigned int old_key_next; + krb5_kvno admin_history_kvno; + osa_pw_hist_ent *old_keys; +} osa_princ_ent_rec, *osa_princ_ent_t; + + +kadm5_ret_t passwd_check(kadm5_server_handle_t handle, + const char *pass, kadm5_policy_ent_t policy, + krb5_principal principal); +kadm5_ret_t principal_exists(krb5_principal principal); +krb5_error_code kdb_init_master(kadm5_server_handle_t handle, + char *r, int from_keyboard); +krb5_error_code kdb_get_active_mkey(kadm5_server_handle_t handle, + krb5_kvno *act_kvno_out, + krb5_keyblock **act_mkey_out); +krb5_error_code kdb_init_hist(kadm5_server_handle_t handle, + char *r); +krb5_error_code kdb_get_hist_key(kadm5_server_handle_t handle, + krb5_keyblock **keyblocks_out, + krb5_kvno *kvno_out); +void kdb_free_keyblocks(kadm5_server_handle_t handle, + krb5_keyblock *keyblocks); +krb5_error_code kdb_get_entry(kadm5_server_handle_t handle, + krb5_principal principal, + krb5_db_entry **kdb, osa_princ_ent_rec *adb); +krb5_error_code kdb_free_entry(kadm5_server_handle_t handle, + krb5_db_entry *kdb, osa_princ_ent_rec *adb); +krb5_error_code kdb_put_entry(kadm5_server_handle_t handle, + krb5_db_entry *kdb, osa_princ_ent_rec *adb); +krb5_error_code kdb_delete_entry(kadm5_server_handle_t handle, + krb5_principal name); +krb5_error_code kdb_iter_entry(kadm5_server_handle_t handle, + char *match_entry, + void (*iter_fct)(void *, krb5_principal), + void *data); + +kadm5_ret_t init_pwqual(kadm5_server_handle_t handle); +void destroy_pwqual(kadm5_server_handle_t handle); + +/* XXX this ought to be in libkrb5.a, but isn't */ +kadm5_ret_t krb5_copy_key_data_contents(krb5_context context, + krb5_key_data *from, + krb5_key_data *to); +kadm5_ret_t krb5_free_key_data_contents(krb5_context context, + krb5_key_data *key); + +/* + * *Warning* + * *Warning* This is going to break if we + * *Warning* ever go multi-threaded + * *Warning* + */ +extern krb5_principal current_caller; + +/* + * Why is this (or something similar) not defined *anywhere* in krb5? + */ +#define KSUCCESS 0 +#define WORD_NOT_FOUND 1 + +/* + * all the various mask bits or'd together + */ + +#define ALL_PRINC_MASK \ + (KADM5_PRINCIPAL | KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION | \ + KADM5_LAST_PWD_CHANGE | KADM5_ATTRIBUTES | KADM5_MAX_LIFE | \ + KADM5_MOD_TIME | KADM5_MOD_NAME | KADM5_KVNO | KADM5_MKVNO | \ + KADM5_AUX_ATTRIBUTES | KADM5_POLICY_CLR | KADM5_POLICY | \ + KADM5_MAX_RLIFE | KADM5_TL_DATA | KADM5_KEY_DATA | KADM5_FAIL_AUTH_COUNT ) + +#define ALL_POLICY_MASK \ + (KADM5_POLICY | KADM5_PW_MAX_LIFE | KADM5_PW_MIN_LIFE | \ + KADM5_PW_MIN_LENGTH | KADM5_PW_MIN_CLASSES | KADM5_PW_HISTORY_NUM | \ + KADM5_REF_COUNT | KADM5_PW_MAX_FAILURE | KADM5_PW_FAILURE_COUNT_INTERVAL | \ + KADM5_PW_LOCKOUT_DURATION | KADM5_POLICY_ATTRIBUTES | \ + KADM5_POLICY_MAX_LIFE | KADM5_POLICY_MAX_RLIFE | \ + KADM5_POLICY_ALLOWED_KEYSALTS | KADM5_POLICY_TL_DATA) + +#define SERVER_CHECK_HANDLE(handle) \ + { \ + kadm5_server_handle_t srvr = \ + (kadm5_server_handle_t) handle; \ + \ + if (! srvr->current_caller) \ + return KADM5_BAD_SERVER_HANDLE; \ + if (! srvr->lhandle) \ + return KADM5_BAD_SERVER_HANDLE; \ + } + +#define CHECK_HANDLE(handle) \ + GENERIC_CHECK_HANDLE(handle, KADM5_OLD_SERVER_API_VERSION, \ + KADM5_NEW_SERVER_API_VERSION) \ + SERVER_CHECK_HANDLE(handle) + +bool_t xdr_osa_princ_ent_rec(XDR *xdrs, osa_princ_ent_t objp); + +void +osa_free_princ_ent(osa_princ_ent_t val); + +/*** Password quality plugin consumer interface ***/ + +/* Load all available password quality plugin modules, bind each module to the + * realm's dictionary file, and store the result into *handles_out. Free the + * result with k5_pwqual_free_handles. */ +krb5_error_code +k5_pwqual_load(krb5_context context, const char *dict_file, + pwqual_handle **handles_out); + +/* Release a handle list allocated by k5_pwqual_load. */ +void +k5_pwqual_free_handles(krb5_context context, pwqual_handle *handles); + +/* Return the name of a password quality plugin module. */ +const char * +k5_pwqual_name(krb5_context context, pwqual_handle handle); + +/* Check a password using a password quality plugin module. */ +krb5_error_code +k5_pwqual_check(krb5_context context, pwqual_handle handle, + const char *password, const char *policy_name, + krb5_principal princ); + +/*** initvt functions for built-in password quality modules ***/ + +/* The dict module checks passwords against the realm's dictionary. */ +krb5_error_code +pwqual_dict_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +/* The empty module rejects empty passwords (even with no password policy). */ +krb5_error_code +pwqual_empty_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +/* The hesiod module checks passwords against GECOS fields from Hesiod passwd + * information (only if the tree was built with Hesiod support). */ +krb5_error_code +pwqual_hesiod_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +/* The princ module checks passwords against principal components. */ +krb5_error_code +pwqual_princ_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +/** @{ + * @name kadm5_hook plugin support + */ + +/** Load all kadm5_hook plugins. */ +krb5_error_code +k5_kadm5_hook_load(krb5_context context, + kadm5_hook_handle **handles_out); + +/** Free handles allocated by k5_kadm5_hook_load(). */ +void +k5_kadm5_hook_free_handles(krb5_context context, kadm5_hook_handle *handles); + +/** Call the chpass entry point on every kadm5_hook in @a handles. */ +kadm5_ret_t +k5_kadm5_hook_chpass (krb5_context context, + kadm5_hook_handle *handles, + int stage, krb5_principal princ, + krb5_boolean keepold, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + const char *newpass); + +/** Call the create entry point for kadm5_hook_plugins. */ +kadm5_ret_t +k5_kadm5_hook_create (krb5_context context, + kadm5_hook_handle *handles, + int stage, + kadm5_principal_ent_t princ, long mask, + int n_ks_tuple, + krb5_key_salt_tuple *ks_tuple, + const char *newpass); + +/** Call modify kadm5_hook entry point. */ +kadm5_ret_t +k5_kadm5_hook_modify (krb5_context context, + kadm5_hook_handle *handles, + int stage, + kadm5_principal_ent_t princ, long mask); + +/** Call remove kadm5_hook entry point. */ +kadm5_ret_t +k5_kadm5_hook_remove (krb5_context context, + kadm5_hook_handle *handles, + int stage, + krb5_principal princ); + +/** Call rename kadm5_hook entry point. */ +kadm5_ret_t +k5_kadm5_hook_rename (krb5_context context, + kadm5_hook_handle *handles, + int stage, + krb5_principal oprinc, krb5_principal nprinc); + +/** @}*/ + +#endif /* __KADM5_SERVER_INTERNAL_H__ */ diff --git a/krb5-1.21.3/src/lib/kadm5/srv/Makefile.in b/krb5-1.21.3/src/lib/kadm5/srv/Makefile.in new file mode 100644 index 00000000..d218ea48 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/Makefile.in @@ -0,0 +1,93 @@ +mydir=lib$(S)kadm5$(S)srv +BUILDTOP=$(REL)..$(S)..$(S).. +LOCALINCLUDES = -I$(BUILDTOP)/include/kadm5 \ + -I$(top_srcdir)/lib/gssapi/krb5 -I$(top_srcdir)/lib/gssapi/generic \ + -I$(BUILDTOP)/lib/gssapi/krb5 -I$(BUILDTOP)/lib/gssapi/generic +DEFINES = @HESIOD_DEFS@ + +##DOSBUILDTOP = ..\..\.. +##DOSLIBNAME = libkadm5srv.lib + +LIBBASE=kadm5srv_mit +LIBMAJOR=12 +LIBMINOR=0 +STOBJLISTS=../OBJS.ST OBJS.ST + +SHLIB_EXPDEPS=\ + $(TOPLIBD)/libgssrpc$(SHLIBEXT) \ + $(TOPLIBD)/libgssapi_krb5$(SHLIBEXT) \ + $(TOPLIBD)/libkdb5$(SHLIBEXT) \ + $(TOPLIBD)/libkrb5$(SHLIBEXT) \ + $(TOPLIBD)/libk5crypto$(SHLIBEXT) \ + $(COM_ERR_DEPLIB) $(SUPPORT_LIBDEP) +SHLIB_EXPLIBS = -lgssrpc -lgssapi_krb5 -lkdb5 $(KDB5_DB_LIB) -lkrb5 \ + -lk5crypto $(SUPPORT_LIB) $(COM_ERR_LIB) @GEN_LIB@ $(LIBS) +RELDIR=kadm5/srv + +SRCS = $(srcdir)/pwqual.c \ + $(srcdir)/kadm5_hook.c \ + $(srcdir)/pwqual_dict.c \ + $(srcdir)/pwqual_empty.c \ + $(srcdir)/pwqual_hesiod.c \ + $(srcdir)/pwqual_princ.c \ + $(srcdir)/svr_policy.c \ + $(srcdir)/svr_principal.c \ + $(srcdir)/server_kdb.c \ + $(srcdir)/server_misc.c \ + $(srcdir)/server_init.c \ + $(srcdir)/svr_iters.c \ + $(srcdir)/svr_chpass_util.c \ + $(srcdir)/adb_xdr.c + +OBJS = pwqual.$(OBJEXT) \ + pwqual_dict.$(OBJEXT) \ + pwqual_empty.$(OBJEXT) \ + pwqual_hesiod.$(OBJEXT) \ + pwqual_princ.$(OBJEXT) \ + kadm5_hook.$(OBJEXT) \ + svr_policy.$(OBJEXT) \ + svr_principal.$(OBJEXT) \ + server_kdb.$(OBJEXT) \ + server_misc.$(OBJEXT) \ + server_init.$(OBJEXT) \ + svr_iters.$(OBJEXT) \ + svr_chpass_util.$(OBJEXT) \ + adb_xdr.$(OBJEXT) + +STLIBOBJS = \ + pwqual.o \ + pwqual_dict.o \ + pwqual_empty.o \ + pwqual_hesiod.o \ + pwqual_princ.o \ + kadm5_hook.o \ + svr_policy.o \ + svr_principal.o \ + server_kdb.o \ + server_misc.o \ + server_init.o \ + svr_iters.o \ + svr_chpass_util.o \ + adb_xdr.o + +all-unix: all-liblinks +all-windows: $(OBJS) + +generate-files-mac: darwin.exports + +check-windows: + +clean-windows:: + +clean-unix:: clean-liblinks clean-libs clean-libobjs + +install: install-libs + +install-unix: + $(RM) $(DESTDIR)$(KRB5_LIBDIR)/libkadm5srv$(DEPLIBEXT) + (cd $(DESTDIR)$(KRB5_LIBDIR) && $(LN_S) lib$(LIBBASE)$(DEPLIBEXT) \ + libkadm5srv$(DEPLIBEXT)) + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/kadm5/srv/adb_xdr.c b/krb5-1.21.3/src/lib/kadm5/srv/adb_xdr.c new file mode 100644 index 00000000..fc732971 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/adb_xdr.c @@ -0,0 +1,106 @@ +/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ + +#include +#include +#include +#include "server_internal.h" +#include "admin_xdr.h" +#ifdef HAVE_MEMORY_H +#include +#endif + +bool_t +xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp) +{ + unsigned int tmp; + + if (!xdr_krb5_int16(xdrs, &objp->key_data_ver)) + return(FALSE); + if (!xdr_krb5_ui_2(xdrs, &objp->key_data_kvno)) + return(FALSE); + if (!xdr_krb5_int16(xdrs, &objp->key_data_type[0])) + return(FALSE); + if (!xdr_krb5_int16(xdrs, &objp->key_data_type[1])) + return(FALSE); + if (!xdr_krb5_ui_2(xdrs, &objp->key_data_length[0])) + return(FALSE); + if (!xdr_krb5_ui_2(xdrs, &objp->key_data_length[1])) + return(FALSE); + + tmp = (unsigned int) objp->key_data_length[0]; + if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[0], + &tmp, ~0)) + return FALSE; + + tmp = (unsigned int) objp->key_data_length[1]; + if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[1], + &tmp, ~0)) + return FALSE; + + /* don't need to copy tmp out, since key_data_length will be set + by the above encoding. */ + + return(TRUE); +} + +bool_t +xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp) +{ + if (!xdr_array(xdrs, (caddr_t *) &objp->key_data, + (u_int *) &objp->n_key_data, ~0, + sizeof(krb5_key_data), + xdr_krb5_key_data)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_osa_princ_ent_rec(XDR *xdrs, osa_princ_ent_t objp) +{ + switch (xdrs->x_op) { + case XDR_ENCODE: + objp->version = OSA_ADB_PRINC_VERSION_1; + /* fall through */ + case XDR_FREE: + if (!xdr_int(xdrs, &objp->version)) + return FALSE; + break; + case XDR_DECODE: + if (!xdr_int(xdrs, &objp->version)) + return FALSE; + if (objp->version != OSA_ADB_PRINC_VERSION_1) + return FALSE; + break; + } + + if (!xdr_nullstring(xdrs, &objp->policy)) + return (FALSE); + if (!xdr_long(xdrs, &objp->aux_attributes)) + return (FALSE); + if (!xdr_u_int(xdrs, &objp->old_key_next)) + return (FALSE); + if (!xdr_krb5_kvno(xdrs, &objp->admin_history_kvno)) + return (FALSE); + if (!xdr_array(xdrs, (caddr_t *) &objp->old_keys, + (unsigned int *) &objp->old_key_len, ~0, + sizeof(osa_pw_hist_ent), + xdr_osa_pw_hist_ent)) + return (FALSE); + return (TRUE); +} + +void +osa_free_princ_ent(osa_princ_ent_t val) +{ + XDR xdrs; + + xdrmem_create(&xdrs, NULL, 0, XDR_FREE); + + xdr_osa_princ_ent_rec(&xdrs, val); + free(val); +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/deps b/krb5-1.21.3/src/lib/kadm5/srv/deps new file mode 100644 index 00000000..01080d56 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/deps @@ -0,0 +1,258 @@ +# +# Generated makefile dependencies follow. +# +pwqual.so pwqual.po $(OUTPRE)pwqual.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/krb5/pwqual_plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h pwqual.c +kadm5_hook.so kadm5_hook.po $(OUTPRE)kadm5_hook.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kadm5_hook_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kadm5_hook.c +pwqual_dict.so pwqual_dict.po $(OUTPRE)pwqual_dict.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/krb5/pwqual_plugin.h \ + pwqual_dict.c +pwqual_empty.so pwqual_empty.po $(OUTPRE)pwqual_empty.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/krb5/pwqual_plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h pwqual_empty.c +pwqual_hesiod.so pwqual_hesiod.po $(OUTPRE)pwqual_hesiod.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/krb5/pwqual_plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h pwqual_hesiod.c +pwqual_princ.so pwqual_princ.po $(OUTPRE)pwqual_princ.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/krb5/pwqual_plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h pwqual_princ.c +svr_policy.so svr_policy.po $(OUTPRE)svr_policy.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/plugin.h \ + svr_policy.c +svr_principal.so svr_principal.po $(OUTPRE)svr_principal.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kadm5_hook_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h svr_principal.c +server_kdb.so server_kdb.po $(OUTPRE)server_kdb.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + server_kdb.c +server_misc.so server_misc.po $(OUTPRE)server_misc.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h server_misc.c +server_init.so server_init.po $(OUTPRE)server_init.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(BUILDTOP)/lib/gssapi/generic/gssapi_err_generic.h \ + $(BUILDTOP)/lib/gssapi/krb5/gssapi_err_krb5.h $(COM_ERR_DEPS) \ + $(srcdir)/../../gssapi/generic/gssapiP_generic.h $(srcdir)/../../gssapi/generic/gssapi_ext.h \ + $(srcdir)/../../gssapi/generic/gssapi_generic.h $(srcdir)/../../gssapi/krb5/gssapiP_krb5.h \ + $(srcdir)/../../gssapi/krb5/gssapi_krb5.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h server_init.c +svr_iters.so svr_iters.po $(OUTPRE)svr_iters.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/plugin.h \ + svr_iters.c +svr_chpass_util.so svr_chpass_util.po $(OUTPRE)svr_chpass_util.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/plugin.h \ + svr_chpass_util.c +adb_xdr.so adb_xdr.po $(OUTPRE)adb_xdr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/admin_xdr.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/kadm_rpc.h \ + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/plugin.h \ + adb_xdr.c diff --git a/krb5-1.21.3/src/lib/kadm5/srv/kadm5_hook.c b/krb5-1.21.3/src/lib/kadm5/srv/kadm5_hook.c new file mode 100644 index 00000000..df337bc3 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/kadm5_hook.c @@ -0,0 +1,186 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kadm5/srv/kadm5_hook.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* Consumer interface for kadm5_hook plugins. */ + +#include "k5-int.h" +#include "server_internal.h" +#include +#include +#include + +struct kadm5_hook_handle_st { + kadm5_hook_vftable_1 vt; + kadm5_hook_modinfo *data; +}; + +krb5_error_code +k5_kadm5_hook_load(krb5_context context, + kadm5_hook_handle **handles_out) +{ + krb5_error_code ret; + krb5_plugin_initvt_fn *modules = NULL, *mod; + size_t count; + kadm5_hook_handle *list = NULL, handle = NULL; + + *handles_out = NULL; + + ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_KADM5_HOOK, &modules); + if (ret != 0) + goto cleanup; + + /* Allocate a large enough list of handles. */ + for (count = 0; modules[count] != NULL; count++); + list = k5calloc(count + 1, sizeof(*list), &ret); + if (list == NULL) + goto cleanup; + + /* For each module, allocate a handle, initialize its vtable, and + * initialize the module. */ + count = 0; + for (mod = modules; *mod != NULL; mod++) { + handle = k5alloc(sizeof(*handle), &ret); + if (handle == NULL) + goto cleanup; + ret = (*mod)(context, 1, 2, (krb5_plugin_vtable)&handle->vt); + if (ret != 0) { /* Failed vtable init is non-fatal. */ + free(handle); + handle = NULL; + continue; + } + handle->data = NULL; + if (handle->vt.init != NULL) { + ret = handle->vt.init(context, &handle->data); + if (ret != 0) /* Failed initialization is fatal. */ + goto cleanup; + } + list[count++] = handle; + list[count] = NULL; + handle = NULL; + } + list[count] = NULL; + + ret = 0; + *handles_out = list; + list = NULL; + +cleanup: + free(handle); + k5_plugin_free_modules(context, modules); + k5_kadm5_hook_free_handles(context, list); + return ret; +} + +void +k5_kadm5_hook_free_handles(krb5_context context, kadm5_hook_handle *handles) +{ + kadm5_hook_handle *hp, handle; + + if (handles == NULL) + return; + for (hp = handles; *hp != NULL; hp++) { + handle = *hp; + if (handle->vt.fini != NULL) + handle->vt.fini(context, handle->data); + free(handle); + } + free(handles); +} + +static void +log_failure(krb5_context context, + const char *name, + const char *function, + krb5_error_code ret) +{ + const char *e = krb5_get_error_message(context, ret); + + krb5_klog_syslog(LOG_ERR, _("kadm5_hook %s failed postcommit %s: %s"), + name, function, e); + krb5_free_error_message(context, e); +} + +#define ITERATE(operation, params) \ + for (; *handles; handles++) { \ + kadm5_hook_handle h = *handles; \ + krb5_error_code ret = 0; \ + if (h->vt.operation) { \ + ret = h->vt.operation params; \ + } \ + if (ret) { \ + if (stage == KADM5_HOOK_STAGE_PRECOMMIT) \ + return ret; \ + else \ + log_failure(context, h->vt.name, #operation, ret); \ + } \ + } + + +kadm5_ret_t +k5_kadm5_hook_chpass(krb5_context context, kadm5_hook_handle *handles, + int stage, krb5_principal princ, krb5_boolean keepold, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, + const char *newpass) +{ + ITERATE(chpass, (context, h->data, + stage, princ, keepold, + n_ks_tuple, ks_tuple, newpass)); + return 0; +} + +kadm5_ret_t +k5_kadm5_hook_create(krb5_context context, kadm5_hook_handle *handles, + int stage, kadm5_principal_ent_t princ, long mask, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, + const char *newpass) +{ + ITERATE(create, (context, h->data, + stage, princ, mask, n_ks_tuple, ks_tuple, newpass)); + return 0; +} + +kadm5_ret_t +k5_kadm5_hook_modify(krb5_context context, kadm5_hook_handle *handles, + int stage, kadm5_principal_ent_t princ, long mask) +{ + ITERATE(modify, (context, h->data, stage, princ, mask)); + return 0; +} + +kadm5_ret_t +k5_kadm5_hook_rename(krb5_context context, kadm5_hook_handle *handles, + int stage, krb5_principal oprinc, krb5_principal nprinc) +{ + ITERATE(rename, (context, h->data, stage, oprinc, nprinc)); + return 0; +} + +kadm5_ret_t +k5_kadm5_hook_remove(krb5_context context, kadm5_hook_handle *handles, + int stage, krb5_principal princ) +{ + ITERATE(remove, (context, h->data, stage, princ)); + return 0; +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/libkadm5srv_mit.exports b/krb5-1.21.3/src/lib/kadm5/srv/libkadm5srv_mit.exports new file mode 100644 index 00000000..14c02a7f --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/libkadm5srv_mit.exports @@ -0,0 +1,134 @@ +_kadm5_check_handle +_kadm5_chpass_principal_util +hist_princ +kadm5_chpass_principal +kadm5_chpass_principal_3 +kadm5_chpass_principal_util +kadm5_create_policy +kadm5_create_principal +kadm5_create_principal_3 +kadm5_decrypt_key +kadm5_delete_policy +kadm5_delete_principal +kadm5_destroy +kadm5_flush +kadm5_free_config_params +kadm5_free_kadm5_key_data +kadm5_free_key_data +kadm5_free_name_list +kadm5_free_policy_ent +kadm5_free_principal_ent +kadm5_free_strings +kadm5_get_config_params +kadm5_get_policies +kadm5_get_policy +kadm5_get_principal +kadm5_get_principal_keys +kadm5_get_principals +kadm5_get_privs +kadm5_get_strings +kadm5_init +kadm5_init_anonymous +kadm5_init_krb5_context +kadm5_init_with_creds +kadm5_init_with_password +kadm5_init_with_skey +kadm5_lock +kadm5_modify_policy +kadm5_modify_principal +kadm5_purgekeys +kadm5_randkey_principal +kadm5_randkey_principal_3 +kadm5_rename_principal +kadm5_set_string +kadm5_setkey_principal +kadm5_setkey_principal_3 +kadm5_setkey_principal_4 +kadm5_unlock +kdb_delete_entry +kdb_free_entry +kdb_init_hist +kdb_init_master +kdb_iter_entry +kdb_put_entry +krb5_aprof_get_boolean +krb5_aprof_get_deltat +krb5_aprof_get_int32 +krb5_aprof_get_string +krb5_aprof_get_string_all +krb5_aprof_getvals +krb5_copy_key_data_contents +krb5_flagnum_to_string +krb5_flagspec_to_mask +krb5_flags_to_strings +krb5_free_key_data_contents +krb5_keysalt_is_present +krb5_keysalt_iterate +krb5_klog_close +krb5_klog_init +krb5_klog_reopen +krb5_klog_set_context +krb5_klog_syslog +krb5_string_to_keysalts +master_db +master_princ +osa_free_princ_ent +passwd_check +xdr_chpass3_arg +xdr_chpass_arg +xdr_chrand3_arg +xdr_chrand_arg +xdr_chrand_ret +xdr_cpol_arg +xdr_cprinc3_arg +xdr_cprinc_arg +xdr_dpol_arg +xdr_dprinc_arg +xdr_generic_ret +xdr_getpkeys_arg +xdr_getpkeys_ret +xdr_getprivs_ret +xdr_gpol_arg +xdr_gpol_ret +xdr_gpols_arg +xdr_gpols_ret +xdr_gprinc_arg +xdr_gprinc_ret +xdr_gprincs_arg +xdr_gprincs_ret +xdr_gstrings_arg +xdr_gstrings_ret +xdr_kadm5_policy_ent_rec +xdr_kadm5_principal_ent_rec +xdr_kadm5_ret_t +xdr_krb5_deltat +xdr_krb5_enctype +xdr_krb5_flags +xdr_krb5_int16 +xdr_krb5_key_data +xdr_krb5_key_data_nocontents +xdr_krb5_key_salt_tuple +xdr_krb5_keyblock +xdr_krb5_kvno +xdr_krb5_octet +xdr_krb5_principal +xdr_krb5_salttype +xdr_krb5_string_attr +xdr_krb5_timestamp +xdr_krb5_tl_data +xdr_krb5_ui_2 +xdr_krb5_ui_4 +xdr_mpol_arg +xdr_mprinc_arg +xdr_nullstring +xdr_nulltype +xdr_osa_princ_ent_rec +xdr_osa_pw_hist_ent +xdr_purgekeys_arg +xdr_rprinc_arg +xdr_setkey3_arg +xdr_setkey4_arg +xdr_setkey_arg +xdr_sstring_arg +xdr_ui_4 +kadm5_init_iprop diff --git a/krb5-1.21.3/src/lib/kadm5/srv/pwqual.c b/krb5-1.21.3/src/lib/kadm5/srv/pwqual.c new file mode 100644 index 00000000..666852f1 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/pwqual.c @@ -0,0 +1,127 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kadm5/srv/pwqual.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * Consumer interface for password quality plugins. + */ + +#include "k5-int.h" +#include "server_internal.h" +#include + +struct pwqual_handle_st { + struct krb5_pwqual_vtable_st vt; + krb5_pwqual_moddata data; +}; + +krb5_error_code +k5_pwqual_load(krb5_context context, const char *dict_file, + pwqual_handle **handles_out) +{ + krb5_error_code ret; + krb5_plugin_initvt_fn *modules = NULL, *mod; + size_t count; + pwqual_handle *list = NULL, handle = NULL; + + *handles_out = NULL; + + ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_PWQUAL, &modules); + if (ret != 0) + goto cleanup; + + /* Allocate a large enough list of handles. */ + for (count = 0; modules[count] != NULL; count++); + list = k5calloc(count + 1, sizeof(*list), &ret); + if (list == NULL) + goto cleanup; + + /* For each module, allocate a handle, initialize its vtable, and bind the + * dictionary filename. */ + count = 0; + for (mod = modules; *mod != NULL; mod++) { + handle = k5alloc(sizeof(*handle), &ret); + if (handle == NULL) + goto cleanup; + ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&handle->vt); + if (ret != 0) { /* Failed vtable init is non-fatal. */ + free(handle); + handle = NULL; + continue; + } + handle->data = NULL; + if (handle->vt.open != NULL) { + ret = handle->vt.open(context, dict_file, &handle->data); + if (ret != 0) /* Failed dictionary binding is fatal. */ + goto cleanup; + } + list[count++] = handle; + list[count] = NULL; + handle = NULL; + } + list[count] = NULL; + + ret = 0; + *handles_out = list; + list = NULL; + +cleanup: + free(handle); + k5_plugin_free_modules(context, modules); + k5_pwqual_free_handles(context, list); + return ret; +} + +void +k5_pwqual_free_handles(krb5_context context, pwqual_handle *handles) +{ + pwqual_handle *hp, handle; + + if (handles == NULL) + return; + for (hp = handles; *hp != NULL; hp++) { + handle = *hp; + if (handle->vt.close != NULL) + handle->vt.close(context, handle->data); + free(handle); + } + free(handles); +} + +const char * +k5_pwqual_name(krb5_context context, pwqual_handle handle) +{ + return handle->vt.name; +} + +krb5_error_code +k5_pwqual_check(krb5_context context, pwqual_handle handle, + const char *password, const char *policy_name, + krb5_principal princ) +{ + return handle->vt.check(context, handle->data, password, policy_name, + princ, NULL); +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/pwqual_dict.c b/krb5-1.21.3/src/lib/kadm5/srv/pwqual_dict.c new file mode 100644 index 00000000..bdd44c23 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/pwqual_dict.c @@ -0,0 +1,257 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kadm5/srv/pwqual_dict.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + */ + +/* Password quality module to look up passwords within the realm dictionary. */ + +#include "k5-platform.h" +#include +#include +#include +#include +#include +#include "adm_proto.h" +#include +#include "server_internal.h" + +typedef struct dict_moddata_st { + char **word_list; /* list of word pointers */ + char *word_block; /* actual word data */ + unsigned int word_count; /* number of words */ +} *dict_moddata; + + +/* + * Function: word_compare + * + * Purpose: compare two words in the dictionary. + * + * Arguments: + * w1 (input) pointer to first word + * w2 (input) pointer to second word + * result of strcmp + * + * Requires: + * w1 and w2 to point to valid memory + * + */ + +static int +word_compare(const void *s1, const void *s2) +{ + return (strcasecmp(*(const char **)s1, *(const char **)s2)); +} + +/* + * Function: init-dict + * + * Purpose: Initialize in memory word dictionary + * + * Arguments: + * none + * KADM5_OK on success errno on failure; + * (but success on ENOENT) + * + * Requires: + * If WORDFILE exists, it must contain a list of words, + * one word per-line. + * + * Effects: + * If WORDFILE exists, it is read into memory sorted for future + * use. If it does not exist, it syslogs an error message and returns + * success. + * + * Modifies: + * word_list to point to a chunk of allocated memory containing + * pointers to words + * word_block to contain the dictionary. + * + */ + +static int +init_dict(dict_moddata dict, const char *dict_file) +{ + int fd; + size_t len, i; + char *p, *t; + struct stat sb; + + if (dict_file == NULL) { + krb5_klog_syslog(LOG_INFO, + _("No dictionary file specified, continuing without " + "one.")); + return KADM5_OK; + } + if ((fd = open(dict_file, O_RDONLY)) == -1) { + if (errno == ENOENT) { + krb5_klog_syslog(LOG_ERR, + _("WARNING! Cannot find dictionary file %s, " + "continuing without one."), dict_file); + return KADM5_OK; + } else + return errno; + } + set_cloexec_fd(fd); + if (fstat(fd, &sb) == -1) { + close(fd); + return errno; + } + dict->word_block = malloc(sb.st_size + 1); + if (dict->word_block == NULL) { + (void)close(fd); + return ENOMEM; + } + if (read(fd, dict->word_block, sb.st_size) != sb.st_size) { + (void)close(fd); + return errno; + } + (void)close(fd); + dict->word_block[sb.st_size] = '\0'; + + p = dict->word_block; + len = sb.st_size; + while(len > 0 && (t = memchr(p, '\n', len)) != NULL) { + *t = '\0'; + len -= t - p + 1; + p = t + 1; + dict->word_count++; + } + if ((dict->word_list = malloc(dict->word_count * sizeof(char *))) == NULL) + return ENOMEM; + p = dict->word_block; + for (i = 0; i < dict->word_count; i++) { + dict->word_list[i] = p; + p += strlen(p) + 1; + } + qsort(dict->word_list, dict->word_count, sizeof(char *), word_compare); + return KADM5_OK; +} + +/* + * Function: destroy_dict + * + * Purpose: destroy in-core copy of dictionary. + * + * Arguments: + * none + * none + * Requires: + * nothing + * Effects: + * frees up memory occupied by word_list and word_block + * sets count back to 0, and resets the pointers to NULL + * + * Modifies: + * word_list, word_block, and word_count. + * + */ + +static void +destroy_dict(dict_moddata dict) +{ + if (dict == NULL) + return; + free(dict->word_list); + free(dict->word_block); + free(dict); + return; +} + +/* Implement the password quality open method by reading in dict_file. */ +static krb5_error_code +dict_open(krb5_context context, const char *dict_file, + krb5_pwqual_moddata *data) +{ + krb5_error_code ret; + dict_moddata dict; + + *data = NULL; + + /* Allocate and initialize a dictionary structure. */ + dict = malloc(sizeof(*dict)); + if (dict == NULL) + return ENOMEM; + dict->word_list = NULL; + dict->word_block = NULL; + dict->word_count = 0; + + /* Fill in the dictionary structure with data from dict_file. */ + ret = init_dict(dict, dict_file); + if (ret != 0) { + destroy_dict(dict); + return ret; + } + + *data = (krb5_pwqual_moddata)dict; + return 0; +} + +/* Implement the password quality check method by checking the password + * against the dictionary, as well as against principal components. */ +static krb5_error_code +dict_check(krb5_context context, krb5_pwqual_moddata data, + const char *password, const char *policy_name, + krb5_principal princ, const char **languages) +{ + dict_moddata dict = (dict_moddata)data; + + /* Don't check the dictionary for principals with no password policy. */ + if (policy_name == NULL) + return 0; + + /* Check against words in the dictionary if we successfully loaded one. */ + if (dict->word_list != NULL && + bsearch(&password, dict->word_list, dict->word_count, sizeof(char *), + word_compare) != NULL) + return KADM5_PASS_Q_DICT; + + return 0; +} + +/* Implement the password quality close method. */ +static void +dict_close(krb5_context context, krb5_pwqual_moddata data) +{ + destroy_dict((dict_moddata)data); +} + +krb5_error_code +pwqual_dict_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_pwqual_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_pwqual_vtable)vtable; + vt->name = "dict"; + vt->open = dict_open; + vt->check = dict_check; + vt->close = dict_close; + return 0; +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/pwqual_empty.c b/krb5-1.21.3/src/lib/kadm5/srv/pwqual_empty.c new file mode 100644 index 00000000..1fc9b7bc --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/pwqual_empty.c @@ -0,0 +1,60 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kadm5/srv/pwqual_empty.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Password quality module to reject empty passwords */ + +#include "k5-int.h" +#include +#include "server_internal.h" + +static krb5_error_code +empty_check(krb5_context context, krb5_pwqual_moddata data, + const char *password, const char *policy_name, + krb5_principal princ, const char **languages) +{ + /* Unlike other built-in modules, this one operates even for principals + * with no password policy. */ + if (*password == '\0') { + k5_setmsg(context, KADM5_PASS_Q_TOOSHORT, + _("Empty passwords are not allowed")); + return KADM5_PASS_Q_TOOSHORT; + } + return 0; +} + +krb5_error_code +pwqual_empty_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_pwqual_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_pwqual_vtable)vtable; + vt->name = "empty"; + vt->check = empty_check; + return 0; +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/pwqual_hesiod.c b/krb5-1.21.3/src/lib/kadm5/srv/pwqual_hesiod.c new file mode 100644 index 00000000..7c82bba9 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/pwqual_hesiod.c @@ -0,0 +1,134 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kadm5/srv/pwqual_hesiod.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Password quality module to check passwords against GECOS fields of Hesiod + * passwd information, if the tree is compiled with Hesiod support. + */ + +#include "k5-int.h" +#include +#include "server_internal.h" +#include + +#ifdef HESIOD +#include + +static char * +reverse(char *str, char *newstr, size_t newstr_size) +{ + char *p, *q; + size_t i; + + i = strlen(str); + if (i >= newstr_size) + i = newstr_size - 1; + p = str + i - 1; + q = newstr; + q[i] = '\0'; + for (; i > 0; i--) + *q++ = *p--; + + return newstr; +} + +static int +str_check_gecos(char *gecos, const char *pwstr) +{ + char *cp, *ncp, *tcp, revbuf[80]; + + for (cp = gecos; *cp; ) { + /* Skip past punctuation */ + for (; *cp; cp++) + if (isalnum(*cp)) + break; + + /* Skip to the end of the word */ + for (ncp = cp; *ncp; ncp++) { + if (!isalnum(*ncp) && *ncp != '\'') + break; + } + + /* Delimit end of word */ + if (*ncp) + *ncp++ = '\0'; + + /* Check word to see if it's the password */ + if (*cp) { + if (!strcasecmp(pwstr, cp)) + return 1; + tcp = reverse(cp, revbuf, sizeof(revbuf)); + if (!strcasecmp(pwstr, tcp)) + return 1; + cp = ncp; + } else + break; + } + return 0; +} +#endif /* HESIOD */ + +static krb5_error_code +hesiod_check(krb5_context context, krb5_pwqual_moddata data, + const char *password, const char *policy_name, + krb5_principal princ, const char **languages) +{ +#ifdef HESIOD + extern struct passwd *hes_getpwnam(); + struct passwd *ent; + int i, n; + const char *cp; + + /* Don't check for principals with no password policy. */ + if (policy_name == NULL) + return 0; + + n = krb5_princ_size(handle->context, princ); + for (i = 0; i < n; i++) { + ent = hes_getpwnam(cp); + if (ent && ent->pw_gecos && str_check_gecos(ent->pw_gecos, password)) { + k5_setmsg(context, KADM5_PASS_Q_DICT, + _("Password may not match user information.")); + return KADM5_PASS_Q_DICT; + } + } +#endif /* HESIOD */ + return 0; +} + +krb5_error_code +pwqual_hesiod_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_pwqual_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_pwqual_vtable)vtable; + vt->name = "hesiod"; + vt->check = hesiod_check; + return 0; +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/pwqual_princ.c b/krb5-1.21.3/src/lib/kadm5/srv/pwqual_princ.c new file mode 100644 index 00000000..14012e59 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/pwqual_princ.c @@ -0,0 +1,74 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kadm5/srv/pwqual_princ.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Password quality module to check passwords against principal components */ + +#include "k5-int.h" +#include +#include "server_internal.h" + +static krb5_error_code +princ_check(krb5_context context, krb5_pwqual_moddata data, + const char *password, const char *policy_name, + krb5_principal princ, const char **languages) +{ + int i, n; + char *cp; + + /* Don't check for principals with no password policy. */ + if (policy_name == NULL) + return 0; + + /* Check against components of the principal. */ + n = krb5_princ_size(handle->context, princ); + cp = krb5_princ_realm(handle->context, princ)->data; + if (strcasecmp(cp, password) == 0) + return KADM5_PASS_Q_DICT; + for (i = 0; i < n; i++) { + cp = krb5_princ_component(handle->context, princ, i)->data; + if (strcasecmp(cp, password) == 0) { + k5_setmsg(context, KADM5_PASS_Q_DICT, + _("Password may not match principal name")); + return KADM5_PASS_Q_DICT; + } + } + + return 0; +} + +krb5_error_code +pwqual_princ_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_pwqual_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_pwqual_vtable)vtable; + vt->name = "princ"; + vt->check = princ_check; + return 0; +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/server_handle.c b/krb5-1.21.3/src/lib/kadm5/srv/server_handle.c new file mode 100644 index 00000000..37425c8b --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/server_handle.c @@ -0,0 +1,10 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include +#include +#include "server_internal.h" + +int _kadm5_check_handle(void *handle) +{ + CHECK_HANDLE(handle); + return 0; +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/server_init.c b/krb5-1.21.3/src/lib/kadm5/srv/server_init.c new file mode 100644 index 00000000..2c0d51ef --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/server_init.c @@ -0,0 +1,362 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. + * + * $Id$ + * $Source$ + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include "k5-int.h" +#include +#include +#include +#include +#include "server_internal.h" +#include "osconf.h" +#include "iprop_hdr.h" + +static int dup_db_args(kadm5_server_handle_t handle, char **db_args) +{ + int count = 0; + int ret = 0; + + for (count=0; db_args && db_args[count]; count++); + if (count == 0) { + handle->db_args = NULL; + goto clean_n_exit; + } + + handle->db_args = calloc(sizeof(char*), count+1); + if (handle->db_args == NULL) { + ret=ENOMEM; + goto clean_n_exit; + } + + for (count=0; db_args[count]; count++) { + handle->db_args[count] = strdup(db_args[count]); + if (handle->db_args[count] == NULL) { + ret = ENOMEM; + goto clean_n_exit; + } + } + +clean_n_exit: + if (ret && handle->db_args) { + for (count=0; handle->db_args[count]; count++) + free(handle->db_args[count]); + + free(handle->db_args), handle->db_args = NULL; + } + + return ret; +} + +static void free_db_args(kadm5_server_handle_t handle) +{ + int count; + + if (handle->db_args) { + for (count=0; handle->db_args[count]; count++) + free(handle->db_args[count]); + + free(handle->db_args), handle->db_args = NULL; + } +} + +static void +free_handle(kadm5_server_handle_t handle) +{ + if (handle == NULL) + return; + + destroy_pwqual(handle); + k5_kadm5_hook_free_handles(handle->context, handle->hook_handles); + ulog_fini(handle->context); + krb5_db_fini(handle->context); + krb5_free_principal(handle->context, handle->current_caller); + kadm5_free_config_params(handle->context, &handle->params); + free(handle->lhandle); + free_db_args(handle); + free(handle); +} + +kadm5_ret_t kadm5_init_with_password(krb5_context context, char *client_name, + char *pass, char *service_name, + kadm5_config_params *params, + krb5_ui_4 struct_version, + krb5_ui_4 api_version, + char **db_args, + void **server_handle) +{ + return kadm5_init(context, client_name, pass, service_name, params, + struct_version, api_version, db_args, + server_handle); +} + +kadm5_ret_t kadm5_init_anonymous(krb5_context context, char *client_name, + char *service_name, + kadm5_config_params *params, + krb5_ui_4 struct_version, + krb5_ui_4 api_version, + char **db_args, + void **server_handle) +{ + return kadm5_init(context, client_name, NULL, service_name, params, + struct_version, api_version, db_args, + server_handle); +} + +kadm5_ret_t kadm5_init_with_creds(krb5_context context, + char *client_name, + krb5_ccache ccache, + char *service_name, + kadm5_config_params *params, + krb5_ui_4 struct_version, + krb5_ui_4 api_version, + char **db_args, + void **server_handle) +{ + /* + * A program calling init_with_creds *never* expects to prompt + * the user. If this is KADM5_API_VERSION_2 and MKEY_FROM_KBD is + * non-zero, return an error. + */ + if (params && (params->mask & KADM5_CONFIG_MKEY_FROM_KBD) && + params->mkey_from_kbd) + return KADM5_BAD_SERVER_PARAMS; + return kadm5_init(context, client_name, NULL, service_name, params, + struct_version, api_version, db_args, + server_handle); +} + + +kadm5_ret_t kadm5_init_with_skey(krb5_context context, char *client_name, + char *keytab, char *service_name, + kadm5_config_params *params, + krb5_ui_4 struct_version, + krb5_ui_4 api_version, + char **db_args, + void **server_handle) +{ + /* + * A program calling init_with_skey *never* expects to prompt the + * user. If this is KADM5_API_VERSION_2 and MKEY_FROM_KBD is + * non-zero, return an error. + */ + if (params && (params->mask & KADM5_CONFIG_MKEY_FROM_KBD) && + params->mkey_from_kbd) + return KADM5_BAD_SERVER_PARAMS; + return kadm5_init(context, client_name, NULL, service_name, params, + struct_version, api_version, db_args, + server_handle); +} + +kadm5_ret_t kadm5_init(krb5_context context, char *client_name, char *pass, + char *service_name, + kadm5_config_params *params_in, + krb5_ui_4 struct_version, + krb5_ui_4 api_version, + char **db_args, + void **server_handle) +{ + krb5_error_code ret; + kadm5_server_handle_t handle = NULL; + kadm5_config_params params_local; /* for v1 compat */ + + if (! server_handle) + return EINVAL; + + if (! client_name) + return EINVAL; + + CHECK_VERSIONS(struct_version, api_version, KADM5_OLD_SERVER_API_VERSION, + KADM5_NEW_SERVER_API_VERSION); + + handle = k5alloc(sizeof(*handle), &ret); + if (handle == NULL) + goto cleanup; + handle->context = context; + + ret = dup_db_args(handle, db_args); + if (ret) + goto cleanup; + + initialize_ovk_error_table(); + initialize_ovku_error_table(); + + handle->magic_number = KADM5_SERVER_HANDLE_MAGIC; + handle->struct_version = struct_version; + handle->api_version = api_version; + + /* + * Acquire relevant profile entries. Merge values + * in params_in with values from profile, based on + * params_in->mask. + */ + memset(¶ms_local, 0, sizeof(params_local)); + + ret = kadm5_get_config_params(handle->context, 1, params_in, + &handle->params); + if (ret) + goto cleanup; + +#define REQUIRED_PARAMS (KADM5_CONFIG_REALM | KADM5_CONFIG_DBNAME | \ + KADM5_CONFIG_ENCTYPE | \ + KADM5_CONFIG_FLAGS | \ + KADM5_CONFIG_MAX_LIFE | KADM5_CONFIG_MAX_RLIFE | \ + KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_ENCTYPES) + +#define IPROP_REQUIRED_PARAMS \ + (KADM5_CONFIG_IPROP_ENABLED | \ + KADM5_CONFIG_IPROP_LOGFILE | \ + KADM5_CONFIG_IPROP_PORT) + + if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) { + ret = KADM5_MISSING_CONF_PARAMS; + goto cleanup; + } + if ((handle->params.mask & KADM5_CONFIG_IPROP_ENABLED) == KADM5_CONFIG_IPROP_ENABLED + && handle->params.iprop_enabled) { + if ((handle->params.mask & IPROP_REQUIRED_PARAMS) != IPROP_REQUIRED_PARAMS) { + ret = KADM5_MISSING_CONF_PARAMS; + goto cleanup; + } + } + + ret = krb5_set_default_realm(handle->context, handle->params.realm); + if (ret) + goto cleanup; + + ret = krb5_db_open(handle->context, db_args, + KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN); + if (ret) + goto cleanup; + + ret = krb5_parse_name(handle->context, client_name, + &handle->current_caller); + if (ret) + goto cleanup; + + handle->lhandle = k5alloc(sizeof(*handle), &ret); + if (handle->lhandle == NULL) + goto cleanup; + *handle->lhandle = *handle; + handle->lhandle->api_version = KADM5_API_VERSION_4; + handle->lhandle->struct_version = KADM5_STRUCT_VERSION; + handle->lhandle->lhandle = handle->lhandle; + + ret = kdb_init_master(handle, handle->params.realm, + (handle->params.mask & KADM5_CONFIG_MKEY_FROM_KBD) + && handle->params.mkey_from_kbd); + if (ret) + goto cleanup; + + ret = kdb_init_hist(handle, handle->params.realm); + if (ret) + goto cleanup; + + ret = k5_kadm5_hook_load(context,&handle->hook_handles); + if (ret) + goto cleanup; + + ret = init_pwqual(handle); + if (ret) + goto cleanup; + + *server_handle = handle; + handle = NULL; + +cleanup: + free_handle(handle); + return ret; +} + +kadm5_ret_t kadm5_destroy(void *server_handle) +{ + CHECK_HANDLE(server_handle); + free_handle(server_handle); + return KADM5_OK; +} + +kadm5_ret_t kadm5_lock(void *server_handle) +{ + kadm5_server_handle_t handle = server_handle; + kadm5_ret_t ret; + + CHECK_HANDLE(server_handle); + ret = krb5_db_lock(handle->context, KRB5_DB_LOCKMODE_EXCLUSIVE); + if (ret) + return ret; + + return KADM5_OK; +} + +kadm5_ret_t kadm5_unlock(void *server_handle) +{ + kadm5_server_handle_t handle = server_handle; + kadm5_ret_t ret; + + CHECK_HANDLE(server_handle); + ret = krb5_db_unlock(handle->context); + if (ret) + return ret; + + return KADM5_OK; +} + +kadm5_ret_t kadm5_flush(void *server_handle) +{ + kadm5_server_handle_t handle = server_handle; + kadm5_ret_t ret; + + CHECK_HANDLE(server_handle); + + if ((ret = krb5_db_fini(handle->context)) || + (ret = krb5_db_open(handle->context, handle->db_args, + KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN))) { + (void) kadm5_destroy(server_handle); + return ret; + } + return KADM5_OK; +} + +int _kadm5_check_handle(void *handle) +{ + CHECK_HANDLE(handle); + return 0; +} + +#include "gssapiP_krb5.h" +krb5_error_code kadm5_init_krb5_context (krb5_context *ctx) +{ + static int first_time = 1; + if (first_time) { + krb5_error_code err; + err = krb5_gss_use_kdc_context(); + if (err) + return err; + first_time = 0; + } + return krb5int_init_context_kdc(ctx); +} + +krb5_error_code +kadm5_init_iprop(void *handle, char **db_args) +{ + kadm5_server_handle_t iprop_h; + krb5_error_code retval; + + iprop_h = handle; + if (iprop_h->params.iprop_enabled) { + ulog_set_role(iprop_h->context, IPROP_PRIMARY); + retval = ulog_map(iprop_h->context, iprop_h->params.iprop_logfile, + iprop_h->params.iprop_ulogsize); + if (retval) + return (retval); + } + return (0); +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/server_kdb.c b/krb5-1.21.3/src/lib/kadm5/srv/server_kdb.c new file mode 100644 index 00000000..2ec80a0f --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/server_kdb.c @@ -0,0 +1,449 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include "k5-int.h" +#include +#include "server_internal.h" + +krb5_principal master_princ; +krb5_keyblock master_keyblock; /* local mkey */ +krb5_db_entry master_db; + +krb5_principal hist_princ; + +/* much of this code is stolen from the kdc. there should be some + library code to deal with this. */ + +krb5_error_code kdb_init_master(kadm5_server_handle_t handle, + char *r, int from_keyboard) +{ + int ret = 0; + char *realm; + krb5_boolean from_kbd = FALSE; + krb5_kvno mkvno = IGNORE_VNO; + + if (from_keyboard) + from_kbd = TRUE; + + if (r == NULL) { + if ((ret = krb5_get_default_realm(handle->context, &realm))) + return ret; + } else { + realm = r; + } + + krb5_free_principal(handle->context, master_princ); + master_princ = NULL; + if ((ret = krb5_db_setup_mkey_name(handle->context, + handle->params.mkey_name, + realm, NULL, &master_princ))) + goto done; + + krb5_free_keyblock_contents(handle->context, &master_keyblock); + master_keyblock.enctype = handle->params.enctype; + + /* + * Fetch the local mkey, may not be the latest but that's okay because we + * really want the list of all mkeys and those can be retrieved with any + * valid mkey. + */ + ret = krb5_db_fetch_mkey(handle->context, master_princ, + master_keyblock.enctype, from_kbd, + FALSE /* only prompt once */, + handle->params.stash_file, + &mkvno /* get the kvno of the returned mkey */, + NULL /* I'm not sure about this, + but it's what the kdc does --marc */, + &master_keyblock); + if (ret) + goto done; + + if ((ret = krb5_db_fetch_mkey_list(handle->context, master_princ, + &master_keyblock))) { + krb5_db_fini(handle->context); + return (ret); + } + +done: + if (r == NULL) + free(realm); + + return(ret); +} + +/* Fetch the currently active master key version number and keyblock. */ +krb5_error_code +kdb_get_active_mkey(kadm5_server_handle_t handle, krb5_kvno *act_kvno_out, + krb5_keyblock **act_mkey_out) +{ + krb5_error_code ret; + krb5_actkvno_node *active_mkey_list; + + ret = krb5_dbe_fetch_act_key_list(handle->context, master_princ, + &active_mkey_list); + if (ret) + return ret; + ret = krb5_dbe_find_act_mkey(handle->context, active_mkey_list, + act_kvno_out, act_mkey_out); + krb5_dbe_free_actkvno_list(handle->context, active_mkey_list); + return ret; +} + +/* + * Function: kdb_init_hist + * + * Purpose: Initializes the hist_princ variable. + * + * Arguments: + * + * handle (r) kadm5 api server handle + * r (r) realm of history principal to use, or NULL + * + * Effects: This function sets the value of the hist_princ global variable. + */ +krb5_error_code kdb_init_hist(kadm5_server_handle_t handle, char *r) +{ + int ret = 0; + char *realm, *hist_name; + + if (r == NULL) { + if ((ret = krb5_get_default_realm(handle->context, &realm))) + return ret; + } else { + realm = r; + } + + if (asprintf(&hist_name, "%s@%s", KADM5_HIST_PRINCIPAL, realm) < 0) { + hist_name = NULL; + goto done; + } + + krb5_free_principal(handle->context, hist_princ); + hist_princ = NULL; + if ((ret = krb5_parse_name(handle->context, hist_name, &hist_princ))) + goto done; + +done: + free(hist_name); + if (r == NULL) + free(realm); + return ret; +} + +static krb5_error_code +create_hist(kadm5_server_handle_t handle) +{ + kadm5_ret_t ret; + krb5_key_salt_tuple ks[1]; + kadm5_principal_ent_rec ent; + long mask = KADM5_PRINCIPAL | KADM5_MAX_LIFE | KADM5_ATTRIBUTES; + + /* Create the history principal. */ + memset(&ent, 0, sizeof(ent)); + ent.principal = hist_princ; + ent.max_life = KRB5_KDB_DISALLOW_ALL_TIX; + ent.attributes = 0; + ks[0].ks_enctype = handle->params.enctype; + ks[0].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL; + ret = kadm5_create_principal_3(handle, &ent, mask, 1, ks, NULL); + if (ret) + return ret; + + /* For better compatibility with pre-1.8 libkadm5 code, we want the + * initial history kvno to be 2, so re-randomize it. */ + return kadm5_randkey_principal_3(handle, ent.principal, 0, 1, ks, + NULL, NULL); +} + +/* + * Fetch the current history key(s), creating the history principal if + * necessary. Database created since krb5 1.3 will have only one key, but + * databases created before that may have multiple keys (of the same kvno) + * and we need to try them all. History keys will be returned in a list + * terminated by an entry with enctype 0. + */ +krb5_error_code +kdb_get_hist_key(kadm5_server_handle_t handle, krb5_keyblock **keyblocks_out, + krb5_kvno *kvno_out) +{ + krb5_error_code ret; + krb5_db_entry *kdb; + krb5_keyblock *mkey, *kblist = NULL; + krb5_int16 i; + + /* Fetch the history principal, creating it if necessary. */ + ret = kdb_get_entry(handle, hist_princ, &kdb, NULL); + if (ret == KADM5_UNK_PRINC) { + ret = create_hist(handle); + if (ret) + return ret; + ret = kdb_get_entry(handle, hist_princ, &kdb, NULL); + } + if (ret) + return ret; + + if (kdb->n_key_data <= 0) { + ret = KRB5_KDB_NO_MATCHING_KEY; + k5_setmsg(handle->context, ret, + _("History entry contains no key data")); + goto done; + } + + ret = krb5_dbe_find_mkey(handle->context, kdb, &mkey); + if (ret) + goto done; + + kblist = k5calloc(kdb->n_key_data + 1, sizeof(*kblist), &ret); + if (kblist == NULL) + goto done; + for (i = 0; i < kdb->n_key_data; i++) { + ret = krb5_dbe_decrypt_key_data(handle->context, mkey, + &kdb->key_data[i], &kblist[i], + NULL); + if (ret) + goto done; + } + + *keyblocks_out = kblist; + kblist = NULL; + *kvno_out = kdb->key_data[0].key_data_kvno; + +done: + kdb_free_entry(handle, kdb, NULL); + kdb_free_keyblocks(handle, kblist); + return ret; +} + +/* Free all keyblocks in a list (terminated by a keyblock with enctype 0). */ +void +kdb_free_keyblocks(kadm5_server_handle_t handle, krb5_keyblock *keyblocks) +{ + krb5_keyblock *kb; + + if (keyblocks == NULL) + return; + for (kb = keyblocks; kb->enctype != 0; kb++) + krb5_free_keyblock_contents(handle->context, kb); + free(keyblocks); +} + +/* + * Function: kdb_get_entry + * + * Purpose: Gets an entry from the kerberos database and breaks + * it out into a krb5_db_entry and an osa_princ_ent_t. + * + * Arguments: + * + * handle (r) the server_handle + * principal (r) the principal to get + * kdb (w) krb5_db_entry to create + * adb (w) osa_princ_ent_rec to fill in + * + * when the caller is done with kdb and adb, kdb_free_entry must be + * called to release them. The adb record is filled in with the + * contents of the KRB5_TL_KADM_DATA record; if that record doesn't + * exist, an empty but valid adb record is returned. + */ +krb5_error_code +kdb_get_entry(kadm5_server_handle_t handle, + krb5_principal principal, krb5_db_entry **kdb_ptr, + osa_princ_ent_rec *adb) +{ + krb5_error_code ret; + krb5_tl_data tl_data; + XDR xdrs; + krb5_db_entry *kdb; + + *kdb_ptr = NULL; + + ret = krb5_db_get_principal(handle->context, principal, 0, &kdb); + if (ret == KRB5_KDB_NOENTRY) + return(KADM5_UNK_PRINC); + if (ret) + return(ret); + + if (adb) { + memset(adb, 0, sizeof(*adb)); + + tl_data.tl_data_type = KRB5_TL_KADM_DATA; + /* + * XXX Currently, lookup_tl_data always returns zero; it sets + * tl_data->tl_data_length to zero if the type isn't found. + * This should be fixed... + */ + if ((ret = krb5_dbe_lookup_tl_data(handle->context, kdb, &tl_data)) + || (tl_data.tl_data_length == 0)) { + /* there's no admin data. this can happen, if the admin + server is put into production after some principals + are created. In this case, return valid admin + data (which is all zeros with the hist_kvno filled + in), and when the entry is written, the admin + data will get stored correctly. */ + + adb->admin_history_kvno = INITIAL_HIST_KVNO; + *kdb_ptr = kdb; + return(ret); + } + + xdrmem_create(&xdrs, (caddr_t)tl_data.tl_data_contents, + tl_data.tl_data_length, XDR_DECODE); + if (! xdr_osa_princ_ent_rec(&xdrs, adb)) { + xdr_destroy(&xdrs); + krb5_db_free_principal(handle->context, kdb); + return(KADM5_XDR_FAILURE); + } + xdr_destroy(&xdrs); + } + + *kdb_ptr = kdb; + return(0); +} + +/* + * Function: kdb_free_entry + * + * Purpose: frees the resources allocated by kdb_get_entry + * + * Arguments: + * + * handle (r) the server_handle + * kdb (w) krb5_db_entry to fill in + * adb (w) osa_princ_ent_rec to fill in + * + * when the caller is done with kdb and adb, kdb_free_entry must be + * called to release them. + */ + +krb5_error_code +kdb_free_entry(kadm5_server_handle_t handle, + krb5_db_entry *kdb, osa_princ_ent_rec *adb) +{ + XDR xdrs; + + + if (kdb) + krb5_db_free_principal(handle->context, kdb); + + if (adb) { + xdrmem_create(&xdrs, NULL, 0, XDR_FREE); + xdr_osa_princ_ent_rec(&xdrs, adb); + xdr_destroy(&xdrs); + } + + return(0); +} + +/* + * Function: kdb_put_entry + * + * Purpose: Stores the osa_princ_ent_t and krb5_db_entry into to + * database. + * + * Arguments: + * + * handle (r) the server_handle + * kdb (r/w) the krb5_db_entry to store + * adb (r) the osa_princ_db_ent to store + * + * Effects: + * + * The last modifier field of the kdb is set to the caller at now. + * adb is encoded with xdr_osa_princ_ent_ret and stored in kbd as + * KRB5_TL_KADM_DATA. kdb is then written to the database. + */ +krb5_error_code +kdb_put_entry(kadm5_server_handle_t handle, + krb5_db_entry *kdb, osa_princ_ent_rec *adb) +{ + krb5_error_code ret; + krb5_timestamp now; + XDR xdrs; + krb5_tl_data tl_data; + + ret = krb5_timeofday(handle->context, &now); + if (ret) + return(ret); + + ret = krb5_dbe_update_mod_princ_data(handle->context, kdb, now, + handle->current_caller); + if (ret) + return(ret); + + xdralloc_create(&xdrs, XDR_ENCODE); + if(! xdr_osa_princ_ent_rec(&xdrs, adb)) { + xdr_destroy(&xdrs); + return(KADM5_XDR_FAILURE); + } + tl_data.tl_data_type = KRB5_TL_KADM_DATA; + tl_data.tl_data_length = xdr_getpos(&xdrs); + tl_data.tl_data_contents = (krb5_octet *)xdralloc_getdata(&xdrs); + + ret = krb5_dbe_update_tl_data(handle->context, kdb, &tl_data); + + xdr_destroy(&xdrs); + + if (ret) + return(ret); + + /* we are always updating TL data */ + kdb->mask |= KADM5_TL_DATA; + + ret = krb5_db_put_principal(handle->context, kdb); + if (ret) + return(ret); + + return(0); +} + +krb5_error_code +kdb_delete_entry(kadm5_server_handle_t handle, krb5_principal name) +{ + krb5_error_code ret; + + ret = krb5_db_delete_principal(handle->context, name); + if (ret == KRB5_KDB_NOENTRY) + ret = 0; + return ret; +} + +typedef struct _iter_data { + void (*func)(void *, krb5_principal); + void *data; +} iter_data; + +static krb5_error_code +kdb_iter_func(krb5_pointer data, krb5_db_entry *kdb) +{ + iter_data *id = (iter_data *) data; + + (*(id->func))(id->data, kdb->princ); + + return(0); +} + +krb5_error_code +kdb_iter_entry(kadm5_server_handle_t handle, char *match_entry, + void (*iter_fct)(void *, krb5_principal), void *data) +{ + iter_data id; + krb5_error_code ret; + + id.func = iter_fct; + id.data = data; + + ret = krb5_db_iterate(handle->context, match_entry, kdb_iter_func, &id, 0); + if (ret) + return(ret); + + return(0); +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/server_misc.c b/krb5-1.21.3/src/lib/kadm5/srv/server_misc.c new file mode 100644 index 00000000..87e97c9f --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/server_misc.c @@ -0,0 +1,158 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + */ + +#include "k5-int.h" +#include +#include +#include +#include +#include "server_internal.h" +#include + +kadm5_ret_t +init_pwqual(kadm5_server_handle_t handle) +{ + krb5_error_code ret; + pwqual_handle *list; + const char *dict_file = NULL; + + /* Register the built-in password quality modules. */ + ret = k5_plugin_register(handle->context, PLUGIN_INTERFACE_PWQUAL, + "dict", pwqual_dict_initvt); + if (ret != 0) + return ret; + ret = k5_plugin_register(handle->context, PLUGIN_INTERFACE_PWQUAL, + "empty", pwqual_empty_initvt); + if (ret != 0) + return ret; + ret = k5_plugin_register(handle->context, PLUGIN_INTERFACE_PWQUAL, + "hesiod", pwqual_hesiod_initvt); + if (ret != 0) + return ret; + ret = k5_plugin_register(handle->context, PLUGIN_INTERFACE_PWQUAL, + "princ", pwqual_princ_initvt); + if (ret != 0) + return ret; + + /* Load all available password quality modules. */ + if (handle->params.mask & KADM5_CONFIG_DICT_FILE) + dict_file = handle->params.dict_file; + ret = k5_pwqual_load(handle->context, dict_file, &list); + if (ret != 0) + return ret; + + handle->qual_handles = list; + return 0; +} + +/* Check that a password meets the quality constraints given in pol. */ +static kadm5_ret_t +check_against_policy(kadm5_server_handle_t handle, const char *password, + kadm5_policy_ent_t pol) +{ + int hasupper = 0, haslower = 0, hasdigit = 0, haspunct = 0, hasspec = 0; + int c, nclasses; + + /* Check against the policy's minimum length. */ + if (strlen(password) < (size_t)pol->pw_min_length) + return KADM5_PASS_Q_TOOSHORT; + + /* Check against the policy's minimum number of character classes. */ + while ((c = (unsigned char)*password++) != '\0') { + if (islower(c)) + haslower = 1; + else if (isupper(c)) + hasupper = 1; + else if (isdigit(c)) + hasdigit = 1; + else if (ispunct(c)) + haspunct = 1; + else + hasspec = 1; + } + nclasses = hasupper + haslower + hasdigit + haspunct + hasspec; + if (nclasses < pol->pw_min_classes) + return KADM5_PASS_Q_CLASS; + return KADM5_OK; +} + +/* Check a password against all available password quality plugin modules + * and against policy. */ +kadm5_ret_t +passwd_check(kadm5_server_handle_t handle, const char *password, + kadm5_policy_ent_t policy, krb5_principal princ) +{ + krb5_error_code ret; + pwqual_handle *h; + const char *polname = (policy == NULL) ? NULL : policy->policy; + + if (policy != NULL) { + ret = check_against_policy(handle, password, policy); + if (ret != 0) + return ret; + } + for (h = handle->qual_handles; *h != NULL; h++) { + ret = k5_pwqual_check(handle->context, *h, password, polname, princ); + if (ret != 0) { + const char *e = krb5_get_error_message(handle->context, ret); + const char *modname = k5_pwqual_name(handle->context, *h); + char *princname; + if (krb5_unparse_name(handle->context, princ, &princname) != 0) + princname = NULL; + krb5_klog_syslog(LOG_ERR, + _("password quality module %s rejected password " + "for %s: %s"), modname, + princname ? princname : "(can't unparse)", e); + krb5_free_error_message(handle->context, e); + free(princname); + return ret; + } + } + return 0; +} + +void +destroy_pwqual(kadm5_server_handle_t handle) +{ + k5_pwqual_free_handles(handle->context, handle->qual_handles); + handle->qual_handles = NULL; +} + +kadm5_ret_t +kadm5_get_privs(void *server_handle, long *privs) +{ + CHECK_HANDLE(server_handle); + + /* this is impossible to do with the current interface. For now, + return all privs, which will confuse some clients, but not + deny any access to users of "smart" clients which try to cache */ + + *privs = ~0; + + return KADM5_OK; +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/svr_chpass_util.c b/krb5-1.21.3/src/lib/kadm5/srv/svr_chpass_util.c new file mode 100644 index 00000000..bfb66466 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/svr_chpass_util.c @@ -0,0 +1,17 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include +#include "server_internal.h" + +kadm5_ret_t kadm5_chpass_principal_util(void *server_handle, + krb5_principal princ, + char *new_pw, + char **ret_pw, + char *msg_ret, + unsigned int msg_len) +{ + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + return _kadm5_chpass_principal_util(handle, handle->lhandle, princ, + new_pw, ret_pw, msg_ret, msg_len); +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/svr_iters.c b/krb5-1.21.3/src/lib/kadm5/srv/svr_iters.c new file mode 100644 index 00000000..d5a99dea --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/svr_iters.c @@ -0,0 +1,270 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ + +#include "autoconf.h" +#if defined(HAVE_COMPILE) && defined(HAVE_STEP) +#define SOLARIS_REGEXPS +#elif defined(HAVE_REGCOMP) && defined(HAVE_REGEXEC) +#define POSIX_REGEXPS +#elif defined(HAVE_RE_COMP) && defined(HAVE_RE_EXEC) +#define BSD_REGEXPS +#else +#error I cannot find any regexp functions +#endif + +#include +#include +#include +#ifdef SOLARIS_REGEXPS +#include +#endif +#ifdef POSIX_REGEXPS +#include +#endif +#include + +#include "server_internal.h" + +struct iter_data { + krb5_context context; + char **names; + int n_names, sz_names; + unsigned int malloc_failed; + char *exp; +#ifdef SOLARIS_REGEXPS + char *expbuf; +#endif +#ifdef POSIX_REGEXPS + regex_t preg; +#endif +}; + +/* XXX Duplicated in kdb5_util! */ +/* + * Function: glob_to_regexp + * + * Arguments: + * + * glob (r) the shell-style glob (?*[]) to convert + * realm (r) the default realm to append, or NULL + * regexp (w) the ed-style regexp created from glob + * + * Effects: + * + * regexp is filled in with allocated memory contained a regular + * expression to be used with re_comp/compile that matches what the + * shell-style glob would match. If glob does not contain an "@" + * character and realm is not NULL, "@*" is appended to the regexp. + * + * Conversion algorithm: + * + * quoted characters are copied quoted + * ? is converted to . + * * is converted to .* + * active characters are quoted: ^, $, . + * [ and ] are active but supported and have the same meaning, so + * they are copied + * other characters are copied + * regexp is anchored with ^ and $ + */ +static kadm5_ret_t glob_to_regexp(char *glob, char *realm, char **regexp) +{ + int append_realm; + char *p; + + /* validate the glob */ + if (glob[strlen(glob)-1] == '\\') + return EINVAL; + + /* A character of glob can turn into two in regexp, plus ^ and $ */ + /* and trailing null. If glob has no @, also allocate space for */ + /* the realm. */ + append_realm = (realm != NULL) && (strchr(glob, '@') == NULL); + p = (char *) malloc(strlen(glob)*2+ 3 + (append_realm ? 3 : 0)); + if (p == NULL) + return ENOMEM; + *regexp = p; + + *p++ = '^'; + while (*glob) { + switch (*glob) { + case '?': + *p++ = '.'; + break; + case '*': + *p++ = '.'; + *p++ = '*'; + break; + case '.': + case '^': + case '$': + *p++ = '\\'; + *p++ = *glob; + break; + case '\\': + *p++ = '\\'; + *p++ = *++glob; + break; + default: + *p++ = *glob; + break; + } + glob++; + } + + if (append_realm) { + *p++ = '@'; + *p++ = '.'; + *p++ = '*'; + } + + *p++ = '$'; + *p++ = '\0'; + return KADM5_OK; +} + +static void get_either_iter(struct iter_data *data, char *name) +{ + int match; +#ifdef SOLARIS_REGEXPS + match = (step(name, data->expbuf) != 0); +#endif +#ifdef POSIX_REGEXPS + match = (regexec(&data->preg, name, 0, NULL, 0) == 0); +#endif +#ifdef BSD_REGEXPS + match = (re_exec(name) != 0); +#endif + if (match) { + if (data->n_names == data->sz_names) { + int new_sz = data->sz_names * 2; + char **new_names = realloc(data->names, + new_sz * sizeof(char *)); + if (new_names) { + data->names = new_names; + data->sz_names = new_sz; + } else { + data->malloc_failed = 1; + free(name); + return; + } + } + data->names[data->n_names++] = name; + } else + free(name); +} + +static void get_pols_iter(void *data, osa_policy_ent_t entry) +{ + char *name; + + if ((name = strdup(entry->name)) == NULL) + return; + get_either_iter(data, name); +} + +static void get_princs_iter(void *data, krb5_principal princ) +{ + struct iter_data *id = (struct iter_data *) data; + char *name; + + if (krb5_unparse_name(id->context, princ, &name) != 0) + return; + get_either_iter(data, name); +} + +static kadm5_ret_t kadm5_get_either(int princ, + void *server_handle, + char *exp, + char ***princs, + int *count) +{ + struct iter_data data; +#ifdef BSD_REGEXPS + char *msg; +#endif + char *regexp = NULL; + int i, ret; + kadm5_server_handle_t handle = server_handle; + + *princs = NULL; + *count = 0; + if (exp == NULL) + exp = "*"; + + CHECK_HANDLE(server_handle); + + if ((ret = glob_to_regexp(exp, princ ? handle->params.realm : NULL, + ®exp)) != KADM5_OK) + return ret; + + if ( +#ifdef SOLARIS_REGEXPS + ((data.expbuf = compile(regexp, NULL, NULL)) == NULL) +#endif +#ifdef POSIX_REGEXPS + ((regcomp(&data.preg, regexp, REG_NOSUB)) != 0) +#endif +#ifdef BSD_REGEXPS + ((msg = (char *) re_comp(regexp)) != NULL) +#endif + ) + { + /* XXX syslog msg or regerr(regerrno) */ + free(regexp); + return EINVAL; + } + + data.n_names = 0; + data.sz_names = 10; + data.malloc_failed = 0; + data.names = malloc(sizeof(char *) * data.sz_names); + if (data.names == NULL) { + free(regexp); + return ENOMEM; + } + + if (princ) { + data.context = handle->context; + ret = kdb_iter_entry(handle, exp, get_princs_iter, (void *) &data); + } else { + ret = krb5_db_iter_policy(handle->context, exp, get_pols_iter, (void *)&data); + } + + free(regexp); +#ifdef POSIX_REGEXPS + regfree(&data.preg); +#endif + if ( !ret && data.malloc_failed) + ret = ENOMEM; + if ( ret ) { + for (i = 0; i < data.n_names; i++) + free(data.names[i]); + free(data.names); + return ret; + } + + *princs = data.names; + *count = data.n_names; + return KADM5_OK; +} + +kadm5_ret_t kadm5_get_principals(void *server_handle, + char *exp, + char ***princs, + int *count) +{ + return kadm5_get_either(1, server_handle, exp, princs, count); +} + +kadm5_ret_t kadm5_get_policies(void *server_handle, + char *exp, + char ***pols, + int *count) +{ + return kadm5_get_either(0, server_handle, exp, pols, count); +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/svr_policy.c b/krb5-1.21.3/src/lib/kadm5/srv/svr_policy.c new file mode 100644 index 00000000..9569e247 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/svr_policy.c @@ -0,0 +1,427 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ + +#include +#include +#include "server_internal.h" +#include +#include +#include + +#define MIN_PW_HISTORY 1 +#define MIN_PW_CLASSES 1 +#define MAX_PW_CLASSES 5 +#define MIN_PW_LENGTH 1 + +/* Validate allowed_keysalts. */ +static kadm5_ret_t +validate_allowed_keysalts(const char *allowed_keysalts) +{ + kadm5_ret_t ret; + krb5_key_salt_tuple *ks_tuple = NULL; + krb5_int32 n_ks_tuple = 0; + + if (strchr(allowed_keysalts, '\t') != NULL) + return KADM5_BAD_KEYSALTS; + ret = krb5_string_to_keysalts(allowed_keysalts, ",", NULL, 0, + &ks_tuple, &n_ks_tuple); + free(ks_tuple); + if (ret == EINVAL) + return KADM5_BAD_KEYSALTS; + return ret; +} + +/* + * Function: kadm5_create_policy + * + * Purpose: Create Policies in the policy DB. + * + * Arguments: + * entry (input) The policy entry to be written out to the DB. + * mask (input) Specifies which fields in entry are to ge written out + * and which get default values. + * 0 if successful otherwise an error code is returned. + * + * Requires: + * Entry must be a valid principal entry, and mask have a valid value. + * + * Effects: + * Writes the data to the database, and does a database sync if + * successful. + * + */ + +kadm5_ret_t +kadm5_create_policy(void *server_handle, kadm5_policy_ent_t entry, long mask) +{ + kadm5_server_handle_t handle = server_handle; + osa_policy_ent_rec pent, *check_pol; + int ret; + char *p; + + CHECK_HANDLE(server_handle); + + krb5_clear_error_message(handle->context); + + if ((entry == (kadm5_policy_ent_t) NULL) || (entry->policy == NULL)) + return EINVAL; + if(strlen(entry->policy) == 0) + return KADM5_BAD_POLICY; + if (!(mask & KADM5_POLICY) || (mask & ~ALL_POLICY_MASK)) + return KADM5_BAD_MASK; + if ((mask & KADM5_POLICY_ALLOWED_KEYSALTS) && + entry->allowed_keysalts != NULL) { + ret = validate_allowed_keysalts(entry->allowed_keysalts); + if (ret) + return ret; + } + + ret = krb5_db_get_policy(handle->context, entry->policy, &check_pol); + if (!ret) { + krb5_db_free_policy(handle->context, check_pol); + return KADM5_DUP; + } else if (ret != KRB5_KDB_NOENTRY) { + return ret; + } + + memset(&pent, 0, sizeof(pent)); + pent.name = entry->policy; + p = entry->policy; + while(*p != '\0') { + if(*p < ' ' || *p > '~') + return KADM5_BAD_POLICY; + else + p++; + } + if (!(mask & KADM5_PW_MAX_LIFE)) + pent.pw_max_life = 0; + else + pent.pw_max_life = entry->pw_max_life; + if (!(mask & KADM5_PW_MIN_LIFE)) + pent.pw_min_life = 0; + else { + if((mask & KADM5_PW_MAX_LIFE)) { + if(entry->pw_min_life > entry->pw_max_life && entry->pw_max_life != 0) + return KADM5_BAD_MIN_PASS_LIFE; + } + pent.pw_min_life = entry->pw_min_life; + } + if (!(mask & KADM5_PW_MIN_LENGTH)) + pent.pw_min_length = MIN_PW_LENGTH; + else { + if(entry->pw_min_length < MIN_PW_LENGTH) + return KADM5_BAD_LENGTH; + pent.pw_min_length = entry->pw_min_length; + } + if (!(mask & KADM5_PW_MIN_CLASSES)) + pent.pw_min_classes = MIN_PW_CLASSES; + else { + if(entry->pw_min_classes > MAX_PW_CLASSES || entry->pw_min_classes < MIN_PW_CLASSES) + return KADM5_BAD_CLASS; + pent.pw_min_classes = entry->pw_min_classes; + } + if (!(mask & KADM5_PW_HISTORY_NUM)) + pent.pw_history_num = MIN_PW_HISTORY; + else { + if(entry->pw_history_num < MIN_PW_HISTORY) + return KADM5_BAD_HISTORY; + else + pent.pw_history_num = entry->pw_history_num; + } + + if (handle->api_version >= KADM5_API_VERSION_4) { + if (!(mask & KADM5_POLICY_ATTRIBUTES)) + pent.attributes = 0; + else + pent.attributes = entry->attributes; + if (!(mask & KADM5_POLICY_MAX_LIFE)) + pent.max_life = 0; + else + pent.max_life = entry->max_life; + if (!(mask & KADM5_POLICY_MAX_RLIFE)) + pent.max_renewable_life = 0; + else + pent.max_renewable_life = entry->max_renewable_life; + if (!(mask & KADM5_POLICY_ALLOWED_KEYSALTS)) + pent.allowed_keysalts = 0; + else + pent.allowed_keysalts = entry->allowed_keysalts; + if (!(mask & KADM5_POLICY_TL_DATA)) { + pent.n_tl_data = 0; + pent.tl_data = NULL; + } else { + pent.n_tl_data = entry->n_tl_data; + pent.tl_data = entry->tl_data; + } + } + if (handle->api_version >= KADM5_API_VERSION_3) { + if (!(mask & KADM5_PW_MAX_FAILURE)) + pent.pw_max_fail = 0; + else + pent.pw_max_fail = entry->pw_max_fail; + if (!(mask & KADM5_PW_FAILURE_COUNT_INTERVAL)) + pent.pw_failcnt_interval = 0; + else + pent.pw_failcnt_interval = entry->pw_failcnt_interval; + if (!(mask & KADM5_PW_LOCKOUT_DURATION)) + pent.pw_lockout_duration = 0; + else + pent.pw_lockout_duration = entry->pw_lockout_duration; + } + + if ((ret = krb5_db_create_policy(handle->context, &pent))) + return ret; + else + return KADM5_OK; +} + +kadm5_ret_t +kadm5_delete_policy(void *server_handle, kadm5_policy_t name) +{ + kadm5_server_handle_t handle = server_handle; + osa_policy_ent_t entry; + int ret; + + CHECK_HANDLE(server_handle); + + krb5_clear_error_message(handle->context); + + if(name == (kadm5_policy_t) NULL) + return EINVAL; + if(strlen(name) == 0) + return KADM5_BAD_POLICY; + ret = krb5_db_get_policy(handle->context, name, &entry); + if (ret == KRB5_KDB_NOENTRY) + return KADM5_UNK_POLICY; + else if (ret) + return ret; + + krb5_db_free_policy(handle->context, entry); + ret = krb5_db_delete_policy(handle->context, name); + if (ret == KRB5_KDB_POLICY_REF) + ret = KADM5_POLICY_REF; + return (ret == 0) ? KADM5_OK : ret; +} + +/* Allocate and form a TL data list of a desired size. */ +static int +alloc_tl_data(krb5_int16 n_tl_data, krb5_tl_data **tldp) +{ + krb5_tl_data **tlp = tldp; + int i; + + for (i = 0; i < n_tl_data; i++) { + *tlp = calloc(1, sizeof(krb5_tl_data)); + if (*tlp == NULL) + return ENOMEM; /* caller cleans up */ + memset(*tlp, 0, sizeof(krb5_tl_data)); + tlp = &((*tlp)->tl_data_next); + } + + return 0; +} + +static kadm5_ret_t +copy_tl_data(krb5_int16 n_tl_data, krb5_tl_data *tl_data, + krb5_tl_data **out) +{ + kadm5_ret_t ret; + krb5_tl_data *tl, *tl_new; + + if ((ret = alloc_tl_data(n_tl_data, out))) + return ret; /* caller cleans up */ + + tl = tl_data; + tl_new = *out; + for (; tl; tl = tl->tl_data_next, tl_new = tl_new->tl_data_next) { + tl_new->tl_data_contents = malloc(tl->tl_data_length); + if (tl_new->tl_data_contents == NULL) + return ENOMEM; + memcpy(tl_new->tl_data_contents, tl->tl_data_contents, + tl->tl_data_length); + tl_new->tl_data_type = tl->tl_data_type; + tl_new->tl_data_length = tl->tl_data_length; + } + + return 0; +} + +kadm5_ret_t +kadm5_modify_policy(void *server_handle, kadm5_policy_ent_t entry, long mask) +{ + kadm5_server_handle_t handle = server_handle; + krb5_tl_data *tl; + osa_policy_ent_t p; + int ret; + + CHECK_HANDLE(server_handle); + + krb5_clear_error_message(handle->context); + + if((entry == (kadm5_policy_ent_t) NULL) || (entry->policy == NULL)) + return EINVAL; + if(strlen(entry->policy) == 0) + return KADM5_BAD_POLICY; + if ((mask & KADM5_POLICY) || (mask & ~ALL_POLICY_MASK)) + return KADM5_BAD_MASK; + if ((mask & KADM5_POLICY_ALLOWED_KEYSALTS) && + entry->allowed_keysalts != NULL) { + ret = validate_allowed_keysalts(entry->allowed_keysalts); + if (ret) + return ret; + } + if ((mask & KADM5_POLICY_TL_DATA)) { + tl = entry->tl_data; + while (tl != NULL) { + if (tl->tl_data_type < 256) + return KADM5_BAD_TL_TYPE; + tl = tl->tl_data_next; + } + } + + ret = krb5_db_get_policy(handle->context, entry->policy, &p); + if (ret == KRB5_KDB_NOENTRY) + return KADM5_UNK_POLICY; + else if (ret) + return ret; + + if ((mask & KADM5_PW_MAX_LIFE)) + p->pw_max_life = entry->pw_max_life; + if ((mask & KADM5_PW_MIN_LIFE)) { + if(entry->pw_min_life > p->pw_max_life && p->pw_max_life != 0) { + krb5_db_free_policy(handle->context, p); + return KADM5_BAD_MIN_PASS_LIFE; + } + p->pw_min_life = entry->pw_min_life; + } + if ((mask & KADM5_PW_MIN_LENGTH)) { + if(entry->pw_min_length < MIN_PW_LENGTH) { + krb5_db_free_policy(handle->context, p); + return KADM5_BAD_LENGTH; + } + p->pw_min_length = entry->pw_min_length; + } + if ((mask & KADM5_PW_MIN_CLASSES)) { + if(entry->pw_min_classes > MAX_PW_CLASSES || + entry->pw_min_classes < MIN_PW_CLASSES) { + krb5_db_free_policy(handle->context, p); + return KADM5_BAD_CLASS; + } + p->pw_min_classes = entry->pw_min_classes; + } + if ((mask & KADM5_PW_HISTORY_NUM)) { + if(entry->pw_history_num < MIN_PW_HISTORY) { + krb5_db_free_policy(handle->context, p); + return KADM5_BAD_HISTORY; + } + p->pw_history_num = entry->pw_history_num; + } + if (handle->api_version >= KADM5_API_VERSION_3) { + if ((mask & KADM5_PW_MAX_FAILURE)) + p->pw_max_fail = entry->pw_max_fail; + if ((mask & KADM5_PW_FAILURE_COUNT_INTERVAL)) + p->pw_failcnt_interval = entry->pw_failcnt_interval; + if ((mask & KADM5_PW_LOCKOUT_DURATION)) + p->pw_lockout_duration = entry->pw_lockout_duration; + } + if (handle->api_version >= KADM5_API_VERSION_4) { + if ((mask & KADM5_POLICY_ATTRIBUTES)) + p->attributes = entry->attributes; + if ((mask & KADM5_POLICY_MAX_LIFE)) + p->max_life = entry->max_life; + if ((mask & KADM5_POLICY_MAX_RLIFE)) + p->max_renewable_life = entry->max_renewable_life; + if ((mask & KADM5_POLICY_ALLOWED_KEYSALTS)) { + free(p->allowed_keysalts); + p->allowed_keysalts = NULL; + if (entry->allowed_keysalts != NULL) { + p->allowed_keysalts = strdup(entry->allowed_keysalts); + if (p->allowed_keysalts == NULL) { + ret = ENOMEM; + goto cleanup; + } + } + } + if ((mask & KADM5_POLICY_TL_DATA)) { + for (tl = entry->tl_data; tl != NULL; tl = tl->tl_data_next) { + ret = krb5_db_update_tl_data(handle->context, &p->n_tl_data, + &p->tl_data, tl); + if (ret) + goto cleanup; + } + } + } + ret = krb5_db_put_policy(handle->context, p); + +cleanup: + krb5_db_free_policy(handle->context, p); + return ret; +} + +kadm5_ret_t +kadm5_get_policy(void *server_handle, kadm5_policy_t name, + kadm5_policy_ent_t entry) +{ + osa_policy_ent_t t; + kadm5_ret_t ret; + kadm5_server_handle_t handle = server_handle; + + memset(entry, 0, sizeof(*entry)); + + CHECK_HANDLE(server_handle); + + krb5_clear_error_message(handle->context); + + if (name == (kadm5_policy_t) NULL) + return EINVAL; + if(strlen(name) == 0) + return KADM5_BAD_POLICY; + ret = krb5_db_get_policy(handle->context, name, &t); + if (ret == KRB5_KDB_NOENTRY) + return KADM5_UNK_POLICY; + else if (ret) + return ret; + + if ((entry->policy = strdup(t->name)) == NULL) { + ret = ENOMEM; + goto cleanup; + } + entry->pw_min_life = t->pw_min_life; + entry->pw_max_life = t->pw_max_life; + entry->pw_min_length = t->pw_min_length; + entry->pw_min_classes = t->pw_min_classes; + entry->pw_history_num = t->pw_history_num; + if (handle->api_version >= KADM5_API_VERSION_3) { + entry->pw_max_fail = t->pw_max_fail; + entry->pw_failcnt_interval = t->pw_failcnt_interval; + entry->pw_lockout_duration = t->pw_lockout_duration; + } + if (handle->api_version >= KADM5_API_VERSION_4) { + entry->attributes = t->attributes; + entry->max_life = t->max_life; + entry->max_renewable_life = t->max_renewable_life; + if (t->allowed_keysalts) { + entry->allowed_keysalts = strdup(t->allowed_keysalts); + if (!entry->allowed_keysalts) { + ret = ENOMEM; + goto cleanup; + } + } + ret = copy_tl_data(t->n_tl_data, t->tl_data, &entry->tl_data); + if (ret) + goto cleanup; + entry->n_tl_data = t->n_tl_data; + } + + ret = 0; + +cleanup: + if (ret) + kadm5_free_policy_ent(handle, entry); + krb5_db_free_policy(handle->context, t); + return ret; +} diff --git a/krb5-1.21.3/src/lib/kadm5/srv/svr_principal.c b/krb5-1.21.3/src/lib/kadm5/srv/svr_principal.c new file mode 100644 index 00000000..8c3ad3a6 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/srv/svr_principal.c @@ -0,0 +1,2058 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved + * + * $Header$ + */ +#include "k5-int.h" +#include +#include +#include +#include "server_internal.h" + +#include + +#ifdef USE_VALGRIND +#include +#else +#define VALGRIND_CHECK_DEFINED(LVALUE) ((void)0) +#endif + +extern krb5_principal master_princ; +extern krb5_principal hist_princ; +extern krb5_keyblock master_keyblock; +extern krb5_db_entry master_db; + +static int decrypt_key_data(krb5_context context, + int n_key_data, krb5_key_data *key_data, + krb5_keyblock **keyblocks, int *n_keys); + +/* + * XXX Functions that ought to be in libkrb5.a, but aren't. + */ +kadm5_ret_t krb5_copy_key_data_contents(context, from, to) + krb5_context context; + krb5_key_data *from, *to; +{ + int i, idx; + + *to = *from; + + idx = (from->key_data_ver == 1 ? 1 : 2); + + for (i = 0; i < idx; i++) { + if ( from->key_data_length[i] ) { + to->key_data_contents[i] = malloc(from->key_data_length[i]); + if (to->key_data_contents[i] == NULL) { + for (i = 0; i < idx; i++) + zapfree(to->key_data_contents[i], to->key_data_length[i]); + return ENOMEM; + } + memcpy(to->key_data_contents[i], from->key_data_contents[i], + from->key_data_length[i]); + } + } + return 0; +} + +static krb5_tl_data *dup_tl_data(krb5_tl_data *tl) +{ + krb5_tl_data *n; + + n = (krb5_tl_data *) malloc(sizeof(krb5_tl_data)); + if (n == NULL) + return NULL; + n->tl_data_contents = malloc(tl->tl_data_length); + if (n->tl_data_contents == NULL) { + free(n); + return NULL; + } + memcpy(n->tl_data_contents, tl->tl_data_contents, tl->tl_data_length); + n->tl_data_type = tl->tl_data_type; + n->tl_data_length = tl->tl_data_length; + n->tl_data_next = NULL; + return n; +} + +/* This is in lib/kdb/kdb_cpw.c, but is static */ +static void cleanup_key_data(context, count, data) + krb5_context context; + int count; + krb5_key_data * data; +{ + int i; + + for (i = 0; i < count; i++) + krb5_free_key_data_contents(context, &data[i]); + free(data); +} + +/* Check whether a ks_tuple is present in an array of ks_tuples. */ +static krb5_boolean +ks_tuple_present(int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, + krb5_key_salt_tuple *looking_for) +{ + int i; + + for (i = 0; i < n_ks_tuple; i++) { + if (ks_tuple[i].ks_enctype == looking_for->ks_enctype && + ks_tuple[i].ks_salttype == looking_for->ks_salttype) + return TRUE; + } + return FALSE; +} + +/* Fetch a policy if it exists; set *have_pol_out appropriately. Return + * success whether or not the policy exists. */ +static kadm5_ret_t +get_policy(kadm5_server_handle_t handle, const char *name, + kadm5_policy_ent_t policy_out, krb5_boolean *have_pol_out) +{ + kadm5_ret_t ret; + + *have_pol_out = FALSE; + if (name == NULL) + return 0; + ret = kadm5_get_policy(handle->lhandle, (char *)name, policy_out); + if (ret == 0) + *have_pol_out = TRUE; + return (ret == KADM5_UNK_POLICY) ? 0 : ret; +} + +/* + * Apply the -allowedkeysalts policy (see kadmin(1)'s addpol/modpol + * commands). We use the allowed key/salt tuple list as a default if + * no ks tuples as provided by the caller. We reject lists that include + * key/salts outside the policy. We re-order the requested ks tuples + * (which may be a subset of the policy) to reflect the policy order. + */ +static kadm5_ret_t +apply_keysalt_policy(kadm5_server_handle_t handle, const char *policy, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, + int *new_n_kstp, krb5_key_salt_tuple **new_kstp) +{ + kadm5_ret_t ret; + kadm5_policy_ent_rec polent; + krb5_boolean have_polent; + int ak_n_ks_tuple = 0; + int new_n_ks_tuple = 0; + krb5_key_salt_tuple *ak_ks_tuple = NULL; + krb5_key_salt_tuple *new_ks_tuple = NULL; + krb5_key_salt_tuple *subset; + int i, m; + + if (new_n_kstp != NULL) { + *new_n_kstp = 0; + *new_kstp = NULL; + } + + memset(&polent, 0, sizeof(polent)); + ret = get_policy(handle, policy, &polent, &have_polent); + if (ret) + goto cleanup; + + if (polent.allowed_keysalts == NULL) { + /* Requested keysalts allowed or default to supported_enctypes. */ + if (n_ks_tuple == 0) { + /* Default to supported_enctypes. */ + n_ks_tuple = handle->params.num_keysalts; + ks_tuple = handle->params.keysalts; + } + /* Dup the requested or defaulted keysalt tuples. */ + new_ks_tuple = malloc(n_ks_tuple * sizeof(*new_ks_tuple)); + if (new_ks_tuple == NULL) { + ret = ENOMEM; + goto cleanup; + } + memcpy(new_ks_tuple, ks_tuple, n_ks_tuple * sizeof(*new_ks_tuple)); + new_n_ks_tuple = n_ks_tuple; + ret = 0; + goto cleanup; + } + + ret = krb5_string_to_keysalts(polent.allowed_keysalts, + ",", /* Tuple separators */ + NULL, /* Key/salt separators */ + 0, /* No duplicates */ + &ak_ks_tuple, + &ak_n_ks_tuple); + /* + * Malformed policy? Shouldn't happen, but it's remotely possible + * someday, so we don't assert, just bail. + */ + if (ret) + goto cleanup; + + /* Check that the requested ks_tuples are within policy, if we have one. */ + for (i = 0; i < n_ks_tuple; i++) { + if (!ks_tuple_present(ak_n_ks_tuple, ak_ks_tuple, &ks_tuple[i])) { + ret = KADM5_BAD_KEYSALTS; + goto cleanup; + } + } + + /* Have policy but no ks_tuple input? Output the policy. */ + if (n_ks_tuple == 0) { + new_n_ks_tuple = ak_n_ks_tuple; + new_ks_tuple = ak_ks_tuple; + ak_ks_tuple = NULL; + goto cleanup; + } + + /* + * Now filter the policy ks tuples by the requested ones so as to + * preserve in the requested sub-set the relative ordering from the + * policy. We could optimize this (if (n_ks_tuple == ak_n_ks_tuple) + * then skip this), but we don't bother. + */ + subset = calloc(n_ks_tuple, sizeof(*subset)); + if (subset == NULL) { + ret = ENOMEM; + goto cleanup; + } + for (m = 0, i = 0; i < ak_n_ks_tuple && m < n_ks_tuple; i++) { + if (ks_tuple_present(n_ks_tuple, ks_tuple, &ak_ks_tuple[i])) + subset[m++] = ak_ks_tuple[i]; + } + new_ks_tuple = subset; + new_n_ks_tuple = m; + ret = 0; + +cleanup: + if (have_polent) + kadm5_free_policy_ent(handle->lhandle, &polent); + free(ak_ks_tuple); + + if (new_n_kstp != NULL) { + *new_n_kstp = new_n_ks_tuple; + *new_kstp = new_ks_tuple; + } else { + free(new_ks_tuple); + } + return ret; +} + + +/* + * Set *passptr to NULL if the request looks like the first part of a krb5 1.6 + * addprinc -randkey operation. The krb5 1.6 dummy password for these requests + * was invalid UTF-8, which runs afoul of the arcfour string-to-key. + */ +static void +check_1_6_dummy(kadm5_principal_ent_t entry, long mask, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, char **passptr) +{ + int i; + char *password = *passptr; + + /* Old-style randkey operations disallowed tickets to start. */ + if (password == NULL || !(mask & KADM5_ATTRIBUTES) || + !(entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX)) + return; + + /* The 1.6 dummy password was the octets 1..255. */ + for (i = 0; (unsigned char) password[i] == i + 1; i++); + if (password[i] != '\0' || i != 255) + return; + + /* This will make the caller use a random password instead. */ + *passptr = NULL; +} + +/* Return the number of keys with the newest kvno. Assumes that all key data + * with the newest kvno are at the front of the key data array. */ +static int +count_new_keys(int n_key_data, krb5_key_data *key_data) +{ + int n; + + for (n = 1; n < n_key_data; n++) { + if (key_data[n - 1].key_data_kvno != key_data[n].key_data_kvno) + return n; + } + return n_key_data; +} + +kadm5_ret_t +kadm5_create_principal(void *server_handle, + kadm5_principal_ent_t entry, long mask, + char *password) +{ + return + kadm5_create_principal_3(server_handle, entry, mask, + 0, NULL, password); +} +kadm5_ret_t +kadm5_create_principal_3(void *server_handle, + kadm5_principal_ent_t entry, long mask, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, + char *password) +{ + krb5_db_entry *kdb; + osa_princ_ent_rec adb; + kadm5_policy_ent_rec polent; + krb5_boolean have_polent = FALSE; + krb5_timestamp now; + krb5_tl_data *tl_data_tail; + unsigned int ret; + kadm5_server_handle_t handle = server_handle; + krb5_keyblock *act_mkey; + krb5_kvno act_kvno; + int new_n_ks_tuple = 0, i; + krb5_key_salt_tuple *new_ks_tuple = NULL; + + CHECK_HANDLE(server_handle); + + krb5_clear_error_message(handle->context); + + check_1_6_dummy(entry, mask, n_ks_tuple, ks_tuple, &password); + + /* + * Argument sanity checking, and opening up the DB + */ + if (entry == NULL) + return EINVAL; + if(!(mask & KADM5_PRINCIPAL) || (mask & KADM5_MOD_NAME) || + (mask & KADM5_MOD_TIME) || (mask & KADM5_LAST_PWD_CHANGE) || + (mask & KADM5_MKVNO) || (mask & KADM5_AUX_ATTRIBUTES) || + (mask & KADM5_LAST_SUCCESS) || (mask & KADM5_LAST_FAILED) || + (mask & KADM5_FAIL_AUTH_COUNT)) + return KADM5_BAD_MASK; + if ((mask & KADM5_KEY_DATA) && entry->n_key_data != 0) + return KADM5_BAD_MASK; + if((mask & KADM5_POLICY) && entry->policy == NULL) + return KADM5_BAD_MASK; + if((mask & KADM5_POLICY) && (mask & KADM5_POLICY_CLR)) + return KADM5_BAD_MASK; + if((mask & ~ALL_PRINC_MASK)) + return KADM5_BAD_MASK; + if (mask & KADM5_TL_DATA) { + for (tl_data_tail = entry->tl_data; tl_data_tail != NULL; + tl_data_tail = tl_data_tail->tl_data_next) { + if (tl_data_tail->tl_data_type < 256) + return KADM5_BAD_TL_TYPE; + } + } + + /* + * Check to see if the principal exists + */ + ret = kdb_get_entry(handle, entry->principal, &kdb, &adb); + + switch(ret) { + case KADM5_UNK_PRINC: + break; + case 0: + kdb_free_entry(handle, kdb, &adb); + return KADM5_DUP; + default: + return ret; + } + + kdb = calloc(1, sizeof(*kdb)); + if (kdb == NULL) + return ENOMEM; + + /* In all cases the principal entry is new and key data is set; let the + * database provider know. */ + kdb->mask = mask | KADM5_KEY_DATA | KADM5_PRINCIPAL; + + memset(&adb, 0, sizeof(osa_princ_ent_rec)); + + /* + * If a policy was specified, load it. + * If we can not find the one specified return an error + */ + if ((mask & KADM5_POLICY)) { + ret = get_policy(handle, entry->policy, &polent, &have_polent); + if (ret) + goto cleanup; + } + if (password) { + ret = passwd_check(handle, password, have_polent ? &polent : NULL, + entry->principal); + if (ret) + goto cleanup; + } + /* + * Start populating the various DB fields, using the + * "defaults" for fields that were not specified by the + * mask. + */ + if ((ret = krb5_timeofday(handle->context, &now))) + goto cleanup; + + kdb->magic = KRB5_KDB_MAGIC_NUMBER; + kdb->len = KRB5_KDB_V1_BASE_LENGTH; /* gag me with a chainsaw */ + + if ((mask & KADM5_ATTRIBUTES)) + kdb->attributes = entry->attributes; + else + kdb->attributes = handle->params.flags; + + if ((mask & KADM5_MAX_LIFE)) + kdb->max_life = entry->max_life; + else + kdb->max_life = handle->params.max_life; + + if (mask & KADM5_MAX_RLIFE) + kdb->max_renewable_life = entry->max_renewable_life; + else + kdb->max_renewable_life = handle->params.max_rlife; + + if ((mask & KADM5_PRINC_EXPIRE_TIME)) + kdb->expiration = entry->princ_expire_time; + else + kdb->expiration = handle->params.expiration; + + kdb->pw_expiration = 0; + if (mask & KADM5_PW_EXPIRATION) { + kdb->pw_expiration = entry->pw_expiration; + } else if (have_polent && polent.pw_max_life) { + kdb->mask |= KADM5_PW_EXPIRATION; + kdb->pw_expiration = ts_incr(now, polent.pw_max_life); + } + + kdb->last_success = 0; + kdb->last_failed = 0; + kdb->fail_auth_count = 0; + + /* this is kind of gross, but in order to free the tl data, I need + to free the entire kdb entry, and that will try to free the + principal. */ + + ret = krb5_copy_principal(handle->context, entry->principal, &kdb->princ); + if (ret) + goto cleanup; + + if ((ret = krb5_dbe_update_last_pwd_change(handle->context, kdb, now))) + goto cleanup; + + if (mask & KADM5_TL_DATA) { + /* splice entry->tl_data onto the front of kdb->tl_data */ + for (tl_data_tail = entry->tl_data; tl_data_tail; + tl_data_tail = tl_data_tail->tl_data_next) + { + ret = krb5_dbe_update_tl_data(handle->context, kdb, tl_data_tail); + if( ret ) + goto cleanup; + } + } + + /* + * We need to have setup the TL data, so we have strings, so we can + * check enctype policy, which is why we check/initialize ks_tuple + * this late. + */ + ret = apply_keysalt_policy(handle, entry->policy, n_ks_tuple, ks_tuple, + &new_n_ks_tuple, &new_ks_tuple); + if (ret) + goto cleanup; + + /* initialize the keys */ + + ret = kdb_get_active_mkey(handle, &act_kvno, &act_mkey); + if (ret) + goto cleanup; + + if (mask & KADM5_KEY_DATA) { + /* The client requested no keys for this principal. */ + assert(entry->n_key_data == 0); + } else if (password) { + ret = krb5_dbe_cpw(handle->context, act_mkey, new_ks_tuple, + new_n_ks_tuple, password, + (mask & KADM5_KVNO)?entry->kvno:1, + FALSE, kdb); + } else { + /* Null password means create with random key (new in 1.8). */ + ret = krb5_dbe_crk(handle->context, &master_keyblock, + new_ks_tuple, new_n_ks_tuple, FALSE, kdb); + if (mask & KADM5_KVNO) { + for (i = 0; i < kdb->n_key_data; i++) + kdb->key_data[i].key_data_kvno = entry->kvno; + } + } + if (ret) + goto cleanup; + + /* Record the master key VNO used to encrypt this entry's keys */ + ret = krb5_dbe_update_mkvno(handle->context, kdb, act_kvno); + if (ret) + goto cleanup; + + ret = k5_kadm5_hook_create(handle->context, handle->hook_handles, + KADM5_HOOK_STAGE_PRECOMMIT, entry, mask, + new_n_ks_tuple, new_ks_tuple, password); + if (ret) + goto cleanup; + + /* populate the admin-server-specific fields. In the OV server, + this used to be in a separate database. Since there's already + marshalling code for the admin fields, to keep things simple, + I'm going to keep it, and make all the admin stuff occupy a + single tl_data record, */ + + adb.admin_history_kvno = INITIAL_HIST_KVNO; + if (mask & KADM5_POLICY) { + adb.aux_attributes = KADM5_POLICY; + + /* this does *not* need to be strdup'ed, because adb is xdr */ + /* encoded in osa_adb_create_princ, and not ever freed */ + + adb.policy = entry->policy; + } + + /* store the new db entry */ + ret = kdb_put_entry(handle, kdb, &adb); + + (void) k5_kadm5_hook_create(handle->context, handle->hook_handles, + KADM5_HOOK_STAGE_POSTCOMMIT, entry, mask, + new_n_ks_tuple, new_ks_tuple, password); + +cleanup: + free(new_ks_tuple); + krb5_db_free_principal(handle->context, kdb); + if (have_polent) + (void) kadm5_free_policy_ent(handle->lhandle, &polent); + return ret; +} + + +kadm5_ret_t +kadm5_delete_principal(void *server_handle, krb5_principal principal) +{ + unsigned int ret; + krb5_db_entry *kdb; + osa_princ_ent_rec adb; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + krb5_clear_error_message(handle->context); + + if (principal == NULL) + return EINVAL; + + /* Deleting K/M is mostly unrecoverable, so don't allow it. */ + if (krb5_principal_compare(handle->context, principal, master_princ)) + return KADM5_PROTECT_PRINCIPAL; + + if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) + return(ret); + ret = k5_kadm5_hook_remove(handle->context, handle->hook_handles, + KADM5_HOOK_STAGE_PRECOMMIT, principal); + if (ret) { + kdb_free_entry(handle, kdb, &adb); + return ret; + } + + ret = kdb_delete_entry(handle, principal); + + kdb_free_entry(handle, kdb, &adb); + + if (ret == 0) + (void) k5_kadm5_hook_remove(handle->context, + handle->hook_handles, + KADM5_HOOK_STAGE_POSTCOMMIT, principal); + + return ret; +} + +kadm5_ret_t +kadm5_modify_principal(void *server_handle, + kadm5_principal_ent_t entry, long mask) +{ + int ret, ret2, i; + kadm5_policy_ent_rec pol; + krb5_boolean have_pol = FALSE; + krb5_db_entry *kdb; + krb5_tl_data *tl_data_orig; + osa_princ_ent_rec adb; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + krb5_clear_error_message(handle->context); + + if(entry == NULL) + return EINVAL; + if((mask & KADM5_PRINCIPAL) || (mask & KADM5_LAST_PWD_CHANGE) || + (mask & KADM5_MOD_TIME) || (mask & KADM5_MOD_NAME) || + (mask & KADM5_MKVNO) || (mask & KADM5_AUX_ATTRIBUTES) || + (mask & KADM5_KEY_DATA) || (mask & KADM5_LAST_SUCCESS) || + (mask & KADM5_LAST_FAILED)) + return KADM5_BAD_MASK; + if((mask & ~ALL_PRINC_MASK)) + return KADM5_BAD_MASK; + if((mask & KADM5_POLICY) && entry->policy == NULL) + return KADM5_BAD_MASK; + if((mask & KADM5_POLICY) && (mask & KADM5_POLICY_CLR)) + return KADM5_BAD_MASK; + if (mask & KADM5_TL_DATA) { + tl_data_orig = entry->tl_data; + while (tl_data_orig) { + if (tl_data_orig->tl_data_type < 256) + return KADM5_BAD_TL_TYPE; + tl_data_orig = tl_data_orig->tl_data_next; + } + } + + ret = kdb_get_entry(handle, entry->principal, &kdb, &adb); + if (ret) + return(ret); + + /* Let the mask propagate to the database provider. */ + kdb->mask = mask; + + /* + * This is pretty much the same as create ... + */ + + if ((mask & KADM5_POLICY)) { + ret = get_policy(handle, entry->policy, &pol, &have_pol); + if (ret) + goto done; + + /* set us up to use the new policy */ + adb.aux_attributes |= KADM5_POLICY; + if (adb.policy) + free(adb.policy); + adb.policy = strdup(entry->policy); + } + + if (mask & KADM5_PW_EXPIRATION) { + kdb->pw_expiration = entry->pw_expiration; + } else if (have_pol) { + /* set pw_max_life based on new policy */ + kdb->mask |= KADM5_PW_EXPIRATION; + if (pol.pw_max_life) { + ret = krb5_dbe_lookup_last_pwd_change(handle->context, kdb, + &kdb->pw_expiration); + if (ret) + goto done; + kdb->pw_expiration = ts_incr(kdb->pw_expiration, pol.pw_max_life); + } else { + kdb->pw_expiration = 0; + } + } + + if ((mask & KADM5_POLICY_CLR) && (adb.aux_attributes & KADM5_POLICY)) { + free(adb.policy); + adb.policy = NULL; + adb.aux_attributes &= ~KADM5_POLICY; + kdb->pw_expiration = 0; + } + + if ((mask & KADM5_ATTRIBUTES)) + kdb->attributes = entry->attributes; + if ((mask & KADM5_MAX_LIFE)) + kdb->max_life = entry->max_life; + if ((mask & KADM5_PRINC_EXPIRE_TIME)) + kdb->expiration = entry->princ_expire_time; + if (mask & KADM5_MAX_RLIFE) + kdb->max_renewable_life = entry->max_renewable_life; + + if((mask & KADM5_KVNO)) { + for (i = 0; i < kdb->n_key_data; i++) + kdb->key_data[i].key_data_kvno = entry->kvno; + } + + if (mask & KADM5_TL_DATA) { + krb5_tl_data *tl; + + /* may have to change the version number of the API. Updates the list with the given tl_data rather than over-writing */ + + for (tl = entry->tl_data; tl; + tl = tl->tl_data_next) + { + ret = krb5_dbe_update_tl_data(handle->context, kdb, tl); + if( ret ) + { + goto done; + } + } + } + + /* + * Setting entry->fail_auth_count to 0 can be used to manually unlock + * an account. It is not possible to set fail_auth_count to any other + * value using kadmin. + */ + if (mask & KADM5_FAIL_AUTH_COUNT) { + if (entry->fail_auth_count != 0) { + ret = KADM5_BAD_SERVER_PARAMS; + goto done; + } + + kdb->fail_auth_count = 0; + } + + ret = k5_kadm5_hook_modify(handle->context, handle->hook_handles, + KADM5_HOOK_STAGE_PRECOMMIT, entry, mask); + if (ret) + goto done; + + ret = kdb_put_entry(handle, kdb, &adb); + if (ret) goto done; + (void) k5_kadm5_hook_modify(handle->context, handle->hook_handles, + KADM5_HOOK_STAGE_POSTCOMMIT, entry, mask); + + ret = KADM5_OK; +done: + if (have_pol) { + ret2 = kadm5_free_policy_ent(handle->lhandle, &pol); + ret = ret ? ret : ret2; + } + kdb_free_entry(handle, kdb, &adb); + return ret; +} + +kadm5_ret_t +kadm5_rename_principal(void *server_handle, + krb5_principal source, krb5_principal target) +{ + krb5_db_entry *kdb; + osa_princ_ent_rec adb; + krb5_error_code ret; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + krb5_clear_error_message(handle->context); + + if (source == NULL || target == NULL) + return EINVAL; + + if ((ret = kdb_get_entry(handle, target, &kdb, &adb)) == 0) { + kdb_free_entry(handle, kdb, &adb); + return(KADM5_DUP); + } + + ret = k5_kadm5_hook_rename(handle->context, handle->hook_handles, + KADM5_HOOK_STAGE_PRECOMMIT, source, target); + if (ret) + return ret; + + ret = krb5_db_rename_principal(handle->context, source, target); + if (ret) + return ret; + + /* Update the principal mod data. */ + ret = kdb_get_entry(handle, target, &kdb, &adb); + if (ret) + return ret; + kdb->mask = 0; + ret = kdb_put_entry(handle, kdb, &adb); + kdb_free_entry(handle, kdb, &adb); + if (ret) + return ret; + + (void) k5_kadm5_hook_rename(handle->context, handle->hook_handles, + KADM5_HOOK_STAGE_POSTCOMMIT, source, target); + return 0; +} + +kadm5_ret_t +kadm5_get_principal(void *server_handle, krb5_principal principal, + kadm5_principal_ent_t entry, + long in_mask) +{ + krb5_db_entry *kdb; + osa_princ_ent_rec adb; + krb5_error_code ret = 0; + long mask; + int i; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + krb5_clear_error_message(handle->context); + + /* + * In version 1, all the defined fields are always returned. + * entry is a pointer to a kadm5_principal_ent_t_v1 that should be + * filled with allocated memory. + */ + mask = in_mask; + + memset(entry, 0, sizeof(*entry)); + + if (principal == NULL) + return EINVAL; + + if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) + return ret; + + if ((mask & KADM5_POLICY) && + adb.policy && (adb.aux_attributes & KADM5_POLICY)) { + if ((entry->policy = strdup(adb.policy)) == NULL) { + ret = ENOMEM; + goto done; + } + } + + if (mask & KADM5_AUX_ATTRIBUTES) + entry->aux_attributes = adb.aux_attributes; + + if ((mask & KADM5_PRINCIPAL) && + (ret = krb5_copy_principal(handle->context, kdb->princ, + &entry->principal))) { + goto done; + } + + if (mask & KADM5_PRINC_EXPIRE_TIME) + entry->princ_expire_time = kdb->expiration; + + if ((mask & KADM5_LAST_PWD_CHANGE) && + (ret = krb5_dbe_lookup_last_pwd_change(handle->context, kdb, + &(entry->last_pwd_change)))) { + goto done; + } + + if (mask & KADM5_PW_EXPIRATION) + entry->pw_expiration = kdb->pw_expiration; + if (mask & KADM5_MAX_LIFE) + entry->max_life = kdb->max_life; + + /* this is a little non-sensical because the function returns two */ + /* values that must be checked separately against the mask */ + if ((mask & KADM5_MOD_NAME) || (mask & KADM5_MOD_TIME)) { + ret = krb5_dbe_lookup_mod_princ_data(handle->context, kdb, + &(entry->mod_date), + &(entry->mod_name)); + if (ret) { + goto done; + } + + if (! (mask & KADM5_MOD_TIME)) + entry->mod_date = 0; + if (! (mask & KADM5_MOD_NAME)) { + krb5_free_principal(handle->context, entry->mod_name); + entry->mod_name = NULL; + } + } + + if (mask & KADM5_ATTRIBUTES) + entry->attributes = kdb->attributes; + + if (mask & KADM5_KVNO) + for (entry->kvno = 0, i=0; in_key_data; i++) + if ((krb5_kvno) kdb->key_data[i].key_data_kvno > entry->kvno) + entry->kvno = kdb->key_data[i].key_data_kvno; + + if (mask & KADM5_MKVNO) { + ret = krb5_dbe_get_mkvno(handle->context, kdb, &entry->mkvno); + if (ret) + goto done; + } + + if (mask & KADM5_MAX_RLIFE) + entry->max_renewable_life = kdb->max_renewable_life; + if (mask & KADM5_LAST_SUCCESS) + entry->last_success = kdb->last_success; + if (mask & KADM5_LAST_FAILED) + entry->last_failed = kdb->last_failed; + if (mask & KADM5_FAIL_AUTH_COUNT) + entry->fail_auth_count = kdb->fail_auth_count; + if (mask & KADM5_TL_DATA) { + krb5_tl_data *tl, *tl2; + + entry->tl_data = NULL; + + tl = kdb->tl_data; + while (tl) { + if (tl->tl_data_type > 255) { + if ((tl2 = dup_tl_data(tl)) == NULL) { + ret = ENOMEM; + goto done; + } + tl2->tl_data_next = entry->tl_data; + entry->tl_data = tl2; + entry->n_tl_data++; + } + + tl = tl->tl_data_next; + } + } + if (mask & KADM5_KEY_DATA) { + entry->n_key_data = kdb->n_key_data; + if(entry->n_key_data) { + entry->key_data = k5calloc(entry->n_key_data, + sizeof(krb5_key_data), &ret); + if (entry->key_data == NULL) + goto done; + } else + entry->key_data = NULL; + + for (i = 0; i < entry->n_key_data; i++) + ret = krb5_copy_key_data_contents(handle->context, + &kdb->key_data[i], + &entry->key_data[i]); + if (ret) + goto done; + } + + ret = KADM5_OK; + +done: + if (ret && entry->principal) { + krb5_free_principal(handle->context, entry->principal); + entry->principal = NULL; + } + kdb_free_entry(handle, kdb, &adb); + + return ret; +} + +/* + * Function: check_pw_reuse + * + * Purpose: Check if a key appears in a list of keys, in order to + * enforce password history. + * + * Arguments: + * + * context (r) the krb5 context + * hist_keyblock (r) the key that hist_key_data is + * encrypted in + * n_new_key_data (r) length of new_key_data + * new_key_data (r) keys to check against + * pw_hist_data, encrypted in hist_keyblock + * n_pw_hist_data (r) length of pw_hist_data + * pw_hist_data (r) passwords to check new_key_data against + * + * Effects: + * For each new_key in new_key_data: + * decrypt new_key with the master_keyblock + * for each password in pw_hist_data: + * for each hist_key in password: + * decrypt hist_key with hist_keyblock + * compare the new_key and hist_key + * + * Returns krb5 errors, KADM5_PASS_RESUSE if a key in + * new_key_data is the same as a key in pw_hist_data, or 0. + */ +static kadm5_ret_t +check_pw_reuse(krb5_context context, + krb5_keyblock *hist_keyblocks, + int n_new_key_data, krb5_key_data *new_key_data, + unsigned int n_pw_hist_data, osa_pw_hist_ent *pw_hist_data) +{ + unsigned int x, y, z; + krb5_keyblock newkey, histkey, *kb; + krb5_key_data *key_data; + krb5_error_code ret; + + assert (n_new_key_data >= 0); + for (x = 0; x < (unsigned) n_new_key_data; x++) { + /* Check only entries with the most recent kvno. */ + if (new_key_data[x].key_data_kvno != new_key_data[0].key_data_kvno) + break; + ret = krb5_dbe_decrypt_key_data(context, NULL, &(new_key_data[x]), + &newkey, NULL); + if (ret) + return(ret); + for (y = 0; y < n_pw_hist_data; y++) { + for (z = 0; z < (unsigned int) pw_hist_data[y].n_key_data; z++) { + for (kb = hist_keyblocks; kb->enctype != 0; kb++) { + key_data = &pw_hist_data[y].key_data[z]; + ret = krb5_dbe_decrypt_key_data(context, kb, key_data, + &histkey, NULL); + if (ret) + continue; + if (newkey.length == histkey.length && + newkey.enctype == histkey.enctype && + memcmp(newkey.contents, histkey.contents, + histkey.length) == 0) { + krb5_free_keyblock_contents(context, &histkey); + krb5_free_keyblock_contents(context, &newkey); + return KADM5_PASS_REUSE; + } + krb5_free_keyblock_contents(context, &histkey); + } + } + } + krb5_free_keyblock_contents(context, &newkey); + } + + return(0); +} + +static void +free_history_entry(krb5_context context, osa_pw_hist_ent *hist) +{ + int i; + + for (i = 0; i < hist->n_key_data; i++) + krb5_free_key_data_contents(context, &hist->key_data[i]); + free(hist->key_data); +} + +/* + * Function: create_history_entry + * + * Purpose: Creates a password history entry from an array of + * key_data. + * + * Arguments: + * + * context (r) krb5_context to use + * mkey (r) master keyblock to decrypt key data with + * hist_key (r) history keyblock to encrypt key data with + * n_key_data (r) number of elements in key_data + * key_data (r) keys to add to the history entry + * hist_out (w) history entry to fill in + * + * Effects: + * + * hist->key_data is allocated to store n_key_data key_datas. Each + * element of key_data is decrypted with master_keyblock, re-encrypted + * in hist_key, and added to hist->key_data. hist->n_key_data is + * set to n_key_data. + */ +static +int create_history_entry(krb5_context context, + krb5_keyblock *hist_key, int n_key_data, + krb5_key_data *key_data, osa_pw_hist_ent *hist_out) +{ + int i; + krb5_error_code ret = 0; + krb5_keyblock key; + krb5_keysalt salt; + krb5_ui_2 kvno; + osa_pw_hist_ent hist; + + hist_out->key_data = NULL; + hist_out->n_key_data = 0; + + if (n_key_data < 0) + return EINVAL; + + memset(&key, 0, sizeof(key)); + memset(&hist, 0, sizeof(hist)); + + if (n_key_data == 0) + goto cleanup; + + hist.key_data = k5calloc(n_key_data, sizeof(krb5_key_data), &ret); + if (hist.key_data == NULL) + goto cleanup; + + /* We only want to store the most recent kvno, and key_data should already + * be sorted in descending order by kvno. */ + kvno = key_data[0].key_data_kvno; + + for (i = 0; i < n_key_data; i++) { + if (key_data[i].key_data_kvno < kvno) + break; + ret = krb5_dbe_decrypt_key_data(context, NULL, + &key_data[i], &key, + &salt); + if (ret) + goto cleanup; + + ret = krb5_dbe_encrypt_key_data(context, hist_key, &key, &salt, + key_data[i].key_data_kvno, + &hist.key_data[hist.n_key_data]); + if (ret) + goto cleanup; + hist.n_key_data++; + krb5_free_keyblock_contents(context, &key); + /* krb5_free_keysalt(context, &salt); */ + } + + *hist_out = hist; + hist.n_key_data = 0; + hist.key_data = NULL; + +cleanup: + krb5_free_keyblock_contents(context, &key); + free_history_entry(context, &hist); + return ret; +} + +/* + * Function: add_to_history + * + * Purpose: Adds a password to a principal's password history. + * + * Arguments: + * + * context (r) krb5_context to use + * hist_kvno (r) kvno of current history key + * adb (r/w) admin principal entry to add keys to + * pol (r) adb's policy + * pw (r) keys for the password to add to adb's key history + * + * Effects: + * + * add_to_history adds a single password to adb's password history. + * pw contains n_key_data keys in its key_data, in storage should be + * allocated but not freed by the caller (XXX blech!). + * + * This function maintains adb->old_keys as a circular queue. It + * starts empty, and grows each time this function is called until it + * is pol->pw_history_num items long. adb->old_key_len holds the + * number of allocated entries in the array, and must therefore be [0, + * pol->pw_history_num). adb->old_key_next is the index into the + * array where the next element should be written, and must be [0, + * adb->old_key_len). + */ +static kadm5_ret_t add_to_history(krb5_context context, + krb5_kvno hist_kvno, + osa_princ_ent_t adb, + kadm5_policy_ent_t pol, + osa_pw_hist_ent *pw) +{ + osa_pw_hist_ent *histp; + uint32_t nhist; + unsigned int i, knext, nkeys; + + nhist = pol->pw_history_num; + /* A history of 1 means just check the current password */ + if (nhist <= 1) + return 0; + + if (adb->admin_history_kvno != hist_kvno) { + /* The history key has changed since the last password change, so we + * have to reset the password history. */ + free(adb->old_keys); + adb->old_keys = NULL; + adb->old_key_len = 0; + adb->old_key_next = 0; + adb->admin_history_kvno = hist_kvno; + } + + nkeys = adb->old_key_len; + knext = adb->old_key_next; + /* resize the adb->old_keys array if necessary */ + if (nkeys + 1 < nhist) { + if (adb->old_keys == NULL) { + adb->old_keys = (osa_pw_hist_ent *) + malloc((nkeys + 1) * sizeof (osa_pw_hist_ent)); + } else { + adb->old_keys = (osa_pw_hist_ent *) + realloc(adb->old_keys, + (nkeys + 1) * sizeof (osa_pw_hist_ent)); + } + if (adb->old_keys == NULL) + return(ENOMEM); + + memset(&adb->old_keys[nkeys], 0, sizeof(osa_pw_hist_ent)); + nkeys = ++adb->old_key_len; + /* + * To avoid losing old keys, shift forward each entry after + * knext. + */ + for (i = nkeys - 1; i > knext; i--) { + adb->old_keys[i] = adb->old_keys[i - 1]; + } + memset(&adb->old_keys[knext], 0, sizeof(osa_pw_hist_ent)); + } else if (nkeys + 1 > nhist) { + /* + * The policy must have changed! Shrink the array. + * Can't simply realloc() down, since it might be wrapped. + * To understand the arithmetic below, note that we are + * copying into new positions 0 .. N-1 from old positions + * old_key_next-N .. old_key_next-1, modulo old_key_len, + * where N = pw_history_num - 1 is the length of the + * shortened list. Matt Crawford, FNAL + */ + /* + * M = adb->old_key_len, N = pol->pw_history_num - 1 + * + * tmp[0] .. tmp[N-1] = old[(knext-N)%M] .. old[(knext-1)%M] + */ + int j; + osa_pw_hist_t tmp; + + tmp = (osa_pw_hist_ent *) + malloc((nhist - 1) * sizeof (osa_pw_hist_ent)); + if (tmp == NULL) + return ENOMEM; + for (i = 0; i < nhist - 1; i++) { + /* + * Add nkeys once before taking remainder to avoid + * negative values. + */ + j = (i + nkeys + knext - (nhist - 1)) % nkeys; + tmp[i] = adb->old_keys[j]; + } + /* Now free the ones we don't keep (the oldest ones) */ + for (i = 0; i < nkeys - (nhist - 1); i++) { + j = (i + nkeys + knext) % nkeys; + histp = &adb->old_keys[j]; + for (j = 0; j < histp->n_key_data; j++) { + krb5_free_key_data_contents(context, &histp->key_data[j]); + } + free(histp->key_data); + } + free(adb->old_keys); + adb->old_keys = tmp; + nkeys = adb->old_key_len = nhist - 1; + knext = adb->old_key_next = 0; + } + + /* + * If nhist decreased since the last password change, and nkeys+1 + * is less than the previous nhist, it is possible for knext to + * index into unallocated space. This condition would not be + * caught by the resizing code above. + */ + if (knext + 1 > nkeys) + knext = adb->old_key_next = 0; + /* free the old pw history entry if it contains data */ + histp = &adb->old_keys[knext]; + for (i = 0; i < (unsigned int) histp->n_key_data; i++) + krb5_free_key_data_contents(context, &histp->key_data[i]); + free(histp->key_data); + + /* store the new entry */ + adb->old_keys[knext] = *pw; + + /* update the next pointer */ + if (++adb->old_key_next == nhist - 1) + adb->old_key_next = 0; + + return(0); +} + +kadm5_ret_t +kadm5_chpass_principal(void *server_handle, + krb5_principal principal, char *password) +{ + return + kadm5_chpass_principal_3(server_handle, principal, FALSE, + 0, NULL, password); +} + +kadm5_ret_t +kadm5_chpass_principal_3(void *server_handle, + krb5_principal principal, krb5_boolean keepold, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, + char *password) +{ + krb5_timestamp now; + kadm5_policy_ent_rec pol; + osa_princ_ent_rec adb; + krb5_db_entry *kdb; + int ret, ret2, hist_added; + krb5_boolean have_pol = FALSE; + kadm5_server_handle_t handle = server_handle; + osa_pw_hist_ent hist; + krb5_keyblock *act_mkey, *hist_keyblocks = NULL; + krb5_kvno act_kvno, hist_kvno; + int new_n_ks_tuple = 0; + krb5_key_salt_tuple *new_ks_tuple = NULL; + + CHECK_HANDLE(server_handle); + + krb5_clear_error_message(handle->context); + + hist_added = 0; + memset(&hist, 0, sizeof(hist)); + + if (principal == NULL || password == NULL) + return EINVAL; + if ((krb5_principal_compare(handle->context, + principal, hist_princ)) == TRUE) + return KADM5_PROTECT_PRINCIPAL; + + if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) + return(ret); + + /* We will always be changing the key data, attributes, auth failure count, + * and password expiration time. */ + kdb->mask = KADM5_KEY_DATA | KADM5_ATTRIBUTES | KADM5_FAIL_AUTH_COUNT | + KADM5_PW_EXPIRATION; + + ret = apply_keysalt_policy(handle, adb.policy, n_ks_tuple, ks_tuple, + &new_n_ks_tuple, &new_ks_tuple); + if (ret) + goto done; + + if ((adb.aux_attributes & KADM5_POLICY)) { + ret = get_policy(handle, adb.policy, &pol, &have_pol); + if (ret) + goto done; + } + if (have_pol) { + /* Create a password history entry before we change kdb's key_data. */ + ret = kdb_get_hist_key(handle, &hist_keyblocks, &hist_kvno); + if (ret) + goto done; + ret = create_history_entry(handle->context, &hist_keyblocks[0], + kdb->n_key_data, kdb->key_data, &hist); + if (ret) + goto done; + } + + if ((ret = passwd_check(handle, password, have_pol ? &pol : NULL, + principal))) + goto done; + + ret = kdb_get_active_mkey(handle, &act_kvno, &act_mkey); + if (ret) + goto done; + + ret = krb5_dbe_cpw(handle->context, act_mkey, new_ks_tuple, new_n_ks_tuple, + password, 0 /* increment kvno */, + keepold, kdb); + if (ret) + goto done; + + ret = krb5_dbe_update_mkvno(handle->context, kdb, act_kvno); + if (ret) + goto done; + + kdb->attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE; + + ret = krb5_timeofday(handle->context, &now); + if (ret) + goto done; + + kdb->pw_expiration = 0; + if ((adb.aux_attributes & KADM5_POLICY)) { + /* the policy was loaded before */ + + ret = check_pw_reuse(handle->context, hist_keyblocks, + kdb->n_key_data, kdb->key_data, + 1, &hist); + if (ret) + goto done; + + if (pol.pw_history_num > 1) { + /* If hist_kvno has changed since the last password change, we + * can't check the history. */ + if (adb.admin_history_kvno == hist_kvno) { + ret = check_pw_reuse(handle->context, hist_keyblocks, + kdb->n_key_data, kdb->key_data, + adb.old_key_len, adb.old_keys); + if (ret) + goto done; + } + + /* Don't save empty history. */ + if (hist.n_key_data > 0) { + ret = add_to_history(handle->context, hist_kvno, &adb, &pol, + &hist); + if (ret) + goto done; + hist_added = 1; + } + } + + if (pol.pw_max_life) + kdb->pw_expiration = ts_incr(now, pol.pw_max_life); + } + + ret = krb5_dbe_update_last_pwd_change(handle->context, kdb, now); + if (ret) + goto done; + + /* unlock principal on this KDC */ + kdb->fail_auth_count = 0; + + if (hist_added) + kdb->mask |= KADM5_KEY_HIST; + + ret = k5_kadm5_hook_chpass(handle->context, handle->hook_handles, + KADM5_HOOK_STAGE_PRECOMMIT, principal, keepold, + new_n_ks_tuple, new_ks_tuple, password); + if (ret) + goto done; + + if ((ret = kdb_put_entry(handle, kdb, &adb))) + goto done; + + (void) k5_kadm5_hook_chpass(handle->context, handle->hook_handles, + KADM5_HOOK_STAGE_POSTCOMMIT, principal, + keepold, new_n_ks_tuple, new_ks_tuple, password); + ret = KADM5_OK; +done: + free(new_ks_tuple); + if (!hist_added && hist.key_data) + free_history_entry(handle->context, &hist); + kdb_free_entry(handle, kdb, &adb); + kdb_free_keyblocks(handle, hist_keyblocks); + + if (have_pol && (ret2 = kadm5_free_policy_ent(handle->lhandle, &pol)) + && !ret) + ret = ret2; + + return ret; +} + +kadm5_ret_t +kadm5_randkey_principal(void *server_handle, + krb5_principal principal, + krb5_keyblock **keyblocks, + int *n_keys) +{ + return + kadm5_randkey_principal_3(server_handle, principal, + FALSE, 0, NULL, + keyblocks, n_keys); +} +kadm5_ret_t +kadm5_randkey_principal_3(void *server_handle, + krb5_principal principal, + krb5_boolean keepold, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, + krb5_keyblock **keyblocks, + int *n_keys) +{ + krb5_db_entry *kdb; + osa_princ_ent_rec adb; + krb5_timestamp now; + kadm5_policy_ent_rec pol; + int ret, n_new_keys; + krb5_boolean have_pol = FALSE; + kadm5_server_handle_t handle = server_handle; + krb5_keyblock *act_mkey; + krb5_kvno act_kvno; + int new_n_ks_tuple = 0; + krb5_key_salt_tuple *new_ks_tuple = NULL; + + if (keyblocks) + *keyblocks = NULL; + + CHECK_HANDLE(server_handle); + + krb5_clear_error_message(handle->context); + + if (principal == NULL) + return EINVAL; + + if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) + return(ret); + + /* We will always be changing the key data, attributes, auth failure count, + * and password expiration time. */ + kdb->mask = KADM5_KEY_DATA | KADM5_ATTRIBUTES | KADM5_FAIL_AUTH_COUNT | + KADM5_PW_EXPIRATION; + + ret = apply_keysalt_policy(handle, adb.policy, n_ks_tuple, ks_tuple, + &new_n_ks_tuple, &new_ks_tuple); + if (ret) + goto done; + + if (krb5_principal_compare(handle->context, principal, hist_princ)) { + /* If changing the history entry, the new entry must have exactly one + * key. */ + if (keepold) { + ret = KADM5_PROTECT_PRINCIPAL; + goto done; + } + new_n_ks_tuple = 1; + } + + ret = kdb_get_active_mkey(handle, &act_kvno, &act_mkey); + if (ret) + goto done; + + ret = krb5_dbe_crk(handle->context, act_mkey, new_ks_tuple, new_n_ks_tuple, + keepold, kdb); + if (ret) + goto done; + + ret = krb5_dbe_update_mkvno(handle->context, kdb, act_kvno); + if (ret) + goto done; + + kdb->attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE; + + ret = krb5_timeofday(handle->context, &now); + if (ret) + goto done; + + if ((adb.aux_attributes & KADM5_POLICY)) { + ret = get_policy(handle, adb.policy, &pol, &have_pol); + if (ret) + goto done; + } + + kdb->pw_expiration = 0; + if (have_pol && pol.pw_max_life) + kdb->pw_expiration = ts_incr(now, pol.pw_max_life); + + ret = krb5_dbe_update_last_pwd_change(handle->context, kdb, now); + if (ret) + goto done; + + /* unlock principal on this KDC */ + kdb->fail_auth_count = 0; + + if (keyblocks) { + /* Return only the new keys added by krb5_dbe_crk. */ + n_new_keys = count_new_keys(kdb->n_key_data, kdb->key_data); + ret = decrypt_key_data(handle->context, n_new_keys, kdb->key_data, + keyblocks, n_keys); + if (ret) + goto done; + } + + ret = k5_kadm5_hook_chpass(handle->context, handle->hook_handles, + KADM5_HOOK_STAGE_PRECOMMIT, principal, keepold, + new_n_ks_tuple, new_ks_tuple, NULL); + if (ret) + goto done; + if ((ret = kdb_put_entry(handle, kdb, &adb))) + goto done; + + (void) k5_kadm5_hook_chpass(handle->context, handle->hook_handles, + KADM5_HOOK_STAGE_POSTCOMMIT, principal, + keepold, new_n_ks_tuple, new_ks_tuple, NULL); + ret = KADM5_OK; +done: + free(new_ks_tuple); + kdb_free_entry(handle, kdb, &adb); + if (have_pol) + kadm5_free_policy_ent(handle->lhandle, &pol); + + return ret; +} + +kadm5_ret_t +kadm5_setkey_principal(void *server_handle, + krb5_principal principal, + krb5_keyblock *keyblocks, + int n_keys) +{ + return + kadm5_setkey_principal_3(server_handle, principal, + FALSE, 0, NULL, + keyblocks, n_keys); +} + +kadm5_ret_t +kadm5_setkey_principal_3(void *server_handle, + krb5_principal principal, + krb5_boolean keepold, + int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, + krb5_keyblock *keyblocks, + int n_keys) +{ + kadm5_key_data *key_data; + kadm5_ret_t ret; + int i; + + if (keyblocks == NULL) + return EINVAL; + + if (n_ks_tuple) { + if (n_ks_tuple != n_keys) + return KADM5_SETKEY3_ETYPE_MISMATCH; + for (i = 0; i < n_ks_tuple; i++) { + if (ks_tuple[i].ks_enctype != keyblocks[i].enctype) + return KADM5_SETKEY3_ETYPE_MISMATCH; + } + } + + key_data = calloc(n_keys, sizeof(kadm5_key_data)); + if (key_data == NULL) + return ENOMEM; + + for (i = 0; i < n_keys; i++) { + key_data[i].key = keyblocks[i]; + key_data[i].salt.type = + n_ks_tuple ? ks_tuple[i].ks_salttype : KRB5_KDB_SALTTYPE_NORMAL; + } + + ret = kadm5_setkey_principal_4(server_handle, principal, keepold, + key_data, n_keys); + free(key_data); + return ret; +} + +/* Create a key/salt list from a key_data array. */ +static kadm5_ret_t +make_ks_from_key_data(krb5_context context, kadm5_key_data *key_data, + int n_key_data, krb5_key_salt_tuple **out) +{ + int i; + krb5_key_salt_tuple *ks; + + *out = NULL; + + ks = calloc(n_key_data, sizeof(*ks)); + if (ks == NULL) + return ENOMEM; + + for (i = 0; i < n_key_data; i++) { + ks[i].ks_enctype = key_data[i].key.enctype; + ks[i].ks_salttype = key_data[i].salt.type; + } + *out = ks; + return 0; +} + +kadm5_ret_t +kadm5_setkey_principal_4(void *server_handle, krb5_principal principal, + krb5_boolean keepold, kadm5_key_data *key_data, + int n_key_data) +{ + krb5_db_entry *kdb; + osa_princ_ent_rec adb; + krb5_timestamp now; + kadm5_policy_ent_rec pol; + krb5_key_data *new_key_data = NULL; + int i, j, ret, n_new_key_data = 0; + krb5_kvno kvno; + krb5_boolean similar, have_pol = FALSE; + kadm5_server_handle_t handle = server_handle; + krb5_keyblock *act_mkey; + krb5_key_salt_tuple *ks_from_keys = NULL; + + CHECK_HANDLE(server_handle); + + krb5_clear_error_message(handle->context); + + if (principal == NULL || key_data == NULL || n_key_data == 0) + return EINVAL; + + /* hist_princ will be NULL when initializing the database. */ + if (hist_princ != NULL && + krb5_principal_compare(handle->context, principal, hist_princ)) + return KADM5_PROTECT_PRINCIPAL; + + /* For now, all keys must have the same kvno. */ + kvno = key_data[0].kvno; + for (i = 1; i < n_key_data; i++) { + if (key_data[i].kvno != kvno) + return KADM5_SETKEY_BAD_KVNO; + } + + ret = kdb_get_entry(handle, principal, &kdb, &adb); + if (ret) + return ret; + + /* We will always be changing the key data, attributes, auth failure count, + * and password expiration time. */ + kdb->mask = KADM5_KEY_DATA | KADM5_ATTRIBUTES | KADM5_FAIL_AUTH_COUNT | + KADM5_PW_EXPIRATION; + + if (kvno == 0) { + /* Pick the next kvno. */ + for (i = 0; i < kdb->n_key_data; i++) { + if (kdb->key_data[i].key_data_kvno > kvno) + kvno = kdb->key_data[i].key_data_kvno; + } + kvno++; + } else if (keepold) { + /* Check that the kvno does collide with existing keys. */ + for (i = 0; i < kdb->n_key_data; i++) { + if (kdb->key_data[i].key_data_kvno == kvno) { + ret = KADM5_SETKEY_BAD_KVNO; + goto done; + } + } + } + + ret = make_ks_from_key_data(handle->context, key_data, n_key_data, + &ks_from_keys); + if (ret) + goto done; + + ret = apply_keysalt_policy(handle, adb.policy, n_key_data, ks_from_keys, + NULL, NULL); + free(ks_from_keys); + if (ret) + goto done; + + for (i = 0; i < n_key_data; i++) { + for (j = i + 1; j < n_key_data; j++) { + ret = krb5_c_enctype_compare(handle->context, + key_data[i].key.enctype, + key_data[j].key.enctype, + &similar); + if (ret) + goto done; + if (similar) { + if (key_data[i].salt.type == key_data[j].salt.type) { + ret = KADM5_SETKEY_DUP_ENCTYPES; + goto done; + } + } + } + } + + n_new_key_data = n_key_data + (keepold ? kdb->n_key_data : 0); + new_key_data = calloc(n_new_key_data, sizeof(krb5_key_data)); + if (new_key_data == NULL) { + n_new_key_data = 0; + ret = ENOMEM; + goto done; + } + + n_new_key_data = 0; + for (i = 0; i < n_key_data; i++) { + + ret = kdb_get_active_mkey(handle, NULL, &act_mkey); + if (ret) + goto done; + + ret = krb5_dbe_encrypt_key_data(handle->context, act_mkey, + &key_data[i].key, &key_data[i].salt, + kvno, &new_key_data[i]); + if (ret) + goto done; + + n_new_key_data++; + } + + /* Copy old key data if necessary. */ + if (keepold) { + memcpy(new_key_data + n_new_key_data, kdb->key_data, + kdb->n_key_data * sizeof(krb5_key_data)); + memset(kdb->key_data, 0, kdb->n_key_data * sizeof(krb5_key_data)); + + /* + * Sort the keys to maintain the defined kvno order. We only need to + * sort if we keep old keys, as otherwise we allow only a single kvno + * to be specified. + */ + krb5_dbe_sort_key_data(new_key_data, n_new_key_data); + } + + /* Replace kdb->key_data with the new keys. */ + cleanup_key_data(handle->context, kdb->n_key_data, kdb->key_data); + kdb->key_data = new_key_data; + kdb->n_key_data = n_new_key_data; + new_key_data = NULL; + n_new_key_data = 0; + + kdb->attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE; + + ret = krb5_timeofday(handle->context, &now); + if (ret) + goto done; + + if (adb.aux_attributes & KADM5_POLICY) { + ret = get_policy(handle, adb.policy, &pol, &have_pol); + if (ret) + goto done; + } + + kdb->pw_expiration = 0; + if (have_pol && pol.pw_max_life) + kdb->pw_expiration = ts_incr(now, pol.pw_max_life); + + ret = krb5_dbe_update_last_pwd_change(handle->context, kdb, now); + if (ret) + goto done; + + /* Unlock principal on this KDC. */ + kdb->fail_auth_count = 0; + + ret = kdb_put_entry(handle, kdb, &adb); + if (ret) + goto done; + + ret = KADM5_OK; + +done: + cleanup_key_data(handle->context, n_new_key_data, new_key_data); + kdb_free_entry(handle, kdb, &adb); + if (have_pol) + kadm5_free_policy_ent(handle->lhandle, &pol); + return ret; +} + +/* + * Return the list of keys like kadm5_randkey_principal, + * but don't modify the principal. + */ +kadm5_ret_t +kadm5_get_principal_keys(void *server_handle /* IN */, + krb5_principal principal /* IN */, + krb5_kvno kvno /* IN */, + kadm5_key_data **key_data_out /* OUT */, + int *n_key_data_out /* OUT */) +{ + krb5_db_entry *kdb; + osa_princ_ent_rec adb; + kadm5_ret_t ret; + kadm5_server_handle_t handle = server_handle; + kadm5_key_data *key_data = NULL; + int i, nkeys = 0; + + if (principal == NULL || key_data_out == NULL || n_key_data_out == NULL) + return EINVAL; + + CHECK_HANDLE(server_handle); + + if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) + return(ret); + + key_data = calloc(kdb->n_key_data, sizeof(kadm5_key_data)); + if (key_data == NULL) { + ret = ENOMEM; + goto done; + } + + for (i = 0, nkeys = 0; i < kdb->n_key_data; i++) { + if (kvno != 0 && kvno != kdb->key_data[i].key_data_kvno) + continue; + key_data[nkeys].kvno = kdb->key_data[i].key_data_kvno; + + ret = krb5_dbe_decrypt_key_data(handle->context, NULL, + &kdb->key_data[i], + &key_data[nkeys].key, + &key_data[nkeys].salt); + if (ret) + goto done; + nkeys++; + } + + *n_key_data_out = nkeys; + *key_data_out = key_data; + key_data = NULL; + nkeys = 0; + ret = KADM5_OK; + +done: + kdb_free_entry(handle, kdb, &adb); + kadm5_free_kadm5_key_data(handle->context, nkeys, key_data); + + return ret; +} + + +/* + * Allocate an array of n_key_data krb5_keyblocks, fill in each + * element with the results of decrypting the nth key in key_data, + * and if n_keys is not NULL fill it in with the + * number of keys decrypted. + */ +static int decrypt_key_data(krb5_context context, + int n_key_data, krb5_key_data *key_data, + krb5_keyblock **keyblocks, int *n_keys) +{ + krb5_keyblock *keys; + int ret, i; + + keys = (krb5_keyblock *) malloc(n_key_data*sizeof(krb5_keyblock)); + if (keys == NULL) + return ENOMEM; + memset(keys, 0, n_key_data*sizeof(krb5_keyblock)); + + for (i = 0; i < n_key_data; i++) { + ret = krb5_dbe_decrypt_key_data(context, NULL, &key_data[i], &keys[i], + NULL); + if (ret) { + for (; i >= 0; i--) + krb5_free_keyblock_contents(context, &keys[i]); + free(keys); + return ret; + } + } + + *keyblocks = keys; + if (n_keys) + *n_keys = n_key_data; + + return 0; +} + +/* + * Function: kadm5_decrypt_key + * + * Purpose: Retrieves and decrypts a principal key. + * + * Arguments: + * + * server_handle (r) kadm5 handle + * entry (r) principal retrieved with kadm5_get_principal + * ktype (r) enctype to search for, or -1 to ignore + * stype (r) salt type to search for, or -1 to ignore + * kvno (r) kvno to search for, -1 for max, 0 for max + * only if it also matches ktype and stype + * keyblock (w) keyblock to fill in + * keysalt (w) keysalt to fill in, or NULL + * kvnop (w) kvno to fill in, or NULL + * + * Effects: Searches the key_data array of entry, which must have been + * retrieved with kadm5_get_principal with the KADM5_KEY_DATA mask, to + * find a key with a specified enctype, salt type, and kvno in a + * principal entry. If not found, return ENOENT. Otherwise, decrypt + * it with the master key, and return the key in keyblock, the salt + * in salttype, and the key version number in kvno. + * + * If ktype or stype is -1, it is ignored for the search. If kvno is + * -1, ktype and stype are ignored and the key with the max kvno is + * returned. If kvno is 0, only the key with the max kvno is returned + * and only if it matches the ktype and stype; otherwise, ENOENT is + * returned. + */ +kadm5_ret_t kadm5_decrypt_key(void *server_handle, + kadm5_principal_ent_t entry, krb5_int32 + ktype, krb5_int32 stype, krb5_int32 + kvno, krb5_keyblock *keyblock, + krb5_keysalt *keysalt, int *kvnop) +{ + kadm5_server_handle_t handle = server_handle; + krb5_db_entry dbent; + krb5_key_data *key_data; + krb5_keyblock *mkey_ptr; + int ret; + + CHECK_HANDLE(server_handle); + + if (entry->n_key_data == 0 || entry->key_data == NULL) + return EINVAL; + + /* find_enctype only uses these two fields */ + dbent.n_key_data = entry->n_key_data; + dbent.key_data = entry->key_data; + if ((ret = krb5_dbe_find_enctype(handle->context, &dbent, ktype, + stype, kvno, &key_data))) + return ret; + + /* find_mkey only uses this field */ + dbent.tl_data = entry->tl_data; + if ((ret = krb5_dbe_find_mkey(handle->context, &dbent, &mkey_ptr))) { + /* try refreshing master key list */ + /* XXX it would nice if we had the mkvno here for optimization */ + if (krb5_db_fetch_mkey_list(handle->context, master_princ, + &master_keyblock) == 0) { + if ((ret = krb5_dbe_find_mkey(handle->context, &dbent, + &mkey_ptr))) { + return ret; + } + } else { + return ret; + } + } + + if ((ret = krb5_dbe_decrypt_key_data(handle->context, NULL, key_data, + keyblock, keysalt))) + return ret; + + /* + * Coerce the enctype of the output keyblock in case we got an + * inexact match on the enctype; this behavior will go away when + * the key storage architecture gets redesigned for 1.3. + */ + if (ktype != -1) + keyblock->enctype = ktype; + + if (kvnop) + *kvnop = key_data->key_data_kvno; + + return KADM5_OK; +} + +kadm5_ret_t +kadm5_purgekeys(void *server_handle, + krb5_principal principal, + int keepkvno) +{ + kadm5_server_handle_t handle = server_handle; + kadm5_ret_t ret; + krb5_db_entry *kdb; + osa_princ_ent_rec adb; + krb5_key_data *old_keydata; + int n_old_keydata; + int i, j, k; + + CHECK_HANDLE(server_handle); + + if (principal == NULL) + return EINVAL; + + ret = kdb_get_entry(handle, principal, &kdb, &adb); + if (ret) + return(ret); + + if (keepkvno <= 0) { + keepkvno = krb5_db_get_key_data_kvno(handle->context, kdb->n_key_data, + kdb->key_data); + } + + old_keydata = kdb->key_data; + n_old_keydata = kdb->n_key_data; + kdb->n_key_data = 0; + /* Allocate one extra key_data to avoid allocating 0 bytes. */ + kdb->key_data = calloc(n_old_keydata, sizeof(krb5_key_data)); + if (kdb->key_data == NULL) { + ret = ENOMEM; + goto done; + } + memset(kdb->key_data, 0, n_old_keydata * sizeof(krb5_key_data)); + for (i = 0, j = 0; i < n_old_keydata; i++) { + if (old_keydata[i].key_data_kvno < keepkvno) + continue; + + /* Alias the key_data_contents pointers; we null them out in the + * source array immediately after. */ + kdb->key_data[j] = old_keydata[i]; + for (k = 0; k < old_keydata[i].key_data_ver; k++) { + old_keydata[i].key_data_contents[k] = NULL; + } + j++; + } + kdb->n_key_data = j; + cleanup_key_data(handle->context, n_old_keydata, old_keydata); + + kdb->mask = KADM5_KEY_DATA; + ret = kdb_put_entry(handle, kdb, &adb); + if (ret) + goto done; + +done: + kdb_free_entry(handle, kdb, &adb); + return ret; +} + +kadm5_ret_t +kadm5_get_strings(void *server_handle, krb5_principal principal, + krb5_string_attr **strings_out, int *count_out) +{ + kadm5_server_handle_t handle = server_handle; + kadm5_ret_t ret; + krb5_db_entry *kdb = NULL; + + *strings_out = NULL; + *count_out = 0; + CHECK_HANDLE(server_handle); + if (principal == NULL) + return EINVAL; + + ret = kdb_get_entry(handle, principal, &kdb, NULL); + if (ret) + return ret; + + ret = krb5_dbe_get_strings(handle->context, kdb, strings_out, count_out); + kdb_free_entry(handle, kdb, NULL); + return ret; +} + +kadm5_ret_t +kadm5_set_string(void *server_handle, krb5_principal principal, + const char *key, const char *value) +{ + kadm5_server_handle_t handle = server_handle; + kadm5_ret_t ret; + krb5_db_entry *kdb; + osa_princ_ent_rec adb; + + CHECK_HANDLE(server_handle); + if (principal == NULL || key == NULL) + return EINVAL; + + ret = kdb_get_entry(handle, principal, &kdb, &adb); + if (ret) + return ret; + + ret = krb5_dbe_set_string(handle->context, kdb, key, value); + if (ret) + goto done; + + kdb->mask = KADM5_TL_DATA; + ret = kdb_put_entry(handle, kdb, &adb); + +done: + kdb_free_entry(handle, kdb, &adb); + return ret; +} diff --git a/krb5-1.21.3/src/lib/kadm5/str_conv.c b/krb5-1.21.3/src/lib/kadm5/str_conv.c new file mode 100644 index 00000000..79829560 --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/str_conv.c @@ -0,0 +1,403 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kadm5/str_conv.c */ +/* + * Copyright (C) 1995-2015 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. + */ + +/* Convert between strings and Kerberos internal data. */ + +#include "k5-int.h" +#include "admin_internal.h" +#include "adm_proto.h" + +#include + +static const char default_tupleseps[] = ", \t"; +static const char default_ksaltseps[] = ":"; + +struct flag_table_row { + const char *spec; /* Input specifier string */ + krb5_flags flag; /* Flag */ + int invert; /* Whether to invert the sense */ +}; + +static const struct flag_table_row ftbl[] = { + {"allow_postdated", KRB5_KDB_DISALLOW_POSTDATED, 1}, + {"postdateable", KRB5_KDB_DISALLOW_POSTDATED, 1}, + {"disallow_postdated", KRB5_KDB_DISALLOW_POSTDATED, 0}, + {"allow_forwardable", KRB5_KDB_DISALLOW_FORWARDABLE, 1}, + {"forwardable", KRB5_KDB_DISALLOW_FORWARDABLE, 1}, + {"disallow_forwardable", KRB5_KDB_DISALLOW_FORWARDABLE, 0}, + {"allow_tgs_req", KRB5_KDB_DISALLOW_TGT_BASED, 1}, + {"tgt_based", KRB5_KDB_DISALLOW_TGT_BASED, 1}, + {"disallow_tgt_based", KRB5_KDB_DISALLOW_TGT_BASED, 0}, + {"allow_renewable", KRB5_KDB_DISALLOW_RENEWABLE, 1}, + {"renewable", KRB5_KDB_DISALLOW_RENEWABLE, 1}, + {"disallow_renewable", KRB5_KDB_DISALLOW_RENEWABLE, 0}, + {"allow_proxiable", KRB5_KDB_DISALLOW_PROXIABLE, 1}, + {"proxiable", KRB5_KDB_DISALLOW_PROXIABLE, 1}, + {"disallow_proxiable", KRB5_KDB_DISALLOW_PROXIABLE, 0}, + {"allow_dup_skey", KRB5_KDB_DISALLOW_DUP_SKEY, 1}, + {"dup_skey", KRB5_KDB_DISALLOW_DUP_SKEY, 1}, + {"disallow_dup_skey", KRB5_KDB_DISALLOW_DUP_SKEY, 0}, + {"allow_tickets", KRB5_KDB_DISALLOW_ALL_TIX, 1}, + {"allow_tix", KRB5_KDB_DISALLOW_ALL_TIX, 1}, + {"disallow_all_tix", KRB5_KDB_DISALLOW_ALL_TIX, 0}, + {"preauth", KRB5_KDB_REQUIRES_PRE_AUTH, 0}, + {"requires_pre_auth", KRB5_KDB_REQUIRES_PRE_AUTH, 0}, + {"requires_preauth", KRB5_KDB_REQUIRES_PRE_AUTH, 0}, + {"hwauth", KRB5_KDB_REQUIRES_HW_AUTH, 0}, + {"requires_hw_auth", KRB5_KDB_REQUIRES_HW_AUTH, 0}, + {"requires_hwauth", KRB5_KDB_REQUIRES_HW_AUTH, 0}, + {"needchange", KRB5_KDB_REQUIRES_PWCHANGE, 0}, + {"pwchange", KRB5_KDB_REQUIRES_PWCHANGE, 0}, + {"requires_pwchange", KRB5_KDB_REQUIRES_PWCHANGE, 0}, + {"allow_svr", KRB5_KDB_DISALLOW_SVR, 1}, + {"service", KRB5_KDB_DISALLOW_SVR, 1}, + {"disallow_svr", KRB5_KDB_DISALLOW_SVR, 0}, + {"password_changing_service", KRB5_KDB_PWCHANGE_SERVICE, 0}, + {"pwchange_service", KRB5_KDB_PWCHANGE_SERVICE, 0}, + {"pwservice", KRB5_KDB_PWCHANGE_SERVICE, 0}, + {"md5", KRB5_KDB_SUPPORT_DESMD5, 0}, + {"support_desmd5", KRB5_KDB_SUPPORT_DESMD5, 0}, + {"new_princ", KRB5_KDB_NEW_PRINC, 0}, + {"ok_as_delegate", KRB5_KDB_OK_AS_DELEGATE, 0}, + {"ok_to_auth_as_delegate", KRB5_KDB_OK_TO_AUTH_AS_DELEGATE, 0}, + {"no_auth_data_required", KRB5_KDB_NO_AUTH_DATA_REQUIRED, 0}, + {"lockdown_keys", KRB5_KDB_LOCKDOWN_KEYS, 0}, +}; +#define NFTBL (sizeof(ftbl) / sizeof(ftbl[0])) + +static const char *outflags[] = { + "DISALLOW_POSTDATED", /* 0x00000001 */ + "DISALLOW_FORWARDABLE", /* 0x00000002 */ + "DISALLOW_TGT_BASED", /* 0x00000004 */ + "DISALLOW_RENEWABLE", /* 0x00000008 */ + "DISALLOW_PROXIABLE", /* 0x00000010 */ + "DISALLOW_DUP_SKEY", /* 0x00000020 */ + "DISALLOW_ALL_TIX", /* 0x00000040 */ + "REQUIRES_PRE_AUTH", /* 0x00000080 */ + "REQUIRES_HW_AUTH", /* 0x00000100 */ + "REQUIRES_PWCHANGE", /* 0x00000200 */ + NULL, /* 0x00000400 */ + NULL, /* 0x00000800 */ + "DISALLOW_SVR", /* 0x00001000 */ + "PWCHANGE_SERVICE", /* 0x00002000 */ + "SUPPORT_DESMD5", /* 0x00004000 */ + "NEW_PRINC", /* 0x00008000 */ + NULL, /* 0x00010000 */ + NULL, /* 0x00020000 */ + NULL, /* 0x00040000 */ + NULL, /* 0x00080000 */ + "OK_AS_DELEGATE", /* 0x00100000 */ + "OK_TO_AUTH_AS_DELEGATE", /* 0x00200000 */ + "NO_AUTH_DATA_REQUIRED", /* 0x00400000 */ + "LOCKDOWN_KEYS", /* 0x00800000 */ +}; +#define NOUTFLAGS (sizeof(outflags) / sizeof(outflags[0])) + +/* + * Given s, which is a normalized flagspec with the prefix stripped off, and + * req_neg indicating whether the flagspec is negated, update the toset and + * toclear masks. + */ +static krb5_error_code +raw_flagspec_to_mask(const char *s, int req_neg, krb5_flags *toset, + krb5_flags *toclear) +{ + int found = 0, invert = 0; + size_t i; + krb5_flags flag; + unsigned long ul; + + for (i = 0; !found && i < NFTBL; i++) { + if (strcmp(s, ftbl[i].spec) != 0) + continue; + /* Found a match */ + found = 1; + invert = ftbl[i].invert; + flag = ftbl[i].flag; + } + /* Accept hexadecimal numbers. */ + if (!found && strncmp(s, "0x", 2) == 0) { + /* Assume that krb5_flags are 32 bits long. */ + ul = strtoul(s, NULL, 16) & 0xffffffff; + flag = (krb5_flags)ul; + found = 1; + } + if (!found) + return EINVAL; + if (req_neg) + invert = !invert; + if (invert) + *toclear &= ~flag; + else + *toset |= flag; + return 0; +} + +/* + * Update the toset and toclear flag masks according to flag specifier string + * spec, which is of the form {+|-}flagname. toset and toclear can point to + * the same flag word. + */ +krb5_error_code +krb5_flagspec_to_mask(const char *spec, krb5_flags *toset, krb5_flags *toclear) +{ + int req_neg = 0; + char *copy, *cp, *s; + krb5_error_code retval; + + s = copy = strdup(spec); + if (s == NULL) + return ENOMEM; + + if (*s == '-') { + req_neg = 1; + s++; + } else if (*s == '+') + s++; + + for (cp = s; *cp != '\0'; cp++) { + /* Transform hyphens to underscores.*/ + if (*cp == '-') + *cp = '_'; + /* Downcase. */ + if (isupper((unsigned char)*cp)) + *cp = tolower((unsigned char)*cp); + } + retval = raw_flagspec_to_mask(s, req_neg, toset, toclear); + free(copy); + return retval; +} + +/* + * Copy the flag name of flagnum to outstr. On error, outstr points to a null + * pointer. + */ +krb5_error_code +krb5_flagnum_to_string(int flagnum, char **outstr) +{ + const char *s = NULL; + + *outstr = NULL; + if ((unsigned int)flagnum < NOUTFLAGS) + s = outflags[flagnum]; + if (s == NULL) { + /* Assume that krb5_flags are 32 bits long. */ + if (asprintf(outstr, "0x%08lx", 1UL << flagnum) == -1) + *outstr = NULL; + } else { + *outstr = strdup(s); + } + if (*outstr == NULL) + return ENOMEM; + return 0; +} + +/* + * Create a null-terminated array of string representations of flags. Store a + * null pointer into outarray if there would be no strings. + */ +krb5_error_code +krb5_flags_to_strings(krb5_int32 flags, char ***outarray) +{ + char **a = NULL, **a_new = NULL, **ap; + size_t amax = 0, i; + krb5_error_code retval; + + *outarray = NULL; + + /* Assume that krb5_flags are 32 bits long. */ + for (i = 0; i < 32; i++) { + if (!(flags & (1UL << i))) + continue; + + a_new = realloc(a, (amax + 2) * sizeof(*a)); + if (a_new == NULL) { + retval = ENOMEM; + goto cleanup; + } + a = a_new; + retval = krb5_flagnum_to_string(i, &a[amax++]); + a[amax] = NULL; + if (retval) + goto cleanup; + } + *outarray = a; + return 0; +cleanup: + for (ap = a; ap != NULL && *ap != NULL; ap++) { + free(*ap); + } + free(a); + return retval; +} + +/* + * krb5_keysalt_is_present() - Determine if a key/salt pair is present + * in a list of key/salt tuples. + * + * Salttype may be negative to indicate a search for only a enctype. + */ +krb5_boolean +krb5_keysalt_is_present(ksaltlist, nksalts, enctype, salttype) + krb5_key_salt_tuple *ksaltlist; + krb5_int32 nksalts; + krb5_enctype enctype; + krb5_int32 salttype; +{ + krb5_boolean foundit; + int i; + + foundit = 0; + if (ksaltlist) { + for (i=0; i + +static uint32_t api; +static krb5_boolean rpc; + +static krb5_context context; + +/* These must match the creation commands in t_kadm5.py. */ +#define ADMIN_PASSWORD "admin" +#define USER_PASSWORD "us3r" + +/* This list must match the supported_enctypes setting in t_kadm5.py. */ +static krb5_enctype +default_supported_enctypes[] = { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_NULL +}; + +static void +check(krb5_error_code code) +{ + assert(code == 0); +} + +static void +check_fail(krb5_error_code code, krb5_error_code expected) +{ + assert(code == expected); +} + +/* + * Initialize a handle using the global context. The caller must destroy this + * handle before initializing another one. If the client name begins with '$', + * authenticate to kadmin/changepw; otherwise authenticate to kadmin/admin. If + * client is null, return a null handle. + */ +static void * +get_handle(char *client) +{ + void *handle; + char *service, *pass; + + if (client == NULL) + return NULL; + + if (*client == '$') { + service = KADM5_CHANGEPW_SERVICE; + client++; + } else { + service = KADM5_ADMIN_SERVICE; + } + pass = (strcmp(client, "user") == 0) ? USER_PASSWORD : ADMIN_PASSWORD; + + check(kadm5_init(context, client, pass, service, NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle)); + return handle; +} + +static void +free_handle(void *handle) +{ + if (handle != NULL) + check(kadm5_destroy(handle)); +} + +static krb5_principal +parse_princ(const char *str) +{ + krb5_principal princ; + + check(krb5_parse_name(context, str, &princ)); + return princ; +} + +static void +create_simple_policy(char *name) +{ + void *handle = get_handle("admin"); + kadm5_policy_ent_rec ent; + + memset(&ent, 0, sizeof(ent)); + ent.policy = name; + check(kadm5_create_policy(handle, &ent, KADM5_POLICY)); + free_handle(handle); +} + +static void +delete_policy(char *name) +{ + void *handle = get_handle("admin"); + + check(kadm5_delete_policy(handle, name)); + free_handle(handle); +} + +static void +compare_policy(kadm5_policy_ent_t x, uint32_t mask) +{ + kadm5_policy_ent_rec g; + void *handle = get_handle("admin"); + + check(kadm5_get_policy(handle, x->policy, &g)); + + assert(strcmp(g.policy, x->policy) == 0); + if (mask & KADM5_PW_MAX_LIFE) + assert(g.pw_max_life == x->pw_max_life); + if (mask & KADM5_PW_MIN_LIFE) + assert(g.pw_min_life == x->pw_min_life); + if (mask & KADM5_PW_MIN_LENGTH) + assert(g.pw_min_length == x->pw_min_length); + if (mask & KADM5_PW_MIN_CLASSES) + assert(g.pw_min_classes == x->pw_min_classes); + if (mask & KADM5_PW_HISTORY_NUM) + assert(g.pw_history_num == x->pw_history_num); + if (mask & KADM5_PW_MAX_FAILURE) + assert(g.pw_max_fail == x->pw_max_fail); + if (mask & KADM5_PW_FAILURE_COUNT_INTERVAL) + assert(g.pw_failcnt_interval == x->pw_failcnt_interval); + if (mask & KADM5_PW_LOCKOUT_DURATION) + assert(g.pw_lockout_duration == x->pw_lockout_duration); + + check(kadm5_free_policy_ent(handle, &g)); + free_handle(handle); +} + +static void +create_simple_princ(krb5_principal princ, char *policy) +{ + void *handle = get_handle("admin"); + kadm5_principal_ent_rec ent; + uint32_t mask = KADM5_PRINCIPAL; + + memset(&ent, 0, sizeof(ent)); + ent.principal = princ; + ent.policy = policy; + if (policy != NULL) + mask |= KADM5_POLICY; + check(kadm5_create_principal(handle, &ent, mask, "pw")); + free_handle(handle); +} + +static void +delete_princ(krb5_principal princ) +{ + void *handle = get_handle("admin"); + + check(kadm5_delete_principal(handle, princ)); + free_handle(handle); +} + +static void +compare_key_data(kadm5_principal_ent_t ent, const krb5_enctype *etypes) +{ + int i; + + for (i = 0; etypes[i] != ENCTYPE_NULL; i++) { + assert(i < ent->n_key_data); + assert(ent->key_data[i].key_data_ver >= 1); + assert(ent->key_data[i].key_data_type[0] == etypes[i]); + } +} + +static void +compare_princ(kadm5_principal_ent_t x, uint32_t mask) +{ + void *handle = get_handle("admin"); + kadm5_principal_ent_rec g; + kadm5_policy_ent_rec pol; + + check(kadm5_get_principal(handle, x->principal, &g, + KADM5_PRINCIPAL_NORMAL_MASK)); + + assert(krb5_principal_compare(context, g.principal, x->principal)); + if (mask & KADM5_POLICY) + assert(strcmp(g.policy, x->policy) == 0); + if (mask & KADM5_PRINC_EXPIRE_TIME) + assert(g.princ_expire_time == x->princ_expire_time); + if (mask & KADM5_MAX_LIFE) + assert(g.max_life == x->max_life); + if (mask & KADM5_MAX_RLIFE) + assert(g.max_renewable_life == x->max_renewable_life); + if (mask & KADM5_FAIL_AUTH_COUNT) + assert(g.fail_auth_count == x->fail_auth_count); + if (mask & KADM5_ATTRIBUTES) + assert(g.attributes == x->attributes); + if (mask & KADM5_KVNO) + assert(g.kvno == x->kvno); + + if (mask & KADM5_PW_EXPIRATION) { + assert(g.pw_expiration == x->pw_expiration); + } else if ((mask & KADM5_POLICY) && + kadm5_get_policy(handle, g.policy, &pol) == 0) { + /* Check the policy pw_max_life computation. */ + if (pol.pw_max_life != 0) { + assert(ts_incr(g.last_pwd_change, pol.pw_max_life) == + g.pw_expiration); + } else { + assert(g.pw_expiration == 0); + } + check(kadm5_free_policy_ent(handle, &pol)); + } + + if (mask & KADM5_POLICY_CLR) { + assert(g.policy == NULL); + if (!(mask & KADM5_PW_EXPIRATION)) + assert(g.pw_expiration == 0); + } + + check(kadm5_free_principal_ent(handle, &g)); + free_handle(handle); +} + +static void +kinit(krb5_ccache cc, const char *user, const char *pass, const char *service) +{ + krb5_get_init_creds_opt *opt; + krb5_principal client = parse_princ(user); + krb5_creds creds; + + check(krb5_get_init_creds_opt_alloc(context, &opt)); + check(krb5_get_init_creds_opt_set_out_ccache(context, opt, cc)); + check(krb5_get_init_creds_password(context, &creds, client, pass, NULL, + NULL, 0, service, opt)); + krb5_get_init_creds_opt_free(context, opt); + krb5_free_cred_contents(context, &creds); + krb5_free_principal(context, client); +} + +static void +cpw_test_fail(char *user, krb5_principal princ, char *pass, + krb5_error_code code) +{ + void *handle = get_handle(user); + + check_fail(kadm5_chpass_principal(handle, princ, pass), code); + free_handle(handle); +} + +static void +cpw_test_succeed(char *user, krb5_principal princ, char *pass) +{ + cpw_test_fail(user, princ, pass, 0); +} + +static void +test_chpass() +{ + krb5_principal princ = parse_princ("chpass-test"); + krb5_principal hist_princ = parse_princ("kadmin/history"); + kadm5_principal_ent_rec ent; + void *handle; + + /* Specify a policy so that kadmin/history is created. */ + create_simple_princ(princ, "minlife-pol"); + + /* Check kvno and enctypes after a password change. */ + handle = get_handle("admin"); + check(kadm5_chpass_principal(handle, princ, "newpassword")); + check(kadm5_get_principal(handle, princ, &ent, KADM5_KEY_DATA)); + compare_key_data(&ent, default_supported_enctypes); + assert(ent.key_data[0].key_data_kvno == 2); + check(kadm5_free_principal_ent(handle, &ent)); + free_handle(handle); + + /* Fails for protected principal. */ + cpw_test_fail("admin", hist_princ, "pw", KADM5_PROTECT_PRINCIPAL); + + /* Fails over RPC if "change" ACL is not granted, or if we authenticated to + * kadmin/changepw and are changing another principal's password. */ + if (rpc) { + cpw_test_succeed("admin/modify", princ, "pw2"); + cpw_test_fail("admin/none", princ, "pw3", KADM5_AUTH_CHANGEPW); + cpw_test_fail("$admin", princ, "pw3", KADM5_AUTH_CHANGEPW); + } + + /* Fails with null handle or principal name. */ + cpw_test_fail(NULL, princ, "pw", KADM5_BAD_SERVER_HANDLE); + cpw_test_fail("admin", NULL, "pw", EINVAL); + + delete_princ(princ); + krb5_free_principal(context, princ); + krb5_free_principal(context, hist_princ); +} + +static void +cpol_test_fail(char *user, kadm5_policy_ent_t ent, uint32_t mask, + krb5_error_code code) +{ + void *handle = get_handle(user); + + check_fail(kadm5_create_policy(handle, ent, mask | KADM5_POLICY), code); + free_handle(handle); +} + +static void +cpol_test_compare(char *user, kadm5_policy_ent_t ent, uint32_t mask) +{ + cpol_test_fail(user, ent, mask, 0); + compare_policy(ent, mask); + delete_policy(ent->policy); +} + +static void +test_create_policy() +{ + void *handle; + kadm5_policy_ent_rec ent; + + memset(&ent, 0, sizeof(ent)); + + /* Fails with undefined mask bit. */ + ent.policy = "create-policy-test"; + cpol_test_fail("admin", &ent, 0x10000000, KADM5_BAD_MASK); + + /* Fails without KADM5_POLICY mask bit. */ + handle = get_handle("admin"); + check_fail(kadm5_create_policy(handle, &ent, 0), KADM5_BAD_MASK); + free_handle(handle); + + /* pw_min_life = 0 and pw_min_life != 0 */ + cpol_test_compare("admin", &ent, KADM5_PW_MIN_LIFE); + ent.pw_min_life = 32; + cpol_test_compare("admin", &ent, KADM5_PW_MIN_LIFE); + + /* pw_max_life = 0 and pw_max_life != 0 */ + cpol_test_compare("admin", &ent, KADM5_PW_MAX_LIFE); + ent.pw_max_life = 32; + cpol_test_compare("admin", &ent, KADM5_PW_MAX_LIFE); + + /* pw_min_length = 0 (rejected) and pw_min_length != 0 */ + cpol_test_fail("admin", &ent, KADM5_PW_MIN_LENGTH, KADM5_BAD_LENGTH); + ent.pw_min_length = 32; + cpol_test_compare("admin", &ent, KADM5_PW_MIN_LENGTH); + + /* pw_min_classes = 0 (rejected), 1, 5, 6 (rejected) */ + cpol_test_fail("admin", &ent, KADM5_PW_MIN_CLASSES, KADM5_BAD_CLASS); + ent.pw_min_classes = 1; + cpol_test_compare("admin", &ent, KADM5_PW_MIN_CLASSES); + ent.pw_min_classes = 5; + cpol_test_compare("admin", &ent, KADM5_PW_MIN_CLASSES); + ent.pw_min_classes = 6; + cpol_test_fail("admin", &ent, KADM5_PW_MIN_CLASSES, KADM5_BAD_CLASS); + + /* pw_history_num = 0 (rejected), 1, 10 */ + cpol_test_fail("admin", &ent, KADM5_PW_HISTORY_NUM, KADM5_BAD_HISTORY); + ent.pw_history_num = 1; + cpol_test_compare("admin", &ent, KADM5_PW_HISTORY_NUM); + ent.pw_history_num = 10; + cpol_test_compare("admin", &ent, KADM5_PW_HISTORY_NUM); + + if (api >= KADM5_API_VERSION_3) { + ent.pw_max_fail = 2; + cpol_test_compare("admin", &ent, KADM5_PW_MAX_FAILURE); + ent.pw_failcnt_interval = 90; + cpol_test_compare("admin", &ent, + KADM5_PW_FAILURE_COUNT_INTERVAL); + ent.pw_lockout_duration = 180; + cpol_test_compare("admin", &ent, KADM5_PW_LOCKOUT_DURATION); + } + + /* Fails over RPC if "add" ACL is not granted, or if we authenticated to + * kadmin/changepw. */ + if (rpc) { + cpol_test_fail("$admin", &ent, 0, KADM5_AUTH_ADD); + cpol_test_fail("admin/none", &ent, 0, KADM5_AUTH_ADD); + cpol_test_fail("admin/get", &ent, 0, KADM5_AUTH_ADD); + cpol_test_fail("admin/modify", &ent, 0, KADM5_AUTH_ADD); + cpol_test_fail("admin/delete", &ent, 0, KADM5_AUTH_ADD); + cpol_test_compare("admin/add", &ent, 0); + } + + /* Fails with existing policy name. */ + ent.policy = "test-pol"; + cpol_test_fail("admin", &ent, 0, KADM5_DUP); + + /* Fails with null or empty policy name, or invalid character in name. */ + ent.policy = NULL; + cpol_test_fail("admin", &ent, 0, EINVAL); + ent.policy = ""; + cpol_test_fail("admin", &ent, 0, KADM5_BAD_POLICY); + ent.policy = "pol\7"; + cpol_test_fail("admin", &ent, 0, KADM5_BAD_POLICY); + + /* Fails with null handle or policy ent. */ + cpol_test_fail(NULL, &ent, 0, KADM5_BAD_SERVER_HANDLE); + cpol_test_fail("admin", NULL, 0, EINVAL); +} + +static void +cprinc_test_fail(char *user, kadm5_principal_ent_t ent, uint32_t mask, + char *pass, krb5_error_code code) +{ + void *handle = get_handle(user); + + check_fail(kadm5_create_principal(handle, ent, mask | KADM5_PRINCIPAL, + pass), code); + free_handle(handle); +} + +static void +cprinc_test_compare(char *user, kadm5_principal_ent_t ent, uint32_t mask, + char *pass) +{ + cprinc_test_fail(user, ent, mask, pass, 0); + compare_princ(ent, mask); + delete_princ(ent->principal); +} + +static void +test_create_principal() +{ + void *handle; + kadm5_principal_ent_rec ent; + krb5_principal princ = parse_princ("create-principal-test"); + krb5_principal user_princ = parse_princ("user"); + + memset(&ent, 0, sizeof(ent)); + ent.principal = princ; + + /* Fails with undefined or prohibited mask bit. */ + cprinc_test_fail("admin", &ent, 0x100000, "", KADM5_BAD_MASK); + cprinc_test_fail("admin", &ent, KADM5_LAST_PWD_CHANGE, "pw", + KADM5_BAD_MASK); + cprinc_test_fail("admin", &ent, KADM5_MOD_TIME, "pw", KADM5_BAD_MASK); + cprinc_test_fail("admin", &ent, KADM5_MOD_NAME, "pw", KADM5_BAD_MASK); + cprinc_test_fail("admin", &ent, KADM5_MKVNO, "pw", KADM5_BAD_MASK); + cprinc_test_fail("admin", &ent, KADM5_AUX_ATTRIBUTES, "pw", + KADM5_BAD_MASK); + + /* Fails without KADM5_PRINCIPAL mask bit. */ + handle = get_handle("admin"); + check_fail(kadm5_create_principal(handle, &ent, 0, "pw"), KADM5_BAD_MASK); + free_handle(handle); + + /* Fails with empty password or password prohibited by policy. */ + cprinc_test_fail("admin", &ent, 0, "", KADM5_PASS_Q_TOOSHORT); + ent.policy = "test-pol"; + cprinc_test_fail("admin", &ent, KADM5_POLICY, "tP", KADM5_PASS_Q_TOOSHORT); + cprinc_test_fail("admin", &ent, KADM5_POLICY, "testpassword", + KADM5_PASS_Q_CLASS); + cprinc_test_fail("admin", &ent, KADM5_POLICY, "Abyssinia", + KADM5_PASS_Q_DICT); + + cprinc_test_compare("admin", &ent, 0, "pw"); + ent.policy = "nonexistent-pol"; + cprinc_test_compare("admin", &ent, KADM5_POLICY, "pw"); + cprinc_test_compare("admin/rename", &ent, KADM5_POLICY, "pw"); + + /* Test pw_expiration explicit specifications vs. policy pw_max_life. */ + ent.policy = "test-pol"; + cprinc_test_compare("admin", &ent, KADM5_POLICY, "NotinTheDictionary"); + cprinc_test_compare("admin", &ent, KADM5_PRINC_EXPIRE_TIME, "pw"); + cprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION, "pw"); + cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION, + "NotinTheDictionary"); + ent.pw_expiration = 1234; + cprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION, "pw"); + cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION, + "NotinTheDictionary"); + ent.pw_expiration = 999999999; + cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION, + "NotinTheDictionary"); + ent.policy = "dict-only-pol"; + cprinc_test_compare("admin", &ent, KADM5_POLICY | KADM5_PW_EXPIRATION, + "pw"); + + /* Fails over RPC if "add" ACL is not granted, or if we authenticated to + * kadmin/changepw. */ + if (rpc) { + cprinc_test_fail("$admin", &ent, 0, "pw", KADM5_AUTH_ADD); + cprinc_test_fail("admin/none", &ent, 0, "pw", KADM5_AUTH_ADD); + cprinc_test_fail("admin/get", &ent, 0, "pw", KADM5_AUTH_ADD); + cprinc_test_fail("admin/modify", &ent, 0, "pw", KADM5_AUTH_ADD); + cprinc_test_fail("admin/delete", &ent, 0, "pw", KADM5_AUTH_ADD); + } + + /* Fails with existing policy name. */ + ent.principal = user_princ; + cprinc_test_fail("admin", &ent, 0, "pw", KADM5_DUP); + + /* Fails with null handle or principal ent. */ + cprinc_test_fail(NULL, &ent, 0, "pw", KADM5_BAD_SERVER_HANDLE); + cprinc_test_fail("admin", NULL, 0, "pw", EINVAL); + + krb5_free_principal(context, princ); + krb5_free_principal(context, user_princ); +} + +static void +dpol_test_fail(char *user, char *name, krb5_error_code code) +{ + void *handle = get_handle(user); + + check_fail(kadm5_delete_policy(handle, name), code); + free_handle(handle); +} + +static void +dpol_test_succeed(char *user, char *name) +{ + dpol_test_fail(user, name, 0); +} + +static void +test_delete_policy() +{ + krb5_principal princ = parse_princ("delete-policy-test-princ"); + + /* Fails with unknown policy. */ + dpol_test_fail("admin", "delete-policy-test", KADM5_UNK_POLICY); + + /* Fails with empty policy name. */ + dpol_test_fail("admin", "", KADM5_BAD_POLICY); + + /* Succeeds with "delete" ACL (or local authentication). */ + create_simple_policy("delete-policy-test"); + dpol_test_succeed("admin/delete", "delete-policy-test"); + + /* Succeeds even if a principal references the policy, since we now allow + * principals to reference nonexistent policies. */ + create_simple_policy("delete-policy-test"); + create_simple_princ(princ, "delete-policy-test"); + dpol_test_succeed("admin", "delete-policy-test"); + delete_princ(princ); + + /* Fails over RPC if "delete" ACL is not granted, or if we authenticated to + * kadmin/changepw. */ + if (rpc) { + dpol_test_fail("$admin", "test-pol", KADM5_AUTH_DELETE); + dpol_test_fail("admin/none", "test-pol", KADM5_AUTH_DELETE); + dpol_test_fail("admin/add", "test-pol", KADM5_AUTH_DELETE); + } + + /* Fails with null handle or principal ent. */ + dpol_test_fail(NULL, "test-pol", KADM5_BAD_SERVER_HANDLE); + dpol_test_fail("admin", NULL, EINVAL); + + krb5_free_principal(context, princ); +} + +static void +dprinc_test_fail(char *user, krb5_principal princ, krb5_error_code code) +{ + void *handle = get_handle(user); + + check_fail(kadm5_delete_principal(handle, princ), code); + free_handle(handle); +} + +static void +dprinc_test_succeed(char *user, krb5_principal princ) +{ + dprinc_test_fail(user, princ, 0); +} + +static void +test_delete_principal() +{ + krb5_principal princ = parse_princ("delete-principal-test"); + + /* Fails with unknown principal. */ + dprinc_test_fail("admin", princ, KADM5_UNK_PRINC); + + /* Succeeds with "delete" ACL (or local authentication). */ + create_simple_princ(princ, NULL); + dprinc_test_succeed("admin/delete", princ); + + /* Fails over RPC if "delete" ACL is not granted, or if we authenticated to + * kadmin/changepw. */ + if (rpc) { + dprinc_test_fail("$admin", princ, KADM5_AUTH_DELETE); + dprinc_test_fail("admin/add", princ, KADM5_AUTH_DELETE); + dprinc_test_fail("admin/modify", princ, KADM5_AUTH_DELETE); + dprinc_test_fail("admin/get", princ, KADM5_AUTH_DELETE); + dprinc_test_fail("admin/none", princ, KADM5_AUTH_DELETE); + } + + /* Fails with null handle or principal ent. */ + dprinc_test_fail(NULL, princ, KADM5_BAD_SERVER_HANDLE); + dprinc_test_fail("admin", NULL, EINVAL); + + krb5_free_principal(context, princ); +} + +static void +gpol_test_succeed(char *user, char *name) +{ + void *handle = get_handle(user); + kadm5_policy_ent_rec ent; + + check(kadm5_get_policy(handle, name, &ent)); + assert(strcmp(ent.policy, name) == 0); + check(kadm5_free_policy_ent(handle, &ent)); + free_handle(handle); +} + +static void +gpol_test_fail(char *user, char *name, krb5_error_code code) +{ + void *handle = get_handle(user); + kadm5_policy_ent_rec ent; + + check_fail(kadm5_get_policy(handle, name, &ent), code); + free_handle(handle); +} + +static void +test_get_policy() +{ + /* Fails with unknown policy. */ + dpol_test_fail("admin", "unknown-policy", KADM5_UNK_POLICY); + + /* Fails with empty or null policy name or a null handle. */ + gpol_test_fail("admin", "", KADM5_BAD_POLICY); + gpol_test_fail("admin", NULL, EINVAL); + gpol_test_fail(NULL, "", KADM5_BAD_SERVER_HANDLE); + + /* Fails over RPC unless "get" ACL is granted or the principal's own policy + * is retrieved. */ + if (rpc) { + gpol_test_fail("admin/none", "test-pol", KADM5_AUTH_GET); + gpol_test_fail("admin/add", "test-pol", KADM5_AUTH_GET); + gpol_test_succeed("admin/get", "test-pol"); + gpol_test_succeed("user", "minlife-pol"); + gpol_test_succeed("$user", "minlife-pol"); + } +} + +static void +gprinc_test_succeed(char *user, krb5_principal princ) +{ + void *handle = get_handle(user); + kadm5_principal_ent_rec ent; + + check(kadm5_get_principal(handle, princ, &ent, + KADM5_PRINCIPAL_NORMAL_MASK)); + assert(krb5_principal_compare(context, ent.principal, princ)); + check(kadm5_free_principal_ent(handle, &ent)); + free_handle(handle); +} + +static void +gprinc_test_fail(char *user, krb5_principal princ, krb5_error_code code) +{ + void *handle = get_handle(user); + kadm5_principal_ent_rec ent; + + check_fail(kadm5_get_principal(handle, princ, &ent, + KADM5_PRINCIPAL_NORMAL_MASK), code); + free_handle(handle); +} + +static void +test_get_principal() +{ + void *handle; + kadm5_principal_ent_rec ent; + krb5_principal princ = parse_princ("get-principal-test"); + krb5_principal admin_princ = parse_princ("admin"); + krb5_principal admin_none_princ = parse_princ("admin/none"); + int i; + + /* Fails with unknown principal. */ + gprinc_test_fail("admin", princ, KADM5_UNK_PRINC); + + create_simple_princ(princ, NULL); + + /* Succeeds with "get" ACL (or local authentication), or operating on + * self. */ + gprinc_test_succeed("admin/none", admin_none_princ); + gprinc_test_succeed("$admin", admin_princ); + gprinc_test_succeed("admin/get", princ); + + /* Fails over RPC if "get" ACL is not granted, or if we authenticated to + * kadmin/changepw and getting another principal entry. */ + if (rpc) { + gprinc_test_fail("$admin", princ, KADM5_AUTH_GET); + gprinc_test_fail("admin/none", princ, KADM5_AUTH_GET); + gprinc_test_fail("admin/add", princ, KADM5_AUTH_GET); + gprinc_test_fail("admin/modify", princ, KADM5_AUTH_GET); + gprinc_test_fail("admin/delete", princ, KADM5_AUTH_GET); + } + + /* Entry contains no key data or tl-data unless asked for. */ + handle = get_handle("admin"); + check(kadm5_get_principal(handle, princ, &ent, + KADM5_PRINCIPAL_NORMAL_MASK)); + assert(ent.n_tl_data == 0); + assert(ent.n_key_data == 0); + assert(ent.tl_data == NULL); + check(kadm5_free_principal_ent(handle, &ent)); + + /* Key data (without the actual keys over RPC) is provided if asked for. */ + check(kadm5_get_principal(handle, princ, &ent, + KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA)); + assert(ent.n_key_data == 2); + for (i = 0; i < ent.n_key_data; i++) + assert(rpc == (ent.key_data[i].key_data_length[0] == 0)); + check(kadm5_free_principal_ent(handle, &ent)); + free_handle(handle); + + /* Fails with null handle or principal. */ + gprinc_test_fail(NULL, princ, KADM5_BAD_SERVER_HANDLE); + gprinc_test_fail("admin", NULL, EINVAL); + + delete_princ(princ); + krb5_free_principal(context, princ); + krb5_free_principal(context, admin_princ); + krb5_free_principal(context, admin_none_princ); +} + +static void +test_init_destroy() +{ + krb5_context ctx; + kadm5_ret_t ret; + kadm5_config_params params; + kadm5_principal_ent_rec ent, gent; + krb5_principal princ = parse_princ("init-test"); + krb5_ccache cc; + void *handle; + char hostname[MAXHOSTNAMELEN]; + int r; + + memset(¶ms, 0, sizeof(params)); + memset(&ent, 0, sizeof(ent)); + ent.principal = princ; + + r = gethostname(hostname, sizeof(hostname)); + assert(r == 0); + + /* Destroy fails with no server handle. */ + check_fail(kadm5_destroy(NULL), KADM5_BAD_SERVER_HANDLE); + + /* Fails with bad structure version mask. */ + check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, + 0x65432101, api, NULL, &handle), + KADM5_BAD_STRUCT_VERSION); + check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, + 1, api, NULL, &handle), KADM5_BAD_STRUCT_VERSION); + + /* Fails with too-old or too-new structure version. */ + check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION_MASK, api, NULL, &handle), + KADM5_OLD_STRUCT_VERSION); + check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION_MASK | 0xca, api, NULL, + &handle), KADM5_NEW_STRUCT_VERSION); + + /* Fails with bad API version mask. */ + check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, 0x65432100, NULL, &handle), + KADM5_BAD_API_VERSION); + check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, 4, NULL, &handle), + KADM5_BAD_API_VERSION); + + /* Fails with too-old or too-new API version.*/ + ret = kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, KADM5_API_VERSION_MASK, NULL, + &handle); + assert(ret == (rpc ? KADM5_OLD_LIB_API_VERSION : + KADM5_OLD_SERVER_API_VERSION)); + ret = kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, KADM5_API_VERSION_MASK | 0xca, NULL, + &handle); + assert(ret == (rpc ? KADM5_NEW_LIB_API_VERSION : + KADM5_NEW_SERVER_API_VERSION)); + + /* Fails with structure and API version reversed. */ + check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, NULL, + api, KADM5_STRUCT_VERSION, NULL, &handle), + KADM5_BAD_STRUCT_VERSION); + + /* Hardcoded default max lifetime is used when no handle or krb5.conf + * setting is given. */ + handle = get_handle("admin"); + check(kadm5_create_principal(handle, &ent, KADM5_PRINCIPAL, "pw")); + check(kadm5_get_principal(handle, princ, &gent, + KADM5_PRINCIPAL_NORMAL_MASK)); + assert(gent.max_life == KRB5_KDB_MAX_LIFE); + check(kadm5_delete_principal(handle, princ)); + check(kadm5_free_principal_ent(handle, &gent)); + free_handle(handle); + + /* Fails with configured unknown realm. Do these tests in separate krb5 + * contexts since the realm setting sticks to the context. */ + check(kadm5_init_krb5_context(&ctx)); + params.realm = ""; + params.mask = KADM5_CONFIG_REALM; + ret = kadm5_init(ctx, "admin", "admin", KADM5_ADMIN_SERVICE, ¶ms, + KADM5_STRUCT_VERSION, api, NULL, &handle); + assert(ret == (rpc ? KADM5_MISSING_KRB5_CONF_PARAMS : ENOENT)); + krb5_free_context(ctx); + + check(kadm5_init_krb5_context(&ctx)); + params.realm = "@"; + ret = kadm5_init(ctx, "admin", "admin", KADM5_ADMIN_SERVICE, ¶ms, + KADM5_STRUCT_VERSION, api, NULL, &handle); + assert(ret == (rpc ? KADM5_MISSING_KRB5_CONF_PARAMS : ENOENT)); + krb5_free_context(ctx); + + check(kadm5_init_krb5_context(&ctx)); + params.realm = "BAD.REALM"; + ret = kadm5_init(ctx, "admin", "admin", KADM5_ADMIN_SERVICE, ¶ms, + KADM5_STRUCT_VERSION, api, NULL, &handle); + assert(ret == (rpc ? KADM5_MISSING_KRB5_CONF_PARAMS : ENOENT)); + krb5_free_context(ctx); + + /* Succeeds with explicit client realm and configured realm. */ + check(kadm5_init_krb5_context(&ctx)); + params.realm = "KRBTEST.COM"; + check(kadm5_init(ctx, "admin@KRBTEST.COM", "admin", KADM5_ADMIN_SERVICE, + ¶ms, KADM5_STRUCT_VERSION, api, NULL, &handle)); + check(kadm5_destroy(handle)); + krb5_free_context(ctx); + + /* Succeeds with explicit client realm. */ + check(kadm5_init(context, "admin@KRBTEST.COM", "admin", + KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION, api, + NULL, &handle)); + check(kadm5_destroy(handle)); + + + if (rpc) { + check(krb5_cc_default(context, &cc)); + + /* Succeeds with configured host and port. */ + params.admin_server = hostname; + params.kadmind_port = 61001; + params.mask = KADM5_CONFIG_ADMIN_SERVER | KADM5_CONFIG_KADMIND_PORT; + check(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, + ¶ms, KADM5_STRUCT_VERSION, api, NULL, &handle)); + check(kadm5_destroy(handle)); + + /* Fails with wrong configured port. */ + params.kadmind_port = 4; + check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, + ¶ms, KADM5_STRUCT_VERSION, api, NULL, + &handle), KADM5_RPC_ERROR); + + /* Fails with non-resolving hostname. */ + params.admin_server = "does.not.exist"; + params.mask = KADM5_CONFIG_ADMIN_SERVER; + check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, + ¶ms, KADM5_STRUCT_VERSION, api, NULL, + &handle), KADM5_CANT_RESOLVE); + + /* Fails with uninitialized cache. */ + check_fail(kadm5_init_with_creds(context, "admin", cc, + KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, api, NULL, + &handle), KRB5_FCC_NOFILE); + + /* Succeeds with cache containing kadmin/admin cred. */ + kinit(cc, "admin", "admin", KADM5_ADMIN_SERVICE); + check(kadm5_init_with_creds(context, "admin", cc, KADM5_ADMIN_SERVICE, + NULL, KADM5_STRUCT_VERSION, api, NULL, + &handle)); + check(kadm5_destroy(handle)); + + /* Succeeds with cache containing kadmin/changepw cred. */ + kinit(cc, "admin", "admin", KADM5_CHANGEPW_SERVICE); + check(kadm5_init_with_creds(context, "admin", cc, + KADM5_CHANGEPW_SERVICE, NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle)); + check(kadm5_destroy(handle)); + + /* Fails with cache containing only a TGT. */ + kinit(cc, "admin", "admin", NULL); + check_fail(kadm5_init_with_creds(context, "admin", cc, + KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, api, NULL, + &handle), KRB5_CC_NOTFOUND); + + /* Fails authenticating to non-kadmin princ. */ + check_fail(kadm5_init(context, "admin", "admin", "user", NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle), + KADM5_RPC_ERROR); + + /* Fails authenticating to nonexistent princ. */ + check_fail(kadm5_init(context, "admin", "admin", "noexist", NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle), + KADM5_SECURE_PRINC_MISSING); + + /* Fails authenticating to client princ (which is non-kadmin). */ + check_fail(kadm5_init(context, "admin", "admin", "admin", NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle), + KADM5_RPC_ERROR); + + /* Fails with wrong password. */ + check_fail(kadm5_init(context, "admin", "wrong", KADM5_ADMIN_SERVICE, + NULL, KADM5_STRUCT_VERSION, api, NULL, &handle), + KADM5_BAD_PASSWORD); + + /* Fails with null client name. */ + check_fail(kadm5_init(context, NULL, "admin", KADM5_ADMIN_SERVICE, + NULL, KADM5_STRUCT_VERSION, api, NULL, &handle), + EINVAL); + + /* Fails with nonexistent client name. */ + check_fail(kadm5_init(context, "noexist", "admin", KADM5_ADMIN_SERVICE, + NULL, KADM5_STRUCT_VERSION, api, NULL, &handle), + KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN); + + /* Fails with nonexistent client name with explicit realm. */ + check_fail(kadm5_init(context, "noexist@KRBTEST.COM", "admin", + KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION, + api, NULL, &handle), + KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN); + + /* Fails with nonexistent client name with unknown realm. */ + check_fail(kadm5_init(context, "noexist@BAD.REALM", "admin", + KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION, + api, NULL, &handle), KRB5_REALM_UNKNOWN); + + /* Fails with known name but unknown realm. */ + check_fail(kadm5_init(context, "admin@BAD.REALM", "admin", + KADM5_ADMIN_SERVICE, NULL, KADM5_STRUCT_VERSION, + api, NULL, &handle), KRB5_REALM_UNKNOWN); + + check(krb5_cc_destroy(context, cc)); + } else { + /* Fails with nonexistent stash file. */ + params.stash_file = "does/not/exist"; + params.mask = KADM5_CONFIG_STASH_FILE; + check_fail(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, + ¶ms, KADM5_STRUCT_VERSION, api, NULL, + &handle), KRB5_KDB_CANTREAD_STORED); + + /* Uses configured defaults for principal creation. */ + params.max_life = 10; + params.max_rlife = 20; + params.expiration = 30; + params.num_keysalts = 0; + params.mask = KADM5_CONFIG_MAX_LIFE | KADM5_CONFIG_MAX_RLIFE | + KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_ENCTYPES; + check(kadm5_init(context, "admin", "admin", KADM5_ADMIN_SERVICE, + ¶ms, KADM5_STRUCT_VERSION, api, NULL, &handle)); + check(kadm5_create_principal(handle, &ent, KADM5_PRINCIPAL, "pw")); + check(kadm5_get_principal(handle, princ, &gent, + KADM5_PRINCIPAL_NORMAL_MASK | + KADM5_KEY_DATA)); + assert(gent.max_life == 10); + assert(gent.max_renewable_life == 20); + assert(gent.princ_expire_time == 30); + assert(gent.n_key_data == 0); + check(kadm5_delete_principal(handle, princ)); + check(kadm5_free_principal_ent(handle, &gent)); + check(kadm5_destroy(handle)); + + /* Succeeds with incorrect password using local auth. */ + check(kadm5_init(context, "admin", "wrong", KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle)); + check(kadm5_destroy(handle)); + + /* Succeeds with null service using local auth. */ + check(kadm5_init(context, "admin", "admin", NULL, NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle)); + check(kadm5_destroy(handle)); + + /* Succeeds with nonexistent, non-kadmin service using local auth. */ + check(kadm5_init(context, "admin", "admin", "foobar", NULL, + KADM5_STRUCT_VERSION, api, NULL, &handle)); + check(kadm5_destroy(handle)); + } + + krb5_free_principal(context, princ); +} + +static void +mpol_test_fail(char *user, kadm5_policy_ent_t ent, uint32_t mask, + krb5_error_code code) +{ + void *handle = get_handle(user); + + check_fail(kadm5_modify_policy(handle, ent, mask), code); + free_handle(handle); +} + +static void +mpol_test_compare(void *handle, kadm5_policy_ent_t ent, uint32_t mask) +{ + mpol_test_fail(handle, ent, mask, 0); + compare_policy(ent, mask); +} + +static void +test_modify_policy() +{ + kadm5_policy_ent_rec ent; + + memset(&ent, 0, sizeof(ent)); + ent.policy = "modify-policy-test"; + create_simple_policy(ent.policy); + + /* pw_min_life = 0 and pw_min_life != 0 */ + mpol_test_compare("admin", &ent, KADM5_PW_MIN_LIFE); + ent.pw_min_life = 32; + mpol_test_compare("admin", &ent, KADM5_PW_MIN_LIFE); + + /* pw_max_life = 0 and pw_max_life != 0 */ + mpol_test_compare("admin", &ent, KADM5_PW_MAX_LIFE); + ent.pw_max_life = 32; + mpol_test_compare("admin", &ent, KADM5_PW_MAX_LIFE); + + /* pw_min_length = 0 (rejected) and pw_min_length != 0 */ + mpol_test_fail("admin", &ent, KADM5_PW_MIN_LENGTH, KADM5_BAD_LENGTH); + ent.pw_min_length = 8; + mpol_test_compare("admin", &ent, KADM5_PW_MIN_LENGTH); + + /* pw_min_classes = 0 (rejected), 1, 5, 6 (rejected) */ + mpol_test_fail("admin", &ent, KADM5_PW_MIN_CLASSES, KADM5_BAD_CLASS); + ent.pw_min_classes = 1; + mpol_test_compare("admin", &ent, KADM5_PW_MIN_CLASSES); + ent.pw_min_classes = 5; + mpol_test_compare("admin", &ent, KADM5_PW_MIN_CLASSES); + ent.pw_min_classes = 6; + mpol_test_fail("admin", &ent, KADM5_PW_MIN_CLASSES, KADM5_BAD_CLASS); + + /* pw_history_num = 0 (rejected), 1, 10 */ + mpol_test_fail("admin", &ent, KADM5_PW_HISTORY_NUM, KADM5_BAD_HISTORY); + ent.pw_history_num = 1; + mpol_test_compare("admin", &ent, KADM5_PW_HISTORY_NUM); + ent.pw_history_num = 10; + mpol_test_compare("admin", &ent, KADM5_PW_HISTORY_NUM); + + if (api >= KADM5_API_VERSION_3) { + ent.pw_max_fail = 2; + mpol_test_compare("admin", &ent, KADM5_PW_MAX_FAILURE); + ent.pw_failcnt_interval = 90; + mpol_test_compare("admin", &ent, KADM5_PW_FAILURE_COUNT_INTERVAL); + ent.pw_lockout_duration = 180; + mpol_test_compare("admin", &ent, KADM5_PW_LOCKOUT_DURATION); + } + + /* Fails over RPC if "modify" ACL is not granted, or if we authenticated to + * kadmin/changepw. */ + if (rpc) { + mpol_test_fail("$admin", &ent, KADM5_PW_MAX_LIFE, KADM5_AUTH_MODIFY); + mpol_test_fail("admin/none", &ent, KADM5_PW_MAX_LIFE, + KADM5_AUTH_MODIFY); + mpol_test_fail("admin/get", &ent, KADM5_PW_MAX_LIFE, + KADM5_AUTH_MODIFY); + mpol_test_compare("admin/modify", &ent, KADM5_PW_MAX_LIFE); + } + + delete_policy(ent.policy); + + /* Fails with empty or null policy name. */ + ent.policy = NULL; + mpol_test_fail("admin", &ent, KADM5_PW_MAX_LIFE, EINVAL); + ent.policy = ""; + mpol_test_fail("admin", &ent, KADM5_PW_MAX_LIFE, KADM5_BAD_POLICY); + + /* Fails with null handle or policy ent. */ + mpol_test_fail(NULL, &ent, KADM5_PW_MAX_LIFE, KADM5_BAD_SERVER_HANDLE); + mpol_test_fail("admin", NULL, KADM5_PW_MAX_LIFE, EINVAL); +} + +static void +mprinc_test_fail(char *user, kadm5_principal_ent_t ent, uint32_t mask, + krb5_error_code code) +{ + void *handle = get_handle(user); + + check_fail(kadm5_modify_principal(handle, ent, mask), code); + free_handle(handle); +} + +static void +mprinc_test_compare(char *user, kadm5_principal_ent_t ent, uint32_t mask) +{ + mprinc_test_fail(user, ent, mask, 0); + compare_princ(ent, mask); +} + +static void +test_modify_principal() +{ + void *handle; + krb5_principal princ = parse_princ("modify-principal-test"); + kadm5_principal_ent_rec ent; + krb5_tl_data tl = { NULL, 1, 1, (uint8_t *)"x" }; + krb5_tl_data tl2 = { NULL, 999, 6, (uint8_t *)"foobar" }; + + memset(&ent, 0, sizeof(ent)); + ent.principal = princ; + + /* Fails with unknown principal. */ + mprinc_test_fail("admin", &ent, KADM5_KVNO, KADM5_UNK_PRINC); + + create_simple_princ(princ, NULL); + + /* Fails with prohibited mask bit or tl-data type. */ + mprinc_test_fail("admin", &ent, KADM5_AUX_ATTRIBUTES, KADM5_BAD_MASK); + mprinc_test_fail("admin", &ent, KADM5_KEY_DATA, KADM5_BAD_MASK); + mprinc_test_fail("admin", &ent, KADM5_LAST_FAILED, KADM5_BAD_MASK); + mprinc_test_fail("admin", &ent, KADM5_LAST_SUCCESS, KADM5_BAD_MASK); + mprinc_test_fail("admin", &ent, KADM5_LAST_PWD_CHANGE, KADM5_BAD_MASK); + mprinc_test_fail("admin", &ent, KADM5_MKVNO, KADM5_BAD_MASK); + mprinc_test_fail("admin", &ent, KADM5_MOD_NAME, KADM5_BAD_MASK); + mprinc_test_fail("admin", &ent, KADM5_MOD_TIME, KADM5_BAD_MASK); + mprinc_test_fail("admin", &ent, KADM5_PRINCIPAL, KADM5_BAD_MASK); + + /* Fails with tl-data type below 256. */ + ent.n_tl_data = 1; + ent.tl_data = &tl; + mprinc_test_fail("admin", &ent, KADM5_TL_DATA, KADM5_BAD_TL_TYPE); + + /* Fails with fail_auth_count other than zero. */ + ent.fail_auth_count = 1234; + mprinc_test_fail("admin", &ent, KADM5_FAIL_AUTH_COUNT, + KADM5_BAD_SERVER_PARAMS); + ent.fail_auth_count = 0; + + /* Succeeds with zero values of various fields. */ + mprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION); + mprinc_test_compare("admin", &ent, KADM5_MAX_LIFE); + mprinc_test_compare("admin", &ent, KADM5_MAX_RLIFE); + mprinc_test_compare("admin", &ent, KADM5_FAIL_AUTH_COUNT); + mprinc_test_compare("admin/modify", &ent, KADM5_PRINC_EXPIRE_TIME); + mprinc_test_compare("admin", &ent, KADM5_POLICY_CLR); + + /* Setting a policy causes a pw_expiration computation. Explicit + * PW_EXPIRATION overrides the policy. */ + ent.pw_expiration = 1234; + mprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION); + ent.policy = "dict-only-pol"; + mprinc_test_compare("admin", &ent, KADM5_POLICY); + ent.policy = "test-pol"; + mprinc_test_compare("admin", &ent, KADM5_POLICY); + ent.pw_expiration = 999999999; + mprinc_test_compare("admin", &ent, KADM5_PW_EXPIRATION); + mprinc_test_compare("admin", &ent, KADM5_POLICY_CLR); + + /* Succeeds with non-zero values of various fields. */ + ent.princ_expire_time = 1234; + mprinc_test_compare("admin", &ent, KADM5_PRINC_EXPIRE_TIME); + ent.attributes = KRB5_KDB_DISALLOW_ALL_TIX; + mprinc_test_compare("admin", &ent, KADM5_ATTRIBUTES); + ent.attributes = KRB5_KDB_REQUIRES_PWCHANGE; + mprinc_test_compare("admin", &ent, KADM5_ATTRIBUTES); + ent.attributes = KRB5_KDB_DISALLOW_TGT_BASED; + mprinc_test_compare("admin", &ent, KADM5_ATTRIBUTES); + ent.max_life = 3456; + mprinc_test_compare("admin", &ent, KADM5_MAX_LIFE); + ent.kvno = 7; + mprinc_test_compare("admin", &ent, KADM5_KVNO); + + /* Fails over RPC if "modify" ACL is not granted, or if we authenticated to + * kadmin/changepw. */ + if (rpc) { + mprinc_test_fail("$admin", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY); + mprinc_test_fail("admin/none", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY); + mprinc_test_fail("admin/get", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY); + mprinc_test_fail("admin/add", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY); + mprinc_test_fail("admin/delete", &ent, KADM5_KVNO, KADM5_AUTH_MODIFY); + } + + /* tl-data of type > 255 is accepted. */ + handle = get_handle("admin"); + ent.max_renewable_life = 88; + ent.tl_data = &tl2; + check(kadm5_modify_principal(handle, &ent, + KADM5_MAX_RLIFE | KADM5_TL_DATA)); + memset(&ent, 0, sizeof(ent)); + check(kadm5_get_principal(handle, princ, &ent, + KADM5_PRINCIPAL_NORMAL_MASK | KADM5_TL_DATA)); + assert(ent.max_renewable_life == 88); + assert(ent.n_tl_data == 1); + assert(ent.tl_data->tl_data_type == tl2.tl_data_type); + assert(ent.tl_data->tl_data_length == tl2.tl_data_length); + assert(memcmp(ent.tl_data->tl_data_contents, tl2.tl_data_contents, + tl2.tl_data_length) == 0); + check(kadm5_free_principal_ent(handle, &ent)); + free_handle(handle); + + /* Fails with null handle or principal ent. */ + mprinc_test_fail(NULL, &ent, KADM5_KVNO, KADM5_BAD_SERVER_HANDLE); + mprinc_test_fail("admin", NULL, KADM5_KVNO, EINVAL); + + delete_princ(princ); + krb5_free_principal(context, princ); +} + +static void +rnd_test_fail(char *user, krb5_principal princ, krb5_error_code code) +{ + void *handle = get_handle(user); + + check_fail(kadm5_randkey_principal(handle, princ, NULL, NULL), code); + free_handle(handle); +} + +static void +rnd_test_succeed(char *user, krb5_principal princ) +{ + rnd_test_fail(user, princ, 0); +} + +static void +test_randkey() +{ + void *handle; + krb5_principal princ = parse_princ("randkey-principal-test"); + krb5_principal user_princ = parse_princ("user"); + krb5_principal admin_princ = parse_princ("admin"); + kadm5_principal_ent_rec ent; + krb5_keyblock *keys; + int n_keys, i; + + create_simple_princ(princ, NULL); + + /* Check kvno and enctypes after randkey. */ + handle = get_handle("admin"); + check(kadm5_randkey_principal(handle, princ, &keys, &n_keys)); + check(kadm5_get_principal(handle, princ, &ent, KADM5_KEY_DATA)); + compare_key_data(&ent, default_supported_enctypes); + assert(ent.key_data[0].key_data_kvno == 2); + assert(n_keys == ent.n_key_data); + for (i = 0; i < n_keys; i++) + krb5_free_keyblock_contents(context, &keys[i]); + free(keys); + check(kadm5_free_principal_ent(handle, &ent)); + free_handle(handle); + + /* + * Fails over RPC if "change" ACL is not granted, or if we authenticated to + * kadmin/changepw and are changing another principal's password, or for + * self-service if the policy minimum life has not elapsed since the last + * key change. + */ + if (rpc) { + rnd_test_fail("$admin", user_princ, KADM5_AUTH_CHANGEPW); + rnd_test_fail("admin/none", user_princ, KADM5_AUTH_CHANGEPW); + rnd_test_fail("admin/delete", user_princ, KADM5_AUTH_CHANGEPW); + rnd_test_succeed("admin/modify", user_princ); + cpw_test_succeed("admin", user_princ, USER_PASSWORD); + rnd_test_fail("user", user_princ, KADM5_PASS_TOOSOON); + rnd_test_fail("$user", user_princ, KADM5_PASS_TOOSOON); + } + + /* Succeeds with change privilege in spite of policy minimum life. */ + rnd_test_succeed("admin/modify", user_princ); + cpw_test_succeed("admin", user_princ, USER_PASSWORD); + + /* Succeeds for self-service when authenticating to kadmin/changepw. */ + handle = get_handle("$admin"); + check(kadm5_randkey_principal(handle, admin_princ, NULL, NULL)); + check(kadm5_chpass_principal(handle, admin_princ, ADMIN_PASSWORD)); + free_handle(handle); + + /* Fails with null handle or principal name. */ + rnd_test_fail(NULL, princ, KADM5_BAD_SERVER_HANDLE); + rnd_test_fail("admin", NULL, EINVAL); + + delete_princ(princ); + krb5_free_principal(context, princ); + krb5_free_principal(context, user_princ); + krb5_free_principal(context, admin_princ); +} + +int +main(int argc, char **argv) +{ + assert(argc == 2); + rpc = (strcmp(argv[1], "clnt") == 0); + + check(kadm5_init_krb5_context(&context)); + + api = KADM5_API_VERSION_2; + test_create_policy(); + test_get_policy(); + test_modify_policy(); + + api = KADM5_API_VERSION_4; + test_chpass(); + test_create_policy(); + test_create_principal(); + test_delete_policy(); + test_delete_principal(); + test_get_policy(); + test_get_principal(); + test_init_destroy(); + test_modify_policy(); + test_modify_principal(); + test_randkey(); + + krb5_free_context(context); + + return 0; +} diff --git a/krb5-1.21.3/src/lib/kadm5/t_kadm5.py b/krb5-1.21.3/src/lib/kadm5/t_kadm5.py new file mode 100644 index 00000000..c218b67c --- /dev/null +++ b/krb5-1.21.3/src/lib/kadm5/t_kadm5.py @@ -0,0 +1,45 @@ +from k5test import * + +# Specify a supported_enctypes so the chpass tests know what to expect. +supported_enctypes = 'aes256-cts:normal aes128-cts:normal' +conf = {'realms': {'$realm': {'supported_enctypes': supported_enctypes}}} +realm = K5Realm(create_user=False, create_host=False, kdc_conf=conf) + +with open(os.path.join(realm.testdir, 'acl'), 'w') as f: + f.write(''' +admin admcilse +admin/get il +admin/modify mc +admin/delete d +admin/add a +admin/rename adil +''') + +with open(os.path.join(realm.testdir, 'dictfile'), 'w') as f: + f.write(''' +Abyssinia +Discordianism +foo +''') + +realm.start_kadmind() + +realm.run([kadminl, 'addpol', '-maxlife', '10000s', '-minlength', '8', + '-minclasses', '2', '-maxfailure', '2', + '-failurecountinterval', '90s', '-lockoutduration', '180s', + 'test-pol']) +realm.run([kadminl, 'addpol', '-minlife', '10s', 'minlife-pol']) +realm.run([kadminl, 'addpol', 'dict-only-pol']) +realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin']) +realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin/get']) +realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin/modify']) +realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin/delete']) +realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin/add']) +realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin/rename']) +realm.run([kadminl, 'addprinc', '-pw', 'admin', 'admin/none']) +realm.run([kadminl, 'addprinc', '-pw', 'us3r', '-policy', 'minlife-pol', + 'user']) + +realm.run(['./t_kadm5srv', 'srv']) +realm.run(['./t_kadm5clnt', 'clnt']) +success('kadm5 API tests') diff --git a/krb5-1.21.3/src/lib/kdb/Makefile.in b/krb5-1.21.3/src/lib/kdb/Makefile.in new file mode 100644 index 00000000..8b346c74 --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/Makefile.in @@ -0,0 +1,84 @@ +mydir=lib$(S)kdb +BUILDTOP=$(REL)..$(S).. +DEFINES= -DKDB5_USE_LIB_KDB_DB2 +LOCALINCLUDES= -I. + +# Keep LIBMAJOR in sync with KRB5_KDB_API_VERSION in include/kdb.h. +LIBBASE=kdb5 +LIBMAJOR=10 +LIBMINOR=0 +LIBINITFUNC=kdb_init_lock_list +LIBFINIFUNC=kdb_fini_lock_list +RELDIR=kdb +# Depends on libk5crypto and libkrb5 + +SHLIB_EXPDEPS = \ + $(TOPLIBD)/libk5crypto$(SHLIBEXT) \ + $(TOPLIBD)/libgssrpc$(SHLIBEXT) \ + $(TOPLIBD)/libkrb5$(SHLIBEXT) +SHLIB_EXPLIBS=-lgssrpc -lkrb5 -lk5crypto $(COM_ERR_LIB) $(SUPPORT_LIB) $(DL_LIB) $(LIBS) + +adb_err.$(OBJEXT): adb_err.c +adb_err.c adb_err.h: $(srcdir)/adb_err.et + +SRCS= \ + $(srcdir)/kdb5.c \ + $(srcdir)/encrypt_key.c \ + $(srcdir)/decrypt_key.c \ + $(srcdir)/kdb_default.c \ + $(srcdir)/kdb_cpw.c \ + adb_err.c \ + $(srcdir)/iprop_xdr.c \ + $(srcdir)/kdb_convert.c \ + $(srcdir)/kdb_log.c \ + $(srcdir)/keytab.c + +STLIBOBJS= \ + kdb5.o \ + encrypt_key.o \ + decrypt_key.o \ + kdb_default.o \ + kdb_cpw.o \ + adb_err.o \ + iprop_xdr.o \ + kdb_convert.o \ + kdb_log.o \ + keytab.o + +EXTRADEPSRCS= t_stringattr.c t_ulog.c t_sort_key_data.c + +all-unix: all-liblinks +install-unix: install-libs +clean-unix:: clean-liblinks clean-libs clean-libobjs + $(RM) adb_err.c adb_err.h t_stringattr.o t_stringattr + $(RM) t_ulog.o t_ulog test.ulog + $(RM) t_sort_key_data.o t_sort_key_data + +check-unix: t_ulog + $(RUN_TEST) ./t_ulog test.ulog + +check-pytests: t_stringattr + $(RUNPYTEST) $(srcdir)/t_stringattr.py $(PYTESTFLAGS) + +check-cmocka: t_sort_key_data + $(RUN_TEST) ./t_sort_key_data > /dev/null + +generate-files-mac: darwin.exports + +depend: adb_err.h + +t_stringattr: t_stringattr.o $(KDB5_DEPLIBS) $(KADM_COMM_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_stringattr.o $(KDB5_LIBS) $(KADM_COMM_LIBS) \ + $(KRB5_BASE_LIBS) + +t_ulog: t_ulog.o $(KDB5_DEPLIBS) $(KADM_COMM_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_ulog.o $(KDB5_LIBS) $(KADM_COMM_LIBS) \ + $(KRB5_BASE_LIBS) + +t_sort_key_data: t_sort_key_data.o $(KDB5_DEPLIBS) $(KADM_COMM_DEPLIBS) \ + $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_sort_key_data.o \ + $(KDB5_LIBS) $(KADM_COMM_LIBS) $(CMOCKA_LIBS) $(KRB5_BASE_LIBS) +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/kdb/adb_err.et b/krb5-1.21.3/src/lib/kdb/adb_err.et new file mode 100644 index 00000000..39480257 --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/adb_err.et @@ -0,0 +1,16 @@ +error_table adb +error_code OSA_ADB_NOERR, "No Error" +error_code OSA_ADB_DUP, "Principal or policy already exists" +error_code OSA_ADB_NOENT, "Principal or policy does not exist" +error_code OSA_ADB_DBINIT, "Database not initialized" +error_code OSA_ADB_BAD_POLICY, "Invalid policy name" +error_code OSA_ADB_BAD_PRINC, "Invalid principal name" +error_code OSA_ADB_BAD_DB, "Database inconsistency detected" +error_code OSA_ADB_XDR_FAILURE, "XDR encoding error" +error_code OSA_ADB_FAILURE, "Failure!" +error_code OSA_ADB_BADLOCKMODE, "Bad lock mode" +error_code OSA_ADB_CANTLOCK_DB, "Cannot lock database" +error_code OSA_ADB_NOTLOCKED, "Database not locked" +error_code OSA_ADB_NOLOCKFILE, "KADM5 administration database lock file missing" +error_code OSA_ADB_NOEXCL_PERM, "Insufficient permission to lock file" +end diff --git a/krb5-1.21.3/src/lib/kdb/decrypt_key.c b/krb5-1.21.3/src/lib/kdb/decrypt_key.c new file mode 100644 index 00000000..82bbed63 --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/decrypt_key.c @@ -0,0 +1,135 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kdb/decrypt_key.c */ +/* + * Copyright 1990,1991,2023 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" +#include "kdb.h" + +/* Decrypt key_data, putting the result into dbkey_out and (if not null) + * keysalt_out. */ +krb5_error_code +krb5_dbe_def_decrypt_key_data(krb5_context context, const krb5_keyblock *mkey, + const krb5_key_data *kd, + krb5_keyblock *dbkey_out, + krb5_keysalt *keysalt_out) +{ + krb5_error_code ret; + int16_t keylen; + krb5_enc_data cipher; + krb5_data plain = empty_data(); + krb5_keyblock kb = { 0 }; + krb5_keysalt salt = { 0 }; + + memset(dbkey_out, 0, sizeof(*dbkey_out)); + if (keysalt_out != NULL) + memset(keysalt_out, 0, sizeof(*keysalt_out)); + + if (mkey == NULL) + return KRB5_KDB_BADSTORED_MKEY; + + if (kd->key_data_contents[0] != NULL && kd->key_data_length[0] >= 2) { + keylen = load_16_le(kd->key_data_contents[0]); + if (keylen < 0) + return EINVAL; + cipher.enctype = ENCTYPE_UNKNOWN; + cipher.ciphertext = make_data(kd->key_data_contents[0] + 2, + kd->key_data_length[0] - 2); + ret = alloc_data(&plain, kd->key_data_length[0] - 2); + if (ret) + goto cleanup; + + ret = krb5_c_decrypt(context, mkey, 0, 0, &cipher, &plain); + if (ret) + goto cleanup; + + /* Make sure the plaintext has at least as many bytes as the true ke + * length (it may have more due to padding). */ + if ((unsigned int)keylen > plain.length) { + ret = KRB5_CRYPTO_INTERNAL; + if (ret) + goto cleanup; + } + + kb.magic = KV5M_KEYBLOCK; + kb.enctype = kd->key_data_type[0]; + kb.length = keylen; + kb.contents = (uint8_t *)plain.data; + plain = empty_data(); + } + + /* Decode salt data. */ + if (keysalt_out != NULL) { + if (kd->key_data_ver == 2) { + salt.type = kd->key_data_type[1]; + salt.data.length = kd->key_data_length[1]; + if (kd->key_data_length[1] > 0) { + ret = alloc_data(&salt.data, kd->key_data_length[1]); + if (ret) + goto cleanup; + memcpy(salt.data.data, kd->key_data_contents[1], + salt.data.length); + } + } else { + salt.type = KRB5_KDB_SALTTYPE_NORMAL; + } + } + + *dbkey_out = kb; + if (keysalt_out != NULL) + *keysalt_out = salt; + memset(&kb, 0, sizeof(kb)); + memset(&salt, 0, sizeof(salt)); + +cleanup: + zapfree(plain.data, plain.length); + krb5_free_keyblock_contents(context, &kb); + free(salt.data.data); + return ret; +} diff --git a/krb5-1.21.3/src/lib/kdb/deps b/krb5-1.21.3/src/lib/kdb/deps new file mode 100644 index 00000000..152ef7fc --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/deps @@ -0,0 +1,158 @@ +# +# Generated makefile dependencies follow. +# +kdb5.so kdb5.po $(OUTPRE)kdb5.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h adb_err.h kdb5.c \ + kdb5.h kdb5int.h +encrypt_key.so encrypt_key.po $(OUTPRE)encrypt_key.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h encrypt_key.c +decrypt_key.so decrypt_key.po $(OUTPRE)decrypt_key.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h decrypt_key.c +kdb_default.so kdb_default.po $(OUTPRE)kdb_default.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdb_default.c +kdb_cpw.so kdb_cpw.po $(OUTPRE)kdb_cpw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kdb_cpw.c +adb_err.so adb_err.po $(OUTPRE)adb_err.$(OBJEXT): $(COM_ERR_DEPS) \ + adb_err.c +iprop_xdr.so iprop_xdr.po $(OUTPRE)iprop_xdr.$(OBJEXT): \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/iprop.h iprop_xdr.c +kdb_convert.so kdb_convert.po $(OUTPRE)kdb_convert.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdb_convert.c +kdb_log.so kdb_log.po $(OUTPRE)kdb_log.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdb5.h kdb5int.h \ + kdb_log.c +keytab.so keytab.po $(OUTPRE)keytab.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_kt.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h keytab.c +t_stringattr.so t_stringattr.po $(OUTPRE)t_stringattr.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_stringattr.c +t_ulog.so t_ulog.po $(OUTPRE)t_ulog.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/iprop.h \ + $(top_srcdir)/include/iprop_hdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/kdb_log.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_ulog.c +t_sort_key_data.so t_sort_key_data.po $(OUTPRE)t_sort_key_data.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-cmocka.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h t_sort_key_data.c diff --git a/krb5-1.21.3/src/lib/kdb/encrypt_key.c b/krb5-1.21.3/src/lib/kdb/encrypt_key.c new file mode 100644 index 00000000..a05c519a --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/encrypt_key.c @@ -0,0 +1,114 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kdb/encrypt_key.c */ +/* + * Copyright 1990,1991,2023 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" +#include "kdb.h" + +/* + * Encrypt dbkey for storage in the database, putting the result into + * key_data_out. + */ +krb5_error_code +krb5_dbe_def_encrypt_key_data(krb5_context context, const krb5_keyblock *mkey, + const krb5_keyblock *dbkey, + const krb5_keysalt *keysalt, int keyver, + krb5_key_data *key_data_out) +{ + krb5_error_code ret; + size_t clen; + krb5_data plain; + krb5_enc_data cipher; + krb5_key_data kd = { 0 }; + + memset(key_data_out, 0, sizeof(*key_data_out)); + + kd.key_data_ver = 1; + kd.key_data_kvno = keyver; + + ret = krb5_c_encrypt_length(context, mkey->enctype, dbkey->length, &clen); + if (ret) + goto cleanup; + + /* The first element of the type/length/contents fields is the key + * type/length/contents. */ + kd.key_data_type[0] = dbkey->enctype; + kd.key_data_length[0] = 2 + clen; + kd.key_data_contents[0] = k5alloc(kd.key_data_length[0], &ret); + if (kd.key_data_contents[0] == NULL) + goto cleanup; + store_16_le(dbkey->length, kd.key_data_contents[0]); + + plain = make_data(dbkey->contents, dbkey->length); + cipher.ciphertext = make_data(kd.key_data_contents[0] + 2, clen); + ret = krb5_c_encrypt(context, mkey, 0, 0, &plain, &cipher); + if (ret) + goto cleanup; + + /* The second element of each array is the salt, if necessary. */ + if (keysalt != NULL && keysalt->type > 0) { + kd.key_data_ver++; + kd.key_data_type[1] = keysalt->type; + kd.key_data_length[1] = keysalt->data.length; + if (keysalt->data.length > 0) { + kd.key_data_contents[1] = k5memdup(keysalt->data.data, + keysalt->data.length, &ret); + if (kd.key_data_contents[1] == NULL) + goto cleanup; + } + } + + *key_data_out = kd; + memset(&kd, 0, sizeof(kd)); + +cleanup: + krb5_dbe_free_key_data_contents(context, &kd); + return ret; +} diff --git a/krb5-1.21.3/src/lib/kdb/iprop.x b/krb5-1.21.3/src/lib/kdb/iprop.x new file mode 100644 index 00000000..8796589f --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/iprop.x @@ -0,0 +1,243 @@ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* %#pragma ident "@(#)iprop.x 1.2 04/02/20 SMI" */ + +/* + * Main source: + * lib/kdb/iprop.x + * + * Generated files: + * lib/kdb/iprop_xdr.c + * include/iprop.h + * kprop/kpropd_rpc.c (clnt) + * + * Derived files: + * kadmin/server/ipropd_svc.c + */ + +/* + * This file gets fed through the preprocessor to handle RPC_* + * symbols, but we don't want it to chew on __GNUC__ in this phase. + */ +#undef __GNUC__ + +#ifdef RPC_XDR +/* + * Sloppy rpcgen code declares "buf" and rarely uses it. As it's + * generated code, and not presented to code building against the + * Kerberos code, it's not a problem we need to fix, so suppress the + * complaint. + */ +%#ifdef __GNUC__ +%#pragma GCC diagnostic ignored "-Wunused-variable" +%#endif +#endif /* RPC_XDR */ + +/* + * Initial declarations + */ + +#ifndef RPC_HDR +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +/*typedef hyper int64_t;*/ +/*typedef unsigned hyper uint64_t;*/ +#endif /* !RPC_HDR */ + +typedef opaque utf8str_t<>; + +/* + * Transaction log serial no. + */ +typedef uint32_t kdb_sno_t; + +/* Timestamp */ +struct kdbe_time_t { + uint32_t seconds; + uint32_t useconds; +}; + +/* Key Data */ +struct kdbe_key_t { + int32_t k_ver; /* Version */ + int32_t k_kvno; /* Key version no. */ + int32_t k_enctype<>; + utf8str_t k_contents<>; +}; + +/* Content data */ +struct kdbe_data_t { + int32_t k_magic; + utf8str_t k_data; +}; + +/* Principal Data */ +struct kdbe_princ_t { + utf8str_t k_realm; + kdbe_data_t k_components<>; + int32_t k_nametype; +}; + +/* TL data (pre-auth specific data) */ +struct kdbe_tl_t { + int16_t tl_type; + opaque tl_data<>; +}; + +/* Structure to store pwd history */ +typedef kdbe_key_t kdbe_pw_hist_t<>; + +/* Basic KDB entry attributes */ +enum kdbe_attr_type_t { + AT_ATTRFLAGS = 0, + AT_MAX_LIFE = 1, + AT_MAX_RENEW_LIFE = 2, + AT_EXP = 3, + AT_PW_EXP = 4, + AT_LAST_SUCCESS = 5, + AT_LAST_FAILED = 6, + AT_FAIL_AUTH_COUNT = 7, + AT_PRINC = 8, + AT_KEYDATA = 9, + AT_TL_DATA = 10, + AT_LEN = 11, + AT_MOD_PRINC = 12, + AT_MOD_TIME = 13, + AT_MOD_WHERE = 14, + AT_PW_LAST_CHANGE = 15, + AT_PW_POLICY = 16, + AT_PW_POLICY_SWITCH = 17, + AT_PW_HIST_KVNO = 18, + AT_PW_HIST = 19 +}; + +/* KDB entry, Attribute=value */ +union kdbe_val_t switch (kdbe_attr_type_t av_type) { +case AT_ATTRFLAGS: + uint32_t av_attrflags; +case AT_MAX_LIFE: + uint32_t av_max_life; +case AT_MAX_RENEW_LIFE: + uint32_t av_max_renew_life; +case AT_EXP: + uint32_t av_exp; +case AT_PW_EXP: + uint32_t av_pw_exp; +case AT_LAST_SUCCESS: + uint32_t av_last_success; +case AT_LAST_FAILED: + uint32_t av_last_failed; +case AT_FAIL_AUTH_COUNT: + uint32_t av_fail_auth_count; +case AT_PRINC: + kdbe_princ_t av_princ; +case AT_KEYDATA: + kdbe_key_t av_keydata<>; /* array of keys */ +case AT_TL_DATA: + kdbe_tl_t av_tldata<>; /* array of TL data */ +case AT_LEN: + int16_t av_len; +case AT_PW_LAST_CHANGE: + uint32_t av_pw_last_change; +case AT_MOD_PRINC: + kdbe_princ_t av_mod_princ; +case AT_MOD_TIME: + uint32_t av_mod_time; +case AT_MOD_WHERE: + utf8str_t av_mod_where; +case AT_PW_POLICY: + utf8str_t av_pw_policy; +case AT_PW_POLICY_SWITCH: + bool av_pw_policy_switch; +case AT_PW_HIST_KVNO: + uint32_t av_pw_hist_kvno; +case AT_PW_HIST: + kdbe_pw_hist_t av_pw_hist<>; /* array of pw history */ +default: + opaque av_extension<>; /* futures */ +}; + +typedef kdbe_val_t kdbe_t<>; /* Array of attr/val makes a KDB entry */ + +/* + * Incremental update + */ +struct kdb_incr_update_t { + utf8str_t kdb_princ_name; /* Principal name */ + kdb_sno_t kdb_entry_sno; /* Serial # of entry */ + kdbe_time_t kdb_time; /* Timestamp of update */ + kdbe_t kdb_update; /* Attributes modified */ + bool kdb_deleted; /* Is this update a DELETION ? */ + bool kdb_commit; /* Is the entry committed or not ? */ + utf8str_t kdb_kdcs_seen_by<>; /* Names of replicass that have */ + /* seen this update - for */ + /* future use */ + opaque kdb_futures<>; /* futures */ +}; + +/* + * Update log body + */ +typedef kdb_incr_update_t kdb_ulog_t<>; + +enum update_status_t { + UPDATE_OK = 0, + UPDATE_ERROR = 1, + UPDATE_FULL_RESYNC_NEEDED = 2, + UPDATE_BUSY = 3, + UPDATE_NIL = 4, + UPDATE_PERM_DENIED = 5 +}; + +struct kdb_last_t { + kdb_sno_t last_sno; + kdbe_time_t last_time; +}; + +struct kdb_incr_result_t { + kdb_last_t lastentry; + kdb_ulog_t updates; + update_status_t ret; +}; + +struct kdb_fullresync_result_t { + kdb_last_t lastentry; + update_status_t ret; +}; + +program KRB5_IPROP_PROG { + version KRB5_IPROP_VERS { + /* + * NULL procedure + */ + void + IPROP_NULL(void) = 0; + + /* + * Keep waiting for and get next incremental update(s) + * + * Will return latest kdb_vers on the master (if different), + * alongwith return value and affected db entries. + */ + kdb_incr_result_t + IPROP_GET_UPDATES(kdb_last_t) = 1; + + /* + * We need to do the full-resync of the db, since the + * serial nos./timestamps are way out-of-whack + */ + kdb_fullresync_result_t + IPROP_FULL_RESYNC(void) = 2; + + /* + * Full resync with version marker + */ + kdb_fullresync_result_t + IPROP_FULL_RESYNC_EXT(uint32_t) = 3; + } = 1; +} = 100423; diff --git a/krb5-1.21.3/src/lib/kdb/iprop_xdr.c b/krb5-1.21.3/src/lib/kdb/iprop_xdr.c new file mode 100644 index 00000000..b866fdf7 --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/iprop_xdr.c @@ -0,0 +1,344 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "iprop.h" +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wunused-variable" +#endif + +static bool_t +xdr_int16_t (XDR *xdrs, int16_t *objp) +{ + int32_t *buf; + + if (!xdr_short (xdrs, objp)) + return FALSE; + return TRUE; +} + +static bool_t +xdr_int32_t (XDR *xdrs, int32_t *objp) +{ + int32_t *buf; + + if (!xdr_int (xdrs, objp)) + return FALSE; + return TRUE; +} + +static bool_t +xdr_uint32_t (XDR *xdrs, uint32_t *objp) +{ + int32_t *buf; + + if (!xdr_u_int (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_utf8str_t (XDR *xdrs, utf8str_t *objp) +{ + int32_t *buf; + + if (!xdr_bytes (xdrs, (char **)&objp->utf8str_t_val, (u_int *) &objp->utf8str_t_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdb_sno_t (XDR *xdrs, kdb_sno_t *objp) +{ + int32_t *buf; + + if (!xdr_uint32_t (xdrs, objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_time_t (XDR *xdrs, kdbe_time_t *objp) +{ + int32_t *buf; + + if (!xdr_uint32_t (xdrs, &objp->seconds)) + return FALSE; + if (!xdr_uint32_t (xdrs, &objp->useconds)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_key_t (XDR *xdrs, kdbe_key_t *objp) +{ + int32_t *buf; + + if (!xdr_int32_t (xdrs, &objp->k_ver)) + return FALSE; + if (!xdr_int32_t (xdrs, &objp->k_kvno)) + return FALSE; + if (!xdr_array (xdrs, (char **)&objp->k_enctype.k_enctype_val, (u_int *) &objp->k_enctype.k_enctype_len, ~0, + sizeof (int32_t), (xdrproc_t) xdr_int32_t)) + return FALSE; + if (!xdr_array (xdrs, (char **)&objp->k_contents.k_contents_val, (u_int *) &objp->k_contents.k_contents_len, ~0, + sizeof (utf8str_t), (xdrproc_t) xdr_utf8str_t)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_data_t (XDR *xdrs, kdbe_data_t *objp) +{ + int32_t *buf; + + if (!xdr_int32_t (xdrs, &objp->k_magic)) + return FALSE; + if (!xdr_utf8str_t (xdrs, &objp->k_data)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_princ_t (XDR *xdrs, kdbe_princ_t *objp) +{ + int32_t *buf; + + if (!xdr_utf8str_t (xdrs, &objp->k_realm)) + return FALSE; + if (!xdr_array (xdrs, (char **)&objp->k_components.k_components_val, (u_int *) &objp->k_components.k_components_len, ~0, + sizeof (kdbe_data_t), (xdrproc_t) xdr_kdbe_data_t)) + return FALSE; + if (!xdr_int32_t (xdrs, &objp->k_nametype)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_tl_t (XDR *xdrs, kdbe_tl_t *objp) +{ + int32_t *buf; + + if (!xdr_int16_t (xdrs, &objp->tl_type)) + return FALSE; + if (!xdr_bytes (xdrs, (char **)&objp->tl_data.tl_data_val, (u_int *) &objp->tl_data.tl_data_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_pw_hist_t (XDR *xdrs, kdbe_pw_hist_t *objp) +{ + int32_t *buf; + + if (!xdr_array (xdrs, (char **)&objp->kdbe_pw_hist_t_val, (u_int *) &objp->kdbe_pw_hist_t_len, ~0, + sizeof (kdbe_key_t), (xdrproc_t) xdr_kdbe_key_t)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_attr_type_t (XDR *xdrs, kdbe_attr_type_t *objp) +{ + int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdbe_val_t (XDR *xdrs, kdbe_val_t *objp) +{ + int32_t *buf; + + if (!xdr_kdbe_attr_type_t (xdrs, &objp->av_type)) + return FALSE; + switch (objp->av_type) { + case AT_ATTRFLAGS: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_attrflags)) + return FALSE; + break; + case AT_MAX_LIFE: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_max_life)) + return FALSE; + break; + case AT_MAX_RENEW_LIFE: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_max_renew_life)) + return FALSE; + break; + case AT_EXP: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_exp)) + return FALSE; + break; + case AT_PW_EXP: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_pw_exp)) + return FALSE; + break; + case AT_LAST_SUCCESS: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_last_success)) + return FALSE; + break; + case AT_LAST_FAILED: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_last_failed)) + return FALSE; + break; + case AT_FAIL_AUTH_COUNT: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_fail_auth_count)) + return FALSE; + break; + case AT_PRINC: + if (!xdr_kdbe_princ_t (xdrs, &objp->kdbe_val_t_u.av_princ)) + return FALSE; + break; + case AT_KEYDATA: + if (!xdr_array (xdrs, (char **)&objp->kdbe_val_t_u.av_keydata.av_keydata_val, (u_int *) &objp->kdbe_val_t_u.av_keydata.av_keydata_len, ~0, + sizeof (kdbe_key_t), (xdrproc_t) xdr_kdbe_key_t)) + return FALSE; + break; + case AT_TL_DATA: + if (!xdr_array (xdrs, (char **)&objp->kdbe_val_t_u.av_tldata.av_tldata_val, (u_int *) &objp->kdbe_val_t_u.av_tldata.av_tldata_len, ~0, + sizeof (kdbe_tl_t), (xdrproc_t) xdr_kdbe_tl_t)) + return FALSE; + break; + case AT_LEN: + if (!xdr_int16_t (xdrs, &objp->kdbe_val_t_u.av_len)) + return FALSE; + break; + case AT_PW_LAST_CHANGE: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_pw_last_change)) + return FALSE; + break; + case AT_MOD_PRINC: + if (!xdr_kdbe_princ_t (xdrs, &objp->kdbe_val_t_u.av_mod_princ)) + return FALSE; + break; + case AT_MOD_TIME: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_mod_time)) + return FALSE; + break; + case AT_MOD_WHERE: + if (!xdr_utf8str_t (xdrs, &objp->kdbe_val_t_u.av_mod_where)) + return FALSE; + break; + case AT_PW_POLICY: + if (!xdr_utf8str_t (xdrs, &objp->kdbe_val_t_u.av_pw_policy)) + return FALSE; + break; + case AT_PW_POLICY_SWITCH: + if (!xdr_bool (xdrs, &objp->kdbe_val_t_u.av_pw_policy_switch)) + return FALSE; + break; + case AT_PW_HIST_KVNO: + if (!xdr_uint32_t (xdrs, &objp->kdbe_val_t_u.av_pw_hist_kvno)) + return FALSE; + break; + case AT_PW_HIST: + if (!xdr_array (xdrs, (char **)&objp->kdbe_val_t_u.av_pw_hist.av_pw_hist_val, (u_int *) &objp->kdbe_val_t_u.av_pw_hist.av_pw_hist_len, ~0, + sizeof (kdbe_pw_hist_t), (xdrproc_t) xdr_kdbe_pw_hist_t)) + return FALSE; + break; + default: + if (!xdr_bytes (xdrs, (char **)&objp->kdbe_val_t_u.av_extension.av_extension_val, (u_int *) &objp->kdbe_val_t_u.av_extension.av_extension_len, ~0)) + return FALSE; + break; + } + return TRUE; +} + +bool_t +xdr_kdbe_t (XDR *xdrs, kdbe_t *objp) +{ + int32_t *buf; + + if (!xdr_array (xdrs, (char **)&objp->kdbe_t_val, (u_int *) &objp->kdbe_t_len, ~0, + sizeof (kdbe_val_t), (xdrproc_t) xdr_kdbe_val_t)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdb_incr_update_t (XDR *xdrs, kdb_incr_update_t *objp) +{ + int32_t *buf; + + if (!xdr_utf8str_t (xdrs, &objp->kdb_princ_name)) + return FALSE; + if (!xdr_kdb_sno_t (xdrs, &objp->kdb_entry_sno)) + return FALSE; + if (!xdr_kdbe_time_t (xdrs, &objp->kdb_time)) + return FALSE; + if (!xdr_kdbe_t (xdrs, &objp->kdb_update)) + return FALSE; + if (!xdr_bool (xdrs, &objp->kdb_deleted)) + return FALSE; + if (!xdr_bool (xdrs, &objp->kdb_commit)) + return FALSE; + if (!xdr_array (xdrs, (char **)&objp->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val, (u_int *) &objp->kdb_kdcs_seen_by.kdb_kdcs_seen_by_len, ~0, + sizeof (utf8str_t), (xdrproc_t) xdr_utf8str_t)) + return FALSE; + if (!xdr_bytes (xdrs, (char **)&objp->kdb_futures.kdb_futures_val, (u_int *) &objp->kdb_futures.kdb_futures_len, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdb_ulog_t (XDR *xdrs, kdb_ulog_t *objp) +{ + int32_t *buf; + + if (!xdr_array (xdrs, (char **)&objp->kdb_ulog_t_val, (u_int *) &objp->kdb_ulog_t_len, ~0, + sizeof (kdb_incr_update_t), (xdrproc_t) xdr_kdb_incr_update_t)) + return FALSE; + return TRUE; +} + +bool_t +xdr_update_status_t (XDR *xdrs, update_status_t *objp) +{ + int32_t *buf; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdb_last_t (XDR *xdrs, kdb_last_t *objp) +{ + int32_t *buf; + + if (!xdr_kdb_sno_t (xdrs, &objp->last_sno)) + return FALSE; + if (!xdr_kdbe_time_t (xdrs, &objp->last_time)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdb_incr_result_t (XDR *xdrs, kdb_incr_result_t *objp) +{ + int32_t *buf; + + if (!xdr_kdb_last_t (xdrs, &objp->lastentry)) + return FALSE; + if (!xdr_kdb_ulog_t (xdrs, &objp->updates)) + return FALSE; + if (!xdr_update_status_t (xdrs, &objp->ret)) + return FALSE; + return TRUE; +} + +bool_t +xdr_kdb_fullresync_result_t (XDR *xdrs, kdb_fullresync_result_t *objp) +{ + int32_t *buf; + + if (!xdr_kdb_last_t (xdrs, &objp->lastentry)) + return FALSE; + if (!xdr_update_status_t (xdrs, &objp->ret)) + return FALSE; + return TRUE; +} diff --git a/krb5-1.21.3/src/lib/kdb/kdb5.c b/krb5-1.21.3/src/lib/kdb/kdb5.c new file mode 100644 index 00000000..415ae64e --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/kdb5.c @@ -0,0 +1,2781 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2006, 2009, 2010, 2016 by the Massachusetts Institute of + * Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * This code was based on code donated to MIT by Novell for + * distribution under the MIT license. + */ + +/* + * Include files + */ + +#include +#include "kdb5.h" +#include "kdb_log.h" +#include "kdb5int.h" + +/* Currently DB2 policy related errors are exported from DAL. But + other databases should set_err function to return string. */ +#include "adb_err.h" + +/* + * internal static variable + */ + +static k5_mutex_t db_lock = K5_MUTEX_PARTIAL_INITIALIZER; + +static db_library lib_list; + +/* + * Helper Functions + */ + +MAKE_INIT_FUNCTION(kdb_init_lock_list); +MAKE_FINI_FUNCTION(kdb_fini_lock_list); + +static void +free_mkey_list(krb5_context context, krb5_keylist_node *mkey_list) +{ + krb5_keylist_node *cur, *next; + + for (cur = mkey_list; cur != NULL; cur = next) { + next = cur->next; + krb5_free_keyblock_contents(context, &cur->keyblock); + free(cur); + } +} + +int +kdb_init_lock_list() +{ + return k5_mutex_finish_init(&db_lock); +} + +static int +kdb_lock_list() +{ + int err; + err = CALL_INIT_FUNCTION (kdb_init_lock_list); + if (err) + return err; + k5_mutex_lock(&db_lock); + return 0; +} + +void +kdb_fini_lock_list() +{ + if (INITIALIZER_RAN(kdb_init_lock_list)) + k5_mutex_destroy(&db_lock); +} + +static void +kdb_unlock_list() +{ + k5_mutex_unlock(&db_lock); +} + +/* Return true if the ulog is mapped in the primary role. */ +static inline krb5_boolean +logging(krb5_context context) +{ + kdb_log_context *log_ctx = context->kdblog_context; + + return log_ctx != NULL && log_ctx->iproprole == IPROP_PRIMARY && + log_ctx->ulog != NULL; +} + +void +krb5_dbe_free_key_data_contents(krb5_context context, krb5_key_data *key) +{ + int i, idx; + + if (key) { + idx = (key->key_data_ver == 1 ? 1 : 2); + for (i = 0; i < idx; i++) { + if (key->key_data_contents[i]) { + zap(key->key_data_contents[i], key->key_data_length[i]); + free(key->key_data_contents[i]); + } + } + } + return; +} + +void +krb5_dbe_free_key_list(krb5_context context, krb5_keylist_node *val) +{ + krb5_keylist_node *temp = val, *prev; + + while (temp != NULL) { + prev = temp; + temp = temp->next; + krb5_free_keyblock_contents(context, &(prev->keyblock)); + free(prev); + } +} + +void +krb5_dbe_free_actkvno_list(krb5_context context, krb5_actkvno_node *val) +{ + krb5_actkvno_node *temp = val, *prev; + + while (temp != NULL) { + prev = temp; + temp = temp->next; + free(prev); + } +} + +void +krb5_dbe_free_mkey_aux_list(krb5_context context, krb5_mkey_aux_node *val) +{ + krb5_mkey_aux_node *temp = val, *prev; + + while (temp != NULL) { + prev = temp; + temp = temp->next; + krb5_dbe_free_key_data_contents(context, &prev->latest_mkey); + free(prev); + } +} + +void +krb5_dbe_free_tl_data(krb5_context context, krb5_tl_data *tl_data) +{ + if (tl_data) { + if (tl_data->tl_data_contents) + free(tl_data->tl_data_contents); + free(tl_data); + } +} + +void +krb5_dbe_free_strings(krb5_context context, krb5_string_attr *strings, + int count) +{ + int i; + + if (strings == NULL) + return; + for (i = 0; i < count; i++) { + free(strings[i].key); + free(strings[i].value); + } + free(strings); +} + +void +krb5_dbe_free_string(krb5_context context, char *string) +{ + free(string); +} + +/* Set *section to the appropriate section to use for a database module's + * profile queries. The caller must free the result. */ +static krb5_error_code +get_conf_section(krb5_context context, char **section) +{ + krb5_error_code status; + char *result = NULL, *value = NULL, *defrealm; + + *section = NULL; + + status = krb5_get_default_realm(context, &defrealm); + if (status) { + k5_setmsg(context, KRB5_KDB_SERVER_INTERNAL_ERR, + _("No default realm set; cannot initialize KDB")); + return KRB5_KDB_SERVER_INTERNAL_ERR; + } + status = profile_get_string(context->profile, + /* realms */ + KDB_REALM_SECTION, + defrealm, + /* under the realm name, database_module */ + KDB_MODULE_POINTER, + /* default value is the realm name itself */ + defrealm, + &value); + krb5_free_default_realm(context, defrealm); + if (status) + return status; + result = strdup(value); + profile_release_string(value); + if (result == NULL) + return ENOMEM; + *section = result; + return 0; +} + +static krb5_error_code +kdb_get_library_name(krb5_context kcontext, char **libname_out) +{ + krb5_error_code status = 0; + char *value = NULL, *lib = NULL, *defrealm = NULL; + + *libname_out = NULL; + + status = krb5_get_default_realm(kcontext, &defrealm); + if (status) + goto clean_n_exit; + status = profile_get_string(kcontext->profile, + /* realms */ + KDB_REALM_SECTION, + defrealm, + /* under the realm name, database_module */ + KDB_MODULE_POINTER, + /* default value is the realm name itself */ + defrealm, + &value); + if (status) + goto clean_n_exit; + +#define DB2_NAME "db2" + /* we got the module section. Get the library name from the module */ + status = profile_get_string(kcontext->profile, KDB_MODULE_SECTION, value, + KDB_LIB_POINTER, + /* default to db2 */ + DB2_NAME, + &lib); + + if (status) { + goto clean_n_exit; + } + + *libname_out = strdup(lib); + if (*libname_out == NULL) + status = ENOMEM; + +clean_n_exit: + krb5_free_default_realm(kcontext, defrealm); + profile_release_string(value); + profile_release_string(lib); + return status; +} + +static void +copy_vtable(const kdb_vftabl *in, kdb_vftabl *out) +{ + /* Copy fields for minor version 0. */ + out->maj_ver = in->maj_ver; + out->min_ver = in->min_ver; + out->init_library = in->init_library; + out->fini_library = in->fini_library; + out->init_module = in->init_module; + out->fini_module = in->fini_module; + out->create = in->create; + out->destroy = in->destroy; + out->get_age = in->get_age; + out->lock = in->lock; + out->unlock = in->unlock; + out->get_principal = in->get_principal; + out->put_principal = in->put_principal; + out->delete_principal = in->delete_principal; + out->rename_principal = in->rename_principal; + out->iterate = in->iterate; + out->create_policy = in->create_policy; + out->get_policy = in->get_policy; + out->put_policy = in->put_policy; + out->iter_policy = in->iter_policy; + out->delete_policy = in->delete_policy; + out->fetch_master_key = in->fetch_master_key; + out->fetch_master_key_list = in->fetch_master_key_list; + out->store_master_key_list = in->store_master_key_list; + out->dbe_search_enctype = in->dbe_search_enctype; + out->change_pwd = in->change_pwd; + out->promote_db = in->promote_db; + out->decrypt_key_data = in->decrypt_key_data; + out->encrypt_key_data = in->encrypt_key_data; + out->check_transited_realms = in->check_transited_realms; + out->check_policy_as = in->check_policy_as; + out->check_policy_tgs = in->check_policy_tgs; + out->audit_as_req = in->audit_as_req; + out->refresh_config = in->refresh_config; + out->check_allowed_to_delegate = in->check_allowed_to_delegate; + out->free_principal_e_data = in->free_principal_e_data; + out->get_s4u_x509_principal = in->get_s4u_x509_principal; + out->allowed_to_delegate_from = in->allowed_to_delegate_from; + out->issue_pac = in->issue_pac; + + /* Set defaults for optional fields. */ + if (out->fetch_master_key == NULL) + out->fetch_master_key = krb5_db_def_fetch_mkey; + if (out->fetch_master_key_list == NULL) + out->fetch_master_key_list = krb5_def_fetch_mkey_list; + if (out->store_master_key_list == NULL) + out->store_master_key_list = krb5_def_store_mkey_list; + if (out->dbe_search_enctype == NULL) + out->dbe_search_enctype = krb5_dbe_def_search_enctype; + if (out->change_pwd == NULL) + out->change_pwd = krb5_dbe_def_cpw; + if (out->decrypt_key_data == NULL) + out->decrypt_key_data = krb5_dbe_def_decrypt_key_data; + if (out->encrypt_key_data == NULL) + out->encrypt_key_data = krb5_dbe_def_encrypt_key_data; + if (out->rename_principal == NULL) + out->rename_principal = krb5_db_def_rename_principal; +} + +#ifdef STATIC_PLUGINS + +extern kdb_vftabl krb5_db2_kdb_function_table; +#ifdef ENABLE_LDAP +extern kdb_vftabl krb5_ldap_kdb_function_table; +#endif + +static krb5_error_code +kdb_load_library(krb5_context kcontext, char *lib_name, db_library *libptr) +{ + krb5_error_code status; + db_library lib; + kdb_vftabl *vftabl_addr = NULL; + + if (strcmp(lib_name, "db2") == 0) + vftabl_addr = &krb5_db2_kdb_function_table; +#ifdef ENABLE_LDAP + if (strcmp(lib_name, "kldap") == 0) + vftabl_addr = &krb5_ldap_kdb_function_table; +#endif + if (!vftabl_addr) { + k5_setmsg(kcontext, KRB5_KDB_DBTYPE_NOTFOUND, + _("Unable to find requested database type: %s"), lib_name); + return KRB5_PLUGIN_OP_NOTSUPP; + } + + lib = calloc(1, sizeof(*lib)); + if (lib == NULL) + return ENOMEM; + + strlcpy(lib->name, lib_name, sizeof(lib->name)); + copy_vtable(vftabl_addr, &lib->vftabl); + + status = lib->vftabl.init_library(); + if (status) + goto cleanup; + + *libptr = lib; + return 0; + +cleanup: + free(lib); + return status; +} + +#else /* KDB5_STATIC_LINK*/ + +static char *db_dl_location[] = DEFAULT_KDB_LIB_PATH; +#define db_dl_n_locations (sizeof(db_dl_location) / sizeof(db_dl_location[0])) + +static krb5_error_code +kdb_load_library(krb5_context kcontext, char *lib_name, db_library *lib) +{ + krb5_error_code status = 0; + int ndx; + void **vftabl_addrs = NULL; + /* N.B.: If this is "const" but not "static", the Solaris 10 + native compiler has trouble building the library because of + absolute relocations needed in read-only section ".rodata". + When it's static, it goes into ".picdata", which is + read-write. */ + static const char *const dbpath_names[] = { + KDB_MODULE_SECTION, KRB5_CONF_DB_MODULE_DIR, NULL, + }; + const char *filebases[2]; + char **profpath = NULL; + char **path = NULL; + + filebases[0] = lib_name; + filebases[1] = NULL; + + *lib = calloc((size_t) 1, sizeof(**lib)); + if (*lib == NULL) + return ENOMEM; + + strlcpy((*lib)->name, lib_name, sizeof((*lib)->name)); + + /* Fetch the list of directories specified in the config + file(s) first. */ + status = profile_get_values(kcontext->profile, dbpath_names, &profpath); + if (status != 0 && status != PROF_NO_RELATION) + goto clean_n_exit; + ndx = 0; + if (profpath) + while (profpath[ndx] != NULL) + ndx++; + + path = calloc(ndx + db_dl_n_locations, sizeof (char *)); + if (path == NULL) { + status = ENOMEM; + goto clean_n_exit; + } + if (ndx) + memcpy(path, profpath, ndx * sizeof(profpath[0])); + memcpy(path + ndx, db_dl_location, db_dl_n_locations * sizeof(char *)); + status = 0; + + if ((status = krb5int_open_plugin_dirs ((const char **) path, + filebases, + &(*lib)->dl_dir_handle, &kcontext->err))) { + status = KRB5_KDB_DBTYPE_NOTFOUND; + k5_prependmsg(kcontext, status, + _("Unable to find requested database type")); + goto clean_n_exit; + } + + if ((status = krb5int_get_plugin_dir_data (&(*lib)->dl_dir_handle, "kdb_function_table", + &vftabl_addrs, &kcontext->err))) { + status = KRB5_KDB_DBTYPE_INIT; + k5_prependmsg(kcontext, status, + _("plugin symbol 'kdb_function_table' lookup failed")); + goto clean_n_exit; + } + + if (vftabl_addrs[0] == NULL) { + /* No plugins! */ + status = KRB5_KDB_DBTYPE_NOTFOUND; + k5_setmsg(kcontext, status, + _("Unable to load requested database module '%s': plugin " + "symbol 'kdb_function_table' not found"), lib_name); + goto clean_n_exit; + } + + if (((kdb_vftabl *)vftabl_addrs[0])->maj_ver != + KRB5_KDB_DAL_MAJOR_VERSION) { + status = KRB5_KDB_DBTYPE_MISMATCH; + goto clean_n_exit; + } + + copy_vtable(vftabl_addrs[0], &(*lib)->vftabl); + + if ((status = (*lib)->vftabl.init_library())) + goto clean_n_exit; + +clean_n_exit: + krb5int_free_plugin_dir_data(vftabl_addrs); + /* Both of these DTRT with NULL. */ + profile_free_list(profpath); + free(path); + if (status && *lib) { + if (PLUGIN_DIR_OPEN((&(*lib)->dl_dir_handle))) + krb5int_close_plugin_dirs (&(*lib)->dl_dir_handle); + free(*lib); + *lib = NULL; + } + return status; +} + +#endif /* end of _KDB5_STATIC_LINK */ + +static krb5_error_code +kdb_find_library(krb5_context kcontext, char *lib_name, db_library *lib) +{ + /* lock here so that no two threads try to do the same at the same time */ + krb5_error_code status = 0; + int locked = 0; + db_library curr_elt, prev_elt = NULL; + static int kdb_db2_pol_err_loaded = 0; + + if (!strcmp(DB2_NAME, lib_name) && (kdb_db2_pol_err_loaded == 0)) { + initialize_adb_error_table(); + kdb_db2_pol_err_loaded = 1; + } + + if ((status = kdb_lock_list()) != 0) + goto clean_n_exit; + locked = 1; + + curr_elt = lib_list; + while (curr_elt != NULL) { + if (strcmp(lib_name, curr_elt->name) == 0) { + *lib = curr_elt; + goto clean_n_exit; + } + prev_elt = curr_elt; + curr_elt = curr_elt->next; + } + + /* module not found. create and add to list */ + status = kdb_load_library(kcontext, lib_name, lib); + if (status) + goto clean_n_exit; + + if (prev_elt) { + /* prev_elt points to the last element in the list */ + prev_elt->next = *lib; + (*lib)->prev = prev_elt; + } else { + lib_list = *lib; + } + +clean_n_exit: + if (*lib) + (*lib)->reference_cnt++; + + if (locked) + kdb_unlock_list(); + + return status; +} + +static krb5_error_code +kdb_free_library(db_library lib) +{ + krb5_error_code status = 0; + int locked = 0; + + if ((status = kdb_lock_list()) != 0) + goto clean_n_exit; + locked = 1; + + lib->reference_cnt--; + + if (lib->reference_cnt == 0) { + status = lib->vftabl.fini_library(); + if (status) + goto clean_n_exit; + + /* close the library */ + if (PLUGIN_DIR_OPEN((&lib->dl_dir_handle))) + krb5int_close_plugin_dirs (&lib->dl_dir_handle); + + if (lib->prev == NULL) + lib_list = lib->next; /* first element in the list */ + else + lib->prev->next = lib->next; + + if (lib->next) + lib->next->prev = lib->prev; + free(lib); + } + +clean_n_exit: + if (locked) + kdb_unlock_list(); + + return status; +} + +krb5_error_code +krb5_db_setup_lib_handle(krb5_context kcontext) +{ + char *library = NULL; + krb5_error_code status = 0; + db_library lib = NULL; + kdb5_dal_handle *dal_handle = NULL; + + dal_handle = calloc((size_t) 1, sizeof(kdb5_dal_handle)); + if (dal_handle == NULL) { + status = ENOMEM; + goto clean_n_exit; + } + + status = kdb_get_library_name(kcontext, &library); + if (library == NULL) { + k5_prependmsg(kcontext, status, + _("Cannot initialize database library")); + goto clean_n_exit; + } + + status = kdb_find_library(kcontext, library, &lib); + if (status) + goto clean_n_exit; + + dal_handle->lib_handle = lib; + kcontext->dal_handle = dal_handle; + +clean_n_exit: + free(library); + + if (status) { + free(dal_handle); + if (lib) + kdb_free_library(lib); + } + + return status; +} + +static krb5_error_code +kdb_free_lib_handle(krb5_context kcontext) +{ + krb5_error_code status = 0; + + status = kdb_free_library(kcontext->dal_handle->lib_handle); + if (status) + return status; + + free_mkey_list(kcontext, kcontext->dal_handle->master_keylist); + krb5_free_principal(kcontext, kcontext->dal_handle->master_princ); + free(kcontext->dal_handle); + kcontext->dal_handle = NULL; + return 0; +} + +static krb5_error_code +get_vftabl(krb5_context kcontext, kdb_vftabl **vftabl_ptr) +{ + krb5_error_code status; + + *vftabl_ptr = NULL; + if (kcontext->dal_handle == NULL) { + status = krb5_db_setup_lib_handle(kcontext); + if (status) + return status; + } + *vftabl_ptr = &kcontext->dal_handle->lib_handle->vftabl; + return 0; +} + +/* + * External functions... DAL API + */ +krb5_error_code +krb5_db_open(krb5_context kcontext, char **db_args, int mode) +{ + krb5_error_code status; + char *section; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + status = get_conf_section(kcontext, §ion); + if (status) + return status; + status = v->init_module(kcontext, section, db_args, mode); + free(section); + if (status) + (void)krb5_db_fini(kcontext); + return status; +} + +krb5_error_code +krb5_db_inited(krb5_context kcontext) +{ + return !(kcontext && kcontext->dal_handle && + kcontext->dal_handle->db_context); +} + +krb5_error_code +krb5_db_create(krb5_context kcontext, char **db_args) +{ + krb5_error_code status; + char *section; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->create == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + status = get_conf_section(kcontext, §ion); + if (status) + return status; + status = v->create(kcontext, section, db_args); + free(section); + if (status) + (void)krb5_db_fini(kcontext); + return status; +} + +krb5_error_code +krb5_db_fini(krb5_context kcontext) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + /* Do nothing if module was never loaded. */ + if (kcontext->dal_handle == NULL) + return 0; + + v = &kcontext->dal_handle->lib_handle->vftabl; + status = v->fini_module(kcontext); + + if (status) + return status; + + return kdb_free_lib_handle(kcontext); +} + +krb5_error_code +krb5_db_destroy(krb5_context kcontext, char **db_args) +{ + krb5_error_code status; + char *section; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->destroy == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + status = get_conf_section(kcontext, §ion); + if (status) + return status; + status = v->destroy(kcontext, section, db_args); + free(section); + return status; +} + +krb5_error_code +krb5_db_get_age(krb5_context kcontext, char *db_name, time_t *t) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->get_age == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + return v->get_age(kcontext, db_name, t); +} + +krb5_error_code +krb5_db_lock(krb5_context kcontext, int lock_mode) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->lock == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + return v->lock(kcontext, lock_mode); +} + +krb5_error_code +krb5_db_unlock(krb5_context kcontext) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->unlock == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + return v->unlock(kcontext); +} + +krb5_error_code +krb5_db_get_principal(krb5_context kcontext, krb5_const_principal search_for, + unsigned int flags, krb5_db_entry **entry) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + *entry = NULL; + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->get_principal == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + status = v->get_principal(kcontext, search_for, flags, entry); + if (status) + return status; + + /* Sort the keys in the db entry as some parts of krb5 expect it to be. */ + if ((*entry)->key_data != NULL) + krb5_dbe_sort_key_data((*entry)->key_data, (*entry)->n_key_data); + + return 0; +} + +static void +free_tl_data(krb5_tl_data *list) +{ + krb5_tl_data *next; + + for (; list != NULL; list = next) { + next = list->tl_data_next; + free(list->tl_data_contents); + free(list); + } +} + +void +krb5_db_free_principal(krb5_context kcontext, krb5_db_entry *entry) +{ + kdb_vftabl *v; + int i; + + if (entry == NULL) + return; + if (entry->e_data != NULL) { + if (get_vftabl(kcontext, &v) == 0 && v->free_principal_e_data != NULL) + v->free_principal_e_data(kcontext, entry->e_data); + else + free(entry->e_data); + } + krb5_free_principal(kcontext, entry->princ); + free_tl_data(entry->tl_data); + for (i = 0; i < entry->n_key_data; i++) + krb5_dbe_free_key_data_contents(kcontext, &entry->key_data[i]); + free(entry->key_data); + free(entry); +} + +static void +free_db_args(char **db_args) +{ + int i; + if (db_args) { + for (i = 0; db_args[i]; i++) + free(db_args[i]); + free(db_args); + } +} + +static krb5_error_code +extract_db_args_from_tl_data(krb5_context kcontext, krb5_tl_data **start, + krb5_int16 *count, char ***db_argsp) +{ + char **db_args = NULL; + int db_args_size = 0; + krb5_tl_data *prev, *curr, *next; + krb5_error_code status; + + /* Giving db_args as part of tl data causes db2 to store the + tl_data as such. To prevent this, tl_data is collated and + passed as a separate argument. Currently supports only one + principal, but passing it as a separate argument makes it + difficult for kadmin remote to pass arguments to server. */ + prev = NULL, curr = *start; + while (curr) { + if (curr->tl_data_type == KRB5_TL_DB_ARGS) { + char **t; + /* Since this is expected to be NULL terminated string and + this could come from any client, do a check before + passing it to db. */ + if (((char *) curr->tl_data_contents)[curr->tl_data_length - 1] != + '\0') { + /* Not null terminated. Dangerous input. */ + status = EINVAL; + goto clean_n_exit; + } + + db_args_size++; + t = realloc(db_args, sizeof(char *) * (db_args_size + 1)); /* 1 for NULL */ + if (t == NULL) { + status = ENOMEM; + goto clean_n_exit; + } + + db_args = t; + db_args[db_args_size - 1] = (char *) curr->tl_data_contents; + db_args[db_args_size] = NULL; + + next = curr->tl_data_next; + if (prev == NULL) { + /* current node is the first in the linked list. remove it */ + *start = curr->tl_data_next; + } else { + prev->tl_data_next = curr->tl_data_next; + } + (*count)--; + free(curr); + + /* previous does not change */ + curr = next; + } else { + prev = curr; + curr = curr->tl_data_next; + } + } + status = 0; +clean_n_exit: + if (status != 0) { + free_db_args(db_args); + db_args = NULL; + } + *db_argsp = db_args; + return status; +} + +krb5_error_code +krb5int_put_principal_no_log(krb5_context kcontext, krb5_db_entry *entry) +{ + kdb_vftabl *v; + krb5_error_code status; + char **db_args; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->put_principal == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + status = extract_db_args_from_tl_data(kcontext, &entry->tl_data, + &entry->n_tl_data, + &db_args); + if (status) + return status; + status = v->put_principal(kcontext, entry, db_args); + free_db_args(db_args); + return status; +} + +krb5_error_code +krb5_db_put_principal(krb5_context kcontext, krb5_db_entry *entry) +{ + krb5_error_code status = 0; + kdb_incr_update_t *upd = NULL; + char *princ_name = NULL; + + if (logging(kcontext)) { + upd = k5alloc(sizeof(*upd), &status); + if (upd == NULL) + goto cleanup; + if ((status = ulog_conv_2logentry(kcontext, entry, upd))) + goto cleanup; + + status = krb5_unparse_name(kcontext, entry->princ, &princ_name); + if (status != 0) + goto cleanup; + + upd->kdb_princ_name.utf8str_t_val = princ_name; + upd->kdb_princ_name.utf8str_t_len = strlen(princ_name); + } + + status = krb5int_put_principal_no_log(kcontext, entry); + if (status) + goto cleanup; + + if (logging(kcontext)) + status = ulog_add_update(kcontext, upd); + +cleanup: + ulog_free_entries(upd, 1); + return status; +} + +krb5_error_code +krb5int_delete_principal_no_log(krb5_context kcontext, + krb5_principal search_for) +{ + kdb_vftabl *v; + krb5_error_code status; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->delete_principal == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + return v->delete_principal(kcontext, search_for); +} + +krb5_error_code +krb5_db_delete_principal(krb5_context kcontext, krb5_principal search_for) +{ + krb5_error_code status = 0; + kdb_incr_update_t upd; + char *princ_name = NULL; + + status = krb5int_delete_principal_no_log(kcontext, search_for); + if (status || !logging(kcontext)) + return status; + + status = krb5_unparse_name(kcontext, search_for, &princ_name); + if (status) + return status; + + memset(&upd, 0, sizeof(kdb_incr_update_t)); + upd.kdb_princ_name.utf8str_t_val = princ_name; + upd.kdb_princ_name.utf8str_t_len = strlen(princ_name); + upd.kdb_deleted = TRUE; + + status = ulog_add_update(kcontext, &upd); + free(princ_name); + return status; +} + +krb5_error_code +krb5_db_rename_principal(krb5_context kcontext, krb5_principal source, + krb5_principal target) +{ + kdb_vftabl *v; + krb5_error_code status; + krb5_db_entry *entry; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + + /* + * If the default rename function isn't used and logging is enabled, iprop + * would fail since it doesn't formally support renaming. In that case + * return KRB5_PLUGIN_OP_NOTSUPP. + */ + if (v->rename_principal != krb5_db_def_rename_principal && + logging(kcontext)) + return KRB5_PLUGIN_OP_NOTSUPP; + + status = krb5_db_get_principal(kcontext, target, 0, &entry); + if (status == 0) { + krb5_db_free_principal(kcontext, entry); + return KRB5_KDB_INUSE; + } + + return v->rename_principal(kcontext, source, target); +} + +/* + * Use a proxy function for iterate so that we can sort the keys before sending + * them to the callback. + */ +struct callback_proxy_args { + int (*func)(krb5_pointer, krb5_db_entry *); + krb5_pointer func_arg; +}; + +static int +sort_entry_callback_proxy(krb5_pointer func_arg, krb5_db_entry *entry) +{ + struct callback_proxy_args *args = (struct callback_proxy_args *)func_arg; + + /* Sort the keys in the db entry as some parts of krb5 expect it to be. */ + if (entry && entry->key_data) + krb5_dbe_sort_key_data(entry->key_data, entry->n_key_data); + return args->func(args->func_arg, entry); +} + +krb5_error_code +krb5_db_iterate(krb5_context kcontext, char *match_entry, + int (*func)(krb5_pointer, krb5_db_entry *), + krb5_pointer func_arg, krb5_flags iterflags) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + struct callback_proxy_args proxy_args; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->iterate == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + + /* Use the proxy function to sort key data before passing entries to + * callback. */ + proxy_args.func = func; + proxy_args.func_arg = func_arg; + return v->iterate(kcontext, match_entry, sort_entry_callback_proxy, + &proxy_args, iterflags); +} + +/* Return a read only pointer alias to mkey list. Do not free this! */ +krb5_keylist_node * +krb5_db_mkey_list_alias(krb5_context kcontext) +{ + return kcontext->dal_handle->master_keylist; +} + +krb5_error_code +krb5_db_fetch_mkey_list(krb5_context context, krb5_principal mname, + const krb5_keyblock *mkey) +{ + kdb_vftabl *v; + krb5_error_code status = 0; + krb5_keylist_node *local_keylist; + + status = get_vftabl(context, &v); + if (status) + return status; + + if (!context->dal_handle->master_princ) { + status = krb5_copy_principal(context, mname, + &context->dal_handle->master_princ); + if (status) + return status; + } + + status = v->fetch_master_key_list(context, mname, mkey, &local_keylist); + if (status == 0) { + free_mkey_list(context, context->dal_handle->master_keylist); + context->dal_handle->master_keylist = local_keylist; + } + return status; +} + +krb5_error_code +krb5_db_store_master_key(krb5_context kcontext, char *keyfile, + krb5_principal mname, krb5_kvno kvno, + krb5_keyblock * key, char *master_pwd) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + krb5_keylist_node list; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + + if (v->store_master_key_list == NULL) + return KRB5_KDB_DBTYPE_NOSUP; + + list.kvno = kvno; + list.keyblock = *key; + list.next = NULL; + + return v->store_master_key_list(kcontext, keyfile, mname, + &list, master_pwd); +} + +krb5_error_code +krb5_db_store_master_key_list(krb5_context kcontext, char *keyfile, + krb5_principal mname, char *master_pwd) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + + if (v->store_master_key_list == NULL) + return KRB5_KDB_DBTYPE_NOSUP; + + if (kcontext->dal_handle->master_keylist == NULL) + return KRB5_KDB_DBNOTINITED; + + return v->store_master_key_list(kcontext, keyfile, mname, + kcontext->dal_handle->master_keylist, + master_pwd); +} + +char *krb5_mkey_pwd_prompt1 = KRB5_KDC_MKEY_1; +char *krb5_mkey_pwd_prompt2 = KRB5_KDC_MKEY_2; + +krb5_error_code +krb5_db_fetch_mkey(krb5_context context, krb5_principal mname, + krb5_enctype etype, krb5_boolean fromkeyboard, + krb5_boolean twice, char *db_args, krb5_kvno *kvno, + krb5_data *salt, krb5_keyblock *key) +{ + krb5_error_code retval; + char password[BUFSIZ]; + krb5_data pwd; + unsigned int size = sizeof(password); + krb5_keyblock tmp_key; + + memset(&tmp_key, 0, sizeof(tmp_key)); + + if (fromkeyboard) { + krb5_data scratch; + + if ((retval = krb5_read_password(context, krb5_mkey_pwd_prompt1, + twice ? krb5_mkey_pwd_prompt2 : 0, + password, &size))) { + goto clean_n_exit; + } + + pwd.data = password; + pwd.length = size; + if (!salt) { + retval = krb5_principal2salt(context, mname, &scratch); + if (retval) + goto clean_n_exit; + } + retval = + krb5_c_string_to_key(context, etype, &pwd, salt ? salt : &scratch, + key); + /* + * If a kvno pointer was passed in and it dereferences the IGNORE_VNO + * value then it should be assigned the value of the kvno associated + * with the current mkey princ key if that princ entry is available + * otherwise assign 1 which is the default kvno value for the mkey + * princ. + */ + if (kvno != NULL && *kvno == IGNORE_VNO) { + krb5_error_code rc; + krb5_db_entry *master_entry; + + rc = krb5_db_get_principal(context, mname, 0, &master_entry); + if (rc == 0 && master_entry->n_key_data > 0) + *kvno = (krb5_kvno) master_entry->key_data->key_data_kvno; + else + *kvno = 1; + if (rc == 0) + krb5_db_free_principal(context, master_entry); + } + + if (!salt) + free(scratch.data); + zap(password, sizeof(password)); /* erase it */ + + } else { + kdb_vftabl *v; + + if (context->dal_handle == NULL) { + retval = krb5_db_setup_lib_handle(context); + if (retval) + goto clean_n_exit; + } + + /* get the enctype from the stash */ + tmp_key.enctype = ENCTYPE_UNKNOWN; + + v = &context->dal_handle->lib_handle->vftabl; + retval = v->fetch_master_key(context, mname, &tmp_key, kvno, db_args); + + if (retval) + goto clean_n_exit; + + key->contents = k5memdup(tmp_key.contents, tmp_key.length, &retval); + if (key->contents == NULL) + goto clean_n_exit; + + key->magic = tmp_key.magic; + key->enctype = tmp_key.enctype; + key->length = tmp_key.length; + } + +clean_n_exit: + zapfree(tmp_key.contents, tmp_key.length); + return retval; +} + +krb5_error_code +krb5_dbe_fetch_act_key_list(krb5_context context, krb5_principal princ, + krb5_actkvno_node **act_key_list) +{ + krb5_error_code retval = 0; + krb5_db_entry *entry; + + if (act_key_list == NULL) + return (EINVAL); + + retval = krb5_db_get_principal(context, princ, 0, &entry); + if (retval == KRB5_KDB_NOENTRY) + return KRB5_KDB_NOMASTERKEY; + else if (retval) + return retval; + + retval = krb5_dbe_lookup_actkvno(context, entry, act_key_list); + krb5_db_free_principal(context, entry); + return retval; +} + +/* Find the most recent entry in list (which must not be empty) for the given + * timestamp, and return its kvno. */ +static krb5_kvno +find_actkvno(krb5_actkvno_node *list, krb5_timestamp now) +{ + /* + * The list is sorted in ascending order of time. Return the kvno of the + * predecessor of the first entry whose time is in the future. If + * (contrary to the safety checks in kdb5_util use_mkey) all of the entries + * are in the future, we will return the first node; if all are in the + * past, we will return the last node. + */ + while (list->next != NULL && !ts_after(list->next->act_time, now)) + list = list->next; + return list->act_kvno; +} + +/* Search the master keylist for the master key with the specified kvno. + * Return the keyblock of the matching entry or NULL if it does not exist. */ +static krb5_keyblock * +find_master_key(krb5_context context, krb5_kvno kvno) +{ + krb5_keylist_node *n; + + for (n = context->dal_handle->master_keylist; n != NULL; n = n->next) { + if (n->kvno == kvno) + return &n->keyblock; + } + return NULL; +} + +/* + * Locates the "active" mkey used when encrypting a princ's keys. Note, the + * caller must NOT free the output act_mkey. + */ + +krb5_error_code +krb5_dbe_find_act_mkey(krb5_context context, krb5_actkvno_node *act_mkey_list, + krb5_kvno *act_kvno, krb5_keyblock **act_mkey) +{ + krb5_kvno kvno; + krb5_error_code retval; + krb5_keyblock *mkey, *cur_mkey; + krb5_timestamp now; + + if (act_mkey_list == NULL) { + *act_kvno = 0; + *act_mkey = NULL; + return 0; + } + + if (context->dal_handle->master_keylist == NULL) + return KRB5_KDB_DBNOTINITED; + + /* Find the currently active master key version. */ + if ((retval = krb5_timeofday(context, &now))) + return (retval); + kvno = find_actkvno(act_mkey_list, now); + + /* Find the corresponding master key. */ + mkey = find_master_key(context, kvno); + if (mkey == NULL) { + /* Reload the master key list and try again. */ + cur_mkey = &context->dal_handle->master_keylist->keyblock; + if (krb5_db_fetch_mkey_list(context, context->dal_handle->master_princ, + cur_mkey) == 0) + mkey = find_master_key(context, kvno); + } + if (mkey == NULL) + return KRB5_KDB_NO_MATCHING_KEY; + + *act_mkey = mkey; + if (act_kvno != NULL) + *act_kvno = kvno; + return 0; +} + +/* + * Locates the mkey used to protect a princ's keys. Note, the caller must not + * free the output key. + */ +krb5_error_code +krb5_dbe_find_mkey(krb5_context context, krb5_db_entry *entry, + krb5_keyblock **mkey) +{ + krb5_kvno mkvno; + krb5_error_code retval; + krb5_keylist_node *cur_keyblock = context->dal_handle->master_keylist; + + if (!cur_keyblock) + return KRB5_KDB_DBNOTINITED; + + retval = krb5_dbe_get_mkvno(context, entry, &mkvno); + if (retval) + return (retval); + + while (cur_keyblock && cur_keyblock->kvno != mkvno) + cur_keyblock = cur_keyblock->next; + + if (cur_keyblock) { + *mkey = &cur_keyblock->keyblock; + return (0); + } else { + return KRB5_KDB_NO_MATCHING_KEY; + } +} + +void * +krb5_db_alloc(krb5_context kcontext, void *ptr, size_t size) +{ + return realloc(ptr, size); +} + +void +krb5_db_free(krb5_context kcontext, void *ptr) +{ + free(ptr); +} + +/* has to be modified */ + +krb5_error_code +krb5_dbe_find_enctype(krb5_context kcontext, krb5_db_entry *dbentp, + krb5_int32 ktype, krb5_int32 stype, krb5_int32 kvno, + krb5_key_data **kdatap) +{ + krb5_int32 start = 0; + return krb5_dbe_search_enctype(kcontext, dbentp, &start, ktype, stype, + kvno, kdatap); +} + +krb5_error_code +krb5_dbe_search_enctype(krb5_context kcontext, krb5_db_entry *dbentp, + krb5_int32 *start, krb5_int32 ktype, krb5_int32 stype, + krb5_int32 kvno, krb5_key_data ** kdatap) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + return v->dbe_search_enctype(kcontext, dbentp, start, ktype, stype, kvno, + kdatap); +} + +#define REALM_SEP_STRING "@" + +krb5_error_code +krb5_db_setup_mkey_name(krb5_context context, const char *keyname, + const char *realm, char **fullname, + krb5_principal *principal) +{ + krb5_error_code retval; + char *fname; + + if (!keyname) + keyname = KRB5_KDB_M_NAME; /* XXX external? */ + + if (asprintf(&fname, "%s%s%s", keyname, REALM_SEP_STRING, realm) < 0) + return ENOMEM; + + retval = krb5_parse_name(context, fname, principal); + if (retval) { + free(fname); + return retval; + } + if (fullname) + *fullname = fname; + else + free(fname); + return 0; +} + +krb5_error_code +krb5_dbe_lookup_last_pwd_change(krb5_context context, krb5_db_entry *entry, + krb5_timestamp *stamp) +{ + krb5_tl_data tl_data; + krb5_error_code code; + krb5_int32 tmp; + + tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE; + + if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))) + return (code); + + if (tl_data.tl_data_length != 4) { + *stamp = 0; + return (0); + } + + krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp); + + *stamp = (krb5_timestamp) tmp; + + return (0); +} + +krb5_error_code +krb5_dbe_lookup_last_admin_unlock(krb5_context context, krb5_db_entry *entry, + krb5_timestamp *stamp) +{ + krb5_tl_data tl_data; + krb5_error_code code; + krb5_int32 tmp; + + tl_data.tl_data_type = KRB5_TL_LAST_ADMIN_UNLOCK; + + if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))) + return (code); + + if (tl_data.tl_data_length != 4) { + *stamp = 0; + return (0); + } + + krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp); + + *stamp = (krb5_timestamp) tmp; + + return (0); +} + +krb5_error_code +krb5_dbe_lookup_tl_data(krb5_context context, krb5_db_entry *entry, + krb5_tl_data *ret_tl_data) +{ + krb5_tl_data *tl_data; + + for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) { + if (tl_data->tl_data_type == ret_tl_data->tl_data_type) { + *ret_tl_data = *tl_data; + return (0); + } + } + + /* + * If the requested record isn't found, return zero bytes. If it + * ever means something to have a zero-length tl_data, this code + * and its callers will have to be changed. + */ + + ret_tl_data->tl_data_length = 0; + ret_tl_data->tl_data_contents = NULL; + return (0); +} + +krb5_error_code +krb5_dbe_create_key_data(krb5_context context, krb5_db_entry *entry) +{ + krb5_key_data *newptr; + + newptr = realloc(entry->key_data, + (entry->n_key_data + 1) * sizeof(*entry->key_data)); + if (newptr == NULL) + return ENOMEM; + entry->key_data = newptr; + + memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data)); + entry->n_key_data++; + + return 0; +} + +krb5_error_code +krb5_dbe_update_mod_princ_data(krb5_context context, krb5_db_entry *entry, + krb5_timestamp mod_date, + krb5_const_principal mod_princ) +{ + krb5_tl_data tl_data; + + krb5_error_code retval = 0; + krb5_octet *nextloc = 0; + char *unparse_mod_princ = 0; + unsigned int unparse_mod_princ_size; + + if ((retval = krb5_unparse_name(context, mod_princ, &unparse_mod_princ))) + return (retval); + + unparse_mod_princ_size = strlen(unparse_mod_princ) + 1; + + if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4)) + == NULL) { + free(unparse_mod_princ); + return (ENOMEM); + } + + tl_data.tl_data_type = KRB5_TL_MOD_PRINC; + tl_data.tl_data_length = unparse_mod_princ_size + 4; + tl_data.tl_data_contents = nextloc; + + /* Mod Date */ + krb5_kdb_encode_int32(mod_date, nextloc); + + /* Mod Princ */ + memcpy(nextloc + 4, unparse_mod_princ, unparse_mod_princ_size); + + retval = krb5_dbe_update_tl_data(context, entry, &tl_data); + + free(unparse_mod_princ); + free(nextloc); + + return (retval); +} + +krb5_error_code +krb5_dbe_lookup_mod_princ_data(krb5_context context, krb5_db_entry *entry, + krb5_timestamp *mod_time, + krb5_principal *mod_princ) +{ + krb5_tl_data tl_data; + krb5_error_code code; + + *mod_princ = NULL; + *mod_time = 0; + + tl_data.tl_data_type = KRB5_TL_MOD_PRINC; + + if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))) + return (code); + + if ((tl_data.tl_data_length < 5) || + (tl_data.tl_data_contents[tl_data.tl_data_length - 1] != '\0')) + return (KRB5_KDB_TRUNCATED_RECORD); + + /* Mod Date */ + krb5_kdb_decode_int32(tl_data.tl_data_contents, *mod_time); + + /* Mod Princ */ + if ((code = krb5_parse_name(context, + (const char *) (tl_data.tl_data_contents + 4), + mod_princ))) + return (code); + + return (0); +} + +krb5_error_code +krb5_dbe_lookup_mkvno(krb5_context context, krb5_db_entry *entry, + krb5_kvno *mkvno) +{ + krb5_tl_data tl_data; + krb5_error_code code; + krb5_int16 tmp; + + tl_data.tl_data_type = KRB5_TL_MKVNO; + + if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))) + return (code); + + if (tl_data.tl_data_length == 0) { + *mkvno = 0; /* Indicates KRB5_TL_MKVNO data not present */ + return (0); + } else if (tl_data.tl_data_length != 2) { + return (KRB5_KDB_TRUNCATED_RECORD); + } + + krb5_kdb_decode_int16(tl_data.tl_data_contents, tmp); + *mkvno = (krb5_kvno) tmp; + return (0); +} + +krb5_error_code +krb5_dbe_get_mkvno(krb5_context context, krb5_db_entry *entry, + krb5_kvno *mkvno) +{ + krb5_error_code code; + krb5_kvno kvno; + krb5_keylist_node *mkey_list = context->dal_handle->master_keylist; + + if (mkey_list == NULL) + return KRB5_KDB_DBNOTINITED; + + /* Output the value from entry tl_data if present. */ + code = krb5_dbe_lookup_mkvno(context, entry, &kvno); + if (code != 0) + return code; + if (kvno != 0) { + *mkvno = kvno; + return 0; + } + + /* Determine the minimum kvno in mkey_list and output that. */ + kvno = (krb5_kvno) -1; + while (mkey_list != NULL) { + if (mkey_list->kvno < kvno) + kvno = mkey_list->kvno; + mkey_list = mkey_list->next; + } + *mkvno = kvno; + return 0; +} + +krb5_error_code +krb5_dbe_update_mkvno(krb5_context context, krb5_db_entry *entry, + krb5_kvno mkvno) +{ + krb5_tl_data tl_data; + krb5_octet buf[2]; /* this is the encoded size of an int16 */ + krb5_int16 tmp_kvno = (krb5_int16) mkvno; + + tl_data.tl_data_type = KRB5_TL_MKVNO; + tl_data.tl_data_length = sizeof(buf); + krb5_kdb_encode_int16(tmp_kvno, buf); + tl_data.tl_data_contents = buf; + + return (krb5_dbe_update_tl_data(context, entry, &tl_data)); +} + +krb5_error_code +krb5_dbe_lookup_mkey_aux(krb5_context context, krb5_db_entry *entry, + krb5_mkey_aux_node **mkey_aux_data_list) +{ + krb5_tl_data tl_data; + krb5_int16 version, mkey_kvno; + krb5_mkey_aux_node *head_data = NULL, *new_data = NULL, + *prev_data = NULL; + krb5_octet *curloc; /* current location pointer */ + krb5_error_code code; + + tl_data.tl_data_type = KRB5_TL_MKEY_AUX; + if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))) + return (code); + + if (tl_data.tl_data_contents == NULL) { + *mkey_aux_data_list = NULL; + return (0); + } else { + /* get version to determine how to parse the data */ + krb5_kdb_decode_int16(tl_data.tl_data_contents, version); + if (version == 1) { + /* variable size, must be at least 10 bytes */ + if (tl_data.tl_data_length < 10) + return (KRB5_KDB_TRUNCATED_RECORD); + + /* curloc points to first tuple entry in the tl_data_contents */ + curloc = tl_data.tl_data_contents + sizeof(version); + + while (curloc < (tl_data.tl_data_contents + tl_data.tl_data_length)) { + + new_data = (krb5_mkey_aux_node *) malloc(sizeof(krb5_mkey_aux_node)); + if (new_data == NULL) { + krb5_dbe_free_mkey_aux_list(context, head_data); + return (ENOMEM); + } + memset(new_data, 0, sizeof(krb5_mkey_aux_node)); + + krb5_kdb_decode_int16(curloc, mkey_kvno); + new_data->mkey_kvno = mkey_kvno; + curloc += sizeof(krb5_ui_2); + krb5_kdb_decode_int16(curloc, new_data->latest_mkey.key_data_kvno); + curloc += sizeof(krb5_ui_2); + krb5_kdb_decode_int16(curloc, new_data->latest_mkey.key_data_type[0]); + curloc += sizeof(krb5_ui_2); + krb5_kdb_decode_int16(curloc, new_data->latest_mkey.key_data_length[0]); + curloc += sizeof(krb5_ui_2); + + new_data->latest_mkey.key_data_contents[0] = (krb5_octet *) + malloc(new_data->latest_mkey.key_data_length[0]); + + if (new_data->latest_mkey.key_data_contents[0] == NULL) { + krb5_dbe_free_mkey_aux_list(context, head_data); + free(new_data); + return (ENOMEM); + } + memcpy(new_data->latest_mkey.key_data_contents[0], curloc, + new_data->latest_mkey.key_data_length[0]); + curloc += new_data->latest_mkey.key_data_length[0]; + + /* always using key data ver 1 for mkeys */ + new_data->latest_mkey.key_data_ver = 1; + + new_data->next = NULL; + if (prev_data != NULL) + prev_data->next = new_data; + else + head_data = new_data; + prev_data = new_data; + } + } else { + k5_setmsg(context, KRB5_KDB_BAD_VERSION, + _("Illegal version number for KRB5_TL_MKEY_AUX %d\n"), + version); + return (KRB5_KDB_BAD_VERSION); + } + } + *mkey_aux_data_list = head_data; + return (0); +} + +#if KRB5_TL_MKEY_AUX_VER == 1 +krb5_error_code +krb5_dbe_update_mkey_aux(krb5_context context, krb5_db_entry *entry, + krb5_mkey_aux_node *mkey_aux_data_list) +{ + krb5_error_code status; + krb5_tl_data tl_data; + krb5_int16 version, tmp_kvno; + unsigned char *nextloc; + krb5_mkey_aux_node *aux_data_entry; + + if (!mkey_aux_data_list) { + /* delete the KRB5_TL_MKEY_AUX from the entry */ + krb5_dbe_delete_tl_data(context, entry, KRB5_TL_MKEY_AUX); + return (0); + } + + memset(&tl_data, 0, sizeof(tl_data)); + tl_data.tl_data_type = KRB5_TL_MKEY_AUX; + /* + * determine out how much space to allocate. Note key_data_ver not stored + * as this is hard coded to one and is accounted for in + * krb5_dbe_lookup_mkey_aux. + */ + tl_data.tl_data_length = sizeof(version); /* version */ + for (aux_data_entry = mkey_aux_data_list; aux_data_entry != NULL; + aux_data_entry = aux_data_entry->next) { + + tl_data.tl_data_length += (sizeof(krb5_ui_2) + /* mkey_kvno */ + sizeof(krb5_ui_2) + /* latest_mkey kvno */ + sizeof(krb5_ui_2) + /* latest_mkey enctype */ + sizeof(krb5_ui_2) + /* latest_mkey length */ + aux_data_entry->latest_mkey.key_data_length[0]); + } + + tl_data.tl_data_contents = (krb5_octet *) malloc(tl_data.tl_data_length); + if (tl_data.tl_data_contents == NULL) + return (ENOMEM); + + nextloc = tl_data.tl_data_contents; + version = KRB5_TL_MKEY_AUX_VER; + krb5_kdb_encode_int16(version, nextloc); + nextloc += sizeof(krb5_ui_2); + + for (aux_data_entry = mkey_aux_data_list; aux_data_entry != NULL; + aux_data_entry = aux_data_entry->next) { + + tmp_kvno = (krb5_int16) aux_data_entry->mkey_kvno; + krb5_kdb_encode_int16(tmp_kvno, nextloc); + nextloc += sizeof(krb5_ui_2); + + krb5_kdb_encode_int16(aux_data_entry->latest_mkey.key_data_kvno, + nextloc); + nextloc += sizeof(krb5_ui_2); + + krb5_kdb_encode_int16(aux_data_entry->latest_mkey.key_data_type[0], + nextloc); + nextloc += sizeof(krb5_ui_2); + + krb5_kdb_encode_int16(aux_data_entry->latest_mkey.key_data_length[0], + nextloc); + nextloc += sizeof(krb5_ui_2); + + if (aux_data_entry->latest_mkey.key_data_length[0] > 0) { + memcpy(nextloc, aux_data_entry->latest_mkey.key_data_contents[0], + aux_data_entry->latest_mkey.key_data_length[0]); + nextloc += aux_data_entry->latest_mkey.key_data_length[0]; + } + } + + status = krb5_dbe_update_tl_data(context, entry, &tl_data); + free(tl_data.tl_data_contents); + return status; +} +#endif /* KRB5_TL_MKEY_AUX_VER == 1 */ + +#if KRB5_TL_ACTKVNO_VER == 1 +/* + * If version of the KRB5_TL_ACTKVNO data is KRB5_TL_ACTKVNO_VER == 1 then size of + * a actkvno tuple {act_kvno, act_time} entry is: + */ +#define ACTKVNO_TUPLE_SIZE (sizeof(krb5_int16) + sizeof(krb5_int32)) +#define act_kvno(cp) (cp) /* return pointer to start of act_kvno data */ +#define act_time(cp) ((cp) + sizeof(krb5_int16)) /* return pointer to start of act_time data */ +#endif + +krb5_error_code +krb5_dbe_lookup_actkvno(krb5_context context, krb5_db_entry *entry, + krb5_actkvno_node **actkvno_list) +{ + krb5_tl_data tl_data; + krb5_error_code code; + krb5_int16 version, tmp_kvno; + krb5_actkvno_node *head_data = NULL, *new_data = NULL, *prev_data = NULL; + unsigned int num_actkvno, i; + krb5_octet *next_tuple; + krb5_kvno earliest_kvno; + + memset(&tl_data, 0, sizeof(tl_data)); + tl_data.tl_data_type = KRB5_TL_ACTKVNO; + + if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))) + return (code); + + if (tl_data.tl_data_contents == NULL) { + /* + * If there is no KRB5_TL_ACTKVNO data (likely because the KDB was + * created prior to 1.7), synthesize the list which should have been + * created at KDB initialization, making the earliest master key + * active. + */ + + /* Get the earliest master key version. */ + if (entry->n_key_data == 0) + return KRB5_KDB_NOMASTERKEY; + earliest_kvno = entry->key_data[entry->n_key_data - 1].key_data_kvno; + + head_data = malloc(sizeof(*head_data)); + if (head_data == NULL) + return ENOMEM; + memset(head_data, 0, sizeof(*head_data)); + head_data->act_time = 0; /* earliest time possible */ + head_data->act_kvno = earliest_kvno; + } else { + /* get version to determine how to parse the data */ + krb5_kdb_decode_int16(tl_data.tl_data_contents, version); + if (version == 1) { + + /* variable size, must be at least 8 bytes */ + if (tl_data.tl_data_length < 8) + return (KRB5_KDB_TRUNCATED_RECORD); + + /* + * Find number of tuple entries, remembering to account for version + * field. + */ + num_actkvno = (tl_data.tl_data_length - sizeof(version)) / + ACTKVNO_TUPLE_SIZE; + prev_data = NULL; + /* next_tuple points to first tuple entry in the tl_data_contents */ + next_tuple = tl_data.tl_data_contents + sizeof(version); + for (i = 0; i < num_actkvno; i++) { + new_data = (krb5_actkvno_node *) malloc(sizeof(krb5_actkvno_node)); + if (new_data == NULL) { + krb5_dbe_free_actkvno_list(context, head_data); + return (ENOMEM); + } + memset(new_data, 0, sizeof(krb5_actkvno_node)); + + /* using tmp_kvno to avoid type mismatch */ + krb5_kdb_decode_int16(act_kvno(next_tuple), tmp_kvno); + new_data->act_kvno = (krb5_kvno) tmp_kvno; + krb5_kdb_decode_int32(act_time(next_tuple), new_data->act_time); + + if (prev_data != NULL) + prev_data->next = new_data; + else + head_data = new_data; + prev_data = new_data; + next_tuple += ACTKVNO_TUPLE_SIZE; + } + } else { + k5_setmsg(context, KRB5_KDB_BAD_VERSION, + _("Illegal version number for KRB5_TL_ACTKVNO %d\n"), + version); + return (KRB5_KDB_BAD_VERSION); + } + } + *actkvno_list = head_data; + return (0); +} + +/* + * Add KRB5_TL_ACTKVNO TL data entries to krb5_db_entry *entry + */ +#if KRB5_TL_ACTKVNO_VER == 1 +krb5_error_code +krb5_dbe_update_actkvno(krb5_context context, krb5_db_entry *entry, + const krb5_actkvno_node *actkvno_list) +{ + krb5_error_code retval = 0; + krb5_int16 version, tmp_kvno; + krb5_tl_data new_tl_data; + unsigned char *nextloc; + const krb5_actkvno_node *cur_actkvno; + krb5_octet *tmpptr; + + if (actkvno_list == NULL) + return EINVAL; + + memset(&new_tl_data, 0, sizeof(new_tl_data)); + /* allocate initial KRB5_TL_ACTKVNO tl_data entry */ + new_tl_data.tl_data_length = sizeof(version); + new_tl_data.tl_data_contents = (krb5_octet *) malloc(new_tl_data.tl_data_length); + if (new_tl_data.tl_data_contents == NULL) + return ENOMEM; + + /* add the current version # for the data format used for KRB5_TL_ACTKVNO */ + version = KRB5_TL_ACTKVNO_VER; + krb5_kdb_encode_int16(version, (unsigned char *) new_tl_data.tl_data_contents); + + for (cur_actkvno = actkvno_list; cur_actkvno != NULL; + cur_actkvno = cur_actkvno->next) { + + new_tl_data.tl_data_length += ACTKVNO_TUPLE_SIZE; + tmpptr = realloc(new_tl_data.tl_data_contents, new_tl_data.tl_data_length); + if (tmpptr == NULL) { + free(new_tl_data.tl_data_contents); + return ENOMEM; + } else { + new_tl_data.tl_data_contents = tmpptr; + } + + /* + * Using realloc so tl_data_contents is required to correctly calculate + * next location to store new tuple. + */ + nextloc = new_tl_data.tl_data_contents + new_tl_data.tl_data_length - ACTKVNO_TUPLE_SIZE; + /* using tmp_kvno to avoid type mismatch issues */ + tmp_kvno = (krb5_int16) cur_actkvno->act_kvno; + krb5_kdb_encode_int16(tmp_kvno, nextloc); + nextloc += sizeof(krb5_ui_2); + krb5_kdb_encode_int32((krb5_ui_4)cur_actkvno->act_time, nextloc); + } + + new_tl_data.tl_data_type = KRB5_TL_ACTKVNO; + retval = krb5_dbe_update_tl_data(context, entry, &new_tl_data); + free(new_tl_data.tl_data_contents); + + return (retval); +} +#endif /* KRB5_TL_ACTKVNO_VER == 1 */ + +krb5_error_code +krb5_dbe_update_last_pwd_change(krb5_context context, krb5_db_entry *entry, + krb5_timestamp stamp) +{ + krb5_tl_data tl_data; + krb5_octet buf[4]; /* this is the encoded size of an int32 */ + + tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE; + tl_data.tl_data_length = sizeof(buf); + krb5_kdb_encode_int32((krb5_int32) stamp, buf); + tl_data.tl_data_contents = buf; + + return (krb5_dbe_update_tl_data(context, entry, &tl_data)); +} + +krb5_error_code +krb5_dbe_update_last_admin_unlock(krb5_context context, krb5_db_entry *entry, + krb5_timestamp stamp) +{ + krb5_tl_data tl_data; + krb5_octet buf[4]; /* this is the encoded size of an int32 */ + + tl_data.tl_data_type = KRB5_TL_LAST_ADMIN_UNLOCK; + tl_data.tl_data_length = sizeof(buf); + krb5_kdb_encode_int32((krb5_int32) stamp, buf); + tl_data.tl_data_contents = buf; + + return (krb5_dbe_update_tl_data(context, entry, &tl_data)); +} + +/* + * Prepare to iterate over the string attributes of entry. The returned + * pointers are aliases into entry's tl_data (or into an empty string literal) + * and remain valid until the entry's tl_data is changed. + */ +static krb5_error_code +begin_attrs(krb5_context context, krb5_db_entry *entry, const char **pos_out, + const char **end_out) +{ + krb5_error_code code; + krb5_tl_data tl_data; + + *pos_out = *end_out = NULL; + tl_data.tl_data_type = KRB5_TL_STRING_ATTRS; + code = krb5_dbe_lookup_tl_data(context, entry, &tl_data); + if (code) + return code; + + /* Copy the current mapping to buf, updating key with value if found. */ + *pos_out = (const char *)tl_data.tl_data_contents; + *end_out = *pos_out + tl_data.tl_data_length; + return 0; +} + +/* Find the next key and value pair in *pos and update *pos. */ +static krb5_boolean +next_attr(const char **pos, const char *end, const char **key_out, + const char **val_out) +{ + const char *key, *key_end, *val, *val_end; + + *key_out = *val_out = NULL; + if (*pos == end) + return FALSE; + key = *pos; + key_end = memchr(key, '\0', end - key); + if (key_end == NULL) /* Malformed representation; give up. */ + return FALSE; + val = key_end + 1; + val_end = memchr(val, '\0', end - val); + if (val_end == NULL) /* Malformed representation; give up. */ + return FALSE; + + *key_out = key; + *val_out = val; + *pos = val_end + 1; + return TRUE; +} + +krb5_error_code +krb5_dbe_get_strings(krb5_context context, krb5_db_entry *entry, + krb5_string_attr **strings_out, int *count_out) +{ + krb5_error_code code; + const char *pos, *end, *mapkey, *mapval; + char *key = NULL, *val = NULL; + krb5_string_attr *strings = NULL, *newstrings; + int count = 0; + + *strings_out = NULL; + *count_out = 0; + code = begin_attrs(context, entry, &pos, &end); + if (code) + return code; + + while (next_attr(&pos, end, &mapkey, &mapval)) { + /* Add a copy of mapkey and mapvalue to strings. */ + newstrings = realloc(strings, (count + 1) * sizeof(*strings)); + if (newstrings == NULL) + goto oom; + strings = newstrings; + key = strdup(mapkey); + val = strdup(mapval); + if (key == NULL || val == NULL) + goto oom; + strings[count].key = key; + strings[count].value = val; + count++; + } + + *strings_out = strings; + *count_out = count; + return 0; + +oom: + free(key); + free(val); + krb5_dbe_free_strings(context, strings, count); + return ENOMEM; +} + +krb5_error_code +krb5_dbe_get_string(krb5_context context, krb5_db_entry *entry, + const char *key, char **value_out) +{ + krb5_error_code code; + const char *pos, *end, *mapkey, *mapval; + + *value_out = NULL; + code = begin_attrs(context, entry, &pos, &end); + if (code) + return code; + while (next_attr(&pos, end, &mapkey, &mapval)) { + if (strcmp(mapkey, key) == 0) { + *value_out = strdup(mapval); + return (*value_out == NULL) ? ENOMEM : 0; + } + } + + return 0; +} + +krb5_error_code +krb5_dbe_set_string(krb5_context context, krb5_db_entry *entry, + const char *key, const char *value) +{ + krb5_error_code code; + const char *pos, *end, *mapkey, *mapval; + struct k5buf buf = EMPTY_K5BUF; + krb5_boolean found = FALSE; + krb5_tl_data tl_data; + + /* Copy the current mapping to buf, updating key with value if found. */ + code = begin_attrs(context, entry, &pos, &end); + if (code) + return code; + k5_buf_init_dynamic(&buf); + while (next_attr(&pos, end, &mapkey, &mapval)) { + if (strcmp(mapkey, key) == 0) { + if (value != NULL) { + k5_buf_add_len(&buf, mapkey, strlen(mapkey) + 1); + k5_buf_add_len(&buf, value, strlen(value) + 1); + } + found = TRUE; + } else { + k5_buf_add_len(&buf, mapkey, strlen(mapkey) + 1); + k5_buf_add_len(&buf, mapval, strlen(mapval) + 1); + } + } + + /* If key wasn't found in the map, add a new entry for it. */ + if (!found && value != NULL) { + k5_buf_add_len(&buf, key, strlen(key) + 1); + k5_buf_add_len(&buf, value, strlen(value) + 1); + } + + if (k5_buf_status(&buf) != 0) + return ENOMEM; + if (buf.len > 65535) { + code = KRB5_KDB_STRINGS_TOOLONG; + goto cleanup; + } + tl_data.tl_data_type = KRB5_TL_STRING_ATTRS; + tl_data.tl_data_contents = buf.data; + tl_data.tl_data_length = buf.len; + + code = krb5_dbe_update_tl_data(context, entry, &tl_data); + +cleanup: + k5_buf_free(&buf); + return code; +} + +krb5_error_code +krb5_dbe_delete_tl_data(krb5_context context, krb5_db_entry *entry, + krb5_int16 tl_data_type) +{ + krb5_tl_data *tl_data, *prev_tl_data, *free_tl_data; + + /* + * Find existing entries of the specified type and remove them from the + * entry's tl_data list. + */ + + for (prev_tl_data = tl_data = entry->tl_data; tl_data != NULL;) { + if (tl_data->tl_data_type == tl_data_type) { + if (tl_data == entry->tl_data) { + /* remove from head */ + entry->tl_data = tl_data->tl_data_next; + prev_tl_data = entry->tl_data; + } else if (tl_data->tl_data_next == NULL) { + /* remove from tail */ + prev_tl_data->tl_data_next = NULL; + } else { + /* remove in between */ + prev_tl_data->tl_data_next = tl_data->tl_data_next; + } + free_tl_data = tl_data; + tl_data = tl_data->tl_data_next; + krb5_dbe_free_tl_data(context, free_tl_data); + entry->n_tl_data--; + } else { + prev_tl_data = tl_data; + tl_data = tl_data->tl_data_next; + } + } + + return (0); +} + +krb5_error_code +krb5_db_update_tl_data(krb5_context context, krb5_int16 *n_tl_datap, + krb5_tl_data **tl_datap, krb5_tl_data *new_tl_data) +{ + krb5_tl_data *tl_data = NULL; + krb5_octet *tmp; + + /* + * Copy the new data first, so we can fail cleanly if malloc() + * fails. + */ + tmp = malloc(new_tl_data->tl_data_length); + if (tmp == NULL) + return (ENOMEM); + + /* + * Find an existing entry of the specified type and point at + * it, or NULL if not found. + */ + + if (new_tl_data->tl_data_type != KRB5_TL_DB_ARGS) { /* db_args can be multiple */ + for (tl_data = *tl_datap; tl_data; + tl_data = tl_data->tl_data_next) + if (tl_data->tl_data_type == new_tl_data->tl_data_type) + break; + } + + /* If necessary, chain a new record in the beginning and point at it. */ + + if (!tl_data) { + tl_data = calloc(1, sizeof(*tl_data)); + if (tl_data == NULL) { + free(tmp); + return (ENOMEM); + } + tl_data->tl_data_next = *tl_datap; + *tl_datap = tl_data; + (*n_tl_datap)++; + } + + /* fill in the record */ + + free(tl_data->tl_data_contents); + + tl_data->tl_data_type = new_tl_data->tl_data_type; + tl_data->tl_data_length = new_tl_data->tl_data_length; + tl_data->tl_data_contents = tmp; + memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length); + + return (0); +} + +krb5_error_code +krb5_dbe_update_tl_data(krb5_context context, krb5_db_entry *entry, + krb5_tl_data *new_tl_data) +{ + return krb5_db_update_tl_data(context, &entry->n_tl_data, &entry->tl_data, + new_tl_data); +} + +krb5_error_code +krb5_dbe_compute_salt(krb5_context context, const krb5_key_data *key, + krb5_const_principal princ, krb5_int16 *salttype_out, + krb5_data **salt_out) +{ + krb5_error_code retval; + krb5_int16 stype; + krb5_data *salt, sdata; + + stype = (key->key_data_ver < 2) ? KRB5_KDB_SALTTYPE_NORMAL : + key->key_data_type[1]; + *salttype_out = stype; + *salt_out = NULL; + + /* Place computed salt into sdata, or directly into salt_out and return. */ + switch (stype) { + case KRB5_KDB_SALTTYPE_NORMAL: + retval = krb5_principal2salt(context, princ, &sdata); + if (retval) + return retval; + break; + case KRB5_KDB_SALTTYPE_NOREALM: + retval = krb5_principal2salt_norealm(context, princ, &sdata); + if (retval) + return retval; + break; + case KRB5_KDB_SALTTYPE_ONLYREALM: + return krb5_copy_data(context, &princ->realm, salt_out); + case KRB5_KDB_SALTTYPE_SPECIAL: + sdata = make_data(key->key_data_contents[1], key->key_data_length[1]); + return krb5_copy_data(context, &sdata, salt_out); + default: + return KRB5_KDB_BAD_SALTTYPE; + } + + /* Make a container for sdata. */ + salt = malloc(sizeof(*salt)); + if (salt == NULL) { + free(sdata.data); + return ENOMEM; + } + *salt = sdata; + *salt_out = salt; + return 0; +} + +krb5_error_code +krb5_dbe_specialize_salt(krb5_context context, krb5_db_entry *entry) +{ + krb5_int16 stype, i; + krb5_data *salt; + krb5_error_code ret; + + if (context == NULL || entry == NULL) + return EINVAL; + + /* + * Store salt values explicitly so that they don't depend on the principal + * name. + */ + for (i = 0; i < entry->n_key_data; i++) { + ret = krb5_dbe_compute_salt(context, &entry->key_data[i], entry->princ, + &stype, &salt); + if (ret) + return ret; + + /* Steal the data pointer from salt and free the container. */ + if (entry->key_data[i].key_data_ver >= 2) + free(entry->key_data[i].key_data_contents[1]); + entry->key_data[i].key_data_type[1] = KRB5_KDB_SALTTYPE_SPECIAL; + entry->key_data[i].key_data_contents[1] = (uint8_t *)salt->data; + entry->key_data[i].key_data_length[1] = salt->length; + entry->key_data[i].key_data_ver = 2; + free(salt); + } + + return 0; +} + +/* change password functions */ +krb5_error_code +krb5_dbe_cpw(krb5_context kcontext, krb5_keyblock *master_key, + krb5_key_salt_tuple *ks_tuple, int ks_tuple_count, char *passwd, + int new_kvno, krb5_boolean keepold, krb5_db_entry *db_entry) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + return v->change_pwd(kcontext, master_key, ks_tuple, ks_tuple_count, + passwd, new_kvno, keepold, db_entry); +} + +/* policy management functions */ +krb5_error_code +krb5_db_create_policy(krb5_context kcontext, osa_policy_ent_t policy) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->create_policy == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + + status = v->create_policy(kcontext, policy); + /* iprop does not support policy mods; force full resync. */ + if (!status && logging(kcontext)) + status = ulog_init_header(kcontext); + return status; +} + +krb5_error_code +krb5_db_get_policy(krb5_context kcontext, char *name, osa_policy_ent_t *policy) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->get_policy == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + return v->get_policy(kcontext, name, policy); +} + +krb5_error_code +krb5_db_put_policy(krb5_context kcontext, osa_policy_ent_t policy) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->put_policy == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + + status = v->put_policy(kcontext, policy); + /* iprop does not support policy mods; force full resync. */ + if (!status && logging(kcontext)) + status = ulog_init_header(kcontext); + return status; +} + +krb5_error_code +krb5_db_iter_policy(krb5_context kcontext, char *match_entry, + osa_adb_iter_policy_func func, void *data) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->iter_policy == NULL) + return 0; + return v->iter_policy(kcontext, match_entry, func, data); +} + +krb5_error_code +krb5_db_delete_policy(krb5_context kcontext, char *policy) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->delete_policy == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + + status = v->delete_policy(kcontext, policy); + /* iprop does not support policy mods; force full resync. */ + if (!status && logging(kcontext)) + status = ulog_init_header(kcontext); + return status; +} + +void +krb5_db_free_policy(krb5_context kcontext, osa_policy_ent_t policy) +{ + if (policy == NULL) + return; + free(policy->name); + free(policy->allowed_keysalts); + free_tl_data(policy->tl_data); + free(policy); +} + +krb5_error_code +krb5_db_promote(krb5_context kcontext, char **db_args) +{ + krb5_error_code status; + char *section; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->promote_db == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + status = get_conf_section(kcontext, §ion); + if (status) + return status; + status = v->promote_db(kcontext, section, db_args); + free(section); + return status; +} + +static krb5_error_code +decrypt_iterator(krb5_context kcontext, const krb5_key_data * key_data, + krb5_keyblock *dbkey, krb5_keysalt *keysalt) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + krb5_keylist_node *n = kcontext->dal_handle->master_keylist; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + for (; n; n = n->next) { + krb5_clear_error_message(kcontext); + status = v->decrypt_key_data(kcontext, &n->keyblock, key_data, dbkey, + keysalt); + if (status == 0) + return 0; + } + return status; +} + +krb5_error_code +krb5_dbe_decrypt_key_data(krb5_context kcontext, const krb5_keyblock *mkey, + const krb5_key_data *key_data, krb5_keyblock *dbkey, + krb5_keysalt *keysalt) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + krb5_keyblock *cur_mkey; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (mkey || kcontext->dal_handle->master_keylist == NULL) + return v->decrypt_key_data(kcontext, mkey, key_data, dbkey, keysalt); + status = decrypt_iterator(kcontext, key_data, dbkey, keysalt); + if (status == 0) + return 0; + if (kcontext->dal_handle->master_keylist) { + /* Try reloading master keys. */ + cur_mkey = &kcontext->dal_handle->master_keylist->keyblock; + if (krb5_db_fetch_mkey_list(kcontext, + kcontext->dal_handle->master_princ, + cur_mkey) == 0) + return decrypt_iterator(kcontext, key_data, dbkey, keysalt); + } + return status; +} + +krb5_error_code +krb5_dbe_encrypt_key_data(krb5_context kcontext, const krb5_keyblock *mkey, + const krb5_keyblock *dbkey, + const krb5_keysalt *keysalt, int keyver, + krb5_key_data *key_data) +{ + krb5_error_code status = 0; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + return v->encrypt_key_data(kcontext, mkey, dbkey, keysalt, keyver, + key_data); +} + +krb5_error_code +krb5_db_get_context(krb5_context context, void **db_context) +{ + *db_context = KRB5_DB_GET_DB_CONTEXT(context); + if (*db_context == NULL) + return KRB5_KDB_DBNOTINITED; + return 0; +} + +krb5_error_code +krb5_db_set_context(krb5_context context, void *db_context) +{ + KRB5_DB_GET_DB_CONTEXT(context) = db_context; + + return 0; +} + +krb5_error_code +krb5_db_check_transited_realms(krb5_context kcontext, + const krb5_data *tr_contents, + const krb5_data *client_realm, + const krb5_data *server_realm) +{ + krb5_error_code status; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status) + return status; + if (v->check_transited_realms == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + return v->check_transited_realms(kcontext, tr_contents, client_realm, + server_realm); +} + +krb5_error_code +krb5_db_check_policy_as(krb5_context kcontext, krb5_kdc_req *request, + krb5_db_entry *client, krb5_db_entry *server, + krb5_timestamp kdc_time, const char **status, + krb5_pa_data ***e_data) +{ + krb5_error_code ret; + kdb_vftabl *v; + + *status = NULL; + *e_data = NULL; + ret = get_vftabl(kcontext, &v); + if (ret) + return ret; + if (v->check_policy_as == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + return v->check_policy_as(kcontext, request, client, server, kdc_time, + status, e_data); +} + +krb5_error_code +krb5_db_check_policy_tgs(krb5_context kcontext, krb5_kdc_req *request, + krb5_db_entry *server, krb5_ticket *ticket, + const char **status, krb5_pa_data ***e_data) +{ + krb5_error_code ret; + kdb_vftabl *v; + + *status = NULL; + *e_data = NULL; + ret = get_vftabl(kcontext, &v); + if (ret) + return ret; + if (v->check_policy_tgs == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + return v->check_policy_tgs(kcontext, request, server, ticket, status, + e_data); +} + +void +krb5_db_audit_as_req(krb5_context kcontext, krb5_kdc_req *request, + const krb5_address *local_addr, + const krb5_address *remote_addr, krb5_db_entry *client, + krb5_db_entry *server, krb5_timestamp authtime, + krb5_error_code error_code) +{ + krb5_error_code status; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status || v->audit_as_req == NULL) + return; + v->audit_as_req(kcontext, request, local_addr, remote_addr, + client, server, authtime, error_code); +} + +void +krb5_db_refresh_config(krb5_context kcontext) +{ + krb5_error_code status; + kdb_vftabl *v; + + status = get_vftabl(kcontext, &v); + if (status || v->refresh_config == NULL) + return; + v->refresh_config(kcontext); +} + +krb5_error_code +krb5_db_check_allowed_to_delegate(krb5_context kcontext, + krb5_const_principal client, + const krb5_db_entry *server, + krb5_const_principal proxy) +{ + krb5_error_code ret; + kdb_vftabl *v; + + ret = get_vftabl(kcontext, &v); + if (ret) + return ret; + if (v->check_allowed_to_delegate == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + return v->check_allowed_to_delegate(kcontext, client, server, proxy); +} + +krb5_error_code +krb5_db_get_s4u_x509_principal(krb5_context kcontext, + const krb5_data *client_cert, + krb5_const_principal in_princ, + unsigned int flags, krb5_db_entry **entry) +{ + krb5_error_code ret; + kdb_vftabl *v; + + ret = get_vftabl(kcontext, &v); + if (ret) + return ret; + if (v->get_s4u_x509_principal == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + ret = v->get_s4u_x509_principal(kcontext, client_cert, in_princ, flags, + entry); + if (ret) + return ret; + + /* Sort the keys in the db entry, same as get_principal(). */ + if ((*entry)->key_data != NULL) + krb5_dbe_sort_key_data((*entry)->key_data, (*entry)->n_key_data); + + return 0; +} + +krb5_error_code +krb5_db_allowed_to_delegate_from(krb5_context kcontext, + krb5_const_principal client, + krb5_const_principal server, + krb5_pac server_pac, + const krb5_db_entry *proxy) +{ + krb5_error_code ret; + kdb_vftabl *v; + + ret = get_vftabl(kcontext, &v); + if (ret) + return ret; + if (v->allowed_to_delegate_from == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + return v->allowed_to_delegate_from(kcontext, client, server, server_pac, + proxy); +} + +void +krb5_dbe_sort_key_data(krb5_key_data *key_data, size_t key_data_length) +{ + size_t i, j; + krb5_key_data tmp; + + /* Use insertion sort as a stable sort. */ + for (i = 1; i < key_data_length; i++) { + j = i; + while (j > 0 && + key_data[j - 1].key_data_kvno < key_data[j].key_data_kvno) { + tmp = key_data[j]; + key_data[j] = key_data[j - 1]; + key_data[j - 1] = tmp; + j--; + } + } +} + +krb5_error_code +krb5_db_issue_pac(krb5_context context, unsigned int flags, + krb5_db_entry *client, krb5_keyblock *replaced_reply_key, + krb5_db_entry *server, krb5_db_entry *krbtgt, + krb5_timestamp authtime, krb5_pac old_pac, krb5_pac new_pac, + krb5_data ***auth_indicators) +{ + krb5_error_code ret; + kdb_vftabl *v; + + ret = get_vftabl(context, &v); + if (ret) + return ret; + if (v->issue_pac == NULL) + return KRB5_PLUGIN_OP_NOTSUPP; + return v->issue_pac(context, flags, client, replaced_reply_key, server, + krbtgt, authtime, old_pac, new_pac, auth_indicators); +} diff --git a/krb5-1.21.3/src/lib/kdb/kdb5.h b/krb5-1.21.3/src/lib/kdb/kdb5.h new file mode 100644 index 00000000..9a43046b --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/kdb5.h @@ -0,0 +1,38 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#ifndef _KRB5_KDB5_H_ +#define _KRB5_KDB5_H_ + +#include + +#if HAVE_UNISTD_H +#include +#endif + +#include +#include +#include "kdb.h" + +#define KRB5_DB_GET_DB_CONTEXT(kcontext) (((kdb5_dal_handle*) (kcontext)->dal_handle)->db_context) +#define KRB5_DB_GET_PROFILE(kcontext) ((kcontext)->profile) +#define KRB5_DB_GET_REALM(kcontext) ((kcontext)->default_realm) + +typedef struct _db_library { + char name[KDB_MAX_DB_NAME]; + int reference_cnt; + struct plugin_dir_handle dl_dir_handle; + kdb_vftabl vftabl; + struct _db_library *next, *prev; +} *db_library; + +struct _kdb5_dal_handle +{ + /* Helps us to change db_library without affecting modules to some + extent. */ + void *db_context; + db_library lib_handle; + krb5_keylist_node *master_keylist; + krb5_principal master_princ; +}; +/* typedef kdb5_dal_handle is in k5-int.h now */ + +#endif /* end of _KRB5_KDB5_H_ */ diff --git a/krb5-1.21.3/src/lib/kdb/kdb5int.h b/krb5-1.21.3/src/lib/kdb/kdb5int.h new file mode 100644 index 00000000..56570cea --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/kdb5int.h @@ -0,0 +1,40 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kdb/kdb5int.h - Private header for kdb5 library */ +/* + * Copyright (C) 2008 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __KDB5INT_H__ +#define __KDB5INT_H__ + +#include "kdb5.h" + +krb5_error_code +krb5int_put_principal_no_log(krb5_context kcontext, + krb5_db_entry *entries); + +krb5_error_code +krb5int_delete_principal_no_log(krb5_context kcontext, + krb5_principal search_for); + +#endif /* __KDB5INT_H__ */ diff --git a/krb5-1.21.3/src/lib/kdb/kdb_convert.c b/krb5-1.21.3/src/lib/kdb/kdb_convert.c new file mode 100644 index 00000000..59952f55 --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/kdb_convert.c @@ -0,0 +1,918 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* #pragma ident "@(#)kdb_convert.c 1.3 05/01/05 SMI" */ + +/* + * This file contains api's for conversion of the kdb_incr_update_t + * struct(s) into krb5_db_entry struct(s) and vice-versa. + */ +#include +#include +#include +#include +#include +#include "iprop.h" +#include +#include + +/* BEGIN CSTYLED */ +#define ULOG_ENTRY_TYPE(upd, i) ((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i] + +#define ULOG_ENTRY(upd, i) ((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i].kdbe_val_t_u + +#define ULOG_ENTRY_KEYVAL(upd, i, j) ((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i].kdbe_val_t_u.av_keydata.av_keydata_val[j] + +#define ULOG_ENTRY_PRINC(upd, i, j) ((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i].kdbe_val_t_u.av_princ.k_components.k_components_val[j] + +#define ULOG_ENTRY_MOD_PRINC(upd, i, j) ((kdb_incr_update_t *)upd)->kdb_update.kdbe_t_val[i].kdbe_val_t_u.av_mod_princ.k_components.k_components_val[j] +/* END CSTYLED */ + +typedef enum { + REG_PRINC = 0, + MOD_PRINC = 1 +} princ_type; + + +/* + * This routine tracks the krb5_db_entry fields that have been modified + * (by comparing it to the db_entry currently present in principal.db) + * in the update. + */ +static void +find_changed_attrs(krb5_db_entry *current, krb5_db_entry *new, + krb5_boolean exclude_nra, + kdbe_attr_type_t *attrs, int *nattrs) +{ + int i = 0, j = 0; + + krb5_tl_data *first, *second; + + if (current->attributes != new->attributes) + attrs[i++] = AT_ATTRFLAGS; + + if (current->max_life != new->max_life) + attrs[i++] = AT_MAX_LIFE; + + if (current->max_renewable_life != new->max_renewable_life) + attrs[i++] = AT_MAX_RENEW_LIFE; + + if (current->expiration != new->expiration) + attrs[i++] = AT_EXP; + + if (current->pw_expiration != new->pw_expiration) + attrs[i++] = AT_PW_EXP; + + if (!exclude_nra) { + if (current->last_success != new->last_success) + attrs[i++] = AT_LAST_SUCCESS; + + if (current->last_failed != new->last_failed) + attrs[i++] = AT_LAST_FAILED; + + if (current->fail_auth_count != new->fail_auth_count) + attrs[i++] = AT_FAIL_AUTH_COUNT; + } + + if ((current->princ->type == new->princ->type) && + (current->princ->length == new->princ->length)) { + if ((current->princ->realm.length == + new->princ->realm.length) && + strncmp(current->princ->realm.data, + new->princ->realm.data, + current->princ->realm.length)) { + for (j = 0; j < current->princ->length; j++) { + if ((current->princ->data[j].data != NULL) && + (strncmp(current->princ->data[j].data, + new->princ->data[j].data, + current->princ->data[j].length))) { + attrs[i++] = AT_PRINC; + break; + } + } + } else { + attrs[i++] = AT_PRINC; + } + } else { + attrs[i++] = AT_PRINC; + } + + if (current->n_key_data == new->n_key_data) { + /* Assuming key ordering is the same in new & current */ + for (j = 0; j < new->n_key_data; j++) { + if (current->key_data[j].key_data_kvno != + new->key_data[j].key_data_kvno) { + attrs[i++] = AT_KEYDATA; + break; + } + } + } else { + attrs[i++] = AT_KEYDATA; + } + + if (current->n_tl_data == new->n_tl_data) { + /* Assuming we preserve the TL_DATA ordering between updates */ + for (first = current->tl_data, second = new->tl_data; + first; first = first->tl_data_next, + second = second->tl_data_next) { + if ((first->tl_data_length == second->tl_data_length) && + (first->tl_data_type == second->tl_data_type)) { + if ((memcmp((char *)first->tl_data_contents, + (char *)second->tl_data_contents, + first->tl_data_length)) != 0) { + attrs[i++] = AT_TL_DATA; + break; + } + } else { + attrs[i++] = AT_TL_DATA; + break; + } + } + } else { + attrs[i++] = AT_TL_DATA; + } + + if (current->len != new->len) + attrs[i++] = AT_LEN; + /* + * Store the no. of (possibly :)) changed attributes + */ + *nattrs = i; +} + + +/* Initialize *u with a copy of d. Return 0 on success, -1 on failure. */ +static int +data_to_utf8str(utf8str_t *u, krb5_data d) +{ + u->utf8str_t_len = d.length; + if (d.data) { + u->utf8str_t_val = malloc(d.length); + if (u->utf8str_t_val == NULL) + return -1; + memcpy(u->utf8str_t_val, d.data, d.length); + } else + u->utf8str_t_val = NULL; + return 0; +} + +/* + * Converts the krb5_principal struct from db2 to ulog format. + */ +static krb5_error_code +conv_princ_2ulog(krb5_principal princ, kdb_incr_update_t *upd, + int cnt, princ_type tp) +{ + int i = 0; + kdbe_princ_t *p; + kdbe_data_t *components; + + if ((upd == NULL) || !princ) + return (KRB5KRB_ERR_GENERIC); + + switch (tp) { + case REG_PRINC: + case MOD_PRINC: + p = &ULOG_ENTRY(upd, cnt).av_princ; /* or av_mod_princ */ + p->k_nametype = (int32_t)princ->type; + + if (data_to_utf8str(&p->k_realm, princ->realm) < 0) { + return ENOMEM; + } + + p->k_components.k_components_len = princ->length; + + p->k_components.k_components_val = components + = malloc(princ->length * sizeof (kdbe_data_t)); + if (p->k_components.k_components_val == NULL) { + free(p->k_realm.utf8str_t_val); + p->k_realm.utf8str_t_val = NULL; + return (ENOMEM); + } + + memset(components, 0, princ->length * sizeof(kdbe_data_t)); + for (i = 0; i < princ->length; i++) + components[i].k_data.utf8str_t_val = NULL; + for (i = 0; i < princ->length; i++) { + components[i].k_magic = princ->data[i].magic; + if (data_to_utf8str(&components[i].k_data, princ->data[i]) < 0) { + int j; + for (j = 0; j < i; j++) { + free(components[j].k_data.utf8str_t_val); + components[j].k_data.utf8str_t_val = NULL; + } + free(components); + p->k_components.k_components_val = NULL; + free(p->k_realm.utf8str_t_val); + p->k_realm.utf8str_t_val = NULL; + return ENOMEM; + } + } + break; + + default: + break; + } + return (0); +} + +/* + * Copies a UTF-8 string from ulog to a krb5_data object, which may + * already have allocated storage associated with it. + * + * Maybe a return value should indicate success/failure? + */ +static void +set_from_utf8str(krb5_data *d, utf8str_t u) +{ + if (u.utf8str_t_len > INT_MAX - 1) { + d->data = NULL; + return; + } + d->length = u.utf8str_t_len; + d->data = malloc(d->length + 1); + if (d->data == NULL) + return; + if (d->length) /* Pointer may be null if length = 0. */ + strncpy(d->data, u.utf8str_t_val, d->length); + d->data[d->length] = 0; +} + +/* + * Converts the krb5_principal struct from ulog to db2 format. + */ +static krb5_principal +conv_princ_2db(krb5_context context, kdbe_princ_t *kdbe_princ) +{ + unsigned int i; + int j; + krb5_principal princ; + kdbe_data_t *components; + + princ = calloc(1, sizeof (krb5_principal_data)); + if (princ == NULL) { + return NULL; + } + princ->length = 0; + princ->data = NULL; + + components = kdbe_princ->k_components.k_components_val; + + princ->type = (krb5_int32) kdbe_princ->k_nametype; + princ->realm.data = NULL; + set_from_utf8str(&princ->realm, kdbe_princ->k_realm); + if (princ->realm.data == NULL) + goto error; + + princ->data = calloc(kdbe_princ->k_components.k_components_len, + sizeof (krb5_data)); + if (princ->data == NULL) + goto error; + for (i = 0; i < kdbe_princ->k_components.k_components_len; i++) + princ->data[i].data = NULL; + princ->length = (krb5_int32)kdbe_princ->k_components.k_components_len; + + for (j = 0; j < princ->length; j++) { + princ->data[j].magic = components[j].k_magic; + set_from_utf8str(&princ->data[j], components[j].k_data); + if (princ->data[j].data == NULL) + goto error; + } + + return princ; +error: + krb5_free_principal(context, princ); + return NULL; +} + + +/* + * This routine converts a krb5 DB record into update log (ulog) entry format. + * Space for the update log entry should be allocated prior to invocation of + * this routine. + */ +krb5_error_code +ulog_conv_2logentry(krb5_context context, krb5_db_entry *entry, + kdb_incr_update_t *update) +{ + int i, j, cnt, final, nattrs, tmpint; + krb5_principal tmpprinc; + krb5_tl_data *newtl; + krb5_db_entry *curr; + krb5_error_code ret; + kdbe_attr_type_t *attr_types; + int kadm_data_yes; + + nattrs = tmpint = 0; + final = -1; + kadm_data_yes = 0; + attr_types = NULL; + + /* + * XXX we rely on the good behaviour of the database not to + * exceed this limit. + */ + if ((update->kdb_update.kdbe_t_val = (kdbe_val_t *) + malloc(MAXENTRY_SIZE)) == NULL) { + return (ENOMEM); + } + + /* + * Find out which attrs have been modified + */ + if ((attr_types = (kdbe_attr_type_t *)malloc( + sizeof (kdbe_attr_type_t) * MAXATTRS_SIZE)) + == NULL) { + return (ENOMEM); + } + + ret = krb5_db_get_principal(context, entry->princ, 0, &curr); + if (ret && ret != KRB5_KDB_NOENTRY) { + free(attr_types); + return (ret); + } + + if (ret == KRB5_KDB_NOENTRY) { + /* + * This is a new entry to the database, hence will + * include all the attribute-value pairs + * + * We leave out the TL_DATA types which we model as + * attrs in kdbe_attr_type_t, since listing AT_TL_DATA + * encompasses these other types-turned-attributes + * + * So, we do *NOT* consider AT_MOD_PRINC, AT_MOD_TIME, + * AT_MOD_WHERE, AT_PW_LAST_CHANGE, AT_PW_POLICY, + * AT_PW_POLICY_SWITCH, AT_PW_HIST_KVNO and AT_PW_HIST, + * totalling 8 attrs. + */ + while (nattrs < MAXATTRS_SIZE - 8) { + attr_types[nattrs] = nattrs; + nattrs++; + } + } else { + /* Always exclude non-replicated attributes for now. */ + find_changed_attrs(curr, entry, TRUE, attr_types, &nattrs); + krb5_db_free_principal(context, curr); + } + + for (i = 0; i < nattrs; i++) { + switch (attr_types[i]) { + case AT_ATTRFLAGS: + if (entry->attributes >= 0) { + ULOG_ENTRY_TYPE(update, ++final).av_type = + AT_ATTRFLAGS; + ULOG_ENTRY(update, final).av_attrflags = + (uint32_t)entry->attributes; + } + break; + + case AT_MAX_LIFE: + if (entry->max_life >= 0) { + ULOG_ENTRY_TYPE(update, ++final).av_type = AT_MAX_LIFE; + ULOG_ENTRY(update, final).av_max_life = + (uint32_t)entry->max_life; + } + break; + + case AT_MAX_RENEW_LIFE: + if (entry->max_renewable_life >= 0) { + ULOG_ENTRY_TYPE(update, ++final).av_type = AT_MAX_RENEW_LIFE; + ULOG_ENTRY(update, final).av_max_renew_life = + (uint32_t)entry->max_renewable_life; + } + break; + + case AT_EXP: + if (entry->expiration >= 0) { + ULOG_ENTRY_TYPE(update, ++final).av_type = AT_EXP; + ULOG_ENTRY(update, final).av_exp = (uint32_t)entry->expiration; + } + break; + + case AT_PW_EXP: + if (entry->pw_expiration >= 0) { + ULOG_ENTRY_TYPE(update, ++final).av_type = AT_PW_EXP; + ULOG_ENTRY(update, final).av_pw_exp = + (uint32_t)entry->pw_expiration; + } + break; + + case AT_PRINC: + if (entry->princ->length > 0) { + ULOG_ENTRY_TYPE(update, ++final).av_type = AT_PRINC; + if ((ret = conv_princ_2ulog(entry->princ, + update, final, REG_PRINC))) { + free(attr_types); + return (ret); + } + } + break; + + case AT_KEYDATA: +/* BEGIN CSTYLED */ + if (entry->n_key_data >= 0) { + ULOG_ENTRY_TYPE(update, ++final).av_type = AT_KEYDATA; + ULOG_ENTRY(update, final).av_keydata.av_keydata_len = + entry->n_key_data; + ULOG_ENTRY(update, final).av_keydata.av_keydata_val = + malloc(entry->n_key_data * sizeof (kdbe_key_t)); + if (ULOG_ENTRY(update, final).av_keydata.av_keydata_val == + NULL) { + free(attr_types); + return (ENOMEM); + } + + for (j = 0; j < entry->n_key_data; j++) { + ULOG_ENTRY_KEYVAL(update, final, j).k_ver = + entry->key_data[j].key_data_ver; + ULOG_ENTRY_KEYVAL(update, final, j).k_kvno = + entry->key_data[j].key_data_kvno; + ULOG_ENTRY_KEYVAL(update, final, j).k_enctype.k_enctype_len = entry->key_data[j].key_data_ver; + ULOG_ENTRY_KEYVAL(update, final, j).k_contents.k_contents_len = entry->key_data[j].key_data_ver; + + ULOG_ENTRY_KEYVAL(update, final, j).k_enctype.k_enctype_val = malloc(entry->key_data[j].key_data_ver * sizeof(int32_t)); + if (ULOG_ENTRY_KEYVAL(update, final, j).k_enctype.k_enctype_val == NULL) { + free(attr_types); + return (ENOMEM); + } + + ULOG_ENTRY_KEYVAL(update, final, j).k_contents.k_contents_val = malloc(entry->key_data[j].key_data_ver * sizeof(utf8str_t)); + if (ULOG_ENTRY_KEYVAL(update, final, j).k_contents.k_contents_val == NULL) { + free(attr_types); + return (ENOMEM); + } + + for (cnt = 0; cnt < entry->key_data[j].key_data_ver; + cnt++) { + ULOG_ENTRY_KEYVAL(update, final, j).k_enctype.k_enctype_val[cnt] = entry->key_data[j].key_data_type[cnt]; + ULOG_ENTRY_KEYVAL(update, final, j).k_contents.k_contents_val[cnt].utf8str_t_len = entry->key_data[j].key_data_length[cnt]; + ULOG_ENTRY_KEYVAL(update, final, j).k_contents.k_contents_val[cnt].utf8str_t_val = malloc(entry->key_data[j].key_data_length[cnt] * sizeof (char)); + if (ULOG_ENTRY_KEYVAL(update, final, j).k_contents.k_contents_val[cnt].utf8str_t_val == NULL) { + free(attr_types); + return (ENOMEM); + } + (void) memcpy(ULOG_ENTRY_KEYVAL(update, final, j).k_contents.k_contents_val[cnt].utf8str_t_val, entry->key_data[j].key_data_contents[cnt], entry->key_data[j].key_data_length[cnt]); + } + } + } + break; + + case AT_TL_DATA: + ret = krb5_dbe_lookup_last_pwd_change(context, entry, &tmpint); + if (ret == 0) { + ULOG_ENTRY_TYPE(update, ++final).av_type = AT_PW_LAST_CHANGE; + ULOG_ENTRY(update, final).av_pw_last_change = tmpint; + } + tmpint = 0; + + if(!(ret = krb5_dbe_lookup_mod_princ_data(context, entry, &tmpint, + &tmpprinc))) { + + ULOG_ENTRY_TYPE(update, ++final).av_type = AT_MOD_PRINC; + + ret = conv_princ_2ulog(tmpprinc, update, final, MOD_PRINC); + krb5_free_principal(context, tmpprinc); + if (ret) { + free(attr_types); + return (ret); + } + ULOG_ENTRY_TYPE(update, ++final).av_type = AT_MOD_TIME; + ULOG_ENTRY(update, final).av_mod_time = + tmpint; + } + + newtl = entry->tl_data; + while (newtl) { + switch (newtl->tl_data_type) { + case KRB5_TL_LAST_PWD_CHANGE: + case KRB5_TL_MOD_PRINC: + break; + + case KRB5_TL_KADM_DATA: + default: + if (kadm_data_yes == 0) { + ULOG_ENTRY_TYPE(update, ++final).av_type = AT_TL_DATA; + ULOG_ENTRY(update, final).av_tldata.av_tldata_len = 0; + ULOG_ENTRY(update, final).av_tldata.av_tldata_val = + malloc(entry->n_tl_data * sizeof(kdbe_tl_t)); + + if (ULOG_ENTRY(update, final).av_tldata.av_tldata_val + == NULL) { + free(attr_types); + return (ENOMEM); + } + kadm_data_yes = 1; + } + + tmpint = ULOG_ENTRY(update, final).av_tldata.av_tldata_len; + ULOG_ENTRY(update, final).av_tldata.av_tldata_len++; + ULOG_ENTRY(update, final).av_tldata.av_tldata_val[tmpint].tl_type = newtl->tl_data_type; + ULOG_ENTRY(update, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_len = newtl->tl_data_length; + ULOG_ENTRY(update, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_val = malloc(newtl->tl_data_length * sizeof (char)); + if (ULOG_ENTRY(update, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_val == NULL) { + free(attr_types); + return (ENOMEM); + } + (void) memcpy(ULOG_ENTRY(update, final).av_tldata.av_tldata_val[tmpint].tl_data.tl_data_val, newtl->tl_data_contents, newtl->tl_data_length); + break; + } + newtl = newtl->tl_data_next; + } + break; +/* END CSTYLED */ + + case AT_LEN: + ULOG_ENTRY_TYPE(update, ++final).av_type = AT_LEN; + ULOG_ENTRY(update, final).av_len = (int16_t)entry->len; + break; + + default: + break; + } + + } + + free(attr_types); + + /* + * Update len field in kdb_update + */ + update->kdb_update.kdbe_t_len = ++final; + return (0); +} + +/* Convert an update log (ulog) entry into a kerberos record. */ +krb5_error_code +ulog_conv_2dbentry(krb5_context context, krb5_db_entry **entry, + kdb_incr_update_t *update) +{ + krb5_db_entry *ent = NULL; + int replica; + krb5_principal mod_princ = NULL; + int i, j, cnt = 0, mod_time = 0, nattrs; + krb5_principal dbprinc; + char *dbprincstr = NULL; + krb5_tl_data newtl; + krb5_error_code ret; + unsigned int prev_n_keys = 0; + krb5_boolean is_add; + void *newptr; + + *entry = NULL; + + replica = (context->kdblog_context != NULL) && + (context->kdblog_context->iproprole == IPROP_REPLICA); + + /* + * Store the no. of changed attributes in nattrs + */ + nattrs = update->kdb_update.kdbe_t_len; + + dbprincstr = k5memdup0(update->kdb_princ_name.utf8str_t_val, + update->kdb_princ_name.utf8str_t_len, &ret); + if (dbprincstr == NULL) + goto cleanup; + + ret = krb5_parse_name(context, dbprincstr, &dbprinc); + free(dbprincstr); + if (ret) + goto cleanup; + + ret = krb5_db_get_principal(context, dbprinc, 0, &ent); + krb5_free_principal(context, dbprinc); + if (ret && ret != KRB5_KDB_NOENTRY) + goto cleanup; + is_add = (ret == KRB5_KDB_NOENTRY); + + /* + * Set ent->n_tl_data = 0 initially, if this is an ADD update + */ + if (is_add) { + ent = calloc(1, sizeof(*ent)); + if (ent == NULL) + return (ENOMEM); + ent->n_tl_data = 0; + } + + for (i = 0; i < nattrs; i++) { + krb5_principal tmpprinc = NULL; + +#define u (ULOG_ENTRY(update, i)) + switch (ULOG_ENTRY_TYPE(update, i).av_type) { + case AT_ATTRFLAGS: + ent->attributes = (krb5_flags) u.av_attrflags; + break; + + case AT_MAX_LIFE: + ent->max_life = (krb5_deltat) u.av_max_life; + break; + + case AT_MAX_RENEW_LIFE: + ent->max_renewable_life = (krb5_deltat) u.av_max_renew_life; + break; + + case AT_EXP: + ent->expiration = (krb5_timestamp) u.av_exp; + break; + + case AT_PW_EXP: + ent->pw_expiration = (krb5_timestamp) u.av_pw_exp; + break; + + case AT_LAST_SUCCESS: + if (!replica) + ent->last_success = (krb5_timestamp) u.av_last_success; + break; + + case AT_LAST_FAILED: + if (!replica) + ent->last_failed = (krb5_timestamp) u.av_last_failed; + break; + + case AT_FAIL_AUTH_COUNT: + if (!replica) + ent->fail_auth_count = (krb5_kvno) u.av_fail_auth_count; + break; + + case AT_PRINC: + tmpprinc = conv_princ_2db(context, &u.av_princ); + if (tmpprinc == NULL) { + ret = ENOMEM; + goto cleanup; + } + krb5_free_principal(context, ent->princ); + ent->princ = tmpprinc; + break; + + case AT_KEYDATA: + if (!is_add) + prev_n_keys = ent->n_key_data; + else + prev_n_keys = 0; + ent->n_key_data = (krb5_int16)u.av_keydata.av_keydata_len; + if (is_add) + ent->key_data = NULL; + + /* Allocate one extra key data to avoid allocating zero bytes. */ + newptr = realloc(ent->key_data, (ent->n_key_data + 1) * + sizeof(krb5_key_data)); + if (newptr == NULL) { + ret = ENOMEM; + goto cleanup; + } + ent->key_data = newptr; + +/* BEGIN CSTYLED */ + for (j = prev_n_keys; j < ent->n_key_data; j++) { + for (cnt = 0; cnt < 2; cnt++) { + ent->key_data[j].key_data_contents[cnt] = NULL; + } + } + for (j = 0; j < ent->n_key_data; j++) { + krb5_key_data *kp = &ent->key_data[j]; + kdbe_key_t *kv = &ULOG_ENTRY_KEYVAL(update, i, j); + kp->key_data_ver = (krb5_int16)kv->k_ver; + kp->key_data_kvno = (krb5_ui_2)kv->k_kvno; + if (kp->key_data_ver > 2) { + ret = EINVAL; /* XXX ? */ + goto cleanup; + } + + for (cnt = 0; cnt < kp->key_data_ver; cnt++) { + kp->key_data_type[cnt] = (krb5_int16)kv->k_enctype.k_enctype_val[cnt]; + kp->key_data_length[cnt] = (krb5_int16)kv->k_contents.k_contents_val[cnt].utf8str_t_len; + newptr = realloc(kp->key_data_contents[cnt], + kp->key_data_length[cnt]); + if (newptr == NULL) { + ret = ENOMEM; + goto cleanup; + } + kp->key_data_contents[cnt] = newptr; + + (void) memset(kp->key_data_contents[cnt], 0, + kp->key_data_length[cnt]); + (void) memcpy(kp->key_data_contents[cnt], + kv->k_contents.k_contents_val[cnt].utf8str_t_val, + kp->key_data_length[cnt]); + } + } + break; + + case AT_TL_DATA: { + for (j = 0; j < (int)u.av_tldata.av_tldata_len; j++) { + newtl.tl_data_type = (krb5_int16)u.av_tldata.av_tldata_val[j].tl_type; + newtl.tl_data_length = (krb5_int16)u.av_tldata.av_tldata_val[j].tl_data.tl_data_len; + newtl.tl_data_contents = (krb5_octet *)u.av_tldata.av_tldata_val[j].tl_data.tl_data_val; + newtl.tl_data_next = NULL; + ret = krb5_dbe_update_tl_data(context, ent, &newtl); + if (ret) + goto cleanup; + } + break; +/* END CSTYLED */ + } + case AT_PW_LAST_CHANGE: + ret = krb5_dbe_update_last_pwd_change(context, ent, + u.av_pw_last_change); + if (ret) + goto cleanup; + break; + + case AT_MOD_PRINC: + tmpprinc = conv_princ_2db(context, &u.av_mod_princ); + if (tmpprinc == NULL) { + ret = ENOMEM; + goto cleanup; + } + mod_princ = tmpprinc; + break; + + case AT_MOD_TIME: + mod_time = u.av_mod_time; + break; + + case AT_LEN: + ent->len = (krb5_int16) u.av_len; + break; + + default: + break; + } +#undef u + } + + /* + * process mod_princ_data request + */ + if (mod_time && mod_princ) { + ret = krb5_dbe_update_mod_princ_data(context, ent, + mod_time, mod_princ); + if (ret) + goto cleanup; + } + + *entry = ent; + ent = NULL; + ret = 0; +cleanup: + krb5_db_free_principal(context, ent); + krb5_free_principal(context, mod_princ); + return ret; +} + + + +/* + * This routine frees up memory associated with the bunched ulog entries. + */ +void +ulog_free_entries(kdb_incr_update_t *updates, int no_of_updates) +{ + + kdb_incr_update_t *upd; + unsigned int i, j; + int k, cnt; + + if (updates == NULL) + return; + + upd = updates; + + /* + * Loop thru each ulog entry + */ + for (cnt = 0; cnt < no_of_updates; cnt++) { + + /* + * ulog entry - kdb_princ_name + */ + free(upd->kdb_princ_name.utf8str_t_val); + +/* BEGIN CSTYLED */ + + /* + * ulog entry - kdb_kdcs_seen_by + */ + if (upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val) { + for (i = 0; i < upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_len; i++) + free(upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val[i].utf8str_t_val); + free(upd->kdb_kdcs_seen_by.kdb_kdcs_seen_by_val); + } + + /* + * ulog entry - kdb_futures + */ + free(upd->kdb_futures.kdb_futures_val); + + /* + * ulog entry - kdb_update + */ + if (upd->kdb_update.kdbe_t_val) { + /* + * Loop thru all the attributes and free up stuff + */ + for (i = 0; i < upd->kdb_update.kdbe_t_len; i++) { + + /* + * Free av_key_data + */ + if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_KEYDATA) && ULOG_ENTRY(upd, i).av_keydata.av_keydata_val) { + + for (j = 0; j < ULOG_ENTRY(upd, i).av_keydata.av_keydata_len; j++) { + free(ULOG_ENTRY_KEYVAL(upd, i, j).k_enctype.k_enctype_val); + if (ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val) { + for (k = 0; k < ULOG_ENTRY_KEYVAL(upd, i, j).k_ver; k++) { + free(ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val[k].utf8str_t_val); + } + free(ULOG_ENTRY_KEYVAL(upd, i, j).k_contents.k_contents_val); + } + } + free(ULOG_ENTRY(upd, i).av_keydata.av_keydata_val); + } + + + /* + * Free av_tl_data + */ + if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_TL_DATA) && ULOG_ENTRY(upd, i).av_tldata.av_tldata_val) { + for (j = 0; j < ULOG_ENTRY(upd, i).av_tldata.av_tldata_len; j++) { + free(ULOG_ENTRY(upd, i).av_tldata.av_tldata_val[j].tl_data.tl_data_val); + } + free(ULOG_ENTRY(upd, i).av_tldata.av_tldata_val); + } + + /* + * Free av_princ + */ + if (ULOG_ENTRY_TYPE(upd, i).av_type == AT_PRINC) { + free(ULOG_ENTRY(upd, i).av_princ.k_realm.utf8str_t_val); + if (ULOG_ENTRY(upd, i).av_princ.k_components.k_components_val) { + for (j = 0; j < ULOG_ENTRY(upd, i).av_princ.k_components.k_components_len; j++) { + free(ULOG_ENTRY_PRINC(upd, i, j).k_data.utf8str_t_val); + } + free(ULOG_ENTRY(upd, i).av_princ.k_components.k_components_val); + } + } + + /* + * Free av_mod_princ + */ + if (ULOG_ENTRY_TYPE(upd, i).av_type == AT_MOD_PRINC) { + free(ULOG_ENTRY(upd, i).av_mod_princ.k_realm.utf8str_t_val); + if (ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_val) { + for (j = 0; j < ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_len; j++) { + free(ULOG_ENTRY_MOD_PRINC(upd, i, j).k_data.utf8str_t_val); + } + free(ULOG_ENTRY(upd, i).av_mod_princ.k_components.k_components_val); + } + } + + /* + * Free av_mod_where + */ + if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_MOD_WHERE) && ULOG_ENTRY(upd, i).av_mod_where.utf8str_t_val) + free(ULOG_ENTRY(upd, i).av_mod_where.utf8str_t_val); + + /* + * Free av_pw_policy + */ + if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_PW_POLICY) && ULOG_ENTRY(upd, i).av_pw_policy.utf8str_t_val) + free(ULOG_ENTRY(upd, i).av_pw_policy.utf8str_t_val); + + /* + * XXX: Free av_pw_hist + * + * For now, we just free the pointer + * to av_pw_hist_val, since we aren't + * populating this union member in + * the conv api function(s) anyways. + */ + if ((ULOG_ENTRY_TYPE(upd, i).av_type == AT_PW_HIST) && ULOG_ENTRY(upd, i).av_pw_hist.av_pw_hist_val) + free(ULOG_ENTRY(upd, i).av_pw_hist.av_pw_hist_val); + + } + + /* + * Free up the pointer to kdbe_t_val + */ + free(upd->kdb_update.kdbe_t_val); + } + +/* END CSTYLED */ + + /* + * Bump up to next struct + */ + upd++; + } + + + /* + * Finally, free up the pointer to the bunched ulog entries + */ + free(updates); +} diff --git a/krb5-1.21.3/src/lib/kdb/kdb_cpw.c b/krb5-1.21.3/src/lib/kdb/kdb_cpw.c new file mode 100644 index 00000000..450860f4 --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/kdb_cpw.c @@ -0,0 +1,462 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kdb/kdb_cpw.c */ +/* + * Copyright 1995, 2009, 2014 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" +#include "kdb.h" +#include +#include + +enum save { DISCARD_ALL, KEEP_LAST_KVNO, KEEP_ALL }; + +int +krb5_db_get_key_data_kvno(context, count, data) + krb5_context context; + int count; + krb5_key_data * data; +{ + int i, kvno; + /* Find last key version number */ + for (kvno = i = 0; i < count; i++) { + if (kvno < data[i].key_data_kvno) { + kvno = data[i].key_data_kvno; + } + } + return(kvno); +} + +static void +cleanup_key_data(context, count, data) + krb5_context context; + int count; + krb5_key_data * data; +{ + int i; + + /* If data is NULL, count is always 0 */ + if (data == NULL) return; + + for (i = 0; i < count; i++) + krb5_dbe_free_key_data_contents(context, &data[i]); + free(data); +} + +/* Transfer key data from old_kd to new_kd, making sure that new_kd is + * encrypted with mkey. May steal from old_kd and zero it out. */ +static krb5_error_code +preserve_one_old_key(krb5_context context, krb5_keyblock *mkey, + krb5_db_entry *dbent, krb5_key_data *old_kd, + krb5_key_data *new_kd) +{ + krb5_error_code ret; + krb5_keyblock kb; + krb5_keysalt salt; + + memset(new_kd, 0, sizeof(*new_kd)); + + ret = krb5_dbe_decrypt_key_data(context, mkey, old_kd, &kb, NULL); + if (ret == 0) { + /* old_kd is already encrypted in mkey, so just move it. */ + *new_kd = *old_kd; + memset(old_kd, 0, sizeof(*old_kd)); + krb5_free_keyblock_contents(context, &kb); + return 0; + } + + /* Decrypt and re-encrypt old_kd using mkey. */ + ret = krb5_dbe_decrypt_key_data(context, NULL, old_kd, &kb, &salt); + if (ret) + return ret; + ret = krb5_dbe_encrypt_key_data(context, mkey, &kb, &salt, + old_kd->key_data_kvno, new_kd); + krb5_free_keyblock_contents(context, &kb); + krb5_free_data_contents(context, &salt.data); + return ret; +} + +/* + * Add key_data to dbent, making sure that each entry is encrypted in mkey. If + * kvno is non-zero, preserve only keys of that kvno. May steal some elements + * from key_data and zero them out. + */ +static krb5_error_code +preserve_old_keys(krb5_context context, krb5_keyblock *mkey, + krb5_db_entry *dbent, int kvno, int n_key_data, + krb5_key_data *key_data) +{ + krb5_error_code ret; + int i; + + for (i = 0; i < n_key_data; i++) { + if (kvno != 0 && key_data[i].key_data_kvno != kvno) + continue; + ret = krb5_dbe_create_key_data(context, dbent); + if (ret) + return ret; + ret = preserve_one_old_key(context, mkey, dbent, &key_data[i], + &dbent->key_data[dbent->n_key_data - 1]); + if (ret) + return ret; + } + return 0; +} + +static krb5_error_code +add_key_rnd(context, master_key, ks_tuple, ks_tuple_count, db_entry, kvno) + krb5_context context; + krb5_keyblock * master_key; + krb5_key_salt_tuple * ks_tuple; + int ks_tuple_count; + krb5_db_entry * db_entry; + int kvno; +{ + krb5_keyblock key; + int i, j; + krb5_error_code retval; + krb5_key_data *kd_slot; + + for (i = 0; i < ks_tuple_count; i++) { + krb5_boolean similar; + + similar = 0; + + /* + * We could use krb5_keysalt_iterate to replace this loop, or use + * krb5_keysalt_is_present for the loop below, but we want to avoid + * circular library dependencies. + */ + for (j = 0; j < i; j++) { + if ((retval = krb5_c_enctype_compare(context, + ks_tuple[i].ks_enctype, + ks_tuple[j].ks_enctype, + &similar))) + return(retval); + + if (similar) + break; + } + + if (similar) + continue; + + if ((retval = krb5_dbe_create_key_data(context, db_entry))) + return retval; + kd_slot = &db_entry->key_data[db_entry->n_key_data - 1]; + + /* there used to be code here to extract the old key, and derive + a new key from it. Now that there's a unified prng, that isn't + necessary. */ + + /* make new key */ + if ((retval = krb5_c_make_random_key(context, ks_tuple[i].ks_enctype, + &key))) + return retval; + + retval = krb5_dbe_encrypt_key_data(context, master_key, &key, NULL, + kvno, kd_slot); + + krb5_free_keyblock_contents(context, &key); + if( retval ) + return retval; + } + + return 0; +} + +/* Construct a random explicit salt. */ +static krb5_error_code +make_random_salt(krb5_context context, krb5_keysalt *salt_out) +{ + krb5_error_code retval; + unsigned char rndbuf[8]; + krb5_data salt, rnd = make_data(rndbuf, sizeof(rndbuf)); + unsigned int i; + + /* + * Salts are limited by RFC 4120 to 7-bit ASCII. For ease of examination + * and to avoid certain folding issues for older enctypes, we use printable + * characters with four fixed bits and four random bits, encoding 64 + * psuedo-random bits into 16 bytes. + */ + retval = krb5_c_random_make_octets(context, &rnd); + if (retval) + return retval; + retval = alloc_data(&salt, sizeof(rndbuf) * 2); + if (retval) + return retval; + for (i = 0; i < sizeof(rndbuf); i++) { + salt.data[i * 2] = 0x40 | (rndbuf[i] >> 4); + salt.data[i * 2 + 1] = 0x40 | (rndbuf[i] & 0xf); + } + + salt_out->type = KRB5_KDB_SALTTYPE_SPECIAL; + salt_out->data = salt; + return 0; +} + +/* + * Add key_data for a krb5_db_entry + * If passwd is NULL the assumes that the caller wants a random password. + */ +static krb5_error_code +add_key_pwd(context, master_key, ks_tuple, ks_tuple_count, passwd, + db_entry, kvno) + krb5_context context; + krb5_keyblock * master_key; + krb5_key_salt_tuple * ks_tuple; + int ks_tuple_count; + const char * passwd; + krb5_db_entry * db_entry; + int kvno; +{ + krb5_error_code retval; + krb5_keysalt key_salt; + krb5_keyblock key; + krb5_data pwd; + int i, j; + krb5_key_data *kd_slot; + + for (i = 0; i < ks_tuple_count; i++) { + krb5_boolean similar; + + similar = 0; + + /* + * We could use krb5_keysalt_iterate to replace this loop, or use + * krb5_keysalt_is_present for the loop below, but we want to avoid + * circular library dependencies. + */ + for (j = 0; j < i; j++) { + if ((retval = krb5_c_enctype_compare(context, + ks_tuple[i].ks_enctype, + ks_tuple[j].ks_enctype, + &similar))) + return(retval); + + if (similar && + (ks_tuple[j].ks_salttype == ks_tuple[i].ks_salttype)) + break; + } + + if (j < i) + continue; + + if ((retval = krb5_dbe_create_key_data(context, db_entry))) + return(retval); + kd_slot = &db_entry->key_data[db_entry->n_key_data - 1]; + + /* Convert password string to key using appropriate salt */ + switch (key_salt.type = ks_tuple[i].ks_salttype) { + case KRB5_KDB_SALTTYPE_ONLYREALM: { + krb5_data * saltdata; + if ((retval = krb5_copy_data(context, krb5_princ_realm(context, + db_entry->princ), &saltdata))) + return(retval); + + key_salt.data = *saltdata; + free(saltdata); + } + break; + case KRB5_KDB_SALTTYPE_NOREALM: + if ((retval=krb5_principal2salt_norealm(context, db_entry->princ, + &key_salt.data))) + return(retval); + break; + case KRB5_KDB_SALTTYPE_NORMAL: + if ((retval = krb5_principal2salt(context, db_entry->princ, + &key_salt.data))) + return(retval); + break; + case KRB5_KDB_SALTTYPE_SPECIAL: + retval = make_random_salt(context, &key_salt); + if (retval) + return retval; + break; + default: + return(KRB5_KDB_BAD_SALTTYPE); + } + + pwd = string2data((char *)passwd); + + retval = krb5_c_string_to_key_with_params(context, + ks_tuple[i].ks_enctype, + &pwd, &key_salt.data, + NULL, &key); + if (retval) { + free(key_salt.data.data); + return retval; + } + + retval = krb5_dbe_encrypt_key_data(context, master_key, &key, + (const krb5_keysalt *)&key_salt, + kvno, kd_slot); + if (key_salt.data.data) + free(key_salt.data.data); + free(key.contents); + + if( retval ) + return retval; + } + + return 0; +} + +static krb5_error_code +rekey(krb5_context context, krb5_keyblock *mkey, krb5_key_salt_tuple *ks_tuple, + int ks_tuple_count, const char *password, int new_kvno, + enum save savekeys, krb5_db_entry *db_entry) +{ + krb5_error_code ret; + krb5_key_data *key_data; + int n_key_data, old_kvno, save_kvno; + + /* Save aside the old key data. */ + n_key_data = db_entry->n_key_data; + key_data = db_entry->key_data; + db_entry->n_key_data = 0; + db_entry->key_data = NULL; + + /* Make sure the new kvno is greater than the old largest kvno. */ + old_kvno = krb5_db_get_key_data_kvno(context, n_key_data, key_data); + if (new_kvno < old_kvno + 1) + new_kvno = old_kvno + 1; + /* Wrap from 65535 to 1; we can only store 16-bit kvno values in key_data, + * and we assign special meaning to kvno 0. */ + if (new_kvno == (1 << 16)) + new_kvno = 1; + + /* Add new keys to the front of the list. */ + if (password != NULL) { + ret = add_key_pwd(context, mkey, ks_tuple, ks_tuple_count, password, + db_entry, new_kvno); + } else { + ret = add_key_rnd(context, mkey, ks_tuple, ks_tuple_count, db_entry, + new_kvno); + } + if (ret) { + cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data); + db_entry->n_key_data = n_key_data; + db_entry->key_data = key_data; + return ret; + } + + /* Possibly add some or all of the old keys to the back of the list. May + * steal from and zero out some of the old key data entries. */ + if (savekeys != DISCARD_ALL) { + save_kvno = (savekeys == KEEP_LAST_KVNO) ? old_kvno : 0; + ret = preserve_old_keys(context, mkey, db_entry, save_kvno, n_key_data, + key_data); + } + + /* Free any old key data entries not stolen and zeroed out above. */ + cleanup_key_data(context, n_key_data, key_data); + return ret; +} + +/* + * Change random key for a krb5_db_entry + * Assumes the max kvno + * + * As a side effect all old keys are nuked if keepold is false. + */ +krb5_error_code +krb5_dbe_crk(krb5_context context, krb5_keyblock *mkey, + krb5_key_salt_tuple *ks_tuple, int ks_tuple_count, + krb5_boolean keepold, krb5_db_entry *dbent) +{ + return rekey(context, mkey, ks_tuple, ks_tuple_count, NULL, 0, + keepold ? KEEP_ALL : DISCARD_ALL, dbent); +} + +/* + * Add random key for a krb5_db_entry + * Assumes the max kvno + * + * As a side effect all old keys older than the max kvno are nuked. + */ +krb5_error_code +krb5_dbe_ark(krb5_context context, krb5_keyblock *mkey, + krb5_key_salt_tuple *ks_tuple, int ks_tuple_count, + krb5_db_entry *dbent) +{ + return rekey(context, mkey, ks_tuple, ks_tuple_count, NULL, 0, + KEEP_LAST_KVNO, dbent); +} + +/* + * Change password for a krb5_db_entry + * Assumes the max kvno + * + * As a side effect all old keys are nuked if keepold is false. + */ +krb5_error_code +krb5_dbe_def_cpw(krb5_context context, krb5_keyblock *mkey, + krb5_key_salt_tuple *ks_tuple, int ks_tuple_count, + char *password, int new_kvno, krb5_boolean keepold, + krb5_db_entry *dbent) +{ + return rekey(context, mkey, ks_tuple, ks_tuple_count, password, new_kvno, + keepold ? KEEP_ALL : DISCARD_ALL, dbent); +} + +/* + * Add password for a krb5_db_entry + * Assumes the max kvno + * + * As a side effect all old keys older than the max kvno are nuked. + */ +krb5_error_code +krb5_dbe_apw(krb5_context context, krb5_keyblock *mkey, + krb5_key_salt_tuple *ks_tuple, int ks_tuple_count, char *password, + krb5_db_entry *dbent) +{ + return rekey(context, mkey, ks_tuple, ks_tuple_count, password, 0, + KEEP_LAST_KVNO, dbent); +} diff --git a/krb5-1.21.3/src/lib/kdb/kdb_default.c b/krb5-1.21.3/src/lib/kdb/kdb_default.c new file mode 100644 index 00000000..526ddd26 --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/kdb_default.c @@ -0,0 +1,551 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kdb/kdb_default.c */ +/* + * Copyright 1995, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include "k5-int.h" +#include "kdb.h" +#include +#include +#include +#include + + +/* + * Set *kd_out to the key data entry matching kvno, enctype, and salttype. If + * any of those three parameters are -1, ignore them. If kvno is 0, match only + * the highest kvno. Begin searching at the index *start and set *start to the + * index after the match. Do not return keys of non-permitted enctypes; return + * KRB5_KDB_NO_PERMITTED_KEY if the whole list was searched and only + * non-permitted matches were found. + */ +krb5_error_code +krb5_dbe_def_search_enctype(krb5_context context, krb5_db_entry *ent, + krb5_int32 *start, krb5_int32 enctype, + krb5_int32 salttype, krb5_int32 kvno, + krb5_key_data **kd_out) +{ + krb5_key_data *kd; + krb5_int32 db_salttype; + krb5_boolean saw_non_permitted = FALSE; + int i; + + *kd_out = NULL; + + if (enctype != -1 && !krb5_is_permitted_enctype(context, enctype)) + return KRB5_KDB_NO_PERMITTED_KEY; + if (ent->n_key_data == 0) + return KRB5_KDB_NO_MATCHING_KEY; + + /* Match the highest kvno if kvno is 0. Key data is sorted in descending + * order of kvno. */ + if (kvno == 0) + kvno = ent->key_data[0].key_data_kvno; + + for (i = *start; i < ent->n_key_data; i++) { + kd = &ent->key_data[i]; + db_salttype = (kd->key_data_ver > 1) ? kd->key_data_type[1] : + KRB5_KDB_SALTTYPE_NORMAL; + + /* Match this entry against the arguments. Stop searching if we have + * passed the entries for the requested kvno. */ + if (enctype != -1 && kd->key_data_type[0] != enctype) + continue; + if (salttype >= 0 && db_salttype != salttype) + continue; + if (kvno >= 0 && kd->key_data_kvno < kvno) + break; + if (kvno >= 0 && kd->key_data_kvno != kvno) + continue; + + /* Filter out non-permitted enctypes. */ + if (!krb5_is_permitted_enctype(context, kd->key_data_type[0])) { + saw_non_permitted = TRUE; + continue; + } + + *start = i + 1; + *kd_out = kd; + return 0; + } + + /* If we scanned the whole set of keys and matched only non-permitted + * enctypes, indicate that. */ + return (*start == 0 && saw_non_permitted) ? KRB5_KDB_NO_PERMITTED_KEY : + KRB5_KDB_NO_MATCHING_KEY; +} + +/* + * kdb default functions. Ideally, some other file should have this functions. For now, TBD. + */ +#ifndef min +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +krb5_error_code +krb5_def_store_mkey_list(krb5_context context, + char *keyfile, + krb5_principal mname, + krb5_keylist_node *keylist, + char *master_pwd) +{ + krb5_error_code retval = 0; + char defkeyfile[MAXPATHLEN+1]; + char *tmp_ktname = NULL, *tmp_ktpath; + krb5_data *realm = krb5_princ_realm(context, mname); + krb5_keytab kt = NULL; + krb5_keytab_entry new_entry; + struct stat stb; + int statrc; + + if (!keyfile) { + (void) snprintf(defkeyfile, sizeof(defkeyfile), "%s%s", + DEFAULT_KEYFILE_STUB, realm->data); + keyfile = defkeyfile; + } + + if ((statrc = stat(keyfile, &stb)) >= 0) { + /* if keyfile exists it better be a regular file */ + if (!S_ISREG(stb.st_mode)) { + retval = EINVAL; + k5_setmsg(context, retval, + _("keyfile (%s) is not a regular file: %s"), + keyfile, error_message(retval)); + goto out; + } + } + + /* + * We assume the stash file is in a directory writable only by root. + * As such, don't worry about collisions, just do an atomic rename. + */ + retval = asprintf(&tmp_ktname, "FILE:%s_tmp", keyfile); + if (retval < 0) { + k5_setmsg(context, retval, + _("Could not create temp keytab file name.")); + goto out; + } + + /* + * Set tmp_ktpath to point to the keyfile path (skip FILE:). Subtracting + * 1 to account for NULL terminator in sizeof calculation of a string + * constant. Used further down. + */ + tmp_ktpath = tmp_ktname + (sizeof("FILE:") - 1); + + /* + * This time-of-check-to-time-of-access race is fine; we care only + * about an administrator running the command twice, not an attacker + * trying to beat us to creating the file. Per the above comment, we + * assume the stash file is in a directory writable only by root. + */ + statrc = stat(tmp_ktpath, &stb); + if (statrc == -1 && errno != ENOENT) { + /* ENOENT is the expected case */ + retval = errno; + goto out; + } else if (statrc == 0) { + retval = EEXIST; + k5_setmsg(context, retval, + _("Temporary stash file already exists: %s."), tmp_ktpath); + goto out; + } + + /* create new stash keytab using temp file name */ + retval = krb5_kt_resolve(context, tmp_ktname, &kt); + if (retval != 0) + goto out; + + while (keylist && !retval) { + memset(&new_entry, 0, sizeof(new_entry)); + new_entry.principal = mname; + new_entry.key = keylist->keyblock; + new_entry.vno = keylist->kvno; + + retval = krb5_kt_add_entry(context, kt, &new_entry); + keylist = keylist->next; + } + krb5_kt_close(context, kt); + + if (retval != 0) { + /* Clean up by deleting the tmp keyfile if it exists. */ + (void)unlink(tmp_ktpath); + } else { + /* Atomically rename temp keyfile to original filename. */ + if (rename(tmp_ktpath, keyfile) < 0) { + retval = errno; + k5_setmsg(context, retval, + _("rename of temporary keyfile (%s) to (%s) failed: %s"), + tmp_ktpath, keyfile, error_message(errno)); + } + } + +out: + if (tmp_ktname != NULL) + free(tmp_ktname); + + return retval; +} + +static krb5_error_code +krb5_db_def_fetch_mkey_stash(krb5_context context, + const char *keyfile, + krb5_keyblock *key, + krb5_kvno *kvno) +{ + krb5_error_code retval = 0; + krb5_ui_2 enctype; + krb5_ui_4 keylength; + FILE *kf = NULL; + + if (!(kf = fopen(keyfile, "rb"))) + return KRB5_KDB_CANTREAD_STORED; + set_cloexec_file(kf); + + if (fread((krb5_pointer) &enctype, 2, 1, kf) != 1) { + retval = KRB5_KDB_CANTREAD_STORED; + goto errout; + } + +#if BIG_ENDIAN_MASTER_KEY + enctype = ntohs((uint16_t) enctype); +#endif + + if (key->enctype == ENCTYPE_UNKNOWN) + key->enctype = enctype; + else if (enctype != key->enctype) { + retval = KRB5_KDB_BADSTORED_MKEY; + goto errout; + } + + if (fread((krb5_pointer) &keylength, + sizeof(keylength), 1, kf) != 1) { + retval = KRB5_KDB_CANTREAD_STORED; + goto errout; + } + +#if BIG_ENDIAN_MASTER_KEY + key->length = ntohl((uint32_t) keylength); +#else + key->length = keylength; +#endif + + if (!key->length || key->length > 1024) { + retval = KRB5_KDB_BADSTORED_MKEY; + goto errout; + } + + if (!(key->contents = (krb5_octet *)malloc(key->length))) { + retval = ENOMEM; + goto errout; + } + + if (fread((krb5_pointer) key->contents, sizeof(key->contents[0]), + key->length, kf) != key->length) { + retval = KRB5_KDB_CANTREAD_STORED; + zap(key->contents, key->length); + free(key->contents); + key->contents = 0; + } else + retval = 0; + + /* + * Note, the old stash format did not store the kvno and at this point it + * can be assumed to be 1 as is the case for the mkey princ. If the kvno is + * passed in and isn't ignore_vno just leave it alone as this could cause + * verifcation trouble if the mkey princ is using a kvno other than 1. + */ + if (kvno && *kvno == IGNORE_VNO) + *kvno = 1; + +errout: + (void) fclose(kf); + return retval; +} + +static krb5_error_code +krb5_db_def_fetch_mkey_keytab(krb5_context context, + const char *keyfile, + krb5_principal mname, + krb5_keyblock *key, + krb5_kvno *kvno) +{ + krb5_error_code retval = 0; + krb5_keytab kt = NULL; + krb5_keytab_entry kt_ent; + krb5_enctype enctype = IGNORE_ENCTYPE; + + if ((retval = krb5_kt_resolve(context, keyfile, &kt)) != 0) + goto errout; + + /* override default */ + if (key->enctype != ENCTYPE_UNKNOWN) + enctype = key->enctype; + + if ((retval = krb5_kt_get_entry(context, kt, mname, + kvno ? *kvno : IGNORE_VNO, + enctype, + &kt_ent)) == 0) { + + if (key->enctype == ENCTYPE_UNKNOWN) + key->enctype = kt_ent.key.enctype; + + if (((int) kt_ent.key.length) < 0) { + retval = KRB5_KDB_BADSTORED_MKEY; + krb5_kt_free_entry(context, &kt_ent); + goto errout; + } + + key->length = kt_ent.key.length; + + /* + * If a kvno pointer was passed in and it dereferences the + * IGNORE_VNO value then it should be assigned the value of the kvno + * found in the keytab otherwise the KNVO specified should be the + * same as the one returned from the keytab. + */ + if (kvno != NULL && *kvno == IGNORE_VNO) + *kvno = kt_ent.vno; + + /* + * kt_ent will be free'd so need to allocate and copy key contents for + * output to caller. + */ + key->contents = k5memdup(kt_ent.key.contents, kt_ent.key.length, + &retval); + if (key->contents == NULL) { + krb5_kt_free_entry(context, &kt_ent); + goto errout; + } + krb5_kt_free_entry(context, &kt_ent); + } + +errout: + if (kt) + krb5_kt_close(context, kt); + + return retval; +} + +krb5_error_code +krb5_db_def_fetch_mkey(krb5_context context, + krb5_principal mname, + krb5_keyblock *key, + krb5_kvno *kvno, + char *db_args) +{ + krb5_error_code retval; + char keyfile[MAXPATHLEN+1]; + krb5_data *realm = krb5_princ_realm(context, mname); + + key->magic = KV5M_KEYBLOCK; + + if (db_args != NULL) { + (void) strncpy(keyfile, db_args, sizeof(keyfile)); + } else { + (void) snprintf(keyfile, sizeof(keyfile), "%s%s", + DEFAULT_KEYFILE_STUB, realm->data); + } + /* null terminate no matter what */ + keyfile[sizeof(keyfile) - 1] = '\0'; + + /* Try the keytab and old stash file formats. */ + retval = krb5_db_def_fetch_mkey_keytab(context, keyfile, mname, key, kvno); + if (retval == KRB5_KEYTAB_BADVNO) + retval = krb5_db_def_fetch_mkey_stash(context, keyfile, key, kvno); + + /* + * Use a generic error code for failure to retrieve the master + * key, but set a message indicating the actual error. + */ + if (retval != 0) { + k5_setmsg(context, KRB5_KDB_CANTREAD_STORED, + _("Can not fetch master key (error: %s)."), + error_message(retval)); + return KRB5_KDB_CANTREAD_STORED; + } else + return 0; +} + +krb5_error_code +krb5_def_fetch_mkey_list(krb5_context context, + krb5_principal mprinc, + const krb5_keyblock *mkey, + krb5_keylist_node **mkeys_list) +{ + krb5_error_code retval; + krb5_db_entry *master_entry; + krb5_boolean found_key = FALSE; + krb5_keyblock cur_mkey; + krb5_keylist_node *mkey_list_head = NULL, **mkey_list_node; + krb5_key_data *key_data; + krb5_mkey_aux_node *mkey_aux_data_list = NULL, *aux_data_entry; + int i; + + if (mkeys_list == NULL) + return (EINVAL); + + memset(&cur_mkey, 0, sizeof(cur_mkey)); + + retval = krb5_db_get_principal(context, mprinc, 0, &master_entry); + if (retval == KRB5_KDB_NOENTRY) + return (KRB5_KDB_NOMASTERKEY); + if (retval) + return (retval); + + if (master_entry->n_key_data == 0) { + retval = KRB5_KDB_NOMASTERKEY; + goto clean_n_exit; + } + + /* + * Check if the input mkey is the latest key and if it isn't then find the + * latest mkey. + */ + + if (mkey->enctype == master_entry->key_data[0].key_data_type[0]) { + if (krb5_dbe_decrypt_key_data(context, mkey, + &master_entry->key_data[0], + &cur_mkey, NULL) == 0) { + found_key = TRUE; + } + } + + if (!found_key) { + if ((retval = krb5_dbe_lookup_mkey_aux(context, master_entry, + &mkey_aux_data_list))) + goto clean_n_exit; + + for (aux_data_entry = mkey_aux_data_list; aux_data_entry != NULL; + aux_data_entry = aux_data_entry->next) { + + if (krb5_dbe_decrypt_key_data(context, mkey, + &aux_data_entry->latest_mkey, + &cur_mkey, NULL) == 0) { + found_key = TRUE; + break; + } + } + if (found_key != TRUE) { + k5_setmsg(context, KRB5_KDB_BADMASTERKEY, + _("Unable to decrypt latest master key with the " + "provided master key\n")); + retval = KRB5_KDB_BADMASTERKEY; + goto clean_n_exit; + } + } + + /* + * Extract all the mkeys from master_entry using the most current mkey and + * create a mkey list for the mkeys field in kdc_realm_t. + */ + + mkey_list_head = (krb5_keylist_node *) malloc(sizeof(krb5_keylist_node)); + if (mkey_list_head == NULL) { + retval = ENOMEM; + goto clean_n_exit; + } + + memset(mkey_list_head, 0, sizeof(krb5_keylist_node)); + + /* Set mkey_list_head to the current mkey as an optimization. */ + /* mkvno may not be latest so ... */ + mkey_list_head->kvno = master_entry->key_data[0].key_data_kvno; + /* this is the latest clear mkey (avoids a redundant decrypt) */ + mkey_list_head->keyblock = cur_mkey; + + /* loop through any other master keys creating a list of krb5_keylist_nodes */ + mkey_list_node = &mkey_list_head->next; + for (i = 1; i < master_entry->n_key_data; i++) { + if (*mkey_list_node == NULL) { + /* *mkey_list_node points to next field of previous node */ + *mkey_list_node = (krb5_keylist_node *) malloc(sizeof(krb5_keylist_node)); + if (*mkey_list_node == NULL) { + retval = ENOMEM; + goto clean_n_exit; + } + memset(*mkey_list_node, 0, sizeof(krb5_keylist_node)); + } + key_data = &master_entry->key_data[i]; + retval = krb5_dbe_decrypt_key_data(context, &cur_mkey, key_data, + &((*mkey_list_node)->keyblock), + NULL); + if (retval) + goto clean_n_exit; + + (*mkey_list_node)->kvno = key_data->key_data_kvno; + mkey_list_node = &((*mkey_list_node)->next); + } + + *mkeys_list = mkey_list_head; + +clean_n_exit: + krb5_db_free_principal(context, master_entry); + krb5_dbe_free_mkey_aux_list(context, mkey_aux_data_list); + if (retval != 0) + krb5_dbe_free_key_list(context, mkey_list_head); + return retval; +} + +krb5_error_code +krb5_db_def_rename_principal(krb5_context kcontext, + krb5_const_principal source, + krb5_const_principal target) +{ + krb5_db_entry *kdb = NULL; + krb5_principal oldprinc; + krb5_error_code ret; + + if (source == NULL || target == NULL) + return EINVAL; + + ret = krb5_db_get_principal(kcontext, source, 0, &kdb); + if (ret) + goto cleanup; + + /* Store salt values explicitly so that they don't depend on the principal + * name. */ + ret = krb5_dbe_specialize_salt(kcontext, kdb); + if (ret) + goto cleanup; + + /* Temporarily alias kdb->princ to target and put the principal entry. */ + oldprinc = kdb->princ; + kdb->princ = (krb5_principal)target; + ret = krb5_db_put_principal(kcontext, kdb); + kdb->princ = oldprinc; + if (ret) + goto cleanup; + + ret = krb5_db_delete_principal(kcontext, (krb5_principal)source); + + +cleanup: + krb5_db_free_principal(kcontext, kdb); + return ret; +} diff --git a/krb5-1.21.3/src/lib/kdb/kdb_log.c b/krb5-1.21.3/src/lib/kdb/kdb_log.c new file mode 100644 index 00000000..2659a250 --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/kdb_log.c @@ -0,0 +1,688 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kdb5.h" +#include "kdb_log.h" +#include "kdb5int.h" + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +/* This module includes all the necessary functions that create and modify the + * Kerberos principal update and header logs. */ + +#define getpagesize() sysconf(_SC_PAGESIZE) + +static int pagesize = 0; + +#define INIT_ULOG(ctx) \ + log_ctx = ctx->kdblog_context; \ + assert(log_ctx != NULL); \ + ulog = log_ctx->ulog; \ + assert(ulog != NULL) + +/* Initialize context->kdblog_context if it does not yet exist, and return it. + * Return NULL on allocation failure. */ +static kdb_log_context * +create_log_context(krb5_context context) +{ + kdb_log_context *log_ctx; + + if (context->kdblog_context != NULL) + return context->kdblog_context; + log_ctx = calloc(1, sizeof(*log_ctx)); + if (log_ctx == NULL) + return NULL; + log_ctx->ulogfd = -1; + context->kdblog_context = log_ctx; + return log_ctx; +} + +static inline krb5_boolean +time_equal(const kdbe_time_t *a, const kdbe_time_t *b) +{ + return a->seconds == b->seconds && a->useconds == b->useconds; +} + +static void +time_current(kdbe_time_t *out) +{ + struct timeval timestamp; + + (void)gettimeofday(×tamp, NULL); + out->seconds = timestamp.tv_sec; + out->useconds = timestamp.tv_usec; +} + +/* Sync update entry to disk. */ +static void +sync_update(kdb_hlog_t *ulog, kdb_ent_header_t *upd) +{ + unsigned long start, end, size; + + if (!pagesize) + pagesize = getpagesize(); + + start = (unsigned long)upd & ~(pagesize - 1); + + end = ((unsigned long)upd + ulog->kdb_block + (pagesize - 1)) & + ~(pagesize - 1); + + size = end - start; + if (msync((caddr_t)start, size, MS_SYNC)) { + /* Couldn't sync to disk, let's panic. */ + syslog(LOG_ERR, _("could not sync ulog update to disk")); + abort(); + } +} + +/* Sync memory to disk for the update log header. */ +static void +sync_header(kdb_hlog_t *ulog) +{ + if (!pagesize) + pagesize = getpagesize(); + + if (msync((caddr_t)ulog, pagesize, MS_SYNC)) { + /* Couldn't sync to disk, let's panic. */ + syslog(LOG_ERR, _("could not sync ulog header to disk")); + abort(); + } +} + +/* Return true if the ulog entry for sno matches sno and timestamp. */ +static krb5_boolean +check_sno(kdb_log_context *log_ctx, kdb_sno_t sno, + const kdbe_time_t *timestamp) +{ + unsigned int indx = (sno - 1) % log_ctx->ulogentries; + kdb_ent_header_t *ent = INDEX(log_ctx->ulog, indx); + + return ent->kdb_entry_sno == sno && time_equal(&ent->kdb_time, timestamp); +} + +/* + * Check last against our ulog and determine whether it is up to date + * (UPDATE_NIL), so far out of date that a full dump is required + * (UPDATE_FULL_RESYNC_NEEDED), or okay to update with ulog entries + * (UPDATE_OK). + */ +static update_status_t +get_sno_status(kdb_log_context *log_ctx, const kdb_last_t *last) +{ + kdb_hlog_t *ulog = log_ctx->ulog; + + /* If last matches the ulog's last serial number and time exactly, it are + * up to date even if the ulog is empty. */ + if (last->last_sno == ulog->kdb_last_sno && + time_equal(&last->last_time, &ulog->kdb_last_time)) + return UPDATE_NIL; + + /* If our ulog is empty or does not contain last_sno, a full resync is + * required. */ + if (ulog->kdb_num == 0 || last->last_sno > ulog->kdb_last_sno || + last->last_sno < ulog->kdb_first_sno) + return UPDATE_FULL_RESYNC_NEEDED; + + /* If the timestamp in our ulog entry does not match last, then sno was + * reused and a full resync is required. */ + if (!check_sno(log_ctx, last->last_sno, &last->last_time)) + return UPDATE_FULL_RESYNC_NEEDED; + + /* last is not fully up to date, but can be updated using our ulog. */ + return UPDATE_OK; +} + +/* Extend update log file. */ +static krb5_error_code +extend_file_to(int fd, unsigned int new_size) +{ + off_t current_offset; + static const char zero[512]; + ssize_t wrote_size; + size_t write_size; + + current_offset = lseek(fd, 0, SEEK_END); + if (current_offset < 0) + return errno; + if (new_size > INT_MAX) + return EINVAL; + while (current_offset < (off_t)new_size) { + write_size = new_size - current_offset; + if (write_size > 512) + write_size = 512; + wrote_size = write(fd, zero, write_size); + if (wrote_size < 0) + return errno; + if (wrote_size == 0) + return EINVAL; + current_offset += wrote_size; + write_size = new_size - current_offset; + } + return 0; +} + +/* + * Resize the array elements. We reinitialize the update log rather than + * unrolling the the log and copying it over to a temporary log for obvious + * performance reasons. Replicas will subsequently do a full resync, but the + * need for resizing should be very small. + */ +static krb5_error_code +resize(kdb_hlog_t *ulog, uint32_t ulogentries, int ulogfd, + unsigned int recsize) +{ + unsigned int new_block, new_size; + + if (ulog == NULL) + return KRB5_LOG_ERROR; + + new_size = sizeof(kdb_hlog_t); + new_block = (recsize / ULOG_BLOCK) + 1; + new_block *= ULOG_BLOCK; + new_size += ulogentries * new_block; + + if (new_size > MAXLOGLEN) + return KRB5_LOG_ERROR; + + /* Reinit log with new block size. */ + memset(ulog, 0, sizeof(*ulog)); + ulog->kdb_hmagic = KDB_ULOG_HDR_MAGIC; + ulog->db_version_num = KDB_VERSION; + ulog->kdb_state = KDB_STABLE; + ulog->kdb_block = new_block; + sync_header(ulog); + + /* Expand log considering new block size. */ + return extend_file_to(ulogfd, new_size); +} + +/* Set the ulog to contain only a dummy entry with the given serial number and + * timestamp. */ +static void +set_dummy(kdb_log_context *log_ctx, kdb_sno_t sno, const kdbe_time_t *kdb_time) +{ + kdb_hlog_t *ulog = log_ctx->ulog; + kdb_ent_header_t *ent = INDEX(ulog, (sno - 1) % log_ctx->ulogentries); + + memset(ent, 0, sizeof(*ent)); + ent->kdb_umagic = KDB_ULOG_MAGIC; + ent->kdb_entry_sno = sno; + ent->kdb_time = *kdb_time; + sync_update(ulog, ent); + + ulog->kdb_num = 1; + ulog->kdb_first_sno = ulog->kdb_last_sno = sno; + ulog->kdb_first_time = ulog->kdb_last_time = *kdb_time; +} + +/* Reinitialize the ulog header, starting from sno 1 with the current time. */ +static void +reset_ulog(kdb_log_context *log_ctx) +{ + kdbe_time_t kdb_time; + kdb_hlog_t *ulog = log_ctx->ulog; + + memset(ulog, 0, sizeof(*ulog)); + ulog->kdb_hmagic = KDB_ULOG_HDR_MAGIC; + ulog->db_version_num = KDB_VERSION; + ulog->kdb_block = ULOG_BLOCK; + + /* Create a dummy entry to remember the timestamp for downstreams. */ + time_current(&kdb_time); + set_dummy(log_ctx, 1, &kdb_time); + ulog->kdb_state = KDB_STABLE; + sync_header(ulog); +} + +/* + * If any database operations will be invoked while the ulog lock is held, the + * caller must explicitly lock the database before locking the ulog, or + * deadlock may result. + */ +static krb5_error_code +lock_ulog(krb5_context context, int mode) +{ + kdb_log_context *log_ctx = NULL; + kdb_hlog_t *ulog = NULL; + + INIT_ULOG(context); + return krb5_lock_file(context, log_ctx->ulogfd, mode); +} + +static void +unlock_ulog(krb5_context context) +{ + (void)lock_ulog(context, KRB5_LOCKMODE_UNLOCK); +} + +/* + * Add an update to the log. The update's kdb_entry_sno and kdb_time fields + * must already be set. The layout of the update log looks like: + * + * header log -> [ update header -> xdr(kdb_incr_update_t) ], ... + */ +static krb5_error_code +store_update(kdb_log_context *log_ctx, kdb_incr_update_t *upd) +{ + XDR xdrs; + kdb_ent_header_t *indx_log; + unsigned int i, recsize; + unsigned long upd_size; + krb5_error_code retval; + kdb_hlog_t *ulog = log_ctx->ulog; + uint32_t ulogentries = log_ctx->ulogentries; + + upd_size = xdr_sizeof((xdrproc_t)xdr_kdb_incr_update_t, upd); + + recsize = sizeof(kdb_ent_header_t) + upd_size; + + if (recsize > ulog->kdb_block) { + retval = resize(ulog, ulogentries, log_ctx->ulogfd, recsize); + if (retval) + return retval; + } + + ulog->kdb_state = KDB_UNSTABLE; + + i = (upd->kdb_entry_sno - 1) % ulogentries; + indx_log = INDEX(ulog, i); + + memset(indx_log, 0, ulog->kdb_block); + indx_log->kdb_umagic = KDB_ULOG_MAGIC; + indx_log->kdb_entry_size = upd_size; + indx_log->kdb_entry_sno = upd->kdb_entry_sno; + indx_log->kdb_time = upd->kdb_time; + indx_log->kdb_commit = FALSE; + + xdrmem_create(&xdrs, (char *)indx_log->entry_data, + indx_log->kdb_entry_size, XDR_ENCODE); + if (!xdr_kdb_incr_update_t(&xdrs, upd)) + return KRB5_LOG_CONV; + + indx_log->kdb_commit = TRUE; + sync_update(ulog, indx_log); + + /* Modify the ulog header to reflect the new update. */ + ulog->kdb_last_sno = upd->kdb_entry_sno; + ulog->kdb_last_time = upd->kdb_time; + if (ulog->kdb_num == 0) { + /* We should only see this in old ulogs. */ + ulog->kdb_num = 1; + ulog->kdb_first_sno = upd->kdb_entry_sno; + ulog->kdb_first_time = upd->kdb_time; + } else if (ulog->kdb_num < ulogentries) { + ulog->kdb_num++; + } else { + /* We are circling; set kdb_first_sno and time to the next update. */ + i = upd->kdb_entry_sno % ulogentries; + indx_log = INDEX(ulog, i); + ulog->kdb_first_sno = indx_log->kdb_entry_sno; + ulog->kdb_first_time = indx_log->kdb_time; + } + + ulog->kdb_state = KDB_STABLE; + sync_header(ulog); + return 0; +} + +/* Add an entry to the update log. */ +krb5_error_code +ulog_add_update(krb5_context context, kdb_incr_update_t *upd) +{ + krb5_error_code ret; + kdb_log_context *log_ctx; + kdb_hlog_t *ulog; + + INIT_ULOG(context); + ret = lock_ulog(context, KRB5_LOCKMODE_EXCLUSIVE); + if (ret) + return ret; + + /* If we have reached the last possible serial number, reinitialize the + * ulog and start over. Replicas will do a full resync. */ + if (ulog->kdb_last_sno == (kdb_sno_t)-1) + reset_ulog(log_ctx); + + upd->kdb_entry_sno = ulog->kdb_last_sno + 1; + time_current(&upd->kdb_time); + ret = store_update(log_ctx, upd); + unlock_ulog(context); + return ret; +} + +/* Used by the replica to update its hash db from the incr update log. */ +krb5_error_code +ulog_replay(krb5_context context, kdb_incr_result_t *incr_ret, char **db_args) +{ + krb5_db_entry *entry = NULL; + kdb_incr_update_t *upd = NULL, *fupd; + int i, no_of_updates; + krb5_error_code retval; + krb5_principal dbprinc; + char *dbprincstr; + kdb_log_context *log_ctx; + kdb_hlog_t *ulog = NULL; + + INIT_ULOG(context); + + retval = krb5_db_open(context, db_args, + KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN); + if (retval) + return retval; + + no_of_updates = incr_ret->updates.kdb_ulog_t_len; + upd = incr_ret->updates.kdb_ulog_t_val; + fupd = upd; + + for (i = 0; i < no_of_updates; i++) { + if (!upd->kdb_commit) + continue; + + /* Replay this update in the database. */ + if (upd->kdb_deleted) { + dbprincstr = k5memdup0(upd->kdb_princ_name.utf8str_t_val, + upd->kdb_princ_name.utf8str_t_len, &retval); + if (dbprincstr == NULL) + goto cleanup; + + retval = krb5_parse_name(context, dbprincstr, &dbprinc); + free(dbprincstr); + if (retval) + goto cleanup; + + retval = krb5int_delete_principal_no_log(context, dbprinc); + krb5_free_principal(context, dbprinc); + if (retval == KRB5_KDB_NOENTRY) + retval = 0; + if (retval) + goto cleanup; + } else { + retval = ulog_conv_2dbentry(context, &entry, upd); + if (retval) + goto cleanup; + + retval = krb5int_put_principal_no_log(context, entry); + krb5_db_free_principal(context, entry); + if (retval) + goto cleanup; + } + + retval = lock_ulog(context, KRB5_LOCKMODE_EXCLUSIVE); + if (retval) + goto cleanup; + + /* If (unexpectedly) this update does not follow the last one we + * stored, discard any previous ulog state. */ + if (ulog->kdb_num != 0 && upd->kdb_entry_sno != ulog->kdb_last_sno + 1) + reset_ulog(log_ctx); + + /* Store this update in the ulog for any downstream KDCs. */ + retval = store_update(log_ctx, upd); + unlock_ulog(context); + if (retval) + goto cleanup; + + upd++; + } + +cleanup: + if (retval) + (void)ulog_init_header(context); + if (fupd) + ulog_free_entries(fupd, no_of_updates); + return retval; +} + +/* Reinitialize the log header. */ +krb5_error_code +ulog_init_header(krb5_context context) +{ + krb5_error_code ret; + kdb_log_context *log_ctx; + kdb_hlog_t *ulog; + + INIT_ULOG(context); + ret = lock_ulog(context, KRB5_LOCKMODE_EXCLUSIVE); + if (ret) + return ret; + reset_ulog(log_ctx); + unlock_ulog(context); + return 0; +} + +/* Map the log file to memory for performance and simplicity. */ +krb5_error_code +ulog_map(krb5_context context, const char *logname, uint32_t ulogentries) +{ + struct stat st; + krb5_error_code retval; + uint32_t filesize; + kdb_log_context *log_ctx; + kdb_hlog_t *ulog = NULL; + krb5_boolean locked = FALSE; + + log_ctx = create_log_context(context); + if (log_ctx == NULL) + return ENOMEM; + + if (stat(logname, &st) == -1) { + log_ctx->ulogfd = open(logname, O_RDWR | O_CREAT, 0600); + if (log_ctx->ulogfd == -1) { + retval = errno; + goto cleanup; + } + + filesize = sizeof(kdb_hlog_t) + ulogentries * ULOG_BLOCK; + retval = extend_file_to(log_ctx->ulogfd, filesize); + if (retval) + goto cleanup; + } else { + log_ctx->ulogfd = open(logname, O_RDWR, 0600); + if (log_ctx->ulogfd == -1) { + retval = errno; + goto cleanup; + } + } + + ulog = mmap(0, MAXLOGLEN, PROT_READ | PROT_WRITE, MAP_SHARED, + log_ctx->ulogfd, 0); + if (ulog == MAP_FAILED) { + retval = errno; + goto cleanup; + } + log_ctx->ulog = ulog; + log_ctx->ulogentries = ulogentries; + + retval = lock_ulog(context, KRB5_LOCKMODE_EXCLUSIVE); + if (retval) + goto cleanup; + locked = TRUE; + + if (ulog->kdb_hmagic != KDB_ULOG_HDR_MAGIC) { + if (ulog->kdb_hmagic != 0) { + retval = KRB5_LOG_CORRUPT; + goto cleanup; + } + reset_ulog(log_ctx); + } + + /* Reinit ulog if ulogentries changed such that we have too many entries or + * our first or last entry was written to the wrong location. */ + if (ulog->kdb_num != 0 && + (ulog->kdb_num > ulogentries || + !check_sno(log_ctx, ulog->kdb_first_sno, &ulog->kdb_first_time) || + !check_sno(log_ctx, ulog->kdb_last_sno, &ulog->kdb_last_time))) + reset_ulog(log_ctx); + + if (ulog->kdb_num != ulogentries) { + /* Expand the ulog file if it isn't big enough. */ + filesize = sizeof(kdb_hlog_t) + ulogentries * ulog->kdb_block; + retval = extend_file_to(log_ctx->ulogfd, filesize); + if (retval) + goto cleanup; + } + +cleanup: + if (locked) + unlock_ulog(context); + if (retval) + ulog_fini(context); + return retval; +} + +/* Get the last set of updates seen, (last+1) to n is returned. */ +krb5_error_code +ulog_get_entries(krb5_context context, const kdb_last_t *last, + kdb_incr_result_t *ulog_handle) +{ + XDR xdrs; + kdb_ent_header_t *indx_log; + kdb_incr_update_t *upd; + unsigned int indx, count; + uint32_t sno; + krb5_error_code retval; + kdb_log_context *log_ctx; + kdb_hlog_t *ulog = NULL; + uint32_t ulogentries; + + INIT_ULOG(context); + ulogentries = log_ctx->ulogentries; + + retval = lock_ulog(context, KRB5_LOCKMODE_SHARED); + if (retval) + return retval; + + /* If another process terminated mid-update, reset the ulog and force full + * resyncs. */ + if (ulog->kdb_state != KDB_STABLE) + reset_ulog(log_ctx); + + ulog_handle->ret = get_sno_status(log_ctx, last); + if (ulog_handle->ret != UPDATE_OK) + goto cleanup; + + sno = last->last_sno; + count = ulog->kdb_last_sno - sno; + upd = calloc(count, sizeof(kdb_incr_update_t)); + if (upd == NULL) { + ulog_handle->ret = UPDATE_ERROR; + retval = ENOMEM; + goto cleanup; + } + ulog_handle->updates.kdb_ulog_t_val = upd; + + for (; sno < ulog->kdb_last_sno; sno++) { + indx = sno % ulogentries; + indx_log = INDEX(ulog, indx); + + memset(upd, 0, sizeof(kdb_incr_update_t)); + xdrmem_create(&xdrs, (char *)indx_log->entry_data, + indx_log->kdb_entry_size, XDR_DECODE); + if (!xdr_kdb_incr_update_t(&xdrs, upd)) { + ulog_handle->ret = UPDATE_ERROR; + retval = KRB5_LOG_CONV; + goto cleanup; + } + + /* Mark commitment since we didn't want to decode and encode the incr + * update record the first time. */ + upd->kdb_commit = indx_log->kdb_commit; + upd++; + } + + ulog_handle->updates.kdb_ulog_t_len = count; + + ulog_handle->lastentry.last_sno = ulog->kdb_last_sno; + ulog_handle->lastentry.last_time.seconds = ulog->kdb_last_time.seconds; + ulog_handle->lastentry.last_time.useconds = ulog->kdb_last_time.useconds; + ulog_handle->ret = UPDATE_OK; + +cleanup: + unlock_ulog(context); + return retval; +} + +krb5_error_code +ulog_set_role(krb5_context ctx, iprop_role role) +{ + if (create_log_context(ctx) == NULL) + return ENOMEM; + ctx->kdblog_context->iproprole = role; + return 0; +} + +update_status_t +ulog_get_sno_status(krb5_context context, const kdb_last_t *last) +{ + update_status_t status; + + if (lock_ulog(context, KRB5_LOCKMODE_SHARED) != 0) + return UPDATE_ERROR; + status = get_sno_status(context->kdblog_context, last); + unlock_ulog(context); + return status; +} + +krb5_error_code +ulog_get_last(krb5_context context, kdb_last_t *last_out) +{ + krb5_error_code ret; + kdb_log_context *log_ctx; + kdb_hlog_t *ulog; + + INIT_ULOG(context); + ret = lock_ulog(context, KRB5_LOCKMODE_SHARED); + if (ret) + return ret; + last_out->last_sno = log_ctx->ulog->kdb_last_sno; + last_out->last_time = log_ctx->ulog->kdb_last_time; + unlock_ulog(context); + return 0; +} + +krb5_error_code +ulog_set_last(krb5_context context, const kdb_last_t *last) +{ + krb5_error_code ret; + kdb_log_context *log_ctx; + kdb_hlog_t *ulog; + + INIT_ULOG(context); + ret = lock_ulog(context, KRB5_LOCKMODE_EXCLUSIVE); + if (ret) + return ret; + + set_dummy(log_ctx, last->last_sno, &last->last_time); + sync_header(ulog); + unlock_ulog(context); + return 0; +} + +void +ulog_fini(krb5_context context) +{ + kdb_log_context *log_ctx = context->kdblog_context; + + if (log_ctx == NULL) + return; + if (log_ctx->ulog != NULL) + munmap(log_ctx->ulog, MAXLOGLEN); + if (log_ctx->ulogfd != -1) + close(log_ctx->ulogfd); + free(log_ctx); + context->kdblog_context = NULL; +} diff --git a/krb5-1.21.3/src/lib/kdb/keytab.c b/krb5-1.21.3/src/lib/kdb/keytab.c new file mode 100644 index 00000000..a623e001 --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/keytab.c @@ -0,0 +1,229 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kdb/keytab.c */ +/* + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include + +#include "k5-int.h" +#include "kdb_kt.h" + +static int +is_xrealm_tgt(krb5_context, krb5_const_principal); + +krb5_error_code krb5_ktkdb_close (krb5_context, krb5_keytab); + +krb5_error_code krb5_ktkdb_get_entry (krb5_context, krb5_keytab, krb5_const_principal, + krb5_kvno, krb5_enctype, krb5_keytab_entry *); + +static krb5_error_code +krb5_ktkdb_get_name(krb5_context context, krb5_keytab keytab, + char *name, unsigned int namelen) +{ + if (strlcpy(name, "KDB:", namelen) >= namelen) + return KRB5_KT_NAME_TOOLONG; + return 0; +} + +krb5_kt_ops krb5_kt_kdb_ops = { + 0, + "KDB", /* Prefix -- this string should not appear anywhere else! */ + krb5_ktkdb_resolve, /* resolve */ + krb5_ktkdb_get_name, /* get_name */ + krb5_ktkdb_close, /* close */ + krb5_ktkdb_get_entry, /* get */ + NULL, /* start_seq_get */ + NULL, /* get_next */ + NULL, /* end_get */ + NULL, /* add (extended) */ + NULL, /* remove (extended) */ +}; + +typedef struct krb5_ktkdb_data { + char * name; +} krb5_ktkdb_data; + +krb5_error_code +krb5_db_register_keytab(krb5_context context) +{ + return krb5_kt_register(context, &krb5_kt_kdb_ops); +} + +krb5_error_code +krb5_ktkdb_resolve(context, name, id) + krb5_context context; + const char * name; + krb5_keytab * id; +{ + if ((*id = (krb5_keytab) malloc(sizeof(**id))) == NULL) + return(ENOMEM); + (*id)->ops = &krb5_kt_kdb_ops; + (*id)->magic = KV5M_KEYTAB; + return(0); +} + +krb5_error_code +krb5_ktkdb_close(context, kt) + krb5_context context; + krb5_keytab kt; +{ + /* + * This routine is responsible for freeing all memory allocated + * for this keytab. There are no system resources that need + * to be freed nor are there any open files. + * + * This routine should undo anything done by krb5_ktkdb_resolve(). + */ + + kt->ops = NULL; + free(kt); + + return 0; +} + +static krb5_context ktkdb_ctx = NULL; + +/* + * Set a different context for use with ktkdb_get_entry(). This is + * primarily useful for kadmind, where the gssapi library context, + * which will be used for the keytab, will necessarily have a + * different context than that used by the kadm5 library to access the + * database for its own purposes. + */ +krb5_error_code +krb5_ktkdb_set_context(krb5_context ctx) +{ + ktkdb_ctx = ctx; + return 0; +} + +krb5_error_code +krb5_ktkdb_get_entry(in_context, id, principal, kvno, enctype, entry) + krb5_context in_context; + krb5_keytab id; + krb5_const_principal principal; + krb5_kvno kvno; + krb5_enctype enctype; + krb5_keytab_entry * entry; +{ + krb5_context context; + krb5_error_code kerror = 0; + krb5_key_data * key_data; + krb5_db_entry * db_entry; + int xrealm_tgt; + krb5_boolean similar; + + if (ktkdb_ctx) + context = ktkdb_ctx; + else + context = in_context; + + xrealm_tgt = is_xrealm_tgt(context, principal); + + /* Check whether database is inited. Open is commented */ + if ((kerror = krb5_db_inited(context))) + return(kerror); + + /* get_principal */ + kerror = krb5_db_get_principal(context, principal, 0, &db_entry); + if (kerror == KRB5_KDB_NOENTRY) + return(KRB5_KT_NOTFOUND); + if (kerror) + return(kerror); + + if (db_entry->attributes & KRB5_KDB_DISALLOW_SVR + || db_entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX) { + kerror = KRB5_KT_NOTFOUND; + goto error; + } + + /* match key */ + /* For cross realm tgts, we match whatever enctype is provided; + * for other principals, we only match the first enctype that is + * found. Since the TGS and AS code do the same thing, then we + * will only successfully decrypt tickets we have issued.*/ + kerror = krb5_dbe_find_enctype(context, db_entry, + xrealm_tgt?enctype:-1, + -1, kvno, &key_data); + if (kerror == KRB5_KDB_NO_MATCHING_KEY) + kerror = KRB5_KT_KVNONOTFOUND; + if (kerror) + goto error; + + + kerror = krb5_dbe_decrypt_key_data(context, NULL, key_data, + &entry->key, NULL); + if (kerror) + goto error; + + if (enctype > 0) { + kerror = krb5_c_enctype_compare(context, enctype, + entry->key.enctype, &similar); + if (kerror) + goto error; + + if (!similar) { + kerror = KRB5_KDB_NO_PERMITTED_KEY; + goto error; + } + } + /* + * Coerce the enctype of the output keyblock in case we got an + * inexact match on the enctype. + */ + entry->key.enctype = enctype; + + kerror = krb5_copy_principal(context, principal, &entry->principal); + if (kerror) + goto error; + + /* Close database */ +error: + krb5_db_free_principal(context, db_entry); + /* krb5_db_close_database(context); */ + return(kerror); +} + +/* + * is_xrealm_tgt: Returns true if the principal is a cross-realm TGT + * principal-- a principal with first component krbtgt and second + * component not equal to realm. + */ +static int +is_xrealm_tgt(krb5_context context, krb5_const_principal princ) +{ + krb5_data *dat; + if (krb5_princ_size(context, princ) != 2) + return 0; + dat = krb5_princ_component(context, princ, 0); + if (strncmp("krbtgt", dat->data, dat->length) != 0) + return 0; + dat = krb5_princ_component(context, princ, 1); + if (dat->length != princ->realm.length) + return 1; + if (strncmp(dat->data, princ->realm.data, dat->length) == 0) + return 0; + return 1; + +} diff --git a/krb5-1.21.3/src/lib/kdb/libkdb5.exports b/krb5-1.21.3/src/lib/kdb/libkdb5.exports new file mode 100644 index 00000000..97dc5c0d --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/libkdb5.exports @@ -0,0 +1,108 @@ +krb5_db_setup_lib_handle +krb5_db_open +krb5_db_inited +krb5_db_alloc +krb5_db_free +krb5_db_allowed_to_delegate_from +krb5_db_audit_as_req +krb5_db_check_allowed_to_delegate +krb5_db_get_s4u_x509_principal +krb5_db_check_policy_as +krb5_db_check_policy_tgs +krb5_db_check_transited_realms +krb5_db_create +krb5_db_delete_principal +krb5_db_destroy +krb5_db_fetch_mkey +krb5_db_fetch_mkey_list +krb5_db_fini +krb5_db_free_principal +krb5_db_get_age +krb5_db_get_key_data_kvno +krb5_db_get_context +krb5_db_get_principal +krb5_db_issue_pac +krb5_db_iterate +krb5_db_lock +krb5_db_mkey_list_alias +krb5_db_put_principal +krb5_db_refresh_config +krb5_db_rename_principal +krb5_db_set_context +krb5_db_setup_mkey_name +krb5_db_unlock +krb5_db_store_master_key +krb5_db_store_master_key_list +krb5_dbe_apw +krb5_dbe_ark +krb5_dbe_cpw +krb5_dbe_create_key_data +krb5_dbe_crk +krb5_dbe_find_act_mkey +krb5_dbe_fetch_act_key_list +krb5_dbe_find_enctype +krb5_dbe_find_mkey +krb5_dbe_free_actkvno_list +krb5_dbe_free_key_data_contents +krb5_dbe_free_mkey_aux_list +krb5_dbe_free_key_list +krb5_dbe_free_string +krb5_dbe_free_strings +krb5_dbe_get_mkvno +krb5_dbe_get_string +krb5_dbe_get_strings +krb5_dbe_compute_salt +krb5_dbe_lookup_last_admin_unlock +krb5_dbe_lookup_last_pwd_change +krb5_dbe_lookup_actkvno +krb5_dbe_lookup_mkey_aux +krb5_dbe_lookup_mkvno +krb5_dbe_lookup_mod_princ_data +krb5_dbe_lookup_tl_data +krb5_dbe_search_enctype +krb5_dbe_set_string +krb5_dbe_specialize_salt +krb5_dbe_update_actkvno +krb5_dbe_update_last_admin_unlock +krb5_dbe_update_last_pwd_change +krb5_dbe_update_mkey_aux +krb5_dbe_update_mkvno +krb5_dbe_update_mod_princ_data +krb5_dbe_update_tl_data +krb5_db_update_tl_data +krb5_dbe_def_encrypt_key_data +krb5_dbe_def_decrypt_key_data +krb5_dbe_decrypt_key_data +krb5_dbe_encrypt_key_data +krb5_kt_kdb_ops +krb5_ktkdb_close +krb5_ktkdb_get_entry +krb5_ktkdb_resolve +krb5_ktkdb_set_context +krb5_mkey_pwd_prompt1 +krb5_mkey_pwd_prompt2 +krb5_db_create_policy +krb5_db_get_policy +krb5_db_put_policy +krb5_db_iter_policy +krb5_db_delete_policy +krb5_db_free_policy +krb5_def_store_mkey_list +krb5_db_promote +krb5_db_register_keytab +ulog_add_update +ulog_init_header +ulog_map +ulog_set_role +ulog_free_entries +xdr_kdb_last_t +xdr_kdb_incr_result_t +xdr_kdb_fullresync_result_t +ulog_fini +ulog_get_entries +ulog_get_last +ulog_get_sno_status +ulog_replay +ulog_set_last +xdr_kdb_incr_update_t +krb5_dbe_sort_key_data diff --git a/krb5-1.21.3/src/lib/kdb/t_sort_key_data.c b/krb5-1.21.3/src/lib/kdb/t_sort_key_data.c new file mode 100644 index 00000000..ffd1a156 --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/t_sort_key_data.c @@ -0,0 +1,96 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kdb/t_sort_key_data.c - krb5_dbe_sort_key_data() unit tests */ +/* + * Copyright (C) 2015 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. + */ + +#include "k5-cmocka.h" +#include "kdb.h" + +#define KEY(kvno) { \ + 1, kvno, { ENCTYPE_AES128_CTS_HMAC_SHA1_96, 0 }, \ + { 16, 0 }, \ + { (uint8_t *)("\xDC\xEE\xB7\x0B\x3D\xE7\x65\x62" \ + "\xE6\x89\x22\x6C\x76\x42\x91\x48"), \ + NULL } \ + } + +static void +assert_sorted(krb5_key_data *keys, int num_keys) +{ + int i; + + for (i = 1; i < num_keys; i++) + assert_true(keys[i].key_data_kvno <= keys[i - 1].key_data_kvno); +} + +static void +test_pre_sorted(void **state) +{ + krb5_key_data keys[] = { KEY(5), KEY(5), KEY(4), KEY(3), KEY(3), KEY(2), + KEY(2), KEY(1) }; + int n_keys = sizeof(keys)/sizeof(keys[0]); + + krb5_dbe_sort_key_data(keys, n_keys); + assert_sorted(keys, n_keys); +} + +static void +test_reverse_sorted(void **state) +{ + krb5_key_data keys[] = { KEY(1), KEY(2), KEY(2), KEY(3), KEY(3), KEY(3), + KEY(4), KEY(5) }; + int n_keys = sizeof(keys)/sizeof(keys[0]); + + krb5_dbe_sort_key_data(keys, n_keys); + assert_sorted(keys, n_keys); +} + +static void +test_random_order(void **state) +{ + krb5_key_data keys[] = { KEY(1), KEY(4), KEY(1), KEY(3), KEY(4), KEY(3), + KEY(5), KEY(2) }; + int n_keys = sizeof(keys)/sizeof(keys[0]); + + krb5_dbe_sort_key_data(keys, n_keys); + assert_sorted(keys, n_keys); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_pre_sorted), + cmocka_unit_test(test_reverse_sorted), + cmocka_unit_test(test_random_order) + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/krb5-1.21.3/src/lib/kdb/t_stringattr.c b/krb5-1.21.3/src/lib/kdb/t_stringattr.c new file mode 100644 index 00000000..11740368 --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/t_stringattr.c @@ -0,0 +1,95 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kdb/t_strings.c - Test program for KDB string attribute functions */ +/* + * Copyright (C) 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include + +/* + * This program exercises the KDB entry APIs for string attributes. It relies + * on some implementation knowledge: + * + * - The APIs will work on a DB entry initialized to all zeros (because it has + * an empty tl_data list). + * + * - Attribute order in krb5_dbe_get_strings matches attribute insertion order. + */ + +int +main() +{ + krb5_db_entry *ent; + krb5_context context; + krb5_string_attr *strings; + char *val; + int count; + + assert(krb5int_init_context_kdc(&context) == 0); + + /* Start with an empty entry. */ + ent = calloc(1, sizeof(*ent)); + if (ent == NULL) { + fprintf(stderr, "Can't allocate memory for entry.\n"); + return 1; + } + + /* Check that the entry has no strings to start. */ + assert(krb5_dbe_get_strings(context, ent, &strings, &count) == 0); + assert(strings == NULL && count == 0); + krb5_dbe_free_strings(context, strings, count); + + /* Check that we get a null value querying a specific attribute. */ + assert(krb5_dbe_get_string(context, ent, "foo", &val) == 0); + assert(val == NULL); + + /* Set some attributes one at a time, including a deletion. */ + assert(krb5_dbe_set_string(context, ent, "eggs", "dozen") == 0); + assert(krb5_dbe_set_string(context, ent, "price", "right") == 0); + assert(krb5_dbe_set_string(context, ent, "eggs", NULL) == 0); + assert(krb5_dbe_set_string(context, ent, "time", "flies") == 0); + + /* Query each attribute. */ + assert(krb5_dbe_get_string(context, ent, "price", &val) == 0); + assert(strcmp(val, "right") == 0); + krb5_dbe_free_string(context, val); + assert(krb5_dbe_get_string(context, ent, "time", &val) == 0); + assert(strcmp(val, "flies") == 0); + krb5_dbe_free_string(context, val); + assert(krb5_dbe_get_string(context, ent, "eggs", &val) == 0); + assert(val == NULL); + + /* Query the list of attributes and verify it. */ + assert(krb5_dbe_get_strings(context, ent, &strings, &count) == 0); + assert(count == 2); + assert(strcmp(strings[0].key, "price") == 0); + assert(strcmp(strings[0].value, "right") == 0); + assert(strcmp(strings[1].key, "time") == 0); + assert(strcmp(strings[1].value, "flies") == 0); + krb5_dbe_free_strings(context, strings, count); + + krb5_db_free_principal(context, ent); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/lib/kdb/t_stringattr.py b/krb5-1.21.3/src/lib/kdb/t_stringattr.py new file mode 100755 index 00000000..93e2b0c0 --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/t_stringattr.py @@ -0,0 +1,5 @@ +from k5test import * + +realm = K5Realm(create_kdb=False) +realm.run(['./t_stringattr']) +success('String attribute unit tests') diff --git a/krb5-1.21.3/src/lib/kdb/t_ulog.c b/krb5-1.21.3/src/lib/kdb/t_ulog.c new file mode 100644 index 00000000..96e00bb4 --- /dev/null +++ b/krb5-1.21.3/src/lib/kdb/t_ulog.c @@ -0,0 +1,88 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kdb/t_ulog.c - Unit tests for KDB update log */ +/* + * Copyright (C) 2014 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. + */ + +/* + * This program performs unit tests for the update log functions in kdb_log.c. + * Right now it contains only a test for issue #7839, checking that + * ulog_add_update behaves appropriately when the last serial number is + * reached. + * + * The test program accepts one argument, which it unlinks and then maps with + * ulog_map(). This lets us test all of the update log functions except for + * ulog_replay(), which needs to open and modify a Kerberos database. + * ulog_replay is adequately exercised by the functional tests in t_iprop.py. + */ + +#include "k5-int.h" +#include "kdb_log.h" + +/* Use a zeroed context structure to avoid reading the profile. This works + * fine for the ulog functions. */ +static struct _krb5_context context_st; +static krb5_context context = &context_st; + +int +main(int argc, char **argv) +{ + kdb_log_context *lctx; + kdb_hlog_t *ulog; + kdb_incr_update_t upd; + const char *filename; + + if (argc != 2) { + fprintf(stderr, "Usage: %s filename\n", argv[0]); + exit(1); + } + filename = argv[1]; + unlink(filename); + + if (ulog_map(context, filename, 10) != 0) + abort(); + lctx = context->kdblog_context; + ulog = lctx->ulog; + + /* Modify the ulog to look like it has reached the last serial number. + * Leave the timestamps at 0 and don't bother setting up the entries. */ + ulog->kdb_num = lctx->ulogentries; + ulog->kdb_last_sno = (kdb_sno_t)-1; + ulog->kdb_first_sno = ulog->kdb_last_sno - ulog->kdb_num + 1; + + /* Add an empty update. This should reinitialize the ulog, then add the + * update with serial number 2. */ + memset(&upd, 0, sizeof(kdb_incr_update_t)); + if (ulog_add_update(context, &upd) != 0) + abort(); + assert(ulog->kdb_num == 2); + assert(ulog->kdb_first_sno == 1); + assert(ulog->kdb_last_sno == 2); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krad/Makefile.in b/krb5-1.21.3/src/lib/krad/Makefile.in new file mode 100644 index 00000000..8c3317fe --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/Makefile.in @@ -0,0 +1,73 @@ +mydir=lib$(S)krad +BUILDTOP=$(REL)..$(S).. +RELDIR=krad + +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) + +SHLIB_EXPLIBS=$(KRB5_BASE_LIBS) $(VERTO_LIBS) +SHLIB_EXPDEPLIBS=$(KRB5_BASE_DEPLIBS) $(VERTO_DEPLIB) +SHLIB_DIRS=-L$(TOPLIBD) +SHLIB_RDIRS=$(KRB5_LIBDIR) + +LIBBASE=krad +LIBMAJOR=0 +LIBMINOR=0 + +STLIBOBJS=attr.o attrset.o client.o code.o packet.o remote.o +LIBOBJS=$(OUTPRE)attr.$(OBJEXT) \ + $(OUTPRE)attrset.$(OBJEXT) \ + $(OUTPRE)client.$(OBJEXT) \ + $(OUTPRE)code.$(OBJEXT) \ + $(OUTPRE)packet.$(OBJEXT) \ + $(OUTPRE)remote.$(OBJEXT) +SRCS=attr.c attrset.c client.c code.c packet.c remote.c \ + t_attr.c t_attrset.c t_client.c t_code.c t_packet.c t_remote.c t_test.c + +STOBJLISTS=OBJS.ST + +all-unix: all-liblinks +install-unix: install-libs + +clean-unix:: clean-liblinks clean-libs clean-libobjs + +check-unix: t_attr t_attrset t_code t_packet t_remote t_client + $(RUN_TEST) ./t_attr + $(RUN_TEST) ./t_attrset + $(RUN_TEST) ./t_code + $(RUN_TEST) ./t_packet $(PYTHON) $(srcdir)/t_daemon.py + $(RUN_TEST) ./t_remote $(PYTHON) $(srcdir)/t_daemon.py + $(RUN_TEST) ./t_client $(PYTHON) $(srcdir)/t_daemon.py + +TESTDEPS=t_test.o $(KRB5_BASE_DEPLIBS) +TESTLIBS=t_test.o $(KRB5_BASE_LIBS) + +T_ATTR_OBJS=attr.o t_attr.o +t_attr: $(T_ATTR_OBJS) $(TESTDEPS) + $(CC_LINK) -o $@ $(T_ATTR_OBJS) $(TESTLIBS) + +T_ATTRSET_OBJS=attr.o attrset.o t_attrset.o +t_attrset: $(T_ATTRSET_OBJS) $(TESTDEPS) + $(CC_LINK) -o $@ $(T_ATTRSET_OBJS) $(TESTLIBS) + +T_CODE_OBJS=code.o t_code.o +t_code: $(T_CODE_OBJS) $(TESTDEPS) + $(CC_LINK) -o $@ $(T_CODE_OBJS) $(TESTLIBS) + +T_PACKET_OBJS=attr.o attrset.o code.o packet.o t_packet.o +t_packet: $(T_PACKET_OBJS) $(TESTDEPS) + $(CC_LINK) -o $@ $(T_PACKET_OBJS) $(TESTLIBS) + +T_REMOTE_OBJS=attr.o attrset.o code.o packet.o remote.o t_remote.o +t_remote: $(T_REMOTE_OBJS) $(TESTDEPS) $(VERTO_DEPLIB) + $(CC_LINK) -o $@ $(T_REMOTE_OBJS) $(TESTLIBS) $(VERTO_LIBS) + +T_CLIENT_OBJS=attr.o attrset.o code.o packet.o remote.o client.o t_client.o +t_client: $(T_CLIENT_OBJS) $(TESTDEPS) $(VERTO_DEPLIB) + $(CC_LINK) -o $@ $(T_CLIENT_OBJS) $(TESTLIBS) $(VERTO_LIBS) + +clean-unix:: clean-libobjs + $(RM) *.o t_attr t_attrset t_code t_packet t_remote t_client + +@lib_frag@ +@libobj_frag@ diff --git a/krb5-1.21.3/src/lib/krad/attr.c b/krb5-1.21.3/src/lib/krad/attr.c new file mode 100644 index 00000000..9c13d9d7 --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/attr.c @@ -0,0 +1,317 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/attr.c - RADIUS attribute functions for libkrad */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include +#include "internal.h" + +#include + +/* RFC 2865 */ +#define BLOCKSIZE 16 + +typedef krb5_error_code +(*attribute_transform_fn)(krb5_context ctx, const char *secret, + const unsigned char *auth, const krb5_data *in, + unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen); + +typedef struct { + const char *name; + unsigned char minval; + unsigned char maxval; + attribute_transform_fn encode; + attribute_transform_fn decode; +} attribute_record; + +static krb5_error_code +user_password_encode(krb5_context ctx, const char *secret, + const unsigned char *auth, const krb5_data *in, + unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen); + +static krb5_error_code +user_password_decode(krb5_context ctx, const char *secret, + const unsigned char *auth, const krb5_data *in, + unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen); + +static const attribute_record attributes[UCHAR_MAX] = { + {"User-Name", 1, MAX_ATTRSIZE, NULL, NULL}, + {"User-Password", 1, 128, user_password_encode, user_password_decode}, + {"CHAP-Password", 17, 17, NULL, NULL}, + {"NAS-IP-Address", 4, 4, NULL, NULL}, + {"NAS-Port", 4, 4, NULL, NULL}, + {"Service-Type", 4, 4, NULL, NULL}, + {"Framed-Protocol", 4, 4, NULL, NULL}, + {"Framed-IP-Address", 4, 4, NULL, NULL}, + {"Framed-IP-Netmask", 4, 4, NULL, NULL}, + {"Framed-Routing", 4, 4, NULL, NULL}, + {"Filter-Id", 1, MAX_ATTRSIZE, NULL, NULL}, + {"Framed-MTU", 4, 4, NULL, NULL}, + {"Framed-Compression", 4, 4, NULL, NULL}, + {"Login-IP-Host", 4, 4, NULL, NULL}, + {"Login-Service", 4, 4, NULL, NULL}, + {"Login-TCP-Port", 4, 4, NULL, NULL}, + {NULL, 0, 0, NULL, NULL}, /* Unassigned */ + {"Reply-Message", 1, MAX_ATTRSIZE, NULL, NULL}, + {"Callback-Number", 1, MAX_ATTRSIZE, NULL, NULL}, + {"Callback-Id", 1, MAX_ATTRSIZE, NULL, NULL}, + {NULL, 0, 0, NULL, NULL}, /* Unassigned */ + {"Framed-Route", 1, MAX_ATTRSIZE, NULL, NULL}, + {"Framed-IPX-Network", 4, 4, NULL, NULL}, + {"State", 1, MAX_ATTRSIZE, NULL, NULL}, + {"Class", 1, MAX_ATTRSIZE, NULL, NULL}, + {"Vendor-Specific", 5, MAX_ATTRSIZE, NULL, NULL}, + {"Session-Timeout", 4, 4, NULL, NULL}, + {"Idle-Timeout", 4, 4, NULL, NULL}, + {"Termination-Action", 4, 4, NULL, NULL}, + {"Called-Station-Id", 1, MAX_ATTRSIZE, NULL, NULL}, + {"Calling-Station-Id", 1, MAX_ATTRSIZE, NULL, NULL}, + {"NAS-Identifier", 1, MAX_ATTRSIZE, NULL, NULL}, + {"Proxy-State", 1, MAX_ATTRSIZE, NULL, NULL}, + {"Login-LAT-Service", 1, MAX_ATTRSIZE, NULL, NULL}, + {"Login-LAT-Node", 1, MAX_ATTRSIZE, NULL, NULL}, + {"Login-LAT-Group", 32, 32, NULL, NULL}, + {"Framed-AppleTalk-Link", 4, 4, NULL, NULL}, + {"Framed-AppleTalk-Network", 4, 4, NULL, NULL}, + {"Framed-AppleTalk-Zone", 1, MAX_ATTRSIZE, NULL, NULL}, + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {NULL, 0, 0, NULL, NULL}, /* Reserved for accounting */ + {"CHAP-Challenge", 5, MAX_ATTRSIZE, NULL, NULL}, + {"NAS-Port-Type", 4, 4, NULL, NULL}, + {"Port-Limit", 4, 4, NULL, NULL}, + {"Login-LAT-Port", 1, MAX_ATTRSIZE, NULL, NULL}, +}; + +/* Encode User-Password attribute. */ +static krb5_error_code +user_password_encode(krb5_context ctx, const char *secret, + const unsigned char *auth, const krb5_data *in, + unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen) +{ + const unsigned char *indx; + krb5_error_code retval; + unsigned int seclen; + krb5_checksum sum; + size_t blck, len, i; + krb5_data tmp; + + /* Copy the input buffer to the (zero-padded) output buffer. */ + len = (in->length + BLOCKSIZE - 1) / BLOCKSIZE * BLOCKSIZE; + if (len > MAX_ATTRSIZE) + return ENOBUFS; + memset(outbuf, 0, len); + memcpy(outbuf, in->data, in->length); + + /* Create our temporary space for processing each block. */ + seclen = strlen(secret); + retval = alloc_data(&tmp, seclen + BLOCKSIZE); + if (retval != 0) + return retval; + + memcpy(tmp.data, secret, seclen); + for (blck = 0, indx = auth; blck * BLOCKSIZE < len; blck++) { + memcpy(tmp.data + seclen, indx, BLOCKSIZE); + + retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &tmp, + &sum); + if (retval != 0) { + zap(tmp.data, tmp.length); + zap(outbuf, len); + krb5_free_data_contents(ctx, &tmp); + return retval; + } + + for (i = 0; i < BLOCKSIZE; i++) + outbuf[blck * BLOCKSIZE + i] ^= sum.contents[i]; + krb5_free_checksum_contents(ctx, &sum); + + indx = &outbuf[blck * BLOCKSIZE]; + } + + zap(tmp.data, tmp.length); + krb5_free_data_contents(ctx, &tmp); + *outlen = len; + return 0; +} + +/* Decode User-Password attribute. */ +static krb5_error_code +user_password_decode(krb5_context ctx, const char *secret, + const unsigned char *auth, const krb5_data *in, + unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen) +{ + const unsigned char *indx; + krb5_error_code retval; + unsigned int seclen; + krb5_checksum sum; + ssize_t blck, i; + krb5_data tmp; + + if (in->length % BLOCKSIZE != 0) + return EINVAL; + if (in->length > MAX_ATTRSIZE) + return ENOBUFS; + + /* Create our temporary space for processing each block. */ + seclen = strlen(secret); + retval = alloc_data(&tmp, seclen + BLOCKSIZE); + if (retval != 0) + return retval; + + memcpy(tmp.data, secret, seclen); + for (blck = 0, indx = auth; blck * BLOCKSIZE < in->length; blck++) { + memcpy(tmp.data + seclen, indx, BLOCKSIZE); + + retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, + &tmp, &sum); + if (retval != 0) { + zap(tmp.data, tmp.length); + zap(outbuf, in->length); + krb5_free_data_contents(ctx, &tmp); + return retval; + } + + for (i = 0; i < BLOCKSIZE; i++) { + outbuf[blck * BLOCKSIZE + i] = in->data[blck * BLOCKSIZE + i] ^ + sum.contents[i]; + } + krb5_free_checksum_contents(ctx, &sum); + + indx = (const unsigned char *)&in->data[blck * BLOCKSIZE]; + } + + /* Strip off trailing NULL bytes. */ + *outlen = in->length; + while (*outlen > 0 && outbuf[*outlen - 1] == '\0') + (*outlen)--; + + krb5_free_data_contents(ctx, &tmp); + return 0; +} + +krb5_error_code +kr_attr_valid(krad_attr type, const krb5_data *data) +{ + const attribute_record *ar; + + if (type == 0) + return EINVAL; + + ar = &attributes[type - 1]; + return (data->length >= ar->minval && data->length <= ar->maxval) ? 0 : + EMSGSIZE; +} + +krb5_error_code +kr_attr_encode(krb5_context ctx, const char *secret, + const unsigned char *auth, krad_attr type, + const krb5_data *in, unsigned char outbuf[MAX_ATTRSIZE], + size_t *outlen) +{ + krb5_error_code retval; + + retval = kr_attr_valid(type, in); + if (retval != 0) + return retval; + + if (attributes[type - 1].encode == NULL) { + if (in->length > MAX_ATTRSIZE) + return ENOBUFS; + + *outlen = in->length; + memcpy(outbuf, in->data, in->length); + return 0; + } + + return attributes[type - 1].encode(ctx, secret, auth, in, outbuf, outlen); +} + +krb5_error_code +kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth, + krad_attr type, const krb5_data *in, + unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen) +{ + krb5_error_code retval; + + retval = kr_attr_valid(type, in); + if (retval != 0) + return retval; + + if (attributes[type - 1].encode == NULL) { + if (in->length > MAX_ATTRSIZE) + return ENOBUFS; + + *outlen = in->length; + memcpy(outbuf, in->data, in->length); + return 0; + } + + return attributes[type - 1].decode(ctx, secret, auth, in, outbuf, outlen); +} + +krad_attr +krad_attr_name2num(const char *name) +{ + unsigned char i; + + for (i = 0; i < UCHAR_MAX; i++) { + if (attributes[i].name == NULL) + continue; + + if (strcmp(attributes[i].name, name) == 0) + return i + 1; + } + + return 0; +} + +const char * +krad_attr_num2name(krad_attr type) +{ + if (type == 0) + return NULL; + + return attributes[type - 1].name; +} diff --git a/krb5-1.21.3/src/lib/krad/attrset.c b/krb5-1.21.3/src/lib/krad/attrset.c new file mode 100644 index 00000000..f309f158 --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/attrset.c @@ -0,0 +1,244 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/attrset.c - RADIUS attribute set functions for libkrad */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include +#include +#include "internal.h" + +#include + +K5_TAILQ_HEAD(attr_head, attr_st); + +typedef struct attr_st attr; +struct attr_st { + K5_TAILQ_ENTRY(attr_st) list; + krad_attr type; + krb5_data attr; + char buffer[MAX_ATTRSIZE]; +}; + +struct krad_attrset_st { + krb5_context ctx; + struct attr_head list; +}; + +krb5_error_code +krad_attrset_new(krb5_context ctx, krad_attrset **set) +{ + krad_attrset *tmp; + + tmp = calloc(1, sizeof(krad_attrset)); + if (tmp == NULL) + return ENOMEM; + tmp->ctx = ctx; + K5_TAILQ_INIT(&tmp->list); + + *set = tmp; + return 0; +} + +void +krad_attrset_free(krad_attrset *set) +{ + attr *a; + + if (set == NULL) + return; + + while (!K5_TAILQ_EMPTY(&set->list)) { + a = K5_TAILQ_FIRST(&set->list); + K5_TAILQ_REMOVE(&set->list, a, list); + zap(a->buffer, sizeof(a->buffer)); + free(a); + } + + free(set); +} + +krb5_error_code +krad_attrset_add(krad_attrset *set, krad_attr type, const krb5_data *data) +{ + krb5_error_code retval; + attr *tmp; + + retval = kr_attr_valid(type, data); + if (retval != 0) + return retval; + + tmp = calloc(1, sizeof(attr)); + if (tmp == NULL) + return ENOMEM; + + tmp->type = type; + tmp->attr = make_data(tmp->buffer, data->length); + memcpy(tmp->attr.data, data->data, data->length); + + K5_TAILQ_INSERT_TAIL(&set->list, tmp, list); + return 0; +} + +krb5_error_code +krad_attrset_add_number(krad_attrset *set, krad_attr type, krb5_ui_4 num) +{ + krb5_data data; + + num = htonl(num); + data = make_data(&num, sizeof(num)); + return krad_attrset_add(set, type, &data); +} + +void +krad_attrset_del(krad_attrset *set, krad_attr type, size_t indx) +{ + attr *a; + + K5_TAILQ_FOREACH(a, &set->list, list) { + if (a->type == type && indx-- == 0) { + K5_TAILQ_REMOVE(&set->list, a, list); + zap(a->buffer, sizeof(a->buffer)); + free(a); + return; + } + } +} + +const krb5_data * +krad_attrset_get(const krad_attrset *set, krad_attr type, size_t indx) +{ + attr *a; + + K5_TAILQ_FOREACH(a, &set->list, list) { + if (a->type == type && indx-- == 0) + return &a->attr; + } + + return NULL; +} + +krb5_error_code +krad_attrset_copy(const krad_attrset *set, krad_attrset **copy) +{ + krb5_error_code retval; + krad_attrset *tmp; + attr *a; + + retval = krad_attrset_new(set->ctx, &tmp); + if (retval != 0) + return retval; + + K5_TAILQ_FOREACH(a, &set->list, list) { + retval = krad_attrset_add(tmp, a->type, &a->attr); + if (retval != 0) { + krad_attrset_free(tmp); + return retval; + } + } + + *copy = tmp; + return 0; +} + +krb5_error_code +kr_attrset_encode(const krad_attrset *set, const char *secret, + const unsigned char *auth, + unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen) +{ + unsigned char buffer[MAX_ATTRSIZE]; + krb5_error_code retval; + size_t i = 0, attrlen; + attr *a; + + if (set == NULL) { + *outlen = 0; + return 0; + } + + K5_TAILQ_FOREACH(a, &set->list, list) { + retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr, + buffer, &attrlen); + if (retval != 0) + return retval; + + if (i + attrlen + 2 > MAX_ATTRSETSIZE) + return EMSGSIZE; + + outbuf[i++] = a->type; + outbuf[i++] = attrlen + 2; + memcpy(&outbuf[i], buffer, attrlen); + i += attrlen; + } + + *outlen = i; + return 0; +} + +krb5_error_code +kr_attrset_decode(krb5_context ctx, const krb5_data *in, const char *secret, + const unsigned char *auth, krad_attrset **set_out) +{ + unsigned char buffer[MAX_ATTRSIZE]; + krb5_data tmp; + krb5_error_code retval; + krad_attr type; + krad_attrset *set; + size_t i, len; + + *set_out = NULL; + + retval = krad_attrset_new(ctx, &set); + if (retval != 0) + return retval; + + for (i = 0; i + 2 < in->length; ) { + type = in->data[i++]; + tmp = make_data(&in->data[i + 1], (uint8_t)in->data[i] - 2); + i += tmp.length + 1; + + retval = (in->length < i) ? EBADMSG : 0; + if (retval != 0) + goto cleanup; + + retval = kr_attr_decode(ctx, secret, auth, type, &tmp, buffer, &len); + if (retval != 0) + goto cleanup; + + tmp = make_data(buffer, len); + retval = krad_attrset_add(set, type, &tmp); + if (retval != 0) + goto cleanup; + } + + *set_out = set; + set = NULL; + +cleanup: + zap(buffer, sizeof(buffer)); + krad_attrset_free(set); + return retval; +} diff --git a/krb5-1.21.3/src/lib/krad/client.c b/krb5-1.21.3/src/lib/krad/client.c new file mode 100644 index 00000000..810940af --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/client.c @@ -0,0 +1,321 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/client.c - Client request code for libkrad */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include +#include "internal.h" + +#include +#include +#include +#include +#include + +K5_LIST_HEAD(server_head, server_st); + +typedef struct remote_state_st remote_state; +typedef struct request_st request; +typedef struct server_st server; + +struct remote_state_st { + const krad_packet *packet; + krad_remote *remote; +}; + +struct request_st { + krad_client *rc; + + krad_code code; + krad_attrset *attrs; + int timeout; + size_t retries; + krad_cb cb; + void *data; + + remote_state *remotes; + ssize_t current; + ssize_t count; +}; + +struct server_st { + krad_remote *serv; + K5_LIST_ENTRY(server_st) list; +}; + +struct krad_client_st { + krb5_context kctx; + verto_ctx *vctx; + struct server_head servers; +}; + +/* Return either a pre-existing server that matches the address info and the + * secret, or create a new one. */ +static krb5_error_code +get_server(krad_client *rc, const struct addrinfo *ai, const char *secret, + krad_remote **out) +{ + krb5_error_code retval; + server *srv; + + K5_LIST_FOREACH(srv, &rc->servers, list) { + if (kr_remote_equals(srv->serv, ai, secret)) { + *out = srv->serv; + return 0; + } + } + + srv = calloc(1, sizeof(server)); + if (srv == NULL) + return ENOMEM; + + retval = kr_remote_new(rc->kctx, rc->vctx, ai, secret, &srv->serv); + if (retval != 0) { + free(srv); + return retval; + } + + K5_LIST_INSERT_HEAD(&rc->servers, srv, list); + *out = srv->serv; + return 0; +} + +/* Free a request. */ +static void +request_free(request *req) +{ + krad_attrset_free(req->attrs); + free(req->remotes); + free(req); +} + +/* Create a request. */ +static krb5_error_code +request_new(krad_client *rc, krad_code code, const krad_attrset *attrs, + const struct addrinfo *ai, const char *secret, int timeout, + size_t retries, krad_cb cb, void *data, request **req) +{ + const struct addrinfo *tmp; + krb5_error_code retval; + request *rqst; + size_t i; + + if (ai == NULL) + return EINVAL; + + rqst = calloc(1, sizeof(request)); + if (rqst == NULL) + return ENOMEM; + + for (tmp = ai; tmp != NULL; tmp = tmp->ai_next) + rqst->count++; + + rqst->rc = rc; + rqst->code = code; + rqst->cb = cb; + rqst->data = data; + rqst->timeout = timeout / rqst->count; + rqst->retries = retries; + + retval = krad_attrset_copy(attrs, &rqst->attrs); + if (retval != 0) { + request_free(rqst); + return retval; + } + + rqst->remotes = calloc(rqst->count + 1, sizeof(remote_state)); + if (rqst->remotes == NULL) { + request_free(rqst); + return ENOMEM; + } + + i = 0; + for (tmp = ai; tmp != NULL; tmp = tmp->ai_next) { + retval = get_server(rc, tmp, secret, &rqst->remotes[i++].remote); + if (retval != 0) { + request_free(rqst); + return retval; + } + } + + *req = rqst; + return 0; +} + +/* Handle a response from a server (or related errors). */ +static void +on_response(krb5_error_code retval, const krad_packet *reqp, + const krad_packet *rspp, void *data) +{ + request *req = data; + size_t i; + + /* Do nothing if we are already completed. */ + if (req->count < 0) + return; + + /* If we have timed out and have more remotes to try, do so. */ + if (retval == ETIMEDOUT && req->remotes[++req->current].remote != NULL) { + retval = kr_remote_send(req->remotes[req->current].remote, req->code, + req->attrs, on_response, req, req->timeout, + req->retries, + &req->remotes[req->current].packet); + if (retval == 0) + return; + } + + /* Mark the request as complete. */ + req->count = -1; + + /* Inform the callback. */ + req->cb(retval, reqp, rspp, req->data); + + /* Cancel the outstanding packets. */ + for (i = 0; req->remotes[i].remote != NULL; i++) + kr_remote_cancel(req->remotes[i].remote, req->remotes[i].packet); + + request_free(req); +} + +krb5_error_code +krad_client_new(krb5_context kctx, verto_ctx *vctx, krad_client **out) +{ + krad_client *tmp; + + tmp = calloc(1, sizeof(krad_client)); + if (tmp == NULL) + return ENOMEM; + + tmp->kctx = kctx; + tmp->vctx = vctx; + + *out = tmp; + return 0; +} + +void +krad_client_free(krad_client *rc) +{ + server *srv; + + if (rc == NULL) + return; + + /* Cancel all requests before freeing any remotes, since each request's + * callback data may contain references to multiple remotes. */ + K5_LIST_FOREACH(srv, &rc->servers, list) + kr_remote_cancel_all(srv->serv); + + while (!K5_LIST_EMPTY(&rc->servers)) { + srv = K5_LIST_FIRST(&rc->servers); + K5_LIST_REMOVE(srv, list); + kr_remote_free(srv->serv); + free(srv); + } + + free(rc); +} + +static krb5_error_code +resolve_remote(const char *remote, struct addrinfo **ai) +{ + const char *svc = "radius"; + krb5_error_code retval; + struct addrinfo hints; + char *sep, *srv; + + /* Isolate the port number if it exists. */ + srv = strdup(remote); + if (srv == NULL) + return ENOMEM; + + if (srv[0] == '[') { + /* IPv6 */ + sep = strrchr(srv, ']'); + if (sep != NULL && sep[1] == ':') { + sep[1] = '\0'; + svc = &sep[2]; + } + } else { + /* IPv4 or DNS */ + sep = strrchr(srv, ':'); + if (sep != NULL && sep[1] != '\0') { + sep[0] = '\0'; + svc = &sep[1]; + } + } + + /* Perform the lookup. */ + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_DGRAM; + retval = gai_error_code(getaddrinfo(srv, svc, &hints, ai)); + free(srv); + return retval; +} + +krb5_error_code +krad_client_send(krad_client *rc, krad_code code, const krad_attrset *attrs, + const char *remote, const char *secret, int timeout, + size_t retries, krad_cb cb, void *data) +{ + struct addrinfo usock, *ai = NULL; + krb5_error_code retval; + struct sockaddr_un ua; + request *req; + + if (remote[0] == '/') { + ua.sun_family = AF_UNIX; + snprintf(ua.sun_path, sizeof(ua.sun_path), "%s", remote); + memset(&usock, 0, sizeof(usock)); + usock.ai_family = AF_UNIX; + usock.ai_socktype = SOCK_STREAM; + usock.ai_addr = (struct sockaddr *)&ua; + usock.ai_addrlen = sizeof(ua); + + retval = request_new(rc, code, attrs, &usock, secret, timeout, retries, + cb, data, &req); + } else { + retval = resolve_remote(remote, &ai); + if (retval == 0) { + retval = request_new(rc, code, attrs, ai, secret, timeout, retries, + cb, data, &req); + freeaddrinfo(ai); + } + } + if (retval != 0) + return retval; + + retval = kr_remote_send(req->remotes[req->current].remote, req->code, + req->attrs, on_response, req, req->timeout, + req->retries, &req->remotes[req->current].packet); + if (retval != 0) { + request_free(req); + return retval; + } + + return 0; +} diff --git a/krb5-1.21.3/src/lib/krad/code.c b/krb5-1.21.3/src/lib/krad/code.c new file mode 100644 index 00000000..16871bb0 --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/code.c @@ -0,0 +1,111 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/code.c - RADIUS code name table for libkrad */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include "internal.h" + +#include + +static const char *codes[UCHAR_MAX] = { + "Access-Request", + "Access-Accept", + "Access-Reject", + "Accounting-Request", + "Accounting-Response", + "Accounting-Status", + "Password-Request", + "Password-Ack", + "Password-Reject", + "Accounting-Message", + "Access-Challenge", + "Status-Server", + "Status-Client", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "Resource-Free-Request", + "Resource-Free-Response", + "Resource-Query-Request", + "Resource-Query-Response", + "Alternate-Resource-Reclaim-Request", + "NAS-Reboot-Request", + "NAS-Reboot-Response", + NULL, + "Next-Passcode", + "New-Pin", + "Terminate-Session", + "Password-Expired", + "Event-Request", + "Event-Response", + NULL, + NULL, + NULL, + NULL, + NULL, + "Disconnect-Request", + "Disconnect-Ack", + "Disconnect-Nak", + "Change-Filters-Request", + "Change-Filters-Ack", + "Change-Filters-Nak", + NULL, + NULL, + NULL, + NULL, + "IP-Address-Allocate", + "IP-Address-Release", +}; + +krad_code +krad_code_name2num(const char *name) +{ + unsigned char i; + + for (i = 0; i < UCHAR_MAX; i++) { + if (codes[i] == NULL) + continue; + + if (strcmp(codes[i], name) == 0) + return ++i; + } + + return 0; +} + +const char * +krad_code_num2name(krad_code code) +{ + if (code == 0) + return NULL; + + return codes[code - 1]; +} diff --git a/krb5-1.21.3/src/lib/krad/deps b/krb5-1.21.3/src/lib/krad/deps new file mode 100644 index 00000000..8171f944 --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/deps @@ -0,0 +1,156 @@ +# +# Generated makefile dependencies follow. +# +attr.so attr.po $(OUTPRE)attr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krad.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h attr.c internal.h +attrset.so attrset.po $(OUTPRE)attrset.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-queue.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krad.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + attrset.c internal.h +client.so client.po $(OUTPRE)client.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-queue.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krad.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + client.c internal.h +code.so code.po $(OUTPRE)code.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krad.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h code.c internal.h +packet.so packet.po $(OUTPRE)packet.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krad.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h internal.h packet.c +remote.so remote.po $(OUTPRE)remote.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-queue.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krad.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + internal.h remote.c +t_attr.so t_attr.po $(OUTPRE)t_attr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krad.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h internal.h t_attr.c \ + t_test.h +t_attrset.so t_attrset.po $(OUTPRE)t_attrset.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(VERTO_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krad.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + internal.h t_attrset.c t_test.h +t_client.so t_client.po $(OUTPRE)t_client.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(VERTO_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krad.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + internal.h t_client.c t_daemon.h t_test.h +t_code.so t_code.po $(OUTPRE)t_code.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krad.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h internal.h t_code.c \ + t_test.h +t_packet.so t_packet.po $(OUTPRE)t_packet.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(VERTO_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krad.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + internal.h t_daemon.h t_packet.c t_test.h +t_remote.so t_remote.po $(OUTPRE)t_remote.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(VERTO_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krad.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + internal.h t_daemon.h t_remote.c t_test.h +t_test.so t_test.po $(OUTPRE)t_test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krad.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h internal.h t_test.c \ + t_test.h diff --git a/krb5-1.21.3/src/lib/krad/internal.h b/krb5-1.21.3/src/lib/krad/internal.h new file mode 100644 index 00000000..7619563f --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/internal.h @@ -0,0 +1,159 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/internal.h - Internal declarations for libkrad */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#ifndef INTERNAL_H_ +#define INTERNAL_H_ + +#include +#include "krad.h" + +#include + +#include +#include +#include + +#ifndef UCHAR_MAX +#define UCHAR_MAX 255 +#endif + +/* RFC 2865 */ +#define MAX_ATTRSIZE (UCHAR_MAX - 2) +#define MAX_ATTRSETSIZE (KRAD_PACKET_SIZE_MAX - 20) + +typedef struct krad_remote_st krad_remote; + +/* Validate constraints of an attribute. */ +krb5_error_code +kr_attr_valid(krad_attr type, const krb5_data *data); + +/* Encode an attribute. */ +krb5_error_code +kr_attr_encode(krb5_context ctx, const char *secret, const unsigned char *auth, + krad_attr type, const krb5_data *in, + unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen); + +/* Decode an attribute. */ +krb5_error_code +kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth, + krad_attr type, const krb5_data *in, + unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen); + +/* Encode the attributes into the buffer. */ +krb5_error_code +kr_attrset_encode(const krad_attrset *set, const char *secret, + const unsigned char *auth, + unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen); + +/* Decode attributes from a buffer. */ +krb5_error_code +kr_attrset_decode(krb5_context ctx, const krb5_data *in, const char *secret, + const unsigned char *auth, krad_attrset **set); + +/* Create a new remote object which manages a socket and the state of + * outstanding requests. */ +krb5_error_code +kr_remote_new(krb5_context kctx, verto_ctx *vctx, const struct addrinfo *info, + const char *secret, krad_remote **rr); + +/* Free a remote object. */ +void +kr_remote_free(krad_remote *rr); + +/* + * Send the packet to the remote. The cb will be called when a response is + * received, the request times out, the request is canceled or an error occurs. + * + * The timeout parameter is the total timeout across all retries in + * milliseconds. + * + * If the cb is called with a retval of ETIMEDOUT it indicates that the + * allotted time has elapsed. However, in the case of a timeout, we continue to + * listen for the packet until krad_remote_cancel() is called or a response is + * received. This means that cb will always be called twice in the event of a + * timeout. This permits you to pursue other remotes while still listening for + * a response from the first one. + */ +krb5_error_code +kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs, + krad_cb cb, void *data, int timeout, size_t retries, + const krad_packet **pkt); + +/* Remove packet from the queue of requests awaiting responses. */ +void +kr_remote_cancel(krad_remote *rr, const krad_packet *pkt); + +/* Cancel all requests awaiting responses. */ +void +kr_remote_cancel_all(krad_remote *rr); + +/* Determine if this remote object refers to the remote resource identified + * by the addrinfo struct and the secret. */ +krb5_boolean +kr_remote_equals(const krad_remote *rr, const struct addrinfo *info, + const char *secret); + +/* Adapted from lib/krb5/os/sendto_kdc.c. */ +static inline krb5_error_code +gai_error_code(int err) +{ + switch (err) { + case 0: + return 0; + case EAI_BADFLAGS: + case EAI_FAMILY: + case EAI_SOCKTYPE: + case EAI_SERVICE: +#ifdef EAI_ADDRFAMILY + case EAI_ADDRFAMILY: +#endif + return EINVAL; + case EAI_AGAIN: + return EAGAIN; + case EAI_MEMORY: + return ENOMEM; +#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME + case EAI_NODATA: +#endif + case EAI_NONAME: + return EADDRNOTAVAIL; +#ifdef EAI_OVERFLOW + case EAI_OVERFLOW: + return EOVERFLOW; +#endif +#ifdef EAI_SYSTEM + case EAI_SYSTEM: + return errno; +#endif + default: + return EINVAL; + } +} + +#endif /* INTERNAL_H_ */ diff --git a/krb5-1.21.3/src/lib/krad/libkrad.exports b/krb5-1.21.3/src/lib/krad/libkrad.exports new file mode 100644 index 00000000..fe3f1590 --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/libkrad.exports @@ -0,0 +1,23 @@ +krad_code_name2num +krad_code_num2name +krad_attr_name2num +krad_attr_num2name +krad_attrset_new +krad_attrset_copy +krad_attrset_free +krad_attrset_add +krad_attrset_add_number +krad_attrset_del +krad_attrset_get +krad_packet_bytes_needed +krad_packet_free +krad_packet_new_request +krad_packet_new_response +krad_packet_decode_request +krad_packet_decode_response +krad_packet_encode +krad_packet_get_code +krad_packet_get_attr +krad_client_new +krad_client_free +krad_client_send diff --git a/krb5-1.21.3/src/lib/krad/packet.c b/krb5-1.21.3/src/lib/krad/packet.c new file mode 100644 index 00000000..c597174b --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/packet.c @@ -0,0 +1,470 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/packet.c - Packet functions for libkrad */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include "internal.h" + +#include + +#include + +typedef unsigned char uchar; + +/* RFC 2865 */ +#define OFFSET_CODE 0 +#define OFFSET_ID 1 +#define OFFSET_LENGTH 2 +#define OFFSET_AUTH 4 +#define OFFSET_ATTR 20 +#define AUTH_FIELD_SIZE (OFFSET_ATTR - OFFSET_AUTH) + +#define offset(d, o) (&(d)->data[o]) +#define pkt_code_get(p) (*(krad_code *)offset(&(p)->pkt, OFFSET_CODE)) +#define pkt_code_set(p, v) (*(krad_code *)offset(&(p)->pkt, OFFSET_CODE)) = v +#define pkt_id_get(p) (*(uchar *)offset(&(p)->pkt, OFFSET_ID)) +#define pkt_id_set(p, v) (*(uchar *)offset(&(p)->pkt, OFFSET_ID)) = v +#define pkt_len_get(p) load_16_be(offset(&(p)->pkt, OFFSET_LENGTH)) +#define pkt_len_set(p, v) store_16_be(v, offset(&(p)->pkt, OFFSET_LENGTH)) +#define pkt_auth(p) ((uchar *)offset(&(p)->pkt, OFFSET_AUTH)) +#define pkt_attr(p) ((unsigned char *)offset(&(p)->pkt, OFFSET_ATTR)) + +struct krad_packet_st { + char buffer[KRAD_PACKET_SIZE_MAX]; + krad_attrset *attrset; + krb5_data pkt; +}; + +typedef struct { + uchar x[(UCHAR_MAX + 1) / 8]; +} idmap; + +/* Ensure the map is empty. */ +static inline void +idmap_init(idmap *map) +{ + memset(map, 0, sizeof(*map)); +} + +/* Set an id as already allocated. */ +static inline void +idmap_set(idmap *map, uchar id) +{ + map->x[id / 8] |= 1 << (id % 8); +} + +/* Determine whether or not an id is used. */ +static inline krb5_boolean +idmap_isset(const idmap *map, uchar id) +{ + return (map->x[id / 8] & (1 << (id % 8))) != 0; +} + +/* Find an unused id starting the search at the value specified in id. + * NOTE: For optimal security, the initial value of id should be random. */ +static inline krb5_error_code +idmap_find(const idmap *map, uchar *id) +{ + krb5_int16 i; + + for (i = *id; i >= 0 && i <= UCHAR_MAX; (*id % 2 == 0) ? i++ : i--) { + if (!idmap_isset(map, i)) + goto success; + } + + for (i = *id; i >= 0 && i <= UCHAR_MAX; (*id % 2 == 1) ? i++ : i--) { + if (!idmap_isset(map, i)) + goto success; + } + + return ERANGE; + +success: + *id = i; + return 0; +} + +/* Generate size bytes of random data into the buffer. */ +static inline krb5_error_code +randomize(krb5_context ctx, void *buffer, unsigned int size) +{ + krb5_data rdata = make_data(buffer, size); + return krb5_c_random_make_octets(ctx, &rdata); +} + +/* Generate a radius packet id. */ +static krb5_error_code +id_generate(krb5_context ctx, krad_packet_iter_cb cb, void *data, uchar *id) +{ + krb5_error_code retval; + const krad_packet *tmp; + idmap used; + uchar i; + + retval = randomize(ctx, &i, sizeof(i)); + if (retval != 0) { + if (cb != NULL) + (*cb)(data, TRUE); + return retval; + } + + if (cb != NULL) { + idmap_init(&used); + for (tmp = (*cb)(data, FALSE); tmp != NULL; tmp = (*cb)(data, FALSE)) + idmap_set(&used, tmp->pkt.data[1]); + + retval = idmap_find(&used, &i); + if (retval != 0) + return retval; + } + + *id = i; + return 0; +} + +/* Generate a random authenticator field. */ +static krb5_error_code +auth_generate_random(krb5_context ctx, uchar *rauth) +{ + krb5_ui_4 trunctime; + time_t currtime; + + /* Get the least-significant four bytes of the current time. */ + currtime = time(NULL); + if (currtime == (time_t)-1) + return errno; + trunctime = (krb5_ui_4)currtime; + memcpy(rauth, &trunctime, sizeof(trunctime)); + + /* Randomize the rest of the buffer. */ + return randomize(ctx, rauth + sizeof(trunctime), + AUTH_FIELD_SIZE - sizeof(trunctime)); +} + +/* Generate a response authenticator field. */ +static krb5_error_code +auth_generate_response(krb5_context ctx, const char *secret, + const krad_packet *response, const uchar *auth, + uchar *rauth) +{ + krb5_error_code retval; + krb5_checksum hash; + krb5_data data; + + /* Allocate the temporary buffer. */ + retval = alloc_data(&data, response->pkt.length + strlen(secret)); + if (retval != 0) + return retval; + + /* Encoded RADIUS packet with the request's + * authenticator and the secret at the end. */ + memcpy(data.data, response->pkt.data, response->pkt.length); + memcpy(data.data + OFFSET_AUTH, auth, AUTH_FIELD_SIZE); + memcpy(data.data + response->pkt.length, secret, strlen(secret)); + + /* Hash it. */ + retval = krb5_c_make_checksum(ctx, CKSUMTYPE_RSA_MD5, NULL, 0, &data, + &hash); + free(data.data); + if (retval != 0) + return retval; + + memcpy(rauth, hash.contents, AUTH_FIELD_SIZE); + krb5_free_checksum_contents(ctx, &hash); + return 0; +} + +/* Create a new packet. */ +static krad_packet * +packet_new() +{ + krad_packet *pkt; + + pkt = calloc(1, sizeof(krad_packet)); + if (pkt == NULL) + return NULL; + pkt->pkt = make_data(pkt->buffer, sizeof(pkt->buffer)); + + return pkt; +} + +/* Set the attrset object by decoding the packet. */ +static krb5_error_code +packet_set_attrset(krb5_context ctx, const char *secret, krad_packet *pkt) +{ + krb5_data tmp; + + tmp = make_data(pkt_attr(pkt), pkt->pkt.length - OFFSET_ATTR); + return kr_attrset_decode(ctx, &tmp, secret, pkt_auth(pkt), &pkt->attrset); +} + +ssize_t +krad_packet_bytes_needed(const krb5_data *buffer) +{ + size_t len; + + if (buffer->length < OFFSET_AUTH) + return OFFSET_AUTH - buffer->length; + + len = load_16_be(offset(buffer, OFFSET_LENGTH)); + if (len > KRAD_PACKET_SIZE_MAX) + return -1; + + return (buffer->length > len) ? 0 : len - buffer->length; +} + +void +krad_packet_free(krad_packet *pkt) +{ + if (pkt) + krad_attrset_free(pkt->attrset); + free(pkt); +} + +/* Create a new request packet. */ +krb5_error_code +krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code, + const krad_attrset *set, krad_packet_iter_cb cb, + void *data, krad_packet **request) +{ + krb5_error_code retval; + krad_packet *pkt; + uchar id; + size_t attrset_len; + + pkt = packet_new(); + if (pkt == NULL) { + if (cb != NULL) + (*cb)(data, TRUE); + return ENOMEM; + } + + /* Generate the ID. */ + retval = id_generate(ctx, cb, data, &id); + if (retval != 0) + goto error; + pkt_id_set(pkt, id); + + /* Generate the authenticator. */ + retval = auth_generate_random(ctx, pkt_auth(pkt)); + if (retval != 0) + goto error; + + /* Encode the attributes. */ + retval = kr_attrset_encode(set, secret, pkt_auth(pkt), pkt_attr(pkt), + &attrset_len); + if (retval != 0) + goto error; + + /* Set the code, ID and length. */ + pkt->pkt.length = attrset_len + OFFSET_ATTR; + pkt_code_set(pkt, code); + pkt_len_set(pkt, pkt->pkt.length); + + /* Copy the attrset for future use. */ + retval = packet_set_attrset(ctx, secret, pkt); + if (retval != 0) + goto error; + + *request = pkt; + return 0; + +error: + free(pkt); + return retval; +} + +/* Create a new request packet. */ +krb5_error_code +krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code, + const krad_attrset *set, const krad_packet *request, + krad_packet **response) +{ + krb5_error_code retval; + krad_packet *pkt; + size_t attrset_len; + + pkt = packet_new(); + if (pkt == NULL) + return ENOMEM; + + /* Encode the attributes. */ + retval = kr_attrset_encode(set, secret, pkt_auth(request), pkt_attr(pkt), + &attrset_len); + if (retval != 0) + goto error; + + /* Set the code, ID and length. */ + pkt->pkt.length = attrset_len + OFFSET_ATTR; + pkt_code_set(pkt, code); + pkt_id_set(pkt, pkt_id_get(request)); + pkt_len_set(pkt, pkt->pkt.length); + + /* Generate the authenticator. */ + retval = auth_generate_response(ctx, secret, pkt, pkt_auth(request), + pkt_auth(pkt)); + if (retval != 0) + goto error; + + /* Copy the attrset for future use. */ + retval = packet_set_attrset(ctx, secret, pkt); + if (retval != 0) + goto error; + + *response = pkt; + return 0; + +error: + free(pkt); + return retval; +} + +/* Decode a packet. */ +static krb5_error_code +decode_packet(krb5_context ctx, const char *secret, const krb5_data *buffer, + krad_packet **pkt) +{ + krb5_error_code retval; + krad_packet *tmp; + krb5_ui_2 len; + + tmp = packet_new(); + if (tmp == NULL) { + retval = ENOMEM; + goto error; + } + + /* Ensure a proper message length. */ + retval = (buffer->length < OFFSET_ATTR) ? EMSGSIZE : 0; + if (retval != 0) + goto error; + len = load_16_be(offset(buffer, OFFSET_LENGTH)); + retval = (len < OFFSET_ATTR) ? EBADMSG : 0; + if (retval != 0) + goto error; + retval = (len > buffer->length || len > tmp->pkt.length) ? EBADMSG : 0; + if (retval != 0) + goto error; + + /* Copy over the buffer. */ + tmp->pkt.length = len; + memcpy(tmp->pkt.data, buffer->data, len); + + /* Parse the packet to ensure it is well-formed. */ + retval = packet_set_attrset(ctx, secret, tmp); + if (retval != 0) + goto error; + + *pkt = tmp; + return 0; + +error: + krad_packet_free(tmp); + return retval; +} + +krb5_error_code +krad_packet_decode_request(krb5_context ctx, const char *secret, + const krb5_data *buffer, krad_packet_iter_cb cb, + void *data, const krad_packet **duppkt, + krad_packet **reqpkt) +{ + const krad_packet *tmp = NULL; + krb5_error_code retval; + + retval = decode_packet(ctx, secret, buffer, reqpkt); + if (cb != NULL && retval == 0) { + for (tmp = (*cb)(data, FALSE); tmp != NULL; tmp = (*cb)(data, FALSE)) { + if (pkt_id_get(*reqpkt) == pkt_id_get(tmp)) + break; + } + } + + if (cb != NULL && (retval != 0 || tmp != NULL)) + (*cb)(data, TRUE); + + *duppkt = tmp; + return retval; +} + +krb5_error_code +krad_packet_decode_response(krb5_context ctx, const char *secret, + const krb5_data *buffer, krad_packet_iter_cb cb, + void *data, const krad_packet **reqpkt, + krad_packet **rsppkt) +{ + uchar auth[AUTH_FIELD_SIZE]; + const krad_packet *tmp = NULL; + krb5_error_code retval; + + retval = decode_packet(ctx, secret, buffer, rsppkt); + if (cb != NULL && retval == 0) { + for (tmp = (*cb)(data, FALSE); tmp != NULL; tmp = (*cb)(data, FALSE)) { + if (pkt_id_get(*rsppkt) != pkt_id_get(tmp)) + continue; + + /* Response */ + retval = auth_generate_response(ctx, secret, *rsppkt, + pkt_auth(tmp), auth); + if (retval != 0) { + krad_packet_free(*rsppkt); + break; + } + + /* If the authenticator matches, then the response is valid. */ + if (memcmp(pkt_auth(*rsppkt), auth, sizeof(auth)) == 0) + break; + } + } + + if (cb != NULL && (retval != 0 || tmp != NULL)) + (*cb)(data, TRUE); + + *reqpkt = tmp; + return retval; +} + +const krb5_data * +krad_packet_encode(const krad_packet *pkt) +{ + return &pkt->pkt; +} + +krad_code +krad_packet_get_code(const krad_packet *pkt) +{ + if (pkt == NULL) + return 0; + + return pkt_code_get(pkt); +} + +const krb5_data * +krad_packet_get_attr(const krad_packet *pkt, krad_attr type, size_t indx) +{ + return krad_attrset_get(pkt->attrset, type, indx); +} diff --git a/krb5-1.21.3/src/lib/krad/remote.c b/krb5-1.21.3/src/lib/krad/remote.c new file mode 100644 index 00000000..06ae751b --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/remote.c @@ -0,0 +1,541 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/remote.c - Protocol code for libkrad */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include +#include +#include "internal.h" + +#include +#include + +#include + +#define FLAGS_NONE VERTO_EV_FLAG_NONE +#define FLAGS_READ VERTO_EV_FLAG_IO_READ +#define FLAGS_WRITE VERTO_EV_FLAG_IO_WRITE +#define FLAGS_BASE VERTO_EV_FLAG_PERSIST | VERTO_EV_FLAG_IO_ERROR + +K5_TAILQ_HEAD(request_head, request_st); + +typedef struct request_st request; +struct request_st { + K5_TAILQ_ENTRY(request_st) list; + krad_remote *rr; + krad_packet *request; + krad_cb cb; + void *data; + verto_ev *timer; + int timeout; + size_t retries; + size_t sent; +}; + +struct krad_remote_st { + krb5_context kctx; + verto_ctx *vctx; + int fd; + verto_ev *io; + char *secret; + struct addrinfo *info; + struct request_head list; + char buffer_[KRAD_PACKET_SIZE_MAX]; + krb5_data buffer; +}; + +static void +on_io(verto_ctx *ctx, verto_ev *ev); + +static void +on_timeout(verto_ctx *ctx, verto_ev *ev); + +/* Iterate over the set of outstanding packets. */ +static const krad_packet * +iterator(request **out) +{ + request *tmp = *out; + + if (tmp == NULL) + return NULL; + + *out = K5_TAILQ_NEXT(tmp, list); + return tmp->request; +} + +/* Create a new request. */ +static krb5_error_code +request_new(krad_remote *rr, krad_packet *rqst, int timeout, size_t retries, + krad_cb cb, void *data, request **out) +{ + request *tmp; + + tmp = calloc(1, sizeof(request)); + if (tmp == NULL) + return ENOMEM; + + tmp->rr = rr; + tmp->request = rqst; + tmp->cb = cb; + tmp->data = data; + tmp->timeout = timeout; + tmp->retries = retries; + + *out = tmp; + return 0; +} + +/* Finish a request, calling the callback and freeing it. */ +static inline void +request_finish(request *req, krb5_error_code retval, + const krad_packet *response) +{ + if (retval != ETIMEDOUT) + K5_TAILQ_REMOVE(&req->rr->list, req, list); + + req->cb(retval, req->request, response, req->data); + + if (retval != ETIMEDOUT) { + krad_packet_free(req->request); + verto_del(req->timer); + free(req); + } +} + +/* Start the timeout timer for the request. */ +static krb5_error_code +request_start_timer(request *r, verto_ctx *vctx) +{ + verto_del(r->timer); + + r->timer = verto_add_timeout(vctx, VERTO_EV_FLAG_NONE, on_timeout, + r->timeout); + if (r->timer != NULL) + verto_set_private(r->timer, r, NULL); + + return (r->timer == NULL) ? ENOMEM : 0; +} + +/* Disconnect from the remote host. */ +static void +remote_disconnect(krad_remote *rr) +{ + if (rr->fd >= 0) + close(rr->fd); + verto_del(rr->io); + rr->fd = -1; + rr->io = NULL; +} + +/* Add the specified flags to the remote. This automatically manages the + * lifecycle of the underlying event. Also connects if disconnected. */ +static krb5_error_code +remote_add_flags(krad_remote *remote, verto_ev_flag flags) +{ + verto_ev_flag curflags = VERTO_EV_FLAG_NONE; + int i; + + flags &= (FLAGS_READ | FLAGS_WRITE); + if (remote == NULL || flags == FLAGS_NONE) + return EINVAL; + + /* If there is no connection, connect. */ + if (remote->fd < 0) { + verto_del(remote->io); + remote->io = NULL; + + remote->fd = socket(remote->info->ai_family, remote->info->ai_socktype, + remote->info->ai_protocol); + if (remote->fd < 0) + return errno; + + i = connect(remote->fd, remote->info->ai_addr, + remote->info->ai_addrlen); + if (i < 0) { + i = errno; + remote_disconnect(remote); + return i; + } + } + + if (remote->io == NULL) { + remote->io = verto_add_io(remote->vctx, FLAGS_BASE | flags, + on_io, remote->fd); + if (remote->io == NULL) + return ENOMEM; + verto_set_private(remote->io, remote, NULL); + } + + curflags = verto_get_flags(remote->io); + if ((curflags & flags) != flags) + verto_set_flags(remote->io, FLAGS_BASE | curflags | flags); + + return 0; +} + +/* Remove the specified flags to the remote. This automatically manages the + * lifecycle of the underlying event. */ +static void +remote_del_flags(krad_remote *remote, verto_ev_flag flags) +{ + if (remote == NULL || remote->io == NULL) + return; + + flags = verto_get_flags(remote->io) & (FLAGS_READ | FLAGS_WRITE) & ~flags; + if (flags == FLAGS_NONE) { + verto_del(remote->io); + remote->io = NULL; + return; + } + + verto_set_flags(remote->io, FLAGS_BASE | flags); +} + +/* Close the connection and start the timers of all outstanding requests. */ +static void +remote_shutdown(krad_remote *rr) +{ + krb5_error_code retval; + request *r, *next; + + remote_disconnect(rr); + + /* Start timers for all unsent packets. */ + K5_TAILQ_FOREACH_SAFE(r, &rr->list, list, next) { + if (r->timer == NULL) { + retval = request_start_timer(r, rr->vctx); + if (retval != 0) + request_finish(r, retval, NULL); + } + } +} + +/* Handle when packets receive no response within their allotted time. */ +static void +on_timeout(verto_ctx *ctx, verto_ev *ev) +{ + request *req = verto_get_private(ev); + krb5_error_code retval = ETIMEDOUT; + + req->timer = NULL; /* Void the timer event. */ + + /* If we have more retries to perform, resend the packet. */ + if (req->retries-- > 0) { + req->sent = 0; + retval = remote_add_flags(req->rr, FLAGS_WRITE); + if (retval == 0) + return; + } + + request_finish(req, retval, NULL); +} + +/* Write data to the socket. */ +static void +on_io_write(krad_remote *rr) +{ + const krb5_data *tmp; + ssize_t written; + request *r; + + K5_TAILQ_FOREACH(r, &rr->list, list) { + tmp = krad_packet_encode(r->request); + + /* If the packet has already been sent, do nothing. */ + if (r->sent == tmp->length) + continue; + + /* Send the packet. */ + written = sendto(verto_get_fd(rr->io), tmp->data + r->sent, + tmp->length - r->sent, 0, NULL, 0); + if (written < 0) { + /* Should we try again? */ + if (errno == EWOULDBLOCK || errno == EAGAIN || errno == ENOBUFS || + errno == EINTR) + return; + + /* This error can't be worked around. */ + remote_shutdown(rr); + return; + } + + /* If the packet was completely sent, set a timeout. */ + r->sent += written; + if (r->sent == tmp->length) { + if (request_start_timer(r, rr->vctx) != 0) { + request_finish(r, ENOMEM, NULL); + return; + } + + if (remote_add_flags(rr, FLAGS_READ) != 0) { + remote_shutdown(rr); + return; + } + } + + return; + } + + remote_del_flags(rr, FLAGS_WRITE); + return; +} + +/* Read data from the socket. */ +static void +on_io_read(krad_remote *rr) +{ + const krad_packet *req = NULL; + krad_packet *rsp = NULL; + krb5_error_code retval; + ssize_t pktlen; + request *tmp, *r; + int i; + + pktlen = sizeof(rr->buffer_) - rr->buffer.length; + if (rr->info->ai_socktype == SOCK_STREAM) { + pktlen = krad_packet_bytes_needed(&rr->buffer); + if (pktlen < 0) { + /* If we received a malformed packet on a stream socket, + * assume the socket to be unrecoverable. */ + remote_shutdown(rr); + return; + } + } + + /* Read the packet. */ + i = recv(verto_get_fd(rr->io), rr->buffer.data + rr->buffer.length, + pktlen, 0); + + /* On these errors, try again. */ + if (i < 0 && (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR)) + return; + + /* On any other errors or on EOF, the socket is unrecoverable. */ + if (i <= 0) { + remote_shutdown(rr); + return; + } + + /* If we have a partial read or just the header, try again. */ + rr->buffer.length += i; + pktlen = krad_packet_bytes_needed(&rr->buffer); + if (rr->info->ai_socktype == SOCK_STREAM && pktlen > 0) + return; + + /* Decode the packet. */ + tmp = K5_TAILQ_FIRST(&rr->list); + retval = krad_packet_decode_response(rr->kctx, rr->secret, &rr->buffer, + (krad_packet_iter_cb)iterator, &tmp, + &req, &rsp); + rr->buffer.length = 0; + if (retval != 0) + return; + + /* Match the response with an outstanding request. */ + if (req != NULL) { + K5_TAILQ_FOREACH(r, &rr->list, list) { + if (r->request == req && + r->sent == krad_packet_encode(req)->length) { + request_finish(r, 0, rsp); + break; + } + } + } + + krad_packet_free(rsp); +} + +/* Handle when IO is ready on the socket. */ +static void +on_io(verto_ctx *ctx, verto_ev *ev) +{ + krad_remote *rr; + + rr = verto_get_private(ev); + + if (verto_get_fd_state(ev) & VERTO_EV_FLAG_IO_WRITE) + on_io_write(rr); + else + on_io_read(rr); +} + +krb5_error_code +kr_remote_new(krb5_context kctx, verto_ctx *vctx, const struct addrinfo *info, + const char *secret, krad_remote **rr) +{ + krb5_error_code retval = ENOMEM; + krad_remote *tmp = NULL; + + tmp = calloc(1, sizeof(krad_remote)); + if (tmp == NULL) + goto error; + tmp->kctx = kctx; + tmp->vctx = vctx; + tmp->buffer = make_data(tmp->buffer_, 0); + K5_TAILQ_INIT(&tmp->list); + tmp->fd = -1; + + tmp->secret = strdup(secret); + if (tmp->secret == NULL) + goto error; + + tmp->info = k5memdup(info, sizeof(*info), &retval); + if (tmp->info == NULL) + goto error; + + tmp->info->ai_addr = k5memdup(info->ai_addr, info->ai_addrlen, &retval); + if (tmp->info == NULL) + goto error; + tmp->info->ai_next = NULL; + tmp->info->ai_canonname = NULL; + + *rr = tmp; + return 0; + +error: + kr_remote_free(tmp); + return retval; +} + +void +kr_remote_cancel_all(krad_remote *rr) +{ + while (!K5_TAILQ_EMPTY(&rr->list)) + request_finish(K5_TAILQ_FIRST(&rr->list), ECANCELED, NULL); +} + +void +kr_remote_free(krad_remote *rr) +{ + if (rr == NULL) + return; + + kr_remote_cancel_all(rr); + free(rr->secret); + if (rr->info != NULL) + free(rr->info->ai_addr); + free(rr->info); + remote_disconnect(rr); + free(rr); +} + +krb5_error_code +kr_remote_send(krad_remote *rr, krad_code code, krad_attrset *attrs, + krad_cb cb, void *data, int timeout, size_t retries, + const krad_packet **pkt) +{ + krad_packet *tmp = NULL; + krb5_error_code retval; + request *r, *new_request = NULL; + + if (rr->info->ai_socktype == SOCK_STREAM) + retries = 0; + + r = K5_TAILQ_FIRST(&rr->list); + retval = krad_packet_new_request(rr->kctx, rr->secret, code, attrs, + (krad_packet_iter_cb)iterator, &r, &tmp); + if (retval != 0) + goto error; + + K5_TAILQ_FOREACH(r, &rr->list, list) { + if (r->request == tmp) { + retval = EALREADY; + goto error; + } + } + + timeout = timeout / (retries + 1); + retval = request_new(rr, tmp, timeout, retries, cb, data, &new_request); + if (retval != 0) + goto error; + + retval = remote_add_flags(rr, FLAGS_WRITE); + if (retval != 0) + goto error; + + K5_TAILQ_INSERT_TAIL(&rr->list, new_request, list); + if (pkt != NULL) + *pkt = tmp; + return 0; + +error: + free(new_request); + krad_packet_free(tmp); + return retval; +} + +void +kr_remote_cancel(krad_remote *rr, const krad_packet *pkt) +{ + request *r; + + K5_TAILQ_FOREACH(r, &rr->list, list) { + if (r->request == pkt) { + request_finish(r, ECANCELED, NULL); + return; + } + } +} + +krb5_boolean +kr_remote_equals(const krad_remote *rr, const struct addrinfo *info, + const char *secret) +{ + struct sockaddr_un *a, *b; + + if (strcmp(rr->secret, secret) != 0) + return FALSE; + + if (info->ai_addrlen != rr->info->ai_addrlen) + return FALSE; + + if (info->ai_family != rr->info->ai_family) + return FALSE; + + if (info->ai_socktype != rr->info->ai_socktype) + return FALSE; + + if (info->ai_protocol != rr->info->ai_protocol) + return FALSE; + + if (info->ai_flags != rr->info->ai_flags) + return FALSE; + + if (memcmp(rr->info->ai_addr, info->ai_addr, info->ai_addrlen) != 0) { + /* AF_UNIX fails the memcmp() test due to uninitialized bytes after the + * socket name. */ + if (info->ai_family != AF_UNIX) + return FALSE; + + a = (struct sockaddr_un *)info->ai_addr; + b = (struct sockaddr_un *)rr->info->ai_addr; + if (strncmp(a->sun_path, b->sun_path, sizeof(a->sun_path)) != 0) + return FALSE; + } + + return TRUE; +} diff --git a/krb5-1.21.3/src/lib/krad/t_attr.c b/krb5-1.21.3/src/lib/krad/t_attr.c new file mode 100644 index 00000000..eb2a780c --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/t_attr.c @@ -0,0 +1,89 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/t_attr.c - Attribute test program */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include "t_test.h" + +const static unsigned char encoded[] = { + 0xba, 0xfc, 0xed, 0x50, 0xe1, 0xeb, 0xa6, 0xc3, + 0xc1, 0x75, 0x20, 0xe9, 0x10, 0xce, 0xc2, 0xcb +}; + +const static unsigned char auth[] = { + 0xac, 0x9d, 0xc1, 0x62, 0x08, 0xc4, 0xc7, 0x8b, + 0xa1, 0x2f, 0x25, 0x0a, 0xc4, 0x1d, 0x36, 0x41 +}; + +int +main() +{ + unsigned char outbuf[MAX_ATTRSETSIZE]; + const char *decoded = "accept"; + const char *secret = "foo"; + krb5_error_code retval; + krb5_context ctx; + const char *tmp; + krb5_data in; + size_t len; + + noerror(krb5_init_context(&ctx)); + + /* Make sure User-Name is 1. */ + insist(krad_attr_name2num("User-Name") == 1); + + /* Make sure 2 is User-Password. */ + tmp = krad_attr_num2name(2); + insist(tmp != NULL); + insist(strcmp(tmp, "User-Password") == 0); + + /* Test decoding. */ + in = make_data((void *)encoded, sizeof(encoded)); + noerror(kr_attr_decode(ctx, secret, auth, + krad_attr_name2num("User-Password"), + &in, outbuf, &len)); + insist(len == strlen(decoded)); + insist(memcmp(outbuf, decoded, len) == 0); + + /* Test encoding. */ + in = string2data((char *)decoded); + retval = kr_attr_encode(ctx, secret, auth, + krad_attr_name2num("User-Password"), + &in, outbuf, &len); + insist(retval == 0); + insist(len == sizeof(encoded)); + insist(memcmp(outbuf, encoded, len) == 0); + + /* Test constraint. */ + in.length = 100; + insist(kr_attr_valid(krad_attr_name2num("User-Password"), &in) == 0); + in.length = 200; + insist(kr_attr_valid(krad_attr_name2num("User-Password"), &in) != 0); + + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krad/t_attrset.c b/krb5-1.21.3/src/lib/krad/t_attrset.c new file mode 100644 index 00000000..7928335c --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/t_attrset.c @@ -0,0 +1,98 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/t_attrset.c - Attribute set test program */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include "t_test.h" + +const static unsigned char auth[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const static unsigned char encpass[] = { + 0x58, 0x8d, 0xff, 0xda, 0x37, 0xf9, 0xe4, 0xca, + 0x19, 0xae, 0x49, 0xb7, 0x16, 0x6d, 0x58, 0x27 +}; + +int +main() +{ + unsigned char buffer[KRAD_PACKET_SIZE_MAX], encoded[MAX_ATTRSETSIZE]; + const char *username = "testUser", *password = "accept"; + const krb5_data *tmpp; + krad_attrset *set; + krb5_context ctx; + size_t len = 0, encode_len; + krb5_data tmp; + + noerror(krb5_init_context(&ctx)); + noerror(krad_attrset_new(ctx, &set)); + + /* Add username. */ + tmp = string2data((char *)username); + noerror(krad_attrset_add(set, krad_attr_name2num("User-Name"), &tmp)); + + /* Add password. */ + tmp = string2data((char *)password); + noerror(krad_attrset_add(set, krad_attr_name2num("User-Password"), &tmp)); + + /* Encode attrset. */ + noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len)); + krad_attrset_free(set); + + /* Manually encode User-Name. */ + encoded[len + 0] = krad_attr_name2num("User-Name"); + encoded[len + 1] = strlen(username) + 2; + memcpy(encoded + len + 2, username, strlen(username)); + len += encoded[len + 1]; + + /* Manually encode User-Password. */ + encoded[len + 0] = krad_attr_name2num("User-Password"); + encoded[len + 1] = sizeof(encpass) + 2; + memcpy(encoded + len + 2, encpass, sizeof(encpass)); + len += encoded[len + 1]; + + /* Compare output. */ + insist(len == encode_len); + insist(memcmp(encoded, buffer, len) == 0); + + /* Decode output. */ + tmp = make_data(buffer, len); + noerror(kr_attrset_decode(ctx, &tmp, "foo", auth, &set)); + + /* Test getting an attribute. */ + tmp = string2data((char *)username); + tmpp = krad_attrset_get(set, krad_attr_name2num("User-Name"), 0); + insist(tmpp != NULL); + insist(tmpp->length == tmp.length); + insist(strncmp(tmpp->data, tmp.data, tmp.length) == 0); + + krad_attrset_free(set); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krad/t_client.c b/krb5-1.21.3/src/lib/krad/t_client.c new file mode 100644 index 00000000..3d0fda93 --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/t_client.c @@ -0,0 +1,126 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/t_client.c - Client request test program */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include "t_daemon.h" + +#define EVENT_COUNT 4 + +static struct +{ + int count; + struct event events[EVENT_COUNT]; +} record; + +static verto_ctx *vctx; + +static void +callback(krb5_error_code retval, const krad_packet *request, + const krad_packet *response, void *data) +{ + struct event *evt; + + evt = &record.events[record.count++]; + evt->error = retval != 0; + if (evt->error) + evt->result.retval = retval; + else + evt->result.code = krad_packet_get_code(response); + verto_break(vctx); +} + +int +main(int argc, const char **argv) +{ + krad_attrset *attrs; + krad_client *rc; + krb5_context kctx; + krb5_data tmp; + + if (!daemon_start(argc, argv)) { + fprintf(stderr, "Unable to start pyrad daemon, skipping test...\n"); + return 0; + } + + noerror(krb5_init_context(&kctx)); + vctx = verto_new(NULL, VERTO_EV_TYPE_IO | VERTO_EV_TYPE_TIMEOUT); + insist(vctx != NULL); + noerror(krad_client_new(kctx, vctx, &rc)); + + tmp = string2data("testUser"); + noerror(krad_attrset_new(kctx, &attrs)); + noerror(krad_attrset_add(attrs, krad_attr_name2num("User-Name"), &tmp)); + + /* Test accept. */ + tmp = string2data("accept"); + noerror(krad_attrset_add(attrs, krad_attr_name2num("User-Password"), + &tmp)); + noerror(krad_client_send(rc, krad_code_name2num("Access-Request"), attrs, + "localhost", "foo", 1000, 3, callback, NULL)); + verto_run(vctx); + + /* Test reject. */ + tmp = string2data("reject"); + krad_attrset_del(attrs, krad_attr_name2num("User-Password"), 0); + noerror(krad_attrset_add(attrs, krad_attr_name2num("User-Password"), + &tmp)); + noerror(krad_client_send(rc, krad_code_name2num("Access-Request"), attrs, + "localhost", "foo", 1000, 3, callback, NULL)); + verto_run(vctx); + + /* Test timeout. */ + daemon_stop(); + noerror(krad_client_send(rc, krad_code_name2num("Access-Request"), attrs, + "localhost", "foo", 1000, 3, callback, NULL)); + verto_run(vctx); + + /* Test outstanding packet freeing. */ + noerror(krad_client_send(rc, krad_code_name2num("Access-Request"), attrs, + "localhost", "foo", 1000, 3, callback, NULL)); + krad_client_free(rc); + rc = NULL; + + /* Verify the results. */ + insist(record.count == EVENT_COUNT); + insist(record.events[0].error == FALSE); + insist(record.events[0].result.code == + krad_code_name2num("Access-Accept")); + insist(record.events[1].error == FALSE); + insist(record.events[1].result.code == + krad_code_name2num("Access-Reject")); + insist(record.events[2].error == TRUE); + insist(record.events[2].result.retval == ETIMEDOUT); + insist(record.events[3].error == TRUE); + insist(record.events[3].result.retval == ECANCELED); + + krad_attrset_free(attrs); + krad_client_free(rc); + verto_free(vctx); + krb5_free_context(kctx); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krad/t_code.c b/krb5-1.21.3/src/lib/krad/t_code.c new file mode 100644 index 00000000..b245a7ef --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/t_code.c @@ -0,0 +1,54 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/t_code.c - RADIUS code table test program */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include "t_test.h" + +int +main() +{ + const char *tmp; + + insist(krad_code_name2num("Access-Request") == 1); + insist(krad_code_name2num("Access-Accept") == 2); + insist(krad_code_name2num("Access-Reject") == 3); + + tmp = krad_code_num2name(1); + insist(tmp != NULL); + insist(strcmp(tmp, "Access-Request") == 0); + + tmp = krad_code_num2name(2); + insist(tmp != NULL); + insist(strcmp(tmp, "Access-Accept") == 0); + + tmp = krad_code_num2name(3); + insist(tmp != NULL); + insist(strcmp(tmp, "Access-Reject") == 0); + + return 0; +} diff --git a/krb5-1.21.3/src/lib/krad/t_daemon.h b/krb5-1.21.3/src/lib/krad/t_daemon.h new file mode 100644 index 00000000..cbcb1325 --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/t_daemon.h @@ -0,0 +1,85 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/t_daemon.h - Daemonization helper for RADIUS test programs */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#ifndef T_DAEMON_H_ +#define T_DAEMON_H_ + +#include "t_test.h" +#include +#include +#include +#include + +static pid_t daemon_pid; + +static void +daemon_stop(void) +{ + if (daemon_pid == 0) + return; + kill(daemon_pid, SIGTERM); + waitpid(daemon_pid, NULL, 0); + daemon_pid = 0; +} + +static krb5_boolean +daemon_start(int argc, const char **argv) +{ + int fds[2]; + char buf[1]; + + if (argc != 3 || argv == NULL) + return FALSE; + + if (daemon_pid != 0) + return TRUE; + + if (pipe(fds) != 0) + return FALSE; + + /* Start the child process with the write end of the pipe as stdout. */ + daemon_pid = fork(); + if (daemon_pid == 0) { + dup2(fds[1], STDOUT_FILENO); + close(fds[0]); + close(fds[1]); + exit(execlp(argv[1], argv[1], argv[2], NULL)); + } + close(fds[1]); + + /* The child will write a sentinel character when it is listening. */ + if (read(fds[0], buf, 1) != 1 || *buf != '~') + return FALSE; + close(fds[0]); + + atexit(daemon_stop); + return TRUE; +} + +#endif /* T_DAEMON_H_ */ diff --git a/krb5-1.21.3/src/lib/krad/t_daemon.py b/krb5-1.21.3/src/lib/krad/t_daemon.py new file mode 100755 index 00000000..4a3de079 --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/t_daemon.py @@ -0,0 +1,71 @@ +# Copyright 2013 Red Hat, Inc. 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. +# +# 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. + +from io import StringIO +import os +import sys +import signal + +try: + from pyrad import dictionary, packet, server +except ImportError: + sys.stderr.write("pyrad not found!\n") + sys.exit(0) + +# We could use a dictionary file, but since we need +# such few attributes, we'll just include them here +DICTIONARY = """ +ATTRIBUTE\tUser-Name\t1\tstring +ATTRIBUTE\tUser-Password\t2\toctets +ATTRIBUTE\tNAS-Identifier\t32\tstring +""" + +class TestServer(server.Server): + def _HandleAuthPacket(self, pkt): + server.Server._HandleAuthPacket(self, pkt) + + passwd = [] + + for key in pkt.keys(): + if key == "User-Password": + passwd = [pkt.PwDecrypt(x) for x in pkt[key]] + + reply = self.CreateReplyPacket(pkt) + if passwd == ['accept']: + reply.code = packet.AccessAccept + else: + reply.code = packet.AccessReject + self.SendReplyPacket(pkt.fd, reply) + +srv = TestServer(addresses=["localhost"], + hosts={"127.0.0.1": + server.RemoteHost("127.0.0.1", b"foo", "localhost")}, + dict=dictionary.Dictionary(StringIO(DICTIONARY))) + +# Write a sentinel character to let the parent process know we're listening. +sys.stdout.write("~") +sys.stdout.flush() + +srv.Run() diff --git a/krb5-1.21.3/src/lib/krad/t_packet.c b/krb5-1.21.3/src/lib/krad/t_packet.c new file mode 100644 index 00000000..c2248914 --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/t_packet.c @@ -0,0 +1,207 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/t_packet.c - RADIUS packet test program */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include "t_daemon.h" + +#define ACCEPT_PACKET 0 +#define REJECT_PACKET 1 + +static krad_packet *packets[3]; + +static const krad_packet * +iterator(void *data, krb5_boolean cancel) +{ + krad_packet *tmp; + int *i = data; + + if (cancel || packets[*i] == NULL) + return NULL; + + tmp = packets[*i]; + *i += 1; + return tmp; +} + +static krb5_error_code +make_packet(krb5_context ctx, const krb5_data *username, + const krb5_data *password, krad_packet **pkt) +{ + krad_attrset *set = NULL; + krad_packet *tmp = NULL; + krb5_error_code retval; + const krb5_data *data; + int i = 0; + krb5_data nas_id; + + nas_id = string2data("12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "12345678901234567890123456789012345678901234567890" + "123"); + + retval = krad_attrset_new(ctx, &set); + if (retval != 0) + goto out; + + retval = krad_attrset_add(set, krad_attr_name2num("User-Name"), username); + if (retval != 0) + goto out; + + retval = krad_attrset_add(set, krad_attr_name2num("User-Password"), + password); + if (retval != 0) + goto out; + + retval = krad_attrset_add(set, krad_attr_name2num("NAS-Identifier"), + &nas_id); + if (retval != 0) + goto out; + + retval = krad_packet_new_request(ctx, "foo", + krad_code_name2num("Access-Request"), + set, iterator, &i, &tmp); + if (retval != 0) + goto out; + + data = krad_packet_get_attr(tmp, krad_attr_name2num("User-Name"), 0); + if (data == NULL) { + retval = ENOENT; + goto out; + } + + if (data->length != username->length || + memcmp(data->data, username->data, data->length) != 0) { + retval = EINVAL; + goto out; + } + + *pkt = tmp; + tmp = NULL; + +out: + krad_attrset_free(set); + krad_packet_free(tmp); + return retval; +} + +static krb5_error_code +do_auth(krb5_context ctx, struct addrinfo *ai, const char *secret, + const krad_packet *rqst, krb5_boolean *auth) +{ + const krad_packet *req = NULL; + char tmp[KRAD_PACKET_SIZE_MAX]; + const krb5_data *request; + krad_packet *rsp = NULL; + krb5_error_code retval; + krb5_data response; + int sock = -1, i; + + response = make_data(tmp, sizeof(tmp)); + + sock = socket(ai->ai_family, ai->ai_socktype, 0); + if (sock < 0) { + retval = errno; + goto out; + } + + request = krad_packet_encode(rqst); + if (sendto(sock, request->data, request->length, 0, ai->ai_addr, + ai->ai_addrlen) < 0) { + retval = errno; + goto out; + } + + i = recv(sock, response.data, sizeof(tmp), 0); + if (i < 0) { + retval = errno; + goto out; + } + response.length = i; + + i = 0; + retval = krad_packet_decode_response(ctx, secret, &response, iterator, &i, + &req, &rsp); + if (retval != 0) + goto out; + + if (req != rqst) { + retval = EBADMSG; + goto out; + } + + *auth = krad_packet_get_code(rsp) == krad_code_name2num("Access-Accept"); + +out: + krad_packet_free(rsp); + if (sock >= 0) + close(sock); + return retval; +} + +int +main(int argc, const char **argv) +{ + struct addrinfo *ai = NULL, hints; + krb5_data username, password; + krb5_boolean auth = FALSE; + krb5_context ctx; + + username = string2data("testUser"); + + if (!daemon_start(argc, argv)) { + fprintf(stderr, "Unable to start pyrad daemon, skipping test...\n"); + return 0; + } + + noerror(krb5_init_context(&ctx)); + + password = string2data("accept"); + noerror(make_packet(ctx, &username, &password, &packets[ACCEPT_PACKET])); + + password = string2data("reject"); + noerror(make_packet(ctx, &username, &password, &packets[REJECT_PACKET])); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + noerror(gai_error_code(getaddrinfo("127.0.0.1", "radius", &hints, &ai))); + + noerror(do_auth(ctx, ai, "foo", packets[ACCEPT_PACKET], &auth)); + insist(auth == TRUE); + + noerror(do_auth(ctx, ai, "foo", packets[REJECT_PACKET], &auth)); + insist(auth == FALSE); + + krad_packet_free(packets[ACCEPT_PACKET]); + krad_packet_free(packets[REJECT_PACKET]); + krb5_free_context(ctx); + freeaddrinfo(ai); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krad/t_remote.c b/krb5-1.21.3/src/lib/krad/t_remote.c new file mode 100644 index 00000000..a521ecb7 --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/t_remote.c @@ -0,0 +1,170 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/t_remote.c - Protocol test program */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include "t_daemon.h" + +#define EVENT_COUNT 6 + +static struct +{ + int count; + struct event events[EVENT_COUNT]; +} record; + +static krad_attrset *set; +static krad_remote *rr; +static verto_ctx *vctx; + +static void +callback(krb5_error_code retval, const krad_packet *request, + const krad_packet *response, void *data) +{ + struct event *evt; + + evt = &record.events[record.count++]; + evt->error = retval != 0; + if (evt->error) + evt->result.retval = retval; + else + evt->result.code = krad_packet_get_code(response); + verto_break(vctx); +} + +static void +remote_new(krb5_context kctx, krad_remote **remote) +{ + struct addrinfo *ai = NULL, hints; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + noerror(gai_error_code(getaddrinfo("127.0.0.1", "radius", &hints, &ai))); + + noerror(kr_remote_new(kctx, vctx, ai, "foo", remote)); + insist(kr_remote_equals(*remote, ai, "foo")); + freeaddrinfo(ai); +} + +static krb5_error_code +do_auth(const char *password, const krad_packet **pkt) +{ + const krad_packet *tmppkt; + krb5_error_code retval; + krb5_data tmp = string2data((char *)password); + + retval = krad_attrset_add(set, krad_attr_name2num("User-Password"), &tmp); + if (retval != 0) + return retval; + + retval = kr_remote_send(rr, krad_code_name2num("Access-Request"), set, + callback, NULL, 1000, 3, &tmppkt); + krad_attrset_del(set, krad_attr_name2num("User-Password"), 0); + if (retval != 0) + return retval; + + if (pkt != NULL) + *pkt = tmppkt; + return 0; +} + +static void +test_timeout(verto_ctx *ctx, verto_ev *ev) +{ + static const krad_packet *pkt; + + noerror(do_auth("accept", &pkt)); + kr_remote_cancel(rr, pkt); +} + +int +main(int argc, const char **argv) +{ + krb5_context kctx = NULL; + krb5_data tmp; + + if (!daemon_start(argc, argv)) { + fprintf(stderr, "Unable to start pyrad daemon, skipping test...\n"); + return 0; + } + + /* Initialize. */ + noerror(krb5_init_context(&kctx)); + vctx = verto_new(NULL, VERTO_EV_TYPE_IO | VERTO_EV_TYPE_TIMEOUT); + insist(vctx != NULL); + remote_new(kctx, &rr); + + /* Create attribute set. */ + noerror(krad_attrset_new(kctx, &set)); + tmp = string2data("testUser"); + noerror(krad_attrset_add(set, krad_attr_name2num("User-Name"), &tmp)); + + /* Send accept packet. */ + noerror(do_auth("accept", NULL)); + verto_run(vctx); + + /* Send reject packet. */ + noerror(do_auth("reject", NULL)); + verto_run(vctx); + + /* Send canceled packet. */ + insist(verto_add_timeout(vctx, VERTO_EV_FLAG_NONE, test_timeout, 0) != + NULL); + verto_run(vctx); + + /* Test timeout. */ + daemon_stop(); + noerror(do_auth("accept", NULL)); + verto_run(vctx); + + /* Test outstanding packet freeing. */ + noerror(do_auth("accept", NULL)); + kr_remote_free(rr); + krad_attrset_free(set); + + /* Verify the results. */ + insist(record.count == EVENT_COUNT); + insist(record.events[0].error == FALSE); + insist(record.events[0].result.code == + krad_code_name2num("Access-Accept")); + insist(record.events[1].error == FALSE); + insist(record.events[1].result.code == + krad_code_name2num("Access-Reject")); + insist(record.events[2].error == TRUE); + insist(record.events[2].result.retval == ECANCELED); + insist(record.events[3].error == TRUE); + insist(record.events[3].result.retval == ETIMEDOUT); + insist(record.events[4].error == TRUE); + insist(record.events[4].result.retval == ECANCELED); + insist(record.events[5].error == TRUE); + insist(record.events[5].result.retval == ECANCELED); + + verto_free(vctx); + krb5_free_context(kctx); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krad/t_test.c b/krb5-1.21.3/src/lib/krad/t_test.c new file mode 100644 index 00000000..152bc77c --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/t_test.c @@ -0,0 +1,50 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/t_test.c - Utility functions for libkrad tests */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include "t_test.h" + +void +noerror_impl(const char *file, int line, const char *cmd, int retval) +{ + if (retval == 0) + return; + + fprintf(stderr, "%s:%d: %s:\n\t%s\n", file, line, strerror(retval), cmd); + exit(1); +} + +void +insist_impl(const char *file, int line, const char *cmd, krb5_boolean result) +{ + if (result) + return; + + fprintf(stderr, "%s:%d: insist failed:\n\t%s\n", file, line, cmd); + exit(1); +} diff --git a/krb5-1.21.3/src/lib/krad/t_test.h b/krb5-1.21.3/src/lib/krad/t_test.h new file mode 100644 index 00000000..f44742f5 --- /dev/null +++ b/krb5-1.21.3/src/lib/krad/t_test.h @@ -0,0 +1,60 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krad/t_test.h - Shared declarations for libkrad test programs */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#ifndef T_TEST_H_ +#define T_TEST_H_ + +#include "internal.h" + +#include +#include +#include +#include +#include +#include + +#define insist(x) insist_impl(__FILE__, __LINE__, #x, x) +#define noerror(x) noerror_impl(__FILE__, __LINE__, #x, x) + +struct event { + krb5_boolean error; + union + { + krb5_error_code retval; + krad_code code; + } result; +}; + +void +noerror_impl(const char *file, int line, const char *cmd, int retval); + +void +insist_impl(const char *file, int line, const char *cmd, krb5_boolean result); + +#endif /* T_TEST_H_ */ diff --git a/krb5-1.21.3/src/lib/krb5.rc b/krb5-1.21.3/src/lib/krb5.rc new file mode 100644 index 00000000..f8e54002 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5.rc @@ -0,0 +1,44 @@ +/* + * lib/krb5/os/win-pwd.h + * + * Copyright 1997 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +#include "win-mac.h" + +ID_READ_PWD_DIALOG DIALOG 60, 72, 200, 84 +STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | + DS_SETFONT +CAPTION "Kerberos Password/Challenge" +FONT 8, "Helv" +{ + LTEXT "", ID_READ_PWD_PROMPT, 10, 8, 180, 10 + LTEXT "", ID_READ_PWD_PROMPT2, 10, 24, 180, 10 + EDITTEXT ID_READ_PWD_PWD, 10, 42, 180, 12, ES_AUTOHSCROLL | ES_PASSWORD | + WS_BORDER | WS_TABSTOP + DEFPUSHBUTTON "&OK", IDOK, 55, 61, 40, 14 + PUSHBUTTON "&Cancel", IDCANCEL, 107, 61, 40, 14 +} + +#include "..\windows\version.rc" diff --git a/krb5-1.21.3/src/lib/krb5/Makefile.in b/krb5-1.21.3/src/lib/krb5/Makefile.in new file mode 100644 index 00000000..1ed0cf34 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/Makefile.in @@ -0,0 +1,65 @@ +mydir=lib$(S)krb5 +BUILDTOP=$(REL)..$(S).. +LOCALINCLUDES = -I$(srcdir)/ccache -I$(srcdir)/keytab -I$(srcdir)/rcache -I$(srcdir)/os -I$(srcdir)/unicode +SUBDIRS= error_tables asn.1 ccache keytab krb os rcache unicode +WINSUBDIRS= $(SUBDIRS) posix +DEFINES=-DLOCALEDIR=\"$(KRB5_LOCALEDIR)\" + +##DOSBUILDTOP = ..\.. +##DOSLIBNAME=$(OUTPRE)krb5.lib +##DOSOBJFILEDEP=$(OUTPRE)asn1.lst $(OUTPRE)ccache.lst $(OUTPRE)err_tbls.lst $(OUTPRE)keytab.lst $(OUTPRE)krb.lst $(OUTPRE)os.lst $(OUTPRE)posix.lst $(OUTPRE)rcache.lst $(OUTPRE)krb5.lst $(OUTPRE)unicode.lst +##DOSOBJFILELIST=@$(OUTPRE)asn1.lst @$(OUTPRE)ccache.lst @$(OUTPRE)err_tbls.lst @$(OUTPRE)keytab.lst @$(OUTPRE)krb.lst @$(OUTPRE)os.lst @$(OUTPRE)posix.lst @$(OUTPRE)rcache.lst @$(OUTPRE)krb5.lst @$(OUTPRE)unicode.lst +##DOSOBJFILE=$(OUTPRE)krb5.lst +##DOSLIBOBJS=$(OBJS) +##DOSLOCALINCLUDES=-Iccache\ccapi -I..\..\windows\lib -Iccache -Ikeytab -Ircache -Ios + +TST=if test -n "`cat DONE`" ; then + +STLIBOBJS=krb5_libinit.o + +LIBBASE=krb5 +LIBMAJOR=3 +LIBMINOR=3 +LIBINITFUNC=profile_library_initializer krb5int_lib_init +LIBFINIFUNC=profile_library_finalizer krb5int_lib_fini + +SUBDIROBJLISTS= \ + error_tables/OBJS.ST \ + asn.1/OBJS.ST \ + ccache/OBJS.ST \ + keytab/OBJS.ST \ + krb/OBJS.ST \ + rcache/OBJS.ST \ + unicode/OBJS.ST \ + os/OBJS.ST \ + $(BUILDTOP)/util/profile/OBJS.ST + +STOBJLISTS= OBJS.ST $(SUBDIROBJLISTS) + +OBJS=\ + $(OUTPRE)krb5_libinit.$(OBJEXT) + +SRCS=\ + $(srcdir)/krb5_libinit.c + +RELDIR=krb5 +SHLIB_EXPDEPS = \ + $(TOPLIBD)/libk5crypto$(SHLIBEXT) \ + $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB) +SHLIB_EXPLIBS=-lk5crypto $(COM_ERR_LIB) $(SUPPORT_LIB) @GEN_LIB@ \ + @MACOS_FRAMEWORK@ $(LIBS) + +all-unix: all-liblinks + +all-windows: + +clean-unix:: clean-liblinks clean-libs clean-libobjs + +clean-windows:: + $(RM) $(OUTPRE)krb5.lib krb5.bak + +install-unix: install-libs + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/krb5/asn.1/KRB5-asn.py b/krb5-1.21.3/src/lib/krb5/asn.1/KRB5-asn.py new file mode 100644 index 00000000..e455fd9a --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/asn.1/KRB5-asn.py @@ -0,0 +1,436 @@ +-- lib/krb5/asn.1/KRB5-asn.py +-- +-- Copyright 1989 by the Massachusetts Institute of Technology. +-- +-- Export of this software from the United States of America may +-- require a specific license from the United States Government. +-- It is the responsibility of any person or organization contemplating +-- export to obtain such a license before exporting. +-- +-- WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +-- distribute this software and its documentation for any purpose and +-- without fee is hereby granted, provided that the above copyright +-- notice appear in all copies and that both that copyright notice and +-- this permission notice appear in supporting documentation, and that +-- the name of M.I.T. not be used in advertising or publicity pertaining +-- to distribution of the software without specific, written prior +-- permission. Furthermore if you modify this software you must label +-- your software as modified software and not distribute it in such a +-- fashion that it might be confused with the original M.I.T. software. +-- M.I.T. makes no representations about the suitability of +-- this software for any purpose. It is provided "as is" without express +-- or implied warranty. +-- +-- ASN.1 definitions for the kerberos network objects +-- +-- Do not change the order of any structure containing some +-- element_KRB5_xx unless the corresponding translation code is also +-- changed. +-- + +KRB5 DEFINITIONS ::= +BEGIN + +-- needed to do the Right Thing with pepsy; this isn't a valid ASN.1 +-- token, however. + +SECTIONS encode decode none + +-- the order of stuff in this file matches the order in the draft RFC + +Realm ::= GeneralString + +HostAddress ::= SEQUENCE { + addr-type[0] INTEGER, + address[1] OCTET STRING +} + +HostAddresses ::= SEQUENCE OF SEQUENCE { + addr-type[0] INTEGER, + address[1] OCTET STRING +} + +AuthorizationData ::= SEQUENCE OF SEQUENCE { + ad-type[0] INTEGER, + ad-data[1] OCTET STRING +} + +KDCOptions ::= BIT STRING { + reserved(0), + forwardable(1), + forwarded(2), + proxiable(3), + proxy(4), + allow-postdate(5), + postdated(6), + unused7(7), + renewable(8), + unused9(9), + renewable-ok(27), + enc-tkt-in-skey(28), + renew(30), + validate(31) +} + +LastReq ::= SEQUENCE OF SEQUENCE { + lr-type[0] INTEGER, + lr-value[1] KerberosTime +} + +KerberosTime ::= GeneralizedTime -- Specifying UTC time zone (Z) + +PrincipalName ::= SEQUENCE{ + name-type[0] INTEGER, + name-string[1] SEQUENCE OF GeneralString +} + +Ticket ::= [APPLICATION 1] SEQUENCE { + tkt-vno[0] INTEGER, + realm[1] Realm, + sname[2] PrincipalName, + enc-part[3] EncryptedData -- EncTicketPart +} + +TransitedEncoding ::= SEQUENCE { + tr-type[0] INTEGER, -- Only supported value is 1 == DOMAIN-COMPRESS + contents[1] OCTET STRING +} + +-- 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 +} + +-- Unencrypted authenticator +Authenticator ::= [APPLICATION 2] SEQUENCE { + authenticator-vno[0] INTEGER, + crealm[1] Realm, + cname[2] PrincipalName, + cksum[3] Checksum OPTIONAL, + cusec[4] INTEGER, + ctime[5] KerberosTime, + subkey[6] EncryptionKey OPTIONAL, + seq-number[7] INTEGER OPTIONAL, + authorization-data[8] AuthorizationData OPTIONAL +} + +TicketFlags ::= BIT STRING { + reserved(0), + forwardable(1), + forwarded(2), + proxiable(3), + proxy(4), + may-postdate(5), + postdated(6), + invalid(7), + renewable(8), + initial(9) +} + +AS-REQ ::= [APPLICATION 10] KDC-REQ +TGS-REQ ::= [APPLICATION 12] KDC-REQ + +KDC-REQ ::= SEQUENCE { + pvno[1] INTEGER, + msg-type[2] INTEGER, + padata[3] SEQUENCE OF PA-DATA OPTIONAL, + req-body[4] KDC-REQ-BODY +} + +PA-DATA ::= SEQUENCE { + padata-type[1] INTEGER, + pa-data[2] OCTET STRING -- might be encoded AP-REQ +} + +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] INTEGER, + etype[8] SEQUENCE OF INTEGER, -- EncryptionType, + -- in preference order + addresses[9] HostAddresses OPTIONAL, + enc-authorization-data[10] EncryptedData OPTIONAL, + -- AuthorizationData + additional-tickets[11] SEQUENCE OF Ticket OPTIONAL +} + +AS-REP ::= [APPLICATION 11] KDC-REP +TGS-REP ::= [APPLICATION 13] KDC-REP +KDC-REP ::= SEQUENCE { + pvno[0] INTEGER, + msg-type[1] INTEGER, + padata[2] SEQUENCE OF PA-DATA OPTIONAL, + crealm[3] Realm, + cname[4] PrincipalName, + ticket[5] Ticket, -- Ticket + enc-part[6] EncryptedData -- EncKDCRepPart +} + +EncASRepPart ::= [APPLICATION 25] EncKDCRepPart +EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart +EncKDCRepPart ::= SEQUENCE { + key[0] EncryptionKey, + last-req[1] LastReq, + nonce[2] INTEGER, + 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 +} + +AP-REQ ::= [APPLICATION 14] SEQUENCE { + pvno[0] INTEGER, + msg-type[1] INTEGER, + ap-options[2] APOptions, + ticket[3] Ticket, + authenticator[4] EncryptedData -- Authenticator +} + +APOptions ::= BIT STRING { + reserved(0), + use-session-key(1), + mutual-required(2) +} + +AP-REP ::= [APPLICATION 15] SEQUENCE { + pvno[0] INTEGER, + msg-type[1] INTEGER, + enc-part[2] EncryptedData -- EncAPRepPart +} + +EncAPRepPart ::= [APPLICATION 27] SEQUENCE { + ctime[0] KerberosTime, + cusec[1] INTEGER, + subkey[2] EncryptionKey OPTIONAL, + seq-number[3] INTEGER OPTIONAL +} + +KRB-SAFE ::= [APPLICATION 20] SEQUENCE { + pvno[0] INTEGER, + msg-type[1] INTEGER, + safe-body[2] KRB-SAFE-BODY, + cksum[3] Checksum +} + +KRB-SAFE-BODY ::= SEQUENCE { + user-data[0] OCTET STRING, + timestamp[1] KerberosTime OPTIONAL, + usec[2] INTEGER OPTIONAL, + seq-number[3] INTEGER OPTIONAL, + s-address[4] HostAddress, -- sender's addr + r-address[5] HostAddress OPTIONAL -- recip's addr +} + +KRB-PRIV ::= [APPLICATION 21] SEQUENCE { + pvno[0] INTEGER, + msg-type[1] INTEGER, + enc-part[3] EncryptedData -- EncKrbPrivPart +} + +EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE { + user-data[0] OCTET STRING, + timestamp[1] KerberosTime OPTIONAL, + usec[2] INTEGER OPTIONAL, + seq-number[3] INTEGER OPTIONAL, + s-address[4] HostAddress, -- sender's addr + r-address[5] HostAddress OPTIONAL -- recip's addr +} + +-- The KRB-CRED message allows easy forwarding of credentials. + +KRB-CRED ::= [APPLICATION 22] SEQUENCE { + pvno[0] INTEGER, + msg-type[1] INTEGER, -- KRB_CRED + tickets[2] SEQUENCE OF Ticket, + enc-part[3] EncryptedData -- EncKrbCredPart +} + +EncKrbCredPart ::= [APPLICATION 29] SEQUENCE { + ticket-info[0] SEQUENCE OF KRB-CRED-INFO, + nonce[1] INTEGER OPTIONAL, + timestamp[2] KerberosTime OPTIONAL, + usec[3] INTEGER OPTIONAL, + s-address[4] HostAddress OPTIONAL, + r-address[5] HostAddress OPTIONAL +} + +KRB-CRED-INFO ::= 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, + msg-type[1] INTEGER, + ctime[2] KerberosTime OPTIONAL, + cusec[3] INTEGER OPTIONAL, + stime[4] KerberosTime, + susec[5] INTEGER, + error-code[6] INTEGER, + crealm[7] Realm OPTIONAL, + cname[8] PrincipalName OPTIONAL, + realm[9] Realm, -- Correct realm + sname[10] PrincipalName, -- Correct name + e-text[11] GeneralString OPTIONAL, + e-data[12] OCTET STRING OPTIONAL +} + +EncryptedData ::= SEQUENCE { + etype[0] INTEGER, -- EncryptionType + kvno[1] INTEGER OPTIONAL, + cipher[2] OCTET STRING -- CipherText +} + +EncryptionKey ::= SEQUENCE { + keytype[0] INTEGER, + keyvalue[1] OCTET STRING +} + +Checksum ::= SEQUENCE { + cksumtype[0] INTEGER, + checksum[1] OCTET STRING +} + +METHOD-DATA ::= SEQUENCE { + method-type[0] INTEGER, + method-data[1] OCTET STRING OPTIONAL +} + +ETYPE-INFO-ENTRY ::= SEQUENCE { + etype[0] INTEGER, + salt[1] OCTET STRING OPTIONAL +} + +ETYPE-INFO ::= SEQUENCE OF ETYPE-INFO-ENTRY + +PA-ENC-TS-ENC ::= SEQUENCE { + patimestamp[0] KerberosTime, -- client's time + pausec[1] INTEGER OPTIONAL +} + +-- These ASN.1 definitions are NOT part of the official Kerberos protocol... + +-- New ASN.1 definitions for the kadmin protocol. +-- Originally contributed from the Sandia modifications + +PasswdSequence ::= SEQUENCE { + passwd[0] OCTET STRING, + phrase[1] OCTET STRING +} + +PasswdData ::= SEQUENCE { + passwd-sequence-count[0] INTEGER, + passwd-sequence[1] SEQUENCE OF PasswdSequence +} + +-- encodings from +-- Integrating Single-use Authentication Mechanisms with Kerberos + +PA-SAM-CHALLENGE ::= SEQUENCE { + sam-type[0] INTEGER, + sam-flags[1] SAMFlags, + sam-type-name[2] GeneralString OPTIONAL, + sam-track-id[3] GeneralString OPTIONAL, + sam-challenge-label[4] GeneralString OPTIONAL, + sam-challenge[5] GeneralString OPTIONAL, + sam-response-prompt[6] GeneralString OPTIONAL, + sam-pk-for-sad[7] OCTET STRING OPTIONAL, + sam-nonce[8] INTEGER OPTIONAL, + sam-cksum[9] Checksum OPTIONAL +} + +PA-SAM-CHALLENGE-2 ::= SEQUENCE { + sam-body[0] PA-SAM-CHALLENGE-2-BODY, + sam-cksum[1] SEQUENCE (1..MAX) OF Checksum, + ... +} + +PA-SAM-CHALLENGE-2-BODY ::= SEQUENCE { + sam-type[0] INTEGER, + sam-flags[1] SAMFlags, + sam-type-name[2] GeneralString OPTIONAL, + sam-track-id[3] GeneralString OPTIONAL, + sam-challenge-label[4] GeneralString OPTIONAL, + sam-challenge[5] GeneralString OPTIONAL, + sam-response-prompt[6] GeneralString OPTIONAL, + sam-pk-for-sad[7] EncryptionKey OPTIONAL, + sam-nonce[8] INTEGER, + sam-etype[9] INTEGER, + ... +} + +-- these are [0].. [2] in the draft +SAMFlags ::= BIT STRING (SIZE (32..MAX)) + -- use-sad-as-key(0) + -- send-encrypted-sad(1) + -- must-pk-encrypt-sad(2) + +PA-SAM-RESPONSE ::= SEQUENCE { + sam-type[0] INTEGER, + sam-flags[1] SAMFlags, + sam-track-id[2] GeneralString OPTIONAL, + -- sam-enc-key is reserved for future use, so I'm making it OPTIONAL - mwe + sam-enc-key[3] EncryptedData, + -- PA-ENC-SAM-KEY + sam-enc-nonce-or-ts[4] EncryptedData, + -- PA-ENC-SAM-RESPONSE-ENC + sam-nonce[5] INTEGER OPTIONAL, + sam-patimestamp[6] KerberosTime OPTIONAL +} + +PA-SAM-RESPONSE-2 ::= SEQUENCE { + sam-type[0] INTEGER, + sam-flags[1] SAMFlags, + sam-track-id[2] GeneralString OPTIONAL, + sam-enc-nonce-or-sad[3] EncryptedData, + -- PA-ENC-SAM-RESPONSE-ENC + sam-nonce[4] INTEGER, + ... +} + +PA-ENC-SAM-KEY ::= SEQUENCE { + sam-key[0] EncryptionKey +} + +PA-ENC-SAM-RESPONSE-ENC ::= SEQUENCE { + sam-nonce[0] INTEGER OPTIONAL, + sam-timestamp[1] KerberosTime OPTIONAL, + sam-usec[2] INTEGER OPTIONAL, + sam-passcode[3] GeneralString OPTIONAL +} + +PA-ENC-SAM-RESPONSE-ENC-2 ::= SEQUENCE { + sam-nonce[0] INTEGER, + sam-sad[1] GeneralString OPTIONAL, + ... +} +END diff --git a/krb5-1.21.3/src/lib/krb5/asn.1/Makefile.in b/krb5-1.21.3/src/lib/krb5/asn.1/Makefile.in new file mode 100644 index 00000000..fe295232 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/asn.1/Makefile.in @@ -0,0 +1,32 @@ +mydir=lib$(S)krb5$(S)asn.1 +BUILDTOP=$(REL)..$(S)..$(S).. + +##DOS##BUILDTOP = ..\..\.. +##DOS##PREFIXDIR=asn.1 +##DOS##OBJFILE=..\$(OUTPRE)asn1.lst + +EHDRDIR=$(BUILDTOP)/include/krb5/asn.1 + +STLIBOBJS= \ + asn1_encode.o\ + asn1_k_encode.o\ + ldap_key_seq.o + +SRCS= \ + $(srcdir)/asn1_encode.c\ + $(srcdir)/asn1_k_encode.c\ + $(srcdir)/ldap_key_seq.c + +OBJS= \ + $(OUTPRE)asn1_encode.$(OBJEXT)\ + $(OUTPRE)asn1_k_encode.$(OBJEXT)\ + $(OUTPRE)ldap_key_seq.$(OBJEXT) + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs + +clean-unix:: clean-libobjs + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/krb5/asn.1/README.asn1 b/krb5-1.21.3/src/lib/krb5/asn.1/README.asn1 new file mode 100644 index 00000000..4990eec4 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/asn.1/README.asn1 @@ -0,0 +1,572 @@ +These notes attempt to explain how to use the ASN.1 infrastructure to +add new ASN.1 types. ASN.1 is complicated and easy to get wrong, so +it is best to verify your results against another tool (such as asn1c) +if at all possible. These notes are up to date as of 2012-02-13. + +If you are trying to debug a problem that shows up in the ASN.1 +encoder or decoder, skip to the last section. + + +General +------- + +For the moment, a developer must hand-translate the ASN.1 module into +macro invocations that generate data structures used by the encoder +and decoder. Ideally we would have a tool to compile an ASN.1 module +(and probably some additional information about C identifier mappings) +and generate the macro invocations. + +Currently the ASN.1 infrastructure is not visible to applications or +plugins. For plugin modules shipped as part of the krb5 tree, the +types can be added to asn1_k_encode.c and exported from libkrb5. +Plugin modules built separately from the krb5 tree must use another +tool (such as asn1c) for now if they need to do ASN.1 encoding or +decoding. + + +Tags +---- + +Before you start writing macro invocations, it is important to +understand a little bit about ASN.1 tags. You will most commonly see +tag notation in a sequence definition, like: + + TypeName ::= SEQUENCE { + field-name [0] IMPLICIT OCTET STRING OPTIONAL + } + +Contrary to intuition, the tag notation "[0] IMPLICIT" is not a +property of the sequence field; instead, it specifies a type that +wraps the type to the right (OCTET STRING). The right way to think +about the above definition is: + + TypeName is defined as a sequence type + which has an optional field named field-name + whose type is a tagged type + the tag's class is context-specific (by default) + the tag's number is 0 + it is an implicit tag + the tagged type wraps OCTET STRING + +The other case you are likely to see tag notation is something like: + + AS-REQ ::= [APPLICATION 10] KDC-REQ + +This example defines AS-REQ to be a tagged type whose class is +application, whose tag number is 10, and whose base type is KDC-REQ. +The tag may be implicit or explicit depending on the module's tag +environment, which we will get to in a moment. + +Tags can have one of four classes: universal, application, private, +and context-specific. Universal tags are used for built-in ASN.1 +types. Application and context-specific tags are the most common to +see in ASN.1 modules; private is rarely used. If no tag class is +specified, the default is context-specific. + +Tags can be explicit or implicit, and the distinction is important to +the wire encoding. If a tag's closing bracket is followed by the word +IMPLICIT or EXPLICIT, then it is clear which kind of tag it is, but +usually there will be no such annotation. If not, the default depends +on the header of the ASN.1 module. Look at the top of the module for +the word DEFINITIONS. It may be followed by one of three phrases: + +* EXPLICIT TAGS -- in this case, tags default to explicit +* IMPLICIT TAGS -- in this case, tags default to implicit (usually) +* AUTOMATIC TAGS -- tags default to implicit (usually) and are also + automatically added to sequence fields (usually) + +If none of those phrases appear, the default is explicit tags. + +Even if a module defaults to implicit tags, a tag defaults to explicit +if its base type is a choice type or ANY type (or the information +object equivalent of an ANY type). + +If the module's default is AUTOMATIC TAGS, sequence and set fields +should have ascending context-specific tags wrapped around the field +types, starting from 0, unless one of the fields of the sequence or +set is already a tagged type. See ITU X.680 section 24.2 for details, +particularly if COMPONENTS OF is used in the sequence definition. + + +Basic types +----------- + +In our infrastructure, a type descriptor specifies a mapping between +an ASN.1 type and a C type. The first step is to ensure that type +descriptors are defined for the basic types used by your ASN.1 module, +as mapped to the C types used in your structures, in asn1_k_encode.c. +If not, you will need to create it. For a BOOLEAN or INTEGER ASN.1 +type, you will use one of these macros: + + DEFBOOLTYPE(descname, ctype) + DEFINTTYPE(descname, ctype) + DEFUINTTYPE(descname, ctype) + +where "descname" is an identifier you make up and "ctype" is the +integer type of the C object you want to map the ASN.1 value to. For +integers, use DEFINTTYPE if the C type is a signed integer type and +DEFUINTTYPE if it is an unsigned type. (For booleans, the distinction +is unimportant since all integer types can hold the values 0 and 1.) +We don't generally define integer mappings for every typedef name of +an integer type. For example, we use the type descriptor int32, which +maps an ASN.1 INTEGER to an int32_t, for krb5_enctype values. + +String types are a little more complicated. Our practice is to store +strings in a krb5_data structure (rather than a zero-terminated C +string), so our infrastructure currently assumes that all strings are +represented as "counted types", meaning the C representation is a +combination of a pointer and an integer type. So, first you must +declare a counted type descriptor (we will describe those in more +detail later) with something like: + + DEFCOUNTEDSTRINGTYPE(generalstring, char *, unsigned int, + k5_asn1_encode_bytestring, k5_asn1_decode_bytestring, + ASN1_GENERALSTRING); + +The first parameter is an identifier you make up. The second and +third parameters are the C types of the pointer and integer holding +the string; for a krb5_data object, those should be the types in the +example. The pointer type must be char * or uint8_t *. The fourth +and fifth parameters reference primitive encoder and decoder +functions; these should almost always be the ones in the example, +unless the ASN.1 type is BIT STRING. The sixth parameter is the +universal tag number of the ASN.1 type, as defined in krbasn1.h. + +Once you have defined the counted type, you can define a normal type +descriptor to wrap it in a krb5_data structure with something like: + + DEFCOUNTEDTYPE(gstring_data, krb5_data, data, length, generalstring); + + +Sequences +--------- + +In our infrastructure, we model ASN.1 sequences using an array of +normal type descriptors. Each type descriptor is applied in turn to +the C object to generate (or consume) an encoding of an ASN.1 value. + +Of course, each value needs to be stored in a different place within +the C object, or they would just overwrite each other. To address +this, you must create an offset type wrapper for each sequence field: + + DEFOFFSETTYPE(descname, structuretype, fieldname, basedesc) + +where "descname" is an identifier you make up, "structuretype" and +"fieldtype" are used to compute the offset and type-check the +structure field, and "basedesc" is the type of the ASN.1 object to be +stored at that offset. + +If your C structure contains a pointer to another C object, you will +need to first define a pointer wrapper, which is very simple: + + DEFPTRTYPE(descname, basedesc) + +Then wrap the defined pointer type in an offset type as described +above. Once a pointer descriptor is defined for a base descriptor, it +can be reused many times, so pointer descriptors are usually defined +right after the types they wrap. When decoding, pointer wrappers +cause a pointer to be allocated with a block of memory equal to the +size of the C type corresponding to the base type. (For offset types, +the corresponding C type is the structure type inside which the offset +is computed.) It is okay for several fields of a sequence to +reference the same pointer field within a structure, as long as the +pointer types all wrap base types with the same corresponding C type. + +If the sequence field has a context tag attached to its type, you will +also need to create a tag wrapper for it: + + DEFCTAGGEDTYPE(descname, tagnum, basedesc) + DEFCTAGGEDTYPE_IMPLICIT(descname, tagnum, basedesc) + +Use the first macro for explicit context tags and the second for +implicit context tags. "tagnum" is the number of the context-specific +tag, and "basedesc" is the name you chose for the offset type above. + +You don't actually need to separately write out DEFOFFSETTYPE and +DEFCTAGGEDTYPE for each field. The combination of offset and context +tag is so common that we have a macro to combine them: + + DEFFIELD(descname, structuretype, fieldname, tagnum, basedesc) + DEFFIELD_IMPLICIT(descname, structuretype, fieldname, tagnum, basedesc) + +Once you have defined tag and offset wrappers for each sequence field, +combine them together in an array and use the DEFSEQTYPE macro to +define the sequence type descriptor: + + static const struct atype_info *my_sequence_fields[] = { + &k5_atype_my_sequence_0, &k5_atype_my_sequence_1, + }; + DEFSEQTYPE(my_sequence, structuretype, my_sequence_fields) + +Each field name must by prefixed by "&k5_atype_" to get a pointer to +the actual variable used to hold the type descriptor. + +ASN.1 sequence types may or may not be defined to be extensible, and +may group extensions together in blocks which must appear together. +Our model does not distinguish these cases. Our decoder treats all +sequence types as extensible. Extension blocks must be modeled by +making all of the extension fields optional, and the decoder will not +enforce that they appear together. + +If your ASN.1 sequence contains optional fields, keep reading. + + +Optional sequence fields +------------------------ + +ASN.1 sequence fields can be annotated with OPTIONAL or, less +commonly, with DEFAULT VALUE. (Be aware that if DEFAULT VALUE is +specified for a sequence field, DER mandates that fields with that +value not be encoded within the sequence. Most standards in the +Kerberos ecosystem avoid the use of DEFAULT VALUE for this reason.) +Although optionality is a property of sequence or set fields, not +types, we still model optional sequence fields using type wrappers. +Optional type wrappers must only be used as members of a sequence, +although they can be nested in offset or pointer wrappers first. + +The simplest way to represent an optional value in a C structure is +with a pointer which takes the value NULL if the field is not present. +In this case, you can just use DEFOPTIONALZEROTYPE to wrap the pointer +type: + + DEFPTRTYPE(ptr_basetype, basetype); + DEFOPTIONALZEROTYPE(opt_ptr_basetype, ptr_basetype); + +and then use opt_ptr_basetype in the DEFFIELD invocation for the +sequence field. DEFOPTIONALZEROTYPE can also be used for integer +types, if it is okay for the value 0 to represent that the +corresponding ASN.1 value is omitted. Optional-zero wrappers, like +pointer wrappers, are usually defined just after the types they wrap. + +For null-terminated sequences, you can use a wrapper like this: + + DEFOPTIONALEMPTYTYPE(opt_seqof_basetype, seqof_basetype) + +to omit the sequence if it is either NULL or of zero length. + +A more general way to wrap optional types is: + + DEFOPTIONALTYPE(descname, predicatefn, initfn, basedesc); + +where "predicatefn" has the signature "int (*fn)(const void *p)" and +is used by the encoder to test whether the ASN.1 value is present in +the C object. "initfn" has the signature "void (*fn)(void *p)" and is +used by the decoder to initialize the C object field if the +corresponding ASN.1 value is omitted in the wire encoding. "initfn" +can be NULL, in which case the C object will simply be left alone. +All C objects are initialized to zero-filled memory when they are +allocated by the decoder. + +An optional string type, represented in a krb5_data structure, can be +wrapped using the nonempty_data function already defined in +asn1_k_encode.c, like so: + + DEFOPTIONALTYPE(opt_ostring_data, nonempty_data, NULL, ostring_data); + + +Sequence-of types +----------------- + +ASN.1 sequence-of types can be represented as C types in two ways. +The simplest is to use an array of pointers terminated in a null +pointer. A descriptor for a sequence-of represented this way is +defined in three steps: + + DEFPTRTYPE(ptr_basetype, basetype); + DEFNULLTERMSEQOFTYPE(seqof_basetype, ptr_basetype); + DEFPTRTYPE(ptr_seqof_basetype, seqof_basetype); + +If the C type corresponding to basetype is "ctype", then the C type +corresponding to ptr_seqof_basetype will be "ctype **". The middle +type sort of corresponds to "ctype *", but not exactly, as it +describes an object of variable size. + +You can also use DEFNONEMPTYNULLTERMSEQOFTYPE in the second step. In +this case, the encoder will throw an error if the sequence is empty. +For historical reasons, the decoder will *not* throw an error if the +sequence is empty, so the calling code must check before assuming a +first element is present. + +The other way of representing sequences is through a combination of +pointer and count. This pattern is most often used for compactness +when the base type is an integer type. A descriptor for a sequence-of +represented this way is defined using a counted type descriptor: + + DEFCOUNTEDSEQOFTYPE(descname, lentype, basedesc) + +where "lentype" is the C type of the length and "basedesc" is a +pointer wrapper for the sequence element type (*not* the element type +itself). For example, an array of 32-bit signed integers is defined +as: + + DEFINTTYPE(int32, int32_t); + DEFPTRTYPE(int32_ptr, int32); + DEFCOUNTEDSEQOFTYPE(cseqof_int32, int32_t, int32_ptr); + +To use a counted sequence-of type in a sequence, use DEFCOUNTEDTYPE: + + DEFCOUNTEDTYPE(descname, structuretype, ptrfield, lenfield, cdesc) + +where "structuretype", "ptrfield", and "lenfield" are used to compute +the field offsets and type-check the structure fields, and "cdesc" is +the name of the counted type descriptor. + +The combination of DEFCOUNTEDTYPE and DEFCTAGGEDTYPE can be +abbreviated using DEFCNFIELD: + + DEFCNFIELD(descname, structuretype, ptrfield, lenfield, tagnum, cdesc) + + +Tag wrappers +------------ + +We've previously covered DEFCTAGGEDTYPE and DEFCTAGGEDTYPE_IMPLICIT, +which are used to define context-specific tag wrappers. There are +two other macros for creating tag wrappers. The first is: + + DEFAPPTAGGEDTYPE(descname, tagnum, basedesc) + +Use this macro to model an "[APPLICATION tagnum]" tag wrapper in an +ASN.1 module. + +There is also a general tag wrapper macro: + + DEFTAGGEDTYPE(descname, class, construction, tag, implicit, basedesc) + +where "class" is one of UNIVERSAL, APPLICATION, CONTEXT_SPECIFIC, or +PRIVATE, "construction" is one of PRIMITIVE or CONSTRUCTED, "tag" is +the tag number, "implicit" is 1 for an implicit tag and 0 for an +explicit tag, and "basedesc" is the wrapped type. Note that that +primitive vs. constructed is not a concept within the abstract ASN.1 +type model, but is instead a concept used in DER. In general, all +explicit tags should be constructed (but see the section on "Dirty +tricks" below). The construction parameter is ignored for implicit +tags. + + +Choice types +------------ + +ASN.1 CHOICE types are represented in C using a signed integer +distinguisher and a union. Modeling a choice type happens in three +steps: + +1. Define type descriptors for each alternative of the choice, +typically using DEFCTAGGEDTYPE to create a tag wrapper for an existing +type. There is no need to create offset type wrappers, as union +fields always have an offset of 0. For example: + + DEFCTAGGEDTYPE(my_choice_0, 0, firstbasedesc); + DEFCTAGGEDTYPE(my_choice_1, 1, secondbasedesc); + +2. Assemble them into an array, similar to how you would for a +sequence, and use DEFCHOICETYPE to create a counted type descriptor: + + static const struct atype_info *my_choice_alternatives[] = { + &k5_atype_my_choice_0, &k5_atype_my_choice_1 + }; + DEFCHOICETYPE(my_choice, union my_choice_choices, enum my_choice_selector, + my_choice_alternatives); + +The second and third parameters to DEFCHOICETYPE are the C types of +the union and distinguisher fields. + +3. Wrap the counted type descriptor in a type descriptor for the +structure containing the distinguisher and union: + + DEFCOUNTEDTYPE_SIGNED(descname, structuretype, u, choice, my_choice); + +The third and fourth parameters to DEFCOUNTEDTYPE_SIGNED are the field +names of the union and distinguisher fields within structuretype. + +ASN.1 choice types may be defined to be extensible, or may not be. +Our model does not distinguish between the two cases. Our decoder +treats all choice types as extensible. + +Our encoder will throw an error if the distinguisher is not within the +range of valid offsets of the alternatives array. Our decoder will +set the distinguisher to -1 if the tag of the ASN.1 value is not +matched by any of the alternatives, and will leave the union +zero-filled in that case. + + +Counted type descriptors +------------------------ + +Several times in earlier sections we've referred to the notion of +"counted type descriptors" without defining what they are. Counted +type descriptors live in a separate namespace from normal type +descriptors, and specify a mapping between an ASN.1 type and two C +objects, one of them having integer type. There are four kinds of +counted type descriptors, defined using the following macros: + + DEFCOUNTEDSTRINGTYPE(descname, ptrtype, lentype, encfn, decfn, tagnum) + DEFCOUNTEDDERTYPE(descname, ptrtype, lentype) + DEFCOUNTEDSEQOFTYPE(descname, lentype, baseptrdesc) + DEFCHOICETYPE(descname, uniontype, distinguishertype, fields) + +DEFCOUNTEDDERTYPE is described in the "Dirty tricks" section below. +The other three kinds of counted types have been covered previously. + +Counted types are always used by wrapping them in a normal type +descriptor with one of these macros: + + DEFCOUNTEDTYPE(descname, structuretype, datafield, countfield, cdesc) + DEFCOUNTEDTYPE_SIGNED(descname, structuretype, datafield, countfield, cdesc) + +These macros are similar in concept to an offset type, only with two +offsets. Use DEFCOUNTEDTYPE if the count field is unsigned, +DEFCOUNTEDTYPE_SIGNED if it is signed. + + +Defining encoder and decoder functions +-------------------------------------- + +After you have created a type descriptor for your types, you need to +create encoder or decoder functions for the ones you want calling code +to be able to process. Do this with one of the following macros: + + MAKE_ENCODER(funcname, desc) + MAKE_DECODER(funcname, desc) + MAKE_CODEC(typename, desc) + +MAKE_ENCODER and MAKE_DECODER allow you to choose function names. +MAKE_CODEC defines encoder and decoder functions with the names +"encode_typename" and "decode_typename". + +If you are defining functions for a null-terminated sequence, use the +descriptor created with DEFNULLTERMSEQOFTYPE or +DEFNONEMPTYNULLTERMSEQOFTYPE, rather than the pointer to it. This is +because encoder and decoder functions implicitly traffic in pointers +to the C object being encoded or decoded. + +Encoder and decoder functions must be prototyped separately, either in +k5-int.h or in a subsidiary included by it. Encoder functions have +the prototype: + + krb5_error_code encode_typename(const ctype *rep, krb5_data **code_out); + +where "ctype" is the C type corresponding to desc. Decoder functions +have the prototype: + + krb5_error_code decode_typename(const krb5_data *code, ctype **rep_out); + +Decoder functions allocate a container for the C type of the object +being decoded and return a pointer to it in *rep_out. + + +Writing test cases +------------------ + +New ASN.1 types in libkrb5 will typically only be accepted with test +cases. Our current test framework lives in src/tests/asn.1. Adding +new types to this framework involves the following steps: + +1. Define an initializer for a sample value of the type in ktest.c, +named ktest_make_sample_typename(). Also define a contents-destructor +for it, named ktest_empty_typename(). Prototype these functions in +ktest.h. + +2. Define an equality test for the type in ktest_equal.c. Prototype +this in ktest_equal.h. (This step is not necessary if the type has no +decoder.) + +3. Add a test case to krb5_encode_test.c, following the examples of +existing test cases there. Update reference_encode.out and +trval_reference.out to contain the output generated by your test case. + +4. Add a test case to krb5_decode_test.c, following the examples of +existing test cases there, and using the output generated by your +encode test. + +5. Add a test case to krb5_decode_leak.c, following the examples of +existing test cases there. + +Following these steps will not ensure the correctness of your +translation of the ASN.1 module to macro invocations; it only lets us +detect unintentional changes to the encodings after they are defined. +To ensure that your translations are correct, you should extend +tests/asn.1/make-vectors.c and use "make test-vectors" to create +vectors using asn1c. + + +Dirty tricks +------------ + +In rare cases you may want to represent the raw DER encoding of a +value in the C structure. If so, you can use DEFCOUNTEDDERTYPE (or +more likely, the existing der_data type descriptor). The encoder and +decoder will throw errors if the wire encoding doesn't have a valid +outermost tag, so be sure to use valid DER encodings in your test +cases (see ktest_make_sample_algorithm_identifier for an example). + +Conversely, the ASN.1 module may define an OCTET STRING wrapper around +a DER encoding which you want to represent as the decoded value. (The +existing example of this is in PKINIT hash agility, where the +PartyUInfo and PartyVInfo fields of OtherInfo are defined as octet +strings which contain the DER encodings of KRB5PrincipalName values.) +In this case you can use a DEFTAGGEDTYPE wrapper like so: + + DEFTAGGEDTYPE(descname, UNIVERSAL, PRIMITIVE, ASN1_OCTETSTRING, 0, + basedesc) + + +Limitations +----------- + +We cannot currently encode or decode SET or SET OF types. + +We cannot model self-referential types (like "MATHSET ::= SET OF +MATHSET"). + +If a sequence uses an optional field that is a choice field (without +a context tag wrapper), or an optional field that uses a stored DER +encoding (again, without a context tag wrapper), our decoder may +assign a value to the choice or stored-DER field when the correct +behavior is to skip that field and assign the value to a subsequent +field. It should be very rare for ASN.1 modules to use choice or open +types this way. + + +Debugging +--------- + +If you are looking at a stack trace with a bunch of ASN.1 encoder or +decoder calls at the top, here are some notes that might help with +debugging: + +1. You may have noticed that the entry point into the encoder is +defined by a macro like MAKE_CODEC. Don't worry about this; those +macros just define thin wrappers around k5_asn1_full_encode and +k5_asn1_full_decode. If you are stepping through code and hit a +wrapper function, just enter "step" to get into the actual encoder or +decoder function. + +2. If you are in the encoder, look for stack frames in +encode_sequence(), and print the value of i within those stack frames. +You should be able to subtract 1 from those values and match them up +with the sequence field offsets in asn1_k_encode.c for the type being +encoded. For example, if an as-req is being encoded and the i values +(starting with the one closest to encode_krb5_as_req) are 4, 2, and 2, +you could match those up as following: + +* as_req_encode wraps untagged_as_req, whose field at offset 3 is the + descriptor for kdc_req_4, which wraps kdc_req_body. + +* kdc_req_body is a function wrapper around kdc_req_hack, whose field + at offset 1 is the descriptor for req_body_1, which wraps + opt_principal. + +* opt_principal wraps principal, which wraps principal_data, whose + field at offset 1 is the descriptor for princname_1. + +* princname_1 is a sequence of general strings represented in the data + and length fields of the krb5_principal_data structure. + +So the problem would likely be in the data components of the client +principal in the kdc_req structure. + +3. If you are in the decoder, look for stacks frames in +decode_sequence(), and again print the values of i. You can match +these up just as above, except without subtracting 1 from the i +values. diff --git a/krb5-1.21.3/src/lib/krb5/asn.1/TODO.asn1 b/krb5-1.21.3/src/lib/krb5/asn.1/TODO.asn1 new file mode 100644 index 00000000..6459f644 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/asn.1/TODO.asn1 @@ -0,0 +1,75 @@ +-*- text -*- + +Stuff that should still be done on the ASN.1 encoder conversion: + +* Make offsetof uses conforming. Currently we may use foo.bar or + foo[0] as fields. + +* Script to generate the tables. Then each type or field entry can + generate multiple bits of code, instead of forcing us to bury the + type consistency checking into the structure initializer + expression. For example, we might generate these bits of code from + one field descriptor: + + * Field table entry. + + * Type-checking code: Create a pointer of the expected type and a + pointer of the actual type (address of field of automatic struct), + and verify consistency with comparison, assignment, or conditional + expr. Plenty of comments to indicate what's being compared and + what a compiler complain means. + + * Range-checking code for bitfields: Create an automatic field info + struct, fill in the computed offset or whatever, read it back, + make sure it matches. Also with comments. + + * Possibly header declarations describing the types that could be + imported, with correct handles *and* C types. + + * Static declarations for non-exported types to keep symbol table + sizes down. + + Then similar bits of code (e.g., all the field table entries) can be + pulled together into the appropriate places. + +* Some kind of "module" system for exporting and importing encoders, + better than relying on the "type_*" variable names. Probably use + meaningful strings that indicate both the ASN.1 type and the + associated C type. Find a way to fit "imported type" into this + scheme so that we can cleanly move the PKINIT types into the PKINIT + plugin, the LDAP types into the LDAP plugin, etc., and still let + them use the encoders in the code. Only a subset of types would be + exported probably. + +* More compact encoding: For struct atype and struct cntype, we could + use structures with a common base type (similar to Xlib events) + instead of a base structure with a void pointer, to save the cost of + a pointer for each type. Doing this might not be strictly correct + C. + +* Pie in the sky: A verbose mode that can tell you "missing field + KDC-REP.cname.name-string[1].data" or some such. This would require + tracking the stack of pending encodes and adding strings with type + and field names. + +* For ALL_POINTERS_ARE_THE_SAME mode (which is not strictly conforming + with the C standard, and thus not default currently, but makes + things a little smaller and faster), eliminate the loadptr structure + entry. (Note that if this infrastructure becomes exposed to + plugins, ALL_POINTERS_ARE_THE_SAME changes the ABI.) + +* Maybe: Reorganize the data of a "module" so everything needing + relocation is put in some tables, referenced by index from other + structures without relocations. E.g., for krb5_data, here's the + offset for the data pointer, here's the offset for the length value, + here's the index into the pointer reader function table, here's the + index into the length reader function table, here's an index into + the string-type encoder table. + + Using an index into a set of pointer types, with a single function + taking an integer parameter used to switch between various + ptr-to-ptr-to-type code paths, will be a lot smaller -- with a good + compiler the function will probably collapse to a simple + fetch-a-pointer function ignoring the integer argument, while at the + C level it's strictly conforming by using the correct types for + access. diff --git a/krb5-1.21.3/src/lib/krb5/asn.1/asn1_encode.c b/krb5-1.21.3/src/lib/krb5/asn.1/asn1_encode.c new file mode 100644 index 00000000..c4140021 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/asn.1/asn1_encode.c @@ -0,0 +1,1585 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/asn.1/asn1_encode.c */ +/* + * Copyright 1994, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "asn1_encode.h" + +struct asn1buf_st { + uint8_t *ptr; /* Position, moving backwards; may be NULL */ + size_t count; /* Count of bytes written so far */ +}; + +/**** Functions for encoding primitive types ****/ + +/* Insert one byte into buf going backwards. */ +static inline void +insert_byte(asn1buf *buf, uint8_t o) +{ + if (buf->ptr != NULL) { + buf->ptr--; + *buf->ptr = o; + } + buf->count++; +} + +/* Insert a block of bytes into buf going backwards (but without reversing + * bytes). */ +static inline void +insert_bytes(asn1buf *buf, const void *bytes, size_t len) +{ + if (buf->ptr != NULL) { + memcpy(buf->ptr - len, bytes, len); + buf->ptr -= len; + } + buf->count += len; +} + +void +k5_asn1_encode_bool(asn1buf *buf, intmax_t val) +{ + insert_byte(buf, val ? 0xFF : 0x00); +} + +void +k5_asn1_encode_int(asn1buf *buf, intmax_t val) +{ + long valcopy; + int digit; + + valcopy = val; + do { + digit = valcopy & 0xFF; + insert_byte(buf, digit); + valcopy = valcopy >> 8; + } while (valcopy != 0 && valcopy != ~0); + + /* Make sure the high bit is of the proper signed-ness. */ + if (val > 0 && (digit & 0x80) == 0x80) + insert_byte(buf, 0); + else if (val < 0 && (digit & 0x80) != 0x80) + insert_byte(buf, 0xFF); +} + +void +k5_asn1_encode_uint(asn1buf *buf, uintmax_t val) +{ + uintmax_t valcopy; + int digit; + + valcopy = val; + do { + digit = valcopy & 0xFF; + insert_byte(buf, digit); + valcopy = valcopy >> 8; + } while (valcopy != 0); + + /* Make sure the high bit is of the proper signed-ness. */ + if (digit & 0x80) + insert_byte(buf, 0); +} + +krb5_error_code +k5_asn1_encode_bytestring(asn1buf *buf, uint8_t *const *val, size_t len) +{ + if (len > 0 && val == NULL) + return ASN1_MISSING_FIELD; + insert_bytes(buf, *val, len); + return 0; +} + +krb5_error_code +k5_asn1_encode_generaltime(asn1buf *buf, time_t val) +{ + struct tm *gtime, gtimebuf; + char s[16], *sp; + time_t gmt_time = val; + int len; + + /* + * Time encoding: YYYYMMDDhhmmssZ + */ + if (gmt_time == 0) { + sp = "19700101000000Z"; + } else { + /* + * Sanity check this just to be paranoid, as gmtime can return NULL, + * and some bogus implementations might overrun on the sprintf. + */ +#ifdef HAVE_GMTIME_R +#ifdef GMTIME_R_RETURNS_INT + if (gmtime_r(&gmt_time, >imebuf) != 0) + return ASN1_BAD_GMTIME; +#else + if (gmtime_r(&gmt_time, >imebuf) == NULL) + return ASN1_BAD_GMTIME; +#endif +#else /* HAVE_GMTIME_R */ + gtime = gmtime(&gmt_time); + if (gtime == NULL) + return ASN1_BAD_GMTIME; + memcpy(>imebuf, gtime, sizeof(gtimebuf)); +#endif /* HAVE_GMTIME_R */ + gtime = >imebuf; + + if (gtime->tm_year > 8099 || gtime->tm_mon > 11 || + gtime->tm_mday > 31 || gtime->tm_hour > 23 || + gtime->tm_min > 59 || gtime->tm_sec > 59) + return ASN1_BAD_GMTIME; + len = snprintf(s, sizeof(s), "%04d%02d%02d%02d%02d%02dZ", + 1900 + gtime->tm_year, gtime->tm_mon + 1, + gtime->tm_mday, gtime->tm_hour, + gtime->tm_min, gtime->tm_sec); + if (SNPRINTF_OVERFLOW(len, sizeof(s))) + /* Shouldn't be possible given above tests. */ + return ASN1_BAD_GMTIME; + sp = s; + } + + insert_bytes(buf, sp, 15); + return 0; +} + +krb5_error_code +k5_asn1_encode_bitstring(asn1buf *buf, uint8_t *const *val, size_t len) +{ + insert_bytes(buf, *val, len); + insert_byte(buf, 0); + return 0; +} + +/**** Functions for decoding primitive types ****/ + +krb5_error_code +k5_asn1_decode_bool(const uint8_t *asn1, size_t len, intmax_t *val) +{ + if (len != 1) + return ASN1_BAD_LENGTH; + *val = (*asn1 != 0); + return 0; +} + +/* Decode asn1/len as the contents of a DER integer, placing the signed result + * in val. */ +krb5_error_code +k5_asn1_decode_int(const uint8_t *asn1, size_t len, intmax_t *val) +{ + intmax_t n; + size_t i; + + if (len == 0) + return ASN1_BAD_LENGTH; + n = (asn1[0] & 0x80) ? -1 : 0; + /* Check length. */ + if (len > sizeof(intmax_t)) + return ASN1_OVERFLOW; + for (i = 0; i < len; i++) + n = n * 256 + asn1[i]; + *val = n; + return 0; +} + +/* Decode asn1/len as the contents of a DER integer, placing the unsigned + * result in val. */ +krb5_error_code +k5_asn1_decode_uint(const uint8_t *asn1, size_t len, uintmax_t *val) +{ + uintmax_t n; + size_t i; + + if (len == 0) + return ASN1_BAD_LENGTH; + /* Check for negative values and check length. */ + if ((asn1[0] & 0x80) || len > sizeof(uintmax_t) + (asn1[0] == 0)) + return ASN1_OVERFLOW; + for (i = 0, n = 0; i < len; i++) + n = (n << 8) | asn1[i]; + *val = n; + return 0; +} + +krb5_error_code +k5_asn1_decode_bytestring(const uint8_t *asn1, size_t len, + uint8_t **str_out, size_t *len_out) +{ + uint8_t *str; + + *str_out = NULL; + *len_out = 0; + if (len == 0) + return 0; + str = malloc(len); + if (str == NULL) + return ENOMEM; + memcpy(str, asn1, len); + *str_out = str; + *len_out = len; + return 0; +} + +krb5_error_code +k5_asn1_decode_generaltime(const uint8_t *asn1, size_t len, time_t *time_out) +{ + const char *s = (char *)asn1; + struct tm ts; + time_t t; + size_t i; + + *time_out = 0; + if (len != 15) + return ASN1_BAD_LENGTH; + /* Time encoding: YYYYMMDDhhmmssZ */ + if (s[14] != 'Z') + return ASN1_BAD_FORMAT; + if (memcmp(s, "19700101000000Z", 15) == 0) { + *time_out = 0; + return 0; + } +#define c2i(c) ((c) - '0') + for (i = 0; i < 14; ++i) { + if ((uint8_t)c2i(s[i]) > 9) + return ASN1_BAD_TIMEFORMAT; + } + ts.tm_year = 1000 * c2i(s[0]) + 100 * c2i(s[1]) + 10 * c2i(s[2]) + + c2i(s[3]) - 1900; + ts.tm_mon = 10 * c2i(s[4]) + c2i(s[5]) - 1; + ts.tm_mday = 10 * c2i(s[6]) + c2i(s[7]); + ts.tm_hour = 10 * c2i(s[8]) + c2i(s[9]); + ts.tm_min = 10 * c2i(s[10]) + c2i(s[11]); + ts.tm_sec = 10 * c2i(s[12]) + c2i(s[13]); + ts.tm_isdst = -1; + t = krb5int_gmt_mktime(&ts); + if (t == -1) + return ASN1_BAD_TIMEFORMAT; + *time_out = t; + return 0; +} + +/* + * Note: we return the number of bytes, not bits, in the bit string. If the + * number of bits is not a multiple of 8 we effectively round up to the next + * multiple of 8. + */ +krb5_error_code +k5_asn1_decode_bitstring(const uint8_t *asn1, size_t len, + uint8_t **bits_out, size_t *len_out) +{ + uint8_t unused, *bits; + + *bits_out = NULL; + *len_out = 0; + if (len == 0) + return ASN1_BAD_LENGTH; + unused = *asn1++; + len--; + if (unused > 7) + return ASN1_BAD_FORMAT; + + bits = malloc(len); + if (bits == NULL) + return ENOMEM; + memcpy(bits, asn1, len); + if (len > 1) + bits[len - 1] &= (0xff << unused); + + *bits_out = bits; + *len_out = len; + return 0; +} + +/**** Functions for encoding and decoding tags ****/ + +/* Encode a DER tag into buf with the tag parameters in t and the content + * length len. Place the length of the encoded tag in *retlen. */ +static krb5_error_code +make_tag(asn1buf *buf, const taginfo *t, size_t len) +{ + asn1_tagnum tag_copy; + size_t len_copy, oldcount; + + if (t->tagnum > ASN1_TAGNUM_MAX) + return ASN1_OVERFLOW; + + /* Encode the length of the content within the tag. */ + if (len < 128) { + insert_byte(buf, len & 0x7F); + } else { + oldcount = buf->count; + for (len_copy = len; len_copy != 0; len_copy >>= 8) + insert_byte(buf, len_copy & 0xFF); + insert_byte(buf, 0x80 | ((buf->count - oldcount) & 0x7F)); + } + + /* Encode the tag and construction bit. */ + if (t->tagnum < 31) { + insert_byte(buf, t->asn1class | t->construction | t->tagnum); + } else { + tag_copy = t->tagnum; + insert_byte(buf, tag_copy & 0x7F); + tag_copy >>= 7; + + for (; tag_copy != 0; tag_copy >>= 7) + insert_byte(buf, 0x80 | (tag_copy & 0x7F)); + + insert_byte(buf, t->asn1class | t->construction | 0x1F); + } + + return 0; +} + +/* + * Read a DER tag and length from asn1/len. Place the tag parameters in + * tag_out. Set contents_out/clen_out to the octet range of the tag's + * contents, and remainder_out/rlen_out to the octet range after the end of the + * DER encoding. + */ +static krb5_error_code +get_tag(const uint8_t *asn1, size_t len, taginfo *tag_out, + const uint8_t **contents_out, size_t *clen_out, + const uint8_t **remainder_out, size_t *rlen_out) +{ + uint8_t o; + const uint8_t *tag_start = asn1; + size_t clen, llen, i; + + *contents_out = *remainder_out = NULL; + *clen_out = *rlen_out = 0; + if (len == 0) + return ASN1_OVERRUN; + o = *asn1++; + len--; + tag_out->asn1class = o & 0xC0; + tag_out->construction = o & 0x20; + if ((o & 0x1F) != 0x1F) { + tag_out->tagnum = o & 0x1F; + } else { + tag_out->tagnum = 0; + do { + if (len == 0) + return ASN1_OVERRUN; + if (tag_out->tagnum > (ASN1_TAGNUM_MAX >> 7)) + return ASN1_OVERFLOW; + o = *asn1++; + len--; + tag_out->tagnum = (tag_out->tagnum << 7) | (o & 0x7F); + } while (o & 0x80); + /* Check for overly large tag values */ + if (tag_out->tagnum > ASN1_TAGNUM_MAX) + return ASN1_OVERFLOW; + } + + if (len == 0) + return ASN1_OVERRUN; + o = *asn1++; + len--; + + if ((o & 0x80) == 0) { + /* Short form (first octet gives content length). */ + if (o > len) + return ASN1_OVERRUN; + *contents_out = asn1; + *clen_out = o; + *remainder_out = asn1 + *clen_out; + *rlen_out = len - (*remainder_out - asn1); + } else { + /* Long form (first octet gives number of base-256 length octets). */ + llen = o & 0x7F; + if (llen > len) + return ASN1_OVERRUN; + if (llen > sizeof(*clen_out)) + return ASN1_OVERFLOW; + if (llen == 0) + return ASN1_INDEF; + for (i = 0, clen = 0; i < llen; i++) + clen = (clen << 8) | asn1[i]; + if (clen > len - llen) + return ASN1_OVERRUN; + *contents_out = asn1 + llen; + *clen_out = clen; + *remainder_out = *contents_out + clen; + *rlen_out = len - (*remainder_out - asn1); + } + tag_out->tag_len = *contents_out - tag_start; + return 0; +} + +#ifdef POINTERS_ARE_ALL_THE_SAME +#define LOADPTR(PTR, TYPE) (*(const void *const *)(PTR)) +#define STOREPTR(PTR, TYPE, VAL) (*(void **)(VAL) = (PTR)) +#else +#define LOADPTR(PTR, PTRINFO) \ + (assert((PTRINFO)->loadptr != NULL), (PTRINFO)->loadptr(PTR)) +#define STOREPTR(PTR, PTRINFO, VAL) \ + (assert((PTRINFO)->storeptr != NULL), (PTRINFO)->storeptr(PTR, VAL)) +#endif + +static size_t +get_nullterm_sequence_len(const void *valp, const struct atype_info *seq) +{ + size_t i; + const struct atype_info *a; + const struct ptr_info *ptr; + const void *elt, *eltptr; + + a = seq; + i = 0; + assert(a->type == atype_ptr); + assert(seq->size != 0); + ptr = a->tinfo; + + while (1) { + eltptr = (const char *)valp + i * seq->size; + elt = LOADPTR(eltptr, ptr); + if (elt == NULL) + break; + i++; + } + return i; +} +static krb5_error_code +encode_sequence_of(asn1buf *buf, size_t seqlen, const void *val, + const struct atype_info *eltinfo); + +static krb5_error_code +encode_nullterm_sequence_of(asn1buf *buf, const void *val, + const struct atype_info *type, int can_be_empty) +{ + size_t len = get_nullterm_sequence_len(val, type); + + if (!can_be_empty && len == 0) + return ASN1_MISSING_FIELD; + return encode_sequence_of(buf, len, val, type); +} + +static intmax_t +load_int(const void *val, size_t size) +{ + switch (size) { + case 1: return *(int8_t *)val; + case 2: return *(int16_t *)val; + case 4: return *(int32_t *)val; + case 8: return *(int64_t *)val; + default: abort(); + } +} + +static uintmax_t +load_uint(const void *val, size_t size) +{ + switch (size) { + case 1: return *(uint8_t *)val; + case 2: return *(uint16_t *)val; + case 4: return *(uint32_t *)val; + case 8: return *(uint64_t *)val; + default: abort(); + } +} + +static krb5_error_code +load_count(const void *val, const struct counted_info *counted, + size_t *count_out) +{ + const void *countptr = (const char *)val + counted->lenoff; + + assert(sizeof(size_t) <= sizeof(uintmax_t)); + if (counted->lensigned) { + intmax_t xlen = load_int(countptr, counted->lensize); + if (xlen < 0 || (uintmax_t)xlen > SIZE_MAX) + return EINVAL; + *count_out = xlen; + } else { + uintmax_t xlen = load_uint(countptr, counted->lensize); + if ((size_t)xlen != xlen || xlen > SIZE_MAX) + return EINVAL; + *count_out = xlen; + } + return 0; +} + +static krb5_error_code +store_int(intmax_t intval, size_t size, void *val) +{ + switch (size) { + case 1: + if ((int8_t)intval != intval) + return ASN1_OVERFLOW; + *(int8_t *)val = intval; + return 0; + case 2: + if ((int16_t)intval != intval) + return ASN1_OVERFLOW; + *(int16_t *)val = intval; + return 0; + case 4: + if ((int32_t)intval != intval) + return ASN1_OVERFLOW; + *(int32_t *)val = intval; + return 0; + case 8: + if ((int64_t)intval != intval) + return ASN1_OVERFLOW; + *(int64_t *)val = intval; + return 0; + default: + abort(); + } +} + +static krb5_error_code +store_uint(uintmax_t intval, size_t size, void *val) +{ + switch (size) { + case 1: + if ((uint8_t)intval != intval) + return ASN1_OVERFLOW; + *(uint8_t *)val = intval; + return 0; + case 2: + if ((uint16_t)intval != intval) + return ASN1_OVERFLOW; + *(uint16_t *)val = intval; + return 0; + case 4: + if ((uint32_t)intval != intval) + return ASN1_OVERFLOW; + *(uint32_t *)val = intval; + return 0; + case 8: + if ((uint64_t)intval != intval) + return ASN1_OVERFLOW; + *(uint64_t *)val = intval; + return 0; + default: + abort(); + } +} + +/* Store a count value in an integer field of a structure. If count is + * SIZE_MAX and the target is a signed field, store -1. */ +static krb5_error_code +store_count(size_t count, const struct counted_info *counted, void *val) +{ + void *countptr = (char *)val + counted->lenoff; + + if (counted->lensigned) { + if (count == SIZE_MAX) + return store_int(-1, counted->lensize, countptr); + else if ((intmax_t)count < 0) + return ASN1_OVERFLOW; + else + return store_int(count, counted->lensize, countptr); + } else + return store_uint(count, counted->lensize, countptr); +} + +/* Split a DER encoding into tag and contents. Insert the contents into buf, + * then return the length of the contents and the tag. */ +static krb5_error_code +split_der(asn1buf *buf, uint8_t *const *der, size_t len, taginfo *tag_out) +{ + krb5_error_code ret; + const uint8_t *contents, *remainder; + size_t clen, rlen; + + ret = get_tag(*der, len, tag_out, &contents, &clen, &remainder, &rlen); + if (ret) + return ret; + if (rlen != 0) + return ASN1_BAD_LENGTH; + insert_bytes(buf, contents, clen); + return 0; +} + +/* + * Store the DER encoding given by t and asn1/len into the char * or + * uint8_t * pointed to by val. Set *count_out to the length of the + * DER encoding. + */ +static krb5_error_code +store_der(const taginfo *t, const uint8_t *asn1, size_t len, void *val, + size_t *count_out) +{ + uint8_t *der; + size_t der_len; + + *count_out = 0; + der_len = t->tag_len + len; + der = malloc(der_len); + if (der == NULL) + return ENOMEM; + memcpy(der, asn1 - t->tag_len, der_len); + *(uint8_t **)val = der; + *count_out = der_len; + return 0; +} + +static krb5_error_code +encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq); +static krb5_error_code +encode_cntype(asn1buf *buf, const void *val, size_t len, + const struct cntype_info *c, taginfo *tag_out); + +/* Encode a value (contents only, no outer tag) according to a type, and return + * its encoded tag information. */ +static krb5_error_code +encode_atype(asn1buf *buf, const void *val, const struct atype_info *a, + taginfo *tag_out) +{ + krb5_error_code ret; + + if (val == NULL) + return ASN1_MISSING_FIELD; + + switch (a->type) { + case atype_fn: { + const struct fn_info *fn = a->tinfo; + assert(fn->enc != NULL); + return fn->enc(buf, val, tag_out); + } + case atype_sequence: + assert(a->tinfo != NULL); + ret = encode_sequence(buf, val, a->tinfo); + if (ret) + return ret; + tag_out->asn1class = UNIVERSAL; + tag_out->construction = CONSTRUCTED; + tag_out->tagnum = ASN1_SEQUENCE; + break; + case atype_ptr: { + const struct ptr_info *ptr = a->tinfo; + assert(ptr->basetype != NULL); + return encode_atype(buf, LOADPTR(val, ptr), ptr->basetype, tag_out); + } + case atype_offset: { + const struct offset_info *off = a->tinfo; + assert(off->basetype != NULL); + return encode_atype(buf, (const char *)val + off->dataoff, + off->basetype, tag_out); + } + case atype_optional: { + const struct optional_info *opt = a->tinfo; + assert(opt->is_present != NULL); + if (opt->is_present(val)) + return encode_atype(buf, val, opt->basetype, tag_out); + else + return ASN1_OMITTED; + } + case atype_counted: { + const struct counted_info *counted = a->tinfo; + const void *dataptr = (const char *)val + counted->dataoff; + size_t count; + assert(counted->basetype != NULL); + ret = load_count(val, counted, &count); + if (ret) + return ret; + return encode_cntype(buf, dataptr, count, counted->basetype, tag_out); + } + case atype_nullterm_sequence_of: + case atype_nonempty_nullterm_sequence_of: + assert(a->tinfo != NULL); + ret = encode_nullterm_sequence_of(buf, val, a->tinfo, + a->type == + atype_nullterm_sequence_of); + if (ret) + return ret; + tag_out->asn1class = UNIVERSAL; + tag_out->construction = CONSTRUCTED; + tag_out->tagnum = ASN1_SEQUENCE; + break; + case atype_tagged_thing: { + const struct tagged_info *tag = a->tinfo; + size_t oldcount = buf->count; + ret = encode_atype(buf, val, tag->basetype, tag_out); + if (ret) + return ret; + if (!tag->implicit) { + ret = make_tag(buf, tag_out, buf->count - oldcount); + if (ret) + return ret; + tag_out->construction = tag->construction; + } + tag_out->asn1class = tag->tagtype; + tag_out->tagnum = tag->tagval; + break; + } + case atype_bool: + k5_asn1_encode_bool(buf, load_int(val, a->size)); + tag_out->asn1class = UNIVERSAL; + tag_out->construction = PRIMITIVE; + tag_out->tagnum = ASN1_BOOLEAN; + break; + case atype_int: + k5_asn1_encode_int(buf, load_int(val, a->size)); + tag_out->asn1class = UNIVERSAL; + tag_out->construction = PRIMITIVE; + tag_out->tagnum = ASN1_INTEGER; + break; + case atype_uint: + k5_asn1_encode_uint(buf, load_uint(val, a->size)); + tag_out->asn1class = UNIVERSAL; + tag_out->construction = PRIMITIVE; + tag_out->tagnum = ASN1_INTEGER; + break; + case atype_int_immediate: { + const struct immediate_info *imm = a->tinfo; + k5_asn1_encode_int(buf, imm->val); + tag_out->asn1class = UNIVERSAL; + tag_out->construction = PRIMITIVE; + tag_out->tagnum = ASN1_INTEGER; + break; + } + default: + assert(a->type > atype_min); + assert(a->type < atype_max); + abort(); + } + + return 0; +} + +static krb5_error_code +encode_atype_and_tag(asn1buf *buf, const void *val, const struct atype_info *a) +{ + taginfo t; + krb5_error_code ret; + size_t oldcount = buf->count; + + ret = encode_atype(buf, val, a, &t); + if (ret) + return ret; + ret = make_tag(buf, &t, buf->count - oldcount); + if (ret) + return ret; + return 0; +} + +/* + * Encode an object and count according to a cntype_info structure. val is a + * pointer to the object being encoded, which in most cases is itself a + * pointer (but is a union in the cntype_choice case). + */ +static krb5_error_code +encode_cntype(asn1buf *buf, const void *val, size_t count, + const struct cntype_info *c, taginfo *tag_out) +{ + krb5_error_code ret; + + switch (c->type) { + case cntype_string: { + const struct string_info *string = c->tinfo; + assert(string->enc != NULL); + ret = string->enc(buf, val, count); + if (ret) + return ret; + tag_out->asn1class = UNIVERSAL; + tag_out->construction = PRIMITIVE; + tag_out->tagnum = string->tagval; + break; + } + case cntype_der: + return split_der(buf, val, count, tag_out); + case cntype_seqof: { + const struct atype_info *a = c->tinfo; + const struct ptr_info *ptr = a->tinfo; + assert(a->type == atype_ptr); + val = LOADPTR(val, ptr); + ret = encode_sequence_of(buf, count, val, ptr->basetype); + if (ret) + return ret; + tag_out->asn1class = UNIVERSAL; + tag_out->construction = CONSTRUCTED; + tag_out->tagnum = ASN1_SEQUENCE; + break; + } + case cntype_choice: { + const struct choice_info *choice = c->tinfo; + if (count >= choice->n_options) + return ASN1_MISSING_FIELD; + return encode_atype(buf, val, choice->options[count], tag_out); + } + + default: + assert(c->type > cntype_min); + assert(c->type < cntype_max); + abort(); + } + + return 0; +} + +static krb5_error_code +encode_sequence(asn1buf *buf, const void *val, const struct seq_info *seq) +{ + krb5_error_code ret; + size_t i; + + for (i = seq->n_fields; i > 0; i--) { + ret = encode_atype_and_tag(buf, val, seq->fields[i - 1]); + if (ret == ASN1_OMITTED) + continue; + else if (ret != 0) + return ret; + } + return 0; +} + +static krb5_error_code +encode_sequence_of(asn1buf *buf, size_t seqlen, const void *val, + const struct atype_info *eltinfo) +{ + krb5_error_code ret; + size_t i; + const void *eltptr; + + assert(eltinfo->size != 0); + for (i = seqlen; i > 0; i--) { + eltptr = (const char *)val + (i - 1) * eltinfo->size; + ret = encode_atype_and_tag(buf, eltptr, eltinfo); + if (ret) + return ret; + } + return 0; +} + +/**** Functions for freeing C objects based on type info ****/ + +static void free_atype_ptr(const struct atype_info *a, void *val); +static void free_sequence(const struct seq_info *seq, void *val); +static void free_sequence_of(const struct atype_info *eltinfo, void *val, + size_t count); +static void free_cntype(const struct cntype_info *a, void *val, size_t count); + +/* + * Free a C object according to a type description. Do not free pointers at + * the first level; they may be referenced by other fields of a sequence, and + * will be freed by free_atype_ptr in a second pass. + */ +static void +free_atype(const struct atype_info *a, void *val) +{ + switch (a->type) { + case atype_fn: { + const struct fn_info *fn = a->tinfo; + if (fn->free_func != NULL) + fn->free_func(val); + break; + } + case atype_sequence: + free_sequence(a->tinfo, val); + break; + case atype_ptr: { + const struct ptr_info *ptrinfo = a->tinfo; + void *ptr = LOADPTR(val, ptrinfo); + if (ptr != NULL) { + free_atype(ptrinfo->basetype, ptr); + free_atype_ptr(ptrinfo->basetype, ptr); + } + break; + } + case atype_offset: { + const struct offset_info *off = a->tinfo; + assert(off->basetype != NULL); + free_atype(off->basetype, (char *)val + off->dataoff); + break; + } + case atype_optional: { + const struct optional_info *opt = a->tinfo; + free_atype(opt->basetype, val); + break; + } + case atype_counted: { + const struct counted_info *counted = a->tinfo; + void *dataptr = (char *)val + counted->dataoff; + size_t count; + if (load_count(val, counted, &count) == 0) + free_cntype(counted->basetype, dataptr, count); + break; + } + case atype_nullterm_sequence_of: + case atype_nonempty_nullterm_sequence_of: { + size_t count = get_nullterm_sequence_len(val, a->tinfo); + free_sequence_of(a->tinfo, val, count); + break; + } + case atype_tagged_thing: { + const struct tagged_info *tag = a->tinfo; + free_atype(tag->basetype, val); + break; + } + case atype_bool: + case atype_int: + case atype_uint: + case atype_int_immediate: + break; + default: + abort(); + } +} + +static void +free_atype_ptr(const struct atype_info *a, void *val) +{ + switch (a->type) { + case atype_fn: + case atype_sequence: + case atype_counted: + case atype_nullterm_sequence_of: + case atype_nonempty_nullterm_sequence_of: + case atype_bool: + case atype_int: + case atype_uint: + case atype_int_immediate: + break; + case atype_ptr: { + const struct ptr_info *ptrinfo = a->tinfo; + void *ptr = LOADPTR(val, ptrinfo); + free(ptr); + STOREPTR(NULL, ptrinfo, val); + break; + } + case atype_offset: { + const struct offset_info *off = a->tinfo; + assert(off->basetype != NULL); + free_atype_ptr(off->basetype, (char *)val + off->dataoff); + break; + } + case atype_optional: { + const struct optional_info *opt = a->tinfo; + free_atype_ptr(opt->basetype, val); + break; + } + case atype_tagged_thing: { + const struct tagged_info *tag = a->tinfo; + free_atype_ptr(tag->basetype, val); + break; + } + default: + abort(); + } +} + +static void +free_cntype(const struct cntype_info *c, void *val, size_t count) +{ + switch (c->type) { + case cntype_string: + case cntype_der: + free(*(char **)val); + *(char **)val = NULL; + break; + case cntype_seqof: { + const struct atype_info *a = c->tinfo; + const struct ptr_info *ptrinfo = a->tinfo; + void *seqptr = LOADPTR(val, ptrinfo); + free_sequence_of(ptrinfo->basetype, seqptr, count); + free(seqptr); + STOREPTR(NULL, ptrinfo, val); + break; + } + case cntype_choice: { + const struct choice_info *choice = c->tinfo; + if (count < choice->n_options) { + free_atype(choice->options[count], val); + free_atype_ptr(choice->options[count], val); + } + break; + } + default: + abort(); + } +} + +static void +free_sequence(const struct seq_info *seq, void *val) +{ + size_t i; + + for (i = 0; i < seq->n_fields; i++) + free_atype(seq->fields[i], val); + for (i = 0; i < seq->n_fields; i++) + free_atype_ptr(seq->fields[i], val); +} + +static void +free_sequence_of(const struct atype_info *eltinfo, void *val, size_t count) +{ + void *eltptr; + + assert(eltinfo->size != 0); + while (count-- > 0) { + eltptr = (char *)val + count * eltinfo->size; + free_atype(eltinfo, eltptr); + free_atype_ptr(eltinfo, eltptr); + } +} + +/**** Functions for decoding objects based on type info ****/ + +/* Return nonzero if t is an expected tag for an ASN.1 object of type a. */ +static int +check_atype_tag(const struct atype_info *a, const taginfo *t) +{ + switch (a->type) { + case atype_fn: { + const struct fn_info *fn = a->tinfo; + assert(fn->check_tag != NULL); + return fn->check_tag(t); + } + case atype_sequence: + case atype_nullterm_sequence_of: + case atype_nonempty_nullterm_sequence_of: + return (t->asn1class == UNIVERSAL && t->construction == CONSTRUCTED && + t->tagnum == ASN1_SEQUENCE); + case atype_ptr: { + const struct ptr_info *ptrinfo = a->tinfo; + return check_atype_tag(ptrinfo->basetype, t); + } + case atype_offset: { + const struct offset_info *off = a->tinfo; + return check_atype_tag(off->basetype, t); + } + case atype_optional: { + const struct optional_info *opt = a->tinfo; + return check_atype_tag(opt->basetype, t); + } + case atype_counted: { + const struct counted_info *counted = a->tinfo; + switch (counted->basetype->type) { + case cntype_string: { + const struct string_info *string = counted->basetype->tinfo; + return (t->asn1class == UNIVERSAL && + t->construction == PRIMITIVE && + t->tagnum == string->tagval); + } + case cntype_seqof: + return (t->asn1class == UNIVERSAL && + t->construction == CONSTRUCTED && + t->tagnum == ASN1_SEQUENCE); + case cntype_der: + /* + * We treat any tag as matching a stored DER encoding. In some + * cases we know what the tag should be; in others, we truly want + * to accept any tag. If it ever becomes an issue, we could add + * optional tag info to the type and check it here. + */ + return 1; + case cntype_choice: + /* + * ASN.1 choices may or may not be extensible. For now, we treat + * all choices as extensible and match any tag. We should consider + * modeling whether choices are extensible before making the + * encoder visible to plugins. + */ + return 1; + default: + abort(); + } + } + case atype_tagged_thing: { + const struct tagged_info *tag = a->tinfo; + /* NOTE: Doesn't check construction bit for implicit tags. */ + if (!tag->implicit && t->construction != tag->construction) + return 0; + return (t->asn1class == tag->tagtype && t->tagnum == tag->tagval); + } + case atype_bool: + return (t->asn1class == UNIVERSAL && t->construction == PRIMITIVE && + t->tagnum == ASN1_BOOLEAN); + case atype_int: + case atype_uint: + case atype_int_immediate: + return (t->asn1class == UNIVERSAL && t->construction == PRIMITIVE && + t->tagnum == ASN1_INTEGER); + default: + abort(); + } +} + +static krb5_error_code +decode_cntype(const taginfo *t, const uint8_t *asn1, size_t len, + const struct cntype_info *c, void *val, size_t *count_out); +static krb5_error_code +decode_atype_to_ptr(const taginfo *t, const uint8_t *asn1, size_t len, + const struct atype_info *basetype, void **ptr_out); +static krb5_error_code +decode_sequence(const uint8_t *asn1, size_t len, const struct seq_info *seq, + void *val); +static krb5_error_code +decode_sequence_of(const uint8_t *asn1, size_t len, + const struct atype_info *elemtype, void **seq_out, + size_t *count_out); + +/* Given the enclosing tag t, decode from asn1/len the contents of the ASN.1 + * type specified by a, placing the result into val (caller-allocated). */ +static krb5_error_code +decode_atype(const taginfo *t, const uint8_t *asn1, size_t len, + const struct atype_info *a, void *val) +{ + krb5_error_code ret; + + switch (a->type) { + case atype_fn: { + const struct fn_info *fn = a->tinfo; + assert(fn->dec != NULL); + return fn->dec(t, asn1, len, val); + } + case atype_sequence: + return decode_sequence(asn1, len, a->tinfo, val); + case atype_ptr: { + const struct ptr_info *ptrinfo = a->tinfo; + void *ptr = LOADPTR(val, ptrinfo); + assert(ptrinfo->basetype != NULL); + if (ptr != NULL) { + /* Container was already allocated by a previous sequence field. */ + return decode_atype(t, asn1, len, ptrinfo->basetype, ptr); + } else { + ret = decode_atype_to_ptr(t, asn1, len, ptrinfo->basetype, &ptr); + if (ret) + return ret; + STOREPTR(ptr, ptrinfo, val); + break; + } + } + case atype_offset: { + const struct offset_info *off = a->tinfo; + assert(off->basetype != NULL); + return decode_atype(t, asn1, len, off->basetype, + (char *)val + off->dataoff); + } + case atype_optional: { + const struct optional_info *opt = a->tinfo; + return decode_atype(t, asn1, len, opt->basetype, val); + } + case atype_counted: { + const struct counted_info *counted = a->tinfo; + void *dataptr = (char *)val + counted->dataoff; + size_t count; + assert(counted->basetype != NULL); + ret = decode_cntype(t, asn1, len, counted->basetype, dataptr, &count); + if (ret) + return ret; + return store_count(count, counted, val); + } + case atype_tagged_thing: { + const struct tagged_info *tag = a->tinfo; + taginfo inner_tag; + const taginfo *tp = t; + const uint8_t *rem; + size_t rlen; + if (!tag->implicit) { + ret = get_tag(asn1, len, &inner_tag, &asn1, &len, &rem, &rlen); + if (ret) + return ret; + if (rlen) + return ASN1_BAD_LENGTH; + tp = &inner_tag; + if (!check_atype_tag(tag->basetype, tp)) + return ASN1_BAD_ID; + } + return decode_atype(tp, asn1, len, tag->basetype, val); + } + case atype_bool: { + intmax_t intval; + ret = k5_asn1_decode_bool(asn1, len, &intval); + if (ret) + return ret; + return store_int(intval, a->size, val); + } + case atype_int: { + intmax_t intval; + ret = k5_asn1_decode_int(asn1, len, &intval); + if (ret) + return ret; + return store_int(intval, a->size, val); + } + case atype_uint: { + uintmax_t intval; + ret = k5_asn1_decode_uint(asn1, len, &intval); + if (ret) + return ret; + return store_uint(intval, a->size, val); + } + case atype_int_immediate: { + const struct immediate_info *imm = a->tinfo; + intmax_t intval; + ret = k5_asn1_decode_int(asn1, len, &intval); + if (ret) + return ret; + if (intval != imm->val && imm->err != 0) + return imm->err; + break; + } + default: + /* Null-terminated sequence types are handled in decode_atype_to_ptr, + * since they create variable-sized objects. */ + assert(a->type != atype_nullterm_sequence_of); + assert(a->type != atype_nonempty_nullterm_sequence_of); + assert(a->type > atype_min); + assert(a->type < atype_max); + abort(); + } + return 0; +} + +/* + * Given the enclosing tag t, decode from asn1/len the contents of the + * ASN.1 type described by c, placing the counted result into val/count_out. + * If the resulting count should be -1 (for an unknown union distinguisher), + * set *count_out to SIZE_MAX. + */ +static krb5_error_code +decode_cntype(const taginfo *t, const uint8_t *asn1, size_t len, + const struct cntype_info *c, void *val, size_t *count_out) +{ + krb5_error_code ret; + + switch (c->type) { + case cntype_string: { + const struct string_info *string = c->tinfo; + assert(string->dec != NULL); + return string->dec(asn1, len, val, count_out); + } + case cntype_der: + return store_der(t, asn1, len, val, count_out); + case cntype_seqof: { + const struct atype_info *a = c->tinfo; + const struct ptr_info *ptrinfo = a->tinfo; + void *seq; + assert(a->type == atype_ptr); + ret = decode_sequence_of(asn1, len, ptrinfo->basetype, &seq, + count_out); + if (ret) + return ret; + STOREPTR(seq, ptrinfo, val); + break; + } + case cntype_choice: { + const struct choice_info *choice = c->tinfo; + size_t i; + for (i = 0; i < choice->n_options; i++) { + if (check_atype_tag(choice->options[i], t)) { + ret = decode_atype(t, asn1, len, choice->options[i], val); + if (ret) + return ret; + *count_out = i; + return 0; + } + } + /* SIZE_MAX will be stored as -1 in the distinguisher. If we start + * modeling non-extensible choices we should check that here. */ + *count_out = SIZE_MAX; + break; + } + default: + assert(c->type > cntype_min); + assert(c->type < cntype_max); + abort(); + } + return 0; +} + +/* Add a null pointer to the end of a sequence. ptr is consumed on success + * (to be replaced by *ptr_out), left alone on failure. */ +static krb5_error_code +null_terminate(const struct atype_info *eltinfo, void *ptr, size_t count, + void **ptr_out) +{ + const struct ptr_info *ptrinfo = eltinfo->tinfo; + void *endptr; + + assert(eltinfo->type == atype_ptr); + ptr = realloc(ptr, (count + 1) * eltinfo->size); + if (ptr == NULL) + return ENOMEM; + endptr = (char *)ptr + count * eltinfo->size; + STOREPTR(NULL, ptrinfo, endptr); + *ptr_out = ptr; + return 0; +} + +static krb5_error_code +decode_atype_to_ptr(const taginfo *t, const uint8_t *asn1, size_t len, + const struct atype_info *a, void **ptr_out) +{ + krb5_error_code ret; + void *ptr; + size_t count; + + *ptr_out = NULL; + switch (a->type) { + case atype_nullterm_sequence_of: + case atype_nonempty_nullterm_sequence_of: + ret = decode_sequence_of(asn1, len, a->tinfo, &ptr, &count); + if (ret) + return ret; + ret = null_terminate(a->tinfo, ptr, count, &ptr); + if (ret) { + free_sequence_of(a->tinfo, ptr, count); + return ret; + } + /* Historically we do not enforce non-emptiness of sequences when + * decoding, even when it is required by the ASN.1 type. */ + break; + default: + ptr = calloc(a->size, 1); + if (ptr == NULL) + return ENOMEM; + ret = decode_atype(t, asn1, len, a, ptr); + if (ret) { + free(ptr); + return ret; + } + break; + } + *ptr_out = ptr; + return 0; +} + +/* Initialize a C object when the corresponding ASN.1 type was omitted within a + * sequence. If the ASN.1 type is not optional, return ASN1_MISSING_FIELD. */ +static krb5_error_code +omit_atype(const struct atype_info *a, void *val) +{ + switch (a->type) + { + case atype_fn: + case atype_sequence: + case atype_nullterm_sequence_of: + case atype_nonempty_nullterm_sequence_of: + case atype_counted: + case atype_bool: + case atype_int: + case atype_uint: + case atype_int_immediate: + return ASN1_MISSING_FIELD; + case atype_ptr: { + const struct ptr_info *ptrinfo = a->tinfo; + return omit_atype(ptrinfo->basetype, val); + } + case atype_offset: { + const struct offset_info *off = a->tinfo; + return omit_atype(off->basetype, (char *)val + off->dataoff); + } + case atype_tagged_thing: { + const struct tagged_info *tag = a->tinfo; + return omit_atype(tag->basetype, val); + } + case atype_optional: { + const struct optional_info *opt = a->tinfo; + if (opt->init != NULL) + opt->init(val); + return 0; + } + default: + abort(); + } +} + +/* Decode an ASN.1 sequence into a C object. */ +static krb5_error_code +decode_sequence(const uint8_t *asn1, size_t len, const struct seq_info *seq, + void *val) +{ + krb5_error_code ret; + const uint8_t *contents; + size_t i, j, clen; + taginfo t; + + assert(seq->n_fields > 0); + for (i = 0; i < seq->n_fields; i++) { + if (len == 0) + break; + ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len); + if (ret) + goto error; + /* + * Find the applicable sequence field. This logic is a little + * oversimplified; we could match an element to an optional extensible + * choice or optional stored-DER type when we ought to match a + * subsequent non-optional field. But it's unwise and (hopefully) very + * rare for ASN.1 modules to require such precision. + */ + for (; i < seq->n_fields; i++) { + if (check_atype_tag(seq->fields[i], &t)) + break; + ret = omit_atype(seq->fields[i], val); + if (ret) + goto error; + } + /* We currently model all sequences as extensible. We should consider + * changing this before making the encoder visible to plugins. */ + if (i == seq->n_fields) + break; + ret = decode_atype(&t, contents, clen, seq->fields[i], val); + if (ret) + goto error; + } + /* Initialize any fields in the C object which were not accounted for in + * the sequence. Error out if any of them aren't optional. */ + for (; i < seq->n_fields; i++) { + ret = omit_atype(seq->fields[i], val); + if (ret) + goto error; + } + return 0; + +error: + /* Free what we've decoded so far. Free pointers in a second pass in + * case multiple fields refer to the same pointer. */ + for (j = 0; j < i; j++) + free_atype(seq->fields[j], val); + for (j = 0; j < i; j++) + free_atype_ptr(seq->fields[j], val); + return ret; +} + +static krb5_error_code +decode_sequence_of(const uint8_t *asn1, size_t len, + const struct atype_info *elemtype, void **seq_out, + size_t *count_out) +{ + krb5_error_code ret; + void *seq = NULL, *elem, *newseq; + const uint8_t *contents; + size_t clen, count = 0; + taginfo t; + + *seq_out = NULL; + *count_out = 0; + while (len > 0) { + ret = get_tag(asn1, len, &t, &contents, &clen, &asn1, &len); + if (ret) + goto error; + if (!check_atype_tag(elemtype, &t)) { + ret = ASN1_BAD_ID; + goto error; + } + newseq = realloc(seq, (count + 1) * elemtype->size); + if (newseq == NULL) { + ret = ENOMEM; + goto error; + } + seq = newseq; + elem = (char *)seq + count * elemtype->size; + memset(elem, 0, elemtype->size); + ret = decode_atype(&t, contents, clen, elemtype, elem); + if (ret) + goto error; + count++; + } + *seq_out = seq; + *count_out = count; + return 0; + +error: + free_sequence_of(elemtype, seq, count); + free(seq); + return ret; +} + +/* These three entry points are only needed for the kdc_req_body hack and may + * go away at some point. Define them here so we can use short names above. */ + +krb5_error_code +k5_asn1_encode_atype(asn1buf *buf, const void *val, const struct atype_info *a, + taginfo *tag_out) +{ + return encode_atype(buf, val, a, tag_out); +} + +krb5_error_code +k5_asn1_decode_atype(const taginfo *t, const uint8_t *asn1, size_t len, + const struct atype_info *a, void *val) +{ + return decode_atype(t, asn1, len, a, val); +} + +krb5_error_code +k5_asn1_full_encode(const void *rep, const struct atype_info *a, + krb5_data **code_out) +{ + krb5_error_code ret; + asn1buf buf; + krb5_data *d; + uint8_t *bytes; + + *code_out = NULL; + + if (rep == NULL) + return ASN1_MISSING_FIELD; + + /* Make a first pass over rep to count the encoding size. */ + buf.ptr = NULL; + buf.count = 0; + ret = encode_atype_and_tag(&buf, rep, a); + if (ret) + return ret; + + /* Allocate space for the encoding. */ + bytes = malloc(buf.count + 1); + if (bytes == NULL) + return ENOMEM; + bytes[buf.count] = 0; + + /* Make a second pass over rep to encode it. buf.ptr moves backwards as we + * encode, and will always exactly return to the base. */ + buf.ptr = bytes + buf.count; + buf.count = 0; + ret = encode_atype_and_tag(&buf, rep, a); + if (ret) { + free(bytes); + return ret; + } + assert(buf.ptr == bytes); + + /* Create the output data object. */ + *code_out = malloc(sizeof(*d)); + if (*code_out == NULL) { + free(bytes); + return ENOMEM; + } + **code_out = make_data(bytes, buf.count); + return 0; +} + +krb5_error_code +k5_asn1_full_decode(const krb5_data *code, const struct atype_info *a, + void **retrep) +{ + krb5_error_code ret; + const uint8_t *contents, *remainder; + size_t clen, rlen; + taginfo t; + + *retrep = NULL; + ret = get_tag((uint8_t *)code->data, code->length, &t, &contents, + &clen, &remainder, &rlen); + if (ret) + return ret; + /* rlen should be 0, but we don't check it (and due to padding in + * non-length-preserving enctypes, it will sometimes be nonzero). */ + if (!check_atype_tag(a, &t)) + return ASN1_BAD_ID; + return decode_atype_to_ptr(&t, contents, clen, a, retrep); +} diff --git a/krb5-1.21.3/src/lib/krb5/asn.1/asn1_encode.h b/krb5-1.21.3/src/lib/krb5/asn.1/asn1_encode.h new file mode 100644 index 00000000..118f5cad --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/asn.1/asn1_encode.h @@ -0,0 +1,577 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/asn.1/asn1_encode.h */ +/* + * Copyright 1994, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __ASN1_ENCODE_H__ +#define __ASN1_ENCODE_H__ + +#include "k5-int.h" +#include "krbasn1.h" +#include + +typedef struct asn1buf_st asn1buf; + +typedef struct { + asn1_class asn1class; + asn1_construction construction; + asn1_tagnum tagnum; + + /* When decoding, stores the leading length of a tag. Used by + * store_der(). */ + size_t tag_len; +} taginfo; + +/* These functions are referenced by encoder structures. They handle the + * encoding of primitive ASN.1 types. */ +void k5_asn1_encode_bool(asn1buf *buf, intmax_t val); +void k5_asn1_encode_int(asn1buf *buf, intmax_t val); +void k5_asn1_encode_uint(asn1buf *buf, uintmax_t val); +krb5_error_code k5_asn1_encode_bytestring(asn1buf *buf, uint8_t *const *val, + size_t len); +krb5_error_code k5_asn1_encode_bitstring(asn1buf *buf, uint8_t *const *val, + size_t len); +krb5_error_code k5_asn1_encode_generaltime(asn1buf *buf, time_t val); + +/* These functions are referenced by encoder structures. They handle the + * decoding of primitive ASN.1 types. */ +krb5_error_code k5_asn1_decode_bool(const uint8_t *asn1, size_t len, + intmax_t *val); +krb5_error_code k5_asn1_decode_int(const uint8_t *asn1, size_t len, + intmax_t *val); +krb5_error_code k5_asn1_decode_uint(const uint8_t *asn1, size_t len, + uintmax_t *val); +krb5_error_code k5_asn1_decode_generaltime(const uint8_t *asn1, size_t len, + time_t *time_out); +krb5_error_code k5_asn1_decode_bytestring(const uint8_t *asn1, size_t len, + uint8_t **str_out, size_t *len_out); +krb5_error_code k5_asn1_decode_bitstring(const uint8_t *asn1, size_t len, + uint8_t **bits_out, size_t *len_out); + +/* + * An atype_info structure specifies how to map a C object to an ASN.1 value. + * + * We wind up with a lot of load-time relocations being done, which is + * a bit annoying. Be careful about "fixing" that at the cost of too + * much run-time performance. It might work to have a master "module" + * descriptor with pointers to various arrays (type descriptors, + * strings, field descriptors, functions) most of which don't need + * relocation themselves, and replace most of the pointers with table + * indices. + * + * It's a work in progress. + */ + +enum atype_type { + /* For bounds checking only. By starting with 2, we guarantee that + * zero-initialized storage will be recognized as invalid. */ + atype_min = 1, + /* Use a function table to handle encoding or decoding. tinfo is a struct + * fn_info *. */ + atype_fn, + /* C object is a pointer to the object to be encoded or decoded. tinfo is + * a struct ptr_info *. */ + atype_ptr, + /* C object to be encoded or decoded is at an offset from the original + * pointer. tinfo is a struct offset_info *. */ + atype_offset, + /* + * Indicates a sequence field which may or may not be present in the C + * object or ASN.1 sequence. tinfo is a struct optional_info *. Must be + * used within a sequence, although the optional type may be nested within + * offset, ptr, and/or tag types. + */ + atype_optional, + /* + * C object contains an integer and another C object at specified offsets, + * to be combined and encoded or decoded as specified by a cntype_info + * structure. tinfo is a struct counted_info *. + */ + atype_counted, + /* Sequence. tinfo is a struct seq_info *. */ + atype_sequence, + /* + * Sequence-of, with pointer to base type descriptor, represented as a + * null-terminated array of pointers (and thus the "base" type descriptor + * is actually an atype_ptr node). tinfo is a struct atype_info * giving + * the base type. + */ + atype_nullterm_sequence_of, + atype_nonempty_nullterm_sequence_of, + /* Tagged version of another type. tinfo is a struct tagged_info *. */ + atype_tagged_thing, + /* Boolean value. tinfo is NULL (size field determines C type width). */ + atype_bool, + /* Signed or unsigned integer. tinfo is NULL. */ + atype_int, + atype_uint, + /* + * Integer value taken from the type info, not from the object being + * encoded. tinfo is a struct immediate_info * giving the integer value + * and error code to return if a decoded object doesn't match it (or 0 if + * the value shouldn't be checked on decode). + */ + atype_int_immediate, + /* Unused except for bounds checking. */ + atype_max +}; + +struct atype_info { + enum atype_type type; + size_t size; /* Used for sequence-of processing */ + const void *tinfo; /* Points to type-specific structure */ +}; + +struct fn_info { + krb5_error_code (*enc)(asn1buf *, const void *, taginfo *); + krb5_error_code (*dec)(const taginfo *, const uint8_t *, size_t, void *); + int (*check_tag)(const taginfo *); + void (*free_func)(void *); +}; + +struct ptr_info { + void *(*loadptr)(const void *); + void (*storeptr)(void *, void *); + const struct atype_info *basetype; +}; + +struct offset_info { + unsigned int dataoff : 9; + const struct atype_info *basetype; +}; + +struct optional_info { + int (*is_present)(const void *); + void (*init)(void *); + const struct atype_info *basetype; +}; + +struct counted_info { + unsigned int dataoff : 9; + unsigned int lenoff : 9; + unsigned int lensigned : 1; + unsigned int lensize : 5; + const struct cntype_info *basetype; +}; + +struct tagged_info { + unsigned int tagval : 16, tagtype : 8, construction : 6, implicit : 1; + const struct atype_info *basetype; +}; + +struct immediate_info { + intmax_t val; + krb5_error_code err; +}; + +/* A cntype_info structure specifies how to map a C object and count (length or + * union distinguisher) to an ASN.1 value. */ + +enum cntype_type { + cntype_min = 1, + + /* + * Apply an encoder function (contents only) and wrap it in a universal + * primitive tag. The C object must be a char * or uint8_t *. tinfo + * is a struct string_info *. + */ + cntype_string, + + /* + * The C object is a DER encoding (with tag), to be simply inserted on + * encode or stored on decode. The C object must be a char * or unsigned + * char *. tinfo is NULL. + */ + cntype_der, + + /* An ASN.1 sequence-of value, represtened in C as a counted array. struct + * atype_info * giving the base type, which must be of type atype_ptr. */ + cntype_seqof, + + /* An ASN.1 choice, represented in C as a distinguisher and union. tinfo + * is a struct choice_info *. */ + cntype_choice, + + cntype_max +}; + +struct cntype_info { + enum cntype_type type; + const void *tinfo; +}; + +struct string_info { + krb5_error_code (*enc)(asn1buf *, uint8_t *const *, size_t); + krb5_error_code (*dec)(const uint8_t *, size_t, uint8_t **, size_t *); + unsigned int tagval : 5; +}; + +struct choice_info { + const struct atype_info **options; + size_t n_options; +}; + +struct seq_info { + const struct atype_info **fields; + size_t n_fields; + /* Currently all sequences are assumed to be extensible. */ +}; + +/* + * The various DEF*TYPE macros must: + * + * + Define a type named aux_type_##DESCNAME, for use in any types derived from + * the type being defined. + * + * + Define an atype_info struct named k5_atype_##DESCNAME + * + * + Define a type-specific structure, referenced by the tinfo field + * of the atype_info structure. + * + * + Define any extra stuff needed in the type descriptor, like + * pointer-load functions. + * + * + Accept a following semicolon syntactically, to keep Emacs parsing + * (and indentation calculating) code happy. + * + * Nothing else should directly define the atype_info structures. + */ + +/* Define a type using a function table. */ +#define DEFFNTYPE(DESCNAME, CTYPENAME, ENCFN, DECFN, CHECKFN, FREEFN) \ + typedef CTYPENAME aux_type_##DESCNAME; \ + static const struct fn_info aux_info_##DESCNAME = { \ + ENCFN, DECFN, CHECKFN, FREEFN \ + }; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_fn, sizeof(CTYPENAME), &aux_info_##DESCNAME \ + } +/* A sequence, defined by the indicated series of types, and an optional + * function indicating which fields are not present. */ +#define DEFSEQTYPE(DESCNAME, CTYPENAME, FIELDS) \ + typedef CTYPENAME aux_type_##DESCNAME; \ + static const struct seq_info aux_seqinfo_##DESCNAME = { \ + FIELDS, sizeof(FIELDS)/sizeof(FIELDS[0]) \ + }; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_sequence, sizeof(CTYPENAME), &aux_seqinfo_##DESCNAME \ + } +/* A boolean type. */ +#define DEFBOOLTYPE(DESCNAME, CTYPENAME) \ + typedef CTYPENAME aux_type_##DESCNAME; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_bool, sizeof(CTYPENAME), NULL \ + } +/* Integer types. */ +#define DEFINTTYPE(DESCNAME, CTYPENAME) \ + typedef CTYPENAME aux_type_##DESCNAME; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_int, sizeof(CTYPENAME), NULL \ + } +#define DEFUINTTYPE(DESCNAME, CTYPENAME) \ + typedef CTYPENAME aux_type_##DESCNAME; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_uint, sizeof(CTYPENAME), NULL \ + } +#define DEFINT_IMMEDIATE(DESCNAME, VAL, ERR) \ + typedef int aux_type_##DESCNAME; \ + static const struct immediate_info aux_info_##DESCNAME = { \ + VAL, ERR \ + }; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_int_immediate, 0, &aux_info_##DESCNAME \ + } + +/* Pointers to other types, to be encoded as those other types. */ +#ifdef POINTERS_ARE_ALL_THE_SAME +#define DEFPTRTYPE(DESCNAME,BASEDESCNAME) \ + typedef aux_type_##BASEDESCNAME *aux_type_##DESCNAME; \ + static const struct ptr_info aux_info_##DESCNAME = { \ + NULL, NULL, &k5_atype_##BASEDESCNAME \ + }; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_ptr, sizeof(aux_type_##DESCNAME), \ + &aux_info_##DESCNAME \ + } +#else +#define DEFPTRTYPE(DESCNAME,BASEDESCNAME) \ + typedef aux_type_##BASEDESCNAME *aux_type_##DESCNAME; \ + static void * \ + aux_loadptr_##DESCNAME(const void *p) \ + { \ + return *(aux_type_##DESCNAME *)p; \ + } \ + static void \ + aux_storeptr_##DESCNAME(void *ptr, void *val) \ + { \ + *(aux_type_##DESCNAME *)val = ptr; \ + } \ + static const struct ptr_info aux_info_##DESCNAME = { \ + aux_loadptr_##DESCNAME, aux_storeptr_##DESCNAME, \ + &k5_atype_##BASEDESCNAME \ + }; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_ptr, sizeof(aux_type_##DESCNAME), \ + &aux_info_##DESCNAME \ + } +#endif +#define DEFOFFSETTYPE(DESCNAME, STYPE, FIELDNAME, BASEDESC) \ + typedef STYPE aux_type_##DESCNAME; \ + static const struct offset_info aux_info_##DESCNAME = { \ + OFFOF(STYPE, FIELDNAME, aux_type_##BASEDESC), \ + &k5_atype_##BASEDESC \ + }; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_offset, sizeof(aux_type_##DESCNAME), \ + &aux_info_##DESCNAME \ + } +#define DEFCOUNTEDTYPE_base(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, SIGNED, \ + CDESC) \ + typedef STYPE aux_type_##DESCNAME; \ + const struct counted_info aux_info_##DESCNAME = { \ + OFFOF(STYPE, DATAFIELD, aux_ptrtype_##CDESC), \ + OFFOF(STYPE, COUNTFIELD, aux_counttype_##CDESC), \ + SIGNED, sizeof(((STYPE*)0)->COUNTFIELD), \ + &k5_cntype_##CDESC \ + }; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_counted, sizeof(STYPE), \ + &aux_info_##DESCNAME \ + } +#define DEFCOUNTEDTYPE(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, CDESC) \ + DEFCOUNTEDTYPE_base(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, 0, CDESC) +#define DEFCOUNTEDTYPE_SIGNED(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, CDESC) \ + DEFCOUNTEDTYPE_base(DESCNAME, STYPE, DATAFIELD, COUNTFIELD, 1, CDESC) + +/* Optional sequence fields. The basic form allows arbitrary test and + * initializer functions to be used. INIT may be null. */ +#define DEFOPTIONALTYPE(DESCNAME, PRESENT, INIT, BASEDESC) \ + typedef aux_type_##BASEDESC aux_type_##DESCNAME; \ + static const struct optional_info aux_info_##DESCNAME = { \ + PRESENT, INIT, &k5_atype_##BASEDESC \ + }; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_optional, sizeof(aux_type_##DESCNAME), \ + &aux_info_##DESCNAME \ + } +/* This form defines an is_present function for a zero-valued integer or null + * pointer of the base type's C type. */ +#define DEFOPTIONALZEROTYPE(DESCNAME, BASEDESC) \ + static int \ + aux_present_##DESCNAME(const void *p) \ + { \ + return *(aux_type_##BASEDESC *)p != 0; \ + } \ + DEFOPTIONALTYPE(DESCNAME, aux_present_##DESCNAME, NULL, BASEDESC) +/* This form defines an is_present function for a null or empty null-terminated + * array of the base type's C type. */ +#define DEFOPTIONALEMPTYTYPE(DESCNAME, BASEDESC) \ + static int \ + aux_present_##DESCNAME(const void *p) \ + { \ + const aux_type_##BASEDESC *val = p; \ + return (*val != NULL && **val != NULL); \ + } \ + DEFOPTIONALTYPE(DESCNAME, aux_present_##DESCNAME, NULL, BASEDESC) + +/* + * This encodes a pointer-to-pointer-to-thing where the passed-in + * value points to a null-terminated list of pointers to objects to be + * encoded, and encodes a (possibly empty) SEQUENCE OF these objects. + * + * BASEDESCNAME is a descriptor name for the pointer-to-thing + * type. + * + * When dealing with a structure containing a + * pointer-to-pointer-to-thing field, make a DEFPTRTYPE of this type, + * and use that type for the structure field. + */ +#define DEFNULLTERMSEQOFTYPE(DESCNAME,BASEDESCNAME) \ + typedef aux_type_##BASEDESCNAME aux_type_##DESCNAME; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_nullterm_sequence_of, sizeof(aux_type_##DESCNAME), \ + &k5_atype_##BASEDESCNAME \ + } +#define DEFNONEMPTYNULLTERMSEQOFTYPE(DESCNAME,BASEDESCNAME) \ + typedef aux_type_##BASEDESCNAME aux_type_##DESCNAME; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_nonempty_nullterm_sequence_of, \ + sizeof(aux_type_##DESCNAME), \ + &k5_atype_##BASEDESCNAME \ + } + +/* Objects with an explicit or implicit tag. (Implicit tags will ignore the + * construction field.) */ +#define DEFTAGGEDTYPE(DESCNAME, CLASS, CONSTRUCTION, TAG, IMPLICIT, BASEDESC) \ + typedef aux_type_##BASEDESC aux_type_##DESCNAME; \ + static const struct tagged_info aux_info_##DESCNAME = { \ + TAG, CLASS, CONSTRUCTION, IMPLICIT, &k5_atype_##BASEDESC \ + }; \ + const struct atype_info k5_atype_##DESCNAME = { \ + atype_tagged_thing, sizeof(aux_type_##DESCNAME), \ + &aux_info_##DESCNAME \ + } +/* Objects with an explicit APPLICATION tag added. */ +#define DEFAPPTAGGEDTYPE(DESCNAME, TAG, BASEDESC) \ + DEFTAGGEDTYPE(DESCNAME, APPLICATION, CONSTRUCTED, TAG, 0, BASEDESC) +/* Object with a context-specific tag added */ +#define DEFCTAGGEDTYPE(DESCNAME, TAG, BASEDESC) \ + DEFTAGGEDTYPE(DESCNAME, CONTEXT_SPECIFIC, CONSTRUCTED, TAG, 0, BASEDESC) +#define DEFCTAGGEDTYPE_IMPLICIT(DESCNAME, TAG, BASEDESC) \ + DEFTAGGEDTYPE(DESCNAME, CONTEXT_SPECIFIC, CONSTRUCTED, TAG, 1, BASEDESC) + +/* Define an offset type with an explicit context tag wrapper (the usual case + * for an RFC 4120 sequence field). */ +#define DEFFIELD(NAME, STYPE, FIELDNAME, TAG, DESC) \ + DEFOFFSETTYPE(NAME##_untagged, STYPE, FIELDNAME, DESC); \ + DEFCTAGGEDTYPE(NAME, TAG, NAME##_untagged) +/* Define a counted type with an explicit context tag wrapper. */ +#define DEFCNFIELD(NAME, STYPE, DATAFIELD, LENFIELD, TAG, CDESC) \ + DEFCOUNTEDTYPE(NAME##_untagged, STYPE, DATAFIELD, LENFIELD, CDESC); \ + DEFCTAGGEDTYPE(NAME, TAG, NAME##_untagged) +/* Like DEFFIELD but with an implicit context tag. */ +#define DEFFIELD_IMPLICIT(NAME, STYPE, FIELDNAME, TAG, DESC) \ + DEFOFFSETTYPE(NAME##_untagged, STYPE, FIELDNAME, DESC); \ + DEFCTAGGEDTYPE_IMPLICIT(NAME, TAG, NAME##_untagged) + +/* + * DEFCOUNTED*TYPE macros must: + * + * + Define types named aux_ptrtype_##DESCNAME and aux_counttype_##DESCNAME, to + * allow type checking when the counted type is referenced with structure + * field offsets in DEFCOUNTEDTYPE. + * + * + Define a cntype_info struct named k5_cntype_##DESCNAME + * + * + Define a type-specific structure, referenced by the tinfo field of the + * cntype_info structure. + * + * + Accept a following semicolon syntactically. + */ + +#define DEFCOUNTEDSTRINGTYPE(DESCNAME, DTYPE, LTYPE, ENCFN, DECFN, TAGVAL) \ + typedef DTYPE aux_ptrtype_##DESCNAME; \ + typedef LTYPE aux_counttype_##DESCNAME; \ + static const struct string_info aux_info_##DESCNAME = { \ + ENCFN, DECFN, TAGVAL \ + }; \ + const struct cntype_info k5_cntype_##DESCNAME = { \ + cntype_string, &aux_info_##DESCNAME \ + } + +#define DEFCOUNTEDDERTYPE(DESCNAME, DTYPE, LTYPE) \ + typedef DTYPE aux_ptrtype_##DESCNAME; \ + typedef LTYPE aux_counttype_##DESCNAME; \ + const struct cntype_info k5_cntype_##DESCNAME = { \ + cntype_der, NULL \ + } + +#define DEFCOUNTEDSEQOFTYPE(DESCNAME, LTYPE, BASEDESC) \ + typedef aux_type_##BASEDESC aux_ptrtype_##DESCNAME; \ + typedef LTYPE aux_counttype_##DESCNAME; \ + const struct cntype_info k5_cntype_##DESCNAME = { \ + cntype_seqof, &k5_atype_##BASEDESC \ + } + +#define DEFCHOICETYPE(DESCNAME, UTYPE, DTYPE, FIELDS) \ + typedef UTYPE aux_ptrtype_##DESCNAME; \ + typedef DTYPE aux_counttype_##DESCNAME; \ + static const struct choice_info aux_info_##DESCNAME = { \ + FIELDS, sizeof(FIELDS) / sizeof(FIELDS[0]) \ + }; \ + const struct cntype_info k5_cntype_##DESCNAME = { \ + cntype_choice, &aux_info_##DESCNAME \ + } + +/* + * Declare an externally-defined type. This is a hack we should do + * away with once we move to generating code from a script. For now, + * this macro is unfortunately not compatible with the defining macros + * above, since you can't do the typedefs twice and we need the + * declarations to produce typedefs. (We could eliminate the typedefs + * from the DEF* macros, but then every DEF* macro use, even the ones + * for internal type nodes we only use to build other types, would + * need an accompanying declaration which explicitly lists the + * type.) + */ +#define IMPORT_TYPE(DESCNAME, CTYPENAME) \ + typedef CTYPENAME aux_type_##DESCNAME; \ + extern const struct atype_info k5_atype_##DESCNAME + +/* Partially encode the contents of a type and return its tag information. + * Used only by kdc_req_body. */ +krb5_error_code +k5_asn1_encode_atype(asn1buf *buf, const void *val, const struct atype_info *a, + taginfo *tag_out); + +/* Decode the tag and contents of a type, storing the result in the + * caller-allocated C object val. Used only by kdc_req_body. */ +krb5_error_code +k5_asn1_decode_atype(const taginfo *t, const uint8_t *asn1, size_t len, + const struct atype_info *a, void *val); + +/* Returns a completed encoding, with tag and in the correct byte order, in an + * allocated krb5_data. */ +extern krb5_error_code +k5_asn1_full_encode(const void *rep, const struct atype_info *a, + krb5_data **code_out); +krb5_error_code +k5_asn1_full_decode(const krb5_data *code, const struct atype_info *a, + void **rep_out); + +#define MAKE_ENCODER(FNAME, DESC) \ + krb5_error_code \ + FNAME(const aux_type_##DESC *rep, krb5_data **code_out) \ + { \ + return k5_asn1_full_encode(rep, &k5_atype_##DESC, code_out); \ + } \ + extern int dummy /* gobble semicolon */ + +#define MAKE_DECODER(FNAME, DESC) \ + krb5_error_code \ + FNAME(const krb5_data *code, aux_type_##DESC **rep_out) \ + { \ + krb5_error_code ret; \ + void *rep; \ + *rep_out = NULL; \ + ret = k5_asn1_full_decode(code, &k5_atype_##DESC, &rep); \ + if (ret) \ + return ret; \ + *rep_out = rep; \ + return 0; \ + } \ + extern int dummy /* gobble semicolon */ + +#include +/* + * Ugly hack! + * Like "offsetof", but with type checking. + */ +#define WARN_IF_TYPE_MISMATCH(LVALUE, TYPE) \ + (sizeof(0 ? (TYPE *) 0 : &(LVALUE))) +#define OFFOF(TYPE,FIELD,FTYPE) \ + (offsetof(TYPE, FIELD) \ + + 0 * WARN_IF_TYPE_MISMATCH(((TYPE*)0)->FIELD, FTYPE)) + +#endif diff --git a/krb5-1.21.3/src/lib/krb5/asn.1/asn1_k_encode.c b/krb5-1.21.3/src/lib/krb5/asn.1/asn1_k_encode.c new file mode 100644 index 00000000..5378b5c2 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/asn.1/asn1_k_encode.c @@ -0,0 +1,1759 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/asn.1/asn1_k_encode.c */ +/* + * Copyright 1994, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "asn1_encode.h" +#include "k5-spake.h" + +DEFINT_IMMEDIATE(krb5_version, KVNO, KRB5KDC_ERR_BAD_PVNO); + +static int +int32_not_minus1(const void *p) +{ + return *(int32_t *)p != -1; +} + +static void +init_int32_minus1(void *p) +{ + *(int32_t *)p = -1; +} + +DEFBOOLTYPE(boolean, krb5_boolean); +DEFINTTYPE(int32, int32_t); +DEFPTRTYPE(int32_ptr, int32); +DEFCOUNTEDSEQOFTYPE(cseqof_int32, int32_t, int32_ptr); +DEFOPTIONALZEROTYPE(opt_int32, int32); +DEFOPTIONALTYPE(opt_int32_minus1, int32_not_minus1, init_int32_minus1, int32); + +DEFUINTTYPE(uint, unsigned int); +DEFUINTTYPE(octet, krb5_octet); +DEFUINTTYPE(uint32, uint32_t); +DEFOPTIONALZEROTYPE(opt_uint, uint); + +static int +nonempty_data(const void *p) +{ + const krb5_data *val = p; + return (val->data != NULL && val->length != 0); +} + +DEFCOUNTEDDERTYPE(der, char *, unsigned int); +DEFCOUNTEDTYPE(der_data, krb5_data, data, length, der); +DEFOPTIONALTYPE(opt_der_data, nonempty_data, NULL, der_data); + +DEFCOUNTEDSTRINGTYPE(octetstring, uint8_t *, unsigned int, + k5_asn1_encode_bytestring, k5_asn1_decode_bytestring, + ASN1_OCTETSTRING); +DEFCOUNTEDSTRINGTYPE(s_octetstring, char *, unsigned int, + k5_asn1_encode_bytestring, k5_asn1_decode_bytestring, + ASN1_OCTETSTRING); +DEFCOUNTEDTYPE(ostring_data, krb5_data, data, length, s_octetstring); +DEFPTRTYPE(ostring_data_ptr, ostring_data); +DEFOPTIONALTYPE(opt_ostring_data, nonempty_data, NULL, ostring_data); +DEFOPTIONALZEROTYPE(opt_ostring_data_ptr, ostring_data_ptr); + +DEFCOUNTEDSTRINGTYPE(generalstring, char *, unsigned int, + k5_asn1_encode_bytestring, k5_asn1_decode_bytestring, + ASN1_GENERALSTRING); +DEFCOUNTEDSTRINGTYPE(u_generalstring, uint8_t *, unsigned int, + k5_asn1_encode_bytestring, k5_asn1_decode_bytestring, + ASN1_GENERALSTRING); +DEFCOUNTEDTYPE(gstring_data, krb5_data, data, length, generalstring); +DEFOPTIONALTYPE(opt_gstring_data, nonempty_data, NULL, gstring_data); +DEFPTRTYPE(gstring_data_ptr, gstring_data); +DEFCOUNTEDSEQOFTYPE(cseqof_gstring_data, int32_t, gstring_data_ptr); + +DEFCOUNTEDSTRINGTYPE(utf8string, char *, unsigned int, + k5_asn1_encode_bytestring, k5_asn1_decode_bytestring, + ASN1_UTF8STRING); +DEFCOUNTEDTYPE(utf8_data, krb5_data, data, length, utf8string); +DEFOPTIONALTYPE(opt_utf8_data, nonempty_data, NULL, utf8_data); +DEFPTRTYPE(utf8_data_ptr, utf8_data); +DEFNULLTERMSEQOFTYPE(seqof_utf8_data, utf8_data_ptr); + +DEFCOUNTEDSTRINGTYPE(object_identifier, char *, unsigned int, + k5_asn1_encode_bytestring, k5_asn1_decode_bytestring, + ASN1_OBJECTIDENTIFIER); +DEFCOUNTEDTYPE(oid_data, krb5_data, data, length, object_identifier); +DEFPTRTYPE(oid_data_ptr, oid_data); + +DEFOFFSETTYPE(realm_of_principal_data, krb5_principal_data, realm, + gstring_data); +DEFPTRTYPE(realm_of_principal, realm_of_principal_data); +DEFOPTIONALZEROTYPE(opt_realm_of_principal, realm_of_principal); + +DEFFIELD(princname_0, krb5_principal_data, type, 0, int32); +DEFCNFIELD(princname_1, krb5_principal_data, data, length, 1, + cseqof_gstring_data); +static const struct atype_info *princname_fields[] = { + &k5_atype_princname_0, &k5_atype_princname_1 +}; +DEFSEQTYPE(principal_data, krb5_principal_data, princname_fields); +DEFPTRTYPE(principal, principal_data); +DEFOPTIONALZEROTYPE(opt_principal, principal); + +/* + * Define the seqno type, which is an ASN.1 integer represented in a uint32_t. + * When decoding, negative 32-bit numbers are accepted for interoperability + * with old implementations. + */ +static krb5_error_code +encode_seqno(asn1buf *buf, const void *p, taginfo *rettag) +{ + uint32_t val = *(uint32_t *)p; + rettag->asn1class = UNIVERSAL; + rettag->construction = PRIMITIVE; + rettag->tagnum = ASN1_INTEGER; + k5_asn1_encode_uint(buf, val); + return 0; +} +static krb5_error_code +decode_seqno(const taginfo *t, const uint8_t *asn1, size_t len, void *p) +{ + krb5_error_code ret; + intmax_t val; + ret = k5_asn1_decode_int(asn1, len, &val); + if (ret) + return ret; + if (val < INT32_MIN || val > 0xFFFFFFFF) + return ASN1_OVERFLOW; + /* Negative values will cast correctly to uint32_t. */ + *(uint32_t *)p = val; + return 0; +} +static int +check_seqno(const taginfo *t) +{ + return (t->asn1class == UNIVERSAL && t->construction == PRIMITIVE && + t->tagnum == ASN1_INTEGER); +} +DEFFNTYPE(seqno, uint32_t, encode_seqno, decode_seqno, check_seqno, NULL); +DEFOPTIONALZEROTYPE(opt_seqno, seqno); + +/* Define the kerberos_time type, which is an ASN.1 generaltime represented in + * a krb5_timestamp. */ +static krb5_error_code +encode_kerberos_time(asn1buf *buf, const void *p, taginfo *rettag) +{ + time_t val = ts2tt(*(krb5_timestamp *)p); + rettag->asn1class = UNIVERSAL; + rettag->construction = PRIMITIVE; + rettag->tagnum = ASN1_GENERALTIME; + return k5_asn1_encode_generaltime(buf, val); +} +static krb5_error_code +decode_kerberos_time(const taginfo *t, const uint8_t *asn1, size_t len, + void *p) +{ + krb5_error_code ret; + time_t val; + ret = k5_asn1_decode_generaltime(asn1, len, &val); + if (ret) + return ret; + *(krb5_timestamp *)p = val; + return 0; +} +static int +check_kerberos_time(const taginfo *t) +{ + return (t->asn1class == UNIVERSAL && t->construction == PRIMITIVE && + t->tagnum == ASN1_GENERALTIME); +} +DEFFNTYPE(kerberos_time, krb5_timestamp, encode_kerberos_time, + decode_kerberos_time, check_kerberos_time, NULL); +DEFOPTIONALZEROTYPE(opt_kerberos_time, kerberos_time); + +DEFFIELD(address_0, krb5_address, addrtype, 0, int32); +DEFCNFIELD(address_1, krb5_address, contents, length, 1, octetstring); +const static struct atype_info *address_fields[] = { + &k5_atype_address_0, &k5_atype_address_1 +}; +DEFSEQTYPE(address, krb5_address, address_fields); +DEFPTRTYPE(address_ptr, address); +DEFOPTIONALZEROTYPE(opt_address_ptr, address_ptr); + +DEFNULLTERMSEQOFTYPE(seqof_host_addresses, address_ptr); +DEFPTRTYPE(ptr_seqof_host_addresses, seqof_host_addresses); +DEFOPTIONALEMPTYTYPE(opt_ptr_seqof_host_addresses, ptr_seqof_host_addresses); + +/* + * krb5_kvno is defined as unsigned int, but historically (MIT krb5 through 1.6 + * in the encoder, and through 1.10 in the decoder) we treat it as signed, in + * violation of RFC 4120. kvno values large enough to be problematic are only + * likely to be seen with Windows read-only domain controllers, which overload + * the high 16-bits of kvno values for krbtgt principals. Since Windows + * encodes kvnos as signed 32-bit values, for interoperability it's best if we + * do the same. + */ +DEFINTTYPE(kvno, krb5_kvno); +DEFOPTIONALZEROTYPE(opt_kvno, kvno); + +DEFFIELD(enc_data_0, krb5_enc_data, enctype, 0, int32); +DEFFIELD(enc_data_1, krb5_enc_data, kvno, 1, opt_kvno); +DEFFIELD(enc_data_2, krb5_enc_data, ciphertext, 2, ostring_data); +static const struct atype_info *encrypted_data_fields[] = { + &k5_atype_enc_data_0, &k5_atype_enc_data_1, &k5_atype_enc_data_2 +}; +DEFSEQTYPE(encrypted_data, krb5_enc_data, encrypted_data_fields); +static int +nonempty_enc_data(const void *p) +{ + const krb5_enc_data *val = p; + return (val->ciphertext.data != NULL); +} +DEFOPTIONALTYPE(opt_encrypted_data, nonempty_enc_data, NULL, encrypted_data); + +/* Define the krb5_flags type, which is an ASN.1 bit string represented in a + * 32-bit integer. */ +static krb5_error_code +encode_krb5_flags(asn1buf *buf, const void *p, taginfo *rettag) +{ + uint8_t cbuf[4], *cptr = cbuf; + store_32_be((uint32_t)*(const krb5_flags *)p, cbuf); + rettag->asn1class = UNIVERSAL; + rettag->construction = PRIMITIVE; + rettag->tagnum = ASN1_BITSTRING; + return k5_asn1_encode_bitstring(buf, &cptr, 4); +} +static krb5_error_code +decode_krb5_flags(const taginfo *t, const uint8_t *asn1, size_t len, void *val) +{ + krb5_error_code ret; + size_t i, blen; + krb5_flags f = 0; + uint8_t *bits; + ret = k5_asn1_decode_bitstring(asn1, len, &bits, &blen); + if (ret) + return ret; + /* Copy up to 32 bits into f, starting at the most significant byte. */ + for (i = 0; i < blen && i < 4; i++) + f |= bits[i] << (8 * (3 - i)); + *(krb5_flags *)val = f; + free(bits); + return 0; +} +static int +check_krb5_flags(const taginfo *t) +{ + return (t->asn1class == UNIVERSAL && t->construction == PRIMITIVE && + t->tagnum == ASN1_BITSTRING); +} +DEFFNTYPE(krb5_flags, krb5_flags, encode_krb5_flags, decode_krb5_flags, + check_krb5_flags, NULL); +DEFOPTIONALZEROTYPE(opt_krb5_flags, krb5_flags); + +DEFFIELD(authdata_0, krb5_authdata, ad_type, 0, int32); +DEFCNFIELD(authdata_1, krb5_authdata, contents, length, 1, octetstring); +static const struct atype_info *authdata_elt_fields[] = { + &k5_atype_authdata_0, &k5_atype_authdata_1 +}; +DEFSEQTYPE(authdata_elt, krb5_authdata, authdata_elt_fields); +DEFPTRTYPE(authdata_elt_ptr, authdata_elt); +DEFNONEMPTYNULLTERMSEQOFTYPE(auth_data, authdata_elt_ptr); +DEFPTRTYPE(auth_data_ptr, auth_data); +DEFOPTIONALEMPTYTYPE(opt_auth_data_ptr, auth_data_ptr); + +/* authdata_types retrieves just the types of authdata elements in an array. */ +DEFCTAGGEDTYPE(authdata_elt_type_0, 0, int32); +static const struct atype_info *authdata_elt_type_fields[] = { + &k5_atype_authdata_elt_type_0 +}; +DEFSEQTYPE(authdata_elt_type, krb5_authdatatype, authdata_elt_type_fields); +DEFPTRTYPE(ptr_authdata_elt_type, authdata_elt_type); +DEFCOUNTEDSEQOFTYPE(cseqof_authdata_elt_type, unsigned int, + ptr_authdata_elt_type); +struct authdata_types { + krb5_authdatatype *types; + unsigned int ntypes; +}; +DEFCOUNTEDTYPE(authdata_types, struct authdata_types, types, ntypes, + cseqof_authdata_elt_type); + +DEFFIELD(keyblock_0, krb5_keyblock, enctype, 0, int32); +DEFCNFIELD(keyblock_1, krb5_keyblock, contents, length, 1, octetstring); +static const struct atype_info *encryption_key_fields[] = { + &k5_atype_keyblock_0, &k5_atype_keyblock_1 +}; +DEFSEQTYPE(encryption_key, krb5_keyblock, encryption_key_fields); +DEFPTRTYPE(ptr_encryption_key, encryption_key); +DEFOPTIONALZEROTYPE(opt_ptr_encryption_key, ptr_encryption_key); + +DEFFIELD(checksum_0, krb5_checksum, checksum_type, 0, int32); +DEFCNFIELD(checksum_1, krb5_checksum, contents, length, 1, octetstring); +static const struct atype_info *checksum_fields[] = { + &k5_atype_checksum_0, &k5_atype_checksum_1 +}; +DEFSEQTYPE(checksum, krb5_checksum, checksum_fields); +DEFPTRTYPE(checksum_ptr, checksum); +DEFNULLTERMSEQOFTYPE(seqof_checksum, checksum_ptr); +DEFPTRTYPE(ptr_seqof_checksum, seqof_checksum); +DEFOPTIONALZEROTYPE(opt_checksum_ptr, checksum_ptr); + +/* Define the last_req_type type, which is an int32_t with some massaging on + * decode for backward compatibility. */ +static krb5_error_code +encode_lr_type(asn1buf *buf, const void *p, taginfo *rettag) +{ + int32_t val = *(int32_t *)p; + rettag->asn1class = UNIVERSAL; + rettag->construction = PRIMITIVE; + rettag->tagnum = ASN1_INTEGER; + k5_asn1_encode_int(buf, val); + return 0; +} +static krb5_error_code +decode_lr_type(const taginfo *t, const uint8_t *asn1, size_t len, void *p) +{ + krb5_error_code ret; + intmax_t val; + ret = k5_asn1_decode_int(asn1, len, &val); + if (ret) + return ret; + if (val > INT32_MAX || val < INT32_MIN) + return ASN1_OVERFLOW; + *(int32_t *)p = val; + return 0; +} +static int +check_lr_type(const taginfo *t) +{ + return (t->asn1class == UNIVERSAL && t->construction == PRIMITIVE && + t->tagnum == ASN1_INTEGER); +} +DEFFNTYPE(last_req_type, int32_t, encode_lr_type, decode_lr_type, + check_lr_type, NULL); + +DEFFIELD(last_req_0, krb5_last_req_entry, lr_type, 0, last_req_type); +DEFFIELD(last_req_1, krb5_last_req_entry, value, 1, kerberos_time); +static const struct atype_info *lr_fields[] = { + &k5_atype_last_req_0, &k5_atype_last_req_1 +}; +DEFSEQTYPE(last_req_ent, krb5_last_req_entry, lr_fields); + +DEFPTRTYPE(last_req_ent_ptr, last_req_ent); +DEFNONEMPTYNULLTERMSEQOFTYPE(last_req, last_req_ent_ptr); +DEFPTRTYPE(last_req_ptr, last_req); + +DEFCTAGGEDTYPE(ticket_0, 0, krb5_version); +DEFFIELD(ticket_1, krb5_ticket, server, 1, realm_of_principal); +DEFFIELD(ticket_2, krb5_ticket, server, 2, principal); +DEFFIELD(ticket_3, krb5_ticket, enc_part, 3, encrypted_data); +static const struct atype_info *ticket_fields[] = { + &k5_atype_ticket_0, &k5_atype_ticket_1, &k5_atype_ticket_2, + &k5_atype_ticket_3 +}; +DEFSEQTYPE(untagged_ticket, krb5_ticket, ticket_fields); +DEFAPPTAGGEDTYPE(ticket, 1, untagged_ticket); + +/* First context tag is 1, not 0. */ +DEFFIELD(pa_data_1, krb5_pa_data, pa_type, 1, int32); +DEFCNFIELD(pa_data_2, krb5_pa_data, contents, length, 2, octetstring); +static const struct atype_info *pa_data_fields[] = { + &k5_atype_pa_data_1, &k5_atype_pa_data_2 +}; +DEFSEQTYPE(pa_data, krb5_pa_data, pa_data_fields); +DEFPTRTYPE(pa_data_ptr, pa_data); + +DEFNULLTERMSEQOFTYPE(seqof_pa_data, pa_data_ptr); +DEFPTRTYPE(ptr_seqof_pa_data, seqof_pa_data); +DEFOPTIONALEMPTYTYPE(opt_ptr_seqof_pa_data, ptr_seqof_pa_data); + +DEFPTRTYPE(ticket_ptr, ticket); +DEFNONEMPTYNULLTERMSEQOFTYPE(seqof_ticket,ticket_ptr); +DEFPTRTYPE(ptr_seqof_ticket, seqof_ticket); +DEFOPTIONALEMPTYTYPE(opt_ptr_seqof_ticket, ptr_seqof_ticket); + +static int +is_enc_kdc_rep_start_set(const void *p) +{ + const krb5_enc_kdc_rep_part *val = p; + return (val->times.starttime != 0); +} +static void +init_enc_kdc_rep_start(void *p) +{ + krb5_enc_kdc_rep_part *val = p; + val->times.starttime = val->times.authtime; +} +static int +is_renewable_flag_set(const void *p) +{ + const krb5_enc_kdc_rep_part *val = p; + return (val->flags & TKT_FLG_RENEWABLE); +} +DEFFIELD(enc_kdc_rep_0, krb5_enc_kdc_rep_part, session, 0, ptr_encryption_key); +DEFFIELD(enc_kdc_rep_1, krb5_enc_kdc_rep_part, last_req, 1, last_req_ptr); +DEFFIELD(enc_kdc_rep_2, krb5_enc_kdc_rep_part, nonce, 2, int32); +DEFFIELD(enc_kdc_rep_3, krb5_enc_kdc_rep_part, key_exp, 3, opt_kerberos_time); +DEFFIELD(enc_kdc_rep_4, krb5_enc_kdc_rep_part, flags, 4, krb5_flags); +DEFFIELD(enc_kdc_rep_5, krb5_enc_kdc_rep_part, times.authtime, 5, + kerberos_time); +DEFFIELD(enc_kdc_rep_6_def, krb5_enc_kdc_rep_part, times.starttime, 6, + kerberos_time); +DEFOPTIONALTYPE(enc_kdc_rep_6, is_enc_kdc_rep_start_set, + init_enc_kdc_rep_start, enc_kdc_rep_6_def); +DEFFIELD(enc_kdc_rep_7, krb5_enc_kdc_rep_part, times.endtime, 7, + kerberos_time); +DEFFIELD(enc_kdc_rep_8_def, krb5_enc_kdc_rep_part, times.renew_till, 8, + kerberos_time); +DEFOPTIONALTYPE(enc_kdc_rep_8, is_renewable_flag_set, NULL, enc_kdc_rep_8_def); +DEFFIELD(enc_kdc_rep_9, krb5_enc_kdc_rep_part, server, 9, realm_of_principal); +DEFFIELD(enc_kdc_rep_10, krb5_enc_kdc_rep_part, server, 10, principal); +DEFFIELD(enc_kdc_rep_11, krb5_enc_kdc_rep_part, caddrs, 11, + opt_ptr_seqof_host_addresses); +DEFFIELD(enc_kdc_rep_12, krb5_enc_kdc_rep_part, enc_padata, 12, + opt_ptr_seqof_pa_data); +static const struct atype_info *enc_kdc_rep_part_fields[] = { + &k5_atype_enc_kdc_rep_0, &k5_atype_enc_kdc_rep_1, &k5_atype_enc_kdc_rep_2, + &k5_atype_enc_kdc_rep_3, &k5_atype_enc_kdc_rep_4, &k5_atype_enc_kdc_rep_5, + &k5_atype_enc_kdc_rep_6, &k5_atype_enc_kdc_rep_7, &k5_atype_enc_kdc_rep_8, + &k5_atype_enc_kdc_rep_9, &k5_atype_enc_kdc_rep_10, + &k5_atype_enc_kdc_rep_11, &k5_atype_enc_kdc_rep_12 +}; +DEFSEQTYPE(enc_kdc_rep_part, krb5_enc_kdc_rep_part, enc_kdc_rep_part_fields); + +/* + * Yuck! Eventually push this *up* above the encoder API and make the + * rest of the library put the realm name in one consistent place. At + * the same time, might as well add the msg-type field and encode both + * AS-REQ and TGS-REQ through the same descriptor. + */ +typedef struct kdc_req_hack { + krb5_kdc_req v; + krb5_data server_realm; +} kdc_req_hack; +DEFFIELD(req_body_0, kdc_req_hack, v.kdc_options, 0, krb5_flags); +DEFFIELD(req_body_1, kdc_req_hack, v.client, 1, opt_principal); +DEFFIELD(req_body_2, kdc_req_hack, server_realm, 2, gstring_data); +DEFFIELD(req_body_3, kdc_req_hack, v.server, 3, opt_principal); +DEFFIELD(req_body_4, kdc_req_hack, v.from, 4, opt_kerberos_time); +DEFFIELD(req_body_5, kdc_req_hack, v.till, 5, kerberos_time); +DEFFIELD(req_body_6, kdc_req_hack, v.rtime, 6, opt_kerberos_time); +DEFFIELD(req_body_7, kdc_req_hack, v.nonce, 7, int32); +DEFCNFIELD(req_body_8, kdc_req_hack, v.ktype, v.nktypes, 8, cseqof_int32); +DEFFIELD(req_body_9, kdc_req_hack, v.addresses, 9, + opt_ptr_seqof_host_addresses); +DEFFIELD(req_body_10, kdc_req_hack, v.authorization_data, 10, + opt_encrypted_data); +DEFFIELD(req_body_11, kdc_req_hack, v.second_ticket, 11, opt_ptr_seqof_ticket); +static const struct atype_info *kdc_req_hack_fields[] = { + &k5_atype_req_body_0, &k5_atype_req_body_1, &k5_atype_req_body_2, + &k5_atype_req_body_3, &k5_atype_req_body_4, &k5_atype_req_body_5, + &k5_atype_req_body_6, &k5_atype_req_body_7, &k5_atype_req_body_8, + &k5_atype_req_body_9, &k5_atype_req_body_10, &k5_atype_req_body_11 +}; +DEFSEQTYPE(kdc_req_body_hack, kdc_req_hack, kdc_req_hack_fields); +static krb5_error_code +encode_kdc_req_body(asn1buf *buf, const void *p, taginfo *tag_out) +{ + const krb5_kdc_req *val = p; + kdc_req_hack h; + h.v = *val; + if (val->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY) { + if (val->second_ticket != NULL && val->second_ticket[0] != NULL) + h.server_realm = val->second_ticket[0]->server->realm; + else + return ASN1_MISSING_FIELD; + } else if (val->server != NULL) + h.server_realm = val->server->realm; + else + return ASN1_MISSING_FIELD; + return k5_asn1_encode_atype(buf, &h, &k5_atype_kdc_req_body_hack, tag_out); +} +static void +free_kdc_req_body(void *val) +{ + krb5_kdc_req *req = val; + krb5_free_principal(NULL, req->client); + krb5_free_principal(NULL, req->server); + free(req->ktype); + krb5_free_addresses(NULL, req->addresses); + free(req->authorization_data.ciphertext.data); + krb5_free_tickets(NULL, req->second_ticket); +} +static krb5_error_code +decode_kdc_req_body(const taginfo *t, const uint8_t *asn1, size_t len, + void *val) +{ + krb5_error_code ret; + kdc_req_hack h; + krb5_kdc_req *b = val; + memset(&h, 0, sizeof(h)); + ret = k5_asn1_decode_atype(t, asn1, len, &k5_atype_kdc_req_body_hack, &h); + if (ret) + return ret; + b->kdc_options = h.v.kdc_options; + b->client = h.v.client; + b->server = h.v.server; + b->from = h.v.from; + b->till = h.v.till; + b->rtime = h.v.rtime; + b->nonce = h.v.nonce; + b->ktype = h.v.ktype; + b->nktypes = h.v.nktypes; + b->addresses = h.v.addresses; + b->authorization_data = h.v.authorization_data; + b->second_ticket = h.v.second_ticket; + if (b->client != NULL && b->server != NULL) { + ret = krb5int_copy_data_contents(NULL, &h.server_realm, + &b->client->realm); + if (ret) { + free_kdc_req_body(b); + free(h.server_realm.data); + return ret; + } + b->server->realm = h.server_realm; + } else if (b->client != NULL) + b->client->realm = h.server_realm; + else if (b->server != NULL) + b->server->realm = h.server_realm; + else + free(h.server_realm.data); + return 0; +} +static int +check_kdc_req_body(const taginfo *t) +{ + return (t->asn1class == UNIVERSAL && t->construction == CONSTRUCTED && + t->tagnum == ASN1_SEQUENCE); +} +DEFFNTYPE(kdc_req_body, krb5_kdc_req, encode_kdc_req_body, decode_kdc_req_body, + check_kdc_req_body, free_kdc_req_body); +/* end ugly hack */ + +DEFFIELD(transited_0, krb5_transited, tr_type, 0, octet); +DEFFIELD(transited_1, krb5_transited, tr_contents, 1, ostring_data); +static const struct atype_info *transited_fields[] = { + &k5_atype_transited_0, &k5_atype_transited_1 +}; +DEFSEQTYPE(transited, krb5_transited, transited_fields); + +static int +is_safe_timestamp_set(const void *p) +{ + const krb5_safe *val = p; + return (val->timestamp != 0); +} +DEFFIELD(safe_body_0, krb5_safe, user_data, 0, ostring_data); +DEFFIELD(safe_body_1, krb5_safe, timestamp, 1, opt_kerberos_time); +DEFFIELD(safe_body_2_def, krb5_safe, usec, 2, int32); +DEFOPTIONALTYPE(safe_body_2, is_safe_timestamp_set, NULL, safe_body_2_def); +DEFFIELD(safe_body_3, krb5_safe, seq_number, 3, opt_seqno); +DEFFIELD(safe_body_4, krb5_safe, s_address, 4, address_ptr); +DEFFIELD(safe_body_5, krb5_safe, r_address, 5, opt_address_ptr); +static const struct atype_info *safe_body_fields[] = { + &k5_atype_safe_body_0, &k5_atype_safe_body_1, &k5_atype_safe_body_2, + &k5_atype_safe_body_3, &k5_atype_safe_body_4, &k5_atype_safe_body_5 +}; +DEFSEQTYPE(safe_body, krb5_safe, safe_body_fields); + +DEFFIELD(cred_info_0, krb5_cred_info, session, 0, ptr_encryption_key); +DEFFIELD(cred_info_1, krb5_cred_info, client, 1, opt_realm_of_principal); +DEFFIELD(cred_info_2, krb5_cred_info, client, 2, opt_principal); +DEFFIELD(cred_info_3, krb5_cred_info, flags, 3, opt_krb5_flags); +DEFFIELD(cred_info_4, krb5_cred_info, times.authtime, 4, opt_kerberos_time); +DEFFIELD(cred_info_5, krb5_cred_info, times.starttime, 5, opt_kerberos_time); +DEFFIELD(cred_info_6, krb5_cred_info, times.endtime, 6, opt_kerberos_time); +DEFFIELD(cred_info_7, krb5_cred_info, times.renew_till, 7, opt_kerberos_time); +DEFFIELD(cred_info_8, krb5_cred_info, server, 8, opt_realm_of_principal); +DEFFIELD(cred_info_9, krb5_cred_info, server, 9, opt_principal); +DEFFIELD(cred_info_10, krb5_cred_info, caddrs, 10, + opt_ptr_seqof_host_addresses); +static const struct atype_info *krb_cred_info_fields[] = { + &k5_atype_cred_info_0, &k5_atype_cred_info_1, &k5_atype_cred_info_2, + &k5_atype_cred_info_3, &k5_atype_cred_info_4, &k5_atype_cred_info_5, + &k5_atype_cred_info_6, &k5_atype_cred_info_7, &k5_atype_cred_info_8, + &k5_atype_cred_info_9, &k5_atype_cred_info_10 +}; +DEFSEQTYPE(cred_info, krb5_cred_info, krb_cred_info_fields); +DEFPTRTYPE(cred_info_ptr, cred_info); +DEFNULLTERMSEQOFTYPE(seqof_cred_info, cred_info_ptr); + +DEFPTRTYPE(ptrseqof_cred_info, seqof_cred_info); + +static int +is_salt_present(const void *p) +{ + const krb5_etype_info_entry *val = p; + return (val->length != KRB5_ETYPE_NO_SALT); +} +static void +init_no_salt(void *p) +{ + krb5_etype_info_entry *val = p; + val->length = KRB5_ETYPE_NO_SALT; +} +DEFFIELD(etype_info_0, krb5_etype_info_entry, etype, 0, int32); +DEFCNFIELD(etype_info_1_def, krb5_etype_info_entry, salt, length, 1, + octetstring); +DEFOPTIONALTYPE(etype_info_1, is_salt_present, init_no_salt, etype_info_1_def); +static const struct atype_info *etype_info_entry_fields[] = { + &k5_atype_etype_info_0, &k5_atype_etype_info_1 +}; +DEFSEQTYPE(etype_info_entry, krb5_etype_info_entry, etype_info_entry_fields); + +/* First field is the same as etype-info. */ +DEFCNFIELD(etype_info2_1_def, krb5_etype_info_entry, salt, length, 1, + u_generalstring); +DEFOPTIONALTYPE(etype_info2_1, is_salt_present, init_no_salt, + etype_info2_1_def); +DEFFIELD(etype_info2_2, krb5_etype_info_entry, s2kparams, 2, opt_ostring_data); +static const struct atype_info *etype_info2_entry_fields[] = { + &k5_atype_etype_info_0, &k5_atype_etype_info2_1, &k5_atype_etype_info2_2 +}; +DEFSEQTYPE(etype_info2_entry, krb5_etype_info_entry, etype_info2_entry_fields); + +DEFPTRTYPE(etype_info_entry_ptr, etype_info_entry); +DEFNULLTERMSEQOFTYPE(etype_info, etype_info_entry_ptr); + +DEFPTRTYPE(etype_info2_entry_ptr, etype_info2_entry); +DEFNULLTERMSEQOFTYPE(etype_info2, etype_info2_entry_ptr); + +DEFFIELD(sch_0, krb5_sam_challenge_2, sam_challenge_2_body, 0, der_data); +DEFFIELD(sch_1, krb5_sam_challenge_2, sam_cksum, 1, ptr_seqof_checksum); +static const struct atype_info *sam_challenge_2_fields[] = { + &k5_atype_sch_0, &k5_atype_sch_1 +}; +DEFSEQTYPE(sam_challenge_2, krb5_sam_challenge_2, sam_challenge_2_fields); + +DEFFIELD(schb_0, krb5_sam_challenge_2_body, sam_type, 0, int32); +DEFFIELD(schb_1, krb5_sam_challenge_2_body, sam_flags, 1, krb5_flags); +DEFFIELD(schb_2, krb5_sam_challenge_2_body, sam_type_name, 2, + opt_ostring_data); +DEFFIELD(schb_3, krb5_sam_challenge_2_body, sam_track_id, 3, opt_ostring_data); +DEFFIELD(schb_4, krb5_sam_challenge_2_body, sam_challenge_label, 4, + opt_ostring_data); +DEFFIELD(schb_5, krb5_sam_challenge_2_body, sam_challenge, 5, + opt_ostring_data); +DEFFIELD(schb_6, krb5_sam_challenge_2_body, sam_response_prompt, 6, + opt_ostring_data); +DEFFIELD(schb_7, krb5_sam_challenge_2_body, sam_pk_for_sad, 7, + opt_ostring_data); +DEFFIELD(schb_8, krb5_sam_challenge_2_body, sam_nonce, 8, int32); +DEFFIELD(schb_9, krb5_sam_challenge_2_body, sam_etype, 9, int32); +static const struct atype_info *sam_challenge_2_body_fields[] = { + &k5_atype_schb_0, &k5_atype_schb_1, &k5_atype_schb_2, &k5_atype_schb_3, + &k5_atype_schb_4, &k5_atype_schb_5, &k5_atype_schb_6, &k5_atype_schb_7, + &k5_atype_schb_8, &k5_atype_schb_9 +}; +DEFSEQTYPE(sam_challenge_2_body,krb5_sam_challenge_2_body, + sam_challenge_2_body_fields); + +DEFFIELD(esre_0, krb5_enc_sam_response_enc_2, sam_nonce, 0, int32); +DEFFIELD(esre_1, krb5_enc_sam_response_enc_2, sam_sad, 1, opt_ostring_data); +static const struct atype_info *enc_sam_response_enc_2_fields[] = { + &k5_atype_esre_0, &k5_atype_esre_1 +}; +DEFSEQTYPE(enc_sam_response_enc_2, krb5_enc_sam_response_enc_2, + enc_sam_response_enc_2_fields); + +DEFFIELD(sam_resp_0, krb5_sam_response_2, sam_type, 0, int32); +DEFFIELD(sam_resp_1, krb5_sam_response_2, sam_flags, 1, krb5_flags); +DEFFIELD(sam_resp_2, krb5_sam_response_2, sam_track_id, 2, opt_ostring_data); +DEFFIELD(sam_resp_3, krb5_sam_response_2, sam_enc_nonce_or_sad, 3, + encrypted_data); +DEFFIELD(sam_resp_4, krb5_sam_response_2, sam_nonce, 4, int32); +static const struct atype_info *sam_response_2_fields[] = { + &k5_atype_sam_resp_0, &k5_atype_sam_resp_1, &k5_atype_sam_resp_2, + &k5_atype_sam_resp_3, &k5_atype_sam_resp_4 +}; +DEFSEQTYPE(sam_response_2, krb5_sam_response_2, sam_response_2_fields); + +DEFCTAGGEDTYPE(authenticator_0, 0, krb5_version); +DEFFIELD(authenticator_1, krb5_authenticator, client, 1, realm_of_principal); +DEFFIELD(authenticator_2, krb5_authenticator, client, 2, principal); +DEFFIELD(authenticator_3, krb5_authenticator, checksum, 3, opt_checksum_ptr); +DEFFIELD(authenticator_4, krb5_authenticator, cusec, 4, int32); +DEFFIELD(authenticator_5, krb5_authenticator, ctime, 5, kerberos_time); +DEFFIELD(authenticator_6, krb5_authenticator, subkey, 6, + opt_ptr_encryption_key); +DEFFIELD(authenticator_7, krb5_authenticator, seq_number, 7, opt_seqno); +DEFFIELD(authenticator_8, krb5_authenticator, authorization_data, 8, + opt_auth_data_ptr); +static const struct atype_info *authenticator_fields[] = { + &k5_atype_authenticator_0, &k5_atype_authenticator_1, + &k5_atype_authenticator_2, &k5_atype_authenticator_3, + &k5_atype_authenticator_4, &k5_atype_authenticator_5, + &k5_atype_authenticator_6, &k5_atype_authenticator_7, + &k5_atype_authenticator_8 +}; +DEFSEQTYPE(untagged_authenticator, krb5_authenticator, authenticator_fields); +DEFAPPTAGGEDTYPE(authenticator, 2, untagged_authenticator); + +DEFFIELD(enc_tkt_0, krb5_enc_tkt_part, flags, 0, krb5_flags); +DEFFIELD(enc_tkt_1, krb5_enc_tkt_part, session, 1, ptr_encryption_key); +DEFFIELD(enc_tkt_2, krb5_enc_tkt_part, client, 2, realm_of_principal); +DEFFIELD(enc_tkt_3, krb5_enc_tkt_part, client, 3, principal); +DEFFIELD(enc_tkt_4, krb5_enc_tkt_part, transited, 4, transited); +DEFFIELD(enc_tkt_5, krb5_enc_tkt_part, times.authtime, 5, kerberos_time); +DEFFIELD(enc_tkt_6, krb5_enc_tkt_part, times.starttime, 6, opt_kerberos_time); +DEFFIELD(enc_tkt_7, krb5_enc_tkt_part, times.endtime, 7, kerberos_time); +DEFFIELD(enc_tkt_8, krb5_enc_tkt_part, times.renew_till, 8, opt_kerberos_time); +DEFFIELD(enc_tkt_9, krb5_enc_tkt_part, caddrs, 9, + opt_ptr_seqof_host_addresses); +DEFFIELD(enc_tkt_10, krb5_enc_tkt_part, authorization_data, 10, + opt_auth_data_ptr); +static const struct atype_info *enc_tkt_part_fields[] = { + &k5_atype_enc_tkt_0, &k5_atype_enc_tkt_1, &k5_atype_enc_tkt_2, + &k5_atype_enc_tkt_3, &k5_atype_enc_tkt_4, &k5_atype_enc_tkt_5, + &k5_atype_enc_tkt_6, &k5_atype_enc_tkt_7, &k5_atype_enc_tkt_8, + &k5_atype_enc_tkt_9, &k5_atype_enc_tkt_10 +}; +DEFSEQTYPE(untagged_enc_tkt_part, krb5_enc_tkt_part, enc_tkt_part_fields); +DEFAPPTAGGEDTYPE(enc_tkt_part, 3, untagged_enc_tkt_part); + +DEFAPPTAGGEDTYPE(enc_as_rep_part, 25, enc_kdc_rep_part); +DEFAPPTAGGEDTYPE(enc_tgs_rep_part, 26, enc_kdc_rep_part); + +DEFCTAGGEDTYPE(kdc_rep_0, 0, krb5_version); +DEFFIELD(kdc_rep_1, krb5_kdc_rep, msg_type, 1, uint); +DEFFIELD(kdc_rep_2, krb5_kdc_rep, padata, 2, opt_ptr_seqof_pa_data); +DEFFIELD(kdc_rep_3, krb5_kdc_rep, client, 3, realm_of_principal); +DEFFIELD(kdc_rep_4, krb5_kdc_rep, client, 4, principal); +DEFFIELD(kdc_rep_5, krb5_kdc_rep, ticket, 5, ticket_ptr); +DEFFIELD(kdc_rep_6, krb5_kdc_rep, enc_part, 6, encrypted_data); +static const struct atype_info *kdc_rep_fields[] = { + &k5_atype_kdc_rep_0, &k5_atype_kdc_rep_1, &k5_atype_kdc_rep_2, + &k5_atype_kdc_rep_3, &k5_atype_kdc_rep_4, &k5_atype_kdc_rep_5, + &k5_atype_kdc_rep_6 +}; +DEFSEQTYPE(kdc_rep, krb5_kdc_rep, kdc_rep_fields); +DEFAPPTAGGEDTYPE(as_rep, 11, kdc_rep); +DEFAPPTAGGEDTYPE(tgs_rep, 13, kdc_rep); + +DEFINT_IMMEDIATE(ap_req_msg_type, ASN1_KRB_AP_REQ, 0); +DEFCTAGGEDTYPE(ap_req_0, 0, krb5_version); +DEFCTAGGEDTYPE(ap_req_1, 1, ap_req_msg_type); +DEFFIELD(ap_req_2, krb5_ap_req, ap_options, 2, krb5_flags); +DEFFIELD(ap_req_3, krb5_ap_req, ticket, 3, ticket_ptr); +DEFFIELD(ap_req_4, krb5_ap_req, authenticator, 4, encrypted_data); +static const struct atype_info *ap_req_fields[] = { + &k5_atype_ap_req_0, &k5_atype_ap_req_1, &k5_atype_ap_req_2, + &k5_atype_ap_req_3, &k5_atype_ap_req_4 +}; +DEFSEQTYPE(untagged_ap_req, krb5_ap_req, ap_req_fields); +DEFAPPTAGGEDTYPE(ap_req, 14, untagged_ap_req); + +DEFINT_IMMEDIATE(ap_rep_msg_type, ASN1_KRB_AP_REP, 0); +DEFCTAGGEDTYPE(ap_rep_0, 0, krb5_version); +DEFCTAGGEDTYPE(ap_rep_1, 1, ap_rep_msg_type); +DEFFIELD(ap_rep_2, krb5_ap_rep, enc_part, 2, encrypted_data); +static const struct atype_info *ap_rep_fields[] = { + &k5_atype_ap_rep_0, &k5_atype_ap_rep_1, &k5_atype_ap_rep_2 +}; +DEFSEQTYPE(untagged_ap_rep, krb5_ap_rep, ap_rep_fields); +DEFAPPTAGGEDTYPE(ap_rep, 15, untagged_ap_rep); + +DEFFIELD(ap_rep_enc_part_0, krb5_ap_rep_enc_part, ctime, 0, kerberos_time); +DEFFIELD(ap_rep_enc_part_1, krb5_ap_rep_enc_part, cusec, 1, int32); +DEFFIELD(ap_rep_enc_part_2, krb5_ap_rep_enc_part, subkey, 2, + opt_ptr_encryption_key); +DEFFIELD(ap_rep_enc_part_3, krb5_ap_rep_enc_part, seq_number, 3, opt_seqno); +static const struct atype_info *ap_rep_enc_part_fields[] = { + &k5_atype_ap_rep_enc_part_0, &k5_atype_ap_rep_enc_part_1, + &k5_atype_ap_rep_enc_part_2, &k5_atype_ap_rep_enc_part_3 +}; +DEFSEQTYPE(untagged_ap_rep_enc_part, krb5_ap_rep_enc_part, + ap_rep_enc_part_fields); +DEFAPPTAGGEDTYPE(ap_rep_enc_part, 27, untagged_ap_rep_enc_part); + +/* First context tag is 1. Fourth field is the encoding of the krb5_kdc_req + * structure as a KDC-REQ-BODY. */ +DEFCTAGGEDTYPE(kdc_req_1, 1, krb5_version); +DEFFIELD(kdc_req_2, krb5_kdc_req, msg_type, 2, uint); +DEFFIELD(kdc_req_3, krb5_kdc_req, padata, 3, opt_ptr_seqof_pa_data); +DEFCTAGGEDTYPE(kdc_req_4, 4, kdc_req_body); +static const struct atype_info *kdc_req_fields[] = { + &k5_atype_kdc_req_1, &k5_atype_kdc_req_2, &k5_atype_kdc_req_3, + &k5_atype_kdc_req_4 +}; +DEFSEQTYPE(kdc_req, krb5_kdc_req, kdc_req_fields); +DEFAPPTAGGEDTYPE(as_req, 10, kdc_req); +DEFAPPTAGGEDTYPE(tgs_req, 12, kdc_req); + +/* This is only needed because libkrb5 doesn't set msg_type when encoding + * krb5_kdc_reqs. If we fix that, we can use the above types for encoding. */ +DEFINT_IMMEDIATE(as_req_msg_type, KRB5_AS_REQ, 0); +DEFCTAGGEDTYPE(as_req_2, 2, as_req_msg_type); +DEFINT_IMMEDIATE(tgs_req_msg_type, KRB5_TGS_REQ, 0); +DEFCTAGGEDTYPE(tgs_req_2, 2, tgs_req_msg_type); +static const struct atype_info *as_req_fields[] = { + &k5_atype_kdc_req_1, &k5_atype_as_req_2, &k5_atype_kdc_req_3, + &k5_atype_kdc_req_4 +}; +static const struct atype_info *tgs_req_fields[] = { + &k5_atype_kdc_req_1, &k5_atype_tgs_req_2, &k5_atype_kdc_req_3, + &k5_atype_kdc_req_4 +}; +DEFSEQTYPE(untagged_as_req, krb5_kdc_req, as_req_fields); +DEFAPPTAGGEDTYPE(as_req_encode, 10, untagged_as_req); +DEFSEQTYPE(untagged_tgs_req, krb5_kdc_req, tgs_req_fields); +DEFAPPTAGGEDTYPE(tgs_req_encode, 12, untagged_tgs_req); + +DEFINT_IMMEDIATE(safe_msg_type, ASN1_KRB_SAFE, 0); +DEFCTAGGEDTYPE(safe_0, 0, krb5_version); +DEFCTAGGEDTYPE(safe_1, 1, safe_msg_type); +DEFCTAGGEDTYPE(safe_2, 2, safe_body); +DEFFIELD(safe_3, krb5_safe, checksum, 3, checksum_ptr); +static const struct atype_info *safe_fields[] = { + &k5_atype_safe_0, &k5_atype_safe_1, &k5_atype_safe_2, &k5_atype_safe_3 +}; +DEFSEQTYPE(untagged_safe, krb5_safe, safe_fields); +DEFAPPTAGGEDTYPE(safe, 20, untagged_safe); + +/* Hack to encode a KRB-SAFE with a pre-specified body encoding. The integer- + * immediate fields are borrowed from krb5_safe_fields above. */ +DEFPTRTYPE(saved_safe_body_ptr, der_data); +DEFOFFSETTYPE(safe_checksum_only, krb5_safe, checksum, checksum_ptr); +DEFPTRTYPE(safe_checksum_only_ptr, safe_checksum_only); +DEFFIELD(safe_with_body_2, struct krb5_safe_with_body, body, 2, + saved_safe_body_ptr); +DEFFIELD(safe_with_body_3, struct krb5_safe_with_body, safe, 3, + safe_checksum_only_ptr); +static const struct atype_info *safe_with_body_fields[] = { + &k5_atype_safe_0, &k5_atype_safe_1, &k5_atype_safe_with_body_2, + &k5_atype_safe_with_body_3 +}; +DEFSEQTYPE(untagged_safe_with_body, struct krb5_safe_with_body, + safe_with_body_fields); +DEFAPPTAGGEDTYPE(safe_with_body, 20, untagged_safe_with_body); + +/* Third tag is [3] instead of [2]. */ +DEFINT_IMMEDIATE(priv_msg_type, ASN1_KRB_PRIV, 0); +DEFCTAGGEDTYPE(priv_0, 0, krb5_version); +DEFCTAGGEDTYPE(priv_1, 1, priv_msg_type); +DEFFIELD(priv_3, krb5_priv, enc_part, 3, encrypted_data); +static const struct atype_info *priv_fields[] = { + &k5_atype_priv_0, &k5_atype_priv_1, &k5_atype_priv_3 +}; +DEFSEQTYPE(untagged_priv, krb5_priv, priv_fields); +DEFAPPTAGGEDTYPE(priv, 21, untagged_priv); + +static int +is_priv_timestamp_set(const void *p) +{ + const krb5_priv_enc_part *val = p; + return (val->timestamp != 0); +} +DEFFIELD(priv_enc_part_0, krb5_priv_enc_part, user_data, 0, ostring_data); +DEFFIELD(priv_enc_part_1, krb5_priv_enc_part, timestamp, 1, opt_kerberos_time); +DEFFIELD(priv_enc_part_2_def, krb5_priv_enc_part, usec, 2, int32); +DEFOPTIONALTYPE(priv_enc_part_2, is_priv_timestamp_set, NULL, + priv_enc_part_2_def); +DEFFIELD(priv_enc_part_3, krb5_priv_enc_part, seq_number, 3, opt_seqno); +DEFFIELD(priv_enc_part_4, krb5_priv_enc_part, s_address, 4, address_ptr); +DEFFIELD(priv_enc_part_5, krb5_priv_enc_part, r_address, 5, opt_address_ptr); +static const struct atype_info *priv_enc_part_fields[] = { + &k5_atype_priv_enc_part_0, &k5_atype_priv_enc_part_1, + &k5_atype_priv_enc_part_2, &k5_atype_priv_enc_part_3, + &k5_atype_priv_enc_part_4, &k5_atype_priv_enc_part_5 +}; +DEFSEQTYPE(untagged_priv_enc_part, krb5_priv_enc_part, priv_enc_part_fields); +DEFAPPTAGGEDTYPE(priv_enc_part, 28, untagged_priv_enc_part); + +DEFINT_IMMEDIATE(cred_msg_type, ASN1_KRB_CRED, 0); +DEFCTAGGEDTYPE(cred_0, 0, krb5_version); +DEFCTAGGEDTYPE(cred_1, 1, cred_msg_type); +DEFFIELD(cred_2, krb5_cred, tickets, 2, ptr_seqof_ticket); +DEFFIELD(cred_3, krb5_cred, enc_part, 3, encrypted_data); +static const struct atype_info *cred_fields[] = { + &k5_atype_cred_0, &k5_atype_cred_1, &k5_atype_cred_2, &k5_atype_cred_3 +}; +DEFSEQTYPE(untagged_cred, krb5_cred, cred_fields); +DEFAPPTAGGEDTYPE(krb5_cred, 22, untagged_cred); + +static int +is_cred_timestamp_set(const void *p) +{ + const krb5_cred_enc_part *val = p; + return (val->timestamp != 0); +} +DEFFIELD(enc_cred_part_0, krb5_cred_enc_part, ticket_info, 0, + ptrseqof_cred_info); +DEFFIELD(enc_cred_part_1, krb5_cred_enc_part, nonce, 1, opt_int32); +DEFFIELD(enc_cred_part_2, krb5_cred_enc_part, timestamp, 2, opt_kerberos_time); +DEFFIELD(enc_cred_part_3_def, krb5_cred_enc_part, usec, 3, int32); +DEFOPTIONALTYPE(enc_cred_part_3, is_cred_timestamp_set, NULL, + enc_cred_part_3_def); +DEFFIELD(enc_cred_part_4, krb5_cred_enc_part, s_address, 4, opt_address_ptr); +DEFFIELD(enc_cred_part_5, krb5_cred_enc_part, r_address, 5, opt_address_ptr); +static const struct atype_info *enc_cred_part_fields[] = { + &k5_atype_enc_cred_part_0, &k5_atype_enc_cred_part_1, + &k5_atype_enc_cred_part_2, &k5_atype_enc_cred_part_3, + &k5_atype_enc_cred_part_4, &k5_atype_enc_cred_part_5 +}; +DEFSEQTYPE(untagged_enc_cred_part, krb5_cred_enc_part, enc_cred_part_fields); +DEFAPPTAGGEDTYPE(enc_cred_part, 29, untagged_enc_cred_part); + +DEFINT_IMMEDIATE(error_msg_type, ASN1_KRB_ERROR, 0); +DEFCTAGGEDTYPE(error_0, 0, krb5_version); +DEFCTAGGEDTYPE(error_1, 1, error_msg_type); +DEFFIELD(error_2, krb5_error, ctime, 2, opt_kerberos_time); +DEFFIELD(error_3, krb5_error, cusec, 3, opt_int32); +DEFFIELD(error_4, krb5_error, stime, 4, kerberos_time); +DEFFIELD(error_5, krb5_error, susec, 5, int32); +DEFFIELD(error_6, krb5_error, error, 6, uint32); +DEFFIELD(error_7, krb5_error, client, 7, opt_realm_of_principal); +DEFFIELD(error_8, krb5_error, client, 8, opt_principal); +DEFFIELD(error_9, krb5_error, server, 9, realm_of_principal); +DEFFIELD(error_10, krb5_error, server, 10, principal); +DEFFIELD(error_11, krb5_error, text, 11, opt_gstring_data); +DEFFIELD(error_12, krb5_error, e_data, 12, opt_ostring_data); +static const struct atype_info *error_fields[] = { + &k5_atype_error_0, &k5_atype_error_1, &k5_atype_error_2, &k5_atype_error_3, + &k5_atype_error_4, &k5_atype_error_5, &k5_atype_error_6, &k5_atype_error_7, + &k5_atype_error_8, &k5_atype_error_9, &k5_atype_error_10, + &k5_atype_error_11, &k5_atype_error_12 +}; +DEFSEQTYPE(untagged_krb5_error, krb5_error, error_fields); +DEFAPPTAGGEDTYPE(krb5_error, 30, untagged_krb5_error); + +DEFFIELD(pa_enc_ts_0, krb5_pa_enc_ts, patimestamp, 0, kerberos_time); +DEFFIELD(pa_enc_ts_1, krb5_pa_enc_ts, pausec, 1, opt_int32); +static const struct atype_info *pa_enc_ts_fields[] = { + &k5_atype_pa_enc_ts_0, &k5_atype_pa_enc_ts_1 +}; +DEFSEQTYPE(pa_enc_ts, krb5_pa_enc_ts, pa_enc_ts_fields); + +DEFFIELD(setpw_0, struct krb5_setpw_req, password, 0, ostring_data); +DEFFIELD(setpw_1, struct krb5_setpw_req, target, 1, principal); +DEFFIELD(setpw_2, struct krb5_setpw_req, target, 2, realm_of_principal); +static const struct atype_info *setpw_req_fields[] = { + &k5_atype_setpw_0, &k5_atype_setpw_1, &k5_atype_setpw_2 +}; +DEFSEQTYPE(setpw_req, struct krb5_setpw_req, setpw_req_fields); + +/* [MS-SFU] Section 2.2.1. */ +DEFFIELD(pa_for_user_0, krb5_pa_for_user, user, 0, principal); +DEFFIELD(pa_for_user_1, krb5_pa_for_user, user, 1, realm_of_principal); +DEFFIELD(pa_for_user_2, krb5_pa_for_user, cksum, 2, checksum); +DEFFIELD(pa_for_user_3, krb5_pa_for_user, auth_package, 3, gstring_data); +static const struct atype_info *pa_for_user_fields[] = { + &k5_atype_pa_for_user_0, &k5_atype_pa_for_user_1, &k5_atype_pa_for_user_2, + &k5_atype_pa_for_user_3, +}; +DEFSEQTYPE(pa_for_user, krb5_pa_for_user, pa_for_user_fields); + +/* [MS-SFU] Section 2.2.2. */ +/* The user principal name may be absent, but the realm is required. */ +static int +is_s4u_principal_present(const void *p) +{ + krb5_const_principal val = *(krb5_const_principal *)p; + return (val->length != 0); +} +DEFOPTIONALTYPE(opt_s4u_principal, is_s4u_principal_present, NULL, principal); +DEFFIELD(s4u_userid_0, krb5_s4u_userid, nonce, 0, int32); +DEFFIELD(s4u_userid_1, krb5_s4u_userid, user, 1, opt_s4u_principal); +DEFFIELD(s4u_userid_2, krb5_s4u_userid, user, 2, realm_of_principal); +DEFFIELD(s4u_userid_3, krb5_s4u_userid, subject_cert, 3, opt_ostring_data); +DEFFIELD(s4u_userid_4, krb5_s4u_userid, options, 4, opt_krb5_flags); +static const struct atype_info *s4u_userid_fields[] = { + &k5_atype_s4u_userid_0, &k5_atype_s4u_userid_1, &k5_atype_s4u_userid_2, + &k5_atype_s4u_userid_3, &k5_atype_s4u_userid_4 +}; +DEFSEQTYPE(s4u_userid, krb5_s4u_userid, s4u_userid_fields); + +DEFFIELD(pa_s4u_x509_user_0, krb5_pa_s4u_x509_user, user_id, 0, s4u_userid); +DEFFIELD(pa_s4u_x509_user_1, krb5_pa_s4u_x509_user, cksum, 1, checksum); +static const struct atype_info *pa_s4u_x509_user_fields[] = { + &k5_atype_pa_s4u_x509_user_0, &k5_atype_pa_s4u_x509_user_1 +}; +DEFSEQTYPE(pa_s4u_x509_user, krb5_pa_s4u_x509_user, pa_s4u_x509_user_fields); + +DEFFIELD(pa_pac_req_0, krb5_pa_pac_req, include_pac, 0, boolean); +static const struct atype_info *pa_pac_req_fields[] = { + &k5_atype_pa_pac_req_0 +}; +DEFSEQTYPE(pa_pac_req, krb5_pa_pac_req, pa_pac_req_fields); + +/* RFC 4537 */ +DEFCOUNTEDTYPE(etype_list, krb5_etype_list, etypes, length, cseqof_int32); + +/* draft-ietf-krb-wg-preauth-framework-09 */ +DEFFIELD(fast_armor_0, krb5_fast_armor, armor_type, 0, int32); +DEFFIELD(fast_armor_1, krb5_fast_armor, armor_value, 1, ostring_data); +static const struct atype_info *fast_armor_fields[] = { + &k5_atype_fast_armor_0, &k5_atype_fast_armor_1 +}; +DEFSEQTYPE(fast_armor, krb5_fast_armor, fast_armor_fields); +DEFPTRTYPE(ptr_fast_armor, fast_armor); +DEFOPTIONALZEROTYPE(opt_ptr_fast_armor, ptr_fast_armor); + +DEFFIELD(fast_armored_req_0, krb5_fast_armored_req, armor, 0, + opt_ptr_fast_armor); +DEFFIELD(fast_armored_req_1, krb5_fast_armored_req, req_checksum, 1, checksum); +DEFFIELD(fast_armored_req_2, krb5_fast_armored_req, enc_part, 2, + encrypted_data); +static const struct atype_info *fast_armored_req_fields[] = { + &k5_atype_fast_armored_req_0, &k5_atype_fast_armored_req_1, + &k5_atype_fast_armored_req_2 +}; +DEFSEQTYPE(fast_armored_req, krb5_fast_armored_req, fast_armored_req_fields); + +/* This is a CHOICE type with only one choice (so far) and we're not using a + * distinguisher/union for it. */ +DEFTAGGEDTYPE(pa_fx_fast_request, CONTEXT_SPECIFIC, CONSTRUCTED, 0, 0, + fast_armored_req); + +DEFOFFSETTYPE(fast_req_padata, krb5_kdc_req, padata, ptr_seqof_pa_data); +DEFPTRTYPE(ptr_fast_req_padata, fast_req_padata); +DEFPTRTYPE(ptr_kdc_req_body, kdc_req_body); +DEFFIELD(fast_req_0, krb5_fast_req, fast_options, 0, krb5_flags); +DEFFIELD(fast_req_1, krb5_fast_req, req_body, 1, ptr_fast_req_padata); +DEFFIELD(fast_req_2, krb5_fast_req, req_body, 2, ptr_kdc_req_body); +static const struct atype_info *fast_req_fields[] = { + &k5_atype_fast_req_0, &k5_atype_fast_req_1, &k5_atype_fast_req_2 +}; +DEFSEQTYPE(fast_req, krb5_fast_req, fast_req_fields); + +DEFFIELD(fast_finished_0, krb5_fast_finished, timestamp, 0, kerberos_time); +DEFFIELD(fast_finished_1, krb5_fast_finished, usec, 1, int32); +DEFFIELD(fast_finished_2, krb5_fast_finished, client, 2, realm_of_principal); +DEFFIELD(fast_finished_3, krb5_fast_finished, client, 3, principal); +DEFFIELD(fast_finished_4, krb5_fast_finished, ticket_checksum, 4, checksum); +static const struct atype_info *fast_finished_fields[] = { + &k5_atype_fast_finished_0, &k5_atype_fast_finished_1, + &k5_atype_fast_finished_2, &k5_atype_fast_finished_3, + &k5_atype_fast_finished_4 +}; +DEFSEQTYPE(fast_finished, krb5_fast_finished, fast_finished_fields); +DEFPTRTYPE(ptr_fast_finished, fast_finished); +DEFOPTIONALZEROTYPE(opt_ptr_fast_finished, ptr_fast_finished); + +DEFFIELD(fast_response_0, krb5_fast_response, padata, 0, ptr_seqof_pa_data); +DEFFIELD(fast_response_1, krb5_fast_response, strengthen_key, 1, + opt_ptr_encryption_key); +DEFFIELD(fast_response_2, krb5_fast_response, finished, 2, + opt_ptr_fast_finished); +DEFFIELD(fast_response_3, krb5_fast_response, nonce, 3, int32); +static const struct atype_info *fast_response_fields[] = { + &k5_atype_fast_response_0, &k5_atype_fast_response_1, + &k5_atype_fast_response_2, &k5_atype_fast_response_3 +}; +DEFSEQTYPE(fast_response, krb5_fast_response, fast_response_fields); + +DEFCTAGGEDTYPE(fast_rep_0, 0, encrypted_data); +static const struct atype_info *fast_rep_fields[] = { + &k5_atype_fast_rep_0 +}; +DEFSEQTYPE(fast_rep, krb5_enc_data, fast_rep_fields); + +/* This is a CHOICE type with only one choice (so far) and we're not using a + * distinguisher/union for it. */ +DEFTAGGEDTYPE(pa_fx_fast_reply, CONTEXT_SPECIFIC, CONSTRUCTED, 0, 0, + fast_rep); + +DEFFIELD(ad_kdcissued_0, krb5_ad_kdcissued, ad_checksum, 0, checksum); +DEFFIELD(ad_kdcissued_1, krb5_ad_kdcissued, i_principal, 1, + opt_realm_of_principal); +DEFFIELD(ad_kdcissued_2, krb5_ad_kdcissued, i_principal, 2, opt_principal); +DEFFIELD(ad_kdcissued_3, krb5_ad_kdcissued, elements, 3, auth_data_ptr); +static const struct atype_info *ad_kdcissued_fields[] = { + &k5_atype_ad_kdcissued_0, &k5_atype_ad_kdcissued_1, + &k5_atype_ad_kdcissued_2, &k5_atype_ad_kdcissued_3 +}; +DEFSEQTYPE(ad_kdc_issued, krb5_ad_kdcissued, ad_kdcissued_fields); + +DEFCTAGGEDTYPE(princ_plus_realm_0, 0, principal_data); +DEFCTAGGEDTYPE(princ_plus_realm_1, 1, realm_of_principal_data); +static const struct atype_info *princ_plus_realm_fields[] = { + &k5_atype_princ_plus_realm_0, &k5_atype_princ_plus_realm_1 +}; +DEFSEQTYPE(princ_plus_realm_data, krb5_principal_data, + princ_plus_realm_fields); +DEFPTRTYPE(princ_plus_realm, princ_plus_realm_data); +DEFNULLTERMSEQOFTYPE(seqof_princ_plus_realm, princ_plus_realm); +DEFPTRTYPE(ptr_seqof_princ_plus_realm, seqof_princ_plus_realm); +DEFOPTIONALEMPTYTYPE(opt_ptr_seqof_princ_plus_realm, + ptr_seqof_princ_plus_realm); + +/* First context tag is 1, not 0. */ +DEFFIELD(iakerb_header_1, krb5_iakerb_header, target_realm, 1, ostring_data); +DEFFIELD(iakerb_header_2, krb5_iakerb_header, cookie, 2, opt_ostring_data_ptr); +static const struct atype_info *iakerb_header_fields[] = { + &k5_atype_iakerb_header_1, &k5_atype_iakerb_header_2 +}; +DEFSEQTYPE(iakerb_header, krb5_iakerb_header, iakerb_header_fields); + +/* First context tag is 1, not 0. */ +DEFFIELD(iakerb_finished_0, krb5_iakerb_finished, checksum, 1, checksum); +static const struct atype_info *iakerb_finished_fields[] = { + &k5_atype_iakerb_finished_0 +}; +DEFSEQTYPE(iakerb_finished, krb5_iakerb_finished, iakerb_finished_fields); + +/* Exported complete encoders -- these produce a krb5_data with + the encoding in the correct byte order. */ + +MAKE_ENCODER(encode_krb5_authenticator, authenticator); +MAKE_DECODER(decode_krb5_authenticator, authenticator); +MAKE_ENCODER(encode_krb5_ticket, ticket); +MAKE_DECODER(decode_krb5_ticket, ticket); +MAKE_ENCODER(encode_krb5_encryption_key, encryption_key); +MAKE_DECODER(decode_krb5_encryption_key, encryption_key); +MAKE_ENCODER(encode_krb5_enc_tkt_part, enc_tkt_part); +MAKE_DECODER(decode_krb5_enc_tkt_part, enc_tkt_part); + +krb5_error_code KRB5_CALLCONV +krb5_decode_ticket(const krb5_data *code, krb5_ticket **repptr) +{ + return decode_krb5_ticket(code, repptr); +} + +/* + * For backwards compatibility, we encode both EncASRepPart and EncTGSRepPart + * with application tag 26. On decode, we accept either app tag and set the + * msg_type field of the resulting structure. This could be simplified and + * pushed up into libkrb5. + */ +MAKE_ENCODER(encode_krb5_enc_kdc_rep_part, enc_tgs_rep_part); +krb5_error_code +decode_krb5_enc_kdc_rep_part(const krb5_data *code, + krb5_enc_kdc_rep_part **rep_out) +{ + krb5_error_code ret; + krb5_enc_kdc_rep_part *rep; + void *rep_ptr; + krb5_msgtype msg_type = KRB5_TGS_REP; + + *rep_out = NULL; + ret = k5_asn1_full_decode(code, &k5_atype_enc_tgs_rep_part, &rep_ptr); + if (ret == ASN1_BAD_ID) { + msg_type = KRB5_AS_REP; + ret = k5_asn1_full_decode(code, &k5_atype_enc_as_rep_part, &rep_ptr); + } + if (ret) + return ret; + rep = rep_ptr; + rep->msg_type = msg_type; + *rep_out = rep; + return 0; +} + +MAKE_ENCODER(encode_krb5_as_rep, as_rep); +MAKE_DECODER(decode_krb5_as_rep, as_rep); +MAKE_ENCODER(encode_krb5_tgs_rep, tgs_rep); +MAKE_DECODER(decode_krb5_tgs_rep, tgs_rep); +MAKE_ENCODER(encode_krb5_ap_req, ap_req); +MAKE_DECODER(decode_krb5_ap_req, ap_req); +MAKE_ENCODER(encode_krb5_ap_rep, ap_rep); +MAKE_DECODER(decode_krb5_ap_rep, ap_rep); +MAKE_ENCODER(encode_krb5_ap_rep_enc_part, ap_rep_enc_part); +MAKE_DECODER(decode_krb5_ap_rep_enc_part, ap_rep_enc_part); +MAKE_ENCODER(encode_krb5_as_req, as_req_encode); +MAKE_DECODER(decode_krb5_as_req, as_req); +MAKE_ENCODER(encode_krb5_tgs_req, tgs_req_encode); +MAKE_DECODER(decode_krb5_tgs_req, tgs_req); +MAKE_ENCODER(encode_krb5_kdc_req_body, kdc_req_body); +MAKE_DECODER(decode_krb5_kdc_req_body, kdc_req_body); +MAKE_ENCODER(encode_krb5_safe, safe); +MAKE_DECODER(decode_krb5_safe, safe); + +/* encode_krb5_safe_with_body takes a saved KRB-SAFE-BODY encoding to avoid + * mismatches from re-encoding if the sender isn't quite DER-compliant. */ +MAKE_ENCODER(encode_krb5_safe_with_body, safe_with_body); + +/* + * decode_krb5_safe_with_body fully decodes a KRB-SAFE, but also returns + * the KRB-SAFE-BODY encoding. This interface was designed for an earlier + * generation of decoder and should probably be re-thought. + */ +krb5_error_code +decode_krb5_safe_with_body(const krb5_data *code, krb5_safe **rep_out, + krb5_data **body_out) +{ + krb5_error_code ret; + void *swb_ptr, *safe_ptr; + struct krb5_safe_with_body *swb; + krb5_safe *safe; + + ret = k5_asn1_full_decode(code, &k5_atype_safe_with_body, &swb_ptr); + if (ret) + return ret; + swb = swb_ptr; + ret = k5_asn1_full_decode(swb->body, &k5_atype_safe_body, &safe_ptr); + if (ret) { + krb5_free_safe(NULL, swb->safe); + krb5_free_data(NULL, swb->body); + free(swb); + return ret; + } + safe = safe_ptr; + safe->checksum = swb->safe->checksum; + free(swb->safe); + *rep_out = safe; + *body_out = swb->body; + free(swb); + return 0; +} + +MAKE_ENCODER(encode_krb5_priv, priv); +MAKE_DECODER(decode_krb5_priv, priv); +MAKE_ENCODER(encode_krb5_enc_priv_part, priv_enc_part); +MAKE_DECODER(decode_krb5_enc_priv_part, priv_enc_part); +MAKE_ENCODER(encode_krb5_checksum, checksum); +MAKE_DECODER(decode_krb5_checksum, checksum); + +MAKE_ENCODER(encode_krb5_cred, krb5_cred); +MAKE_DECODER(decode_krb5_cred, krb5_cred); +MAKE_ENCODER(encode_krb5_enc_cred_part, enc_cred_part); +MAKE_DECODER(decode_krb5_enc_cred_part, enc_cred_part); +MAKE_ENCODER(encode_krb5_error, krb5_error); +MAKE_DECODER(decode_krb5_error, krb5_error); +MAKE_ENCODER(encode_krb5_authdata, auth_data); +MAKE_DECODER(decode_krb5_authdata, auth_data); +MAKE_ENCODER(encode_krb5_etype_info, etype_info); +MAKE_DECODER(decode_krb5_etype_info, etype_info); +MAKE_ENCODER(encode_krb5_etype_info2, etype_info2); +MAKE_DECODER(decode_krb5_etype_info2, etype_info2); +MAKE_ENCODER(encode_krb5_enc_data, encrypted_data); +MAKE_DECODER(decode_krb5_enc_data, encrypted_data); +MAKE_ENCODER(encode_krb5_pa_enc_ts, pa_enc_ts); +MAKE_DECODER(decode_krb5_pa_enc_ts, pa_enc_ts); +MAKE_ENCODER(encode_krb5_padata_sequence, seqof_pa_data); +MAKE_DECODER(decode_krb5_padata_sequence, seqof_pa_data); +/* sam preauth additions */ +MAKE_ENCODER(encode_krb5_sam_challenge_2, sam_challenge_2); +MAKE_DECODER(decode_krb5_sam_challenge_2, sam_challenge_2); +MAKE_ENCODER(encode_krb5_sam_challenge_2_body, sam_challenge_2_body); +MAKE_DECODER(decode_krb5_sam_challenge_2_body, sam_challenge_2_body); +MAKE_ENCODER(encode_krb5_enc_sam_response_enc_2, enc_sam_response_enc_2); +MAKE_DECODER(decode_krb5_enc_sam_response_enc_2, enc_sam_response_enc_2); +MAKE_ENCODER(encode_krb5_sam_response_2, sam_response_2); +MAKE_DECODER(decode_krb5_sam_response_2, sam_response_2); + +/* setpw_req has an odd decoder interface which should probably be + * normalized. */ +MAKE_ENCODER(encode_krb5_setpw_req, setpw_req); +krb5_error_code +decode_krb5_setpw_req(const krb5_data *code, krb5_data **password_out, + krb5_principal *target_out) +{ + krb5_error_code ret; + void *req_ptr; + struct krb5_setpw_req *req; + krb5_data *data; + + *password_out = NULL; + *target_out = NULL; + data = malloc(sizeof(*data)); + if (data == NULL) + return ENOMEM; + ret = k5_asn1_full_decode(code, &k5_atype_setpw_req, &req_ptr); + if (ret) { + free(data); + return ret; + } + req = req_ptr; + *data = req->password; + *password_out = data; + *target_out = req->target; + return 0; +} + +MAKE_ENCODER(encode_krb5_pa_for_user, pa_for_user); +MAKE_DECODER(decode_krb5_pa_for_user, pa_for_user); +MAKE_ENCODER(encode_krb5_s4u_userid, s4u_userid); +MAKE_ENCODER(encode_krb5_pa_s4u_x509_user, pa_s4u_x509_user); +MAKE_DECODER(decode_krb5_pa_s4u_x509_user, pa_s4u_x509_user); +MAKE_ENCODER(encode_krb5_pa_pac_req, pa_pac_req); +MAKE_DECODER(decode_krb5_pa_pac_req, pa_pac_req); +MAKE_ENCODER(encode_krb5_etype_list, etype_list); +MAKE_DECODER(decode_krb5_etype_list, etype_list); + +MAKE_ENCODER(encode_krb5_pa_fx_fast_request, pa_fx_fast_request); +MAKE_DECODER(decode_krb5_pa_fx_fast_request, pa_fx_fast_request); +MAKE_ENCODER(encode_krb5_fast_req, fast_req); +MAKE_DECODER(decode_krb5_fast_req, fast_req); +MAKE_ENCODER(encode_krb5_pa_fx_fast_reply, pa_fx_fast_reply); +MAKE_DECODER(decode_krb5_pa_fx_fast_reply, pa_fx_fast_reply); +MAKE_ENCODER(encode_krb5_fast_response, fast_response); +MAKE_DECODER(decode_krb5_fast_response, fast_response); + +MAKE_ENCODER(encode_krb5_ad_kdcissued, ad_kdc_issued); +MAKE_DECODER(decode_krb5_ad_kdcissued, ad_kdc_issued); +MAKE_ENCODER(encode_krb5_iakerb_header, iakerb_header); +MAKE_DECODER(decode_krb5_iakerb_header, iakerb_header); +MAKE_ENCODER(encode_krb5_iakerb_finished, iakerb_finished); +MAKE_DECODER(decode_krb5_iakerb_finished, iakerb_finished); + +krb5_error_code KRB5_CALLCONV +krb5int_get_authdata_containee_types(krb5_context context, + const krb5_authdata *authdata, + unsigned int *num_out, + krb5_authdatatype **types_out) +{ + krb5_error_code ret; + struct authdata_types *atypes; + void *atypes_ptr; + krb5_data d = make_data(authdata->contents, authdata->length); + + ret = k5_asn1_full_decode(&d, &k5_atype_authdata_types, &atypes_ptr); + if (ret) + return ret; + atypes = atypes_ptr; + *num_out = atypes->ntypes; + *types_out = atypes->types; + free(atypes); + return 0; +} + +/* RFC 3280. No context tags. */ +DEFOFFSETTYPE(algid_0, krb5_algorithm_identifier, algorithm, oid_data); +DEFOFFSETTYPE(algid_1, krb5_algorithm_identifier, parameters, opt_der_data); +static const struct atype_info *algorithm_identifier_fields[] = { + &k5_atype_algid_0, &k5_atype_algid_1 +}; +DEFSEQTYPE(algorithm_identifier, krb5_algorithm_identifier, + algorithm_identifier_fields); +DEFPTRTYPE(ptr_algorithm_identifier, algorithm_identifier); +DEFOPTIONALZEROTYPE(opt_ptr_algorithm_identifier, ptr_algorithm_identifier); +DEFNULLTERMSEQOFTYPE(seqof_algorithm_identifier, ptr_algorithm_identifier); +DEFPTRTYPE(ptr_seqof_algorithm_identifier, seqof_algorithm_identifier); +DEFOPTIONALEMPTYTYPE(opt_ptr_seqof_algorithm_identifier, + ptr_seqof_algorithm_identifier); + +/* + * PKINIT + */ + +#ifndef DISABLE_PKINIT + +DEFCTAGGEDTYPE(kdf_alg_id_0, 0, oid_data); +static const struct atype_info *kdf_alg_id_fields[] = { + &k5_atype_kdf_alg_id_0 +}; +DEFSEQTYPE(kdf_alg_id, krb5_data, kdf_alg_id_fields); +DEFPTRTYPE(ptr_kdf_alg_id, kdf_alg_id); +DEFNONEMPTYNULLTERMSEQOFTYPE(supported_kdfs, ptr_kdf_alg_id); +DEFPTRTYPE(ptr_supported_kdfs, supported_kdfs); +DEFOPTIONALZEROTYPE(opt_ptr_kdf_alg_id, ptr_kdf_alg_id); +DEFOPTIONALZEROTYPE(opt_ptr_supported_kdfs, ptr_supported_kdfs); + +/* KRB5PrincipalName from RFC 4556 (*not* PrincipalName from RFC 4120) */ +DEFCTAGGEDTYPE(pkinit_princ_0, 0, realm_of_principal_data); +DEFCTAGGEDTYPE(pkinit_princ_1, 1, principal_data); +static const struct atype_info *pkinit_krb5_principal_name_fields[] = { + &k5_atype_pkinit_princ_0, &k5_atype_pkinit_princ_1 +}; +DEFSEQTYPE(pkinit_krb5_principal_name_data, krb5_principal_data, + pkinit_krb5_principal_name_fields); +DEFPTRTYPE(pkinit_krb5_principal_name, pkinit_krb5_principal_name_data); + +/* SP80056A OtherInfo, for pkinit agility. No context tag on first field. */ +DEFTAGGEDTYPE(pkinit_krb5_principal_name_wrapped, UNIVERSAL, PRIMITIVE, + ASN1_OCTETSTRING, 0, pkinit_krb5_principal_name); +DEFOFFSETTYPE(oinfo_notag, krb5_sp80056a_other_info, algorithm_identifier, + algorithm_identifier); +DEFFIELD(oinfo_0, krb5_sp80056a_other_info, party_u_info, 0, + pkinit_krb5_principal_name_wrapped); +DEFFIELD(oinfo_1, krb5_sp80056a_other_info, party_v_info, 1, + pkinit_krb5_principal_name_wrapped); +DEFFIELD(oinfo_2, krb5_sp80056a_other_info, supp_pub_info, 2, ostring_data); +static const struct atype_info *sp80056a_other_info_fields[] = { + &k5_atype_oinfo_notag, &k5_atype_oinfo_0, &k5_atype_oinfo_1, + &k5_atype_oinfo_2 +}; +DEFSEQTYPE(sp80056a_other_info, krb5_sp80056a_other_info, + sp80056a_other_info_fields); + +/* For PkinitSuppPubInfo, for pkinit agility */ +DEFFIELD(supp_pub_0, krb5_pkinit_supp_pub_info, enctype, 0, int32); +DEFFIELD(supp_pub_1, krb5_pkinit_supp_pub_info, as_req, 1, ostring_data); +DEFFIELD(supp_pub_2, krb5_pkinit_supp_pub_info, pk_as_rep, 2, ostring_data); +static const struct atype_info *pkinit_supp_pub_info_fields[] = { + &k5_atype_supp_pub_0, &k5_atype_supp_pub_1, &k5_atype_supp_pub_2 +}; +DEFSEQTYPE(pkinit_supp_pub_info, krb5_pkinit_supp_pub_info, + pkinit_supp_pub_info_fields); + +MAKE_ENCODER(encode_krb5_pkinit_supp_pub_info, pkinit_supp_pub_info); +MAKE_ENCODER(encode_krb5_sp80056a_other_info, sp80056a_other_info); + +/* A krb5_checksum encoded as an OCTET STRING, for PKAuthenticator. */ +DEFCOUNTEDTYPE(ostring_checksum, krb5_checksum, contents, length, octetstring); + +DEFFIELD(pk_authenticator_0, krb5_pk_authenticator, cusec, 0, int32); +DEFFIELD(pk_authenticator_1, krb5_pk_authenticator, ctime, 1, kerberos_time); +DEFFIELD(pk_authenticator_2, krb5_pk_authenticator, nonce, 2, int32); +DEFFIELD(pk_authenticator_3, krb5_pk_authenticator, paChecksum, 3, + ostring_checksum); +DEFFIELD(pk_authenticator_4, krb5_pk_authenticator, freshnessToken, 4, + opt_ostring_data_ptr); +static const struct atype_info *pk_authenticator_fields[] = { + &k5_atype_pk_authenticator_0, &k5_atype_pk_authenticator_1, + &k5_atype_pk_authenticator_2, &k5_atype_pk_authenticator_3, + &k5_atype_pk_authenticator_4 +}; +DEFSEQTYPE(pk_authenticator, krb5_pk_authenticator, pk_authenticator_fields); + +DEFCOUNTEDSTRINGTYPE(s_bitstring, char *, unsigned int, + k5_asn1_encode_bitstring, k5_asn1_decode_bitstring, + ASN1_BITSTRING); +DEFCOUNTEDTYPE(bitstring_data, krb5_data, data, length, s_bitstring); + +DEFFIELD(auth_pack_0, krb5_auth_pack, pkAuthenticator, 0, pk_authenticator); +DEFFIELD(auth_pack_1, krb5_auth_pack, clientPublicValue, 1, opt_der_data); +DEFFIELD(auth_pack_2, krb5_auth_pack, supportedCMSTypes, 2, + opt_ptr_seqof_algorithm_identifier); +DEFFIELD(auth_pack_3, krb5_auth_pack, clientDHNonce, 3, opt_ostring_data); +DEFFIELD(auth_pack_4, krb5_auth_pack, supportedKDFs, 4, + opt_ptr_supported_kdfs); +static const struct atype_info *auth_pack_fields[] = { + &k5_atype_auth_pack_0, &k5_atype_auth_pack_1, &k5_atype_auth_pack_2, + &k5_atype_auth_pack_3, &k5_atype_auth_pack_4 +}; +DEFSEQTYPE(auth_pack, krb5_auth_pack, auth_pack_fields); + +DEFFIELD_IMPLICIT(extprinc_0, krb5_external_principal_identifier, + subjectName, 0, opt_ostring_data); +DEFFIELD_IMPLICIT(extprinc_1, krb5_external_principal_identifier, + issuerAndSerialNumber, 1, opt_ostring_data); +DEFFIELD_IMPLICIT(extprinc_2, krb5_external_principal_identifier, + subjectKeyIdentifier, 2, opt_ostring_data); +static const struct atype_info *external_principal_identifier_fields[] = { + &k5_atype_extprinc_0, &k5_atype_extprinc_1, &k5_atype_extprinc_2 +}; +DEFSEQTYPE(external_principal_identifier, krb5_external_principal_identifier, + external_principal_identifier_fields); +DEFPTRTYPE(external_principal_identifier_ptr, external_principal_identifier); + +DEFNULLTERMSEQOFTYPE(seqof_external_principal_identifier, + external_principal_identifier_ptr); +DEFPTRTYPE(ptr_seqof_external_principal_identifier, + seqof_external_principal_identifier); +DEFOPTIONALZEROTYPE(opt_ptr_seqof_external_principal_identifier, + ptr_seqof_external_principal_identifier); + +DEFFIELD_IMPLICIT(pa_pk_as_req_0, krb5_pa_pk_as_req, signedAuthPack, 0, + ostring_data); +DEFFIELD(pa_pk_as_req_1, krb5_pa_pk_as_req, trustedCertifiers, 1, + opt_ptr_seqof_external_principal_identifier); +DEFFIELD_IMPLICIT(pa_pk_as_req_2, krb5_pa_pk_as_req, kdcPkId, 2, + opt_ostring_data); +static const struct atype_info *pa_pk_as_req_fields[] = { + &k5_atype_pa_pk_as_req_0, &k5_atype_pa_pk_as_req_1, + &k5_atype_pa_pk_as_req_2 +}; +DEFSEQTYPE(pa_pk_as_req, krb5_pa_pk_as_req, pa_pk_as_req_fields); + +DEFFIELD_IMPLICIT(dh_rep_info_0, krb5_dh_rep_info, dhSignedData, 0, + ostring_data); +DEFFIELD(dh_rep_info_1, krb5_dh_rep_info, serverDHNonce, 1, opt_ostring_data); +DEFFIELD(dh_rep_info_2, krb5_dh_rep_info, kdfID, 2, opt_ptr_kdf_alg_id); +static const struct atype_info *dh_rep_info_fields[] = { + &k5_atype_dh_rep_info_0, &k5_atype_dh_rep_info_1, &k5_atype_dh_rep_info_2 +}; +DEFSEQTYPE(dh_rep_info, krb5_dh_rep_info, dh_rep_info_fields); + +DEFFIELD(dh_key_0, krb5_kdc_dh_key_info, subjectPublicKey, 0, bitstring_data); +DEFFIELD(dh_key_1, krb5_kdc_dh_key_info, nonce, 1, int32); +DEFFIELD(dh_key_2, krb5_kdc_dh_key_info, dhKeyExpiration, 2, + opt_kerberos_time); +static const struct atype_info *kdc_dh_key_info_fields[] = { + &k5_atype_dh_key_0, &k5_atype_dh_key_1, &k5_atype_dh_key_2 +}; +DEFSEQTYPE(kdc_dh_key_info, krb5_kdc_dh_key_info, kdc_dh_key_info_fields); + +DEFFIELD(reply_key_pack_0, krb5_reply_key_pack, replyKey, 0, encryption_key); +DEFFIELD(reply_key_pack_1, krb5_reply_key_pack, asChecksum, 1, checksum); +static const struct atype_info *reply_key_pack_fields[] = { + &k5_atype_reply_key_pack_0, &k5_atype_reply_key_pack_1 +}; +DEFSEQTYPE(reply_key_pack, krb5_reply_key_pack, reply_key_pack_fields); + +DEFCTAGGEDTYPE(pa_pk_as_rep_0, 0, dh_rep_info); +DEFCTAGGEDTYPE_IMPLICIT(pa_pk_as_rep_1, 1, ostring_data); +static const struct atype_info *pa_pk_as_rep_alternatives[] = { + &k5_atype_pa_pk_as_rep_0, &k5_atype_pa_pk_as_rep_1 +}; +DEFCHOICETYPE(pa_pk_as_rep_choice, union krb5_pa_pk_as_rep_choices, + enum krb5_pa_pk_as_rep_selection, pa_pk_as_rep_alternatives); +DEFCOUNTEDTYPE_SIGNED(pa_pk_as_rep, krb5_pa_pk_as_rep, u, choice, + pa_pk_as_rep_choice); + +MAKE_ENCODER(encode_krb5_pa_pk_as_req, pa_pk_as_req); +MAKE_DECODER(decode_krb5_pa_pk_as_req, pa_pk_as_req); +MAKE_ENCODER(encode_krb5_pa_pk_as_rep, pa_pk_as_rep); +MAKE_DECODER(decode_krb5_pa_pk_as_rep, pa_pk_as_rep); +MAKE_ENCODER(encode_krb5_auth_pack, auth_pack); +MAKE_DECODER(decode_krb5_auth_pack, auth_pack); +MAKE_ENCODER(encode_krb5_kdc_dh_key_info, kdc_dh_key_info); +MAKE_DECODER(decode_krb5_kdc_dh_key_info, kdc_dh_key_info); +MAKE_ENCODER(encode_krb5_reply_key_pack, reply_key_pack); +MAKE_DECODER(decode_krb5_reply_key_pack, reply_key_pack); +MAKE_ENCODER(encode_krb5_td_trusted_certifiers, + seqof_external_principal_identifier); +MAKE_DECODER(decode_krb5_td_trusted_certifiers, + seqof_external_principal_identifier); +MAKE_ENCODER(encode_krb5_td_dh_parameters, seqof_algorithm_identifier); +MAKE_DECODER(decode_krb5_td_dh_parameters, seqof_algorithm_identifier); +MAKE_DECODER(decode_krb5_principal_name, pkinit_krb5_principal_name_data); + +#else /* DISABLE_PKINIT */ + +/* Stubs for exported pkinit encoder functions. */ + +krb5_error_code +encode_krb5_sp80056a_other_info(const krb5_sp80056a_other_info *rep, + krb5_data **code) +{ + return EINVAL; +} + +krb5_error_code +encode_krb5_pkinit_supp_pub_info(const krb5_pkinit_supp_pub_info *rep, + krb5_data **code) +{ + return EINVAL; +} + +#endif /* not DISABLE_PKINIT */ + +DEFFIELD(typed_data_0, krb5_pa_data, pa_type, 0, int32); +DEFCNFIELD(typed_data_1, krb5_pa_data, contents, length, 1, octetstring); +static const struct atype_info *typed_data_fields[] = { + &k5_atype_typed_data_0, &k5_atype_typed_data_1 +}; +DEFSEQTYPE(typed_data, krb5_pa_data, typed_data_fields); +DEFPTRTYPE(typed_data_ptr, typed_data); + +DEFNULLTERMSEQOFTYPE(seqof_typed_data, typed_data_ptr); +MAKE_ENCODER(encode_krb5_typed_data, seqof_typed_data); +MAKE_DECODER(decode_krb5_typed_data, seqof_typed_data); + +/* Definitions for OTP preauth (RFC 6560) */ + +DEFFIELD_IMPLICIT(tokinfo_0, krb5_otp_tokeninfo, flags, 0, krb5_flags); +DEFFIELD_IMPLICIT(tokinfo_1, krb5_otp_tokeninfo, vendor, 1, opt_utf8_data); +DEFFIELD_IMPLICIT(tokinfo_2, krb5_otp_tokeninfo, challenge, 2, + opt_ostring_data); +DEFFIELD_IMPLICIT(tokinfo_3, krb5_otp_tokeninfo, length, 3, opt_int32_minus1); +DEFFIELD_IMPLICIT(tokinfo_4, krb5_otp_tokeninfo, format, 4, opt_int32_minus1); +DEFFIELD_IMPLICIT(tokinfo_5, krb5_otp_tokeninfo, token_id, 5, + opt_ostring_data); +DEFFIELD_IMPLICIT(tokinfo_6, krb5_otp_tokeninfo, alg_id, 6, opt_utf8_data); +DEFFIELD_IMPLICIT(tokinfo_7, krb5_otp_tokeninfo, supported_hash_alg, 7, + opt_ptr_seqof_algorithm_identifier); +DEFFIELD_IMPLICIT(tokinfo_8, krb5_otp_tokeninfo, iteration_count, 8, + opt_int32_minus1); +static const struct atype_info *otp_tokeninfo_fields[] = { + &k5_atype_tokinfo_0, &k5_atype_tokinfo_1, &k5_atype_tokinfo_2, + &k5_atype_tokinfo_3, &k5_atype_tokinfo_4, &k5_atype_tokinfo_5, + &k5_atype_tokinfo_6, &k5_atype_tokinfo_7, &k5_atype_tokinfo_8 +}; +DEFSEQTYPE(otp_tokeninfo, krb5_otp_tokeninfo, otp_tokeninfo_fields); +MAKE_ENCODER(encode_krb5_otp_tokeninfo, otp_tokeninfo); +MAKE_DECODER(decode_krb5_otp_tokeninfo, otp_tokeninfo); + +DEFPTRTYPE(otp_tokeninfo_ptr, otp_tokeninfo); +DEFNONEMPTYNULLTERMSEQOFTYPE(seqof_otp_tokeninfo, otp_tokeninfo_ptr); +DEFPTRTYPE(ptr_seqof_otp_tokeninfo, seqof_otp_tokeninfo); + +DEFFIELD_IMPLICIT(otp_ch_0, krb5_pa_otp_challenge, nonce, 0, ostring_data); +DEFFIELD_IMPLICIT(otp_ch_1, krb5_pa_otp_challenge, service, 1, opt_utf8_data); +DEFFIELD_IMPLICIT(otp_ch_2, krb5_pa_otp_challenge, tokeninfo, 2, + ptr_seqof_otp_tokeninfo); +DEFFIELD_IMPLICIT(otp_ch_3, krb5_pa_otp_challenge, salt, 3, opt_gstring_data); +DEFFIELD_IMPLICIT(otp_ch_4, krb5_pa_otp_challenge, s2kparams, 4, + opt_ostring_data); +static const struct atype_info *pa_otp_challenge_fields[] = { + &k5_atype_otp_ch_0, &k5_atype_otp_ch_1, &k5_atype_otp_ch_2, + &k5_atype_otp_ch_3, &k5_atype_otp_ch_4 +}; +DEFSEQTYPE(pa_otp_challenge, krb5_pa_otp_challenge, pa_otp_challenge_fields); +MAKE_ENCODER(encode_krb5_pa_otp_challenge, pa_otp_challenge); +MAKE_DECODER(decode_krb5_pa_otp_challenge, pa_otp_challenge); + +DEFFIELD_IMPLICIT(otp_req_0, krb5_pa_otp_req, flags, 0, krb5_flags); +DEFFIELD_IMPLICIT(otp_req_1, krb5_pa_otp_req, nonce, 1, opt_ostring_data); +DEFFIELD_IMPLICIT(otp_req_2, krb5_pa_otp_req, enc_data, 2, encrypted_data); +DEFFIELD_IMPLICIT(otp_req_3, krb5_pa_otp_req, hash_alg, 3, + opt_ptr_algorithm_identifier); +DEFFIELD_IMPLICIT(otp_req_4, krb5_pa_otp_req, iteration_count, 4, + opt_int32_minus1); +DEFFIELD_IMPLICIT(otp_req_5, krb5_pa_otp_req, otp_value, 5, opt_ostring_data); +DEFFIELD_IMPLICIT(otp_req_6, krb5_pa_otp_req, pin, 6, opt_utf8_data); +DEFFIELD_IMPLICIT(otp_req_7, krb5_pa_otp_req, challenge, 7, opt_ostring_data); +DEFFIELD_IMPLICIT(otp_req_8, krb5_pa_otp_req, time, 8, opt_kerberos_time); +DEFFIELD_IMPLICIT(otp_req_9, krb5_pa_otp_req, counter, 9, opt_ostring_data); +DEFFIELD_IMPLICIT(otp_req_10, krb5_pa_otp_req, format, 10, opt_int32_minus1); +DEFFIELD_IMPLICIT(otp_req_11, krb5_pa_otp_req, token_id, 11, opt_ostring_data); +DEFFIELD_IMPLICIT(otp_req_12, krb5_pa_otp_req, alg_id, 12, opt_utf8_data); +DEFFIELD_IMPLICIT(otp_req_13, krb5_pa_otp_req, vendor, 13, opt_utf8_data); +static const struct atype_info *pa_otp_req_fields[] = { + &k5_atype_otp_req_0, &k5_atype_otp_req_1, &k5_atype_otp_req_2, + &k5_atype_otp_req_3, &k5_atype_otp_req_4, &k5_atype_otp_req_5, + &k5_atype_otp_req_6, &k5_atype_otp_req_7, &k5_atype_otp_req_8, + &k5_atype_otp_req_9, &k5_atype_otp_req_10, &k5_atype_otp_req_11, + &k5_atype_otp_req_12, &k5_atype_otp_req_13 +}; +DEFSEQTYPE(pa_otp_req, krb5_pa_otp_req, pa_otp_req_fields); +MAKE_ENCODER(encode_krb5_pa_otp_req, pa_otp_req); +MAKE_DECODER(decode_krb5_pa_otp_req, pa_otp_req); + +DEFCTAGGEDTYPE_IMPLICIT(pa_otp_enc_req_0, 0, ostring_data); +static const struct atype_info *pa_otp_enc_req_fields[] = { + &k5_atype_pa_otp_enc_req_0 +}; +DEFSEQTYPE(pa_otp_enc_req, krb5_data, pa_otp_enc_req_fields); +MAKE_ENCODER(encode_krb5_pa_otp_enc_req, pa_otp_enc_req); +MAKE_DECODER(decode_krb5_pa_otp_enc_req, pa_otp_enc_req); + +DEFFIELD(kkdcp_message_0, krb5_kkdcp_message, + kerb_message, 0, ostring_data); +DEFFIELD(kkdcp_message_1, krb5_kkdcp_message, + target_domain, 1, opt_gstring_data); +DEFFIELD(kkdcp_message_2, krb5_kkdcp_message, + dclocator_hint, 2, opt_int32); +static const struct atype_info *kkdcp_message_fields[] = { + &k5_atype_kkdcp_message_0, &k5_atype_kkdcp_message_1, + &k5_atype_kkdcp_message_2 +}; +DEFSEQTYPE(kkdcp_message, krb5_kkdcp_message, + kkdcp_message_fields); +MAKE_ENCODER(encode_krb5_kkdcp_message, kkdcp_message); +MAKE_DECODER(decode_krb5_kkdcp_message, kkdcp_message); + +DEFFIELD(vmac_0, krb5_verifier_mac, princ, 0, opt_principal); +DEFFIELD(vmac_1, krb5_verifier_mac, kvno, 1, opt_kvno); +DEFFIELD(vmac_2, krb5_verifier_mac, enctype, 2, opt_int32); +DEFFIELD(vmac_3, krb5_verifier_mac, checksum, 3, checksum); +static const struct atype_info *vmac_fields[] = { + &k5_atype_vmac_0, &k5_atype_vmac_1, &k5_atype_vmac_2, &k5_atype_vmac_3 +}; +DEFSEQTYPE(vmac, krb5_verifier_mac, vmac_fields); +DEFPTRTYPE(vmac_ptr, vmac); +DEFOPTIONALZEROTYPE(opt_vmac_ptr, vmac_ptr); +DEFNONEMPTYNULLTERMSEQOFTYPE(vmacs, vmac_ptr); +DEFPTRTYPE(vmacs_ptr, vmacs); +DEFOPTIONALEMPTYTYPE(opt_vmacs_ptr, vmacs_ptr); + +DEFFIELD(cammac_0, krb5_cammac, elements, 0, auth_data_ptr); +DEFFIELD(cammac_1, krb5_cammac, kdc_verifier, 1, opt_vmac_ptr); +DEFFIELD(cammac_2, krb5_cammac, svc_verifier, 2, opt_vmac_ptr); +DEFFIELD(cammac_3, krb5_cammac, other_verifiers, 3, opt_vmacs_ptr); +static const struct atype_info *cammac_fields[] = { + &k5_atype_cammac_0, &k5_atype_cammac_1, &k5_atype_cammac_2, + &k5_atype_cammac_3 +}; +DEFSEQTYPE(cammac, krb5_cammac, cammac_fields); + +MAKE_ENCODER(encode_krb5_cammac, cammac); +MAKE_DECODER(decode_krb5_cammac, cammac); + +MAKE_ENCODER(encode_utf8_strings, seqof_utf8_data); +MAKE_DECODER(decode_utf8_strings, seqof_utf8_data); + +/* + * SecureCookie ::= SEQUENCE { + * time INTEGER, + * data SEQUENCE OF PA-DATA, + * ... + * } + */ +DEFINTTYPE(inttime, time_t); +DEFOFFSETTYPE(secure_cookie_0, krb5_secure_cookie, time, inttime); +DEFOFFSETTYPE(secure_cookie_1, krb5_secure_cookie, data, ptr_seqof_pa_data); +static const struct atype_info *secure_cookie_fields[] = { + &k5_atype_secure_cookie_0, &k5_atype_secure_cookie_1 +}; +DEFSEQTYPE(secure_cookie, krb5_secure_cookie, secure_cookie_fields); +MAKE_ENCODER(encode_krb5_secure_cookie, secure_cookie); +MAKE_DECODER(decode_krb5_secure_cookie, secure_cookie); + +/* + * -- based on MS-KILE and MS-SFU + * PAC-OPTIONS-FLAGS ::= BIT STRING { + * claims(0), + * branch-aware(1), + * forward-to-full-dc(2), + * resource-based-constrained-delegation(3) + * } + * + * PA-PAC-OPTIONS ::= SEQUENCE { + * flags [0] PAC-OPTIONS-FLAGS + * } + */ +DEFFIELD(pa_pac_options_0, krb5_pa_pac_options, options, 0, krb5_flags); +static const struct atype_info *pa_pac_options_fields[] = { + &k5_atype_pa_pac_options_0 +}; +DEFSEQTYPE(pa_pac_options, krb5_pa_pac_options, pa_pac_options_fields); +MAKE_ENCODER(encode_krb5_pa_pac_options, pa_pac_options); +MAKE_DECODER(decode_krb5_pa_pac_options, pa_pac_options); + + +DEFFIELD(spake_factor_0, krb5_spake_factor, type, 0, int32); +DEFFIELD(spake_factor_1, krb5_spake_factor, data, 1, opt_ostring_data_ptr); +static const struct atype_info *spake_factor_fields[] = { + &k5_atype_spake_factor_0, &k5_atype_spake_factor_1 +}; +DEFSEQTYPE(spake_factor, krb5_spake_factor, spake_factor_fields); +DEFPTRTYPE(spake_factor_ptr, spake_factor); +DEFNULLTERMSEQOFTYPE(seqof_spake_factor, spake_factor_ptr); +DEFPTRTYPE(ptr_seqof_spake_factor, seqof_spake_factor); +MAKE_ENCODER(encode_krb5_spake_factor, spake_factor); +MAKE_DECODER(decode_krb5_spake_factor, spake_factor); + +DEFCNFIELD(spake_support_0, krb5_spake_support, groups, ngroups, 0, + cseqof_int32); +static const struct atype_info *spake_support_fields[] = { + &k5_atype_spake_support_0 +}; +DEFSEQTYPE(spake_support, krb5_spake_support, spake_support_fields); + +DEFFIELD(spake_challenge_0, krb5_spake_challenge, group, 0, int32); +DEFFIELD(spake_challenge_1, krb5_spake_challenge, pubkey, 1, ostring_data); +DEFFIELD(spake_challenge_2, krb5_spake_challenge, factors, 2, + ptr_seqof_spake_factor); +static const struct atype_info *spake_challenge_fields[] = { + &k5_atype_spake_challenge_0, &k5_atype_spake_challenge_1, + &k5_atype_spake_challenge_2 +}; +DEFSEQTYPE(spake_challenge, krb5_spake_challenge, spake_challenge_fields); + +DEFFIELD(spake_response_0, krb5_spake_response, pubkey, 0, ostring_data); +DEFFIELD(spake_response_1, krb5_spake_response, factor, 1, encrypted_data); +static const struct atype_info *spake_response_fields[] = { + &k5_atype_spake_response_0, &k5_atype_spake_response_1, +}; +DEFSEQTYPE(spake_response, krb5_spake_response, spake_response_fields); + +DEFCTAGGEDTYPE(pa_spake_0, 0, spake_support); +DEFCTAGGEDTYPE(pa_spake_1, 1, spake_challenge); +DEFCTAGGEDTYPE(pa_spake_2, 2, spake_response); +DEFCTAGGEDTYPE(pa_spake_3, 3, encrypted_data); +static const struct atype_info *pa_spake_alternatives[] = { + &k5_atype_pa_spake_0, &k5_atype_pa_spake_1, &k5_atype_pa_spake_2, + &k5_atype_pa_spake_3 +}; +DEFCHOICETYPE(pa_spake_choice, union krb5_spake_message_choices, + enum krb5_spake_msgtype, pa_spake_alternatives); +DEFCOUNTEDTYPE_SIGNED(pa_spake, krb5_pa_spake, u, choice, pa_spake_choice); +MAKE_ENCODER(encode_krb5_pa_spake, pa_spake); +MAKE_DECODER(decode_krb5_pa_spake, pa_spake); diff --git a/krb5-1.21.3/src/lib/krb5/asn.1/deps b/krb5-1.21.3/src/lib/krb5/asn.1/deps new file mode 100644 index 00000000..01d2d23a --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/asn.1/deps @@ -0,0 +1,38 @@ +# +# Generated makefile dependencies follow. +# +asn1_encode.so asn1_encode.po $(OUTPRE)asn1_encode.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + asn1_encode.c asn1_encode.h krbasn1.h +asn1_k_encode.so asn1_k_encode.po $(OUTPRE)asn1_k_encode.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-spake.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h asn1_encode.h \ + asn1_k_encode.c krbasn1.h +ldap_key_seq.so ldap_key_seq.po $(OUTPRE)ldap_key_seq.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h asn1_encode.h \ + krbasn1.h ldap_key_seq.c diff --git a/krb5-1.21.3/src/lib/krb5/asn.1/krbasn1.h b/krb5-1.21.3/src/lib/krb5/asn.1/krbasn1.h new file mode 100644 index 00000000..59d7fd98 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/asn.1/krbasn1.h @@ -0,0 +1,56 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#ifndef __KRBASN1_H__ +#define __KRBASN1_H__ + +#include "k5-int.h" +#include +#include +#include /* For INT_MAX */ +#ifdef HAVE_STDLIB_H +#include +#endif + +typedef krb5_error_code asn1_error_code; + +typedef enum { PRIMITIVE = 0x00, CONSTRUCTED = 0x20 } asn1_construction; + +typedef enum { UNIVERSAL = 0x00, APPLICATION = 0x40, + CONTEXT_SPECIFIC = 0x80, PRIVATE = 0xC0 } asn1_class; + +typedef int asn1_tagnum; +#define ASN1_TAGNUM_CEILING INT_MAX +#define ASN1_TAGNUM_MAX (ASN1_TAGNUM_CEILING-1) + +/* This is Kerberos Version 5 */ +#define KVNO 5 + +/* Universal Tag Numbers */ +#define ASN1_BOOLEAN 1 +#define ASN1_INTEGER 2 +#define ASN1_BITSTRING 3 +#define ASN1_OCTETSTRING 4 +#define ASN1_NULL 5 +#define ASN1_OBJECTIDENTIFIER 6 +#define ASN1_ENUMERATED 10 +#define ASN1_UTF8STRING 12 +#define ASN1_SEQUENCE 16 +#define ASN1_SET 17 +#define ASN1_PRINTABLESTRING 19 +#define ASN1_IA5STRING 22 +#define ASN1_UTCTIME 23 +#define ASN1_GENERALTIME 24 +#define ASN1_GENERALSTRING 27 + +/* Kerberos Message Types */ +#define ASN1_KRB_AS_REQ 10 +#define ASN1_KRB_AS_REP 11 +#define ASN1_KRB_TGS_REQ 12 +#define ASN1_KRB_TGS_REP 13 +#define ASN1_KRB_AP_REQ 14 +#define ASN1_KRB_AP_REP 15 +#define ASN1_KRB_SAFE 20 +#define ASN1_KRB_PRIV 21 +#define ASN1_KRB_CRED 22 +#define ASN1_KRB_ERROR 30 + +#endif diff --git a/krb5-1.21.3/src/lib/krb5/asn.1/ldap_key_seq.c b/krb5-1.21.3/src/lib/krb5/asn.1/ldap_key_seq.c new file mode 100644 index 00000000..9508bc34 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/asn.1/ldap_key_seq.c @@ -0,0 +1,124 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* ... copyright ... */ + +/* + * Novell key-format scheme: + * + * KrbKeySet ::= SEQUENCE { + * attribute-major-vno [0] UInt16, + * attribute-minor-vno [1] UInt16, + * kvno [2] UInt32, + * mkvno [3] UInt32 OPTIONAL, + * keys [4] SEQUENCE OF KrbKey, + * ... + * } + * + * KrbKey ::= SEQUENCE { + * salt [0] KrbSalt OPTIONAL, + * key [1] EncryptionKey, + * s2kparams [2] OCTET STRING OPTIONAL, + * ... + * } + * + * KrbSalt ::= SEQUENCE { + * type [0] Int32, + * salt [1] OCTET STRING OPTIONAL + * } + * + * EncryptionKey ::= SEQUENCE { + * keytype [0] Int32, + * keyvalue [1] OCTET STRING + * } + * + */ + +#include +#include + +#include "krbasn1.h" +#include "asn1_encode.h" + +#ifdef ENABLE_LDAP + +/************************************************************************/ +/* Encode the Principal's keys */ +/************************************************************************/ + +/* + * Imports from asn1_k_encode.c. + * XXX Must be manually synchronized for now. + */ +IMPORT_TYPE(int32, int32_t); + +DEFINTTYPE(int16, int16_t); +DEFINTTYPE(uint16, uint16_t); + +DEFCOUNTEDSTRINGTYPE(ui2_octetstring, uint8_t *, uint16_t, + k5_asn1_encode_bytestring, k5_asn1_decode_bytestring, + ASN1_OCTETSTRING); + +static int +is_value_present(const void *p) +{ + const krb5_key_data *val = p; + return (val->key_data_length[1] != 0); +} +DEFCOUNTEDTYPE(krbsalt_salt, krb5_key_data, key_data_contents[1], + key_data_length[1], ui2_octetstring); +DEFOPTIONALTYPE(krbsalt_salt_if_present, is_value_present, NULL, krbsalt_salt); +DEFFIELD(krbsalt_0, krb5_key_data, key_data_type[1], 0, int16); +DEFCTAGGEDTYPE(krbsalt_1, 1, krbsalt_salt_if_present); +static const struct atype_info *krbsalt_fields[] = { + &k5_atype_krbsalt_0, &k5_atype_krbsalt_1 +}; +DEFSEQTYPE(krbsalt, krb5_key_data, krbsalt_fields); + +DEFFIELD(encryptionkey_0, krb5_key_data, key_data_type[0], 0, int16); +DEFCNFIELD(encryptionkey_1, krb5_key_data, key_data_contents[0], + key_data_length[0], 1, ui2_octetstring); +static const struct atype_info *encryptionkey_fields[] = { + &k5_atype_encryptionkey_0, &k5_atype_encryptionkey_1 +}; +DEFSEQTYPE(encryptionkey, krb5_key_data, encryptionkey_fields); + +static int +is_salt_present(const void *p) +{ + const krb5_key_data *val = p; + return val->key_data_ver > 1; +} +static void +no_salt(void *p) +{ + krb5_key_data *val = p; + val->key_data_ver = 1; +} +DEFOPTIONALTYPE(key_data_salt_if_present, is_salt_present, no_salt, krbsalt); +DEFCTAGGEDTYPE(key_data_0, 0, key_data_salt_if_present); +DEFCTAGGEDTYPE(key_data_1, 1, encryptionkey); +static const struct atype_info *key_data_fields[] = { + &k5_atype_key_data_0, &k5_atype_key_data_1 +}; +DEFSEQTYPE(key_data, krb5_key_data, key_data_fields); +DEFPTRTYPE(ptr_key_data, key_data); +DEFCOUNTEDSEQOFTYPE(cseqof_key_data, int16_t, ptr_key_data); + +DEFINT_IMMEDIATE(one, 1, ASN1_BAD_FORMAT); +DEFCTAGGEDTYPE(ldap_key_seq_0, 0, one); +DEFCTAGGEDTYPE(ldap_key_seq_1, 1, one); +DEFFIELD(ldap_key_seq_2, ldap_seqof_key_data, kvno, 2, uint16); +DEFFIELD(ldap_key_seq_3, ldap_seqof_key_data, mkvno, 3, int32); +DEFCNFIELD(ldap_key_seq_4, ldap_seqof_key_data, key_data, n_key_data, 4, + cseqof_key_data); +static const struct atype_info *ldap_key_seq_fields[] = { + &k5_atype_ldap_key_seq_0, &k5_atype_ldap_key_seq_1, + &k5_atype_ldap_key_seq_2, &k5_atype_ldap_key_seq_3, + &k5_atype_ldap_key_seq_4 +}; +DEFSEQTYPE(ldap_key_seq, ldap_seqof_key_data, ldap_key_seq_fields); + +/* Export a function to do the whole encoding. */ +MAKE_ENCODER(krb5int_ldap_encode_sequence_of_keys, ldap_key_seq); +MAKE_DECODER(krb5int_ldap_decode_sequence_of_keys, ldap_key_seq); + +#endif diff --git a/krb5-1.21.3/src/lib/krb5/ccache/Makefile.in b/krb5-1.21.3/src/lib/krb5/ccache/Makefile.in new file mode 100644 index 00000000..2864e92b --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/Makefile.in @@ -0,0 +1,166 @@ +mydir=lib$(S)krb5$(S)ccache +BUILDTOP=$(REL)..$(S)..$(S).. +SUBDIRS = # ccapi +WINSUBDIRS = ccapi +##WIN32##DEFINES = -DUSE_CCAPI + +LOCALINCLUDES = -I$(srcdir)$(S)ccapi -I$(srcdir) -I. + +##DOS##BUILDTOP = ..\..\.. +##DOS##PREFIXDIR=ccache +##DOS##OBJFILE=..\$(OUTPRE)$(PREFIXDIR).lst + +##WIN32##MSLSA_OBJ = $(OUTPRE)cc_mslsa.$(OBJEXT) +##WIN32##MSLSA_SRC = $(srcdir)/cc_mslsa.c + +##WIN32##!if 0 +KCMRPC_DEPS-osx = kcmrpc.h kcmrpc_types.h +KCMRPC_OBJ-osx = kcmrpc.o +KCMRPC_DEPS-no = # empty +KCMRPC_OBJ-no = # empty + +KCMRPC_DEPS = $(KCMRPC_DEPS-@OSX@) +KCMRPC_OBJ = $(KCMRPC_OBJ-@OSX@) +##WIN32##!endif + + +STLIBOBJS= \ + ccapi_util.o \ + ccbase.o \ + cccopy.o \ + cccursor.o \ + ccdefault.o \ + ccdefops.o \ + ccmarshal.o \ + ccselect.o \ + ccselect_hostname.o \ + ccselect_k5identity.o \ + ccselect_realm.o \ + cc_api_macos.o \ + cc_dir.o \ + cc_retr.o \ + cc_file.o \ + cc_kcm.o \ + cc_memory.o \ + cc_keyring.o \ + ccfns.o \ + $(KCMRPC_OBJ) + +OBJS= $(OUTPRE)ccapi_util.$(OBJEXT) \ + $(OUTPRE)ccbase.$(OBJEXT) \ + $(OUTPRE)cccopy.$(OBJEXT) \ + $(OUTPRE)cccursor.$(OBJEXT) \ + $(OUTPRE)ccdefault.$(OBJEXT) \ + $(OUTPRE)ccdefops.$(OBJEXT) \ + $(OUTPRE)ccmarshal.$(OBJEXT) \ + $(OUTPRE)ccselect.$(OBJEXT) \ + $(OUTPRE)ccselect_hostname.$(OBJEXT) \ + $(OUTPRE)ccselect_k5identity.$(OBJEXT) \ + $(OUTPRE)ccselect_realm.$(OBJEXT) \ + $(OUTPRE)cc_api_macos.$(OBJEXT) \ + $(OUTPRE)cc_dir.$(OBJEXT) \ + $(OUTPRE)cc_retr.$(OBJEXT) \ + $(OUTPRE)cc_file.$(OBJEXT) \ + $(OUTPRE)cc_kcm.$(OBJEXT) \ + $(OUTPRE)cc_memory.$(OBJEXT) \ + $(OUTPRE)cc_keyring.$(OBJEXT) \ + $(OUTPRE)ccfns.$(OBJEXT) \ + $(MSLSA_OBJ) + +SRCS= $(srcdir)/ccapi_util.c \ + $(srcdir)/ccbase.c \ + $(srcdir)/cccopy.c \ + $(srcdir)/cccursor.c \ + $(srcdir)/ccdefault.c \ + $(srcdir)/ccdefops.c \ + $(srcdir)/ccmarshal.c \ + $(srcdir)/ccselect.c \ + $(srcdir)/ccselect_hostname.c \ + $(srcdir)/ccselect_k5identity.c \ + $(srcdir)/ccselect_realm.c \ + $(srcdir)/cc_api_macos.c \ + $(srcdir)/cc_dir.c \ + $(srcdir)/cc_retr.c \ + $(srcdir)/cc_file.c \ + $(srcdir)/cc_kcm.c \ + $(srcdir)/cc_memory.c \ + $(srcdir)/cc_keyring.c \ + $(srcdir)/ccfns.c \ + $(MSLSA_SRC) + +EXTRADEPSRCS= \ + $(srcdir)/t_cc.c \ + $(srcdir)/t_cccol.c \ + $(srcdir)/t_cccursor.c \ + $(srcdir)/t_marshal.c + +##DOS##OBJS=$(OBJS) $(OUTPRE)ccfns.$(OBJEXT) + +all-unix: all-libobjs + +all-windows: subdirs $(OBJFILE) + +##DOS##subdirs: ccapi\$(OUTPRE)file.lst + +##DOS##ccapi\$(OUTPRE)file.lst: +##DOS## cd ccapi +##DOS## @echo Making in krb5\ccache\ccapi +##DOS## $(MAKE) -$(MFLAGS) +##DOS## cd .. + +##DOS##$(OBJFILE): $(OBJS) ccapi\$(OUTPRE)file.lst +##DOS## $(RM) $(OBJFILE) +##WIN32## $(LIBECHO) -p $(PREFIXDIR)\ $(OUTPRE)*.obj \ +##WIN32## ccapi\$(OUTPRE)*.obj > $(OBJFILE) + +kcmrpc.h kcmrpc.c: kcmrpc.defs + mig -header kcmrpc.h -user kcmrpc.c -sheader /dev/null \ + -server /dev/null -I$(srcdir) $(srcdir)/kcmrpc.defs + +clean-unix:: clean-libobjs + +clean-windows:: + cd ccapi + @echo Making clean in krb5\ccache\ccapi + $(MAKE) -$(MFLAGS) clean + cd .. + @echo Making clean in krb5\ccache + $(RM) $(OBJFILE) + +T_CC_OBJS=t_cc.o + +t_cc: $(T_CC_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_cc $(T_CC_OBJS) $(KRB5_BASE_LIBS) + +T_CCCOL_OBJS = t_cccol.o +t_cccol: $(T_CCCOL_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ $(T_CCCOL_OBJS) $(KRB5_BASE_LIBS) + +T_CCCURSOR_OBJS = t_cccursor.o +t_cccursor: $(T_CCCURSOR_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ $(T_CCCURSOR_OBJS) $(KRB5_BASE_LIBS) + +T_MARSHAL_OBJS = t_marshal.o +t_marshal: $(T_MARSHAL_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ $(T_MARSHAL_OBJS) $(KRB5_BASE_LIBS) + +check-unix: t_cc t_marshal + $(RUN_TEST) ./t_cc + $(RUN_TEST) ./t_marshal testcache + +check-pytests: t_cccursor t_cccol + $(RUNPYTEST) $(srcdir)/t_cccol.py $(PYTESTFLAGS) + +clean-unix:: + $(RM) t_cc t_cc.o t_cccursor t_cccursor.o t_cccol t_cccol.o + $(RM) t_marshal t_marshal.o testcache kcmrpc.c kcmrpc.h + +depend: $(KCMRPC_DEPS) + +##WIN32##$(OUTPRE)cc_mslsa.$(OBJEXT): cc_mslsa.c $(top_srcdir)/include/k5-int.h $(BUILDTOP)/include/krb5.h $(COM_ERR_DEPS) + +cc_kcm.so cc_kcm.o: $(KCMRPC_DEPS) +kcmrpc.so kcmrpc.o: kcmrpc.h kcmrpc_types.h + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/krb5/ccache/cc-int.h b/krb5-1.21.3/src/lib/krb5/ccache/cc-int.h new file mode 100644 index 00000000..51c6df21 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/cc-int.h @@ -0,0 +1,229 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/cc-int.h */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* This file contains constant and function declarations used in the + * file-based credential cache routines. */ + +#ifndef __KRB5_CCACHE_H__ +#define __KRB5_CCACHE_H__ + +#include "k5-int.h" + +struct _krb5_ccache { + krb5_magic magic; + const struct _krb5_cc_ops *ops; + krb5_pointer data; +}; + +krb5_error_code +k5_cc_retrieve_cred_default(krb5_context, krb5_ccache, krb5_flags, + krb5_creds *, krb5_creds *); + +krb5_boolean +krb5int_cc_creds_match_request(krb5_context, krb5_flags whichfields, krb5_creds *mcreds, krb5_creds *creds); + +int +krb5int_cc_initialize(void); + +void +krb5int_cc_finalize(void); + +krb5_error_code +k5_nonatomic_replace(krb5_context context, krb5_ccache ccache, + krb5_principal princ, krb5_creds **creds); + +/* + * Cursor for iterating over ccache types + */ +struct krb5_cc_typecursor; +typedef struct krb5_cc_typecursor *krb5_cc_typecursor; + +krb5_error_code +krb5int_cc_typecursor_new(krb5_context context, krb5_cc_typecursor *cursor); + +krb5_error_code +krb5int_cc_typecursor_next( + krb5_context context, + krb5_cc_typecursor cursor, + const struct _krb5_cc_ops **ops); + +krb5_error_code +krb5int_cc_typecursor_free( + krb5_context context, + krb5_cc_typecursor *cursor); + +/* reentrant mutex used by krb5_cc_* functions */ +typedef struct _k5_cc_mutex { + k5_mutex_t lock; + krb5_context owner; + krb5_int32 refcount; +} k5_cc_mutex; + +#define K5_CC_MUTEX_PARTIAL_INITIALIZER \ + { K5_MUTEX_PARTIAL_INITIALIZER, NULL, 0 } + +krb5_error_code +k5_cc_mutex_init(k5_cc_mutex *m); + +krb5_error_code +k5_cc_mutex_finish_init(k5_cc_mutex *m); + +#define k5_cc_mutex_destroy(M) \ + k5_mutex_destroy(&(M)->lock); + +void +k5_cc_mutex_assert_locked(krb5_context context, k5_cc_mutex *m); + +void +k5_cc_mutex_assert_unlocked(krb5_context context, k5_cc_mutex *m); + +void +k5_cc_mutex_lock(krb5_context context, k5_cc_mutex *m); + +void +k5_cc_mutex_unlock(krb5_context context, k5_cc_mutex *m); + +extern k5_cc_mutex krb5int_mcc_mutex; +extern k5_cc_mutex krb5int_krcc_mutex; +extern k5_cc_mutex krb5int_cc_file_mutex; + +extern krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_lock +(krb5_context context); + +extern krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_unlock +(krb5_context context); + +krb5_error_code +k5_cc_lock(krb5_context context, krb5_ccache ccache); + +krb5_error_code +k5_cc_unlock(krb5_context context, krb5_ccache ccache); + +krb5_error_code +k5_cccol_lock(krb5_context context); + +krb5_error_code +k5_cccol_unlock(krb5_context context); + +void +k5_cc_mutex_force_unlock(k5_cc_mutex *m); + +void +k5_cccol_force_unlock(void); + +krb5_error_code +krb5int_fcc_new_unique(krb5_context context, char *template, krb5_ccache *id); + +krb5_error_code +ccselect_hostname_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +ccselect_realm_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +ccselect_k5identity_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +k5_unmarshal_cred(const unsigned char *data, size_t len, int version, + krb5_creds *creds); + +krb5_error_code +k5_unmarshal_princ(const unsigned char *data, size_t len, int version, + krb5_principal *princ_out); + +void +k5_marshal_cred(struct k5buf *buf, int version, krb5_creds *creds); + +void +k5_marshal_mcred(struct k5buf *buf, krb5_creds *mcred); + +void +k5_marshal_princ(struct k5buf *buf, int version, krb5_principal princ); + +krb5_error_code +k5_kcm_primary_name(krb5_context context, char **name_out); + +/* + * Per-type ccache cursor. + */ +struct krb5_cc_ptcursor_s { + const struct _krb5_cc_ops *ops; + krb5_pointer data; +}; +typedef struct krb5_cc_ptcursor_s *krb5_cc_ptcursor; + +struct _krb5_cc_ops { + krb5_magic magic; + char *prefix; + const char * (KRB5_CALLCONV *get_name)(krb5_context, krb5_ccache); + krb5_error_code (KRB5_CALLCONV *resolve)(krb5_context, krb5_ccache *, + const char *); + krb5_error_code (KRB5_CALLCONV *gen_new)(krb5_context, krb5_ccache *); + krb5_error_code (KRB5_CALLCONV *init)(krb5_context, krb5_ccache, + krb5_principal); + krb5_error_code (KRB5_CALLCONV *destroy)(krb5_context, krb5_ccache); + krb5_error_code (KRB5_CALLCONV *close)(krb5_context, krb5_ccache); + krb5_error_code (KRB5_CALLCONV *store)(krb5_context, krb5_ccache, + krb5_creds *); + krb5_error_code (KRB5_CALLCONV *retrieve)(krb5_context, krb5_ccache, + krb5_flags, krb5_creds *, + krb5_creds *); + krb5_error_code (KRB5_CALLCONV *get_princ)(krb5_context, krb5_ccache, + krb5_principal *); + krb5_error_code (KRB5_CALLCONV *get_first)(krb5_context, krb5_ccache, + krb5_cc_cursor *); + krb5_error_code (KRB5_CALLCONV *get_next)(krb5_context, krb5_ccache, + krb5_cc_cursor *, krb5_creds *); + krb5_error_code (KRB5_CALLCONV *end_get)(krb5_context, krb5_ccache, + krb5_cc_cursor *); + krb5_error_code (KRB5_CALLCONV *remove_cred)(krb5_context, krb5_ccache, + krb5_flags, krb5_creds *); + krb5_error_code (KRB5_CALLCONV *set_flags)(krb5_context, krb5_ccache, + krb5_flags); + krb5_error_code (KRB5_CALLCONV *get_flags)(krb5_context, krb5_ccache, + krb5_flags *); + krb5_error_code (KRB5_CALLCONV *ptcursor_new)(krb5_context, + krb5_cc_ptcursor *); + krb5_error_code (KRB5_CALLCONV *ptcursor_next)(krb5_context, + krb5_cc_ptcursor, + krb5_ccache *); + krb5_error_code (KRB5_CALLCONV *ptcursor_free)(krb5_context, + krb5_cc_ptcursor *); + krb5_error_code (KRB5_CALLCONV *replace)(krb5_context, krb5_ccache, + krb5_principal, krb5_creds **); + krb5_error_code (KRB5_CALLCONV *wasdefault)(krb5_context, krb5_ccache, + krb5_timestamp *); + krb5_error_code (KRB5_CALLCONV *lock)(krb5_context, krb5_ccache); + krb5_error_code (KRB5_CALLCONV *unlock)(krb5_context, krb5_ccache); + krb5_error_code (KRB5_CALLCONV *switch_to)(krb5_context, krb5_ccache); +}; + +extern const krb5_cc_ops *krb5_cc_dfl_ops; + +#endif /* __KRB5_CCACHE_H__ */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/cc_api_macos.c b/krb5-1.21.3/src/lib/krb5/ccache/cc_api_macos.c new file mode 100644 index 00000000..34b1c350 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/cc_api_macos.c @@ -0,0 +1,727 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/cc_api_macos.c - Native MacOS X ccache code */ +/* + * Copyright (C) 2022 United States Government as represented by the + * Secretary of the Navy. + * 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. + */ + +/* + * This ccache module provides compatibility with the default native ccache + * type for macOS, by linking against the native Kerberos framework and calling + * the CCAPI stubs. Due to workarounds for specific behaviors of the CCAPI + * stubs, this implementation is separate from the API ccache implementation + * used on Windows. + */ + +#include "k5-int.h" +#include "cc-int.h" +#include "ccapi_util.h" +#include + +#ifdef USE_CCAPI_MACOS + +#include +#include + +const krb5_cc_ops krb5_api_macos_ops; + +struct api_macos_cache_data { + char *residual; + cc_context_t cc_context; + cc_ccache_t cache; +}; + +struct api_macos_ptcursor { + krb5_boolean first; + char *primary; + cc_context_t cc_context; + cc_ccache_iterator_t iter; +}; + +/* Map a CCAPI error code to a com_err code. */ +static krb5_error_code +ccerr2mit(uint32_t err) +{ + switch (err) { + case ccNoError: + return 0; + case ccIteratorEnd: + return KRB5_CC_END; + case ccErrNoMem: + return ENOMEM; + case ccErrCCacheNotFound: + return KRB5_FCC_NOFILE; + default: + return KRB5_FCC_INTERNAL; + } +} + +/* Construct a ccache handle for residual. Use cc_context if it is not null, + * or initialize a new one if it is. */ +static krb5_error_code +make_cache(const char *residual, cc_context_t cc_context, + krb5_ccache *ccache_out) +{ + krb5_ccache cache = NULL; + char *residual_copy = NULL; + struct api_macos_cache_data *data = NULL; + uint32_t err; + + *ccache_out = NULL; + + if (cc_context == NULL) { + err = cc_initialize(&cc_context, ccapi_version_max, NULL, NULL); + if (err != ccNoError) + return KRB5_FCC_INTERNAL; + } + + cache = malloc(sizeof(*cache)); + if (cache == NULL) + goto oom; + + data = calloc(1, sizeof(*data)); + if (data == NULL) + goto oom; + + residual_copy = strdup(residual); + if (residual_copy == NULL) + goto oom; + + data->residual = residual_copy; + data->cc_context = cc_context; + cache->ops = &krb5_api_macos_ops; + cache->data = data; + cache->magic = KV5M_CCACHE; + *ccache_out = cache; + return 0; + +oom: + free(cache); + free(data); + free(residual_copy); + if (cc_context) + cc_context_release(cc_context); + return ENOMEM; +} + +static uint32_t +open_cache(struct api_macos_cache_data *data) +{ + if (data->cache != NULL) + return ccNoError; + return cc_context_open_ccache(data->cc_context, data->residual, + &data->cache); +} + +static const char * +api_macos_get_name(krb5_context context, krb5_ccache ccache) +{ + struct api_macos_cache_data *data = ccache->data; + + return data->residual; +} + +/* + * We would like to use cc_context_get_default_ccache_name() for this, but that + * doesn't work on macOS if the default cache name is set by the environment or + * configuration. So we have to do what the underlying macOS Heimdal API cache + * type does to fetch the primary name. + * + * For macOS 11 (Darwin 20) and later, implement just enough of the XCACHE + * protocol to fetch the primary UUID. For earlier versions, query the KCM + * daemon. + */ +static krb5_error_code +get_primary_name(krb5_context context, char **name_out) +{ + krb5_error_code ret; + xpc_connection_t conn = NULL; + xpc_object_t request = NULL, reply = NULL; + const uint8_t *uuid; + uint64_t flags = XPC_CONNECTION_MACH_SERVICE_PRIVILEGED; + char uuidstr[37], *end; + struct utsname un; + long release; + + *name_out = NULL; + + if (uname(&un) == 0) { + release = strtol(un.release, &end, 10); + if (end != un.release && release < 20) { + /* Query the KCM daemon for macOS 10 and earlier. */ + ret = k5_kcm_primary_name(context, name_out); + goto cleanup; + } + } + + conn = xpc_connection_create_mach_service("com.apple.GSSCred", NULL, + flags); + if (conn == NULL) { + ret = ENOMEM; + goto cleanup; + } + xpc_connection_set_event_handler(conn, ^(xpc_object_t o){ ; }); + xpc_connection_resume(conn); + + request = xpc_dictionary_create(NULL, NULL, 0); + if (request == NULL) { + ret = ENOMEM; + goto cleanup; + } + xpc_dictionary_set_string(request, "command", "default"); + xpc_dictionary_set_string(request, "mech", "kHEIMTypeKerberos"); + + reply = xpc_connection_send_message_with_reply_sync(conn, request); + if (reply == NULL || xpc_get_type(reply) == XPC_TYPE_ERROR) { + ret = KRB5_CC_IO; + goto cleanup; + } + + uuid = xpc_dictionary_get_uuid(reply, "default"); + if (uuid == NULL) { + ret = KRB5_CC_IO; + goto cleanup; + } + uuid_unparse(uuid, uuidstr); + + *name_out = strdup(uuidstr); + ret = (*name_out == NULL) ? ENOMEM : 0; + +cleanup: + if (request != NULL) + xpc_release(request); + if (reply != NULL) + xpc_release(reply); + if (conn != NULL) + xpc_release(conn); + return ret; +} + +static krb5_error_code +api_macos_resolve(krb5_context context, krb5_ccache *cache_out, + const char *residual) +{ + krb5_error_code ret; + char *primary = NULL; + + if (*residual == '\0') { + ret = get_primary_name(context, &primary); + if (ret) + return ret; + residual = primary; + } + ret = make_cache(residual, NULL, cache_out); + free(primary); + return ret; +} + +static krb5_error_code +api_macos_gen_new(krb5_context context, krb5_ccache *cache_out) +{ + krb5_error_code ret; + uint32_t err; + cc_context_t cc_context = NULL; + cc_ccache_t cc_ccache = NULL; + cc_string_t cachename = NULL; + struct api_macos_cache_data *data; + + *cache_out = NULL; + + err = cc_initialize(&cc_context, ccapi_version_max, NULL, NULL); + if (err) + goto cleanup; + + err = cc_context_create_new_ccache(cc_context, cc_credentials_v5, "", + &cc_ccache); + if (err) + goto cleanup; + + err = cc_ccache_get_name(cc_ccache, &cachename); + if (err) + goto cleanup; + + ret = make_cache(cachename->data, cc_context, cache_out); + cc_context = NULL; + if (!ret) { + data = (*cache_out)->data; + data->cache = cc_ccache; + cc_ccache = NULL; + } + +cleanup: + if (cc_context != NULL) + cc_context_release(cc_context); + if (cc_ccache != NULL) + cc_ccache_release(cc_ccache); + return err ? KRB5_FCC_INTERNAL : 0; +} + +static krb5_error_code +api_macos_initialize(krb5_context context, krb5_ccache cache, + krb5_principal princ) +{ + krb5_error_code ret; + struct api_macos_cache_data *data = cache->data; + uint32_t err; + char *princstr = NULL, *prefix_name = NULL; + + /* Apple's cc_context_create_ccache() requires a name with type prefix. */ + if (asprintf(&prefix_name, "API:%s", data->residual) < 0) + return ENOMEM; + + ret = krb5_unparse_name(context, princ, &princstr); + if (ret) { + free(prefix_name); + return ret; + } + + if (data->cache != NULL) { + cc_ccache_release(data->cache); + data->cache = NULL; + } + + err = cc_context_create_ccache(data->cc_context, prefix_name, + cc_credentials_v5, princstr, + &data->cache); + krb5_free_unparsed_name(context, princstr); + free(prefix_name); + return ccerr2mit(err); +} + +static krb5_error_code +api_macos_close(krb5_context context, krb5_ccache cache) +{ + struct api_macos_cache_data *data = cache->data; + + if (data->cache != NULL) + cc_ccache_release(data->cache); + cc_context_release(data->cc_context); + free(data->residual); + free(data); + free(cache); + return 0; +} + +static krb5_error_code +api_macos_destroy(krb5_context context, krb5_ccache cache) +{ + struct api_macos_cache_data *data = cache->data; + + open_cache(data); + if (data->cache != NULL) { + cc_ccache_destroy(data->cache); + data->cache = NULL; + } + return api_macos_close(context, cache); +} + +static krb5_error_code +api_macos_store(krb5_context context, krb5_ccache cache, krb5_creds *creds) +{ + struct api_macos_cache_data *data = cache->data; + cc_credentials_union *c_un = NULL; + krb5_error_code ret; + uint32_t err; + + err = open_cache(data); + if (err) + return ccerr2mit(err); + + ret = k5_krb5_to_ccapi_creds(context, creds, &c_un); + if (ret) + return ret; + err = cc_ccache_store_credentials(data->cache, c_un); + k5_release_ccapi_cred(c_un); + return ccerr2mit(err); +} + +static krb5_error_code +api_macos_retrieve(krb5_context context, krb5_ccache cache, + krb5_flags whichfields, krb5_creds *mcreds, + krb5_creds *creds) +{ + return k5_cc_retrieve_cred_default(context, cache, whichfields, + mcreds, creds); +} + +static krb5_error_code +api_macos_get_princ(krb5_context context, krb5_ccache cache, + krb5_principal *princ) +{ + struct api_macos_cache_data *data = cache->data; + krb5_error_code ret; + uint32_t err; + cc_string_t outprinc; + + err = open_cache(data); + if (err) + return ccerr2mit(err); + + err = cc_ccache_get_principal(data->cache, cc_credentials_v5, &outprinc); + if (err) + return ccerr2mit(err); + ret = krb5_parse_name(context, outprinc->data, princ); + cc_string_release(outprinc); + return ret; +} + +static krb5_error_code +api_macos_start_seq_get(krb5_context context, krb5_ccache cache, + krb5_cc_cursor *cursor) +{ + struct api_macos_cache_data *data = cache->data; + uint32_t err; + cc_credentials_iterator_t iter; + + err = open_cache(data); + if (err) + return ccerr2mit(err); + + err = cc_ccache_new_credentials_iterator(data->cache, &iter); + if (err) + return ccerr2mit(err); + + *cursor = (krb5_cc_cursor)iter; + return 0; +} + +static krb5_error_code +api_macos_next_cred(krb5_context context, krb5_ccache cache, + krb5_cc_cursor *cursor, krb5_creds *creds) +{ + struct api_macos_cache_data *data = cache->data; + uint32_t err; + krb5_error_code ret; + cc_credentials_iterator_t iter = (cc_credentials_iterator_t) *cursor; + cc_credentials_t acreds; + + err = open_cache(data); + if (err) + return ccerr2mit(err); + + err = cc_credentials_iterator_next(iter, &acreds); + if (!err) { + ret = k5_ccapi_to_krb5_creds(context, acreds->data, creds); + cc_credentials_release(acreds); + } else { + ret = ccerr2mit(err); + } + return ret; +} + +static krb5_error_code +api_macos_end_seq_get(krb5_context context, krb5_ccache cache, + krb5_cc_cursor *cursor) +{ + cc_credentials_iterator_t iter = *cursor; + + cc_credentials_iterator_release(iter); + *cursor = NULL; + return 0; +} + +static krb5_error_code +api_macos_remove_cred(krb5_context context, krb5_ccache cache, + krb5_flags flags, krb5_creds *creds) +{ + struct api_macos_cache_data *data = cache->data; + uint32_t err; + krb5_error_code ret = 0; + cc_credentials_iterator_t iter = NULL; + cc_credentials_t acreds; + krb5_creds mcreds; + krb5_boolean match; + + err = open_cache(data); + if (err) + return ccerr2mit(err); + + err = cc_ccache_new_credentials_iterator(data->cache, &iter); + if (err) + return ccerr2mit(err); + + for (;;) { + err = cc_credentials_iterator_next(iter, &acreds); + if (err) + break; + + ret = k5_ccapi_to_krb5_creds(context, acreds->data, &mcreds); + if (ret) { + cc_credentials_release(acreds); + break; + } + + match = krb5int_cc_creds_match_request(context, flags, creds, &mcreds); + krb5_free_cred_contents(context, &mcreds); + if (match) + err = cc_ccache_remove_credentials(data->cache, acreds); + cc_credentials_release(acreds); + if (err) + break; + } + + cc_credentials_iterator_release(iter); + + if (ret) + return ret; + if (err != ccIteratorEnd) + return ccerr2mit(err); + return 0; +} + +static krb5_error_code +api_macos_set_flags(krb5_context context, krb5_ccache cache, krb5_flags flags) +{ + return 0; +} + +static krb5_error_code +api_macos_get_flags(krb5_context context, krb5_ccache cache, krb5_flags *flags) +{ + *flags = 0; + return 0; +} + +static krb5_error_code +api_macos_ptcursor_new(krb5_context context, krb5_cc_ptcursor *ptcursor_out) +{ + krb5_cc_ptcursor ptcursor = NULL; + struct api_macos_ptcursor *apt = NULL; + + apt = malloc(sizeof(*apt)); + if (apt == NULL) + return ENOMEM; + apt->first = TRUE; + apt->primary = NULL; + apt->cc_context = NULL; + apt->iter = NULL; + + ptcursor = malloc(sizeof(*ptcursor)); + if (ptcursor == NULL) { + free(apt); + return ENOMEM; + } + + ptcursor->ops = &krb5_api_macos_ops; + ptcursor->data = apt; + *ptcursor_out = ptcursor; + return 0; +} + +/* Create a cache object and open it to ensure that it exists in the + * collection. If it does not, return success but set *cache_out to NULL. */ +static krb5_error_code +make_open_cache(const char *residual, krb5_ccache *cache_out) +{ + krb5_error_code ret; + krb5_ccache cache; + uint32_t err; + + *cache_out = NULL; + + ret = make_cache(residual, NULL, &cache); + if (ret) + return ret; + + err = open_cache(cache->data); + if (err) { + api_macos_close(NULL, cache); + return (err == ccErrCCacheNotFound) ? 0 : ccerr2mit(err); + } + + *cache_out = cache; + return 0; +} + +static krb5_error_code +api_macos_ptcursor_next(krb5_context context, krb5_cc_ptcursor ptcursor, + krb5_ccache *cache_out) +{ + krb5_error_code ret; + uint32_t err; + struct api_macos_ptcursor *apt = ptcursor->data; + const char *defname, *defresidual; + cc_ccache_t cache; + cc_string_t residual; + struct api_macos_cache_data *data; + + *cache_out = NULL; + + defname = krb5_cc_default_name(context); + if (defname == NULL || strncmp(defname, "API:", 4) != 0) + return 0; + defresidual = defname + 4; + + /* If the default cache name is a subsidiary cache, yield that cache if it + * exists and stop. */ + if (*defresidual != '\0') { + if (!apt->first) + return 0; + apt->first = FALSE; + return make_open_cache(defresidual, cache_out); + } + + if (apt->first) { + apt->first = FALSE; + + /* Prepare to iterate over the collection. */ + err = cc_initialize(&apt->cc_context, ccapi_version_max, NULL, NULL); + if (err) + return KRB5_FCC_INTERNAL; + err = cc_context_new_ccache_iterator(apt->cc_context, &apt->iter); + if (err) + return KRB5_FCC_INTERNAL; + + /* Yield the primary cache first if it exists. */ + ret = get_primary_name(context, &apt->primary); + if (ret) + return ret; + ret = make_open_cache(apt->primary, cache_out); + if (ret || *cache_out != NULL) + return ret; + } + + for (;;) { + err = cc_ccache_iterator_next(apt->iter, &cache); + if (err) + return (err == ccIteratorEnd) ? 0 : ccerr2mit(err); + + err = cc_ccache_get_name(cache, &residual); + if (err) { + cc_ccache_release(cache); + return ccerr2mit(err); + } + + /* Skip the primary cache since we yielded it first. */ + if (strcmp(residual->data, apt->primary) != 0) + break; + } + + ret = make_cache(residual->data, NULL, cache_out); + cc_string_release(residual); + if (ret) { + cc_ccache_release(cache); + return ret; + } + data = (*cache_out)->data; + data->cache = cache; + return 0; +} + +static krb5_error_code +api_macos_ptcursor_free(krb5_context context, krb5_cc_ptcursor *ptcursor) +{ + struct api_macos_ptcursor *apt = (*ptcursor)->data; + + if (apt != NULL) { + if (apt->iter != NULL) + cc_ccache_iterator_release(apt->iter); + if (apt->cc_context != NULL) + cc_context_release(apt->cc_context); + free(apt->primary); + free(apt); + } + + free(*ptcursor); + *ptcursor = NULL; + + return 0; +} + +static krb5_error_code +api_macos_lock(krb5_context context, krb5_ccache cache) +{ + struct api_macos_cache_data *data = cache->data; + uint32_t err; + + err = open_cache(data); + if (err) + return ccerr2mit(err); + + err = cc_ccache_lock(data->cache, cc_lock_write, cc_lock_block); + return ccerr2mit(err); +} + +static krb5_error_code +api_macos_unlock(krb5_context context, krb5_ccache cache) +{ + struct api_macos_cache_data *data = cache->data; + uint32_t err; + + err = open_cache(data); + if (err) + return ccerr2mit(err); + + err = cc_ccache_unlock(data->cache); + return ccerr2mit(err); +} + +static krb5_error_code +api_macos_switch_to(krb5_context context, krb5_ccache cache) +{ + struct api_macos_cache_data *data = cache->data; + uint32_t err; + + err = open_cache(data); + if (err) + return ccerr2mit(err); + + err = cc_ccache_set_default(data->cache); + return ccerr2mit(err); +} + +const krb5_cc_ops krb5_api_macos_ops = { + 0, + "API", + api_macos_get_name, + api_macos_resolve, + api_macos_gen_new, + api_macos_initialize, + api_macos_destroy, + api_macos_close, + api_macos_store, + api_macos_retrieve, + api_macos_get_princ, + api_macos_start_seq_get, + api_macos_next_cred, + api_macos_end_seq_get, + api_macos_remove_cred, + api_macos_set_flags, + api_macos_get_flags, + api_macos_ptcursor_new, + api_macos_ptcursor_next, + api_macos_ptcursor_free, + NULL, /* move */ + NULL, /* wasdefault */ + api_macos_lock, + api_macos_unlock, + api_macos_switch_to, +}; + +#endif /* TARGET_OS_MAC */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/cc_dir.c b/krb5-1.21.3/src/lib/krb5/ccache/cc_dir.c new file mode 100644 index 00000000..1da40b51 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/cc_dir.c @@ -0,0 +1,771 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/cc_dir.c - Directory-based credential cache collection */ +/* + * Copyright (C) 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This credential cache type represents a set of file-based caches with a + * switchable primary cache. An alternate form of the type represents a + * subsidiary file cache within the directory. + * + * A cache name of the form DIR:dirname identifies a directory containing the + * cache set. Resolving a name of this form results in dirname's primary + * cache. If a context's default cache is of this form, the global cache + * collection will contain dirname's cache set, and new unique caches of type + * DIR will be created within dirname. + * + * A cache name of the form DIR::filepath represents a single cache within the + * directory. Switching to a ccache of this type causes the directory's + * primary cache to be set to the named cache. + * + * Within the directory, cache names begin with 'tkt'. The file "primary" + * contains a single line naming the primary cache. The directory must already + * exist when the DIR ccache is resolved, but the primary file will be created + * automatically if it does not exist. + */ + +#include "k5-int.h" +#include "cc-int.h" + +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif + +/* This is Unix-only for now. To work on Windows, we will need opendir/readdir + * replacements and possibly more flexible newline handling. */ +#ifndef _WIN32 + +#include + +extern const krb5_cc_ops krb5_dcc_ops; +extern const krb5_cc_ops krb5_fcc_ops; + +/* Fields are not modified after creation, so no lock is necessary. */ +typedef struct dcc_data_st { + char *residual; /* dirname or :filename */ + krb5_ccache fcc; /* File cache for actual cache ops */ +} dcc_data; + +static inline krb5_boolean +filename_is_cache(const char *filename) +{ + return (strncmp(filename, "tkt", 3) == 0); +} + +/* Compose the pathname of the primary file within a cache directory. */ +static inline krb5_error_code +primary_pathname(const char *dirname, char **path_out) +{ + return k5_path_join(dirname, "primary", path_out); +} + +/* Compose a residual string for a subsidiary path with the specified directory + * name and filename. */ +static krb5_error_code +subsidiary_residual(const char *dirname, const char *filename, char **out) +{ + krb5_error_code ret; + char *path, *residual; + + *out = NULL; + ret = k5_path_join(dirname, filename, &path); + if (ret) + return ret; + ret = asprintf(&residual, ":%s", path); + free(path); + if (ret < 0) + return ENOMEM; + *out = residual; + return 0; +} + +static inline krb5_error_code +split_path(krb5_context context, const char *path, char **dirname_out, + char **filename_out) +{ + krb5_error_code ret; + char *dirname, *filename; + + *dirname_out = NULL; + *filename_out = NULL; + ret = k5_path_split(path, &dirname, &filename); + if (ret) + return ret; + + if (*dirname == '\0') { + ret = KRB5_CC_BADNAME; + k5_setmsg(context, ret, + _("Subsidiary cache path %s has no parent directory"), path); + goto error; + } + if (!filename_is_cache(filename)) { + ret = KRB5_CC_BADNAME; + k5_setmsg(context, ret, + _("Subsidiary cache path %s filename does not begin with " + "\"tkt\""), path); + goto error; + } + + *dirname_out = dirname; + *filename_out = filename; + return 0; + +error: + free(dirname); + free(filename); + return ret; +} + +/* Read the primary file and compose the residual string for the primary + * subsidiary cache file. */ +static krb5_error_code +read_primary_file(krb5_context context, const char *primary_path, + const char *dirname, char **residual_out) +{ + FILE *fp; + char buf[64], *ret; + size_t len; + + *residual_out = NULL; + + /* Open the file and read its first line. */ + fp = fopen(primary_path, "r"); + if (fp == NULL) + return ENOENT; + ret = fgets(buf, sizeof(buf), fp); + fclose(fp); + if (ret == NULL) + return KRB5_CC_IO; + len = strlen(buf); + + /* Check if line is too long, doesn't look like a subsidiary cache + * filename, or isn't a single-component filename. */ + if (buf[len - 1] != '\n' || !filename_is_cache(buf) || + strchr(buf, '/') || strchr(buf, '\\')) { + k5_setmsg(context, KRB5_CC_FORMAT, _("%s contains invalid filename"), + primary_path); + return KRB5_CC_FORMAT; + } + buf[len - 1] = '\0'; + + return subsidiary_residual(dirname, buf, residual_out); +} + +/* Create or update the primary file with a line containing contents. */ +static krb5_error_code +write_primary_file(const char *primary_path, const char *contents) +{ + krb5_error_code ret = KRB5_CC_IO; + char *newpath = NULL; + FILE *fp = NULL; + int fd = -1, status; + + if (asprintf(&newpath, "%s.XXXXXX", primary_path) < 0) + return ENOMEM; + fd = mkstemp(newpath); + if (fd < 0) + goto cleanup; +#ifdef HAVE_CHMOD + chmod(newpath, S_IRUSR | S_IWUSR); +#endif + fp = fdopen(fd, "w"); + if (fp == NULL) + goto cleanup; + fd = -1; + if (fprintf(fp, "%s\n", contents) < 0) + goto cleanup; + status = fclose(fp); + fp = NULL; + if (status == EOF) + goto cleanup; + fp = NULL; + if (rename(newpath, primary_path) != 0) + goto cleanup; + ret = 0; + +cleanup: + if (fd >= 0) + close(fd); + if (fp != NULL) + fclose(fp); + free(newpath); + return ret; +} + +/* Verify or create a cache directory path. */ +static krb5_error_code +verify_dir(krb5_context context, const char *dirname) +{ + struct stat st; + + if (stat(dirname, &st) < 0) { + if (errno == ENOENT && mkdir(dirname, S_IRWXU) == 0) + return 0; + k5_setmsg(context, KRB5_FCC_NOFILE, + _("Credential cache directory %s does not exist"), + dirname); + return KRB5_FCC_NOFILE; + } + if (!S_ISDIR(st.st_mode)) { + k5_setmsg(context, KRB5_CC_FORMAT, + _("Credential cache directory %s exists but is not a " + "directory"), dirname); + return KRB5_CC_FORMAT; + } + return 0; +} + +/* + * If the default ccache name for context is a directory collection, set + * *dirname_out to the directory name for that collection. Otherwise set + * *dirname_out to NULL. + */ +static krb5_error_code +get_context_default_dir(krb5_context context, char **dirname_out) +{ + const char *defname; + char *dirname; + + *dirname_out = NULL; + defname = krb5_cc_default_name(context); + if (defname == NULL) + return 0; + if (strncmp(defname, "DIR:", 4) != 0 || + defname[4] == ':' || defname[4] == '\0') + return 0; + dirname = strdup(defname + 4); + if (dirname == NULL) + return ENOMEM; + *dirname_out = dirname; + return 0; +} + +/* + * If the default ccache name for context is a subsidiary file in a directory + * collection, set *subsidiary_out to the residual value. Otherwise set + * *subsidiary_out to NULL. + */ +static krb5_error_code +get_context_subsidiary_file(krb5_context context, char **subsidiary_out) +{ + const char *defname; + char *residual; + + *subsidiary_out = NULL; + defname = krb5_cc_default_name(context); + if (defname == NULL || strncmp(defname, "DIR::", 5) != 0) + return 0; + residual = strdup(defname + 4); + if (residual == NULL) + return ENOMEM; + *subsidiary_out = residual; + return 0; +} + +static const char * KRB5_CALLCONV +dcc_get_name(krb5_context context, krb5_ccache cache) +{ + dcc_data *data = cache->data; + + return data->residual; +} + +/* Construct a cache object given a residual string and file ccache. Take + * ownership of fcc on success. */ +static krb5_error_code +make_cache(const char *residual, krb5_ccache fcc, krb5_ccache *cache_out) +{ + krb5_ccache cache = NULL; + dcc_data *data = NULL; + char *residual_copy = NULL; + + cache = malloc(sizeof(*cache)); + if (cache == NULL) + goto oom; + data = malloc(sizeof(*data)); + if (data == NULL) + goto oom; + residual_copy = strdup(residual); + if (residual_copy == NULL) + goto oom; + + data->residual = residual_copy; + data->fcc = fcc; + cache->ops = &krb5_dcc_ops; + cache->data = data; + cache->magic = KV5M_CCACHE; + *cache_out = cache; + return 0; + +oom: + free(cache); + free(data); + free(residual_copy); + return ENOMEM; +} + +static krb5_error_code KRB5_CALLCONV +dcc_resolve(krb5_context context, krb5_ccache *cache_out, const char *residual) +{ + krb5_error_code ret; + krb5_ccache fcc; + char *primary_path = NULL, *sresidual = NULL, *dirname, *filename; + + *cache_out = NULL; + + if (*residual == ':') { + /* This is a subsidiary cache within the directory. */ + ret = split_path(context, residual + 1, &dirname, &filename); + if (ret) + return ret; + + ret = verify_dir(context, dirname); + free(dirname); + free(filename); + if (ret) + return ret; + } else { + /* This is the directory itself; resolve to the primary cache. */ + ret = verify_dir(context, residual); + if (ret) + return ret; + + ret = primary_pathname(residual, &primary_path); + if (ret) + goto cleanup; + + ret = read_primary_file(context, primary_path, residual, &sresidual); + if (ret == ENOENT) { + /* Create an initial primary file. */ + ret = write_primary_file(primary_path, "tkt"); + if (ret) + goto cleanup; + ret = subsidiary_residual(residual, "tkt", &sresidual); + } + if (ret) + goto cleanup; + residual = sresidual; + } + + ret = krb5_fcc_ops.resolve(context, &fcc, residual + 1); + if (ret) + goto cleanup; + ret = make_cache(residual, fcc, cache_out); + if (ret) + krb5_fcc_ops.close(context, fcc); + +cleanup: + free(primary_path); + free(sresidual); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +dcc_gen_new(krb5_context context, krb5_ccache *cache_out) +{ + krb5_error_code ret; + char *dirname = NULL, *template = NULL, *residual = NULL; + krb5_ccache fcc = NULL; + + *cache_out = NULL; + ret = get_context_default_dir(context, &dirname); + if (ret) + return ret; + if (dirname == NULL) { + k5_setmsg(context, KRB5_DCC_CANNOT_CREATE, + _("Can't create new subsidiary cache because default cache " + "is not a directory collection")); + return KRB5_DCC_CANNOT_CREATE; + } + ret = verify_dir(context, dirname); + if (ret) + goto cleanup; + ret = k5_path_join(dirname, "tktXXXXXX", &template); + if (ret) + goto cleanup; + ret = krb5int_fcc_new_unique(context, template, &fcc); + if (ret) + goto cleanup; + if (asprintf(&residual, ":%s", template) < 0) { + ret = ENOMEM; + goto cleanup; + } + ret = make_cache(residual, fcc, cache_out); + if (ret) + goto cleanup; + fcc = NULL; + +cleanup: + if (fcc != NULL) + krb5_fcc_ops.destroy(context, fcc); + free(dirname); + free(template); + free(residual); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +dcc_init(krb5_context context, krb5_ccache cache, krb5_principal princ) +{ + dcc_data *data = cache->data; + + return krb5_fcc_ops.init(context, data->fcc, princ); +} + +static krb5_error_code KRB5_CALLCONV +dcc_destroy(krb5_context context, krb5_ccache cache) +{ + dcc_data *data = cache->data; + krb5_error_code ret; + + ret = krb5_fcc_ops.destroy(context, data->fcc); + free(data->residual); + free(data); + free(cache); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +dcc_close(krb5_context context, krb5_ccache cache) +{ + dcc_data *data = cache->data; + krb5_error_code ret; + + ret = krb5_fcc_ops.close(context, data->fcc); + free(data->residual); + free(data); + free(cache); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +dcc_store(krb5_context context, krb5_ccache cache, krb5_creds *creds) +{ + dcc_data *data = cache->data; + + return krb5_fcc_ops.store(context, data->fcc, creds); +} + +static krb5_error_code KRB5_CALLCONV +dcc_retrieve(krb5_context context, krb5_ccache cache, krb5_flags flags, + krb5_creds *mcreds, krb5_creds *creds) +{ + dcc_data *data = cache->data; + + return krb5_fcc_ops.retrieve(context, data->fcc, flags, mcreds, + creds); +} + +static krb5_error_code KRB5_CALLCONV +dcc_get_princ(krb5_context context, krb5_ccache cache, + krb5_principal *princ_out) +{ + dcc_data *data = cache->data; + + return krb5_fcc_ops.get_princ(context, data->fcc, princ_out); +} + +static krb5_error_code KRB5_CALLCONV +dcc_get_first(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor) +{ + dcc_data *data = cache->data; + + return krb5_fcc_ops.get_first(context, data->fcc, cursor); +} + +static krb5_error_code KRB5_CALLCONV +dcc_get_next(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + dcc_data *data = cache->data; + + return krb5_fcc_ops.get_next(context, data->fcc, cursor, creds); +} + +static krb5_error_code KRB5_CALLCONV +dcc_end_get(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor) +{ + dcc_data *data = cache->data; + + return krb5_fcc_ops.end_get(context, data->fcc, cursor); +} + +static krb5_error_code KRB5_CALLCONV +dcc_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags, + krb5_creds *creds) +{ + dcc_data *data = cache->data; + + return krb5_fcc_ops.remove_cred(context, data->fcc, flags, creds); +} + +static krb5_error_code KRB5_CALLCONV +dcc_set_flags(krb5_context context, krb5_ccache cache, krb5_flags flags) +{ + dcc_data *data = cache->data; + + return krb5_fcc_ops.set_flags(context, data->fcc, flags); +} + +static krb5_error_code KRB5_CALLCONV +dcc_get_flags(krb5_context context, krb5_ccache cache, krb5_flags *flags_out) +{ + dcc_data *data = cache->data; + + return krb5_fcc_ops.get_flags(context, data->fcc, flags_out); +} + +struct dcc_ptcursor_data { + char *primary; + char *dirname; + DIR *dir; + krb5_boolean first; +}; + +/* Construct a cursor, taking ownership of dirname, primary, and dir on + * success. */ +static krb5_error_code +make_cursor(char *dirname, char *primary, DIR *dir, + krb5_cc_ptcursor *cursor_out) +{ + krb5_cc_ptcursor cursor; + struct dcc_ptcursor_data *data; + + *cursor_out = NULL; + + data = malloc(sizeof(*data)); + if (data == NULL) + return ENOMEM; + cursor = malloc(sizeof(*cursor)); + if (cursor == NULL) { + free(data); + return ENOMEM; + } + + data->dirname = dirname; + data->primary = primary; + data->dir = dir; + data->first = TRUE; + cursor->ops = &krb5_dcc_ops; + cursor->data = data; + *cursor_out = cursor; + return 0; +} + +static krb5_error_code KRB5_CALLCONV +dcc_ptcursor_new(krb5_context context, krb5_cc_ptcursor *cursor_out) +{ + krb5_error_code ret; + char *dirname = NULL, *primary_path = NULL, *primary = NULL; + DIR *dir = NULL; + + *cursor_out = NULL; + + /* If the default cache is a subsidiary file, make a cursor with the + * specified file as the primary but with no directory collection. */ + ret = get_context_subsidiary_file(context, &primary); + if (ret) + goto cleanup; + if (primary != NULL) { + ret = make_cursor(NULL, primary, NULL, cursor_out); + if (ret) + free(primary); + return ret; + } + + /* Open the directory for the context's default cache. */ + ret = get_context_default_dir(context, &dirname); + if (ret || dirname == NULL) + goto cleanup; + dir = opendir(dirname); + if (dir == NULL) + goto cleanup; + + /* Fetch the primary cache name if possible. */ + ret = primary_pathname(dirname, &primary_path); + if (ret) + goto cleanup; + ret = read_primary_file(context, primary_path, dirname, &primary); + if (ret) + krb5_clear_error_message(context); + + ret = make_cursor(dirname, primary, dir, cursor_out); + if (ret) + goto cleanup; + dirname = primary = NULL; + dir = NULL; + +cleanup: + free(dirname); + free(primary_path); + free(primary); + if (dir) + closedir(dir); + /* Return an empty cursor if we fail for any reason. */ + if (*cursor_out == NULL) + return make_cursor(NULL, NULL, NULL, cursor_out); + return 0; +} + +static krb5_error_code KRB5_CALLCONV +dcc_ptcursor_next(krb5_context context, krb5_cc_ptcursor cursor, + krb5_ccache *cache_out) +{ + struct dcc_ptcursor_data *data = cursor->data; + struct dirent *ent; + char *residual; + krb5_error_code ret; + struct stat sb; + + *cache_out = NULL; + + /* Return the primary or specified subsidiary cache if we haven't yet. */ + if (data->first) { + data->first = FALSE; + if (data->primary != NULL && stat(data->primary + 1, &sb) == 0) + return dcc_resolve(context, cache_out, data->primary); + } + + if (data->dir == NULL) /* No directory collection */ + return 0; + + /* Look for the next filename of the correct form, without repeating the + * primary cache. */ + while ((ent = readdir(data->dir)) != NULL) { + if (!filename_is_cache(ent->d_name)) + continue; + ret = subsidiary_residual(data->dirname, ent->d_name, &residual); + if (ret) + return ret; + if (data->primary != NULL && strcmp(residual, data->primary) == 0) { + free(residual); + continue; + } + ret = dcc_resolve(context, cache_out, residual); + free(residual); + return ret; + } + + /* We exhausted the directory without finding a cache to yield. */ + closedir(data->dir); + data->dir = NULL; + return 0; +} + +static krb5_error_code KRB5_CALLCONV +dcc_ptcursor_free(krb5_context context, krb5_cc_ptcursor *cursor) +{ + struct dcc_ptcursor_data *data = (*cursor)->data; + + if (data->dir) + closedir(data->dir); + free(data->dirname); + free(data->primary); + free(data); + free(*cursor); + *cursor = NULL; + return 0; +} + +static krb5_error_code KRB5_CALLCONV +dcc_replace(krb5_context context, krb5_ccache cache, krb5_principal princ, + krb5_creds **creds) +{ + dcc_data *data = cache->data; + + return krb5_fcc_ops.replace(context, data->fcc, princ, creds); +} + +static krb5_error_code KRB5_CALLCONV +dcc_lock(krb5_context context, krb5_ccache cache) +{ + dcc_data *data = cache->data; + + return krb5_fcc_ops.lock(context, data->fcc); +} + +static krb5_error_code KRB5_CALLCONV +dcc_unlock(krb5_context context, krb5_ccache cache) +{ + dcc_data *data = cache->data; + + return krb5_fcc_ops.unlock(context, data->fcc); +} + +static krb5_error_code KRB5_CALLCONV +dcc_switch_to(krb5_context context, krb5_ccache cache) +{ + dcc_data *data = cache->data; + char *primary_path = NULL, *dirname = NULL, *filename = NULL; + krb5_error_code ret; + + ret = split_path(context, data->residual + 1, &dirname, &filename); + if (ret) + return ret; + + ret = primary_pathname(dirname, &primary_path); + if (ret) + goto cleanup; + + ret = write_primary_file(primary_path, filename); + +cleanup: + free(primary_path); + free(dirname); + free(filename); + return ret; +} + +const krb5_cc_ops krb5_dcc_ops = { + 0, + "DIR", + dcc_get_name, + dcc_resolve, + dcc_gen_new, + dcc_init, + dcc_destroy, + dcc_close, + dcc_store, + dcc_retrieve, + dcc_get_princ, + dcc_get_first, + dcc_get_next, + dcc_end_get, + dcc_remove_cred, + dcc_set_flags, + dcc_get_flags, + dcc_ptcursor_new, + dcc_ptcursor_next, + dcc_ptcursor_free, + dcc_replace, + NULL, /* wasdefault */ + dcc_lock, + dcc_unlock, + dcc_switch_to, +}; + +#endif /* not _WIN32 */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/cc_file.c b/krb5-1.21.3/src/lib/krb5/ccache/cc_file.c new file mode 100644 index 00000000..c70a2827 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/cc_file.c @@ -0,0 +1,1479 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/cc_file.c - File-based credential cache */ +/* + * Copyright 1990,1991,1992,1993,1994,2000,2004,2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Original stdio support copyright 1995 by Cygnus Support. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * A psuedo-BNF grammar for the FILE credential cache format is: + * + * file ::= + * version (2 bytes; 05 01 for version 1 through 05 04 for version 4) + * header [not present before version 4] + * principal + * credential1 + * credential2 + * ... + * + * header ::= + * headerlen (16 bits) + * header1tag (16 bits) + * header1len (16 bits) + * header1val (header1len bytes) + * + * See ccmarshal.c for the principal and credential formats. Although versions + * 1 and 2 of the FILE format use native byte order for integer representations + * within principals and credentials, the integer fields in the grammar above + * are always in big-endian byte order. + * + * Only one header tag is currently defined. The tag value is 1 + * (FCC_TAG_DELTATIME), and its contents are two 32-bit integers giving the + * seconds and microseconds of the time offset of the KDC relative to the + * client. + * + * Each of the file ccache functions opens and closes the file whenever it + * needs to access it. + * + * This module depends on UNIX-like file descriptors, and UNIX-like behavior + * from the functions: open, close, read, write, lseek. + */ + +#include "k5-int.h" +#include "cc-int.h" + +#include +#include + +#if HAVE_UNISTD_H +#include +#endif + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +extern const krb5_cc_ops krb5_cc_file_ops; + +krb5_error_code krb5_change_cache(void); + +static krb5_error_code interpret_errno(krb5_context, int); + +/* The cache format version is a positive integer, represented in the cache + * file as a two-byte big endian number with 0x0500 added to it. */ +#define FVNO_BASE 0x0500 + +#define FCC_TAG_DELTATIME 1 + +#ifndef TKT_ROOT +#ifdef MSDOS_FILESYSTEM +#define TKT_ROOT "\\tkt" +#else +#define TKT_ROOT "/tmp/tkt" +#endif +#endif + +typedef struct fcc_data_st { + k5_cc_mutex lock; + char *filename; +} fcc_data; + +/* Iterator over file caches. */ +struct krb5_fcc_ptcursor_data { + krb5_boolean first; +}; + +/* Iterator over a cache. */ +typedef struct _krb5_fcc_cursor { + FILE *fp; + int version; +} krb5_fcc_cursor; + +k5_cc_mutex krb5int_cc_file_mutex = K5_CC_MUTEX_PARTIAL_INITIALIZER; + +/* Add fname to the standard error message for ret. */ +static krb5_error_code +set_errmsg_filename(krb5_context context, krb5_error_code ret, + const char *fname) +{ + if (!ret) + return 0; + k5_setmsg(context, ret, "%s (filename: %s)", error_message(ret), fname); + return ret; +} + +/* Get the size of the cache file as a size_t, or SIZE_MAX if it is too + * large to be represented as a size_t. */ +static krb5_error_code +get_size(krb5_context context, FILE *fp, size_t *size_out) +{ + struct stat sb; + + *size_out = 0; + if (fstat(fileno(fp), &sb) == -1) + return interpret_errno(context, errno); + if (sizeof(off_t) > sizeof(size_t) && sb.st_size > (off_t)SIZE_MAX) + *size_out = SIZE_MAX; + else + *size_out = sb.st_size; + return 0; +} + +/* Read len bytes from fp, storing them in buf. Return KRB5_CC_END + * if not enough bytes are present. */ +static krb5_error_code +read_bytes(krb5_context context, FILE *fp, void *buf, size_t len) +{ + size_t nread; + + nread = fread(buf, 1, len, fp); + if (nread < len) + return ferror(fp) ? errno : KRB5_CC_END; + return 0; +} + +/* Load four bytes from the cache file. Add them to buf (if set) and return + * their value as a 32-bit unsigned integer according to the file format. */ +static krb5_error_code +read32(krb5_context context, FILE *fp, int version, struct k5buf *buf, + uint32_t *out) +{ + krb5_error_code ret; + char bytes[4]; + + ret = read_bytes(context, fp, bytes, 4); + if (ret) + return ret; + if (buf != NULL) + k5_buf_add_len(buf, bytes, 4); + *out = (version < 3) ? load_32_n(bytes) : load_32_be(bytes); + return 0; +} + +/* Load two bytes from the cache file and return their value as a 16-bit + * unsigned integer according to the file format. */ +static krb5_error_code +read16(krb5_context context, FILE *fp, int version, uint16_t *out) +{ + krb5_error_code ret; + char bytes[2]; + + ret = read_bytes(context, fp, bytes, 2); + if (ret) + return ret; + *out = (version < 3) ? load_16_n(bytes) : load_16_be(bytes); + return 0; +} + +/* Read len bytes from the cache file and add them to buf. */ +static krb5_error_code +load_bytes(krb5_context context, FILE *fp, size_t len, struct k5buf *buf) +{ + void *ptr; + + ptr = k5_buf_get_space(buf, len); + return (ptr == NULL) ? KRB5_CC_NOMEM : read_bytes(context, fp, ptr, len); +} + +/* Load a 32-bit length and data from the cache file into buf, but not more + * than maxsize bytes. */ +static krb5_error_code +load_data(krb5_context context, FILE *fp, int version, size_t maxsize, + struct k5buf *buf) +{ + krb5_error_code ret; + uint32_t count; + + ret = read32(context, fp, version, buf, &count); + if (ret) + return ret; + if (count > maxsize) + return KRB5_CC_FORMAT; + return load_bytes(context, fp, count, buf); +} + +/* Load a marshalled principal from the cache file into buf, without + * unmarshalling it. */ +static krb5_error_code +load_principal(krb5_context context, FILE *fp, int version, size_t maxsize, + struct k5buf *buf) +{ + krb5_error_code ret; + uint32_t count; + + if (version > 1) { + ret = load_bytes(context, fp, 4, buf); + if (ret) + return ret; + } + ret = read32(context, fp, version, buf, &count); + if (ret) + return ret; + /* Add one for the realm (except in version 1 which already counts it). */ + if (version != 1) + count++; + while (count-- > 0) { + ret = load_data(context, fp, version, maxsize, buf); + if (ret) + return ret; + } + return 0; +} + +/* Load a marshalled credential from the cache file into buf, without + * unmarshalling it. */ +static krb5_error_code +load_cred(krb5_context context, FILE *fp, int version, size_t maxsize, + struct k5buf *buf) +{ + krb5_error_code ret; + uint32_t count, i; + + /* client and server */ + ret = load_principal(context, fp, version, maxsize, buf); + if (ret) + return ret; + ret = load_principal(context, fp, version, maxsize, buf); + if (ret) + return ret; + + /* keyblock (enctype, enctype again for version 3, length, value) */ + ret = load_bytes(context, fp, (version == 3) ? 4 : 2, buf); + if (ret) + return ret; + ret = load_data(context, fp, version, maxsize, buf); + if (ret) + return ret; + + /* times (4*4 bytes), is_skey (1 byte), ticket flags (4 bytes) */ + ret = load_bytes(context, fp, 4 * 4 + 1 + 4, buf); + if (ret) + return ret; + + /* addresses and authdata, both lists of {type, length, data} */ + for (i = 0; i < 2; i++) { + ret = read32(context, fp, version, buf, &count); + if (ret) + return ret; + while (count-- > 0) { + ret = load_bytes(context, fp, 2, buf); + if (ret) + return ret; + ret = load_data(context, fp, version, maxsize, buf); + if (ret) + return ret; + } + } + + /* ticket and second_ticket */ + ret = load_data(context, fp, version, maxsize, buf); + if (ret) + return ret; + return load_data(context, fp, version, maxsize, buf); +} + +static krb5_error_code +read_principal(krb5_context context, FILE *fp, int version, + krb5_principal *princ) +{ + krb5_error_code ret; + struct k5buf buf; + size_t maxsize; + + *princ = NULL; + k5_buf_init_dynamic(&buf); + + /* Read the principal representation into memory. */ + ret = get_size(context, fp, &maxsize); + if (ret) + goto cleanup; + ret = load_principal(context, fp, version, maxsize, &buf); + if (ret) + goto cleanup; + ret = k5_buf_status(&buf); + if (ret) + goto cleanup; + + /* Unmarshal it from buf into princ. */ + ret = k5_unmarshal_princ(buf.data, buf.len, version, princ); + +cleanup: + k5_buf_free(&buf); + return ret; +} + +/* + * Open and lock an existing cache file. If writable is true, open it for + * writing (with O_APPEND) and get an exclusive lock; otherwise open it for + * reading and get a shared lock. + */ +static krb5_error_code +open_cache_file(krb5_context context, const char *filename, + krb5_boolean writable, FILE **fp_out) +{ + krb5_error_code ret; + int fd, flags, lockmode; + FILE *fp; + + *fp_out = NULL; + + flags = writable ? (O_RDWR | O_APPEND) : O_RDONLY; + fd = open(filename, flags | O_BINARY | O_CLOEXEC, 0600); + if (fd == -1) + return interpret_errno(context, errno); + set_cloexec_fd(fd); + + lockmode = writable ? KRB5_LOCKMODE_EXCLUSIVE : KRB5_LOCKMODE_SHARED; + ret = krb5_lock_file(context, fd, lockmode); + if (ret) { + (void)close(fd); + return ret; + } + + fp = fdopen(fd, writable ? "r+b" : "rb"); + if (fp == NULL) { + (void)krb5_unlock_file(context, fd); + (void)close(fd); + return KRB5_CC_NOMEM; + } + + *fp_out = fp; + return 0; +} + +/* Unlock and close the cache file. Do nothing if fp is NULL. */ +static krb5_error_code +close_cache_file(krb5_context context, FILE *fp) +{ + int st; + krb5_error_code ret; + + if (fp == NULL) + return 0; + ret = krb5_unlock_file(context, fileno(fp)); + st = fclose(fp); + if (ret) + return ret; + return st ? interpret_errno(context, errno) : 0; +} + +/* Read the cache file header. Set time offsets in context from the header if + * appropriate. Set *version_out to the cache file format version. */ +static krb5_error_code +read_header(krb5_context context, FILE *fp, int *version_out) +{ + krb5_error_code ret; + krb5_os_context os_ctx = &context->os_context; + uint16_t fields_len, tag, flen; + uint32_t time_offset, usec_offset; + char i16buf[2]; + int version; + + *version_out = 0; + + /* Get the file format version. */ + ret = read_bytes(context, fp, i16buf, 2); + if (ret) + return KRB5_CC_FORMAT; + version = load_16_be(i16buf) - FVNO_BASE; + if (version < 1 || version > 4) + return KRB5_CCACHE_BADVNO; + *version_out = version; + + /* Tagged header fields begin with version 4. */ + if (version < 4) + return 0; + + if (read16(context, fp, version, &fields_len)) + return KRB5_CC_FORMAT; + while (fields_len) { + if (fields_len < 4 || read16(context, fp, version, &tag) || + read16(context, fp, version, &flen) || flen > fields_len - 4) + return KRB5_CC_FORMAT; + + switch (tag) { + case FCC_TAG_DELTATIME: + if (flen != 8 || + read32(context, fp, version, NULL, &time_offset) || + read32(context, fp, version, NULL, &usec_offset)) + return KRB5_CC_FORMAT; + + if (!(context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) || + (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID)) + break; + + os_ctx->time_offset = time_offset; + os_ctx->usec_offset = usec_offset; + os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) | + KRB5_OS_TOFFSET_VALID); + break; + + default: + if (flen && fseek(fp, flen, SEEK_CUR) != 0) + return KRB5_CC_FORMAT; + break; + } + fields_len -= (4 + flen); + } + return 0; +} + +static void +marshal_header(krb5_context context, struct k5buf *buf, krb5_principal princ) +{ + krb5_os_context os_ctx = &context->os_context; + int version = context->fcc_default_format - FVNO_BASE; + uint16_t fields_len; + + version = context->fcc_default_format - FVNO_BASE; + k5_buf_add_uint16_be(buf, FVNO_BASE + version); + if (version >= 4) { + /* Add tagged header fields. */ + fields_len = 0; + if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) + fields_len += 12; + k5_buf_add_uint16_be(buf, fields_len); + if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) { + /* Add time offset tag. */ + k5_buf_add_uint16_be(buf, FCC_TAG_DELTATIME); + k5_buf_add_uint16_be(buf, 8); + k5_buf_add_uint32_be(buf, os_ctx->time_offset); + k5_buf_add_uint32_be(buf, os_ctx->usec_offset); + } + } + k5_marshal_princ(buf, version, princ); +} + +/* Create or overwrite the cache file with a header and default principal. */ +static krb5_error_code KRB5_CALLCONV +fcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ) +{ + krb5_error_code ret; + fcc_data *data = id->data; + ssize_t nwritten; + int st, flags, fd = -1; + struct k5buf buf = EMPTY_K5BUF; + krb5_boolean file_locked = FALSE; + + k5_cc_mutex_lock(context, &data->lock); + + unlink(data->filename); + flags = O_CREAT | O_EXCL | O_RDWR | O_BINARY | O_CLOEXEC; + fd = open(data->filename, flags, 0600); + if (fd == -1) { + ret = interpret_errno(context, errno); + goto cleanup; + } + set_cloexec_fd(fd); + +#if defined(HAVE_FCHMOD) || defined(HAVE_CHMOD) +#ifdef HAVE_FCHMOD + st = fchmod(fd, S_IRUSR | S_IWUSR); +#else + st = chmod(data->filename, S_IRUSR | S_IWUSR); +#endif + if (st == -1) { + ret = interpret_errno(context, errno); + goto cleanup; + } +#endif + + ret = krb5_lock_file(context, fd, KRB5_LOCKMODE_EXCLUSIVE); + if (ret) + goto cleanup; + file_locked = TRUE; + + /* Prepare the header and principal in buf. */ + k5_buf_init_dynamic(&buf); + marshal_header(context, &buf, princ); + ret = k5_buf_status(&buf); + if (ret) + goto cleanup; + + /* Write the header and principal. */ + nwritten = write(fd, buf.data, buf.len); + if (nwritten == -1) + ret = interpret_errno(context, errno); + if ((size_t)nwritten != buf.len) + ret = KRB5_CC_IO; + +cleanup: + k5_buf_free(&buf); + if (file_locked) + krb5_unlock_file(context, fd); + if (fd != -1) + close(fd); + k5_cc_mutex_unlock(context, &data->lock); + krb5_change_cache(); + return set_errmsg_filename(context, ret, data->filename); +} + +/* Release an fcc_data object. */ +static void +free_fccdata(krb5_context context, fcc_data *data) +{ + k5_cc_mutex_assert_unlocked(context, &data->lock); + free(data->filename); + k5_cc_mutex_destroy(&data->lock); + free(data); +} + +/* Release the ccache handle. */ +static krb5_error_code KRB5_CALLCONV +fcc_close(krb5_context context, krb5_ccache id) +{ + free_fccdata(context, id->data); + free(id); + return 0; +} + +/* Destroy the cache file and release the handle. */ +static krb5_error_code KRB5_CALLCONV +fcc_destroy(krb5_context context, krb5_ccache id) +{ + krb5_error_code ret = 0; + fcc_data *data = id->data; + int st, fd; + struct stat buf; + unsigned long i, size; + unsigned int wlen; + char zeros[BUFSIZ]; + + k5_cc_mutex_lock(context, &data->lock); + + fd = open(data->filename, O_RDWR | O_BINARY | O_CLOEXEC, 0); + if (fd < 0) { + ret = interpret_errno(context, errno); + goto cleanup; + } + set_cloexec_fd(fd); + +#ifdef MSDOS_FILESYSTEM + /* + * "Disgusting bit of UNIX trivia" - that's how the writers of NFS describe + * the ability of UNIX to still write to a file which has been unlinked. + * Naturally, the PC can't do this. As a result, we have to delete the + * file after we wipe it clean, but that throws off all the error handling + * code. So we have do the work ourselves. + */ + st = fstat(fd, &buf); + if (st == -1) { + ret = interpret_errno(context, errno); + size = 0; /* Nothing to wipe clean */ + } else { + size = (unsigned long)buf.st_size; + } + + memset(zeros, 0, BUFSIZ); + while (size > 0) { + wlen = (int)((size > BUFSIZ) ? BUFSIZ : size); /* How much to write */ + i = write(fd, zeros, wlen); + if (i < 0) { + ret = interpret_errno(context, errno); + /* Don't jump to cleanup--we still want to delete the file. */ + break; + } + size -= i; + } + + (void)close(fd); + + st = unlink(data->filename); + if (st < 0) { + ret = interpret_errno(context, errno); + goto cleanup; + } + +#else /* MSDOS_FILESYSTEM */ + + st = unlink(data->filename); + if (st < 0) { + ret = interpret_errno(context, errno); + (void)close(fd); + goto cleanup; + } + + st = fstat(fd, &buf); + if (st < 0) { + ret = interpret_errno(context, errno); + (void)close(fd); + goto cleanup; + } + + /* XXX This may not be legal XXX */ + size = (unsigned long)buf.st_size; + memset(zeros, 0, BUFSIZ); + for (i = 0; i < size / BUFSIZ; i++) { + if (write(fd, zeros, BUFSIZ) < 0) { + ret = interpret_errno(context, errno); + (void)close(fd); + goto cleanup; + } + } + + wlen = size % BUFSIZ; + if (write(fd, zeros, wlen) < 0) { + ret = interpret_errno(context, errno); + (void)close(fd); + goto cleanup; + } + + st = close(fd); + + if (st) + ret = interpret_errno(context, errno); + +#endif /* MSDOS_FILESYSTEM */ + +cleanup: + (void)set_errmsg_filename(context, ret, data->filename); + k5_cc_mutex_unlock(context, &data->lock); + free_fccdata(context, data); + free(id); + + krb5_change_cache(); + return ret; +} + +extern const krb5_cc_ops krb5_fcc_ops; + +/* Create a file ccache handle for the pathname given by residual. */ +static krb5_error_code KRB5_CALLCONV +fcc_resolve(krb5_context context, krb5_ccache *id, const char *residual) +{ + krb5_ccache lid; + krb5_error_code ret; + fcc_data *data; + + data = malloc(sizeof(fcc_data)); + if (data == NULL) + return KRB5_CC_NOMEM; + data->filename = strdup(residual); + if (data->filename == NULL) { + free(data); + return KRB5_CC_NOMEM; + } + ret = k5_cc_mutex_init(&data->lock); + if (ret) { + free(data->filename); + free(data); + return ret; + } + + lid = malloc(sizeof(struct _krb5_ccache)); + if (lid == NULL) { + free_fccdata(context, data); + return KRB5_CC_NOMEM; + } + + lid->ops = &krb5_fcc_ops; + lid->data = data; + lid->magic = KV5M_CCACHE; + + /* Other routines will get errors on open, and callers must expect them, if + * cache is non-existent/unusable. */ + *id = lid; + return 0; +} + +/* Prepare for a sequential iteration over the cache file. */ +static krb5_error_code KRB5_CALLCONV +fcc_start_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor) +{ + krb5_fcc_cursor *fcursor = NULL; + krb5_error_code ret; + krb5_principal princ = NULL; + fcc_data *data = id->data; + FILE *fp = NULL; + int version; + + k5_cc_mutex_lock(context, &data->lock); + + fcursor = malloc(sizeof(krb5_fcc_cursor)); + if (fcursor == NULL) { + ret = KRB5_CC_NOMEM; + goto cleanup; + } + + /* Open the cache file and read the header. */ + ret = open_cache_file(context, data->filename, FALSE, &fp); + if (ret) + goto cleanup; + ret = read_header(context, fp, &version); + if (ret) + goto cleanup; + + /* Read past the default client principal name. */ + ret = read_principal(context, fp, version, &princ); + if (ret) + goto cleanup; + + /* Drop the shared file lock but retain the file handle. */ + (void)krb5_unlock_file(context, fileno(fp)); + fcursor->fp = fp; + fp = NULL; + fcursor->version = version; + *cursor = (krb5_cc_cursor)fcursor; + fcursor = NULL; + +cleanup: + (void)close_cache_file(context, fp); + free(fcursor); + krb5_free_principal(context, princ); + k5_cc_mutex_unlock(context, &data->lock); + return set_errmsg_filename(context, ret, data->filename); +} + +/* Return true if cred is a removed entry (assuming that no legitimate cred + * entries will have authtime=-1 and endtime=0). */ +static inline krb5_boolean +cred_removed(krb5_creds *c) +{ + return c->times.endtime == 0 && c->times.authtime == -1; +} + +/* Get the next credential from the cache file. */ +static krb5_error_code KRB5_CALLCONV +fcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + krb5_error_code ret; + krb5_fcc_cursor *fcursor = *cursor; + fcc_data *data = id->data; + struct k5buf buf; + size_t maxsize; + krb5_boolean file_locked = FALSE; + + memset(creds, 0, sizeof(*creds)); + k5_cc_mutex_lock(context, &data->lock); + k5_buf_init_dynamic_zap(&buf); + + ret = krb5_lock_file(context, fileno(fcursor->fp), KRB5_LOCKMODE_SHARED); + if (ret) + goto cleanup; + file_locked = TRUE; + + for (;;) { + /* Load a marshalled cred into memory. */ + ret = get_size(context, fcursor->fp, &maxsize); + if (ret) + goto cleanup; + ret = load_cred(context, fcursor->fp, fcursor->version, maxsize, &buf); + if (ret) + goto cleanup; + ret = k5_buf_status(&buf); + if (ret) + goto cleanup; + + /* Unmarshal it from buf into creds. */ + ret = k5_unmarshal_cred(buf.data, buf.len, fcursor->version, creds); + if (ret) + goto cleanup; + + /* Keep going if this entry has been removed; otherwise stop. */ + if (!cred_removed(creds)) + break; + + k5_buf_truncate(&buf, 0); + krb5_free_cred_contents(context, creds); + } + +cleanup: + if (file_locked) + (void)krb5_unlock_file(context, fileno(fcursor->fp)); + k5_cc_mutex_unlock(context, &data->lock); + k5_buf_free(&buf); + return set_errmsg_filename(context, ret, data->filename); +} + +/* Release an iteration cursor. */ +static krb5_error_code KRB5_CALLCONV +fcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor) +{ + krb5_fcc_cursor *fcursor = *cursor; + + (void)fclose(fcursor->fp); + free(fcursor); + *cursor = NULL; + return 0; +} + +/* Generate a unique file ccache using the given template (which will be + * modified to contain the actual name of the file). */ +krb5_error_code +krb5int_fcc_new_unique(krb5_context context, char *template, krb5_ccache *id) +{ + krb5_ccache lid; + int fd; + krb5_error_code ret; + fcc_data *data; + char fcc_fvno[2]; + int16_t fcc_flen = 0; + int errsave, cnt; + + fd = mkstemp(template); + if (fd == -1) + return interpret_errno(context, errno); + set_cloexec_fd(fd); + + /* Allocate memory */ + data = malloc(sizeof(fcc_data)); + if (data == NULL) { + close(fd); + unlink(template); + return KRB5_CC_NOMEM; + } + + data->filename = strdup(template); + if (data->filename == NULL) { + free(data); + close(fd); + unlink(template); + return KRB5_CC_NOMEM; + } + + ret = k5_cc_mutex_init(&data->lock); + if (ret) { + free(data->filename); + free(data); + close(fd); + unlink(template); + return ret; + } + k5_cc_mutex_lock(context, &data->lock); + + /* Ignore user's umask, set mode = 0600 */ +#ifndef HAVE_FCHMOD +#ifdef HAVE_CHMOD + chmod(data->filename, S_IRUSR | S_IWUSR); +#endif +#else + fchmod(fd, S_IRUSR | S_IWUSR); +#endif + store_16_be(context->fcc_default_format, fcc_fvno); + cnt = write(fd, &fcc_fvno, 2); + if (cnt != 2) { + errsave = errno; + (void)close(fd); + (void)unlink(data->filename); + ret = (cnt == -1) ? interpret_errno(context, errsave) : KRB5_CC_IO; + goto err_out; + } + /* For version 4 we save a length for the rest of the header */ + if (context->fcc_default_format == FVNO_BASE + 4) { + cnt = write(fd, &fcc_flen, sizeof(fcc_flen)); + if (cnt != sizeof(fcc_flen)) { + errsave = errno; + (void)close(fd); + (void)unlink(data->filename); + ret = (cnt == -1) ? interpret_errno(context, errsave) : KRB5_CC_IO; + goto err_out; + } + } + if (close(fd) == -1) { + errsave = errno; + (void)unlink(data->filename); + ret = interpret_errno(context, errsave); + goto err_out; + } + + k5_cc_mutex_assert_locked(context, &data->lock); + k5_cc_mutex_unlock(context, &data->lock); + lid = malloc(sizeof(*lid)); + if (lid == NULL) { + free_fccdata(context, data); + return KRB5_CC_NOMEM; + } + + lid->ops = &krb5_fcc_ops; + lid->data = data; + lid->magic = KV5M_CCACHE; + + *id = lid; + + krb5_change_cache(); + return 0; + +err_out: + (void)set_errmsg_filename(context, ret, data->filename); + k5_cc_mutex_unlock(context, &data->lock); + k5_cc_mutex_destroy(&data->lock); + free(data->filename); + free(data); + return ret; +} + +/* + * Create a new file cred cache whose name is guaranteed to be unique. The + * name begins with the string TKT_ROOT (from fcc.h). The cache file is not + * opened, but the new filename is reserved. + */ +static krb5_error_code KRB5_CALLCONV +fcc_generate_new(krb5_context context, krb5_ccache *id) +{ + char scratch[sizeof(TKT_ROOT) + 7]; /* Room for XXXXXX and terminator */ + + (void)snprintf(scratch, sizeof(scratch), "%sXXXXXX", TKT_ROOT); + return krb5int_fcc_new_unique(context, scratch, id); +} + +/* Return an alias to the pathname of the cache file. */ +static const char * KRB5_CALLCONV +fcc_get_name(krb5_context context, krb5_ccache id) +{ + return ((fcc_data *)id->data)->filename; +} + +/* Retrieve a copy of the default principal, if the cache is initialized. */ +static krb5_error_code KRB5_CALLCONV +fcc_get_principal(krb5_context context, krb5_ccache id, krb5_principal *princ) +{ + krb5_error_code ret; + fcc_data *data = id->data; + FILE *fp = NULL; + int version; + + k5_cc_mutex_lock(context, &data->lock); + ret = open_cache_file(context, data->filename, FALSE, &fp); + if (ret) + goto cleanup; + ret = read_header(context, fp, &version); + if (ret) + goto cleanup; + ret = read_principal(context, fp, version, princ); + +cleanup: + (void)close_cache_file(context, fp); + k5_cc_mutex_unlock(context, &data->lock); + return set_errmsg_filename(context, ret, data->filename); +} + +/* Search for a credential within the cache file. */ +static krb5_error_code KRB5_CALLCONV +fcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields, + krb5_creds *mcreds, krb5_creds *creds) +{ + krb5_error_code ret; + + ret = k5_cc_retrieve_cred_default(context, id, whichfields, mcreds, creds); + return set_errmsg_filename(context, ret, ((fcc_data *)id->data)->filename); +} + +/* Store a credential in the cache file. */ +static krb5_error_code KRB5_CALLCONV +fcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds) +{ + krb5_error_code ret, ret2; + fcc_data *data = id->data; + FILE *fp = NULL; + int version; + struct k5buf buf = EMPTY_K5BUF; + ssize_t nwritten; + + k5_cc_mutex_lock(context, &data->lock); + + /* Open the cache file for O_APPEND writing. */ + ret = open_cache_file(context, data->filename, TRUE, &fp); + if (ret) + goto cleanup; + ret = read_header(context, fp, &version); + if (ret) + goto cleanup; + + /* Marshal the cred and write it to the file with a single append write. */ + k5_buf_init_dynamic_zap(&buf); + k5_marshal_cred(&buf, version, creds); + ret = k5_buf_status(&buf); + if (ret) + goto cleanup; + nwritten = write(fileno(fp), buf.data, buf.len); + if (nwritten == -1) + ret = interpret_errno(context, errno); + if ((size_t)nwritten != buf.len) + ret = KRB5_CC_IO; + + krb5_change_cache(); + +cleanup: + k5_buf_free(&buf); + ret2 = close_cache_file(context, fp); + k5_cc_mutex_unlock(context, &data->lock); + return set_errmsg_filename(context, ret ? ret : ret2, data->filename); +} + +/* + * Overwrite cred in the ccache file with an entry that should not match any + * reasonable search. Deletion is not guaranteed. This method is originally + * from Heimdal, with the addition of setting authtime to -1. + */ +static krb5_error_code +delete_cred(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor, + krb5_creds *cred) +{ + krb5_error_code ret; + krb5_fcc_cursor *fcursor = *cursor; + fcc_data *data = cache->data; + struct k5buf expected = EMPTY_K5BUF, overwrite = EMPTY_K5BUF; + int fd = -1; + uint8_t *on_disk = NULL; + ssize_t rwret; + off_t start_offset; + + k5_buf_init_dynamic_zap(&expected); + k5_buf_init_dynamic_zap(&overwrite); + + /* Re-marshal cred to get its byte representation in the file. */ + k5_marshal_cred(&expected, fcursor->version, cred); + ret = k5_buf_status(&expected); + if (ret) + goto cleanup; + + /* + * Mark the cred expired so that it will be skipped over by any future + * match checks. Heimdal only sets endtime, but we also set authtime to + * distinguish from gssproxy's creds. + */ + cred->times.endtime = 0; + cred->times.authtime = -1; + + /* For config entries, also change the realm so that other implementations + * won't match them. */ + if (data_eq_string(cred->server->realm, "X-CACHECONF:")) + memcpy(cred->server->realm.data, "X-RMED-CONF:", 12); + + k5_marshal_cred(&overwrite, fcursor->version, cred); + ret = k5_buf_status(&overwrite); + if (ret) + goto cleanup; + + if (expected.len != overwrite.len) { + ret = KRB5_CC_FORMAT; + goto cleanup; + } + + /* Get a non-O_APPEND handle to the raw file. */ + fd = open(data->filename, O_RDWR | O_BINARY | O_CLOEXEC); + if (fd == -1) { + ret = interpret_errno(context, errno); + goto cleanup; + } + + start_offset = ftell(fcursor->fp); + if (start_offset == -1) { + ret = interpret_errno(context, errno); + goto cleanup; + } + start_offset -= expected.len; + + /* Read the bytes at the entry to be overwritten. */ + if (lseek(fd, start_offset, SEEK_SET) == -1) { + ret = interpret_errno(context, errno); + goto cleanup; + } + on_disk = k5alloc(expected.len, &ret); + if (ret != 0) + goto cleanup; + rwret = read(fd, on_disk, expected.len); + if (rwret < 0) { + ret = interpret_errno(context, errno); + goto cleanup; + } else if ((size_t)rwret != expected.len) { + ret = KRB5_CC_FORMAT; + goto cleanup; + } + + /* + * If the bytes have changed, either someone else removed the same cred or + * the cache was reinitialized. Either way the cred is no longer present, + * so return successfully. + */ + if (memcmp(on_disk, expected.data, expected.len) != 0) + goto cleanup; + + /* Write out the altered entry. */ + if (lseek(fd, start_offset, SEEK_SET) == -1) { + ret = interpret_errno(context, errno); + goto cleanup; + } + rwret = write(fd, overwrite.data, overwrite.len); + if (rwret < 0) { + ret = interpret_errno(context, errno); + goto cleanup; + } + +cleanup: + if (fd >= 0) + close(fd); + zapfree(on_disk, expected.len); + k5_buf_free(&expected); + k5_buf_free(&overwrite); + return ret; +} + +/* Remove the given creds from the ccache file. */ +static krb5_error_code KRB5_CALLCONV +fcc_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags, + krb5_creds *creds) +{ + krb5_error_code ret; + krb5_cc_cursor cursor; + krb5_creds cur; + + ret = krb5_cc_start_seq_get(context, cache, &cursor); + if (ret) + return ret; + + for (;;) { + ret = krb5_cc_next_cred(context, cache, &cursor, &cur); + if (ret) + break; + + if (krb5int_cc_creds_match_request(context, flags, creds, &cur)) + ret = delete_cred(context, cache, &cursor, &cur); + krb5_free_cred_contents(context, &cur); + if (ret) + break; + } + + krb5_cc_end_seq_get(context, cache, &cursor); + return (ret == KRB5_CC_END) ? 0 : ret; +} + +static krb5_error_code KRB5_CALLCONV +fcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags) +{ + return 0; +} + +static krb5_error_code KRB5_CALLCONV +fcc_get_flags(krb5_context context, krb5_ccache id, krb5_flags *flags) +{ + *flags = 0; + return 0; +} + +/* Prepare to iterate over the caches in the per-type collection. */ +static krb5_error_code KRB5_CALLCONV +fcc_ptcursor_new(krb5_context context, krb5_cc_ptcursor *cursor) +{ + krb5_cc_ptcursor n = NULL; + struct krb5_fcc_ptcursor_data *cdata = NULL; + + *cursor = NULL; + + n = malloc(sizeof(*n)); + if (n == NULL) + return ENOMEM; + n->ops = &krb5_fcc_ops; + cdata = malloc(sizeof(*cdata)); + if (cdata == NULL) { + free(n); + return ENOMEM; + } + cdata->first = TRUE; + n->data = cdata; + *cursor = n; + return 0; +} + +/* Get the next cache in the per-type collection. The FILE per-type collection + * contains only the context's default cache if it is a file cache. */ +static krb5_error_code KRB5_CALLCONV +fcc_ptcursor_next(krb5_context context, krb5_cc_ptcursor cursor, + krb5_ccache *cache_out) +{ + krb5_error_code ret; + struct krb5_fcc_ptcursor_data *cdata = cursor->data; + const char *defname, *residual; + krb5_ccache cache; + struct stat sb; + + *cache_out = NULL; + if (!cdata->first) + return 0; + cdata->first = FALSE; + + defname = krb5_cc_default_name(context); + if (!defname) + return 0; + + /* Check if the default has type FILE or no type; find the residual. */ + if (strncmp(defname, "FILE:", 5) == 0) + residual = defname + 5; + else if (strchr(defname + 2, ':') == NULL) /* Skip drive prefix if any. */ + residual = defname; + else + return 0; + + /* Don't yield a nonexistent default file cache. */ + if (stat(residual, &sb) != 0) + return 0; + + ret = krb5_cc_resolve(context, defname, &cache); + if (ret) + return set_errmsg_filename(context, ret, defname); + *cache_out = cache; + return 0; +} + +/* Release a per-type collection iteration cursor. */ +static krb5_error_code KRB5_CALLCONV +fcc_ptcursor_free(krb5_context context, krb5_cc_ptcursor *cursor) +{ + if (*cursor == NULL) + return 0; + free((*cursor)->data); + free(*cursor); + *cursor = NULL; + return 0; +} + +/* Lock the cache handle against other threads. (This does not lock the cache + * file against other processes.) */ +static krb5_error_code KRB5_CALLCONV +fcc_lock(krb5_context context, krb5_ccache id) +{ + fcc_data *data = id->data; + k5_cc_mutex_lock(context, &data->lock); + return 0; +} + +/* Unlock the cache handle. */ +static krb5_error_code KRB5_CALLCONV +fcc_unlock(krb5_context context, krb5_ccache id) +{ + fcc_data *data = id->data; + k5_cc_mutex_unlock(context, &data->lock); + return 0; +} + +static krb5_error_code KRB5_CALLCONV +fcc_replace(krb5_context context, krb5_ccache id, krb5_principal princ, + krb5_creds **creds) +{ + krb5_error_code ret; + fcc_data *data = id->data; + char *tmpname = NULL; + int i, st, fd = -1, version = context->fcc_default_format - FVNO_BASE; + ssize_t nwritten; + struct k5buf buf = EMPTY_K5BUF; + krb5_boolean tmpfile_exists = FALSE; + + if (asprintf(&tmpname, "%s.XXXXXX", data->filename) < 0) + return ENOMEM; + fd = mkstemp(tmpname); + if (fd < 0) + goto errno_cleanup; + tmpfile_exists = TRUE; + + k5_buf_init_dynamic_zap(&buf); + marshal_header(context, &buf, princ); + for (i = 0; creds[i] != NULL; i++) + k5_marshal_cred(&buf, version, creds[i]); + ret = k5_buf_status(&buf); + if (ret) + goto cleanup; + + nwritten = write(fd, buf.data, buf.len); + if (nwritten == -1) + goto errno_cleanup; + if ((size_t)nwritten != buf.len) { + ret = KRB5_CC_IO; + goto cleanup; + } + st = close(fd); + fd = -1; + if (st != 0) + goto errno_cleanup; + + st = rename(tmpname, data->filename); + if (st != 0) + goto errno_cleanup; + tmpfile_exists = FALSE; + +cleanup: + k5_buf_free(&buf); + if (fd != -1) + close(fd); + if (tmpfile_exists) + unlink(tmpname); + free(tmpname); + return ret; + +errno_cleanup: + ret = interpret_errno(context, errno); + goto cleanup; +} + +/* Translate a system errno value to a Kerberos com_err code. */ +static krb5_error_code +interpret_errno(krb5_context context, int errnum) +{ + krb5_error_code ret; + + switch (errnum) { + case ENOENT: + case ENOTDIR: +#ifdef ELOOP + case ELOOP: +#endif +#ifdef ENAMETOOLONG + case ENAMETOOLONG: +#endif + ret = KRB5_FCC_NOFILE; + break; + case EPERM: + case EACCES: +#ifdef EISDIR + case EISDIR: /* Mac doesn't have EISDIR */ +#endif + case EROFS: + ret = KRB5_FCC_PERM; + break; + case EINVAL: + case EEXIST: + case EFAULT: + case EBADF: +#ifdef EWOULDBLOCK + case EWOULDBLOCK: +#endif + ret = KRB5_FCC_INTERNAL; + break; + /* + * The rest all map to KRB5_CC_IO. These errnos are listed to + * document that they've been considered explicitly: + * + * - EDQUOT + * - ENOSPC + * - EIO + * - ENFILE + * - EMFILE + * - ENXIO + * - EBUSY + * - ETXTBSY + */ + default: + ret = KRB5_CC_IO; + break; + } + return ret; +} + +const krb5_cc_ops krb5_fcc_ops = { + 0, + "FILE", + fcc_get_name, + fcc_resolve, + fcc_generate_new, + fcc_initialize, + fcc_destroy, + fcc_close, + fcc_store, + fcc_retrieve, + fcc_get_principal, + fcc_start_seq_get, + fcc_next_cred, + fcc_end_seq_get, + fcc_remove_cred, + fcc_set_flags, + fcc_get_flags, + fcc_ptcursor_new, + fcc_ptcursor_next, + fcc_ptcursor_free, + fcc_replace, + NULL, /* wasdefault */ + fcc_lock, + fcc_unlock, + NULL, /* switch_to */ +}; + +#if defined(_WIN32) +/* + * krb5_change_cache should be called after the cache changes. + * A notification message is is posted out to all top level + * windows so that they may recheck the cache based on the + * changes made. We register a unique message type with which + * we'll communicate to all other processes. + */ + +krb5_error_code +krb5_change_cache(void) +{ + PostMessage(HWND_BROADCAST, krb5_get_notification_message(), 0, 0); + return 0; +} + +unsigned int KRB5_CALLCONV +krb5_get_notification_message(void) +{ + static unsigned int message = 0; + + if (message == 0) + message = RegisterWindowMessage(WM_KERBEROS5_CHANGED); + + return message; +} +#else /* _WIN32 */ + +krb5_error_code +krb5_change_cache(void) +{ + return 0; +} + +unsigned int +krb5_get_notification_message(void) +{ + return 0; +} + +#endif /* _WIN32 */ + +const krb5_cc_ops krb5_cc_file_ops = { + 0, + "FILE", + fcc_get_name, + fcc_resolve, + fcc_generate_new, + fcc_initialize, + fcc_destroy, + fcc_close, + fcc_store, + fcc_retrieve, + fcc_get_principal, + fcc_start_seq_get, + fcc_next_cred, + fcc_end_seq_get, + fcc_remove_cred, + fcc_set_flags, + fcc_get_flags, + fcc_ptcursor_new, + fcc_ptcursor_next, + fcc_ptcursor_free, + fcc_replace, + NULL, /* wasdefault */ + fcc_lock, + fcc_unlock, + NULL, /* switch_to */ +}; diff --git a/krb5-1.21.3/src/lib/krb5/ccache/cc_kcm.c b/krb5-1.21.3/src/lib/krb5/ccache/cc_kcm.c new file mode 100644 index 00000000..c93e7c78 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/cc_kcm.c @@ -0,0 +1,1366 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/cc_kcm.c - KCM cache type (client side) */ +/* + * Copyright (C) 2014 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. + */ + +/* + * This cache type contacts a daemon for each cache operation, using Heimdal's + * KCM protocol. On macOS, the preferred transport is Mach RPC; on other + * Unix-like platforms or if the daemon is not available via RPC, Unix domain + * sockets are used instead. + */ + +#ifndef _WIN32 +#include "k5-int.h" +#include "k5-input.h" +#include "cc-int.h" +#include "kcm.h" +#include "../os/os-proto.h" +#include +#include +#ifdef __APPLE__ +#include +#include +#include "kcmrpc.h" +#endif + +#define MAX_REPLY_SIZE (10 * 1024 * 1024) + +const krb5_cc_ops krb5_kcm_ops; + +struct uuid_list { + unsigned char *uuidbytes; /* all of the uuids concatenated together */ + size_t count; + size_t pos; +}; + +struct cred_list { + krb5_creds *creds; + size_t count; + size_t pos; +}; + +struct kcm_cursor { + struct uuid_list *uuids; + struct cred_list *creds; +}; + +struct kcmio { + SOCKET fd; +#ifdef __APPLE__ + mach_port_t mport; +#endif +}; + +/* This structure bundles together a KCM request and reply, to minimize how + * much we have to declare and clean up in each method. */ +struct kcmreq { + struct k5buf reqbuf; + struct k5input reply; + void *reply_mem; +}; +#define EMPTY_KCMREQ { EMPTY_K5BUF } + +struct kcm_cache_data { + char *residual; /* immutable; may be accessed without lock */ + k5_cc_mutex lock; /* protects io */ + struct kcmio *io; +}; + +struct kcm_ptcursor { + char *residual; /* primary or singleton subsidiary */ + struct uuid_list *uuids; /* NULL for singleton subsidiary */ + struct kcmio *io; + krb5_boolean first; +}; + +/* Map EINVAL or KRB5_CC_FORMAT to KRB5_KCM_MALFORMED_REPLY; pass through all + * other codes. */ +static inline krb5_error_code +map_invalid(krb5_error_code code) +{ + return (code == EINVAL || code == KRB5_CC_FORMAT) ? + KRB5_KCM_MALFORMED_REPLY : code; +} + +/* + * Map an MIT krb5 KRB5_TC flag word to the equivalent Heimdal flag word. Note + * that there is no MIT krb5 equivalent for Heimdal's KRB5_TC_DONT_MATCH_REALM + * (which is like KRB5_TC_MATCH_SRV_NAMEONLY but also applies to the client + * principal) and no Heimdal equivalent for MIT krb5's KRB5_TC_SUPPORTED_KTYPES + * (which matches against enctypes from the krb5_context rather than the + * matching cred). + */ +static inline krb5_flags +map_tcflags(krb5_flags mitflags) +{ + krb5_flags heimflags = 0; + + if (mitflags & KRB5_TC_MATCH_TIMES) + heimflags |= KCM_TC_MATCH_TIMES; + if (mitflags & KRB5_TC_MATCH_IS_SKEY) + heimflags |= KCM_TC_MATCH_IS_SKEY; + if (mitflags & KRB5_TC_MATCH_FLAGS) + heimflags |= KCM_TC_MATCH_FLAGS; + if (mitflags & KRB5_TC_MATCH_TIMES_EXACT) + heimflags |= KCM_TC_MATCH_TIMES_EXACT; + if (mitflags & KRB5_TC_MATCH_FLAGS_EXACT) + heimflags |= KCM_TC_MATCH_FLAGS_EXACT; + if (mitflags & KRB5_TC_MATCH_AUTHDATA) + heimflags |= KCM_TC_MATCH_AUTHDATA; + if (mitflags & KRB5_TC_MATCH_SRV_NAMEONLY) + heimflags |= KCM_TC_MATCH_SRV_NAMEONLY; + if (mitflags & KRB5_TC_MATCH_2ND_TKT) + heimflags |= KCM_TC_MATCH_2ND_TKT; + if (mitflags & KRB5_TC_MATCH_KTYPE) + heimflags |= KCM_TC_MATCH_KEYTYPE; + return heimflags; +} + +/* + * Return true if code could indicate an unsupported operation. Heimdal's KCM + * returns KRB5_FCC_INTERNAL. sssd's KCM daemon (as of sssd 2.4) returns + * KRB5_CC_NO_SUPP if it recognizes the operation but does not implement it, + * and KRB5_CC_IO if it doesn't recognize the operation (which is unfortunate + * since it could also indicate a communication failure). + */ +static krb5_boolean +unsupported_op_error(krb5_error_code code) +{ + return code == KRB5_FCC_INTERNAL || code == KRB5_CC_IO || + code == KRB5_CC_NOSUPP; +} + +/* Begin a request for the given opcode. If cache is non-null, supply the + * cache name as a request parameter. */ +static void +kcmreq_init(struct kcmreq *req, kcm_opcode opcode, krb5_ccache cache) +{ + unsigned char bytes[4]; + const char *name; + + memset(req, 0, sizeof(*req)); + + bytes[0] = KCM_PROTOCOL_VERSION_MAJOR; + bytes[1] = KCM_PROTOCOL_VERSION_MINOR; + store_16_be(opcode, bytes + 2); + + k5_buf_init_dynamic(&req->reqbuf); + k5_buf_add_len(&req->reqbuf, bytes, 4); + if (cache != NULL) { + name = ((struct kcm_cache_data *)cache->data)->residual; + k5_buf_add_len(&req->reqbuf, name, strlen(name) + 1); + } +} + +#ifdef __APPLE__ + +/* The maximum length of an in-band request or reply as defined by the RPC + * protocol. */ +#define MAX_INBAND_SIZE 2048 + +/* Connect or reconnect to the KCM daemon via Mach RPC, if possible. */ +static krb5_error_code +kcmio_mach_connect(krb5_context context, struct kcmio *io) +{ + krb5_error_code ret; + kern_return_t st; + mach_port_t mport; + char *service; + + ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_KCM_MACH_SERVICE, NULL, + DEFAULT_KCM_MACH_SERVICE, &service); + if (ret) + return ret; + if (strcmp(service, "-") == 0) { + profile_release_string(service); + return KRB5_KCM_NO_SERVER; + } + + st = bootstrap_look_up(bootstrap_port, service, &mport); + profile_release_string(service); + if (st) + return KRB5_KCM_NO_SERVER; + if (io->mport != MACH_PORT_NULL) + mach_port_deallocate(mach_task_self(), io->mport); + io->mport = mport; + return 0; +} + +/* Invoke the Mach RPC to get a reply from the KCM daemon. */ +static krb5_error_code +kcmio_mach_call(krb5_context context, struct kcmio *io, void *data, + size_t len, void **reply_out, size_t *len_out) +{ + krb5_error_code ret; + size_t inband_req_len = 0, outband_req_len = 0, reply_len; + char *inband_req = NULL, *outband_req = NULL, *outband_reply, *copy; + char inband_reply[MAX_INBAND_SIZE]; + mach_msg_type_number_t inband_reply_len, outband_reply_len; + const void *reply; + kern_return_t st; + int code; + + *reply_out = NULL; + *len_out = 0; + + /* Use the in-band or out-of-band request buffer depending on len. */ + if (len <= MAX_INBAND_SIZE) { + inband_req = data; + inband_req_len = len; + } else { + outband_req = data; + outband_req_len = len; + } + + st = k5_kcmrpc_call(io->mport, inband_req, inband_req_len, outband_req, + outband_req_len, &code, inband_reply, + &inband_reply_len, &outband_reply, &outband_reply_len); + if (st == MACH_SEND_INVALID_DEST) { + /* Get a new port and try again. */ + st = kcmio_mach_connect(context, io); + if (st) + return KRB5_KCM_RPC_ERROR; + st = k5_kcmrpc_call(io->mport, inband_req, inband_req_len, outband_req, + outband_req_len, &code, inband_reply, + &inband_reply_len, &outband_reply, + &outband_reply_len); + } + if (st) + return KRB5_KCM_RPC_ERROR; + + if (code) { + ret = code; + goto cleanup; + } + + /* The reply could be in the in-band or out-of-band reply buffer. */ + reply = outband_reply_len ? outband_reply : inband_reply; + reply_len = outband_reply_len ? outband_reply_len : inband_reply_len; + copy = k5memdup(reply, reply_len, &ret); + if (copy == NULL) + goto cleanup; + + *reply_out = copy; + *len_out = reply_len; + +cleanup: + if (outband_reply_len) { + vm_deallocate(mach_task_self(), (vm_address_t)outband_reply, + outband_reply_len); + } + return ret; +} + +/* Release any Mach RPC state within io. */ +static void +kcmio_mach_close(struct kcmio *io) +{ + if (io->mport != MACH_PORT_NULL) + mach_port_deallocate(mach_task_self(), io->mport); +} + +#else /* __APPLE__ */ + +#define kcmio_mach_connect(context, io) EINVAL +#define kcmio_mach_call(context, io, data, len, reply_out, len_out) EINVAL +#define kcmio_mach_close(io) + +#endif + +/* Connect to the KCM daemon via a Unix domain socket. */ +static krb5_error_code +kcmio_unix_socket_connect(krb5_context context, struct kcmio *io) +{ + krb5_error_code ret; + SOCKET fd = INVALID_SOCKET; + struct sockaddr_un addr; + char *path = NULL; + + ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_KCM_SOCKET, NULL, + DEFAULT_KCM_SOCKET_PATH, &path); + if (ret) + goto cleanup; + if (strcmp(path, "-") == 0) { + ret = KRB5_KCM_NO_SERVER; + goto cleanup; + } + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == INVALID_SOCKET) { + ret = SOCKET_ERRNO; + goto cleanup; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strlcpy(addr.sun_path, path, sizeof(addr.sun_path)); + if (SOCKET_CONNECT(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) { + ret = (SOCKET_ERRNO == ENOENT) ? KRB5_KCM_NO_SERVER : SOCKET_ERRNO; + goto cleanup; + } + + io->fd = fd; + fd = INVALID_SOCKET; + +cleanup: + if (fd != INVALID_SOCKET) + closesocket(fd); + profile_release_string(path); + return ret; +} + +/* Write a KCM request: 4-byte big-endian length, then the marshalled + * request. */ +static krb5_error_code +kcmio_unix_socket_write(krb5_context context, struct kcmio *io, void *request, + size_t len) +{ + char lenbytes[4]; + sg_buf sg[2]; + int ret; + krb5_boolean reconnected = FALSE; + + SG_SET(&sg[0], lenbytes, sizeof(lenbytes)); + SG_SET(&sg[1], request, len); + store_32_be(len, lenbytes); + + for (;;) { + ret = krb5int_net_writev(context, io->fd, sg, 2); + if (ret >= 0) + return 0; + ret = errno; + if (ret != EPIPE || reconnected) + return ret; + + /* + * Try once to reconnect on an EPIPE, in case the server has an idle + * timeout (like sssd does) and we went too long between ccache + * operations. Reconnecting might also help if the server was + * restarted for an upgrade--although the server must be designed to + * always listen for connections on the socket during upgrades, or a + * single reconnect attempt won't be robust. + */ + close(io->fd); + ret = kcmio_unix_socket_connect(context, io); + if (ret) + return ret; + reconnected = TRUE; + } +} + +/* Read a KCM reply: 4-byte big-endian length, 4-byte big-endian status code, + * then the marshalled reply. */ +static krb5_error_code +kcmio_unix_socket_read(krb5_context context, struct kcmio *io, + void **reply_out, size_t *len_out) +{ + krb5_error_code code; + char lenbytes[4], codebytes[4], *reply; + size_t len; + int st; + + *reply_out = NULL; + *len_out = 0; + + st = krb5_net_read(context, io->fd, lenbytes, 4); + if (st != 4) + return (st == -1) ? errno : KRB5_CC_IO; + len = load_32_be(lenbytes); + if (len > MAX_REPLY_SIZE) + return KRB5_KCM_REPLY_TOO_BIG; + + st = krb5_net_read(context, io->fd, codebytes, 4); + if (st != 4) + return (st == -1) ? errno : KRB5_CC_IO; + code = load_32_be(codebytes); + if (code != 0) + return code; + + reply = malloc(len); + if (reply == NULL) + return ENOMEM; + st = krb5_net_read(context, io->fd, reply, len); + if (st == -1 || (size_t)st != len) { + free(reply); + return (st < 0) ? errno : KRB5_CC_IO; + } + + *reply_out = reply; + *len_out = len; + return 0; +} + +static krb5_error_code +kcmio_connect(krb5_context context, struct kcmio **io_out) +{ + krb5_error_code ret; + struct kcmio *io; + + *io_out = NULL; + io = calloc(1, sizeof(*io)); + if (io == NULL) + return ENOMEM; + io->fd = INVALID_SOCKET; + + /* Try Mach RPC (macOS only), then fall back to Unix domain sockets */ + ret = kcmio_mach_connect(context, io); + if (ret) + ret = kcmio_unix_socket_connect(context, io); + if (ret) { + free(io); + return ret; + } + + *io_out = io; + return 0; +} + +/* Check req->reqbuf for an error condition and return it. Otherwise, send the + * request to the KCM daemon and get a response. */ +static krb5_error_code +kcmio_call(krb5_context context, struct kcmio *io, struct kcmreq *req) +{ + krb5_error_code ret; + size_t reply_len = 0; + + if (k5_buf_status(&req->reqbuf) != 0) + return ENOMEM; + + if (io->fd != INVALID_SOCKET) { + ret = kcmio_unix_socket_write(context, io, req->reqbuf.data, + req->reqbuf.len); + if (ret) + return ret; + ret = kcmio_unix_socket_read(context, io, &req->reply_mem, &reply_len); + if (ret) + return ret; + } else { + /* We must be using Mach RPC. */ + ret = kcmio_mach_call(context, io, req->reqbuf.data, req->reqbuf.len, + &req->reply_mem, &reply_len); + if (ret) + return ret; + } + + /* Read the status code from the marshalled reply. */ + k5_input_init(&req->reply, req->reply_mem, reply_len); + ret = k5_input_get_uint32_be(&req->reply); + return req->reply.status ? KRB5_KCM_MALFORMED_REPLY : ret; +} + +static void +kcmio_close(struct kcmio *io) +{ + if (io != NULL) { + kcmio_mach_close(io); + if (io->fd != INVALID_SOCKET) + closesocket(io->fd); + free(io); + } +} + +/* Fetch a zero-terminated name string from req->reply. The returned pointer + * is an alias and must not be freed by the caller. */ +static krb5_error_code +kcmreq_get_name(struct kcmreq *req, const char **name_out) +{ + const unsigned char *end; + struct k5input *in = &req->reply; + + *name_out = NULL; + end = memchr(in->ptr, '\0', in->len); + if (end == NULL) + return KRB5_KCM_MALFORMED_REPLY; + *name_out = (const char *)in->ptr; + (void)k5_input_get_bytes(in, end + 1 - in->ptr); + return 0; +} + +/* Fetch a UUID list from req->reply. UUID lists are not delimited, so we + * consume the rest of the input. */ +static krb5_error_code +kcmreq_get_uuid_list(struct kcmreq *req, struct uuid_list **uuids_out) +{ + struct uuid_list *uuids; + + *uuids_out = NULL; + + if (req->reply.len % KCM_UUID_LEN != 0) + return KRB5_KCM_MALFORMED_REPLY; + + uuids = malloc(sizeof(*uuids)); + if (uuids == NULL) + return ENOMEM; + uuids->count = req->reply.len / KCM_UUID_LEN; + uuids->pos = 0; + + if (req->reply.len > 0) { + uuids->uuidbytes = malloc(req->reply.len); + if (uuids->uuidbytes == NULL) { + free(uuids); + return ENOMEM; + } + memcpy(uuids->uuidbytes, req->reply.ptr, req->reply.len); + (void)k5_input_get_bytes(&req->reply, req->reply.len); + } else { + uuids->uuidbytes = NULL; + } + + *uuids_out = uuids; + return 0; +} + +static void +free_uuid_list(struct uuid_list *uuids) +{ + if (uuids != NULL) + free(uuids->uuidbytes); + free(uuids); +} + +static void +free_cred_list(struct cred_list *list) +{ + size_t i; + + if (list == NULL) + return; + + /* Creds are transferred to the caller as list->pos is incremented, so we + * can start freeing there. */ + for (i = list->pos; i < list->count; i++) + krb5_free_cred_contents(NULL, &list->creds[i]); + free(list->creds); + free(list); +} + +/* Fetch a cred list from req->reply. */ +static krb5_error_code +kcmreq_get_cred_list(struct kcmreq *req, struct cred_list **creds_out) +{ + struct cred_list *list; + const unsigned char *data; + krb5_error_code ret = 0; + size_t count, len, i; + + *creds_out = NULL; + + /* Check a rough bound on the count to prevent very large allocations. */ + count = k5_input_get_uint32_be(&req->reply); + if (count > req->reply.len / 4) + return KRB5_KCM_MALFORMED_REPLY; + + list = malloc(sizeof(*list)); + if (list == NULL) + return ENOMEM; + + list->creds = NULL; + list->count = count; + list->pos = 0; + list->creds = k5calloc(count, sizeof(*list->creds), &ret); + if (list->creds == NULL) { + free(list); + return ret; + } + + for (i = 0; i < count; i++) { + len = k5_input_get_uint32_be(&req->reply); + data = k5_input_get_bytes(&req->reply, len); + if (data == NULL) + break; + ret = k5_unmarshal_cred(data, len, 4, &list->creds[i]); + if (ret) + break; + } + if (i < count) { + free_cred_list(list); + return (ret == ENOMEM) ? ENOMEM : KRB5_KCM_MALFORMED_REPLY; + } + + *creds_out = list; + return 0; +} + +static void +kcmreq_free(struct kcmreq *req) +{ + k5_buf_free(&req->reqbuf); + free(req->reply_mem); +} + +/* Create a krb5_ccache structure. If io is NULL, make a new connection for + * the cache. Otherwise, always take ownership of io. */ +static krb5_error_code +make_cache(krb5_context context, const char *residual, struct kcmio *io, + krb5_ccache *cache_out) +{ + krb5_error_code ret; + krb5_ccache cache = NULL; + struct kcm_cache_data *data = NULL; + char *residual_copy = NULL; + + *cache_out = NULL; + + if (io == NULL) { + ret = kcmio_connect(context, &io); + if (ret) + return ret; + } + + cache = malloc(sizeof(*cache)); + if (cache == NULL) + goto oom; + data = calloc(1, sizeof(*data)); + if (data == NULL) + goto oom; + residual_copy = strdup(residual); + if (residual_copy == NULL) + goto oom; + if (k5_cc_mutex_init(&data->lock) != 0) + goto oom; + + data->residual = residual_copy; + data->io = io; + cache->ops = &krb5_kcm_ops; + cache->data = data; + cache->magic = KV5M_CCACHE; + *cache_out = cache; + return 0; + +oom: + free(cache); + free(data); + free(residual_copy); + kcmio_close(io); + return ENOMEM; +} + +/* Lock cache's I/O structure and use it to call the KCM daemon. */ +static krb5_error_code +cache_call(krb5_context context, krb5_ccache cache, struct kcmreq *req) +{ + krb5_error_code ret; + struct kcm_cache_data *data = cache->data; + + k5_cc_mutex_lock(context, &data->lock); + ret = kcmio_call(context, data->io, req); + k5_cc_mutex_unlock(context, &data->lock); + return ret; +} + +/* Try to propagate the KDC time offset from the cache to the krb5 context. */ +static void +get_kdc_offset(krb5_context context, krb5_ccache cache) +{ + struct kcmreq req = EMPTY_KCMREQ; + int32_t time_offset; + + kcmreq_init(&req, KCM_OP_GET_KDC_OFFSET, cache); + if (cache_call(context, cache, &req) != 0) + goto cleanup; + time_offset = k5_input_get_uint32_be(&req.reply); + if (req.reply.status) + goto cleanup; + context->os_context.time_offset = time_offset; + context->os_context.usec_offset = 0; + context->os_context.os_flags &= ~KRB5_OS_TOFFSET_TIME; + context->os_context.os_flags |= KRB5_OS_TOFFSET_VALID; + +cleanup: + kcmreq_free(&req); +} + +/* Try to propagate the KDC offset from the krb5 context to the cache. */ +static void +set_kdc_offset(krb5_context context, krb5_ccache cache) +{ + struct kcmreq req; + + if (context->os_context.os_flags & KRB5_OS_TOFFSET_VALID) { + kcmreq_init(&req, KCM_OP_SET_KDC_OFFSET, cache); + k5_buf_add_uint32_be(&req.reqbuf, context->os_context.time_offset); + (void)cache_call(context, cache, &req); + kcmreq_free(&req); + } +} + +static const char * KRB5_CALLCONV +kcm_get_name(krb5_context context, krb5_ccache cache) +{ + return ((struct kcm_cache_data *)cache->data)->residual; +} + +/* Fetch the primary name within the collection. The result is only valid for + * the lifetime of req and should not be freed. */ +static krb5_error_code +get_primary_name(krb5_context context, struct kcmreq *req, struct kcmio *io, + const char **name_out) +{ + krb5_error_code ret; + + *name_out = NULL; + + kcmreq_init(req, KCM_OP_GET_DEFAULT_CACHE, NULL); + ret = kcmio_call(context, io, req); + if (ret) + return ret; + return kcmreq_get_name(req, name_out); +} + +static krb5_error_code KRB5_CALLCONV +kcm_resolve(krb5_context context, krb5_ccache *cache_out, const char *residual) +{ + krb5_error_code ret; + struct kcmreq req = EMPTY_KCMREQ; + struct kcmio *io = NULL; + const char *defname = NULL; + + *cache_out = NULL; + + ret = kcmio_connect(context, &io); + if (ret) + goto cleanup; + + if (*residual == '\0') { + ret = get_primary_name(context, &req, io, &defname); + if (ret) + goto cleanup; + residual = defname; + } + + ret = make_cache(context, residual, io, cache_out); + io = NULL; + +cleanup: + kcmio_close(io); + kcmreq_free(&req); + return ret; +} + +krb5_error_code +k5_kcm_primary_name(krb5_context context, char **name_out) +{ + krb5_error_code ret; + struct kcmreq req = EMPTY_KCMREQ; + struct kcmio *io = NULL; + const char *name; + + *name_out = NULL; + + ret = kcmio_connect(context, &io); + if (ret) + goto cleanup; + ret = get_primary_name(context, &req, io, &name); + if (ret) + goto cleanup; + *name_out = strdup(name); + ret = (*name_out == NULL) ? ENOMEM : 0; + +cleanup: + kcmio_close(io); + kcmreq_free(&req); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +kcm_gen_new(krb5_context context, krb5_ccache *cache_out) +{ + krb5_error_code ret; + struct kcmreq req = EMPTY_KCMREQ; + struct kcmio *io = NULL; + const char *name; + + *cache_out = NULL; + + ret = kcmio_connect(context, &io); + if (ret) + goto cleanup; + kcmreq_init(&req, KCM_OP_GEN_NEW, NULL); + ret = kcmio_call(context, io, &req); + if (ret) + goto cleanup; + ret = kcmreq_get_name(&req, &name); + if (ret) + goto cleanup; + ret = make_cache(context, name, io, cache_out); + io = NULL; + +cleanup: + kcmreq_free(&req); + kcmio_close(io); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +kcm_initialize(krb5_context context, krb5_ccache cache, krb5_principal princ) +{ + krb5_error_code ret; + struct kcmreq req; + + kcmreq_init(&req, KCM_OP_INITIALIZE, cache); + k5_marshal_princ(&req.reqbuf, 4, princ); + ret = cache_call(context, cache, &req); + kcmreq_free(&req); + set_kdc_offset(context, cache); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +kcm_close(krb5_context context, krb5_ccache cache) +{ + struct kcm_cache_data *data = cache->data; + + k5_cc_mutex_destroy(&data->lock); + kcmio_close(data->io); + free(data->residual); + free(data); + free(cache); + return 0; +} + +static krb5_error_code KRB5_CALLCONV +kcm_destroy(krb5_context context, krb5_ccache cache) +{ + krb5_error_code ret; + struct kcmreq req; + + kcmreq_init(&req, KCM_OP_DESTROY, cache); + ret = cache_call(context, cache, &req); + kcmreq_free(&req); + (void)kcm_close(context, cache); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +kcm_store(krb5_context context, krb5_ccache cache, krb5_creds *cred) +{ + krb5_error_code ret; + struct kcmreq req; + + kcmreq_init(&req, KCM_OP_STORE, cache); + k5_marshal_cred(&req.reqbuf, 4, cred); + ret = cache_call(context, cache, &req); + kcmreq_free(&req); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +kcm_retrieve(krb5_context context, krb5_ccache cache, krb5_flags flags, + krb5_creds *mcred, krb5_creds *cred_out) +{ + krb5_error_code ret; + struct kcmreq req = EMPTY_KCMREQ; + krb5_creds cred; + krb5_enctype *enctypes = NULL; + + memset(&cred, 0, sizeof(cred)); + + /* Include KCM_GC_CACHED in flags to prevent Heimdal's sssd from making a + * TGS request itself. */ + kcmreq_init(&req, KCM_OP_RETRIEVE, cache); + k5_buf_add_uint32_be(&req.reqbuf, map_tcflags(flags) | KCM_GC_CACHED); + k5_marshal_mcred(&req.reqbuf, mcred); + ret = cache_call(context, cache, &req); + + /* Fall back to iteration if the server does not support retrieval. */ + if (unsupported_op_error(ret)) { + ret = k5_cc_retrieve_cred_default(context, cache, flags, mcred, + cred_out); + goto cleanup; + } + if (ret) + goto cleanup; + + ret = k5_unmarshal_cred(req.reply.ptr, req.reply.len, 4, &cred); + if (ret) + goto cleanup; + + /* In rare cases we might retrieve a credential with a session key this + * context can't support, in which case we must retry using iteration. */ + if (flags & KRB5_TC_SUPPORTED_KTYPES) { + ret = krb5_get_tgs_ktypes(context, cred.server, &enctypes); + if (ret) + goto cleanup; + if (!k5_etypes_contains(enctypes, cred.keyblock.enctype)) { + ret = k5_cc_retrieve_cred_default(context, cache, flags, mcred, + cred_out); + goto cleanup; + } + } + + *cred_out = cred; + memset(&cred, 0, sizeof(cred)); + +cleanup: + kcmreq_free(&req); + krb5_free_cred_contents(context, &cred); + free(enctypes); + /* Heimdal's KCM returns KRB5_CC_END if no cred is found. */ + return (ret == KRB5_CC_END) ? KRB5_CC_NOTFOUND : map_invalid(ret); +} + +static krb5_error_code KRB5_CALLCONV +kcm_get_princ(krb5_context context, krb5_ccache cache, + krb5_principal *princ_out) +{ + krb5_error_code ret; + struct kcmreq req; + struct kcm_cache_data *data = cache->data; + + kcmreq_init(&req, KCM_OP_GET_PRINCIPAL, cache); + ret = cache_call(context, cache, &req); + /* Heimdal KCM can respond with code 0 and no principal. */ + if (!ret && req.reply.len == 0) + ret = KRB5_FCC_NOFILE; + if (ret == KRB5_FCC_NOFILE) { + k5_setmsg(context, ret, _("Credentials cache 'KCM:%s' not found"), + data->residual); + } + + if (!ret) + ret = k5_unmarshal_princ(req.reply.ptr, req.reply.len, 4, princ_out); + kcmreq_free(&req); + return map_invalid(ret); +} + +static krb5_error_code KRB5_CALLCONV +kcm_start_seq_get(krb5_context context, krb5_ccache cache, + krb5_cc_cursor *cursor_out) +{ + krb5_error_code ret; + struct kcmreq req = EMPTY_KCMREQ; + struct uuid_list *uuids = NULL; + struct cred_list *creds = NULL; + struct kcm_cursor *cursor; + + *cursor_out = NULL; + + get_kdc_offset(context, cache); + + kcmreq_init(&req, KCM_OP_GET_CRED_LIST, cache); + ret = cache_call(context, cache, &req); + if (ret == 0) { + /* GET_CRED_LIST is available. */ + ret = kcmreq_get_cred_list(&req, &creds); + if (ret) + goto cleanup; + } else if (unsupported_op_error(ret)) { + /* Fall back to GET_CRED_UUID_LIST. */ + kcmreq_free(&req); + kcmreq_init(&req, KCM_OP_GET_CRED_UUID_LIST, cache); + ret = cache_call(context, cache, &req); + if (ret) + goto cleanup; + ret = kcmreq_get_uuid_list(&req, &uuids); + if (ret) + goto cleanup; + } else { + goto cleanup; + } + + cursor = k5alloc(sizeof(*cursor), &ret); + if (cursor == NULL) + goto cleanup; + cursor->uuids = uuids; + cursor->creds = creds; + *cursor_out = (krb5_cc_cursor)cursor; + +cleanup: + kcmreq_free(&req); + return ret; +} + +static krb5_error_code +next_cred_by_uuid(krb5_context context, krb5_ccache cache, + struct uuid_list *uuids, krb5_creds *cred_out) +{ + krb5_error_code ret; + struct kcmreq req; + + memset(cred_out, 0, sizeof(*cred_out)); + + if (uuids->pos >= uuids->count) + return KRB5_CC_END; + + kcmreq_init(&req, KCM_OP_GET_CRED_BY_UUID, cache); + k5_buf_add_len(&req.reqbuf, uuids->uuidbytes + (uuids->pos * KCM_UUID_LEN), + KCM_UUID_LEN); + uuids->pos++; + ret = cache_call(context, cache, &req); + if (!ret) + ret = k5_unmarshal_cred(req.reply.ptr, req.reply.len, 4, cred_out); + kcmreq_free(&req); + return map_invalid(ret); +} + +static krb5_error_code KRB5_CALLCONV +kcm_next_cred(krb5_context context, krb5_ccache cache, krb5_cc_cursor *cursor, + krb5_creds *cred_out) +{ + struct kcm_cursor *c = (struct kcm_cursor *)*cursor; + struct cred_list *list; + + if (c->uuids != NULL) + return next_cred_by_uuid(context, cache, c->uuids, cred_out); + + list = c->creds; + if (list->pos >= list->count) + return KRB5_CC_END; + + /* Transfer memory ownership of one cred to the caller. */ + *cred_out = list->creds[list->pos]; + memset(&list->creds[list->pos], 0, sizeof(*list->creds)); + list->pos++; + + return 0; +} + +static krb5_error_code KRB5_CALLCONV +kcm_end_seq_get(krb5_context context, krb5_ccache cache, + krb5_cc_cursor *cursor) +{ + struct kcm_cursor *c = *cursor; + + if (c == NULL) + return 0; + free_uuid_list(c->uuids); + free_cred_list(c->creds); + free(c); + *cursor = NULL; + return 0; +} + +static krb5_error_code KRB5_CALLCONV +kcm_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags, + krb5_creds *mcred) +{ + krb5_error_code ret; + struct kcmreq req; + + kcmreq_init(&req, KCM_OP_REMOVE_CRED, cache); + k5_buf_add_uint32_be(&req.reqbuf, map_tcflags(flags)); + k5_marshal_mcred(&req.reqbuf, mcred); + ret = cache_call(context, cache, &req); + kcmreq_free(&req); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +kcm_set_flags(krb5_context context, krb5_ccache cache, krb5_flags flags) +{ + /* We don't currently care about any flags for this type. */ + return 0; +} + +static krb5_error_code KRB5_CALLCONV +kcm_get_flags(krb5_context context, krb5_ccache cache, krb5_flags *flags_out) +{ + /* We don't currently have any operational flags for this type. */ + *flags_out = 0; + return 0; +} + +/* Construct a per-type cursor, always taking ownership of io and uuids. */ +static krb5_error_code +make_ptcursor(const char *residual, struct uuid_list *uuids, struct kcmio *io, + krb5_cc_ptcursor *cursor_out) +{ + krb5_cc_ptcursor cursor = NULL; + struct kcm_ptcursor *data = NULL; + char *residual_copy = NULL; + + *cursor_out = NULL; + + if (residual != NULL) { + residual_copy = strdup(residual); + if (residual_copy == NULL) + goto oom; + } + cursor = malloc(sizeof(*cursor)); + if (cursor == NULL) + goto oom; + data = malloc(sizeof(*data)); + if (data == NULL) + goto oom; + + data->residual = residual_copy; + data->uuids = uuids; + data->io = io; + data->first = TRUE; + cursor->ops = &krb5_kcm_ops; + cursor->data = data; + *cursor_out = cursor; + return 0; + +oom: + kcmio_close(io); + free_uuid_list(uuids); + free(residual_copy); + free(data); + free(cursor); + return ENOMEM; +} + +static krb5_error_code KRB5_CALLCONV +kcm_ptcursor_new(krb5_context context, krb5_cc_ptcursor *cursor_out) +{ + krb5_error_code ret; + struct kcmreq req = EMPTY_KCMREQ; + struct kcmio *io = NULL; + struct uuid_list *uuids = NULL; + const char *defname, *primary; + + *cursor_out = NULL; + + /* Don't try to use KCM for the cache collection unless the default cache + * name has the KCM type. */ + defname = krb5_cc_default_name(context); + if (defname == NULL || strncmp(defname, "KCM:", 4) != 0) + return make_ptcursor(NULL, NULL, NULL, cursor_out); + + ret = kcmio_connect(context, &io); + if (ret) + return ret; + + /* If defname is a subsidiary cache, return a singleton cursor. */ + if (strlen(defname) > 4) + return make_ptcursor(defname + 4, NULL, io, cursor_out); + + kcmreq_init(&req, KCM_OP_GET_CACHE_UUID_LIST, NULL); + ret = kcmio_call(context, io, &req); + if (ret == KRB5_FCC_NOFILE) { + /* There are no accessible caches; return an empty cursor. */ + ret = make_ptcursor(NULL, NULL, NULL, cursor_out); + goto cleanup; + } + if (ret) + goto cleanup; + ret = kcmreq_get_uuid_list(&req, &uuids); + if (ret) + goto cleanup; + + kcmreq_free(&req); + kcmreq_init(&req, KCM_OP_GET_DEFAULT_CACHE, NULL); + ret = kcmio_call(context, io, &req); + if (ret) + goto cleanup; + ret = kcmreq_get_name(&req, &primary); + if (ret) + goto cleanup; + + ret = make_ptcursor(primary, uuids, io, cursor_out); + uuids = NULL; + io = NULL; + +cleanup: + free_uuid_list(uuids); + kcmio_close(io); + kcmreq_free(&req); + return ret; +} + +/* Return true if name is an initialized cache. */ +static krb5_boolean +name_exists(krb5_context context, struct kcmio *io, const char *name) +{ + krb5_error_code ret; + struct kcmreq req; + + kcmreq_init(&req, KCM_OP_GET_PRINCIPAL, NULL); + k5_buf_add_len(&req.reqbuf, name, strlen(name) + 1); + ret = kcmio_call(context, io, &req); + kcmreq_free(&req); + return ret == 0; +} + +static krb5_error_code KRB5_CALLCONV +kcm_ptcursor_next(krb5_context context, krb5_cc_ptcursor cursor, + krb5_ccache *cache_out) +{ + krb5_error_code ret = 0; + struct kcmreq req = EMPTY_KCMREQ; + struct kcm_ptcursor *data = cursor->data; + struct uuid_list *uuids; + const unsigned char *id; + const char *name; + + *cache_out = NULL; + + /* Return the primary or specified subsidiary cache if we haven't yet. */ + if (data->first && data->residual != NULL) { + data->first = FALSE; + if (name_exists(context, data->io, data->residual)) + return make_cache(context, data->residual, NULL, cache_out); + } + + uuids = data->uuids; + if (uuids == NULL) + return 0; + + while (uuids->pos < uuids->count) { + /* Get the name of the next cache. */ + id = &uuids->uuidbytes[KCM_UUID_LEN * uuids->pos++]; + kcmreq_free(&req); + kcmreq_init(&req, KCM_OP_GET_CACHE_BY_UUID, NULL); + k5_buf_add_len(&req.reqbuf, id, KCM_UUID_LEN); + ret = kcmio_call(context, data->io, &req); + /* Continue if the cache has been deleted. */ + if (ret == KRB5_CC_END || ret == KRB5_FCC_NOFILE) { + ret = 0; + continue; + } + if (ret) + goto cleanup; + ret = kcmreq_get_name(&req, &name); + if (ret) + goto cleanup; + + /* Don't yield the primary cache twice. */ + if (strcmp(name, data->residual) == 0) + continue; + + ret = make_cache(context, name, NULL, cache_out); + break; + } + +cleanup: + kcmreq_free(&req); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +kcm_ptcursor_free(krb5_context context, krb5_cc_ptcursor *cursor) +{ + struct kcm_ptcursor *data = (*cursor)->data; + + free(data->residual); + free_uuid_list(data->uuids); + kcmio_close(data->io); + free(data); + free(*cursor); + *cursor = NULL; + return 0; +} + +static krb5_error_code KRB5_CALLCONV +kcm_replace(krb5_context context, krb5_ccache cache, krb5_principal princ, + krb5_creds **creds) +{ + krb5_error_code ret; + struct kcmreq req = EMPTY_KCMREQ; + size_t pos; + uint8_t *lenptr; + int ncreds, i; + krb5_os_context octx = &context->os_context; + int32_t offset; + + kcmreq_init(&req, KCM_OP_REPLACE, cache); + offset = (octx->os_flags & KRB5_OS_TOFFSET_VALID) ? octx->time_offset : 0; + k5_buf_add_uint32_be(&req.reqbuf, offset); + k5_marshal_princ(&req.reqbuf, 4, princ); + for (ncreds = 0; creds[ncreds] != NULL; ncreds++); + k5_buf_add_uint32_be(&req.reqbuf, ncreds); + for (i = 0; creds[i] != NULL; i++) { + /* Store a dummy length, then fix it up after marshalling the cred. */ + pos = req.reqbuf.len; + k5_buf_add_uint32_be(&req.reqbuf, 0); + k5_marshal_cred(&req.reqbuf, 4, creds[i]); + if (k5_buf_status(&req.reqbuf) == 0) { + lenptr = (uint8_t *)req.reqbuf.data + pos; + store_32_be(req.reqbuf.len - (pos + 4), lenptr); + } + } + ret = cache_call(context, cache, &req); + kcmreq_free(&req); + + if (unsupported_op_error(ret)) + return k5_nonatomic_replace(context, cache, princ, creds); + + return ret; +} + +static krb5_error_code KRB5_CALLCONV +kcm_lock(krb5_context context, krb5_ccache cache) +{ + k5_cc_mutex_lock(context, &((struct kcm_cache_data *)cache->data)->lock); + return 0; +} + +static krb5_error_code KRB5_CALLCONV +kcm_unlock(krb5_context context, krb5_ccache cache) +{ + k5_cc_mutex_unlock(context, &((struct kcm_cache_data *)cache->data)->lock); + return 0; +} + +static krb5_error_code KRB5_CALLCONV +kcm_switch_to(krb5_context context, krb5_ccache cache) +{ + krb5_error_code ret; + struct kcmreq req; + + kcmreq_init(&req, KCM_OP_SET_DEFAULT_CACHE, cache); + ret = cache_call(context, cache, &req); + kcmreq_free(&req); + return ret; +} + +const krb5_cc_ops krb5_kcm_ops = { + 0, + "KCM", + kcm_get_name, + kcm_resolve, + kcm_gen_new, + kcm_initialize, + kcm_destroy, + kcm_close, + kcm_store, + kcm_retrieve, + kcm_get_princ, + kcm_start_seq_get, + kcm_next_cred, + kcm_end_seq_get, + kcm_remove_cred, + kcm_set_flags, + kcm_get_flags, + kcm_ptcursor_new, + kcm_ptcursor_next, + kcm_ptcursor_free, + kcm_replace, + NULL, /* wasdefault */ + kcm_lock, + kcm_unlock, + kcm_switch_to, +}; + +#endif /* not _WIN32 */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/cc_keyring.c b/krb5-1.21.3/src/lib/krb5/ccache/cc_keyring.c new file mode 100644 index 00000000..1dadeef6 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/cc_keyring.c @@ -0,0 +1,1749 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/cc_keyring.c */ +/* + * Copyright (c) 2006 + * The Regents of the University of Michigan + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ +/* + * Copyright 1990,1991,1992,1993,1994,2000,2004 Massachusetts Institute of + * Technology. All Rights Reserved. + * + * Original stdio support copyright 1995 by Cygnus Support. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This file implements a collection-enabled credential cache type where the + * credentials are stored in the Linux keyring facility. + * + * A residual of this type can have three forms: + * anchor:collection:subsidiary + * anchor:collection + * collection + * + * The anchor name is "process", "thread", or "legacy" and determines where we + * search for keyring collections. In the third form, the anchor name is + * presumed to be "legacy". The anchor keyring for legacy caches is the + * session keyring. + * + * If the subsidiary name is present, the residual identifies a single cache + * within a collection. Otherwise, the residual identifies the collection + * itself. When a residual identifying a collection is resolved, the + * collection's primary key is looked up (or initialized, using the collection + * name as the subsidiary name), and the resulting cache's name will use the + * first name form and will identify the primary cache. + * + * Keyring collections are named "_krb_" and are linked from the + * anchor keyring. The keys within a keyring collection are links to cache + * keyrings, plus a link to one user key named "krb_ccache:primary" which + * contains a serialized representation of the collection version (currently 1) + * and the primary name of the collection. + * + * Cache keyrings contain one user key per credential which contains a + * serialized representation of the credential. There is also one user key + * named "__krb5_princ__" which contains a serialized representation of the + * cache's default principal. + * + * If the anchor name is "legacy", then the initial primary cache (the one + * named with the collection name) is also linked to the session keyring, and + * we look for a cache in that location when initializing the collection. This + * extra link allows that cache to be visible to old versions of the KEYRING + * cache type, and allows us to see caches created by that code. + */ + +#include "cc-int.h" + +#ifdef USE_KEYRING_CCACHE + +#include +#include + +#ifdef DEBUG +#define KRCC_DEBUG 1 +#endif + +#if KRCC_DEBUG +void debug_print(char *fmt, ...); /* prototype to silence warning */ +#include +#define DEBUG_PRINT(x) debug_print x +void +debug_print(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); +#ifdef DEBUG_STDERR + vfprintf(stderr, fmt, ap); +#else + vsyslog(LOG_ERR, fmt, ap); +#endif + va_end(ap); +} +#else +#define DEBUG_PRINT(x) +#endif + +/* + * We try to use the big_key key type for credentials except in legacy caches. + * We fall back to the user key type if the kernel does not support big_key. + * If the library doesn't support keyctl_get_persistent(), we don't even try + * big_key since the two features were added at the same time. + */ +#ifdef HAVE_PERSISTENT_KEYRING +#define KRCC_CRED_KEY_TYPE "big_key" +#else +#define KRCC_CRED_KEY_TYPE "user" +#endif + +/* + * We use the "user" key type for collection primary names, for cache principal + * names, and for credentials in legacy caches. + */ +#define KRCC_KEY_TYPE_USER "user" + +/* + * We create ccaches as separate keyrings + */ +#define KRCC_KEY_TYPE_KEYRING "keyring" + +/* + * Special name of the key within a ccache keyring + * holding principal information + */ +#define KRCC_SPEC_PRINC_KEYNAME "__krb5_princ__" + +/* + * Special name for the key to communicate the name(s) + * of credentials caches to be used for requests. + * This should currently contain a single name, but + * in the future may contain a list that may be + * intelligently chosen from. + */ +#define KRCC_SPEC_CCACHE_SET_KEYNAME "__krb5_cc_set__" + +/* + * This name identifies the key containing the name of the current primary + * cache within a collection. + */ +#define KRCC_COLLECTION_PRIMARY "krb_ccache:primary" + +/* + * If the library context does not specify a keyring collection, unique ccaches + * will be created within this collection. + */ +#define KRCC_DEFAULT_UNIQUE_COLLECTION "session:__krb5_unique__" + +/* + * Collection keyring names begin with this prefix. We use a prefix so that a + * cache keyring with the collection name itself can be linked directly into + * the anchor, for legacy session keyring compatibility. + */ +#define KRCC_CCCOL_PREFIX "_krb_" + +/* + * For the "persistent" anchor type, we look up or create this fixed keyring + * name within the per-UID persistent keyring. + */ +#define KRCC_PERSISTENT_KEYRING_NAME "_krb" + +/* + * Name of the key holding time offsets for the individual cache + */ +#define KRCC_TIME_OFFSETS "__krb5_time_offsets__" + +/* + * Keyring name prefix and length of random name part + */ +#define KRCC_NAME_PREFIX "krb_ccache_" +#define KRCC_NAME_RAND_CHARS 8 + +#define KRCC_COLLECTION_VERSION 1 + +#define KRCC_PERSISTENT_ANCHOR "persistent" +#define KRCC_PROCESS_ANCHOR "process" +#define KRCC_THREAD_ANCHOR "thread" +#define KRCC_SESSION_ANCHOR "session" +#define KRCC_USER_ANCHOR "user" +#define KRCC_LEGACY_ANCHOR "legacy" + +typedef struct _krcc_cursor +{ + int numkeys; + int currkey; + key_serial_t princ_id; + key_serial_t offsets_id; + key_serial_t *keys; +} *krcc_cursor; + +/* + * This represents a credentials cache "file" + * where cache_id is the keyring serial number for + * this credentials cache "file". Each key + * in the keyring contains a separate key. + */ +typedef struct _krcc_data +{ + char *name; /* Name for this credentials cache */ + k5_cc_mutex lock; /* synchronization */ + key_serial_t collection_id; /* collection containing this cache keyring */ + key_serial_t cache_id; /* keyring representing ccache */ + key_serial_t princ_id; /* key holding principal info */ + krb5_boolean is_legacy_type; +} krcc_data; + +/* Global mutex */ +k5_cc_mutex krb5int_krcc_mutex = K5_CC_MUTEX_PARTIAL_INITIALIZER; + +extern const krb5_cc_ops krb5_krcc_ops; + +static const char *KRB5_CALLCONV +krcc_get_name(krb5_context context, krb5_ccache id); + +static krb5_error_code KRB5_CALLCONV +krcc_start_seq_get(krb5_context, krb5_ccache id, krb5_cc_cursor *cursor); + +static krb5_error_code KRB5_CALLCONV +krcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor, + krb5_creds *creds); + +static krb5_error_code KRB5_CALLCONV +krcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor); + +static krb5_error_code KRB5_CALLCONV +krcc_ptcursor_free(krb5_context context, krb5_cc_ptcursor *cursor); + +static krb5_error_code clear_cache_keyring(krb5_context context, + krb5_ccache id); + +static krb5_error_code make_krcc_data(const char *anchor_name, + const char *collection_name, + const char *subsidiary_name, + key_serial_t cache_id, key_serial_t + collection_id, krcc_data **datapp); + +static krb5_error_code save_principal(krb5_context context, krb5_ccache id, + krb5_principal princ); + +static krb5_error_code save_time_offsets(krb5_context context, krb5_ccache id, + int32_t time_offset, + int32_t usec_offset); + +static krb5_error_code get_time_offsets(krb5_context context, krb5_ccache id, + int32_t *time_offset, + int32_t *usec_offset); + +/* Note the following is a stub function for Linux */ +extern krb5_error_code krb5_change_cache(void); + +/* + * GET_PERSISTENT(uid) acquires the persistent keyring for uid, or falls back + * to the user keyring if uid matches the current effective uid. + */ + +static key_serial_t +get_persistent_fallback(uid_t uid) +{ + return (uid == geteuid()) ? KEY_SPEC_USER_KEYRING : -1; +} + +#ifdef HAVE_PERSISTENT_KEYRING +#define GET_PERSISTENT get_persistent_real +static key_serial_t +get_persistent_real(uid_t uid) +{ + key_serial_t key; + + key = keyctl_get_persistent(uid, KEY_SPEC_PROCESS_KEYRING); + return (key == -1 && errno == ENOTSUP) ? get_persistent_fallback(uid) : + key; +} +#else +#define GET_PERSISTENT get_persistent_fallback +#endif + +/* + * If a process has no explicitly set session keyring, KEY_SPEC_SESSION_KEYRING + * will resolve to the user session keyring for ID lookup and reading, but in + * some kernel versions, writing to that special keyring will instead create a + * new empty session keyring for the process. We do not want that; the keys we + * create would be invisible to other processes. We can work around that + * behavior by explicitly writing to the user session keyring when it matches + * the session keyring. This function returns the keyring we should write to + * for the session anchor. + */ +static key_serial_t +session_write_anchor() +{ + key_serial_t s, u; + + s = keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 0); + u = keyctl_get_keyring_ID(KEY_SPEC_USER_SESSION_KEYRING, 0); + return (s == u) ? KEY_SPEC_USER_SESSION_KEYRING : KEY_SPEC_SESSION_KEYRING; +} + +/* + * Find or create a keyring within parent with the given name. If possess is + * nonzero, also make sure the key is linked from possess. This is necessary + * to ensure that we have possession rights on the key when the parent is the + * user or persistent keyring. + */ +static krb5_error_code +find_or_create_keyring(key_serial_t parent, key_serial_t possess, + const char *name, key_serial_t *key_out) +{ + key_serial_t key; + + *key_out = -1; + key = keyctl_search(parent, KRCC_KEY_TYPE_KEYRING, name, possess); + if (key == -1) { + if (possess != 0) { + key = add_key(KRCC_KEY_TYPE_KEYRING, name, NULL, 0, possess); + if (key == -1) + return errno; + if (keyctl_link(key, parent) == -1) + return errno; + } else { + key = add_key(KRCC_KEY_TYPE_KEYRING, name, NULL, 0, parent); + if (key == -1) + return errno; + } + } + *key_out = key; + return 0; +} + +/* Parse a residual name into an anchor name, a collection name, and possibly a + * subsidiary name. */ +static krb5_error_code +parse_residual(const char *residual, char **anchor_name_out, + char **collection_name_out, char **subsidiary_name_out) +{ + krb5_error_code ret; + char *anchor_name = NULL, *collection_name = NULL, *subsidiary_name = NULL; + const char *sep; + + *anchor_name_out = 0; + *collection_name_out = NULL; + *subsidiary_name_out = NULL; + + /* Parse out the anchor name. Use the legacy anchor if not present. */ + sep = strchr(residual, ':'); + if (sep == NULL) { + anchor_name = strdup(KRCC_LEGACY_ANCHOR); + if (anchor_name == NULL) + goto oom; + } else { + anchor_name = k5memdup0(residual, sep - residual, &ret); + if (anchor_name == NULL) + goto oom; + residual = sep + 1; + } + + /* Parse out the collection and subsidiary name. */ + sep = strchr(residual, ':'); + if (sep == NULL) { + collection_name = strdup(residual); + if (collection_name == NULL) + goto oom; + subsidiary_name = NULL; + } else { + collection_name = k5memdup0(residual, sep - residual, &ret); + if (collection_name == NULL) + goto oom; + subsidiary_name = strdup(sep + 1); + if (subsidiary_name == NULL) + goto oom; + } + + *anchor_name_out = anchor_name; + *collection_name_out = collection_name; + *subsidiary_name_out = subsidiary_name; + return 0; + +oom: + free(anchor_name); + free(collection_name); + free(subsidiary_name); + return ENOMEM; +} + +/* + * Return true if residual identifies a subsidiary cache which should be linked + * into the anchor so it can be visible to old code. This is the case if the + * residual has the legacy anchor and the subsidiary name matches the + * collection name. + */ +static krb5_boolean +is_legacy_cache_name(const char *residual) +{ + const char *sep, *aname, *cname, *sname; + size_t alen, clen, legacy_len = sizeof(KRCC_LEGACY_ANCHOR) - 1; + + /* Get pointers to the anchor, collection, and subsidiary names. */ + aname = residual; + sep = strchr(residual, ':'); + if (sep == NULL) + return FALSE; + alen = sep - aname; + cname = sep + 1; + sep = strchr(cname, ':'); + if (sep == NULL) + return FALSE; + clen = sep - cname; + sname = sep + 1; + + return alen == legacy_len && clen == strlen(sname) && + strncmp(aname, KRCC_LEGACY_ANCHOR, alen) == 0 && + strncmp(cname, sname, clen) == 0; +} + +/* If the default cache name for context is a KEYRING cache, parse its residual + * string. Otherwise set all outputs to NULL. */ +static krb5_error_code +get_default(krb5_context context, char **anchor_name_out, + char **collection_name_out, char **subsidiary_name_out) +{ + const char *defname; + + *anchor_name_out = *collection_name_out = *subsidiary_name_out = NULL; + defname = krb5_cc_default_name(context); + if (defname == NULL || strncmp(defname, "KEYRING:", 8) != 0) + return 0; + return parse_residual(defname + 8, anchor_name_out, collection_name_out, + subsidiary_name_out); +} + +/* Create a residual identifying a subsidiary cache. */ +static krb5_error_code +make_subsidiary_residual(const char *anchor_name, const char *collection_name, + const char *subsidiary_name, char **residual_out) +{ + if (asprintf(residual_out, "%s:%s:%s", anchor_name, collection_name, + subsidiary_name) < 0) { + *residual_out = NULL; + return ENOMEM; + } + return 0; +} + +/* Retrieve or create a keyring for collection_name within the anchor, and set + * *collection_id_out to its serial number. */ +static krb5_error_code +get_collection(const char *anchor_name, const char *collection_name, + key_serial_t *collection_id_out) +{ + krb5_error_code ret; + key_serial_t persistent_id, anchor_id, possess_id = 0; + char *ckname, *cnend; + long uidnum; + + *collection_id_out = 0; + + if (strcmp(anchor_name, KRCC_PERSISTENT_ANCHOR) == 0) { + /* + * The collection name is a uid (or empty for the current effective + * uid), and we look up a fixed keyring name within the persistent + * keyring for that uid. We link it to the process keyring to ensure + * that we have possession rights on the collection key. + */ + if (*collection_name != '\0') { + errno = 0; + uidnum = strtol(collection_name, &cnend, 10); + if (errno || *cnend != '\0') + return KRB5_KCC_INVALID_UID; + } else { + uidnum = geteuid(); + } + persistent_id = GET_PERSISTENT(uidnum); + if (persistent_id == -1) + return KRB5_KCC_INVALID_UID; + return find_or_create_keyring(persistent_id, KEY_SPEC_PROCESS_KEYRING, + KRCC_PERSISTENT_KEYRING_NAME, + collection_id_out); + } + + if (strcmp(anchor_name, KRCC_PROCESS_ANCHOR) == 0) { + anchor_id = KEY_SPEC_PROCESS_KEYRING; + } else if (strcmp(anchor_name, KRCC_THREAD_ANCHOR) == 0) { + anchor_id = KEY_SPEC_THREAD_KEYRING; + } else if (strcmp(anchor_name, KRCC_SESSION_ANCHOR) == 0) { + anchor_id = session_write_anchor(); + } else if (strcmp(anchor_name, KRCC_USER_ANCHOR) == 0) { + /* The user keyring does not confer possession, so we need to link the + * collection to the process keyring to maintain possession rights. */ + anchor_id = KEY_SPEC_USER_KEYRING; + possess_id = KEY_SPEC_PROCESS_KEYRING; + } else if (strcmp(anchor_name, KRCC_LEGACY_ANCHOR) == 0) { + anchor_id = session_write_anchor(); + } else { + return KRB5_KCC_INVALID_ANCHOR; + } + + /* Look up the collection keyring name within the anchor keyring. */ + if (asprintf(&ckname, "%s%s", KRCC_CCCOL_PREFIX, collection_name) == -1) + return ENOMEM; + ret = find_or_create_keyring(anchor_id, possess_id, ckname, + collection_id_out); + free(ckname); + return ret; +} + +/* Store subsidiary_name into the primary index key for collection_id. */ +static krb5_error_code +set_primary_name(krb5_context context, key_serial_t collection_id, + const char *subsidiary_name) +{ + key_serial_t key; + uint32_t len = strlen(subsidiary_name), plen = 8 + len; + unsigned char *payload; + + payload = malloc(plen); + if (payload == NULL) + return ENOMEM; + store_32_be(KRCC_COLLECTION_VERSION, payload); + store_32_be(len, payload + 4); + memcpy(payload + 8, subsidiary_name, len); + key = add_key(KRCC_KEY_TYPE_USER, KRCC_COLLECTION_PRIMARY, + payload, plen, collection_id); + free(payload); + return (key == -1) ? errno : 0; +} + +static krb5_error_code +parse_index(krb5_context context, int32_t *version, char **primary, + const unsigned char *payload, size_t psize) +{ + krb5_error_code ret; + uint32_t len; + + if (psize < 8) + return KRB5_CC_END; + + *version = load_32_be(payload); + len = load_32_be(payload + 4); + if (len > psize - 8) + return KRB5_CC_END; + *primary = k5memdup0(payload + 8, len, &ret); + return (*primary == NULL) ? ret : 0; +} + +/* + * Get or initialize the primary name within collection_id and set + * *subsidiary_out to its value. If initializing a legacy collection, look + * for a legacy cache and add it to the collection. + */ +static krb5_error_code +get_primary_name(krb5_context context, const char *anchor_name, + const char *collection_name, key_serial_t collection_id, + char **subsidiary_out) +{ + krb5_error_code ret; + key_serial_t primary_id, legacy; + void *payload = NULL; + int payloadlen; + int32_t version; + char *subsidiary_name = NULL; + + *subsidiary_out = NULL; + + primary_id = keyctl_search(collection_id, KRCC_KEY_TYPE_USER, + KRCC_COLLECTION_PRIMARY, 0); + if (primary_id == -1) { + /* Initialize the primary key using the collection name. We can't name + * a key with the empty string, so map that to an arbitrary string. */ + subsidiary_name = strdup((*collection_name == '\0') ? "tkt" : + collection_name); + if (subsidiary_name == NULL) { + ret = ENOMEM; + goto cleanup; + } + ret = set_primary_name(context, collection_id, subsidiary_name); + if (ret) + goto cleanup; + + if (strcmp(anchor_name, KRCC_LEGACY_ANCHOR) == 0) { + /* Look for a cache created by old code. If we find one, add it to + * the collection. */ + legacy = keyctl_search(KEY_SPEC_SESSION_KEYRING, + KRCC_KEY_TYPE_KEYRING, subsidiary_name, 0); + if (legacy != -1 && keyctl_link(legacy, collection_id) == -1) { + ret = errno; + goto cleanup; + } + } + } else { + /* Read, parse, and free the primary key's payload. */ + payloadlen = keyctl_read_alloc(primary_id, &payload); + if (payloadlen == -1) { + ret = errno; + goto cleanup; + } + ret = parse_index(context, &version, &subsidiary_name, payload, + payloadlen); + if (ret) + goto cleanup; + + if (version != KRCC_COLLECTION_VERSION) { + ret = KRB5_KCC_UNKNOWN_VERSION; + goto cleanup; + } + } + + *subsidiary_out = subsidiary_name; + subsidiary_name = NULL; + +cleanup: + free(payload); + free(subsidiary_name); + return ret; +} + +/* + * Create a keyring with a unique random name within collection_id. Set + * *subsidiary to its name and *cache_id_out to its key serial number. + */ +static krb5_error_code +unique_keyring(krb5_context context, key_serial_t collection_id, + char **subsidiary_out, key_serial_t *cache_id_out) +{ + key_serial_t key; + krb5_error_code ret; + char uniquename[sizeof(KRCC_NAME_PREFIX) + KRCC_NAME_RAND_CHARS]; + int prefixlen = sizeof(KRCC_NAME_PREFIX) - 1; + int tries; + + *subsidiary_out = NULL; + *cache_id_out = 0; + + memcpy(uniquename, KRCC_NAME_PREFIX, sizeof(KRCC_NAME_PREFIX)); + k5_cc_mutex_lock(context, &krb5int_krcc_mutex); + + /* Loop until we successfully create a new ccache keyring with + * a unique name, or we get an error. Limit to 100 tries. */ + tries = 100; + while (tries-- > 0) { + ret = krb5int_random_string(context, uniquename + prefixlen, + KRCC_NAME_RAND_CHARS); + if (ret) + goto cleanup; + + key = keyctl_search(collection_id, KRCC_KEY_TYPE_KEYRING, uniquename, + 0); + if (key < 0) { + /* Name does not already exist. Create it to reserve the name. */ + key = add_key(KRCC_KEY_TYPE_KEYRING, uniquename, NULL, 0, + collection_id); + if (key < 0) { + ret = errno; + goto cleanup; + } + break; + } + } + + if (tries <= 0) { + ret = KRB5_CC_BADNAME; + goto cleanup; + } + + *subsidiary_out = strdup(uniquename); + if (*subsidiary_out == NULL) { + ret = ENOMEM; + goto cleanup; + } + *cache_id_out = key; + ret = 0; +cleanup: + k5_cc_mutex_unlock(context, &krb5int_krcc_mutex); + return ret; +} + +static krb5_error_code +add_cred_key(const char *name, const void *payload, size_t plen, + key_serial_t cache_id, krb5_boolean legacy_type, + key_serial_t *key_out) +{ + key_serial_t key; + + *key_out = -1; + if (!legacy_type) { + /* Try the preferred cred key type; fall back if no kernel support. */ + key = add_key(KRCC_CRED_KEY_TYPE, name, payload, plen, cache_id); + if (key != -1) { + *key_out = key; + return 0; + } else if (errno != EINVAL && errno != ENODEV) { + return errno; + } + } + /* Use the user key type. */ + key = add_key(KRCC_KEY_TYPE_USER, name, payload, plen, cache_id); + if (key == -1) + return errno; + *key_out = key; + return 0; +} + +static void +update_keyring_expiration(krb5_context context, krb5_ccache id) +{ + krcc_data *data = id->data; + krb5_cc_cursor cursor; + krb5_creds creds; + krb5_timestamp now, endtime = 0; + unsigned int timeout; + + /* + * We have no way to know what is the actual timeout set on the keyring. + * We also cannot keep track of it in a local variable as another process + * can always modify the keyring independently, so just always enumerate + * all keys and find out the highest endtime time. + */ + + /* Find the maximum endtime of all creds in the cache. */ + if (krcc_start_seq_get(context, id, &cursor) != 0) + return; + for (;;) { + if (krcc_next_cred(context, id, &cursor, &creds) != 0) + break; + if (ts_after(creds.times.endtime, endtime)) + endtime = creds.times.endtime; + krb5_free_cred_contents(context, &creds); + } + (void)krcc_end_seq_get(context, id, &cursor); + + if (endtime == 0) /* No creds with end times */ + return; + + if (krb5_timeofday(context, &now) != 0) + return; + + /* Setting the timeout to zero would reset the timeout, so we set it to one + * second instead if creds are already expired. */ + timeout = ts_after(endtime, now) ? ts_interval(now, endtime) : 1; + (void)keyctl_set_timeout(data->cache_id, timeout); +} + +/* Create or overwrite the cache keyring, and set the default principal. */ +static krb5_error_code KRB5_CALLCONV +krcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ) +{ + krcc_data *data = (krcc_data *)id->data; + krb5_os_context os_ctx = &context->os_context; + krb5_error_code ret; + const char *cache_name, *p; + + k5_cc_mutex_lock(context, &data->lock); + + ret = clear_cache_keyring(context, id); + if (ret) + goto out; + + if (!data->cache_id) { + /* The key didn't exist at resolve time. Check again and create the + * key if it still isn't there. */ + p = strrchr(data->name, ':'); + cache_name = (p != NULL) ? p + 1 : data->name; + ret = find_or_create_keyring(data->collection_id, 0, cache_name, + &data->cache_id); + if (ret) + goto out; + } + + /* If this is the legacy cache in a legacy session collection, link it + * directly to the session keyring so that old code can see it. */ + if (is_legacy_cache_name(data->name)) + (void)keyctl_link(data->cache_id, session_write_anchor()); + + ret = save_principal(context, id, princ); + + /* Save time offset if it is valid and this is not a legacy cache. Legacy + * applications would fail to parse the new key in the cache keyring. */ + if (!is_legacy_cache_name(data->name) && + (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID)) { + ret = save_time_offsets(context, id, os_ctx->time_offset, + os_ctx->usec_offset); + } + + if (ret == 0) + krb5_change_cache(); + +out: + k5_cc_mutex_unlock(context, &data->lock); + return ret; +} + +/* Release the ccache handle. */ +static krb5_error_code KRB5_CALLCONV +krcc_close(krb5_context context, krb5_ccache id) +{ + krcc_data *data = id->data; + + k5_cc_mutex_destroy(&data->lock); + free(data->name); + free(data); + free(id); + return 0; +} + +/* Clear out a ccache keyring, unlinking all keys within it. Call with the + * mutex locked. */ +static krb5_error_code +clear_cache_keyring(krb5_context context, krb5_ccache id) +{ + krcc_data *data = id->data; + int res; + + k5_cc_mutex_assert_locked(context, &data->lock); + + DEBUG_PRINT(("clear_cache_keyring: cache_id %d, princ_id %d\n", + data->cache_id, data->princ_id)); + + if (data->cache_id) { + res = keyctl_clear(data->cache_id); + if (res != 0) + return errno; + } + data->princ_id = 0; + + return 0; +} + +/* Destroy the cache keyring and release the handle. */ +static krb5_error_code KRB5_CALLCONV +krcc_destroy(krb5_context context, krb5_ccache id) +{ + krb5_error_code ret = 0; + krcc_data *data = id->data; + int res; + + k5_cc_mutex_lock(context, &data->lock); + + clear_cache_keyring(context, id); + if (data->cache_id) { + res = keyctl_unlink(data->cache_id, data->collection_id); + if (res < 0) { + ret = errno; + DEBUG_PRINT(("unlinking key %d from ring %d: %s", data->cache_id, + data->collection_id, error_message(errno))); + } + /* If this is a legacy cache, unlink it from the session anchor. */ + if (is_legacy_cache_name(data->name)) + (void)keyctl_unlink(data->cache_id, session_write_anchor()); + } + + k5_cc_mutex_unlock(context, &data->lock); + k5_cc_mutex_destroy(&data->lock); + free(data->name); + free(data); + free(id); + krb5_change_cache(); + return ret; +} + +/* Create a cache handle for a cache ID. */ +static krb5_error_code +make_cache(krb5_context context, key_serial_t collection_id, + key_serial_t cache_id, const char *anchor_name, + const char *collection_name, const char *subsidiary_name, + krb5_ccache *cache_out) +{ + krb5_error_code ret; + krb5_os_context os_ctx = &context->os_context; + krb5_ccache ccache = NULL; + krcc_data *data; + key_serial_t pkey = 0; + + /* Determine the key containing principal information, if present. */ + pkey = keyctl_search(cache_id, KRCC_KEY_TYPE_USER, KRCC_SPEC_PRINC_KEYNAME, + 0); + if (pkey < 0) + pkey = 0; + + ccache = malloc(sizeof(struct _krb5_ccache)); + if (!ccache) + return ENOMEM; + + ret = make_krcc_data(anchor_name, collection_name, subsidiary_name, + cache_id, collection_id, &data); + if (ret) { + free(ccache); + return ret; + } + + data->princ_id = pkey; + ccache->ops = &krb5_krcc_ops; + ccache->data = data; + ccache->magic = KV5M_CCACHE; + *cache_out = ccache; + + /* Look up time offsets if necessary. */ + if ((context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) && + !(os_ctx->os_flags & KRB5_OS_TOFFSET_VALID)) { + if (get_time_offsets(context, ccache, &os_ctx->time_offset, + &os_ctx->usec_offset) == 0) { + os_ctx->os_flags &= ~KRB5_OS_TOFFSET_TIME; + os_ctx->os_flags |= KRB5_OS_TOFFSET_VALID; + } + } + + return 0; +} + +/* Create a keyring ccache handle for the given residual string. */ +static krb5_error_code KRB5_CALLCONV +krcc_resolve(krb5_context context, krb5_ccache *id, const char *residual) +{ + krb5_error_code ret; + key_serial_t collection_id, cache_id; + char *anchor_name = NULL, *collection_name = NULL, *subsidiary_name = NULL; + + ret = parse_residual(residual, &anchor_name, &collection_name, + &subsidiary_name); + if (ret) + goto cleanup; + ret = get_collection(anchor_name, collection_name, &collection_id); + if (ret) + goto cleanup; + + if (subsidiary_name == NULL) { + /* Retrieve or initialize the primary name for the collection. */ + ret = get_primary_name(context, anchor_name, collection_name, + collection_id, &subsidiary_name); + if (ret) + goto cleanup; + } + + /* Look up the cache keyring ID, if the cache is already initialized. */ + cache_id = keyctl_search(collection_id, KRCC_KEY_TYPE_KEYRING, + subsidiary_name, 0); + if (cache_id < 0) + cache_id = 0; + + ret = make_cache(context, collection_id, cache_id, anchor_name, + collection_name, subsidiary_name, id); + if (ret) + goto cleanup; + +cleanup: + free(anchor_name); + free(collection_name); + free(subsidiary_name); + return ret; +} + +/* Prepare for a sequential iteration over the cache keyring. */ +static krb5_error_code KRB5_CALLCONV +krcc_start_seq_get(krb5_context context, krb5_ccache id, + krb5_cc_cursor *cursor) +{ + krcc_cursor krcursor; + krcc_data *data = id->data; + void *keys; + long size; + + k5_cc_mutex_lock(context, &data->lock); + + if (!data->cache_id) { + k5_cc_mutex_unlock(context, &data->lock); + return KRB5_FCC_NOFILE; + } + + size = keyctl_read_alloc(data->cache_id, &keys); + if (size == -1) { + DEBUG_PRINT(("Error getting from keyring: %s\n", strerror(errno))); + k5_cc_mutex_unlock(context, &data->lock); + return KRB5_CC_IO; + } + + krcursor = calloc(1, sizeof(*krcursor)); + if (krcursor == NULL) { + free(keys); + k5_cc_mutex_unlock(context, &data->lock); + return KRB5_CC_NOMEM; + } + + krcursor->princ_id = data->princ_id; + krcursor->offsets_id = keyctl_search(data->cache_id, KRCC_KEY_TYPE_USER, + KRCC_TIME_OFFSETS, 0); + krcursor->numkeys = size / sizeof(key_serial_t); + krcursor->keys = keys; + + k5_cc_mutex_unlock(context, &data->lock); + *cursor = krcursor; + return 0; +} + +/* Get the next credential from the cache keyring. */ +static krb5_error_code KRB5_CALLCONV +krcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + krcc_cursor krcursor; + krb5_error_code ret; + int psize; + void *payload = NULL; + + memset(creds, 0, sizeof(krb5_creds)); + + /* The cursor has the entire list of keys. */ + krcursor = *cursor; + if (krcursor == NULL) + return KRB5_CC_END; + + while (krcursor->currkey < krcursor->numkeys) { + /* If we're pointing at the entry with the principal, or at the key + * with the time offsets, skip it. */ + if (krcursor->keys[krcursor->currkey] == krcursor->princ_id || + krcursor->keys[krcursor->currkey] == krcursor->offsets_id) { + krcursor->currkey++; + continue; + } + + /* Read the key; the right size buffer will be allocated and + * returned. */ + psize = keyctl_read_alloc(krcursor->keys[krcursor->currkey], + &payload); + if (psize != -1) { + krcursor->currkey++; + + /* Unmarshal the cred using the file ccache version 4 format. */ + ret = k5_unmarshal_cred(payload, psize, 4, creds); + free(payload); + return ret; + } else if (errno != ENOKEY && errno != EACCES) { + DEBUG_PRINT(("Error reading key %d: %s\n", + krcursor->keys[krcursor->currkey], strerror(errno))); + return KRB5_FCC_NOFILE; + } + + /* The current key was unlinked, probably by a remove_cred call; move + * on to the next one. */ + krcursor->currkey++; + } + + /* No more keys in keyring. */ + return KRB5_CC_END; +} + +/* Release an iteration cursor. */ +static krb5_error_code KRB5_CALLCONV +krcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor) +{ + krcc_cursor krcursor = *cursor; + + if (krcursor != NULL) { + free(krcursor->keys); + free(krcursor); + } + *cursor = NULL; + return 0; +} + +/* Create keyring data for a credential cache. */ +static krb5_error_code +make_krcc_data(const char *anchor_name, const char *collection_name, + const char *subsidiary_name, key_serial_t cache_id, + key_serial_t collection_id, krcc_data **data_out) +{ + krb5_error_code ret; + krcc_data *data; + + *data_out = NULL; + + data = malloc(sizeof(krcc_data)); + if (data == NULL) + return KRB5_CC_NOMEM; + + ret = k5_cc_mutex_init(&data->lock); + if (ret) { + free(data); + return ret; + } + + ret = make_subsidiary_residual(anchor_name, collection_name, + subsidiary_name, &data->name); + if (ret) { + k5_cc_mutex_destroy(&data->lock); + free(data); + return ret; + } + data->princ_id = 0; + data->cache_id = cache_id; + data->collection_id = collection_id; + data->is_legacy_type = (strcmp(anchor_name, KRCC_LEGACY_ANCHOR) == 0); + + *data_out = data; + return 0; +} + +/* Create a new keyring cache with a unique name. */ +static krb5_error_code KRB5_CALLCONV +krcc_generate_new(krb5_context context, krb5_ccache *id_out) +{ + krb5_ccache id = NULL; + krb5_error_code ret; + char *anchor_name = NULL, *collection_name = NULL, *subsidiary_name = NULL; + char *new_subsidiary_name = NULL, *new_residual = NULL; + krcc_data *data; + key_serial_t collection_id; + key_serial_t cache_id = 0; + + *id_out = NULL; + + /* Determine the collection in which we will create the cache.*/ + ret = get_default(context, &anchor_name, &collection_name, + &subsidiary_name); + if (ret) + return ret; + if (anchor_name == NULL) { + ret = parse_residual(KRCC_DEFAULT_UNIQUE_COLLECTION, &anchor_name, + &collection_name, &subsidiary_name); + if (ret) + return ret; + } + if (subsidiary_name != NULL) { + k5_setmsg(context, KRB5_DCC_CANNOT_CREATE, + _("Can't create new subsidiary cache because default cache " + "is already a subsidiary")); + ret = KRB5_DCC_CANNOT_CREATE; + goto cleanup; + } + + /* Allocate memory */ + id = malloc(sizeof(struct _krb5_ccache)); + if (id == NULL) { + ret = ENOMEM; + goto cleanup; + } + + id->ops = &krb5_krcc_ops; + + /* Make a unique keyring within the chosen collection. */ + ret = get_collection(anchor_name, collection_name, &collection_id); + if (ret) + goto cleanup; + ret = unique_keyring(context, collection_id, &new_subsidiary_name, + &cache_id); + if (ret) + goto cleanup; + + ret = make_krcc_data(anchor_name, collection_name, new_subsidiary_name, + cache_id, collection_id, &data); + if (ret) + goto cleanup; + + id->data = data; + krb5_change_cache(); + +cleanup: + free(anchor_name); + free(collection_name); + free(subsidiary_name); + free(new_subsidiary_name); + free(new_residual); + if (ret) { + free(id); + return ret; + } + *id_out = id; + return 0; +} + +/* Return an alias to the residual string of the cache. */ +static const char *KRB5_CALLCONV +krcc_get_name(krb5_context context, krb5_ccache id) +{ + return ((krcc_data *)id->data)->name; +} + +/* Retrieve a copy of the default principal, if the cache is initialized. */ +static krb5_error_code KRB5_CALLCONV +krcc_get_principal(krb5_context context, krb5_ccache id, + krb5_principal *princ_out) +{ + krcc_data *data = id->data; + krb5_error_code ret; + void *payload = NULL; + int psize; + + *princ_out = NULL; + k5_cc_mutex_lock(context, &data->lock); + + if (!data->cache_id || !data->princ_id) { + ret = KRB5_FCC_NOFILE; + k5_setmsg(context, ret, _("Credentials cache keyring '%s' not found"), + data->name); + goto errout; + } + + psize = keyctl_read_alloc(data->princ_id, &payload); + if (psize == -1) { + DEBUG_PRINT(("Reading principal key %d: %s\n", + data->princ_id, strerror(errno))); + ret = KRB5_CC_IO; + goto errout; + } + + /* Unmarshal the principal using the file ccache version 4 format. */ + ret = k5_unmarshal_princ(payload, psize, 4, princ_out); + +errout: + free(payload); + k5_cc_mutex_unlock(context, &data->lock); + return ret; +} + +/* Search for a credential within the cache keyring. */ +static krb5_error_code KRB5_CALLCONV +krcc_retrieve(krb5_context context, krb5_ccache id, + krb5_flags whichfields, krb5_creds *mcreds, + krb5_creds *creds) +{ + return k5_cc_retrieve_cred_default(context, id, whichfields, mcreds, + creds); +} + +/* Remove a credential from the cache keyring. */ +static krb5_error_code KRB5_CALLCONV +krcc_remove_cred(krb5_context context, krb5_ccache cache, + krb5_flags flags, krb5_creds *creds) +{ + krb5_error_code ret; + krcc_data *data = cache->data; + krb5_cc_cursor cursor; + krb5_creds c; + krcc_cursor krcursor; + key_serial_t key; + krb5_boolean match; + + ret = krcc_start_seq_get(context, cache, &cursor); + if (ret) + return ret; + + for (;;) { + ret = krcc_next_cred(context, cache, &cursor, &c); + if (ret) + break; + match = krb5int_cc_creds_match_request(context, flags, creds, &c); + krb5_free_cred_contents(context, &c); + if (match) { + krcursor = cursor; + key = krcursor->keys[krcursor->currkey - 1]; + if (keyctl_unlink(key, data->cache_id) == -1) { + ret = errno; + break; + } + } + } + + krcc_end_seq_get(context, cache, &cursor); + return (ret == KRB5_CC_END) ? 0 : ret; +} + +/* Set flags on the cache. (We don't care about any flags.) */ +static krb5_error_code KRB5_CALLCONV +krcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags) +{ + return 0; +} + +/* Get the current operational flags (of which we have none) for the cache. */ +static krb5_error_code KRB5_CALLCONV +krcc_get_flags(krb5_context context, krb5_ccache id, krb5_flags *flags_out) +{ + *flags_out = 0; + return 0; +} + +/* Store a credential in the cache keyring. */ +static krb5_error_code KRB5_CALLCONV +krcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds) +{ + krb5_error_code ret; + krcc_data *data = id->data; + struct k5buf buf = EMPTY_K5BUF; + char *keyname = NULL; + key_serial_t cred_key; + krb5_timestamp now; + + k5_cc_mutex_lock(context, &data->lock); + + if (!data->cache_id) { + k5_cc_mutex_unlock(context, &data->lock); + return KRB5_FCC_NOFILE; + } + + /* Get the service principal name and use it as the key name */ + ret = krb5_unparse_name(context, creds->server, &keyname); + if (ret) + goto errout; + + /* Serialize credential using the file ccache version 4 format. */ + k5_buf_init_dynamic_zap(&buf); + k5_marshal_cred(&buf, 4, creds); + ret = k5_buf_status(&buf); + if (ret) + goto errout; + + /* Add new key (credentials) into keyring */ + DEBUG_PRINT(("krcc_store: adding new key '%s' to keyring %d\n", + keyname, data->cache_id)); + ret = add_cred_key(keyname, buf.data, buf.len, data->cache_id, + data->is_legacy_type, &cred_key); + if (ret) + goto errout; + + /* Set appropriate timeouts on cache keys. */ + ret = krb5_timeofday(context, &now); + if (ret) + goto errout; + + if (ts_after(creds->times.endtime, now)) { + (void)keyctl_set_timeout(cred_key, + ts_interval(now, creds->times.endtime)); + } + + update_keyring_expiration(context, id); + +errout: + k5_buf_free(&buf); + krb5_free_unparsed_name(context, keyname); + k5_cc_mutex_unlock(context, &data->lock); + return ret; +} + +/* Lock the cache handle against other threads. (This does not lock the cache + * keyring against other processes.) */ +static krb5_error_code KRB5_CALLCONV +krcc_lock(krb5_context context, krb5_ccache id) +{ + krcc_data *data = id->data; + + k5_cc_mutex_lock(context, &data->lock); + return 0; +} + +/* Unlock the cache handle. */ +static krb5_error_code KRB5_CALLCONV +krcc_unlock(krb5_context context, krb5_ccache id) +{ + krcc_data *data = id->data; + + k5_cc_mutex_unlock(context, &data->lock); + return 0; +} + +static krb5_error_code +save_principal(krb5_context context, krb5_ccache id, krb5_principal princ) +{ + krcc_data *data = id->data; + krb5_error_code ret; + struct k5buf buf; + key_serial_t newkey; + + k5_cc_mutex_assert_locked(context, &data->lock); + + /* Serialize princ using the file ccache version 4 format. */ + k5_buf_init_dynamic(&buf); + k5_marshal_princ(&buf, 4, princ); + if (k5_buf_status(&buf) != 0) + return ENOMEM; + + /* Add new key into keyring */ +#ifdef KRCC_DEBUG + { + krb5_error_code rc; + char *princname = NULL; + rc = krb5_unparse_name(context, princ, &princname); + DEBUG_PRINT(("save_principal: adding new key '%s' " + "to keyring %d for principal '%s'\n", + KRCC_SPEC_PRINC_KEYNAME, data->cache_id, + rc ? "" : princname)); + if (rc == 0) + krb5_free_unparsed_name(context, princname); + } +#endif + newkey = add_key(KRCC_KEY_TYPE_USER, KRCC_SPEC_PRINC_KEYNAME, buf.data, + buf.len, data->cache_id); + if (newkey < 0) { + ret = errno; + DEBUG_PRINT(("Error adding principal key: %s\n", strerror(ret))); + } else { + data->princ_id = newkey; + ret = 0; + } + + k5_buf_free(&buf); + return ret; +} + +/* Add a key to the cache keyring containing the given time offsets. */ +static krb5_error_code +save_time_offsets(krb5_context context, krb5_ccache id, int32_t time_offset, + int32_t usec_offset) +{ + krcc_data *data = id->data; + key_serial_t newkey; + unsigned char payload[8]; + + k5_cc_mutex_assert_locked(context, &data->lock); + + /* Prepare the payload. */ + store_32_be(time_offset, payload); + store_32_be(usec_offset, payload + 4); + + /* Add new key into keyring. */ + newkey = add_key(KRCC_KEY_TYPE_USER, KRCC_TIME_OFFSETS, payload, 8, + data->cache_id); + if (newkey == -1) + return errno; + return 0; +} + +/* Retrieve and parse the key in the cache keyring containing time offsets. */ +static krb5_error_code +get_time_offsets(krb5_context context, krb5_ccache id, int32_t *time_offset, + int32_t *usec_offset) +{ + krcc_data *data = id->data; + krb5_error_code ret = 0; + key_serial_t key; + void *payload = NULL; + int psize; + + k5_cc_mutex_lock(context, &data->lock); + + if (!data->cache_id) { + ret = KRB5_FCC_NOFILE; + goto errout; + } + + key = keyctl_search(data->cache_id, KRCC_KEY_TYPE_USER, KRCC_TIME_OFFSETS, + 0); + if (key == -1) { + ret = ENOENT; + goto errout; + } + + psize = keyctl_read_alloc(key, &payload); + if (psize == -1) { + DEBUG_PRINT(("Reading time offsets key %d: %s\n", + key, strerror(errno))); + ret = KRB5_CC_IO; + goto errout; + } + + if (psize < 8) { + ret = KRB5_CC_END; + goto errout; + } + *time_offset = load_32_be(payload); + *usec_offset = load_32_be((char *)payload + 4); + +errout: + free(payload); + k5_cc_mutex_unlock(context, &data->lock); + return ret; +} + +struct krcc_ptcursor_data { + key_serial_t collection_id; + char *anchor_name; + char *collection_name; + char *subsidiary_name; + char *primary_name; + krb5_boolean first; + long num_keys; + long next_key; + key_serial_t *keys; +}; + +static krb5_error_code KRB5_CALLCONV +krcc_ptcursor_new(krb5_context context, krb5_cc_ptcursor *cursor_out) +{ + struct krcc_ptcursor_data *ptd; + krb5_cc_ptcursor cursor; + krb5_error_code ret; + void *keys; + long size; + + *cursor_out = NULL; + + cursor = k5alloc(sizeof(*cursor), &ret); + if (cursor == NULL) + return ENOMEM; + ptd = k5alloc(sizeof(*ptd), &ret); + if (ptd == NULL) + goto error; + cursor->ops = &krb5_krcc_ops; + cursor->data = ptd; + ptd->first = TRUE; + + ret = get_default(context, &ptd->anchor_name, &ptd->collection_name, + &ptd->subsidiary_name); + if (ret) + goto error; + + /* If there is no default collection, return an empty cursor. */ + if (ptd->anchor_name == NULL) { + *cursor_out = cursor; + return 0; + } + + ret = get_collection(ptd->anchor_name, ptd->collection_name, + &ptd->collection_id); + if (ret) + goto error; + + if (ptd->subsidiary_name == NULL) { + ret = get_primary_name(context, ptd->anchor_name, + ptd->collection_name, ptd->collection_id, + &ptd->primary_name); + if (ret) + goto error; + + size = keyctl_read_alloc(ptd->collection_id, &keys); + if (size == -1) { + ret = errno; + goto error; + } + ptd->keys = keys; + ptd->num_keys = size / sizeof(key_serial_t); + } + + *cursor_out = cursor; + return 0; + +error: + krcc_ptcursor_free(context, &cursor); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +krcc_ptcursor_next(krb5_context context, krb5_cc_ptcursor cursor, + krb5_ccache *cache_out) +{ + krb5_error_code ret; + struct krcc_ptcursor_data *ptd = cursor->data; + key_serial_t key, cache_id = 0; + const char *first_name, *keytype, *sep, *subsidiary_name; + size_t keytypelen; + char *description = NULL; + + *cache_out = NULL; + + /* No keyring available */ + if (ptd->collection_id == 0) + return 0; + + if (ptd->first) { + /* Look for the primary cache for a collection cursor, or the + * subsidiary cache for a subsidiary cursor. */ + ptd->first = FALSE; + first_name = (ptd->primary_name != NULL) ? ptd->primary_name : + ptd->subsidiary_name; + cache_id = keyctl_search(ptd->collection_id, KRCC_KEY_TYPE_KEYRING, + first_name, 0); + if (cache_id != -1) { + return make_cache(context, ptd->collection_id, cache_id, + ptd->anchor_name, ptd->collection_name, + first_name, cache_out); + } + } + + /* A subsidiary cursor yields at most the first cache. */ + if (ptd->subsidiary_name != NULL) + return 0; + + keytype = KRCC_KEY_TYPE_KEYRING ";"; + keytypelen = strlen(keytype); + + for (; ptd->next_key < ptd->num_keys; ptd->next_key++) { + /* Free any previously retrieved key description. */ + free(description); + description = NULL; + + /* + * Get the key description, which should have the form: + * typename;UID;GID;permissions;description + */ + key = ptd->keys[ptd->next_key]; + if (keyctl_describe_alloc(key, &description) < 0) + continue; + sep = strrchr(description, ';'); + if (sep == NULL) + continue; + subsidiary_name = sep + 1; + + /* Skip this key if it isn't a keyring. */ + if (strncmp(description, keytype, keytypelen) != 0) + continue; + + /* Don't repeat the primary cache. */ + if (strcmp(subsidiary_name, ptd->primary_name) == 0) + continue; + + /* We found a valid key */ + ptd->next_key++; + ret = make_cache(context, ptd->collection_id, key, ptd->anchor_name, + ptd->collection_name, subsidiary_name, cache_out); + free(description); + return ret; + } + + free(description); + return 0; +} + +static krb5_error_code KRB5_CALLCONV +krcc_ptcursor_free(krb5_context context, krb5_cc_ptcursor *cursor) +{ + struct krcc_ptcursor_data *ptd = (*cursor)->data; + + if (ptd != NULL) { + free(ptd->anchor_name); + free(ptd->collection_name); + free(ptd->subsidiary_name); + free(ptd->primary_name); + free(ptd->keys); + free(ptd); + } + free(*cursor); + *cursor = NULL; + return 0; +} + +static krb5_error_code KRB5_CALLCONV +krcc_switch_to(krb5_context context, krb5_ccache cache) +{ + krcc_data *data = cache->data; + krb5_error_code ret; + char *anchor_name = NULL, *collection_name = NULL, *subsidiary_name = NULL; + key_serial_t collection_id; + + ret = parse_residual(data->name, &anchor_name, &collection_name, + &subsidiary_name); + if (ret) + goto cleanup; + ret = get_collection(anchor_name, collection_name, &collection_id); + if (ret) + goto cleanup; + ret = set_primary_name(context, collection_id, subsidiary_name); + +cleanup: + free(anchor_name); + free(collection_name); + free(subsidiary_name); + return ret; +} + +/* + * ccache implementation storing credentials in the Linux keyring facility + * The default is to put them at the session keyring level. + * If "KEYRING:process:" or "KEYRING:thread:" is specified, then they will + * be stored at the process or thread level respectively. + */ +const krb5_cc_ops krb5_krcc_ops = { + 0, + "KEYRING", + krcc_get_name, + krcc_resolve, + krcc_generate_new, + krcc_initialize, + krcc_destroy, + krcc_close, + krcc_store, + krcc_retrieve, + krcc_get_principal, + krcc_start_seq_get, + krcc_next_cred, + krcc_end_seq_get, + krcc_remove_cred, + krcc_set_flags, + krcc_get_flags, /* added after 1.4 release */ + krcc_ptcursor_new, + krcc_ptcursor_next, + krcc_ptcursor_free, + NULL, /* move */ + NULL, /* wasdefault */ + krcc_lock, + krcc_unlock, + krcc_switch_to, +}; + +#else /* !USE_KEYRING_CCACHE */ + +/* + * Export this, but it shouldn't be used. + */ +const krb5_cc_ops krb5_krcc_ops = { + 0, + "KEYRING", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* added after 1.4 release */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; +#endif /* USE_KEYRING_CCACHE */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/cc_memory.c b/krb5-1.21.3/src/lib/krb5/ccache/cc_memory.c new file mode 100644 index 00000000..2df76ed4 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/cc_memory.c @@ -0,0 +1,830 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/cc_memory.c - Memory-based credential cache */ +/* + * Copyright 1990,1991,2000,2004,2008 by the Massachusetts Institute of + * Technology. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "cc-int.h" +#include "../krb/int-proto.h" +#include "k5-hashtab.h" +#include + +static krb5_error_code KRB5_CALLCONV krb5_mcc_close +(krb5_context, krb5_ccache id ); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_destroy +(krb5_context, krb5_ccache id ); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_end_seq_get +(krb5_context, krb5_ccache id , krb5_cc_cursor *cursor ); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_generate_new +(krb5_context, krb5_ccache *id ); + +static const char * KRB5_CALLCONV krb5_mcc_get_name +(krb5_context, krb5_ccache id ); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_get_principal +(krb5_context, krb5_ccache id , krb5_principal *princ ); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_initialize +(krb5_context, krb5_ccache id , krb5_principal princ ); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_next_cred +(krb5_context, + krb5_ccache id , + krb5_cc_cursor *cursor , + krb5_creds *creds ); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_resolve +(krb5_context, krb5_ccache *id , const char *residual ); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_retrieve +(krb5_context, + krb5_ccache id , + krb5_flags whichfields , + krb5_creds *mcreds , + krb5_creds *creds ); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_start_seq_get +(krb5_context, krb5_ccache id , krb5_cc_cursor *cursor ); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_store +(krb5_context, krb5_ccache id , krb5_creds *creds ); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_set_flags +(krb5_context, krb5_ccache id , krb5_flags flags ); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_new +(krb5_context, krb5_cc_ptcursor *); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_next +(krb5_context, krb5_cc_ptcursor, krb5_ccache *); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_free +(krb5_context, krb5_cc_ptcursor *); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_lock +(krb5_context context, krb5_ccache id); + +static krb5_error_code KRB5_CALLCONV krb5_mcc_unlock +(krb5_context context, krb5_ccache id); + + +extern const krb5_cc_ops krb5_mcc_ops; +extern krb5_error_code krb5_change_cache (void); + +#define KRB5_OK 0 + +/* Individual credentials within a cache, in a linked list. */ +typedef struct _krb5_mcc_link { + struct _krb5_mcc_link *next; + krb5_creds *creds; +} krb5_mcc_link; + +/* Per-cache data header. */ +typedef struct _krb5_mcc_data { + char *name; + k5_cc_mutex lock; + krb5_principal prin; + krb5_mcc_link *link; + krb5_mcc_link **tail; /* Where to store next added cred */ + /* Time offsets for clock-skewed clients. */ + krb5_int32 time_offset; + krb5_int32 usec_offset; + int refcount; /* One for the table slot, one per handle */ + int generation; /* Incremented at each initialize */ +} krb5_mcc_data; + +/* Iterator over credentials in a memory cache. */ +struct mcc_cursor { + int generation; + krb5_mcc_link *next_link; +}; + +/* Iterator over memory caches. */ +struct krb5_mcc_ptcursor_data { + krb5_boolean first; +}; + +k5_cc_mutex krb5int_mcc_mutex = K5_CC_MUTEX_PARTIAL_INITIALIZER; +static struct k5_hashtab *mcc_hashtab = NULL; + +/* Ensure that mcc_hashtab is initialized. Call with krb5int_mcc_mutex + * locked. */ +static krb5_error_code +init_table(krb5_context context) +{ + krb5_error_code ret; + uint8_t seed[K5_HASH_SEED_LEN]; + krb5_data d = make_data(seed, sizeof(seed)); + + if (mcc_hashtab != NULL) + return 0; + ret = krb5_c_random_make_octets(context, &d); + if (ret) + return ret; + return k5_hashtab_create(seed, 64, &mcc_hashtab); +} + +/* Remove creds from d, invalidate any existing cursors, and unset the client + * principal. The caller is responsible for locking. */ +static void +empty_mcc_cache(krb5_context context, krb5_mcc_data *d) +{ + krb5_mcc_link *curr, *next; + + for (curr = d->link; curr != NULL; curr = next) { + next = curr->next; + krb5_free_creds(context, curr->creds); + free(curr); + } + d->link = NULL; + d->tail = &d->link; + d->generation++; + krb5_free_principal(context, d->prin); + d->prin = NULL; +} + +/* Remove all creds from d and initialize it with princ as the default client + * principal. The caller is responsible for locking. */ +static krb5_error_code +init_mcc_cache(krb5_context context, krb5_mcc_data *d, krb5_principal princ) +{ + krb5_os_context os_ctx = &context->os_context; + + empty_mcc_cache(context, d); + if (os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) { + /* Store client time offsets in the cache. */ + d->time_offset = os_ctx->time_offset; + d->usec_offset = os_ctx->usec_offset; + } + return krb5_copy_principal(context, princ, &d->prin); +} + +/* Add cred to d. The caller is responsible for locking. */ +static krb5_error_code +store_cred(krb5_context context, krb5_mcc_data *d, krb5_creds *cred) +{ + krb5_error_code ret; + krb5_mcc_link *new_node; + + new_node = malloc(sizeof(*new_node)); + if (new_node == NULL) + return ENOMEM; + new_node->next = NULL; + ret = krb5_copy_creds(context, cred, &new_node->creds); + if (ret) { + free(new_node); + return ret; + } + + /* Place the new node at the tail of the list. */ + *d->tail = new_node; + d->tail = &new_node->next; + return 0; +} + +/* + * Modifies: + * id + * + * Effects: + * Creates/refreshes the memory cred cache id. If the cache exists, its + * contents are destroyed. + * + * Errors: + * system errors + */ +krb5_error_code KRB5_CALLCONV +krb5_mcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ) +{ + krb5_error_code ret; + krb5_mcc_data *d = id->data; + + k5_cc_mutex_lock(context, &d->lock); + ret = init_mcc_cache(context, d, princ); + k5_cc_mutex_unlock(context, &d->lock); + if (ret == KRB5_OK) + krb5_change_cache(); + return ret; +} + +/* + * Modifies: + * id + * + * Effects: + * Invalidates the id, and frees any resources associated with accessing + * the cache. + */ +krb5_error_code KRB5_CALLCONV +krb5_mcc_close(krb5_context context, krb5_ccache id) +{ + krb5_mcc_data *d = id->data; + int count; + + free(id); + k5_cc_mutex_lock(context, &d->lock); + count = --d->refcount; + k5_cc_mutex_unlock(context, &d->lock); + if (count == 0) { + /* This is the last active handle referencing d and d has been removed + * from the table, so we can release it. */ + empty_mcc_cache(context, d); + free(d->name); + k5_cc_mutex_destroy(&d->lock); + free(d); + } + return KRB5_OK; +} + +/* + * Effects: + * Destroys the contents of id. id is invalid after call. + */ +krb5_error_code KRB5_CALLCONV +krb5_mcc_destroy(krb5_context context, krb5_ccache id) +{ + krb5_mcc_data *d = id->data; + krb5_boolean removed_from_table = FALSE; + + /* Remove this node from the table if it is still present. */ + k5_cc_mutex_lock(context, &krb5int_mcc_mutex); + if (k5_hashtab_remove(mcc_hashtab, d->name, strlen(d->name))) + removed_from_table = TRUE; + k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); + + /* Empty the cache and remove the reference for the table slot. There will + * always be at least one reference left for the handle being destroyed. */ + k5_cc_mutex_lock(context, &d->lock); + empty_mcc_cache(context, d); + if (removed_from_table) + d->refcount--; + k5_cc_mutex_unlock(context, &d->lock); + + /* Invalidate the handle, possibly removing the last reference to d and + * freeing it. */ + krb5_mcc_close(context, id); + + krb5_change_cache (); + return KRB5_OK; +} + +/* + * Requires: + * residual is a legal path name, and a null-terminated string + * + * Modifies: + * id + * + * Effects: + * creates or accesses a memory-based cred cache that is referenced by + * residual. + * + * Returns: + * A filled in krb5_ccache structure "id". + * + * Errors: + * KRB5_CC_NOMEM - there was insufficient memory to allocate the + * krb5_ccache. id is undefined. + * system errors (mutex locks related) + */ +static krb5_error_code new_mcc_data (const char *, krb5_mcc_data **); + +krb5_error_code KRB5_CALLCONV +krb5_mcc_resolve (krb5_context context, krb5_ccache *id, const char *residual) +{ + krb5_os_context os_ctx = &context->os_context; + krb5_ccache lid; + krb5_error_code err; + krb5_mcc_data *d; + + k5_cc_mutex_lock(context, &krb5int_mcc_mutex); + init_table(context); + d = k5_hashtab_get(mcc_hashtab, residual, strlen(residual)); + if (d != NULL) { + k5_cc_mutex_lock(context, &d->lock); + d->refcount++; + k5_cc_mutex_unlock(context, &d->lock); + } else { + err = new_mcc_data(residual, &d); + if (err) { + k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); + return err; + } + } + k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); + + lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); + if (lid == NULL) + return KRB5_CC_NOMEM; + + if ((context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) && + !(os_ctx->os_flags & KRB5_OS_TOFFSET_VALID)) { + /* Use the time offset from the cache entry */ + os_ctx->time_offset = d->time_offset; + os_ctx->usec_offset = d->usec_offset; + os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) | + KRB5_OS_TOFFSET_VALID); + } + + lid->ops = &krb5_mcc_ops; + lid->data = d; + *id = lid; + return KRB5_OK; +} + +/* + * Effects: + * Prepares for a sequential search of the credentials cache. + * Returns a krb5_cc_cursor to be used with krb5_mcc_next_cred and + * krb5_mcc_end_seq_get. + * + * If the cache is modified between the time of this call and the time + * of the final krb5_mcc_end_seq_get, the results are undefined. + * + * Errors: + * KRB5_CC_NOMEM + * system errors + */ +krb5_error_code KRB5_CALLCONV +krb5_mcc_start_seq_get(krb5_context context, krb5_ccache id, + krb5_cc_cursor *cursor) +{ + struct mcc_cursor *mcursor; + krb5_mcc_data *d; + + mcursor = malloc(sizeof(*mcursor)); + if (mcursor == NULL) + return KRB5_CC_NOMEM; + d = id->data; + k5_cc_mutex_lock(context, &d->lock); + mcursor->generation = d->generation; + mcursor->next_link = d->link; + k5_cc_mutex_unlock(context, &d->lock); + *cursor = mcursor; + return KRB5_OK; +} + +/* + * Requires: + * cursor is a krb5_cc_cursor originally obtained from + * krb5_mcc_start_seq_get. + * + * Modifies: + * cursor, creds + * + * Effects: + * Fills in creds with the "next" credentals structure from the cache + * id. The actual order the creds are returned in is arbitrary. + * Space is allocated for the variable length fields in the + * credentials structure, so the object returned must be passed to + * krb5_destroy_credential. + * + * The cursor is updated for the next call to krb5_mcc_next_cred. + * + * Errors: + * system errors + */ +krb5_error_code KRB5_CALLCONV +krb5_mcc_next_cred(krb5_context context, krb5_ccache id, + krb5_cc_cursor *cursor, krb5_creds *creds) +{ + struct mcc_cursor *mcursor; + krb5_error_code retval; + krb5_mcc_data *d = id->data; + + memset(creds, 0, sizeof(krb5_creds)); + mcursor = *cursor; + if (mcursor->next_link == NULL) + return KRB5_CC_END; + + /* + * Check the cursor generation against the cache generation in case the + * cache has been reinitialized or destroyed, freeing the pointer in the + * cursor. Keep the cache locked while we copy the creds and advance the + * pointer, in case another thread reinitializes the cache after we check + * the generation. + */ + k5_cc_mutex_lock(context, &d->lock); + if (mcursor->generation != d->generation) { + retval = KRB5_CC_END; + goto done; + } + + /* Skip over removed creds. */ + while (mcursor->next_link != NULL && mcursor->next_link->creds == NULL) + mcursor->next_link = mcursor->next_link->next; + if (mcursor->next_link == NULL) { + retval = KRB5_CC_END; + goto done; + } + + retval = k5_copy_creds_contents(context, mcursor->next_link->creds, creds); + if (retval == 0) + mcursor->next_link = mcursor->next_link->next; + +done: + k5_cc_mutex_unlock(context, &d->lock); + return retval; +} + +/* + * Requires: + * cursor is a krb5_cc_cursor originally obtained from + * krb5_mcc_start_seq_get. + * + * Modifies: + * id, cursor + * + * Effects: + * Finishes sequential processing of the memory credentials ccache id, + * and invalidates the cursor (it must never be used after this call). + */ +/* ARGSUSED */ +krb5_error_code KRB5_CALLCONV +krb5_mcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor) +{ + free(*cursor); + *cursor = NULL; + return KRB5_OK; +} + +/* + * Utility routine: Creates the back-end data for a memory cache, and adds it + * to the global table. Give the new object two references, one for the table + * slot and one for the caller's handle. + * + * Call with the global table lock held. + */ +static krb5_error_code +new_mcc_data (const char *name, krb5_mcc_data **dataptr) +{ + krb5_error_code err; + krb5_mcc_data *d; + + d = malloc(sizeof(krb5_mcc_data)); + if (d == NULL) + return KRB5_CC_NOMEM; + + err = k5_cc_mutex_init(&d->lock); + if (err) { + free(d); + return err; + } + + d->name = strdup(name); + if (d->name == NULL) { + k5_cc_mutex_destroy(&d->lock); + free(d); + return KRB5_CC_NOMEM; + } + d->link = NULL; + d->tail = &d->link; + d->prin = NULL; + d->time_offset = 0; + d->usec_offset = 0; + d->refcount = 2; + d->generation = 0; + + if (k5_hashtab_add(mcc_hashtab, d->name, strlen(d->name), d) != 0) { + free(d->name); + k5_cc_mutex_destroy(&d->lock); + free(d); + return KRB5_CC_NOMEM; + } + + *dataptr = d; + return 0; +} + +/* + * Effects: + * Creates a new memory cred cache whose name is guaranteed to be + * unique. The name begins with the string TKT_ROOT (from mcc.h). + * + * Returns: + * The filled in krb5_ccache id. + * + * Errors: + * KRB5_CC_NOMEM - there was insufficient memory to allocate the + * krb5_ccache. id is undefined. + * system errors (from open, mutex locking) + */ + +krb5_error_code KRB5_CALLCONV +krb5_mcc_generate_new (krb5_context context, krb5_ccache *id) +{ + krb5_ccache lid; + char uniquename[8]; + krb5_error_code err; + krb5_mcc_data *d; + + /* Allocate memory */ + lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); + if (lid == NULL) + return KRB5_CC_NOMEM; + + lid->ops = &krb5_mcc_ops; + + k5_cc_mutex_lock(context, &krb5int_mcc_mutex); + init_table(context); + + /* Check for uniqueness with mutex locked to avoid race conditions */ + while (1) { + err = krb5int_random_string (context, uniquename, sizeof (uniquename)); + if (err) { + k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); + free(lid); + return err; + } + + if (k5_hashtab_get(mcc_hashtab, uniquename, + strlen(uniquename)) == NULL) + break; + } + + err = new_mcc_data(uniquename, &d); + + k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); + if (err) { + free(lid); + return err; + } + lid->data = d; + *id = lid; + krb5_change_cache (); + return KRB5_OK; +} + +/* + * Requires: + * id is a file credential cache + * + * Returns: + * A pointer to the name of the file cred cache id. + */ +const char * KRB5_CALLCONV +krb5_mcc_get_name (krb5_context context, krb5_ccache id) +{ + return (char *) ((krb5_mcc_data *) id->data)->name; +} + +/* + * Modifies: + * id, princ + * + * Effects: + * Retrieves the primary principal from id, as set with + * krb5_mcc_initialize. The principal is returned is allocated + * storage that must be freed by the caller via krb5_free_principal. + * + * Errors: + * system errors + * ENOMEM + */ +krb5_error_code KRB5_CALLCONV +krb5_mcc_get_principal(krb5_context context, krb5_ccache id, krb5_principal *princ) +{ + krb5_error_code ret; + krb5_mcc_data *d = id->data; + + *princ = NULL; + k5_cc_mutex_lock(context, &d->lock); + if (d->prin == NULL) + ret = KRB5_FCC_NOFILE; + else + ret = krb5_copy_principal(context, d->prin, princ); + k5_cc_mutex_unlock(context, &d->lock); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_mcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields, + krb5_creds *mcreds, krb5_creds *creds) +{ + return k5_cc_retrieve_cred_default(context, id, whichfields, mcreds, + creds); +} + +/* + * Modifies: + * the memory cache + * + * Effects: + * Remove the given creds from the ccache. + */ +static krb5_error_code KRB5_CALLCONV +krb5_mcc_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags, + krb5_creds *creds) +{ + krb5_mcc_data *data = (krb5_mcc_data *)cache->data; + krb5_mcc_link *l; + + k5_cc_mutex_lock(context, &data->lock); + + for (l = data->link; l != NULL; l = l->next) { + if (l->creds != NULL && + krb5int_cc_creds_match_request(context, flags, creds, l->creds)) { + krb5_free_creds(context, l->creds); + l->creds = NULL; + } + } + + k5_cc_mutex_unlock(context, &data->lock); + return 0; +} + + +/* + * Requires: + * id is a cred cache returned by krb5_mcc_resolve or + * krb5_mcc_generate_new. + * + * Modifies: + * id + * + * Effects: + * Sets the operational flags of id to flags. + */ +krb5_error_code KRB5_CALLCONV +krb5_mcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags) +{ + return KRB5_OK; +} + +static krb5_error_code KRB5_CALLCONV +krb5_mcc_get_flags(krb5_context context, krb5_ccache id, krb5_flags *flags) +{ + *flags = 0; + return KRB5_OK; +} + +/* + * Modifies: + * the memory cache + * + * Effects: + * Save away creds in the ccache. + * + * Errors: + * ENOMEM + */ +krb5_error_code KRB5_CALLCONV +krb5_mcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds) +{ + krb5_error_code ret; + krb5_mcc_data *d = id->data; + + /* Place the new node at the tail of the list. */ + k5_cc_mutex_lock(context, &d->lock); + ret = store_cred(context, d, creds); + k5_cc_mutex_unlock(context, &d->lock); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +krb5_mcc_ptcursor_new( + krb5_context context, + krb5_cc_ptcursor *cursor) +{ + krb5_cc_ptcursor n = NULL; + struct krb5_mcc_ptcursor_data *cdata = NULL; + + *cursor = NULL; + + n = malloc(sizeof(*n)); + if (n == NULL) + return ENOMEM; + n->ops = &krb5_mcc_ops; + cdata = malloc(sizeof(struct krb5_mcc_ptcursor_data)); + if (cdata == NULL) { + free(n); + return ENOMEM; + } + n->data = cdata; + cdata->first = TRUE; + *cursor = n; + return 0; +} + +static krb5_error_code KRB5_CALLCONV +krb5_mcc_ptcursor_next( + krb5_context context, + krb5_cc_ptcursor cursor, + krb5_ccache *ccache) +{ + struct krb5_mcc_ptcursor_data *cdata = NULL; + const char *defname; + + *ccache = NULL; + cdata = cursor->data; + if (!cdata->first) + return 0; + cdata->first = FALSE; + + defname = krb5_cc_default_name(context); + if (defname == NULL || strncmp(defname, "MEMORY:", 7) != 0) + return 0; + + return krb5_cc_resolve(context, defname, ccache); +} + +static krb5_error_code KRB5_CALLCONV +krb5_mcc_ptcursor_free( + krb5_context context, + krb5_cc_ptcursor *cursor) +{ + if (*cursor == NULL) + return 0; + if ((*cursor)->data != NULL) + free((*cursor)->data); + free(*cursor); + *cursor = NULL; + return 0; +} + +static krb5_error_code KRB5_CALLCONV +krb5_mcc_replace(krb5_context context, krb5_ccache id, krb5_principal princ, + krb5_creds **creds) +{ + krb5_error_code ret; + krb5_mcc_data *d = id->data; + int i; + + k5_cc_mutex_lock(context, &d->lock); + ret = init_mcc_cache(context, d, princ); + for (i = 0; !ret && creds[i] != NULL; i++) + ret = store_cred(context, d, creds[i]); + k5_cc_mutex_unlock(context, &d->lock); + if (!ret) + krb5_change_cache(); + return ret; +} + +static krb5_error_code KRB5_CALLCONV +krb5_mcc_lock(krb5_context context, krb5_ccache id) +{ + krb5_mcc_data *data = (krb5_mcc_data *) id->data; + + k5_cc_mutex_lock(context, &data->lock); + return 0; +} + +static krb5_error_code KRB5_CALLCONV +krb5_mcc_unlock(krb5_context context, krb5_ccache id) +{ + krb5_mcc_data *data = (krb5_mcc_data *) id->data; + + k5_cc_mutex_unlock(context, &data->lock); + return 0; +} + +const krb5_cc_ops krb5_mcc_ops = { + 0, + "MEMORY", + krb5_mcc_get_name, + krb5_mcc_resolve, + krb5_mcc_generate_new, + krb5_mcc_initialize, + krb5_mcc_destroy, + krb5_mcc_close, + krb5_mcc_store, + krb5_mcc_retrieve, + krb5_mcc_get_principal, + krb5_mcc_start_seq_get, + krb5_mcc_next_cred, + krb5_mcc_end_seq_get, + krb5_mcc_remove_cred, + krb5_mcc_set_flags, + krb5_mcc_get_flags, + krb5_mcc_ptcursor_new, + krb5_mcc_ptcursor_next, + krb5_mcc_ptcursor_free, + krb5_mcc_replace, + NULL, /* wasdefault */ + krb5_mcc_lock, + krb5_mcc_unlock, + NULL, /* switch_to */ +}; diff --git a/krb5-1.21.3/src/lib/krb5/ccache/cc_mslsa.c b/krb5-1.21.3/src/lib/krb5/ccache/cc_mslsa.c new file mode 100644 index 00000000..4931e6c1 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/cc_mslsa.c @@ -0,0 +1,2212 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/cc_mslsa.c */ +/* + * Copyright 2007 Secure Endpoints Inc. + * + * Copyright 2003,2004 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * Copyright 2000 by Carnegie Mellon University + * + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of Carnegie Mellon + * University not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. + * + * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO + * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR + * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Implementation of microsoft windows lsa credentials cache + */ + +#ifdef _WIN32 +#define UNICODE +#define _UNICODE + +#include +#define WIN32_NO_STATUS +#include "k5-int.h" +#include "com_err.h" +#include "cc-int.h" + +#include +#include +#include +#include +#include + +#define SECURITY_WIN32 +#include +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif +#define _WIN32_WINNT 0x0600 +#include + + +#define MAX_MSG_SIZE 256 +#define MAX_MSPRINC_SIZE 1024 + +/* THREAD SAFETY + * The function does_query_ticket_cache_ex2() + * contains static variables to cache the responses of the tests being + * performed. There is no harm in the test being performed more than + * once since the result will always be the same. + */ + +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); + +static VOID +ShowWinError(LPSTR szAPI, DWORD dwError) +{ + + // TODO - Write errors to event log so that scripts that don't + // check for errors will still get something in the event log + + // This code is completely unsafe for use on non-English systems + // Any call to this function will result in the FormatMessage + // call failing and the program terminating. This might have + // been acceptable when this code was part of ms2mit.exe as + // a standalone executable but it is not appropriate for a library + +#ifdef COMMENT + WCHAR szMsgBuf[MAX_MSG_SIZE]; + DWORD dwRes; + + printf("Error calling function %s: %lu\n", szAPI, dwError); + + dwRes = FormatMessage ( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwError, + MAKELANGID (LANG_ENGLISH, SUBLANG_ENGLISH_US), + szMsgBuf, + MAX_MSG_SIZE, + NULL); + if (0 == dwRes) { + printf("FormatMessage failed with %d\n", GetLastError()); + ExitProcess(EXIT_FAILURE); + } + + printf("%S",szMsgBuf); +#endif /* COMMENT */ +} + +static VOID +ShowLsaError(LPSTR szAPI, NTSTATUS Status) +{ + // + // Convert the NTSTATUS to Winerror. Then call ShowWinError(). + // + ShowWinError(szAPI, LsaNtStatusToWinError(Status)); +} + +static BOOL +WINAPI +UnicodeToANSI(LPTSTR lpInputString, LPSTR lpszOutputString, int nOutStringLen) +{ + CPINFO CodePageInfo; + + GetCPInfo(CP_ACP, &CodePageInfo); + + if (CodePageInfo.MaxCharSize > 1) { + // Only supporting non-Unicode strings + int reqLen = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) lpInputString, -1, + NULL, 0, NULL, NULL); + if ( reqLen > nOutStringLen) + { + return FALSE; + } else { + if (WideCharToMultiByte(CP_ACP, + /* WC_NO_BEST_FIT_CHARS | */ WC_COMPOSITECHECK, + (LPCWSTR) lpInputString, -1, + lpszOutputString, + nOutStringLen, NULL, NULL) == 0) + return FALSE; + } + } + else + { + // Looks like unicode, better translate it + if (WideCharToMultiByte(CP_ACP, + /* WC_NO_BEST_FIT_CHARS | */ WC_COMPOSITECHECK, + (LPCWSTR) lpInputString, -1, + lpszOutputString, + nOutStringLen, NULL, NULL) == 0) + return FALSE; + } + + return TRUE; +} // UnicodeToANSI + +static VOID +WINAPI +ANSIToUnicode(LPCSTR lpInputString, LPWSTR lpszOutputString, int nOutStringLen) +{ + + CPINFO CodePageInfo; + + GetCPInfo(CP_ACP, &CodePageInfo); + + MultiByteToWideChar(CP_ACP, 0, lpInputString, -1, + lpszOutputString, nOutStringLen); +} // ANSIToUnicode + + +static void +MITPrincToMSPrinc(krb5_context context, krb5_principal principal, UNICODE_STRING * msprinc) +{ + char *aname = NULL; + + if (!krb5_unparse_name(context, principal, &aname)) { + msprinc->Length = strlen(aname) * sizeof(WCHAR); + if ( msprinc->Length <= msprinc->MaximumLength ) + ANSIToUnicode(aname, msprinc->Buffer, msprinc->MaximumLength); + else + msprinc->Length = 0; + krb5_free_unparsed_name(context,aname); + } +} + +static BOOL +UnicodeStringToMITPrinc(UNICODE_STRING *service, UNICODE_STRING *realm, + krb5_context context, krb5_principal *principal) +{ + WCHAR princbuf[512]; + WCHAR realmbuf[512]; + char aname[512]; + + /* Convert the realm to a wchar string. */ + realmbuf[0] = '\0'; + wcsncpy(realmbuf, realm->Buffer, realm->Length / sizeof(WCHAR)); + realmbuf[realm->Length / sizeof(WCHAR)] = 0; + /* Convert the principal components to a wchar string. */ + princbuf[0]=0; + wcsncpy(princbuf, service->Buffer, service->Length/sizeof(WCHAR)); + princbuf[service->Length/sizeof(WCHAR)]=0; + wcscat(princbuf, L"@"); + wcscat(princbuf, realmbuf); + if (UnicodeToANSI(princbuf, aname, sizeof(aname))) { + if (krb5_parse_name(context, aname, principal) == 0) + return TRUE; + } + return FALSE; +} + + +static BOOL +KerbExternalNameToMITPrinc(KERB_EXTERNAL_NAME *msprinc, WCHAR *realm, krb5_context context, + krb5_principal *principal) +{ + WCHAR princbuf[512],tmpbuf[128]; + char aname[512]; + USHORT i; + princbuf[0]=0; + for (i=0;iNameCount;i++) { + wcsncpy(tmpbuf, msprinc->Names[i].Buffer, + msprinc->Names[i].Length/sizeof(WCHAR)); + tmpbuf[msprinc->Names[i].Length/sizeof(WCHAR)]=0; + if (princbuf[0]) + wcscat(princbuf, L"/"); + wcscat(princbuf, tmpbuf); + } + wcscat(princbuf, L"@"); + wcscat(princbuf, realm); + if (UnicodeToANSI(princbuf, aname, sizeof(aname))) { + if (krb5_parse_name(context, aname, principal) == 0) + return TRUE; + } + return FALSE; +} + +static time_t +FileTimeToUnixTime(LARGE_INTEGER *ltime) +{ + FILETIME filetime, localfiletime; + SYSTEMTIME systime; + struct tm utime; + filetime.dwLowDateTime=ltime->LowPart; + filetime.dwHighDateTime=ltime->HighPart; + FileTimeToLocalFileTime(&filetime, &localfiletime); + FileTimeToSystemTime(&localfiletime, &systime); + utime.tm_sec=systime.wSecond; + utime.tm_min=systime.wMinute; + utime.tm_hour=systime.wHour; + utime.tm_mday=systime.wDay; + utime.tm_mon=systime.wMonth-1; + utime.tm_year=systime.wYear-1900; + utime.tm_isdst=-1; + return(mktime(&utime)); +} + +static void +MSSessionKeyToMITKeyblock(KERB_CRYPTO_KEY *mskey, krb5_context context, krb5_keyblock *keyblock) +{ + krb5_keyblock tmpblock; + tmpblock.magic=KV5M_KEYBLOCK; + tmpblock.enctype=mskey->KeyType; + tmpblock.length=mskey->Length; + tmpblock.contents=mskey->Value; + krb5_copy_keyblock_contents(context, &tmpblock, keyblock); +} + +static BOOL +IsMSSessionKeyNull(KERB_CRYPTO_KEY *mskey) +{ + DWORD i; + + if (mskey->KeyType == KERB_ETYPE_NULL) + return TRUE; + + for ( i=0; iLength; i++ ) { + if (mskey->Value[i]) + return FALSE; + } + + return TRUE; +} + +static void +MSFlagsToMITFlags(ULONG msflags, ULONG *mitflags) +{ + *mitflags=msflags; +} + +static BOOL +MSTicketToMITTicket(KERB_EXTERNAL_TICKET *msticket, krb5_context context, krb5_data *ticket) +{ + krb5_data tmpdata, *newdata = 0; + krb5_error_code rc; + + tmpdata.magic=KV5M_DATA; + tmpdata.length=msticket->EncodedTicketSize; + tmpdata.data=msticket->EncodedTicket; + + // this is ugly and will break krb5_free_data() + // now that this is being done within the library it won't break krb5_free_data() + rc = krb5_copy_data(context, &tmpdata, &newdata); + if (rc) + return FALSE; + + memcpy(ticket, newdata, sizeof(krb5_data)); + free(newdata); + return TRUE; +} + +static BOOL +MSCredToMITCred(KERB_EXTERNAL_TICKET *msticket, UNICODE_STRING ClientRealm, + krb5_context context, krb5_creds *creds) +{ + WCHAR wrealm[128]; + ZeroMemory(creds, sizeof(krb5_creds)); + creds->magic=KV5M_CREDS; + + // construct Client Principal + wcsncpy(wrealm, ClientRealm.Buffer, ClientRealm.Length/sizeof(WCHAR)); + wrealm[ClientRealm.Length/sizeof(WCHAR)]=0; + if (!KerbExternalNameToMITPrinc(msticket->ClientName, wrealm, context, &creds->client)) + return FALSE; + + // construct Service Principal + wcsncpy(wrealm, msticket->DomainName.Buffer, + msticket->DomainName.Length/sizeof(WCHAR)); + wrealm[msticket->DomainName.Length/sizeof(WCHAR)]=0; + if (!KerbExternalNameToMITPrinc(msticket->ServiceName, wrealm, context, &creds->server)) + return FALSE; + MSSessionKeyToMITKeyblock(&msticket->SessionKey, context, + &creds->keyblock); + MSFlagsToMITFlags(msticket->TicketFlags, &creds->ticket_flags); + creds->times.starttime=FileTimeToUnixTime(&msticket->StartTime); + creds->times.endtime=FileTimeToUnixTime(&msticket->EndTime); + creds->times.renew_till=FileTimeToUnixTime(&msticket->RenewUntil); + + creds->addresses = NULL; + + return MSTicketToMITTicket(msticket, context, &creds->ticket); +} + +/* CacheInfoEx2ToMITCred is used when we do not need the real ticket */ +static BOOL +CacheInfoEx2ToMITCred(KERB_TICKET_CACHE_INFO_EX2 *info, + krb5_context context, krb5_creds *creds) +{ + ZeroMemory(creds, sizeof(krb5_creds)); + creds->magic=KV5M_CREDS; + + // construct Client Principal + if (!UnicodeStringToMITPrinc(&info->ClientName, &info->ClientRealm, + context, &creds->client)) + return FALSE; + + // construct Service Principal + if (!UnicodeStringToMITPrinc(&info->ServerName, &info->ServerRealm, + context, &creds->server)) + return FALSE; + + creds->keyblock.magic = KV5M_KEYBLOCK; + creds->keyblock.enctype = info->SessionKeyType; + creds->ticket_flags = info->TicketFlags; + MSFlagsToMITFlags(info->TicketFlags, &creds->ticket_flags); + creds->times.starttime=FileTimeToUnixTime(&info->StartTime); + creds->times.endtime=FileTimeToUnixTime(&info->EndTime); + creds->times.renew_till=FileTimeToUnixTime(&info->RenewTime); + + /* MS Tickets are addressless. MIT requires an empty address + * not a NULL list of addresses. + */ + creds->addresses = (krb5_address **)malloc(sizeof(krb5_address *)); + if (creds->addresses == NULL) + return FALSE; + memset(creds->addresses, 0, sizeof(krb5_address *)); + + return TRUE; +} + +static BOOL +PackageConnectLookup(HANDLE *pLogonHandle, ULONG *pPackageId) +{ + LSA_STRING Name; + NTSTATUS Status; + + Status = LsaConnectUntrusted( + pLogonHandle + ); + + if (FAILED(Status)) + { + ShowLsaError("LsaConnectUntrusted", Status); + return FALSE; + } + + Name.Buffer = MICROSOFT_KERBEROS_NAME_A; + Name.Length = strlen(Name.Buffer); + Name.MaximumLength = Name.Length + 1; + + Status = LsaLookupAuthenticationPackage( + *pLogonHandle, + &Name, + pPackageId + ); + + if (FAILED(Status)) + { + ShowLsaError("LsaLookupAuthenticationPackage", Status); + return FALSE; + } + + return TRUE; + +} + +/* + * This runtime check is only needed on Windows XP and Server 2003. + * It can safely be removed when we no longer wish to support any + * versions of those platforms. + */ +static BOOL +does_query_ticket_cache_ex2 (void) +{ + static BOOL fChecked = FALSE; + static BOOL fEx2Response = FALSE; + + if (!fChecked) + { + NTSTATUS Status = 0; + NTSTATUS SubStatus = 0; + HANDLE LogonHandle; + ULONG PackageId; + ULONG RequestSize; + PKERB_QUERY_TKT_CACHE_REQUEST pCacheRequest = NULL; + PKERB_QUERY_TKT_CACHE_EX2_RESPONSE pCacheResponse = NULL; + ULONG ResponseSize; + + RequestSize = sizeof(*pCacheRequest) + 1; + + if (!PackageConnectLookup(&LogonHandle, &PackageId)) + return FALSE; + + pCacheRequest = (PKERB_QUERY_TKT_CACHE_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize); + if (!pCacheRequest) { + LsaDeregisterLogonProcess(LogonHandle); + return FALSE; + } + + pCacheRequest->MessageType = KerbQueryTicketCacheEx2Message; + pCacheRequest->LogonId.LowPart = 0; + pCacheRequest->LogonId.HighPart = 0; + + Status = LsaCallAuthenticationPackage( LogonHandle, + PackageId, + pCacheRequest, + RequestSize, + &pCacheResponse, + &ResponseSize, + &SubStatus + ); + + LocalFree(pCacheRequest); + LsaDeregisterLogonProcess(LogonHandle); + + if (!(FAILED(Status) || FAILED(SubStatus))) { + LsaFreeReturnBuffer(pCacheResponse); + fEx2Response = TRUE; + } + fChecked = TRUE; + } + + return fEx2Response; +} + +static DWORD +ConcatenateUnicodeStrings(UNICODE_STRING *pTarget, UNICODE_STRING Source1, UNICODE_STRING Source2) +{ + // + // The buffers for Source1 and Source2 cannot overlap pTarget's + // buffer. Source1.Length + Source2.Length must be <= 0xFFFF, + // otherwise we overflow... + // + + USHORT TotalSize = Source1.Length + Source2.Length; + PBYTE buffer = (PBYTE) pTarget->Buffer; + + if (TotalSize > pTarget->MaximumLength) + return ERROR_INSUFFICIENT_BUFFER; + + if ( pTarget->Buffer != Source1.Buffer ) + memcpy(buffer, Source1.Buffer, Source1.Length); + memcpy(buffer + Source1.Length, Source2.Buffer, Source2.Length); + + pTarget->Length = TotalSize; + return ERROR_SUCCESS; +} + +static BOOL +get_STRING_from_registry(HKEY hBaseKey, char * key, char * value, char * outbuf, DWORD outlen) +{ + HKEY hKey; + DWORD dwCount; + LONG rc; + + if (!outbuf || outlen == 0) + return FALSE; + + rc = RegOpenKeyExA(hBaseKey, key, 0, KEY_QUERY_VALUE, &hKey); + if (rc) + return FALSE; + + dwCount = outlen; + rc = RegQueryValueExA(hKey, value, 0, 0, (LPBYTE) outbuf, &dwCount); + RegCloseKey(hKey); + + return rc?FALSE:TRUE; +} + +static BOOL +GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData) +{ + NTSTATUS Status = 0; + HANDLE TokenHandle; + TOKEN_STATISTICS Stats; + DWORD ReqLen; + BOOL Success; + + if (!ppSessionData) + return FALSE; + *ppSessionData = NULL; + + Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle ); + if ( !Success ) + return FALSE; + + Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen ); + CloseHandle( TokenHandle ); + if ( !Success ) + return FALSE; + + Status = LsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData ); + if ( FAILED(Status) || !ppSessionData ) + return FALSE; + + return TRUE; +} + +static DWORD +ConstructTicketRequest(UNICODE_STRING DomainName, PKERB_RETRIEVE_TKT_REQUEST * outRequest, ULONG * outSize) +{ + DWORD Error; + UNICODE_STRING TargetPrefix; + USHORT TargetSize; + ULONG RequestSize; + PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL; + + *outRequest = NULL; + *outSize = 0; + + // + // Set up the "krbtgt/" target prefix into a UNICODE_STRING so we + // can easily concatenate it later. + // + + TargetPrefix.Buffer = L"krbtgt/"; + TargetPrefix.Length = wcslen(TargetPrefix.Buffer) * sizeof(WCHAR); + TargetPrefix.MaximumLength = TargetPrefix.Length; + + // + // We will need to concatenate the "krbtgt/" prefix and the + // Logon Session's DnsDomainName into our request's target name. + // + // Therefore, first compute the necessary buffer size for that. + // + // Note that we might theoretically have integer overflow. + // + + TargetSize = TargetPrefix.Length + DomainName.Length; + + // + // The ticket request buffer needs to be a single buffer. That buffer + // needs to include the buffer for the target name. + // + + RequestSize = sizeof(*pTicketRequest) + TargetSize; + + // + // Allocate the request buffer and make sure it's zero-filled. + // + + pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize); + if (!pTicketRequest) + return GetLastError(); + + // + // Concatenate the target prefix with the previous reponse's + // target domain. + // + + pTicketRequest->TargetName.Length = 0; + pTicketRequest->TargetName.MaximumLength = TargetSize; + pTicketRequest->TargetName.Buffer = (PWSTR) (pTicketRequest + 1); + Error = ConcatenateUnicodeStrings(&(pTicketRequest->TargetName), + TargetPrefix, + DomainName); + *outRequest = pTicketRequest; + *outSize = RequestSize; + return Error; +} + +static BOOL +PurgeAllTickets(HANDLE LogonHandle, ULONG PackageId) +{ + NTSTATUS Status = 0; + NTSTATUS SubStatus = 0; + KERB_PURGE_TKT_CACHE_REQUEST PurgeRequest; + + PurgeRequest.MessageType = KerbPurgeTicketCacheMessage; + PurgeRequest.LogonId.LowPart = 0; + PurgeRequest.LogonId.HighPart = 0; + PurgeRequest.ServerName.Buffer = L""; + PurgeRequest.ServerName.Length = 0; + PurgeRequest.ServerName.MaximumLength = 0; + PurgeRequest.RealmName.Buffer = L""; + PurgeRequest.RealmName.Length = 0; + PurgeRequest.RealmName.MaximumLength = 0; + Status = LsaCallAuthenticationPackage(LogonHandle, + PackageId, + &PurgeRequest, + sizeof(PurgeRequest), + NULL, + NULL, + &SubStatus + ); + if (FAILED(Status) || FAILED(SubStatus)) + return FALSE; + return TRUE; +} + +static BOOL +PurgeTicketEx(HANDLE LogonHandle, ULONG PackageId, + krb5_context context, krb5_flags flags, krb5_creds *cred) +{ + NTSTATUS Status = 0; + NTSTATUS SubStatus = 0; + KERB_PURGE_TKT_CACHE_EX_REQUEST * pPurgeRequest; + DWORD dwRequestLen = sizeof(KERB_PURGE_TKT_CACHE_EX_REQUEST) + 4096; + char * cname = NULL, * crealm = NULL; + char * sname = NULL, * srealm = NULL; + + if (krb5_unparse_name(context, cred->client, &cname)) + return FALSE; + + if (krb5_unparse_name(context, cred->server, &sname)) { + krb5_free_unparsed_name(context, cname); + return FALSE; + } + + pPurgeRequest = malloc(dwRequestLen); + if ( pPurgeRequest == NULL ) + return FALSE; + memset(pPurgeRequest, 0, dwRequestLen); + + crealm = strrchr(cname, '@'); + *crealm = '\0'; + crealm++; + + srealm = strrchr(sname, '@'); + *srealm = '\0'; + srealm++; + + pPurgeRequest->MessageType = KerbPurgeTicketCacheExMessage; + pPurgeRequest->LogonId.LowPart = 0; + pPurgeRequest->LogonId.HighPart = 0; + pPurgeRequest->Flags = 0; + pPurgeRequest->TicketTemplate.ClientName.Buffer = (PWSTR)((CHAR *)pPurgeRequest + sizeof(KERB_PURGE_TKT_CACHE_EX_REQUEST)); + pPurgeRequest->TicketTemplate.ClientName.Length = strlen(cname)*sizeof(WCHAR); + pPurgeRequest->TicketTemplate.ClientName.MaximumLength = 256; + ANSIToUnicode(cname, pPurgeRequest->TicketTemplate.ClientName.Buffer, + pPurgeRequest->TicketTemplate.ClientName.MaximumLength); + + pPurgeRequest->TicketTemplate.ClientRealm.Buffer = (PWSTR)(((CHAR *)pPurgeRequest)+sizeof(KERB_PURGE_TKT_CACHE_EX_REQUEST) + 512); + pPurgeRequest->TicketTemplate.ClientRealm.Length = strlen(crealm)*sizeof(WCHAR); + pPurgeRequest->TicketTemplate.ClientRealm.MaximumLength = 256; + ANSIToUnicode(crealm, pPurgeRequest->TicketTemplate.ClientRealm.Buffer, + pPurgeRequest->TicketTemplate.ClientRealm.MaximumLength); + + pPurgeRequest->TicketTemplate.ServerName.Buffer = (PWSTR)(((CHAR *)pPurgeRequest)+sizeof(KERB_PURGE_TKT_CACHE_EX_REQUEST) + 1024); + pPurgeRequest->TicketTemplate.ServerName.Length = strlen(sname)*sizeof(WCHAR); + pPurgeRequest->TicketTemplate.ServerName.MaximumLength = 256; + ANSIToUnicode(sname, pPurgeRequest->TicketTemplate.ServerName.Buffer, + pPurgeRequest->TicketTemplate.ServerName.MaximumLength); + + pPurgeRequest->TicketTemplate.ServerRealm.Buffer = (PWSTR)(((CHAR *)pPurgeRequest)+sizeof(KERB_PURGE_TKT_CACHE_EX_REQUEST) + 1536); + pPurgeRequest->TicketTemplate.ServerRealm.Length = strlen(srealm)*sizeof(WCHAR); + pPurgeRequest->TicketTemplate.ServerRealm.MaximumLength = 256; + ANSIToUnicode(srealm, pPurgeRequest->TicketTemplate.ServerRealm.Buffer, + pPurgeRequest->TicketTemplate.ServerRealm.MaximumLength); + + pPurgeRequest->TicketTemplate.StartTime; + pPurgeRequest->TicketTemplate.EndTime; + pPurgeRequest->TicketTemplate.RenewTime; + pPurgeRequest->TicketTemplate.EncryptionType = cred->keyblock.enctype; + pPurgeRequest->TicketTemplate.TicketFlags = flags; + + Status = LsaCallAuthenticationPackage( LogonHandle, + PackageId, + pPurgeRequest, + dwRequestLen, + NULL, + NULL, + &SubStatus + ); + free(pPurgeRequest); + krb5_free_unparsed_name(context,cname); + krb5_free_unparsed_name(context,sname); + + if (FAILED(Status) || FAILED(SubStatus)) + return FALSE; + return TRUE; +} + +static BOOL +KerbSubmitTicket( HANDLE LogonHandle, ULONG PackageId, + krb5_context context, krb5_creds *cred) +{ + NTSTATUS Status = 0; + NTSTATUS SubStatus = 0; + KERB_SUBMIT_TKT_REQUEST * pSubmitRequest = NULL; + DWORD dwRequestLen; + krb5_auth_context auth_context = NULL; + krb5_keyblock * keyblock = 0; + krb5_replay_data replaydata; + krb5_data * krb_cred = 0; + krb5_error_code rc; + BOOL rv = FALSE; + + if (krb5_auth_con_init(context, &auth_context)) { + return FALSE; + } + + if (krb5_auth_con_setflags(context, auth_context, + KRB5_AUTH_CONTEXT_RET_TIME)) { + return FALSE; + } + + krb5_auth_con_getsendsubkey(context, auth_context, &keyblock); + if (keyblock == NULL) + krb5_auth_con_getkey(context, auth_context, &keyblock); + + /* make up a key, any key, that can be used to generate the + * encrypted KRB_CRED pdu. The Vista release LSA requires + * that an enctype other than NULL be used. */ + if (keyblock == NULL) { + keyblock = (krb5_keyblock *)malloc(sizeof(krb5_keyblock)); + if (keyblock == NULL) + return FALSE; + keyblock->enctype = ENCTYPE_ARCFOUR_HMAC; + keyblock->length = 16; + keyblock->contents = (krb5_octet *)malloc(16); + if (keyblock->contents == NULL) + goto cleanup; + keyblock->contents[0] = 0xde; + keyblock->contents[1] = 0xad; + keyblock->contents[2] = 0xbe; + keyblock->contents[3] = 0xef; + keyblock->contents[4] = 0xfe; + keyblock->contents[5] = 0xed; + keyblock->contents[6] = 0xf0; + keyblock->contents[7] = 0xd; + keyblock->contents[8] = 0xde; + keyblock->contents[9] = 0xad; + keyblock->contents[10] = 0xbe; + keyblock->contents[11] = 0xef; + keyblock->contents[12] = 0xfe; + keyblock->contents[13] = 0xed; + keyblock->contents[14] = 0xf0; + keyblock->contents[15] = 0xd; + krb5_auth_con_setsendsubkey(context, auth_context, keyblock); + } + rc = krb5_mk_1cred(context, auth_context, cred, &krb_cred, &replaydata); + if (rc) + goto cleanup; + + dwRequestLen = sizeof(KERB_SUBMIT_TKT_REQUEST) + krb_cred->length + (keyblock ? keyblock->length : 0); + + pSubmitRequest = (PKERB_SUBMIT_TKT_REQUEST)malloc(dwRequestLen); + if (pSubmitRequest == NULL) + goto cleanup; + memset(pSubmitRequest, 0, dwRequestLen); + + pSubmitRequest->MessageType = KerbSubmitTicketMessage; + pSubmitRequest->LogonId.LowPart = 0; + pSubmitRequest->LogonId.HighPart = 0; + pSubmitRequest->Flags = 0; + + if (keyblock) { + pSubmitRequest->Key.KeyType = keyblock->enctype; + pSubmitRequest->Key.Length = keyblock->length; + pSubmitRequest->Key.Offset = sizeof(KERB_SUBMIT_TKT_REQUEST)+krb_cred->length; + } else { + pSubmitRequest->Key.KeyType = ENCTYPE_NULL; + pSubmitRequest->Key.Length = 0; + pSubmitRequest->Key.Offset = 0; + } + pSubmitRequest->KerbCredSize = krb_cred->length; + pSubmitRequest->KerbCredOffset = sizeof(KERB_SUBMIT_TKT_REQUEST); + memcpy(((CHAR *)pSubmitRequest)+sizeof(KERB_SUBMIT_TKT_REQUEST), + krb_cred->data, krb_cred->length); + if (keyblock) + memcpy(((CHAR *)pSubmitRequest)+sizeof(KERB_SUBMIT_TKT_REQUEST)+krb_cred->length, + keyblock->contents, keyblock->length); + Status = LsaCallAuthenticationPackage( LogonHandle, + PackageId, + pSubmitRequest, + dwRequestLen, + NULL, + NULL, + &SubStatus + ); + + rv = (!FAILED(Status) && !FAILED(SubStatus)); + +cleanup: + free(pSubmitRequest); + krb5_free_keyblock(context, keyblock); + krb5_free_data(context, krb_cred); + krb5_auth_con_free(context, auth_context); + + return rv; +} + +/* + * A simple function to determine if there is an exact match between two tickets + * We rely on the fact that the external tickets contain the raw Kerberos ticket. + * If the EncodedTicket fields match, the KERB_EXTERNAL_TICKETs must be the same. + */ +static BOOL +KerbExternalTicketMatch( PKERB_EXTERNAL_TICKET one, PKERB_EXTERNAL_TICKET two ) +{ + if ( one->EncodedTicketSize != two->EncodedTicketSize ) + return FALSE; + + if ( memcmp(one->EncodedTicket, two->EncodedTicket, one->EncodedTicketSize) ) + return FALSE; + + return TRUE; +} + +krb5_boolean +krb5_is_permitted_tgs_enctype(krb5_context context, krb5_const_principal princ, krb5_enctype etype) +{ + krb5_enctype *list, *ptr; + krb5_boolean ret; + + if (krb5_get_tgs_ktypes(context, princ, &list)) + return(0); + + ret = 0; + + for (ptr = list; *ptr; ptr++) + if (*ptr == etype) + ret = 1; + + krb5_free_enctypes(context, list); + + return(ret); +} + +// to allow the purging of expired tickets from LSA cache. This is necessary +// to force the retrieval of new TGTs. Microsoft does not appear to retrieve +// new tickets when they expire. Instead they continue to accept the expired +// tickets. This is safe to do because the LSA purges its cache when it +// retrieves a new TGT (ms calls this renew) but not when it renews the TGT +// (ms calls this refresh). +// UAC-limited processes are not allowed to obtain a copy of the MSTGT +// session key. We used to check for UAC-limited processes and refuse all +// access to the TGT, but this makes the MSLSA ccache completely unusable. +// Instead we ought to just flag that the tgt session key is not valid. + +static BOOL +GetMSTGT(krb5_context context, HANDLE LogonHandle, ULONG PackageId, KERB_EXTERNAL_TICKET **ticket, BOOL enforce_tgs_enctypes) +{ + // + // INVARIANTS: + // + // (FAILED(Status) || FAILED(SubStatus)) ==> error + // bIsLsaError ==> LsaCallAuthenticationPackage() error + // + + BOOL bIsLsaError = FALSE; + NTSTATUS Status = 0; + NTSTATUS SubStatus = 0; + DWORD Error; + + KERB_QUERY_TKT_CACHE_REQUEST CacheRequest; + PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL; + PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL; + ULONG RequestSize; + ULONG ResponseSize; + int purge_cache = 0; + int ignore_cache = 0; + krb5_enctype *etype_list = NULL, *ptr = NULL, etype = 0; + + memset(&CacheRequest, 0, sizeof(KERB_QUERY_TKT_CACHE_REQUEST)); + CacheRequest.MessageType = KerbRetrieveTicketMessage; + CacheRequest.LogonId.LowPart = 0; + CacheRequest.LogonId.HighPart = 0; + + Status = LsaCallAuthenticationPackage( + LogonHandle, + PackageId, + &CacheRequest, + sizeof(CacheRequest), + &pTicketResponse, + &ResponseSize, + &SubStatus + ); + + if (FAILED(Status)) + { + // if the call to LsaCallAuthenticationPackage failed we cannot + // perform any queries most likely because the Kerberos package + // is not available or we do not have access + bIsLsaError = TRUE; + goto cleanup; + } + + if (FAILED(SubStatus)) { + PSECURITY_LOGON_SESSION_DATA pSessionData = NULL; + BOOL Success = FALSE; + OSVERSIONINFOEX verinfo; + int supported = 0; + + // SubStatus 0x8009030E is not documented. However, it appears + // to mean there is no TGT + if (SubStatus != 0x8009030E) { + bIsLsaError = TRUE; + goto cleanup; + } + + verinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + GetVersionEx((OSVERSIONINFO *)&verinfo); + supported = (verinfo.dwMajorVersion > 5) || + (verinfo.dwMajorVersion == 5 && verinfo.dwMinorVersion >= 1); + + // If we could not get a TGT from the cache we won't know what the + // Kerberos Domain should have been. On Windows XP and 2003 Server + // we can extract it from the Security Logon Session Data. However, + // the required fields are not supported on Windows 2000. :( + if ( supported && GetSecurityLogonSessionData(&pSessionData) ) { + if ( pSessionData->DnsDomainName.Buffer ) { + Error = ConstructTicketRequest(pSessionData->DnsDomainName, + &pTicketRequest, &RequestSize); + LsaFreeReturnBuffer(pSessionData); + if ( Error ) + goto cleanup; + } else { + LsaFreeReturnBuffer(pSessionData); + bIsLsaError = TRUE; + goto cleanup; + } + } else { + CHAR UserDnsDomain[256]; + WCHAR UnicodeUserDnsDomain[256]; + UNICODE_STRING wrapper; + if ( !get_STRING_from_registry(HKEY_CURRENT_USER, + "Volatile Environment", + "USERDNSDOMAIN", + UserDnsDomain, + sizeof(UserDnsDomain) + ) ) + { + goto cleanup; + } + + ANSIToUnicode(UserDnsDomain,UnicodeUserDnsDomain,256); + wrapper.Buffer = UnicodeUserDnsDomain; + wrapper.Length = wcslen(UnicodeUserDnsDomain) * sizeof(WCHAR); + wrapper.MaximumLength = 256; + + Error = ConstructTicketRequest(wrapper, + &pTicketRequest, &RequestSize); + if ( Error ) + goto cleanup; + } + } else { + /* We have succeeded in obtaining a credential from the cache. + * Assuming the enctype is one that we support and the ticket + * has not expired and is not marked invalid we will use it. + * Otherwise, we must create a new ticket request and obtain + * a credential we can use. + */ + + /* Check Supported Enctypes */ + if ( !enforce_tgs_enctypes || + IsMSSessionKeyNull(&pTicketResponse->Ticket.SessionKey) || + krb5_is_permitted_tgs_enctype(context, NULL, pTicketResponse->Ticket.SessionKey.KeyType) ) { + FILETIME Now, MinLife, EndTime, LocalEndTime; + __int64 temp; + // FILETIME is in units of 100 nano-seconds + // If obtained tickets are either expired or have a lifetime + // less than 20 minutes, retry ... + GetSystemTimeAsFileTime(&Now); + EndTime.dwLowDateTime=pTicketResponse->Ticket.EndTime.LowPart; + EndTime.dwHighDateTime=pTicketResponse->Ticket.EndTime.HighPart; + FileTimeToLocalFileTime(&EndTime, &LocalEndTime); + temp = Now.dwHighDateTime; + temp <<= 32; + temp = Now.dwLowDateTime; + temp += 1200 * 10000; + MinLife.dwHighDateTime = (DWORD)((temp >> 32) & 0xFFFFFFFF); + MinLife.dwLowDateTime = (DWORD)(temp & 0xFFFFFFFF); + if (CompareFileTime(&MinLife, &LocalEndTime) >= 0) { + purge_cache = 1; + } + if (pTicketResponse->Ticket.TicketFlags & KERB_TICKET_FLAGS_invalid) { + ignore_cache = 1; // invalid, need to attempt a TGT request + } + goto cleanup; // we have a valid ticket, all done + } else { + // not supported + ignore_cache = 1; + } + + Error = ConstructTicketRequest(pTicketResponse->Ticket.TargetDomainName, + &pTicketRequest, &RequestSize); + if ( Error ) { + goto cleanup; + } + + // + // Free the previous response buffer so we can get the new response. + // + + if ( pTicketResponse ) { + memset(pTicketResponse,0,sizeof(KERB_RETRIEVE_TKT_RESPONSE)); + LsaFreeReturnBuffer(pTicketResponse); + pTicketResponse = NULL; + } + + if ( purge_cache ) { + // + // Purge the existing tickets which we cannot use so new ones can + // be requested. It is not possible to purge just the TGT. All + // service tickets must be purged. + // + PurgeAllTickets(LogonHandle, PackageId); + } + } + + // + // Initialize the request of the request. + // + + pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage; + pTicketRequest->LogonId.LowPart = 0; + pTicketRequest->LogonId.HighPart = 0; + // Note: pTicketRequest->TargetName set up above + pTicketRequest->CacheOptions = ((ignore_cache || !purge_cache) ? + KERB_RETRIEVE_TICKET_DONT_USE_CACHE : 0L); + pTicketRequest->TicketFlags = 0L; + pTicketRequest->EncryptionType = 0L; + + Status = LsaCallAuthenticationPackage( LogonHandle, + PackageId, + pTicketRequest, + RequestSize, + &pTicketResponse, + &ResponseSize, + &SubStatus + ); + + if (FAILED(Status) || FAILED(SubStatus)) + { + bIsLsaError = TRUE; + goto cleanup; + } + + // + // Check to make sure the new tickets we received are of a type we support + // + + /* Check Supported Enctypes */ + if ( !enforce_tgs_enctypes || + krb5_is_permitted_tgs_enctype(context, NULL, pTicketResponse->Ticket.SessionKey.KeyType) ) { + goto cleanup; // we have a valid ticket, all done + } + + if (krb5_get_tgs_ktypes(context, NULL, &etype_list)) { + /* No enctypes - nothing we can do. */ + bIsLsaError = TRUE; + goto cleanup; + } + + ptr = etype_list + 1; + etype = *etype_list; + + while ( etype ) { + // Try once more but this time specify the Encryption Type + // (This will not store the retrieved tickets in the LSA cache unless + // 0 is supported.) + pTicketRequest->EncryptionType = etype; + pTicketRequest->CacheOptions = KERB_RETRIEVE_TICKET_CACHE_TICKET; + + if ( pTicketResponse ) { + memset(pTicketResponse,0,sizeof(KERB_RETRIEVE_TKT_RESPONSE)); + LsaFreeReturnBuffer(pTicketResponse); + pTicketResponse = NULL; + } + + Status = LsaCallAuthenticationPackage( LogonHandle, + PackageId, + pTicketRequest, + RequestSize, + &pTicketResponse, + &ResponseSize, + &SubStatus + ); + + if (FAILED(Status) || FAILED(SubStatus)) + { + bIsLsaError = TRUE; + goto cleanup; + } + + if ( pTicketResponse->Ticket.SessionKey.KeyType == etype && + (!enforce_tgs_enctypes || + krb5_is_permitted_tgs_enctype(context, NULL, pTicketResponse->Ticket.SessionKey.KeyType)) ) { + goto cleanup; // we have a valid ticket, all done + } + + if ( ptr ) { + etype = *ptr++; + } else { + etype = 0; + } + } + +cleanup: + if ( etype_list ) + krb5_free_enctypes(context, etype_list); + + if ( pTicketRequest ) + LocalFree(pTicketRequest); + + if (FAILED(Status) || FAILED(SubStatus)) + { + if (bIsLsaError) + { + // XXX - Will be fixed later + if (FAILED(Status)) + ShowLsaError("LsaCallAuthenticationPackage", Status); + if (FAILED(SubStatus)) + ShowLsaError("LsaCallAuthenticationPackage", SubStatus); + } + else + { + ShowWinError("GetMSTGT", Status); + } + + if (pTicketResponse) { + memset(pTicketResponse,0,sizeof(KERB_RETRIEVE_TKT_RESPONSE)); + LsaFreeReturnBuffer(pTicketResponse); + pTicketResponse = NULL; + } + return(FALSE); + } + + *ticket = &(pTicketResponse->Ticket); + return(TRUE); +} + +static BOOL +GetQueryTktCacheResponseEx(HANDLE LogonHandle, ULONG PackageId, + PKERB_QUERY_TKT_CACHE_EX_RESPONSE * ppResponse) +{ + NTSTATUS Status = 0; + NTSTATUS SubStatus = 0; + + KERB_QUERY_TKT_CACHE_REQUEST CacheRequest; + PKERB_QUERY_TKT_CACHE_EX_RESPONSE pQueryResponse = NULL; + ULONG ResponseSize; + + CacheRequest.MessageType = KerbQueryTicketCacheExMessage; + CacheRequest.LogonId.LowPart = 0; + CacheRequest.LogonId.HighPart = 0; + + Status = LsaCallAuthenticationPackage( + LogonHandle, + PackageId, + &CacheRequest, + sizeof(CacheRequest), + &pQueryResponse, + &ResponseSize, + &SubStatus + ); + + if ( !(FAILED(Status) || FAILED(SubStatus)) ) { + *ppResponse = pQueryResponse; + return TRUE; + } + + return FALSE; +} + +static BOOL +GetQueryTktCacheResponseEx2(HANDLE LogonHandle, ULONG PackageId, + PKERB_QUERY_TKT_CACHE_EX2_RESPONSE * ppResponse) +{ + NTSTATUS Status = 0; + NTSTATUS SubStatus = 0; + + KERB_QUERY_TKT_CACHE_REQUEST CacheRequest; + PKERB_QUERY_TKT_CACHE_EX2_RESPONSE pQueryResponse = NULL; + ULONG ResponseSize; + + CacheRequest.MessageType = KerbQueryTicketCacheEx2Message; + CacheRequest.LogonId.LowPart = 0; + CacheRequest.LogonId.HighPart = 0; + + Status = LsaCallAuthenticationPackage( + LogonHandle, + PackageId, + &CacheRequest, + sizeof(CacheRequest), + &pQueryResponse, + &ResponseSize, + &SubStatus + ); + + if ( !(FAILED(Status) || FAILED(SubStatus)) ) { + *ppResponse = pQueryResponse; + return TRUE; + } + + return FALSE; +} + +static BOOL +GetMSCacheTicketFromMITCred( HANDLE LogonHandle, ULONG PackageId, + krb5_context context, krb5_creds *creds, + PKERB_EXTERNAL_TICKET *ticket) +{ + NTSTATUS Status = 0; + NTSTATUS SubStatus = 0; + ULONG RequestSize; + PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL; + PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL; + ULONG ResponseSize; + + RequestSize = sizeof(*pTicketRequest) + MAX_MSPRINC_SIZE; + + pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize); + if (!pTicketRequest) + return FALSE; + + pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage; + pTicketRequest->LogonId.LowPart = 0; + pTicketRequest->LogonId.HighPart = 0; + + pTicketRequest->TargetName.Length = 0; + pTicketRequest->TargetName.MaximumLength = MAX_MSPRINC_SIZE; + pTicketRequest->TargetName.Buffer = (PWSTR) (pTicketRequest + 1); + MITPrincToMSPrinc(context, creds->server, &pTicketRequest->TargetName); + pTicketRequest->CacheOptions = KERB_RETRIEVE_TICKET_CACHE_TICKET; + pTicketRequest->TicketFlags = creds->ticket_flags; + pTicketRequest->EncryptionType = creds->keyblock.enctype; + + Status = LsaCallAuthenticationPackage( LogonHandle, + PackageId, + pTicketRequest, + RequestSize, + &pTicketResponse, + &ResponseSize, + &SubStatus + ); + + LocalFree(pTicketRequest); + + if (FAILED(Status) || FAILED(SubStatus)) + return(FALSE); + + /* otherwise return ticket */ + *ticket = &(pTicketResponse->Ticket); + return(TRUE); +} + +static BOOL +GetMSCacheTicketFromCacheInfoEx(HANDLE LogonHandle, ULONG PackageId, + PKERB_TICKET_CACHE_INFO_EX tktinfo, + PKERB_EXTERNAL_TICKET *ticket) +{ + NTSTATUS Status = 0; + NTSTATUS SubStatus = 0; + ULONG RequestSize; + PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL; + PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL; + ULONG ResponseSize; + + RequestSize = sizeof(*pTicketRequest) + tktinfo->ServerName.Length; + + pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize); + if (!pTicketRequest) + return FALSE; + + pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage; + pTicketRequest->LogonId.LowPart = 0; + pTicketRequest->LogonId.HighPart = 0; + pTicketRequest->TargetName.Length = tktinfo->ServerName.Length; + pTicketRequest->TargetName.MaximumLength = tktinfo->ServerName.Length; + pTicketRequest->TargetName.Buffer = (PWSTR) (pTicketRequest + 1); + memcpy(pTicketRequest->TargetName.Buffer,tktinfo->ServerName.Buffer, tktinfo->ServerName.Length); + pTicketRequest->CacheOptions = 0; + pTicketRequest->EncryptionType = tktinfo->EncryptionType; + pTicketRequest->TicketFlags = 0; + if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_forwardable ) + pTicketRequest->TicketFlags |= KDC_OPT_FORWARDABLE; + if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_forwarded ) + pTicketRequest->TicketFlags |= KDC_OPT_FORWARDED; + if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_proxiable ) + pTicketRequest->TicketFlags |= KDC_OPT_PROXIABLE; + if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_renewable ) + pTicketRequest->TicketFlags |= KDC_OPT_RENEWABLE; + + Status = LsaCallAuthenticationPackage( + LogonHandle, + PackageId, + pTicketRequest, + RequestSize, + &pTicketResponse, + &ResponseSize, + &SubStatus + ); + + LocalFree(pTicketRequest); + + if (FAILED(Status) || FAILED(SubStatus)) + return(FALSE); + + /* otherwise return ticket */ + *ticket = &(pTicketResponse->Ticket); + + /* set the initial flag if we were attempting to retrieve one + * because Windows won't necessarily return the initial ticket + * to us. + */ + if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_initial ) + (*ticket)->TicketFlags |= KERB_TICKET_FLAGS_initial; + + return(TRUE); +} + +static BOOL +GetMSCacheTicketFromCacheInfoEx2(HANDLE LogonHandle, ULONG PackageId, + PKERB_TICKET_CACHE_INFO_EX2 tktinfo, + PKERB_EXTERNAL_TICKET *ticket) +{ + NTSTATUS Status = 0; + NTSTATUS SubStatus = 0; + ULONG RequestSize; + PKERB_RETRIEVE_TKT_REQUEST pTicketRequest = NULL; + PKERB_RETRIEVE_TKT_RESPONSE pTicketResponse = NULL; + ULONG ResponseSize; + + RequestSize = sizeof(*pTicketRequest) + tktinfo->ServerName.Length; + + pTicketRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, RequestSize); + if (!pTicketRequest) + return FALSE; + + pTicketRequest->MessageType = KerbRetrieveEncodedTicketMessage; + pTicketRequest->LogonId.LowPart = 0; + pTicketRequest->LogonId.HighPart = 0; + pTicketRequest->TargetName.Length = tktinfo->ServerName.Length; + pTicketRequest->TargetName.MaximumLength = tktinfo->ServerName.Length; + pTicketRequest->TargetName.Buffer = (PWSTR) (pTicketRequest + 1); + memcpy(pTicketRequest->TargetName.Buffer,tktinfo->ServerName.Buffer, tktinfo->ServerName.Length); + pTicketRequest->CacheOptions = KERB_RETRIEVE_TICKET_CACHE_TICKET; + pTicketRequest->EncryptionType = tktinfo->SessionKeyType; + pTicketRequest->TicketFlags = 0; + if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_forwardable ) + pTicketRequest->TicketFlags |= KDC_OPT_FORWARDABLE; + if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_forwarded ) + pTicketRequest->TicketFlags |= KDC_OPT_FORWARDED; + if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_proxiable ) + pTicketRequest->TicketFlags |= KDC_OPT_PROXIABLE; + if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_renewable ) + pTicketRequest->TicketFlags |= KDC_OPT_RENEWABLE; + + Status = LsaCallAuthenticationPackage( + LogonHandle, + PackageId, + pTicketRequest, + RequestSize, + &pTicketResponse, + &ResponseSize, + &SubStatus + ); + + LocalFree(pTicketRequest); + + if (FAILED(Status) || FAILED(SubStatus)) + return(FALSE); + + /* otherwise return ticket */ + *ticket = &(pTicketResponse->Ticket); + + + /* set the initial flag if we were attempting to retrieve one + * because Windows won't necessarily return the initial ticket + * to us. + */ + if ( tktinfo->TicketFlags & KERB_TICKET_FLAGS_initial ) + (*ticket)->TicketFlags |= KERB_TICKET_FLAGS_initial; + + return(TRUE); +} + +static krb5_error_code KRB5_CALLCONV krb5_lcc_close +(krb5_context, krb5_ccache id); + +static krb5_error_code KRB5_CALLCONV krb5_lcc_destroy +(krb5_context, krb5_ccache id); + +static krb5_error_code KRB5_CALLCONV krb5_lcc_end_seq_get +(krb5_context, krb5_ccache id, krb5_cc_cursor *cursor); + +static krb5_error_code KRB5_CALLCONV krb5_lcc_generate_new +(krb5_context, krb5_ccache *id); + +static const char * KRB5_CALLCONV krb5_lcc_get_name +(krb5_context, krb5_ccache id); + +static krb5_error_code KRB5_CALLCONV krb5_lcc_get_principal +(krb5_context, krb5_ccache id, krb5_principal *princ); + +static krb5_error_code KRB5_CALLCONV krb5_lcc_initialize +(krb5_context, krb5_ccache id, krb5_principal princ); + +static krb5_error_code KRB5_CALLCONV krb5_lcc_next_cred +(krb5_context, krb5_ccache id, krb5_cc_cursor *cursor, + krb5_creds *creds); + +static krb5_error_code KRB5_CALLCONV krb5_lcc_resolve +(krb5_context, krb5_ccache *id, const char *residual); + +static krb5_error_code KRB5_CALLCONV krb5_lcc_retrieve +(krb5_context, krb5_ccache id, krb5_flags whichfields, + krb5_creds *mcreds, krb5_creds *creds); + +static krb5_error_code KRB5_CALLCONV krb5_lcc_start_seq_get +(krb5_context, krb5_ccache id, krb5_cc_cursor *cursor); + +static krb5_error_code KRB5_CALLCONV krb5_lcc_store +(krb5_context, krb5_ccache id, krb5_creds *creds); + +static krb5_error_code KRB5_CALLCONV krb5_lcc_set_flags +(krb5_context, krb5_ccache id, krb5_flags flags); + +static krb5_error_code KRB5_CALLCONV krb5_lcc_get_flags +(krb5_context, krb5_ccache id, krb5_flags *flags); + +extern const krb5_cc_ops krb5_lcc_ops; + +krb5_error_code krb5_change_cache (void); + +krb5_boolean +krb5int_cc_creds_match_request(krb5_context, krb5_flags whichfields, krb5_creds *mcreds, krb5_creds *creds); + +#define KRB5_OK 0 + +typedef struct _krb5_lcc_data { + HANDLE LogonHandle; + ULONG PackageId; + char * cc_name; + krb5_principal princ; + krb5_flags flags; +} krb5_lcc_data; + +typedef struct _krb5_lcc_cursor { + union { + PKERB_QUERY_TKT_CACHE_RESPONSE w2k; + PKERB_QUERY_TKT_CACHE_EX_RESPONSE xp; + PKERB_QUERY_TKT_CACHE_EX2_RESPONSE ex2; + } response; + unsigned int index; + PKERB_EXTERNAL_TICKET mstgt; +} krb5_lcc_cursor; + + +/* + * Requires: + * residual is ignored + * + * Modifies: + * id + * + * Effects: + * Access the MS Kerberos LSA cache in the current logon session + * Ignore the residual. + * + * Returns: + * A filled in krb5_ccache structure "id". + * + * Errors: + * KRB5_CC_NOMEM - there was insufficient memory to allocate the + * + * krb5_ccache. id is undefined. + * permission errors + */ +static krb5_error_code KRB5_CALLCONV +krb5_lcc_resolve (krb5_context context, krb5_ccache *id, const char *residual) +{ + krb5_ccache lid; + krb5_lcc_data *data; + HANDLE LogonHandle; + ULONG PackageId, i; + PKERB_QUERY_TKT_CACHE_EX_RESPONSE pResponse; + + if (!PackageConnectLookup(&LogonHandle, &PackageId)) + return KRB5_FCC_NOFILE; + + lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache)); + if (lid == NULL) { + LsaDeregisterLogonProcess(LogonHandle); + return KRB5_CC_NOMEM; + } + + lid->ops = &krb5_lcc_ops; + + lid->data = (krb5_pointer) malloc(sizeof(krb5_lcc_data)); + if (lid->data == NULL) { + free(lid); + LsaDeregisterLogonProcess(LogonHandle); + return KRB5_CC_NOMEM; + } + + lid->magic = KV5M_CCACHE; + data = (krb5_lcc_data *)lid->data; + data->LogonHandle = LogonHandle; + data->PackageId = PackageId; + data->princ = NULL; + data->flags = 0; + + data->cc_name = (char *)malloc(strlen(residual)+1); + if (data->cc_name == NULL) { + free(lid->data); + free(lid); + LsaDeregisterLogonProcess(LogonHandle); + return KRB5_CC_NOMEM; + } + strcpy(data->cc_name, residual); + + /* If there are already tickets present, grab a client principal name. */ + if (GetQueryTktCacheResponseEx(LogonHandle, PackageId, &pResponse)) { + /* Take the first client principal we find; they should all be the + * same anyway. */ + for (i = 0; i < pResponse->CountOfTickets; i++) { + if (UnicodeStringToMITPrinc(&pResponse->Tickets[i].ClientName, + &pResponse->Tickets[i].ClientRealm, + context, &data->princ)) + break; + + } + LsaFreeReturnBuffer(pResponse); + } + + /* + * other routines will get errors on open, and callers must expect them, + * if cache is non-existent/unusable + */ + *id = lid; + return KRB5_OK; +} + +/* + * return success although we do not do anything + * We should delete all tickets belonging to the specified principal + */ + +static krb5_error_code KRB5_CALLCONV +krb5_lcc_remove_cred(krb5_context context, krb5_ccache id, krb5_flags flags, + krb5_creds *creds); + +static krb5_error_code KRB5_CALLCONV +krb5_lcc_initialize(krb5_context context, krb5_ccache id, krb5_principal princ) +{ + krb5_cc_cursor cursor; + krb5_error_code code; + krb5_creds cred; + + code = krb5_cc_start_seq_get(context, id, &cursor); + if (code) { + if (code == KRB5_CC_NOTFOUND) + return KRB5_OK; + return code; + } + + while ( !(code = krb5_cc_next_cred(context, id, &cursor, &cred)) ) + { + if ( krb5_principal_compare(context, princ, cred.client) ) { + code = krb5_lcc_remove_cred(context, id, 0, &cred); + } + krb5_free_cred_contents(context, &cred); + } + + if (code == KRB5_CC_END || code == KRB5_CC_NOTFOUND) + { + krb5_cc_end_seq_get(context, id, &cursor); + return KRB5_OK; + } + return code; +} + +/* + * Modifies: + * id + * + * Effects: + * Closes the microsoft lsa cache, invalidates the id, and frees any resources + * associated with the cache. + */ +static krb5_error_code KRB5_CALLCONV +krb5_lcc_close(krb5_context context, krb5_ccache id) +{ + int closeval = KRB5_OK; + krb5_lcc_data *data; + + if (id) { + data = (krb5_lcc_data *) id->data; + + if (data) { + LsaDeregisterLogonProcess(data->LogonHandle); + if (data->cc_name) + free(data->cc_name); + free(data); + } + free(id); + } + return closeval; +} + +/* + * Effects: + * Destroys the contents of id. + * + * Errors: + * system errors + */ +static krb5_error_code KRB5_CALLCONV +krb5_lcc_destroy(krb5_context context, krb5_ccache id) +{ + krb5_lcc_data *data; + + if (id) { + data = (krb5_lcc_data *) id->data; + + return PurgeAllTickets(data->LogonHandle, data->PackageId) ? KRB5_OK : KRB5_FCC_INTERNAL; + } + return KRB5_FCC_INTERNAL; +} + +/* + * Effects: + * Prepares for a sequential search of the credentials cache. + * Returns a krb5_cc_cursor to be used with krb5_lcc_next_cred and + * krb5_lcc_end_seq_get. + * + * If the cache is modified between the time of this call and the time + * of the final krb5_lcc_end_seq_get, the results are undefined. + * + * Errors: + * KRB5_CC_NOMEM + * KRB5_FCC_INTERNAL - system errors + */ +static krb5_error_code KRB5_CALLCONV +krb5_lcc_start_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor) +{ + krb5_lcc_cursor *lcursor; + krb5_lcc_data *data = (krb5_lcc_data *)id->data; + + lcursor = (krb5_lcc_cursor *) malloc(sizeof(krb5_lcc_cursor)); + if (lcursor == NULL) { + *cursor = 0; + return KRB5_CC_NOMEM; + } + + /* + * obtain a tgt to refresh the ccache in case the ticket is expired + */ + if (!GetMSTGT(context, data->LogonHandle, data->PackageId, &lcursor->mstgt, TRUE)) { + free(lcursor); + *cursor = 0; + return KRB5_CC_NOTFOUND; + } + + if ( does_query_ticket_cache_ex2() ) { + if (!GetQueryTktCacheResponseEx2(data->LogonHandle, data->PackageId, + &lcursor->response.ex2)) { + LsaFreeReturnBuffer(lcursor->mstgt); + free(lcursor); + *cursor = 0; + return KRB5_FCC_INTERNAL; + } + } else + if (!GetQueryTktCacheResponseEx(data->LogonHandle, data->PackageId, + &lcursor->response.xp)) { + LsaFreeReturnBuffer(lcursor->mstgt); + free(lcursor); + *cursor = 0; + return KRB5_FCC_INTERNAL; + } + lcursor->index = 0; + *cursor = (krb5_cc_cursor) lcursor; + return KRB5_OK; +} + + +/* + * Requires: + * cursor is a krb5_cc_cursor originally obtained from + * krb5_lcc_start_seq_get. + * + * Modifies: + * cursor + * + * Effects: + * Fills in creds with the TGT obtained from the MS LSA + * + * The cursor is updated to indicate TGT retrieval + * + * Errors: + * KRB5_CC_END + * KRB5_FCC_INTERNAL - system errors + */ +static krb5_error_code KRB5_CALLCONV +krb5_lcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor, krb5_creds *creds) +{ + krb5_lcc_cursor *lcursor = (krb5_lcc_cursor *) *cursor; + krb5_lcc_data *data; + KERB_EXTERNAL_TICKET *msticket; + krb5_error_code retval = KRB5_OK; + + data = (krb5_lcc_data *)id->data; + +next_cred: + if ( does_query_ticket_cache_ex2() ) { + if ( lcursor->index >= lcursor->response.ex2->CountOfTickets ) { + if (retval == KRB5_OK) + return KRB5_CC_END; + else { + LsaFreeReturnBuffer(lcursor->mstgt); + LsaFreeReturnBuffer(lcursor->response.ex2); + free(*cursor); + *cursor = 0; + return retval; + } + } + + if ( data->flags & KRB5_TC_NOTICKET ) { + if (!CacheInfoEx2ToMITCred( &lcursor->response.ex2->Tickets[lcursor->index++], + context, creds)) { + retval = KRB5_FCC_INTERNAL; + goto next_cred; + } + return KRB5_OK; + } else { + if (!GetMSCacheTicketFromCacheInfoEx2(data->LogonHandle, + data->PackageId, + &lcursor->response.ex2->Tickets[lcursor->index++],&msticket)) { + retval = KRB5_FCC_INTERNAL; + goto next_cred; + } + } + } else { + if (lcursor->index >= lcursor->response.xp->CountOfTickets) { + if (retval == KRB5_OK) { + return KRB5_CC_END; + } else { + LsaFreeReturnBuffer(lcursor->mstgt); + LsaFreeReturnBuffer(lcursor->response.xp); + free(*cursor); + *cursor = 0; + return retval; + } + } + + if (!GetMSCacheTicketFromCacheInfoEx(data->LogonHandle, + data->PackageId, + &lcursor->response.xp->Tickets[lcursor->index++], + &msticket)) { + retval = KRB5_FCC_INTERNAL; + goto next_cred; + } + } + + /* Don't return tickets with NULL Session Keys */ + if ( IsMSSessionKeyNull(&msticket->SessionKey) ) { + LsaFreeReturnBuffer(msticket); + goto next_cred; + } + + /* convert the ticket */ + if ( does_query_ticket_cache_ex2() ) { + if (!MSCredToMITCred(msticket, lcursor->response.ex2->Tickets[lcursor->index-1].ClientRealm, context, creds)) + retval = KRB5_FCC_INTERNAL; + } else { + if (!MSCredToMITCred(msticket, + lcursor->response.xp->Tickets[lcursor->index - + 1].ClientRealm, + context, creds)) + retval = KRB5_FCC_INTERNAL; + } + LsaFreeReturnBuffer(msticket); + return retval; +} + +/* + * Requires: + * cursor is a krb5_cc_cursor originally obtained from + * krb5_lcc_start_seq_get. + * + * Modifies: + * id, cursor + * + * Effects: + * Finishes sequential processing of the file credentials ccache id, + * and invalidates the cursor (it must never be used after this call). + */ +/* ARGSUSED */ +static krb5_error_code KRB5_CALLCONV +krb5_lcc_end_seq_get(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor) +{ + krb5_lcc_cursor *lcursor = (krb5_lcc_cursor *) *cursor; + + if ( lcursor ) { + LsaFreeReturnBuffer(lcursor->mstgt); + if ( does_query_ticket_cache_ex2() ) + LsaFreeReturnBuffer(lcursor->response.ex2); + else + LsaFreeReturnBuffer(lcursor->response.xp); + free(*cursor); + } + *cursor = 0; + + return KRB5_OK; +} + + +/* + * Errors: + * KRB5_CC_READONLY - not supported + */ +static krb5_error_code KRB5_CALLCONV +krb5_lcc_generate_new (krb5_context context, krb5_ccache *id) +{ + return KRB5_CC_READONLY; +} + +/* + * Requires: + * id is a ms lsa credential cache + * + * Returns: + * The ccname specified during the krb5_lcc_resolve call + */ +static const char * KRB5_CALLCONV +krb5_lcc_get_name (krb5_context context, krb5_ccache id) +{ + + if ( !id ) + return ""; + + return (char *) ((krb5_lcc_data *) id->data)->cc_name; +} + +/* + * Modifies: + * id, princ + * + * Effects: + * Retrieves the primary principal from id, as set with + * krb5_lcc_initialize. The principal is returned is allocated + * storage that must be freed by the caller via krb5_free_principal. + * + * Errors: + * system errors + * KRB5_CC_NOT_KTYPE + */ +static krb5_error_code KRB5_CALLCONV +krb5_lcc_get_principal(krb5_context context, krb5_ccache id, krb5_principal *princ) +{ + PKERB_QUERY_TKT_CACHE_EX_RESPONSE pResponse; + krb5_lcc_data *data = (krb5_lcc_data *)id->data; + ULONG i; + + /* obtain principal */ + if (data->princ) + return krb5_copy_principal(context, data->princ, princ); + else { + if (GetQueryTktCacheResponseEx(data->LogonHandle, data->PackageId, + &pResponse)) { + /* Take the first client principal we find; they should all be the + * same anyway. */ + for (i = 0; i < pResponse->CountOfTickets; i++) { + if (UnicodeStringToMITPrinc(&pResponse->Tickets[i].ClientName, + &pResponse->Tickets[i].ClientRealm, + context, &data->princ)) + break; + } + LsaFreeReturnBuffer(pResponse); + if (data->princ) + return krb5_copy_principal(context, data->princ, princ); + } + } + return KRB5_CC_NOTFOUND; +} + + +static krb5_error_code KRB5_CALLCONV +krb5_lcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields, + krb5_creds *mcreds, krb5_creds *creds) +{ + krb5_error_code kret = KRB5_OK; + krb5_lcc_data *data = (krb5_lcc_data *)id->data; + KERB_EXTERNAL_TICKET *msticket = 0, *mstgt = 0, *mstmp = 0; + krb5_creds * mcreds_noflags = 0; + krb5_creds fetchcreds; + PKERB_QUERY_TKT_CACHE_EX_RESPONSE pResponse = 0; + unsigned int i; + + memset(&fetchcreds, 0, sizeof(krb5_creds)); + + /* first try to find out if we have an existing ticket which meets the requirements */ + kret = k5_cc_retrieve_cred_default(context, id, whichfields, mcreds, + creds); + /* This sometimes returns a zero-length ticket; work around it. */ + if ( !kret && creds->ticket.length > 0 ) + return KRB5_OK; + + /* if not, we must try to get a ticket without specifying any flags or etypes */ + kret = krb5_copy_creds(context, mcreds, &mcreds_noflags); + if (kret) + goto cleanup; + mcreds_noflags->ticket_flags = 0; + mcreds_noflags->keyblock.enctype = 0; + + if (!GetMSCacheTicketFromMITCred(data->LogonHandle, data->PackageId, context, mcreds_noflags, &msticket)) { + kret = KRB5_CC_NOTFOUND; + goto cleanup; + } + + /* try again to find out if we have an existing ticket which meets the requirements */ + kret = k5_cc_retrieve_cred_default(context, id, whichfields, mcreds, + creds); + /* This sometimes returns a zero-length ticket; work around it. */ + if ( !kret && creds->ticket.length > 0 ) + goto cleanup; + + /* if not, obtain a ticket using the request flags and enctype even though it may not + * be stored in the LSA cache for future use. + */ + if ( msticket ) { + LsaFreeReturnBuffer(msticket); + msticket = 0; + } + + if (!GetMSCacheTicketFromMITCred(data->LogonHandle, data->PackageId, context, mcreds, &msticket)) { + kret = KRB5_CC_NOTFOUND; + goto cleanup; + } + + /* convert the ticket */ + /* + * We can obtain the correct client realm for a ticket by walking the + * cache contents until we find the matching service ticket. + */ + + if (!GetQueryTktCacheResponseEx(data->LogonHandle, data->PackageId, + &pResponse)) { + kret = KRB5_FCC_INTERNAL; + goto cleanup; + } + + for (i = 0; i < pResponse->CountOfTickets; i++) { + if (!GetMSCacheTicketFromCacheInfoEx(data->LogonHandle, + data->PackageId, + &pResponse->Tickets[i], &mstmp)) { + continue; + } + + if (KerbExternalTicketMatch(msticket,mstmp)) + break; + + LsaFreeReturnBuffer(mstmp); + mstmp = 0; + } + + if (!MSCredToMITCred(msticket, mstmp ? + pResponse->Tickets[i].ClientRealm : + msticket->DomainName, context, &fetchcreds)) { + LsaFreeReturnBuffer(pResponse); + kret = KRB5_FCC_INTERNAL; + goto cleanup; + } + LsaFreeReturnBuffer(pResponse); + + + /* check to see if this ticket matches the request using logic from + * k5_cc_retrieve_cred_default() + */ + if ( krb5int_cc_creds_match_request(context, whichfields, mcreds, &fetchcreds) ) { + *creds = fetchcreds; + } else { + krb5_free_cred_contents(context, &fetchcreds); + kret = KRB5_CC_NOTFOUND; + } + +cleanup: + if ( mstmp ) + LsaFreeReturnBuffer(mstmp); + if ( mstgt ) + LsaFreeReturnBuffer(mstgt); + if ( msticket ) + LsaFreeReturnBuffer(msticket); + if ( mcreds_noflags ) + krb5_free_creds(context, mcreds_noflags); + return kret; +} + + +/* + * We can't write to the MS LSA cache. So we request the cache to obtain a ticket for the same + * principal in the hope that next time the application requires a ticket for the service it + * is attempt to store, the retrieved ticket will be good enough. + * + * Errors: + * KRB5_CC_READONLY - not supported + */ +static krb5_error_code KRB5_CALLCONV +krb5_lcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds) +{ + krb5_error_code kret = KRB5_OK; + krb5_lcc_data *data = (krb5_lcc_data *)id->data; + KERB_EXTERNAL_TICKET *msticket = 0, *msticket2 = 0; + krb5_creds * creds_noflags = 0; + + if (krb5_is_config_principal(context, creds->server)) { + /* mslsa cannot store config creds, so we have to bail. + * The 'right' thing to do would be to return an appropriate error, + * but that would require modifying the calling code to check + * for that error and ignore it. + */ + return KRB5_OK; + } + + if (KerbSubmitTicket( data->LogonHandle, data->PackageId, context, creds )) + return KRB5_OK; + + /* If not, lets try to obtain a matching ticket from the KDC */ + if ( creds->ticket_flags != 0 && creds->keyblock.enctype != 0 ) { + /* if not, we must try to get a ticket without specifying any flags or etypes */ + kret = krb5_copy_creds(context, creds, &creds_noflags); + if (kret == 0) { + creds_noflags->ticket_flags = 0; + creds_noflags->keyblock.enctype = 0; + + GetMSCacheTicketFromMITCred(data->LogonHandle, data->PackageId, context, creds_noflags, &msticket2); + krb5_free_creds(context, creds_noflags); + } + } + + GetMSCacheTicketFromMITCred(data->LogonHandle, data->PackageId, context, creds, &msticket); + if (msticket || msticket2) { + if (msticket) + LsaFreeReturnBuffer(msticket); + if (msticket2) + LsaFreeReturnBuffer(msticket2); + return KRB5_OK; + } + return KRB5_CC_READONLY; +} + +/* + * Individual credentials can be implemented differently depending + * on the operating system version. (undocumented.) + * + * Errors: + * KRB5_CC_READONLY: + */ +static krb5_error_code KRB5_CALLCONV +krb5_lcc_remove_cred(krb5_context context, krb5_ccache id, krb5_flags flags, + krb5_creds *creds) +{ + krb5_lcc_data *data = (krb5_lcc_data *)id->data; + + if (PurgeTicketEx(data->LogonHandle, data->PackageId, context, flags, + creds)) + return KRB5_OK; + + return KRB5_CC_READONLY; +} + + +/* + * Effects: + * Set + */ +static krb5_error_code KRB5_CALLCONV +krb5_lcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags) +{ + krb5_lcc_data *data = (krb5_lcc_data *)id->data; + + data->flags = flags; + return KRB5_OK; +} + +static krb5_error_code KRB5_CALLCONV +krb5_lcc_get_flags(krb5_context context, krb5_ccache id, krb5_flags *flags) +{ + krb5_lcc_data *data = (krb5_lcc_data *)id->data; + + *flags = data->flags; + return KRB5_OK; +} + +static krb5_error_code KRB5_CALLCONV +krb5_lcc_ptcursor_new(krb5_context context, krb5_cc_ptcursor *cursor) +{ + krb5_cc_ptcursor new_cursor = (krb5_cc_ptcursor )malloc(sizeof(*new_cursor)); + if (!new_cursor) + return ENOMEM; + new_cursor->ops = &krb5_lcc_ops; + new_cursor->data = (krb5_pointer)(1); + *cursor = new_cursor; + new_cursor = NULL; + return 0; +} + +static krb5_error_code KRB5_CALLCONV +krb5_lcc_ptcursor_next(krb5_context context, krb5_cc_ptcursor cursor, krb5_ccache *ccache) +{ + krb5_error_code code = 0; + *ccache = 0; + if (cursor->data == NULL) + return 0; + + cursor->data = NULL; + if ((code = krb5_lcc_resolve(context, ccache, ""))) { + if (code != KRB5_FCC_NOFILE) + /* Note that we only want to return serious errors. + * Any non-zero return code will prevent the cccol iterator + * from advancing to the next ccache collection. */ + return code; + } + return 0; +} + +static krb5_error_code KRB5_CALLCONV +krb5_lcc_ptcursor_free(krb5_context context, krb5_cc_ptcursor *cursor) +{ + if (*cursor) { + free(*cursor); + *cursor = NULL; + } + return 0; +} + +const krb5_cc_ops krb5_lcc_ops = { + 0, + "MSLSA", + krb5_lcc_get_name, + krb5_lcc_resolve, + krb5_lcc_generate_new, + krb5_lcc_initialize, + krb5_lcc_destroy, + krb5_lcc_close, + krb5_lcc_store, + krb5_lcc_retrieve, + krb5_lcc_get_principal, + krb5_lcc_start_seq_get, + krb5_lcc_next_cred, + krb5_lcc_end_seq_get, + krb5_lcc_remove_cred, + krb5_lcc_set_flags, + krb5_lcc_get_flags, + krb5_lcc_ptcursor_new, + krb5_lcc_ptcursor_next, + krb5_lcc_ptcursor_free, + NULL, /* move */ + NULL, /* wasdefault */ + NULL, /* lock */ + NULL, /* unlock */ + NULL, /* switch_to */ +}; +#endif /* _WIN32 */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/cc_retr.c b/krb5-1.21.3/src/lib/krb5/ccache/cc_retr.c new file mode 100644 index 00000000..4328b7d6 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/cc_retr.c @@ -0,0 +1,276 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/cc_retr.c */ +/* + * Copyright 1990,1991,1999,2007,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "cc-int.h" +#include "../krb/int-proto.h" + +#define KRB5_OK 0 + +static int +times_match_exact(const krb5_ticket_times *t1, const krb5_ticket_times *t2) +{ + return (t1->authtime == t2->authtime && + t1->starttime == t2->starttime && + t1->endtime == t2->endtime && + t1->renew_till == t2->renew_till); +} + +static krb5_boolean +times_match(const krb5_ticket_times *t1, const krb5_ticket_times *t2) +{ + if (t1->renew_till) { + if (ts_after(t1->renew_till, t2->renew_till)) + return FALSE; /* this one expires too late */ + } + if (t1->endtime) { + if (ts_after(t1->endtime, t2->endtime)) + return FALSE; /* this one expires too late */ + } + /* only care about expiration on a times_match */ + return TRUE; +} + +static krb5_boolean +princs_match(krb5_context context, krb5_flags whichfields, + const krb5_creds *mcreds, const krb5_creds *creds) +{ + if (mcreds->client != NULL && + !krb5_principal_compare(context, mcreds->client, creds->client)) + return FALSE; + if (mcreds->server == NULL) + return TRUE; + if (whichfields & KRB5_TC_MATCH_SRV_NAMEONLY) { + return krb5_principal_compare_any_realm(context, mcreds->server, + creds->server); + } else { + return krb5_principal_compare(context, mcreds->server, creds->server); + } +} + +static krb5_boolean +authdata_match(krb5_authdata *const *mdata, krb5_authdata *const *data) +{ + const krb5_authdata *mdatap, *datap; + + if (mdata == data) + return TRUE; + + if (mdata == NULL) + return *data == NULL; + + if (data == NULL) + return *mdata == NULL; + + while ((mdatap = *mdata) && (datap = *data)) { + if ((mdatap->ad_type != datap->ad_type) || + (mdatap->length != datap->length) || + (memcmp ((char *)mdatap->contents, + (char *)datap->contents, (unsigned) mdatap->length) != 0)) + return FALSE; + mdata++; + data++; + } + return (*mdata == NULL) && (*data == NULL); +} + +static krb5_boolean +data_match(const krb5_data *data1, const krb5_data *data2) +{ + if (!data1) { + if (!data2) + return TRUE; + else + return FALSE; + } + if (!data2) return FALSE; + + return data_eq(*data1, *data2) ? TRUE : FALSE; +} + +static int +pref (krb5_enctype my_ktype, int nktypes, krb5_enctype *ktypes) +{ + int i; + for (i = 0; i < nktypes; i++) + if (my_ktype == ktypes[i]) + return i; + return -1; +} + +/* + * Effects: + * Searches the credentials cache for a credential matching mcreds, + * with the fields specified by whichfields. If one if found, it is + * returned in creds, which should be freed by the caller with + * krb5_free_credentials(). + * + * The fields are interpreted in the following way (all constants are + * preceded by KRB5_TC_). MATCH_IS_SKEY requires the is_skey field to + * match exactly. MATCH_TIMES requires the requested lifetime to be + * at least as great as that specified; MATCH_TIMES_EXACT requires the + * requested lifetime to be exactly that specified. MATCH_FLAGS + * requires only the set bits in mcreds be set in creds; + * MATCH_FLAGS_EXACT requires all bits to match. + * + * Flag SUPPORTED_KTYPES means check all matching entries that have + * any supported enctype (according to tgs_enctypes) and return the one + * with the enctype listed earliest. Return CC_NOT_KTYPE if a match + * is found *except* for having a supported enctype. + * + * Errors: + * system errors + * permission errors + * KRB5_CC_NOMEM + * KRB5_CC_NOT_KTYPE + */ + +krb5_boolean +krb5int_cc_creds_match_request(krb5_context context, krb5_flags whichfields, + krb5_creds *mcreds, krb5_creds *creds) +{ + krb5_boolean is_skey; + + if (!princs_match(context, whichfields, mcreds, creds)) + return FALSE; + + /* Only match a user-to-user credential if explicitly asked for, since the + * ticket won't work as a regular service ticket. */ + is_skey = (whichfields & KRB5_TC_MATCH_IS_SKEY) ? mcreds->is_skey : FALSE; + if (creds->is_skey != is_skey) + return FALSE; + + if ((whichfields & KRB5_TC_MATCH_FLAGS_EXACT) && + mcreds->ticket_flags != creds->ticket_flags) + return FALSE; + if ((whichfields & KRB5_TC_MATCH_FLAGS) && + (creds->ticket_flags & mcreds->ticket_flags) != mcreds->ticket_flags) + return FALSE; + + if ((whichfields & KRB5_TC_MATCH_TIMES_EXACT) && + !times_match_exact(&mcreds->times, &creds->times)) + return FALSE; + if ((whichfields & KRB5_TC_MATCH_TIMES) && + !times_match(&mcreds->times, &creds->times)) + return FALSE; + + if ((whichfields & KRB5_TC_MATCH_AUTHDATA) && + !authdata_match(mcreds->authdata, creds->authdata)) + return FALSE; + + if ((whichfields & KRB5_TC_MATCH_2ND_TKT) && + !data_match(&mcreds->second_ticket, &creds->second_ticket)) + return FALSE; + + if ((whichfields & KRB5_TC_MATCH_KTYPE) && + mcreds->keyblock.enctype != creds->keyblock.enctype) + return FALSE; + + return TRUE; +} + +static krb5_error_code +krb5_cc_retrieve_cred_seq (krb5_context context, krb5_ccache id, + krb5_flags whichfields, krb5_creds *mcreds, + krb5_creds *creds, int nktypes, krb5_enctype *ktypes) +{ + /* This function could be considerably faster if it kept indexing */ + /* information.. sounds like a "next version" idea to me. :-) */ + + krb5_cc_cursor cursor; + krb5_error_code kret; + krb5_error_code nomatch_err = KRB5_CC_NOTFOUND; + struct { + krb5_creds creds; + int pref; + } fetched, best; + int have_creds = 0; +#define fetchcreds (fetched.creds) + + kret = krb5_cc_start_seq_get(context, id, &cursor); + if (kret != KRB5_OK) + return kret; + + while (krb5_cc_next_cred(context, id, &cursor, &fetchcreds) == KRB5_OK) { + if (krb5int_cc_creds_match_request(context, whichfields, mcreds, &fetchcreds)) + { + if (ktypes) { + fetched.pref = pref (fetchcreds.keyblock.enctype, + nktypes, ktypes); + if (fetched.pref < 0) + nomatch_err = KRB5_CC_NOT_KTYPE; + else if (!have_creds || fetched.pref < best.pref) { + if (have_creds) + krb5_free_cred_contents (context, &best.creds); + else + have_creds = 1; + best = fetched; + continue; + } + } else { + krb5_cc_end_seq_get(context, id, &cursor); + *creds = fetchcreds; + return KRB5_OK; + } + } + + /* This one doesn't match */ + krb5_free_cred_contents(context, &fetchcreds); + } + + /* If we get here, a match wasn't found */ + krb5_cc_end_seq_get(context, id, &cursor); + if (have_creds) { + *creds = best.creds; + return KRB5_OK; + } else + return nomatch_err; +} + +krb5_error_code +k5_cc_retrieve_cred_default(krb5_context context, krb5_ccache id, + krb5_flags flags, krb5_creds *mcreds, + krb5_creds *creds) +{ + krb5_enctype *ktypes; + int nktypes; + krb5_error_code ret; + + if (flags & KRB5_TC_SUPPORTED_KTYPES) { + ret = krb5_get_tgs_ktypes (context, mcreds->server, &ktypes); + if (ret) + return ret; + nktypes = k5_count_etypes (ktypes); + + ret = krb5_cc_retrieve_cred_seq (context, id, flags, mcreds, creds, + nktypes, ktypes); + free (ktypes); + return ret; + } else { + return krb5_cc_retrieve_cred_seq (context, id, flags, mcreds, creds, + 0, 0); + } +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccapi/Makefile.in b/krb5-1.21.3/src/lib/krb5/ccache/ccapi/Makefile.in new file mode 100644 index 00000000..2e379e46 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccapi/Makefile.in @@ -0,0 +1,25 @@ +mydir=lib$(S)krb5$(S)ccache$(S)ccapi +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +LOCALINCLUDES = $(WIN_INCLUDES) +DEFINES= -DUSE_CCAPI + +##DOS##WIN_INCLUDES = -I$(top_srcdir)\windows\lib + +##DOS##BUILDTOP = ..\..\..\.. +##DOS##PREFIXDIR = ccache\file +##DOS##OBJFILE = $(OUTPRE)file.lst + +STLIBOBJS = \ + stdcc.o \ + winccld.o + +OBJS = $(OUTPRE)stdcc.$(OBJEXT) $(OUTPRE)winccld.$(OBJEXT) + +SRCS = $(srcdir)/stdcc.c $(srcdir)/winccld.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs +clean-unix:: clean-libobjs + +@libobj_frag@ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccapi/deps b/krb5-1.21.3/src/lib/krb5/ccache/ccapi/deps new file mode 100644 index 00000000..c3ef7d0d --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccapi/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +stdcc.so stdcc.po $(OUTPRE)stdcc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/locate_plugin.h \ + $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h stdcc.c stdcc.h +winccld.so winccld.po $(OUTPRE)winccld.$(OBJEXT): winccld.c diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccapi/stdcc.c b/krb5-1.21.3/src/lib/krb5/ccache/ccapi/stdcc.c new file mode 100644 index 00000000..427b3296 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccapi/stdcc.c @@ -0,0 +1,1020 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/ccapi/stdcc.c - ccache API support functions */ +/* + * Copyright 1998, 1999, 2006, 2008 by the Massachusetts Institute of + * Technology. All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Written by Frank Dabek July 1998 + * Updated by Jeffrey Altman June 2006 + */ + +#if defined(_WIN32) || defined(USE_CCAPI) + +#include "k5-int.h" +#include "../cc-int.h" +#include "../ccapi_util.h" +#include "stdcc.h" +#include "string.h" +#include + +#if defined(_WIN32) +#include "winccld.h" +#endif + +#ifndef CC_API_VER2 +#define CC_API_VER2 +#endif + +#ifdef DEBUG +#if defined(_WIN32) +#include +#define SHOW_DEBUG(buf) MessageBox((HWND)NULL, (buf), "ccapi debug", MB_OK) +#endif +/* XXX need macintosh debugging statement if we want to debug */ +/* on the mac */ +#else +#define SHOW_DEBUG(buf) +#endif + +cc_context_t gCntrlBlock = NULL; +cc_int32 gCCVersion = 0; + +/* + * declare our global object wanna-be + * must be installed in ccdefops.c + */ + +krb5_cc_ops krb5_cc_stdcc_ops = { + 0, + "API", + krb5_stdccv3_get_name, + krb5_stdccv3_resolve, + krb5_stdccv3_generate_new, + krb5_stdccv3_initialize, + krb5_stdccv3_destroy, + krb5_stdccv3_close, + krb5_stdccv3_store, + krb5_stdccv3_retrieve, + krb5_stdccv3_get_principal, + krb5_stdccv3_start_seq_get, + krb5_stdccv3_next_cred, + krb5_stdccv3_end_seq_get, + krb5_stdccv3_remove, + krb5_stdccv3_set_flags, + krb5_stdccv3_get_flags, + krb5_stdccv3_ptcursor_new, + krb5_stdccv3_ptcursor_next, + krb5_stdccv3_ptcursor_free, + NULL, /* move */ + NULL, /* wasdefault */ + krb5_stdccv3_lock, + krb5_stdccv3_unlock, + krb5_stdccv3_switch_to, +}; + +#if defined(_WIN32) +/* + * cache_changed be called after the cache changes. + * A notification message is is posted out to all top level + * windows so that they may recheck the cache based on the + * changes made. We register a unique message type with which + * we'll communicate to all other processes. + */ +static void cache_changed() +{ + static unsigned int message = 0; + + if (message == 0) + message = RegisterWindowMessage(WM_KERBEROS5_CHANGED); + + PostMessage(HWND_BROADCAST, message, 0, 0); +} +#else /* _WIN32 */ + +static void cache_changed() +{ + return; +} +#endif /* _WIN32 */ + +struct err_xlate +{ + int cc_err; + krb5_error_code krb5_err; +}; + +static const struct err_xlate err_xlate_table[] = +{ + { ccIteratorEnd, KRB5_CC_END }, + { ccErrBadParam, KRB5_FCC_INTERNAL }, + { ccErrNoMem, KRB5_CC_NOMEM }, + { ccErrInvalidContext, KRB5_FCC_NOFILE }, + { ccErrInvalidCCache, KRB5_FCC_NOFILE }, + { ccErrInvalidString, KRB5_FCC_INTERNAL }, + { ccErrInvalidCredentials, KRB5_FCC_INTERNAL }, + { ccErrInvalidCCacheIterator, KRB5_FCC_INTERNAL }, + { ccErrInvalidCredentialsIterator, KRB5_FCC_INTERNAL }, + { ccErrInvalidLock, KRB5_FCC_INTERNAL }, + { ccErrBadName, KRB5_CC_BADNAME }, + { ccErrBadCredentialsVersion, KRB5_FCC_INTERNAL }, + { ccErrBadAPIVersion, KRB5_FCC_INTERNAL }, + { ccErrContextLocked, KRB5_FCC_INTERNAL }, + { ccErrContextUnlocked, KRB5_FCC_INTERNAL }, + { ccErrCCacheLocked, KRB5_FCC_INTERNAL }, + { ccErrCCacheUnlocked, KRB5_FCC_INTERNAL }, + { ccErrBadLockType, KRB5_FCC_INTERNAL }, + { ccErrNeverDefault, KRB5_FCC_INTERNAL }, + { ccErrCredentialsNotFound, KRB5_CC_NOTFOUND }, + { ccErrCCacheNotFound, KRB5_FCC_NOFILE }, + { ccErrContextNotFound, KRB5_FCC_NOFILE }, + { ccErrServerUnavailable, KRB5_CC_IO }, + { ccErrServerInsecure, KRB5_CC_IO }, + { ccErrServerCantBecomeUID, KRB5_CC_IO }, + { ccErrTimeOffsetNotSet, KRB5_FCC_INTERNAL }, + { ccErrBadInternalMessage, KRB5_FCC_INTERNAL }, + { ccErrNotImplemented, KRB5_FCC_INTERNAL }, + { 0, 0 } +}; + +/* Note: cc_err_xlate is NOT idempotent. Don't call it multiple times. */ +static krb5_error_code cc_err_xlate(int err) +{ + const struct err_xlate *p; + + if (err == ccNoError) + return 0; + + for (p = err_xlate_table; p->cc_err; p++) { + if (err == p->cc_err) + return p->krb5_err; + } + + return KRB5_FCC_INTERNAL; +} + + +static krb5_error_code stdccv3_get_timeoffset (krb5_context in_context, + cc_ccache_t in_ccache) +{ + krb5_error_code err = 0; + + if (gCCVersion >= ccapi_version_5) { + krb5_os_context os_ctx = (krb5_os_context) &in_context->os_context; + cc_time_t time_offset = 0; + + err = cc_ccache_get_kdc_time_offset (in_ccache, cc_credentials_v5, + &time_offset); + + if (!err) { + os_ctx->time_offset = time_offset; + os_ctx->usec_offset = 0; + os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) | + KRB5_OS_TOFFSET_VALID); + } + + if (err == ccErrTimeOffsetNotSet) { + err = 0; /* okay if there is no time offset */ + } + } + + return err; /* Don't translate. Callers will translate for us */ +} + +static krb5_error_code stdccv3_set_timeoffset (krb5_context in_context, + cc_ccache_t in_ccache) +{ + krb5_error_code err = 0; + + if (gCCVersion >= ccapi_version_5) { + krb5_os_context os_ctx = (krb5_os_context) &in_context->os_context; + + if (!err && os_ctx->os_flags & KRB5_OS_TOFFSET_VALID) { + err = cc_ccache_set_kdc_time_offset (in_ccache, + cc_credentials_v5, + os_ctx->time_offset); + } + } + + return err; /* Don't translate. Callers will translate for us */ +} + +static krb5_error_code stdccv3_setup (krb5_context context, + stdccCacheDataPtr ccapi_data) +{ + krb5_error_code err = 0; + + if (!err && !gCntrlBlock) { + err = cc_initialize (&gCntrlBlock, ccapi_version_max, &gCCVersion, NULL); + } + + if (!err && ccapi_data && !ccapi_data->NamedCache) { + /* ccache has not been opened yet. open it. */ + err = cc_context_open_ccache (gCntrlBlock, ccapi_data->cache_name, + &ccapi_data->NamedCache); + } + + if (!err && ccapi_data && ccapi_data->NamedCache) { + err = stdccv3_get_timeoffset (context, ccapi_data->NamedCache); + } + + return err; /* Don't translate. Callers will translate for us */ +} + +/* krb5_stdcc_shutdown is exported; use the old name */ +void krb5_stdcc_shutdown() +{ + if (gCntrlBlock) { cc_context_release(gCntrlBlock); } + gCntrlBlock = NULL; + gCCVersion = 0; +} + +/* + * -- generate_new -------------------------------- + * + * create a new cache with a unique name, corresponds to creating a + * named cache initialize the API here if we have to. + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_generate_new (krb5_context context, krb5_ccache *id ) +{ + krb5_error_code err = 0; + krb5_ccache newCache = NULL; + stdccCacheDataPtr ccapi_data = NULL; + cc_ccache_t ccache = NULL; + cc_string_t ccstring = NULL; + char *name = NULL; + + if (!err) { + err = stdccv3_setup(context, NULL); + } + + if (!err) { + newCache = (krb5_ccache) malloc (sizeof (*newCache)); + if (!newCache) { err = KRB5_CC_NOMEM; } + } + + if (!err) { + ccapi_data = (stdccCacheDataPtr) malloc (sizeof (*ccapi_data)); + if (!ccapi_data) { err = KRB5_CC_NOMEM; } + } + + if (!err) { + err = cc_context_create_new_ccache (gCntrlBlock, cc_credentials_v5, "", + &ccache); + } + + if (!err) { + err = stdccv3_set_timeoffset (context, ccache); + } + + if (!err) { + err = cc_ccache_get_name (ccache, &ccstring); + } + + if (!err) { + name = strdup (ccstring->data); + if (!name) { err = KRB5_CC_NOMEM; } + } + + if (!err) { + ccapi_data->cache_name = name; + name = NULL; /* take ownership */ + + ccapi_data->NamedCache = ccache; + ccache = NULL; /* take ownership */ + + newCache->ops = &krb5_cc_stdcc_ops; + newCache->data = ccapi_data; + ccapi_data = NULL; /* take ownership */ + + /* return a pointer to the new cache */ + *id = newCache; + newCache = NULL; + } + + if (ccstring) { cc_string_release (ccstring); } + if (name) { free (name); } + if (ccache) { cc_ccache_release (ccache); } + if (ccapi_data) { free (ccapi_data); } + if (newCache) { free (newCache); } + + return cc_err_xlate (err); +} + +/* + * resolve + * + * create a new cache with the name stored in residual + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_resolve (krb5_context context, krb5_ccache *id , const char *residual ) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = NULL; + krb5_ccache ccache = NULL; + char *name = NULL; + cc_string_t defname = NULL; + + if (id == NULL) { err = KRB5_CC_NOMEM; } + + if (!err) { + err = stdccv3_setup (context, NULL); + } + + if (!err) { + ccapi_data = (stdccCacheDataPtr) malloc (sizeof (*ccapi_data)); + if (!ccapi_data) { err = KRB5_CC_NOMEM; } + } + + if (!err) { + ccache = (krb5_ccache ) malloc (sizeof (*ccache)); + if (!ccache) { err = KRB5_CC_NOMEM; } + } + + if (!err) { + if ((residual == NULL) || (strlen(residual) == 0)) { + err = cc_context_get_default_ccache_name(gCntrlBlock, &defname); + if (defname) + residual = defname->data; + } + } + + if (!err) { + name = strdup (residual); + if (!name) { err = KRB5_CC_NOMEM; } + } + + if (!err) { + err = cc_context_open_ccache (gCntrlBlock, residual, + &ccapi_data->NamedCache); + if (err == ccErrCCacheNotFound) { + ccapi_data->NamedCache = NULL; + err = 0; /* ccache just doesn't exist yet */ + } + } + + if (!err) { + ccapi_data->cache_name = name; + name = NULL; /* take ownership */ + + ccache->ops = &krb5_cc_stdcc_ops; + ccache->data = ccapi_data; + ccapi_data = NULL; /* take ownership */ + + *id = ccache; + ccache = NULL; /* take ownership */ + } + + if (ccache) { free (ccache); } + if (ccapi_data) { free (ccapi_data); } + if (name) { free (name); } + if (defname) { cc_string_release(defname); } + + return cc_err_xlate (err); +} + +/* + * initialize + * + * initialize the cache, check to see if one already exists for this + * principal if not set our principal to this principal. This + * searching enables ticket sharing + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_initialize (krb5_context context, + krb5_ccache id, + krb5_principal princ) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + char *name = NULL; + cc_ccache_t ccache = NULL; + + if (id == NULL) { err = KRB5_CC_NOMEM; } + + if (!err) { + err = stdccv3_setup (context, NULL); + } + + if (!err) { + err = krb5_unparse_name(context, princ, &name); + } + + if (!err) { + err = cc_context_create_ccache (gCntrlBlock, ccapi_data->cache_name, + cc_credentials_v5, name, + &ccache); + } + + if (!err) { + err = stdccv3_set_timeoffset (context, ccache); + } + + if (!err) { + if (ccapi_data->NamedCache) { + err = cc_ccache_release (ccapi_data->NamedCache); + } + ccapi_data->NamedCache = ccache; + ccache = NULL; /* take ownership */ + cache_changed (); + } + + if (ccache) { cc_ccache_release (ccache); } + if (name ) { krb5_free_unparsed_name(context, name); } + + return cc_err_xlate(err); +} + +/* + * store + * + * store some credentials in our cache + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_store (krb5_context context, krb5_ccache id, krb5_creds *creds ) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + cc_credentials_union *cred_union = NULL; + + if (!err) { + err = stdccv3_setup (context, ccapi_data); + } + + if (!err) { + /* copy the fields from the almost identical structures */ + err = k5_krb5_to_ccapi_creds (context, creds, &cred_union); + } + + if (!err) { + err = cc_ccache_store_credentials (ccapi_data->NamedCache, cred_union); + } + + if (!err) { + cache_changed(); + } + + if (cred_union) { k5_release_ccapi_cred (cred_union); } + + return cc_err_xlate (err); +} + +/* + * start_seq_get + * + * begin an iterator call to get all of the credentials in the cache + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_start_seq_get (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor ) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + cc_credentials_iterator_t iterator = NULL; + + if (!err) { + err = stdccv3_setup (context, ccapi_data); + } + + if (!err) { + err = cc_ccache_new_credentials_iterator(ccapi_data->NamedCache, + &iterator); + } + + if (!err) { + *cursor = iterator; + } + + return cc_err_xlate (err); +} + +/* + * next cred + * + * - get the next credential in the cache as part of an iterator call + * - this maps to call to cc_seq_fetch_creds + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_next_cred (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + cc_credentials_t credentials = NULL; + cc_credentials_iterator_t iterator = *cursor; + + if (!iterator) { err = KRB5_CC_END; } + + if (!err) { + err = stdccv3_setup (context, ccapi_data); + } + + while (!err) { + err = cc_credentials_iterator_next (iterator, &credentials); + + if (!err && (credentials->data->version == cc_credentials_v5)) { + err = k5_ccapi_to_krb5_creds (context, credentials->data, creds); + break; + } + } + + if (credentials) { cc_credentials_release (credentials); } + if (err == ccIteratorEnd) { + cc_credentials_iterator_release (iterator); + *cursor = 0; + } + + return cc_err_xlate (err); +} + + +/* + * retrieve + * + * - try to find a matching credential in the cache + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_retrieve (krb5_context context, + krb5_ccache id, + krb5_flags whichfields, + krb5_creds *mcreds, + krb5_creds *creds) +{ + return k5_cc_retrieve_cred_default(context, id, whichfields, mcreds, + creds); +} + +/* + * end seq + * + * just free up the storage associated with the cursor (if we can) + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_end_seq_get (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + cc_credentials_iterator_t iterator = *cursor; + + if (!iterator) { return 0; } + + if (!err) { + err = stdccv3_setup (context, ccapi_data); + } + + if (!err) { + err = cc_credentials_iterator_release(iterator); + } + + return cc_err_xlate(err); +} + +/* + * close + * + * - free our pointers to the NC + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_close(krb5_context context, + krb5_ccache id) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + + if (!err) { + err = stdccv3_setup (context, NULL); + } + + if (!err) { + if (ccapi_data) { + if (ccapi_data->cache_name) { + free (ccapi_data->cache_name); + } + if (ccapi_data->NamedCache) { + err = cc_ccache_release (ccapi_data->NamedCache); + } + free (ccapi_data); + id->data = NULL; + } + free (id); + } + + return cc_err_xlate(err); +} + +/* + * destroy + * + * - free our storage and the cache + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_destroy (krb5_context context, + krb5_ccache id) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + + if (!err) { + err = stdccv3_setup(context, ccapi_data); + } + + if (!err) { + if (ccapi_data) { + if (ccapi_data->cache_name) { + free(ccapi_data->cache_name); + } + if (ccapi_data->NamedCache) { + /* destroy the named cache */ + err = cc_ccache_destroy(ccapi_data->NamedCache); + if (err == ccErrCCacheNotFound) { + err = 0; /* ccache maybe already destroyed */ + } + cache_changed(); + } + free(ccapi_data); + id->data = NULL; + } + free(id); + } + + return cc_err_xlate(err); +} + +/* + * getname + * + * - return the name of the named cache + */ +const char * KRB5_CALLCONV +krb5_stdccv3_get_name (krb5_context context, + krb5_ccache id ) +{ + stdccCacheDataPtr ccapi_data = id->data; + + if (!ccapi_data) { + return NULL; + } else { + return (ccapi_data->cache_name); + } +} + + +/* get_principal + * + * - return the principal associated with the named cache + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_get_principal (krb5_context context, + krb5_ccache id , + krb5_principal *princ) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + cc_string_t name = NULL; + + if (!err) { + err = stdccv3_setup(context, ccapi_data); + } + + if (!err) { + err = cc_ccache_get_principal (ccapi_data->NamedCache, cc_credentials_v5, &name); + } + + if (!err) { + err = krb5_parse_name (context, name->data, princ); + } else { + err = cc_err_xlate (err); + } + + if (name) { cc_string_release (name); } + + return err; +} + +/* + * set_flags + * + * - currently a NOP since we don't store any flags in the NC + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_set_flags (krb5_context context, + krb5_ccache id, + krb5_flags flags) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + + err = stdccv3_setup (context, ccapi_data); + + return cc_err_xlate (err); +} + +/* + * get_flags + * + * - currently a NOP since we don't store any flags in the NC + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_get_flags (krb5_context context, + krb5_ccache id, + krb5_flags *flags) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + + err = stdccv3_setup (context, ccapi_data); + + return cc_err_xlate (err); +} + +/* + * remove + * + * - remove the specified credentials from the NC + */ +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_remove (krb5_context context, + krb5_ccache id, + krb5_flags whichfields, + krb5_creds *in_creds) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + cc_credentials_iterator_t iterator = NULL; + int found = 0; + + if (!err) { + err = stdccv3_setup(context, ccapi_data); + } + + + if (!err) { + err = cc_ccache_new_credentials_iterator(ccapi_data->NamedCache, + &iterator); + } + + while (!err && !found) { + cc_credentials_t credentials = NULL; + + err = cc_credentials_iterator_next (iterator, &credentials); + + if (!err && (credentials->data->version == cc_credentials_v5)) { + krb5_creds creds; + + err = k5_ccapi_to_krb5_creds (context, credentials->data, &creds); + + if (!err) { + found = krb5int_cc_creds_match_request(context, + whichfields, + in_creds, + &creds); + krb5_free_cred_contents (context, &creds); + } + + if (!err && found) { + err = cc_ccache_remove_credentials (ccapi_data->NamedCache, credentials); + } + } + + if (credentials) { cc_credentials_release (credentials); } + } + if (err == ccIteratorEnd) { err = ccErrCredentialsNotFound; } + + if (iterator) { + err = cc_credentials_iterator_release(iterator); + } + + if (!err) { + cache_changed (); + } + + return cc_err_xlate (err); +} + +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_ptcursor_new(krb5_context context, + krb5_cc_ptcursor *cursor) +{ + krb5_error_code err = 0; + krb5_cc_ptcursor ptcursor = NULL; + cc_ccache_iterator_t iterator = NULL; + + ptcursor = malloc(sizeof(*ptcursor)); + if (ptcursor == NULL) { + err = ccErrNoMem; + } + else { + memset(ptcursor, 0, sizeof(*ptcursor)); + } + + if (!err) { + err = stdccv3_setup(context, NULL); + } + if (!err) { + ptcursor->ops = &krb5_cc_stdcc_ops; + err = cc_context_new_ccache_iterator(gCntrlBlock, &iterator); + } + + if (!err) { + ptcursor->data = iterator; + } + + if (err) { + if (ptcursor) { krb5_stdccv3_ptcursor_free(context, &ptcursor); } + // krb5_stdccv3_ptcursor_free sets ptcursor to NULL for us + } + + *cursor = ptcursor; + + return cc_err_xlate(err); +} + +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_ptcursor_next( + krb5_context context, + krb5_cc_ptcursor cursor, + krb5_ccache *ccache) +{ + krb5_error_code err = 0; + cc_ccache_iterator_t iterator = NULL; + + krb5_ccache newCache = NULL; + stdccCacheDataPtr ccapi_data = NULL; + cc_ccache_t ccCache = NULL; + cc_string_t ccstring = NULL; + char *name = NULL; + + if (!cursor || !cursor->data) { + err = ccErrInvalidContext; + } + + *ccache = NULL; + + if (!err) { + newCache = (krb5_ccache) malloc (sizeof (*newCache)); + if (!newCache) { err = ccErrNoMem; } + } + + if (!err) { + ccapi_data = (stdccCacheDataPtr) malloc (sizeof (*ccapi_data)); + if (!ccapi_data) { err = ccErrNoMem; } + } + + if (!err) { + iterator = cursor->data; + err = cc_ccache_iterator_next(iterator, &ccCache); + } + + if (!err) { + err = cc_ccache_get_name (ccCache, &ccstring); + } + + if (!err) { + name = strdup (ccstring->data); + if (!name) { err = ccErrNoMem; } + } + + if (!err) { + ccapi_data->cache_name = name; + name = NULL; /* take ownership */ + + ccapi_data->NamedCache = ccCache; + ccCache = NULL; /* take ownership */ + + newCache->ops = &krb5_cc_stdcc_ops; + newCache->data = ccapi_data; + ccapi_data = NULL; /* take ownership */ + + /* return a pointer to the new cache */ + *ccache = newCache; + newCache = NULL; + } + + if (name) { free (name); } + if (ccstring) { cc_string_release (ccstring); } + if (ccCache) { cc_ccache_release (ccCache); } + if (ccapi_data) { free (ccapi_data); } + if (newCache) { free (newCache); } + + if (err == ccIteratorEnd) { + err = ccNoError; + } + + return cc_err_xlate(err); +} + +krb5_error_code KRB5_CALLCONV +krb5_stdccv3_ptcursor_free( + krb5_context context, + krb5_cc_ptcursor *cursor) +{ + if (*cursor != NULL) { + if ((*cursor)->data != NULL) { + cc_ccache_iterator_release((cc_ccache_iterator_t)((*cursor)->data)); + } + free(*cursor); + *cursor = NULL; + } + return 0; +} + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_lock +(krb5_context context, krb5_ccache id) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + + if (!err) { + err = stdccv3_setup(context, ccapi_data); + } + if (!err) { + err = cc_ccache_lock(ccapi_data->NamedCache, cc_lock_write, cc_lock_block); + } + return cc_err_xlate(err); +} + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_unlock +(krb5_context context, krb5_ccache id) +{ + krb5_error_code err = 0; + stdccCacheDataPtr ccapi_data = id->data; + + if (!err) { + err = stdccv3_setup(context, ccapi_data); + } + if (!err) { + err = cc_ccache_unlock(ccapi_data->NamedCache); + } + return cc_err_xlate(err); +} + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_lock +(krb5_context context) +{ + krb5_error_code err = 0; + + if (!err && !gCntrlBlock) { + err = cc_initialize (&gCntrlBlock, ccapi_version_max, &gCCVersion, NULL); + } + if (!err) { + err = cc_context_lock(gCntrlBlock, cc_lock_write, cc_lock_block); + } + return cc_err_xlate(err); +} + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_unlock +(krb5_context context) +{ + krb5_error_code err = 0; + + if (!err && !gCntrlBlock) { + err = cc_initialize (&gCntrlBlock, ccapi_version_max, &gCCVersion, NULL); + } + if (!err) { + err = cc_context_unlock(gCntrlBlock); + } + return cc_err_xlate(err); +} + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_switch_to +(krb5_context context, krb5_ccache id) +{ + krb5_error_code retval; + stdccCacheDataPtr ccapi_data = id->data; + int err; + + retval = stdccv3_setup(context, ccapi_data); + if (retval) + return cc_err_xlate(retval); + + err = cc_ccache_set_default(ccapi_data->NamedCache); + return cc_err_xlate(err); +} + +#endif /* defined(_WIN32) || defined(USE_CCAPI) */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccapi/stdcc.h b/krb5-1.21.3/src/lib/krb5/ccache/ccapi/stdcc.h new file mode 100644 index 00000000..ef50445b --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccapi/stdcc.h @@ -0,0 +1,108 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#ifndef __KRB5_STDCC_H__ +#define __KRB5_STDCC_H__ + +#if defined(_WIN32) || defined(USE_CCAPI) + +#include "k5-int.h" /* loads krb5.h */ +#include "../cc-int.h" + +#include + +#define kStringLiteralLen 255 + +/* globals to be exported */ +extern krb5_cc_ops krb5_cc_stdcc_ops; + +/* + * structure to stash in the cache's data field + */ +typedef struct _stdccCacheData { + char *cache_name; + cc_ccache_t NamedCache; +} stdccCacheData, *stdccCacheDataPtr; + + +/* function prototypes */ + +void krb5_stdcc_shutdown(void); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_close +(krb5_context, krb5_ccache id ); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_destroy +(krb5_context, krb5_ccache id ); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_end_seq_get +(krb5_context, krb5_ccache id , krb5_cc_cursor *cursor ); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_generate_new +(krb5_context, krb5_ccache *id ); + +const char * KRB5_CALLCONV krb5_stdccv3_get_name +(krb5_context, krb5_ccache id ); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_get_principal +(krb5_context, krb5_ccache id , krb5_principal *princ ); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_initialize +(krb5_context, krb5_ccache id , krb5_principal princ ); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_next_cred +(krb5_context, + krb5_ccache id , + krb5_cc_cursor *cursor , + krb5_creds *creds ); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_resolve +(krb5_context, krb5_ccache *id , const char *residual ); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_retrieve +(krb5_context, + krb5_ccache id , + krb5_flags whichfields , + krb5_creds *mcreds , + krb5_creds *creds ); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_start_seq_get +(krb5_context, krb5_ccache id , krb5_cc_cursor *cursor ); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_store +(krb5_context, krb5_ccache id , krb5_creds *creds ); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_set_flags +(krb5_context, krb5_ccache id , krb5_flags flags ); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_get_flags +(krb5_context, krb5_ccache id , krb5_flags *flags ); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_remove +(krb5_context, krb5_ccache id , krb5_flags flags, krb5_creds *creds); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_new +(krb5_context context, krb5_cc_ptcursor *cursor); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_next +(krb5_context context, krb5_cc_ptcursor cursor, krb5_ccache *ccache); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_ptcursor_free +(krb5_context context, krb5_cc_ptcursor *cursor); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_lock +(krb5_context, krb5_ccache id); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_unlock +(krb5_context, krb5_ccache id); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_lock +(krb5_context context); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_context_unlock +(krb5_context context); + +krb5_error_code KRB5_CALLCONV krb5_stdccv3_switch_to +(krb5_context context, krb5_ccache id); + +#endif /* defined(_WIN32) || defined(USE_CCAPI) */ + +#endif diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccapi/winccld.c b/krb5-1.21.3/src/lib/krb5/ccache/ccapi/winccld.c new file mode 100644 index 00000000..8b2e90c4 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccapi/winccld.c @@ -0,0 +1,101 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#if defined(_WIN32) +/* + * winccld.c --- routine for dynamically loading the ccache DLL if + * it's present. + */ + +#include +#include +#include "k5-int.h" +#include "stdcc.h" + +/* from fcc-proto.h */ +extern const krb5_cc_ops krb5_fcc_ops; + +#define KRB5_WINCCLD_C_ +#include "winccld.h" + +static int krb5_win_ccdll_loaded = 0; + +extern void krb5_win_ccdll_load(); +extern int krb5_is_ccdll_loaded(); + +/* + * return codes + */ +#define LF_OK 0 +#define LF_NODLL 1 +#define LF_NOFUNC 2 + +#ifdef _WIN64 +#define KRBCC_DLL "krbcc64.dll" +#else +#define KRBCC_DLL "krbcc32.dll" +#endif + +static int LoadFuncs(const char* dll_name, FUNC_INFO fi[], + HINSTANCE* ph, int debug); + +static int LoadFuncs(const char* dll_name, FUNC_INFO fi[], + HINSTANCE* ph, int debug) +{ + HINSTANCE h; + int i, n; + int error = 0; + + if (ph) *ph = 0; + + for (n = 0; fi[n].func_ptr_var; n++) { + *(fi[n].func_ptr_var) = 0; + } + + if (!(h = LoadLibrary(dll_name))) { + /* Get error for source debugging purposes. */ + error = (int)GetLastError(); + return LF_NODLL; + } + + if (debug) + printf("Loaded %s\n", dll_name); + for (i = 0; !error && (i < n); i++) { + void* p = (void*)GetProcAddress(h, fi[i].func_name); + if (!p) { + if (debug) + printf("Could not get function: %s\n", fi[i].func_name); + error = 1; + } else { + *(fi[i].func_ptr_var) = p; + if (debug) + printf("Loaded function %s at 0x%08X\n", fi[i].func_name, p); + } + } + if (error) { + for (i = 0; i < n; i++) { + *(fi[i].func_ptr_var) = 0; + } + FreeLibrary(h); + return LF_NOFUNC; + } + if (ph) *ph = h; + return LF_OK; +} + +void krb5_win_ccdll_load(context) + krb5_context context; +{ + krb5_cc_register(context, &krb5_fcc_ops, 0); + if (krb5_win_ccdll_loaded) + return; + if (LoadFuncs(KRBCC_DLL, krbcc_fi, 0, 0)) + return; /* Error, give up */ + krb5_win_ccdll_loaded = 1; + krb5_cc_dfl_ops = &krb5_cc_stdcc_ops; /* Use stdcc! */ +} + +int krb5_is_ccdll_loaded() +{ + return krb5_win_ccdll_loaded; +} + +#endif /* Windows */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccapi/winccld.h b/krb5-1.21.3/src/lib/krb5/ccache/ccapi/winccld.h new file mode 100644 index 00000000..d617d4d2 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccapi/winccld.h @@ -0,0 +1,47 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * winccld.h -- the dynamic loaded version of the ccache DLL + */ + + +#ifndef KRB5_WINCCLD_H_ +#define KRB5_WINCCLD_H_ + +#include + +typedef CCACHE_API cc_int32 (*FP_cc_initialize) ( + cc_context_t* outContext, + cc_int32 inVersion, + cc_int32* outSupportedVersion, + char const** outVendor); + +#ifdef KRB5_WINCCLD_C_ +typedef struct _FUNC_INFO { + void** func_ptr_var; + char* func_name; +} FUNC_INFO; + +#define DECL_FUNC_PTR(x) FP_##x p##x +#define MAKE_FUNC_INFO(x) { (void**) &p##x, #x } +#define END_FUNC_INFO { 0, 0 } +#else +#define DECL_FUNC_PTR(x) extern FP_##x p##x +#endif + +DECL_FUNC_PTR(cc_initialize); + +#ifdef KRB5_WINCCLD_C_ +FUNC_INFO krbcc_fi[] = { + MAKE_FUNC_INFO(cc_initialize), + END_FUNC_INFO +}; +#undef MAKE_FUNC_INFO +#undef END_FUNC_INFO +#else + +#define cc_initialize pcc_initialize +#endif + +#undef DECL_FUNC_PTR + +#endif /* KRB5_WINCCLD_H_ */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccapi_util.c b/krb5-1.21.3/src/lib/krb5/ccache/ccapi_util.c new file mode 100644 index 00000000..b035c7ee --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccapi_util.c @@ -0,0 +1,425 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/ccapi_util.c - conversion functions for CCAPI creds */ +/* + * Copyright (C) 2022 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. + */ + +#include "cc-int.h" +#include "ccapi_util.h" + +#if defined(USE_CCAPI) || defined(USE_CCAPI_MACOS) + +static void +free_cc_data_list(cc_data **list) +{ + size_t i; + + for (i = 0; list != NULL && list[i] != NULL; i++) { + free(list[i]->data); + free(list[i]); + } + free(list); +} + +static krb5_error_code +cc_data_list_to_addresses(krb5_context context, cc_data **list, + krb5_address ***addrs_out) +{ + krb5_error_code ret; + size_t count, i; + krb5_address **addrs = NULL; + + *addrs_out = NULL; + if (list == NULL) + return 0; + + for (count = 0; list[count]; count++); + addrs = k5calloc(count + 1, sizeof(*addrs), &ret); + if (addrs == NULL) + return ret; + + for (i = 0; i < count; i++) { + addrs[i] = k5alloc(sizeof(*addrs[i]), &ret); + if (addrs[i] == NULL) + goto cleanup; + + addrs[i]->contents = k5memdup(list[i]->data, list[i]->length, &ret); + if (addrs[i]->contents == NULL) + goto cleanup; + addrs[i]->length = list[i]->length; + addrs[i]->addrtype = list[i]->type; + addrs[i]->magic = KV5M_ADDRESS; + } + + *addrs_out = addrs; + addrs = NULL; + +cleanup: + krb5_free_addresses(context, addrs); + return ret; +} + +static krb5_error_code +cc_data_list_to_authdata(krb5_context context, cc_data **list, + krb5_authdata ***authdata_out) +{ + krb5_error_code ret; + size_t count, i; + krb5_authdata **authdata = NULL; + + *authdata_out = NULL; + if (list == NULL) + return 0; + + for (count = 0; list[count]; count++); + authdata = k5calloc(count + 1, sizeof(*authdata), &ret); + if (authdata == NULL) + return ret; + + for (i = 0; i < count; i++) { + authdata[i] = k5alloc(sizeof(*authdata[i]), &ret); + if (authdata[i] == NULL) + goto cleanup; + + authdata[i]->contents = k5memdup(list[i]->data, list[i]->length, &ret); + if (authdata[i]->contents == NULL) + goto cleanup; + authdata[i]->length = list[i]->length; + authdata[i]->ad_type = list[i]->type; + authdata[i]->magic = KV5M_AUTHDATA; + } + + *authdata_out = authdata; + authdata = NULL; + +cleanup: + krb5_free_authdata(context, authdata); + return ret; +} + +static krb5_error_code +addresses_to_cc_data_list(krb5_context context, krb5_address **addrs, + cc_data ***list_out) +{ + krb5_error_code ret; + size_t count, i; + cc_data **list = NULL; + + *list_out = NULL; + if (addrs == NULL) + return 0; + + for (count = 0; addrs[count]; count++); + list = k5calloc(count + 1, sizeof(*list), &ret); + if (list == NULL) + return ret; + + for (i = 0; i < count; i++) { + list[i] = k5alloc(sizeof(*list[i]), &ret); + if (list[i] == NULL) + goto cleanup; + + list[i]->data = k5memdup(addrs[i]->contents, addrs[i]->length, &ret); + if (list[i]->data == NULL) + goto cleanup; + list[i]->length = addrs[i]->length; + list[i]->type = addrs[i]->addrtype; + } + + *list_out = list; + list = NULL; + +cleanup: + free_cc_data_list(list); + return ret; +} + +static krb5_error_code +authdata_to_cc_data_list(krb5_context context, krb5_authdata **authdata, + cc_data ***list_out) +{ + krb5_error_code ret; + size_t count, i; + cc_data **list = NULL; + + *list_out = NULL; + if (authdata == NULL) + return 0; + + for (count = 0; authdata[count]; count++); + list = k5calloc(count + 1, sizeof(*list), &ret); + if (list == NULL) + return ret; + + for (i = 0; i < count; i++) { + list[i] = k5alloc(sizeof(*list[i]), &ret); + if (list[i] == NULL) + goto cleanup; + + list[i]->data = k5memdup(authdata[i]->contents, authdata[i]->length, + &ret); + if (list[i]->data == NULL) + goto cleanup; + list[i]->length = authdata[i]->length; + list[i]->type = authdata[i]->ad_type; + } + + *list_out = list; + list = NULL; + +cleanup: + free_cc_data_list(list); + return ret; +} + +krb5_error_code +k5_ccapi_to_krb5_creds(krb5_context context, + const cc_credentials_union *ccapi_cred, + krb5_creds *cred_out) +{ + krb5_error_code ret; + cc_credentials_v5_t *cv5 = NULL; + krb5_principal client = NULL; + krb5_principal server = NULL; + char *ticket_data = NULL; + char *second_ticket_data = NULL; + uint8_t *keyblock_contents = NULL; + krb5_address **addresses = NULL; + krb5_authdata **authdata = NULL; + + if (ccapi_cred->version != cc_credentials_v5) + return KRB5_CC_NOT_KTYPE; + + cv5 = ccapi_cred->credentials.credentials_v5; + + ret = krb5_parse_name(context, cv5->client, &client); + if (ret) + goto cleanup; + ret = krb5_parse_name(context, cv5->server, &server); + if (ret) + goto cleanup; + + if (cv5->keyblock.length > 0) { + keyblock_contents = k5memdup(cv5->keyblock.data, cv5->keyblock.length, + &ret); + if (keyblock_contents == NULL) + goto cleanup; + } + + if (cv5->ticket.length > 0) { + ticket_data = k5memdup(cv5->ticket.data, cv5->ticket.length, &ret); + if (ticket_data == NULL) + goto cleanup; + } + + if (cv5->second_ticket.length > 0) { + second_ticket_data = k5memdup(cv5->second_ticket.data, + cv5->second_ticket.length, &ret); + if (second_ticket_data == NULL) + goto cleanup; + } + + ret = cc_data_list_to_addresses(context, cv5->addresses, &addresses); + if (ret) + goto cleanup; + + ret = cc_data_list_to_authdata(context, cv5->authdata, &authdata); + if (ret) + goto cleanup; + + cred_out->client = client; + cred_out->server = server; + client = server = NULL; + + cred_out->keyblock.magic = KV5M_KEYBLOCK; + cred_out->keyblock.enctype = cv5->keyblock.type; + cred_out->keyblock.length = cv5->keyblock.length; + cred_out->keyblock.contents = keyblock_contents; + keyblock_contents = NULL; + + cred_out->times.authtime = cv5->authtime; + cred_out->times.starttime = cv5->starttime; + cred_out->times.endtime = cv5->endtime; + cred_out->times.renew_till = cv5->renew_till; + cred_out->is_skey = cv5->is_skey; + cred_out->ticket_flags = cv5->ticket_flags; + + cred_out->ticket = make_data(ticket_data, cv5->ticket.length); + cred_out->second_ticket = make_data(second_ticket_data, + cv5->second_ticket.length); + ticket_data = second_ticket_data = NULL; + + cred_out->addresses = addresses; + addresses = NULL; + + cred_out->authdata = authdata; + authdata = NULL; + + cred_out->magic = KV5M_CREDS; + +cleanup: + krb5_free_principal(context, client); + krb5_free_principal(context, server); + krb5_free_addresses(context, addresses); + krb5_free_authdata(context, authdata); + free(keyblock_contents); + free(ticket_data); + free(second_ticket_data); + return ret; +} + +krb5_error_code +k5_krb5_to_ccapi_creds(krb5_context context, krb5_creds *cred, + cc_credentials_union **ccapi_cred_out) +{ + krb5_error_code ret; + cc_credentials_union *cred_union = NULL; + cc_credentials_v5_t *cv5 = NULL; + char *client = NULL, *server = NULL; + uint8_t *ticket_data = NULL, *second_ticket_data = NULL; + uint8_t *keyblock_data = NULL; + cc_data **addr_list = NULL, **authdata_list = NULL; + + cred_union = k5alloc(sizeof(*cred_union), &ret); + if (cred_union == NULL) + goto cleanup; + + cv5 = k5alloc(sizeof(*cv5), &ret); + if (cv5 == NULL) + goto cleanup; + + ret = krb5_unparse_name(context, cred->client, &client); + if (ret) + goto cleanup; + ret = krb5_unparse_name(context, cred->server, &server); + if (ret) + goto cleanup; + + if (cred->keyblock.length > 0) { + keyblock_data = k5memdup(cred->keyblock.contents, + cred->keyblock.length, &ret); + if (keyblock_data == NULL) + goto cleanup; + } + + if (cred->ticket.length > 0) { + ticket_data = k5memdup0(cred->ticket.data, cred->ticket.length, &ret); + if (ticket_data == NULL) + goto cleanup; + } + + if (cred->second_ticket.length > 0) { + second_ticket_data = k5memdup0(cred->second_ticket.data, + cred->second_ticket.length, &ret); + if (second_ticket_data == NULL) + goto cleanup; + } + + ret = addresses_to_cc_data_list(context, cred->addresses, &addr_list); + if (ret) + goto cleanup; + + ret = authdata_to_cc_data_list(context, cred->authdata, &authdata_list); + if (ret) + goto cleanup; + + cv5->client = client; + cv5->server = server; + client = server = NULL; + + cv5->keyblock.type = cred->keyblock.enctype; + cv5->keyblock.length = cred->keyblock.length; + cv5->keyblock.data = keyblock_data; + keyblock_data = NULL; + + cv5->authtime = cred->times.authtime; + cv5->starttime = cred->times.starttime; + cv5->endtime = cred->times.endtime; + cv5->renew_till = cred->times.renew_till; + cv5->is_skey = cred->is_skey; + cv5->ticket_flags = cred->ticket_flags; + + cv5->ticket.length = cred->ticket.length; + cv5->ticket.data = ticket_data; + cv5->second_ticket.length = cred->second_ticket.length; + cv5->second_ticket.data = second_ticket_data; + ticket_data = second_ticket_data = NULL; + + cv5->addresses = addr_list; + addr_list = NULL; + + cv5->authdata = authdata_list; + authdata_list = NULL; + + cred_union->version = cc_credentials_v5; + cred_union->credentials.credentials_v5 = cv5; + cv5 = NULL; + + *ccapi_cred_out = cred_union; + cred_union = NULL; + +cleanup: + free_cc_data_list(addr_list); + free_cc_data_list(authdata_list); + free(keyblock_data); + free(ticket_data); + free(second_ticket_data); + krb5_free_unparsed_name(context, client); + krb5_free_unparsed_name(context, server); + free(cv5); + free(cred_union); + return ret; +} + +void +k5_release_ccapi_cred(cc_credentials_union *ccapi_cred) +{ + cc_credentials_v5_t *cv5; + + if (ccapi_cred == NULL) + return; + if (ccapi_cred->version != cc_credentials_v5) + return; + if (ccapi_cred->credentials.credentials_v5 == NULL) + return; + + cv5 = ccapi_cred->credentials.credentials_v5; + + free(cv5->client); + free(cv5->server); + free(cv5->keyblock.data); + free(cv5->ticket.data); + free(cv5->second_ticket.data); + free_cc_data_list(cv5->addresses); + free_cc_data_list(cv5->authdata); + free(cv5); + free(ccapi_cred); +} + +#endif /* defined(USE_CCAPI) */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccapi_util.h b/krb5-1.21.3/src/lib/krb5/ccache/ccapi_util.h new file mode 100644 index 00000000..6a866082 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccapi_util.h @@ -0,0 +1,50 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/ccapi_util.c - conversion declarations for CCAPI creds */ +/* + * Copyright (C) 2021 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. + */ + +#ifndef CCAPI_UTIL_H +#define CCAPI_UTIL_H + +#include + +krb5_error_code +k5_ccapi_to_krb5_creds(krb5_context context, + const cc_credentials_union *ccapi_cred, + krb5_creds *cred_out); + +krb5_error_code +k5_krb5_to_ccapi_creds(krb5_context context, krb5_creds *cred, + cc_credentials_union **ccapi_cred_out); + +void +k5_release_ccapi_cred(cc_credentials_union *ccapi_cred); + +#endif /* CCAPI_UTIL_H */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccbase.c b/krb5-1.21.3/src/lib/krb5/ccache/ccbase.c new file mode 100644 index 00000000..5a013208 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccbase.c @@ -0,0 +1,638 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/ccbase.c - Registration functions for ccache */ +/* + * Copyright 1990,2004,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "k5-thread.h" + +#include "fcc.h" +#include "cc-int.h" + +struct krb5_cc_typelist { + const krb5_cc_ops *ops; + struct krb5_cc_typelist *next; +}; + +struct krb5_cc_typecursor { + struct krb5_cc_typelist *tptr; +}; +/* typedef krb5_cc_typecursor in k5-int.h */ + +extern const krb5_cc_ops krb5_mcc_ops; + +#define NEXT NULL + +#ifdef _WIN32 +extern const krb5_cc_ops krb5_lcc_ops; +static struct krb5_cc_typelist cc_lcc_entry = { &krb5_lcc_ops, NEXT }; +#undef NEXT +#define NEXT &cc_lcc_entry +#endif + +#ifdef USE_CCAPI +extern const krb5_cc_ops krb5_cc_stdcc_ops; +static struct krb5_cc_typelist cc_stdcc_entry = { &krb5_cc_stdcc_ops, NEXT }; +#undef NEXT +#define NEXT &cc_stdcc_entry +#endif + +static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, NEXT }; +#undef NEXT +#define NEXT &cc_mcc_entry + +#ifndef NO_FILE_CCACHE +static struct krb5_cc_typelist cc_fcc_entry = { &krb5_cc_file_ops, NEXT }; +#undef NEXT +#define NEXT &cc_fcc_entry +#endif + +#ifdef USE_KEYRING_CCACHE +extern const krb5_cc_ops krb5_krcc_ops; +static struct krb5_cc_typelist cc_krcc_entry = { &krb5_krcc_ops, NEXT }; +#undef NEXT +#define NEXT &cc_krcc_entry +#endif /* USE_KEYRING_CCACHE */ + +#ifndef _WIN32 +extern const krb5_cc_ops krb5_dcc_ops; +static struct krb5_cc_typelist cc_dcc_entry = { &krb5_dcc_ops, NEXT }; +#undef NEXT +#define NEXT &cc_dcc_entry + +extern const krb5_cc_ops krb5_kcm_ops; +static struct krb5_cc_typelist cc_kcm_entry = { &krb5_kcm_ops, NEXT }; +#undef NEXT +#define NEXT &cc_kcm_entry +#endif /* not _WIN32 */ + +#ifdef USE_CCAPI_MACOS +extern const krb5_cc_ops krb5_api_macos_ops; +static struct krb5_cc_typelist cc_macos_entry = { &krb5_api_macos_ops, NEXT }; +#undef NEXT +#define NEXT &cc_macos_entry +#endif /* USE_CCAPI_MACOS */ + +#define INITIAL_TYPEHEAD (NEXT) +static struct krb5_cc_typelist *cc_typehead = INITIAL_TYPEHEAD; +static k5_mutex_t cc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER; + +/* mutex for krb5_cccol_[un]lock */ +static k5_cc_mutex cccol_lock = K5_CC_MUTEX_PARTIAL_INITIALIZER; + +static krb5_error_code +krb5int_cc_getops(krb5_context, const char *, const krb5_cc_ops **); + +int +krb5int_cc_initialize(void) +{ + int err; + + err = k5_cc_mutex_finish_init(&cccol_lock); + if (err) + return err; + err = k5_cc_mutex_finish_init(&krb5int_mcc_mutex); + if (err) + return err; + err = k5_mutex_finish_init(&cc_typelist_lock); + if (err) + return err; +#ifndef NO_FILE_CCACHE + err = k5_cc_mutex_finish_init(&krb5int_cc_file_mutex); + if (err) + return err; +#endif +#ifdef USE_KEYRING_CCACHE + err = k5_cc_mutex_finish_init(&krb5int_krcc_mutex); + if (err) + return err; +#endif + return 0; +} + +void +krb5int_cc_finalize(void) +{ + struct krb5_cc_typelist *t, *t_next; + k5_cccol_force_unlock(); + k5_cc_mutex_destroy(&cccol_lock); + k5_mutex_destroy(&cc_typelist_lock); +#ifndef NO_FILE_CCACHE + k5_cc_mutex_destroy(&krb5int_cc_file_mutex); +#endif + k5_cc_mutex_destroy(&krb5int_mcc_mutex); +#ifdef USE_KEYRING_CCACHE + k5_cc_mutex_destroy(&krb5int_krcc_mutex); +#endif + for (t = cc_typehead; t != INITIAL_TYPEHEAD; t = t_next) { + t_next = t->next; + free(t); + } +} + + +/* + * Register a new credentials cache type + * If override is set, replace any existing ccache with that type tag + */ + +krb5_error_code KRB5_CALLCONV +krb5_cc_register(krb5_context context, const krb5_cc_ops *ops, + krb5_boolean override) +{ + struct krb5_cc_typelist *t; + + k5_mutex_lock(&cc_typelist_lock); + for (t = cc_typehead;t && strcmp(t->ops->prefix,ops->prefix);t = t->next) + ; + if (t) { + if (override) { + t->ops = ops; + k5_mutex_unlock(&cc_typelist_lock); + return 0; + } else { + k5_mutex_unlock(&cc_typelist_lock); + return KRB5_CC_TYPE_EXISTS; + } + } + if (!(t = (struct krb5_cc_typelist *) malloc(sizeof(*t)))) { + k5_mutex_unlock(&cc_typelist_lock); + return ENOMEM; + } + t->next = cc_typehead; + t->ops = ops; + cc_typehead = t; + k5_mutex_unlock(&cc_typelist_lock); + return 0; +} + +/* + * Resolve a credential cache name into a cred. cache object. + * + * The name is currently constrained to be of the form "type:residual"; + * + * The "type" portion corresponds to one of the predefined credential + * cache types, while the "residual" portion is specific to the + * particular cache type. + */ + +#include +krb5_error_code KRB5_CALLCONV +krb5_cc_resolve (krb5_context context, const char *name, krb5_ccache *cache) +{ + char *pfx, *cp; + const char *resid; + unsigned int pfxlen; + krb5_error_code err; + const krb5_cc_ops *ops; + + if (name == NULL) + return KRB5_CC_BADNAME; + pfx = NULL; + cp = strchr (name, ':'); + if (!cp) { + if (krb5_cc_dfl_ops) + return (*krb5_cc_dfl_ops->resolve)(context, cache, name); + else + return KRB5_CC_BADNAME; + } + + pfxlen = cp - name; + + if ( pfxlen == 1 && isalpha((unsigned char) name[0]) ) { + /* We found a drive letter not a prefix - use FILE */ + pfx = strdup("FILE"); + if (!pfx) + return ENOMEM; + + resid = name; + } else { + resid = name + pfxlen + 1; + pfx = k5memdup0(name, pfxlen, &err); + if (pfx == NULL) + return err; + } + + *cache = (krb5_ccache) 0; + + err = krb5int_cc_getops(context, pfx, &ops); + if (pfx != NULL) + free(pfx); + if (err) + return err; + + return ops->resolve(context, cache, resid); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_dup(krb5_context context, krb5_ccache in, krb5_ccache *out) +{ + return in->ops->resolve(context, out, in->ops->get_name(context, in)); +} + +/* + * cc_getops + * + * Internal function to return the ops vector for a given ccache + * prefix string. + */ +static krb5_error_code +krb5int_cc_getops(krb5_context context, + const char *pfx, + const krb5_cc_ops **ops) +{ + struct krb5_cc_typelist *tlist; + + k5_mutex_lock(&cc_typelist_lock); + for (tlist = cc_typehead; tlist; tlist = tlist->next) { + if (strcmp (tlist->ops->prefix, pfx) == 0) { + *ops = tlist->ops; + k5_mutex_unlock(&cc_typelist_lock); + return 0; + } + } + k5_mutex_unlock(&cc_typelist_lock); + if (krb5_cc_dfl_ops && !strcmp (pfx, krb5_cc_dfl_ops->prefix)) { + *ops = krb5_cc_dfl_ops; + return 0; + } + return KRB5_CC_UNKNOWN_TYPE; +} + +/* + * cc_new_unique + * + * Generate a new unique ccache, given a ccache type and a hint + * string. Ignores the hint string for now. + */ +krb5_error_code KRB5_CALLCONV +krb5_cc_new_unique( + krb5_context context, + const char *type, + const char *hint, + krb5_ccache *id) +{ + const krb5_cc_ops *ops; + krb5_error_code err; + + *id = NULL; + + TRACE_CC_NEW_UNIQUE(context, type); + err = krb5int_cc_getops(context, type, &ops); + if (err) + return err; + + return ops->gen_new(context, id); +} + +/* + * cc_typecursor + * + * Note: to avoid copying the typelist at cursor creation time, among + * other things, we assume that the only additions ever occur to the + * typelist. + */ +krb5_error_code +krb5int_cc_typecursor_new(krb5_context context, krb5_cc_typecursor *t) +{ + krb5_cc_typecursor n = NULL; + + *t = NULL; + n = malloc(sizeof(*n)); + if (n == NULL) + return ENOMEM; + + k5_mutex_lock(&cc_typelist_lock); + n->tptr = cc_typehead; + k5_mutex_unlock(&cc_typelist_lock); + *t = n; + return 0; +} + +krb5_error_code +krb5int_cc_typecursor_next(krb5_context context, + krb5_cc_typecursor t, + const krb5_cc_ops **ops) +{ + *ops = NULL; + if (t->tptr == NULL) + return 0; + + k5_mutex_lock(&cc_typelist_lock); + *ops = t->tptr->ops; + t->tptr = t->tptr->next; + k5_mutex_unlock(&cc_typelist_lock); + return 0; +} + +krb5_error_code +krb5int_cc_typecursor_free(krb5_context context, krb5_cc_typecursor *t) +{ + free(*t); + *t = NULL; + return 0; +} + +krb5_error_code +k5_nonatomic_replace(krb5_context context, krb5_ccache ccache, + krb5_principal princ, krb5_creds **creds) +{ + krb5_error_code ret; + int i; + + ret = krb5_cc_initialize(context, ccache, princ); + for (i = 0; !ret && creds[i] != NULL; creds++) + ret = krb5_cc_store_cred(context, ccache, creds[i]); + return ret; +} + +static krb5_error_code +read_creds(krb5_context context, krb5_ccache ccache, krb5_creds ***creds_out) +{ + krb5_error_code ret; + krb5_cc_cursor cur = NULL; + krb5_creds **list = NULL, *cred = NULL, **newptr; + int i; + + *creds_out = NULL; + + ret = krb5_cc_start_seq_get(context, ccache, &cur); + if (ret) + goto cleanup; + + /* Allocate one extra entry so that list remains valid for freeing after + * we add the next entry and before we reallocate it. */ + list = k5calloc(2, sizeof(*list), &ret); + if (list == NULL) + goto cleanup; + + i = 0; + for (;;) { + cred = k5alloc(sizeof(*cred), &ret); + if (cred == NULL) + goto cleanup; + ret = krb5_cc_next_cred(context, ccache, &cur, cred); + if (ret == KRB5_CC_END) + break; + if (ret) + goto cleanup; + list[i++] = cred; + list[i] = NULL; + cred = NULL; + + newptr = realloc(list, (i + 2) * sizeof(*list)); + if (newptr == NULL) { + ret = ENOMEM; + goto cleanup; + } + list = newptr; + list[i + 1] = NULL; + } + ret = 0; + + *creds_out = list; + list = NULL; + +cleanup: + if (cur != NULL) + (void)krb5_cc_end_seq_get(context, ccache, &cur); + krb5_free_tgt_creds(context, list); + free(cred); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_move(krb5_context context, krb5_ccache src, krb5_ccache dst) +{ + krb5_error_code ret; + krb5_principal princ = NULL; + krb5_creds **creds = NULL; + + TRACE_CC_MOVE(context, src, dst); + + ret = krb5_cc_get_principal(context, src, &princ); + if (ret) + goto cleanup; + + ret = read_creds(context, src, &creds); + if (ret) + goto cleanup; + + if (dst->ops->replace == NULL) + ret = k5_nonatomic_replace(context, dst, princ, creds); + else + ret = dst->ops->replace(context, dst, princ, creds); + if (ret) + goto cleanup; + + ret = krb5_cc_destroy(context, src); + +cleanup: + krb5_free_principal(context, princ); + krb5_free_tgt_creds(context, creds); + return ret; +} + +krb5_boolean KRB5_CALLCONV +krb5_cc_support_switch(krb5_context context, const char *type) +{ + const krb5_cc_ops *ops; + krb5_error_code err; + + err = krb5int_cc_getops(context, type, &ops); + return (err ? FALSE : (ops->switch_to != NULL)); +} + +krb5_error_code +k5_cc_mutex_init(k5_cc_mutex *m) +{ + krb5_error_code ret = 0; + + ret = k5_mutex_init(&m->lock); + if (ret) return ret; + m->owner = NULL; + m->refcount = 0; + + return ret; +} + +krb5_error_code +k5_cc_mutex_finish_init(k5_cc_mutex *m) +{ + krb5_error_code ret = 0; + + ret = k5_mutex_finish_init(&m->lock); + if (ret) return ret; + m->owner = NULL; + m->refcount = 0; + + return ret; +} + +void +k5_cc_mutex_assert_locked(krb5_context context, k5_cc_mutex *m) +{ +#ifdef DEBUG_THREADS + assert(m->refcount > 0); + assert(m->owner == context); +#endif + k5_assert_locked(&m->lock); +} + +void +k5_cc_mutex_assert_unlocked(krb5_context context, k5_cc_mutex *m) +{ +#ifdef DEBUG_THREADS + assert(m->refcount == 0); + assert(m->owner == NULL); +#endif + k5_assert_unlocked(&m->lock); +} + +void +k5_cc_mutex_lock(krb5_context context, k5_cc_mutex *m) +{ + /* not locked or already locked by another context */ + if (m->owner != context) { + /* acquire lock, blocking until available */ + k5_mutex_lock(&m->lock); + m->owner = context; + m->refcount = 1; + } + /* already locked by this context, just increase refcount */ + else { + m->refcount++; + } +} + +void +k5_cc_mutex_unlock(krb5_context context, k5_cc_mutex *m) +{ + /* verify owner and sanity check refcount */ + if ((m->owner != context) || (m->refcount < 1)) { + return; + } + /* decrement & unlock when count reaches zero */ + m->refcount--; + if (m->refcount == 0) { + m->owner = NULL; + k5_mutex_unlock(&m->lock); + } +} + +/* necessary to make reentrant locks play nice with krb5int_cc_finalize */ +void +k5_cc_mutex_force_unlock(k5_cc_mutex *m) +{ + m->refcount = 0; + m->owner = NULL; + if (m->refcount > 0) { + k5_mutex_unlock(&m->lock); + } +} + +/* + * holds on to all pertype global locks as well as typelist lock + */ + +krb5_error_code +k5_cccol_lock(krb5_context context) +{ + krb5_error_code ret = 0; + + k5_cc_mutex_lock(context, &cccol_lock); + k5_mutex_lock(&cc_typelist_lock); + k5_cc_mutex_lock(context, &krb5int_cc_file_mutex); + k5_cc_mutex_lock(context, &krb5int_mcc_mutex); +#ifdef USE_KEYRING_CCACHE + k5_cc_mutex_lock(context, &krb5int_krcc_mutex); +#endif +#ifdef USE_CCAPI + ret = krb5_stdccv3_context_lock(context); + if (ret) { + k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + k5_mutex_unlock(&cc_typelist_lock); + k5_cc_mutex_unlock(context, &cccol_lock); + return ret; + } +#endif + k5_mutex_unlock(&cc_typelist_lock); + return ret; +} + +krb5_error_code +k5_cccol_unlock(krb5_context context) +{ + krb5_error_code ret = 0; + + /* sanity check */ + k5_cc_mutex_assert_locked(context, &cccol_lock); + + k5_mutex_lock(&cc_typelist_lock); + + /* unlock each type in the opposite order */ +#ifdef USE_CCAPI + krb5_stdccv3_context_unlock(context); +#endif +#ifdef USE_KEYRING_CCACHE + k5_cc_mutex_assert_locked(context, &krb5int_krcc_mutex); + k5_cc_mutex_unlock(context, &krb5int_krcc_mutex); +#endif + k5_cc_mutex_assert_locked(context, &krb5int_mcc_mutex); + k5_cc_mutex_unlock(context, &krb5int_mcc_mutex); + k5_cc_mutex_assert_locked(context, &krb5int_cc_file_mutex); + k5_cc_mutex_unlock(context, &krb5int_cc_file_mutex); + k5_mutex_assert_locked(&cc_typelist_lock); + + k5_mutex_unlock(&cc_typelist_lock); + k5_cc_mutex_unlock(context, &cccol_lock); + + return ret; +} + +/* necessary to make reentrant locks play nice with krb5int_cc_finalize */ +void +k5_cccol_force_unlock() +{ + /* sanity check */ + if ((&cccol_lock)->refcount == 0) { + return; + } + + k5_mutex_lock(&cc_typelist_lock); + + /* unlock each type in the opposite order */ +#ifdef USE_KEYRING_CCACHE + k5_cc_mutex_force_unlock(&krb5int_krcc_mutex); +#endif +#ifdef USE_CCAPI + krb5_stdccv3_context_unlock(NULL); +#endif + k5_cc_mutex_force_unlock(&krb5int_mcc_mutex); + k5_cc_mutex_force_unlock(&krb5int_cc_file_mutex); + + k5_mutex_unlock(&cc_typelist_lock); + k5_cc_mutex_force_unlock(&cccol_lock); +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/cccopy.c b/krb5-1.21.3/src/lib/krb5/ccache/cccopy.c new file mode 100644 index 00000000..d71d439d --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/cccopy.c @@ -0,0 +1,37 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include "k5-int.h" + +krb5_error_code KRB5_CALLCONV +krb5_cc_copy_creds(krb5_context context, krb5_ccache incc, krb5_ccache outcc) +{ + krb5_error_code code; + krb5_cc_cursor cur = 0; + krb5_creds creds; + + if ((code = krb5_cc_start_seq_get(context, incc, &cur))) + goto cleanup; + + while (!(code = krb5_cc_next_cred(context, incc, &cur, &creds))) { + code = krb5_cc_store_cred(context, outcc, &creds); + krb5_free_cred_contents(context, &creds); + if (code) + goto cleanup; + } + + if (code != KRB5_CC_END) + goto cleanup; + + code = krb5_cc_end_seq_get(context, incc, &cur); + cur = 0; + if (code) + goto cleanup; + + code = 0; + +cleanup: + /* If set then we are in an error pathway */ + if (cur) + krb5_cc_end_seq_get(context, incc, &cur); + + return(code); +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/cccursor.c b/krb5-1.21.3/src/lib/krb5/ccache/cccursor.c new file mode 100644 index 00000000..926873f2 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/cccursor.c @@ -0,0 +1,282 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/cccursor.c */ +/* + * Copyright 2006, 2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * cursor for sequential traversal of ccaches + */ + +#include "cc-int.h" +#include "../krb/int-proto.h" +#include "../os/os-proto.h" + +#include + +struct _krb5_cccol_cursor { + krb5_cc_typecursor typecursor; + const krb5_cc_ops *ops; + krb5_cc_ptcursor ptcursor; +}; +/* typedef of krb5_cccol_cursor is in krb5.h */ + +krb5_error_code KRB5_CALLCONV +krb5_cccol_cursor_new(krb5_context context, + krb5_cccol_cursor *cursor) +{ + krb5_error_code ret = 0; + krb5_cccol_cursor n = NULL; + + *cursor = NULL; + n = malloc(sizeof(*n)); + if (n == NULL) + return ENOMEM; + + n->typecursor = NULL; + n->ptcursor = NULL; + n->ops = NULL; + + ret = krb5int_cc_typecursor_new(context, &n->typecursor); + if (ret) + goto errout; + + do { + /* Find first backend with ptcursor functionality. */ + ret = krb5int_cc_typecursor_next(context, n->typecursor, &n->ops); + if (ret || n->ops == NULL) + goto errout; + } while (n->ops->ptcursor_new == NULL); + + ret = n->ops->ptcursor_new(context, &n->ptcursor); + if (ret) + goto errout; + +errout: + if (ret) { + krb5_cccol_cursor_free(context, &n); + } + *cursor = n; + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_cccol_cursor_next(krb5_context context, + krb5_cccol_cursor cursor, + krb5_ccache *ccache_out) +{ + krb5_error_code ret = 0; + krb5_ccache ccache; + + *ccache_out = NULL; + + /* Are we out of backends? */ + if (cursor->ops == NULL) + return 0; + + while (1) { + ret = cursor->ops->ptcursor_next(context, cursor->ptcursor, &ccache); + if (ret) + return ret; + if (ccache != NULL) { + *ccache_out = ccache; + return 0; + } + + ret = cursor->ops->ptcursor_free(context, &cursor->ptcursor); + if (ret) + return ret; + + do { + /* Find next type with ptcursor functionality. */ + ret = krb5int_cc_typecursor_next(context, cursor->typecursor, + &cursor->ops); + if (ret) + return ret; + if (cursor->ops == NULL) + return 0; + } while (cursor->ops->ptcursor_new == NULL); + + ret = cursor->ops->ptcursor_new(context, &cursor->ptcursor); + if (ret) + return ret; + } +} + +krb5_error_code KRB5_CALLCONV +krb5_cccol_cursor_free(krb5_context context, + krb5_cccol_cursor *cursor) +{ + krb5_cccol_cursor c = *cursor; + + if (c == NULL) + return 0; + + if (c->ptcursor != NULL) + c->ops->ptcursor_free(context, &c->ptcursor); + if (c->typecursor != NULL) + krb5int_cc_typecursor_free(context, &c->typecursor); + free(c); + + *cursor = NULL; + return 0; +} + +static krb5_error_code +match_caches(krb5_context context, krb5_const_principal client, + krb5_ccache *cache_out) +{ + krb5_error_code ret; + krb5_cccol_cursor cursor; + krb5_ccache cache = NULL; + krb5_principal princ; + krb5_boolean eq; + + *cache_out = NULL; + + ret = krb5_cccol_cursor_new(context, &cursor); + if (ret) + return ret; + + while ((ret = krb5_cccol_cursor_next(context, cursor, &cache)) == 0 && + cache != NULL) { + ret = krb5_cc_get_principal(context, cache, &princ); + if (ret == 0) { + eq = krb5_principal_compare(context, princ, client); + krb5_free_principal(context, princ); + if (eq) + break; + } + krb5_cc_close(context, cache); + } + krb5_cccol_cursor_free(context, &cursor); + + if (ret) + return ret; + if (cache == NULL) + return KRB5_CC_NOTFOUND; + + *cache_out = cache; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_cache_match(krb5_context context, krb5_principal client, + krb5_ccache *cache_out) +{ + krb5_error_code ret; + struct canonprinc iter = { client, .subst_defrealm = TRUE }; + krb5_const_principal canonprinc = NULL; + krb5_ccache cache = NULL; + char *name; + + *cache_out = NULL; + + while ((ret = k5_canonprinc(context, &iter, &canonprinc)) == 0 && + canonprinc != NULL) { + ret = match_caches(context, canonprinc, &cache); + if (ret != KRB5_CC_NOTFOUND) + break; + } + free_canonprinc(&iter); + + if (ret == 0 && canonprinc == NULL) { + ret = KRB5_CC_NOTFOUND; + if (krb5_unparse_name(context, client, &name) == 0) { + k5_setmsg(context, ret, + _("Can't find client principal %s in cache collection"), + name); + krb5_free_unparsed_name(context, name); + } + } + + TRACE_CC_CACHE_MATCH(context, client, ret); + if (ret) + return ret; + + *cache_out = cache; + return 0; +} + +/* Store the error state for code from context into errsave, but only if code + * indicates an error and errsave is empty. */ +static void +save_first_error(krb5_context context, krb5_error_code code, + struct errinfo *errsave) +{ + if (code && code != KRB5_FCC_NOFILE && !errsave->code) + k5_save_ctx_error(context, code, errsave); +} + +krb5_error_code KRB5_CALLCONV +krb5_cccol_have_content(krb5_context context) +{ + krb5_error_code ret; + krb5_cccol_cursor col_cursor; + krb5_ccache cache; + krb5_principal princ; + krb5_boolean found = FALSE; + struct errinfo errsave = EMPTY_ERRINFO; + const char *defname; + + ret = krb5_cccol_cursor_new(context, &col_cursor); + save_first_error(context, ret, &errsave); + if (ret) + goto no_entries; + + while (!found) { + ret = krb5_cccol_cursor_next(context, col_cursor, &cache); + save_first_error(context, ret, &errsave); + if (ret || cache == NULL) + break; + princ = NULL; + ret = krb5_cc_get_principal(context, cache, &princ); + save_first_error(context, ret, &errsave); + if (!ret) + found = TRUE; + krb5_free_principal(context, princ); + krb5_cc_close(context, cache); + } + krb5_cccol_cursor_free(context, &col_cursor); + if (found) { + k5_clear_error(&errsave); + return 0; + } + +no_entries: + if (errsave.code) { + /* Report the first error we encountered. */ + ret = k5_restore_ctx_error(context, &errsave); + k5_wrapmsg(context, ret, KRB5_CC_NOTFOUND, + _("No Kerberos credentials available")); + } else { + /* Report the default cache name. */ + defname = krb5_cc_default_name(context); + if (defname != NULL) { + k5_setmsg(context, KRB5_CC_NOTFOUND, + _("No Kerberos credentials available " + "(default cache: %s)"), defname); + } + } + return KRB5_CC_NOTFOUND; +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccdefault.c b/krb5-1.21.3/src/lib/krb5/ccache/ccdefault.c new file mode 100644 index 00000000..1d3625c4 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccdefault.c @@ -0,0 +1,97 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/ccdefault.c - Find default credential cache */ +/* + * Copyright 1990, 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +#ifdef USE_LEASH +static void (*pLeash_AcquireInitialTicketsIfNeeded)(krb5_context,krb5_principal,char*,int) = NULL; +static HANDLE hLeashDLL = INVALID_HANDLE_VALUE; +#ifdef _WIN64 +#define LEASH_DLL "leashw64.dll" +#else +#define LEASH_DLL "leashw32.dll" +#endif +#endif + + +krb5_error_code KRB5_CALLCONV +krb5_cc_default(krb5_context context, krb5_ccache *ccache) +{ + const char *default_name; + + if (!context || context->magic != KV5M_CONTEXT) + return KV5M_CONTEXT; + + default_name = krb5_cc_default_name(context); + if (default_name == NULL) { + /* Could be a bogus context, or an allocation failure, or + other things. Unfortunately the API doesn't allow us + to find out any specifics. */ + return KRB5_FCC_INTERNAL; + } + + return krb5_cc_resolve(context, default_name, ccache); +} + +/* This is the internal function which opens the default ccache. On + platforms supporting the login library's automatic popup dialog to + get tickets, this function also updated the library's internal view + of the current principal associated with this cache. + + All krb5 and GSS functions which need to open a cache to get a tgt + to obtain service tickets should call this function, not + krb5_cc_default(). */ + +krb5_error_code KRB5_CALLCONV +krb5int_cc_default(krb5_context context, krb5_ccache *ccache) +{ + if (!context || context->magic != KV5M_CONTEXT) { + return KV5M_CONTEXT; + } + +#ifdef USE_LEASH + if ( hLeashDLL == INVALID_HANDLE_VALUE ) { + hLeashDLL = LoadLibrary(LEASH_DLL); + if ( hLeashDLL != INVALID_HANDLE_VALUE ) { + (FARPROC) pLeash_AcquireInitialTicketsIfNeeded = + GetProcAddress(hLeashDLL, "not_an_API_Leash_AcquireInitialTicketsIfNeeded"); + } + } + + if ( pLeash_AcquireInitialTicketsIfNeeded ) { + char ccname[256]=""; + pLeash_AcquireInitialTicketsIfNeeded(context, NULL, ccname, sizeof(ccname)); + if (ccname[0]) { + char * ccdefname = krb5_cc_default_name (context); + if (!ccdefname || strcmp (ccdefname, ccname) != 0) { + krb5_cc_set_default_name (context, ccname); + } + } + } +#endif + + return krb5_cc_default (context, ccache); +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccdefops.c b/krb5-1.21.3/src/lib/krb5/ccache/ccdefops.c new file mode 100644 index 00000000..abe0c6d8 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccdefops.c @@ -0,0 +1,58 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/ccdefops.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Default credentials cache determination. This is a separate file + * so that the user can more easily override it. */ + +#include "k5-int.h" + +#if defined(USE_CCAPI) + +/* + * Macs use the shared, memory based credentials cache + * Windows may also use the ccapi cache, but only if the Krbcc32.dll + * can be found; otherwise it falls back to using the old + * file-based ccache. + */ +#include "stdcc.h" /* from ccapi subdir */ + +const krb5_cc_ops *krb5_cc_dfl_ops = &krb5_cc_stdcc_ops; + +#elif defined(NO_FILE_CCACHE) + +/* Note that this version isn't likely to work very well for multiple + processes. It's mostly a placeholder so we can experiment with + building the NO_FILE_CCACHE code on UNIX. */ + +extern const krb5_cc_ops krb5_mcc_ops; +const krb5_cc_ops *krb5_cc_dfl_ops = &krb5_mcc_ops; + +#else + +#include "fcc.h" +const krb5_cc_ops *krb5_cc_dfl_ops = &krb5_cc_file_ops; + +#endif diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccfns.c b/krb5-1.21.3/src/lib/krb5/ccache/ccfns.c new file mode 100644 index 00000000..e0eb39a6 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccfns.c @@ -0,0 +1,320 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/ccfns.c - Dispatch methods for credentials cache code.*/ +/* + * Copyright 2000, 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "cc-int.h" +#include "../krb/int-proto.h" + +const char * KRB5_CALLCONV +krb5_cc_get_name(krb5_context context, krb5_ccache cache) +{ + return cache->ops->get_name(context, cache); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_get_full_name(krb5_context context, krb5_ccache cache, + char **fullname_out) +{ + char *name; + + *fullname_out = NULL; + if (asprintf(&name, "%s:%s", cache->ops->prefix, + cache->ops->get_name(context, cache)) < 0) + return ENOMEM; + *fullname_out = name; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_gen_new(krb5_context context, krb5_ccache *cache) +{ + TRACE_CC_GEN_NEW(context, cache); + return (*cache)->ops->gen_new(context, cache); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_initialize(krb5_context context, krb5_ccache cache, + krb5_principal principal) +{ + TRACE_CC_INIT(context, cache, principal); + return cache->ops->init(context, cache, principal); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_destroy(krb5_context context, krb5_ccache cache) +{ + TRACE_CC_DESTROY(context, cache); + return cache->ops->destroy(context, cache); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_close(krb5_context context, krb5_ccache cache) +{ + return cache->ops->close(context, cache); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_store_cred(krb5_context context, krb5_ccache cache, + krb5_creds *creds) +{ + TRACE_CC_STORE(context, cache, creds); + return cache->ops->store(context, cache, creds); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_retrieve_cred(krb5_context context, krb5_ccache cache, + krb5_flags flags, krb5_creds *mcreds, + krb5_creds *creds) +{ + krb5_error_code ret; + krb5_data tmprealm; + + ret = cache->ops->retrieve(context, cache, flags, mcreds, creds); + TRACE_CC_RETRIEVE(context, cache, mcreds, ret); + if (ret != KRB5_CC_NOTFOUND) + return ret; + if (mcreds->client == NULL || mcreds->server == NULL || + !krb5_is_referral_realm(&mcreds->server->realm)) + return ret; + + /* + * Retry using client's realm if service has referral realm. + */ + tmprealm = mcreds->server->realm; + mcreds->server->realm = mcreds->client->realm; + ret = cache->ops->retrieve(context, cache, flags, mcreds, creds); + TRACE_CC_RETRIEVE_REF(context, cache, mcreds, ret); + mcreds->server->realm = tmprealm; + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_get_principal(krb5_context context, krb5_ccache cache, + krb5_principal *principal) +{ + return cache->ops->get_princ(context, cache, principal); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_start_seq_get(krb5_context context, krb5_ccache cache, + krb5_cc_cursor *cursor) +{ + return cache->ops->get_first(context, cache, cursor); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_next_cred(krb5_context context, krb5_ccache cache, + krb5_cc_cursor *cursor, krb5_creds *creds) +{ + return cache->ops->get_next(context, cache, cursor, creds); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_end_seq_get(krb5_context context, krb5_ccache cache, + krb5_cc_cursor *cursor) +{ + return cache->ops->end_get(context, cache, cursor); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_remove_cred(krb5_context context, krb5_ccache cache, krb5_flags flags, + krb5_creds *creds) +{ + TRACE_CC_REMOVE(context, cache, creds); + return cache->ops->remove_cred(context, cache, flags, creds); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_set_flags(krb5_context context, krb5_ccache cache, krb5_flags flags) +{ + return cache->ops->set_flags(context, cache, flags); +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_get_flags(krb5_context context, krb5_ccache cache, krb5_flags *flags) +{ + return cache->ops->get_flags(context, cache, flags); +} + +const char * KRB5_CALLCONV +krb5_cc_get_type(krb5_context context, krb5_ccache cache) +{ + return cache->ops->prefix; +} + +krb5_error_code +k5_cc_lock(krb5_context context, krb5_ccache ccache) +{ + return ccache->ops->lock(context, ccache); +} + +krb5_error_code +k5_cc_unlock(krb5_context context, krb5_ccache ccache) +{ + return ccache->ops->unlock(context, ccache); +} + +static const char conf_realm[] = "X-CACHECONF:"; +static const char conf_name[] = "krb5_ccache_conf_data"; + +krb5_error_code +k5_build_conf_principals(krb5_context context, krb5_ccache id, + krb5_const_principal principal, + const char *name, krb5_creds *cred) +{ + krb5_principal client; + krb5_error_code ret; + char *pname = NULL; + + memset(cred, 0, sizeof(*cred)); + + ret = krb5_cc_get_principal(context, id, &client); + if (ret) + return ret; + + if (principal) { + ret = krb5_unparse_name(context, principal, &pname); + if (ret) + return ret; + } + + ret = krb5_build_principal(context, &cred->server, + sizeof(conf_realm) - 1, conf_realm, + conf_name, name, pname, (char *)NULL); + krb5_free_unparsed_name(context, pname); + if (ret) { + krb5_free_principal(context, client); + return ret; + } + ret = krb5_copy_principal(context, client, &cred->client); + krb5_free_principal(context, client); + return ret; +} + +krb5_boolean KRB5_CALLCONV +krb5_is_config_principal(krb5_context context, + krb5_const_principal principal) +{ + const krb5_data *realm = &principal->realm; + + if (realm->length != sizeof(conf_realm) - 1 || + memcmp(realm->data, conf_realm, sizeof(conf_realm) - 1) != 0) + return FALSE; + + if (principal->length == 0 || + principal->data[0].length != (sizeof(conf_name) - 1) || + memcmp(principal->data[0].data, conf_name, sizeof(conf_name) - 1) != 0) + return FALSE; + + return TRUE; +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_set_config(krb5_context context, krb5_ccache id, + krb5_const_principal principal, + const char *key, krb5_data *data) +{ + krb5_error_code ret; + krb5_creds cred; + memset(&cred, 0, sizeof(cred)); + + TRACE_CC_SET_CONFIG(context, id, principal, key, data); + + ret = k5_build_conf_principals(context, id, principal, key, &cred); + if (ret) + goto out; + + if (data == NULL) { + ret = krb5_cc_remove_cred(context, id, 0, &cred); + } else { + ret = krb5int_copy_data_contents(context, data, &cred.ticket); + if (ret) + goto out; + ret = krb5_cc_store_cred(context, id, &cred); + } +out: + krb5_free_cred_contents(context, &cred); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_get_config(krb5_context context, krb5_ccache id, + krb5_const_principal principal, + const char *key, krb5_data *data) +{ + krb5_creds mcred, cred; + krb5_error_code ret; + + memset(&cred, 0, sizeof(cred)); + memset(data, 0, sizeof(*data)); + + ret = k5_build_conf_principals(context, id, principal, key, &mcred); + if (ret) + goto out; + + ret = krb5_cc_retrieve_cred(context, id, 0, &mcred, &cred); + if (ret) + goto out; + + ret = krb5int_copy_data_contents(context, &cred.ticket, data); + if (ret) + goto out; + + TRACE_CC_GET_CONFIG(context, id, principal, key, data); + +out: + krb5_free_cred_contents(context, &cred); + krb5_free_cred_contents(context, &mcred); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_switch(krb5_context context, krb5_ccache cache) +{ + if (cache->ops->switch_to == NULL) + return 0; + return cache->ops->switch_to(context, cache); +} + +krb5_error_code +k5_cc_store_primary_cred(krb5_context context, krb5_ccache cache, + krb5_creds *creds) +{ + krb5_error_code ret; + + /* Write a start realm if we're writing a TGT and the client realm isn't + * the same as the TGS realm. */ + if (IS_TGS_PRINC(creds->server) && + !data_eq(creds->client->realm, creds->server->data[1])) { + ret = krb5_cc_set_config(context, cache, NULL, + KRB5_CC_CONF_START_REALM, + &creds->server->data[1]); + if (ret) + return ret; + } + + return krb5_cc_store_cred(context, cache, creds); +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccmarshal.c b/krb5-1.21.3/src/lib/krb5/ccache/ccmarshal.c new file mode 100644 index 00000000..ab284e72 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccmarshal.c @@ -0,0 +1,570 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/ccmarshal.c - Functions for serializing creds */ +/* + * Copyright (C) 2014 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. + */ + +/* + * This file implements marshalling and unmarshalling of krb5 credentials and + * principals in versions 1 through 4 of the FILE ccache format. Version 4 is + * also used for the KEYRING ccache type. + * + * The FILE credential cache format uses fixed 16-bit or 32-bit representations + * of integers. In versions 1 and 2 these are in host byte order; in later + * versions they are in big-endian byte order. Variable-length fields are + * represented with a 32-bit length followed by the field value. There is no + * type tagging; field representations are simply concatenated together. + * + * A psuedo-BNF grammar for the credential and principal formats is: + * + * credential ::= + * client (principal) + * server (principal) + * keyblock (keyblock) + * authtime (32 bits) + * starttime (32 bits) + * endtime (32 bits) + * renew_till (32 bits) + * is_skey (1 byte, 0 or 1) + * ticket_flags (32 bits) + * addresses (addresses) + * authdata (authdata) + * ticket (data) + * second_ticket (data) + * + * principal ::= + * name type (32 bits) [omitted in version 1] + * count of components (32 bits) [includes realm in version 1] + * realm (data) + * component1 (data) + * component2 (data) + * ... + * + * keyblock ::= + * enctype (16 bits) [repeated twice in version 3; see below] + * data + * + * addresses ::= + * count (32 bits) + * address1 + * address2 + * ... + * + * address ::= + * addrtype (16 bits) + * data + * + * authdata ::= + * count (32 bits) + * authdata1 + * authdata2 + * ... + * + * authdata ::= + * ad_type (16 bits) + * data + * + * data ::= + * length (32 bits) + * value (length bytes) + * + * When version 3 was current (before release 1.0), the keyblock had separate + * key type and enctype fields, and both were recorded. At present we record + * the enctype field twice when writing the version 3 format and ignore the + * second value when reading it. + */ + +#include "cc-int.h" +#include "k5-input.h" + +/* Read a 16-bit integer in host byte order for versions 1 and 2, or in + * big-endian byte order for later versions.*/ +static uint16_t +get16(struct k5input *in, int version) +{ + return (version < 3) ? k5_input_get_uint16_n(in) : + k5_input_get_uint16_be(in); +} + +/* Read a 32-bit integer in host byte order for versions 1 and 2, or in + * big-endian byte order for later versions.*/ +static uint32_t +get32(struct k5input *in, int version) +{ + return (version < 3) ? k5_input_get_uint32_n(in) : + k5_input_get_uint32_be(in); +} + +/* Read a 32-bit length and make a copy of that many bytes. Return NULL on + * error. */ +static void * +get_len_bytes(struct k5input *in, int version, unsigned int *len_out) +{ + krb5_error_code ret; + unsigned int len = get32(in, version); + const void *bytes = k5_input_get_bytes(in, len); + void *copy; + + *len_out = 0; + if (bytes == NULL) + return NULL; + copy = k5memdup0(bytes, len, &ret); + if (copy == NULL) { + k5_input_set_status(in, ret); + return NULL; + } + *len_out = len; + return copy; +} + +/* Like get_len_bytes, but put the result in data. */ +static void +get_data(struct k5input *in, int version, krb5_data *data) +{ + unsigned int len; + void *bytes = get_len_bytes(in, version, &len); + + *data = (bytes == NULL) ? empty_data() : make_data(bytes, len); +} + +static krb5_principal +unmarshal_princ(struct k5input *in, int version) +{ + krb5_error_code ret; + krb5_principal princ; + uint32_t i, ncomps; + + princ = k5alloc(sizeof(krb5_principal_data), &ret); + if (princ == NULL) { + k5_input_set_status(in, ret); + return NULL; + } + princ->magic = KV5M_PRINCIPAL; + /* Version 1 does not store the principal name type, and counts the realm + * in the number of components. */ + princ->type = (version == 1) ? KRB5_NT_UNKNOWN : get32(in, version); + ncomps = get32(in, version); + if (version == 1) + ncomps--; + if (ncomps > in->len) { /* Sanity check to avoid large allocations */ + ret = EINVAL; + goto error; + } + if (ncomps != 0) { + princ->data = k5calloc(ncomps, sizeof(krb5_data), &ret); + if (princ->data == NULL) + goto error; + princ->length = ncomps; + } + get_data(in, version, &princ->realm); + for (i = 0; i < ncomps; i++) + get_data(in, version, &princ->data[i]); + return princ; + +error: + k5_input_set_status(in, ret); + krb5_free_principal(NULL, princ); + return NULL; +} + +static void +unmarshal_keyblock(struct k5input *in, int version, krb5_keyblock *kb) +{ + memset(kb, 0, sizeof(*kb)); + kb->magic = KV5M_KEYBLOCK; + /* enctypes can be negative, so sign-extend the 16-bit result. */ + kb->enctype = (int16_t)get16(in, version); + /* Version 3 stores the enctype twice. */ + if (version == 3) + (void)get16(in, version); + kb->contents = get_len_bytes(in, version, &kb->length); +} + +static krb5_address * +unmarshal_addr(struct k5input *in, int version) +{ + krb5_address *addr; + + addr = calloc(1, sizeof(*addr)); + if (addr == NULL) { + k5_input_set_status(in, ENOMEM); + return NULL; + } + addr->magic = KV5M_ADDRESS; + addr->addrtype = get16(in, version); + addr->contents = get_len_bytes(in, version, &addr->length); + return addr; +} + +static krb5_address ** +unmarshal_addrs(struct k5input *in, int version) +{ + krb5_address **addrs; + size_t i, count; + + count = get32(in, version); + if (count > in->len) { /* Sanity check to avoid large allocations */ + k5_input_set_status(in, EINVAL); + return NULL; + } + addrs = calloc(count + 1, sizeof(*addrs)); + if (addrs == NULL) { + k5_input_set_status(in, ENOMEM); + return NULL; + } + for (i = 0; i < count; i++) + addrs[i] = unmarshal_addr(in, version); + return addrs; +} + +static krb5_authdata * +unmarshal_authdatum(struct k5input *in, int version) +{ + krb5_authdata *ad; + + ad = calloc(1, sizeof(*ad)); + if (ad == NULL) { + k5_input_set_status(in, ENOMEM); + return NULL; + } + ad->magic = KV5M_ADDRESS; + /* Authdata types can be negative, so sign-extend the get16 result. */ + ad->ad_type = (int16_t)get16(in, version); + ad->contents = get_len_bytes(in, version, &ad->length); + return ad; +} + +static krb5_authdata ** +unmarshal_authdata(struct k5input *in, int version) +{ + krb5_authdata **authdata; + size_t i, count; + + count = get32(in, version); + if (count > in->len) { /* Sanity check to avoid large allocations */ + k5_input_set_status(in, EINVAL); + return NULL; + } + authdata = calloc(count + 1, sizeof(*authdata)); + if (authdata == NULL) { + k5_input_set_status(in, ENOMEM); + return NULL; + } + for (i = 0; i < count; i++) + authdata[i] = unmarshal_authdatum(in, version); + return authdata; +} + +/* Unmarshal a credential using the specified file ccache version (expressed as + * an integer from 1 to 4). Does not check for trailing garbage. */ +krb5_error_code +k5_unmarshal_cred(const unsigned char *data, size_t len, int version, + krb5_creds *creds) +{ + struct k5input in; + + k5_input_init(&in, data, len); + creds->client = unmarshal_princ(&in, version); + creds->server = unmarshal_princ(&in, version); + unmarshal_keyblock(&in, version, &creds->keyblock); + creds->times.authtime = get32(&in, version); + creds->times.starttime = get32(&in, version); + creds->times.endtime = get32(&in, version); + creds->times.renew_till = get32(&in, version); + creds->is_skey = k5_input_get_byte(&in); + creds->ticket_flags = get32(&in, version); + creds->addresses = unmarshal_addrs(&in, version); + creds->authdata = unmarshal_authdata(&in, version); + get_data(&in, version, &creds->ticket); + get_data(&in, version, &creds->second_ticket); + if (in.status) { + krb5_free_cred_contents(NULL, creds); + memset(creds, 0, sizeof(*creds)); + } + return (in.status == EINVAL) ? KRB5_CC_FORMAT : in.status; +} + +/* Unmarshal a principal using the specified file ccache version (expressed as + * an integer from 1 to 4). Does not check for trailing garbage. */ +krb5_error_code +k5_unmarshal_princ(const unsigned char *data, size_t len, int version, + krb5_principal *princ_out) +{ + struct k5input in; + krb5_principal princ; + + *princ_out = NULL; + k5_input_init(&in, data, len); + princ = unmarshal_princ(&in, version); + if (in.status) + krb5_free_principal(NULL, princ); + else + *princ_out = princ; + return (in.status == EINVAL) ? KRB5_CC_FORMAT : in.status; +} + +/* Store a 16-bit integer in host byte order for versions 1 and 2, or in + * big-endian byte order for later versions.*/ +static void +put16(struct k5buf *buf, int version, uint16_t num) +{ + char n[2]; + + if (version < 3) + store_16_n(num, n); + else + store_16_be(num, n); + k5_buf_add_len(buf, n, 2); +} + +/* Store a 32-bit integer in host byte order for versions 1 and 2, or in + * big-endian byte order for later versions.*/ +static void +put32(struct k5buf *buf, int version, uint32_t num) +{ + char n[4]; + + if (version < 3) + store_32_n(num, n); + else + store_32_be(num, n); + k5_buf_add_len(buf, n, 4); +} + +static void +put_len_bytes(struct k5buf *buf, int version, const void *bytes, + unsigned int len) +{ + put32(buf, version, len); + k5_buf_add_len(buf, bytes, len); +} + +static void +put_data(struct k5buf *buf, int version, krb5_data *data) +{ + put_len_bytes(buf, version, data->data, data->length); +} + +void +k5_marshal_princ(struct k5buf *buf, int version, krb5_principal princ) +{ + int32_t i, ncomps; + + /* Version 1 does not store the principal name type, and counts the realm + * in the number of components. */ + if (version != 1) + put32(buf, version, princ->type); + ncomps = princ->length + ((version == 1) ? 1 : 0); + put32(buf, version, ncomps); + put_data(buf, version, &princ->realm); + for (i = 0; i < princ->length; i++) + put_data(buf, version, &princ->data[i]); +} + +static void +marshal_keyblock(struct k5buf *buf, int version, krb5_keyblock *kb) +{ + put16(buf, version, kb->enctype); + /* Version 3 stores the enctype twice. */ + if (version == 3) + put16(buf, version, kb->enctype); + put_len_bytes(buf, version, kb->contents, kb->length); +} + +static void +marshal_addrs(struct k5buf *buf, int version, krb5_address **addrs) +{ + size_t i, count; + + for (count = 0; addrs != NULL && addrs[count] != NULL; count++); + put32(buf, version, count); + for (i = 0; i < count; i++) { + put16(buf, version, addrs[i]->addrtype); + put_len_bytes(buf, version, addrs[i]->contents, addrs[i]->length); + } +} + +static void +marshal_authdata(struct k5buf *buf, int version, krb5_authdata **authdata) +{ + size_t i, count; + + for (count = 0; authdata != NULL && authdata[count] != NULL; count++); + put32(buf, version, count); + for (i = 0; i < count; i++) { + put16(buf, version, authdata[i]->ad_type); + put_len_bytes(buf, version, authdata[i]->contents, + authdata[i]->length); + } +} + +/* Marshal a credential using the specified file ccache version (expressed as + * an integer from 1 to 4). */ +void +k5_marshal_cred(struct k5buf *buf, int version, krb5_creds *creds) +{ + char is_skey; + + k5_marshal_princ(buf, version, creds->client); + k5_marshal_princ(buf, version, creds->server); + marshal_keyblock(buf, version, &creds->keyblock); + put32(buf, version, creds->times.authtime); + put32(buf, version, creds->times.starttime); + put32(buf, version, creds->times.endtime); + put32(buf, version, creds->times.renew_till); + is_skey = creds->is_skey; + k5_buf_add_len(buf, &is_skey, 1); + put32(buf, version, creds->ticket_flags); + marshal_addrs(buf, version, creds->addresses); + marshal_authdata(buf, version, creds->authdata); + put_data(buf, version, &creds->ticket); + put_data(buf, version, &creds->second_ticket); +} + +#define SC_CLIENT_PRINCIPAL 0x0001 +#define SC_SERVER_PRINCIPAL 0x0002 +#define SC_SESSION_KEY 0x0004 +#define SC_TICKET 0x0008 +#define SC_SECOND_TICKET 0x0010 +#define SC_AUTHDATA 0x0020 +#define SC_ADDRESSES 0x0040 + +/* Construct the header flags field for a matching credential for the Heimdal + * KCM format. */ +static uint32_t +mcred_header(krb5_creds *mcred) +{ + uint32_t header = 0; + + if (mcred->client != NULL) + header |= SC_CLIENT_PRINCIPAL; + if (mcred->server != NULL) + header |= SC_SERVER_PRINCIPAL; + if (mcred->keyblock.enctype != ENCTYPE_NULL) + header |= SC_SESSION_KEY; + if (mcred->ticket.length > 0) + header |= SC_TICKET; + if (mcred->second_ticket.length > 0) + header |= SC_SECOND_TICKET; + if (mcred->authdata != NULL && *mcred->authdata != NULL) + header |= SC_AUTHDATA; + if (mcred->addresses != NULL && *mcred->addresses != NULL) + header |= SC_ADDRESSES; + return header; +} + +/* + * Marshal a matching credential in the Heimdal KCM format. Matching + * credentials are used to identify an existing credential to retrieve or + * remove from a cache. + */ +void +k5_marshal_mcred(struct k5buf *buf, krb5_creds *mcred) +{ + const int version = 4; /* subfields use v4 file format */ + uint32_t header; + char is_skey; + + header = mcred_header(mcred); + put32(buf, version, header); + if (mcred->client != NULL) + k5_marshal_princ(buf, version, mcred->client); + if (mcred->server != NULL) + k5_marshal_princ(buf, version, mcred->server); + if (mcred->keyblock.enctype != ENCTYPE_NULL) + marshal_keyblock(buf, version, &mcred->keyblock); + put32(buf, version, mcred->times.authtime); + put32(buf, version, mcred->times.starttime); + put32(buf, version, mcred->times.endtime); + put32(buf, version, mcred->times.renew_till); + is_skey = mcred->is_skey; + k5_buf_add_len(buf, &is_skey, 1); + put32(buf, version, mcred->ticket_flags); + if (mcred->addresses != NULL && *mcred->addresses != NULL) + marshal_addrs(buf, version, mcred->addresses); + if (mcred->authdata != NULL && *mcred->authdata != NULL) + marshal_authdata(buf, version, mcred->authdata); + if (mcred->ticket.length > 0) + put_data(buf, version, &mcred->ticket); + if (mcred->second_ticket.length > 0) + put_data(buf, version, &mcred->second_ticket); +} + +krb5_error_code KRB5_CALLCONV +krb5_marshal_credentials(krb5_context context, krb5_creds *in_creds, + krb5_data **data_out) +{ + krb5_error_code ret; + krb5_data *data; + struct k5buf buf; + + *data_out = NULL; + + data = k5alloc(sizeof(krb5_data), &ret); + if (ret) + return ret; + + k5_buf_init_dynamic(&buf); + k5_marshal_cred(&buf, 4, in_creds); + + ret = k5_buf_status(&buf); + if (ret) { + free(data); + return ret; + } + + /* Steal payload from buf. */ + *data = make_data(buf.data, buf.len); + *data_out = data; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_unmarshal_credentials(krb5_context context, const krb5_data *data, + krb5_creds **creds_out) +{ + krb5_error_code ret; + krb5_creds *creds; + + *creds_out = NULL; + + creds = k5alloc(sizeof(krb5_creds), &ret); + if (ret) + return ret; + + ret = k5_unmarshal_cred((unsigned char *)data->data, data->length, 4, + creds); + if (ret) { + free(creds); + return ret; + } + + *creds_out = creds; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccselect.c b/krb5-1.21.3/src/lib/krb5/ccache/ccselect.c new file mode 100644 index 00000000..dee4c461 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccselect.c @@ -0,0 +1,204 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/ccselect.c - krb5_cc_select API and module loader */ +/* + * Copyright (C) 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "cc-int.h" +#include +#include "../krb/int-proto.h" + +struct ccselect_module_handle { + struct krb5_ccselect_vtable_st vt; + krb5_ccselect_moddata data; + int priority; +}; + +static void +free_handles(krb5_context context, struct ccselect_module_handle **handles) +{ + struct ccselect_module_handle *h, **hp; + + if (handles == NULL) + return; + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.fini) + h->vt.fini(context, h->data); + free(h); + } + free(handles); +} + +static krb5_error_code +load_modules(krb5_context context) +{ + krb5_error_code ret; + struct ccselect_module_handle **list = NULL, *handle; + krb5_plugin_initvt_fn *modules = NULL, *mod; + size_t count; + +#ifndef _WIN32 + ret = k5_plugin_register(context, PLUGIN_INTERFACE_CCSELECT, "k5identity", + ccselect_k5identity_initvt); + if (ret != 0) + goto cleanup; +#endif + + ret = k5_plugin_register(context, PLUGIN_INTERFACE_CCSELECT, "realm", + ccselect_realm_initvt); + if (ret != 0) + goto cleanup; + + ret = k5_plugin_register(context, PLUGIN_INTERFACE_CCSELECT, "hostname", + ccselect_hostname_initvt); + if (ret != 0) + goto cleanup; + + ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_CCSELECT, &modules); + if (ret != 0) + goto cleanup; + + /* Allocate a large enough list of handles. */ + for (count = 0; modules[count] != NULL; count++); + list = k5calloc(count + 1, sizeof(*list), &ret); + if (list == NULL) + goto cleanup; + + /* Initialize each module, ignoring ones that fail. */ + count = 0; + for (mod = modules; *mod != NULL; mod++) { + handle = k5alloc(sizeof(*handle), &ret); + if (handle == NULL) + goto cleanup; + ret = (*mod)(context, 1, 1, (krb5_plugin_vtable)&handle->vt); + if (ret != 0) { /* Failed vtable init is non-fatal. */ + TRACE_CCSELECT_VTINIT_FAIL(context, ret); + free(handle); + continue; + } + handle->data = NULL; + ret = handle->vt.init(context, &handle->data, &handle->priority); + if (ret != 0) { /* Failed initialization is non-fatal. */ + TRACE_CCSELECT_INIT_FAIL(context, handle->vt.name, ret); + free(handle); + continue; + } + list[count++] = handle; + list[count] = NULL; + } + list[count] = NULL; + + ret = 0; + context->ccselect_handles = list; + list = NULL; + +cleanup: + k5_plugin_free_modules(context, modules); + free_handles(context, list); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_cc_select(krb5_context context, krb5_principal server, + krb5_ccache *cache_out, krb5_principal *princ_out) +{ + krb5_error_code ret; + int priority; + struct ccselect_module_handle **hp, *h; + krb5_ccache cache; + krb5_principal princ; + krb5_principal srvcp = NULL; + char **fbrealms = NULL; + + *cache_out = NULL; + *princ_out = NULL; + + if (context->ccselect_handles == NULL) { + ret = load_modules(context); + if (ret) + goto cleanup; + } + + /* Try to use the fallback host realm for the server if there is no + * authoritative realm. */ + if (krb5_is_referral_realm(&server->realm) && + server->type == KRB5_NT_SRV_HST && server->length == 2) { + ret = krb5_get_fallback_host_realm(context, &server->data[1], + &fbrealms); + /* Continue without realm if we failed due to no default realm. */ + if (ret && ret != KRB5_CONFIG_NODEFREALM) + goto cleanup; + if (!ret) { + /* Make a copy with the first fallback realm. */ + ret = krb5_copy_principal(context, server, &srvcp); + if (ret) + goto cleanup; + ret = krb5_set_principal_realm(context, srvcp, fbrealms[0]); + if (ret) + goto cleanup; + server = srvcp; + } + } + + /* Consult authoritative modules first, then heuristic ones. */ + for (priority = KRB5_CCSELECT_PRIORITY_AUTHORITATIVE; + priority >= KRB5_CCSELECT_PRIORITY_HEURISTIC; priority--) { + for (hp = context->ccselect_handles; *hp != NULL; hp++) { + h = *hp; + if (h->priority != priority) + continue; + ret = h->vt.choose(context, h->data, server, &cache, &princ); + if (ret == 0) { + TRACE_CCSELECT_MODCHOICE(context, h->vt.name, server, cache, + princ); + *cache_out = cache; + *princ_out = princ; + goto cleanup; + } else if (ret == KRB5_CC_NOTFOUND) { + TRACE_CCSELECT_MODNOTFOUND(context, h->vt.name, server, princ); + *princ_out = princ; + goto cleanup; + } else if (ret != KRB5_PLUGIN_NO_HANDLE) { + TRACE_CCSELECT_MODFAIL(context, h->vt.name, ret, server); + goto cleanup; + } + } + } + + TRACE_CCSELECT_NOTFOUND(context, server); + ret = KRB5_CC_NOTFOUND; + +cleanup: + krb5_free_principal(context, srvcp); + krb5_free_host_realm(context, fbrealms); + return ret; +} + +void +k5_ccselect_free_context(krb5_context context) +{ + free_handles(context, context->ccselect_handles); + context->ccselect_handles = NULL; +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccselect_hostname.c b/krb5-1.21.3/src/lib/krb5/ccache/ccselect_hostname.c new file mode 100644 index 00000000..475cfaba --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccselect_hostname.c @@ -0,0 +1,146 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/ccselect_hostname.c - hostname ccselect module */ +/* + * Copyright (C) 2017 by Red Hat, Inc. + * 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. + */ + +#include "k5-int.h" +#include "cc-int.h" +#include +#include + +/* Swap a and b, using tmp as an intermediate. */ +#define SWAP(a, b, tmp) \ + tmp = a; \ + a = b; \ + b = tmp; + +static krb5_error_code +hostname_init(krb5_context context, krb5_ccselect_moddata *data_out, + int *priority_out) +{ + *data_out = NULL; + *priority_out = KRB5_CCSELECT_PRIORITY_HEURISTIC; + return 0; +} + +static krb5_error_code +hostname_choose(krb5_context context, krb5_ccselect_moddata data, + krb5_principal server, krb5_ccache *ccache_out, + krb5_principal *princ_out) +{ + krb5_error_code ret; + char *p, *host = NULL; + size_t hostlen; + krb5_cccol_cursor col_cursor; + krb5_ccache ccache, tmp_ccache, best_ccache = NULL; + krb5_principal princ, tmp_princ, best_princ = NULL; + krb5_data domain; + + *ccache_out = NULL; + *princ_out = NULL; + + if (server->type != KRB5_NT_SRV_HST || server->length < 2) + return KRB5_PLUGIN_NO_HANDLE; + + /* Compute upper-case hostname. */ + hostlen = server->data[1].length; + host = k5memdup0(server->data[1].data, hostlen, &ret); + if (host == NULL) + return ret; + for (p = host; *p != '\0'; p++) { + if (islower(*p)) + *p = toupper(*p); + } + + /* Scan the collection for a cache with a client principal whose realm is + * the longest tail of the server hostname. */ + ret = krb5_cccol_cursor_new(context, &col_cursor); + if (ret) + goto done; + + for (ret = krb5_cccol_cursor_next(context, col_cursor, &ccache); + ret == 0 && ccache != NULL; + ret = krb5_cccol_cursor_next(context, col_cursor, &ccache)) { + ret = krb5_cc_get_principal(context, ccache, &princ); + if (ret) { + krb5_cc_close(context, ccache); + break; + } + + /* Check for a longer match than we have. */ + domain = make_data(host, hostlen); + while (best_princ == NULL || + best_princ->realm.length < domain.length) { + if (data_eq(princ->realm, domain)) { + SWAP(best_ccache, ccache, tmp_ccache); + SWAP(best_princ, princ, tmp_princ); + break; + } + + /* Try the next parent domain. */ + p = memchr(domain.data, '.', domain.length); + if (p == NULL) + break; + domain = make_data(p + 1, hostlen - (p + 1 - host)); + } + + if (ccache != NULL) + krb5_cc_close(context, ccache); + krb5_free_principal(context, princ); + } + + krb5_cccol_cursor_free(context, &col_cursor); + + if (best_ccache != NULL) { + *ccache_out = best_ccache; + *princ_out = best_princ; + } else { + ret = KRB5_PLUGIN_NO_HANDLE; + } + +done: + free(host); + return ret; +} + +krb5_error_code +ccselect_hostname_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_ccselect_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_ccselect_vtable)vtable; + vt->name = "hostname"; + vt->init = hostname_init; + vt->choose = hostname_choose; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccselect_k5identity.c b/krb5-1.21.3/src/lib/krb5/ccache/ccselect_k5identity.c new file mode 100644 index 00000000..b2dbf8a0 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccselect_k5identity.c @@ -0,0 +1,210 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/ccselect_k5identity.c - k5identity ccselect module */ +/* + * Copyright (C) 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "cc-int.h" +#include +#include + +#ifndef _WIN32 + +#include + +static krb5_error_code +k5identity_init(krb5_context context, krb5_ccselect_moddata *data_out, + int *priority_out) +{ + *data_out = NULL; + *priority_out = KRB5_CCSELECT_PRIORITY_AUTHORITATIVE; + return 0; +} + +/* Match data (folded to lowercase if fold_case is set) against pattern. */ +static krb5_boolean +fnmatch_data(const char *pattern, krb5_data *data, krb5_boolean fold_case) +{ + krb5_error_code ret; + char *str, *p; + int res; + + str = k5memdup0(data->data, data->length, &ret); + if (str == NULL) + return FALSE; + + if (fold_case) { + for (p = str; *p != '\0'; p++) { + if (isupper((unsigned char)*p)) + *p = tolower((unsigned char)*p); + } + } + + res = fnmatch(pattern, str, 0); + free(str); + return (res == 0); +} + +/* Return true if server satisfies the constraint given by name and value. */ +static krb5_boolean +check_constraint(krb5_context context, const char *name, const char *value, + krb5_principal server) +{ + if (strcmp(name, "realm") == 0) { + return fnmatch_data(value, &server->realm, FALSE); + } else if (strcmp(name, "service") == 0) { + return (server->type == KRB5_NT_SRV_HST && server->length >= 2 && + fnmatch_data(value, &server->data[0], FALSE)); + } else if (strcmp(name, "host") == 0) { + return (server->type == KRB5_NT_SRV_HST && server->length >= 2 && + fnmatch_data(value, &server->data[1], TRUE)); + } + /* Assume unrecognized constraints are critical. */ + return FALSE; +} + +/* + * If line begins with a valid principal and server matches the constraints + * listed afterwards, set *princ_out to the client principal described in line + * and return true. Otherwise return false. May destructively affect line. + */ +static krb5_boolean +parse_line(krb5_context context, char *line, krb5_principal server, + krb5_principal *princ_out) +{ + const char *whitespace = " \t\r\n"; + char *princ, *princ_end, *field, *field_end, *sep; + + *princ_out = NULL; + + /* Find the bounds of the principal. */ + princ = line + strspn(line, whitespace); + if (*princ == '#') + return FALSE; + princ_end = princ + strcspn(princ, whitespace); + if (princ_end == princ) + return FALSE; + + /* Check all constraints. */ + field = princ_end + strspn(princ_end, whitespace); + while (*field != '\0') { + field_end = field + strcspn(field, whitespace); + if (*field_end != '\0') + *field_end++ = '\0'; + sep = strchr(field, '='); + if (sep == NULL) /* Malformed line. */ + return FALSE; + *sep = '\0'; + if (!check_constraint(context, field, sep + 1, server)) + return FALSE; + field = field_end + strspn(field_end, whitespace); + } + + *princ_end = '\0'; + return (krb5_parse_name(context, princ, princ_out) == 0); +} + +/* Determine the current user's homedir. Allow HOME to override the result for + * non-secure profiles; otherwise, use the euid's homedir from passwd. */ +static char * +get_homedir(krb5_context context) +{ + const char *homedir = NULL; + char pwbuf[BUFSIZ]; + struct passwd pwx, *pwd; + + if (!context->profile_secure) + homedir = secure_getenv("HOME"); + + if (homedir == NULL) { + if (k5_getpwuid_r(geteuid(), &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0) + return NULL; + homedir = pwd->pw_dir; + } + + return strdup(homedir); +} + +static krb5_error_code +k5identity_choose(krb5_context context, krb5_ccselect_moddata data, + krb5_principal server, krb5_ccache *cache_out, + krb5_principal *princ_out) +{ + krb5_error_code ret; + krb5_principal princ = NULL; + char *filename, *homedir; + FILE *fp; + char buf[256]; + + *cache_out = NULL; + *princ_out = NULL; + + /* Open the .k5identity file. */ + homedir = get_homedir(context); + if (homedir == NULL) + return KRB5_PLUGIN_NO_HANDLE; + ret = k5_path_join(homedir, ".k5identity", &filename); + free(homedir); + if (ret) + return ret; + fp = fopen(filename, "r"); + free(filename); + if (fp == NULL) + return KRB5_PLUGIN_NO_HANDLE; + + /* Look for a line with constraints matched by server. */ + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (parse_line(context, buf, server, &princ)) + break; + } + fclose(fp); + if (princ == NULL) + return KRB5_PLUGIN_NO_HANDLE; + + /* Look for a ccache with the appropriate client principal. If we don't + * find out, set *princ_out to indicate the desired client principal. */ + ret = krb5_cc_cache_match(context, princ, cache_out); + if (ret == 0 || ret == KRB5_CC_NOTFOUND) + *princ_out = princ; + else + krb5_free_principal(context, princ); + return ret; +} + +krb5_error_code +ccselect_k5identity_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_ccselect_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_ccselect_vtable)vtable; + vt->name = "k5identity"; + vt->init = k5identity_init; + vt->choose = k5identity_choose; + return 0; +} + +#endif /* not _WIN32 */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/ccselect_realm.c b/krb5-1.21.3/src/lib/krb5/ccache/ccselect_realm.c new file mode 100644 index 00000000..3a4b4af1 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/ccselect_realm.c @@ -0,0 +1,95 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/ccselect_realm.c - realm ccselect module */ +/* + * Copyright (C) 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "cc-int.h" +#include + +static krb5_error_code +realm_init(krb5_context context, krb5_ccselect_moddata *data_out, + int *priority_out) +{ + *data_out = NULL; + *priority_out = KRB5_CCSELECT_PRIORITY_HEURISTIC; + return 0; +} + +static krb5_error_code +realm_choose(krb5_context context, krb5_ccselect_moddata data, + krb5_principal server, krb5_ccache *cache_out, + krb5_principal *princ_out) +{ + krb5_error_code ret; + krb5_cccol_cursor cursor; + krb5_ccache cache; + krb5_principal princ; + + *cache_out = NULL; + *princ_out = NULL; + + if (krb5_is_referral_realm(&server->realm)) + return KRB5_PLUGIN_NO_HANDLE; + + /* Scan the collection for a cache with a client principal in the same + * realm as the server principal. */ + ret = krb5_cccol_cursor_new(context, &cursor); + if (ret) + return ret; + while ((ret = krb5_cccol_cursor_next(context, cursor, &cache)) == 0 && + cache != NULL) { + ret = krb5_cc_get_principal(context, cache, &princ); + if (ret == 0) { + if (data_eq(princ->realm, server->realm)) + break; + krb5_free_principal(context, princ); + } + krb5_cc_close(context, cache); + } + krb5_cccol_cursor_free(context, &cursor); + if (ret) + return ret; + + if (cache == NULL) + return KRB5_PLUGIN_NO_HANDLE; + *cache_out = cache; + *princ_out = princ; + return 0; +} + +krb5_error_code +ccselect_realm_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_ccselect_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_ccselect_vtable)vtable; + vt->name = "realm"; + vt->init = realm_init; + vt->choose = realm_choose; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/deps b/krb5-1.21.3/src/lib/krb5/ccache/deps new file mode 100644 index 00000000..6429e928 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/deps @@ -0,0 +1,249 @@ +# +# Generated makefile dependencies follow. +# +ccapi_util.so ccapi_util.po $(OUTPRE)ccapi_util.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cc-int.h ccapi_util.c ccapi_util.h +ccbase.so ccbase.po $(OUTPRE)ccbase.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cc-int.h ccbase.c \ + fcc.h +cccopy.so cccopy.po $(OUTPRE)cccopy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cccopy.c +cccursor.so cccursor.po $(OUTPRE)cccursor.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../krb/int-proto.h $(srcdir)/../os/os-proto.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cc-int.h cccursor.c +ccdefault.so ccdefault.po $(OUTPRE)ccdefault.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ccdefault.c +ccdefops.so ccdefops.po $(OUTPRE)ccdefops.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ccdefops.c fcc.h +ccmarshal.so ccmarshal.po $(OUTPRE)ccmarshal.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-input.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cc-int.h ccmarshal.c +ccselect.so ccselect.po $(OUTPRE)ccselect.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../krb/int-proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/ccselect_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cc-int.h ccselect.c +ccselect_hostname.so ccselect_hostname.po $(OUTPRE)ccselect_hostname.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/ccselect_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cc-int.h ccselect_hostname.c +ccselect_k5identity.so ccselect_k5identity.po $(OUTPRE)ccselect_k5identity.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/ccselect_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cc-int.h ccselect_k5identity.c +ccselect_realm.so ccselect_realm.po $(OUTPRE)ccselect_realm.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/ccselect_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cc-int.h ccselect_realm.c +cc_api_macos.so cc_api_macos.po $(OUTPRE)cc_api_macos.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/CredentialsCache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cc-int.h cc_api_macos.c ccapi_util.h +cc_dir.so cc_dir.po $(OUTPRE)cc_dir.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cc-int.h cc_dir.c +cc_retr.so cc_retr.po $(OUTPRE)cc_retr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/int-proto.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cc-int.h cc_retr.c +cc_file.so cc_file.po $(OUTPRE)cc_file.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cc-int.h cc_file.c +cc_kcm.so cc_kcm.po $(OUTPRE)cc_kcm.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-input.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kcm.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cc-int.h cc_kcm.c +cc_memory.so cc_memory.po $(OUTPRE)cc_memory.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../krb/int-proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-hashtab.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cc-int.h cc_memory.c +cc_keyring.so cc_keyring.po $(OUTPRE)cc_keyring.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cc-int.h cc_keyring.c +ccfns.so ccfns.po $(OUTPRE)ccfns.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/int-proto.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cc-int.h ccfns.c +t_cc.so t_cc.po $(OUTPRE)t_cc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h cc-int.h t_cc.c +t_cccol.so t_cccol.po $(OUTPRE)t_cccol.$(OBJEXT): $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h t_cccol.c +t_cccursor.so t_cccursor.po $(OUTPRE)t_cccursor.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_cccursor.c +t_marshal.so t_marshal.po $(OUTPRE)t_marshal.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cc-int.h t_marshal.c diff --git a/krb5-1.21.3/src/lib/krb5/ccache/fcc.h b/krb5-1.21.3/src/lib/krb5/ccache/fcc.h new file mode 100644 index 00000000..b31c3a7a --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/fcc.h @@ -0,0 +1,41 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/fcc.h */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * This file contains constant and function declarations used in the + * file-based credential cache routines. + */ + +#ifndef __KRB5_FILE_CCACHE__ +#define __KRB5_FILE_CCACHE__ + +extern const krb5_cc_ops krb5_cc_file_ops; + +krb5_error_code krb5int_fcc_new_unique(krb5_context context, char *template, + krb5_ccache *id); + +#endif /* __KRB5_FILE_CCACHE__ */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/kcmrpc.defs b/krb5-1.21.3/src/lib/krb5/ccache/kcmrpc.defs new file mode 100644 index 00000000..997bae6d --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/kcmrpc.defs @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2009 Kungliga Tekniska Hgskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. 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 +#include + +type k5_kcm_inband_msg = array [ * : 2048 ] of char; +type k5_kcm_outband_msg = array [] of char; + +import "kcmrpc_types.h"; + +subsystem mheim_ipc 1; +userprefix k5_kcmrpc_; +serverprefix k5_kcmrpc_server_; + +routine call( + server_port : mach_port_t; + ServerAuditToken client_creds : audit_token_t; + sreplyport reply_port : mach_port_make_send_once_t; + in requestin : k5_kcm_inband_msg; + in requestout : k5_kcm_outband_msg; + out returnvalue : int; + out replyin : k5_kcm_inband_msg; + out replyout : k5_kcm_outband_msg, dealloc); diff --git a/krb5-1.21.3/src/lib/krb5/ccache/kcmrpc_types.h b/krb5-1.21.3/src/lib/krb5/ccache/kcmrpc_types.h new file mode 100644 index 00000000..f43b41e5 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/kcmrpc_types.h @@ -0,0 +1,39 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/kcmrpc_types.h - KCM RPC type definitions */ +/* + * Copyright (C) 2014 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. + */ + +#ifndef KCMRPC_H +#define KCMRPC_H + +typedef char k5_kcm_inband_msg[2048]; +typedef char *k5_kcm_outband_msg; + +#endif diff --git a/krb5-1.21.3/src/lib/krb5/ccache/scc.h b/krb5-1.21.3/src/lib/krb5/ccache/scc.h new file mode 100644 index 00000000..6c23614b --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/scc.h @@ -0,0 +1,88 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/scc.h */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * This file contains constant and function declarations used in the + * file-based credential cache routines. + */ + +#ifndef __KRB5_FILE_CCACHE__ +#define __KRB5_FILE_CCACHE__ + +#include "k5-int.h" +#include + +#define KRB5_OK 0 + +#define KRB5_SCC_MAXLEN 100 + +/* + * SCC version 2 contains type information for principals. SCC + * version 1 does not. The code will accept either, and depending on + * what KRB5_SCC_DEFAULT_FVNO is set to, it will create version 1 or + * version 2 SCC caches. + * + */ + +#define KRB5_SCC_FVNO_1 0x0501 /* krb v5, scc v1 */ +#define KRB5_SCC_FVNO_2 0x0502 /* krb v5, scc v2 */ +#define KRB5_SCC_FVNO_3 0x0503 /* krb v5, scc v3 */ +#define KRB5_SCC_FVNO_4 0x0504 /* krb v5, scc v4 */ + +#define SCC_OPEN_AND_ERASE 1 +#define SCC_OPEN_RDWR 2 +#define SCC_OPEN_RDONLY 3 + +/* Credential file header tags. + * The header tags are constructed as: + * krb5_ui_2 tag + * krb5_ui_2 len + * krb5_octet data[len] + * This format allows for older versions of the fcc processing code to skip + * past unrecognized tag formats. + */ +#define SCC_TAG_DELTATIME 1 + +#ifndef TKT_ROOT +#define TKT_ROOT "/tmp/tkt" +#endif + +typedef struct _krb5_scc_data { + char *filename; + FILE *file; + krb5_flags flags; + char stdio_buffer[BUFSIZ]; + int version; +} krb5_scc_data; + +/* An off_t can be arbitrarily complex */ +typedef struct _krb5_scc_cursor { + long pos; +} krb5_scc_cursor; + +/* DO NOT ADD ANYTHING AFTER THIS #endif */ +#endif /* __KRB5_FILE_CCACHE__ */ diff --git a/krb5-1.21.3/src/lib/krb5/ccache/t_cc.c b/krb5-1.21.3/src/lib/krb5/ccache/t_cc.c new file mode 100644 index 00000000..edd22094 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/t_cc.c @@ -0,0 +1,660 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/t_cc.c */ +/* + * Copyright 2000 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "cc-int.h" +#include +#include +#include "autoconf.h" +#ifdef HAVE_UNISTD_H +#include +#endif +#include "com_err.h" + +#define KRB5_OK 0 + +krb5_creds test_creds, test_creds2; + +int debug=0; + +static void +init_structs(void) +{ + static int add=0x12345; + + static krb5_address addr; + + static krb5_address *addrs[] = { + &addr, + 0, + }; + + addr.magic = KV5M_ADDRESS; + addr.addrtype = ADDRTYPE_INET; + addr.length = 4; + addr.contents = (krb5_octet *) &add; + + test_creds.magic = KV5M_CREDS; + test_creds.client = NULL; + test_creds.server = NULL; + + test_creds.keyblock.magic = KV5M_KEYBLOCK; + test_creds.keyblock.contents = 0; + test_creds.keyblock.enctype = 1; + test_creds.keyblock.length = 1; + test_creds.keyblock.contents = (unsigned char *) "1"; + test_creds.times.authtime = 1111; + test_creds.times.starttime = 2222; + test_creds.times.endtime = 3333; + test_creds.times.renew_till = 4444; + test_creds.is_skey = 1; + test_creds.ticket_flags = 5555; + test_creds.addresses = addrs; + +#define SET_TICKET(ent, str) {ent.magic = KV5M_DATA; ent.length = sizeof(str); ent.data = str;} + SET_TICKET(test_creds.ticket, "This is ticket 1"); + SET_TICKET(test_creds.second_ticket, "This is ticket 2"); + test_creds.authdata = NULL; +} + +static krb5_error_code +init_test_cred(krb5_context context) +{ + krb5_error_code kret; + unsigned int i; + krb5_authdata *a; +#define REALM "REALM" + kret = krb5_build_principal(context, &test_creds.client, sizeof(REALM), REALM, + "client-comp1", "client-comp2", NULL); + if(kret) + return kret; + + kret = krb5_build_principal(context, &test_creds.server, sizeof(REALM), REALM, + "server-comp1", "server-comp2", NULL); + if(kret) { + krb5_free_principal(context, test_creds.client); + test_creds.client = 0; + goto cleanup; + } + + test_creds.authdata = malloc (3 * sizeof(krb5_authdata *)); + if (!test_creds.authdata) { + kret = ENOMEM; + goto cleanup; + } + + for (i = 0 ; i <= 2 ; i++) { + test_creds.authdata[i] = 0; + } + a = (krb5_authdata *) malloc(sizeof(krb5_authdata)); + if(!a) { + kret = ENOMEM; + goto cleanup; + } + a->magic = KV5M_AUTHDATA; + a->ad_type = KRB5_AUTHDATA_IF_RELEVANT; + a->contents = (krb5_octet * ) malloc(1); + if(!a->contents) { + free(a); + kret = ENOMEM; + goto cleanup; + } + a->contents[0]=5; + a->length = 1; + test_creds.authdata[0] = a; + + a = (krb5_authdata *) malloc(sizeof(krb5_authdata)); + if(!a) { + kret = ENOMEM; + goto cleanup; + } + a->magic = KV5M_AUTHDATA; + a->ad_type = KRB5_AUTHDATA_KDC_ISSUED; + a->contents = (krb5_octet * ) malloc(2); + if(!a->contents) { + free(a); + kret = ENOMEM; + goto cleanup; + } + a->contents[0]=4; + a->contents[1]=6; + a->length = 2; + test_creds.authdata[1] = a; + + memcpy(&test_creds2, &test_creds, sizeof(test_creds)); + kret = krb5_build_principal(context, &test_creds2.server, sizeof(REALM), + REALM, "server-comp1", "server-comp3", NULL); + +cleanup: + if(kret) { + if (test_creds.client) { + krb5_free_principal(context, test_creds.client); + test_creds.client = 0; + } + if (test_creds.server) { + krb5_free_principal(context, test_creds.server); + test_creds.server = 0; + + } + if (test_creds.authdata) { + krb5_free_authdata(context, test_creds.authdata); + test_creds.authdata = 0; + } + } + + return kret; +} + +static void +free_test_cred(krb5_context context) +{ + krb5_free_principal(context, test_creds.client); + + krb5_free_principal(context, test_creds.server); + krb5_free_principal(context, test_creds2.server); + + if(test_creds.authdata) { + krb5_free_authdata(context, test_creds.authdata); + test_creds.authdata = 0; + } +} + +#define CHECK(kret,msg) \ + if (kret != KRB5_OK) { \ + com_err(msg, kret, ""); \ + fflush(stderr); \ + exit(1); \ + } else if(debug) printf("%s went ok\n", msg); + +#define CHECK_STR(str,msg) \ + if (str == 0) { \ + com_err(msg, kret, ""); \ + exit(1); \ + } else if(debug) printf("%s went ok\n", msg); + +#define CHECK_BOOL(expr,errstr,msg) \ + if (expr) { \ + fprintf(stderr, "%s %s\n", msg, errstr); \ + exit(1); \ + } else if(debug) printf("%s went ok\n", msg); + +#define CHECK_FAIL(experr, kret, msg) \ + if (experr != kret) { CHECK(kret, msg);} + +static void +check_num_entries(krb5_context context, krb5_ccache cache, int expected, + unsigned linenum) +{ + krb5_error_code ret; + krb5_cc_cursor cursor; + krb5_creds creds; + int count = 0; + + ret = krb5_cc_start_seq_get(context, cache, &cursor); + if (ret != 0) { + com_err("", ret, "(on line %d) - krb5_cc_start_seq_get", linenum); + fflush(stderr); + exit(1); + } + + while (1) { + ret = krb5_cc_next_cred(context, cache, &cursor, &creds); + if (ret) + break; + + count++; + krb5_free_cred_contents(context, &creds); + } + krb5_cc_end_seq_get(context, cache, &cursor); + if (ret != KRB5_CC_END) { + CHECK(ret, "counting entries in ccache"); + } + + if (count != expected) { + com_err("", KRB5_FCC_INTERNAL, + "(on line %d) - count didn't match (expected %d, got %d)", + linenum, expected, count); + fflush(stderr); + exit(1); + } +} + +static void +cc_test(krb5_context context, const char *name, krb5_flags flags) +{ + krb5_ccache id, id2; + krb5_creds creds; + krb5_error_code kret; + krb5_cc_cursor cursor; + krb5_principal tmp; + krb5_flags matchflags = KRB5_TC_MATCH_IS_SKEY; + + const char *c_name; + char newcache[300]; + char *save_type; + + kret = init_test_cred(context); + CHECK(kret, "init_creds"); + + kret = krb5_cc_resolve(context, name, &id); + CHECK(kret, "resolve"); + kret = krb5_cc_initialize(context, id, test_creds.client); + CHECK(kret, "initialize"); + + c_name = krb5_cc_get_name(context, id); + CHECK_STR(c_name, "get_name"); + + c_name = krb5_cc_get_type(context, id); + CHECK_STR(c_name, "get_type"); + save_type=strdup(c_name); + CHECK_STR(save_type, "copying type"); + + kret = krb5_cc_store_cred(context, id, &test_creds); + CHECK(kret, "store"); + + kret = krb5_cc_get_principal(context, id, &tmp); + CHECK(kret, "get_principal"); + + CHECK_BOOL(krb5_realm_compare(context, tmp, test_creds.client) != TRUE, + "realms do not match", "realm_compare"); + + + CHECK_BOOL(krb5_principal_compare(context, tmp, test_creds.client) != TRUE, + "principals do not match", "principal_compare"); + + krb5_free_principal(context, tmp); + + kret = krb5_cc_set_flags (context, id, flags); + CHECK(kret, "set_flags"); + + kret = krb5_cc_start_seq_get(context, id, &cursor); + CHECK(kret, "start_seq_get"); + kret = 0; + while (kret != KRB5_CC_END) { + if(debug) printf("Calling next_cred\n"); + kret = krb5_cc_next_cred(context, id, &cursor, &creds); + if(kret == KRB5_CC_END) { + if(debug) printf("next_cred: ok at end\n"); + } + else { + CHECK(kret, "next_cred"); + krb5_free_cred_contents(context, &creds); + } + + } + kret = krb5_cc_end_seq_get(context, id, &cursor); + CHECK(kret, "end_seq_get"); + + kret = krb5_cc_close(context, id); + CHECK(kret, "close"); + + + /* ------------------------------------------------- */ + kret = krb5_cc_resolve(context, name, &id); + CHECK(kret, "resolve2"); + + { + /* Copy the cache test*/ + snprintf(newcache, sizeof(newcache), "%s.new", name); + kret = krb5_cc_resolve(context, newcache, &id2); + CHECK(kret, "resolve of new cache"); + + /* This should fail as the new creds are not initialized */ + kret = krb5_cc_copy_creds(context, id, id2); + CHECK_FAIL(KRB5_FCC_NOFILE, kret, "copy_creds"); + + kret = krb5_cc_initialize(context, id2, test_creds.client); + CHECK(kret, "initialize of id2"); + + kret = krb5_cc_copy_creds(context, id, id2); + CHECK(kret, "copy_creds"); + + kret = krb5_cc_destroy(context, id2); + CHECK(kret, "destroy new cache"); + } + + /* Destroy the first cache */ + kret = krb5_cc_destroy(context, id); + CHECK(kret, "destroy"); + + /* ----------------------------------------------------- */ + /* Tests the generate new code */ + kret = krb5_cc_new_unique(context, save_type, + NULL, &id2); + CHECK(kret, "new_unique"); + + kret = krb5_cc_initialize(context, id2, test_creds.client); + CHECK(kret, "initialize"); + + kret = krb5_cc_store_cred(context, id2, &test_creds); + CHECK(kret, "store"); + + kret = krb5_cc_destroy(context, id2); + CHECK(kret, "destroy id2"); + + /* ----------------------------------------------------- */ + /* Test credential removal */ + kret = krb5_cc_resolve(context, name, &id); + CHECK(kret, "resolving for remove"); + + kret = krb5_cc_initialize(context, id, test_creds.client); + CHECK(kret, "initialize for remove"); + check_num_entries(context, id, 0, __LINE__); + + kret = krb5_cc_store_cred(context, id, &test_creds); + CHECK(kret, "store for remove (first pass)"); + check_num_entries(context, id, 1, __LINE__); /* 1 */ + + kret = krb5_cc_remove_cred(context, id, matchflags, &test_creds); + CHECK(kret, "removing credential (first pass)"); + check_num_entries(context, id, 0, __LINE__); /* empty */ + + kret = krb5_cc_store_cred(context, id, &test_creds); + CHECK(kret, "first store for remove (second pass)"); + check_num_entries(context, id, 1, __LINE__); /* 1 */ + + kret = krb5_cc_store_cred(context, id, &test_creds2); + CHECK(kret, "second store for remove (second pass)"); + check_num_entries(context, id, 2, __LINE__); /* 1, 2 */ + + kret = krb5_cc_remove_cred(context, id, matchflags, &test_creds2); + CHECK(kret, "first remove (second pass)"); + check_num_entries(context, id, 1, __LINE__); /* 1 */ + + kret = krb5_cc_store_cred(context, id, &test_creds2); + CHECK(kret, "third store for remove (second pass)"); + check_num_entries(context, id, 2, __LINE__); /* 1, 2 */ + + kret = krb5_cc_remove_cred(context, id, matchflags, &test_creds); + CHECK(kret, "second remove (second pass)"); + check_num_entries(context, id, 1, __LINE__); /* 2 */ + + kret = krb5_cc_remove_cred(context, id, matchflags, &test_creds2); + CHECK(kret, "third remove (second pass)"); + check_num_entries(context, id, 0, __LINE__); /* empty */ + + kret = krb5_cc_destroy(context, id); + CHECK(kret, "destruction for remove"); + + /* Test removal with iteration. */ + kret = krb5_cc_resolve(context, name, &id); + CHECK(kret, "resolving for remove-iter"); + + kret = krb5_cc_initialize(context, id, test_creds.client); + CHECK(kret, "initialize for remove-iter"); + + kret = krb5_cc_store_cred(context, id, &test_creds); + CHECK(kret, "first store for remove-iter"); + + kret = krb5_cc_store_cred(context, id, &test_creds2); + CHECK(kret, "second store for remove-iter"); + + kret = krb5_cc_start_seq_get(context, id, &cursor); + CHECK(kret, "start_seq_get for remove-iter"); + + kret = krb5_cc_remove_cred(context, id, matchflags, &test_creds); + CHECK(kret, "remove for remove-iter"); + + while (1) { + /* The removed credential may or may not be present in the cache - + * either behavior is technically correct. */ + kret = krb5_cc_next_cred(context, id, &cursor, &creds); + if (kret == KRB5_CC_END) + break; + CHECK(kret, "next_cred for remove-iter: %s"); + + CHECK(creds.times.endtime == 0, "no-lifetime cred"); + + krb5_free_cred_contents(context, &creds); + } + + kret = krb5_cc_end_seq_get(context, id, &cursor); + CHECK(kret, "end_seq_get for remove-iter"); + + kret = krb5_cc_destroy(context, id); + CHECK(kret, "destruction for remove-iter"); + + free(save_type); + free_test_cred(context); +} + +/* + * Checks if a credential type is registered with the library + */ +static int +check_registered(krb5_context context, const char *prefix) +{ + char name[300]; + krb5_error_code kret; + krb5_ccache id; + + snprintf(name, sizeof(name), "%s/tmp/cctest.%ld", prefix, (long) getpid()); + + kret = krb5_cc_resolve(context, name, &id); + if(kret != KRB5_OK) { + if(kret == KRB5_CC_UNKNOWN_TYPE) + return 0; + com_err("Checking on credential type", kret, "%s", prefix); + fflush(stderr); + return 0; + } + + kret = krb5_cc_close(context, id); + if(kret != KRB5_OK) { + com_err("Checking on credential type - closing", kret, "%s", prefix); + fflush(stderr); + } + + return 1; +} + + +static void +do_test(krb5_context context, const char *prefix) +{ + char name[300]; + + snprintf(name, sizeof(name), "%s/tmp/cctest.%ld", prefix, (long) getpid()); + printf("Starting test on %s\n", name); + cc_test (context, name, 0); + cc_test (context, name, !0); + printf("Test on %s passed\n", name); +} + +static void +test_misc(krb5_context context) +{ + /* Tests for certain error returns */ + krb5_error_code kret; + krb5_ccache id; + const krb5_cc_ops *ops_save; + + fprintf(stderr, "Testing miscellaneous error conditions\n"); + + kret = krb5_cc_resolve(context, "unknown_method_ep:/tmp/name", &id); + if (kret != KRB5_CC_UNKNOWN_TYPE) { + CHECK(kret, "resolve unknown type"); + } + + /* Test for not specifying a cache type with no defaults */ + ops_save = krb5_cc_dfl_ops; + krb5_cc_dfl_ops = 0; + + kret = krb5_cc_resolve(context, "/tmp/e", &id); + if (kret != KRB5_CC_BADNAME) { + CHECK(kret, "resolve no builtin type"); + } + + krb5_cc_dfl_ops = ops_save; + +} + +/* + * Regression tests for #8202. Because memory ccaches share objects between + * different handles to the same cache and between iterators and caches, + * historically there have been some bugs when those objects are released. + */ +static void +test_memory_concurrent(krb5_context context) +{ + krb5_error_code kret; + krb5_ccache id1, id2; + krb5_cc_cursor cursor; + krb5_creds creds; + + /* Create two handles to the same memory ccache and destroy them. */ + kret = krb5_cc_resolve(context, "MEMORY:x", &id1); + CHECK(kret, "resolve 1"); + kret = krb5_cc_resolve(context, "MEMORY:x", &id2); + CHECK(kret, "resolve 2"); + kret = krb5_cc_destroy(context, id1); + CHECK(kret, "destroy 1"); + kret = krb5_cc_destroy(context, id2); + CHECK(kret, "destroy 2"); + + kret = init_test_cred(context); + CHECK(kret, "init_creds"); + + /* Reinitialize the cache after creating an iterator for it, and verify + * that the iterator ends gracefully. */ + kret = krb5_cc_resolve(context, "MEMORY:x", &id1); + CHECK(kret, "resolve"); + kret = krb5_cc_initialize(context, id1, test_creds.client); + CHECK(kret, "initialize"); + kret = krb5_cc_store_cred(context, id1, &test_creds); + CHECK(kret, "store"); + kret = krb5_cc_start_seq_get(context, id1, &cursor); + CHECK(kret, "start_seq_get"); + kret = krb5_cc_initialize(context, id1, test_creds.client); + CHECK(kret, "initialize again"); + kret = krb5_cc_next_cred(context, id1, &cursor, &creds); + CHECK_BOOL(kret != KRB5_CC_END, "iterator should end", "next_cred"); + kret = krb5_cc_end_seq_get(context, id1, &cursor); + CHECK(kret, "end_seq_get"); + kret = krb5_cc_destroy(context, id1); + CHECK(kret, "destroy"); + + free_test_cred(context); +} + +/* Check that order is preserved during iteration. Not all cache types have + * this property. */ +static void +test_order(krb5_context context, const char *name) +{ + krb5_error_code kret; + krb5_ccache id; + krb5_cc_cursor cursor; + krb5_creds creds; + + kret = init_test_cred(context); + CHECK(kret, "init_creds"); + + kret = krb5_cc_resolve(context, name, &id); + CHECK(kret, "resolve"); + kret = krb5_cc_initialize(context, id, test_creds.client); + CHECK(kret, "initialize"); + kret = krb5_cc_store_cred(context, id, &test_creds); + CHECK(kret, "store 1"); + kret = krb5_cc_store_cred(context, id, &test_creds2); + CHECK(kret, "store 2"); + + kret = krb5_cc_start_seq_get(context, id, &cursor); + CHECK(kret, "start_seq_get"); + kret = krb5_cc_next_cred(context, id, &cursor, &creds); + CHECK(kret, "next_cred 1"); + CHECK_BOOL(krb5_principal_compare(context, creds.server, + test_creds.server) != TRUE, + "first cred does not match", "principal_compare"); + krb5_free_cred_contents(context, &creds); + + kret = krb5_cc_next_cred(context, id, &cursor, &creds); + CHECK(kret, "next_cred 2"); + CHECK_BOOL(krb5_principal_compare(context, creds.server, + test_creds2.server) != TRUE, + "second cred does not match", "principal_compare"); + krb5_free_cred_contents(context, &creds); + + krb5_cc_end_seq_get(context, id, &cursor); + krb5_cc_close(context, id); + free_test_cred(context); +} + +extern const krb5_cc_ops krb5_mcc_ops; +extern const krb5_cc_ops krb5_fcc_ops; + +int +main(void) +{ + krb5_context context; + krb5_error_code kret; + + if ((kret = krb5_init_context(&context))) { + printf("Couldn't initialize krb5 library: %s\n", + error_message(kret)); + exit(1); + } + + kret = krb5_cc_register(context, &krb5_mcc_ops,0); + if(kret && kret != KRB5_CC_TYPE_EXISTS) { + CHECK(kret, "register_mem"); + } + + kret = krb5_cc_register(context, &krb5_fcc_ops,0); + if(kret && kret != KRB5_CC_TYPE_EXISTS) { + CHECK(kret, "register_mem"); + } + + /* Registering a second time tests for error return */ + kret = krb5_cc_register(context, &krb5_fcc_ops,0); + if(kret != KRB5_CC_TYPE_EXISTS) { + CHECK(kret, "register_mem"); + } + + /* Registering with override should work */ + kret = krb5_cc_register(context, &krb5_fcc_ops,1); + CHECK(kret, "register_mem override"); + + init_structs(); + + test_misc(context); + do_test(context, ""); + + if (check_registered(context, "KEYRING:process:")) + do_test(context, "KEYRING:process:"); + else + printf("Skipping KEYRING: test - unregistered type\n"); + + do_test(context, "MEMORY:"); + do_test(context, "FILE:"); + + test_memory_concurrent(context); + + test_order(context, "MEMORY:order"); + + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/t_cccol.c b/krb5-1.21.3/src/lib/krb5/ccache/t_cccol.c new file mode 100644 index 00000000..741f955d --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/t_cccol.c @@ -0,0 +1,363 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/t_cccol.py - Test ccache collection via API */ +/* + * 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. + */ + +#include +#include +#include +#include +#include + +static krb5_context ctx; + +/* Check that code is 0. Display an error message first if it is not. */ +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code != 0) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + } + assert(code == 0); +} + +/* Construct a list of the names of each credential cache in the collection. */ +static void +get_collection_names(char ***list_out, size_t *count_out) +{ + krb5_cccol_cursor cursor; + krb5_ccache cache; + char **list = NULL; + size_t count = 0; + char *name; + + check(krb5_cccol_cursor_new(ctx, &cursor)); + while (1) { + check(krb5_cccol_cursor_next(ctx, cursor, &cache)); + if (cache == NULL) + break; + check(krb5_cc_get_full_name(ctx, cache, &name)); + krb5_cc_close(ctx, cache); + list = realloc(list, (count + 1) * sizeof(*list)); + assert(list != NULL); + list[count++] = name; + } + krb5_cccol_cursor_free(ctx, &cursor); + *list_out = list; + *count_out = count; +} + +/* Return true if list contains name. */ +static krb5_boolean +in_list(char **list, size_t count, const char *name) +{ + size_t i; + + for (i = 0; i < count; i++) { + if (strcmp(list[i], name) == 0) + return TRUE; + } + return FALSE; +} + +/* Release the memory for a list of credential cache names. */ +static void +free_list(char **list, size_t count) +{ + size_t i; + + for (i = 0; i < count; i++) + krb5_free_string(ctx, list[i]); + free(list); +} + +/* + * Check that the cache names within the current collection begin with first + * (unless first is NULL), that the other elements match the remaining + * arguments in some order. others must be the number of additional cache + * names. + */ +static void +check_collection(const char *first, size_t others, ...) +{ + va_list ap; + char **list; + size_t count, i; + const char *name; + + get_collection_names(&list, &count); + if (first != NULL) { + assert(strcmp(first, list[0]) == 0); + assert(count == others + 1); + } else { + assert(count == others); + } + va_start(ap, others); + for (i = 0; i < others; i++) { + name = va_arg(ap, const char *); + assert(in_list(list, count, name)); + } + va_end(ap); + free_list(list, count); +} + +/* Check that the name of cache matches expected_name. */ +static void +check_name(krb5_ccache cache, const char *expected_name) +{ + char *name; + + check(krb5_cc_get_full_name(ctx, cache, &name)); + assert(strcmp(name, expected_name) == 0); + krb5_free_string(ctx, name); +} + +/* Check that when collection_name is resolved, the resulting cache's name + * matches expected_name. */ +static void +check_primary_name(const char *collection_name, const char *expected_name) +{ + krb5_ccache cache; + + check(krb5_cc_resolve(ctx, collection_name, &cache)); + check_name(cache, expected_name); + krb5_cc_close(ctx, cache); +} + +/* Check that when name is resolved, the resulting cache's principal matches + * expected_princ, or has no principal if expected_princ is NULL. */ +static void +check_princ(const char *name, krb5_principal expected_princ) +{ + krb5_ccache cache; + krb5_principal princ; + + check(krb5_cc_resolve(ctx, name, &cache)); + if (expected_princ != NULL) { + check(krb5_cc_get_principal(ctx, cache, &princ)); + assert(krb5_principal_compare(ctx, princ, expected_princ)); + krb5_free_principal(ctx, princ); + } else { + assert(krb5_cc_get_principal(ctx, cache, &princ) != 0); + } + krb5_cc_close(ctx, cache); +} + +/* Check that krb5_cc_cache_match on princ returns a cache whose name matches + * expected_name, or that the match fails if expected_name is NULL. */ +static void +check_match(krb5_principal princ, const char *expected_name) +{ + krb5_ccache cache; + + if (expected_name != NULL) { + check(krb5_cc_cache_match(ctx, princ, &cache)); + check_name(cache, expected_name); + krb5_cc_close(ctx, cache); + } else { + assert(krb5_cc_cache_match(ctx, princ, &cache) != 0); + } +} + +int +main(int argc, char **argv) +{ + krb5_ccache ccinitial, ccu1, ccu2; + krb5_principal princ1, princ2, princ3; + const char *collection_name, *typename; + char *initial_primary_name, *unique1_name, *unique2_name; + + /* + * Get the collection name from the command line. This is a ccache name + * with collection semantics, like DIR:/path/to/directory. This test + * program assumes that the collection is empty to start with. + */ + assert(argc == 2); + collection_name = argv[1]; + + /* + * Set the default ccache for the context to be the collection name, so the + * library can find the collection. + */ + check(krb5_init_context(&ctx)); + check(krb5_cc_set_default_name(ctx, collection_name)); + + /* + * Resolve the collection name. Since the collection is empty, this should + * generate a subsidiary name of an uninitialized cache. Getting the name + * of the resulting cache should give us the subsidiary name, not the + * collection name. This resulting subsidiary name should be consistent if + * we resolve the collection name again, and the collection should still be + * empty since we haven't initialized the cache. + */ + check(krb5_cc_resolve(ctx, collection_name, &ccinitial)); + check(krb5_cc_get_full_name(ctx, ccinitial, &initial_primary_name)); + assert(strcmp(initial_primary_name, collection_name) != 0); + check_primary_name(collection_name, initial_primary_name); + check_collection(NULL, 0); + check_princ(collection_name, NULL); + check_princ(initial_primary_name, NULL); + + /* + * Before initializing the primary ccache, generate and initialize two + * unique caches of the collection's type. Check that the cache names + * resolve to the generated caches and appear in the collection. (They + * might appear before being initialized; that's not currently considered + * important). The primary cache for the collection should remain as the + * uninitialized cache from the previous step. + */ + typename = krb5_cc_get_type(ctx, ccinitial); + check(krb5_cc_new_unique(ctx, typename, NULL, &ccu1)); + check(krb5_cc_get_full_name(ctx, ccu1, &unique1_name)); + check(krb5_parse_name(ctx, "princ1@X", &princ1)); + check(krb5_cc_initialize(ctx, ccu1, princ1)); + check_princ(unique1_name, princ1); + check_match(princ1, unique1_name); + check_collection(NULL, 1, unique1_name); + check(krb5_cc_new_unique(ctx, typename, NULL, &ccu2)); + check(krb5_cc_get_full_name(ctx, ccu2, &unique2_name)); + check(krb5_parse_name(ctx, "princ2@X", &princ2)); + check(krb5_cc_initialize(ctx, ccu2, princ2)); + check_princ(unique2_name, princ2); + check_match(princ1, unique1_name); + check_match(princ2, unique2_name); + check_collection(NULL, 2, unique1_name, unique2_name); + assert(strcmp(unique1_name, initial_primary_name) != 0); + assert(strcmp(unique1_name, collection_name) != 0); + assert(strcmp(unique2_name, initial_primary_name) != 0); + assert(strcmp(unique2_name, collection_name) != 0); + assert(strcmp(unique2_name, unique1_name) != 0); + check_primary_name(collection_name, initial_primary_name); + + /* + * Initialize the initial primary cache. Make sure it didn't change names, + * that the previously retrieved name and the collection name both resolve + * to the initialized cache, and that it now appears first in the + * collection. + */ + check(krb5_parse_name(ctx, "princ3@X", &princ3)); + check(krb5_cc_initialize(ctx, ccinitial, princ3)); + check_name(ccinitial, initial_primary_name); + check_princ(initial_primary_name, princ3); + check_princ(collection_name, princ3); + check_match(princ3, initial_primary_name); + check_collection(initial_primary_name, 2, unique1_name, unique2_name); + + /* + * Switch the primary cache to each cache we have open. One each switch, + * check the primary name, check that the collection resolves to the + * expected cache, and check that the new primary name appears first in the + * collection. + */ + check(krb5_cc_switch(ctx, ccu1)); + check_primary_name(collection_name, unique1_name); + check_princ(collection_name, princ1); + check_collection(unique1_name, 2, initial_primary_name, unique2_name); + check(krb5_cc_switch(ctx, ccu2)); + check_primary_name(collection_name, unique2_name); + check_princ(collection_name, princ2); + check_collection(unique2_name, 2, initial_primary_name, unique1_name); + check(krb5_cc_switch(ctx, ccinitial)); + check_primary_name(collection_name, initial_primary_name); + check_princ(collection_name, princ3); + check_collection(initial_primary_name, 2, unique1_name, unique2_name); + + /* + * Temporarily set the context default ccache to a subsidiary name, and + * check that iterating over the collection yields that subsidiary cache + * and no others. + */ + check(krb5_cc_set_default_name(ctx, unique1_name)); + check_collection(unique1_name, 0); + check(krb5_cc_set_default_name(ctx, collection_name)); + + /* + * Destroy the primary cache. Make sure this causes both the initial + * primary name and the collection name to resolve to an uninitialized + * cache. Make sure the primary name doesn't change and doesn't appear in + * the collection any more. + */ + check(krb5_cc_destroy(ctx, ccinitial)); + check_princ(initial_primary_name, NULL); + check_princ(collection_name, NULL); + check_primary_name(collection_name, initial_primary_name); + check_match(princ1, unique1_name); + check_match(princ2, unique2_name); + check_match(princ3, NULL); + check_collection(NULL, 2, unique1_name, unique2_name); + + /* + * Switch to the first unique cache after destroying the primary cache. + * Check that the collection name resolves to this cache and that the new + * primary name appears first in the collection. + */ + check(krb5_cc_switch(ctx, ccu1)); + check_primary_name(collection_name, unique1_name); + check_princ(collection_name, princ1); + check_collection(unique1_name, 1, unique2_name); + + /* + * Destroy the second unique cache (which is not the current primary), + * check that it is on longer initialized, and check that it no longer + * appears in the collection. Check that destroying the non-primary cache + * doesn't affect the primary name. + */ + check(krb5_cc_destroy(ctx, ccu2)); + check_princ(unique2_name, NULL); + check_match(princ2, NULL); + check_collection(unique1_name, 0); + check_primary_name(collection_name, unique1_name); + check_match(princ1, unique1_name); + check_princ(collection_name, princ1); + + /* + * Destroy the first unique cache. Check that the collection is empty and + * still has the same primary name. + */ + check(krb5_cc_destroy(ctx, ccu1)); + check_princ(unique1_name, NULL); + check_princ(collection_name, NULL); + check_primary_name(collection_name, unique1_name); + check_match(princ1, NULL); + check_collection(NULL, 0); + + krb5_free_string(ctx, initial_primary_name); + krb5_free_string(ctx, unique1_name); + krb5_free_string(ctx, unique2_name); + krb5_free_principal(ctx, princ1); + krb5_free_principal(ctx, princ2); + krb5_free_principal(ctx, princ3); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/t_cccol.py b/krb5-1.21.3/src/lib/krb5/ccache/t_cccol.py new file mode 100755 index 00000000..7dfe05b1 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/t_cccol.py @@ -0,0 +1,125 @@ +from k5test import * + +realm = K5Realm(create_kdb=False) + +keyctl = which('keyctl') +out = realm.run([klist, '-c', 'KEYRING:process:abcd'], expected_code=1) +test_keyring = (keyctl is not None and + 'Unknown credential cache type' not in out) +if not test_keyring: + skipped('keyring collection tests', 'keyring support not built') + +# Run the collection test program against each collection-enabled type. +realm.run(['./t_cccol', 'DIR:' + os.path.join(realm.testdir, 'cc')]) +if test_keyring: + def cleanup_keyring(anchor, name): + out = realm.run(['keyctl', 'list', anchor]) + if ('keyring: ' + name + '\n') in out: + keyid = realm.run(['keyctl', 'search', anchor, 'keyring', name]) + realm.run(['keyctl', 'unlink', keyid.strip(), anchor]) + + # Use the test directory as the collection name to avoid colliding + # with other build trees. + cname = realm.testdir + col_ringname = '_krb_' + cname + + # Remove any keys left behind by previous failed test runs. + cleanup_keyring('@s', cname) + cleanup_keyring('@s', col_ringname) + cleanup_keyring('@u', col_ringname) + + # Run test program over each subtype, cleaning up as we go. Don't + # test the persistent subtype, since it supports only one + # collection and might be in actual use. + realm.run(['./t_cccol', 'KEYRING:' + cname]) + cleanup_keyring('@s', col_ringname) + realm.run(['./t_cccol', 'KEYRING:legacy:' + cname]) + cleanup_keyring('@s', col_ringname) + realm.run(['./t_cccol', 'KEYRING:session:' + cname]) + cleanup_keyring('@s', col_ringname) + realm.run(['./t_cccol', 'KEYRING:user:' + cname]) + cleanup_keyring('@u', col_ringname) + realm.run(['./t_cccol', 'KEYRING:process:abcd']) + realm.run(['./t_cccol', 'KEYRING:thread:abcd']) + +realm.stop() + +# Test cursor semantics using real ccaches. +realm = K5Realm(create_host=False) + +realm.addprinc('alice', password('alice')) +realm.addprinc('bob', password('bob')) + +ccdir = os.path.join(realm.testdir, 'cc') +dccname = 'DIR:%s' % ccdir +duser = 'DIR::%s/tkt1' % ccdir +dalice = 'DIR::%s/tkt2' % ccdir +dbob = 'DIR::%s/tkt3' % ccdir +dnoent = 'DIR::%s/noent' % ccdir +realm.kinit('user', password('user'), flags=['-c', duser]) +realm.kinit('alice', password('alice'), flags=['-c', dalice]) +realm.kinit('bob', password('bob'), flags=['-c', dbob]) + +if test_keyring: + cleanup_keyring('@s', col_ringname) + krccname = 'KEYRING:session:' + cname + kruser = '%s:tkt1' % krccname + kralice = '%s:tkt2' % krccname + krbob = '%s:tkt3' % krccname + krnoent = '%s:noent' % krccname + realm.kinit('user', password('user'), flags=['-c', kruser]) + realm.kinit('alice', password('alice'), flags=['-c', kralice]) + realm.kinit('bob', password('bob'), flags=['-c', krbob]) + +def cursor_test(testname, args, expected): + outlines = realm.run(['./t_cccursor'] + args).splitlines() + outlines.sort() + expected.sort() + if outlines != expected: + fail('Output not expected for %s\n' % testname + + 'Expected output:\n\n' + '\n'.join(expected) + '\n\n' + + 'Actual output:\n\n' + '\n'.join(outlines)) + +mark('FILE cursor') +fccname = 'FILE:%s' % realm.ccache +cursor_test('file-default', [], [fccname]) +cursor_test('file-default2', [realm.ccache], [fccname]) +cursor_test('file-default3', [fccname], [fccname]) + +mark('DIR cursor') +cursor_test('dir', [dccname], [duser, dalice, dbob]) +cursor_test('dir-subsidiary', [duser], [duser]) +cursor_test('dir-nofile', [dnoent], []) + +if test_keyring: + mark('KEYRING cursor') + cursor_test('keyring', [krccname], [kruser, kralice, krbob]) + cursor_test('keyring-subsidiary', [kruser], [kruser]) + cursor_test('keyring-noent', [krnoent], []) + +mark('MEMORY cursor') +mfoo = 'MEMORY:foo' +mbar = 'MEMORY:bar' +cursor_test('filemem', [fccname, mfoo], [fccname]) +cursor_test('dirmem', [dccname, mfoo], [duser, dalice, dbob]) +cursor_test('mem', [mfoo, mbar], [mfoo]) +if test_keyring: + cursor_test('keyringmem', [krccname, mfoo], [kruser, kralice, krbob]) + +# Test krb5_cccol_have_content. +mark('krb5_cccol_have_content') +realm.run(['./t_cccursor', dccname, 'CONTENT']) +realm.run(['./t_cccursor', fccname, 'CONTENT']) +realm.run(['./t_cccursor', realm.ccache, 'CONTENT']) +realm.run(['./t_cccursor', mfoo, 'CONTENT'], expected_code=1) +if test_keyring: + realm.run(['./t_cccursor', krccname, 'CONTENT']) + cleanup_keyring('@s', col_ringname) + +# Make sure FILE doesn't yield a nonexistent default cache. +mark('FILE nonexistent') +realm.run([kdestroy]) +cursor_test('noexist', [], []) +realm.run(['./t_cccursor', fccname, 'CONTENT'], expected_code=1) + +success('Renewing credentials') diff --git a/krb5-1.21.3/src/lib/krb5/ccache/t_cccursor.c b/krb5-1.21.3/src/lib/krb5/ccache/t_cccursor.c new file mode 100644 index 00000000..96ca3aee --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/t_cccursor.c @@ -0,0 +1,81 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/t_cccursor.c - Simple test harness for cccol API */ +/* + * Copyright 2011 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Displays a list of caches returned by the cccol cursor. The first argument, + * if given, is set to the default cache name for the context before iterating. + * Any remaining arguments are resolved as caches and kept open during the + * iteration. If the argument "CONTENT" is given as one of the cache names, + * immediately exit with status 0 if the collection contains credentials and 1 + * if it does not. + */ + +#include "k5-int.h" + +int +main(int argc, char **argv) +{ + krb5_error_code ret; + krb5_context ctx; + krb5_cccol_cursor cursor; + krb5_ccache cache, hold[64]; + int i; + char *name; + + assert(krb5_init_context(&ctx) == 0); + if (argc > 1) + assert(krb5_cc_set_default_name(ctx, argv[1]) == 0); + + if (argc > 2) { + assert(argc < 60); + for (i = 2; i < argc; i++) { + if (strcmp(argv[i], "CONTENT") == 0) { + ret = krb5_cccol_have_content(ctx); + krb5_free_context(ctx); + return ret != 0; + } + assert(krb5_cc_resolve(ctx, argv[i], &hold[i - 2]) == 0); + } + } + + assert(krb5_cccol_cursor_new(ctx, &cursor) == 0); + while (1) { + assert(krb5_cccol_cursor_next(ctx, cursor, &cache) == 0); + if (cache == NULL) + break; + assert(krb5_cc_get_full_name(ctx, cache, &name) == 0); + printf("%s\n", name); + krb5_free_string(ctx, name); + krb5_cc_close(ctx, cache); + } + assert(krb5_cccol_cursor_free(ctx, &cursor) == 0); + + for (i = 2; i < argc; i++) + krb5_cc_close(ctx, hold[i - 2]); + + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/t_marshal.c b/krb5-1.21.3/src/lib/krb5/ccache/t_marshal.c new file mode 100644 index 00000000..96e0931a --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/t_marshal.c @@ -0,0 +1,420 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/t_marshal.c - test program for cred marshalling */ +/* + * Copyright (C) 2014 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. + */ + +#include "cc-int.h" +#include +#include +#include +#include + +/* + * Versions 1 and 2 of the ccache format use native byte order representations + * of integers. The test data below is from a little-endian platform. Skip + * those tests on big-endian platforms by starting at version 3. + */ +#ifdef K5_BE +#define FIRST_VERSION 3 +#else +#define FIRST_VERSION 1 +#endif + +/* Each test contains the expected binary representation of a credential cache + * divided into the header, the default principal, and two credentials. */ +const struct test { + size_t headerlen; + const unsigned char header[256]; + size_t princlen; + const unsigned char princ[256]; + size_t cred1len; + const unsigned char cred1[256]; + size_t cred2len; + const unsigned char cred2[256]; +} tests[4] = { + { + /* Version 1 header */ + 2, + "\x05\x01", + /* Version 1 principal */ + 33, + "\x02\x00\x00\x00\x0B\x00\x00\x00\x4B\x52\x42\x54\x45\x53\x54\x2E" + "\x43\x4F\x4D\x0A\x00\x00\x00\x74\x65\x73\x74\x63\x6C\x69\x65\x6E" + "\x74", + /* Version 1 cred 1 */ + 165, + "\x02\x00\x00\x00\x0B\x00\x00\x00\x4B\x52\x42\x54\x45\x53\x54\x2E" + "\x43\x4F\x4D\x0A\x00\x00\x00\x74\x65\x73\x74\x63\x6C\x69\x65\x6E" + "\x74\x03\x00\x00\x00\x0B\x00\x00\x00\x45\x58\x41\x4D\x50\x4C\x45" + "\x2E\x43\x4F\x4D\x04\x00\x00\x00\x74\x65\x73\x74\x04\x00\x00\x00" + "\x68\x6F\x73\x74\x11\x00\x10\x00\x00\x00\x00\x01\x02\x03\x04\x05" + "\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x0B\x00\x00\x00\xDE\x00" + "\x00\x00\x05\x0D\x00\x00\x00\xCA\x9A\x3B\x00\x00\x00\x80\x40\x01" + "\x00\x00\x00\x02\x00\x04\x00\x00\x00\x0A\x00\x00\x01\x02\x00\x00" + "\x00\x00\x02\x0A\x00\x00\x00\x73\x69\x67\x6E\x74\x69\x63\x6B\x65" + "\x74\x9C\xFF\x00\x00\x00\x00\x06\x00\x00\x00\x74\x69\x63\x6B\x65" + "\x74\x00\x00\x00\x00", + /* Version 1 cred 2 */ + 113, + "\x02\x00\x00\x00\x0B\x00\x00\x00\x4B\x52\x42\x54\x45\x53\x54\x2E" + "\x43\x4F\x4D\x0A\x00\x00\x00\x74\x65\x73\x74\x63\x6C\x69\x65\x6E" + "\x74\x01\x00\x00\x00\x00\x00\x00\x00\x17\x00\x10\x00\x00\x00\x0F" + "\x0E\x0D\x0C\x0B\x0A\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00" + "\x74\x69\x63\x6B\x65\x74\x07\x00\x00\x00\x32\x74\x69\x63\x6B\x65" + "\x74" + }, + { + /* Version 2 header */ + 2, + "\x05\x02", + /* Version 2 principal */ + 37, + "\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x00\x00\x00\x4B\x52\x42\x54" + "\x45\x53\x54\x2E\x43\x4F\x4D\x0A\x00\x00\x00\x74\x65\x73\x74\x63" + "\x6C\x69\x65\x6E\x74", + /* Version 2 cred 1 */ + 173, + "\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x00\x00\x00\x4B\x52\x42\x54" + "\x45\x53\x54\x2E\x43\x4F\x4D\x0A\x00\x00\x00\x74\x65\x73\x74\x63" + "\x6C\x69\x65\x6E\x74\x01\x00\x00\x00\x02\x00\x00\x00\x0B\x00\x00" + "\x00\x45\x58\x41\x4D\x50\x4C\x45\x2E\x43\x4F\x4D\x04\x00\x00\x00" + "\x74\x65\x73\x74\x04\x00\x00\x00\x68\x6F\x73\x74\x11\x00\x10\x00" + "\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D" + "\x0E\x0F\x0B\x00\x00\x00\xDE\x00\x00\x00\x05\x0D\x00\x00\x00\xCA" + "\x9A\x3B\x00\x00\x00\x80\x40\x01\x00\x00\x00\x02\x00\x04\x00\x00" + "\x00\x0A\x00\x00\x01\x02\x00\x00\x00\x00\x02\x0A\x00\x00\x00\x73" + "\x69\x67\x6E\x74\x69\x63\x6B\x65\x74\x9C\xFF\x00\x00\x00\x00\x06" + "\x00\x00\x00\x74\x69\x63\x6B\x65\x74\x00\x00\x00\x00", + /* Version 2 cred 2 */ + 121, + "\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x00\x00\x00\x4B\x52\x42\x54" + "\x45\x53\x54\x2E\x43\x4F\x4D\x0A\x00\x00\x00\x74\x65\x73\x74\x63" + "\x6C\x69\x65\x6E\x74\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x17\x00\x10\x00\x00\x00\x0F\x0E\x0D\x0C\x0B\x0A\x09\x08\x07" + "\x06\x05\x04\x03\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x06\x00\x00\x00\x74\x69\x63\x6B\x65\x74\x07\x00" + "\x00\x00\x32\x74\x69\x63\x6B\x65\x74" + }, + { + /* Version 3 header */ + 2, + "\x05\x03", + /* Version 3 principal */ + 37, + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x4B\x52\x42\x54" + "\x45\x53\x54\x2E\x43\x4F\x4D\x00\x00\x00\x0A\x74\x65\x73\x74\x63" + "\x6C\x69\x65\x6E\x74", + /* Version 3 cred 1 */ + 175, + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x4B\x52\x42\x54" + "\x45\x53\x54\x2E\x43\x4F\x4D\x00\x00\x00\x0A\x74\x65\x73\x74\x63" + "\x6C\x69\x65\x6E\x74\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00" + "\x0B\x45\x58\x41\x4D\x50\x4C\x45\x2E\x43\x4F\x4D\x00\x00\x00\x04" + "\x74\x65\x73\x74\x00\x00\x00\x04\x68\x6F\x73\x74\x00\x11\x00\x11" + "\x00\x00\x00\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B" + "\x0C\x0D\x0E\x0F\x00\x00\x00\x0B\x00\x00\x00\xDE\x00\x00\x0D\x05" + "\x3B\x9A\xCA\x00\x00\x40\x80\x00\x00\x00\x00\x00\x01\x00\x02\x00" + "\x00\x00\x04\x0A\x00\x00\x01\x00\x00\x00\x02\x02\x00\x00\x00\x00" + "\x0A\x73\x69\x67\x6E\x74\x69\x63\x6B\x65\x74\xFF\x9C\x00\x00\x00" + "\x00\x00\x00\x00\x06\x74\x69\x63\x6B\x65\x74\x00\x00\x00\x00", + /* Version 3 cred 2 */ + 123, + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x4B\x52\x42\x54" + "\x45\x53\x54\x2E\x43\x4F\x4D\x00\x00\x00\x0A\x74\x65\x73\x74\x63" + "\x6C\x69\x65\x6E\x74\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x17\x00\x17\x00\x00\x00\x10\x0F\x0E\x0D\x0C\x0B\x0A\x09" + "\x08\x07\x06\x05\x04\x03\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x74\x69\x63\x6B\x65\x74" + "\x00\x00\x00\x07\x32\x74\x69\x63\x6B\x65\x74" + }, + { + /* Version 4 header */ + 16, + "\x05\x04\x00\x0C\x00\x01\x00\x08\x00\x00\x01\x2C\x00\x00\xD4\x31", + /* Version 4 principal */ + 37, + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x4B\x52\x42\x54" + "\x45\x53\x54\x2E\x43\x4F\x4D\x00\x00\x00\x0A\x74\x65\x73\x74\x63" + "\x6C\x69\x65\x6E\x74", + /* Version 4 cred 1 */ + 173, + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x4B\x52\x42\x54" + "\x45\x53\x54\x2E\x43\x4F\x4D\x00\x00\x00\x0A\x74\x65\x73\x74\x63" + "\x6C\x69\x65\x6E\x74\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00" + "\x0B\x45\x58\x41\x4D\x50\x4C\x45\x2E\x43\x4F\x4D\x00\x00\x00\x04" + "\x74\x65\x73\x74\x00\x00\x00\x04\x68\x6F\x73\x74\x00\x11\x00\x00" + "\x00\x10\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D" + "\x0E\x0F\x00\x00\x00\x0B\x00\x00\x00\xDE\x00\x00\x0D\x05\x3B\x9A" + "\xCA\x00\x00\x40\x80\x00\x00\x00\x00\x00\x01\x00\x02\x00\x00\x00" + "\x04\x0A\x00\x00\x01\x00\x00\x00\x02\x02\x00\x00\x00\x00\x0A\x73" + "\x69\x67\x6E\x74\x69\x63\x6B\x65\x74\xFF\x9C\x00\x00\x00\x00\x00" + "\x00\x00\x06\x74\x69\x63\x6B\x65\x74\x00\x00\x00\x00", + /* Version 4 cred 2 */ + 121, + "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x0B\x4B\x52\x42\x54" + "\x45\x53\x54\x2E\x43\x4F\x4D\x00\x00\x00\x0A\x74\x65\x73\x74\x63" + "\x6C\x69\x65\x6E\x74\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x17\x00\x00\x00\x10\x0F\x0E\x0D\x0C\x0B\x0A\x09\x08\x07" + "\x06\x05\x04\x03\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x06\x74\x69\x63\x6B\x65\x74\x00\x00" + "\x00\x07\x32\x74\x69\x63\x6B\x65\x74" + } +}; + +static void +verify_princ(krb5_principal p) +{ + assert(p->length == 1); + assert(data_eq_string(p->realm, "KRBTEST.COM")); + assert(data_eq_string(p->data[0], "testclient")); +} + +static void +verify_cred1(const krb5_creds *c) +{ + uint32_t ipaddr = ntohl(0x0A000001); + + verify_princ(c->client); + assert(c->server->length == 2); + assert(data_eq_string(c->server->realm, "EXAMPLE.COM")); + assert(data_eq_string(c->server->data[0], "test")); + assert(data_eq_string(c->server->data[1], "host")); + assert(c->keyblock.enctype == ENCTYPE_AES128_CTS_HMAC_SHA1_96); + assert(c->keyblock.length == 16); + assert(memcmp(c->keyblock.contents, + "\x0\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF", + 16) == 0); + assert(c->times.authtime == 11); + assert(c->times.starttime == 222); + assert(c->times.endtime == 3333); + assert(c->times.renew_till == 1000000000); + assert(c->is_skey == FALSE); + assert(c->ticket_flags == (TKT_FLG_FORWARDABLE | TKT_FLG_RENEWABLE)); + assert(c->addresses != NULL && c->addresses[0] != NULL); + assert(c->addresses[0]->addrtype == ADDRTYPE_INET); + assert(c->addresses[0]->length == 4); + assert(memcmp(c->addresses[0]->contents, &ipaddr, 4) == 0); + assert(c->addresses[1] == NULL); + assert(c->authdata != NULL && c->authdata[0] != NULL); + assert(c->authdata[0]->ad_type == KRB5_AUTHDATA_SIGNTICKET); + assert(c->authdata[0]->length == 10); + assert(memcmp(c->authdata[0]->contents, "signticket", 10) == 0); + assert(c->authdata[1] != NULL); + assert(c->authdata[1]->ad_type == -100); + assert(c->authdata[1]->length == 0); + assert(c->authdata[2] == NULL); + assert(data_eq_string(c->ticket, "ticket")); + assert(c->second_ticket.length == 0); +} + +static void +verify_cred2(const krb5_creds *c) +{ + verify_princ(c->client); + assert(c->server->length == 0); + assert(c->server->realm.length == 0); + assert(c->keyblock.enctype == ENCTYPE_ARCFOUR_HMAC); + assert(c->keyblock.length == 16); + assert(memcmp(c->keyblock.contents, + "\xF\xE\xD\xC\xB\xA\x9\x8\x7\x6\x5\x4\x3\x2\x1\x0", + 16) == 0); + assert(c->times.authtime == 0); + assert(c->times.starttime == 0); + assert(c->times.endtime == 0); + assert(c->times.renew_till == 0); + assert(c->is_skey == TRUE); + assert(c->ticket_flags == 0); + assert(c->addresses == NULL || c->addresses[0] == NULL); + assert(c->authdata == NULL || c->authdata[0] == NULL); + assert(data_eq_string(c->ticket, "ticket")); + assert(data_eq_string(c->second_ticket, "2ticket")); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_ccache cache; + krb5_principal princ; + krb5_creds cred1, cred2, *alloc_cred; + krb5_cc_cursor cursor; + const char *filename; + char *ccname, filebuf[256]; + int version, fd; + const struct test *t; + struct k5buf buf; + krb5_data ser_data, *alloc_data; + + if (argc != 2) + abort(); + filename = argv[1]; + if (asprintf(&ccname, "FILE:%s", filename) == -1) + abort(); + + if (krb5_init_context(&context) != 0) + abort(); + + /* Test public functions for unmarshalling and marshalling. */ + ser_data = make_data((char *)tests[3].cred1, tests[3].cred1len); + if (krb5_unmarshal_credentials(context, &ser_data, &alloc_cred) != 0) + abort(); + verify_cred1(alloc_cred); + if (krb5_marshal_credentials(context, alloc_cred, &alloc_data) != 0) + abort(); + assert(alloc_data->length == tests[3].cred1len); + assert(memcmp(tests[3].cred1, alloc_data->data, alloc_data->length) == 0); + krb5_free_data(context, alloc_data); + krb5_free_creds(context, alloc_cred); + + for (version = FIRST_VERSION; version <= 4; version++) { + t = &tests[version - 1]; + + /* Test principal unmarshalling and marshalling. */ + if (k5_unmarshal_princ(t->princ, t->princlen, version, &princ) != 0) + abort(); + verify_princ(princ); + k5_buf_init_dynamic(&buf); + k5_marshal_princ(&buf, version, princ); + assert(buf.len == t->princlen); + assert(memcmp(t->princ, buf.data, buf.len) == 0); + k5_buf_free(&buf); + + /* Test cred1 unmarshalling and marshalling. */ + if (k5_unmarshal_cred(t->cred1, t->cred1len, version, &cred1) != 0) + abort(); + verify_cred1(&cred1); + k5_buf_init_dynamic(&buf); + k5_marshal_cred(&buf, version, &cred1); + assert(buf.len == t->cred1len); + assert(memcmp(t->cred1, buf.data, buf.len) == 0); + k5_buf_free(&buf); + + /* Test cred2 unmarshalling and marshalling. */ + if (k5_unmarshal_cred(t->cred2, t->cred2len, version, &cred2) != 0) + abort(); + verify_cred2(&cred2); + k5_buf_init_dynamic(&buf); + k5_marshal_cred(&buf, version, &cred2); + assert(buf.len == t->cred2len); + assert(memcmp(t->cred2, buf.data, buf.len) == 0); + k5_buf_free(&buf); + + /* Write a ccache containing the principal and creds. Use the same + * time offset as the version 4 test data used. */ + context->fcc_default_format = 0x0500 + version; + context->os_context.time_offset = 300; + context->os_context.usec_offset = 54321; + context->os_context.os_flags = KRB5_OS_TOFFSET_VALID; + if (krb5_cc_resolve(context, ccname, &cache) != 0) + abort(); + if (krb5_cc_initialize(context, cache, princ) != 0) + abort(); + if (krb5_cc_store_cred(context, cache, &cred1) != 0) + abort(); + if (krb5_cc_store_cred(context, cache, &cred2) != 0) + abort(); + if (krb5_cc_close(context, cache) != 0) + abort(); + + /* Verify the cache representation against the test data. */ + fd = open(filename, O_RDONLY); + if (fd == -1) + abort(); + if (read(fd, filebuf, t->headerlen) != (ssize_t)t->headerlen) + abort(); + assert(memcmp(filebuf, t->header, t->headerlen) == 0); + if (read(fd, filebuf, t->princlen) != (ssize_t)t->princlen) + abort(); + assert(memcmp(filebuf, t->princ, t->princlen) == 0); + if (read(fd, filebuf, t->cred1len) != (ssize_t)t->cred1len) + abort(); + assert(memcmp(filebuf, t->cred1, t->cred1len) == 0); + if (read(fd, filebuf, t->cred2len) != (ssize_t)t->cred2len) + abort(); + assert(memcmp(filebuf, t->cred2, t->cred2len) == 0); + close(fd); + + krb5_free_principal(context, princ); + krb5_free_cred_contents(context, &cred1); + krb5_free_cred_contents(context, &cred2); + + /* Write a cache containing the test data. */ + fd = open(filename, O_CREAT|O_TRUNC|O_RDWR, 0700); + if (fd == -1) + abort(); + if (write(fd, t->header, t->headerlen) != (ssize_t)t->headerlen) + abort(); + if (write(fd, t->princ, t->princlen) != (ssize_t)t->princlen) + abort(); + if (write(fd, t->cred1, t->cred1len) != (ssize_t)t->cred1len) + abort(); + if (write(fd, t->cred2, t->cred2len) != (ssize_t)t->cred2len) + abort(); + close(fd); + + /* Read the cache and verify that it matches. */ + if (krb5_cc_resolve(context, ccname, &cache) != 0) + abort(); + if (krb5_cc_get_principal(context, cache, &princ) != 0) + abort(); + /* Not every version stores the time offset, but at least it shouldn't + * have changed from when we set it before. */ + assert(context->os_context.time_offset == 300); + assert(context->os_context.usec_offset == 54321); + verify_princ(princ); + if (krb5_cc_start_seq_get(context, cache, &cursor) != 0) + abort(); + if (krb5_cc_next_cred(context, cache, &cursor, &cred1) != 0) + abort(); + verify_cred1(&cred1); + krb5_free_cred_contents(context, &cred1); + if (krb5_cc_next_cred(context, cache, &cursor, &cred2) != 0) + abort(); + verify_cred2(&cred2); + krb5_free_cred_contents(context, &cred2); + if (krb5_cc_next_cred(context, cache, &cursor, &cred2) != KRB5_CC_END) + abort(); + if (krb5_cc_end_seq_get(context, cache, &cursor) != 0) + abort(); + if (krb5_cc_close(context, cache) != 0) + abort(); + krb5_free_principal(context, princ); + } + + (void)unlink(filename); + free(ccname); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/t_memory.c b/krb5-1.21.3/src/lib/krb5/ccache/t_memory.c new file mode 100644 index 00000000..6d103a00 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/t_memory.c @@ -0,0 +1,138 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/t_memory.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "mcc.h" + +krb5_data client1 = { +#define DATA "client1-comp1" + sizeof(DATA), + DATA, +#undef DATA +}; + +krb5_data client2 = { +#define DATA "client1-comp2" + sizeof(DATA), + DATA, +#undef DATA +}; + +krb5_data server1 = { +#define DATA "server1-comp1" + sizeof(DATA), + DATA, +#undef DATA +}; + +krb5_data server2 = { +#define DATA "server1-comp2" + sizeof(DATA), + DATA, +#undef DATA +}; + +krb5_creds test_creds = { + NULL, + NULL, + { + 1, + 1, + (unsigned char *) "1" + }, + { + 1111, + 2222, + 3333, + 4444 + }, + 1, + 5555, + { +#define TICKET "This is ticket 1" + sizeof(TICKET), + TICKET, +#undef TICKET + }, + { +#define TICKET "This is ticket 2" + sizeof(TICKET), + TICKET, +#undef TICKET + }, +}; + +void +init_test_cred() +{ + test_creds.client = (krb5_principal) malloc(sizeof(krb5_data *)*3); + test_creds.client[0] = &client1; + test_creds.client[1] = &client2; + test_creds.client[2] = NULL; + + test_creds.server = (krb5_principal) malloc(sizeof(krb5_data *)*3); + test_creds.server[0] = &server1; + test_creds.server[1] = &server2; + test_creds.server[2] = NULL; +} + +#define CHECK(kret,msg) \ + if (kret != KRB5_OK) { \ + printf("%s returned %d\n", msg, kret); \ + }; + +void +mcc_test() +{ + krb5_ccache id; + krb5_creds creds; + krb5_error_code kret; + krb5_cc_cursor cursor; + + init_test_cred(); + + kret = krb5_mcc_resolve(context, &id, "/tmp/tkt_test"); + CHECK(kret, "resolve"); + kret = krb5_mcc_initialize(context, id, test_creds.client); + CHECK(kret, "initialize"); + kret = krb5_mcc_store(context, id, &test_creds); + CHECK(kret, "store"); + + kret = krb5_mcc_start_seq_get(context, id, &cursor); + CHECK(kret, "start_seq_get"); + kret = 0; + while (kret != KRB5_CC_END) { + printf("Calling next_cred\n"); + kret = krb5_mcc_next_cred(context, id, &cursor, &creds); + CHECK(kret, "next_cred"); + } + kret = krb5_mcc_end_seq_get(context, id, &cursor); + CHECK(kret, "end_seq_get"); + + kret = krb5_mcc_destroy(context, id); + CHECK(kret, "destroy"); + kret = krb5_mcc_close(context, id); + CHECK(kret, "close"); +} diff --git a/krb5-1.21.3/src/lib/krb5/ccache/t_stdio.c b/krb5-1.21.3/src/lib/krb5/ccache/t_stdio.c new file mode 100644 index 00000000..15185e30 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/ccache/t_stdio.c @@ -0,0 +1,168 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/ccache/t_stdio.c */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "scc.h" + +krb5_data client1 = { +#define DATA "client1-comp1" + sizeof(DATA), + DATA, +#undef DATA +}; + +krb5_data client2 = { +#define DATA "client1-comp2" + sizeof(DATA), + DATA, +#undef DATA +}; + +krb5_data server1 = { +#define DATA "server1-comp1" + sizeof(DATA), + DATA, +#undef DATA +}; + +krb5_data server2 = { +#define DATA "server1-comp2" + sizeof(DATA), + DATA, +#undef DATA +}; + +int x = 0x12345; +krb5_address addr = { + ADDRTYPE_INET, + 4, + (krb5_octet *) &x, +}; + +krb5_address *addrs[] = { + &addr, + 0, +}; + +krb5_creds test_creds = { + NULL, + NULL, + { + 1, + 1, + (unsigned char *) "1" + }, + { + 1111, + 2222, + 3333, + 4444, + }, + 1, + 5555, + addrs, + { +#define TICKET "This is ticket 1" + sizeof(TICKET), + TICKET, +#undef TICKET + }, + { +#define TICKET "This is ticket 2" + sizeof(TICKET), + TICKET, +#undef TICKET + }, +}; + +void +init_test_cred() +{ + test_creds.client = (krb5_principal) malloc(sizeof(krb5_data *)*3); + test_creds.client[0] = &client1; + test_creds.client[1] = &client2; + test_creds.client[2] = NULL; + + test_creds.server = (krb5_principal) malloc(sizeof(krb5_data *)*3); + test_creds.server[0] = &server1; + test_creds.server[1] = &server2; + test_creds.server[2] = NULL; +} + +#define CHECK(kret,msg) \ + if (kret != KRB5_OK) { \ + com_err(msg, kret, ""); \ + } else printf("%s went ok\n", msg); + +int flags = 0; +void +scc_test() +{ + krb5_ccache id; + krb5_creds creds; + krb5_error_code kret; + krb5_cc_cursor cursor; + + init_test_cred(); + + kret = krb5_scc_resolve(context, &id, "/tmp/tkt_test"); + CHECK(kret, "resolve"); + kret = krb5_scc_initialize(context, id, test_creds.client); + CHECK(kret, "initialize"); + kret = krb5_scc_store(id, &test_creds); + CHECK(kret, "store"); + + kret = krb5_scc_set_flags (id, flags); + CHECK(kret, "set_flags"); + kret = krb5_scc_start_seq_get(id, &cursor); + CHECK(kret, "start_seq_get"); + kret = 0; + while (kret != KRB5_CC_END) { + printf("Calling next_cred\n"); + kret = krb5_scc_next_cred(id, &cursor, &creds); + CHECK(kret, "next_cred"); + } + kret = krb5_scc_end_seq_get(id, &cursor); + CHECK(kret, "end_seq_get"); + + kret = krb5_scc_close(id); + CHECK(kret, "close"); + + + kret = krb5_scc_resolve(&id, "/tmp/tkt_test"); + CHECK(kret, "resolve"); + kret = krb5_scc_destroy(id); + CHECK(kret, "destroy"); +} + +int remove (s) char*s; { return unlink(s); } +int main () { + initialize_krb5_error_table (); + init_test_cred (); + scc_test (); + flags = !flags; + scc_test (); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/deps b/krb5-1.21.3/src/lib/krb5/deps new file mode 100644 index 00000000..6fb333d9 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/deps @@ -0,0 +1,16 @@ +# +# Generated makefile dependencies follow. +# +krb5_libinit.so krb5_libinit.po $(OUTPRE)krb5_libinit.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/ccache/cc-int.h $(srcdir)/keytab/kt-int.h \ + $(srcdir)/os/os-proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + krb5_libinit.c krb5_libinit.h diff --git a/krb5-1.21.3/src/lib/krb5/error_tables/Makefile.in b/krb5-1.21.3/src/lib/krb5/error_tables/Makefile.in new file mode 100644 index 00000000..4e0591ef --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/error_tables/Makefile.in @@ -0,0 +1,63 @@ +mydir=lib$(S)krb5$(S)error_tables +BUILDTOP=$(REL)..$(S)..$(S).. + +##DOS##BUILDTOP = ..\..\.. +##DOS##PREFIXDIR=error_tables +##DOS##OBJFILE=..\$(OUTPRE)err_tbls.lst + +THDRDIR=$(BUILDTOP)$(S)include +EHDRDIR=$(BUILDTOP)$(S)include +ETDIR=$(top_srcdir)$(S)util$(S)et + +STLIBOBJS= asn1_err.o kdb5_err.o krb5_err.o k5e1_err.o \ + kv5m_err.o krb524_err.o + +HDRS= asn1_err.h kdb5_err.h krb5_err.h k5e1_err.h kv5m_err.h krb524_err.h +OBJS= $(OUTPRE)asn1_err.$(OBJEXT) $(OUTPRE)kdb5_err.$(OBJEXT) \ + $(OUTPRE)krb5_err.$(OBJEXT) $(OUTPRE)k5e1_err.$(OBJEXT) \ + $(OUTPRE)kv5m_err.$(OBJEXT) $(OUTPRE)krb524_err.$(OBJEXT) +ETSRCS= asn1_err.c kdb5_err.c krb5_err.c k5e1_err.c kv5m_err.c krb524_err.c +SRCS= asn1_err.c kdb5_err.c krb5_err.c k5e1_err.c kv5m_err.c krb524_err.c + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs +all-libobjs: $(HDRS) + +includes: $(HDRS) + +awk-windows: + $(AWK) -f $(ETDIR)/et_h.awk outfile=asn1_err.h asn1_err.et + $(AWK) -f $(ETDIR)/et_h.awk outfile=kdb5_err.h kdb5_err.et + $(AWK) -f $(ETDIR)/et_h.awk outfile=krb5_err.h krb5_err.et + $(AWK) -f $(ETDIR)/et_h.awk outfile=k5e1_err.h k5e1_err.et + $(AWK) -f $(ETDIR)/et_h.awk outfile=kv5m_err.h kv5m_err.et + $(AWK) -f $(ETDIR)/et_h.awk outfile=krb524_err.h krb524_err.et + $(AWK) -f $(ETDIR)/et_c.awk outfile=asn1_err.c asn1_err.et + $(AWK) -f $(ETDIR)/et_c.awk outfile=kdb5_err.c kdb5_err.et + $(AWK) -f $(ETDIR)/et_c.awk outfile=krb5_err.c krb5_err.et + $(AWK) -f $(ETDIR)/et_c.awk outfile=k5e1_err.c k5e1_err.et + $(AWK) -f $(ETDIR)/et_c.awk outfile=kv5m_err.c kv5m_err.et + $(AWK) -f $(ETDIR)/et_c.awk outfile=krb524_err.c krb524_err.et + if exist asn1_err.h copy asn1_err.h "$(EHDRDIR)" + if exist kdb5_err.h copy kdb5_err.h "$(EHDRDIR)" + if exist krb5_err.h copy krb5_err.h "$(EHDRDIR)" + if exist k5e1_err.h copy k5e1_err.h "$(EHDRDIR)" + if exist kv5m_err.h copy kv5m_err.h "$(EHDRDIR)" + if exist krb524_err.h copy krb524_err.h "$(EHDRDIR)" + +# +# dependencies for traditional makes +# +$(OUTPRE)asn1_err.$(OBJEXT): asn1_err.c +$(OUTPRE)kdb5_err.$(OBJEXT): kdb5_err.c +$(OUTPRE)krb5_err.$(OBJEXT): krb5_err.c +$(OUTPRE)k5e1_err.$(OBJEXT): k5e1_err.c +$(OUTPRE)kv5m_err.$(OBJEXT): kv5m_err.c +$(OUTPRE)krb524_err.$(OBJEXT): krb524_err.c + +clean-unix:: clean-libobjs + $(RM) $(HDRS) $(ETSRCS) + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/krb5/error_tables/asn1_err.et b/krb5-1.21.3/src/lib/krb5/error_tables/asn1_err.et new file mode 100644 index 00000000..a448bb59 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/error_tables/asn1_err.et @@ -0,0 +1,16 @@ +error_table asn1 +error_code ASN1_BAD_TIMEFORMAT, "ASN.1 failed call to system time library" +error_code ASN1_MISSING_FIELD, "ASN.1 structure is missing a required field" +error_code ASN1_MISPLACED_FIELD, "ASN.1 unexpected field number" +error_code ASN1_TYPE_MISMATCH, "ASN.1 type numbers are inconsistent" +error_code ASN1_OVERFLOW, "ASN.1 value too large" +error_code ASN1_OVERRUN, "ASN.1 encoding ended unexpectedly" +error_code ASN1_BAD_ID, "ASN.1 identifier doesn't match expected value" +error_code ASN1_BAD_LENGTH, "ASN.1 length doesn't match expected value" +error_code ASN1_BAD_FORMAT, "ASN.1 badly-formatted encoding" +error_code ASN1_PARSE_ERROR, "ASN.1 parse error" +error_code ASN1_BAD_GMTIME, "ASN.1 bad return from gmtime" +error_code ASN1_INDEF, "ASN.1 indefinite encoding" +error_code ASN1_MISSING_EOC, "ASN.1 missing expected EOC" +error_code ASN1_OMITTED, "ASN.1 object omitted in sequence" +end diff --git a/krb5-1.21.3/src/lib/krb5/error_tables/deps b/krb5-1.21.3/src/lib/krb5/error_tables/deps new file mode 100644 index 00000000..48dbd129 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/error_tables/deps @@ -0,0 +1,15 @@ +# +# Generated makefile dependencies follow. +# +asn1_err.so asn1_err.po $(OUTPRE)asn1_err.$(OBJEXT): \ + $(COM_ERR_DEPS) asn1_err.c +kdb5_err.so kdb5_err.po $(OUTPRE)kdb5_err.$(OBJEXT): \ + $(COM_ERR_DEPS) kdb5_err.c +krb5_err.so krb5_err.po $(OUTPRE)krb5_err.$(OBJEXT): \ + $(COM_ERR_DEPS) krb5_err.c +k5e1_err.so k5e1_err.po $(OUTPRE)k5e1_err.$(OBJEXT): \ + $(COM_ERR_DEPS) k5e1_err.c +kv5m_err.so kv5m_err.po $(OUTPRE)kv5m_err.$(OBJEXT): \ + $(COM_ERR_DEPS) kv5m_err.c +krb524_err.so krb524_err.po $(OUTPRE)krb524_err.$(OBJEXT): \ + $(COM_ERR_DEPS) krb524_err.c diff --git a/krb5-1.21.3/src/lib/krb5/error_tables/init_ets.c b/krb5-1.21.3/src/lib/krb5/error_tables/init_ets.c new file mode 100644 index 00000000..e5e50c7e --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/error_tables/init_ets.c @@ -0,0 +1,48 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/error_tables/init_ets.c - Initialize krb5 library error tables */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +void +krb5_init_ets (krb5_context context) +{ + static int inited = 0; + + if (inited == 0) { + initialize_krb5_error_table(); + initialize_k5e1_error_table(); + initialize_kv5m_error_table(); + initialize_kdb5_error_table(); + initialize_asn1_error_table(); + initialize_k524_error_table(); + inited++; + } +} + +void +krb5_free_ets (krb5_context context) +{ +} diff --git a/krb5-1.21.3/src/lib/krb5/error_tables/k5e1_err.et b/krb5-1.21.3/src/lib/krb5/error_tables/k5e1_err.et new file mode 100644 index 00000000..593d63ea --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/error_tables/k5e1_err.et @@ -0,0 +1,47 @@ +# +# lib/krb5/error_tables/k5e1_err.et +# +# Copyright 2010 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. +# +# +# The Kerberos v5 library error code expansion table (#1). +# This table exists to hold new libkrb5 error codes since the +# original krb5 error table is full. +# +error_table k5e1 + +error_code KRB5_PLUGIN_VER_NOTSUPP, "Plugin does not support interface version" +error_code KRB5_PLUGIN_BAD_MODULE_SPEC, "Invalid module specifier" +error_code KRB5_PLUGIN_NAME_NOTFOUND, "Plugin module name not found" +error_code KRB5KDC_ERR_DISCARD, "The KDC should discard this request" +error_code KRB5_DCC_CANNOT_CREATE, "Can't create new subsidiary cache" +error_code KRB5_KCC_INVALID_ANCHOR, "Invalid keyring anchor name" +error_code KRB5_KCC_UNKNOWN_VERSION, "Unknown keyring collection version" +error_code KRB5_KCC_INVALID_UID, "Invalid UID in persistent keyring name" +error_code KRB5_KCM_MALFORMED_REPLY, "Malformed reply from KCM daemon" +error_code KRB5_KCM_RPC_ERROR, "Mach RPC error communicating with KCM daemon" +error_code KRB5_KCM_REPLY_TOO_BIG, "KCM daemon reply too big" +error_code KRB5_KCM_NO_SERVER, "No KCM server found" +error_code KRB5_CERTAUTH_HWAUTH, "Authorize and set hw-authent ticket flag" +error_code KRB5_CERTAUTH_HWAUTH_PASS, "Set hw-authent ticket flag but do not authorize" +end diff --git a/krb5-1.21.3/src/lib/krb5/error_tables/kdb5_err.et b/krb5-1.21.3/src/lib/krb5/error_tables/kdb5_err.et new file mode 100644 index 00000000..1b08ec1a --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/error_tables/kdb5_err.et @@ -0,0 +1,89 @@ +# +# lib/krb5/error_tables/kdb5_err.et +# +# Copyright 1990, 2008 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. +# +# +# The Kerberos v5 database library error code table. +# +error_table kdb5 + +ec KRB5_KDB_RCSID, "$Id$" +# /* From the server side routines */ +ec KRB5_KDB_INUSE, "Entry already exists in database" +ec KRB5_KDB_UK_SERROR, "Database store error" +ec KRB5_KDB_UK_RERROR, "Database read error" +ec KRB5_KDB_UNAUTH, "Insufficient access to perform requested operation" +# KRB5_KDB_DATA isn't really an error, but... +ec KRB5_KDB_NOENTRY, "No such entry in the database" + +ec KRB5_KDB_ILL_WILDCARD, "Illegal use of wildcard" + +ec KRB5_KDB_DB_INUSE, "Database is locked or in use--try again later" + +ec KRB5_KDB_DB_CHANGED, "Database was modified during read" + +ec KRB5_KDB_TRUNCATED_RECORD, "Database record is incomplete or corrupted" +ec KRB5_KDB_RECURSIVELOCK, "Attempt to lock database twice" +ec KRB5_KDB_NOTLOCKED, "Attempt to unlock database when not locked" +ec KRB5_KDB_BADLOCKMODE, "Invalid kdb lock mode" +ec KRB5_KDB_DBNOTINITED, "Database has not been initialized" +ec KRB5_KDB_DBINITED, "Database has already been initialized" + +ec KRB5_KDB_ILLDIRECTION, "Bad direction for converting keys" + +ec KRB5_KDB_NOMASTERKEY, "Cannot find master key record in database" +ec KRB5_KDB_BADMASTERKEY, "Master key does not match database" +ec KRB5_KDB_INVALIDKEYSIZE, "Key size in database is invalid" +ec KRB5_KDB_CANTREAD_STORED, "Cannot find/read stored master key" +ec KRB5_KDB_BADSTORED_MKEY, "Stored master key is corrupted" +ec KRB5_KDB_NOACTMASTERKEY, "Cannot find active master key" +ec KRB5_KDB_KVNONOMATCH, "KVNO of new master key does not match expected value" +ec KRB5_KDB_STORED_MKEY_NOTCURRENT, "Stored master key is not current" + +ec KRB5_KDB_CANTLOCK_DB, "Insufficient access to lock database" + +ec KRB5_KDB_DB_CORRUPT, "Database format error" +ec KRB5_KDB_BAD_VERSION, "Unsupported version in database entry" + +ec KRB5_KDB_BAD_SALTTYPE, "Unsupported salt type" +ec KRB5_KDB_BAD_ENCTYPE, "Unsupported encryption type" +ec KRB5_KDB_BAD_CREATEFLAGS, "Bad database creation flags" +ec KRB5_KDB_NO_PERMITTED_KEY, "No matching key in entry having a permitted enctype" +ec KRB5_KDB_NO_MATCHING_KEY, "No matching key in entry" +ec KRB5_KDB_DBTYPE_NOTFOUND, "Unable to find requested database type" +ec KRB5_KDB_DBTYPE_NOSUP, "Database type not supported" +ec KRB5_KDB_DBTYPE_INIT, "Database library failed to initialize" +ec KRB5_KDB_SERVER_INTERNAL_ERR, "Server error" +ec KRB5_KDB_ACCESS_ERROR, "Unable to access Kerberos database" +ec KRB5_KDB_INTERNAL_ERROR, "Kerberos database internal error" +ec KRB5_KDB_CONSTRAINT_VIOLATION, "Kerberos database constraints violated" +ec KRB5_LOG_CONV, "Update log conversion error" +ec KRB5_LOG_UNSTABLE, "Update log is unstable" +ec KRB5_LOG_CORRUPT, "Update log is corrupt" +ec KRB5_LOG_ERROR, "Generic update log error" +ec KRB5_KDB_DBTYPE_MISMATCH, "Database module does not match KDC version" +ec KRB5_KDB_POLICY_REF, "Policy is in use" +ec KRB5_KDB_STRINGS_TOOLONG, "Too much string mapping data" + +end diff --git a/krb5-1.21.3/src/lib/krb5/error_tables/krb524_err.et b/krb5-1.21.3/src/lib/krb5/error_tables/krb524_err.et new file mode 100644 index 00000000..5a4a004c --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/error_tables/krb524_err.et @@ -0,0 +1,34 @@ +# Copyright 1994 by OpenVision Technologies, Inc. +# +# Permission to use, copy, modify, distribute, and sell this software +# and its documentation for any purpose is hereby granted without fee, +# provided that the above copyright notice appears in all copies and +# that both that copyright notice and this permission notice appear in +# supporting documentation, and that the name of OpenVision not be used +# in advertising or publicity pertaining to distribution of the software +# without specific, written prior permission. OpenVision makes no +# representations about the suitability of this software for any +# purpose. It is provided "as is" without express or implied warranty. +# +# OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# + +error_table k524 + +error_code KRB524_BADKEY, "Cannot convert V5 keyblock" +error_code KRB524_BADADDR, "Cannot convert V5 address information" +error_code KRB524_BADPRINC, "Cannot convert V5 principal" +error_code KRB524_BADREALM, "V5 realm name longer than V4 maximum" +error_code KRB524_V4ERR, "Kerberos V4 error" +error_code KRB524_ENCFULL, "Encoding too large" +error_code KRB524_DECEMPTY, "Decoding out of data" +error_code KRB524_NOTRESP, "Service not responding" +error_code KRB524_KRB4_DISABLED, "Kerberos version 4 support is disabled" + +end diff --git a/krb5-1.21.3/src/lib/krb5/error_tables/krb5_err.et b/krb5-1.21.3/src/lib/krb5/error_tables/krb5_err.et new file mode 100644 index 00000000..74a576a7 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/error_tables/krb5_err.et @@ -0,0 +1,356 @@ +# +# lib/krb5/error_tables/krb5_err.et +# +# Copyright 1989,1990,1991,2007 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. +# +# +# The Kerberos v5 library error code table. +# Protocol error codes are ERROR_TABLE_BASE_krb5 + the protocol error +# code number; other error codes start at ERROR_TABLE_BASE_krb5 + 128. +# +error_table krb5 + + +# +# Note: the first 128 error codes are hard-coded and must match the error +# numbers defined in the Kerberos protocol specification, RFC-1510 or +# its successors. +# + +# vv 0 +error_code KRB5KDC_ERR_NONE, "No error" +error_code KRB5KDC_ERR_NAME_EXP, "Client's entry in database has expired" +error_code KRB5KDC_ERR_SERVICE_EXP, "Server's entry in database has expired" +error_code KRB5KDC_ERR_BAD_PVNO, "Requested protocol version not supported" +error_code KRB5KDC_ERR_C_OLD_MAST_KVNO, "Client's key is encrypted in an old master key" +error_code KRB5KDC_ERR_S_OLD_MAST_KVNO, "Server's key is encrypted in an old master key" +error_code KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, "Client not found in Kerberos database" +error_code KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, "Server not found in Kerberos database" +error_code KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE, "Principal has multiple entries in Kerberos database" +error_code KRB5KDC_ERR_NULL_KEY, "Client or server has a null key" +error_code KRB5KDC_ERR_CANNOT_POSTDATE, "Ticket is ineligible for postdating" +error_code KRB5KDC_ERR_NEVER_VALID, "Requested effective lifetime is negative or too short" +error_code KRB5KDC_ERR_POLICY, "KDC policy rejects request" +error_code KRB5KDC_ERR_BADOPTION, "KDC can't fulfill requested option" +error_code KRB5KDC_ERR_ETYPE_NOSUPP, "KDC has no support for encryption type" +error_code KRB5KDC_ERR_SUMTYPE_NOSUPP, "KDC has no support for checksum type" +error_code KRB5KDC_ERR_PADATA_TYPE_NOSUPP, "KDC has no support for padata type" +error_code KRB5KDC_ERR_TRTYPE_NOSUPP, "KDC has no support for transited type" +error_code KRB5KDC_ERR_CLIENT_REVOKED, "Client's credentials have been revoked" +error_code KRB5KDC_ERR_SERVICE_REVOKED, "Credentials for server have been revoked" +error_code KRB5KDC_ERR_TGT_REVOKED, "TGT has been revoked" +error_code KRB5KDC_ERR_CLIENT_NOTYET, "Client not yet valid - try again later" +error_code KRB5KDC_ERR_SERVICE_NOTYET, "Server not yet valid - try again later" +error_code KRB5KDC_ERR_KEY_EXP, "Password has expired" +error_code KRB5KDC_ERR_PREAUTH_FAILED, "Preauthentication failed" +# ^^ 24 +error_code KRB5KDC_ERR_PREAUTH_REQUIRED, "Additional pre-authentication required" +error_code KRB5KDC_ERR_SERVER_NOMATCH, "Requested server and ticket don't match" +error_code KRB5KDC_ERR_MUST_USE_USER2USER, "Server principal valid for user2user only" +error_code KRB5KDC_ERR_PATH_NOT_ACCEPTED, "KDC policy rejects transited path" +error_code KRB5KDC_ERR_SVC_UNAVAILABLE, "A service is not available that is required to process the request" +error_code KRB5PLACEHOLD_30, "KRB5 error code 30" +# vv 31 +error_code KRB5KRB_AP_ERR_BAD_INTEGRITY, "Decrypt integrity check failed" +error_code KRB5KRB_AP_ERR_TKT_EXPIRED, "Ticket expired" +error_code KRB5KRB_AP_ERR_TKT_NYV, "Ticket not yet valid" +error_code KRB5KRB_AP_ERR_REPEAT, "Request is a replay" +error_code KRB5KRB_AP_ERR_NOT_US, "The ticket isn't for us" +error_code KRB5KRB_AP_ERR_BADMATCH, "Ticket/authenticator don't match" +error_code KRB5KRB_AP_ERR_SKEW, "Clock skew too great" +error_code KRB5KRB_AP_ERR_BADADDR, "Incorrect net address" +error_code KRB5KRB_AP_ERR_BADVERSION, "Protocol version mismatch" +error_code KRB5KRB_AP_ERR_MSG_TYPE, "Invalid message type" +error_code KRB5KRB_AP_ERR_MODIFIED, "Message stream modified" +error_code KRB5KRB_AP_ERR_BADORDER, "Message out of order" +error_code KRB5KRB_AP_ERR_ILL_CR_TKT, "Illegal cross-realm ticket" +error_code KRB5KRB_AP_ERR_BADKEYVER, "Key version is not available" +error_code KRB5KRB_AP_ERR_NOKEY, "Service key not available" +error_code KRB5KRB_AP_ERR_MUT_FAIL, "Mutual authentication failed" +error_code KRB5KRB_AP_ERR_BADDIRECTION, "Incorrect message direction" +error_code KRB5KRB_AP_ERR_METHOD, "Alternative authentication method required" +error_code KRB5KRB_AP_ERR_BADSEQ, "Incorrect sequence number in message" +error_code KRB5KRB_AP_ERR_INAPP_CKSUM, "Inappropriate type of checksum in message" +#^^ 50 +error_code KRB5KRB_AP_PATH_NOT_ACCEPTED, "Policy rejects transited path" +error_code KRB5KRB_ERR_RESPONSE_TOO_BIG, "Response too big for UDP, retry with TCP" +error_code KRB5PLACEHOLD_53, "KRB5 error code 53" +error_code KRB5PLACEHOLD_54, "KRB5 error code 54" +error_code KRB5PLACEHOLD_55, "KRB5 error code 55" +error_code KRB5PLACEHOLD_56, "KRB5 error code 56" +error_code KRB5PLACEHOLD_57, "KRB5 error code 57" +error_code KRB5PLACEHOLD_58, "KRB5 error code 58" +error_code KRB5PLACEHOLD_59, "KRB5 error code 59" +error_code KRB5KRB_ERR_GENERIC, "Generic error (see e-text)" +error_code KRB5KRB_ERR_FIELD_TOOLONG, "Field is too long for this implementation" +error_code KRB5KDC_ERR_CLIENT_NOT_TRUSTED, "Client not trusted" +error_code KRB5KDC_ERR_KDC_NOT_TRUSTED, "KDC not trusted" +error_code KRB5KDC_ERR_INVALID_SIG, "Invalid signature" +error_code KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED, "Key parameters not accepted" +error_code KRB5KDC_ERR_CERTIFICATE_MISMATCH, "Certificate mismatch" +error_code KRB5KRB_AP_ERR_NO_TGT, "No ticket granting ticket" +error_code KRB5KDC_ERR_WRONG_REALM, "Realm not local to KDC" +error_code KRB5KRB_AP_ERR_USER_TO_USER_REQUIRED, "User to user required" +error_code KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE, "Can't verify certificate" +error_code KRB5KDC_ERR_INVALID_CERTIFICATE, "Invalid certificate" +error_code KRB5KDC_ERR_REVOKED_CERTIFICATE, "Revoked certificate" +error_code KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN, "Revocation status unknown" +error_code KRB5KDC_ERR_REVOCATION_STATUS_UNAVAILABLE, "Revocation status unavailable" +error_code KRB5KDC_ERR_CLIENT_NAME_MISMATCH, "Client name mismatch" +error_code KRB5KDC_ERR_KDC_NAME_MISMATCH, "KDC name mismatch" +error_code KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE, "Inconsistent key purpose" +error_code KRB5KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED, "Digest in certificate not accepted" +error_code KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED, "Checksum must be included" +error_code KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED, "Digest in signed-data not accepted" +error_code KRB5KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not supported" +error_code KRB5PLACEHOLD_82, "KRB5 error code 82" +error_code KRB5PLACEHOLD_83, "KRB5 error code 83" +error_code KRB5PLACEHOLD_84, "KRB5 error code 84" +error_code KRB5KRB_AP_ERR_IAKERB_KDC_NOT_FOUND, "The IAKERB proxy could not find a KDC" +error_code KRB5KRB_AP_ERR_IAKERB_KDC_NO_RESPONSE, "The KDC did not respond to the IAKERB proxy" +error_code KRB5PLACEHOLD_87, "KRB5 error code 87" +error_code KRB5PLACEHOLD_88, "KRB5 error code 88" +error_code KRB5PLACEHOLD_89, "KRB5 error code 89" +error_code KRB5KDC_ERR_PREAUTH_EXPIRED, "Preauthentication expired" +error_code KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, "More preauthentication data is required" +error_code KRB5PLACEHOLD_92, "KRB5 error code 92" +error_code KRB5KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTION, "An unsupported critical FAST option was requested" +error_code KRB5PLACEHOLD_94, "KRB5 error code 94" +error_code KRB5PLACEHOLD_95, "KRB5 error code 95" +error_code KRB5PLACEHOLD_96, "KRB5 error code 96" +error_code KRB5PLACEHOLD_97, "KRB5 error code 97" +error_code KRB5PLACEHOLD_98, "KRB5 error code 98" +error_code KRB5PLACEHOLD_99, "KRB5 error code 99" +error_code KRB5KDC_ERR_NO_ACCEPTABLE_KDF, "No acceptable KDF offered" +error_code KRB5PLACEHOLD_101, "KRB5 error code 101" +error_code KRB5PLACEHOLD_102, "KRB5 error code 102" +error_code KRB5PLACEHOLD_103, "KRB5 error code 103" +error_code KRB5PLACEHOLD_104, "KRB5 error code 104" +error_code KRB5PLACEHOLD_105, "KRB5 error code 105" +error_code KRB5PLACEHOLD_106, "KRB5 error code 106" +error_code KRB5PLACEHOLD_107, "KRB5 error code 107" +error_code KRB5PLACEHOLD_108, "KRB5 error code 108" +error_code KRB5PLACEHOLD_109, "KRB5 error code 109" +error_code KRB5PLACEHOLD_110, "KRB5 error code 110" +error_code KRB5PLACEHOLD_111, "KRB5 error code 111" +error_code KRB5PLACEHOLD_112, "KRB5 error code 112" +error_code KRB5PLACEHOLD_113, "KRB5 error code 113" +error_code KRB5PLACEHOLD_114, "KRB5 error code 114" +error_code KRB5PLACEHOLD_115, "KRB5 error code 115" +error_code KRB5PLACEHOLD_116, "KRB5 error code 116" +error_code KRB5PLACEHOLD_117, "KRB5 error code 117" +error_code KRB5PLACEHOLD_118, "KRB5 error code 118" +error_code KRB5PLACEHOLD_119, "KRB5 error code 119" +error_code KRB5PLACEHOLD_120, "KRB5 error code 120" +error_code KRB5PLACEHOLD_121, "KRB5 error code 121" +error_code KRB5PLACEHOLD_122, "KRB5 error code 122" +error_code KRB5PLACEHOLD_123, "KRB5 error code 123" +error_code KRB5PLACEHOLD_124, "KRB5 error code 124" +error_code KRB5PLACEHOLD_125, "KRB5 error code 125" +error_code KRB5PLACEHOLD_126, "KRB5 error code 126" +error_code KRB5PLACEHOLD_127, "KRB5 error code 127" + +error_code KRB5_ERR_RCSID, "$Id$" + +error_code KRB5_LIBOS_BADLOCKFLAG, "Invalid flag for file lock mode" +error_code KRB5_LIBOS_CANTREADPWD, "Cannot read password" +error_code KRB5_LIBOS_BADPWDMATCH, "Password mismatch" +error_code KRB5_LIBOS_PWDINTR, "Password read interrupted" + +error_code KRB5_PARSE_ILLCHAR, "Illegal character in component name" +error_code KRB5_PARSE_MALFORMED, "Malformed representation of principal" + +error_code KRB5_CONFIG_CANTOPEN, "Can't open/find Kerberos configuration file" +error_code KRB5_CONFIG_BADFORMAT, "Improper format of Kerberos configuration file" +error_code KRB5_CONFIG_NOTENUFSPACE, "Insufficient space to return complete information" + +error_code KRB5_BADMSGTYPE, "Invalid message type specified for encoding" + +error_code KRB5_CC_BADNAME, "Credential cache name malformed" +error_code KRB5_CC_UNKNOWN_TYPE, "Unknown credential cache type" +error_code KRB5_CC_NOTFOUND, "Matching credential not found" +error_code KRB5_CC_END, "End of credential cache reached" + +error_code KRB5_NO_TKT_SUPPLIED, "Request did not supply a ticket" + +error_code KRB5KRB_AP_WRONG_PRINC, "Wrong principal in request" +error_code KRB5KRB_AP_ERR_TKT_INVALID, "Ticket has invalid flag set" + +error_code KRB5_PRINC_NOMATCH, "Requested principal and ticket don't match" +error_code KRB5_KDCREP_MODIFIED, "KDC reply did not match expectations" +error_code KRB5_KDCREP_SKEW, "Clock skew too great in KDC reply" +error_code KRB5_IN_TKT_REALM_MISMATCH, "Client/server realm mismatch in initial ticket request" + +error_code KRB5_PROG_ETYPE_NOSUPP, "Program lacks support for encryption type" +error_code KRB5_PROG_KEYTYPE_NOSUPP, "Program lacks support for key type" +error_code KRB5_WRONG_ETYPE, "Requested encryption type not used in message" +error_code KRB5_PROG_SUMTYPE_NOSUPP, "Program lacks support for checksum type" + +error_code KRB5_REALM_UNKNOWN, "Cannot find KDC for requested realm" +error_code KRB5_SERVICE_UNKNOWN, "Kerberos service unknown" +error_code KRB5_KDC_UNREACH, "Cannot contact any KDC for requested realm" +error_code KRB5_NO_LOCALNAME, "No local name found for principal name" + +error_code KRB5_MUTUAL_FAILED, "Mutual authentication failed" + +# some of these should be combined/supplanted by system codes + +error_code KRB5_RC_TYPE_EXISTS, "Replay cache type is already registered" +error_code KRB5_RC_MALLOC, "No more memory to allocate (in replay cache code)" +error_code KRB5_RC_TYPE_NOTFOUND, "Replay cache type is unknown" +error_code KRB5_RC_UNKNOWN, "Generic unknown RC error" +error_code KRB5_RC_REPLAY, "Message is a replay" +error_code KRB5_RC_IO, "Replay cache I/O operation failed" +error_code KRB5_RC_NOIO, "Replay cache type does not support non-volatile storage" +error_code KRB5_RC_PARSE, "Replay cache name parse/format error" + +error_code KRB5_RC_IO_EOF, "End-of-file on replay cache I/O" +error_code KRB5_RC_IO_MALLOC, "No more memory to allocate (in replay cache I/O code)" +error_code KRB5_RC_IO_PERM, "Permission denied in replay cache code" +error_code KRB5_RC_IO_IO, "I/O error in replay cache i/o code" +error_code KRB5_RC_IO_UNKNOWN, "Generic unknown RC/IO error" +error_code KRB5_RC_IO_SPACE, "Insufficient system space to store replay information" + +error_code KRB5_TRANS_CANTOPEN, "Can't open/find realm translation file" +error_code KRB5_TRANS_BADFORMAT, "Improper format of realm translation file" + +error_code KRB5_LNAME_CANTOPEN, "Can't open/find lname translation database" +error_code KRB5_LNAME_NOTRANS, "No translation available for requested principal" +error_code KRB5_LNAME_BADFORMAT, "Improper format of translation database entry" + +error_code KRB5_CRYPTO_INTERNAL, "Cryptosystem internal error" + +error_code KRB5_KT_BADNAME, "Key table name malformed" +error_code KRB5_KT_UNKNOWN_TYPE, "Unknown Key table type" +error_code KRB5_KT_NOTFOUND, "Key table entry not found" +error_code KRB5_KT_END, "End of key table reached" +error_code KRB5_KT_NOWRITE, "Cannot write to specified key table" +error_code KRB5_KT_IOERR, "Error writing to key table" + +error_code KRB5_NO_TKT_IN_RLM, "Cannot find ticket for requested realm" +error_code KRB5DES_BAD_KEYPAR, "DES key has bad parity" +error_code KRB5DES_WEAK_KEY, "DES key is a weak key" + +error_code KRB5_BAD_ENCTYPE, "Bad encryption type" +error_code KRB5_BAD_KEYSIZE, "Key size is incompatible with encryption type" +error_code KRB5_BAD_MSIZE, "Message size is incompatible with encryption type" + +error_code KRB5_CC_TYPE_EXISTS, "Credentials cache type is already registered." +error_code KRB5_KT_TYPE_EXISTS, "Key table type is already registered." + +error_code KRB5_CC_IO, "Credentials cache I/O operation failed" +error_code KRB5_FCC_PERM, "Credentials cache permissions incorrect" +error_code KRB5_FCC_NOFILE, "No credentials cache found" +error_code KRB5_FCC_INTERNAL, "Internal credentials cache error" +error_code KRB5_CC_WRITE, "Error writing to credentials cache" +error_code KRB5_CC_NOMEM, "No more memory to allocate (in credentials cache code)" +error_code KRB5_CC_FORMAT, "Bad format in credentials cache" +error_code KRB5_CC_NOT_KTYPE, "No credentials found with supported encryption types" + +# errors for dual tgt library calls +error_code KRB5_INVALID_FLAGS, "Invalid KDC option combination (library internal error)" +error_code KRB5_NO_2ND_TKT, "Request missing second ticket" + +error_code KRB5_NOCREDS_SUPPLIED, "No credentials supplied to library routine" + +# errors for sendauth (and recvauth) + +error_code KRB5_SENDAUTH_BADAUTHVERS, "Bad sendauth version was sent" +error_code KRB5_SENDAUTH_BADAPPLVERS, "Bad application version was sent (via sendauth)" +error_code KRB5_SENDAUTH_BADRESPONSE, "Bad response (during sendauth exchange)" +error_code KRB5_SENDAUTH_REJECTED, "Server rejected authentication (during sendauth exchange)" + +# errors for preauthentication + +error_code KRB5_PREAUTH_BAD_TYPE, "Unsupported preauthentication type" +error_code KRB5_PREAUTH_NO_KEY, "Required preauthentication key not supplied" +error_code KRB5_PREAUTH_FAILED, "Generic preauthentication failure" + +# version number errors + +error_code KRB5_RCACHE_BADVNO, "Unsupported replay cache format version number" +error_code KRB5_CCACHE_BADVNO, "Unsupported credentials cache format version number" +error_code KRB5_KEYTAB_BADVNO, "Unsupported key table format version number" + +# +# + +error_code KRB5_PROG_ATYPE_NOSUPP, "Program lacks support for address type" +error_code KRB5_RC_REQUIRED, "Message replay detection requires rcache parameter" +error_code KRB5_ERR_BAD_HOSTNAME, "Hostname cannot be canonicalized" +error_code KRB5_ERR_HOST_REALM_UNKNOWN, "Cannot determine realm for host" +error_code KRB5_SNAME_UNSUPP_NAMETYPE, "Conversion to service principal undefined for name type" + +error_code KRB5KRB_AP_ERR_V4_REPLY, "Initial Ticket response appears to be Version 4 error" +error_code KRB5_REALM_CANT_RESOLVE, "Cannot resolve network address for KDC in requested realm" +error_code KRB5_TKT_NOT_FORWARDABLE, "Requesting ticket can't get forwardable tickets" +error_code KRB5_FWD_BAD_PRINCIPAL, "Bad principal name while trying to forward credentials" + +error_code KRB5_GET_IN_TKT_LOOP, "Looping detected inside krb5_get_in_tkt" +error_code KRB5_CONFIG_NODEFREALM, "Configuration file does not specify default realm" + +error_code KRB5_SAM_UNSUPPORTED, "Bad SAM flags in obtain_sam_padata" +error_code KRB5_SAM_INVALID_ETYPE, "Invalid encryption type in SAM challenge" +error_code KRB5_SAM_NO_CHECKSUM, "Missing checksum in SAM challenge" +error_code KRB5_SAM_BAD_CHECKSUM, "Bad checksum in SAM challenge" +error_code KRB5_KT_NAME_TOOLONG, "Keytab name too long" +error_code KRB5_KT_KVNONOTFOUND, "Key version number for principal in key table is incorrect" +error_code KRB5_APPL_EXPIRED, "This application has expired" +error_code KRB5_LIB_EXPIRED, "This Krb5 library has expired" + +error_code KRB5_CHPW_PWDNULL, "New password cannot be zero length" +error_code KRB5_CHPW_FAIL, "Password change failed" +error_code KRB5_KT_FORMAT, "Bad format in keytab" + +error_code KRB5_NOPERM_ETYPE, "Encryption type not permitted" +error_code KRB5_CONFIG_ETYPE_NOSUPP, "No supported encryption types (config file error?)" +error_code KRB5_OBSOLETE_FN, "Program called an obsolete, deleted function" + +# translated versions of getaddrinfo errors +error_code KRB5_EAI_FAIL, "unknown getaddrinfo failure" +error_code KRB5_EAI_NODATA, "no data available for host/domain name" +error_code KRB5_EAI_NONAME, "host/domain name not found" +error_code KRB5_EAI_SERVICE, "service name unknown" + +error_code KRB5_ERR_NUMERIC_REALM, "Cannot determine realm for numeric host address" + +error_code KRB5_ERR_BAD_S2K_PARAMS, "Invalid key generation parameters from KDC" + +error_code KRB5_ERR_NO_SERVICE, "service not available" + +error_code KRB5_CC_READONLY, "Ccache function not supported: read-only ccache type" +error_code KRB5_CC_NOSUPP, "Ccache function not supported: not implemented" + +error_code KRB5_DELTAT_BADFORMAT, "Invalid format of Kerberos lifetime or clock skew string" + +error_code KRB5_PLUGIN_NO_HANDLE, "Supplied data not handled by this plugin" +error_code KRB5_PLUGIN_OP_NOTSUPP, "Plugin does not support the operation" + +error_code KRB5_ERR_INVALID_UTF8, "Invalid UTF-8 string" +error_code KRB5_ERR_FAST_REQUIRED, "FAST protected pre-authentication required but not supported by KDC" + +error_code KRB5_LOCAL_ADDR_REQUIRED, "Auth context must contain local address" +error_code KRB5_REMOTE_ADDR_REQUIRED, "Auth context must contain remote address" + +error_code KRB5_TRACE_NOSUPP, "Tracing unsupported" +end diff --git a/krb5-1.21.3/src/lib/krb5/error_tables/kv5m_err.et b/krb5-1.21.3/src/lib/krb5/error_tables/kv5m_err.et new file mode 100644 index 00000000..6259adab --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/error_tables/kv5m_err.et @@ -0,0 +1,93 @@ +# +# src/lib/krb5/kv5m_err.et +# +# Copyright 1994 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. +# +# +# The Kerberos v5 magic numbers errorcode table + +error_table kv5m + +error_code KV5M_NONE, "Kerberos V5 magic number table" +error_code KV5M_PRINCIPAL, "Bad magic number for krb5_principal structure" +error_code KV5M_DATA, "Bad magic number for krb5_data structure" +error_code KV5M_KEYBLOCK, "Bad magic number for krb5_keyblock structure" +error_code KV5M_CHECKSUM, "Bad magic number for krb5_checksum structure" +error_code KV5M_ENCRYPT_BLOCK, "Bad magic number for krb5_encrypt_block structure" +error_code KV5M_ENC_DATA, "Bad magic number for krb5_enc_data structure" +error_code KV5M_CRYPTOSYSTEM_ENTRY, "Bad magic number for krb5_cryptosystem_entry structure" +error_code KV5M_CS_TABLE_ENTRY, "Bad magic number for krb5_cs_table_entry structure" +error_code KV5M_CHECKSUM_ENTRY, "Bad magic number for krb5_checksum_entry structure" + +error_code KV5M_AUTHDATA, "Bad magic number for krb5_authdata structure" +error_code KV5M_TRANSITED, "Bad magic number for krb5_transited structure" +error_code KV5M_ENC_TKT_PART, "Bad magic number for krb5_enc_tkt_part structure" +error_code KV5M_TICKET, "Bad magic number for krb5_ticket structure" +error_code KV5M_AUTHENTICATOR, "Bad magic number for krb5_authenticator structure" +error_code KV5M_TKT_AUTHENT, "Bad magic number for krb5_tkt_authent structure" +error_code KV5M_CREDS, "Bad magic number for krb5_creds structure" +error_code KV5M_LAST_REQ_ENTRY, "Bad magic number for krb5_last_req_entry structure" +error_code KV5M_PA_DATA, "Bad magic number for krb5_pa_data structure" +error_code KV5M_KDC_REQ, "Bad magic number for krb5_kdc_req structure" +error_code KV5M_ENC_KDC_REP_PART, "Bad magic number for krb5_enc_kdc_rep_part structure" +error_code KV5M_KDC_REP, "Bad magic number for krb5_kdc_rep structure" +error_code KV5M_ERROR, "Bad magic number for krb5_error structure" +error_code KV5M_AP_REQ, "Bad magic number for krb5_ap_req structure" +error_code KV5M_AP_REP, "Bad magic number for krb5_ap_rep structure" +error_code KV5M_AP_REP_ENC_PART, "Bad magic number for krb5_ap_rep_enc_part structure" +error_code KV5M_RESPONSE, "Bad magic number for krb5_response structure" +error_code KV5M_SAFE, "Bad magic number for krb5_safe structure" +error_code KV5M_PRIV, "Bad magic number for krb5_priv structure" +error_code KV5M_PRIV_ENC_PART, "Bad magic number for krb5_priv_enc_part structure" +error_code KV5M_CRED, "Bad magic number for krb5_cred structure" +error_code KV5M_CRED_INFO, "Bad magic number for krb5_cred_info structure" +error_code KV5M_CRED_ENC_PART, "Bad magic number for krb5_cred_enc_part structure" +error_code KV5M_PWD_DATA, "Bad magic number for krb5_pwd_data structure" +error_code KV5M_ADDRESS, "Bad magic number for krb5_address structure" +error_code KV5M_KEYTAB_ENTRY, "Bad magic number for krb5_keytab_entry structure" +error_code KV5M_CONTEXT, "Bad magic number for krb5_context structure" +error_code KV5M_OS_CONTEXT, "Bad magic number for krb5_os_context structure" +error_code KV5M_ALT_METHOD, "Bad magic number for krb5_alt_method structure" +error_code KV5M_ETYPE_INFO_ENTRY, "Bad magic number for krb5_etype_info_entry structure" +error_code KV5M_DB_CONTEXT, "Bad magic number for krb5_db_context structure" +error_code KV5M_AUTH_CONTEXT, "Bad magic number for krb5_auth_context structure" +error_code KV5M_KEYTAB, "Bad magic number for krb5_keytab structure" +error_code KV5M_RCACHE, "Bad magic number for krb5_rcache structure" +error_code KV5M_CCACHE, "Bad magic number for krb5_ccache structure" +error_code KV5M_PREAUTH_OPS, "Bad magic number for krb5_preauth_ops" +error_code KV5M_SAM_CHALLENGE, "Bad magic number for krb5_sam_challenge" +error_code KV5M_SAM_CHALLENGE_2, "Bad magic number for krb5_sam_challenge_2" +error_code KV5M_SAM_KEY, "Bad magic number for krb5_sam_key" +error_code KV5M_ENC_SAM_RESPONSE_ENC, "Bad magic number for krb5_enc_sam_response_enc" +error_code KV5M_ENC_SAM_RESPONSE_ENC_2, "Bad magic number for krb5_enc_sam_response_enc" +error_code KV5M_SAM_RESPONSE, "Bad magic number for krb5_sam_response" +error_code KV5M_SAM_RESPONSE_2, "Bad magic number for krb5_sam_response 2" +error_code KV5M_PREDICTED_SAM_RESPONSE, "Bad magic number for krb5_predicted_sam_response" +error_code KV5M_PASSWD_PHRASE_ELEMENT, "Bad magic number for passwd_phrase_element" +error_code KV5M_GSS_OID, "Bad magic number for GSSAPI OID" +error_code KV5M_GSS_QUEUE, "Bad magic number for GSSAPI QUEUE" +error_code KV5M_FAST_ARMORED_REQ, "Bad magic number for fast armored request" +error_code KV5M_FAST_REQ, "Bad magic number for FAST request" +error_code KV5M_FAST_RESPONSE, "Bad magic number for FAST response" +error_code KV5M_AUTHDATA_CONTEXT, "Bad magic number for krb5_authdata_context" +end diff --git a/krb5-1.21.3/src/lib/krb5/keytab/Makefile.in b/krb5-1.21.3/src/lib/krb5/keytab/Makefile.in new file mode 100644 index 00000000..4621bf71 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/keytab/Makefile.in @@ -0,0 +1,69 @@ +mydir=lib$(S)krb5$(S)keytab +BUILDTOP=$(REL)..$(S)..$(S).. + +##DOS##BUILDTOP = ..\..\.. +##DOS##PREFIXDIR=keytab +##DOS##OBJFILE=..\$(OUTPRE)$(PREFIXDIR).lst + +STLIBOBJS= \ + ktadd.o \ + ktbase.o \ + ktdefault.o \ + ktfr_entry.o \ + ktremove.o \ + ktfns.o \ + kt_file.o \ + kt_memory.o \ + read_servi.o + +OBJS= \ + $(OUTPRE)ktadd.$(OBJEXT) \ + $(OUTPRE)ktbase.$(OBJEXT) \ + $(OUTPRE)ktdefault.$(OBJEXT) \ + $(OUTPRE)ktfr_entry.$(OBJEXT) \ + $(OUTPRE)ktremove.$(OBJEXT) \ + $(OUTPRE)ktfns.$(OBJEXT) \ + $(OUTPRE)kt_file.$(OBJEXT) \ + $(OUTPRE)kt_memory.$(OBJEXT) \ + $(OUTPRE)read_servi.$(OBJEXT) + +SRCS= \ + $(srcdir)/ktadd.c \ + $(srcdir)/ktbase.c \ + $(srcdir)/ktdefault.c \ + $(srcdir)/ktfr_entry.c \ + $(srcdir)/ktremove.c \ + $(srcdir)/ktfns.c \ + $(srcdir)/kt_file.c \ + $(srcdir)/kt_memory.c \ + $(srcdir)/read_servi.c + +EXTRADEPSRCS= \ + $(srcdir)/t_keytab.c + +all-windows: $(OBJFILE) + +##DOS$(OBJFILE): $(OBJS) +##DOS $(RM) $(OBJFILE) +##WIN32## $(LIBECHO) -p $(PREFIXDIR)\ $(OUTPRE)*.obj > $(OBJFILE) + +all-unix: all-libobjs +clean-unix:: clean-libobjs + +check-unix: t_keytab + $(RUN_TEST) ./t_keytab + +T_KEYTAB_OBJS = t_keytab.o +t_keytab: $(T_KEYTAB_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ $(T_KEYTAB_OBJS) $(KRB5_BASE_LIBS) + +clean-unix:: + $(RM) t_keytab t_keytab.o + +clean-windows:: + @echo Making clean in krb5\keytab + $(RM) $(OBJFILE) + + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/krb5/keytab/deps b/krb5-1.21.3/src/lib/krb5/keytab/deps new file mode 100644 index 00000000..8ae40759 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/keytab/deps @@ -0,0 +1,113 @@ +# +# Generated makefile dependencies follow. +# +ktadd.so ktadd.po $(OUTPRE)ktadd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h ktadd.c +ktbase.so ktbase.po $(OUTPRE)ktbase.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kt-int.h ktbase.c +ktdefault.so ktdefault.po $(OUTPRE)ktdefault.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ktdefault.c +ktfr_entry.so ktfr_entry.po $(OUTPRE)ktfr_entry.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ktfr_entry.c +ktremove.so ktremove.po $(OUTPRE)ktremove.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ktremove.c +ktfns.so ktfns.po $(OUTPRE)ktfns.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../krb/int-proto.h \ + $(srcdir)/../os/os-proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ktfns.c +kt_file.so kt_file.po $(OUTPRE)kt_file.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kt_file.c +kt_memory.so kt_memory.po $(OUTPRE)kt_memory.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kt-int.h kt_memory.c +read_servi.so read_servi.po $(OUTPRE)read_servi.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + read_servi.c +t_keytab.so t_keytab.po $(OUTPRE)t_keytab.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_keytab.c diff --git a/krb5-1.21.3/src/lib/krb5/keytab/kt-int.h b/krb5-1.21.3/src/lib/krb5/keytab/kt-int.h new file mode 100644 index 00000000..b55118e2 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/keytab/kt-int.h @@ -0,0 +1,47 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/keytab/kt-int.h */ +/* + * Copyright 2004 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * This file contains constant and function declarations used in the + * file-based credential cache routines. + */ + +#ifndef __KRB5_KEYTAB_INT_H__ +#define __KRB5_KEYTAB_INT_H__ + + +int krb5int_kt_initialize(void); + +void krb5int_kt_finalize(void); + +int krb5int_mkt_initialize(void); + +void krb5int_mkt_finalize(void); + +extern const krb5_kt_ops krb5_kt_dfl_ops; + +#endif /* __KRB5_KEYTAB_INT_H__ */ diff --git a/krb5-1.21.3/src/lib/krb5/keytab/kt_file.c b/krb5-1.21.3/src/lib/krb5/keytab/kt_file.c new file mode 100644 index 00000000..e510211f --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/keytab/kt_file.c @@ -0,0 +1,1382 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/keytab/kt_file.c */ +/* + * Copyright 1990,1991,1995,2007,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (c) Hewlett-Packard Company 1991 + * Released to the Massachusetts Institute of Technology for inclusion + * in the Kerberos source code distribution. + * + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef LEAN_CLIENT + +#include "k5-int.h" +#include "../os/os-proto.h" +#include + +/* + * Information needed by internal routines of the file-based ticket + * cache implementation. + */ + + +/* + * Constants + */ + +#define KRB5_KT_VNO_1 0x0501 /* krb v5, keytab version 1 (DCE compat) */ +#define KRB5_KT_VNO 0x0502 /* krb v5, keytab version 2 (standard) */ + +#define KRB5_KT_DEFAULT_VNO KRB5_KT_VNO + +/* + * Types + */ +typedef struct _krb5_ktfile_data { + char *name; /* Name of the file */ + FILE *openf; /* open file, if any. */ + char iobuf[BUFSIZ]; /* so we can zap it later */ + int version; /* Version number of keytab */ + unsigned int iter_count; /* Number of active iterators */ + long start_offset; /* Starting offset after version */ + k5_mutex_t lock; /* Protect openf, version */ +} krb5_ktfile_data; + +/* + * Some limitations: + * + * If the file OPENF is left open between calls, we have an iterator + * active, and OPENF is opened in read-only mode. So, no changes + * can be made via that handle. + * + * An advisory file lock is used while the file is open. Thus, + * multiple handles on the same underlying file cannot be used without + * disrupting the locking in effect. + * + * The start_offset field is only valid if the file is open. It will + * almost certainly always be the same constant. It's used so that + * if an iterator is active, and we start another one, we don't have + * to seek back to the start and re-read the version number to set + * the position for the iterator. + */ + +/* + * Macros + */ +#define KTPRIVATE(id) ((krb5_ktfile_data *)(id)->data) +#define KTFILENAME(id) (((krb5_ktfile_data *)(id)->data)->name) +#define KTFILEP(id) (((krb5_ktfile_data *)(id)->data)->openf) +#define KTFILEBUFP(id) (((krb5_ktfile_data *)(id)->data)->iobuf) +#define KTVERSION(id) (((krb5_ktfile_data *)(id)->data)->version) +#define KTITERS(id) (((krb5_ktfile_data *)(id)->data)->iter_count) +#define KTSTARTOFF(id) (((krb5_ktfile_data *)(id)->data)->start_offset) +#define KTLOCK(id) k5_mutex_lock(&((krb5_ktfile_data *)(id)->data)->lock) +#define KTUNLOCK(id) k5_mutex_unlock(&((krb5_ktfile_data *)(id)->data)->lock) +#define KTCHECKLOCK(id) k5_mutex_assert_locked(&((krb5_ktfile_data *)(id)->data)->lock) + +extern const struct _krb5_kt_ops krb5_ktf_ops; +extern const struct _krb5_kt_ops krb5_ktf_writable_ops; + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_resolve(krb5_context, const char *, krb5_keytab *); + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_get_name(krb5_context, krb5_keytab, char *, unsigned int); + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_close(krb5_context, krb5_keytab); + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_get_entry(krb5_context, krb5_keytab, krb5_const_principal, + krb5_kvno, krb5_enctype, krb5_keytab_entry *); + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_start_seq_get(krb5_context, krb5_keytab, krb5_kt_cursor *); + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_get_next(krb5_context, krb5_keytab, krb5_keytab_entry *, + krb5_kt_cursor *); + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_end_get(krb5_context, krb5_keytab, krb5_kt_cursor *); + +/* routines to be included on extended version (write routines) */ +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_add(krb5_context, krb5_keytab, krb5_keytab_entry *); + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_remove(krb5_context, krb5_keytab, krb5_keytab_entry *); + +static krb5_error_code +krb5_ktfileint_openr(krb5_context, krb5_keytab); + +static krb5_error_code +krb5_ktfileint_openw(krb5_context, krb5_keytab); + +static krb5_error_code +krb5_ktfileint_close(krb5_context, krb5_keytab); + +static krb5_error_code +krb5_ktfileint_read_entry(krb5_context, krb5_keytab, krb5_keytab_entry *); + +static krb5_error_code +krb5_ktfileint_write_entry(krb5_context, krb5_keytab, krb5_keytab_entry *); + +static krb5_error_code +krb5_ktfileint_delete_entry(krb5_context, krb5_keytab, krb5_int32); + +static krb5_error_code +krb5_ktfileint_internal_read_entry(krb5_context, krb5_keytab, + krb5_keytab_entry *, krb5_int32 *); + +static krb5_error_code +krb5_ktfileint_size_entry(krb5_context, krb5_keytab_entry *, krb5_int32 *); + +static krb5_error_code +krb5_ktfileint_find_slot(krb5_context, krb5_keytab, krb5_int32 *, + krb5_int32 *); + + +/* + * This is an implementation specific resolver. It returns a keytab id + * initialized with file keytab routines. + */ + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_resolve(krb5_context context, const char *name, + krb5_keytab *id_out) +{ + krb5_ktfile_data *data = NULL; + krb5_error_code err = ENOMEM; + krb5_keytab id; + + *id_out = NULL; + + id = calloc(1, sizeof(*id)); + if (id == NULL) + return ENOMEM; + + id->ops = &krb5_ktf_ops; + data = calloc(1, sizeof(krb5_ktfile_data)); + if (data == NULL) + goto cleanup; + + data->name = strdup(name); + if (data->name == NULL) + goto cleanup; + + err = k5_mutex_init(&data->lock); + if (err) + goto cleanup; + + data->openf = 0; + data->version = 0; + data->iter_count = 0; + + id->data = (krb5_pointer) data; + id->magic = KV5M_KEYTAB; + *id_out = id; + return 0; +cleanup: + if (data) + free(data->name); + free(data); + free(id); + return err; +} + + +/* + * "Close" a file-based keytab and invalidate the id. This means + * free memory hidden in the structures. + */ + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_close(krb5_context context, krb5_keytab id) +/* + * This routine is responsible for freeing all memory allocated + * for this keytab. There are no system resources that need + * to be freed nor are there any open files. + * + * This routine should undo anything done by krb5_ktfile_resolve(). + */ +{ + free(KTFILENAME(id)); + zap(KTFILEBUFP(id), BUFSIZ); + k5_mutex_destroy(&((krb5_ktfile_data *)id->data)->lock); + free(id->data); + id->ops = 0; + free(id); + return (0); +} + +/* Return true if k1 is more recent than k2, applying wraparound heuristics. */ +static krb5_boolean +more_recent(const krb5_keytab_entry *k1, const krb5_keytab_entry *k2) +{ + /* + * If a small kvno was written at the same time or later than a large kvno, + * the kvno probably wrapped at some boundary, so consider the small kvno + * more recent. Wraparound can happen due to pre-1.14 keytab file format + * limitations (8-bit kvno storage), pre-1.14 kadmin protocol limitations + * (8-bit kvno marshalling), or KDB limitations (16-bit kvno storage). + */ + if (!ts_after(k2->timestamp, k1->timestamp) && + k1->vno < 128 && k2->vno > 240) + return TRUE; + if (!ts_after(k1->timestamp, k2->timestamp) && + k1->vno > 240 && k2->vno < 128) + return FALSE; + + /* Otherwise do a simple version comparison. */ + return k1->vno > k2->vno; +} + +/* + * This is the get_entry routine for the file based keytab implementation. + * It opens the keytab file, and either retrieves the entry or returns + * an error. + */ + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_get_entry(krb5_context context, krb5_keytab id, + krb5_const_principal principal, krb5_kvno kvno, + krb5_enctype enctype, krb5_keytab_entry *entry) +{ + krb5_keytab_entry cur_entry, new_entry; + krb5_error_code kerror = 0; + int found_wrong_kvno = 0; + int was_open; + char *princname; + + KTLOCK(id); + + if (KTFILEP(id) != NULL) { + was_open = 1; + + if (fseek(KTFILEP(id), KTSTARTOFF(id), SEEK_SET) == -1) { + KTUNLOCK(id); + return errno; + } + } else { + was_open = 0; + + /* Open the keyfile for reading */ + if ((kerror = krb5_ktfileint_openr(context, id))) { + KTUNLOCK(id); + return(kerror); + } + } + + /* + * For efficiency and simplicity, we'll use a while true that + * is exited with a break statement. + */ + cur_entry.principal = 0; + cur_entry.vno = 0; + cur_entry.key.contents = 0; + + while (TRUE) { + if ((kerror = krb5_ktfileint_read_entry(context, id, &new_entry))) + break; + + /* by the time this loop exits, it must either free cur_entry, + and copy new_entry there, or free new_entry. Otherwise, it + leaks. */ + + /* if the principal isn't the one requested, free new_entry + and continue to the next. */ + + if (!krb5_principal_compare(context, principal, new_entry.principal)) { + krb5_kt_free_entry(context, &new_entry); + continue; + } + + /* If the enctype is not ignored and doesn't match, free new_entry and + continue to the next. */ + if (enctype != IGNORE_ENCTYPE && enctype != new_entry.key.enctype) { + krb5_kt_free_entry(context, &new_entry); + continue; + } + + if (kvno == IGNORE_VNO || new_entry.vno == IGNORE_VNO) { + /* If this entry is more recent (or the first match), free the + * current and keep the new. Otherwise, free the new. */ + if (cur_entry.principal == NULL || + more_recent(&new_entry, &cur_entry)) { + krb5_kt_free_entry(context, &cur_entry); + cur_entry = new_entry; + } else { + krb5_kt_free_entry(context, &new_entry); + } + } else { + /* + * If this kvno matches exactly, free the current, keep the new, + * and break out. If it matches the low 8 bits of the desired + * kvno, remember the first match (because the recorded kvno may + * have been truncated due to pre-1.14 keytab format or kadmin + * protocol limitations) but keep looking for an exact match. + * Otherwise, remember that we were here so we can return the right + * error, and free the new. + */ + if (new_entry.vno == kvno) { + krb5_kt_free_entry(context, &cur_entry); + cur_entry = new_entry; + if (new_entry.vno == kvno) + break; + } else if (new_entry.vno == (kvno & 0xff) && + cur_entry.principal == NULL) { + cur_entry = new_entry; + } else { + found_wrong_kvno++; + krb5_kt_free_entry(context, &new_entry); + } + } + } + + if (kerror == KRB5_KT_END) { + if (cur_entry.principal) + kerror = 0; + else if (found_wrong_kvno) + kerror = KRB5_KT_KVNONOTFOUND; + else { + kerror = KRB5_KT_NOTFOUND; + if (krb5_unparse_name(context, principal, &princname) == 0) { + k5_setmsg(context, kerror, + _("No key table entry found for %s"), princname); + free(princname); + } + } + } + if (kerror) { + if (was_open == 0) + (void) krb5_ktfileint_close(context, id); + KTUNLOCK(id); + krb5_kt_free_entry(context, &cur_entry); + return kerror; + } + if (was_open == 0 && (kerror = krb5_ktfileint_close(context, id)) != 0) { + KTUNLOCK(id); + krb5_kt_free_entry(context, &cur_entry); + return kerror; + } + KTUNLOCK(id); + *entry = cur_entry; + return 0; +} + +/* + * Get the name of the file containing a file-based keytab. + */ + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_get_name(krb5_context context, krb5_keytab id, char *name, unsigned int len) +/* + * This routine returns the name of the name of the file associated with + * this file-based keytab. name is zeroed and the filename is truncated + * to fit in name if necessary. The name is prefixed with PREFIX:, so that + * trt will happen if the name is passed back to resolve. + */ +{ + int result; + + memset(name, 0, len); + result = snprintf(name, len, "%s:%s", id->ops->prefix, KTFILENAME(id)); + if (SNPRINTF_OVERFLOW(result, len)) + return(KRB5_KT_NAME_TOOLONG); + return(0); +} + +/* + * krb5_ktfile_start_seq_get() + */ + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_start_seq_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursorp) +{ + krb5_error_code retval; + long *fileoff; + + KTLOCK(id); + + if (KTITERS(id) == 0) { + if ((retval = krb5_ktfileint_openr(context, id))) { + KTUNLOCK(id); + return retval; + } + } + + if (!(fileoff = (long *)malloc(sizeof(*fileoff)))) { + if (KTITERS(id) == 0) + krb5_ktfileint_close(context, id); + KTUNLOCK(id); + return ENOMEM; + } + *fileoff = KTSTARTOFF(id); + *cursorp = (krb5_kt_cursor)fileoff; + KTITERS(id)++; + if (KTITERS(id) == 0) { + /* Wrapped?! */ + KTITERS(id)--; + KTUNLOCK(id); + k5_setmsg(context, KRB5_KT_IOERR, "Too many keytab iterators active"); + return KRB5_KT_IOERR; /* XXX */ + } + KTUNLOCK(id); + + return 0; +} + +/* + * krb5_ktfile_get_next() + */ + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_get_next(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry, krb5_kt_cursor *cursor) +{ + long *fileoff = (long *)*cursor; + krb5_keytab_entry cur_entry; + krb5_error_code kerror; + + KTLOCK(id); + if (KTFILEP(id) == NULL) { + KTUNLOCK(id); + return KRB5_KT_IOERR; + } + if (fseek(KTFILEP(id), *fileoff, 0) == -1) { + KTUNLOCK(id); + return KRB5_KT_END; + } + if ((kerror = krb5_ktfileint_read_entry(context, id, &cur_entry))) { + KTUNLOCK(id); + return kerror; + } + *fileoff = ftell(KTFILEP(id)); + *entry = cur_entry; + KTUNLOCK(id); + return 0; +} + +/* + * krb5_ktfile_end_get() + */ + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_end_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursor) +{ + krb5_error_code kerror; + + free(*cursor); + KTLOCK(id); + KTITERS(id)--; + if (KTFILEP(id) != NULL && KTITERS(id) == 0) + kerror = krb5_ktfileint_close(context, id); + else + kerror = 0; + KTUNLOCK(id); + return kerror; +} + +/* + * krb5_ktfile_add() + */ + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_add(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) +{ + krb5_error_code retval; + + KTLOCK(id); + if (KTFILEP(id)) { + /* Iterator(s) active -- no changes. */ + KTUNLOCK(id); + k5_setmsg(context, KRB5_KT_IOERR, + _("Cannot change keytab with keytab iterators active")); + return KRB5_KT_IOERR; /* XXX */ + } + if ((retval = krb5_ktfileint_openw(context, id))) { + KTUNLOCK(id); + return retval; + } + if (fseek(KTFILEP(id), 0, 2) == -1) { + KTUNLOCK(id); + return KRB5_KT_END; + } + retval = krb5_ktfileint_write_entry(context, id, entry); + krb5_ktfileint_close(context, id); + KTUNLOCK(id); + return retval; +} + +/* + * krb5_ktfile_remove() + */ + +static krb5_error_code KRB5_CALLCONV +krb5_ktfile_remove(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) +{ + krb5_keytab_entry cur_entry; + krb5_error_code kerror; + krb5_int32 delete_point; + + KTLOCK(id); + if (KTFILEP(id)) { + /* Iterator(s) active -- no changes. */ + KTUNLOCK(id); + k5_setmsg(context, KRB5_KT_IOERR, + _("Cannot change keytab with keytab iterators active")); + return KRB5_KT_IOERR; /* XXX */ + } + + if ((kerror = krb5_ktfileint_openw(context, id))) { + KTUNLOCK(id); + return kerror; + } + + /* + * For efficiency and simplicity, we'll use a while true that + * is exited with a break statement. + */ + while (TRUE) { + if ((kerror = krb5_ktfileint_internal_read_entry(context, id, + &cur_entry, + &delete_point))) + break; + + if ((entry->vno == cur_entry.vno) && + (entry->key.enctype == cur_entry.key.enctype) && + krb5_principal_compare(context, entry->principal, cur_entry.principal)) { + /* found a match */ + krb5_kt_free_entry(context, &cur_entry); + break; + } + krb5_kt_free_entry(context, &cur_entry); + } + + if (kerror == KRB5_KT_END) + kerror = KRB5_KT_NOTFOUND; + + if (kerror) { + (void) krb5_ktfileint_close(context, id); + KTUNLOCK(id); + return kerror; + } + + kerror = krb5_ktfileint_delete_entry(context, id, delete_point); + + if (kerror) { + (void) krb5_ktfileint_close(context, id); + } else { + kerror = krb5_ktfileint_close(context, id); + } + KTUNLOCK(id); + return kerror; +} + +/* + * krb5_ktf_ops + */ + +const struct _krb5_kt_ops krb5_ktf_ops = { + 0, + "FILE", /* Prefix -- this string should not appear anywhere else! */ + krb5_ktfile_resolve, + krb5_ktfile_get_name, + krb5_ktfile_close, + krb5_ktfile_get_entry, + krb5_ktfile_start_seq_get, + krb5_ktfile_get_next, + krb5_ktfile_end_get, + krb5_ktfile_add, + krb5_ktfile_remove +}; + +/* + * krb5_ktf_writable_ops -- this is the same as krb5_ktf_ops except for the + * prefix. WRFILE should no longer be needed, but is effectively aliased to + * FILE for compatibility. + */ + +const struct _krb5_kt_ops krb5_ktf_writable_ops = { + 0, + "WRFILE", /* Prefix -- this string should not appear anywhere else! */ + krb5_ktfile_resolve, + krb5_ktfile_get_name, + krb5_ktfile_close, + krb5_ktfile_get_entry, + krb5_ktfile_start_seq_get, + krb5_ktfile_get_next, + krb5_ktfile_end_get, + krb5_ktfile_add, + krb5_ktfile_remove +}; + +/* + * krb5_kt_dfl_ops + */ + +const krb5_kt_ops krb5_kt_dfl_ops = { + 0, + "FILE", /* Prefix -- this string should not appear anywhere else! */ + krb5_ktfile_resolve, + krb5_ktfile_get_name, + krb5_ktfile_close, + krb5_ktfile_get_entry, + krb5_ktfile_start_seq_get, + krb5_ktfile_get_next, + krb5_ktfile_end_get, + 0, + 0 +}; + +/* Formerly lib/krb5/keytab/file/ktf_util.c */ + +/* + * This function contains utilities for the file based implementation of + * the keytab. There are no public functions in this file. + * + * This file is the only one that has knowledge of the format of a + * keytab file. + * + * The format is as follows: + * + * + * + * principal timestamp vno key + * + * principal timestamp vno key + * .... + * + * A length field (sizeof(krb5_int32)) exists between entries. When this + * length is positive it indicates an active entry, when negative a hole. + * The length indicates the size of the block in the file (this may be + * larger than the size of the next record, since we are using a first + * fit algorithm for re-using holes and the first fit may be larger than + * the entry we are writing). Another (compatible) implementation could + * break up holes when allocating them to smaller entries to minimize + * wasted space. (Such an implementation should also coalesce adjacent + * holes to reduce fragmentation). This implementation does neither. + * + * There are no separators between fields of an entry. + * A principal is a length-encoded array of length-encoded strings. The + * length is a krb5_int16 in each case. The specific format, then, is + * multiple entries concatenated with no separators. An entry has this + * exact format: + * + * sizeof(krb5_int16) bytes for number of components in the principal; + * then, each component listed in ordser. + * For each component, sizeof(krb5_int16) bytes for the number of bytes + * in the component, followed by the component. + * sizeof(krb5_int32) for the principal type (for KEYTAB V2 and higher) + * sizeof(krb5_int32) bytes for the timestamp + * sizeof(krb5_octet) bytes for the key version number + * sizeof(krb5_int16) bytes for the enctype + * sizeof(krb5_int16) bytes for the key length, followed by the key + */ + +#ifndef SEEK_SET +#define SEEK_SET 0 +#define SEEK_CUR 1 +#endif + +typedef krb5_int16 krb5_kt_vno; + +#define krb5_kt_default_vno ((krb5_kt_vno)KRB5_KT_DEFAULT_VNO) + +static krb5_error_code +krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode) +{ + krb5_error_code kerror; + krb5_kt_vno kt_vno; + int writevno = 0; + + KTCHECKLOCK(id); + errno = 0; + KTFILEP(id) = fopen(KTFILENAME(id), + (mode == KRB5_LOCKMODE_EXCLUSIVE) ? "rb+" : "rb"); + if (!KTFILEP(id)) { + if ((mode == KRB5_LOCKMODE_EXCLUSIVE) && (errno == ENOENT)) { + /* try making it first time around */ + k5_create_secure_file(context, KTFILENAME(id)); + errno = 0; + KTFILEP(id) = fopen(KTFILENAME(id), "rb+"); + if (!KTFILEP(id)) + goto report_errno; + writevno = 1; + } else { + report_errno: + switch (errno) { + case 0: + /* XXX */ + return EMFILE; + case ENOENT: + k5_setmsg(context, ENOENT, + _("Key table file '%s' not found"), KTFILENAME(id)); + return ENOENT; + default: + return errno; + } + } + } + set_cloexec_file(KTFILEP(id)); + if ((kerror = krb5_lock_file(context, fileno(KTFILEP(id)), mode))) { + (void) fclose(KTFILEP(id)); + KTFILEP(id) = 0; + return kerror; + } + /* assume ANSI or BSD-style stdio */ + setbuf(KTFILEP(id), KTFILEBUFP(id)); + + /* get the vno and verify it */ + if (writevno) { + kt_vno = htons(krb5_kt_default_vno); + KTVERSION(id) = krb5_kt_default_vno; + if (!fwrite(&kt_vno, sizeof(kt_vno), 1, KTFILEP(id))) { + kerror = errno; + (void) krb5_unlock_file(context, fileno(KTFILEP(id))); + (void) fclose(KTFILEP(id)); + KTFILEP(id) = 0; + return kerror; + } + } else { + /* gotta verify it instead... */ + if (!fread(&kt_vno, sizeof(kt_vno), 1, KTFILEP(id))) { + if (feof(KTFILEP(id))) + kerror = KRB5_KEYTAB_BADVNO; + else + kerror = errno; + (void) krb5_unlock_file(context, fileno(KTFILEP(id))); + (void) fclose(KTFILEP(id)); + KTFILEP(id) = 0; + return kerror; + } + kt_vno = KTVERSION(id) = ntohs(kt_vno); + if ((kt_vno != KRB5_KT_VNO) && + (kt_vno != KRB5_KT_VNO_1)) { + (void) krb5_unlock_file(context, fileno(KTFILEP(id))); + (void) fclose(KTFILEP(id)); + KTFILEP(id) = 0; + return KRB5_KEYTAB_BADVNO; + } + } + KTSTARTOFF(id) = ftell(KTFILEP(id)); + return 0; +} + +static krb5_error_code +krb5_ktfileint_openr(krb5_context context, krb5_keytab id) +{ + return krb5_ktfileint_open(context, id, KRB5_LOCKMODE_SHARED); +} + +static krb5_error_code +krb5_ktfileint_openw(krb5_context context, krb5_keytab id) +{ + return krb5_ktfileint_open(context, id, KRB5_LOCKMODE_EXCLUSIVE); +} + +static krb5_error_code +krb5_ktfileint_close(krb5_context context, krb5_keytab id) +{ + krb5_error_code kerror; + + KTCHECKLOCK(id); + if (!KTFILEP(id)) + return 0; + kerror = krb5_unlock_file(context, fileno(KTFILEP(id))); + (void) fclose(KTFILEP(id)); + KTFILEP(id) = 0; + return kerror; +} + +static krb5_error_code +krb5_ktfileint_delete_entry(krb5_context context, krb5_keytab id, krb5_int32 delete_point) +{ + krb5_int32 size; + krb5_int32 len; + char iobuf[BUFSIZ]; + + KTCHECKLOCK(id); + if (fseek(KTFILEP(id), delete_point, SEEK_SET)) { + return errno; + } + if (!fread(&size, sizeof(size), 1, KTFILEP(id))) { + return KRB5_KT_END; + } + if (KTVERSION(id) != KRB5_KT_VNO_1) + size = ntohl(size); + + if (size > 0) { + krb5_int32 minus_size = -size; + if (KTVERSION(id) != KRB5_KT_VNO_1) + minus_size = htonl(minus_size); + + if (fseek(KTFILEP(id), delete_point, SEEK_SET)) { + return errno; + } + + if (!fwrite(&minus_size, sizeof(minus_size), 1, KTFILEP(id))) { + return KRB5_KT_IOERR; + } + + if (size < BUFSIZ) { + len = size; + } else { + len = BUFSIZ; + } + + memset(iobuf, 0, (size_t) len); + while (size > 0) { + if (!fwrite(iobuf, 1, (size_t) len, KTFILEP(id))) { + return KRB5_KT_IOERR; + } + size -= len; + if (size < len) { + len = size; + } + } + + return k5_sync_disk_file(context, KTFILEP(id)); + } + + return 0; +} + +static krb5_error_code +krb5_ktfileint_internal_read_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *ret_entry, krb5_int32 *delete_point) +{ + krb5_octet vno; + krb5_int16 count; + unsigned int u_count, u_princ_size; + krb5_int16 enctype; + krb5_int16 princ_size; + int i; + krb5_int32 size; + krb5_int32 start_pos, pos; + krb5_error_code error; + char *tmpdata; + krb5_data *princ; + uint32_t vno32; + + KTCHECKLOCK(id); + memset(ret_entry, 0, sizeof(krb5_keytab_entry)); + ret_entry->magic = KV5M_KEYTAB_ENTRY; + + /* fseek to synchronise buffered I/O on the key table. */ + + if (fseek(KTFILEP(id), 0L, SEEK_CUR) < 0) + { + return errno; + } + + do { + *delete_point = ftell(KTFILEP(id)); + if (!fread(&size, sizeof(size), 1, KTFILEP(id))) { + return KRB5_KT_END; + } + if (KTVERSION(id) != KRB5_KT_VNO_1) + size = ntohl(size); + + if (size < 0) { + if (size == INT32_MIN) /* INT32_MIN inverts to itself. */ + return KRB5_KT_FORMAT; + if (fseek(KTFILEP(id), -size, SEEK_CUR)) { + return errno; + } + } + } while (size < 0); + + if (size == 0) { + return KRB5_KT_END; + } + + start_pos = ftell(KTFILEP(id)); + + /* deal with guts of parsing... */ + + /* first, int16 with #princ components */ + if (!fread(&count, sizeof(count), 1, KTFILEP(id))) + return KRB5_KT_END; + if (KTVERSION(id) == KRB5_KT_VNO_1) { + count -= 1; /* V1 includes the realm in the count */ + } else { + count = ntohs(count); + } + if (!count || (count < 0)) + return KRB5_KT_END; + ret_entry->principal = (krb5_principal)malloc(sizeof(krb5_principal_data)); + if (!ret_entry->principal) + return ENOMEM; + + u_count = count; + ret_entry->principal->magic = KV5M_PRINCIPAL; + ret_entry->principal->length = u_count; + ret_entry->principal->data = (krb5_data *) + calloc(u_count, sizeof(krb5_data)); + if (!ret_entry->principal->data) { + free(ret_entry->principal); + ret_entry->principal = 0; + return ENOMEM; + } + + /* Now, get the realm data */ + if (!fread(&princ_size, sizeof(princ_size), 1, KTFILEP(id))) { + error = KRB5_KT_END; + goto fail; + } + if (KTVERSION(id) != KRB5_KT_VNO_1) + princ_size = ntohs(princ_size); + if (!princ_size || (princ_size < 0)) { + error = KRB5_KT_END; + goto fail; + } + u_princ_size = princ_size; + + ret_entry->principal->realm.length = u_princ_size; + tmpdata = malloc(u_princ_size+1); + if (!tmpdata) { + error = ENOMEM; + goto fail; + } + if (fread(tmpdata, 1, u_princ_size, KTFILEP(id)) != (size_t) princ_size) { + free(tmpdata); + error = KRB5_KT_END; + goto fail; + } + tmpdata[princ_size] = 0; /* Some things might be expecting null */ + /* termination... ``Be conservative in */ + /* what you send out'' */ + ret_entry->principal->realm.data = tmpdata; + + for (i = 0; i < count; i++) { + princ = &ret_entry->principal->data[i]; + if (!fread(&princ_size, sizeof(princ_size), 1, KTFILEP(id))) { + error = KRB5_KT_END; + goto fail; + } + if (KTVERSION(id) != KRB5_KT_VNO_1) + princ_size = ntohs(princ_size); + if (!princ_size || (princ_size < 0)) { + error = KRB5_KT_END; + goto fail; + } + + u_princ_size = princ_size; + princ->length = u_princ_size; + princ->data = malloc(u_princ_size+1); + if (!princ->data) { + error = ENOMEM; + goto fail; + } + if (!fread(princ->data, sizeof(char), u_princ_size, KTFILEP(id))) { + error = KRB5_KT_END; + goto fail; + } + princ->data[princ_size] = 0; /* Null terminate */ + } + + /* read in the principal type, if we can get it */ + if (KTVERSION(id) != KRB5_KT_VNO_1) { + if (!fread(&ret_entry->principal->type, + sizeof(ret_entry->principal->type), 1, KTFILEP(id))) { + error = KRB5_KT_END; + goto fail; + } + ret_entry->principal->type = ntohl(ret_entry->principal->type); + } + + /* read in the timestamp */ + if (!fread(&ret_entry->timestamp, sizeof(ret_entry->timestamp), 1, KTFILEP(id))) { + error = KRB5_KT_END; + goto fail; + } + if (KTVERSION(id) != KRB5_KT_VNO_1) + ret_entry->timestamp = ntohl(ret_entry->timestamp); + + /* read in the version number */ + if (!fread(&vno, sizeof(vno), 1, KTFILEP(id))) { + error = KRB5_KT_END; + goto fail; + } + ret_entry->vno = (krb5_kvno)vno; + + /* key type */ + if (!fread(&enctype, sizeof(enctype), 1, KTFILEP(id))) { + error = KRB5_KT_END; + goto fail; + } + if (KTVERSION(id) != KRB5_KT_VNO_1) + enctype = ntohs(enctype); + ret_entry->key.enctype = (krb5_enctype)enctype; + + /* key contents */ + ret_entry->key.magic = KV5M_KEYBLOCK; + + if (!fread(&count, sizeof(count), 1, KTFILEP(id))) { + error = KRB5_KT_END; + goto fail; + } + if (KTVERSION(id) != KRB5_KT_VNO_1) + count = ntohs(count); + if (!count || (count < 0)) { + error = KRB5_KT_END; + goto fail; + } + + u_count = count; + ret_entry->key.length = u_count; + + ret_entry->key.contents = (krb5_octet *)malloc(u_count); + if (!ret_entry->key.contents) { + error = ENOMEM; + goto fail; + } + if (!fread(ret_entry->key.contents, sizeof(krb5_octet), count, + KTFILEP(id))) { + error = KRB5_KT_END; + goto fail; + } + + /* Check for a 32-bit kvno extension if four or more bytes remain. */ + pos = ftell(KTFILEP(id)); + if (pos - start_pos + 4 <= size) { + if (!fread(&vno32, sizeof(vno32), 1, KTFILEP(id))) { + error = KRB5_KT_END; + goto fail; + } + if (KTVERSION(id) != KRB5_KT_VNO_1) + vno32 = ntohl(vno32); + /* If the value is 0, the bytes are just zero-fill. */ + if (vno32) + ret_entry->vno = vno32; + } + + /* + * Reposition file pointer to the next inter-record length field. + */ + if (fseek(KTFILEP(id), start_pos + size, SEEK_SET) == -1) { + error = errno; + goto fail; + } + + return 0; +fail: + + for (i = 0; i < ret_entry->principal->length; i++) + free(ret_entry->principal->data[i].data); + free(ret_entry->principal->data); + ret_entry->principal->data = 0; + free(ret_entry->principal); + ret_entry->principal = 0; + return error; +} + +static krb5_error_code +krb5_ktfileint_read_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entryp) +{ + krb5_int32 delete_point; + + return krb5_ktfileint_internal_read_entry(context, id, entryp, &delete_point); +} + +static krb5_error_code +krb5_ktfileint_write_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) +{ + krb5_octet vno; + krb5_data *princ; + krb5_int16 count, size, enctype; + krb5_error_code retval = 0; + krb5_timestamp timestamp; + krb5_int32 princ_type; + krb5_int32 size_needed; + krb5_int32 commit_point = -1; + uint32_t vno32; + int i; + + KTCHECKLOCK(id); + retval = krb5_ktfileint_size_entry(context, entry, &size_needed); + if (retval) + return retval; + retval = krb5_ktfileint_find_slot(context, id, &size_needed, &commit_point); + if (retval) + return retval; + + /* fseek to synchronise buffered I/O on the key table. */ + /* XXX Without the weird setbuf crock, can we get rid of this now? */ + if (fseek(KTFILEP(id), 0L, SEEK_CUR) < 0) + { + return errno; + } + + if (KTVERSION(id) == KRB5_KT_VNO_1) { + count = (krb5_int16)entry->principal->length + 1; + } else { + count = htons((u_short)entry->principal->length); + } + + if (!fwrite(&count, sizeof(count), 1, KTFILEP(id))) { + abend: + return KRB5_KT_IOERR; + } + size = entry->principal->realm.length; + if (KTVERSION(id) != KRB5_KT_VNO_1) + size = htons(size); + if (!fwrite(&size, sizeof(size), 1, KTFILEP(id))) { + goto abend; + } + if (!fwrite(entry->principal->realm.data, sizeof(char), + entry->principal->realm.length, KTFILEP(id))) { + goto abend; + } + + count = (krb5_int16)entry->principal->length; + for (i = 0; i < count; i++) { + princ = &entry->principal->data[i]; + size = princ->length; + if (KTVERSION(id) != KRB5_KT_VNO_1) + size = htons(size); + if (!fwrite(&size, sizeof(size), 1, KTFILEP(id))) { + goto abend; + } + if (!fwrite(princ->data, sizeof(char), princ->length, KTFILEP(id))) { + goto abend; + } + } + + /* + * Write out the principal type + */ + if (KTVERSION(id) != KRB5_KT_VNO_1) { + princ_type = htonl(entry->principal->type); + if (!fwrite(&princ_type, sizeof(princ_type), 1, KTFILEP(id))) { + goto abend; + } + } + + /* + * Fill in the time of day the entry was written to the keytab. + */ + if (krb5_timeofday(context, &entry->timestamp)) { + entry->timestamp = 0; + } + if (KTVERSION(id) == KRB5_KT_VNO_1) + timestamp = entry->timestamp; + else + timestamp = htonl(entry->timestamp); + if (!fwrite(×tamp, sizeof(timestamp), 1, KTFILEP(id))) { + goto abend; + } + + /* key version number */ + vno = (krb5_octet)entry->vno; + if (!fwrite(&vno, sizeof(vno), 1, KTFILEP(id))) { + goto abend; + } + /* key type */ + if (KTVERSION(id) == KRB5_KT_VNO_1) + enctype = entry->key.enctype; + else + enctype = htons(entry->key.enctype); + if (!fwrite(&enctype, sizeof(enctype), 1, KTFILEP(id))) { + goto abend; + } + /* key length */ + if (KTVERSION(id) == KRB5_KT_VNO_1) + size = entry->key.length; + else + size = htons(entry->key.length); + if (!fwrite(&size, sizeof(size), 1, KTFILEP(id))) { + goto abend; + } + if (!fwrite(entry->key.contents, sizeof(krb5_octet), + entry->key.length, KTFILEP(id))) { + goto abend; + } + + /* 32-bit key version number */ + vno32 = entry->vno; + if (KTVERSION(id) != KRB5_KT_VNO_1) + vno32 = htonl(vno32); + if (!fwrite(&vno32, sizeof(vno32), 1, KTFILEP(id))) + goto abend; + + if (fflush(KTFILEP(id))) + goto abend; + + retval = k5_sync_disk_file(context, KTFILEP(id)); + + if (retval) { + return retval; + } + + if (fseek(KTFILEP(id), commit_point, SEEK_SET)) { + return errno; + } + if (KTVERSION(id) != KRB5_KT_VNO_1) + size_needed = htonl(size_needed); + if (!fwrite(&size_needed, sizeof(size_needed), 1, KTFILEP(id))) { + goto abend; + } + if (fflush(KTFILEP(id))) + goto abend; + retval = k5_sync_disk_file(context, KTFILEP(id)); + + return retval; +} + +/* + * Determine the size needed for a file entry for the given + * keytab entry. + */ +static krb5_error_code +krb5_ktfileint_size_entry(krb5_context context, krb5_keytab_entry *entry, krb5_int32 *size_needed) +{ + krb5_int16 count; + krb5_int32 total_size, i; + krb5_error_code retval = 0; + + count = (krb5_int16)entry->principal->length; + + total_size = sizeof(count); + total_size += entry->principal->realm.length + sizeof(krb5_int16); + + for (i = 0; i < count; i++) + total_size += entry->principal->data[i].length + sizeof(krb5_int16); + + total_size += sizeof(entry->principal->type); + total_size += sizeof(entry->timestamp); + total_size += sizeof(krb5_octet); + total_size += sizeof(krb5_int16); + total_size += sizeof(krb5_int16) + entry->key.length; + total_size += sizeof(uint32_t); + + *size_needed = total_size; + return retval; +} + +/* + * Find and reserve a slot in the file for an entry of the needed size. + * The commit point will be set to the position in the file where the + * the length (sizeof(krb5_int32) bytes) of this node should be written + * when committing the write. The file position left as a result of this + * call is the position where the actual data should be written. + * + * The size_needed argument may be adjusted if we find a hole that is + * larger than the size needed. (Recall that size_needed will be used + * to commit the write, but that this field must indicate the size of the + * block in the file rather than the size of the actual entry) + */ +static krb5_error_code +krb5_ktfileint_find_slot(krb5_context context, krb5_keytab id, krb5_int32 *size_needed, krb5_int32 *commit_point_ptr) +{ + FILE *fp; + krb5_int32 size, zero_point, commit_point; + krb5_kt_vno kt_vno; + + KTCHECKLOCK(id); + fp = KTFILEP(id); + /* Skip over file version number. */ + if (fseek(fp, 0, SEEK_SET)) + return errno; + if (!fread(&kt_vno, sizeof(kt_vno), 1, fp)) + return errno; + + for (;;) { + commit_point = ftell(fp); + if (commit_point == -1) + return errno; + if (!fread(&size, sizeof(size), 1, fp)) { + /* Hit the end of file, reserve this slot. */ + /* Necessary to avoid a later fseek failing on Solaris 10. */ + if (fseek(fp, 0, SEEK_CUR)) + return errno; + /* htonl(0) is 0, so no need to worry about byte order */ + size = 0; + if (!fwrite(&size, sizeof(size), 1, fp)) + return errno; + break; + } + + if (KTVERSION(id) != KRB5_KT_VNO_1) + size = ntohl(size); + + if (size > 0) { + /* Non-empty record; seek past it. */ + if (fseek(fp, size, SEEK_CUR)) + return errno; + } else if (size < 0) { + /* Empty record; use if it's big enough, seek past otherwise. */ + if (size == INT32_MIN) /* INT32_MIN inverts to itself. */ + return KRB5_KT_FORMAT; + size = -size; + if (size >= *size_needed) { + *size_needed = size; + break; + } else { + if (fseek(fp, size, SEEK_CUR)) + return errno; + } + } else { + /* Empty record at end of file; use it. */ + /* Ensure the new record will be followed by another 0. */ + zero_point = ftell(fp); + if (zero_point == -1) + return errno; + if (fseek(fp, *size_needed, SEEK_CUR)) + return errno; + /* htonl(0) is 0, so no need to worry about byte order */ + if (!fwrite(&size, sizeof(size), 1, fp)) + return errno; + if (fseek(fp, zero_point, SEEK_SET)) + return errno; + break; + } + } + + *commit_point_ptr = commit_point; + return 0; +} +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/krb5/keytab/kt_memory.c b/krb5-1.21.3/src/lib/krb5/keytab/kt_memory.c new file mode 100644 index 00000000..c0eb6e5d --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/keytab/kt_memory.c @@ -0,0 +1,637 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/keytab/kt_memory.c */ +/* + * Copyright 2007 by Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "k5-int.h" +#include "kt-int.h" +#include + +#ifndef LEAN_CLIENT + +#define HEIMDAL_COMPATIBLE + +/* + * Information needed by internal routines of the file-based ticket + * cache implementation. + */ + + +/* + * Constants + */ + +/* + * Types + */ +/* From krb5.h: + * typedef struct krb5_keytab_entry_st { + * krb5_magic magic; + * krb5_principal principal; principal of this key + * krb5_timestamp timestamp; time entry written to keytable + * krb5_kvno vno; key version number + * krb5_keyblock key; the secret key + *} krb5_keytab_entry; + */ + +/* Individual key entries within a table, in a linked list */ +typedef struct _krb5_mkt_link { + struct _krb5_mkt_link *next; + krb5_keytab_entry *entry; +} krb5_mkt_link, *krb5_mkt_cursor; + +/* Per-keytab data header */ +typedef struct _krb5_mkt_data { + char *name; /* Name of the keytab */ + k5_mutex_t lock; /* Thread-safety - all but link */ + krb5_int32 refcount; + krb5_mkt_cursor link; +} krb5_mkt_data; + +/* List of memory key tables */ +typedef struct _krb5_mkt_list_node { + struct _krb5_mkt_list_node *next; + krb5_keytab keytab; +} krb5_mkt_list_node; + +/* Iterator over memory key tables */ +typedef struct _krb5_mkt_ptcursor_data { + struct _krb5_mkt_list_node *cur; +} krb5_mkt_ptcursor_data; + +/* + * Globals + */ +static krb5_mkt_list_node * krb5int_mkt_list = NULL; +static k5_mutex_t krb5int_mkt_mutex = K5_MUTEX_PARTIAL_INITIALIZER; + +/* + * Macros + */ +#define KTLOCK(id) k5_mutex_lock(&(((krb5_mkt_data *)(id)->data)->lock)) +#define KTUNLOCK(id) k5_mutex_unlock(&(((krb5_mkt_data *)(id)->data)->lock)) +#define KTCHECKLOCK(id) k5_mutex_assert_locked(&(((krb5_mkt_data *)(id)->data)->lock)) + +#define KTGLOCK k5_mutex_lock(&krb5int_mkt_mutex) +#define KTGUNLOCK k5_mutex_unlock(&krb5int_mkt_mutex) +#define KTGCHECKLOCK k5_mutex_assert_locked(&krb5int_mkt_mutex) + +#define KTLINK(id) (((krb5_mkt_data *)(id)->data)->link) +#define KTREFCNT(id) (((krb5_mkt_data *)(id)->data)->refcount) +#define KTNAME(id) (((krb5_mkt_data *)(id)->data)->name) + +extern const struct _krb5_kt_ops krb5_mkt_ops; + +krb5_error_code KRB5_CALLCONV +krb5_mkt_resolve(krb5_context, const char *, krb5_keytab *); + +krb5_error_code KRB5_CALLCONV +krb5_mkt_get_name(krb5_context, krb5_keytab, char *, unsigned int); + +krb5_error_code KRB5_CALLCONV +krb5_mkt_close(krb5_context, krb5_keytab); + +krb5_error_code KRB5_CALLCONV +krb5_mkt_get_entry(krb5_context, krb5_keytab, krb5_const_principal, krb5_kvno, + krb5_enctype, krb5_keytab_entry *); + +krb5_error_code KRB5_CALLCONV +krb5_mkt_start_seq_get(krb5_context, krb5_keytab, krb5_kt_cursor *); + +krb5_error_code KRB5_CALLCONV +krb5_mkt_get_next(krb5_context, krb5_keytab, krb5_keytab_entry *, + krb5_kt_cursor *); + +krb5_error_code KRB5_CALLCONV +krb5_mkt_end_get(krb5_context, krb5_keytab, krb5_kt_cursor *); + +/* routines to be included on extended version (write routines) */ +krb5_error_code KRB5_CALLCONV +krb5_mkt_add(krb5_context, krb5_keytab, krb5_keytab_entry *); + +krb5_error_code KRB5_CALLCONV +krb5_mkt_remove(krb5_context, krb5_keytab, krb5_keytab_entry *); + +int +krb5int_mkt_initialize(void) +{ + return k5_mutex_finish_init(&krb5int_mkt_mutex); +} + +void +krb5int_mkt_finalize(void) +{ + krb5_mkt_list_node *node, *next_node; + krb5_mkt_cursor cursor, next_cursor; + + k5_mutex_destroy(&krb5int_mkt_mutex); + + for (node = krb5int_mkt_list; node; node = next_node) { + next_node = node->next; + + /* destroy the contents of node->keytab */ + free(KTNAME(node->keytab)); + + /* free the keytab entries */ + for (cursor = KTLINK(node->keytab); cursor; cursor = next_cursor) { + next_cursor = cursor->next; + /* the call to krb5_kt_free_entry uses a NULL in place of the + * krb5_context since we know that the context isn't used by + * krb5_kt_free_entry or krb5_free_principal. */ + krb5_kt_free_entry(NULL, cursor->entry); + free(cursor->entry); + free(cursor); + } + + /* destroy the lock */ + k5_mutex_destroy(&(((krb5_mkt_data *)node->keytab->data)->lock)); + + /* free the private data */ + free(node->keytab->data); + + /* and the keytab */ + free(node->keytab); + + /* and finally the node */ + free(node); + } +} + +static krb5_error_code +create_list_node(const char *name, krb5_mkt_list_node **listp) +{ + krb5_mkt_list_node *list; + krb5_mkt_data *data = NULL; + krb5_error_code err; + + *listp = NULL; + + list = calloc(1, sizeof(krb5_mkt_list_node)); + if (list == NULL) { + err = ENOMEM; + goto cleanup; + } + + list->keytab = calloc(1, sizeof(struct _krb5_kt)); + if (list->keytab == NULL) { + err = ENOMEM; + goto cleanup; + } + list->keytab->ops = &krb5_mkt_ops; + + data = calloc(1, sizeof(krb5_mkt_data)); + if (data == NULL) { + err = ENOMEM; + goto cleanup; + } + data->link = NULL; + data->refcount = 0; + + data->name = strdup(name); + if (data->name == NULL) { + err = ENOMEM; + goto cleanup; + } + + err = k5_mutex_init(&data->lock); + if (err) + goto cleanup; + + list->keytab->data = data; + list->keytab->magic = KV5M_KEYTAB; + list->next = NULL; + *listp = list; + return 0; + +cleanup: + /* data->lock was initialized last, so no need to destroy. */ + if (data) + free(data->name); + free(data); + if (list) + free(list->keytab); + free(list); + return err; +} + +/* + * This is an implementation specific resolver. It returns a keytab + * initialized with memory keytab routines. + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_resolve(krb5_context context, const char *name, krb5_keytab *id) +{ + krb5_mkt_list_node *list; + krb5_error_code err = 0; + + *id = NULL; + + /* First determine if a memory keytab of this name already exists */ + KTGLOCK; + + for (list = krb5int_mkt_list; list; list = list->next) { + if (strcmp(name,KTNAME(list->keytab)) == 0) + break; + } + + if (!list) { + /* We will now create the new key table with the specified name. + * We do not drop the global lock, therefore the name will indeed + * be unique when we add it. + */ + err = create_list_node(name, &list); + if (err) + goto done; + list->next = krb5int_mkt_list; + krb5int_mkt_list = list; + } + + /* Increment the reference count on the keytab we found or created. */ + KTLOCK(list->keytab); + KTREFCNT(list->keytab)++; + KTUNLOCK(list->keytab); + *id = list->keytab; +done: + KTGUNLOCK; + return err; +} + + +/* + * "Close" a memory-based keytab. This is effectively a no-op. + * We check to see if the keytab exists and that is about it. + * Closing a file keytab does not destroy the contents. Closing + * a memory keytab shouldn't either. + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_close(krb5_context context, krb5_keytab id) +{ + krb5_mkt_list_node **listp; +#ifdef HEIMDAL_COMPATIBLE + krb5_mkt_list_node *node; + krb5_mkt_data * data; +#endif + krb5_error_code err = 0; + + /* First determine if a memory keytab of this name already exists */ + KTGLOCK; + + for (listp = &krb5int_mkt_list; *listp; listp = &((*listp)->next)) + { + if (id == (*listp)->keytab) { + /* Found */ + break; + } + } + + if (*listp == NULL) { + /* The specified keytab could not be found */ + err = KRB5_KT_NOTFOUND; + goto done; + } + + /* reduce the refcount and return */ + KTLOCK(id); + KTREFCNT(id)--; + KTUNLOCK(id); + +#ifdef HEIMDAL_COMPATIBLE + /* In Heimdal if the refcount hits 0, the MEMORY keytab is + * destroyed since there is no krb5_kt_destroy function. + * There is no need to lock the entry while performing + * these operations as the refcount will be 0 and we are + * holding the global lock. + */ + data = (krb5_mkt_data *)id->data; + if (data->refcount == 0) { + krb5_mkt_cursor cursor, next_cursor; + + node = *listp; + *listp = node->next; + + /* destroy the contents of node->keytab (aka id) */ + free(data->name); + + /* free the keytab entries */ + for (cursor = KTLINK(node->keytab); cursor; cursor = next_cursor) { + next_cursor = cursor->next; + + krb5_kt_free_entry(context, cursor->entry); + free(cursor->entry); + free(cursor); + } + + /* destroy the lock */ + k5_mutex_destroy(&(data->lock)); + + /* free the private data */ + free(data); + + /* and the keytab */ + free(node->keytab); + + /* and finally the node */ + free(node); + } +#endif /* HEIMDAL_COMPATIBLE */ + +done: + KTGUNLOCK; + return(err); +} + +/* + * This is the get_entry routine for the memory based keytab implementation. + * It either retrieves the entry or returns an error. + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_get_entry(krb5_context context, krb5_keytab id, + krb5_const_principal principal, krb5_kvno kvno, + krb5_enctype enctype, krb5_keytab_entry *out_entry) +{ + krb5_mkt_cursor cursor; + krb5_keytab_entry *entry, *match = NULL; + krb5_error_code err = 0; + int found_wrong_kvno = 0; + krb5_boolean similar = 0; + + KTLOCK(id); + + for (cursor = KTLINK(id); cursor && cursor->entry; cursor = cursor->next) { + entry = cursor->entry; + + /* if the principal isn't the one requested, continue to the next. */ + + if (!krb5_principal_compare(context, principal, entry->principal)) + continue; + + /* if the enctype is not ignored and doesn't match, + and continue to the next */ + if (enctype != IGNORE_ENCTYPE) { + if ((err = krb5_c_enctype_compare(context, enctype, + entry->key.enctype, + &similar))) { + /* we can't determine the enctype of the entry */ + continue; + } + + if (!similar) + continue; + } + + if (kvno == IGNORE_VNO || entry->vno == IGNORE_VNO) { + if (match == NULL) + match = entry; + else if (entry->vno > match->vno) + match = entry; + } else { + if (entry->vno == kvno) { + match = entry; + break; + } else { + found_wrong_kvno++; + } + } + } + + /* if we found an entry that matches, ... */ + if (match) { + out_entry->magic = match->magic; + out_entry->timestamp = match->timestamp; + out_entry->vno = match->vno; + out_entry->key = match->key; + err = krb5_copy_keyblock_contents(context, &(match->key), + &(out_entry->key)); + /* + * Coerce the enctype of the output keyblock in case we + * got an inexact match on the enctype. + */ + if(enctype != IGNORE_ENCTYPE) + out_entry->key.enctype = enctype; + if(!err) { + err = krb5_copy_principal(context, + match->principal, + &(out_entry->principal)); + } + } else { + if (!err) + err = found_wrong_kvno ? KRB5_KT_KVNONOTFOUND : KRB5_KT_NOTFOUND; + } + + KTUNLOCK(id); + return(err); +} + +/* + * Get the name of the memory-based keytab. + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_get_name(krb5_context context, krb5_keytab id, char *name, unsigned int len) +{ + int result; + + memset(name, 0, len); + result = snprintf(name, len, "%s:%s", id->ops->prefix, KTNAME(id)); + if (SNPRINTF_OVERFLOW(result, len)) + return(KRB5_KT_NAME_TOOLONG); + return(0); +} + +/* + * krb5_mkt_start_seq_get() + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_start_seq_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursorp) +{ + KTLOCK(id); + *cursorp = (krb5_kt_cursor)KTLINK(id); + KTUNLOCK(id); + + return(0); +} + +/* + * krb5_mkt_get_next() + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_get_next(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry, krb5_kt_cursor *cursor) +{ + krb5_mkt_cursor mkt_cursor = (krb5_mkt_cursor)*cursor; + krb5_error_code err = 0; + + KTLOCK(id); + + if (mkt_cursor == NULL) { + KTUNLOCK(id); + return KRB5_KT_END; + } + + entry->magic = mkt_cursor->entry->magic; + entry->timestamp = mkt_cursor->entry->timestamp; + entry->vno = mkt_cursor->entry->vno; + entry->key = mkt_cursor->entry->key; + err = krb5_copy_keyblock_contents(context, &(mkt_cursor->entry->key), + &(entry->key)); + if (!err) + err = krb5_copy_principal(context, mkt_cursor->entry->principal, + &(entry->principal)); + if (!err) + *cursor = (krb5_kt_cursor *)mkt_cursor->next; + KTUNLOCK(id); + return(err); +} + +/* + * krb5_mkt_end_get() + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_end_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursor) +{ + *cursor = NULL; + return(0); +} + + +/* + * krb5_mkt_add() + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_add(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) +{ + krb5_error_code err = 0; + krb5_mkt_cursor cursor; + + KTLOCK(id); + + cursor = (krb5_mkt_cursor)malloc(sizeof(krb5_mkt_link)); + if (cursor == NULL) { + err = ENOMEM; + goto done; + } + cursor->entry = (krb5_keytab_entry *)malloc(sizeof(krb5_keytab_entry)); + if (cursor->entry == NULL) { + free(cursor); + err = ENOMEM; + goto done; + } + cursor->entry->magic = entry->magic; + cursor->entry->timestamp = entry->timestamp; + cursor->entry->vno = entry->vno; + err = krb5_copy_keyblock_contents(context, &(entry->key), + &(cursor->entry->key)); + if (err) { + free(cursor->entry); + free(cursor); + goto done; + } + + err = krb5_copy_principal(context, entry->principal, &(cursor->entry->principal)); + if (err) { + krb5_free_keyblock_contents(context, &(cursor->entry->key)); + free(cursor->entry); + free(cursor); + goto done; + } + + if (KTLINK(id) == NULL) { + cursor->next = NULL; + KTLINK(id) = cursor; + } else { + cursor->next = KTLINK(id); + KTLINK(id) = cursor; + } + +done: + KTUNLOCK(id); + return err; +} + +/* + * krb5_mkt_remove() + */ + +krb5_error_code KRB5_CALLCONV +krb5_mkt_remove(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) +{ + krb5_mkt_cursor *pcursor, next; + krb5_error_code err = 0; + + KTLOCK(id); + + if ( KTLINK(id) == NULL ) { + err = KRB5_KT_NOTFOUND; + goto done; + } + + for ( pcursor = &KTLINK(id); *pcursor; pcursor = &(*pcursor)->next ) { + if ( (*pcursor)->entry->vno == entry->vno && + (*pcursor)->entry->key.enctype == entry->key.enctype && + krb5_principal_compare(context, (*pcursor)->entry->principal, entry->principal)) + break; + } + + if (!*pcursor) { + err = KRB5_KT_NOTFOUND; + goto done; + } + + krb5_kt_free_entry(context, (*pcursor)->entry); + free((*pcursor)->entry); + next = (*pcursor)->next; + free(*pcursor); + (*pcursor) = next; + +done: + KTUNLOCK(id); + return err; +} + + +/* + * krb5_mkt_ops + */ + +const struct _krb5_kt_ops krb5_mkt_ops = { + 0, + "MEMORY", /* Prefix -- this string should not appear anywhere else! */ + krb5_mkt_resolve, + krb5_mkt_get_name, + krb5_mkt_close, + krb5_mkt_get_entry, + krb5_mkt_start_seq_get, + krb5_mkt_get_next, + krb5_mkt_end_get, + krb5_mkt_add, + krb5_mkt_remove +}; + +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/krb5/keytab/ktadd.c b/krb5-1.21.3/src/lib/krb5/keytab/ktadd.c new file mode 100644 index 00000000..71f47e7f --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/keytab/ktadd.c @@ -0,0 +1,39 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/keytab/ktadd.c */ +/* + * Copyright 1990,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +#ifndef LEAN_CLIENT + +krb5_error_code KRB5_CALLCONV +krb5_kt_add_entry (krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) +{ + if (id->ops->add) + return (*id->ops->add)(context, id, entry); + else + return KRB5_KT_NOWRITE; +} +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/krb5/keytab/ktbase.c b/krb5-1.21.3/src/lib/krb5/keytab/ktbase.c new file mode 100644 index 00000000..9010b6e6 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/keytab/ktbase.c @@ -0,0 +1,221 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/keytab/ktbase.c - Registration functions for keytab */ +/* + * Copyright 1990,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright 2007 by Secure Endpoints Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "k5-int.h" +#include "k5-thread.h" +#include "kt-int.h" + +#ifndef LEAN_CLIENT + +extern const krb5_kt_ops krb5_ktf_ops; +extern const krb5_kt_ops krb5_ktf_writable_ops; +extern const krb5_kt_ops krb5_mkt_ops; + +struct krb5_kt_typelist { + const krb5_kt_ops *ops; + const struct krb5_kt_typelist *next; +}; +const static struct krb5_kt_typelist krb5_kt_typelist_memory = { + &krb5_mkt_ops, + NULL +}; +const static struct krb5_kt_typelist krb5_kt_typelist_wrfile = { + &krb5_ktf_writable_ops, + &krb5_kt_typelist_memory +}; +const static struct krb5_kt_typelist krb5_kt_typelist_file = { + &krb5_ktf_ops, + &krb5_kt_typelist_wrfile +}; + +static const struct krb5_kt_typelist *kt_typehead = &krb5_kt_typelist_file; +/* Lock for protecting the type list. */ +static k5_mutex_t kt_typehead_lock = K5_MUTEX_PARTIAL_INITIALIZER; + +int krb5int_kt_initialize(void) +{ + int err; + + err = k5_mutex_finish_init(&kt_typehead_lock); + if (err) + goto done; + err = krb5int_mkt_initialize(); + if (err) + goto done; + +done: + return(err); +} + +void +krb5int_kt_finalize(void) +{ + const struct krb5_kt_typelist *t, *t_next; + + k5_mutex_destroy(&kt_typehead_lock); + for (t = kt_typehead; t != &krb5_kt_typelist_file; t = t_next) { + t_next = t->next; + free((struct krb5_kt_typelist *)t); + } + + krb5int_mkt_finalize(); +} + + +/* + * Register a new key table type + * don't replace if it already exists; return an error instead. + */ + +krb5_error_code KRB5_CALLCONV +krb5_kt_register(krb5_context context, const krb5_kt_ops *ops) +{ + const struct krb5_kt_typelist *t; + struct krb5_kt_typelist *newt; + + k5_mutex_lock(&kt_typehead_lock); + for (t = kt_typehead; t && strcmp(t->ops->prefix,ops->prefix);t = t->next) + ; + if (t) { + k5_mutex_unlock(&kt_typehead_lock); + return KRB5_KT_TYPE_EXISTS; + } + if (!(newt = (struct krb5_kt_typelist *) malloc(sizeof(*t)))) { + k5_mutex_unlock(&kt_typehead_lock); + return ENOMEM; + } + newt->next = kt_typehead; + newt->ops = ops; + kt_typehead = newt; + k5_mutex_unlock(&kt_typehead_lock); + return 0; +} + +/* + * Resolve a key table name into a keytab object. + * + * The name is currently constrained to be of the form "type:residual"; + * + * The "type" portion corresponds to one of the registered key table + * types, while the "residual" portion is specific to the + * particular keytab type. + */ + +#include +krb5_error_code KRB5_CALLCONV +krb5_kt_resolve (krb5_context context, const char *name, krb5_keytab *ktid) +{ + const struct krb5_kt_typelist *tlist; + char *pfx = NULL; + unsigned int pfxlen; + const char *cp, *resid; + krb5_error_code err = 0; + krb5_keytab id; + + *ktid = NULL; + + cp = strchr (name, ':'); + if (!cp) + return (*krb5_kt_dfl_ops.resolve)(context, name, ktid); + + pfxlen = cp - name; + + if ( pfxlen == 1 && isalpha((unsigned char) name[0]) ) { + /* We found a drive letter not a prefix - use FILE */ + pfx = strdup("FILE"); + if (!pfx) + return ENOMEM; + + resid = name; + } else if (name[0] == '/') { + pfx = strdup("FILE"); + if (!pfx) + return ENOMEM; + resid = name; + } else { + resid = name + pfxlen + 1; + pfx = k5memdup0(name, pfxlen, &err); + if (pfx == NULL) + return err; + } + + *ktid = (krb5_keytab) 0; + + k5_mutex_lock(&kt_typehead_lock); + tlist = kt_typehead; + /* Don't need to hold the lock, since entries are never modified + or removed once they're in the list. Just need to protect + access to the list head variable itself. */ + k5_mutex_unlock(&kt_typehead_lock); + for (; tlist; tlist = tlist->next) { + if (strcmp (tlist->ops->prefix, pfx) == 0) { + err = (*tlist->ops->resolve)(context, resid, &id); + if (!err) + *ktid = id; + goto cleanup; + } + } + err = KRB5_KT_UNKNOWN_TYPE; + +cleanup: + free(pfx); + return err; +} + +krb5_error_code KRB5_CALLCONV +krb5_kt_dup(krb5_context context, krb5_keytab in, krb5_keytab *out) +{ + krb5_error_code err; + char name[BUFSIZ]; + + err = in->ops->get_name(context, in, name, sizeof(name)); + return err ? err : krb5_kt_resolve(context, name, out); +} + +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/krb5/keytab/ktdefault.c b/krb5-1.21.3/src/lib/krb5/keytab/ktdefault.c new file mode 100644 index 00000000..482d52ad --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/keytab/ktdefault.c @@ -0,0 +1,62 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/keytab/ktdefault.c */ +/* + * Copyright 1990,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * Get a default keytab. + */ + +#include "k5-int.h" +#include "../os/os-proto.h" +#include + +#ifndef LEAN_CLIENT +krb5_error_code KRB5_CALLCONV +krb5_kt_default(krb5_context context, krb5_keytab *id) +{ + char defname[BUFSIZ]; + krb5_error_code retval; + + if ((retval = krb5_kt_default_name(context, defname, sizeof(defname)))) + return retval; + return krb5_kt_resolve(context, defname, id); +} + +krb5_error_code KRB5_CALLCONV +krb5_kt_client_default(krb5_context context, krb5_keytab *keytab_out) +{ + krb5_error_code ret; + char *name; + + ret = k5_kt_client_default_name(context, &name); + if (ret) + return ret; + ret = krb5_kt_resolve(context, name, keytab_out); + free(name); + return ret; +} + +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/krb5/keytab/ktfns.c b/krb5-1.21.3/src/lib/krb5/keytab/ktfns.c new file mode 100644 index 00000000..d6658b35 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/keytab/ktfns.c @@ -0,0 +1,214 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/keytab/ktfns.c */ +/* + * Copyright 2001,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Dispatch methods for keytab code. + */ + +#ifndef LEAN_CLIENT + +#include "k5-int.h" +#include "../krb/int-proto.h" +#include "../os/os-proto.h" + +const char * KRB5_CALLCONV +krb5_kt_get_type (krb5_context context, krb5_keytab keytab) +{ + return keytab->ops->prefix; +} + +krb5_error_code KRB5_CALLCONV +krb5_kt_get_name(krb5_context context, krb5_keytab keytab, char *name, + unsigned int namelen) +{ + return krb5_x((keytab)->ops->get_name,(context, keytab,name,namelen)); +} + +krb5_error_code KRB5_CALLCONV +krb5_kt_close(krb5_context context, krb5_keytab keytab) +{ + return krb5_x((keytab)->ops->close,(context, keytab)); +} + +krb5_error_code KRB5_CALLCONV +krb5_kt_get_entry(krb5_context context, krb5_keytab keytab, + krb5_const_principal principal, krb5_kvno vno, + krb5_enctype enctype, krb5_keytab_entry *entry) +{ + krb5_error_code err; + krb5_principal_data princ_data; + + if (krb5_is_referral_realm(&principal->realm)) { + char *realm; + princ_data = *principal; + principal = &princ_data; + err = krb5_get_default_realm(context, &realm); + if (err) + return err; + princ_data.realm.data = realm; + princ_data.realm.length = strlen(realm); + } + err = krb5_x((keytab)->ops->get,(context, keytab, principal, vno, enctype, + entry)); + TRACE_KT_GET_ENTRY(context, keytab, principal, vno, enctype, err); + if (principal == &princ_data) + krb5_free_default_realm(context, princ_data.realm.data); + return err; +} + +krb5_error_code KRB5_CALLCONV +krb5_kt_start_seq_get(krb5_context context, krb5_keytab keytab, + krb5_kt_cursor *cursor) +{ + return krb5_x((keytab)->ops->start_seq_get,(context, keytab, cursor)); +} + +krb5_error_code KRB5_CALLCONV +krb5_kt_next_entry(krb5_context context, krb5_keytab keytab, + krb5_keytab_entry *entry, krb5_kt_cursor *cursor) +{ + return krb5_x((keytab)->ops->get_next,(context, keytab, entry, cursor)); +} + +krb5_error_code KRB5_CALLCONV +krb5_kt_end_seq_get(krb5_context context, krb5_keytab keytab, + krb5_kt_cursor *cursor) +{ + return krb5_x((keytab)->ops->end_get,(context, keytab, cursor)); +} + +krb5_error_code KRB5_CALLCONV +krb5_kt_have_content(krb5_context context, krb5_keytab keytab) +{ + krb5_keytab_entry entry; + krb5_kt_cursor cursor; + krb5_error_code ret; + char name[1024]; + + /* If the keytab is not iterable, assume that it has content. */ + if (keytab->ops->start_seq_get == NULL) + return 0; + + /* See if we can get at least one entry via iteration. */ + ret = krb5_kt_start_seq_get(context, keytab, &cursor); + if (ret) + goto no_entries; + ret = krb5_kt_next_entry(context, keytab, &entry, &cursor); + krb5_kt_end_seq_get(context, keytab, &cursor); + if (ret) + goto no_entries; + krb5_kt_free_entry(context, &entry); + return 0; + +no_entries: + if (krb5_kt_get_name(context, keytab, name, sizeof(name)) == 0) { + k5_setmsg(context, KRB5_KT_NOTFOUND, + _("Keytab %s is nonexistent or empty"), name); + } + return KRB5_KT_NOTFOUND; +} + +static krb5_error_code +match_entries(krb5_context context, krb5_keytab keytab, + krb5_const_principal mprinc) +{ + krb5_error_code ret; + krb5_keytab_entry ent; + krb5_kt_cursor cursor; + krb5_boolean match; + + /* Scan the keytab for host-based entries matching accprinc. */ + ret = krb5_kt_start_seq_get(context, keytab, &cursor); + if (ret) + return ret; + while ((ret = krb5_kt_next_entry(context, keytab, &ent, &cursor)) == 0) { + match = krb5_sname_match(context, mprinc, ent.principal); + (void)krb5_free_keytab_entry_contents(context, &ent); + if (match) + break; + } + (void)krb5_kt_end_seq_get(context, keytab, &cursor); + if (ret && ret != KRB5_KT_END) + return ret; + return match ? 0 : KRB5_KT_NOTFOUND; +} + +krb5_error_code +k5_kt_have_match(krb5_context context, krb5_keytab keytab, + krb5_principal mprinc) +{ + krb5_error_code ret; + struct canonprinc iter = { mprinc, .no_hostrealm = TRUE }; + krb5_const_principal canonprinc = NULL; + + /* Don't try to canonicalize if we're going to ignore hostnames. */ + if (k5_sname_wildcard_host(context, mprinc)) + return match_entries(context, keytab, mprinc); + + while ((ret = k5_canonprinc(context, &iter, &canonprinc)) == 0 && + canonprinc != NULL) { + ret = match_entries(context, keytab, canonprinc); + if (ret != KRB5_KT_NOTFOUND) + break; + } + free_canonprinc(&iter); + return (ret == 0 && canonprinc == NULL) ? KRB5_KT_NOTFOUND : ret; +} + +/* + * In a couple of places we need to get a principal name from a keytab: when + * verifying credentials against a keytab, and when querying the name of a + * default GSS acceptor cred. Keytabs do not have the concept of a default + * principal like ccaches do, so for now we just return the first principal + * listed in the keytab, or an error if it's not iterable. In the future we + * could consider elevating this to a public API and giving keytab types an + * operation to return a default principal, and maybe extending the file format + * and tools to support it. Returns KRB5_KT_NOTFOUND if the keytab is empty + * or non-iterable. + */ +krb5_error_code +k5_kt_get_principal(krb5_context context, krb5_keytab keytab, + krb5_principal *princ_out) +{ + krb5_error_code ret; + krb5_kt_cursor cursor; + krb5_keytab_entry kte; + + *princ_out = NULL; + if (keytab->ops->start_seq_get == NULL) + return KRB5_KT_NOTFOUND; + ret = krb5_kt_start_seq_get(context, keytab, &cursor); + if (ret) + return ret; + ret = krb5_kt_next_entry(context, keytab, &kte, &cursor); + (void)krb5_kt_end_seq_get(context, keytab, &cursor); + if (ret) + return (ret == KRB5_KT_END) ? KRB5_KT_NOTFOUND : ret; + ret = krb5_copy_principal(context, kte.principal, princ_out); + krb5_kt_free_entry(context, &kte); + return ret; +} +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/krb5/keytab/ktfr_entry.c b/krb5-1.21.3/src/lib/krb5/keytab/ktfr_entry.c new file mode 100644 index 00000000..c0048407 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/keytab/ktfr_entry.c @@ -0,0 +1,50 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/keytab/ktfr_entry.c */ +/* + * Copyright 1990, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef LEAN_CLIENT + +#include "k5-int.h" + +krb5_error_code KRB5_CALLCONV +krb5_free_keytab_entry_contents (krb5_context context, krb5_keytab_entry *entry) +{ + if (!entry) + return 0; + + krb5_free_principal(context, entry->principal); + if (entry->key.contents) { + zap((char *)entry->key.contents, entry->key.length); + free(entry->key.contents); + } + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_kt_free_entry (krb5_context context, krb5_keytab_entry *entry) +{ + return krb5_free_keytab_entry_contents (context, entry); +} +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/krb5/keytab/ktremove.c b/krb5-1.21.3/src/lib/krb5/keytab/ktremove.c new file mode 100644 index 00000000..da6a4dff --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/keytab/ktremove.c @@ -0,0 +1,39 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/keytab/ktremove.c */ +/* + * Copyright 1990,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef LEAN_CLIENT + +#include "k5-int.h" + +krb5_error_code KRB5_CALLCONV +krb5_kt_remove_entry (krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) +{ + if (id->ops->remove) + return (*id->ops->remove)(context, id, entry); + else + return KRB5_KT_NOWRITE; +} +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/krb5/keytab/read_servi.c b/krb5-1.21.3/src/lib/krb5/keytab/read_servi.c new file mode 100644 index 00000000..5d5edffc --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/keytab/read_servi.c @@ -0,0 +1,84 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/keytab/read_servi.c */ +/* + * Copyright 1990,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This routine is designed to be passed to krb5_rd_req. + * It is a convenience function that reads a key out of a keytab. + * It handles all of the opening and closing of the keytab + * internally. + */ +#ifndef LEAN_CLIENT + +#include "k5-int.h" + +#define KSUCCESS 0 + +/* + * effects: If keyprocarg is not NULL, it is taken to be the name of a + * keytab. Otherwise, the default keytab will be used. This + * routine opens the keytab and finds the principal associated with + * principal, vno, and enctype and returns the resulting key in *key + * or returning an error code if it is not found. + * returns: Either KSUCCESS or error code. + * errors: error code if not found or keyprocarg is invalid. + */ +krb5_error_code KRB5_CALLCONV +krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg, krb5_principal principal, krb5_kvno vno, krb5_enctype enctype, krb5_keyblock **key) +{ + krb5_error_code kerror = KSUCCESS; + char keytabname[MAX_KEYTAB_NAME_LEN + 1]; /* + 1 for NULL termination */ + krb5_keytab id; + krb5_keytab_entry entry; + + /* + * Get the name of the file that we should use. + */ + if (!keyprocarg) { + if ((kerror = krb5_kt_default_name(context, (char *)keytabname, + sizeof(keytabname) - 1))!= KSUCCESS) + return (kerror); + } else { + memset(keytabname, 0, sizeof(keytabname)); + (void) strncpy(keytabname, (char *)keyprocarg, + sizeof(keytabname) - 1); + } + + if ((kerror = krb5_kt_resolve(context, (char *)keytabname, &id))) + return (kerror); + + kerror = krb5_kt_get_entry(context, id, principal, vno, enctype, &entry); + krb5_kt_close(context, id); + + if (kerror) + return(kerror); + + krb5_copy_keyblock(context, &entry.key, key); + + krb5_kt_free_entry(context, &entry); + + return (KSUCCESS); +} +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/krb5/keytab/t_keytab.c b/krb5-1.21.3/src/lib/krb5/keytab/t_keytab.c new file mode 100644 index 00000000..aa5153c9 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/keytab/t_keytab.c @@ -0,0 +1,445 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/keytab/t_keytab.c - Tests for keytab interface */ +/* + * Copyright (C) 2007 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "autoconf.h" +#include +#include +#if HAVE_UNISTD_H +#include +#endif +#include + + +int debug=0; + +extern const krb5_kt_ops krb5_ktf_writable_ops; + +#define KRB5_OK 0 + +#define CHECK_ERR(kret,err,msg) \ + if (kret != err) { \ + com_err(msg, kret, ""); \ + fflush(stderr); \ + exit(1); \ + } else if(debug) printf("%s went ok\n", msg); + +#define CHECK(kret,msg) CHECK_ERR(kret, 0, msg) + +#define CHECK_STR(str,msg) \ + if (str == 0) { \ + com_err(msg, kret, ""); \ + exit(1); \ + } else if(debug) printf("%s went ok\n", msg); + +static void +test_misc(krb5_context context) +{ + /* Tests for certain error returns */ + krb5_error_code kret; + krb5_keytab ktid; + char defname[BUFSIZ]; + char *name; + + fprintf(stderr, "Testing miscellaneous error conditions\n"); + + kret = krb5_kt_resolve(context, "unknown_method_ep:/tmp/name", &ktid); + CHECK_ERR(kret, KRB5_KT_UNKNOWN_TYPE, "resolve unknown type"); + + /* Test length limits on krb5_kt_default_name */ + kret = krb5_kt_default_name(context, defname, sizeof(defname)); + CHECK(kret, "krb5_kt_default_name error"); + + /* Now allocate space - without the null... */ + name = malloc(strlen(defname)); + if(!name) { + fprintf(stderr, "Out of memory in testing\n"); + exit(1); + } + kret = krb5_kt_default_name(context, name, strlen(defname)); + free(name); + CHECK_ERR(kret, KRB5_CONFIG_NOTENUFSPACE, "krb5_kt_default_name limited"); +} + +static void +kt_test(krb5_context context, const char *name) +{ + krb5_error_code kret; + krb5_keytab kt; + const char *type; + char buf[BUFSIZ]; + char *p; + krb5_keytab_entry kent, kent2; + krb5_principal princ; + krb5_kt_cursor cursor, cursor2; + int cnt; + krb5_enctype e1 = ENCTYPE_AES128_CTS_HMAC_SHA256_128, + e2 = ENCTYPE_AES256_CTS_HMAC_SHA384_192; + + kret = krb5_kt_resolve(context, name, &kt); + CHECK(kret, "resolve"); + + type = krb5_kt_get_type(context, kt); + CHECK_STR(type, "getting kt type"); + printf(" Type is: %s\n", type); + + kret = krb5_kt_get_name(context, kt, buf, sizeof(buf)); + CHECK(kret, "get_name"); + printf(" Name is: %s\n", buf); + + /* Check that length checks fail */ + /* The buffer is allocated too small - to allow for valgrind test of + overflows + */ + p = malloc(strlen(buf)); + kret = krb5_kt_get_name(context, kt, p, 1); + CHECK_ERR(kret, KRB5_KT_NAME_TOOLONG, "get_name - size 1"); + + + kret = krb5_kt_get_name(context, kt, p, strlen(buf)); + CHECK_ERR(kret, KRB5_KT_NAME_TOOLONG, "get_name"); + free(p); + + /* Try to lookup unknown principal - when keytab does not exist*/ + kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ); + CHECK(kret, "parsing principal"); + + /* This will return ENOENT for FILE because the file doesn't exist, + * so accept that or KRB5_KT_NOTFOUND. */ + kret = krb5_kt_get_entry(context, kt, princ, 0, 0, &kent); + if (kret != ENOENT) { + CHECK_ERR(kret, KRB5_KT_NOTFOUND, "Getting non-existent entry"); + } + + kret = krb5_kt_have_content(context, kt); + CHECK_ERR(kret, KRB5_KT_NOTFOUND, "Checking for keytab content (empty)"); + + + /* =================== Add entries to keytab ================= */ + /* + * Add the following for this principal + * enctype e1, kvno 1, key = "1" + * enctype e2, kvno 1, key = "1" + * enctype e1, kvno 2, key = "2" + */ + memset(&kent, 0, sizeof(kent)); + kent.magic = KV5M_KEYTAB_ENTRY; + kent.principal = princ; + kent.timestamp = 327689; + kent.vno = 1; + kent.key.magic = KV5M_KEYBLOCK; + kent.key.enctype = e1; + kent.key.length = 1; + kent.key.contents = (krb5_octet *) "1"; + + + kret = krb5_kt_add_entry(context, kt, &kent); + CHECK(kret, "Adding initial entry"); + + kent.key.enctype = e2; + kret = krb5_kt_add_entry(context, kt, &kent); + CHECK(kret, "Adding second entry"); + + kent.key.enctype = e1; + kent.vno = 2; + kent.key.contents = (krb5_octet *) "2"; + kret = krb5_kt_add_entry(context, kt, &kent); + CHECK(kret, "Adding third entry"); + + /* Free memory */ + krb5_free_principal(context, princ); + + /* ============== Test iterating over contents of keytab ========= */ + + kret = krb5_kt_have_content(context, kt); + CHECK(kret, "Checking for keytab content (full)"); + + kret = krb5_kt_start_seq_get(context, kt, &cursor); + CHECK(kret, "Start sequence get"); + + + memset(&kent, 0, sizeof(kent)); + cnt = 0; + while((kret = krb5_kt_next_entry(context, kt, &kent, &cursor)) == 0) { + if(((kent.vno != 1) && (kent.vno != 2)) || + ((kent.key.enctype != e1) && (kent.key.enctype != e2)) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Error in read contents\n"); + exit(1); + } + + if((kent.magic != KV5M_KEYTAB_ENTRY) || + (kent.key.magic != KV5M_KEYBLOCK)) { + fprintf(stderr, "Magic number in sequence not proper\n"); + exit(1); + } + + cnt++; + krb5_free_keytab_entry_contents(context, &kent); + } + CHECK_ERR(kret, KRB5_KT_END, "getting next entry"); + + if(cnt != 3) { + fprintf(stderr, "Mismatch in number of entries in keytab"); + } + + kret = krb5_kt_end_seq_get(context, kt, &cursor); + CHECK(kret, "End sequence get"); + + + /* ========================== get_entry tests ============== */ + + /* Try to lookup unknown principal - now that keytab exists*/ + kret = krb5_parse_name(context, "test3/test2@TEST.MIT.EDU", &princ); + CHECK(kret, "parsing principal"); + + + kret = krb5_kt_get_entry(context, kt, princ, 0, 0, &kent); + CHECK_ERR(kret, KRB5_KT_NOTFOUND, "Getting nonexistent entry"); + + krb5_free_principal(context, princ); + + /* Try to lookup known principal */ + kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ); + CHECK(kret, "parsing principal"); + + kret = krb5_kt_get_entry(context, kt, princ, 0, 0, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - we did not specify an enctype or kvno */ + if (!krb5_principal_compare(context, princ, kent.principal) || + ((kent.vno != 1) && (kent.vno != 2)) || + ((kent.key.enctype != e1) && (kent.key.enctype != e2)) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + exit(1); + } + + krb5_free_keytab_entry_contents(context, &kent); + + /* Try to lookup a specific enctype - but unspecified kvno - should give + * max kvno + */ + kret = krb5_kt_get_entry(context, kt, princ, 0, e1, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - we did specified an enctype */ + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 2) || (kent.key.enctype != e1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + + exit(1); + + } + + krb5_free_keytab_entry_contents(context, &kent); + + /* Try to lookup unspecified enctype, but a specified kvno */ + + kret = krb5_kt_get_entry(context, kt, princ, 2, 0, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - we did not specify a kvno */ + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 2) || (kent.key.enctype != e1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + + exit(1); + + } + + krb5_free_keytab_entry_contents(context, &kent); + + + + /* Try to lookup specified enctype and kvno */ + + kret = krb5_kt_get_entry(context, kt, princ, 1, e1, &kent); + CHECK(kret, "looking up principal"); + + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 1) || (kent.key.enctype != e1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + + exit(1); + + } + + krb5_free_keytab_entry_contents(context, &kent); + + + /* Try lookup with active iterators. */ + kret = krb5_kt_start_seq_get(context, kt, &cursor); + CHECK(kret, "Start sequence get(2)"); + kret = krb5_kt_start_seq_get(context, kt, &cursor2); + CHECK(kret, "Start sequence get(3)"); + kret = krb5_kt_next_entry(context, kt, &kent, &cursor); + CHECK(kret, "getting next entry(2)"); + krb5_free_keytab_entry_contents(context, &kent); + kret = krb5_kt_next_entry(context, kt, &kent, &cursor); + CHECK(kret, "getting next entry(3)"); + kret = krb5_kt_next_entry(context, kt, &kent2, &cursor2); + CHECK(kret, "getting next entry(4)"); + krb5_free_keytab_entry_contents(context, &kent2); + kret = krb5_kt_get_entry(context, kt, kent.principal, 0, 0, &kent2); + CHECK(kret, "looking up principal(2)"); + krb5_free_keytab_entry_contents(context, &kent2); + kret = krb5_kt_next_entry(context, kt, &kent2, &cursor2); + CHECK(kret, "getting next entry(5)"); + if (!krb5_principal_compare(context, kent.principal, kent2.principal)) { + fprintf(stderr, "iterators not in sync\n"); + exit(1); + } + krb5_free_keytab_entry_contents(context, &kent); + krb5_free_keytab_entry_contents(context, &kent2); + kret = krb5_kt_next_entry(context, kt, &kent, &cursor); + CHECK(kret, "getting next entry(6)"); + kret = krb5_kt_next_entry(context, kt, &kent2, &cursor2); + CHECK(kret, "getting next entry(7)"); + krb5_free_keytab_entry_contents(context, &kent); + krb5_free_keytab_entry_contents(context, &kent2); + kret = krb5_kt_end_seq_get(context, kt, &cursor); + CHECK(kret, "ending sequence get(1)"); + kret = krb5_kt_end_seq_get(context, kt, &cursor2); + CHECK(kret, "ending sequence get(2)"); + + /* Try to lookup specified enctype and kvno - that does not exist*/ + + kret = krb5_kt_get_entry(context, kt, princ, 3, e1, &kent); + CHECK_ERR(kret, KRB5_KT_KVNONOTFOUND, + "looking up specific principal, kvno, enctype"); + + krb5_free_principal(context, princ); + + + /* ========================= krb5_kt_remove_entry =========== */ + /* Lookup the keytab entry w/ 2 kvno - and delete version 2 - + ensure gone */ + kret = krb5_parse_name(context, "test/test2@TEST.MIT.EDU", &princ); + CHECK(kret, "parsing principal"); + + kret = krb5_kt_get_entry(context, kt, princ, 0, e1, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - we are looking for max(kvno) and enc=e1 */ + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 2) || (kent.key.enctype != e1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Retrieved principal does not check\n"); + + exit(1); + + } + + /* Delete it */ + kret = krb5_kt_remove_entry(context, kt, &kent); + CHECK(kret, "Removing entry"); + + krb5_free_keytab_entry_contents(context, &kent); + /* And ensure gone */ + + kret = krb5_kt_get_entry(context, kt, princ, 0, e1, &kent); + CHECK(kret, "looking up principal"); + + /* Ensure a valid answer - kvno should now be 1 - we deleted 2 */ + if (!krb5_principal_compare(context, princ, kent.principal) || + (kent.vno != 1) || (kent.key.enctype != e1) || + (kent.key.length != 1) || + (kent.key.contents[0] != kent.vno +'0')) { + fprintf(stderr, "Delete principal check failed\n"); + + exit(1); + + } + krb5_free_keytab_entry_contents(context, &kent); + + krb5_free_principal(context, princ); + + /* ======================= Finally close ======================= */ + + kret = krb5_kt_close(context, kt); + CHECK(kret, "close"); + +} + +static void +do_test(krb5_context context, const char *prefix, krb5_boolean delete) +{ + char *name, *filename; + + if (asprintf(&filename, "/tmp/kttest.%ld", (long) getpid()) < 0) { + perror("asprintf"); + exit(1); + } + if (asprintf(&name, "%s%s", prefix, filename) < 0) { + perror("asprintf"); + exit(1); + } + printf("Starting test on %s\n", name); + kt_test(context, name); + printf("Test on %s passed\n", name); + if(delete) + unlink(filename); + free(filename); + free(name); + +} + +int +main(void) +{ + krb5_context context; + krb5_error_code kret; + + + if ((kret = krb5_init_context(&context))) { + printf("Couldn't initialize krb5 library: %s\n", + error_message(kret)); + exit(1); + } + + /* All keytab types are registered by default -- test for + redundant error */ + kret = krb5_kt_register(context, &krb5_ktf_writable_ops); + CHECK_ERR(kret, KRB5_KT_TYPE_EXISTS, "register ktf_writable"); + + test_misc(context); + do_test(context, "WRFILE:", FALSE); + do_test(context, "MEMORY:", TRUE); + + krb5_free_context(context); + return 0; + +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/Makefile.in b/krb5-1.21.3/src/lib/krb5/krb/Makefile.in new file mode 100644 index 00000000..e4b560fb --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/Makefile.in @@ -0,0 +1,550 @@ +mydir=lib$(S)krb5$(S)krb +BUILDTOP=$(REL)..$(S)..$(S).. +LOCALINCLUDES = -I$(srcdir)/../os -I$(top_srcdir) +DEFINES=-DLIBDIR=\"$(KRB5_LIBDIR)\" -DDYNOBJEXT=\"$(DYNOBJEXT)\" + +# Like RUN_TEST, but use t_krb5.conf from this directory. +RUN_TEST_LOCAL_CONF=$(RUN_SETUP) KRB5_CONFIG=$(srcdir)/t_krb5.conf LC_ALL=C \ + $(VALGRIND) + +##DOS##BUILDTOP = ..\..\.. +##DOS##PREFIXDIR=krb +##DOS##OBJFILE=..\$(OUTPRE)$(PREFIXDIR).lst + +STLIBOBJS= \ + addr_comp.o \ + addr_order.o \ + addr_srch.o \ + allow_weak.o \ + appdefault.o \ + ai_authdata.o \ + auth_con.o \ + cammac_util.o \ + authdata.o \ + authdata_exp.o \ + authdata_enc.o \ + authdata_dec.o \ + bld_pr_ext.o \ + bld_princ.o \ + chk_trans.o \ + chpw.o \ + conv_creds.o \ + conv_princ.o \ + copy_addrs.o \ + copy_auth.o \ + copy_athctr.o \ + copy_cksum.o \ + copy_creds.o \ + copy_data.o \ + copy_key.o \ + copy_princ.o \ + copy_tick.o \ + cp_key_cnt.o \ + decode_kdc.o \ + decrypt_tk.o \ + deltat.o \ + enc_helper.o \ + enc_keyhelper.o \ + encode_kdc.o \ + encrypt_tk.o \ + etype_list.o \ + fast.o \ + fwd_tgt.o \ + gc_via_tkt.o \ + gen_seqnum.o \ + gen_subkey.o \ + gen_save_subkey.o \ + get_creds.o \ + get_etype_info.o \ + get_in_tkt.o \ + gic_keytab.o \ + gic_opt.o \ + gic_pwd.o \ + in_tkt_sky.o \ + init_ctx.o \ + copy_ctx.o \ + init_keyblock.o \ + kdc_rep_dc.o \ + kerrs.o \ + kfree.o \ + libdef_parse.o \ + mk_cred.o \ + mk_error.o \ + mk_priv.o \ + mk_rep.o \ + mk_req.o \ + mk_req_ext.o \ + mk_safe.o \ + pac.o \ + pac_sign.o \ + padata.o \ + parse.o \ + parse_host_string.o \ + plugin.o \ + pr_to_salt.o \ + preauth2.o \ + preauth_ec.o \ + preauth_encts.o \ + preauth_otp.o \ + preauth_pkinit.o \ + preauth_sam2.o \ + princ_comp.o \ + privsafe.o \ + random_str.o \ + rd_cred.o \ + rd_error.o \ + rd_priv.o \ + rd_rep.o \ + rd_req.o \ + rd_req_dec.o \ + rd_safe.o \ + recvauth.o \ + response_items.o \ + s4u_creds.o \ + sendauth.o \ + send_tgs.o \ + ser_actx.o \ + ser_adata.o \ + ser_addr.o \ + ser_auth.o \ + ser_cksum.o \ + ser_ctx.o \ + ser_key.o \ + ser_princ.o \ + serialize.o \ + set_realm.o \ + sname_match.o \ + srv_dec_tkt.o \ + srv_rcache.o \ + str_conv.o \ + tgtname.o \ + unparse.o \ + val_renew.o \ + valid_times.o \ + vfy_increds.o \ + vic_opt.o \ + walk_rtree.o + +OBJS= $(OUTPRE)addr_comp.$(OBJEXT) \ + $(OUTPRE)addr_order.$(OBJEXT) \ + $(OUTPRE)addr_srch.$(OBJEXT) \ + $(OUTPRE)allow_weak.$(OBJEXT) \ + $(OUTPRE)appdefault.$(OBJEXT) \ + $(OUTPRE)ai_authdata.$(OBJEXT) \ + $(OUTPRE)auth_con.$(OBJEXT) \ + $(OUTPRE)cammac_util.$(OBJEXT) \ + $(OUTPRE)authdata.$(OBJEXT) \ + $(OUTPRE)authdata_exp.$(OBJEXT) \ + $(OUTPRE)authdata_enc.$(OBJEXT) \ + $(OUTPRE)authdata_dec.$(OBJEXT) \ + $(OUTPRE)bld_pr_ext.$(OBJEXT) \ + $(OUTPRE)bld_princ.$(OBJEXT) \ + $(OUTPRE)chk_trans.$(OBJEXT) \ + $(OUTPRE)chpw.$(OBJEXT) \ + $(OUTPRE)conv_creds.$(OBJEXT) \ + $(OUTPRE)conv_princ.$(OBJEXT) \ + $(OUTPRE)copy_addrs.$(OBJEXT) \ + $(OUTPRE)copy_auth.$(OBJEXT) \ + $(OUTPRE)copy_athctr.$(OBJEXT) \ + $(OUTPRE)copy_cksum.$(OBJEXT) \ + $(OUTPRE)copy_creds.$(OBJEXT) \ + $(OUTPRE)copy_data.$(OBJEXT) \ + $(OUTPRE)copy_key.$(OBJEXT) \ + $(OUTPRE)copy_princ.$(OBJEXT) \ + $(OUTPRE)copy_tick.$(OBJEXT) \ + $(OUTPRE)cp_key_cnt.$(OBJEXT) \ + $(OUTPRE)decode_kdc.$(OBJEXT) \ + $(OUTPRE)decrypt_tk.$(OBJEXT) \ + $(OUTPRE)deltat.$(OBJEXT) \ + $(OUTPRE)enc_helper.$(OBJEXT) \ + $(OUTPRE)enc_keyhelper.$(OBJEXT) \ + $(OUTPRE)encode_kdc.$(OBJEXT) \ + $(OUTPRE)encrypt_tk.$(OBJEXT) \ + $(OUTPRE)etype_list.$(OBJEXT) \ + $(OUTPRE)fast.$(OBJEXT) \ + $(OUTPRE)fwd_tgt.$(OBJEXT) \ + $(OUTPRE)gc_via_tkt.$(OBJEXT) \ + $(OUTPRE)gen_seqnum.$(OBJEXT) \ + $(OUTPRE)gen_subkey.$(OBJEXT) \ + $(OUTPRE)gen_save_subkey.$(OBJEXT) \ + $(OUTPRE)get_creds.$(OBJEXT) \ + $(OUTPRE)get_etype_info.$(OBJEXT) \ + $(OUTPRE)get_in_tkt.$(OBJEXT) \ + $(OUTPRE)gic_keytab.$(OBJEXT) \ + $(OUTPRE)gic_opt.$(OBJEXT) \ + $(OUTPRE)gic_pwd.$(OBJEXT) \ + $(OUTPRE)in_tkt_sky.$(OBJEXT) \ + $(OUTPRE)init_ctx.$(OBJEXT) \ + $(OUTPRE)copy_ctx.$(OBJEXT) \ + $(OUTPRE)init_keyblock.$(OBJEXT) \ + $(OUTPRE)kdc_rep_dc.$(OBJEXT) \ + $(OUTPRE)kerrs.$(OBJEXT) \ + $(OUTPRE)kfree.$(OBJEXT) \ + $(OUTPRE)libdef_parse.$(OBJEXT) \ + $(OUTPRE)mk_cred.$(OBJEXT) \ + $(OUTPRE)mk_error.$(OBJEXT) \ + $(OUTPRE)mk_priv.$(OBJEXT) \ + $(OUTPRE)mk_rep.$(OBJEXT) \ + $(OUTPRE)mk_req.$(OBJEXT) \ + $(OUTPRE)mk_req_ext.$(OBJEXT) \ + $(OUTPRE)mk_safe.$(OBJEXT) \ + $(OUTPRE)pac.$(OBJEXT) \ + $(OUTPRE)pac_sign.$(OBJEXT) \ + $(OUTPRE)padata.$(OBJEXT) \ + $(OUTPRE)parse.$(OBJEXT) \ + $(OUTPRE)parse_host_string.$(OBJEXT) \ + $(OUTPRE)plugin.$(OBJEXT) \ + $(OUTPRE)pr_to_salt.$(OBJEXT) \ + $(OUTPRE)preauth2.$(OBJEXT) \ + $(OUTPRE)preauth_ec.$(OBJEXT) \ + $(OUTPRE)preauth_encts.$(OBJEXT) \ + $(OUTPRE)preauth_otp.$(OBJEXT) \ + $(OUTPRE)preauth_pkinit.$(OBJEXT) \ + $(OUTPRE)preauth_sam2.$(OBJEXT) \ + $(OUTPRE)princ_comp.$(OBJEXT) \ + $(OUTPRE)privsafe.$(OBJEXT) \ + $(OUTPRE)random_str.$(OBJEXT) \ + $(OUTPRE)rd_cred.$(OBJEXT) \ + $(OUTPRE)rd_error.$(OBJEXT) \ + $(OUTPRE)rd_priv.$(OBJEXT) \ + $(OUTPRE)rd_rep.$(OBJEXT) \ + $(OUTPRE)rd_req.$(OBJEXT) \ + $(OUTPRE)rd_req_dec.$(OBJEXT) \ + $(OUTPRE)rd_safe.$(OBJEXT) \ + $(OUTPRE)recvauth.$(OBJEXT) \ + $(OUTPRE)response_items.$(OBJEXT) \ + $(OUTPRE)s4u_creds.$(OBJEXT) \ + $(OUTPRE)sendauth.$(OBJEXT) \ + $(OUTPRE)send_tgs.$(OBJEXT) \ + $(OUTPRE)ser_actx.$(OBJEXT) \ + $(OUTPRE)ser_adata.$(OBJEXT) \ + $(OUTPRE)ser_addr.$(OBJEXT) \ + $(OUTPRE)ser_auth.$(OBJEXT) \ + $(OUTPRE)ser_cksum.$(OBJEXT) \ + $(OUTPRE)ser_ctx.$(OBJEXT) \ + $(OUTPRE)ser_key.$(OBJEXT) \ + $(OUTPRE)ser_princ.$(OBJEXT) \ + $(OUTPRE)serialize.$(OBJEXT) \ + $(OUTPRE)set_realm.$(OBJEXT) \ + $(OUTPRE)sname_match.$(OBJEXT) \ + $(OUTPRE)srv_dec_tkt.$(OBJEXT) \ + $(OUTPRE)srv_rcache.$(OBJEXT) \ + $(OUTPRE)str_conv.$(OBJEXT) \ + $(OUTPRE)tgtname.$(OBJEXT) \ + $(OUTPRE)unparse.$(OBJEXT) \ + $(OUTPRE)val_renew.$(OBJEXT) \ + $(OUTPRE)valid_times.$(OBJEXT) \ + $(OUTPRE)vfy_increds.$(OBJEXT) \ + $(OUTPRE)vic_opt.$(OBJEXT) \ + $(OUTPRE)walk_rtree.$(OBJEXT) + +SRCS= $(srcdir)/addr_comp.c \ + $(srcdir)/addr_order.c \ + $(srcdir)/addr_srch.c \ + $(srcdir)/appdefault.c \ + $(srcdir)/auth_con.c \ + $(srcdir)/cammac_util.c \ + $(srcdir)/ai_authdata.c \ + $(srcdir)/authdata.c \ + $(srcdir)/authdata_exp.c \ + $(srcdir)/authdata_enc.c \ + $(srcdir)/authdata_dec.c \ + $(srcdir)/bld_pr_ext.c \ + $(srcdir)/bld_princ.c \ + $(srcdir)/brand.c \ + $(srcdir)/chk_trans.c \ + $(srcdir)/chpw.c \ + $(srcdir)/conv_creds.c \ + $(srcdir)/conv_princ.c \ + $(srcdir)/copy_addrs.c \ + $(srcdir)/copy_auth.c \ + $(srcdir)/copy_athctr.c \ + $(srcdir)/copy_cksum.c \ + $(srcdir)/copy_creds.c \ + $(srcdir)/copy_data.c \ + $(srcdir)/copy_key.c \ + $(srcdir)/copy_princ.c \ + $(srcdir)/copy_tick.c \ + $(srcdir)/cp_key_cnt.c \ + $(srcdir)/decode_kdc.c \ + $(srcdir)/decrypt_tk.c \ + $(srcdir)/deltat.c \ + $(srcdir)/enc_helper.c \ + $(srcdir)/enc_keyhelper.c \ + $(srcdir)/encode_kdc.c \ + $(srcdir)/encrypt_tk.c \ + $(srcdir)/etype_list.c \ + $(srcdir)/fast.c \ + $(srcdir)/fwd_tgt.c \ + $(srcdir)/gc_via_tkt.c \ + $(srcdir)/gen_seqnum.c \ + $(srcdir)/gen_subkey.c \ + $(srcdir)/gen_save_subkey.c \ + $(srcdir)/get_creds.c \ + $(srcdir)/get_etype_info.c \ + $(srcdir)/get_in_tkt.c \ + $(srcdir)/gic_keytab.c \ + $(srcdir)/gic_opt.c \ + $(srcdir)/gic_pwd.c \ + $(srcdir)/in_tkt_sky.c \ + $(srcdir)/init_ctx.c \ + $(srcdir)/copy_ctx.c \ + $(srcdir)/init_keyblock.c \ + $(srcdir)/kdc_rep_dc.c \ + $(srcdir)/kerrs.c \ + $(srcdir)/kfree.c \ + $(srcdir)/libdef_parse.c \ + $(srcdir)/mk_cred.c \ + $(srcdir)/mk_error.c \ + $(srcdir)/mk_priv.c \ + $(srcdir)/mk_rep.c \ + $(srcdir)/mk_req.c \ + $(srcdir)/mk_req_ext.c \ + $(srcdir)/mk_safe.c \ + $(srcdir)/pac.c \ + $(srcdir)/pac_sign.c \ + $(srcdir)/padata.c \ + $(srcdir)/parse.c \ + $(srcdir)/parse_host_string.c \ + $(srcdir)/plugin.c \ + $(srcdir)/pr_to_salt.c \ + $(srcdir)/preauth2.c \ + $(srcdir)/preauth_ec.c \ + $(srcdir)/preauth_encts.c \ + $(srcdir)/preauth_otp.c \ + $(srcdir)/preauth_pkinit.c \ + $(srcdir)/preauth_sam2.c \ + $(srcdir)/princ_comp.c \ + $(srcdir)/privsafe.c \ + $(srcdir)/random_str.c \ + $(srcdir)/rd_cred.c \ + $(srcdir)/rd_error.c \ + $(srcdir)/rd_priv.c \ + $(srcdir)/rd_rep.c \ + $(srcdir)/rd_req.c \ + $(srcdir)/rd_req_dec.c \ + $(srcdir)/rd_safe.c \ + $(srcdir)/recvauth.c \ + $(srcdir)/response_items.c \ + $(srcdir)/s4u_creds.c \ + $(srcdir)/sendauth.c \ + $(srcdir)/send_tgs.c \ + $(srcdir)/ser_actx.c \ + $(srcdir)/ser_adata.c \ + $(srcdir)/ser_addr.c \ + $(srcdir)/ser_auth.c \ + $(srcdir)/ser_cksum.c \ + $(srcdir)/ser_ctx.c \ + $(srcdir)/ser_key.c \ + $(srcdir)/ser_princ.c \ + $(srcdir)/serialize.c \ + $(srcdir)/set_realm.c \ + $(srcdir)/sname_match.c \ + $(srcdir)/srv_dec_tkt.c \ + $(srcdir)/srv_rcache.c \ + $(srcdir)/str_conv.c \ + $(srcdir)/t_ad_fx_armor.c \ + $(srcdir)/tgtname.c \ + $(srcdir)/unparse.c \ + $(srcdir)/val_renew.c \ + $(srcdir)/valid_times.c \ + $(srcdir)/vfy_increds.c \ + $(srcdir)/vic_opt.c \ + $(srcdir)/walk_rtree.c \ + $(srcdir)/t_walk_rtree.c \ + $(srcdir)/t_kerb.c \ + $(srcdir)/t_ser.c \ + $(srcdir)/t_deltat.c \ + $(srcdir)/t_expand.c \ + $(srcdir)/t_get_etype_info.c \ + $(srcdir)/t_pac.c \ + $(srcdir)/t_parse_host_string.c \ + $(srcdir)/t_princ.c \ + $(srcdir)/t_etypes.c \ + $(srcdir)/t_expire_warn.c \ + $(srcdir)/t_authdata.c \ + $(srcdir)/t_cc_config.c \ + $(srcdir)/t_copy_context.c \ + $(srcdir)/t_in_ccache.c \ + $(srcdir)/t_response_items.c \ + $(srcdir)/t_sname_match.c \ + $(srcdir)/t_valid_times.c \ + $(srcdir)/t_vfy_increds.c + +# Someday, when we have a "maintainer mode", do this right: +BISON=bison +BISONFLAGS= # -v -> .output; -d -> .h +DELTAT_DEP=@MAINT@ x-deltat.y +##WIN32##DELTAT_DEP= + +$(srcdir)/deltat.c : $(DELTAT_DEP) + (cd $(srcdir) && $(BISON) $(BISONFLAGS) -o deltat.c x-deltat.y) + +##DOS##LIBOBJS = $(OBJS) + +all-unix: all-libobjs +clean-unix:: clean-libobjs + +COMERRLIB=$(TOPLIBD)/libcom_err.a + +T_WALK_RTREE_OBJS= t_walk_rtree.o + +T_KERB_OBJS= t_kerb.o conv_princ.o unparse.o set_realm.o str_conv.o + +T_SER_OBJS= t_ser.o ser_actx.o ser_adata.o ser_addr.o ser_auth.o ser_cksum.o \ + ser_ctx.o ser_key.o ser_princ.o serialize.o authdata.o pac.o \ + pac_sign.o ai_authdata.o authdata_exp.o copy_data.o etype_list.o + +T_DELTAT_OBJS= t_deltat.o deltat.o + +T_PAC_OBJS= t_pac.o pac.o pac_sign.o copy_data.o + +T_PRINC_OBJS= t_princ.o + +T_ETYPES_OBJS= t_etypes.o init_ctx.o etype_list.o plugin.o + +T_PARSE_HOST_STRING_OBJS= t_parse_host_string.o parse_host_string.o + +t_walk_rtree: $(T_WALK_RTREE_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_walk_rtree $(T_WALK_RTREE_OBJS) $(KRB5_BASE_LIBS) +t_ad_fx_armor: t_ad_fx_armor.o + $(CC_LINK) -o $@ t_ad_fx_armor.o $(KRB5_BASE_LIBS) + +t_authdata: t_authdata.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_authdata.o $(KRB5_BASE_LIBS) + +t_kerb: $(T_KERB_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_kerb $(T_KERB_OBJS) $(KRB5_BASE_LIBS) + +t_ser: $(T_SER_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_ser $(T_SER_OBJS) $(KRB5_BASE_LIBS) + +t_deltat : $(T_DELTAT_OBJS) $(SUPPORT_DEPLIB) + $(CC_LINK) -o t_deltat $(T_DELTAT_OBJS) $(SUPPORT_LIB) + +T_EXPAND_OBJS=t_expand.o +t_expand.o : t_expand.c +t_expand : $(T_EXPAND_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_expand $(T_EXPAND_OBJS) $(KRB5_BASE_LIBS) + +t_pac: $(T_PAC_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_pac $(T_PAC_OBJS) $(KRB5_BASE_LIBS) + +t_princ: $(T_PRINC_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_princ $(T_PRINC_OBJS) $(KRB5_BASE_LIBS) + +t_etypes: $(T_ETYPES_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_etypes $(T_ETYPES_OBJS) $(KRB5_BASE_LIBS) + +t_parse_host_string: $(T_PARSE_HOST_STRING_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ $(T_PARSE_HOST_STRING_OBJS) $(CMOCKA_LIBS) \ + $(KRB5_BASE_LIBS) + +t_expire_warn: t_expire_warn.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_expire_warn.o $(KRB5_BASE_LIBS) + +t_vfy_increds: t_vfy_increds.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_vfy_increds.o $(KRB5_BASE_LIBS) + +t_in_ccache: t_in_ccache.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_in_ccache.o $(KRB5_BASE_LIBS) + +t_cc_config: t_cc_config.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_cc_config.o $(KRB5_BASE_LIBS) + +t_copy_context: t_copy_context.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_copy_context.o $(KRB5_BASE_LIBS) + +t_response_items: t_response_items.o response_items.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_response_items.o response_items.o $(KRB5_BASE_LIBS) + +t_sname_match: t_sname_match.o sname_match.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_sname_match.o sname_match.o $(KRB5_BASE_LIBS) + +t_valid_times: t_valid_times.o valid_times.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_valid_times.o valid_times.o $(KRB5_BASE_LIBS) + +t_get_etype_info: t_get_etype_info.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_get_etype_info.o $(KRB5_BASE_LIBS) + +TEST_PROGS= t_walk_rtree t_kerb t_ser t_deltat t_expand t_authdata t_pac \ + t_in_ccache t_cc_config t_copy_context t_princ t_etypes t_vfy_increds \ + t_response_items t_sname_match t_valid_times t_get_etype_info + +check-unix: $(TEST_PROGS) runenv.sh + $(RUN_TEST_LOCAL_CONF) ./t_kerb \ + parse_name tytso \ + parse_name tytso@SHAZAAM \ + parse_name tytso/root@VEGGIE.COM \ + parse_name tytso/tuber/carrot@VEGGIE.COM \ + parse_name tytso/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t \ + parse_name tytso/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t@FOO \ + parse_name tytso\\\\0/\\0@B\\n\\t\\\\GAG \ + parse_name tytso/\\n/\\b\\t@B\\0hacky-test \ + parse_name \\/slash/\\@atsign/octa\\/thorpe@\\/slash\\@at\\/sign \ + name_type host/www.krb5.test@KRB5.TEST \ + name_type krbtg/KRB5.TEST@KRB5.TEST \ + name_type krbtgt/KRB5.TEST@KRB5.TEST \ + name_type WELLKNOWN/ANONYMOUS@KRB5.TEST \ + 425_conv_principal rcmd e40-po ATHENA.MIT.EDU \ + 425_conv_principal rcmd mit ATHENA.MIT.EDU \ + 425_conv_principal rcmd lithium ATHENA.MIT.EDU \ + 425_conv_principal rcmd tweedledumb CYGNUS.COM \ + 425_conv_principal rcmd uunet UU.NET \ + 425_conv_principal zephyr zephyr ATHENA.MIT.EDU \ + 425_conv_principal kadmin ATHENA.MIT.EDU ATHENA.MIT.EDU \ + 524_conv_principal host/e40-po.mit.edu@ATHENA.MIT.EDU \ + 524_conv_principal host/foobar.stanford.edu@stanford.edu \ + set_realm marc@MIT.EDU CYGNUS.COM \ + > test.out + cmp test.out $(srcdir)/t_ref_kerb.out + $(RM) test.out + $(RUN_TEST) ./t_ser + $(RUN_TEST) ./t_deltat + $(RUN_TEST) sh $(srcdir)/transit-tests + $(RUN_TEST_LOCAL_CONF) sh $(srcdir)/walktree-tests + $(RUN_TEST) ./t_authdata + $(RUN_TEST) ./t_pac + $(RUN_TEST) ./t_princ + $(RUN_TEST) ./t_etypes + $(RUN_TEST) ./t_response_items + $(RUN_TEST) ./t_copy_context + $(RUN_TEST) ./t_sname_match + $(RUN_TEST) ./t_valid_times + +check-pytests: t_expire_warn t_get_etype_info t_vfy_increds + $(RUNPYTEST) $(srcdir)/t_expire_warn.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_vfy_increds.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_in_ccache_patypes.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_get_etype_info.py $(PYTESTFLAGS) + +check-cmocka: t_parse_host_string + $(RUN_TEST) ./t_parse_host_string > /dev/null + +clean: + $(RM) $(OUTPRE)t_walk_rtree$(EXEEXT) $(OUTPRE)t_walk_rtree.$(OBJEXT) \ + $(OUTPRE)t_kerb$(EXEEXT) $(OUTPRE)t_kerb.$(OBJEXT) \ + $(OUTPRE)t_ser$(EXEEXT) $(OUTPRE)t_ser.$(OBJEXT) \ + $(OUTPRE)t_deltat$(EXEEXT) $(OUTPRE)t_deltat.$(OBJEXT) \ + $(OUTPRE)t_expand$(EXEEXT) $(OUTPRE)t_expand.$(OBJEXT) \ + $(OUTPRE)t_expire_warn$(EXEEXT) $(OUTPRE)t_expire_warn.$(OBJEXT) \ + $(OUTPRE)t_etypes$(EXEEXT) $(OUTPRE)t_etypes.$(OBJEXT) \ + $(OUTPRE)t_pac$(EXEEXT) $(OUTPRE)t_pac.$(OBJEXT) \ + $(OUTPRE)t_princ$(EXEEXT) $(OUTPRE)t_princ.$(OBJEXT) \ + $(OUTPRE)t_authdata$(EXEEXT) $(OUTPRE)t_authdata.$(OBJEXT) \ + $(OUTPRE)t_cc_config$(EXEEXT) $(OUTPRE)t_cc_config.$(OBJEXT) \ + $(OUTPRE)t_copy_context$(EXEEXT) $(OUTPRE)t_copy_context.$(OBJEXT) \ + $(OUTPRE)t_in_ccache$(EXEEXT) $(OUTPRE)t_in_ccache.$(OBJEXT) \ + $(OUTPRE)t_ad_fx_armor$(EXEEXT) $(OUTPRE)t_ad_fx_armor.$(OBJEXT) \ + $(OUTPRE)t_vfy_increds$(EXEEXT) $(OUTPRE)t_vfy_increds.$(OBJEXT) \ + $(OUTPRE)t_response_items$(EXEEXT) \ + $(OUTPRE)t_response_items.$(OBJEXT) \ + $(OUTPRE)t_sname_match$(EXEEXT) $(OUTPRE)t_sname_match.$(OBJEXT) \ + $(OUTPRE)t_valid_times$(EXEEXT) $(OUTPRE)t_valid_times.$(OBJEXT) \ + $(OUTPRE)t_get_etype_info$(EXEEXT) \ + $(OUTPRE)t_get_etype_info.$(OBJEXT) \ + $(OUTPRE)t_parse_host_string$(EXEEXT) \ + $(OUTPRE)t_parse_host_string.$(OBJEXT) + +@libobj_frag@ + diff --git a/krb5-1.21.3/src/lib/krb5/krb/addr_comp.c b/krb5-1.21.3/src/lib/krb5/krb/addr_comp.c new file mode 100644 index 00000000..12177e6e --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/addr_comp.c @@ -0,0 +1,45 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/addr_comp.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +/* + * If the two addresses are the same, return TRUE, else return FALSE + */ +krb5_boolean KRB5_CALLCONV +krb5_address_compare(krb5_context context, const krb5_address *addr1, const krb5_address *addr2) +{ + if (addr1->addrtype != addr2->addrtype) + return(FALSE); + + if (addr1->length != addr2->length) + return(FALSE); + if (memcmp((char *)addr1->contents, (char *)addr2->contents, + addr1->length)) + return FALSE; + else + return TRUE; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/addr_order.c b/krb5-1.21.3/src/lib/krb5/krb/addr_order.c new file mode 100644 index 00000000..39c9e1e6 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/addr_order.c @@ -0,0 +1,60 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/addr_order.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* + * Return an ordering on two addresses: 0 if the same, + * < 0 if first is less than 2nd, > 0 if first is greater than 2nd. + */ +int KRB5_CALLCONV +krb5_address_order(krb5_context context, const krb5_address *addr1, const krb5_address *addr2) +{ + int dir; + int i; + const int minlen = min(addr1->length, addr2->length); + + if (addr1->addrtype != addr2->addrtype) + return(FALSE); + + dir = addr1->length - addr2->length; + + + for (i = 0; i < minlen; i++) { + if ((unsigned char) addr1->contents[i] < + (unsigned char) addr2->contents[i]) + return -1; + else if ((unsigned char) addr1->contents[i] > + (unsigned char) addr2->contents[i]) + return 1; + } + /* compared equal so far...which is longer? */ + return dir; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/addr_srch.c b/krb5-1.21.3/src/lib/krb5/krb/addr_srch.c new file mode 100644 index 00000000..113c5209 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/addr_srch.c @@ -0,0 +1,65 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/addr_srch.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +static unsigned int +address_count(krb5_address *const *addrlist) +{ + unsigned int i; + + if (addrlist == NULL) + return 0; + + for (i = 0; addrlist[i]; i++) + ; + + return i; +} + +/* + * if addr is listed in addrlist, or addrlist is null, return TRUE. + * if not listed, return FALSE + */ +krb5_boolean +krb5_address_search(krb5_context context, const krb5_address *addr, krb5_address *const *addrlist) +{ + /* + * Treat an address list containing only a NetBIOS address + * as empty, because we presently have no way of associating + * a client with its NetBIOS address. + */ + if (address_count(addrlist) == 1 && + addrlist[0]->addrtype == ADDRTYPE_NETBIOS) + return TRUE; + if (!addrlist) + return TRUE; + for (; *addrlist; addrlist++) { + if (krb5_address_compare(context, addr, *addrlist)) + return TRUE; + } + return FALSE; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/ai_authdata.c b/krb5-1.21.3/src/lib/krb5/krb/ai_authdata.c new file mode 100644 index 00000000..4ac28ff8 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/ai_authdata.c @@ -0,0 +1,341 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* src/lib/krb5/krb/ai_authdata.c - auth-indicator authdata module */ +/* + * Copyright (C) 2016 by Red Hat, Inc. + * 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. + */ + +#include "k5-int.h" +#include "authdata.h" +#include "auth_con.h" +#include "int-proto.h" + +struct authind_context { + krb5_data **indicators; +}; + +static krb5_error_code +authind_init(krb5_context kcontext, void **plugin_context) +{ + *plugin_context = NULL; + return 0; +} + +static void +authind_flags(krb5_context kcontext, void *plugin_context, + krb5_authdatatype ad_type, krb5_flags *flags) +{ + *flags = AD_CAMMAC_PROTECTED; +} + +static krb5_error_code +authind_request_init(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void **request_context) +{ + krb5_error_code ret = 0; + struct authind_context *aictx; + + *request_context = NULL; + + aictx = k5alloc(sizeof(*aictx), &ret); + if (aictx == NULL) + return ret; + aictx->indicators = NULL; + *request_context = aictx; + return ret; +} + +static krb5_error_code +authind_import_authdata(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context, + krb5_authdata **authdata, krb5_boolean kdc_issued, + krb5_const_principal kdc_issuer) +{ + struct authind_context *aictx = request_context; + krb5_error_code ret = 0; + krb5_data **indps = NULL; + int i; + + for (i = 0; authdata != NULL && authdata[i] != NULL; i++) { + ret = k5_authind_decode(authdata[i], &indps); + if (ret) + goto cleanup; + } + + if (indps != NULL && *indps != NULL) { + aictx->indicators = indps; + indps = NULL; + } + +cleanup: + k5_free_data_ptr_list(indps); + return ret; +} + +static void +authind_request_fini(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context) +{ + struct authind_context *aictx = request_context; + + if (aictx != NULL) { + k5_free_data_ptr_list(aictx->indicators); + free(aictx); + } +} + +/* This is a non-URI "local attribute" that is implementation defined. */ +static krb5_data authind_attr = { + KV5M_DATA, + sizeof("auth-indicators") - 1, + "auth-indicators" +}; + +static krb5_error_code +authind_get_attribute_types(krb5_context kcontext, + krb5_authdata_context context, + void *plugin_context, void *request_context, + krb5_data **out_attrs) +{ + struct authind_context *aictx = request_context; + krb5_error_code ret; + krb5_data *attrs; + + *out_attrs = NULL; + + if (aictx->indicators == NULL || *aictx->indicators == NULL) + return ENOENT; + + attrs = k5calloc(2, sizeof(*attrs), &ret); + if (attrs == NULL) + return ENOMEM; + + ret = krb5int_copy_data_contents(kcontext, &authind_attr, &attrs[0]); + if (ret) + goto cleanup; + + attrs[1].data = NULL; + attrs[1].length = 0; + + *out_attrs = attrs; + attrs = NULL; + +cleanup: + krb5int_free_data_list(kcontext, attrs); + return ret; +} + +static krb5_error_code +authind_get_attribute(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context, + const krb5_data *attribute, krb5_boolean *authenticated, + krb5_boolean *complete, krb5_data *value, + krb5_data *display_value, int *more) +{ + struct authind_context *aictx = request_context; + krb5_error_code ret; + int ind; + + if (!data_eq(*attribute, authind_attr)) + return ENOENT; + + /* *more will be -1 on the first call, or the next index on subsequent + * calls. */ + ind = (*more < 0) ? 0 : *more; + if (aictx->indicators == NULL || aictx->indicators[ind] == NULL) + return ENOENT; + + ret = krb5int_copy_data_contents(kcontext, aictx->indicators[ind], value); + if (ret) + return ret; + + /* Set *more to the next index, or to 0 if there are no more. */ + *more = (aictx->indicators[ind + 1] == NULL) ? 0 : ind + 1; + + /* Indicators are delivered in a CAMMAC verified outside of this module, + * so these are authenticated values. */ + *authenticated = TRUE; + *complete = TRUE; + + return ret; +} + +static krb5_error_code +authind_set_attribute(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context, + krb5_boolean complete, const krb5_data *attribute, + const krb5_data *value) +{ + /* Indicators are imported from ticket authdata, not set by this module. */ + if (!data_eq(*attribute, authind_attr)) + return ENOENT; + + return EPERM; +} + +static krb5_error_code +authind_size(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context, size_t *sizep) +{ + struct authind_context *aictx = request_context; + int i; + + /* Add the indicator count. */ + *sizep += sizeof(int32_t); + + /* Add each indicator's length and value. */ + for (i = 0; aictx->indicators != NULL && aictx->indicators[i] != NULL; i++) + *sizep += sizeof(int32_t) + aictx->indicators[i]->length; + + return 0; +} + +static krb5_error_code +authind_externalize(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context, + uint8_t **buffer, size_t *lenremain) +{ + struct authind_context *aictx = request_context; + krb5_error_code ret = 0; + uint8_t *bp = *buffer; + size_t remain = *lenremain; + int i, count; + + if (aictx->indicators == NULL) + return krb5_ser_pack_int32(0, buffer, lenremain); + + /* Serialize the indicator count. */ + for (count = 0; aictx->indicators[count] != NULL; count++); + ret = krb5_ser_pack_int32(count, &bp, &remain); + if (ret) + return ret; + + for (i = 0; aictx->indicators[i] != NULL; i++) { + /* Serialize the length and indicator value. */ + ret = krb5_ser_pack_int32(aictx->indicators[i]->length, &bp, &remain); + if (ret) + return ret; + ret = krb5_ser_pack_bytes((uint8_t *)aictx->indicators[i]->data, + aictx->indicators[i]->length, &bp, &remain); + if (ret) + return ret; + } + + *buffer = bp; + *lenremain = remain; + return ret; +} + + +static krb5_error_code +authind_internalize(krb5_context kcontext, krb5_authdata_context context, + void *plugin_context, void *request_context, + uint8_t **buffer, size_t *lenremain) +{ + struct authind_context *aictx = request_context; + krb5_error_code ret; + int32_t count, len, i; + uint8_t *bp = *buffer; + size_t remain = *lenremain; + krb5_data **inds = NULL; + + /* Get the count. */ + ret = krb5_ser_unpack_int32(&count, &bp, &remain); + if (ret) + return ret; + + if (count < 0 || (size_t)count > remain) + return ERANGE; + + if (count > 0) { + inds = k5calloc(count + 1, sizeof(*inds), &ret); + if (inds == NULL) + return errno; + } + + for (i = 0; i < count; i++) { + /* Get the length. */ + ret = krb5_ser_unpack_int32(&len, &bp, &remain); + if (ret) + goto cleanup; + if (len < 0 || (size_t)len > remain) { + ret = ERANGE; + goto cleanup; + } + + /* Get the indicator. */ + inds[i] = k5alloc(sizeof(*inds[i]), &ret); + if (inds[i] == NULL) + goto cleanup; + ret = alloc_data(inds[i], len); + if (ret) + goto cleanup; + ret = krb5_ser_unpack_bytes((uint8_t *)inds[i]->data, len, &bp, + &remain); + if (ret) + goto cleanup; + } + + k5_free_data_ptr_list(aictx->indicators); + aictx->indicators = inds; + inds = NULL; + + *buffer = bp; + *lenremain = remain; + +cleanup: + k5_free_data_ptr_list(inds); + return ret; +} + +static krb5_authdatatype authind_ad_types[] = { + KRB5_AUTHDATA_AUTH_INDICATOR, 0 +}; + +krb5plugin_authdata_client_ftable_v0 k5_authind_ad_client_ftable = { + "authentication-indicators", + authind_ad_types, + authind_init, + NULL, /* fini */ + authind_flags, + authind_request_init, + authind_request_fini, + authind_get_attribute_types, + authind_get_attribute, + authind_set_attribute, + NULL, /* delete_attribute_proc */ + NULL, /* export_authdata */ + authind_import_authdata, + NULL, /* export_internal */ + NULL, /* free_internal */ + NULL, /* verify */ + authind_size, + authind_externalize, + authind_internalize, + NULL /* authind_copy */ +}; diff --git a/krb5-1.21.3/src/lib/krb5/krb/allow_weak.c b/krb5-1.21.3/src/lib/krb5/krb/allow_weak.c new file mode 100644 index 00000000..1c887375 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/allow_weak.c @@ -0,0 +1,34 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/allow_weak.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +krb5_error_code KRB5_CALLCONV +krb5_allow_weak_crypto(krb5_context context, krb5_boolean enable) +{ + context->allow_weak_crypto = (enable != FALSE); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/appdefault.c b/krb5-1.21.3/src/lib/krb5/krb/appdefault.c new file mode 100644 index 00000000..3f7dc237 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/appdefault.c @@ -0,0 +1,169 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * appdefault - routines designed to be called from applications to + * handle the [appdefaults] profile section + */ + +#include "k5-int.h" + + + +/*xxx Duplicating this is annoying; try to work on a better way.*/ +static const char *const conf_yes[] = { + "y", "yes", "true", "t", "1", "on", + 0, +}; + +static const char *const conf_no[] = { + "n", "no", "false", "nil", "0", "off", + 0, +}; + +static int +conf_boolean(char *s) +{ + const char * const *p; + for(p=conf_yes; *p; p++) { + if (!strcasecmp(*p,s)) + return 1; + } + for(p=conf_no; *p; p++) { + if (!strcasecmp(*p,s)) + return 0; + } + /* Default to "no" */ + return 0; +} + +static krb5_error_code +appdefault_get(krb5_context context, const char *appname, const krb5_data *realm, const char *option, char **ret_value) +{ + profile_t profile; + const char *names[5]; + char **nameval = NULL; + krb5_error_code retval; + const char * realmstr = realm?realm->data:NULL; + + *ret_value = NULL; + + if (!context || (context->magic != KV5M_CONTEXT)) + return KV5M_CONTEXT; + + profile = context->profile; + + /* + * Try number one: + * + * [appdefaults] + * app = { + * SOME.REALM = { + * option = + * } + * } + */ + + names[0] = "appdefaults"; + names[1] = appname; + + if (realmstr) { + names[2] = realmstr; + names[3] = option; + names[4] = 0; + retval = profile_get_values(profile, names, &nameval); + if (retval == 0 && nameval && nameval[0]) { + *ret_value = strdup(nameval[0]); + goto goodbye; + } + } + + /* + * Try number two: + * + * [appdefaults] + * app = { + * option = + * } + */ + + names[2] = option; + names[3] = 0; + retval = profile_get_values(profile, names, &nameval); + if (retval == 0 && nameval && nameval[0]) { + *ret_value = strdup(nameval[0]); + goto goodbye; + } + + /* + * Try number three: + * + * [appdefaults] + * realm = { + * option = + */ + + if (realmstr) { + names[1] = realmstr; + names[2] = option; + names[3] = 0; + retval = profile_get_values(profile, names, &nameval); + if (retval == 0 && nameval && nameval[0]) { + *ret_value = strdup(nameval[0]); + goto goodbye; + } + } + + /* + * Try number four: + * + * [appdefaults] + * option = + */ + + names[1] = option; + names[2] = 0; + retval = profile_get_values(profile, names, &nameval); + if (retval == 0 && nameval && nameval[0]) { + *ret_value = strdup(nameval[0]); + } else { + return retval; + } + +goodbye: + if (nameval) { + char **cpp; + for (cpp = nameval; *cpp; cpp++) + free(*cpp); + free(nameval); + } + return 0; +} + +void KRB5_CALLCONV +krb5_appdefault_boolean(krb5_context context, const char *appname, const krb5_data *realm, const char *option, int default_value, int *ret_value) +{ + char *string = NULL; + krb5_error_code retval; + + retval = appdefault_get(context, appname, realm, option, &string); + + if (! retval && string) { + *ret_value = conf_boolean(string); + free(string); + } else + *ret_value = default_value; +} + +void KRB5_CALLCONV +krb5_appdefault_string(krb5_context context, const char *appname, const krb5_data *realm, const char *option, const char *default_value, char **ret_value) +{ + krb5_error_code retval; + char *string; + + retval = appdefault_get(context, appname, realm, option, &string); + + if (! retval && string) { + *ret_value = string; + } else { + *ret_value = strdup(default_value); + } +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/auth_con.c b/krb5-1.21.3/src/lib/krb5/krb/auth_con.c new file mode 100644 index 00000000..91d8e26a --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/auth_con.c @@ -0,0 +1,445 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/auth_con.c */ +/* + * Copyright 2010 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "auth_con.h" + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_init(krb5_context context, krb5_auth_context *auth_context) +{ + *auth_context = + (krb5_auth_context)calloc(1, sizeof(struct _krb5_auth_context)); + if (!*auth_context) + return ENOMEM; + + /* Default flags, do time not seq */ + (*auth_context)->auth_context_flags = + KRB5_AUTH_CONTEXT_DO_TIME | KRB5_AUTH_CONN_INITIALIZED; + + (*auth_context)->checksum_func = NULL; + (*auth_context)->checksum_func_data = NULL; + (*auth_context)->negotiated_etype = ENCTYPE_NULL; + (*auth_context)->magic = KV5M_AUTH_CONTEXT; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_free(krb5_context context, krb5_auth_context auth_context) +{ + if (auth_context == NULL) + return 0; + if (auth_context->local_addr) + krb5_free_address(context, auth_context->local_addr); + if (auth_context->remote_addr) + krb5_free_address(context, auth_context->remote_addr); + if (auth_context->local_port) + krb5_free_address(context, auth_context->local_port); + if (auth_context->remote_port) + krb5_free_address(context, auth_context->remote_port); + if (auth_context->authentp) + krb5_free_authenticator(context, auth_context->authentp); + if (auth_context->key) + krb5_k_free_key(context, auth_context->key); + if (auth_context->send_subkey) + krb5_k_free_key(context, auth_context->send_subkey); + if (auth_context->recv_subkey) + krb5_k_free_key(context, auth_context->recv_subkey); + zapfree(auth_context->cstate.data, auth_context->cstate.length); + if (auth_context->rcache) + k5_rc_close(context, auth_context->rcache); + if (auth_context->permitted_etypes) + free(auth_context->permitted_etypes); + if (auth_context->ad_context) + krb5_authdata_context_free(context, auth_context->ad_context); + k5_memrcache_free(context, auth_context->memrcache); + free(auth_context); + return 0; +} + +krb5_error_code +krb5_auth_con_setaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address *local_addr, krb5_address *remote_addr) +{ + krb5_error_code retval; + + /* Free old addresses */ + if (auth_context->local_addr) + (void) krb5_free_address(context, auth_context->local_addr); + if (auth_context->remote_addr) + (void) krb5_free_address(context, auth_context->remote_addr); + + retval = 0; + if (local_addr) + retval = krb5_copy_addr(context, + local_addr, + &auth_context->local_addr); + else + auth_context->local_addr = NULL; + + if (!retval && remote_addr) + retval = krb5_copy_addr(context, + remote_addr, + &auth_context->remote_addr); + else + auth_context->remote_addr = NULL; + + return retval; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address **local_addr, krb5_address **remote_addr) +{ + krb5_error_code retval; + + retval = 0; + if (local_addr && auth_context->local_addr) { + retval = krb5_copy_addr(context, + auth_context->local_addr, + local_addr); + } + if (!retval && (remote_addr) && auth_context->remote_addr) { + retval = krb5_copy_addr(context, + auth_context->remote_addr, + remote_addr); + } + return retval; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setports(krb5_context context, krb5_auth_context auth_context, krb5_address *local_port, krb5_address *remote_port) +{ + krb5_error_code retval; + + /* Free old addresses */ + if (auth_context->local_port) + (void) krb5_free_address(context, auth_context->local_port); + if (auth_context->remote_port) + (void) krb5_free_address(context, auth_context->remote_port); + + retval = 0; + if (local_port) + retval = krb5_copy_addr(context, + local_port, + &auth_context->local_port); + else + auth_context->local_port = NULL; + + if (!retval && remote_port) + retval = krb5_copy_addr(context, + remote_port, + &auth_context->remote_port); + else + auth_context->remote_port = NULL; + + return retval; +} + + +/* + * This function overloads the keyblock field. It is only useful prior to + * a krb5_rd_req_decode() call for user to user authentication where the + * server has the key and needs to use it to decrypt the incoming request. + * Once decrypted this key is no longer necessary and is then overwritten + * with the session key sent by the client. + */ +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock) +{ + if (auth_context->key) + krb5_k_free_key(context, auth_context->key); + return(krb5_k_create_key(context, keyblock, &(auth_context->key))); +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock) +{ + if (auth_context->key) + return krb5_k_key_keyblock(context, auth_context->key, keyblock); + *keyblock = NULL; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getkey_k(krb5_context context, krb5_auth_context auth_context, + krb5_key *key) +{ + krb5_k_reference_key(context, auth_context->key); + *key = auth_context->key; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getlocalsubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock) +{ + return krb5_auth_con_getsendsubkey(context, auth_context, keyblock); +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getremotesubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock) +{ + return krb5_auth_con_getrecvsubkey(context, auth_context, keyblock); +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock *keyblock) +{ + if (ac->send_subkey != NULL) + krb5_k_free_key(ctx, ac->send_subkey); + ac->send_subkey = NULL; + if (keyblock !=NULL) + return krb5_k_create_key(ctx, keyblock, &ac->send_subkey); + else + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setsendsubkey_k(krb5_context ctx, krb5_auth_context ac, + krb5_key key) +{ + krb5_k_free_key(ctx, ac->send_subkey); + ac->send_subkey = key; + krb5_k_reference_key(ctx, key); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock *keyblock) +{ + if (ac->recv_subkey != NULL) + krb5_k_free_key(ctx, ac->recv_subkey); + ac->recv_subkey = NULL; + if (keyblock != NULL) + return krb5_k_create_key(ctx, keyblock, &ac->recv_subkey); + else + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setrecvsubkey_k(krb5_context ctx, krb5_auth_context ac, + krb5_key key) +{ + krb5_k_free_key(ctx, ac->recv_subkey); + ac->recv_subkey = key; + krb5_k_reference_key(ctx, key); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock) +{ + if (ac->send_subkey != NULL) + return krb5_k_key_keyblock(ctx, ac->send_subkey, keyblock); + *keyblock = NULL; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getsendsubkey_k(krb5_context ctx, krb5_auth_context ac, + krb5_key *key) +{ + krb5_k_reference_key(ctx, ac->send_subkey); + *key = ac->send_subkey; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keyblock **keyblock) +{ + if (ac->recv_subkey != NULL) + return krb5_k_key_keyblock(ctx, ac->recv_subkey, keyblock); + *keyblock = NULL; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getrecvsubkey_k(krb5_context ctx, krb5_auth_context ac, + krb5_key *key) +{ + krb5_k_reference_key(ctx, ac->recv_subkey); + *key = ac->recv_subkey; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_set_req_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype) +{ + auth_context->req_cksumtype = cksumtype; + return 0; +} + +krb5_error_code +krb5_auth_con_set_safe_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype) +{ + auth_context->safe_cksumtype = cksumtype; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getlocalseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber) +{ + *seqnumber = auth_context->local_seq_number; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getremoteseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber) +{ + *seqnumber = auth_context->remote_seq_number; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_initivector(krb5_context context, krb5_auth_context auth_context) +{ + if (auth_context->key == NULL) + return EINVAL; + return krb5_c_init_state(context, &auth_context->key->keyblock, + KRB5_KEYUSAGE_KRB_PRIV_ENCPART, + &auth_context->cstate); +} + +krb5_error_code +krb5_auth_con_setivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer ivector) +{ + /* + * This function was part of the pre-1.2.2 API. Because it aliased the + * caller's memory into auth_context, and doesn't provide the size of the + * cipher state, it's inconvenient to support now, so return an error. + */ + return EINVAL; +} + +krb5_error_code +krb5_auth_con_getivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer *ivector) +{ + *ivector = auth_context->cstate.data; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 flags) +{ + auth_context->auth_context_flags = flags; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 *flags) +{ + *flags = auth_context->auth_context_flags; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_setrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache rcache) +{ + auth_context->rcache = rcache; + return 0; +} + +krb5_error_code +krb5_auth_con_getrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache *rcache) +{ + *rcache = auth_context->rcache; + return 0; +} + +krb5_error_code +krb5_auth_con_setpermetypes(krb5_context context, + krb5_auth_context auth_context, + const krb5_enctype *permetypes) +{ + krb5_enctype *newpe; + krb5_error_code ret; + + ret = k5_copy_etypes(permetypes, &newpe); + if (ret != 0) + return ret; + + free(auth_context->permitted_etypes); + auth_context->permitted_etypes = newpe; + return 0; +} + +krb5_error_code +krb5_auth_con_getpermetypes(krb5_context context, + krb5_auth_context auth_context, + krb5_enctype **permetypes) +{ + *permetypes = NULL; + if (auth_context->permitted_etypes == NULL) + return 0; + return k5_copy_etypes(auth_context->permitted_etypes, permetypes); +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_set_checksum_func( krb5_context context, + krb5_auth_context auth_context, + krb5_mk_req_checksum_func func, + void *data) +{ + auth_context->checksum_func = func; + auth_context->checksum_func_data = data; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_get_checksum_func( krb5_context context, + krb5_auth_context auth_context, + krb5_mk_req_checksum_func *func, + void **data) +{ + *func = auth_context->checksum_func; + *data = auth_context->checksum_func_data; + return 0; +} + +krb5_error_code +krb5_auth_con_get_subkey_enctype(krb5_context context, + krb5_auth_context auth_context, + krb5_enctype *etype) +{ + *etype = auth_context->negotiated_etype; + return 0; +} + +krb5_error_code +krb5_auth_con_get_authdata_context(krb5_context context, + krb5_auth_context auth_context, + krb5_authdata_context *ad_context) +{ + *ad_context = auth_context->ad_context; + return 0; +} + +krb5_error_code +krb5_auth_con_set_authdata_context(krb5_context context, + krb5_auth_context auth_context, + krb5_authdata_context ad_context) +{ + auth_context->ad_context = ad_context; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/auth_con.h b/krb5-1.21.3/src/lib/krb5/krb/auth_con.h new file mode 100644 index 00000000..a010ae40 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/auth_con.h @@ -0,0 +1,42 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ + +#ifndef KRB5_AUTH_CONTEXT +#define KRB5_AUTH_CONTEXT + +#include "../rcache/memrcache.h" + +struct _krb5_auth_context { + krb5_magic magic; + krb5_address * remote_addr; + krb5_address * remote_port; + krb5_address * local_addr; + krb5_address * local_port; + krb5_key key; + krb5_key send_subkey; + krb5_key recv_subkey; + + krb5_int32 auth_context_flags; + krb5_ui_4 remote_seq_number; + krb5_ui_4 local_seq_number; + krb5_authenticator *authentp; /* mk_req, rd_req, mk_rep, ...*/ + krb5_cksumtype req_cksumtype; /* mk_safe, ... */ + krb5_cksumtype safe_cksumtype; /* mk_safe, ... */ + krb5_data cstate; /* mk_priv, rd_priv only */ + krb5_rcache rcache; + k5_memrcache memrcache; + krb5_enctype * permitted_etypes; /* rd_req */ + krb5_mk_req_checksum_func checksum_func; + void *checksum_func_data; + krb5_enctype negotiated_etype; + krb5_authdata_context ad_context; +}; + + +/* Internal auth_context_flags */ +#define KRB5_AUTH_CONN_INITIALIZED 0x00010000 +#define KRB5_AUTH_CONN_USED_W_MK_REQ 0x00020000 +#define KRB5_AUTH_CONN_USED_W_RD_REQ 0x00040000 +#define KRB5_AUTH_CONN_SANE_SEQ 0x00080000 +#define KRB5_AUTH_CONN_HEIMDAL_SEQ 0x00100000 + +#endif diff --git a/krb5-1.21.3/src/lib/krb5/krb/authdata.c b/krb5-1.21.3/src/lib/krb5/krb/authdata.c new file mode 100644 index 00000000..a9023b0a --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/authdata.c @@ -0,0 +1,1286 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. All + * Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +#include "k5-int.h" +#include "authdata.h" +#include "auth_con.h" +#include "int-proto.h" + +/* Loosely based on preauth2.c */ + +#define IS_PRIMARY_INSTANCE(_module) ((_module)->client_req_init != NULL) + +static const char *objdirs[] = { +#if TARGET_OS_MAC + KRB5_AUTHDATA_PLUGIN_BUNDLE_DIR, +#endif + LIBDIR "/krb5/plugins/authdata", + NULL +}; /* should be a list */ + +/* Internal authdata systems */ +static krb5plugin_authdata_client_ftable_v0 *authdata_systems[] = { + &k5_mspac_ad_client_ftable, + &k5_authind_ad_client_ftable, + NULL +}; + +static inline int +k5_ad_module_count(krb5plugin_authdata_client_ftable_v0 *table) +{ + int i; + + if (table->ad_type_list == NULL) + return 0; + + for (i = 0; table->ad_type_list[i]; i++) + ; + + return i; +} + +static krb5_error_code +k5_ad_init_modules(krb5_context kcontext, + krb5_authdata_context context, + krb5plugin_authdata_client_ftable_v0 *table, + int *module_count) +{ + int j, k = *module_count; + krb5_error_code code; + void *plugin_context = NULL; + void **rcpp = NULL; + + if (table->ad_type_list == NULL) { +#ifdef DEBUG + fprintf(stderr, "warning: module \"%s\" does not advertise " + "any AD types\n", table->name); +#endif + return ENOENT; + } + + if (table->init == NULL) + return ENOSYS; + + code = (*table->init)(kcontext, &plugin_context); + if (code != 0) { +#ifdef DEBUG + fprintf(stderr, "warning: skipping module \"%s\" which " + "failed to initialize\n", table->name); +#endif + return code; + } + + for (j = 0; table->ad_type_list[j] != 0; j++) { + context->modules[k].ad_type = table->ad_type_list[j]; + context->modules[k].plugin_context = plugin_context; + if (j == 0) + context->modules[k].client_fini = table->fini; + else + context->modules[k].client_fini = NULL; + context->modules[k].ftable = table; + context->modules[k].name = table->name; + if (table->flags != NULL) { + (*table->flags)(kcontext, plugin_context, + context->modules[k].ad_type, + &context->modules[k].flags); + } else { + context->modules[k].flags = 0; + } + context->modules[k].request_context = NULL; + if (j == 0) { + context->modules[k].client_req_init = table->request_init; + context->modules[k].client_req_fini = table->request_fini; + rcpp = &context->modules[k].request_context; + + /* For now, single request per context. That may change */ + code = (*table->request_init)(kcontext, + context, + plugin_context, + rcpp); + if ((code != 0 && code != ENOMEM) && + (context->modules[k].flags & AD_INFORMATIONAL)) + code = 0; + if (code != 0) + break; + } else { + context->modules[k].client_req_init = NULL; + context->modules[k].client_req_fini = NULL; + } + context->modules[k].request_context_pp = rcpp; + +#ifdef DEBUG + fprintf(stderr, "init module \"%s\", ad_type %d, flags %08x\n", + context->modules[k].name, + context->modules[k].ad_type, + context->modules[k].flags); +#endif + k++; + } + *module_count = k; + + return code; +} + +/* + * Determine size of to-be-externalized authdata context, for + * modules that match given flags mask. Note that this size + * does not include the magic identifier/trailer. + */ +static krb5_error_code +k5_ad_size(krb5_context kcontext, + krb5_authdata_context context, + krb5_flags flags, + size_t *sizep) +{ + int i; + krb5_error_code code = 0; + + *sizep += sizeof(krb5_int32); /* count */ + + for (i = 0; i < context->n_modules; i++) { + struct _krb5_authdata_context_module *module = &context->modules[i]; + size_t size; + + if ((module->flags & flags) == 0) + continue; + + /* externalize request context for the first instance only */ + if (!IS_PRIMARY_INSTANCE(module)) + continue; + + if (module->ftable->size == NULL) + continue; + + assert(module->ftable->externalize != NULL); + + size = sizeof(krb5_int32) /* namelen */ + strlen(module->name); + + code = (*module->ftable->size)(kcontext, + context, + module->plugin_context, + *(module->request_context_pp), + &size); + if (code != 0) + break; + + *sizep += size; + } + + return code; +} + +/* + * Externalize authdata context, for modules that match given flags + * mask. Note that the magic identifier/trailer is not included. + */ +static krb5_error_code +k5_ad_externalize(krb5_context kcontext, + krb5_authdata_context context, + krb5_flags flags, + krb5_octet **buffer, + size_t *lenremain) +{ + int i; + krb5_error_code code; + krb5_int32 ad_count = 0; + krb5_octet *bp; + size_t remain; + + bp = *buffer; + remain = *lenremain; + + /* placeholder for count */ + code = krb5_ser_pack_int32(0, &bp, &remain); + if (code != 0) + return code; + + for (i = 0; i < context->n_modules; i++) { + struct _krb5_authdata_context_module *module = &context->modules[i]; + size_t namelen; + + if ((module->flags & flags) == 0) + continue; + + /* externalize request context for the first instance only */ + if (!IS_PRIMARY_INSTANCE(module)) + continue; + + if (module->ftable->externalize == NULL) + continue; + + /* + * We use the module name rather than the authdata type, because + * there may be multiple modules for a particular authdata type. + */ + namelen = strlen(module->name); + + code = krb5_ser_pack_int32((krb5_int32)namelen, &bp, &remain); + if (code != 0) + break; + + code = krb5_ser_pack_bytes((krb5_octet *)module->name, + namelen, &bp, &remain); + if (code != 0) + break; + + code = (*module->ftable->externalize)(kcontext, + context, + module->plugin_context, + *(module->request_context_pp), + &bp, + &remain); + if (code != 0) + break; + + ad_count++; + } + + if (code == 0) { + /* store actual count */ + krb5_ser_pack_int32(ad_count, buffer, lenremain); + + *buffer = bp; + *lenremain = remain; + } + + return code; +} + +/* + * Find authdata module for authdata type that matches flag mask + */ +static struct _krb5_authdata_context_module * +k5_ad_find_module(krb5_context kcontext, + krb5_authdata_context context, + krb5_flags flags, + const krb5_data *name) +{ + int i; + struct _krb5_authdata_context_module *ret = NULL; + + for (i = 0; i < context->n_modules; i++) { + struct _krb5_authdata_context_module *module = &context->modules[i]; + + if ((module->flags & flags) == 0) + continue; + + /* internalize request context for the first instance only */ + if (!IS_PRIMARY_INSTANCE(module)) + continue; + + /* check for name match */ + if (!data_eq_string(*name, module->name)) + continue; + + ret = module; + break; + } + + return ret; +} + +/* + * In-place internalize authdata context, for modules that match given + * flags mask. The magic identifier/trailer is not expected by this. + */ +static krb5_error_code +k5_ad_internalize(krb5_context kcontext, + krb5_authdata_context context, + krb5_flags flags, + krb5_octet **buffer, + size_t *lenremain) +{ + krb5_error_code code = 0; + krb5_int32 i, count; + krb5_octet *bp; + size_t remain; + + bp = *buffer; + remain = *lenremain; + + code = krb5_ser_unpack_int32(&count, &bp, &remain); + if (code != 0) + return code; + + for (i = 0; i < count; i++) { + struct _krb5_authdata_context_module *module; + krb5_int32 namelen; + krb5_data name; + + code = krb5_ser_unpack_int32(&namelen, &bp, &remain); + if (code != 0) + break; + + if (remain < (size_t)namelen) { + code = ENOMEM; + break; + } + + name.length = namelen; + name.data = (char *)bp; + + module = k5_ad_find_module(kcontext, context, flags, &name); + if (module == NULL || module->ftable->internalize == NULL) { + code = EINVAL; + break; + } + + bp += namelen; + remain -= namelen; + + code = (*module->ftable->internalize)(kcontext, + context, + module->plugin_context, + *(module->request_context_pp), + &bp, + &remain); + if (code != 0) + break; + } + + if (code == 0) { + *buffer = bp; + *lenremain = remain; + } + + return code; +} + +krb5_error_code KRB5_CALLCONV +krb5_authdata_context_init(krb5_context kcontext, + krb5_authdata_context *pcontext) +{ + int n_modules, n_tables, i, k; + void **tables = NULL; + krb5plugin_authdata_client_ftable_v0 *table; + krb5_authdata_context context = NULL; + int internal_count = 0; + struct plugin_dir_handle plugins; + krb5_error_code code; + + *pcontext = NULL; + memset(&plugins, 0, sizeof(plugins)); + + n_modules = 0; + for (n_tables = 0; authdata_systems[n_tables] != NULL; n_tables++) { + n_modules += k5_ad_module_count(authdata_systems[n_tables]); + } + internal_count = n_tables; + + if (PLUGIN_DIR_OPEN(&plugins) == 0 && + krb5int_open_plugin_dirs(objdirs, NULL, + &plugins, + &kcontext->err) == 0 && + krb5int_get_plugin_dir_data(&plugins, + "authdata_client_0", + &tables, + &kcontext->err) == 0 && + tables != NULL) + { + for (; tables[n_tables - internal_count] != NULL; n_tables++) { + table = tables[n_tables - internal_count]; + n_modules += k5_ad_module_count(table); + } + } + + context = calloc(1, sizeof(*context)); + if (context == NULL) { + code = ENOMEM; + goto cleanup; + } + context->magic = KV5M_AUTHDATA_CONTEXT; + context->modules = calloc(n_modules, sizeof(context->modules[0])); + if (context->modules == NULL) { + code = ENOMEM; + goto cleanup; + } + context->n_modules = n_modules; + + /* fill in the structure */ + for (i = 0, k = 0, code = 0; i < n_tables - internal_count; i++) { + code = k5_ad_init_modules(kcontext, context, tables[i], &k); + if (code != 0) + goto cleanup; + } + + for (i = 0; i < internal_count; i++) { + code = k5_ad_init_modules(kcontext, context, authdata_systems[i], &k); + if (code != 0) + goto cleanup; + } + + context->plugins = plugins; + +cleanup: + if (tables != NULL) + krb5int_free_plugin_dir_data(tables); + + if (code != 0) { + krb5int_close_plugin_dirs(&plugins); + krb5_authdata_context_free(kcontext, context); + } else { + /* plugins is owned by context now */ + *pcontext = context; + } + + return code; +} + +void KRB5_CALLCONV +krb5_authdata_context_free(krb5_context kcontext, + krb5_authdata_context context) +{ + int i; + + if (context == NULL) + return; + + for (i = 0; i < context->n_modules; i++) { + struct _krb5_authdata_context_module *module = &context->modules[i]; + + if (module->client_req_fini != NULL && + module->request_context != NULL) + (*module->client_req_fini)(kcontext, + context, + module->plugin_context, + module->request_context); + + if (module->client_fini != NULL) + (*module->client_fini)(kcontext, module->plugin_context); + + memset(module, 0, sizeof(*module)); + } + + if (context->modules != NULL) { + free(context->modules); + context->modules = NULL; + } + krb5int_close_plugin_dirs(&context->plugins); + zapfree(context, sizeof(*context)); +} + +krb5_error_code KRB5_CALLCONV +krb5_authdata_import_attributes(krb5_context kcontext, + krb5_authdata_context context, + krb5_flags usage, + const krb5_data *attrs) +{ + krb5_octet *bp; + size_t remain; + + bp = (krb5_octet *)attrs->data; + remain = attrs->length; + + return k5_ad_internalize(kcontext, context, usage, &bp, &remain); +} + +/* Return 0 with *kdc_issued_authdata == NULL on verification failure. */ +static krb5_error_code +k5_get_kdc_issued_authdata(krb5_context kcontext, + const krb5_ap_req *ap_req, + krb5_principal *kdc_issuer, + krb5_authdata ***kdc_issued_authdata) +{ + krb5_error_code code; + krb5_authdata **authdata; + krb5_authdata **ticket_authdata; + + *kdc_issuer = NULL; + *kdc_issued_authdata = NULL; + + ticket_authdata = ap_req->ticket->enc_part2->authorization_data; + + code = krb5_find_authdata(kcontext, ticket_authdata, NULL, + KRB5_AUTHDATA_KDC_ISSUED, &authdata); + if (code != 0 || authdata == NULL) + return code; + + /* + * Note: a module must still implement a verify_authdata + * method, even it is a NOOP that simply records the value + * of the kdc_issued_flag. + */ + code = krb5_verify_authdata_kdc_issued(kcontext, + ap_req->ticket->enc_part2->session, + authdata[0], + kdc_issuer, + kdc_issued_authdata); + + if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY || + code == KRB5KRB_AP_ERR_INAPP_CKSUM || + code == KRB5_BAD_ENCTYPE || code == KRB5_BAD_MSIZE) + code = 0; + + krb5_free_authdata(kcontext, authdata); + + return code; +} + +/* Decode and verify each CAMMAC and collect the resulting authdata, + * ignoring those that failed verification. */ +static krb5_error_code +extract_cammacs(krb5_context kcontext, krb5_authdata **cammacs, + const krb5_keyblock *key, krb5_authdata ***ad_out) +{ + krb5_error_code ret = 0; + krb5_authdata **list = NULL, **elements = NULL, **new_list; + size_t i, n_elements, count = 0; + + *ad_out = NULL; + + for (i = 0; cammacs != NULL && cammacs[i] != NULL; i++) { + ret = k5_unwrap_cammac_svc(kcontext, cammacs[i], key, &elements); + if (ret && ret != KRB5KRB_AP_ERR_BAD_INTEGRITY) + goto cleanup; + ret = 0; + if (elements == NULL) + continue; + + /* Add the verified elements to list and free the container array. */ + for (n_elements = 0; elements[n_elements] != NULL; n_elements++); + new_list = realloc(list, (count + n_elements + 1) * sizeof(*list)); + if (new_list == NULL) { + ret = ENOMEM; + goto cleanup; + } + list = new_list; + memcpy(list + count, elements, n_elements * sizeof(*list)); + count += n_elements; + list[count] = NULL; + free(elements); + elements = NULL; + } + + *ad_out = list; + list = NULL; + +cleanup: + krb5_free_authdata(kcontext, list); + krb5_free_authdata(kcontext, elements); + return ret; +} + +/* Retrieve verified CAMMAC contained elements. */ +static krb5_error_code +get_cammac_authdata(krb5_context kcontext, const krb5_ap_req *ap_req, + const krb5_keyblock *key, krb5_authdata ***elems_out) +{ + krb5_error_code ret = 0; + krb5_authdata **ticket_authdata, **cammacs, **elements; + + *elems_out = NULL; + + ticket_authdata = ap_req->ticket->enc_part2->authorization_data; + ret = krb5_find_authdata(kcontext, ticket_authdata, NULL, + KRB5_AUTHDATA_CAMMAC, &cammacs); + if (ret || cammacs == NULL) + return ret; + + ret = extract_cammacs(kcontext, cammacs, key, &elements); + if (!ret) + *elems_out = elements; + + krb5_free_authdata(kcontext, cammacs); + return ret; +} + +krb5_error_code +krb5int_authdata_verify(krb5_context kcontext, + krb5_authdata_context context, + krb5_flags usage, + const krb5_auth_context *auth_context, + const krb5_keyblock *key, + const krb5_ap_req *ap_req) +{ + int i; + krb5_error_code code = 0; + krb5_authdata **authen_authdata; + krb5_authdata **ticket_authdata; + krb5_principal kdc_issuer = NULL; + krb5_authdata **kdc_issued_authdata = NULL; + krb5_authdata **cammac_authdata = NULL; + + authen_authdata = (*auth_context)->authentp->authorization_data; + ticket_authdata = ap_req->ticket->enc_part2->authorization_data; + + code = k5_get_kdc_issued_authdata(kcontext, ap_req, &kdc_issuer, + &kdc_issued_authdata); + if (code) + goto cleanup; + + code = get_cammac_authdata(kcontext, ap_req, key, &cammac_authdata); + if (code) + goto cleanup; + + for (i = 0; i < context->n_modules; i++) { + struct _krb5_authdata_context_module *module = &context->modules[i]; + krb5_authdata **authdata = NULL; + krb5_boolean kdc_issued_flag = FALSE; + + if ((module->flags & usage) == 0) + continue; + + if (module->ftable->import_authdata == NULL) + continue; + + if (kdc_issued_authdata != NULL && + (module->flags & AD_USAGE_KDC_ISSUED)) { + code = krb5_find_authdata(kcontext, kdc_issued_authdata, NULL, + module->ad_type, &authdata); + if (code != 0) + break; + + kdc_issued_flag = TRUE; + } + + if (cammac_authdata != NULL && (module->flags & AD_CAMMAC_PROTECTED)) { + code = krb5_find_authdata(kcontext, cammac_authdata, NULL, + module->ad_type, &authdata); + if (code) + break; + + kdc_issued_flag = TRUE; + } + + if (authdata == NULL) { + krb5_boolean ticket_usage = FALSE; + krb5_boolean authen_usage = FALSE; + + /* + * Determine which authdata sources to interrogate based on the + * module's usage. This is important if the authdata is signed + * by the KDC with the TGT key (as the user can forge that in + * the AP-REQ). + */ + if (module->flags & (AD_USAGE_AS_REQ | AD_USAGE_TGS_REQ)) + ticket_usage = TRUE; + if (module->flags & AD_USAGE_AP_REQ) + authen_usage = TRUE; + + code = krb5_find_authdata(kcontext, + ticket_usage ? ticket_authdata : NULL, + authen_usage ? authen_authdata : NULL, + module->ad_type, &authdata); + if (code != 0) + break; + } + + if (authdata == NULL) + continue; + + assert(authdata[0] != NULL); + + code = (*module->ftable->import_authdata)(kcontext, + context, + module->plugin_context, + *(module->request_context_pp), + authdata, + kdc_issued_flag, + kdc_issuer); + if (code == 0 && module->ftable->verify != NULL) { + code = (*module->ftable->verify)(kcontext, + context, + module->plugin_context, + *(module->request_context_pp), + auth_context, + key, + ap_req); + } + if (code != 0 && (module->flags & AD_INFORMATIONAL)) + code = 0; + krb5_free_authdata(kcontext, authdata); + if (code != 0) + break; + } + +cleanup: + krb5_free_principal(kcontext, kdc_issuer); + krb5_free_authdata(kcontext, kdc_issued_authdata); + krb5_free_authdata(kcontext, cammac_authdata); + + return code; +} + +static krb5_error_code +k5_merge_data_list(krb5_data **dst, krb5_data *src, unsigned int *len) +{ + unsigned int i; + krb5_data *d; + + if (src == NULL) + return 0; + + for (i = 0; src[i].data != NULL; i++) + ; + + d = realloc(*dst, (*len + i + 1) * sizeof(krb5_data)); + if (d == NULL) + return ENOMEM; + + memcpy(&d[*len], src, i * sizeof(krb5_data)); + + *len += i; + + d[*len].data = NULL; + d[*len].length = 0; + + *dst = d; + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_authdata_get_attribute_types(krb5_context kcontext, + krb5_authdata_context context, + krb5_data **out_attrs) +{ + int i; + krb5_error_code code = 0; + krb5_data *attrs = NULL; + unsigned int attrs_len = 0; + + for (i = 0; i < context->n_modules; i++) { + struct _krb5_authdata_context_module *module = &context->modules[i]; + krb5_data *attrs2 = NULL; + + if (module->ftable->get_attribute_types == NULL) + continue; + + if ((*module->ftable->get_attribute_types)(kcontext, + context, + module->plugin_context, + *(module->request_context_pp), + &attrs2)) + continue; + + code = k5_merge_data_list(&attrs, attrs2, &attrs_len); + if (code != 0) { + krb5int_free_data_list(kcontext, attrs2); + break; + } + if (attrs2 != NULL) + free(attrs2); + } + + if (code != 0) { + krb5int_free_data_list(kcontext, attrs); + attrs = NULL; + } + + *out_attrs = attrs; + + return code; +} + +krb5_error_code KRB5_CALLCONV +krb5_authdata_get_attribute(krb5_context kcontext, + krb5_authdata_context context, + const krb5_data *attribute, + krb5_boolean *authenticated, + krb5_boolean *complete, + krb5_data *value, + krb5_data *display_value, + int *more) +{ + int i; + krb5_error_code code = ENOENT; + + *authenticated = FALSE; + *complete = FALSE; + + value->data = NULL; + value->length = 0; + + display_value->data = NULL; + display_value->length = 0; + + /* + * NB at present a module is presumed to be authoritative for + * an attribute; not sure how to federate "more" across module + * yet + */ + for (i = 0; i < context->n_modules; i++) { + struct _krb5_authdata_context_module *module = &context->modules[i]; + + if (module->ftable->get_attribute == NULL) + continue; + + code = (*module->ftable->get_attribute)(kcontext, + context, + module->plugin_context, + *(module->request_context_pp), + attribute, + authenticated, + complete, + value, + display_value, + more); + if (code == 0) + break; + } + + if (code != 0) + *more = 0; + + return code; +} + +krb5_error_code KRB5_CALLCONV +krb5_authdata_set_attribute(krb5_context kcontext, + krb5_authdata_context context, + krb5_boolean complete, + const krb5_data *attribute, + const krb5_data *value) +{ + int i; + krb5_error_code code = 0; + int found = 0; + + for (i = 0; i < context->n_modules; i++) { + struct _krb5_authdata_context_module *module = &context->modules[i]; + + if (module->ftable->set_attribute == NULL) + continue; + + code = (*module->ftable->set_attribute)(kcontext, + context, + module->plugin_context, + *(module->request_context_pp), + complete, + attribute, + value); + if (code == ENOENT) + code = 0; + else if (code == 0) + found++; + else + break; + } + + if (code == 0 && found == 0) + code = ENOENT; + + return code; +} + +krb5_error_code KRB5_CALLCONV +krb5_authdata_delete_attribute(krb5_context kcontext, + krb5_authdata_context context, + const krb5_data *attribute) +{ + int i; + krb5_error_code code = ENOENT; + int found = 0; + + for (i = 0; i < context->n_modules; i++) { + struct _krb5_authdata_context_module *module = &context->modules[i]; + + if (module->ftable->delete_attribute == NULL) + continue; + + code = (*module->ftable->delete_attribute)(kcontext, + context, + module->plugin_context, + *(module->request_context_pp), + attribute); + if (code == ENOENT) + code = 0; + else if (code == 0) + found++; + else + break; + } + + if (code == 0 && found == 0) + code = ENOENT; + + return code; +} + +krb5_error_code KRB5_CALLCONV +krb5_authdata_export_attributes(krb5_context kcontext, + krb5_authdata_context context, + krb5_flags flags, + krb5_data **attrsp) +{ + krb5_error_code code; + size_t required = 0; + krb5_octet *bp; + size_t remain; + krb5_data *attrs; + + code = k5_ad_size(kcontext, context, AD_USAGE_MASK, &required); + if (code != 0) + return code; + + attrs = malloc(sizeof(*attrs)); + if (attrs == NULL) + return ENOMEM; + + attrs->magic = KV5M_DATA; + attrs->length = 0; + attrs->data = malloc(required); + if (attrs->data == NULL) { + free(attrs); + return ENOMEM; + } + + bp = (krb5_octet *)attrs->data; + remain = required; + + code = k5_ad_externalize(kcontext, context, AD_USAGE_MASK, &bp, &remain); + if (code != 0) { + krb5_free_data(kcontext, attrs); + return code; + } + + attrs->length = (bp - (krb5_octet *)attrs->data); + + *attrsp = attrs; + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_authdata_export_internal(krb5_context kcontext, + krb5_authdata_context context, + krb5_boolean restrict_authenticated, + const char *module_name, + void **ptr) +{ + krb5_error_code code; + krb5_data name; + struct _krb5_authdata_context_module *module; + + *ptr = NULL; + + name = make_data((char *)module_name, strlen(module_name)); + module = k5_ad_find_module(kcontext, context, AD_USAGE_MASK, &name); + if (module == NULL) + return ENOENT; + + if (module->ftable->export_internal == NULL) + return ENOENT; + + code = (*module->ftable->export_internal)(kcontext, + context, + module->plugin_context, + *(module->request_context_pp), + restrict_authenticated, + ptr); + + return code; +} + +krb5_error_code KRB5_CALLCONV +krb5_authdata_free_internal(krb5_context kcontext, + krb5_authdata_context context, + const char *module_name, + void *ptr) +{ + krb5_data name; + struct _krb5_authdata_context_module *module; + + name = make_data((char *)module_name, strlen(module_name)); + module = k5_ad_find_module(kcontext, context, AD_USAGE_MASK, &name); + if (module == NULL) + return ENOENT; + + if (module->ftable->free_internal == NULL) + return ENOENT; + + (*module->ftable->free_internal)(kcontext, + context, + module->plugin_context, + *(module->request_context_pp), + ptr); + + return 0; +} + +static krb5_error_code +k5_copy_ad_module_data(krb5_context kcontext, + krb5_authdata_context context, + struct _krb5_authdata_context_module *src_module, + krb5_authdata_context dst) +{ + int i; + krb5_error_code code; + struct _krb5_authdata_context_module *dst_module = NULL; + + for (i = 0; i < dst->n_modules; i++) { + struct _krb5_authdata_context_module *module = &dst->modules[i]; + + if (module->ftable == src_module->ftable) { + /* XXX is this safe to assume these pointers are interned? */ + dst_module = module; + break; + } + } + + if (dst_module == NULL) + return ENOENT; + + /* copy request context for the first instance only */ + if (!IS_PRIMARY_INSTANCE(dst_module)) + return 0; + + assert(strcmp(dst_module->name, src_module->name) == 0); + + /* If copy is unimplemented, externalize/internalize */ + if (src_module->ftable->copy == NULL) { + size_t size = 0, remain; + krb5_octet *contents, *bp; + + assert(src_module->ftable->size != NULL); + assert(src_module->ftable->externalize != NULL); + assert(dst_module->ftable->internalize != NULL); + + code = (*src_module->ftable->size)(kcontext, + context, + src_module->plugin_context, + src_module->request_context, + &size); + if (code != 0) + return code; + + contents = malloc(size); + if (contents == NULL) + return ENOMEM; + + bp = contents; + remain = size; + + code = (*src_module->ftable->externalize)(kcontext, + context, + src_module->plugin_context, + *(src_module->request_context_pp), + &bp, + &remain); + if (code != 0) { + free(contents); + return code; + } + + remain = (bp - contents); + bp = contents; + + code = (*dst_module->ftable->internalize)(kcontext, + context, + dst_module->plugin_context, + *(dst_module->request_context_pp), + &bp, + &remain); + if (code != 0) { + free(contents); + return code; + } + + free(contents); + } else { + assert(src_module->request_context_pp == &src_module->request_context); + assert(dst_module->request_context_pp == &dst_module->request_context); + + code = (*src_module->ftable->copy)(kcontext, + context, + src_module->plugin_context, + src_module->request_context, + dst_module->plugin_context, + dst_module->request_context); + } + + return code; +} + +krb5_error_code KRB5_CALLCONV +krb5_authdata_context_copy(krb5_context kcontext, + krb5_authdata_context src, + krb5_authdata_context *pdst) +{ + int i; + krb5_error_code code; + krb5_authdata_context dst; + + /* XXX we need to init a new context because we can't copy plugins */ + code = krb5_authdata_context_init(kcontext, &dst); + if (code != 0) + return code; + + for (i = 0; i < src->n_modules; i++) { + struct _krb5_authdata_context_module *module = &src->modules[i]; + + code = k5_copy_ad_module_data(kcontext, src, module, dst); + if (code != 0) + break; + } + + if (code != 0) { + krb5_authdata_context_free(kcontext, dst); + return code; + } + + *pdst = dst; + + return 0; +} + +/* + * Calculate size of to-be-externalized authdata context. + */ +krb5_error_code +k5_size_authdata_context(krb5_context kcontext, krb5_authdata_context context, + size_t *sizep) +{ + krb5_error_code code; + + code = k5_ad_size(kcontext, context, AD_USAGE_MASK, sizep); + if (code != 0) + return code; + + *sizep += 2 * sizeof(krb5_int32); /* identifier/trailer */ + + return 0; +} + +/* + * Externalize an authdata context. + */ +krb5_error_code +k5_externalize_authdata_context(krb5_context kcontext, + krb5_authdata_context context, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code code; + krb5_octet *bp; + size_t remain; + + bp = *buffer; + remain = *lenremain; + + /* Our identifier */ + code = krb5_ser_pack_int32(KV5M_AUTHDATA_CONTEXT, &bp, &remain); + if (code != 0) + return code; + + /* The actual context data */ + code = k5_ad_externalize(kcontext, context, AD_USAGE_MASK, + &bp, &remain); + if (code != 0) + return code; + + /* Our trailer */ + code = krb5_ser_pack_int32(KV5M_AUTHDATA_CONTEXT, &bp, &remain); + if (code != 0) + return code; + + *buffer = bp; + *lenremain = remain; + + return 0; +} + +/* + * Internalize an authdata context. + */ +krb5_error_code +k5_internalize_authdata_context(krb5_context kcontext, + krb5_authdata_context *ptr, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code code; + krb5_authdata_context context; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + + bp = *buffer; + remain = *lenremain; + + code = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + if (code != 0) + return code; + + if (ibuf != KV5M_AUTHDATA_CONTEXT) + return EINVAL; + + code = krb5_authdata_context_init(kcontext, &context); + if (code != 0) + return code; + + code = k5_ad_internalize(kcontext, context, AD_USAGE_MASK, + &bp, &remain); + if (code != 0) { + krb5_authdata_context_free(kcontext, context); + return code; + } + + code = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + if (code != 0) + return code; + + if (ibuf != KV5M_AUTHDATA_CONTEXT) { + krb5_authdata_context_free(kcontext, context); + return EINVAL; + } + + *buffer = bp; + *lenremain = remain; + *ptr = context; + + return 0; +} + +krb5_error_code +krb5int_copy_authdatum(krb5_context context, + const krb5_authdata *inad, krb5_authdata **outad) +{ + krb5_authdata *tmpad; + + if (!(tmpad = (krb5_authdata *)malloc(sizeof(*tmpad)))) + return ENOMEM; + *tmpad = *inad; + if (!(tmpad->contents = (krb5_octet *)malloc(inad->length))) { + free(tmpad); + return ENOMEM; + } + memcpy(tmpad->contents, inad->contents, inad->length); + *outad = tmpad; + return 0; +} + +void KRB5_CALLCONV +krb5_free_authdata(krb5_context context, krb5_authdata **val) +{ + krb5_authdata **temp; + + if (val == NULL) + return; + for (temp = val; *temp; temp++) { + free((*temp)->contents); + free(*temp); + } + free(val); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/authdata.h b/krb5-1.21.3/src/lib/krb5/krb/authdata.h new file mode 100644 index 00000000..296cc496 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/authdata.h @@ -0,0 +1,104 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/authdata.h */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef KRB_AUTHDATA_H + +#define KRB_AUTHDATA_H + +#include +#include "k5-utf8.h" + + +/* authdata.c */ +krb5_error_code +krb5int_authdata_verify(krb5_context context, + krb5_authdata_context, + krb5_flags usage, + const krb5_auth_context *auth_context, + const krb5_keyblock *key, + const krb5_ap_req *ap_req); + +/* PAC */ +/* + * A PAC consists of a sequence of PAC_INFO_BUFFERs, preceded by + * a PACTYPE header. Decoding the contents of the buffers is left + * to the application (notwithstanding signature verification). + */ + +struct k5_pac_buffer { + uint32_t type; + uint32_t size; + uint64_t offset; +}; + +struct krb5_pac_data { + krb5_data data; /* PAC data (including uninitialised header) */ + krb5_boolean verified; + uint32_t nbuffers; + uint32_t version; + struct k5_pac_buffer *buffers; +}; + + + +#define PAC_ALIGNMENT 8 +#define PACTYPE_LENGTH 8U +#define PAC_SIGNATURE_DATA_LENGTH 4U +#define PAC_CLIENT_INFO_LENGTH 10U +#define PAC_INFO_BUFFER_LENGTH 16 + +#define NT_TIME_EPOCH 11644473600LL + +extern krb5plugin_authdata_client_ftable_v0 k5_mspac_ad_client_ftable; +extern krb5plugin_authdata_client_ftable_v0 k5_s4u2proxy_ad_client_ftable; +extern krb5plugin_authdata_client_ftable_v0 k5_authind_ad_client_ftable; + +krb5_error_code +k5_pac_locate_buffer(krb5_context context, + const krb5_pac pac, + krb5_ui_4 type, + krb5_data *data); + +krb5_error_code +k5_pac_validate_client(krb5_context context, + const krb5_pac pac, + krb5_timestamp authtime, + krb5_const_principal principal, + krb5_boolean with_realm); + +krb5_error_code +k5_pac_add_buffer(krb5_context context, + krb5_pac pac, + krb5_ui_4 type, + const krb5_data *data, + krb5_boolean zerofill, + krb5_data *out_data); + +krb5_error_code +k5_seconds_since_1970_to_time(krb5_timestamp elapsedSeconds, uint64_t *ntTime); + + +#endif /* !KRB_AUTHDATA_H */ diff --git a/krb5-1.21.3/src/lib/krb5/krb/authdata_dec.c b/krb5-1.21.3/src/lib/krb5/krb/authdata_dec.c new file mode 100644 index 00000000..0d1c1c4d --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/authdata_dec.c @@ -0,0 +1,296 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/authdata_dec.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "k5-int.h" +#include "int-proto.h" + +krb5_error_code KRB5_CALLCONV +krb5_decode_authdata_container(krb5_context context, + krb5_authdatatype type, + const krb5_authdata *container, + krb5_authdata ***authdata) +{ + krb5_error_code code; + krb5_data data; + + *authdata = NULL; + + if ((container->ad_type & AD_TYPE_FIELD_TYPE_MASK) != type) + return EINVAL; + + data.length = container->length; + data.data = (char *)container->contents; + + code = decode_krb5_authdata(&data, authdata); + if (code) + return code; + + return 0; +} + +struct find_authdata_context { + krb5_authdata **out; + size_t space; + size_t length; +}; + +static krb5_error_code +grow_find_authdata(krb5_context context, struct find_authdata_context *fctx, + krb5_authdata *elem) +{ + krb5_error_code retval = 0; + if (fctx->length == fctx->space) { + krb5_authdata **new; + if (fctx->space >= 256) { + k5_setmsg(context, ERANGE, + "More than 256 authdata matched a query"); + return ERANGE; + } + new = realloc(fctx->out, + sizeof (krb5_authdata *)*(2*fctx->space+1)); + if (new == NULL) + return ENOMEM; + fctx->out = new; + fctx->space *=2; + } + fctx->out[fctx->length+1] = NULL; + retval = krb5int_copy_authdatum(context, elem, + &fctx->out[fctx->length]); + if (retval == 0) + fctx->length++; + return retval; +} + +static krb5_error_code +find_authdata_1(krb5_context context, krb5_authdata *const *in_authdat, + krb5_authdatatype ad_type, struct find_authdata_context *fctx, + int from_ap_req) +{ + int i = 0; + krb5_error_code retval = 0; + + for (i = 0; in_authdat[i] && retval == 0; i++) { + krb5_authdata *ad = in_authdat[i]; + krb5_authdata **decoded_container; + + switch (ad->ad_type) { + case KRB5_AUTHDATA_IF_RELEVANT: + if (retval == 0) + retval = krb5_decode_authdata_container(context, + ad->ad_type, + ad, + &decoded_container); + if (retval == 0) { + retval = find_authdata_1(context, + decoded_container, + ad_type, + fctx, + from_ap_req); + krb5_free_authdata(context, decoded_container); + } + break; + case KRB5_AUTHDATA_SIGNTICKET: + case KRB5_AUTHDATA_KDC_ISSUED: + case KRB5_AUTHDATA_WIN2K_PAC: + case KRB5_AUTHDATA_CAMMAC: + case KRB5_AUTHDATA_AUTH_INDICATOR: + if (from_ap_req) + continue; + default: + if (ad->ad_type == ad_type && retval == 0) + retval = grow_find_authdata(context, fctx, ad); + break; + } + } + + return retval; +} + +krb5_error_code KRB5_CALLCONV +krb5_find_authdata(krb5_context context, + krb5_authdata *const *ticket_authdata, + krb5_authdata *const *ap_req_authdata, + krb5_authdatatype ad_type, krb5_authdata ***results) +{ + krb5_error_code retval = 0; + struct find_authdata_context fctx; + fctx.length = 0; + fctx.space = 2; + fctx.out = calloc(fctx.space+1, sizeof (krb5_authdata *)); + *results = NULL; + if (fctx.out == NULL) + return ENOMEM; + if (ticket_authdata) + retval = find_authdata_1( context, ticket_authdata, ad_type, &fctx, 0); + if ((retval==0) && ap_req_authdata) + retval = find_authdata_1( context, ap_req_authdata, ad_type, &fctx, 1); + if ((retval== 0) && fctx.length) + *results = fctx.out; + else krb5_free_authdata(context, fctx.out); + return retval; +} + +krb5_error_code KRB5_CALLCONV +krb5_verify_authdata_kdc_issued(krb5_context context, + const krb5_keyblock *key, + const krb5_authdata *ad_kdcissued, + krb5_principal *issuer, + krb5_authdata ***authdata) +{ + krb5_error_code code; + krb5_ad_kdcissued *ad_kdci; + krb5_data data, *data2; + krb5_boolean valid = FALSE; + + if ((ad_kdcissued->ad_type & AD_TYPE_FIELD_TYPE_MASK) != + KRB5_AUTHDATA_KDC_ISSUED) + return EINVAL; + + if (issuer != NULL) + *issuer = NULL; + if (authdata != NULL) + *authdata = NULL; + + data.length = ad_kdcissued->length; + data.data = (char *)ad_kdcissued->contents; + + code = decode_krb5_ad_kdcissued(&data, &ad_kdci); + if (code != 0) + return code; + + if (!krb5_c_is_keyed_cksum(ad_kdci->ad_checksum.checksum_type)) { + krb5_free_ad_kdcissued(context, ad_kdci); + return KRB5KRB_AP_ERR_INAPP_CKSUM; + } + + code = encode_krb5_authdata(ad_kdci->elements, &data2); + if (code != 0) { + krb5_free_ad_kdcissued(context, ad_kdci); + return code; + } + + code = krb5_c_verify_checksum(context, key, + KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM, + data2, &ad_kdci->ad_checksum, &valid); + if (code != 0) { + krb5_free_ad_kdcissued(context, ad_kdci); + krb5_free_data(context, data2); + return code; + } + + krb5_free_data(context, data2); + + if (valid == FALSE) { + krb5_free_ad_kdcissued(context, ad_kdci); + return KRB5KRB_AP_ERR_BAD_INTEGRITY; + } + + if (issuer != NULL) { + *issuer = ad_kdci->i_principal; + ad_kdci->i_principal = NULL; + } + + if (authdata != NULL) { + *authdata = ad_kdci->elements; + ad_kdci->elements = NULL; + } + + krb5_free_ad_kdcissued(context, ad_kdci); + + return 0; +} + +/* + * Decode authentication indicator strings from authdata and return as an + * allocated array of krb5_data pointers. The caller must initialize + * *indicators to NULL for the first call, and successive calls will reallocate + * and append to the indicators array. + */ +krb5_error_code +k5_authind_decode(const krb5_authdata *ad, krb5_data ***indicators) +{ + krb5_error_code ret = 0; + krb5_data der_ad, **strdata = NULL, **ai_list = *indicators; + size_t count, scount; + + if (ad == NULL || ad->ad_type != KRB5_AUTHDATA_AUTH_INDICATOR) + goto cleanup; + + /* Count existing auth indicators. */ + for (count = 0; ai_list != NULL && ai_list[count] != NULL; count++); + + der_ad = make_data(ad->contents, ad->length); + ret = decode_utf8_strings(&der_ad, &strdata); + if (ret) + return ret; + + /* Count new auth indicators. */ + for (scount = 0; strdata[scount] != NULL; scount++); + + ai_list = realloc(ai_list, (count + scount + 1) * sizeof(*ai_list)); + if (ai_list == NULL) { + ret = ENOMEM; + goto cleanup; + } + *indicators = ai_list; + + /* Steal decoder-allocated pointers and free the container array. */ + memcpy(ai_list + count, strdata, scount * sizeof(*strdata)); + ai_list[count + scount] = NULL; + free(strdata); + strdata = NULL; + +cleanup: + k5_free_data_ptr_list(strdata); + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/authdata_enc.c b/krb5-1.21.3/src/lib/krb5/krb/authdata_enc.c new file mode 100644 index 00000000..3f7b3897 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/authdata_enc.c @@ -0,0 +1,146 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/authdata_enc.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "k5-int.h" + +krb5_error_code KRB5_CALLCONV +krb5_encode_authdata_container(krb5_context context, + krb5_authdatatype type, + krb5_authdata *const*authdata, + krb5_authdata ***container) +{ + krb5_error_code code; + krb5_data *data; + krb5_authdata ad_datum; + krb5_authdata *ad_data[2]; + + *container = NULL; + + code = encode_krb5_authdata((krb5_authdata * const *)authdata, &data); + if (code) + return code; + + ad_datum.ad_type = type & AD_TYPE_FIELD_TYPE_MASK; + ad_datum.length = data->length; + ad_datum.contents = (unsigned char *)data->data; + + ad_data[0] = &ad_datum; + ad_data[1] = NULL; + + code = krb5_copy_authdata(context, ad_data, container); + + krb5_free_data(context, data); + + return code; +} + +krb5_error_code KRB5_CALLCONV +krb5_make_authdata_kdc_issued(krb5_context context, + const krb5_keyblock *key, + krb5_const_principal issuer, + krb5_authdata *const *authdata, + krb5_authdata ***ad_kdcissued) +{ + krb5_error_code code; + krb5_ad_kdcissued ad_kdci; + krb5_data *data; + krb5_cksumtype cksumtype; + krb5_authdata ad_datum; + krb5_authdata *ad_data[2]; + + *ad_kdcissued = NULL; + + ad_kdci.ad_checksum.contents = NULL; + ad_kdci.i_principal = (krb5_principal)issuer; + ad_kdci.elements = (krb5_authdata **)authdata; + + code = krb5int_c_mandatory_cksumtype(context, key->enctype, + &cksumtype); + if (code != 0) + return code; + + if (!krb5_c_is_keyed_cksum(cksumtype)) + return KRB5KRB_AP_ERR_INAPP_CKSUM; + + code = encode_krb5_authdata(ad_kdci.elements, &data); + if (code != 0) + return code; + + code = krb5_c_make_checksum(context, cksumtype, + key, KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM, + data, &ad_kdci.ad_checksum); + if (code != 0) { + krb5_free_data(context, data); + return code; + } + + krb5_free_data(context, data); + + code = encode_krb5_ad_kdcissued(&ad_kdci, &data); + if (code != 0) + return code; + + ad_datum.ad_type = KRB5_AUTHDATA_KDC_ISSUED; + ad_datum.length = data->length; + ad_datum.contents = (unsigned char *)data->data; + + ad_data[0] = &ad_datum; + ad_data[1] = NULL; + + code = krb5_copy_authdata(context, ad_data, ad_kdcissued); + + krb5_free_data(context, data); + krb5_free_checksum_contents(context, &ad_kdci.ad_checksum); + + return code; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/authdata_exp.c b/krb5-1.21.3/src/lib/krb5/krb/authdata_exp.c new file mode 100644 index 00000000..22758190 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/authdata_exp.c @@ -0,0 +1,95 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. All + * Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * krb5_authdata_export_authdata() + */ + +#include "k5-int.h" +#include "authdata.h" +#include "auth_con.h" +#include "int-proto.h" + +krb5_error_code KRB5_CALLCONV +krb5_authdata_export_authdata(krb5_context kcontext, + krb5_authdata_context context, + krb5_flags flags, + krb5_authdata ***pauthdata) +{ + int i; + krb5_error_code code = 0; + krb5_authdata **authdata = NULL; + unsigned int len = 0; + + *pauthdata = NULL; + + for (i = 0; i < context->n_modules; i++) { + struct _krb5_authdata_context_module *module = &context->modules[i]; + krb5_authdata **authdata2 = NULL; + int j; + + if ((module->flags & flags) == 0) + continue; + + if (module->ftable->export_authdata == NULL) + continue; + + code = (*module->ftable->export_authdata)(kcontext, + context, + module->plugin_context, + *(module->request_context_pp), + flags, + &authdata2); + if (code == ENOENT) + code = 0; + else if (code != 0) + break; + + if (authdata2 == NULL) + continue; + + for (j = 0; authdata2[j] != NULL; j++) + ; + + authdata = realloc(authdata, (len + j + 1) * sizeof(krb5_authdata *)); + if (authdata == NULL) + return ENOMEM; + + memcpy(&authdata[len], authdata2, j * sizeof(krb5_authdata *)); + free(authdata2); + + len += j; + } + + if (authdata != NULL) + authdata[len] = NULL; + + if (code != 0) { + krb5_free_authdata(kcontext, authdata); + return code; + } + + *pauthdata = authdata; + + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/bld_pr_ext.c b/krb5-1.21.3/src/lib/krb5/krb/bld_pr_ext.c new file mode 100644 index 00000000..4da6f9fb --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/bld_pr_ext.c @@ -0,0 +1,98 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/bld_pr_ext.c */ +/* + * Copyright 1991, 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * Build a principal from a list of lengths and strings + */ + +#include "k5-int.h" +#include "int-proto.h" + +#include + +krb5_error_code KRB5_CALLCONV_C +krb5_build_principal_ext(krb5_context context, krb5_principal * princ, + unsigned int rlen, const char * realm, ...) +{ + va_list ap; + int i, count = 0; + krb5_data *princ_data; + krb5_principal princ_ret; + krb5_data tmpdata; + + va_start(ap, realm); + /* count up */ + while (va_arg(ap, int) != 0) { + (void)va_arg(ap, char *); /* pass one up */ + count++; + } + va_end(ap); + + /* we do a 2-pass to avoid the need to guess on allocation needs + cf. bld_princ.c */ + /* get space for array */ + princ_data = (krb5_data *) malloc(sizeof(krb5_data) * count); + if (!princ_data) + return ENOMEM; + princ_ret = (krb5_principal) malloc(sizeof(krb5_principal_data)); + if (!princ_ret) { + free(princ_data); + return ENOMEM; + } + princ_ret->data = princ_data; + princ_ret->length = count; + tmpdata.length = rlen; + tmpdata.data = (char *) realm; + if (krb5int_copy_data_contents_add0(context, &tmpdata, &princ_ret->realm) != 0) { + free(princ_data); + free(princ_ret); + return ENOMEM; + } + + /* process rest of components */ + va_start(ap, realm); + for (i = 0; i < count; i++) { + tmpdata.length = va_arg(ap, unsigned int); + tmpdata.data = va_arg(ap, char *); + if (krb5int_copy_data_contents_add0(context, &tmpdata, + &princ_data[i]) != 0) + goto free_out; + } + va_end(ap); + *princ = princ_ret; + princ_ret->type = k5_infer_principal_type(princ_ret); + return 0; + +free_out: + while (--i >= 0) + free(princ_data[i].data); + free(princ_data); + free(princ_ret->realm.data); + free(princ_ret); + va_end(ap); + return ENOMEM; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/bld_princ.c b/krb5-1.21.3/src/lib/krb5/krb/bld_princ.c new file mode 100644 index 00000000..ff8265ac --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/bld_princ.c @@ -0,0 +1,182 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/bld_princ.c - Build a principal from a list of strings */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" + +krb5_int32 +k5_infer_principal_type(krb5_principal princ) +{ + /* RFC 4120 section 7.3 */ + if (princ->length == 2 && data_eq_string(princ->data[0], KRB5_TGS_NAME)) + return KRB5_NT_SRV_INST; + + /* RFC 6111 section 3.1 */ + if (princ->length >= 2 && + data_eq_string(princ->data[0], KRB5_WELLKNOWN_NAMESTR)) + return KRB5_NT_WELLKNOWN; + + return KRB5_NT_PRINCIPAL; +} + +static krb5_error_code +build_principal_va(krb5_context context, krb5_principal princ, + unsigned int rlen, const char *realm, va_list ap) +{ + krb5_error_code retval = 0; + char *r = NULL; + krb5_data *data = NULL; + krb5_int32 count = 0; + krb5_int32 size = 2; /* initial guess at needed space */ + char *component = NULL; + + data = malloc(size * sizeof(krb5_data)); + if (!data) { retval = ENOMEM; } + + if (!retval) + r = k5memdup0(realm, rlen, &retval); + + while (!retval && (component = va_arg(ap, char *))) { + if (count == size) { + krb5_data *new_data = NULL; + + size *= 2; + new_data = realloc(data, size * sizeof(krb5_data)); + if (new_data) { + data = new_data; + } else { + retval = ENOMEM; + } + } + + if (!retval) { + data[count].length = strlen(component); + data[count].data = strdup(component); + if (!data[count].data) { retval = ENOMEM; } + count++; + } + } + + if (!retval) { + princ->magic = KV5M_PRINCIPAL; + princ->realm = make_data(r, rlen); + princ->data = data; + princ->length = count; + princ->type = k5_infer_principal_type(princ); + r = NULL; /* take ownership */ + data = NULL; /* take ownership */ + } + + if (data) { + while (--count >= 0) { + free(data[count].data); + } + free(data); + } + free(r); + + return retval; +} + +krb5_error_code KRB5_CALLCONV +krb5_build_principal_va(krb5_context context, + krb5_principal princ, + unsigned int rlen, + const char *realm, + va_list ap) +{ + return build_principal_va(context, princ, rlen, realm, ap); +} + +krb5_error_code KRB5_CALLCONV +krb5_build_principal_alloc_va(krb5_context context, + krb5_principal *princ, + unsigned int rlen, + const char *realm, + va_list ap) +{ + krb5_error_code retval = 0; + krb5_principal p; + + p = malloc(sizeof(krb5_principal_data)); + if (p == NULL) + return ENOMEM; + + retval = build_principal_va(context, p, rlen, realm, ap); + if (retval) { + free(p); + return retval; + } + + *princ = p; + return 0; +} + +krb5_error_code KRB5_CALLCONV_C +krb5_build_principal(krb5_context context, + krb5_principal * princ, + unsigned int rlen, + const char * realm, ...) +{ + krb5_error_code retval = 0; + va_list ap; + + va_start(ap, realm); + retval = krb5_build_principal_alloc_va(context, princ, rlen, realm, ap); + va_end(ap); + + return retval; +} + +/*Anonymous and well known principals*/ +static const char anon_realm_str[] = KRB5_ANONYMOUS_REALMSTR; +static const krb5_data anon_realm_data = { + KV5M_DATA, sizeof(anon_realm_str) - 1, (char *) anon_realm_str +}; +static const char wellknown_str[] = KRB5_WELLKNOWN_NAMESTR; +static const char anon_str[] = KRB5_ANONYMOUS_PRINCSTR; +static const krb5_data anon_princ_data[] = { + { KV5M_DATA, sizeof(wellknown_str) - 1, (char *) wellknown_str }, + { KV5M_DATA, sizeof(anon_str) - 1, (char *) anon_str } +}; + +const krb5_principal_data anon_princ = { + KV5M_PRINCIPAL, + { KV5M_DATA, sizeof(anon_realm_str) - 1, (char *) anon_realm_str }, + (krb5_data *) anon_princ_data, 2, KRB5_NT_WELLKNOWN +}; + +const krb5_data * KRB5_CALLCONV +krb5_anonymous_realm() +{ + return &anon_realm_data; +} + +krb5_const_principal KRB5_CALLCONV +krb5_anonymous_principal() +{ + return &anon_princ; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/brand.c b/krb5-1.21.3/src/lib/krb5/krb/brand.c new file mode 100644 index 00000000..60662d5b --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/brand.c @@ -0,0 +1,72 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/brand.c */ +/* + * Copyright (C) 2004 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This file is used to put a "release brand" on a Krb5 library before + * it is released via some release engineering process. This gives us + * an easy way to tell where a binary came from. + * + * It depends on patchlevel.h for the master version stamp info. + */ + +/* Format: "KRB5_BRAND: " */ + +#include "patchlevel.h" + +#define XSTR(x) #x +#define STR(x) XSTR(x) + +#ifdef KRB5_RELTAG +#define RELTAG KRB5_RELTAG +#else +#define RELTAG "[untagged]" +#endif + +#define MAJOR_MINOR STR(KRB5_MAJOR_RELEASE) "." STR(KRB5_MINOR_RELEASE) + +#if KRB5_PATCHLEVEL != 0 +#define MAYBE_PATCH "." STR(KRB5_PATCHLEVEL) +#else +#define MAYBE_PATCH "" +#endif + +#ifdef KRB5_RELTAIL +#define RELTAIL "-" KRB5_RELTAIL +#else +#define RELTAIL "" +#endif + +#define RELNAME MAJOR_MINOR MAYBE_PATCH RELTAIL + +#ifdef KRB5_RELDATE +#define RELDATE KRB5_RELDATE +#else +#define RELDATE "[date unknown]" +#endif + +#define BRANDSTR RELTAG " " RELNAME " " RELDATE + +char krb5_brand[] = "KRB5_BRAND: " BRANDSTR; diff --git a/krb5-1.21.3/src/lib/krb5/krb/cammac_util.c b/krb5-1.21.3/src/lib/krb5/krb/cammac_util.c new file mode 100644 index 00000000..ab9da05a --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/cammac_util.c @@ -0,0 +1,86 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* cammac_util.c - CAMMAC related functions */ +/* + * Copyright (C) 2016 by Red Hat, Inc. + * 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. + */ + +#include "k5-int.h" + +/* Return 0 if cammac's service verifier is valid for server_key. */ +static krb5_error_code +check_svcver(krb5_context context, const krb5_cammac *cammac, + const krb5_keyblock *server_key) +{ + krb5_error_code ret; + krb5_boolean valid = FALSE; + krb5_verifier_mac *ver = cammac->svc_verifier; + krb5_data *der_authdata = NULL; + + if (ver == NULL) + return EINVAL; + + ret = encode_krb5_authdata(cammac->elements, &der_authdata); + if (ret) + return ret; + + ret = krb5_c_verify_checksum(context, server_key, KRB5_KEYUSAGE_CAMMAC, + der_authdata, &ver->checksum, &valid); + if (!ret && !valid) + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + + krb5_free_data(context, der_authdata); + return ret; +} + +/* Decode and verify CAMMAC authdata using the svc verifier, + * and return the contents as an allocated array of authdata pointers. */ +krb5_error_code +k5_unwrap_cammac_svc(krb5_context context, const krb5_authdata *ad, + const krb5_keyblock *key, krb5_authdata ***adata_out) +{ + krb5_data ad_data; + krb5_error_code ret; + krb5_cammac *cammac = NULL; + + *adata_out = NULL; + + ad_data = make_data(ad->contents, ad->length); + ret = decode_krb5_cammac(&ad_data, &cammac); + if (ret) + return ret; + + ret = check_svcver(context, cammac, key); + if (!ret) { + *adata_out = cammac->elements; + cammac->elements = NULL; + } + + k5_free_cammac(context, cammac); + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/chk_trans.c b/krb5-1.21.3/src/lib/krb5/krb/chk_trans.c new file mode 100644 index 00000000..36c6845b --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/chk_trans.c @@ -0,0 +1,438 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/chk_trans.c */ +/* + * Copyright 2001, 2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include + +#if defined (TEST) || defined (TEST2) +# undef DEBUG +# define DEBUG +#endif + +#ifdef DEBUG +#define verbose krb5int_chk_trans_verbose +static int verbose = 0; +# define Tprintf(ARGS) if (verbose) printf ARGS +#else +# define Tprintf(ARGS) (void)(0) +#endif + +#define MAXLEN 512 + +static krb5_error_code +process_intermediates (krb5_error_code (*fn)(krb5_data *, void *), void *data, + const krb5_data *n1, const krb5_data *n2) { + unsigned int len1, len2, i; + char *p1, *p2; + + Tprintf (("process_intermediates(%.*s,%.*s)\n", + (int) n1->length, n1->data, (int) n2->length, n2->data)); + + len1 = n1->length; + len2 = n2->length; + + Tprintf (("(walking intermediates now)\n")); + /* Simplify... */ + if (len1 > len2) { + const krb5_data *p; + int tmp = len1; + len1 = len2; + len2 = tmp; + p = n1; + n1 = n2; + n2 = p; + } + /* Okay, now len1 is always shorter or equal. */ + if (len1 == len2) { + if (memcmp (n1->data, n2->data, len1)) { + Tprintf (("equal length but different strings in path: '%.*s' '%.*s'\n", + (int) n1->length, n1->data, (int) n2->length, n2->data)); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + Tprintf (("(end intermediates)\n")); + return 0; + } + /* Now len1 is always shorter. */ + if (len1 == 0) + /* Shouldn't be possible. Internal error? */ + return KRB5KRB_AP_ERR_ILL_CR_TKT; + p1 = n1->data; + p2 = n2->data; + if (p1[0] == '/') { + /* X.500 style names, with common prefix. */ + if (p2[0] != '/') { + Tprintf (("mixed name formats in path: x500='%.*s' domain='%.*s'\n", + (int) len1, p1, (int) len2, p2)); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + if (memcmp (p1, p2, len1)) { + Tprintf (("x500 names with different prefixes '%.*s' '%.*s'\n", + (int) len1, p1, (int) len2, p2)); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + for (i = len1 + 1; i < len2; i++) + if (p2[i] == '/') { + krb5_data d; + krb5_error_code r; + + d.data = p2; + d.length = i; + r = (*fn) (&d, data); + if (r) + return r; + } + } else { + /* Domain style names, with common suffix. */ + if (p2[0] == '/') { + Tprintf (("mixed name formats in path: domain='%.*s' x500='%.*s'\n", + (int) len1, p1, (int) len2, p2)); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + if (memcmp (p1, p2 + (len2 - len1), len1)) { + Tprintf (("domain names with different suffixes '%.*s' '%.*s'\n", + (int) len1, p1, (int) len2, p2)); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + for (i = len2 - len1 - 1; i > 0; i--) { + Tprintf (("looking at '%.*s'\n", (int) (len2 - i), p2+i)); + if (p2[i-1] == '.') { + krb5_data d; + krb5_error_code r; + + d.data = p2+i; + d.length = len2 - i; + r = (*fn) (&d, data); + if (r) + return r; + } + } + } + Tprintf (("(end intermediates)\n")); + return 0; +} + +static krb5_error_code +maybe_join (krb5_data *last, krb5_data *buf, unsigned int bufsiz) +{ + if (buf->length == 0) + return 0; + if (buf->data[0] == '/') { + if (last->length + buf->length > bufsiz) { + Tprintf (("too big: last=%d cur=%d max=%d\n", last->length, buf->length, bufsiz)); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + memmove (buf->data+last->length, buf->data, buf->length); + memcpy (buf->data, last->data, last->length); + buf->length += last->length; + } else if (buf->data[buf->length-1] == '.') { + /* We can ignore the case where the previous component was + empty; the strcat will be a no-op. It should probably + be an error case, but let's be flexible. */ + if (last->length+buf->length > bufsiz) { + Tprintf (("too big\n")); + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + memcpy (buf->data + buf->length, last->data, last->length); + buf->length += last->length; + } + /* Otherwise, do nothing. */ + return 0; +} + +/* The input strings cannot contain any \0 bytes, according to the + spec, but our API is such that they may not be \0 terminated + either. Thus we keep on treating them as krb5_data objects instead + of C strings. */ +static krb5_error_code +foreach_realm (krb5_error_code (*fn)(krb5_data *comp,void *data), void *data, + const krb5_data *crealm, const krb5_data *srealm, + const krb5_data *transit) +{ + char buf[MAXLEN], last[MAXLEN]; + char *p, *bufp; + int next_lit, intermediates, l; + krb5_data this_component; + krb5_error_code r; + krb5_data last_component; + + /* Invariants: + - last_component points to last[] + - this_component points to buf[] + - last_component has length of last + - this_component has length of buf when calling out + Keep these consistent, and we should be okay. */ + + next_lit = 0; + intermediates = 0; + memset (buf, 0, sizeof (buf)); + + this_component.data = buf; + last_component.data = last; + last_component.length = 0; + +#define print_data(fmt,d) Tprintf((fmt,(int)(d)->length,(d)->data)) + print_data ("client realm: %.*s\n", crealm); + print_data ("server realm: %.*s\n", srealm); + print_data ("transit enc.: %.*s\n", transit); + + if (transit->length == 0) { + Tprintf (("no other realms transited\n")); + return 0; + } + + bufp = buf; + for (p = transit->data, l = transit->length; l; p++, l--) { + if (next_lit) { + *bufp++ = *p; + if (bufp == buf+sizeof(buf)) + return KRB5KRB_AP_ERR_ILL_CR_TKT; + next_lit = 0; + } else if (*p == '\\') { + next_lit = 1; + } else if (*p == ',') { + if (bufp != buf) { + this_component.length = bufp - buf; + r = maybe_join (&last_component, &this_component, sizeof(buf)); + if (r) + return r; + r = (*fn) (&this_component, data); + if (r) + return r; + if (intermediates) { + if (p == transit->data) + r = process_intermediates (fn, data, + &this_component, crealm); + else { + r = process_intermediates (fn, data, &this_component, + &last_component); + } + if (r) + return r; + } + intermediates = 0; + memcpy (last, buf, sizeof (buf)); + last_component.length = this_component.length; + memset (buf, 0, sizeof (buf)); + bufp = buf; + } else { + intermediates = 1; + if (p == transit->data) { + if (crealm->length >= MAXLEN) + return KRB5KRB_AP_ERR_ILL_CR_TKT; + if (crealm->length > 0) + memcpy (last, crealm->data, crealm->length); + last[crealm->length] = '\0'; + last_component.length = crealm->length; + } + } + } else if (*p == ' ' && bufp == buf) { + /* This next component stands alone, even if it has a + trailing dot or leading slash. */ + memset (last, 0, sizeof (last)); + last_component.length = 0; + } else { + /* Not a special character; literal. */ + *bufp++ = *p; + if (bufp == buf+sizeof(buf)) + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + } + /* At end. Must be normal state. */ + if (next_lit) + Tprintf (("ending in next-char-literal state\n")); + /* Process trailing element or comma. */ + if (bufp == buf) { + /* Trailing comma. */ + r = process_intermediates (fn, data, &last_component, srealm); + } else { + /* Trailing component. */ + this_component.length = bufp - buf; + r = maybe_join (&last_component, &this_component, sizeof(buf)); + if (r) + return r; + r = (*fn) (&this_component, data); + if (r) + return r; + if (intermediates) + r = process_intermediates (fn, data, &this_component, + &last_component); + } + if (r != 0) + return r; + return 0; +} + +struct check_data { + krb5_context ctx; + krb5_principal *tgs; +}; + +static krb5_error_code +check_realm_in_list (krb5_data *realm, void *data) +{ + struct check_data *cdata = data; + int i; + + Tprintf ((".. checking '%.*s'\n", (int) realm->length, realm->data)); + for (i = 0; cdata->tgs[i]; i++) { + if (data_eq (cdata->tgs[i]->realm, *realm)) + return 0; + } + Tprintf (("BAD!\n")); + return KRB5KRB_AP_ERR_ILL_CR_TKT; +} + +krb5_error_code +krb5_check_transited_list (krb5_context ctx, const krb5_data *trans_in, + const krb5_data *crealm, const krb5_data *srealm) +{ + krb5_data trans; + struct check_data cdata; + krb5_error_code r; + const krb5_data *anonymous; + + trans.length = trans_in->length; + trans.data = (char *) trans_in->data; + if (trans.length && (trans.data[trans.length-1] == '\0')) + trans.length--; + + Tprintf (("krb5_check_transited_list(trans=\"%.*s\", crealm=\"%.*s\", srealm=\"%.*s\")\n", + (int) trans.length, trans.data, + (int) crealm->length, crealm->data, + (int) srealm->length, srealm->data)); + if (trans.length == 0) + return 0; + anonymous = krb5_anonymous_realm(); + if (crealm->length == anonymous->length && + (memcmp(crealm->data, anonymous->data, anonymous->length) == 0)) + return 0; /* Nothing to check for anonymous */ + + r = krb5_walk_realm_tree (ctx, crealm, srealm, &cdata.tgs, + KRB5_REALM_BRANCH_CHAR); + if (r) { + Tprintf (("error %ld\n", (long) r)); + return r; + } +#ifdef DEBUG /* avoid compiler warning about 'd' unused */ + { + int i; + Tprintf (("tgs list = {\n")); + for (i = 0; cdata.tgs[i]; i++) { + char *name; + r = krb5_unparse_name (ctx, cdata.tgs[i], &name); + Tprintf (("\t'%s'\n", name)); + free (name); + } + Tprintf (("}\n")); + } +#endif + cdata.ctx = ctx; + r = foreach_realm (check_realm_in_list, &cdata, crealm, srealm, &trans); + krb5_free_realm_tree (ctx, cdata.tgs); + return r; +} + +#ifdef TEST + +static krb5_error_code +print_a_realm (krb5_data *realm, void *data) +{ + printf ("%.*s\n", (int) realm->length, realm->data); + return 0; +} + +int main (int argc, char *argv[]) { + const char *me; + krb5_data crealm, srealm, transit; + krb5_error_code r; + int expand_only = 0; + + me = strrchr (argv[0], '/'); + me = me ? me+1 : argv[0]; + + while (argc > 3 && argv[1][0] == '-') { + if (!strcmp ("-v", argv[1])) + verbose++, argc--, argv++; + else if (!strcmp ("-x", argv[1])) + expand_only++, argc--, argv++; + else + goto usage; + } + + if (argc != 4) { + usage: + printf ("usage: %s [-v] [-x] clientRealm serverRealm transitEncoding\n", + me); + return 1; + } + + crealm.data = argv[1]; + crealm.length = strlen(argv[1]); + srealm.data = argv[2]; + srealm.length = strlen(argv[2]); + transit.data = argv[3]; + transit.length = strlen(argv[3]); + + if (expand_only) { + + printf ("client realm: %s\n", argv[1]); + printf ("server realm: %s\n", argv[2]); + printf ("transit enc.: %s\n", argv[3]); + + if (argv[3][0] == 0) { + printf ("no other realms transited\n"); + return 0; + } + + r = foreach_realm (print_a_realm, NULL, &crealm, &srealm, &transit); + if (r) + printf ("--> returned error %ld\n", (long) r); + return r != 0; + + } else { + + /* Actually check the values against the supplied krb5.conf file. */ + krb5_context ctx; + r = krb5_init_context (&ctx); + if (r) { + com_err (me, r, "initializing krb5 context"); + return 1; + } + r = krb5_check_transited_list (ctx, &transit, &crealm, &srealm); + if (r == KRB5KRB_AP_ERR_ILL_CR_TKT) { + printf ("NO\n"); + } else if (r == 0) { + printf ("YES\n"); + } else { + printf ("kablooey!\n"); + com_err (me, r, "checking transited-realm list"); + return 1; + } + return 0; + } +} + +#endif /* TEST */ diff --git a/krb5-1.21.3/src/lib/krb5/krb/chpw.c b/krb5-1.21.3/src/lib/krb5/krb/chpw.c new file mode 100644 index 00000000..aca39459 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/chpw.c @@ -0,0 +1,510 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* +** set password functions added by Paul W. Nelson, Thursby Software Systems, Inc. +*/ + +#include "k5-int.h" +#include "k5-unicode.h" +#include "int-proto.h" +#include "auth_con.h" + + +krb5_error_code +krb5int_mk_chpw_req(krb5_context context, + krb5_auth_context auth_context, + krb5_data *ap_req, + const char *passwd, + krb5_data *packet) +{ + krb5_error_code ret = 0; + krb5_data clearpw; + krb5_data cipherpw; + krb5_replay_data replay; + char *ptr; + + cipherpw.data = NULL; + + if ((ret = krb5_auth_con_setflags(context, auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE))) + goto cleanup; + + clearpw = string2data((char *)passwd); + + if ((ret = krb5_mk_priv(context, auth_context, + &clearpw, &cipherpw, &replay))) + goto cleanup; + + packet->length = 6 + ap_req->length + cipherpw.length; + packet->data = (char *) malloc(packet->length); + if (packet->data == NULL) { + ret = ENOMEM; + goto cleanup; + } + ptr = packet->data; + + /* length */ + + store_16_be(packet->length, ptr); + ptr += 2; + + /* version == 0x0001 big-endian */ + + *ptr++ = 0; + *ptr++ = 1; + + /* ap_req length, big-endian */ + + store_16_be(ap_req->length, ptr); + ptr += 2; + + /* ap-req data */ + + memcpy(ptr, ap_req->data, ap_req->length); + ptr += ap_req->length; + + /* krb-priv of password */ + + memcpy(ptr, cipherpw.data, cipherpw.length); + +cleanup: + if (cipherpw.data != NULL) /* allocated by krb5_mk_priv */ + free(cipherpw.data); + + return(ret); +} + +/* Decode error_packet as a KRB-ERROR message and retrieve its e-data into + * *edata_out. */ +static krb5_error_code +get_error_edata(krb5_context context, const krb5_data *error_packet, + krb5_data **edata_out) +{ + krb5_error_code ret; + krb5_error *krberror = NULL; + + *edata_out = NULL; + + ret = krb5_rd_error(context, error_packet, &krberror); + if (ret) + return ret; + + if (krberror->e_data.data == NULL) { + /* Return a krb5 error code based on the error number. */ + ret = ERROR_TABLE_BASE_krb5 + (krb5_error_code)krberror->error; + goto cleanup; + } + + ret = krb5_copy_data(context, &krberror->e_data, edata_out); + +cleanup: + krb5_free_error(context, krberror); + return ret; +} + +/* Decode a reply to produce the clear-text output. */ +static krb5_error_code +get_clear_result(krb5_context context, krb5_auth_context auth_context, + const krb5_data *packet, krb5_data **clear_out, + krb5_boolean *is_error_out) +{ + krb5_error_code ret; + char *ptr, *end = packet->data + packet->length; + unsigned int plen, vno, aplen; + krb5_data ap_rep, cipher, error; + krb5_ap_rep_enc_part *ap_rep_enc; + krb5_replay_data replay; + krb5_key send_subkey = NULL; + krb5_data clear = empty_data(); + + *clear_out = NULL; + *is_error_out = FALSE; + + /* Check for an unframed KRB-ERROR (expected for RFC 3244 requests; also + * received from MS AD for version 1 requests). */ + if (krb5_is_krb_error(packet)) { + *is_error_out = TRUE; + return get_error_edata(context, packet, clear_out); + } + + if (packet->length < 6) + return KRB5KRB_AP_ERR_MODIFIED; + + /* Decode and verify the length. */ + ptr = packet->data; + plen = (*ptr++ & 0xff); + plen = (plen << 8) | (*ptr++ & 0xff); + if (plen != packet->length) + return KRB5KRB_AP_ERR_MODIFIED; + + /* Decode and verify the version number. */ + vno = (*ptr++ & 0xff); + vno = (vno << 8) | (*ptr++ & 0xff); + if (vno != 1 && vno != 0xff80) + return KRB5KDC_ERR_BAD_PVNO; + + /* Decode and check the AP-REP length. */ + aplen = (*ptr++ & 0xff); + aplen = (aplen << 8) | (*ptr++ & 0xff); + if (aplen > end - ptr) + return KRB5KRB_AP_ERR_MODIFIED; + + /* A zero-length AP-REQ indicates a framed KRB-ERROR response. (Expected + * for protocol version 1; specified but unusual for RFC 3244 requests.) */ + if (aplen == 0) { + *is_error_out = TRUE; + error = make_data(ptr, end - ptr); + return get_error_edata(context, &error, clear_out); + } + + /* We have an AP-REP. Save send_subkey to later smash recv_subkey. */ + ret = krb5_auth_con_getsendsubkey_k(context, auth_context, &send_subkey); + if (ret) + return ret; + + /* Verify the AP-REP. */ + ap_rep = make_data(ptr, aplen); + ptr += ap_rep.length; + ret = krb5_rd_rep(context, auth_context, &ap_rep, &ap_rep_enc); + if (ret) + goto cleanup; + krb5_free_ap_rep_enc_part(context, ap_rep_enc); + + /* Smash recv_subkey to be send_subkey, per spec. */ + ret = krb5_auth_con_setrecvsubkey_k(context, auth_context, send_subkey); + if (ret) + goto cleanup; + + /* Extract and decrypt the result. */ + cipher = make_data(ptr, end - ptr); + ret = krb5_rd_priv(context, auth_context, &cipher, &clear, &replay); + if (ret) + goto cleanup; + + ret = krb5_copy_data(context, &clear, clear_out); + if (ret) + goto cleanup; + *is_error_out = FALSE; + +cleanup: + krb5_k_free_key(context, send_subkey); + krb5_free_data_contents(context, &clear); + return ret; +} + +krb5_error_code +krb5int_rd_chpw_rep(krb5_context context, krb5_auth_context auth_context, + krb5_data *packet, int *result_code_out, + krb5_data *result_data_out) +{ + krb5_error_code ret; + krb5_data result_data, *clear = NULL; + krb5_boolean is_error; + char *ptr; + int result_code; + + *result_code_out = 0; + *result_data_out = empty_data(); + + ret = get_clear_result(context, auth_context, packet, &clear, &is_error); + if (ret) + return ret; + + if (clear->length < 2) { + ret = KRB5KRB_AP_ERR_MODIFIED; + goto cleanup; + } + + /* Decode and check the result code. */ + ptr = clear->data; + result_code = (*ptr++ & 0xff); + result_code = (result_code << 8) | (*ptr++ & 0xff); + if (result_code < KRB5_KPASSWD_SUCCESS || + result_code > KRB5_KPASSWD_INITIAL_FLAG_NEEDED) { + ret = KRB5KRB_AP_ERR_MODIFIED; + goto cleanup; + } + + /* Successful replies must not come from errors. */ + if (is_error && result_code == KRB5_KPASSWD_SUCCESS) { + ret = KRB5KRB_AP_ERR_MODIFIED; + goto cleanup; + } + + result_data = make_data(ptr, clear->data + clear->length - ptr); + ret = krb5int_copy_data_contents(context, &result_data, result_data_out); + if (ret) + goto cleanup; + *result_code_out = result_code; + +cleanup: + krb5_free_data(context, clear); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_chpw_result_code_string(krb5_context context, int result_code, + char **code_string) +{ + switch (result_code) { + case KRB5_KPASSWD_MALFORMED: + *code_string = _("Malformed request error"); + break; + case KRB5_KPASSWD_HARDERROR: + *code_string = _("Server error"); + break; + case KRB5_KPASSWD_AUTHERROR: + *code_string = _("Authentication error"); + break; + case KRB5_KPASSWD_SOFTERROR: + *code_string = _("Password change rejected"); + break; + case KRB5_KPASSWD_ACCESSDENIED: + *code_string = _("Access denied"); + break; + case KRB5_KPASSWD_BAD_VERSION: + *code_string = _("Wrong protocol version"); + break; + case KRB5_KPASSWD_INITIAL_FLAG_NEEDED: + *code_string = _("Initial password required"); + break; + case 0: + *code_string = _("Success"); + break; + default: + *code_string = _("Password change failed"); + break; + } + + return 0; +} + +krb5_error_code +krb5int_mk_setpw_req(krb5_context context, + krb5_auth_context auth_context, + krb5_data *ap_req, + krb5_principal targprinc, + const char *passwd, + krb5_data *packet) +{ + krb5_error_code ret; + krb5_data cipherpw; + krb5_data *encoded_setpw; + struct krb5_setpw_req req; + + char *ptr; + + cipherpw.data = NULL; + cipherpw.length = 0; + + if ((ret = krb5_auth_con_setflags(context, auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE))) + return(ret); + + req.target = targprinc; + req.password = string2data((char *)passwd); + ret = encode_krb5_setpw_req(&req, &encoded_setpw); + if (ret) { + return ret; + } + + if ((ret = krb5_mk_priv(context, auth_context, encoded_setpw, &cipherpw, NULL)) != 0) { + krb5_free_data(context, encoded_setpw); + return(ret); + } + krb5_free_data(context, encoded_setpw); + + + packet->length = 6 + ap_req->length + cipherpw.length; + packet->data = (char *) malloc(packet->length); + if (packet->data == NULL) { + ret = ENOMEM; + goto cleanup; + } + ptr = packet->data; + /* + ** build the packet - + */ + /* put in the length */ + store_16_be(packet->length, ptr); + ptr += 2; + /* put in the version */ + *ptr++ = (char)0xff; + *ptr++ = (char)0x80; + /* the ap_req length is big endian */ + store_16_be(ap_req->length, ptr); + ptr += 2; + /* put in the request data */ + memcpy(ptr, ap_req->data, ap_req->length); + ptr += ap_req->length; + /* + ** put in the "private" password data - + */ + memcpy(ptr, cipherpw.data, cipherpw.length); + ret = 0; +cleanup: + if (cipherpw.data) + krb5_free_data_contents(context, &cipherpw); + if ((ret != 0) && packet->data) { + free(packet->data); + packet->data = NULL; + } + return ret; +} + +/* + * Active Directory policy information is communicated in the result string + * field as a packed 30-byte sequence, starting with two zero bytes (so that + * the string appears as zero-length when interpreted as UTF-8). The bytes + * correspond to the fields in the following structure, with each field in + * big-endian byte order. + */ +struct ad_policy_info { + uint16_t zero_bytes; + uint32_t min_length_password; + uint32_t password_history; + uint32_t password_properties; /* see defines below */ + uint64_t expire; /* in seconds * 10,000,000 */ + uint64_t min_passwordage; /* in seconds * 10,000,000 */ +}; + +#define AD_POLICY_INFO_LENGTH 30 +#define AD_POLICY_TIME_TO_DAYS (86400ULL * 10000000ULL) + +#define AD_POLICY_COMPLEX 0x00000001 +#define AD_POLICY_NO_ANON_CHANGE 0x00000002 +#define AD_POLICY_NO_CLEAR_CHANGE 0x00000004 +#define AD_POLICY_LOCKOUT_ADMINS 0x00000008 +#define AD_POLICY_STORE_CLEARTEXT 0x00000010 +#define AD_POLICY_REFUSE_CHANGE 0x00000020 + +/* If buf already contains one or more sentences, add spaces to separate them + * from the next sentence. */ +static void +add_spaces(struct k5buf *buf) +{ + if (buf->len > 0) + k5_buf_add(buf, " "); +} + +static krb5_error_code +decode_ad_policy_info(const krb5_data *data, char **msg_out) +{ + struct ad_policy_info policy; + uint64_t password_days; + const char *p; + struct k5buf buf; + char *msg; + + *msg_out = NULL; + if (data->length != AD_POLICY_INFO_LENGTH) + return 0; + + p = data->data; + policy.zero_bytes = load_16_be(p); + p += 2; + + /* first two bytes are zeros */ + if (policy.zero_bytes != 0) + return 0; + + /* Read in the rest of structure */ + policy.min_length_password = load_32_be(p); + p += 4; + policy.password_history = load_32_be(p); + p += 4; + policy.password_properties = load_32_be(p); + p += 4; + policy.expire = load_64_be(p); + p += 8; + policy.min_passwordage = load_64_be(p); + p += 8; + + /* Check that we processed exactly the expected number of bytes. */ + assert(p == data->data + AD_POLICY_INFO_LENGTH); + + k5_buf_init_dynamic(&buf); + + /* + * Update src/tests/misc/test_chpw_message.c if changing these strings! + */ + + if (policy.password_properties & AD_POLICY_COMPLEX) { + k5_buf_add(&buf, _("The password must include numbers or symbols. " + "Don't include any part of your name in the " + "password.")); + } + if (policy.min_length_password > 0) { + add_spaces(&buf); + k5_buf_add_fmt(&buf, ngettext("The password must contain at least %d " + "character.", + "The password must contain at least %d " + "characters.", + policy.min_length_password), + policy.min_length_password); + } + if (policy.password_history) { + add_spaces(&buf); + k5_buf_add_fmt(&buf, ngettext("The password must be different from " + "the previous password.", + "The password must be different from " + "the previous %d passwords.", + policy.password_history), + policy.password_history); + } + if (policy.min_passwordage) { + password_days = policy.min_passwordage / AD_POLICY_TIME_TO_DAYS; + if (password_days == 0) + password_days = 1; + add_spaces(&buf); + k5_buf_add_fmt(&buf, ngettext("The password can only be changed once " + "a day.", + "The password can only be changed every " + "%d days.", (int)password_days), + (int)password_days); + } + + msg = k5_buf_cstring(&buf); + if (msg == NULL) + return ENOMEM; + if (*msg != '\0') + *msg_out = msg; + else + free(msg); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_chpw_message(krb5_context context, const krb5_data *server_string, + char **message_out) +{ + krb5_error_code ret; + char *msg; + + *message_out = NULL; + + /* If server_string contains an AD password policy, construct a message + * based on that. */ + ret = decode_ad_policy_info(server_string, &msg); + if (ret == 0 && msg != NULL) { + *message_out = msg; + return 0; + } + + /* If server_string contains a valid UTF-8 string, return that. */ + if (server_string->length > 0 && + memchr(server_string->data, 0, server_string->length) == NULL && + k5_utf8_validate(server_string)) { + *message_out = k5memdup0(server_string->data, server_string->length, + &ret); + return (*message_out == NULL) ? ENOMEM : 0; + } + + /* server_string appears invalid, so try to be helpful. */ + msg = strdup(_("Try a more complex password, or contact your " + "administrator.")); + if (msg == NULL) + return ENOMEM; + + *message_out = msg; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/conv_creds.c b/krb5-1.21.3/src/lib/krb5/krb/conv_creds.c new file mode 100644 index 00000000..6f460881 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/conv_creds.c @@ -0,0 +1,61 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1994 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include "k5-int.h" +#include +#include +#include +#include "port-sockets.h" +#include "socket-utils.h" + +krb5_error_code KRB5_CALLCONV +krb5_524_convert_creds(krb5_context context, krb5_creds *v5creds, + struct credentials *v4creds) +{ + return KRB524_KRB4_DISABLED; +} + +/* These may be needed for object-level backwards compatibility on Mac + OS and UNIX, but Windows should be okay. */ +#ifndef _WIN32 +#undef krb524_convert_creds_kdc +#undef krb524_init_ets + +/* Declarations ahead of the definitions will suppress some gcc + warnings. */ +void KRB5_CALLCONV krb524_init_ets (void); +krb5_error_code KRB5_CALLCONV +krb524_convert_creds_kdc(krb5_context context, krb5_creds *v5creds, + struct credentials *v4creds); + +krb5_error_code KRB5_CALLCONV +krb524_convert_creds_kdc(krb5_context context, krb5_creds *v5creds, + struct credentials *v4creds) +{ + return KRB524_KRB4_DISABLED; +} + +void KRB5_CALLCONV krb524_init_ets () +{ +} +#endif diff --git a/krb5-1.21.3/src/lib/krb5/krb/conv_princ.c b/krb5-1.21.3/src/lib/krb5/krb/conv_princ.c new file mode 100644 index 00000000..9601bb47 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/conv_princ.c @@ -0,0 +1,361 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/conv_princ.c */ +/* + * Copyright 1992 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Build a principal from a V4 specification, or separate a V5 + * principal into name, instance, and realm. + * + * NOTE: This is highly site specific, and is only really necessary + * for sites who need to convert from V4 to V5. It is used by both + * the KDC and the kdb5_convert program. Since its use is highly + * specialized, the necessary information is just going to be + * hard-coded in this file. + */ + +#include "k5-int.h" +#include +#include + +/* The maximum sizes for V4 aname, realm, sname, and instance +1 */ +/* Taken from krb.h */ +#define ANAME_SZ 40 +#define REALM_SZ 40 +#define SNAME_SZ 40 +#define INST_SZ 40 + +struct krb_convert { + char *v4_str; + char *v5_str; + unsigned int flags : 8; + unsigned int len : 8; +}; + +#define DO_REALM_CONVERSION 0x00000001 + +/* + * Kadmin doesn't do realm conversion because it's currently + * kadmin/REALM.NAME. Zephyr doesn't because it's just zephyr/zephyr. + * + * "Realm conversion" is a bit of a misnomer; really, the v5 name is + * using a FQDN or something that looks like it, where the v4 name is + * just using the first label. Sometimes that second principal name + * component is a hostname, sometimes the realm name, sometimes it's + * neither. + * + * This list should probably be more configurable, and more than + * likely on a per-realm basis, so locally-defined services can be + * added, or not. + */ +static const struct krb_convert sconv_list[] = { + /* Realm conversion, Change service name */ +#define RC(V5NAME,V4NAME) { V5NAME, V4NAME, DO_REALM_CONVERSION, sizeof(V5NAME)-1 } + /* Realm conversion */ +#define R(NAME) { NAME, NAME, DO_REALM_CONVERSION, sizeof(NAME)-1 } + /* No Realm conversion */ +#define NR(NAME) { NAME, NAME, 0, sizeof(NAME)-1 } + + NR("kadmin"), + RC("rcmd", "host"), + R("discuss"), + R("rvdsrv"), + R("sample"), + R("olc"), + R("pop"), + R("sis"), + R("rfs"), + R("imap"), + R("ftp"), + R("ecat"), + R("daemon"), + R("gnats"), + R("moira"), + R("prms"), + R("mandarin"), + R("register"), + R("changepw"), + R("sms"), + R("afpserver"), + R("gdss"), + R("news"), + R("abs"), + R("nfs"), + R("tftp"), + NR("zephyr"), + R("http"), + R("khttp"), + R("pgpsigner"), + R("irc"), + R("mandarin-agent"), + R("write"), + R("palladium"), + {0, 0, 0, 0}, +#undef R +#undef RC +#undef NR +}; + +/* + * char *strnchr(s, c, n) + * char *s; + * char c; + * unsigned int n; + * + * returns a pointer to the first occurrence of character c in the + * string s, or a NULL pointer if c does not occur in in the string; + * however, at most the first n characters will be considered. + * + * This falls in the "should have been in the ANSI C library" + * category. :-) + */ +static char * +strnchr(char *s, int c, unsigned int n) +{ + if (n < 1) + return 0; + + while (n-- && *s) { + if (*s == c) + return s; + s++; + } + return 0; +} + + +/* XXX This calls for a new error code */ +#define KRB5_INVALID_PRINCIPAL KRB5_LNAME_BADFORMAT + +krb5_error_code KRB5_CALLCONV +krb5_524_conv_principal(krb5_context context, krb5_const_principal princ, + char *name, char *inst, char *realm) +{ + const struct krb_convert *p; + const krb5_data *compo; + char *c, *tmp_realm, *tmp_prealm; + unsigned int tmp_realm_len; + int retval; + + if (context->profile == 0) + return KRB5_CONFIG_CANTOPEN; + + *name = *inst = '\0'; + switch (princ->length) { + case 2: + /* Check if this principal is listed in the table */ + compo = &princ->data[0]; + p = sconv_list; + while (p->v4_str) { + if (p->len == compo->length + && memcmp(p->v5_str, compo->data, compo->length) == 0) { + /* + * It is, so set the new name now, and chop off + * instance's domain name if requested. + */ + if (strlcpy(name, p->v4_str, ANAME_SZ) >= ANAME_SZ) + return KRB5_INVALID_PRINCIPAL; + if (p->flags & DO_REALM_CONVERSION) { + compo = &princ->data[1]; + c = strnchr(compo->data, '.', compo->length); + if (!c || (c - compo->data) >= INST_SZ - 1) + return KRB5_INVALID_PRINCIPAL; + memcpy(inst, compo->data, (size_t) (c - compo->data)); + inst[c - compo->data] = '\0'; + } + break; + } + p++; + } + /* If inst isn't set, the service isn't listed in the table, */ + /* so just copy it. */ + if (*inst == '\0') { + compo = &princ->data[1]; + if (compo->length >= INST_SZ - 1) + return KRB5_INVALID_PRINCIPAL; + if (compo->length > 0) + memcpy(inst, compo->data, compo->length); + inst[compo->length] = '\0'; + } + /* fall through */ + case 1: + /* name may have been set above; otherwise, just copy it */ + if (*name == '\0') { + compo = &princ->data[0]; + if (compo->length >= ANAME_SZ) + return KRB5_INVALID_PRINCIPAL; + if (compo->length > 0) + memcpy(name, compo->data, compo->length); + name[compo->length] = '\0'; + } + break; + default: + return KRB5_INVALID_PRINCIPAL; + } + + compo = &princ->realm; + + tmp_prealm = malloc(compo->length + 1); + if (tmp_prealm == NULL) + return ENOMEM; + strncpy(tmp_prealm, compo->data, compo->length); + tmp_prealm[compo->length] = '\0'; + + /* Ask for v4_realm corresponding to + krb5 principal realm from krb5.conf realms stanza */ + + retval = profile_get_string(context->profile, KRB5_CONF_REALMS, + tmp_prealm, KRB5_CONF_V4_REALM, 0, + &tmp_realm); + free(tmp_prealm); + if (retval) { + return retval; + } else { + if (tmp_realm == 0) { + if (compo->length > REALM_SZ - 1) + return KRB5_INVALID_PRINCIPAL; + strncpy(realm, compo->data, compo->length); + realm[compo->length] = '\0'; + } else { + tmp_realm_len = strlen(tmp_realm); + if (tmp_realm_len > REALM_SZ - 1) { + profile_release_string(tmp_realm); + return KRB5_INVALID_PRINCIPAL; + } + strncpy(realm, tmp_realm, tmp_realm_len); + realm[tmp_realm_len] = '\0'; + profile_release_string(tmp_realm); + } + } + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_425_conv_principal(krb5_context context, const char *name, + const char *instance, const char *realm, + krb5_principal *princ) +{ + const struct krb_convert *p; + char buf[256]; /* V4 instances are limited to 40 characters */ + krb5_error_code retval; + char *domain, *cp; + char **full_name = 0; + const char *names[5], *names2[2]; + void* iterator = NULL; + char** v4realms = NULL; + char* realm_name = NULL; + char* dummy_value = NULL; + + /* First, convert the realm, since the v4 realm is not necessarily the same as the v5 realm + To do that, iterate over all the realms in the config file, looking for a matching + v4_realm line */ + names2 [0] = KRB5_CONF_REALMS; + names2 [1] = NULL; + retval = profile_iterator_create (context -> profile, names2, PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY, &iterator); + while (retval == 0) { + retval = profile_iterator (&iterator, &realm_name, &dummy_value); + if ((retval == 0) && (realm_name != NULL)) { + names [0] = KRB5_CONF_REALMS; + names [1] = realm_name; + names [2] = KRB5_CONF_V4_REALM; + names [3] = NULL; + + retval = profile_get_values (context -> profile, names, &v4realms); + if ((retval == 0) && (v4realms != NULL) && (v4realms [0] != NULL) && (strcmp (v4realms [0], realm) == 0)) { + realm = realm_name; + break; + } else if (retval == PROF_NO_RELATION) { + /* If it's not found, just keep going */ + retval = 0; + } + } else if ((retval == 0) && (realm_name == NULL)) { + break; + } + if (v4realms != NULL) { + profile_free_list(v4realms); + v4realms = NULL; + } + if (realm_name != NULL) { + profile_release_string (realm_name); + realm_name = NULL; + } + if (dummy_value != NULL) { + profile_release_string (dummy_value); + dummy_value = NULL; + } + } + + if (instance) { + if (instance[0] == '\0') { + instance = 0; + goto not_service; + } + p = sconv_list; + while (1) { + if (!p->v4_str) + goto not_service; + if (!strcmp(p->v4_str, name)) + break; + p++; + } + name = p->v5_str; + if ((p->flags & DO_REALM_CONVERSION) && !strchr(instance, '.')) { + names[0] = KRB5_CONF_REALMS; + names[1] = realm; + names[2] = KRB5_CONF_V4_INSTANCE_CONVERT; + names[3] = instance; + names[4] = 0; + retval = profile_get_values(context->profile, names, &full_name); + if (retval == 0 && full_name && full_name[0]) { + instance = full_name[0]; + } else { + strncpy(buf, instance, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + retval = krb5_get_realm_domain(context, realm, &domain); + if (retval) + goto cleanup; + if (domain) { + for (cp = domain; *cp; cp++) + if (isupper((unsigned char) (*cp))) + *cp = tolower((unsigned char) *cp); + strncat(buf, ".", sizeof(buf) - 1 - strlen(buf)); + strncat(buf, domain, sizeof(buf) - 1 - strlen(buf)); + free(domain); + } + instance = buf; + } + } + } + +not_service: + retval = krb5_build_principal(context, princ, strlen(realm), realm, name, + instance, NULL); +cleanup: + if (iterator) profile_iterator_free (&iterator); + if (full_name) profile_free_list(full_name); + if (v4realms) profile_free_list(v4realms); + if (realm_name) profile_release_string (realm_name); + if (dummy_value) profile_release_string (dummy_value); + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/copy_addrs.c b/krb5-1.21.3/src/lib/krb5/krb/copy_addrs.c new file mode 100644 index 00000000..9c9bc7ba --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/copy_addrs.c @@ -0,0 +1,77 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/copy_addrs.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +krb5_error_code KRB5_CALLCONV +krb5_copy_addr(krb5_context context, const krb5_address *inad, krb5_address **outad) +{ + krb5_address *tmpad; + + if (!(tmpad = (krb5_address *)malloc(sizeof(*tmpad)))) + return ENOMEM; + *tmpad = *inad; + if (!(tmpad->contents = (krb5_octet *)malloc(inad->length))) { + free(tmpad); + return ENOMEM; + } + memcpy(tmpad->contents, inad->contents, inad->length); + *outad = tmpad; + return 0; +} + +/* + * Copy an address array, with fresh allocation. + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_addresses(krb5_context context, krb5_address *const *inaddr, krb5_address ***outaddr) +{ + krb5_error_code retval; + krb5_address ** tempaddr; + unsigned int nelems = 0; + + if (!inaddr) { + *outaddr = 0; + return 0; + } + + while (inaddr[nelems]) nelems++; + + /* one more for a null terminated list */ + if (!(tempaddr = (krb5_address **) calloc(nelems+1, sizeof(*tempaddr)))) + return ENOMEM; + + for (nelems = 0; inaddr[nelems]; nelems++) { + retval = krb5_copy_addr(context, inaddr[nelems], &tempaddr[nelems]); + if (retval) { + krb5_free_addresses(context, tempaddr); + return retval; + } + } + + *outaddr = tempaddr; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/copy_athctr.c b/krb5-1.21.3/src/lib/krb5/krb/copy_athctr.c new file mode 100644 index 00000000..9cc7b4c6 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/copy_athctr.c @@ -0,0 +1,88 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/copy_athctr.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "auth_con.h" + +#ifndef LEAN_CLIENT +krb5_error_code KRB5_CALLCONV +krb5_copy_authenticator(krb5_context context, const krb5_authenticator *authfrom, + krb5_authenticator **authto) +{ + krb5_error_code retval; + krb5_authenticator *tempto; + + if (!(tempto = (krb5_authenticator *)malloc(sizeof(*tempto)))) + return ENOMEM; + *tempto = *authfrom; + + retval = krb5_copy_principal(context, authfrom->client, &tempto->client); + if (retval) { + free(tempto); + return retval; + } + + if (authfrom->checksum && + (retval = krb5_copy_checksum(context, authfrom->checksum, &tempto->checksum))) { + krb5_free_principal(context, tempto->client); + free(tempto); + return retval; + } + + if (authfrom->subkey) { + retval = krb5_copy_keyblock(context, authfrom->subkey, &tempto->subkey); + if (retval) { + krb5_free_checksum(context, tempto->checksum); + krb5_free_principal(context, tempto->client); + free(tempto); + return retval; + } + } + + if (authfrom->authorization_data) { + retval = krb5_copy_authdata(context, authfrom->authorization_data, + &tempto->authorization_data); + if (retval) { + krb5_free_keyblock(context, tempto->subkey); + krb5_free_checksum(context, tempto->checksum); + krb5_free_principal(context, tempto->client); + free(tempto); + return retval; + } + } + + *authto = tempto; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_auth_con_getauthenticator(krb5_context context, krb5_auth_context auth_context, + krb5_authenticator **authenticator) +{ + return (krb5_copy_authenticator(context, auth_context->authentp, + authenticator)); +} +#endif diff --git a/krb5-1.21.3/src/lib/krb5/krb/copy_auth.c b/krb5-1.21.3/src/lib/krb5/krb/copy_auth.c new file mode 100644 index 00000000..ffb7ee9c --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/copy_auth.c @@ -0,0 +1,117 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/copy_auth.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "k5-int.h" +#include "int-proto.h" + +/* + * Copy an authdata array, with fresh allocation. + */ +krb5_error_code KRB5_CALLCONV +krb5_merge_authdata(krb5_context context, + krb5_authdata *const *inauthdat1, + krb5_authdata * const *inauthdat2, + krb5_authdata ***outauthdat) +{ + krb5_error_code retval; + krb5_authdata ** tempauthdat; + unsigned int nelems = 0, nelems2 = 0; + + *outauthdat = NULL; + if (!inauthdat1 && !inauthdat2) { + *outauthdat = 0; + return 0; + } + + if (inauthdat1) + while (inauthdat1[nelems]) nelems++; + if (inauthdat2) + while (inauthdat2[nelems2]) nelems2++; + + /* one more for a null terminated list */ + if (!(tempauthdat = (krb5_authdata **) calloc(nelems+nelems2+1, + sizeof(*tempauthdat)))) + return ENOMEM; + + if (inauthdat1) { + for (nelems = 0; inauthdat1[nelems]; nelems++) { + retval = krb5int_copy_authdatum(context, inauthdat1[nelems], + &tempauthdat[nelems]); + if (retval) { + krb5_free_authdata(context, tempauthdat); + return retval; + } + } + } + + if (inauthdat2) { + for (nelems2 = 0; inauthdat2[nelems2]; nelems2++) { + retval = krb5int_copy_authdatum(context, inauthdat2[nelems2], + &tempauthdat[nelems++]); + if (retval) { + krb5_free_authdata(context, tempauthdat); + return retval; + } + } + } + + *outauthdat = tempauthdat; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_copy_authdata(krb5_context context, + krb5_authdata *const *in_authdat, krb5_authdata ***out) +{ + return krb5_merge_authdata(context, in_authdat, NULL, out); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/copy_cksum.c b/krb5-1.21.3/src/lib/krb5/krb/copy_cksum.c new file mode 100644 index 00000000..90b677b4 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/copy_cksum.c @@ -0,0 +1,46 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/copy_cksum.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +krb5_error_code KRB5_CALLCONV +krb5_copy_checksum(krb5_context context, const krb5_checksum *ckfrom, krb5_checksum **ckto) +{ + krb5_checksum *tempto; + + if (!(tempto = (krb5_checksum *)malloc(sizeof(*tempto)))) + return ENOMEM; + *tempto = *ckfrom; + + if (!(tempto->contents = (krb5_octet *)malloc(tempto->length))) { + free(tempto); + return ENOMEM; + } + memcpy(tempto->contents, ckfrom->contents, ckfrom->length); + + *ckto = tempto; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/copy_creds.c b/krb5-1.21.3/src/lib/krb5/krb/copy_creds.c new file mode 100644 index 00000000..1de56dc4 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/copy_creds.c @@ -0,0 +1,114 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/copy_creds.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" + +/* + * Copy credentials, allocating fresh storage where needed. + */ + +krb5_error_code KRB5_CALLCONV +krb5_copy_creds(krb5_context context, const krb5_creds *incred, krb5_creds **outcred) +{ + krb5_creds *tempcred; + krb5_error_code retval; + + if (!(tempcred = (krb5_creds *)malloc(sizeof(*tempcred)))) + return ENOMEM; + + retval = k5_copy_creds_contents(context, incred, tempcred); + if (retval) + free(tempcred); + else + *outcred = tempcred; + return retval; +} + +/* + * Copy contents of input credentials structure to supplied + * destination, allocating storage for indirect fields as needed. On + * success, the output is a deep copy of the input. On error, the + * output structure is garbage and its contents should be ignored. + */ +krb5_error_code +k5_copy_creds_contents(krb5_context context, const krb5_creds *incred, + krb5_creds *tempcred) +{ + krb5_error_code retval; + krb5_data *scratch; + + *tempcred = *incred; + retval = krb5_copy_principal(context, incred->client, &tempcred->client); + if (retval) + goto cleanlast; + retval = krb5_copy_principal(context, incred->server, &tempcred->server); + if (retval) + goto cleanclient; + retval = krb5_copy_keyblock_contents(context, &incred->keyblock, + &tempcred->keyblock); + if (retval) + goto cleanserver; + retval = krb5_copy_addresses(context, incred->addresses, &tempcred->addresses); + if (retval) + goto cleanblock; + retval = krb5_copy_data(context, &incred->ticket, &scratch); + if (retval) + goto cleanaddrs; + tempcred->ticket = *scratch; + free(scratch); + retval = krb5_copy_data(context, &incred->second_ticket, &scratch); + if (retval) + goto clearticket; + + tempcred->second_ticket = *scratch; + free(scratch); + + retval = krb5_copy_authdata(context, incred->authdata,&tempcred->authdata); + if (retval) + goto clearsecondticket; + + return 0; + +clearsecondticket: + memset(tempcred->second_ticket.data,0,tempcred->second_ticket.length); + free(tempcred->second_ticket.data); +clearticket: + memset(tempcred->ticket.data,0,tempcred->ticket.length); + free(tempcred->ticket.data); +cleanaddrs: + krb5_free_addresses(context, tempcred->addresses); +cleanblock: + free(tempcred->keyblock.contents); +cleanserver: + krb5_free_principal(context, tempcred->server); +cleanclient: + krb5_free_principal(context, tempcred->client); +cleanlast: + /* Do not free tempcred - we did not allocate it - its contents are + garbage - but we should not free it */ + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/copy_ctx.c b/krb5-1.21.3/src/lib/krb5/krb/copy_ctx.c new file mode 100644 index 00000000..121f5d41 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/copy_ctx.c @@ -0,0 +1,123 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/copy_ctx.c */ +/* + * Copyright 1994,1999,2000, 2002, 2003, 2007, 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include + +krb5_error_code KRB5_CALLCONV +krb5_copy_context(krb5_context ctx, krb5_context *nctx_out) +{ + krb5_error_code ret; + krb5_context nctx; + + *nctx_out = NULL; + if (ctx == NULL) + return EINVAL; /* XXX */ + + nctx = malloc(sizeof(*nctx)); + if (nctx == NULL) + return ENOMEM; + + *nctx = *ctx; + + nctx->tgs_etypes = NULL; + nctx->default_realm = NULL; + nctx->profile = NULL; + nctx->dal_handle = NULL; + nctx->prompt_types = NULL; + nctx->preauth_context = NULL; + nctx->ccselect_handles = NULL; + nctx->localauth_handles = NULL; + nctx->hostrealm_handles = NULL; + nctx->tls = NULL; + nctx->kdblog_context = NULL; + nctx->trace_callback = NULL; + nctx->trace_callback_data = NULL; + nctx->err_fmt = NULL; + if (ctx->err_fmt != NULL) + nctx->err_fmt = strdup(ctx->err_fmt); /* It's OK if this fails */ + nctx->plugin_base_dir = NULL; + nctx->os_context.default_ccname = NULL; + + memset(&nctx->libkrb5_plugins, 0, sizeof(nctx->libkrb5_plugins)); + memset(&nctx->err, 0, sizeof(nctx->err)); + memset(&nctx->plugins, 0, sizeof(nctx->plugins)); + + ret = k5_copy_etypes(ctx->tgs_etypes, &nctx->tgs_etypes); + if (ret) + goto errout; + + if (ctx->os_context.default_ccname != NULL) { + nctx->os_context.default_ccname = + strdup(ctx->os_context.default_ccname); + if (nctx->os_context.default_ccname == NULL) { + ret = ENOMEM; + goto errout; + } + } + ret = krb5_get_profile(ctx, &nctx->profile); + if (ret) + goto errout; + nctx->plugin_base_dir = strdup(ctx->plugin_base_dir); + if (nctx->plugin_base_dir == NULL) { + ret = ENOMEM; + goto errout; + } + +errout: + if (ret) { + krb5_free_context(nctx); + } else { + *nctx_out = nctx; + } + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/copy_data.c b/krb5-1.21.3/src/lib/krb5/krb/copy_data.c new file mode 100644 index 00000000..9969e042 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/copy_data.c @@ -0,0 +1,98 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/copy_data.c */ +/* + * Copyright 1990,1991,2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * krb5_copy_data() + */ + +#include "k5-int.h" + +/* + * Copy a data structure, with fresh allocation. + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_data(krb5_context context, const krb5_data *indata, krb5_data **outdata) +{ + krb5_data *tempdata; + krb5_error_code retval; + + if (!indata) { + *outdata = 0; + return 0; + } + + if (!(tempdata = (krb5_data *)malloc(sizeof(*tempdata)))) + return ENOMEM; + + retval = krb5int_copy_data_contents(context, indata, tempdata); + if (retval) { + free(tempdata); + return retval; + } + + *outdata = tempdata; + return 0; +} + +krb5_error_code +krb5int_copy_data_contents(krb5_context context, const krb5_data *indata, krb5_data *outdata) +{ + if (!indata) { + return EINVAL; + } + + outdata->length = indata->length; + if (outdata->length) { + if (!(outdata->data = malloc(outdata->length))) { + return ENOMEM; + } + memcpy(outdata->data, indata->data, outdata->length); + } else + outdata->data = 0; + outdata->magic = KV5M_DATA; + + return 0; +} + +/* As above, but add an (uncounted) extra byte at the end to + null-terminate the data so it can be used as a standard C + string. */ +krb5_error_code +krb5int_copy_data_contents_add0(krb5_context context, const krb5_data *indata, krb5_data *outdata) +{ + if (!indata) + return EINVAL; + outdata->length = indata->length; + if (!(outdata->data = malloc(outdata->length + 1))) + return ENOMEM; + if (outdata->length) + memcpy(outdata->data, indata->data, outdata->length); + outdata->data[outdata->length] = 0; + outdata->magic = KV5M_DATA; + + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/copy_key.c b/krb5-1.21.3/src/lib/krb5/krb/copy_key.c new file mode 100644 index 00000000..26d9b7d5 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/copy_key.c @@ -0,0 +1,35 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/copy_key.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +/* Copy a keyblock, including alloc'ed storage. */ +krb5_error_code KRB5_CALLCONV +krb5_copy_keyblock(krb5_context context, const krb5_keyblock *from, + krb5_keyblock **to) +{ + return krb5int_c_copy_keyblock(context, from, to); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/copy_princ.c b/krb5-1.21.3/src/lib/krb5/krb/copy_princ.c new file mode 100644 index 00000000..81b33812 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/copy_princ.c @@ -0,0 +1,74 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/copy_princ.c */ +/* + * Copyright 1990, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +/* + * Copy a principal structure, with fresh allocation. + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_principal(krb5_context context, krb5_const_principal inprinc, krb5_principal *outprinc) +{ + krb5_principal tempprinc; + krb5_int32 i; + + tempprinc = (krb5_principal)malloc(sizeof(krb5_principal_data)); + + if (tempprinc == 0) + return ENOMEM; + + *tempprinc = *inprinc; + + tempprinc->data = malloc(inprinc->length * sizeof(krb5_data)); + + if (tempprinc->data == 0) { + free(tempprinc); + return ENOMEM; + } + + for (i = 0; i < inprinc->length; i++) { + if (krb5int_copy_data_contents(context, &inprinc->data[i], + &tempprinc->data[i]) != 0) { + while (--i >= 0) + free(tempprinc->data[i].data); + free (tempprinc->data); + free (tempprinc); + return ENOMEM; + } + } + + if (krb5int_copy_data_contents_add0(context, &inprinc->realm, + &tempprinc->realm) != 0) { + for (i = 0; i < inprinc->length; i++) + free(tempprinc->data[i].data); + free(tempprinc->data); + free(tempprinc); + return ENOMEM; + } + + *outprinc = tempprinc; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/copy_tick.c b/krb5-1.21.3/src/lib/krb5/krb/copy_tick.c new file mode 100644 index 00000000..660d977b --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/copy_tick.c @@ -0,0 +1,122 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/copy_tick.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +static krb5_error_code +copy_enc_tkt_part(krb5_context context, const krb5_enc_tkt_part *partfrom, + krb5_enc_tkt_part **partto) +{ + krb5_error_code retval; + krb5_enc_tkt_part *tempto; + + if (!(tempto = (krb5_enc_tkt_part *)malloc(sizeof(*tempto)))) + return ENOMEM; + *tempto = *partfrom; + retval = krb5_copy_keyblock(context, partfrom->session, + &tempto->session); + if (retval) { + free(tempto); + return retval; + } + retval = krb5_copy_principal(context, partfrom->client, &tempto->client); + if (retval) { + krb5_free_keyblock(context, tempto->session); + free(tempto); + return retval; + } + tempto->transited = partfrom->transited; + if (tempto->transited.tr_contents.length == 0) { + tempto->transited.tr_contents.data = 0; + } else { + tempto->transited.tr_contents.data = + k5memdup(partfrom->transited.tr_contents.data, + partfrom->transited.tr_contents.length, &retval); + if (!tempto->transited.tr_contents.data) { + krb5_free_principal(context, tempto->client); + krb5_free_keyblock(context, tempto->session); + free(tempto); + return ENOMEM; + } + } + + retval = krb5_copy_addresses(context, partfrom->caddrs, &tempto->caddrs); + if (retval) { + free(tempto->transited.tr_contents.data); + krb5_free_principal(context, tempto->client); + krb5_free_keyblock(context, tempto->session); + free(tempto); + return retval; + } + if (partfrom->authorization_data) { + retval = krb5_copy_authdata(context, partfrom->authorization_data, + &tempto->authorization_data); + if (retval) { + krb5_free_addresses(context, tempto->caddrs); + free(tempto->transited.tr_contents.data); + krb5_free_principal(context, tempto->client); + krb5_free_keyblock(context, tempto->session); + free(tempto); + return retval; + } + } + *partto = tempto; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_copy_ticket(krb5_context context, const krb5_ticket *from, krb5_ticket **pto) +{ + krb5_error_code retval; + krb5_ticket *tempto; + krb5_data *scratch; + + if (!(tempto = (krb5_ticket *)malloc(sizeof(*tempto)))) + return ENOMEM; + *tempto = *from; + retval = krb5_copy_principal(context, from->server, &tempto->server); + if (retval) { + free(tempto); + return retval; + } + retval = krb5_copy_data(context, &from->enc_part.ciphertext, &scratch); + if (retval) { + krb5_free_principal(context, tempto->server); + free(tempto); + return retval; + } + tempto->enc_part.ciphertext = *scratch; + free(scratch); + retval = copy_enc_tkt_part(context, from->enc_part2, &tempto->enc_part2); + if (retval) { + free(tempto->enc_part.ciphertext.data); + krb5_free_principal(context, tempto->server); + free(tempto); + return retval; + } + *pto = tempto; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/cp_key_cnt.c b/krb5-1.21.3/src/lib/krb5/krb/cp_key_cnt.c new file mode 100644 index 00000000..18cb0f21 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/cp_key_cnt.c @@ -0,0 +1,36 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/cp_key_cnt.c */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +/* + * Copy a keyblock, including alloc'ed storage. + */ +krb5_error_code KRB5_CALLCONV +krb5_copy_keyblock_contents(krb5_context context, const krb5_keyblock *from, krb5_keyblock *to) +{ + return krb5int_c_copy_keyblock_contents(context, from, to); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/decode_kdc.c b/krb5-1.21.3/src/lib/krb5/krb/decode_kdc.c new file mode 100644 index 00000000..a1593a2a --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/decode_kdc.c @@ -0,0 +1,86 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/decode_kdc.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "fast.h" + +/* + Takes a KDC_REP message and decrypts encrypted part using etype and + *key, putting result in *rep. + dec_rep->client,ticket,session,last_req,server,caddrs + are all set to allocated storage which should be freed by the caller + when finished with the response. + + If the response isn't a KDC_REP (tgs or as), it returns an error from + the decoding routines. + + returns errors from encryption routines, system errors +*/ + +krb5_error_code +krb5int_decode_tgs_rep(krb5_context context, + struct krb5int_fast_request_state *fast_state, + krb5_data *enc_rep, const krb5_keyblock *key, + krb5_keyusage usage, krb5_kdc_rep **dec_rep_out) +{ + krb5_error_code retval; + krb5_kdc_rep *dec_rep = NULL; + krb5_keyblock *strengthen_key = NULL, tgs_key; + + tgs_key.contents = NULL; + if (krb5_is_as_rep(enc_rep)) + retval = decode_krb5_as_rep(enc_rep, &dec_rep); + else if (krb5_is_tgs_rep(enc_rep)) + retval = decode_krb5_tgs_rep(enc_rep, &dec_rep); + else + retval = KRB5KRB_AP_ERR_MSG_TYPE; + if (retval) + goto cleanup; + + retval = krb5int_fast_process_response(context, fast_state, dec_rep, + &strengthen_key); + if (retval == KRB5_ERR_FAST_REQUIRED) + retval = 0; + else if (retval) + goto cleanup; + retval = krb5int_fast_reply_key(context, strengthen_key, key, &tgs_key); + if (retval) + goto cleanup; + + retval = krb5_kdc_rep_decrypt_proc(context, &tgs_key, &usage, dec_rep); + if (retval) + goto cleanup; + + *dec_rep_out = dec_rep; + dec_rep = NULL; + +cleanup: + krb5_free_kdc_rep(context, dec_rep); + krb5_free_keyblock(context, strengthen_key); + krb5_free_keyblock_contents(context, &tgs_key); + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/decrypt_tk.c b/krb5-1.21.3/src/lib/krb5/krb/decrypt_tk.c new file mode 100644 index 00000000..e848554e --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/decrypt_tk.c @@ -0,0 +1,71 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/decrypt_tk.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +/* + Decrypts dec_ticket->enc_part + using *srv_key, and places result in dec_ticket->enc_part2. + The storage of dec_ticket->enc_part2 will be allocated before return. + + returns errors from encryption routines, system errors + +*/ + +krb5_error_code KRB5_CALLCONV +krb5_decrypt_tkt_part(krb5_context context, const krb5_keyblock *srv_key, + krb5_ticket *ticket) +{ + krb5_enc_tkt_part *dec_tkt_part; + krb5_data scratch; + krb5_error_code retval; + + if (!krb5_c_valid_enctype(ticket->enc_part.enctype)) + return KRB5_PROG_ETYPE_NOSUPP; + + if (!krb5_is_permitted_enctype(context, ticket->enc_part.enctype)) + return KRB5_NOPERM_ETYPE; + + scratch.length = ticket->enc_part.ciphertext.length; + if (!(scratch.data = malloc(ticket->enc_part.ciphertext.length))) + return(ENOMEM); + + /* call the encryption routine */ + if ((retval = krb5_c_decrypt(context, srv_key, + KRB5_KEYUSAGE_KDC_REP_TICKET, 0, + &ticket->enc_part, &scratch))) { + free(scratch.data); + return retval; + } + + /* now decode the decrypted stuff */ + retval = decode_krb5_enc_tkt_part(&scratch, &dec_tkt_part); + if (!retval) { + ticket->enc_part2 = dec_tkt_part; + } + zapfree(scratch.data, scratch.length); + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/deltat.c b/krb5-1.21.3/src/lib/krb5/krb/deltat.c new file mode 100644 index 00000000..59ba5b19 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/deltat.c @@ -0,0 +1,1697 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + 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 . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "3.0.4" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + + + +/* Copy the first part of user declarations. */ +#line 38 "x-deltat.y" /* yacc.c:339 */ + + +/* + * GCC optimizer will detect a variable used without being set in a YYERROR + * path. As this is generated code, suppress the complaint. + */ +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuninitialized" +#endif + +#include "k5-int.h" +#include + +struct param { + krb5_int32 delta; + char *p; +}; + +#define MAX_TIME KRB5_INT32_MAX +#define MIN_TIME KRB5_INT32_MIN + +#define DAY (24 * 3600) +#define HOUR 3600 + +#define MAX_DAY (MAX_TIME / DAY) +#define MIN_DAY (MIN_TIME / DAY) +#define MAX_HOUR (MAX_TIME / HOUR) +#define MIN_HOUR (MIN_TIME / HOUR) +#define MAX_MIN (MAX_TIME / 60) +#define MIN_MIN (MIN_TIME / 60) + +/* An explanation of the tests being performed. + We do not want to overflow a 32 bit integer with out manipulations, + even for testing for overflow. Therefore we rely on the following: + + The lex parser will not return a number > MAX_TIME (which is out 32 + bit limit). + + Therefore, seconds (s) will require + MIN_TIME < s < MAX_TIME + + For subsequent tests, the logic is as follows: + + If A < MAX_TIME and B < MAX_TIME + + If we want to test if A+B < MAX_TIME, there are two cases + if (A > 0) + then A + B < MAX_TIME if B < MAX_TIME - A + else A + B < MAX_TIME always. + + if we want to test if MIN_TIME < A + B + if A > 0 - then nothing to test + otherwise, we test if MIN_TIME - A < B. + + We of course are testing for: + MIN_TIME < A + B < MAX_TIME +*/ + + +#define DAY_NOT_OK(d) (d) > MAX_DAY || (d) < MIN_DAY +#define HOUR_NOT_OK(h) (h) > MAX_HOUR || (h) < MIN_HOUR +#define MIN_NOT_OK(m) (m) > MAX_MIN || (m) < MIN_MIN +#define SUM_OK(a, b) (((a) > 0) ? ( (b) <= MAX_TIME - (a)) : (MIN_TIME - (a) <= (b))) +#define DO_SUM(res, a, b) if (!SUM_OK((a), (b))) YYERROR; \ + res = (a) + (b) + + +#define OUT_D tmv->delta +#define DO(D,H,M,S) \ + { \ + /* Overflow testing - this does not handle negative values well.. */ \ + if (DAY_NOT_OK(D) || HOUR_NOT_OK(H) || MIN_NOT_OK(M)) YYERROR; \ + OUT_D = D * DAY; \ + DO_SUM(OUT_D, OUT_D, H * HOUR); \ + DO_SUM(OUT_D, OUT_D, M * 60); \ + DO_SUM(OUT_D, OUT_D, S); \ + } + +static int mylex(int *intp, struct param *tmv); +#undef yylex +#define yylex(U, P) mylex (&(U)->val, (P)) + +#undef yyerror +#define yyerror(tmv, msg) + +static int yyparse(struct param *); + + +#line 156 "deltat.c" /* yacc.c:339 */ + +# ifndef YY_NULLPTR +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + + +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + tok_NUM = 258, + tok_LONGNUM = 259, + tok_OVERFLOW = 260, + tok_WS = 261 + }; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED + +union YYSTYPE +{ +#line 128 "x-deltat.y" /* yacc.c:355 */ +int val; + +#line 203 "deltat.c" /* yacc.c:355 */ +}; + +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + + +int yyparse (struct param *tmv); + + + +/* Copy the second part of user declarations. */ + +#line 219 "deltat.c" /* yacc.c:358 */ + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef YY_ATTRIBUTE +# if (defined __GNUC__ \ + && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ + || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C +# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +# else +# define YY_ATTRIBUTE(Spec) /* empty */ +# endif +#endif + +#ifndef YY_ATTRIBUTE_PURE +# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif + +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) +#else +# define YYUSE(E) /* empty */ +#endif + +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 6 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 37 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 13 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 10 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 24 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 42 + +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 261 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 6, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 7, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 8, 2, 2, 2, 9, 2, 2, 2, 2, 10, + 2, 2, 2, 2, 2, 11, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 12 +}; + +#if YYDEBUG + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_uint8 yyrline[] = +{ + 0, 142, 142, 143, 143, 144, 144, 145, 145, 146, + 147, 149, 150, 151, 152, 153, 154, 155, 156, 161, + 162, 165, 166, 169, 170 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || 0 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "tok_NUM", "tok_LONGNUM", "tok_OVERFLOW", + "'-'", "':'", "'d'", "'h'", "'m'", "'s'", "tok_WS", "$accept", "start", + "posnum", "num", "ws", "wsnum", "deltat", "opt_hms", "opt_ms", "opt_s", YY_NULLPTR +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 45, 58, 100, 104, + 109, 115, 261 +}; +# endif + +#define YYPACT_NINF -16 + +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-16))) + +#define YYTABLE_NINF -1 + +#define yytable_value_is_error(Yytable_value) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = +{ + -10, -16, 14, 7, -2, -16, -16, -16, -16, -16, + 21, -16, -16, 13, 25, -10, -10, -10, -16, -16, + 22, 23, 7, 12, -16, -16, -16, 16, -16, 8, + -16, 28, 29, -10, -10, -16, 26, -16, -16, -16, + 32, -16 +}; + + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 7, 8, 0, 0, 18, 2, 1, 3, 4, 10, + 0, 5, 9, 0, 0, 7, 7, 7, 14, 6, + 0, 17, 23, 0, 11, 19, 21, 0, 12, 0, + 13, 0, 0, 7, 7, 24, 0, 16, 20, 22, + 0, 15 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -16, -16, 27, -16, 36, 0, -16, -16, -15, -14 +}; + + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 2, 11, 12, 22, 27, 5, 24, 25, 26 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_uint8 yytable[] = +{ + 4, 28, 1, 30, 13, 14, 15, 16, 17, 18, + 7, 8, 9, 10, 6, 23, 20, 29, 38, 35, + 39, 33, 34, 35, 7, 8, 34, 35, 21, 31, + 32, 36, 37, 40, 29, 41, 3, 19 +}; + +static const yytype_uint8 yycheck[] = +{ + 0, 16, 12, 17, 6, 7, 8, 9, 10, 11, + 3, 4, 5, 6, 0, 15, 3, 17, 33, 11, + 34, 9, 10, 11, 3, 4, 10, 11, 3, 7, + 7, 3, 3, 7, 34, 3, 0, 10 +}; + + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 12, 14, 17, 18, 19, 0, 3, 4, 5, + 6, 15, 16, 6, 7, 8, 9, 10, 11, 15, + 3, 3, 17, 18, 20, 21, 22, 18, 21, 18, + 22, 7, 7, 9, 10, 11, 3, 3, 21, 22, + 7, 3 +}; + + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 13, 14, 15, 15, 16, 16, 17, 17, 18, + 18, 19, 19, 19, 19, 19, 19, 19, 19, 20, + 20, 21, 21, 22, 22 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 1, 1, 1, 2, 0, 1, 2, + 2, 3, 3, 3, 2, 7, 5, 3, 1, 1, + 3, 1, 3, 1, 2 +}; + + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (tmv, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (0) + +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 + + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, tmv); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct param *tmv) +{ + FILE *yyo = yyoutput; + YYUSE (yyo); + YYUSE (tmv); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + YYUSE (yytype); +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct param *tmv) +{ + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep, tmv); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule, struct param *tmv) +{ + unsigned long int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , tmv); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule, tmv); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +yystrlen (const char *yystr) +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +yystpcpy (char *yydest, const char *yysrc) +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULLPTR; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, struct param *tmv) +{ + YYUSE (yyvaluep); + YYUSE (tmv); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (struct param *tmv) +{ +/* The lookahead symbol. */ +int yychar; + + +/* The semantic value of the lookahead symbol. */ +/* Default value used for initialization, for pacifying older GCCs + or non-GCC compilers. */ +YY_INITIAL_VALUE (static YYSTYPE yyval_default;) +YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); + + /* Number of syntax errors so far. */ + int yynerrs; + + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = yylex (&yylval, tmv); + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 6: +#line 144 "x-deltat.y" /* yacc.c:1646 */ + { (yyval.val) = - (yyvsp[0].val); } +#line 1317 "deltat.c" /* yacc.c:1646 */ + break; + + case 9: +#line 146 "x-deltat.y" /* yacc.c:1646 */ + { (yyval.val) = (yyvsp[0].val); } +#line 1323 "deltat.c" /* yacc.c:1646 */ + break; + + case 10: +#line 147 "x-deltat.y" /* yacc.c:1646 */ + { YYERROR; } +#line 1329 "deltat.c" /* yacc.c:1646 */ + break; + + case 11: +#line 149 "x-deltat.y" /* yacc.c:1646 */ + { DO ((yyvsp[-2].val), 0, 0, (yyvsp[0].val)); } +#line 1335 "deltat.c" /* yacc.c:1646 */ + break; + + case 12: +#line 150 "x-deltat.y" /* yacc.c:1646 */ + { DO ( 0, (yyvsp[-2].val), 0, (yyvsp[0].val)); } +#line 1341 "deltat.c" /* yacc.c:1646 */ + break; + + case 13: +#line 151 "x-deltat.y" /* yacc.c:1646 */ + { DO ( 0, 0, (yyvsp[-2].val), (yyvsp[0].val)); } +#line 1347 "deltat.c" /* yacc.c:1646 */ + break; + + case 14: +#line 152 "x-deltat.y" /* yacc.c:1646 */ + { DO ( 0, 0, 0, (yyvsp[-1].val)); } +#line 1353 "deltat.c" /* yacc.c:1646 */ + break; + + case 15: +#line 153 "x-deltat.y" /* yacc.c:1646 */ + { DO ((yyvsp[-6].val), (yyvsp[-4].val), (yyvsp[-2].val), (yyvsp[0].val)); } +#line 1359 "deltat.c" /* yacc.c:1646 */ + break; + + case 16: +#line 154 "x-deltat.y" /* yacc.c:1646 */ + { DO ( 0, (yyvsp[-4].val), (yyvsp[-2].val), (yyvsp[0].val)); } +#line 1365 "deltat.c" /* yacc.c:1646 */ + break; + + case 17: +#line 155 "x-deltat.y" /* yacc.c:1646 */ + { DO ( 0, (yyvsp[-2].val), (yyvsp[0].val), 0); } +#line 1371 "deltat.c" /* yacc.c:1646 */ + break; + + case 18: +#line 156 "x-deltat.y" /* yacc.c:1646 */ + { DO ( 0, 0, 0, (yyvsp[0].val)); } +#line 1377 "deltat.c" /* yacc.c:1646 */ + break; + + case 20: +#line 162 "x-deltat.y" /* yacc.c:1646 */ + { if (HOUR_NOT_OK((yyvsp[-2].val))) YYERROR; + DO_SUM((yyval.val), (yyvsp[-2].val) * 3600, (yyvsp[0].val)); } +#line 1384 "deltat.c" /* yacc.c:1646 */ + break; + + case 22: +#line 166 "x-deltat.y" /* yacc.c:1646 */ + { if (MIN_NOT_OK((yyvsp[-2].val))) YYERROR; + DO_SUM((yyval.val), (yyvsp[-2].val) * 60, (yyvsp[0].val)); } +#line 1391 "deltat.c" /* yacc.c:1646 */ + break; + + case 23: +#line 169 "x-deltat.y" /* yacc.c:1646 */ + { (yyval.val) = 0; } +#line 1397 "deltat.c" /* yacc.c:1646 */ + break; + + +#line 1401 "deltat.c" /* yacc.c:1646 */ + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (tmv, YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (tmv, yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval, tmv); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp, tmv); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined yyoverflow || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (tmv, YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, tmv); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp, tmv); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + return yyresult; +} +#line 172 "x-deltat.y" /* yacc.c:1906 */ + + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +static int +mylex(int *intp, struct param *tmv) +{ + int num, c; +#define P (tmv->p) + char *orig_p = P; + +#ifdef isascii + if (!isascii (*P)) + return 0; +#endif + switch (c = *P++) { + case '-': + case ':': + case 'd': + case 'h': + case 'm': + case 's': + return c; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + /* XXX assumes ASCII */ + num = c - '0'; + while (isdigit ((int) *P)) { + if (num > MAX_TIME / 10) + return tok_OVERFLOW; + num *= 10; + if (num > MAX_TIME - (*P - '0')) + return tok_OVERFLOW; + num += *P++ - '0'; + } + *intp = num; + return (P - orig_p > 2) ? tok_LONGNUM : tok_NUM; + case ' ': + case '\t': + case '\n': + while (isspace ((int) *P)) + P++; + return tok_WS; + default: + return YYEOF; + } +} + +krb5_error_code KRB5_CALLCONV +krb5_string_to_deltat(char *string, krb5_deltat *deltatp) +{ + struct param p; + p.delta = 0; + p.p = string; + if (yyparse (&p)) + return KRB5_DELTAT_BADFORMAT; + *deltatp = p.delta; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/deps b/krb5-1.21.3/src/lib/krb5/krb/deps new file mode 100644 index 00000000..6ea570c5 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/deps @@ -0,0 +1,1452 @@ +# +# Generated makefile dependencies follow. +# +addr_comp.so addr_comp.po $(OUTPRE)addr_comp.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + addr_comp.c +addr_order.so addr_order.po $(OUTPRE)addr_order.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + addr_order.c +addr_srch.so addr_srch.po $(OUTPRE)addr_srch.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + addr_srch.c +appdefault.so appdefault.po $(OUTPRE)appdefault.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + appdefault.c +auth_con.so auth_con.po $(OUTPRE)auth_con.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth_con.c auth_con.h \ + int-proto.h +cammac_util.so cammac_util.po $(OUTPRE)cammac_util.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cammac_util.c +ai_authdata.so ai_authdata.po $(OUTPRE)ai_authdata.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/k5-utf8.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ai_authdata.c auth_con.h authdata.h int-proto.h +authdata.so authdata.po $(OUTPRE)authdata.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/k5-utf8.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h authdata.c authdata.h int-proto.h +authdata_exp.so authdata_exp.po $(OUTPRE)authdata_exp.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/k5-utf8.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h authdata.h authdata_exp.c int-proto.h +authdata_enc.so authdata_enc.po $(OUTPRE)authdata_enc.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + authdata_enc.c +authdata_dec.so authdata_dec.po $(OUTPRE)authdata_dec.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + authdata_dec.c int-proto.h +bld_pr_ext.so bld_pr_ext.po $(OUTPRE)bld_pr_ext.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + bld_pr_ext.c int-proto.h +bld_princ.so bld_princ.po $(OUTPRE)bld_princ.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + bld_princ.c int-proto.h +brand.so brand.po $(OUTPRE)brand.$(OBJEXT): $(top_srcdir)/patchlevel.h \ + brand.c +chk_trans.so chk_trans.po $(OUTPRE)chk_trans.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + chk_trans.c +chpw.so chpw.po $(OUTPRE)chpw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-unicode.h \ + $(top_srcdir)/include/k5-utf8.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h chpw.c int-proto.h +conv_creds.so conv_creds.po $(OUTPRE)conv_creds.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + conv_creds.c +conv_princ.so conv_princ.po $(OUTPRE)conv_princ.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + conv_princ.c +copy_addrs.so copy_addrs.po $(OUTPRE)copy_addrs.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + copy_addrs.c +copy_auth.so copy_auth.po $(OUTPRE)copy_auth.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + copy_auth.c int-proto.h +copy_athctr.so copy_athctr.po $(OUTPRE)copy_athctr.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth_con.h copy_athctr.c +copy_cksum.so copy_cksum.po $(OUTPRE)copy_cksum.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + copy_cksum.c +copy_creds.so copy_creds.po $(OUTPRE)copy_creds.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + copy_creds.c int-proto.h +copy_data.so copy_data.po $(OUTPRE)copy_data.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + copy_data.c +copy_key.so copy_key.po $(OUTPRE)copy_key.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + copy_key.c +copy_princ.so copy_princ.po $(OUTPRE)copy_princ.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + copy_princ.c +copy_tick.so copy_tick.po $(OUTPRE)copy_tick.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + copy_tick.c +cp_key_cnt.so cp_key_cnt.po $(OUTPRE)cp_key_cnt.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cp_key_cnt.c +decode_kdc.so decode_kdc.po $(OUTPRE)decode_kdc.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + decode_kdc.c fast.h int-proto.h +decrypt_tk.so decrypt_tk.po $(OUTPRE)decrypt_tk.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + decrypt_tk.c +deltat.so deltat.po $(OUTPRE)deltat.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h deltat.c +enc_helper.so enc_helper.po $(OUTPRE)enc_helper.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + enc_helper.c +enc_keyhelper.so enc_keyhelper.po $(OUTPRE)enc_keyhelper.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + enc_keyhelper.c int-proto.h +encode_kdc.so encode_kdc.po $(OUTPRE)encode_kdc.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + encode_kdc.c +encrypt_tk.so encrypt_tk.po $(OUTPRE)encrypt_tk.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + encrypt_tk.c +etype_list.so etype_list.po $(OUTPRE)etype_list.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + etype_list.c int-proto.h +fast.so fast.po $(OUTPRE)fast.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h fast.c fast.h \ + int-proto.h +fwd_tgt.so fwd_tgt.po $(OUTPRE)fwd_tgt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h fwd_tgt.c int-proto.h +gc_via_tkt.so gc_via_tkt.po $(OUTPRE)gc_via_tkt.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + fast.h gc_via_tkt.c int-proto.h +gen_seqnum.so gen_seqnum.po $(OUTPRE)gen_seqnum.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + gen_seqnum.c +gen_subkey.so gen_subkey.po $(OUTPRE)gen_subkey.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + gen_subkey.c +gen_save_subkey.so gen_save_subkey.po $(OUTPRE)gen_save_subkey.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth_con.h gen_save_subkey.c \ + int-proto.h +get_creds.so get_creds.po $(OUTPRE)get_creds.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + fast.h get_creds.c int-proto.h +get_etype_info.so get_etype_info.po $(OUTPRE)get_etype_info.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-json.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h fast.h get_etype_info.c \ + init_creds_ctx.h int-proto.h +get_in_tkt.so get_in_tkt.po $(OUTPRE)get_in_tkt.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-json.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h fast.h get_in_tkt.c \ + init_creds_ctx.h int-proto.h +gic_keytab.so gic_keytab.po $(OUTPRE)gic_keytab.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-json.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h gic_keytab.c init_creds_ctx.h \ + int-proto.h +gic_opt.so gic_opt.po $(OUTPRE)gic_opt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/clpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + gic_opt.c int-proto.h +gic_pwd.so gic_pwd.po $(OUTPRE)gic_pwd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-json.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + gic_pwd.c init_creds_ctx.h int-proto.h +in_tkt_sky.so in_tkt_sky.po $(OUTPRE)in_tkt_sky.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + in_tkt_sky.c int-proto.h +init_ctx.so init_ctx.po $(OUTPRE)init_ctx.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../krb5_libinit.h $(srcdir)/../os/os-proto.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h $(top_srcdir)/patchlevel.h \ + brand.c init_ctx.c int-proto.h +copy_ctx.so copy_ctx.po $(OUTPRE)copy_ctx.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + copy_ctx.c int-proto.h +init_keyblock.so init_keyblock.po $(OUTPRE)init_keyblock.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + init_keyblock.c +kdc_rep_dc.so kdc_rep_dc.po $(OUTPRE)kdc_rep_dc.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kdc_rep_dc.c +kerrs.so kerrs.po $(OUTPRE)kerrs.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h int-proto.h kerrs.c +kfree.so kfree.po $(OUTPRE)kfree.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-spake.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kfree.c +libdef_parse.so libdef_parse.po $(OUTPRE)libdef_parse.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h libdef_parse.c +mk_cred.so mk_cred.po $(OUTPRE)mk_cred.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h int-proto.h mk_cred.c +mk_error.so mk_error.po $(OUTPRE)mk_error.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + mk_error.c +mk_priv.so mk_priv.po $(OUTPRE)mk_priv.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h int-proto.h mk_priv.c +mk_rep.so mk_rep.po $(OUTPRE)mk_rep.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h int-proto.h mk_rep.c +mk_req.so mk_req.po $(OUTPRE)mk_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h mk_req.c +mk_req_ext.so mk_req_ext.po $(OUTPRE)mk_req_ext.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth_con.h int-proto.h \ + mk_req_ext.c +mk_safe.so mk_safe.po $(OUTPRE)mk_safe.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h int-proto.h mk_safe.c +pac.so pac.po $(OUTPRE)pac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-input.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h authdata.h int-proto.h \ + pac.c +pac_sign.so pac_sign.po $(OUTPRE)pac_sign.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h authdata.h int-proto.h \ + pac_sign.c +padata.so padata.po $(OUTPRE)padata.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h padata.c +parse.so parse.po $(OUTPRE)parse.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h int-proto.h parse.c +parse_host_string.so parse_host_string.po $(OUTPRE)parse_host_string.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + parse_host_string.c +plugin.so plugin.po $(OUTPRE)plugin.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h plugin.c +pr_to_salt.so pr_to_salt.po $(OUTPRE)pr_to_salt.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + pr_to_salt.c +preauth2.so preauth2.po $(OUTPRE)preauth2.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-json.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/clpreauth_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + fast.h init_creds_ctx.h int-proto.h preauth2.c +preauth_ec.so preauth_ec.po $(OUTPRE)preauth_ec.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/clpreauth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h int-proto.h preauth_ec.c +preauth_encts.so preauth_encts.po $(OUTPRE)preauth_encts.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-json.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/clpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + init_creds_ctx.h int-proto.h preauth_encts.c +preauth_otp.so preauth_otp.po $(OUTPRE)preauth_otp.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-json.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/clpreauth_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h preauth_otp.c +preauth_pkinit.so preauth_pkinit.po $(OUTPRE)preauth_pkinit.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-json.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h init_creds_ctx.h \ + int-proto.h preauth_pkinit.c +preauth_sam2.so preauth_sam2.po $(OUTPRE)preauth_sam2.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-json.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/clpreauth_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + init_creds_ctx.h int-proto.h preauth_sam2.c +princ_comp.so princ_comp.po $(OUTPRE)princ_comp.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-unicode.h \ + $(top_srcdir)/include/k5-utf8.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + princ_comp.c +privsafe.so privsafe.po $(OUTPRE)privsafe.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth_con.h int-proto.h \ + privsafe.c +random_str.so random_str.po $(OUTPRE)random_str.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + random_str.c +rd_cred.so rd_cred.po $(OUTPRE)rd_cred.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h int-proto.h rd_cred.c +rd_error.so rd_error.po $(OUTPRE)rd_error.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + rd_error.c +rd_priv.so rd_priv.po $(OUTPRE)rd_priv.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h int-proto.h rd_priv.c +rd_rep.so rd_rep.po $(OUTPRE)rd_rep.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h rd_rep.c +rd_req.so rd_req.po $(OUTPRE)rd_req.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h rd_req.c +rd_req_dec.so rd_req_dec.po $(OUTPRE)rd_req_dec.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h authdata.h int-proto.h rd_req_dec.c +rd_safe.so rd_safe.po $(OUTPRE)rd_safe.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h int-proto.h rd_safe.c +recvauth.so recvauth.po $(OUTPRE)recvauth.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth_con.h recvauth.c +response_items.so response_items.po $(OUTPRE)response_items.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h response_items.c +s4u_creds.so s4u_creds.po $(OUTPRE)s4u_creds.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h s4u_creds.c +sendauth.so sendauth.po $(OUTPRE)sendauth.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/locate_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth_con.h sendauth.c +send_tgs.so send_tgs.po $(OUTPRE)send_tgs.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + fast.h int-proto.h send_tgs.c +ser_actx.so ser_actx.po $(OUTPRE)ser_actx.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h auth_con.h int-proto.h \ + ser_actx.c +ser_adata.so ser_adata.po $(OUTPRE)ser_adata.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h ser_adata.c +ser_addr.so ser_addr.po $(OUTPRE)ser_addr.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h ser_addr.c +ser_auth.so ser_auth.po $(OUTPRE)ser_auth.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h ser_auth.c +ser_cksum.so ser_cksum.po $(OUTPRE)ser_cksum.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h ser_cksum.c +ser_ctx.so ser_ctx.po $(OUTPRE)ser_ctx.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h int-proto.h ser_ctx.c +ser_key.so ser_key.po $(OUTPRE)ser_key.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h int-proto.h ser_key.c +ser_princ.so ser_princ.po $(OUTPRE)ser_princ.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h ser_princ.c +serialize.so serialize.po $(OUTPRE)serialize.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + serialize.c +set_realm.so set_realm.po $(OUTPRE)set_realm.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + set_realm.c +sname_match.so sname_match.po $(OUTPRE)sname_match.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h sname_match.c +srv_dec_tkt.so srv_dec_tkt.po $(OUTPRE)srv_dec_tkt.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + srv_dec_tkt.c +srv_rcache.so srv_rcache.po $(OUTPRE)srv_rcache.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + srv_rcache.c +str_conv.so str_conv.po $(OUTPRE)str_conv.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h str_conv.c +t_ad_fx_armor.so t_ad_fx_armor.po $(OUTPRE)t_ad_fx_armor.$(OBJEXT): \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) t_ad_fx_armor.c +tgtname.so tgtname.po $(OUTPRE)tgtname.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h int-proto.h tgtname.c +unparse.so unparse.po $(OUTPRE)unparse.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h unparse.c +val_renew.so val_renew.po $(OUTPRE)val_renew.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h val_renew.c +valid_times.so valid_times.po $(OUTPRE)valid_times.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h valid_times.c +vfy_increds.so vfy_increds.po $(OUTPRE)vfy_increds.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h vfy_increds.c +vic_opt.so vic_opt.po $(OUTPRE)vic_opt.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h vic_opt.c +walk_rtree.so walk_rtree.po $(OUTPRE)walk_rtree.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h walk_rtree.c +t_walk_rtree.so t_walk_rtree.po $(OUTPRE)t_walk_rtree.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_walk_rtree.c +t_kerb.so t_kerb.po $(OUTPRE)t_kerb.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_kerb.c +t_ser.so t_ser.po $(OUTPRE)t_ser.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../rcache/memrcache.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + auth_con.h t_ser.c +t_deltat.so t_deltat.po $(OUTPRE)t_deltat.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_deltat.c +t_expand.so t_expand.po $(OUTPRE)t_expand.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + chk_trans.c t_expand.c +t_get_etype_info.so t_get_etype_info.po $(OUTPRE)t_get_etype_info.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-hex.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ + t_get_etype_info.c +t_pac.so t_pac.po $(OUTPRE)t_pac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_pac.c +t_parse_host_string.so t_parse_host_string.po $(OUTPRE)t_parse_host_string.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-cmocka.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_parse_host_string.c +t_princ.so t_princ.po $(OUTPRE)t_princ.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_princ.c +t_etypes.so t_etypes.po $(OUTPRE)t_etypes.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_etypes.c +t_expire_warn.so t_expire_warn.po $(OUTPRE)t_expire_warn.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_expire_warn.c +t_authdata.so t_authdata.po $(OUTPRE)t_authdata.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_authdata.c +t_cc_config.so t_cc_config.po $(OUTPRE)t_cc_config.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h t_cc_config.c +t_copy_context.so t_copy_context.po $(OUTPRE)t_copy_context.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_copy_context.c +t_in_ccache.so t_in_ccache.po $(OUTPRE)t_in_ccache.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_in_ccache.c +t_response_items.so t_response_items.po $(OUTPRE)t_response_items.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h t_response_items.c +t_sname_match.so t_sname_match.po $(OUTPRE)t_sname_match.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_sname_match.c +t_valid_times.so t_valid_times.po $(OUTPRE)t_valid_times.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + int-proto.h t_valid_times.c +t_vfy_increds.so t_vfy_increds.po $(OUTPRE)t_vfy_increds.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + t_vfy_increds.c diff --git a/krb5-1.21.3/src/lib/krb5/krb/enc_helper.c b/krb5-1.21.3/src/lib/krb5/krb/enc_helper.c new file mode 100644 index 00000000..b9bf94c2 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/enc_helper.c @@ -0,0 +1,53 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/enc_helper.c */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" + +krb5_error_code +krb5_encrypt_helper(krb5_context context, + const krb5_keyblock *key, krb5_keyusage usage, + const krb5_data *plain, krb5_enc_data *cipher) +{ + krb5_error_code ret; + size_t enclen; + + if ((ret = krb5_c_encrypt_length(context, key->enctype, plain->length, + &enclen))) + return(ret); + + cipher->ciphertext.length = enclen; + if ((cipher->ciphertext.data = (char *) malloc(enclen)) == NULL) + return(ENOMEM); + ret = krb5_c_encrypt(context, key, usage, 0, plain, cipher); + if (ret) { + free(cipher->ciphertext.data); + cipher->ciphertext.data = NULL; + } + + return(ret); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/enc_keyhelper.c b/krb5-1.21.3/src/lib/krb5/krb/enc_keyhelper.c new file mode 100644 index 00000000..6878b252 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/enc_keyhelper.c @@ -0,0 +1,56 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/enc_keyhelper.c */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" +#include "int-proto.h" + +krb5_error_code +k5_encrypt_keyhelper(krb5_context context, krb5_key key, krb5_keyusage usage, + const krb5_data *plain, krb5_enc_data *cipher) +{ + krb5_enctype enctype; + krb5_error_code ret; + size_t enclen; + + enctype = krb5_k_key_enctype(context, key); + ret = krb5_c_encrypt_length(context, enctype, plain->length, &enclen); + if (ret != 0) + return ret; + + cipher->ciphertext.length = enclen; + cipher->ciphertext.data = malloc(enclen); + if (cipher->ciphertext.data == NULL) + return ENOMEM; + ret = krb5_k_encrypt(context, key, usage, 0, plain, cipher); + if (ret) { + free(cipher->ciphertext.data); + cipher->ciphertext.data = NULL; + } + + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/encode_kdc.c b/krb5-1.21.3/src/lib/krb5/krb/encode_kdc.c new file mode 100644 index 00000000..e4907da1 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/encode_kdc.c @@ -0,0 +1,125 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/encode_kdc.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +/* + Takes KDC rep parts in *rep and *encpart, and formats it into *enc_rep, + using message type type and encryption key client_key and encryption type + etype. + + The string *enc_rep will be allocated before formatting; the caller should + free when finished. + + returns system errors + + dec_rep->enc_part.ciphertext is allocated and filled in. +*/ +/* due to argument promotion rules, we need to use the DECLARG/OLDDECLARG + stuff... */ +krb5_error_code +krb5_encode_kdc_rep(krb5_context context, krb5_msgtype type, + const krb5_enc_kdc_rep_part *encpart, + int using_subkey, const krb5_keyblock *client_key, + krb5_kdc_rep *dec_rep, krb5_data **enc_rep) +{ + krb5_data *scratch; + krb5_error_code retval; + krb5_enc_kdc_rep_part tmp_encpart; + krb5_keyusage usage; + + if (!krb5_c_valid_enctype(dec_rep->enc_part.enctype)) + return KRB5_PROG_ETYPE_NOSUPP; + + switch (type) { + case KRB5_AS_REP: + usage = KRB5_KEYUSAGE_AS_REP_ENCPART; + break; + case KRB5_TGS_REP: + if (using_subkey) + usage = KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY; + else + usage = KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY; + break; + default: + return KRB5_BADMSGTYPE; + } + + /* + * We don't want to modify encpart, but we need to be able to pass + * in the message type to the encoder, so it can set the ASN.1 + * type correct. + * + * Although note that it may be doing nothing with the message + * type, to be compatible with old versions of Kerberos that always + * encode this as a TGS_REP regardly of what it really should be; + * also note that the reason why we are passing it in a structure + * instead of as an argument to encode_krb5_enc_kdc_rep_part (the + * way we should) is for compatibility with the ISODE version of + * this function. Ah, compatibility.... + */ + tmp_encpart = *encpart; + tmp_encpart.msg_type = type; + retval = encode_krb5_enc_kdc_rep_part(&tmp_encpart, &scratch); + if (retval) { + return retval; + } + memset(&tmp_encpart, 0, sizeof(tmp_encpart)); + +#define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \ + krb5_free_data(context, scratch); } + + retval = krb5_encrypt_helper(context, client_key, usage, scratch, + &dec_rep->enc_part); + +#define cleanup_encpart() { \ + (void) memset(dec_rep->enc_part.ciphertext.data, 0, \ + dec_rep->enc_part.ciphertext.length); \ + free(dec_rep->enc_part.ciphertext.data); \ + dec_rep->enc_part.ciphertext.length = 0; \ + dec_rep->enc_part.ciphertext.data = 0;} + + cleanup_scratch(); + + if (retval) + return(retval); + + /* now it's ready to be encoded for the wire! */ + + switch (type) { + case KRB5_AS_REP: + retval = encode_krb5_as_rep(dec_rep, enc_rep); + break; + case KRB5_TGS_REP: + retval = encode_krb5_tgs_rep(dec_rep, enc_rep); + break; + } + + if (retval) + cleanup_encpart(); + + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/encrypt_tk.c b/krb5-1.21.3/src/lib/krb5/krb/encrypt_tk.c new file mode 100644 index 00000000..13a774f0 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/encrypt_tk.c @@ -0,0 +1,65 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/encrypt_tk.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +/* + Takes unencrypted dec_ticket & dec_tkt_part, encrypts with + dec_ticket->enc_part.etype + using *srv_key, and places result in dec_ticket->enc_part. + The string dec_ticket->enc_part.ciphertext will be allocated before + formatting. + + returns errors from encryption routines, system errors + + enc_part->ciphertext.data allocated & filled in with encrypted stuff +*/ + +krb5_error_code +krb5_encrypt_tkt_part(krb5_context context, const krb5_keyblock *srv_key, + krb5_ticket *dec_ticket) +{ + krb5_data *scratch; + krb5_error_code retval; + krb5_enc_tkt_part *dec_tkt_part = dec_ticket->enc_part2; + + /* start by encoding the to-be-encrypted part. */ + if ((retval = encode_krb5_enc_tkt_part(dec_tkt_part, &scratch))) { + return retval; + } + +#define cleanup_scratch() { (void) memset(scratch->data, 0, scratch->length); \ + krb5_free_data(context, scratch); } + + /* call the encryption routine */ + retval = krb5_encrypt_helper(context, srv_key, + KRB5_KEYUSAGE_KDC_REP_TICKET, scratch, + &dec_ticket->enc_part); + + cleanup_scratch(); + + return(retval); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/etype_list.c b/krb5-1.21.3/src/lib/krb5/krb/etype_list.c new file mode 100644 index 00000000..71f664f0 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/etype_list.c @@ -0,0 +1,70 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/etype_list.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * Helper functions related to zero-terminated lists of enctypes. + */ + +#include "k5-int.h" +#include "int-proto.h" + +size_t +k5_count_etypes(const krb5_enctype *list) +{ + size_t count; + + for (count = 0; list[count]; count++); + return count; +} + +/* Copy the zero-terminated enctype list old_list into *new_list. */ +krb5_error_code +k5_copy_etypes(const krb5_enctype *old_list, krb5_enctype **new_list) +{ + size_t count; + krb5_enctype *list; + + *new_list = NULL; + if (old_list == NULL) + return 0; + count = k5_count_etypes(old_list); + list = malloc(sizeof(krb5_enctype) * (count + 1)); + if (list == NULL) + return ENOMEM; + memcpy(list, old_list, sizeof(krb5_enctype) * (count + 1)); + *new_list = list; + return 0; +} + +krb5_boolean +k5_etypes_contains(const krb5_enctype *list, krb5_enctype etype) +{ + size_t i; + + for (i = 0; list[i] && list[i] != etype; i++); + return (list[i] == etype); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/fast.c b/krb5-1.21.3/src/lib/krb5/krb/fast.c new file mode 100644 index 00000000..62c9f084 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/fast.c @@ -0,0 +1,689 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/fast.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include "int-proto.h" + +/* + * It is possible to support sending a request that includes both a FAST and + * normal version. This would complicate the pre-authentication logic + * significantly. You would need to maintain two contexts, one for FAST and + * one for normal use. In adition, you would need to manage the security + * issues surrounding downgrades. However trying FAST at all requires an armor + * key. Generally in obtaining the armor key, the client learns enough to know + * that FAST is supported. If not, the client can see FAST in the + * preauth_required error's padata and retry with FAST. So, this + * implementation does not support FAST+normal. + * + * We store the outer version of the request to use. The caller stores the + * inner version. We handle the encoding of the request body (and request) and + * provide encoded request bodies for the caller to use as these may be used + * for checksums. In the AS case we also evaluate whether to continue a + * conversation as one of the important questions there is the presence of a + * cookie. + */ +#include "fast.h" +#include "int-proto.h" + +static krb5_error_code +fast_armor_ap_request(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_ccache ccache, krb5_principal target_principal) +{ + krb5_error_code retval = 0; + krb5_creds creds, *out_creds = NULL; + krb5_auth_context authcontext = NULL; + krb5_data encoded_authenticator; + krb5_fast_armor *armor = NULL; + krb5_keyblock *subkey = NULL, *armor_key = NULL; + + encoded_authenticator.data = NULL; + memset(&creds, 0, sizeof(creds)); + creds.server = target_principal; + retval = krb5_cc_get_principal(context, ccache, &creds.client); + if (retval == 0) + retval = krb5_get_credentials(context, 0, ccache, &creds, &out_creds); + if (retval == 0) { + TRACE_FAST_ARMOR_CCACHE_KEY(context, &out_creds->keyblock); + retval = krb5_mk_req_extended(context, &authcontext, + AP_OPTS_USE_SUBKEY, NULL /*data*/, + out_creds, &encoded_authenticator); + } + if (retval == 0) + retval = krb5_auth_con_getsendsubkey(context, authcontext, &subkey); + if (retval == 0) + retval = krb5_c_fx_cf2_simple(context, subkey, "subkeyarmor", + &out_creds->keyblock, "ticketarmor", + &armor_key); + if (retval == 0) { + TRACE_FAST_ARMOR_KEY(context, armor_key); + armor = calloc(1, sizeof(krb5_fast_armor)); + if (armor == NULL) + retval = ENOMEM; + } + if (retval == 0) { + armor->armor_type = KRB5_FAST_ARMOR_AP_REQUEST; + armor->armor_value = encoded_authenticator; + encoded_authenticator.data = NULL; + encoded_authenticator.length = 0; + state->armor = armor; + armor = NULL; + state->armor_key = armor_key; + armor_key = NULL; + } + krb5_free_keyblock(context, armor_key); + krb5_free_keyblock(context, subkey); + if (out_creds) + krb5_free_creds(context, out_creds); + /* target_principal is owned by caller. */ + creds.server = NULL; + krb5_free_cred_contents(context, &creds); + if (encoded_authenticator.data) + krb5_free_data_contents(context, &encoded_authenticator); + krb5_auth_con_free(context, authcontext); + return retval; +} + +krb5_error_code +krb5int_fast_tgs_armor(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_keyblock *subkey, krb5_keyblock *session_key, + krb5_ccache ccache, krb5_data *target_realm) +{ + krb5_principal target_principal = NULL; + krb5_keyblock *existing_armor = NULL; + krb5_error_code retval = 0; + + if (ccache) { + retval = krb5int_tgtname(context, target_realm, target_realm, + &target_principal); + if (retval == 0) + retval = fast_armor_ap_request(context, state, ccache, + target_principal); + if (retval == 0) { + existing_armor = state->armor_key; + state->armor_key = NULL; + retval = krb5_c_fx_cf2_simple(context, existing_armor, + "explicitarmor", subkey, + "tgsarmor", &state->armor_key); + } + } else { + retval = krb5_c_fx_cf2_simple(context, subkey, "subkeyarmor", + session_key, "ticketarmor", + &state->armor_key); + } + if (target_principal) + krb5_free_principal(context, target_principal); + krb5_free_keyblock(context, existing_armor); + return retval; +} + +krb5_error_code +krb5int_fast_prep_req_body(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_kdc_req *request, + krb5_data **encoded_request_body) +{ + krb5_error_code retval = 0; + krb5_data *local_encoded_request_body = NULL; + + assert(state != NULL); + *encoded_request_body = NULL; + if (state->armor_key == NULL) + return encode_krb5_kdc_req_body(request, encoded_request_body); + state->fast_outer_request = *request; + state->fast_outer_request.padata = NULL; + if (retval == 0) + retval = encode_krb5_kdc_req_body(&state->fast_outer_request, + &local_encoded_request_body); + if (retval == 0) { + *encoded_request_body = local_encoded_request_body; + local_encoded_request_body = NULL; + } + if (local_encoded_request_body != NULL) + krb5_free_data(context, local_encoded_request_body); + return retval; +} + +krb5_error_code +krb5int_fast_as_armor(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_get_init_creds_opt *opt, krb5_kdc_req *request) +{ + krb5_error_code retval = 0; + krb5_ccache ccache = NULL; + krb5_principal target_principal = NULL; + krb5_data *target_realm; + const char *ccname = k5_gic_opt_get_fast_ccache_name(opt); + krb5_flags fast_flags; + + krb5_clear_error_message(context); + target_realm = &request->server->realm; + if (ccname != NULL) { + TRACE_FAST_ARMOR_CCACHE(context, ccname); + state->fast_state_flags |= KRB5INT_FAST_ARMOR_AVAIL; + retval = krb5_cc_resolve(context, ccname, &ccache); + if (retval == 0) { + retval = krb5int_tgtname(context, target_realm, target_realm, + &target_principal); + } + if (retval == 0) { + krb5_data config_data; + config_data.data = NULL; + retval = krb5_cc_get_config(context, ccache, target_principal, + KRB5_CC_CONF_FAST_AVAIL, &config_data); + if ((retval == 0) && config_data.data) { + TRACE_FAST_CCACHE_CONFIG(context); + state->fast_state_flags |= KRB5INT_FAST_DO_FAST; + } + krb5_free_data_contents(context, &config_data); + retval = 0; + } + fast_flags = k5_gic_opt_get_fast_flags(opt); + if (fast_flags & KRB5_FAST_REQUIRED) { + TRACE_FAST_REQUIRED(context); + state->fast_state_flags |= KRB5INT_FAST_DO_FAST; + } + if (retval == 0 && (state->fast_state_flags & KRB5INT_FAST_DO_FAST)) { + retval = fast_armor_ap_request(context, state, ccache, + target_principal); + } + if (retval != 0) { + k5_prependmsg(context, retval, + _("Error constructing AP-REQ armor")); + } + } + if (ccache) + krb5_cc_close(context, ccache); + if (target_principal) + krb5_free_principal(context, target_principal); + return retval; +} + +/* + * Construct a list of outer request padata for a TGS request. Since we do + * FAST TGS even when we don't have reason to believe the KDC supports FAST, + * the outer padata has to contain duplicates of the inner padata (such as + * S4U2Self padata) as well as the PA-TGS-REQ and PA-FX-FAST padata. The + * caller must free *out_padata with free() as it is not a deep copy. + */ +static krb5_error_code +make_tgs_outer_padata(krb5_pa_data *tgs, krb5_pa_data *fast, + krb5_pa_data **other, krb5_pa_data ***out_padata) +{ + krb5_pa_data **pa_list; + size_t i; + + *out_padata = NULL; + for (i = 0; other[i] != NULL; i++); + pa_list = calloc(i + 3, sizeof(*pa_list)); + if (pa_list == NULL) + return ENOMEM; + pa_list[0] = tgs; + pa_list[1] = fast; + for (i = 0; other[i] != NULL; i++) + pa_list[i + 2] = other[i]; + *out_padata = pa_list; + return 0; +} + +krb5_error_code +krb5int_fast_prep_req(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_kdc_req *request, + const krb5_data *to_be_checksummed, + kdc_req_encoder_proc encoder, + krb5_data **encoded_request) +{ + krb5_error_code retval = 0; + krb5_pa_data *pa_array[2], **pa_tgs_array = NULL; + krb5_pa_data pa[2]; + krb5_fast_req fast_req; + krb5_pa_data *tgs = NULL; + krb5_fast_armored_req *armored_req = NULL; + krb5_data *encoded_fast_req = NULL; + krb5_data *encoded_armored_req = NULL; + krb5_data *local_encoded_result = NULL; + int i, j; + + assert(state != NULL); + assert(state->fast_outer_request.padata == NULL); + memset(pa_array, 0, sizeof(pa_array)); + if (state->armor_key == NULL) { + return encoder(request, encoded_request); + } + + TRACE_FAST_ENCODE(context); + state->nonce = request->nonce; + fast_req.req_body = request; + if (fast_req.req_body->padata == NULL) { + fast_req.req_body->padata = calloc(1, sizeof(krb5_pa_data *)); + if (fast_req.req_body->padata == NULL) + retval = ENOMEM; + } + fast_req.fast_options = state->fast_options; + if (retval == 0 + && (tgs = krb5int_find_pa_data(context, fast_req.req_body->padata, + KRB5_PADATA_AP_REQ)) != NULL) { + krb5_pa_data **paptr = &fast_req.req_body->padata[0]; + for (i = 0, j = 0; paptr[j] != NULL; j++) { + if (paptr[j]->pa_type == KRB5_PADATA_AP_REQ) + paptr[j] = NULL; + else + paptr[i++] = paptr[j]; + } + paptr[i] = NULL; + } + if (retval == 0) + retval = encode_krb5_fast_req(&fast_req, &encoded_fast_req); + if (retval == 0) { + armored_req = calloc(1, sizeof(krb5_fast_armored_req)); + if (armored_req == NULL) + retval = ENOMEM; + } + if (retval == 0) + armored_req->armor = state->armor; + if (retval ==0) + retval = krb5_c_make_checksum(context, 0, state->armor_key, + KRB5_KEYUSAGE_FAST_REQ_CHKSUM, + to_be_checksummed, + &armored_req->req_checksum); + if (retval == 0) + retval = krb5_encrypt_helper(context, state->armor_key, + KRB5_KEYUSAGE_FAST_ENC, encoded_fast_req, + &armored_req->enc_part); + if (retval == 0) + retval = encode_krb5_pa_fx_fast_request(armored_req, + &encoded_armored_req); + if (retval == 0) { + pa[0].pa_type = KRB5_PADATA_FX_FAST; + pa[0].contents = (unsigned char *) encoded_armored_req->data; + pa[0].length = encoded_armored_req->length; + if (tgs) { + retval = make_tgs_outer_padata(tgs, pa, request->padata, + &pa_tgs_array); + state->fast_outer_request.padata = pa_tgs_array; + } else { + pa_array[0] = &pa[0]; + state->fast_outer_request.padata = pa_array; + } + } + if (retval == 0) + retval = encoder(&state->fast_outer_request, &local_encoded_result); + if (retval == 0) { + *encoded_request = local_encoded_result; + local_encoded_result = NULL; + } + if (encoded_armored_req) + krb5_free_data(context, encoded_armored_req); + if (armored_req) { + armored_req->armor = NULL; /*owned by state*/ + krb5_free_fast_armored_req(context, armored_req); + } + if (encoded_fast_req) + krb5_free_data(context, encoded_fast_req); + if (local_encoded_result) + krb5_free_data(context, local_encoded_result); + if (tgs) { + free(tgs->contents); + free(tgs); + } + state->fast_outer_request.padata = NULL; + free(pa_tgs_array); + return retval; +} + +static krb5_error_code +decrypt_fast_reply(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_pa_data **in_padata, + krb5_fast_response **response) +{ + krb5_error_code retval = 0; + krb5_data scratch; + krb5_enc_data *encrypted_response = NULL; + krb5_pa_data *fx_reply = NULL; + krb5_fast_response *local_resp = NULL; + + assert(state != NULL); + assert(state->armor_key); + fx_reply = krb5int_find_pa_data(context, in_padata, KRB5_PADATA_FX_FAST); + if (fx_reply == NULL) + retval = KRB5_ERR_FAST_REQUIRED; + TRACE_FAST_DECODE(context); + if (retval == 0) { + scratch.data = (char *) fx_reply->contents; + scratch.length = fx_reply->length; + retval = decode_krb5_pa_fx_fast_reply(&scratch, &encrypted_response); + } + scratch.data = NULL; + if (retval == 0) { + scratch.data = malloc(encrypted_response->ciphertext.length); + if (scratch.data == NULL) + retval = ENOMEM; + scratch.length = encrypted_response->ciphertext.length; + } + if (retval == 0) + retval = krb5_c_decrypt(context, state->armor_key, + KRB5_KEYUSAGE_FAST_REP, NULL, + encrypted_response, &scratch); + if (retval != 0) + k5_prependmsg(context, retval, _("Failed to decrypt FAST reply")); + if (retval == 0) + retval = decode_krb5_fast_response(&scratch, &local_resp); + if (retval == 0) { + if (local_resp->nonce != state->nonce) { + retval = KRB5_KDCREP_MODIFIED; + k5_setmsg(context, retval, _("nonce modified in FAST response: " + "KDC response modified")); + } + } + if (retval == 0) { + *response = local_resp; + local_resp = NULL; + } + if (scratch.data) + free(scratch.data); + if (encrypted_response) + krb5_free_enc_data(context, encrypted_response); + if (local_resp) + krb5_free_fast_response(context, local_resp); + return retval; +} + +/* + * If state contains an armor key and *err_replyptr contains a FAST error, + * decode it and set *err_replyptr to the inner error and *out_padata to the + * padata in the FAST response. Otherwise, leave *err_replyptr alone and set + * *out_padata to the error e_data decoded as pa-data or typed-data, or to NULL + * if it doesn't decode as either. In either case, set *retry to indicate + * whether the client should try to make a follow-up request. + */ +krb5_error_code +krb5int_fast_process_error(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_error **err_replyptr, + krb5_pa_data ***out_padata, + krb5_boolean *retry) +{ + krb5_error_code retval = 0; + krb5_error *err_reply = *err_replyptr; + krb5_pa_data *fx_error_pa; + krb5_pa_data **result = NULL; + krb5_data scratch = empty_data(); + krb5_error *fx_error = NULL; + krb5_fast_response *fast_response = NULL; + + if (out_padata) + *out_padata = NULL; + if (retry) + *retry = 0; + + if (state->armor_key) { + retval = decode_krb5_padata_sequence(&err_reply->e_data, &result); + if (retval == 0) + retval = decrypt_fast_reply(context, state, result, + &fast_response); + if (retval) { + /* + * This can happen if the KDC does not understand FAST. We don't + * expect that, but treating it as the fatal error indicated by the + * KDC seems reasonable. + */ + if (retry != NULL) + *retry = 0; + krb5_free_pa_data(context, result); + return 0; + } + if (retval == 0) { + fx_error_pa = krb5int_find_pa_data(context, fast_response->padata, + KRB5_PADATA_FX_ERROR); + if (fx_error_pa == NULL) { + k5_setmsg(context, KRB5KDC_ERR_PREAUTH_FAILED, + _("Expecting FX_ERROR pa-data inside FAST " + "container")); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + } + } + if (retval == 0) { + scratch = make_data(fx_error_pa->contents, fx_error_pa->length); + retval = decode_krb5_error(&scratch, &fx_error); + } + if (retval == 0) { + krb5_free_error(context, err_reply); + *err_replyptr = fx_error; + fx_error = NULL; + if (out_padata) { + *out_padata = fast_response->padata; + fast_response->padata = NULL; + } + /* + * If there is more than the fx_error padata, then we want + * to retry the error if a cookie is present + */ + if (retry != NULL) { + *retry = (*out_padata)[1] != NULL; + if (krb5int_find_pa_data(context, *out_padata, + KRB5_PADATA_FX_COOKIE) == NULL) + *retry = 0; + } + } + } else { /*not FAST*/ + /* Possibly retry if there's any e_data to process. */ + if (retry) + *retry = (err_reply->e_data.length > 0); + /* Try to decode e_data as pa-data or typed-data for out_padata. */ + if (out_padata) { + retval = decode_krb5_padata_sequence(&err_reply->e_data, + out_padata); + if (retval != 0) { + (void)decode_krb5_typed_data(&err_reply->e_data, out_padata); + retval = 0; + } + } + } + krb5_free_pa_data(context, result); + krb5_free_fast_response(context, fast_response); + if (fx_error) + krb5_free_error(context, fx_error); + return retval; +} + + +krb5_error_code +krb5int_fast_process_response(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_kdc_rep *resp, + krb5_keyblock **strengthen_key) +{ + krb5_error_code retval = 0; + krb5_fast_response *fast_response = NULL; + krb5_data *encoded_ticket = NULL; + krb5_boolean cksum_valid; + + krb5_clear_error_message(context); + *strengthen_key = NULL; + if (state->armor_key == 0) + return 0; + retval = decrypt_fast_reply(context, state, resp->padata, + &fast_response); + if (retval == 0) { + if (fast_response->finished == 0) { + retval = KRB5_KDCREP_MODIFIED; + k5_setmsg(context, retval, + _("FAST response missing finish message in KDC reply")); + } + } + if (retval == 0) + retval = encode_krb5_ticket(resp->ticket, &encoded_ticket); + if (retval == 0) + retval = krb5_c_verify_checksum(context, state->armor_key, + KRB5_KEYUSAGE_FAST_FINISHED, + encoded_ticket, + &fast_response->finished->ticket_checksum, + &cksum_valid); + if (retval == 0 && cksum_valid == 0) { + retval = KRB5_KDCREP_MODIFIED; + k5_setmsg(context, retval, _("Ticket modified in KDC reply")); + } + if (retval == 0) { + krb5_free_principal(context, resp->client); + resp->client = fast_response->finished->client; + fast_response->finished->client = NULL; + *strengthen_key = fast_response->strengthen_key; + fast_response->strengthen_key = NULL; + krb5_free_pa_data(context, resp->padata); + resp->padata = fast_response->padata; + fast_response->padata = NULL; + } + if (fast_response) + krb5_free_fast_response(context, fast_response); + if (encoded_ticket) + krb5_free_data(context, encoded_ticket); + return retval; +} + +krb5_error_code +krb5int_fast_reply_key(krb5_context context, + const krb5_keyblock *strengthen_key, + const krb5_keyblock *existing_key, + krb5_keyblock *out_key) +{ + krb5_keyblock *key = NULL; + krb5_error_code retval = 0; + krb5_free_keyblock_contents(context, out_key); + if (strengthen_key) { + retval = krb5_c_fx_cf2_simple(context, (krb5_keyblock *)strengthen_key, + "strengthenkey", + (krb5_keyblock *)existing_key, + "replykey", &key); + if (retval == 0) { + TRACE_FAST_REPLY_KEY(context, key); + *out_key = *key; + free(key); + } + } else { + retval = krb5_copy_keyblock_contents(context, existing_key, out_key); + } + return retval; +} + + +krb5_error_code +krb5int_fast_make_state(krb5_context context, + struct krb5int_fast_request_state **state) +{ + struct krb5int_fast_request_state *local_state ; + + local_state = malloc(sizeof *local_state); + if (local_state == NULL) + return ENOMEM; + memset(local_state, 0, sizeof(*local_state)); + *state = local_state; + return 0; +} + +void +krb5int_fast_free_state(krb5_context context, + struct krb5int_fast_request_state *state) +{ + if (state == NULL) + return; + /*We are responsible for none of the store in the fast_outer_req*/ + krb5_free_keyblock(context, state->armor_key); + krb5_free_fast_armor(context, state->armor); + free(state); +} + +/* + * Implement FAST negotiation as specified in RFC 6806 section 11. If + * the encrypted part of rep sets the enc-pa-rep flag, look for and + * verify a PA-REQ-ENC-PA-REP entry in the encrypted padata. If a + * PA-FX-FAST entry is also present in the encrypted padata, set + * *fast_avail to true. This will result in a fast_avail config entry + * being written to the credential cache, if an output ccache was + * specified using krb5_get_init_creds_opt_set_out_ccache(). That + * entry will be detected in the armor ccache by + * krb5int_fast_as_armor(), allowing us to use FAST without a + * round-trip for the KDC to indicate support, and without a downgrade + * attack. + */ +krb5_error_code +krb5int_fast_verify_nego(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_kdc_rep *rep, krb5_data *request, + krb5_keyblock *decrypting_key, + krb5_boolean *fast_avail) +{ + krb5_error_code retval = 0; + krb5_checksum *checksum = NULL; + krb5_pa_data *pa; + krb5_data scratch; + krb5_boolean valid; + + *fast_avail = FALSE; + if (rep->enc_part2->flags& TKT_FLG_ENC_PA_REP) { + pa = krb5int_find_pa_data(context, rep->enc_part2->enc_padata, + KRB5_ENCPADATA_REQ_ENC_PA_REP); + if (pa == NULL) + retval = KRB5_KDCREP_MODIFIED; + else { + scratch.data = (char *) pa->contents; + scratch.length = pa->length; + } + if (retval == 0) + retval = decode_krb5_checksum(&scratch, &checksum); + if (retval == 0) + retval = krb5_c_verify_checksum(context, decrypting_key, + KRB5_KEYUSAGE_AS_REQ, + request, checksum, &valid); + if (retval == 0 &&valid == 0) + retval = KRB5_KDCREP_MODIFIED; + if (retval == 0) { + pa = krb5int_find_pa_data(context, rep->enc_part2->enc_padata, + KRB5_PADATA_FX_FAST); + *fast_avail = (pa != NULL); + } + } + TRACE_FAST_NEGO(context, *fast_avail); + if (checksum) + krb5_free_checksum(context, checksum); + return retval; +} + +krb5_boolean +k5_upgrade_to_fast_p(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_pa_data **padata) +{ + if (state->armor_key != NULL) + return FALSE; /* Already using FAST. */ + if (!(state->fast_state_flags & KRB5INT_FAST_ARMOR_AVAIL)) + return FALSE; + if (krb5int_find_pa_data(context, padata, KRB5_PADATA_FX_FAST) != NULL) + return TRUE; + return FALSE; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/fast.h b/krb5-1.21.3/src/lib/krb5/krb/fast.h new file mode 100644 index 00000000..7156ea20 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/fast.h @@ -0,0 +1,114 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/fast.h */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef KRB_FAST_H + +#define KRB_FAST_H + +#include + +struct krb5int_fast_request_state { + krb5_kdc_req fast_outer_request; + krb5_keyblock *armor_key; /*non-null means fast is in use*/ + krb5_fast_armor *armor; + krb5_ui_4 fast_state_flags; + krb5_ui_4 fast_options; + krb5_int32 nonce; +}; + +#define KRB5INT_FAST_DO_FAST (1l<<0) /* Perform FAST */ +#define KRB5INT_FAST_ARMOR_AVAIL (1l<<1) + +krb5_error_code +krb5int_fast_prep_req_body(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_kdc_req *request, + krb5_data **encoded_req_body); + +typedef krb5_error_code (*kdc_req_encoder_proc)(const krb5_kdc_req *, + krb5_data **); + +krb5_error_code +krb5int_fast_prep_req(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_kdc_req *request, + const krb5_data *to_be_checksummed, + kdc_req_encoder_proc encoder, + krb5_data **encoded_request); + +krb5_error_code +krb5int_fast_process_error(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_error **err_replyptr, + krb5_pa_data ***out_padata, + krb5_boolean *retry); + +krb5_error_code +krb5int_fast_process_response(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_kdc_rep *resp, + krb5_keyblock **strengthen_key); + +krb5_error_code +krb5int_fast_make_state(krb5_context context, + struct krb5int_fast_request_state **state); + +void +krb5int_fast_free_state(krb5_context context, + struct krb5int_fast_request_state *state); + +krb5_error_code +krb5int_fast_as_armor(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_get_init_creds_opt *opt, krb5_kdc_req *request); + +krb5_error_code +krb5int_fast_reply_key(krb5_context context, + const krb5_keyblock *strengthen_key, + const krb5_keyblock *existing_key, krb5_keyblock *output_key); + + +krb5_error_code +krb5int_fast_verify_nego(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_kdc_rep *rep, krb5_data *request, + krb5_keyblock *decrypting_key, + krb5_boolean *fast_avail); + +krb5_boolean +k5_upgrade_to_fast_p(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_pa_data **padata); + +krb5_error_code +krb5int_fast_tgs_armor(krb5_context context, + struct krb5int_fast_request_state *state, + krb5_keyblock *subkey, + krb5_keyblock *session_key, + krb5_ccache ccache, + krb5_data *target_realm); + +#endif diff --git a/krb5-1.21.3/src/lib/krb5/krb/fwd_tgt.c b/krb5-1.21.3/src/lib/krb5/krb/fwd_tgt.c new file mode 100644 index 00000000..87f63b6b --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/fwd_tgt.c @@ -0,0 +1,186 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/fwd_tgt.c Definition of krb5_fwd_tgt_creds() routine */ +/* + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#ifdef HAVE_MEMORY_H +#include +#endif +#include "int-proto.h" +#include "os-proto.h" + +/* helper function: convert flags to necessary KDC options */ +#define flags2options(flags) (flags & KDC_TKT_COMMON_MASK) + +/* Get a TGT for use at the remote host */ +krb5_error_code KRB5_CALLCONV +krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, + const char *rhost, krb5_principal client, + krb5_principal server, krb5_ccache cc, int forwardable, + krb5_data *outbuf) +/* Should forwarded TGT also be forwardable? */ +{ + krb5_replay_data replaydata; + krb5_data * scratch = 0; + krb5_address **addrs = NULL; + krb5_error_code retval; + krb5_creds creds, tgt; + krb5_creds *pcreds; + krb5_flags kdcoptions; + krb5_ccache defcc = NULL; + char *def_rhost = NULL; + krb5_enctype enctype = 0; + krb5_keyblock *session_key; + krb5_boolean old_use_conf_ktypes = context->use_conf_ktypes; + + memset(&creds, 0, sizeof(creds)); + memset(&tgt, 0, sizeof(creds)); + + if (cc == 0) { + if ((retval = krb5int_cc_default(context, &defcc))) + goto errout; + cc = defcc; + } + retval = krb5_auth_con_getkey (context, auth_context, &session_key); + if (retval) + goto errout; + if (session_key) { + enctype = session_key->enctype; + krb5_free_keyblock (context, session_key); + session_key = NULL; + } else if (server) { /* must server be non-NULL when rhost is given? */ + /* Try getting credentials to see what the remote side supports. + Not bulletproof, just a heuristic. */ + krb5_creds in, *out = 0; + memset (&in, 0, sizeof(in)); + + retval = krb5_copy_principal (context, server, &in.server); + if (retval) + goto punt; + retval = krb5_copy_principal (context, client, &in.client); + if (retval) + goto punt; + retval = krb5_get_credentials (context, 0, cc, &in, &out); + if (retval) + goto punt; + /* Got the credentials. Okay, now record the enctype and + throw them away. */ + enctype = out->keyblock.enctype; + krb5_free_creds (context, out); + punt: + krb5_free_cred_contents (context, &in); + } + + if ((retval = krb5_copy_principal(context, client, &creds.client))) + goto errout; + + retval = krb5int_tgtname(context, &client->realm, &client->realm, + &creds.server); + if (retval) + goto errout; + + /* fetch tgt directly from cache */ + context->use_conf_ktypes = 1; + retval = krb5_cc_retrieve_cred (context, cc, KRB5_TC_SUPPORTED_KTYPES, + &creds, &tgt); + context->use_conf_ktypes = old_use_conf_ktypes; + if (retval) + goto errout; + + /* tgt->client must be equal to creds.client */ + if (!krb5_principal_compare(context, tgt.client, creds.client)) { + retval = KRB5_PRINC_NOMATCH; + goto errout; + } + + if (!tgt.ticket.length) { + retval = KRB5_NO_TKT_SUPPLIED; + goto errout; + } + + if (tgt.addresses && *tgt.addresses) { + if (rhost == NULL) { + if (server->type != KRB5_NT_SRV_HST) { + retval = KRB5_FWD_BAD_PRINCIPAL; + goto errout; + } + + if (server->length < 2){ + retval = KRB5_CC_BADNAME; + goto errout; + } + + def_rhost = k5memdup0(server->data[1].data, server->data[1].length, + &retval); + if (def_rhost == NULL) + goto errout; + rhost = def_rhost; + } + + retval = k5_os_hostaddr(context, rhost, &addrs); + if (retval) + goto errout; + } + + creds.keyblock.enctype = enctype; + creds.times = tgt.times; + creds.times.starttime = 0; + kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED; + + if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */ + kdcoptions &= ~(KDC_OPT_FORWARDABLE); + + if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions, + addrs, &creds, &pcreds))) { + if (enctype) { + creds.keyblock.enctype = 0; + if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions, + addrs, &creds, &pcreds))) + goto errout; + } + else goto errout; + } + retval = krb5_mk_1cred(context, auth_context, pcreds, + &scratch, &replaydata); + krb5_free_creds(context, pcreds); + + if (retval) { + if (scratch) + krb5_free_data(context, scratch); + } else { + *outbuf = *scratch; + free(scratch); + } + +errout: + if (addrs) + krb5_free_addresses(context, addrs); + if (defcc) + krb5_cc_close(context, defcc); + free(def_rhost); + krb5_free_cred_contents(context, &creds); + krb5_free_cred_contents(context, &tgt); + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/gc_via_tkt.c b/krb5-1.21.3/src/lib/krb5/krb/gc_via_tkt.c new file mode 100644 index 00000000..f8a256b2 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/gc_via_tkt.c @@ -0,0 +1,420 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/gc_via_tkt.c */ +/* + * Copyright 1990,1991,2007-2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Given a tkt, and a target cred, get it. + * Assumes that the kdc_rep has been decrypted. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "fast.h" + +static krb5_error_code +kdcrep2creds(krb5_context context, krb5_kdc_rep *pkdcrep, + krb5_address *const *address, krb5_boolean is_skey, + krb5_data *psectkt, krb5_creds **ppcreds) +{ + krb5_error_code retval; + krb5_data *pdata; + + if ((*ppcreds = (krb5_creds *)calloc(1,sizeof(krb5_creds))) == NULL) { + return ENOMEM; + } + + if ((retval = krb5_copy_principal(context, pkdcrep->client, + &(*ppcreds)->client))) + goto cleanup; + + if ((retval = krb5_copy_principal(context, pkdcrep->enc_part2->server, + &(*ppcreds)->server))) + goto cleanup; + + if ((retval = krb5_copy_keyblock_contents(context, + pkdcrep->enc_part2->session, + &(*ppcreds)->keyblock))) + goto cleanup; + TRACE_TGS_REPLY(context, (*ppcreds)->client, (*ppcreds)->server, + &(*ppcreds)->keyblock); + + if ((retval = krb5_copy_data(context, psectkt, &pdata))) + goto cleanup_keyblock; + (*ppcreds)->second_ticket = *pdata; + free(pdata); + + (*ppcreds)->ticket_flags = pkdcrep->enc_part2->flags; + (*ppcreds)->times = pkdcrep->enc_part2->times; + (*ppcreds)->magic = KV5M_CREDS; + + (*ppcreds)->authdata = NULL; /* not used */ + (*ppcreds)->is_skey = is_skey; + + if (pkdcrep->enc_part2->caddrs) { + if ((retval = krb5_copy_addresses(context, pkdcrep->enc_part2->caddrs, + &(*ppcreds)->addresses))) + goto cleanup_keyblock; + } else { + /* no addresses in the list means we got what we had */ + if ((retval = krb5_copy_addresses(context, address, + &(*ppcreds)->addresses))) + goto cleanup_keyblock; + } + + if ((retval = encode_krb5_ticket(pkdcrep->ticket, &pdata))) + goto cleanup_keyblock; + + (*ppcreds)->ticket = *pdata; + free(pdata); + return 0; + +cleanup_keyblock: + krb5_free_keyblock_contents(context, &(*ppcreds)->keyblock); + +cleanup: + free (*ppcreds); + *ppcreds = NULL; + return retval; +} + +static krb5_error_code +check_reply_server(krb5_context context, krb5_flags kdcoptions, + krb5_creds *in_cred, krb5_kdc_rep *dec_rep) +{ + + if (!krb5_principal_compare(context, dec_rep->ticket->server, + dec_rep->enc_part2->server)) + return KRB5_KDCREP_MODIFIED; + + /* Reply is self-consistent. */ + + if (krb5_principal_compare(context, dec_rep->ticket->server, + in_cred->server)) + return 0; + + /* Server in reply differs from what we requested. */ + + if (kdcoptions & KDC_OPT_CANONICALIZE) { + /* in_cred server differs from ticket returned, but ticket + returned is consistent and we requested canonicalization. */ + + TRACE_CHECK_REPLY_SERVER_DIFFERS(context, in_cred->server, + dec_rep->enc_part2->server); + return 0; + } + + /* We didn't request canonicalization. */ + + if (!IS_TGS_PRINC(in_cred->server) || + !IS_TGS_PRINC(dec_rep->ticket->server)) { + /* Canonicalization not requested, and not a TGS referral. */ + return KRB5_KDCREP_MODIFIED; + } + return 0; +} + +/* Return true if a TGS credential is for the client's local realm. */ +static inline int +tgt_is_local_realm(krb5_creds *tgt) +{ + return (tgt->server->length == 2 + && data_eq_string(tgt->server->data[0], KRB5_TGS_NAME) + && data_eq(tgt->server->data[1], tgt->client->realm) + && data_eq(tgt->server->realm, tgt->client->realm)); +} + +krb5_error_code +krb5_get_cred_via_tkt(krb5_context context, krb5_creds *tkt, + krb5_flags kdcoptions, krb5_address *const *address, + krb5_creds *in_cred, krb5_creds **out_cred) +{ + return krb5_get_cred_via_tkt_ext (context, tkt, + kdcoptions, address, + NULL, in_cred, NULL, NULL, + NULL, NULL, out_cred, NULL); +} + +krb5_error_code +krb5int_process_tgs_reply(krb5_context context, + struct krb5int_fast_request_state *fast_state, + krb5_data *response_data, + krb5_creds *tkt, + krb5_flags kdcoptions, + krb5_address *const *address, + krb5_pa_data **in_padata, + krb5_creds *in_cred, + krb5_timestamp timestamp, + krb5_int32 nonce, + krb5_keyblock *subkey, + krb5_pa_data ***out_padata, + krb5_pa_data ***out_enc_padata, + krb5_creds **out_cred) +{ + krb5_error_code retval; + krb5_kdc_rep *dec_rep = NULL; + krb5_error *err_reply = NULL; + krb5_boolean s4u2self, is_skey; + + s4u2self = krb5int_find_pa_data(context, in_padata, + KRB5_PADATA_S4U_X509_USER) || + krb5int_find_pa_data(context, in_padata, + KRB5_PADATA_FOR_USER); + + if (krb5_is_krb_error(response_data)) { + retval = decode_krb5_error(response_data, &err_reply); + if (retval != 0) + goto cleanup; + retval = krb5int_fast_process_error(context, fast_state, + &err_reply, NULL, NULL); + if (retval) + goto cleanup; + retval = (krb5_error_code) err_reply->error + ERROR_TABLE_BASE_krb5; + if (err_reply->text.length > 0) { + switch (err_reply->error) { + case KRB_ERR_GENERIC: + k5_setmsg(context, retval, + _("KDC returned error string: %.*s"), + err_reply->text.length, err_reply->text.data); + break; + case KDC_ERR_S_PRINCIPAL_UNKNOWN: + { + char *s_name; + if (err_reply->server && + krb5_unparse_name(context, err_reply->server, &s_name) == 0) { + k5_setmsg(context, retval, + _("Server %s not found in Kerberos database"), + s_name); + krb5_free_unparsed_name(context, s_name); + } else + /* In case there's a stale S_PRINCIPAL_UNKNOWN + report already noted. */ + krb5_clear_error_message(context); + } + break; + } + } + krb5_free_error(context, err_reply); + goto cleanup; + } else if (!krb5_is_tgs_rep(response_data)) { + retval = KRB5KRB_AP_ERR_MSG_TYPE; + goto cleanup; + } + + /* Unfortunately, Heimdal at least up through 1.2 encrypts using + the session key not the subsession key. So we try both. */ + retval = krb5int_decode_tgs_rep(context, fast_state, response_data, subkey, + KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY, + &dec_rep); + if (retval) { + TRACE_TGS_REPLY_DECODE_SESSION(context, &tkt->keyblock); + if ((krb5int_decode_tgs_rep(context, fast_state, response_data, + &tkt->keyblock, + KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY, &dec_rep)) == 0) + retval = 0; + else + goto cleanup; + } + + if (dec_rep->msg_type != KRB5_TGS_REP) { + retval = KRB5KRB_AP_ERR_MSG_TYPE; + goto cleanup; + } + + /* + * Don't trust the ok-as-delegate flag from foreign KDCs unless the + * cross-realm TGT also had the ok-as-delegate flag set. + */ + if (!tgt_is_local_realm(tkt) + && !(tkt->ticket_flags & TKT_FLG_OK_AS_DELEGATE)) + dec_rep->enc_part2->flags &= ~TKT_FLG_OK_AS_DELEGATE; + + /* make sure the response hasn't been tampered with..... */ + retval = 0; + + if (s4u2self && !IS_TGS_PRINC(dec_rep->ticket->server)) { + /* Final hop, check whether KDC supports S4U2Self */ + if (krb5_principal_compare(context, dec_rep->client, in_cred->server)) + retval = KRB5KDC_ERR_PADATA_TYPE_NOSUPP; + } else if ((kdcoptions & KDC_OPT_CNAME_IN_ADDL_TKT) == 0 || + IS_TGS_PRINC(dec_rep->ticket->server)) { + /* + * For constrained delegation this check must be performed by caller, + * as we can't decrypt the evidence ticket. However, if it is a + * referral the client should match the TGT client like normal. + */ + if (!krb5_principal_compare(context, dec_rep->client, tkt->client)) + retval = KRB5_KDCREP_MODIFIED; + } + + if (retval == 0) + retval = check_reply_server(context, kdcoptions, in_cred, dec_rep); + + if (dec_rep->enc_part2->nonce != nonce) + retval = KRB5_KDCREP_MODIFIED; + + if ((kdcoptions & KDC_OPT_POSTDATED) && + (in_cred->times.starttime != 0) && + (in_cred->times.starttime != dec_rep->enc_part2->times.starttime)) + retval = KRB5_KDCREP_MODIFIED; + + if ((in_cred->times.endtime != 0) && + ts_after(dec_rep->enc_part2->times.endtime, in_cred->times.endtime)) + retval = KRB5_KDCREP_MODIFIED; + + if ((kdcoptions & KDC_OPT_RENEWABLE) && + (in_cred->times.renew_till != 0) && + ts_after(dec_rep->enc_part2->times.renew_till, + in_cred->times.renew_till)) + retval = KRB5_KDCREP_MODIFIED; + + if ((kdcoptions & KDC_OPT_RENEWABLE_OK) && + (dec_rep->enc_part2->flags & KDC_OPT_RENEWABLE) && + (in_cred->times.endtime != 0) && + ts_after(dec_rep->enc_part2->times.renew_till, in_cred->times.endtime)) + retval = KRB5_KDCREP_MODIFIED; + + if (retval != 0) + goto cleanup; + + if (!in_cred->times.starttime && + !ts_within(dec_rep->enc_part2->times.starttime, timestamp, + context->clockskew)) { + retval = KRB5_KDCREP_SKEW; + goto cleanup; + } + + if (out_padata != NULL) { + *out_padata = dec_rep->padata; + dec_rep->padata = NULL; + } + if (out_enc_padata != NULL) { + *out_enc_padata = dec_rep->enc_part2->enc_padata; + dec_rep->enc_part2->enc_padata = NULL; + } + + is_skey = (kdcoptions & KDC_OPT_ENC_TKT_IN_SKEY); + retval = kdcrep2creds(context, dec_rep, address, is_skey, + &in_cred->second_ticket, out_cred); + if (retval != 0) + goto cleanup; + +cleanup: + if (dec_rep != NULL) { + memset(dec_rep->enc_part2->session->contents, 0, + dec_rep->enc_part2->session->length); + krb5_free_kdc_rep(context, dec_rep); + } + + return retval; +} + +krb5_error_code +krb5_get_cred_via_tkt_ext(krb5_context context, krb5_creds *tkt, + krb5_flags kdcoptions, krb5_address *const *address, + krb5_pa_data **in_padata, krb5_creds *in_cred, + k5_pacb_fn pacb_fn, void *pacb_data, + krb5_pa_data ***out_padata, + krb5_pa_data ***out_enc_padata, + krb5_creds **out_cred, krb5_keyblock **out_subkey) +{ + krb5_error_code retval; + krb5_data request_data; + krb5_data response_data; + krb5_timestamp timestamp; + krb5_int32 nonce; + krb5_keyblock *subkey = NULL; + int tcp_only = 0, use_primary = 0; + struct krb5int_fast_request_state *fast_state = NULL; + + request_data.data = NULL; + request_data.length = 0; + response_data.data = NULL; + response_data.length = 0; + + retval = krb5int_fast_make_state(context, &fast_state); + if (retval) + goto cleanup; + + TRACE_GET_CRED_VIA_TKT_EXT(context, in_cred->server, tkt->server, + kdcoptions); + + retval = k5_make_tgs_req(context, fast_state, tkt, kdcoptions, address, + in_padata, in_cred, pacb_fn, pacb_data, + &request_data, ×tamp, &nonce, &subkey); + if (retval != 0) + goto cleanup; + +send_again: + use_primary = 0; + retval = krb5_sendto_kdc(context, &request_data, &in_cred->server->realm, + &response_data, &use_primary, tcp_only); + if (retval == 0) { + if (krb5_is_krb_error(&response_data)) { + if (!tcp_only) { + krb5_error *err_reply; + retval = decode_krb5_error(&response_data, &err_reply); + if (retval != 0) + goto cleanup; + retval = krb5int_fast_process_error(context, fast_state, + &err_reply, NULL, NULL); + if (retval) + goto cleanup; + if (err_reply->error == KRB_ERR_RESPONSE_TOO_BIG) { + tcp_only = 1; + krb5_free_error(context, err_reply); + krb5_free_data_contents(context, &response_data); + goto send_again; + } + krb5_free_error(context, err_reply); + } + } + } else + goto cleanup; + + retval = krb5int_process_tgs_reply(context, fast_state, &response_data, + tkt, kdcoptions, address, + in_padata, in_cred, + timestamp, nonce, subkey, + out_padata, + out_enc_padata, out_cred); + if (retval != 0) + goto cleanup; + +cleanup: + krb5int_fast_free_state(context, fast_state); + TRACE_GET_CRED_VIA_TKT_EXT_RETURN(context, retval); + + krb5_free_data_contents(context, &request_data); + krb5_free_data_contents(context, &response_data); + + if (subkey != NULL) { + if (retval == 0 && out_subkey != NULL) + *out_subkey = subkey; + else + krb5_free_keyblock(context, subkey); + } + + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/gen_save_subkey.c b/krb5-1.21.3/src/lib/krb5/krb/gen_save_subkey.c new file mode 100644 index 00000000..d027271b --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/gen_save_subkey.c @@ -0,0 +1,56 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/gen_save_subkey.c */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "auth_con.h" + +krb5_error_code +k5_generate_and_save_subkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock, krb5_enctype enctype) +{ + krb5_error_code retval; + krb5_keyblock *kb = NULL; + + retval = krb5_generate_subkey_extended(context, keyblock, enctype, &kb); + if (retval) + return retval; + retval = krb5_auth_con_setsendsubkey(context, auth_context, kb); + if (retval) + goto cleanup; + retval = krb5_auth_con_setrecvsubkey(context, auth_context, kb); + if (retval) + goto cleanup; + +cleanup: + if (retval) { + (void) krb5_auth_con_setsendsubkey(context, auth_context, NULL); + (void) krb5_auth_con_setrecvsubkey(context, auth_context, NULL); + } + krb5_free_keyblock(context, kb); + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/gen_seqnum.c b/krb5-1.21.3/src/lib/krb5/krb/gen_seqnum.c new file mode 100644 index 00000000..74855c7c --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/gen_seqnum.c @@ -0,0 +1,63 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/gen_seqnum.c */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Routine to automatically generate a starting sequence number. + * We do this by getting a random key and encrypting something with it, + * then taking the output and slicing it up. + */ + +#include "k5-int.h" + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +krb5_error_code +krb5_generate_seq_number(krb5_context context, const krb5_keyblock *key, krb5_ui_4 *seqno) +{ + krb5_data seed; + krb5_error_code retval; + + seed.length = sizeof(*seqno); + seed.data = (char *) seqno; + retval = krb5_c_random_make_octets(context, &seed); + if (retval) + return retval; + /* + * Work around implementation incompatibilities by not generating + * initial sequence numbers greater than 2^30. Previous MIT + * implementations use signed sequence numbers, so initial + * sequence numbers 2^31 to 2^32-1 inclusive will be rejected. + * Letting the maximum initial sequence number be 2^30-1 allows + * for about 2^30 messages to be sent before wrapping into + * "negative" numbers. + */ + *seqno &= 0x3fffffff; + if (*seqno == 0) + *seqno = 1; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/gen_subkey.c b/krb5-1.21.3/src/lib/krb5/krb/gen_subkey.c new file mode 100644 index 00000000..fe6fdecf --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/gen_subkey.c @@ -0,0 +1,58 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/gen_subkey.c - Generate a subsession key based on input key */ +/* + * Copyright 1991, 2002 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +krb5_error_code +krb5_generate_subkey_extended(krb5_context context, + const krb5_keyblock *key, + krb5_enctype enctype, + krb5_keyblock **subkey) +{ + krb5_error_code retval; + krb5_keyblock *keyblock; + + *subkey = NULL; + + keyblock = malloc(sizeof(krb5_keyblock)); + if (!keyblock) + return ENOMEM; + + retval = krb5_c_make_random_key(context, enctype, keyblock); + if (retval) { + free(*subkey); + return retval; + } + + *subkey = keyblock; + return 0; +} + +krb5_error_code +krb5_generate_subkey(krb5_context context, const krb5_keyblock *key, krb5_keyblock **subkey) +{ + return krb5_generate_subkey_extended(context, key, key->enctype, subkey); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/get_creds.c b/krb5-1.21.3/src/lib/krb5/krb/get_creds.c new file mode 100644 index 00000000..698c04ef --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/get_creds.c @@ -0,0 +1,1353 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/get_creds.c */ +/* + * Copyright 1990, 2008, 2010 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Attempts to use the credentials cache or TGS exchange to get an additional + * ticket for the client identified by in_creds->client, the server identified + * by in_creds->server, with options options, expiration date specified in + * in_creds->times.endtime (0 means as long as possible), session key type + * specified in in_creds->keyblock.enctype (if non-zero) + * + * Any returned ticket and intermediate ticket-granting tickets are stored in + * ccache. + * + * Returns errors from encryption routines, system errors. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "os-proto.h" +#include "fast.h" + +/* + * Set *mcreds and *fields to a matching credential and field set for + * use with krb5_cc_retrieve_cred, based on a set of input credentials + * and options. The fields of *mcreds will be aliased to the fields + * of in_creds, so the contents of *mcreds should not be freed. + */ +static krb5_error_code +construct_matching_creds(krb5_context context, krb5_flags options, + krb5_creds *in_creds, krb5_creds *mcreds, + krb5_flags *fields) +{ + if (!in_creds || !in_creds->server || !in_creds->client) + return EINVAL; + + memset(mcreds, 0, sizeof(krb5_creds)); + mcreds->magic = KV5M_CREDS; + if (in_creds->times.endtime != 0) { + mcreds->times.endtime = in_creds->times.endtime; + } else { + krb5_error_code retval; + retval = krb5_timeofday(context, &mcreds->times.endtime); + if (retval != 0) return retval; + } + mcreds->keyblock = in_creds->keyblock; + mcreds->authdata = in_creds->authdata; + mcreds->server = in_creds->server; + mcreds->client = in_creds->client; + + *fields = KRB5_TC_MATCH_TIMES /*XXX |KRB5_TC_MATCH_SKEY_TYPE */ + | KRB5_TC_MATCH_AUTHDATA + | KRB5_TC_SUPPORTED_KTYPES; + if (mcreds->keyblock.enctype) { + krb5_enctype *ktypes; + krb5_error_code ret; + int i; + + *fields |= KRB5_TC_MATCH_KTYPE; + ret = krb5_get_tgs_ktypes(context, mcreds->server, &ktypes); + for (i = 0; ktypes[i]; i++) + if (ktypes[i] == mcreds->keyblock.enctype) + break; + if (ktypes[i] == 0) + ret = KRB5_CC_NOT_KTYPE; + free (ktypes); + if (ret) + return ret; + } + if (options & (KRB5_GC_USER_USER | KRB5_GC_CONSTRAINED_DELEGATION)) { + /* also match on identical 2nd tkt and tkt encrypted in a + session key */ + *fields |= KRB5_TC_MATCH_2ND_TKT; + if (options & KRB5_GC_USER_USER) { + *fields |= KRB5_TC_MATCH_IS_SKEY; + mcreds->is_skey = TRUE; + } + mcreds->second_ticket = in_creds->second_ticket; + if (!in_creds->second_ticket.length) + return KRB5_NO_2ND_TKT; + } + + /* For S4U2Proxy requests we don't know the impersonated client in this + * API, but matching against the second ticket is good enough. */ + if (options & KRB5_GC_CONSTRAINED_DELEGATION) + mcreds->client = NULL; + + return 0; +} + +/* Simple wrapper around krb5_cc_retrieve_cred which allocates the result + * container. */ +static krb5_error_code +cache_get(krb5_context context, krb5_ccache ccache, krb5_flags flags, + krb5_creds *in_creds, krb5_creds **out_creds) +{ + krb5_error_code code; + krb5_creds *creds; + + *out_creds = NULL; + + creds = malloc(sizeof(*creds)); + if (creds == NULL) + return ENOMEM; + + code = krb5_cc_retrieve_cred(context, ccache, flags, in_creds, creds); + if (code != 0) { + free(creds); + return code; + } + + *out_creds = creds; + return 0; +} + +krb5_error_code +k5_get_cached_cred(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_creds **creds_out) +{ + krb5_error_code code; + krb5_creds mcreds; + krb5_flags fields; + + *creds_out = NULL; + + code = construct_matching_creds(context, options, in_creds, + &mcreds, &fields); + if (code) + return code; + + return cache_get(context, ccache, fields, &mcreds, creds_out); +} + +/* + * krb5_tkt_creds_step() is implemented using a tail call style. Every + * begin_*, step_*, or *_request function is responsible for returning an + * error, generating the next request, or delegating to another function using + * a tail call. + * + * The process is divided up into states which govern how the next input token + * should be interpreted. Each state has a "begin_" function to set up + * the context fields related to the state, a "step_" function to + * process a reply and update the related context fields, and possibly a + * "_request" function (invoked by the begin_ and step_ functions) to + * generate the next request. If it's time to advance to another state, any of + * the three functions can make a tail call to begin_ to do so. + * + * The general process is as follows: + * 1. Get a TGT for the service principal's realm (STATE_GET_TGT). + * 2. Make one or more referrals queries (STATE_REFERRALS). + * 3. In some cases, get a TGT for the fallback realm (STATE_GET_TGT again). + * 4. In some cases, make a non-referral query (STATE_NON_REFERRAL). + * + * STATE_GET_TGT can precede either STATE_REFERRALS or STATE_NON_REFERRAL. The + * getting_tgt_for field in the context keeps track of what state we will go to + * after successfully obtaining the TGT, and the end_get_tgt() function + * advances to the proper next state. + * + * If fallback DNS canonicalization is in use, the process can be repeated a + * second time for the second server principal canonicalization candidate. + */ + +enum state { + STATE_BEGIN, /* Initial step (no input token) */ + STATE_GET_TGT, /* Getting TGT for service realm */ + STATE_GET_TGT_OFFPATH, /* Getting TGT via off-path referrals */ + STATE_REFERRALS, /* Retrieving service ticket or referral */ + STATE_NON_REFERRAL, /* Non-referral service ticket request */ + STATE_COMPLETE /* Creds ready for retrieval */ +}; + +struct _krb5_tkt_creds_context { + enum state state; /* What we should do with the next reply */ + enum state getting_tgt_for; /* STATE_REFERRALS or STATE_NON_REFERRAL */ + + /* The following fields are set up at initialization time. */ + krb5_creds *in_creds; /* Creds requested by caller */ + krb5_principal client; /* Caller-requested client principal (alias) */ + krb5_principal server; /* Server principal (alias) */ + krb5_principal req_server; /* Caller-requested server principal */ + krb5_ccache ccache; /* Caller-provided ccache */ + krb5_data start_realm; /* Realm of starting TGT in ccache */ + krb5_flags req_options; /* Caller-requested KRB5_GC_* options */ + krb5_flags req_kdcopt; /* Caller-requested options as KDC options */ + krb5_authdata **authdata; /* Caller-requested authdata */ + struct canonprinc iter; /* Iterator over canonicalized server princs */ + krb5_boolean referral_req; /* Server initially contained referral realm */ + + /* The following fields are used in multiple steps. */ + krb5_creds *cur_tgt; /* TGT to be used for next query */ + krb5_data *realms_seen; /* For loop detection */ + + /* The following fields track state between request and reply. */ + krb5_principal tgt_princ; /* Storage for TGT principal */ + krb5_creds tgt_in_creds; /* Container for TGT matching creds */ + krb5_creds *tgs_in_creds; /* Input credentials of request (alias) */ + krb5_timestamp timestamp; /* Timestamp of request */ + krb5_int32 nonce; /* Nonce of request */ + int kdcopt; /* KDC options of request */ + krb5_keyblock *subkey; /* subkey of request */ + krb5_data previous_request; /* Encoded request (for TCP retransmission) */ + struct krb5int_fast_request_state *fast_state; + + /* The following fields are used when acquiring foreign TGTs. */ + krb5_data *realm_path; /* Path from client to server realm */ + const krb5_data *last_realm;/* Last realm in realm_path */ + const krb5_data *cur_realm; /* Position of cur_tgt in realm_path */ + const krb5_data *next_realm;/* Current target realm in realm_path */ + unsigned int offpath_count; /* Offpath requests made */ + + /* The following fields are used during the referrals loop. */ + unsigned int referral_count;/* Referral requests made */ + + /* The following fields are used within a _step call to avoid + * passing them as parameters everywhere. */ + krb5_creds *reply_creds; /* Creds from TGS reply */ + krb5_error_code reply_code; /* Error status from TGS reply */ + krb5_data *caller_out; /* Caller's out parameter */ + krb5_data *caller_realm; /* Caller's realm parameter */ + unsigned int *caller_flags; /* Caller's flags parameter */ +}; + +/* Convert ticket flags to necessary KDC options */ +#define FLAGS2OPTS(flags) (flags & KDC_TKT_COMMON_MASK) + +static krb5_error_code +begin_get_tgt(krb5_context context, krb5_tkt_creds_context ctx); + +/* + * Fill in the caller out, realm, and flags output variables. out is filled in + * with ctx->previous_request, which the caller should set, and realm is filled + * in with the realm of ctx->cur_tgt. + */ +static krb5_error_code +set_caller_request(krb5_context context, krb5_tkt_creds_context ctx) +{ + krb5_error_code code; + const krb5_data *req = &ctx->previous_request; + const krb5_data *realm = &ctx->cur_tgt->server->data[1]; + krb5_data out_copy = empty_data(), realm_copy = empty_data(); + + code = krb5int_copy_data_contents(context, req, &out_copy); + if (code != 0) + goto cleanup; + code = krb5int_copy_data_contents(context, realm, &realm_copy); + if (code != 0) + goto cleanup; + + *ctx->caller_out = out_copy; + *ctx->caller_realm = realm_copy; + *ctx->caller_flags = KRB5_TKT_CREDS_STEP_FLAG_CONTINUE; + return 0; + +cleanup: + krb5_free_data_contents(context, &out_copy); + krb5_free_data_contents(context, &realm_copy); + return code; +} + +/* + * Set up the request given by ctx->tgs_in_creds, using ctx->cur_tgt. KDC + * options for the requests are determined by ctx->cur_tgt->ticket_flags and + * extra_options. + */ +static krb5_error_code +make_request(krb5_context context, krb5_tkt_creds_context ctx, + int extra_options) +{ + krb5_error_code code; + krb5_data request = empty_data(); + + ctx->kdcopt = extra_options | FLAGS2OPTS(ctx->cur_tgt->ticket_flags); + + /* XXX This check belongs in gc_via_tgt.c or nowhere. */ + if (!krb5_c_valid_enctype(ctx->cur_tgt->keyblock.enctype)) + return KRB5_PROG_ETYPE_NOSUPP; + + /* Create a new FAST state structure to store this request's armor key. */ + krb5int_fast_free_state(context, ctx->fast_state); + ctx->fast_state = NULL; + code = krb5int_fast_make_state(context, &ctx->fast_state); + if (code) + return code; + + krb5_free_keyblock(context, ctx->subkey); + ctx->subkey = NULL; + code = k5_make_tgs_req(context, ctx->fast_state, ctx->cur_tgt, ctx->kdcopt, + ctx->cur_tgt->addresses, NULL, ctx->tgs_in_creds, + NULL, NULL, &request, &ctx->timestamp, &ctx->nonce, + &ctx->subkey); + if (code != 0) + return code; + + krb5_free_data_contents(context, &ctx->previous_request); + ctx->previous_request = request; + return set_caller_request(context, ctx); +} + +/* Set up a request for a TGT for realm, using ctx->cur_tgt. */ +static krb5_error_code +make_request_for_tgt(krb5_context context, krb5_tkt_creds_context ctx, + const krb5_data *realm) +{ + krb5_error_code code; + + /* Construct the principal krbtgt/@. */ + krb5_free_principal(context, ctx->tgt_princ); + ctx->tgt_princ = NULL; + code = krb5int_tgtname(context, realm, &ctx->cur_tgt->server->data[1], + &ctx->tgt_princ); + if (code != 0) + return code; + + TRACE_TKT_CREDS_TGT_REQ(context, ctx->tgt_princ, ctx->cur_tgt->server); + + /* Construct input creds using ctx->tgt_in_creds as a container. */ + memset(&ctx->tgt_in_creds, 0, sizeof(ctx->tgt_in_creds)); + ctx->tgt_in_creds.client = ctx->client; + ctx->tgt_in_creds.server = ctx->tgt_princ; + + /* Make a request for the above creds with no extra options. */ + ctx->tgs_in_creds = &ctx->tgt_in_creds; + code = make_request(context, ctx, 0); + return code; +} + +/* Set up a request for the desired service principal, using ctx->cur_tgt. + * Optionally allow the answer to be a referral. */ +static krb5_error_code +make_request_for_service(krb5_context context, krb5_tkt_creds_context ctx, + krb5_boolean referral) +{ + krb5_error_code code; + int extra_options; + + TRACE_TKT_CREDS_SERVICE_REQ(context, ctx->server, referral); + + /* Include the caller-specified KDC options in service requests. */ + extra_options = ctx->req_kdcopt; + + /* Automatically set the enc-tkt-in-skey flag for user-to-user requests. */ + if (ctx->in_creds->second_ticket.length != 0) + extra_options |= KDC_OPT_ENC_TKT_IN_SKEY; + + /* Set the canonicalize flag for referral requests. */ + if (referral) + extra_options |= KDC_OPT_CANONICALIZE; + + /* + * Use the profile enctypes for referral requests, since we might get back + * a TGT. We'll ask again with context enctypes if we get the actual + * service ticket and it's not consistent with the context enctypes. + */ + if (referral) + context->use_conf_ktypes = TRUE; + ctx->tgs_in_creds = ctx->in_creds; + code = make_request(context, ctx, extra_options); + if (referral) + context->use_conf_ktypes = FALSE; + return code; +} + +/* Decode and decrypt a TGS reply, and set the reply_code or reply_creds field + * of ctx with the result. Also handle too-big errors. */ +static krb5_error_code +get_creds_from_tgs_reply(krb5_context context, krb5_tkt_creds_context ctx, + krb5_data *reply) +{ + krb5_error_code code; + + krb5_free_creds(context, ctx->reply_creds); + ctx->reply_creds = NULL; + code = krb5int_process_tgs_reply(context, ctx->fast_state, + reply, ctx->cur_tgt, ctx->kdcopt, + ctx->cur_tgt->addresses, NULL, + ctx->tgs_in_creds, ctx->timestamp, + ctx->nonce, ctx->subkey, NULL, NULL, + &ctx->reply_creds); + if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG) { + /* Instruct the caller to re-send the request with TCP. */ + code = set_caller_request(context, ctx); + if (code != 0) + return code; + return KRB5KRB_ERR_RESPONSE_TOO_BIG; + } + + /* Depending on our state, we may or may not be able to handle an error. + * For now, store it in the context and return success. */ + TRACE_TKT_CREDS_RESPONSE_CODE(context, code); + ctx->reply_code = code; + return 0; +} + +/* Add realm to ctx->realms_seen so that we can avoid revisiting it later. */ +static krb5_error_code +remember_realm(krb5_context context, krb5_tkt_creds_context ctx, + const krb5_data *realm) +{ + size_t len = 0; + krb5_data *new_list; + + if (ctx->realms_seen != NULL) { + for (len = 0; ctx->realms_seen[len].data != NULL; len++); + } + new_list = realloc(ctx->realms_seen, (len + 2) * sizeof(krb5_data)); + if (new_list == NULL) + return ENOMEM; + ctx->realms_seen = new_list; + new_list[len] = empty_data(); + new_list[len + 1] = empty_data(); + return krb5int_copy_data_contents(context, realm, &new_list[len]); +} + +/* Return TRUE if realm appears to ctx->realms_seen. */ +static krb5_boolean +seen_realm_before(krb5_context context, krb5_tkt_creds_context ctx, + const krb5_data *realm) +{ + size_t i; + + if (ctx->realms_seen != NULL) { + for (i = 0; ctx->realms_seen[i].data != NULL; i++) { + if (data_eq(ctx->realms_seen[i], *realm)) + return TRUE; + } + } + return FALSE; +} + +/***** STATE_COMPLETE *****/ + +/* Check and cache the desired credential when we receive it. Expects the + * received credential to be in ctx->reply_creds. */ +static krb5_error_code +complete(krb5_context context, krb5_tkt_creds_context ctx) +{ + TRACE_TKT_CREDS_COMPLETE(context, ctx->reply_creds->server); + + /* Put the requested server principal in the output creds. */ + krb5_free_principal(context, ctx->reply_creds->server); + ctx->reply_creds->server = ctx->req_server; + ctx->req_server = NULL; + + /* Note the authdata we asked for in the output creds. */ + ctx->reply_creds->authdata = ctx->authdata; + ctx->authdata = NULL; + + if (!(ctx->req_options & KRB5_GC_NO_STORE)) { + /* Try to cache the credential. */ + (void) krb5_cc_store_cred(context, ctx->ccache, ctx->reply_creds); + } + + ctx->state = STATE_COMPLETE; + return 0; +} + +/***** STATE_NON_REFERRAL *****/ + +/* Process the response to a non-referral request. */ +static krb5_error_code +step_non_referral(krb5_context context, krb5_tkt_creds_context ctx) +{ + /* No fallbacks if we didn't get a successful reply. */ + if (ctx->reply_code) + return ctx->reply_code; + + return complete(context, ctx); +} + +/* Make a non-referrals request for the desired service ticket. */ +static krb5_error_code +begin_non_referral(krb5_context context, krb5_tkt_creds_context ctx) +{ + ctx->state = STATE_NON_REFERRAL; + return make_request_for_service(context, ctx, FALSE); +} + +/***** STATE_REFERRALS *****/ + +/* Possibly try a non-referral request after a referral request failure. + * Expects ctx->reply_code to be set to the error from a referral request. */ +static krb5_error_code +try_fallback(krb5_context context, krb5_tkt_creds_context ctx) +{ + krb5_error_code code; + char **hrealms; + + /* Only fall back if our error was from the first referral request. */ + if (ctx->referral_count > 1) + return ctx->reply_code; + + /* If the request used a specified realm, make a non-referral request to + * that realm (in case it's a KDC which rejects KDC_OPT_CANONICALIZE). */ + if (!ctx->referral_req) + return begin_non_referral(context, ctx); + + if (ctx->server->length < 2) { + /* We need a type/host format principal to find a fallback realm. */ + return KRB5_ERR_HOST_REALM_UNKNOWN; + } + + /* We expect this to give exactly one answer (XXX clean up interface). */ + code = krb5_get_fallback_host_realm(context, &ctx->server->data[1], + &hrealms); + if (code != 0) + return code; + + /* If the fallback realm isn't any different, use the existing TGT. */ + if (data_eq_string(ctx->server->realm, hrealms[0])) { + krb5_free_host_realm(context, hrealms); + return begin_non_referral(context, ctx); + } + + /* Rewrite server->realm to be the fallback realm. */ + krb5_free_data_contents(context, &ctx->server->realm); + ctx->server->realm = string2data(hrealms[0]); + free(hrealms); + TRACE_TKT_CREDS_FALLBACK(context, &ctx->server->realm); + + /* Obtain a TGT for the new service realm. */ + ctx->getting_tgt_for = STATE_NON_REFERRAL; + return begin_get_tgt(context, ctx); +} + +/* Return true if context contains app-provided TGS enctypes and enctype is not + * one of them. */ +static krb5_boolean +wrong_enctype(krb5_context context, krb5_enctype enctype) +{ + size_t i; + + if (context->tgs_etypes == NULL) + return FALSE; + for (i = 0; context->tgs_etypes[i] != 0; i++) { + if (enctype == context->tgs_etypes[i]) + return FALSE; + } + return TRUE; +} + +/* Advance the referral request loop. */ +static krb5_error_code +step_referrals(krb5_context context, krb5_tkt_creds_context ctx) +{ + krb5_error_code code; + const krb5_data *referral_realm; + + /* Possibly try a non-referral fallback request on error. */ + if (ctx->reply_code != 0) + return try_fallback(context, ctx); + + /* Check if we got the ticket we asked for. Allow the KDC to canonicalize + * the realm. */ + if (krb5_principal_compare_any_realm(context, ctx->reply_creds->server, + ctx->server)) { + /* We didn't necessarily ask for it with the right enctypes. Try a + * non-referral request if so. */ + if (wrong_enctype(context, ctx->reply_creds->keyblock.enctype)) { + TRACE_TKT_CREDS_WRONG_ENCTYPE(context); + return begin_non_referral(context, ctx); + } + + return complete(context, ctx); + } + + /* Old versions of Active Directory can rewrite the server name instead of + * returning a referral. Try a non-referral query if we see this. */ + if (!IS_TGS_PRINC(ctx->reply_creds->server)) { + TRACE_TKT_CREDS_NON_TGT(context, ctx->reply_creds->server); + return begin_non_referral(context, ctx); + } + + /* Active Directory may return a TGT to the local realm. Try a + * non-referral query if we see this. */ + referral_realm = &ctx->reply_creds->server->data[1]; + if (data_eq(*referral_realm, ctx->cur_tgt->server->data[1])) { + TRACE_TKT_CREDS_SAME_REALM_TGT(context, referral_realm); + return begin_non_referral(context, ctx); + } + + if (ctx->referral_count == 1) { + /* The authdata in this TGT will be copied into subsequent TGTs or the + * final credentials, so we don't need to request it again. */ + krb5_free_authdata(context, ctx->in_creds->authdata); + ctx->in_creds->authdata = NULL; + } + + /* Give up if we've gotten too many referral TGTs. */ + if (ctx->referral_count++ >= KRB5_REFERRAL_MAXHOPS) + return KRB5_KDC_UNREACH; + + /* Check for referral loops. */ + if (seen_realm_before(context, ctx, referral_realm)) + return KRB5_KDC_UNREACH; + code = remember_realm(context, ctx, referral_realm); + if (code != 0) + return code; + + /* Use the referral TGT for the next request. */ + krb5_free_creds(context, ctx->cur_tgt); + ctx->cur_tgt = ctx->reply_creds; + ctx->reply_creds = NULL; + TRACE_TKT_CREDS_REFERRAL(context, ctx->cur_tgt->server); + + /* Rewrite the server realm to be the referral realm. */ + krb5_free_data_contents(context, &ctx->server->realm); + code = krb5int_copy_data_contents(context, referral_realm, + &ctx->server->realm); + if (code != 0) + return code; + + /* Generate the next referral request. */ + return make_request_for_service(context, ctx, TRUE); +} + +/* + * Begin the referrals request loop. Expects ctx->cur_tgt to be a TGT for + * ctx->realm->server. + */ +static krb5_error_code +begin_referrals(krb5_context context, krb5_tkt_creds_context ctx) +{ + ctx->state = STATE_REFERRALS; + ctx->referral_count = 1; + + /* Empty out the realms-seen list for loop checking. */ + krb5int_free_data_list(context, ctx->realms_seen); + ctx->realms_seen = NULL; + + /* Generate the first referral request. */ + return make_request_for_service(context, ctx, TRUE); +} + +/***** STATE_GET_TGT_OFFPATH *****/ + +/* + * Foreign TGT acquisition can happen either before the referrals loop, if the + * service principal had an explicitly specified foreign realm, or after it + * fails, if we wind up using the fallback realm. end_get_tgt() advances to + * the appropriate state depending on which we were doing. + */ +static krb5_error_code +end_get_tgt(krb5_context context, krb5_tkt_creds_context ctx) +{ + if (ctx->getting_tgt_for == STATE_REFERRALS) + return begin_referrals(context, ctx); + else + return begin_non_referral(context, ctx); +} + +/* + * We enter STATE_GET_TGT_OFFPATH from STATE_GET_TGT if we receive, from one of + * the KDCs in the expected path, a TGT for a realm not in the path. This may + * happen if the KDC has a different idea of the expected path than we do. If + * it happens, we repeatedly ask the KDC of the TGT we have for a destination + * realm TGT, until we get it, fail, or give up. + */ + +/* Advance the process of chasing off-path TGTs. */ +static krb5_error_code +step_get_tgt_offpath(krb5_context context, krb5_tkt_creds_context ctx) +{ + krb5_error_code code; + const krb5_data *tgt_realm; + + /* We have no fallback if the last request failed, so just give up. */ + if (ctx->reply_code != 0) + return ctx->reply_code; + + /* Verify that we got a TGT. */ + if (!IS_TGS_PRINC(ctx->reply_creds->server)) + return KRB5_KDCREP_MODIFIED; + + /* Use this tgt for the next request. */ + krb5_free_creds(context, ctx->cur_tgt); + ctx->cur_tgt = ctx->reply_creds; + ctx->reply_creds = NULL; + + /* Check if we've seen this realm before, and remember it. */ + tgt_realm = &ctx->cur_tgt->server->data[1]; + if (seen_realm_before(context, ctx, tgt_realm)) + return KRB5_KDC_UNREACH; + code = remember_realm(context, ctx, tgt_realm); + if (code != 0) + return code; + + if (data_eq(*tgt_realm, ctx->server->realm)) { + /* We received the server realm TGT we asked for. */ + TRACE_TKT_CREDS_TARGET_TGT_OFFPATH(context, ctx->cur_tgt->server); + return end_get_tgt(context, ctx); + } else if (ctx->offpath_count++ >= KRB5_REFERRAL_MAXHOPS) { + /* Time to give up. */ + return KRB5_KDCREP_MODIFIED; + } + + return make_request_for_tgt(context, ctx, &ctx->server->realm); +} + +/* Begin chasing off-path referrals, starting from ctx->cur_tgt. */ +static krb5_error_code +begin_get_tgt_offpath(krb5_context context, krb5_tkt_creds_context ctx) +{ + ctx->state = STATE_GET_TGT_OFFPATH; + ctx->offpath_count = 1; + return make_request_for_tgt(context, ctx, &ctx->server->realm); +} + +/***** STATE_GET_TGT *****/ + +/* + * To obtain a foreign TGT, we first construct a path of realms R1..Rn between + * the local realm and the target realm, using k5_client_realm_path(). Usually + * this path is based on the domain hierarchy, but it may be altered by + * configuration. + * + * We begin with cur_realm set to the local realm (R1) and next_realm set to + * the target realm (Rn). At each step, we check to see if we have a cached + * TGT for next_realm; if not, we ask cur_realm to give us a TGT for + * next_realm. If that fails, we decrement next_realm until we get a + * successful answer or reach cur_realm--in which case we've gotten as far as + * we can, and have to give up. If we do get back a TGT, it may or may not be + * for the realm we asked for, so we search for it in the path. The realm of + * the TGT we get back becomes cur_realm, and next_realm is reset to the target + * realm. Overall, this is an O(n^2) process in the length of the path, but + * the path length will generally be short and the process will usually end + * much faster than the worst case. + * + * In some cases we may get back a TGT for a realm not in the path. In that + * case we enter STATE_GET_TGT_OFFPATH. + */ + +/* + * Point *tgt_out at an allocated credentials structure containing a + * cross-realm TGT for realm retrieved from ctx->ccache. Accept any issuing + * realm (i.e. match only the service principal name). If the TGT is not found + * in the cache, return successfully but set *tgt_out to NULL. + */ +static krb5_error_code +get_cached_tgt(krb5_context context, krb5_tkt_creds_context ctx, + const krb5_data *realm, krb5_creds **tgt_out) +{ + krb5_creds mcreds; + krb5_error_code code; + krb5_principal tgtname = NULL; + krb5_flags flags = KRB5_TC_SUPPORTED_KTYPES | KRB5_TC_MATCH_SRV_NAMEONLY | + KRB5_TC_MATCH_TIMES; + krb5_timestamp now; + + *tgt_out = NULL; + + code = krb5_timeofday(context, &now); + if (code != 0) + return code; + + /* Construct the TGT principal name (the realm part doesn't matter). */ + code = krb5int_tgtname(context, realm, realm, &tgtname); + if (code != 0) + return code; + + /* Construct a matching cred for the ccache query. Look for unexpired + * entries since there could be more than one. */ + memset(&mcreds, 0, sizeof(mcreds)); + mcreds.client = ctx->client; + mcreds.server = tgtname; + mcreds.times.endtime = now; + + /* Fetch the TGT credential. */ + context->use_conf_ktypes = TRUE; + code = cache_get(context, ctx->ccache, flags, &mcreds, tgt_out); + context->use_conf_ktypes = FALSE; + krb5_free_principal(context, tgtname); + return (code == KRB5_CC_NOTFOUND || code != KRB5_CC_NOT_KTYPE) ? 0 : code; +} + +/* Point *tgt_out at an allocated credentials structure containing the local + * TGT retrieved from ctx->ccache. */ +static krb5_error_code +get_cached_local_tgt(krb5_context context, krb5_tkt_creds_context ctx, + krb5_creds **tgt_out) +{ + krb5_creds mcreds; + krb5_error_code code; + krb5_principal tgtname = NULL; + krb5_flags flags = KRB5_TC_SUPPORTED_KTYPES; + krb5_timestamp now; + krb5_creds *tgt; + + *tgt_out = NULL; + + code = krb5_timeofday(context, &now); + if (code != 0) + return code; + + /* Construct the principal name. */ + code = krb5int_tgtname(context, &ctx->start_realm, &ctx->start_realm, + &tgtname); + if (code != 0) + return code; + + /* Construct a matching cred for the ccache query. */ + memset(&mcreds, 0, sizeof(mcreds)); + mcreds.client = ctx->client; + mcreds.server = tgtname; + + /* Fetch the TGT credential. */ + context->use_conf_ktypes = TRUE; + code = cache_get(context, ctx->ccache, flags, &mcreds, &tgt); + context->use_conf_ktypes = FALSE; + krb5_free_principal(context, tgtname); + if (code) + return code; + + /* Check if the TGT is expired before bothering the KDC with it. */ + if (ts_after(now, tgt->times.endtime)) { + krb5_free_creds(context, tgt); + return KRB5KRB_AP_ERR_TKT_EXPIRED; + } + + *tgt_out = tgt; + return 0; +} + +/* Initialize the realm path fields for getting a TGT for + * ctx->server->realm. */ +static krb5_error_code +init_realm_path(krb5_context context, krb5_tkt_creds_context ctx) +{ + krb5_error_code code; + krb5_data *realm_path; + size_t nrealms; + + /* Get the client realm path and count its length. */ + code = k5_client_realm_path(context, &ctx->start_realm, + &ctx->server->realm, &realm_path); + if (code != 0) + return code; + for (nrealms = 0; realm_path[nrealms].data != NULL; nrealms++); + assert(nrealms > 1); + + /* Initialize the realm path fields in ctx. */ + krb5int_free_data_list(context, ctx->realm_path); + ctx->realm_path = realm_path; + ctx->last_realm = realm_path + nrealms - 1; + ctx->cur_realm = realm_path; + ctx->next_realm = ctx->last_realm; + return 0; +} + +/* Find realm within the portion of ctx->realm_path following + * ctx->cur_realm. Return NULL if it is not found. */ +static const krb5_data * +find_realm_in_path(krb5_context context, krb5_tkt_creds_context ctx, + const krb5_data *realm) +{ + const krb5_data *r; + + for (r = ctx->cur_realm + 1; r->data != NULL; r++) { + if (data_eq(*r, *realm)) + return r; + } + return NULL; +} + +/* + * Generate the next request in the path traversal. If a cached TGT for the + * target realm appeared in the ccache since we started the TGT acquisition + * process, this function may invoke end_get_tgt(). + */ +static krb5_error_code +get_tgt_request(krb5_context context, krb5_tkt_creds_context ctx) +{ + krb5_error_code code; + krb5_creds *cached_tgt; + + while (1) { + /* Check if we have a cached TGT for the target realm. */ + code = get_cached_tgt(context, ctx, ctx->next_realm, &cached_tgt); + if (code != 0) + return code; + if (cached_tgt != NULL) { + /* Advance the current realm and keep going. */ + TRACE_TKT_CREDS_CACHED_INTERMEDIATE_TGT(context, cached_tgt); + krb5_free_creds(context, ctx->cur_tgt); + ctx->cur_tgt = cached_tgt; + if (ctx->next_realm == ctx->last_realm) + return end_get_tgt(context, ctx); + ctx->cur_realm = ctx->next_realm; + ctx->next_realm = ctx->last_realm; + continue; + } + + return make_request_for_tgt(context, ctx, ctx->next_realm); + } +} + +/* Process a TGS reply and advance the path traversal to get a foreign TGT. */ +static krb5_error_code +step_get_tgt(krb5_context context, krb5_tkt_creds_context ctx) +{ + krb5_error_code code; + const krb5_data *tgt_realm, *path_realm; + + if (ctx->reply_code != 0) { + /* The last request failed. Try the next-closest realm to + * ctx->cur_realm. */ + ctx->next_realm--; + if (ctx->next_realm == ctx->cur_realm) { + /* We've tried all the realms we could and couldn't progress beyond + * ctx->cur_realm, so it's time to give up. */ + return ctx->reply_code; + } + TRACE_TKT_CREDS_CLOSER_REALM(context, ctx->next_realm); + } else { + /* Verify that we got a TGT. */ + if (!IS_TGS_PRINC(ctx->reply_creds->server)) + return KRB5_KDCREP_MODIFIED; + + /* Use this tgt for the next request regardless of what it is. */ + krb5_free_creds(context, ctx->cur_tgt); + ctx->cur_tgt = ctx->reply_creds; + ctx->reply_creds = NULL; + + /* Remember that we saw this realm. */ + tgt_realm = &ctx->cur_tgt->server->data[1]; + code = remember_realm(context, ctx, tgt_realm); + if (code != 0) + return code; + + /* See where we wound up on the path (or off it). */ + path_realm = find_realm_in_path(context, ctx, tgt_realm); + if (path_realm != NULL) { + /* Only cache the TGT if we asked for it, to avoid duplicates. */ + if (path_realm == ctx->next_realm) + (void)krb5_cc_store_cred(context, ctx->ccache, ctx->cur_tgt); + if (path_realm == ctx->last_realm) { + /* We received a TGT for the target realm. */ + TRACE_TKT_CREDS_TARGET_TGT(context, ctx->cur_tgt->server); + return end_get_tgt(context, ctx); + } else if (path_realm != NULL) { + /* We still have further to go; advance the traversal. */ + TRACE_TKT_CREDS_ADVANCE(context, tgt_realm); + ctx->cur_realm = path_realm; + ctx->next_realm = ctx->last_realm; + } + } else if (data_eq(*tgt_realm, ctx->start_realm)) { + /* We were referred back to the local realm, which is bad. */ + return KRB5_KDCREP_MODIFIED; + } else { + /* We went off the path; start the off-path chase. */ + TRACE_TKT_CREDS_OFFPATH(context, tgt_realm); + return begin_get_tgt_offpath(context, ctx); + } + } + + /* Generate the next request in the path traversal. */ + return get_tgt_request(context, ctx); +} + +/* + * Begin the process of getting a foreign TGT, either for the explicitly + * specified server realm or for the fallback realm. Expects that + * ctx->server->realm is the realm of the desired TGT, and that + * ctx->getting_tgt_for is the state we should advance to after we have the + * desired TGT. + */ +static krb5_error_code +begin_get_tgt(krb5_context context, krb5_tkt_creds_context ctx) +{ + krb5_error_code code; + krb5_creds *cached_tgt; + krb5_boolean is_local_service; + + ctx->state = STATE_GET_TGT; + + is_local_service = data_eq(ctx->start_realm, ctx->server->realm); + if (!is_local_service) { + /* See if we have a cached TGT for the server realm. */ + code = get_cached_tgt(context, ctx, &ctx->server->realm, &cached_tgt); + if (code != 0) + return code; + if (cached_tgt != NULL) { + TRACE_TKT_CREDS_CACHED_SERVICE_TGT(context, cached_tgt); + krb5_free_creds(context, ctx->cur_tgt); + ctx->cur_tgt = cached_tgt; + return end_get_tgt(context, ctx); + } + } + + /* Start with the local tgt. */ + krb5_free_creds(context, ctx->cur_tgt); + ctx->cur_tgt = NULL; + code = get_cached_local_tgt(context, ctx, &ctx->cur_tgt); + if (code != 0) + return code; + TRACE_TKT_CREDS_LOCAL_TGT(context, ctx->cur_tgt); + + if (is_local_service) + return end_get_tgt(context, ctx); + + /* Initialize the realm path. */ + code = init_realm_path(context, ctx); + if (code != 0) + return code; + + /* Empty out the realms-seen list for loop checking. */ + krb5int_free_data_list(context, ctx->realms_seen); + ctx->realms_seen = NULL; + + /* Generate the first request. */ + return get_tgt_request(context, ctx); +} + +/***** STATE_BEGIN *****/ + +/* + * Look for the desired credentials in the cache, if possible. If we find + * them, put them in ctx->reply_creds and advance the state to STATE_COMPLETE. + * Return successfully even if creds are not found, unless the caller only + * wanted cached creds. + */ +static krb5_error_code +check_cache(krb5_context context, krb5_tkt_creds_context ctx) +{ + krb5_error_code code; + krb5_creds req_in_creds; + + /* Check the cache for the originally requested server principal. */ + req_in_creds = *ctx->in_creds; + req_in_creds.server = ctx->req_server; + code = k5_get_cached_cred(context, ctx->req_options, ctx->ccache, + &req_in_creds, &ctx->reply_creds); + if (code == 0) { + ctx->state = STATE_COMPLETE; + return 0; + } + + /* Stop on unexpected cache errors. */ + if (code != KRB5_CC_NOTFOUND && code != KRB5_CC_NOT_KTYPE) + return code; + + /* Stop if the caller only wanted cached creds. */ + if (ctx->req_options & KRB5_GC_CACHED) + return code; + + return 0; +} + +/* Decide where to begin the acquisition process. */ +static krb5_error_code +begin(krb5_context context, krb5_tkt_creds_context ctx) +{ + krb5_error_code code; + + /* If the server realm is unspecified, start with the TGT realm. */ + ctx->referral_req = krb5_is_referral_realm(&ctx->server->realm); + if (ctx->referral_req) { + krb5_free_data_contents(context, &ctx->server->realm); + code = krb5int_copy_data_contents(context, &ctx->start_realm, + &ctx->server->realm); + TRACE_TKT_CREDS_REFERRAL_REALM(context, ctx->server); + if (code != 0) + return code; + } + + /* Obtain a TGT for the service realm. */ + ctx->getting_tgt_for = STATE_REFERRALS; + return begin_get_tgt(context, ctx); +} + +/***** API functions *****/ + +krb5_error_code KRB5_CALLCONV +krb5_tkt_creds_init(krb5_context context, krb5_ccache ccache, + krb5_creds *in_creds, krb5_flags options, + krb5_tkt_creds_context *pctx) +{ + krb5_error_code code; + krb5_tkt_creds_context ctx = NULL; + krb5_const_principal canonprinc; + + TRACE_TKT_CREDS(context, in_creds, ccache); + ctx = k5alloc(sizeof(*ctx), &code); + if (ctx == NULL) + goto cleanup; + + ctx->req_options = options; + ctx->req_kdcopt = 0; + if (options & KRB5_GC_CANONICALIZE) + ctx->req_kdcopt |= KDC_OPT_CANONICALIZE; + if (options & KRB5_GC_FORWARDABLE) + ctx->req_kdcopt |= KDC_OPT_FORWARDABLE; + if (options & KRB5_GC_NO_TRANSIT_CHECK) + ctx->req_kdcopt |= KDC_OPT_DISABLE_TRANSITED_CHECK; + + ctx->state = STATE_BEGIN; + + /* Copy the matching cred so we can modify it. Steal the copy of the + * service principal name to remember the original request server. */ + code = krb5_copy_creds(context, in_creds, &ctx->in_creds); + if (code != 0) + goto cleanup; + ctx->req_server = ctx->in_creds->server; + ctx->in_creds->server = NULL; + + /* Get the first canonicalization candidate for the requested server. */ + ctx->iter.princ = ctx->req_server; + + code = k5_canonprinc(context, &ctx->iter, &canonprinc); + if (code == 0 && canonprinc == NULL) + code = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + if (code != 0) + goto cleanup; + code = krb5_copy_principal(context, canonprinc, &ctx->in_creds->server); + if (code != 0) + goto cleanup; + + ctx->client = ctx->in_creds->client; + ctx->server = ctx->in_creds->server; + code = krb5_cc_dup(context, ccache, &ctx->ccache); + if (code != 0) + goto cleanup; + + /* Get the start realm from the cache config, defaulting to the client + * realm. */ + code = krb5_cc_get_config(context, ccache, NULL, "start_realm", + &ctx->start_realm); + if (code != 0) { + code = krb5int_copy_data_contents(context, &ctx->client->realm, + &ctx->start_realm); + if (code != 0) + goto cleanup; + } + + code = krb5_copy_authdata(context, in_creds->authdata, &ctx->authdata); + if (code != 0) + goto cleanup; + + *pctx = ctx; + ctx = NULL; + +cleanup: + krb5_tkt_creds_free(context, ctx); + return code; +} + +krb5_error_code KRB5_CALLCONV +krb5_tkt_creds_get_creds(krb5_context context, krb5_tkt_creds_context ctx, + krb5_creds *creds) +{ + if (ctx->state != STATE_COMPLETE) + return KRB5_NO_TKT_SUPPLIED; + return k5_copy_creds_contents(context, ctx->reply_creds, creds); +} + +krb5_error_code KRB5_CALLCONV +krb5_tkt_creds_get_times(krb5_context context, krb5_tkt_creds_context ctx, + krb5_ticket_times *times) +{ + if (ctx->state != STATE_COMPLETE) + return KRB5_NO_TKT_SUPPLIED; + *times = ctx->reply_creds->times; + return 0; +} + +void KRB5_CALLCONV +krb5_tkt_creds_free(krb5_context context, krb5_tkt_creds_context ctx) +{ + if (ctx == NULL) + return; + krb5int_fast_free_state(context, ctx->fast_state); + krb5_free_creds(context, ctx->in_creds); + free_canonprinc(&ctx->iter); + krb5_cc_close(context, ctx->ccache); + krb5_free_data_contents(context, &ctx->start_realm); + krb5_free_principal(context, ctx->req_server); + krb5_free_authdata(context, ctx->authdata); + krb5_free_creds(context, ctx->cur_tgt); + krb5int_free_data_list(context, ctx->realms_seen); + krb5_free_principal(context, ctx->tgt_princ); + krb5_free_keyblock(context, ctx->subkey); + krb5_free_data_contents(context, &ctx->previous_request); + krb5int_free_data_list(context, ctx->realm_path); + krb5_free_creds(context, ctx->reply_creds); + free(ctx); +} + +krb5_error_code KRB5_CALLCONV +krb5_tkt_creds_get(krb5_context context, krb5_tkt_creds_context ctx) +{ + krb5_error_code code; + krb5_data request = empty_data(), reply = empty_data(); + krb5_data realm = empty_data(); + unsigned int flags = 0; + int tcp_only = 0, use_primary; + + for (;;) { + /* Get the next request and realm. Turn on TCP if necessary. */ + code = krb5_tkt_creds_step(context, ctx, &reply, &request, &realm, + &flags); + if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !tcp_only) { + TRACE_TKT_CREDS_RETRY_TCP(context); + tcp_only = 1; + } else if (code != 0 || !(flags & KRB5_TKT_CREDS_STEP_FLAG_CONTINUE)) + break; + krb5_free_data_contents(context, &reply); + + /* Send it to a KDC for the appropriate realm. */ + use_primary = 0; + code = krb5_sendto_kdc(context, &request, &realm, + &reply, &use_primary, tcp_only); + if (code != 0) + break; + + krb5_free_data_contents(context, &request); + krb5_free_data_contents(context, &realm); + } + + krb5_free_data_contents(context, &request); + krb5_free_data_contents(context, &reply); + krb5_free_data_contents(context, &realm); + return code; +} + +krb5_error_code KRB5_CALLCONV +krb5_tkt_creds_step(krb5_context context, krb5_tkt_creds_context ctx, + krb5_data *in, krb5_data *out, krb5_data *realm, + unsigned int *flags) +{ + krb5_error_code code; + krb5_boolean no_input = (in == NULL || in->length == 0); + krb5_const_principal canonprinc; + + *out = empty_data(); + *realm = empty_data(); + *flags = 0; + + /* We should receive an empty input on the first step only, and should not + * get called after completion. */ + if (no_input != (ctx->state == STATE_BEGIN) || + ctx->state == STATE_COMPLETE) + return EINVAL; + + if (ctx->state == STATE_BEGIN) { + code = check_cache(context, ctx); + if (code != 0 || ctx->state == STATE_COMPLETE) + return code; + } + + ctx->caller_out = out; + ctx->caller_realm = realm; + ctx->caller_flags = flags; + + if (!no_input) { + /* Convert the input token into a credential and store it in ctx. */ + code = get_creds_from_tgs_reply(context, ctx, in); + if (code != 0) + return code; + } + + if (ctx->state == STATE_BEGIN) + code = begin(context, ctx); + else if (ctx->state == STATE_GET_TGT) + code = step_get_tgt(context, ctx); + else if (ctx->state == STATE_GET_TGT_OFFPATH) + code = step_get_tgt_offpath(context, ctx); + else if (ctx->state == STATE_REFERRALS) + code = step_referrals(context, ctx); + else if (ctx->state == STATE_NON_REFERRAL) + code = step_non_referral(context, ctx); + else + code = EINVAL; + + /* Terminate on success or most errors. */ + if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) + return code; + + /* Restart with the next server principal canonicalization candidate. */ + code = k5_canonprinc(context, &ctx->iter, &canonprinc); + if (code) + return code; + if (canonprinc == NULL) + return KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + krb5_free_principal(context, ctx->in_creds->server); + code = krb5_copy_principal(context, canonprinc, &ctx->in_creds->server); + ctx->server = ctx->in_creds->server; + return begin(context, ctx); +} + +krb5_error_code KRB5_CALLCONV +krb5_get_credentials(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_creds **out_creds) +{ + krb5_error_code code; + krb5_creds *ncreds = NULL; + krb5_tkt_creds_context ctx = NULL; + + *out_creds = NULL; + + /* If S4U2Proxy is requested, use the synchronous implementation in + * s4u_creds.c. */ + if (options & KRB5_GC_CONSTRAINED_DELEGATION) { + return k5_get_proxy_cred_from_kdc(context, options, ccache, in_creds, + out_creds); + } + + /* Allocate a container. */ + ncreds = k5alloc(sizeof(*ncreds), &code); + if (ncreds == NULL) + goto cleanup; + + /* Make and execute a krb5_tkt_creds context to get the credential. */ + code = krb5_tkt_creds_init(context, ccache, in_creds, options, &ctx); + if (code != 0) + goto cleanup; + code = krb5_tkt_creds_get(context, ctx); + if (code != 0) + goto cleanup; + code = krb5_tkt_creds_get_creds(context, ctx, ncreds); + if (code != 0) + goto cleanup; + + *out_creds = ncreds; + ncreds = NULL; + +cleanup: + krb5_free_creds(context, ncreds); + krb5_tkt_creds_free(context, ctx); + return code; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/get_etype_info.c b/krb5-1.21.3/src/lib/krb5/krb/get_etype_info.c new file mode 100644 index 00000000..1a75b9fc --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/get_etype_info.c @@ -0,0 +1,180 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/get_etype_salt_s2kp.c - Retrieve enctype, salt and s2kparams */ +/* + * Copyright (C) 2017 by Cloudera, Inc. + * 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. + */ + +#include "k5-int.h" +#include "fast.h" +#include "init_creds_ctx.h" + +/* Extract etype info from the error message pkt into icc, if it is a + * PREAUTH_REQUIRED error. Otherwise return the protocol error code. */ +static krb5_error_code +get_from_error(krb5_context context, krb5_data *pkt, + krb5_init_creds_context icc) +{ + krb5_error *error = NULL; + krb5_pa_data **padata = NULL; + krb5_error_code ret; + + ret = decode_krb5_error(pkt, &error); + if (ret) + return ret; + ret = krb5int_fast_process_error(context, icc->fast_state, &error, &padata, + NULL); + if (ret) + goto cleanup; + if (error->error != KDC_ERR_PREAUTH_REQUIRED) { + ret = ERROR_TABLE_BASE_krb5 + error->error; + goto cleanup; + } + ret = k5_get_etype_info(context, icc, padata); + +cleanup: + krb5_free_pa_data(context, padata); + krb5_free_error(context, error); + return ret; +} + +/* Extract etype info from the AS reply pkt into icc. */ +static krb5_error_code +get_from_reply(krb5_context context, krb5_data *pkt, + krb5_init_creds_context icc) +{ + krb5_kdc_rep *asrep = NULL; + krb5_error_code ret; + krb5_keyblock *strengthen_key = NULL; + + ret = decode_krb5_as_rep(pkt, &asrep); + if (ret) + return ret; + ret = krb5int_fast_process_response(context, icc->fast_state, asrep, + &strengthen_key); + if (ret) + goto cleanup; + ret = k5_get_etype_info(context, icc, asrep->padata); + +cleanup: + krb5_free_kdc_rep(context, asrep); + krb5_free_keyblock(context, strengthen_key); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_etype_info(krb5_context context, krb5_principal principal, + krb5_get_init_creds_opt *opt, krb5_enctype *enctype_out, + krb5_data *salt_out, krb5_data *s2kparams_out) +{ + krb5_init_creds_context icc = NULL; + krb5_data reply = empty_data(), req = empty_data(), realm = empty_data(); + krb5_data salt = empty_data(), s2kparams = empty_data(); + unsigned int flags; + int primary, tcp_only; + krb5_error_code ret; + + *enctype_out = ENCTYPE_NULL; + *salt_out = empty_data(); + *s2kparams_out = empty_data(); + + /* Create an initial creds context and get the initial request packet. */ + ret = krb5_init_creds_init(context, principal, NULL, NULL, 0, opt, &icc); + if (ret) + goto cleanup; + ret = krb5_init_creds_step(context, icc, &reply, &req, &realm, &flags); + if (ret) + goto cleanup; + if (flags != KRB5_INIT_CREDS_STEP_FLAG_CONTINUE) { + ret = KRB5KRB_AP_ERR_MSG_TYPE; + goto cleanup; + } + + /* Send the packet (possibly once with UDP and again with TCP). */ + tcp_only = 0; + for (;;) { + primary = 0; + ret = krb5_sendto_kdc(context, &req, &realm, &reply, &primary, + tcp_only); + if (ret) + goto cleanup; + + icc->etype = ENCTYPE_NULL; + if (krb5_is_krb_error(&reply)) { + ret = get_from_error(context, &reply, icc); + if (ret) { + if (!tcp_only && ret == KRB5KRB_ERR_RESPONSE_TOO_BIG) { + tcp_only = 1; + krb5_free_data_contents(context, &reply); + continue; + } + goto cleanup; + } + } else if (krb5_is_as_rep(&reply)) { + ret = get_from_reply(context, &reply, icc); + if (ret) + goto cleanup; + } else { + ret = KRB5KRB_AP_ERR_MSG_TYPE; + goto cleanup; + } + break; + } + + /* If we found no etype-info, return successfully with all null values. */ + if (icc->etype == ENCTYPE_NULL) + goto cleanup; + + if (icc->default_salt) + ret = krb5_principal2salt(context, principal, &salt); + else if (icc->salt.length > 0) + ret = krb5int_copy_data_contents(context, &icc->salt, &salt); + if (ret) + goto cleanup; + + if (icc->s2kparams.length > 0) { + ret = krb5int_copy_data_contents(context, &icc->s2kparams, &s2kparams); + if (ret) + goto cleanup; + } + + *salt_out = salt; + *s2kparams_out = s2kparams; + *enctype_out = icc->etype; + salt = empty_data(); + s2kparams = empty_data(); + +cleanup: + krb5_free_data_contents(context, &req); + krb5_free_data_contents(context, &reply); + krb5_free_data_contents(context, &realm); + krb5_free_data_contents(context, &salt); + krb5_free_data_contents(context, &s2kparams); + krb5_init_creds_free(context, icc); + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/get_in_tkt.c b/krb5-1.21.3/src/lib/krb5/krb/get_in_tkt.c new file mode 100644 index 00000000..ea089f0f --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/get_in_tkt.c @@ -0,0 +1,2095 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/get_in_tkt.c */ +/* + * Copyright 1990,1991, 2003, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "os-proto.h" +#include "fast.h" +#include "init_creds_ctx.h" + +/* some typedef's for the function args to make things look a bit cleaner */ + +static krb5_error_code make_preauth_list (krb5_context, + krb5_preauthtype *, + int, krb5_pa_data ***); +static krb5_error_code sort_krb5_padata_sequence(krb5_context context, + krb5_data *realm, + krb5_pa_data **padata); + +/* + * Decrypt the AS reply in ctx, populating ctx->reply->enc_part2. If + * strengthen_key is not null, combine it with the reply key as specified in + * RFC 6113 section 5.4.3. Place the key used in *key_out. + */ +static krb5_error_code +decrypt_as_reply(krb5_context context, krb5_init_creds_context ctx, + const krb5_keyblock *strengthen_key, krb5_keyblock *key_out) +{ + krb5_error_code ret; + krb5_keyblock key; + krb5_responder_fn responder; + void *responder_data; + + memset(key_out, 0, sizeof(*key_out)); + memset(&key, 0, sizeof(key)); + + if (ctx->as_key.length) { + /* The reply key was computed or replaced during preauth processing; + * try it. */ + TRACE_INIT_CREDS_AS_KEY_PREAUTH(context, &ctx->as_key); + ret = krb5int_fast_reply_key(context, strengthen_key, &ctx->as_key, + &key); + if (ret) + return ret; + ret = krb5_kdc_rep_decrypt_proc(context, &key, NULL, ctx->reply); + if (!ret) { + *key_out = key; + return 0; + } + krb5_free_keyblock_contents(context, &key); + TRACE_INIT_CREDS_PREAUTH_DECRYPT_FAIL(context, ret); + + /* + * For two reasons, we fall back to trying or retrying the gak_fct if + * this fails: + * + * 1. The KDC might encrypt the reply using a different enctype than + * the AS key we computed during preauth. + * + * 2. For 1.1.1 and prior KDC's, when SAM is used with USE_SAD_AS_KEY, + * the AS-REP is encrypted in the client long-term key instead of + * the SAD. + * + * The gak_fct for krb5_get_init_creds_with_password() caches the + * password, so this fallback does not result in a second password + * prompt. + */ + } else { + /* + * No AS key was computed during preauth processing, perhaps because + * preauth was not used. If the caller supplied a responder callback, + * possibly invoke it before calling the gak_fct for real. + */ + k5_gic_opt_get_responder(ctx->opt, &responder, &responder_data); + if (responder != NULL) { + /* Indicate a need for the AS key by calling the gak_fct with a + * NULL as_key. */ + ret = ctx->gak_fct(context, ctx->request->client, ctx->etype, NULL, + NULL, NULL, NULL, NULL, ctx->gak_data, + ctx->rctx.items); + if (ret) + return ret; + + /* If that produced a responder question, invoke the responder. */ + if (!k5_response_items_empty(ctx->rctx.items)) { + ret = (*responder)(context, responder_data, &ctx->rctx); + if (ret) + return ret; + } + } + } + + /* Compute or re-compute the AS key, prompting for the password if + * necessary. */ + TRACE_INIT_CREDS_GAK(context, &ctx->salt, &ctx->s2kparams); + ret = ctx->gak_fct(context, ctx->request->client, + ctx->reply->enc_part.enctype, ctx->prompter, + ctx->prompter_data, &ctx->salt, &ctx->s2kparams, + &ctx->as_key, ctx->gak_data, ctx->rctx.items); + if (ret) + return ret; + TRACE_INIT_CREDS_AS_KEY_GAK(context, &ctx->as_key); + + ret = krb5int_fast_reply_key(context, strengthen_key, &ctx->as_key, &key); + if (ret) + return ret; + ret = krb5_kdc_rep_decrypt_proc(context, &key, NULL, ctx->reply); + if (ret) { + krb5_free_keyblock_contents(context, &key); + return ret; + } + + *key_out = key; + return 0; +} + +/** + * Fully anonymous replies include a pa_pkinit_kx padata type including the KDC + * contribution key. This routine confirms that the session key is of the + * right form for fully anonymous requests. It is here rather than in the + * preauth code because the session key cannot be verified until the AS reply + * is decrypted and the preauth code all runs before the AS reply is decrypted. + */ +static krb5_error_code +verify_anonymous( krb5_context context, krb5_kdc_req *request, + krb5_kdc_rep *reply, krb5_keyblock *as_key) +{ + krb5_error_code ret = 0; + krb5_pa_data *pa; + krb5_data scratch; + krb5_keyblock *kdc_key = NULL, *expected = NULL; + krb5_enc_data *enc = NULL; + krb5_keyblock *session = reply->enc_part2->session; + + if (!krb5_principal_compare_any_realm(context, request->client, + krb5_anonymous_principal())) + return 0; /* Only applies to fully anonymous */ + pa = krb5int_find_pa_data(context, reply->padata, KRB5_PADATA_PKINIT_KX); + if (pa == NULL) + goto verification_error; + scratch.length = pa->length; + scratch.data = (char *) pa->contents; + ret = decode_krb5_enc_data( &scratch, &enc); + if (ret) + goto cleanup; + scratch.data = k5alloc(enc->ciphertext.length, &ret); + if (ret) + goto cleanup; + scratch.length = enc->ciphertext.length; + ret = krb5_c_decrypt(context, as_key, KRB5_KEYUSAGE_PA_PKINIT_KX, + NULL /*cipherstate*/, enc, &scratch); + if (ret) { + free(scratch.data); + goto cleanup; + } + ret = decode_krb5_encryption_key( &scratch, &kdc_key); + zap(scratch.data, scratch.length); + free(scratch.data); + if (ret) + goto cleanup; + ret = krb5_c_fx_cf2_simple(context, kdc_key, "PKINIT", + as_key, "KEYEXCHANGE", &expected); + if (ret) + goto cleanup; + if ((expected->enctype != session->enctype) || + (expected->length != session->length) || + (memcmp(expected->contents, session->contents, expected->length) != 0)) + goto verification_error; +cleanup: + if (kdc_key) + krb5_free_keyblock(context, kdc_key); + if (expected) + krb5_free_keyblock(context, expected); + if (enc) + krb5_free_enc_data(context, enc); + return ret; +verification_error: + ret = KRB5_KDCREP_MODIFIED; + k5_setmsg(context, ret, + _("Reply has wrong form of session key for anonymous request")); + goto cleanup; +} + +static krb5_error_code +verify_as_reply(krb5_context context, + krb5_timestamp time_now, + krb5_kdc_req *request, + krb5_kdc_rep *as_reply) +{ + krb5_error_code retval; + int canon_req; + int canon_ok; + krb5_timestamp time_offset; + + /* check the contents for sanity: */ + if (!as_reply->enc_part2->times.starttime) + as_reply->enc_part2->times.starttime = + as_reply->enc_part2->times.authtime; + + /* + * We only allow the AS-REP server name to be changed if the + * caller set the canonicalize flag (or requested an enterprise + * principal) and we requested (and received) a TGT. + */ + canon_req = ((request->kdc_options & KDC_OPT_CANONICALIZE) != 0) || + request->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL || + (request->kdc_options & KDC_OPT_REQUEST_ANONYMOUS); + if (canon_req) { + canon_ok = IS_TGS_PRINC(request->server) && + IS_TGS_PRINC(as_reply->enc_part2->server); + } else + canon_ok = 0; + + if ((!canon_ok && + !krb5_principal_compare(context, as_reply->enc_part2->server, request->server)) + || (!canon_req && !krb5_principal_compare(context, as_reply->client, request->client)) + || !krb5_principal_compare(context, as_reply->enc_part2->server, as_reply->ticket->server) + || (request->nonce != as_reply->enc_part2->nonce) + /* XXX check for extraneous flags */ + /* XXX || (!krb5_addresses_compare(context, addrs, as_reply->enc_part2->caddrs)) */ + || ((request->kdc_options & KDC_OPT_POSTDATED) && + (request->from != 0) && + (request->from != as_reply->enc_part2->times.starttime)) + || ((request->till != 0) && + ts_after(as_reply->enc_part2->times.endtime, request->till)) + || ((request->kdc_options & KDC_OPT_RENEWABLE) && + (request->rtime != 0) && + ts_after(as_reply->enc_part2->times.renew_till, request->rtime)) + || ((request->kdc_options & KDC_OPT_RENEWABLE_OK) && + !(request->kdc_options & KDC_OPT_RENEWABLE) && + (as_reply->enc_part2->flags & KDC_OPT_RENEWABLE) && + (request->till != 0) && + ts_after(as_reply->enc_part2->times.renew_till, request->till)) + ) { + return KRB5_KDCREP_MODIFIED; + } + + if (context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) { + time_offset = ts_delta(as_reply->enc_part2->times.authtime, time_now); + retval = krb5_set_time_offsets(context, time_offset, 0); + if (retval) + return retval; + } else { + if ((request->from == 0) && + !ts_within(as_reply->enc_part2->times.starttime, time_now, + context->clockskew)) + return (KRB5_KDCREP_SKEW); + } + return 0; +} + +static krb5_error_code +stash_as_reply(krb5_context context, + krb5_kdc_rep *as_reply, + krb5_creds * creds, + krb5_ccache ccache) +{ + krb5_error_code retval; + krb5_data * packet; + krb5_principal client; + krb5_principal server; + + client = NULL; + server = NULL; + + if (!creds->client) + if ((retval = krb5_copy_principal(context, as_reply->client, &client))) + goto cleanup; + + if (!creds->server) + if ((retval = krb5_copy_principal(context, as_reply->enc_part2->server, + &server))) + goto cleanup; + + /* fill in the credentials */ + if ((retval = krb5_copy_keyblock_contents(context, + as_reply->enc_part2->session, + &creds->keyblock))) + goto cleanup; + + creds->times = as_reply->enc_part2->times; + creds->is_skey = FALSE; /* this is an AS_REQ, so cannot + be encrypted in skey */ + creds->ticket_flags = as_reply->enc_part2->flags; + if ((retval = krb5_copy_addresses(context, as_reply->enc_part2->caddrs, + &creds->addresses))) + goto cleanup; + + creds->second_ticket.length = 0; + creds->second_ticket.data = 0; + + if ((retval = encode_krb5_ticket(as_reply->ticket, &packet))) + goto cleanup; + + creds->ticket = *packet; + free(packet); + + /* store it in the ccache! */ + if (ccache) + if ((retval = krb5_cc_store_cred(context, ccache, creds))) + goto cleanup; + + if (!creds->client) + creds->client = client; + if (!creds->server) + creds->server = server; + +cleanup: + if (retval) { + if (client) + krb5_free_principal(context, client); + if (server) + krb5_free_principal(context, server); + if (creds->keyblock.contents) { + memset(creds->keyblock.contents, 0, + creds->keyblock.length); + free(creds->keyblock.contents); + creds->keyblock.contents = 0; + creds->keyblock.length = 0; + } + if (creds->ticket.data) { + free(creds->ticket.data); + creds->ticket.data = 0; + } + if (creds->addresses) { + krb5_free_addresses(context, creds->addresses); + creds->addresses = 0; + } + } + return (retval); +} + +static krb5_error_code +make_preauth_list(krb5_context context, + krb5_preauthtype * ptypes, + int nptypes, + krb5_pa_data *** ret_list) +{ + krb5_preauthtype * ptypep; + krb5_pa_data ** preauthp; + int i; + + if (nptypes < 0) { + for (nptypes=0, ptypep = ptypes; *ptypep; ptypep++, nptypes++) + ; + } + + /* allocate space for a NULL to terminate the list */ + + if ((preauthp = + (krb5_pa_data **) malloc((nptypes+1)*sizeof(krb5_pa_data *))) == NULL) + return(ENOMEM); + + for (i=0; i=0; i--) + free(preauthp[i]); + free(preauthp); + return (ENOMEM); + } + preauthp[i]->magic = KV5M_PA_DATA; + preauthp[i]->pa_type = ptypes[i]; + preauthp[i]->length = 0; + preauthp[i]->contents = 0; + } + + /* fill in the terminating NULL */ + + preauthp[nptypes] = NULL; + + *ret_list = preauthp; + return 0; +} + +#define MAX_IN_TKT_LOOPS 16 + +/* Sort a pa_data sequence so that types named in the "preferred_preauth_types" + * libdefaults entry are listed before any others. */ +static krb5_error_code +sort_krb5_padata_sequence(krb5_context context, krb5_data *realm, + krb5_pa_data **padata) +{ + int i, j, base; + krb5_error_code ret; + const char *p; + long l; + char *q, *preauth_types = NULL; + krb5_pa_data *tmp; + int need_free_string = 1; + + if ((padata == NULL) || (padata[0] == NULL)) { + return 0; + } + + ret = krb5int_libdefault_string(context, realm, KRB5_CONF_PREFERRED_PREAUTH_TYPES, + &preauth_types); + if ((ret != 0) || (preauth_types == NULL)) { + /* Try to use PKINIT first. */ + preauth_types = "17, 16, 15, 14"; + need_free_string = 0; + } + +#ifdef DEBUG + fprintf (stderr, "preauth data types before sorting:"); + for (i = 0; padata[i]; i++) { + fprintf (stderr, " %d", padata[i]->pa_type); + } + fprintf (stderr, "\n"); +#endif + + base = 0; + for (p = preauth_types; *p != '\0';) { + /* skip whitespace to find an entry */ + p += strspn(p, ", "); + if (*p != '\0') { + /* see if we can extract a number */ + l = strtol(p, &q, 10); + if ((q != NULL) && (q > p)) { + /* got a valid number; search for a matching entry */ + for (i = base; padata[i] != NULL; i++) { + /* bubble the matching entry to the front of the list */ + if (padata[i]->pa_type == l) { + tmp = padata[i]; + for (j = i; j > base; j--) + padata[j] = padata[j - 1]; + padata[base] = tmp; + base++; + break; + } + } + p = q; + } else { + break; + } + } + } + if (need_free_string) + free(preauth_types); + +#ifdef DEBUG + fprintf (stderr, "preauth data types after sorting:"); + for (i = 0; padata[i]; i++) + fprintf (stderr, " %d", padata[i]->pa_type); + fprintf (stderr, "\n"); +#endif + + return 0; +} + +static krb5_error_code +build_in_tkt_name(krb5_context context, + const char *in_tkt_service, + krb5_const_principal client, + krb5_principal *server_out) +{ + krb5_error_code ret; + krb5_principal server = NULL; + + *server_out = NULL; + + if (in_tkt_service) { + ret = krb5_parse_name_flags(context, in_tkt_service, + KRB5_PRINCIPAL_PARSE_IGNORE_REALM, + &server); + if (ret) + return ret; + krb5_free_data_contents(context, &server->realm); + ret = krb5int_copy_data_contents(context, &client->realm, + &server->realm); + if (ret) { + krb5_free_principal(context, server); + return ret; + } + } else { + ret = krb5_build_principal_ext(context, &server, + client->realm.length, + client->realm.data, + KRB5_TGS_NAME_SIZE, + KRB5_TGS_NAME, + client->realm.length, + client->realm.data, + 0); + if (ret) + return ret; + } + + *server_out = server; + return 0; +} + +void KRB5_CALLCONV +krb5_init_creds_free(krb5_context context, + krb5_init_creds_context ctx) +{ + if (ctx == NULL) + return; + + k5_response_items_free(ctx->rctx.items); + free(ctx->in_tkt_service); + zapfree(ctx->gakpw.storage.data, ctx->gakpw.storage.length); + k5_preauth_request_context_fini(context, ctx); + krb5_free_error(context, ctx->err_reply); + krb5_free_pa_data(context, ctx->err_padata); + krb5_free_cred_contents(context, &ctx->cred); + krb5_free_kdc_req(context, ctx->request); + krb5_free_kdc_rep(context, ctx->reply); + krb5_free_data(context, ctx->outer_request_body); + krb5_free_data(context, ctx->inner_request_body); + krb5_free_data(context, ctx->encoded_previous_request); + krb5int_fast_free_state(context, ctx->fast_state); + krb5_free_pa_data(context, ctx->optimistic_padata); + krb5_free_pa_data(context, ctx->method_padata); + krb5_free_pa_data(context, ctx->more_padata); + krb5_free_data_contents(context, &ctx->salt); + krb5_free_data_contents(context, &ctx->s2kparams); + krb5_free_keyblock_contents(context, &ctx->as_key); + k5_json_release(ctx->cc_config_in); + k5_json_release(ctx->cc_config_out); + free(ctx); +} + +krb5_error_code +k5_init_creds_get(krb5_context context, krb5_init_creds_context ctx, + int *use_primary) +{ + krb5_error_code code; + krb5_data request; + krb5_data reply; + krb5_data realm; + unsigned int flags = 0; + int tcp_only = 0, primary = *use_primary; + + request.length = 0; + request.data = NULL; + reply.length = 0; + reply.data = NULL; + realm.length = 0; + realm.data = NULL; + + for (;;) { + code = krb5_init_creds_step(context, + ctx, + &reply, + &request, + &realm, + &flags); + if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !tcp_only) { + TRACE_INIT_CREDS_RETRY_TCP(context); + tcp_only = 1; + } else if (code != 0 || !(flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE)) + break; + + krb5_free_data_contents(context, &reply); + + primary = *use_primary; + code = krb5_sendto_kdc(context, &request, &realm, + &reply, &primary, tcp_only); + if (code != 0) + break; + + krb5_free_data_contents(context, &request); + krb5_free_data_contents(context, &realm); + } + + krb5_free_data_contents(context, &request); + krb5_free_data_contents(context, &reply); + krb5_free_data_contents(context, &realm); + + *use_primary = primary; + return code; +} + +/* Heimdal API */ +krb5_error_code KRB5_CALLCONV +krb5_init_creds_get(krb5_context context, + krb5_init_creds_context ctx) +{ + int use_primary = 0; + + return k5_init_creds_get(context, ctx, &use_primary); +} + +krb5_error_code KRB5_CALLCONV +krb5_init_creds_get_creds(krb5_context context, + krb5_init_creds_context ctx, + krb5_creds *creds) +{ + if (!ctx->complete) + return KRB5_NO_TKT_SUPPLIED; + + return k5_copy_creds_contents(context, &ctx->cred, creds); +} + +krb5_error_code KRB5_CALLCONV +krb5_init_creds_get_times(krb5_context context, + krb5_init_creds_context ctx, + krb5_ticket_times *times) +{ + if (!ctx->complete) + return KRB5_NO_TKT_SUPPLIED; + + *times = ctx->cred.times; + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_init_creds_get_error(krb5_context context, + krb5_init_creds_context ctx, + krb5_error **error) +{ + krb5_error_code code; + krb5_error *ret = NULL; + + *error = NULL; + + if (ctx->err_reply == NULL) + return 0; + + ret = k5alloc(sizeof(*ret), &code); + if (code != 0) + goto cleanup; + + ret->magic = KV5M_ERROR; + ret->ctime = ctx->err_reply->ctime; + ret->cusec = ctx->err_reply->cusec; + ret->susec = ctx->err_reply->susec; + ret->stime = ctx->err_reply->stime; + ret->error = ctx->err_reply->error; + + if (ctx->err_reply->client != NULL) { + code = krb5_copy_principal(context, ctx->err_reply->client, + &ret->client); + if (code != 0) + goto cleanup; + } + + code = krb5_copy_principal(context, ctx->err_reply->server, &ret->server); + if (code != 0) + goto cleanup; + + code = krb5int_copy_data_contents(context, &ctx->err_reply->text, + &ret->text); + if (code != 0) + goto cleanup; + + code = krb5int_copy_data_contents(context, &ctx->err_reply->e_data, + &ret->e_data); + if (code != 0) + goto cleanup; + + *error = ret; + +cleanup: + if (code != 0) + krb5_free_error(context, ret); + + return code; +} + +/* Return the current time, possibly using the offset from a previously + * received preauth-required error. */ +krb5_error_code +k5_init_creds_current_time(krb5_context context, krb5_init_creds_context ctx, + krb5_boolean allow_unauth, krb5_timestamp *time_out, + krb5_int32 *usec_out) +{ + if (ctx->pa_offset_state != NO_OFFSET && + (allow_unauth || ctx->pa_offset_state == AUTH_OFFSET) && + (context->library_options & KRB5_LIBOPT_SYNC_KDCTIME)) { + /* Use the offset we got from a preauth-required error. */ + return k5_time_with_offset(ctx->pa_offset, ctx->pa_offset_usec, + time_out, usec_out); + } else { + /* Use the time offset from the context, or no offset. */ + return krb5_us_timeofday(context, time_out, usec_out); + } +} + +/* Set the timestamps for ctx->request based on the desired lifetimes. */ +static krb5_error_code +set_request_times(krb5_context context, krb5_init_creds_context ctx) +{ + krb5_error_code code; + krb5_timestamp from, now; + krb5_int32 now_ms; + + code = k5_init_creds_current_time(context, ctx, TRUE, &now, &now_ms); + if (code != 0) + return code; + + /* Omit request start time unless the caller explicitly asked for one. */ + from = ts_incr(now, ctx->start_time); + if (ctx->start_time != 0) + ctx->request->from = from; + + ctx->request->till = ts_incr(from, ctx->tkt_life); + + if (ctx->renew_life > 0) { + /* Don't ask for a smaller renewable time than the lifetime. */ + ctx->request->rtime = ts_incr(from, ctx->renew_life); + if (ts_after(ctx->request->till, ctx->request->rtime)) + ctx->request->rtime = ctx->request->till; + ctx->request->kdc_options &= ~KDC_OPT_RENEWABLE_OK; + } else { + ctx->request->rtime = 0; + } + + return 0; +} + +static void +read_allowed_preauth_type(krb5_context context, krb5_init_creds_context ctx) +{ + krb5_error_code ret; + krb5_data config; + char *tmp, *p; + krb5_ccache in_ccache = k5_gic_opt_get_in_ccache(ctx->opt); + + ctx->allowed_preauth_type = KRB5_PADATA_NONE; + if (in_ccache == NULL) + return; + memset(&config, 0, sizeof(config)); + if (krb5_cc_get_config(context, in_ccache, ctx->request->server, + KRB5_CC_CONF_PA_TYPE, &config) != 0) + return; + tmp = k5memdup0(config.data, config.length, &ret); + krb5_free_data_contents(context, &config); + if (tmp == NULL) + return; + ctx->allowed_preauth_type = strtol(tmp, &p, 10); + if (p == NULL || *p != '\0') + ctx->allowed_preauth_type = KRB5_PADATA_NONE; + free(tmp); +} + +/* Return true if encrypted timestamp is disabled for realm. */ +static krb5_boolean +encts_disabled(profile_t profile, const krb5_data *realm) +{ + krb5_error_code ret; + char *realmstr; + int bval; + + realmstr = k5memdup0(realm->data, realm->length, &ret); + if (realmstr == NULL) + return FALSE; + ret = profile_get_boolean(profile, KRB5_CONF_REALMS, realmstr, + KRB5_CONF_DISABLE_ENCRYPTED_TIMESTAMP, FALSE, + &bval); + free(realmstr); + return (ret == 0) ? bval : FALSE; +} + +/** + * Throw away any pre-authentication realm state and begin with a + * unauthenticated or optimistically authenticated request. If fast_upgrade is + * set, use FAST for this request. + */ +static krb5_error_code +restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx, + krb5_boolean fast_upgrade) +{ + krb5_error_code code = 0; + + krb5_free_pa_data(context, ctx->optimistic_padata); + krb5_free_pa_data(context, ctx->method_padata); + krb5_free_pa_data(context, ctx->more_padata); + krb5_free_pa_data(context, ctx->err_padata); + krb5_free_error(context, ctx->err_reply); + ctx->optimistic_padata = ctx->method_padata = ctx->more_padata = NULL; + ctx->err_padata = NULL; + ctx->err_reply = NULL; + ctx->selected_preauth_type = KRB5_PADATA_NONE; + + krb5int_fast_free_state(context, ctx->fast_state); + ctx->fast_state = NULL; + code = krb5int_fast_make_state(context, &ctx->fast_state); + if (code != 0) + goto cleanup; + if (fast_upgrade) + ctx->fast_state->fast_state_flags |= KRB5INT_FAST_DO_FAST; + + k5_preauth_request_context_fini(context, ctx); + k5_preauth_request_context_init(context, ctx); + krb5_free_data(context, ctx->outer_request_body); + ctx->outer_request_body = NULL; + if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) { + code = make_preauth_list(context, ctx->opt->preauth_list, + ctx->opt->preauth_list_length, + &ctx->optimistic_padata); + if (code) + goto cleanup; + } + + /* Never set encts_disabled back to false, so it can't be circumvented with + * client realm referrals. */ + if (encts_disabled(context->profile, &ctx->request->client->realm)) + ctx->encts_disabled = TRUE; + + krb5_free_principal(context, ctx->request->server); + ctx->request->server = NULL; + + code = build_in_tkt_name(context, ctx->in_tkt_service, + ctx->request->client, + &ctx->request->server); + if (code != 0) + goto cleanup; + + code = krb5int_fast_as_armor(context, ctx->fast_state, ctx->opt, + ctx->request); + if (code != 0) + goto cleanup; + /* give the preauth plugins a chance to prep the request body */ + k5_preauth_prepare_request(context, ctx->opt, ctx->request); + + code = krb5int_fast_prep_req_body(context, ctx->fast_state, + ctx->request, + &ctx->outer_request_body); + if (code != 0) + goto cleanup; + + /* Read the allowed preauth type for this server principal from the input + * ccache, if the application supplied one. */ + read_allowed_preauth_type(context, ctx); + +cleanup: + return code; +} + +krb5_error_code KRB5_CALLCONV +krb5_init_creds_init(krb5_context context, + krb5_principal client, + krb5_prompter_fct prompter, + void *data, + krb5_deltat start_time, + krb5_get_init_creds_opt *opt, + krb5_init_creds_context *pctx) +{ + krb5_error_code code; + krb5_init_creds_context ctx; + int tmp; + char *str = NULL; + + TRACE_INIT_CREDS(context, client); + + ctx = k5alloc(sizeof(*ctx), &code); + if (code != 0) + goto cleanup; + + ctx->request = k5alloc(sizeof(krb5_kdc_req), &code); + if (code != 0) + goto cleanup; + ctx->info_pa_permitted = TRUE; + code = krb5_copy_principal(context, client, &ctx->request->client); + if (code != 0) + goto cleanup; + + ctx->prompter = prompter; + ctx->prompter_data = data; + ctx->gak_fct = krb5_get_as_key_password; + ctx->gak_data = &ctx->gakpw; + + ctx->start_time = start_time; + + if (opt == NULL) { + ctx->opt = &ctx->opt_storage; + krb5_get_init_creds_opt_init(ctx->opt); + } else { + ctx->opt = opt; + } + + code = k5_response_items_new(&ctx->rctx.items); + if (code != 0) + goto cleanup; + + /* Initialise request parameters as per krb5_get_init_creds() */ + ctx->request->kdc_options = context->kdc_default_options; + + /* forwardable */ + if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE) + tmp = ctx->opt->forwardable; + else if (krb5int_libdefault_boolean(context, &ctx->request->client->realm, + KRB5_CONF_FORWARDABLE, &tmp) == 0) + ; + else + tmp = 0; + if (tmp) + ctx->request->kdc_options |= KDC_OPT_FORWARDABLE; + + /* proxiable */ + if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE) + tmp = ctx->opt->proxiable; + else if (krb5int_libdefault_boolean(context, &ctx->request->client->realm, + KRB5_CONF_PROXIABLE, &tmp) == 0) + ; + else + tmp = 0; + if (tmp) + ctx->request->kdc_options |= KDC_OPT_PROXIABLE; + + /* canonicalize */ + if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_CANONICALIZE) + tmp = 1; + else if (krb5int_libdefault_boolean(context, &ctx->request->client->realm, + KRB5_CONF_CANONICALIZE, &tmp) == 0) + ; + else + tmp = 0; + if (tmp) + ctx->request->kdc_options |= KDC_OPT_CANONICALIZE; + + /* allow_postdate */ + if (ctx->start_time > 0) + ctx->request->kdc_options |= KDC_OPT_ALLOW_POSTDATE | KDC_OPT_POSTDATED; + + /* ticket lifetime */ + if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_TKT_LIFE) + ctx->tkt_life = ctx->opt->tkt_life; + else if (krb5int_libdefault_string(context, &ctx->request->client->realm, + KRB5_CONF_TICKET_LIFETIME, &str) == 0) { + code = krb5_string_to_deltat(str, &ctx->tkt_life); + if (code != 0) + goto cleanup; + free(str); + str = NULL; + } else + ctx->tkt_life = 24 * 60 * 60; /* previously hardcoded in kinit */ + + /* renewable lifetime */ + if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE) + ctx->renew_life = ctx->opt->renew_life; + else if (krb5int_libdefault_string(context, &ctx->request->client->realm, + KRB5_CONF_RENEW_LIFETIME, &str) == 0) { + code = krb5_string_to_deltat(str, &ctx->renew_life); + if (code != 0) + goto cleanup; + free(str); + str = NULL; + } else + ctx->renew_life = 0; + + if (ctx->renew_life > 0) + ctx->request->kdc_options |= KDC_OPT_RENEWABLE; + + /* enctypes */ + if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST) { + ctx->request->ktype = + k5memdup(ctx->opt->etype_list, + ctx->opt->etype_list_length * sizeof(krb5_enctype), + &code); + if (code != 0) + goto cleanup; + ctx->request->nktypes = ctx->opt->etype_list_length; + } else if (krb5_get_default_in_tkt_ktypes(context, + &ctx->request->ktype) == 0) { + ctx->request->nktypes = k5_count_etypes(ctx->request->ktype); + } else { + /* there isn't any useful default here. */ + code = KRB5_CONFIG_ETYPE_NOSUPP; + goto cleanup; + } + + /* + * Set a default enctype for optimistic preauth. If we're not doing + * optimistic preauth, this should ordinarily get overwritten when we + * process the etype-info2 of the preauth-required error. + */ + if (ctx->request->nktypes > 0) + ctx->etype = ctx->request->ktype[0]; + + /* addresses */ + if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST) { + code = krb5_copy_addresses(context, ctx->opt->address_list, + &ctx->request->addresses); + if (code != 0) + goto cleanup; + } else if (krb5int_libdefault_boolean(context, &ctx->request->client->realm, + KRB5_CONF_NOADDRESSES, &tmp) != 0 + || tmp) { + ctx->request->addresses = NULL; + } else { + code = krb5_os_localaddr(context, &ctx->request->addresses); + if (code != 0) + goto cleanup; + } + + if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_SALT) { + code = krb5int_copy_data_contents(context, ctx->opt->salt, &ctx->salt); + if (code != 0) + goto cleanup; + ctx->default_salt = FALSE; + } else { + ctx->salt = empty_data(); + ctx->default_salt = TRUE; + } + + /* Anonymous. */ + if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS) { + ctx->request->kdc_options |= KDC_OPT_REQUEST_ANONYMOUS; + /* Remap @REALM to WELLKNOWN/ANONYMOUS@REALM. */ + if (client->length == 1 && client->data[0].length ==0) { + krb5_principal new_client; + code = krb5_build_principal_ext(context, &new_client, + client->realm.length, + client->realm.data, + strlen(KRB5_WELLKNOWN_NAMESTR), + KRB5_WELLKNOWN_NAMESTR, + strlen(KRB5_ANONYMOUS_PRINCSTR), + KRB5_ANONYMOUS_PRINCSTR, + 0); + if (code) + goto cleanup; + krb5_free_principal(context, ctx->request->client); + ctx->request->client = new_client; + ctx->request->client->type = KRB5_NT_WELLKNOWN; + } + } + /* We will also handle anonymous if the input principal is the anonymous + * principal. */ + if (krb5_principal_compare_any_realm(context, ctx->request->client, + krb5_anonymous_principal())) { + ctx->request->kdc_options |= KDC_OPT_REQUEST_ANONYMOUS; + ctx->request->client->type = KRB5_NT_WELLKNOWN; + } + + *pctx = ctx; + ctx = NULL; + +cleanup: + krb5_init_creds_free(context, ctx); + free(str); + + return code; +} + +krb5_error_code KRB5_CALLCONV +krb5_init_creds_set_service(krb5_context context, + krb5_init_creds_context ctx, + const char *service) +{ + char *s; + + TRACE_INIT_CREDS_SERVICE(context, service); + + s = strdup(service); + if (s == NULL) + return ENOMEM; + + free(ctx->in_tkt_service); + ctx->in_tkt_service = s; + + return restart_init_creds_loop(context, ctx, FALSE); +} + +static krb5_error_code +init_creds_validate_reply(krb5_context context, + krb5_init_creds_context ctx, + krb5_data *reply) +{ + krb5_error_code code; + krb5_error *error = NULL; + krb5_kdc_rep *as_reply = NULL; + + krb5_free_error(context, ctx->err_reply); + ctx->err_reply = NULL; + + krb5_free_kdc_rep(context, ctx->reply); + ctx->reply = NULL; + + if (krb5_is_krb_error(reply)) { + code = decode_krb5_error(reply, &error); + if (code != 0) + return code; + + assert(error != NULL); + + TRACE_INIT_CREDS_ERROR_REPLY(context, + error->error + ERROR_TABLE_BASE_krb5); + if (error->error == KRB_ERR_RESPONSE_TOO_BIG) { + krb5_free_error(context, error); + return KRB5KRB_ERR_RESPONSE_TOO_BIG; + } else { + ctx->err_reply = error; + return 0; + } + } + + /* + * Check to make sure it isn't a V4 reply. + */ + if (reply->length != 0 && !krb5_is_as_rep(reply)) { +/* these are in as well but it isn't worth including. */ +#define V4_KRB_PROT_VERSION 4 +#define V4_AUTH_MSG_ERR_REPLY (5<<1) + /* check here for V4 reply */ + unsigned int t_switch; + + /* From v4 g_in_tkt.c: This used to be + switch (pkt_msg_type(rpkt) & ~1) { + but SCO 3.2v4 cc compiled that incorrectly. */ + t_switch = reply->data[1]; + t_switch &= ~1; + + if (t_switch == V4_AUTH_MSG_ERR_REPLY + && reply->data[0] == V4_KRB_PROT_VERSION) { + code = KRB5KRB_AP_ERR_V4_REPLY; + } else { + code = KRB5KRB_AP_ERR_MSG_TYPE; + } + return code; + } + + /* It must be a KRB_AS_REP message, or an bad returned packet */ + code = decode_krb5_as_rep(reply, &as_reply); + if (code != 0) + return code; + + if (as_reply->msg_type != KRB5_AS_REP) { + krb5_free_kdc_rep(context, as_reply); + return KRB5KRB_AP_ERR_MSG_TYPE; + } + + ctx->reply = as_reply; + + return 0; +} + +static krb5_error_code +save_selected_preauth_type(krb5_context context, krb5_ccache ccache, + krb5_init_creds_context ctx) +{ + krb5_data config_data; + char *tmp; + krb5_error_code code; + + if (ctx->selected_preauth_type == KRB5_PADATA_NONE) + return 0; + if (asprintf(&tmp, "%ld", (long)ctx->selected_preauth_type) < 0) + return ENOMEM; + config_data = string2data(tmp); + code = krb5_cc_set_config(context, ccache, ctx->cred.server, + KRB5_CC_CONF_PA_TYPE, &config_data); + free(tmp); + return code; +} + +static krb5_error_code +clear_cc_config_out_data(krb5_context context, krb5_init_creds_context ctx) +{ + k5_json_release(ctx->cc_config_out); + ctx->cc_config_out = NULL; + return k5_json_object_create(&ctx->cc_config_out); +} + +static krb5_error_code +read_cc_config_in_data(krb5_context context, krb5_init_creds_context ctx) +{ + k5_json_value val; + krb5_data config; + char *encoded; + krb5_error_code code; + krb5_ccache in_ccache = k5_gic_opt_get_in_ccache(ctx->opt); + + k5_json_release(ctx->cc_config_in); + ctx->cc_config_in = NULL; + + if (in_ccache == NULL) + return 0; + + memset(&config, 0, sizeof(config)); + code = krb5_cc_get_config(context, in_ccache, ctx->request->server, + KRB5_CC_CONF_PA_CONFIG_DATA, &config); + if (code) + return code; + + encoded = k5memdup0(config.data, config.length, &code); + krb5_free_data_contents(context, &config); + if (encoded == NULL) + return ENOMEM; + + code = k5_json_decode(encoded, &val); + free(encoded); + if (code) + return code; + if (k5_json_get_tid(val) != K5_JSON_TID_OBJECT) { + k5_json_release(val); + return EINVAL; + } + ctx->cc_config_in = val; + return 0; +} + +static krb5_error_code +save_cc_config_out_data(krb5_context context, krb5_ccache ccache, + krb5_init_creds_context ctx) +{ + krb5_data config; + char *encoded; + krb5_error_code code; + + if (ctx->cc_config_out == NULL || + k5_json_object_count(ctx->cc_config_out) == 0) + return 0; + code = k5_json_encode(ctx->cc_config_out, &encoded); + if (code) + return code; + config = string2data(encoded); + code = krb5_cc_set_config(context, ccache, ctx->cred.server, + KRB5_CC_CONF_PA_CONFIG_DATA, &config); + free(encoded); + return code; +} + +/* Add a KERB-PA-PAC-REQUEST pa-data item if the gic options require one. */ +static krb5_error_code +maybe_add_pac_request(krb5_context context, krb5_init_creds_context ctx) +{ + krb5_error_code code; + krb5_pa_pac_req pac_req; + krb5_data *encoded; + int val; + + val = k5_gic_opt_pac_request(ctx->opt); + if (val == -1) + return 0; + + pac_req.include_pac = val; + code = encode_krb5_pa_pac_req(&pac_req, &encoded); + if (code) + return code; + code = k5_add_pa_data_from_data(&ctx->request->padata, + KRB5_PADATA_PAC_REQUEST, encoded); + krb5_free_data(context, encoded); + return code; +} + +static krb5_error_code +init_creds_step_request(krb5_context context, + krb5_init_creds_context ctx, + krb5_data *out) +{ + krb5_error_code code; + krb5_preauthtype pa_type; + krb5_data copy; + struct errinfo save = EMPTY_ERRINFO; + uint32_t rcode = (ctx->err_reply == NULL) ? 0 : ctx->err_reply->error; + + if (ctx->loopcount >= MAX_IN_TKT_LOOPS) { + code = KRB5_GET_IN_TKT_LOOP; + goto cleanup; + } + + /* RFC 6113 requires a new nonce for the inner request on each try. */ + code = k5_generate_nonce(context, &ctx->request->nonce); + if (code != 0) + goto cleanup; + + /* Reset the request timestamps, possibly adjusting to the KDC time. */ + code = set_request_times(context, ctx); + if (code != 0) + goto cleanup; + + krb5_free_data(context, ctx->inner_request_body); + ctx->inner_request_body = NULL; + code = encode_krb5_kdc_req_body(ctx->request, &ctx->inner_request_body); + if (code) + goto cleanup; + + /* + * Read cached preauth configuration data for this server principal from + * the in_ccache, if the application supplied one, and delete any that was + * stored by a previous (clearly failed) module. + */ + read_cc_config_in_data(context, ctx); + clear_cc_config_out_data(context, ctx); + + ctx->request->padata = NULL; + if (ctx->optimistic_padata != NULL) { + /* Our first attempt, using an optimistic padata list. */ + TRACE_INIT_CREDS_PREAUTH_OPTIMISTIC(context); + code = k5_preauth(context, ctx, ctx->optimistic_padata, TRUE, + &ctx->request->padata, &ctx->selected_preauth_type); + krb5_free_pa_data(context, ctx->optimistic_padata); + ctx->optimistic_padata = NULL; + if (code) { + /* Make an unauthenticated request. */ + krb5_clear_error_message(context); + code = 0; + } + } if (ctx->more_padata != NULL) { + /* Continuing after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED. */ + TRACE_INIT_CREDS_PREAUTH_MORE(context, ctx->selected_preauth_type); + code = k5_preauth(context, ctx, ctx->more_padata, TRUE, + &ctx->request->padata, &pa_type); + } else if (rcode == KDC_ERR_PREAUTH_FAILED) { + /* Report the KDC-side failure code if we can't try another mech. */ + code = KRB5KDC_ERR_PREAUTH_FAILED; + } else if (rcode && rcode != KDC_ERR_PREAUTH_REQUIRED) { + /* Retrying after an error (possibly mechanism-specific), using error + * padata to figure out what to change. */ + TRACE_INIT_CREDS_PREAUTH_TRYAGAIN(context, ctx->err_reply->error, + ctx->selected_preauth_type); + code = k5_preauth_tryagain(context, ctx, ctx->selected_preauth_type, + ctx->err_reply, ctx->err_padata, + &ctx->request->padata); + if (code) { + krb5_clear_error_message(context); + code = ctx->err_reply->error + ERROR_TABLE_BASE_krb5; + } + } + /* Don't continue after a keyboard interrupt. */ + if (code == KRB5_LIBOS_PWDINTR) + goto cleanup; + /* Don't continue if fallback is disabled. */ + if (code && ctx->fallback_disabled) + goto cleanup; + if (code) { + /* See if we can try a different preauth mech before giving up. */ + k5_save_ctx_error(context, code, &save); + ctx->selected_preauth_type = KRB5_PADATA_NONE; + } + + if (ctx->request->padata == NULL && ctx->method_padata != NULL) { + /* Retrying after KDC_ERR_PREAUTH_REQUIRED, or trying again with a + * different mechanism after a failure. */ + TRACE_INIT_CREDS_PREAUTH(context); + code = k5_preauth(context, ctx, ctx->method_padata, TRUE, + &ctx->request->padata, &ctx->selected_preauth_type); + if (code) { + if (save.code != 0) + code = k5_restore_ctx_error(context, &save); + goto cleanup; + } + } + if (ctx->request->padata == NULL) + TRACE_INIT_CREDS_PREAUTH_NONE(context); + + /* Remember when we sent this request (after any preauth delay). */ + ctx->request_time = time(NULL); + + if (ctx->encoded_previous_request != NULL) { + krb5_free_data(context, ctx->encoded_previous_request); + ctx->encoded_previous_request = NULL; + } + if (ctx->info_pa_permitted) { + code = k5_add_empty_pa_data(&ctx->request->padata, + KRB5_PADATA_AS_FRESHNESS); + if (code) + goto cleanup; + code = k5_add_empty_pa_data(&ctx->request->padata, + KRB5_ENCPADATA_REQ_ENC_PA_REP); + } + if (code) + goto cleanup; + + if (ctx->subject_cert != NULL) { + code = krb5int_copy_data_contents(context, ctx->subject_cert, ©); + if (code) + goto cleanup; + code = k5_add_pa_data_from_data(&ctx->request->padata, + KRB5_PADATA_S4U_X509_USER, ©); + krb5_free_data_contents(context, ©); + if (code) + goto cleanup; + } + + code = maybe_add_pac_request(context, ctx); + if (code) + goto cleanup; + + code = krb5int_fast_prep_req(context, ctx->fast_state, + ctx->request, ctx->outer_request_body, + encode_krb5_as_req, + &ctx->encoded_previous_request); + if (code != 0) + goto cleanup; + + code = krb5int_copy_data_contents(context, + ctx->encoded_previous_request, + out); + if (code != 0) + goto cleanup; + +cleanup: + krb5_free_pa_data(context, ctx->request->padata); + ctx->request->padata = NULL; + k5_clear_error(&save); + return code; +} + +/* Ensure that the reply enctype was among the requested enctypes. */ +static krb5_error_code +check_reply_enctype(krb5_init_creds_context ctx) +{ + int i; + + for (i = 0; i < ctx->request->nktypes; i++) { + if (ctx->request->ktype[i] == ctx->reply->enc_part.enctype) + return 0; + } + return KRB5_CONFIG_ETYPE_NOSUPP; +} + +/* Note the difference between the KDC's time, as reported to us in a + * preauth-required error, and the current time. */ +static void +note_req_timestamp(krb5_context context, krb5_init_creds_context ctx, + krb5_timestamp kdc_time, krb5_int32 kdc_usec) +{ + krb5_timestamp now; + krb5_int32 usec; + + if (k5_time_with_offset(0, 0, &now, &usec) != 0) + return; + ctx->pa_offset = ts_delta(kdc_time, now); + ctx->pa_offset_usec = kdc_usec - usec; + ctx->pa_offset_state = (ctx->fast_state->armor_key != NULL) ? + AUTH_OFFSET : UNAUTH_OFFSET; +} + +/* + * Determine whether err is a client referral to another realm, given the + * previously requested client principal name. + * + * RFC 6806 Section 7 requires that KDCs return the referral realm in an error + * type WRONG_REALM, but Microsoft Windows Server 2003 (and possibly others) + * return the realm in a PRINCIPAL_UNKNOWN message. + */ +static krb5_boolean +is_referral(krb5_context context, krb5_error *err, krb5_principal client) +{ + if (err->error != KDC_ERR_WRONG_REALM && + err->error != KDC_ERR_C_PRINCIPAL_UNKNOWN) + return FALSE; + if (err->client == NULL) + return FALSE; + return !krb5_realm_compare(context, err->client, client); +} + +/* Transfer error padata to method data in ctx and sort it according to + * configuration. */ +static krb5_error_code +accept_method_data(krb5_context context, krb5_init_creds_context ctx) +{ + krb5_free_pa_data(context, ctx->method_padata); + ctx->method_padata = ctx->err_padata; + ctx->err_padata = NULL; + return sort_krb5_padata_sequence(context, &ctx->request->client->realm, + ctx->method_padata); +} + +/* Return the password expiry time indicated by enc_part2. Set *is_last_req + * if the information came from a last_req value. */ +static void +get_expiry_times(krb5_enc_kdc_rep_part *enc_part2, krb5_timestamp *pw_exp, + krb5_timestamp *acct_exp, krb5_boolean *is_last_req) +{ + krb5_last_req_entry **last_req; + krb5_int32 lr_type; + + *pw_exp = 0; + *acct_exp = 0; + *is_last_req = FALSE; + + /* Look for last-req entries for password or account expiration. */ + if (enc_part2->last_req) { + for (last_req = enc_part2->last_req; *last_req; last_req++) { + lr_type = (*last_req)->lr_type; + if (lr_type == KRB5_LRQ_ALL_PW_EXPTIME || + lr_type == KRB5_LRQ_ONE_PW_EXPTIME) { + *is_last_req = TRUE; + *pw_exp = (*last_req)->value; + } else if (lr_type == KRB5_LRQ_ALL_ACCT_EXPTIME || + lr_type == KRB5_LRQ_ONE_ACCT_EXPTIME) { + *is_last_req = TRUE; + *acct_exp = (*last_req)->value; + } + } + } + + /* If we didn't find any, use the ambiguous key_exp field. */ + if (*is_last_req == FALSE) + *pw_exp = enc_part2->key_exp; +} + +/* + * Send an appropriate warning prompter if as_reply indicates that the password + * is going to expire soon. If an expire callback was provided, use that + * instead. + */ +static void +warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options, + krb5_prompter_fct prompter, void *data, + const char *in_tkt_service, krb5_kdc_rep *as_reply) +{ + krb5_error_code ret; + krb5_expire_callback_func expire_cb; + void *expire_data; + krb5_timestamp pw_exp, acct_exp, now; + krb5_boolean is_last_req; + uint32_t interval; + char ts[256], banner[1024]; + + if (as_reply == NULL || as_reply->enc_part2 == NULL) + return; + + get_expiry_times(as_reply->enc_part2, &pw_exp, &acct_exp, &is_last_req); + + k5_gic_opt_get_expire_cb(options, &expire_cb, &expire_data); + if (expire_cb != NULL) { + /* Invoke the expire callback and don't send prompter warnings. */ + (*expire_cb)(context, expire_data, pw_exp, acct_exp, is_last_req); + return; + } + + /* Don't warn if no password expiry value was sent. */ + if (pw_exp == 0) + return; + + /* Don't warn if the password is being changed. */ + if (in_tkt_service && strcmp(in_tkt_service, "kadmin/changepw") == 0) + return; + + /* + * If the expiry time came from a last_req field, assume the KDC wants us + * to warn. Otherwise, warn only if the expiry time is less than a week + * from now. + */ + ret = krb5_timeofday(context, &now); + if (ret != 0) + return; + interval = ts_interval(now, pw_exp); + if (!is_last_req && (!interval || interval > 7 * 24 * 60 * 60)) + return; + + if (!prompter) + return; + + ret = krb5_timestamp_to_string(pw_exp, ts, sizeof(ts)); + if (ret != 0) + return; + + if (interval < 3600) { + snprintf(banner, sizeof(banner), + _("Warning: Your password will expire in less than one hour " + "on %s"), ts); + } else if (interval < 86400 * 2) { + snprintf(banner, sizeof(banner), + _("Warning: Your password will expire in %d hour%s on %s"), + interval / 3600, interval < 7200 ? "" : "s", ts); + } else { + snprintf(banner, sizeof(banner), + _("Warning: Your password will expire in %d days on %s"), + interval / 86400, ts); + } + + /* PROMPTER_INVOCATION */ + (*prompter)(context, data, 0, banner, 0, 0); +} + +/* Display a warning via the prompter if a deprecated enctype was used for + * either the reply key or the session key. */ +static void +warn_deprecated(krb5_context context, krb5_init_creds_context ctx, + krb5_enctype as_key_enctype) +{ + krb5_enctype etype; + char encbuf[128], banner[256]; + + if (ctx->prompter == NULL) + return; + + if (krb5int_c_deprecated_enctype(as_key_enctype)) + etype = as_key_enctype; + else if (krb5int_c_deprecated_enctype(ctx->cred.keyblock.enctype)) + etype = ctx->cred.keyblock.enctype; + else + return; + + if (krb5_enctype_to_name(etype, FALSE, encbuf, sizeof(encbuf)) != 0) + return; + snprintf(banner, sizeof(banner), + _("Warning: encryption type %s used for authentication is " + "deprecated and will be disabled"), encbuf); + + /* PROMPTER_INVOCATION */ + (*ctx->prompter)(context, ctx->prompter_data, NULL, banner, 0, NULL); +} + +/* + * If ctx specifies an output ccache, create or refresh it (atomically, if + * possible) with the obtained credential and any appropriate ccache + * configuration. + */ +static krb5_error_code +write_out_ccache(krb5_context context, krb5_init_creds_context ctx, + krb5_boolean fast_avail) +{ + krb5_error_code ret; + krb5_ccache out_ccache = k5_gic_opt_get_out_ccache(ctx->opt); + krb5_ccache mcc = NULL; + krb5_data yes = string2data("yes"); + + if (out_ccache == NULL) + return 0; + + ret = krb5_cc_new_unique(context, "MEMORY", NULL, &mcc); + if (ret) + goto cleanup; + + ret = krb5_cc_initialize(context, mcc, ctx->cred.client); + if (ret) + goto cleanup; + + if (fast_avail) { + ret = krb5_cc_set_config(context, mcc, ctx->cred.server, + KRB5_CC_CONF_FAST_AVAIL, &yes); + if (ret) + goto cleanup; + } + + ret = save_selected_preauth_type(context, mcc, ctx); + if (ret) + goto cleanup; + + ret = save_cc_config_out_data(context, mcc, ctx); + if (ret) + goto cleanup; + + ret = k5_cc_store_primary_cred(context, mcc, &ctx->cred); + if (ret) + goto cleanup; + + ret = krb5_cc_move(context, mcc, out_ccache); + if (ret) + goto cleanup; + mcc = NULL; + +cleanup: + if (mcc != NULL) + krb5_cc_destroy(context, mcc); + return ret; +} + +static krb5_error_code +init_creds_step_reply(krb5_context context, + krb5_init_creds_context ctx, + krb5_data *in) +{ + krb5_error_code code; + krb5_pa_data **kdc_padata = NULL; + krb5_preauthtype kdc_pa_type; + krb5_boolean retry = FALSE; + int canon_flag = 0; + uint32_t reply_code; + krb5_keyblock *strengthen_key = NULL; + krb5_keyblock encrypting_key; + krb5_boolean fast_avail; + + encrypting_key.length = 0; + encrypting_key.contents = NULL; + + /* process previous KDC response */ + code = init_creds_validate_reply(context, ctx, in); + if (code != 0) + goto cleanup; + + /* per referrals draft, enterprise principals imply canonicalization */ + canon_flag = ((ctx->request->kdc_options & KDC_OPT_CANONICALIZE) != 0) || + ctx->request->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL; + + if (ctx->err_reply != NULL) { + krb5_free_pa_data(context, ctx->more_padata); + krb5_free_pa_data(context, ctx->err_padata); + ctx->more_padata = ctx->err_padata = NULL; + code = krb5int_fast_process_error(context, ctx->fast_state, + &ctx->err_reply, &ctx->err_padata, + &retry); + if (code != 0) + goto cleanup; + reply_code = ctx->err_reply->error; + if (!ctx->restarted && + k5_upgrade_to_fast_p(context, ctx->fast_state, ctx->err_padata)) { + /* Retry with FAST after discovering that the KDC supports + * it. (FAST negotiation usually avoids this restart.) */ + TRACE_FAST_PADATA_UPGRADE(context); + ctx->restarted = TRUE; + code = restart_init_creds_loop(context, ctx, TRUE); + } else if (!ctx->restarted && reply_code == KDC_ERR_PREAUTH_FAILED && + ctx->selected_preauth_type == KRB5_PADATA_NONE) { + /* The KDC didn't like our informational padata (probably a pre-1.7 + * MIT krb5 KDC). Retry without it. */ + ctx->info_pa_permitted = FALSE; + ctx->restarted = TRUE; + code = restart_init_creds_loop(context, ctx, FALSE); + } else if (reply_code == KDC_ERR_PREAUTH_EXPIRED) { + /* We sent an expired KDC cookie. Start over, allowing another + * FAST upgrade. */ + ctx->restarted = FALSE; + code = restart_init_creds_loop(context, ctx, FALSE); + } else if (ctx->identify_realm && + (reply_code == KDC_ERR_PREAUTH_REQUIRED || + reply_code == KDC_ERR_KEY_EXP)) { + /* The client exists in this realm; we can stop. */ + ctx->complete = TRUE; + goto cleanup; + } else if (reply_code == KDC_ERR_PREAUTH_REQUIRED && retry) { + note_req_timestamp(context, ctx, ctx->err_reply->stime, + ctx->err_reply->susec); + code = accept_method_data(context, ctx); + } else if (reply_code == KDC_ERR_PREAUTH_FAILED && retry) { + note_req_timestamp(context, ctx, ctx->err_reply->stime, + ctx->err_reply->susec); + /* Don't try again with the mechanism that failed. */ + code = k5_preauth_note_failed(ctx, ctx->selected_preauth_type); + if (code) + goto cleanup; + ctx->selected_preauth_type = KRB5_PADATA_NONE; + /* Accept or update method data if the KDC sent it. */ + if (ctx->err_padata != NULL) + code = accept_method_data(context, ctx); + } else if (reply_code == KDC_ERR_MORE_PREAUTH_DATA_REQUIRED && retry) { + ctx->more_padata = ctx->err_padata; + ctx->err_padata = NULL; + } else if (canon_flag && is_referral(context, ctx->err_reply, + ctx->request->client)) { + TRACE_INIT_CREDS_REFERRAL(context, &ctx->err_reply->client->realm); + /* Rewrite request.client with realm from error reply */ + krb5_free_data_contents(context, &ctx->request->client->realm); + code = krb5int_copy_data_contents(context, + &ctx->err_reply->client->realm, + &ctx->request->client->realm); + if (code != 0) + goto cleanup; + /* Reset per-realm negotiation state. */ + ctx->restarted = FALSE; + ctx->info_pa_permitted = TRUE; + code = restart_init_creds_loop(context, ctx, FALSE); + } else { + if (retry && ctx->selected_preauth_type != KRB5_PADATA_NONE) { + code = 0; + } else { + /* error + no hints (or no preauth mech) = give up */ + code = (krb5_error_code)reply_code + ERROR_TABLE_BASE_krb5; + } + } + + /* Return error code, or continue with next iteration */ + goto cleanup; + } + + /* We have a response. Process it. */ + assert(ctx->reply != NULL); + + /* Check for replies (likely forged) with unasked-for enctypes. */ + code = check_reply_enctype(ctx); + if (code != 0) + goto cleanup; + + /* process any preauth data in the as_reply */ + code = krb5int_fast_process_response(context, ctx->fast_state, + ctx->reply, &strengthen_key); + if (code != 0) + goto cleanup; + + if (ctx->identify_realm) { + /* Just getting a reply means the client exists in this realm. */ + ctx->complete = TRUE; + goto cleanup; + } + + code = sort_krb5_padata_sequence(context, &ctx->request->client->realm, + ctx->reply->padata); + if (code != 0) + goto cleanup; + + ctx->etype = ctx->reply->enc_part.enctype; + + /* Process the final reply padata. Don't restrict the preauth types or + * record a selected preauth type. */ + ctx->allowed_preauth_type = KRB5_PADATA_NONE; + code = k5_preauth(context, ctx, ctx->reply->padata, FALSE, &kdc_padata, + &kdc_pa_type); + if (code != 0) + goto cleanup; + + /* + * If we haven't gotten a salt from another source yet, set up one + * corresponding to the client principal returned by the KDC. We + * could get the same effect by passing local_as_reply->client to + * gak_fct below, but that would put the canonicalized client name + * in the prompt, which raises issues of needing to sanitize + * unprintable characters. So for now we just let it affect the + * salt. local_as_reply->client will be checked later on in + * verify_as_reply. + */ + if (ctx->default_salt) { + code = krb5_principal2salt(context, ctx->reply->client, &ctx->salt); + TRACE_INIT_CREDS_SALT_PRINC(context, &ctx->salt); + if (code != 0) + goto cleanup; + } + + code = decrypt_as_reply(context, ctx, strengthen_key, &encrypting_key); + if (code) + goto cleanup; + TRACE_INIT_CREDS_DECRYPTED_REPLY(context, ctx->reply->enc_part2->session); + + code = krb5int_fast_verify_nego(context, ctx->fast_state, + ctx->reply, ctx->encoded_previous_request, + &encrypting_key, &fast_avail); + if (code) + goto cleanup; + code = verify_as_reply(context, ctx->request_time, + ctx->request, ctx->reply); + if (code != 0) + goto cleanup; + code = verify_anonymous(context, ctx->request, ctx->reply, + &ctx->as_key); + if (code) + goto cleanup; + + code = stash_as_reply(context, ctx->reply, &ctx->cred, NULL); + if (code != 0) + goto cleanup; + code = write_out_ccache(context, ctx, fast_avail); + if (code) + k5_prependmsg(context, code, _("Failed to store credentials")); + + k5_preauth_request_context_fini(context, ctx); + + /* success */ + ctx->complete = TRUE; + warn_pw_expiry(context, ctx->opt, ctx->prompter, ctx->prompter_data, + ctx->in_tkt_service, ctx->reply); + warn_deprecated(context, ctx, encrypting_key.enctype); + +cleanup: + krb5_free_pa_data(context, kdc_padata); + krb5_free_keyblock(context, strengthen_key); + krb5_free_keyblock_contents(context, &encrypting_key); + + return code; +} + +/* + * Do next step of credentials acquisition. + * + * On success returns 0 or KRB5KRB_ERR_RESPONSE_TOO_BIG if the request + * should be sent with TCP. + */ +krb5_error_code KRB5_CALLCONV +krb5_init_creds_step(krb5_context context, + krb5_init_creds_context ctx, + krb5_data *in, + krb5_data *out, + krb5_data *realm, + unsigned int *flags) +{ + krb5_error_code code, code2; + + *flags = 0; + + out->data = NULL; + out->length = 0; + + realm->data = NULL; + realm->length = 0; + + if (ctx->complete) + return EINVAL; + + code = k5_preauth_check_context(context, ctx); + if (code) + return code; + + if (in->length != 0) { + code = init_creds_step_reply(context, ctx, in); + if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG) { + code2 = krb5int_copy_data_contents(context, + ctx->encoded_previous_request, + out); + if (code2 != 0) { + code = code2; + goto cleanup; + } + goto copy_realm; + } + if (code != 0 || ctx->complete) + goto cleanup; + } else { + code = restart_init_creds_loop(context, ctx, FALSE); + if (code) + goto cleanup; + } + + code = init_creds_step_request(context, ctx, out); + if (code != 0) + goto cleanup; + + /* Only a new request increments the loop count, not a TCP retry */ + ctx->loopcount++; + +copy_realm: + assert(ctx->request->server != NULL); + + code2 = krb5int_copy_data_contents(context, + &ctx->request->server->realm, + realm); + if (code2 != 0) { + code = code2; + goto cleanup; + } + +cleanup: + if (code == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN) { + char *client_name; + + /* See if we can produce a more detailed error message */ + code2 = krb5_unparse_name(context, ctx->request->client, &client_name); + if (code2 == 0) { + k5_setmsg(context, code, + _("Client '%s' not found in Kerberos database"), + client_name); + krb5_free_unparsed_name(context, client_name); + } + } + + *flags = ctx->complete ? 0 : KRB5_INIT_CREDS_STEP_FLAG_CONTINUE; + return code; +} + +krb5_error_code KRB5_CALLCONV +k5_get_init_creds(krb5_context context, krb5_creds *creds, + krb5_principal client, krb5_prompter_fct prompter, + void *prompter_data, krb5_deltat start_time, + const char *in_tkt_service, krb5_get_init_creds_opt *options, + get_as_key_fn gak_fct, void *gak_data, int *use_primary, + krb5_kdc_rep **as_reply) +{ + krb5_error_code code; + krb5_init_creds_context ctx = NULL; + + code = krb5_init_creds_init(context, + client, + prompter, + prompter_data, + start_time, + options, + &ctx); + if (code != 0) + goto cleanup; + + ctx->gak_fct = gak_fct; + ctx->gak_data = gak_data; + + if (in_tkt_service) { + code = krb5_init_creds_set_service(context, ctx, in_tkt_service); + if (code != 0) + goto cleanup; + } + + code = k5_init_creds_get(context, ctx, use_primary); + if (code != 0) + goto cleanup; + + code = krb5_init_creds_get_creds(context, ctx, creds); + if (code != 0) + goto cleanup; + + if (as_reply != NULL) { + *as_reply = ctx->reply; + ctx->reply = NULL; + } + +cleanup: + krb5_init_creds_free(context, ctx); + + return code; +} + +krb5_error_code +k5_identify_realm(krb5_context context, krb5_principal client, + const krb5_data *subject_cert, krb5_principal *client_out) +{ + krb5_error_code ret; + krb5_get_init_creds_opt *opts = NULL; + krb5_init_creds_context ctx = NULL; + int use_primary = 0; + + *client_out = NULL; + + ret = krb5_get_init_creds_opt_alloc(context, &opts); + if (ret) + goto cleanup; + krb5_get_init_creds_opt_set_tkt_life(opts, 15); + krb5_get_init_creds_opt_set_renew_life(opts, 0); + krb5_get_init_creds_opt_set_forwardable(opts, 0); + krb5_get_init_creds_opt_set_proxiable(opts, 0); + krb5_get_init_creds_opt_set_canonicalize(opts, 1); + + ret = krb5_init_creds_init(context, client, NULL, NULL, 0, opts, &ctx); + if (ret) + goto cleanup; + + ctx->identify_realm = TRUE; + ctx->subject_cert = subject_cert; + + ret = k5_init_creds_get(context, ctx, &use_primary); + if (ret) + goto cleanup; + + TRACE_INIT_CREDS_IDENTIFIED_REALM(context, &ctx->request->client->realm); + ret = krb5_copy_principal(context, ctx->request->client, client_out); + +cleanup: + krb5_get_init_creds_opt_free(context, opts); + krb5_init_creds_free(context, ctx); + return ret; +} + +krb5_error_code +k5_populate_gic_opt(krb5_context context, krb5_get_init_creds_opt **out, + krb5_flags options, krb5_address *const *addrs, + krb5_enctype *ktypes, krb5_preauthtype *pre_auth_types, + krb5_creds *creds) +{ + int i; + krb5_timestamp starttime; + krb5_deltat lifetime; + krb5_get_init_creds_opt *opt; + krb5_error_code retval; + + *out = NULL; + retval = krb5_get_init_creds_opt_alloc(context, &opt); + if (retval) + return(retval); + + if (addrs) + krb5_get_init_creds_opt_set_address_list(opt, (krb5_address **) addrs); + if (ktypes) { + i = k5_count_etypes(ktypes); + if (i) + krb5_get_init_creds_opt_set_etype_list(opt, ktypes, i); + } + if (pre_auth_types) { + for (i=0; pre_auth_types[i]; i++); + if (i) + krb5_get_init_creds_opt_set_preauth_list(opt, pre_auth_types, i); + } + if (options&KDC_OPT_FORWARDABLE) + krb5_get_init_creds_opt_set_forwardable(opt, 1); + else krb5_get_init_creds_opt_set_forwardable(opt, 0); + if (options&KDC_OPT_PROXIABLE) + krb5_get_init_creds_opt_set_proxiable(opt, 1); + else krb5_get_init_creds_opt_set_proxiable(opt, 0); + if (creds && creds->times.endtime) { + retval = krb5_timeofday(context, &starttime); + if (retval) + goto cleanup; + if (creds->times.starttime) starttime = creds->times.starttime; + lifetime = ts_delta(creds->times.endtime, starttime); + krb5_get_init_creds_opt_set_tkt_life(opt, lifetime); + } + *out = opt; + return 0; + +cleanup: + krb5_get_init_creds_opt_free(context, opt); + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/gic_keytab.c b/krb5-1.21.3/src/lib/krb5/krb/gic_keytab.c new file mode 100644 index 00000000..f9baabbf --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/gic_keytab.c @@ -0,0 +1,395 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/gic_keytab.c */ +/* + * Copyright (C) 2002, 2003, 2008 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +#ifndef LEAN_CLIENT + +#include "k5-int.h" +#include "int-proto.h" +#include "os-proto.h" +#include "init_creds_ctx.h" + +static krb5_error_code +get_as_key_keytab(krb5_context context, + krb5_principal client, + krb5_enctype etype, + krb5_prompter_fct prompter, + void *prompter_data, + krb5_data *salt, + krb5_data *params, + krb5_keyblock *as_key, + void *gak_data, + k5_response_items *ritems) +{ + krb5_keytab keytab = (krb5_keytab) gak_data; + krb5_error_code ret; + krb5_keytab_entry kt_ent; + + /* We don't need the password from the responder to create the AS key. */ + if (as_key == NULL) + return 0; + + /* if there's already a key of the correct etype, we're done. + if the etype is wrong, free the existing key, and make + a new one. */ + + if (as_key->length) { + if (as_key->enctype == etype) + return(0); + + krb5_free_keyblock_contents(context, as_key); + as_key->length = 0; + } + + if (!krb5_c_valid_enctype(etype)) + return(KRB5_PROG_ETYPE_NOSUPP); + + if ((ret = krb5_kt_get_entry(context, keytab, client, + 0, /* don't have vno available */ + etype, &kt_ent))) + return(ret); + + /* Steal the keyblock from kt_ent for the caller. */ + *as_key = kt_ent.key; + memset(&kt_ent.key, 0, sizeof(kt_ent.key)); + + (void) krb5_kt_free_entry(context, &kt_ent); + + return 0; +} + +/* Return the list of etypes available for client in keytab. */ +static krb5_error_code +lookup_etypes_for_keytab(krb5_context context, krb5_keytab keytab, + krb5_const_principal client, + krb5_enctype **etypes_out) +{ + krb5_kt_cursor cursor; + krb5_keytab_entry entry; + krb5_enctype *p, *etypes = NULL, etype; + krb5_kvno max_kvno = 0, vno; + krb5_error_code ret; + krb5_boolean match; + size_t count = 0; + + *etypes_out = NULL; + + if (keytab->ops->start_seq_get == NULL) + return EINVAL; + ret = krb5_kt_start_seq_get(context, keytab, &cursor); + if (ret != 0) + return ret; + + while (!(ret = krb5_kt_next_entry(context, keytab, &entry, &cursor))) { + /* Extract what we need from the entry and free it. */ + etype = entry.key.enctype; + vno = entry.vno; + match = krb5_principal_compare(context, entry.principal, client); + krb5_free_keytab_entry_contents(context, &entry); + + /* Filter out old or non-matching entries and invalid enctypes. */ + if (vno < max_kvno || !match || !krb5_c_valid_enctype(etype)) + continue; + + /* Update max_kvno and reset the list if we find a newer kvno. */ + if (vno > max_kvno) { + max_kvno = vno; + free(etypes); + etypes = NULL; + count = 0; + } + + /* Leave room for the terminator and possibly a second entry. */ + p = realloc(etypes, (count + 3) * sizeof(*etypes)); + if (p == NULL) { + ret = ENOMEM; + goto cleanup; + } + etypes = p; + etypes[count++] = etype; + etypes[count] = 0; + } + if (ret != KRB5_KT_END) + goto cleanup; + ret = 0; + + *etypes_out = etypes; + etypes = NULL; + +cleanup: + krb5_kt_end_seq_get(context, keytab, &cursor); + free(etypes); + return ret; +} + +/* Move the entries in keytab_list (zero-terminated) to the front of req_list + * (of length req_len), preserving order otherwise. */ +static krb5_error_code +sort_enctypes(krb5_enctype *req_list, int req_len, krb5_enctype *keytab_list) +{ + krb5_enctype *save_list; + int save_pos, req_pos, i; + + save_list = malloc(req_len * sizeof(*save_list)); + if (save_list == NULL) + return ENOMEM; + + /* Sort req_list entries into the front of req_list or into save_list. */ + req_pos = save_pos = 0; + for (i = 0; i < req_len; i++) { + if (k5_etypes_contains(keytab_list, req_list[i])) + req_list[req_pos++] = req_list[i]; + else + save_list[save_pos++] = req_list[i]; + } + + /* Put the entries we saved back in at the end, in order. */ + for (i = 0; i < save_pos; i++) + req_list[req_pos++] = save_list[i]; + assert(req_pos == req_len); + + free(save_list); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_init_creds_set_keytab(krb5_context context, + krb5_init_creds_context ctx, + krb5_keytab keytab) +{ + krb5_enctype *etype_list = NULL; + krb5_error_code ret; + struct canonprinc iter = { ctx->request->client, .subst_defrealm = TRUE }; + krb5_const_principal canonprinc; + krb5_principal copy; + char *name; + + ctx->gak_fct = get_as_key_keytab; + ctx->gak_data = keytab; + + /* We may be authenticating as a host-based principal. If so, look for + * each canonicalization candidate in the keytab. */ + while ((ret = k5_canonprinc(context, &iter, &canonprinc)) == 0 && + canonprinc != NULL) { + ret = lookup_etypes_for_keytab(context, keytab, canonprinc, + &etype_list); + if (ret || etype_list != NULL) + break; + } + if (!ret && canonprinc != NULL) { + /* Authenticate as the principal we found in the keytab. */ + ret = krb5_copy_principal(context, canonprinc, ©); + if (!ret) { + krb5_free_principal(context, ctx->request->client); + ctx->request->client = copy; + } + } + free_canonprinc(&iter); + if (ret) { + TRACE_INIT_CREDS_KEYTAB_LOOKUP_FAILED(context, ret); + free(etype_list); + return 0; + } + TRACE_INIT_CREDS_KEYTAB_LOOKUP(context, ctx->request->client, etype_list); + + /* Error out if we have no keys for the client principal. */ + if (etype_list == NULL) { + ret = krb5_unparse_name(context, ctx->request->client, &name); + if (ret == 0) { + k5_setmsg(context, KRB5_KT_NOTFOUND, + _("Keytab contains no suitable keys for %s"), name); + } + krb5_free_unparsed_name(context, name); + return KRB5_KT_NOTFOUND; + } + + /* Sort the request enctypes so the ones in the keytab appear first. */ + ret = sort_enctypes(ctx->request->ktype, ctx->request->nktypes, + etype_list); + free(etype_list); + return ret; +} + +static krb5_error_code +get_init_creds_keytab(krb5_context context, krb5_creds *creds, + krb5_principal client, krb5_keytab keytab, + krb5_deltat start_time, const char *in_tkt_service, + krb5_get_init_creds_opt *options, int *use_primary) +{ + krb5_error_code ret; + krb5_init_creds_context ctx = NULL; + + ret = krb5_init_creds_init(context, client, NULL, NULL, start_time, + options, &ctx); + if (ret != 0) + goto cleanup; + + if (in_tkt_service) { + ret = krb5_init_creds_set_service(context, ctx, in_tkt_service); + if (ret != 0) + goto cleanup; + } + + ret = krb5_init_creds_set_keytab(context, ctx, keytab); + if (ret != 0) + goto cleanup; + + ret = k5_init_creds_get(context, ctx, use_primary); + if (ret != 0) + goto cleanup; + + ret = krb5_init_creds_get_creds(context, ctx, creds); + if (ret != 0) + goto cleanup; + +cleanup: + krb5_init_creds_free(context, ctx); + + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_keytab(krb5_context context, + krb5_creds *creds, + krb5_principal client, + krb5_keytab arg_keytab, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *options) +{ + krb5_error_code ret; + int use_primary; + krb5_keytab keytab; + struct errinfo errsave = EMPTY_ERRINFO; + + if (arg_keytab == NULL) { + if ((ret = krb5_kt_default(context, &keytab))) + return ret; + } else { + keytab = arg_keytab; + } + + use_primary = 0; + + /* first try: get the requested tkt from any kdc */ + + ret = get_init_creds_keytab(context, creds, client, keytab, start_time, + in_tkt_service, options, &use_primary); + + /* check for success */ + + if (ret == 0) + goto cleanup; + + /* If all the kdc's are unavailable fail */ + + if ((ret == KRB5_KDC_UNREACH) || (ret == KRB5_REALM_CANT_RESOLVE)) + goto cleanup; + + /* If the reply did not come from the primary kdc, try again with + * the primary kdc. */ + + if (!use_primary) { + use_primary = 1; + + k5_save_ctx_error(context, ret, &errsave); + ret = get_init_creds_keytab(context, creds, client, keytab, + start_time, in_tkt_service, options, + &use_primary); + if (ret == 0) + goto cleanup; + + /* If the primary is unreachable, return the error from the replica we + * were able to contact. */ + if (ret == KRB5_KDC_UNREACH || ret == KRB5_REALM_CANT_RESOLVE || + ret == KRB5_REALM_UNKNOWN) + ret = k5_restore_ctx_error(context, &errsave); + } + + /* at this point, we have a response from the primary. Since we don't + do any prompting or changing for keytabs, that's it. */ + +cleanup: + if (arg_keytab == NULL) + krb5_kt_close(context, keytab); + k5_clear_error(&errsave); + + return(ret); +} +krb5_error_code KRB5_CALLCONV +krb5_get_in_tkt_with_keytab(krb5_context context, krb5_flags options, + krb5_address *const *addrs, krb5_enctype *ktypes, + krb5_preauthtype *pre_auth_types, + krb5_keytab arg_keytab, krb5_ccache ccache, + krb5_creds *creds, krb5_kdc_rep **ret_as_reply) +{ + krb5_error_code retval; + krb5_get_init_creds_opt *opts; + char * server = NULL; + krb5_keytab keytab; + krb5_principal client_princ, server_princ; + int use_primary = 0; + + retval = k5_populate_gic_opt(context, &opts, options, addrs, ktypes, + pre_auth_types, creds); + if (retval) + return retval; + + if (arg_keytab == NULL) { + retval = krb5_kt_default(context, &keytab); + if (retval) + goto cleanup; + } + else keytab = arg_keytab; + + retval = krb5_unparse_name( context, creds->server, &server); + if (retval) + goto cleanup; + server_princ = creds->server; + client_princ = creds->client; + retval = k5_get_init_creds(context, creds, creds->client, + krb5_prompter_posix, NULL, 0, server, opts, + get_as_key_keytab, (void *)keytab, &use_primary, + ret_as_reply); + krb5_free_unparsed_name( context, server); + if (retval) { + goto cleanup; + } + krb5_free_principal(context, creds->server); + krb5_free_principal(context, creds->client); + creds->client = client_princ; + creds->server = server_princ; + + /* store it in the ccache! */ + if (ccache) + if ((retval = krb5_cc_store_cred(context, ccache, creds))) + goto cleanup; +cleanup: + krb5_get_init_creds_opt_free(context, opts); + if (arg_keytab == NULL) + krb5_kt_close(context, keytab); + return retval; +} + +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/krb5/krb/gic_opt.c b/krb5-1.21.3/src/lib/krb5/krb/gic_opt.c new file mode 100644 index 00000000..11f0b719 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/gic_opt.c @@ -0,0 +1,500 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include "k5-int.h" +#include "int-proto.h" +#include + +#define GIC_OPT_EXTENDED 0x80000000 +#define GIC_OPT_SHALLOW_COPY 0x40000000 + +#define DEFAULT_FLAGS KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT + +#if defined(__MACH__) && defined(__APPLE__) +#include +#endif + +/* Match struct packing of krb5_get_init_creds_opt on macOS. */ +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)) +#pragma pack(push,2) +#endif +struct extended_options { + krb5_get_init_creds_opt opt; + int num_preauth_data; + krb5_gic_opt_pa_data *preauth_data; + char *fast_ccache_name; + krb5_ccache in_ccache; + krb5_ccache out_ccache; + krb5_flags fast_flags; + krb5_expire_callback_func expire_cb; + void *expire_data; + krb5_responder_fn responder; + void *responder_data; + int pac_request; /* -1 unset, 0 false, 1 true */ +}; +#if defined(__APPLE__) && (defined(__ppc__) || defined(__ppc64__) || defined(__i386__) || defined(__x86_64__)) +#pragma pack(pop) +#endif + +void KRB5_CALLCONV +krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) +{ + opt->flags = DEFAULT_FLAGS; +} + +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt, + krb5_deltat tkt_life) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_TKT_LIFE; + opt->tkt_life = tkt_life; +} + +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt, + krb5_deltat renew_life) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE; + opt->renew_life = renew_life; +} + +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt, + int forwardable) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_FORWARDABLE; + opt->forwardable = forwardable; +} + +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt, + int proxiable) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_PROXIABLE; + opt->proxiable = proxiable; +} + +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_canonicalize(krb5_get_init_creds_opt *opt, + int canonicalize) +{ + if (canonicalize) + opt->flags |= KRB5_GET_INIT_CREDS_OPT_CANONICALIZE; + else + opt->flags &= ~(KRB5_GET_INIT_CREDS_OPT_CANONICALIZE); +} + +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_anonymous (krb5_get_init_creds_opt *opt, + int anonymous) +{ + if (anonymous) + opt->flags |= KRB5_GET_INIT_CREDS_OPT_ANONYMOUS; + else opt->flags &= ~KRB5_GET_INIT_CREDS_OPT_ANONYMOUS; +} + +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt, krb5_enctype *etype_list, int etype_list_length) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST; + opt->etype_list = etype_list; + opt->etype_list_length = etype_list_length; +} + +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt, + krb5_address **addresses) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST; + opt->address_list = addresses; +} + +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, + krb5_preauthtype *preauth_list, + int preauth_list_length) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST; + opt->preauth_list = preauth_list; + opt->preauth_list_length = preauth_list_length; +} + +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, krb5_data *salt) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_SALT; + opt->salt = salt; +} + +void KRB5_CALLCONV +krb5_get_init_creds_opt_set_change_password_prompt( + krb5_get_init_creds_opt *opt, int prompt) +{ + if (prompt) + opt->flags |= KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT; + else + opt->flags &= ~KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_alloc(krb5_context context, + krb5_get_init_creds_opt **opt) +{ + struct extended_options *opte; + + if (opt == NULL) + return EINVAL; + *opt = NULL; + + /* Return an extended structure cast as a krb5_get_init_creds_opt. */ + opte = calloc(1, sizeof(*opte)); + if (opte == NULL) + return ENOMEM; + opte->opt.flags = DEFAULT_FLAGS | GIC_OPT_EXTENDED; + opte->pac_request = -1; + *opt = (krb5_get_init_creds_opt *)opte; + return 0; +} + +void KRB5_CALLCONV +krb5_get_init_creds_opt_free(krb5_context context, + krb5_get_init_creds_opt *opt) +{ + struct extended_options *opte = (struct extended_options *)opt; + int i; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return; + assert(!(opt->flags & GIC_OPT_SHALLOW_COPY)); + for (i = 0; i < opte->num_preauth_data; i++) { + free(opte->preauth_data[i].attr); + free(opte->preauth_data[i].value); + } + free(opte->preauth_data); + free(opte->fast_ccache_name); + free(opte); +} + +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_pa(krb5_context context, + krb5_get_init_creds_opt *opt, + const char *attr, + const char *value) +{ + struct extended_options *opte = (struct extended_options *)opt; + krb5_gic_opt_pa_data *t, *pa; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return EINVAL; + assert(!(opt->flags & GIC_OPT_SHALLOW_COPY)); + + /* Allocate space for another option. */ + t = realloc(opte->preauth_data, (opte->num_preauth_data + 1) * sizeof(*t)); + if (t == NULL) + return ENOMEM; + opte->preauth_data = t; + + /* Copy the option into the new slot. */ + pa = &opte->preauth_data[opte->num_preauth_data]; + pa->attr = strdup(attr); + if (pa->attr == NULL) + return ENOMEM; + pa->value = strdup(value); + if (pa->value == NULL) { + free(pa->attr); + return ENOMEM; + } + opte->num_preauth_data++; + + /* Give preauth modules a chance to look at the option now. */ + return krb5_preauth_supply_preauth_data(context, opt, attr, value); +} + +/* + * This function allows a preauth plugin to obtain preauth + * options. The preauth_data returned from this function + * should be freed by calling krb5_get_init_creds_opt_free_pa(). + * + * The 'opt' pointer supplied to this function must have been + * obtained using krb5_get_init_creds_opt_alloc() + */ +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_get_pa(krb5_context context, + krb5_get_init_creds_opt *opt, + int *num_preauth_data, + krb5_gic_opt_pa_data **preauth_data) +{ + struct extended_options *opte = (struct extended_options *)opt; + krb5_gic_opt_pa_data *p = NULL; + int i; + + if (num_preauth_data == NULL || preauth_data == NULL) + return EINVAL; + *num_preauth_data = 0; + *preauth_data = NULL; + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return EINVAL; + + if (opte->num_preauth_data == 0) + return 0; + + p = calloc(opte->num_preauth_data, sizeof(*p)); + if (p == NULL) + return ENOMEM; + + for (i = 0; i < opte->num_preauth_data; i++) { + p[i].attr = strdup(opte->preauth_data[i].attr); + p[i].value = strdup(opte->preauth_data[i].value); + if (p[i].attr == NULL || p[i].value == NULL) + goto cleanup; + } + *num_preauth_data = i; + *preauth_data = p; + return 0; + +cleanup: + krb5_get_init_creds_opt_free_pa(context, opte->num_preauth_data, p); + return ENOMEM; +} + +/* + * This function frees the preauth_data that was returned by + * krb5_get_init_creds_opt_get_pa(). + */ +void KRB5_CALLCONV +krb5_get_init_creds_opt_free_pa(krb5_context context, int num_preauth_data, + krb5_gic_opt_pa_data *preauth_data) +{ + int i; + + if (num_preauth_data <= 0 || preauth_data == NULL) + return; + + for (i = 0; i < num_preauth_data; i++) { + free(preauth_data[i].attr); + free(preauth_data[i].value); + } + free(preauth_data); +} + +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_fast_ccache_name(krb5_context context, + krb5_get_init_creds_opt *opt, + const char *ccache_name) +{ + struct extended_options *opte = (struct extended_options *)opt; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return EINVAL; + assert(!(opt->flags & GIC_OPT_SHALLOW_COPY)); + free(opte->fast_ccache_name); + opte->fast_ccache_name = strdup(ccache_name); + if (opte->fast_ccache_name == NULL) + return ENOMEM; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_fast_ccache(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_ccache ccache) +{ + krb5_error_code ret; + char *name; + + ret = krb5_cc_get_full_name(context, ccache, &name); + if (ret) + return ret; + ret = krb5_get_init_creds_opt_set_fast_ccache_name(context, opt, name); + free(name); + return ret; +} + +const char * +k5_gic_opt_get_fast_ccache_name(krb5_get_init_creds_opt *opt) +{ + struct extended_options *opte = (struct extended_options *)opt; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return NULL; + return opte->fast_ccache_name; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_in_ccache(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_ccache ccache) +{ + struct extended_options *opte = (struct extended_options *)opt; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return EINVAL; + opte->in_ccache = ccache; + return 0; +} + +krb5_ccache +k5_gic_opt_get_in_ccache(krb5_get_init_creds_opt *opt) +{ + struct extended_options *opte = (struct extended_options *)opt; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return NULL; + return opte->in_ccache; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_out_ccache(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_ccache ccache) +{ + struct extended_options *opte = (struct extended_options *)opt; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return EINVAL; + opte->out_ccache = ccache; + return 0; +} + +krb5_ccache +k5_gic_opt_get_out_ccache(krb5_get_init_creds_opt *opt) +{ + struct extended_options *opte = (struct extended_options *)opt; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return NULL; + return opte->out_ccache; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_fast_flags(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_flags flags) +{ + struct extended_options *opte = (struct extended_options *)opt; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return EINVAL; + opte->fast_flags = flags; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_get_fast_flags(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_flags *out_flags) +{ + struct extended_options *opte = (struct extended_options *)opt; + + if (out_flags == NULL) + return EINVAL; + *out_flags = 0; + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return EINVAL; + *out_flags = opte->fast_flags; + return 0; +} + +krb5_flags +k5_gic_opt_get_fast_flags(krb5_get_init_creds_opt *opt) +{ + struct extended_options *opte = (struct extended_options *)opt; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return 0; + return opte->fast_flags; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_expire_callback(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_expire_callback_func cb, + void *data) +{ + struct extended_options *opte = (struct extended_options *)opt; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return EINVAL; + opte->expire_cb = cb; + opte->expire_data = data; + return 0; +} + +void +k5_gic_opt_get_expire_cb(krb5_get_init_creds_opt *opt, + krb5_expire_callback_func *cb_out, void **data_out) +{ + struct extended_options *opte = (struct extended_options *)opt; + + *cb_out = NULL; + *data_out = NULL; + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return; + *cb_out = opte->expire_cb; + *data_out = opte->expire_data; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_responder(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_responder_fn responder, void *data) +{ + struct extended_options *opte = (struct extended_options *)opt; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return EINVAL; + opte->responder = responder; + opte->responder_data = data; + return 0; +} + +void +k5_gic_opt_get_responder(krb5_get_init_creds_opt *opt, + krb5_responder_fn *responder_out, void **data_out) +{ + struct extended_options *opte = (struct extended_options *)opt; + + *responder_out = NULL; + *data_out = NULL; + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return; + *responder_out = opte->responder; + *data_out = opte->responder_data; +} + +krb5_get_init_creds_opt * +k5_gic_opt_shallow_copy(krb5_get_init_creds_opt *opt) +{ + struct extended_options *opte; + + opte = calloc(1, sizeof(*opte)); + if (opt == NULL) + opte->opt.flags = DEFAULT_FLAGS; + else if (opt->flags & GIC_OPT_EXTENDED) + *opte = *(struct extended_options *)opt; + else + opte->opt = *opt; + opte->opt.flags |= GIC_OPT_SHALLOW_COPY; + return (krb5_get_init_creds_opt *)opte; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_opt_set_pac_request(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_boolean req_pac) +{ + struct extended_options *opte = (struct extended_options *)opt; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return EINVAL; + opte->pac_request = !!req_pac; + return 0; +} + +int +k5_gic_opt_pac_request(krb5_get_init_creds_opt *opt) +{ + struct extended_options *opte = (struct extended_options *)opt; + + if (opt == NULL || !(opt->flags & GIC_OPT_EXTENDED)) + return -1; + return opte->pac_request; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/gic_pwd.c b/krb5-1.21.3/src/lib/krb5/krb/gic_pwd.c new file mode 100644 index 00000000..9a3d5988 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/gic_pwd.c @@ -0,0 +1,473 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include "k5-int.h" +#include "com_err.h" +#include "init_creds_ctx.h" +#include "int-proto.h" +#include "os-proto.h" + +krb5_error_code +krb5_get_as_key_password(krb5_context context, + krb5_principal client, + krb5_enctype etype, + krb5_prompter_fct prompter, + void *prompter_data, + krb5_data *salt, + krb5_data *params, + krb5_keyblock *as_key, + void *gak_data, + k5_response_items *ritems) +{ + struct gak_password *gp = gak_data; + krb5_error_code ret; + krb5_data defsalt; + char *clientstr; + char promptstr[1024], pwbuf[1024]; + krb5_data pw; + krb5_prompt prompt; + krb5_prompt_type prompt_type; + const char *rpass; + + /* If we need to get the AS key via the responder, ask for it. */ + if (as_key == NULL) { + if (gp->password != NULL) + return 0; + + return k5_response_items_ask_question(ritems, + KRB5_RESPONDER_QUESTION_PASSWORD, + ""); + } + + /* If there's already a key of the correct etype, we're done. + If the etype is wrong, free the existing key, and make + a new one. + + XXX This was the old behavior, and was wrong in hw preauth + cases. Is this new behavior -- always asking -- correct in all + cases? */ + + if (as_key->length) { + if (as_key->enctype != etype) { + krb5_free_keyblock_contents (context, as_key); + as_key->length = 0; + } + } + + if (gp->password == NULL) { + /* Check the responder for the password. */ + rpass = k5_response_items_get_answer(ritems, + KRB5_RESPONDER_QUESTION_PASSWORD); + if (rpass != NULL) { + ret = alloc_data(&gp->storage, strlen(rpass)); + if (ret) + return ret; + memcpy(gp->storage.data, rpass, strlen(rpass)); + gp->password = &gp->storage; + } + } + + if (gp->password == NULL) { + if (prompter == NULL) + return(EIO); + + if ((ret = krb5_unparse_name(context, client, &clientstr))) + return(ret); + + snprintf(promptstr, sizeof(promptstr), _("Password for %s"), + clientstr); + free(clientstr); + + pw = make_data(pwbuf, sizeof(pwbuf)); + prompt.prompt = promptstr; + prompt.hidden = 1; + prompt.reply = &pw; + prompt_type = KRB5_PROMPT_TYPE_PASSWORD; + + /* PROMPTER_INVOCATION */ + k5_set_prompt_types(context, &prompt_type); + ret = (*prompter)(context, prompter_data, NULL, NULL, 1, &prompt); + k5_set_prompt_types(context, 0); + if (ret) + return(ret); + + ret = krb5int_copy_data_contents(context, &pw, &gp->storage); + zap(pw.data, pw.length); + if (ret) + return ret; + gp->password = &gp->storage; + } + + if (salt == NULL) { + if ((ret = krb5_principal2salt(context, client, &defsalt))) + return(ret); + + salt = &defsalt; + } else { + defsalt.length = 0; + } + + ret = krb5_c_string_to_key_with_params(context, etype, gp->password, salt, + params->data?params:NULL, as_key); + + if (defsalt.length) + free(defsalt.data); + + return(ret); +} + +krb5_error_code KRB5_CALLCONV +krb5_init_creds_set_password(krb5_context context, + krb5_init_creds_context ctx, + const char *password) +{ + char *s; + + s = strdup(password); + if (s == NULL) + return ENOMEM; + + zapfree(ctx->gakpw.storage.data, ctx->gakpw.storage.length); + ctx->gakpw.storage = string2data(s); + ctx->gakpw.password = &ctx->gakpw.storage; + ctx->gak_fct = krb5_get_as_key_password; + ctx->gak_data = &ctx->gakpw; + return 0; +} + +/* + * Create a temporary options structure for getting a kadmin/changepw ticket, + * based on the appplication-specified options. Propagate all application + * options which affect preauthentication, but not options which affect the + * resulting ticket or how it is stored. Set lifetime and flags appropriate + * for a ticket which we will use immediately and then discard. + * + * The caller should free the result with free(). + */ +static krb5_error_code +make_chpw_options(krb5_context context, krb5_get_init_creds_opt *in, + krb5_get_init_creds_opt **out) +{ + krb5_get_init_creds_opt *opt; + + *out = NULL; + opt = k5_gic_opt_shallow_copy(in); + if (opt == NULL) + return ENOMEM; + + /* Get a non-forwardable, non-proxiable, short-lifetime ticket. */ + krb5_get_init_creds_opt_set_tkt_life(opt, 5 * 60); + krb5_get_init_creds_opt_set_renew_life(opt, 0); + krb5_get_init_creds_opt_set_forwardable(opt, 0); + krb5_get_init_creds_opt_set_proxiable(opt, 0); + + /* Unset options which should only apply to the actual ticket. */ + opt->flags &= ~KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST; + opt->flags &= ~KRB5_GET_INIT_CREDS_OPT_ANONYMOUS; + + /* The output ccache should only be used for the actual ticket. */ + krb5_get_init_creds_opt_set_out_ccache(context, opt, NULL); + + *out = opt; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_init_creds_password(krb5_context context, + krb5_creds *creds, + krb5_principal client, + const char *password, + krb5_prompter_fct prompter, + void *data, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *options) +{ + krb5_error_code ret; + int use_primary; + krb5_kdc_rep *as_reply; + int tries; + krb5_creds chpw_creds; + krb5_get_init_creds_opt *chpw_opts = NULL; + struct gak_password gakpw; + krb5_data pw0, pw1; + char banner[1024], pw0array[1024], pw1array[1024]; + krb5_prompt prompt[2]; + krb5_prompt_type prompt_types[sizeof(prompt)/sizeof(prompt[0])]; + struct errinfo errsave = EMPTY_ERRINFO; + char *message; + + use_primary = 0; + as_reply = NULL; + memset(&chpw_creds, 0, sizeof(chpw_creds)); + memset(&gakpw, 0, sizeof(gakpw)); + + if (password != NULL) { + pw0 = string2data((char *)password); + gakpw.password = &pw0; + } + + /* first try: get the requested tkt from any kdc */ + + ret = k5_get_init_creds(context, creds, client, prompter, data, start_time, + in_tkt_service, options, krb5_get_as_key_password, + &gakpw, &use_primary, &as_reply); + + /* check for success */ + + if (ret == 0) + goto cleanup; + + /* If all the kdc's are unavailable, or if the error was due to a + user interrupt, fail */ + + if (ret == KRB5_KDC_UNREACH || ret == KRB5_REALM_CANT_RESOLVE || + ret == KRB5_LIBOS_PWDINTR || ret == KRB5_LIBOS_CANTREADPWD) + goto cleanup; + + /* If the reply did not come from the primary kdc, try again with + * the primary kdc. */ + + if (!use_primary) { + TRACE_GIC_PWD_PRIMARY(context); + use_primary = 1; + + k5_save_ctx_error(context, ret, &errsave); + if (as_reply) { + krb5_free_kdc_rep( context, as_reply); + as_reply = NULL; + } + ret = k5_get_init_creds(context, creds, client, prompter, data, + start_time, in_tkt_service, options, + krb5_get_as_key_password, &gakpw, &use_primary, + &as_reply); + + if (ret == 0) + goto cleanup; + + /* If the primary is unreachable, return the error from the replica we + * were able to contact and reset the use_primary flag. */ + if (ret == KRB5_KDC_UNREACH || ret == KRB5_REALM_CANT_RESOLVE || + ret == KRB5_REALM_UNKNOWN) { + ret = k5_restore_ctx_error(context, &errsave); + use_primary = 0; + } + } + + /* at this point, we have an error from the primary. if the error + is not password expired, or if it is but there's no prompter, + return this error */ + + if ((ret != KRB5KDC_ERR_KEY_EXP) || + (prompter == NULL)) + goto cleanup; + + /* historically the default has been to prompt for password change. + * if the change password prompt option has not been set, we continue + * to prompt. Prompting is only disabled if the option has been set + * and the value has been set to false. + */ + if (options && !(options->flags & KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT)) + goto cleanup; + TRACE_GIC_PWD_EXPIRED(context); + + /* ok, we have an expired password. Give the user a few chances + to change it */ + + ret = make_chpw_options(context, options, &chpw_opts); + if (ret) + goto cleanup; + ret = k5_get_init_creds(context, &chpw_creds, client, prompter, data, + start_time, "kadmin/changepw", chpw_opts, + krb5_get_as_key_password, &gakpw, &use_primary, + NULL); + if (ret) + goto cleanup; + + pw0.data = pw0array; + pw0.data[0] = '\0'; + pw0.length = sizeof(pw0array); + prompt[0].prompt = _("Enter new password"); + prompt[0].hidden = 1; + prompt[0].reply = &pw0; + prompt_types[0] = KRB5_PROMPT_TYPE_NEW_PASSWORD; + + pw1.data = pw1array; + pw1.data[0] = '\0'; + pw1.length = sizeof(pw1array); + prompt[1].prompt = _("Enter it again"); + prompt[1].hidden = 1; + prompt[1].reply = &pw1; + prompt_types[1] = KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN; + + strlcpy(banner, _("Password expired. You must change it now."), + sizeof(banner)); + + for (tries = 3; tries; tries--) { + TRACE_GIC_PWD_CHANGEPW(context, tries); + pw0.length = sizeof(pw0array); + pw1.length = sizeof(pw1array); + + /* PROMPTER_INVOCATION */ + k5_set_prompt_types(context, prompt_types); + ret = (*prompter)(context, data, 0, banner, + sizeof(prompt)/sizeof(prompt[0]), prompt); + k5_set_prompt_types(context, 0); + if (ret) + goto cleanup; + + if (strcmp(pw0.data, pw1.data) != 0) { + ret = KRB5_LIBOS_BADPWDMATCH; + snprintf(banner, sizeof(banner), + _("%s. Please try again."), error_message(ret)); + } else if (pw0.length == 0) { + ret = KRB5_CHPW_PWDNULL; + snprintf(banner, sizeof(banner), + _("%s. Please try again."), error_message(ret)); + } else { + int result_code; + krb5_data code_string; + krb5_data result_string; + + if ((ret = krb5_change_password(context, &chpw_creds, pw0array, + &result_code, &code_string, + &result_string))) + goto cleanup; + + /* the change succeeded. go on */ + + if (result_code == 0) { + free(code_string.data); + free(result_string.data); + break; + } + + /* set this in case the retry loop falls through */ + + ret = KRB5_CHPW_FAIL; + + if (result_code != KRB5_KPASSWD_SOFTERROR) { + free(code_string.data); + free(result_string.data); + goto cleanup; + } + + /* the error was soft, so try again */ + + if (krb5_chpw_message(context, &result_string, &message) != 0) + message = NULL; + + /* 100 is I happen to know that no code_string will be longer + than 100 chars */ + + if (message != NULL && strlen(message) > (sizeof(banner) - 100)) + message[sizeof(banner) - 100] = '\0'; + + snprintf(banner, sizeof(banner), + _("%.*s%s%s. Please try again.\n"), + (int) code_string.length, code_string.data, + message ? ": " : "", message ? message : ""); + + free(message); + free(code_string.data); + free(result_string.data); + } + } + + if (ret) + goto cleanup; + + /* The password change was successful. Get an initial ticket from the + * primary. This is the last try. The return from this is final. */ + + TRACE_GIC_PWD_CHANGED(context); + gakpw.password = &pw0; + ret = k5_get_init_creds(context, creds, client, prompter, data, + start_time, in_tkt_service, options, + krb5_get_as_key_password, &gakpw, &use_primary, + &as_reply); + if (ret) + goto cleanup; + +cleanup: + free(chpw_opts); + zapfree(gakpw.storage.data, gakpw.storage.length); + memset(pw0array, 0, sizeof(pw0array)); + memset(pw1array, 0, sizeof(pw1array)); + krb5_free_cred_contents(context, &chpw_creds); + if (as_reply) + krb5_free_kdc_rep(context, as_reply); + k5_clear_error(&errsave); + + return(ret); +} + +/* + Rewrites get_in_tkt in terms of newer get_init_creds API. + Attempts to get an initial ticket for creds->client to use server + creds->server, (realm is taken from creds->client), with options + options, and using creds->times.starttime, creds->times.endtime, + creds->times.renew_till as from, till, and rtime. + creds->times.renew_till is ignored unless the RENEWABLE option is requested. + + If addrs is non-NULL, it is used for the addresses requested. If it is + null, the system standard addresses are used. + + If password is non-NULL, it is converted using the cryptosystem entry + point for a string conversion routine, seeded with the client's name. + If password is passed as NULL, the password is read from the terminal, + and then converted into a key. + + A successful call will place the ticket in the credentials cache ccache. + + returns system errors, encryption errors +*/ +krb5_error_code KRB5_CALLCONV +krb5_get_in_tkt_with_password(krb5_context context, krb5_flags options, + krb5_address *const *addrs, krb5_enctype *ktypes, + krb5_preauthtype *pre_auth_types, + const char *password, krb5_ccache ccache, + krb5_creds *creds, krb5_kdc_rep **ret_as_reply) +{ + krb5_error_code retval; + struct gak_password gakpw; + krb5_data pw; + char * server; + krb5_principal server_princ, client_princ; + int use_primary = 0; + krb5_get_init_creds_opt *opts = NULL; + + memset(&gakpw, 0, sizeof(gakpw)); + if (password != NULL) { + pw = string2data((char *)password); + gakpw.password = &pw; + } + retval = k5_populate_gic_opt(context, &opts, options, addrs, ktypes, + pre_auth_types, creds); + if (retval) + return (retval); + retval = krb5_unparse_name( context, creds->server, &server); + if (retval) { + krb5_get_init_creds_opt_free(context, opts); + return (retval); + } + server_princ = creds->server; + client_princ = creds->client; + retval = k5_get_init_creds(context, creds, creds->client, + krb5_prompter_posix, NULL, 0, server, opts, + krb5_get_as_key_password, &gakpw, &use_primary, + ret_as_reply); + krb5_free_unparsed_name( context, server); + krb5_get_init_creds_opt_free(context, opts); + zapfree(gakpw.storage.data, gakpw.storage.length); + if (retval) { + return (retval); + } + krb5_free_principal( context, creds->server); + krb5_free_principal( context, creds->client); + creds->client = client_princ; + creds->server = server_princ; + /* store it in the ccache! */ + if (ccache) + if ((retval = krb5_cc_store_cred(context, ccache, creds))) + return (retval); + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/in_tkt_sky.c b/krb5-1.21.3/src/lib/krb5/krb/in_tkt_sky.c new file mode 100644 index 00000000..55c951a9 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/in_tkt_sky.c @@ -0,0 +1,120 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/in_tkt_sky.c */ +/* + * Copyright 1990,1991, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" + +/* Copy the caller-provided keyblock into the AS keyblock. */ +static krb5_error_code +get_as_key_skey(krb5_context context, krb5_principal client, + krb5_enctype etype, krb5_prompter_fct prompter, + void *prompter_data, krb5_data *salt, krb5_data *params, + krb5_keyblock *as_key, void *gak_data, + k5_response_items *ritems) +{ + const krb5_keyblock *key = gak_data; + + if (!krb5_c_valid_enctype(etype)) + return(KRB5_PROG_ETYPE_NOSUPP); + if (as_key->length) + krb5_free_keyblock_contents(context, as_key); + return krb5int_c_copy_keyblock_contents(context, key, as_key); +} + +/* + Similar to krb5_get_in_tkt_with_password. + + Attempts to get an initial ticket for creds->client to use server + creds->server, (realm is taken from creds->client), with options + options, and using creds->times.starttime, creds->times.endtime, + creds->times.renew_till as from, till, and rtime. + creds->times.renew_till is ignored unless the RENEWABLE option is requested. + + If addrs is non-NULL, it is used for the addresses requested. If it is + null, the system standard addresses are used. + + If keyblock is NULL, an appropriate key for creds->client is retrieved from + the system key store (e.g. /etc/krb5.keytab). If keyblock is non-NULL, it + is used as the decryption key. + + A successful call will place the ticket in the credentials cache ccache. + + returns system errors, encryption errors + +*/ +krb5_error_code KRB5_CALLCONV +krb5_get_in_tkt_with_skey(krb5_context context, krb5_flags options, + krb5_address *const *addrs, krb5_enctype *ktypes, + krb5_preauthtype *pre_auth_types, + const krb5_keyblock *key, krb5_ccache ccache, + krb5_creds *creds, krb5_kdc_rep **ret_as_reply) +{ + krb5_error_code retval; + char *server; + krb5_principal server_princ, client_princ; + int use_primary = 0; + krb5_get_init_creds_opt *opts = NULL; + + retval = k5_populate_gic_opt(context, &opts, options, addrs, ktypes, + pre_auth_types, creds); + if (retval) + return retval; + + retval = krb5_get_init_creds_opt_set_out_ccache(context, opts, ccache); + if (retval) + goto cleanup; + +#ifndef LEAN_CLIENT + if (key == NULL) { + retval = krb5_get_init_creds_keytab(context, creds, creds->client, + NULL /* keytab */, + creds->times.starttime, + NULL /* in_tkt_service */, + opts); + goto cleanup; + } +#endif /* LEAN_CLIENT */ + + retval = krb5_unparse_name(context, creds->server, &server); + if (retval) + goto cleanup; + server_princ = creds->server; + client_princ = creds->client; + retval = k5_get_init_creds(context, creds, creds->client, + krb5_prompter_posix, NULL, 0, server, opts, + get_as_key_skey, (void *)key, &use_primary, + ret_as_reply); + krb5_free_unparsed_name(context, server); + if (retval) + goto cleanup; + krb5_free_principal( context, creds->server); + krb5_free_principal( context, creds->client); + creds->client = client_princ; + creds->server = server_princ; +cleanup: + krb5_get_init_creds_opt_free(context, opts); + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/init_creds_ctx.h b/krb5-1.21.3/src/lib/krb5/krb/init_creds_ctx.h new file mode 100644 index 00000000..17d55dd7 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/init_creds_ctx.h @@ -0,0 +1,92 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ + +#ifndef KRB5_INIT_CREDS_CONTEXT +#define KRB5_INIT_CREDS_CONTEXT 1 + +#include "k5-json.h" +#include "int-proto.h" + +typedef struct krb5_preauth_req_context_st *krb5_preauth_req_context; + +struct krb5_responder_context_st { + k5_response_items *items; +}; + +struct gak_password { + krb5_data storage; + const krb5_data *password; +}; + +struct _krb5_init_creds_context { + krb5_get_init_creds_opt *opt; + krb5_get_init_creds_opt opt_storage; + krb5_boolean identify_realm; + const krb5_data *subject_cert; + krb5_principal keytab_princ; + char *in_tkt_service; + krb5_prompter_fct prompter; + void *prompter_data; + get_as_key_fn gak_fct; + void *gak_data; + krb5_timestamp request_time; + krb5_deltat start_time; + krb5_deltat tkt_life; + krb5_deltat renew_life; + krb5_boolean complete; + unsigned int loopcount; + struct gak_password gakpw; + krb5_error *err_reply; + krb5_pa_data **err_padata; + krb5_creds cred; + krb5_kdc_req *request; + krb5_kdc_rep *reply; + /** + * Stores the outer request body in order to feed into FAST for + * checksumming. This is maintained even if FAST is not used. This is not + * used for preauth: that requires the inner request body. For AS-only + * FAST it would be better for krb5int_fast_prep_req() to simply generate + * this. However for TGS FAST, the client needs to supply the + * to_be_checksummed data. Whether this should be refactored should be + * revisited as TGS fast is integrated. + */ + krb5_data *outer_request_body; + krb5_data *inner_request_body; /**< For preauth */ + krb5_data *encoded_previous_request; + struct krb5int_fast_request_state *fast_state; + krb5_pa_data **optimistic_padata; /* from gic options */ + krb5_pa_data **method_padata; /* from PREAUTH_REQUIRED or PREAUTH_FAILED */ + krb5_pa_data **more_padata; /* from MORE_PREAUTH_DATA_REQUIRED */ + krb5_boolean default_salt; + krb5_data salt; + krb5_data s2kparams; + krb5_keyblock as_key; + krb5_enctype etype; + krb5_boolean info_pa_permitted; + krb5_boolean restarted; + krb5_boolean fallback_disabled; + krb5_boolean encts_disabled; + struct krb5_responder_context_st rctx; + krb5_preauthtype selected_preauth_type; + krb5_preauthtype allowed_preauth_type; + k5_json_object cc_config_in; + k5_json_object cc_config_out; + /* Discovered offset of server time during preauth */ + krb5_timestamp pa_offset; + krb5_int32 pa_offset_usec; + enum { NO_OFFSET = 0, UNAUTH_OFFSET, AUTH_OFFSET } pa_offset_state; + krb5_preauth_req_context preauth_reqctx; +}; + +krb5_error_code +krb5_get_as_key_password(krb5_context context, + krb5_principal client, + krb5_enctype etype, + krb5_prompter_fct prompter, + void *prompter_data, + krb5_data *salt, + krb5_data *params, + krb5_keyblock *as_key, + void *gak_data, + k5_response_items *ritems); + +#endif /* !KRB5_INIT_CREDS_CONTEXT */ diff --git a/krb5-1.21.3/src/lib/krb5/krb/init_ctx.c b/krb5-1.21.3/src/lib/krb5/krb/init_ctx.c new file mode 100644 index 00000000..a6c2bbeb --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/init_ctx.c @@ -0,0 +1,596 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/init_ctx.c */ +/* + * Copyright 1994,1999,2000, 2002, 2003, 2007, 2008, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "os-proto.h" +#include +#include "brand.c" +#include "../krb5_libinit.h" + +static krb5_enctype default_enctype_list[] = { + ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_AES256_CTS_HMAC_SHA384_192, ENCTYPE_AES128_CTS_HMAC_SHA256_128, + ENCTYPE_DES3_CBC_SHA1, + ENCTYPE_ARCFOUR_HMAC, + ENCTYPE_CAMELLIA128_CTS_CMAC, ENCTYPE_CAMELLIA256_CTS_CMAC, + 0 +}; + +#if (defined(_WIN32)) +extern krb5_error_code krb5_vercheck(); +extern void krb5_win_ccdll_load(krb5_context context); +#endif + +#define DEFAULT_CLOCKSKEW 300 /* 5 min */ + +static krb5_error_code +get_integer(krb5_context ctx, const char *name, int def_val, int *int_out) +{ + krb5_error_code retval; + + retval = profile_get_integer(ctx->profile, KRB5_CONF_LIBDEFAULTS, + name, NULL, def_val, int_out); + if (retval) + TRACE_PROFILE_ERR(ctx, name, KRB5_CONF_LIBDEFAULTS, retval); + return retval; +} + +static krb5_error_code +get_boolean(krb5_context ctx, const char *name, int def_val, int *boolean_out) +{ + krb5_error_code retval; + + retval = profile_get_boolean(ctx->profile, KRB5_CONF_LIBDEFAULTS, + name, NULL, def_val, boolean_out); + if (retval) + TRACE_PROFILE_ERR(ctx, name, KRB5_CONF_LIBDEFAULTS, retval); + return retval; +} + +static krb5_error_code +get_tristate(krb5_context ctx, const char *name, const char *third_option, + int third_option_val, int def_val, int *val_out) +{ + krb5_error_code retval; + char *str; + int match; + + retval = profile_get_boolean(ctx->profile, KRB5_CONF_LIBDEFAULTS, name, + NULL, def_val, val_out); + if (retval != PROF_BAD_BOOLEAN) + return retval; + retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS, name, + NULL, NULL, &str); + if (retval) + return retval; + match = (strcasecmp(third_option, str) == 0); + free(str); + if (!match) + return EINVAL; + *val_out = third_option_val; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_init_context(krb5_context *context) +{ + /* + * This is rather silly, but should improve our chances of + * retaining the krb5_brand array in the final linked library, + * better than a static variable that's unreferenced after + * optimization, or even a non-static symbol that's not exported + * from the library nor referenced from anywhere else in the + * library. + * + * If someday we grow an API to actually return the string, we can + * get rid of this silliness. + */ + int my_zero = (krb5_brand[0] == 0); + + return krb5_init_context_profile(NULL, my_zero, context); +} + +krb5_error_code KRB5_CALLCONV +krb5_init_secure_context(krb5_context *context) +{ + return krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_SECURE, context); +} + +krb5_error_code +krb5int_init_context_kdc(krb5_context *context) +{ + return krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_KDC, context); +} + +krb5_error_code KRB5_CALLCONV +krb5_init_context_profile(profile_t profile, krb5_flags flags, + krb5_context *context_out) +{ + krb5_context ctx = 0; + krb5_error_code retval; + int tmp; + char *plugin_dir = NULL; + + /* Verify some assumptions. If the assumptions hold and the + compiler is optimizing, this should result in no code being + executed. If we're guessing "unsigned long long" instead + of using uint64_t, the possibility does exist that we're + wrong. */ + { + uint64_t i64; + assert(sizeof(i64) == 8); + i64 = 0, i64--, i64 >>= 62; + assert(i64 == 3); + i64 = 1, i64 <<= 31, i64 <<= 31, i64 <<= 1; + assert(i64 != 0); + i64 <<= 1; + assert(i64 == 0); + } + + retval = krb5int_initialize_library(); + if (retval) + return retval; + +#if (defined(_WIN32)) + /* + * Load the krbcc32.dll if necessary. We do this here so that + * we know to use API: later on during initialization. + * The context being NULL is ok. + */ + krb5_win_ccdll_load(ctx); + + /* + * krb5_vercheck() is defined in win_glue.c, and this is + * where we handle the timebomb and version server checks. + */ + retval = krb5_vercheck(); + if (retval) + return retval; +#endif + + *context_out = NULL; + + ctx = calloc(1, sizeof(struct _krb5_context)); + if (!ctx) + return ENOMEM; + ctx->magic = KV5M_CONTEXT; + + ctx->profile_secure = (flags & KRB5_INIT_CONTEXT_SECURE) != 0; + + retval = k5_os_init_context(ctx, profile, flags); + if (retval) + goto cleanup; + + ctx->trace_callback = NULL; +#ifndef DISABLE_TRACING + if (!ctx->profile_secure) + k5_init_trace(ctx); +#endif + + retval = get_boolean(ctx, KRB5_CONF_ALLOW_WEAK_CRYPTO, 0, &tmp); + if (retval) + goto cleanup; + ctx->allow_weak_crypto = tmp; + + retval = get_boolean(ctx, KRB5_CONF_ALLOW_DES3, 0, &tmp); + if (retval) + goto cleanup; + ctx->allow_des3 = tmp; + + retval = get_boolean(ctx, KRB5_CONF_ALLOW_RC4, 0, &tmp); + if (retval) + goto cleanup; + ctx->allow_rc4 = tmp; + + retval = get_boolean(ctx, KRB5_CONF_IGNORE_ACCEPTOR_HOSTNAME, 0, &tmp); + if (retval) + goto cleanup; + ctx->ignore_acceptor_hostname = tmp; + + retval = get_boolean(ctx, KRB5_CONF_ENFORCE_OK_AS_DELEGATE, 0, &tmp); + if (retval) + goto cleanup; + ctx->enforce_ok_as_delegate = tmp; + + retval = get_tristate(ctx, KRB5_CONF_DNS_CANONICALIZE_HOSTNAME, "fallback", + CANONHOST_FALLBACK, 1, &tmp); + if (retval) + goto cleanup; + ctx->dns_canonicalize_hostname = tmp; + + ctx->default_realm = 0; + get_integer(ctx, KRB5_CONF_CLOCKSKEW, DEFAULT_CLOCKSKEW, &tmp); + ctx->clockskew = tmp; + + get_integer(ctx, KRB5_CONF_KDC_DEFAULT_OPTIONS, KDC_OPT_RENEWABLE_OK, + &tmp); + ctx->kdc_default_options = tmp; +#define DEFAULT_KDC_TIMESYNC 1 + get_integer(ctx, KRB5_CONF_KDC_TIMESYNC, DEFAULT_KDC_TIMESYNC, &tmp); + ctx->library_options = tmp ? KRB5_LIBOPT_SYNC_KDCTIME : 0; + + retval = profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_PLUGIN_BASE_DIR, 0, + DEFAULT_PLUGIN_BASE_DIR, &plugin_dir); + if (!retval) + retval = k5_expand_path_tokens(ctx, plugin_dir, &ctx->plugin_base_dir); + if (retval) { + TRACE_PROFILE_ERR(ctx, KRB5_CONF_PLUGIN_BASE_DIR, + KRB5_CONF_LIBDEFAULTS, retval); + goto cleanup; + } + + /* + * We use a default file credentials cache of 3. See + * lib/krb5/krb/ccache/file/fcc.h for a description of the + * credentials cache types. + * + * Note: DCE 1.0.3a only supports a cache type of 1 + * DCE 1.1 supports a cache type of 2. + */ +#define DEFAULT_CCACHE_TYPE 4 + get_integer(ctx, KRB5_CONF_CCACHE_TYPE, DEFAULT_CCACHE_TYPE, &tmp); + ctx->fcc_default_format = tmp + 0x0500; + ctx->prompt_types = 0; + ctx->use_conf_ktypes = 0; + ctx->udp_pref_limit = -1; + + /* It's OK if this fails */ + (void)profile_get_string(ctx->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_ERR_FMT, NULL, NULL, &ctx->err_fmt); + *context_out = ctx; + ctx = NULL; + +cleanup: + profile_release_string(plugin_dir); + krb5_free_context(ctx); + return retval; +} + +void KRB5_CALLCONV +krb5_free_context(krb5_context ctx) +{ + if (ctx == NULL) + return; + k5_os_free_context(ctx); + + free(ctx->tgs_etypes); + ctx->tgs_etypes = NULL; + free(ctx->default_realm); + ctx->default_realm = 0; + + krb5_clear_error_message(ctx); + free(ctx->err_fmt); + +#ifndef DISABLE_TRACING + if (ctx->trace_callback) + ctx->trace_callback(ctx, NULL, ctx->trace_callback_data); +#endif + + k5_ccselect_free_context(ctx); + k5_hostrealm_free_context(ctx); + k5_localauth_free_context(ctx); + k5_plugin_free_context(ctx); + free(ctx->plugin_base_dir); + free(ctx->tls); + + ctx->magic = 0; + free(ctx); +} + +/* + * Set the desired default ktypes, making sure they are valid. + */ +krb5_error_code KRB5_CALLCONV +krb5_set_default_tgs_enctypes(krb5_context context, const krb5_enctype *etypes) +{ + krb5_error_code code; + krb5_enctype *list; + size_t src, dst; + + if (etypes) { + /* Empty list passed in. */ + if (etypes[0] == 0) + return EINVAL; + code = k5_copy_etypes(etypes, &list); + if (code) + return code; + + /* Filter list in place to exclude invalid and (optionally) weak + * enctypes. */ + for (src = dst = 0; list[src]; src++) { + if (!krb5_c_valid_enctype(list[src])) + continue; + if (!context->allow_weak_crypto + && krb5int_c_weak_enctype(list[src])) + continue; + list[dst++] = list[src]; + } + list[dst] = 0; /* Zero-terminate. */ + if (dst == 0) { + free(list); + return KRB5_CONFIG_ETYPE_NOSUPP; + } + } else { + list = NULL; + } + + free(context->tgs_etypes); + context->tgs_etypes = list; + return 0; +} + +/* Old name for above function. This is not a public API, but Samba (as of + * 2021-02-12) uses this name if it finds it in the library. */ +krb5_error_code +krb5_set_default_tgs_ktypes(krb5_context context, const krb5_enctype *etypes); + +krb5_error_code +krb5_set_default_tgs_ktypes(krb5_context context, const krb5_enctype *etypes) +{ + return krb5_set_default_tgs_enctypes(context, etypes); +} + +/* + * Add etype to, or remove etype from, the zero-terminated list *list_ptr, + * reallocating if the list size changes. Filter out weak enctypes if + * allow_weak is false. If memory allocation fails, set *list_ptr to NULL and + * do nothing for subsequent operations. + */ +static void +mod_list(krb5_enctype etype, krb5_boolean add, krb5_boolean allow_weak, + krb5_enctype **list_ptr) +{ + size_t i; + krb5_enctype *list = *list_ptr; + + /* Stop now if a previous allocation failed or the enctype is filtered. */ + if (list == NULL || (!allow_weak && krb5int_c_weak_enctype(etype))) + return; + if (add) { + /* Count entries; do nothing if etype is a duplicate. */ + for (i = 0; list[i] != 0; i++) { + if (list[i] == etype) + return; + } + /* Make room for the new entry and add it. */ + list = realloc(list, (i + 2) * sizeof(krb5_enctype)); + if (list != NULL) { + list[i] = etype; + list[i + 1] = 0; + } + } else { + /* Look for etype in the list. */ + for (i = 0; list[i] != 0; i++) { + if (list[i] != etype) + continue; + /* Perform removal. */ + for (; list[i + 1] != 0; i++) + list[i] = list[i + 1]; + list[i] = 0; + list = realloc(list, (i + 1) * sizeof(krb5_enctype)); + break; + } + } + /* Update *list_ptr, freeing the old value if realloc failed. */ + if (list == NULL) + free(*list_ptr); + *list_ptr = list; +} + +/* + * Set *result to a zero-terminated list of enctypes resulting from + * parsing profstr. profstr may be modified during parsing. + */ +krb5_error_code +krb5int_parse_enctype_list(krb5_context context, const char *profkey, + char *profstr, krb5_enctype *default_list, + krb5_enctype **result) +{ + char *token, *delim = " \t\r\n,", *save = NULL; + krb5_boolean sel, weak = context->allow_weak_crypto; + krb5_enctype etype, *list; + unsigned int i; + + *result = NULL; + + /* Set up an empty list. Allocation failure is detected at the end. */ + list = malloc(sizeof(krb5_enctype)); + if (list != NULL) + list[0] = 0; + + /* Walk through the words in profstr. */ + for (token = strtok_r(profstr, delim, &save); token; + token = strtok_r(NULL, delim, &save)) { + /* Determine if we are adding or removing enctypes. */ + sel = TRUE; + if (*token == '+' || *token == '-') + sel = (*token++ == '+'); + + if (strcasecmp(token, "DEFAULT") == 0) { + /* Set all enctypes in the default list. */ + for (i = 0; default_list[i]; i++) + mod_list(default_list[i], sel, weak, &list); + } else if (strcasecmp(token, "des3") == 0) { + mod_list(ENCTYPE_DES3_CBC_SHA1, sel, weak, &list); + } else if (strcasecmp(token, "aes") == 0) { + mod_list(ENCTYPE_AES256_CTS_HMAC_SHA1_96, sel, weak, &list); + mod_list(ENCTYPE_AES128_CTS_HMAC_SHA1_96, sel, weak, &list); + mod_list(ENCTYPE_AES256_CTS_HMAC_SHA384_192, sel, weak, &list); + mod_list(ENCTYPE_AES128_CTS_HMAC_SHA256_128, sel, weak, &list); + } else if (strcasecmp(token, "rc4") == 0) { + mod_list(ENCTYPE_ARCFOUR_HMAC, sel, weak, &list); + } else if (strcasecmp(token, "camellia") == 0) { + mod_list(ENCTYPE_CAMELLIA256_CTS_CMAC, sel, weak, &list); + mod_list(ENCTYPE_CAMELLIA128_CTS_CMAC, sel, weak, &list); + } else if (krb5_string_to_enctype(token, &etype) == 0) { + /* Set a specific enctype. */ + mod_list(etype, sel, weak, &list); + } else { + TRACE_ENCTYPE_LIST_UNKNOWN(context, profkey, token); + } + } + + if (list == NULL) + return ENOMEM; + if (list[0] == ENCTYPE_NULL) { + free(list); + return KRB5_CONFIG_ETYPE_NOSUPP; + } + *result = list; + return 0; +} + +krb5_error_code +krb5_get_default_in_tkt_ktypes(krb5_context context, krb5_enctype **ktypes) +{ + krb5_error_code ret; + char *profstr = NULL; + const char *profkey; + + *ktypes = NULL; + + profkey = KRB5_CONF_DEFAULT_TKT_ENCTYPES; + ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS, + profkey, NULL, NULL, &profstr); + if (ret) + return ret; + if (profstr == NULL) { + profkey = KRB5_CONF_PERMITTED_ENCTYPES; + ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS, + profkey, NULL, "DEFAULT", &profstr); + if (ret) + return ret; + } + + ret = krb5int_parse_enctype_list(context, profkey, profstr, + default_enctype_list, ktypes); + profile_release_string(profstr); + return ret; +} + +void +KRB5_CALLCONV +krb5_free_enctypes(krb5_context context, krb5_enctype *val) +{ + free (val); +} + +krb5_error_code KRB5_CALLCONV +krb5_get_tgs_ktypes(krb5_context context, krb5_const_principal princ, + krb5_enctype **ktypes) +{ + krb5_error_code ret; + char *profstr = NULL; + const char *profkey; + + *ktypes = NULL; + + /* Use only profile configuration when use_conf_ktypes is set. */ + if (!context->use_conf_ktypes && context->tgs_etypes != NULL) + return k5_copy_etypes(context->tgs_etypes, ktypes); + + profkey = KRB5_CONF_DEFAULT_TGS_ENCTYPES; + ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS, + profkey, NULL, NULL, &profstr); + if (ret) + return ret; + if (profstr == NULL) { + profkey = KRB5_CONF_PERMITTED_ENCTYPES; + ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS, + profkey, NULL, "DEFAULT", &profstr); + if (ret) + return ret; + } + + ret = krb5int_parse_enctype_list(context, profkey, profstr, + default_enctype_list, ktypes); + profile_release_string(profstr); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **ktypes) +{ + krb5_error_code ret; + char *profstr = NULL; + const char *profkey; + + *ktypes = NULL; + + if (context->tgs_etypes != NULL) + return k5_copy_etypes(context->tgs_etypes, ktypes); + + profkey = KRB5_CONF_PERMITTED_ENCTYPES; + ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS, + profkey, NULL, "DEFAULT", &profstr); + if (ret) + return ret; + + ret = krb5int_parse_enctype_list(context, profkey, profstr, + default_enctype_list, ktypes); + profile_release_string(profstr); + return ret; +} + +krb5_boolean +krb5_is_permitted_enctype(krb5_context context, krb5_enctype etype) +{ + krb5_enctype *list; + krb5_boolean ret; + + if (krb5_get_permitted_enctypes(context, &list)) + return FALSE; + ret = k5_etypes_contains(list, etype); + krb5_free_enctypes(context, list); + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/init_keyblock.c b/krb5-1.21.3/src/lib/krb5/krb/init_keyblock.c new file mode 100644 index 00000000..7e24cbde --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/init_keyblock.c @@ -0,0 +1,35 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/init_keyblock.c - Set up an empty keyblock */ +/* + * Copyright (C) 2002 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include + +krb5_error_code KRB5_CALLCONV +krb5_init_keyblock(krb5_context context, krb5_enctype enctype, + size_t length, krb5_keyblock **out) +{ + return krb5int_c_init_keyblock(context, enctype, length, out); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/int-proto.h b/krb5-1.21.3/src/lib/krb5/krb/int-proto.h new file mode 100644 index 00000000..b62f9049 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/int-proto.h @@ -0,0 +1,401 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/int-proto.h - Prototypes for libkrb5 internal functions */ +/* + * Copyright 1990,1991 the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef KRB5_INT_FUNC_PROTO__ +#define KRB5_INT_FUNC_PROTO__ + +struct krb5int_fast_request_state; + +typedef struct k5_response_items_st k5_response_items; + +typedef krb5_error_code +(*get_as_key_fn)(krb5_context, krb5_principal, krb5_enctype, krb5_prompter_fct, + void *prompter_data, krb5_data *salt, krb5_data *s2kparams, + krb5_keyblock *as_key, void *gak_data, + k5_response_items *ritems); + +krb5_error_code +krb5int_tgtname(krb5_context context, const krb5_data *, const krb5_data *, + krb5_principal *); + +krb5_error_code +krb5int_libdefault_boolean(krb5_context, const krb5_data *, const char *, + int *); +krb5_error_code +krb5int_libdefault_string(krb5_context context, const krb5_data *realm, + const char *option, char **ret_value); + + +krb5_error_code krb5_ser_authdata_init (krb5_context); +krb5_error_code krb5_ser_address_init (krb5_context); +krb5_error_code krb5_ser_authenticator_init (krb5_context); +krb5_error_code krb5_ser_checksum_init (krb5_context); +krb5_error_code krb5_ser_keyblock_init (krb5_context); +krb5_error_code krb5_ser_principal_init (krb5_context); +krb5_error_code krb5_ser_authdata_context_init (krb5_context); + +krb5_error_code +krb5_preauth_supply_preauth_data(krb5_context context, + krb5_get_init_creds_opt *opt, + const char *attr, const char *value); + +krb5_error_code +clpreauth_encrypted_challenge_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); + +krb5_error_code +clpreauth_encrypted_timestamp_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); + +krb5_error_code +clpreauth_sam2_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +clpreauth_otp_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +k5_get_cached_cred(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_creds **creds_out); + +#define IS_TGS_PRINC(p) ((p)->length == 2 && \ + data_eq_string((p)->data[0], KRB5_TGS_NAME)) + +typedef krb5_error_code +(*k5_pacb_fn)(krb5_context context, krb5_keyblock *subkey, krb5_kdc_req *req, + void *arg); + +krb5_error_code +krb5_get_cred_via_tkt_ext(krb5_context context, krb5_creds *tkt, + krb5_flags kdcoptions, krb5_address *const *address, + krb5_pa_data **in_padata, krb5_creds *in_cred, + k5_pacb_fn pacb_fn, void *pacb_data, + krb5_pa_data ***out_padata, + krb5_pa_data ***enc_padata, krb5_creds **out_cred, + krb5_keyblock **out_subkey); + +krb5_error_code +k5_generate_nonce(krb5_context context, int32_t *out); + +krb5_error_code +k5_make_tgs_req(krb5_context context, struct krb5int_fast_request_state *, + krb5_creds *tkt, krb5_flags kdcoptions, + krb5_address *const *address, krb5_pa_data **in_padata, + krb5_creds *in_cred, k5_pacb_fn pacb_fn, void *pacb_data, + krb5_data *req_asn1_out, krb5_timestamp *timestamp_out, + krb5_int32 *nonce_out, krb5_keyblock **subkey_out); + +krb5_error_code +krb5int_process_tgs_reply(krb5_context context, + struct krb5int_fast_request_state *, + krb5_data *response_data, + krb5_creds *tkt, + krb5_flags kdcoptions, + krb5_address *const *address, + krb5_pa_data **in_padata, + krb5_creds *in_cred, + krb5_timestamp timestamp, + krb5_int32 nonce, + krb5_keyblock *subkey, + krb5_pa_data ***out_padata, + krb5_pa_data ***out_enc_padata, + krb5_creds **out_cred); + +/* The subkey field is an output parameter; if a + * tgs-rep is received then the subkey will be filled + * in with the subkey needed to decrypt the TGS + * response. Otherwise it will be set to null. + */ +krb5_error_code krb5int_decode_tgs_rep(krb5_context, + struct krb5int_fast_request_state *, + krb5_data *, + const krb5_keyblock *, krb5_keyusage, + krb5_kdc_rep ** ); + +krb5_error_code +krb5int_validate_times(krb5_context, krb5_ticket_times *); + +krb5_error_code +krb5int_copy_authdatum(krb5_context, const krb5_authdata *, krb5_authdata **); + +/* Set replay data fields in rdata and caller_rdata according to the flags in + * authcon. */ +krb5_error_code +k5_privsafe_gen_rdata(krb5_context context, krb5_auth_context authcon, + krb5_replay_data *rdata, krb5_replay_data *caller_rdata); + +/* + * Set *local_out and *remote_out to addresses based on authcon. The resulting + * pointers should not be freed, but addresses may be placed into *lstorage and + * *rstorage which the caller must free, even on error. + */ +krb5_error_code +k5_privsafe_gen_addrs(krb5_context context, krb5_auth_context authcon, + krb5_address *lstorage, krb5_address *rstorage, + krb5_address **local_out, krb5_address **remote_out); + +/* + * If the DO_TIME flag is set in authcon, store a replay record in a memory + * replay cache (initializing one if necessary). Either enc or cksum must be + * non-null. If rdata is not null, also check that its timestamp is within + * clock skew. + */ +krb5_error_code +k5_privsafe_check_replay(krb5_context context, krb5_auth_context authcon, + const krb5_replay_data *rdata, + const krb5_enc_data *enc, const krb5_checksum *cksum); + +krb5_boolean +k5_privsafe_check_seqnum(krb5_context ctx, krb5_auth_context ac, + krb5_ui_4 in_seq); + +krb5_error_code +k5_privsafe_check_addrs(krb5_context context, krb5_auth_context ac, + krb5_address *msg_s_addr, krb5_address *msg_r_addr); + +krb5_error_code +krb5int_mk_chpw_req(krb5_context context, krb5_auth_context auth_context, + krb5_data *ap_req, const char *passwd, krb5_data *packet); + +krb5_error_code +krb5int_rd_chpw_rep(krb5_context context, krb5_auth_context auth_context, + krb5_data *packet, int *result_code, + krb5_data *result_data); + +krb5_error_code KRB5_CALLCONV +krb5_chpw_result_code_string(krb5_context context, int result_code, + char **result_codestr); + +krb5_error_code +krb5int_mk_setpw_req(krb5_context context, krb5_auth_context auth_context, + krb5_data *ap_req, krb5_principal targetprinc, + const char *passwd, krb5_data *packet); + +void +k5_ccselect_free_context(krb5_context context); + +krb5_error_code +k5_init_creds_get(krb5_context context, krb5_init_creds_context ctx, + int *use_primary); + +krb5_error_code +k5_init_creds_current_time(krb5_context context, krb5_init_creds_context ctx, + krb5_boolean allow_unauth, krb5_timestamp *time_out, + krb5_int32 *usec_out); + +krb5_error_code +k5_preauth(krb5_context context, krb5_init_creds_context ctx, + krb5_pa_data **in_padata, krb5_boolean must_preauth, + krb5_pa_data ***padata_out, krb5_preauthtype *pa_type_out); + +krb5_error_code +k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx, + krb5_preauthtype pa_type, krb5_error *err, + krb5_pa_data **err_padata, krb5_pa_data ***padata_out); + +void +k5_init_preauth_context(krb5_context context); + +void +k5_free_preauth_context(krb5_context context); + +krb5_error_code +k5_preauth_note_failed(krb5_init_creds_context ctx, krb5_preauthtype pa_type); + +void +k5_preauth_prepare_request(krb5_context context, krb5_get_init_creds_opt *opt, + krb5_kdc_req *request); + +void +k5_preauth_request_context_init(krb5_context context, + krb5_init_creds_context ctx); + +void +k5_preauth_request_context_fini(krb5_context context, + krb5_init_creds_context ctx); + +krb5_error_code +k5_preauth_check_context(krb5_context context, krb5_init_creds_context ctx); + +krb5_error_code +k5_response_items_new(k5_response_items **ri_out); + +void +k5_response_items_free(k5_response_items *ri); + +void +k5_response_items_reset(k5_response_items *ri); + +krb5_boolean +k5_response_items_empty(const k5_response_items *ri); + +const char * const * +k5_response_items_list_questions(const k5_response_items *ri); + +krb5_error_code +k5_response_items_ask_question(k5_response_items *ri, const char *question, + const char *challenge); + +const char * +k5_response_items_get_challenge(const k5_response_items *ri, + const char *question); + +krb5_error_code +k5_response_items_set_answer(k5_response_items *ri, const char *question, + const char *answer); + +const char * +k5_response_items_get_answer(const k5_response_items *ri, + const char *question); + +/* Save code and its extended message (if any) in out. */ +void +k5_save_ctx_error(krb5_context ctx, krb5_error_code code, struct errinfo *out); + +/* Return the code from in and restore its extended message (if any). */ +krb5_error_code +k5_restore_ctx_error(krb5_context ctx, struct errinfo *in); + +krb5_error_code +k5_encrypt_keyhelper(krb5_context context, krb5_key key, + krb5_keyusage keyusage, const krb5_data *plain, + krb5_enc_data *cipher); + +krb5_error_code KRB5_CALLCONV +k5_get_init_creds(krb5_context context, krb5_creds *creds, + krb5_principal client, krb5_prompter_fct prompter, + void *prompter_data, krb5_deltat start_time, + const char *in_tkt_service, krb5_get_init_creds_opt *options, + get_as_key_fn gak, void *gak_data, int *primary, + krb5_kdc_rep **as_reply); + +/* + * Make AS requests with the canonicalize flag set, stopping when we get a + * message indicating which realm the client principal is in. Set *client_out + * to a copy of client with the canonical realm. If subject_cert is non-null, + * include PA_S4U_X509_USER pa-data with the subject certificate each request. + * (See [MS-SFU] 3.1.5.1.1.1 and 3.1.5.1.1.2.) + */ +krb5_error_code +k5_identify_realm(krb5_context context, krb5_principal client, + const krb5_data *subject_cert, krb5_principal *client_out); + +krb5_error_code +k5_populate_gic_opt(krb5_context context, krb5_get_init_creds_opt **opt, + krb5_flags options, krb5_address *const *addrs, + krb5_enctype *ktypes, krb5_preauthtype *pre_auth_types, + krb5_creds *creds); + +krb5_error_code +k5_copy_creds_contents(krb5_context, const krb5_creds *, krb5_creds *); + +krb5_error_code +k5_build_conf_principals(krb5_context context, krb5_ccache id, + krb5_const_principal principal, const char *name, + krb5_creds *cred); + +krb5_error_code +k5_generate_and_save_subkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock, krb5_enctype enctype); + +krb5_error_code +k5_client_realm_path(krb5_context context, const krb5_data *client, + const krb5_data *server, krb5_data **rpath_out); + +size_t +k5_count_etypes(const krb5_enctype *list); + +krb5_error_code +k5_copy_etypes(const krb5_enctype *old_list, krb5_enctype **new_list); + +krb5_ccache +k5_gic_opt_get_in_ccache(krb5_get_init_creds_opt *opt); + +krb5_ccache +k5_gic_opt_get_out_ccache(krb5_get_init_creds_opt *opt); + +const char * +k5_gic_opt_get_fast_ccache_name(krb5_get_init_creds_opt *opt); + +krb5_flags +k5_gic_opt_get_fast_flags(krb5_get_init_creds_opt *opt); + +void +k5_gic_opt_get_expire_cb(krb5_get_init_creds_opt *opt, + krb5_expire_callback_func *cb_out, void **data_out); + +void +k5_gic_opt_get_responder(krb5_get_init_creds_opt *opt, + krb5_responder_fn *responder_out, void **data_out); + +/* + * Make a shallow copy of opt, with all pointer fields aliased, or NULL on an + * out-of-memory failure. The caller must free the result with free, and must + * not use it with the following functions: + * + * krb5_get_init_creds_opt_free + * krb5_get_init_creds_opt_set_pa + * krb5_get_init_creds_opt_set_fast_ccache + * krb5_get_init_creds_opt_set_fast_ccache_name + */ +krb5_get_init_creds_opt * +k5_gic_opt_shallow_copy(krb5_get_init_creds_opt *opt); + +/* Return -1 if no PAC request option was specified, or the option value as a + * boolean (0 or 1). */ +int +k5_gic_opt_pac_request(krb5_get_init_creds_opt *opt); + +krb5_error_code +k5_get_etype_info(krb5_context context, krb5_init_creds_context ctx, + krb5_pa_data **padata); + +/* + * Make an S4U2Proxy (constrained delegation) request. in_creds->client is the + * impersonator principal, and in_creds->second_ticket is the evidence + * ticket. + */ +krb5_error_code +k5_get_proxy_cred_from_kdc(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_creds **out_creds); + +/* Return true if mprinc will match any hostname in a host-based principal name + * (possibly due to ignore_acceptor_hostname) with krb5_sname_match(). */ +krb5_boolean +k5_sname_wildcard_host(krb5_context context, krb5_const_principal mprinc); + +/* Guess the appropriate name-type for a principal based on the name. */ +krb5_int32 +k5_infer_principal_type(krb5_principal princ); + +krb5_boolean +k5_pac_should_have_ticket_signature(krb5_const_principal sprinc); + +#endif /* KRB5_INT_FUNC_PROTO__ */ diff --git a/krb5-1.21.3/src/lib/krb5/krb/kdc_rep_dc.c b/krb5-1.21.3/src/lib/krb5/krb/kdc_rep_dc.c new file mode 100644 index 00000000..0aedcb7a --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/kdc_rep_dc.c @@ -0,0 +1,77 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/kdc_rep_dc.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +/* + * Decrypt the encrypted portion of the KDC_REP message, using the key + * passed. + * + */ + +/*ARGSUSED*/ +krb5_error_code +krb5_kdc_rep_decrypt_proc(krb5_context context, const krb5_keyblock *key, krb5_const_pointer decryptarg, krb5_kdc_rep *dec_rep) +{ + krb5_error_code retval; + krb5_data scratch; + krb5_enc_kdc_rep_part *local_encpart; + krb5_keyusage usage; + + if (decryptarg) { + usage = *(const krb5_keyusage *) decryptarg; + } else { + usage = KRB5_KEYUSAGE_AS_REP_ENCPART; + } + + /* set up scratch decrypt/decode area */ + + scratch.length = dec_rep->enc_part.ciphertext.length; + if (!(scratch.data = malloc(dec_rep->enc_part.ciphertext.length))) { + return(ENOMEM); + } + + /*dec_rep->enc_part.enctype;*/ + + if ((retval = krb5_c_decrypt(context, key, usage, 0, &dec_rep->enc_part, + &scratch))) { + free(scratch.data); + return(retval); + } + +#define clean_scratch() {memset(scratch.data, 0, scratch.length); \ + free(scratch.data);} + + /* and do the decode */ + retval = decode_krb5_enc_kdc_rep_part(&scratch, &local_encpart); + clean_scratch(); + if (retval) + return retval; + + dec_rep->enc_part2 = local_encpart; + + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/kerrs.c b/krb5-1.21.3/src/lib/krb5/krb/kerrs.c new file mode 100644 index 00000000..0e816792 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/kerrs.c @@ -0,0 +1,252 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/kerrs.c - Error message functions */ +/* + * Copyright 2006 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" + +#ifdef DEBUG +static int error_message_debug = 0; +#ifndef ERROR_MESSAGE_DEBUG +#define ERROR_MESSAGE_DEBUG() (error_message_debug != 0) +#endif +#endif + +void KRB5_CALLCONV_C +krb5_set_error_message(krb5_context ctx, krb5_error_code code, + const char *fmt, ...) +{ + va_list args; + + if (ctx == NULL) + return; + va_start(args, fmt); +#ifdef DEBUG + if (ERROR_MESSAGE_DEBUG()) { + fprintf(stderr, + "krb5_set_error_message(ctx=%p/err=%p, code=%ld, ...)\n", + ctx, &ctx->err, (long)code); + } +#endif + k5_vset_error(&ctx->err, code, fmt, args); +#ifdef DEBUG + if (ERROR_MESSAGE_DEBUG()) + fprintf(stderr, "->%s\n", ctx->err.msg); +#endif + va_end(args); +} + +void KRB5_CALLCONV +krb5_vset_error_message(krb5_context ctx, krb5_error_code code, + const char *fmt, va_list args) +{ +#ifdef DEBUG + if (ERROR_MESSAGE_DEBUG()) { + fprintf(stderr, "krb5_vset_error_message(ctx=%p, code=%ld, ...)\n", + ctx, (long)code); + } +#endif + if (ctx == NULL) + return; + k5_vset_error(&ctx->err, code, fmt, args); +#ifdef DEBUG + if (ERROR_MESSAGE_DEBUG()) + fprintf(stderr, "->%s\n", ctx->err.msg); +#endif +} + +void KRB5_CALLCONV +krb5_prepend_error_message(krb5_context ctx, krb5_error_code code, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + krb5_vwrap_error_message(ctx, code, code, fmt, ap); + va_end(ap); +} + +void KRB5_CALLCONV +krb5_vprepend_error_message(krb5_context ctx, krb5_error_code code, + const char *fmt, va_list ap) +{ + krb5_wrap_error_message(ctx, code, code, fmt, ap); +} + +void KRB5_CALLCONV +krb5_wrap_error_message(krb5_context ctx, krb5_error_code old_code, + krb5_error_code code, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + krb5_vwrap_error_message(ctx, old_code, code, fmt, ap); + va_end(ap); +} + +void KRB5_CALLCONV +krb5_vwrap_error_message(krb5_context ctx, krb5_error_code old_code, + krb5_error_code code, const char *fmt, va_list ap) +{ + const char *prev_msg; + char *prepend; + + if (ctx == NULL || vasprintf(&prepend, fmt, ap) < 0) + return; + prev_msg = k5_get_error(&ctx->err, old_code); + k5_set_error(&ctx->err, code, "%s: %s", prepend, prev_msg); + k5_free_error(&ctx->err, prev_msg); + free(prepend); +} + +/* Set the error message state of dest_ctx to that of src_ctx. */ +void KRB5_CALLCONV +krb5_copy_error_message(krb5_context dest_ctx, krb5_context src_ctx) +{ + if (dest_ctx == src_ctx) + return; + if (src_ctx->err.msg != NULL) { + k5_set_error(&dest_ctx->err, src_ctx->err.code, "%s", + src_ctx->err.msg); + } else { + k5_clear_error(&dest_ctx->err); + } +} + +/* Re-format msg using the format string err_fmt. Return an allocated result, + * or NULL if err_fmt is NULL or on allocation failure. */ +static char * +err_fmt_fmt(const char *err_fmt, long code, const char *msg) +{ + struct k5buf buf; + const char *p, *s; + + if (err_fmt == NULL) + return NULL; + + k5_buf_init_dynamic(&buf); + + s = err_fmt; + while ((p = strchr(s, '%')) != NULL) { + k5_buf_add_len(&buf, s, p - s); + s = p; + if (p[1] == '\0') + break; + else if (p[1] == 'M') + k5_buf_add(&buf, msg); + else if (p[1] == 'C') + k5_buf_add_fmt(&buf, "%ld", code); + else if (p[1] == '%') + k5_buf_add(&buf, "%"); + else + k5_buf_add_fmt(&buf, "%%%c", p[1]); + s += 2; + } + k5_buf_add(&buf, s); /* Remainder after last token */ + return k5_buf_cstring(&buf); +} + +const char * KRB5_CALLCONV +krb5_get_error_message(krb5_context ctx, krb5_error_code code) +{ + const char *std, *custom; + +#ifdef DEBUG + if (ERROR_MESSAGE_DEBUG()) + fprintf(stderr, "krb5_get_error_message(%p, %ld)\n", ctx, (long)code); +#endif + if (ctx == NULL) + return error_message(code); + + std = k5_get_error(&ctx->err, code); + custom = err_fmt_fmt(ctx->err_fmt, code, std); + if (custom != NULL) { + free((char *)std); + return custom; + } + return std; +} + +void KRB5_CALLCONV +krb5_free_error_message(krb5_context ctx, const char *msg) +{ +#ifdef DEBUG + if (ERROR_MESSAGE_DEBUG()) + fprintf(stderr, "krb5_free_error_message(%p, %p)\n", ctx, msg); +#endif + if (ctx == NULL) + return; + k5_free_error(&ctx->err, msg); +} + +void KRB5_CALLCONV +krb5_clear_error_message(krb5_context ctx) +{ +#ifdef DEBUG + if (ERROR_MESSAGE_DEBUG()) + fprintf(stderr, "krb5_clear_error_message(%p)\n", ctx); +#endif + if (ctx == NULL) + return; + k5_clear_error(&ctx->err); +} + +void +k5_save_ctx_error(krb5_context ctx, krb5_error_code code, struct errinfo *out) +{ + out->code = code; + out->msg = NULL; + if (ctx != NULL && ctx->err.code == code) { + out->msg = ctx->err.msg; + ctx->err.code = 0; + ctx->err.msg = NULL; + } +} + +krb5_error_code +k5_restore_ctx_error(krb5_context ctx, struct errinfo *in) +{ + krb5_error_code code = in->code; + + if (ctx != NULL) { + k5_clear_error(&ctx->err); + ctx->err.code = in->code; + ctx->err.msg = in->msg; + in->msg = NULL; + } else { + k5_clear_error(in); + } + return code; +} + +/* If ctx contains an extended error message for oldcode, change it to be an + * extended error message for newcode. */ +void +k5_change_error_message_code(krb5_context ctx, krb5_error_code oldcode, + krb5_error_code newcode) +{ + if (ctx != NULL && ctx->err.msg != NULL && ctx->err.code == oldcode) + ctx->err.code = newcode; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/kfree.c b/krb5-1.21.3/src/lib/krb5/krb/kfree.c new file mode 100644 index 00000000..b4503d26 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/kfree.c @@ -0,0 +1,916 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/kfree.c */ +/* + * Copyright 1990-1998, 2009 by the Massachusetts Institute of Technology. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "k5-int.h" +#include "k5-spake.h" +#include + +void KRB5_CALLCONV +krb5_free_address(krb5_context context, krb5_address *val) +{ + if (val == NULL) + return; + free(val->contents); + free(val); +} + +void KRB5_CALLCONV +krb5_free_addresses(krb5_context context, krb5_address **val) +{ + krb5_address **temp; + + if (val == NULL) + return; + for (temp = val; *temp; temp++) { + free((*temp)->contents); + free(*temp); + } + free(val); +} + +void KRB5_CALLCONV +krb5_free_ap_rep(krb5_context context, krb5_ap_rep *val) +{ + if (val == NULL) + return; + free(val->enc_part.ciphertext.data); + free(val); +} + +void KRB5_CALLCONV +krb5_free_ap_req(krb5_context context, krb5_ap_req *val) +{ + if (val == NULL) + return; + krb5_free_ticket(context, val->ticket); + free(val->authenticator.ciphertext.data); + free(val); +} + +void KRB5_CALLCONV +krb5_free_ap_rep_enc_part(krb5_context context, krb5_ap_rep_enc_part *val) +{ + if (val == NULL) + return; + krb5_free_keyblock(context, val->subkey); + free(val); +} + +void KRB5_CALLCONV +krb5_free_authenticator_contents(krb5_context context, krb5_authenticator *val) +{ + if (val == NULL) + return; + krb5_free_checksum(context, val->checksum); + val->checksum = 0; + krb5_free_principal(context, val->client); + val->client = 0; + krb5_free_keyblock(context, val->subkey); + val->subkey = 0; + krb5_free_authdata(context, val->authorization_data); + val->authorization_data = 0; +} + +void KRB5_CALLCONV +krb5_free_authenticator(krb5_context context, krb5_authenticator *val) +{ + if (val == NULL) + return; + krb5_free_authenticator_contents(context, val); + free(val); +} + +void KRB5_CALLCONV +krb5_free_checksum(krb5_context context, krb5_checksum *val) +{ + if (val == NULL) + return; + krb5_free_checksum_contents(context, val); + free(val); +} + +void KRB5_CALLCONV +krb5_free_checksum_contents(krb5_context context, krb5_checksum *val) +{ + if (val == NULL) + return; + free(val->contents); + val->contents = NULL; + val->length = 0; +} + +void KRB5_CALLCONV +krb5_free_cred(krb5_context context, krb5_cred *val) +{ + if (val == NULL) + return; + krb5_free_tickets(context, val->tickets); + free(val->enc_part.ciphertext.data); + free(val); +} + +/* + * krb5_free_cred_contents zeros out the session key, and then frees + * the credentials structures + */ + +void KRB5_CALLCONV +krb5_free_cred_contents(krb5_context context, krb5_creds *val) +{ + if (val == NULL) + return; + krb5_free_principal(context, val->client); + val->client = 0; + krb5_free_principal(context, val->server); + val->server = 0; + krb5_free_keyblock_contents(context, &val->keyblock); + free(val->ticket.data); + val->ticket.data = 0; + free(val->second_ticket.data); + val->second_ticket.data = 0; + krb5_free_addresses(context, val->addresses); + val->addresses = 0; + krb5_free_authdata(context, val->authdata); + val->authdata = 0; +} + +void KRB5_CALLCONV +krb5_free_cred_enc_part(krb5_context context, krb5_cred_enc_part *val) +{ + krb5_cred_info **temp; + + if (val == NULL) + return; + krb5_free_address(context, val->r_address); + val->r_address = 0; + krb5_free_address(context, val->s_address); + val->s_address = 0; + + if (val->ticket_info) { + for (temp = val->ticket_info; *temp; temp++) { + krb5_free_keyblock(context, (*temp)->session); + krb5_free_principal(context, (*temp)->client); + krb5_free_principal(context, (*temp)->server); + krb5_free_addresses(context, (*temp)->caddrs); + free(*temp); + } + free(val->ticket_info); + val->ticket_info = 0; + } +} + + +void KRB5_CALLCONV +krb5_free_creds(krb5_context context, krb5_creds *val) +{ + if (val == NULL) + return; + krb5_free_cred_contents(context, val); + free(val); +} + + +void KRB5_CALLCONV +krb5_free_data(krb5_context context, krb5_data *val) +{ + if (val == NULL) + return; + free(val->data); + free(val); +} + + +void KRB5_CALLCONV +krb5_free_octet_data(krb5_context context, krb5_octet_data *val) +{ + if (val == NULL) + return; + free(val->data); + free(val); +} + +void KRB5_CALLCONV +krb5_free_data_contents(krb5_context context, krb5_data *val) +{ + if (val == NULL) + return; + free(val->data); + val->data = NULL; + val->length = 0; +} + +void KRB5_CALLCONV +krb5_free_enc_data(krb5_context context, krb5_enc_data *val) +{ + if (val == NULL) + return; + krb5_free_data_contents(context, &val->ciphertext); + free(val); +} + +void krb5_free_etype_info(krb5_context context, krb5_etype_info info) +{ + int i; + + if (info == NULL) + return; + for (i=0; info[i] != NULL; i++) { + free(info[i]->salt); + krb5_free_data_contents(context, &info[i]->s2kparams); + free(info[i]); + } + free(info); +} + + +void KRB5_CALLCONV +krb5_free_enc_kdc_rep_part(krb5_context context, krb5_enc_kdc_rep_part *val) +{ + if (val == NULL) + return; + krb5_free_keyblock(context, val->session); + krb5_free_last_req(context, val->last_req); + krb5_free_principal(context, val->server); + krb5_free_addresses(context, val->caddrs); + krb5_free_pa_data(context, val->enc_padata); + free(val); +} + +void KRB5_CALLCONV +krb5_free_enc_tkt_part(krb5_context context, krb5_enc_tkt_part *val) +{ + if (val == NULL) + return; + krb5_free_keyblock(context, val->session); + krb5_free_principal(context, val->client); + free(val->transited.tr_contents.data); + krb5_free_addresses(context, val->caddrs); + krb5_free_authdata(context, val->authorization_data); + free(val); +} + + +void KRB5_CALLCONV +krb5_free_error(krb5_context context, krb5_error *val) +{ + if (val == NULL) + return; + krb5_free_principal(context, val->client); + krb5_free_principal(context, val->server); + free(val->text.data); + free(val->e_data.data); + free(val); +} + +void KRB5_CALLCONV +krb5_free_kdc_rep(krb5_context context, krb5_kdc_rep *val) +{ + if (val == NULL) + return; + krb5_free_pa_data(context, val->padata); + krb5_free_principal(context, val->client); + krb5_free_ticket(context, val->ticket); + free(val->enc_part.ciphertext.data); + krb5_free_enc_kdc_rep_part(context, val->enc_part2); + free(val); +} + + +void KRB5_CALLCONV +krb5_free_kdc_req(krb5_context context, krb5_kdc_req *val) +{ + if (val == NULL) + return; + krb5_free_pa_data(context, val->padata); + krb5_free_principal(context, val->client); + krb5_free_principal(context, val->server); + free(val->ktype); + krb5_free_addresses(context, val->addresses); + free(val->authorization_data.ciphertext.data); + krb5_free_authdata(context, val->unenc_authdata); + krb5_free_tickets(context, val->second_ticket); + free(val); +} + +void KRB5_CALLCONV +krb5_free_keyblock_contents(krb5_context context, krb5_keyblock *key) +{ + krb5int_c_free_keyblock_contents (context, key); +} + +void KRB5_CALLCONV +krb5_free_keyblock(krb5_context context, krb5_keyblock *val) +{ + krb5int_c_free_keyblock (context, val); +} + + + +void KRB5_CALLCONV +krb5_free_last_req(krb5_context context, krb5_last_req_entry **val) +{ + krb5_last_req_entry **temp; + + if (val == NULL) + return; + for (temp = val; *temp; temp++) + free(*temp); + free(val); +} + +void +k5_zapfree_pa_data(krb5_pa_data **val) +{ + krb5_pa_data **pa; + + if (val == NULL) + return; + for (pa = val; *pa != NULL; pa++) { + zapfree((*pa)->contents, (*pa)->length); + zapfree(*pa, sizeof(**pa)); + } + free(val); +} + +void KRB5_CALLCONV +krb5_free_pa_data(krb5_context context, krb5_pa_data **val) +{ + krb5_pa_data **temp; + + if (val == NULL) + return; + for (temp = val; *temp; temp++) { + free((*temp)->contents); + free(*temp); + } + free(val); +} + +void KRB5_CALLCONV +krb5_free_principal(krb5_context context, krb5_principal val) +{ + krb5_int32 i; + + if (!val) + return; + + if (val->data) { + i = val->length; + while(--i >= 0) + free(val->data[i].data); + free(val->data); + } + free(val->realm.data); + free(val); +} + +void KRB5_CALLCONV +krb5_free_priv(krb5_context context, krb5_priv *val) +{ + if (val == NULL) + return; + free(val->enc_part.ciphertext.data); + free(val); +} + +void KRB5_CALLCONV +krb5_free_priv_enc_part(krb5_context context, krb5_priv_enc_part *val) +{ + if (val == NULL) + return; + free(val->user_data.data); + krb5_free_address(context, val->r_address); + krb5_free_address(context, val->s_address); + free(val); +} + +void KRB5_CALLCONV +krb5_free_safe(krb5_context context, krb5_safe *val) +{ + if (val == NULL) + return; + free(val->user_data.data); + krb5_free_address(context, val->r_address); + krb5_free_address(context, val->s_address); + krb5_free_checksum(context, val->checksum); + free(val); +} + + +void KRB5_CALLCONV +krb5_free_ticket(krb5_context context, krb5_ticket *val) +{ + if (val == NULL) + return; + krb5_free_principal(context, val->server); + free(val->enc_part.ciphertext.data); + krb5_free_enc_tkt_part(context, val->enc_part2); + free(val); +} + +void KRB5_CALLCONV +krb5_free_tickets(krb5_context context, krb5_ticket **val) +{ + krb5_ticket **temp; + + if (val == NULL) + return; + for (temp = val; *temp; temp++) + krb5_free_ticket(context, *temp); + free(val); +} + + +void KRB5_CALLCONV +krb5_free_tgt_creds(krb5_context context, krb5_creds **tgts) +{ + krb5_creds **tgtpp; + if (tgts == NULL) + return; + for (tgtpp = tgts; *tgtpp; tgtpp++) + krb5_free_creds(context, *tgtpp); + free(tgts); +} + +void KRB5_CALLCONV +krb5_free_tkt_authent(krb5_context context, krb5_tkt_authent *val) +{ + if (val == NULL) + return; + krb5_free_ticket(context, val->ticket); + krb5_free_authenticator(context, val->authenticator); + free(val); +} + +void KRB5_CALLCONV +krb5_free_unparsed_name(krb5_context context, char *val) +{ + if (val != NULL) + free(val); +} + +void KRB5_CALLCONV +krb5_free_string(krb5_context context, char *val) +{ + free(val); +} + +void KRB5_CALLCONV +krb5_free_sam_challenge_2(krb5_context ctx, krb5_sam_challenge_2 *sc2) +{ + if (!sc2) + return; + krb5_free_sam_challenge_2_contents(ctx, sc2); + free(sc2); +} + +void KRB5_CALLCONV +krb5_free_sam_challenge_2_contents(krb5_context ctx, + krb5_sam_challenge_2 *sc2) +{ + krb5_checksum **cksump; + + if (!sc2) + return; + if (sc2->sam_challenge_2_body.data) + krb5_free_data_contents(ctx, &sc2->sam_challenge_2_body); + if (sc2->sam_cksum) { + cksump = sc2->sam_cksum; + while (*cksump) { + krb5_free_checksum(ctx, *cksump); + cksump++; + } + free(sc2->sam_cksum); + sc2->sam_cksum = 0; + } +} + +void KRB5_CALLCONV +krb5_free_sam_challenge_2_body(krb5_context ctx, + krb5_sam_challenge_2_body *sc2) +{ + if (!sc2) + return; + krb5_free_sam_challenge_2_body_contents(ctx, sc2); + free(sc2); +} + +void KRB5_CALLCONV +krb5_free_sam_challenge_2_body_contents(krb5_context ctx, + krb5_sam_challenge_2_body *sc2) +{ + if (!sc2) + return; + if (sc2->sam_type_name.data) + krb5_free_data_contents(ctx, &sc2->sam_type_name); + if (sc2->sam_track_id.data) + krb5_free_data_contents(ctx, &sc2->sam_track_id); + if (sc2->sam_challenge_label.data) + krb5_free_data_contents(ctx, &sc2->sam_challenge_label); + if (sc2->sam_challenge.data) + krb5_free_data_contents(ctx, &sc2->sam_challenge); + if (sc2->sam_response_prompt.data) + krb5_free_data_contents(ctx, &sc2->sam_response_prompt); + if (sc2->sam_pk_for_sad.data) + krb5_free_data_contents(ctx, &sc2->sam_pk_for_sad); +} + +void KRB5_CALLCONV +krb5_free_sam_response_2(krb5_context ctx, krb5_sam_response_2 *sr2) +{ + if (!sr2) + return; + krb5_free_sam_response_2_contents(ctx, sr2); + free(sr2); +} + +void KRB5_CALLCONV +krb5_free_sam_response_2_contents(krb5_context ctx, krb5_sam_response_2 *sr2) +{ + if (!sr2) + return; + if (sr2->sam_track_id.data) + krb5_free_data_contents(ctx, &sr2->sam_track_id); + if (sr2->sam_enc_nonce_or_sad.ciphertext.data) + krb5_free_data_contents(ctx, &sr2->sam_enc_nonce_or_sad.ciphertext); +} + +void KRB5_CALLCONV +krb5_free_enc_sam_response_enc_2(krb5_context ctx, + krb5_enc_sam_response_enc_2 *esre2) +{ + if (!esre2) + return; + krb5_free_enc_sam_response_enc_2_contents(ctx, esre2); + free(esre2); +} + +void KRB5_CALLCONV +krb5_free_enc_sam_response_enc_2_contents(krb5_context ctx, + krb5_enc_sam_response_enc_2 *esre2) +{ + if (!esre2) + return; + if (esre2->sam_sad.data) + krb5_free_data_contents(ctx, &esre2->sam_sad); +} + +void KRB5_CALLCONV +krb5_free_pa_enc_ts(krb5_context ctx, krb5_pa_enc_ts *pa_enc_ts) +{ + if (!pa_enc_ts) + return; + free(pa_enc_ts); +} + +void KRB5_CALLCONV +krb5_free_pa_for_user(krb5_context context, krb5_pa_for_user *req) +{ + if (req == NULL) + return; + krb5_free_principal(context, req->user); + req->user = NULL; + krb5_free_checksum_contents(context, &req->cksum); + krb5_free_data_contents(context, &req->auth_package); + free(req); +} + +void KRB5_CALLCONV +krb5_free_s4u_userid_contents(krb5_context context, krb5_s4u_userid *user_id) +{ + if (user_id == NULL) + return; + user_id->nonce = 0; + krb5_free_principal(context, user_id->user); + user_id->user = NULL; + krb5_free_data_contents(context, &user_id->subject_cert); + user_id->subject_cert.length = 0; + user_id->subject_cert.data = NULL; + user_id->options = 0; +} + +void KRB5_CALLCONV +krb5_free_pa_s4u_x509_user(krb5_context context, krb5_pa_s4u_x509_user *req) +{ + if (req == NULL) + return; + krb5_free_s4u_userid_contents(context, &req->user_id); + krb5_free_checksum_contents(context, &req->cksum); + free(req); +} + +void KRB5_CALLCONV +krb5_free_pa_pac_req(krb5_context context, + krb5_pa_pac_req *req) +{ + free(req); +} + +void KRB5_CALLCONV +krb5_free_fast_req(krb5_context context, krb5_fast_req *val) +{ + if (val == NULL) + return; + krb5_free_kdc_req(context, val->req_body); + free(val); +} + +void KRB5_CALLCONV +krb5_free_fast_armor(krb5_context context, krb5_fast_armor *val) +{ + if (val == NULL) + return; + krb5_free_data_contents(context, &val->armor_value); + free(val); +} + +void KRB5_CALLCONV +krb5_free_fast_response(krb5_context context, krb5_fast_response *val) +{ + if (!val) + return; + krb5_free_pa_data(context, val->padata); + krb5_free_fast_finished(context, val->finished); + krb5_free_keyblock(context, val->strengthen_key); + free(val); +} + +void KRB5_CALLCONV +krb5_free_fast_finished(krb5_context context, krb5_fast_finished *val) +{ + if (!val) + return; + krb5_free_principal(context, val->client); + krb5_free_checksum_contents(context, &val->ticket_checksum); + free(val); +} + +void KRB5_CALLCONV +krb5_free_fast_armored_req(krb5_context context, krb5_fast_armored_req *val) +{ + if (val == NULL) + return; + if (val->armor) + krb5_free_fast_armor(context, val->armor); + krb5_free_data_contents(context, &val->enc_part.ciphertext); + if (val->req_checksum.contents) + krb5_free_checksum_contents(context, &val->req_checksum); + free(val); +} + +void +k5_free_data_ptr_list(krb5_data **list) +{ + int i; + + for (i = 0; list != NULL && list[i] != NULL; i++) + krb5_free_data(NULL, list[i]); + free(list); +} + +void KRB5_CALLCONV +krb5int_free_data_list(krb5_context context, krb5_data *data) +{ + int i; + + if (data == NULL) + return; + + for (i = 0; data[i].data != NULL; i++) + free(data[i].data); + + free(data); +} + +void KRB5_CALLCONV +krb5_free_ad_kdcissued(krb5_context context, krb5_ad_kdcissued *val) +{ + if (val == NULL) + return; + + krb5_free_checksum_contents(context, &val->ad_checksum); + krb5_free_principal(context, val->i_principal); + krb5_free_authdata(context, val->elements); + free(val); +} + +void KRB5_CALLCONV +krb5_free_iakerb_header(krb5_context context, krb5_iakerb_header *val) +{ + if (val == NULL) + return ; + + krb5_free_data_contents(context, &val->target_realm); + krb5_free_data(context, val->cookie); + free(val); +} + +void KRB5_CALLCONV +krb5_free_iakerb_finished(krb5_context context, krb5_iakerb_finished *val) +{ + if (val == NULL) + return ; + + krb5_free_checksum_contents(context, &val->checksum); + free(val); +} + +void +k5_free_algorithm_identifier(krb5_context context, + krb5_algorithm_identifier *val) +{ + if (val == NULL) + return; + free(val->algorithm.data); + free(val->parameters.data); + free(val); +} + +void +k5_free_otp_tokeninfo(krb5_context context, krb5_otp_tokeninfo *val) +{ + krb5_algorithm_identifier **alg; + + if (val == NULL) + return; + free(val->vendor.data); + free(val->challenge.data); + free(val->token_id.data); + free(val->alg_id.data); + for (alg = val->supported_hash_alg; alg != NULL && *alg != NULL; alg++) + k5_free_algorithm_identifier(context, *alg); + free(val->supported_hash_alg); + free(val); +} + +void +k5_free_pa_otp_challenge(krb5_context context, krb5_pa_otp_challenge *val) +{ + krb5_otp_tokeninfo **ti; + + if (val == NULL) + return; + free(val->nonce.data); + free(val->service.data); + for (ti = val->tokeninfo; *ti != NULL; ti++) + k5_free_otp_tokeninfo(context, *ti); + free(val->tokeninfo); + free(val->salt.data); + free(val->s2kparams.data); + free(val); +} + +void +k5_free_pa_otp_req(krb5_context context, krb5_pa_otp_req *val) +{ + if (val == NULL) + return; + val->flags = 0; + free(val->nonce.data); + free(val->enc_data.ciphertext.data); + if (val->hash_alg != NULL) + k5_free_algorithm_identifier(context, val->hash_alg); + free(val->otp_value.data); + free(val->pin.data); + free(val->challenge.data); + free(val->counter.data); + free(val->token_id.data); + free(val->alg_id.data); + free(val->vendor.data); + free(val); +} + +void +k5_free_kkdcp_message(krb5_context context, krb5_kkdcp_message *val) +{ + if (val == NULL) + return; + free(val->target_domain.data); + free(val->kerb_message.data); + free(val); +} + +static void +free_vmac(krb5_context context, krb5_verifier_mac *val) +{ + if (val == NULL) + return; + krb5_free_principal(context, val->princ); + krb5_free_checksum_contents(context, &val->checksum); + free(val); +} + +void +k5_free_cammac(krb5_context context, krb5_cammac *val) +{ + krb5_verifier_mac **vp; + + if (val == NULL) + return; + krb5_free_authdata(context, val->elements); + free_vmac(context, val->kdc_verifier); + free_vmac(context, val->svc_verifier); + for (vp = val->other_verifiers; vp != NULL && *vp != NULL; vp++) + free_vmac(context, *vp); + free(val->other_verifiers); + free(val); +} + +void +k5_free_secure_cookie(krb5_context context, krb5_secure_cookie *val) +{ + if (val == NULL) + return; + k5_zapfree_pa_data(val->data); + free(val); +} + +void +k5_free_spake_factor(krb5_context context, krb5_spake_factor *val) +{ + if (val == NULL) + return; + if (val->data != NULL) + zapfree(val->data->data, val->data->length); + free(val->data); + free(val); +} + +void +k5_free_pa_spake(krb5_context context, krb5_pa_spake *val) +{ + krb5_spake_factor **f; + + if (val == NULL) + return; + switch (val->choice) { + case SPAKE_MSGTYPE_SUPPORT: + free(val->u.support.groups); + break; + case SPAKE_MSGTYPE_CHALLENGE: + krb5_free_data_contents(context, &val->u.challenge.pubkey); + for (f = val->u.challenge.factors; f != NULL && *f != NULL; f++) + k5_free_spake_factor(context, *f); + free(val->u.challenge.factors); + break; + case SPAKE_MSGTYPE_RESPONSE: + krb5_free_data_contents(context, &val->u.response.pubkey); + krb5_free_data_contents(context, &val->u.response.factor.ciphertext); + break; + case SPAKE_MSGTYPE_ENCDATA: + krb5_free_data_contents(context, &val->u.encdata.ciphertext); + break; + default: + break; + } + free(val); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/libdef_parse.c b/krb5-1.21.3/src/lib/krb5/krb/libdef_parse.c new file mode 100644 index 00000000..05b912dd --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/libdef_parse.c @@ -0,0 +1,152 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/libdef_parse.c */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * krb5int_libdefault_string() + * krb5int_libdefault_boolean() + * + */ +#include "k5-int.h" +#include "int-proto.h" +/* For _krb5_conf_boolean prototype */ +#include "os-proto.h" + +static const char *const conf_yes[] = { + "y", "yes", "true", "t", "1", "on", + 0, +}; + +static const char *const conf_no[] = { + "n", "no", "false", "nil", "0", "off", + 0, +}; + +int +_krb5_conf_boolean(const char *s) +{ + const char *const *p; + + for(p=conf_yes; *p; p++) { + if (!strcasecmp(*p,s)) + return 1; + } + + for(p=conf_no; *p; p++) { + if (!strcasecmp(*p,s)) + return 0; + } + + /* Default to "no" */ + return 0; +} + +krb5_error_code +krb5int_libdefault_string(krb5_context context, const krb5_data *realm, + const char *option, char **ret_value) +{ + profile_t profile; + const char *names[5]; + char **nameval = NULL; + krb5_error_code retval; + char realmstr[1024]; + + if (realm->length > sizeof(realmstr)-1) + return(EINVAL); + + strncpy(realmstr, realm->data, realm->length); + realmstr[realm->length] = '\0'; + + if (!context || (context->magic != KV5M_CONTEXT)) + return KV5M_CONTEXT; + + profile = context->profile; + + names[0] = KRB5_CONF_LIBDEFAULTS; + + /* + * Try number one: + * + * [libdefaults] + * REALM = { + * option = + * } + */ + + names[1] = realmstr; + names[2] = option; + names[3] = 0; + retval = profile_get_values(profile, names, &nameval); + if (retval == 0 && nameval && nameval[0]) + goto goodbye; + + + /* + * Try number two: + * + * [libdefaults] + * option = + */ + + names[1] = option; + names[2] = 0; + retval = profile_get_values(profile, names, &nameval); + if (retval == 0 && nameval && nameval[0]) + goto goodbye; + +goodbye: + if (!nameval) + return(ENOENT); + + if (!nameval[0]) { + retval = ENOENT; + } else { + *ret_value = strdup(nameval[0]); + if (!*ret_value) + retval = ENOMEM; + } + + profile_free_list(nameval); + + return retval; +} + +krb5_error_code +krb5int_libdefault_boolean(krb5_context context, const krb5_data *realm, + const char *option, int *ret_value) +{ + char *string = NULL; + krb5_error_code retval; + + retval = krb5int_libdefault_string(context, realm, option, &string); + + if (retval) + return(retval); + + *ret_value = _krb5_conf_boolean(string); + free(string); + + return(0); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/mk_cred.c b/krb5-1.21.3/src/lib/krb5/krb/mk_cred.c new file mode 100644 index 00000000..c0d7b381 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/mk_cred.c @@ -0,0 +1,231 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/mk_cred.c - definition of krb5_mk_ncred(), krb5_mk_1cred() */ +/* + * Copyright (C) 2019 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. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "auth_con.h" + +/* Encrypt the enc_part of krb5_cred. key may be NULL to use the unencrypted + * KRB-CRED form (RFC 6448). */ +static krb5_error_code +encrypt_credencpart(krb5_context context, krb5_cred_enc_part *encpart, + krb5_key key, krb5_enc_data *encdata_out) +{ + krb5_error_code ret; + krb5_data *der_enccred; + + /* Start by encoding to-be-encrypted part of the message. */ + ret = encode_krb5_enc_cred_part(encpart, &der_enccred); + if (ret) + return ret; + + if (key == NULL) { + /* Just copy the encoded data to the ciphertext area. */ + encdata_out->enctype = ENCTYPE_NULL; + encdata_out->ciphertext = *der_enccred; + free(der_enccred); + return 0; + } + + ret = k5_encrypt_keyhelper(context, key, KRB5_KEYUSAGE_KRB_CRED_ENCPART, + der_enccred, encdata_out); + + zapfreedata(der_enccred); + return ret; +} + +/* + * Marshal a KRB-CRED message into der_out, encrypted with key (or unencrypted + * if key is NULL). Store the ciphertext in enc_out. Use the timestamp and + * sequence number from rdata and the addresses from local_addr and remote_addr + * (either of which may be NULL). der_out and enc_out should be freed by the + * caller when finished. + */ +static krb5_error_code +create_krbcred(krb5_context context, krb5_creds **creds, krb5_key key, + const krb5_replay_data *rdata, krb5_address *local_addr, + krb5_address *remote_addr, krb5_data **der_out, + krb5_enc_data *enc_out) +{ + krb5_error_code ret; + krb5_cred_enc_part credenc; + krb5_cred cred; + krb5_ticket **tickets = NULL; + krb5_cred_info **ticket_info = NULL, *tinfos = NULL; + krb5_enc_data enc; + size_t i, ncreds; + + *der_out = NULL; + memset(enc_out, 0, sizeof(*enc_out)); + memset(&enc, 0, sizeof(enc)); + + for (ncreds = 0; creds[ncreds] != NULL; ncreds++); + + tickets = k5calloc(ncreds + 1, sizeof(*tickets), &ret); + if (tickets == NULL) + goto cleanup; + + ticket_info = k5calloc(ncreds + 1, sizeof(*ticket_info), &ret); + if (ticket_info == NULL) + goto cleanup; + + tinfos = k5calloc(ncreds, sizeof(*tinfos), &ret); + if (tinfos == NULL) + goto cleanup; + + /* For each credential in the list, decode the ticket and create a cred + * info structure using alias pointers. */ + for (i = 0; i < ncreds; i++) { + ret = decode_krb5_ticket(&creds[i]->ticket, &tickets[i]); + if (ret) + goto cleanup; + + tinfos[i].magic = KV5M_CRED_INFO; + tinfos[i].times = creds[i]->times; + tinfos[i].flags = creds[i]->ticket_flags; + tinfos[i].session = &creds[i]->keyblock; + tinfos[i].client = creds[i]->client; + tinfos[i].server = creds[i]->server; + tinfos[i].caddrs = creds[i]->addresses; + ticket_info[i] = &tinfos[i]; + } + + /* Encrypt the credential encrypted part. */ + credenc.magic = KV5M_CRED_ENC_PART; + credenc.s_address = local_addr; + credenc.r_address = remote_addr; + credenc.nonce = rdata->seq; + credenc.usec = rdata->usec; + credenc.timestamp = rdata->timestamp; + credenc.ticket_info = ticket_info; + ret = encrypt_credencpart(context, &credenc, key, &enc); + if (ret) + goto cleanup; + + /* Encode the KRB-CRED message. */ + cred.magic = KV5M_CRED; + cred.tickets = tickets; + cred.enc_part = enc; + ret = encode_krb5_cred(&cred, der_out); + if (ret) + goto cleanup; + + *enc_out = enc; + memset(&enc, 0, sizeof(enc)); + +cleanup: + krb5_free_tickets(context, tickets); + krb5_free_data_contents(context, &enc.ciphertext); + free(tinfos); + free(ticket_info); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_mk_ncred(krb5_context context, krb5_auth_context authcon, + krb5_creds **creds, krb5_data **der_out, + krb5_replay_data *rdata_out) +{ + krb5_error_code ret; + krb5_key key; + krb5_replay_data rdata; + krb5_data *der_krbcred = NULL; + krb5_enc_data enc; + krb5_address *local_addr, *remote_addr, lstorage, rstorage; + + *der_out = NULL; + memset(&enc, 0, sizeof(enc)); + memset(&lstorage, 0, sizeof(lstorage)); + memset(&rstorage, 0, sizeof(rstorage)); + + if (creds == NULL) + return KRB5KRB_AP_ERR_BADADDR; + + ret = k5_privsafe_gen_rdata(context, authcon, &rdata, rdata_out); + if (ret) + goto cleanup; + /* Historically we always set the timestamp, so keep doing that. */ + if (rdata.timestamp == 0) { + ret = krb5_us_timeofday(context, &rdata.timestamp, &rdata.usec); + if (ret) + goto cleanup; + } + + ret = k5_privsafe_gen_addrs(context, authcon, &lstorage, &rstorage, + &local_addr, &remote_addr); + if (ret) + goto cleanup; + + key = (authcon->send_subkey != NULL) ? authcon->send_subkey : authcon->key; + ret = create_krbcred(context, creds, key, &rdata, local_addr, remote_addr, + &der_krbcred, &enc); + if (ret) + goto cleanup; + + if (key != NULL) { + ret = k5_privsafe_check_replay(context, authcon, NULL, &enc, NULL); + if (ret) + goto cleanup; + } + + *der_out = der_krbcred; + der_krbcred = NULL; + if ((authcon->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || + (authcon->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) + authcon->local_seq_number++; + +cleanup: + krb5_free_data_contents(context, &enc.ciphertext); + free(lstorage.contents); + free(rstorage.contents); + zapfreedata(der_krbcred); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_mk_1cred(krb5_context context, krb5_auth_context authcon, + krb5_creds *creds, krb5_data **der_out, + krb5_replay_data *rdata_out) +{ + krb5_error_code retval; + krb5_creds **list; + + list = calloc(2, sizeof(*list)); + if (list == NULL) + return ENOMEM; + + list[0] = creds; + list[1] = NULL; + retval = krb5_mk_ncred(context, authcon, list, der_out, rdata_out); + free(list); + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/mk_error.c b/krb5-1.21.3/src/lib/krb5/krb/mk_error.c new file mode 100644 index 00000000..d1acd028 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/mk_error.c @@ -0,0 +1,49 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/mk_error.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +/* + formats the error structure *dec_err into an error buffer *enc_err. + + The error buffer storage is allocated, and should be freed by the + caller when finished. + + returns system errors +*/ +krb5_error_code KRB5_CALLCONV +krb5_mk_error(krb5_context context, const krb5_error *dec_err, + krb5_data *enc_err) +{ + krb5_error_code retval; + krb5_data *new_enc_err; + + if ((retval = encode_krb5_error(dec_err, &new_enc_err))) + return(retval); + *enc_err = *new_enc_err; + free(new_enc_err); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/mk_priv.c b/krb5-1.21.3/src/lib/krb5/krb/mk_priv.c new file mode 100644 index 00000000..b537a2ca --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/mk_priv.c @@ -0,0 +1,155 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/mk_priv.c - definition of krb5_mk_priv() */ +/* + * Copyright 1990,1991,2019 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. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "auth_con.h" + +/* + * Marshal a KRB-PRIV message into der_out, encrypted with key. Store the + * ciphertext in enc_out. Use the timestamp and sequence number from rdata and + * the addresses from local_addr and remote_addr (the second of which may be + * NULL). der_out and enc_out should be freed by the caller when finished. + */ +static krb5_error_code +create_krbpriv(krb5_context context, const krb5_data *userdata, + krb5_key key, const krb5_replay_data *rdata, + krb5_address *local_addr, krb5_address *remote_addr, + krb5_data *cstate, krb5_data *der_out, krb5_enc_data *enc_out) +{ + krb5_enctype enctype = krb5_k_key_enctype(context, key); + krb5_error_code ret; + krb5_priv privmsg; + krb5_priv_enc_part encpart; + krb5_data *der_encpart = NULL, *der_krbpriv; + size_t enclen; + + memset(&privmsg, 0, sizeof(privmsg)); + privmsg.enc_part.kvno = 0; + privmsg.enc_part.enctype = enctype; + encpart.user_data = *userdata; + encpart.s_address = local_addr; + encpart.r_address = remote_addr; + encpart.timestamp = rdata->timestamp; + encpart.usec = rdata->usec; + encpart.seq_number = rdata->seq; + + /* Start by encoding the to-be-encrypted part of the message. */ + ret = encode_krb5_enc_priv_part(&encpart, &der_encpart); + if (ret) + return ret; + + /* put together an eblock for this encryption */ + ret = krb5_c_encrypt_length(context, enctype, der_encpart->length, + &enclen); + if (ret) + goto cleanup; + + ret = alloc_data(&privmsg.enc_part.ciphertext, enclen); + if (ret) + goto cleanup; + + ret = krb5_k_encrypt(context, key, KRB5_KEYUSAGE_KRB_PRIV_ENCPART, + (cstate->length > 0) ? cstate : NULL, der_encpart, + &privmsg.enc_part); + if (ret) + goto cleanup; + + ret = encode_krb5_priv(&privmsg, &der_krbpriv); + if (ret) + goto cleanup; + + *der_out = *der_krbpriv; + free(der_krbpriv); + + *enc_out = privmsg.enc_part; + memset(&privmsg.enc_part, 0, sizeof(privmsg.enc_part)); + +cleanup: + zapfree(privmsg.enc_part.ciphertext.data, + privmsg.enc_part.ciphertext.length); + zapfreedata(der_encpart); + return ret; +} + + +krb5_error_code KRB5_CALLCONV +krb5_mk_priv(krb5_context context, krb5_auth_context authcon, + const krb5_data *userdata, krb5_data *der_out, + krb5_replay_data *rdata_out) +{ + krb5_error_code ret; + krb5_key key; + krb5_replay_data rdata; + krb5_data der_krbpriv = empty_data(); + krb5_enc_data enc; + krb5_address *local_addr, *remote_addr, lstorage, rstorage; + + *der_out = empty_data(); + memset(&enc, 0, sizeof(enc)); + memset(&lstorage, 0, sizeof(lstorage)); + memset(&rstorage, 0, sizeof(rstorage)); + if (!authcon->local_addr) + return KRB5_LOCAL_ADDR_REQUIRED; + + ret = k5_privsafe_gen_rdata(context, authcon, &rdata, rdata_out); + if (ret) + goto cleanup; + + ret = k5_privsafe_gen_addrs(context, authcon, &lstorage, &rstorage, + &local_addr, &remote_addr); + if (ret) + goto cleanup; + + key = (authcon->send_subkey != NULL) ? authcon->send_subkey : authcon->key; + ret = create_krbpriv(context, userdata, key, &rdata, local_addr, + remote_addr, &authcon->cstate, &der_krbpriv, &enc); + if (ret) + goto cleanup; + + ret = k5_privsafe_check_replay(context, authcon, NULL, &enc, NULL); + if (ret) + goto cleanup; + + *der_out = der_krbpriv; + der_krbpriv = empty_data(); + if ((authcon->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || + (authcon->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) + authcon->local_seq_number++; + +cleanup: + krb5_free_data_contents(context, &der_krbpriv); + zapfree(enc.ciphertext.data, enc.ciphertext.length); + free(lstorage.contents); + free(rstorage.contents); + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/mk_rep.c b/krb5-1.21.3/src/lib/krb5/krb/mk_rep.c new file mode 100644 index 00000000..dd7a7d91 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/mk_rep.c @@ -0,0 +1,152 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/mk_rep.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "auth_con.h" + +/* + Formats a KRB_AP_REP message into outbuf. + + The outbuf buffer storage is allocated, and should be freed by the + caller when finished. + + returns system errors +*/ + +static krb5_error_code +k5_mk_rep(krb5_context context, krb5_auth_context auth_context, + krb5_data *outbuf, int dce_style) +{ + krb5_error_code retval; + krb5_ap_rep_enc_part repl; + krb5_ap_rep reply; + krb5_data * scratch; + krb5_data * toutbuf; + + /* Make the reply */ + if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || + (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + (auth_context->local_seq_number == 0)) { + if ((retval = krb5_generate_seq_number(context, + &auth_context->key->keyblock, + &auth_context->local_seq_number))) + return(retval); + } + + if (dce_style) { + krb5_us_timeofday(context, &repl.ctime, &repl.cusec); + } else { + repl.ctime = auth_context->authentp->ctime; + repl.cusec = auth_context->authentp->cusec; + } + + if (dce_style) + repl.subkey = NULL; + else if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_USE_SUBKEY) { + assert(auth_context->negotiated_etype != ENCTYPE_NULL); + + retval = k5_generate_and_save_subkey(context, auth_context, + &auth_context->key->keyblock, + auth_context->negotiated_etype); + if (retval) + return retval; + repl.subkey = &auth_context->send_subkey->keyblock; + } else + repl.subkey = auth_context->authentp->subkey; + + if (dce_style) + repl.seq_number = auth_context->remote_seq_number; + else + repl.seq_number = auth_context->local_seq_number; + + TRACE_MK_REP(context, repl.ctime, repl.cusec, repl.subkey, + repl.seq_number); + + /* encode it before encrypting */ + if ((retval = encode_krb5_ap_rep_enc_part(&repl, &scratch))) + return retval; + + if ((retval = k5_encrypt_keyhelper(context, auth_context->key, + KRB5_KEYUSAGE_AP_REP_ENCPART, scratch, + &reply.enc_part))) + goto cleanup_scratch; + + if (!(retval = encode_krb5_ap_rep(&reply, &toutbuf))) { + *outbuf = *toutbuf; + free(toutbuf); + } + + memset(reply.enc_part.ciphertext.data, 0, reply.enc_part.ciphertext.length); + free(reply.enc_part.ciphertext.data); + reply.enc_part.ciphertext.length = 0; + reply.enc_part.ciphertext.data = 0; + +cleanup_scratch: + memset(scratch->data, 0, scratch->length); + krb5_free_data(context, scratch); + + return retval; +} + +krb5_error_code KRB5_CALLCONV +krb5_mk_rep(krb5_context context, krb5_auth_context auth_context, krb5_data *outbuf) +{ + return k5_mk_rep(context, auth_context, outbuf, 0); +} + +krb5_error_code KRB5_CALLCONV +krb5_mk_rep_dce(krb5_context context, krb5_auth_context auth_context, krb5_data *outbuf) +{ + return k5_mk_rep(context, auth_context, outbuf, 1); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/mk_req.c b/krb5-1.21.3/src/lib/krb5/krb/mk_req.c new file mode 100644 index 00000000..162c05b5 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/mk_req.c @@ -0,0 +1,89 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/mk_req.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "auth_con.h" + +/* + Formats a KRB_AP_REQ message into outbuf. + + server specifies the principal of the server to receive the message; if + credentials are not present in the credentials cache for this server, the + TGS request with default parameters is used in an attempt to obtain + such credentials, and they are stored in ccache. + + kdc_options specifies the options requested for the + ap_req_options specifies the KRB_AP_REQ options desired. + + checksum specifies the checksum to be used in the authenticator. + + The outbuf buffer storage is allocated, and should be freed by the + caller when finished. + + returns system errors +*/ + +krb5_error_code KRB5_CALLCONV +krb5_mk_req(krb5_context context, krb5_auth_context *auth_context, + krb5_flags ap_req_options, const char *service, + const char *hostname, krb5_data *in_data, krb5_ccache ccache, + krb5_data *outbuf) +{ + krb5_error_code retval; + krb5_principal server; + krb5_creds * credsp; + krb5_creds creds; + + retval = krb5_sname_to_principal(context, hostname, service, + KRB5_NT_SRV_HST, &server); + if (retval) + return retval; + + /* obtain ticket & session key */ + memset(&creds, 0, sizeof(creds)); + if ((retval = krb5_copy_principal(context, server, &creds.server))) + goto cleanup_princ; + + if ((retval = krb5_cc_get_principal(context, ccache, &creds.client))) + goto cleanup_creds; + + if ((retval = krb5_get_credentials(context, 0, + ccache, &creds, &credsp))) + goto cleanup_creds; + + retval = krb5_mk_req_extended(context, auth_context, ap_req_options, + in_data, credsp, outbuf); + + krb5_free_creds(context, credsp); + +cleanup_creds: + krb5_free_cred_contents(context, &creds); + +cleanup_princ: + krb5_free_principal(context, server); + + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/mk_req_ext.c b/krb5-1.21.3/src/lib/krb5/krb/mk_req_ext.c new file mode 100644 index 00000000..08504860 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/mk_req_ext.c @@ -0,0 +1,400 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/mk_req_ext.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * krb5_mk_req_extended() + */ + + +#include "k5-int.h" +#include "int-proto.h" +#include "auth_con.h" + +/* + Formats a KRB_AP_REQ message into outbuf, with more complete options than + krb_mk_req. + + outbuf, ap_req_options, checksum, and ccache are used in the + same fashion as for krb5_mk_req. + + creds is used to supply the credentials (ticket and session key) needed + to form the request. + + if creds->ticket has no data (length == 0), then a ticket is obtained + from either the cache or the TGS, passing creds to krb5_get_credentials(). + kdc_options specifies the options requested for the ticket to be used. + If a ticket with appropriate flags is not found in the cache, then these + options are passed on in a request to an appropriate KDC. + + ap_req_options specifies the KRB_AP_REQ options desired. + + if ap_req_options specifies AP_OPTS_USE_SESSION_KEY, then creds->ticket + must contain the appropriate ENC-TKT-IN-SKEY ticket. + + checksum specifies the checksum to be used in the authenticator. + + The outbuf buffer storage is allocated, and should be freed by the + caller when finished. + + On an error return, the credentials pointed to by creds might have been + augmented with additional fields from the obtained credentials; the entire + credentials should be released by calling krb5_free_creds(). + + returns system errors +*/ + +static krb5_error_code +make_ap_authdata(krb5_context context, krb5_enctype *desired_enctypes, + krb5_enctype tkt_enctype, krb5_boolean client_aware_cb, + krb5_authdata ***authdata_out); + +static krb5_error_code +generate_authenticator(krb5_context, + krb5_authenticator *, krb5_principal, + krb5_checksum *, krb5_key, + krb5_ui_4, krb5_authdata **, + krb5_authdata_context ad_context, + krb5_enctype *desired_etypes, + krb5_enctype tkt_enctype); + +krb5_error_code KRB5_CALLCONV +krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context, + krb5_flags ap_req_options, krb5_data *in_data, + krb5_creds *in_creds, krb5_data *outbuf) +{ + krb5_error_code retval; + krb5_checksum checksum; + krb5_checksum *checksump = 0; + krb5_auth_context new_auth_context; + krb5_enctype *desired_etypes = NULL; + + krb5_ap_req request; + krb5_data *scratch = 0; + krb5_data *toutbuf; + + request.ap_options = ap_req_options & AP_OPTS_WIRE_MASK; + request.authenticator.ciphertext.data = NULL; + request.ticket = 0; + + if (!in_creds->ticket.length) + return(KRB5_NO_TKT_SUPPLIED); + + if ((ap_req_options & AP_OPTS_ETYPE_NEGOTIATION) && + !(ap_req_options & AP_OPTS_MUTUAL_REQUIRED)) + return(EINVAL); + + /* we need a native ticket */ + if ((retval = decode_krb5_ticket(&(in_creds)->ticket, &request.ticket))) + return(retval); + + /* verify that the ticket is not expired */ + if ((retval = krb5int_validate_times(context, &in_creds->times)) != 0) + goto cleanup; + + /* generate auth_context if needed */ + if (*auth_context == NULL) { + if ((retval = krb5_auth_con_init(context, &new_auth_context))) + goto cleanup; + *auth_context = new_auth_context; + } + + if ((*auth_context)->key != NULL) { + krb5_k_free_key(context, (*auth_context)->key); + (*auth_context)->key = NULL; + } + + /* set auth context keyblock */ + if ((retval = krb5_k_create_key(context, &in_creds->keyblock, + &((*auth_context)->key)))) + goto cleanup; + + /* generate seq number if needed */ + if ((((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) + || ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) + && ((*auth_context)->local_seq_number == 0)) { + if ((retval = krb5_generate_seq_number(context, &in_creds->keyblock, + &(*auth_context)->local_seq_number))) + goto cleanup; + } + + /* generate subkey if needed */ + if ((ap_req_options & AP_OPTS_USE_SUBKEY)&&(!(*auth_context)->send_subkey)) { + retval = k5_generate_and_save_subkey(context, *auth_context, + &in_creds->keyblock, + in_creds->keyblock.enctype); + if (retval) + goto cleanup; + } + + + if (!in_data && (*auth_context)->checksum_func) { + retval = (*auth_context)->checksum_func( context, + *auth_context, + (*auth_context)->checksum_func_data, + &in_data); + if (retval) + goto cleanup; + } + + if (in_data) { + if ((*auth_context)->req_cksumtype == 0x8003) { + /* XXX Special hack for GSSAPI */ + checksum.checksum_type = 0x8003; + checksum.length = in_data->length; + checksum.contents = (krb5_octet *) in_data->data; + } else { + retval = krb5_k_make_checksum(context, 0, (*auth_context)->key, + KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM, + in_data, &checksum); + if (retval) + goto cleanup_cksum; + } + checksump = &checksum; + } + + /* Generate authenticator */ + if (((*auth_context)->authentp = (krb5_authenticator *)malloc(sizeof( + krb5_authenticator))) == NULL) { + retval = ENOMEM; + goto cleanup_cksum; + } + + if (ap_req_options & AP_OPTS_ETYPE_NEGOTIATION) { + if ((*auth_context)->permitted_etypes == NULL) { + retval = krb5_get_tgs_ktypes(context, in_creds->server, &desired_etypes); + if (retval) + goto cleanup_cksum; + } else + desired_etypes = (*auth_context)->permitted_etypes; + } + + TRACE_MK_REQ(context, in_creds, (*auth_context)->local_seq_number, + (*auth_context)->send_subkey, &in_creds->keyblock); + if ((retval = generate_authenticator(context, + (*auth_context)->authentp, + in_creds->client, checksump, + (*auth_context)->send_subkey, + (*auth_context)->local_seq_number, + in_creds->authdata, + (*auth_context)->ad_context, + desired_etypes, + in_creds->keyblock.enctype))) + goto cleanup_cksum; + + /* encode the authenticator */ + if ((retval = encode_krb5_authenticator((*auth_context)->authentp, + &scratch))) + goto cleanup_cksum; + + /* call the encryption routine */ + if ((retval = krb5_encrypt_helper(context, &in_creds->keyblock, + KRB5_KEYUSAGE_AP_REQ_AUTH, + scratch, &request.authenticator))) + goto cleanup_cksum; + + if ((retval = encode_krb5_ap_req(&request, &toutbuf))) + goto cleanup_cksum; + *outbuf = *toutbuf; + + free(toutbuf); + +cleanup_cksum: + /* Null out these fields, to prevent pointer sharing problems; + * they were supplied by the caller + */ + if ((*auth_context)->authentp != NULL) { + (*auth_context)->authentp->client = NULL; + (*auth_context)->authentp->checksum = NULL; + } + if (checksump && checksump->checksum_type != 0x8003) + free(checksump->contents); + +cleanup: + if (desired_etypes && + desired_etypes != (*auth_context)->permitted_etypes) + free(desired_etypes); + if (request.ticket) + krb5_free_ticket(context, request.ticket); + if (request.authenticator.ciphertext.data) { + (void) memset(request.authenticator.ciphertext.data, 0, + request.authenticator.ciphertext.length); + free(request.authenticator.ciphertext.data); + } + if (scratch) { + memset(scratch->data, 0, scratch->length); + free(scratch->data); + free(scratch); + } + return retval; +} + +static krb5_error_code +generate_authenticator(krb5_context context, krb5_authenticator *authent, + krb5_principal client, krb5_checksum *cksum, + krb5_key key, krb5_ui_4 seq_number, + krb5_authdata **authorization, + krb5_authdata_context ad_context, + krb5_enctype *desired_etypes, + krb5_enctype tkt_enctype) +{ + krb5_error_code retval; + krb5_authdata **ext_authdata = NULL, **ap_authdata, **combined; + int client_aware_cb; + + authent->client = client; + authent->checksum = cksum; + if (key) { + retval = krb5_k_key_keyblock(context, key, &authent->subkey); + if (retval) + return retval; + } else + authent->subkey = 0; + authent->seq_number = seq_number; + authent->authorization_data = NULL; + + if (ad_context != NULL) { + retval = krb5_authdata_export_authdata(context, + ad_context, + AD_USAGE_AP_REQ, + &ext_authdata); + if (retval) + return retval; + } + + if (authorization != NULL || ext_authdata != NULL) { + retval = krb5_merge_authdata(context, + authorization, + ext_authdata, + &authent->authorization_data); + if (retval) { + krb5_free_authdata(context, ext_authdata); + return retval; + } + krb5_free_authdata(context, ext_authdata); + } + + retval = profile_get_boolean(context->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_CLIENT_AWARE_GSS_BINDINGS, NULL, + FALSE, &client_aware_cb); + if (retval) + return retval; + + /* Add etype negotiation or channel-binding awareness authdata to the + * front, if appropriate. */ + retval = make_ap_authdata(context, desired_etypes, tkt_enctype, + client_aware_cb, &ap_authdata); + if (retval) + return retval; + if (ap_authdata != NULL) { + retval = krb5_merge_authdata(context, ap_authdata, + authent->authorization_data, &combined); + krb5_free_authdata(context, ap_authdata); + if (retval) + return retval; + krb5_free_authdata(context, authent->authorization_data); + authent->authorization_data = combined; + } + + return(krb5_us_timeofday(context, &authent->ctime, &authent->cusec)); +} + +/* Set *out to a DER-encoded RFC 4537 etype list, or to NULL if no etype list + * should be sent. */ +static krb5_error_code +make_etype_list(krb5_context context, krb5_enctype *desired_enctypes, + krb5_enctype tkt_enctype, krb5_data **out) +{ + krb5_etype_list etlist; + int count; + + *out = NULL; + + /* Only send a list if we prefer another enctype to tkt_enctype. */ + if (desired_enctypes == NULL || desired_enctypes[0] == tkt_enctype) + return 0; + + /* Count elements of desired_etypes, stopping at tkt_enctypes if present. + * (Per RFC 4537, it must be the last option if it is included.) */ + for (count = 0; desired_enctypes[count] != ENCTYPE_NULL; count++) { + if (count > 0 && desired_enctypes[count - 1] == tkt_enctype) + break; + } + + etlist.etypes = desired_enctypes; + etlist.length = count; + return encode_krb5_etype_list(&etlist, out); +} + +/* Set *authdata_out to appropriate authenticator authdata for the request, + * encoded in a single AD_IF_RELEVANT element. */ +static krb5_error_code +make_ap_authdata(krb5_context context, krb5_enctype *desired_enctypes, + krb5_enctype tkt_enctype, krb5_boolean client_aware_cb, + krb5_authdata ***authdata_out) +{ + krb5_error_code ret; + krb5_authdata etypes_ad, flags_ad, *list[3]; + krb5_data *der_etypes = NULL; + size_t count = 0; + uint8_t flagbuf[4]; + const uint32_t KERB_AP_OPTIONS_CBT = 0x4000; + + *authdata_out = NULL; + + /* Include an ETYPE_NEGOTIATION element if appropriate. */ + ret = make_etype_list(context, desired_enctypes, tkt_enctype, &der_etypes); + if (ret) + goto cleanup; + if (der_etypes != NULL) { + etypes_ad.magic = KV5M_AUTHDATA; + etypes_ad.ad_type = KRB5_AUTHDATA_ETYPE_NEGOTIATION; + etypes_ad.length = der_etypes->length; + etypes_ad.contents = (uint8_t *)der_etypes->data; + list[count++] = &etypes_ad; + } + + /* Include an AP_OPTIONS element if the CBT flag is configured. */ + if (client_aware_cb != 0) { + store_32_le(KERB_AP_OPTIONS_CBT, flagbuf); + flags_ad.magic = KV5M_AUTHDATA; + flags_ad.ad_type = KRB5_AUTHDATA_AP_OPTIONS; + flags_ad.length = 4; + flags_ad.contents = flagbuf; + list[count++] = &flags_ad; + } + + if (count > 0) { + list[count] = NULL; + ret = krb5_encode_authdata_container(context, + KRB5_AUTHDATA_IF_RELEVANT, + list, authdata_out); + } + +cleanup: + krb5_free_data(context, der_etypes); + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/mk_safe.c b/krb5-1.21.3/src/lib/krb5/krb/mk_safe.c new file mode 100644 index 00000000..151a06e6 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/mk_safe.c @@ -0,0 +1,174 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/mk_safe.c - definition of krb5_mk_safe() */ +/* + * Copyright 1990,1991,2019 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. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "auth_con.h" + +/* + * Marshal a KRB-SAFE message into der_out, with a keyed checksum of type + * sumtype. Store the checksum in cksum_out. Use the timestamp and sequence + * number from rdata and the addresses from local_addr and remote_addr (the + * second of which may be NULL). der_out and cksum_out should be freed by the + * caller when finished. + */ +static krb5_error_code +create_krbsafe(krb5_context context, const krb5_data *userdata, krb5_key key, + const krb5_replay_data *rdata, krb5_address *local_addr, + krb5_address *remote_addr, krb5_cksumtype sumtype, + krb5_data *der_out, krb5_checksum *cksum_out) +{ + krb5_error_code ret; + krb5_safe safemsg; + krb5_octet zero_octet = 0; + krb5_checksum safe_checksum; + krb5_data *der_krbsafe; + + if (sumtype && !krb5_c_valid_cksumtype(sumtype)) + return KRB5_PROG_SUMTYPE_NOSUPP; + if (sumtype && !krb5_c_is_keyed_cksum(sumtype)) + return KRB5KRB_AP_ERR_INAPP_CKSUM; + + safemsg.user_data = *userdata; + safemsg.s_address = local_addr; + safemsg.r_address = remote_addr; + safemsg.timestamp = rdata->timestamp; + safemsg.usec = rdata->usec; + safemsg.seq_number = rdata->seq; + + /* Encode the message with a zero-length zero-type checksum. */ + safe_checksum.length = 0; + safe_checksum.checksum_type = 0; + safe_checksum.contents = &zero_octet; + safemsg.checksum = &safe_checksum; + ret = encode_krb5_safe(&safemsg, &der_krbsafe); + if (ret) + return ret; + + /* Checksum the encoding. */ + ret = krb5_k_make_checksum(context, sumtype, key, + KRB5_KEYUSAGE_KRB_SAFE_CKSUM, der_krbsafe, + &safe_checksum); + zapfreedata(der_krbsafe); + if (ret) + return ret; + + /* Encode the message again with the real checksum. */ + safemsg.checksum = &safe_checksum; + ret = encode_krb5_safe(&safemsg, &der_krbsafe); + if (ret) { + krb5_free_checksum_contents(context, &safe_checksum); + return ret; + } + + *der_out = *der_krbsafe; + free(der_krbsafe); + *cksum_out = safe_checksum; + return 0; +} + +/* Return the checksum type for the KRB-SAFE message, or 0 to use the enctype's + * mandatory checksum. */ +static krb5_cksumtype +safe_cksumtype(krb5_context context, krb5_auth_context auth_context, + krb5_enctype enctype) +{ + krb5_error_code ret; + unsigned int nsumtypes, i; + krb5_cksumtype *sumtypes; + + /* Use the auth context's safe_cksumtype if it is valid for the enctype. + * Otherwise return 0 for the mandatory checksum. */ + ret = krb5_c_keyed_checksum_types(context, enctype, &nsumtypes, &sumtypes); + if (ret != 0) + return 0; + for (i = 0; i < nsumtypes; i++) { + if (auth_context->safe_cksumtype == sumtypes[i]) + break; + } + krb5_free_cksumtypes(context, sumtypes); + return (i == nsumtypes) ? 0 : auth_context->safe_cksumtype; +} + +krb5_error_code KRB5_CALLCONV +krb5_mk_safe(krb5_context context, krb5_auth_context authcon, + const krb5_data *userdata, krb5_data *der_out, + krb5_replay_data *rdata_out) +{ + krb5_error_code ret; + krb5_key key; + krb5_replay_data rdata; + krb5_data der_krbsafe = empty_data(); + krb5_checksum cksum; + krb5_address *local_addr, *remote_addr, lstorage, rstorage; + krb5_cksumtype sumtype; + + *der_out = empty_data(); + memset(&cksum, 0, sizeof(cksum)); + memset(&lstorage, 0, sizeof(lstorage)); + memset(&rstorage, 0, sizeof(rstorage)); + if (authcon->local_addr == NULL) + return KRB5_LOCAL_ADDR_REQUIRED; + + ret = k5_privsafe_gen_rdata(context, authcon, &rdata, rdata_out); + if (ret) + goto cleanup; + + ret = k5_privsafe_gen_addrs(context, authcon, &lstorage, &rstorage, + &local_addr, &remote_addr); + if (ret) + goto cleanup; + + key = (authcon->send_subkey != NULL) ? authcon->send_subkey : authcon->key; + sumtype = safe_cksumtype(context, authcon, key->keyblock.enctype); + ret = create_krbsafe(context, userdata, key, &rdata, local_addr, + remote_addr, sumtype, &der_krbsafe, &cksum); + if (ret) + goto cleanup; + + ret = k5_privsafe_check_replay(context, authcon, NULL, NULL, &cksum); + if (ret) + goto cleanup; + + *der_out = der_krbsafe; + der_krbsafe = empty_data(); + if ((authcon->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) || + (authcon->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) + authcon->local_seq_number++; + +cleanup: + krb5_free_data_contents(context, &der_krbsafe); + krb5_free_checksum_contents(context, &cksum); + free(lstorage.contents); + free(rstorage.contents); + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/pac.c b/krb5-1.21.3/src/lib/krb5/krb/pac.c new file mode 100644 index 00000000..5d1fdf1b --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/pac.c @@ -0,0 +1,1279 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/pac.c */ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "authdata.h" +#include "k5-input.h" + +#define MAX_BUFFERS 4096 + +/* + * Add a buffer containing data to pac's metadata and encoding. If zerofill is + * true, data->data must be NULL and the buffer will be zero-filled with length + * data->length. + */ +krb5_error_code +k5_pac_add_buffer(krb5_context context, krb5_pac pac, uint32_t type, + const krb5_data *data, krb5_boolean zerofill, + krb5_data *data_out) +{ + struct k5_pac_buffer *nbufs; + size_t header_len, i, pad = 0; + char *ndata, *bufdata; + + assert((data->data == NULL) == zerofill); + + /* Check for an existing buffer of this type. */ + if (k5_pac_locate_buffer(context, pac, type, NULL) == 0) + return EEXIST; + + if (pac->nbuffers >= MAX_BUFFERS) + return ERANGE; + nbufs = realloc(pac->buffers, (pac->nbuffers + 1) * sizeof(*pac->buffers)); + if (nbufs == NULL) + return ENOMEM; + pac->buffers = nbufs; + + header_len = PACTYPE_LENGTH + pac->nbuffers * PAC_INFO_BUFFER_LENGTH; + + if (data->length % PAC_ALIGNMENT) + pad = PAC_ALIGNMENT - (data->length % PAC_ALIGNMENT); + ndata = realloc(pac->data.data, + pac->data.length + PAC_INFO_BUFFER_LENGTH + + data->length + pad); + if (ndata == NULL) + return ENOMEM; + pac->data.data = ndata; + + /* Update the offsets of existing buffers. */ + for (i = 0; i < pac->nbuffers; i++) + pac->buffers[i].offset += PAC_INFO_BUFFER_LENGTH; + + /* Make room for the new buffer's metadata. */ + memmove(pac->data.data + header_len + PAC_INFO_BUFFER_LENGTH, + pac->data.data + header_len, + pac->data.length - header_len); + memset(pac->data.data + header_len, 0, PAC_INFO_BUFFER_LENGTH); + + /* Initialize the new buffer. */ + pac->buffers[i].type = type; + pac->buffers[i].size = data->length; + pac->buffers[i].offset = pac->data.length + PAC_INFO_BUFFER_LENGTH; + assert((pac->buffers[i].offset % PAC_ALIGNMENT) == 0); + + /* Copy in new PAC data and zero padding bytes. */ + bufdata = pac->data.data + pac->buffers[i].offset; + if (zerofill) + memset(bufdata, 0, data->length); + else + memcpy(bufdata, data->data, data->length); + memset(bufdata + data->length, 0, pad); + + pac->nbuffers++; + pac->data.length += PAC_INFO_BUFFER_LENGTH + data->length + pad; + + if (data_out != NULL) + *data_out = make_data(bufdata, data->length); + + pac->verified = FALSE; + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_pac_add_buffer(krb5_context context, krb5_pac pac, uint32_t type, + const krb5_data *data) +{ + return k5_pac_add_buffer(context, pac, type, data, FALSE, NULL); +} + +/* + * Free a PAC + */ +void KRB5_CALLCONV +krb5_pac_free(krb5_context context, krb5_pac pac) +{ + if (pac != NULL) { + zapfree(pac->data.data, pac->data.length); + free(pac->buffers); + zapfree(pac, sizeof(*pac)); + } +} + +krb5_error_code +k5_pac_locate_buffer(krb5_context context, const krb5_pac pac, uint32_t type, + krb5_data *data_out) +{ + struct k5_pac_buffer *buffer = NULL; + size_t i; + + if (pac == NULL) + return EINVAL; + + for (i = 0; i < pac->nbuffers; i++) { + if (pac->buffers[i].type == type) { + if (buffer == NULL) + buffer = &pac->buffers[i]; + else + return EINVAL; + } + } + + if (buffer == NULL) + return ENOENT; + + assert(buffer->offset < pac->data.length); + assert(buffer->size <= pac->data.length - buffer->offset); + + if (data_out != NULL) + *data_out = make_data(pac->data.data + buffer->offset, buffer->size); + + return 0; +} + +/* + * Find a buffer and copy data into output + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_get_buffer(krb5_context context, krb5_pac pac, uint32_t type, + krb5_data *data_out) +{ + krb5_data d; + krb5_error_code ret; + + ret = k5_pac_locate_buffer(context, pac, type, &d); + if (ret) + return ret; + + data_out->data = k5memdup(d.data, d.length, &ret); + if (data_out->data == NULL) + return ret; + data_out->length = d.length; + return 0; +} + +/* + * Return an array of the types of data in the PAC + */ +krb5_error_code KRB5_CALLCONV +krb5_pac_get_types(krb5_context context, krb5_pac pac, size_t *len_out, + uint32_t **types_out) +{ + size_t i; + + *types_out = calloc(pac->nbuffers, sizeof(*types_out)); + if (*types_out == NULL) + return ENOMEM; + + *len_out = pac->nbuffers; + + for (i = 0; i < pac->nbuffers; i++) + (*types_out)[i] = pac->buffers[i].type; + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_pac_init(krb5_context context, krb5_pac *pac_out) +{ + krb5_error_code ret; + krb5_pac pac; + + *pac_out = NULL; + + pac = malloc(sizeof(*pac)); + if (pac == NULL) + return ENOMEM; + + pac->nbuffers = 0; + pac->buffers = NULL; + pac->version = 0; + + pac->data.length = PACTYPE_LENGTH; + pac->data.data = k5alloc(pac->data.length, &ret); + if (pac->data.data == NULL) { + free(pac); + return ret; + } + + pac->verified = FALSE; + + *pac_out = pac; + return 0; +} + +static krb5_error_code +copy_pac(krb5_context context, krb5_pac src, krb5_pac *dst_out) +{ + krb5_error_code ret; + krb5_pac pac; + + *dst_out = NULL; + + pac = k5alloc(sizeof(*pac), &ret); + if (pac == NULL) + goto fail; + + pac->buffers = k5memdup(src->buffers, + src->nbuffers * sizeof(*pac->buffers), &ret); + if (pac->buffers == NULL) + goto fail; + + ret = krb5int_copy_data_contents(context, &src->data, &pac->data); + if (ret) + goto fail; + + pac->nbuffers = src->nbuffers; + pac->version = src->version; + pac->verified = src->verified; + + *dst_out = pac; + return 0; + +fail: + krb5_pac_free(context, pac); + return ret; +} + +/* Parse the supplied data into an allocated PAC. */ +krb5_error_code KRB5_CALLCONV +krb5_pac_parse(krb5_context context, const void *ptr, size_t len, + krb5_pac *ppac) +{ + krb5_error_code ret; + size_t i; + krb5_pac pac; + size_t header_len; + uint32_t nbuffers, version; + struct k5input in; + char *ndata; + + *ppac = NULL; + + k5_input_init(&in, ptr, len); + + nbuffers = k5_input_get_uint32_le(&in); + version = k5_input_get_uint32_le(&in); + if (in.status || version != 0) + return EINVAL; + + if (nbuffers < 1 || nbuffers > MAX_BUFFERS) + return ERANGE; + + header_len = PACTYPE_LENGTH + (nbuffers * PAC_INFO_BUFFER_LENGTH); + if (len < header_len) + return ERANGE; + + ret = krb5_pac_init(context, &pac); + if (ret) + return ret; + + pac->buffers = k5calloc(nbuffers, sizeof(*pac->buffers), &ret); + if (ret) + goto fail; + + pac->nbuffers = nbuffers; + pac->version = version; + + for (i = 0; i < nbuffers; i++) { + struct k5_pac_buffer *buffer = &pac->buffers[i]; + + buffer->type = k5_input_get_uint32_le(&in); + buffer->size = k5_input_get_uint32_le(&in); + buffer->offset = k5_input_get_uint64_le(&in); + + if (in.status || buffer->offset % PAC_ALIGNMENT) { + ret = EINVAL; + goto fail; + } + if (buffer->offset < header_len || buffer->offset > len || + buffer->size > len - buffer->offset) { + ret = ERANGE; + goto fail; + } + } + + ndata = realloc(pac->data.data, len); + if (ndata == NULL) { + krb5_pac_free(context, pac); + return ENOMEM; + } + pac->data.data = ndata; + memcpy(ndata, ptr, len); + + pac->data.length = len; + + *ppac = pac; + + return 0; + +fail: + krb5_pac_free(context, pac); + return ret; +} + +static krb5_error_code +k5_time_to_seconds_since_1970(uint64_t ntTime, krb5_timestamp *elapsedSeconds) +{ + uint64_t abstime = ntTime / 10000000 - NT_TIME_EPOCH; + + if (abstime > UINT32_MAX) + return ERANGE; + *elapsedSeconds = abstime; + return 0; +} + +krb5_error_code +k5_seconds_since_1970_to_time(krb5_timestamp elapsedSeconds, uint64_t *ntTime) +{ + *ntTime = (uint32_t)elapsedSeconds; + *ntTime += NT_TIME_EPOCH; + *ntTime *= 10000000; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_pac_get_client_info(krb5_context context, const krb5_pac pac, + krb5_timestamp *authtime_out, char **princname_out) +{ + krb5_error_code ret; + krb5_data client_info; + char *pac_princname; + unsigned char *p; + krb5_timestamp pac_authtime; + uint16_t pac_princname_length; + uint64_t pac_nt_authtime; + + if (authtime_out != NULL) + *authtime_out = 0; + *princname_out = NULL; + + ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_CLIENT_INFO, + &client_info); + if (ret) + return ret; + + if (client_info.length < PAC_CLIENT_INFO_LENGTH) + return ERANGE; + + p = (unsigned char *)client_info.data; + pac_nt_authtime = load_64_le(p); + p += 8; + pac_princname_length = load_16_le(p); + p += 2; + + ret = k5_time_to_seconds_since_1970(pac_nt_authtime, &pac_authtime); + if (ret) + return ret; + + if (client_info.length < PAC_CLIENT_INFO_LENGTH + pac_princname_length || + pac_princname_length % 2) + return ERANGE; + + ret = k5_utf16le_to_utf8(p, pac_princname_length, &pac_princname); + if (ret) + return ret; + + if (authtime_out != NULL) + *authtime_out = pac_authtime; + *princname_out = pac_princname; + + return 0; +} + +krb5_error_code +k5_pac_validate_client(krb5_context context, const krb5_pac pac, + krb5_timestamp authtime, krb5_const_principal principal, + krb5_boolean with_realm) +{ + krb5_error_code ret; + char *pac_princname, *princname; + krb5_timestamp pac_authtime; + int flags = 0; + + ret = krb5_pac_get_client_info(context, pac, &pac_authtime, + &pac_princname); + if (ret) + return ret; + + flags = KRB5_PRINCIPAL_UNPARSE_DISPLAY; + if (!with_realm) + flags |= KRB5_PRINCIPAL_UNPARSE_NO_REALM; + + ret = krb5_unparse_name_flags(context, principal, flags, &princname); + if (ret) { + free(pac_princname); + return ret; + } + + if (pac_authtime != authtime || strcmp(pac_princname, princname) != 0) + ret = KRB5KRB_AP_WRONG_PRINC; + + free(pac_princname); + krb5_free_unparsed_name(context, princname); + + return ret; +} + +/* Zero out the signature in a copy of the PAC data. */ +static krb5_error_code +zero_signature(krb5_context context, const krb5_pac pac, uint32_t type, + krb5_data *data) +{ + struct k5_pac_buffer *buffer = NULL; + size_t i; + + assert(type == KRB5_PAC_SERVER_CHECKSUM || + type == KRB5_PAC_PRIVSVR_CHECKSUM || + type == KRB5_PAC_FULL_CHECKSUM); + assert(data->length >= pac->data.length); + + for (i = 0; i < pac->nbuffers; i++) { + if (pac->buffers[i].type == type) { + buffer = &pac->buffers[i]; + break; + } + } + + if (buffer == NULL) + return ENOENT; + + if (buffer->size < PAC_SIGNATURE_DATA_LENGTH) + return KRB5_BAD_MSIZE; + if (buffer->size > pac->data.length || + buffer->offset > pac->data.length - buffer->size) + return ERANGE; + + /* Within the copy, zero out the data portion of the checksum only. */ + memset(data->data + buffer->offset + PAC_SIGNATURE_DATA_LENGTH, 0, + buffer->size - PAC_SIGNATURE_DATA_LENGTH); + + return 0; +} + +static krb5_error_code +verify_checksum(krb5_context context, const krb5_pac pac, uint32_t buffer_type, + const krb5_keyblock *key, krb5_keyusage usage, + const krb5_data *data) +{ + krb5_error_code ret; + krb5_data buffer; + krb5_cksumtype cksumtype; + krb5_checksum checksum; + krb5_boolean valid; + size_t cksumlen; + + ret = k5_pac_locate_buffer(context, pac, buffer_type, &buffer); + if (ret) + return ret; + if (buffer.length < PAC_SIGNATURE_DATA_LENGTH) + return KRB5_BAD_MSIZE; + + cksumtype = load_32_le(buffer.data); + if (buffer_type == KRB5_PAC_SERVER_CHECKSUM && cksumtype == CKSUMTYPE_SHA1) + return KRB5KDC_ERR_SUMTYPE_NOSUPP; + if (!krb5_c_is_keyed_cksum(cksumtype)) + return KRB5KRB_ERR_GENERIC; + + /* There may be an RODCIdentifier trailer (see [MS-PAC] 2.8), so look up + * the length of the checksum by its type. */ + ret = krb5_c_checksum_length(context, cksumtype, &cksumlen); + if (ret) + return ret; + if (cksumlen > buffer.length - PAC_SIGNATURE_DATA_LENGTH) + return KRB5_BAD_MSIZE; + checksum.checksum_type = cksumtype; + checksum.length = cksumlen; + checksum.contents = (uint8_t *)buffer.data + PAC_SIGNATURE_DATA_LENGTH; + + ret = krb5_c_verify_checksum(context, key, usage, data, &checksum, &valid); + return ret ? ret : (valid ? 0 : KRB5KRB_AP_ERR_MODIFIED); +} + +static krb5_error_code +verify_pac_checksums(krb5_context context, const krb5_pac pac, + krb5_boolean expect_full_checksum, + const krb5_keyblock *server, const krb5_keyblock *privsvr) +{ + krb5_error_code ret; + krb5_data copy, server_checksum; + + /* Make a copy of the PAC with zeroed out server and privsvr checksums. */ + ret = krb5int_copy_data_contents(context, &pac->data, ©); + if (ret) + return ret; + + ret = zero_signature(context, pac, KRB5_PAC_SERVER_CHECKSUM, ©); + if (ret) + goto cleanup; + ret = zero_signature(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, ©); + if (ret) + goto cleanup; + + if (server != NULL) { + /* Verify the server checksum over the PAC copy. */ + ret = verify_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, server, + KRB5_KEYUSAGE_APP_DATA_CKSUM, ©); + } + + if (privsvr != NULL && expect_full_checksum) { + /* Zero the full checksum buffer in the copy and verify the full + * checksum over the copy with all three checksums zeroed. */ + ret = zero_signature(context, pac, KRB5_PAC_FULL_CHECKSUM, ©); + if (ret) + goto cleanup; + ret = verify_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM, privsvr, + KRB5_KEYUSAGE_APP_DATA_CKSUM, ©); + if (ret) + goto cleanup; + } + + if (privsvr != NULL) { + /* Verify the privsvr checksum over the server checksum. */ + ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_SERVER_CHECKSUM, + &server_checksum); + if (ret) + return ret; + if (server_checksum.length < PAC_SIGNATURE_DATA_LENGTH) + return KRB5_BAD_MSIZE; + server_checksum.data += PAC_SIGNATURE_DATA_LENGTH; + server_checksum.length -= PAC_SIGNATURE_DATA_LENGTH; + + ret = verify_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, privsvr, + KRB5_KEYUSAGE_APP_DATA_CKSUM, &server_checksum); + if (ret) + goto cleanup; + } + + pac->verified = TRUE; + +cleanup: + free(copy.data); + return ret; +} + +/* Per MS-PAC 2.8.3, tickets encrypted to TGS and password change principals + * should not have ticket signatures. */ +krb5_boolean +k5_pac_should_have_ticket_signature(krb5_const_principal sprinc) +{ + if (IS_TGS_PRINC(sprinc)) + return FALSE; + if (sprinc->length == 2 && data_eq_string(sprinc->data[0], "kadmin") && + data_eq_string(sprinc->data[1], "changepw")) + return FALSE; + return TRUE; +} + +krb5_error_code KRB5_CALLCONV +krb5_kdc_verify_ticket(krb5_context context, const krb5_enc_tkt_part *enc_tkt, + krb5_const_principal server_princ, + const krb5_keyblock *server, + const krb5_keyblock *privsvr, krb5_pac *pac_out) +{ + krb5_error_code ret; + krb5_pac pac = NULL; + krb5_data *recoded_tkt = NULL; + krb5_authdata **authdata = enc_tkt->authorization_data; + krb5_authdata *orig, **ifrel = NULL, **recoded_ifrel = NULL; + uint8_t z = 0; + krb5_authdata zpac = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC, 1, &z }; + krb5_boolean is_service_tkt; + size_t i, j; + + *pac_out = NULL; + + if (authdata == NULL) + return 0; + + /* + * Find the position of the PAC in the ticket authdata. ifrel will be the + * decoded AD-IF-RELEVANT container at position i containing a PAC, and j + * will be the offset within the container. + */ + for (i = 0; authdata[i] != NULL; i++) { + if (authdata[i]->ad_type != KRB5_AUTHDATA_IF_RELEVANT) + continue; + + ret = krb5_decode_authdata_container(context, + KRB5_AUTHDATA_IF_RELEVANT, + authdata[i], &ifrel); + if (ret) + goto cleanup; + + for (j = 0; ifrel[j] != NULL; j++) { + if (ifrel[j]->ad_type == KRB5_AUTHDATA_WIN2K_PAC) + break; + } + if (ifrel[j] != NULL) + break; + + krb5_free_authdata(context, ifrel); + ifrel = NULL; + } + + /* Stop and return successfully if we didn't find a PAC. */ + if (authdata[i] == NULL) { + ret = 0; + goto cleanup; + } + + ret = krb5_pac_parse(context, ifrel[j]->contents, ifrel[j]->length, &pac); + if (ret) + goto cleanup; + + is_service_tkt = k5_pac_should_have_ticket_signature(server_princ); + if (privsvr != NULL && is_service_tkt) { + /* To check the PAC ticket signatures, re-encode the ticket with the + * PAC contents replaced by a single zero. */ + orig = ifrel[j]; + ifrel[j] = &zpac; + ret = krb5_encode_authdata_container(context, + KRB5_AUTHDATA_IF_RELEVANT, + ifrel, &recoded_ifrel); + ifrel[j] = orig; + if (ret) + goto cleanup; + orig = authdata[i]; + authdata[i] = recoded_ifrel[0]; + ret = encode_krb5_enc_tkt_part(enc_tkt, &recoded_tkt); + authdata[i] = orig; + if (ret) + goto cleanup; + + ret = verify_checksum(context, pac, KRB5_PAC_TICKET_CHECKSUM, privsvr, + KRB5_KEYUSAGE_APP_DATA_CKSUM, recoded_tkt); + if (ret) + goto cleanup; + } + + ret = verify_pac_checksums(context, pac, is_service_tkt, server, privsvr); + if (ret) + goto cleanup; + + *pac_out = pac; + pac = NULL; + +cleanup: + krb5_pac_free(context, pac); + krb5_free_data(context, recoded_tkt); + krb5_free_authdata(context, ifrel); + krb5_free_authdata(context, recoded_ifrel); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_pac_verify(krb5_context context, + const krb5_pac pac, + krb5_timestamp authtime, + krb5_const_principal principal, + const krb5_keyblock *server, + const krb5_keyblock *privsvr) +{ + return krb5_pac_verify_ext(context, pac, authtime, principal, server, + privsvr, FALSE); +} + +krb5_error_code KRB5_CALLCONV +krb5_pac_verify_ext(krb5_context context, + const krb5_pac pac, + krb5_timestamp authtime, + krb5_const_principal principal, + const krb5_keyblock *server, + const krb5_keyblock *privsvr, + krb5_boolean with_realm) +{ + krb5_error_code ret; + + if (server != NULL || privsvr != NULL) { + ret = verify_pac_checksums(context, pac, FALSE, server, privsvr); + if (ret) + return ret; + } + + if (principal != NULL) { + ret = k5_pac_validate_client(context, pac, authtime, + principal, with_realm); + if (ret) + return ret; + } + + return 0; +} + +/* + * PAC auth data attribute backend + */ +struct mspac_context { + krb5_pac pac; +}; + +static krb5_error_code +mspac_init(krb5_context context, void **plugin_context) +{ + *plugin_context = NULL; + return 0; +} + +static void +mspac_flags(krb5_context context, void *plugin_context, + krb5_authdatatype ad_type, krb5_flags *flags) +{ + *flags = AD_USAGE_TGS_REQ; +} + +static void +mspac_fini(krb5_context context, void *plugin_context) +{ + return; +} + +static krb5_error_code +mspac_request_init(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void **request_context) +{ + struct mspac_context *pacctx; + + pacctx = malloc(sizeof(*pacctx)); + if (pacctx == NULL) + return ENOMEM; + + pacctx->pac = NULL; + + *request_context = pacctx; + + return 0; +} + +static krb5_error_code +mspac_import_authdata(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void *request_context, + krb5_authdata **authdata, krb5_boolean kdc_issued, + krb5_const_principal kdc_issuer) +{ + struct mspac_context *pacctx = (struct mspac_context *)request_context; + + if (kdc_issued) + return EINVAL; + + if (pacctx->pac != NULL) { + krb5_pac_free(context, pacctx->pac); + pacctx->pac = NULL; + } + + assert(authdata[0] != NULL); + assert((authdata[0]->ad_type & AD_TYPE_FIELD_TYPE_MASK) == + KRB5_AUTHDATA_WIN2K_PAC); + + return krb5_pac_parse(context, authdata[0]->contents, authdata[0]->length, + &pacctx->pac); +} + +static krb5_error_code +mspac_export_authdata(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void *request_context, + krb5_flags usage, krb5_authdata ***authdata_out) +{ + struct mspac_context *pacctx = (struct mspac_context *)request_context; + krb5_error_code code; + krb5_authdata **authdata; + krb5_data data; + + if (pacctx->pac == NULL) + return 0; + + authdata = calloc(2, sizeof(krb5_authdata *)); + if (authdata == NULL) + return ENOMEM; + + authdata[0] = calloc(1, sizeof(krb5_authdata)); + if (authdata[0] == NULL) { + free(authdata); + return ENOMEM; + } + authdata[1] = NULL; + + code = krb5int_copy_data_contents(context, &pacctx->pac->data, &data); + if (code != 0) { + krb5_free_authdata(context, authdata); + return code; + } + + authdata[0]->magic = KV5M_AUTHDATA; + authdata[0]->ad_type = KRB5_AUTHDATA_WIN2K_PAC; + authdata[0]->length = data.length; + authdata[0]->contents = (krb5_octet *)data.data; + + authdata[1] = NULL; + + *authdata_out = authdata; + + return 0; +} + +static krb5_error_code +mspac_verify(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void *request_context, + const krb5_auth_context *auth_context, const krb5_keyblock *key, + const krb5_ap_req *req) +{ + krb5_error_code ret; + struct mspac_context *pacctx = (struct mspac_context *)request_context; + + if (pacctx->pac == NULL) + return EINVAL; + + ret = krb5_pac_verify(context, pacctx->pac, + req->ticket->enc_part2->times.authtime, + req->ticket->enc_part2->client, key, NULL); + if (ret) + TRACE_MSPAC_VERIFY_FAIL(context, ret); + + /* + * If the above verification failed, don't fail the whole authentication, + * just don't mark the PAC as verified. A checksum mismatch can occur if + * the PAC was copied from a cross-realm TGT by an ignorant KDC, and Apple + * macOS Server Open Directory (as of 10.6) generates PACs with no server + * checksum at all. + */ + return 0; +} + +static void +mspac_request_fini(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void *request_context) +{ + struct mspac_context *pacctx = (struct mspac_context *)request_context; + + if (pacctx != NULL) { + krb5_pac_free(context, pacctx->pac); + free(pacctx); + } +} + +#define STRLENOF(x) (sizeof((x)) - 1) + +static struct { + uint32_t type; + krb5_data attribute; +} mspac_attribute_types[] = { + { (uint32_t)-1, { KV5M_DATA, STRLENOF("urn:mspac:"), + "urn:mspac:" } }, + { KRB5_PAC_LOGON_INFO, { KV5M_DATA, + STRLENOF("urn:mspac:logon-info"), + "urn:mspac:logon-info" } }, + { KRB5_PAC_CREDENTIALS_INFO, { KV5M_DATA, + STRLENOF("urn:mspac:credentials-info"), + "urn:mspac:credentials-info" } }, + { KRB5_PAC_SERVER_CHECKSUM, { KV5M_DATA, + STRLENOF("urn:mspac:server-checksum"), + "urn:mspac:server-checksum" } }, + { KRB5_PAC_PRIVSVR_CHECKSUM, { KV5M_DATA, + STRLENOF("urn:mspac:privsvr-checksum"), + "urn:mspac:privsvr-checksum" } }, + { KRB5_PAC_CLIENT_INFO, { KV5M_DATA, + STRLENOF("urn:mspac:client-info"), + "urn:mspac:client-info" } }, + { KRB5_PAC_DELEGATION_INFO, { KV5M_DATA, + STRLENOF("urn:mspac:delegation-info"), + "urn:mspac:delegation-info" } }, + { KRB5_PAC_UPN_DNS_INFO, { KV5M_DATA, + STRLENOF("urn:mspac:upn-dns-info"), + "urn:mspac:upn-dns-info" } }, +}; + +#define MSPAC_ATTRIBUTE_COUNT (sizeof(mspac_attribute_types)/sizeof(mspac_attribute_types[0])) + +static krb5_error_code +mspac_type2attr(uint32_t type, krb5_data *attr) +{ + unsigned int i; + + for (i = 0; i < MSPAC_ATTRIBUTE_COUNT; i++) { + if (mspac_attribute_types[i].type == type) { + *attr = mspac_attribute_types[i].attribute; + return 0; + } + } + + return ENOENT; +} + +static krb5_error_code +mspac_attr2type(const krb5_data *attr, uint32_t *type) +{ + unsigned int i; + + for (i = 0; i < MSPAC_ATTRIBUTE_COUNT; i++) { + if (attr->length == mspac_attribute_types[i].attribute.length && + strncasecmp(attr->data, mspac_attribute_types[i].attribute.data, attr->length) == 0) { + *type = mspac_attribute_types[i].type; + return 0; + } + } + + if (attr->length > STRLENOF("urn:mspac:") && + strncasecmp(attr->data, "urn:mspac:", STRLENOF("urn:mspac:")) == 0) + { + char *p = &attr->data[STRLENOF("urn:mspac:")]; + char *endptr; + + *type = strtoul(p, &endptr, 10); + if (*type != 0 && *endptr == '\0') + return 0; + } + + return ENOENT; +} + +static krb5_error_code +mspac_get_attribute_types(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void *request_context, + krb5_data **attrs_out) +{ + struct mspac_context *pacctx = (struct mspac_context *)request_context; + unsigned int i, j; + krb5_data *attrs; + krb5_error_code ret; + + if (pacctx->pac == NULL) + return ENOENT; + + attrs = calloc(1 + pacctx->pac->nbuffers + 1, sizeof(krb5_data)); + if (attrs == NULL) + return ENOMEM; + + j = 0; + + /* The entire PAC */ + ret = krb5int_copy_data_contents(context, + &mspac_attribute_types[0].attribute, + &attrs[j++]); + if (ret) + goto fail; + + /* PAC buffers */ + for (i = 0; i < pacctx->pac->nbuffers; i++) { + krb5_data attr; + + ret = mspac_type2attr(pacctx->pac->buffers[i].type, &attr); + if (!ret) { + ret = krb5int_copy_data_contents(context, &attr, &attrs[j++]); + if (ret) + goto fail; + } else { + int length; + + length = asprintf(&attrs[j].data, "urn:mspac:%d", + pacctx->pac->buffers[i].type); + if (length < 0) { + ret = ENOMEM; + goto fail; + } + attrs[j++].length = length; + } + } + attrs[j].data = NULL; + attrs[j].length = 0; + + *attrs_out = attrs; + + return 0; + +fail: + krb5int_free_data_list(context, attrs); + return ret; +} + +static krb5_error_code +mspac_get_attribute(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void *request_context, + const krb5_data *attribute, krb5_boolean *authenticated, + krb5_boolean *complete, krb5_data *value, + krb5_data *display_value, int *more) +{ + struct mspac_context *pacctx = (struct mspac_context *)request_context; + krb5_error_code ret; + uint32_t type; + + if (display_value != NULL) { + display_value->data = NULL; + display_value->length = 0; + } + + if (*more != -1 || pacctx->pac == NULL) + return ENOENT; + + /* If it didn't verify, pretend it didn't exist. */ + if (!pacctx->pac->verified) { + TRACE_MSPAC_DISCARD_UNVERF(context); + return ENOENT; + } + + ret = mspac_attr2type(attribute, &type); + if (ret) + return ret; + + /* -1 is a magic type that refers to the entire PAC */ + if (type == (uint32_t)-1) { + if (value != NULL) + ret = krb5int_copy_data_contents(context, &pacctx->pac->data, + value); + else + ret = 0; + } else { + if (value != NULL) + ret = krb5_pac_get_buffer(context, pacctx->pac, type, value); + else + ret = k5_pac_locate_buffer(context, pacctx->pac, type, NULL); + } + if (!ret) { + *authenticated = pacctx->pac->verified; + *complete = TRUE; + } + + *more = 0; + + return ret; +} + +static krb5_error_code +mspac_set_attribute(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void *request_context, + krb5_boolean complete, const krb5_data *attribute, + const krb5_data *value) +{ + struct mspac_context *pacctx = (struct mspac_context *)request_context; + krb5_error_code ret; + uint32_t type; + + if (pacctx->pac == NULL) + return ENOENT; + + ret = mspac_attr2type(attribute, &type); + if (ret) + return ret; + + /* -1 is a magic type that refers to the entire PAC */ + if (type == (uint32_t)-1) { + krb5_pac newpac; + + ret = krb5_pac_parse(context, value->data, value->length, &newpac); + if (ret) + return ret; + + krb5_pac_free(context, pacctx->pac); + pacctx->pac = newpac; + } else { + ret = krb5_pac_add_buffer(context, pacctx->pac, type, value); + } + + return ret; +} + +static krb5_error_code +mspac_export_internal(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void *request_context, + krb5_boolean restrict_authenticated, void **ptr) +{ + struct mspac_context *pacctx = (struct mspac_context *)request_context; + krb5_error_code ret; + krb5_pac pac; + + *ptr = NULL; + + if (pacctx->pac == NULL) + return ENOENT; + + if (restrict_authenticated && (pacctx->pac->verified) == FALSE) + return ENOENT; + + ret = krb5_pac_parse(context, pacctx->pac->data.data, + pacctx->pac->data.length, &pac); + if (!ret) { + pac->verified = pacctx->pac->verified; + *ptr = pac; + } + + return ret; +} + +static void +mspac_free_internal(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void *request_context, void *ptr) +{ + if (ptr != NULL) + krb5_pac_free(context, (krb5_pac)ptr); + + return; +} + +static krb5_error_code +mspac_size(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void *request_context, size_t *sizep) +{ + struct mspac_context *pacctx = (struct mspac_context *)request_context; + + *sizep += sizeof(int32_t); + + if (pacctx->pac != NULL) + *sizep += pacctx->pac->data.length; + + *sizep += sizeof(int32_t); + + return 0; +} + +static krb5_error_code +mspac_externalize(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void *request_context, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code ret = 0; + struct mspac_context *pacctx = (struct mspac_context *)request_context; + size_t required = 0; + krb5_octet *bp; + size_t remain; + + bp = *buffer; + remain = *lenremain; + + if (pacctx->pac != NULL) { + mspac_size(context, actx, plugin_context, request_context, &required); + + if (required <= remain) { + krb5_ser_pack_int32(pacctx->pac->data.length, &bp, &remain); + krb5_ser_pack_bytes((krb5_octet *)pacctx->pac->data.data, + (size_t)pacctx->pac->data.length, + &bp, &remain); + krb5_ser_pack_int32(pacctx->pac->verified, &bp, &remain); + } else { + ret = ENOMEM; + } + } else { + krb5_ser_pack_int32(0, &bp, &remain); /* length */ + krb5_ser_pack_int32(0, &bp, &remain); /* verified */ + } + + *buffer = bp; + *lenremain = remain; + + return ret; +} + +static krb5_error_code +mspac_internalize(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void *request_context, + krb5_octet **buffer, size_t *lenremain) +{ + struct mspac_context *pacctx = (struct mspac_context *)request_context; + krb5_error_code ret; + int32_t ibuf; + uint8_t *bp; + size_t remain; + krb5_pac pac = NULL; + + bp = *buffer; + remain = *lenremain; + + /* length */ + ret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + if (ret) + return ret; + + if (ibuf != 0) { + ret = krb5_pac_parse(context, bp, ibuf, &pac); + if (ret) + return ret; + + bp += ibuf; + remain -= ibuf; + } + + /* verified */ + ret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + if (ret) { + krb5_pac_free(context, pac); + return ret; + } + + if (pac != NULL) + pac->verified = (ibuf != 0); + + if (pacctx->pac != NULL) + krb5_pac_free(context, pacctx->pac); + + pacctx->pac = pac; + + *buffer = bp; + *lenremain = remain; + + return 0; +} + +static krb5_error_code +mspac_copy(krb5_context context, krb5_authdata_context actx, + void *plugin_context, void *request_context, + void *dst_plugin_context, void *dst_request_context) +{ + struct mspac_context *srcctx = (struct mspac_context *)request_context; + struct mspac_context *dstctx = (struct mspac_context *)dst_request_context; + krb5_error_code ret = 0; + + assert(dstctx != NULL); + assert(dstctx->pac == NULL); + + if (srcctx->pac != NULL) + ret = copy_pac(context, srcctx->pac, &dstctx->pac); + + return ret; +} + +static krb5_authdatatype mspac_ad_types[] = { KRB5_AUTHDATA_WIN2K_PAC, 0 }; + +krb5plugin_authdata_client_ftable_v0 k5_mspac_ad_client_ftable = { + "mspac", + mspac_ad_types, + mspac_init, + mspac_fini, + mspac_flags, + mspac_request_init, + mspac_request_fini, + mspac_get_attribute_types, + mspac_get_attribute, + mspac_set_attribute, + NULL, /* delete_attribute_proc */ + mspac_export_authdata, + mspac_import_authdata, + mspac_export_internal, + mspac_free_internal, + mspac_verify, + mspac_size, + mspac_externalize, + mspac_internalize, + mspac_copy +}; diff --git a/krb5-1.21.3/src/lib/krb5/krb/pac_sign.c b/krb5-1.21.3/src/lib/krb5/krb/pac_sign.c new file mode 100644 index 00000000..36e1bf03 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/pac_sign.c @@ -0,0 +1,425 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/pac_sign.c */ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "authdata.h" + +/* draft-brezak-win2k-krb-authz-00 */ + +static krb5_error_code +insert_client_info(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + krb5_const_principal principal, krb5_boolean with_realm) +{ + krb5_error_code ret; + krb5_data client_info; + char *princ_name_utf8 = NULL; + uint8_t *princ_name_utf16 = NULL, *p; + size_t princ_name_utf16_len = 0; + uint64_t nt_authtime; + int flags = 0; + + /* If we already have a CLIENT_INFO buffer, then just validate it */ + if (k5_pac_locate_buffer(context, pac, KRB5_PAC_CLIENT_INFO, + &client_info) == 0) { + return k5_pac_validate_client(context, pac, authtime, principal, + with_realm); + } + + if (!with_realm) { + flags |= KRB5_PRINCIPAL_UNPARSE_NO_REALM; + } else if (principal->type == KRB5_NT_ENTERPRISE_PRINCIPAL) { + /* Avoid quoting the first @ sign for enterprise name with realm. */ + flags |= KRB5_PRINCIPAL_UNPARSE_DISPLAY; + } + + ret = krb5_unparse_name_flags(context, principal, flags, &princ_name_utf8); + if (ret) + goto cleanup; + + ret = k5_utf8_to_utf16le(princ_name_utf8, &princ_name_utf16, + &princ_name_utf16_len); + if (ret) + goto cleanup; + + client_info.length = PAC_CLIENT_INFO_LENGTH + princ_name_utf16_len; + client_info.data = NULL; + + ret = k5_pac_add_buffer(context, pac, KRB5_PAC_CLIENT_INFO, + &client_info, TRUE, &client_info); + if (ret) + goto cleanup; + + p = (uint8_t *)client_info.data; + + /* copy in authtime converted to a 64-bit NT time */ + k5_seconds_since_1970_to_time(authtime, &nt_authtime); + store_64_le(nt_authtime, p); + p += 8; + + /* copy in number of UTF-16 bytes in principal name */ + store_16_le(princ_name_utf16_len, p); + p += 2; + + /* copy in principal name */ + memcpy(p, princ_name_utf16, princ_name_utf16_len); + +cleanup: + if (princ_name_utf16 != NULL) + free(princ_name_utf16); + krb5_free_unparsed_name(context, princ_name_utf8); + + return ret; +} + +static krb5_error_code +insert_checksum(krb5_context context, krb5_pac pac, krb5_ui_4 type, + const krb5_keyblock *key, krb5_cksumtype *cksumtype) +{ + krb5_error_code ret; + size_t len; + krb5_data cksumdata; + + ret = krb5int_c_mandatory_cksumtype(context, key->enctype, cksumtype); + if (ret) + return ret; + + ret = krb5_c_checksum_length(context, *cksumtype, &len); + if (ret) + return ret; + + ret = k5_pac_locate_buffer(context, pac, type, &cksumdata); + if (!ret) { + /* + * If we're resigning PAC, make sure we can fit checksum + * into existing buffer + */ + if (cksumdata.length != PAC_SIGNATURE_DATA_LENGTH + len) + return ERANGE; + + memset(cksumdata.data, 0, cksumdata.length); + } else { + /* Add a zero filled buffer */ + cksumdata.length = PAC_SIGNATURE_DATA_LENGTH + len; + cksumdata.data = NULL; + + ret = k5_pac_add_buffer(context, pac, type, &cksumdata, TRUE, + &cksumdata); + if (ret) + return ret; + } + + /* Encode checksum type into buffer */ + store_32_le((krb5_ui_4)*cksumtype, cksumdata.data); + + return 0; +} + +/* in-place encoding of PAC header */ +static krb5_error_code +encode_header(krb5_context context, krb5_pac pac) +{ + size_t i; + unsigned char *p; + size_t header_len; + + header_len = PACTYPE_LENGTH + (pac->nbuffers * PAC_INFO_BUFFER_LENGTH); + assert(pac->data.length >= header_len); + + p = (uint8_t *)pac->data.data; + + store_32_le(pac->nbuffers, p); + p += 4; + store_32_le(pac->version, p); + p += 4; + + for (i = 0; i < pac->nbuffers; i++) { + struct k5_pac_buffer *buffer = &pac->buffers[i]; + + store_32_le(buffer->type, p); + p += 4; + store_32_le(buffer->size, p); + p += 4; + store_64_le(buffer->offset, p); + p += 8; + + assert((buffer->offset % PAC_ALIGNMENT) == 0); + assert(buffer->size < pac->data.length); + assert(buffer->offset <= pac->data.length - buffer->size); + assert(buffer->offset >= header_len); + + if (buffer->offset % PAC_ALIGNMENT || + buffer->size > pac->data.length || + buffer->offset > pac->data.length - buffer->size || + buffer->offset < header_len) + return ERANGE; + } + + return 0; +} + +/* Find the buffer of type buftype in pac and write within it a checksum of + * type cksumtype over data. Set *cksum_out to the checksum. */ +static krb5_error_code +compute_pac_checksum(krb5_context context, krb5_pac pac, uint32_t buftype, + const krb5_keyblock *key, krb5_cksumtype cksumtype, + const krb5_data *data, krb5_data *cksum_out) +{ + krb5_error_code ret; + krb5_data buf; + krb5_crypto_iov iov[2]; + + ret = k5_pac_locate_buffer(context, pac, buftype, &buf); + if (ret) + return ret; + + assert(buf.length > PAC_SIGNATURE_DATA_LENGTH); + *cksum_out = make_data(buf.data + PAC_SIGNATURE_DATA_LENGTH, + buf.length - PAC_SIGNATURE_DATA_LENGTH); + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = *data; + iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + iov[1].data = *cksum_out; + return krb5_c_make_checksum_iov(context, cksumtype, key, + KRB5_KEYUSAGE_APP_DATA_CKSUM, iov, 2); +} + +static krb5_error_code +sign_pac(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + krb5_const_principal principal, const krb5_keyblock *server_key, + const krb5_keyblock *privsvr_key, krb5_boolean with_realm, + krb5_boolean is_service_tkt, krb5_data *data) +{ + krb5_error_code ret; + krb5_data full_cksum, server_cksum, privsvr_cksum; + krb5_cksumtype server_cksumtype, privsvr_cksumtype; + + data->length = 0; + data->data = NULL; + + if (principal != NULL) { + ret = insert_client_info(context, pac, authtime, principal, + with_realm); + if (ret) + return ret; + } + + /* Create zeroed buffers for all checksums. */ + ret = insert_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, server_key, + &server_cksumtype); + if (ret) + return ret; + ret = insert_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, privsvr_key, + &privsvr_cksumtype); + if (ret) + return ret; + if (is_service_tkt) { + ret = insert_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM, + privsvr_key, &privsvr_cksumtype); + if (ret) + return ret; + } + + /* Encode the PAC header so that the checksums will include it. */ + ret = encode_header(context, pac); + if (ret) + return ret; + + if (is_service_tkt) { + /* Generate a full KDC checksum over the whole PAC. */ + ret = compute_pac_checksum(context, pac, KRB5_PAC_FULL_CHECKSUM, + privsvr_key, privsvr_cksumtype, + &pac->data, &full_cksum); + if (ret) + return ret; + } + + /* Generate the server checksum over the whole PAC, including the full KDC + * checksum if we added one. */ + ret = compute_pac_checksum(context, pac, KRB5_PAC_SERVER_CHECKSUM, + server_key, server_cksumtype, &pac->data, + &server_cksum); + if (ret) + return ret; + + /* Generate the privsvr checksum over the server checksum buffer. */ + ret = compute_pac_checksum(context, pac, KRB5_PAC_PRIVSVR_CHECKSUM, + privsvr_key, privsvr_cksumtype, &server_cksum, + &privsvr_cksum); + if (ret) + return ret; + + data->data = k5memdup(pac->data.data, pac->data.length, &ret); + if (data->data == NULL) + return ret; + data->length = pac->data.length; + + memset(pac->data.data, 0, + PACTYPE_LENGTH + (pac->nbuffers * PAC_INFO_BUFFER_LENGTH)); + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_pac_sign(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + krb5_const_principal principal, const krb5_keyblock *server_key, + const krb5_keyblock *privsvr_key, krb5_data *data) +{ + return sign_pac(context, pac, authtime, principal, server_key, + privsvr_key, FALSE, FALSE, data); +} + +krb5_error_code KRB5_CALLCONV +krb5_pac_sign_ext(krb5_context context, krb5_pac pac, krb5_timestamp authtime, + krb5_const_principal principal, + const krb5_keyblock *server_key, + const krb5_keyblock *privsvr_key, krb5_boolean with_realm, + krb5_data *data) +{ + return sign_pac(context, pac, authtime, principal, server_key, privsvr_key, + with_realm, FALSE, data); +} + +/* Add a signature over der_enc_tkt in privsvr to pac. der_enc_tkt should be + * encoded with a dummy PAC authdata element containing a single zero byte. */ +static krb5_error_code +add_ticket_signature(krb5_context context, const krb5_pac pac, + krb5_data *der_enc_tkt, const krb5_keyblock *privsvr) +{ + krb5_error_code ret; + krb5_data ticket_cksum; + krb5_cksumtype ticket_cksumtype; + krb5_crypto_iov iov[2]; + + /* Create zeroed buffer for checksum. */ + ret = insert_checksum(context, pac, KRB5_PAC_TICKET_CHECKSUM, privsvr, + &ticket_cksumtype); + if (ret) + return ret; + + ret = k5_pac_locate_buffer(context, pac, KRB5_PAC_TICKET_CHECKSUM, + &ticket_cksum); + if (ret) + return ret; + + iov[0].flags = KRB5_CRYPTO_TYPE_DATA; + iov[0].data = *der_enc_tkt; + iov[1].flags = KRB5_CRYPTO_TYPE_CHECKSUM; + iov[1].data = make_data(ticket_cksum.data + PAC_SIGNATURE_DATA_LENGTH, + ticket_cksum.length - PAC_SIGNATURE_DATA_LENGTH); + ret = krb5_c_make_checksum_iov(context, ticket_cksumtype, privsvr, + KRB5_KEYUSAGE_APP_DATA_CKSUM, iov, 2); + if (ret) + return ret; + + store_32_le(ticket_cksumtype, ticket_cksum.data); + return 0; +} + +/* Set *out to an AD-IF-RELEVANT authdata element containing a PAC authdata + * element with contents pac_data. */ +static krb5_error_code +encode_pac_ad(krb5_context context, krb5_data *pac_data, krb5_authdata **out) +{ + krb5_error_code ret; + krb5_authdata *container[2], **encoded_container = NULL; + krb5_authdata pac_ad = { KV5M_AUTHDATA, KRB5_AUTHDATA_WIN2K_PAC }; + uint8_t z = 0; + + pac_ad.contents = (pac_data != NULL) ? (uint8_t *)pac_data->data : &z; + pac_ad.length = (pac_data != NULL) ? pac_data->length : 1; + container[0] = &pac_ad; + container[1] = NULL; + + ret = krb5_encode_authdata_container(context, KRB5_AUTHDATA_IF_RELEVANT, + container, &encoded_container); + if (ret) + return ret; + + *out = encoded_container[0]; + free(encoded_container); + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_kdc_sign_ticket(krb5_context context, krb5_enc_tkt_part *enc_tkt, + const krb5_pac pac, krb5_const_principal server_princ, + krb5_const_principal client_princ, + const krb5_keyblock *server, const krb5_keyblock *privsvr, + krb5_boolean with_realm) +{ + krb5_error_code ret; + krb5_data *der_enc_tkt = NULL, pac_data = empty_data(); + krb5_authdata **list, *pac_ad; + krb5_boolean is_service_tkt; + size_t count; + + /* Reallocate space for another authdata element in enc_tkt. */ + list = enc_tkt->authorization_data; + for (count = 0; list != NULL && list[count] != NULL; count++); + list = realloc(enc_tkt->authorization_data, (count + 2) * sizeof(*list)); + if (list == NULL) + return ENOMEM; + list[count] = NULL; + enc_tkt->authorization_data = list; + + /* Create a dummy PAC for ticket signing and make it the first element. */ + ret = encode_pac_ad(context, NULL, &pac_ad); + if (ret) + goto cleanup; + memmove(list + 1, list, (count + 1) * sizeof(*list)); + list[0] = pac_ad; + + is_service_tkt = k5_pac_should_have_ticket_signature(server_princ); + if (is_service_tkt) { + ret = encode_krb5_enc_tkt_part(enc_tkt, &der_enc_tkt); + if (ret) + goto cleanup; + + assert(privsvr != NULL); + ret = add_ticket_signature(context, pac, der_enc_tkt, privsvr); + if (ret) + goto cleanup; + } + + ret = sign_pac(context, pac, enc_tkt->times.authtime, client_princ, server, + privsvr, with_realm, is_service_tkt, &pac_data); + if (ret) + goto cleanup; + + /* Replace the dummy PAC with the signed real one. */ + ret = encode_pac_ad(context, &pac_data, &pac_ad); + if (ret) + goto cleanup; + free(list[0]->contents); + free(list[0]); + list[0] = pac_ad; + +cleanup: + krb5_free_data(context, der_enc_tkt); + krb5_free_data_contents(context, &pac_data); + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/padata.c b/krb5-1.21.3/src/lib/krb5/krb/padata.c new file mode 100644 index 00000000..b307f8b2 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/padata.c @@ -0,0 +1,127 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/padata.c - utility functions for krb5_pa_data lists */ +/* + * Copyright (C) 2019 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. + */ + +#include "k5-int.h" + +krb5_pa_data * +krb5int_find_pa_data(krb5_context context, krb5_pa_data *const *pa_list, + krb5_preauthtype pa_type) +{ + krb5_pa_data *const *pa; + + for (pa = pa_list; pa != NULL && *pa != NULL; pa++) { + if ((*pa)->pa_type == pa_type) + return *pa; + } + return NULL; +} + +krb5_error_code +k5_alloc_pa_data(krb5_preauthtype pa_type, size_t len, krb5_pa_data **out) +{ + krb5_pa_data *pa; + uint8_t *buf = NULL; + + *out = NULL; + if (len > 0) { + buf = malloc(len); + if (buf == NULL) + return ENOMEM; + } + pa = malloc(sizeof(*pa)); + if (pa == NULL) { + free(buf); + return ENOMEM; + } + pa->magic = KV5M_PA_DATA; + pa->pa_type = pa_type; + pa->length = len; + pa->contents = buf; + *out = pa; + return 0; +} + +void +k5_free_pa_data_element(krb5_pa_data *pa) +{ + if (pa != NULL) { + free(pa->contents); + free(pa); + } +} + +krb5_error_code +k5_add_pa_data_element(krb5_pa_data ***list, krb5_pa_data **pa) +{ + size_t count; + krb5_pa_data **newlist; + + for (count = 0; *list != NULL && (*list)[count] != NULL; count++); + + newlist = realloc(*list, (count + 2) * sizeof(*newlist)); + if (newlist == NULL) + return ENOMEM; + newlist[count] = *pa; + newlist[count + 1] = NULL; + *pa = NULL; + *list = newlist; + return 0; +} + +krb5_error_code +k5_add_pa_data_from_data(krb5_pa_data ***list, krb5_preauthtype pa_type, + krb5_data *data) +{ + krb5_error_code ret; + krb5_pa_data *pa; + + ret = k5_alloc_pa_data(pa_type, 0, &pa); + if (ret) + return ret; + pa->contents = (uint8_t *)data->data; + pa->length = data->length; + ret = k5_add_pa_data_element(list, &pa); + if (ret) { + free(pa); + return ret; + } + *data = empty_data(); + return 0; +} + +krb5_error_code +k5_add_empty_pa_data(krb5_pa_data ***list, krb5_preauthtype pa_type) +{ + krb5_data empty = empty_data(); + + return k5_add_pa_data_from_data(list, pa_type, &empty); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/parse.c b/krb5-1.21.3/src/lib/krb5/krb/parse.c new file mode 100644 index 00000000..953389b6 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/parse.c @@ -0,0 +1,238 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/parse.c - Parse strings into krb5_principals */ +/* + * Copyright 1990,1991,2008,2012 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" + +/* + * Scan name and allocate a shell principal with enough space in each field. + * If enterprise is true, use enterprise principal parsing rules. Return + * KRB5_PARSE_MALFORMED if name is malformed. Set *has_realm_out according to + * whether name contains a realm separator. + */ +static krb5_error_code +allocate_princ(krb5_context context, const char *name, krb5_boolean enterprise, + krb5_principal *princ_out, krb5_boolean *has_realm_out) +{ + krb5_error_code ret; + const char *p; + krb5_boolean first_at = TRUE; + krb5_principal princ = NULL; + krb5_data *cur_data, *new_comps; + krb5_int32 i; + + *princ_out = NULL; + *has_realm_out = FALSE; + + /* Allocate a starting principal with one component. */ + princ = k5alloc(sizeof(*princ), &ret); + if (princ == NULL) + goto cleanup; + princ->data = k5alloc(sizeof(*princ->data), &ret); + if (princ->data == NULL) + goto cleanup; + princ->realm = empty_data(); + princ->data[0] = empty_data(); + princ->length = 1; + + cur_data = &princ->data[0]; + for (p = name; *p != '\0'; p++) { + if (*p == '/' && !enterprise) { + /* Component separator (for non-enterprise principals). We + * shouldn't see this in the realm name. */ + if (cur_data == &princ->realm) { + ret = KRB5_PARSE_MALFORMED; + goto cleanup; + } + new_comps = realloc(princ->data, + (princ->length + 1) * sizeof(*princ->data)); + if (new_comps == NULL) { + ret = ENOMEM; + goto cleanup; + } + princ->data = new_comps; + princ->length++; + cur_data = &princ->data[princ->length - 1]; + *cur_data = empty_data(); + } else if (*p == '@' && (!enterprise || !first_at)) { + /* Realm separator. In enterprise principals, the first one of + * these we see is part of the component. */ + if (cur_data == &princ->realm) { + ret = KRB5_PARSE_MALFORMED; + goto cleanup; + } + cur_data = &princ->realm; + } else { + /* Component or realm character, possibly quoted. Make note if + * we're seeing the first '@' in an enterprise principal. */ + cur_data->length++; + if (*p == '@' && enterprise) + first_at = FALSE; + if (*p == '\\') { + /* Quote character can't be the last character of the name. */ + if (*++p == '\0') { + ret = KRB5_PARSE_MALFORMED; + goto cleanup; + } + } + } + } + + /* Allocate space for each component and the realm, with space for null + * terminators on each field. */ + for (i = 0; i < princ->length; i++) { + princ->data[i].data = k5alloc(princ->data[i].length + 1, &ret); + if (princ->data[i].data == NULL) + goto cleanup; + } + princ->realm.data = k5alloc(princ->realm.length + 1, &ret); + if (princ->realm.data == NULL) + goto cleanup; + + *princ_out = princ; + *has_realm_out = (cur_data == &princ->realm); + princ = NULL; +cleanup: + krb5_free_principal(context, princ); + return ret; +} + +/* + * Parse name into princ, assuming that name is correctly formed and that all + * principal fields are allocated to the correct length with zero-filled memory + * (so we get null-terminated fields without any extra work). If enterprise is + * true, use enterprise principal parsing rules. + */ +static void +parse_name_into_princ(const char *name, krb5_boolean enterprise, + krb5_principal princ) +{ + const char *p; + char c; + krb5_boolean first_at = TRUE; + krb5_data *cur_data = princ->data; + unsigned int pos = 0; + + for (p = name; *p != '\0'; p++) { + if (*p == '/' && !enterprise) { + /* Advance to the next component. */ + assert(pos == cur_data->length); + assert(cur_data != &princ->realm); + assert(cur_data - princ->data + 1 < princ->length); + cur_data++; + pos = 0; + } else if (*p == '@' && (!enterprise || !first_at)) { + /* Advance to the realm. */ + assert(pos == cur_data->length); + cur_data = &princ->realm; + pos = 0; + } else { + /* Add to the current component or to the realm. */ + if (*p == '@' && enterprise) + first_at = FALSE; + c = *p; + if (c == '\\') { + c = *++p; + if (c == 'n') + c = '\n'; + else if (c == 't') + c = '\t'; + else if (c == 'b') + c = '\b'; + else if (c == '0') + c = '\0'; + } + assert(pos < cur_data->length); + cur_data->data[pos++] = c; + } + } + assert(pos == cur_data->length); +} + +krb5_error_code KRB5_CALLCONV +krb5_parse_name_flags(krb5_context context, const char *name, + int flags, krb5_principal *principal_out) +{ + krb5_error_code ret; + krb5_principal princ = NULL; + char *default_realm; + krb5_boolean has_realm; + krb5_boolean enterprise = (flags & KRB5_PRINCIPAL_PARSE_ENTERPRISE); + krb5_boolean require_realm = (flags & KRB5_PRINCIPAL_PARSE_REQUIRE_REALM); + krb5_boolean no_realm = (flags & KRB5_PRINCIPAL_PARSE_NO_REALM); + krb5_boolean ignore_realm = (flags & KRB5_PRINCIPAL_PARSE_IGNORE_REALM); + krb5_boolean no_def_realm = (flags & KRB5_PRINCIPAL_PARSE_NO_DEF_REALM); + + *principal_out = NULL; + + ret = allocate_princ(context, name, enterprise, &princ, &has_realm); + if (ret) + goto cleanup; + parse_name_into_princ(name, enterprise, princ); + + /* If a realm was not included, use the default realm, unless flags + * indicate otherwise. */ + if (!has_realm) { + if (require_realm) { + ret = KRB5_PARSE_MALFORMED; + k5_setmsg(context, ret, + _("Principal %s is missing required realm"), name); + goto cleanup; + } + if (!no_realm && !ignore_realm && !no_def_realm) { + ret = krb5_get_default_realm(context, &default_realm); + if (ret) + goto cleanup; + krb5_free_data_contents(context, &princ->realm); + princ->realm = string2data(default_realm); + } + } else if (no_realm) { + ret = KRB5_PARSE_MALFORMED; + k5_setmsg(context, ret, _("Principal %s has realm present"), name); + goto cleanup; + } else if (ignore_realm) { + krb5_free_data_contents(context, &princ->realm); + princ->realm = empty_data(); + } + + princ->type = (enterprise) ? KRB5_NT_ENTERPRISE_PRINCIPAL : + k5_infer_principal_type(princ); + + princ->magic = KV5M_PRINCIPAL; + *principal_out = princ; + princ = NULL; + +cleanup: + krb5_free_principal(context, princ); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_parse_name(krb5_context context, const char *name, + krb5_principal *principal_out) +{ + return krb5_parse_name_flags(context, name, 0, principal_out); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/parse_host_string.c b/krb5-1.21.3/src/lib/krb5/krb/parse_host_string.c new file mode 100644 index 00000000..ff6b0452 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/parse_host_string.c @@ -0,0 +1,124 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/parse_host_string.c - Parse host strings into host and port */ +/* + * Copyright (C) 2016 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. + */ + +#include "k5-int.h" +#include + +/* Return true if s is composed solely of digits. */ +krb5_boolean +k5_is_string_numeric(const char *s) +{ + if (*s == '\0') + return FALSE; + + for (; *s != '\0'; s++) { + if (!isdigit(*s)) + return FALSE; + } + + return TRUE; +} + +/* + * Parse a string containing a host specifier. The expected format for the + * string is: + * + * host[:port] or port + * + * host and port are optional, though one must be present. host may have + * brackets around it for IPv6 addresses. + * + * Arguments: + * address - The address string that should be parsed. + * default_port - The default port to use if no port is found. + * host_out - An output pointer for the parsed host, or NULL if no host was + * specified or an error occurred. Must be freed. + * port_out - An output pointer for the parsed port. Will be 0 on error. + * + * Returns 0 on success, otherwise an error. + */ +krb5_error_code +k5_parse_host_string(const char *address, int default_port, char **host_out, + int *port_out) +{ + krb5_error_code ret; + int port_num; + const char *p, *host = NULL, *port = NULL; + char *endptr, *hostname = NULL; + size_t hostlen = 0; + unsigned long l; + + *host_out = NULL; + *port_out = 0; + + if (address == NULL || *address == '\0' || *address == ':') + return EINVAL; + if (default_port < 0 || default_port > 65535) + return EINVAL; + + /* Find the bounds of the host string and the start of the port string. */ + if (k5_is_string_numeric(address)) { + port = address; + } else if (*address == '[' && (p = strchr(address, ']')) != NULL) { + host = address + 1; + hostlen = p - host; + if (*(p + 1) == ':') + port = p + 2; + } else { + host = address; + hostlen = strcspn(host, " \t:"); + if (host[hostlen] == ':') + port = host + hostlen + 1; + } + + /* Parse the port number, or use the default port. */ + if (port != NULL) { + errno = 0; + l = strtoul(port, &endptr, 10); + if (errno || endptr == port || *endptr != '\0' || l > 65535) + return EINVAL; + port_num = l; + } else { + port_num = default_port; + } + + /* Copy the host if it was specified. */ + if (host != NULL) { + hostname = k5memdup0(host, hostlen, &ret); + if (hostname == NULL) + return ENOMEM; + } + + *host_out = hostname; + *port_out = port_num; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/plugin.c b/krb5-1.21.3/src/lib/krb5/krb/plugin.c new file mode 100644 index 00000000..3bb7a38d --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/plugin.c @@ -0,0 +1,511 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/plugin.c - Plugin framework functions */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +/* + * A plugin_mapping structure maps a module name to a built-in or dynamic + * module. modname is always present; the other three fields can be in four + * different states: + * + * - If dyn_path and dyn_handle are null but module is set, the mapping is to a + * built-in module. + * - If dyn_path is set but dyn_handle and module are null, the mapping is to a + * dynamic module which hasn't been loaded yet. + * - If all three fields are set, the mapping is to a dynamic module which has + * been loaded and is ready to use. + * - If all three fields are null, the mapping is to a dynamic module which + * failed to load and should be ignored. + */ +struct plugin_mapping { + char *modname; + char *dyn_path; + struct plugin_file_handle *dyn_handle; + krb5_plugin_initvt_fn module; +}; + +const char *interface_names[] = { + "pwqual", + "kadm5_hook", + "clpreauth", + "kdcpreauth", + "ccselect", + "localauth", + "hostrealm", + "audit", + "tls", + "kdcauthdata", + "certauth", + "kadm5_auth", + "kdcpolicy", +}; + +/* Return the context's interface structure for id, or NULL if invalid. */ +static inline struct plugin_interface * +get_interface(krb5_context context, int id) +{ + if (context == NULL || id < 0 || id >= PLUGIN_NUM_INTERFACES) + return NULL; + return &context->plugins[id]; +} + +/* Release the memory associated with the mapping list entry map. */ +static void +free_plugin_mapping(struct plugin_mapping *map) +{ + if (map == NULL) + return; + free(map->modname); + free(map->dyn_path); + if (map->dyn_handle != NULL) + krb5int_close_plugin(map->dyn_handle); + free(map); +} + +static void +free_mapping_list(struct plugin_mapping **list) +{ + struct plugin_mapping **mp; + + for (mp = list; mp != NULL && *mp != NULL; mp++) + free_plugin_mapping(*mp); + free(list); +} + +/* Construct a plugin mapping object. path may be NULL (for a built-in + * module), or may be relative to the plugin base directory. */ +static krb5_error_code +make_plugin_mapping(krb5_context context, const char *name, size_t namelen, + const char *path, krb5_plugin_initvt_fn module, + struct plugin_mapping **map_out) +{ + krb5_error_code ret; + struct plugin_mapping *map = NULL; + + /* Create the mapping entry. */ + map = k5alloc(sizeof(*map), &ret); + if (map == NULL) + return ret; + + map->modname = k5memdup0(name, namelen, &ret); + if (map->modname == NULL) + goto oom; + if (path != NULL) { + if (k5_path_join(context->plugin_base_dir, path, &map->dyn_path)) + goto oom; + } + map->module = module; + *map_out = map; + return 0; + +oom: + free_plugin_mapping(map); + return ENOMEM; +} + +/* + * Register a mapping from modname to either dyn_path (for an auto-registered + * dynamic module) or to module (for a builtin module). dyn_path may be + * relative to the plugin base directory. + */ +static krb5_error_code +register_module(krb5_context context, struct plugin_interface *interface, + const char *modname, const char *dyn_path, + krb5_plugin_initvt_fn module) +{ + struct plugin_mapping **list; + size_t count; + + /* Allocate list space for another element and a terminator. */ + list = interface->modules; + for (count = 0; list != NULL && list[count] != NULL; count++); + list = realloc(interface->modules, (count + 2) * sizeof(*list)); + if (list == NULL) + return ENOMEM; + list[count] = list[count + 1] = NULL; + interface->modules = list; + + /* Create a new mapping structure and add it to the list. */ + return make_plugin_mapping(context, modname, strlen(modname), dyn_path, + module, &list[count]); +} + +/* Parse a profile module string of the form "modname:modpath" into a mapping + * entry. */ +static krb5_error_code +parse_modstr(krb5_context context, const char *modstr, + struct plugin_mapping **map_out) +{ + const char *sep; + + *map_out = NULL; + + sep = strchr(modstr, ':'); + if (sep == NULL) { + k5_setmsg(context, KRB5_PLUGIN_BAD_MODULE_SPEC, + _("Invalid module specifier %s"), modstr); + return KRB5_PLUGIN_BAD_MODULE_SPEC; + } + + return make_plugin_mapping(context, modstr, sep - modstr, sep + 1, NULL, + map_out); +} + +/* Return true if value is found in list. */ +static krb5_boolean +find_in_list(char **list, const char *value) +{ + for (; *list != NULL; list++) { + if (strcmp(*list, value) == 0) + return TRUE; + } + return FALSE; +} + +/* Get the list of values for the profile variable varname in the section for + * interface id, or NULL if no values are set. */ +static krb5_error_code +get_profile_var(krb5_context context, int id, const char *varname, char ***out) +{ + krb5_error_code ret; + const char *path[4]; + + *out = NULL; + path[0] = KRB5_CONF_PLUGINS; + path[1] = interface_names[id]; + path[2] = varname; + path[3] = NULL; + ret = profile_get_values(context->profile, path, out); + return (ret == PROF_NO_RELATION) ? 0 : ret; +} + +/* Expand *list_inout to contain the mappings from modstrs, followed by the + * existing built-in module mappings. */ +static krb5_error_code +make_full_list(krb5_context context, char **modstrs, + struct plugin_mapping ***list_inout) +{ + krb5_error_code ret = 0; + size_t count, pos, i, j; + struct plugin_mapping **list, **mp; + char **mod; + + /* Allocate space for all of the modules plus a null terminator. */ + for (count = 0; modstrs[count] != NULL; count++); + for (mp = *list_inout; mp != NULL && *mp != NULL; mp++, count++); + list = calloc(count + 1, sizeof(*list)); + if (list == NULL) + return ENOMEM; + + /* Parse each profile module entry and store it in the list. */ + for (mod = modstrs, pos = 0; *mod != NULL; mod++, pos++) { + ret = parse_modstr(context, *mod, &list[pos]); + if (ret != 0) { + free_mapping_list(list); + return ret; + } + } + + /* Cannibalize the old list of built-in modules. */ + for (mp = *list_inout; mp != NULL && *mp != NULL; mp++, pos++) + list[pos] = *mp; + assert(pos == count); + + /* Filter out duplicates, preferring earlier entries to later ones. */ + for (i = 0, pos = 0; i < count; i++) { + for (j = 0; j < pos; j++) { + if (strcmp(list[i]->modname, list[j]->modname) == 0) { + free_plugin_mapping(list[i]); + break; + } + } + if (j == pos) + list[pos++] = list[i]; + } + list[pos] = NULL; + + free(*list_inout); + *list_inout = list; + return 0; +} + +/* Remove any entries from list which match values in disabled. */ +static void +remove_disabled_modules(struct plugin_mapping **list, char **disable) +{ + struct plugin_mapping **in, **out; + + out = list; + for (in = list; *in != NULL; in++) { + if (find_in_list(disable, (*in)->modname)) + free_plugin_mapping(*in); + else + *out++ = *in; + } + *out = NULL; +} + +/* Modify list to include only the entries matching strings in enable, in + * the order they are listed there. */ +static void +filter_enabled_modules(struct plugin_mapping **list, char **enable) +{ + size_t count, i, pos = 0; + struct plugin_mapping *tmp; + + /* Count the number of existing entries. */ + for (count = 0; list[count] != NULL; count++); + + /* For each string in enable, look for a matching module. */ + for (; *enable != NULL; enable++) { + for (i = pos; i < count; i++) { + if (strcmp(list[i]->modname, *enable) == 0) { + /* Swap the matching module into the next result position. */ + tmp = list[pos]; + list[pos++] = list[i]; + list[i] = tmp; + break; + } + } + } + + /* Free all mappings which didn't match and terminate the list. */ + for (i = pos; i < count; i++) + free_plugin_mapping(list[i]); + list[pos] = NULL; +} + +/* Ensure that a plugin interface is configured. id must be valid. */ +static krb5_error_code +configure_interface(krb5_context context, int id) +{ + krb5_error_code ret; + struct plugin_interface *interface = &context->plugins[id]; + char **modstrs = NULL, **enable = NULL, **disable = NULL; + + if (interface->configured) + return 0; + + /* Detect consistency errors when plugin interfaces are added. */ + assert(sizeof(interface_names) / sizeof(*interface_names) == + PLUGIN_NUM_INTERFACES); + + /* Get profile variables for this interface. */ + ret = get_profile_var(context, id, KRB5_CONF_MODULE, &modstrs); + if (ret) + goto cleanup; + ret = get_profile_var(context, id, KRB5_CONF_DISABLE, &disable); + if (ret) + goto cleanup; + ret = get_profile_var(context, id, KRB5_CONF_ENABLE_ONLY, &enable); + if (ret) + goto cleanup; + + /* Create the full list of dynamic and built-in modules. */ + if (modstrs != NULL) { + ret = make_full_list(context, modstrs, &interface->modules); + if (ret) + goto cleanup; + } + + /* Remove disabled modules. */ + if (disable != NULL) + remove_disabled_modules(interface->modules, disable); + + /* Filter and re-order the list according to enable-modules. */ + if (enable != NULL) + filter_enabled_modules(interface->modules, enable); + +cleanup: + profile_free_list(modstrs); + profile_free_list(enable); + profile_free_list(disable); + return ret; +} + +/* If map is for a dynamic module which hasn't been loaded yet, attempt to load + * it. Only try to load a module once. */ +static void +load_if_needed(krb5_context context, struct plugin_mapping *map, + const char *iname) +{ + krb5_error_code ret; + char *symname = NULL; + struct plugin_file_handle *handle = NULL; + void (*initvt_fn)(); + + if (map->module != NULL || map->dyn_path == NULL) + return; + if (asprintf(&symname, "%s_%s_initvt", iname, map->modname) < 0) + return; + + ret = krb5int_open_plugin(map->dyn_path, &handle, &context->err); + if (ret) { + TRACE_PLUGIN_LOAD_FAIL(context, map->modname, ret); + goto err; + } + + ret = krb5int_get_plugin_func(handle, symname, &initvt_fn, &context->err); + if (ret) { + TRACE_PLUGIN_LOOKUP_FAIL(context, map->modname, ret); + goto err; + } + + free(symname); + map->dyn_handle = handle; + map->module = (krb5_plugin_initvt_fn)initvt_fn; + return; + +err: + /* Clean up, and also null out map->dyn_path so we don't try again. */ + if (handle != NULL) + krb5int_close_plugin(handle); + free(symname); + free(map->dyn_path); + map->dyn_path = NULL; +} + +krb5_error_code +k5_plugin_load(krb5_context context, int interface_id, const char *modname, + krb5_plugin_initvt_fn *module) +{ + krb5_error_code ret; + struct plugin_interface *interface = get_interface(context, interface_id); + struct plugin_mapping **mp, *map; + + if (interface == NULL) + return EINVAL; + ret = configure_interface(context, interface_id); + if (ret != 0) + return ret; + for (mp = interface->modules; mp != NULL && *mp != NULL; mp++) { + map = *mp; + if (strcmp(map->modname, modname) == 0) { + load_if_needed(context, map, interface_names[interface_id]); + if (map->module != NULL) { + *module = map->module; + return 0; + } + break; + } + } + k5_setmsg(context, KRB5_PLUGIN_NAME_NOTFOUND, + _("Could not find %s plugin module named '%s'"), + interface_names[interface_id], modname); + return KRB5_PLUGIN_NAME_NOTFOUND; +} + +krb5_error_code +k5_plugin_load_all(krb5_context context, int interface_id, + krb5_plugin_initvt_fn **modules) +{ + krb5_error_code ret; + struct plugin_interface *interface = get_interface(context, interface_id); + struct plugin_mapping **mp, *map; + krb5_plugin_initvt_fn *list; + size_t count; + + if (interface == NULL) + return EINVAL; + ret = configure_interface(context, interface_id); + if (ret != 0) + return ret; + + /* Count the modules and allocate a list to hold them. */ + mp = interface->modules; + for (count = 0; mp != NULL && mp[count] != NULL; count++); + list = calloc(count + 1, sizeof(*list)); + if (list == NULL) + return ENOMEM; + + /* Place each module's initvt function into list. */ + count = 0; + for (mp = interface->modules; mp != NULL && *mp != NULL; mp++) { + map = *mp; + load_if_needed(context, map, interface_names[interface_id]); + if (map->module != NULL) + list[count++] = map->module; + } + + *modules = list; + return 0; +} + +void +k5_plugin_free_modules(krb5_context context, krb5_plugin_initvt_fn *modules) +{ + free(modules); +} + +krb5_error_code +k5_plugin_register(krb5_context context, int interface_id, const char *modname, + krb5_plugin_initvt_fn module) +{ + struct plugin_interface *interface = get_interface(context, interface_id); + + if (interface == NULL) + return EINVAL; + + /* Disallow registering plugins after load. We may need to reconsider + * this, but it simplifies the design. */ + if (interface->configured) + return EINVAL; + + return register_module(context, interface, modname, NULL, module); +} + +krb5_error_code +k5_plugin_register_dyn(krb5_context context, int interface_id, + const char *modname, const char *modsubdir) +{ + krb5_error_code ret; + struct plugin_interface *interface = get_interface(context, interface_id); + char *fname, *path; + + /* Disallow registering plugins after load. */ + if (interface == NULL || interface->configured) + return EINVAL; + + if (asprintf(&fname, "%s%s", modname, PLUGIN_EXT) < 0) + return ENOMEM; + ret = k5_path_join(modsubdir, fname, &path); + free(fname); + if (ret) + return ret; + ret = register_module(context, interface, modname, path, NULL); + free(path); + return ret; +} + +void +k5_plugin_free_context(krb5_context context) +{ + int i; + + for (i = 0; i < PLUGIN_NUM_INTERFACES; i++) + free_mapping_list(context->plugins[i].modules); + memset(context->plugins, 0, sizeof(context->plugins)); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/pr_to_salt.c b/krb5-1.21.3/src/lib/krb5/krb/pr_to_salt.c new file mode 100644 index 00000000..7bcb6276 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/pr_to_salt.c @@ -0,0 +1,82 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/pr_to_salt.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +static krb5_error_code +principal2salt_internal(krb5_context, krb5_const_principal, + krb5_data *ret, int); + +/* + * Convert a krb5_principal into the default salt for that principal. + */ +static krb5_error_code +principal2salt_internal(krb5_context context, krb5_const_principal pr, + krb5_data *ret, int use_realm) +{ + unsigned int size = 0, offset=0; + krb5_int32 i; + + *ret = empty_data(); + if (pr == NULL) + return 0; + + if (use_realm) + size += pr->realm.length; + + for (i = 0; i < pr->length; i++) + size += pr->data[i].length; + + if (alloc_data(ret, size)) + return ENOMEM; + + if (use_realm) { + offset = pr->realm.length; + if (offset > 0) + memcpy(ret->data, pr->realm.data, offset); + } + + for (i = 0; i < pr->length; i++) { + if (pr->data[i].length > 0) + memcpy(&ret->data[offset], pr->data[i].data, pr->data[i].length); + offset += pr->data[i].length; + } + return 0; +} + +krb5_error_code +krb5_principal2salt(krb5_context context, krb5_const_principal pr, + krb5_data *ret) +{ + return principal2salt_internal(context, pr, ret, 1); +} + +krb5_error_code +krb5_principal2salt_norealm(krb5_context context, krb5_const_principal pr, + krb5_data *ret) +{ + return principal2salt_internal(context, pr, ret, 0); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/preauth2.c b/krb5-1.21.3/src/lib/krb5/krb/preauth2.c new file mode 100644 index 00000000..32f35b76 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/preauth2.c @@ -0,0 +1,1068 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1995, 2003, 2008, 2012 by the Massachusetts Institute of Technology. All + * Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +/* + * This file contains routines for establishing, verifying, and any other + * necessary functions, for utilizing the pre-authentication field of the + * kerberos kdc request, with various hardware/software verification devices. + */ + +#include "k5-int.h" +#include "k5-json.h" +#include "osconf.h" +#include +#include "int-proto.h" +#include "os-proto.h" +#include "fast.h" +#include "init_creds_ctx.h" + +#if !defined(_WIN32) +#include +#endif + +typedef struct { + struct krb5_clpreauth_vtable_st vt; + krb5_clpreauth_moddata data; +} *clpreauth_handle; + +struct krb5_preauth_context_st { + clpreauth_handle *handles; +}; + +struct krb5_preauth_req_context_st { + krb5_context orig_context; + krb5_preauthtype *failed; + krb5_clpreauth_modreq *modreqs; +}; + +/* Release the memory used by a list of handles. */ +static void +free_handles(krb5_context context, clpreauth_handle *handles) +{ + clpreauth_handle *hp, h; + + if (handles == NULL) + return; + for (hp = handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.fini != NULL) + h->vt.fini(context, h->data); + free(h); + } + free(handles); +} + +/* Return an index into handles which can process pa_type, or -1 if none is + * found found. */ +static int +search_module_list(clpreauth_handle *handles, krb5_preauthtype pa_type) +{ + clpreauth_handle h; + int i, j; + + for (i = 0; handles[i] != NULL; i++) { + h = handles[i]; + for (j = 0; h->vt.pa_type_list[j] != 0; j++) { + if (h->vt.pa_type_list[j] == pa_type) + return i; + } + } + return -1; +} + +/* Find the handle which can process pa_type, or NULL if none is found. On + * success, set *modreq_out to the corresponding per-request module data. */ +static clpreauth_handle +find_module(krb5_context context, krb5_init_creds_context ctx, + krb5_preauthtype pa_type, krb5_clpreauth_modreq *modreq_out) +{ + krb5_preauth_context pctx = context->preauth_context; + krb5_preauth_req_context reqctx = ctx->preauth_reqctx; + int i; + + *modreq_out = NULL; + if (pctx == NULL || reqctx == NULL) + return NULL; + + i = search_module_list(pctx->handles, pa_type); + if (i == -1) + return NULL; + + *modreq_out = reqctx->modreqs[i]; + return pctx->handles[i]; +} + +/* Initialize the preauth state for a krb5 context. */ +void +k5_init_preauth_context(krb5_context context) +{ + krb5_plugin_initvt_fn *modules = NULL, *mod; + clpreauth_handle *list = NULL, h; + int i; + size_t count; + krb5_preauthtype *tp; + + /* Only do this once for each krb5_context */ + if (context->preauth_context != NULL) + return; + + /* Auto-register built-in modules. */ + k5_plugin_register_dyn(context, PLUGIN_INTERFACE_CLPREAUTH, "pkinit", + "preauth"); + k5_plugin_register_dyn(context, PLUGIN_INTERFACE_CLPREAUTH, "spake", + "preauth"); + k5_plugin_register(context, PLUGIN_INTERFACE_CLPREAUTH, + "encrypted_challenge", + clpreauth_encrypted_challenge_initvt); + k5_plugin_register(context, PLUGIN_INTERFACE_CLPREAUTH, + "encrypted_timestamp", + clpreauth_encrypted_timestamp_initvt); + k5_plugin_register(context, PLUGIN_INTERFACE_CLPREAUTH, "sam2", + clpreauth_sam2_initvt); + k5_plugin_register(context, PLUGIN_INTERFACE_CLPREAUTH, "otp", + clpreauth_otp_initvt); + + /* Get all available clpreauth vtables. */ + if (k5_plugin_load_all(context, PLUGIN_INTERFACE_CLPREAUTH, &modules)) + return; + + /* Allocate a large enough list of handles. */ + for (count = 0; modules[count] != NULL; count++); + list = calloc(count + 1, sizeof(*list)); + if (list == NULL) + goto cleanup; + + /* Create a handle for each module we can successfully initialize. */ + count = 0; + for (mod = modules; *mod != NULL; mod++) { + h = calloc(1, sizeof(*h)); + if (h == NULL) + goto cleanup; + + /* Initialize the handle vtable. */ + if ((*mod)(context, 1, 1, (krb5_plugin_vtable)&h->vt) != 0) { + free(h); + continue; + } + + /* Check for a preauth type conflict with an existing module. */ + for (tp = h->vt.pa_type_list; *tp != 0; tp++) { + i = search_module_list(list, *tp); + if (i != -1) { + TRACE_PREAUTH_CONFLICT(context, h->vt.name, list[i]->vt.name, + *tp); + break; + } + } + if (*tp != 0) + continue; + + /* Initialize the module data. */ + h->data = NULL; + if (h->vt.init != NULL && h->vt.init(context, &h->data) != 0) { + free(h); + continue; + } + list[count++] = h; + list[count] = NULL; + } + list[count] = NULL; + + /* Place the constructed preauth context into the krb5 context. */ + context->preauth_context = malloc(sizeof(*context->preauth_context)); + if (context->preauth_context == NULL) + goto cleanup; + context->preauth_context->handles = list; + list = NULL; + +cleanup: + k5_plugin_free_modules(context, modules); + free_handles(context, list); +} + +/* Add pa_type to the list of types which has previously failed. */ +krb5_error_code +k5_preauth_note_failed(krb5_init_creds_context ctx, krb5_preauthtype pa_type) +{ + krb5_preauth_req_context reqctx = ctx->preauth_reqctx; + krb5_preauthtype *newptr; + size_t i; + + for (i = 0; reqctx->failed != NULL && reqctx->failed[i] != 0; i++); + newptr = realloc(reqctx->failed, (i + 2) * sizeof(*newptr)); + if (newptr == NULL) + return ENOMEM; + reqctx->failed = newptr; + reqctx->failed[i] = pa_type; + reqctx->failed[i + 1] = 0; + return 0; +} + +/* Free the per-krb5_context preauth_context. This means clearing any + * plugin-specific context which may have been created, and then + * freeing the context itself. */ +void +k5_free_preauth_context(krb5_context context) +{ + krb5_preauth_context pctx = context->preauth_context; + + if (pctx == NULL) + return; + free_handles(context, pctx->handles); + free(pctx); + context->preauth_context = NULL; +} + +/* Initialize the per-AS-REQ context. This means calling the client_req_init + * function to give the plugin a chance to allocate a per-request context. */ +void +k5_preauth_request_context_init(krb5_context context, + krb5_init_creds_context ctx) +{ + krb5_preauth_context pctx = context->preauth_context; + clpreauth_handle h; + krb5_preauth_req_context reqctx; + size_t count, i; + + if (pctx == NULL) { + k5_init_preauth_context(context); + pctx = context->preauth_context; + if (pctx == NULL) + return; + } + + reqctx = calloc(1, sizeof(*reqctx)); + if (reqctx == NULL) + return; + reqctx->orig_context = context; + + /* Create an array of per-request module data objects corresponding to the + * preauth context's array of handles. */ + for (count = 0; pctx->handles[count] != NULL; count++); + reqctx->modreqs = calloc(count, sizeof(*reqctx->modreqs)); + if (reqctx->modreqs == NULL) { + free(reqctx); + return; + } + for (i = 0; i < count; i++) { + h = pctx->handles[i]; + if (h->vt.request_init != NULL) + h->vt.request_init(context, h->data, &reqctx->modreqs[i]); + } + ctx->preauth_reqctx = reqctx; +} + +/* Free the per-AS-REQ context. This means clearing any request-specific + * context which the plugin may have created. */ +void +k5_preauth_request_context_fini(krb5_context context, + krb5_init_creds_context ctx) +{ + krb5_preauth_context pctx = context->preauth_context; + krb5_preauth_req_context reqctx = ctx->preauth_reqctx; + size_t i; + clpreauth_handle h; + + if (reqctx == NULL) + return; + if (reqctx->orig_context == context && pctx != NULL) { + for (i = 0; pctx->handles[i] != NULL; i++) { + h = pctx->handles[i]; + if (reqctx->modreqs[i] != NULL && h->vt.request_fini != NULL) + h->vt.request_fini(context, h->data, reqctx->modreqs[i]); + } + } else { + TRACE_PREAUTH_WRONG_CONTEXT(context); + } + free(reqctx->modreqs); + free(reqctx->failed); + free(reqctx); + ctx->preauth_reqctx = NULL; +} + +krb5_error_code +k5_preauth_check_context(krb5_context context, krb5_init_creds_context ctx) +{ + krb5_preauth_req_context reqctx = ctx->preauth_reqctx; + + if (reqctx != NULL && reqctx->orig_context != context) { + k5_setmsg(context, EINVAL, + _("krb5_init_creds calls must use same library context")); + return EINVAL; + } + return 0; +} + +/* Return 1 if pa_type is a real preauthentication mechanism according to the + * module h. Return 0 if it is not. */ +static int +clpreauth_is_real(krb5_context context, clpreauth_handle h, + krb5_preauthtype pa_type) +{ + if (h->vt.flags == NULL) + return 1; + return (h->vt.flags(context, pa_type) & PA_REAL) != 0; +} + +static krb5_error_code +clpreauth_prep_questions(krb5_context context, clpreauth_handle h, + krb5_clpreauth_modreq modreq, + krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_kdc_req *req, krb5_data *req_body, + krb5_data *prev_req, krb5_pa_data *pa_data) +{ + if (h->vt.prep_questions == NULL) + return 0; + return h->vt.prep_questions(context, h->data, modreq, opt, cb, rock, req, + req_body, prev_req, pa_data); +} + +static krb5_error_code +clpreauth_process(krb5_context context, clpreauth_handle h, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_kdc_req *req, krb5_data *req_body, krb5_data *prev_req, + krb5_pa_data *pa_data, krb5_prompter_fct prompter, + void *prompter_data, krb5_pa_data ***pa_data_out) +{ + return h->vt.process(context, h->data, modreq, opt, cb, rock, req, + req_body, prev_req, pa_data, prompter, prompter_data, + pa_data_out); +} + +static krb5_error_code +clpreauth_tryagain(krb5_context context, clpreauth_handle h, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_kdc_req *req, krb5_data *req_body, krb5_data *prev_req, + krb5_preauthtype pa_type, krb5_error *error, + krb5_pa_data **error_padata, krb5_prompter_fct prompter, + void *prompter_data, krb5_pa_data ***pa_data_out) +{ + if (h->vt.tryagain == NULL) + return 0; + return h->vt.tryagain(context, h->data, modreq, opt, cb, rock, req, + req_body, prev_req, pa_type, error, error_padata, + prompter, prompter_data, pa_data_out); +} + +static krb5_error_code +clpreauth_gic_opts(krb5_context context, clpreauth_handle h, + krb5_get_init_creds_opt *opt, const char *attr, + const char *value) +{ + if (h->vt.gic_opts == NULL) + return 0; + return h->vt.gic_opts(context, h->data, opt, attr, value); +} + +/* Add the named encryption type to the existing list of ktypes. */ +static void +grow_ktypes(krb5_enctype **out_ktypes, int *out_nktypes, krb5_enctype ktype) +{ + int i; + krb5_enctype *ktypes; + + for (i = 0; i < *out_nktypes; i++) { + if ((*out_ktypes)[i] == ktype) + return; + } + ktypes = realloc(*out_ktypes, (*out_nktypes + 2) * sizeof(ktype)); + if (ktypes != NULL) { + *out_ktypes = ktypes; + ktypes[(*out_nktypes)++] = ktype; + ktypes[*out_nktypes] = 0; + } +} + +/* Add a list of new pa_data items to an existing list. */ +static int +grow_pa_list(krb5_pa_data ***out_pa_list, int *out_pa_list_size, + krb5_pa_data **addition, int num_addition) +{ + krb5_pa_data **pa_list; + int i; + + /* Allocate space for new entries and a null terminator. */ + pa_list = realloc(*out_pa_list, (*out_pa_list_size + num_addition + 1) * + sizeof(*pa_list)); + if (pa_list == NULL) + return ENOMEM; + *out_pa_list = pa_list; + for (i = 0; i < num_addition; i++) + pa_list[(*out_pa_list_size)++] = addition[i]; + pa_list[*out_pa_list_size] = NULL; + return 0; +} + +static krb5_enctype +get_etype(krb5_context context, krb5_clpreauth_rock rock) +{ + krb5_init_creds_context ctx = (krb5_init_creds_context)rock; + + if (ctx->reply != NULL) + return ctx->reply->enc_part.enctype; + return ctx->etype; +} + +static krb5_keyblock * +fast_armor(krb5_context context, krb5_clpreauth_rock rock) +{ + return ((krb5_init_creds_context)rock)->fast_state->armor_key; +} + +static krb5_error_code +get_as_key(krb5_context context, krb5_clpreauth_rock rock, + krb5_keyblock **keyblock) +{ + krb5_init_creds_context ctx = (krb5_init_creds_context)rock; + krb5_error_code ret; + krb5_data *salt; + + if (ctx->as_key.length == 0) { + salt = ctx->default_salt ? NULL : &ctx->salt; + ret = ctx->gak_fct(context, ctx->request->client, ctx->etype, + ctx->prompter, ctx->prompter_data, salt, + &ctx->s2kparams, &ctx->as_key, ctx->gak_data, + ctx->rctx.items); + if (ret) + return ret; + } + *keyblock = &ctx->as_key; + return 0; +} + +static krb5_error_code +set_as_key(krb5_context context, krb5_clpreauth_rock rock, + const krb5_keyblock *keyblock) +{ + krb5_init_creds_context ctx = (krb5_init_creds_context)rock; + + krb5_free_keyblock_contents(context, &ctx->as_key); + return krb5_copy_keyblock_contents(context, keyblock, &ctx->as_key); +} + +static krb5_error_code +get_preauth_time(krb5_context context, krb5_clpreauth_rock rock, + krb5_boolean allow_unauth_time, krb5_timestamp *time_out, + krb5_int32 *usec_out) +{ + return k5_init_creds_current_time(context, (krb5_init_creds_context)rock, + allow_unauth_time, time_out, usec_out); +} + +static krb5_error_code +responder_ask_question(krb5_context context, krb5_clpreauth_rock rock, + const char *question, const char *challenge) +{ + krb5_init_creds_context ctx = (krb5_init_creds_context)rock; + + /* Force plugins to use need_as_key(). */ + if (strcmp(KRB5_RESPONDER_QUESTION_PASSWORD, question) == 0) + return EINVAL; + return k5_response_items_ask_question(ctx->rctx.items, question, + challenge); +} + +static const char * +responder_get_answer(krb5_context context, krb5_clpreauth_rock rock, + const char *question) +{ + krb5_init_creds_context ctx = (krb5_init_creds_context)rock; + + /* Don't let plugins get the raw password. */ + if (strcmp(KRB5_RESPONDER_QUESTION_PASSWORD, question) == 0) + return NULL; + return k5_response_items_get_answer(ctx->rctx.items, question); +} + +static void +need_as_key(krb5_context context, krb5_clpreauth_rock rock) +{ + krb5_init_creds_context ctx = (krb5_init_creds_context)rock; + + /* Calling gac_fct() with NULL as_key indicates desire for the AS key. */ + ctx->gak_fct(context, ctx->request->client, ctx->etype, NULL, NULL, NULL, + NULL, NULL, ctx->gak_data, ctx->rctx.items); +} + +static const char * +get_cc_config(krb5_context context, krb5_clpreauth_rock rock, const char *key) +{ + krb5_init_creds_context ctx = (krb5_init_creds_context)rock; + k5_json_value value; + + if (ctx->cc_config_in == NULL) + return NULL; + + value = k5_json_object_get(ctx->cc_config_in, key); + if (value == NULL) + return NULL; + + if (k5_json_get_tid(value) != K5_JSON_TID_STRING) + return NULL; + + return k5_json_string_utf8(value); +} + +static krb5_error_code +set_cc_config(krb5_context context, krb5_clpreauth_rock rock, + const char *key, const char *data) +{ + krb5_init_creds_context ctx = (krb5_init_creds_context)rock; + krb5_error_code ret; + k5_json_string str; + + if (ctx->cc_config_out == NULL) + return ENOENT; + + ret = k5_json_string_create(data, &str); + if (ret) + return ret; + + ret = k5_json_object_set(ctx->cc_config_out, key, str); + k5_json_release(str); + return ret; +} + +static void +disable_fallback(krb5_context context, krb5_clpreauth_rock rock) +{ + ((krb5_init_creds_context)rock)->fallback_disabled = TRUE; +} + +static struct krb5_clpreauth_callbacks_st callbacks = { + 3, + get_etype, + fast_armor, + get_as_key, + set_as_key, + get_preauth_time, + responder_ask_question, + responder_get_answer, + need_as_key, + get_cc_config, + set_cc_config, + disable_fallback +}; + +/* Tweak the request body, for now adding any enctypes which the module claims + * to add support for to the list, but in the future perhaps doing more + * involved things. */ +void +k5_preauth_prepare_request(krb5_context context, krb5_get_init_creds_opt *opt, + krb5_kdc_req *req) +{ + krb5_preauth_context pctx = context->preauth_context; + clpreauth_handle *hp, h; + krb5_enctype *ep; + + if (pctx == NULL) + return; + /* Don't modify the enctype list if it's specified in the gic opts. */ + if (opt != NULL && (opt->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST)) + return; + for (hp = pctx->handles; *hp != NULL; hp++) { + h = *hp; + if (h->vt.enctype_list == NULL) + continue; + for (ep = h->vt.enctype_list; *ep != ENCTYPE_NULL; ep++) + grow_ktypes(&req->ktype, &req->nktypes, *ep); + } +} + +const char * const * KRB5_CALLCONV +krb5_responder_list_questions(krb5_context ctx, krb5_responder_context rctx) +{ + return k5_response_items_list_questions(rctx->items); +} + +const char * KRB5_CALLCONV +krb5_responder_get_challenge(krb5_context ctx, krb5_responder_context rctx, + const char *question) +{ + if (rctx == NULL) + return NULL; + + return k5_response_items_get_challenge(rctx->items, question); +} + +krb5_error_code KRB5_CALLCONV +krb5_responder_set_answer(krb5_context ctx, krb5_responder_context rctx, + const char *question, const char *answer) +{ + if (rctx == NULL) + return EINVAL; + + return k5_response_items_set_answer(rctx->items, question, answer); +} + +/* Return true if pa_type matches the specific preauth type allowed for this + * authentication, or if there is no specific allowed type. */ +static inline krb5_boolean +pa_type_allowed(krb5_init_creds_context ctx, krb5_preauthtype pa_type) +{ + return ctx->allowed_preauth_type == KRB5_PADATA_NONE || + pa_type == ctx->allowed_preauth_type; +} + +/* Return true if pa_type previously failed during this authentication. */ +static krb5_boolean +previously_failed(krb5_init_creds_context ctx, krb5_preauthtype pa_type) +{ + krb5_preauth_req_context reqctx = ctx->preauth_reqctx; + size_t i; + + for (i = 0; reqctx->failed != NULL && reqctx->failed[i] != 0; i++) { + if (reqctx->failed[i] == pa_type) + return TRUE; + } + return FALSE; +} + +/* Allow clpreauth modules to process in_pa_list and produce output padata. */ +static krb5_error_code +process_pa_data(krb5_context context, krb5_init_creds_context ctx, + krb5_pa_data **in_pa_list, krb5_boolean must_preauth, + krb5_pa_data ***out_pa_list, int *out_pa_list_size, + krb5_preauthtype *out_type) +{ + struct errinfo save = EMPTY_ERRINFO; + krb5_pa_data *pa, **pa_ptr, **mod_pa; + krb5_error_code ret = 0; + krb5_clpreauth_modreq modreq; + clpreauth_handle h; + int real, i; + + /* Process all informational padata types, then the first real preauth type + * we succeed on. */ + for (real = 0; real <= 1; real++) { + for (pa_ptr = in_pa_list; *pa_ptr != NULL; pa_ptr++) { + pa = *pa_ptr; + /* Restrict real mechanisms to the chosen one if we have one. */ + if (real && !pa_type_allowed(ctx, pa->pa_type)) + continue; + h = find_module(context, ctx, pa->pa_type, &modreq); + if (h == NULL) + continue; + /* Make sure this type is for the current pass. */ + if (clpreauth_is_real(context, h, pa->pa_type) != real) + continue; + /* Don't try a real mechanism again after failure. */ + if (real && previously_failed(ctx, pa->pa_type)) + continue; + mod_pa = NULL; + ret = clpreauth_process(context, h, modreq, ctx->opt, &callbacks, + (krb5_clpreauth_rock)ctx, ctx->request, + ctx->inner_request_body, + ctx->encoded_previous_request, pa, + ctx->prompter, ctx->prompter_data, + &mod_pa); + TRACE_PREAUTH_PROCESS(context, h->vt.name, pa->pa_type, real, + ret); + if (mod_pa != NULL) { + for (i = 0; mod_pa[i] != NULL; i++); + ret = grow_pa_list(out_pa_list, out_pa_list_size, mod_pa, i); + if (ret) { + krb5_free_pa_data(context, mod_pa); + goto cleanup; + } + free(mod_pa); + } + /* Don't continue to try mechanisms after a keyboard interrupt. */ + if (ret == KRB5_LIBOS_PWDINTR) + goto cleanup; + if (ret == 0 && real) { + /* Stop now and record which real padata type we answered. */ + *out_type = pa->pa_type; + goto cleanup; + } else if (real && save.code == 0) { + /* Save the first error we get from a real preauth type. */ + k5_save_ctx_error(context, ret, &save); + } + if (real && ret) { + /* Don't try this mechanism again for this authentication. */ + ret = k5_preauth_note_failed(ctx, pa->pa_type); + if (ret) + goto cleanup; + } + } + } + + if (must_preauth) { + /* No real preauth types succeeded and we needed to preauthenticate. */ + if (save.code != 0) { + ret = k5_restore_ctx_error(context, &save); + k5_wrapmsg(context, ret, KRB5_PREAUTH_FAILED, + _("Pre-authentication failed")); + } + ret = KRB5_PREAUTH_FAILED; + } + +cleanup: + k5_clear_error(&save); + return ret; +} + +static inline krb5_data +padata2data(krb5_pa_data p) +{ + krb5_data d; + d.magic = KV5M_DATA; + d.length = p.length; + d.data = (char *) p.contents; + return d; +} + +/* Set salt in rock based on pw-salt or afs3-salt elements in padata. */ +static krb5_error_code +get_salt(krb5_context context, krb5_init_creds_context ctx, + krb5_pa_data **padata) +{ + krb5_error_code ret; + krb5_pa_data *pa; + krb5_data d; + const char *p; + + /* Look for a pw-salt or afs3-salt element. */ + pa = krb5int_find_pa_data(context, padata, KRB5_PADATA_PW_SALT); + if (pa == NULL) + pa = krb5int_find_pa_data(context, padata, KRB5_PADATA_AFS3_SALT); + if (pa == NULL) + return 0; + + /* Set ctx->salt based on the element we found. */ + krb5_free_data_contents(context, &ctx->salt); + d = padata2data(*pa); + ret = krb5int_copy_data_contents(context, &d, &ctx->salt); + if (ret) + return ret; + + /* Adjust the salt if we got it from an afs3-salt element. */ + if (pa->pa_type == KRB5_PADATA_AFS3_SALT) { + /* Work around a (possible) old Heimdal KDC foible. */ + p = memchr(ctx->salt.data, '@', ctx->salt.length); + if (p != NULL) + ctx->salt.length = p - ctx->salt.data; + /* Tolerate extra null in MIT KDC afs3-salt value. */ + if (ctx->salt.length > 0 && + ctx->salt.data[ctx->salt.length - 1] == '\0') + ctx->salt.length--; + /* Set an s2kparams value to indicate AFS string-to-key. */ + krb5_free_data_contents(context, &ctx->s2kparams); + ret = alloc_data(&ctx->s2kparams, 1); + if (ret) + return ret; + ctx->s2kparams.data[0] = '\1'; + } + + ctx->default_salt = FALSE; + TRACE_PREAUTH_SALT(context, &ctx->salt, pa->pa_type); + return 0; +} + +/* Set etype info parameters in rock based on padata. */ +krb5_error_code +k5_get_etype_info(krb5_context context, krb5_init_creds_context ctx, + krb5_pa_data **padata) +{ + krb5_error_code ret = 0; + krb5_pa_data *pa; + krb5_data d; + krb5_etype_info etype_info = NULL, e; + krb5_etype_info_entry *entry; + krb5_boolean valid_found; + int i; + + /* Find an etype-info2 or etype-info element in padata. */ + pa = krb5int_find_pa_data(context, padata, KRB5_PADATA_ETYPE_INFO2); + if (pa != NULL) { + d = padata2data(*pa); + (void)decode_krb5_etype_info2(&d, &etype_info); + } else { + pa = krb5int_find_pa_data(context, padata, KRB5_PADATA_ETYPE_INFO); + if (pa != NULL) { + d = padata2data(*pa); + (void)decode_krb5_etype_info(&d, &etype_info); + } + } + + /* Fall back to pw-salt/afs3-salt if no etype-info element is present. */ + if (etype_info == NULL) + return get_salt(context, ctx, padata); + + /* Search entries in order of the request's enctype preference. */ + entry = NULL; + valid_found = FALSE; + for (i = 0; i < ctx->request->nktypes && entry == NULL; i++) { + for (e = etype_info; *e != NULL && entry == NULL; e++) { + if ((*e)->etype == ctx->request->ktype[i]) + entry = *e; + if (krb5_c_valid_enctype((*e)->etype)) + valid_found = TRUE; + } + } + if (entry == NULL) { + ret = (valid_found) ? KRB5_CONFIG_ETYPE_NOSUPP : + KRB5_PROG_ETYPE_NOSUPP; + goto cleanup; + } + + /* Set etype/salt/s2kparams fields based on the entry we selected. */ + ctx->etype = entry->etype; + krb5_free_data_contents(context, &ctx->salt); + if (entry->length != KRB5_ETYPE_NO_SALT) { + ctx->salt = make_data(entry->salt, entry->length); + entry->salt = NULL; + ctx->default_salt = FALSE; + } else { + ctx->salt = empty_data(); + ctx->default_salt = TRUE; + } + krb5_free_data_contents(context, &ctx->s2kparams); + ctx->s2kparams = entry->s2kparams; + entry->s2kparams = empty_data(); + TRACE_PREAUTH_ETYPE_INFO(context, ctx->etype, &ctx->salt, &ctx->s2kparams); + +cleanup: + krb5_free_etype_info(context, etype_info); + return ret; +} + +/* Look for an fx-cookie element in in_padata and add it to out_pa_list. */ +static krb5_error_code +copy_cookie(krb5_context context, krb5_pa_data **in_padata, + krb5_pa_data ***out_pa_list, int *out_pa_list_size) +{ + krb5_error_code ret; + krb5_pa_data *cookie, *pa = NULL; + + cookie = krb5int_find_pa_data(context, in_padata, KRB5_PADATA_FX_COOKIE); + if (cookie == NULL) + return 0; + TRACE_PREAUTH_COOKIE(context, cookie->length, cookie->contents); + pa = k5alloc(sizeof(*pa), &ret); + if (pa == NULL) + return ret; + *pa = *cookie; + pa->contents = k5memdup(cookie->contents, cookie->length, &ret); + if (pa->contents == NULL) + goto error; + ret = grow_pa_list(out_pa_list, out_pa_list_size, &pa, 1); + if (ret) + goto error; + return 0; + +error: + free(pa->contents); + free(pa); + return ENOMEM; +} + +/* + * If the module for pa_type can adjust its AS_REQ data using the contents of + * err and err_padata, return 0 with *padata_out set to a padata list for the + * next request. If it's the sort of correction which requires that we ask the + * user another question, we let the calling application deal with it. + */ +krb5_error_code +k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx, + krb5_preauthtype pa_type, krb5_error *err, + krb5_pa_data **err_padata, krb5_pa_data ***padata_out) +{ + krb5_error_code ret; + krb5_pa_data **mod_pa; + krb5_clpreauth_modreq modreq; + clpreauth_handle h; + int count; + + *padata_out = NULL; + + TRACE_PREAUTH_TRYAGAIN_INPUT(context, pa_type, err_padata); + + h = find_module(context, ctx, pa_type, &modreq); + if (h == NULL) + return KRB5KRB_ERR_GENERIC; + mod_pa = NULL; + ret = clpreauth_tryagain(context, h, modreq, ctx->opt, &callbacks, + (krb5_clpreauth_rock)ctx, ctx->request, + ctx->inner_request_body, + ctx->encoded_previous_request, pa_type, err, + err_padata, ctx->prompter, ctx->prompter_data, + &mod_pa); + TRACE_PREAUTH_TRYAGAIN(context, h->vt.name, pa_type, ret); + if (!ret && mod_pa == NULL) + ret = KRB5KRB_ERR_GENERIC; + if (ret) { + k5_preauth_note_failed(ctx, pa_type); + return ret; + } + + for (count = 0; mod_pa[count] != NULL; count++); + ret = copy_cookie(context, err_padata, &mod_pa, &count); + if (ret) { + krb5_free_pa_data(context, mod_pa); + return ret; + } + + TRACE_PREAUTH_TRYAGAIN_OUTPUT(context, mod_pa); + *padata_out = mod_pa; + return 0; +} + +/* Compile the set of response items for in_padata by invoke each module's + * prep_questions method. */ +static krb5_error_code +fill_response_items(krb5_context context, krb5_init_creds_context ctx, + krb5_pa_data **in_padata) +{ + krb5_error_code ret; + krb5_pa_data *pa; + krb5_clpreauth_modreq modreq; + clpreauth_handle h; + int i; + + k5_response_items_reset(ctx->rctx.items); + for (i = 0; in_padata[i] != NULL; i++) { + pa = in_padata[i]; + if (!pa_type_allowed(ctx, pa->pa_type)) + continue; + h = find_module(context, ctx, pa->pa_type, &modreq); + if (h == NULL) + continue; + ret = clpreauth_prep_questions(context, h, modreq, ctx->opt, + &callbacks, (krb5_clpreauth_rock)ctx, + ctx->request, ctx->inner_request_body, + ctx->encoded_previous_request, pa); + if (ret) + return ret; + } + return 0; +} + +krb5_error_code +k5_preauth(krb5_context context, krb5_init_creds_context ctx, + krb5_pa_data **in_padata, krb5_boolean must_preauth, + krb5_pa_data ***padata_out, krb5_preauthtype *pa_type_out) +{ + int out_pa_list_size = 0; + krb5_pa_data **out_pa_list = NULL; + krb5_error_code ret; + krb5_responder_fn responder; + void *responder_data; + + *padata_out = NULL; + *pa_type_out = KRB5_PADATA_NONE; + + /* We should never invoke preauth modules when identifying the realm. */ + if (in_padata == NULL || ctx->identify_realm) + return 0; + + TRACE_PREAUTH_INPUT(context, in_padata); + + /* Scan the padata list and process etype-info or salt elements. */ + ret = k5_get_etype_info(context, ctx, in_padata); + if (ret) + return ret; + + /* Copy the cookie if there is one. */ + ret = copy_cookie(context, in_padata, &out_pa_list, &out_pa_list_size); + if (ret) + goto error; + + /* If we can't initialize the preauth context, stop with what we have. */ + k5_init_preauth_context(context); + if (context->preauth_context == NULL) { + *padata_out = out_pa_list; + out_pa_list = NULL; + goto error; + } + + /* Get a list of response items for in_padata from the preauth modules. */ + ret = fill_response_items(context, ctx, in_padata); + if (ret) + goto error; + + /* Call the responder to answer response items. */ + k5_gic_opt_get_responder(ctx->opt, &responder, &responder_data); + if (responder != NULL && !k5_response_items_empty(ctx->rctx.items)) { + ret = (*responder)(context, responder_data, &ctx->rctx); + if (ret) + goto error; + } + + ret = process_pa_data(context, ctx, in_padata, must_preauth, + &out_pa_list, &out_pa_list_size, pa_type_out); + if (ret) + goto error; + + TRACE_PREAUTH_OUTPUT(context, out_pa_list); + *padata_out = out_pa_list; + return 0; + +error: + krb5_free_pa_data(context, out_pa_list); + return ret; +} + +/* + * Give all the preauth plugins a look at the preauth option which + * has just been set + */ +krb5_error_code +krb5_preauth_supply_preauth_data(krb5_context context, + krb5_get_init_creds_opt *opt, + const char *attr, const char *value) +{ + krb5_preauth_context pctx = context->preauth_context; + clpreauth_handle *hp, h; + krb5_error_code ret; + + if (pctx == NULL) { + k5_init_preauth_context(context); + pctx = context->preauth_context; + if (pctx == NULL) { + k5_setmsg(context, EINVAL, + _("Unable to initialize preauth context")); + return EINVAL; + } + } + + /* + * Go down the list of preauth modules, and supply them with the + * attribute/value pair. + */ + for (hp = pctx->handles; *hp != NULL; hp++) { + h = *hp; + ret = clpreauth_gic_opts(context, h, opt, attr, value); + if (ret) { + k5_prependmsg(context, ret, _("Preauth module %s"), h->vt.name); + return ret; + } + } + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/preauth_ec.c b/krb5-1.21.3/src/lib/krb5/krb/preauth_ec.c new file mode 100644 index 00000000..75aab770 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/preauth_ec.c @@ -0,0 +1,169 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/preauth_ec.c - Encrypted Challenge clpreauth module */ +/* + * Copyright (C) 2009, 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Implement Encrypted Challenge fast factor from + * draft-ietf-krb-wg-preauth-framework + */ + +#include +#include +#include "int-proto.h" + +static krb5_error_code +ec_prep_questions(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_kdc_req *request, krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, krb5_pa_data *pa_data) +{ + cb->need_as_key(context, rock); + return 0; +} + +static krb5_error_code +ec_process(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, krb5_kdc_req *request, + krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, krb5_pa_data *padata, + krb5_prompter_fct prompter, void *prompter_data, + krb5_pa_data ***out_padata) +{ + krb5_error_code retval = 0; + krb5_keyblock *challenge_key = NULL, *armor_key, *as_key; + + armor_key = cb->fast_armor(context, rock); + if (armor_key == NULL) + return ENOENT; + retval = cb->get_as_key(context, rock, &as_key); + if (retval == 0 && padata->length) { + krb5_enc_data *enc = NULL; + krb5_data scratch; + scratch.length = padata->length; + scratch.data = (char *) padata->contents; + retval = krb5_c_fx_cf2_simple(context,armor_key, "kdcchallengearmor", + as_key, "challengelongterm", + &challenge_key); + if (retval == 0) + retval = decode_krb5_enc_data(&scratch, &enc); + scratch.data = NULL; + if (retval == 0) { + scratch.data = malloc(enc->ciphertext.length); + scratch.length = enc->ciphertext.length; + if (scratch.data == NULL) + retval = ENOMEM; + } + if (retval == 0) + retval = krb5_c_decrypt(context, challenge_key, + KRB5_KEYUSAGE_ENC_CHALLENGE_KDC, NULL, + enc, &scratch); + /* + * Per draft 11 of the preauth framework, the client MAY but is not + * required to actually check the timestamp from the KDC other than to + * confirm it decrypts. This code does not perform that check. + */ + if (scratch.data) + krb5_free_data_contents(context, &scratch); + /* If we had a callback to assert that the KDC is verified, we would + * call it here. */ + if (enc) + krb5_free_enc_data(context, enc); + } else if (retval == 0) { /*No padata; we send*/ + krb5_enc_data enc; + krb5_pa_data **pa = NULL; + krb5_data *encoded_ts = NULL; + krb5_pa_enc_ts ts; + enc.ciphertext.data = NULL; + /* Use the timestamp from the preauth-required error if possible. + * This time should always be secured by the FAST channel. */ + retval = cb->get_preauth_time(context, rock, FALSE, &ts.patimestamp, + &ts.pausec); + if (retval == 0) + retval = encode_krb5_pa_enc_ts(&ts, &encoded_ts); + if (retval == 0) + retval = krb5_c_fx_cf2_simple(context, + armor_key, "clientchallengearmor", + as_key, "challengelongterm", + &challenge_key); + if (retval == 0) + retval = krb5_encrypt_helper(context, challenge_key, + KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT, + encoded_ts, &enc); + if (encoded_ts) + krb5_free_data(context, encoded_ts); + encoded_ts = NULL; + if (retval == 0) { + retval = encode_krb5_enc_data(&enc, &encoded_ts); + krb5_free_data_contents(context, &enc.ciphertext); + } + if (retval == 0) { + pa = calloc(2, sizeof(krb5_pa_data *)); + if (pa == NULL) + retval = ENOMEM; + } + if (retval == 0) { + pa[0] = calloc(1, sizeof(krb5_pa_data)); + if (pa[0] == NULL) + retval = ENOMEM; + } + if (retval == 0) { + pa[0]->length = encoded_ts->length; + pa[0]->contents = (unsigned char *) encoded_ts->data; + pa[0]->pa_type = KRB5_PADATA_ENCRYPTED_CHALLENGE; + encoded_ts->data = NULL; + *out_padata = pa; + pa = NULL; + cb->disable_fallback(context, rock); + } + free(pa); + krb5_free_data(context, encoded_ts); + } + if (challenge_key) + krb5_free_keyblock(context, challenge_key); + return retval; +} + + +static krb5_preauthtype ec_types[] = { + KRB5_PADATA_ENCRYPTED_CHALLENGE, 0}; + +krb5_error_code +clpreauth_encrypted_challenge_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) +{ + krb5_clpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_clpreauth_vtable)vtable; + vt->name = "encrypted_challenge"; + vt->pa_type_list = ec_types; + vt->prep_questions = ec_prep_questions; + vt->process = ec_process; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/preauth_encts.c b/krb5-1.21.3/src/lib/krb5/krb/preauth_encts.c new file mode 100644 index 00000000..34570198 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/preauth_encts.c @@ -0,0 +1,151 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/preauth_encts.c - Encrypted timestamp clpreauth module */ +/* + * Copyright 1995, 2003, 2008, 2011 by the Massachusetts Institute of Technology. All + * Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +#include +#include +#include "int-proto.h" +#include "init_creds_ctx.h" + +static krb5_error_code +encts_prep_questions(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, + krb5_get_init_creds_opt *opt, krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, krb5_kdc_req *request, + krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, + krb5_pa_data *pa_data) +{ + krb5_init_creds_context ctx = (krb5_init_creds_context)rock; + + if (!ctx->encts_disabled) + cb->need_as_key(context, rock); + return 0; +} + +static krb5_error_code +encts_process(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_kdc_req *request, krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, krb5_pa_data *padata, + krb5_prompter_fct prompter, void *prompter_data, + krb5_pa_data ***out_padata) +{ + krb5_init_creds_context ctx = (krb5_init_creds_context)rock; + krb5_error_code ret; + krb5_pa_enc_ts pa_enc; + krb5_data *ts = NULL, *enc_ts = NULL; + krb5_enc_data enc_data; + krb5_pa_data **pa = NULL; + krb5_keyblock *as_key; + + enc_data.ciphertext = empty_data(); + + if (ctx->encts_disabled) { + TRACE_PREAUTH_ENC_TS_DISABLED(context); + k5_setmsg(context, KRB5_PREAUTH_FAILED, + _("Encrypted timestamp is disabled")); + return KRB5_PREAUTH_FAILED; + } + + ret = cb->get_as_key(context, rock, &as_key); + if (ret) + goto cleanup; + TRACE_PREAUTH_ENC_TS_KEY_GAK(context, as_key); + + /* + * Try and use the timestamp of the preauth request, even if it's + * unauthenticated. We could be fooled into making a preauth response for + * a future time, but that has no security consequences other than the + * KDC's audit logs. If kdc_timesync is not configured, then this will + * just use local time. + */ + ret = cb->get_preauth_time(context, rock, TRUE, &pa_enc.patimestamp, + &pa_enc.pausec); + if (ret) + goto cleanup; + + ret = encode_krb5_pa_enc_ts(&pa_enc, &ts); + if (ret) + goto cleanup; + + ret = krb5_encrypt_helper(context, as_key, KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS, + ts, &enc_data); + if (ret) + goto cleanup; + TRACE_PREAUTH_ENC_TS(context, pa_enc.patimestamp, pa_enc.pausec, + ts, &enc_data.ciphertext); + + ret = encode_krb5_enc_data(&enc_data, &enc_ts); + if (ret) + goto cleanup; + + pa = k5calloc(2, sizeof(krb5_pa_data *), &ret); + if (pa == NULL) + goto cleanup; + + pa[0] = k5alloc(sizeof(krb5_pa_data), &ret); + if (pa[0] == NULL) + goto cleanup; + + pa[0]->magic = KV5M_PA_DATA; + pa[0]->pa_type = KRB5_PADATA_ENC_TIMESTAMP; + pa[0]->length = enc_ts->length; + pa[0]->contents = (krb5_octet *) enc_ts->data; + enc_ts->data = NULL; + pa[1] = NULL; + *out_padata = pa; + pa = NULL; + + cb->disable_fallback(context, rock); + +cleanup: + krb5_free_data(context, ts); + krb5_free_data(context, enc_ts); + free(enc_data.ciphertext.data); + free(pa); + return ret; +} + +static krb5_preauthtype encts_pa_types[] = { + KRB5_PADATA_ENC_TIMESTAMP, 0}; + +krb5_error_code +clpreauth_encrypted_timestamp_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) +{ + krb5_clpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_clpreauth_vtable)vtable; + vt->name = "encrypted_timestamp"; + vt->pa_type_list = encts_pa_types; + vt->prep_questions = encts_prep_questions; + vt->process = encts_process; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/preauth_otp.c b/krb5-1.21.3/src/lib/krb5/krb/preauth_otp.c new file mode 100644 index 00000000..38eaf426 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/preauth_otp.c @@ -0,0 +1,1265 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/preauth_otp.c - OTP clpreauth module */ +/* + * Copyright 2011 NORDUnet A/S. All rights reserved. + * Copyright 2011 Red Hat, Inc. 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. + * + * 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. + */ + +#include "k5-int.h" +#include "k5-json.h" +#include "int-proto.h" +#include "os-proto.h" + +#include +#include + +static krb5_preauthtype otp_client_supported_pa_types[] = + { KRB5_PADATA_OTP_CHALLENGE, 0 }; + +/* Frees a tokeninfo. */ +static void +free_tokeninfo(krb5_responder_otp_tokeninfo *ti) +{ + if (ti == NULL) + return; + + free(ti->alg_id); + free(ti->challenge); + free(ti->token_id); + free(ti->vendor); + free(ti); +} + +/* Converts a property of a json object into a char*. */ +static krb5_error_code +codec_value_to_string(k5_json_object obj, const char *key, char **string) +{ + k5_json_value val; + char *str; + + val = k5_json_object_get(obj, key); + if (val == NULL) + return ENOENT; + + if (k5_json_get_tid(val) != K5_JSON_TID_STRING) + return EINVAL; + + str = strdup(k5_json_string_utf8(val)); + if (str == NULL) + return ENOMEM; + + *string = str; + return 0; +} + +/* Converts a property of a json object into a krb5_data struct. */ +static krb5_error_code +codec_value_to_data(k5_json_object obj, const char *key, krb5_data *data) +{ + krb5_error_code retval; + char *tmp; + + retval = codec_value_to_string(obj, key, &tmp); + if (retval != 0) + return retval; + + *data = string2data(tmp); + return 0; +} + +/* Converts a krb5_data struct into a property of a JSON object. */ +static krb5_error_code +codec_data_to_value(krb5_data *data, k5_json_object obj, const char *key) +{ + krb5_error_code retval; + k5_json_string str; + + if (data->data == NULL) + return 0; + + retval = k5_json_string_create_len(data->data, data->length, &str); + if (retval) + return retval; + + retval = k5_json_object_set(obj, key, str); + k5_json_release(str); + return retval; +} + +/* Converts a property of a json object into a krb5_int32. */ +static krb5_error_code +codec_value_to_int32(k5_json_object obj, const char *key, krb5_int32 *int32) +{ + k5_json_value val; + + val = k5_json_object_get(obj, key); + if (val == NULL) + return ENOENT; + + if (k5_json_get_tid(val) != K5_JSON_TID_NUMBER) + return EINVAL; + + *int32 = k5_json_number_value(val); + return 0; +} + +/* Converts a krb5_int32 into a property of a JSON object. */ +static krb5_error_code +codec_int32_to_value(krb5_int32 int32, k5_json_object obj, const char *key) +{ + krb5_error_code retval; + k5_json_number num; + + if (int32 == -1) + return 0; + + retval = k5_json_number_create(int32, &num); + if (retval) + return retval; + + retval = k5_json_object_set(obj, key, num); + k5_json_release(num); + return retval; +} + +/* Converts a krb5_otp_tokeninfo into a JSON object. */ +static krb5_error_code +codec_encode_tokeninfo(krb5_otp_tokeninfo *ti, k5_json_object *out) +{ + krb5_error_code retval; + k5_json_object obj; + krb5_flags flags; + + retval = k5_json_object_create(&obj); + if (retval != 0) + goto error; + + flags = KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN; + if (ti->flags & KRB5_OTP_FLAG_COLLECT_PIN) { + flags |= KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN; + if (ti->flags & KRB5_OTP_FLAG_SEPARATE_PIN) + flags |= KRB5_RESPONDER_OTP_FLAGS_NEXTOTP; + } + if (ti->flags & KRB5_OTP_FLAG_NEXTOTP) + flags |= KRB5_RESPONDER_OTP_FLAGS_NEXTOTP; + + retval = codec_int32_to_value(flags, obj, "flags"); + if (retval != 0) + goto error; + + retval = codec_data_to_value(&ti->vendor, obj, "vendor"); + if (retval != 0) + goto error; + + retval = codec_data_to_value(&ti->challenge, obj, "challenge"); + if (retval != 0) + goto error; + + retval = codec_int32_to_value(ti->length, obj, "length"); + if (retval != 0) + goto error; + + if (ti->format != KRB5_OTP_FORMAT_BASE64 && + ti->format != KRB5_OTP_FORMAT_BINARY) { + retval = codec_int32_to_value(ti->format, obj, "format"); + if (retval != 0) + goto error; + } + + retval = codec_data_to_value(&ti->token_id, obj, "tokenID"); + if (retval != 0) + goto error; + + retval = codec_data_to_value(&ti->alg_id, obj, "algID"); + if (retval != 0) + goto error; + + *out = obj; + return 0; + +error: + k5_json_release(obj); + return retval; +} + +/* Converts a krb5_pa_otp_challenge into a JSON object. */ +static krb5_error_code +codec_encode_challenge(krb5_context ctx, krb5_pa_otp_challenge *chl, + char **json) +{ + k5_json_object obj = NULL, tmp = NULL; + k5_json_string str = NULL; + k5_json_array arr = NULL; + krb5_error_code retval; + int i; + + retval = k5_json_object_create(&obj); + if (retval != 0) + goto cleanup; + + if (chl->service.data) { + retval = k5_json_string_create_len(chl->service.data, + chl->service.length, &str); + if (retval != 0) + goto cleanup; + retval = k5_json_object_set(obj, "service", str); + k5_json_release(str); + if (retval != 0) + goto cleanup; + } + + retval = k5_json_array_create(&arr); + if (retval != 0) + goto cleanup; + + for (i = 0; chl->tokeninfo[i] != NULL ; i++) { + retval = codec_encode_tokeninfo(chl->tokeninfo[i], &tmp); + if (retval != 0) + goto cleanup; + + retval = k5_json_array_add(arr, tmp); + k5_json_release(tmp); + if (retval != 0) + goto cleanup; + } + + retval = k5_json_object_set(obj, "tokenInfo", arr); + if (retval != 0) + goto cleanup; + + retval = k5_json_encode(obj, json); + if (retval) + goto cleanup; + +cleanup: + k5_json_release(arr); + k5_json_release(obj); + return retval; +} + +/* Converts a JSON object into a krb5_responder_otp_tokeninfo. */ +static krb5_responder_otp_tokeninfo * +codec_decode_tokeninfo(k5_json_object obj) +{ + krb5_responder_otp_tokeninfo *ti = NULL; + krb5_error_code retval; + + ti = calloc(1, sizeof(krb5_responder_otp_tokeninfo)); + if (ti == NULL) + goto error; + + retval = codec_value_to_int32(obj, "flags", &ti->flags); + if (retval != 0) + goto error; + + retval = codec_value_to_string(obj, "vendor", &ti->vendor); + if (retval != 0 && retval != ENOENT) + goto error; + + retval = codec_value_to_string(obj, "challenge", &ti->challenge); + if (retval != 0 && retval != ENOENT) + goto error; + + retval = codec_value_to_int32(obj, "length", &ti->length); + if (retval == ENOENT) + ti->length = -1; + else if (retval != 0) + goto error; + + retval = codec_value_to_int32(obj, "format", &ti->format); + if (retval == ENOENT) + ti->format = -1; + else if (retval != 0) + goto error; + + retval = codec_value_to_string(obj, "tokenID", &ti->token_id); + if (retval != 0 && retval != ENOENT) + goto error; + + retval = codec_value_to_string(obj, "algID", &ti->alg_id); + if (retval != 0 && retval != ENOENT) + goto error; + + return ti; + +error: + free_tokeninfo(ti); + return NULL; +} + +/* Converts a JSON object into a krb5_responder_otp_challenge. */ +static krb5_responder_otp_challenge * +codec_decode_challenge(krb5_context ctx, const char *json) +{ + krb5_responder_otp_challenge *chl = NULL; + k5_json_value obj = NULL, arr = NULL, tmp = NULL; + krb5_error_code retval; + size_t i; + + retval = k5_json_decode(json, &obj); + if (retval != 0) + goto error; + + if (k5_json_get_tid(obj) != K5_JSON_TID_OBJECT) + goto error; + + arr = k5_json_object_get(obj, "tokenInfo"); + if (arr == NULL) + goto error; + + if (k5_json_get_tid(arr) != K5_JSON_TID_ARRAY) + goto error; + + chl = calloc(1, sizeof(krb5_responder_otp_challenge)); + if (chl == NULL) + goto error; + + chl->tokeninfo = calloc(k5_json_array_length(arr) + 1, + sizeof(krb5_responder_otp_tokeninfo*)); + if (chl->tokeninfo == NULL) + goto error; + + retval = codec_value_to_string(obj, "service", &chl->service); + if (retval != 0 && retval != ENOENT) + goto error; + + for (i = 0; i < k5_json_array_length(arr); i++) { + tmp = k5_json_array_get(arr, i); + if (k5_json_get_tid(tmp) != K5_JSON_TID_OBJECT) + goto error; + + chl->tokeninfo[i] = codec_decode_tokeninfo(tmp); + if (chl->tokeninfo[i] == NULL) + goto error; + } + + k5_json_release(obj); + return chl; + +error: + if (chl != NULL) { + for (i = 0; chl->tokeninfo != NULL && chl->tokeninfo[i] != NULL; i++) + free_tokeninfo(chl->tokeninfo[i]); + free(chl->tokeninfo); + free(chl); + } + k5_json_release(obj); + return NULL; +} + +/* Decode the responder answer into a tokeninfo, a value and a pin. */ +static krb5_error_code +codec_decode_answer(krb5_context context, const char *answer, + krb5_otp_tokeninfo **tis, krb5_otp_tokeninfo **ti, + krb5_data *value, krb5_data *pin) +{ + krb5_error_code retval; + k5_json_value val = NULL; + krb5_int32 indx, i; + krb5_data tmp; + + if (answer == NULL) + return EBADMSG; + + retval = k5_json_decode(answer, &val); + if (retval != 0) + goto cleanup; + + if (k5_json_get_tid(val) != K5_JSON_TID_OBJECT) + goto cleanup; + + retval = codec_value_to_int32(val, "tokeninfo", &indx); + if (retval != 0) + goto cleanup; + + for (i = 0; tis[i] != NULL; i++) { + if (i == indx) { + retval = codec_value_to_data(val, "value", &tmp); + if (retval != 0 && retval != ENOENT) + goto cleanup; + + retval = codec_value_to_data(val, "pin", pin); + if (retval != 0 && retval != ENOENT) { + krb5_free_data_contents(context, &tmp); + goto cleanup; + } + + *value = tmp; + *ti = tis[i]; + retval = 0; + goto cleanup; + } + } + retval = EINVAL; + +cleanup: + k5_json_release(val); + return retval; +} + +/* Takes the nonce from the challenge and encrypts it into the request. */ +static krb5_error_code +encrypt_nonce(krb5_context ctx, krb5_keyblock *key, + const krb5_pa_otp_challenge *chl, krb5_pa_otp_req *req) +{ + krb5_error_code retval; + krb5_enc_data encdata; + krb5_data *er; + + /* Encode the nonce. */ + retval = encode_krb5_pa_otp_enc_req(&chl->nonce, &er); + if (retval != 0) + return retval; + + /* Do the encryption. */ + retval = krb5_encrypt_helper(ctx, key, KRB5_KEYUSAGE_PA_OTP_REQUEST, + er, &encdata); + krb5_free_data(ctx, er); + if (retval != 0) + return retval; + + req->enc_data = encdata; + return 0; +} + +/* Checks to see if the user-supplied otp value matches the length and format + * of the supplied tokeninfo. */ +static int +otpvalue_matches_tokeninfo(const char *otpvalue, krb5_otp_tokeninfo *ti) +{ + int (*table[])(int c) = { isdigit, isxdigit, isalnum }; + + if (otpvalue == NULL || ti == NULL) + return 0; + + if (ti->length >= 0 && strlen(otpvalue) != (size_t)ti->length) + return 0; + + if (ti->format >= 0 && ti->format < 3) { + while (*otpvalue) { + if (!(*table[ti->format])((unsigned char)*otpvalue++)) + return 0; + } + } + + return 1; +} + +/* Performs a prompt and saves the response in the out parameter. */ +static krb5_error_code +doprompt(krb5_context context, krb5_prompter_fct prompter, void *prompter_data, + const char *banner, const char *prompttxt, char *out, size_t len) +{ + krb5_prompt prompt; + krb5_data prompt_reply; + krb5_error_code retval; + krb5_prompt_type prompt_type = KRB5_PROMPT_TYPE_PREAUTH; + + if (prompttxt == NULL || out == NULL) + return EINVAL; + + memset(out, 0, len); + + prompt_reply = make_data(out, len); + prompt.reply = &prompt_reply; + prompt.prompt = (char *)prompttxt; + prompt.hidden = 1; + + /* PROMPTER_INVOCATION */ + k5_set_prompt_types(context, &prompt_type); + retval = (*prompter)(context, prompter_data, NULL, banner, 1, &prompt); + k5_set_prompt_types(context, NULL); + if (retval != 0) + return retval; + + return 0; +} + +/* Forces the user to choose a single tokeninfo via prompting. */ +static krb5_error_code +prompt_for_tokeninfo(krb5_context context, krb5_prompter_fct prompter, + void *prompter_data, krb5_otp_tokeninfo **tis, + krb5_otp_tokeninfo **out_ti) +{ + char response[1024], *prompt; + krb5_otp_tokeninfo *ti = NULL; + krb5_error_code retval = 0; + struct k5buf buf; + int i = 0, j = 0; + + k5_buf_init_dynamic(&buf); + k5_buf_add(&buf, _("Please choose from the following:\n")); + for (i = 0; tis[i] != NULL; i++) { + k5_buf_add_fmt(&buf, "\t%d. %s ", i + 1, _("Vendor:")); + k5_buf_add_len(&buf, tis[i]->vendor.data, tis[i]->vendor.length); + k5_buf_add(&buf, "\n"); + } + prompt = k5_buf_cstring(&buf); + if (prompt == NULL) + return ENOMEM; + + do { + retval = doprompt(context, prompter, prompter_data, prompt, + _("Enter #"), response, sizeof(response)); + if (retval != 0) + goto cleanup; + + errno = 0; + j = strtol(response, NULL, 0); + if (errno != 0) { + retval = errno; + goto cleanup; + } + if (j < 1 || j > i) + continue; + + ti = tis[--j]; + } while (ti == NULL); + + *out_ti = ti; + +cleanup: + k5_buf_free(&buf); + return retval; +} + +/* Builds a challenge string from the given tokeninfo. */ +static krb5_error_code +make_challenge(const krb5_otp_tokeninfo *ti, char **challenge) +{ + if (challenge == NULL) + return EINVAL; + + *challenge = NULL; + + if (ti == NULL || ti->challenge.data == NULL) + return 0; + + if (asprintf(challenge, "%s %.*s\n", + _("OTP Challenge:"), + ti->challenge.length, + ti->challenge.data) < 0) + return ENOMEM; + + return 0; +} + +/* Determines if a pin is required. If it is, it will be prompted for. */ +static inline krb5_error_code +collect_pin(krb5_context context, krb5_prompter_fct prompter, + void *prompter_data, const krb5_otp_tokeninfo *ti, + krb5_data *out_pin) +{ + krb5_error_code retval; + char otppin[1024]; + krb5_flags collect; + krb5_data pin; + + /* If no PIN will be collected, don't prompt. */ + collect = ti->flags & (KRB5_OTP_FLAG_COLLECT_PIN | + KRB5_OTP_FLAG_SEPARATE_PIN); + if (collect == 0) { + *out_pin = empty_data(); + return 0; + } + + /* Collect the PIN. */ + retval = doprompt(context, prompter, prompter_data, NULL, + _("OTP Token PIN"), otppin, sizeof(otppin)); + if (retval != 0) + return retval; + + /* Set the PIN. */ + pin = make_data(strdup(otppin), strlen(otppin)); + if (pin.data == NULL) + return ENOMEM; + + *out_pin = pin; + return 0; +} + +/* Builds a request using the specified tokeninfo, value and pin. */ +static krb5_error_code +make_request(krb5_context ctx, krb5_otp_tokeninfo *ti, const krb5_data *value, + const krb5_data *pin, krb5_pa_otp_req **out_req) +{ + krb5_pa_otp_req *req = NULL; + krb5_error_code retval = 0; + + if (ti == NULL) + return 0; + + if (ti->format == KRB5_OTP_FORMAT_BASE64) + return ENOTSUP; + + req = calloc(1, sizeof(krb5_pa_otp_req)); + if (req == NULL) + return ENOMEM; + + req->flags = ti->flags & KRB5_OTP_FLAG_NEXTOTP; + + retval = krb5int_copy_data_contents(ctx, &ti->vendor, &req->vendor); + if (retval != 0) + goto error; + + req->format = ti->format; + + retval = krb5int_copy_data_contents(ctx, &ti->token_id, &req->token_id); + if (retval != 0) + goto error; + + retval = krb5int_copy_data_contents(ctx, &ti->alg_id, &req->alg_id); + if (retval != 0) + goto error; + + retval = krb5int_copy_data_contents(ctx, value, &req->otp_value); + if (retval != 0) + goto error; + + if (ti->flags & KRB5_OTP_FLAG_COLLECT_PIN) { + if (ti->flags & KRB5_OTP_FLAG_SEPARATE_PIN) { + if (pin == NULL || pin->data == NULL) { + retval = EINVAL; /* No pin found! */ + goto error; + } + + retval = krb5int_copy_data_contents(ctx, pin, &req->pin); + if (retval != 0) + goto error; + } else if (pin != NULL && pin->data != NULL) { + krb5_free_data_contents(ctx, &req->otp_value); + retval = asprintf(&req->otp_value.data, "%.*s%.*s", + pin->length, pin->data, + value->length, value->data); + if (retval < 0) { + retval = ENOMEM; + req->otp_value = empty_data(); + goto error; + } + req->otp_value.length = req->pin.length + req->otp_value.length; + } /* Otherwise, the responder has already combined them. */ + } + + *out_req = req; + return 0; + +error: + k5_free_pa_otp_req(ctx, req); + return retval; +} + +/* + * Filters a set of tokeninfos given an otp value. If the set is reduced to + * a single tokeninfo, it will be set in out_ti. Otherwise, a new shallow copy + * will be allocated in out_filtered. + */ +static inline krb5_error_code +filter_tokeninfos(krb5_context context, const char *otpvalue, + krb5_otp_tokeninfo **tis, + krb5_otp_tokeninfo ***out_filtered, + krb5_otp_tokeninfo **out_ti) +{ + krb5_otp_tokeninfo **filtered; + size_t i = 0, j = 0; + + while (tis[i] != NULL) + i++; + + filtered = calloc(i + 1, sizeof(const krb5_otp_tokeninfo *)); + if (filtered == NULL) + return ENOMEM; + + /* Make a list of tokeninfos that match the value. */ + for (i = 0, j = 0; tis[i] != NULL; i++) { + if (otpvalue_matches_tokeninfo(otpvalue, tis[i])) + filtered[j++] = tis[i]; + } + + /* It is an error if we have no matching tokeninfos. */ + if (filtered[0] == NULL) { + free(filtered); + k5_setmsg(context, KRB5_PREAUTH_FAILED, + _("OTP value doesn't match any token formats")); + return KRB5_PREAUTH_FAILED; /* We have no supported tokeninfos. */ + } + + /* Otherwise, if we have just one tokeninfo, choose it. */ + if (filtered[1] == NULL) { + *out_ti = filtered[0]; + *out_filtered = NULL; + free(filtered); + return 0; + } + + /* Otherwise, we'll return the remaining list. */ + *out_ti = NULL; + *out_filtered = filtered; + return 0; +} + +/* Outputs the selected tokeninfo and possibly a value and pin. + * Prompting may occur. */ +static krb5_error_code +prompt_for_token(krb5_context context, krb5_prompter_fct prompter, + void *prompter_data, krb5_otp_tokeninfo **tis, + krb5_otp_tokeninfo **out_ti, krb5_data *out_value, + krb5_data *out_pin) +{ + krb5_otp_tokeninfo **filtered = NULL; + krb5_otp_tokeninfo *ti = NULL; + krb5_error_code retval; + int i, challengers = 0; + char *challenge = NULL; + char otpvalue[1024]; + krb5_data value, pin; + + memset(otpvalue, 0, sizeof(otpvalue)); + + if (tis == NULL || tis[0] == NULL || out_ti == NULL) + return EINVAL; + + /* Count how many challenges we have. */ + for (i = 0; tis[i] != NULL; i++) { + if (tis[i]->challenge.data != NULL) + challengers++; + } + + /* If we have only one tokeninfo as input, choose it. */ + if (i == 1) + ti = tis[0]; + + /* Setup our challenge, if present. */ + if (challengers > 0) { + /* If we have multiple tokeninfos still, choose now. */ + if (ti == NULL) { + retval = prompt_for_tokeninfo(context, prompter, prompter_data, + tis, &ti); + if (retval != 0) + return retval; + } + + /* Create the challenge prompt. */ + retval = make_challenge(ti, &challenge); + if (retval != 0) + return retval; + } + + /* Prompt for token value. */ + retval = doprompt(context, prompter, prompter_data, challenge, + _("Enter OTP Token Value"), otpvalue, sizeof(otpvalue)); + free(challenge); + if (retval != 0) + return retval; + + if (ti == NULL) { + /* Filter out tokeninfos that don't match our token value. */ + retval = filter_tokeninfos(context, otpvalue, tis, &filtered, &ti); + if (retval != 0) + return retval; + + /* If we still don't have a single tokeninfo, choose now. */ + if (filtered != NULL) { + retval = prompt_for_tokeninfo(context, prompter, prompter_data, + filtered, &ti); + free(filtered); + if (retval != 0) + return retval; + } + } + + assert(ti != NULL); + + /* Set the value. */ + value = make_data(strdup(otpvalue), strlen(otpvalue)); + if (value.data == NULL) + return ENOMEM; + + /* Collect the PIN, if necessary. */ + retval = collect_pin(context, prompter, prompter_data, ti, &pin); + if (retval != 0) { + krb5_free_data_contents(context, &value); + return retval; + } + + *out_value = value; + *out_pin = pin; + *out_ti = ti; + return 0; +} + +/* Encode the OTP request into a krb5_pa_data buffer. */ +static krb5_error_code +set_pa_data(const krb5_pa_otp_req *req, krb5_pa_data ***pa_data_out) +{ + krb5_pa_data **out = NULL; + krb5_data *tmp; + + /* Allocate the preauth data array and one item. */ + out = calloc(2, sizeof(krb5_pa_data *)); + if (out == NULL) + goto error; + out[0] = calloc(1, sizeof(krb5_pa_data)); + out[1] = NULL; + if (out[0] == NULL) + goto error; + + /* Encode our request into the preauth data item. */ + memset(out[0], 0, sizeof(krb5_pa_data)); + out[0]->pa_type = KRB5_PADATA_OTP_REQUEST; + if (encode_krb5_pa_otp_req(req, &tmp) != 0) + goto error; + out[0]->contents = (krb5_octet *)tmp->data; + out[0]->length = tmp->length; + free(tmp); + + *pa_data_out = out; + return 0; + +error: + if (out != NULL) { + free(out[0]); + free(out); + } + return ENOMEM; +} + +/* Tests krb5_data to see if it is printable. */ +static krb5_boolean +is_printable_string(const krb5_data *data) +{ + unsigned int i; + + if (data == NULL) + return FALSE; + + for (i = 0; i < data->length; i++) { + if (!isprint((unsigned char)data->data[i])) + return FALSE; + } + + return TRUE; +} + +/* Returns TRUE when the given tokeninfo contains the subset of features we + * support. */ +static krb5_boolean +is_tokeninfo_supported(krb5_otp_tokeninfo *ti) +{ + krb5_flags supported_flags = KRB5_OTP_FLAG_COLLECT_PIN | + KRB5_OTP_FLAG_NO_COLLECT_PIN | + KRB5_OTP_FLAG_SEPARATE_PIN; + + /* Flags we don't support... */ + if (ti->flags & ~supported_flags) + return FALSE; + + /* We don't currently support hashing. */ + if (ti->supported_hash_alg != NULL || ti->iteration_count >= 0) + return FALSE; + + /* Remove tokeninfos with invalid vendor strings. */ + if (!is_printable_string(&ti->vendor)) + return FALSE; + + /* Remove tokeninfos with non-printable challenges. */ + if (!is_printable_string(&ti->challenge)) + return FALSE; + + /* We don't currently support base64. */ + if (ti->format == KRB5_OTP_FORMAT_BASE64) + return FALSE; + + return TRUE; +} + +/* Removes unsupported tokeninfos. Returns an error if no tokeninfos remain. */ +static krb5_error_code +filter_supported_tokeninfos(krb5_context context, krb5_otp_tokeninfo **tis) +{ + size_t i, j; + + /* Filter out any tokeninfos we don't support. */ + for (i = 0, j = 0; tis[i] != NULL; i++) { + if (!is_tokeninfo_supported(tis[i])) + k5_free_otp_tokeninfo(context, tis[i]); + else + tis[j++] = tis[i]; + } + + /* Terminate the array. */ + tis[j] = NULL; + + if (tis[0] != NULL) + return 0; + + k5_setmsg(context, KRB5_PREAUTH_FAILED, _("No supported tokens")); + return KRB5_PREAUTH_FAILED; /* We have no supported tokeninfos. */ +} + +/* + * Try to find tokeninfos which match configuration data recorded in the input + * ccache, and if exactly one is found, drop the rest. + */ +static krb5_error_code +filter_config_tokeninfos(krb5_context context, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, + krb5_otp_tokeninfo **tis) +{ + krb5_otp_tokeninfo *match = NULL; + size_t i, j; + const char *vendor, *alg_id, *token_id; + + /* Pull up what we know about the token we want to use. */ + vendor = cb->get_cc_config(context, rock, "vendor"); + alg_id = cb->get_cc_config(context, rock, "algID"); + token_id = cb->get_cc_config(context, rock, "tokenID"); + + /* Look for a single matching entry. */ + for (i = 0; tis[i] != NULL; i++) { + if (vendor != NULL && tis[i]->vendor.length > 0 && + !data_eq_string(tis[i]->vendor, vendor)) + continue; + if (alg_id != NULL && tis[i]->alg_id.length > 0 && + !data_eq_string(tis[i]->alg_id, alg_id)) + continue; + if (token_id != NULL && tis[i]->token_id.length > 0 && + !data_eq_string(tis[i]->token_id, token_id)) + continue; + /* Oh, we already had a matching entry. More than one -> no change. */ + if (match != NULL) + return 0; + match = tis[i]; + } + + /* No matching entry -> no change. */ + if (match == NULL) + return 0; + + /* Prune out everything except the best match. */ + for (i = 0, j = 0; tis[i] != NULL; i++) { + if (tis[i] != match) + k5_free_otp_tokeninfo(context, tis[i]); + else + tis[j++] = tis[i]; + } + tis[j] = NULL; + + return 0; +} + +static void +otp_client_request_init(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq *modreq_out) +{ + *modreq_out = calloc(1, sizeof(krb5_pa_otp_challenge *)); +} + +static krb5_error_code +otp_client_prep_questions(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, + krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, krb5_kdc_req *request, + krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, + krb5_pa_data *pa_data) +{ + krb5_pa_otp_challenge *chl; + krb5_error_code retval; + krb5_data tmp; + char *json; + + if (modreq == NULL) + return ENOMEM; + + /* Decode the challenge. */ + tmp = make_data(pa_data->contents, pa_data->length); + retval = decode_krb5_pa_otp_challenge(&tmp, + (krb5_pa_otp_challenge **)modreq); + if (retval != 0) + return retval; + chl = *(krb5_pa_otp_challenge **)modreq; + + /* Remove unsupported tokeninfos. */ + retval = filter_supported_tokeninfos(context, chl->tokeninfo); + if (retval != 0) + return retval; + + /* Remove tokeninfos that don't match the recorded description, if that + * results in there being only one that does. */ + retval = filter_config_tokeninfos(context, cb, rock, chl->tokeninfo); + if (retval != 0) + return retval; + + /* Make the JSON representation. */ + retval = codec_encode_challenge(context, chl, &json); + if (retval != 0) + return retval; + + /* Ask the question. */ + retval = cb->ask_responder_question(context, rock, + KRB5_RESPONDER_QUESTION_OTP, + json); + free(json); + return retval; +} + +/* + * Save the vendor, algID, and tokenID values for the selected token to the + * out_ccache, so that later we can try to use them to select the right one + * without having ot ask the user. + */ +static void +save_config_tokeninfo(krb5_context context, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, + krb5_otp_tokeninfo *ti) +{ + char *tmp; + if (ti->vendor.length > 0 && + asprintf(&tmp, "%.*s", ti->vendor.length, ti->vendor.data) >= 0) { + cb->set_cc_config(context, rock, "vendor", tmp); + free(tmp); + } + if (ti->alg_id.length > 0 && + asprintf(&tmp, "%.*s", ti->alg_id.length, ti->alg_id.data) >= 0) { + cb->set_cc_config(context, rock, "algID", tmp); + free(tmp); + } + if (ti->token_id.length > 0 && + asprintf(&tmp, "%.*s", ti->token_id.length, ti->token_id.data) >= 0) { + cb->set_cc_config(context, rock, "tokenID", tmp); + free(tmp); + } +} + +static krb5_error_code +otp_client_process(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_kdc_req *request, krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, krb5_pa_data *pa_data, + krb5_prompter_fct prompter, void *prompter_data, + krb5_pa_data ***pa_data_out) +{ + krb5_pa_otp_challenge *chl = NULL; + krb5_otp_tokeninfo *ti = NULL; + krb5_keyblock *as_key = NULL; + krb5_pa_otp_req *req = NULL; + krb5_error_code retval = 0; + krb5_data value, pin; + const char *answer; + + if (modreq == NULL) + return ENOMEM; + chl = *(krb5_pa_otp_challenge **)modreq; + + *pa_data_out = NULL; + + /* Get FAST armor key. */ + as_key = cb->fast_armor(context, rock); + if (as_key == NULL) + return ENOENT; + + /* Attempt to get token selection from the responder. */ + pin = empty_data(); + value = empty_data(); + answer = cb->get_responder_answer(context, rock, + KRB5_RESPONDER_QUESTION_OTP); + retval = codec_decode_answer(context, answer, chl->tokeninfo, &ti, &value, + &pin); + if (retval != 0) { + /* If the responder doesn't have a token selection, + * we need to select the token via prompting. */ + retval = prompt_for_token(context, prompter, prompter_data, + chl->tokeninfo, &ti, &value, &pin); + if (retval != 0) + goto error; + } + + /* Make the request. */ + retval = make_request(context, ti, &value, &pin, &req); + if (retval != 0) + goto error; + + /* Save information about the token which was used. */ + save_config_tokeninfo(context, cb, rock, ti); + + /* Encrypt the challenge's nonce and set it in the request. */ + retval = encrypt_nonce(context, as_key, chl, req); + if (retval != 0) + goto error; + + /* Use FAST armor key as response key. */ + retval = cb->set_as_key(context, rock, as_key); + if (retval != 0) + goto error; + + /* Encode the request into the pa_data output. */ + retval = set_pa_data(req, pa_data_out); + if (retval != 0) + goto error; + cb->disable_fallback(context, rock); + +error: + krb5_free_data_contents(context, &value); + krb5_free_data_contents(context, &pin); + k5_free_pa_otp_req(context, req); + return retval; +} + +static void +otp_client_request_fini(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq) +{ + if (modreq == NULL) + return; + + k5_free_pa_otp_challenge(context, *(krb5_pa_otp_challenge **)modreq); + free(modreq); +} + +krb5_error_code +clpreauth_otp_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_clpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + + vt = (krb5_clpreauth_vtable)vtable; + vt->name = "otp"; + vt->pa_type_list = otp_client_supported_pa_types; + vt->request_init = otp_client_request_init; + vt->prep_questions = otp_client_prep_questions; + vt->process = otp_client_process; + vt->request_fini = otp_client_request_fini; + vt->gic_opts = NULL; + + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_responder_otp_get_challenge(krb5_context ctx, + krb5_responder_context rctx, + krb5_responder_otp_challenge **chl) +{ + const char *answer; + krb5_responder_otp_challenge *challenge; + + answer = krb5_responder_get_challenge(ctx, rctx, + KRB5_RESPONDER_QUESTION_OTP); + if (answer == NULL) { + *chl = NULL; + return 0; + } + + challenge = codec_decode_challenge(ctx, answer); + if (challenge == NULL) + return ENOMEM; + + *chl = challenge; + return 0; +} + +krb5_error_code KRB5_CALLCONV +krb5_responder_otp_set_answer(krb5_context ctx, krb5_responder_context rctx, + size_t ti, const char *value, const char *pin) +{ + krb5_error_code retval; + k5_json_object obj = NULL; + k5_json_number num; + k5_json_string str; + char *tmp; + + retval = k5_json_object_create(&obj); + if (retval != 0) + goto error; + + retval = k5_json_number_create(ti, &num); + if (retval != 0) + goto error; + + retval = k5_json_object_set(obj, "tokeninfo", num); + k5_json_release(num); + if (retval != 0) + goto error; + + if (value != NULL) { + retval = k5_json_string_create(value, &str); + if (retval != 0) + goto error; + + retval = k5_json_object_set(obj, "value", str); + k5_json_release(str); + if (retval != 0) + goto error; + } + + if (pin != NULL) { + retval = k5_json_string_create(pin, &str); + if (retval != 0) + goto error; + + retval = k5_json_object_set(obj, "pin", str); + k5_json_release(str); + if (retval != 0) + goto error; + } + + retval = k5_json_encode(obj, &tmp); + if (retval != 0) + goto error; + k5_json_release(obj); + + retval = krb5_responder_set_answer(ctx, rctx, KRB5_RESPONDER_QUESTION_OTP, + tmp); + free(tmp); + return retval; + +error: + k5_json_release(obj); + return retval; +} + +void KRB5_CALLCONV +krb5_responder_otp_challenge_free(krb5_context ctx, + krb5_responder_context rctx, + krb5_responder_otp_challenge *chl) +{ + size_t i; + + if (chl == NULL) + return; + + for (i = 0; chl->tokeninfo[i]; i++) + free_tokeninfo(chl->tokeninfo[i]); + free(chl->service); + free(chl->tokeninfo); + free(chl); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/preauth_pkinit.c b/krb5-1.21.3/src/lib/krb5/krb/preauth_pkinit.c new file mode 100644 index 00000000..02810f2b --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/preauth_pkinit.c @@ -0,0 +1,204 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/preauth_pkinit.c - PKINIT clpreauth helpers */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +/* + * This file defines libkrb5 APIs for manipulating PKINIT responder questions + * and answers. The main body of the PKINIT clpreauth module is in the + * plugins/preauth/pkinit directory. + */ + +#include "k5-int.h" +#include "k5-json.h" +#include "int-proto.h" +#include "init_creds_ctx.h" + +struct get_one_challenge_data { + krb5_responder_pkinit_identity **identities; + krb5_error_code err; +}; + +static void +get_one_challenge(void *arg, const char *key, k5_json_value val) +{ + struct get_one_challenge_data *data; + unsigned long token_flags; + int i; + + data = arg; + if (data->err != 0) + return; + if (k5_json_get_tid(val) != K5_JSON_TID_NUMBER) { + data->err = EINVAL; + return; + } + + token_flags = k5_json_number_value(val); + /* Find the slot for this entry. */ + for (i = 0; data->identities[i] != NULL; i++) + continue; + /* Set the identity (a copy of the key) and the token flags. */ + data->identities[i] = k5alloc(sizeof(*data->identities[i]), &data->err); + if (data->identities[i] == NULL) + return; + data->identities[i]->identity = strdup(key); + if (data->identities[i]->identity == NULL) { + data->err = ENOMEM; + return; + } + data->identities[i]->token_flags = token_flags; +} + +krb5_error_code KRB5_CALLCONV +krb5_responder_pkinit_get_challenge(krb5_context ctx, + krb5_responder_context rctx, + krb5_responder_pkinit_challenge **chl_out) +{ + const char *challenge; + k5_json_value j; + struct get_one_challenge_data get_one_challenge_data; + krb5_responder_pkinit_challenge *chl = NULL; + unsigned int n_ids; + krb5_error_code ret; + + *chl_out = NULL; + challenge = krb5_responder_get_challenge(ctx, rctx, + KRB5_RESPONDER_QUESTION_PKINIT); + if (challenge == NULL) + return 0; + + ret = k5_json_decode(challenge, &j); + if (ret != 0) + return ret; + + /* Create the returned object. */ + chl = k5alloc(sizeof(*chl), &ret); + if (chl == NULL) + goto failed; + + /* Create the list of identities. */ + n_ids = k5_json_object_count(j); + chl->identities = k5calloc(n_ids + 1, sizeof(chl->identities[0]), &ret); + if (chl->identities == NULL) + goto failed; + + /* Populate the object with identities. */ + memset(&get_one_challenge_data, 0, sizeof(get_one_challenge_data)); + get_one_challenge_data.identities = chl->identities; + k5_json_object_iterate(j, get_one_challenge, &get_one_challenge_data); + if (get_one_challenge_data.err != 0) { + ret = get_one_challenge_data.err; + goto failed; + } + + /* All done. */ + k5_json_release(j); + *chl_out = chl; + return 0; + +failed: + k5_json_release(j); + krb5_responder_pkinit_challenge_free(ctx, rctx, chl); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_responder_pkinit_set_answer(krb5_context ctx, krb5_responder_context rctx, + const char *identity, const char *pin) +{ + char *answer = NULL; + const char *old_answer; + k5_json_value answers = NULL; + k5_json_string jpin = NULL; + krb5_error_code ret = ENOMEM; + + /* If there's an answer already set, we're adding/removing a value. */ + old_answer = k5_response_items_get_answer(rctx->items, + KRB5_RESPONDER_QUESTION_PKINIT); + + /* If we're removing a value, and we have no values, we're done. */ + if (old_answer == NULL && pin == NULL) + return 0; + + /* Decode the old answers. */ + if (old_answer == NULL) + old_answer = "{}"; + ret = k5_json_decode(old_answer, &answers); + if (ret != 0) + goto cleanup; + + if (k5_json_get_tid(answers) != K5_JSON_TID_OBJECT) { + ret = EINVAL; + goto cleanup; + } + + /* Create and add the new pin string, if we're adding a value. */ + if (pin != NULL) { + ret = k5_json_string_create(pin, &jpin); + if (ret != 0) + goto cleanup; + ret = k5_json_object_set(answers, identity, jpin); + if (ret != 0) + goto cleanup; + } else { + ret = k5_json_object_set(answers, identity, NULL); + if (ret != 0) + goto cleanup; + } + + /* Encode and we're done. */ + ret = k5_json_encode(answers, &answer); + if (ret != 0) + goto cleanup; + + ret = krb5_responder_set_answer(ctx, rctx, KRB5_RESPONDER_QUESTION_PKINIT, + answer); + +cleanup: + k5_json_release(jpin); + k5_json_release(answers); + free(answer); + return ret; +} + +void KRB5_CALLCONV +krb5_responder_pkinit_challenge_free(krb5_context ctx, + krb5_responder_context rctx, + krb5_responder_pkinit_challenge *chl) +{ + unsigned int i; + + if (chl == NULL) + return; + for (i = 0; chl->identities != NULL && chl->identities[i] != NULL; i++) { + free(chl->identities[i]->identity); + free(chl->identities[i]); + } + free(chl->identities); + free(chl); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/preauth_sam2.c b/krb5-1.21.3/src/lib/krb5/krb/preauth_sam2.c new file mode 100644 index 00000000..fda86bee --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/preauth_sam2.c @@ -0,0 +1,397 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/preauth_sam2.c - SAM-2 clpreauth module */ +/* + * Copyright 1995, 2003, 2008, 2012 by the Massachusetts Institute of Technology. All + * Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +#include +#include +#include "int-proto.h" +#include "os-proto.h" +#include "init_creds_ctx.h" + +/* this macro expands to the int,ptr necessary for "%.*s" in an sprintf */ + +#define SAMDATA(kdata, str, maxsize) \ + (int)((kdata.length)? \ + ((((kdata.length)<=(maxsize))?(kdata.length):strlen(str))): \ + strlen(str)), \ + (kdata.length)? \ + ((((kdata.length)<=(maxsize))?(kdata.data):(str))):(str) +static char * +sam_challenge_banner(krb5_int32 sam_type) +{ + char *label; + + switch (sam_type) { + case PA_SAM_TYPE_ENIGMA: /* Enigma Logic */ + label = _("Challenge for Enigma Logic mechanism"); + break; + case PA_SAM_TYPE_DIGI_PATH: /* Digital Pathways */ + case PA_SAM_TYPE_DIGI_PATH_HEX: /* Digital Pathways */ + label = _("Challenge for Digital Pathways mechanism"); + break; + case PA_SAM_TYPE_ACTIVCARD_DEC: /* Digital Pathways */ + case PA_SAM_TYPE_ACTIVCARD_HEX: /* Digital Pathways */ + label = _("Challenge for Activcard mechanism"); + break; + case PA_SAM_TYPE_SKEY_K0: /* S/key where KDC has key 0 */ + label = _("Challenge for Enhanced S/Key mechanism"); + break; + case PA_SAM_TYPE_SKEY: /* Traditional S/Key */ + label = _("Challenge for Traditional S/Key mechanism"); + break; + case PA_SAM_TYPE_SECURID: /* Security Dynamics */ + label = _("Challenge for Security Dynamics mechanism"); + break; + case PA_SAM_TYPE_SECURID_PREDICT: /* predictive Security Dynamics */ + label = _("Challenge for Security Dynamics mechanism"); + break; + default: + label = _("Challenge from authentication server"); + break; + } + + return(label); +} + +static krb5_error_code +sam2_process(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_kdc_req *request, krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, krb5_pa_data *padata, + krb5_prompter_fct prompter, void *prompter_data, + krb5_pa_data ***out_padata) +{ + krb5_init_creds_context ctx = (krb5_init_creds_context)rock; + krb5_error_code retval; + krb5_sam_challenge_2 *sc2 = NULL; + krb5_sam_challenge_2_body *sc2b = NULL; + krb5_data tmp_data; + krb5_data response_data; + char name[100], banner[100], prompt[100], response[100]; + krb5_prompt kprompt; + krb5_prompt_type prompt_type; + krb5_data defsalt, *salt; + krb5_checksum **cksum; + krb5_data *scratch = NULL; + krb5_boolean valid_cksum = 0; + krb5_enc_sam_response_enc_2 enc_sam_response_enc_2; + krb5_sam_response_2 sr2; + size_t ciph_len; + krb5_pa_data **sam_padata; + + if (prompter == NULL) + return KRB5_LIBOS_CANTREADPWD; + + tmp_data.length = padata->length; + tmp_data.data = (char *)padata->contents; + + if ((retval = decode_krb5_sam_challenge_2(&tmp_data, &sc2))) + return(retval); + + retval = decode_krb5_sam_challenge_2_body(&sc2->sam_challenge_2_body, &sc2b); + + if (retval) { + krb5_free_sam_challenge_2(context, sc2); + return(retval); + } + + if (!sc2->sam_cksum || ! *sc2->sam_cksum) { + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + return(KRB5_SAM_NO_CHECKSUM); + } + + if (sc2b->sam_flags & KRB5_SAM_MUST_PK_ENCRYPT_SAD) { + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + return(KRB5_SAM_UNSUPPORTED); + } + + if (!krb5_c_valid_enctype(sc2b->sam_etype)) { + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + return(KRB5_SAM_INVALID_ETYPE); + } + + /* All of the above error checks are KDC-specific, that is, they */ + /* assume a failure in the KDC reply. By returning anything other */ + /* than KRB5_KDC_UNREACH, KRB5_PREAUTH_FAILED, */ + /* KRB5_LIBOS_PWDINTR, or KRB5_REALM_CANT_RESOLVE, the client will */ + /* most likely go on to try the AS_REQ against master KDC */ + + if (!(sc2b->sam_flags & KRB5_SAM_USE_SAD_AS_KEY)) { + /* We will need the password to obtain the key used for */ + /* the checksum, and encryption of the sam_response. */ + /* Go ahead and get it now, preserving the ordering of */ + /* prompts for the user. */ + + salt = ctx->default_salt ? NULL : &ctx->salt; + retval = ctx->gak_fct(context, request->client, sc2b->sam_etype, + prompter, prompter_data, salt, &ctx->s2kparams, + &ctx->as_key, ctx->gak_data, ctx->rctx.items); + if (retval) { + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + return(retval); + } + } + + snprintf(name, sizeof(name), "%.*s", + SAMDATA(sc2b->sam_type_name, _("SAM Authentication"), + sizeof(name) - 1)); + + snprintf(banner, sizeof(banner), "%.*s", + SAMDATA(sc2b->sam_challenge_label, + sam_challenge_banner(sc2b->sam_type), + sizeof(banner)-1)); + + snprintf(prompt, sizeof(prompt), "%s%.*s%s%.*s", + sc2b->sam_challenge.length?"Challenge is [":"", + SAMDATA(sc2b->sam_challenge, "", 20), + sc2b->sam_challenge.length?"], ":"", + SAMDATA(sc2b->sam_response_prompt, "passcode", 55)); + + response_data.data = response; + response_data.length = sizeof(response); + kprompt.prompt = prompt; + kprompt.hidden = 1; + kprompt.reply = &response_data; + + prompt_type = KRB5_PROMPT_TYPE_PREAUTH; + k5_set_prompt_types(context, &prompt_type); + + if ((retval = ((*prompter)(context, prompter_data, name, + banner, 1, &kprompt)))) { + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + k5_set_prompt_types(context, NULL); + return(retval); + } + + k5_set_prompt_types(context, NULL); + + /* Generate salt used by string_to_key() */ + if (ctx->default_salt) { + if ((retval = + krb5_principal2salt(context, request->client, &defsalt))) { + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + return(retval); + } + salt = &defsalt; + } else { + salt = &ctx->salt; + defsalt.length = 0; + } + + /* Get encryption key to be used for checksum and sam_response */ + if (!(sc2b->sam_flags & KRB5_SAM_USE_SAD_AS_KEY)) { + /* Retain as_key from above gak_fct call. */ + if (defsalt.length) + free(defsalt.data); + + if (!(sc2b->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD)) { + /* + * If no flags are set, the protocol calls for us to combine the + * initial reply key with the SAD, using a method which is only + * specified for DES and 3DES enctypes. We no longer support this + * case. + */ + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + return(KRB5_SAM_UNSUPPORTED); + } + } else { + /* as_key = string_to_key(SAD) */ + + if (ctx->as_key.length) { + krb5_free_keyblock_contents(context, &ctx->as_key); + ctx->as_key.length = 0; + } + + /* generate a key using the supplied password */ + retval = krb5_c_string_to_key(context, sc2b->sam_etype, + &response_data, salt, &ctx->as_key); + + if (defsalt.length) + free(defsalt.data); + + if (retval) { + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + return(retval); + } + } + + /* Now we have a key, verify the checksum on the sam_challenge */ + + cksum = sc2->sam_cksum; + + for (; *cksum; cksum++) { + if (!krb5_c_is_keyed_cksum((*cksum)->checksum_type)) + continue; + /* Check this cksum */ + retval = krb5_c_verify_checksum(context, &ctx->as_key, + KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM, + &sc2->sam_challenge_2_body, + *cksum, &valid_cksum); + if (retval) { + krb5_free_data(context, scratch); + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + return(retval); + } + if (valid_cksum) + break; + } + + if (!valid_cksum) { + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + /* + * Note: We return AP_ERR_BAD_INTEGRITY so upper-level applications + * can interpret that as "password incorrect", which is probably + * the best error we can return in this situation. + */ + return(KRB5KRB_AP_ERR_BAD_INTEGRITY); + } + + /* fill in enc_sam_response_enc_2 */ + enc_sam_response_enc_2.magic = KV5M_ENC_SAM_RESPONSE_ENC_2; + enc_sam_response_enc_2.sam_nonce = sc2b->sam_nonce; + if (sc2b->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD) { + enc_sam_response_enc_2.sam_sad = response_data; + } else { + enc_sam_response_enc_2.sam_sad.data = NULL; + enc_sam_response_enc_2.sam_sad.length = 0; + } + + /* encode and encrypt enc_sam_response_enc_2 with as_key */ + retval = encode_krb5_enc_sam_response_enc_2(&enc_sam_response_enc_2, + &scratch); + if (retval) { + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + return(retval); + } + + /* Fill in sam_response_2 */ + memset(&sr2, 0, sizeof(sr2)); + sr2.sam_type = sc2b->sam_type; + sr2.sam_flags = sc2b->sam_flags; + sr2.sam_track_id = sc2b->sam_track_id; + sr2.sam_nonce = sc2b->sam_nonce; + + /* Now take care of sr2.sam_enc_nonce_or_sad by encrypting encoded */ + /* enc_sam_response_enc_2 from above */ + + retval = krb5_c_encrypt_length(context, ctx->as_key.enctype, + scratch->length, &ciph_len); + if (retval) { + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + krb5_free_data(context, scratch); + return(retval); + } + sr2.sam_enc_nonce_or_sad.ciphertext.length = ciph_len; + + sr2.sam_enc_nonce_or_sad.ciphertext.data = + (char *)malloc(sr2.sam_enc_nonce_or_sad.ciphertext.length); + + if (!sr2.sam_enc_nonce_or_sad.ciphertext.data) { + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + krb5_free_data(context, scratch); + return(ENOMEM); + } + + retval = krb5_c_encrypt(context, &ctx->as_key, + KRB5_KEYUSAGE_PA_SAM_RESPONSE, NULL, scratch, + &sr2.sam_enc_nonce_or_sad); + if (retval) { + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + krb5_free_data(context, scratch); + krb5_free_data_contents(context, &sr2.sam_enc_nonce_or_sad.ciphertext); + return(retval); + } + krb5_free_data(context, scratch); + scratch = NULL; + + /* Encode the sam_response_2 */ + retval = encode_krb5_sam_response_2(&sr2, &scratch); + krb5_free_sam_challenge_2(context, sc2); + krb5_free_sam_challenge_2_body(context, sc2b); + krb5_free_data_contents(context, &sr2.sam_enc_nonce_or_sad.ciphertext); + + if (retval) { + return (retval); + } + + /* Almost there, just need to make padata ! */ + sam_padata = malloc(2 * sizeof(*sam_padata)); + if (sam_padata == NULL) { + krb5_free_data(context, scratch); + return(ENOMEM); + } + sam_padata[0] = malloc(sizeof(krb5_pa_data)); + if (sam_padata[0] == NULL) { + krb5_free_data(context, scratch); + free(sam_padata); + return(ENOMEM); + } + + sam_padata[0]->magic = KV5M_PA_DATA; + sam_padata[0]->pa_type = KRB5_PADATA_SAM_RESPONSE_2; + sam_padata[0]->length = scratch->length; + sam_padata[0]->contents = (krb5_octet *) scratch->data; + free(scratch); + sam_padata[1] = NULL; + + *out_padata = sam_padata; + cb->disable_fallback(context, rock); + + return(0); +} + +static krb5_preauthtype sam2_pa_types[] = { + KRB5_PADATA_SAM_CHALLENGE_2, 0}; + +krb5_error_code +clpreauth_sam2_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_clpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_clpreauth_vtable)vtable; + vt->name = "sam2"; + vt->pa_type_list = sam2_pa_types; + vt->process = sam2_process; + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/princ_comp.c b/krb5-1.21.3/src/lib/krb5/krb/princ_comp.c new file mode 100644 index 00000000..a6936107 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/princ_comp.c @@ -0,0 +1,167 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/princ_comp.c - Compare two principals for equality */ +/* + * Copyright 1990,1991,2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "k5-unicode.h" + +static krb5_boolean +realm_compare_flags(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2, + int flags) +{ + const krb5_data *realm1 = &princ1->realm; + const krb5_data *realm2 = &princ2->realm; + + if (realm1->length != realm2->length) + return FALSE; + if (realm1->length == 0) + return TRUE; + + return (flags & KRB5_PRINCIPAL_COMPARE_CASEFOLD) ? + (strncasecmp(realm1->data, realm2->data, realm2->length) == 0) : + (memcmp(realm1->data, realm2->data, realm2->length) == 0); +} + +krb5_boolean KRB5_CALLCONV +krb5_realm_compare(krb5_context context, krb5_const_principal princ1, krb5_const_principal princ2) +{ + return realm_compare_flags(context, princ1, princ2, 0); +} + +static krb5_error_code +upn_to_principal(krb5_context context, + krb5_const_principal princ, + krb5_principal *upn) +{ + char *unparsed_name; + krb5_error_code code; + + code = krb5_unparse_name_flags(context, princ, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &unparsed_name); + if (code) { + *upn = NULL; + return code; + } + + code = krb5_parse_name(context, unparsed_name, upn); + + free(unparsed_name); + + return code; +} + +krb5_boolean KRB5_CALLCONV +krb5_principal_compare_flags(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2, + int flags) +{ + krb5_int32 i; + unsigned int utf8 = (flags & KRB5_PRINCIPAL_COMPARE_UTF8) != 0; + unsigned int casefold = (flags & KRB5_PRINCIPAL_COMPARE_CASEFOLD) != 0; + krb5_principal upn1 = NULL; + krb5_principal upn2 = NULL; + krb5_boolean ret = FALSE; + + if (flags & KRB5_PRINCIPAL_COMPARE_ENTERPRISE) { + /* Treat UPNs as if they were real principals */ + if (princ1->type == KRB5_NT_ENTERPRISE_PRINCIPAL) { + if (upn_to_principal(context, princ1, &upn1) == 0) + princ1 = upn1; + } + if (princ2->type == KRB5_NT_ENTERPRISE_PRINCIPAL) { + if (upn_to_principal(context, princ2, &upn2) == 0) + princ2 = upn2; + } + } + + if (princ1->length != princ2->length) + goto out; + + if ((flags & KRB5_PRINCIPAL_COMPARE_IGNORE_REALM) == 0 && + !realm_compare_flags(context, princ1, princ2, flags)) + goto out; + + for (i = 0; i < princ1->length; i++) { + const krb5_data *p1 = &princ1->data[i]; + const krb5_data *p2 = &princ2->data[i]; + krb5_boolean eq; + + if (casefold) { + if (utf8) + eq = (krb5int_utf8_normcmp(p1, p2, KRB5_UTF8_CASEFOLD) == 0); + else + eq = (p1->length == p2->length + && strncasecmp(p1->data, p2->data, p2->length) == 0); + } else + eq = data_eq(*p1, *p2); + + if (!eq) + goto out; + } + + ret = TRUE; + +out: + if (upn1 != NULL) + krb5_free_principal(context, upn1); + if (upn2 != NULL) + krb5_free_principal(context, upn2); + + return ret; +} + +krb5_boolean KRB5_CALLCONV krb5_is_referral_realm(const krb5_data *r) +{ + /* + * Check for a match with KRB5_REFERRAL_REALM. Currently this relies + * on that string constant being zero-length. (Unlike principal realm + * names, KRB5_REFERRAL_REALM is known to be a string.) + */ + assert(strlen(KRB5_REFERRAL_REALM)==0); + if (r->length==0) + return TRUE; + else + return FALSE; +} + +krb5_boolean KRB5_CALLCONV +krb5_principal_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + return krb5_principal_compare_flags(context, princ1, princ2, 0); +} + +krb5_boolean KRB5_CALLCONV +krb5_principal_compare_any_realm(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + return krb5_principal_compare_flags(context, princ1, princ2, KRB5_PRINCIPAL_COMPARE_IGNORE_REALM); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/privsafe.c b/krb5-1.21.3/src/lib/krb5/krb/privsafe.c new file mode 100644 index 00000000..9ba41dd4 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/privsafe.c @@ -0,0 +1,382 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/privsafe.c - Shared logic for KRB-SAFE and KRB-PRIV messages */ +/* + * Copyright (C) 2011,2019 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. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "auth_con.h" + +krb5_error_code +k5_privsafe_gen_rdata(krb5_context context, krb5_auth_context authcon, + krb5_replay_data *rdata, krb5_replay_data *caller_rdata) +{ + krb5_error_code ret; + krb5_int32 flags = authcon->auth_context_flags; + krb5_boolean do_time = !!(flags & KRB5_AUTH_CONTEXT_DO_TIME); + krb5_boolean do_sequence = !!(flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE); + krb5_boolean ret_time = !!(flags & KRB5_AUTH_CONTEXT_RET_TIME); + krb5_boolean ret_sequence = !!(flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE); + + memset(rdata, 0, sizeof(*rdata)); + if ((ret_time || ret_sequence) && caller_rdata == NULL) + return KRB5_RC_REQUIRED; + + if (do_time || ret_time) { + ret = krb5_us_timeofday(context, &rdata->timestamp, &rdata->usec); + if (ret) + return ret; + if (ret_time) { + caller_rdata->timestamp = rdata->timestamp; + caller_rdata->usec = rdata->usec; + } + } + if (do_sequence || ret_sequence) { + rdata->seq = authcon->local_seq_number; + if (ret_sequence) + caller_rdata->seq = rdata->seq; + } + + return 0; +} + +krb5_error_code +k5_privsafe_gen_addrs(krb5_context context, krb5_auth_context authcon, + krb5_address *lstorage, krb5_address *rstorage, + krb5_address **local_out, krb5_address **remote_out) +{ + krb5_error_code ret; + + *local_out = NULL; + *remote_out = NULL; + + if (authcon->local_addr != NULL) { + if (authcon->local_port != NULL) { + ret = krb5_make_fulladdr(context, authcon->local_addr, + authcon->local_port, lstorage); + if (ret) + return ret; + *local_out = lstorage; + } else { + *local_out = authcon->local_addr; + } + } + + if (authcon->remote_addr != NULL) { + if (authcon->remote_port != NULL) { + ret = krb5_make_fulladdr(context, authcon->remote_addr, + authcon->remote_port, rstorage); + if (ret) + return ret; + *remote_out = rstorage; + } else { + *remote_out = authcon->remote_addr; + } + } + + return 0; +} + +krb5_error_code +k5_privsafe_check_replay(krb5_context context, krb5_auth_context authcon, + const krb5_replay_data *rdata, + const krb5_enc_data *enc, const krb5_checksum *cksum) +{ + krb5_error_code ret; + krb5_data tag; + + assert(enc != NULL || cksum != NULL); + + if (!(authcon->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME)) + return 0; + + if (rdata != NULL) { + ret = krb5_check_clockskew(context, rdata->timestamp); + if (ret) + return ret; + } + + if (enc != NULL) { + ret = k5_rc_tag_from_ciphertext(context, enc, &tag); + if (ret) + return ret; + } else { + tag = make_data(cksum->contents, cksum->length); + } + + if (authcon->memrcache == NULL) { + ret = k5_memrcache_create(context, &authcon->memrcache); + if (ret) + return ret; + } + + return k5_memrcache_store(context, authcon->memrcache, &tag); +} + +/* + * k5_privsafe_check_seqnum + * + * We use a somewhat complex heuristic for validating received + * sequence numbers. We must accommodate both our older + * implementation, which sends negative sequence numbers, and the + * broken Heimdal implementation (at least as of 0.5.2), which + * violates X.690 BER for integer encodings. The requirement of + * handling negative sequence numbers removes one of easier means of + * detecting a Heimdal implementation, so we resort to this mess + * here. + * + * X.690 BER (and consequently DER, which are the required encoding + * rules in RFC1510) encode all integer types as signed integers. + * This means that the MSB being set on the first octet of the + * contents of the encoding indicates a negative value. Heimdal does + * not prepend the required zero octet to unsigned integer encodings + * which would otherwise have the MSB of the first octet of their + * encodings set. + * + * Our ASN.1 library implements a special decoder for sequence + * numbers, accepting both negative and positive 32-bit numbers but + * mapping them both into the space of positive unsigned 32-bit + * numbers in the obvious bit-pattern-preserving way. This maintains + * compatibility with our older implementations. This also means that + * encodings emitted by Heimdal are ambiguous. + * + * Heimdal counter value received uint32 value + * + * 0x00000080 0xFFFFFF80 + * 0x000000FF 0xFFFFFFFF + * 0x00008000 0xFFFF8000 + * 0x0000FFFF 0xFFFFFFFF + * 0x00800000 0xFF800000 + * 0x00FFFFFF 0xFFFFFFFF + * 0xFF800000 0xFF800000 + * 0xFFFFFFFF 0xFFFFFFFF + * + * We use two auth_context flags, SANE_SEQ and HEIMDAL_SEQ, which are + * only set after we can unambiguously determine the sanity of the + * sending implementation. Once one of these flags is set, we accept + * only the sequence numbers appropriate to the remote implementation + * type. We can make the determination in two different ways. The + * first is to note the receipt of a "negative" sequence number when a + * "positive" one was expected. The second is to note the receipt of + * a sequence number that wraps through "zero" in a weird way. The + * latter corresponds to the receipt of an initial sequence number in + * the ambiguous range. + * + * There are 2^7 + 2^15 + 2^23 + 2^23 = 16810112 total ambiguous + * initial Heimdal counter values, but we receive them as one of 2^23 + * possible values. There is a ~1/256 chance of a Heimdal + * implementation sending an initial sequence number in the ambiguous + * range. + * + * We have to do special treatment when receiving sequence numbers + * between 0xFF800000..0xFFFFFFFF, or when wrapping through zero + * weirdly (due to ambiguous initial sequence number). If we are + * expecting a value corresponding to an ambiguous Heimdal counter + * value, and we receive an exact match, we can mark the remote end as + * sane. + */ + +static krb5_boolean +chk_heimdal_seqnum(krb5_ui_4 exp_seq, krb5_ui_4 in_seq) +{ + if (( exp_seq & 0xFF800000) == 0x00800000 + && (in_seq & 0xFF800000) == 0xFF800000 + && (in_seq & 0x00FFFFFF) == exp_seq) + return 1; + else if (( exp_seq & 0xFFFF8000) == 0x00008000 + && (in_seq & 0xFFFF8000) == 0xFFFF8000 + && (in_seq & 0x0000FFFF) == exp_seq) + return 1; + else if (( exp_seq & 0xFFFFFF80) == 0x00000080 + && (in_seq & 0xFFFFFF80) == 0xFFFFFF80 + && (in_seq & 0x000000FF) == exp_seq) + return 1; + else + return 0; +} + +krb5_boolean +k5_privsafe_check_seqnum(krb5_context ctx, krb5_auth_context ac, + krb5_ui_4 in_seq) +{ + krb5_ui_4 exp_seq; + + exp_seq = ac->remote_seq_number; + + /* + * If sender is known to be sane, accept _only_ exact matches. + */ + if (ac->auth_context_flags & KRB5_AUTH_CONN_SANE_SEQ) + return in_seq == exp_seq; + + /* + * If sender is not known to be sane, first check the ambiguous + * range of received values, 0xFF800000..0xFFFFFFFF. + */ + if ((in_seq & 0xFF800000) == 0xFF800000) { + /* + * If expected sequence number is in the range + * 0xFF800000..0xFFFFFFFF, then we can't make any + * determinations about the sanity of the sending + * implementation. + */ + if ((exp_seq & 0xFF800000) == 0xFF800000 && in_seq == exp_seq) + return 1; + /* + * If sender is not known for certain to be a broken Heimdal + * implementation, check for exact match. + */ + if (!(ac->auth_context_flags & KRB5_AUTH_CONN_HEIMDAL_SEQ) + && in_seq == exp_seq) + return 1; + /* + * Now apply hairy algorithm for matching sequence numbers + * sent by broken Heimdal implementations. If it matches, we + * know for certain it's a broken Heimdal sender. + */ + if (chk_heimdal_seqnum(exp_seq, in_seq)) { + ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ; + return 1; + } + return 0; + } + + /* + * Received value not in the ambiguous range? If the _expected_ + * value is in the range of ambiguous Hemidal counter values, and + * it matches the received value, sender is known to be sane. + */ + if (in_seq == exp_seq) { + if (( exp_seq & 0xFFFFFF80) == 0x00000080 + || (exp_seq & 0xFFFF8000) == 0x00008000 + || (exp_seq & 0xFF800000) == 0x00800000) + ac->auth_context_flags |= KRB5_AUTH_CONN_SANE_SEQ; + return 1; + } + + /* + * Magic wraparound for the case where the initial sequence number + * is in the ambiguous range. This means that the sender's + * counter is at a different count than ours, so we correct ours, + * and mark the sender as being a broken Heimdal implementation. + */ + if (exp_seq == 0 + && !(ac->auth_context_flags & KRB5_AUTH_CONN_HEIMDAL_SEQ)) { + switch (in_seq) { + case 0x100: + case 0x10000: + case 0x1000000: + ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ; + exp_seq = in_seq; + return 1; + default: + return 0; + } + } + return 0; +} + +/* + * Verify the sender and receiver addresses from a KRB-SAFE or KRB-PRIV message + * against the auth context. msg_r_addr may be NULL, but msg_s_addr must not + * be. The auth context's remote addr must be set. + */ +krb5_error_code +k5_privsafe_check_addrs(krb5_context context, krb5_auth_context ac, + krb5_address *msg_s_addr, krb5_address *msg_r_addr) +{ + krb5_error_code ret = 0; + krb5_address **our_addrs = NULL; + const krb5_address *local_addr, *remote_addr; + krb5_address local_fulladdr, remote_fulladdr; + + local_fulladdr.contents = remote_fulladdr.contents = NULL; + + /* Determine the remote comparison address. */ + if (ac->remote_addr != NULL) { + if (ac->remote_port != NULL) { + ret = krb5_make_fulladdr(context, ac->remote_addr, ac->remote_port, + &remote_fulladdr); + if (ret) + goto cleanup; + remote_addr = &remote_fulladdr; + } else + remote_addr = ac->remote_addr; + } else + remote_addr = NULL; + + /* Determine the local comparison address (possibly NULL). */ + if (ac->local_addr != NULL) { + if (ac->local_port != NULL) { + ret = krb5_make_fulladdr(context, ac->local_addr, ac->local_port, + &local_fulladdr); + if (ret) + goto cleanup; + local_addr = &local_fulladdr; + } else + local_addr = ac->local_addr; + } else + local_addr = NULL; + + /* Check the remote address against the message's sender address. */ + if (remote_addr != NULL && + !krb5_address_compare(context, remote_addr, msg_s_addr)) { + ret = KRB5KRB_AP_ERR_BADADDR; + goto cleanup; + } + + /* Receiver address is optional; only check it if supplied. */ + if (msg_r_addr == NULL) + goto cleanup; + + /* Check the message's receiver address against the local address, or + * against all local addresses if no specific local address is set. */ + if (local_addr != NULL) { + if (!krb5_address_compare(context, local_addr, msg_r_addr)) { + ret = KRB5KRB_AP_ERR_BADADDR; + goto cleanup; + } + } else { + ret = krb5_os_localaddr(context, &our_addrs); + if (ret) + goto cleanup; + + if (!krb5_address_search(context, msg_r_addr, our_addrs)) { + ret = KRB5KRB_AP_ERR_BADADDR; + goto cleanup; + } + } + +cleanup: + free(local_fulladdr.contents); + free(remote_fulladdr.contents); + krb5_free_addresses(context, our_addrs); + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/random_str.c b/krb5-1.21.3/src/lib/krb5/krb/random_str.c new file mode 100644 index 00000000..e31430cc --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/random_str.c @@ -0,0 +1,68 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/random_str.c - Definition of krb5int_random_string() */ +/* + * 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. + */ + +#include "k5-int.h" + +/* Utility routine: Creates a readable random string in a fixed size buffer. */ +krb5_error_code +krb5int_random_string(krb5_context context, char *string, unsigned int length) +{ + static const unsigned char charlist[] = + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + krb5_error_code err = 0; + unsigned char *bytes = NULL; + unsigned int bytecount = length - 1; + + if (!err) { + bytes = malloc (bytecount); + if (bytes == NULL) { err = ENOMEM; } + } + + if (!err) { + krb5_data data; + data.length = bytecount; + data.data = (char *) bytes; + err = krb5_c_random_make_octets (context, &data); + } + + if (!err) { + unsigned int i; + for (i = 0; i < bytecount; i++) { + string [i] = charlist[bytes[i] % (sizeof (charlist) - 1)]; + } + string[length - 1] = '\0'; + } + + if (bytes != NULL) { free (bytes); } + + return err; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/rd_cred.c b/krb5-1.21.3/src/lib/krb5/krb/rd_cred.c new file mode 100644 index 00000000..d89a98ae --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/rd_cred.c @@ -0,0 +1,204 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/rd_cred.c - definition of krb5_rd_cred() */ +/* + * Copyright 1994-2009,2014 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. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "auth_con.h" + +/* + * Decrypt and decode the enc_part of a krb5_cred using the receiving subkey or + * the session key of authcon. If neither key is present, ctext->ciphertext is + * assumed to be unencrypted plain text (RFC 6448). + */ +static krb5_error_code +decrypt_encpart(krb5_context context, krb5_enc_data *ctext, + krb5_auth_context authcon, krb5_cred_enc_part **encpart_out) +{ + krb5_error_code ret; + krb5_data plain = empty_data(); + krb5_boolean decrypted = FALSE; + + *encpart_out = NULL; + + if (authcon->recv_subkey == NULL && authcon->key == NULL) + return decode_krb5_enc_cred_part(&ctext->ciphertext, encpart_out); + + ret = alloc_data(&plain, ctext->ciphertext.length); + if (ret) + return ret; + if (authcon->recv_subkey != NULL) { + ret = krb5_k_decrypt(context, authcon->recv_subkey, + KRB5_KEYUSAGE_KRB_CRED_ENCPART, 0, ctext, &plain); + decrypted = (ret == 0); + } + if (!decrypted && authcon->key != NULL) { + ret = krb5_k_decrypt(context, authcon->key, + KRB5_KEYUSAGE_KRB_CRED_ENCPART, 0, ctext, &plain); + decrypted = (ret == 0); + } + if (decrypted) + ret = decode_krb5_enc_cred_part(&plain, encpart_out); + zapfree(plain.data, plain.length); + return ret; +} + +/* Produce a list of credentials from a KRB-CRED message and its enc_part. */ +static krb5_error_code +make_cred_list(krb5_context context, krb5_cred *krbcred, + krb5_cred_enc_part *encpart, krb5_creds ***creds_out) +{ + krb5_error_code ret = 0; + krb5_creds **list = NULL; + krb5_cred_info *info; + krb5_data *ticket_data; + size_t i, count; + + *creds_out = NULL; + + /* Allocate the list of creds. */ + for (count = 0; krbcred->tickets[count] != NULL; count++); + list = k5calloc(count + 1, sizeof(*list), &ret); + if (list == NULL) + goto cleanup; + + /* For each credential, create a structure in the list of credentials and + * copy the information. */ + for (i = 0; i < count; i++) { + list[i] = k5alloc(sizeof(*list[i]), &ret); + if (list[i] == NULL) + goto cleanup; + + info = encpart->ticket_info[i]; + ret = krb5_copy_principal(context, info->client, &list[i]->client); + if (ret) + goto cleanup; + + ret = krb5_copy_principal(context, info->server, &list[i]->server); + if (ret) + goto cleanup; + + ret = krb5_copy_keyblock_contents(context, info->session, + &list[i]->keyblock); + if (ret) + goto cleanup; + + ret = krb5_copy_addresses(context, info->caddrs, &list[i]->addresses); + if (ret) + goto cleanup; + + ret = encode_krb5_ticket(krbcred->tickets[i], &ticket_data); + if (ret) + goto cleanup; + list[i]->ticket = *ticket_data; + free(ticket_data); + + list[i]->is_skey = FALSE; + list[i]->magic = KV5M_CREDS; + list[i]->times = info->times; + list[i]->ticket_flags = info->flags; + list[i]->authdata = NULL; + list[i]->second_ticket = empty_data(); + } + + *creds_out = list; + list = NULL; + +cleanup: + krb5_free_tgt_creds(context, list); + return ret; +} + +/* Validate a KRB-CRED message in creddata, and return a list of forwarded + * credentials along with replay cache information. */ +krb5_error_code KRB5_CALLCONV +krb5_rd_cred(krb5_context context, krb5_auth_context authcon, + krb5_data *creddata, krb5_creds ***creds_out, + krb5_replay_data *replaydata_out) +{ + krb5_error_code ret = 0; + krb5_creds **credlist = NULL; + krb5_cred *krbcred = NULL; + krb5_cred_enc_part *encpart = NULL; + krb5_replay_data rdata; + const krb5_int32 flags = authcon->auth_context_flags; + + *creds_out = NULL; + + if (((flags & KRB5_AUTH_CONTEXT_RET_TIME) || + (flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + replaydata_out == NULL) + return KRB5_RC_REQUIRED; + + ret = decode_krb5_cred(creddata, &krbcred); + if (ret) + goto cleanup; + + ret = decrypt_encpart(context, &krbcred->enc_part, authcon, &encpart); + if (ret) + goto cleanup; + + ret = make_cred_list(context, krbcred, encpart, &credlist); + if (ret) + goto cleanup; + + if (authcon->recv_subkey != NULL || authcon->key != NULL) { + rdata.timestamp = encpart->timestamp; + ret = k5_privsafe_check_replay(context, authcon, &rdata, + &krbcred->enc_part, NULL); + if (ret) + goto cleanup; + } + + if (flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + if (authcon->remote_seq_number != (uint32_t)encpart->nonce) { + ret = KRB5KRB_AP_ERR_BADORDER; + goto cleanup; + } + authcon->remote_seq_number++; + } + + *creds_out = credlist; + credlist = NULL; + if ((flags & KRB5_AUTH_CONTEXT_RET_TIME) || + (flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { + replaydata_out->timestamp = encpart->timestamp; + replaydata_out->usec = encpart->usec; + replaydata_out->seq = encpart->nonce; + } + +cleanup: + krb5_free_tgt_creds(context, credlist); + krb5_free_cred(context, krbcred); + krb5_free_cred_enc_part(context, encpart); + free(encpart); /* krb5_free_cred_enc_part doesn't do this */ + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/rd_error.c b/krb5-1.21.3/src/lib/krb5/krb/rd_error.c new file mode 100644 index 00000000..dbb6798c --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/rd_error.c @@ -0,0 +1,44 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/rd_error.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +/* + * Parse an error message from enc_errbuf and return an allocated structure + * containing the error message. Upon return, dec_error will point to + * allocated storage which the caller should free when finished. + * + * Returns system errors. + */ + +krb5_error_code KRB5_CALLCONV +krb5_rd_error(krb5_context context, const krb5_data *enc_errbuf, + krb5_error **dec_error) +{ + if (!krb5_is_krb_error(enc_errbuf)) + return KRB5KRB_AP_ERR_MSG_TYPE; + return(decode_krb5_error(enc_errbuf, dec_error)); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/rd_priv.c b/krb5-1.21.3/src/lib/krb5/krb/rd_priv.c new file mode 100644 index 00000000..29a97465 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/rd_priv.c @@ -0,0 +1,150 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/rd_priv.c - krb5_rd_priv() */ +/* + * Copyright 1990,1991,2007,2019 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. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "auth_con.h" + +/* + * Unmarshal a KRB-PRIV message from der_krbpriv, placing the confidential user + * data in *userdata_out, ciphertext in *enc_out, and replay data in + * *rdata_out. The caller should free *userdata_out and *enc_out when + * finished. + */ +static krb5_error_code +read_krbpriv(krb5_context context, krb5_auth_context authcon, + const krb5_data *der_krbpriv, const krb5_key key, + krb5_replay_data *rdata_out, krb5_data *userdata_out, + krb5_enc_data *enc_out) +{ + krb5_error_code ret; + krb5_priv *privmsg = NULL; + krb5_data plaintext = empty_data(); + krb5_priv_enc_part *encpart = NULL; + krb5_data *cstate; + + if (!krb5_is_krb_priv(der_krbpriv)) + return KRB5KRB_AP_ERR_MSG_TYPE; + + /* decode private message */ + ret = decode_krb5_priv(der_krbpriv, &privmsg); + if (ret) + return ret; + + ret = alloc_data(&plaintext, privmsg->enc_part.ciphertext.length); + if (ret) + goto cleanup; + + cstate = (authcon->cstate.length > 0) ? &authcon->cstate : NULL; + ret = krb5_k_decrypt(context, key, KRB5_KEYUSAGE_KRB_PRIV_ENCPART, cstate, + &privmsg->enc_part, &plaintext); + if (ret) + goto cleanup; + + ret = decode_krb5_enc_priv_part(&plaintext, &encpart); + if (ret) + goto cleanup; + + ret = k5_privsafe_check_addrs(context, authcon, encpart->s_address, + encpart->r_address); + if (ret) + goto cleanup; + + rdata_out->timestamp = encpart->timestamp; + rdata_out->usec = encpart->usec; + rdata_out->seq = encpart->seq_number; + + *userdata_out = encpart->user_data; + encpart->user_data.data = NULL; + + *enc_out = privmsg->enc_part; + memset(&privmsg->enc_part, 0, sizeof(privmsg->enc_part)); + +cleanup: + krb5_free_priv_enc_part(context, encpart); + krb5_free_priv(context, privmsg); + zapfree(plaintext.data, plaintext.length); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_rd_priv(krb5_context context, krb5_auth_context authcon, + const krb5_data *inbuf, krb5_data *userdata_out, + krb5_replay_data *rdata_out) +{ + krb5_error_code ret; + krb5_key key; + krb5_replay_data rdata; + krb5_enc_data enc; + krb5_data userdata = empty_data(); + const krb5_int32 flags = authcon->auth_context_flags; + + *userdata_out = empty_data(); + memset(&enc, 0, sizeof(enc)); + + if (((flags & KRB5_AUTH_CONTEXT_RET_TIME) || + (flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && rdata_out == NULL) + return KRB5_RC_REQUIRED; + + key = (authcon->recv_subkey != NULL) ? authcon->recv_subkey : authcon->key; + memset(&rdata, 0, sizeof(rdata)); + ret = read_krbpriv(context, authcon, inbuf, key, &rdata, &userdata, &enc); + if (ret) + goto cleanup; + + ret = k5_privsafe_check_replay(context, authcon, &rdata, &enc, NULL); + if (ret) + goto cleanup; + + if (flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + if (!k5_privsafe_check_seqnum(context, authcon, rdata.seq)) { + ret = KRB5KRB_AP_ERR_BADORDER; + goto cleanup; + } + authcon->remote_seq_number++; + } + + if ((flags & KRB5_AUTH_CONTEXT_RET_TIME) || + (flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { + rdata_out->timestamp = rdata.timestamp; + rdata_out->usec = rdata.usec; + rdata_out->seq = rdata.seq; + } + + *userdata_out = userdata; + userdata = empty_data(); + +cleanup: + krb5_free_data_contents(context, &enc.ciphertext); + krb5_free_data_contents(context, &userdata); + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/rd_rep.c b/krb5-1.21.3/src/lib/krb5/krb/rd_rep.c new file mode 100644 index 00000000..1ace4ca1 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/rd_rep.c @@ -0,0 +1,204 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/rd_rep.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (c) 2006-2008, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "k5-int.h" +#include "auth_con.h" + +/* + * Parses a KRB_AP_REP message, returning its contents. + * + * repl is filled in with with a pointer to allocated memory containing + * the fields from the encrypted response. + * + * the key in kblock is used to decrypt the message. + * + * returns system errors, encryption errors, replay errors + */ + +krb5_error_code KRB5_CALLCONV +krb5_rd_rep(krb5_context context, krb5_auth_context auth_context, + const krb5_data *inbuf, krb5_ap_rep_enc_part **repl) +{ + krb5_error_code retval; + krb5_ap_rep *reply = NULL; + krb5_ap_rep_enc_part *enc = NULL; + krb5_data scratch; + + *repl = NULL; + + if (!krb5_is_ap_rep(inbuf)) + return KRB5KRB_AP_ERR_MSG_TYPE; + + /* Decode inbuf. */ + retval = decode_krb5_ap_rep(inbuf, &reply); + if (retval) + return retval; + + /* Put together an eblock for this encryption. */ + scratch.length = reply->enc_part.ciphertext.length; + scratch.data = malloc(scratch.length); + if (scratch.data == NULL) { + retval = ENOMEM; + goto clean_scratch; + } + + retval = krb5_k_decrypt(context, auth_context->key, + KRB5_KEYUSAGE_AP_REP_ENCPART, 0, + &reply->enc_part, &scratch); + if (retval) + goto clean_scratch; + + /* Now decode the decrypted stuff. */ + retval = decode_krb5_ap_rep_enc_part(&scratch, &enc); + if (retval) + goto clean_scratch; + + /* Check reply fields. */ + if ((enc->ctime != auth_context->authentp->ctime) + || (enc->cusec != auth_context->authentp->cusec)) { + retval = KRB5_MUTUAL_FAILED; + goto clean_scratch; + } + + /* Set auth subkey. */ + if (enc->subkey) { + retval = krb5_auth_con_setrecvsubkey(context, auth_context, + enc->subkey); + if (retval) + goto clean_scratch; + retval = krb5_auth_con_setsendsubkey(context, auth_context, + enc->subkey); + if (retval) { + (void) krb5_auth_con_setrecvsubkey(context, auth_context, NULL); + goto clean_scratch; + } + /* Not used for anything yet. */ + auth_context->negotiated_etype = enc->subkey->enctype; + } + + /* Get remote sequence number. */ + auth_context->remote_seq_number = enc->seq_number; + + TRACE_RD_REP(context, enc->ctime, enc->cusec, enc->subkey, + enc->seq_number); + + *repl = enc; + enc = NULL; + +clean_scratch: + if (scratch.data) + memset(scratch.data, 0, scratch.length); + free(scratch.data); + krb5_free_ap_rep(context, reply); + krb5_free_ap_rep_enc_part(context, enc); + return retval; +} + +krb5_error_code KRB5_CALLCONV +krb5_rd_rep_dce(krb5_context context, krb5_auth_context auth_context, + const krb5_data *inbuf, krb5_ui_4 *nonce) +{ + krb5_error_code retval; + krb5_ap_rep * reply; + krb5_data scratch; + krb5_ap_rep_enc_part *repl = NULL; + + if (!krb5_is_ap_rep(inbuf)) + return KRB5KRB_AP_ERR_MSG_TYPE; + + /* decode it */ + + if ((retval = decode_krb5_ap_rep(inbuf, &reply))) + return retval; + + /* put together an eblock for this encryption */ + + scratch.length = reply->enc_part.ciphertext.length; + if (!(scratch.data = malloc(scratch.length))) { + krb5_free_ap_rep(context, reply); + return(ENOMEM); + } + + if ((retval = krb5_k_decrypt(context, auth_context->key, + KRB5_KEYUSAGE_AP_REP_ENCPART, 0, + &reply->enc_part, &scratch))) + goto clean_scratch; + + /* now decode the decrypted stuff */ + retval = decode_krb5_ap_rep_enc_part(&scratch, &repl); + if (retval) + goto clean_scratch; + + *nonce = repl->seq_number; + if (*nonce != auth_context->local_seq_number) { + retval = KRB5_MUTUAL_FAILED; + goto clean_scratch; + } + + /* Must be NULL to prevent echoing for client AP-REP */ + if (repl->subkey != NULL) { + retval = KRB5_MUTUAL_FAILED; + goto clean_scratch; + } + + TRACE_RD_REP_DCE(context, repl->ctime, repl->cusec, repl->seq_number); + +clean_scratch: + memset(scratch.data, 0, scratch.length); + + if (repl != NULL) + krb5_free_ap_rep_enc_part(context, repl); + krb5_free_ap_rep(context, reply); + free(scratch.data); + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/rd_req.c b/krb5-1.21.3/src/lib/krb5/krb/rd_req.c new file mode 100644 index 00000000..c0fc9793 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/rd_req.c @@ -0,0 +1,109 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/rd_req.c */ +/* + * Copyright 1990,1991, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "auth_con.h" + +/* + * Parses a KRB_AP_REQ message, returning its contents. + * + * server specifies the expected server's name for the ticket. + * + * keyproc specifies a procedure to generate a decryption key for the + * ticket. If keyproc is non-NULL, keyprocarg is passed to it, and the result + * used as a decryption key. If keyproc is NULL, then fetchfrom is checked; + * if it is non-NULL, it specifies a parameter name from which to retrieve the + * decryption key. If fetchfrom is NULL, then the default key store is + * consulted. + * + * returns system errors, encryption errors, replay errors + */ + +krb5_error_code KRB5_CALLCONV +krb5_rd_req(krb5_context context, krb5_auth_context *auth_context, + const krb5_data *inbuf, krb5_const_principal server, + krb5_keytab keytab, krb5_flags *ap_req_options, + krb5_ticket **ticket) +{ + krb5_error_code retval; + krb5_ap_req * request; + krb5_auth_context new_auth_context; + krb5_keytab new_keytab = NULL; + + if (!krb5_is_ap_req(inbuf)) + return KRB5KRB_AP_ERR_MSG_TYPE; +#ifndef LEAN_CLIENT + if ((retval = decode_krb5_ap_req(inbuf, &request))) { + switch (retval) { + case KRB5_BADMSGTYPE: + return KRB5KRB_AP_ERR_BADVERSION; + default: + return(retval); + } + } +#endif /* LEAN_CLIENT */ + + /* Get an auth context if necessary. */ + new_auth_context = NULL; + if (*auth_context == NULL) { + if ((retval = krb5_auth_con_init(context, &new_auth_context))) + goto cleanup_request; + *auth_context = new_auth_context; + } + + +#ifndef LEAN_CLIENT + /* Get a keytab if necessary. */ + if (keytab == NULL) { + if ((retval = krb5_kt_default(context, &new_keytab))) + goto cleanup_auth_context; + keytab = new_keytab; + } +#endif /* LEAN_CLIENT */ + + retval = krb5_rd_req_decoded(context, auth_context, request, server, + keytab, ap_req_options, NULL); + if (!retval && ticket != NULL) { + /* Steal the ticket pointer for the caller. */ + *ticket = request->ticket; + request->ticket = NULL; + } + +#ifndef LEAN_CLIENT + if (new_keytab != NULL) + (void) krb5_kt_close(context, new_keytab); +#endif /* LEAN_CLIENT */ + +cleanup_auth_context: + if (new_auth_context && retval) { + krb5_auth_con_free(context, new_auth_context); + *auth_context = NULL; + } + +cleanup_request: + krb5_free_ap_req(context, request); + return retval; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/rd_req_dec.c b/krb5-1.21.3/src/lib/krb5/krb/rd_req_dec.c new file mode 100644 index 00000000..f37a3602 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/rd_req_dec.c @@ -0,0 +1,976 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/rd_req_dec.c */ +/* + * Copyright (c) 1994 CyberSAFE Corporation. + * Copyright 1990,1991,2007,2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * Neither M.I.T., the Open Computing Security Group, nor + * CyberSAFE Corporation make any representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * + * krb5_rd_req_decoded() + */ + +#include "k5-int.h" +#include "auth_con.h" +#include "authdata.h" +#include "int-proto.h" +#include "os-proto.h" + +/* + * essentially the same as krb_rd_req, but uses a decoded AP_REQ as + * the input rather than an encoded input. + */ +/* + * Parses a KRB_AP_REQ message, returning its contents. + * + * server specifies the expected server's name for the ticket; if NULL, then + * any server will be accepted if the key can be found, and the caller should + * verify that the principal is something it trusts. With the exception of the + * kdb keytab, the ticket's server field need not match the name passed in for + * server. All that is required is that the ticket be encrypted with a key + * from the keytab associated with the specified server principal. This + * permits the KDC to have a set of aliases for the server without keeping + * this information consistent with the server. So, when server is non-null, + * the principal expected by the application needs to be consistent with the + * local keytab, but not with the informational name in the ticket. + * + * rcache specifies a replay detection cache used to store authenticators and + * server names + * + * keyproc specifies a procedure to generate a decryption key for the + * ticket. If keyproc is non-NULL, keyprocarg is passed to it, and the result + * used as a decryption key. If keyproc is NULL, then fetchfrom is checked; + * if it is non-NULL, it specifies a parameter name from which to retrieve the + * decryption key. If fetchfrom is NULL, then the default key store is + * consulted. + * + * authdat is set to point at allocated storage structures; the caller + * should free them when finished. + * + * returns system errors, encryption errors, replay errors + */ + +static krb5_error_code +decrypt_authenticator(krb5_context, const krb5_ap_req *, + krb5_authenticator **, int); +static krb5_error_code +decode_etype_list(krb5_context context, + const krb5_authenticator *authp, + krb5_enctype **desired_etypes, + int *desired_etypes_len); +static krb5_error_code +negotiate_etype(krb5_context context, + const krb5_enctype *desired_etypes, + int desired_etypes_len, + int mandatory_etypes_index, + const krb5_enctype *permitted_etypes, + int permitted_etypes_len, + krb5_enctype *negotiated_etype); + +/* Unparse the specified server principal (which may be NULL) and the ticket + * server principal. */ +static krb5_error_code +unparse_princs(krb5_context context, krb5_const_principal server, + krb5_const_principal tkt_server, char **sname_out, + char **tsname_out) +{ + krb5_error_code ret; + char *sname = NULL, *tsname; + + *sname_out = *tsname_out = NULL; + if (server != NULL) { + ret = krb5_unparse_name(context, server, &sname); + if (ret) + return ret; + } + ret = krb5_unparse_name(context, tkt_server, &tsname); + if (ret) { + krb5_free_unparsed_name(context, sname); + return ret; + } + *sname_out = sname; + *tsname_out = tsname; + return 0; +} + +/* Return a helpful code and error when we cannot look up the keytab entry for + * an explicit server principal using the ticket's kvno and enctype. */ +static krb5_error_code +keytab_fetch_error(krb5_context context, krb5_error_code code, + krb5_const_principal princ, + krb5_const_principal tkt_server, krb5_kvno tkt_kvno, + krb5_boolean explicit_server) +{ + krb5_error_code ret; + char *sname = NULL, *tsname = NULL; + + if (code == ENOENT || code == EPERM || code == EACCES) { + k5_change_error_message_code(context, code, KRB5KRB_AP_ERR_NOKEY); + return KRB5KRB_AP_ERR_NOKEY; + } + + if (code == KRB5_KT_NOTFOUND) { + ret = explicit_server ? KRB5KRB_AP_ERR_NOKEY : KRB5KRB_AP_ERR_NOT_US; + k5_change_error_message_code(context, code, ret); + return ret; + } + + if (code != KRB5_KT_KVNONOTFOUND) + return code; + + assert(princ != NULL); + ret = unparse_princs(context, princ, tkt_server, &sname, &tsname); + if (ret) + return ret; + if (krb5_principal_compare(context, princ, tkt_server)) { + ret = KRB5KRB_AP_ERR_BADKEYVER; + k5_setmsg(context, ret, _("Cannot find key for %s kvno %d in keytab"), + sname, (int)tkt_kvno); + } else { + ret = KRB5KRB_AP_ERR_NOT_US; + k5_setmsg(context, ret, + _("Cannot find key for %s kvno %d in keytab (request ticket " + "server %s)"), sname, (int)tkt_kvno, tsname); + } + krb5_free_unparsed_name(context, sname); + krb5_free_unparsed_name(context, tsname); + return ret; +} + +/* Return a helpful code and error when ticket decryption fails using the key + * for an explicit server principal. */ +static krb5_error_code +integrity_error(krb5_context context, krb5_const_principal server, + krb5_const_principal tkt_server) +{ + krb5_error_code ret; + char *sname = NULL, *tsname = NULL; + + assert(server != NULL); + ret = unparse_princs(context, server, tkt_server, &sname, &tsname); + if (ret) + return ret; + + ret = krb5_principal_compare(context, server, tkt_server) ? + KRB5KRB_AP_ERR_BAD_INTEGRITY : KRB5KRB_AP_ERR_NOT_US; + k5_setmsg(context, ret, + _("Cannot decrypt ticket for %s using keytab key for %s"), + tsname, sname); + krb5_free_unparsed_name(context, sname); + krb5_free_unparsed_name(context, tsname); + return ret; +} + +/* Return a helpful code and error when we cannot iterate over the keytab and + * the specified server does not match the ticket server. */ +static krb5_error_code +nomatch_error(krb5_context context, krb5_const_principal server, + krb5_const_principal tkt_server) +{ + krb5_error_code ret; + char *sname = NULL, *tsname = NULL; + + assert(server != NULL); + ret = unparse_princs(context, server, tkt_server, &sname, &tsname); + if (ret) + return ret; + + k5_setmsg(context, KRB5KRB_AP_ERR_NOT_US, + _("Server principal %s does not match request ticket server %s"), + sname, tsname); + krb5_free_unparsed_name(context, sname); + krb5_free_unparsed_name(context, tsname); + return KRB5KRB_AP_ERR_NOT_US; +} + +/* Return a helpful error code and message when we fail to find a key after + * iterating over the keytab. */ +static krb5_error_code +iteration_error(krb5_context context, krb5_const_principal server, + krb5_const_principal tkt_server, krb5_kvno tkt_kvno, + krb5_enctype tkt_etype, krb5_boolean tkt_server_mismatch, + krb5_boolean found_server_match, krb5_boolean found_tkt_server, + krb5_boolean found_kvno, krb5_boolean found_higher_kvno, + krb5_boolean found_enctype) +{ + krb5_error_code ret; + char *sname = NULL, *tsname = NULL, encname[128]; + + ret = unparse_princs(context, server, tkt_server, &sname, &tsname); + if (ret) + return ret; + if (krb5_enctype_to_name(tkt_etype, TRUE, encname, sizeof(encname)) != 0) + (void)snprintf(encname, sizeof(encname), "%d", (int)tkt_etype); + + if (!found_server_match) { + ret = KRB5KRB_AP_ERR_NOKEY; + if (sname == NULL) { + k5_setmsg(context, ret, _("No keys in keytab")); + } else { + k5_setmsg(context, ret, + _("Server principal %s does not match any keys in " + "keytab"), sname); + } + } else if (tkt_server_mismatch) { + assert(sname != NULL); /* Null server princ would match anything. */ + ret = KRB5KRB_AP_ERR_NOT_US; + k5_setmsg(context, ret, + _("Request ticket server %s found in keytab but does not " + "match server principal %s"), tsname, sname); + } else if (!found_tkt_server) { + ret = KRB5KRB_AP_ERR_NOT_US; + k5_setmsg(context, ret, + _("Request ticket server %s not found in keytab (ticket " + "kvno %d)"), tsname, (int)tkt_kvno); + } else if (!found_kvno) { + ret = KRB5KRB_AP_ERR_BADKEYVER; + if (found_higher_kvno) { + k5_setmsg(context, ret, + _("Request ticket server %s kvno %d not found in " + "keytab; ticket is likely out of date"), + tsname, (int)tkt_kvno); + } else { + k5_setmsg(context, ret, + _("Request ticket server %s kvno %d not found in " + "keytab; keytab is likely out of date"), + tsname, (int)tkt_kvno); + } + } else if (!found_enctype) { + /* There's no defined error for having the key version but not the + * enctype. */ + ret = KRB5KRB_AP_ERR_BADKEYVER; + k5_setmsg(context, ret, + _("Request ticket server %s kvno %d found in keytab but not " + "with enctype %s"), tsname, (int)tkt_kvno, encname); + } else { + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + k5_setmsg(context, ret, + _("Request ticket server %s kvno %d enctype %s found in " + "keytab but cannot decrypt ticket"), + tsname, (int)tkt_kvno, encname); + } + + krb5_free_unparsed_name(context, sname); + krb5_free_unparsed_name(context, tsname); + return ret; +} + +/* Return true if princ might match multiple principals. */ +static inline krb5_boolean +is_matching(krb5_context context, krb5_const_principal princ) +{ + if (princ == NULL) + return TRUE; + return (princ->type == KRB5_NT_SRV_HST && princ->length == 2 + && (princ->realm.length == 0 || princ->data[1].length == 0 || + context->ignore_acceptor_hostname)); +} + +/* Decrypt the ticket in req using the key in ent. */ +static krb5_error_code +try_one_entry(krb5_context context, const krb5_ap_req *req, + krb5_keytab_entry *ent, krb5_keyblock *keyblock_out) +{ + krb5_error_code ret; + krb5_principal tmp = NULL; + + /* Try decrypting the ticket with this entry's key. */ + ret = krb5_decrypt_tkt_part(context, &ent->key, req->ticket); + if (ret) + return ret; + + /* Make a copy of the principal for the ticket server field. */ + ret = krb5_copy_principal(context, ent->principal, &tmp); + if (ret) + return ret; + + /* Make a copy of the decrypting key if requested by the caller. */ + if (keyblock_out != NULL) { + ret = krb5_copy_keyblock_contents(context, &ent->key, keyblock_out); + if (ret) { + krb5_free_principal(context, tmp); + return ret; + } + } + + /* Make req->ticket->server indicate the actual server principal. */ + krb5_free_principal(context, req->ticket->server); + req->ticket->server = tmp; + + return 0; +} + +/* Decrypt the ticket in req using a principal looked up from keytab. + * explicit_server should be true if this is the only usable principal. */ +static krb5_error_code +try_one_princ(krb5_context context, const krb5_ap_req *req, + krb5_const_principal princ, krb5_keytab keytab, + krb5_boolean explicit_server, krb5_keyblock *keyblock_out) +{ + krb5_error_code ret; + krb5_keytab_entry ent; + krb5_kvno tkt_kvno = req->ticket->enc_part.kvno; + krb5_enctype tkt_etype = req->ticket->enc_part.enctype; + krb5_principal tkt_server = req->ticket->server; + + ret = krb5_kt_get_entry(context, keytab, princ, tkt_kvno, tkt_etype, &ent); + if (ret) { + return keytab_fetch_error(context, ret, princ, tkt_server, tkt_kvno, + explicit_server); + } + ret = try_one_entry(context, req, &ent, keyblock_out); + if (ret == 0) + TRACE_RD_REQ_DECRYPT_SPECIFIC(context, ent.principal, &ent.key); + (void)krb5_free_keytab_entry_contents(context, &ent); + if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) + return integrity_error(context, princ, req->ticket->server); + return ret; +} + +/* + * Decrypt the ticket in req using an entry in keytab matching server (if + * given). Set req->ticket->server to the principal of the keytab entry used. + * Store the decrypting key in *keyblock_out if it is not NULL. + */ +static krb5_error_code +decrypt_try_server(krb5_context context, const krb5_ap_req *req, + krb5_const_principal server, krb5_keytab keytab, + krb5_keyblock *keyblock_out) +{ + krb5_error_code ret; + krb5_keytab_entry ent; + krb5_kt_cursor cursor; + krb5_principal tkt_server = req->ticket->server; + krb5_kvno tkt_kvno = req->ticket->enc_part.kvno; + krb5_enctype tkt_etype = req->ticket->enc_part.enctype; + krb5_boolean similar_enctype; + krb5_boolean tkt_server_mismatch = FALSE, found_server_match = FALSE; + krb5_boolean found_tkt_server = FALSE, found_enctype = FALSE; + krb5_boolean found_kvno = FALSE, found_higher_kvno = FALSE; + +#ifdef LEAN_CLIENT + return KRB5KRB_AP_WRONG_PRINC; +#else + /* If we have an explicit server principal, try just that one. */ + if (!is_matching(context, server)) { + return try_one_princ(context, req, server, keytab, TRUE, + keyblock_out); + } + + if (keytab->ops->start_seq_get == NULL) { + /* We can't iterate over the keytab. Try the principal asserted by the + * client if it's allowed by the server parameter. */ + if (!krb5_sname_match(context, server, tkt_server)) + return nomatch_error(context, server, tkt_server); + return try_one_princ(context, req, tkt_server, keytab, FALSE, + keyblock_out); + } + + /* Scan all keys in the keytab, in case the ticket server is an alias for + * one of the principals in the keytab. */ + ret = krb5_kt_start_seq_get(context, keytab, &cursor); + if (ret) { + k5_change_error_message_code(context, ret, KRB5KRB_AP_ERR_NOKEY); + return KRB5KRB_AP_ERR_NOKEY; + } + while ((ret = krb5_kt_next_entry(context, keytab, &ent, &cursor)) == 0) { + /* Only try keys which match the server principal. */ + if (!krb5_sname_match(context, server, ent.principal)) { + if (krb5_principal_compare(context, ent.principal, tkt_server)) + tkt_server_mismatch = TRUE; + (void)krb5_free_keytab_entry_contents(context, &ent); + continue; + } + found_server_match = TRUE; + + if (krb5_c_enctype_compare(context, ent.key.enctype, tkt_etype, + &similar_enctype) != 0) + similar_enctype = FALSE; + + if (krb5_principal_compare(context, ent.principal, tkt_server)) { + found_tkt_server = TRUE; + if (ent.vno == tkt_kvno) { + found_kvno = TRUE; + if (similar_enctype) + found_enctype = TRUE; + } else if (ent.vno > tkt_kvno) { + found_higher_kvno = TRUE; + } + } + + /* Only try keys with similar enctypes to the ticket enctype. */ + if (similar_enctype) { + /* Coerce inexact matches to the request enctype. */ + ent.key.enctype = tkt_etype; + if (try_one_entry(context, req, &ent, keyblock_out) == 0) { + TRACE_RD_REQ_DECRYPT_ANY(context, ent.principal, &ent.key); + (void)krb5_free_keytab_entry_contents(context, &ent); + break; + } + } + + (void)krb5_free_keytab_entry_contents(context, &ent); + } + + (void)krb5_kt_end_seq_get(context, keytab, &cursor); + + if (ret != KRB5_KT_END) + return ret; + return iteration_error(context, server, tkt_server, tkt_kvno, tkt_etype, + tkt_server_mismatch, found_server_match, + found_tkt_server, found_kvno, found_higher_kvno, + found_enctype); +#endif /* LEAN_CLIENT */ +} + +static krb5_error_code +decrypt_ticket(krb5_context context, const krb5_ap_req *req, + krb5_const_principal server, krb5_keytab keytab, + krb5_keyblock *keyblock_out) +{ + krb5_error_code ret, dret = 0; + struct canonprinc iter = { server, .no_hostrealm = TRUE }; + krb5_const_principal canonprinc; + + /* Don't try to canonicalize if we're going to ignore hostnames. */ + if (k5_sname_wildcard_host(context, server)) + return decrypt_try_server(context, req, server, keytab, keyblock_out); + + /* Try each canonicalization candidate for server. If they all fail, + * return the error from the last attempt. */ + while ((ret = k5_canonprinc(context, &iter, &canonprinc)) == 0 && + canonprinc != NULL) { + dret = decrypt_try_server(context, req, canonprinc, keytab, + keyblock_out); + /* Only continue if we found no keytab entries matching canonprinc. */ + if (dret != KRB5KRB_AP_ERR_NOKEY) + break; + } + free_canonprinc(&iter); + return (ret != 0) ? ret : dret; +} + +static krb5_error_code +rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context, + const krb5_ap_req *req, krb5_const_principal server, + krb5_keytab keytab, krb5_flags *ap_req_options, + krb5_ticket **ticket, int check_valid_flag) +{ + krb5_error_code retval = 0; + krb5_enctype *desired_etypes = NULL; + int desired_etypes_len = 0; + int rfc4537_etypes_len = 0; + krb5_enctype *permitted_etypes = NULL; + int permitted_etypes_len = 0; + krb5_keyblock decrypt_key; + + decrypt_key.enctype = ENCTYPE_NULL; + decrypt_key.contents = NULL; + req->ticket->enc_part2 = NULL; + + /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY) + do we need special processing here ? */ + + /* decrypt the ticket */ + if ((*auth_context)->key) { /* User to User authentication */ + if ((retval = krb5_decrypt_tkt_part(context, + &(*auth_context)->key->keyblock, + req->ticket))) + goto cleanup; + if (check_valid_flag) { + decrypt_key = (*auth_context)->key->keyblock; + (*auth_context)->key->keyblock.contents = NULL; + } + krb5_k_free_key(context, (*auth_context)->key); + (*auth_context)->key = NULL; + if (server == NULL) + server = req->ticket->server; + } else { + retval = decrypt_ticket(context, req, server, keytab, + check_valid_flag ? &decrypt_key : NULL); + if (retval) { + TRACE_RD_REQ_DECRYPT_FAIL(context, retval); + goto cleanup; + } + /* decrypt_ticket placed the principal of the keytab key in + * req->ticket->server; always use this for later steps. */ + server = req->ticket->server; + } + TRACE_RD_REQ_TICKET(context, req->ticket->enc_part2->client, + req->ticket->server, req->ticket->enc_part2->session); + + /* XXX this is an evil hack. check_valid_flag is set iff the call + is not from inside the kdc. we can use this to determine which + key usage to use */ +#ifndef LEAN_CLIENT + if ((retval = decrypt_authenticator(context, req, + &((*auth_context)->authentp), + check_valid_flag))) + goto cleanup; +#endif + if (!krb5_principal_compare(context, (*auth_context)->authentp->client, + req->ticket->enc_part2->client)) { + retval = KRB5KRB_AP_ERR_BADMATCH; + goto cleanup; + } + + if ((*auth_context)->remote_addr && + !krb5_address_search(context, (*auth_context)->remote_addr, + req->ticket->enc_part2->caddrs)) { + retval = KRB5KRB_AP_ERR_BADADDR; + goto cleanup; + } + + /* Get an rcache if necessary. */ + if (((*auth_context)->rcache == NULL) && + ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME)) { + retval = k5_rc_default(context, &(*auth_context)->rcache); + if (retval) + goto cleanup; + } + /* okay, now check cross-realm policy */ + +#if defined(_SINGLE_HOP_ONLY) + + /* Single hop cross-realm tickets only */ + + { + krb5_transited *trans = &(req->ticket->enc_part2->transited); + + /* If the transited list is empty, then we have at most one hop */ + if (trans->tr_contents.length > 0 && trans->tr_contents.data[0]) + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + } + +#elif defined(_NO_CROSS_REALM) + + /* No cross-realm tickets */ + + { + char * lrealm; + krb5_data * realm; + krb5_transited * trans; + + realm = &req->ticket->enc_part2->client->realm; + trans = &(req->ticket->enc_part2->transited); + + /* + * If the transited list is empty, then we have at most one hop + * So we also have to check that the client's realm is the local one + */ + krb5_get_default_realm(context, &lrealm); + if ((trans->tr_contents.length > 0 && trans->tr_contents.data[0]) || + !data_eq_string(*realm, lrealm)) { + retval = KRB5KRB_AP_ERR_ILL_CR_TKT; + } + free(lrealm); + } + +#else + + /* Hierarchical Cross-Realm */ + + { + krb5_data * realm; + krb5_transited * trans; + krb5_flags flags; + + realm = &req->ticket->enc_part2->client->realm; + trans = &(req->ticket->enc_part2->transited); + flags = req->ticket->enc_part2->flags; + + /* + * If the transited list is not empty and the KDC hasn't checked it, + * then check that all realms transited are within the hierarchy + * between the client's realm and the local realm. + */ + if (!(flags & TKT_FLG_TRANSIT_POLICY_CHECKED) && + trans->tr_contents.length > 0 && trans->tr_contents.data[0]) { + retval = krb5_check_transited_list(context, &(trans->tr_contents), + realm, &server->realm); + } + } + +#endif + + if (retval) goto cleanup; + + /* only check rcache if sender has provided one---some services + may not be able to use replay caches (such as datagram servers) */ + + if ((*auth_context)->rcache != NULL) { + retval = k5_rc_store(context, (*auth_context)->rcache, + &req->authenticator); + if (retval) + goto cleanup; + } + + retval = krb5int_validate_times(context, &req->ticket->enc_part2->times); + if (retval != 0) + goto cleanup; + + if ((retval = krb5_check_clockskew(context, (*auth_context)->authentp->ctime))) + goto cleanup; + + if (check_valid_flag) { + if (req->ticket->enc_part2->flags & TKT_FLG_INVALID) { + retval = KRB5KRB_AP_ERR_TKT_INVALID; + goto cleanup; + } + + if ((retval = krb5_authdata_context_init(context, + &(*auth_context)->ad_context))) + goto cleanup; + if ((retval = krb5int_authdata_verify(context, + (*auth_context)->ad_context, + AD_USAGE_MASK, + auth_context, + &decrypt_key, + req))) + goto cleanup; + } + + /* read RFC 4537 etype list from sender */ + retval = decode_etype_list(context, + (*auth_context)->authentp, + &desired_etypes, + &rfc4537_etypes_len); + if (retval != 0) + goto cleanup; + + if (desired_etypes == NULL) + desired_etypes = (krb5_enctype *)calloc(4, sizeof(krb5_enctype)); + else + desired_etypes = (krb5_enctype *)realloc(desired_etypes, + (rfc4537_etypes_len + 4) * + sizeof(krb5_enctype)); + if (desired_etypes == NULL) { + retval = ENOMEM; + goto cleanup; + } + + desired_etypes_len = rfc4537_etypes_len; + + /* + * RFC 4537: + * + * If the EtypeList is present and the server prefers an enctype from + * the client's enctype list over that of the AP-REQ authenticator + * subkey (if that is present) or the service ticket session key, the + * server MUST create a subkey using that enctype. This negotiated + * subkey is sent in the subkey field of AP-REP message, and it is then + * used as the protocol key or base key [RFC3961] for subsequent + * communication. + * + * If the enctype of the ticket session key is included in the enctype + * list sent by the client, it SHOULD be the last on the list; + * otherwise, this enctype MUST NOT be negotiated if it was not included + * in the list. + * + * The second paragraph does appear to contradict the first with respect + * to whether it is legal to negotiate the ticket session key type if it + * is absent in the EtypeList. A literal reading suggests that we can use + * the AP-REQ subkey enctype. Also a client has no way of distinguishing + * a server that does not RFC 4537 from one that has chosen the same + * enctype as the ticket session key for the acceptor subkey, surely. + */ + + if ((*auth_context)->authentp->subkey != NULL) { + desired_etypes[desired_etypes_len++] = (*auth_context)->authentp->subkey->enctype; + } + desired_etypes[desired_etypes_len++] = req->ticket->enc_part2->session->enctype; + desired_etypes[desired_etypes_len] = ENCTYPE_NULL; + + if (((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_PERMIT_ALL) == 0) { + if ((*auth_context)->permitted_etypes != NULL) { + permitted_etypes = (*auth_context)->permitted_etypes; + } else { + retval = krb5_get_permitted_enctypes(context, &permitted_etypes); + if (retval != 0) + goto cleanup; + } + permitted_etypes_len = k5_count_etypes(permitted_etypes); + } else { + permitted_etypes = NULL; + permitted_etypes_len = 0; + } + + /* check if the various etypes are permitted */ + retval = negotiate_etype(context, + desired_etypes, desired_etypes_len, + rfc4537_etypes_len, + permitted_etypes, permitted_etypes_len, + &(*auth_context)->negotiated_etype); + if (retval != 0) + goto cleanup; + TRACE_RD_REQ_NEGOTIATED_ETYPE(context, (*auth_context)->negotiated_etype); + + assert((*auth_context)->negotiated_etype != ENCTYPE_NULL); + + (*auth_context)->remote_seq_number = (*auth_context)->authentp->seq_number; + if ((*auth_context)->authentp->subkey) { + TRACE_RD_REQ_SUBKEY(context, (*auth_context)->authentp->subkey); + if ((retval = krb5_k_create_key(context, + (*auth_context)->authentp->subkey, + &((*auth_context)->recv_subkey)))) + goto cleanup; + retval = krb5_k_create_key(context, (*auth_context)->authentp->subkey, + &((*auth_context)->send_subkey)); + if (retval) { + krb5_k_free_key(context, (*auth_context)->recv_subkey); + (*auth_context)->recv_subkey = NULL; + goto cleanup; + } + } else { + (*auth_context)->recv_subkey = 0; + (*auth_context)->send_subkey = 0; + } + + if ((retval = krb5_k_create_key(context, req->ticket->enc_part2->session, + &((*auth_context)->key)))) + goto cleanup; + + /* + * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used + * then the default sequence number is the one's complement of the + * sequence number sent ot us. + */ + if ((!(req->ap_options & AP_OPTS_MUTUAL_REQUIRED)) && + (*auth_context)->remote_seq_number) { + (*auth_context)->local_seq_number ^= + (*auth_context)->remote_seq_number; + } + + if (ticket) + if ((retval = krb5_copy_ticket(context, req->ticket, ticket))) + goto cleanup; + if (ap_req_options) { + *ap_req_options = req->ap_options & AP_OPTS_WIRE_MASK; + if (rfc4537_etypes_len != 0) + *ap_req_options |= AP_OPTS_ETYPE_NEGOTIATION; + if ((*auth_context)->negotiated_etype != + krb5_k_key_enctype(context, (*auth_context)->key)) + *ap_req_options |= AP_OPTS_USE_SUBKEY; + } + + retval = 0; + +cleanup: + if (desired_etypes != NULL) + free(desired_etypes); + if (permitted_etypes != NULL && + permitted_etypes != (*auth_context)->permitted_etypes) + free(permitted_etypes); + if (check_valid_flag) + krb5_free_keyblock_contents(context, &decrypt_key); + + return retval; +} + +krb5_error_code +krb5_rd_req_decoded(krb5_context context, krb5_auth_context *auth_context, + const krb5_ap_req *req, krb5_const_principal server, + krb5_keytab keytab, krb5_flags *ap_req_options, + krb5_ticket **ticket) +{ + krb5_error_code retval; + retval = rd_req_decoded_opt(context, auth_context, + req, server, keytab, + ap_req_options, ticket, + 1); /* check_valid_flag */ + return retval; +} + +krb5_error_code +krb5_rd_req_decoded_anyflag(krb5_context context, + krb5_auth_context *auth_context, + const krb5_ap_req *req, + krb5_const_principal server, krb5_keytab keytab, + krb5_flags *ap_req_options, krb5_ticket **ticket) +{ + krb5_error_code retval; + retval = rd_req_decoded_opt(context, auth_context, + req, server, keytab, + ap_req_options, ticket, + 0); /* don't check_valid_flag */ + return retval; +} + +#ifndef LEAN_CLIENT +static krb5_error_code +decrypt_authenticator(krb5_context context, const krb5_ap_req *request, + krb5_authenticator **authpp, int is_ap_req) +{ + krb5_authenticator *local_auth; + krb5_error_code retval; + krb5_data scratch; + krb5_keyblock *sesskey; + + sesskey = request->ticket->enc_part2->session; + + scratch.length = request->authenticator.ciphertext.length; + if (!(scratch.data = malloc(scratch.length))) + return(ENOMEM); + + if ((retval = krb5_c_decrypt(context, sesskey, + is_ap_req?KRB5_KEYUSAGE_AP_REQ_AUTH: + KRB5_KEYUSAGE_TGS_REQ_AUTH, 0, + &request->authenticator, &scratch))) { + free(scratch.data); + return(retval); + } + +#define clean_scratch() {memset(scratch.data, 0, scratch.length); \ + free(scratch.data);} + + /* now decode the decrypted stuff */ + if (!(retval = decode_krb5_authenticator(&scratch, &local_auth))) + *authpp = local_auth; + + clean_scratch(); + return retval; +} +#endif + +static krb5_error_code +negotiate_etype(krb5_context context, + const krb5_enctype *desired_etypes, + int desired_etypes_len, + int mandatory_etypes_index, + const krb5_enctype *permitted_etypes, + int permitted_etypes_len, + krb5_enctype *negotiated_etype) +{ + int i, j; + + *negotiated_etype = ENCTYPE_NULL; + + /* mandatory segment of desired_etypes must be permitted */ + for (i = mandatory_etypes_index; i < desired_etypes_len; i++) { + krb5_boolean permitted = FALSE; + + for (j = 0; j < permitted_etypes_len; j++) { + if (desired_etypes[i] == permitted_etypes[j]) { + permitted = TRUE; + break; + } + } + + if (permitted == FALSE) { + char enctype_name[30]; + + if (krb5_enctype_to_name(desired_etypes[i], FALSE, enctype_name, + sizeof(enctype_name)) == 0) + k5_setmsg(context, KRB5_NOPERM_ETYPE, + _("Encryption type %s not permitted"), enctype_name); + return KRB5_NOPERM_ETYPE; + } + } + + /* + * permitted_etypes is ordered from most to least preferred; + * find first desired_etype that matches. + */ + for (j = 0; j < permitted_etypes_len; j++) { + for (i = 0; i < desired_etypes_len; i++) { + if (desired_etypes[i] == permitted_etypes[j]) { + *negotiated_etype = permitted_etypes[j]; + return 0; + } + } + } + + /*NOTREACHED*/ + return KRB5_NOPERM_ETYPE; +} + +static krb5_error_code +decode_etype_list(krb5_context context, + const krb5_authenticator *authp, + krb5_enctype **desired_etypes, + int *desired_etypes_len) +{ + krb5_error_code code; + krb5_authdata **ad_if_relevant = NULL; + krb5_authdata *etype_adata = NULL; + krb5_etype_list *etype_list = NULL; + int i, j; + krb5_data data; + + *desired_etypes = NULL; + + if (authp->authorization_data == NULL) + return 0; + + /* + * RFC 4537 says that ETYPE_NEGOTIATION auth data should be wrapped + * in AD_IF_RELEVANT, but we handle the case where it is mandatory. + */ + for (i = 0; authp->authorization_data[i] != NULL; i++) { + switch (authp->authorization_data[i]->ad_type) { + case KRB5_AUTHDATA_IF_RELEVANT: + code = krb5_decode_authdata_container(context, + KRB5_AUTHDATA_IF_RELEVANT, + authp->authorization_data[i], + &ad_if_relevant); + if (code != 0) + continue; + + for (j = 0; ad_if_relevant[j] != NULL; j++) { + if (ad_if_relevant[j]->ad_type == KRB5_AUTHDATA_ETYPE_NEGOTIATION) { + etype_adata = ad_if_relevant[j]; + break; + } + } + if (etype_adata == NULL) { + krb5_free_authdata(context, ad_if_relevant); + ad_if_relevant = NULL; + } + break; + case KRB5_AUTHDATA_ETYPE_NEGOTIATION: + etype_adata = authp->authorization_data[i]; + break; + default: + break; + } + if (etype_adata != NULL) + break; + } + + if (etype_adata == NULL) + return 0; + + data.data = (char *)etype_adata->contents; + data.length = etype_adata->length; + + code = decode_krb5_etype_list(&data, &etype_list); + if (code == 0) { + *desired_etypes = etype_list->etypes; + *desired_etypes_len = etype_list->length; + free(etype_list); + } + + if (ad_if_relevant != NULL) + krb5_free_authdata(context, ad_if_relevant); + + return code; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/rd_safe.c b/krb5-1.21.3/src/lib/krb5/krb/rd_safe.c new file mode 100644 index 00000000..6e5c97aa --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/rd_safe.c @@ -0,0 +1,178 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/rd_safe.c - krb5_rd_safe() */ +/* + * Copyright 1990,1991,2007,2008,2019 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. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "auth_con.h" + +/* + * Unmarshal a KRB-SAFE message from der_krbsafe, placing the + * integrity-protected user data in *userdata_out, replay data in *rdata_out, + * and checksum in *cksum_out. The caller should free *userdata_out and + * *cksum_out when finished. + */ +static krb5_error_code +read_krbsafe(krb5_context context, krb5_auth_context ac, + const krb5_data *der_krbsafe, krb5_key key, + krb5_replay_data *rdata_out, krb5_data *userdata_out, + krb5_checksum **cksum_out) +{ + krb5_error_code ret; + krb5_safe *krbsafe; + krb5_data *safe_body = NULL, *der_zerosafe = NULL; + krb5_checksum zero_cksum, *safe_cksum = NULL; + krb5_octet zero_octet = 0; + krb5_boolean valid; + struct krb5_safe_with_body swb; + + *userdata_out = empty_data(); + *cksum_out = NULL; + if (!krb5_is_krb_safe(der_krbsafe)) + return KRB5KRB_AP_ERR_MSG_TYPE; + + ret = decode_krb5_safe_with_body(der_krbsafe, &krbsafe, &safe_body); + if (ret) + return ret; + + if (!krb5_c_valid_cksumtype(krbsafe->checksum->checksum_type)) { + ret = KRB5_PROG_SUMTYPE_NOSUPP; + goto cleanup; + } + if (!krb5_c_is_coll_proof_cksum(krbsafe->checksum->checksum_type) || + !krb5_c_is_keyed_cksum(krbsafe->checksum->checksum_type)) { + ret = KRB5KRB_AP_ERR_INAPP_CKSUM; + goto cleanup; + } + + ret = k5_privsafe_check_addrs(context, ac, krbsafe->s_address, + krbsafe->r_address); + if (ret) + goto cleanup; + + /* Regenerate the KRB-SAFE message without the checksum. Save the message + * checksum to verify. */ + safe_cksum = krbsafe->checksum; + zero_cksum.length = 0; + zero_cksum.checksum_type = 0; + zero_cksum.contents = &zero_octet; + krbsafe->checksum = &zero_cksum; + swb.body = safe_body; + swb.safe = krbsafe; + ret = encode_krb5_safe_with_body(&swb, &der_zerosafe); + krbsafe->checksum = NULL; + if (ret) + goto cleanup; + + /* Verify the checksum over the re-encoded message. */ + ret = krb5_k_verify_checksum(context, key, KRB5_KEYUSAGE_KRB_SAFE_CKSUM, + der_zerosafe, safe_cksum, &valid); + if (!valid) { + /* Checksum over only the KRB-SAFE-BODY as specified in RFC 1510. */ + ret = krb5_k_verify_checksum(context, key, + KRB5_KEYUSAGE_KRB_SAFE_CKSUM, + safe_body, safe_cksum, &valid); + if (!valid) { + ret = KRB5KRB_AP_ERR_MODIFIED; + goto cleanup; + } + } + + rdata_out->timestamp = krbsafe->timestamp; + rdata_out->usec = krbsafe->usec; + rdata_out->seq = krbsafe->seq_number; + + *userdata_out = krbsafe->user_data; + krbsafe->user_data.data = NULL; + + *cksum_out = safe_cksum; + safe_cksum = NULL; + +cleanup: + zapfreedata(der_zerosafe); + krb5_free_data(context, safe_body); + krb5_free_safe(context, krbsafe); + krb5_free_checksum(context, safe_cksum); + return ret; +} + +krb5_error_code KRB5_CALLCONV +krb5_rd_safe(krb5_context context, krb5_auth_context authcon, + const krb5_data *inbuf, krb5_data *userdata_out, + krb5_replay_data *rdata_out) +{ + krb5_error_code ret; + krb5_key key; + krb5_replay_data rdata; + krb5_data userdata = empty_data(); + krb5_checksum *cksum; + const krb5_int32 flags = authcon->auth_context_flags; + + *userdata_out = empty_data(); + + if (((flags & KRB5_AUTH_CONTEXT_RET_TIME) || + (flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && rdata_out == NULL) + return KRB5_RC_REQUIRED; + + key = (authcon->recv_subkey != NULL) ? authcon->recv_subkey : authcon->key; + memset(&rdata, 0, sizeof(rdata)); + ret = read_krbsafe(context, authcon, inbuf, key, &rdata, &userdata, + &cksum); + if (ret) + goto cleanup; + + ret = k5_privsafe_check_replay(context, authcon, &rdata, NULL, cksum); + if (ret) + goto cleanup; + + if (flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + if (!k5_privsafe_check_seqnum(context, authcon, rdata.seq)) { + ret = KRB5KRB_AP_ERR_BADORDER; + goto cleanup; + } + authcon->remote_seq_number++; + } + + if ((flags & KRB5_AUTH_CONTEXT_RET_TIME) || + (flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { + rdata_out->timestamp = rdata.timestamp; + rdata_out->usec = rdata.usec; + rdata_out->seq = rdata.seq; + } + + *userdata_out = userdata; + userdata = empty_data(); + +cleanup: + krb5_free_data_contents(context, &userdata); + krb5_free_checksum(context, cksum); + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/recvauth.c b/krb5-1.21.3/src/lib/krb5/krb/recvauth.c new file mode 100644 index 00000000..f784fa37 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/recvauth.c @@ -0,0 +1,240 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/recvauth.c */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * convenience sendauth/recvauth functions + */ + +#include "k5-int.h" +#include "auth_con.h" +#include "com_err.h" +#include +#include +#include + +static const char sendauth_version[] = "KRB5_SENDAUTH_V1.0"; + +static krb5_error_code +recvauth_common(krb5_context context, + krb5_auth_context * auth_context, + /* IN */ + krb5_pointer fd, + char *appl_version, + krb5_principal server, + krb5_int32 flags, + krb5_keytab keytab, + /* OUT */ + krb5_ticket ** ticket, + krb5_data *version) +{ + krb5_auth_context new_auth_context; + krb5_flags ap_option = 0; + krb5_error_code retval, problem; + krb5_data inbuf; + krb5_data outbuf; + krb5_rcache rcache = 0; + krb5_octet response; + krb5_data d; + int need_error_free = 0; + int local_rcache = 0, local_authcon = 0; + + /* + * Zero out problem variable. If problem is set at the end of + * the initial version negotiation section, it means that we + * need to send an error code back to the client application + * and exit. + */ + problem = 0; + response = 0; + + if (!(flags & KRB5_RECVAUTH_SKIP_VERSION)) { + /* + * First read the sendauth version string and check it. + */ + if ((retval = krb5_read_message(context, fd, &inbuf))) + return(retval); + d = make_data((char *)sendauth_version, strlen(sendauth_version) + 1); + if (!data_eq(inbuf, d)) { + problem = KRB5_SENDAUTH_BADAUTHVERS; + response = 1; + } + free(inbuf.data); + } + if (flags & KRB5_RECVAUTH_BADAUTHVERS) { + problem = KRB5_SENDAUTH_BADAUTHVERS; + response = 1; + } + + /* + * Do the same thing for the application version string. + */ + if ((retval = krb5_read_message(context, fd, &inbuf))) + return(retval); + if (appl_version != NULL && !problem) { + d = make_data(appl_version, strlen(appl_version) + 1); + if (!data_eq(inbuf, d)) { + problem = KRB5_SENDAUTH_BADAPPLVERS; + response = 2; + } + } + if (version && !problem) + *version = inbuf; + else + free(inbuf.data); + + /* + * Now we actually write the response. If the response is non-zero, + * exit with a return value of problem + */ + if ((krb5_net_write(context, *((int *)fd), (char *)&response, 1)) < 0) { + return(problem); /* We'll return the top-level problem */ + } + if (problem) + return(problem); + + /* We are clear of errors here */ + + /* + * Now, let's read the AP_REQ message and decode it + */ + if ((retval = krb5_read_message(context, fd, &inbuf))) + return retval; + + if (*auth_context == NULL) { + problem = krb5_auth_con_init(context, &new_auth_context); + *auth_context = new_auth_context; + local_authcon = 1; + } + krb5_auth_con_getrcache(context, *auth_context, &rcache); + if ((!problem) && rcache == NULL) { + problem = k5_rc_default(context, &rcache); + if (!problem) + problem = krb5_auth_con_setrcache(context, *auth_context, rcache); + local_rcache = 1; + } + if (!problem) { + problem = krb5_rd_req(context, auth_context, &inbuf, server, + keytab, &ap_option, ticket); + free(inbuf.data); + } + + /* + * If there was a problem, send back a krb5_error message, + * preceded by the length of the krb5_error message. If + * everything's ok, send back 0 for the length. + */ + if (problem) { + krb5_error error; + const char *message; + + memset(&error, 0, sizeof(error)); + krb5_us_timeofday(context, &error.stime, &error.susec); + if(server) + error.server = server; + else { + /* If this fails - ie. ENOMEM we are hosed + we cannot even send the error if we wanted to... */ + (void) krb5_parse_name(context, "????", &error.server); + need_error_free = 1; + } + + error.error = problem - ERROR_TABLE_BASE_krb5; + if (error.error > 127) + error.error = KRB_ERR_GENERIC; + message = error_message(problem); + error.text.length = strlen(message) + 1; + error.text.data = strdup(message); + if (!error.text.data) { + retval = ENOMEM; + goto cleanup; + } + if ((retval = krb5_mk_error(context, &error, &outbuf))) { + free(error.text.data); + goto cleanup; + } + free(error.text.data); + if(need_error_free) + krb5_free_principal(context, error.server); + + } else { + outbuf.length = 0; + outbuf.data = 0; + } + + retval = krb5_write_message(context, fd, &outbuf); + if (outbuf.data) { + free(outbuf.data); + /* We sent back an error, we need cleanup then return */ + retval = problem; + goto cleanup; + } + if (retval) + goto cleanup; + + /* Here lies the mutual authentication stuff... */ + if ((ap_option & AP_OPTS_MUTUAL_REQUIRED)) { + if ((retval = krb5_mk_rep(context, *auth_context, &outbuf))) { + return(retval); + } + retval = krb5_write_message(context, fd, &outbuf); + free(outbuf.data); + } + +cleanup:; + if (retval) { + if (local_authcon) { + krb5_auth_con_free(context, *auth_context); + } else if (local_rcache && rcache != NULL) { + k5_rc_close(context, rcache); + krb5_auth_con_setrcache(context, *auth_context, NULL); + } + } + return retval; +} + +krb5_error_code KRB5_CALLCONV +krb5_recvauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fd, char *appl_version, krb5_principal server, krb5_int32 flags, krb5_keytab keytab, krb5_ticket **ticket) +{ + return recvauth_common (context, auth_context, fd, appl_version, + server, flags, keytab, ticket, 0); +} + +krb5_error_code KRB5_CALLCONV +krb5_recvauth_version(krb5_context context, + krb5_auth_context *auth_context, + /* IN */ + krb5_pointer fd, + krb5_principal server, + krb5_int32 flags, + krb5_keytab keytab, + /* OUT */ + krb5_ticket **ticket, + krb5_data *version) +{ + return recvauth_common (context, auth_context, fd, 0, + server, flags, keytab, ticket, version); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/response_items.c b/krb5-1.21.3/src/lib/krb5/krb/response_items.c new file mode 100644 index 00000000..606d4f34 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/response_items.c @@ -0,0 +1,224 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/response_items.c - Response items */ +/* + * Copyright 2012 Red Hat, Inc. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Red Hat not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original Red Hat software. + * Red Hat makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" + +struct k5_response_items_st { + size_t count; + char **questions; + char **challenges; + char **answers; +}; + +krb5_error_code +k5_response_items_new(k5_response_items **ri_out) +{ + *ri_out = calloc(1, sizeof(**ri_out)); + return (*ri_out == NULL) ? ENOMEM : 0; +} + +void +k5_response_items_free(k5_response_items *ri) +{ + k5_response_items_reset(ri); + free(ri); +} + +void +k5_response_items_reset(k5_response_items *ri) +{ + size_t i; + + if (ri == NULL) + return; + + for (i = 0; i < ri->count; i++) + free(ri->questions[i]); + free(ri->questions); + ri->questions = NULL; + + for (i = 0; i < ri->count; i++) + zapfreestr(ri->challenges[i]); + free(ri->challenges); + ri->challenges = NULL; + + for (i = 0; i < ri->count; i++) + zapfreestr(ri->answers[i]); + free(ri->answers); + ri->answers = NULL; + + ri->count = 0; +} + +krb5_boolean +k5_response_items_empty(const k5_response_items *ri) +{ + return ri == NULL ? TRUE : ri->count == 0; +} + +const char * const * +k5_response_items_list_questions(const k5_response_items *ri) +{ + if (ri == NULL) + return NULL; + return (const char * const *)ri->questions; +} + +static ssize_t +find_question(const k5_response_items *ri, const char *question) +{ + size_t i; + + if (ri == NULL) + return -1; + + for (i = 0; i < ri->count; i++) { + if (strcmp(ri->questions[i], question) == 0) + return i; + } + + return -1; +} + +static krb5_error_code +push_question(k5_response_items *ri, const char *question, + const char *challenge) +{ + char **tmp; + size_t size; + + if (ri == NULL) + return EINVAL; + + size = sizeof(char *) * (ri->count + 2); + tmp = realloc(ri->questions, size); + if (tmp == NULL) + return ENOMEM; + ri->questions = tmp; + ri->questions[ri->count] = NULL; + ri->questions[ri->count + 1] = NULL; + + tmp = realloc(ri->challenges, size); + if (tmp == NULL) + return ENOMEM; + ri->challenges = tmp; + ri->challenges[ri->count] = NULL; + ri->challenges[ri->count + 1] = NULL; + + tmp = realloc(ri->answers, size); + if (tmp == NULL) + return ENOMEM; + ri->answers = tmp; + ri->answers[ri->count] = NULL; + ri->answers[ri->count + 1] = NULL; + + ri->questions[ri->count] = strdup(question); + if (ri->questions[ri->count] == NULL) + return ENOMEM; + + if (challenge != NULL) { + ri->challenges[ri->count] = strdup(challenge); + if (ri->challenges[ri->count] == NULL) { + free(ri->questions[ri->count]); + ri->questions[ri->count] = NULL; + return ENOMEM; + } + } + + ri->count++; + return 0; +} + +krb5_error_code +k5_response_items_ask_question(k5_response_items *ri, const char *question, + const char *challenge) +{ + ssize_t i; + char *tmp = NULL; + + i = find_question(ri, question); + if (i < 0) + return push_question(ri, question, challenge); + + if (challenge != NULL) { + tmp = strdup(challenge); + if (tmp == NULL) + return ENOMEM; + } + + zapfreestr(ri->challenges[i]); + ri->challenges[i] = tmp; + return 0; +} + +const char * +k5_response_items_get_challenge(const k5_response_items *ri, + const char *question) +{ + ssize_t i; + + i = find_question(ri, question); + if (i < 0) + return NULL; + + return ri->challenges[i]; +} + +krb5_error_code +k5_response_items_set_answer(k5_response_items *ri, const char *question, + const char *answer) +{ + char *tmp = NULL; + ssize_t i; + + i = find_question(ri, question); + if (i < 0) + return EINVAL; + + if (answer != NULL) { + tmp = strdup(answer); + if (tmp == NULL) + return ENOMEM; + } + + zapfreestr(ri->answers[i]); + ri->answers[i] = tmp; + return 0; +} + +const char * +k5_response_items_get_answer(const k5_response_items *ri, + const char *question) +{ + ssize_t i; + + i = find_question(ri, question); + if (i < 0) + return NULL; + + return ri->answers[i]; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/s4u_creds.c b/krb5-1.21.3/src/lib/krb5/krb/s4u_creds.c new file mode 100644 index 00000000..44d113e7 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/s4u_creds.c @@ -0,0 +1,1263 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/s4u_creds.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "os-proto.h" + +/* Convert ticket flags to necessary KDC options */ +#define FLAGS2OPTS(flags) (flags & KDC_TKT_COMMON_MASK) + +/* + * Implements S4U2Self, by which a service can request a ticket to + * itself on behalf of an arbitrary principal. + */ + +static krb5_error_code +s4u_identify_user(krb5_context context, + krb5_creds *in_creds, + krb5_data *subject_cert, + krb5_principal *canon_user) +{ + krb5_principal_data client; + krb5_data empty_name = empty_data(); + + *canon_user = NULL; + + if (in_creds->client == NULL && subject_cert == NULL) { + return EINVAL; + } + + if (in_creds->client != NULL && + in_creds->client->type != KRB5_NT_ENTERPRISE_PRINCIPAL) { + int anonymous; + + anonymous = krb5_principal_compare(context, in_creds->client, + krb5_anonymous_principal()); + + return krb5_copy_principal(context, + anonymous ? in_creds->server + : in_creds->client, + canon_user); + } + + if (in_creds->client != NULL) { + client = *in_creds->client; + client.realm = in_creds->server->realm; + + /* Don't send subject_cert if we have an enterprise principal. */ + return k5_identify_realm(context, &client, NULL, canon_user); + } + + client.magic = KV5M_PRINCIPAL; + client.realm = in_creds->server->realm; + + /* + * Windows clients send the certificate subject as the client name. + * However, Windows KDC seem to be happy with an empty string as long as + * the name-type is NT-X500-PRINCIPAL. + */ + client.data = &empty_name; + client.length = 1; + client.type = KRB5_NT_X500_PRINCIPAL; + + return k5_identify_realm(context, &client, subject_cert, canon_user); +} + +static krb5_error_code +make_pa_for_user_checksum(krb5_context context, + krb5_keyblock *key, + krb5_pa_for_user *req, + krb5_checksum *cksum) +{ + krb5_error_code code; + int i; + char *p; + krb5_data data; + + data.length = 4; + for (i = 0; i < req->user->length; i++) + data.length += req->user->data[i].length; + data.length += req->user->realm.length; + data.length += req->auth_package.length; + + p = data.data = malloc(data.length); + if (data.data == NULL) + return ENOMEM; + + p[0] = (req->user->type >> 0) & 0xFF; + p[1] = (req->user->type >> 8) & 0xFF; + p[2] = (req->user->type >> 16) & 0xFF; + p[3] = (req->user->type >> 24) & 0xFF; + p += 4; + + for (i = 0; i < req->user->length; i++) { + if (req->user->data[i].length > 0) + memcpy(p, req->user->data[i].data, req->user->data[i].length); + p += req->user->data[i].length; + } + + if (req->user->realm.length > 0) + memcpy(p, req->user->realm.data, req->user->realm.length); + p += req->user->realm.length; + + if (req->auth_package.length > 0) + memcpy(p, req->auth_package.data, req->auth_package.length); + + /* Per spec, use hmac-md5 checksum regardless of key type. */ + code = krb5_c_make_checksum(context, CKSUMTYPE_HMAC_MD5_ARCFOUR, key, + KRB5_KEYUSAGE_APP_DATA_CKSUM, &data, + cksum); + + free(data.data); + + return code; +} + +static krb5_error_code +build_pa_for_user(krb5_context context, + krb5_creds *tgt, + krb5_s4u_userid *userid, + krb5_pa_data **out_padata) +{ + krb5_error_code code; + krb5_pa_data *padata; + krb5_pa_for_user for_user; + krb5_data *for_user_data = NULL; + char package[] = "Kerberos"; + + if (userid->user == NULL) + return EINVAL; + + memset(&for_user, 0, sizeof(for_user)); + for_user.user = userid->user; + for_user.auth_package.data = package; + for_user.auth_package.length = sizeof(package) - 1; + + code = make_pa_for_user_checksum(context, &tgt->keyblock, + &for_user, &for_user.cksum); + if (code != 0) + goto cleanup; + + code = encode_krb5_pa_for_user(&for_user, &for_user_data); + if (code != 0) + goto cleanup; + + padata = malloc(sizeof(*padata)); + if (padata == NULL) { + code = ENOMEM; + goto cleanup; + } + + padata->magic = KV5M_PA_DATA; + padata->pa_type = KRB5_PADATA_FOR_USER; + padata->length = for_user_data->length; + padata->contents = (krb5_octet *)for_user_data->data; + + free(for_user_data); + for_user_data = NULL; + + *out_padata = padata; + +cleanup: + if (for_user.cksum.contents != NULL) + krb5_free_checksum_contents(context, &for_user.cksum); + krb5_free_data(context, for_user_data); + + return code; +} + +/* + * This function is invoked by krb5int_make_tgs_request_ext() just before the + * request is encoded; it gives us access to the nonce and subkey without + * requiring them to be generated by the caller. + */ +static krb5_error_code +build_pa_s4u_x509_user(krb5_context context, + krb5_keyblock *subkey, + krb5_kdc_req *tgsreq, + void *gcvt_data) +{ + krb5_error_code code; + krb5_pa_s4u_x509_user *s4u_user = (krb5_pa_s4u_x509_user *)gcvt_data; + krb5_data *data = NULL; + krb5_cksumtype cksumtype; + int i; + + assert(s4u_user->cksum.contents == NULL); + + s4u_user->user_id.nonce = tgsreq->nonce; + + code = encode_krb5_s4u_userid(&s4u_user->user_id, &data); + if (code != 0) + goto cleanup; + + /* [MS-SFU] 2.2.2: unusual to say the least, but enc_padata secures it */ + if (subkey->enctype == ENCTYPE_ARCFOUR_HMAC || + subkey->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { + cksumtype = CKSUMTYPE_RSA_MD4; + } else { + code = krb5int_c_mandatory_cksumtype(context, subkey->enctype, + &cksumtype); + } + if (code != 0) + goto cleanup; + + code = krb5_c_make_checksum(context, cksumtype, subkey, + KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST, data, + &s4u_user->cksum); + if (code != 0) + goto cleanup; + + krb5_free_data(context, data); + data = NULL; + + code = encode_krb5_pa_s4u_x509_user(s4u_user, &data); + if (code != 0) + goto cleanup; + + /* Find the empty PA-S4U-X509-USER element placed in the TGS request padata + * by krb5_get_self_cred_from_kdc() and replace it with the encoding. */ + assert(tgsreq->padata != NULL); + for (i = 0; tgsreq->padata[i] != NULL; i++) { + if (tgsreq->padata[i]->pa_type == KRB5_PADATA_S4U_X509_USER) + break; + } + assert(tgsreq->padata[i] != NULL); + free(tgsreq->padata[i]->contents); + tgsreq->padata[i]->length = data->length; + tgsreq->padata[i]->contents = (krb5_octet *)data->data; + free(data); + data = NULL; + +cleanup: + if (code != 0 && s4u_user->cksum.contents != NULL) { + krb5_free_checksum_contents(context, &s4u_user->cksum); + s4u_user->cksum.contents = NULL; + } + krb5_free_data(context, data); + + return code; +} + +/* + * Validate the S4U2Self padata in the KDC reply. If update_req_user is true + * and the KDC sent S4U-X509-USER padata, replace req_s4u_user->user_id.user + * with the checksum-protected client name from the KDC. If update_req_user is + * false, verify that the client name has not changed. + */ +static krb5_error_code +verify_s4u2self_reply(krb5_context context, + krb5_keyblock *subkey, + krb5_pa_s4u_x509_user *req_s4u_user, + krb5_pa_data **rep_padata, + krb5_pa_data **enc_padata, + krb5_boolean update_req_user) +{ + krb5_error_code code; + krb5_pa_data *rep_s4u_padata, *enc_s4u_padata; + krb5_pa_s4u_x509_user *rep_s4u_user = NULL; + krb5_data data, *datap = NULL; + krb5_keyusage usage; + krb5_boolean valid; + krb5_boolean not_newer; + + assert(req_s4u_user != NULL); + + switch (subkey->enctype) { + case ENCTYPE_DES3_CBC_SHA1: + case ENCTYPE_DES3_CBC_RAW: + case ENCTYPE_ARCFOUR_HMAC: + case ENCTYPE_ARCFOUR_HMAC_EXP : + not_newer = TRUE; + break; + default: + not_newer = FALSE; + break; + } + + enc_s4u_padata = krb5int_find_pa_data(context, + enc_padata, + KRB5_PADATA_S4U_X509_USER); + + rep_s4u_padata = krb5int_find_pa_data(context, + rep_padata, + KRB5_PADATA_S4U_X509_USER); + if (rep_s4u_padata == NULL) + return (enc_s4u_padata != NULL) ? KRB5_KDCREP_MODIFIED : 0; + + data.length = rep_s4u_padata->length; + data.data = (char *)rep_s4u_padata->contents; + + code = decode_krb5_pa_s4u_x509_user(&data, &rep_s4u_user); + if (code != 0) + goto cleanup; + + if (rep_s4u_user->user_id.nonce != req_s4u_user->user_id.nonce) { + code = KRB5_KDCREP_MODIFIED; + goto cleanup; + } + + code = encode_krb5_s4u_userid(&rep_s4u_user->user_id, &datap); + if (code != 0) + goto cleanup; + + if (rep_s4u_user->user_id.options & KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE) + usage = KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY; + else + usage = KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST; + + code = krb5_c_verify_checksum(context, subkey, usage, datap, + &rep_s4u_user->cksum, &valid); + if (code != 0) + goto cleanup; + if (valid == FALSE) { + code = KRB5_KDCREP_MODIFIED; + goto cleanup; + } + + if (rep_s4u_user->user_id.user == NULL || + rep_s4u_user->user_id.user->length == 0) { + code = KRB5_KDCREP_MODIFIED; + goto cleanup; + } + + if (update_req_user) { + krb5_free_principal(context, req_s4u_user->user_id.user); + code = krb5_copy_principal(context, rep_s4u_user->user_id.user, + &req_s4u_user->user_id.user); + if (code != 0) + goto cleanup; + } else if (!krb5_principal_compare(context, rep_s4u_user->user_id.user, + req_s4u_user->user_id.user)) { + code = KRB5_KDCREP_MODIFIED; + goto cleanup; + } + + /* + * KDCs that support KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE also return + * S4U enc_padata for older (pre-AES) encryption types only. + */ + if (not_newer) { + if (enc_s4u_padata == NULL) { + if (rep_s4u_user->user_id.options & + KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE) { + code = KRB5_KDCREP_MODIFIED; + goto cleanup; + } + } else { + if (enc_s4u_padata->length != + req_s4u_user->cksum.length + rep_s4u_user->cksum.length) { + code = KRB5_KDCREP_MODIFIED; + goto cleanup; + } + if (memcmp(enc_s4u_padata->contents, + req_s4u_user->cksum.contents, + req_s4u_user->cksum.length) || + memcmp(&enc_s4u_padata->contents[req_s4u_user->cksum.length], + rep_s4u_user->cksum.contents, + rep_s4u_user->cksum.length)) { + code = KRB5_KDCREP_MODIFIED; + goto cleanup; + } + } + } else if (!krb5_c_is_keyed_cksum(rep_s4u_user->cksum.checksum_type)) { + code = KRB5KRB_AP_ERR_INAPP_CKSUM; + goto cleanup; + } + +cleanup: + krb5_free_pa_s4u_x509_user(context, rep_s4u_user); + krb5_free_data(context, datap); + + return code; +} + +/* Unparse princ and re-parse it as an enterprise principal. */ +static krb5_error_code +convert_to_enterprise(krb5_context context, krb5_principal princ, + krb5_principal *eprinc_out) +{ + krb5_error_code code; + char *str; + + *eprinc_out = NULL; + code = krb5_unparse_name(context, princ, &str); + if (code != 0) + return code; + code = krb5_parse_name_flags(context, str, + KRB5_PRINCIPAL_PARSE_ENTERPRISE | + KRB5_PRINCIPAL_PARSE_IGNORE_REALM, + eprinc_out); + krb5_free_unparsed_name(context, str); + return code; +} + +static krb5_error_code +krb5_get_self_cred_from_kdc(krb5_context context, + krb5_flags options, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_data *subject_cert, + krb5_data *user_realm, + krb5_creds **out_creds) +{ + krb5_error_code code; + krb5_principal tgs = NULL, eprinc = NULL; + krb5_principal_data sprinc; + krb5_creds tgtq, s4u_creds, *tgt = NULL, *tgtptr; + krb5_creds *referral_tgts[KRB5_REFERRAL_MAXHOPS]; + krb5_pa_s4u_x509_user s4u_user; + int referral_count = 0, i; + krb5_flags kdcopt; + + memset(&tgtq, 0, sizeof(tgtq)); + memset(referral_tgts, 0, sizeof(referral_tgts)); + *out_creds = NULL; + + memset(&s4u_user, 0, sizeof(s4u_user)); + + if (in_creds->client != NULL && in_creds->client->length > 0) { + if (in_creds->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL) { + code = krb5_build_principal_ext(context, + &s4u_user.user_id.user, + user_realm->length, + user_realm->data, + in_creds->client->data[0].length, + in_creds->client->data[0].data, + 0); + if (code != 0) + goto cleanup; + s4u_user.user_id.user->type = KRB5_NT_ENTERPRISE_PRINCIPAL; + } else { + code = krb5_copy_principal(context, + in_creds->client, + &s4u_user.user_id.user); + if (code != 0) + goto cleanup; + } + } else { + code = krb5_build_principal_ext(context, &s4u_user.user_id.user, + user_realm->length, user_realm->data, + 0); + if (code != 0) + goto cleanup; + } + if (subject_cert != NULL) + s4u_user.user_id.subject_cert = *subject_cert; + s4u_user.user_id.options = KRB5_S4U_OPTS_USE_REPLY_KEY_USAGE; + + /* First, acquire a TGT to the user's realm. */ + code = krb5int_tgtname(context, user_realm, &in_creds->server->realm, + &tgs); + if (code != 0) + goto cleanup; + + tgtq.client = in_creds->server; + tgtq.server = tgs; + + code = krb5_get_credentials(context, options, ccache, &tgtq, &tgt); + if (code != 0) + goto cleanup; + + tgtptr = tgt; + + /* Convert the server principal to an enterprise principal, for use with + * foreign realms. */ + code = convert_to_enterprise(context, in_creds->server, &eprinc); + if (code != 0) + goto cleanup; + + /* Make a shallow copy of in_creds with client pointing to the server + * principal. We will set s4u_creds.server for each request. */ + s4u_creds = *in_creds; + s4u_creds.client = in_creds->server; + + /* Then, walk back the referral path to S4U2Self for user */ + kdcopt = 0; + if (options & KRB5_GC_CANONICALIZE) + kdcopt |= KDC_OPT_CANONICALIZE; + if (options & KRB5_GC_FORWARDABLE) + kdcopt |= KDC_OPT_FORWARDABLE; + if (options & KRB5_GC_NO_TRANSIT_CHECK) + kdcopt |= KDC_OPT_DISABLE_TRANSITED_CHECK; + + for (referral_count = 0; + referral_count < KRB5_REFERRAL_MAXHOPS; + referral_count++) + { + krb5_pa_data **in_padata = NULL; + krb5_pa_data **out_padata = NULL; + krb5_pa_data **enc_padata = NULL; + krb5_keyblock *subkey = NULL; + + in_padata = k5calloc(3, sizeof(krb5_pa_data *), &code); + if (in_padata == NULL) + goto cleanup; + + in_padata[0] = k5alloc(sizeof(krb5_pa_data), &code); + if (in_padata[0] == NULL) { + krb5_free_pa_data(context, in_padata); + goto cleanup; + } + + in_padata[0]->magic = KV5M_PA_DATA; + in_padata[0]->pa_type = KRB5_PADATA_S4U_X509_USER; + in_padata[0]->length = 0; + in_padata[0]->contents = NULL; + + if (s4u_user.user_id.user != NULL && s4u_user.user_id.user->length) { + code = build_pa_for_user(context, tgtptr, &s4u_user.user_id, + &in_padata[1]); + /* + * If we couldn't compute the hmac-md5 checksum, send only the + * KRB5_PADATA_S4U_X509_USER; this will still work against modern + * Windows and MIT KDCs. + */ + if (code == KRB5_CRYPTO_INTERNAL) + code = 0; + if (code != 0) { + krb5_free_pa_data(context, in_padata); + goto cleanup; + } + } + + if (data_eq(tgtptr->server->data[1], in_creds->server->realm)) { + /* When asking the server realm, use the real principal. */ + s4u_creds.server = in_creds->server; + } else { + /* When asking a foreign realm, use the enterprise principal, with + * the realm set to the TGS realm. */ + sprinc = *eprinc; + sprinc.realm = tgtptr->server->data[1]; + s4u_creds.server = &sprinc; + } + + code = krb5_get_cred_via_tkt_ext(context, tgtptr, + KDC_OPT_CANONICALIZE | + FLAGS2OPTS(tgtptr->ticket_flags) | + kdcopt, + tgtptr->addresses, + in_padata, &s4u_creds, + build_pa_s4u_x509_user, &s4u_user, + &out_padata, &enc_padata, + out_creds, &subkey); + if (code != 0) { + krb5_free_checksum_contents(context, &s4u_user.cksum); + krb5_free_pa_data(context, in_padata); + goto cleanup; + } + + /* Update s4u_user.user_id.user if this is the initial request to the + * client realm; otherwise verify that it doesn't change. */ + code = verify_s4u2self_reply(context, subkey, &s4u_user, out_padata, + enc_padata, referral_count == 0); + + krb5_free_checksum_contents(context, &s4u_user.cksum); + krb5_free_pa_data(context, in_padata); + krb5_free_pa_data(context, out_padata); + krb5_free_pa_data(context, enc_padata); + krb5_free_keyblock(context, subkey); + + if (code != 0) + goto cleanup; + + /* The authdata in this referral TGT will be copied into the final + * credentials, so we don't need to request it again. */ + s4u_creds.authdata = NULL; + + /* Only include a cert in the initial request to the client realm. */ + s4u_user.user_id.subject_cert = empty_data(); + + if (krb5_principal_compare_any_realm(context, in_creds->server, + (*out_creds)->server)) { + /* Verify that the unprotected client name in the reply matches the + * checksum-protected one from the client realm's KDC padata. */ + if (!krb5_principal_compare(context, (*out_creds)->client, + s4u_user.user_id.user)) + code = KRB5_KDCREP_MODIFIED; + goto cleanup; + } else if (IS_TGS_PRINC((*out_creds)->server)) { + krb5_data *r1 = &tgtptr->server->data[1]; + krb5_data *r2 = &(*out_creds)->server->data[1]; + + if (data_eq(*r1, *r2)) { + krb5_free_creds(context, *out_creds); + *out_creds = NULL; + code = KRB5_ERR_HOST_REALM_UNKNOWN; + break; + } + for (i = 0; i < referral_count; i++) { + if (krb5_principal_compare(context, + (*out_creds)->server, + referral_tgts[i]->server)) { + code = KRB5_KDC_UNREACH; + goto cleanup; + } + } + + tgtptr = *out_creds; + referral_tgts[referral_count] = *out_creds; + *out_creds = NULL; + } else { + krb5_free_creds(context, *out_creds); + *out_creds = NULL; + code = KRB5KRB_AP_WRONG_PRINC; /* XXX */ + break; + } + } + +cleanup: + for (i = 0; i < KRB5_REFERRAL_MAXHOPS; i++) { + if (referral_tgts[i] != NULL) + krb5_free_creds(context, referral_tgts[i]); + } + krb5_free_principal(context, tgs); + krb5_free_principal(context, eprinc); + krb5_free_creds(context, tgt); + krb5_free_principal(context, s4u_user.user_id.user); + krb5_free_checksum_contents(context, &s4u_user.cksum); + + return code; +} + +krb5_error_code KRB5_CALLCONV +krb5_get_credentials_for_user(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_data *subject_cert, + krb5_creds **out_creds) +{ + krb5_error_code code; + krb5_principal realm = NULL; + + *out_creds = NULL; + + if (options & KRB5_GC_CONSTRAINED_DELEGATION) { + code = EINVAL; + goto cleanup; + } + + if (in_creds->client != NULL) { + /* Uncanonicalised check */ + code = krb5_get_credentials(context, options | KRB5_GC_CACHED, + ccache, in_creds, out_creds); + if ((code != KRB5_CC_NOTFOUND && code != KRB5_CC_NOT_KTYPE) || + (options & KRB5_GC_CACHED)) + goto cleanup; + } else if (options & KRB5_GC_CACHED) { + /* Fail immediately, since we can't check the cache by certificate. */ + code = KRB5_CC_NOTFOUND; + goto cleanup; + } + + code = s4u_identify_user(context, in_creds, subject_cert, &realm); + if (code != 0) + goto cleanup; + + if (in_creds->client != NULL && + in_creds->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL) { + /* Post-canonicalisation check for enterprise principals */ + krb5_creds mcreds = *in_creds; + mcreds.client = realm; + code = krb5_get_credentials(context, options | KRB5_GC_CACHED, + ccache, &mcreds, out_creds); + if (code != KRB5_CC_NOTFOUND && code != KRB5_CC_NOT_KTYPE) + goto cleanup; + } + + code = krb5_get_self_cred_from_kdc(context, options, ccache, in_creds, + subject_cert, &realm->realm, out_creds); + if (code != 0) + goto cleanup; + + assert(*out_creds != NULL); + + /* If we canonicalized the client name or discovered it using subject_cert, + * check if we had cached credentials and return them if found. */ + if (in_creds->client == NULL || + !krb5_principal_compare(context, in_creds->client, + (*out_creds)->client)) { + krb5_creds *old_creds; + krb5_creds mcreds = *in_creds; + mcreds.client = (*out_creds)->client; + code = krb5_get_credentials(context, options | KRB5_GC_CACHED, ccache, + &mcreds, &old_creds); + if (code == 0) { + krb5_free_creds(context, *out_creds); + *out_creds = old_creds; + options |= KRB5_GC_NO_STORE; + } else if (code != KRB5_CC_NOTFOUND && code != KRB5_CC_NOT_KTYPE) { + goto cleanup; + } + } + + /* Note the authdata we asked for in the output creds. */ + code = krb5_copy_authdata(context, in_creds->authdata, + &(*out_creds)->authdata); + if (code) + goto cleanup; + + if ((options & KRB5_GC_NO_STORE) == 0) { + code = krb5_cc_store_cred(context, ccache, *out_creds); + if (code != 0) + goto cleanup; + } + +cleanup: + if (code != 0 && *out_creds != NULL) { + krb5_free_creds(context, *out_creds); + *out_creds = NULL; + } + + krb5_free_principal(context, realm); + + return code; +} + +static krb5_error_code +check_rbcd_support(krb5_context context, krb5_pa_data **padata) +{ + krb5_error_code code; + krb5_pa_data *pa; + krb5_pa_pac_options *pac_options; + krb5_data der_pac_options; + + pa = krb5int_find_pa_data(context, padata, KRB5_PADATA_PAC_OPTIONS); + if (pa == NULL) + return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; + + der_pac_options = make_data(pa->contents, pa->length); + code = decode_krb5_pa_pac_options(&der_pac_options, &pac_options); + if (code) + return code; + + if (!(pac_options->options & KRB5_PA_PAC_OPTIONS_RBCD)) + code = KRB5KDC_ERR_PADATA_TYPE_NOSUPP; + + free(pac_options); + return code; +} + +static krb5_error_code +add_rbcd_padata(krb5_context context, krb5_pa_data ***in_padata) +{ + krb5_error_code code; + krb5_pa_pac_options pac_options; + krb5_data *der_pac_options = NULL; + + memset(&pac_options, 0, sizeof(pac_options)); + pac_options.options |= KRB5_PA_PAC_OPTIONS_RBCD; + + code = encode_krb5_pa_pac_options(&pac_options, &der_pac_options); + if (code) + return code; + + code = k5_add_pa_data_from_data(in_padata, KRB5_PADATA_PAC_OPTIONS, + der_pac_options); + krb5_free_data(context, der_pac_options); + return code; +} + +/* Set *tgt_out to a local TGT for the client realm retrieved from ccache. */ +static krb5_error_code +get_client_tgt(krb5_context context, krb5_flags options, krb5_ccache ccache, + krb5_principal client, krb5_creds **tgt_out) +{ + krb5_error_code code; + krb5_principal tgs; + krb5_creds mcreds; + + *tgt_out = NULL; + + code = krb5int_tgtname(context, &client->realm, &client->realm, &tgs); + if (code) + return code; + + memset(&mcreds, 0, sizeof(mcreds)); + mcreds.client = client; + mcreds.server = tgs; + code = krb5_get_credentials(context, options, ccache, &mcreds, tgt_out); + krb5_free_principal(context, tgs); + return code; +} + +/* + * Copy req_server to *out_server. If req_server has the referral realm, set + * the realm of *out_server to realm. Otherwise the S4U2Proxy request will + * fail unless the specified realm is the same as the TGT (or an alias to it). + */ +static krb5_error_code +normalize_server_princ(krb5_context context, const krb5_data *realm, + krb5_principal req_server, krb5_principal *out_server) +{ + krb5_error_code code; + krb5_principal server; + + *out_server = NULL; + + code = krb5_copy_principal(context, req_server, &server); + if (code) + return code; + + if (krb5_is_referral_realm(&server->realm)) { + krb5_free_data_contents(context, &server->realm); + code = krb5int_copy_data_contents(context, realm, &server->realm); + if (code) { + krb5_free_principal(context, server); + return code; + } + } + + *out_server = server; + return 0; +} + +/* Return an error if server is present in referral_list. */ +static krb5_error_code +check_referral_path(krb5_context context, krb5_principal server, + krb5_creds **referral_list, int referral_count) +{ + int i; + + for (i = 0; i < referral_count; i++) { + if (krb5_principal_compare(context, server, referral_list[i]->server)) + return KRB5_KDC_UNREACH; + } + return 0; +} + +/* + * Make TGS requests for in_creds using *tgt_inout, following referrals until + * the requested service ticket is issued. Replace *tgt_inout with the final + * TGT used, or free it and set it to NULL on error. Place the final creds + * received in *creds_out. + */ +static krb5_error_code +chase_referrals(krb5_context context, krb5_creds *in_creds, krb5_flags kdcopt, + krb5_creds **tgt_inout, krb5_creds **creds_out) +{ + krb5_error_code code; + krb5_creds *referral_tgts[KRB5_REFERRAL_MAXHOPS] = { NULL }; + krb5_creds mcreds, *tgt, *tkt = NULL; + krb5_principal_data server; + int referral_count = 0, i; + + tgt = *tgt_inout; + *tgt_inout = NULL; + *creds_out = NULL; + + mcreds = *in_creds; + server = *in_creds->server; + mcreds.server = &server; + + for (referral_count = 0; referral_count < KRB5_REFERRAL_MAXHOPS; + referral_count++) { + code = krb5_get_cred_via_tkt(context, tgt, kdcopt, tgt->addresses, + &mcreds, &tkt); + if (code) + goto cleanup; + + if (krb5_principal_compare_any_realm(context, mcreds.server, + tkt->server)) { + *creds_out = tkt; + *tgt_inout = tgt; + tkt = tgt = NULL; + goto cleanup; + } + + if (!IS_TGS_PRINC(tkt->server)) { + code = KRB5KRB_AP_WRONG_PRINC; + goto cleanup; + } + + if (data_eq(tgt->server->data[1], tkt->server->data[1])) { + code = KRB5_ERR_HOST_REALM_UNKNOWN; + goto cleanup; + } + + code = check_referral_path(context, tkt->server, referral_tgts, + referral_count); + if (code) + goto cleanup; + + referral_tgts[referral_count] = tgt; + tgt = tkt; + tkt = NULL; + server.realm = tgt->server->data[1]; + } + + /* Max hop count exceeded. */ + code = KRB5_KDCREP_MODIFIED; + +cleanup: + for (i = 0; i < KRB5_REFERRAL_MAXHOPS; i++) + krb5_free_creds(context, referral_tgts[i]); + krb5_free_creds(context, tkt); + krb5_free_creds(context, tgt); + return code; +} + +/* + * Make non-S4U2Proxy TGS requests for in_creds using *tgt_inout, following + * referrals until the requested service ticket is returned. Discard the + * service ticket, but replace *tgt_inout with the final referral TGT. + */ +static krb5_error_code +get_tgt_to_target_realm(krb5_context context, krb5_creds *in_creds, + krb5_flags req_kdcopt, krb5_creds **tgt_inout) +{ + krb5_error_code code; + krb5_flags kdcopt; + krb5_creds mcreds, *out; + + mcreds = *in_creds; + mcreds.second_ticket = empty_data(); + kdcopt = FLAGS2OPTS((*tgt_inout)->ticket_flags) | req_kdcopt; + + code = chase_referrals(context, &mcreds, kdcopt, tgt_inout, &out); + krb5_free_creds(context, out); + + return code; +} + +/* + * Make TGS requests for a cross-TGT to realm using *tgt_inout, following + * alternate TGS replies until the requested TGT is issued. Replace *tgt_inout + * with the result. Do nothing if *tgt_inout is already a cross-TGT for realm. + */ +static krb5_error_code +get_target_realm_proxy_tgt(krb5_context context, const krb5_data *realm, + krb5_flags req_kdcopt, krb5_creds **tgt_inout) +{ + krb5_error_code code; + krb5_creds mcreds, *out; + krb5_principal tgs; + krb5_flags flags; + + if (data_eq(*realm, (*tgt_inout)->server->data[1])) + return 0; + + code = krb5int_tgtname(context, realm, &(*tgt_inout)->server->data[1], + &tgs); + if (code) + return code; + + memset(&mcreds, 0, sizeof(mcreds)); + mcreds.client = (*tgt_inout)->client; + mcreds.server = tgs; + flags = req_kdcopt | FLAGS2OPTS((*tgt_inout)->ticket_flags); + + code = chase_referrals(context, &mcreds, flags, tgt_inout, &out); + krb5_free_principal(context, tgs); + if (code) + return code; + + krb5_free_creds(context, *tgt_inout); + *tgt_inout = out; + + return 0; +} + +static krb5_error_code +get_proxy_cred_from_kdc(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_creds **out_creds) +{ + krb5_error_code code; + krb5_flags flags, req_kdcopt = 0; + krb5_principal server = NULL; + krb5_pa_data **in_padata = NULL; + krb5_pa_data **enc_padata = NULL; + krb5_creds mcreds, *tgt = NULL, *tkt = NULL; + + *out_creds = NULL; + + if (in_creds->second_ticket.length == 0 || + (options & KRB5_GC_CONSTRAINED_DELEGATION) == 0) + return EINVAL; + + options &= ~KRB5_GC_CONSTRAINED_DELEGATION; + + code = get_client_tgt(context, options, ccache, in_creds->client, &tgt); + if (code) + goto cleanup; + + code = normalize_server_princ(context, &in_creds->client->realm, + in_creds->server, &server); + if (code) + goto cleanup; + + code = add_rbcd_padata(context, &in_padata); + if (code) + goto cleanup; + + if (options & KRB5_GC_CANONICALIZE) + req_kdcopt |= KDC_OPT_CANONICALIZE; + if (options & KRB5_GC_FORWARDABLE) + req_kdcopt |= KDC_OPT_FORWARDABLE; + if (options & KRB5_GC_NO_TRANSIT_CHECK) + req_kdcopt |= KDC_OPT_DISABLE_TRANSITED_CHECK; + + mcreds = *in_creds; + mcreds.server = server; + + flags = req_kdcopt | FLAGS2OPTS(tgt->ticket_flags) | + KDC_OPT_CNAME_IN_ADDL_TKT | KDC_OPT_CANONICALIZE; + code = krb5_get_cred_via_tkt_ext(context, tgt, flags, tgt->addresses, + in_padata, &mcreds, NULL, NULL, NULL, + &enc_padata, &tkt, NULL); + + /* + * If the server principal name included a foreign realm which wasn't an + * alias for the local realm, the KDC won't be able to decrypt the TGT. + * Windows KDCs will return a BAD_INTEGRITY error in this case, while MIT + * KDCs will return S_PRINCIPAL_UNKNOWN. We cannot distinguish the latter + * error from the service principal actually being unknown in the realm, + * but set a comprehensible error message for the BAD_INTEGRITY error. + */ + if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY && + !krb5_realm_compare(context, in_creds->client, server)) { + k5_setmsg(context, code, _("Realm specified but S4U2Proxy must use " + "referral realm")); + } + + if (code) + goto cleanup; + + if (!krb5_principal_compare_any_realm(context, server, tkt->server)) { + /* Make sure we got a referral. */ + if (!IS_TGS_PRINC(tkt->server)) { + code = KRB5KRB_AP_WRONG_PRINC; + goto cleanup; + } + + /* The authdata in this referral TGT will be copied into the final + * credentials, so we don't need to request it again. */ + mcreds.authdata = NULL; + + /* + * Make sure the KDC supports S4U and resource-based constrained + * delegation; otherwise we might have gotten a regular TGT referral + * rather than a proxy TGT referral. + */ + code = check_rbcd_support(context, enc_padata); + if (code) + goto cleanup; + + krb5_free_pa_data(context, enc_padata); + enc_padata = NULL; + + /* + * Replace tgt with a regular (not proxy) TGT to the target realm, by + * making a normal TGS request and following referrals. Per [MS-SFU] + * 3.1.5.2.2, we need this TGT to make the final TGS request. + */ + code = get_tgt_to_target_realm(context, &mcreds, req_kdcopt, &tgt); + if (code) + goto cleanup; + + /* + * Replace tkt with a proxy TGT (meaning, one obtained using the + * referral TGT we got from the first S4U2Proxy request) to the target + * realm, if it isn't already one. + */ + code = get_target_realm_proxy_tgt(context, &tgt->server->data[1], + req_kdcopt, &tkt); + if (code) + goto cleanup; + + krb5_free_data_contents(context, &server->realm); + code = krb5int_copy_data_contents(context, &tgt->server->data[1], + &server->realm); + if (code) + goto cleanup; + + /* Make an S4U2Proxy request to the target realm using the regular TGT, + * with the proxy TGT as the evidence ticket. */ + mcreds.second_ticket = tkt->ticket; + tkt->ticket = empty_data(); + krb5_free_creds(context, tkt); + tkt = NULL; + flags = req_kdcopt | FLAGS2OPTS(tgt->ticket_flags) | + KDC_OPT_CNAME_IN_ADDL_TKT | KDC_OPT_CANONICALIZE; + code = krb5_get_cred_via_tkt_ext(context, tgt, flags, tgt->addresses, + in_padata, &mcreds, NULL, NULL, NULL, + &enc_padata, &tkt, NULL); + free(mcreds.second_ticket.data); + if (code) + goto cleanup; + + code = check_rbcd_support(context, enc_padata); + if (code) + goto cleanup; + + if (!krb5_principal_compare(context, server, tkt->server)) { + code = KRB5KRB_AP_WRONG_PRINC; + goto cleanup; + } + + /* Put the original evidence ticket in the output creds. */ + krb5_free_data_contents(context, &tkt->second_ticket); + code = krb5int_copy_data_contents(context, &in_creds->second_ticket, + &tkt->second_ticket); + if (code) + goto cleanup; + } + + /* Note the authdata we asked for in the output creds. */ + code = krb5_copy_authdata(context, in_creds->authdata, &tkt->authdata); + if (code) + goto cleanup; + + *out_creds = tkt; + tkt = NULL; + +cleanup: + krb5_free_creds(context, tgt); + krb5_free_creds(context, tkt); + krb5_free_principal(context, server); + krb5_free_pa_data(context, in_padata); + krb5_free_pa_data(context, enc_padata); + return code; +} + +krb5_error_code +k5_get_proxy_cred_from_kdc(krb5_context context, krb5_flags options, + krb5_ccache ccache, krb5_creds *in_creds, + krb5_creds **out_creds) +{ + krb5_error_code code; + krb5_const_principal canonprinc; + krb5_creds copy, *creds; + struct canonprinc iter = { in_creds->server, .no_hostrealm = TRUE }; + + *out_creds = NULL; + + code = k5_get_cached_cred(context, options, ccache, in_creds, out_creds); + if ((code != KRB5_CC_NOTFOUND && code != KRB5_CC_NOT_KTYPE) || + options & KRB5_GC_CACHED) + return code; + + copy = *in_creds; + while ((code = k5_canonprinc(context, &iter, &canonprinc)) == 0 && + canonprinc != NULL) { + copy.server = (krb5_principal)canonprinc; + code = get_proxy_cred_from_kdc(context, options, ccache, ©, + &creds); + if (code != KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) + break; + } + if (!code && canonprinc == NULL) + code = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + free_canonprinc(&iter); + if (code) + return code; + + krb5_free_principal(context, creds->server); + creds->server = NULL; + code = krb5_copy_principal(context, in_creds->server, &creds->server); + if (code) { + krb5_free_creds(context, creds); + return code; + } + + if (!(options & KRB5_GC_NO_STORE)) + (void)krb5_cc_store_cred(context, ccache, creds); + + *out_creds = creds; + return 0; +} + +/* + * Exported API for constrained delegation (S4U2Proxy). + * + * This is preferable to using krb5_get_credentials directly because + * it can perform some additional checks. + */ +krb5_error_code KRB5_CALLCONV +krb5_get_credentials_for_proxy(krb5_context context, + krb5_flags options, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_ticket *evidence_tkt, + krb5_creds **out_creds) +{ + krb5_error_code code; + krb5_data *evidence_tkt_data = NULL; + krb5_creds s4u_creds; + + *out_creds = NULL; + + if (in_creds == NULL || in_creds->client == NULL || evidence_tkt == NULL) { + code = EINVAL; + goto cleanup; + } + + /* + * Caller should have set in_creds->client to match evidence + * ticket client. If we can, verify it before issuing the request. + */ + if (evidence_tkt->enc_part2 != NULL && + !krb5_principal_compare(context, evidence_tkt->enc_part2->client, + in_creds->client)) { + code = EINVAL; + goto cleanup; + } + + code = encode_krb5_ticket(evidence_tkt, &evidence_tkt_data); + if (code != 0) + goto cleanup; + + s4u_creds = *in_creds; + s4u_creds.client = evidence_tkt->server; + s4u_creds.second_ticket = *evidence_tkt_data; + + code = k5_get_proxy_cred_from_kdc(context, + options | KRB5_GC_CONSTRAINED_DELEGATION, + ccache, &s4u_creds, out_creds); + if (code != 0) + goto cleanup; + + /* + * Check client name because we couldn't compare that inside + * krb5_get_credentials() (enc_part2 is unavailable in clear) + */ + if (!krb5_principal_compare(context, in_creds->client, + (*out_creds)->client)) { + code = KRB5_KDCREP_MODIFIED; + goto cleanup; + } + +cleanup: + if (*out_creds != NULL && code != 0) { + krb5_free_creds(context, *out_creds); + *out_creds = NULL; + } + if (evidence_tkt_data != NULL) + krb5_free_data(context, evidence_tkt_data); + + return code; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/send_tgs.c b/krb5-1.21.3/src/lib/krb5/krb/send_tgs.c new file mode 100644 index 00000000..7a11864f --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/send_tgs.c @@ -0,0 +1,300 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/send_tgs.c - Construct a TGS request */ +/* + * Copyright 1990,1991,2009,2013 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "fast.h" + +/* Choose a random nonce for an AS or TGS request. */ +krb5_error_code +k5_generate_nonce(krb5_context context, int32_t *out) +{ + krb5_error_code ret; + unsigned char random_buf[4]; + krb5_data random_data = make_data(random_buf, 4); + + *out = 0; + + /* We and Heimdal incorrectly encode nonces as signed, so make sure we use + * a non-negative value to avoid interoperability issues. */ + ret = krb5_c_random_make_octets(context, &random_data); + if (ret) + return ret; + *out = 0x7FFFFFFF & load_32_n(random_buf); + return 0; +} + +/* Construct an AP-REQ message for a TGS request. */ +static krb5_error_code +tgs_construct_ap_req(krb5_context context, krb5_data *checksum_data, + krb5_creds *tgt, krb5_keyblock *subkey, + krb5_data **ap_req_asn1_out) +{ + krb5_error_code ret; + krb5_checksum checksum; + krb5_authenticator authent; + krb5_ap_req ap_req; + krb5_data *authent_asn1 = NULL; + krb5_ticket *ticket = NULL; + krb5_enc_data authent_enc; + + *ap_req_asn1_out = NULL; + memset(&checksum, 0, sizeof(checksum)); + memset(&ap_req, 0, sizeof(ap_req)); + memset(&authent_enc, 0, sizeof(authent_enc)); + + /* Generate checksum. */ + ret = krb5_c_make_checksum(context, 0, &tgt->keyblock, + KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, checksum_data, + &checksum); + if (ret) + goto cleanup; + + /* Construct, encode, and encrypt an authenticator. */ + authent.subkey = subkey; + authent.seq_number = 0; + authent.checksum = &checksum; + authent.client = tgt->client; + authent.authorization_data = tgt->authdata; + ret = krb5_us_timeofday(context, &authent.ctime, &authent.cusec); + if (ret) + goto cleanup; + ret = encode_krb5_authenticator(&authent, &authent_asn1); + if (ret) + goto cleanup; + ret = krb5_encrypt_helper(context, &tgt->keyblock, + KRB5_KEYUSAGE_TGS_REQ_AUTH, authent_asn1, + &authent_enc); + if (ret) + goto cleanup; + + ret = decode_krb5_ticket(&tgt->ticket, &ticket); + if (ret) + goto cleanup; + + /* Encode the AP-REQ. */ + ap_req.authenticator = authent_enc; + ap_req.ticket = ticket; + ret = encode_krb5_ap_req(&ap_req, ap_req_asn1_out); + +cleanup: + free(checksum.contents); + krb5_free_ticket(context, ticket); + krb5_free_data_contents(context, &authent_enc.ciphertext); + if (authent_asn1 != NULL) + zapfree(authent_asn1->data, authent_asn1->length); + free(authent_asn1); + return ret; +} + +/* + * Construct a TGS request and return its ASN.1 encoding as well as the + * timestamp, nonce, and subkey used. The pacb_fn callback allows the caller + * to amend the request padata after the nonce and subkey are determined. + */ +krb5_error_code +k5_make_tgs_req(krb5_context context, + struct krb5int_fast_request_state *fast_state, + krb5_creds *tgt, krb5_flags kdcoptions, + krb5_address *const *addrs, krb5_pa_data **in_padata, + krb5_creds *desired, k5_pacb_fn pacb_fn, void *pacb_data, + krb5_data *req_asn1_out, krb5_timestamp *timestamp_out, + krb5_int32 *nonce_out, krb5_keyblock **subkey_out) +{ + krb5_error_code ret; + krb5_kdc_req req; + krb5_data *authdata_asn1 = NULL, *req_body_asn1 = NULL; + krb5_data *ap_req_asn1 = NULL, *tgs_req_asn1 = NULL; + krb5_ticket *sec_ticket = NULL; + krb5_ticket *sec_ticket_arr[2]; + krb5_timestamp time_now; + krb5_pa_data **padata = NULL, *pa; + krb5_keyblock *subkey = NULL; + krb5_enc_data authdata_enc; + krb5_enctype enctypes[2], *defenctypes = NULL; + size_t count, i; + + *req_asn1_out = empty_data(); + *timestamp_out = 0; + *nonce_out = 0; + *subkey_out = NULL; + memset(&req, 0, sizeof(req)); + memset(&authdata_enc, 0, sizeof(authdata_enc)); + + /* tgt's client principal must match the desired client principal. */ + if (!krb5_principal_compare(context, tgt->client, desired->client)) + return KRB5_PRINC_NOMATCH; + + /* tgt must be an actual credential, not a template. */ + if (!tgt->ticket.length) + return KRB5_NO_TKT_SUPPLIED; + + req.kdc_options = kdcoptions; + req.server = desired->server; + req.from = desired->times.starttime; + req.till = desired->times.endtime ? desired->times.endtime : + tgt->times.endtime; + req.rtime = desired->times.renew_till; + ret = k5_generate_nonce(context, &req.nonce); + if (ret) + return ret; + *nonce_out = req.nonce; + ret = krb5_timeofday(context, &time_now); + if (ret) + return ret; + *timestamp_out = time_now; + + req.addresses = (krb5_address **)addrs; + + /* Generate subkey. */ + ret = krb5_generate_subkey(context, &tgt->keyblock, &subkey); + if (ret) + return ret; + TRACE_SEND_TGS_SUBKEY(context, subkey); + + ret = krb5int_fast_tgs_armor(context, fast_state, subkey, &tgt->keyblock, + NULL, NULL); + if (ret) + goto cleanup; + + if (desired->authdata != NULL) { + ret = encode_krb5_authdata(desired->authdata, &authdata_asn1); + if (ret) + goto cleanup; + ret = krb5_encrypt_helper(context, subkey, + KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY, + authdata_asn1, &authdata_enc); + if (ret) + goto cleanup; + req.authorization_data = authdata_enc; + } + + if (desired->keyblock.enctype != ENCTYPE_NULL) { + if (!krb5_c_valid_enctype(desired->keyblock.enctype)) { + ret = KRB5_PROG_ETYPE_NOSUPP; + goto cleanup; + } + enctypes[0] = desired->keyblock.enctype; + enctypes[1] = ENCTYPE_NULL; + req.ktype = enctypes; + req.nktypes = 1; + } else { + /* Get the default TGS enctypes. */ + ret = krb5_get_tgs_ktypes(context, desired->server, &defenctypes); + if (ret) + goto cleanup; + for (count = 0; defenctypes[count]; count++); + req.ktype = defenctypes; + req.nktypes = count; + } + TRACE_SEND_TGS_ETYPES(context, req.ktype); + + if (kdcoptions & (KDC_OPT_ENC_TKT_IN_SKEY | KDC_OPT_CNAME_IN_ADDL_TKT)) { + if (desired->second_ticket.length == 0) { + ret = KRB5_NO_2ND_TKT; + goto cleanup; + } + ret = decode_krb5_ticket(&desired->second_ticket, &sec_ticket); + if (ret) + goto cleanup; + sec_ticket_arr[0] = sec_ticket; + sec_ticket_arr[1] = NULL; + req.second_ticket = sec_ticket_arr; + } + + /* Encode the request body. */ + ret = krb5int_fast_prep_req_body(context, fast_state, &req, + &req_body_asn1); + if (ret) + goto cleanup; + + ret = tgs_construct_ap_req(context, req_body_asn1, tgt, subkey, + &ap_req_asn1); + if (ret) + goto cleanup; + + for (count = 0; in_padata != NULL && in_padata[count] != NULL; count++); + + /* Construct a padata array for the request, beginning with the ap-req. */ + padata = k5calloc(count + 2, sizeof(krb5_pa_data *), &ret); + if (padata == NULL) + goto cleanup; + padata[0] = k5alloc(sizeof(krb5_pa_data), &ret); + if (padata[0] == NULL) + goto cleanup; + padata[0]->pa_type = KRB5_PADATA_AP_REQ; + padata[0]->contents = k5memdup(ap_req_asn1->data, ap_req_asn1->length, + &ret); + if (padata[0] == NULL) + goto cleanup; + padata[0]->length = ap_req_asn1->length; + + /* Append copies of any other supplied padata. */ + for (i = 0; in_padata != NULL && in_padata[i] != NULL; i++) { + pa = k5alloc(sizeof(krb5_pa_data), &ret); + if (pa == NULL) + goto cleanup; + pa->pa_type = in_padata[i]->pa_type; + pa->length = in_padata[i]->length; + pa->contents = k5memdup(in_padata[i]->contents, in_padata[i]->length, + &ret); + if (pa->contents == NULL) { + free(pa); + goto cleanup; + } + padata[i + 1] = pa; + } + req.padata = padata; + + if (pacb_fn != NULL) { + ret = (*pacb_fn)(context, subkey, &req, pacb_data); + if (ret) + goto cleanup; + } + + /* Encode the TGS-REQ. Discard the krb5_data container. */ + ret = krb5int_fast_prep_req(context, fast_state, &req, ap_req_asn1, + encode_krb5_tgs_req, &tgs_req_asn1); + if (ret) + goto cleanup; + *req_asn1_out = *tgs_req_asn1; + free(tgs_req_asn1); + tgs_req_asn1 = NULL; + + *subkey_out = subkey; + subkey = NULL; + +cleanup: + krb5_free_data(context, authdata_asn1); + krb5_free_data(context, req_body_asn1); + krb5_free_data(context, ap_req_asn1); + krb5_free_pa_data(context, padata); + krb5_free_ticket(context, sec_ticket); + krb5_free_data_contents(context, &authdata_enc.ciphertext); + krb5_free_keyblock(context, subkey); + free(defenctypes); + return ret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/sendauth.c b/krb5-1.21.3/src/lib/krb5/krb/sendauth.c new file mode 100644 index 00000000..9e73294e --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/sendauth.c @@ -0,0 +1,206 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/sendauth.c */ +/* + * Copyright 1991, 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "os-proto.h" +#include "com_err.h" +#include "auth_con.h" +#include +#include +#include + +static const char sendauth_version[] = "KRB5_SENDAUTH_V1.0"; + +krb5_error_code KRB5_CALLCONV +krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, + krb5_pointer fd, char *appl_version, krb5_principal client, + krb5_principal server, krb5_flags ap_req_options, + krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, + krb5_error **error, krb5_ap_rep_enc_part **rep_result, + krb5_creds **out_creds) +{ + krb5_octet result; + krb5_creds creds; + krb5_creds * credsp = NULL; + krb5_creds * credspout = NULL; + krb5_error_code retval = 0; + krb5_data inbuf, outbuf[2]; + int len; + krb5_ccache use_ccache = 0; + + if (error) + *error = 0; + + /* + * First, send over the length of the sendauth version string; + * then, we send over the sendauth version. Next, we send + * over the length of the application version strings followed + * by the string itself. + */ + outbuf[0].length = strlen(sendauth_version) + 1; + outbuf[0].data = (char *) sendauth_version; + outbuf[1].length = strlen(appl_version) + 1; + outbuf[1].data = appl_version; + if ((retval = k5_write_messages(context, fd, outbuf, 2))) + return(retval); + /* + * Now, read back a byte: 0 means no error, 1 means bad sendauth + * version, 2 means bad application version + */ + if ((len = krb5_net_read(context, *((int *) fd), (char *)&result, 1)) != 1) + return((len < 0) ? errno : ECONNABORTED); + if (result == 1) + return(KRB5_SENDAUTH_BADAUTHVERS); + else if (result == 2) + return(KRB5_SENDAUTH_BADAPPLVERS); + else if (result != 0) + return(KRB5_SENDAUTH_BADRESPONSE); + /* + * We're finished with the initial negotiations; let's get and + * send over the authentication header. (The AP_REQ message) + */ + + /* + * If no credentials were provided, try getting it from the + * credentials cache. + */ + memset(&creds, 0, sizeof(creds)); + + /* + * See if we need to access the credentials cache + */ + if (!in_creds || !in_creds->ticket.length) { + if (ccache) + use_ccache = ccache; + else if ((retval = krb5int_cc_default(context, &use_ccache))) + goto error_return; + } + if (!in_creds) { + if ((retval = krb5_copy_principal(context, server, + &creds.server))) + goto error_return; + if (client) + retval = krb5_copy_principal(context, client, + &creds.client); + else + retval = krb5_cc_get_principal(context, use_ccache, + &creds.client); + if (retval) + goto error_return; + /* creds.times.endtime = 0; -- memset 0 takes care of this + zero means "as long as possible" */ + /* creds.keyblock.enctype = 0; -- as well as this. + zero means no session enctype + preference */ + in_creds = &creds; + } + if (!in_creds->ticket.length) { + if ((retval = krb5_get_credentials(context, 0, + use_ccache, in_creds, &credsp))) + goto error_return; + credspout = credsp; + } else { + credsp = in_creds; + } + + outbuf[0].data = NULL; /* Coverity is confused otherwise */ + if ((retval = krb5_mk_req_extended(context, auth_context, + ap_req_options, in_data, credsp, + &outbuf[0]))) + goto error_return; + + /* + * First write the length of the AP_REQ message, then write + * the message itself. + */ + retval = krb5_write_message(context, fd, &outbuf[0]); + free(outbuf[0].data); + if (retval) + goto error_return; + + /* + * Now, read back a message. If it was a null message (the + * length was zero) then there was no error. If not, we the + * authentication was rejected, and we need to return the + * error structure. + */ + if ((retval = krb5_read_message(context, fd, &inbuf))) + goto error_return; + + if (inbuf.length) { + if (error) { + if ((retval = krb5_rd_error(context, &inbuf, error))) { + free(inbuf.data); + goto error_return; + } + } + retval = KRB5_SENDAUTH_REJECTED; + free(inbuf.data); + goto error_return; + } + + /* + * If we asked for mutual authentication, we should now get a + * length field, followed by a AP_REP message + */ + if ((ap_req_options & AP_OPTS_MUTUAL_REQUIRED)) { + krb5_ap_rep_enc_part *repl = 0; + + if ((retval = krb5_read_message(context, fd, &inbuf))) + goto error_return; + + if ((retval = krb5_rd_rep(context, *auth_context, &inbuf, + &repl))) { + if (repl) + krb5_free_ap_rep_enc_part(context, repl); + free(inbuf.data); + goto error_return; + } + + free(inbuf.data); + /* + * If the user wants to look at the AP_REP message, + * copy it for him + */ + if (rep_result) + *rep_result = repl; + else + krb5_free_ap_rep_enc_part(context, repl); + } + retval = 0; /* Normal return */ + if (out_creds) { + *out_creds = credsp; + credspout = NULL; + } + +error_return: + krb5_free_cred_contents(context, &creds); + if (credspout != NULL) + krb5_free_creds(context, credspout); + if (!ccache && use_ccache) + krb5_cc_close(context, use_ccache); + return(retval); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/ser_actx.c b/krb5-1.21.3/src/lib/krb5/krb/ser_actx.c new file mode 100644 index 00000000..6de35a14 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/ser_actx.c @@ -0,0 +1,397 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/ser_actx.c - Serialize krb5_auth_context structure */ +/* + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" +#include "auth_con.h" + +#define TOKEN_RADDR 950916 +#define TOKEN_RPORT 950917 +#define TOKEN_LADDR 950918 +#define TOKEN_LPORT 950919 +#define TOKEN_KEYBLOCK 950920 +#define TOKEN_LSKBLOCK 950921 +#define TOKEN_RSKBLOCK 950922 + +krb5_error_code +k5_size_auth_context(krb5_auth_context auth_context, size_t *sizep) +{ + krb5_error_code kret; + size_t required; + + /* + * krb5_auth_context requires at minimum: + * krb5_int32 for KV5M_AUTH_CONTEXT + * krb5_int32 for auth_context_flags + * krb5_int32 for remote_seq_number + * krb5_int32 for local_seq_number + * krb5_int32 for req_cksumtype + * krb5_int32 for safe_cksumtype + * krb5_int32 for size of i_vector + * krb5_int32 for KV5M_AUTH_CONTEXT + */ + kret = EINVAL; + if (auth_context != NULL) { + kret = 0; + + required = auth_context->cstate.length; + required += sizeof(krb5_int32)*8; + + /* Calculate size required by remote_addr, if appropriate */ + if (!kret && auth_context->remote_addr) { + kret = k5_size_address(auth_context->remote_addr, &required); + if (!kret) + required += sizeof(krb5_int32); + } + + /* Calculate size required by remote_port, if appropriate */ + if (!kret && auth_context->remote_port) { + kret = k5_size_address(auth_context->remote_port, &required); + if (!kret) + required += sizeof(krb5_int32); + } + + /* Calculate size required by local_addr, if appropriate */ + if (!kret && auth_context->local_addr) { + kret = k5_size_address(auth_context->local_addr, &required); + if (!kret) + required += sizeof(krb5_int32); + } + + /* Calculate size required by local_port, if appropriate */ + if (!kret && auth_context->local_port) { + kret = k5_size_address(auth_context->local_port, &required); + if (!kret) + required += sizeof(krb5_int32); + } + + /* Calculate size required by key, if appropriate */ + if (!kret && auth_context->key) { + kret = k5_size_keyblock(&auth_context->key->keyblock, &required); + if (!kret) + required += sizeof(krb5_int32); + } + + /* Calculate size required by send_subkey, if appropriate */ + if (!kret && auth_context->send_subkey) { + kret = k5_size_keyblock(&auth_context->send_subkey->keyblock, + &required); + if (!kret) + required += sizeof(krb5_int32); + } + + /* Calculate size required by recv_subkey, if appropriate */ + if (!kret && auth_context->recv_subkey) { + kret = k5_size_keyblock(&auth_context->recv_subkey->keyblock, + &required); + if (!kret) + required += sizeof(krb5_int32); + } + + /* Calculate size required by authentp, if appropriate */ + if (!kret && auth_context->authentp) + kret = k5_size_authenticator(auth_context->authentp, &required); + + } + if (!kret) + *sizep += required; + return(kret); +} + +krb5_error_code +k5_externalize_auth_context(krb5_auth_context auth_context, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + size_t required; + krb5_octet *bp; + size_t remain; + + required = 0; + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + if (auth_context != NULL) { + kret = ENOMEM; + if (!k5_size_auth_context(auth_context, &required) && + required <= remain) { + + /* Write fixed portion */ + (void) krb5_ser_pack_int32(KV5M_AUTH_CONTEXT, &bp, &remain); + (void) krb5_ser_pack_int32(auth_context->auth_context_flags, + &bp, &remain); + (void) krb5_ser_pack_int32(auth_context->remote_seq_number, + &bp, &remain); + (void) krb5_ser_pack_int32(auth_context->local_seq_number, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) auth_context->req_cksumtype, + &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) auth_context->safe_cksumtype, + &bp, &remain); + + /* Write the cipher state */ + (void) krb5_ser_pack_int32(auth_context->cstate.length, &bp, + &remain); + (void) krb5_ser_pack_bytes((krb5_octet *)auth_context->cstate.data, + auth_context->cstate.length, + &bp, &remain); + + kret = 0; + + /* Now handle remote_addr, if appropriate */ + if (!kret && auth_context->remote_addr) { + (void) krb5_ser_pack_int32(TOKEN_RADDR, &bp, &remain); + kret = k5_externalize_address(auth_context->remote_addr, + &bp, &remain); + } + + /* Now handle remote_port, if appropriate */ + if (!kret && auth_context->remote_port) { + (void) krb5_ser_pack_int32(TOKEN_RPORT, &bp, &remain); + kret = k5_externalize_address(auth_context->remote_addr, + &bp, &remain); + } + + /* Now handle local_addr, if appropriate */ + if (!kret && auth_context->local_addr) { + (void) krb5_ser_pack_int32(TOKEN_LADDR, &bp, &remain); + kret = k5_externalize_address(auth_context->local_addr, + &bp, &remain); + } + + /* Now handle local_port, if appropriate */ + if (!kret && auth_context->local_port) { + (void) krb5_ser_pack_int32(TOKEN_LPORT, &bp, &remain); + kret = k5_externalize_address(auth_context->local_addr, + &bp, &remain); + } + + /* Now handle keyblock, if appropriate */ + if (!kret && auth_context->key) { + (void) krb5_ser_pack_int32(TOKEN_KEYBLOCK, &bp, &remain); + kret = k5_externalize_keyblock(&auth_context->key->keyblock, + &bp, &remain); + } + + /* Now handle subkey, if appropriate */ + if (!kret && auth_context->send_subkey) { + (void) krb5_ser_pack_int32(TOKEN_LSKBLOCK, &bp, &remain); + kret = k5_externalize_keyblock(&auth_context-> + send_subkey->keyblock, + &bp, &remain); + } + + /* Now handle subkey, if appropriate */ + if (!kret && auth_context->recv_subkey) { + (void) krb5_ser_pack_int32(TOKEN_RSKBLOCK, &bp, &remain); + kret = k5_externalize_keyblock(&auth_context-> + recv_subkey->keyblock, + &bp, &remain); + } + + /* Now handle authentp, if appropriate */ + if (!kret && auth_context->authentp) + kret = k5_externalize_authenticator(auth_context->authentp, + &bp, &remain); + + /* + * If we were successful, write trailer then update the pointer and + * remaining length; + */ + if (!kret) { + /* Write our trailer */ + (void) krb5_ser_pack_int32(KV5M_AUTH_CONTEXT, &bp, &remain); + *buffer = bp; + *lenremain = remain; + } + } + } + return(kret); +} + +/* Internalize a keyblock and convert it to a key. */ +static krb5_error_code +intern_key(krb5_key *key, krb5_octet **bp, size_t *sp) +{ + krb5_keyblock *keyblock; + krb5_error_code ret; + + ret = k5_internalize_keyblock(&keyblock, bp, sp); + if (ret != 0) + return ret; + ret = krb5_k_create_key(NULL, keyblock, key); + krb5_free_keyblock(NULL, keyblock); + return ret; +} + +krb5_error_code +k5_internalize_auth_context(krb5_auth_context *argp, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + krb5_auth_context auth_context; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + krb5_int32 cstate_len; + krb5_int32 tag; + + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + /* Read our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) + ibuf = 0; + if (ibuf == KV5M_AUTH_CONTEXT) { + kret = ENOMEM; + + /* Get memory for the auth_context */ + if ((remain >= (5*sizeof(krb5_int32))) && + (auth_context = (krb5_auth_context) + calloc(1, sizeof(struct _krb5_auth_context)))) { + + /* Get auth_context_flags */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + auth_context->auth_context_flags = ibuf; + + /* Get remote_seq_number */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + auth_context->remote_seq_number = ibuf; + + /* Get local_seq_number */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + auth_context->local_seq_number = ibuf; + + /* Get req_cksumtype */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + auth_context->req_cksumtype = (krb5_cksumtype) ibuf; + + /* Get safe_cksumtype */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + auth_context->safe_cksumtype = (krb5_cksumtype) ibuf; + + /* Get length of cstate */ + (void) krb5_ser_unpack_int32(&cstate_len, &bp, &remain); + + if (cstate_len) { + kret = alloc_data(&auth_context->cstate, cstate_len); + if (!kret) { + kret = krb5_ser_unpack_bytes((krb5_octet *) + auth_context->cstate.data, + cstate_len, &bp, &remain); + } + } + else + kret = 0; + + /* Peek at next token */ + tag = 0; + if (!kret) + kret = krb5_ser_unpack_int32(&tag, &bp, &remain); + + /* This is the remote_addr */ + if (!kret && (tag == TOKEN_RADDR)) { + if (!(kret = k5_internalize_address(&auth_context->remote_addr, + &bp, &remain))) + kret = krb5_ser_unpack_int32(&tag, &bp, &remain); + } + + /* This is the remote_port */ + if (!kret && (tag == TOKEN_RPORT)) { + if (!(kret = k5_internalize_address(&auth_context->remote_port, + &bp, &remain))) + kret = krb5_ser_unpack_int32(&tag, &bp, &remain); + } + + /* This is the local_addr */ + if (!kret && (tag == TOKEN_LADDR)) { + if (!(kret = k5_internalize_address(&auth_context->local_addr, + &bp, &remain))) + kret = krb5_ser_unpack_int32(&tag, &bp, &remain); + } + + /* This is the local_port */ + if (!kret && (tag == TOKEN_LPORT)) { + if (!(kret = k5_internalize_address(&auth_context->local_port, + &bp, &remain))) + kret = krb5_ser_unpack_int32(&tag, &bp, &remain); + } + + /* This is the keyblock */ + if (!kret && (tag == TOKEN_KEYBLOCK)) { + if (!(kret = intern_key(&auth_context->key, &bp, &remain))) + kret = krb5_ser_unpack_int32(&tag, &bp, &remain); + } + + /* This is the send_subkey */ + if (!kret && (tag == TOKEN_LSKBLOCK)) { + if (!(kret = intern_key(&auth_context->send_subkey, + &bp, &remain))) + kret = krb5_ser_unpack_int32(&tag, &bp, &remain); + } + + /* This is the recv_subkey */ + if (!kret) { + if (tag == TOKEN_RSKBLOCK) { + kret = intern_key(&auth_context->recv_subkey, + &bp, &remain); + } + else { + /* + * We read the next tag, but it's not of any use here, so + * we effectively 'unget' it here. + */ + bp -= sizeof(krb5_int32); + remain += sizeof(krb5_int32); + } + } + + /* Now find the authentp */ + if (!kret) { + kret = k5_internalize_authenticator(&auth_context->authentp, + &bp, &remain); + if (kret == EINVAL) + kret = 0; + } + + /* Finally, find the trailer */ + if (!kret) { + kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + if (!kret && (ibuf != KV5M_AUTH_CONTEXT)) + kret = EINVAL; + } + if (!kret) { + *buffer = bp; + *lenremain = remain; + auth_context->magic = KV5M_AUTH_CONTEXT; + *argp = auth_context; + } + else + krb5_auth_con_free(NULL, auth_context); + } + } + return(kret); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/ser_adata.c b/krb5-1.21.3/src/lib/krb5/krb/ser_adata.c new file mode 100644 index 00000000..2c0094df --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/ser_adata.c @@ -0,0 +1,153 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/ser_adata.c - Serialize krb5_authdata structure */ +/* + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" + +krb5_error_code +k5_size_authdata(krb5_authdata *authdata, size_t *sizep) +{ + krb5_error_code kret; + + /* + * krb5_authdata requires: + * krb5_int32 for KV5M_AUTHDATA + * krb5_int32 for ad_type + * krb5_int32 for length + * authdata->length for contents + * krb5_int32 for KV5M_AUTHDATA + */ + kret = EINVAL; + if (authdata != NULL) { + *sizep += (sizeof(krb5_int32) + + sizeof(krb5_int32) + + sizeof(krb5_int32) + + sizeof(krb5_int32) + + (size_t) authdata->length); + kret = 0; + } + return(kret); +} + +krb5_error_code +k5_externalize_authdata(krb5_authdata *authdata, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + size_t required; + krb5_octet *bp; + size_t remain; + + required = 0; + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + if (authdata != NULL) { + kret = ENOMEM; + if (!k5_size_authdata(authdata, &required) && required <= remain) { + /* Our identifier */ + (void) krb5_ser_pack_int32(KV5M_AUTHDATA, &bp, &remain); + + /* Our ad_type */ + (void) krb5_ser_pack_int32((krb5_int32) authdata->ad_type, + &bp, &remain); + + /* Our length */ + (void) krb5_ser_pack_int32((krb5_int32) authdata->length, + &bp, &remain); + + /* Our contents */ + (void) krb5_ser_pack_bytes(authdata->contents, + (size_t) authdata->length, + &bp, &remain); + + /* Finally, our trailer */ + (void) krb5_ser_pack_int32(KV5M_AUTHDATA, &bp, &remain); + kret = 0; + *buffer = bp; + *lenremain = remain; + } + } + return(kret); +} + +krb5_error_code +k5_internalize_authdata(krb5_authdata **argp, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + krb5_authdata *authdata; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + /* Read our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) + ibuf = 0; + if (ibuf == KV5M_AUTHDATA) { + kret = ENOMEM; + + /* Get a authdata */ + if ((remain >= (2*sizeof(krb5_int32))) && + (authdata = (krb5_authdata *) calloc(1, sizeof(krb5_authdata)))) { + + /* Get the ad_type */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + authdata->ad_type = (krb5_authdatatype) ibuf; + + /* Get the length */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + authdata->length = (int) ibuf; + + /* Get the string */ + if ((authdata->contents = (krb5_octet *) + malloc((size_t) (ibuf))) && + !(kret = krb5_ser_unpack_bytes(authdata->contents, + (size_t) ibuf, + &bp, &remain))) { + if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) + ibuf = 0; + if (ibuf == KV5M_AUTHDATA) { + authdata->magic = KV5M_AUTHDATA; + *buffer = bp; + *lenremain = remain; + *argp = authdata; + } + else + kret = EINVAL; + } + if (kret) { + if (authdata->contents) + free(authdata->contents); + free(authdata); + } + } + } + return(kret); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/ser_addr.c b/krb5-1.21.3/src/lib/krb5/krb/ser_addr.c new file mode 100644 index 00000000..52aa6f2a --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/ser_addr.c @@ -0,0 +1,157 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/ser_addr.c - Serialize krb5_address structure */ +/* + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" + +krb5_error_code +k5_size_address(krb5_address *address, size_t *sizep) +{ + krb5_error_code kret; + + /* + * krb5_address requires: + * krb5_int32 for KV5M_ADDRESS + * krb5_int32 for addrtype + * krb5_int32 for length + * address->length for contents + * krb5_int32 for KV5M_ADDRESS + */ + kret = EINVAL; + if (address != NULL) { + *sizep += (sizeof(krb5_int32) + + sizeof(krb5_int32) + + sizeof(krb5_int32) + + sizeof(krb5_int32) + + (size_t) address->length); + kret = 0; + } + return(kret); +} + +krb5_error_code +k5_externalize_address(krb5_address *address, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + size_t required; + krb5_octet *bp; + size_t remain; + + required = 0; + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + if (address != NULL) { + kret = ENOMEM; + if (!k5_size_address(address, &required) && required <= remain) { + /* Our identifier */ + (void) krb5_ser_pack_int32(KV5M_ADDRESS, &bp, &remain); + + /* Our addrtype */ + (void) krb5_ser_pack_int32((krb5_int32) address->addrtype, + &bp, &remain); + + /* Our length */ + (void) krb5_ser_pack_int32((krb5_int32) address->length, + &bp, &remain); + + /* Our contents */ + (void) krb5_ser_pack_bytes(address->contents, + (size_t) address->length, + &bp, &remain); + + /* Finally, our trailer */ + (void) krb5_ser_pack_int32(KV5M_ADDRESS, &bp, &remain); + + kret = 0; + *buffer = bp; + *lenremain = remain; + } + } + return(kret); +} + +krb5_error_code +k5_internalize_address(krb5_address **argp, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + krb5_address *address; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + /* Read our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) + ibuf = 0; + if (ibuf == KV5M_ADDRESS) { + kret = ENOMEM; + + /* Get a address */ + if ((remain >= (2*sizeof(krb5_int32))) && + (address = (krb5_address *) calloc(1, sizeof(krb5_address)))) { + + address->magic = KV5M_ADDRESS; + + /* Get the addrtype */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + address->addrtype = (krb5_addrtype) ibuf; + + /* Get the length */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + address->length = (int) ibuf; + + /* Get the string */ + if ((address->contents = (krb5_octet *) malloc((size_t) (ibuf))) && + !(kret = krb5_ser_unpack_bytes(address->contents, + (size_t) ibuf, + &bp, &remain))) { + /* Get the trailer */ + if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) + ibuf = 0; + + if (!kret && (ibuf == KV5M_ADDRESS)) { + address->magic = KV5M_ADDRESS; + *buffer = bp; + *lenremain = remain; + *argp = address; + } + else + kret = EINVAL; + } + if (kret) { + if (address->contents) + free(address->contents); + free(address); + } + } + } + return(kret); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/ser_auth.c b/krb5-1.21.3/src/lib/krb5/krb/ser_auth.c new file mode 100644 index 00000000..f835a793 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/ser_auth.c @@ -0,0 +1,262 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/ser_auth.c - Serialize krb5_authenticator structure */ +/* + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef LEAN_CLIENT + +#include "k5-int.h" +#include "int-proto.h" + +krb5_error_code +k5_size_authenticator(krb5_authenticator *authenticator, size_t *sizep) +{ + krb5_error_code kret; + size_t required; + + /* + * krb5_authenticator requires at minimum: + * krb5_int32 for KV5M_AUTHENTICATOR + * krb5_int32 for seconds + * krb5_int32 for cusec + * krb5_int32 for seq_number + * krb5_int32 for number in authorization_data array. + * krb5_int32 for KV5M_AUTHENTICATOR + */ + kret = EINVAL; + if (authenticator != NULL) { + required = sizeof(krb5_int32)*6; + + /* Calculate size required by client, if appropriate */ + if (authenticator->client) + kret = k5_size_principal(authenticator->client, &required); + else + kret = 0; + + /* Calculate size required by checksum, if appropriate */ + if (!kret && authenticator->checksum) + kret = k5_size_checksum(authenticator->checksum, &required); + + /* Calculate size required by subkey, if appropriate */ + if (!kret && authenticator->subkey) + kret = k5_size_keyblock(authenticator->subkey, &required); + + /* Calculate size required by authorization_data, if appropriate */ + if (!kret && authenticator->authorization_data) { + int i; + + for (i=0; !kret && authenticator->authorization_data[i]; i++) { + kret = k5_size_authdata(authenticator->authorization_data[i], + &required); + } + } + } + if (!kret) + *sizep += required; + return(kret); +} + +krb5_error_code +k5_externalize_authenticator(krb5_authenticator *authenticator, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + size_t required; + krb5_octet *bp; + size_t remain; + int i; + + required = 0; + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + if (authenticator != NULL) { + kret = ENOMEM; + if (!k5_size_authenticator(authenticator, &required) && + required <= remain) { + /* First write our magic number */ + (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain); + + /* Now ctime */ + (void) krb5_ser_pack_int32((krb5_int32) authenticator->ctime, + &bp, &remain); + + /* Now cusec */ + (void) krb5_ser_pack_int32((krb5_int32) authenticator->cusec, + &bp, &remain); + + /* Now seq_number */ + (void) krb5_ser_pack_int32(authenticator->seq_number, + &bp, &remain); + + /* Now handle client, if appropriate */ + if (authenticator->client) + kret = k5_externalize_principal(authenticator->client, + &bp, &remain); + else + kret = 0; + + /* Now handle checksum, if appropriate */ + if (!kret && authenticator->checksum) + kret = k5_externalize_checksum(authenticator->checksum, + &bp, &remain); + + /* Now handle subkey, if appropriate */ + if (!kret && authenticator->subkey) + kret = k5_externalize_keyblock(authenticator->subkey, + &bp, &remain); + + /* Now handle authorization_data, if appropriate */ + if (!kret) { + if (authenticator->authorization_data) + for (i=0; authenticator->authorization_data[i]; i++); + else + i = 0; + (void) krb5_ser_pack_int32((krb5_int32) i, &bp, &remain); + + /* Now pound out the authorization_data */ + if (authenticator->authorization_data) { + for (i=0; !kret && authenticator->authorization_data[i]; + i++) + kret = k5_externalize_authdata(authenticator-> + authorization_data[i], + &bp, &remain); + } + } + + /* + * If we were successful, write trailer then update the pointer and + * remaining length; + */ + if (!kret) { + /* Write our trailer */ + (void) krb5_ser_pack_int32(KV5M_AUTHENTICATOR, &bp, &remain); + *buffer = bp; + *lenremain = remain; + } + } + } + return(kret); +} + +krb5_error_code +k5_internalize_authenticator(krb5_authenticator **argp, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + krb5_authenticator *authenticator; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + int i; + krb5_int32 nadata; + size_t len; + + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + /* Read our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) + ibuf = 0; + if (ibuf == KV5M_AUTHENTICATOR) { + kret = ENOMEM; + + /* Get memory for the authenticator */ + if ((remain >= (3*sizeof(krb5_int32))) && + (authenticator = (krb5_authenticator *) + calloc(1, sizeof(krb5_authenticator)))) { + + /* Get ctime */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + authenticator->ctime = (krb5_timestamp) ibuf; + + /* Get cusec */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + authenticator->cusec = ibuf; + + /* Get seq_number */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + authenticator->seq_number = ibuf; + + kret = 0; + + /* Attempt to read in the client */ + kret = k5_internalize_principal(&authenticator->client, + &bp, &remain); + if (kret == EINVAL) + kret = 0; + + /* Attempt to read in the checksum */ + if (!kret) { + kret = k5_internalize_checksum(&authenticator->checksum, + &bp, &remain); + if (kret == EINVAL) + kret = 0; + } + + /* Attempt to read in the subkey */ + if (!kret) { + kret = k5_internalize_keyblock(&authenticator->subkey, + &bp, &remain); + if (kret == EINVAL) + kret = 0; + } + + /* Attempt to read in the authorization data count */ + if (!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) { + nadata = ibuf; + len = (size_t) (nadata + 1); + + /* Get memory for the authorization data pointers */ + if ((authenticator->authorization_data = (krb5_authdata **) + calloc(len, sizeof(krb5_authdata *)))) { + for (i=0; !kret && (i + authorization_data[i], + &bp, &remain); + } + + /* Finally, find the trailer */ + if (!kret) { + kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + if (!kret && (ibuf == KV5M_AUTHENTICATOR)) + authenticator->magic = KV5M_AUTHENTICATOR; + else + kret = EINVAL; + } + } + } + if (!kret) { + *buffer = bp; + *lenremain = remain; + *argp = authenticator; + } + else + krb5_free_authenticator(NULL, authenticator); + } + } + return(kret); +} + +#endif diff --git a/krb5-1.21.3/src/lib/krb5/krb/ser_cksum.c b/krb5-1.21.3/src/lib/krb5/krb/ser_cksum.c new file mode 100644 index 00000000..de8cb2b9 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/ser_cksum.c @@ -0,0 +1,155 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/ser_cksum.c - Serialize krb5_checksum structure */ +/* + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" + +krb5_error_code +k5_size_checksum(krb5_checksum *checksum, size_t *sizep) +{ + krb5_error_code kret; + + /* + * krb5_checksum requires: + * krb5_int32 for KV5M_CHECKSUM + * krb5_int32 for checksum_type + * krb5_int32 for length + * krb5_int32 for KV5M_CHECKSUM + * checksum->length for contents + */ + kret = EINVAL; + if (checksum != NULL) { + *sizep += (sizeof(krb5_int32) + + sizeof(krb5_int32) + + sizeof(krb5_int32) + + sizeof(krb5_int32) + + (size_t) checksum->length); + kret = 0; + } + return(kret); +} + +krb5_error_code +k5_externalize_checksum(krb5_checksum *checksum, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + size_t required; + krb5_octet *bp; + size_t remain; + + required = 0; + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + if (checksum != NULL) { + kret = ENOMEM; + if (!k5_size_checksum(checksum, &required) && required <= remain) { + /* Our identifier */ + (void) krb5_ser_pack_int32(KV5M_CHECKSUM, &bp, &remain); + + /* Our checksum_type */ + (void) krb5_ser_pack_int32((krb5_int32) checksum->checksum_type, + &bp, &remain); + + /* Our length */ + (void) krb5_ser_pack_int32((krb5_int32) checksum->length, + &bp, &remain); + + /* Our contents */ + (void) krb5_ser_pack_bytes(checksum->contents, + (size_t) checksum->length, + &bp, &remain); + + /* Finally, our trailer */ + (void) krb5_ser_pack_int32(KV5M_CHECKSUM, &bp, &remain); + + kret = 0; + *buffer = bp; + *lenremain = remain; + } + } + return(kret); +} + +krb5_error_code +k5_internalize_checksum(krb5_checksum **argp, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + krb5_checksum *checksum; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + /* Read our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) + ibuf = 0; + if (ibuf == KV5M_CHECKSUM) { + kret = ENOMEM; + + /* Get a checksum */ + if ((remain >= (2*sizeof(krb5_int32))) && + (checksum = (krb5_checksum *) calloc(1, sizeof(krb5_checksum)))) { + /* Get the checksum_type */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + checksum->checksum_type = (krb5_cksumtype) ibuf; + + /* Get the length */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + checksum->length = (int) ibuf; + + /* Get the string */ + if (!ibuf || + ((checksum->contents = (krb5_octet *) + malloc((size_t) (ibuf))) && + !(kret = krb5_ser_unpack_bytes(checksum->contents, + (size_t) ibuf, + &bp, &remain)))) { + + /* Get the trailer */ + kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + if (!kret && (ibuf == KV5M_CHECKSUM)) { + checksum->magic = KV5M_CHECKSUM; + *buffer = bp; + *lenremain = remain; + *argp = checksum; + } + else + kret = EINVAL; + } + if (kret) { + if (checksum->contents) + free(checksum->contents); + free(checksum); + } + } + } + return(kret); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/ser_ctx.c b/krb5-1.21.3/src/lib/krb5/krb/ser_ctx.c new file mode 100644 index 00000000..da3582f9 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/ser_ctx.c @@ -0,0 +1,433 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/ser_ctx.c - Serialize krb5_context structure */ +/* + * Copyright 1995, 2007, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" + +krb5_error_code profile_ser_size(krb5_context, profile_t, size_t *); +krb5_error_code profile_ser_externalize(krb5_context, profile_t, + krb5_octet **, size_t *); +krb5_error_code profile_ser_internalize(krb5_context, profile_t *, + krb5_octet **, size_t *); + +static krb5_error_code size_oscontext(krb5_os_context os_ctx, size_t *sizep); +static krb5_error_code externalize_oscontext(krb5_os_context os_ctx, + krb5_octet **buffer, + size_t *lenremain); +static krb5_error_code internalize_oscontext(krb5_os_context *argp, + krb5_octet **buffer, + size_t *lenremain); + +static inline unsigned int +etypes_len(krb5_enctype *list) +{ + return (list == NULL) ? 0 : k5_count_etypes(list); +} + +krb5_error_code +k5_size_context(krb5_context context, size_t *sizep) +{ + krb5_error_code kret; + size_t required; + + /* + * The KRB5 context itself requires: + * krb5_int32 for KV5M_CONTEXT + * krb5_int32 for sizeof(default_realm) + * strlen(default_realm) for default_realm. + * krb5_int32 for n_tgs_etypes*sizeof(krb5_int32) + * nktypes*sizeof(krb5_int32) for tgs_etypes. + * krb5_int32 for clockskew + * krb5_int32 for kdc_default_options + * krb5_int32 for library_options + * krb5_int32 for profile_secure + * krb5_int32 for fcc_default_format + * <> for os_context + * <> for profile + * krb5_int32 for trailer. + */ + kret = EINVAL; + if (context != NULL) { + /* Calculate base length */ + required = (9 * sizeof(krb5_int32) + + (etypes_len(context->tgs_etypes) * sizeof(krb5_int32))); + + if (context->default_realm) + required += strlen(context->default_realm); + + /* Calculate size required by os_context, if appropriate */ + kret = size_oscontext(&context->os_context, &required); + + /* Calculate size required by profile, if appropriate */ + if (!kret && context->profile) + kret = profile_ser_size(NULL, context->profile, &required); + } + if (!kret) + *sizep += required; + return(kret); +} + +krb5_error_code +k5_externalize_context(krb5_context context, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + size_t required; + krb5_octet *bp; + size_t remain; + unsigned int i; + + required = 0; + bp = *buffer; + remain = *lenremain; + if (!context) + return (EINVAL); + if (context->magic != KV5M_CONTEXT) + return (KV5M_CONTEXT); + + if ((kret = k5_size_context(context, &required))) + return (kret); + + if (required > remain) + return (ENOMEM); + + /* First write our magic number */ + kret = krb5_ser_pack_int32(KV5M_CONTEXT, &bp, &remain); + if (kret) + return (kret); + + /* Now sizeof default realm */ + kret = krb5_ser_pack_int32((context->default_realm) ? + (krb5_int32) strlen(context->default_realm) : 0, + &bp, &remain); + if (kret) + return (kret); + + /* Now default_realm bytes */ + if (context->default_realm) { + kret = krb5_ser_pack_bytes((krb5_octet *) context->default_realm, + strlen(context->default_realm), + &bp, &remain); + if (kret) + return (kret); + } + + /* Now number of default ktypes */ + kret = krb5_ser_pack_int32(etypes_len(context->tgs_etypes), &bp, &remain); + if (kret) + return (kret); + + /* Now serialize ktypes */ + if (context->tgs_etypes) { + for (i = 0; context->tgs_etypes[i]; i++) { + kret = krb5_ser_pack_int32(context->tgs_etypes[i], &bp, &remain); + if (kret) + return (kret); + } + } + + /* Now allowable clockskew */ + kret = krb5_ser_pack_int32((krb5_int32) context->clockskew, + &bp, &remain); + if (kret) + return (kret); + + /* Now kdc_default_options */ + kret = krb5_ser_pack_int32((krb5_int32) context->kdc_default_options, + &bp, &remain); + if (kret) + return (kret); + + /* Now library_options */ + kret = krb5_ser_pack_int32((krb5_int32) context->library_options, + &bp, &remain); + if (kret) + return (kret); + + /* Now profile_secure */ + kret = krb5_ser_pack_int32((krb5_int32) context->profile_secure, + &bp, &remain); + if (kret) + return (kret); + + /* Now fcc_default_format */ + kret = krb5_ser_pack_int32((krb5_int32) context->fcc_default_format, + &bp, &remain); + if (kret) + return (kret); + + /* Now handle os_context, if appropriate */ + kret = externalize_oscontext(&context->os_context, &bp, &remain); + if (kret) + return (kret); + + /* Finally, handle profile, if appropriate */ + if (context->profile != NULL) { + kret = profile_ser_externalize(NULL, context->profile, &bp, &remain); + if (kret) + return (kret); + } + + /* + * If we were successful, write trailer then update the pointer and + * remaining length; + */ + kret = krb5_ser_pack_int32(KV5M_CONTEXT, &bp, &remain); + if (kret) + return (kret); + + *buffer = bp; + *lenremain = remain; + + return (0); +} + +krb5_error_code +k5_internalize_context(krb5_context *argp, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + krb5_context context; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + unsigned int i, count; + + bp = *buffer; + remain = *lenremain; + + /* Read our magic number */ + if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) + return (EINVAL); + + if (ibuf != KV5M_CONTEXT) + return (EINVAL); + + /* Get memory for the context */ + context = (krb5_context) calloc(1, sizeof(struct _krb5_context)); + if (!context) + return (ENOMEM); + + /* Get the size of the default realm */ + if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) + goto cleanup; + + if (ibuf) { + context->default_realm = (char *) malloc((size_t) ibuf+1); + if (!context->default_realm) { + kret = ENOMEM; + goto cleanup; + } + + kret = krb5_ser_unpack_bytes((krb5_octet *) context->default_realm, + (size_t) ibuf, &bp, &remain); + if (kret) + goto cleanup; + + context->default_realm[ibuf] = '\0'; + } + + /* Get the tgs_etypes */ + if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) + goto cleanup; + count = ibuf; + if (count > 0) { + context->tgs_etypes = calloc(count + 1, sizeof(krb5_enctype)); + if (!context->tgs_etypes) { + kret = ENOMEM; + goto cleanup; + } + for (i = 0; i < count; i++) { + if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) + goto cleanup; + context->tgs_etypes[i] = ibuf; + } + context->tgs_etypes[count] = 0; + } else + context->tgs_etypes = NULL; + + /* Allowable clockskew */ + if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) + goto cleanup; + context->clockskew = (krb5_deltat) ibuf; + + /* kdc_default_options */ + if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) + goto cleanup; + context->kdc_default_options = (krb5_flags) ibuf; + + /* library_options */ + if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) + goto cleanup; + context->library_options = (krb5_flags) ibuf; + + /* profile_secure */ + if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) + goto cleanup; + context->profile_secure = (krb5_boolean) ibuf; + + /* fcc_default_format */ + if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) + goto cleanup; + context->fcc_default_format = (int) ibuf; + + /* Attempt to read in the os_context. It's an array now, but + we still treat it in most places as a separate object with + a pointer. */ + { + krb5_os_context osp = 0; + kret = internalize_oscontext(&osp, &bp, &remain); + if (kret && (kret != EINVAL) && (kret != ENOENT)) + goto cleanup; + /* Put the newly allocated data into the krb5_context + structure where we're really keeping it these days. */ + if (osp) + context->os_context = *osp; + free(osp); + } + + /* Attempt to read in the profile */ + kret = profile_ser_internalize(NULL, &context->profile, &bp, &remain); + if (kret && (kret != EINVAL) && (kret != ENOENT)) + goto cleanup; + + /* Finally, find the trailer */ + if ((kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain))) + goto cleanup; + + if (ibuf != KV5M_CONTEXT) { + kret = EINVAL; + goto cleanup; + } + + context->magic = KV5M_CONTEXT; + *buffer = bp; + *lenremain = remain; + *argp = context; + + return 0; + +cleanup: + if (context) + krb5_free_context(context); + return(kret); +} + +krb5_error_code +size_oscontext(krb5_os_context os_ctx, size_t *sizep) +{ + /* + * We need five 32-bit integers: + * two for header and trailer + * one each for time_offset, usec_offset and os_flags + */ + *sizep += (5*sizeof(krb5_int32)); + return(0); +} + +krb5_error_code +externalize_oscontext(krb5_os_context os_ctx, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + size_t required; + krb5_octet *bp; + size_t remain; + + required = 0; + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + if (os_ctx != NULL) { + kret = ENOMEM; + if (!size_oscontext(os_ctx, &required) && required <= remain) { + (void) krb5_ser_pack_int32(KV5M_OS_CONTEXT, &bp, &remain); + (void) krb5_ser_pack_int32(os_ctx->time_offset, &bp, &remain); + (void) krb5_ser_pack_int32(os_ctx->usec_offset, &bp, &remain); + (void) krb5_ser_pack_int32(os_ctx->os_flags, &bp, &remain); + (void) krb5_ser_pack_int32(KV5M_OS_CONTEXT, &bp, &remain); + + /* Handle any other OS context here */ + kret = 0; + if (!kret) { + *buffer = bp; + *lenremain = remain; + } + } + } + return(kret); +} + +static krb5_error_code +internalize_oscontext(krb5_os_context *argp, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + krb5_os_context os_ctx; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + os_ctx = (krb5_os_context) NULL; + /* Read our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) + ibuf = 0; + if (ibuf == KV5M_OS_CONTEXT) { + kret = ENOMEM; + + /* Get memory for the context */ + if ((os_ctx = (krb5_os_context) + calloc(1, sizeof(struct _krb5_os_context))) && + (remain >= 4*sizeof(krb5_int32))) { + os_ctx->magic = KV5M_OS_CONTEXT; + + /* Read out our context */ + (void) krb5_ser_unpack_int32(&os_ctx->time_offset, &bp, &remain); + (void) krb5_ser_unpack_int32(&os_ctx->usec_offset, &bp, &remain); + (void) krb5_ser_unpack_int32(&os_ctx->os_flags, &bp, &remain); + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + + if (ibuf == KV5M_OS_CONTEXT) { + os_ctx->magic = KV5M_OS_CONTEXT; + kret = 0; + *buffer = bp; + *lenremain = remain; + } else + kret = EINVAL; + } + } + if (!kret) { + *argp = os_ctx; + } + else { + if (os_ctx) + free(os_ctx); + } + return(kret); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/ser_key.c b/krb5-1.21.3/src/lib/krb5/krb/ser_key.c new file mode 100644 index 00000000..7a294d68 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/ser_key.c @@ -0,0 +1,148 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/ser_key.c - Serialize krb5_keyblock structure */ +/* + * Copyright 1995, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" + +krb5_error_code +k5_size_keyblock(krb5_keyblock *keyblock, size_t *sizep) +{ + krb5_error_code kret; + + /* + * krb5_keyblock requires: + * krb5_int32 for KV5M_KEYBLOCK + * krb5_int32 for enctype + * krb5_int32 for length + * keyblock->length for contents + * krb5_int32 for KV5M_KEYBLOCK + */ + kret = EINVAL; + if (keyblock != NULL) { + *sizep += 4 * sizeof(krb5_int32) + keyblock->length; + kret = 0; + } + return(kret); +} + +krb5_error_code +k5_externalize_keyblock(krb5_keyblock *keyblock, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + size_t required; + krb5_octet *bp; + size_t remain; + + required = 0; + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + if (keyblock != NULL) { + kret = ENOMEM; + if (!k5_size_keyblock(keyblock, &required) && required <= remain) { + /* Our identifier */ + (void) krb5_ser_pack_int32(KV5M_KEYBLOCK, &bp, &remain); + + /* Our enctype */ + (void) krb5_ser_pack_int32((krb5_int32) keyblock->enctype, + &bp, &remain); + + /* Our length */ + (void) krb5_ser_pack_int32((krb5_int32) keyblock->length, + &bp, &remain); + + /* Our contents */ + (void) krb5_ser_pack_bytes(keyblock->contents, + (size_t) keyblock->length, + &bp, &remain); + + /* Finally, our trailer */ + (void) krb5_ser_pack_int32(KV5M_KEYBLOCK, &bp, &remain); + + kret = 0; + *buffer = bp; + *lenremain = remain; + } + } + return(kret); +} + +krb5_error_code +k5_internalize_keyblock(krb5_keyblock **argp, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + krb5_keyblock *keyblock; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + /* Read our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) + ibuf = 0; + if (ibuf == KV5M_KEYBLOCK) { + kret = ENOMEM; + + /* Get a keyblock */ + if ((remain >= (3*sizeof(krb5_int32))) && + (keyblock = (krb5_keyblock *) calloc(1, sizeof(krb5_keyblock)))) { + /* Get the enctype */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + keyblock->enctype = (krb5_enctype) ibuf; + + /* Get the length */ + (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain); + keyblock->length = (int) ibuf; + + /* Get the string */ + if ((keyblock->contents = (krb5_octet *) malloc((size_t) (ibuf)))&& + !(kret = krb5_ser_unpack_bytes(keyblock->contents, + (size_t) ibuf, + &bp, &remain))) { + kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + if (!kret && (ibuf == KV5M_KEYBLOCK)) { + kret = 0; + *buffer = bp; + *lenremain = remain; + keyblock->magic = KV5M_KEYBLOCK; + *argp = keyblock; + } + else + kret = EINVAL; + } + if (kret) { + if (keyblock->contents) + free(keyblock->contents); + free(keyblock); + } + } + } + return(kret); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/ser_princ.c b/krb5-1.21.3/src/lib/krb5/krb/ser_princ.c new file mode 100644 index 00000000..fc564997 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/ser_princ.c @@ -0,0 +1,138 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/ser_princ.c - Serialize krb5_principal structure */ +/* + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" + +krb5_error_code +k5_size_principal(krb5_principal principal, size_t *sizep) +{ + krb5_error_code kret; + char *fname; + + /* + * krb5_principal requires: + * krb5_int32 for KV5M_PRINCIPAL + * krb5_int32 for flattened name size + * strlen(name) for name. + * krb5_int32 for KV5M_PRINCIPAL + */ + kret = EINVAL; + if (principal != NULL && + !(kret = krb5_unparse_name(NULL, principal, &fname))) { + *sizep += (3*sizeof(krb5_int32)) + strlen(fname); + free(fname); + } + return(kret); +} + +krb5_error_code +k5_externalize_principal(krb5_principal principal, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + size_t required; + krb5_octet *bp; + size_t remain; + char *fname; + + required = 0; + bp = *buffer; + remain = *lenremain; + kret = EINVAL; + if (principal != NULL) { + kret = ENOMEM; + if (!k5_size_principal(principal, &required) && required <= remain) { + if (!(kret = krb5_unparse_name(NULL, principal, &fname))) { + + (void) krb5_ser_pack_int32(KV5M_PRINCIPAL, &bp, &remain); + (void) krb5_ser_pack_int32((krb5_int32) strlen(fname), + &bp, &remain); + (void) krb5_ser_pack_bytes((krb5_octet *) fname, + strlen(fname), &bp, &remain); + (void) krb5_ser_pack_int32(KV5M_PRINCIPAL, &bp, &remain); + *buffer = bp; + *lenremain = remain; + + free(fname); + } + } + } + return(kret); +} + +krb5_error_code +k5_internalize_principal(krb5_principal *argp, + krb5_octet **buffer, size_t *lenremain) +{ + krb5_error_code kret; + krb5_principal principal = NULL; + krb5_int32 ibuf; + krb5_octet *bp; + size_t remain; + char *tmpname = NULL; + + *argp = NULL; + bp = *buffer; + remain = *lenremain; + + /* Read our magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain) || ibuf != KV5M_PRINCIPAL) + return EINVAL; + + /* Read the principal name */ + kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain); + if (kret) + return kret; + tmpname = malloc(ibuf + 1); + kret = krb5_ser_unpack_bytes((krb5_octet *) tmpname, (size_t) ibuf, + &bp, &remain); + if (kret) + goto cleanup; + tmpname[ibuf] = '\0'; + + /* Parse the name to a principal structure */ + kret = krb5_parse_name_flags(NULL, tmpname, + KRB5_PRINCIPAL_PARSE_REQUIRE_REALM, + &principal); + if (kret) + goto cleanup; + + /* Read the trailing magic number */ + if (krb5_ser_unpack_int32(&ibuf, &bp, &remain) || ibuf != KV5M_PRINCIPAL) { + kret = EINVAL; + goto cleanup; + } + + *buffer = bp; + *lenremain = remain; + *argp = principal; +cleanup: + if (kret) + krb5_free_principal(NULL, principal); + free(tmpname); + return kret; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/serialize.c b/krb5-1.21.3/src/lib/krb5/krb/serialize.c new file mode 100644 index 00000000..8934cf15 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/serialize.c @@ -0,0 +1,125 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/serialize.c - Base serialization routines */ +/* + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +/* + * krb5_ser_pack_int32() - Pack a 4-byte integer if space is available. + * Update buffer pointer and remaining space. + */ +krb5_error_code KRB5_CALLCONV +krb5_ser_pack_int32(krb5_int32 iarg, krb5_octet **bufp, size_t *remainp) +{ + if (*remainp >= sizeof(krb5_int32)) { + store_32_be(iarg, *bufp); + *bufp += sizeof(krb5_int32); + *remainp -= sizeof(krb5_int32); + return(0); + } + else + return(ENOMEM); +} + +/* + * krb5_ser_pack_int64() - Pack an 8-byte integer if space is available. + * Update buffer pointer and remaining space. + */ +krb5_error_code KRB5_CALLCONV +krb5_ser_pack_int64(int64_t iarg, krb5_octet **bufp, size_t *remainp) +{ + if (*remainp >= sizeof(int64_t)) { + store_64_be(iarg, (unsigned char *)*bufp); + *bufp += sizeof(int64_t); + *remainp -= sizeof(int64_t); + return(0); + } + else + return(ENOMEM); +} + +/* + * krb5_ser_pack_bytes() - Pack a string of bytes. + */ +krb5_error_code KRB5_CALLCONV +krb5_ser_pack_bytes(krb5_octet *ostring, size_t osize, krb5_octet **bufp, size_t *remainp) +{ + if (*remainp >= osize) { + memcpy(*bufp, ostring, osize); + *bufp += osize; + *remainp -= osize; + return(0); + } + else + return(ENOMEM); +} + +/* + * krb5_ser_unpack_int32() - Unpack a 4-byte integer if it's there. + */ +krb5_error_code KRB5_CALLCONV +krb5_ser_unpack_int32(krb5_int32 *intp, krb5_octet **bufp, size_t *remainp) +{ + if (*remainp >= sizeof(krb5_int32)) { + *intp = load_32_be(*bufp); + *bufp += sizeof(krb5_int32); + *remainp -= sizeof(krb5_int32); + return(0); + } + else + return(ENOMEM); +} + +/* + * krb5_ser_unpack_int64() - Unpack an 8-byte integer if it's there. + */ +krb5_error_code KRB5_CALLCONV +krb5_ser_unpack_int64(int64_t *intp, krb5_octet **bufp, size_t *remainp) +{ + if (*remainp >= sizeof(int64_t)) { + *intp = load_64_be((unsigned char *)*bufp); + *bufp += sizeof(int64_t); + *remainp -= sizeof(int64_t); + return(0); + } + else + return(ENOMEM); +} + +/* + * krb5_ser_unpack_bytes() - Unpack a byte string if it's there. + */ +krb5_error_code KRB5_CALLCONV +krb5_ser_unpack_bytes(krb5_octet *istring, size_t isize, krb5_octet **bufp, size_t *remainp) +{ + if (*remainp >= isize) { + memcpy(istring, *bufp, isize); + *bufp += isize; + *remainp -= isize; + return(0); + } + else + return(ENOMEM); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/set_realm.c b/krb5-1.21.3/src/lib/krb5/krb/set_realm.c new file mode 100644 index 00000000..9697ff6e --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/set_realm.c @@ -0,0 +1,48 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/set_realm.c */ +/* + * Copyright 1997 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +krb5_error_code KRB5_CALLCONV +krb5_set_principal_realm(krb5_context context, krb5_principal principal, + const char *realm) +{ + size_t length; + char *newrealm; + + if (!realm) + return EINVAL; + + length = strlen(realm); + newrealm = strdup(realm); + if (!newrealm) + return ENOMEM; + + free(principal->realm.data); + principal->realm = make_data(newrealm, length); + + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/sname_match.c b/krb5-1.21.3/src/lib/krb5/krb/sname_match.c new file mode 100644 index 00000000..55a4b7dc --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/sname_match.c @@ -0,0 +1,70 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/sname_match.c - krb5_sname_match API function */ +/* + * Copyright (C) 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "int-proto.h" + +krb5_boolean KRB5_CALLCONV +krb5_sname_match(krb5_context context, krb5_const_principal matching, + krb5_const_principal princ) +{ + if (matching == NULL) + return TRUE; + + if (matching->type != KRB5_NT_SRV_HST || matching->length != 2) + return krb5_principal_compare(context, matching, princ); + + if (princ->length != 2) + return FALSE; + + /* Check the realm if present in matching. */ + if (matching->realm.length != 0 && !data_eq(matching->realm, princ->realm)) + return FALSE; + + /* Check the service name (must be present in matching). */ + if (!data_eq(matching->data[0], princ->data[0])) + return FALSE; + + /* Check the hostname if present in matching and not ignored. */ + if (matching->data[1].length != 0 && !context->ignore_acceptor_hostname && + !data_eq(matching->data[1], princ->data[1])) + return FALSE; + + /* All elements match. */ + return TRUE; +} + +krb5_boolean +k5_sname_wildcard_host(krb5_context context, krb5_const_principal mprinc) +{ + if (mprinc == NULL) + return TRUE; + + if (mprinc->type != KRB5_NT_SRV_HST || mprinc->length != 2) + return FALSE; + + return context->ignore_acceptor_hostname || mprinc->data[1].length == 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/srv_dec_tkt.c b/krb5-1.21.3/src/lib/krb5/krb/srv_dec_tkt.c new file mode 100644 index 00000000..6c922523 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/srv_dec_tkt.c @@ -0,0 +1,140 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/srv_dec_tkt.c */ +/* + * Copyright 2006, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Server decrypt ticket via keytab or keyblock. + * + * Different from krb5_rd_req_decoded. (krb5/src/lib/krb5/krb/rd_req_dec.c) + * - No krb5_principal_compare or KRB5KRB_AP_ERR_BADMATCH error. + * - No replay cache processing. + * - No skew checking or KRB5KRB_AP_ERR_SKEW error. + * - No address checking or KRB5KRB_AP_ERR_BADADDR error. + * - No time validation. + * - No permitted enctype validation or KRB5_NOPERM_ETYPE error. + * - Does not free ticket->enc_part2 on error. + */ + +#include + +#ifndef LEAN_CLIENT +static krb5_error_code +decrypt_ticket_keyblock(krb5_context context, const krb5_keyblock *key, + krb5_ticket *ticket) +{ + krb5_error_code retval; + krb5_data *realm; + krb5_transited *trans; + + retval = krb5_decrypt_tkt_part(context, key, ticket); + if (retval) + goto done; + + trans = &ticket->enc_part2->transited; + realm = &ticket->enc_part2->client->realm; + if (trans->tr_contents.data && *trans->tr_contents.data) { + retval = krb5_check_transited_list(context, &trans->tr_contents, + realm, &ticket->server->realm); + goto done; + } + + if (ticket->enc_part2->flags & TKT_FLG_INVALID) { /* ie, KDC_OPT_POSTDATED */ + retval = KRB5KRB_AP_ERR_TKT_INVALID; + goto done; + } + +done: + return retval; +} + + +krb5_error_code KRB5_CALLCONV +krb5_server_decrypt_ticket_keytab(krb5_context context, + const krb5_keytab keytab, + krb5_ticket *ticket) +{ + krb5_error_code retval; + krb5_keytab_entry ktent; + + if (keytab->ops->start_seq_get == NULL) { + retval = krb5_kt_get_entry(context, keytab, + ticket->server, + ticket->enc_part.kvno, + ticket->enc_part.enctype, &ktent); + if (retval == 0) { + retval = decrypt_ticket_keyblock(context, &ktent.key, ticket); + + (void) krb5_free_keytab_entry_contents(context, &ktent); + } + } else { + krb5_error_code code; + krb5_kt_cursor cursor; + + retval = krb5_kt_start_seq_get(context, keytab, &cursor); + if (retval != 0) + goto map_error; + + retval = KRB5_KT_NOTFOUND; + while ((code = krb5_kt_next_entry(context, keytab, + &ktent, &cursor)) == 0) { + if (ktent.key.enctype != ticket->enc_part.enctype) { + (void) krb5_free_keytab_entry_contents(context, &ktent); + continue; + } + + retval = decrypt_ticket_keyblock(context, &ktent.key, ticket); + if (retval == 0) { + krb5_principal tmp; + + retval = krb5_copy_principal(context, ktent.principal, &tmp); + if (retval == 0) { + krb5_free_principal(context, ticket->server); + ticket->server = tmp; + } + (void) krb5_free_keytab_entry_contents(context, &ktent); + break; + } + (void) krb5_free_keytab_entry_contents(context, &ktent); + } + + code = krb5_kt_end_seq_get(context, keytab, &cursor); + if (code != 0) + retval = code; + } + +map_error: + switch (retval) { + case KRB5_KT_KVNONOTFOUND: + case KRB5_KT_NOTFOUND: + case KRB5KRB_AP_ERR_BAD_INTEGRITY: + retval = KRB5KRB_AP_WRONG_PRINC; + break; + default: + break; + } + + return retval; +} +#endif /* LEAN_CLIENT */ diff --git a/krb5-1.21.3/src/lib/krb5/krb/srv_rcache.c b/krb5-1.21.3/src/lib/krb5/krb/srv_rcache.c new file mode 100644 index 00000000..64a270e6 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/srv_rcache.c @@ -0,0 +1,41 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/srv_rcache.c - Acquire default replay cache for a server */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include +#include + +krb5_error_code KRB5_CALLCONV +krb5_get_server_rcache(krb5_context context, const krb5_data *piece, + krb5_rcache *rcptr) +{ + /* + * This function used to compose a name based on the first component of the + * server principal, but now ignores the piece argument and resolves the + * default replay cache. + */ + return k5_rc_default(context, rcptr); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/str_conv.c b/krb5-1.21.3/src/lib/krb5/krb/str_conv.c new file mode 100644 index 00000000..c8421a8c --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/str_conv.c @@ -0,0 +1,319 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/str_conv.c - Convert between strings and krb5 data types */ +/* + * Copyright 1995, 1999, 2007 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Table of contents: + * + * String decoding: + * ---------------- + * krb5_string_to_salttype() - Convert string to salttype (krb5_int32) + * krb5_string_to_timestamp() - Convert string to krb5_timestamp. + * krb5_string_to_deltat() - Convert string to krb5_deltat. + * + * String encoding: + * ---------------- + * krb5_salttype_to_string() - Convert salttype (krb5_int32) to string. + * krb5_timestamp_to_string() - Convert krb5_timestamp to string. + * krb5_timestamp_to_sfstring() - Convert krb5_timestamp to short filled string + * krb5_deltat_to_string() - Convert krb5_deltat to string. + */ + +#include "k5-int.h" +#include + +/* Salt type conversions */ + +/* + * Local data structures. + */ +struct salttype_lookup_entry { + krb5_int32 stt_enctype; /* Salt type number */ + const char * stt_name; /* Salt type name */ +}; + +/* + * Lookup tables. + */ + +#include "kdb.h" +static const struct salttype_lookup_entry salttype_table[] = { + { KRB5_KDB_SALTTYPE_NORMAL, "normal" }, + { KRB5_KDB_SALTTYPE_NOREALM, "norealm", }, + { KRB5_KDB_SALTTYPE_ONLYREALM, "onlyrealm", }, + { KRB5_KDB_SALTTYPE_SPECIAL, "special", }, +}; +static const int salttype_table_nents = sizeof(salttype_table)/ + sizeof(salttype_table[0]); + +krb5_error_code KRB5_CALLCONV +krb5_string_to_salttype(char *string, krb5_int32 *salttypep) +{ + int i; + int found; + + found = 0; + for (i=0; i= buflen) + return(ENOMEM); + return(0); + } + else + return(EINVAL); +} + +/* (absolute) time conversions */ + +#ifdef HAVE_STRPTIME +#ifdef NEED_STRPTIME_PROTO +extern char *strptime (const char *, const char *, + struct tm *) +#ifdef __cplusplus + throw() +#endif + ; +#endif +#else /* HAVE_STRPTIME */ +#undef strptime +#define strptime my_strptime +static char *strptime (const char *, const char *, struct tm *); +#endif + +#ifndef HAVE_LOCALTIME_R +static inline struct tm * +localtime_r(const time_t *t, struct tm *buf) +{ + struct tm *tm = localtime(t); + if (tm == NULL) + return NULL; + *buf = *tm; + return buf; +} +#endif + +krb5_error_code KRB5_CALLCONV +krb5_string_to_timestamp(char *string, krb5_timestamp *timestampp) +{ + int i; + struct tm timebuf, timebuf2; + time_t now, ret_time; + char *s; + static const char * const atime_format_table[] = { + "%Y%m%d%H%M%S", /* yyyymmddhhmmss */ + "%Y.%m.%d.%H.%M.%S", /* yyyy.mm.dd.hh.mm.ss */ + "%y%m%d%H%M%S", /* yymmddhhmmss */ + "%y.%m.%d.%H.%M.%S", /* yy.mm.dd.hh.mm.ss */ + "%y%m%d%H%M", /* yymmddhhmm */ + "%H%M%S", /* hhmmss */ + "%H%M", /* hhmm */ + "%T", /* hh:mm:ss */ + "%R", /* hh:mm */ + /* The following not really supported unless native strptime present */ + "%x:%X", /* locale-dependent short format */ + "%d-%b-%Y:%T", /* dd-month-yyyy:hh:mm:ss */ + "%d-%b-%Y:%R" /* dd-month-yyyy:hh:mm */ + }; + static const int atime_format_table_nents = + sizeof(atime_format_table)/sizeof(atime_format_table[0]); + + + now = time((time_t *) NULL); + if (localtime_r(&now, &timebuf2) == NULL) + return EINVAL; + for (i=0; ideltat is in deltat.y */ + +krb5_error_code KRB5_CALLCONV +krb5_deltat_to_string(krb5_deltat deltat, char *buffer, size_t buflen) +{ + int days, hours, minutes, seconds; + krb5_deltat dt; + + days = (int) (deltat / (24*3600L)); + dt = deltat % (24*3600L); + hours = (int) (dt / 3600); + dt %= 3600; + minutes = (int) (dt / 60); + seconds = (int) (dt % 60); + + if (days == 0) + snprintf(buffer, buflen, "%d:%02d:%02d", hours, minutes, seconds); + else if (hours || minutes || seconds) + snprintf(buffer, buflen, "%d %s %02d:%02d:%02d", days, + (days > 1) ? "days" : "day", + hours, minutes, seconds); + else + snprintf(buffer, buflen, "%d %s", days, + (days > 1) ? "days" : "day"); + return 0; +} + +#undef __P +#define __P(X) X + +#ifndef HAVE_STRPTIME +#undef _CurrentTimeLocale +#define _CurrentTimeLocale (&dummy_locale_info) + +struct dummy_locale_info_t { + char d_t_fmt[15]; + char t_fmt_ampm[12]; + char t_fmt[9]; + char d_fmt[9]; + char day[7][10]; + char abday[7][4]; + char mon[12][10]; + char abmon[12][4]; + char am_pm[2][3]; +}; +static const struct dummy_locale_info_t dummy_locale_info = { + "%a %b %d %X %Y", /* %c */ + "%I:%M:%S %p", /* %r */ + "%H:%M:%S", /* %X */ + "%m/%d/%y", /* %x */ + { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", + "Saturday" }, + { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }, + { "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" }, + { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }, + { "AM", "PM" }, +}; +#undef TM_YEAR_BASE +#define TM_YEAR_BASE 1900 + +#include "strptime.c" +#endif diff --git a/krb5-1.21.3/src/lib/krb5/krb/strptime.c b/krb5-1.21.3/src/lib/krb5/krb/strptime.c new file mode 100644 index 00000000..22813f56 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/strptime.c @@ -0,0 +1,386 @@ +/* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t -*- */ +/* lib/krb5/krb/strptime.c */ +/* + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code was contributed to The NetBSD Foundation by Klaus Klein. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: strptime.c,v 1.18 1999/04/29 02:58:30 tv Exp $"); +#endif + +#include +#include +#include + +#undef _ctloc +#define _ctloc(x) _CurrentTimeLocale->x + +/* + * We do not implement alternate representations. However, we always + * check whether a given modifier is allowed for a certain conversion. + */ +#define ALT_E 0x01 +#define ALT_O 0x02 +#define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); } + + +static int conv_num __P((const char **, int *, int, int)); + + +static char * +strptime(buf, fmt, tm) + const char *buf, *fmt; + struct tm *tm; +{ + char c; + const char *bp; + size_t len = 0; + int alt_format, i, split_year = 0; + + bp = buf; + + while ((c = *fmt) != '\0') { + /* Clear `alternate' modifier prior to new conversion. */ + alt_format = 0; + + /* Eat up white-space. */ + if (isspace(c)) { + while (isspace(*bp)) + bp++; + + fmt++; + continue; + } + + if ((c = *fmt++) != '%') + goto literal; + + +again: switch (c = *fmt++) { + case '%': /* "%%" is converted to "%". */ +literal: + if (c != *bp++) + return (0); + break; + + /* + * "Alternative" modifiers. Just set the appropriate flag + * and start over again. + */ + case 'E': /* "%E?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_E; + goto again; + + case 'O': /* "%O?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_O; + goto again; + + /* + * "Complex" conversion rules, implemented through recursion. + */ + case 'c': /* Date and time, using the locale's format. */ + LEGAL_ALT(ALT_E); + if (!(bp = strptime(bp, _ctloc(d_t_fmt), tm))) + return (0); + break; + + case 'D': /* The date as "%m/%d/%y". */ + LEGAL_ALT(0); + if (!(bp = strptime(bp, "%m/%d/%y", tm))) + return (0); + break; + + case 'R': /* The time as "%H:%M". */ + LEGAL_ALT(0); + if (!(bp = strptime(bp, "%H:%M", tm))) + return (0); + break; + + case 'r': /* The time in 12-hour clock representation. */ + LEGAL_ALT(0); + if (!(bp = strptime(bp, _ctloc(t_fmt_ampm), tm))) + return (0); + break; + + case 'T': /* The time as "%H:%M:%S". */ + LEGAL_ALT(0); + if (!(bp = strptime(bp, "%H:%M:%S", tm))) + return (0); + break; + + case 'X': /* The time, using the locale's format. */ + LEGAL_ALT(ALT_E); + if (!(bp = strptime(bp, _ctloc(t_fmt), tm))) + return (0); + break; + + case 'x': /* The date, using the locale's format. */ + LEGAL_ALT(ALT_E); + if (!(bp = strptime(bp, _ctloc(d_fmt), tm))) + return (0); + break; + + /* + * "Elementary" conversion rules. + */ + case 'A': /* The day of week, using the locale's form. */ + case 'a': + LEGAL_ALT(0); + for (i = 0; i < 7; i++) { + /* Full name. */ + len = strlen(_ctloc(day[i])); + if (strncasecmp(_ctloc(day[i]), bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(_ctloc(abday[i])); + if (strncasecmp(_ctloc(abday[i]), bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 7) + return (0); + + tm->tm_wday = i; + bp += len; + break; + + case 'B': /* The month, using the locale's form. */ + case 'b': + case 'h': + LEGAL_ALT(0); + for (i = 0; i < 12; i++) { + /* Full name. */ + len = strlen(_ctloc(mon[i])); + if (strncasecmp(_ctloc(mon[i]), bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(_ctloc(abmon[i])); + if (strncasecmp(_ctloc(abmon[i]), bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 12) + return (0); + + tm->tm_mon = i; + bp += len; + break; + + case 'C': /* The century number. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) { + tm->tm_year = (tm->tm_year % 100) + (i * 100); + } else { + tm->tm_year = i * 100; + split_year = 1; + } + break; + + case 'd': /* The day of month. */ + case 'e': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_mday, 1, 31))) + return (0); + break; + + case 'k': /* The hour (24-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'H': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 0, 23))) + return (0); + break; + + case 'l': /* The hour (12-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'I': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 1, 12))) + return (0); + if (tm->tm_hour == 12) + tm->tm_hour = 0; + break; + + case 'j': /* The day of year. */ + LEGAL_ALT(0); + if (!(conv_num(&bp, &i, 1, 366))) + return (0); + tm->tm_yday = i - 1; + break; + + case 'M': /* The minute. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_min, 0, 59))) + return (0); + break; + + case 'm': /* The month. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &i, 1, 12))) + return (0); + tm->tm_mon = i - 1; + break; + + case 'p': /* The locale's equivalent of AM/PM. */ + LEGAL_ALT(0); + /* AM? */ + if (strcasecmp(_ctloc(am_pm[0]), bp) == 0) { + if (tm->tm_hour > 11) + return (0); + + bp += strlen(_ctloc(am_pm[0])); + break; + } + /* PM? */ + else if (strcasecmp(_ctloc(am_pm[1]), bp) == 0) { + if (tm->tm_hour > 11) + return (0); + + tm->tm_hour += 12; + bp += strlen(_ctloc(am_pm[1])); + break; + } + + /* Nothing matched. */ + return (0); + + case 'S': /* The seconds. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_sec, 0, 61))) + return (0); + break; + + case 'U': /* The week of year, beginning on sunday. */ + case 'W': /* The week of year, beginning on monday. */ + LEGAL_ALT(ALT_O); + /* + * XXX This is bogus, as we can not assume any valid + * information present in the tm structure at this + * point to calculate a real value, so just check the + * range for now. + */ + if (!(conv_num(&bp, &i, 0, 53))) + return (0); + break; + + case 'w': /* The day of week, beginning on sunday. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_wday, 0, 6))) + return (0); + break; + + case 'Y': /* The year. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 9999))) + return (0); + + tm->tm_year = i - TM_YEAR_BASE; + break; + + case 'y': /* The year within 100 years of the epoch. */ + LEGAL_ALT(ALT_E | ALT_O); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) { + tm->tm_year = ((tm->tm_year / 100) * 100) + i; + break; + } + split_year = 1; + if (i <= 68) + tm->tm_year = i + 2000 - TM_YEAR_BASE; + else + tm->tm_year = i + 1900 - TM_YEAR_BASE; + break; + + /* + * Miscellaneous conversions. + */ + case 'n': /* Any kind of white-space. */ + case 't': + LEGAL_ALT(0); + while (isspace(*bp)) + bp++; + break; + + + default: /* Unknown/unsupported conversion. */ + return (0); + } + + + } + + /* LINTED functional specification */ + return ((char *)bp); +} + + +static int +conv_num(buf, dest, llim, ulim) + const char **buf; + int *dest; + int llim, ulim; +{ + int result = 0; + + /* The limit also determines the number of valid digits. */ + int rulim = ulim; + + if (**buf < '0' || **buf > '9') + return (0); + + do { + result *= 10; + result += *(*buf)++ - '0'; + rulim /= 10; + } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); + + if (result < llim || result > ulim) + return (0); + + *dest = result; + return (1); +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_ad_fx_armor.c b/krb5-1.21.3/src/lib/krb5/krb/t_ad_fx_armor.c new file mode 100644 index 00000000..73dbb3a6 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_ad_fx_armor.c @@ -0,0 +1,37 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include +#include +#include + +#define test(x) do {retval = (x); \ + if(retval != 0) { \ + const char *errmsg = krb5_get_error_message(context, retval); \ + fprintf(stderr, "Error message: %s\n", errmsg); \ + abort(); } \ + } while(0); + +krb5_authdata ad_fx_armor = {0, KRB5_AUTHDATA_FX_ARMOR, 1, ""}; +krb5_authdata *array[] = {&ad_fx_armor, NULL}; + + +int main( int argc, char **argv) +{ + krb5_context context; + krb5_ccache ccache = NULL; + krb5_creds creds, *out_creds = NULL; + krb5_error_code retval = 0; + test(krb5_init_context(&context)); + memset(&creds, 0, sizeof(creds)); + creds.authdata = array; + test(krb5_cc_default(context, &ccache)); + test(krb5_cc_get_principal(context, ccache, &creds.client)); + test(krb5_parse_name(context, argv[1], &creds.server)); + test(krb5_get_credentials(context, 0, ccache, &creds, &out_creds)); + test(krb5_cc_destroy(context, ccache)); + test(krb5_cc_default(context, &ccache)); + test(krb5_cc_initialize(context, ccache, out_creds->client)); + test(krb5_cc_store_cred(context, ccache, out_creds)); + test(krb5_cc_close(context,ccache)); + return 0; + +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_authdata.c b/krb5-1.21.3/src/lib/krb5/krb/t_authdata.c new file mode 100644 index 00000000..dd834b9b --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_authdata.c @@ -0,0 +1,113 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/t_authdata.c - Test authorization data search */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include +#include + +krb5_authdata ad1 = { + KV5M_AUTHDATA, + 22, + 4, + (unsigned char *) "abcd"}; +krb5_authdata ad2 = { + KV5M_AUTHDATA, + 23, + 5, + (unsigned char *) "abcde" +}; + +krb5_authdata ad3= { + KV5M_AUTHDATA, + 22, + 3, + (unsigned char *) "ab" +}; +/* We want three results in the return from krb5_find_authdata so it has to + * grow its list. */ +krb5_authdata ad4 = { + KV5M_AUTHDATA, + 22, + 5, + (unsigned char *)"abcd" +}; + +krb5_authdata *adseq1[] = {&ad1, &ad2, &ad4, NULL}; + +krb5_authdata *adseq2[] = {&ad3, NULL}; + +krb5_keyblock key = { + KV5M_KEYBLOCK, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, + 16, + (unsigned char *)"1234567890ABCDEF" +}; + +static void compare_authdata(const krb5_authdata *adc1, krb5_authdata *adc2) { + assert(adc1->ad_type == adc2->ad_type); + assert(adc1->length == adc2->length); + assert(memcmp(adc1->contents, adc2->contents, adc1->length) == 0); +} + +int +main() +{ + krb5_context context; + krb5_authdata **results; + krb5_authdata *container[2]; + krb5_authdata **container_out; + krb5_authdata **kdci; + + assert(krb5_init_context(&context) == 0); + assert(krb5_merge_authdata(context, adseq1, adseq2, &results) == 0); + compare_authdata(results[0], &ad1); + compare_authdata( results[1], &ad2); + compare_authdata(results[2], &ad4); + compare_authdata( results[3], &ad3); + assert(results[4] == NULL); + krb5_free_authdata(context, results); + container[0] = &ad3; + container[1] = NULL; + assert(krb5_encode_authdata_container( context, KRB5_AUTHDATA_IF_RELEVANT, container, &container_out) == 0); + assert(krb5_find_authdata(context, adseq1, container_out, 22, + &results) == 0); + compare_authdata(&ad1, results[0]); + compare_authdata( results[1], &ad4); + compare_authdata( results[2], &ad3); + assert( results[3] == NULL); + krb5_free_authdata(context, container_out); + assert(krb5_make_authdata_kdc_issued(context, &key, NULL, results, &kdci) == 0); + assert(krb5_verify_authdata_kdc_issued(context, &key, kdci[0], NULL, &container_out) == 0); + compare_authdata(container_out[0], results[0]); + compare_authdata(container_out[1], results[1]); + compare_authdata(container_out[2], results[2]); + krb5_free_authdata(context, kdci); + krb5_free_authdata(context, results); + krb5_free_authdata(context, container_out); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_cc_config.c b/krb5-1.21.3/src/lib/krb5/krb/t_cc_config.c new file mode 100644 index 00000000..c2546d7a --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_cc_config.c @@ -0,0 +1,163 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* t_cc_config.c: read and write configuration items in ccaches */ +/* + * Copyright (C) 2012 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. + */ + +/* + * A test helper which either reads or writes a configuration setting from or + * to a credential cache, optionally for a specified server principal name. + */ + +#include +#include "int-proto.h" + +static void +bail_on_err(krb5_context context, const char *msg, krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(context, code); + printf("%s: %s\n", msg, errmsg); + krb5_free_error_message(context, errmsg); + exit(1); + } +} + +/* + * The default unset code path depends on the underlying ccache implementation + * knowing how to remove a credential, which most types don't actually support, + * so we have to jump through some hoops to ensure that when we set a value for + * a key, it'll be the only value for that key that'll be found later. The + * ccache portions of libkrb5 will currently duplicate some of the actual + * tickets. + */ +static void +unset_config(krb5_context context, krb5_ccache ccache, + krb5_principal server, const char *key) +{ + krb5_ccache tmp1, tmp2; + krb5_cc_cursor cursor; + krb5_creds mcreds, creds; + + memset(&mcreds, 0, sizeof(mcreds)); + memset(&creds, 0, sizeof(creds)); + bail_on_err(context, "Error while deriving configuration principal names", + k5_build_conf_principals(context, ccache, server, key, + &mcreds)); + bail_on_err(context, "Error resolving first in-memory ccache", + krb5_cc_resolve(context, "MEMORY:tmp1", &tmp1)); + bail_on_err(context, "Error initializing first in-memory ccache", + krb5_cc_initialize(context, tmp1, mcreds.client)); + bail_on_err(context, "Error resolving second in-memory ccache", + krb5_cc_resolve(context, "MEMORY:tmp2", &tmp2)); + bail_on_err(context, "Error initializing second in-memory ccache", + krb5_cc_initialize(context, tmp2, mcreds.client)); + bail_on_err(context, "Error copying credentials to first in-memory ccache", + krb5_cc_copy_creds(context, ccache, tmp1)); + bail_on_err(context, "Error starting traversal of first in-memory ccache", + krb5_cc_start_seq_get(context, tmp1, &cursor)); + while (krb5_cc_next_cred(context, tmp1, &cursor, &creds) == 0) { + if (!krb5_is_config_principal(context, creds.server) || + !krb5_principal_compare(context, mcreds.server, creds.server) || + !krb5_principal_compare(context, mcreds.client, creds.client)) { + bail_on_err(context, + "Error storing non-config item to in-memory ccache", + krb5_cc_store_cred(context, tmp2, &creds)); + } + krb5_free_cred_contents(context, &creds); + } + bail_on_err(context, "Error ending traversal of first in-memory ccache", + krb5_cc_end_seq_get(context, tmp1, &cursor)); + bail_on_err(context, "Error clearing ccache", + krb5_cc_initialize(context, ccache, mcreds.client)); + bail_on_err(context, "Error storing creds to the ccache", + krb5_cc_copy_creds(context, tmp2, ccache)); + bail_on_err(context, "Error cleaning up first in-memory ccache", + krb5_cc_destroy(context, tmp1)); + bail_on_err(context, "Error cleaning up second in-memory ccache", + krb5_cc_destroy(context, tmp2)); + krb5_free_principal(context, mcreds.client); + krb5_free_principal(context, mcreds.server); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_principal server; + krb5_ccache ccache; + krb5_data data; + krb5_error_code ret; + char *perr; + int c; + unsigned int i; + + bail_on_err(NULL, "Error initializing Kerberos library", + krb5_init_context(&context)); + bail_on_err(context, "Error getting location of default ccache", + krb5_cc_default(context, &ccache)); + server = NULL; + while ((c = getopt(argc, argv, "p:")) != -1) { + switch (c) { + case 'p': + if (asprintf(&perr, "Error parsing principal name \"%s\"", + optarg) < 0) + abort(); + bail_on_err(context, perr, + krb5_parse_name(context, optarg, &server)); + free(perr); + break; + } + } + if (argc - optind < 1 || argc - optind > 2) { + fprintf(stderr, "Usage: %s [-p principal] key [value]\n", argv[0]); + return 1; + } + memset(&data, 0, sizeof(data)); + if (argc - optind == 2) { + unset_config(context, ccache, server, argv[optind]); + data = string2data(argv[optind + 1]); + bail_on_err(context, "Error adding configuration data to ccache", + krb5_cc_set_config(context, ccache, server, argv[optind], + &data)); + } else { + ret = krb5_cc_get_config(context, ccache, server, argv[optind], &data); + if (ret == 0) { + for (i = 0; i < data.length; i++) + putc((unsigned int)data.data[i], stdout); + krb5_free_data_contents(context, &data); + } + } + krb5_free_principal(context, server); + krb5_cc_close(context, ccache); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_copy_context.c b/krb5-1.21.3/src/lib/krb5/krb/t_copy_context.c new file mode 100644 index 00000000..0a5f2a38 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_copy_context.c @@ -0,0 +1,157 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/t_copy_context.C - Test program for krb5_copy_context */ +/* + * 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. + */ + +#include + +static void +trace(krb5_context ctx, const krb5_trace_info *info, void *data) +{ +} + +static void +check(int cond) +{ + if (!cond) + abort(); +} + +static void +compare_string(const char *str1, const char *str2) +{ + check((str1 == NULL) == (str2 == NULL)); + if (str1 != NULL) + check(strcmp(str1, str2) == 0); +} + +static void +compare_etypes(krb5_enctype *list1, krb5_enctype *list2) +{ + check((list1 == NULL) == (list2 == NULL)); + if (list1 == NULL) + return; + while (*list1 != ENCTYPE_NULL && *list1 == *list2) + list1++, list2++; + check(*list1 == *list2); +} + +/* Check that the context c is a valid copy of the reference context r. */ +static void +check_context(krb5_context c, krb5_context r) +{ + int i; + + /* Check fields which should have been propagated from r. */ + compare_etypes(c->tgs_etypes, r->tgs_etypes); + check(c->os_context.time_offset == r->os_context.time_offset); + check(c->os_context.usec_offset == r->os_context.usec_offset); + check(c->os_context.os_flags == r->os_context.os_flags); + compare_string(c->os_context.default_ccname, r->os_context.default_ccname); + check(c->clockskew == r->clockskew); + check(c->kdc_default_options == r->kdc_default_options); + check(c->library_options == r->library_options); + check(c->profile_secure == r->profile_secure); + check(c->fcc_default_format == r->fcc_default_format); + check(c->udp_pref_limit == r->udp_pref_limit); + check(c->use_conf_ktypes == r->use_conf_ktypes); + check(c->allow_weak_crypto == r->allow_weak_crypto); + check(c->ignore_acceptor_hostname == r->ignore_acceptor_hostname); + check(c->enforce_ok_as_delegate == r->enforce_ok_as_delegate); + check(c->dns_canonicalize_hostname == r->dns_canonicalize_hostname); + compare_string(c->plugin_base_dir, r->plugin_base_dir); + + /* Check fields which don't propagate. */ + check(c->dal_handle == NULL); + check(c->prompt_types == NULL); + check(c->libkrb5_plugins.files == NULL); + check(c->preauth_context == NULL); + check(c->ccselect_handles == NULL); + check(c->localauth_handles == NULL); + check(c->hostrealm_handles == NULL); + check(c->err.code == 0); + check(c->err.msg == NULL); + check(c->kdblog_context == NULL); + check(c->trace_callback == NULL); + check(c->trace_callback_data == NULL); + for (i = 0; i < PLUGIN_NUM_INTERFACES; i++) { + check(c->plugins[i].modules == NULL); + check(!c->plugins[i].configured); + } +} + +int +main(int argc, char **argv) +{ + krb5_context ctx, ctx2; + krb5_plugin_initvt_fn *mods; + const krb5_enctype etypes[] = { ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 }; + krb5_prompt_type ptypes[] = { KRB5_PROMPT_TYPE_PASSWORD }; + + /* Copy a default context and verify the result. */ + check(krb5_init_context(&ctx) == 0); + check(krb5_copy_context(ctx, &ctx2) == 0); + check_context(ctx2, ctx); + krb5_free_context(ctx2); + + /* Set non-default values for all of the propagated fields in ctx. */ + ctx->allow_weak_crypto = TRUE; + check(krb5_set_default_tgs_enctypes(ctx, etypes) == 0); + check(krb5_set_debugging_time(ctx, 1234, 5678) == 0); + check(krb5_cc_set_default_name(ctx, "defccname") == 0); + check(krb5_set_default_realm(ctx, "defrealm") == 0); + ctx->clockskew = 18; + ctx->kdc_default_options = KDC_OPT_FORWARDABLE; + ctx->library_options = 0; + ctx->profile_secure = TRUE; + ctx->udp_pref_limit = 2345; + ctx->use_conf_ktypes = TRUE; + ctx->ignore_acceptor_hostname = TRUE; + ctx->enforce_ok_as_delegate = TRUE; + ctx->dns_canonicalize_hostname = CANONHOST_FALSE; + free(ctx->plugin_base_dir); + check((ctx->plugin_base_dir = strdup("/a/b/c/d")) != NULL); + + /* Also set some of the non-propagated fields. */ + ctx->prompt_types = ptypes; + check(k5_plugin_load_all(ctx, PLUGIN_INTERFACE_PWQUAL, &mods) == 0); + k5_plugin_free_modules(ctx, mods); + k5_setmsg(ctx, ENOMEM, "nooooooooo"); + krb5_set_trace_callback(ctx, trace, ctx); + + /* Copy the intentionally messy context and verify the result. */ + check(krb5_copy_context(ctx, &ctx2) == 0); + check_context(ctx2, ctx); + krb5_free_context(ctx2); + + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_deltat.c b/krb5-1.21.3/src/lib/krb5/krb/t_deltat.c new file mode 100644 index 00000000..e519ee80 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_deltat.c @@ -0,0 +1,157 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/t_deltat.c */ +/* + * Copyright 1999 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +int +main (void) +{ + struct { + char *string; + krb5_deltat expected; + int is_error; +#define GOOD(STR,VAL) { STR, VAL, 0 } +#define BAD(STR) { STR, 0, 1 } +#define DAY (24 * 3600) +#define HOUR 3600 +#ifdef MIN +#undef MIN +#endif +#define MIN 60 + } values[] = { + /* d-h-m-s patterns */ + GOOD ("3d", 3*DAY), + GOOD ("3h", 3*HOUR), + GOOD ("3m", 3*MIN), + GOOD ("3s", 3), + BAD ("3dd"), + GOOD ("3d4m 42s", 3 * DAY + 4 * MIN + 42), + GOOD ("3d-1h", 3 * DAY - 1 * HOUR), + GOOD ("3d -1h", 3 * DAY - HOUR), + GOOD ("3d4h5m6s", 3 * DAY + 4 * HOUR + 5 * MIN + 6), + BAD ("3d4m5h"), + GOOD ("12345s", 12345), + GOOD ("1m 12345s", MIN + 12345), + GOOD ("1m12345s", MIN + 12345), + GOOD ("3d 0m", 3 * DAY), + GOOD ("3d 0m ", 3 * DAY), + GOOD ("3d \n\t 0m ", 3 * DAY), + /* colon patterns */ + GOOD ("42-13:42:47", 42 * DAY + 13 * HOUR + 42 * MIN + 47), + BAD ("3: 4"), + BAD ("13:0003"), + GOOD ("12:34", 12 * HOUR + 34 * MIN), + GOOD ("1:02:03", 1 * HOUR + 2 * MIN + 3), + BAD ("3:-4"), + /* XX We might want to require exactly two digits after a colon? */ + GOOD ("3:4", 3 * HOUR + 4 * MIN), + /* misc */ + GOOD ("42", 42), + BAD ("1-2"), + /* Test overflow limitations */ + GOOD ("2147483647s", 2147483647), + BAD ("2147483648s"), + GOOD ("24855d", 24855 * DAY), + BAD ("24856d"), + BAD ("24855d 100000000h"), + GOOD ("24855d 3h", 24855 * DAY + 3 * HOUR), + BAD ("24855d 4h"), + GOOD ("24855d 11647s", 24855 * DAY + 11647), + BAD ("24855d 11648s"), + GOOD ("24855d 194m 7s", 24855 * DAY + 194 * MIN + 7), + BAD ("24855d 194m 8s"), + BAD ("24855d 195m"), + BAD ("24855d 19500000000m"), + GOOD ("24855d 3h 14m 7s", 24855 * DAY + 3 * HOUR + 14 * MIN + 7), + BAD ("24855d 3h 14m 8s"), + GOOD ("596523h", 596523 * HOUR), + BAD ("596524h"), + GOOD ("596523h 847s", 596523 * HOUR + 847), + BAD ("596523h 848s"), + GOOD ("596523h 14m 7s", 596523 * HOUR + 14 * MIN + 7), + BAD ("596523h 14m 8s"), + GOOD ("35791394m", 35791394 * MIN), + GOOD ("35791394m7s", 35791394 * MIN + 7), + BAD ("35791394m8s"), + /* Test underflow */ + GOOD ("-2147483647s", -2147483647), + /* This should be valid, but isn't */ + /*BAD ("-2147483648s"),*/ + GOOD ("-24855d", -24855 * DAY), + BAD ("-24856d"), + BAD ("-24855d -100000000h"), + GOOD ("-24855d -3h", -24855 * DAY - 3 * HOUR), + BAD ("-24855d -4h"), + GOOD ("-24855d -11647s", -24855 * DAY - 11647), + BAD ("-24855d -11649s"), + GOOD ("-24855d -194m -7s", -24855 * DAY - 194 * MIN - 7), + BAD ("-24855d -194m -9s"), + BAD ("-24855d -195m"), + BAD ("-24855d -19500000000m"), + GOOD ("-24855d -3h -14m -7s", -24855 * DAY - 3 * HOUR - 14 * MIN - 7), + BAD ("-24855d -3h -14m -9s"), + GOOD ("-596523h", -596523 * HOUR), + BAD ("-596524h"), + GOOD ("-596523h -847s", -596523 * HOUR - 847), + GOOD ("-596523h -848s", -596523 * HOUR - 848), + BAD ("-596523h -849s"), + GOOD ("-596523h -14m -8s", -596523 * HOUR - 14 * MIN - 8), + BAD ("-596523h -14m -9s"), + GOOD ("-35791394m", -35791394 * MIN), + GOOD ("-35791394m7s", -35791394 * MIN + 7), + BAD ("-35791394m-9s"), + + }; + int fail = 0; + size_t i; + + for (i = 0; i < sizeof(values)/sizeof(values[0]); i++) { + krb5_deltat result; + krb5_error_code code; + + code = krb5_string_to_deltat (values[i].string, &result); + if (code && !values[i].is_error) { + fprintf (stderr, "unexpected error for `%s'\n", values[i].string); + fail++; + } else if (!code && values[i].is_error) { + fprintf (stderr, "expected but didn't get error for `%s'\n", + values[i].string); + fail++; + } else if (code && values[i].is_error) { + /* do nothing */ + } else if (result != values[i].expected) { + fprintf (stderr, "got %ld instead of expected %ld for `%s'\n", + (long) result, (long) values[i].expected, + values[i].string); + fail++; + } + } + if (fail == 0) + printf ("Passed all %d tests.\n", (int)i); + else + printf ("Failed %d of %d tests.\n", fail, (int)i); + return fail; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_etypes.c b/krb5-1.21.3/src/lib/krb5/krb/t_etypes.c new file mode 100644 index 00000000..90c9f626 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_etypes.c @@ -0,0 +1,230 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/t_etypes.c - test program for krb5int_parse_enctype_list */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include +#include "com_err.h" + +static struct { + const char *str; + krb5_enctype defaults[64]; + krb5_enctype expected_noweak[64]; + krb5_enctype expected[64]; + krb5_error_code expected_err_noweak; + krb5_error_code expected_err_weak; +} tests[] = { + /* Single non-weak enctype */ + { "aes128-cts-hmac-sha1-96", + { 0 }, + { ENCTYPE_AES128_CTS_HMAC_SHA1_96, 0 }, + { ENCTYPE_AES128_CTS_HMAC_SHA1_96, 0 }, + 0, 0 + }, + /* Default set with enctypes removed */ + { "default -aes128-cts -des-hmac-sha1", + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, 0 }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 }, + 0, 0 + }, + /* Family followed by enctype */ + { "aes des3-cbc-sha1-kd", + { 0 }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_AES256_CTS_HMAC_SHA384_192, ENCTYPE_AES128_CTS_HMAC_SHA256_128, + ENCTYPE_DES3_CBC_SHA1, 0 }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_AES256_CTS_HMAC_SHA384_192, ENCTYPE_AES128_CTS_HMAC_SHA256_128, + ENCTYPE_DES3_CBC_SHA1, 0 }, + 0, 0 + }, + /* Family with enctype removed */ + { "camellia -camellia256-cts-cmac", + { 0 }, + { ENCTYPE_CAMELLIA128_CTS_CMAC, 0 }, + { ENCTYPE_CAMELLIA128_CTS_CMAC, 0 } + }, + /* Default set with family added and enctype removed */ + { "DEFAULT +aes -arcfour-hmac-md5", + { ENCTYPE_ARCFOUR_HMAC, ENCTYPE_DES3_CBC_SHA1, 0 }, + { ENCTYPE_DES3_CBC_SHA1, ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, ENCTYPE_AES256_CTS_HMAC_SHA384_192, + ENCTYPE_AES128_CTS_HMAC_SHA256_128, 0 }, + { ENCTYPE_DES3_CBC_SHA1, + ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_AES256_CTS_HMAC_SHA384_192, ENCTYPE_AES128_CTS_HMAC_SHA256_128, + 0 }, + 0, 0 + }, + /* Default set with families removed and enctypes added (one redundant) */ + { "DEFAULT -des3 rc4-hmac rc4-hmac-exp", + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_DES3_CBC_SHA1, ENCTYPE_ARCFOUR_HMAC, 0 }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_ARCFOUR_HMAC, 0 }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_ARCFOUR_HMAC, ENCTYPE_ARCFOUR_HMAC_EXP, 0 }, + 0, 0 + }, + /* Default set with family moved to front */ + { "des3 +DEFAULT", + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_DES3_CBC_SHA1, 0 }, + { ENCTYPE_DES3_CBC_SHA1, ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, 0 }, + { ENCTYPE_DES3_CBC_SHA1, ENCTYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_AES128_CTS_HMAC_SHA1_96, 0 }, + 0, 0 + }, + /* Two families with default set removed (exotic case), enctype added */ + { "aes +rc4 -DEFaulT des3-hmac-sha1", + { ENCTYPE_AES128_CTS_HMAC_SHA1_96, ENCTYPE_DES3_CBC_SHA1, + ENCTYPE_ARCFOUR_HMAC, 0 }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES256_CTS_HMAC_SHA384_192, + ENCTYPE_AES128_CTS_HMAC_SHA256_128, ENCTYPE_DES3_CBC_SHA1, 0 }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, ENCTYPE_AES256_CTS_HMAC_SHA384_192, + ENCTYPE_AES128_CTS_HMAC_SHA256_128, ENCTYPE_DES3_CBC_SHA1, 0 }, + 0, 0 + }, + /* Test krb5_set_default_in_tkt_ktypes */ + { NULL, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, 0 }, + 0, 0 + }, + /* Should get KRB5_CONFIG_ETYPE_NOSUPP if app-provided list has no strong + * enctypes and allow_weak_crypto=false. */ + { NULL, + { ENCTYPE_ARCFOUR_HMAC_EXP, 0 }, + { 0 }, + { ENCTYPE_ARCFOUR_HMAC_EXP, 0 }, + KRB5_CONFIG_ETYPE_NOSUPP, 0 + }, + /* Should get EINVAL if app provides an empty list. */ + { NULL, + { 0 }, + { 0 }, + { 0 }, + EINVAL, EINVAL + } +}; + +static void +show_enctypes(krb5_context ctx, krb5_enctype *list) +{ + unsigned int i; + + for (i = 0; list[i]; i++) { + fprintf(stderr, "%d", (int) list[i]); + if (list[i + 1]) + fprintf(stderr, " "); + } + fprintf(stderr, "\n"); +} + +static void +compare(krb5_context ctx, krb5_enctype *result, krb5_enctype *expected, + const char *profstr, krb5_boolean weak) +{ + unsigned int i; + + if (!result) + return; + for (i = 0; result[i]; i++) { + if (result[i] != expected[i]) + break; + } + if (!result[i] && !expected[i]) /* Success! */ + return; + if (profstr != NULL) + fprintf(stderr, "Unexpected result while parsing: %s\n", profstr); + fprintf(stderr, "Expected: "); + show_enctypes(ctx, expected); + fprintf(stderr, "Result: "); + show_enctypes(ctx, result); + fprintf(stderr, "allow_weak_crypto was %s\n", weak ? "true" : "false"); + exit(1); +} + +int +main(int argc, char **argv) +{ + krb5_context ctx; + krb5_error_code ret, expected_err; + krb5_enctype *list; + krb5_boolean weak; + unsigned int i; + char *copy; + + ret = krb5_init_context(&ctx); + if (ret) { + com_err("krb5_init_context", ret, ""); + return 2; + } + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { + for (weak = FALSE; weak <= TRUE; weak++) { + ctx->allow_weak_crypto = weak; + if (weak) + expected_err = tests[i].expected_err_weak; + else + expected_err = tests[i].expected_err_noweak; + + if (tests[i].str != NULL) { + copy = strdup(tests[i].str); + ret = krb5int_parse_enctype_list(ctx, "", copy, + tests[i].defaults, &list); + if (ret != expected_err) { + com_err("krb5int_parse_enctype_list", ret, ""); + return 2; + } + } else { + /* No string; test the filtering on the set_default_etype_var + * instead. */ + copy = NULL; + list = NULL; + ret = krb5_set_default_tgs_enctypes(ctx, tests[i].defaults); + if (ret != expected_err) { + com_err("krb5_set_default_in_tkt_ktypes", ret, ""); + return 2; + } + } + if (!expected_err) { + compare(ctx, tests[i].str ? list : ctx->tgs_etypes, + (weak) ? tests[i].expected : tests[i].expected_noweak, + tests[i].str, weak); + } + free(copy); + free(list); + if (!tests[i].str) + krb5_set_default_tgs_enctypes(ctx, NULL); + } + } + + krb5_free_context(ctx); + + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_expand.c b/krb5-1.21.3/src/lib/krb5/krb/t_expand.c new file mode 100644 index 00000000..b108e4bb --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_expand.c @@ -0,0 +1,3 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#define TEST +#include "chk_trans.c" diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_expire_warn.c b/krb5-1.21.3/src/lib/krb5/krb/t_expire_warn.c new file mode 100644 index 00000000..dc8dc8fb --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_expire_warn.c @@ -0,0 +1,106 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/t_expire_warn.c - Test harness for password expiry warnings */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" + +static int exp_dummy, prompt_dummy; + +static void +check(krb5_error_code code) +{ + if (code != 0) + abort(); +} + +static krb5_error_code +prompter_cb(krb5_context ctx, void *data, const char *name, + const char *banner, int num_prompts, krb5_prompt prompts[]) +{ + /* Not expecting any actual prompts, only banners. */ + assert(num_prompts == 0); + assert(banner != NULL); + printf("Prompter: %s\n", banner); + return 0; +} + +static void +expire_cb(krb5_context ctx, void *data, krb5_timestamp password_expiration, + krb5_timestamp account_expiration, krb5_boolean is_last_req) +{ + printf("password_expiration = %ld\n", (long)password_expiration); + printf("account_expiration = %ld\n", (long)account_expiration); + printf("is_last_req = %d\n", (int)is_last_req); +} + +int +main(int argc, char **argv) +{ + krb5_context ctx; + krb5_init_creds_context icctx; + krb5_get_init_creds_opt *opt; + char *user, *password, *service = NULL; + krb5_boolean use_cb, stepwise; + krb5_principal client; + krb5_creds creds; + + if (argc < 5) { + fprintf(stderr, "Usage: %s username password {1|0} {1|0} [service]\n", + argv[0]); + return 1; + } + user = argv[1]; + password = argv[2]; + use_cb = atoi(argv[3]); + stepwise = atoi(argv[4]); + if (argc >= 6) + service = argv[5]; + + check(krb5_init_context(&ctx)); + check(krb5_get_init_creds_opt_alloc(ctx, &opt)); + if (use_cb) { + check(krb5_get_init_creds_opt_set_expire_callback(ctx, opt, expire_cb, + &exp_dummy)); + } + check(krb5_parse_name(ctx, user, &client)); + if (stepwise) { + check(krb5_init_creds_init(ctx, client, prompter_cb, &prompt_dummy, 0, + opt, &icctx)); + krb5_init_creds_set_password(ctx, icctx, password); + if (service != NULL) + check(krb5_init_creds_set_service(ctx, icctx, service)); + check(krb5_init_creds_get(ctx, icctx)); + krb5_init_creds_free(ctx, icctx); + } else { + check(krb5_get_init_creds_password(ctx, &creds, client, password, + prompter_cb, &prompt_dummy, 0, + service, opt)); + krb5_free_cred_contents(ctx, &creds); + } + krb5_get_init_creds_opt_free(ctx, opt); + krb5_free_principal(ctx, client); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_expire_warn.py b/krb5-1.21.3/src/lib/krb5/krb/t_expire_warn.py new file mode 100755 index 00000000..e163cc7e --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_expire_warn.py @@ -0,0 +1,68 @@ +# Copyright (C) 2010 by the Massachusetts Institute of Technology. +# All rights reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +from k5test import * + +# Create a bare-bones KDC. +realm = K5Realm(create_user=False, create_host=False) + +# Create principals with various password expirations. +realm.run([kadminl, 'addprinc', '-pw', 'pass', 'noexpire']) +realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '30 minutes', + 'minutes']) +realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '12 hours', + 'hours']) +realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '3 days', 'days']) + +# Check for expected prompter warnings when no expire callback is used. +output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '0', '0']) +if output: + fail('Unexpected output for noexpire') +realm.run(['./t_expire_warn', 'minutes', 'pass', '0', '0'], + expected_msg=' less than one hour on ') +realm.run(['./t_expire_warn', 'hours', 'pass', '0', '0'], + expected_msg=' hours on ') +realm.run(['./t_expire_warn', 'days', 'pass', '0', '0'], + expected_msg=' days on ') +# Try one case with the stepwise interface. +realm.run(['./t_expire_warn', 'days', 'pass', '0', '1'], + expected_msg=' days on ') + +# Check for expected expire callback behavior. These tests are +# carefully agnostic about whether the KDC supports last_req fields, +# and could be made more specific if last_req support is added. +output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '1', '0']) +if 'password_expiration = 0\n' not in output or \ + 'account_expiration = 0\n' not in output or \ + 'is_last_req = ' not in output: + fail('Expected callback output not seen for noexpire') +output = realm.run(['./t_expire_warn', 'days', 'pass', '1', '0']) +if 'password_expiration = ' not in output or \ + 'password_expiration = 0\n' in output: + fail('Expected non-zero password expiration not seen for days') +# Try one case with the stepwise interface. +output = realm.run(['./t_expire_warn', 'days', 'pass', '1', '1']) +if 'password_expiration = ' not in output or \ + 'password_expiration = 0\n' in output: + fail('Expected non-zero password expiration not seen for days') + +success('Password expiration warning tests') diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_get_etype_info.c b/krb5-1.21.3/src/lib/krb5/krb/t_get_etype_info.c new file mode 100644 index 00000000..041c3499 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_get_etype_info.c @@ -0,0 +1,110 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/krb5/krb/t_get_etype_info.c - test harness for krb5_get_etype_info() */ +/* + * Copyright (C) 2018 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. + */ + +#include "k5-platform.h" +#include "k5-hex.h" +#include + +int +main(int argc, char **argv) +{ + krb5_error_code ret; + krb5_context context; + krb5_principal princ; + krb5_get_init_creds_opt *opt = NULL; + krb5_enctype *etypes = NULL, *newptr, etype; + krb5_data salt, s2kparams; + const char *armor_ccache = NULL, *msg; + char buf[128], *hex; + int c, netypes = 0; + + while ((c = getopt(argc, argv, "e:T:")) != -1) { + switch (c) { + case 'e': + newptr = realloc(etypes, (netypes + 1) * sizeof(*etypes)); + assert(newptr != NULL); + etypes = newptr; + ret = krb5_string_to_enctype(optarg, &etypes[netypes]); + assert(!ret); + netypes++; + break; + case 'T': + armor_ccache = optarg; + break; + } + } + assert(argc == optind + 1); + + ret = krb5_init_context(&context); + assert(!ret); + ret = krb5_parse_name(context, argv[optind], &princ); + assert(!ret); + if (netypes > 0 || armor_ccache != NULL) { + ret = krb5_get_init_creds_opt_alloc(context, &opt); + assert(!ret); + if (netypes > 0) + krb5_get_init_creds_opt_set_etype_list(opt, etypes, netypes); + if (armor_ccache != NULL) { + ret = krb5_get_init_creds_opt_set_fast_ccache_name(context, opt, + armor_ccache); + assert(!ret); + } + } + ret = krb5_get_etype_info(context, princ, opt, &etype, &salt, &s2kparams); + if (ret) { + msg = krb5_get_error_message(context, ret); + fprintf(stderr, "%s\n", msg); + krb5_free_error_message(context, msg); + exit(1); + } else if (etype == ENCTYPE_NULL) { + printf("no etype-info\n"); + } else { + ret = krb5_enctype_to_name(etype, TRUE, buf, sizeof(buf)); + assert(!ret); + printf("etype: %s\n", buf); + printf("salt: %.*s\n", (int)salt.length, salt.data); + if (s2kparams.length > 0) { + ret = k5_hex_encode(s2kparams.data, s2kparams.length, TRUE, &hex); + assert(!ret); + printf("s2kparams: %s\n", hex); + free(hex); + } + } + + krb5_free_data_contents(context, &salt); + krb5_free_data_contents(context, &s2kparams); + krb5_free_principal(context, princ); + krb5_get_init_creds_opt_free(context, opt); + krb5_free_context(context); + free(etypes); + return 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_get_etype_info.py b/krb5-1.21.3/src/lib/krb5/krb/t_get_etype_info.py new file mode 100644 index 00000000..3c916859 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_get_etype_info.py @@ -0,0 +1,56 @@ +from k5test import * + +conf = {'libdefaults': {'allow_weak_crypto': 'true'}} +realm = K5Realm(create_host=False, krb5_conf=conf) + +realm.run([kadminl, 'ank', '-pw', 'pw', '+preauth', 'puser']) +realm.run([kadminl, 'ank', '-nokey', 'nokey']) +realm.run([kadminl, 'ank', '-nokey', '+preauth', 'pnokey']) +realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw', 'exp']) +realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw', '+preauth', + 'pexp']) + +# Extract the explicit salt values from the database. +out = realm.run([kdb5_util, 'tabdump', 'keyinfo']) +salt_dict = {f[0]: f[5] for f in [l.split('\t') for l in out.splitlines()]} +exp_salt = bytes.fromhex(salt_dict['exp@KRBTEST.COM']).decode('ascii') +pexp_salt = bytes.fromhex(salt_dict['pexp@KRBTEST.COM']).decode('ascii') + +# Test an error reply (other than PREAUTH_REQUIRED). +out = realm.run(['./t_get_etype_info', 'notfound'], expected_code=1, + expected_msg='Client not found in Kerberos database') + +# Test with default salt and no specific options, with and without +# preauth. (Our KDC always sends an explicit salt, so unfortunately +# we aren't really testing client handling of the default salt.) +realm.run(['./t_get_etype_info', 'user'], + expected_msg='etype: aes256-cts\nsalt: KRBTEST.COMuser\n') +realm.run(['./t_get_etype_info', 'puser'], + expected_msg='etype: aes256-cts\nsalt: KRBTEST.COMpuser\n') + +# Test with a specified request enctype. +msg = 'etype: aes128-cts\nsalt: KRBTEST.COMuser\n' +realm.run(['./t_get_etype_info', '-e', 'aes128-cts', 'user'], + expected_msg='etype: aes128-cts\nsalt: KRBTEST.COMuser\n') +realm.run(['./t_get_etype_info', '-e', 'aes128-cts', 'puser'], + expected_msg='etype: aes128-cts\nsalt: KRBTEST.COMpuser\n') + +# Test with FAST. +msg = 'etype: aes256-cts\nsalt: KRBTEST.COMuser\n' +realm.run(['./t_get_etype_info', '-T', realm.ccache, 'user'], + expected_msg='etype: aes256-cts\nsalt: KRBTEST.COMuser\n') +realm.run(['./t_get_etype_info', '-T', realm.ccache, 'puser'], + expected_msg='etype: aes256-cts\nsalt: KRBTEST.COMpuser\n') + +# Test with no available etype-info. +realm.run(['./t_get_etype_info', 'nokey'], expected_code=1, + expected_msg='KDC has no support for encryption type') +realm.run(['./t_get_etype_info', 'pnokey'], expected_msg='no etype-info') + +# Test with explicit salt. +realm.run(['./t_get_etype_info', 'exp'], + expected_msg='etype: aes256-cts\nsalt: ' + exp_salt + '\n') +realm.run(['./t_get_etype_info', 'pexp'], + expected_msg='etype: aes256-cts\nsalt: ' + pexp_salt + '\n') + +success('krb5_get_etype_info() tests') diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_in_ccache.c b/krb5-1.21.3/src/lib/krb5/krb/t_in_ccache.c new file mode 100644 index 00000000..3f157a48 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_in_ccache.c @@ -0,0 +1,149 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* t_in_ccache.c: get creds while using input and/or armor ccaches */ +/* + * Copyright (C) 2012 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. + */ + +/* + * A test helper that exercises the input-ccache option, potentially in + * combination with armor-ccache options. + */ + +#include "k5-int.h" + +static void +bail_on_err(krb5_context context, const char *msg, krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(context, code); + printf("%s: %s\n", msg, errmsg); + krb5_free_error_message(context, errmsg); + exit(1); + } +} + +static krb5_error_code +prompter_cb(krb5_context ctx, void *data, const char *name, + const char *banner, int num_prompts, krb5_prompt prompts[]) +{ + /* Not expecting any actual prompts. */ + if (num_prompts != 0) { + printf("too many prompts passed to prompter callback (%d), failing\n", + num_prompts); + exit(1); + } + return 0; +} + +int +main(int argc, char **argv) +{ + krb5_context ctx; + krb5_ccache in_ccache, out_ccache, armor_ccache; + krb5_get_init_creds_opt *opt; + char *user, *password, *armor_ccname = NULL, *in_ccname = NULL, *perr; + const char *err; + krb5_principal client; + krb5_creds creds; + krb5_flags fast_flags; + krb5_error_code ret; + int c; + + while ((c = getopt(argc, argv, "I:A:")) != -1) { + switch (c) { + case 'A': + armor_ccname = optarg; + break; + case 'I': + in_ccname = optarg; + break; + } + } + if (argc - optind < 2) { + fprintf(stderr, "Usage: %s [-A armor_ccache] [-I in_ccache] " + "username password\n", argv[0]); + return 1; + } + user = argv[optind]; + password = argv[optind + 1]; + + bail_on_err(NULL, "Error initializing Kerberos", krb5_init_context(&ctx)); + bail_on_err(ctx, "Error allocating space for get_init_creds options", + krb5_get_init_creds_opt_alloc(ctx, &opt)); + if (in_ccname != NULL) { + bail_on_err(ctx, "Error resolving input ccache", + krb5_cc_resolve(ctx, in_ccname, &in_ccache)); + bail_on_err(ctx, "Error setting input_ccache option", + krb5_get_init_creds_opt_set_in_ccache(ctx, opt, + in_ccache)); + } else { + in_ccache = NULL; + } + if (armor_ccname != NULL) { + bail_on_err(ctx, "Error resolving armor ccache", + krb5_cc_resolve(ctx, armor_ccname, &armor_ccache)); + bail_on_err(ctx, "Error setting fast_ccache option", + krb5_get_init_creds_opt_set_fast_ccache(ctx, opt, + armor_ccache)); + fast_flags = KRB5_FAST_REQUIRED; + bail_on_err(ctx, "Error setting option to force use of FAST", + krb5_get_init_creds_opt_set_fast_flags(ctx, opt, + fast_flags)); + } else { + armor_ccache = NULL; + } + bail_on_err(ctx, "Error resolving output (default) ccache", + krb5_cc_default(ctx, &out_ccache)); + bail_on_err(ctx, "Error setting output ccache option", + krb5_get_init_creds_opt_set_out_ccache(ctx, opt, out_ccache)); + if (asprintf(&perr, "Error parsing principal name \"%s\"", user) < 0) + abort(); + bail_on_err(ctx, perr, krb5_parse_name(ctx, user, &client)); + ret = krb5_get_init_creds_password(ctx, &creds, client, password, + prompter_cb, NULL, 0, NULL, opt); + if (ret) { + err = krb5_get_error_message(ctx, ret); + printf("%s\n", err); + krb5_free_error_message(ctx, err); + } else { + krb5_free_cred_contents(ctx, &creds); + } + krb5_get_init_creds_opt_free(ctx, opt); + krb5_free_principal(ctx, client); + krb5_cc_close(ctx, out_ccache); + if (armor_ccache != NULL) + krb5_cc_close(ctx, armor_ccache); + if (in_ccache != NULL) + krb5_cc_close(ctx, in_ccache); + krb5_free_context(ctx); + free(perr); + return ret ? (ret - KRB5KDC_ERR_NONE) : 0; +} diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_in_ccache_patypes.py b/krb5-1.21.3/src/lib/krb5/krb/t_in_ccache_patypes.py new file mode 100755 index 00000000..b2812688 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_in_ccache_patypes.py @@ -0,0 +1,84 @@ +# Copyright (C) 2010,2012 by the Massachusetts Institute of Technology. +# All rights reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +from k5test import * + +# Create a bare-bones KDC. +realm = K5Realm(create_user=False, create_host=False) + +# Create principals with various password expirations. +realm.run([kadminl, 'addprinc', '-pw', 'pass', 'nopreauth']) +realm.run([kadminl, 'addprinc', '-pw', 'pass', '+requires_preauth', 'preauth']) + +# Check that we can get creds without preauth without an in_ccache. This is +# the default behavior for kinit. +realm.run(['./t_in_ccache', 'nopreauth', 'pass']) + +# Check that we can get creds with preauth without an in_ccache. This is the +# default behavior for kinit. +realm.run(['./t_in_ccache', 'preauth', 'pass']) + +# Check that we can get creds while supplying a now-populated input ccache that +# doesn't contain any relevant configuration. +realm.run(['./t_in_ccache', 'nopreauth', 'pass']) +realm.run(['./t_in_ccache', '-I', realm.ccache, 'preauth', 'pass']) + +# Check that we can get creds while supplying a now-populated input ccache. +realm.run(['./t_in_ccache', 'preauth', 'pass']) +realm.run(['./t_in_ccache', '-I', realm.ccache, 'preauth', 'pass']) + +# Check that we can't get creds while specifying patypes that aren't available +# in a FAST tunnel while using a FAST tunnel. Expect the client-end +# preauth-failed error. +realm.run(['./t_in_ccache', 'nopreauth', 'pass']) +realm.run(['./t_cc_config', '-p', realm.krbtgt_princ, 'pa_type', '2']) +realm.run(['./t_in_ccache', '-A', realm.ccache, '-I', realm.ccache, + 'preauth', 'pass'], expected_code=210) + +# Check that we can't get creds while specifying patypes that are only +# available in a FAST tunnel while not using a FAST tunnel. Expect the +# client-end preauth-failed error. +realm.run(['./t_in_ccache', 'nopreauth', 'pass']) +realm.run(['./t_cc_config', '-p', realm.krbtgt_princ, 'pa_type', '138']) +realm.run(['./t_in_ccache', '-I', realm.ccache, 'preauth', 'pass'], + expected_code=210) + +# Check that we can get creds using FAST, and that we end up using +# encrypted_challenge when we do. +realm.run(['./t_in_ccache', 'preauth', 'pass']) +realm.run(['./t_cc_config', '-p', realm.krbtgt_princ, 'pa_type', '138']) +realm.run(['./t_in_ccache', '-A', realm.ccache, 'preauth', 'pass']) +output = realm.run(['./t_cc_config', '-p', realm.krbtgt_princ, 'pa_type']) +# We should have selected and used encrypted_challenge. +if output != '138': + fail('Unexpected pa_type value in out_ccache: "%s"' % output) + +# Check that we can get creds while specifying the right patypes. +realm.run(['./t_in_ccache', 'nopreauth', 'pass']) +realm.run(['./t_cc_config', '-p', realm.krbtgt_princ, 'pa_type', '2']) +realm.run(['./t_in_ccache', '-I', realm.ccache, 'preauth', 'pass']) +output = realm.run(['./t_cc_config', '-p', realm.krbtgt_princ, 'pa_type']) +# We should have selected and used encrypted_timestamp. +if output != '2': + fail('Unexpected pa_type value in out_ccache') + +success('input ccache pa_type tests') diff --git a/krb5-1.21.3/src/lib/krb5/krb/t_kerb.c b/krb5-1.21.3/src/lib/krb5/krb/t_kerb.c new file mode 100644 index 00000000..e8c42ab5 --- /dev/null +++ b/krb5-1.21.3/src/lib/krb5/krb/t_kerb.c @@ -0,0 +1,248 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * This driver routine is used to test many of the standard Kerberos library + * routines. + */ + +#include "autoconf.h" +#include "k5-int.h" +#include + +#include "com_err.h" + +void test_string_to_timestamp (krb5_context, char *); +void test_425_conv_principal (krb5_context, char *, char*, char *); +void test_524_conv_principal (krb5_context, char *); +void test_parse_name (krb5_context, const char *); +void test_name_type (krb5_context, const char *); +void test_set_realm (krb5_context, const char *, const char *); +void usage (char *); + +void +test_string_to_timestamp(krb5_context ctx, char *ktime) +{ + krb5_timestamp timestamp; + time_t t; + krb5_error_code retval; + + retval = krb5_string_to_timestamp(ktime, ×tamp); + if (retval) { + com_err("krb5_string_to_timestamp", retval, 0); + return; + } + t = ts2tt(timestamp); + printf("Parsed time was %s", ctime(&t)); +} + +void +test_425_conv_principal(krb5_context ctx, char *name, char *inst, char *realm) +{ + krb5_error_code retval; + krb5_principal princ; + char *out_name; + + retval = krb5_425_conv_principal(ctx, name, inst, realm, &princ); + if (retval) { + com_err("krb5_425_conv_principal", retval, 0); + return; + } + retval = krb5_unparse_name(ctx, princ, &out_name); + if (retval) { + com_err("krb5_unparse_name", retval, 0); + return; + } + printf("425_converted principal(%s, %s, %s): '%s'\n", + name, inst, realm, out_name); + free(out_name); + krb5_free_principal(ctx, princ); +} + +void +test_524_conv_principal(krb5_context ctx, char *name) +{ + krb5_principal princ = 0; + krb5_error_code retval; +#define ANAME_SZ 40 +#define INST_SZ 40 +#define REALM_SZ 40 + char aname[ANAME_SZ+1], inst[INST_SZ+1], realm[REALM_SZ+1]; + + aname[ANAME_SZ] = inst[INST_SZ] = realm[REALM_SZ] = 0; + retval = krb5_parse_name(ctx, name, &princ); + if (retval) { + com_err("krb5_parse_name", retval, 0); + goto fail; + } + retval = krb5_524_conv_principal(ctx, princ, aname, inst, realm); + if (retval) { + com_err("krb5_524_conv_principal", retval, 0); + goto fail; + } + printf("524_converted_principal(%s): '%s' '%s' '%s'\n", + name, aname, inst, realm); +fail: + if (princ) + krb5_free_principal (ctx, princ); +} + +void +test_parse_name(krb5_context ctx, const char *name) +{ + krb5_error_code retval; + krb5_principal princ = 0, princ2 = 0; + char *outname = 0; + + retval = krb5_parse_name(ctx, name, &princ); + if (retval) { + com_err("krb5_parse_name", retval, 0); + goto fail; + } + retval = krb5_copy_principal(ctx, princ, &princ2); + if (retval) { + com_err("krb5_copy_principal", retval, 0); + goto fail; + } + retval = krb5_unparse_name(ctx, princ2, &outname); + if (retval) { + com_err("krb5_unparse_name", retval, 0); + goto fail; + } + printf("parsed (and unparsed) principal(%s): ", name); + if (strcmp(name, outname) == 0) + printf("MATCH\n"); + else + printf("'%s'\n", outname); +fail: + if (outname) + free(outname); + if (princ) + krb5_free_principal(ctx, princ); + if (princ2) + krb5_free_principal(ctx, princ2); +} + +void +test_name_type(krb5_context ctx, const char *name) +{ + krb5_error_code retval; + krb5_principal princ = 0; + + retval = krb5_parse_name(ctx, name, &princ); + if (retval) { + com_err("krb5_parse_name", retval, 0); + return; + } + printf("name_type principal(%s): %d\n", name, krb5_princ_type(ctx, princ)); + krb5_free_principal(ctx, princ); +} + +void +test_set_realm(krb5_context ctx, const char *name, const char *realm) +{ + krb5_error_code retval; + krb5_principal princ = 0; + char *outname = 0; + + retval = krb5_parse_name(ctx, name, &princ); + if (retval) { + com_err("krb5_parse_name", retval, 0); + goto fail; + } + retval = krb5_set_principal_realm(ctx, princ, realm); + if (retval) { + com_err("krb5_set_principal_realm", retval, 0); + goto fail; + } + retval = krb5_unparse_name(ctx, princ, &outname); + if (retval) { + com_err("krb5_unparse_name", retval, 0); + goto fail; + } + printf("old principal: %s, modified principal: %s\n", name, + outname); +fail: + if (outname) + free(outname); + if (princ) + krb5_free_principal(ctx, princ); +} + +void +usage(char *progname) +{ + fprintf(stderr, "%s: Usage: %s 425_conv_principal \n", + progname, progname); + fprintf(stderr, "\t%s 524_conv_principal \n", progname); + fprintf(stderr, "\t%s parse_name \n", progname); + fprintf(stderr, "\t%s name_type \n", progname); + fprintf(stderr, "\t%s set_realm \n", progname); + fprintf(stderr, "\t%s string_to_timestamp

      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�swi=BCi(aZ+ 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 H^UePPmu~Mn literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/docs/mpool.3.ps b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/docs/mpool.3.ps new file mode 100644 index 0000000000000000000000000000000000000000..816c9243c8636087c0c9cb31b2f9354af6ac5fea GIT binary patch literal 13573 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 K=;sTUQ}sW}*6BL{ literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/docs/recno.3.ps b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/docs/recno.3.ps new file mode 100644 index 0000000000000000000000000000000000000000..8ffccfca90db10b200826806cb47c3bcc2acc42b GIT binary patch literal 14632 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 + +#include +#include +#include + +#include "db-ndbm.h" +#include "db-dbm.h" +#include "hash.h" + +/* If the two size fields of datum and DBMT are not equal, then + * casting between structures will result in stack garbage being + * transferred. Has been observed for DEC Alpha OSF, but will handle + * the general case. + */ + +#define NEED_COPY + +/* + * + * This package provides dbm and ndbm compatible interfaces to DB. + * First are the DBM routines, which call the NDBM routines, and + * the NDBM routines, which call the DB routines. + */ +static DBM *__cur_db; + +static void no_open_db __P((void)); + +int +kdb2_dbminit(file) + char *file; +{ + if (__cur_db != NULL) + (void)kdb2_dbm_close(__cur_db); + if ((__cur_db = kdb2_dbm_open(file, O_RDWR|O_BINARY, 0)) != NULL) + return (0); + if ((__cur_db = kdb2_dbm_open(file, O_RDONLY|O_BINARY, 0)) != NULL) + return (0); + return (-1); +} + +datum +kdb2_fetch(key) + datum key; +{ + datum item; + + if (__cur_db == NULL) { + no_open_db(); + item.dptr = 0; + item.dsize = 0; + return (item); + } + return (kdb2_dbm_fetch(__cur_db, key)); +} + +datum +kdb2_firstkey() +{ + datum item; + + if (__cur_db == NULL) { + no_open_db(); + item.dptr = 0; + item.dsize = 0; + return (item); + } + return (kdb2_dbm_firstkey(__cur_db)); +} + +datum +kdb2_nextkey(key) + datum key; +{ + datum item; + + if (__cur_db == NULL) { + no_open_db(); + item.dptr = 0; + item.dsize = 0; + return (item); + } + return (kdb2_dbm_nextkey(__cur_db)); +} + +int +kdb2_delete(key) + datum key; +{ + if (__cur_db == NULL) { + no_open_db(); + return (-1); + } + return (kdb2_dbm_delete(__cur_db, key)); +} + +int +kdb2_store(key, dat) + datum key, dat; +{ + if (__cur_db == NULL) { + no_open_db(); + return (-1); + } + return (kdb2_dbm_store(__cur_db, key, dat, DBM_REPLACE)); +} + +static void +no_open_db() +{ + (void)fprintf(stderr, "dbm: no open database.\n"); +} + +/* + * Returns: + * *DBM on success + * NULL on failure + */ +DBM * +kdb2_dbm_open(file, flags, mode) + const char *file; + int flags, mode; +{ + HASHINFO info; + char path[MAXPATHLEN]; + + info.bsize = 4096; + info.ffactor = 40; + info.nelem = 1; + info.cachesize = 0; + info.hash = NULL; + info.lorder = 0; + (void)strncpy(path, file, sizeof(path) - 1); + path[sizeof(path) - 1] = '\0'; + (void)strncat(path, DBM_SUFFIX, sizeof(path) - 1 - strlen(path)); + return ((DBM *)__hash_open(path, flags, mode, &info, 0)); +} + +/* + * Returns: + * Nothing. + */ +void +kdb2_dbm_close(db) + DBM *db; +{ + (void)(db->close)(db); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ +datum +kdb2_dbm_fetch(db, key) + DBM *db; + datum key; +{ + datum retval; + int status; + +#ifdef NEED_COPY + DBT k, r; + + k.data = key.dptr; + k.size = key.dsize; + status = (db->get)(db, &k, &r, 0); + retval.dptr = r.data; + retval.dsize = r.size; +#else + status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0); +#endif + if (status) { + retval.dptr = NULL; + retval.dsize = 0; + } + return (retval); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ +datum +kdb2_dbm_firstkey(db) + DBM *db; +{ + int status; + datum retkey; + +#ifdef NEED_COPY + DBT k, r; + + status = (db->seq)(db, &k, &r, R_FIRST); + retkey.dptr = k.data; + retkey.dsize = k.size; +#else + datum retdata; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); +#endif + if (status) + retkey.dptr = NULL; + return (retkey); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ +datum +kdb2_dbm_nextkey(db) + DBM *db; +{ + int status; + datum retkey; + +#ifdef NEED_COPY + DBT k, r; + + status = (db->seq)(db, &k, &r, R_NEXT); + retkey.dptr = k.data; + retkey.dsize = k.size; +#else + datum retdata; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); +#endif + if (status) + retkey.dptr = NULL; + return (retkey); +} + +/* + * Returns: + * 0 on success + * <0 failure + */ +int +kdb2_dbm_delete(db, key) + DBM *db; + datum key; +{ + int status; + +#ifdef NEED_COPY + DBT k; + + k.data = key.dptr; + k.size = key.dsize; + status = (db->del)(db, &k, 0); +#else + status = (db->del)(db, (DBT *)&key, 0); +#endif + if (status) + return (-1); + else + return (0); +} + +/* + * Returns: + * 0 on success + * <0 failure + * 1 if DBM_INSERT and entry exists + */ +int +kdb2_dbm_store(db, key, content, flags) + DBM *db; + datum key, content; + int flags; +{ +#ifdef NEED_COPY + DBT k, c; + + k.data = key.dptr; + k.size = key.dsize; + c.data = content.dptr; + c.size = content.dsize; + return ((db->put)(db, &k, &c, + (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); +#else + return ((db->put)(db, (DBT *)&key, (DBT *)&content, + (flags == DBM_INSERT) ? R_NOOVERWRITE : 0)); +#endif +} + +int +kdb2_dbm_error(db) + DBM *db; +{ + HTAB *hp; + + hp = (HTAB *)db->internal; + return (hp->local_errno); +} + +int +kdb2_dbm_clearerr(db) + DBM *db; +{ + HTAB *hp; + + hp = (HTAB *)db->internal; + hp->local_errno = 0; + return (0); +} + +int +kdb2_dbm_dirfno(db) + DBM *db; +{ + return(((HTAB *)db->internal)->fp); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/deps b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/deps new file mode 100644 index 00000000..ac4ca549 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/deps @@ -0,0 +1,37 @@ +# +# Generated makefile dependencies follow. +# +hash.so hash.po $(OUTPRE)hash.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(DB_DEPS) $(srcdir)/../include/config.h $(srcdir)/../include/db-int.h \ + $(srcdir)/../include/db-queue.h $(srcdir)/../mpool/mpool.h \ + extern.h hash.c hash.h page.h +hash_bigkey.so hash_bigkey.po $(OUTPRE)hash_bigkey.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(DB_DEPS) $(srcdir)/../include/config.h \ + $(srcdir)/../include/db-int.h $(srcdir)/../include/db-queue.h \ + $(srcdir)/../mpool/mpool.h extern.h hash.h hash_bigkey.c \ + page.h +hash_debug.so hash_debug.po $(OUTPRE)hash_debug.$(OBJEXT): \ + hash_debug.c +hash_func.so hash_func.po $(OUTPRE)hash_func.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(DB_DEPS) $(srcdir)/../include/config.h \ + $(srcdir)/../include/db-int.h $(srcdir)/../include/db-queue.h \ + $(srcdir)/../mpool/mpool.h extern.h hash.h hash_func.c \ + page.h +hash_log2.so hash_log2.po $(OUTPRE)hash_log2.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(DB_DEPS) $(srcdir)/../include/config.h \ + $(srcdir)/../include/db-int.h $(srcdir)/../include/db-queue.h \ + $(srcdir)/../mpool/mpool.h extern.h hash.h hash_log2.c \ + page.h +hash_page.so hash_page.po $(OUTPRE)hash_page.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(DB_DEPS) $(srcdir)/../include/config.h \ + $(srcdir)/../include/db-int.h $(srcdir)/../include/db-queue.h \ + $(srcdir)/../mpool/mpool.h extern.h hash.h hash_page.c \ + page.h +hsearch.so hsearch.po $(OUTPRE)hsearch.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(DB_DEPS) $(srcdir)/../include/config.h $(srcdir)/../include/db-int.h \ + hsearch.c search.h +dbm.so dbm.po $(OUTPRE)dbm.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(DB_DEPS) $(srcdir)/../include/config.h $(srcdir)/../include/db-dbm.h \ + $(srcdir)/../include/db-int.h $(srcdir)/../include/db-ndbm.h \ + $(srcdir)/../include/db-queue.h $(srcdir)/../mpool/mpool.h \ + dbm.c hash.h diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/extern.h b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/extern.h new file mode 100644 index 00000000..872b6b0f --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/extern.h @@ -0,0 +1,109 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)extern.h 8.8 (Berkeley) 11/7/95 + */ + +#define __add_bigpage __kdb2_add_bigpage +#define __add_ovflpage __kdb2_add_ovflpage +#define __addel __kdb2_addel +#define __alloc_tmp __kdb2_alloc_tmp +#define __big_delete __kdb2_big_delete +#define __big_insert __kdb2_big_insert +#define __big_keydata __kdb2_big_keydata +#define __big_return __kdb2_big_return +#define __call_hash __kdb2_call_hash +#define __cursor_creat __kdb2_cursor_creat +#define __delete_page __kdb2_delete_page +#define __delpair __kdb2_delpair +#define __expand_table __kdb2_expand_table +#define __find_bigpair __kdb2_find_bigpair +#define __free_ovflpage __kdb2_free_ovflpage +#define __get_bigkey __kdb2_get_bigkey +#define __get_buf __kdb2_get_buf +#define __get_item __kdb2_get_item +#define __get_item_done __kdb2_get_item_done +#define __get_item_first __kdb2_get_item_first +#define __get_item_next __kdb2_get_item_next +#define __get_item_reset __kdb2_get_item_reset +#define __get_page __kdb2_get_page +#define __ibitmap __kdb2_ibitmap +#define __log2 __kdb2_log2 +#define __new_page __kdb2_new_page +#define __pgin_routine __kdb2_pgin_routine +#define __pgout_routine __kdb2_pgout_routine +#define __put_buf __kdb2_put_buf +#define __put_page __kdb2_put_page +#define __reclaim_tmp __kdb2_reclaim_tmp +#define __split_page __kdb2_split_page + +PAGE16 *__add_bigpage __P((HTAB *, PAGE16 *, indx_t, const u_int8_t)); +PAGE16 *__add_ovflpage __P((HTAB *, PAGE16 *)); +int32_t __addel __P((HTAB *, ITEM_INFO *, + const DBT *, const DBT *, u_int32_t, const u_int8_t)); +u_int32_t __alloc_tmp __P((HTAB*)); +int32_t __big_delete __P((HTAB *, PAGE16 *, indx_t)); +int32_t __big_insert __P((HTAB *, PAGE16 *, const DBT *, const DBT *)); +int32_t __big_keydata __P((HTAB *, PAGE16 *, DBT *, DBT *, int32_t)); +int32_t __big_return __P((HTAB *, ITEM_INFO *, DBT *, int32_t)); +u_int32_t __call_hash __P((HTAB *, int8_t *, int32_t)); +CURSOR *__cursor_creat __P((const DB *)); +int32_t __delete_page __P((HTAB *, PAGE16 *, int32_t)); +int32_t __delpair __P((HTAB *, CURSOR *, ITEM_INFO *)); +int32_t __expand_table __P((HTAB *)); +int32_t __find_bigpair __P((HTAB *, CURSOR *, int8_t *, int32_t)); +void __free_ovflpage __P((HTAB *, PAGE16 *)); +int32_t __get_bigkey __P((HTAB *, PAGE16 *, indx_t, DBT *)); +PAGE16 *__get_buf __P((HTAB *, u_int32_t, int32_t)); +u_int32_t __get_item __P((HTAB *, CURSOR *, DBT *, DBT *, ITEM_INFO *)); +u_int32_t __get_item_done __P((HTAB *, CURSOR *)); +u_int32_t __get_item_first __P((HTAB *, CURSOR *, DBT *, DBT *, ITEM_INFO *)); +u_int32_t __get_item_next __P((HTAB *, CURSOR *, DBT *, DBT *, ITEM_INFO *)); +u_int32_t __get_item_reset __P((HTAB *, CURSOR *)); +PAGE16 *__get_page __P((HTAB *, u_int32_t, int32_t)); +int32_t __ibitmap __P((HTAB *, int32_t, int32_t, int32_t)); +u_int32_t __log2 __P((u_int32_t)); +int32_t __new_page __P((HTAB *, u_int32_t, int32_t)); +void __pgin_routine __P((void *, db_pgno_t, void *)); +void __pgout_routine __P((void *, db_pgno_t, void *)); +u_int32_t __put_buf __P((HTAB *, PAGE16 *, u_int32_t)); +int32_t __put_page __P((HTAB *, PAGE16 *, int32_t, int32_t)); +void __reclaim_tmp __P((HTAB *)); +int32_t __split_page __P((HTAB *, u_int32_t, u_int32_t)); + +/* Default hash routine. */ +extern u_int32_t (*__default_hash) __P((const void *, size_t)); + +#ifdef HASH_STATISTICS +extern long hash_accesses, hash_bigpages, hash_collisions, hash_expansions; +extern long hash_overflow; +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash.c new file mode 100644 index 00000000..862dbb16 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash.c @@ -0,0 +1,1054 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash.c 8.12 (Berkeley) 11/7/95"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#ifdef DEBUG +#include +#endif + +#include "db-int.h" +#include "hash.h" +#include "page.h" +#include "extern.h" + +static int32_t flush_meta __P((HTAB *)); +static int32_t hash_access __P((HTAB *, ACTION, const DBT *, DBT *)); +static int32_t hash_close __P((DB *)); +static int32_t hash_delete __P((const DB *, const DBT *, u_int32_t)); +static int32_t hash_fd __P((const DB *)); +static int32_t hash_get __P((const DB *, const DBT *, DBT *, u_int32_t)); +static int32_t hash_put __P((const DB *, DBT *, const DBT *, u_int32_t)); +static int32_t hash_seq __P((const DB *, DBT *, DBT *, u_int32_t)); +static int32_t hash_sync __P((const DB *, u_int32_t)); +static int32_t hdestroy __P((HTAB *)); +static int32_t cursor_get __P((const DB *, CURSOR *, DBT *, DBT *, \ + u_int32_t)); +static int32_t cursor_delete __P((const DB *, CURSOR *, u_int32_t)); +static HTAB *init_hash __P((HTAB *, const char *, const HASHINFO *)); +static int32_t init_htab __P((HTAB *, int32_t)); +#if DB_BYTE_ORDER == DB_LITTLE_ENDIAN +static void swap_header __P((HTAB *)); +static void swap_header_copy __P((HASHHDR *, HASHHDR *)); +#endif +static u_int32_t hget_header __P((HTAB *, u_int32_t)); +static void hput_header __P((HTAB *)); + +#define RETURN_ERROR(ERR, LOC) { save_errno = ERR; goto LOC; } + +/* Return values */ +#define SUCCESS (0) +#define ERROR (-1) +#define ABNORMAL (1) + +#ifdef HASH_STATISTICS +u_int32_t hash_accesses, hash_collisions, hash_expansions, hash_overflows, + hash_bigpages; +#endif + +/************************** INTERFACE ROUTINES ***************************/ +/* OPEN/CLOSE */ + +extern DB * +__kdb2_hash_open(file, flags, mode, info, dflags) + const char *file; + int flags, mode, dflags; + const HASHINFO *info; /* Special directives for create */ +{ + struct stat statbuf; + DB *dbp; + DBT mpool_key; + HTAB *hashp; + int32_t bpages, csize, new_table, save_errno; + + if (!file || (flags & O_ACCMODE) == O_WRONLY) { + errno = EINVAL; + return (NULL); + } + if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB)))) + return (NULL); + hashp->fp = -1; + /* + * Even if user wants write only, we need to be able to read + * the actual file, so we need to open it read/write. But, the + * field in the hashp structure needs to be accurate so that + * we can check accesses. + */ + hashp->flags = flags; + hashp->save_file = hashp->flags & O_RDWR; + + new_table = 0; + if (!file || (flags & O_TRUNC) || + (stat(file, &statbuf) && (errno == ENOENT))) { + if (errno == ENOENT) + errno = 0; /* In case someone looks at errno. */ + new_table = 1; + } + if (file) { + if ((hashp->fp = open(file, flags|O_BINARY, mode)) == -1) + RETURN_ERROR(errno, error0); + (void)fcntl(hashp->fp, F_SETFD, 1); + } + + /* Process arguments to set up hash table header. */ + if (new_table) { + if (!(hashp = init_hash(hashp, file, info))) + RETURN_ERROR(errno, error1); + } else { + /* Table already exists */ + if (info && info->hash) + hashp->hash = info->hash; + else + hashp->hash = __default_hash; + + /* copy metadata from page into header */ + if (hget_header(hashp, + (info && info->bsize ? info->bsize : DEF_BUCKET_SIZE)) != + sizeof(HASHHDR)) + RETURN_ERROR(EFTYPE, error1); + + /* Verify file type, versions and hash function */ + if (hashp->hdr.magic != HASHMAGIC) + RETURN_ERROR(EFTYPE, error1); +#define OLDHASHVERSION 1 + if (hashp->hdr.version != HASHVERSION && + hashp->hdr.version != OLDHASHVERSION) + RETURN_ERROR(EFTYPE, error1); + if (hashp->hash(CHARKEY, sizeof(CHARKEY)) + != hashp->hdr.h_charkey) + RETURN_ERROR(EFTYPE, error1); + /* + * Figure out how many segments we need. Max_Bucket is the + * maximum bucket number, so the number of buckets is + * max_bucket + 1. + */ + + /* Read in bitmaps */ + bpages = (hashp->hdr.spares[hashp->hdr.ovfl_point] + + (hashp->hdr.bsize << BYTE_SHIFT) - 1) >> + (hashp->hdr.bshift + BYTE_SHIFT); + + hashp->nmaps = bpages; + (void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *)); + } + + /* start up mpool */ + mpool_key.data = (u_int8_t *)file; + mpool_key.size = strlen(file); + + if (info && info->cachesize) + csize = info->cachesize / hashp->hdr.bsize; + else + csize = DEF_CACHESIZE / hashp->hdr.bsize; + hashp->mp = mpool_open(&mpool_key, hashp->fp, hashp->hdr.bsize, csize); + + if (!hashp->mp) + RETURN_ERROR(errno, error1); + mpool_filter(hashp->mp, __pgin_routine, __pgout_routine, hashp); + + /* + * For a new table, set up the bitmaps. + */ + if (new_table && + init_htab(hashp, info && info->nelem ? info->nelem : 1)) + goto error2; + + /* initialize the cursor queue */ + TAILQ_INIT(&hashp->curs_queue); + hashp->seq_cursor = NULL; + + + /* get a chunk of memory for our split buffer */ + hashp->split_buf = (PAGE16 *)malloc(hashp->hdr.bsize); + if (!hashp->split_buf) + goto error2; + + hashp->new_file = new_table; + + if (!(dbp = (DB *)malloc(sizeof(DB)))) + goto error2; + + dbp->internal = hashp; + dbp->close = hash_close; + dbp->del = hash_delete; + dbp->fd = hash_fd; + dbp->get = hash_get; + dbp->put = hash_put; + dbp->seq = hash_seq; + dbp->sync = hash_sync; + dbp->type = DB_HASH; + +#ifdef DEBUG + (void)fprintf(stderr, + "%s\n%s%lx\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n", + "init_htab:", + "TABLE POINTER ", (void *)hashp, + "BUCKET SIZE ", hashp->hdr.bsize, + "BUCKET SHIFT ", hashp->hdr.bshift, + "FILL FACTOR ", hashp->hdr.ffactor, + "MAX BUCKET ", hashp->hdr.max_bucket, + "OVFL POINT ", hashp->hdr.ovfl_point, + "LAST FREED ", hashp->hdr.last_freed, + "HIGH MASK ", hashp->hdr.high_mask, + "LOW MASK ", hashp->hdr.low_mask, + "NKEYS ", hashp->hdr.nkeys); +#endif +#ifdef HASH_STATISTICS + hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0; + hash_bigpages = 0; +#endif + return (dbp); + +error2: + save_errno = errno; + hdestroy(hashp); + errno = save_errno; + return (NULL); + +error1: + if (hashp != NULL) + (void)close(hashp->fp); + +error0: + free(hashp); + errno = save_errno; + return (NULL); +} + +static int32_t +hash_close(dbp) + DB *dbp; +{ + HTAB *hashp; + int32_t retval; + + if (!dbp) + return (ERROR); + + hashp = (HTAB *)dbp->internal; + retval = hdestroy(hashp); + free(dbp); + return (retval); +} + +static int32_t +hash_fd(dbp) + const DB *dbp; +{ + HTAB *hashp; + + if (!dbp) + return (ERROR); + + hashp = (HTAB *)dbp->internal; + if (hashp->fp == -1) { + errno = ENOENT; + return (-1); + } + return (hashp->fp); +} + +/************************** LOCAL CREATION ROUTINES **********************/ +static HTAB * +init_hash(hashp, file, info) + HTAB *hashp; + const char *file; + const HASHINFO *info; +{ + struct stat statbuf; + + hashp->hdr.nkeys = 0; + hashp->hdr.lorder = DB_BYTE_ORDER; + hashp->hdr.bsize = DEF_BUCKET_SIZE; + hashp->hdr.bshift = DEF_BUCKET_SHIFT; + hashp->hdr.ffactor = DEF_FFACTOR; + hashp->hash = __default_hash; + memset(hashp->hdr.spares, 0, sizeof(hashp->hdr.spares)); + memset(hashp->hdr.bitmaps, 0, sizeof(hashp->hdr.bitmaps)); + + /* Fix bucket size to be optimal for file system */ + if (file != NULL) { + if (stat(file, &statbuf)) + return (NULL); + hashp->hdr.bsize = statbuf.st_blksize; + if (hashp->hdr.bsize > MAX_BSIZE) + hashp->hdr.bsize = MAX_BSIZE; + hashp->hdr.bshift = __log2(hashp->hdr.bsize); + } + if (info) { + if (info->bsize) { + /* Round pagesize up to power of 2 */ + hashp->hdr.bshift = __log2(info->bsize); + hashp->hdr.bsize = 1 << hashp->hdr.bshift; + if (hashp->hdr.bsize > MAX_BSIZE) { + errno = EINVAL; + return (NULL); + } + } + if (info->ffactor) + hashp->hdr.ffactor = info->ffactor; + if (info->hash) + hashp->hash = info->hash; + if (info->lorder) { + if ((info->lorder != DB_BIG_ENDIAN) && + (info->lorder != DB_LITTLE_ENDIAN)) { + errno = EINVAL; + return (NULL); + } + hashp->hdr.lorder = info->lorder; + } + } + return (hashp); +} + +/* + * Returns 0 on No Error + */ +static int32_t +init_htab(hashp, nelem) + HTAB *hashp; + int32_t nelem; +{ + int32_t l2, nbuckets; + + /* + * Divide number of elements by the fill factor and determine a + * desired number of buckets. Allocate space for the next greater + * power of two number of buckets. + */ + nelem = (nelem - 1) / hashp->hdr.ffactor + 1; + + l2 = __log2(MAX(nelem, 2)); + nbuckets = 1 << l2; + + hashp->hdr.spares[l2] = l2 + 1; + hashp->hdr.spares[l2 + 1] = l2 + 1; + hashp->hdr.ovfl_point = l2; + hashp->hdr.last_freed = 2; + + hashp->hdr.max_bucket = hashp->hdr.low_mask = nbuckets - 1; + hashp->hdr.high_mask = (nbuckets << 1) - 1; + + /* + * The number of header pages is the size of the header divided by + * the amount of freespace on header pages (the page size - the + * size of 1 integer where the length of the header info on that + * page is stored) plus another page if it didn't divide evenly. + */ + hashp->hdr.hdrpages = + (sizeof(HASHHDR) / (hashp->hdr.bsize - HEADER_OVERHEAD)) + + (((sizeof(HASHHDR) % (hashp->hdr.bsize - HEADER_OVERHEAD)) == 0) + ? 0 : 1); + + /* Create pages for these buckets */ + /* + for (i = 0; i <= hashp->hdr.max_bucket; i++) { + if (__new_page(hashp, (u_int32_t)i, A_BUCKET) != 0) + return (-1); + } + */ + + /* First bitmap page is at: splitpoint l2 page offset 1 */ + if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0)) + return (-1); + + return (0); +} + +/* + * Functions to get/put hash header. We access the file directly. + */ +static u_int32_t +hget_header(hashp, page_size) + HTAB *hashp; + u_int32_t page_size; +{ + u_int32_t num_copied; + u_int8_t *hdr_dest; + + num_copied = 0; + + hdr_dest = (u_int8_t *)&hashp->hdr; + + /* + * XXX + * This should not be printing to stderr on a "normal" error case. + */ + lseek(hashp->fp, 0, SEEK_SET); + num_copied = read(hashp->fp, hdr_dest, sizeof(HASHHDR)); + if (num_copied != sizeof(HASHHDR)) { + fprintf(stderr, "hash: could not retrieve header"); + return (0); + } +#if DB_BYTE_ORDER == DB_LITTLE_ENDIAN + swap_header(hashp); +#endif + return (num_copied); +} + +static void +hput_header(hashp) + HTAB *hashp; +{ + HASHHDR *whdrp; +#if DB_BYTE_ORDER == DB_LITTLE_ENDIAN + HASHHDR whdr; +#endif + u_int32_t num_copied; + + num_copied = 0; + + whdrp = &hashp->hdr; +#if DB_BYTE_ORDER == DB_LITTLE_ENDIAN + whdrp = &whdr; + swap_header_copy(&hashp->hdr, whdrp); +#endif + + lseek(hashp->fp, 0, SEEK_SET); + num_copied = write(hashp->fp, whdrp, sizeof(HASHHDR)); + if (num_copied != sizeof(HASHHDR)) + (void)fprintf(stderr, "hash: could not write hash header"); + return; +} + +/********************** DESTROY/CLOSE ROUTINES ************************/ + +/* + * Flushes any changes to the file if necessary and destroys the hashp + * structure, freeing all allocated space. + */ +static int32_t +hdestroy(hashp) + HTAB *hashp; +{ + int32_t save_errno; + + save_errno = 0; + +#ifdef HASH_STATISTICS + { int i; + (void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n", + hash_accesses, hash_collisions); + (void)fprintf(stderr, + "hdestroy: expansions %ld\n", hash_expansions); + (void)fprintf(stderr, + "hdestroy: overflows %ld\n", hash_overflows); + (void)fprintf(stderr, + "hdestroy: big key/data pages %ld\n", hash_bigpages); + (void)fprintf(stderr, + "keys %ld maxp %d\n", hashp->hdr.nkeys, hashp->hdr.max_bucket); + + for (i = 0; i < NCACHED; i++) + (void)fprintf(stderr, + "spares[%d] = %d\n", i, hashp->hdr.spares[i]); + } +#endif + + if (flush_meta(hashp) && !save_errno) + save_errno = errno; + + /* Free the split page */ + if (hashp->split_buf) + free(hashp->split_buf); + + /* Free the big key and big data returns */ + if (hashp->bigkey_buf) + free(hashp->bigkey_buf); + if (hashp->bigdata_buf) + free(hashp->bigdata_buf); + + /* XXX This should really iterate over the cursor queue, but + it's not clear how to do that, and the only cursor a hash + table ever creates is the one used by hash_seq(). Passing + NULL as the first arg is also a kludge, but I know that + it's never used, so I do it. The intent is to plug the + memory leak. Correctness can come later. */ + + if (hashp->seq_cursor) + hashp->seq_cursor->delete(NULL, hashp->seq_cursor, 0); + + /* shut down mpool */ + mpool_sync(hashp->mp); + mpool_close(hashp->mp); + + if (hashp->fp != -1) + (void)close(hashp->fp); + + /* + * *** This may cause problems if hashp->fname is set in any case + * other than the case that we are generating a temporary file name. + * Note that the new version of mpool should support temporary + * files within mpool itself. + */ + if (hashp->fname && !hashp->save_file) { +#ifdef DEBUG + fprintf(stderr, "Unlinking file %s.\n", hashp->fname); +#endif + /* we need to chmod the file to allow it to be deleted... */ + chmod(hashp->fname, 0700); + unlink(hashp->fname); + } + free(hashp); + + if (save_errno) { + errno = save_errno; + return (ERROR); + } + return (SUCCESS); +} + +/* + * Write modified pages to disk + * + * Returns: + * 0 == OK + * -1 ERROR + */ +static int32_t +hash_sync(dbp, flags) + const DB *dbp; + u_int32_t flags; +{ + HTAB *hashp; + + hashp = (HTAB *)dbp->internal; + + /* + * XXX + * Check success/failure conditions. + */ + return (flush_meta(hashp) || mpool_sync(hashp->mp)); +} + +/* + * Returns: + * 0 == OK + * -1 indicates that errno should be set + */ +static int32_t +flush_meta(hashp) + HTAB *hashp; +{ + int32_t i; + + if (!hashp->save_file) + return (0); + hashp->hdr.magic = HASHMAGIC; + hashp->hdr.version = HASHVERSION; + hashp->hdr.h_charkey = hashp->hash(CHARKEY, sizeof(CHARKEY)); + + /* write out metadata */ + hput_header(hashp); + + for (i = 0; i < NCACHED; i++) + if (hashp->mapp[i]) { + if (__put_page(hashp, + (PAGE16 *)hashp->mapp[i], A_BITMAP, 1)) + return (-1); + hashp->mapp[i] = NULL; + } + return (0); +} + +/*******************************SEARCH ROUTINES *****************************/ +/* + * All the access routines return + * + * Returns: + * 0 on SUCCESS + * 1 to indicate an external ERROR (i.e. key not found, etc) + * -1 to indicate an internal ERROR (i.e. out of memory, etc) + */ + +/* *** make sure this is true! */ + +static int32_t +hash_get(dbp, key, data, flag) + const DB *dbp; + const DBT *key; + DBT *data; + u_int32_t flag; +{ + HTAB *hashp; + + hashp = (HTAB *)dbp->internal; + if (flag) { + hashp->local_errno = errno = EINVAL; + return (ERROR); + } + return (hash_access(hashp, HASH_GET, key, data)); +} + +static int32_t +hash_put(dbp, key, data, flag) + const DB *dbp; + DBT *key; + const DBT *data; + u_int32_t flag; +{ + HTAB *hashp; + + hashp = (HTAB *)dbp->internal; + if (flag && flag != R_NOOVERWRITE) { + hashp->local_errno = errno = EINVAL; + return (ERROR); + } + if ((hashp->flags & O_ACCMODE) == O_RDONLY) { + hashp->local_errno = errno = EPERM; + return (ERROR); + } + return (hash_access(hashp, flag == R_NOOVERWRITE ? + HASH_PUTNEW : HASH_PUT, key, (DBT *)data)); +} + +static int32_t +hash_delete(dbp, key, flag) + const DB *dbp; + const DBT *key; + u_int32_t flag; /* Ignored */ +{ + HTAB *hashp; + + hashp = (HTAB *)dbp->internal; + if (flag) { + hashp->local_errno = errno = EINVAL; + return (ERROR); + } + if ((hashp->flags & O_ACCMODE) == O_RDONLY) { + hashp->local_errno = errno = EPERM; + return (ERROR); + } + + return (hash_access(hashp, HASH_DELETE, key, NULL)); +} + +/* + * Assume that hashp has been set in wrapper routine. + */ +static int32_t +hash_access(hashp, action, key, val) + HTAB *hashp; + ACTION action; + const DBT *key; + DBT *val; +{ + DBT page_key, page_val; + CURSOR cursor; + ITEM_INFO item_info; + u_int32_t bucket; + u_int32_t num_items; + +#ifdef HASH_STATISTICS + hash_accesses++; +#endif + + num_items = 0; + + /* + * Set up item_info so that we're looking for space to add an item + * as we cycle through the pages looking for the key. + */ + if (action == HASH_PUT || action == HASH_PUTNEW) { + if (ISBIG(key->size + val->size, hashp)) + item_info.seek_size = PAIR_OVERHEAD; + else + item_info.seek_size = key->size + val->size; + } else + item_info.seek_size = 0; + item_info.seek_found_page = 0; + + bucket = __call_hash(hashp, (int8_t *)key->data, key->size); + + cursor.pagep = NULL; + __get_item_reset(hashp, &cursor); + + cursor.bucket = bucket; + while (1) { + __get_item_next(hashp, &cursor, &page_key, &page_val, &item_info); + if (item_info.status == ITEM_ERROR) + return (ABNORMAL); + if (item_info.status == ITEM_NO_MORE) + break; + num_items++; + if (item_info.key_off == BIGPAIR) { + /* + * !!! + * 0 is a valid index. + */ + if (__find_bigpair(hashp, &cursor, (int8_t *)key->data, + key->size) > 0) + goto found; + } else if (key->size == page_key.size && + !memcmp(key->data, page_key.data, key->size)) + goto found; + } +#ifdef HASH_STATISTICS + hash_collisions++; +#endif + __get_item_done(hashp, &cursor); + + /* + * At this point, item_info will list either the last page in + * the chain, or the last page in the chain plus a pgno for where + * to find the first page in the chain with space for the + * item we wish to add. + */ + + /* Not found */ + switch (action) { + case HASH_PUT: + case HASH_PUTNEW: + if (__addel(hashp, &item_info, key, val, num_items, 0)) + return (ERROR); + break; + case HASH_GET: + case HASH_DELETE: + default: + return (ABNORMAL); + } + + if (item_info.caused_expand) + __expand_table(hashp); + return (SUCCESS); + +found: __get_item_done(hashp, &cursor); + + switch (action) { + case HASH_PUTNEW: + /* mpool_put(hashp->mp, pagep, 0); */ + return (ABNORMAL); + case HASH_GET: + if (item_info.key_off == BIGPAIR) { + if (__big_return(hashp, &item_info, val, 0)) + return (ERROR); + } else { + val->data = page_val.data; + val->size = page_val.size; + } + /* *** data may not be available! */ + break; + case HASH_PUT: + if (__delpair(hashp, &cursor, &item_info) || + __addel(hashp, &item_info, key, val, UNKNOWN, 0)) + return (ERROR); + __get_item_done(hashp, &cursor); + if (item_info.caused_expand) + __expand_table(hashp); + break; + case HASH_DELETE: + if (__delpair(hashp, &cursor, &item_info)) + return (ERROR); + break; + default: + abort(); + } + return (SUCCESS); +} + +/* ****************** CURSORS ********************************** */ +CURSOR * +__cursor_creat(dbp) + const DB *dbp; +{ + CURSOR *new_curs; + HTAB *hashp; + + new_curs = (CURSOR *)malloc(sizeof(struct cursor_t)); + if (!new_curs) + return NULL; + new_curs->internal = + (struct item_info *)malloc(sizeof(struct item_info)); + if (!new_curs->internal) { + free(new_curs); + return NULL; + } + new_curs->get = cursor_get; + new_curs->delete = cursor_delete; + + new_curs->bucket = 0; + new_curs->pgno = INVALID_PGNO; + new_curs->ndx = 0; + new_curs->pgndx = 0; + new_curs->pagep = NULL; + + /* place onto queue of cursors */ + hashp = (HTAB *)dbp->internal; + TAILQ_INSERT_TAIL(&hashp->curs_queue, new_curs, queue); + + return new_curs; +} + +static int32_t +cursor_get(dbp, cursorp, key, val, flags) + const DB *dbp; + CURSOR *cursorp; + DBT *key, *val; + u_int32_t flags; +{ + HTAB *hashp; + ITEM_INFO item_info; + + hashp = (HTAB *)dbp->internal; + + if (flags && flags != R_FIRST && flags != R_NEXT) { + hashp->local_errno = errno = EINVAL; + return (ERROR); + } +#ifdef HASH_STATISTICS + hash_accesses++; +#endif + + item_info.seek_size = 0; + + if (flags == R_FIRST) + __get_item_first(hashp, cursorp, key, val, &item_info); + else + __get_item_next(hashp, cursorp, key, val, &item_info); + + /* + * This needs to be changed around. As is, get_item_next advances + * the pointers on the page but this function actually advances + * bucket pointers. This works, since the only other place we + * use get_item_next is in hash_access which only deals with one + * bucket at a time. However, there is the problem that certain other + * functions (such as find_bigpair and delpair) depend on the + * pgndx member of the cursor. Right now, they are using pngdx - 1 + * since indices refer to the __next__ item that is to be fetched + * from the page. This is ugly, as you may have noticed, whoever + * you are. The best solution would be to depend on item_infos to + * deal with _current_ information, and have the cursors only + * deal with _next_ information. In that scheme, get_item_next + * would also advance buckets. Version 3... + */ + + + /* + * Must always enter this loop to do error handling and + * check for big key/data pair. + */ + while (1) { + if (item_info.status == ITEM_OK) { + if (item_info.key_off == BIGPAIR && + __big_keydata(hashp, cursorp->pagep, key, val, + item_info.pgndx)) + return (ABNORMAL); + + break; + } else if (item_info.status != ITEM_NO_MORE) + return (ABNORMAL); + + __put_page(hashp, cursorp->pagep, A_RAW, 0); + cursorp->ndx = cursorp->pgndx = 0; + cursorp->bucket++; + cursorp->pgno = INVALID_PGNO; + cursorp->pagep = NULL; + if (cursorp->bucket > hashp->hdr.max_bucket) + return (ABNORMAL); + __get_item_next(hashp, cursorp, key, val, &item_info); + } + + __get_item_done(hashp, cursorp); + return (0); +} + +static int32_t +cursor_delete(dbp, cursor, flags) + const DB *dbp; + CURSOR *cursor; + u_int32_t flags; +{ + /* XXX this is empirically determined, so it might not be completely + correct, but it seems to work. At the very least it fixes + a memory leak */ + + free(cursor->internal); + free(cursor); + + return (0); +} + +static int32_t +hash_seq(dbp, key, val, flag) + const DB *dbp; + DBT *key, *val; + u_int32_t flag; +{ + HTAB *hashp; + + /* + * Seq just uses the default cursor to go sequecing through the + * database. Note that the default cursor is the first in the list. + */ + + hashp = (HTAB *)dbp->internal; + if (!hashp->seq_cursor) + hashp->seq_cursor = __cursor_creat(dbp); + + return (hashp->seq_cursor->get(dbp, hashp->seq_cursor, key, val, flag)); +} + +/********************************* UTILITIES ************************/ + +/* + * Returns: + * 0 ==> OK + * -1 ==> Error + */ +int32_t +__expand_table(hashp) + HTAB *hashp; +{ + u_int32_t old_bucket, new_bucket; + int32_t spare_ndx; + +#ifdef HASH_STATISTICS + hash_expansions++; +#endif + new_bucket = ++hashp->hdr.max_bucket; + old_bucket = (hashp->hdr.max_bucket & hashp->hdr.low_mask); + + /* Get a page for this new bucket */ + if (__new_page(hashp, new_bucket, A_BUCKET) != 0) + return (-1); + + /* + * If the split point is increasing (hdr.max_bucket's log base 2 + * increases), we need to copy the current contents of the spare + * split bucket to the next bucket. + */ + spare_ndx = __log2(hashp->hdr.max_bucket + 1); + if (spare_ndx > hashp->hdr.ovfl_point) { + hashp->hdr.spares[spare_ndx] = hashp->hdr.spares[hashp->hdr.ovfl_point]; + hashp->hdr.ovfl_point = spare_ndx; + } + if (new_bucket > hashp->hdr.high_mask) { + /* Starting a new doubling */ + hashp->hdr.low_mask = hashp->hdr.high_mask; + hashp->hdr.high_mask = new_bucket | hashp->hdr.low_mask; + } + if (BUCKET_TO_PAGE(new_bucket) > MAX_PAGES(hashp)) { + fprintf(stderr, "hash: Cannot allocate new bucket. Pages exhausted.\n"); + return (-1); + } + /* Relocate records to the new bucket */ + return (__split_page(hashp, old_bucket, new_bucket)); +} + +u_int32_t +__call_hash(hashp, k, len) + HTAB *hashp; + int8_t *k; + int32_t len; +{ + u_int32_t n, bucket; + + n = hashp->hash(k, len); + bucket = n & hashp->hdr.high_mask; + if (bucket > hashp->hdr.max_bucket) + bucket = bucket & hashp->hdr.low_mask; + return (bucket); +} + +#if DB_BYTE_ORDER == DB_LITTLE_ENDIAN +/* + * Hashp->hdr needs to be byteswapped. + */ +static void +swap_header_copy(srcp, destp) + HASHHDR *srcp, *destp; +{ + int32_t i; + + P_32_COPY(srcp->magic, destp->magic); + P_32_COPY(srcp->version, destp->version); + P_32_COPY(srcp->lorder, destp->lorder); + P_32_COPY(srcp->bsize, destp->bsize); + P_32_COPY(srcp->bshift, destp->bshift); + P_32_COPY(srcp->ovfl_point, destp->ovfl_point); + P_32_COPY(srcp->last_freed, destp->last_freed); + P_32_COPY(srcp->max_bucket, destp->max_bucket); + P_32_COPY(srcp->high_mask, destp->high_mask); + P_32_COPY(srcp->low_mask, destp->low_mask); + P_32_COPY(srcp->ffactor, destp->ffactor); + P_32_COPY(srcp->nkeys, destp->nkeys); + P_32_COPY(srcp->hdrpages, destp->hdrpages); + P_32_COPY(srcp->h_charkey, destp->h_charkey); + for (i = 0; i < NCACHED; i++) { + P_32_COPY(srcp->spares[i], destp->spares[i]); + P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]); + } +} + +static void +swap_header(hashp) + HTAB *hashp; +{ + HASHHDR *hdrp; + int32_t i; + + hdrp = &hashp->hdr; + + M_32_SWAP(hdrp->magic); + M_32_SWAP(hdrp->version); + M_32_SWAP(hdrp->lorder); + M_32_SWAP(hdrp->bsize); + M_32_SWAP(hdrp->bshift); + M_32_SWAP(hdrp->ovfl_point); + M_32_SWAP(hdrp->last_freed); + M_32_SWAP(hdrp->max_bucket); + M_32_SWAP(hdrp->high_mask); + M_32_SWAP(hdrp->low_mask); + M_32_SWAP(hdrp->ffactor); + M_32_SWAP(hdrp->nkeys); + M_32_SWAP(hdrp->hdrpages); + M_32_SWAP(hdrp->h_charkey); + for (i = 0; i < NCACHED; i++) { + M_32_SWAP(hdrp->spares[i]); + M_16_SWAP(hdrp->bitmaps[i]); + } +} +#endif /* DB_BYTE_ORDER == DB_LITTLE_ENDIAN */ diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash.c.patch b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash.c.patch new file mode 100644 index 00000000..b72cc0d2 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash.c.patch @@ -0,0 +1,109 @@ +*** /tmp/,RCSt1a21714 Wed Apr 3 11:49:15 1996 +--- hash.c Wed Apr 3 08:43:04 1996 +*************** +*** 399,405 + /* Create pages for these buckets */ + /* + for (i = 0; i <= hashp->hdr.max_bucket; i++) { +! if (__new_page(hashp, i, A_BUCKET) != 0) + return (-1); + } + */ + +--- 399,405 ----- + /* Create pages for these buckets */ + /* + for (i = 0; i <= hashp->hdr.max_bucket; i++) { +! if (__new_page(hashp, (u_int32_t)i, A_BUCKET) != 0) + return (-1); + } + */ +*************** +*** 560,567 + * XXX + * Check success/failure conditions. + */ +! mpool_sync(hashp->mp); +! return (0); + } + + /* + +--- 560,566 ----- + * XXX + * Check success/failure conditions. + */ +! return (flush_meta(hashp) || mpool_sync(hashp->mp)); + } + + /* +*************** +*** 585,591 + hput_header(hashp); + + for (i = 0; i < NCACHED; i++) +! if (hashp->mapp[i]) + if (__put_page(hashp, + (PAGE16 *)hashp->mapp[i], A_BITMAP, 1)) + return (-1); + +--- 584,590 ----- + hput_header(hashp); + + for (i = 0; i < NCACHED; i++) +! if (hashp->mapp[i]) { + if (__put_page(hashp, + (PAGE16 *)hashp->mapp[i], A_BITMAP, 1)) + return (-1); +*************** +*** 589,594 + if (__put_page(hashp, + (PAGE16 *)hashp->mapp[i], A_BITMAP, 1)) + return (-1); + return (0); + } + + +--- 588,595 ----- + if (__put_page(hashp, + (PAGE16 *)hashp->mapp[i], A_BITMAP, 1)) + return (-1); ++ hashp->mapp[i] = NULL; ++ } + return (0); + } + +*************** +*** 726,732 + #ifdef HASH_STATISTICS + hash_collisions++; + #endif +- + __get_item_done(hashp, &cursor); + + /* + +--- 727,732 ----- + #ifdef HASH_STATISTICS + hash_collisions++; + #endif + __get_item_done(hashp, &cursor); + + /* +*************** +*** 773,778 + if (__delpair(hashp, &cursor, &item_info) || + __addel(hashp, &item_info, key, val, UNKNOWN, 0)) + return (ERROR); + if (item_info.caused_expand) + __expand_table(hashp); + break; + +--- 773,779 ----- + if (__delpair(hashp, &cursor, &item_info) || + __addel(hashp, &item_info, key, val, UNKNOWN, 0)) + return (ERROR); ++ __get_item_done(hashp, &cursor); + if (item_info.caused_expand) + __expand_table(hashp); + break; diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash.h b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash.h new file mode 100644 index 00000000..2f1e47bf --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash.h @@ -0,0 +1,196 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)hash.h 8.4 (Berkeley) 11/2/95 + */ + +#include "mpool.h" +#include "db-queue.h" + +/* Operations */ +typedef enum { + HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT +} ACTION; + +/* cursor structure */ +typedef struct cursor_t { + TAILQ_ENTRY(cursor_t) queue; + int (*get) __P((const DB *, struct cursor_t *, DBT *, DBT *, \ + u_int32_t)); + int (*delete) __P((const DB *, struct cursor_t *, u_int32_t)); + db_pgno_t bucket; + db_pgno_t pgno; + indx_t ndx; + indx_t pgndx; + u_int16_t *pagep; + void *internal; +} CURSOR; + + +#define IS_BUCKET(X) ((X) & BUF_BUCKET) +#define IS_VALID(X) (!((X) & BUF_INVALID)) + +/* Hash Table Information */ +typedef struct hashhdr { /* Disk resident portion */ + int32_t magic; /* Magic NO for hash tables */ + int32_t version; /* Version ID */ + int32_t lorder; /* Byte Order */ + u_int32_t bsize; /* Bucket/Page Size */ + int32_t bshift; /* Bucket shift */ + int32_t ovfl_point; /* Where overflow pages are being allocated */ + u_int32_t last_freed; /* Last overflow page freed */ + u_int32_t max_bucket; /* ID of Maximum bucket in use */ + u_int32_t high_mask; /* Mask to modulo into entire table */ + u_int32_t low_mask; /* Mask to modulo into lower half of table */ + u_int32_t ffactor; /* Fill factor */ + int32_t nkeys; /* Number of keys in hash table */ + u_int32_t hdrpages; /* Size of table header */ + u_int32_t h_charkey; /* value of hash(CHARKEY) */ +#define NCACHED 32 /* number of bit maps and spare points */ + u_int32_t spares[NCACHED];/* spare pages for overflow */ + u_int16_t bitmaps[NCACHED]; /* address of overflow page bitmaps */ +} HASHHDR; + +typedef struct htab { /* Memory resident data structure */ + TAILQ_HEAD(_cursor_queue, cursor_t) curs_queue; + HASHHDR hdr; /* Header */ + u_int32_t (*hash) __P((const void *, size_t)); /* Hash Function */ + int32_t flags; /* Flag values */ + int32_t fp; /* File pointer */ + const char *fname; /* File path */ + u_int8_t *bigdata_buf; /* Temporary Buffer for BIG data */ + u_int8_t *bigkey_buf; /* Temporary Buffer for BIG keys */ + u_int16_t *split_buf; /* Temporary buffer for splits */ + CURSOR *seq_cursor; /* Cursor used for hash_seq */ + int32_t local_errno; /* Error Number -- for DBM compatibility */ + int32_t new_file; /* Indicates if fd is backing store or no */ + int32_t save_file; /* Indicates whether we need to flush file at + * exit */ + u_int32_t *mapp[NCACHED];/* Pointers to page maps */ + int32_t nmaps; /* Initial number of bitmaps */ + MPOOL *mp; /* mpool for buffer management */ +} HTAB; + +/* + * Constants + */ +#define MAX_BSIZE 65536 /* 2^16 */ +#define MIN_BUFFERS 6 +#define MINHDRSIZE 512 +#define DEF_CACHESIZE 65536 +#define DEF_BUCKET_SHIFT 12 /* log2(BUCKET) */ +#define DEF_BUCKET_SIZE (1<> SPLITSHIFT) +#define OPAGENUM(N) ((N) & SPLITMASK) +#define OADDR_OF(S,O) ((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O)) + +#define BUCKET_TO_PAGE(B) \ + ((B) + hashp->hdr.hdrpages + ((B) \ + ? hashp->hdr.spares[__log2((B)+1)-1] : 0)) +#define OADDR_TO_PAGE(B) \ + (BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B))) + +#define POW2(N) (1 << (N)) + +#define MAX_PAGES(H) (DB_OFF_T_MAX / (H)->hdr.bsize) + +/* Shorthands for accessing structure */ +#define METADATA_PGNO 0 +#define SPLIT_PGNO 0xFFFF + +typedef struct item_info { + db_pgno_t pgno; + db_pgno_t bucket; + indx_t ndx; + indx_t pgndx; + u_int8_t status; + u_int32_t seek_size; + db_pgno_t seek_found_page; + indx_t key_off; + indx_t data_off; + u_int8_t caused_expand; +} ITEM_INFO; + + +#define ITEM_ERROR 0 +#define ITEM_OK 1 +#define ITEM_NO_MORE 2 + +#define ITEM_GET_FIRST 0 +#define ITEM_GET_NEXT 1 +#define ITEM_GET_RESET 2 +#define ITEM_GET_DONE 3 +#define ITEM_GET_N 4 + +#define UNKNOWN 0xffffffff /* for num_items */ +#define NO_EXPAND 0xfffffffe diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_bigkey.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_bigkey.c new file mode 100644 index 00000000..4b95278f --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_bigkey.c @@ -0,0 +1,481 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_bigkey.c 8.5 (Berkeley) 11/2/95"; +#endif /* LIBC_SCCS and not lint */ + +/* + * PACKAGE: hash + * DESCRIPTION: + * Big key/data handling for the hashing package. + * + * ROUTINES: + * External + * __big_keydata + * __big_split + * __big_insert + * __big_return + * __big_delete + * __find_last_page + * Internal + * collect_key + * collect_data + */ +#include + +#include +#include + +#ifdef DEBUG +#include +#endif + +#include "db-int.h" +#include "hash.h" +#include "page.h" +#include "extern.h" + +static int32_t collect_key __P((HTAB *, PAGE16 *, int32_t, db_pgno_t *)); +static int32_t collect_data __P((HTAB *, PAGE16 *, int32_t)); + +/* + * Big_insert + * + * You need to do an insert and the key/data pair is greater than + * MINFILL * the bucket size + * + * Returns: + * 0 ==> OK + * -1 ==> ERROR + */ +int32_t +__big_insert(hashp, pagep, key, val) + HTAB *hashp; + PAGE16 *pagep; + const DBT *key, *val; +{ + size_t key_size, val_size; + indx_t key_move_bytes, val_move_bytes; + int8_t *key_data, *val_data, base_page; + + key_data = (int8_t *)key->data; + key_size = key->size; + val_data = (int8_t *)val->data; + val_size = val->size; + + NUM_ENT(pagep) = NUM_ENT(pagep) + 1; + + for (base_page = 1; key_size + val_size;) { + /* Add a page! */ + pagep = + __add_bigpage(hashp, pagep, NUM_ENT(pagep) - 1, base_page); + if (!pagep) + return (-1); + + /* There's just going to be one entry on this page. */ + NUM_ENT(pagep) = 1; + + /* Move the key's data. */ + key_move_bytes = MIN(FREESPACE(pagep), key_size); + /* Mark the page as to how much key & data is on this page. */ + BIGKEYLEN(pagep) = key_move_bytes; + val_move_bytes = + MIN(FREESPACE(pagep) - key_move_bytes, val_size); + BIGDATALEN(pagep) = val_move_bytes; + + /* Note big pages build beginning --> end, not vice versa. */ + if (key_move_bytes) + memmove(BIGKEY(pagep), key_data, key_move_bytes); + if (val_move_bytes) + memmove(BIGDATA(pagep), val_data, val_move_bytes); + + key_size -= key_move_bytes; + key_data += key_move_bytes; + val_size -= val_move_bytes; + val_data += val_move_bytes; + + base_page = 0; + } + __put_page(hashp, pagep, A_RAW, 1); + return (0); +} + +/* + * Called when we need to delete a big pair. + * + * Returns: + * 0 => OK + * -1 => ERROR + */ +int32_t +#ifdef __STDC__ +__big_delete(HTAB *hashp, PAGE16 *pagep, indx_t ndx) +#else +__big_delete(hashp, pagep, ndx) + HTAB *hashp; + PAGE16 *pagep; + u_int32_t ndx; /* Index of big pair on base page. */ +#endif +{ + PAGE16 *last_pagep; + + /* Get first page with big key/data. */ + pagep = __get_page(hashp, OADDR_TO_PAGE(DATA_OFF(pagep, ndx)), A_RAW); + if (!pagep) + return (-1); + + /* + * Traverse through the pages, freeing the previous one (except + * the first) at each new page. + */ + while (NEXT_PGNO(pagep) != INVALID_PGNO) { + last_pagep = pagep; + pagep = __get_page(hashp, NEXT_PGNO(pagep), A_RAW); + if (!pagep) + return (-1); + __delete_page(hashp, last_pagep, A_OVFL); + } + + /* Free the last page in the chain. */ + __delete_page(hashp, pagep, A_OVFL); + return (0); +} + +/* + * Given a key, indicates whether the big key at cursorp matches the + * given key. + * + * Returns: + * 1 = Found! + * 0 = Key not found + * -1 error + */ +int32_t +__find_bigpair(hashp, cursorp, key, size) + HTAB *hashp; + CURSOR *cursorp; + int8_t *key; + int32_t size; +{ + PAGE16 *pagep, *hold_pagep; + db_pgno_t next_pgno; + int32_t ksize; + int8_t *kkey; + + ksize = size; + kkey = key; + + hold_pagep = NULL; + /* Chances are, hashp->cpage is the base page. */ + if (cursorp->pagep) + pagep = hold_pagep = cursorp->pagep; + else { + pagep = __get_page(hashp, cursorp->pgno, A_RAW); + if (!pagep) + return (-1); + } + + /* + * Now, get the first page with the big stuff on it. + * + * XXX + * KLUDGE: we know that cursor is looking at the _next_ item, so + * we have to look at pgndx - 1. + */ + next_pgno = OADDR_TO_PAGE(DATA_OFF(pagep, (cursorp->pgndx - 1))); + if (!hold_pagep) + __put_page(hashp, pagep, A_RAW, 0); + pagep = __get_page(hashp, next_pgno, A_RAW); + if (!pagep) + return (-1); + + /* While there are both keys to compare. */ + while ((ksize > 0) && (BIGKEYLEN(pagep))) { + if (ksize < KEY_OFF(pagep, 0) || + memcmp(BIGKEY(pagep), kkey, BIGKEYLEN(pagep))) { + __put_page(hashp, pagep, A_RAW, 0); + return (0); + } + kkey += BIGKEYLEN(pagep); + ksize -= BIGKEYLEN(pagep); + if (NEXT_PGNO(pagep) != INVALID_PGNO) { + next_pgno = NEXT_PGNO(pagep); + __put_page(hashp, pagep, A_RAW, 0); + pagep = __get_page(hashp, next_pgno, A_RAW); + if (!pagep) + return (-1); + } + } + __put_page(hashp, pagep, A_RAW, 0); +#ifdef DEBUG + assert(ksize >= 0); +#endif + if (ksize != 0) { +#ifdef HASH_STATISTICS + ++hash_collisions; +#endif + return (0); + } else + return (1); +} + +/* + * Fill in the key and data for this big pair. + */ +int32_t +__big_keydata(hashp, pagep, key, val, ndx) + HTAB *hashp; + PAGE16 *pagep; + DBT *key, *val; + int32_t ndx; +{ + ITEM_INFO ii; + PAGE16 *key_pagep; + db_pgno_t last_page; + + key_pagep = + __get_page(hashp, OADDR_TO_PAGE(DATA_OFF(pagep, ndx)), A_RAW); + if (!key_pagep) + return (-1); + key->size = collect_key(hashp, key_pagep, 0, &last_page); + key->data = hashp->bigkey_buf; + __put_page(hashp, key_pagep, A_RAW, 0); + + if (key->size == (size_t)-1) + return (-1); + + /* Create an item_info to direct __big_return to the beginning pgno. */ + ii.pgno = last_page; + return (__big_return(hashp, &ii, val, 1)); +} + +/* + * Return the big key on page, ndx. + */ +int32_t +#ifdef __STDC__ +__get_bigkey(HTAB *hashp, PAGE16 *pagep, indx_t ndx, DBT *key) +#else +__get_bigkey(hashp, pagep, ndx, key) + HTAB *hashp; + PAGE16 *pagep; + u_int32_t ndx; + DBT *key; +#endif +{ + PAGE16 *key_pagep; + + key_pagep = + __get_page(hashp, OADDR_TO_PAGE(DATA_OFF(pagep, ndx)), A_RAW); + if (!key_pagep) + return (-1); + key->size = collect_key(hashp, key_pagep, 0, NULL); + key->data = hashp->bigkey_buf; + + __put_page(hashp, key_pagep, A_RAW, 0); + + return (0); +} + +/* + * Return the big key and data indicated in item_info. + */ +int32_t +__big_return(hashp, item_info, val, on_bigkey_page) + HTAB *hashp; + ITEM_INFO *item_info; + DBT *val; + int32_t on_bigkey_page; +{ + PAGE16 *pagep; + db_pgno_t next_pgno; + + if (!on_bigkey_page) { + /* Get first page with big pair on it. */ + pagep = __get_page(hashp, + OADDR_TO_PAGE(item_info->data_off), A_RAW); + if (!pagep) + return (-1); + } else { + pagep = __get_page(hashp, item_info->pgno, A_RAW); + if (!pagep) + return (-1); + } + + /* Traverse through the bigkey pages until a page with data is found. */ + while (!BIGDATALEN(pagep)) { + next_pgno = NEXT_PGNO(pagep); + __put_page(hashp, pagep, A_RAW, 0); + pagep = __get_page(hashp, next_pgno, A_RAW); + if (!pagep) + return (-1); + } + + val->size = collect_data(hashp, pagep, 0); + if (val->size < 1) + return (-1); + val->data = (void *)hashp->bigdata_buf; + + __put_page(hashp, pagep, A_RAW, 0); + return (0); +} + +/* + * Given a page with a big key on it, traverse through the pages counting data + * length, and collect all of the data on the way up. Store the key in + * hashp->bigkey_buf. last_page indicates to the calling function what the + * last page with key on it is; this will help if you later want to retrieve + * the data portion. + * + * Does the work for __get_bigkey. + * + * Return total length of data; -1 if error. + */ +static int32_t +collect_key(hashp, pagep, len, last_page) + HTAB *hashp; + PAGE16 *pagep; + int32_t len; + db_pgno_t *last_page; +{ + PAGE16 *next_pagep; + int32_t totlen, retval; + db_pgno_t next_pgno; +#ifdef DEBUG + db_pgno_t save_addr; +#endif + + /* If this is the last page with key. */ + if (BIGDATALEN(pagep)) { + totlen = len + BIGKEYLEN(pagep); + if (hashp->bigkey_buf) + free(hashp->bigkey_buf); + hashp->bigkey_buf = (u_int8_t *)malloc(totlen); + if (!hashp->bigkey_buf) + return (-1); + memcpy(hashp->bigkey_buf + len, + BIGKEY(pagep), BIGKEYLEN(pagep)); + if (last_page) + *last_page = ADDR(pagep); + return (totlen); + } + + /* Key filled up all of last key page, so we've gone 1 too far. */ + if (BIGKEYLEN(pagep) == 0) { + if (hashp->bigkey_buf) + free(hashp->bigkey_buf); + hashp->bigkey_buf = (u_int8_t *)malloc(len); + return (hashp->bigkey_buf ? len : -1); + } + totlen = len + BIGKEYLEN(pagep); + + /* Set pagep to the next page in the chain. */ + if (last_page) + *last_page = ADDR(pagep); + next_pgno = NEXT_PGNO(pagep); + next_pagep = __get_page(hashp, next_pgno, A_RAW); + if (!next_pagep) + return (-1); +#ifdef DEBUG + save_addr = ADDR(pagep); +#endif + retval = collect_key(hashp, next_pagep, totlen, last_page); + +#ifdef DEBUG + assert(save_addr == ADDR(pagep)); +#endif + memcpy(hashp->bigkey_buf + len, BIGKEY(pagep), BIGKEYLEN(pagep)); + __put_page(hashp, next_pagep, A_RAW, 0); + + return (retval); +} + +/* + * Given a page with big data on it, recur through the pages counting data + * length, and collect all of the data on the way up. Store the data in + * hashp->bigdata_buf. + * + * Does the work for __big_return. + * + * Return total length of data; -1 if error. + */ +static int32_t +collect_data(hashp, pagep, len) + HTAB *hashp; + PAGE16 *pagep; + int32_t len; +{ + PAGE16 *next_pagep; + int32_t totlen, retval; + db_pgno_t next_pgno; +#ifdef DEBUG + db_pgno_t save_addr; +#endif + + /* If there is no next page. */ + if (NEXT_PGNO(pagep) == INVALID_PGNO) { + if (hashp->bigdata_buf) + free(hashp->bigdata_buf); + totlen = len + BIGDATALEN(pagep); + hashp->bigdata_buf = (u_int8_t *)malloc(totlen); + if (!hashp->bigdata_buf) + return (-1); + memcpy(hashp->bigdata_buf + totlen - BIGDATALEN(pagep), + BIGDATA(pagep), BIGDATALEN(pagep)); + return (totlen); + } + totlen = len + BIGDATALEN(pagep); + + /* Set pagep to the next page in the chain. */ + next_pgno = NEXT_PGNO(pagep); + next_pagep = __get_page(hashp, next_pgno, A_RAW); + if (!next_pagep) + return (-1); + +#ifdef DEBUG + save_addr = ADDR(pagep); +#endif + retval = collect_data(hashp, next_pagep, totlen); +#ifdef DEBUG + assert(save_addr == ADDR(pagep)); +#endif + memcpy(hashp->bigdata_buf + totlen - BIGDATALEN(pagep), + BIGDATA(pagep), BIGDATALEN(pagep)); + __put_page(hashp, next_pagep, A_RAW, 0); + + return (retval); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_debug.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_debug.c new file mode 100644 index 00000000..43f537f5 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_debug.c @@ -0,0 +1,106 @@ +/*- + * Copyright (c) 1995 + * The President and Fellows of Harvard University + * + * This code is derived from software contributed to Harvard by + * Jeremy Rassen. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_debug.c 8.4 (Berkeley) 11/7/95"; +#endif /* LIBC_SCCS and not lint */ + +#ifdef DEBUG +/* + * PACKAGE: hashing + * + * DESCRIPTION: + * Debug routines. + * + * ROUTINES: + * + * External + * __dump_bucket + */ +#include +#include + +#include "db-int.h" +#include "hash.h" +#include "page.h" +#include "extern.h" + +void +__dump_bucket(hashp, bucket) + HTAB *hashp; + u_int32_t bucket; +{ + CURSOR cursor; + DBT key, val; + ITEM_INFO item_info; + int var; + char *cp; + + cursor.pagep = NULL; + item_info.seek_size = 0; + item_info.seek_found_page = 0; + + __get_item_reset(hashp, &cursor); + + cursor.bucket = bucket; + for (;;) { + __get_item_next(hashp, &cursor, &key, &val, &item_info); + if (item_info.status == ITEM_ERROR) { + (void)printf("get_item_next returned error\n"); + break; + } else if (item_info.status == ITEM_NO_MORE) + break; + + if (item_info.key_off == BIGPAIR) { + if (__big_keydata(hashp, cursor.pagep, &key, &val, + item_info.pgndx)) { + (void)printf("__big_keydata returned error\n"); + break; + } + } + + if (key.size == sizeof(int)) { + memcpy(&var, key.data, sizeof(int)); + (void)printf("%d\n", var); + } else { + for (cp = (char *)key.data; key.size--; cp++) + (void)printf("%c", *cp); + (void)printf("\n"); + } + } + __get_item_done(hashp, &cursor); +} +#endif /* DEBUG */ diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_func.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_func.c new file mode 100644 index 00000000..1dee6946 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_func.c @@ -0,0 +1,201 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_func.c 8.4 (Berkeley) 11/7/95"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include "db-int.h" +#include "hash.h" +#include "page.h" +#include "extern.h" + +#if 0 +static u_int32_t hash1 __P((const void *, size_t)); +static u_int32_t hash2 __P((const void *, size_t)); +static u_int32_t hash3 __P((const void *, size_t)); +#endif +static u_int32_t hash4 __P((const void *, size_t)); + +/* Default hash function. */ +u_int32_t (*__default_hash) __P((const void *, size_t)) = hash4; + +/* + * Assume that we've already split the bucket to which this key hashes, + * calculate that bucket, and check that in fact we did already split it. + * + * EJB's original hsearch hash. + */ +#define PRIME1 37 +#define PRIME2 1048583 + +#if 0 +static u_int32_t +hash1(key, len) + const void *key; + size_t len; +{ + u_int32_t h; + u_int8_t *k; + + h = 0; + k = (u_int8_t *)key; + /* Convert string to integer */ + while (len--) + h = h * PRIME1 ^ (*k++ - ' '); + h %= PRIME2; + return (h); +} + +/* + * Phong Vo's linear congruential hash + */ +#define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c)) + +static u_int32_t +hash2(key, len) + const void *key; + size_t len; +{ + u_int32_t h; + u_int8_t *e, c, *k; + + k = (u_int8_t *)key; + e = k + len; + for (h = 0; k != e;) { + c = *k++; + if (!c && k > e) + break; + dcharhash(h, c); + } + return (h); +} + +/* + * This is INCREDIBLY ugly, but fast. We break the string up into 8 byte + * units. On the first time through the loop we get the "leftover bytes" + * (strlen % 8). On every other iteration, we perform 8 HASHC's so we handle + * all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If + * this routine is heavily used enough, it's worth the ugly coding. + * + * Ozan Yigit's original sdbm hash. + */ +static u_int32_t +hash3(key, len) + const void *key; + size_t len; +{ + u_int32_t n, loop; + u_int8_t *k; + +#define HASHC n = *k++ + 65599 * n + + n = 0; + k = (u_int8_t *)key; + if (len > 0) { + loop = (len + 8 - 1) >> 3; + + switch (len & (8 - 1)) { + case 0: + do { /* All fall throughs */ + HASHC; + case 7: + HASHC; + case 6: + HASHC; + case 5: + HASHC; + case 4: + HASHC; + case 3: + HASHC; + case 2: + HASHC; + case 1: + HASHC; + } while (--loop); + } + + } + return (n); +} +#endif + + +/* Chris Torek's hash function. */ +static u_int32_t +hash4(key, len) + const void *key; + size_t len; +{ + u_int32_t h, loop; + const u_int8_t *k; + +#define HASH4a h = (h << 5) - h + *k++; +#define HASH4b h = (h << 5) + h + *k++; +#define HASH4 HASH4b + + h = 0; + k = (const u_int8_t *)key; + if (len > 0) { + loop = (len + 8 - 1) >> 3; + + switch (len & (8 - 1)) { + case 0: + do { /* All fall throughs */ + HASH4; + case 7: + HASH4; + case 6: + HASH4; + case 5: + HASH4; + case 4: + HASH4; + case 3: + HASH4; + case 2: + HASH4; + case 1: + HASH4; + } while (--loop); + } + + } + return (h); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_log2.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_log2.c new file mode 100644 index 00000000..8c710e5d --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_log2.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_log2.c 8.4 (Berkeley) 11/7/95"; +#endif /* LIBC_SCCS and not lint */ + +#include "db-int.h" +#include "hash.h" +#include "page.h" +#include "extern.h" + +u_int32_t +__kdb2_log2(num) + u_int32_t num; +{ + u_int32_t i, limit; + + limit = 1; + for (i = 0; limit < num; limit = limit << 1, i++); + return (i); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_page.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_page.c new file mode 100644 index 00000000..0da35710 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hash_page.c @@ -0,0 +1,1362 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hash_page.c 8.11 (Berkeley) 11/7/95"; +#endif /* LIBC_SCCS and not lint */ + +/* + * PACKAGE: hashing + * + * DESCRIPTION: + * Page manipulation for hashing package. + * + * ROUTINES: + * + * External + * __get_page + * __add_ovflpage + * Internal + * overflow_page + * open_temp + */ + +#include + +#ifdef DEBUG +#include +#endif +#include +#include +#include +#include + +#include "db-int.h" +#include "hash.h" +#include "page.h" +#include "extern.h" + +static int32_t add_bigptr __P((HTAB *, ITEM_INFO *, indx_t)); +static u_int32_t *fetch_bitmap __P((HTAB *, int32_t)); +static u_int32_t first_free __P((u_int32_t)); +static u_int16_t overflow_page __P((HTAB *)); +static void page_init __P((HTAB *, PAGE16 *, db_pgno_t, u_int8_t)); +static indx_t prev_realkey __P((PAGE16 *, indx_t)); +static void putpair __P((PAGE8 *, const DBT *, const DBT *)); +static void swap_page_header_in __P((PAGE16 *)); +static void swap_page_header_out __P((PAGE16 *)); + +#ifdef DEBUG_SLOW +static void account_page(HTAB *, db_pgno_t, int); +#endif + +u_int32_t +__get_item(hashp, cursorp, key, val, item_info) + HTAB *hashp; + CURSOR *cursorp; + DBT *key, *val; + ITEM_INFO *item_info; +{ + db_pgno_t next_pgno; + int32_t i; + + /* Check if we need to get a page. */ + if (!cursorp->pagep) { + if (cursorp->pgno == INVALID_PGNO) { + cursorp->pagep = + __get_page(hashp, cursorp->bucket, A_BUCKET); + cursorp->pgno = ADDR(cursorp->pagep); + cursorp->ndx = 0; + cursorp->pgndx = 0; + } else + cursorp->pagep = + __get_page(hashp, cursorp->pgno, A_RAW); + if (!cursorp->pagep) { + item_info->status = ITEM_ERROR; + return (-1); + } + } + if (item_info->seek_size && + FREESPACE(cursorp->pagep) > item_info->seek_size) + item_info->seek_found_page = cursorp->pgno; + + if (cursorp->pgndx == NUM_ENT(cursorp->pagep)) { + /* Fetch next page. */ + if (NEXT_PGNO(cursorp->pagep) == INVALID_PGNO) { + item_info->status = ITEM_NO_MORE; + return (-1); + } + next_pgno = NEXT_PGNO(cursorp->pagep); + cursorp->pgndx = 0; + __put_page(hashp, cursorp->pagep, A_RAW, 0); + cursorp->pagep = __get_page(hashp, next_pgno, A_RAW); + if (!cursorp->pagep) { + item_info->status = ITEM_ERROR; + return (-1); + } + cursorp->pgno = next_pgno; + } + if (KEY_OFF(cursorp->pagep, cursorp->pgndx) != BIGPAIR) { + if ((i = prev_realkey(cursorp->pagep, cursorp->pgndx)) == + cursorp->pgndx) + key->size = hashp->hdr.bsize - + KEY_OFF(cursorp->pagep, cursorp->pgndx); + else + key->size = DATA_OFF(cursorp->pagep, i) - + KEY_OFF(cursorp->pagep, cursorp->pgndx); + } + + /* + * All of this information will be set incorrectly for big keys, but + * it will be ignored anyway. + */ + val->size = KEY_OFF(cursorp->pagep, cursorp->pgndx) - + DATA_OFF(cursorp->pagep, cursorp->pgndx); + key->data = KEY(cursorp->pagep, cursorp->pgndx); + val->data = DATA(cursorp->pagep, cursorp->pgndx); + item_info->pgno = cursorp->pgno; + item_info->bucket = cursorp->bucket; + item_info->ndx = cursorp->ndx; + item_info->pgndx = cursorp->pgndx; + item_info->key_off = KEY_OFF(cursorp->pagep, cursorp->pgndx); + item_info->data_off = DATA_OFF(cursorp->pagep, cursorp->pgndx); + item_info->status = ITEM_OK; + + return (0); +} + +u_int32_t +__get_item_reset(hashp, cursorp) + HTAB *hashp; + CURSOR *cursorp; +{ + if (cursorp->pagep) + __put_page(hashp, cursorp->pagep, A_RAW, 0); + cursorp->pagep = NULL; + cursorp->bucket = -1; + cursorp->ndx = 0; + cursorp->pgndx = 0; + cursorp->pgno = INVALID_PGNO; + return (0); +} + +u_int32_t +__get_item_done(hashp, cursorp) + HTAB *hashp; + CURSOR *cursorp; +{ + if (cursorp->pagep) + __put_page(hashp, cursorp->pagep, A_RAW, 0); + cursorp->pagep = NULL; + + /* + * We don't throw out the page number since we might want to + * continue getting on this page. + */ + return (0); +} + +u_int32_t +__get_item_first(hashp, cursorp, key, val, item_info) + HTAB *hashp; + CURSOR *cursorp; + DBT *key, *val; + ITEM_INFO *item_info; +{ + __get_item_reset(hashp, cursorp); + cursorp->bucket = 0; + return (__get_item_next(hashp, cursorp, key, val, item_info)); +} + +/* + * Returns a pointer to key/data pair on a page. In the case of bigkeys, + * just returns the page number and index of the bigkey pointer pair. + */ +u_int32_t +__get_item_next(hashp, cursorp, key, val, item_info) + HTAB *hashp; + CURSOR *cursorp; + DBT *key, *val; + ITEM_INFO *item_info; +{ + int status; + + status = __get_item(hashp, cursorp, key, val, item_info); + cursorp->ndx++; + cursorp->pgndx++; + return (status); +} + +/* + * Put a non-big pair on a page. + */ +static void +putpair(p, key, val) + PAGE8 *p; + const DBT *key, *val; +{ + u_int16_t *pagep, n, off; + + pagep = (PAGE16 *)(void *)p; + + /* Items on the page are 0-indexed. */ + n = NUM_ENT(pagep); + off = OFFSET(pagep) - key->size + 1; + memmove(p + off, key->data, key->size); + KEY_OFF(pagep, n) = off; + + off -= val->size; + memmove(p + off, val->data, val->size); + DATA_OFF(pagep, n) = off; + + /* Adjust page info. */ + NUM_ENT(pagep) = n + 1; + OFFSET(pagep) = off - 1; +} + +/* + * Returns the index of the previous non-bigkey pair after n on the page. + * Returns n if there are no previous non-big things on the page. + */ +static indx_t +#ifdef __STDC__ +prev_realkey(PAGE16 * pagep, indx_t n) +#else +prev_realkey(pagep, n) + PAGE16 *pagep; + u_int32_t n; +#endif +{ + int32_t i; + + /* Need a signed value to do the compare properly. */ + for (i = n - 1; i > -1; i--) + if (KEY_OFF(pagep, i) != BIGPAIR) + return (i); + return (n); +} + +/* + * Returns: + * 0 OK + * -1 error + */ +extern int32_t +__delpair(hashp, cursorp, item_info) + HTAB *hashp; + CURSOR *cursorp; + ITEM_INFO *item_info; +{ + PAGE16 *pagep; + indx_t ndx; + short check_ndx; + int16_t delta, len; + int32_t n; + u_int8_t *src, *dest; + + ndx = cursorp->pgndx; + if (!cursorp->pagep) { + pagep = __get_page(hashp, cursorp->pgno, A_RAW); + if (!pagep) + return (-1); + /* + * KLUGE: pgndx has gone one too far, because cursor points + * to the _next_ item. Use pgndx - 1. + */ + --ndx; + } else + pagep = cursorp->pagep; +#ifdef DEBUG + assert(ADDR(pagep) == cursorp->pgno); +#endif + + if (KEY_OFF(pagep, ndx) == BIGPAIR) { + delta = 0; + __big_delete(hashp, pagep, ndx); + } else { + /* + * Compute "delta", the amount we have to shift all of the + * offsets. To find the delta, we need to make sure that + * we aren't looking at the DATA_OFF of a big/keydata pair. + */ + for (check_ndx = (short)(ndx - 1); + check_ndx >= 0 && KEY_OFF(pagep, check_ndx) == BIGPAIR; + check_ndx--); + if (check_ndx < 0) + delta = hashp->hdr.bsize - DATA_OFF(pagep, ndx); + else + delta = + DATA_OFF(pagep, check_ndx) - DATA_OFF(pagep, ndx); + + /* + * The hard case: we want to remove something other than + * the last item on the page. We need to shift data and + * offsets down. + */ + if (ndx != NUM_ENT(pagep) - 1) { + /* + * Move the data: src is the address of the last data + * item on the page. + */ + src = (u_int8_t *)pagep + OFFSET(pagep) + 1; + /* + * Length is the distance between where to start + * deleting and end of the data on the page. + */ + len = DATA_OFF(pagep, ndx) - (OFFSET(pagep) + 1); + /* + * Dest is the location of the to-be-deleted item + * occupied - length. + */ + if (check_ndx < 0) + dest = + (u_int8_t *)pagep + hashp->hdr.bsize - len; + else + dest = (u_int8_t *)pagep + + DATA_OFF(pagep, (check_ndx)) - len; + memmove(dest, src, len); + } + } + + /* Adjust the offsets. */ + for (n = ndx; n < NUM_ENT(pagep) - 1; n++) + if (KEY_OFF(pagep, (n + 1)) != BIGPAIR) { + KEY_OFF(pagep, n) = KEY_OFF(pagep, (n + 1)) + delta; + DATA_OFF(pagep, n) = DATA_OFF(pagep, (n + 1)) + delta; + } else { + KEY_OFF(pagep, n) = KEY_OFF(pagep, (n + 1)); + DATA_OFF(pagep, n) = DATA_OFF(pagep, (n + 1)); + } + + /* Adjust page metadata. */ + OFFSET(pagep) = OFFSET(pagep) + delta; + NUM_ENT(pagep) = NUM_ENT(pagep) - 1; + + --hashp->hdr.nkeys; + + /* Is this page now an empty overflow page? If so, free it. */ + if (TYPE(pagep) == HASH_OVFLPAGE && NUM_ENT(pagep) == 0) { + PAGE16 *empty_page; + db_pgno_t to_find, next_pgno, link_page; + + /* + * We need to go back to the first page in the chain and + * look for this page so that we can update the previous + * page's NEXT_PGNO field. + */ + to_find = ADDR(pagep); + empty_page = pagep; + link_page = NEXT_PGNO(empty_page); + pagep = __get_page(hashp, item_info->bucket, A_BUCKET); + if (!pagep) + return (-1); + while (NEXT_PGNO(pagep) != to_find) { + next_pgno = NEXT_PGNO(pagep); +#ifdef DEBUG + assert(next_pgno != INVALID_PGNO); +#endif + __put_page(hashp, pagep, A_RAW, 0); + pagep = __get_page(hashp, next_pgno, A_RAW); + if (!pagep) + return (-1); + } + + /* + * At this point, pagep should point to the page before the + * page to be deleted. + */ + NEXT_PGNO(pagep) = link_page; + if (item_info->pgno == to_find) { + item_info->pgno = ADDR(pagep); + item_info->pgndx = NUM_ENT(pagep); + item_info->seek_found_page = ADDR(pagep); + } + __delete_page(hashp, empty_page, A_OVFL); + } + __put_page(hashp, pagep, A_RAW, 1); + + return (0); +} + +extern int32_t +__split_page(hashp, obucket, nbucket) + HTAB *hashp; + u_int32_t obucket, nbucket; +{ + DBT key, val; + ITEM_INFO old_ii, new_ii; + PAGE16 *old_pagep, *temp_pagep; + db_pgno_t next_pgno; + int32_t off; + u_int16_t n; + int8_t base_page; + + off = hashp->hdr.bsize; + old_pagep = __get_page(hashp, obucket, A_BUCKET); + + base_page = 1; + + temp_pagep = hashp->split_buf; + memcpy(temp_pagep, old_pagep, hashp->hdr.bsize); + + page_init(hashp, old_pagep, ADDR(old_pagep), HASH_PAGE); + __put_page(hashp, old_pagep, A_RAW, 1); + + old_ii.pgno = BUCKET_TO_PAGE(obucket); + new_ii.pgno = BUCKET_TO_PAGE(nbucket); + old_ii.bucket = obucket; + new_ii.bucket = nbucket; + old_ii.seek_found_page = new_ii.seek_found_page = 0; + + while (temp_pagep != 0) { + off = hashp->hdr.bsize; + for (n = 0; n < NUM_ENT(temp_pagep); n++) { + if (KEY_OFF(temp_pagep, n) == BIGPAIR) { + __get_bigkey(hashp, temp_pagep, n, &key); + if (__call_hash(hashp, + key.data, key.size) == obucket) + add_bigptr(hashp, &old_ii, + DATA_OFF(temp_pagep, n)); + else + add_bigptr(hashp, &new_ii, + DATA_OFF(temp_pagep, n)); + } else { + key.size = off - KEY_OFF(temp_pagep, n); + key.data = KEY(temp_pagep, n); + off = KEY_OFF(temp_pagep, n); + val.size = off - DATA_OFF(temp_pagep, n); + val.data = DATA(temp_pagep, n); + if (__call_hash(hashp, + key.data, key.size) == obucket) + __addel(hashp, &old_ii, &key, &val, + NO_EXPAND, 1); + else + __addel(hashp, &new_ii, &key, &val, + NO_EXPAND, 1); + off = DATA_OFF(temp_pagep, n); + } + } + next_pgno = NEXT_PGNO(temp_pagep); + + /* Clear temp_page; if it's an overflow page, free it. */ + if (!base_page) + __delete_page(hashp, temp_pagep, A_OVFL); + else + base_page = 0; + if (next_pgno != INVALID_PGNO) + temp_pagep = __get_page(hashp, next_pgno, A_RAW); + else + break; + } + return (0); +} + +/* + * Add the given pair to the page. + * + * + * Returns: + * 0 ==> OK + * -1 ==> failure + */ +extern int32_t +#ifdef __STDC__ +__addel(HTAB *hashp, ITEM_INFO *item_info, const DBT *key, const DBT *val, + u_int32_t num_items, const u_int8_t expanding) +#else +__addel(hashp, item_info, key, val, num_items, expanding) + HTAB *hashp; + ITEM_INFO *item_info; + const DBT *key, *val; + u_int32_t num_items; + const u_int32_t expanding; +#endif +{ + PAGE16 *pagep; + int32_t do_expand; + db_pgno_t next_pgno; + + do_expand = 0; + + pagep = __get_page(hashp, + item_info->seek_found_page != 0 ? + item_info->seek_found_page : item_info->pgno, A_RAW); + if (!pagep) + return (-1); + + /* Advance to first page in chain with room for item. */ + while (NUM_ENT(pagep) && NEXT_PGNO(pagep) != INVALID_PGNO) { + /* + * This may not be the end of the chain, but the pair may fit + * anyway. + */ + if (ISBIG(PAIRSIZE(key, val), hashp) && BIGPAIRFITS(pagep)) + break; + if (PAIRFITS(pagep, key, val)) + break; + next_pgno = NEXT_PGNO(pagep); + __put_page(hashp, pagep, A_RAW, 0); + pagep = (PAGE16 *)__get_page(hashp, next_pgno, A_RAW); + if (!pagep) + return (-1); + } + + if ((ISBIG(PAIRSIZE(key, val), hashp) && + !BIGPAIRFITS(pagep)) || + (!ISBIG(PAIRSIZE(key, val), hashp) && + !PAIRFITS(pagep, key, val))) { + do_expand = 1; + pagep = __add_ovflpage(hashp, pagep); + if (!pagep) + return (-1); + + if ((ISBIG(PAIRSIZE(key, val), hashp) && + !BIGPAIRFITS(pagep)) || + (!ISBIG(PAIRSIZE(key, val), hashp) && + !PAIRFITS(pagep, key, val))) { + __put_page(hashp, pagep, A_RAW, 0); + return (-1); + } + } + + /* At this point, we know the page fits, so we just add it */ + + if (ISBIG(PAIRSIZE(key, val), hashp)) { + if (__big_insert(hashp, pagep, key, val)) + return (-1); + } else { + putpair((PAGE8 *)pagep, key, val); + } + + /* + * For splits, we are going to update item_info's page number + * field, so that we can easily return to the same page the + * next time we come in here. For other operations, this shouldn't + * matter, since adds are the last thing that happens before we + * return to the user program. + */ + item_info->pgno = ADDR(pagep); + + if (!expanding) + hashp->hdr.nkeys++; + + /* Kludge: if this is a big page, then it's already been put. */ + if (!ISBIG(PAIRSIZE(key, val), hashp)) + __put_page(hashp, pagep, A_RAW, 1); + + if (expanding) + item_info->caused_expand = 0; + else + switch (num_items) { + case NO_EXPAND: + item_info->caused_expand = 0; + break; + case UNKNOWN: + item_info->caused_expand |= + (hashp->hdr.nkeys / hashp->hdr.max_bucket) > + hashp->hdr.ffactor || + item_info->pgndx > hashp->hdr.ffactor; + break; + default: + item_info->caused_expand = + num_items > hashp->hdr.ffactor ? 1 : do_expand; + break; + } + return (0); +} + +/* + * Special __addel used in big splitting; this one just puts the pointer + * to an already-allocated big page in the appropriate bucket. + */ +static int32_t +#ifdef __STDC__ +add_bigptr(HTAB * hashp, ITEM_INFO * item_info, indx_t big_pgno) +#else +add_bigptr(hashp, item_info, big_pgno) + HTAB *hashp; + ITEM_INFO *item_info; + u_int32_t big_pgno; +#endif +{ + PAGE16 *pagep; + db_pgno_t next_pgno; + + pagep = __get_page(hashp, item_info->bucket, A_BUCKET); + if (!pagep) + return (-1); + + /* + * Note: in __addel(), we used item_info->pgno for the beginning of + * our search for space. Now, we use item_info->bucket, since we + * know that the space required by a big pair on the base page is + * quite small, and we may very well find that space early in the + * chain. + */ + + /* Find first page in chain that has space for a big pair. */ + while (NUM_ENT(pagep) && (NEXT_PGNO(pagep) != INVALID_PGNO)) { + if (BIGPAIRFITS(pagep)) + break; + next_pgno = NEXT_PGNO(pagep); + __put_page(hashp, pagep, A_RAW, 0); + pagep = __get_page(hashp, next_pgno, A_RAW); + if (!pagep) + return (-1); + } + if (!BIGPAIRFITS(pagep)) { + pagep = __add_ovflpage(hashp, pagep); + if (!pagep) + return (-1); +#ifdef DEBUG + assert(BIGPAIRFITS(pagep)); +#endif + } + KEY_OFF(pagep, NUM_ENT(pagep)) = BIGPAIR; + DATA_OFF(pagep, NUM_ENT(pagep)) = big_pgno; + NUM_ENT(pagep) = NUM_ENT(pagep) + 1; + + __put_page(hashp, pagep, A_RAW, 1); + + return (0); +} + +/* + * + * Returns: + * pointer on success + * NULL on error + */ +extern PAGE16 * +__add_ovflpage(hashp, pagep) + HTAB *hashp; + PAGE16 *pagep; +{ + PAGE16 *new_pagep; + u_int16_t ovfl_num; + + /* Check if we are dynamically determining the fill factor. */ + if (hashp->hdr.ffactor == DEF_FFACTOR) { + hashp->hdr.ffactor = NUM_ENT(pagep) >> 1; + if (hashp->hdr.ffactor < MIN_FFACTOR) + hashp->hdr.ffactor = MIN_FFACTOR; + } + ovfl_num = overflow_page(hashp); + if (!ovfl_num) + return (NULL); + + if (__new_page(hashp, (u_int32_t)ovfl_num, A_OVFL) != 0) + return (NULL); + + if (!ovfl_num || !(new_pagep = __get_page(hashp, ovfl_num, A_OVFL))) + return (NULL); + + NEXT_PGNO(pagep) = (db_pgno_t)OADDR_TO_PAGE(ovfl_num); + TYPE(new_pagep) = HASH_OVFLPAGE; + + __put_page(hashp, pagep, A_RAW, 1); + +#ifdef HASH_STATISTICS + hash_overflows++; +#endif + return (new_pagep); +} + +/* + * + * Returns: + * pointer on success + * NULL on error + */ +extern PAGE16 * +#ifdef __STDC__ +__add_bigpage(HTAB * hashp, PAGE16 * pagep, indx_t ndx, const u_int8_t + is_basepage) +#else +__add_bigpage(hashp, pagep, ndx, is_basepage) + HTAB *hashp; + PAGE16 *pagep; + u_int32_t ndx; + const u_int32_t is_basepage; +#endif +{ + PAGE16 *new_pagep; + u_int16_t ovfl_num; + + ovfl_num = overflow_page(hashp); + if (!ovfl_num) + return (NULL); + + if (__new_page(hashp, (u_int32_t)ovfl_num, A_OVFL) != 0) + return (NULL); + + if (!ovfl_num || !(new_pagep = __get_page(hashp, ovfl_num, A_OVFL))) + return (NULL); + + if (is_basepage) { + KEY_OFF(pagep, ndx) = BIGPAIR; + DATA_OFF(pagep, ndx) = (indx_t)ovfl_num; + } else + NEXT_PGNO(pagep) = ADDR(new_pagep); + + __put_page(hashp, pagep, A_RAW, 1); + + TYPE(new_pagep) = HASH_BIGPAGE; + +#ifdef HASH_STATISTICS + hash_bigpages++; +#endif + return (new_pagep); +} + +static void +#ifdef __STDC__ +page_init(HTAB * hashp, PAGE16 * pagep, db_pgno_t pgno, u_int8_t type) +#else +page_init(hashp, pagep, pgno, type) + HTAB *hashp; + PAGE16 *pagep; + db_pgno_t pgno; + u_int32_t type; +#endif +{ + NUM_ENT(pagep) = 0; + PREV_PGNO(pagep) = NEXT_PGNO(pagep) = INVALID_PGNO; + TYPE(pagep) = type; + OFFSET(pagep) = hashp->hdr.bsize - 1; + /* + * Note: since in the current version ADDR(pagep) == PREV_PGNO(pagep), + * make sure that ADDR(pagep) is set after resetting PREV_PGNO(pagep). + * We reset PREV_PGNO(pagep) just in case the macros are changed. + */ + ADDR(pagep) = pgno; + + return; +} + +int32_t +__new_page(hashp, addr, addr_type) + HTAB *hashp; + u_int32_t addr; + int32_t addr_type; +{ + db_pgno_t paddr; + PAGE16 *pagep; + + switch (addr_type) { /* Convert page number. */ + case A_BUCKET: + paddr = BUCKET_TO_PAGE(addr); + break; + case A_OVFL: + case A_BITMAP: + paddr = OADDR_TO_PAGE(addr); + break; + default: + paddr = addr; + break; + } + pagep = mpool_new(hashp->mp, &paddr, MPOOL_PAGE_REQUEST); + if (!pagep) + return (-1); +#if DEBUG_SLOW + account_page(hashp, paddr, 1); +#endif + + if (addr_type != A_BITMAP) + page_init(hashp, pagep, paddr, HASH_PAGE); + + __put_page(hashp, pagep, addr_type, 1); + + return (0); +} + +int32_t +__delete_page(hashp, pagep, page_type) + HTAB *hashp; + PAGE16 *pagep; + int32_t page_type; +{ + if (page_type == A_OVFL) + __free_ovflpage(hashp, pagep); + return (mpool_delete(hashp->mp, pagep)); +} + +static u_int8_t +is_bitmap_pgno(hashp, pgno) + HTAB *hashp; + db_pgno_t pgno; +{ + int32_t i; + + for (i = 0; i < hashp->nmaps; i++) + if (OADDR_TO_PAGE(hashp->hdr.bitmaps[i]) == pgno) + return (1); + return (0); +} + +void +__pgin_routine(pg_cookie, pgno, page) + void *pg_cookie; + db_pgno_t pgno; + void *page; +{ + HTAB *hashp; + PAGE16 *pagep; + int32_t max, i; + + pagep = (PAGE16 *)page; + hashp = (HTAB *)pg_cookie; + + /* + * There are the following cases for swapping: + * 0) New page that may be unitialized. + * 1) Bucket page or overflow page. Either swap + * the header or initialize the page. + * 2) Bitmap page. Swap the whole page! + * 3) Header pages. Not handled here; these are written directly + * to the file. + */ + + if (NUM_ENT(pagep) == 0 && NEXT_PGNO(pagep) == 0 && + !is_bitmap_pgno(hashp, pgno)) { + /* XXX check for !0 LSN */ + page_init(hashp, pagep, pgno, HASH_PAGE); + return; + } + + if (hashp->hdr.lorder == DB_BYTE_ORDER) + return; + if (is_bitmap_pgno(hashp, pgno)) { + max = hashp->hdr.bsize >> 2; /* divide by 4 bytes */ + for (i = 0; i < max; i++) + M_32_SWAP(((int32_t *)(void *)pagep)[i]); + } else + swap_page_header_in(pagep); +} + +void +__pgout_routine(pg_cookie, pgno, page) + void *pg_cookie; + db_pgno_t pgno; + void *page; +{ + HTAB *hashp; + PAGE16 *pagep; + int32_t i, max; + + pagep = (PAGE16 *)page; + hashp = (HTAB *)pg_cookie; + + /* + * There are the following cases for swapping: + * 1) Bucket page or overflow page. Just swap the header. + * 2) Bitmap page. Swap the whole page! + * 3) Header pages. Not handled here; these are written directly + * to the file. + */ + + if (hashp->hdr.lorder == DB_BYTE_ORDER) + return; + if (is_bitmap_pgno(hashp, pgno)) { + max = hashp->hdr.bsize >> 2; /* divide by 4 bytes */ + for (i = 0; i < max; i++) + M_32_SWAP(((int32_t *)(void *)pagep)[i]); + } else + swap_page_header_out(pagep); +} + +/* + * + * Returns: + * 0 ==> OK + * -1 ==>failure + */ +extern int32_t +__put_page(hashp, pagep, addr_type, is_dirty) + HTAB *hashp; + PAGE16 *pagep; + int32_t addr_type, is_dirty; +{ +#if DEBUG_SLOW + account_page(hashp, + ((BKT *)((char *)pagep - sizeof(BKT)))->pgno, -1); +#endif + + return (mpool_put(hashp->mp, pagep, (is_dirty ? MPOOL_DIRTY : 0))); +} + +/* + * Returns: + * 0 indicates SUCCESS + * -1 indicates FAILURE + */ +extern PAGE16 * +__get_page(hashp, addr, addr_type) + HTAB *hashp; + u_int32_t addr; + int32_t addr_type; +{ + PAGE16 *pagep; + db_pgno_t paddr; + + switch (addr_type) { /* Convert page number. */ + case A_BUCKET: + paddr = BUCKET_TO_PAGE(addr); + break; + case A_OVFL: + case A_BITMAP: + paddr = OADDR_TO_PAGE(addr); + break; + default: + paddr = addr; + break; + } + pagep = (PAGE16 *)mpool_get(hashp->mp, paddr, 0); + +#if DEBUG_SLOW + account_page(hashp, paddr, 1); +#endif +#ifdef DEBUG + assert(ADDR(pagep) == paddr || ADDR(pagep) == 0 || + addr_type == A_BITMAP || addr_type == A_HEADER); +#endif + + return (pagep); +} + +static void +swap_page_header_in(pagep) + PAGE16 *pagep; +{ + u_int32_t i; + + /* can leave type and filler alone, since they're 1-byte quantities */ + + M_32_SWAP(PREV_PGNO(pagep)); + M_32_SWAP(NEXT_PGNO(pagep)); + M_16_SWAP(NUM_ENT(pagep)); + M_16_SWAP(OFFSET(pagep)); + + for (i = 0; i < NUM_ENT(pagep); i++) { + M_16_SWAP(KEY_OFF(pagep, i)); + M_16_SWAP(DATA_OFF(pagep, i)); + } +} + +static void +swap_page_header_out(pagep) + PAGE16 *pagep; +{ + u_int32_t i; + + for (i = 0; i < NUM_ENT(pagep); i++) { + M_16_SWAP(KEY_OFF(pagep, i)); + M_16_SWAP(DATA_OFF(pagep, i)) + } + + /* can leave type and filler alone, since they're 1-byte quantities */ + + M_32_SWAP(PREV_PGNO(pagep)); + M_32_SWAP(NEXT_PGNO(pagep)); + M_16_SWAP(NUM_ENT(pagep)); + M_16_SWAP(OFFSET(pagep)); +} + +#define BYTE_MASK ((1 << INT32_T_BYTE_SHIFT) -1) +/* + * Initialize a new bitmap page. Bitmap pages are left in memory + * once they are read in. + */ +extern int32_t +__ibitmap(hashp, pnum, nbits, ndx) + HTAB *hashp; + int32_t pnum, nbits, ndx; +{ + u_int32_t *ip; + int32_t clearbytes, clearints; + + /* make a new bitmap page */ + if (__new_page(hashp, pnum, A_BITMAP) != 0) + return (1); + if (!(ip = (u_int32_t *)(void *)__get_page(hashp, pnum, A_BITMAP))) + return (1); + hashp->nmaps++; + clearints = ((nbits - 1) >> INT32_T_BYTE_SHIFT) + 1; + clearbytes = clearints << INT32_T_TO_BYTE; + (void)memset((int8_t *)ip, 0, clearbytes); + (void)memset((int8_t *)ip + clearbytes, + 0xFF, hashp->hdr.bsize - clearbytes); + ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK); + SETBIT(ip, 0); + hashp->hdr.bitmaps[ndx] = (u_int16_t)pnum; + hashp->mapp[ndx] = ip; + return (0); +} + +static u_int32_t +first_free(map) + u_int32_t map; +{ + u_int32_t i, mask; + + for (mask = 0x1, i = 0; i < BITS_PER_MAP; i++) { + if (!(mask & map)) + return (i); + mask = mask << 1; + } + return (i); +} + +/* + * returns 0 on error + */ +static u_int16_t +overflow_page(hashp) + HTAB *hashp; +{ + u_int32_t *freep; + u_int32_t bit, first_page, free_bit, free_page, i, in_use_bits, j; + u_int32_t max_free, offset, splitnum; + u_int16_t addr; +#ifdef DEBUG2 + int32_t tmp1, tmp2; +#endif + + splitnum = hashp->hdr.ovfl_point; + max_free = hashp->hdr.spares[splitnum]; + + free_page = (max_free - 1) >> (hashp->hdr.bshift + BYTE_SHIFT); + free_bit = (max_free - 1) & ((hashp->hdr.bsize << BYTE_SHIFT) - 1); + + /* + * Look through all the free maps to find the first free block. + * The compiler under -Wall will complain that freep may be used + * before being set, however, this loop will ALWAYS get executed + * at least once, so freep is guaranteed to be set. + */ + freep = NULL; + first_page = hashp->hdr.last_freed >> (hashp->hdr.bshift + BYTE_SHIFT); + for (i = first_page; i <= free_page; i++) { + if (!(freep = fetch_bitmap(hashp, i))) + return (0); + if (i == free_page) + in_use_bits = free_bit; + else + in_use_bits = (hashp->hdr.bsize << BYTE_SHIFT) - 1; + + if (i == first_page) { + bit = hashp->hdr.last_freed & + ((hashp->hdr.bsize << BYTE_SHIFT) - 1); + j = bit / BITS_PER_MAP; + bit = bit & ~(BITS_PER_MAP - 1); + } else { + bit = 0; + j = 0; + } + for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP) + if (freep[j] != ALL_SET) + goto found; + } + + /* No Free Page Found */ + hashp->hdr.last_freed = hashp->hdr.spares[splitnum]; + hashp->hdr.spares[splitnum]++; + offset = hashp->hdr.spares[splitnum] - + (splitnum ? hashp->hdr.spares[splitnum - 1] : 0); + +#define OVMSG "HASH: Out of overflow pages. Increase page size\n" + + if (offset > SPLITMASK) { + if (++splitnum >= NCACHED) { + (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); + return (0); + } + hashp->hdr.ovfl_point = splitnum; + hashp->hdr.spares[splitnum] = hashp->hdr.spares[splitnum - 1]; + hashp->hdr.spares[splitnum - 1]--; + offset = 1; + } + /* Check if we need to allocate a new bitmap page. */ + if (free_bit == (hashp->hdr.bsize << BYTE_SHIFT) - 1) { + free_page++; + if (free_page >= NCACHED) { + (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); + return (0); + } + /* + * This is tricky. The 1 indicates that you want the new page + * allocated with 1 clear bit. Actually, you are going to + * allocate 2 pages from this map. The first is going to be + * the map page, the second is the overflow page we were + * looking for. The __ibitmap routine automatically, sets + * the first bit of itself to indicate that the bitmap itself + * is in use. We would explicitly set the second bit, but + * don't have to if we tell __ibitmap not to leave it clear + * in the first place. + */ + if (__ibitmap(hashp, + (int32_t)OADDR_OF(splitnum, offset), 1, free_page)) + return (0); + hashp->hdr.spares[splitnum]++; +#ifdef DEBUG2 + free_bit = 2; +#endif + offset++; + if (offset > SPLITMASK) { + if (++splitnum >= NCACHED) { + (void)write(STDERR_FILENO, + OVMSG, sizeof(OVMSG) - 1); + return (0); + } + hashp->hdr.ovfl_point = splitnum; + hashp->hdr.spares[splitnum] = + hashp->hdr.spares[splitnum - 1]; + hashp->hdr.spares[splitnum - 1]--; + offset = 0; + } + } else { + /* + * Free_bit addresses the last used bit. Bump it to address + * the first available bit. + */ + free_bit++; + SETBIT(freep, free_bit); + } + + /* Calculate address of the new overflow page */ + addr = OADDR_OF(splitnum, offset); +#ifdef DEBUG2 + (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n", + addr, free_bit, free_page); +#endif + + if (OADDR_TO_PAGE(addr) > MAX_PAGES(hashp)) { + (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); + return (0); + } + return (addr); + +found: + bit = bit + first_free(freep[j]); + SETBIT(freep, bit); +#ifdef DEBUG2 + tmp1 = bit; + tmp2 = i; +#endif + /* + * Bits are addressed starting with 0, but overflow pages are addressed + * beginning at 1. Bit is a bit address number, so we need to increment + * it to convert it to a page number. + */ + bit = 1 + bit + (i * (hashp->hdr.bsize << BYTE_SHIFT)); + if (bit >= hashp->hdr.last_freed) + hashp->hdr.last_freed = bit - 1; + + /* Calculate the split number for this page */ + for (i = 0; i < splitnum && (bit > hashp->hdr.spares[i]); i++); + offset = (i ? bit - hashp->hdr.spares[i - 1] : bit); + if (offset >= SPLITMASK) + return (0); /* Out of overflow pages */ + addr = OADDR_OF(i, offset); +#ifdef DEBUG2 + (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n", + addr, tmp1, tmp2); +#endif + + if (OADDR_TO_PAGE(addr) > MAX_PAGES(hashp)) { + (void)write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1); + return (0); + } + /* Allocate and return the overflow page */ + return (addr); +} + +#ifdef DEBUG +int +bucket_to_page(hashp, n) + HTAB *hashp; + int n; +{ + int ret_val; + + ret_val = n + hashp->hdr.hdrpages; + if (n != 0) + ret_val += hashp->hdr.spares[__log2(n + 1) - 1]; + return (ret_val); +} + +int32_t +oaddr_to_page(hashp, n) + HTAB *hashp; + int n; +{ + int ret_val, temp; + + temp = (1 << SPLITNUM(n)) - 1; + ret_val = bucket_to_page(hashp, temp); + ret_val += (n & SPLITMASK); + + return (ret_val); +} +#endif /* DEBUG */ + +static indx_t +page_to_oaddr(hashp, pgno) + HTAB *hashp; + db_pgno_t pgno; +{ + int32_t sp, ret_val; + + /* + * To convert page number to overflow address: + * + * 1. Find a starting split point -- use 0 since there are only + * 32 split points. + * 2. Find the split point s.t. 2^sp + hdr.spares[sp] < pgno and + * 2^(sp+1) = hdr.spares[sp+1] > pgno. The overflow address will + * be located at sp. + * 3. return... + */ + pgno -= hashp->hdr.hdrpages; + for (sp = 0; sp < NCACHED - 1; sp++) + if (POW2(sp) + hashp->hdr.spares[sp] < pgno && + (POW2(sp + 1) + hashp->hdr.spares[sp + 1]) > pgno) + break; + + ret_val = OADDR_OF(sp + 1, + pgno - ((POW2(sp + 1) - 1) + hashp->hdr.spares[sp])); +#ifdef DEBUG + assert(OADDR_TO_PAGE(ret_val) == (pgno + hashp->hdr.hdrpages)); +#endif + return (ret_val); +} + +/* + * Mark this overflow page as free. + */ +extern void +__free_ovflpage(hashp, pagep) + HTAB *hashp; + PAGE16 *pagep; +{ + u_int32_t *freep; + u_int32_t bit_address, free_page, free_bit; + u_int16_t addr, ndx; + + addr = page_to_oaddr(hashp, ADDR(pagep)); + +#ifdef DEBUG2 + (void)fprintf(stderr, "Freeing %d\n", addr); +#endif + ndx = ((u_int16_t)addr) >> SPLITSHIFT; + bit_address = + (ndx ? hashp->hdr.spares[ndx - 1] : 0) + (addr & SPLITMASK) - 1; + if (bit_address < hashp->hdr.last_freed) + hashp->hdr.last_freed = bit_address; + free_page = (bit_address >> (hashp->hdr.bshift + BYTE_SHIFT)); + free_bit = bit_address & ((hashp->hdr.bsize << BYTE_SHIFT) - 1); + + freep = fetch_bitmap(hashp, free_page); +#ifdef DEBUG + /* + * This had better never happen. It means we tried to read a bitmap + * that has already had overflow pages allocated off it, and we + * failed to read it from the file. + */ + if (!freep) + assert(0); +#endif + CLRBIT(freep, free_bit); +#ifdef DEBUG2 + (void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n", + obufp->addr, free_bit, free_page); +#endif +} + +static u_int32_t * +fetch_bitmap(hashp, ndx) + HTAB *hashp; + int32_t ndx; +{ + if (ndx >= hashp->nmaps) + return (NULL); + if (!hashp->mapp[ndx]) + hashp->mapp[ndx] = (u_int32_t *)(void *)__get_page(hashp, + hashp->hdr.bitmaps[ndx], A_BITMAP); + + return (hashp->mapp[ndx]); +} + +#ifdef DEBUG_SLOW +static void +account_page(hashp, pgno, inout) + HTAB *hashp; + db_pgno_t pgno; + int inout; +{ + static struct { + db_pgno_t pgno; + int times; + } list[100]; + static int last; + int i, j; + + if (inout == -1) /* XXX: Kluge */ + inout = 0; + + /* Find page in list. */ + for (i = 0; i < last; i++) + if (list[i].pgno == pgno) + break; + /* Not found. */ + if (i == last) { + list[last].times = inout; + list[last].pgno = pgno; + last++; + } + list[i].times = inout; + if (list[i].times == 0) { + for (j = i; j < last; j++) + list[j] = list[j + 1]; + last--; + } + for (i = 0; i < last; i++, list[i].times++) + if (list[i].times > 20 && !is_bitmap_pgno(hashp, list[i].pgno)) + (void)fprintf(stderr, + "Warning: pg %d has been out for %d times\n", + list[i].pgno, list[i].times); +} +#endif /* DEBUG_SLOW */ diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hsearch.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hsearch.c new file mode 100644 index 00000000..02ff7ef8 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/hsearch.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)hsearch.c 8.5 (Berkeley) 9/21/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include + +#include "db-int.h" +#include "search.h" + +static DB *dbp = NULL; +static ENTRY retval; + +extern int +hcreate(nel) + u_int nel; +{ + HASHINFO info; + + info.nelem = nel; + info.bsize = 256; + info.ffactor = 8; + info.cachesize = 0; + info.hash = NULL; + info.lorder = 0; + dbp = (DB *)__hash_open(NULL, O_CREAT | O_RDWR | O_BINARY, 0600, &info, 0); + return (dbp != NULL); +} + +extern ENTRY * +hsearch(item, action) + ENTRY item; + ACTION action; +{ + DBT key, val; + int status; + + if (!dbp) + return (NULL); + key.data = (u_char *)item.key; + key.size = strlen(item.key) + 1; + + if (action == ENTER) { + val.data = (u_char *)item.data; + val.size = strlen(item.data) + 1; + status = (dbp->put)(dbp, &key, &val, R_NOOVERWRITE); + if (status) + return (NULL); + } else { + /* FIND */ + status = (dbp->get)(dbp, &key, &val, 0); + if (status) + return (NULL); + else + item.data = (char *)val.data; + } + retval.key = item.key; + retval.data = item.data; + return (&retval); +} + +extern void +hdestroy() +{ + if (dbp) { + (void)(dbp->close)(dbp); + dbp = NULL; + } +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/page.h b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/page.h new file mode 100644 index 00000000..8cfdf004 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/page.h @@ -0,0 +1,178 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)page.h 8.4 (Berkeley) 11/7/95 + */ + +#define HI_MASK 0xFFFF0000 +#define LO_MASK (~HI_MASK) + +#define HI(N) ((u_int16_t)(((N) & HI_MASK) >> 16)) +#define LO(N) ((u_int16_t)((N) & LO_MASK)) + +/* Constants for big key page overhead information. */ +#define NUMSHORTS 0 +#define KEYLEN 1 +#define DATALEN 2 +#define NEXTPAGE 3 + +/* + * Hash pages store meta-data beginning at the top of the page (offset 0) + * and key/data values beginning at the bottom of the page (offset pagesize). + * Fields are always accessed via macros so that we can change the page + * format without too much pain. The only changes that will require massive + * code changes are if we no longer store key/data offsets next to each + * other (since we use that fact to compute key lengths). In the accessor + * macros below, P means a pointer to the page, I means an index of the + * particular entry being accessed. + * + * Hash base page format + * BYTE ITEM NBYTES TYPE ACCESSOR MACRO + * ---- ------------------ ------ -------- -------------- + * 0 previous page number 4 db_pgno_t PREV_PGNO(P) + * 4 next page number 4 db_pgno_t NEXT_PGNO(P) + * 8 # pairs on page 2 indx_t NUM_ENT(P) + * 10 page type 1 u_int8_t TYPE(P) + * 11 padding 1 u_int8_t none + * 12 highest free byte 2 indx_t OFFSET(P) + * 14 key offset 0 2 indx_t KEY_OFF(P, I) + * 16 data offset 0 2 indx_t DATA_OFF(P, I) + * 18 key offset 1 2 indx_t KEY_OFF(P, I) + * 20 data offset 1 2 indx_t DATA_OFF(P, I) + * ...etc... + */ + +/* Indices (in bytes) of the beginning of each of these entries */ +#define I_PREV_PGNO 0 +#define I_NEXT_PGNO 4 +#define I_ENTRIES 8 +#define I_TYPE 10 +#define I_HF_OFFSET 12 + +/* Overhead is everything prior to the first key/data pair. */ +#define PAGE_OVERHEAD (I_HF_OFFSET + sizeof(indx_t)) + +/* To allocate a pair, we need room for one key offset and one data offset. */ +#define PAIR_OVERHEAD ((sizeof(indx_t) << 1)) + +/* Use this macro to extract a value of type T from page P at offset O. */ +#define REFERENCE(P, T, O) (((T *)(void *)((u_int8_t *)(void *)(P) + O))[0]) + +/* + * Use these macros to access fields on a page; P is a PAGE16 *. + */ +#define NUM_ENT(P) (REFERENCE((P), indx_t, I_ENTRIES)) +#define PREV_PGNO(P) (REFERENCE((P), db_pgno_t, I_PREV_PGNO)) +#define NEXT_PGNO(P) (REFERENCE((P), db_pgno_t, I_NEXT_PGNO)) +#define TYPE(P) (REFERENCE((P), u_int8_t, I_TYPE)) +#define OFFSET(P) (REFERENCE((P), indx_t, I_HF_OFFSET)) +/* + * We need to store a page's own address on each page (unlike the Btree + * access method which needs the previous page). We use the PREV_PGNO + * field to store our own page number. + */ +#define ADDR(P) (PREV_PGNO((P))) + +/* Extract key/data offsets and data for a given index. */ +#define DATA_OFF(P, N) \ + REFERENCE(P, indx_t, PAGE_OVERHEAD + N * PAIR_OVERHEAD + sizeof(indx_t)) +#define KEY_OFF(P, N) \ + REFERENCE(P, indx_t, PAGE_OVERHEAD + N * PAIR_OVERHEAD) + +#define KEY(P, N) (((PAGE8 *)(P)) + KEY_OFF((P), (N))) +#define DATA(P, N) (((PAGE8 *)(P)) + DATA_OFF((P), (N))) + +/* + * Macros used to compute various sizes on a page. + */ +#define PAIRSIZE(K, D) (PAIR_OVERHEAD + (K)->size + (D)->size) +#define BIGOVERHEAD (4 * sizeof(u_int16_t)) +#define KEYSIZE(K) (4 * sizeof(u_int16_t) + (K)->size); +#define OVFLSIZE (2 * sizeof(u_int16_t)) +#define BIGPAGEOVERHEAD (4 * sizeof(u_int16_t)) +#define BIGPAGEOFFSET 4 +#define BIGPAGESIZE(P) ((P)->BSIZE - BIGPAGEOVERHEAD) + +#define PAGE_META(N) (((N) + 3) * sizeof(u_int16_t)) +#define MINFILL 0.75 +#define ISBIG(N, P) (((N) > ((P)->hdr.bsize * MINFILL)) ? 1 : 0) + +#define ITEMSIZE(I) (sizeof(u_int16_t) + (I)->size) + +/* + * Big key/data pages use a different page format. They have a single + * key/data "pair" containing the length of the key and data instead + * of offsets. + */ +#define BIGKEYLEN(P) (KEY_OFF((P), 0)) +#define BIGDATALEN(P) (DATA_OFF((P), 0)) +#define BIGKEY(P) (((PAGE8 *)(P)) + PAGE_OVERHEAD + PAIR_OVERHEAD) +#define BIGDATA(P) \ + (((PAGE8 *)(P)) + PAGE_OVERHEAD + PAIR_OVERHEAD + KEY_OFF((P), 0)) + + +#define OVFLPAGE 0 +#define BIGPAIR 0 +#define INVALID_PGNO 0xFFFFFFFF + +typedef unsigned short PAGE16; +typedef unsigned char PAGE8; + +#define A_BUCKET 0 +#define A_OVFL 1 +#define A_BITMAP 2 +#define A_RAW 4 +#define A_HEADER 5 + +#define PAIRFITS(P,K,D) ((PAIRSIZE((K),(D))) <= FREESPACE((P))) +#define BIGPAIRFITS(P) ((FREESPACE((P)) >= PAIR_OVERHEAD)) +/* + * Since these are all unsigned, we need to guarantee that we never go + * negative. Offset values are 0-based and overheads are one based (i.e. + * one byte of overhead is 1, not 0), so we need to convert OFFSETs to + * 1-based counting before subtraction. + */ +#define FREESPACE(P) \ + ((OFFSET((P)) + 1 - PAGE_OVERHEAD - (NUM_ENT((P)) * PAIR_OVERHEAD))) + +/* + * Overhead on header pages is just one word -- the length of the + * header info stored on that page. + */ +#define HEADER_OVERHEAD 4 + +#define HASH_PAGE 2 +#define HASH_BIGPAGE 3 +#define HASH_OVFLPAGE 4 diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/page.h.patch b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/page.h.patch new file mode 100644 index 00000000..4a0311fe --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/page.h.patch @@ -0,0 +1,42 @@ +*** /tmp/,RCSt1a21720 Wed Apr 3 11:49:55 1996 +--- page.h Wed Apr 3 08:42:25 1996 +*************** +*** 158,163 + + #define PAIRFITS(P,K,D) ((PAIRSIZE((K),(D))) <= FREESPACE((P))) + #define BIGPAIRFITS(P) ((FREESPACE((P)) >= PAIR_OVERHEAD)) + #define FREESPACE(P) \ + ((OFFSET((P)) - PAGE_OVERHEAD - (NUM_ENT((P)) * PAIR_OVERHEAD))) + + +--- 158,169 ----- + + #define PAIRFITS(P,K,D) ((PAIRSIZE((K),(D))) <= FREESPACE((P))) + #define BIGPAIRFITS(P) ((FREESPACE((P)) >= PAIR_OVERHEAD)) ++ /* ++ * Since these are all unsigned, we need to guarantee that we never go ++ * negative. Offset values are 0-based and overheads are one based (i.e. ++ * one byte of overhead is 1, not 0), so we need to convert OFFSETs to ++ * 1-based counting before subtraction. ++ */ + #define FREESPACE(P) \ + ((OFFSET((P)) + 1 - PAGE_OVERHEAD - (NUM_ENT((P)) * PAIR_OVERHEAD))) + +*************** +*** 159,165 + #define PAIRFITS(P,K,D) ((PAIRSIZE((K),(D))) <= FREESPACE((P))) + #define BIGPAIRFITS(P) ((FREESPACE((P)) >= PAIR_OVERHEAD)) + #define FREESPACE(P) \ +! ((OFFSET((P)) - PAGE_OVERHEAD - (NUM_ENT((P)) * PAIR_OVERHEAD))) + + /* + * Overhead on header pages is just one word -- the length of the + +--- 165,171 ----- + * 1-based counting before subtraction. + */ + #define FREESPACE(P) \ +! ((OFFSET((P)) + 1 - PAGE_OVERHEAD - (NUM_ENT((P)) * PAIR_OVERHEAD))) + + /* + * Overhead on header pages is just one word -- the length of the diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/search.h b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/search.h new file mode 100644 index 00000000..6d6a0a82 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/hash/search.h @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)search.h 8.1 (Berkeley) 6/4/93 + */ + +/* Backward compatibility to hsearch interface. */ +typedef struct entry { + char *key; + char *data; +} ENTRY; + +typedef enum { + FIND, ENTER +} ACTION; + +#define hcreate kdb2_hcreate +#define hdestroy kdb2_hdestroy +#define hsearch kdb2_hsearch + +int hcreate __P((unsigned int)); +void hdestroy __P((void)); +ENTRY *hsearch __P((ENTRY, ACTION)); diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/config.h b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/config.h new file mode 100644 index 00000000..b4ace4e0 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/config.h @@ -0,0 +1,23 @@ +/* This includes autoconf.h and defines u_int32_t. */ +#include "db-config.h" + +#ifndef HAVE_U_INT16_T +#define u_int16_t unsigned short +#endif +#ifndef HAVE_INT16_T +#define int16_t short +#endif + +#ifndef HAVE_INT8_T +#define int8_t signed char +#endif +#ifndef HAVE_U_INT8_T +#define u_int8_t unsigned char +#endif +#ifndef HAVE_INT32_T +#define int32_t int +#endif + +#ifndef HAVE_SSIZE_T +#define ssize_t int +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-config.hin b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-config.hin new file mode 100644 index 00000000..0ac7c916 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-config.hin @@ -0,0 +1,17 @@ +#include "autoconf.h" + +#ifndef HAVE_U_CHAR +#define u_char unsigned char +#endif + +#ifndef HAVE_U_INT +#define u_int unsigned int +#endif + +#ifndef HAVE_U_LONG +#define u_long unsigned long +#endif + +#ifndef HAVE_U_INT32_T +#define u_int32_t unsigned int +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-dbm.h b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-dbm.h new file mode 100644 index 00000000..28c93786 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-dbm.h @@ -0,0 +1,23 @@ +#ifndef _DBM_H_ +#define _DBM_H_ + +#include "db.h" + +#define dbminit kdb2_dbminit +#define fetch kdb2_fetch +#define firstkey kdb2_firstkey +#define nextkey kdb2_nextkey +#define delete kdb2_delete +#define store kdb2_store + +__BEGIN_DECLS +int dbminit __P((char *)); +datum fetch __P((datum)); +datum firstkey __P((void)); +datum nextkey __P((datum)); +int delete __P((datum)); +int store __P((datum, datum)); +__END_DECLS + + +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-int.h b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-int.h new file mode 100644 index 00000000..7e981d4a --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-int.h @@ -0,0 +1,283 @@ +/*- + * Copyright (c) 1991, 1993, 2007 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)compat.h 8.13 (Berkeley) 2/21/94 + */ + +#ifndef _DB_INT_H_ +#define _DB_INT_H_ + +#include "config.h" +#include "db.h" + +/* deal with autoconf-based stuff */ + +#define DB_LITTLE_ENDIAN 1234 +#define DB_BIG_ENDIAN 4321 + +#include +#ifdef HAVE_ENDIAN_H +# include +#endif +#ifdef HAVE_MACHINE_ENDIAN_H +# include +#endif +#ifdef HAVE_SYS_PARAM_H +# include +#endif +/* Handle both BIG and LITTLE defined and BYTE_ORDER matches one, or + just one defined; both with and without leading underscores. + + Ignore "PDP endian" machines, this code doesn't support them + anyways. */ +#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) && !defined(BYTE_ORDER) +# ifdef __LITTLE_ENDIAN__ +# define LITTLE_ENDIAN __LITTLE_ENDIAN__ +# endif +# ifdef __BIG_ENDIAN__ +# define BIG_ENDIAN __BIG_ENDIAN__ +# endif +#endif +#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) && !defined(BYTE_ORDER) +# ifdef _LITTLE_ENDIAN +# define LITTLE_ENDIAN _LITTLE_ENDIAN +# endif +# ifdef _BIG_ENDIAN +# define BIG_ENDIAN _BIG_ENDIAN +# endif +# ifdef _BYTE_ORDER +# define BYTE_ORDER _BYTE_ORDER +# endif +#endif +#if !defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) && !defined(BYTE_ORDER) +# ifdef __LITTLE_ENDIAN +# define LITTLE_ENDIAN __LITTLE_ENDIAN +# endif +# ifdef __BIG_ENDIAN +# define BIG_ENDIAN __BIG_ENDIAN +# endif +# ifdef __BYTE_ORDER +# define BYTE_ORDER __BYTE_ORDER +# endif +#endif + +#if defined(_MIPSEL) && !defined(LITTLE_ENDIAN) +# define LITTLE_ENDIAN +#endif +#if defined(_MIPSEB) && !defined(BIG_ENDIAN) +# define BIG_ENDIAN +#endif + +#if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) && defined(BYTE_ORDER) +# if LITTLE_ENDIAN == BYTE_ORDER +# define DB_BYTE_ORDER DB_LITTLE_ENDIAN +# elif BIG_ENDIAN == BYTE_ORDER +# define DB_BYTE_ORDER DB_BIG_ENDIAN +# else +# error "LITTLE_ENDIAN and BIG_ENDIAN defined, but can't determine byte order" +# endif +#elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) +# define DB_BYTE_ORDER DB_LITTLE_ENDIAN +#elif defined(BIG_ENDIAN) && !defined(LITTLE_ENDIAN) +# define DB_BYTE_ORDER DB_BIG_ENDIAN +#else +# error "can't determine byte order from included system headers" +#endif + +#if 0 +#ifdef WORDS_BIGENDIAN +#define DB_BYTE_ORDER DB_BIG_ENDIAN +#else +#define DB_BYTE_ORDER DB_LITTLE_ENDIAN +#endif +#endif + +/* end autoconf-based stuff */ + +/* include necessary system header files */ + +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +/* types and constants used for database structure */ + +#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */ +typedef u_int32_t db_pgno_t; +#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */ +typedef u_int16_t indx_t; +#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */ +typedef u_int32_t recno_t; + +/* + * Little endian <==> big endian 32-bit swap macros. + * M_32_SWAP swap a memory location + * P_32_SWAP swap a referenced memory location + * P_32_COPY swap from one location to another + */ +#define M_32_SWAP(a) { \ + u_int32_t _tmp = a; \ + ((char *)&a)[0] = ((char *)&_tmp)[3]; \ + ((char *)&a)[1] = ((char *)&_tmp)[2]; \ + ((char *)&a)[2] = ((char *)&_tmp)[1]; \ + ((char *)&a)[3] = ((char *)&_tmp)[0]; \ +} +#define P_32_SWAP(a) { \ + char _tmp[4]; \ + _tmp[0] = ((char *)a)[0]; \ + _tmp[1] = ((char *)a)[1]; \ + _tmp[2] = ((char *)a)[2]; \ + _tmp[3] = ((char *)a)[3]; \ + ((char *)a)[0] = _tmp[3]; \ + ((char *)a)[1] = _tmp[2]; \ + ((char *)a)[2] = _tmp[1]; \ + ((char *)a)[3] = _tmp[0]; \ +} +#define P_32_COPY(a, b) { \ + ((char *)&(b))[0] = ((char *)&(a))[3]; \ + ((char *)&(b))[1] = ((char *)&(a))[2]; \ + ((char *)&(b))[2] = ((char *)&(a))[1]; \ + ((char *)&(b))[3] = ((char *)&(a))[0]; \ +} + +/* + * Little endian <==> big endian 16-bit swap macros. + * M_16_SWAP swap a memory location + * P_16_SWAP swap a referenced memory location + * P_16_COPY swap from one location to another + */ +#define M_16_SWAP(a) { \ + u_int16_t _tmp = a; \ + ((char *)&a)[0] = ((char *)&_tmp)[1]; \ + ((char *)&a)[1] = ((char *)&_tmp)[0]; \ +} +#define P_16_SWAP(a) { \ + char _tmp[2]; \ + _tmp[0] = ((char *)a)[0]; \ + _tmp[1] = ((char *)a)[1]; \ + ((char *)a)[0] = _tmp[1]; \ + ((char *)a)[1] = _tmp[0]; \ +} +#define P_16_COPY(a, b) { \ + ((char *)&(b))[0] = ((char *)&(a))[1]; \ + ((char *)&(b))[1] = ((char *)&(a))[0]; \ +} + +/* open functions for each database type, used in dbopen() */ + +#define __bt_open __kdb2_bt_open +#define __hash_open __kdb2_hash_open +#define __rec_open __kdb2_rec_open +#define __dbpanic __kdb2_dbpanic + +DB *__bt_open __P((const char *, int, int, const BTREEINFO *, int)); +DB *__hash_open __P((const char *, int, int, const HASHINFO *, int)); +DB *__rec_open __P((const char *, int, int, const RECNOINFO *, int)); +void __dbpanic __P((DB *dbp)); + +/* + * There is no portable way to figure out the maximum value of a file + * offset, so we put it here. + */ +#ifdef OFF_T_MAX +#define DB_OFF_T_MAX OFF_T_MAX +#else +#define DB_OFF_T_MAX LONG_MAX +#endif + +#ifndef O_ACCMODE /* POSIX 1003.1 access mode mask. */ +#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) +#endif + +/* + * If you can't provide lock values in the open(2) call. Note, this + * allows races to happen. + */ +#ifndef O_EXLOCK /* 4.4BSD extension. */ +#define O_EXLOCK 0 +#endif + +#ifndef O_SHLOCK /* 4.4BSD extension. */ +#define O_SHLOCK 0 +#endif + +#ifndef EFTYPE +#define EFTYPE EINVAL /* POSIX 1003.1 format errno. */ +#endif + +#ifndef STDERR_FILENO +#define STDIN_FILENO 0 /* ANSI C #defines */ +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 +#endif + +#ifndef SEEK_END +#define SEEK_SET 0 /* POSIX 1003.1 seek values */ +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif + +#ifndef NULL /* ANSI C #defines NULL everywhere. */ +#define NULL 0 +#endif + +#ifndef MAX /* Usually found in . */ +#define MAX(_a,_b) ((_a)<(_b)?(_b):(_a)) +#endif +#ifndef MIN /* Usually found in . */ +#define MIN(_a,_b) ((_a)<(_b)?(_a):(_b)) +#endif + +#ifndef S_ISDIR /* POSIX 1003.1 file type tests. */ +#define S_ISDIR(m) ((m & 0170000) == 0040000) /* directory */ +#define S_ISCHR(m) ((m & 0170000) == 0020000) /* char special */ +#define S_ISBLK(m) ((m & 0170000) == 0060000) /* block special */ +#define S_ISREG(m) ((m & 0170000) == 0100000) /* regular file */ +#define S_ISFIFO(m) ((m & 0170000) == 0010000) /* fifo */ +#endif +#ifndef S_ISLNK /* BSD POSIX 1003.1 extensions */ +#define S_ISLNK(m) ((m & 0170000) == 0120000) /* symbolic link */ +#define S_ISSOCK(m) ((m & 0170000) == 0140000) /* socket */ +#endif + +#ifndef O_BINARY +#define O_BINARY 0 /* Needed for Win32 compiles */ +#endif +#endif /* _DB_INT_H_ */ diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-ndbm.h b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-ndbm.h new file mode 100644 index 00000000..e99f46fd --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-ndbm.h @@ -0,0 +1,91 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)ndbm.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _NDBM_H_ +#define _NDBM_H_ + +#include "db.h" + +/* Map dbm interface onto db(3). */ +#define DBM_RDONLY O_RDONLY + +/* Flags to dbm_store(). */ +#define DBM_INSERT 0 +#define DBM_REPLACE 1 + +/* + * The db(3) support for ndbm(3) always appends this suffix to the + * file name to avoid overwriting the user's original database. + */ +#define DBM_SUFFIX ".db" + +typedef struct { + char *dptr; + int dsize; +} datum; + +typedef DB DBM; +#define dbm_pagfno(a) DBM_PAGFNO_NOT_AVAILABLE + +#define dbm_close kdb2_dbm_close +#define dbm_delete kdb2_dbm_delete +#define dbm_fetch kdb2_dbm_fetch +#define dbm_firstkey kdb2_dbm_firstkey +#define dbm_forder kdb2_dbm_forder +#define dbm_nextkey kdb2_dbm_nextkey +#define dbm_open kdb2_dbm_open +#define dbm_store kdb2_dbm_store +#define dbm_dirfno kdb2_dbm_dirfno +#define dbm_error kdb2_dbm_error +#define dbm_clearerr kdb2_dbm_clearerr + +__BEGIN_DECLS +void dbm_close __P((DBM *)); +int dbm_delete __P((DBM *, datum)); +datum dbm_fetch __P((DBM *, datum)); +datum dbm_firstkey __P((DBM *)); +long dbm_forder __P((DBM *, datum)); +datum dbm_nextkey __P((DBM *)); +DBM *dbm_open __P((const char *, int, int)); +int dbm_store __P((DBM *, datum, datum, int)); +int dbm_dirfno __P((DBM *)); +int dbm_error __P((DBM *db)); +int dbm_clearerr __P((DBM *db)); +__END_DECLS + +#endif /* !_NDBM_H_ */ diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-queue.h b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-queue.h new file mode 100644 index 00000000..65612ce6 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db-queue.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)queue.h 8.3 (Berkeley) 12/13/93 + */ + +#ifndef _QUEUE_H_ +#define _QUEUE_H_ + +/* + * This file defines three types of data structures: lists, tail queues, + * and circular queues. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list after + * an existing element or at the head of the list. A list may only be + * traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list after + * an existing element, at the head of the list, or at the end of the + * list. A tail queue may only be traversed in the forward direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ +#define LIST_INIT(head) { \ + (head)->lh_first = NULL; \ +} + +#define LIST_INSERT_AFTER(listelm, elm, field) { \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} + +#define LIST_INSERT_HEAD(head, elm, field) { \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} + +#define LIST_REMOVE(elm, field) { \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ +} + +/* + * Tail queue definitions. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * Tail queue functions. + */ +#define TAILQ_INIT(head) { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} + +#define TAILQ_INSERT_HEAD(head, elm, field) { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} + +#define TAILQ_INSERT_TAIL(head, elm, field) { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} + +#define TAILQ_REMOVE(head, elm, field) { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ +} + +/* + * Circular queue definitions. + */ +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue functions. + */ +#define CIRCLEQ_INIT(head) { \ + (head)->cqh_first = (void *)(head); \ + (head)->cqh_last = (void *)(head); \ +} + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) { \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = (void *)(head); \ + if ((head)->cqh_last == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) { \ + (elm)->field.cqe_next = (void *)(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} + +#define CIRCLEQ_REMOVE(head, elm, field) { \ + if ((elm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ +} +#endif /* !_QUEUE_H_ */ diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db.hin b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db.hin new file mode 100644 index 00000000..9ae8f8be --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/include/db.hin @@ -0,0 +1,190 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)db.h 8.8 (Berkeley) 11/2/95 + */ + +#ifndef _DB_H_ +#define _DB_H_ + +#include + +#include + +#define RET_ERROR -1 /* Return values. */ +#define RET_SUCCESS 0 +#define RET_SPECIAL 1 + +/* Key/data structure -- a Data-Base Thang. */ +typedef struct { + void *data; /* data */ + size_t size; /* data length */ +} DBT; + +/* Routine flags. */ +#define R_CURSOR 1 /* del, put, seq */ +#define __R_UNUSED 2 /* UNUSED */ +#define R_FIRST 3 /* seq */ +#define R_IAFTER 4 /* put (RECNO) */ +#define R_IBEFORE 5 /* put (RECNO) */ +#define R_LAST 6 /* seq (BTREE, RECNO) */ +#define R_NEXT 7 /* seq */ +#define R_NOOVERWRITE 8 /* put */ +#define R_PREV 9 /* seq (BTREE, RECNO) */ +#define R_SETCURSOR 10 /* put (RECNO) */ +#define R_RECNOSYNC 11 /* sync (RECNO) */ + +/* + * Recursive sequential scan. + * + * This avoids using sibling pointers, permitting (possibly partial) + * recovery from some kinds of btree corruption. Start a sequential + * scan as usual, but use R_RNEXT or R_RPREV to move forward or + * backward. + * + * This probably doesn't work with btrees that allow duplicate keys. + * Database modifications during the scan can also modify the parent + * page stack needed for correct functioning. Intermixing + * non-recursive traversal by using R_NEXT or R_PREV can also make the + * page stack inconsistent with the cursor and cause problems. + */ +#define R_RNEXT 128 /* seq (BTREE, RECNO) */ +#define R_RPREV 129 /* seq (BTREE, RECNO) */ + +typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE; + +/* + * !!! + * The following flags are included in the dbopen(3) call as part of the + * open(2) flags. In order to avoid conflicts with the open flags, start + * at the top of the 16 or 32-bit number space and work our way down. If + * the open flags were significantly expanded in the future, it could be + * a problem. Wish I'd left another flags word in the dbopen call. + * + * !!! + * None of this stuff is implemented yet. The only reason that it's here + * is so that the access methods can skip copying the key/data pair when + * the DB_LOCK flag isn't set. + */ +#if UINT_MAX >= 0xffffffffUL +#define DB_LOCK 0x20000000 /* Do locking. */ +#define DB_SHMEM 0x40000000 /* Use shared memory. */ +#define DB_TXN 0x80000000 /* Do transactions. */ +#else +#define DB_LOCK 0x2000 /* Do locking. */ +#define DB_SHMEM 0x4000 /* Use shared memory. */ +#define DB_TXN 0x8000 /* Do transactions. */ +#endif + +/* deal with turning prototypes on and off */ + +#ifndef __P +#if defined(__STDC__) || defined(__cplusplus) +#define __P(protos) protos /* full-blown ANSI C */ +#else /* !(__STDC__ || __cplusplus) */ +#define __P(protos) () /* traditional C preprocessor */ +#endif +#endif /* no __P from system */ + +/* Access method description structure. */ +typedef struct __db { + DBTYPE type; /* Underlying db type. */ + int (*close) __P((struct __db *)); + int (*del) __P((const struct __db *, const DBT *, u_int)); + int (*get) __P((const struct __db *, const DBT *, DBT *, u_int)); + int (*put) __P((const struct __db *, DBT *, const DBT *, u_int)); + int (*seq) __P((const struct __db *, DBT *, DBT *, u_int)); + int (*sync) __P((const struct __db *, u_int)); + void *internal; /* Access method private. */ + int (*fd) __P((const struct __db *)); +} DB; + +#define BTREEMAGIC 0x053162 +#define BTREEVERSION 3 + +/* Structure used to pass parameters to the btree routines. */ +typedef struct { +#define R_DUP 0x01 /* duplicate keys */ + u_long flags; + u_int cachesize; /* bytes to cache */ + int maxkeypage; /* maximum keys per page */ + int minkeypage; /* minimum keys per page */ + u_int psize; /* page size */ + int (*compare) /* comparison function */ + __P((const DBT *, const DBT *)); + size_t (*prefix) /* prefix function */ + __P((const DBT *, const DBT *)); + int lorder; /* byte order */ +} BTREEINFO; + +#define HASHMAGIC 0x061561 +#define HASHVERSION 3 + +/* Structure used to pass parameters to the hashing routines. */ +typedef struct { + u_int bsize; /* bucket size */ + u_int ffactor; /* fill factor */ + u_int nelem; /* number of elements */ + u_int cachesize; /* bytes to cache */ + u_int32_t /* hash function */ + (*hash) __P((const void *, size_t)); + int lorder; /* byte order */ +} HASHINFO; + +/* Structure used to pass parameters to the record routines. */ +typedef struct { +#define R_FIXEDLEN 0x01 /* fixed-length records */ +#define R_NOKEY 0x02 /* key not required */ +#define R_SNAPSHOT 0x04 /* snapshot the input */ + u_long flags; + u_int cachesize; /* bytes to cache */ + u_int psize; /* page size */ + int lorder; /* byte order */ + size_t reclen; /* record length (fixed-length records) */ + u_char bval; /* delimiting byte (variable-length records */ + char *bfname; /* btree file name */ +} RECNOINFO; + +#if defined(__cplusplus) +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS }; +#else +#define __BEGIN_DECLS +#define __END_DECLS +#endif + +#define dbopen kdb2_dbopen +__BEGIN_DECLS +DB *dbopen __P((const char *, int, int, DBTYPE, const void *)); +__END_DECLS + +#endif /* !_DB_H_ */ diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/libdb.exports b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/libdb.exports new file mode 100644 index 00000000..0c168918 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/libdb.exports @@ -0,0 +1,105 @@ +__default_hash +__kdb2_add_bigpage +__kdb2_add_ovflpage +__kdb2_addel +__kdb2_big_delete +__kdb2_big_insert +__kdb2_big_keydata +__kdb2_big_return +__kdb2_bt_close +__kdb2_bt_cmp +__kdb2_bt_defcmp +__kdb2_bt_defpfx +__kdb2_bt_deleaf +__kdb2_bt_delete +__kdb2_bt_dmpage +__kdb2_bt_dnpage +__kdb2_bt_dpage +__kdb2_bt_dump +__kdb2_bt_fd +__kdb2_bt_free +__kdb2_bt_get +__kdb2_bt_new +__kdb2_bt_open +__kdb2_bt_pgin +__kdb2_bt_pgout +__kdb2_bt_put +__kdb2_bt_relink +__kdb2_bt_ret +__kdb2_bt_search +__kdb2_bt_seq +__kdb2_bt_setcur +__kdb2_bt_split +__kdb2_bt_stat +__kdb2_bt_sync +__kdb2_call_hash +__kdb2_cursor_creat +__kdb2_dbpanic +__kdb2_delete_page +__kdb2_delpair +__kdb2_expand_table +__kdb2_find_bigpair +__kdb2_free_ovflpage +__kdb2_get_bigkey +__kdb2_get_item +__kdb2_get_item_done +__kdb2_get_item_first +__kdb2_get_item_next +__kdb2_get_item_reset +__kdb2_get_page +__kdb2_hash_open +__kdb2_ibitmap +__kdb2_log2 +__kdb2_new_page +__kdb2_ovfl_delete +__kdb2_ovfl_get +__kdb2_ovfl_put +__kdb2_pgin_routine +__kdb2_pgout_routine +__kdb2_put_page +__kdb2_rec_close +__kdb2_rec_delete +__kdb2_rec_dleaf +__kdb2_rec_fd +__kdb2_rec_fmap +__kdb2_rec_fpipe +__kdb2_rec_get +__kdb2_rec_iput +__kdb2_rec_open +__kdb2_rec_put +__kdb2_rec_ret +__kdb2_rec_search +__kdb2_rec_seq +__kdb2_rec_sync +__kdb2_rec_vmap +__kdb2_rec_vpipe +__kdb2_split_page +kdb2_dbm_clearerr +kdb2_dbm_close +kdb2_dbm_delete +kdb2_dbm_dirfno +kdb2_dbm_error +kdb2_dbm_fetch +kdb2_dbm_firstkey +kdb2_dbm_nextkey +kdb2_dbm_open +kdb2_dbm_store +kdb2_dbminit +kdb2_dbopen +kdb2_delete +kdb2_fetch +kdb2_firstkey +kdb2_hcreate +kdb2_hdestroy +kdb2_hsearch +kdb2_mpool_close +kdb2_mpool_delete +kdb2_mpool_filter +kdb2_mpool_get +kdb2_mpool_new +kdb2_mpool_open +kdb2_mpool_put +kdb2_mpool_stat +kdb2_mpool_sync +kdb2_nextkey +kdb2_store diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/Makefile.inc b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/Makefile.inc new file mode 100644 index 00000000..f85cba1f --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/Makefile.inc @@ -0,0 +1,7 @@ +# @(#)Makefile.inc 8.2 (Berkeley) 11/14/94 + +.PATH: ${.CURDIR}/db/man + +MAN3+= db_btree.0 db_hash.0 db_lock.0 db_log.0 db_mpool.0 db_open.0 \ + db_recno.0 +MLINKS+=db_open.3 db.3 db_open.3 dbopen.3 diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db.man.ps b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db.man.ps new file mode 100644 index 0000000000000000000000000000000000000000..23feea6e5c1db9d56058548fe4e6ef46b2cdbf08 GIT binary patch literal 149053 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�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 psTEt7p641#m$bz_gicv^@(JqYZPdj5J>ct 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 rn?Mp}5X;LXAjb9|KUn$SnLg3G literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_btree.3 b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_btree.3 new file mode 100644 index 00000000..25e289f3 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_btree.3 @@ -0,0 +1,246 @@ +.\" Copyright (c) 1990, 1993, 1994, 1995 +.\" The Regents of the University of California. 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. +.\" +.\" @(#)db_btree.3 8.11 (Berkeley) 8/1/95 +.\" +.TH DB_BTREE 3 "August 1, 1995" +.UC 7 +.SH NAME +db_btree \- btree database access method +.SH DESCRIPTION +.so db.so +.GN +specific details of the btree access method. +.PP +The btree data structure is a sorted, balanced tree structure storing +associated key/data pairs. +Searches, insertions, and deletions in the btree will all complete in +O lg base N where base is the average fill factor. +Often, inserting ordered data into btrees results in a low fill factor. +This implementation has been modified to make ordered insertion the best +case, resulting in a much better than normal page fill factor. +.SH "ACCESS METHOD SPECIFIC INFORMATION" +The btree access method specific data structure provided to +.I db_open +is typedef'd and named BTREEINFO. +A BTREEINFO structure has at least the following fields, +which may be initialized before calling +.IR db_open : +.TP 5 +u_int cachesize; +A suggested maximum size (in bytes) of the memory cache. +This value is +.B only +advisory, and the access method will allocate more memory rather than fail. +Since every search examines the root page of the tree, caching the most +recently used pages substantially improves access time. +In addition, physical writes are delayed as long as possible, so a moderate +cache can reduce the number of I/O operations significantly. +Obviously, using a cache increases (but only increases) the likelihood of +corruption or lost data if the system crashes while a tree is being modified. +If +.I cachesize +is 0 (no size is specified) a default cache is used. +.TP 5 +int (*compare)(const DBT *, const DBT *); +Compare is the key comparison function. +It must return an integer less than, equal to, or greater than zero if the +first key argument is considered to be respectively less than, equal to, +or greater than the second key argument. +The same comparison function must be used on a given tree every time it +is opened. +If +.I compare +is NULL (no comparison function is specified), the keys are compared +lexically, with shorter keys considered less than longer keys. +.TP 5 +u_long flags; +The flag value is specified by +.IR or 'ing +any of the following values: +.RS +.TP 5 +R_DUP +Permit duplicate keys in the tree, i.e. permit insertion if the key to be +inserted already exists in the tree. +The default behavior, as described in +.IR db_open (3), +is to overwrite a matching key when inserting a new key or to fail if +the R_NOOVERWRITE flag is specified. +The R_DUP flag is overridden by the R_NOOVERWRITE flag, and if the +R_NOOVERWRITE flag is specified, attempts to insert duplicate keys into +the tree will fail. +.IP +If the database contains duplicate keys, the order of retrieval of +key/data pairs is undefined if the +.I get +function is used, however, +.I seq +function calls with the R_CURSOR flag set will always return the logical +``first'' of any group of duplicate keys. +.RE +.TP 5 +int lorder; +The byte order for integers in the stored database metadata. +The number should represent the order as an integer; for example, +big endian order would be the number 4,321. +If +.I lorder +is 0 (no order is specified) the current host order is used. +.TP 5 +int maxkeypage; +The maximum number of keys which will be stored on any single page. +This functionality is not currently implemented. +.\" The maximum number of keys which will be stored on any single page. +.\" Because of the way the btree data structure works, +.\" .I maxkeypage +.\" must always be greater than or equal to 2. +.\" If +.\" .I maxkeypage +.\" is 0 (no maximum number of keys is specified) the page fill factor is +.\" made as large as possible (which is almost invariably what is wanted). +.TP 5 +int minkeypage; +The minimum number of keys which will be stored on any single page. +This value is used to determine which keys will be stored on overflow +pages, i.e. if a key or data item is longer than the pagesize divided +by the minkeypage value, it will be stored on overflow pages instead +of in the page itself. +If +.I minkeypage +is 0 (no minimum number of keys is specified) a value of 2 is used. +.TP 5 +size_t (*prefix)(const DBT *, const DBT *); +Prefix is the prefix comparison function. +If specified, this function must return the number of bytes of the second key +argument which are necessary to determine that it is greater than the first +key argument. +If the keys are equal, the key length should be returned. +Note, the usefulness of this function is very data dependent, but, in some +data sets can produce significantly reduced tree sizes and search times. +If +.I prefix +is NULL (no prefix function is specified), +.B and +no comparison function is specified, a default lexical comparison function +is used. +If +.I prefix +is NULL and a comparison function is specified, no prefix comparison is +done. +.TP 5 +u_int psize; +Page size is the size (in bytes) of the pages used for nodes in the tree. +The minimum page size is 512 bytes and the maximum page size is 64K. +If +.I psize +is 0 (no page size is specified) a page size is chosen based on the +underlying file system I/O block size. +.PP +If the file already exists (and the O_TRUNC flag is not specified), the +values specified for the parameters flags, lorder and psize are ignored +in favor of the values used when the tree was created. +.SH "DB OPERATIONS" +The functions returned by +.I db_open +for the btree access method are as described in +.IR db_open (3), +with the following exceptions and additions: +.TP 5 +type +The type is DB_BTREE. +.TP 5 +del +Space freed up by deleting key/data pairs from the tree is never reclaimed, +although it is reused where possible. +This means that the btree storage structure is grow-only. +The only solutions are to avoid excessive deletions, or to create a fresh +tree periodically from a scan of an existing one. +.TP 5 +put +The +.I put +function takes the following additional flags: +.RS +.TP 5 +R_SETCURSOR +Store the key/data pair, setting or initializing the position of the +cursor to reference it. +.RE +.TP 5 +seq +Forward sequential scans of a tree are from the least key to the greatest. +.IP +The returned key for the +.I seq +function is not necessarily an exact match for the specified key in +the btree access method. +The returned key is the smallest key greater than or equal to the +specified key, permitting partial key matches and range searches. +.IP +The +.I seq +function takes the following additional flags: +.RS +.TP 5 +R_LAST +The last key/data pair of the database is returned, and the cursor +is set or initialized to reference it. +.TP 5 +R_PREV +Retrieve the key/data pair immediately before the cursor. +If the cursor is not yet set, this is the same as the R_LAST flag. +.RE +.SH ERRORS +The +.I btree +access method functions may fail and set +.I errno +for any of the errors specified for the library function +.IR db_open (3). +.SH "SEE ALSO" +.IR db_hash (3), +.IR db_lock (3), +.IR db_log (3), +.IR db_mpool (3), +.IR db_open (3), +.IR db_recno (3), +.IR db_txn (3) +.sp +.IR "The Ubiquitous B-tree" , +Douglas Comer, ACM Comput. Surv. 11, 2 (June 1979), 121-138. +.sp +.IR "Prefix B-trees" , +Bayer and Unterauer, ACM Transactions on Database Systems, Vol. 2, 1 +(March 1977), 11-26. +.sp +.IR "The Art of Computer Programming Vol. 3: Sorting and Searching" , +D.E. Knuth, 1968, pp 471-480. diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_hash.3 b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_hash.3 new file mode 100644 index 00000000..adb88fca --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_hash.3 @@ -0,0 +1,138 @@ +.\" Copyright (c) 1990, 1993, 1994, 1995 +.\" The Regents of the University of California. 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. +.\" +.\" @(#)db_hash.3 8.13 (Berkeley) 8/1/95 +.\" +.TH DB_HASH 3 "August 1, 1995" +.UC 7 +.SH NAME +db_hash \- hash database access method +.SH DESCRIPTION +.so db.so +.GN +specific details of the hashing access method. +.PP +The hash data structure is an extensible, dynamic hashing scheme. +Backward compatible interfaces to the functions described in +.IR dbm (3), +and +.IR ndbm (3) +are provided, however these interfaces are not compatible with +previous file formats. +.SH "ACCESS METHOD SPECIFIC INFORMATION" +The hash access method specific data structure provided to +.I db_open +is typedef'd and named HASHINFO. +A HASHINFO structure has at least the following fields, +which may be initialized before calling +.IR db_open : +.TP 5 +u_int bsize; +.I Bsize +defines the hash table bucket size, and is, by default, 256 bytes. +It may be preferable to increase the page size for disk-resident tables +and tables with large data items. +.TP 5 +u_int cachesize; +A suggested maximum size, in bytes, of the memory cache. +This value is +.B only +advisory, and the access method will allocate more memory rather +than fail. +.TP 5 +u_int ffactor; +.I Ffactor +indicates a desired density within the hash table. +It is an approximation of the number of keys allowed to accumulate in any +one bucket, determining when the hash table grows or shrinks. +The default value is 8. +.TP 5 +u_int32_t (*hash)(const void *, size_t); +.I Hash +is a user defined hash function. +Since no hash function performs equally well on all possible data, the +user may find that the built-in hash function does poorly on a particular +data set. +User specified hash functions must take two arguments (a pointer to a byte +string and a length) and return a 32-bit quantity to be used as the hash +value. +.IP +If a hash function is specified, +.I hash_open +will attempt to determine if the hash function specified is the same as +the one with which the database was created, and will fail if it is not. +.TP 5 +int lorder; +The byte order for integers in the stored database metadata. +The number should represent the order as an integer; for example, +big endian order would be the number 4,321. +If +.I lorder +is 0 (no order is specified) the current host order is used. +If the file already exists, the specified value is ignored and the +value specified when the tree was created is used. +.TP 5 +u_int nelem; +.I Nelem +is an estimate of the final size of the hash table. +If not set or set too low, hash tables will expand gracefully as keys +are entered, although a slight performance degradation may be noticed. +The default value is 1. +.PP +If the file already exists (and the O_TRUNC flag is not specified), the +values specified for the parameters bsize, ffactor, lorder and nelem are +ignored and the values specified when the tree was created are used. +.SH "DB OPERATIONS" +The functions returned by +.I db_open +for the hash access method are as described in +.IR db_open (3). +.SH ERRORS +The +.I hash +access method functions may fail and set +.I errno +for any of the errors specified for the library function +.IR db_open (3). +.SH "SEE ALSO" +.IR db_btree (3), +.IR db_lock (3), +.IR db_log (3), +.IR db_mpool (3), +.IR db_open (3), +.IR db_recno (3), +.IR db_txn (3) +.sp +.IR "Dynamic Hash Tables" , +Per-Ake Larson, Communications of the ACM, April 1988. +.sp +.IR "A New Hash Package for UNIX" , +Margo Seltzer, USENIX Proceedings, Winter 1991. diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_lock.3 b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_lock.3 new file mode 100644 index 00000000..b18a38c6 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_lock.3 @@ -0,0 +1,462 @@ +.\" Copyright (c) 1994, 1995 +.\" The Regents of the University of California. 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. +.\" +.\" @(#)db_lock.3 8.14 (Berkeley) 8/1/95 +.\" +.TH DB_LOCK 3 "August 1, 1995" +.UC 7 +.SH NAME +db_lock \- general purpose lock manager +.SH SYNOPSIS +.nf +.ft B +#include + +int +lock_create(const char *path, mode_t mode, +.ti +5 +int lock_modes, const int8_t conflicts[][], u_int maxlocks); + +LOCK_TABLE_T * +lock_open(const char *path); + +int +lock_vec(LOCK_TABLE_T *lt, DBT *locker, struct timespec *timeout, +.ti +5 +LOCK_REQ_T list[], int nlist, LOCK_REQ_T **elistp, DBT *conflict); + +int +lock_get(LOCK_TABLE_T *lt, const DBT *locker, +.ti +5 +const DBT *obj, const lock_mode_t lock_mode, LOCK_T **lockp); + +int +lock_put(LOCK_T *lockp); + +int +lock_close(LOCK_TABLE_T *lt); + +int +lock_unlink(const char *path, int force); +.ft R +.fi +.SH DESCRIPTION +.so db.so +.GN +specific details of the locking interface. +.PP +.I Db_lock +is the library interface intended to provide general-purpose locking. +While designed to work with the other DB functions, these functions are +also useful for more general locking purposes. +Locks can be shared between processes. +.PP +.CR "lock table" lock +.PP +The parameter +.I lock_modes +is the number of lock modes to be recognized by the lock table +(including the ``not-granted'' mode). +The parameter +.I conflicts +is an +.I lock_modes +by +.I lock_modes +array. +A non-0 value for: +.sp +.ti +5 +conflicts[requested_mode][held_mode] +.sp +indicates that +.I requested_mode +and +.I held_mode +conflict. +The ``not-granted'' mode must be represented by 0. +.PP +The include file declares two commonly used conflict arrays: +.TP 5 +int lock_sx_n; +.br +.ns +.TP 5 +const int8_t lock_sx_c[lock_sx_n][lock_sx_n]; +These variables specify a conflict array +for a simple scheme using shared and exclusive lock modes. +.TP 5 +int lock_g_n; +.br +.ns +.TP 5 +const int8_t lock_g_c[lock_g_n][lock_g_n]; +These variables specify a conflict array that involves various intent +lock modes (e.g. intent shared) that are used for multigranularity locking. +.PP +In addition, + defines the following macros that name lock modes for use with +the standard tables above: +.RS +.TP 5 +LOCK_IS +intent shared +.br +.ns +.TP 5 +LOCK_IX +intent exclusive +.br +.ns +.TP 5 +LOCK_NG +not granted (always 0) +.br +.ns +.TP 5 +LOCK_S +shared +.br +.ns +.TP 5 +LOCK_SIX +shared/intent exclusive +.br +.ns +.TP 5 +LOCK_X +exclusive +.RE +.PP +.I Maxlocks +is the maximum number of locks to be held or requested in the table, +and is used by +.I lock_create +to estimate how much space to allocate for various lock-table data +structures. +.PP +.RT lock_create +.PP +.OP "lock table" lock +.PP +The function +.I lock_vec +atomically obtains and releases one or more locks from the designated +table. +The function +.I lock_vec +is intended to support acquisition or trading of multiple locks +under one lock table semaphore, as is needed for lock coupling or +in multigranularity locking for lock escalation. +.PP +If any of the requested locks cannot be acquired +or any of the locks to be released cannot be released, +no locks are acquired and no locks are released, and +.I lock_vec +returns an error. +The function +.I lock_vec +returns 0 on success. +If an error occurs, +.I lock_vec +returns one of the following values. +In addition, if +.I elistp +is not NULL, it is set to point to the LOCK_REQ_T entry which +was being processed when the error occurred. +.TP 5 +LOCK_GET_DEADLOCK +The specified +.I locker +was selected as a victim in order to resolve a deadlock. +In this case, if the +.I conflict +argument is non-NULL, it is set to reference the identity of a +locker holding the lock referenced by +.I elistp +at the time the request was denied. +(This identity resides in static memory and may be overwritten by +subsequent calls to +.IR lock_vec ). +.TP 5 +LOCK_GET_ERROR +An error occurred and the external variable +.I errno +has been set to indicate the error. +.TP 5 +LOCK_GET_NOTHELD +The lock cannot be released, as it was not held by the +.IR locker . +.TP 5 +LOCK_GET_RESOURCE +The lock manager is unable to grant the requested locks because of +limited internal resources. +(Releasing locks may allow future calls to +.I lock_vec +to succeed.) +.TP 5 +LOCK_GET_TIMEOUT +A timeout argument was specified, and the requested locks were not +available soon enough. +In this case, if the +.I conflict +argument is non-NULL, it is set to reference the identity of a +locker holding the lock referenced by +.I elistp +at the time the request was denied. +(This identity resides in static memory and may be overwritten by +subsequent calls to +.IR lock_vec ). +.PP +The +.I locker +argument specified to +.I lock_vec +is a pointer to an untyped byte string which identifies the entity +requesting or releasing the lock. +If +.I locker +is NULL, the calling process' pid is used instead. +.PP +The +.I timeout +argument provided to +.I lock_vec +specifies a maximum interval to wait for the locks to be granted. +If +.I timeout +is NULL, it is ignored, and +.I lock_vec +will not return until all of the locks are acquired or an error has +occurred. +.PP +The +.I list +array provided to +.I lock_vec +is typedef'd in as LOCK_REQ_T. +A LOCK_REQ_T structure has at least the following fields, +which must be initialized before calling +.IR lock_vec : +.TP 5 +enum lockop op; +The operation to be performed, which must be set to one of the +following values: +.RS +.TP 5 +LOCK_GET +Get a lock, as defined by the values of +.IR locker , +.I obj +and +.IR lock_mode . +Upon return from +.IR lock_vec , +if the +.I lockp +field is non-NULL, a reference to the acquired lock is stored there. +(This reference is invalidated by any call to +.I lock_vec +or +.I lock_put +which releases the lock.) +.TP 5 +LOCK_PUT +The lock referenced by the contents of the +.I lockp +field is released. +.TP 5 +LOCK_PUT_ALL +All locks held by the +.I locker +are released. +(Any locks acquired as a part of the current call to +.I lock_vec +are not considered for this operation). +.TP 5 +LOCK_PUT_OBJ +All locks held by the +.IR locker , +on the object +.IR obj , +with the mode specified by +.IR lock_mode , +are released. +A +.I lock_mode +of LOCK_NG indicates that all locks on the object should be released. +(Any locks acquired as a part of the current call to +.I lock_vec +are not considered for this operation). +.RE +.TP 5 +const DBT obj; +An untyped byte string which specifies the object to be locked or +released. +.TP 5 +const lock_mode_t lock_mode; +The lock mode, used as an index into +.IR lt 's +conflict array. +.TP 5 +LOCK_T **lockp; +A pointer to a pointer to a lock reference. +.PP +The +.I nlist +argument specifies the number of elements in the +.I list +array. +.PP +The function +.I lock_get +is a simple interface to the +.I lock_vec +functionality, and is equivalent to calling the +.I lock_vec +function with the +.I lt +and +.I locker +arguments, NULL +.IR timeout , +.I elistp +and +.I conflict +arguments, and a single element +.I list +array, for which the +.I op +field is LOCK_GET, and the +.IR obj , +.I lock_mode +and +.I lockp +fields are represented by the arguments of the same name. +Note that the type of the +.I obj +argument to +.I lock_get +is different from the +.I obj +element found in the LOCK_REQ_T structure. +The +.I lock_get +function returns success and failure as described for the +.I lock_vec +function. +.PP +The function +.I lock_put +is a simple interface to the +.I lock_vec +functionality, and is equivalent to calling the +.I lock_vec +function with a single element +.I list +array, for which the +.I op +field is LOCK_PUT and the +.I lockp +field is represented by the argument of the same name. +Note that the type of the +.I lockp +argument to +.I lock_put +is different from the +.I lockp +element found in the LOCK_REQ_T structure. +The +.I lock_put +function returns success and failure as described for the +.I lock_vec +function. +.PP +The function +.I lock_close +disassociates the calling process from the lock table +.IR lt , +after releasing all locks held or requested by that process. +.RT lock_close +.PP +.UN "lock table" lock +.SH "ERRORS" +The +.I lock_create +function may fail and set +.I errno +for any of the errors specified for the library routines +.IR mmap (2), +.IR open (2) +and +.IR malloc (3). +.PP +The +.I lock_open +function may fail and set +.I errno +for any of the errors specified for the library routine +.IR mmap (2) +and +.IR open (2). +.PP +The +.I lock_close +function may fail and set +.I errno +for any of the errors specified for the library routine +.IR close (2) +and +.IR munmap (2). +.PP +The +.I lock_unlink +function may fail and set +.I errno +for any of the errors specified for the library function +.IR unlink (2) +or the following: +.TP 5 +[EBUSY] +The lock table was in use and the force flag was not set. +.SH "SEE ALSO" +.IR db_btree (3), +.IR db_hash (3), +.IR db_log (3), +.IR db_mpool (3), +.IR db_open (3), +.IR db_recno (3), +.IR db_txn (3) +.SH BUGS +The +.I maxlocks +parameter is a kluge, and should be deleted in favor of dynamically +expanding the lock table. diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_log.3 b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_log.3 new file mode 100644 index 00000000..34c4d1f5 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_log.3 @@ -0,0 +1,290 @@ +.\" Copyright (c) 1990, 1993, 1994, 1995 +.\" The Regents of the University of California. 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. +.\" +.\" @(#)db_log.3 8.15 (Berkeley) 8/3/95 +.\" +.TH DB_LOG 3 "August 3, 1995" +.UC 7 +.SH NAME +db_log \- log-manager access method +.SH DESCRIPTION +.so db.so +.GN +specific details of the logging access method. +.PP +These functions provide a general-purpose logging facility sufficient +for transaction management. +Logs can be shared by multiple processes. +.PP +A log is represented by the directory, +.IR "not the file" , +named by the first argument to +.IR db_open (3). +The first argument must be non-NULL, +and the directory must already exist +.I db_open +is called. +In that directory, the log is stored in one or more files named +in the format ``log.YYYY.MM.DD.HH.MM.SS'', where ``YYYY.MM.DD.HH.SS'' +is the approximate creation time of the log file, and is guaranteed +to be unique in the directory. +.PP +The group of the created files is based on the system and directory +defaults, and is not further specified by the log access method. +All files are created with the +.I mode +specified to +.IR db_open , +(as described in +.IR chmod (2)) +and modified by the process' umask value (see +.IR umask (2)). +.PP +The +.I flags +argument to +.I db_open +must be 0 for the +.I db_log +access method. +.SH "ACCESS METHOD SPECIFIC INFORMATION" +The log access method specific data structure provided to +.I db_open +is typedef'd and named LOGINFO. +A LOGINFO structure has at least the following fields, +which may be initialized before calling +.IR db_open : +.TP 5 +off_t max_file_size; +The maximum size of a single file in the log. +If not specified, the maximum size defaults to an implementation-specific +value. +.TP 5 +int lorder; +The byte order for integers in the stored database metadata. +The number should represent the order as an integer; for example, +big endian order would be the number 4,321. +If +.I lorder +is 0 (no order is specified) the current host order is used. +.PP +If the log already exists, the values specified for the parameters +max_file_size and lorder are ignored in favor of the values used +when the log was created. +.SH "DB OPERATIONS" +The data part of the key/data pair used by the log access method +is the same as for other access methods. +The key is different. +Each log record is identified by a log sequence number (LSN), +which is stored in a DBT, and which is used as the +.I key +for all log functions that take +.I key +arguments. +Applications cannot create LSN's, and all LSN's provided to functions +as arguments must first be retrieved using the +.I put +or +.I seq +functions. +To provide a distinguished value for applications, it is guaranteed that +no valid LSN will ever have a size of 0. +.PP +Applications can compare LSN's using the +.I log_lsn_compare +function (see below). +.PP +Applications can associate LSN's with specific log files. +The function +.I log_lsn_file +(see below), returns the name of the log file containing the +record with a specified LSN. +(The mapping of LSN to file is needed for database administration. +For example, a transaction manager typically records the earliest LSN +needed for restart, and the database administrator may want to archive +log files to tape when they contain only LSN's before the earliest one +needed for restart.) +.PP +Applications can truncate the log file up to a specific LSN using the +.I log_trunc +function (see below). +.PP +The functions returned by +.I db_open +for the log access method are as described in +.IR db_open , +with the following exceptions and additions: +.TP 5 +type +The type is DB_LOG. +.TP 5 +del +The +.I del +function always returns an error for the log-manager access method, +setting +.I errno +to EINVAL. +.TP 5 +int (*log_flush)(const DB *db, const DBT *lsn); +The +.I log_flush +function flushes the log up to and including the log record +.IR lsn . +.RT log_flush +.TP 5 +int (*log_lsn_compare)(const DB *, +.ti +5 +const DBT *lsn1, const DBT *lsn2); +A pointer to a function which is provided to permit applications to +compare LSN's. +The +.I log_lsn_compare +function returns an integer less than, equal to, or greater than zero +if the first LSN is considered to be respectively less than, equal to, +or greater than the second LSN. +.TP 5 +int (*log_lsn_file)(const DB *db, +.ti +5 +const DBT *lsn, char *name); +.br +The +.I log_lsn_file +function stores a pointer to the name of the file containing +.I lsn +in the address referenced by +.IR name. +This pointer is to an internal static object, and subsequent calls to +the same function will modify the same object. +.IP +.RT log_lsn_file +.TP 5 +int (*log_unlink)(const char *path, int force); +The +.I log_unlink +function destroys the log represented by +.IR path . +If the +.I force +parameter is not set to 1 and there are other processes using the +log, then +.I log_unlink +will return -1, setting +.IR errno +to EBUSY. +If +.I force is not set or there are no processes using the log, then all files +used by the log are destroyed. +.I log_unlink +will return -1 on failure, setting +.IR errno , +and 0 on success. +.TP 5 +int (*log_trunc)(const DB *db, const DBT *lsn); +The +.I log_trunc +function truncates the log up to an LSN which is less than +.IR lsn . +.RT log_trunc +.TP 5 +put +A log record containing +.I data +is appended to the log. +Unlike the +.I put +functions for other access methods, the key parameter is not initialized +by the application, instead, the LSN assigned to the data is returned in +the +.I key +parameter. +.IP +The caller is responsible for providing any necessary structure to +.I data . +(For example, in a write-ahead logging protocol, the application must +understand what part of +.I data +is an operation code, what part is redo information, and what part is +undo information. +In addition, most transaction managers will store in +.I data +the LSN of the previous log record for the same transaction, +to support chaining back through the transaction's log records +during undo.) +.IP +The parameter +.I flag +must be set to 0 or exactly one of the following values: +.RS +.TP 5 +R_CHECKPOINT +Specify the key/data pair of the current call as the one to be returned +when the +.I seq +function is next called with the R_CHECKPOINT flag. +.TP 5 +R_FLUSH +Flush immediately (ignoring any possibility for group commit). +.RE +.TP 5 +seq +The +.I seq +function takes the following additional flag: +.RS +.TP 5 +R_CHECKPOINT +The last key/data pair stored by the +.I put +function (using the R_CHECKPOINT flag) is returned, +and the cursor is set or initialized to reference it. +The expected use of this flag is during restart and to determine what +part of the log must be available for restart. +Therefore, the log record retrieved with R_CHECKPOINT should contain +all the information that the transaction manager will need for this +purpose. +.RE +.TP 5 +sync +The +.I sync +function always returns an error for the log-manager access method, +setting +.I errno +to EINVAL. +.SH "SEE ALSO" +.IR db_btree (3), +.IR db_hash (3), +.IR db_lock (3), +.IR db_mpool (3), +.IR db_open (3), +.IR db_recno (3), +.IR db_txn (3) diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_mpool.3 b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_mpool.3 new file mode 100644 index 00000000..4b683b61 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_mpool.3 @@ -0,0 +1,403 @@ +.\" Copyright (c) 1990, 1993, 1994, 1995 +.\" The Regents of the University of California. 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. +.\" +.\" @(#)db_mpool.3 8.14 (Berkeley) 8/1/95 +.\" +.TH DB_MPOOL 3 "August 1, 1995" +.UC 7 +.SH NAME +db_mpool \- general purpose shared memory buffer pool +.SH SYNOPSIS +.nf +.ft B +#include +#include + +int +mpool_create(char *path, mode_t mode, size_t cachesize, u_long flags); + +MPOOL * +mpool_open(char *path); + +int +mpool_close(MPOOL *mp); + +MPOOLFILE * +mpool_fopen(MPOOL *mp, char *path, size_t pagesize, void *pgcookie, +.ti +5 +int (*pgin)(MPOOLFILE *mpf, +.ti +8 +pgno_t pgno, void *pgaddr, void *pgcookie), +.ti +5 +int (*pgout)(MPOOLFILE *mpf, +.ti +8 +pgno_t pgno, void *pgaddr, void *pgcookie); + +int +mpool_fclose(MPOOLFILE *mpf); + +void * +mpool_get(MPOOLFILE *mpf, pgno_t *pgnoaddr, u_long flags, +.ti +5 +int (*callback)(MPOOLFILE *mpf, pgno_t pgno)); + +int +mpool_put(MPOOLFILE *mpf, void *pgaddr, u_long flags); + +int +mpool_sync(MPOOLFILE *mpf); + +int +mpool_unlink(const char *path, int force); + +void +mpool_stat(MPOOL *mp, FILE *fp); +.ft R +.fi +.SH DESCRIPTION +.so db.so +.GN +specific details of the memory pool interface. +.PP +The +.I db_mpool +function is the library interface intended to provide general-purpose, +page-oriented buffer management of one or more files. +While designed to work with the other DB functions, these functions are +also useful for more general purposes. +The memory pools (MPOOL's) are referred to in this document as +simply ``pools''. +Pools may be shared between processes. +Pools are usually filled by pages from one or more files (MPOOLFILE's). +Pages in the pool are replaced in LRU (least-recently-used) order, +with each new page replacing the page which has been unused the longest. +Pages retrieved from the pool using +.I mpool_get +are ``pinned'' in memory, by default, +until they are returned to the pool using the +.I mpool_put +function. +.PP +.CR "memory pool" mpool +.PP +The +.I cachesize +argument specifies the size of the pool in bytes, +and should be the size of the normal working set of the application with +some small amount of additional memory for unusual situations. +If the number of bytes currently ``pinned'' in memory exceeds +.IR cachesize , +the +.I db_mpool +functions will attempt to allocate more memory and do not necessarily fail, +although they may suffer performance degradation. +.PP +The +.I flags +argument is set by +.IR or 'ing +any of the following values: +.TP +MPOOL_PRIVATE +The pool is not shared by other processes or threads, +so no locking of pool resources is required. +.PP +.OP "memory pool" mpool +.PP +The +.I mpool_close +function closes the pool indicated by the MPOOL pointer +.IR mp , +as returned by +.IR mpool_open . +This function does +.B not +imply a call to +.I mpool_sync +(or to +.IR mpool_fclose ) +i.e. no pages are written to the source file as as a result of calling +.IR mpool_close . +.RT mpool_close +.PP +The function +.I mpool_fopen +opens a file for buffering in the pool specified by the MPOOL +argument. +The +.I path +argument is the name of the file to be opened. +The +.I pagesize +argument is the size, in bytes, of the unit of transfer between the +application and the pool, although not necessarily the unit of transfer +between the pool and the source file. +Applications not knowing the page size of the source file should +retrieve the metadata from the file using a page size that is correct +for the metadata, then close and reopen the file, or, +otherwise determine the page size before calling +.IR mpool_fopen . +.PP +If the +.I pgin +function is specified, it is called each time a page is read into +the memory pool from the source file. +If the +.I pgout +function is specified, it is called each time a page is written +to the source file. +Both functions are called with the MPOOLFILE pointer returned from +.IR mpool_fopen , +the page number, a pointer to the page being read or written, and +the argument +.IR pgcookie . +If either function fails, it should return non-zero and set +.IR errno , +in which case the +.I db_mpool +function calling it will also fail, leaving +.I errno +intact. +.PP +The +.I mpool_fclose +function closes the source file indicated by the MPOOLFILE pointer +.IR mpf . +This function does +.B not +imply a call to +.IR mpool_sync , +i.e. no pages are written to the source file as as a result of calling +.IR mpool_fclose . +.RT mpool_fclose +.\" +.\".PP +.\"int +.\"mpool_fd (MPOOLFILE *mpf); +.\" +.\".PP +.\"The function +.\".I mpool_fd +.\"takes an MPOOLFILE pointer and returns the file descriptor being +.\"used to read/write that file +.\"to/from the pool. +.PP +The function +.I mpool_get +returns a pointer to the page with the page number specified by +.IR pgnoaddr , +from the source file specified by the MPOOLFILE pointer +.IR mpf . +If the page does not exist or cannot be retrieved, +.I mpool_get +returns NULL and sets errno. +.PP +The +.I flags +argument is set by +.IR or 'ing +any of the following values: +.TP 5 +MPOOL_CALLBACK +After the page number has been determined, but before any other +process or thread can access the page, the function specified by +the +.I callback +argument is called. +If the function fails, it should return non-zero and set +.IR errno , +in which case +.I mpool_get +will also fail, leaving +.I errno +intact. +The +.I callback +function is called with the MPOOLFILE pointer returned from +.I mpool_fopen +and the page number. +This functionality is commonly used when page locking is required, +but the page number of the page being retrieved is not known. +.TP 5 +MPOOL_CREATE +If the specified page does not exist, create it. +.TP 5 +MPOOL_LAST +Return the last page of the source file and copy its page number +to the location referenced by +.IR pgnoaddr . +.TP 5 +MPOOL_NEW +Create a new page in the file and copy its page number to the location +referenced by +.IR pgnoaddr . +.TP 5 +MPOOL_NOPIN +Don't pin the page into memory. +(This flag is intended for debugging purposes, when it's often useful +to examine pages which are currently held by other parts of the +application. +Pages retrieved in this manner don't need to be returned to the +memory pool, i.e. they should +.B not +be specified as arguments to the +.IR mpool_put +routine.) +.PP +Created pages have all their bytes set to 0. +.PP +All pages returned by +.I mpool_get +(unless the MPOOL_NOPIN flag is specified), +will be retained (i.e. ``pinned'') in the pool until a subsequent +call to +.IR mpool_put . +.PP +The function +.I mpool_put +indicates that the page referenced by +.I pgaddr +can be evicted from the pool. +.I Pgaddr +must be an address previously returned by +.IR mpool_get . +.PP +The flag value is specified by +.IR or 'ing +any of the following values: +.TP 5 +MPOOL_DIRTY +The page has been modified and must be written to the source file +before being evicted from the pool. +.TP 5 +MPOOL_DISCARD +The page is unlikely to be useful in the near future, and should be +discarded before other pages in the pool. +.PP +.RT mpool_put +.PP +The function +.I mpool_sync +writes all pages associated with the MPOOLFILE pointer +.IR mpf , +which were specified as arguments to the +.I mpool_put +function with an associated flag of +MPOOL_DIRTY, +to the source file. +.RT mpool_sync +.PP +.UN "memory pool" mpool +.PP +The function +.I mpool_stat +writes statistics for the memory pool +.I mp +to the file specified by +.IR fp . +These statistics include the number of files participating in the pool, +the active pages in the pool, and numbers as to how effective the cache +has been. +.SH ERRORS +The +.IR mpool_create , +.I mpool_open +and +.I mpool_fopen +functions may fail and set +.I errno +for any of the errors specified for the library functions +.IR open (2), +.IR read (2), +and +.IR malloc (3). +.PP +The +.I mpool_close +and +.I mpool_fclose +functions may fail and set +.I errno +for any of the errors specified for the library functions +.IR close (2) +and +.IR free (3). +.PP +The +.I mpool_get +function may fail and set +.I errno +for any of the errors specified for the library functions +.IR read (2), +.IR write (2), +and +.IR malloc (3) +or the following: +.TP 5 +[EINVAL] +The requested page does not exist and MPOOL_CREATE was not set. +.PP +The +.I mpool_put +function may fail and set +.I errno +for any of the errors specified for the library function +.IR write (2) +or the following: +.TP 5 +[EACCES] +The source file was not opened for writing. +.PP +The +.I mpool_sync +function may fail and set +.I errno +for any of the errors specified for the library function +.IR write (2). +.PP +The +.I mpool_unlink +function may fail and set +.I errno +for any of the errors specified for the library function +.IR unlink (2) +or the following: +.TP 5 +[EBUSY] +The memory pool was in use and the force flag was not set. +.SH "SEE ALSO" +.IR db_btree (3), +.IR db_hash (3), +.IR db_lock (3), +.IR db_log (3), +.IR db_open (3), +.IR db_recno (3), +.IR db_txn (3) diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_open.3 b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_open.3 new file mode 100644 index 00000000..f988ef92 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_open.3 @@ -0,0 +1,574 @@ +.\" Copyright (c) 1990, 1993, 1994, 1995 +.\" The Regents of the University of California. 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. +.\" +.\" @(#)db_open.3 8.15 (Berkeley) 8/1/95 +.\" +.TH DB_OPEN 3 "August 1, 1995" +.UC 7 +.SH NAME +db_open \- database access methods +.SH SYNOPSIS +.nf +.ft B +#include + +DB * +db_open(const char *file, int flags, int mode, +.ti +5 +DBTYPE type, DBINFO *dbinfo, const void *openinfo); +.ft R +.fi +.SH DESCRIPTION +.so db.so +.GN +the overall structure of the available access methods. +.PP +The currently supported file formats are btree, hashed, log and recno +(i.e. flat-file oriented). +The btree format is a representation of a sorted, balanced tree structure. +The hashed format is an extensible, dynamic hashing scheme. +The log format is a general-purpose logging facility. +The recno format is a byte stream file with fixed or variable length +records. +The formats and other, format specific information are described in detail +in their respective manual pages: +.IR db_btree (3), +.IR db_hash (3), +.IR db_log (3), +and +.IR db_recno (3). +.PP +Db_open opens +.I file +for reading and/or writing. +Files never intended to be preserved on disk may be created by setting +the file parameter to NULL. +(Note, while most of the access methods use +.I file +as the name of an underlying file on disk, this is not guaranteed. +See the manual pages for the individual access methods for more +information.) +.PP +The +.I flags +and +.I mode arguments +are as specified to the +.IR open (2) +function, however, only the O_CREAT, O_EXCL, O_EXLOCK, O_NONBLOCK, +O_RDONLY, O_RDWR, O_SHLOCK and O_TRUNC flags are meaningful. +(Note, opening a database file O_WRONLY is not possible.) +.\"Three additional options may be specified by +.\".IR or 'ing +.\"them into the +.\".I flags +.\"argument. +.\".TP +.\"DB_LOCK +.\"Do the necessary locking in the database to support concurrent access. +.\"If concurrent access isn't needed or the database is read-only this +.\"flag should not be set, as it tends to have an associated performance +.\"penalty. +.\".TP +.\"DB_SHMEM +.\"Place the underlying memory pool used by the database in shared +.\"memory. +.\"Necessary for concurrent access. +.\".TP +.\"DB_TXN +.\"Support transactions in the database. +.\"The DB_LOCK and DB_SHMEM flags must be set as well. +.PP +The +.I type +argument is of type DBTYPE (as defined in the include file) and +may be set to DB_BTREE, DB_HASH, DB_LOG or DB_RECNO. +.PP +The +.I dbinfo +argument is a pointer to a structure containing references to locking, +logging, transaction, and shared-memory buffer pool information. +If +.I dbinfo +is NULL, then the access method may still use these subsystems, +but the usage will be private to the application and managed by DB. +If +.I dbinfo +is non-NULL, +then the module referenced by each of the non-NULL fields is used by DB +as necessary. +The fields of the DBINFO structure are defined as follows: +.TP 5 +const char *errpfx; +A prefix to prepend to error messages; used only if +.I errfile +is non-NULL. +.TP 5 +FILE *errfile; +The +.IR stdio (3) +file stream to which error messages are logged. +.sp +When any error occurs in the +.I db_open +function, or in any function called using a field of the returned DB +structure, an error value is returned by the function, +and the global variable +.I errno +is set appropriately. +In some cases, however, the +.I errno +value may be insufficient to describe the cause of the error. +In these cases, if +.I errfile +is non-NULL, additional error information will be written to the file +stream it represents, preceded by the string, if any, specified by +.IR errpfx . +This error logging facility should not be required for normal operation, +but may be useful in debugging applications. +.TP 5 +char *errbuf; +The buffer to which error messages are copied. +If non-NULL, +.I errbuf +behaves as described for +.IR errfile , +except that the +.I errpfx +field is ignored and the error message is copied into the specified +buffer instead of being written to the FILE stream. +The DB routines assume that the associated buffer is at least 1024 bytes +in length. +.TP 5 +LOCK_TABLE_T *lockinfo; +If locking is required for the file being opened (as in the case of +buffers being maintained in a shared memory buffer pool), +the +.I lockinfo +field contains a return value from the function +.I lock_open +that should be used +(see +.IR db_lock (3)). +If +.I lockinfo +is NULL, no locking is done. +.TP 5 +DB *loginfo; +If modifications to the file being opened should be logged, the +.I loginfo +field contains a return value from the function +.IR dbopen , +when opening a DB file of type DB_LOG. +If +.I loginfo +is NULL, no logging is done. +.TP 5 +MPOOL *mpoolinfo; +If the cache for the file being opened should be maintained in a shared +buffer pool, the +.I mpoolinfo +field contains a return value from the function +.I mpool_open +that should be used +(see +.IR db_mpool (3)). +If +.I mpoolinfo +is NULL, a memory pool may still be created, +but it will be private to the application and managed by DB. +.TP 5 +TXNMGR *txninfo; +If the accesses to the file being opened should take place in the context +of transactions (providing atomicity and complete error recovery), the +.I txninfo +field contains a return value from the function +.I txn_open +(see +.IR db_txn (3)). +If transactions are specified, +the application is responsible for making suitable calls to +.IR txn_begin , +.IR txn_abort , +and +.IR txn_commit . +If +.I txninfo +is NULL, no transaction support is done. +.PP +The +.I openinfo +argument is a pointer to an access method specific structure described +in the access method's manual page. +If +.I openinfo +is NULL, each access method will use defaults appropriate for the system +and the access method. +.SH "KEY/DATA PAIRS" +Access to all access methods is based on key/data pairs. +Both keys and data are represented by the following data structure: +.PP +typedef struct { +.RS +void *data; +.br +size_t size; +.RE +} DBT; +.PP +The elements of the DBT structure are defined as follows: +.TP 5 +data +A pointer to a byte string. +.ns +.br +.TP 5 +size +The length of +.IR data , +in bytes. +.PP +Key and data byte strings may reference strings of essentially unlimited +length, although any two of them must fit into available memory at the +same time. +.PP +The access methods provide no guarantees about byte string alignment, +and applications are responsible for maintaining any necessary alignment. +.SH "DB OPERATIONS" +.I Db_open +returns a pointer to a DB structure (as defined in the include file) +on success, and NULL on error. +The DB structure describes a database type, and includes a set of functions +to perform various actions, as described below. +Each of these functions takes a pointer to a DB structure, and may take +one or more DBT *'s and a flag value as well. +Individual access methods specify additional functions and flags which +are specific to the method. +The fields of the DB structure are as follows: +.TP 5 +DBTYPE type; +The type of the underlying access method (and file format). +.TP 5 +int (*close)(const DB *db); +A pointer to a function to flush any cached information to disk, +free any allocated resources, and close any underlying files. +Since key/data pairs are cached in memory, failing to sync the +file with the +.I close +or +.I sync +function may result in inconsistent or lost information. +.IP +The +.I close +functions return -1 on failure, setting +.IR errno , +and 0 on success. +.TP 5 +int (*del)(const DB *db, TXN *txnid, +.ti +5 +const DBT *key, u_int flags); +.br +A pointer to a function to remove key/data pairs from the database. +The key/data pair associated with the specified +.I key +are discarded from the database. +.IP +The +.I txnid +parameter contains a transaction ID returned from +.IR txn_begin , +if the file is being accessed under transaction protection, +or NULL if transactions are not in effect. +.IP +The parameter +.I flag +must be set to 0 or exactly one of the following values: +.RS +.TP 5 +R_CURSOR +Delete the record referenced by the cursor. +The cursor must have previously been initialized. +.RE +.IP +The +.I delete +functions return -1 on error, setting +.IR errno , +0 on success, and 1 if the specified +.I key +did not exist in the file. +.TP 5 +int (*fd)(const DB *db); +A pointer to a function which returns a file descriptor representative +of the underlying database. +A file descriptor referencing the same file will be returned to all +processes which call +.I db_open +with the same +.I file +name. +This file descriptor may be safely used as an argument to the +.IR fcntl (2) +and +.IR flock (2) +locking functions. +The file descriptor is not necessarily associated with any of the +underlying files used by the access method. +No file descriptor is available for in memory databases. +.IP +The +.I fd +functions return -1 on error, setting +.IR errno , +and the file descriptor on success. +.TP 5 +int (*get)(const DB *db, TXN *txnid, +.ti +5 +const DBT *key, DBT *data, u_int flags); +.br +A pointer to a function which is the interface for keyed retrieval from +the database. +The address and length of the data associated with the specified +.I key +are returned in the structure referenced by +.IR data . +.IP +The +.I txnid +parameter contains a transaction ID returned from +.IR txn_begin , +if the file is being accessed under transaction protection, +or NULL if transactions are not in effect. +.IP +The +.I get +functions return -1 on error, setting +.IR errno , +0 on success, and 1 if the +.I key +was not found. +.TP 5 +int (*put)(const DB *db, TXN *txnid, +.ti +5 +DBT *key, const DBT *data, u_int flags); +.br +A pointer to a function to store key/data pairs in the database. +.IP +The +.I txnid +parameter contains a transaction ID returned from +.IR txn_begin , +if the file is being accessed under transaction protection, +or NULL if transactions are not in effect. +.IP +The parameter +.I flag +must be set to 0 or exactly one of the following values: +.RS +.TP 5 +R_CURSOR +Replace the key/data pair referenced by the cursor. +The cursor must have previously been initialized. +.TP 5 +R_NOOVERWRITE +Enter the new key/data pair only if the key does not previously exist. +.RE +.IP +The default behavior of the +.I put +functions is to enter the new key/data pair, replacing any previously +existing key. +.IP +The +.I put +functions return -1 on error, setting +.IR errno , +0 on success, and 1 if the R_NOOVERWRITE +.I flag +was set and the key already exists in the file. +.TP 5 +int (*seq)(const DB *db, TXN *txnid, +.ti +5 +DBT *key, DBT *data, u_int flags); +.br +A pointer to a function which is the interface for sequential +retrieval from the database. +The address and length of the key are returned in the structure +referenced by +.IR key , +and the address and length of the data are returned in the +structure referenced +by +.IR data . +.IP +The +.I txnid +parameter contains a transaction ID returned from +.IR txn_begin , +if the file is being accessed under transaction protection, +or NULL if transactions are not in effect. +.IP +Sequential key/data pair retrieval may begin at any time, and the +logical position of the ``cursor'' is not affected by calls to the +.IR del , +.IR get , +.IR put , +or +.I sync +functions. +Modifications to the database during a sequential scan will be reflected +in the scan, i.e. records inserted behind the cursor will not be returned +while records inserted in front of the cursor will be returned. +.IP +The parameter +.I flag +must be set to 0 or exactly one of the following values: +.RS +.TP 5 +R_CURSOR +The data associated with the specified key is returned. +This differs from the +.I get +functions in that it sets or initializes the cursor to the location of +the key as well. +.TP 5 +R_FIRST +The first key/data pair of the database is returned, and the cursor +is set or initialized to reference it. +.TP 5 +R_NEXT +Retrieve the key/data pair immediately after the cursor. +If the cursor is not yet set, this is the same as the R_FIRST flag. +.RE +.IP +The +.I seq +functions return -1 on error, setting +.IR errno , +0 on success, +and 1 if there are no key/data pairs less than or greater than the +specified or current key. +.TP 5 +int (*sync)(const DB *db, u_int flags); +A pointer to a function to flush any cached information to disk. +If the database is in memory only, the +.I sync +function has no effect and will always succeed. +.IP +The parameter +.I flag +must be set to 0 or a value specified by an access method specific +manual page. +.IP +The +.I sync +functions return -1 on failure, setting +.IR errno , +and 0 on success. +.SH ERRORS +The +.I db_open +function may fail and set +.I errno +for any of the errors specified for the library functions +.IR open (2), +.IR malloc (3) +or the following: +.TP 5 +[EFTYPE] +A file is incorrectly formatted. +.TP 5 +[EINVAL] +A parameter has been specified (hash function, recno pad byte etc.) +that is incompatible with the current file specification or, a flag +to a function which is not meaningful for the function (for example, +use of the cursor without prior initialization) or there is a mismatch +between the version number of file and the software. +.PP +The +.I close +functions may fail and set +.I errno +for any of the errors specified for the library functions +.IR close (2), +.IR read (2), +.IR write (2), +.IR free (3), +or +.IR fsync (2). +.PP +The +.IR del , +.IR get , +.I put +and +.I seq +functions may fail and set +.I errno +for any of the errors specified for the library functions +.IR read (2), +.IR write (2), +.IR free (3) +or +.IR malloc (3). +.PP +The +.I fd +functions will fail and set +.I errno +to ENOENT for in memory databases. +.PP +The +.I sync +functions may fail and set +.I errno +for any of the errors specified for the library function +.IR fsync (2). +.SH "SEE ALSO" +.IR db_btree (3), +.IR db_hash (3), +.IR db_lock (3), +.IR db_log (3), +.IR db_mpool (3), +.IR db_recno (3), +.IR db_txn (3) +.SH BUGS +The name DBT is a mnemonic for ``data base thang'', and was used +because noone could think of a reasonable name that wasn't already +in use somewhere else. +.PP +The +.I fd +function interface is a kluge, +and will be deleted in a future version of the interface. +.PP +Only big and little endian byte order is supported. diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_recno.3 b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_recno.3 new file mode 100644 index 00000000..6b93b3f5 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_recno.3 @@ -0,0 +1,268 @@ +.\" Copyright (c) 1990, 1993, 1994, 1995 +.\" The Regents of the University of California. 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. +.\" +.\" @(#)db_recno.3 8.12 (Berkeley) 8/1/95 +.\" +.TH DB_RECNO 3 "August 1, 1995" +.UC 7 +.SH NAME +db_recno \- record number database access method +.SH DESCRIPTION +.so db.so +specific details of the recno access method. +.SH "ACCESS METHOD SPECIFIC INFORMATION" +The recno access method specific data structure provided to +.I db_open +is typedef'd and named RECNOINFO. +A RECNOINFO structure has at least the following fields, +which may be initialized before calling +.IR db_open : +.TP 5 +u_int8_t bval; +The delimiting byte to be used to mark the end of a record for +variable-length records, and the pad character for fixed-length +records. +If no value is specified, newlines (``\en'') are used to mark the end +of variable-length records and fixed-length records are padded with +spaces. +.TP 5 +char *bfname; +The recno access method stores the in-memory copies of its records +in a btree. +If bfname is non-NULL, it specifies the name of the btree file, +as if specified as the file name for a +.I db_open +of a btree file. +.TP 5 +u_int cachesize; +A suggested maximum size, in bytes, of the memory cache. +This value is +.B only +advisory, and the access method will allocate more memory rather than fail. +If +.I cachesize +is 0 (no size is specified) a default size is used. +.TP 5 +u_long flags; +The flag value is specified by +.IR or 'ing +any of the following values: +.RS +.TP 5 +R_FIXEDLEN +The records are fixed-length, not byte delimited. +The structure element +.I reclen +specifies the length of the record, and the structure element +.I bval +is used as the pad character. +Any records, inserted into the database, that are less than +.I reclen +bytes long are automatically padded. +.TP 5 +R_NOKEY +In the interface specified by +.IR db_open , +the sequential record retrieval fills in both the caller's key and +data structures. +If the R_NOKEY flag is specified, the +.I cursor +functions are not required to fill in the key structure. +This permits applications to retrieve records at the end of files without +reading all of the intervening records. +.TP 5 +R_SNAPSHOT +This flag requires that a snapshot of the file be taken when +.I db_open +is called, instead of permitting any unmodified records to be read from +the original file. +.RE +.TP 5 +int lorder; +The byte order for integers in the stored database metadata. +The number should represent the order as an integer; for example, +big endian order would be the number 4,321. +If +.I lorder +is 0 (no order is specified) the current host order is used. +.TP 5 +u_int psize; +The recno access method stores the in-memory copies of its records +in a btree. +This value is the size (in bytes) of the pages used for nodes in that tree. +If +.I psize +is 0 (no page size is specified) a page size is chosen based on the +underlying file system I/O block size. +See +.IR btree (3) +for more information. +.TP 5 +size_t reclen; +The length of a fixed-length record. +.SH "DB OPERATIONS" +The data part of the key/data pair used by the recno access method +is the same as other access methods. +The key is different. +The +.I data +field of the key should be a pointer to a memory location of type +.IR recno_t , +as defined in the include file. +This type is normally the largest unsigned integral type available to +the implementation. +The +.I size +field of the key should be the size of that type. +.PP +The record number data structure is either variable or fixed-length +records stored in a flat-file format, accessed by the logical record +number. +The existence of record number five requires the existence of records +one through four, and the deletion of record number one causes +record number five to be renumbered to record number four, as well +as the cursor, if positioned after record number one, to shift down +one record. +The creation of record number five when records one through four do +not exist causes the logical creation of them with zero-length data. +.PP +Because there is no meta-data associated with the underlying recno access +method files, any changes made to the default values (e.g. fixed record +length or byte separator value) must be explicitly specified each time the +file is opened. +.PP +The functions returned by +.I db_open +for the btree access method are as described in +.IR db_open (3), +with the following exceptions and additions: +.TP 5 +type +The type is DB_RECNO. +.TP 5 +put +Using the +.I put +interface to create a new record will cause the creation of multiple, +empty records if the record number is more than one greater than the +largest record currently in the database. +.IP +The +.I put +function takes the following additional flags: +.RS +.TP 5 +R_IAFTER +Append the data immediately after the data referenced by +.IR key , +creating a new key/data pair. +The record number of the appended key/data pair is returned in the +.I key +structure. +.TP 5 +R_IBEFORE +Insert the data immediately before the data referenced by +.IR key , +creating a new key/data pair. +The record number of the inserted key/data pair is returned in the +.I key +structure. +.TP 5 +R_SETCURSOR +Store the key/data pair, setting or initializing the position of the +cursor to reference it. +.RE +.TP 5 +seq +The +.I seq +function takes the following additional flags: +.RS +.TP 5 +R_LAST +The last key/data pair of the database is returned, and the cursor +is set or initialized to reference it. +.TP 5 +R_PREV +Retrieve the key/data pair immediately before the cursor. +If the cursor is not yet set, this is the same as the R_LAST flag. +.RE +.IP +If the database file is a character special file and no complete +key/data pairs are currently available, the +.I seq +function returns 2. +.TP 5 +sync +The +.I sync +function takes the following additional flag: +.RS +.TP 5 +R_RECNOSYNC +This flag causes the +.I sync +function to apply to the btree file which underlies the recno file, +not the recno file itself. +(See the +.I bfname +field of RECNOINFO +structure, above, for more information.) +.RE +.SH ERRORS +The +.I recno +access method functions may fail and set +.I errno +for any of the errors specified for the library function +.IR db_open (3) +or the following: +.TP 5 +[EINVAL] +An attempt was made to add a record to a fixed-length database that +was too large to fit. +.SH "SEE ALSO" +.IR db_btree (3), +.IR db_hash (3), +.IR db_lock (3), +.IR db_log (3), +.IR db_mpool (3), +.IR db_open (3), +.IR db_txn (3) +.sp +.IR "Document Processing in a Relational Database System" , +Michael Stonebraker, Heidi Stettner, Joseph Kalash, Antonin Guttman, +Nadene Lynn, Memorandum No. UCB/ERL M82/32, May 1982. +.SH BUGS +The +.I sync +function's R_RECNOSYNC interface is a kluge, +and will be deleted in a future version of the interface. diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_txn.3 b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_txn.3 new file mode 100644 index 00000000..18ad6469 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/db_txn.3 @@ -0,0 +1,373 @@ +.\" Copyright (c) 1994, 1995 +.\" The President and Fellows of Harvard University. All rights reserved. +.\" Copyright (c) 1994, 1995 +.\" Margo I. Selzer. 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. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. +.\" +.\" @(#)db_txn.3 8.8 (Harvard) 8/1/95 +.\" +.TH DB_TXN 3 "August 1, 1995" +.UC 7 +.SH NAME +db_txn \- transaction management functions +.SH SYNOPSIS +.nf +.ft B +#include +#include + +int +txn_create(const char *path, mode_t mode, u_int maxtxns, u_int flags); + +TXNMGR * +txn_open(const char *path, DBT *logp, LOCK_TABLE_T *lockp, +.ti +5 +int (*recover)(DBT *lsn, DBT *log_entry, int isundo)); + +TXN * +txn_begin(TXNMGR *txnp); + +int +txn_commit(TXN *tid); + +int +txn_prepare(TXN *tid); + +int +txn_abort(TXN *tid); + +int +txn_close(TXNMGR *txnp); + +int +txn_unlink(const char *path, int force); +.ft R +.fi +.SH DESCRIPTION +.so db.so +specific details of the transaction support. +.PP +.I Db_txn +is the library interface that provides transaction semantics. +Full transaction support is provided by a collection of modules +that provide well defined interfaces to the services required for +transaction processing. +These services are recovery (see +.IR db_log (3)), +concurrency control (see +.IR db_lock (3)), +and the management of shared data (see +.IR db_mpool (3)). +Transaction semantics can be applied to the access methods described in +.IR db (3) +through function call parameters. +.PP +The model intended for transactional use (and that is used by the +access methods) is that write-ahead logging is provided by +.IR db_log (3) +to record both before- and after-image logging. +Locking follows a two-phase protocol and is implemented by +.IR db_lock (3). +.PP +.CR "transaction region" txn +Any necessary, +associated log and lock regions are created as well (see +.IR db_log (3) +and +.IR db_lock (3)). +.PP +The +.I maxtxns +argument specifies the maximum number of simultaneous transactions that +are supported. +This bounds the size of backing files and is used to derive limits for +the size of the lock region and logfiles. +When there are more than +.I maxtxns +concurrent transactions, calls to +.I txn_begin +may fail. +.PP +Default locking and logging protocols are provided only if the +backing files exist. +If the backing files do not exist, the +.I flags +parameter must indicate both a logging mode and locking mode specified by +.IR or 'ing +together at most one flag from each of the TXN_LOCK and TXN_LOG classes +as follows: +.TP 5 +TXN_LOCK_2PL +Use two-phase locking. +.TP 5 +TXN_LOCK_OPTIMISTIC +Use optimistic locking (not currently implemented). +.TP 5 +TXN_LOG_REDO +Provide redo-only logging (not currently implemented). +.TP 5 +TXN_LOG_UNDO +Provide undo-only logging (not currently implemented). +.TP 5 +TXN_LOG_UNDOREDO +Provide undo/redo write-ahead logging. +.PP +.RT txn_create +.PP +.OP "transaction region" txn +.PP +The +.I recover +argument specifies a function that is called by +.I txn_abort +during transaction abort. +This function takes three arguments: +.TP 5 +lsn +A log sequence number (LSN). +.TP 5 +log_entry +A log record. +.TP 5 +isundo +An undo flag set to 0 if the operation is a redo and set to 1 if the +operation an undo. +.PP +As discussed in the +.I db_log (3) +manual page, +the application is responsible for providing any necessary structure +to the log record. +For example, the application must understand what part of the log +record is an operation code, what part is redo information, and what +part is undo information. +.PP +The +.I txn_begin +function creates a new transaction in the designated transaction +manager, returning a pointer to a TXN that uniquely identifies it. +.PP +The +.I txn_commit +function ends the transaction specified by the +.I tid +argument. +Any locks held by the transaction are released. +If logging is enabled, a commit log record is written and flushed to disk. +.PP +The +.I txn_abort +function causes an abnormal termination of the transaction. +If logging is enabled, the log is played backwards and any recovery +operations are initiated through the +.I recover +function specified to +.IR txn_open . +After recovery is completed, all locks held by the transaction are released. +.PP +The +.I txn_close +function detaches a process from the transaction environment specified +by the TXNMGR pointer. +All mapped regions are unmapped and any allocated resources are freed. +Any uncommitted transactions are aborted. +.PP +.UN "transaction region" txn +.PP +The +.I txn_prepare +function initiates the beginning of a two phase commit. +In a distributed transaction, +the prepare directive should be issued to all participating +transaction managers. +Each manager must take whatever action is necessary to guarantee +that a future call to +.I txn_commit +on the specified +.I tid +will succeed. +.SH "SYSTEM INTEGRATION" +This model can be applied to data bases other than the provided access +methods. +For example, consider an application that provides transaction semantics +to data stored in regular files accessed using the +.IR read (2) +and +.IR write (2) +system calls. +The operations for which transaction protection is desired are bracketed +by calls to +.I txn_begin +and +.IR txn_commit . +.PP +Before data are referenced, a call is made to the lock manager, +.IR db_lock , +for a lock of the appropriate type (e.g. read) +on the object being locked. +The object might be a page in the file, a byte, a range of bytes, +or some key. +Before a write is performed, the application makes a call to the +log manager, +.IR db_log , +to record enough information to redo the operation in case of +failure after commit and to undo the operation in case of abort. +After the log message is written, the write system calls are issued. +After all requests are issued, the application calls +.IR txn_commit . +When +.I txn_commit +returns, the caller is guaranteed that all necessary log writes have +been written to disk. +.PP +At any time, the application may call +.IR txn_abort , +which will result in the appropriate calls to the +.I recover +routine to restore the ``database'' to a consistent pre-transaction +state. +(The recover routine must be able to either reapply or undo the update +depending on the context, for each different type of log record.) +.PP +If the application should crash, the recovery process uses the +.I db_log +interface to read the log and call the +.I recover +routine to restore the database to a consistent state. +.PP +The +.I txn_prepare +function provides the core functionality to implement distributed +transactions, +but it does not actually manage the notification of distributed +transaction managers. +The caller is responsible for issuing +.I txn_prepare +calls to all sites participating in the transaction. +If all responses are positive, the caller can issue a +.IR txn_commit . +If any of the responses are negative, the caller should issue a +.IR txn_abort . +In general, the +.I txn_prepare +call requires that the transaction log be flushed to disk. +.PP +The structure of the transaction support allows application designers +to trade off performance and protection. +Since DB manages many structures in shared memory, +its information is subject to corruption by applications when the library +is linked directly with the application. +For this reason, DB is designed to allow compilation into a separate +server process that may be accessed via a socket interface. +In this way DB's data structures are protected from application code, +but communication overhead is increased. +When applications are trusted, DB may be compiled directly into the +application for increased performance. +.SH ERRORS +The +.I txn_create +function may fail and set +.I errno +for any of the errors specified for the library functions +.IR open (2), +.IR write (2), +.IR malloc (3), +.IR lock_create (3), +and +.IR log_create (3). +.PP +The +.I txn_open +function may fail and set +.I errno +to any of the errors specified for the library functions +.IR open (2), +.IR write (2), +.IR malloc (3), +.IR lock_open (3), +and +.IR log_open (3). +.PP +The +.I txn_begin +function may fail and set +.I errno +to ENOSPC indicating that the maximum number of concurrent +transactions has been reached. +.PP +The +.I txn_commit +function may fail and set +.I errno +to EINVAL indicating that the transaction was aborted. +.PP +The +.I txn_close +function may fail and set +.I errno +to any of the errors specified for the library functions +.IR close (2), +.IR read (2), +.IR write (2), +.IR free (3), +.IR fsync (2), +.IR lock_close (3) +or +.IR log_close (3). +.PP +The +.I txn_unlink +function may fail and set +.I errno +to any of the errors specified for the library functions +.IR unlink (2), +.IR lock_unlink (3), +and +.IR log_unlink (3), +or the following: +.TP 5 +[EBUSY] +The transaction region was in use and the force flag was not set. +.SH "SEE ALSO" +.IR db_btree (3), +.IR db_hash (3), +.IR db_lock (3), +.IR db_log (3), +.IR db_mpool (3), +.IR db_open (3), +.IR db_recno (3) +.sp +.IR "LIBTP: Portable, Modular Transactions for UNIX" , +Margo Seltzer, Michael Olson, USENIX proceedings, Winter 1992. +.SH BUGS +The +.I maxtxns +parameter is a kluge, and should be deleted in favor of dynamically +expanding the transaction region. diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/spell.ok b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/spell.ok new file mode 100644 index 00000000..794b00bf --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/man/spell.ok @@ -0,0 +1,170 @@ +Ake +Antonin +BTREE +BTREEINFO +Bsize +CALLBACK +Comput +D.E +DB +DB's +DBINFO +DBT +DBTYPE +Db +EACCES +EBUSY +EFTYPE +EINVAL +ENOENT +ENOSPC +ERL +EXCL +EXLOCK +FIXEDLEN +Ffactor +Guttman +HASHINFO +Heidi +IAFTER +IBEFORE +Kalash +Knuth +LIBTP +LOGINFO +LRU +LSN +LSN's +MPOOL +MPOOL's +MPOOLFILE +MPOOLFILE's +Maxlocks +Mpool +NG +NOKEY +NOOVERWRITE +NOPIN +NOTHELD +Nadene +Nelem +Nelems +OBJ +Pgaddr +RDONLY +RDWR +RECNO +RECNOINFO +RECNOSYNC +REQ +SETCURSOR +SHLOCK +Stettner +Stonebraker +Surv +TMPDIR +TRUNC +TXN +TXNMGR +Txn +UCB +UNDOREDO +USENIX +Unterauer +Vol +WAL +WRONLY +XACT +YYYY.MM.DD.HH.SS +al +bfname +bsize +btree +btrees +bval +cachesize +callback +const +db +db.h +dbinfo +dbopen +del +elistp +endian +enum +errbuf +errfile +errno +errpfx +fd +ffactor +getv +ing +int +int32 +int8 +isundo +kluge +lastlsn +lg +lock.h +lockinfo +lockop +lockp +log.YYYY.MM.DD.HH.MM.SS +logfiles +loginfo +logp +lreq +lsn +lsn1 +lsn2 +lt +maxcache +maxkeypage +maxlocks +maxtxns +meta +minkeypage +mmap +mpf +mpool +mpool.h +mpoolinfo +munmap +nacquire +nelem +nelems +nmodes +noone +nrelease +obj +op +openinfo +pathname +pgaddr +pgcookie +pgin +pgno +pgnoaddr +pgout +pid +pp +psize +queue.h +reclen +recno +sx +thang +timespec +tmp +trunc +txn +txnid +txninfo +txnp +typedef +typedef'd +vec +writeable diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/Makefile.in b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/Makefile.in new file mode 100644 index 00000000..cacff78d --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/Makefile.in @@ -0,0 +1,12 @@ +mydir=plugins$(S)kdb$(S)db2$(S)libdb2$(S)mpool +BUILDTOP=$(REL)..$(S)..$(S)..$(S)..$(S).. +STLIBOBJS=mpool.o + +LOCALINCLUDES= -I. -I$(srcdir)/../include -I../include -I$(srcdir)/../db + +all-unix: all-libobjs +clean-unix:: clean-libobjs +@libobj_frag@ + +SRCS= $(STLIBOBJS:.o=.c) + diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/Makefile.inc b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/Makefile.inc new file mode 100644 index 00000000..93210c89 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/Makefile.inc @@ -0,0 +1,5 @@ +# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93 + +.PATH: ${.CURDIR}/db/mpool + +SRCS+= mpool.c diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/README b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/README new file mode 100644 index 00000000..0f01fbcd --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/README @@ -0,0 +1,7 @@ +# @(#)README 8.1 (Berkeley) 6/4/93 + +These are the current memory pool routines. +They aren't ready for prime time, yet, and +the interface is expected to change. + +--keith diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/deps b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/deps new file mode 100644 index 00000000..86afee67 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/deps @@ -0,0 +1,6 @@ +# +# Generated makefile dependencies follow. +# +mpool.so mpool.po $(OUTPRE)mpool.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(DB_DEPS) $(srcdir)/../include/config.h $(srcdir)/../include/db-int.h \ + $(srcdir)/../include/db-queue.h mpool.c mpool.h diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/mpool.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/mpool.c new file mode 100644 index 00000000..0fcfd4ac --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/mpool.c @@ -0,0 +1,527 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)mpool.c 8.7 (Berkeley) 11/2/95"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "db-int.h" +#include "mpool.h" + +static BKT *mpool_bkt __P((MPOOL *)); +static BKT *mpool_look __P((MPOOL *, db_pgno_t)); +static int mpool_write __P((MPOOL *, BKT *)); + +/* + * mpool_open -- + * Initialize a memory pool. + */ +MPOOL * +mpool_open(key, fd, pagesize, maxcache) + void *key; + int fd; + db_pgno_t pagesize, maxcache; +{ + struct stat sb; + MPOOL *mp; + int entry; + + /* + * Get information about the file. + * + * XXX + * We don't currently handle pipes, although we should. + */ + if (fstat(fd, &sb)) + return (NULL); + if (!S_ISREG(sb.st_mode)) { + errno = ESPIPE; + return (NULL); + } + + /* Allocate and initialize the MPOOL cookie. */ + if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL) + return (NULL); + TAILQ_INIT(&mp->lqh); + for (entry = 0; entry < HASHSIZE; ++entry) + TAILQ_INIT(&mp->hqh[entry]); + mp->maxcache = maxcache; + mp->npages = sb.st_size / pagesize; + mp->pagesize = pagesize; + mp->fd = fd; + return (mp); +} + +/* + * mpool_filter -- + * Initialize input/output filters. + */ +void +mpool_filter(mp, pgin, pgout, pgcookie) + MPOOL *mp; + void (*pgin) __P((void *, db_pgno_t, void *)); + void (*pgout) __P((void *, db_pgno_t, void *)); + void *pgcookie; +{ + mp->pgin = pgin; + mp->pgout = pgout; + mp->pgcookie = pgcookie; +} + +/* + * mpool_new -- + * Get a new page of memory. + */ +void * +mpool_new(mp, pgnoaddr, flags) + MPOOL *mp; + db_pgno_t *pgnoaddr; + u_int flags; +{ + struct _hqh *head; + BKT *bp; + + if (mp->npages == MAX_PAGE_NUMBER) { + (void)fprintf(stderr, "mpool_new: page allocation overflow.\n"); + abort(); + } +#ifdef STATISTICS + ++mp->pagenew; +#endif + /* + * Get a BKT from the cache. Assign a new page number, attach + * it to the head of the hash chain, the tail of the lru chain, + * and return. + */ + if ((bp = mpool_bkt(mp)) == NULL) + return (NULL); + if (flags == MPOOL_PAGE_REQUEST) { + mp->npages++; + bp->pgno = *pgnoaddr; + } else + bp->pgno = *pgnoaddr = mp->npages++; + + bp->flags = MPOOL_PINNED | MPOOL_INUSE; + + head = &mp->hqh[HASHKEY(bp->pgno)]; + TAILQ_INSERT_HEAD(head, bp, hq); + TAILQ_INSERT_TAIL(&mp->lqh, bp, q); + return (bp->page); +} + +int +mpool_delete(mp, page) + MPOOL *mp; + void *page; +{ + struct _hqh *head; + BKT *bp; + + bp = (void *)((char *)page - sizeof(BKT)); + +#ifdef DEBUG + if (!(bp->flags & MPOOL_PINNED)) { + (void)fprintf(stderr, + "mpool_delete: page %d not pinned\n", bp->pgno); + abort(); + } +#endif + + /* Remove from the hash and lru queues. */ + head = &mp->hqh[HASHKEY(bp->pgno)]; + TAILQ_REMOVE(head, bp, hq); + TAILQ_REMOVE(&mp->lqh, bp, q); + + free(bp); + return (RET_SUCCESS); +} + +/* + * mpool_get + * Get a page. + */ +void * +mpool_get(mp, pgno, flags) + MPOOL *mp; + db_pgno_t pgno; + u_int flags; /* XXX not used? */ +{ + struct _hqh *head; + BKT *bp; + off_t off; + int nr; + +#ifdef STATISTICS + ++mp->pageget; +#endif + + /* Check for a page that is cached. */ + if ((bp = mpool_look(mp, pgno)) != NULL) { +#ifdef DEBUG + if (!(flags & MPOOL_IGNOREPIN) && bp->flags & MPOOL_PINNED) { + (void)fprintf(stderr, + "mpool_get: page %d already pinned\n", bp->pgno); + abort(); + } +#endif + /* + * Move the page to the head of the hash chain and the tail + * of the lru chain. + */ + head = &mp->hqh[HASHKEY(bp->pgno)]; + TAILQ_REMOVE(head, bp, hq); + TAILQ_INSERT_HEAD(head, bp, hq); + TAILQ_REMOVE(&mp->lqh, bp, q); + TAILQ_INSERT_TAIL(&mp->lqh, bp, q); + + /* Return a pinned page. */ + if (!(flags & MPOOL_IGNOREPIN)) + bp->flags |= MPOOL_PINNED; + return (bp->page); + } + + /* Get a page from the cache. */ + if ((bp = mpool_bkt(mp)) == NULL) + return (NULL); + + /* Read in the contents. */ +#ifdef STATISTICS + ++mp->pageread; +#endif + off = mp->pagesize * pgno; + if (off / mp->pagesize != pgno) { + /* Run past the end of the file, or at least the part we + can address without large-file support? */ + errno = E2BIG; + return NULL; + } + if (lseek(mp->fd, off, SEEK_SET) != off) + return (NULL); + + if ((nr = read(mp->fd, bp->page, mp->pagesize)) != + (ssize_t)mp->pagesize) { + if (nr > 0) { + /* A partial read is definitely bad. */ + errno = EINVAL; + return (NULL); + } else { + /* + * A zero-length reads, means you need to create a + * new page. + */ + memset(bp->page, 0, mp->pagesize); + } + } + + /* Set the page number, pin the page. */ + bp->pgno = pgno; + if (!(flags & MPOOL_IGNOREPIN)) + bp->flags = MPOOL_PINNED; + bp->flags |= MPOOL_INUSE; + + /* + * Add the page to the head of the hash chain and the tail + * of the lru chain. + */ + head = &mp->hqh[HASHKEY(bp->pgno)]; + TAILQ_INSERT_HEAD(head, bp, hq); + TAILQ_INSERT_TAIL(&mp->lqh, bp, q); + + /* Run through the user's filter. */ + if (mp->pgin != NULL) + (mp->pgin)(mp->pgcookie, bp->pgno, bp->page); + + return (bp->page); +} + +/* + * mpool_put + * Return a page. + */ +int +mpool_put(mp, page, flags) + MPOOL *mp; + void *page; + u_int flags; +{ + BKT *bp; + +#ifdef STATISTICS + ++mp->pageput; +#endif + bp = (void *)((char *)page - sizeof(BKT)); +#ifdef DEBUG + if (!(bp->flags & MPOOL_PINNED)) { + (void)fprintf(stderr, + "mpool_put: page %d not pinned\n", bp->pgno); + abort(); + } +#endif + bp->flags &= ~MPOOL_PINNED; + if (flags & MPOOL_DIRTY) + bp->flags |= flags & MPOOL_DIRTY; + return (RET_SUCCESS); +} + +/* + * mpool_close + * Close the buffer pool. + */ +int +mpool_close(mp) + MPOOL *mp; +{ + BKT *bp; + + /* Free up any space allocated to the lru pages. */ + while ((bp = mp->lqh.tqh_first) != NULL) { + TAILQ_REMOVE(&mp->lqh, mp->lqh.tqh_first, q); + free(bp); + } + + /* Free the MPOOL cookie. */ + free(mp); + return (RET_SUCCESS); +} + +/* + * mpool_sync + * Sync the pool to disk. + */ +int +mpool_sync(mp) + MPOOL *mp; +{ + BKT *bp; + + /* Walk the lru chain, flushing any dirty pages to disk. */ + for (bp = mp->lqh.tqh_first; bp != NULL; bp = bp->q.tqe_next) + if (bp->flags & MPOOL_DIRTY && + mpool_write(mp, bp) == RET_ERROR) + return (RET_ERROR); + + /* Sync the file descriptor. */ + return (fsync(mp->fd) ? RET_ERROR : RET_SUCCESS); +} + +/* + * mpool_bkt + * Get a page from the cache (or create one). + */ +static BKT * +mpool_bkt(mp) + MPOOL *mp; +{ + struct _hqh *head; + BKT *bp; + + /* If under the max cached, always create a new page. */ + if (mp->curcache < mp->maxcache) + goto new; + + /* + * If the cache is max'd out, walk the lru list for a buffer we + * can flush. If we find one, write it (if necessary) and take it + * off any lists. If we don't find anything we grow the cache anyway. + * The cache never shrinks. + */ + for (bp = mp->lqh.tqh_first; bp != NULL; bp = bp->q.tqe_next) + if (!(bp->flags & MPOOL_PINNED)) { + /* Flush if dirty. */ + if (bp->flags & MPOOL_DIRTY && + mpool_write(mp, bp) == RET_ERROR) + return (NULL); +#ifdef STATISTICS + ++mp->pageflush; +#endif + /* Remove from the hash and lru queues. */ + head = &mp->hqh[HASHKEY(bp->pgno)]; + TAILQ_REMOVE(head, bp, hq); + TAILQ_REMOVE(&mp->lqh, bp, q); +#if defined(DEBUG) && !defined(DEBUG_IDX0SPLIT) + { void *spage; + spage = bp->page; + memset(bp, 0xff, sizeof(BKT) + mp->pagesize); + bp->page = spage; + } +#endif + bp->flags = 0; + return (bp); + } + +new: if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL) + return (NULL); +#ifdef STATISTICS + ++mp->pagealloc; +#endif +#if defined(DEBUG) || defined(PURIFY) || 1 + memset(bp, 0xff, sizeof(BKT) + mp->pagesize); +#endif + bp->page = (char *)bp + sizeof(BKT); + bp->flags = 0; + ++mp->curcache; + return (bp); +} + +/* + * mpool_write + * Write a page to disk. + */ +static int +mpool_write(mp, bp) + MPOOL *mp; + BKT *bp; +{ + off_t off; + +#ifdef STATISTICS + ++mp->pagewrite; +#endif + + /* Run through the user's filter. */ + if (mp->pgout) + (mp->pgout)(mp->pgcookie, bp->pgno, bp->page); + + off = mp->pagesize * bp->pgno; + if (off / mp->pagesize != bp->pgno) { + /* Run past the end of the file, or at least the part we + can address without large-file support? */ + errno = E2BIG; + return RET_ERROR; + } + if (lseek(mp->fd, off, SEEK_SET) != off) + return (RET_ERROR); + if (write(mp->fd, bp->page, mp->pagesize) != + (ssize_t)mp->pagesize) + return (RET_ERROR); + + /* + * Re-run through the input filter since this page may soon be + * accessed via the cache, and whatever the user's output filter + * did may screw things up if we don't let the input filter + * restore the in-core copy. + */ + if (mp->pgin) + (mp->pgin)(mp->pgcookie, bp->pgno, bp->page); + bp->flags &= ~MPOOL_DIRTY; + return (RET_SUCCESS); +} + +/* + * mpool_look + * Lookup a page in the cache. + */ +static BKT * +mpool_look(mp, pgno) + MPOOL *mp; + db_pgno_t pgno; +{ + struct _hqh *head; + BKT *bp; + + head = &mp->hqh[HASHKEY(pgno)]; + for (bp = head->tqh_first; bp != NULL; bp = bp->hq.tqe_next) + if ((bp->pgno == pgno) && (bp->flags & MPOOL_INUSE)) { +#ifdef STATISTICS + ++mp->cachehit; +#endif + return (bp); + } +#ifdef STATISTICS + ++mp->cachemiss; +#endif + return (NULL); +} + +#ifdef STATISTICS +/* + * mpool_stat + * Print out cache statistics. + */ +void +mpool_stat(mp) + MPOOL *mp; +{ + BKT *bp; + int cnt; + char *sep; + + (void)fprintf(stderr, "%lu pages in the file\n", mp->npages); + (void)fprintf(stderr, + "page size %lu, cacheing %lu pages of %lu page max cache\n", + mp->pagesize, mp->curcache, mp->maxcache); + (void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n", + mp->pageput, mp->pageget, mp->pagenew); + (void)fprintf(stderr, "%lu page allocs, %lu page flushes\n", + mp->pagealloc, mp->pageflush); + if (mp->cachehit + mp->cachemiss) + (void)fprintf(stderr, + "%.0f%% cache hit rate (%lu hits, %lu misses)\n", + ((double)mp->cachehit / (mp->cachehit + mp->cachemiss)) + * 100, mp->cachehit, mp->cachemiss); + (void)fprintf(stderr, "%lu page reads, %lu page writes\n", + mp->pageread, mp->pagewrite); + + sep = ""; + cnt = 0; + for (bp = mp->lqh.tqh_first; bp != NULL; bp = bp->q.tqe_next) { + (void)fprintf(stderr, "%s%d", sep, bp->pgno); + if (bp->flags & MPOOL_DIRTY) + (void)fprintf(stderr, "d"); + if (bp->flags & MPOOL_PINNED) + (void)fprintf(stderr, "P"); + if (++cnt == 10) { + sep = "\n"; + cnt = 0; + } else + sep = ", "; + + } + (void)fprintf(stderr, "\n"); +} +#else +void +mpool_stat(mp) + MPOOL *mp; +{ +} +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/mpool.h b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/mpool.h new file mode 100644 index 00000000..7957df69 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/mpool/mpool.h @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)mpool.h 8.4 (Berkeley) 11/2/95 + */ + +#include "db-queue.h" + +/* + * The memory pool scheme is a simple one. Each in-memory page is referenced + * by a bucket which is threaded in up to two of three ways. All active pages + * are threaded on a hash chain (hashed by page number) and an lru chain. + * Inactive pages are threaded on a free chain. Each reference to a memory + * pool is handed an opaque MPOOL cookie which stores all of this information. + */ +#define HASHSIZE 128 +#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE) + +/* The BKT structures are the elements of the queues. */ +typedef struct _bkt { + TAILQ_ENTRY(_bkt) hq; /* hash queue */ + TAILQ_ENTRY(_bkt) q; /* lru queue */ + void *page; /* page */ + db_pgno_t pgno; /* page number */ + +#define MPOOL_DIRTY 0x01 /* page needs to be written */ +#define MPOOL_PINNED 0x02 /* page is pinned into memory */ +#define MPOOL_INUSE 0x04 /* page address is valid */ + u_int8_t flags; /* flags */ +} BKT; + +typedef struct MPOOL { + TAILQ_HEAD(_lqh, _bkt) lqh; /* lru queue head */ + /* hash queue array */ + TAILQ_HEAD(_hqh, _bkt) hqh[HASHSIZE]; + db_pgno_t curcache; /* current number of cached pages */ + db_pgno_t maxcache; /* max number of cached pages */ + db_pgno_t npages; /* number of pages in the file */ + u_long pagesize; /* file page size */ + int fd; /* file descriptor */ + /* page in conversion routine */ + void (*pgin) __P((void *, db_pgno_t, void *)); + /* page out conversion routine */ + void (*pgout) __P((void *, db_pgno_t, void *)); + void *pgcookie; /* cookie for page in/out routines */ +#ifdef STATISTICS + u_long cachehit; + u_long cachemiss; + u_long pagealloc; + u_long pageflush; + u_long pageget; + u_long pagenew; + u_long pageput; + u_long pageread; + u_long pagewrite; +#endif +} MPOOL; + +#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */ +#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a + specific page number. */ +#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next + page number. */ + +#define mpool_open kdb2_mpool_open +#define mpool_filter kdb2_mpool_filter +#define mpool_new kdb2_mpool_new +#define mpool_get kdb2_mpool_get +#define mpool_delete kdb2_mpool_delete +#define mpool_put kdb2_mpool_put +#define mpool_sync kdb2_mpool_sync +#define mpool_close kdb2_mpool_close +#define mpool_stat kdb2_mpool_stat + +__BEGIN_DECLS +MPOOL *mpool_open __P((void *, int, db_pgno_t, db_pgno_t)); +void mpool_filter __P((MPOOL *, void (*)(void *, db_pgno_t, void *), + void (*)(void *, db_pgno_t, void *), void *)); +void *mpool_new __P((MPOOL *, db_pgno_t *, u_int)); +void *mpool_get __P((MPOOL *, db_pgno_t, u_int)); +int mpool_delete __P((MPOOL *, void *)); +int mpool_put __P((MPOOL *, void *, u_int)); +int mpool_sync __P((MPOOL *)); +int mpool_close __P((MPOOL *)); + +void mpool_stat __P((MPOOL *)); + +__END_DECLS diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/Makefile.in b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/Makefile.in new file mode 100644 index 00000000..2a9db95f --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/Makefile.in @@ -0,0 +1,14 @@ +mydir=plugins$(S)kdb$(S)db2$(S)libdb2$(S)recno +BUILDTOP=$(REL)..$(S)..$(S)..$(S)..$(S).. +STLIBOBJS= rec_close.o rec_delete.o rec_get.o rec_open.o rec_put.o \ + rec_search.o rec_seq.o rec_utils.o + +LOCALINCLUDES= -I. -I$(srcdir)/../include -I../include -I$(srcdir)/../mpool \ + -I$(srcdir)/../db + +all-unix: all-libobjs +clean-unix:: clean-libobjs +@libobj_frag@ + +SRCS= $(STLIBOBJS:.o=.c) + diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/Makefile.inc b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/Makefile.inc new file mode 100644 index 00000000..e49e2255 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/Makefile.inc @@ -0,0 +1,6 @@ +# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93 + +.PATH: ${.CURDIR}/db/recno + +SRCS+= rec_close.c rec_delete.c rec_get.c rec_open.c rec_put.c rec_search.c \ + rec_seq.c rec_utils.c diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/deps b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/deps new file mode 100644 index 00000000..3756fb77 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/deps @@ -0,0 +1,43 @@ +# +# Generated makefile dependencies follow. +# +rec_close.so rec_close.po $(OUTPRE)rec_close.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(DB_DEPS) $(srcdir)/../btree/btree.h \ + $(srcdir)/../btree/extern.h $(srcdir)/../include/config.h \ + $(srcdir)/../include/db-int.h $(srcdir)/../include/db-queue.h \ + $(srcdir)/../mpool/mpool.h extern.h rec_close.c recno.h +rec_delete.so rec_delete.po $(OUTPRE)rec_delete.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(DB_DEPS) $(srcdir)/../btree/btree.h \ + $(srcdir)/../btree/extern.h $(srcdir)/../include/config.h \ + $(srcdir)/../include/db-int.h $(srcdir)/../include/db-queue.h \ + $(srcdir)/../mpool/mpool.h extern.h rec_delete.c recno.h +rec_get.so rec_get.po $(OUTPRE)rec_get.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(DB_DEPS) $(srcdir)/../btree/btree.h $(srcdir)/../btree/extern.h \ + $(srcdir)/../include/config.h $(srcdir)/../include/db-int.h \ + $(srcdir)/../include/db-queue.h $(srcdir)/../mpool/mpool.h \ + extern.h rec_get.c recno.h +rec_open.so rec_open.po $(OUTPRE)rec_open.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(DB_DEPS) $(srcdir)/../btree/btree.h \ + $(srcdir)/../btree/extern.h $(srcdir)/../include/config.h \ + $(srcdir)/../include/db-int.h $(srcdir)/../include/db-queue.h \ + $(srcdir)/../mpool/mpool.h extern.h rec_open.c recno.h +rec_put.so rec_put.po $(OUTPRE)rec_put.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(DB_DEPS) $(srcdir)/../btree/btree.h $(srcdir)/../btree/extern.h \ + $(srcdir)/../include/config.h $(srcdir)/../include/db-int.h \ + $(srcdir)/../include/db-queue.h $(srcdir)/../mpool/mpool.h \ + extern.h rec_put.c recno.h +rec_search.so rec_search.po $(OUTPRE)rec_search.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(DB_DEPS) $(srcdir)/../btree/btree.h \ + $(srcdir)/../btree/extern.h $(srcdir)/../include/config.h \ + $(srcdir)/../include/db-int.h $(srcdir)/../include/db-queue.h \ + $(srcdir)/../mpool/mpool.h extern.h rec_search.c recno.h +rec_seq.so rec_seq.po $(OUTPRE)rec_seq.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(DB_DEPS) $(srcdir)/../btree/btree.h $(srcdir)/../btree/extern.h \ + $(srcdir)/../include/config.h $(srcdir)/../include/db-int.h \ + $(srcdir)/../include/db-queue.h $(srcdir)/../mpool/mpool.h \ + extern.h rec_seq.c recno.h +rec_utils.so rec_utils.po $(OUTPRE)rec_utils.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(DB_DEPS) $(srcdir)/../btree/btree.h \ + $(srcdir)/../btree/extern.h $(srcdir)/../include/config.h \ + $(srcdir)/../include/db-int.h $(srcdir)/../include/db-queue.h \ + $(srcdir)/../mpool/mpool.h extern.h rec_utils.c recno.h diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/extern.h b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/extern.h new file mode 100644 index 00000000..98e382c3 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/extern.h @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)extern.h 8.3 (Berkeley) 6/4/94 + */ + +#include "../btree/extern.h" + +#define __rec_close __kdb2_rec_close +#define __rec_delete __kdb2_rec_delete +#define __rec_dleaf __kdb2_rec_dleaf +#define __rec_fd __kdb2_rec_fd +#define __rec_fmap __kdb2_rec_fmap +#define __rec_fout __kdb2_rec_fout +#define __rec_fpipe __kdb2_rec_fpipe +#define __rec_get __kdb2_rec_get +#define __rec_iput __kdb2_rec_iput +#define __rec_put __kdb2_rec_put +#define __rec_ret __kdb2_rec_ret +#define __rec_search __kdb2_rec_search +#define __rec_seq __kdb2_rec_seq +#define __rec_sync __kdb2_rec_sync +#define __rec_vmap __kdb2_rec_vmap +#define __rec_vout __kdb2_rec_vout +#define __rec_vpipe __kdb2_rec_vpipe + +int __rec_close __P((DB *)); +int __rec_delete __P((const DB *, const DBT *, u_int)); +int __rec_dleaf __P((BTREE *, PAGE *, u_int32_t)); +int __rec_fd __P((const DB *)); +int __rec_fmap __P((BTREE *, recno_t)); +int __rec_fout __P((BTREE *)); +int __rec_fpipe __P((BTREE *, recno_t)); +int __rec_get __P((const DB *, const DBT *, DBT *, u_int)); +int __rec_iput __P((BTREE *, recno_t, const DBT *, u_int)); +int __rec_put __P((const DB *dbp, DBT *, const DBT *, u_int)); +int __rec_ret __P((BTREE *, EPG *, recno_t, DBT *, DBT *)); +EPG *__rec_search __P((BTREE *, recno_t, enum SRCHOP)); +int __rec_seq __P((const DB *, DBT *, DBT *, u_int)); +int __rec_sync __P((const DB *, u_int)); +int __rec_vmap __P((BTREE *, recno_t)); +int __rec_vout __P((BTREE *)); +int __rec_vpipe __P((BTREE *, recno_t)); diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_close.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_close.c new file mode 100644 index 00000000..4ef4dd1b --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_close.c @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_close.c 8.9 (Berkeley) 11/18/94"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#ifdef RECNO_USE_MMAP +#include +#endif + +#include +#include +#include +#include + +#include "db-int.h" +#include "recno.h" + +/* + * __REC_CLOSE -- Close a recno tree. + * + * Parameters: + * dbp: pointer to access method + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__rec_close(dbp) + DB *dbp; +{ + BTREE *t; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + if (__rec_sync(dbp, 0) == RET_ERROR) + return (RET_ERROR); + + /* Committed to closing. */ + status = RET_SUCCESS; +#ifdef RECNO_USE_MMAP + if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize)) + status = RET_ERROR; +#endif + + if (!F_ISSET(t, R_INMEM)) { + if (F_ISSET(t, R_CLOSEFP)) { + if (fclose(t->bt_rfp)) + status = RET_ERROR; + } else + if (close(t->bt_rfd)) + status = RET_ERROR; + } + + if (__bt_close(dbp) == RET_ERROR) + status = RET_ERROR; + + return (status); +} + +/* + * __REC_SYNC -- sync the recno tree to disk. + * + * Parameters: + * dbp: pointer to access method + * + * Returns: + * RET_SUCCESS, RET_ERROR. + */ +int +__rec_sync(dbp, flags) + const DB *dbp; + u_int flags; +{ + struct iovec iov[2]; + BTREE *t; + DBT data, key; + off_t off; + recno_t scursor, trec; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + if (flags == R_RECNOSYNC) + return (__bt_sync(dbp, 0)); + + if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED)) + return (RET_SUCCESS); + + /* Read any remaining records into the tree. */ + if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) + return (RET_ERROR); + + /* Rewind the file descriptor. */ + if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0) + return (RET_ERROR); + + /* Save the cursor. */ + scursor = t->bt_cursor.rcursor; + + key.size = sizeof(recno_t); + key.data = &trec; + + if (F_ISSET(t, R_FIXLEN)) { + /* + * We assume that fixed length records are all fixed length. + * Any that aren't are either EINVAL'd or corrected by the + * record put code. + */ + status = (dbp->seq)(dbp, &key, &data, R_FIRST); + while (status == RET_SUCCESS) { + if (write(t->bt_rfd, data.data, data.size) != + (ssize_t)data.size) + return (RET_ERROR); + status = (dbp->seq)(dbp, &key, &data, R_NEXT); + } + } else { + iov[1].iov_base = &t->bt_bval; + iov[1].iov_len = 1; + + status = (dbp->seq)(dbp, &key, &data, R_FIRST); + while (status == RET_SUCCESS) { + iov[0].iov_base = data.data; + iov[0].iov_len = data.size; + if (writev(t->bt_rfd, iov, 2) != (ssize_t)data.size + 1) + return (RET_ERROR); + status = (dbp->seq)(dbp, &key, &data, R_NEXT); + } + } + + /* Restore the cursor. */ + t->bt_cursor.rcursor = scursor; + + if (status == RET_ERROR) + return (RET_ERROR); + if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1) + return (RET_ERROR); + if (ftruncate(t->bt_rfd, off)) + return (RET_ERROR); + F_CLR(t, R_MODIFIED); + return (RET_SUCCESS); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_delete.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_delete.c new file mode 100644 index 00000000..b69c9ad7 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_delete.c @@ -0,0 +1,197 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_delete.c 8.7 (Berkeley) 7/14/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include + +#include "db-int.h" +#include "recno.h" + +static int rec_rdelete __P((BTREE *, recno_t)); + +/* + * __REC_DELETE -- Delete the item(s) referenced by a key. + * + * Parameters: + * dbp: pointer to access method + * key: key to delete + * flags: R_CURSOR if deleting what the cursor references + * + * Returns: + * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. + */ +int +__rec_delete(dbp, key, flags) + const DB *dbp; + const DBT *key; + u_int flags; +{ + BTREE *t; + recno_t nrec; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + switch(flags) { + case 0: + if ((nrec = *(recno_t *)key->data) == 0) + goto einval; + if (nrec > t->bt_nrecs) + return (RET_SPECIAL); + --nrec; + status = rec_rdelete(t, nrec); + break; + case R_CURSOR: + if (!F_ISSET(&t->bt_cursor, CURS_INIT)) + goto einval; + if (t->bt_nrecs == 0) + return (RET_SPECIAL); + status = rec_rdelete(t, t->bt_cursor.rcursor - 1); + if (status == RET_SUCCESS) + --t->bt_cursor.rcursor; + break; + default: +einval: errno = EINVAL; + return (RET_ERROR); + } + + if (status == RET_SUCCESS) + F_SET(t, B_MODIFIED | R_MODIFIED); + return (status); +} + +/* + * REC_RDELETE -- Delete the data matching the specified key. + * + * Parameters: + * tree: tree + * nrec: record to delete + * + * Returns: + * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. + */ +static int +rec_rdelete(t, nrec) + BTREE *t; + recno_t nrec; +{ + EPG *e; + PAGE *h; + int status; + + /* Find the record; __rec_search pins the page. */ + if ((e = __rec_search(t, nrec, SDELETE)) == NULL) + return (RET_ERROR); + + /* Delete the record. */ + h = e->page; + status = __rec_dleaf(t, h, e->index); + if (status != RET_SUCCESS) { + mpool_put(t->bt_mp, h, 0); + return (status); + } + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + return (RET_SUCCESS); +} + +/* + * __REC_DLEAF -- Delete a single record from a recno leaf page. + * + * Parameters: + * t: tree + * idx: index on current page to delete + * + * Returns: + * RET_SUCCESS, RET_ERROR. + */ +int +__rec_dleaf(t, h, idx) + BTREE *t; + PAGE *h; + u_int32_t idx; +{ + RLEAF *rl; + indx_t *ip, cnt, offset; + u_int32_t nbytes; + char *from; + void *to; + + /* + * Delete a record from a recno leaf page. Internal records are never + * deleted from internal pages, regardless of the records that caused + * them to be added being deleted. Pages made empty by deletion are + * not reclaimed. They are, however, made available for reuse. + * + * Pack the remaining entries at the end of the page, shift the indices + * down, overwriting the deleted record and its index. If the record + * uses overflow pages, make them available for reuse. + */ + to = rl = GETRLEAF(h, idx); + if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR) + return (RET_ERROR); + nbytes = NRLEAF(rl); + + /* + * Compress the key/data pairs. Compress and adjust the [BR]LEAF + * offsets. Reset the headers. + */ + from = (char *)h + h->upper; + memmove(from + nbytes, from, (char *)to - from); + h->upper += nbytes; + + offset = h->linp[idx]; + for (cnt = &h->linp[idx] - (ip = &h->linp[0]); cnt--; ++ip) + if (ip[0] < offset) + ip[0] += nbytes; + for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip) + ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1]; + h->lower -= sizeof(indx_t); + --t->bt_nrecs; + return (RET_SUCCESS); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_get.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_get.c new file mode 100644 index 00000000..230b2d4f --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_get.c @@ -0,0 +1,311 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_get.c 8.9 (Berkeley) 8/18/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "db-int.h" +#include "recno.h" + +/* + * __REC_GET -- Get a record from the btree. + * + * Parameters: + * dbp: pointer to access method + * key: key to find + * data: data to return + * flag: currently unused + * + * Returns: + * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found. + */ +int +__rec_get(dbp, key, data, flags) + const DB *dbp; + const DBT *key; + DBT *data; + u_int flags; +{ + BTREE *t; + EPG *e; + recno_t nrec; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + /* Get currently doesn't take any flags, and keys of 0 are illegal. */ + if (flags || (nrec = *(recno_t *)key->data) == 0) { + errno = EINVAL; + return (RET_ERROR); + } + + /* + * If we haven't seen this record yet, try to find it in the + * original file. + */ + if (nrec > t->bt_nrecs) { + if (F_ISSET(t, R_EOF | R_INMEM)) + return (RET_SPECIAL); + if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS) + return (status); + } + + --nrec; + if ((e = __rec_search(t, nrec, SEARCH)) == NULL) + return (RET_ERROR); + + status = __rec_ret(t, e, 0, NULL, data); + if (F_ISSET(t, B_DB_LOCK)) + mpool_put(t->bt_mp, e->page, 0); + else + t->bt_pinned = e->page; + return (status); +} + +/* + * __REC_FPIPE -- Get fixed length records from a pipe. + * + * Parameters: + * t: tree + * cnt: records to read + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__rec_fpipe(t, top) + BTREE *t; + recno_t top; +{ + DBT data; + recno_t nrec; + size_t len; + int ch; + u_char *p; + + if (t->bt_rdata.size < t->bt_reclen) { + t->bt_rdata.data = t->bt_rdata.data == NULL ? + malloc(t->bt_reclen) : + realloc(t->bt_rdata.data, t->bt_reclen); + if (t->bt_rdata.data == NULL) + return (RET_ERROR); + t->bt_rdata.size = t->bt_reclen; + } + data.data = t->bt_rdata.data; + data.size = t->bt_reclen; + + for (nrec = t->bt_nrecs; nrec < top;) { + len = t->bt_reclen; + for (p = t->bt_rdata.data;; *p++ = ch) + if ((ch = getc(t->bt_rfp)) == EOF || !--len) { + if (ch != EOF) + *p = ch; + if (len != 0) + memset(p, t->bt_bval, len); + if (__rec_iput(t, + nrec, &data, 0) != RET_SUCCESS) + return (RET_ERROR); + ++nrec; + break; + } + if (ch == EOF) + break; + } + if (nrec < top) { + F_SET(t, R_EOF); + return (RET_SPECIAL); + } + return (RET_SUCCESS); +} + +/* + * __REC_VPIPE -- Get variable length records from a pipe. + * + * Parameters: + * t: tree + * cnt: records to read + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__rec_vpipe(t, top) + BTREE *t; + recno_t top; +{ + DBT data; + recno_t nrec; + indx_t len; + size_t sz; + int bval, ch; + u_char *p; + + bval = t->bt_bval; + for (nrec = t->bt_nrecs; nrec < top; ++nrec) { + for (p = t->bt_rdata.data, + sz = t->bt_rdata.size;; *p++ = ch, --sz) { + if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) { + data.data = t->bt_rdata.data; + data.size = p - (u_char *)t->bt_rdata.data; + if (ch == EOF && data.size == 0) + break; + if (__rec_iput(t, nrec, &data, 0) + != RET_SUCCESS) + return (RET_ERROR); + break; + } + if (sz == 0) { + len = p - (u_char *)t->bt_rdata.data; + t->bt_rdata.size += (sz = 256); + t->bt_rdata.data = t->bt_rdata.data == NULL ? + malloc(t->bt_rdata.size) : + realloc(t->bt_rdata.data, t->bt_rdata.size); + if (t->bt_rdata.data == NULL) + return (RET_ERROR); + p = (u_char *)t->bt_rdata.data + len; + } + } + if (ch == EOF) + break; + } + if (nrec < top) { + F_SET(t, R_EOF); + return (RET_SPECIAL); + } + return (RET_SUCCESS); +} + +/* + * __REC_FMAP -- Get fixed length records from a file. + * + * Parameters: + * t: tree + * cnt: records to read + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__rec_fmap(t, top) + BTREE *t; + recno_t top; +{ + DBT data; + recno_t nrec; + u_char *sp, *ep, *p; + size_t len; + + if (t->bt_rdata.size < t->bt_reclen) { + t->bt_rdata.data = t->bt_rdata.data == NULL ? + malloc(t->bt_reclen) : + realloc(t->bt_rdata.data, t->bt_reclen); + if (t->bt_rdata.data == NULL) + return (RET_ERROR); + t->bt_rdata.size = t->bt_reclen; + } + data.data = t->bt_rdata.data; + data.size = t->bt_reclen; + + sp = (u_char *)t->bt_cmap; + ep = (u_char *)t->bt_emap; + for (nrec = t->bt_nrecs; nrec < top; ++nrec) { + if (sp >= ep) { + F_SET(t, R_EOF); + return (RET_SPECIAL); + } + len = t->bt_reclen; + for (p = t->bt_rdata.data; + sp < ep && len > 0; *p++ = *sp++, --len); + if (len != 0) + memset(p, t->bt_bval, len); + if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS) + return (RET_ERROR); + } + t->bt_cmap = (caddr_t)sp; + return (RET_SUCCESS); +} + +/* + * __REC_VMAP -- Get variable length records from a file. + * + * Parameters: + * t: tree + * cnt: records to read + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__rec_vmap(t, top) + BTREE *t; + recno_t top; +{ + DBT data; + u_char *sp, *ep; + recno_t nrec; + int bval; + + sp = (u_char *)t->bt_cmap; + ep = (u_char *)t->bt_emap; + bval = t->bt_bval; + + for (nrec = t->bt_nrecs; nrec < top; ++nrec) { + if (sp >= ep) { + F_SET(t, R_EOF); + return (RET_SPECIAL); + } + for (data.data = sp; sp < ep && *sp != bval; ++sp); + data.size = sp - (u_char *)data.data; + if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS) + return (RET_ERROR); + ++sp; + } + t->bt_cmap = (caddr_t)sp; + return (RET_SUCCESS); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_open.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_open.c new file mode 100644 index 00000000..d8b26e70 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_open.c @@ -0,0 +1,248 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_open.c 8.12 (Berkeley) 11/18/94"; +#endif /* LIBC_SCCS and not lint */ + +#include +#ifdef RECNO_USE_MMAP +#include +#endif +#include + +#include +#include +#include +#include +#include +#include + +#include "db-int.h" +#include "recno.h" + +DB * +__rec_open(fname, flags, mode, openinfo, dflags) + const char *fname; + int flags, mode, dflags; + const RECNOINFO *openinfo; +{ + BTREE *t; + BTREEINFO btopeninfo; + DB *dbp; + PAGE *h; + struct stat sb; + int rfd = -1, sverrno; + + /* Open the user's file -- if this fails, we're done. */ + if (fname != NULL && (rfd = open(fname, flags | O_BINARY, mode)) < 0) + return (NULL); + + if (fname != NULL && fcntl(rfd, F_SETFD, 1) == -1) { + close(rfd); + return NULL; + } + + /* Create a btree in memory (backed by disk). */ + dbp = NULL; + if (openinfo) { + if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT)) + goto einval; + btopeninfo.flags = 0; + btopeninfo.cachesize = openinfo->cachesize; + btopeninfo.maxkeypage = 0; + btopeninfo.minkeypage = 0; + btopeninfo.psize = openinfo->psize; + btopeninfo.compare = NULL; + btopeninfo.prefix = NULL; + btopeninfo.lorder = openinfo->lorder; + dbp = __bt_open(openinfo->bfname, + O_RDWR | O_BINARY, S_IRUSR | S_IWUSR, &btopeninfo, dflags); + } else + dbp = __bt_open(NULL, O_RDWR | O_BINARY, S_IRUSR | S_IWUSR, NULL, dflags); + if (dbp == NULL) + goto err; + + /* + * Some fields in the tree structure are recno specific. Fill them + * in and make the btree structure look like a recno structure. We + * don't change the bt_ovflsize value, it's close enough and slightly + * bigger. + */ + t = dbp->internal; + if (openinfo) { + if (openinfo->flags & R_FIXEDLEN) { + F_SET(t, R_FIXLEN); + t->bt_reclen = openinfo->reclen; + if (t->bt_reclen == 0) + goto einval; + } + t->bt_bval = openinfo->bval; + } else + t->bt_bval = '\n'; + + F_SET(t, R_RECNO); + if (fname == NULL) + F_SET(t, R_EOF | R_INMEM); + else + t->bt_rfd = rfd; + + if (fname != NULL) { + /* + * In 4.4BSD, stat(2) returns true for ISSOCK on pipes. + * Unfortunately, that's not portable, so we use lseek + * and check the errno values. + */ + errno = 0; + if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) { + switch (flags & O_ACCMODE) { + case O_RDONLY: + F_SET(t, R_RDONLY); + break; + default: + goto einval; + } +slow: if ((t->bt_rfp = fdopen(rfd, "rb")) == NULL) + goto err; + F_SET(t, R_CLOSEFP); + t->bt_irec = + F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe; + } else { + switch (flags & O_ACCMODE) { + case O_RDONLY: + F_SET(t, R_RDONLY); + break; + case O_RDWR: + break; + default: + goto einval; + } + + if (fstat(rfd, &sb)) + goto err; + /* + * Kluge -- we'd like to test to see if the file is too + * big to mmap. Since, we don't know what size or type + * off_t's or size_t's are, what the largest unsigned + * integral type is, or what random insanity the local + * C compiler will perpetrate, doing the comparison in + * a portable way is flatly impossible. Hope that mmap + * fails if the file is too large. + */ + if (sb.st_size == 0) + F_SET(t, R_EOF); + else { +#ifdef RECNO_USE_MMAP + /* + * XXX + * Mmap doesn't work correctly on many current + * systems. In particular, it can fail subtly, + * with cache coherency problems. Don't use it + * for now. + */ + t->bt_msize = sb.st_size; + if ((t->bt_smap = mmap(NULL, t->bt_msize, + PROT_READ, MAP_PRIVATE, rfd, + (off_t)0)) == (caddr_t)-1) + goto slow; + t->bt_cmap = t->bt_smap; + t->bt_emap = t->bt_smap + sb.st_size; + t->bt_irec = F_ISSET(t, R_FIXLEN) ? + __rec_fmap : __rec_vmap; + F_SET(t, R_MEMMAPPED); +#else + goto slow; +#endif + } + } + } + + /* Use the recno routines. */ + dbp->close = __rec_close; + dbp->del = __rec_delete; + dbp->fd = __rec_fd; + dbp->get = __rec_get; + dbp->put = __rec_put; + dbp->seq = __rec_seq; + dbp->sync = __rec_sync; + + /* If the root page was created, reset the flags. */ + if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL) + goto err; + if ((h->flags & P_TYPE) == P_BLEAF) { + F_CLR(h, P_TYPE); + F_SET(h, P_RLEAF); + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + } else + mpool_put(t->bt_mp, h, 0); + + if (openinfo && openinfo->flags & R_SNAPSHOT && + !F_ISSET(t, R_EOF | R_INMEM) && + t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) + goto err; + return (dbp); + +einval: errno = EINVAL; +err: sverrno = errno; + if (dbp != NULL) + (void)__bt_close(dbp); + if (fname != NULL) + (void)close(rfd); + errno = sverrno; + return (NULL); +} + +int +__rec_fd(dbp) + const DB *dbp; +{ + BTREE *t; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + /* In-memory database can't have a file descriptor. */ + if (F_ISSET(t, R_INMEM)) { + errno = ENOENT; + return (-1); + } + return (t->bt_rfd); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_put.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_put.c new file mode 100644 index 00000000..c53c9578 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_put.c @@ -0,0 +1,281 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_put.c 8.7 (Berkeley) 8/18/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include +#include + +#include "db-int.h" +#include "recno.h" + +/* + * __REC_PUT -- Add a recno item to the tree. + * + * Parameters: + * dbp: pointer to access method + * key: key + * data: data + * flag: R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE + * + * Returns: + * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is + * already in the tree and R_NOOVERWRITE specified. + */ +int +__rec_put(dbp, key, data, flags) + const DB *dbp; + DBT *key; + const DBT *data; + u_int flags; +{ + BTREE *t; + DBT fdata, tdata; + recno_t nrec; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + /* + * If using fixed-length records, and the record is long, return + * EINVAL. If it's short, pad it out. Use the record data return + * memory, it's only short-term. + */ + if (F_ISSET(t, R_FIXLEN) && data->size != t->bt_reclen) { + if (data->size > t->bt_reclen) + goto einval; + + if (t->bt_rdata.size < t->bt_reclen) { + t->bt_rdata.data = t->bt_rdata.data == NULL ? + malloc(t->bt_reclen) : + realloc(t->bt_rdata.data, t->bt_reclen); + if (t->bt_rdata.data == NULL) + return (RET_ERROR); + t->bt_rdata.size = t->bt_reclen; + } + memmove(t->bt_rdata.data, data->data, data->size); + memset((char *)t->bt_rdata.data + data->size, + t->bt_bval, t->bt_reclen - data->size); + fdata.data = t->bt_rdata.data; + fdata.size = t->bt_reclen; + } else { + fdata.data = data->data; + fdata.size = data->size; + } + + switch (flags) { + case R_CURSOR: + if (!F_ISSET(&t->bt_cursor, CURS_INIT)) + goto einval; + nrec = t->bt_cursor.rcursor; + break; + case R_SETCURSOR: + if ((nrec = *(recno_t *)key->data) == 0) + goto einval; + break; + case R_IAFTER: + if ((nrec = *(recno_t *)key->data) == 0) { + nrec = 1; + flags = R_IBEFORE; + } + break; + case 0: + case R_IBEFORE: + if ((nrec = *(recno_t *)key->data) == 0) + goto einval; + break; + case R_NOOVERWRITE: + if ((nrec = *(recno_t *)key->data) == 0) + goto einval; + if (nrec <= t->bt_nrecs) + return (RET_SPECIAL); + break; + default: +einval: errno = EINVAL; + return (RET_ERROR); + } + + /* + * Make sure that records up to and including the put record are + * already in the database. If skipping records, create empty ones. + */ + if (nrec > t->bt_nrecs) { + if (!F_ISSET(t, R_EOF | R_INMEM) && + t->bt_irec(t, nrec) == RET_ERROR) + return (RET_ERROR); + if (nrec > t->bt_nrecs + 1) { + if (F_ISSET(t, R_FIXLEN)) { + if ((tdata.data = + (void *)malloc(t->bt_reclen)) == NULL) + return (RET_ERROR); + tdata.size = t->bt_reclen; + memset(tdata.data, t->bt_bval, tdata.size); + } else { + tdata.data = NULL; + tdata.size = 0; + } + while (nrec > t->bt_nrecs + 1) + if (__rec_iput(t, + t->bt_nrecs, &tdata, 0) != RET_SUCCESS) + return (RET_ERROR); + if (F_ISSET(t, R_FIXLEN)) + free(tdata.data); + } + } + + if ((status = __rec_iput(t, nrec - 1, &fdata, flags)) != RET_SUCCESS) + return (status); + + if (flags == R_SETCURSOR) + t->bt_cursor.rcursor = nrec; + + F_SET(t, R_MODIFIED); + return (__rec_ret(t, NULL, nrec, key, NULL)); +} + +/* + * __REC_IPUT -- Add a recno item to the tree. + * + * Parameters: + * t: tree + * nrec: record number + * data: data + * + * Returns: + * RET_ERROR, RET_SUCCESS + */ +int +__rec_iput(t, nrec, data, flags) + BTREE *t; + recno_t nrec; + const DBT *data; + u_int flags; +{ + DBT tdata; + EPG *e; + PAGE *h; + indx_t idx, nxtindex; + db_pgno_t pg; + u_int32_t nbytes; + int dflags, status; + char *dest, db[NOVFLSIZE]; + + /* + * If the data won't fit on a page, store it on indirect pages. + * + * XXX + * If the insert fails later on, these pages aren't recovered. + */ + if (data->size > t->bt_ovflsize) { + if (__ovfl_put(t, data, &pg) == RET_ERROR) + return (RET_ERROR); + tdata.data = db; + tdata.size = NOVFLSIZE; + memcpy(db, &pg, sizeof(pg)); + *(u_int32_t *)(void *)(db + sizeof(db_pgno_t)) = data->size; + dflags = P_BIGDATA; + data = &tdata; + } else + dflags = 0; + + /* __rec_search pins the returned page. */ + if ((e = __rec_search(t, nrec, + nrec > t->bt_nrecs || flags == R_IAFTER || flags == R_IBEFORE ? + SINSERT : SEARCH)) == NULL) + return (RET_ERROR); + + h = e->page; + idx = e->index; + + /* + * Add the specified key/data pair to the tree. The R_IAFTER and + * R_IBEFORE flags insert the key after/before the specified key. + * + * Pages are split as required. + */ + switch (flags) { + case R_IAFTER: + ++idx; + break; + case R_IBEFORE: + break; + default: + if (nrec < t->bt_nrecs && + __rec_dleaf(t, h, idx) == RET_ERROR) { + mpool_put(t->bt_mp, h, 0); + return (RET_ERROR); + } + break; + } + + /* + * If not enough room, split the page. The split code will insert + * the key and data and unpin the current page. If inserting into + * the offset array, shift the pointers up. + */ + nbytes = NRLEAFDBT(data->size); + if ((u_int32_t)h->upper - (u_int32_t)h->lower + < nbytes + sizeof(indx_t)) { + status = __bt_split(t, h, NULL, data, dflags, nbytes, idx); + if (status == RET_SUCCESS) + ++t->bt_nrecs; + return (status); + } + + if (idx < (nxtindex = NEXTINDEX(h))) + memmove(h->linp + idx + 1, h->linp + idx, + (nxtindex - idx) * sizeof(indx_t)); + h->lower += sizeof(indx_t); + + h->linp[idx] = h->upper -= nbytes; + dest = (char *)h + h->upper; + WR_RLEAF(dest, data, dflags); + + ++t->bt_nrecs; + F_SET(t, B_MODIFIED); + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + + return (RET_SUCCESS); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_search.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_search.c new file mode 100644 index 00000000..244d79f3 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_search.c @@ -0,0 +1,126 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_search.c 8.4 (Berkeley) 7/14/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include + +#include "db-int.h" +#include "recno.h" + +/* + * __REC_SEARCH -- Search a btree for a key. + * + * Parameters: + * t: tree to search + * recno: key to find + * op: search operation + * + * Returns: + * EPG for matching record, if any, or the EPG for the location of the + * key, if it were inserted into the tree. + * + * Returns: + * The EPG for matching record, if any, or the EPG for the location + * of the key, if it were inserted into the tree, is entered into + * the bt_cur field of the tree. A pointer to the field is returned. + */ +EPG * +__rec_search(t, recno, op) + BTREE *t; + recno_t recno; + enum SRCHOP op; +{ + indx_t idx; + PAGE *h; + EPGNO *parent; + RINTERNAL *r; + db_pgno_t pg; + indx_t top; + recno_t total; + int sverrno; + + BT_CLR(t); + for (pg = P_ROOT, total = 0;;) { + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + goto err; + if (h->flags & P_RLEAF) { + t->bt_cur.page = h; + t->bt_cur.index = recno - total; + return (&t->bt_cur); + } + for (idx = 0, top = NEXTINDEX(h);;) { + r = GETRINTERNAL(h, idx); + if (++idx == top || total + r->nrecs > recno) + break; + total += r->nrecs; + } + + BT_PUSH(t, pg, idx - 1); + + pg = r->pgno; + switch (op) { + case SDELETE: + --GETRINTERNAL(h, (idx - 1))->nrecs; + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + break; + case SINSERT: + ++GETRINTERNAL(h, (idx - 1))->nrecs; + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + break; + case SEARCH: + mpool_put(t->bt_mp, h, 0); + break; + } + + } + /* Try and recover the tree. */ +err: sverrno = errno; + if (op != SEARCH) + while ((parent = BT_POP(t)) != NULL) { + if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL) + break; + if (op == SINSERT) + --GETRINTERNAL(h, parent->index)->nrecs; + else + ++GETRINTERNAL(h, parent->index)->nrecs; + mpool_put(t->bt_mp, h, MPOOL_DIRTY); + } + errno = sverrno; + return (NULL); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_seq.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_seq.c new file mode 100644 index 00000000..8af1378c --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_seq.c @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 1991, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_seq.c 8.3 (Berkeley) 7/14/94"; +#endif /* not lint */ + +#include + +#include +#include +#include +#include + +#include "db-int.h" +#include "recno.h" + +/* + * __REC_SEQ -- Recno sequential scan interface. + * + * Parameters: + * dbp: pointer to access method + * key: key for positioning and return value + * data: data return value + * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV. + * + * Returns: + * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key. + */ +int +__rec_seq(dbp, key, data, flags) + const DB *dbp; + DBT *key, *data; + u_int flags; +{ + BTREE *t; + EPG *e; + recno_t nrec; + int status; + + t = dbp->internal; + + /* Toss any page pinned across calls. */ + if (t->bt_pinned != NULL) { + mpool_put(t->bt_mp, t->bt_pinned, 0); + t->bt_pinned = NULL; + } + + switch(flags) { + case R_CURSOR: + if ((nrec = *(recno_t *)key->data) == 0) + goto einval; + break; + case R_NEXT: + if (F_ISSET(&t->bt_cursor, CURS_INIT)) { + nrec = t->bt_cursor.rcursor + 1; + break; + } + /* FALLTHROUGH */ + case R_FIRST: + nrec = 1; + break; + case R_PREV: + if (F_ISSET(&t->bt_cursor, CURS_INIT)) { + if ((nrec = t->bt_cursor.rcursor - 1) == 0) + return (RET_SPECIAL); + break; + } + /* FALLTHROUGH */ + case R_LAST: + if (!F_ISSET(t, R_EOF | R_INMEM) && + t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR) + return (RET_ERROR); + nrec = t->bt_nrecs; + break; + default: +einval: errno = EINVAL; + return (RET_ERROR); + } + + if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) { + if (!F_ISSET(t, R_EOF | R_INMEM) && + (status = t->bt_irec(t, nrec)) != RET_SUCCESS) + return (status); + if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) + return (RET_SPECIAL); + } + + if ((e = __rec_search(t, nrec - 1, SEARCH)) == NULL) + return (RET_ERROR); + + F_SET(&t->bt_cursor, CURS_INIT); + t->bt_cursor.rcursor = nrec; + + status = __rec_ret(t, e, nrec, key, data); + if (F_ISSET(t, B_DB_LOCK)) + mpool_put(t->bt_mp, e->page, 0); + else + t->bt_pinned = e->page; + return (status); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_utils.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_utils.c new file mode 100644 index 00000000..f757a724 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/rec_utils.c @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)rec_utils.c 8.6 (Berkeley) 7/16/94"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include +#include +#include + +#include "db-int.h" +#include "recno.h" + +/* + * __rec_ret -- + * Build return data. + * + * Parameters: + * t: tree + * e: key/data pair to be returned + * nrec: record number + * key: user's key structure + * data: user's data structure + * + * Returns: + * RET_SUCCESS, RET_ERROR. + */ +int +__rec_ret(t, e, nrec, key, data) + BTREE *t; + EPG *e; + recno_t nrec; + DBT *key, *data; +{ + RLEAF *rl; + void *p; + + if (key == NULL) + goto dataonly; + + /* We have to copy the key, it's not on the page. */ + if (sizeof(recno_t) > t->bt_rkey.size) { + p = (void *)(t->bt_rkey.data == NULL ? + malloc(sizeof(recno_t)) : + realloc(t->bt_rkey.data, sizeof(recno_t))); + if (p == NULL) + return (RET_ERROR); + t->bt_rkey.data = p; + t->bt_rkey.size = sizeof(recno_t); + } + memmove(t->bt_rkey.data, &nrec, sizeof(recno_t)); + key->size = sizeof(recno_t); + key->data = t->bt_rkey.data; + +dataonly: + if (data == NULL) + return (RET_SUCCESS); + + /* + * We must copy big keys/data to make them contigous. Otherwise, + * leave the page pinned and don't copy unless the user specified + * concurrent access. + */ + rl = GETRLEAF(e->page, e->index); + if (rl->flags & P_BIGDATA) { + if (__ovfl_get(t, rl->bytes, + &data->size, &t->bt_rdata.data, &t->bt_rdata.size)) + return (RET_ERROR); + data->data = t->bt_rdata.data; + } else if (F_ISSET(t, B_DB_LOCK)) { + /* Use +1 in case the first record retrieved is 0 length. */ + if (rl->dsize + 1 > t->bt_rdata.size) { + p = (void *)(t->bt_rdata.data == NULL ? + malloc(rl->dsize + 1) : + realloc(t->bt_rdata.data, rl->dsize + 1)); + if (p == NULL) + return (RET_ERROR); + t->bt_rdata.data = p; + t->bt_rdata.size = rl->dsize + 1; + } + memmove(t->bt_rdata.data, rl->bytes, rl->dsize); + data->size = rl->dsize; + data->data = t->bt_rdata.data; + } else { + data->size = rl->dsize; + data->data = rl->bytes; + } + return (RET_SUCCESS); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/recno.h b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/recno.h new file mode 100644 index 00000000..bec772c2 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/recno/recno.h @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)recno.h 8.1 (Berkeley) 6/4/93 + */ + +enum SRCHOP { SDELETE, SINSERT, SEARCH}; /* Rec_search operation. */ + +#include "../btree/btree.h" +#include "extern.h" diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/Makefile.in b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/Makefile.in new file mode 100644 index 00000000..d7a22b1f --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/Makefile.in @@ -0,0 +1,37 @@ +mydir=plugins$(S)kdb$(S)db2$(S)libdb2$(S)test +BUILDTOP=$(REL)..$(S)..$(S)..$(S)..$(S).. + +FCTSH = @FCTSH@ +TMPDIR=. + +LOCALINCLUDES= -I. -I$(srcdir)/../include -I../include -I$(srcdir)/../mpool \ + -I$(srcdir)/../btree -I$(srcdir)/../hash -I$(srcdir)/../db + +PROG_LIBPATH=-L.. -L$(TOPLIBD) + +DB_LIB = -ldb $(SUPPORT_LIB) +DB_DEPLIB = ../libdb$(DEPLIBEXT) $(SUPPORT_DEPLIB) + +all: + +dbtest: dbtest.o $(DB_DEPLIB) + $(CC_LINK) -o $@ dbtest.o $(STRERROR_OBJ) $(DB_LIB) + +t.be.db: $(srcdir)/t.be.txt +t.le.db: $(srcdir)/t.le.txt +t.be.db t.le.db: + $(PERL) -ne 'chomp; print pack("H*", $$_);' $? > $@ + +check: dbtest t.be.db t.le.db runenv.sh + $(RUN_SETUP) srcdir=$(srcdir) TMPDIR=$(TMPDIR) $(VALGRIND) $(FCTSH) $(srcdir)/run.test + +bttest.o: $(srcdir)/btree.tests/main.c + $(CC) $(ALL_CFLAGS) -c $(srcdir)/btree.tests/main.c -o $@ + +bttest: bttest.o $(DB_DEPLIB) + $(CC_LINK) -o $@ bttest.o $(STRERROR_OBJ) $(DB_LIB) + +clean-unix:: + $(RM) dbtest.o dbtest __dbtest + $(RM) bttest.o bttest + $(RM) t.be.db t.le.db diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/README b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/README new file mode 100644 index 00000000..0c0cd13d --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/README @@ -0,0 +1,74 @@ +# @(#)README 8.8 (Berkeley) 7/31/94 + +To build this portably, try something like: + + make PORTDIR="../PORT/MACH" + +where MACH is the machine, i.e. "sunos.4.1.1". + +To run the tests, enter "sh run.test". If your system dictionary isn't +in /usr/share/dict/words, edit run.test to reflect the correct place. + +Fairly large files (the command files) are built in this directory during +the test runs, and even larger files (the database files) are created in +"/var/tmp". If the latter directory doesn't exist, set the environmental +variable TMPDIR to a directory where the files can be built. + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +The script file consists of lines with an initial character which is +the command for that line, or an initial character indicating a key +or data entry for a previous command. + +Legal command characters are as follows: + +c: compare a record + + must be followed by [kK][dD]; the data value in the database + associated with the specified key is compared to the specified + data value. +e: echo a string + + writes out the rest of the line into the output file; if the + last character is not a carriage-return, a newline is appended. +f: set the flags for the next command + + no value zero's the flags +g: do a get command + + must be followed by [kK] + + writes out the retrieved data DBT. +o [r]: dump [reverse] + + dump the database out, if 'r' is set, in reverse order. +p: do a put command + + must be followed by [kK][dD] +r: do a del command + + must be followed by [kK] unless R_CURSOR flag set. +S: sync the database +s: do a seq command + + must be followed by [kK] if R_CURSOR flag set. + + writes out the retrieved data DBT. + +Legal key/data characters are as follows: + +D [file]: data file + + set the current data value to the contents of the file +d [data]: + + set the current key value to the contents of the line. +K [file]: key file + + set the current key value to the contents of the file +k [data]: + + set the current key value to the contents of the line. + +Blank lines, lines with leading white space, and lines with leading +hash marks (#) are ignored. + +Options to dbtest are as follows: + + -d: Set the DB_LOCK flag. + -f: Use the file argument as the database file. + -i: Use the rest of the argument to set elements in the info + structure. If the type is btree, then "-i cachesize=10240" + will set BTREEINFO.cachesize to 10240. + -o: The rest of the argument is the output file instead of + using stdout. + -s: Don't delete the database file before opening it, i.e. + use the database file from a previous run. + +Dbtest requires two arguments, the type of access "hash", "recno" +or "btree", and the script name or "-" to indicate stdin. diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/data b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/data new file mode 100644 index 00000000..37a51853 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/data @@ -0,0 +1,8 @@ +A000027875A000135891 +A000059165A000130168 +A000060256A000133490 +A040025906A000136770 +A040027881A000135829 +A040028611A000137873 +A040032413A000056974 +A040050163A000126233 diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/mbox b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/mbox new file mode 100644 index 00000000..9d5d49d0 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/mbox @@ -0,0 +1,399 @@ +From wiggans@aipl.arsusda.gov Mon Sep 12 11:05:58 1994 +Received: from vangogh.CS.Berkeley.EDU by python.bostic.com (8.6.9.Beta4/2.6) + id OAA16853; Mon, 12 Sep 1994 14:05:42 -0400 +From: wiggans@aipl.arsusda.gov +Received: from hofmann.CS.Berkeley.EDU (hofmann.CS.Berkeley.EDU [128.32.34.35]) by vangogh.CS.Berkeley.EDU (8.7.Alpha.1/8.6.9.Beta0) with ESMTP id LAA15825 for ; Mon, 12 Sep 1994 11:05:20 -0700 (PDT) +Received: from uu7.psi.com (uu7.psi.com [38.145.204.6]) by hofmann.CS.Berkeley.EDU (8.6.9/8.6.6.Beta11) with SMTP id LAA25681 for ; Mon, 12 Sep 1994 11:05:44 -0700 +Received: from AIPL.ARSUSDA.GOV by uu7.psi.com (5.65b/4.0.071791-PSI/PSINet) via SMTP; + id AA00699 for bostic@cs.berkeley.edu; Mon, 12 Sep 94 14:06:15 -0400 +Received: by aipl.arsusda.gov (AIX 3.2/UCB 5.64/4.03) + id AA14802; Mon, 12 Sep 1994 14:05:48 -0400 +Message-Id: <9409121805.AA14802@aipl.arsusda.gov> +Subject: db 1.85 problem +To: bostic@cs.berkeley.edu (Keith Bostic) +Date: Mon, 12 Sep 1994 14:05:47 -0400 (EDT) +X-Mailer: ELM [version 2.4 PL22] +Content-Type: text +Content-Length: 2553 +Status: RO + +In using the btree option to sequentially read and then write a file, we +are having a problem with 1.85. When compiled with 1.73 there is no +problem. The problem is that the seq call keeps reading the same record. +The code follows: + +/* chkseq.c Check sequential read and write */ + +#include +#include +#include +#include +#include /* O_CREAT, O_RDWR */ +#include /* Error numbers */ +#include + +extern int errno; +extern char *sys_errlist[]; + +typedef struct idst { + char id1[7]; +} id; + +void cvtid(char *, char *); + +void main() { + char anim10[11], datastor[212],keystor[10], *pc; + int i; + long in = 0L; + DB *dbp, *dbpo; + DBT key, data, keyo, datao; + + if ((dbp = dbopen("bullxrf.db", O_RDWR, 0664 + , DB_BTREE, NULL )) == NULL) { + printf("\n Error on dbopen %d %s\n",errno,strerror(errno)); + exit(61); + } + key.size = 7; + keyo.size = 7; + + while (dbp->seq(dbp, &key, &data,R_NEXT) == 0) { + in++; + if (in > 20) break; +/* pc = (char *) key.data; +for (i=0;iput(dbp, &keyo, &datao,0) != 0) { + printf("Write failed at %d\n",in); + exit(85); + } +/* } + */ + } + printf("%d Records copied\n",in); + dbp->close(dbp); +} + +I am running on an RS/6000 AIX 3.2.5. The section of the make file +follows: + +# Make file +all: chkseq + +chkseq: chkseq.c + cc -gO3 -lm -o chkseq\ + -L /data6/hash/include/sys/lib -l db -I /data6/hash/include \ + chkseq.c cvtid.o ascii.o +# -L /data12/db.1.85 -l db -I /data12/db.1.85/include \ + +We would appreciate your help. +Thanks, + +-- +George Wiggans I================================================I + |Animal Improvement Programs Laboratory | +Phone: 301-504-8407 |Bldg 263 Beltsville Agricultural Research Center| +FAX: 301-504-8092 |Beltsville, MD 20705-2350 USA | +wiggans@aipl.arsusda.gov | | +=========================I================================================I + +From wiggans@aipl.arsusda.gov Fri Sep 16 20:27:22 1994 +Received: from vangogh.CS.Berkeley.EDU by python.bostic.com (8.6.9.Beta4/2.6) + id XAA09260; Fri, 16 Sep 1994 23:27:09 -0400 +From: wiggans@aipl.arsusda.gov +Received: from hofmann.CS.Berkeley.EDU (hofmann.CS.Berkeley.EDU [128.32.34.35]) by vangogh.CS.Berkeley.EDU (8.7.Alpha.1/8.6.9.Beta0) with ESMTP id UAA25674 for ; Fri, 16 Sep 1994 20:27:03 -0700 (PDT) +Received: from uu7.psi.com (uu7.psi.com [38.145.204.6]) by hofmann.CS.Berkeley.EDU (8.6.9/8.6.6.Beta11) with SMTP id UAA15043 for ; Fri, 16 Sep 1994 20:27:16 -0700 +Received: from AIPL.ARSUSDA.GOV by uu7.psi.com (5.65b/4.0.071791-PSI/PSINet) via SMTP; + id AA18737 for bostic@cs.berkeley.edu; Fri, 16 Sep 94 23:27:14 -0400 +Received: by aipl.arsusda.gov (AIX 3.2/UCB 5.64/4.03) + id AA10907; Fri, 16 Sep 1994 23:26:18 -0400 +Message-Id: <9409170326.AA10907@aipl.arsusda.gov> +Subject: Test case +To: bostic@cs.berkeley.edu (Keith Bostic) +Date: Fri, 16 Sep 1994 23:26:16 -0400 (EDT) +X-Mailer: ELM [version 2.4 PL22] +Content-Type: text +Content-Length: 3713 +Status: RO + +The following program loads 2 10 character animal ID which are used to +change an animal's ID. After loading, it closes, then opens and +sequentially reads and rewrites the file changing the first character of +the 2nd ID to U. Failure is observed when the update part gets stuck on +the first record, rereading it. The last step displays the updated file. +The name of the data file is a command line argument. + +The data: +A000027875A000135891 +A000059165A000130168 +A000060256A000133490 +A040025906A000136770 +A040027881A000135829 +A040028611A000137873 +A040032413A000056974 +A040050163A000126233 +A040050329A000126177 +A040050411A000119017 +A040050995A000116767 +A040051022A000126669 +A040051276A000127444 +A040051514A000120563 +A040051597A000127287 +A040051627A000127284 +A040051700A000126914 +A040051810A000127286 +A040051964A000118834 +A040052164A000135104 +A040052165A000127688 +A040052186A000126926 +A040052530A000126287 +A040052560A000119160 +A040052892A000125334 +A040053004A000127684 +A040053359A000128628 +A040053378A000137680 +A040053416A000128825 +A040053589A000120369 +A040053620A000128460 +A040053751A000123525 +A040053754A000126736 +A040054191A000126286 +A040054251A000121745 +A040054253A000127848 +A040054596A000130931 +A040054981A000128731 +A040055000A000127689 + +The program: +/* chkseq.c Check sequential read and write */ + +#include +#include +#include +#include +#include /* O_CREAT, O_RDWR */ +#include /* Error numbers */ +#include + +extern int errno; +extern char *sys_errlist[]; + + +void main(int argc, char *argv[]) { + char id1[] = {" "}, id2[] = {" "}; + int i; + long in = 0L, out = 0L; + DB *dbp, *dbpo; + DBT key, data, keyo, datao; + FILE *fopen(), *fin; + + if ((fin = fopen(argv[1],"r")) == NULL) { + printf("Unable to open %s\n",argv[1]); + exit(25); + } + if ((dbp = dbopen("test.db",O_RDWR | O_CREAT, 0664 + , DB_BTREE, NULL )) == NULL) { + printf("\n Open error on test.db %d %s\n",errno,strerror(errno)); + exit(25); + } + + while (fscanf(fin," %10s%10s",id1,id2) > 0) { + key.size = 11; + data.size = 11; + key.data = id1; + data.data = id2; + printf("%10s %10s\n",key.data,data.data); + if (dbp->put(dbp, &key, &data,R_NOOVERWRITE) != 0) { + printf("Error writing output\n"); + } + out++; + } + printf("%d Records in\n",out); + dbp->close(dbp); + + if ((dbp = dbopen("test.db", O_RDWR, 0664 + , DB_BTREE, NULL )) == NULL) { + printf("\n Error on dbopen %d %s\n",errno,strerror(errno)); + exit(61); + } + + while (dbp->seq(dbp, &key, &data,R_NEXT) == 0) { + strcpy(id1,key.data); + keyo.size = 11; + datao.size = 11; + keyo.data = id1; + strcpy(id2,data.data); + id2[0] = 'U'; + datao.data=id2; + printf("%10s %10s\n",key.data,data.data); + in++; + if (in > 50) break; + if (dbp->put(dbp, &keyo, &datao,0) != 0) { + printf("Write failed at %d\n",in); + exit(85); + } + } + printf("%d Records copied\n",in); + in = 0; + dbp->seq(dbp, &key, &data,R_FIRST); + printf("%10s %10s\n",key.data,data.data); + in++; + while (dbp->seq(dbp, &key, &data,R_NEXT) == 0) { + in++; + printf("%10s %10s\n",key.data,data.data); + } + printf("%d Records read\n",in); + dbp->close(dbp); +} + + +-- +George Wiggans I================================================I + |Animal Improvement Programs Laboratory | +Phone: 301-504-8407 |Bldg 263 Beltsville Agricultural Research Center| +FAX: 301-504-8092 |Beltsville, MD 20705-2350 USA | +wiggans@aipl.arsusda.gov | | +=========================I================================================I + +From bostic Fri Sep 23 08:44:56 1994 +To: wiggans@aipl.arsusda.gov /usr/src/local/db/test/SEQ_TEST/mbox +Subject: Re: Test case + + +OK, I've attached a tentative patch for the bug, that appears +to fix it on my local system. Please let me know if you have +any further problems with this. + +There are a couple of issues here. The first, is that to some +extent, the btree code is correct. You aren't replacing the +cursor in your test program, you're adding a new key, which +just happens to be where the cursor was. So, the btree code +is doing you a favor by returning the new key as part of the +cursor walk, and it's not its fault. ;-} + +However, because a put to the cursor record is done using a +delete/add pair, doing it the "right" way will result in the +exact same behavior as you saw doing it "wrong". + +Thinking about this further, there's another bug that's going to +hit eventually -- if you have duplicate records, the current +scheme of doing delete/add to replace the cursor record can result +in a record being returned twice, which is tacky at best, if not +actually wrong. + +I think I may have to revisit how duplicate records are stored. +Which does not make me happy. ;-{ + +--keith + +*** db/btree/bt_seq.c.orig Fri Sep 23 08:35:06 1994 +--- db/btree/bt_seq.c Fri Sep 23 08:34:58 1994 +*************** +*** 35,41 **** + */ + + #if defined(LIBC_SCCS) && !defined(lint) +! static char sccsid[] = "@(#)bt_seq.c 8.7 (Berkeley) 7/20/94"; + #endif /* LIBC_SCCS and not lint */ + + #include +--- 35,41 ---- + */ + + #if defined(LIBC_SCCS) && !defined(lint) +! static char sccsid[] = "@(#)bt_seq.c 8.8 (Berkeley) 9/23/94"; + #endif /* LIBC_SCCS and not lint */ + + #include +*************** +*** 246,252 **** + PAGE *h; + indx_t index; + pgno_t pg; +! int exact; + + /* + * There are a couple of states that we can be in. The cursor has +--- 246,252 ---- + PAGE *h; + indx_t index; + pgno_t pg; +! int exact, rval; + + /* + * There are a couple of states that we can be in. The cursor has +*************** +*** 255,269 **** + c = &t->bt_cursor; + + /* +! * The cursor was deleted where there weren't any duplicate records, +! * so the key was saved. Find out where that key would go in the +! * current tree. It doesn't matter if the returned key is an exact +! * match or not -- if it's an exact match, the record was added after +! * the delete so we can just return it. If not, as long as there's +! * a record there, return it. + */ +! if (F_ISSET(c, CURS_ACQUIRE)) +! return (__bt_first(t, &c->key, ep, &exact)); + + /* Get the page referenced by the cursor. */ + if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL) +--- 255,299 ---- + c = &t->bt_cursor; + + /* +! * The cursor was deleted and there weren't any duplicate records, +! * so the cursor's key was saved. Find out where that key would +! * be in the current tree. If the returned key is an exact match, +! * it means that a key/data pair was inserted into the tree after +! * the delete. We could reasonably return the key, but the problem +! * is that this is the access pattern we'll see if the user is +! * doing seq(..., R_NEXT)/put(..., 0) pairs, i.e. the put deletes +! * the cursor record and then replaces it, so the cursor was saved, +! * and we'll simply return the same "new" record until the user +! * notices and doesn't do a put() of it. Since the key is an exact +! * match, we could as easily put the new record before the cursor, +! * and we've made no guarantee to return it. So, move forward or +! * back a record if it's an exact match. +! * +! * XXX +! * In the current implementation, put's to the cursor are done with +! * delete/add pairs. This has two consequences. First, it means +! * that seq(..., R_NEXT)/put(..., R_CURSOR) pairs are going to exhibit +! * the same behavior as above. Second, you can return the same key +! * twice if you have duplicate records. The scenario is that the +! * cursor record is deleted, moving the cursor forward or backward +! * to a duplicate. The add then inserts the new record at a location +! * ahead of the cursor because duplicates aren't sorted in any way, +! * and the new record is later returned. This has to be fixed at some +! * point. + */ +! if (F_ISSET(c, CURS_ACQUIRE)) { +! if (rval = __bt_first(t, &c->key, ep, &exact)) +! return (RET_ERROR); +! if (!exact) +! return (rval); +! /* +! * XXX +! * Kluge -- get, release, get the page. +! */ +! c->pg.pgno = ep->page->pgno; +! c->pg.index = ep->index; +! mpool_put(t->bt_mp, ep->page, 0); +! } + + /* Get the page referenced by the cursor. */ + if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL) + + + diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/t.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/t.c new file mode 100644 index 00000000..cfd1a421 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/SEQ_TEST/t.c @@ -0,0 +1,85 @@ +/* chkseq.c Check sequential read and write */ + +#include +#include "db-int.h" +#include /* Error numbers */ +#include /* O_CREAT, O_RDWR */ +#include +#include +#include + + +void main(int argc, char *argv[]) { + char id1[] = {" "}, id2[] = {" "}; + int i; + long in = 0L, out = 0L; + DB *dbp, *dbpo; + DBT key, data, keyo, datao; + FILE *fopen(), *fin; + + unlink("test.db"); + if ((fin = fopen("data","r")) == NULL) { + printf("Unable to open %s\n","data"); + exit(25); + } + if ((dbp = dbopen("test.db",O_RDWR | O_CREAT | O_BINARY, 0664 + , DB_BTREE, NULL )) == NULL) { + printf("\n Open error on test.db %d %s\n",errno,strerror(errno)); + exit(25); + } + + while (fscanf(fin," %10s%10s",id1,id2) > 0) { + key.size = 11; + data.size = 11; + key.data = id1; + data.data = id2; + printf("%10s %10s\n",key.data,data.data); + if (dbp->put(dbp, &key, &data,R_NOOVERWRITE) != 0) { + printf("Error writing output\n"); + } + out++; + } + printf("%d Records in\n",out); + dbp->close(dbp); + + if ((dbp = dbopen("test.db", O_RDWR | O_BINARY, 0664 + , DB_BTREE, NULL )) == NULL) { + printf("\n Error on dbopen %d %s\n",errno,strerror(errno)); + exit(61); + } + + while (dbp->seq(dbp, &key, &data,R_NEXT) == 0) { + strcpy(id1,key.data); + keyo.size = 11; + datao.size = 11; + keyo.data = id1; + strcpy(id2,data.data); + id2[0] = 'U'; + datao.data=id2; + printf("%10s %10s\n",key.data,data.data); + in++; + if (in > 10) break; +#ifdef notdef + if (dbp->put(dbp, &keyo, &datao,0) != 0) { + printf("Write failed at %d\n",in); + exit(85); + } +#else + if (dbp->put(dbp, &keyo, &datao,R_CURSOR) != 0) { + printf("Write failed at %d\n",in); + exit(85); + } +#endif + } + printf("%d Records copied\n",in); + in = 0; + dbp->seq(dbp, &key, &data,R_FIRST); + printf("%10s %10s\n",key.data,data.data); + in++; + while (dbp->seq(dbp, &key, &data,R_NEXT) == 0) { + in++; + printf("%10s %10s\n",key.data,data.data); + } + printf("%d Records read\n",in); + dbp->close(dbp); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c new file mode 100644 index 00000000..088f9032 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/btree.tests/main.c @@ -0,0 +1,973 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ +/* + * Copyright (C) 2016 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include "db-int.h" +#include +#include +#include +#include +#include +#include "btree.h" + +typedef struct cmd_table { + char *cmd; + int nargs; + int rconv; + void (*func) __P((DB *, char **)); + char *usage, *descrip; +} cmd_table; + +int stopstop; +DB *globaldb; + +#if 0 +void append __P((DB *, char **)); +#endif +#ifdef STATISTICS +void bstat __P((DB *, char **)); +#endif +void cursor __P((DB *, char **)); +void delcur __P((DB *, char **)); +void delete __P((DB *, char **)); +#ifdef DEBUG +void dump __P((DB *, char **)); +#endif +void first __P((DB *, char **)); +void get __P((DB *, char **)); +void help __P((DB *, char **)); +void iafter __P((DB *, char **)); +void ibefore __P((DB *, char **)); +void icursor __P((DB *, char **)); +void insert __P((DB *, char **)); +void keydata __P((DBT *, DBT *)); +void last __P((DB *, char **)); +void list __P((DB *, char **)); +#if 0 +void load __P((DB *, char **)); +#endif +#ifdef STATISTICS +void mstat __P((DB *, char **)); +#endif +void next __P((DB *, char **)); +int parse __P((char *, char **, int)); +void previous __P((DB *, char **)); +#ifdef DEBUG +void show __P((DB *, char **)); +#endif +void rlist __P((DB *, char **)); +void rnext __P((DB *, char **)); +void rprev __P((DB *, char **)); +void usage __P((void)); +void user __P((DB *)); +void unlinkpg __P((DB *, char **)); + +cmd_table commands[] = { + "?", 0, 0, help, "help", NULL, +#if 0 + "a", 2, 1, append, "append key def", "append key with data def", +#endif +#ifdef STATISTICS + "b", 0, 0, bstat, "bstat", "stat btree", +#endif + "c", 1, 1, cursor, "cursor word", "move cursor to word", + "delc", 0, 0, delcur, "delcur", "delete key the cursor references", + "dele", 1, 1, delete, "delete word", "delete word", +#ifdef DEBUG + "d", 0, 0, dump, "dump", "dump database", +#endif + "f", 0, 0, first, "first", "move cursor to first record", + "g", 1, 1, get, "get key", "locate key", + "h", 0, 0, help, "help", "print command summary", + "ia", 2, 1, iafter, "iafter key data", "insert data after key", + "ib", 2, 1, ibefore, "ibefore key data", "insert data before key", + "ic", 2, 1, icursor, "icursor key data", "replace cursor", + "in", 2, 1, insert, "insert key def", "insert key with data def", + "la", 0, 0, last, "last", "move cursor to last record", + "li", 1, 1, list, "list file", "list to a file", +#if 0 + "loa", 1, 0, load, "load file", NULL, +#endif + "loc", 1, 1, get, "get key", NULL, +#ifdef STATISTICS + "m", 0, 0, mstat, "mstat", "stat memory pool", +#endif + "n", 0, 0, next, "next", "move cursor forward one record", + "p", 0, 0, previous, "previous", "move cursor back one record", + "q", 0, 0, NULL, "quit", "quit", + "rli", 1, 1, rlist, "rlist file", "list to a file (recursive)", + "rn", 0, 0, rnext, "rnext", "move cursor forward one record (recursive)", + "rp", 0, 0, rprev, "rprev", "move cursor back one record (recursive)", +#ifdef DEBUG + "sh", 1, 0, show, "show page", "dump a page", +#endif + "u", 1, 0, unlinkpg, "unlink pgno|internal|leaf", "unlink a page", + + { NULL }, +}; + +int recno; /* use record numbers */ +char *dict = "words"; /* default dictionary */ +char *progname; + +int +main(argc, argv) + int argc; + char **argv; +{ + int c; + int omode; + DB *db; + BTREEINFO b; + + progname = *argv; + + omode = O_RDONLY; + b.flags = 0; + b.cachesize = 0; + b.maxkeypage = 0; + b.minkeypage = 0; + b.psize = 0; + b.compare = NULL; + b.prefix = NULL; + b.lorder = 0; + + while ((c = getopt(argc, argv, "bc:di:lp:ruw")) != -1) { + switch (c) { + case 'b': + b.lorder = DB_BIG_ENDIAN; + break; + case 'c': + b.cachesize = atoi(optarg); + break; + case 'd': + b.flags |= R_DUP; + break; + case 'i': + dict = optarg; + break; + case 'l': + b.lorder = DB_LITTLE_ENDIAN; + break; + case 'p': + b.psize = atoi(optarg); + break; + case 'r': + recno = 1; + break; + case 'u': + b.flags = 0; + break; + case 'w': + omode = O_RDWR; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (recno) + db = dbopen(*argv == NULL ? NULL : *argv, omode|O_BINARY, + 0, DB_RECNO, NULL); + else + db = dbopen(*argv == NULL ? NULL : *argv, O_CREAT|omode|O_BINARY, + 0600, DB_BTREE, &b); + + if (db == NULL) { + (void)fprintf(stderr, "dbopen: %s\n", strerror(errno)); + exit(1); + } + globaldb = db; + user(db); + exit(0); + /* NOTREACHED */ +} + +void +user(db) + DB *db; +{ + FILE *ifp; + int argc, i, last; + char *lbuf, *argv[4], buf[512]; + + if ((ifp = fopen("/dev/tty", "r")) == NULL) { + (void)fprintf(stderr, + "/dev/tty: %s\n", strerror(errno)); + exit(1); + } + for (last = 0;;) { + (void)printf("> "); + (void)fflush(stdout); + if ((lbuf = fgets(&buf[0], 512, ifp)) == NULL) { + (void)printf("\n"); + if (ferror(ifp) && errno == EINTR) { + clearerr(ifp); + continue; + } + break; + } + if (lbuf[0] == '\n') { + i = last; + goto uselast; + } + lbuf[strlen(lbuf) - 1] = '\0'; + + if (lbuf[0] == 'q') + break; + + argc = parse(lbuf, &argv[0], 3); + if (argc == 0) + continue; + + for (i = 0; commands[i].cmd != NULL; i++) + if (strncmp(commands[i].cmd, argv[0], + strlen(commands[i].cmd)) == 0) + break; + + if (commands[i].cmd == NULL) { + (void)fprintf(stderr, + "%s: command unknown ('help' for help)\n", lbuf); + continue; + } + + if (commands[i].nargs != argc - 1) { + (void)fprintf(stderr, "usage: %s\n", commands[i].usage); + continue; + } + + if (recno && commands[i].rconv) { + static recno_t nlong; + nlong = atoi(argv[1]); + argv[1] = (char *)&nlong; + } +uselast: last = i; + (*commands[i].func)(db, argv); + } + if ((db->sync)(db, 0) == RET_ERROR) + perror("dbsync"); + else if ((db->close)(db) == RET_ERROR) + perror("dbclose"); +} + +int +parse(lbuf, argv, maxargc) + char *lbuf, **argv; + int maxargc; +{ + int argc = 0; + char *c; + + c = lbuf; + while (isspace(*c)) + c++; + while (*c != '\0' && argc < maxargc) { + *argv++ = c; + argc++; + while (!isspace(*c) && *c != '\0') { + c++; + } + while (isspace(*c)) + *c++ = '\0'; + } + return (argc); +} + +#if 0 +void +append(db, argv) + DB *db; + char **argv; +{ + DBT key, data; + int status; + + if (!recno) { + (void)fprintf(stderr, + "append only available for recno db's.\n"); + return; + } + key.data = argv[1]; + key.size = sizeof(recno_t); + data.data = argv[2]; + data.size = strlen(data.data); + status = (db->put)(db, &key, &data, R_APPEND); + switch (status) { + case RET_ERROR: + perror("append/put"); + break; + case RET_SPECIAL: + (void)printf("%s (duplicate key)\n", argv[1]); + break; + case RET_SUCCESS: + break; + } +} +#endif + +void +cursor(db, argv) + DB *db; + char **argv; +{ + DBT data, key; + int status; + + key.data = argv[1]; + if (recno) + key.size = sizeof(recno_t); + else + key.size = strlen(argv[1]) + 1; + status = (*db->seq)(db, &key, &data, R_CURSOR); + switch (status) { + case RET_ERROR: + perror("cursor/seq"); + break; + case RET_SPECIAL: + (void)printf("key not found\n"); + break; + case RET_SUCCESS: + keydata(&key, &data); + break; + } +} + +void +delcur(db, argv) + DB *db; + char **argv; +{ + int status; + + status = (*db->del)(db, NULL, R_CURSOR); + + if (status == RET_ERROR) + perror("delcur/del"); +} + +void +delete(db, argv) + DB *db; + char **argv; +{ + DBT key; + int status; + + key.data = argv[1]; + if (recno) + key.size = sizeof(recno_t); + else + key.size = strlen(argv[1]) + 1; + + status = (*db->del)(db, &key, 0); + switch (status) { + case RET_ERROR: + perror("delete/del"); + break; + case RET_SPECIAL: + (void)printf("key not found\n"); + break; + case RET_SUCCESS: + break; + } +} + +#ifdef DEBUG +void +dump(db, argv) + DB *db; + char **argv; +{ + __bt_dump(db); +} +#endif + +void +first(db, argv) + DB *db; + char **argv; +{ + DBT data, key; + int status; + + status = (*db->seq)(db, &key, &data, R_FIRST); + + switch (status) { + case RET_ERROR: + perror("first/seq"); + break; + case RET_SPECIAL: + (void)printf("no more keys\n"); + break; + case RET_SUCCESS: + keydata(&key, &data); + break; + } +} + +void +get(db, argv) + DB *db; + char **argv; +{ + DBT data, key; + int status; + + key.data = argv[1]; + if (recno) + key.size = sizeof(recno_t); + else + key.size = strlen(argv[1]) + 1; + + status = (*db->get)(db, &key, &data, 0); + + switch (status) { + case RET_ERROR: + perror("get/get"); + break; + case RET_SPECIAL: + (void)printf("key not found\n"); + break; + case RET_SUCCESS: + keydata(&key, &data); + break; + } +} + +void +help(db, argv) + DB *db; + char **argv; +{ + int i; + + for (i = 0; commands[i].cmd; i++) + if (commands[i].descrip) + (void)printf("%s: %s\n", + commands[i].usage, commands[i].descrip); +} + +void +iafter(db, argv) + DB *db; + char **argv; +{ + DBT key, data; + int status; + + if (!recno) { + (void)fprintf(stderr, + "iafter only available for recno db's.\n"); + return; + } + key.data = argv[1]; + key.size = sizeof(recno_t); + data.data = argv[2]; + data.size = strlen(data.data); + status = (db->put)(db, &key, &data, R_IAFTER); + switch (status) { + case RET_ERROR: + perror("iafter/put"); + break; + case RET_SPECIAL: + (void)printf("%s (duplicate key)\n", argv[1]); + break; + case RET_SUCCESS: + break; + } +} + +void +ibefore(db, argv) + DB *db; + char **argv; +{ + DBT key, data; + int status; + + if (!recno) { + (void)fprintf(stderr, + "ibefore only available for recno db's.\n"); + return; + } + key.data = argv[1]; + key.size = sizeof(recno_t); + data.data = argv[2]; + data.size = strlen(data.data); + status = (db->put)(db, &key, &data, R_IBEFORE); + switch (status) { + case RET_ERROR: + perror("ibefore/put"); + break; + case RET_SPECIAL: + (void)printf("%s (duplicate key)\n", argv[1]); + break; + case RET_SUCCESS: + break; + } +} + +void +icursor(db, argv) + DB *db; + char **argv; +{ + int status; + DBT data, key; + + key.data = argv[1]; + if (recno) + key.size = sizeof(recno_t); + else + key.size = strlen(argv[1]) + 1; + data.data = argv[2]; + data.size = strlen(argv[2]) + 1; + + status = (*db->put)(db, &key, &data, R_CURSOR); + switch (status) { + case RET_ERROR: + perror("icursor/put"); + break; + case RET_SPECIAL: + (void)printf("%s (duplicate key)\n", argv[1]); + break; + case RET_SUCCESS: + break; + } +} + +void +insert(db, argv) + DB *db; + char **argv; +{ + int status; + DBT data, key; + + key.data = argv[1]; + if (recno) + key.size = sizeof(recno_t); + else + key.size = strlen(argv[1]) + 1; + data.data = argv[2]; + data.size = strlen(argv[2]) + 1; + + status = (*db->put)(db, &key, &data, R_NOOVERWRITE); + switch (status) { + case RET_ERROR: + perror("insert/put"); + break; + case RET_SPECIAL: + (void)printf("%s (duplicate key)\n", argv[1]); + break; + case RET_SUCCESS: + break; + } +} + +void +last(db, argv) + DB *db; + char **argv; +{ + DBT data, key; + int status; + + status = (*db->seq)(db, &key, &data, R_LAST); + + switch (status) { + case RET_ERROR: + perror("last/seq"); + break; + case RET_SPECIAL: + (void)printf("no more keys\n"); + break; + case RET_SUCCESS: + keydata(&key, &data); + break; + } +} + +void +list(db, argv) + DB *db; + char **argv; +{ + DBT data, key; + FILE *fp; + int status; + + if ((fp = fopen(argv[1], "w")) == NULL) { + (void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno)); + return; + } + status = (*db->seq)(db, &key, &data, R_FIRST); + while (status == RET_SUCCESS) { + (void)fprintf(fp, "%.*s\n", (int)key.size, key.data); + status = (*db->seq)(db, &key, &data, R_NEXT); + } + (void)fclose(fp); + if (status == RET_ERROR) + perror("list/seq"); +} + +void +rlist(db, argv) + DB *db; + char **argv; +{ + DBT data, key; + FILE *fp; + int status; + + if ((fp = fopen(argv[1], "w")) == NULL) { + (void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno)); + return; + } + status = (*db->seq)(db, &key, &data, R_FIRST); + while (status == RET_SUCCESS) { + (void)fprintf(fp, "%.*s\n", (int)key.size, key.data); + status = (*db->seq)(db, &key, &data, R_RNEXT); + } + (void)fclose(fp); + if (status == RET_ERROR) + perror("list/seq"); +} + +#if 0 +DB *BUGdb; +void +load(db, argv) + DB *db; + char **argv; +{ + char *p, *t; + FILE *fp; + DBT data, key; + recno_t cnt; + size_t len; + int status; + char *lp, buf[16 * 1024]; + + BUGdb = db; + if ((fp = fopen(argv[1], "r")) == NULL) { + (void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno)); + return; + } + (void)printf("loading %s...\n", argv[1]); + + for (cnt = 1; (lp = fgetline(fp, &len)) != NULL; ++cnt) { + if (recno) { + key.data = &cnt; + key.size = sizeof(recno_t); + data.data = lp; + data.size = len + 1; + } else { + key.data = lp; + key.size = len + 1; + for (p = lp + len - 1, t = buf; p >= lp; *t++ = *p--); + *t = '\0'; + data.data = buf; + data.size = len + 1; + } + + status = (*db->put)(db, &key, &data, R_NOOVERWRITE); + switch (status) { + case RET_ERROR: + perror("load/put"); + exit(1); + case RET_SPECIAL: + if (recno) + (void)fprintf(stderr, + "duplicate: %ld {%s}\n", cnt, data.data); + else + (void)fprintf(stderr, + "duplicate: %ld {%s}\n", cnt, key.data); + exit(1); + case RET_SUCCESS: + break; + } + } + (void)fclose(fp); +} +#endif + +void +next(db, argv) + DB *db; + char **argv; +{ + DBT data, key; + int status; + + status = (*db->seq)(db, &key, &data, R_NEXT); + + switch (status) { + case RET_ERROR: + perror("next/seq"); + break; + case RET_SPECIAL: + (void)printf("no more keys\n"); + break; + case RET_SUCCESS: + keydata(&key, &data); + break; + } +} + +void +previous(db, argv) + DB *db; + char **argv; +{ + DBT data, key; + int status; + + status = (*db->seq)(db, &key, &data, R_PREV); + + switch (status) { + case RET_ERROR: + perror("previous/seq"); + break; + case RET_SPECIAL: + (void)printf("no more keys\n"); + break; + case RET_SUCCESS: + keydata(&key, &data); + break; + } +} + +void +rnext(db, argv) + DB *db; + char **argv; +{ + DBT data, key; + int status; + + status = (*db->seq)(db, &key, &data, R_RNEXT); + + switch (status) { + case RET_ERROR: + perror("rnext/seq"); + break; + case RET_SPECIAL: + (void)printf("no more keys\n"); + break; + case RET_SUCCESS: + keydata(&key, &data); + break; + } +} + +void +rprev(db, argv) + DB *db; + char **argv; +{ + DBT data, key; + int status; + + status = (*db->seq)(db, &key, &data, R_RPREV); + + switch (status) { + case RET_ERROR: + perror("rprev/seq"); + break; + case RET_SPECIAL: + (void)printf("no more keys\n"); + break; + case RET_SUCCESS: + keydata(&key, &data); + break; + } +} + +#ifdef DEBUG +void +show(db, argv) + DB *db; + char **argv; +{ + BTREE *t; + PAGE *h; + db_pgno_t pg; + + pg = atoi(argv[1]); + t = db->internal; + if ((h = mpool_get(t->bt_mp, pg, MPOOL_IGNOREPIN)) == NULL) { + (void)printf("getpage of %ld failed\n", pg); + return; + } + if (pg == 0) + __bt_dmpage(h); + else + __bt_dpage(db, h); +} +#endif + +#ifdef STATISTICS +void +bstat(db, argv) + DB *db; + char **argv; +{ + (void)printf("BTREE\n"); + __bt_stat(db); +} + +void +mstat(db, argv) + DB *db; + char **argv; +{ + (void)printf("MPOOL\n"); + mpool_stat(((BTREE *)db->internal)->bt_mp); +} +#endif + +void +keydata(key, data) + DBT *key, *data; +{ + if (!recno && key->size > 0) + (void)printf("%.*s/", (int)key->size, key->data); + if (data->size > 0) + (void)printf("%.*s", (int)data->size, data->data); + (void)printf("\n"); +} + +void +usage() +{ + (void)fprintf(stderr, + "usage: %s [-bdluw] [-c cache] [-i file] [-p page] [file]\n", + progname); + exit (1); +} + +/* Find a candidate page to unlink. */ +static PAGE * +candidatepg(BTREE *t, char *arg) +{ + PAGE *h = NULL; + db_pgno_t pg; + u_int32_t sflags; + + if (arg[0] == 'i') + sflags = P_BINTERNAL | P_RINTERNAL; + if (arg[0] == 'l') + sflags = P_BLEAF | P_RLEAF; + for (pg = P_ROOT; pg < t->bt_mp->npages; + mpool_put(t->bt_mp, h, 0), pg++) { + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + return h; + /* Look for a nonempty page of the correct + * type that has both left and right siblings. */ + if (h->prevpg == P_INVALID || h->nextpg == P_INVALID) + continue; + if ((h->flags & sflags) && NEXTINDEX(h) != 0) + break; + } + if (pg == t->bt_mp->npages) + h = NULL; + return h; +} + +void +unlinkpg(DB *db, char **argv) +{ + BTREE *t = db->internal; + PAGE *h = NULL; + db_pgno_t pg; + + pg = atoi(argv[1]); + if (pg == 0) + h = candidatepg(t, argv[1]); + else + h = mpool_get(t->bt_mp, pg, 0); + + if (h == NULL) { + fprintf(stderr, "unable to find appropriate page to unlink\n"); + return; + } + printf("chain %d <- %d -> %d\n", h->prevpg, h->pgno, h->nextpg); + if (__bt_relink(t, h) != 0) { + perror("unlinkpg"); + goto cleanup; + } + h->prevpg = P_INVALID; + h->nextpg = P_INVALID; +cleanup: + mpool_put(t->bt_mp, h, MPOOL_DIRTY); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/dbtest.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/dbtest.c new file mode 100644 index 00000000..5d76b1dd --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/dbtest.c @@ -0,0 +1,842 @@ +/*- + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ +/* + * Copyright (C) 2016 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. + */ + +#if !defined(lint) && defined(LIBC_SCCS) +static char copyright[] = +"@(#) Copyright (c) 1992, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#if !defined(lint) && defined(LIBC_SCCS) +static char sccsid[] = "@(#)dbtest.c 8.17 (Berkeley) 9/1/94"; +#endif /* not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "db-int.h" +#include "btree.h" + +enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA }; + +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) +#define ATTR(x) __attribute__(x) +#else +#define ATTR(x) +#endif + +void compare __P((DBT *, DBT *)); +DBTYPE dbtype __P((char *)); +void dump __P((DB *, int, int)); +void err __P((const char *, ...)) ATTR ((__format__(__printf__,1,2))) ATTR ((__noreturn__)); +void get __P((DB *, DBT *)); +void getdata __P((DB *, DBT *, DBT *)); +void put __P((DB *, DBT *, DBT *)); +void rem __P((DB *, DBT *)); +char *sflags __P((int)); +void synk __P((DB *)); +void *rfile __P((char *, size_t *)); +void seq __P((DB *, DBT *)); +u_int setflags __P((char *)); +void *setinfo __P((DBTYPE, char *)); +void unlinkpg __P((DB *)); +void usage __P((void)); +void *xmalloc __P((char *, size_t)); + +DBTYPE type; /* Database type. */ +void *infop; /* Iflags. */ +u_long lineno; /* Current line in test script. */ +u_int flags; /* Current DB flags. */ +int ofd = STDOUT_FILENO; /* Standard output fd. */ + +DB *XXdbp; /* Global for gdb. */ +u_long XXlineno; /* Fast breakpoint for gdb. */ + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern int optind; + extern char *optarg; + enum S command = COMMAND, state; + DB *dbp; + DBT data, key, keydata; + size_t len; + int ch, oflags, sflag; + char *fname, *infoarg, *p, *t, buf[8 * 1024]; + + infoarg = NULL; + fname = NULL; + oflags = O_CREAT | O_RDWR | O_BINARY; + sflag = 0; + while ((ch = getopt(argc, argv, "f:i:lo:s")) != -1) + switch (ch) { + case 'f': + fname = optarg; + break; + case 'i': + infoarg = optarg; + break; + case 'l': + oflags |= DB_LOCK; + break; + case 'o': + if ((ofd = open(optarg, + O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) + err("%s: %s", optarg, strerror(errno)); + break; + case 's': + sflag = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc != 2) + usage(); + + /* Set the type. */ + type = dbtype(*argv++); + + /* Open the descriptor file. */ + if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL) + err("%s: %s", *argv, strerror(errno)); + + /* Set up the db structure as necessary. */ + if (infoarg == NULL) + infop = NULL; + else + for (p = strtok(infoarg, ",\t "); p != NULL; + p = strtok(0, ",\t ")) + if (*p != '\0') + infop = setinfo(type, p); + + /* + * Open the DB. Delete any preexisting copy, you almost never + * want it around, and it often screws up tests. + */ + if (fname == NULL) { + p = getenv("TMPDIR"); + if (p == NULL) + p = "/var/tmp"; + (void)snprintf(buf, sizeof(buf), "%s/__dbtest", p); + fname = buf; + (void)unlink(buf); + } else if (!sflag) + (void)unlink(fname); + + if ((dbp = dbopen(fname, + oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL) + err("dbopen: %s", strerror(errno)); + XXdbp = dbp; + + state = COMMAND; + for (lineno = 1; + (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) { + /* Delete the newline, displaying the key/data is easier. */ + if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL) + *t = '\0'; + if ((len = strlen(buf)) == 0 || isspace((int) *p) || *p == '#') + continue; + + /* Convenient gdb break point. */ + if (XXlineno == lineno) + XXlineno = 1; + switch (*p) { + case 'c': /* compare */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + state = KEY; + command = COMPARE; + break; + case 'e': /* echo */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + /* Don't display the newline, if CR at EOL. */ + if (p[len - 2] == '\r') + --len; + if (write(ofd, p + 1, len - 1) != (ssize_t)len - 1 || + write(ofd, "\n", 1) != 1) + err("write: %s", strerror(errno)); + break; + case 'g': /* get */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + state = KEY; + command = GET; + break; + case 'p': /* put */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + state = KEY; + command = PUT; + break; + case 'r': /* remove */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + if (flags == R_CURSOR) { + rem(dbp, &key); + state = COMMAND; + } else { + state = KEY; + command = REMOVE; + } + break; + case 'S': /* sync */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + synk(dbp); + state = COMMAND; + break; + case 's': /* seq */ + if (state != COMMAND) + err("line %lu: not expecting command", lineno); + if (flags == R_CURSOR) { + state = KEY; + command = SEQ; + } else + seq(dbp, &key); + break; + case 'f': + flags = setflags(p + 1); + break; + case 'D': /* data file */ + if (state != DATA) + err("line %lu: not expecting data", lineno); + data.data = rfile(p + 1, &data.size); + goto ldata; + case 'd': /* data */ + if (state != DATA) + err("line %lu: not expecting data", lineno); + data.data = xmalloc(p + 1, len - 1); + data.size = len - 1; +ldata: switch (command) { + case COMPARE: + compare(&keydata, &data); + break; + case PUT: + put(dbp, &key, &data); + break; + default: + err("line %lu: command doesn't take data", + lineno); + } + if (type != DB_RECNO) + free(key.data); + free(data.data); + state = COMMAND; + break; + case 'K': /* key file */ + if (state != KEY) + err("line %lu: not expecting a key", lineno); + if (type == DB_RECNO) + err("line %lu: 'K' not available for recno", + lineno); + key.data = rfile(p + 1, &key.size); + goto lkey; + case 'k': /* key */ + if (state != KEY) + err("line %lu: not expecting a key", lineno); + if (type == DB_RECNO) { + static recno_t recno; + recno = atoi(p + 1); + key.data = &recno; + key.size = sizeof(recno); + } else { + key.data = xmalloc(p + 1, len - 1); + key.size = len - 1; + } +lkey: switch (command) { + case COMPARE: + getdata(dbp, &key, &keydata); + state = DATA; + break; + case GET: + get(dbp, &key); + if (type != DB_RECNO) + free(key.data); + state = COMMAND; + break; + case PUT: + state = DATA; + break; + case REMOVE: + rem(dbp, &key); + if ((type != DB_RECNO) && (flags != R_CURSOR)) + free(key.data); + state = COMMAND; + break; + case SEQ: + seq(dbp, &key); + if ((type != DB_RECNO) && (flags != R_CURSOR)) + free(key.data); + state = COMMAND; + break; + default: + err("line %lu: command doesn't take a key", + lineno); + } + break; + case 'o': + dump(dbp, p[1] == 'r', 0); + break; + case 'O': + dump(dbp, p[1] == 'r', 1); + break; + case 'u': + unlinkpg(dbp); + break; + default: + err("line %lu: %s: unknown command character", + lineno, p); + } + } +#ifdef STATISTICS + /* + * -l must be used (DB_LOCK must be set) for this to be + * used, otherwise a page will be locked and it will fail. + */ + if (type == DB_BTREE && oflags & DB_LOCK) + __bt_stat(dbp); +#endif + if (dbp->close(dbp)) + err("db->close: %s", strerror(errno)); + (void)close(ofd); + exit(0); +} + +#define NOOVERWRITE "put failed, would overwrite key\n" + +void +compare(db1, db2) + DBT *db1, *db2; +{ + size_t len; + u_char *p1, *p2; + + if (db1->size != db2->size) { + printf("compare failed: key->data len %lu != data len %lu\n", + (u_long) db1->size, (u_long) db2->size); + exit (1); + } + + len = MIN(db1->size, db2->size); + for (p1 = db1->data, p2 = db2->data; len--;) + if (*p1++ != *p2++) { + err("compare failed at offset %d\n", + (int)(p1 - (u_char *)db1->data)); + break; + } +} + +void +get(dbp, kp) + DB *dbp; + DBT *kp; +{ + DBT data; + + switch (dbp->get(dbp, kp, &data, flags)) { + case 0: + if (write(ofd, data.data, data.size) != (ssize_t)data.size) + err("write: %s", strerror(errno)); + if (ofd == STDOUT_FILENO) { + if (write(ofd, "\n", 1) != 1) + err("write: %s", strerror(errno)); + } + break; + case -1: + err("line %lu: get: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: +#define NOSUCHKEY "get failed, no such key\n" + if (ofd != STDOUT_FILENO) { + if (write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1) != + sizeof(NOSUCHKEY) - 1) + err("write: %s", strerror(errno)); + exit(1); + } else + (void)fprintf(stderr, "%lu: %.*s: %s", + lineno, (int) MIN(kp->size, 20), (char *) kp->data, + NOSUCHKEY); +#undef NOSUCHKEY + break; + } +} + +void +getdata(dbp, kp, dp) + DB *dbp; + DBT *kp, *dp; +{ + switch (dbp->get(dbp, kp, dp, flags)) { + case 0: + return; + case -1: + err("line %lu: getdata: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: + err("line %lu: getdata failed, no such key", lineno); + /* NOTREACHED */ + } +} + +void +put(dbp, kp, dp) + DB *dbp; + DBT *kp, *dp; +{ + switch (dbp->put(dbp, kp, dp, flags)) { + case 0: + break; + case -1: + err("line %lu: put: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: + if (write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1) != + sizeof(NOOVERWRITE) - 1) + err("write: %s", strerror(errno)); + break; + } +} + +void +rem(dbp, kp) + DB *dbp; + DBT *kp; +{ + switch (dbp->del(dbp, kp, flags)) { + case 0: + break; + case -1: + err("line %lu: rem: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: +#define NOSUCHKEY "rem failed, no such key\n" + if (ofd != STDOUT_FILENO) { + if (write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1) != + sizeof(NOSUCHKEY) - 1) + err("write: %s", strerror(errno)); + } else if (flags != R_CURSOR) + (void)fprintf(stderr, "%lu: %.*s: %s", + lineno, (int) MIN(kp->size, 20), (char *) kp->data, + NOSUCHKEY); + else + (void)fprintf(stderr, + "%lu: rem of cursor failed\n", lineno); +#undef NOSUCHKEY + break; + } +} + +void +synk(dbp) + DB *dbp; +{ + switch (dbp->sync(dbp, flags)) { + case 0: + break; + case -1: + err("line %lu: synk: %s", lineno, strerror(errno)); + /* NOTREACHED */ + } +} + +void +seq(dbp, kp) + DB *dbp; + DBT *kp; +{ + DBT data; + + switch (dbp->seq(dbp, kp, &data, flags)) { + case 0: + if (write(ofd, data.data, data.size) != (ssize_t)data.size) + err("write: %s", strerror(errno)); + if (ofd == STDOUT_FILENO) + if (write(ofd, "\n", 1) != 1) + err("write: %s", strerror(errno)); + break; + case -1: + err("line %lu: seq: %s", lineno, strerror(errno)); + /* NOTREACHED */ + case 1: +#define NOSUCHKEY "seq failed, no such key\n" + if (ofd != STDOUT_FILENO) { + if (write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1) != + sizeof(NOSUCHKEY) - 1) + err("write: %s", strerror(errno)); + } else if (flags == R_CURSOR) + (void)fprintf(stderr, "%lu: %.*s: %s", + lineno, (int) MIN(kp->size, 20), (char *) kp->data, + NOSUCHKEY); + else + (void)fprintf(stderr, + "%lu: seq (%s) failed\n", lineno, sflags(flags)); +#undef NOSUCHKEY + break; + } +} + +void +dump(dbp, rev, recurse) + DB *dbp; + int rev; + int recurse; +{ + DBT key, data; + int lflags, nflags; + + if (rev) { + lflags = R_LAST; + nflags = recurse ? R_RPREV : R_PREV; + } else { + lflags = R_FIRST; + nflags = recurse ? R_RNEXT : R_NEXT; + } + for (;; lflags = nflags) + switch (dbp->seq(dbp, &key, &data, lflags)) { + case 0: + if (write(ofd, data.data, data.size) != + (ssize_t)data.size) + err("write: %s", strerror(errno)); + if (ofd == STDOUT_FILENO) { + if (write(ofd, "\n", 1) != 1) + err("write: %s", strerror(errno)); + } + break; + case 1: + goto done; + case -1: + err("line %lu: (dump) seq: %s", + lineno, strerror(errno)); + /* NOTREACHED */ + } +done: return; +} + +void +unlinkpg(dbp) + DB *dbp; +{ + BTREE *t = dbp->internal; + PAGE *h = NULL; + db_pgno_t pg; + + for (pg = P_ROOT; pg < t->bt_mp->npages; + mpool_put(t->bt_mp, h, 0), pg++) { + if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) + break; + /* Look for a nonempty leaf page that has both left + * and right siblings. */ + if (h->prevpg == P_INVALID || h->nextpg == P_INVALID) + continue; + if (NEXTINDEX(h) == 0) + continue; + if ((h->flags & (P_BLEAF | P_RLEAF))) + break; + } + if (h == NULL || pg == t->bt_mp->npages) { + fprintf(stderr, "unlinkpg: no appropriate page found\n"); + return; + } + if (__bt_relink(t, h) != 0) { + perror("unlinkpg"); + goto cleanup; + } + h->prevpg = P_INVALID; + h->nextpg = P_INVALID; +cleanup: + mpool_put(t->bt_mp, h, MPOOL_DIRTY); +} + +u_int +setflags(s) + char *s; +{ + char *p; + + for (; isspace((int) *s); ++s); + if (*s == '\n' || *s == '\0') + return (0); + if ((p = strchr(s, '\n')) != NULL) + *p = '\0'; + if (!strcmp(s, "R_CURSOR")) return (R_CURSOR); + if (!strcmp(s, "R_FIRST")) return (R_FIRST); + if (!strcmp(s, "R_IAFTER")) return (R_IAFTER); + if (!strcmp(s, "R_IBEFORE")) return (R_IBEFORE); + if (!strcmp(s, "R_LAST")) return (R_LAST); + if (!strcmp(s, "R_NEXT")) return (R_NEXT); + if (!strcmp(s, "R_NOOVERWRITE")) return (R_NOOVERWRITE); + if (!strcmp(s, "R_PREV")) return (R_PREV); + if (!strcmp(s, "R_SETCURSOR")) return (R_SETCURSOR); + + err("line %lu: %s: unknown flag", lineno, s); + /* NOTREACHED */ +} + +char * +sflags(lflags) + int lflags; +{ + switch (lflags) { + case R_CURSOR: return ("R_CURSOR"); + case R_FIRST: return ("R_FIRST"); + case R_IAFTER: return ("R_IAFTER"); + case R_IBEFORE: return ("R_IBEFORE"); + case R_LAST: return ("R_LAST"); + case R_NEXT: return ("R_NEXT"); + case R_NOOVERWRITE: return ("R_NOOVERWRITE"); + case R_PREV: return ("R_PREV"); + case R_SETCURSOR: return ("R_SETCURSOR"); + } + + return ("UNKNOWN!"); +} + +DBTYPE +dbtype(s) + char *s; +{ + if (!strcmp(s, "btree")) + return (DB_BTREE); + if (!strcmp(s, "hash")) + return (DB_HASH); + if (!strcmp(s, "recno")) + return (DB_RECNO); + err("%s: unknown type (use btree, hash or recno)", s); + /* NOTREACHED */ +} + +void * +setinfo(db_type, s) + DBTYPE db_type; + char *s; +{ + static BTREEINFO ib; + static HASHINFO ih; + static RECNOINFO rh; + char *eq; + + if ((eq = strchr(s, '=')) == NULL) + err("%s: illegal structure set statement", s); + *eq++ = '\0'; + if (!isdigit((int) *eq)) + err("%s: structure set statement must be a number", s); + + switch (db_type) { + case DB_BTREE: + if (!strcmp("flags", s)) { + ib.flags = atoi(eq); + return (&ib); + } + if (!strcmp("cachesize", s)) { + ib.cachesize = atoi(eq); + return (&ib); + } + if (!strcmp("maxkeypage", s)) { + ib.maxkeypage = atoi(eq); + return (&ib); + } + if (!strcmp("minkeypage", s)) { + ib.minkeypage = atoi(eq); + return (&ib); + } + if (!strcmp("lorder", s)) { + ib.lorder = atoi(eq); + return (&ib); + } + if (!strcmp("psize", s)) { + ib.psize = atoi(eq); + return (&ib); + } + break; + case DB_HASH: + if (!strcmp("bsize", s)) { + ih.bsize = atoi(eq); + return (&ih); + } + if (!strcmp("ffactor", s)) { + ih.ffactor = atoi(eq); + return (&ih); + } + if (!strcmp("nelem", s)) { + ih.nelem = atoi(eq); + return (&ih); + } + if (!strcmp("cachesize", s)) { + ih.cachesize = atoi(eq); + return (&ih); + } + if (!strcmp("lorder", s)) { + ih.lorder = atoi(eq); + return (&ih); + } + break; + case DB_RECNO: + if (!strcmp("flags", s)) { + rh.flags = atoi(eq); + return (&rh); + } + if (!strcmp("cachesize", s)) { + rh.cachesize = atoi(eq); + return (&rh); + } + if (!strcmp("lorder", s)) { + rh.lorder = atoi(eq); + return (&rh); + } + if (!strcmp("reclen", s)) { + rh.reclen = atoi(eq); + return (&rh); + } + if (!strcmp("bval", s)) { + rh.bval = atoi(eq); + return (&rh); + } + if (!strcmp("psize", s)) { + rh.psize = atoi(eq); + return (&rh); + } + break; + } + err("%s: unknown structure value", s); + /* NOTREACHED */ +} + +void * +rfile(name, lenp) + char *name; + size_t *lenp; +{ + struct stat sb; + void *p; + int fd; + char *np; + + for (; isspace((int) *name); ++name); + if ((np = strchr(name, '\n')) != NULL) + *np = '\0'; + if ((fd = open(name, O_RDONLY, 0)) < 0 || + fstat(fd, &sb)) + err("%s: %s\n", name, strerror(errno)); +#ifdef NOT_PORTABLE + if (sb.st_size > (off_t)SIZE_T_MAX) + err("%s: %s\n", name, strerror(E2BIG)); +#endif + if ((p = (void *)malloc((u_int)sb.st_size)) == NULL) + err("%s", strerror(errno)); + if (read(fd, p, (int)sb.st_size) == -1) + err("%s", strerror(errno)); + *lenp = sb.st_size; + (void)close(fd); + return (p); +} + +void * +xmalloc(text, len) + char *text; + size_t len; +{ + void *p; + + if ((p = (void *)malloc(len)) == NULL) + err("%s", strerror(errno)); + memmove(p, text, len); + return (p); +} + +void +usage() +{ + (void)fprintf(stderr, + "usage: dbtest [-l] [-f file] [-i info] [-o file] type script\n"); + exit(1); +} + +#include + +void +err(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + (void)fprintf(stderr, "dbtest: "); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); + exit(1); + /* NOTREACHED */ +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/deps b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/dictionary b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/dictionary new file mode 100644 index 00000000..53640f01 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/dictionary @@ -0,0 +1,308 @@ +abintrme +ablatweo +agdbevea +aglamber +aicehayt +alerover +anadanth +ancmirtt +ancthada +angcther +antasikt +arathmsm +arescofa +arthatea +asallyth +asathedl +ascelass +athaneal +atheneri +atheryit +athiopep +athysidc +atyhtiti +auletard +aytthepr +bedthesa +beiofttw +bemofrda +bertedud +bessdide +bestiemb +blllanof +bllssunt +blstther +bttelthh +bulyousi +bupedire +buseatsd +butritat +byeditam +cedvecur +censaith +centhfro +centitar +ceourire +cetheaso +chancora +chavengl +chederas +chemsywh +civadayo +ckedacag +ckstiptr +colither +congchin +corepppl +cronoria +cthilath +cthouthe +ctofowon +cumetbry +dbethere +degeerin +detherai +dingthin +dryslyse +dscesild +ealecerm +edftserh +efosondi +eherrreg +emidesja +ereananm +estersns +etedtili +evermerh +falsuran +faringsi +fawerist +fcedethe +fedhessh +fedlerca +feupbori +ffeedift +fllbasia +foftabll +fomehage +fotsenki +fwisudls +ggeuptha +gswofryt +hedcecou +hereacun +huvedpth +iabengre +ianfovin +iaresice +iasmived +idengedi +ilftisut +ilinefem +imeorran +imsstoft +inararto +indanrei +ingelaly +ingeored +inmotiom +inoatlfr +inoviler +insedihe +intaspan +intowade +inyfeprt +iobloinc +ionepuse +iourofig +ireeingi +irreland +irsfandb +isewhell +isocisad +isriacth +istaverr +ithmblet +itoingri +itongala +itsgrint +ivyttisa +laltthea +lanesmef +lanonepi +lerithay +lllmeris +lysatspa +lysceert +masishio +mathmmat +meastrei +medengny +medwindb +membonam +moronash +mpeotlin +msomirei +msrmstri +mstirtis +nbempeef +ncheckno +nddtthec +ndilymor +nditheiv +ndoncath +nenkingo +ngryasth +nichelnd +nndarrof +nongeatt +noviearc +npecheca +nsttmema +nwiowhan +oalsaldt +obullury +odtenens +offorind +ofoditin +ogarofab +olossofe +olspooth +omajorul +omantrvi +omawevat +onotorit +oorendbe +oosarang +othowong +otinffte +ouatheno +ountshep +ouputope +owhesatu +owiaindh +padisath +pangream +pawicofa +pendamam +pepofond +peroncti +perysege +petotith +plocarov +pomasbor +powholyi +ppllosof +pptinoma +psenesff +puiondit +reestand +rendlabl +rerathsy +rewathat +rirndiff +ritricui +samasome +satameer +sathecur +sbespral +sconbeis +sedfinhe +sharveon +shhoftrd +sianthem +sieaveve +simedera +sinandff +sinulsma +sllobofl +sndfermh +soffatic +soingris +songiorb +sthottsa +suewemat +swicales +tagttisf +tanalatt +tancodbo +tarethal +tbisesia +teftyall +tengstwh +tepeshth +teranand +tevinohi +tgthehal +thansirs +thecequs +thereaco +therimut +therorea +thestiom +theveame +thhastth +thiasatt +thidirve +thingbaa +thithbed +thovires +thswenpe +thublthe +tiamarss +tincthes +tindtofo +tinedave +tisanwex +tlarnste +tleicorb +tnymesie +toftemal +tombeasw +torarsen +totheheo +toudanty +tremywel +treonove +trhandfy +trrhmont +trysnter +tssasofo +ttemaith +ttiserds +ttorissa +tuiabeoi +twirfton +tyhentha +tyngorti +tyoarich +ucatbouc +ungyconh +untinore +uopsaren +upecmuit +ureaidrb +usinittr +ussofedt +usunochp +utbapofo +veveplel +vimathea +walondui +wavairet +waysioft +wceempil +wealttig +wefondio +werdtian +weswevar +whaclthe +wheanler +wheiforv +whisurtr +whrithat +wiesulci +wirofrec +witthile +wtserodr +ybutherr diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/Makefile b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/Makefile new file mode 100644 index 00000000..348a8f81 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/Makefile @@ -0,0 +1,43 @@ +# @(#)Makefile 8.16 (Berkeley) 11/20/95 + +ALL = driver2 tcreat3 tdel thash4 tread2 tseq tverify +OBJ = driver2.o tcreat3.o tdel.o thash4.o tread2.o tseq.o tverify.o +CC = gcc + +all: ${ALL} + +# Uncomment the STAT line get hash and btree statistical use info. This +# also forces ld to load the btree debug functions for use by gdb, which +# is useful. The db library has to be compiled with -DSTATISTICS as well. +INC= -I${PORTDIR}/include -I${PORTDIR} +OORG= -g +#STAT= -DSTATISTICS +CFLAGS= -D__DBINTERFACE_PRIVATE -DDEBUG ${STAT} ${OORG} ${INC} + +tcreat3: tcreat3.o ${PORTDIR}/libdb.a + ${CC} -o $@ tcreat3.o ${PORTDIR}/libdb.a + +tdel: tdel.o ${PORTDIR}/libdb.a + ${CC} -o $@ tdel.o ${PORTDIR}/libdb.a + +thash4: thash4.o ${PORTDIR}/libdb.a + ${CC} -o $@ thash4.o ${PORTDIR}/libdb.a + +tread2: tread2.o ${PORTDIR}/libdb.a + ${CC} -o $@ tread2.o ${PORTDIR}/libdb.a + +tseq: tseq.o ${PORTDIR}/libdb.a + ${CC} -o $@ tseq.o ${PORTDIR}/libdb.a + +tverify: tverify.o ${PORTDIR}/libdb.a + ${CC} -o $@ tverify.o ${PORTDIR}/libdb.a + +driver2: driver2.o ${PORTDIR}/libdb.a + ${CC} -o $@ driver2.o ${PORTDIR}/libdb.a + +strerror.o: ${PORTDIR}/clib/strerror.c + ${CC} -c ${PORTDIR}/clib/strerror.c + +clean: + rm -f *.core gmon.out ${ALL} ${OBJ} t1 t2 t3 + diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/driver2.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/driver2.c new file mode 100644 index 00000000..02982b16 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/driver2.c @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)driver2.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +/* + * Test driver, to try to tackle the large ugly-split problem. + */ + +#include +#include +#include "ndbm.h" + +int my_hash(key, len) + char *key; + int len; +{ + return(17); /* So I'm cruel... */ +} + +main(argc, argv) + int argc; +{ + DB *db; + DBT key, content; + char keybuf[2049]; + char contentbuf[2049]; + char buf[256]; + int i; + HASHINFO info; + + info.bsize = 1024; + info.ffactor = 5; + info.nelem = 1; + info.cachesize = NULL; +#ifdef HASH_ID_PROGRAM_SPECIFIED + info.hash_id = HASH_ID_PROGRAM_SPECIFIED; + info.hash_func = my_hash; +#else + info.hash = my_hash; +#endif + info.lorder = 0; + if (!(db = dbopen("bigtest", O_RDWR | O_CREAT | O_BINARY, 0644, DB_HASH, &info))) { + snprintf(buf, sizeof(buf), "dbopen: failed on file bigtest"); + perror(buf); + exit(1); + } + srand(17); + key.data = keybuf; + content.data = contentbuf; + memset(keybuf, '\0', sizeof(keybuf)); + memset(contentbuf, '\0', sizeof(contentbuf)); + for (i=1; i <= 500; i++) { + key.size = 128 + (rand()&1023); + content.size = 128 + (rand()&1023); +/* printf("%d: Key size %d, data size %d\n", i, key.size, + content.size); */ + snprintf(keybuf, sizeof(keybuf), "Key #%d", i); + snprintf(contentbuf, sizeof(contentbuf), "Contents #%d", i); + if ((db->put)(db, &key, &content, R_NOOVERWRITE)) { + snprintf(buf, sizeof(buf), "dbm_store #%d", i); + perror(buf); + } + } + if ((db->close)(db)) { + perror("closing hash file"); + exit(1); + } + exit(0); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/makedb.sh b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/makedb.sh new file mode 100644 index 00000000..15901de1 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/makedb.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# +# @(#)makedb.sh 8.1 (Berkeley) 6/4/93 + +awk '{i++; print $0; print i;}' /usr/local/lib/dict/words > WORDS +ls /bin /usr/bin /usr/ucb /etc | egrep '^(...|....|.....|......)$' | \ +sort | uniq | \ +awk '{ + printf "%s\n", $0 + for (i = 0; i < 1000; i++) + printf "%s+", $0 + printf "\n" +}' > LONG.DATA diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tcreat3.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tcreat3.c new file mode 100644 index 00000000..6767de5e --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tcreat3.c @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tcreat3.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include +#include "db-int.h" + +#define INITIAL 25000 +#define MAXWORDS 25000 /* # of elements in search table */ + +char wp1[8192]; +char wp2[8192]; +main(argc, argv) +char **argv; +{ + DBT item, key; + DB *dbp; + HASHINFO ctl; + FILE *fp; + int trash; + + int i = 0; + + argv++; + ctl.hash = NULL; + ctl.bsize = atoi(*argv++); + ctl.ffactor = atoi(*argv++); + ctl.nelem = atoi(*argv++); + ctl.lorder = 0; + if (!(dbp = dbopen( "hashtest", + O_CREAT|O_TRUNC|O_RDWR|O_BINARY, 0600, DB_HASH, &ctl))){ + /* create table */ + fprintf(stderr, "cannot create: hash table (size %d)\n", + INITIAL); + exit(1); + } + + key.data = wp1; + item.data = wp2; + while ( fgets(wp1, 8192, stdin) && + fgets(wp2, 8192, stdin) && + i++ < MAXWORDS) { +/* +* put info in structure, and structure in the item +*/ + key.size = strlen(wp1); + item.size = strlen(wp2); + +/* + * enter key/data pair into the table + */ + if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) { + fprintf(stderr, "cannot enter: key %s\n", + item.data); + exit(1); + } + } + + (dbp->close)(dbp); + exit(0); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tdel.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tdel.c new file mode 100644 index 00000000..32d8250f --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tdel.c @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tdel.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include "db-int.h" +#include + +#define INITIAL 25000 +#define MAXWORDS 25000 /* # of elements in search table */ + +/* Usage: thash pagesize fillfactor file */ +char wp1[8192]; +char wp2[8192]; +main(argc, argv) +char **argv; +{ + DBT item, key; + DB *dbp; + HASHINFO ctl; + FILE *fp; + int stat; + + int i = 0; + + argv++; + ctl.nelem = INITIAL; + ctl.hash = NULL; + ctl.bsize = atoi(*argv++); + ctl.ffactor = atoi(*argv++); + ctl.cachesize = 1024 * 1024; /* 1 MEG */ + ctl.lorder = 0; + argc -= 2; + if (!(dbp = dbopen( NULL, O_CREAT|O_RDWR|O_BINARY, 0400, DB_HASH, &ctl))) { + /* create table */ + fprintf(stderr, "cannot create: hash table size %d)\n", + INITIAL); + exit(1); + } + + key.data = wp1; + item.data = wp2; + while ( fgets(wp1, 8192, stdin) && + fgets(wp2, 8192, stdin) && + i++ < MAXWORDS) { +/* +* put info in structure, and structure in the item +*/ + key.size = strlen(wp1); + item.size = strlen(wp2); + +/* + * enter key/data pair into the table + */ + if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) { + fprintf(stderr, "cannot enter: key %s\n", + item.data); + exit(1); + } + } + + if ( --argc ) { + fp = fopen ( argv[0], "r"); + i = 0; + while ( fgets(wp1, 8192, fp) && + fgets(wp2, 8192, fp) && + i++ < MAXWORDS) { + key.size = strlen(wp1); + stat = (dbp->del)(dbp, &key, 0); + if (stat) { + fprintf ( stderr, "Error retrieving %s\n", key.data ); + exit(1); + } + } + fclose(fp); + } + (dbp->close)(dbp); + exit(0); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/testit b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/testit new file mode 100644 index 00000000..c80dc4e6 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/testit @@ -0,0 +1,154 @@ +#!/bin/csh -f +# +# @(#)testit 8.1 (Berkeley) 6/4/93 +# + +echo "" +echo "PAGE FILL " +set name=WORDS + set i = 256 + foreach j ( 11 14 21 ) + echo "thash4 $i $j" + ./thash4 $i $j 25000 65536 $name < $name + end + set i = 512 + foreach j ( 21 28 43 ) + echo "thash4 $i $j" + ./thash4 $i $j 25000 65536 $name < $name + end + set i = 1024 + foreach j ( 43 57 85 ) + echo "thash4 $i $j" + ./thash4 $i $j 25000 65536 $name < $name + end + set i = 2048 + foreach j ( 85 114 171 ) + echo "thash4 $i $j" + ./thash4 $i $j 25000 65536 $name < $name + end + set i = 4096 + foreach j ( 171 228 341 ) + echo "thash4 $i $j" + ./thash4 $i $j 25000 65536 $name < $name + end + set i = 8192 + foreach j ( 341 455 683 ) + echo "thash4 $i $j" + ./thash4 $i $j 25000 65536 $name < $name + end + echo "PAGE FILL " + set i = 256 + foreach j ( 11 14 21 ) + echo "$i"_"$j" + ./tcreat3 $i $j 25000 $name < $name + ./tread2 65536 < $name + ./tverify $name < $name + ./tseq > /dev/null + ./tdel $i $j $name < $name + end + set i = 512 + foreach j ( 21 28 43 ) + echo "$i"_"$j" + ./tcreat3 $i $j 25000 $name < $name + ./tread2 65536 < $name + ./tverify $name < $name + ./tseq > /dev/null + ./tdel $i $j $name < $name + end + set i = 1024 + foreach j ( 43 57 85 ) + echo "$i"_"$j" + ./tcreat3 $i $j 25000 $name < $name + ./tread2 65536 < $name + ./tverify $name < $name + ./tseq > /dev/null + ./tdel $i $j $name < $name + end + set i = 2048 + foreach j ( 85 114 171 ) + echo "$i"_"$j" + ./tcreat3 $i $j 25000 $name < $name + ./tread2 65536 < $name + ./tverify $name < $name + ./tseq > /dev/null + ./tdel $i $j $name < $name + end + set i = 4096 + foreach j ( 171 228 341 ) + echo "$i"_"$j" + ./tcreat3 $i $j 25000 $name < $name + ./tread2 65536 < $name + ./tverify $name < $name + ./tseq > /dev/null + ./tdel $i $j $name < $name + end + set i = 8192 + foreach j ( 341 455 683 ) + echo "$i"_"$j" + ./tcreat3 $i $j 25000 $name < $name + ./tread2 65536 < $name + ./tverify $name < $name + ./tseq > /dev/null + ./tdel $i $j $name < $name + end +set name=LONG.DATA + set i = 1024 + foreach j ( 1 2 4 ) + echo ./thash4 $i $j 600 65536 $name + ./thash4 $i $j 600 65536 $name < $name + end + + set i = 2048 + foreach j ( 1 2 4 ) + echo ./thash4 $i $j 600 65536 $name + ./thash4 $i $j 600 65536 $name < $name + end + set i = 4096 + foreach j ( 1 2 4 ) + echo ./thash4 $i $j 600 65536 $name + ./thash4 $i $j 600 65536 $name < $name + end + set i = 8192 + foreach j ( 2 4 8 ) + echo ./thash4 $i $j 600 65536 $name + ./thash4 $i $j 600 65536 $name < $name + end + echo "PAGE FILL " + set i = 1024 + foreach j ( 1 2 4 ) + echo "$i"_"$j" + ./tcreat3 $i $j 600 $name < $name + ./tread2 65536 < $name + ./tverify $name < $name + ./tseq > /dev/null + ./tdel $i $j $name < $name + end + set i = 2048 + foreach j ( 1 2 4 ) + echo "$i"_"$j" + ./tcreat3 $i $j 600 $name < $name + ./tread2 65536 < $name + ./tverify $name < $name + ./tseq > /dev/null + ./tdel $i $j $name < $name + end + set i = 4096 + foreach j ( 1 2 4 ) + echo "$i"_"$j" + ./tcreat3 $i $j 600 $name < $name + ./tread2 65536 < $name + ./tverify $name < $name + ./tseq > /dev/null + ./tdel $i $j $name < $name + end + set i = 8192 + foreach j ( 2 4 8 ) + echo "$i"_"$j" + ./tcreat3 $i $j 600 $name < $name + ./tread2 65536 < $name + ./tverify $name < $name + ./tseq > /dev/null + ./tdel $i $j $name < $name + end + +./driver2 diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/thash4.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/thash4.c new file mode 100644 index 00000000..830d7a18 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/thash4.c @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)thash4.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include +#include +#include "db-int.h" + +#define INITIAL 25000 +#define MAXWORDS 25000 /* # of elements in search table */ + +/* Usage: thash pagesize fillfactor file */ +char wp1[8192]; +char wp2[8192]; +main(argc, argv) +char **argv; +{ + DBT item, key, res; + DB *dbp; + HASHINFO ctl; + FILE *fp; + int stat; + time_t t; + + int i = 0; + + argv++; + ctl.hash = NULL; + ctl.bsize = atoi(*argv++); + ctl.ffactor = atoi(*argv++); + ctl.nelem = atoi(*argv++); + ctl.cachesize = atoi(*argv++); + ctl.lorder = 0; + if (!(dbp = dbopen( NULL, O_CREAT|O_RDWR|O_BINARY, 0400, DB_HASH, &ctl))) { + /* create table */ + fprintf(stderr, "cannot create: hash table size %d)\n", + INITIAL); + fprintf(stderr, "\terrno: %d\n", errno); + exit(1); + } + + key.data = wp1; + item.data = wp2; + while ( fgets(wp1, 8192, stdin) && + fgets(wp2, 8192, stdin) && + i++ < MAXWORDS) { +/* +* put info in structure, and structure in the item +*/ + key.size = strlen(wp1); + item.size = strlen(wp2); + +/* + * enter key/data pair into the table + */ + if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) { + fprintf(stderr, "cannot enter: key %s\n", + item.data); + fprintf(stderr, "\terrno: %d\n", errno); + exit(1); + } + } + + if ( --argc ) { + fp = fopen ( argv[0], "r"); + i = 0; + while ( fgets(wp1, 256, fp) && + fgets(wp2, 8192, fp) && + i++ < MAXWORDS) { + + key.size = strlen(wp1); + stat = (dbp->get)(dbp, &key, &res, 0); + if (stat < 0 ) { + fprintf ( stderr, "Error retrieving %s\n", key.data ); + fprintf(stderr, "\terrno: %d\n", errno); + exit(1); + } else if ( stat > 0 ) { + fprintf ( stderr, "%s not found\n", key.data ); + fprintf(stderr, "\terrno: %d\n", errno); + exit(1); + } + } + fclose(fp); + } + dbp->close(dbp); + exit(0); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tread2.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tread2.c new file mode 100644 index 00000000..1e2cc4c5 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tread2.c @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tread2.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include +#include "db-int.h" + +#define INITIAL 25000 +#define MAXWORDS 25000 /* # of elements in search table */ + +typedef struct { /* info to be stored */ + int num, siz; +} info; + +char wp1[8192]; +char wp2[8192]; +main(argc, argv) +char **argv; +{ + DBT item, key, res; + DB *dbp; + HASHINFO ctl; + int stat; + + int i = 0; + + ctl.nelem = INITIAL; + ctl.hash = NULL; + ctl.bsize = 64; + ctl.ffactor = 1; + ctl.cachesize = atoi(*argv++); + ctl.lorder = 0; + if (!(dbp = dbopen( "hashtest", O_RDONLY|O_BINARY, 0400, DB_HASH, &ctl))) { + /* create table */ + fprintf(stderr, "cannot open: hash table\n" ); + exit(1); + } + + key.data = wp1; + item.data = wp2; + while ( fgets(wp1, 8192, stdin) && + fgets(wp2, 8192, stdin) && + i++ < MAXWORDS) { +/* +* put info in structure, and structure in the item +*/ + key.size = strlen(wp1); + item.size = strlen(wp2); + + stat = (dbp->get)(dbp, &key, &res,0); + if (stat < 0) { + fprintf ( stderr, "Error retrieving %s\n", key.data ); + exit(1); + } else if ( stat > 0 ) { + fprintf ( stderr, "%s not found\n", key.data ); + exit(1); + } + } + (dbp->close)(dbp); + exit(0); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tseq.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tseq.c new file mode 100644 index 00000000..bee41961 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tseq.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tseq.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include +#include "db-int.h" + +#define INITIAL 25000 +#define MAXWORDS 25000 /* # of elements in search table */ + + +char wp[8192]; +char cp[8192]; +main(argc, argv) +char **argv; +{ + DBT item, key, res; + DB *dbp; + FILE *fp; + int stat; + + if (!(dbp = dbopen( "hashtest", O_RDONLY|O_BINARY, 0400, DB_HASH, NULL))) { + /* create table */ + fprintf(stderr, "cannot open: hash table\n" ); + exit(1); + } + +/* +* put info in structure, and structure in the item +*/ + for ( stat = (dbp->seq) (dbp, &res, &item, 1 ); + stat == 0; + stat = (dbp->seq) (dbp, &res, &item, 0 ) ) { + + memcpy ( wp, res.data, res.size ); + wp[res.size] = 0; + memcpy ( cp, item.data, item.size ); + cp[item.size] = 0; + + printf ( "%s %s\n", wp, cp ); + } + (dbp->close)(dbp); + exit(0); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tverify.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tverify.c new file mode 100644 index 00000000..4747804f --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash1.tests/tverify.c @@ -0,0 +1,107 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tverify.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include +#include "db-int.h" + +#define INITIAL 25000 +#define MAXWORDS 25000 /* # of elements in search table */ + +typedef struct { /* info to be stored */ + int num, siz; +} info; + +char wp1[8192]; +char wp2[8192]; +main(argc, argv) +char **argv; +{ + DBT key, res; + DB *dbp; + HASHINFO ctl; + int trash; + int stat; + + int i = 0; + + ctl.nelem = INITIAL; + ctl.hash = NULL; + ctl.bsize = 64; + ctl.ffactor = 1; + ctl.cachesize = 1024 * 1024; /* 1 MEG */ + ctl.lorder = 0; + if (!(dbp = dbopen( "hashtest", O_RDONLY|O_BINARY, 0400, DB_HASH, &ctl))) { + /* create table */ + fprintf(stderr, "cannot open: hash table\n" ); + exit(1); + } + + key.data = wp1; + while ( fgets(wp1, 8192, stdin) && + fgets(wp2, 8192, stdin) && + i++ < MAXWORDS) { +/* +* put info in structure, and structure in the item +*/ + key.size = strlen(wp1); + + stat = (dbp->get)(dbp, &key, &res,0); + if (stat < 0) { + fprintf ( stderr, "Error retrieving %s\n", key.data ); + exit(1); + } else if ( stat > 0 ) { + fprintf ( stderr, "%s not found\n", key.data ); + exit(1); + } + if ( memcmp ( res.data, wp2, res.size ) ) { + fprintf ( stderr, "data for %s is incorrect. Data was %s. Should have been %s\n", key.data, res.data, wp2 ); + } + } + (dbp->close)(dbp); + exit(0); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/README b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/README new file mode 100644 index 00000000..f29ccf7e --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/README @@ -0,0 +1,72 @@ +# @(#)README 8.1 (Berkeley) 6/4/93 + +This package implements a superset of the hsearch and dbm/ndbm libraries. + +Test Programs: + All test programs which need key/data pairs expect them entered + with key and data on separate lines + + tcreat3.c + Takes + bucketsize (bsize), + fill factor (ffactor), and + initial number of elements (nelem). + Creates a hash table named hashtest containing the + keys/data pairs entered from standard in. + thash4.c + Takes + bucketsize (bsize), + fill factor (ffactor), + initial number of elements (nelem) + bytes of cache (ncached), and + file from which to read data (fname) + Creates a table from the key/data pairs on standard in and + then does a read of each key/data in fname + tdel.c + Takes + bucketsize (bsize), and + fill factor (ffactor). + file from which to read data (fname) + Reads each key/data pair from fname and deletes the + key from the hash table hashtest + tseq.c + Reads the key/data pairs in the file hashtest and writes them + to standard out. + tread2.c + Takes + butes of cache (ncached). + Reads key/data pairs from standard in and looks them up + in the file hashtest. + tverify.c + Reads key/data pairs from standard in, looks them up + in the file hashtest, and verifies that the data is + correct. + +NOTES: + +The file search.h is provided for using the hsearch compatible interface +on BSD systems. On System V derived systems, search.h should appear in +/usr/include. + +The man page ../man/db.3 explains the interface to the hashing system. +The file hash.ps is a postscript copy of a paper explaining +the history, implementation, and performance of the hash package. + +"bugs" or idiosyncracies + +If you have a lot of overflows, it is possible to run out of overflow +pages. Currently, this will cause a message to be printed on stderr. +Eventually, this will be indicated by a return error code. + +If you are using the ndbm interface and exit without flushing or closing the +file, you may lose updates since the package buffers all writes. Also, +the db interface only creates a single database file. To avoid overwriting +the user's original file, the suffix ".db" is appended to the file name +passed to dbm_open. Additionally, if your code "knows" about the historic +.dir and .pag files, it will break. + +There is a fundamental difference between this package and the old hsearch. +Hsearch requires the user to maintain the keys and data in the application's +allocated memory while hash takes care of all storage management. The down +side is that the byte strings passed in the ENTRY structure must be null +terminated (both the keys and the data). diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/bigtest.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/bigtest.c new file mode 100644 index 00000000..c8070c50 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/bigtest.c @@ -0,0 +1,75 @@ +#include "db-int.h" +#include +#include +#include +#include + +int +main(void) +{ + HASHINFO info; + DB *db; + DBT key, value, returned; + int *data; + int n, i; + + info.bsize = 512; + info.cachesize = 500; + info.lorder = 0; + info.ffactor = 4; + info.nelem = 0; + info.hash = NULL; + + db = dbopen("big2.db", O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0664, DB_HASH, &info); + data = malloc(800 * sizeof(int)); + for (n = 0; n < 800; n++) + data[n] = 0xDEADBEEF; + key.size = sizeof(int); + key.data = &n; + value.size = 800 * sizeof(int); + value.data = (void *)data; + + for (n = 0; n < 200000; n++) { + returned.data = NULL; + if (n == 4627) + printf(""); + if (n % 50 == 0) + printf("put n = %d\n", n); + if (db->put(db, &key, &value, 0) != 0) + printf("put error, n = %d\n", n); + if (db->get(db, &key, &returned, 0) != 0) + printf("Immediate get error, n = %d\n", n); + assert (returned.size == 3200); + for (i = 0; i < 800; i++) + if (((int *)returned.data)[i] != 0xDEADBEEF) + printf("ERRORRRRRR!!!\n"); + + } + + for (n = 0; n < 200000; n++) { + if (n % 50 == 0) + printf("seq n = %d\n", n); + if ((db->seq(db, &key, &returned, 0)) != 0) + printf("Seq error, n = %d\n", n); + + assert(returned.size == 3200); + + for (i = 0; i < 800; i++) + if (((int *)returned.data)[i] != 0xDEADBEEF) + printf("ERRORRRRRR!!! seq %d\n", n); + } + + for (n = 0; n < 2000; n++) { + if (n % 50 == 0) + printf("get n = %d\n", n); + if (db->get(db, &key, &returned, 0) != 0) + printf("Late get error, n = %d\n", n); + assert(returned.size == 1200); + for (i = 0; i < 300; i++) + if (((int *)returned.data)[i] != 0xDEADBEEF) + printf("ERRORRRRRR!!!, get %d\n", n); + } + db->close(db); + free(value.data); + return(0); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/passtest.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/passtest.c new file mode 100644 index 00000000..43895a42 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/passtest.c @@ -0,0 +1,184 @@ +#include "db-int.h" +#include +#include +#include + +extern int hash_expansions; + +int +main(void) +{ + FILE *keys, *vals; + DB *db; + DBT key, val; + char *key_line, *val_line, *get_key, *get_val, *old, *key2; + HASHINFO passwd; + int n = 0, i = 0, expected; + + key_line = (char *)malloc(100); + val_line = (char *)malloc(300); + old = (char *)malloc(300); + + keys = fopen("yp.keys", "rt"); + vals = fopen("yp.total", "rt"); + + passwd.bsize = 1024; + passwd.cachesize = 1024 * 1024; + passwd.ffactor = 10; + passwd.hash = NULL; + passwd.nelem = 0; + passwd.lorder = 4321; + + + db = dbopen("/usr/tmp/passwd.db", O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0664, DB_HASH, + &passwd); + if (!db) { + fprintf(stderr, "create_db: couldn't create database file\n"); + exit(1); + } + + while ((key_line = fgets(key_line, 100, keys)) != NULL) { + if (n % 1000 == 0) + fprintf(stderr, "Putting #%d.\n", n); + n++; + fgets(val_line, 300, vals); + key.size = strlen(key_line); + key.data = (void *)key_line; + val.size = strlen(val_line); + val.data = (void *)val_line; + if (db->put(db, &key, &val, 0) != 0) + fprintf(stderr, "Put error, n = %d\n", n); + if (db->get(db, &key, &val, 0) != 0) + fprintf(stderr, "Immediate get error, n = %d\n", n); + } + fprintf(stderr, "Done with put!\n"); + free(key_line); + free(val_line); + fclose(keys); + fclose(vals); + db->close(db); + + + + + keys = fopen("yp.keys", "rt"); + vals = fopen("yp.total", "rt"); + get_key = (char *)malloc(100); + get_val = (char *)malloc(300); + + db = dbopen("/usr/tmp/passwd.db", O_RDWR|O_BINARY, 0664, DB_HASH, &passwd); + if (!db) + fprintf(stderr, "Could not open db!\n"); + n = 0; + while ((get_key = fgets(get_key, 100, keys)) != NULL) { + n++; + if (n % 1000 == 0) + fprintf(stderr, "Getting #%d.\n", n); + key.size = strlen(get_key); + key.data = (void *)get_key; + if (db->get(db, &key, &val, 0) != 0) + fprintf(stderr, "Retrieval error on %s\n", get_key); + fgets(get_val, 300, vals); + if (memcmp(val.data, (void *)get_val, val.size)) { + fprintf(stderr, "Unmatched get on %s.\n", get_key); + fprintf(stderr, "Input = %s\nOutput = %s\n", get_val, + (char *)val.data); + } + } + expected = n; + fclose(vals); + fclose(keys); + free(get_key); + free(get_val); + db->close(db); + + + + + get_key = (char *)malloc(100); + get_val = (char *)malloc(300); + + db = dbopen("/usr/tmp/passwd.db", O_RDWR, 0664, DB_HASH, &passwd); + if (!db) + fprintf(stderr, "Could not open db!\n"); + n = 0; + for (;;) { + n++; + if (n % 1000 == 0) + fprintf(stderr, "Sequence getting #%d.\n", n); + if (db->seq(db, &key, &val, 0) != 0) { + fprintf(stderr, + "Exiting sequence retrieve; n = %d, expected = %d\n", + n - 1 , expected); + break; + } + } + free(get_key); + free(get_val); + db->close(db); + + get_key = (char *)malloc(100); + key2 = (char *)malloc(100); + + keys = fopen("yp.keys", "rt"); + vals = fopen("yp.total", "rt"); + + db = dbopen("/usr/tmp/passwd.db", O_RDWR|O_BINARY, 0664, DB_HASH, &passwd); + n = 0; + while ((get_key = fgets(get_key, 100, keys)) != NULL) { + if (n % 1000 == 0) + fprintf(stderr, "Deleting #%d.\n", n); + n+=2; + key2 = fgets(get_key, 100, keys); + if (!key2) + break; + key.data = (void *)key2; + key.size = strlen(key2); + if (db->del(db, &key, 0) != 0) + fprintf(stderr, "Delete error on %d", n); + } + + db->close(db); + free(get_key); + free(key2); + fclose(keys); + fclose(vals); + + get_key = (char *)malloc(100); + key2 = (char *)malloc(100); + get_val = (char *)malloc(300); + + keys = fopen("yp.keys", "rt"); + vals = fopen("yp.total", "rt"); + + db = dbopen("/usr/tmp/passwd.db", O_RDWR|O_BINARY, 0664, DB_HASH, &passwd); + n = 0; + while ((get_key = fgets(get_key, 100, keys)) != NULL) { + n += 2; + if (n % 1000 == 0) + fprintf(stderr, "Re-retrieving #%d.\n", n); + key2 = fgets(key2, 100, keys); + if (!key2) + break; + key.data = (void *)get_key; + key.size = strlen(get_key); + if (db->get(db, &key, &val, 0) != 0) + fprintf(stderr, "Retrieval after delete error on %d\n", n); + fgets(get_val, 300, vals); + if (memcmp(val.data, (void *)get_val, val.size)) { + fprintf(stderr, "Unmatched get after delete on %s.\n", get_key); + fprintf(stderr, "Input = %s\nOutput = %s\n", get_val, + (char *)val.data); + } + fgets(get_val, 300, vals); + } + + db->close(db); + free(get_key); + free(key2); + free(get_val); + fclose(keys); + fclose(vals); + + exit(0); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/passwd/genpass.c b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/passwd/genpass.c new file mode 100644 index 00000000..7d03e609 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/hash2.tests/passwd/genpass.c @@ -0,0 +1,22 @@ +#include +#include + +void +main(int argc, char **argv) +{ + int i,j,n; + char *pass[8], r; + + n = atoi(argv[1]); + + srandom(101173); + for (i = 0; i < n; i++) { + for (j = 0; j < 8; j++) { + r = random() % 122; + while (r < 48) + r += random() % (122 - r); + printf("%c", r); + } + printf("\n"); + } +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/run.test b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/run.test new file mode 100644 index 00000000..ebce8e27 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/run.test @@ -0,0 +1,1036 @@ +#!/bin/sh - +# +# @(#)run.test 8.13 (Berkeley) 11/2/95 +# + +. ./runenv.sh + +# db regression tests +main() +{ + + PROG=./dbtest + TMP1=${TMPDIR-.}/t1 + TMP2=${TMPDIR-.}/t2 + TMP3=${TMPDIR-.}/t3 + BINFILES=${TMPDIR-.}/binfiles + + if [ \! -z "$WORDLIST" -a -f "$WORDLIST" ]; then + DICT=$WORDLIST + elif [ -f /usr/local/lib/dict/words ]; then + DICT=/usr/local/lib/dict/words + elif [ -f /usr/share/dict/words ]; then + DICT=/usr/share/dict/words + elif [ -f /usr/dict/words ]; then + DICT=/usr/dict/words + elif [ -f /usr/share/lib/dict/words ]; then + DICT=/usr/share/lib/dict/words + elif [ -f $srcdir/../test/dictionary ]; then + DICT=`cd $srcdir/../test && pwd`/dictionary + else + echo 'run.test: no dictionary' + exit 1 + fi + + dictsize=`wc -l < $DICT` + + bindir=/bin/. + find $bindir -type f -exec test -r {} \; -print | head -100 > $BINFILES + + if [ $# -eq 0 ]; then + for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20 40 41 50 60 61 62 63; do + test$t + done + else + while [ $# -gt 0 ] + do case "$1" in + test*) + $1;; + [0-9]*) + test$1;; + btree) + for t in 1 2 3 7 8 9 10 12 13 40 41 50 60 61 62 63; do + test$t + done;; + hash) + for t in 1 2 3 8 13 20; do + test$t + done;; + recno) + for t in 1 2 3 4 5 6 7 10 11; do + test$t + done;; + *) + echo "run.test: unknown test $1" + echo "usage: run.test test# | type" + exit 1 + esac + shift + done + fi + rm -f $TMP1 $TMP2 $TMP3 $BINFILES + exit 0 +} + +getnwords() { + # Delete blank lines because the db code appears not to like + # empty keys. Omit lines with non-alphanumeric characters to + # avoid shell metacharacters and non-ASCII characters which + # could cause 'rev' to choke. + LC_ALL=C sed -e '/^$/d' -e '/[^A-Za-z]/d' < $DICT | sed -e ${1}q +} + +# Take the first hundred entries in the dictionary, and make them +# be key/data pairs. +test1() +{ + echo "Test 1: btree, hash: small key, small data pairs" + getnwords 200 > $TMP1 + for type in btree hash; do + rm -f $TMP2 $TMP3 + for i in `cat $TMP1`; do + echo p + echo k$i + echo d$i + echo g + echo k$i + done > $TMP2 + $PROG -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test1: type $type: failed" + exit 1 + fi + done + echo "Test 1: recno: small key, small data pairs" + rm -f $TMP2 $TMP3 + awk '{ + ++i; + printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i); + }' < $TMP1 > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test1: type recno: failed" + exit 1 + fi +} + +# Take the first 200 entries in the dictionary, and give them +# each a medium size data entry. +test2() +{ + echo "Test 2: btree, hash: small key, medium data pairs" + mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz + echo $mdata | + awk '{ for (i = 1; i < 201; ++i) print $0 }' > $TMP1 + for type in hash btree; do + rm -f $TMP2 $TMP3 + for i in `getnwords 200`; do + echo p + echo k$i + echo d$mdata + echo g + echo k$i + done > $TMP2 + $PROG -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test2: type $type: failed" + exit 1 + fi + done + echo "Test 2: recno: small key, medium data pairs" + rm -f $TMP2 $TMP3 + echo $mdata | + awk '{ for (i = 1; i < 201; ++i) + printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test2: type recno: failed" + exit 1 + fi +} + +# Insert the programs in $bindir with their paths as their keys. +test3() +{ + echo "Test 3: hash: small key, big data pairs" + rm -f $TMP1 + xargs cat < $BINFILES > $TMP1 + for type in hash; do + rm -f $TMP2 $TMP3 + for i in `cat $BINFILES`; do + echo p + echo k$i + echo D$i + echo g + echo k$i + done > $TMP2 + $PROG -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test3: $type: failed" + exit 1 + fi + done + echo "Test 3: btree: small key, big data pairs" + for psize in 512 16384 65536; do + echo " page size $psize" + for type in btree; do + rm -f $TMP2 $TMP3 + for i in `cat $BINFILES`; do + echo p + echo k$i + echo D$i + echo g + echo k$i + done > $TMP2 + $PROG -i psize=$psize -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test3: $type: page size $psize: failed" + exit 1 + fi + done + done + echo "Test 3: recno: big data pairs" + rm -f $TMP2 $TMP3 + awk '{ + ++i; + printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i); + }' < $BINFILES > $TMP2 + for psize in 512 16384 65536; do + echo " page size $psize" + $PROG -i psize=$psize -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test3: recno: page size $psize: failed" + exit 1 + fi + done +} + +# Do random recno entries. +test4() +{ + echo "Test 4: recno: random entries" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 37; i <= 37 + 88 * 17; i += 17) { + if (i % 41) + s = substr($0, 1, i % 41); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + for (i = 1; i <= 15; ++i) { + if (i % 41) + s = substr($0, 1, i % 41); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + for (i = 19234; i <= 19234 + 61 * 27; i += 27) { + if (i % 41) + s = substr($0, 1, i % 41); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + exit + }' > $TMP1 + rm -f $TMP2 $TMP3 + cat $TMP1 | + awk 'BEGIN { + i = 37; + incr = 17; + } + { + printf("p\nk%d\nd%s\n", i, $0); + if (i == 19234 + 61 * 27) + exit; + if (i == 37 + 88 * 17) { + i = 1; + incr = 1; + } else if (i == 15) { + i = 19234; + incr = 27; + } else + i += incr; + } + END { + for (i = 37; i <= 37 + 88 * 17; i += 17) + printf("g\nk%d\n", i); + for (i = 1; i <= 15; ++i) + printf("g\nk%d\n", i); + for (i = 19234; i <= 19234 + 61 * 27; i += 27) + printf("g\nk%d\n", i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test4: type recno: failed" + exit 1 + fi +} + +# Do reverse order recno entries. +test5() +{ + echo "Test 5: recno: reverse order entries" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk ' { + for (i = 1500; i; --i) { + if (i % 34) + s = substr($0, 1, i % 34); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + cat $TMP1 | + awk 'BEGIN { + i = 1500; + } + { + printf("p\nk%d\nd%s\n", i, $0); + --i; + } + END { + for (i = 1500; i; --i) + printf("g\nk%d\n", i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test5: type recno: failed" + exit 1 + fi +} + +# Do alternating order recno entries. +test6() +{ + echo "Test 6: recno: alternating order entries" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk ' { + for (i = 1; i < 1200; i += 2) { + if (i % 34) + s = substr($0, 1, i % 34); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + for (i = 2; i < 1200; i += 2) { + if (i % 34) + s = substr($0, 1, i % 34); + else + s = substr($0, 1); + printf("input key %d: %s\n", i, s); + } + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + cat $TMP1 | + awk 'BEGIN { + i = 1; + even = 0; + } + { + printf("p\nk%d\nd%s\n", i, $0); + i += 2; + if (i >= 1200) { + if (even == 1) + exit; + even = 1; + i = 2; + } + } + END { + for (i = 1; i < 1200; ++i) + printf("g\nk%d\n", i); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + sort -o $TMP1 $TMP1 + sort -o $TMP3 $TMP3 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test6: type recno: failed" + exit 1 + fi +} + +# Delete cursor record +test7() +{ + echo "Test 7: btree, recno: delete cursor record" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 120; ++i) + printf("%05d: input key %d: %s\n", i, i, $0); + printf("%05d: input key %d: %s\n", 120, 120, $0); + printf("seq failed, no such key\n"); + printf("%05d: input key %d: %s\n", 1, 1, $0); + printf("%05d: input key %d: %s\n", 2, 2, $0); + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + + for type in btree recno; do + cat $TMP1 | + awk '{ + if (i == 120) + exit; + printf("p\nk%d\nd%s\n", ++i, $0); + } + END { + printf("fR_NEXT\n"); + for (i = 1; i <= 120; ++i) + printf("s\n"); + printf("fR_CURSOR\ns\nk120\n"); + printf("r\n"); + printf("fR_NEXT\ns\n"); + printf("fR_CURSOR\ns\nk1\n"); + printf("r\n"); + printf("fR_FIRST\ns\n"); + }' > $TMP2 + $PROG -o $TMP3 recno $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test7: type $type: failed" + exit 1 + fi + done +} + +# Make sure that overflow pages are reused. +test8() +{ + echo "Test 8: btree: repeated small key, big data pairs" + rm -f $TMP1 + # /bin/csh is no longer ubiquitous - find a substitute + # The test stores contents of a known file + tfile="" + for tp in /bin/csh /bin/ls /usr/bin/ls /bin/cat /usr/bin/cat; do + if [ "x$tfile" = "x" -a -f $tp ]; then + tfile=$tp + fi + done + if [ "x$tfile" = "x" ]; then + echo "No suitable file for testing purposes" + exit 1 + fi + echo "" | + awk 'BEGIN { + for (i = 1; i <= 10; ++i) { + printf("p\nkkey1\nD/bin/sh\n"); + printf("p\nkkey2\nD'$tfile'\n"); + if (i % 8 == 0) { + printf("c\nkkey2\nD'$tfile'\n"); + printf("c\nkkey1\nD/bin/sh\n"); + printf("e\t%d of 10 (comparison)\n", i); + } else + printf("e\t%d of 10 \n", i); + printf("r\nkkey1\nr\nkkey2\n"); + } + }' > $TMP1 + if $PROG btree $TMP1 ; then + true + else + echo "test8: btree tests failed" + exit 1 + fi +# $PROG hash $TMP1 + # No explicit test for success. +} + +# Test btree duplicate keys +test9() +{ + echo "Test 9: btree: duplicate keys" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 543; ++i) + printf("%05d: input key %d: %s\n", i, i, $0); + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + + for type in btree; do + cat $TMP1 | + awk '{ + if (i++ % 2) + printf("p\nkduplicatekey\nd%s\n", $0); + else + printf("p\nkunique%dkey\nd%s\n", i, $0); + } + END { + printf("o\n"); + }' > $TMP2 + $PROG -iflags=1 -o $TMP3 $type $TMP2 + sort -o $TMP3 $TMP3 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test9: type $type: failed" + exit 1 + fi + done +} + +# Test use of cursor flags without initialization +test10() +{ + echo "Test 10: btree, recno: test cursor flag use" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 20; ++i) + printf("%05d: input key %d: %s\n", i, i, $0); + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + + # Test that R_CURSOR doesn't succeed before cursor initialized + for type in btree recno; do + cat $TMP1 | + awk '{ + if (i == 10) + exit; + printf("p\nk%d\nd%s\n", ++i, $0); + } + END { + printf("fR_CURSOR\nr\n"); + printf("eR_CURSOR SHOULD HAVE FAILED\n"); + }' > $TMP2 + $PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1 + if [ -s $TMP3 ] ; then + echo "Test 10: delete: R_CURSOR SHOULD HAVE FAILED" + exit 1 + fi + done + for type in btree recno; do + cat $TMP1 | + awk '{ + if (i == 10) + exit; + printf("p\nk%d\nd%s\n", ++i, $0); + } + END { + printf("fR_CURSOR\np\nk1\ndsome data\n"); + printf("eR_CURSOR SHOULD HAVE FAILED\n"); + }' > $TMP2 + $PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1 + if [ -s $TMP3 ] ; then + echo "Test 10: put: R_CURSOR SHOULD HAVE FAILED" + exit 1 + fi + done +} + +# Test insert in reverse order. +test11() +{ + echo "Test 11: recno: reverse order insert" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 779; ++i) + printf("%05d: input key %d: %s\n", i, i, $0); + exit; + }' > $TMP1 + rm -f $TMP2 $TMP3 + + for type in recno; do + cat $TMP1 | + awk '{ + if (i == 0) { + i = 1; + printf("p\nk1\nd%s\n", $0); + printf("%s\n", "fR_IBEFORE"); + } else + printf("p\nk1\nd%s\n", $0); + } + END { + printf("or\n"); + }' > $TMP2 + $PROG -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test11: type $type: failed" + exit 1 + fi + done +} + +# Take the first 20000 entries in the dictionary, reverse them, and give +# them each a small size data entry. Use a small page size to make sure +# the btree split code gets hammered. +test12() +{ + if ( rev < /dev/null ) > /dev/null 2>&1 ; then + : + else + echo "Test 12: skipped, rev not found" + return + fi + if test $dictsize -lt 20001 ; then + echo "Test 12: skipped, dictionary too small" + return + else + : + fi + echo "Test 12: btree: lots of keys, small page size" + mdata=abcdefghijklmnopqrstuvwxy + echo $mdata | + awk '{ for (i = 1; i < 20001; ++i) print $0 }' > $TMP1 + for type in btree; do + rm -f $TMP2 $TMP3 + for i in `getnwords 20000 | rev`; do + echo p + echo k$i + echo d$mdata + echo g + echo k$i + done > $TMP2 + $PROG -i psize=512 -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test12: type $type: failed" + exit 1 + fi + done +} + +# Test different byte orders. +test13() +{ + echo "Test 13: btree, hash: differing byte orders" + getnwords 50 > $TMP1 + for order in 1234 4321; do + for type in btree hash; do + rm -f byte.file $TMP2 $TMP3 + for i in `cat $TMP1`; do + echo p + echo k$i + echo d$i + echo S + echo g + echo k$i + done > $TMP2 + $PROG -ilorder=$order -f byte.file -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test13: $type/$order put failed" + exit 1 + fi + for i in `cat $TMP1`; do + echo g + echo k$i + done > $TMP2 + $PROG -s \ + -ilorder=$order -f byte.file -o $TMP3 $type $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test13: $type/$order get failed" + exit 1 + fi + done + done + rm -f byte.file +} + +# Try a variety of bucketsizes and fill factors for hashing +test20() +{ + if test $dictsize -lt 10001 ; then + echo "Test 20: skipped, dictionary too small" + return + else + : + fi + echo\ + "Test 20: hash: bucketsize, fill factor; nelem 25000 cachesize 65536" + echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" | + awk '{ + for (i = 1; i <= 10000; ++i) { + if (i % 34) + s = substr($0, 1, i % 34); + else + s = substr($0, 1); + printf("%s\n", s); + } + exit; + }' > $TMP1 + getnwords 10000 | + awk 'BEGIN { + ds="abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" + } + { + if (++i % 34) + s = substr(ds, 1, i % 34); + else + s = substr(ds, 1); + printf("p\nk%s\nd%s\n", $0, s); + }' > $TMP2 + getnwords 10000 | + awk '{ + ++i; + printf("g\nk%s\n", $0); + }' >> $TMP2 + bsize=256 + for ffactor in 11 14 21; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=512 + for ffactor in 21 28 43; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=1024 + for ffactor in 43 57 85; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=2048 + for ffactor in 85 114 171; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=4096 + for ffactor in 171 228 341; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done + bsize=8192 + for ffactor in 341 455 683; do + echo " bucketsize $bsize, fill factor $ffactor" + $PROG -o$TMP3 \ + -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\ + hash $TMP2 + if (cmp -s $TMP1 $TMP3) ; then : + else + echo "test20: type hash:\ +bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed" + exit 1 + fi + done +} + +# Test for a weird page split condition where an insertion into index +# 0 of a page that would cause the new item to be the only item on the +# left page results in index 0 of the right page being erroneously +# skipped; this only happens with one particular key+data length for +# each page size. +test40 () { + echo "Test 40: btree: page split on index 0" + e=: + for psize in 512 1024 2048 4096 8192; do + echo " page size $psize" + kdsizes=`awk 'BEGIN { + psize = '$psize'; hsize = int(psize/2); + for (kdsize = hsize-40; kdsize <= hsize; kdsize++) { + print kdsize; + } + }' /dev/null` + + # Use a series of keylen+datalen values in the right + # neighborhood to find the one that triggers the bug. + # We could compute the exact size that triggers the + # bug but this additional fuzz may be useful. + + # Insert keys in reverse order to maximize the chances + # for a split on index 0. + + for kdsize in $kdsizes; do + awk 'BEGIN { + kdsize = '$kdsize'; + for (i = 8; i-- > 0; ) { + s = sprintf("a%03d:%09d", i, kdsize); + for (j = 0; j < kdsize-20; j++) { + s = s "x"; + } + printf("p\nka%03d\nd%s\n", i, s); + } + print "o"; + }' /dev/null > $TMP2 + sed -n 's/^d//p' $TMP2 | sort > $TMP1 + $PROG -o $TMP3 -i psize=$psize btree $TMP2 + if (cmp -s $TMP1 $TMP3); then : + else + echo "test40: btree: page size $psize, \ +keylen+datalen=$kdsize failed" + e='exit 1' + fi + done + done + $e +} + +# Extremely tricky test attempting to replicate some unusual database +# corruption seen in the field: pieces of the database becoming +# inaccessible to random access, sequential access, or both. The +# hypothesis is that at least some of these are triggered by the bug +# in page splits on index 0 with a particular exact keylen+datalen. +# (See Test 40.) For psize=4096, this size is exactly 2024. + +# The order of operations here relies on very specific knowledge of +# the internals of the btree access method in order to place records +# at specific offsets in a page and to create certain keys on internal +# pages. The to-be-split page immediately prior to the bug-triggering +# split has the following properties: +# +# * is not the leftmost leaf page +# * key on the parent page is compares less than the key of the item +# on index 0 +# * triggering record's key also compares greater than the key on the +# parent page + +# Additionally, we prime the mpool LRU chain so that the head page on +# the chain has the following properties: +# +# * record at index 0 is located where it will not get overwritten by +# items written to the right-hand page during the split +# * key of the record at index 0 compares less than the key of the +# bug-triggering record + +# If the page-split bug exists, this test appears to create a database +# where some records are inaccessible to a search, but still remain in +# the file and are accessible by sequential traversal. At least one +# record gets duplicated out of sequence. + +test41 () { + echo "Test 41: btree: no unsearchables due to page split on index 0" + # list of individual retrievals in a variable for easy reuse + list=`(for i in a b c d; do + for j in 990 998 999; do + echo g ${i}${j} 1024 + done + done; + echo g y997 2014 + for i in y z; do + for j in 998 999; do + echo g ${i}${j} 1024 + done + done)` + # Exact number for trigger condition accounts for newlines + # retained by dbtest with -ofile but not without; we use + # -ofile, so count newlines. keylen=5,datalen=5+2014 for + # psize=4096 here. + (cat - < $TMP2 + (echo "$list"; echo "$list") | awk '{ + s = $2; + for (i = 0; i < $3; i++) { + s = s "x"; + } + print s; + }' > $TMP1 + $PROG -o $TMP3 -i psize=4096 btree $TMP2 + if (cmp -s $TMP1 $TMP3); then : + else + echo "test41: btree: failed" + exit 1 + fi +} + +# Test for recursive traversal successfully retrieving records that +# are inaccessible to normal sequential (sibling-link) traversal. +# This works by unlinking a few leaf pages but leaving their parent +# links intact. To verify that the unlink actually makes records +# inaccessible, the test first uses "o" to do a normal sequential +# traversal, followed by "O" to do a recursive traversal. +test50 () { + echo "Test 50: btree: recursive traversal" + fill="abcdefghijklmnopqrstuvwxyzy" + script='{ + for (i = 0; i < 20000; i++) { + printf("p\nkAA%05d\nd%05d%s\n", i, i, $0); + } + print "u"; + print "u"; + print "u"; + print "u"; + }' + (echo $fill | awk "$script"; echo o) > $TMP2 + echo $fill | + awk '{ + for (i = 0; i < 20000; i++) { + printf("%05d%s\n", i, $0); + } + }' > $TMP1 + $PROG -o $TMP3 -i psize=512 btree $TMP2 + if (cmp -s $TMP1 $TMP3); then + echo "test50: btree: unexpected success after unlinking pages" + exit 1 + fi + (echo $fill | awk "$script"; echo O) > $TMP2 + $PROG -o $TMP3 -i psize=512 btree $TMP2 + if (cmp -s $TMP1 $TMP3); then : + else + echo "test50: btree: failed" + exit 1 + fi +} + +test60 () { + echo "Test 60: btree: big key, small data, byteswap unaligned access" + # 488 = 512 - 20 (header) - 3 ("foo") - 1 (newline) + (echo foo; echo bar) | + awk '{ + s = $0 + for (i = 0; i < 488; i++) { + s = s "x"; + } + printf("p\nk%s\ndx\n", s); + }' > $TMP2 + for order in 1234 4321; do + $PROG -o $TMP3 -i psize=512,lorder=$order btree $TMP2 + done +} + +test61 () { + echo "Test 61: btree: small key, big data, byteswap unaligned access" + # 484 = 512 - 20 (header) - 7 ("foo1234") - 1 (newline) + (echo foo1234; echo bar1234) | + awk '{ + s = $0 + for (i = 0; i < 484; i++) { + s = s "x"; + } + printf("p\nk%s\nd%s\n", $0, s); + }' > $TMP2 + for order in 1234 4321; do + $PROG -o $TMP3 -i psize=512,lorder=$order btree $TMP2 + done +} + +test62 () { + echo "Test 62: btree: small key, big data, known byte order files" + (echo foo1234; echo bar1234) | + awk '{ + s = $0 + for (i = 0; i < 484; i++) { + s = s "x"; + } + printf("%s\n", s); + }' > $TMP1 + (echo g; echo kfoo1234; echo g; echo kbar1234) > $TMP2 + for f in t.le.db t.be.db; do + echo " $f" + $PROG -f $f -s -o $TMP3 btree $TMP2 + if (cmp -s $TMP1 $TMP3); then : + else + echo "test62: btree: failed" + exit 1 + fi + done +} + +test63 () { + echo "Test 63: btree: big key, medium data, bt_split unaligned access" + # 488 = 512 - 20 (header) - 3 ("foo") - 1 (newline) + # 223 = 232 - 8 (key pointer) + # 232 = bt_ovflsize = (512 - 20 (header)) / 2 (DEFMINKEYPAGE) + # - (2 (indx_t) + 12 (NBLEAFDBT(0,0))) + awk 'BEGIN { + s = ""; + for (i = 0; i < 488; i++) { + s = s "x"; + } + d = ""; + for (i = 0; i < 223; i++) { + d = d "x"; + } + for (i = 0; i < 128; i++) { + printf("p\nk%s%03d\nd%s\n", s, i, d); + } + }' /dev/null > $TMP2 + $PROG -o $TMP3 -i psize=512 btree $TMP2 +} + +main $* diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/t.be.txt b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/t.be.txt new file mode 100644 index 00000000..4c60e2e2 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/t.be.txt @@ -0,0 +1,64 @@ +0005316200000003000002000000000000000000000000200000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +00000001000000000000000000000002001801C801C801E4FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF000000080000000801626172313233340A00000003000001 +ECFFFFFF000000080000000801666F6F313233340A00000002000001ECFFFFFF +0000000200000000000000000000000400000000666F6F313233347878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +787878787878787878787878787878787878787878787878787878787878780A +0000000300000000000000000000000400000000626172313233347878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +787878787878787878787878787878787878787878787878787878787878780A diff --git a/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/t.le.txt b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/t.le.txt new file mode 100644 index 00000000..ad1154b0 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/libdb2/test/t.le.txt @@ -0,0 +1,64 @@ +6231050003000000000200000000000000000000200000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +0000000000000000000000000000000000000000000000000000000000000000 +010000000000000000000000020000001800C801C801E401FFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFF080000000800000001626172313233340A03000000EC0100 +00FFFFFF080000000800000001666F6F313233340A02000000EC010000FFFFFF +0200000000000000000000000400000000000000666F6F313233347878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +787878787878787878787878787878787878787878787878787878787878780A +0300000000000000000000000400000000000000626172313233347878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +7878787878787878787878787878787878787878787878787878787878787878 +787878787878787878787878787878787878787878787878787878787878780A diff --git a/krb5-1.21.3/src/plugins/kdb/db2/lockout.c b/krb5-1.21.3/src/plugins/kdb/db2/lockout.c new file mode 100644 index 00000000..30fb554d --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/lockout.c @@ -0,0 +1,222 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/db2/lockout.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "kdb.h" +#include +#include +#include +#include "kdb5.h" +#include "kdb_db2.h" + +/* + * Helper routines for databases that wish to use the default + * principal lockout functionality. + */ + +static krb5_error_code +lookup_lockout_policy(krb5_context context, + krb5_db_entry *entry, + krb5_kvno *pw_max_fail, + krb5_deltat *pw_failcnt_interval, + krb5_deltat *pw_lockout_duration) +{ + krb5_tl_data tl_data; + krb5_error_code code; + osa_princ_ent_rec adb; + XDR xdrs; + + *pw_max_fail = 0; + *pw_failcnt_interval = 0; + *pw_lockout_duration = 0; + + tl_data.tl_data_type = KRB5_TL_KADM_DATA; + + code = krb5_dbe_lookup_tl_data(context, entry, &tl_data); + if (code != 0 || tl_data.tl_data_length == 0) + return code; + + memset(&adb, 0, sizeof(adb)); + xdrmem_create(&xdrs, (char *)tl_data.tl_data_contents, + tl_data.tl_data_length, XDR_DECODE); + if (!xdr_osa_princ_ent_rec(&xdrs, &adb)) { + xdr_destroy(&xdrs); + return KADM5_XDR_FAILURE; + } + + if (adb.policy != NULL) { + osa_policy_ent_t policy = NULL; + + code = krb5_db2_get_policy(context, adb.policy, &policy); + if (code == 0) { + *pw_max_fail = policy->pw_max_fail; + *pw_failcnt_interval = policy->pw_failcnt_interval; + *pw_lockout_duration = policy->pw_lockout_duration; + krb5_db_free_policy(context, policy); + } + } + + xdr_destroy(&xdrs); + + xdrmem_create(&xdrs, NULL, 0, XDR_FREE); + xdr_osa_princ_ent_rec(&xdrs, &adb); + xdr_destroy(&xdrs); + + return 0; +} + +/* draft-behera-ldap-password-policy-10.txt 7.1 */ +static krb5_boolean +locked_check_p(krb5_context context, + krb5_timestamp stamp, + krb5_kvno max_fail, + krb5_timestamp lockout_duration, + krb5_db_entry *entry) +{ + krb5_timestamp unlock_time; + + /* If the entry was unlocked since the last failure, it's not locked. */ + if (krb5_dbe_lookup_last_admin_unlock(context, entry, &unlock_time) == 0 && + !ts_after(entry->last_failed, unlock_time)) + return FALSE; + + if (max_fail == 0 || entry->fail_auth_count < max_fail) + return FALSE; + + if (lockout_duration == 0) + return TRUE; /* principal permanently locked */ + + return ts_after(ts_incr(entry->last_failed, lockout_duration), stamp); +} + +krb5_error_code +krb5_db2_lockout_check_policy(krb5_context context, + krb5_db_entry *entry, + krb5_timestamp stamp) +{ + krb5_error_code code; + krb5_kvno max_fail = 0; + krb5_deltat failcnt_interval = 0; + krb5_deltat lockout_duration = 0; + krb5_db2_context *db_ctx = context->dal_handle->db_context; + + if (db_ctx->disable_lockout) + return 0; + + code = lookup_lockout_policy(context, entry, &max_fail, + &failcnt_interval, + &lockout_duration); + if (code != 0) + return code; + + if (locked_check_p(context, stamp, max_fail, lockout_duration, entry)) + return KRB5KDC_ERR_CLIENT_REVOKED; + + return 0; +} + +krb5_error_code +krb5_db2_lockout_audit(krb5_context context, + krb5_db_entry *entry, + krb5_timestamp stamp, + krb5_error_code status) +{ + krb5_error_code code; + krb5_kvno max_fail = 0; + krb5_deltat failcnt_interval = 0; + krb5_deltat lockout_duration = 0; + krb5_db2_context *db_ctx = context->dal_handle->db_context; + krb5_boolean need_update = FALSE; + krb5_timestamp unlock_time; + + switch (status) { + case 0: + case KRB5KDC_ERR_PREAUTH_FAILED: + case KRB5KRB_AP_ERR_BAD_INTEGRITY: + break; + default: + return 0; + } + + if (entry == NULL) + return 0; + + if (!db_ctx->disable_lockout) { + code = lookup_lockout_policy(context, entry, &max_fail, + &failcnt_interval, &lockout_duration); + if (code != 0) + return code; + } + + /* + * Don't continue to modify the DB for an already locked account. + * (In most cases, status will be KRB5KDC_ERR_CLIENT_REVOKED, and + * this check is unneeded, but in rare cases, we can fail with an + * integrity error or preauth failure before a policy check.) + */ + if (locked_check_p(context, stamp, max_fail, lockout_duration, entry)) + return 0; + + /* Only mark the authentication as successful if the entry + * required preauthentication, otherwise we have no idea. */ + if (status == 0 && (entry->attributes & KRB5_KDB_REQUIRES_PRE_AUTH)) { + if (!db_ctx->disable_lockout && entry->fail_auth_count != 0) { + entry->fail_auth_count = 0; + need_update = TRUE; + } + if (!db_ctx->disable_last_success) { + entry->last_success = stamp; + need_update = TRUE; + } + } else if (!db_ctx->disable_lockout && + (status == KRB5KDC_ERR_PREAUTH_FAILED || + status == KRB5KRB_AP_ERR_BAD_INTEGRITY)) { + if (krb5_dbe_lookup_last_admin_unlock(context, entry, + &unlock_time) == 0 && + !ts_after(entry->last_failed, unlock_time)) { + /* Reset fail_auth_count after administrative unlock. */ + entry->fail_auth_count = 0; + } + + if (failcnt_interval != 0 && + ts_after(stamp, ts_incr(entry->last_failed, failcnt_interval))) { + /* Reset fail_auth_count after failcnt_interval. */ + entry->fail_auth_count = 0; + } + + entry->last_failed = stamp; + entry->fail_auth_count++; + need_update = TRUE; + } + + if (need_update) { + code = krb5_db2_put_principal(context, entry, NULL); + if (code != 0) + return code; + } + + return 0; +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/pol_xdr.c b/krb5-1.21.3/src/plugins/kdb/db2/pol_xdr.c new file mode 100644 index 00000000..e8576337 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/pol_xdr.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include "policy_db.h" +#ifdef HAVE_MEMORY_H +#include +#endif +#include + +static int +osa_policy_min_vers(osa_policy_ent_t objp) +{ + if (objp->attributes || + objp->max_life || + objp->max_renewable_life || + objp->allowed_keysalts || + objp->n_tl_data) + return OSA_ADB_POLICY_VERSION_3; + + if (objp->pw_max_fail || + objp->pw_failcnt_interval || + objp->pw_lockout_duration) + return OSA_ADB_POLICY_VERSION_2; + + return OSA_ADB_POLICY_VERSION_1; +} + +bool_t +xdr_osa_policy_ent_rec(XDR *xdrs, osa_policy_ent_t objp) +{ + switch (xdrs->x_op) { + case XDR_ENCODE: + objp->version = osa_policy_min_vers(objp); + /* fall through */ + case XDR_FREE: + if (!xdr_int(xdrs, &objp->version)) + return FALSE; + break; + case XDR_DECODE: + if (!xdr_int(xdrs, &objp->version)) + return FALSE; + if (objp->version != OSA_ADB_POLICY_VERSION_1 && + objp->version != OSA_ADB_POLICY_VERSION_2 && + objp->version != OSA_ADB_POLICY_VERSION_3) + return FALSE; + break; + } + + if(!xdr_nullstring(xdrs, &objp->name)) + return (FALSE); + if (!xdr_u_int32(xdrs, &objp->pw_min_life)) + return (FALSE); + if (!xdr_u_int32(xdrs, &objp->pw_max_life)) + return (FALSE); + if (!xdr_u_int32(xdrs, &objp->pw_min_length)) + return (FALSE); + if (!xdr_u_int32(xdrs, &objp->pw_min_classes)) + return (FALSE); + if (!xdr_u_int32(xdrs, &objp->pw_history_num)) + return (FALSE); + if (!xdr_u_int32(xdrs, &objp->policy_refcnt)) + return (FALSE); + if (objp->version > OSA_ADB_POLICY_VERSION_1) { + if (!xdr_u_int32(xdrs, &objp->pw_max_fail)) + return (FALSE); + if (!xdr_u_int32(xdrs, &objp->pw_failcnt_interval)) + return (FALSE); + if (!xdr_u_int32(xdrs, &objp->pw_lockout_duration)) + return (FALSE); + } + if (objp->version > OSA_ADB_POLICY_VERSION_2) { + if (!xdr_u_int32(xdrs, &objp->attributes)) + return (FALSE); + if (!xdr_u_int32(xdrs, &objp->max_life)) + return (FALSE); + if (!xdr_u_int32(xdrs, &objp->max_renewable_life)) + return (FALSE); + if (!xdr_nullstring(xdrs, &objp->allowed_keysalts)) + return (FALSE); + if (!xdr_short(xdrs, &objp->n_tl_data)) + return (FALSE); + if (!xdr_nulltype(xdrs, (void **) &objp->tl_data, + xdr_krb5_tl_data)) + return FALSE; + } + return (TRUE); +} diff --git a/krb5-1.21.3/src/plugins/kdb/db2/policy_db.h b/krb5-1.21.3/src/plugins/kdb/db2/policy_db.h new file mode 100644 index 00000000..62d11464 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/db2/policy_db.h @@ -0,0 +1,107 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Data Types for policy and principal information that + * exists in the respective databases. + * + * $Header$ + * + * This file was originally created with rpcgen. + * It has been hacked up since then. + */ + +#ifndef __ADB_H__ +#define __ADB_H__ +#include +#include +#include +#include +/* Okay, this is a bit obscure. The libdb2 configure script doesn't + detect it, but on Tru64 5.1, netinet/in.h causes sys/bittypes.h to + be included, and that has a typedef for u_int32_t. Because the + configure script doesn't detect it, it causes db-config.h to have a + #define for u_int32_t, so including db.h and then netinet/in.h + causes compilation to fail. + + Since gssrpc/types.h includes netinet/in.h, including that first + will cause the typedef to be seen before the macro definition, + which still isn't quite right, but is close enough for now. + + A better fix might be for db.h to include netinet/in.h if that's + where we find u_int32_t. */ +#include +#include +#include +#include "adb_err.h" +#include + +/* DB2 uses EFTYPE to indicate a database file of the wrong format, and falls + * back to EINVAL if the platform does not define EFTYPE. */ +#ifdef EFTYPE +#define IS_EFTYPE(e) ((e) == EFTYPE || (e) == EINVAL) +#else +#define IS_EFTYPE(e) ((e) == EINVAL) +#endif + +typedef long osa_adb_ret_t; + +#define OSA_ADB_POLICY_DB_MAGIC 0x12345A00 + +#define OSA_ADB_POLICY_VERSION_MASK 0x12345D00 +#define OSA_ADB_POLICY_VERSION_1 0x12345D01 +#define OSA_ADB_POLICY_VERSION_2 0x12345D02 +#define OSA_ADB_POLICY_VERSION_3 0x12345D03 + + + +typedef struct _osa_adb_db_lock_ent_t { + FILE *lockfile; + char *filename; + int refcnt, lockmode, lockcnt; + krb5_context context; +} osa_adb_lock_ent, *osa_adb_lock_t; + +typedef struct _osa_adb_db_ent_t { + int magic; + DB *db; + HASHINFO info; + BTREEINFO btinfo; + char *filename; + osa_adb_lock_t lock; + int opencnt; +} osa_adb_db_ent, *osa_adb_db_t, *osa_adb_princ_t, *osa_adb_policy_t; + +/* + * Return Code (the rest are in adb_err.h) + */ + +#define OSA_ADB_OK 0 + +/* + * Functions + */ + +krb5_error_code osa_adb_create_db(char *filename, char *lockfile, int magic); +krb5_error_code osa_adb_destroy_db(char *filename, char *lockfile, int magic); +krb5_error_code osa_adb_init_db(osa_adb_db_t *dbp, char *filename, + char *lockfile, int magic); +krb5_error_code osa_adb_fini_db(osa_adb_db_t db, int magic); +krb5_error_code osa_adb_get_lock(osa_adb_db_t db, int mode); +krb5_error_code osa_adb_release_lock(osa_adb_db_t db); +krb5_error_code osa_adb_open_and_lock(osa_adb_princ_t db, int locktype); +krb5_error_code osa_adb_close_and_unlock(osa_adb_princ_t db); +krb5_error_code osa_adb_create_policy(osa_adb_policy_t db, + osa_policy_ent_t entry); +krb5_error_code osa_adb_destroy_policy(osa_adb_policy_t db, + char * name); +krb5_error_code osa_adb_get_policy(osa_adb_policy_t db, char *name, + osa_policy_ent_t *entry); +krb5_error_code osa_adb_put_policy(osa_adb_policy_t db, + osa_policy_ent_t entry); +krb5_error_code osa_adb_iter_policy(osa_adb_policy_t db, + osa_adb_iter_policy_func func, + void * data); +void osa_free_policy_ent(osa_policy_ent_t val); + +bool_t xdr_osa_policy_ent_rec(XDR *xdrs, osa_policy_ent_t objp); + +#endif /* __ADB_H__ */ diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/Makefile.in b/krb5-1.21.3/src/plugins/kdb/ldap/Makefile.in new file mode 100644 index 00000000..69c120eb --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/Makefile.in @@ -0,0 +1,36 @@ +mydir=plugins$(S)kdb$(S)ldap +BUILDTOP=$(REL)..$(S)..$(S).. +MODULE_INSTALL_DIR = $(KRB5_DB_MODULE_DIR) + +SUBDIRS= libkdb_ldap + +LOCALINCLUDES = -I../../../lib/kdb -I$(srcdir)/../../../lib/kdb \ + -I$(srcdir)/libkdb_ldap + +LIBBASE=kldap +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/kdb/ldap +# Depends on libk5crypto and libkrb5 +# Also on gssrpc, for xdr stuff. +SHLIB_EXPDEPS = \ + $(TOPLIBD)/libkdb_ldap$(SHLIBEXT) \ + $(GSSRPC_DEPLIBS) \ + $(TOPLIBD)/libk5crypto$(SHLIBEXT) \ + $(TOPLIBD)/libkrb5$(SHLIBEXT) \ + $(TOPLIBD)/lib$(SUPPORT_LIBNAME)$(SHLIBEXT) +SHLIB_EXPLIBS= -lkdb_ldap $(GSSRPC_LIBS) -lkrb5 $(COM_ERR_LIB) -lk5crypto -lkrb5support $(LIBS) + +SRCS= $(srcdir)/ldap_exp.c + +$(TOPLIBD)/libkdb_ldap$(SHLIBEXT) : all-recurse + +STLIBOBJS= ldap_exp.o + +all-unix: all-liblinks +install-unix: install-libs +clean-unix:: clean-liblinks clean-libs clean-libobjs + +@libnover_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/deps b/krb5-1.21.3/src/plugins/kdb/ldap/deps new file mode 100644 index 00000000..40668289 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/deps @@ -0,0 +1,27 @@ +# +# Generated makefile dependencies follow. +# +ldap_exp.so ldap_exp.po $(OUTPRE)ldap_exp.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../../lib/kdb/kdb5.h \ + $(srcdir)/libkdb_ldap/kdb_ldap.h $(srcdir)/libkdb_ldap/ldap_krbcontainer.h \ + $(srcdir)/libkdb_ldap/ldap_principal.h $(srcdir)/libkdb_ldap/ldap_pwd_policy.h \ + $(srcdir)/libkdb_ldap/ldap_realm.h $(srcdir)/libkdb_ldap/ldap_tkt_policy.h \ + $(srcdir)/libkdb_ldap/princ_xdr.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + ldap_exp.c diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/kldap.exports b/krb5-1.21.3/src/plugins/kdb/ldap/kldap.exports new file mode 100644 index 00000000..f2b7c111 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/kldap.exports @@ -0,0 +1 @@ +kdb_function_table diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/ldap_exp.c b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_exp.c new file mode 100644 index 00000000..d5cd82bb --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_exp.c @@ -0,0 +1,86 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/ldap_exp.c */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "k5-int.h" +#if HAVE_UNISTD_H +#include +#endif +#include +#include +#include +#include +#include "kdb_ldap.h" +#include "ldap_principal.h" +#include "ldap_pwd_policy.h" + + +/* + * Exposed API + */ + +kdb_vftabl PLUGIN_SYMBOL_NAME(krb5_ldap, kdb_function_table) = { + KRB5_KDB_DAL_MAJOR_VERSION, /* major version number */ + 0, /* minor version number 0 */ + /* init_library */ krb5_ldap_lib_init, + /* fini_library */ krb5_ldap_lib_cleanup, + /* init_module */ krb5_ldap_open, + /* fini_module */ krb5_ldap_close, + /* create */ krb5_ldap_create, + /* destroy */ krb5_ldap_delete_realm_1, + /* get_age */ krb5_ldap_get_age, + /* lock */ krb5_ldap_lock, + /* unlock */ krb5_ldap_unlock, + /* get_principal */ krb5_ldap_get_principal, + /* put_principal */ krb5_ldap_put_principal, + /* delete_principal */ krb5_ldap_delete_principal, + /* rename_principal */ krb5_ldap_rename_principal, + /* iterate */ krb5_ldap_iterate, + /* create_policy */ krb5_ldap_create_password_policy, + /* get_policy */ krb5_ldap_get_password_policy, + /* put_policy */ krb5_ldap_put_password_policy, + /* iter_policy */ krb5_ldap_iterate_password_policy, + /* delete_policy */ krb5_ldap_delete_password_policy, + /* optional functions */ + /* fetch_master_key */ NULL /* krb5_ldap_fetch_mkey */, + /* fetch_master_key_list */ NULL, + /* store_master_key_list */ NULL, + /* Search enc type */ NULL, + /* Change pwd */ NULL, + /* promote_db */ NULL, + /* decrypt_key_data */ NULL, + /* encrypt_key_data */ NULL, + /* check_transited_realms */ NULL, + /* check_policy_as */ krb5_ldap_check_policy_as, + /* check_policy_tgs */ NULL, + /* audit_as_req */ krb5_ldap_audit_as_req, + /* refresh_config */ NULL, + /* check_allowed_to_delegate */ krb5_ldap_check_allowed_to_delegate + +}; diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/Makefile.in b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/Makefile.in new file mode 100644 index 00000000..8669c243 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/Makefile.in @@ -0,0 +1,29 @@ +mydir=plugins$(S)kdb$(S)ldap$(S)ldap_util +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +DEFINES = -DKDB4_DISABLE +LOCALINCLUDES = -I. -I$(srcdir)/../libkdb_ldap -I$(top_srcdir)/lib/kdb +#KDB_DEP_LIB=$(DL_LIB) $(THREAD_LINKOPTS) +KDB_DEP_LIB=$(DL_LIB) -lkdb_ldap $(THREAD_LINKOPTS) + +PROG = kdb5_ldap_util +SRCS = kdb5_ldap_util.c kdb5_ldap_list.c kdb5_ldap_realm.c kdb5_ldap_policy.c kdb5_ldap_services.c getdate.c +OBJS = kdb5_ldap_util.o kdb5_ldap_list.o kdb5_ldap_realm.o kdb5_ldap_policy.o kdb5_ldap_services.o getdate.o + +GETDATE = $(srcdir)/../../../../kadmin/cli/getdate.y + +all: $(PROG) + +$(PROG): $(OBJS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIB) $(GETDATE) + $(CC_LINK) -o $(PROG) $(OBJS) \ + $(KADMSRV_LIBS) $(KDB_DEP_LIB) $(KRB5_BASE_LIBS) + +getdate.c: $(GETDATE) + $(RM) getdate.c y.tab.c + $(YACC) $(GETDATE) + $(MV) y.tab.c getdate.c + +install: + $(INSTALL_PROGRAM) $(PROG) ${DESTDIR}$(ADMIN_BINDIR)/$(PROG) + +clean: + $(RM) $(PROG) $(OBJS) getdate.c diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/deps b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/deps new file mode 100644 index 00000000..a641fe8e --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/deps @@ -0,0 +1,104 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kdb5_ldap_util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../libkdb_ldap/kdb_ldap.h \ + $(srcdir)/../libkdb_ldap/ldap_krbcontainer.h $(srcdir)/../libkdb_ldap/ldap_misc.h \ + $(srcdir)/../libkdb_ldap/ldap_realm.h $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h $(top_srcdir)/lib/kdb/kdb5.h \ + kdb5_ldap_policy.h kdb5_ldap_realm.h kdb5_ldap_services.h \ + kdb5_ldap_util.c kdb5_ldap_util.h +$(OUTPRE)kdb5_ldap_list.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdb5_ldap_list.c \ + kdb5_ldap_list.h +$(OUTPRE)kdb5_ldap_realm.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../libkdb_ldap/kdb_ldap.h \ + $(srcdir)/../libkdb_ldap/ldap_krbcontainer.h $(srcdir)/../libkdb_ldap/ldap_misc.h \ + $(srcdir)/../libkdb_ldap/ldap_principal.h $(srcdir)/../libkdb_ldap/ldap_realm.h \ + $(srcdir)/../libkdb_ldap/ldap_tkt_policy.h $(srcdir)/../libkdb_ldap/princ_xdr.h \ + $(top_srcdir)/include/adm_proto.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + $(top_srcdir)/lib/kdb/kdb5.h kdb5_ldap_list.h kdb5_ldap_policy.h \ + kdb5_ldap_realm.c kdb5_ldap_realm.h kdb5_ldap_services.h \ + kdb5_ldap_util.h +$(OUTPRE)kdb5_ldap_policy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../libkdb_ldap/kdb_ldap.h \ + $(srcdir)/../libkdb_ldap/ldap_krbcontainer.h $(srcdir)/../libkdb_ldap/ldap_misc.h \ + $(srcdir)/../libkdb_ldap/ldap_realm.h $(srcdir)/../libkdb_ldap/ldap_tkt_policy.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h $(top_srcdir)/lib/kdb/kdb5.h \ + kdb5_ldap_list.h kdb5_ldap_policy.c kdb5_ldap_policy.h \ + kdb5_ldap_realm.h kdb5_ldap_services.h kdb5_ldap_util.h +$(OUTPRE)kdb5_ldap_services.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../libkdb_ldap/kdb_ldap.h \ + $(srcdir)/../libkdb_ldap/ldap_krbcontainer.h $(srcdir)/../libkdb_ldap/ldap_misc.h \ + $(srcdir)/../libkdb_ldap/ldap_realm.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-hex.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h $(top_srcdir)/lib/kdb/kdb5.h \ + kdb5_ldap_list.h kdb5_ldap_policy.h kdb5_ldap_realm.h \ + kdb5_ldap_services.c kdb5_ldap_services.h kdb5_ldap_util.h +$(OUTPRE)getdate.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + getdate.c diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c new file mode 100644 index 00000000..52375a22 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c @@ -0,0 +1,275 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/ldap_util/kdb5_ldap_list.c */ +/* Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +/* + * Miscellaneous functions for managing the string and integer lists + */ + +#include +#include "kdb5_ldap_list.h" + +/* + * Counts the number of entries in the given array of strings + */ +int +list_count_str_array(char **list) +{ + int i = 0; + + if (list == NULL) + return 0; + + for (i = 0; *list != NULL; list++) { + i++; + } + + return i; +} + + +/* + * Counts the number of entries in the given array of integers + */ +int +list_count_int_array(int *list) +{ + int i = 0; + + if (list == NULL) + return 0; + + for (i = 0; *list != END_OF_LIST; list++) { + i++; + } + + return i; +} + + +/* + * Frees the entries in a given list and not the list pointer + */ +void +krb5_free_list_entries(char **list) +{ + if (list == NULL) + return; + for (; *list != NULL; list++) { + free(*list); + *list = NULL; + } + + return; +} + + +/* + * Tokenize the given string based on the delimiter provided + * and return the result as a list + */ +krb5_error_code +krb5_parse_list(char *buffer, char *delimiter, char **list) +{ + char *str = NULL; + char *token = NULL; + char *ptrptr = NULL; + char **plist = list; + krb5_error_code retval = 0; + int count = 0; + + if ((buffer == NULL) || (list == NULL) || (delimiter == NULL)) { + return EINVAL; + } + + str = strdup(buffer); + if (str == NULL) + return ENOMEM; + + token = strtok_r(str, delimiter, &ptrptr); + for (count = 1; ((token != NULL) && (count < MAX_LIST_ENTRIES)); + plist++, count++) { + *plist = strdup(token); + if (*plist == NULL) { + retval = ENOMEM; + goto cleanup; + } + token = strtok_r(NULL, delimiter, &ptrptr); + } + *plist = NULL; + +cleanup: + if (str) { + free(str); + str = NULL; + } + if (retval) + krb5_free_list_entries(list); + + return retval; +} + + +int +compare_int(const void *m1, const void *m2) +{ + int mi1 = *(const int *)m1; + int mi2 = *(const int *)m2; + + return (mi1 - mi2); +} + + +/* + * Modifies the destination list to contain or not to contain the + * entries present in the source list, depending on the mode + * (ADD or DELETE). + */ +void +list_modify_str_array(char ***destlist, const char **sourcelist, int mode) +{ + char **dlist = NULL, **tmplist = NULL; + const char **slist = NULL; + int dcount = 0, scount = 0, copycount = 0; + + if ((destlist == NULL) || (*destlist == NULL) || (sourcelist == NULL)) + return; + + /* We need to add every entry present in the source list to + * the destination list */ + if (mode == LIST_MODE_ADD) { + /* Traverse through the end of destlist for appending */ + for (dlist = *destlist, dcount = 0; *dlist != NULL; + dlist++, dcount++) { + ; /* NULL statement */ + } + /* Count the number of entries in the source list */ + for (slist = sourcelist, scount = 0; *slist != NULL; + slist++, scount++) { + ; /* NULL statement */ + } + /* Reset the slist pointer to the start of source list */ + slist = sourcelist; + + /* Now append the source list to the existing destlist */ + if ((dcount + scount) < MAX_LIST_ENTRIES) + copycount = scount; + else + /* Leave the last entry for list terminator(=NULL) */ + copycount = (MAX_LIST_ENTRIES -1) - dcount; + + memcpy(dlist, slist, (sizeof(char *) * copycount)); + dlist += copycount; + *dlist = NULL; + } else if (mode == LIST_MODE_DELETE) { + /* We need to delete every entry present in the source list + * from the destination list */ + for (slist = sourcelist; *slist != NULL; slist++) { + for (dlist = *destlist; *dlist != NULL; dlist++) { + /* DN is case insensitive string */ + if (strcasecmp(*dlist, *slist) == 0) { + free(*dlist); + /* Advance the rest of the entries by one */ + for (tmplist = dlist; *tmplist != NULL; tmplist++) { + *tmplist = *(tmplist+1); + } + break; + } + } + } + } + + return; +} + + +/* + * Modifies the destination list to contain or not to contain the + * entries present in the source list, depending on the mode + * (ADD or DELETE). where the list is array of integers. + */ +int +list_modify_int_array(int *destlist, const int *sourcelist, int mode) +{ + int *dlist = NULL, *tmplist = NULL; + const int *slist = NULL; + int dcount = 0, scount = 0, copycount = 0; + int tcount = 0; + + if ((destlist == NULL) || (sourcelist == NULL)) + return 0; + + /* We need to add every entry present in the source list to the + * destination list */ + if (mode == LIST_MODE_ADD) { + /* Traverse through the end of destlist for appending */ + for (dlist = destlist, dcount = 0; *dlist != END_OF_LIST; + dlist++, dcount++) + ; /* NULL statement */ + + /* Count the number of entries in the source list */ + for (slist = sourcelist, scount = 0; *slist != END_OF_LIST; + slist++, scount++) + ; /* NULL statement */ + + /* Reset the slist pointer to the start of source list */ + slist = sourcelist; + + /* Now append the source list to the existing destlist */ + if ((dcount + scount) < MAX_LIST_ENTRIES) + copycount = scount; + else + /* Leave the last entry for list terminator(=NULL) */ + copycount = (MAX_LIST_ENTRIES -1) - dcount; + + memcpy(dlist, slist, (sizeof(int) * copycount)); + dlist += copycount; + *dlist = END_OF_LIST; + tcount = dcount + copycount; + } else if (mode == LIST_MODE_DELETE) { + /* We need to delete every entry present in the source list from + * the destination list */ + for (slist = sourcelist; *slist != END_OF_LIST; slist++) { + for (dlist = destlist; *dlist != END_OF_LIST; dlist++) { + if (*dlist == *slist) { + /* Advance the rest of the entries by one */ + for (tmplist = dlist; *tmplist != END_OF_LIST; tmplist++) { + *tmplist = *(tmplist+1); + } + break; + } + } + } + /* count the number of entries */ + for (dlist = destlist, tcount = 0; *dlist != END_OF_LIST; dlist++) { + tcount++; + } + } + + return tcount; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h new file mode 100644 index 00000000..a729318b --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h @@ -0,0 +1,44 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/ldap_util/kdb5_ldap_list.h */ +/* Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + + +#define MAX_LIST_ENTRIES 64 +#define END_OF_LIST -1 /* End of List */ +#define LIST_DELIMITER ":" /* List entry separator */ +#define LIST_MODE_ADD 0x701 /* Add to the List */ +#define LIST_MODE_DELETE 0x702 /* Delete from the list */ +#define MAX_LEN_LIST_ENTRY 512 /* Max len of an entry */ + +extern krb5_error_code krb5_parse_list(char *buffer, char *delimiter, char **list); +extern void krb5_free_list_entries(char **list); +extern void list_modify_str_array(char ***destlist, const char **sourcelist, int mode); +extern int list_modify_int_array(int *destlist, const int *sourcelist, int mode); +extern int list_count_str_array(char **list); +extern int list_count_int_array(int *list); +extern int compare_int(const void*, const void *); diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c new file mode 100644 index 00000000..c642e174 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c @@ -0,0 +1,866 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c */ +/* Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +/* + * Create / Delete / Modify / View / List policy objects. + */ + +#include +#include +#include "kdb5_ldap_util.h" +#include "kdb5_ldap_list.h" +#include "ldap_tkt_policy.h" +extern time_t get_date(char *); /* kadmin/cli/getdate.o */ + +static void print_policy_params(krb5_ldap_policy_params *policyparams, int mask); +static char *strdur(time_t duration); + +extern char *yes; +extern kadm5_config_params global_params; + +static krb5_error_code +init_ldap_realm(int argc, char *argv[]) +{ + /* This operation is being performed in the context of a realm. So, + * initialize the realm */ + int mask = 0; + krb5_error_code retval = 0; + kdb5_dal_handle *dal_handle = NULL; + krb5_ldap_context *ldap_context=NULL; + + dal_handle = util_context->dal_handle; + ldap_context = (krb5_ldap_context *) dal_handle->db_context; + if (!ldap_context) { + retval = EINVAL; + goto cleanup; + } + + if (ldap_context->container_dn == NULL) { + retval = krb5_ldap_read_krbcontainer_dn(util_context, + &ldap_context->container_dn); + if (retval != 0) { + com_err(progname, retval, + _("while reading kerberos container information")); + goto cleanup; + } + } + + if (ldap_context->lrparams == NULL) { + retval = krb5_ldap_read_realm_params(util_context, + global_params.realm, + &(ldap_context->lrparams), + &mask); + + if (retval != 0) { + goto cleanup; + } + } +cleanup: + return retval; +} + +/* + * This function will create a ticket policy object with the + * specified attributes. + */ +void +kdb5_ldap_create_policy(int argc, char *argv[]) +{ + char *me = progname; + krb5_error_code retval = 0; + krb5_ldap_policy_params *policyparams = NULL; + krb5_boolean print_usage = FALSE; + krb5_boolean no_msg = FALSE; + int mask = 0; + time_t date = 0; + time_t now = 0; + int i = 0; + + /* Check for number of arguments */ + if ((argc < 2) || (argc > 16)) { + goto err_usage; + } + + /* Allocate memory for policy parameters structure */ + policyparams = (krb5_ldap_policy_params*) calloc(1, sizeof(krb5_ldap_policy_params)); + if (policyparams == NULL) { + retval = ENOMEM; + goto cleanup; + } + + /* Get current time */ + time (&now); + + /* Parse all arguments */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-maxtktlife")) { + if (++i > argc - 1) + goto err_usage; + + date = get_date(argv[i]); + if (date == (time_t)(-1)) { + retval = EINVAL; + com_err(me, retval, _("while providing time specification")); + goto err_nomsg; + } + + policyparams->maxtktlife = date - now; + + mask |= LDAP_POLICY_MAXTKTLIFE; + } else if (!strcmp(argv[i], "-maxrenewlife")) { + if (++i > argc - 1) + goto err_usage; + + date = get_date(argv[i]); + if (date == (time_t)(-1)) { + retval = EINVAL; + com_err(me, retval, _("while providing time specification")); + goto err_nomsg; + } + + policyparams->maxrenewlife = date - now; + + mask |= LDAP_POLICY_MAXRENEWLIFE; + } else if (!strcmp((argv[i] + 1), "allow_postdated")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_POSTDATED); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_POSTDATED; + else + goto err_usage; + + mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_forwardable")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_FORWARDABLE); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_FORWARDABLE; + else + goto err_usage; + + mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_renewable")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_RENEWABLE); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_RENEWABLE; + else + goto err_usage; + + mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_proxiable")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_PROXIABLE); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_PROXIABLE; + else + goto err_usage; + + mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_dup_skey")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_DUP_SKEY); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_DUP_SKEY; + else + goto err_usage; + + mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "requires_preauth")) { + if (*(argv[i]) == '+') + policyparams->tktflags |= KRB5_KDB_REQUIRES_PRE_AUTH; + else if (*(argv[i]) == '-') + policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PRE_AUTH); + else + goto err_usage; + + mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "requires_hwauth")) { + if (*(argv[i]) == '+') + policyparams->tktflags |= KRB5_KDB_REQUIRES_HW_AUTH; + else if (*(argv[i]) == '-') + policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_HW_AUTH); + else + goto err_usage; + + mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_svr")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_SVR); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_SVR; + else + goto err_usage; + + mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_tgs_req")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_TGT_BASED); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_TGT_BASED; + else + goto err_usage; + + mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_tix")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_ALL_TIX); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_ALL_TIX; + else + goto err_usage; + + mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "needchange")) { + if (*(argv[i]) == '+') + policyparams->tktflags |= KRB5_KDB_REQUIRES_PWCHANGE; + else if (*(argv[i]) == '-') + policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PWCHANGE); + else + goto err_usage; + + mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "password_changing_service")) { + if (*(argv[i]) == '+') + policyparams->tktflags |= KRB5_KDB_PWCHANGE_SERVICE; + else if (*(argv[i]) == '-') + policyparams->tktflags &= (int)(~KRB5_KDB_PWCHANGE_SERVICE); + else + goto err_usage; + + mask |= LDAP_POLICY_TKTFLAGS; + } else { /* Any other argument must be policy DN */ + /* First check if policy DN is already provided -- + if so, there's a usage error */ + if (policyparams->policy != NULL) + goto err_usage; + + /* If not present already, fill up policy DN */ + policyparams->policy = strdup(argv[i]); + if (policyparams->policy == NULL) { + retval = ENOMEM; + com_err(me, retval, _("while creating policy object")); + goto err_nomsg; + } + } + } + + /* policy DN is a mandatory argument. If not provided, print usage */ + if (policyparams->policy == NULL) + goto err_usage; + + if ((retval = init_ldap_realm (argc, argv))) { + com_err(me, retval, _("while reading realm information")); + goto err_nomsg; + } + + /* Create object with all attributes provided */ + if ((retval = krb5_ldap_create_policy(util_context, policyparams, mask)) != 0) + goto cleanup; + + goto cleanup; + +err_usage: + print_usage = TRUE; + +err_nomsg: + no_msg = TRUE; + +cleanup: + /* Clean-up structure */ + krb5_ldap_free_policy (util_context, policyparams); + + if (print_usage) + db_usage(CREATE_POLICY); + + if (retval) { + if (!no_msg) + com_err(me, retval, _("while creating policy object")); + + exit_status++; + } + + return; +} + + +/* + * This function will destroy the specified ticket policy + * object interactively, unless forced through an option. + */ +void +kdb5_ldap_destroy_policy(int argc, char *argv[]) +{ + char *me = progname; + krb5_error_code retval = 0; + krb5_ldap_policy_params *policyparams = NULL; + krb5_boolean print_usage = FALSE; + krb5_boolean no_msg = FALSE; + char *policy = NULL; + int mask = 0; + int force = 0; + char buf[5] = {0}; + int i = 0; + + if ((argc < 2) || (argc > 3)) { + goto err_usage; + } + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-force") == 0) { + force++; + } else { /* Any other argument must be policy DN */ + /* First check if policy DN is already provided -- + if so, there's a usage error */ + if (policy != NULL) + goto err_usage; + + /* If not present already, fill up policy DN */ + policy = strdup(argv[i]); + if (policy == NULL) { + retval = ENOMEM; + com_err(me, retval, _("while destroying policy object")); + goto err_nomsg; + } + } + } + + if (policy == NULL) + goto err_usage; + + if (!force) { + printf(_("This will delete the policy object '%s', are you sure?\n"), + policy); + printf(_("(type 'yes' to confirm)? ")); + + if (fgets(buf, sizeof(buf), stdin) == NULL) { + retval = EINVAL; + goto cleanup; + } + + if (strcmp(buf, yes)) { + exit_status++; + goto cleanup; + } + } + + if ((retval = init_ldap_realm (argc, argv))) + goto err_nomsg; + + if ((retval = krb5_ldap_read_policy(util_context, policy, &policyparams, &mask))) + goto cleanup; + + + if ((retval = krb5_ldap_delete_policy(util_context, policy))) + goto cleanup; + + printf("** policy object '%s' deleted.\n", policy); + goto cleanup; + + +err_usage: + print_usage = TRUE; + +err_nomsg: + no_msg = TRUE; + +cleanup: + /* Clean-up structure */ + krb5_ldap_free_policy (util_context, policyparams); + + if (policy) { + free (policy); + } + + if (print_usage) { + db_usage(DESTROY_POLICY); + } + + if (retval) { + if (!no_msg) + com_err(me, retval, _("while destroying policy object")); + + exit_status++; + } + + return; +} + + +/* + * This function will modify the attributes of a given ticket + * policy object. + */ +void +kdb5_ldap_modify_policy(int argc, char *argv[]) +{ + char *me = progname; + krb5_error_code retval = 0; + krb5_ldap_policy_params *policyparams = NULL; + krb5_boolean print_usage = FALSE; + krb5_boolean no_msg = FALSE; + char *policy = NULL; + int in_mask = 0, out_mask = 0; + time_t date = 0; + time_t now = 0; + int i = 0; + + /* Check for number of arguments -- minimum is 3 + since at least one parameter should be given in + addition to 'modify_policy' and policy DN */ + if ((argc < 3) || (argc > 16)) { + goto err_usage; + } + + /* Parse all arguments, only to pick up policy DN (Pass 1) */ + for (i = 1; i < argc; i++) { + /* Skip arguments next to 'maxtktlife' + and 'maxrenewlife' arguments */ + if (!strcmp(argv[i], "-maxtktlife")) { + ++i; + } else if (!strcmp(argv[i], "-maxrenewlife")) { + ++i; + } + /* Do nothing for ticket flag arguments */ + else if (!strcmp((argv[i] + 1), "allow_postdated") || + !strcmp((argv[i] + 1), "allow_forwardable") || + !strcmp((argv[i] + 1), "allow_renewable") || + !strcmp((argv[i] + 1), "allow_proxiable") || + !strcmp((argv[i] + 1), "allow_dup_skey") || + !strcmp((argv[i] + 1), "requires_preauth") || + !strcmp((argv[i] + 1), "requires_hwauth") || + !strcmp((argv[i] + 1), "allow_svr") || + !strcmp((argv[i] + 1), "allow_tgs_req") || + !strcmp((argv[i] + 1), "allow_tix") || + !strcmp((argv[i] + 1), "needchange") || + !strcmp((argv[i] + 1), "password_changing_service")) { + } else { /* Any other argument must be policy DN */ + /* First check if policy DN is already provided -- + if so, there's a usage error */ + if (policy != NULL) + goto err_usage; + + /* If not present already, fill up policy DN */ + policy = strdup(argv[i]); + if (policy == NULL) { + retval = ENOMEM; + com_err(me, retval, _("while modifying policy object")); + goto err_nomsg; + } + } + } + + if (policy == NULL) + goto err_usage; + + if ((retval = init_ldap_realm (argc, argv))) + goto cleanup; + + retval = krb5_ldap_read_policy(util_context, policy, &policyparams, &in_mask); + if (retval) { + com_err(me, retval, _("while reading information of policy '%s'"), + policy); + goto err_nomsg; + } + + /* Get current time */ + time (&now); + + /* Parse all arguments, but skip policy DN (Pass 2) */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-maxtktlife")) { + if (++i > argc - 1) + goto err_usage; + + date = get_date(argv[i]); + if (date == (time_t)(-1)) { + retval = EINVAL; + com_err(me, retval, _("while providing time specification")); + goto err_nomsg; + } + + policyparams->maxtktlife = date - now; + + out_mask |= LDAP_POLICY_MAXTKTLIFE; + } else if (!strcmp(argv[i], "-maxrenewlife")) { + if (++i > argc - 1) + goto err_usage; + + date = get_date(argv[i]); + if (date == (time_t)(-1)) { + retval = EINVAL; + com_err(me, retval, _("while providing time specification")); + goto err_nomsg; + } + + policyparams->maxrenewlife = date - now; + + out_mask |= LDAP_POLICY_MAXRENEWLIFE; + } else if (!strcmp((argv[i] + 1), "allow_postdated")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_POSTDATED); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_POSTDATED; + else + goto err_usage; + + out_mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_forwardable")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_FORWARDABLE); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_FORWARDABLE; + else + goto err_usage; + + out_mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_renewable")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_RENEWABLE); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_RENEWABLE; + else + goto err_usage; + + out_mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_proxiable")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_PROXIABLE); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_PROXIABLE; + else + goto err_usage; + + out_mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_dup_skey")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_DUP_SKEY); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_DUP_SKEY; + else + goto err_usage; + + out_mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "requires_preauth")) { + if (*(argv[i]) == '+') + policyparams->tktflags |= KRB5_KDB_REQUIRES_PRE_AUTH; + else if (*(argv[i]) == '-') + policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PRE_AUTH); + else + goto err_usage; + + out_mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "requires_hwauth")) { + if (*(argv[i]) == '+') + policyparams->tktflags |= KRB5_KDB_REQUIRES_HW_AUTH; + else if (*(argv[i]) == '-') + policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_HW_AUTH); + else + goto err_usage; + + out_mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_svr")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_SVR); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_SVR; + else + goto err_usage; + + out_mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_tgs_req")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_TGT_BASED); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_TGT_BASED; + else + goto err_usage; + + out_mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "allow_tix")) { + if (*(argv[i]) == '+') + policyparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_ALL_TIX); + else if (*(argv[i]) == '-') + policyparams->tktflags |= KRB5_KDB_DISALLOW_ALL_TIX; + else + goto err_usage; + + out_mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "needchange")) { + if (*(argv[i]) == '+') + policyparams->tktflags |= KRB5_KDB_REQUIRES_PWCHANGE; + else if (*(argv[i]) == '-') + policyparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PWCHANGE); + else + goto err_usage; + + out_mask |= LDAP_POLICY_TKTFLAGS; + } else if (!strcmp((argv[i] + 1), "password_changing_service")) { + if (*(argv[i]) == '+') + policyparams->tktflags |= KRB5_KDB_PWCHANGE_SERVICE; + else if (*(argv[i]) == '-') + policyparams->tktflags &= (int)(~KRB5_KDB_PWCHANGE_SERVICE); + else + goto err_usage; + + out_mask |= LDAP_POLICY_TKTFLAGS; + } else { + /* Any other argument must be policy DN + -- skip it */ + } + } + + /* Modify attributes of object */ + if ((retval = krb5_ldap_modify_policy(util_context, policyparams, out_mask))) + goto cleanup; + + goto cleanup; + +err_usage: + print_usage = TRUE; + +err_nomsg: + no_msg = TRUE; + +cleanup: + /* Clean-up structure */ + krb5_ldap_free_policy (util_context, policyparams); + + if (policy) + free (policy); + + if (print_usage) + db_usage(MODIFY_POLICY); + + if (retval) { + if (!no_msg) + com_err(me, retval, _("while modifying policy object")); + + exit_status++; + } + + return; +} + + +/* + * This function will display information about the given policy object, + * fetching the information from the LDAP Server. + */ +void +kdb5_ldap_view_policy(int argc, char *argv[]) +{ + char *me = progname; + krb5_ldap_policy_params *policyparams = NULL; + krb5_error_code retval = 0; + krb5_boolean print_usage = FALSE; + char *policy = NULL; + int mask = 0; + + if (argc != 2) { + goto err_usage; + } + + policy = strdup(argv[1]); + if (policy == NULL) { + com_err(me, ENOMEM, _("while viewing policy")); + exit_status++; + goto cleanup; + } + + if ((retval = init_ldap_realm (argc, argv))) + goto cleanup; + + if ((retval = krb5_ldap_read_policy(util_context, policy, &policyparams, &mask))) { + com_err(me, retval, _("while viewing policy '%s'"), policy); + exit_status++; + goto cleanup; + } + + print_policy_params (policyparams, mask); + + goto cleanup; + +err_usage: + print_usage = TRUE; + +cleanup: + krb5_ldap_free_policy (util_context, policyparams); + + if (policy) + free (policy); + + if (print_usage) { + db_usage(VIEW_POLICY); + } + + return; +} + + +/* + * This function will print the policy object information to the + * standard output. + */ +static void +print_policy_params(krb5_ldap_policy_params *policyparams, int mask) +{ + /* Print the policy DN */ + printf("%25s: %s\n", "Ticket policy", policyparams->policy); + + /* Print max. ticket life and max. renewable life, if present */ + if (mask & LDAP_POLICY_MAXTKTLIFE) + printf("%25s: %s\n", "Maximum ticket life", strdur(policyparams->maxtktlife)); + if (mask & LDAP_POLICY_MAXRENEWLIFE) + printf("%25s: %s\n", "Maximum renewable life", strdur(policyparams->maxrenewlife)); + + /* Service flags are printed */ + printf("%25s: ", "Ticket flags"); + if (mask & LDAP_POLICY_TKTFLAGS) { + int ticketflags = policyparams->tktflags; + + if (ticketflags & KRB5_KDB_DISALLOW_POSTDATED) + printf("%s ","DISALLOW_POSTDATED"); + + if (ticketflags & KRB5_KDB_DISALLOW_FORWARDABLE) + printf("%s ","DISALLOW_FORWARDABLE"); + + if (ticketflags & KRB5_KDB_DISALLOW_RENEWABLE) + printf("%s ","DISALLOW_RENEWABLE"); + + if (ticketflags & KRB5_KDB_DISALLOW_PROXIABLE) + printf("%s ","DISALLOW_PROXIABLE"); + + if (ticketflags & KRB5_KDB_DISALLOW_DUP_SKEY) + printf("%s ","DISALLOW_DUP_SKEY"); + + if (ticketflags & KRB5_KDB_REQUIRES_PRE_AUTH) + printf("%s ","REQUIRES_PRE_AUTH"); + + if (ticketflags & KRB5_KDB_REQUIRES_HW_AUTH) + printf("%s ","REQUIRES_HW_AUTH"); + + if (ticketflags & KRB5_KDB_DISALLOW_SVR) + printf("%s ","DISALLOW_SVR"); + + if (ticketflags & KRB5_KDB_DISALLOW_TGT_BASED) + printf("%s ","DISALLOW_TGT_BASED"); + + if (ticketflags & KRB5_KDB_DISALLOW_ALL_TIX) + printf("%s ","DISALLOW_ALL_TIX"); + + if (ticketflags & KRB5_KDB_REQUIRES_PWCHANGE) + printf("%s ","REQUIRES_PWCHANGE"); + + if (ticketflags & KRB5_KDB_PWCHANGE_SERVICE) + printf("%s ","PWCHANGE_SERVICE"); + } + printf("\n"); + + return; +} + + +/* + * This function will list the DNs of policy objects under a specific + * sub-tree (entire tree by default) + */ +void +kdb5_ldap_list_policies(int argc, char *argv[]) +{ + char *me = progname; + krb5_error_code retval = 0; + krb5_boolean print_usage = FALSE; + char **list = NULL; + char **plist = NULL; + + /* Check for number of arguments */ + if ((argc != 1) && (argc != 3)) { + goto err_usage; + } + + if ((retval = init_ldap_realm (argc, argv))) + goto cleanup; + + retval = krb5_ldap_list_policy(util_context, NULL, &list); + if ((retval != 0) || (list == NULL)) + goto cleanup; + + for (plist = list; *plist != NULL; plist++) { + printf("%s\n", *plist); + } + + goto cleanup; + +err_usage: + print_usage = TRUE; + +cleanup: + if (list != NULL) { + krb5_free_list_entries (list); + free (list); + } + + if (print_usage) { + db_usage(LIST_POLICY); + } + + if (retval) { + com_err(me, retval, _("while listing policy objects")); + exit_status++; + } + + return; +} + + +/* Reproduced from kadmin.c, instead of linking + the entire kadmin.o */ +static char * +strdur(time_t duration) +{ + static char out[50]; + int neg, days, hours, minutes, seconds; + + if (duration < 0) { + duration *= -1; + neg = 1; + } else + neg = 0; + days = duration / (24 * 3600); + duration %= 24 * 3600; + hours = duration / 3600; + duration %= 3600; + minutes = duration / 60; + duration %= 60; + seconds = duration; + snprintf(out, sizeof(out), "%s%d %s %02d:%02d:%02d", neg ? "-" : "", + days, days == 1 ? "day" : "days", hours, minutes, seconds); + return out; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h new file mode 100644 index 00000000..0d3948de --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h @@ -0,0 +1,35 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.h */ +/* Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + + +extern void kdb5_ldap_create_policy(int argc, char **argv); +extern void kdb5_ldap_destroy_policy(int argc, char **argv); +extern void kdb5_ldap_modify_policy(int argc, char **argv); +extern void kdb5_ldap_view_policy(int argc, char **argv); +extern void kdb5_ldap_list_policies(int argc, char **argv); diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c new file mode 100644 index 00000000..bba550ac --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c @@ -0,0 +1,1484 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c */ +/* + * Copyright 1990,1991,2001, 2002, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +/* + * Create / Modify / Destroy / View / List realm(s) + */ + +#include +#include +#include +#include "kdb5_ldap_util.h" +#include "kdb5_ldap_list.h" +#include +#include +extern time_t get_date(char *); /* kadmin/cli/getdate.o */ + +char *yes = "yes\n"; /* \n to compare against result of fgets */ + +krb5_data tgt_princ_entries[] = { + {0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME}, + {0, 0, 0} }; + +krb5_data db_creator_entries[] = { + {0, sizeof("db_creation")-1, "db_creation"} }; + + +static krb5_principal_data db_create_princ = { + 0, /* magic number */ + {0, 0, 0}, /* krb5_data realm */ + db_creator_entries, /* krb5_data *data */ + 1, /* int length */ + KRB5_NT_SRV_INST /* int type */ +}; + +extern char *mkey_password; +extern char *progname; +extern kadm5_config_params global_params; + +static void print_realm_params(krb5_ldap_realm_params *rparams, int mask); +static int kdb_ldap_create_principal (krb5_context context, krb5_principal + princ, enum ap_op op, + struct realm_info *pblock, + const krb5_keyblock *master_keyblock); + + +static char *strdur(time_t duration); +static int get_ticket_policy(krb5_ldap_realm_params *rparams, int *i, char *argv[],int argc); +static krb5_error_code krb5_dbe_update_mod_princ_data_new (krb5_context context, krb5_db_entry *entry, krb5_timestamp mod_date, krb5_const_principal mod_princ); +static krb5_error_code krb5_dbe_update_tl_data_new ( krb5_context context, krb5_db_entry *entry, krb5_tl_data *new_tl_data); + +#define ADMIN_LIFETIME 60*60*3 /* 3 hours */ +#define CHANGEPW_LIFETIME 60*5 /* 5 minutes */ + +static int +get_ticket_policy(krb5_ldap_realm_params *rparams, int *i, char *argv[], + int argc) +{ + time_t date; + time_t now; + int mask = 0; + krb5_error_code retval = 0; + char *me = progname; + + time(&now); + if (!strcmp(argv[*i], "-maxtktlife")) { + if (++(*i) > argc-1) + return 0; + date = get_date(argv[*i]); + if (date == (time_t)(-1)) { + retval = EINVAL; + com_err(me, retval, _("while providing time specification")); + return 0; + } + rparams->max_life = date-now; + mask |= LDAP_REALM_MAXTICKETLIFE; + } + + + else if (!strcmp(argv[*i], "-maxrenewlife")) { + if (++(*i) > argc-1) + return 0; + + date = get_date(argv[*i]); + if (date == (time_t)(-1)) { + retval = EINVAL; + com_err(me, retval, _("while providing time specification")); + return 0; + } + rparams->max_renewable_life = date-now; + mask |= LDAP_REALM_MAXRENEWLIFE; + } else if (!strcmp((argv[*i] + 1), "allow_postdated")) { + if (*(argv[*i]) == '+') + rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_POSTDATED); + else if (*(argv[*i]) == '-') + rparams->tktflags |= KRB5_KDB_DISALLOW_POSTDATED; + else + return 0; + + mask |= LDAP_REALM_KRBTICKETFLAGS; + } else if (!strcmp((argv[*i] + 1), "allow_forwardable")) { + if (*(argv[*i]) == '+') + rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_FORWARDABLE); + + else if (*(argv[*i]) == '-') + rparams->tktflags |= KRB5_KDB_DISALLOW_FORWARDABLE; + else + return 0; + + mask |= LDAP_REALM_KRBTICKETFLAGS; + } else if (!strcmp((argv[*i] + 1), "allow_renewable")) { + if (*(argv[*i]) == '+') + rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_RENEWABLE); + else if (*(argv[*i]) == '-') + rparams->tktflags |= KRB5_KDB_DISALLOW_RENEWABLE; + else + return 0; + + mask |= LDAP_REALM_KRBTICKETFLAGS; + } else if (!strcmp((argv[*i] + 1), "allow_proxiable")) { + if (*(argv[*i]) == '+') + rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_PROXIABLE); + else if (*(argv[*i]) == '-') + rparams->tktflags |= KRB5_KDB_DISALLOW_PROXIABLE; + else + return 0; + + mask |= LDAP_REALM_KRBTICKETFLAGS; + } else if (!strcmp((argv[*i] + 1), "allow_dup_skey")) { + if (*(argv[*i]) == '+') + rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_DUP_SKEY); + else if (*(argv[*i]) == '-') + rparams->tktflags |= KRB5_KDB_DISALLOW_DUP_SKEY; + else + return 0; + + mask |= LDAP_REALM_KRBTICKETFLAGS; + } + + else if (!strcmp((argv[*i] + 1), "requires_preauth")) { + if (*(argv[*i]) == '+') + rparams->tktflags |= KRB5_KDB_REQUIRES_PRE_AUTH; + else if (*(argv[*i]) == '-') + rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PRE_AUTH); + else + return 0; + + mask |= LDAP_REALM_KRBTICKETFLAGS; + } else if (!strcmp((argv[*i] + 1), "requires_hwauth")) { + if (*(argv[*i]) == '+') + rparams->tktflags |= KRB5_KDB_REQUIRES_HW_AUTH; + else if (*(argv[*i]) == '-') + rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_HW_AUTH); + else + return 0; + + mask |= LDAP_REALM_KRBTICKETFLAGS; + } else if (!strcmp((argv[*i] + 1), "allow_svr")) { + if (*(argv[*i]) == '+') + rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_SVR); + else if (*(argv[*i]) == '-') + rparams->tktflags |= KRB5_KDB_DISALLOW_SVR; + else + return 0; + + mask |= LDAP_REALM_KRBTICKETFLAGS; + } else if (!strcmp((argv[*i] + 1), "allow_tgs_req")) { + if (*(argv[*i]) == '+') + rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_TGT_BASED); + else if (*(argv[*i]) == '-') + rparams->tktflags |= KRB5_KDB_DISALLOW_TGT_BASED; + else + return 0; + + mask |= LDAP_REALM_KRBTICKETFLAGS; + } else if (!strcmp((argv[*i] + 1), "allow_tix")) { + if (*(argv[*i]) == '+') + rparams->tktflags &= (int)(~KRB5_KDB_DISALLOW_ALL_TIX); + else if (*(argv[*i]) == '-') + rparams->tktflags |= KRB5_KDB_DISALLOW_ALL_TIX; + else + return 0; + + mask |= LDAP_REALM_KRBTICKETFLAGS; + } else if (!strcmp((argv[*i] + 1), "needchange")) { + if (*(argv[*i]) == '+') + rparams->tktflags |= KRB5_KDB_REQUIRES_PWCHANGE; + else if (*(argv[*i]) == '-') + rparams->tktflags &= (int)(~KRB5_KDB_REQUIRES_PWCHANGE); + else + return 0; + + mask |= LDAP_REALM_KRBTICKETFLAGS; + } else if (!strcmp((argv[*i] + 1), "password_changing_service")) { + if (*(argv[*i]) == '+') + rparams->tktflags |= KRB5_KDB_PWCHANGE_SERVICE; + else if (*(argv[*i]) == '-') + rparams->tktflags &= (int)(~KRB5_KDB_PWCHANGE_SERVICE); + else + return 0; + + mask |=LDAP_REALM_KRBTICKETFLAGS; + } + + return mask; +} + +/* Create a special principal using two specified components. */ +static krb5_error_code +create_fixed_special(krb5_context context, struct realm_info *rinfo, + krb5_keyblock *mkey, const char *comp1, const char *comp2) +{ + krb5_error_code ret; + krb5_principal princ; + const char *realm = global_params.realm; + + ret = krb5_build_principal(context, &princ, strlen(realm), realm, comp1, + comp2, (const char *)NULL); + if (ret) + return ret; + ret = kdb_ldap_create_principal(context, princ, TGT_KEY, rinfo, mkey); + krb5_free_principal(context, princ); + return ret; + +} + +/* Create all special principals for the realm. */ +static krb5_error_code +create_special_princs(krb5_context context, krb5_principal master_princ, + krb5_keyblock *mkey) +{ + krb5_error_code ret; + struct realm_info rblock; + + rblock.max_life = global_params.max_life; + rblock.max_rlife = global_params.max_rlife; + rblock.expiration = global_params.expiration; + rblock.flags = global_params.flags; + rblock.key = mkey; + rblock.nkslist = global_params.num_keysalts; + rblock.kslist = global_params.keysalts; + + /* Create master principal. */ + rblock.flags |= KRB5_KDB_DISALLOW_ALL_TIX; + ret = kdb_ldap_create_principal(context, master_princ, MASTER_KEY, &rblock, + mkey); + if (ret) + return ret; + + /* Create local krbtgt principal. */ + rblock.flags = 0; + ret = create_fixed_special(context, &rblock, mkey, KRB5_TGS_NAME, + global_params.realm); + if (ret) + return ret; + + /* Create kadmin/admin. */ + rblock.max_life = ADMIN_LIFETIME; + rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED; + ret = create_fixed_special(context, &rblock, mkey, "kadmin", "admin"); + if (ret) + return ret; + + /* Create kadmin/changepw. */ + rblock.max_life = CHANGEPW_LIFETIME; + rblock.flags = KRB5_KDB_DISALLOW_TGT_BASED | KRB5_KDB_PWCHANGE_SERVICE; + ret = create_fixed_special(context, &rblock, mkey, "kadmin", "changepw"); + if (ret) + return ret; + + /* Create kadmin/history. */ + rblock.max_life = global_params.max_life; + rblock.flags = 0; + return create_fixed_special(context, &rblock, mkey, "kadmin", "history"); +} + +/* + * This function will create a realm on the LDAP Server, with + * the specified attributes. + */ +void +kdb5_ldap_create(int argc, char *argv[]) +{ + krb5_error_code retval = 0; + krb5_keyblock master_keyblock; + krb5_ldap_realm_params *rparams = NULL; + krb5_principal master_princ = NULL; + kdb5_dal_handle *dal_handle = NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_boolean realm_obj_created = FALSE; + krb5_boolean create_complete = FALSE; + krb5_boolean print_usage = FALSE; + krb5_boolean no_msg = FALSE; + char *oldcontainerref=NULL; + char pw_str[1024]; + int do_stash = 0; + int i = 0; + int mask = 0, ret_mask = 0; + char **list = NULL; + + memset(&master_keyblock, 0, sizeof(master_keyblock)); + + rparams = (krb5_ldap_realm_params *)malloc( + sizeof(krb5_ldap_realm_params)); + if (rparams == NULL) { + retval = ENOMEM; + goto cleanup; + } + memset(rparams, 0, sizeof(krb5_ldap_realm_params)); + + /* Parse the arguments */ + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-subtrees")) { + if (++i > argc-1) + goto err_usage; + + if (strncmp(argv[i], "", strlen(argv[i]))!=0) { + list = (char **) calloc(MAX_LIST_ENTRIES, sizeof(char *)); + if (list == NULL) { + retval = ENOMEM; + goto cleanup; + } + if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, list))) { + free(list); + list = NULL; + goto cleanup; + } + + rparams->subtreecount=0; + while (list[rparams->subtreecount]!=NULL) + (rparams->subtreecount)++; + rparams->subtree = list; + } else if (strncmp(argv[i], "", strlen(argv[i]))==0) { + /* dont allow subtree value to be set at the root(NULL, "") of the tree */ + com_err(progname, EINVAL, + _("for subtree while creating realm '%s'"), + global_params.realm); + goto err_nomsg; + } + rparams->subtree[rparams->subtreecount] = NULL; + mask |= LDAP_REALM_SUBTREE; + } else if (!strcmp(argv[i], "-containerref")) { + if (++i > argc-1) + goto err_usage; + if (strncmp(argv[i], "", strlen(argv[i]))==0) { + /* dont allow containerref value to be set at the root(NULL, "") of the tree */ + com_err(progname, EINVAL, + _("for container reference while creating realm '%s'"), + global_params.realm); + goto err_nomsg; + } + free(rparams->containerref); + rparams->containerref = strdup(argv[i]); + if (rparams->containerref == NULL) { + retval = ENOMEM; + goto cleanup; + } + mask |= LDAP_REALM_CONTREF; + } else if (!strcmp(argv[i], "-sscope")) { + if (++i > argc-1) + goto err_usage; + /* Possible values for search scope are + * one (or 1) and sub (or 2) + */ + if (!strcasecmp(argv[i], "one")) { + rparams->search_scope = 1; + } else if (!strcasecmp(argv[i], "sub")) { + rparams->search_scope = 2; + } else { + rparams->search_scope = atoi(argv[i]); + if ((rparams->search_scope != 1) && + (rparams->search_scope != 2)) { + com_err(progname, EINVAL, _("invalid search scope while " + "creating realm '%s'"), + global_params.realm); + goto err_nomsg; + } + } + mask |= LDAP_REALM_SEARCHSCOPE; + } + else if (!strcmp(argv[i], "-s")) { + do_stash = 1; + } else if ((ret_mask= get_ticket_policy(rparams,&i,argv,argc)) !=0) { + mask|=ret_mask; + } + + else { + printf(_("'%s' is an invalid option\n"), argv[i]); + goto err_usage; + } + } + + krb5_princ_set_realm_data(util_context, &db_create_princ, global_params.realm); + krb5_princ_set_realm_length(util_context, &db_create_princ, strlen(global_params.realm)); + + printf(_("Initializing database for realm '%s'\n"), global_params.realm); + + if (!mkey_password) { + unsigned int pw_size; + printf(_("You will be prompted for the database Master Password.\n")); + printf(_("It is important that you NOT FORGET this password.\n")); + fflush(stdout); + + pw_size = sizeof (pw_str); + memset(pw_str, 0, pw_size); + + retval = krb5_read_password(util_context, KRB5_KDC_MKEY_1, KRB5_KDC_MKEY_2, + pw_str, &pw_size); + if (retval) { + com_err(progname, retval, + _("while reading master key from keyboard")); + goto err_nomsg; + } + mkey_password = pw_str; + } + + rparams->realm_name = strdup(global_params.realm); + if (rparams->realm_name == NULL) { + retval = ENOMEM; + com_err(progname, ENOMEM, _("while creating realm '%s'"), + global_params.realm); + goto err_nomsg; + } + + dal_handle = util_context->dal_handle; + ldap_context = (krb5_ldap_context *) dal_handle->db_context; + if (!ldap_context) { + retval = EINVAL; + goto cleanup; + } + + /* read the kerberos container */ + retval = krb5_ldap_read_krbcontainer_dn(util_context, + &ldap_context->container_dn); + if (retval) { + /* Prompt the user for entering the DN of Kerberos container */ + char krb_location[MAX_KRB_CONTAINER_LEN]; + int krb_location_len = 0; + + printf(_("Enter DN of Kerberos container: ")); + if (fgets(krb_location, MAX_KRB_CONTAINER_LEN, stdin) != NULL) { + /* Remove the newline character at the end */ + krb_location_len = strlen(krb_location); + if ((krb_location[krb_location_len - 1] == '\n') || + (krb_location[krb_location_len - 1] == '\r')) { + krb_location[krb_location_len - 1] = '\0'; + krb_location_len--; + } + ldap_context->container_dn = strdup(krb_location); + if (ldap_context->container_dn == NULL) { + retval = ENOMEM; + goto cleanup; + } + } + } + + /* create the kerberos container if it doesn't exist */ + retval = krb5_ldap_create_krbcontainer(util_context, + ldap_context->container_dn); + if (retval) + goto cleanup; + + if ((retval = krb5_ldap_create_realm(util_context, + /* global_params.realm, */ rparams, mask))) { + goto cleanup; + } + + /* We just created the Realm container. Here starts our transaction tracking */ + realm_obj_created = TRUE; + + if ((retval = krb5_ldap_read_realm_params(util_context, + global_params.realm, + &(ldap_context->lrparams), + &mask))) { + com_err(progname, retval, _("while reading information of realm '%s'"), + global_params.realm); + goto err_nomsg; + } + free(ldap_context->lrparams->realm_name); + ldap_context->lrparams->realm_name = strdup(global_params.realm); + if (ldap_context->lrparams->realm_name == NULL) { + retval = ENOMEM; + goto cleanup; + } + + /* assemble & parse the master key name */ + if ((retval = krb5_db_setup_mkey_name(util_context, + global_params.mkey_name, + global_params.realm, + 0, &master_princ))) { + com_err(progname, retval, _("while setting up master key name")); + goto err_nomsg; + } + + /* Obtain master key from master password */ + { + krb5_data master_salt, pwd; + + pwd.data = mkey_password; + pwd.length = strlen(mkey_password); + retval = krb5_principal2salt(util_context, master_princ, &master_salt); + if (retval) { + com_err(progname, retval, _("while calculating master key salt")); + goto err_nomsg; + } + + retval = krb5_c_string_to_key(util_context, global_params.enctype, + &pwd, &master_salt, &master_keyblock); + + if (master_salt.data) + free(master_salt.data); + + if (retval) { + com_err(progname, retval, + _("while transforming master key from password")); + goto err_nomsg; + } + } + + /* Create special principals (not in the container reference). */ + oldcontainerref = ldap_context->lrparams->containerref; + ldap_context->lrparams->containerref = NULL; + retval = create_special_princs(util_context, master_princ, + &master_keyblock); + ldap_context->lrparams->containerref = oldcontainerref; + if (retval) { + com_err(progname, retval, _("while adding entries to the database")); + goto err_nomsg; + } + + /* The Realm creation is completed. Here is the end of transaction */ + create_complete = TRUE; + + /* Stash the master key only if '-s' option is specified */ + if (do_stash || global_params.mask & KADM5_CONFIG_STASH_FILE) { + krb5_kvno mkey_kvno; + /* + * Determine the kvno to use, it must be that used to create the master + * key princ. + */ + if (global_params.mask & KADM5_CONFIG_KVNO) + mkey_kvno = global_params.kvno; /* user specified */ + else + mkey_kvno = 1; /* Default */ + + retval = krb5_db_store_master_key(util_context, + global_params.stash_file, + master_princ, + mkey_kvno, + &master_keyblock, NULL); + if (retval) { + com_err(progname, errno, _("while storing key")); + printf(_("Warning: couldn't stash master key.\n")); + } + } + + goto cleanup; + + +err_usage: + print_usage = TRUE; + +err_nomsg: + no_msg = TRUE; + +cleanup: + /* If the Realm creation is not complete, do the roll-back here */ + if ((realm_obj_created) && (!create_complete)) + krb5_ldap_delete_realm(util_context, global_params.realm); + + if (rparams) + krb5_ldap_free_realm_params(rparams); + + memset (pw_str, 0, sizeof (pw_str)); + + if (print_usage) + db_usage(CREATE_REALM); + + if (retval) { + if (!no_msg) { + com_err(progname, retval, _("while creating realm '%s'"), + global_params.realm); + } + exit_status++; + } + + krb5_free_keyblock_contents(util_context, &master_keyblock); + krb5_free_principal(util_context, master_princ); +} + + +/* + * This function will modify the attributes of a given realm object + */ +void +kdb5_ldap_modify(int argc, char *argv[]) +{ + krb5_error_code retval = 0; + krb5_ldap_realm_params *rparams = NULL; + krb5_boolean print_usage = FALSE; + krb5_boolean no_msg = FALSE; + kdb5_dal_handle *dal_handle = NULL; + krb5_ldap_context *ldap_context=NULL; + int i = 0; + int mask = 0, rmask = 0, ret_mask = 0; + char **slist = {NULL}; + + dal_handle = util_context->dal_handle; + ldap_context = (krb5_ldap_context *) dal_handle->db_context; + if (!(ldap_context)) { + retval = EINVAL; + goto cleanup; + } + + retval = krb5_ldap_read_krbcontainer_dn(util_context, + &ldap_context->container_dn); + if (retval) { + com_err(progname, retval, + _("while reading Kerberos container information")); + goto err_nomsg; + } + + retval = krb5_ldap_read_realm_params(util_context, + global_params.realm, &rparams, &rmask); + if (retval) + goto cleanup; + /* Parse the arguments */ + for (i = 1; i < argc; i++) { + int k = 0; + if (!strcmp(argv[i], "-subtrees")) { + if (++i > argc-1) + goto err_usage; + + if (rmask & LDAP_REALM_SUBTREE) { + if (rparams->subtree) { + for (k=0; ksubtreecount && rparams->subtree[k]; k++) + free(rparams->subtree[k]); + free(rparams->subtree); + rparams->subtreecount=0; + rparams->subtree = NULL; + } + } + if (strncmp(argv[i] ,"", strlen(argv[i]))!=0) { + slist = (char **) calloc(MAX_LIST_ENTRIES, sizeof(char *)); + if (slist == NULL) { + retval = ENOMEM; + goto cleanup; + } + if ((retval = krb5_parse_list(argv[i], LIST_DELIMITER, slist))) { + free(slist); + slist = NULL; + goto cleanup; + } + + rparams->subtreecount=0; + while (slist[rparams->subtreecount]!=NULL) + (rparams->subtreecount)++; + rparams->subtree = slist; + } else if (strncmp(argv[i], "", strlen(argv[i]))==0) { + /* dont allow subtree value to be set at the root(NULL, "") of the tree */ + com_err(progname, EINVAL, + _("for subtree while modifying realm '%s'"), + global_params.realm); + goto err_nomsg; + } + rparams->subtree[rparams->subtreecount] = NULL; + mask |= LDAP_REALM_SUBTREE; + } else if (!strncmp(argv[i], "-containerref", strlen(argv[i]))) { + if (++i > argc-1) + goto err_usage; + if (strncmp(argv[i], "", strlen(argv[i]))==0) { + /* dont allow containerref value to be set at the root(NULL, "") of the tree */ + com_err(progname, EINVAL, _("for container reference while " + "modifying realm '%s'"), + global_params.realm); + goto err_nomsg; + } + free(rparams->containerref); + rparams->containerref = strdup(argv[i]); + if (rparams->containerref == NULL) { + retval = ENOMEM; + goto cleanup; + } + mask |= LDAP_REALM_CONTREF; + } else if (!strcmp(argv[i], "-sscope")) { + if (++i > argc-1) + goto err_usage; + /* Possible values for search scope are + * one (or 1) and sub (or 2) + */ + if (strcasecmp(argv[i], "one") == 0) { + rparams->search_scope = 1; + } else if (strcasecmp(argv[i], "sub") == 0) { + rparams->search_scope = 2; + } else { + rparams->search_scope = atoi(argv[i]); + if ((rparams->search_scope != 1) && + (rparams->search_scope != 2)) { + retval = EINVAL; + com_err(progname, retval, + _("specified for search scope while modifying " + "information of realm '%s'"), + global_params.realm); + goto err_nomsg; + } + } + mask |= LDAP_REALM_SEARCHSCOPE; + } + else if ((ret_mask= get_ticket_policy(rparams,&i,argv,argc)) !=0) { + mask|=ret_mask; + } else { + printf(_("'%s' is an invalid option\n"), argv[i]); + goto err_usage; + } + } + + if ((retval = krb5_ldap_modify_realm(util_context, + /* global_params.realm, */ rparams, mask))) { + goto cleanup; + } + + goto cleanup; + +err_usage: + print_usage = TRUE; + +err_nomsg: + no_msg = TRUE; + +cleanup: + krb5_ldap_free_realm_params(rparams); + + if (print_usage) { + db_usage(MODIFY_REALM); + } + + if (retval) { + if (!no_msg) + com_err(progname, retval, + _("while modifying information of realm '%s'"), + global_params.realm); + exit_status++; + } + + return; +} + + + +/* + * This function displays the attributes of a Realm + */ +void +kdb5_ldap_view(int argc, char *argv[]) +{ + krb5_ldap_realm_params *rparams = NULL; + krb5_error_code retval = 0; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + int mask = 0; + + dal_handle = util_context->dal_handle; + ldap_context = (krb5_ldap_context *) dal_handle->db_context; + if (!(ldap_context)) { + retval = EINVAL; + com_err(progname, retval, _("while initializing database")); + exit_status++; + return; + } + + /* Read the kerberos container information */ + retval = krb5_ldap_read_krbcontainer_dn(util_context, + &ldap_context->container_dn); + if (retval) { + com_err(progname, retval, + _("while reading kerberos container information")); + exit_status++; + return; + } + + if ((retval = krb5_ldap_read_realm_params(util_context, + global_params.realm, &rparams, &mask)) || (!rparams)) { + com_err(progname, retval, _("while reading information of realm '%s'"), + global_params.realm); + exit_status++; + return; + } + print_realm_params(rparams, mask); + krb5_ldap_free_realm_params(rparams); + + return; +} + +static char * +strdur(time_t duration) +{ + static char out[50]; + int neg, days, hours, minutes, seconds; + + if (duration < 0) { + duration *= -1; + neg = 1; + } else + neg = 0; + days = duration / (24 * 3600); + duration %= 24 * 3600; + hours = duration / 3600; + duration %= 3600; + minutes = duration / 60; + duration %= 60; + seconds = duration; + snprintf(out, sizeof(out), "%s%d %s %02d:%02d:%02d", neg ? "-" : "", + days, days == 1 ? "day" : "days", + hours, minutes, seconds); + return out; +} + +/* + * This function prints the attributes of a given realm to the + * standard output. + */ +static void +print_realm_params(krb5_ldap_realm_params *rparams, int mask) +{ + char **slist = NULL; + unsigned int num_entry_printed = 0, i = 0; + + /* Print the Realm Attributes on the standard output */ + printf("%25s: %-50s\n", _("Realm Name"), global_params.realm); + if (mask & LDAP_REALM_SUBTREE) { + for (i=0; rparams->subtree[i]!=NULL; i++) + printf("%25s: %-50s\n", _("Subtree"), rparams->subtree[i]); + } + if (mask & LDAP_REALM_CONTREF) + printf("%25s: %-50s\n", _("Principal Container Reference"), + rparams->containerref); + if (mask & LDAP_REALM_SEARCHSCOPE) { + if ((rparams->search_scope != 1) && + (rparams->search_scope != 2)) { + printf("%25s: %-50s\n", _("SearchScope"), _("Invalid !")); + } else { + printf("%25s: %-50s\n", _("SearchScope"), + (rparams->search_scope == 1) ? "ONE" : "SUB"); + } + } + if (mask & LDAP_REALM_KDCSERVERS) { + printf("%25s:", _("KDC Services")); + if (rparams->kdcservers != NULL) { + num_entry_printed = 0; + for (slist = rparams->kdcservers; *slist != NULL; slist++) { + if (num_entry_printed) + printf(" %25s %-50s\n", " ", *slist); + else + printf(" %-50s\n", *slist); + num_entry_printed++; + } + } + if (num_entry_printed == 0) + printf("\n"); + } + if (mask & LDAP_REALM_ADMINSERVERS) { + printf("%25s:", _("Admin Services")); + if (rparams->adminservers != NULL) { + num_entry_printed = 0; + for (slist = rparams->adminservers; *slist != NULL; slist++) { + if (num_entry_printed) + printf(" %25s %-50s\n", " ", *slist); + else + printf(" %-50s\n", *slist); + num_entry_printed++; + } + } + if (num_entry_printed == 0) + printf("\n"); + } + if (mask & LDAP_REALM_PASSWDSERVERS) { + printf("%25s:", _("Passwd Services")); + if (rparams->passwdservers != NULL) { + num_entry_printed = 0; + for (slist = rparams->passwdservers; *slist != NULL; slist++) { + if (num_entry_printed) + printf(" %25s %-50s\n", " ", *slist); + else + printf(" %-50s\n", *slist); + num_entry_printed++; + } + } + if (num_entry_printed == 0) + printf("\n"); + } + + if (mask & LDAP_REALM_MAXTICKETLIFE) { + printf("%25s:", _("Maximum Ticket Life")); + printf(" %s \n", strdur(rparams->max_life)); + } + + if (mask & LDAP_REALM_MAXRENEWLIFE) { + printf("%25s:", _("Maximum Renewable Life")); + printf(" %s \n", strdur(rparams->max_renewable_life)); + } + + if (mask & LDAP_REALM_KRBTICKETFLAGS) { + int ticketflags = rparams->tktflags; + + printf("%25s: ", _("Ticket flags")); + if (ticketflags & KRB5_KDB_DISALLOW_POSTDATED) + printf("%s ","DISALLOW_POSTDATED"); + + if (ticketflags & KRB5_KDB_DISALLOW_FORWARDABLE) + printf("%s ","DISALLOW_FORWARDABLE"); + + if (ticketflags & KRB5_KDB_DISALLOW_RENEWABLE) + printf("%s ","DISALLOW_RENEWABLE"); + + if (ticketflags & KRB5_KDB_DISALLOW_PROXIABLE) + printf("%s ","DISALLOW_PROXIABLE"); + + if (ticketflags & KRB5_KDB_DISALLOW_DUP_SKEY) + printf("%s ","DISALLOW_DUP_SKEY"); + + if (ticketflags & KRB5_KDB_REQUIRES_PRE_AUTH) + printf("%s ","REQUIRES_PRE_AUTH"); + + if (ticketflags & KRB5_KDB_REQUIRES_HW_AUTH) + printf("%s ","REQUIRES_HW_AUTH"); + + if (ticketflags & KRB5_KDB_DISALLOW_SVR) + printf("%s ","DISALLOW_SVR"); + + if (ticketflags & KRB5_KDB_DISALLOW_TGT_BASED) + printf("%s ","DISALLOW_TGT_BASED"); + + if (ticketflags & KRB5_KDB_DISALLOW_ALL_TIX) + printf("%s ","DISALLOW_ALL_TIX"); + + if (ticketflags & KRB5_KDB_REQUIRES_PWCHANGE) + printf("%s ","REQUIRES_PWCHANGE"); + + if (ticketflags & KRB5_KDB_PWCHANGE_SERVICE) + printf("%s ","PWCHANGE_SERVICE"); + + printf("\n"); + } + + + return; +} + + + +/* + * This function lists the Realm(s) present under the Kerberos container + * on the LDAP Server. + */ +void +kdb5_ldap_list(int argc, char *argv[]) +{ + char **list = NULL; + char **plist = NULL; + krb5_error_code retval = 0; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + + dal_handle = util_context->dal_handle; + ldap_context = (krb5_ldap_context *) dal_handle->db_context; + if (!(ldap_context)) { + retval = EINVAL; + exit_status++; + return; + } + + /* Read the kerberos container information */ + retval = krb5_ldap_read_krbcontainer_dn(util_context, + &ldap_context->container_dn); + if (retval) { + com_err(progname, retval, + _("while reading kerberos container information")); + exit_status++; + return; + } + + retval = krb5_ldap_list_realm(util_context, &list); + if (retval != 0) { + com_err(progname, retval, _("while listing realms")); + exit_status++; + return; + } + /* This is to handle the case of realm not present */ + if (list == NULL) + return; + + for (plist = list; *plist != NULL; plist++) { + printf("%s\n", *plist); + } + krb5_free_list_entries(list); + free(list); + + return; +} + +/* + * Duplicating the following two functions here because + * 'krb5_dbe_update_tl_data' uses backend specific memory allocation. The catch + * here is that the backend is not initialized - kdb5_ldap_util doesn't go + * through DAL. + * 1. krb5_dbe_update_tl_data + * 2. krb5_dbe_update_mod_princ_data + */ + +/* Start duplicate code ... */ + +static krb5_error_code +krb5_dbe_update_tl_data_new(krb5_context context, krb5_db_entry *entry, + krb5_tl_data *new_tl_data) +{ + krb5_tl_data *tl_data = NULL; + krb5_octet *tmp; + + /* copy the new data first, so we can fail cleanly if malloc() + * fails */ + if ((tmp = (krb5_octet *) malloc (new_tl_data->tl_data_length)) == NULL) + return (ENOMEM); + + /* Find an existing entry of the specified type and point at + * it, or NULL if not found */ + + if (new_tl_data->tl_data_type != KRB5_TL_DB_ARGS) { /* db_args can be multiple */ + for (tl_data = entry->tl_data; tl_data; + tl_data = tl_data->tl_data_next) + if (tl_data->tl_data_type == new_tl_data->tl_data_type) + break; + } + + /* if necessary, chain a new record in the beginning and point at it */ + + if (!tl_data) { + if ((tl_data = (krb5_tl_data *) malloc (sizeof(krb5_tl_data))) == NULL) { + free(tmp); + return (ENOMEM); + } + memset(tl_data, 0, sizeof(krb5_tl_data)); + tl_data->tl_data_next = entry->tl_data; + entry->tl_data = tl_data; + entry->n_tl_data++; + } + + /* fill in the record */ + + free(tl_data->tl_data_contents); + + tl_data->tl_data_type = new_tl_data->tl_data_type; + tl_data->tl_data_length = new_tl_data->tl_data_length; + tl_data->tl_data_contents = tmp; + memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length); + + return (0); +} + +static krb5_error_code +krb5_dbe_update_mod_princ_data_new(krb5_context context, krb5_db_entry *entry, + krb5_timestamp mod_date, + krb5_const_principal mod_princ) +{ + krb5_tl_data tl_data; + + krb5_error_code retval = 0; + krb5_octet * nextloc = 0; + char * unparse_mod_princ = 0; + unsigned int unparse_mod_princ_size; + + if ((retval = krb5_unparse_name(context, mod_princ, + &unparse_mod_princ))) + return(retval); + + unparse_mod_princ_size = strlen(unparse_mod_princ) + 1; + + if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4)) + == NULL) { + free(unparse_mod_princ); + return(ENOMEM); + } + + tl_data.tl_data_type = KRB5_TL_MOD_PRINC; + tl_data.tl_data_length = unparse_mod_princ_size + 4; + tl_data.tl_data_contents = nextloc; + + /* Mod Date */ + krb5_kdb_encode_int32(mod_date, nextloc); + + /* Mod Princ */ + memcpy(nextloc+4, unparse_mod_princ, unparse_mod_princ_size); + + retval = krb5_dbe_update_tl_data_new(context, entry, &tl_data); + + free(unparse_mod_princ); + free(nextloc); + + return(retval); +} + +static krb5_error_code +kdb_ldap_tgt_keysalt_iterate(krb5_key_salt_tuple *ksent, krb5_pointer ptr) +{ + krb5_context context; + krb5_error_code kret; + struct iterate_args *iargs; + krb5_keyblock key; + krb5_int32 ind; + krb5_data pwd; + krb5_db_entry *entry; + + iargs = (struct iterate_args *) ptr; + kret = 0; + + context = iargs->ctx; + entry = iargs->dbentp; + + /* + * Convert the master key password into a key for this particular + * encryption system. + */ + pwd.data = mkey_password; + pwd.length = strlen(mkey_password); + kret = krb5_c_random_seed(context, &pwd); + if (kret) + return kret; + + /*if (!(kret = krb5_dbe_create_key_data(iargs->ctx, iargs->dbentp))) {*/ + if ((entry->key_data = + (krb5_key_data *) realloc(entry->key_data, + (sizeof(krb5_key_data) * + (entry->n_key_data + 1)))) == NULL) + return (ENOMEM); + + memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data)); + ind = entry->n_key_data++; + + if (!(kret = krb5_c_make_random_key(context, ksent->ks_enctype, + &key))) { + kret = krb5_dbe_encrypt_key_data(context, iargs->rblock->key, &key, + NULL, 1, &entry->key_data[ind]); + krb5_free_keyblock_contents(context, &key); + } + /*}*/ + + return(kret); +} +/* End duplicate code */ + +/* + * This function creates service principals when + * creating the realm object. + */ +static int +kdb_ldap_create_principal(krb5_context context, krb5_principal princ, + enum ap_op op, struct realm_info *pblock, + const krb5_keyblock *master_keyblock) +{ + int retval=0, currlen=0, princtype = 2 /* Service Principal */; + unsigned char *curr=NULL; + krb5_tl_data *tl_data=NULL; + krb5_db_entry entry; + long mask = 0; + krb5_keyblock key; + int kvno = 0; + kdb5_dal_handle *dal_handle = NULL; + krb5_ldap_context *ldap_context=NULL; + struct iterate_args iargs; + krb5_data *pdata; + krb5_timestamp now; + krb5_actkvno_node actkvno; + + memset(&entry, 0, sizeof(entry)); + + if ((pblock == NULL) || (context == NULL)) { + retval = EINVAL; + goto cleanup; + } + dal_handle = context->dal_handle; + ldap_context = (krb5_ldap_context *) dal_handle->db_context; + if (!(ldap_context)) { + retval = EINVAL; + goto cleanup; + } + + tl_data = malloc(sizeof(*tl_data)); + if (tl_data == NULL) { + retval = ENOMEM; + goto cleanup; + } + memset(tl_data, 0, sizeof(*tl_data)); + tl_data->tl_data_length = 1 + 2 + 2 + 1 + 2 + 4; + tl_data->tl_data_type = 7; /* KDB_TL_USER_INFO */ + curr = tl_data->tl_data_contents = malloc(tl_data->tl_data_length); + if (tl_data->tl_data_contents == NULL) { + retval = ENOMEM; + goto cleanup; + } + + memset(curr, 1, 1); /* Passing the mask as principal type */ + curr += 1; + currlen = 2; + STORE16_INT(curr, currlen); + curr += currlen; + STORE16_INT(curr, princtype); + curr += currlen; + + mask |= KADM5_PRINCIPAL; + mask |= KADM5_ATTRIBUTES ; + mask |= KADM5_MAX_LIFE ; + mask |= KADM5_MAX_RLIFE ; + mask |= KADM5_PRINC_EXPIRE_TIME ; + mask |= KADM5_KEY_DATA; + + entry.tl_data = tl_data; + entry.n_tl_data += 1; + /* Set the creator's name */ + if ((retval = krb5_timeofday(context, &now))) + goto cleanup; + if ((retval = krb5_dbe_update_mod_princ_data_new(context, &entry, + now, &db_create_princ))) + goto cleanup; + + entry.attributes = pblock->flags | KRB5_KDB_LOCKDOWN_KEYS; + entry.max_life = pblock->max_life; + entry.max_renewable_life = pblock->max_rlife; + entry.expiration = pblock->expiration; + entry.mask = mask; + if ((retval = krb5_copy_principal(context, princ, &entry.princ))) + goto cleanup; + + + switch (op) { + case TGT_KEY: + if ((pdata = krb5_princ_component(context, princ, 1)) && + pdata->length == strlen("history") && + !memcmp(pdata->data, "history", strlen("history"))) { + + /* Allocate memory for storing the key */ + if ((entry.key_data = (krb5_key_data *) malloc( + sizeof(krb5_key_data))) == NULL) { + retval = ENOMEM; + goto cleanup; + } + + memset(entry.key_data, 0, sizeof(krb5_key_data)); + entry.n_key_data++; + + retval = krb5_c_make_random_key(context, global_params.enctype, &key); + if (retval) { + goto cleanup; + } + kvno = 1; /* New key is getting set */ + retval = krb5_dbe_encrypt_key_data(context, master_keyblock, + &key, NULL, kvno, + &entry.key_data[entry.n_key_data - 1]); + krb5_free_keyblock_contents(context, &key); + if (retval) { + goto cleanup; + } + } else { + /*retval = krb5_c_make_random_key(context, 16, &key) ;*/ + iargs.ctx = context; + iargs.rblock = pblock; + iargs.dbentp = &entry; + + /* + * Iterate through the key/salt list, ignoring salt types. + */ + if ((retval = krb5_keysalt_iterate(pblock->kslist, + pblock->nkslist, + 1, + kdb_ldap_tgt_keysalt_iterate, + (krb5_pointer) &iargs))) + return retval; + } + break; + + case MASTER_KEY: + /* Allocate memory for storing the key */ + if ((entry.key_data = (krb5_key_data *) malloc( + sizeof(krb5_key_data))) == NULL) { + retval = ENOMEM; + goto cleanup; + } + + memset(entry.key_data, 0, sizeof(krb5_key_data)); + entry.n_key_data++; + kvno = 1; /* New key is getting set */ + retval = krb5_dbe_encrypt_key_data(context, pblock->key, + master_keyblock, NULL, kvno, + &entry.key_data[entry.n_key_data - 1]); + if (retval) { + goto cleanup; + } + /* + * There should always be at least one "active" mkey so creating the + * KRB5_TL_ACTKVNO entry now so the initial mkey is active. + */ + actkvno.next = NULL; + actkvno.act_kvno = kvno; + actkvno.act_time = now; + retval = krb5_dbe_update_actkvno(context, &entry, &actkvno); + if (retval) + goto cleanup; + + break; + + case NULL_KEY: + default: + break; + } /* end of switch */ + + retval = krb5_ldap_put_principal(context, &entry, NULL); + if (retval) { + com_err(NULL, retval, _("while adding entries to database")); + goto cleanup; + } + +cleanup: + krb5_dbe_free_contents(context, &entry); + return retval; +} + + +/* + * This function destroys the realm object and the associated principals + */ +void +kdb5_ldap_destroy(int argc, char *argv[]) +{ + extern char *optarg; + extern int optind; + int optchar = 0; + char buf[5] = {0}; + krb5_error_code retval = 0; + int force = 0; + int mask = 0; + kdb5_dal_handle *dal_handle = NULL; + krb5_ldap_context *ldap_context = NULL; + + optind = 1; + while ((optchar = getopt(argc, argv, "f")) != -1) { + switch (optchar) { + case 'f': + force++; + break; + case '?': + default: + db_usage(DESTROY_REALM); + return; + /*NOTREACHED*/ + } + } + + if (!force) { + printf(_("Deleting KDC database of '%s', are you sure?\n"), + global_params.realm); + printf(_("(type 'yes' to confirm)? ")); + if (fgets(buf, sizeof(buf), stdin) == NULL) { + exit_status++; + return; + } + if (strcmp(buf, yes)) { + exit_status++; + return; + } + printf(_("OK, deleting database of '%s'...\n"), global_params.realm); + } + + dal_handle = util_context->dal_handle; + ldap_context = (krb5_ldap_context *) dal_handle->db_context; + if (!(ldap_context)) { + com_err(progname, EINVAL, _("while initializing database")); + exit_status++; + return; + } + + /* Read the kerberos container DN */ + retval = krb5_ldap_read_krbcontainer_dn(util_context, + &ldap_context->container_dn); + if (retval) { + com_err(progname, retval, + _("while reading kerberos container information")); + exit_status++; + return; + } + + /* Read the Realm information from the LDAP Server */ + if ((retval = krb5_ldap_read_realm_params(util_context, global_params.realm, + &(ldap_context->lrparams), &mask)) != 0) { + com_err(progname, retval, _("while reading realm information")); + exit_status++; + return; + } + + /* Delete the realm container and all the associated principals */ + retval = krb5_ldap_delete_realm(util_context, global_params.realm); + if (retval) { + com_err(progname, retval, + _("deleting database of '%s'"), global_params.realm); + exit_status++; + return; + } + + printf(_("** Database of '%s' destroyed.\n"), global_params.realm); + + return; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h new file mode 100644 index 00000000..aa086fe6 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h @@ -0,0 +1,59 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.h */ +/* Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#define BUFF_LEN 64 /* Max len of enctype string */ +#define MAX_PRINC_SIZE 256 + +enum ap_op { + NULL_KEY, /* setup null keys */ + MASTER_KEY, /* use master key as new key */ + TGT_KEY /* special handling for tgt key */ +}; + +struct realm_info { + krb5_deltat max_life; + krb5_deltat max_rlife; + krb5_timestamp expiration; + krb5_flags flags; + krb5_keyblock *key; + krb5_int32 nkslist; + krb5_key_salt_tuple *kslist; +}; + +struct iterate_args { + krb5_context ctx; + struct realm_info *rblock; + krb5_db_entry *dbentp; +}; + +extern void kdb5_ldap_create(int argc, char **argv); +extern void kdb5_ldap_destroy(int argc, char **argv); +extern void kdb5_ldap_modify(int argc, char **argv); +extern void kdb5_ldap_view(int argc, char **argv); +extern void kdb5_ldap_list(int argc, char **argv); diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c new file mode 100644 index 00000000..e87688d6 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c @@ -0,0 +1,319 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c */ +/* Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +/* + * Create / Delete / Modify / View / List service objects. + */ + +/* + * Service objects have rights over realm objects and principals. The following + * functions manage the service objects. + */ + +#include +#include +#include "kdb5_ldap_util.h" +#include "kdb5_ldap_list.h" + +/* Get the configured LDAP service password file. The caller should free the + * result with profile_release_string(). */ +static krb5_error_code +get_conf_service_file(profile_t profile, const char *realm, char **path_out) +{ + char *subsection, *path; + long ret; + + *path_out = NULL; + + /* Get the [dbmodules] subsection for realm. */ + ret = profile_get_string(profile, KDB_REALM_SECTION, realm, + KDB_MODULE_POINTER, realm, &subsection); + if (ret) + return ret; + + /* Look up the password file in the [dbmodules] subsection. */ + ret = profile_get_string(profile, KDB_MODULE_SECTION, subsection, + KRB5_CONF_LDAP_SERVICE_PASSWORD_FILE, NULL, + &path); + profile_release_string(subsection); + if (ret) + return ret; + + if (path == NULL) { + /* Look up the password file in [dbdefaults] as a fallback. */ + ret = profile_get_string(profile, KDB_MODULE_DEF_SECTION, + KRB5_CONF_LDAP_SERVICE_PASSWORD_FILE, NULL, + NULL, &path); + if (ret) + return ret; + } + + if (path == NULL) { + k5_setmsg(util_context, ENOENT, + _("ldap_service_password_file not configured")); + return ENOENT; + } + + *path_out = path; + return 0; +} + +/* + * Convert the user supplied password into hexadecimal and stash it. Only a + * little more secure than storing plain password in the file ... + */ +void +kdb5_ldap_stash_service_password(int argc, char **argv) +{ + int ret = 0; + unsigned int passwd_len = 0; + char *me = progname; + char *service_object = NULL; + char *file_name = NULL, *tmp_file = NULL; + char passwd[MAX_SERVICE_PASSWD_LEN]; + char *str = NULL, *hexpasswd = NULL; + char line[MAX_LEN]; + FILE *pfile = NULL; + krb5_boolean print_usage = FALSE; + mode_t old_mode = 0; + + /* + * Format: + * stashsrvpw [-f filename] service_dn + * where + * 'service_dn' is the DN of the service object + * 'filename' is the path of the stash file + */ + if (argc != 2 && argc != 4) { + print_usage = TRUE; + goto cleanup; + } + + if (argc == 4) { + /* Find the stash file name */ + if (strcmp (argv[1], "-f") == 0) { + if (((file_name = strdup (argv[2])) == NULL) || + ((service_object = strdup (argv[3])) == NULL)) { + com_err(me, ENOMEM, + _("while setting service object password")); + goto cleanup; + } + } else if (strcmp (argv[2], "-f") == 0) { + if (((file_name = strdup (argv[3])) == NULL) || + ((service_object = strdup (argv[1])) == NULL)) { + com_err(me, ENOMEM, + _("while setting service object password")); + goto cleanup; + } + } else { + print_usage = TRUE; + goto cleanup; + } + } else { /* argc == 2 */ + service_object = strdup (argv[1]); + if (service_object == NULL) { + com_err(me, ENOMEM, _("while setting service object password")); + goto cleanup; + } + + ret = get_conf_service_file(util_context->profile, + util_context->default_realm, &file_name); + if (ret) { + com_err(me, ret, _("while getting service password filename")); + goto cleanup; + } + } + + /* Get password from user */ + { + char prompt1[256], prompt2[256]; + + /* Get the service object password from the terminal */ + memset(passwd, 0, sizeof (passwd)); + passwd_len = sizeof (passwd); + + snprintf(prompt1, sizeof(prompt1), _("Password for \"%s\""), + service_object); + + snprintf(prompt2, sizeof(prompt2), _("Re-enter password for \"%s\""), + service_object); + + ret = krb5_read_password(util_context, prompt1, prompt2, passwd, &passwd_len); + if (ret != 0) { + com_err(me, ret, _("while setting service object password")); + memset(passwd, 0, sizeof (passwd)); + goto cleanup; + } + + if (passwd_len == 0) { + printf(_("%s: Invalid password\n"), me); + memset(passwd, 0, MAX_SERVICE_PASSWD_LEN); + goto cleanup; + } + } + + /* Convert the password to hexadecimal */ + ret = k5_hex_encode(passwd, passwd_len, FALSE, &hexpasswd); + zap(passwd, passwd_len); + if (ret != 0) { + com_err(me, ret, _("Failed to convert the password to hexadecimal")); + goto cleanup; + } + + /* TODO: file lock for the service password file */ + + /* set password in the file */ + old_mode = umask(0177); + pfile = fopen(file_name, "a+"); + if (pfile == NULL) { + com_err(me, errno, _("Failed to open file %s: %s"), file_name, + strerror (errno)); + goto cleanup; + } + set_cloexec_file(pfile); + rewind (pfile); + umask(old_mode); + + while (fgets (line, MAX_LEN, pfile) != NULL) { + if ((str = strstr (line, service_object)) != NULL) { + /* White spaces not allowed */ + if (line [strlen (service_object)] == '#') + break; + str = NULL; + } + } + + if (str == NULL) { + if (feof(pfile)) { + /* If the service object dn is not present in the service password file */ + if (fprintf(pfile, "%s#{HEX}%s\n", service_object, hexpasswd) < 0) { + com_err(me, errno, + _("Failed to write service object password to file")); + fclose(pfile); + goto cleanup; + } + } else { + com_err(me, errno, + _("Error reading service object password file")); + fclose(pfile); + goto cleanup; + } + fclose(pfile); + } else { + /* + * Password entry for the service object is already present in the file + * Delete the existing entry and add the new entry + */ + FILE *newfile; + + mode_t omask; + + /* Create a new file with the extension .tmp */ + if (asprintf(&tmp_file,"%s.tmp",file_name) < 0) { + com_err(me, ENOMEM, _("while setting service object password")); + fclose(pfile); + goto cleanup; + } + + omask = umask(077); + newfile = fopen(tmp_file, "w"); + umask (omask); + if (newfile == NULL) { + com_err(me, errno, _("Error creating file %s"), tmp_file); + fclose(pfile); + goto cleanup; + } + set_cloexec_file(newfile); + + fseek(pfile, 0, SEEK_SET); + while (fgets(line, MAX_LEN, pfile) != NULL) { + if (((str = strstr(line, service_object)) != NULL) && + (line[strlen(service_object)] == '#')) { + if (fprintf(newfile, "%s#{HEX}%s\n", service_object, hexpasswd) < 0) { + com_err(me, errno, _("Failed to write service object " + "password to file")); + fclose(newfile); + unlink(tmp_file); + fclose(pfile); + goto cleanup; + } + } else { + if (fprintf (newfile, "%s", line) < 0) { + com_err(me, errno, _("Failed to write service object " + "password to file")); + fclose(newfile); + unlink(tmp_file); + fclose(pfile); + goto cleanup; + } + } + } + + if (!feof(pfile)) { + com_err(me, errno, + _("Error reading service object password file")); + fclose(newfile); + unlink(tmp_file); + fclose(pfile); + goto cleanup; + } + + /* TODO: file lock for the service password file */ + + fclose(pfile); + fclose(newfile); + + ret = rename(tmp_file, file_name); + if (ret != 0) { + com_err(me, errno, + _("Failed to write service object password to file")); + goto cleanup; + } + } + ret = 0; + +cleanup: + + zapfreestr(hexpasswd); + + if (service_object) + free(service_object); + + profile_release_string(file_name); + + if (tmp_file) + free(tmp_file); + + if (print_usage) + usage(); +/* db_usage(STASH_SRV_PW); */ + + if (ret) + exit_status++; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h new file mode 100644 index 00000000..08af62e1 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h @@ -0,0 +1,35 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/ldap_util/kdb5_ldap_services.h */ +/* Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "ldap_misc.h" + +#define MAX_LEN 1024 +#define MAX_SERVICE_PASSWD_LEN 256 + +extern void kdb5_ldap_stash_service_password(int argc, char **argv); diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c new file mode 100644 index 00000000..0b56ba86 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c @@ -0,0 +1,608 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c */ +/* + * (C) Copyright 1990,1991, 1996, 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +/* Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include +#include +#include +#include +#include +#include "kdb5_ldap_util.h" + +typedef void (*cmd_func)(int, char **); +int cmd_index(char *name); + +char *mkey_password = 0; +int exit_status = 0; +krb5_context util_context; +kadm5_config_params global_params; +krb5_boolean db_inited = FALSE; + +char *progname; +krb5_boolean manual_mkey = FALSE; + +/* + * This function prints the usage of kdb5_ldap_util, which is + * the LDAP configuration utility. + */ +void +usage(void) +{ + fprintf(stderr, + _("Usage: kdb5_ldap_util [-D user_dn [-w passwd]] [-H ldapuri] " + "[-r realm]\n" + "\tcmd [cmd_options]\n" + +/* Create realm */ + "create [-subtrees subtree_dn_list] [-sscope search_scope]\n" + "\t\t[-containerref container_reference_dn]\n" + "\t\t[-m|-P password|-sf stashfilename] [-s]\n" + "\t\t[-k mkeytype] [-kv mkeyVNO] [-M mkeyname]\n" + "\t\t[-maxtktlife max_ticket_life]\n" + "\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags]\n" + +/* modify realm */ + "modify [-subtrees subtree_dn_list] [-sscope search_scope]\n" + "\t\t[-containerref container_reference_dn]\n" + "\t\t[-maxtktlife max_ticket_life]\n" + "\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags]\n" +/* View realm */ + "view\n" + +/* Destroy realm */ + "destroy [-f]\n" + +/* List realms */ + "list\n" + +/* Stash the service password */ + "stashsrvpw [-f filename] service_dn\n" + +/* Create policy */ + "create_policy [-maxtktlife max_ticket_life]\n" + "\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n" + +/* Modify policy */ + "modify_policy [-maxtktlife max_ticket_life]\n" + "\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n" + +/* View policy */ + "view_policy policy\n" + +/* Destroy policy */ + "destroy_policy [-force] policy\n" + +/* List policies */ + "list_policy\n")); +} + +void +db_usage(int type) +{ + /* + * This should print usage of 'type' command. For now, we will print usage + * of all commands. + */ + usage (); +} + +/* The help messages for all sub-commands should be in the + * same order as listed in this table. + */ +static struct _cmd_table { + char *name; + cmd_func func; + int opendb; +} cmd_table[] = { + {"create", kdb5_ldap_create, 1}, + {"modify", kdb5_ldap_modify, 1}, + {"view", kdb5_ldap_view, 1}, + {"destroy", kdb5_ldap_destroy, 1}, + {"list", kdb5_ldap_list, 1}, + {"stashsrvpw", kdb5_ldap_stash_service_password, 0}, + {"create_policy", kdb5_ldap_create_policy, 1}, + {"modify_policy", kdb5_ldap_modify_policy, 1}, + {"view_policy", kdb5_ldap_view_policy, 1}, + {"destroy_policy", kdb5_ldap_destroy_policy, 1}, + {"list_policy", kdb5_ldap_list_policies, 1}, + {NULL, NULL, 0}, +}; + + +/* + * The function cmd_lookup returns the structure matching the + * command name and returns NULL if nothing matches. + */ +static struct _cmd_table *cmd_lookup(name) + char *name; +{ + int i; + + for (i = 0; cmd_table[i].name != NULL; i++) + if (strcmp(cmd_table[i].name, name) == 0) + return &cmd_table[i]; + + return NULL; +} + + +/* + * The function cmd_index provides the offset of the command + * in the command table, which can be used to get the corresponding + * help from the help message table. + */ +int +cmd_index(char *name) +{ + int i; + + if (name == NULL) + return -1; + + for (i = 0; cmd_table[i].name != NULL; i++) + if (strcmp(cmd_table[i].name, name) == 0) + return i; + + return -1; +} + +static void +extended_com_err_fn(const char *myprog, errcode_t code, const char *fmt, + va_list args) +{ + const char *emsg; + emsg = krb5_get_error_message (util_context, code); + fprintf (stderr, "%s: %s ", myprog, emsg); + krb5_free_error_message (util_context, emsg); + vfprintf (stderr, fmt, args); + fprintf (stderr, "\n"); +} + +int +main(int argc, char *argv[]) +{ + struct _cmd_table *cmd = NULL; + char *koptarg = NULL, **cmd_argv = NULL; + int cmd_argc = 0; + krb5_error_code retval; + int usage_print = 0; + int gp_is_static = 1; + krb5_error_code db_retval = 1; + char *bind_dn = NULL; + char *passwd = NULL; + char *ldap_server = NULL; + unsigned int ldapmask = 0; + unsigned int passwd_len = 0; + char *prompt = NULL; + krb5_ldap_context *ldap_context=NULL; + char *value = NULL, *conf_section = NULL; + krb5_boolean realm_name_required = TRUE; + krb5_boolean print_help_message = FALSE; + + /* + * Ensure that "progname" is set before calling com_err. + */ + setlocale(LC_ALL, ""); + progname = (strrchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]); + + retval = kadm5_init_krb5_context(&util_context); + set_com_err_hook(extended_com_err_fn); + if (retval) { + com_err(progname, retval, _("while initializing Kerberos code")); + exit_status++; + goto cleanup; + } + + cmd_argv = (char **) malloc(sizeof(char *)*argc); + if (cmd_argv == NULL) { + com_err(progname, ENOMEM, _("while creating sub-command arguments")); + exit_status++; + goto cleanup; + } + memset(cmd_argv, 0, sizeof(char *)*argc); + cmd_argc = 1; + + memset(&global_params, 0, sizeof(kadm5_config_params)); + + argv++; argc--; + while (*argv) { + if (strcmp(*argv, "--help") == 0) { + print_help_message = TRUE; + } + if (strcmp(*argv, "-P") == 0 && ARG_VAL) { + mkey_password = koptarg; + manual_mkey = TRUE; + } else if (strcmp(*argv, "-r") == 0 && ARG_VAL) { + global_params.realm = koptarg; + global_params.mask |= KADM5_CONFIG_REALM; + /* not sure this is really necessary */ + if ((retval = krb5_set_default_realm(util_context, + global_params.realm))) { + com_err(progname, retval, + _("while setting default realm name")); + exit_status++; + goto cleanup; + } + } else if (strcmp(*argv, "-k") == 0 && ARG_VAL) { + if (krb5_string_to_enctype(koptarg, &global_params.enctype)) { + com_err(progname, EINVAL, + _(": %s is an invalid enctype"), koptarg); + exit_status++; + goto cleanup; + } else + global_params.mask |= KADM5_CONFIG_ENCTYPE; + } else if (strcmp(*argv, "-kv") == 0 && ARG_VAL) { + global_params.kvno = (krb5_kvno) atoi(koptarg); + if (global_params.kvno == IGNORE_VNO) { + com_err(progname, EINVAL, + _(": %s is an invalid mkeyVNO"), koptarg); + exit_status++; + goto cleanup; + } else + global_params.mask |= KADM5_CONFIG_KVNO; + } else if (strcmp(*argv, "-M") == 0 && ARG_VAL) { + global_params.mkey_name = koptarg; + global_params.mask |= KADM5_CONFIG_MKEY_NAME; + } else if (strcmp(*argv, "-sf") == 0 && ARG_VAL) { + global_params.stash_file = koptarg; + global_params.mask |= KADM5_CONFIG_STASH_FILE; + } else if (strcmp(*argv, "-m") == 0) { + manual_mkey = TRUE; + global_params.mkey_from_kbd = 1; + global_params.mask |= KADM5_CONFIG_MKEY_FROM_KBD; + } else if (strcmp(*argv, "-D") == 0 && ARG_VAL) { + bind_dn = koptarg; + if (bind_dn == NULL) { + com_err(progname, ENOMEM, _("while reading ldap parameters")); + exit_status++; + goto cleanup; + } + ldapmask |= CMD_LDAP_D; + } else if (strcmp(*argv, "-w") == 0 && ARG_VAL) { + passwd = strdup(koptarg); + if (passwd == NULL) { + com_err(progname, ENOMEM, _("while reading ldap parameters")); + exit_status++; + goto cleanup; + } + ldapmask |= CMD_LDAP_W; + } else if (strcmp(*argv, "-H") == 0 && ARG_VAL) { + ldap_server = koptarg; + if (ldap_server == NULL) { + com_err(progname, ENOMEM, _("while reading ldap parameters")); + exit_status++; + goto cleanup; + } + ldapmask |= CMD_LDAP_H; + } else if (cmd_lookup(*argv) != NULL) { + if (cmd_argv[0] == NULL) + cmd_argv[0] = *argv; + else { + free(cmd_argv); + cmd_argv = NULL; + usage(); + goto cleanup; + } + } else { + cmd_argv[cmd_argc++] = *argv; + } + argv++; argc--; + } + + if (cmd_argv[0] == NULL) { + free(cmd_argv); + cmd_argv = NULL; + usage(); + goto cleanup; + } + + /* if we need to print the help message (because of --help option) + * we will print the help corresponding to the sub-command. + */ + if (print_help_message) { + free(cmd_argv); + cmd_argv = NULL; + usage(); + goto cleanup; + } + + /* We need to check for the presence of default realm name only in + * the case of realm related operations like create, destroy etc. + */ + if ((strcmp(cmd_argv[0], "list") == 0) || + (strcmp(cmd_argv[0], "stashsrvpw") == 0)) { + realm_name_required = FALSE; + } + + if (!util_context->default_realm) { + char *temp = NULL; + retval = krb5_get_default_realm(util_context, &temp); + if (retval) { + if (realm_name_required) { + com_err (progname, retval, _("while getting default realm")); + exit_status++; + goto cleanup; + } + } + krb5_free_default_realm(util_context, temp); + } + /* If we have the realm name, we can safely say that + * realm_name is required so that we don't neglect any information. + */ + else + realm_name_required = TRUE; + + retval = profile_get_string(util_context->profile, KDB_REALM_SECTION, + util_context->default_realm, KDB_MODULE_POINTER, + NULL, + &value); + + if (!(value)) { + retval = profile_get_string(util_context->profile, KDB_MODULE_DEF_SECTION, + KDB_MODULE_POINTER, NULL, + NULL, + &value); + if (!(value)) { + if (util_context->default_realm) + conf_section = strdup(util_context->default_realm); + } else { + conf_section = strdup(value); + free(value); + } + } else { + conf_section = strdup(value); + free(value); + } + + if (realm_name_required) { + retval = kadm5_get_config_params(util_context, 1, + &global_params, &global_params); + if (retval) { + com_err(progname, retval, + _("while retrieving configuration parameters")); + exit_status++; + goto cleanup; + } + gp_is_static = 0; + } + + if ((retval = krb5_ldap_lib_init()) != 0) { + com_err(progname, retval, _("while initializing error handling")); + exit_status++; + goto cleanup; + } + + /* Initialize the ldap context */ + ldap_context = calloc(sizeof(krb5_ldap_context), 1); + if (ldap_context == NULL) { + com_err(progname, ENOMEM, _("while initializing ldap handle")); + exit_status++; + goto cleanup; + } + + ldap_context->kcontext = util_context; + + /* If LDAP parameters are specified, replace them with the values from config */ + if (ldapmask & CMD_LDAP_D) { + /* If password is not specified, prompt for it */ + if (passwd == NULL) { + passwd = (char *)malloc(MAX_PASSWD_LEN); + if (passwd == NULL) { + com_err(progname, ENOMEM, + _("while retrieving ldap configuration")); + exit_status++; + goto cleanup; + } + prompt = (char *)malloc(MAX_PASSWD_PROMPT_LEN); + if (prompt == NULL) { + free(passwd); + passwd = NULL; + com_err(progname, ENOMEM, + _("while retrieving ldap configuration")); + exit_status++; + goto cleanup; + } + memset(passwd, 0, MAX_PASSWD_LEN); + passwd_len = MAX_PASSWD_LEN - 1; + snprintf(prompt, MAX_PASSWD_PROMPT_LEN, + _("Password for \"%s\""), bind_dn); + + db_retval = krb5_read_password(util_context, prompt, NULL, passwd, &passwd_len); + + if ((db_retval) || (passwd_len == 0)) { + com_err(progname, ENOMEM, + _("while retrieving ldap configuration")); + free(passwd); + passwd = NULL; + exit_status++; + goto cleanup; + } + } + + ldap_context->bind_pwd = passwd; + passwd = NULL; + } + + /* If ldaphost is specified, release entry filled by configuration & use this */ + if (ldapmask & CMD_LDAP_H) { + + ldap_context->server_info_list = (krb5_ldap_server_info **) calloc (2, sizeof (krb5_ldap_server_info *)) ; + if (ldap_context->server_info_list == NULL) { + com_err(progname, ENOMEM, _("while initializing server list")); + exit_status++; + goto cleanup; + } + + ldap_context->server_info_list[0] = (krb5_ldap_server_info *) calloc (1, sizeof (krb5_ldap_server_info)); + if (ldap_context->server_info_list[0] == NULL) { + com_err(progname, ENOMEM, _("while initializing server list")); + exit_status++; + goto cleanup; + } + + ldap_context->server_info_list[0]->server_status = NOTSET; + + ldap_context->server_info_list[0]->server_name = strdup(ldap_server); + if (ldap_context->server_info_list[0]->server_name == NULL) { + com_err(progname, ENOMEM, _("while initializing server list")); + exit_status++; + goto cleanup; + } + } + if (bind_dn) { + ldap_context->bind_dn = strdup(bind_dn); + if (ldap_context->bind_dn == NULL) { + com_err(progname, ENOMEM, + _("while retrieving ldap configuration")); + exit_status++; + goto cleanup; + } + } else + ldap_context->bind_dn = NULL; + + ldap_context->service_type = SERVICE_DN_TYPE_CLIENT; + + if (realm_name_required) { + if ((global_params.enctype != ENCTYPE_UNKNOWN) && + (!krb5_c_valid_enctype(global_params.enctype))) { + com_err(progname, KRB5_PROG_KEYTYPE_NOSUPP, + _("while setting up enctype %d"), global_params.enctype); + } + } + + cmd = cmd_lookup(cmd_argv[0]); + + /* Setup DAL handle to access the database */ + db_retval = krb5_db_setup_lib_handle(util_context); + if (db_retval) { + com_err(progname, db_retval, _("while setting up lib handle")); + exit_status++; + goto cleanup; + } + util_context->dal_handle->db_context = ldap_context; + ldap_context = NULL; + + db_retval = krb5_ldap_read_server_params(util_context, conf_section, KRB5_KDB_SRV_TYPE_OTHER); + if (db_retval) { + com_err(progname, db_retval, _("while reading ldap configuration")); + exit_status++; + goto cleanup; + } + + if (cmd->opendb) { + db_retval = krb5_ldap_db_init(util_context, (krb5_ldap_context *)util_context->dal_handle->db_context); + if (db_retval) { + com_err(progname, db_retval, _("while initializing database")); + exit_status++; + goto cleanup; + } + db_inited = TRUE; + } + (*cmd->func)(cmd_argc, cmd_argv); + + goto cleanup; + +cleanup: + if (passwd) { + memset(passwd, 0, strlen(passwd)); + free(passwd); + } + + if (ldap_context) { + krb5_ldap_free_server_context_params(ldap_context); + free(ldap_context); + } + + if (util_context) { + if (gp_is_static == 0) + kadm5_free_config_params(util_context, &global_params); + krb5_db_fini(util_context); + krb5_free_context(util_context); + } + + if (cmd_argv) + free(cmd_argv); + if (prompt) + free(prompt); + if (conf_section) + free(conf_section); + + if (usage_print) { + usage(); + } + + return exit_status; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h new file mode 100644 index 00000000..dd626314 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h @@ -0,0 +1,69 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/ldap_util/kdb5_ldap_util.h */ +/* Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "kdb_ldap.h" +#include "kdb5_ldap_realm.h" +#include "kdb5_ldap_services.h" +#include "kdb5_ldap_policy.h" + +#define MAIN_HELP -1 +#define CREATE_REALM 1 +#define MODIFY_REALM 2 +#define VIEW_REALM 3 +#define DESTROY_REALM 4 +#define LIST_REALM 5 + +#define STASH_SRV_PW 17 + +#define CREATE_POLICY 11 +#define MODIFY_POLICY 12 +#define VIEW_POLICY 13 +#define DESTROY_POLICY 14 +#define LIST_POLICY 15 + +extern char *progname; + +extern int exit_status; +extern krb5_context util_context; + +extern void usage(void); +extern void db_usage(int); + +#define ARG_VAL (--argc > 0 ? (koptarg = *(++argv)) : (char *)(db_usage(MAIN_HELP), NULL)) + +/* Following are the bitmaps that indicate which of the options among -D, -w, -h, -p & -t + * were specified on the command line. + */ +#define CMD_LDAP_D 0x1 /* set if -D option is specified */ +#define CMD_LDAP_W 0x2 /* set if -w option is specified */ +#define CMD_LDAP_H 0x4 /* set if -h option is specified */ +#define CMD_LDAP_P 0x8 /* set if -p option is specified */ + +#define MAX_PASSWD_LEN 1024 +#define MAX_PASSWD_PROMPT_LEN 276 /* max_dn_size(=256) + strlen("Password for \" \"")=20 */ diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in new file mode 100644 index 00000000..b40d6399 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/Makefile.in @@ -0,0 +1,70 @@ +mydir=plugins$(S)kdb$(S)ldap$(S)libkdb_ldap +BUILDTOP=$(REL)..$(S)..$(S)..$(S).. +# Lots of ugliness here because of duplicated symbol names. +# Can I just punt the duplicates and import from libkdb5, or +# is keeping them separate important? +DEFINES = \ + -Dkrb5_dbe_lookup_last_pwd_change=kdb_ldap_dbe_lookup_last_pwd_change \ + -Dkrb5_dbe_lookup_tl_data=kdb_ldap_dbe_lookup_tl_data \ + -Dkrb5_dbe_update_last_pwd_change=kdb_ldap_dbe_update_last_pwd_change \ + -Dkrb5_dbe_update_tl_data=kdb_ldap_dbe_update_tl_data + +LOCALINCLUDES = -I$(top_srcdir)/lib/kdb -I$(top_srcdir)/lib/krb5/asn.1 + +LIBBASE=kdb_ldap +LIBMAJOR=1 +LIBMINOR=0 +RELDIR=../plugins/kdb/ldap/libkdb_ldap +# Depends on libk5crypto and libkrb5 +# Also on gssrpc, for xdr stuff. +SHLIB_EXPDEPS = \ + $(GSSRPC_DEPLIBS) \ + $(TOPLIBD)/libk5crypto$(SHLIBEXT) \ + $(SUPPORT_DEPLIB) \ + $(TOPLIBD)/libkrb5$(SHLIBEXT) +SHLIB_EXPLIBS= $(KADMSRV_LIBS) -lkrb5 -lk5crypto $(COM_ERR_LIB) $(SUPPORT_LIB) $(LDAP_LIBS) $(LIBS) + +LIBINITFUNC= kldap_init_fn +LIBFINIFUNC= + +SRCS= $(srcdir)/kdb_ldap.c \ + $(srcdir)/kdb_ldap_conn.c \ + $(srcdir)/ldap_realm.c \ + $(srcdir)/ldap_create.c \ + $(srcdir)/ldap_krbcontainer.c \ + $(srcdir)/ldap_principal.c \ + $(srcdir)/ldap_principal2.c \ + $(srcdir)/ldap_pwd_policy.c \ + $(srcdir)/ldap_misc.c \ + $(srcdir)/ldap_handle.c \ + $(srcdir)/ldap_tkt_policy.c \ + $(srcdir)/princ_xdr.c \ + $(srcdir)/ldap_service_stash.c \ + $(srcdir)/kdb_xdr.c \ + $(srcdir)/ldap_err.c \ + $(srcdir)/lockout.c \ + +STLIBOBJS= kdb_ldap.o \ + kdb_ldap_conn.o \ + ldap_realm.o \ + ldap_create.o \ + ldap_krbcontainer.o \ + ldap_principal.o \ + ldap_principal2.o \ + ldap_pwd_policy.o \ + ldap_misc.o \ + ldap_handle.o \ + ldap_tkt_policy.o \ + princ_xdr.o \ + ldap_service_stash.o \ + kdb_xdr.o \ + ldap_err.o \ + lockout.o + +all-unix: all-liblinks +install-unix: install-libs +clean-unix:: clean-liblinks clean-libobjs clean-libs + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/deps b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/deps new file mode 100644 index 00000000..6a6ab280 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/deps @@ -0,0 +1,277 @@ +# +# Generated makefile dependencies follow. +# +kdb_ldap.so kdb_ldap.po $(OUTPRE)kdb_ldap.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + $(top_srcdir)/lib/kdb/kdb5.h kdb_ldap.c kdb_ldap.h \ + ldap_err.h ldap_krbcontainer.h ldap_misc.h ldap_realm.h +kdb_ldap_conn.so kdb_ldap_conn.po $(OUTPRE)kdb_ldap_conn.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h $(top_srcdir)/lib/kdb/kdb5.h \ + kdb_ldap.h kdb_ldap_conn.c ldap_handle.h ldap_krbcontainer.h \ + ldap_main.h ldap_misc.h ldap_realm.h ldap_service_stash.h +ldap_realm.so ldap_realm.po $(OUTPRE)ldap_realm.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + $(top_srcdir)/lib/kdb/kdb5.h kdb_ldap.h ldap_err.h \ + ldap_handle.h ldap_krbcontainer.h ldap_main.h ldap_misc.h \ + ldap_principal.h ldap_pwd_policy.h ldap_realm.c ldap_realm.h \ + ldap_tkt_policy.h princ_xdr.h +ldap_create.so ldap_create.po $(OUTPRE)ldap_create.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + $(top_srcdir)/lib/kdb/kdb5.h kdb_ldap.h ldap_create.c \ + ldap_err.h ldap_handle.h ldap_krbcontainer.h ldap_main.h \ + ldap_misc.h ldap_principal.h ldap_realm.h ldap_tkt_policy.h \ + princ_xdr.h +ldap_krbcontainer.so ldap_krbcontainer.po $(OUTPRE)ldap_krbcontainer.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h $(top_srcdir)/lib/kdb/kdb5.h \ + kdb_ldap.h ldap_err.h ldap_handle.h ldap_krbcontainer.c \ + ldap_krbcontainer.h ldap_main.h ldap_misc.h ldap_realm.h +ldap_principal.so ldap_principal.po $(OUTPRE)ldap_principal.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + $(top_srcdir)/lib/kdb/kdb5.h kdb_ldap.h ldap_err.h \ + ldap_handle.h ldap_krbcontainer.h ldap_main.h ldap_misc.h \ + ldap_principal.c ldap_principal.h ldap_realm.h ldap_tkt_policy.h \ + princ_xdr.h +ldap_principal2.so ldap_principal2.po $(OUTPRE)ldap_principal2.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + $(top_srcdir)/lib/kdb/kdb5.h kdb_ldap.h ldap_err.h \ + ldap_handle.h ldap_krbcontainer.h ldap_main.h ldap_misc.h \ + ldap_principal.h ldap_principal2.c ldap_pwd_policy.h \ + ldap_realm.h ldap_tkt_policy.h princ_xdr.h +ldap_pwd_policy.so ldap_pwd_policy.po $(OUTPRE)ldap_pwd_policy.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h $(top_srcdir)/lib/kdb/kdb5.h \ + kdb_ldap.h ldap_err.h ldap_handle.h ldap_krbcontainer.h \ + ldap_main.h ldap_misc.h ldap_pwd_policy.c ldap_pwd_policy.h \ + ldap_realm.h +ldap_misc.so ldap_misc.po $(OUTPRE)ldap_misc.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + $(top_srcdir)/lib/kdb/kdb5.h kdb_ldap.h ldap_err.h \ + ldap_handle.h ldap_krbcontainer.h ldap_misc.c ldap_misc.h \ + ldap_principal.h ldap_pwd_policy.h ldap_realm.h ldap_tkt_policy.h \ + princ_xdr.h +ldap_handle.so ldap_handle.po $(OUTPRE)ldap_handle.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h $(top_srcdir)/lib/kdb/kdb5.h \ + kdb_ldap.h ldap_handle.c ldap_handle.h ldap_krbcontainer.h \ + ldap_main.h ldap_misc.h ldap_realm.h +ldap_tkt_policy.so ldap_tkt_policy.po $(OUTPRE)ldap_tkt_policy.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h $(top_srcdir)/lib/kdb/kdb5.h \ + kdb_ldap.h ldap_err.h ldap_handle.h ldap_krbcontainer.h \ + ldap_main.h ldap_misc.h ldap_realm.h ldap_tkt_policy.c \ + ldap_tkt_policy.h +princ_xdr.so princ_xdr.po $(OUTPRE)princ_xdr.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/admin_internal.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/kadm5/server_internal.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + $(top_srcdir)/lib/kdb/kdb5.h kdb_ldap.h ldap_krbcontainer.h \ + ldap_principal.h ldap_realm.h ldap_tkt_policy.h princ_xdr.c \ + princ_xdr.h +ldap_service_stash.so ldap_service_stash.po $(OUTPRE)ldap_service_stash.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-hex.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + $(top_srcdir)/lib/kdb/kdb5.h kdb_ldap.h ldap_handle.h \ + ldap_krbcontainer.h ldap_main.h ldap_misc.h ldap_realm.h \ + ldap_service_stash.c ldap_service_stash.h +kdb_xdr.so kdb_xdr.po $(OUTPRE)kdb_xdr.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + kdb_xdr.c +ldap_err.so ldap_err.po $(OUTPRE)ldap_err.$(OBJEXT): \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + ldap_err.c ldap_err.h +lockout.so lockout.po $(OUTPRE)lockout.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + $(top_srcdir)/lib/kdb/kdb5.h kdb_ldap.h ldap_krbcontainer.h \ + ldap_principal.h ldap_pwd_policy.h ldap_realm.h ldap_tkt_policy.h \ + lockout.c princ_xdr.h diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c new file mode 100644 index 00000000..1f0c8684 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c @@ -0,0 +1,317 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "autoconf.h" +#if HAVE_UNISTD_H +#include +#endif + +#include +#include "kdb_ldap.h" +#include "ldap_misc.h" +#include +#include + +/* + * ldap get age + */ +krb5_error_code +krb5_ldap_get_age(context, db_name, age) + krb5_context context; + char *db_name; + time_t *age; +{ + time (age); + return 0; +} + +/* + * read startup information - kerberos and realm container + */ +krb5_error_code +krb5_ldap_read_startup_information(krb5_context context) +{ + krb5_error_code retval = 0; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + int mask = 0; + + SETUP_CONTEXT(); + if ((retval=krb5_ldap_read_krbcontainer_dn(context, &(ldap_context->container_dn)))) { + k5_prependmsg(context, retval, _("Unable to read Kerberos container")); + goto cleanup; + } + + if ((retval=krb5_ldap_read_realm_params(context, context->default_realm, &(ldap_context->lrparams), &mask))) { + k5_prependmsg(context, retval, _("Unable to read Realm")); + goto cleanup; + } + + if (((mask & LDAP_REALM_MAXTICKETLIFE) == 0) || ((mask & LDAP_REALM_MAXRENEWLIFE) == 0) + || ((mask & LDAP_REALM_KRBTICKETFLAGS) == 0)) { + kadm5_config_params params_in, params_out; + + memset(¶ms_in, 0, sizeof(params_in)); + memset(¶ms_out, 0, sizeof(params_out)); + + retval = kadm5_get_config_params(context, 1, ¶ms_in, ¶ms_out); + if (retval) { + if ((mask & LDAP_REALM_MAXTICKETLIFE) == 0) { + ldap_context->lrparams->max_life = 24 * 60 * 60; /* 1 day */ + } + if ((mask & LDAP_REALM_MAXRENEWLIFE) == 0) { + ldap_context->lrparams->max_renewable_life = 0; + } + if ((mask & LDAP_REALM_KRBTICKETFLAGS) == 0) { + ldap_context->lrparams->tktflags = KRB5_KDB_DEF_FLAGS; + } + retval = 0; + goto cleanup; + } + + if ((mask & LDAP_REALM_MAXTICKETLIFE) == 0) { + if (params_out.mask & KADM5_CONFIG_MAX_LIFE) + ldap_context->lrparams->max_life = params_out.max_life; + } + + if ((mask & LDAP_REALM_MAXRENEWLIFE) == 0) { + if (params_out.mask & KADM5_CONFIG_MAX_RLIFE) + ldap_context->lrparams->max_renewable_life = params_out.max_rlife; + } + + if ((mask & LDAP_REALM_KRBTICKETFLAGS) == 0) { + if (params_out.mask & KADM5_CONFIG_FLAGS) + ldap_context->lrparams->tktflags = params_out.flags; + } + + kadm5_free_config_params(context, ¶ms_out); + } + +cleanup: + return retval; +} + + +/* Interrogate the root DSE (zero length DN) for an attribute value assertion. + * Return true if it is present, false if it is absent or we can't tell. */ +static krb5_boolean +has_rootdse_ava(krb5_context context, const char *server_name, + const char *attribute, const char *value) +{ + krb5_boolean result = FALSE; + char *attrs[2], **values = NULL; + int i, st; + LDAP *ld = NULL; + LDAPMessage *msg, *res = NULL; + struct berval cred; + + attrs[0] = (char *)attribute; + attrs[1] = NULL; + + st = ldap_initialize(&ld, server_name); + if (st != LDAP_SUCCESS) + goto cleanup; + + /* Bind anonymously. */ + cred.bv_val = ""; + cred.bv_len = 0; + st = ldap_sasl_bind_s(ld, "", NULL, &cred, NULL, NULL, NULL); + if (st != LDAP_SUCCESS) + goto cleanup; + + st = ldap_search_ext_s(ld, "", LDAP_SCOPE_BASE, NULL, attrs, 0, NULL, + NULL, NULL, 0, &res); + if (st != LDAP_SUCCESS) + goto cleanup; + + msg = ldap_first_message(ld, res); + if (msg == NULL) + goto cleanup; + + values = ldap_get_values(ld, msg, attribute); + if (values == NULL) + goto cleanup; + + for (i = 0; values[i] != NULL; i++) { + if (strcmp(values[i], value) == 0) { + result = TRUE; + goto cleanup; + } + } + +cleanup: + ldap_value_free(values); + ldap_msgfree(res); + ldap_unbind_ext_s(ld, NULL, NULL); + + return result; +} + +krb5_boolean +has_modify_increment(krb5_context context, const char *server_name) +{ + return has_rootdse_ava(context, server_name, "supportedFeatures", + "1.3.6.1.1.14"); +} + +void * +krb5_ldap_alloc(krb5_context context, void *ptr, size_t size) +{ + return realloc(ptr, size); +} + +void +krb5_ldap_free(krb5_context context, void *ptr) +{ + free(ptr); +} + +krb5_error_code +krb5_ldap_open(krb5_context context, char *conf_section, char **db_args, + int mode) +{ + krb5_error_code status = 0; + krb5_ldap_context *ldap_context=NULL; + + /* Clear the global error string */ + krb5_clear_error_message(context); + + ldap_context = k5alloc(sizeof(krb5_ldap_context), &status); + if (ldap_context == NULL) + goto clean_n_exit; + context->dal_handle->db_context = ldap_context; + ldap_context->kcontext = context; + + status = krb5_ldap_parse_db_params(context, db_args); + if (status) { + k5_prependmsg(context, status, _("Error processing LDAP DB params")); + goto clean_n_exit; + } + + status = krb5_ldap_read_server_params(context, conf_section, mode & 0x0300); + if (status) { + k5_prependmsg(context, status, _("Error reading LDAP server params")); + goto clean_n_exit; + } + if ((status=krb5_ldap_db_init(context, ldap_context)) != 0) { + goto clean_n_exit; + } + + if ((status=krb5_ldap_read_startup_information(context)) != 0) { + goto clean_n_exit; + } + +clean_n_exit: + /* may be clearing up is not required db_fini might do it for us, check out */ + if (status) { + krb5_ldap_close(context); + } + return status; +} + +#include "ldap_err.h" +int +set_ldap_error(krb5_context ctx, int st, int op) +{ + int translated_st = translate_ldap_error(st, op); + k5_setmsg(ctx, translated_st, "%s", ldap_err2string(st)); + return translated_st; +} + +extern krb5int_access accessor; +MAKE_INIT_FUNCTION(kldap_init_fn); + +int +kldap_init_fn(void) +{ + /* Global (per-module) initialization. */ + return krb5int_accessor (&accessor, KRB5INT_ACCESS_VERSION); +} + +int +kldap_ensure_initialized(void) +{ + return CALL_INIT_FUNCTION (kldap_init_fn); +} + +krb5_error_code +krb5_ldap_check_policy_as(krb5_context kcontext, krb5_kdc_req *request, + krb5_db_entry *client, krb5_db_entry *server, + krb5_timestamp kdc_time, const char **status, + krb5_pa_data ***e_data) +{ + krb5_error_code retval; + + retval = krb5_ldap_lockout_check_policy(kcontext, client, kdc_time); + if (retval == KRB5KDC_ERR_CLIENT_REVOKED) + *status = "LOCKED_OUT"; + return retval; +} + +void +krb5_ldap_audit_as_req(krb5_context kcontext, krb5_kdc_req *request, + const krb5_address *local_addr, + const krb5_address *remote_addr, krb5_db_entry *client, + krb5_db_entry *server, krb5_timestamp authtime, + krb5_error_code error_code) +{ + (void) krb5_ldap_lockout_audit(kcontext, client, authtime, error_code); +} + +krb5_error_code +krb5_ldap_check_allowed_to_delegate(krb5_context context, + krb5_const_principal client, + const krb5_db_entry *server, + krb5_const_principal proxy) +{ + krb5_error_code code; + krb5_tl_data *tlp; + + code = KRB5KDC_ERR_BADOPTION; + + for (tlp = server->tl_data; tlp != NULL; tlp = tlp->tl_data_next) { + krb5_principal acl; + + if (tlp->tl_data_type != KRB5_TL_CONSTRAINED_DELEGATION_ACL) + continue; + + if (krb5_parse_name(context, (char *)tlp->tl_data_contents, &acl) != 0) + continue; + + if (proxy == NULL || krb5_principal_compare(context, proxy, acl)) { + code = 0; + krb5_free_principal(context, acl); + break; + } + krb5_free_principal(context, acl); + } + + return code; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h new file mode 100644 index 00000000..8b8420fa --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h @@ -0,0 +1,316 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +/* */ +#ifndef _KDB_LDAP_H +#define _KDB_LDAP_H 1 + +#include "k5-int.h" +#include +#include +#include "ldap_krbcontainer.h" +#include "ldap_realm.h" + +/* We want the interfaces marked "deprecated" in OpenLDAP. */ +#define LDAP_DEPRECATED 1 +#include + +/* Check for acceptable versions. + + OpenLDAP version 2.2.6 is known to have some kind of problem that + is tickled by the use of multiple handles in this code. Version + 2.2.19 in Mac OS 10.4.7 seems to be buggy as well. Version 2.2.24 + doesn't have this problem. Other in-between versions have not been + tested. */ +#ifndef BUILD_WITH_BROKEN_LDAP +# if defined(LDAP_API_FEATURE_X_OPENLDAP) +# if LDAP_VENDOR_VERSION < 20224 +# error This code triggers bugs in old OpenLDAP implementations. Please update to 2.2.24 or later. +# endif +# endif +#endif /* BUILD_WITH_BROKEN_LDAP */ + +extern struct timeval timelimit; + +#define DEFAULT_CONNS_PER_SERVER 5 +#define REALM_READ_REFRESH_INTERVAL (5 * 60) + +#if !defined(LDAP_OPT_RESULT_CODE) && defined(LDAP_OPT_ERROR_NUMBER) +#define LDAP_OPT_RESULT_CODE LDAP_OPT_ERROR_NUMBER +#endif + +#define MAXINTLEN 10 + +#define IGNORE_STATUS 0 +#define CHECK_STATUS 1 + +#define SETUP_CONTEXT() if (context == NULL || context->dal_handle == NULL \ + || context->dal_handle->db_context == NULL) { \ + return EINVAL; \ + } \ + dal_handle = context->dal_handle; \ + ldap_context = (krb5_ldap_context *) dal_handle->db_context; \ + if (ldap_context == NULL || ldap_context->server_info_list == NULL) \ + return KRB5_KDB_DBNOTINITED; + +#define GET_HANDLE() ld = NULL; \ + st = krb5_ldap_request_handle_from_pool(ldap_context, &ldap_server_handle); \ + if (st != 0) { \ + k5_wrapmsg(context, st, KRB5_KDB_ACCESS_ERROR, \ + "LDAP handle unavailable"); \ + st = KRB5_KDB_ACCESS_ERROR; \ + goto cleanup; \ + } \ + ld = ldap_server_handle->ldap_handle; + +extern int set_ldap_error (krb5_context ctx, int st, int op); + +#define LDAP_SEARCH(base, scope, filter, attrs) LDAP_SEARCH_1(base, scope, filter, attrs, CHECK_STATUS) + +#define LDAP_SEARCH_1(base, scope, filter, attrs, status_check) \ + tempst = 0; \ + st = ldap_search_ext_s(ld, base, scope, filter, attrs, 0, NULL, \ + NULL, &timelimit, LDAP_NO_LIMIT, &result); \ + if (translate_ldap_error(st, OP_SEARCH) == KRB5_KDB_ACCESS_ERROR) { \ + tempst = krb5_ldap_rebind(ldap_context, &ldap_server_handle); \ + if (ldap_server_handle) \ + ld = ldap_server_handle->ldap_handle; \ + if (tempst == 0) \ + st = ldap_search_ext_s(ld, base, scope, filter, attrs, 0, \ + NULL, NULL, &timelimit, \ + LDAP_NO_LIMIT, &result); \ + } \ + \ + if (status_check != IGNORE_STATUS) { \ + if (tempst != 0) { \ + k5_wrapmsg(context, st, KRB5_KDB_ACCESS_ERROR, \ + "LDAP handle unavailable"); \ + st = KRB5_KDB_ACCESS_ERROR; \ + goto cleanup; \ + } \ + if (st != LDAP_SUCCESS) { \ + st = set_ldap_error(context, st, OP_SEARCH); \ + goto cleanup; \ + } \ + } + + +#define CHECK_CLASS_VALIDITY(st, mask, str) \ + if (st != 0 || mask == 0) { \ + if (st == 0 && mask == 0) { \ + st = set_ldap_error(context, LDAP_OBJECT_CLASS_VIOLATION, OP_SEARCH); \ + } \ + k5_prependmsg(context, st, str); \ + goto cleanup; \ + } + +#define CHECK_NULL(ptr) if (ptr == NULL) { \ + st = ENOMEM; \ + goto cleanup; \ + } + +#define STORE16_INT(ptr, val) store_16_be(val, ptr) +#define STORE32_INT(ptr, val) store_32_be(val, ptr) +#define UNSTORE16_INT(ptr, val) (val = load_16_be(ptr)) +#define UNSTORE32_INT(ptr, val) (val = load_32_be(ptr)) + +#define KDB_TL_USER_INFO 0xff + +#define KDB_TL_PRINCTYPE 0x01 +#define KDB_TL_PRINCCOUNT 0x02 +#define KDB_TL_USERDN 0x03 +#define KDB_TL_KEYINFO 0x04 +#define KDB_TL_MASK 0x05 +/* 0x06 was KDB_TL_CONTAINERDN but is no longer used */ +#define KDB_TL_LINKDN 0x07 + + +#define CHECK_LDAP_HANDLE(lcontext) if (!(ldap_context \ + && ldap_context->server_info_list)) { \ + return KRB5_KDB_DBNOTINITED; \ + } + +#define HNDL_LOCK(lcontext) k5_mutex_lock(&lcontext->hndl_lock) +#define HNDL_UNLOCK(lcontext) k5_mutex_unlock(&lcontext->hndl_lock) + +/* ldap server info structure */ + +typedef enum _server_type {PRIMARY, SECONDARY} krb5_ldap_server_type; + +typedef enum _server_status {OFF, ON, NOTSET} krb5_ldap_server_status; + +typedef struct _krb5_ldap_server_info krb5_ldap_server_info; + +typedef struct _krb5_ldap_server_handle { + int msgid; + LDAP *ldap_handle; + krb5_ldap_server_info *server_info; + struct _krb5_ldap_server_handle *next; +} krb5_ldap_server_handle; + +struct _krb5_ldap_server_info { + krb5_ldap_server_type server_type; + krb5_ldap_server_status server_status; + krb5_ui_4 num_conns; + krb5_ldap_server_handle *ldap_server_handles; + time_t downtime; + char *server_name; + int modify_increment; + struct _krb5_ldap_server_info *next; +}; + + +/* ldap server structure */ + +typedef enum {SERVICE_DN_TYPE_SERVER, SERVICE_DN_TYPE_CLIENT} krb5_ldap_servicetype; + +typedef struct _krb5_ldap_context { + krb5_ldap_servicetype service_type; + krb5_ldap_server_info **server_info_list; + krb5_ui_4 max_server_conns; + char *conf_section; + char *bind_dn; + char *bind_pwd; + char *service_password_file; + char *sasl_mech; + char *sasl_authcid; + char *sasl_authzid; + char *sasl_realm; + char *root_certificate_file; + krb5_ui_4 cert_count; /* certificate count */ + k5_mutex_t hndl_lock; + char *container_dn; + krb5_ldap_realm_params *lrparams; + krb5_boolean disable_last_success; + krb5_boolean disable_lockout; + int ldap_debug; + krb5_context kcontext; /* to set the error code and message */ +} krb5_ldap_context; + + +typedef struct { + int nkey; + struct berval **keys; +}KEY; + +#define k5ldap_inited(c) (c && c->db_context \ + && ((kdb5_dal_handle*)c->db_context)->db_context \ + && ((krb5_ldap_context *) ((kdb5_dal_handle*)c->db_context)->db_context)) + + +/* misc functions */ + +krb5_error_code +krb5_ldap_db_init(krb5_context, krb5_ldap_context *); + +krb5_error_code +krb5_ldap_db_single_init(krb5_ldap_context *); + +krb5_error_code +krb5_ldap_rebind(krb5_ldap_context *, krb5_ldap_server_handle **); + +krb5_error_code +krb5_ldap_get_age(krb5_context, char *, time_t *); + +krb5_error_code +krb5_ldap_lib_init(void); + +krb5_error_code +krb5_ldap_lib_cleanup(void); + +void * +krb5_ldap_alloc( krb5_context kcontext, void *ptr, size_t size ); + +void +krb5_ldap_free( krb5_context kcontext, void *ptr ); + +krb5_error_code +krb5_ldap_create(krb5_context , char *, char **); + +krb5_error_code +krb5_ldap_open( krb5_context , char *, + char **db_args, + int mode ); +krb5_error_code +krb5_ldap_close( krb5_context ); + +krb5_error_code +krb5_ldap_free_ldap_context(krb5_ldap_context *); + +krb5_error_code +krb5_ldap_read_startup_information(krb5_context ); + +krb5_boolean +has_modify_increment(krb5_context, const char *); + +void +krb5_ldap_free_server_context_params(krb5_ldap_context *ldap_context); + +krb5_error_code +krb5_ldap_check_policy_as(krb5_context kcontext, krb5_kdc_req *request, + krb5_db_entry *client, krb5_db_entry *server, + krb5_timestamp kdc_time, const char **status, + krb5_pa_data ***e_data); + +void +krb5_ldap_audit_as_req(krb5_context kcontext, krb5_kdc_req *request, + const krb5_address *local_addr, + const krb5_address *remote_addr, krb5_db_entry *client, + krb5_db_entry *server, krb5_timestamp authtime, + krb5_error_code error_code); + +krb5_error_code +krb5_ldap_check_allowed_to_delegate(krb5_context context, + krb5_const_principal client, + const krb5_db_entry *server, + krb5_const_principal proxy); + +/* DAL functions */ + + +krb5_error_code +krb5_ldap_lock( krb5_context, int ); + +krb5_error_code +krb5_ldap_unlock( krb5_context ); + +/* lockout.c */ +krb5_error_code +krb5_ldap_lockout_check_policy(krb5_context context, + krb5_db_entry *entry, + krb5_timestamp stamp); + +krb5_error_code +krb5_ldap_lockout_audit(krb5_context context, + krb5_db_entry *entry, + krb5_timestamp stamp, + krb5_error_code status); + +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c new file mode 100644 index 00000000..cee4b7b8 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c @@ -0,0 +1,364 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "autoconf.h" +#if HAVE_UNISTD_H +#include +#endif + +#include "ldap_main.h" +#include "ldap_service_stash.h" +#include +#ifdef HAVE_SASL_SASL_H +#include +#endif + +/* Ensure that we have the parameters we need to authenticate to the LDAP + * server. Read the password if necessary. */ +static krb5_error_code +validate_context(krb5_context context, krb5_ldap_context *ctx) +{ + krb5_error_code ret; + + if (ctx->sasl_mech != NULL) { + /* Read the password for use as the SASL secret if we can, but do not + * require one as not all mechanisms need it. */ + if (ctx->bind_pwd == NULL && ctx->sasl_authcid != NULL && + ctx->service_password_file != NULL) { + (void)krb5_ldap_readpassword(context, ctx->service_password_file, + ctx->sasl_authcid, &ctx->bind_pwd); + } + return 0; + } + + /* For a simple bind, a DN and password are required. */ + + if (ctx->bind_dn == NULL) { + k5_setmsg(context, EINVAL, _("LDAP bind dn value missing")); + return EINVAL; + } + + if (ctx->bind_pwd == NULL && ctx->service_password_file == NULL) { + k5_setmsg(context, EINVAL, _("LDAP bind password value missing")); + return EINVAL; + } + + if (ctx->bind_pwd == NULL && ctx->service_password_file != NULL) { + ret = krb5_ldap_readpassword(context, ctx->service_password_file, + ctx->bind_dn, &ctx->bind_pwd); + if (ret) { + k5_prependmsg(context, ret, + _("Error reading password from stash")); + return ret; + } + } + + /* An empty password is not allowed. */ + if (*ctx->bind_pwd == '\0') { + k5_setmsg(context, EINVAL, _("Service password length is zero")); + return EINVAL; + } + + return 0; +} + +/* + * Internal Functions called by init functions. + */ + +#ifdef HAVE_SASL_SASL_H + +static int +interact(LDAP *ld, unsigned flags, void *defaults, void *sin) +{ + sasl_interact_t *in = NULL; + krb5_ldap_context *ctx = defaults; + + for (in = sin; in != NULL && in->id != SASL_CB_LIST_END; in++) { + if (in->id == SASL_CB_AUTHNAME) + in->result = ctx->sasl_authcid; + else if (in->id == SASL_CB_USER) + in->result = ctx->sasl_authzid; + else if (in->id == SASL_CB_GETREALM) + in->result = ctx->sasl_realm; + else if (in->id == SASL_CB_PASS) + in->result = ctx->bind_pwd; + else + return LDAP_OTHER; + in->len = (in->result != NULL) ? strlen(in->result) : 0; + } + + return LDAP_SUCCESS; +} + +#else /* HAVE_SASL_SASL_H */ + +/* We can't define an interaction function, so only non-interactive mechs like + * EXTERNAL can work. */ +static int +interact(LDAP *ld, unsigned flags, void *defaults, void *sin) +{ + return LDAP_OTHER; +} + +#endif + +static krb5_error_code +authenticate(krb5_ldap_context *ctx, krb5_ldap_server_handle *server) +{ + int st; + struct berval bv; + + if (ctx->sasl_mech != NULL) { + st = ldap_sasl_interactive_bind_s(server->ldap_handle, NULL, + ctx->sasl_mech, NULL, NULL, + LDAP_SASL_QUIET, interact, ctx); + if (st != LDAP_SUCCESS) { + k5_setmsg(ctx->kcontext, KRB5_KDB_ACCESS_ERROR, + _("Cannot bind to LDAP server '%s' with SASL mechanism " + "'%s': %s"), server->server_info->server_name, + ctx->sasl_mech, ldap_err2string(st)); + return KRB5_KDB_ACCESS_ERROR; + } + } else { + /* Do a simple bind with DN and password. */ + bv.bv_val = ctx->bind_pwd; + bv.bv_len = strlen(ctx->bind_pwd); + st = ldap_sasl_bind_s(server->ldap_handle, ctx->bind_dn, NULL, &bv, + NULL, NULL, NULL); + if (st != LDAP_SUCCESS) { + k5_setmsg(ctx->kcontext, KRB5_KDB_ACCESS_ERROR, + _("Cannot bind to LDAP server '%s' as '%s': %s"), + server->server_info->server_name, ctx->bind_dn, + ldap_err2string(st)); + return KRB5_KDB_ACCESS_ERROR; + } + } + return 0; +} + +static krb5_error_code +initialize_server(krb5_ldap_context *ldap_context, krb5_ldap_server_info *info) +{ + krb5_ldap_server_handle *server; + krb5_error_code ret; + int st; + + server = calloc(1, sizeof(krb5_ldap_server_handle)); + if (server == NULL) + return ENOMEM; + server->server_info = info; + + st = ldap_initialize(&server->ldap_handle, info->server_name); + if (st) { + free(server); + k5_setmsg(ldap_context->kcontext, KRB5_KDB_ACCESS_ERROR, + _("Cannot create LDAP handle for '%s': %s"), + info->server_name, ldap_err2string(st)); + return KRB5_KDB_ACCESS_ERROR; + } + + ret = authenticate(ldap_context, server); + if (ret) { + info->server_status = OFF; + time(&info->downtime); + free(server); + return ret; + } + + server->next = info->ldap_server_handles; + info->ldap_server_handles = server; + info->num_conns++; + info->server_status = ON; + return 0; +} + +/* + * initialization for data base routines. + */ + +krb5_error_code +krb5_ldap_db_init(krb5_context context, krb5_ldap_context *ctx) +{ + krb5_error_code ret; + int i, version = LDAP_VERSION3; + unsigned int conns; + krb5_ldap_server_info *info; + struct timeval local_timelimit = { 10, 0 }; + + ret = validate_context(context, ctx); + if (ret) + return ret; + +#ifdef LDAP_OPT_DEBUG_LEVEL + ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &ctx->ldap_debug); +#endif + ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &version); +#ifdef LDAP_OPT_NETWORK_TIMEOUT + ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &local_timelimit); +#elif defined LDAP_X_OPT_CONNECT_TIMEOUT + ldap_set_option(NULL, LDAP_X_OPT_CONNECT_TIMEOUT, &local_timelimit); +#endif + + HNDL_LOCK(ctx); + for (i = 0; ctx->server_info_list[i] != NULL; i++) { + info = ctx->server_info_list[i]; + if (info->server_status == NOTSET) { + krb5_clear_error_message(context); + +#ifdef LDAP_MOD_INCREMENT + info->modify_increment = has_modify_increment(context, + info->server_name); +#else + info->modify_increment = 0; +#endif + + for (conns = 0; conns < ctx->max_server_conns; conns++) { + ret = initialize_server(ctx, info); + if (ret) + break; + } + + /* If we opened a connection, don't try any more servers. */ + if (info->server_status == ON) + break; + } + } + HNDL_UNLOCK(ctx); + + return ret; +} + + +/* + * get a single handle. Do not lock the mutex + */ + +krb5_error_code +krb5_ldap_db_single_init(krb5_ldap_context *ldap_context) +{ + krb5_error_code st=0; + int cnt=0; + krb5_ldap_server_info *server_info=NULL; + + while (ldap_context->server_info_list[cnt] != NULL) { + server_info = ldap_context->server_info_list[cnt]; + if ((server_info->server_status == NOTSET || server_info->server_status == ON)) { + if (server_info->num_conns < ldap_context->max_server_conns-1) { + st = initialize_server(ldap_context, server_info); + if (st == LDAP_SUCCESS) + goto cleanup; + } + } + ++cnt; + } + + /* If we are here, try to connect to all the servers */ + + cnt = 0; + while (ldap_context->server_info_list[cnt] != NULL) { + server_info = ldap_context->server_info_list[cnt]; + st = initialize_server(ldap_context, server_info); + if (st == LDAP_SUCCESS) + goto cleanup; + ++cnt; + } +cleanup: + return (st); +} + +krb5_error_code +krb5_ldap_rebind(krb5_ldap_context *ldap_context, + krb5_ldap_server_handle **ldap_server_handle) +{ + krb5_ldap_server_handle *handle = *ldap_server_handle; + + ldap_unbind_ext_s(handle->ldap_handle, NULL, NULL); + if (ldap_initialize(&handle->ldap_handle, + handle->server_info->server_name) != LDAP_SUCCESS || + authenticate(ldap_context, handle) != 0) { + return krb5_ldap_request_next_handle_from_pool(ldap_context, + ldap_server_handle); + } + return LDAP_SUCCESS; +} + +/* + * DAL API functions + */ +krb5_error_code +krb5_ldap_lib_init() +{ + return 0; +} + +krb5_error_code +krb5_ldap_lib_cleanup() +{ + /* right now, no cleanup required */ + return 0; +} + +krb5_error_code +krb5_ldap_free_ldap_context(krb5_ldap_context *ldap_context) +{ + if (ldap_context == NULL) + return 0; + + free(ldap_context->container_dn); + ldap_context->container_dn = NULL; + + krb5_ldap_free_realm_params(ldap_context->lrparams); + ldap_context->lrparams = NULL; + + krb5_ldap_free_server_params(ldap_context); + + return 0; +} + +krb5_error_code +krb5_ldap_close(krb5_context context) +{ + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + + if (context == NULL || + context->dal_handle == NULL || + context->dal_handle->db_context == NULL) + return 0; + + dal_handle = context->dal_handle; + ldap_context = (krb5_ldap_context *) dal_handle->db_context; + dal_handle->db_context = NULL; + + krb5_ldap_free_ldap_context(ldap_context); + + return 0; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c new file mode 100644 index 00000000..ae51905a --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c @@ -0,0 +1,141 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/kdb_xdr.c */ +/* + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include +#include +#include + +#define safe_realloc(p,n) ((p)?(realloc(p,n)):(malloc(n))) + +krb5_error_code +krb5_dbe_update_tl_data(krb5_context context, krb5_db_entry *entry, + krb5_tl_data *new_tl_data) +{ + krb5_tl_data * tl_data; + krb5_octet * tmp; + + /* copy the new data first, so we can fail cleanly if malloc() + fails */ + + if ((tmp = (krb5_octet *) malloc(new_tl_data->tl_data_length)) == NULL) + return(ENOMEM); + + /* Find an existing entry of the specified type and point at + it, or NULL if not found */ + + for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) + if (tl_data->tl_data_type == new_tl_data->tl_data_type) + break; + + /* if necessary, chain a new record in the beginning and point at it */ + + if (!tl_data) { + if ((tl_data = (krb5_tl_data *) calloc(1, sizeof(krb5_tl_data))) + == NULL) { + free(tmp); + return(ENOMEM); + } + tl_data->tl_data_next = entry->tl_data; + entry->tl_data = tl_data; + entry->n_tl_data++; + } + + /* fill in the record */ + + if (tl_data->tl_data_contents) + free(tl_data->tl_data_contents); + + tl_data->tl_data_type = new_tl_data->tl_data_type; + tl_data->tl_data_length = new_tl_data->tl_data_length; + tl_data->tl_data_contents = tmp; + memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length); + + return(0); +} + +krb5_error_code +krb5_dbe_lookup_tl_data(krb5_context context, krb5_db_entry *entry, + krb5_tl_data *ret_tl_data) +{ + krb5_tl_data *tl_data; + + for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) { + if (tl_data->tl_data_type == ret_tl_data->tl_data_type) { + *ret_tl_data = *tl_data; + return(0); + } + } + + /* if the requested record isn't found, return zero bytes. + if it ever means something to have a zero-length tl_data, + this code and its callers will have to be changed */ + + ret_tl_data->tl_data_length = 0; + ret_tl_data->tl_data_contents = NULL; + return(0); +} + +krb5_error_code +krb5_dbe_update_last_pwd_change(krb5_context context, krb5_db_entry *entry, + krb5_timestamp stamp) +{ + krb5_tl_data tl_data; + krb5_octet buf[4]; /* this is the encoded size of an int32 */ + + tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE; + tl_data.tl_data_length = sizeof(buf); + krb5_kdb_encode_int32((krb5_int32) stamp, buf); + tl_data.tl_data_contents = buf; + + return(krb5_dbe_update_tl_data(context, entry, &tl_data)); +} + +krb5_error_code +krb5_dbe_lookup_last_pwd_change(krb5_context context, krb5_db_entry *entry, + krb5_timestamp *stamp) +{ + krb5_tl_data tl_data; + krb5_error_code code; + krb5_int32 tmp; + + tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE; + + if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))) + return(code); + + if (tl_data.tl_data_length != 4) { + *stamp = 0; + return(0); + } + + krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp); + + *stamp = (krb5_timestamp) tmp; + + return(0); +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif new file mode 100644 index 00000000..4224f085 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kerberos.ldif @@ -0,0 +1,905 @@ +# Novell Kerberos Schema Definitions +# Novell Inc. +# 1800 South Novell Place +# Provo, UT 84606 +# +# VeRsIoN=1.0 +# CoPyRiGhT=(c) Copyright 2006, Novell, Inc. All rights reserved +# +# OIDs: +# joint-iso-ccitt(2) +# country(16) +# us(840) +# organization(1) +# Novell(113719) +# applications(1) +# kerberos(301) +# Kerberos Attribute Type(4) attr# version# +# specific attribute definitions +# Kerberos Attribute Syntax(5) +# specific syntax definitions +# Kerberos Object Class(6) class# version# +# specific class definitions +# +# iso(1) +# member-body(2) +# United States(840) +# mit (113554) +# infosys(1) +# ldap(4) +# attributeTypes(1) +# Kerberos(6) + +######################################################################## + + +######################################################################## +# Attribute Type Definitions # +######################################################################## + +##### This is the principal name in the RFC 1964 specified format + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.1.1 + NAME 'krbPrincipalName' + EQUALITY caseExactIA5Match + SUBSTR caseExactSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + +##### If there are multiple krbPrincipalName values for an entry, this +##### is the canonical principal name in the RFC 1964 specified +##### format. (If this attribute does not exist, then all +##### krbPrincipalName values are treated as canonical.) + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 1.2.840.113554.1.4.1.6.1 + NAME 'krbCanonicalName' + EQUALITY caseExactIA5Match + SUBSTR caseExactSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +##### This specifies the type of the principal, the types could be any of +##### the types mentioned in section 6.2 of RFC 4120 + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.3.1 + NAME 'krbPrincipalType' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### This flag is used to find whether directory User Password has to be used +##### as kerberos password. +##### TRUE, if User Password is to be used as the kerberos password. +##### FALSE, if User Password and the kerberos password are different. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.5.1 + NAME 'krbUPEnabled' + DESC 'Boolean' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE ) + + +##### The time at which the principal expires + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.6.1 + NAME 'krbPrincipalExpiration' + EQUALITY generalizedTimeMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE ) + + +##### The krbTicketFlags attribute holds information about the kerberos flags for a principal +##### The values (0x00000001 - 0x00800000) are reserved for standards and +##### values (0x01000000 - 0x80000000) can be used for proprietary extensions. +##### The flags and values as per RFC 4120 and MIT implementation are, +##### DISALLOW_POSTDATED 0x00000001 +##### DISALLOW_FORWARDABLE 0x00000002 +##### DISALLOW_TGT_BASED 0x00000004 +##### DISALLOW_RENEWABLE 0x00000008 +##### DISALLOW_PROXIABLE 0x00000010 +##### DISALLOW_DUP_SKEY 0x00000020 +##### DISALLOW_ALL_TIX 0x00000040 +##### REQUIRES_PRE_AUTH 0x00000080 +##### REQUIRES_HW_AUTH 0x00000100 +##### REQUIRES_PWCHANGE 0x00000200 +##### DISALLOW_SVR 0x00001000 +##### PWCHANGE_SERVICE 0x00002000 + + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.8.1 + NAME 'krbTicketFlags' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### The maximum ticket lifetime for a principal in seconds + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.9.1 + NAME 'krbMaxTicketLife' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### Maximum renewable lifetime for a principal's ticket in seconds + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.10.1 + NAME 'krbMaxRenewableAge' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### Forward reference to the Realm object. +##### (FDN of the krbRealmContainer object). +##### Example: cn=ACME.COM, cn=Kerberos, cn=Security + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.14.1 + NAME 'krbRealmReferences' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + + +##### List of LDAP servers that kerberos servers can contact. +##### The attribute holds data in the ldap uri format, +##### Example: ldaps://acme.com:636 +##### +##### The values of this attribute need to be updated, when +##### the LDAP servers listed here are renamed, moved or deleted. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.15.1 + NAME 'krbLdapServers' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + +##### A set of forward references to the KDC Service objects. +##### (FDNs of the krbKdcService objects). +##### Example: cn=kdc - server 1, ou=uvw, o=xyz + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.17.1 + NAME 'krbKdcServers' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + + +##### A set of forward references to the Password Service objects. +##### (FDNs of the krbPwdService objects). +##### Example: cn=kpasswdd - server 1, ou=uvw, o=xyz + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.18.1 + NAME 'krbPwdServers' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + + +##### This attribute holds the Host Name or the ip address, +##### transport protocol and ports of the kerberos service host +##### The format is host_name-or-ip_address#protocol#port +##### Protocol can be 0 or 1. 0 is for UDP. 1 is for TCP. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.24.1 + NAME 'krbHostServer' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + +##### This attribute holds the scope for searching the principals +##### under krbSubTree attribute of krbRealmContainer +##### The value can either be 1 (ONE) or 2 (SUB_TREE). + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.25.1 + NAME 'krbSearchScope' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### FDNs pointing to Kerberos principals + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.26.1 + NAME 'krbPrincipalReferences' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + + +##### This attribute specifies which attribute of the user objects +##### be used as the principal name component for Kerberos. +##### The allowed values are cn, sn, uid, givenname, fullname. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.28.1 + NAME 'krbPrincNamingAttr' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE ) + + +##### A set of forward references to the Administration Service objects. +##### (FDNs of the krbAdmService objects). +##### Example: cn=kadmindd - server 1, ou=uvw, o=xyz + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.29.1 + NAME 'krbAdmServers' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + + +##### Maximum lifetime of a principal's password + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.30.1 + NAME 'krbMaxPwdLife' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### Minimum lifetime of a principal's password + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.31.1 + NAME 'krbMinPwdLife' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### Minimum number of character clases allowed in a password + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.32.1 + NAME 'krbPwdMinDiffChars' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### Minimum length of the password + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.33.1 + NAME 'krbPwdMinLength' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### Number of previous versions of passwords that are stored + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.34.1 + NAME 'krbPwdHistoryLength' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### Number of consecutive pre-authentication failures before lockout + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 1.3.6.1.4.1.5322.21.2.1 + NAME 'krbPwdMaxFailure' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### Period after which bad preauthentication count will be reset + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 1.3.6.1.4.1.5322.21.2.2 + NAME 'krbPwdFailureCountInterval' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### Period in which lockout is enforced + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 1.3.6.1.4.1.5322.21.2.3 + NAME 'krbPwdLockoutDuration' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### Policy attribute flags + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 1.2.840.113554.1.4.1.6.2 + NAME 'krbPwdAttributes' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### Policy maximum ticket lifetime + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 1.2.840.113554.1.4.1.6.3 + NAME 'krbPwdMaxLife' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### Policy maximum ticket renewable lifetime + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 1.2.840.113554.1.4.1.6.4 + NAME 'krbPwdMaxRenewableLife' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + +##### Allowed enctype:salttype combinations for key changes + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 1.2.840.113554.1.4.1.6.5 + NAME 'krbPwdAllowedKeysalts' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + + +##### FDN pointing to a Kerberos Password Policy object + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.36.1 + NAME 'krbPwdPolicyReference' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE ) + + +##### The time at which the principal's password expires + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.37.1 + NAME 'krbPasswordExpiration' + EQUALITY generalizedTimeMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE ) + + +##### This attribute holds the principal's key (krbPrincipalKey) that is encrypted with +##### the master key (krbMKey). +##### The attribute is ASN.1 encoded. +##### +##### The format of the value for this attribute is explained below, +##### KrbKeySet ::= SEQUENCE { +##### attribute-major-vno [0] UInt16, +##### attribute-minor-vno [1] UInt16, +##### kvno [2] UInt32, +##### mkvno [3] UInt32 OPTIONAL, +##### keys [4] SEQUENCE OF KrbKey, +##### ... +##### } +##### +##### KrbKey ::= SEQUENCE { +##### salt [0] KrbSalt OPTIONAL, +##### key [1] EncryptionKey, +##### s2kparams [2] OCTET STRING OPTIONAL, +##### ... +##### } +##### +##### KrbSalt ::= SEQUENCE { +##### type [0] Int32, +##### salt [1] OCTET STRING OPTIONAL +##### } +##### +##### EncryptionKey ::= SEQUENCE { +##### keytype [0] Int32, +##### keyvalue [1] OCTET STRING +##### } + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.39.1 + NAME 'krbPrincipalKey' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) + + +##### FDN pointing to a Kerberos Ticket Policy object. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.40.1 + NAME 'krbTicketPolicyReference' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE ) + + +##### Forward reference to an entry that starts sub-trees +##### where principals and other kerberos objects in the realm are configured. +##### Example: ou=acme, ou=pq, o=xyz + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.41.1 + NAME 'krbSubTrees' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + + +##### Holds the default encryption/salt type combinations of principals for +##### the Realm. Stores in the form of key:salt strings. +##### Example: aes256-cts-hmac-sha384-192:normal + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.42.1 + NAME 'krbDefaultEncSaltTypes' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + +##### Holds the Supported encryption/salt type combinations of principals for +##### the Realm. Stores in the form of key:salt strings. +##### The supported encryption types are mentioned in RFC 3961 +##### The supported salt types are, +##### NORMAL +##### V4 +##### NOREALM +##### ONLYREALM +##### SPECIAL +##### AFS3 +##### Example: aes256-cts-hmac-sha384-192:normal +##### +##### This attribute obsoletes the krbSupportedEncTypes and krbSupportedSaltTypes +##### attributes. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.43.1 + NAME 'krbSupportedEncSaltTypes' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) + + +##### This attribute holds the principal's old keys (krbPwdHistory) that is encrypted with +##### the kadmin/history key. +##### The attribute is ASN.1 encoded. +##### +##### The format of the value for this attribute is explained below, +##### KrbKeySet ::= SEQUENCE { +##### attribute-major-vno [0] UInt16, +##### attribute-minor-vno [1] UInt16, +##### kvno [2] UInt32, +##### mkvno [3] UInt32 OPTIONAL -- actually kadmin/history key, +##### keys [4] SEQUENCE OF KrbKey, +##### ... +##### } +##### +##### KrbKey ::= SEQUENCE { +##### salt [0] KrbSalt OPTIONAL, +##### key [1] EncryptionKey, +##### s2kparams [2] OCTET STRING OPTIONAL, +##### ... +##### } +##### +##### KrbSalt ::= SEQUENCE { +##### type [0] Int32, +##### salt [1] OCTET STRING OPTIONAL +##### } +##### +##### EncryptionKey ::= SEQUENCE { +##### keytype [0] Int32, +##### keyvalue [1] OCTET STRING +##### } + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.44.1 + NAME 'krbPwdHistory' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) + + +##### The time at which the principal's password last password change happened. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.45.1 + NAME 'krbLastPwdChange' + EQUALITY generalizedTimeMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE ) + +##### The time at which the principal was last administratively unlocked. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 1.3.6.1.4.1.5322.21.2.5 + NAME 'krbLastAdminUnlock' + EQUALITY generalizedTimeMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE ) + +##### This attribute holds the kerberos master key. +##### This can be used to encrypt principal keys. +##### This attribute has to be secured in directory. +##### +##### This attribute is ASN.1 encoded. +##### The format of the value for this attribute is explained below, +##### KrbMKey ::= SEQUENCE { +##### kvno [0] UInt32, +##### key [1] MasterKey +##### } +##### +##### MasterKey ::= SEQUENCE { +##### keytype [0] Int32, +##### keyvalue [1] OCTET STRING +##### } + + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.46.1 + NAME 'krbMKey' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) + + +##### This stores the alternate principal names for the principal in the RFC 1961 specified format + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.47.1 + NAME 'krbPrincipalAliases' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + + +##### The time at which the principal's last successful authentication happened. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.48.1 + NAME 'krbLastSuccessfulAuth' + EQUALITY generalizedTimeMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE ) + + +##### The time at which the principal's last failed authentication happened. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.49.1 + NAME 'krbLastFailedAuth' + EQUALITY generalizedTimeMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE ) + + +##### This attribute stores the number of failed authentication attempts +##### happened for the principal since the last successful authentication. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.50.1 + NAME 'krbLoginFailedCount' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE ) + + + +##### This attribute holds the application specific data. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.51.1 + NAME 'krbExtraData' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) + + +##### This attributes holds references to the set of directory objects. +##### This stores the DNs of the directory objects to which the +##### principal object belongs to. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.52.1 + NAME 'krbObjectReferences' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + + +##### This attribute holds references to a Container object where +##### the additional principal objects and stand alone principal +##### objects (krbPrincipal) can be created. + +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113719.1.301.4.53.1 + NAME 'krbPrincContainerRef' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) + + +##### A list of authentication indicator strings, one of which must be satisfied +##### to authenticate to the principal as a service. +##### FreeIPA OID: +##### joint-iso-ccitt(3) country(16) us(840) organization(1) netscape(113730) +##### ldap(3) freeipa(8) krb5(15) attributes(2) +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 2.16.840.1.113730.3.8.15.2.1 + NAME 'krbPrincipalAuthInd' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15) + + +##### A list of services to which a service principal can delegate. +dn: cn=schema +changetype: modify +add: attributetypes +attributetypes: ( 1.3.6.1.4.1.5322.21.2.4 + NAME 'krbAllowedToDelegateTo' + EQUALITY caseExactIA5Match + SUBSTR caseExactSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) + +######################################################################## +######################################################################## +# Object Class Definitions # +######################################################################## + +#### This is a kerberos container for all the realms in a tree. + +dn: cn=schema +changetype: modify +add: objectclasses +objectClasses: ( 2.16.840.1.113719.1.301.6.1.1 + NAME 'krbContainer' + SUP top + MUST ( cn ) ) + + +##### The krbRealmContainer is created per realm and holds realm specific data. + +dn: cn=schema +changetype: modify +add: objectclasses +objectClasses: ( 2.16.840.1.113719.1.301.6.2.1 + NAME 'krbRealmContainer' + SUP top + MUST ( cn ) + MAY ( krbMKey $ krbUPEnabled $ krbSubTrees $ krbSearchScope $ krbLdapServers $ krbSupportedEncSaltTypes $ krbDefaultEncSaltTypes $ krbTicketPolicyReference $ krbKdcServers $ krbPwdServers $ krbAdmServers $ krbPrincNamingAttr $krbPwdPolicyReference $ krbPrincContainerRef ) ) + + +##### An instance of a class derived from krbService is created per +##### kerberos authentication or administration server in an realm and holds +##### references to the realm objects. These references is used to further read +##### realm specific data to service AS/TGS requests. Additionally this object +##### contains some server specific data like pathnames and ports that the +##### server uses. This is the identity the kerberos server logs in with. A key +##### pair for the same is created and the kerberos server logs in with the same. +##### +##### krbKdcService, krbAdmService and krbPwdService derive from this class. + +dn: cn=schema +changetype: modify +add: objectclasses +objectClasses: ( 2.16.840.1.113719.1.301.6.3.1 + NAME 'krbService' + ABSTRACT + SUP ( top ) + MUST ( cn ) + MAY ( krbHostServer $ krbRealmReferences ) ) + + +##### Representative object for the KDC server to bind into a LDAP directory +##### and have a connection to access Kerberos data with the required +##### access rights. + +dn: cn=schema +changetype: modify +add: objectclasses +objectClasses: ( 2.16.840.1.113719.1.301.6.4.1 + NAME 'krbKdcService' + SUP ( krbService ) ) + + +##### Representative object for the Kerberos Password server to bind into a LDAP directory +##### and have a connection to access Kerberos data with the required +##### access rights. + +dn: cn=schema +changetype: modify +add: objectclasses +objectClasses: ( 2.16.840.1.113719.1.301.6.5.1 + NAME 'krbPwdService' + SUP ( krbService ) ) + + +###### The principal data auxiliary class. Holds principal information +###### and is used to store principal information for Person, Service objects. + +dn: cn=schema +changetype: modify +add: objectclasses +objectClasses: ( 2.16.840.1.113719.1.301.6.8.1 + NAME 'krbPrincipalAux' + AUXILIARY + MAY ( krbPrincipalName $ krbCanonicalName $ krbUPEnabled $ krbPrincipalKey $ krbTicketPolicyReference $ krbPrincipalExpiration $ krbPasswordExpiration $ krbPwdPolicyReference $ krbPrincipalType $ krbPwdHistory $ krbLastPwdChange $ krbLastAdminUnlock $ krbPrincipalAliases $ krbLastSuccessfulAuth $ krbLastFailedAuth $ krbLoginFailedCount $ krbExtraData $ krbAllowedToDelegateTo $ krbPrincipalAuthInd ) ) + + +###### This class is used to create additional principals and stand alone principals. + +dn: cn=schema +changetype: modify +add: objectclasses +objectClasses: ( 2.16.840.1.113719.1.301.6.9.1 + NAME 'krbPrincipal' + SUP ( top ) + MUST ( krbPrincipalName ) + MAY ( krbObjectReferences ) ) + + +###### The principal references auxiliary class. Holds all principals referred +###### from a service + +dn: cn=schema +changetype: modify +add: objectclasses +objectClasses: ( 2.16.840.1.113719.1.301.6.11.1 + NAME 'krbPrincRefAux' + SUP top + AUXILIARY + MAY krbPrincipalReferences ) + + +##### Representative object for the Kerberos Administration server to bind into a LDAP directory +##### and have a connection Id to access Kerberos data with the required access rights. + +dn: cn=schema +changetype: modify +add: objectclasses +objectClasses: ( 2.16.840.1.113719.1.301.6.13.1 + NAME 'krbAdmService' + SUP ( krbService ) ) + + +##### The krbPwdPolicy object is a template password policy that +##### can be applied to principals when they are created. +##### These policy attributes will be in effect, when the Kerberos +##### passwords are different from users' passwords (UP). + +dn: cn=schema +changetype: modify +add: objectclasses +objectClasses: ( 2.16.840.1.113719.1.301.6.14.1 + NAME 'krbPwdPolicy' + SUP top + MUST ( cn ) + MAY ( krbMaxPwdLife $ krbMinPwdLife $ krbPwdMinDiffChars $ krbPwdMinLength $ krbPwdHistoryLength $ krbPwdMaxFailure $ krbPwdFailureCountInterval $ krbPwdLockoutDuration $ krbPwdAttributes $ krbPwdMaxLife $ krbPwdMaxRenewableLife $ krbPwdAllowedKeysalts ) ) + + +##### The krbTicketPolicyAux holds Kerberos ticket policy attributes. +##### This class can be attached to a principal object or realm object. + +dn: cn=schema +changetype: modify +add: objectclasses +objectClasses: ( 2.16.840.1.113719.1.301.6.16.1 + NAME 'krbTicketPolicyAux' + AUXILIARY + MAY ( krbTicketFlags $ krbMaxTicketLife $ krbMaxRenewableAge ) ) + + +##### The krbTicketPolicy object is an effective ticket policy that is associated with a realm or a principal + +dn: cn=schema +changetype: modify +add: objectclasses +objectClasses: ( 2.16.840.1.113719.1.301.6.17.1 + NAME 'krbTicketPolicy' + SUP top + MUST ( cn ) ) + diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kerberos.openldap.ldif b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kerberos.openldap.ldif new file mode 100644 index 00000000..830277d7 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kerberos.openldap.ldif @@ -0,0 +1,68 @@ +# This LDIF version of the Kerberos schema can be loaded into an +# OpenLDAP database. It was originally converted semi-automatically +# from kerberos.schema using slaptest. + +dn: cn=kerberos,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: kerberos +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.1.1 NAME 'krbPrincipalName' EQUALITY caseExactIA5Match SUBSTR caseExactSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 1.2.840.113554.1.4.1.6.1 NAME 'krbCanonicalName' EQUALITY caseExactIA5Match SUBSTR caseExactSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.3.1 NAME 'krbPrincipalType' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.5.1 NAME 'krbUPEnabled' DESC 'Boolean' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.6.1 NAME 'krbPrincipalExpiration' EQUALITY generalizedTimeMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.8.1 NAME 'krbTicketFlags' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.9.1 NAME 'krbMaxTicketLife' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.10.1 NAME 'krbMaxRenewableAge' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.14.1 NAME 'krbRealmReferences' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.15.1 NAME 'krbLdapServers' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.17.1 NAME 'krbKdcServers' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.18.1 NAME 'krbPwdServers' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.24.1 NAME 'krbHostServer' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.25.1 NAME 'krbSearchScope' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.26.1 NAME 'krbPrincipalReferences' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.28.1 NAME 'krbPrincNamingAttr' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.29.1 NAME 'krbAdmServers' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.30.1 NAME 'krbMaxPwdLife' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.31.1 NAME 'krbMinPwdLife' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.32.1 NAME 'krbPwdMinDiffChars' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.33.1 NAME 'krbPwdMinLength' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.34.1 NAME 'krbPwdHistoryLength' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.5322.21.2.1 NAME 'krbPwdMaxFailure' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.5322.21.2.2 NAME 'krbPwdFailureCountInterval' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.5322.21.2.3 NAME 'krbPwdLockoutDuration' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 1.2.840.113554.1.4.1.6.2 NAME 'krbPwdAttributes' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 1.2.840.113554.1.4.1.6.3 NAME 'krbPwdMaxLife' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 1.2.840.113554.1.4.1.6.4 NAME 'krbPwdMaxRenewableLife' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 1.2.840.113554.1.4.1.6.5 NAME 'krbPwdAllowedKeysalts' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.36.1 NAME 'krbPwdPolicyReference' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.37.1 NAME 'krbPasswordExpiration' EQUALITY generalizedTimeMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.39.1 NAME 'krbPrincipalKey' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.40.1 NAME 'krbTicketPolicyReference' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.41.1 NAME 'krbSubTrees' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.42.1 NAME 'krbDefaultEncSaltTypes' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.43.1 NAME 'krbSupportedEncSaltTypes' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.44.1 NAME 'krbPwdHistory' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.45.1 NAME 'krbLastPwdChange' EQUALITY generalizedTimeMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.5322.21.2.5 NAME 'krbLastAdminUnlock' EQUALITY generalizedTimeMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.46.1 NAME 'krbMKey' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.47.1 NAME 'krbPrincipalAliases' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.48.1 NAME 'krbLastSuccessfulAuth' EQUALITY generalizedTimeMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.49.1 NAME 'krbLastFailedAuth' EQUALITY generalizedTimeMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.50.1 NAME 'krbLoginFailedCount' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.51.1 NAME 'krbExtraData' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.52.1 NAME 'krbObjectReferences' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: ( 2.16.840.1.113719.1.301.4.53.1 NAME 'krbPrincContainerRef' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 ) +olcAttributeTypes: ( 2.16.840.1.113730.3.8.15.2.1 NAME 'krbPrincipalAuthInd' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: ( 1.3.6.1.4.1.5322.21.2.4 NAME 'krbAllowedToDelegateTo' EQUALITY caseExactIA5Match SUBSTR caseExactSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) +olcObjectClasses: ( 2.16.840.1.113719.1.301.6.1.1 NAME 'krbContainer' SUP top STRUCTURAL MUST cn ) +olcObjectClasses: ( 2.16.840.1.113719.1.301.6.2.1 NAME 'krbRealmContainer' SUP top STRUCTURAL MUST cn MAY ( krbMKey $ krbUPEnabled $ krbSubTrees $ krbSearchScope $ krbLdapServers $ krbSupportedEncSaltTypes $ krbDefaultEncSaltTypes $ krbTicketPolicyReference $ krbKdcServers $ krbPwdServers $ krbAdmServers $ krbPrincNamingAttr $ krbPwdPolicyReference $ krbPrincContainerRef ) ) +olcObjectClasses: ( 2.16.840.1.113719.1.301.6.3.1 NAME 'krbService' SUP top ABSTRACT MUST cn MAY ( krbHostServer $ krbRealmReferences ) ) +olcObjectClasses: ( 2.16.840.1.113719.1.301.6.4.1 NAME 'krbKdcService' SUP krbService STRUCTURAL ) +olcObjectClasses: ( 2.16.840.1.113719.1.301.6.5.1 NAME 'krbPwdService' SUP krbService STRUCTURAL ) +olcObjectClasses: ( 2.16.840.1.113719.1.301.6.8.1 NAME 'krbPrincipalAux' SUP top AUXILIARY MAY ( krbPrincipalName $ krbCanonicalName $ krbUPEnabled $ krbPrincipalKey $ krbTicketPolicyReference $ krbPrincipalExpiration $ krbPasswordExpiration $ krbPwdPolicyReference $ krbPrincipalType $ krbPwdHistory $ krbLastPwdChange $ krbLastAdminUnlock $ krbPrincipalAliases $ krbLastSuccessfulAuth $ krbLastFailedAuth $ krbLoginFailedCount $ krbExtraData $ krbAllowedToDelegateTo $ krbPrincipalAuthInd ) ) +olcObjectClasses: ( 2.16.840.1.113719.1.301.6.9.1 NAME 'krbPrincipal' SUP top STRUCTURAL MUST krbPrincipalName MAY krbObjectReferences ) +olcObjectClasses: ( 2.16.840.1.113719.1.301.6.11.1 NAME 'krbPrincRefAux' SUP top AUXILIARY MAY krbPrincipalReferences ) +olcObjectClasses: ( 2.16.840.1.113719.1.301.6.13.1 NAME 'krbAdmService' SUP krbService STRUCTURAL ) +olcObjectClasses: ( 2.16.840.1.113719.1.301.6.14.1 NAME 'krbPwdPolicy' SUP top STRUCTURAL MUST cn MAY ( krbMaxPwdLife $ krbMinPwdLife $ krbPwdMinDiffChars $ krbPwdMinLength $ krbPwdHistoryLength $ krbPwdMaxFailure $ krbPwdFailureCountInterval $ krbPwdLockoutDuration $ krbPwdAttributes $ krbPwdMaxLife $ krbPwdMaxRenewableLife $ krbPwdAllowedKeysalts ) ) +olcObjectClasses: ( 2.16.840.1.113719.1.301.6.16.1 NAME 'krbTicketPolicyAux' SUP top AUXILIARY MAY ( krbTicketFlags $ krbMaxTicketLife $ krbMaxRenewableAge ) ) +olcObjectClasses: ( 2.16.840.1.113719.1.301.6.17.1 NAME 'krbTicketPolicy' SUP top STRUCTURAL MUST cn ) diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema new file mode 100644 index 00000000..171f6692 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema @@ -0,0 +1,726 @@ +# Novell Kerberos Schema Definitions +# Novell Inc. +# 1800 South Novell Place +# Provo, UT 84606 +# +# VeRsIoN=1.0 +# CoPyRiGhT=(c) Copyright 2006, Novell, Inc. All rights reserved +# +# OIDs: +# joint-iso-ccitt(2) +# country(16) +# us(840) +# organization(1) +# Novell(113719) +# applications(1) +# kerberos(301) +# Kerberos Attribute Type(4) attr# version# +# specific attribute definitions +# Kerberos Attribute Syntax(5) +# specific syntax definitions +# Kerberos Object Class(6) class# version# +# specific class definitions +# +# iso(1) +# member-body(2) +# United States(840) +# mit (113554) +# infosys(1) +# ldap(4) +# attributeTypes(1) +# Kerberos(6) + +######################################################################## + + +######################################################################## +# Attribute Type Definitions # +######################################################################## + +##### This is the principal name in the RFC 1964 specified format + +attributetype ( 2.16.840.1.113719.1.301.4.1.1 + NAME 'krbPrincipalName' + EQUALITY caseExactIA5Match + SUBSTR caseExactSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26) + +##### If there are multiple krbPrincipalName values for an entry, this +##### is the canonical principal name in the RFC 1964 specified +##### format. (If this attribute does not exist, then all +##### krbPrincipalName values are treated as canonical.) + +attributetype ( 1.2.840.113554.1.4.1.6.1 + NAME 'krbCanonicalName' + EQUALITY caseExactIA5Match + SUBSTR caseExactSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE) + +##### This specifies the type of the principal, the types could be any of +##### the types mentioned in section 6.2 of RFC 4120 + +attributetype ( 2.16.840.1.113719.1.301.4.3.1 + NAME 'krbPrincipalType' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### This flag is used to find whether directory User Password has to be used +##### as kerberos password. +##### TRUE, if User Password is to be used as the kerberos password. +##### FALSE, if User Password and the kerberos password are different. + +attributetype ( 2.16.840.1.113719.1.301.4.5.1 + NAME 'krbUPEnabled' + DESC 'Boolean' + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE) + + +##### The time at which the principal expires + +attributetype ( 2.16.840.1.113719.1.301.4.6.1 + NAME 'krbPrincipalExpiration' + EQUALITY generalizedTimeMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE) + + +##### The krbTicketFlags attribute holds information about the kerberos flags for a principal +##### The values (0x00000001 - 0x00800000) are reserved for standards and +##### values (0x01000000 - 0x80000000) can be used for proprietary extensions. +##### The flags and values as per RFC 4120 and MIT implementation are, +##### DISALLOW_POSTDATED 0x00000001 +##### DISALLOW_FORWARDABLE 0x00000002 +##### DISALLOW_TGT_BASED 0x00000004 +##### DISALLOW_RENEWABLE 0x00000008 +##### DISALLOW_PROXIABLE 0x00000010 +##### DISALLOW_DUP_SKEY 0x00000020 +##### DISALLOW_ALL_TIX 0x00000040 +##### REQUIRES_PRE_AUTH 0x00000080 +##### REQUIRES_HW_AUTH 0x00000100 +##### REQUIRES_PWCHANGE 0x00000200 +##### DISALLOW_SVR 0x00001000 +##### PWCHANGE_SERVICE 0x00002000 + + +attributetype ( 2.16.840.1.113719.1.301.4.8.1 + NAME 'krbTicketFlags' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### The maximum ticket lifetime for a principal in seconds + +attributetype ( 2.16.840.1.113719.1.301.4.9.1 + NAME 'krbMaxTicketLife' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### Maximum renewable lifetime for a principal's ticket in seconds + +attributetype ( 2.16.840.1.113719.1.301.4.10.1 + NAME 'krbMaxRenewableAge' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### Forward reference to the Realm object. +##### (FDN of the krbRealmContainer object). +##### Example: cn=ACME.COM, cn=Kerberos, cn=Security + +attributetype ( 2.16.840.1.113719.1.301.4.14.1 + NAME 'krbRealmReferences' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12) + + +##### List of LDAP servers that kerberos servers can contact. +##### The attribute holds data in the ldap uri format, +##### Examples: acme.com#636, 164.164.164.164#1636, ldaps://acme.com:636 +##### +##### The values of this attribute need to be updated, when +##### the LDAP servers listed here are renamed, moved or deleted. + +attributetype ( 2.16.840.1.113719.1.301.4.15.1 + NAME 'krbLdapServers' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15) + + +##### A set of forward references to the KDC Service objects. +##### (FDNs of the krbKdcService objects). +##### Example: cn=kdc - server 1, ou=uvw, o=xyz + +attributetype ( 2.16.840.1.113719.1.301.4.17.1 + NAME 'krbKdcServers' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12) + + +##### A set of forward references to the Password Service objects. +##### (FDNs of the krbPwdService objects). +##### Example: cn=kpasswdd - server 1, ou=uvw, o=xyz + +attributetype ( 2.16.840.1.113719.1.301.4.18.1 + NAME 'krbPwdServers' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12) + + +##### This attribute holds the Host Name or the ip address, +##### transport protocol and ports of the kerberos service host +##### The format is host_name-or-ip_address#protocol#port +##### Protocol can be 0 or 1. 0 is for UDP. 1 is for TCP. + +attributetype ( 2.16.840.1.113719.1.301.4.24.1 + NAME 'krbHostServer' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26) + + +##### This attribute holds the scope for searching the principals +##### under krbSubTree attribute of krbRealmContainer +##### The value can either be 1 (ONE) or 2 (SUB_TREE). + +attributetype ( 2.16.840.1.113719.1.301.4.25.1 + NAME 'krbSearchScope' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### FDNs pointing to Kerberos principals + +attributetype ( 2.16.840.1.113719.1.301.4.26.1 + NAME 'krbPrincipalReferences' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12) + + +##### This attribute specifies which attribute of the user objects +##### be used as the principal name component for Kerberos. +##### The allowed values are cn, sn, uid, givenname, fullname. + +attributetype ( 2.16.840.1.113719.1.301.4.28.1 + NAME 'krbPrincNamingAttr' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE) + + +##### A set of forward references to the Administration Service objects. +##### (FDNs of the krbAdmService objects). +##### Example: cn=kadmindd - server 1, ou=uvw, o=xyz + +attributetype ( 2.16.840.1.113719.1.301.4.29.1 + NAME 'krbAdmServers' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12) + + +##### Maximum lifetime of a principal's password + +attributetype ( 2.16.840.1.113719.1.301.4.30.1 + NAME 'krbMaxPwdLife' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### Minimum lifetime of a principal's password + +attributetype ( 2.16.840.1.113719.1.301.4.31.1 + NAME 'krbMinPwdLife' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### Minimum number of character clases allowed in a password + +attributetype ( 2.16.840.1.113719.1.301.4.32.1 + NAME 'krbPwdMinDiffChars' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### Minimum length of the password + +attributetype ( 2.16.840.1.113719.1.301.4.33.1 + NAME 'krbPwdMinLength' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### Number of previous versions of passwords that are stored + +attributetype ( 2.16.840.1.113719.1.301.4.34.1 + NAME 'krbPwdHistoryLength' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### Number of consecutive pre-authentication failures before lockout + +attributetype ( 1.3.6.1.4.1.5322.21.2.1 + NAME 'krbPwdMaxFailure' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### Period after which bad preauthentication count will be reset + +attributetype ( 1.3.6.1.4.1.5322.21.2.2 + NAME 'krbPwdFailureCountInterval' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### Period in which lockout is enforced + +attributetype ( 1.3.6.1.4.1.5322.21.2.3 + NAME 'krbPwdLockoutDuration' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### Policy attribute flags + +attributetype ( 1.2.840.113554.1.4.1.6.2 + NAME 'krbPwdAttributes' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### Policy maximum ticket lifetime + +attributetype ( 1.2.840.113554.1.4.1.6.3 + NAME 'krbPwdMaxLife' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### Policy maximum ticket renewable lifetime + +attributetype ( 1.2.840.113554.1.4.1.6.4 + NAME 'krbPwdMaxRenewableLife' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + +##### Allowed enctype:salttype combinations for key changes + +attributetype ( 1.2.840.113554.1.4.1.6.5 + NAME 'krbPwdAllowedKeysalts' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE) + + +##### FDN pointing to a Kerberos Password Policy object + +attributetype ( 2.16.840.1.113719.1.301.4.36.1 + NAME 'krbPwdPolicyReference' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE) + + +##### The time at which the principal's password expires + +attributetype ( 2.16.840.1.113719.1.301.4.37.1 + NAME 'krbPasswordExpiration' + EQUALITY generalizedTimeMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE) + + +##### This attribute holds the principal's key (krbPrincipalKey) that is encrypted with +##### the master key (krbMKey). +##### The attribute is ASN.1 encoded. +##### +##### The format of the value for this attribute is explained below, +##### KrbKeySet ::= SEQUENCE { +##### attribute-major-vno [0] UInt16, +##### attribute-minor-vno [1] UInt16, +##### kvno [2] UInt32, +##### mkvno [3] UInt32 OPTIONAL, +##### keys [4] SEQUENCE OF KrbKey, +##### ... +##### } +##### +##### KrbKey ::= SEQUENCE { +##### salt [0] KrbSalt OPTIONAL, +##### key [1] EncryptionKey, +##### s2kparams [2] OCTET STRING OPTIONAL, +##### ... +##### } +##### +##### KrbSalt ::= SEQUENCE { +##### type [0] Int32, +##### salt [1] OCTET STRING OPTIONAL +##### } +##### +##### EncryptionKey ::= SEQUENCE { +##### keytype [0] Int32, +##### keyvalue [1] OCTET STRING +##### } + +attributetype ( 2.16.840.1.113719.1.301.4.39.1 + NAME 'krbPrincipalKey' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40) + + +##### FDN pointing to a Kerberos Ticket Policy object. + +attributetype ( 2.16.840.1.113719.1.301.4.40.1 + NAME 'krbTicketPolicyReference' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 + SINGLE-VALUE) + + +##### Forward reference to an entry that starts sub-trees +##### where principals and other kerberos objects in the realm are configured. +##### Example: ou=acme, ou=pq, o=xyz + +attributetype ( 2.16.840.1.113719.1.301.4.41.1 + NAME 'krbSubTrees' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12) + + +##### Holds the default encryption/salt type combinations of principals for +##### the Realm. Stores in the form of key:salt strings. This will be +##### subset of the supported encryption/salt types. +##### Example: aes256-cts-hmac-sha384-192:normal + +attributetype ( 2.16.840.1.113719.1.301.4.42.1 + NAME 'krbDefaultEncSaltTypes' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15) + + +##### Holds the supported encryption/salt type combinations of principals for +##### the Realm. Stores in the form of key:salt strings. +##### The supported encryption types are mentioned in RFC 3961 +##### The supported salt types are, +##### NORMAL +##### V4 +##### NOREALM +##### ONLYREALM +##### SPECIAL +##### AFS3 +##### Example: aes256-cts-hmac-sha384-192:normal + +attributetype ( 2.16.840.1.113719.1.301.4.43.1 + NAME 'krbSupportedEncSaltTypes' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15) + + +##### This attribute holds the principal's old keys (krbPwdHistory) that is encrypted with +##### the kadmin/history key. +##### The attribute is ASN.1 encoded. +##### +##### The format of the value for this attribute is explained below, +##### KrbKeySet ::= SEQUENCE { +##### attribute-major-vno [0] UInt16, +##### attribute-minor-vno [1] UInt16, +##### kvno [2] UInt32, +##### mkvno [3] UInt32 OPTIONAL -- actually kadmin/history key, +##### keys [4] SEQUENCE OF KrbKey, +##### ... +##### } +##### +##### KrbKey ::= SEQUENCE { +##### salt [0] KrbSalt OPTIONAL, +##### key [1] EncryptionKey, +##### s2kparams [2] OCTET STRING OPTIONAL, +##### ... +##### } +##### +##### KrbSalt ::= SEQUENCE { +##### type [0] Int32, +##### salt [1] OCTET STRING OPTIONAL +##### } +##### +##### EncryptionKey ::= SEQUENCE { +##### keytype [0] Int32, +##### keyvalue [1] OCTET STRING +##### } + +attributetype ( 2.16.840.1.113719.1.301.4.44.1 + NAME 'krbPwdHistory' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40) + + +##### The time at which the principal's password last password change happened. + +attributetype ( 2.16.840.1.113719.1.301.4.45.1 + NAME 'krbLastPwdChange' + EQUALITY generalizedTimeMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE) + +##### The time at which the principal was last administratively unlocked. + +attributetype ( 1.3.6.1.4.1.5322.21.2.5 + NAME 'krbLastAdminUnlock' + EQUALITY generalizedTimeMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE) + +##### This attribute holds the kerberos master key. +##### This can be used to encrypt principal keys. +##### This attribute has to be secured in directory. +##### +##### This attribute is ASN.1 encoded. +##### The format of the value for this attribute is explained below, +##### KrbMKey ::= SEQUENCE { +##### kvno [0] UInt32, +##### key [1] MasterKey +##### } +##### +##### MasterKey ::= SEQUENCE { +##### keytype [0] Int32, +##### keyvalue [1] OCTET STRING +##### } + + +attributetype ( 2.16.840.1.113719.1.301.4.46.1 + NAME 'krbMKey' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40) + + +##### This stores the alternate principal names for the principal in the RFC 1964 specified format + +attributetype ( 2.16.840.1.113719.1.301.4.47.1 + NAME 'krbPrincipalAliases' + EQUALITY caseExactIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26) + + +##### The time at which the principal's last successful authentication happened. + +attributetype ( 2.16.840.1.113719.1.301.4.48.1 + NAME 'krbLastSuccessfulAuth' + EQUALITY generalizedTimeMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE) + + +##### The time at which the principal's last failed authentication happened. + +attributetype ( 2.16.840.1.113719.1.301.4.49.1 + NAME 'krbLastFailedAuth' + EQUALITY generalizedTimeMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 + SINGLE-VALUE) + + +##### This attribute stores the number of failed authentication attempts +##### happened for the principal since the last successful authentication. + +attributetype ( 2.16.840.1.113719.1.301.4.50.1 + NAME 'krbLoginFailedCount' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 + SINGLE-VALUE) + + + +##### This attribute holds the application specific data. + +attributetype ( 2.16.840.1.113719.1.301.4.51.1 + NAME 'krbExtraData' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40) + + +##### This attributes holds references to the set of directory objects. +##### This stores the DNs of the directory objects to which the +##### principal object belongs to. + +attributetype ( 2.16.840.1.113719.1.301.4.52.1 + NAME 'krbObjectReferences' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12) + + +##### This attribute holds references to a Container object where +##### the additional principal objects and stand alone principal +##### objects (krbPrincipal) can be created. + +attributetype ( 2.16.840.1.113719.1.301.4.53.1 + NAME 'krbPrincContainerRef' + EQUALITY distinguishedNameMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.12) + + +##### A list of authentication indicator strings, one of which must be satisfied +##### to authenticate to the principal as a service. +##### FreeIPA OID: +##### joint-iso-ccitt(3) country(16) us(840) organization(1) netscape(113730) +##### ldap(3) freeipa(8) krb5(15) attributes(2) +attributetype ( 2.16.840.1.113730.3.8.15.2.1 + NAME 'krbPrincipalAuthInd' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15) + + +##### A list of services to which a service principal can delegate. +attributetype ( 1.3.6.1.4.1.5322.21.2.4 + NAME 'krbAllowedToDelegateTo' + EQUALITY caseExactIA5Match + SUBSTR caseExactSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26) + +######################################################################## +######################################################################## +# Object Class Definitions # +######################################################################## + +#### This is a kerberos container for all the realms in a tree. + +objectclass ( 2.16.840.1.113719.1.301.6.1.1 + NAME 'krbContainer' + SUP top + STRUCTURAL + MUST ( cn ) ) + + +##### The krbRealmContainer is created per realm and holds realm specific data. + +objectclass ( 2.16.840.1.113719.1.301.6.2.1 + NAME 'krbRealmContainer' + SUP top + STRUCTURAL + MUST ( cn ) + MAY ( krbMKey $ krbUPEnabled $ krbSubTrees $ krbSearchScope $ krbLdapServers $ krbSupportedEncSaltTypes $ krbDefaultEncSaltTypes $ krbTicketPolicyReference $ krbKdcServers $ krbPwdServers $ krbAdmServers $ krbPrincNamingAttr $ krbPwdPolicyReference $ krbPrincContainerRef ) ) + + +##### An instance of a class derived from krbService is created per +##### kerberos authentication or administration server in an realm and holds +##### references to the realm objects. These references is used to further read +##### realm specific data to service AS/TGS requests. Additionally this object +##### contains some server specific data like pathnames and ports that the +##### server uses. This is the identity the kerberos server logs in with. A key +##### pair for the same is created and the kerberos server logs in with the same. +##### +##### krbKdcService, krbAdmService and krbPwdService derive from this class. + +objectclass ( 2.16.840.1.113719.1.301.6.3.1 + NAME 'krbService' + SUP top + ABSTRACT + MUST ( cn ) + MAY ( krbHostServer $ krbRealmReferences ) ) + + +##### Representative object for the KDC server to bind into a LDAP directory +##### and have a connection to access Kerberos data with the required +##### access rights. + +objectclass ( 2.16.840.1.113719.1.301.6.4.1 + NAME 'krbKdcService' + SUP krbService + STRUCTURAL ) + + +##### Representative object for the Kerberos Password server to bind into a LDAP directory +##### and have a connection to access Kerberos data with the required +##### access rights. + +objectclass ( 2.16.840.1.113719.1.301.6.5.1 + NAME 'krbPwdService' + SUP krbService + STRUCTURAL ) + + +###### The principal data auxiliary class. Holds principal information +###### and is used to store principal information for Person, Service objects. + +objectclass ( 2.16.840.1.113719.1.301.6.8.1 + NAME 'krbPrincipalAux' + SUP top + AUXILIARY + MAY ( krbPrincipalName $ krbCanonicalName $ krbUPEnabled $ krbPrincipalKey $ krbTicketPolicyReference $ krbPrincipalExpiration $ krbPasswordExpiration $ krbPwdPolicyReference $ krbPrincipalType $ krbPwdHistory $ krbLastPwdChange $ krbLastAdminUnlock $ krbPrincipalAliases $ krbLastSuccessfulAuth $ krbLastFailedAuth $ krbLoginFailedCount $ krbExtraData $ krbAllowedToDelegateTo $ krbPrincipalAuthInd ) ) + + +###### This class is used to create additional principals and stand alone principals. + +objectclass ( 2.16.840.1.113719.1.301.6.9.1 + NAME 'krbPrincipal' + SUP top + MUST ( krbPrincipalName ) + MAY ( krbObjectReferences ) ) + + +###### The principal references auxiliary class. Holds all principals referred +###### from a service + +objectclass ( 2.16.840.1.113719.1.301.6.11.1 + NAME 'krbPrincRefAux' + SUP top + AUXILIARY + MAY krbPrincipalReferences ) + + +##### Representative object for the Kerberos Administration server to bind into a LDAP directory +##### and have a connection Id to access Kerberos data with the required access rights. + +objectclass ( 2.16.840.1.113719.1.301.6.13.1 + NAME 'krbAdmService' + SUP krbService + STRUCTURAL ) + + +##### The krbPwdPolicy object is a template password policy that +##### can be applied to principals when they are created. +##### These policy attributes will be in effect, when the Kerberos +##### passwords are different from users' passwords (UP). + +objectclass ( 2.16.840.1.113719.1.301.6.14.1 + NAME 'krbPwdPolicy' + SUP top + MUST ( cn ) + MAY ( krbMaxPwdLife $ krbMinPwdLife $ krbPwdMinDiffChars $ krbPwdMinLength $ krbPwdHistoryLength $ krbPwdMaxFailure $ krbPwdFailureCountInterval $ krbPwdLockoutDuration $ krbPwdAttributes $ krbPwdMaxLife $ krbPwdMaxRenewableLife $ krbPwdAllowedKeysalts ) ) + + +##### The krbTicketPolicyAux holds Kerberos ticket policy attributes. +##### This class can be attached to a principal object or realm object. + +objectclass ( 2.16.840.1.113719.1.301.6.16.1 + NAME 'krbTicketPolicyAux' + SUP top + AUXILIARY + MAY ( krbTicketFlags $ krbMaxTicketLife $ krbMaxRenewableAge ) ) + + +##### The krbTicketPolicy object is an effective ticket policy that is associated with a realm or a principal + +objectclass ( 2.16.840.1.113719.1.301.6.17.1 + NAME 'krbTicketPolicy' + SUP top + MUST ( cn ) ) + diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c new file mode 100644 index 00000000..2d660566 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c @@ -0,0 +1,125 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_create.c */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include "ldap_main.h" +#include "ldap_realm.h" +#include "ldap_principal.h" +#include "ldap_krbcontainer.h" +#include "ldap_err.h" + +/* + * ****************************************************************************** + * DAL functions + * ****************************************************************************** + */ + +/* + * This function will create a krbcontainer and realm on the LDAP Server, with + * the specified attributes. + */ +krb5_error_code +krb5_ldap_create(krb5_context context, char *conf_section, char **db_args) +{ + krb5_error_code status = 0; + krb5_ldap_realm_params *rparams = NULL; + krb5_ldap_context *ldap_context=NULL; + int mask = 0; + + /* Clear the global error string */ + krb5_clear_error_message(context); + + ldap_context = k5alloc(sizeof(krb5_ldap_context), &status); + if (ldap_context == NULL) + goto cleanup; + context->dal_handle->db_context = ldap_context; + ldap_context->kcontext = context; + + status = krb5_ldap_parse_db_params(context, db_args); + if (status) { + k5_prependmsg(context, status, _("Error processing LDAP DB params")); + goto cleanup; + } + + status = krb5_ldap_read_server_params(context, conf_section, KRB5_KDB_SRV_TYPE_ADMIN); + if (status) { + k5_prependmsg(context, status, _("Error reading LDAP server params")); + goto cleanup; + } + status = krb5_ldap_db_init(context, ldap_context); + if (status) { + goto cleanup; + } + + /* read the kerberos container */ + status = krb5_ldap_read_krbcontainer_dn(context, + &ldap_context->container_dn); + if (status) + goto cleanup; + + status = krb5_ldap_create_krbcontainer(context, + ldap_context->container_dn); + if (status) + goto cleanup; + + rparams = (krb5_ldap_realm_params *) malloc(sizeof(krb5_ldap_realm_params)); + if (rparams == NULL) { + status = ENOMEM; + goto cleanup; + } + memset(rparams, 0, sizeof(*rparams)); + rparams->realm_name = strdup(context->default_realm); + if (rparams->realm_name == NULL) { + status = ENOMEM; + goto cleanup; + } + + if ((status = krb5_ldap_create_realm(context, rparams, mask))) + goto cleanup; + + /* verify realm object */ + if ((status = krb5_ldap_read_realm_params(context, + rparams->realm_name, + &(ldap_context->lrparams), + &mask))) + goto cleanup; + +cleanup: + if (rparams) + krb5_ldap_free_realm_params(rparams); + + if (status) + krb5_ldap_close(context); + return(status); +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.c new file mode 100644 index 00000000..16f9dccd --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.c @@ -0,0 +1,195 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#include +#include +#include +#include "ldap_err.h" +#ifndef LDAP_X_ERROR +#define LDAP_X_ERROR(x) (0) +#endif + +#ifndef LDAP_NAME_ERROR +#ifdef NAME_ERROR +#define LDAP_NAME_ERROR NAME_ERROR +#else +#define LDAP_NAME_ERROR(x) (0) +#endif +#endif + +#ifndef LDAP_SECURITY_ERROR +#define LDAP_SECURITY_ERROR(x) (0) +#endif + +#ifndef LDAP_SERVICE_ERROR +#define LDAP_SERVICE_ERROR(x) (0) +#endif + +#ifndef LDAP_API_ERROR +#define LDAP_API_ERROR(x) (0) +#endif + +#ifndef LDAP_UPDATE_ERROR +#define LDAP_UPDATE_ERROR(x) (0) +#endif + +/* + * The possible KDB errors are + * 1. KRB5_KDB_UK_RERROR + * 2. KRB5_KDB_UK_SERROR + * 3. KRB5_KDB_NOENTRY + * 4. KRB5_KDB_TRUNCATED_RECORD + * 5. KRB5_KDB_UNAUTH + * 6. KRB5_KDB_DB_CORRUPT + * 7. KRB5_KDB_ACCESS_ERROR (NEW) + * 8. KRB5_KDB_INTERNAL_ERROR (NEW) + * 9. KRB5_KDB_SERVER_INTERNAL_ERR (NEW) + * 10. KRB5_KDB_CONSTRAINT_VIOLATION (NEW) + * + */ + +/* + * op : + * 0 => not specified + * OP_INIT => ldap_init + * OP_BIND => ldap_bind + * OP_UNBIND => ldap_unbind + * OP_ADD => ldap_add + * OP_MOD => ldap_modify + * OP_DEL => ldap_delete + * OP_SEARCH => ldap_search + * OP_CMP => ldap_compare + * OP_ABANDON => ldap_abandon + */ + +int +translate_ldap_error(int err, int op) { + + switch (err) { + case LDAP_SUCCESS: + return 0; + + case LDAP_OPERATIONS_ERROR: + /* LDAP_OPERATIONS_ERROR: Indicates an internal error. The server is + * unable to respond with a more specific error and is also unable + * to properly respond to a request */ + case LDAP_UNAVAILABLE_CRITICAL_EXTENSION: + /* LDAP server was unable to satisfy a request because one or more + * critical extensions were not available */ + /* This might mean that the schema was not extended ... */ + case LDAP_UNDEFINED_TYPE: + /* The attribute specified in the modify or add operation does not + * exist in the LDAP server's schema. */ + return KRB5_KDB_INTERNAL_ERROR; + + + case LDAP_INAPPROPRIATE_MATCHING: + /* The matching rule specified in the search filter does not match a + * rule defined for the attribute's syntax */ + return KRB5_KDB_UK_RERROR; + + case LDAP_CONSTRAINT_VIOLATION: + /* The attribute value specified in a modify, add, or modify DN + * operation violates constraints placed on the attribute */ + case LDAP_TYPE_OR_VALUE_EXISTS: + /* The attribute value specified in a modify or add operation + * already exists as a value for that attribute */ + return KRB5_KDB_UK_SERROR; + + case LDAP_INVALID_SYNTAX: + /* The attribute value specified in an add, compare, or modify + * operation is an unrecognized or invalid syntax for the attribute */ + if (op == OP_ADD || op == OP_MOD) + return KRB5_KDB_UK_SERROR; + else /* OP_CMP */ + return KRB5_KDB_UK_RERROR; + + /* Ensure that the following don't occur in the DAL-LDAP code. + * Don't rely on the LDAP server to catch it */ + case LDAP_SASL_BIND_IN_PROGRESS: + /* This is not an error. So, this function should not be called */ + case LDAP_COMPARE_FALSE: + case LDAP_COMPARE_TRUE: + /* LDAP_COMPARE_FALSE and LDAP_COMPARE_TRUE are not errors. This + * function should not be invoked for them */ + case LDAP_RESULTS_TOO_LARGE: /* CLDAP */ + case LDAP_TIMELIMIT_EXCEEDED: + case LDAP_SIZELIMIT_EXCEEDED: + return KRB5_KDB_SERVER_INTERNAL_ERR; + + case LDAP_INVALID_DN_SYNTAX: + /* The syntax of the DN is incorrect */ + return EINVAL; + + case LDAP_PROTOCOL_ERROR: + /* LDAP_PROTOCOL_ERROR: Indicates that the server has received an + * invalid or malformed request from the client */ + case LDAP_CONFIDENTIALITY_REQUIRED: + + /* Bind problems ... */ + case LDAP_AUTH_METHOD_NOT_SUPPORTED: +/* case LDAP_STRONG_AUTH_NOT_SUPPORTED: // Is this a bind error ? */ + case LDAP_INAPPROPRIATE_AUTH: + case LDAP_INVALID_CREDENTIALS: + case LDAP_UNAVAILABLE: + return KRB5_KDB_ACCESS_ERROR; + + case LDAP_STRONG_AUTH_REQUIRED: + if (op == OP_BIND) /* the LDAP server accepts only strong authentication. */ + return KRB5_KDB_ACCESS_ERROR; + else /* Client requested an operation such that requires strong authentication */ + return KRB5_KDB_CONSTRAINT_VIOLATION; + + case LDAP_REFERRAL: + return KRB5_KDB_NOENTRY; + + case LDAP_ADMINLIMIT_EXCEEDED: + /* An LDAP server limit set by an administrative authority has been + * exceeded */ + return KRB5_KDB_CONSTRAINT_VIOLATION; + case LDAP_UNWILLING_TO_PERFORM: + /* The LDAP server cannot process the request because of + * server-defined restrictions */ + return KRB5_KDB_CONSTRAINT_VIOLATION; + + + case LDAP_NO_SUCH_ATTRIBUTE: + /* Indicates that the attribute specified in the modify or compare + * operation does not exist in the entry */ + if (op == OP_MOD) + return KRB5_KDB_UK_SERROR; + else /* OP_CMP */ + return KRB5_KDB_TRUNCATED_RECORD; + + + case LDAP_ALIAS_DEREF_PROBLEM: + /* Either the client does not have access rights to read the aliased + * object's name or dereferencing is not allowed */ +#ifdef LDAP_PROXY_AUTHZ_FAILURE + case LDAP_PROXY_AUTHZ_FAILURE: // Is this correct ? +#endif + case LDAP_INSUFFICIENT_ACCESS: + /* Caller does not have sufficient rights to perform the requested + * operation */ + return KRB5_KDB_UNAUTH; + + case LDAP_LOOP_DETECT: + /* Client discovered an alias or referral loop */ + return KRB5_KDB_DB_CORRUPT; + + default: + + if (LDAP_NAME_ERROR (err)) + return KRB5_KDB_NOENTRY; + + if (LDAP_SECURITY_ERROR (err)) + return KRB5_KDB_UNAUTH; + + if (LDAP_SERVICE_ERROR (err) || LDAP_API_ERROR (err) || LDAP_X_ERROR (err)) + return KRB5_KDB_ACCESS_ERROR; + + if (LDAP_UPDATE_ERROR(err)) + return KRB5_KDB_UK_SERROR; + + /* LDAP_OTHER */ + return KRB5_KDB_SERVER_INTERNAL_ERR; + } +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.h b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.h new file mode 100644 index 00000000..1f866925 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_err.h @@ -0,0 +1,13 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +#define OP_INIT 1 +#define OP_BIND 2 +#define OP_UNBIND 3 +#define OP_ADD 4 +#define OP_MOD 5 +#define OP_DEL 6 +#define OP_SEARCH 7 +#define OP_CMP 8 +#define OP_ABANDON 9 + + +int translate_ldap_error(int err, int op); diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c new file mode 100644 index 00000000..49d684ec --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.c @@ -0,0 +1,175 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_handle.c */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "ldap_main.h" + +/* + * Return ldap server handle from the pool. If the pool is exhausted return NULL. + * Do not lock the mutex, caller should lock it + */ + +static krb5_ldap_server_handle * +krb5_get_ldap_handle(krb5_ldap_context *ldap_context) +{ + krb5_ldap_server_handle *ldap_server_handle=NULL; + krb5_ldap_server_info *ldap_server_info=NULL; + int cnt=0; + + while (ldap_context->server_info_list[cnt] != NULL) { + ldap_server_info = ldap_context->server_info_list[cnt]; + if (ldap_server_info->server_status != OFF) { + if (ldap_server_info->ldap_server_handles != NULL) { + ldap_server_handle = ldap_server_info->ldap_server_handles; + ldap_server_info->ldap_server_handles = ldap_server_handle->next; + break; + } + } + ++cnt; + } + return ldap_server_handle; +} + +/* + * This is called in case krb5_get_ldap_handle returns NULL. + * Try getting a single connection (handle) and return the same by + * calling krb5_get_ldap_handle function. + * Do not lock the mutex here. The caller should lock it + */ + +static krb5_ldap_server_handle * +krb5_retry_get_ldap_handle(krb5_ldap_context *ldap_context, + krb5_error_code *st) +{ + krb5_ldap_server_handle *ldap_server_handle=NULL; + + if ((*st=krb5_ldap_db_single_init(ldap_context)) != 0) + return NULL; + + ldap_server_handle = krb5_get_ldap_handle(ldap_context); + return ldap_server_handle; +} + +/* + * Put back the ldap server handle to the front of the list of handles of the + * ldap server info structure. + * Do not lock the mutex here. The caller should lock it. + */ + +static krb5_error_code +krb5_put_ldap_handle(krb5_ldap_server_handle *ldap_server_handle) +{ + + if (ldap_server_handle == NULL) + return 0; + + ldap_server_handle->next = ldap_server_handle->server_info->ldap_server_handles; + ldap_server_handle->server_info->ldap_server_handles = ldap_server_handle; + return 0; +} + +/* + * Free up all the ldap server handles of the server info. + * This function is called when the ldap server returns LDAP_SERVER_DOWN. + */ + +static krb5_error_code +krb5_ldap_cleanup_handles(krb5_ldap_server_info *ldap_server_info) +{ + krb5_ldap_server_handle *ldap_server_handle = NULL; + + while (ldap_server_info->ldap_server_handles != NULL) { + ldap_server_handle = ldap_server_info->ldap_server_handles; + ldap_server_info->ldap_server_handles = ldap_server_handle->next; + /* ldap_unbind_s(ldap_server_handle); */ + free (ldap_server_handle); + ldap_server_handle = NULL; + } + return 0; +} + +/* + * wrapper function called from outside to get a handle. + */ + +krb5_error_code +krb5_ldap_request_handle_from_pool(krb5_ldap_context *ldap_context, + krb5_ldap_server_handle ** + ldap_server_handle) +{ + krb5_error_code st=0; + + *ldap_server_handle = NULL; + + HNDL_LOCK(ldap_context); + if (((*ldap_server_handle)=krb5_get_ldap_handle(ldap_context)) == NULL) + (*ldap_server_handle)=krb5_retry_get_ldap_handle(ldap_context, &st); + HNDL_UNLOCK(ldap_context); + return st; +} + +/* + * wrapper function wrapper called to get the next ldap server handle, when the current + * ldap server handle returns LDAP_SERVER_DOWN. + */ + +krb5_error_code +krb5_ldap_request_next_handle_from_pool(krb5_ldap_context *ldap_context, + krb5_ldap_server_handle ** + ldap_server_handle) +{ + krb5_error_code st=0; + + HNDL_LOCK(ldap_context); + (*ldap_server_handle)->server_info->server_status = OFF; + time(&(*ldap_server_handle)->server_info->downtime); + krb5_put_ldap_handle(*ldap_server_handle); + krb5_ldap_cleanup_handles((*ldap_server_handle)->server_info); + + if (((*ldap_server_handle)=krb5_get_ldap_handle(ldap_context)) == NULL) + (*ldap_server_handle)=krb5_retry_get_ldap_handle(ldap_context, &st); + HNDL_UNLOCK(ldap_context); + return st; +} + +/* + * wrapper function to call krb5_put_ldap_handle. + */ + +void +krb5_ldap_put_handle_to_pool(krb5_ldap_context *ldap_context, + krb5_ldap_server_handle *ldap_server_handle) +{ + if (ldap_server_handle != NULL) { + HNDL_LOCK(ldap_context); + krb5_put_ldap_handle(ldap_server_handle); + HNDL_UNLOCK(ldap_context); + } + return; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.h b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.h new file mode 100644 index 00000000..f56dead3 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_handle.h @@ -0,0 +1,43 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_handle.h */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#ifndef _LDAP_HANDLE_H_ +#define _LDAP_HANDLE_H_ + +krb5_error_code +krb5_ldap_request_handle_from_pool(krb5_ldap_context *, krb5_ldap_server_handle **); + +krb5_error_code +krb5_ldap_request_next_handle_from_pool(krb5_ldap_context *, krb5_ldap_server_handle **); + +void +krb5_ldap_put_handle_to_pool(krb5_ldap_context *, krb5_ldap_server_handle *); + +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c new file mode 100644 index 00000000..a810e633 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c @@ -0,0 +1,84 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "ldap_main.h" +#include "kdb_ldap.h" +#include "ldap_err.h" + +/* + * Read the kerberos container location from krb5.conf. + */ + +krb5_error_code +krb5_ldap_read_krbcontainer_dn(krb5_context context, char **container_dn) +{ + krb5_error_code st=0; + char *dn=NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + + *container_dn = NULL; + SETUP_CONTEXT(); + + /* read kerberos container location from [dbmodules] section of krb5.conf file */ + if (ldap_context->conf_section) { + if ((st=profile_get_string(context->profile, KDB_MODULE_SECTION, ldap_context->conf_section, + KRB5_CONF_LDAP_KERBEROS_CONTAINER_DN, NULL, + &dn)) != 0) { + k5_setmsg(context, st, _("Error reading kerberos container " + "location from krb5.conf")); + goto cleanup; + } + } + + /* read kerberos container location from [dbdefaults] section of krb5.conf file */ + if (dn == NULL) { + if ((st=profile_get_string(context->profile, KDB_MODULE_DEF_SECTION, + KRB5_CONF_LDAP_KERBEROS_CONTAINER_DN, NULL, + NULL, &dn)) != 0) { + k5_setmsg(context, st, _("Error reading kerberos container " + "location from krb5.conf")); + goto cleanup; + } + } + + if (dn == NULL) { + st = KRB5_KDB_SERVER_INTERNAL_ERR; + k5_setmsg(context, st, _("Kerberos container location not specified")); + goto cleanup; + } + + *container_dn = dn; + +cleanup: + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h new file mode 100644 index 00000000..549f8ce9 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h @@ -0,0 +1,47 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.h */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#ifndef _LDAP_KRBCONTAINER_H_ +#define _LDAP_KRBCONTAINER_H_ 1 + +#define MAX_KRB_CONTAINER_LEN 256 + +/* kerberos container structure */ + +krb5_error_code +krb5_ldap_read_krbcontainer_dn(krb5_context, char **); + +krb5_error_code +krb5_ldap_create_krbcontainer(krb5_context, const char *); + +krb5_error_code +krb5_ldap_delete_krbcontainer(krb5_context, const char *); + +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_main.h b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_main.h new file mode 100644 index 00000000..722dd869 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_main.h @@ -0,0 +1,38 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_main.h */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#ifndef LDAP_MAIN_H +#define LDAP_MAIN_H 1 + +#include "kdb_ldap.h" +#include "ldap_misc.h" +#include "ldap_handle.h" + +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c new file mode 100644 index 00000000..b3bf1ba6 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c @@ -0,0 +1,1701 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_misc.c */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +#include "kdb_ldap.h" +#include "ldap_misc.h" +#include "ldap_handle.h" +#include "ldap_err.h" +#include "ldap_principal.h" +#include "princ_xdr.h" +#include "ldap_pwd_policy.h" +#include +#include +#include + +#ifdef NEED_STRPTIME_PROTO +extern char *strptime(const char *, const char *, struct tm *); +#endif + +static void remove_overlapping_subtrees(char **listin, int *subtcount, + int sscope); + +/* Set an extended error message about being unable to read name. */ +static krb5_error_code +attr_read_error(krb5_context ctx, krb5_error_code code, const char *name) +{ + k5_setmsg(ctx, code, _("Error reading '%s' attribute: %s"), name, + error_message(code)); + return code; +} + +/* Get integer or string values from the config section, falling back to the + * default section, then to hard-coded values. */ +static krb5_error_code +prof_get_integer_def(krb5_context ctx, const char *conf_section, + const char *name, int dfl, krb5_ui_4 *out) +{ + krb5_error_code ret; + int val; + + ret = profile_get_integer(ctx->profile, KDB_MODULE_SECTION, conf_section, + name, 0, &val); + if (ret) + return attr_read_error(ctx, ret, name); + if (val != 0) { + *out = val; + return 0; + } + ret = profile_get_integer(ctx->profile, KDB_MODULE_DEF_SECTION, name, NULL, + dfl, &val); + if (ret) + return attr_read_error(ctx, ret, name); + *out = val; + return 0; +} + +/* Get integer or string values from the config section, falling back to the + * default section, then to hard-coded values. */ +static krb5_error_code +prof_get_boolean_def(krb5_context ctx, const char *conf_section, + const char *name, krb5_boolean dfl, krb5_boolean *out) +{ + krb5_error_code ret; + int val = 0; + + ret = profile_get_boolean(ctx->profile, KDB_MODULE_SECTION, conf_section, + name, -1, &val); + if (ret) + return attr_read_error(ctx, ret, name); + if (val != -1) { + *out = val; + return 0; + } + ret = profile_get_boolean(ctx->profile, KDB_MODULE_DEF_SECTION, name, NULL, + dfl, &val); + if (ret) + return attr_read_error(ctx, ret, name); + *out = val; + return 0; +} + +/* We don't have non-null defaults in any of our calls, so don't bother with + * the extra argument. */ +static krb5_error_code +prof_get_string_def(krb5_context ctx, const char *conf_section, + const char *name, char **out) +{ + krb5_error_code ret; + + ret = profile_get_string(ctx->profile, KDB_MODULE_SECTION, conf_section, + name, NULL, out); + if (ret) + return attr_read_error(ctx, ret, name); + if (*out != NULL) + return 0; + ret = profile_get_string(ctx->profile, KDB_MODULE_DEF_SECTION, name, NULL, + NULL, out); + if (ret) + return attr_read_error(ctx, ret, name); + return 0; +} + +static krb5_error_code +get_db_opt(const char *input, char **opt_out, char **val_out) +{ + krb5_error_code ret; + const char *pos; + char *opt, *val = NULL; + size_t len; + + *opt_out = *val_out = NULL; + pos = strchr(input, '='); + if (pos == NULL) { + opt = strdup(input); + if (opt == NULL) + return ENOMEM; + } else { + len = pos - input; + /* Ignore trailing spaces. */ + while (len > 0 && isspace((unsigned char)input[len - 1])) + len--; + opt = k5memdup0(input, len, &ret); + if (opt == NULL) + return ret; + + pos++; /* Move past '='. */ + while (isspace(*pos)) /* Ignore leading spaces. */ + pos++; + if (*pos != '\0') { + val = strdup(pos); + if (val == NULL) { + free(opt); + return ENOMEM; + } + } + } + *opt_out = opt; + *val_out = val; + return 0; +} + +static krb5_error_code +add_server_entry(krb5_context context, const char *name) +{ + krb5_ldap_context *ctx = context->dal_handle->db_context; + krb5_ldap_server_info **sp, **list, *server; + size_t count = 0; + + /* Allocate list space for the new entry and null terminator. */ + for (sp = ctx->server_info_list; sp != NULL && *sp != NULL; sp++) + count++; + list = realloc(ctx->server_info_list, (count + 2) * sizeof(*list)); + if (list == NULL) + return ENOMEM; + ctx->server_info_list = list; + + server = calloc(1, sizeof(krb5_ldap_server_info)); + if (server == NULL) + return ENOMEM; + server->server_status = NOTSET; + server->server_name = strdup(name); + if (server->server_name == NULL) { + free(server); + return ENOMEM; + } + list[count] = server; + list[count + 1] = NULL; + return 0; +} + +krb5_error_code +krb5_ldap_parse_db_params(krb5_context context, char **db_args) +{ + char *opt = NULL, *val = NULL; + krb5_error_code ret = 0; + krb5_ldap_context *ctx = context->dal_handle->db_context; + + if (db_args == NULL) + return 0; + for (; *db_args != NULL; db_args++) { + ret = get_db_opt(*db_args, &opt, &val); + if (ret) + goto cleanup; + + /* Check for options which don't require values. */ + if (!strcmp(opt, "temporary")) { + /* "temporary" is passed by kdb5_util load without -update, + * which we don't support. */ + ret = EINVAL; + k5_setmsg(context, ret, _("KDB module requires -update argument")); + goto cleanup; + } + + if (val == NULL) { + ret = EINVAL; + k5_setmsg(context, ret, _("'%s' value missing"), opt); + goto cleanup; + } + + /* Check for options which do require arguments. */ + if (!strcmp(opt, "binddn")) { + free(ctx->bind_dn); + ctx->bind_dn = strdup(val); + if (ctx->bind_dn == NULL) { + ret = ENOMEM; + goto cleanup; + } + } else if (!strcmp(opt, "nconns")) { + ctx->max_server_conns = atoi(val) ? atoi(val) : + DEFAULT_CONNS_PER_SERVER; + } else if (!strcmp(opt, "bindpwd")) { + free(ctx->bind_pwd); + ctx->bind_pwd = strdup(val); + if (ctx->bind_pwd == NULL) { + ret = ENOMEM; + goto cleanup; + } + } else if (!strcmp(opt, "sasl_mech")) { + free(ctx->sasl_mech); + ctx->sasl_mech = strdup(val); + if (ctx->sasl_mech == NULL) { + ret = ENOMEM; + goto cleanup; + } + } else if (!strcmp(opt, "sasl_authcid")) { + free(ctx->sasl_authcid); + ctx->sasl_authcid = strdup(val); + if (ctx->sasl_authcid == NULL) { + ret = ENOMEM; + goto cleanup; + } + } else if (!strcmp(opt, "sasl_authzid")) { + free(ctx->sasl_authzid); + ctx->sasl_authzid = strdup(val); + if (ctx->sasl_authzid == NULL) { + ret = ENOMEM; + goto cleanup; + } + } else if (!strcmp(opt, "sasl_realm")) { + free(ctx->sasl_realm); + ctx->sasl_realm = strdup(val); + if (ctx->sasl_realm == NULL) { + ret = ENOMEM; + goto cleanup; + } + } else if (!strcmp(opt, "host")) { + ret = add_server_entry(context, val); + if (ret) + goto cleanup; + } else if (!strcmp(opt, "debug")) { + ctx->ldap_debug = atoi(val); + } else { + ret = EINVAL; + k5_setmsg(context, ret, _("unknown option '%s'"), opt); + goto cleanup; + } + + free(opt); + free(val); + opt = val = NULL; + } + +cleanup: + free(opt); + free(val); + return ret; +} + +/* Pick kdc_var or kadmind_var depending on the server type. */ +static inline const char * +choose_var(int srv_type, const char *kdc_var, const char *kadmind_var) +{ + return (srv_type == KRB5_KDB_SRV_TYPE_KDC) ? kdc_var : kadmind_var; +} + +/* + * This function reads the parameters from the krb5.conf file. The + * parameters read here are DAL-LDAP specific attributes. Some of + * these are ldap_server .... + */ +krb5_error_code +krb5_ldap_read_server_params(krb5_context context, char *conf_section, + int srv_type) +{ + char *servers, *save_ptr, *item; + const char *delims = "\t\n\f\v\r ,", *name; + krb5_error_code ret = 0; + kdb5_dal_handle *dal_handle = context->dal_handle; + krb5_ldap_context *ldap_context = dal_handle->db_context; + + /* copy the conf_section into ldap_context for later use */ + if (conf_section != NULL) { + ldap_context->conf_section = strdup(conf_section); + if (ldap_context->conf_section == NULL) + return ENOMEM; + } + + /* This mutex is used in the LDAP connection pool. */ + if (k5_mutex_init(&(ldap_context->hndl_lock)) != 0) + return KRB5_KDB_SERVER_INTERNAL_ERR; + + /* Read the maximum number of LDAP connections per server. */ + if (ldap_context->max_server_conns == 0) { + ret = prof_get_integer_def(context, conf_section, + KRB5_CONF_LDAP_CONNS_PER_SERVER, + DEFAULT_CONNS_PER_SERVER, + &ldap_context->max_server_conns); + if (ret) + return ret; + } + + if (ldap_context->max_server_conns < 2) { + k5_setmsg(context, EINVAL, + _("Minimum connections required per server is 2")); + return EINVAL; + } + + /* Read the DN used to connect to the LDAP server. */ + if (ldap_context->bind_dn == NULL) { + name = choose_var(srv_type, KRB5_CONF_LDAP_KDC_DN, + KRB5_CONF_LDAP_KADMIND_DN); + ret = prof_get_string_def(context, conf_section, name, + &ldap_context->bind_dn); + if (ret) + return ret; + } + + /* Read the filename containing stashed DN passwords. */ + if (ldap_context->service_password_file == NULL) { + ret = prof_get_string_def(context, conf_section, + KRB5_CONF_LDAP_SERVICE_PASSWORD_FILE, + &ldap_context->service_password_file); + if (ret) + return ret; + } + + if (ldap_context->sasl_mech == NULL) { + name = choose_var(srv_type, KRB5_CONF_LDAP_KDC_SASL_MECH, + KRB5_CONF_LDAP_KADMIND_SASL_MECH); + ret = prof_get_string_def(context, conf_section, name, + &ldap_context->sasl_mech); + if (ret) + return ret; + } + + if (ldap_context->sasl_authcid == NULL) { + name = choose_var(srv_type, KRB5_CONF_LDAP_KDC_SASL_AUTHCID, + KRB5_CONF_LDAP_KADMIND_SASL_AUTHCID); + ret = prof_get_string_def(context, conf_section, name, + &ldap_context->sasl_authcid); + if (ret) + return ret; + } + + if (ldap_context->sasl_authzid == NULL) { + name = choose_var(srv_type, KRB5_CONF_LDAP_KDC_SASL_AUTHZID, + KRB5_CONF_LDAP_KADMIND_SASL_AUTHZID); + ret = prof_get_string_def(context, conf_section, name, + &ldap_context->sasl_authzid); + if (ret) + return ret; + } + + if (ldap_context->sasl_realm == NULL) { + name = choose_var(srv_type, KRB5_CONF_LDAP_KDC_SASL_REALM, + KRB5_CONF_LDAP_KADMIND_SASL_REALM); + ret = prof_get_string_def(context, conf_section, name, + &ldap_context->sasl_realm); + if (ret) + return ret; + } + + /* Read the LDAP server URL list. */ + if (ldap_context->server_info_list == NULL) { + ret = profile_get_string(context->profile, KDB_MODULE_SECTION, + conf_section, KRB5_CONF_LDAP_SERVERS, NULL, + &servers); + if (ret) + return attr_read_error(context, ret, KRB5_CONF_LDAP_SERVERS); + + if (servers == NULL) { + ret = add_server_entry(context, "ldapi://"); + if (ret) + return ret; + } else { + item = strtok_r(servers, delims, &save_ptr); + while (item != NULL) { + ret = add_server_entry(context, item); + if (ret) { + profile_release_string(servers); + return ret; + } + item = strtok_r(NULL, delims, &save_ptr); + } + profile_release_string(servers); + } + } + + ret = prof_get_boolean_def(context, conf_section, + KRB5_CONF_DISABLE_LAST_SUCCESS, FALSE, + &ldap_context->disable_last_success); + if (ret) + return ret; + + return prof_get_boolean_def(context, conf_section, + KRB5_CONF_DISABLE_LOCKOUT, FALSE, + &ldap_context->disable_lockout); +} + +void +krb5_ldap_free_server_context_params(krb5_ldap_context *ctx) +{ + int i; + krb5_ldap_server_info **list; + krb5_ldap_server_handle *h, *next; + + if (ctx == NULL) + return; + + list = ctx->server_info_list; + for (i = 0; list != NULL && list[i] != NULL; i++) { + free(list[i]->server_name); + for (h = list[i]->ldap_server_handles; h != NULL; h = next) { + next = h->next; + ldap_unbind_ext_s(h->ldap_handle, NULL, NULL); + free(h); + } + free(list[i]); + } + free(list); + ctx->server_info_list = NULL; + + free(ctx->sasl_mech); + free(ctx->sasl_authcid); + free(ctx->sasl_authzid); + free(ctx->sasl_realm); + free(ctx->conf_section); + free(ctx->bind_dn); + zapfreestr(ctx->bind_pwd); + free(ctx->service_password_file); + ctx->conf_section = ctx->bind_dn = ctx->bind_pwd = NULL; + ctx->service_password_file = NULL; +} + +void +krb5_ldap_free_server_params(krb5_ldap_context *ctx) +{ + if (ctx == NULL) + return; + krb5_ldap_free_server_context_params(ctx); + k5_mutex_destroy(&ctx->hndl_lock); + free(ctx); +} + +/* Return true if princ is in the default realm of ldap_context or is a + * cross-realm TGS principal for that realm. */ +krb5_boolean +is_principal_in_realm(krb5_ldap_context *ldap_context, + krb5_const_principal princ) +{ + const char *realm = ldap_context->lrparams->realm_name; + + if (princ->length == 2 && + data_eq_string(princ->data[0], "krbtgt") && + data_eq_string(princ->data[1], realm)) + return TRUE; + return data_eq_string(princ->realm, realm); +} + +/* + * Deduce the subtree information from the context. A realm can have + * multiple subtrees. + * 1. the Realm container + * 2. the actual subtrees associated with the Realm + * + * However, there are some conditions to be considered to deduce the + * actual subtree/s associated with the realm. The conditions are as + * follows: + * 1. If the subtree information of the Realm is [Root] or NULL (that + * is internal a [Root]) then the realm has only one subtree + * i.e [Root], i.e. whole of the tree. + * 2. If the subtree information of the Realm is missing/absent, then the + * realm has only one, i.e., the Realm container. NOTE: In all cases + * Realm container SHOULD be the one among the subtrees or the only + * one subtree. + * 3. The subtree information of the realm is overlapping the realm + * container of the realm, then the realm has only one subtree and + * it is the subtree information associated with the realm. + */ +krb5_error_code +krb5_get_subtree_info(krb5_ldap_context *ldap_context, char ***subtreearr, + unsigned int *ntree) +{ + krb5_error_code ret; + int subtreecount, count = 0, search_scope; + char **subtree, *realm_cont_dn, *containerref; + char **subtarr = NULL; + + containerref = ldap_context->lrparams->containerref; + subtree = ldap_context->lrparams->subtree; + realm_cont_dn = ldap_context->lrparams->realmdn; + subtreecount = ldap_context->lrparams->subtreecount; + search_scope = ldap_context->lrparams->search_scope; + + /* Leave space for realm DN, containerref, and null terminator. */ + subtarr = k5calloc(subtreecount + 3, sizeof(char *), &ret); + if (subtarr == NULL) + goto cleanup; + + /* Get the complete subtree list. */ + while (count < subtreecount && subtree[count] != NULL) { + subtarr[count] = strdup(subtree[count]); + if (subtarr[count++] == NULL) { + ret = ENOMEM; + goto cleanup; + } + } + + subtarr[count] = strdup(realm_cont_dn); + if (subtarr[count++] == NULL) { + ret = ENOMEM; + goto cleanup; + } + + if (containerref != NULL) { + subtarr[count] = strdup(containerref); + if (subtarr[count++] == NULL) { + ret = ENOMEM; + goto cleanup; + } + } + + remove_overlapping_subtrees(subtarr, &count, search_scope); + *ntree = count; + *subtreearr = subtarr; + subtarr = NULL; + count = 0; + +cleanup: + while (count > 0) + free(subtarr[--count]); + free(subtarr); + return ret; +} + +/* Reallocate tl and return a pointer to the new space, or NULL on failure. */ +static unsigned char * +expand_tl_data(krb5_tl_data *tl, uint16_t len) +{ + unsigned char *newptr; + + if (len > UINT16_MAX - tl->tl_data_length) + return NULL; + newptr = realloc(tl->tl_data_contents, tl->tl_data_length + len); + if (newptr == NULL) + return NULL; + tl->tl_data_contents = newptr; + tl->tl_data_length += len; + return tl->tl_data_contents + tl->tl_data_length - len; +} + +/* Append a one-byte type, a two-byte length, and a value to a KDB_TL_USER_INFO + * tl_data item. The length is inferred from type and value. */ +krb5_error_code +store_tl_data(krb5_tl_data *tl, int type, void *value) +{ + unsigned char *ptr; + int ival; + char *str; + size_t len; + + tl->tl_data_type = KDB_TL_USER_INFO; + switch (type) { + case KDB_TL_PRINCCOUNT: + case KDB_TL_PRINCTYPE: + case KDB_TL_MASK: + ival = *(int *)value; + if (ival > UINT16_MAX) + return EINVAL; + ptr = expand_tl_data(tl, 5); + if (ptr == NULL) + return ENOMEM; + *ptr = type; + store_16_be(2, ptr + 1); + store_16_be(ival, ptr + 3); + break; + + case KDB_TL_USERDN: + case KDB_TL_LINKDN: + str = value; + len = strlen(str); + if (len > UINT16_MAX - 3) + return ENOMEM; + ptr = expand_tl_data(tl, 3 + len); + if (ptr == NULL) + return ENOMEM; + *ptr = type; + store_16_be(len, ptr + 1); + memcpy(ptr + 3, str, len); + break; + + default: + return EINVAL; + } + return 0; +} + +/* Scan tl for a value of the given type and return it in allocated memory. + * For KDB_TL_LINKDN, return a list of all values found. */ +static krb5_error_code +decode_tl_data(krb5_tl_data *tl, int type, void **data_out) +{ + krb5_error_code ret; + const unsigned char *ptr, *end; + uint16_t len; + size_t linkcount = 0, i; + char **dnlist = NULL, **newlist; + int *intptr; + + *data_out = NULL; + + /* Find the first matching subfield or return ENOENT. For KDB_TL_LINKDN, + * keep iterating after finding a match as it may be repeated. */ + ptr = tl->tl_data_contents; + end = ptr + tl->tl_data_length; + for (;;) { + if (end - ptr < 3) + break; + len = load_16_be(ptr + 1); + if (len > (end - ptr) - 3) + break; + if (*ptr != type) { + ptr += 3 + len; + continue; + } + ptr += 3; + + switch (type) { + case KDB_TL_PRINCCOUNT: + case KDB_TL_PRINCTYPE: + case KDB_TL_MASK: + if (len != 2) + return EINVAL; + intptr = malloc(sizeof(int)); + if (intptr == NULL) + return ENOMEM; + *intptr = load_16_be(ptr); + *data_out = intptr; + return 0; + + case KDB_TL_USERDN: + *data_out = k5memdup0(ptr, len, &ret); + return ret; + + case KDB_TL_LINKDN: + newlist = realloc(dnlist, (linkcount + 2) * sizeof(char *)); + if (newlist == NULL) + goto oom; + dnlist = newlist; + dnlist[linkcount] = k5memdup0(ptr, len, &ret); + if (dnlist[linkcount] == NULL) + goto oom; + dnlist[linkcount + 1] = NULL; + linkcount++; + break; + } + + ptr += len; + } + + if (type != KDB_TL_LINKDN || dnlist == NULL) + return ENOENT; + *data_out = dnlist; + return 0; + +oom: + for (i = 0; i < linkcount; i++) + free(dnlist[i]); + free(dnlist); + return ENOMEM; +} + +/* + * wrapper routines for decode_tl_data + */ +static krb5_error_code +get_int_from_tl_data(krb5_context context, krb5_db_entry *entry, int type, + int *intval) +{ + krb5_error_code ret; + krb5_tl_data tl_data; + void *ptr; + int *intptr; + + *intval = 0; + + tl_data.tl_data_type = KDB_TL_USER_INFO; + ret = krb5_dbe_lookup_tl_data(context, entry, &tl_data); + if (ret || tl_data.tl_data_length == 0) + return ret; + + if (decode_tl_data(&tl_data, type, &ptr) == 0) { + intptr = ptr; + *intval = *intptr; + free(intptr); + } + + return 0; +} + +/* + * Get the mask representing the attributes set on the directory + * object (user, policy ...). + */ +krb5_error_code +krb5_get_attributes_mask(krb5_context context, krb5_db_entry *entry, + int *mask) +{ + return get_int_from_tl_data(context, entry, KDB_TL_MASK, mask); +} + +krb5_error_code +krb5_get_princ_type(krb5_context context, krb5_db_entry *entry, int *ptype) +{ + return get_int_from_tl_data(context, entry, KDB_TL_PRINCTYPE, ptype); +} + +krb5_error_code +krb5_get_princ_count(krb5_context context, krb5_db_entry *entry, int *pcount) +{ + return get_int_from_tl_data(context, entry, KDB_TL_PRINCCOUNT, pcount); +} + +krb5_error_code +krb5_get_linkdn(krb5_context context, krb5_db_entry *entry, char ***link_dn) +{ + krb5_error_code ret; + krb5_tl_data tl_data; + void *ptr; + + *link_dn = NULL; + tl_data.tl_data_type = KDB_TL_USER_INFO; + ret = krb5_dbe_lookup_tl_data(context, entry, &tl_data); + if (ret || tl_data.tl_data_length == 0) + return ret; + + if (decode_tl_data(&tl_data, KDB_TL_LINKDN, &ptr) == 0) + *link_dn = ptr; + + return 0; +} + +static krb5_error_code +get_str_from_tl_data(krb5_context context, krb5_db_entry *entry, int type, + char **strval) +{ + krb5_error_code ret; + krb5_tl_data tl_data; + void *ptr; + + if (type != KDB_TL_USERDN) + return EINVAL; + + tl_data.tl_data_type = KDB_TL_USER_INFO; + ret = krb5_dbe_lookup_tl_data(context, entry, &tl_data); + if (ret || tl_data.tl_data_length == 0) + return ret; + + if (decode_tl_data(&tl_data, type, &ptr) == 0) + *strval = ptr; + + return 0; +} + +/* + * Replace the relative DN component of dn with newrdn. + */ +krb5_error_code +replace_rdn(krb5_context context, const char *dn, const char *newrdn, + char **newdn_out) +{ + krb5_error_code ret; + LDAPDN ldn = NULL; + LDAPRDN lrdn = NULL; + char *next; + + *newdn_out = NULL; + + ret = ldap_str2dn(dn, &ldn, LDAP_DN_FORMAT_LDAPV3); + if (ret != LDAP_SUCCESS || ldn[0] == NULL) { + ret = EINVAL; + goto cleanup; + } + + ret = ldap_str2rdn(newrdn, &lrdn, &next, LDAP_DN_FORMAT_LDAPV3); + if (ret != LDAP_SUCCESS) { + ret = EINVAL; + goto cleanup; + } + + ldap_rdnfree(ldn[0]); + ldn[0] = lrdn; + lrdn = NULL; + + ret = ldap_dn2str(ldn, newdn_out, LDAP_DN_FORMAT_LDAPV3); + if (ret != LDAP_SUCCESS) + ret = KRB5_KDB_SERVER_INTERNAL_ERR; + +cleanup: + if (ldn != NULL) + ldap_dnfree(ldn); + if (lrdn != NULL) + ldap_rdnfree(lrdn); + return ret; +} + +krb5_error_code +krb5_get_userdn(krb5_context context, krb5_db_entry *entry, char **userdn) +{ + *userdn = NULL; + return get_str_from_tl_data(context, entry, KDB_TL_USERDN, userdn); +} + +/* + * If attribute or attrvalues is NULL, just check for the existence of dn. + * Otherwise, read values for attribute from dn; then set the bit 1<mod_type = strdup(attribute); + if (mod->mod_type == NULL) + return ENOMEM; + mod->mod_op = op; + + mod->mod_values = NULL; + if (values == NULL) + return 0; + + for (count = 0; values[count] != NULL; count++); + mod->mod_values = calloc(count + 1, sizeof(char *)); + if (mod->mod_values == NULL) + return ENOMEM; + + for (i = 0; i < count; i++) { + mod->mod_values[i] = strdup(values[i]); + if (mod->mod_values[i] == NULL) + return ENOMEM; + } + mod->mod_values[i] = NULL; + return 0; +} + +krb5_error_code +krb5_add_ber_mem_ldap_mod(LDAPMod ***list, char *attribute, int op, + struct berval **ber_values) +{ + krb5_error_code ret; + LDAPMod *mod; + size_t count, i; + + ret = alloc_mod(list, &mod); + if (ret) + return ret; + + mod->mod_type = strdup(attribute); + if (mod->mod_type == NULL) + return ENOMEM; + mod->mod_op = op; + + for (count = 0; ber_values[count] != NULL; count++); + mod->mod_bvalues = calloc(count + 1, sizeof(struct berval *)); + if (mod->mod_bvalues == NULL) + return ENOMEM; + + for (i = 0; i < count; i++) { + mod->mod_bvalues[i] = calloc(1, sizeof(struct berval)); + if (mod->mod_bvalues[i] == NULL) + return ENOMEM; + + mod->mod_bvalues[i]->bv_len = ber_values[i]->bv_len; + mod->mod_bvalues[i]->bv_val = k5memdup(ber_values[i]->bv_val, + ber_values[i]->bv_len, &ret); + if (mod->mod_bvalues[i]->bv_val == NULL) + return ret; + } + mod->mod_bvalues[i] = NULL; + return 0; +} + +static inline char * +format_d(int val) +{ + char tmpbuf[3 * sizeof(val) + 2]; + + snprintf(tmpbuf, sizeof(tmpbuf), "%d", val); + return strdup(tmpbuf); +} + +krb5_error_code +krb5_add_int_mem_ldap_mod(LDAPMod ***list, char *attribute, int op, int value) +{ + krb5_error_code ret; + LDAPMod *mod; + + ret = alloc_mod(list, &mod); + if (ret) + return ret; + + mod->mod_type = strdup(attribute); + if (mod->mod_type == NULL) + return ENOMEM; + + mod->mod_op = op; + mod->mod_values = calloc(2, sizeof(char *)); + if (mod->mod_values == NULL) + return ENOMEM; + mod->mod_values[0] = format_d(value); + if (mod->mod_values[0] == NULL) + return ENOMEM; + return 0; +} + +krb5_error_code +krb5_ldap_modify_ext(krb5_context context, LDAP *ld, const char *dn, + LDAPMod **mods, int op) +{ + int ret; + + ret = ldap_modify_ext_s(ld, dn, mods, NULL, NULL); + return (ret == LDAP_SUCCESS) ? 0 : set_ldap_error(context, ret, op); +} + +krb5_error_code +krb5_ldap_lock(krb5_context kcontext, int mode) +{ + krb5_error_code status = KRB5_PLUGIN_OP_NOTSUPP; + + k5_setmsg(kcontext, status, "LDAP %s", error_message(status)); + return status; +} + +krb5_error_code +krb5_ldap_unlock(krb5_context kcontext) +{ + krb5_error_code status = KRB5_PLUGIN_OP_NOTSUPP; + + k5_setmsg(kcontext, status, "LDAP %s", error_message(status)); + return status; +} + + +/* + * Get the number of times an object has been referred to in a realm. This is + * needed to find out if deleting the attribute will cause dangling links. + * + * An LDAP handle may be optionally specified to prevent race condition - there + * are a limited number of LDAP handles. + */ +krb5_error_code +krb5_ldap_get_reference_count(krb5_context context, char *dn, char *refattr, + int *count, LDAP *ld) +{ + int n, st, tempst, gothandle = 0; + unsigned int i, ntrees = 0; + char *refcntattr[2]; + char *filter = NULL, *corrected = NULL, **subtree = NULL; + kdb5_dal_handle *dal_handle = NULL; + krb5_ldap_context *ldap_context = NULL; + krb5_ldap_server_handle *ldap_server_handle = NULL; + LDAPMessage *result = NULL; + + if (dn == NULL || refattr == NULL) { + st = EINVAL; + goto cleanup; + } + + SETUP_CONTEXT(); + if (ld == NULL) { + GET_HANDLE(); + gothandle = 1; + } + + refcntattr[0] = refattr; + refcntattr[1] = NULL; + + corrected = ldap_filter_correct(dn); + if (corrected == NULL) { + st = ENOMEM; + goto cleanup; + } + + if (asprintf(&filter, "%s=%s", refattr, corrected) < 0) { + filter = NULL; + st = ENOMEM; + goto cleanup; + } + + st = krb5_get_subtree_info(ldap_context, &subtree, &ntrees); + if (st) + goto cleanup; + + for (i = 0, *count = 0; i < ntrees; i++) { + LDAP_SEARCH(subtree[i], LDAP_SCOPE_SUBTREE, filter, refcntattr); + n = ldap_count_entries(ld, result); + if (n == -1) { + int ret, errcode = 0; + ret = ldap_parse_result(ld, result, &errcode, NULL, NULL, NULL, + NULL, 0); + if (ret != LDAP_SUCCESS) + errcode = ret; + st = translate_ldap_error(errcode, OP_SEARCH); + goto cleanup; + } + + ldap_msgfree(result); + result = NULL; + + *count += n; + } + +cleanup: + free(filter); + ldap_msgfree(result); + for (i = 0; i < ntrees; i++) + free(subtree[i]); + free(subtree); + free(corrected); + if (gothandle) + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + +/* Extract a name from policy_dn, which must be directly under the realm + * container. */ +krb5_error_code +krb5_ldap_policydn_to_name(krb5_context context, const char *policy_dn, + char **name_out) +{ + size_t len1, len2, plen; + krb5_error_code ret; + kdb5_dal_handle *dal_handle; + krb5_ldap_context *ldap_context; + const char *realmdn; + char *rdn; + LDAPDN dn; + + *name_out = NULL; + SETUP_CONTEXT(); + + realmdn = ldap_context->lrparams->realmdn; + if (realmdn == NULL) + return EINVAL; + + /* policyn_dn should be "cn=,". */ + len1 = strlen(realmdn); + len2 = strlen(policy_dn); + if (len1 == 0 || len2 == 0 || len1 + 1 >= len2) + return EINVAL; + plen = len2 - len1 - 1; + if (policy_dn[plen] != ',' || strcmp(realmdn, policy_dn + plen + 1) != 0) + return EINVAL; + + rdn = k5memdup0(policy_dn, plen, &ret); + if (rdn == NULL) + return ret; + ret = ldap_str2dn(rdn, &dn, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PEDANTIC); + free(rdn); + if (ret) + return EINVAL; + if (dn[0] == NULL || dn[1] != NULL || dn[0][0]->la_attr.bv_len != 2 || + strncasecmp(dn[0][0]->la_attr.bv_val, "cn", 2) != 0) { + ret = EINVAL; + } else { + *name_out = k5memdup0(dn[0][0]->la_value.bv_val, + dn[0][0]->la_value.bv_len, &ret); + } + ldap_dnfree(dn); + return ret; +} + +/* Compute the policy DN for the given policy name. */ +krb5_error_code +krb5_ldap_name_to_policydn(krb5_context context, char *name, char **policy_dn) +{ + int st; + char *corrected; + kdb5_dal_handle *dal_handle; + krb5_ldap_context *ldap_context; + + *policy_dn = NULL; + + /* Used for removing policy reference from an object */ + if (name[0] == '\0') { + *policy_dn = strdup(""); + return (*policy_dn == NULL) ? ENOMEM : 0; + } + + SETUP_CONTEXT(); + + if (ldap_context->lrparams->realmdn == NULL) + return EINVAL; + + corrected = ldap_filter_correct(name); + if (corrected == NULL) + return ENOMEM; + + st = asprintf(policy_dn, "cn=%s,%s", corrected, + ldap_context->lrparams->realmdn); + free(corrected); + if (st == -1) { + *policy_dn = NULL; + return ENOMEM; + } + return 0; +} + +/* Return true if dn1 is a subtree of dn2. */ +static inline krb5_boolean +is_subtree(const char *dn1, size_t len1, const char *dn2, size_t len2) +{ + return len1 > len2 && dn1[len1 - len2 - 1] == ',' && + strcasecmp(dn1 + (len1 - len2), dn2) == 0; +} + +/* Remove overlapping and repeated subtree entries from the list of subtrees. + * If sscope is not 2 (sub), only remove repeated entries. */ +static void +remove_overlapping_subtrees(char **list, int *subtcount, int sscope) +{ + size_t ilen, jlen; + int i, j; + int count = *subtcount; + + for (i = 0; i < count && list[i] != NULL; i++) { + ilen = strlen(list[i]); + for (j = i + 1; j < count && list[j] != NULL; j++) { + jlen = strlen(list[j]); + /* Remove list[j] if it is identical to list[i] or a subtree of it. + * Remove list[i] if it is a subtree of list[j]. */ + if ((ilen == jlen && strcasecmp(list[j], list[i]) == 0) || + (sscope == 2 && is_subtree(list[j], jlen, list[i], ilen))) { + free(list[j]); + list[j--] = list[count - 1]; + list[--count] = NULL; + } else if (sscope == 2 && + is_subtree(list[i], ilen, list[j], jlen)) { + free(list[i]); + list[i--] = list[count - 1]; + list[--count] = NULL; + break; + } + } + } + *subtcount = count; +} + +static void +free_princ_ent_contents(osa_princ_ent_t princ_ent) +{ + unsigned int i; + + for (i = 0; i < princ_ent->old_key_len; i++) { + k5_free_key_data(princ_ent->old_keys[i].n_key_data, + princ_ent->old_keys[i].key_data); + princ_ent->old_keys[i].n_key_data = 0; + princ_ent->old_keys[i].key_data = NULL; + } + free(princ_ent->old_keys); + princ_ent->old_keys = NULL; + princ_ent->old_key_len = 0; +} + +/* Get any auth indicator values from LDAP and update the "require_auth" + * string. */ +static krb5_error_code +get_ldap_auth_ind(krb5_context context, LDAP *ld, LDAPMessage *ldap_ent, + krb5_db_entry *entry, unsigned int *mask) +{ + krb5_error_code ret; + int i; + char **auth_inds = NULL, *indstr; + struct k5buf buf = EMPTY_K5BUF; + + auth_inds = ldap_get_values(ld, ldap_ent, "krbPrincipalAuthInd"); + if (auth_inds == NULL) + return 0; + + k5_buf_init_dynamic(&buf); + + /* Make a space-separated list of indicators. */ + for (i = 0; auth_inds[i] != NULL; i++) { + k5_buf_add(&buf, auth_inds[i]); + if (auth_inds[i + 1] != NULL) + k5_buf_add(&buf, " "); + } + + indstr = k5_buf_cstring(&buf); + if (indstr == NULL) { + ret = ENOMEM; + goto cleanup; + } + + ret = krb5_dbe_set_string(context, entry, KRB5_KDB_SK_REQUIRE_AUTH, + indstr); + if (!ret) + *mask |= KDB_AUTH_IND_ATTR; + +cleanup: + k5_buf_free(&buf); + ldap_value_free(auth_inds); + return ret; +} + +/* + * Fill out a krb5_db_entry princ entry struct given a LDAP message containing + * the results of a principal search of the directory. + */ +krb5_error_code +populate_krb5_db_entry(krb5_context context, krb5_ldap_context *ldap_context, + LDAP *ld, LDAPMessage *ent, krb5_const_principal princ, + krb5_db_entry *entry) +{ + krb5_error_code ret; + unsigned int mask = 0; + int val, i, pcount, objtype; + krb5_boolean attr_present; + krb5_kvno mkvno = 0; + krb5_timestamp lastpwdchange, unlock_time; + char *policydn = NULL, *pwdpolicydn = NULL, *polname = NULL, *user = NULL; + char *tktpolname = NULL, *dn = NULL, **link_references = NULL; + char **pnvalues = NULL, **ocvalues = NULL, **a2d2 = NULL; + struct berval **ber_key_data = NULL, **ber_tl_data = NULL; + krb5_tl_data userinfo_tl_data = { NULL }, **endp, *tl; + osa_princ_ent_rec princ_ent; + char *is_login_disabled = NULL; + + memset(&princ_ent, 0, sizeof(princ_ent)); + + ret = krb5_copy_principal(context, princ, &entry->princ); + if (ret) + goto cleanup; + + /* get the associated directory user information */ + pnvalues = ldap_get_values(ld, ent, "krbprincipalname"); + if (pnvalues != NULL) { + ret = krb5_unparse_name(context, princ, &user); + if (ret) + goto cleanup; + + pcount = 0; + for (i = 0; pnvalues[i] != NULL; i++) { + if (strcasecmp(pnvalues[i], user) == 0) { + pcount = ldap_count_values(pnvalues); + break; + } + } + + dn = ldap_get_dn(ld, ent); + if (dn == NULL) { + ldap_get_option(ld, LDAP_OPT_RESULT_CODE, &ret); + ret = set_ldap_error(context, ret, 0); + goto cleanup; + } + + ocvalues = ldap_get_values(ld, ent, "objectclass"); + if (ocvalues != NULL) { + for (i = 0; ocvalues[i] != NULL; i++) { + if (strcasecmp(ocvalues[i], "krbprincipal") == 0) { + objtype = KDB_STANDALONE_PRINCIPAL_OBJECT; + ret = store_tl_data(&userinfo_tl_data, KDB_TL_PRINCTYPE, + &objtype); + if (ret) + goto cleanup; + break; + } + } + } + + /* Add principalcount, DN and principaltype user information to + * tl_data */ + ret = store_tl_data(&userinfo_tl_data, KDB_TL_PRINCCOUNT, &pcount); + if (ret) + goto cleanup; + ret = store_tl_data(&userinfo_tl_data, KDB_TL_USERDN, dn); + if (ret) + goto cleanup; + } + + ret = get_time(ld, ent, "krbLastSuccessfulAuth", &entry->last_success, + &attr_present); + if (ret) + goto cleanup; + if (attr_present) + mask |= KDB_LAST_SUCCESS_ATTR; + + ret = get_time(ld, ent, "krbLastFailedAuth", &entry->last_failed, + &attr_present); + if (ret) + goto cleanup; + if (attr_present) + mask |= KDB_LAST_FAILED_ATTR; + + if (krb5_ldap_get_value(ld, ent, "krbLoginFailedCount", &val) == 0) { + entry->fail_auth_count = val; + mask |= KDB_FAIL_AUTH_COUNT_ATTR; + } + if (krb5_ldap_get_value(ld, ent, "krbmaxticketlife", &val) == 0) { + entry->max_life = val; + mask |= KDB_MAX_LIFE_ATTR; + } + if (krb5_ldap_get_value(ld, ent, "krbmaxrenewableage", &val) == 0) { + entry->max_renewable_life = val; + mask |= KDB_MAX_RLIFE_ATTR; + } + if (krb5_ldap_get_value(ld, ent, "krbticketflags", &val) == 0) { + entry->attributes = val; + mask |= KDB_TKT_FLAGS_ATTR; + } + ret = get_time(ld, ent, "krbprincipalexpiration", &entry->expiration, + &attr_present); + if (ret) + goto cleanup; + if (attr_present) + mask |= KDB_PRINC_EXPIRE_TIME_ATTR; + + ret = get_time(ld, ent, "krbpasswordexpiration", &entry->pw_expiration, + &attr_present); + if (ret) + goto cleanup; + if (attr_present) + mask |= KDB_PWD_EXPIRE_TIME_ATTR; + + ret = krb5_ldap_get_string(ld, ent, "krbticketpolicyreference", &policydn, + &attr_present); + if (ret) + goto cleanup; + if (attr_present) { + mask |= KDB_POL_REF_ATTR; + /* Ensure that the policy is inside the realm container. */ + ret = krb5_ldap_policydn_to_name(context, policydn, &tktpolname); + if (ret) + goto cleanup; + } + + ret = krb5_ldap_get_string(ld, ent, "krbpwdpolicyreference", &pwdpolicydn, + &attr_present); + if (ret) + goto cleanup; + if (attr_present) { + mask |= KDB_PWD_POL_REF_ATTR; + + /* Ensure that the policy is inside the realm container. */ + ret = krb5_ldap_policydn_to_name(context, pwdpolicydn, &polname); + if (ret) + goto cleanup; + princ_ent.policy = polname; + princ_ent.aux_attributes |= KADM5_POLICY; + } + + ber_key_data = ldap_get_values_len(ld, ent, "krbpwdhistory"); + if (ber_key_data != NULL) { + mask |= KDB_PWD_HISTORY_ATTR; + ret = krb5_decode_histkey(context, ber_key_data, &princ_ent); + if (ret) + goto cleanup; + ldap_value_free_len(ber_key_data); + } + + if (princ_ent.aux_attributes) { + ret = krb5_update_tl_kadm_data(context, entry, &princ_ent); + if (ret) + goto cleanup; + } + + ber_key_data = ldap_get_values_len(ld, ent, "krbprincipalkey"); + if (ber_key_data != NULL) { + mask |= KDB_SECRET_KEY_ATTR; + ret = krb5_decode_krbsecretkey(context, entry, ber_key_data, &mkvno); + if (ret) + goto cleanup; + if (mkvno != 0) { + ret = krb5_dbe_update_mkvno(context, entry, mkvno); + if (ret) + goto cleanup; + } + } + + ret = get_time(ld, ent, "krbLastPwdChange", &lastpwdchange, &attr_present); + if (ret) + goto cleanup; + if (attr_present) { + ret = krb5_dbe_update_last_pwd_change(context, entry, lastpwdchange); + if (ret) + goto cleanup; + mask |= KDB_LAST_PWD_CHANGE_ATTR; + } + + ret = get_time(ld, ent, "krbLastAdminUnlock", &unlock_time, &attr_present); + if (ret) + goto cleanup; + if (attr_present) { + ret = krb5_dbe_update_last_admin_unlock(context, entry, unlock_time); + if (ret) + goto cleanup; + mask |= KDB_LAST_ADMIN_UNLOCK_ATTR; + } + + a2d2 = ldap_get_values(ld, ent, "krbAllowedToDelegateTo"); + if (a2d2 != NULL) { + for (endp = &entry->tl_data; *endp; endp = &(*endp)->tl_data_next); + for (i = 0; a2d2[i] != NULL; i++) { + tl = k5alloc(sizeof(*tl), &ret); + if (tl == NULL) + goto cleanup; + tl->tl_data_type = KRB5_TL_CONSTRAINED_DELEGATION_ACL; + tl->tl_data_length = strlen(a2d2[i]); + tl->tl_data_contents = (unsigned char *)strdup(a2d2[i]); + if (tl->tl_data_contents == NULL) { + ret = ENOMEM; + free(tl); + goto cleanup; + } + tl->tl_data_next = NULL; + *endp = tl; + endp = &tl->tl_data_next; + } + } + + link_references = ldap_get_values(ld, ent, "krbobjectreferences"); + if (link_references != NULL) { + for (i = 0; link_references[i] != NULL; i++) { + ret = store_tl_data(&userinfo_tl_data, KDB_TL_LINKDN, + link_references[i]); + if (ret) + goto cleanup; + } + } + + ber_tl_data = ldap_get_values_len(ld, ent, "krbExtraData"); + if (ber_tl_data != NULL) { + for (i = 0; ber_tl_data[i] != NULL; i++) { + ret = berval2tl_data(ber_tl_data[i], &tl); + if (ret) + goto cleanup; + ret = krb5_dbe_update_tl_data(context, entry, tl); + free(tl->tl_data_contents); + free(tl); + if (ret) + goto cleanup; + } + mask |= KDB_EXTRA_DATA_ATTR; + } + + /* Auth indicators from krbPrincipalAuthInd will replace those from + * krbExtraData. */ + ret = get_ldap_auth_ind(context, ld, ent, entry, &mask); + if (ret) + goto cleanup; + + /* Update the mask of attributes present on the directory object to the + * tl_data. */ + ret = store_tl_data(&userinfo_tl_data, KDB_TL_MASK, &mask); + if (ret) + goto cleanup; + ret = krb5_dbe_update_tl_data(context, entry, &userinfo_tl_data); + if (ret) + goto cleanup; + + /* + * 389ds and other Netscape directory server derivatives support an + * attribute "nsAccountLock" which functions similarly to eDirectory's + * "loginDisabled". When the user's account object is also a + * krbPrincipalAux object, the kdb entry should be treated as if + * DISALLOW_ALL_TIX has been set. + */ + ret = krb5_ldap_get_string(ld, ent, "nsAccountLock", &is_login_disabled, + &attr_present); + if (ret) + goto cleanup; + if (attr_present == TRUE) { + if (strcasecmp(is_login_disabled, "TRUE") == 0) + entry->attributes |= KRB5_KDB_DISALLOW_ALL_TIX; + free(is_login_disabled); + } + + ret = krb5_read_tkt_policy(context, ldap_context, entry, tktpolname); + if (ret) + goto cleanup; + + /* For compatibility with DB2 principals. */ + entry->len = KRB5_KDB_V1_BASE_LENGTH; + +cleanup: + ldap_memfree(dn); + ldap_value_free_len(ber_key_data); + ldap_value_free_len(ber_tl_data); + ldap_value_free(pnvalues); + ldap_value_free(ocvalues); + ldap_value_free(link_references); + ldap_value_free(a2d2); + free(userinfo_tl_data.tl_data_contents); + free(pwdpolicydn); + free(polname); + free(tktpolname); + free(policydn); + krb5_free_unparsed_name(context, user); + free_princ_ent_contents(&princ_ent); + return ret; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h new file mode 100644 index 00000000..9ea5dd5c --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.h @@ -0,0 +1,125 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_misc.h */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#ifndef _HAVE_LDAP_MISC_H +#define _HAVE_LDAP_MISC_H 1 + +/* misc functions */ + +krb5_boolean +is_principal_in_realm(krb5_ldap_context *, krb5_const_principal); + +krb5_error_code +checkattributevalue(LDAP *, char *, char *, char **, int *); + +krb5_error_code +krb5_get_attributes_mask(krb5_context, krb5_db_entry *, int *); + +krb5_error_code +krb5_get_princ_type(krb5_context, krb5_db_entry *, int *); + +krb5_error_code +krb5_get_princ_count(krb5_context, krb5_db_entry *, int *); + +krb5_error_code +krb5_get_linkdn(krb5_context, krb5_db_entry *, char ***); + +krb5_error_code +krb5_get_userdn(krb5_context, krb5_db_entry *, char **); + +krb5_error_code +replace_rdn(krb5_context context, const char *dn, const char *newrdn, + char **newdn); + +krb5_error_code +store_tl_data(krb5_tl_data *, int, void *); + +krb5_error_code +krb5_get_subtree_info(krb5_ldap_context *, char ***, unsigned int *); + +krb5_error_code +krb5_ldap_parse_db_params(krb5_context, char **); + +krb5_error_code +krb5_ldap_read_server_params(krb5_context , char *, int); + +void +krb5_ldap_free_server_params(krb5_ldap_context *); + +krb5_error_code +krb5_ldap_list(krb5_context, char ***, char *, char *); + +krb5_error_code +krb5_ldap_get_value(LDAP *, LDAPMessage *, char *, int *); + +krb5_error_code +krb5_ldap_get_string(LDAP *, LDAPMessage *, char *, char **, krb5_boolean *); + +krb5_error_code +krb5_add_str_mem_ldap_mod(LDAPMod ***, char *, int, char **); + +krb5_error_code +krb5_add_ber_mem_ldap_mod(LDAPMod ***, char *, int, struct berval **); + +krb5_error_code +krb5_add_int_mem_ldap_mod(LDAPMod ***, char *, int , int); + +krb5_error_code +krb5_ldap_modify_ext(krb5_context context, LDAP *ld, const char *dn, + LDAPMod **mods, int op); + +krb5_error_code +krb5_ldap_free_mod_array(LDAPMod **); + +krb5_error_code +krb5_ldap_get_reference_count (krb5_context, char *, char *, int *, LDAP *); + +krb5_error_code +krb5_ldap_policydn_to_name (krb5_context, const char *, char **); + +krb5_error_code +krb5_ldap_name_to_policydn (krb5_context, char *, char **); + +krb5_error_code +populate_krb5_db_entry(krb5_context context, + krb5_ldap_context *ldap_context, + LDAP *ld, + LDAPMessage *ent, + krb5_const_principal princ, + krb5_db_entry *entry); + +int kldap_ensure_initialized (void); + +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c new file mode 100644 index 00000000..6328fbe2 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c @@ -0,0 +1,628 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_principal.c */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include "ldap_main.h" +#include "kdb_ldap.h" +#include "ldap_principal.h" +#include "princ_xdr.h" +#include "ldap_err.h" + +struct timeval timelimit = {300, 0}; /* 5 minutes */ +char *principal_attributes[] = { "krbprincipalname", + "krbcanonicalname", + "objectclass", + "krbprincipalkey", + "krbmaxrenewableage", + "krbmaxticketlife", + "krbticketflags", + "krbprincipalexpiration", + "krbticketpolicyreference", + "krbUpEnabled", + "krbpwdpolicyreference", + "krbpasswordexpiration", + "krbLastFailedAuth", + "krbLoginFailedCount", + "krbLastSuccessfulAuth", + "nsAccountLock", + "krbLastPwdChange", + "krbLastAdminUnlock", + "krbPrincipalAuthInd", + "krbExtraData", + "krbObjectReferences", + "krbAllowedToDelegateTo", + "krbPwdHistory", + NULL }; + +/* Must match KDB_*_ATTR macros in ldap_principal.h. */ +static char *attributes_set[] = { "krbmaxticketlife", + "krbmaxrenewableage", + "krbticketflags", + "krbprincipalexpiration", + "krbticketpolicyreference", + "krbPrincipalAuthInd", + "krbpwdpolicyreference", + "krbpasswordexpiration", + "krbprincipalkey", + "krblastpwdchange", + "krbextradata", + "krbLastSuccessfulAuth", + "krbLastFailedAuth", + "krbLoginFailedCount", + "krbLastAdminUnlock", + "krbPwdHistory", + NULL }; + + +static void +k5_free_key_data_contents(krb5_key_data *key) +{ + int16_t i; + + for (i = 0; i < key->key_data_ver; i++) { + zapfree(key->key_data_contents[i], key->key_data_length[i]); + key->key_data_contents[i] = NULL; + } +} + +void +k5_free_key_data(krb5_int16 n_key_data, krb5_key_data *key_data) +{ + int16_t i; + + if (key_data == NULL) + return; + for (i = 0; i < n_key_data; i++) + k5_free_key_data_contents(&key_data[i]); + free(key_data); +} + +void +krb5_dbe_free_contents(krb5_context context, krb5_db_entry *entry) +{ + krb5_tl_data *tl_data_next=NULL; + krb5_tl_data *tl_data=NULL; + + if (entry->e_data) + free(entry->e_data); + if (entry->princ) + 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) + free(tl_data->tl_data_contents); + free(tl_data); + } + k5_free_key_data(entry->n_key_data, entry->key_data); + memset(entry, 0, sizeof(*entry)); + return; +} + + +krb5_error_code +krb5_ldap_iterate(krb5_context context, char *match_expr, + krb5_error_code (*func)(krb5_pointer, krb5_db_entry *), + krb5_pointer func_arg, krb5_flags iterflags) +{ + krb5_db_entry entry; + krb5_principal principal; + char **subtree=NULL, *princ_name=NULL, *realm=NULL, **values=NULL, *filter=NULL; + unsigned int tree=0, ntree=1, i=0; + krb5_error_code st=0, tempst=0; + LDAP *ld=NULL; + LDAPMessage *result=NULL, *ent=NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + char *default_match_expr = "*"; + + /* Clear the global error string */ + krb5_clear_error_message(context); + + memset(&entry, 0, sizeof(krb5_db_entry)); + SETUP_CONTEXT(); + + realm = ldap_context->lrparams->realm_name; + if (realm == NULL) { + realm = context->default_realm; + if (realm == NULL) { + st = EINVAL; + k5_setmsg(context, st, _("Default realm not set")); + goto cleanup; + } + } + + /* + * If no match_expr then iterate through all krb princs like the db2 plugin + */ + if (match_expr == NULL) + match_expr = default_match_expr; + + if (asprintf(&filter, FILTER"%s))", match_expr) < 0) + filter = NULL; + CHECK_NULL(filter); + + if ((st = krb5_get_subtree_info(ldap_context, &subtree, &ntree)) != 0) + goto cleanup; + + GET_HANDLE(); + + for (tree=0; tree < ntree; ++tree) { + + LDAP_SEARCH(subtree[tree], ldap_context->lrparams->search_scope, filter, principal_attributes); + for (ent=ldap_first_entry(ld, result); ent != NULL; ent=ldap_next_entry(ld, ent)) { + values=ldap_get_values(ld, ent, "krbcanonicalname"); + if (values == NULL) + values=ldap_get_values(ld, ent, "krbprincipalname"); + if (values != NULL) { + for (i=0; values[i] != NULL; ++i) { + if (krb5_ldap_parse_principal_name(values[i], &princ_name) != 0) + continue; + st = krb5_parse_name(context, princ_name, &principal); + free(princ_name); + if (st) + continue; + + if (is_principal_in_realm(ldap_context, principal)) { + st = populate_krb5_db_entry(context, ldap_context, ld, + ent, principal, &entry); + krb5_free_principal(context, principal); + if (st) + goto cleanup; + (*func)(func_arg, &entry); + krb5_dbe_free_contents(context, &entry); + break; + } + (void) krb5_free_principal(context, principal); + } + ldap_value_free(values); + } + } /* end of for (ent= ... */ + ldap_msgfree(result); + result = NULL; + } /* end of for (tree= ... */ + +cleanup: + if (filter) + free (filter); + + for (;ntree; --ntree) + if (subtree[ntree-1]) + free (subtree[ntree-1]); + free(subtree); + + ldap_msgfree(result); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + + +/* + * delete a principal from the directory. + */ +krb5_error_code +krb5_ldap_delete_principal(krb5_context context, + krb5_const_principal searchfor) +{ + char *user=NULL, *DN=NULL, *strval[10] = {NULL}; + LDAPMod **mods=NULL; + LDAP *ld=NULL; + int j=0, ptype=0, pcount=0, attrsetmask=0; + krb5_error_code st=0; + krb5_boolean singleentry=FALSE; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + krb5_db_entry *entry = NULL; + + /* Clear the global error string */ + krb5_clear_error_message(context); + + SETUP_CONTEXT(); + /* get the principal info */ + if ((st=krb5_ldap_get_principal(context, searchfor, 0, &entry))) + goto cleanup; + + if (((st=krb5_get_princ_type(context, entry, &(ptype))) != 0) || + ((st=krb5_get_attributes_mask(context, entry, &(attrsetmask))) != 0) || + ((st=krb5_get_princ_count(context, entry, &(pcount))) != 0) || + ((st=krb5_get_userdn(context, entry, &(DN))) != 0)) + goto cleanup; + + if (DN == NULL) { + st = EINVAL; + k5_setmsg(context, st, _("DN information missing")); + goto cleanup; + } + + GET_HANDLE(); + + if (ptype == KDB_STANDALONE_PRINCIPAL_OBJECT) { + st = ldap_delete_ext_s(ld, DN, NULL, NULL); + if (st != LDAP_SUCCESS) { + st = set_ldap_error (context, st, OP_DEL); + goto cleanup; + } + } else { + if (((st=krb5_unparse_name(context, searchfor, &user)) != 0) + || ((st=krb5_ldap_unparse_principal_name(user)) != 0)) + goto cleanup; + + memset(strval, 0, sizeof(strval)); + strval[0] = user; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_DELETE, + strval)) != 0) + goto cleanup; + + singleentry = (pcount == 1) ? TRUE: FALSE; + if (singleentry == TRUE) { + /* + * If the Kerberos user principal to be deleted happens to be the last one associated + * with the directory user object, then it is time to delete the other kerberos + * specific attributes like krbmaxticketlife, i.e, unkerberize the directory user. + * From the attrsetmask value, identify the attributes set on the directory user + * object and delete them. + * NOTE: krbsecretkey attribute has per principal entries. There can be chances that the + * other principals' keys are existing/left-over. So delete all the values. + */ + while (attrsetmask) { + if (attrsetmask & 1) { + if ((st=krb5_add_str_mem_ldap_mod(&mods, attributes_set[j], LDAP_MOD_DELETE, + NULL)) != 0) + goto cleanup; + } + attrsetmask >>= 1; + ++j; + } + + /* the same should be done with the objectclass attributes */ + { + char *attrvalues[] = {"krbticketpolicyaux", "krbprincipalaux", NULL}; +/* char *attrvalues[] = {"krbpwdpolicyrefaux", "krbticketpolicyaux", "krbprincipalaux", NULL}; */ + int p, q, r=0, amask=0; + + if ((st=checkattributevalue(ld, DN, "objectclass", attrvalues, &amask)) != 0) + goto cleanup; + memset(strval, 0, sizeof(strval)); + for (p=1, q=0; p<=4; p<<=1, ++q) + if (p & amask) + strval[r++] = attrvalues[q]; + strval[r] = NULL; + if (r > 0) { + if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_DELETE, + strval)) != 0) + goto cleanup; + } + } + } + st=ldap_modify_ext_s(ld, DN, mods, NULL, NULL); + if (st != LDAP_SUCCESS) { + st = set_ldap_error(context, st, OP_MOD); + goto cleanup; + } + } + +cleanup: + if (user) + free (user); + + if (DN) + free (DN); + + krb5_db_free_principal(context, entry); + + ldap_mods_free(mods, 1); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + +/* + * Set *res will to 1 if entry is a standalone principal entry, 0 if not. On + * error, the value of *res is not defined. + */ +static inline krb5_error_code +is_standalone_principal(krb5_context kcontext, krb5_db_entry *entry, int *res) +{ + krb5_error_code code; + + code = krb5_get_princ_type(kcontext, entry, res); + if (!code) + *res = (*res == KDB_STANDALONE_PRINCIPAL_OBJECT) ? 1 : 0; + return code; +} + +/* + * Unparse princ in the format used for LDAP attributes, and set *user to the + * result. + */ +static krb5_error_code +unparse_principal_name(krb5_context context, krb5_const_principal princ, + char **user_out) +{ + krb5_error_code st; + char *luser = NULL; + + *user_out = NULL; + + st = krb5_unparse_name(context, princ, &luser); + if (st) + goto cleanup; + + st = krb5_ldap_unparse_principal_name(luser); + if (st) + goto cleanup; + + *user_out = luser; + luser = NULL; + +cleanup: + free(luser); + return st; +} + +/* + * Rename a principal's rdn. + * + * NOTE: Not every LDAP ds supports deleting the old rdn. If that is desired, + * it will have to be deleted afterwards. + */ +static krb5_error_code +rename_principal_rdn(krb5_context context, LDAP *ld, const char *dn, + const char *newprinc, char **newdn_out) +{ + int ret; + char *newrdn = NULL; + + *newdn_out = NULL; + + ret = asprintf(&newrdn, "krbprincipalname=%s", newprinc); + if (ret < 0) + return ENOMEM; + + /* + * ldap_rename_s takes a deleteoldrdn parameter, but setting it to 1 fails + * on 389 Directory Server (as of version 1.3.5.4) if the old RDN value + * contains uppercase letters. Instead, change the RDN without deleting + * the old value and delete it later. + */ + ret = ldap_rename_s(ld, dn, newrdn, NULL, 0, NULL, NULL); + if (ret == -1) { + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &ret); + ret = set_ldap_error(context, ret, OP_MOD); + goto cleanup; + } + + ret = replace_rdn(context, dn, newrdn, newdn_out); + +cleanup: + free(newrdn); + return ret; +} + +/* + * Rename a principal. + */ +krb5_error_code +krb5_ldap_rename_principal(krb5_context context, krb5_const_principal source, + krb5_const_principal target) +{ + int is_standalone; + krb5_error_code st; + char *suser = NULL, *tuser = NULL, *strval[2], *dn = NULL, *newdn = NULL; + krb5_db_entry *entry = NULL; + krb5_kvno mkvno; + struct berval **bersecretkey = NULL; + kdb5_dal_handle *dal_handle = NULL; + krb5_ldap_context *ldap_context = NULL; + krb5_ldap_server_handle *ldap_server_handle = NULL; + LDAP *ld = NULL; + LDAPMod **mods = NULL; + + /* Clear the global error string */ + krb5_clear_error_message(context); + + SETUP_CONTEXT(); + if (ldap_context->lrparams == NULL || ldap_context->container_dn == NULL) + return EINVAL; + + /* get ldap handle */ + GET_HANDLE(); + + /* Pass no flags. Principal aliases won't be returned, which is a good + * thing since we don't support renaming aliases. */ + st = krb5_ldap_get_principal(context, source, 0, &entry); + if (st) + goto cleanup; + + st = is_standalone_principal(context, entry, &is_standalone); + if (st) + goto cleanup; + + st = krb5_get_userdn(context, entry, &dn); + if (st) + goto cleanup; + if (dn == NULL) { + st = EINVAL; + k5_setmsg(context, st, _("dn information missing")); + goto cleanup; + } + + st = unparse_principal_name(context, source, &suser); + if (st) + goto cleanup; + st = unparse_principal_name(context, target, &tuser); + if (st) + goto cleanup; + + /* Specialize the salt and store it first so that in case of an error the + * correct salt will still be used. */ + st = krb5_dbe_specialize_salt(context, entry); + if (st) + goto cleanup; + + st = krb5_dbe_lookup_mkvno(context, entry, &mkvno); + if (st) + goto cleanup; + + bersecretkey = krb5_encode_krbsecretkey(entry->key_data, entry->n_key_data, + mkvno); + if (bersecretkey == NULL) { + st = ENOMEM; + goto cleanup; + } + + st = krb5_add_ber_mem_ldap_mod(&mods, "krbPrincipalKey", + LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, + bersecretkey); + if (st != 0) + goto cleanup; + + /* Update the principal. */ + st = krb5_ldap_modify_ext(context, ld, dn, mods, OP_MOD); + if (st) + goto cleanup; + ldap_mods_free(mods, 1); + mods = NULL; + + /* If this is a standalone principal, we want to rename the DN of the LDAP + * entry. If not, we will modify the entry without changing its DN. */ + if (is_standalone) { + st = rename_principal_rdn(context, ld, dn, tuser, &newdn); + if (st) + goto cleanup; + free(dn); + dn = newdn; + newdn = NULL; + } + + /* There can be more than one krbPrincipalName, so we have to delete + * the old one and add the new one. */ + strval[0] = suser; + strval[1] = NULL; + st = krb5_add_str_mem_ldap_mod(&mods, "krbPrincipalName", LDAP_MOD_DELETE, + strval); + if (st) + goto cleanup; + + strval[0] = tuser; + strval[1] = NULL; + if (!is_standalone) { + st = krb5_add_str_mem_ldap_mod(&mods, "krbPrincipalName", LDAP_MOD_ADD, + strval); + if (st) + goto cleanup; + } + + st = krb5_add_str_mem_ldap_mod(&mods, "krbCanonicalName", LDAP_MOD_REPLACE, + strval); + if (st) + goto cleanup; + + /* Update the principal. */ + st = krb5_ldap_modify_ext(context, ld, dn, mods, OP_MOD); + if (st) + goto cleanup; + +cleanup: + free(dn); + free(suser); + free(tuser); + free_berdata(bersecretkey); + krb5_db_free_principal(context, entry); + ldap_mods_free(mods, 1); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + +/* + * Function: krb5_ldap_unparse_principal_name + * + * Purpose: Removes '\\' that comes before every occurrence of '@' + * in the principal name component. + * + * Arguments: + * user_name (input/output) Principal name + * + */ + +krb5_error_code +krb5_ldap_unparse_principal_name(char *user_name) +{ + char *in, *out; + + out = user_name; + for (in = user_name; *in; in++) { + if (*in == '\\' && *(in + 1) == '@') + continue; + *out++ = *in; + } + *out = '\0'; + + return 0; +} + + +/* + * Function: krb5_ldap_parse_principal_name + * + * Purpose: Inserts '\\' before every occurrence of '@' + * in the principal name component. + * + * Arguments: + * i_princ_name (input) Principal name without '\\' + * o_princ_name (output) Principal name with '\\' + * + * Note: The caller has to free the memory allocated for o_princ_name. + */ + +krb5_error_code +krb5_ldap_parse_principal_name(char *i_princ_name, char **o_princ_name) +{ + const char *at_rlm_name, *p; + struct k5buf buf; + + at_rlm_name = strrchr(i_princ_name, '@'); + if (!at_rlm_name) { + *o_princ_name = strdup(i_princ_name); + } else { + k5_buf_init_dynamic(&buf); + for (p = i_princ_name; p < at_rlm_name; p++) { + if (*p == '@') + k5_buf_add(&buf, "\\"); + k5_buf_add_len(&buf, p, 1); + } + k5_buf_add(&buf, at_rlm_name); + *o_princ_name = k5_buf_cstring(&buf); + } + return (*o_princ_name == NULL) ? ENOMEM : 0; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h new file mode 100644 index 00000000..72a9f960 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.h @@ -0,0 +1,152 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_principal.h */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#ifndef _LDAP_PRINCIPAL_H +#define _LDAP_PRINCIPAL_H 1 + +#include "ldap_tkt_policy.h" +#include "princ_xdr.h" + +#define KEYHEADER 12 + +#define NOOFKEYS(ptr) ((ptr[10]<<8) | ptr[11]) + +#define PRINCIPALLEN(ptr) ((ptr[0]<<8) | ptr[1]) +#define PRINCIPALNAME(ptr) (ptr + KEYHEADER + (NOOFKEYS(ptr) *8)) + +#define KEYBODY(ptr) PRINCIPALNAME(ptr) + PRINCIPALLEN(ptr) + +#define PKEYVER(ptr) ((ptr[2]<<8) | ptr[3]) +#define MKEYVER(ptr) ((ptr[4]<<8) | ptr[5]) + +#define KEYTYPE(ptr,j) ((ptr[KEYHEADER+(j*8)]<<8) | ptr[KEYHEADER+1+(j*8)]) +#define KEYLENGTH(ptr,j) ((ptr[KEYHEADER+2+(j*8)]<<8) | ptr[KEYHEADER+3+(j*8)]) +#define SALTTYPE(ptr,j) ((ptr[KEYHEADER+4+(j*8)]<<8) | ptr[KEYHEADER+5+(j*8)]) +#define SALTLENGTH(ptr,j) ((ptr[KEYHEADER+6+(j*8)]<<8) | ptr[KEYHEADER+7+(j*8)]) + +#define MAX_KEY_LENGTH 1024 +#define CONTAINERDN_ARG "containerdn" +#define USERDN_ARG "dn" +#define TKTPOLICY_ARG "tktpolicy" +#define LINKDN_ARG "linkdn" + +/* #define FILTER "(&(objectclass=krbprincipalaux)(krbprincipalname=" */ +#define FILTER "(&(|(objectclass=krbprincipalaux)(objectclass=krbprincipal))(krbprincipalname=" + +#define KDB_USER_PRINCIPAL 0x01 +#define KDB_SERVICE_PRINCIPAL 0x02 +#define KDB_STANDALONE_PRINCIPAL_OBJECT 0x01 + +/* these will be consumed only by krb5_ldap_delete_principal*/ +/* these will be set by krb5_ldap_get_principal and fed into the tl_data */ + +/* See also attributes_set[] in ldap_principal.c. */ +#define KDB_MAX_LIFE_ATTR 0x000001 +#define KDB_MAX_RLIFE_ATTR 0x000002 +#define KDB_TKT_FLAGS_ATTR 0x000004 +#define KDB_PRINC_EXPIRE_TIME_ATTR 0x000008 +#define KDB_POL_REF_ATTR 0x000010 +#define KDB_AUTH_IND_ATTR 0x000020 +#define KDB_PWD_POL_REF_ATTR 0x000040 +#define KDB_PWD_EXPIRE_TIME_ATTR 0x000080 +#define KDB_SECRET_KEY_ATTR 0x000100 +#define KDB_LAST_PWD_CHANGE_ATTR 0x000200 +#define KDB_EXTRA_DATA_ATTR 0x000400 +#define KDB_LAST_SUCCESS_ATTR 0x000800 +#define KDB_LAST_FAILED_ATTR 0x001000 +#define KDB_FAIL_AUTH_COUNT_ATTR 0x002000 +#define KDB_LAST_ADMIN_UNLOCK_ATTR 0x004000 +#define KDB_PWD_HISTORY_ATTR 0x008000 + +/* + * This is a private contract between krb5_ldap_lockout_audit() + * and krb5_ldap_put_principal(). If present, it means that the + * krbPwdMaxFailure attribute should be incremented by one. + */ +#define KADM5_FAIL_AUTH_COUNT_INCREMENT 0x080000 /* KADM5_CPW_FUNCTION */ + +extern struct timeval timeout; +extern char *policyclass[]; + +krb5_error_code +krb5_ldap_put_principal(krb5_context, krb5_db_entry *, char **); + +krb5_error_code +krb5_ldap_get_principal(krb5_context , krb5_const_principal , + unsigned int, krb5_db_entry **); + +krb5_error_code +krb5_ldap_delete_principal(krb5_context, krb5_const_principal); + +krb5_error_code +krb5_ldap_rename_principal(krb5_context context, krb5_const_principal source, + krb5_const_principal target); + +krb5_error_code +krb5_ldap_iterate(krb5_context, char *, + krb5_error_code (*)(krb5_pointer, krb5_db_entry *), + krb5_pointer, krb5_flags); + +void +k5_free_key_data(krb5_int16 n_key_data, krb5_key_data *key_data); + +void +krb5_dbe_free_contents(krb5_context context, krb5_db_entry *entry); + +void +krb5_dbe_free_contents(krb5_context, krb5_db_entry *); + +krb5_error_code +krb5_ldap_unparse_principal_name(char *); + +krb5_error_code +krb5_ldap_parse_principal_name(char *, char **); + +struct berval** +krb5_encode_krbsecretkey(krb5_key_data *key_data, int n_key_data, + krb5_kvno mkvno); + +krb5_error_code +krb5_decode_histkey(krb5_context, struct berval **, osa_princ_ent_rec *); + +krb5_error_code +krb5_decode_krbsecretkey(krb5_context, krb5_db_entry *, struct berval **, + krb5_kvno *); + +void +free_berdata(struct berval **array); + +krb5_error_code +berval2tl_data(struct berval *in, krb5_tl_data **out); + +krb5_error_code +krb5_read_tkt_policy(krb5_context, krb5_ldap_context *, krb5_db_entry *, + char *); +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c new file mode 100644 index 00000000..ff705a2c --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c @@ -0,0 +1,1751 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c */ +/* + * Copyright (C) 2016 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. + */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include "ldap_main.h" +#include "kdb_ldap.h" +#include "ldap_principal.h" +#include "princ_xdr.h" +#include "ldap_tkt_policy.h" +#include "ldap_pwd_policy.h" +#include "ldap_err.h" +#include +#include + +extern char* principal_attributes[]; +extern char* max_pwd_life_attr[]; + +static char * +getstringtime(krb5_timestamp); + +krb5_error_code +berval2tl_data(struct berval *in, krb5_tl_data **out) +{ + *out = (krb5_tl_data *) malloc (sizeof (krb5_tl_data)); + if (*out == NULL) + return ENOMEM; + + (*out)->tl_data_length = in->bv_len - 2; + (*out)->tl_data_contents = (krb5_octet *) malloc + ((*out)->tl_data_length * sizeof (krb5_octet)); + if ((*out)->tl_data_contents == NULL) { + free (*out); + return ENOMEM; + } + + UNSTORE16_INT (in->bv_val, (*out)->tl_data_type); + memcpy ((*out)->tl_data_contents, in->bv_val + 2, (*out)->tl_data_length); + + return 0; +} + +/* + * look up a principal in the directory. + */ + +krb5_error_code +krb5_ldap_get_principal(krb5_context context, krb5_const_principal searchfor, + unsigned int flags, krb5_db_entry **entry_ptr) +{ + char *user=NULL, *filter=NULL, *filtuser=NULL; + unsigned int tree=0, ntrees=1, princlen=0; + krb5_error_code tempst=0, st=0; + char **values=NULL, **subtree=NULL, *cname=NULL; + LDAP *ld=NULL; + LDAPMessage *result=NULL, *ent=NULL; + krb5_ldap_context *ldap_context=NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + krb5_principal cprinc=NULL; + krb5_boolean found=FALSE; + krb5_db_entry *entry = NULL; + + *entry_ptr = NULL; + + /* Clear the global error string */ + krb5_clear_error_message(context); + + if (searchfor == NULL) + return EINVAL; + + dal_handle = context->dal_handle; + ldap_context = (krb5_ldap_context *) dal_handle->db_context; + + CHECK_LDAP_HANDLE(ldap_context); + + if (!is_principal_in_realm(ldap_context, searchfor)) { + st = KRB5_KDB_NOENTRY; + k5_setmsg(context, st, _("Principal does not belong to realm")); + goto cleanup; + } + + if ((st=krb5_unparse_name(context, searchfor, &user)) != 0) + goto cleanup; + + if ((st=krb5_ldap_unparse_principal_name(user)) != 0) + goto cleanup; + + filtuser = ldap_filter_correct(user); + if (filtuser == NULL) { + st = ENOMEM; + goto cleanup; + } + + princlen = strlen(FILTER) + strlen(filtuser) + 2 + 1; /* 2 for closing brackets */ + if ((filter = malloc(princlen)) == NULL) { + st = ENOMEM; + goto cleanup; + } + snprintf(filter, princlen, FILTER"%s))", filtuser); + + if ((st = krb5_get_subtree_info(ldap_context, &subtree, &ntrees)) != 0) + goto cleanup; + + GET_HANDLE(); + for (tree=0; tree < ntrees && !found; ++tree) { + + LDAP_SEARCH(subtree[tree], ldap_context->lrparams->search_scope, filter, principal_attributes); + for (ent=ldap_first_entry(ld, result); ent != NULL && !found; ent=ldap_next_entry(ld, ent)) { + + /* get the associated directory user information */ + if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) { + int i; + + /* a wild-card in a principal name can return a list of kerberos principals. + * Make sure that the correct principal is returned. + * NOTE: a principalname k* in ldap server will return all the principals starting with a k + */ + for (i=0; values[i] != NULL; ++i) { + if (strcmp(values[i], user) == 0) { + found = TRUE; + break; + } + } + ldap_value_free(values); + + if (!found) /* no matching principal found */ + continue; + } + + if ((values=ldap_get_values(ld, ent, "krbcanonicalname")) != NULL) { + if (values[0] && strcmp(values[0], user) != 0) { + /* We matched an alias, not the canonical name. */ + st = krb5_ldap_parse_principal_name(values[0], &cname); + if (st != 0) + goto cleanup; + st = krb5_parse_name(context, cname, &cprinc); + if (st != 0) + goto cleanup; + } + ldap_value_free(values); + if (!found) + continue; + } + + entry = k5alloc(sizeof(*entry), &st); + if (entry == NULL) + goto cleanup; + if ((st = populate_krb5_db_entry(context, ldap_context, ld, ent, + cprinc ? cprinc : searchfor, + entry)) != 0) + goto cleanup; + } + ldap_msgfree(result); + result = NULL; + } /* for (tree=0 ... */ + + if (found) { + *entry_ptr = entry; + entry = NULL; + } else + st = KRB5_KDB_NOENTRY; + +cleanup: + ldap_msgfree(result); + krb5_db_free_principal(context, entry); + + if (filter) + free (filter); + + if (subtree) { + for (; ntrees; --ntrees) + if (subtree[ntrees-1]) + free (subtree[ntrees-1]); + free (subtree); + } + + if (ldap_server_handle) + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + + if (user) + free(user); + + if (filtuser) + free(filtuser); + + if (cname) + free(cname); + + if (cprinc) + krb5_free_principal(context, cprinc); + + return st; +} + +typedef enum{ ADD_PRINCIPAL, MODIFY_PRINCIPAL } OPERATION; +/* + * ptype is creating confusions. Additionally the logic + * surronding ptype is redundunt and can be achevied + * with the help of dn and containerdn members. + * so dropping the ptype member + */ + +typedef struct _xargs_t { + char *dn; + char *linkdn; + krb5_boolean dn_from_kbd; + char *containerdn; + char *tktpolicydn; +}xargs_t; + +static void +free_xargs(xargs_t xargs) +{ + if (xargs.dn) + free (xargs.dn); + if (xargs.linkdn) + free(xargs.linkdn); + if (xargs.containerdn) + free (xargs.containerdn); + if (xargs.tktpolicydn) + free (xargs.tktpolicydn); +} + +static krb5_error_code +process_db_args(krb5_context context, char **db_args, xargs_t *xargs, + OPERATION optype) +{ + int i=0; + krb5_error_code st=0; + char *arg=NULL, *arg_val=NULL; + char **dptr=NULL; + unsigned int arg_val_len=0; + + if (db_args) { + for (i=0; db_args[i]; ++i) { + arg = strtok_r(db_args[i], "=", &arg_val); + arg = (arg != NULL) ? arg : ""; + if (strcmp(arg, TKTPOLICY_ARG) == 0) { + dptr = &xargs->tktpolicydn; + } else { + if (strcmp(arg, USERDN_ARG) == 0) { + if (optype == MODIFY_PRINCIPAL || + xargs->dn != NULL || xargs->containerdn != NULL || + xargs->linkdn != NULL) { + st = EINVAL; + k5_setmsg(context, st, _("%s option not supported"), + arg); + goto cleanup; + } + dptr = &xargs->dn; + } else if (strcmp(arg, CONTAINERDN_ARG) == 0) { + if (optype == MODIFY_PRINCIPAL || + xargs->dn != NULL || xargs->containerdn != NULL) { + st = EINVAL; + k5_setmsg(context, st, _("%s option not supported"), + arg); + goto cleanup; + } + dptr = &xargs->containerdn; + } else if (strcmp(arg, LINKDN_ARG) == 0) { + if (xargs->dn != NULL || xargs->linkdn != NULL) { + st = EINVAL; + k5_setmsg(context, st, _("%s option not supported"), + arg); + goto cleanup; + } + dptr = &xargs->linkdn; + } else { + st = EINVAL; + k5_setmsg(context, st, _("unknown option: %s"), arg); + goto cleanup; + } + + xargs->dn_from_kbd = TRUE; + if (arg_val == NULL || strlen(arg_val) == 0) { + st = EINVAL; + k5_setmsg(context, st, _("%s option value missing"), arg); + goto cleanup; + } + } + + if (arg_val == NULL) { + st = EINVAL; + k5_setmsg(context, st, _("%s option value missing"), arg); + goto cleanup; + } + arg_val_len = strlen(arg_val) + 1; + + if (strcmp(arg, TKTPOLICY_ARG) == 0) { + if ((st = krb5_ldap_name_to_policydn (context, + arg_val, + dptr)) != 0) + goto cleanup; + } else { + *dptr = k5memdup(arg_val, arg_val_len, &st); + if (*dptr == NULL) + goto cleanup; + } + } + } + +cleanup: + return st; +} + +krb5int_access accessor; + +static krb5_error_code +asn1_encode_sequence_of_keys(krb5_key_data *key_data, krb5_int16 n_key_data, + krb5_int32 mkvno, krb5_data **code) +{ + krb5_error_code err; + ldap_seqof_key_data val; + + /* + * This should be pushed back into other library initialization + * code. + */ + err = kldap_ensure_initialized (); + if (err) + return err; + + val.key_data = key_data; + val.n_key_data = n_key_data; + val.mkvno = mkvno; + val.kvno = key_data[0].key_data_kvno; + + return accessor.asn1_ldap_encode_sequence_of_keys(&val, code); +} + +static krb5_error_code +asn1_decode_sequence_of_keys(krb5_data *in, ldap_seqof_key_data *out) +{ + krb5_error_code err; + ldap_seqof_key_data *p; + int i; + + memset(out, 0, sizeof(*out)); + + /* + * This should be pushed back into other library initialization + * code. + */ + err = kldap_ensure_initialized (); + if (err) + return err; + + err = accessor.asn1_ldap_decode_sequence_of_keys(in, &p); + if (err) + return err; + + /* Set kvno and key_data_ver in each key_data element. */ + for (i = 0; i < p->n_key_data; i++) { + p->key_data[i].key_data_kvno = p->kvno; + /* The decoder sets key_data_ver to 1 if no salt is present, but leaves + * it at 0 if salt is present. */ + if (p->key_data[i].key_data_ver == 0) + p->key_data[i].key_data_ver = 2; + } + + *out = *p; + free(p); + return 0; +} + +/* + * Free a NULL-terminated struct berval *array[] and all its contents. + * Does not set array to NULL after freeing it. + */ +void +free_berdata(struct berval **array) +{ + int i; + + if (array != NULL) { + for (i = 0; array[i] != NULL; i++) { + if (array[i]->bv_val != NULL) + free(array[i]->bv_val); + free(array[i]); + } + free(array); + } +} + +/* + * Encode krb5_key_data into a berval struct for insertion into LDAP. + */ +static krb5_error_code +encode_keys(krb5_key_data *key_data_in, int n_key_data, krb5_kvno mkvno, + struct berval **bval_out) +{ + krb5_error_code err = 0; + int i; + krb5_key_data *key_data = NULL; + struct berval *bval = NULL; + krb5_data *code; + + *bval_out = NULL; + if (n_key_data <= 0) { + err = EINVAL; + goto cleanup; + } + + /* Make a shallow copy of the key data so we can alter it. */ + key_data = k5calloc(n_key_data, sizeof(*key_data), &err); + if (key_data == NULL) + goto cleanup; + memcpy(key_data, key_data_in, n_key_data * sizeof(*key_data)); + + /* Unpatched krb5 1.11 and 1.12 cannot decode KrbKey sequences with no salt + * field. For compatibility, always encode a salt field. */ + for (i = 0; i < n_key_data; i++) { + if (key_data[i].key_data_ver == 1) { + key_data[i].key_data_ver = 2; + key_data[i].key_data_type[1] = KRB5_KDB_SALTTYPE_NORMAL; + key_data[i].key_data_length[1] = 0; + key_data[i].key_data_contents[1] = NULL; + } + } + + bval = k5alloc(sizeof(struct berval), &err); + if (bval == NULL) + goto cleanup; + + err = asn1_encode_sequence_of_keys(key_data, n_key_data, mkvno, &code); + if (err) + goto cleanup; + + /* Steal the data pointer from code for bval and discard code. */ + bval->bv_len = code->length; + bval->bv_val = code->data; + free(code); + + *bval_out = bval; + bval = NULL; + +cleanup: + free(key_data); + free(bval); + return err; +} + +/* Decoding ASN.1 encoded key */ +struct berval ** +krb5_encode_krbsecretkey(krb5_key_data *key_data, int n_key_data, + krb5_kvno mkvno) +{ + struct berval **ret = NULL; + int currkvno; + int num_versions = 0; + int i, j, last; + krb5_error_code err = 0; + + if (n_key_data < 0) + return NULL; + + /* Find the number of key versions */ + if (n_key_data > 0) { + for (i = 0, num_versions = 1; i < n_key_data - 1; i++) { + if (key_data[i].key_data_kvno != key_data[i + 1].key_data_kvno) + num_versions++; + } + } + + ret = calloc(num_versions + 1, sizeof(struct berval *)); + if (ret == NULL) { + err = ENOMEM; + goto cleanup; + } + ret[num_versions] = NULL; + + /* n_key_data may be 0 if a principal is created without a key. */ + if (n_key_data == 0) + goto cleanup; + + currkvno = key_data[0].key_data_kvno; + for (i = 0, last = 0, j = 0; i < n_key_data; i++) { + if (i == n_key_data - 1 || key_data[i + 1].key_data_kvno != currkvno) { + err = encode_keys(key_data + last, (krb5_int16)i - last + 1, mkvno, + &ret[j]); + if (err) + goto cleanup; + j++; + last = i + 1; + + if (i < n_key_data - 1) + currkvno = key_data[i + 1].key_data_kvno; + } + } + +cleanup: + if (err != 0) { + free_berdata(ret); + ret = NULL; + } + + return ret; +} + +/* + * Encode a principal's key history for insertion into ldap. + */ +static struct berval ** +krb5_encode_histkey(osa_princ_ent_rec *princ_ent) +{ + unsigned int i; + krb5_error_code err = 0; + struct berval **ret = NULL; + + if (princ_ent->old_key_len <= 0) + return NULL; + + ret = k5calloc(princ_ent->old_key_len + 1, sizeof(struct berval *), &err); + if (ret == NULL) + goto cleanup; + + for (i = 0; i < princ_ent->old_key_len; i++) { + if (princ_ent->old_keys[i].n_key_data <= 0) { + err = EINVAL; + goto cleanup; + } + err = encode_keys(princ_ent->old_keys[i].key_data, + princ_ent->old_keys[i].n_key_data, + princ_ent->admin_history_kvno, &ret[i]); + if (err) + goto cleanup; + } + + ret[princ_ent->old_key_len] = NULL; + +cleanup: + if (err != 0) { + free_berdata(ret); + ret = NULL; + } + + return ret; +} + +static krb5_error_code +tl_data2berval (krb5_tl_data *in, struct berval **out) +{ + *out = (struct berval *) malloc (sizeof (struct berval)); + if (*out == NULL) + return ENOMEM; + + (*out)->bv_len = in->tl_data_length + 2; + (*out)->bv_val = (char *) malloc ((*out)->bv_len); + if ((*out)->bv_val == NULL) { + free (*out); + return ENOMEM; + } + + STORE16_INT((*out)->bv_val, in->tl_data_type); + memcpy ((*out)->bv_val + 2, in->tl_data_contents, in->tl_data_length); + + return 0; +} + +/* Parse the "require_auth" string for auth indicators, adding them to the + * krbPrincipalAuthInd attribute. */ +static krb5_error_code +update_ldap_mod_auth_ind(krb5_context context, krb5_db_entry *entry, + LDAPMod ***mods) +{ + int i = 0; + krb5_error_code ret; + char *auth_ind = NULL; + char *strval[10] = { 0 }; + char *ai, *ai_save = NULL; + int mask, sv_num = sizeof(strval) / sizeof(*strval); + + ret = krb5_dbe_get_string(context, entry, KRB5_KDB_SK_REQUIRE_AUTH, + &auth_ind); + if (ret) + return ret; + if (auth_ind == NULL) { + /* If we know krbPrincipalAuthInd attributes are present from loading + * the entry, delete them. */ + ret = krb5_get_attributes_mask(context, entry, &mask); + if (!ret && (mask & KDB_AUTH_IND_ATTR)) { + return krb5_add_str_mem_ldap_mod(mods, "krbPrincipalAuthInd", + LDAP_MOD_DELETE, NULL); + } + return 0; + } + + ai = strtok_r(auth_ind, " ", &ai_save); + while (ai != NULL && i < sv_num) { + strval[i++] = ai; + ai = strtok_r(NULL, " ", &ai_save); + } + + ret = krb5_add_str_mem_ldap_mod(mods, "krbPrincipalAuthInd", + LDAP_MOD_REPLACE, strval); + krb5_dbe_free_string(context, auth_ind); + return ret; +} + +static krb5_error_code +check_dn_in_container(krb5_context context, const char *dn, + char *const *subtrees, unsigned int ntrees) +{ + unsigned int i; + size_t dnlen = strlen(dn), stlen; + + for (i = 0; i < ntrees; i++) { + if (subtrees[i] == NULL || *subtrees[i] == '\0') + return 0; + stlen = strlen(subtrees[i]); + if (dnlen >= stlen && + strcasecmp(dn + dnlen - stlen, subtrees[i]) == 0 && + (dnlen == stlen || dn[dnlen - stlen - 1] == ',')) + return 0; + } + + k5_setmsg(context, EINVAL, _("DN is out of the realm subtree")); + return EINVAL; +} + +static krb5_error_code +check_dn_exists(krb5_context context, + krb5_ldap_server_handle *ldap_server_handle, + const char *dn, krb5_boolean nonkrb_only) +{ + krb5_error_code st = 0, tempst; + krb5_ldap_context *ldap_context = context->dal_handle->db_context; + LDAP *ld = ldap_server_handle->ldap_handle; + LDAPMessage *result = NULL, *ent; + char *attrs[] = { "krbticketpolicyreference", "krbprincipalname", NULL }; + char **values; + + LDAP_SEARCH_1(dn, LDAP_SCOPE_BASE, 0, attrs, IGNORE_STATUS); + if (st != LDAP_SUCCESS) + return set_ldap_error(context, st, OP_SEARCH); + + ent = ldap_first_entry(ld, result); + CHECK_NULL(ent); + + values = ldap_get_values(ld, ent, "krbticketpolicyreference"); + if (values != NULL) + ldap_value_free(values); + + values = ldap_get_values(ld, ent, "krbprincipalname"); + if (values != NULL) { + ldap_value_free(values); + if (nonkrb_only) { + st = EINVAL; + k5_setmsg(context, st, _("ldap object is already kerberized")); + goto cleanup; + } + } + +cleanup: + ldap_msgfree(result); + return st; +} + +static krb5_error_code +validate_xargs(krb5_context context, + krb5_ldap_server_handle *ldap_server_handle, + const xargs_t *xargs, const char *standalone_dn, + char *const *subtrees, unsigned int ntrees) +{ + krb5_error_code st; + + if (xargs->dn != NULL) { + /* The supplied dn must be within a realm container. */ + st = check_dn_in_container(context, xargs->dn, subtrees, ntrees); + if (st) + return st; + /* The supplied dn must exist without Kerberos attributes. */ + st = check_dn_exists(context, ldap_server_handle, xargs->dn, TRUE); + if (st) + return st; + } + + if (xargs->linkdn != NULL) { + /* The supplied linkdn must be within a realm container. */ + st = check_dn_in_container(context, xargs->linkdn, subtrees, ntrees); + if (st) + return st; + /* The supplied linkdn must exist. */ + st = check_dn_exists(context, ldap_server_handle, xargs->linkdn, + FALSE); + if (st) + return st; + } + + if (xargs->containerdn != NULL && standalone_dn != NULL) { + /* standalone_dn (likely composed using containerdn) must be within a + * container. */ + st = check_dn_in_container(context, standalone_dn, subtrees, ntrees); + if (st) + return st; + } + + return 0; +} + +krb5_error_code +krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry, + char **db_args) +{ + int l=0, kerberos_principal_object_type=0; + unsigned int ntrees=0, tre=0; + krb5_error_code st=0, tempst=0; + LDAP *ld=NULL; + LDAPMessage *result=NULL, *ent=NULL; + char **subtreelist = NULL; + char *user=NULL, *subtree=NULL, *principal_dn=NULL; + char *strval[10]={NULL}, errbuf[1024]; + char *filtuser=NULL; + struct berval **bersecretkey=NULL; + LDAPMod **mods=NULL; + krb5_boolean create_standalone=FALSE; + krb5_boolean establish_links=FALSE; + char *standalone_principal_dn=NULL; + krb5_tl_data *tl_data=NULL; + krb5_key_data **keys=NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + osa_princ_ent_rec princ_ent = {0}; + xargs_t xargs = {0}; + char *polname = NULL; + OPERATION optype; + krb5_boolean found_entry = FALSE; + char *filter = NULL; + + /* Clear the global error string */ + krb5_clear_error_message(context); + + SETUP_CONTEXT(); + if (ldap_context->lrparams == NULL || ldap_context->container_dn == NULL) + return EINVAL; + + /* get ldap handle */ + GET_HANDLE(); + + if (!is_principal_in_realm(ldap_context, entry->princ)) { + st = EINVAL; + k5_setmsg(context, st, + _("Principal does not belong to the default realm")); + goto cleanup; + } + + /* get the principal information to act on */ + if (((st=krb5_unparse_name(context, entry->princ, &user)) != 0) || + ((st=krb5_ldap_unparse_principal_name(user)) != 0)) + goto cleanup; + filtuser = ldap_filter_correct(user); + if (filtuser == NULL) { + st = ENOMEM; + goto cleanup; + } + + /* Identity the type of operation, it can be + * add principal or modify principal. + * hack if the entry->mask has KRB_PRINCIPAL flag set + * then it is a add operation + */ + if (entry->mask & KADM5_PRINCIPAL) + optype = ADD_PRINCIPAL; + else + optype = MODIFY_PRINCIPAL; + + if (((st=krb5_get_princ_type(context, entry, &kerberos_principal_object_type)) != 0) || + ((st=krb5_get_userdn(context, entry, &principal_dn)) != 0)) + goto cleanup; + + if ((st=process_db_args(context, db_args, &xargs, optype)) != 0) + goto cleanup; + + if (entry->mask & KADM5_LOAD) { + unsigned int tree = 0; + int numlentries = 0; + + /* A load operation is special, will do a mix-in (add krbprinc + * attrs to a non-krb object entry) if an object exists with a + * matching krbprincipalname attribute so try to find existing + * object and set principal_dn. This assumes that the + * krbprincipalname attribute is unique (only one object entry has + * a particular krbprincipalname attribute). + */ + if (asprintf(&filter, FILTER"%s))", filtuser) < 0) { + filter = NULL; + st = ENOMEM; + goto cleanup; + } + + /* get the current subtree list */ + if ((st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees)) != 0) + goto cleanup; + + found_entry = FALSE; + /* search for entry with matching krbprincipalname attribute */ + for (tree = 0; found_entry == FALSE && tree < ntrees; ++tree) { + if (principal_dn == NULL) { + LDAP_SEARCH_1(subtreelist[tree], ldap_context->lrparams->search_scope, filter, principal_attributes, IGNORE_STATUS); + } else { + /* just look for entry with principal_dn */ + LDAP_SEARCH_1(principal_dn, LDAP_SCOPE_BASE, filter, principal_attributes, IGNORE_STATUS); + } + if (st == LDAP_SUCCESS) { + numlentries = ldap_count_entries(ld, result); + if (numlentries > 1) { + st = EINVAL; + k5_setmsg(context, st, + _("operation can not continue, more than one " + "entry with principal name \"%s\" found"), + user); + goto cleanup; + } else if (numlentries == 1) { + found_entry = TRUE; + if (principal_dn == NULL) { + ent = ldap_first_entry(ld, result); + if (ent != NULL) { + /* setting principal_dn will cause that entry to be modified further down */ + if ((principal_dn = ldap_get_dn(ld, ent)) == NULL) { + ldap_get_option (ld, LDAP_OPT_RESULT_CODE, &st); + st = set_ldap_error (context, st, 0); + goto cleanup; + } + } + } + } + } else if (st != LDAP_NO_SUCH_OBJECT) { + /* could not perform search, return with failure */ + st = set_ldap_error (context, st, 0); + goto cleanup; + } + ldap_msgfree(result); + result = NULL; + /* + * If it isn't found then assume a standalone princ entry is to + * be created. + */ + } /* end for (tree = 0; principal_dn == ... */ + + if (found_entry == FALSE && principal_dn != NULL) { + /* + * if principal_dn is null then there is code further down to + * deal with setting standalone_principal_dn. Also note that + * this will set create_standalone true for + * non-mix-in entries which is okay if loading from a dump. + */ + create_standalone = TRUE; + standalone_principal_dn = strdup(principal_dn); + CHECK_NULL(standalone_principal_dn); + } + } /* end if (entry->mask & KADM5_LOAD */ + + /* time to generate the DN information with the help of + * containerdn, principalcontainerreference or + * realmcontainerdn information + */ + if (principal_dn == NULL && xargs.dn == NULL) { /* creation of standalone principal */ + /* get the subtree information */ + if (entry->princ->length == 2 && entry->princ->data[0].length == strlen("krbtgt") && + strncmp(entry->princ->data[0].data, "krbtgt", entry->princ->data[0].length) == 0) { + /* if the principal is a inter-realm principal, always created in the realm container */ + subtree = strdup(ldap_context->lrparams->realmdn); + } else if (xargs.containerdn) { + if ((st=checkattributevalue(ld, xargs.containerdn, NULL, NULL, NULL)) != 0) { + if (st == KRB5_KDB_NOENTRY || st == KRB5_KDB_CONSTRAINT_VIOLATION) { + int ost = st; + st = EINVAL; + k5_wrapmsg(context, ost, st, _("'%s' not found"), + xargs.containerdn); + } + goto cleanup; + } + subtree = strdup(xargs.containerdn); + } else if (ldap_context->lrparams->containerref && strlen(ldap_context->lrparams->containerref) != 0) { + /* + * Here the subtree should be changed with + * principalcontainerreference attribute value + */ + subtree = strdup(ldap_context->lrparams->containerref); + } else { + subtree = strdup(ldap_context->lrparams->realmdn); + } + CHECK_NULL(subtree); + + if (asprintf(&standalone_principal_dn, "krbprincipalname=%s,%s", + filtuser, subtree) < 0) + standalone_principal_dn = NULL; + CHECK_NULL(standalone_principal_dn); + /* + * free subtree when you are done using the subtree + * set the boolean create_standalone to TRUE + */ + create_standalone = TRUE; + free(subtree); + subtree = NULL; + } + + /* + * If the DN information is presented by the user, time to + * validate the input to ensure that the DN falls under + * any of the subtrees + */ + if (xargs.dn_from_kbd == TRUE) { + /* Get the current subtree list if we haven't already done so. */ + if (subtreelist == NULL) { + st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees); + if (st) + goto cleanup; + } + + st = validate_xargs(context, ldap_server_handle, &xargs, + standalone_principal_dn, subtreelist, ntrees); + if (st) + goto cleanup; + } + + if (xargs.linkdn != NULL) { + /* + * link information can be changed using modprinc. + * However, link information can be changed only on the + * standalone kerberos principal objects. A standalone + * kerberos principal object is of type krbprincipal + * structural objectclass. + * + * NOTE: kerberos principals on an ldap object can't be + * linked to other ldap objects. + */ + if (optype == MODIFY_PRINCIPAL && + kerberos_principal_object_type != KDB_STANDALONE_PRINCIPAL_OBJECT) { + st = EINVAL; + snprintf(errbuf, sizeof(errbuf), + _("link information can not be set/updated as the " + "kerberos principal belongs to an ldap object")); + k5_setmsg(context, st, "%s", errbuf); + goto cleanup; + } + /* + * Check the link information. If there is already a link + * existing then this operation is not allowed. + */ + { + char **linkdns=NULL; + int j=0; + + if ((st=krb5_get_linkdn(context, entry, &linkdns)) != 0) { + snprintf(errbuf, sizeof(errbuf), + _("Failed getting object references")); + k5_setmsg(context, st, "%s", errbuf); + goto cleanup; + } + if (linkdns != NULL) { + st = EINVAL; + snprintf(errbuf, sizeof(errbuf), + _("kerberos principal is already linked to a ldap " + "object")); + k5_setmsg(context, st, "%s", errbuf); + for (j=0; linkdns[j] != NULL; ++j) + free (linkdns[j]); + free (linkdns); + goto cleanup; + } + } + + establish_links = TRUE; + } + + if (entry->mask & KADM5_LAST_SUCCESS) { + memset(strval, 0, sizeof(strval)); + if ((strval[0]=getstringtime(entry->last_success)) == NULL) + goto cleanup; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastSuccessfulAuth", LDAP_MOD_REPLACE, strval)) != 0) { + free (strval[0]); + goto cleanup; + } + free (strval[0]); + } + + if (entry->mask & KADM5_LAST_FAILED) { + memset(strval, 0, sizeof(strval)); + if ((strval[0]=getstringtime(entry->last_failed)) == NULL) + goto cleanup; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastFailedAuth", LDAP_MOD_REPLACE, strval)) != 0) { + free (strval[0]); + goto cleanup; + } + free(strval[0]); + } + + if (entry->mask & KADM5_FAIL_AUTH_COUNT) { + krb5_kvno fail_auth_count; + + fail_auth_count = entry->fail_auth_count; + if (entry->mask & KADM5_FAIL_AUTH_COUNT_INCREMENT) + fail_auth_count++; + + st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", + LDAP_MOD_REPLACE, + fail_auth_count); + if (st != 0) + goto cleanup; + } else if (entry->mask & KADM5_FAIL_AUTH_COUNT_INCREMENT) { + int attr_mask = 0; + krb5_boolean has_fail_count; + + /* Check if the krbLoginFailedCount attribute exists. (Through + * krb5 1.8.1, it wasn't set in new entries.) */ + st = krb5_get_attributes_mask(context, entry, &attr_mask); + if (st != 0) + goto cleanup; + has_fail_count = ((attr_mask & KDB_FAIL_AUTH_COUNT_ATTR) != 0); + + /* + * If the client library and server supports RFC 4525, + * then use it to increment by one the value of the + * krbLoginFailedCount attribute. Otherwise, assert the + * (provided) old value by deleting it before adding. + */ +#ifdef LDAP_MOD_INCREMENT + if (ldap_server_handle->server_info->modify_increment && + has_fail_count) { + st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", + LDAP_MOD_INCREMENT, 1); + if (st != 0) + goto cleanup; + } else { +#endif /* LDAP_MOD_INCREMENT */ + if (has_fail_count) { + st = krb5_add_int_mem_ldap_mod(&mods, + "krbLoginFailedCount", + LDAP_MOD_DELETE, + entry->fail_auth_count); + if (st != 0) + goto cleanup; + } + st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", + LDAP_MOD_ADD, + entry->fail_auth_count + 1); + if (st != 0) + goto cleanup; +#ifdef LDAP_MOD_INCREMENT + } +#endif + } else if (optype == ADD_PRINCIPAL) { + /* Initialize krbLoginFailedCount in new entries to help avoid a + * race during the first failed login. */ + st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount", + LDAP_MOD_ADD, 0); + } + + if (entry->mask & KADM5_MAX_LIFE) { + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_REPLACE, entry->max_life)) != 0) + goto cleanup; + } + + if (entry->mask & KADM5_MAX_RLIFE) { + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_REPLACE, + entry->max_renewable_life)) != 0) + goto cleanup; + } + + if (entry->mask & KADM5_ATTRIBUTES) { + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_REPLACE, + entry->attributes)) != 0) + goto cleanup; + } + + if (entry->mask & KADM5_PRINCIPAL) { + memset(strval, 0, sizeof(strval)); + strval[0] = user; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_REPLACE, strval)) != 0) + goto cleanup; + } + + if (entry->mask & KADM5_PRINC_EXPIRE_TIME) { + memset(strval, 0, sizeof(strval)); + if ((strval[0]=getstringtime(entry->expiration)) == NULL) + goto cleanup; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalexpiration", LDAP_MOD_REPLACE, strval)) != 0) { + free (strval[0]); + goto cleanup; + } + free (strval[0]); + } + + if (entry->mask & KADM5_PW_EXPIRATION) { + memset(strval, 0, sizeof(strval)); + if ((strval[0]=getstringtime(entry->pw_expiration)) == NULL) + goto cleanup; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpasswordexpiration", + LDAP_MOD_REPLACE, + strval)) != 0) { + free (strval[0]); + goto cleanup; + } + free (strval[0]); + } + + if (entry->mask & KADM5_POLICY || entry->mask & KADM5_KEY_HIST) { + memset(&princ_ent, 0, sizeof(princ_ent)); + for (tl_data=entry->tl_data; tl_data; tl_data=tl_data->tl_data_next) { + if (tl_data->tl_data_type == KRB5_TL_KADM_DATA) { + if ((st = krb5_lookup_tl_kadm_data(tl_data, &princ_ent)) != 0) { + goto cleanup; + } + break; + } + } + } + + if (entry->mask & KADM5_POLICY) { + if (princ_ent.aux_attributes & KADM5_POLICY) { + memset(strval, 0, sizeof(strval)); + if ((st = krb5_ldap_name_to_policydn (context, princ_ent.policy, &polname)) != 0) + goto cleanup; + strval[0] = polname; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, strval)) != 0) + goto cleanup; + } else { + st = EINVAL; + k5_setmsg(context, st, "Password policy value null"); + goto cleanup; + } + } else if (entry->mask & KADM5_LOAD && found_entry == TRUE) { + /* + * a load is special in that existing entries must have attrs that + * removed. + */ + + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, NULL)) != 0) + goto cleanup; + } + + if (entry->mask & KADM5_POLICY_CLR) { + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_DELETE, NULL)) != 0) + goto cleanup; + } + + if (entry->mask & KADM5_KEY_HIST) { + bersecretkey = krb5_encode_histkey(&princ_ent); + if (bersecretkey == NULL) { + st = ENOMEM; + goto cleanup; + } + + st = krb5_add_ber_mem_ldap_mod(&mods, "krbpwdhistory", + LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, + bersecretkey); + if (st != 0) + goto cleanup; + free_berdata(bersecretkey); + bersecretkey = NULL; + } + + if (entry->mask & KADM5_KEY_DATA || entry->mask & KADM5_KVNO) { + krb5_kvno mkvno; + + if ((st=krb5_dbe_lookup_mkvno(context, entry, &mkvno)) != 0) + goto cleanup; + bersecretkey = krb5_encode_krbsecretkey (entry->key_data, + entry->n_key_data, mkvno); + + if (bersecretkey == NULL) { + st = ENOMEM; + goto cleanup; + } + /* An empty list of bervals is only accepted for modify operations, + * not add operations. */ + if (bersecretkey[0] != NULL || !create_standalone) { + st = krb5_add_ber_mem_ldap_mod(&mods, "krbprincipalkey", + LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, + bersecretkey); + if (st != 0) + goto cleanup; + } + + /* Update last password change whenever a new key is set */ + { + krb5_timestamp last_pw_changed; + if ((st=krb5_dbe_lookup_last_pwd_change(context, entry, + &last_pw_changed)) != 0) + goto cleanup; + + memset(strval, 0, sizeof(strval)); + if ((strval[0] = getstringtime(last_pw_changed)) == NULL) + goto cleanup; + + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastPwdChange", + LDAP_MOD_REPLACE, strval)) != 0) { + free (strval[0]); + goto cleanup; + } + free (strval[0]); + } + + } /* Modify Key data ends here */ + + /* Set tl_data */ + if (entry->tl_data != NULL) { + int count = 0; + struct berval **ber_tl_data = NULL; + krb5_tl_data *ptr; + krb5_timestamp unlock_time; + + /* Normalize required auth indicators, but also store them as string + * attributes within krbExtraData. */ + st = update_ldap_mod_auth_ind(context, entry, &mods); + if (st != 0) + goto cleanup; + + for (ptr = entry->tl_data; ptr != NULL; ptr = ptr->tl_data_next) { + if (ptr->tl_data_type == KRB5_TL_LAST_PWD_CHANGE +#ifdef SECURID + || ptr->tl_data_type == KRB5_TL_DB_ARGS +#endif + || ptr->tl_data_type == KRB5_TL_KADM_DATA + || ptr->tl_data_type == KDB_TL_USER_INFO + || ptr->tl_data_type == KRB5_TL_CONSTRAINED_DELEGATION_ACL + || ptr->tl_data_type == KRB5_TL_LAST_ADMIN_UNLOCK) + continue; + count++; + } + if (count != 0) { + int j; + ber_tl_data = (struct berval **) calloc (count + 1, + sizeof (struct berval*)); + if (ber_tl_data == NULL) { + st = ENOMEM; + goto cleanup; + } + for (j = 0, ptr = entry->tl_data; ptr != NULL; ptr = ptr->tl_data_next) { + /* Ignore tl_data that are stored in separate directory + * attributes */ + if (ptr->tl_data_type == KRB5_TL_LAST_PWD_CHANGE +#ifdef SECURID + || ptr->tl_data_type == KRB5_TL_DB_ARGS +#endif + || ptr->tl_data_type == KRB5_TL_KADM_DATA + || ptr->tl_data_type == KDB_TL_USER_INFO + || ptr->tl_data_type == KRB5_TL_CONSTRAINED_DELEGATION_ACL + || ptr->tl_data_type == KRB5_TL_LAST_ADMIN_UNLOCK) + continue; + if ((st = tl_data2berval (ptr, &ber_tl_data[j])) != 0) + break; + j++; + } + if (st == 0) { + ber_tl_data[count] = NULL; + st=krb5_add_ber_mem_ldap_mod(&mods, "krbExtraData", + LDAP_MOD_REPLACE | + LDAP_MOD_BVALUES, ber_tl_data); + } + free_berdata(ber_tl_data); + if (st != 0) + goto cleanup; + } + if ((st=krb5_dbe_lookup_last_admin_unlock(context, entry, + &unlock_time)) != 0) + goto cleanup; + if (unlock_time != 0) { + /* Update last admin unlock */ + memset(strval, 0, sizeof(strval)); + if ((strval[0] = getstringtime(unlock_time)) == NULL) + goto cleanup; + + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastAdminUnlock", + LDAP_MOD_REPLACE, strval)) != 0) { + free (strval[0]); + goto cleanup; + } + free (strval[0]); + } + } + + /* Directory specific attribute */ + if (xargs.tktpolicydn != NULL) { + int tmask=0; + + if (strlen(xargs.tktpolicydn) != 0) { + st = checkattributevalue(ld, xargs.tktpolicydn, "objectclass", policyclass, &tmask); + CHECK_CLASS_VALIDITY(st, tmask, _("ticket policy object value: ")); + + strval[0] = xargs.tktpolicydn; + strval[1] = NULL; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_REPLACE, strval)) != 0) + goto cleanup; + + } else { + /* if xargs.tktpolicydn is a empty string, then delete + * already existing krbticketpolicyreference attr */ + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_DELETE, NULL)) != 0) + goto cleanup; + } + + } + + if (establish_links == TRUE) { + memset(strval, 0, sizeof(strval)); + strval[0] = xargs.linkdn; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbObjectReferences", LDAP_MOD_REPLACE, strval)) != 0) + goto cleanup; + } + + /* + * in case mods is NULL then return + * not sure but can happen in a modprinc + * so no need to return an error + * addprinc will at least have the principal name + * and the keys passed in + */ + if (mods == NULL) + goto cleanup; + + if (create_standalone == TRUE) { + memset(strval, 0, sizeof(strval)); + strval[0] = "krbprincipal"; + strval[1] = "krbprincipalaux"; + strval[2] = "krbTicketPolicyAux"; + + if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) + goto cleanup; + + st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL); + if (st == LDAP_ALREADY_EXISTS && entry->mask & KADM5_LOAD) { + /* a load operation must replace an existing entry */ + st = ldap_delete_ext_s(ld, standalone_principal_dn, NULL, NULL); + if (st != LDAP_SUCCESS) { + snprintf(errbuf, sizeof(errbuf), + _("Principal delete failed (trying to replace " + "entry): %s"), ldap_err2string(st)); + st = translate_ldap_error (st, OP_ADD); + k5_setmsg(context, st, "%s", errbuf); + goto cleanup; + } else { + st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL); + } + } + if (st != LDAP_SUCCESS) { + snprintf(errbuf, sizeof(errbuf), _("Principal add failed: %s"), + ldap_err2string(st)); + st = translate_ldap_error (st, OP_ADD); + k5_setmsg(context, st, "%s", errbuf); + goto cleanup; + } + } else { + /* + * Here existing ldap object is modified and can be related + * to any attribute, so always ensure that the ldap + * object is extended with all the kerberos related + * objectclasses so that there are no constraint + * violations. + */ + { + char *attrvalues[] = {"krbprincipalaux", "krbTicketPolicyAux", NULL}; + int p, q, r=0, amask=0; + + if ((st=checkattributevalue(ld, (xargs.dn) ? xargs.dn : principal_dn, + "objectclass", attrvalues, &amask)) != 0) + goto cleanup; + + memset(strval, 0, sizeof(strval)); + for (p=1, q=0; p<=2; p<<=1, ++q) { + if ((p & amask) == 0) + strval[r++] = attrvalues[q]; + } + if (r != 0) { + if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) + goto cleanup; + } + } + if (xargs.dn != NULL) + st=ldap_modify_ext_s(ld, xargs.dn, mods, NULL, NULL); + else + st = ldap_modify_ext_s(ld, principal_dn, mods, NULL, NULL); + + if (st != LDAP_SUCCESS) { + snprintf(errbuf, sizeof(errbuf), _("User modification failed: %s"), + ldap_err2string(st)); + st = translate_ldap_error (st, OP_MOD); + k5_setmsg(context, st, "%s", errbuf); + goto cleanup; + } + + if (entry->mask & KADM5_FAIL_AUTH_COUNT_INCREMENT) + entry->fail_auth_count++; + } + +cleanup: + free(filter); + if (user) + free(user); + + if (filtuser) + free(filtuser); + + free_xargs(xargs); + + if (standalone_principal_dn) + free(standalone_principal_dn); + + if (principal_dn) + free (principal_dn); + + if (polname != NULL) + free(polname); + + for (tre = 0; tre < ntrees; tre++) + free(subtreelist[tre]); + free(subtreelist); + + if (subtree) + free (subtree); + + if (bersecretkey) { + for (l=0; bersecretkey[l]; ++l) { + if (bersecretkey[l]->bv_val) + free (bersecretkey[l]->bv_val); + free (bersecretkey[l]); + } + free (bersecretkey); + } + + if (keys) + free (keys); + + ldap_mods_free(mods, 1); + ldap_osa_free_princ_ent(&princ_ent); + ldap_msgfree(result); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return(st); +} + +krb5_error_code +krb5_read_tkt_policy(krb5_context context, krb5_ldap_context *ldap_context, + krb5_db_entry *entries, char *policy) +{ + krb5_error_code st=0; + int mask=0, omask=0; + int tkt_mask=(KDB_MAX_LIFE_ATTR | KDB_MAX_RLIFE_ATTR | KDB_TKT_FLAGS_ATTR); + krb5_ldap_policy_params *tktpoldnparam=NULL; + + if ((st=krb5_get_attributes_mask(context, entries, &mask)) != 0) + goto cleanup; + + if ((mask & tkt_mask) == tkt_mask) + goto cleanup; + + if (policy != NULL) { + st = krb5_ldap_read_policy(context, policy, &tktpoldnparam, &omask); + if (st && st != KRB5_KDB_NOENTRY) { + k5_prependmsg(context, st, _("Error reading ticket policy")); + goto cleanup; + } + + st = 0; /* reset the return status */ + } + + if ((mask & KDB_MAX_LIFE_ATTR) == 0) { + if ((omask & KDB_MAX_LIFE_ATTR) == KDB_MAX_LIFE_ATTR) + entries->max_life = tktpoldnparam->maxtktlife; + else if (ldap_context->lrparams->max_life) + entries->max_life = ldap_context->lrparams->max_life; + } + + if ((mask & KDB_MAX_RLIFE_ATTR) == 0) { + if ((omask & KDB_MAX_RLIFE_ATTR) == KDB_MAX_RLIFE_ATTR) + entries->max_renewable_life = tktpoldnparam->maxrenewlife; + else if (ldap_context->lrparams->max_renewable_life) + entries->max_renewable_life = ldap_context->lrparams->max_renewable_life; + } + + if ((mask & KDB_TKT_FLAGS_ATTR) == 0) { + if ((omask & KDB_TKT_FLAGS_ATTR) == KDB_TKT_FLAGS_ATTR) + entries->attributes = tktpoldnparam->tktflags; + else if (ldap_context->lrparams->tktflags) + entries->attributes |= ldap_context->lrparams->tktflags; + } + krb5_ldap_free_policy(context, tktpoldnparam); + +cleanup: + return st; +} + +static void +free_ldap_seqof_key_data(ldap_seqof_key_data *keysets, krb5_int16 n_keysets) +{ + int i; + + if (keysets == NULL) + return; + + for (i = 0; i < n_keysets; i++) + k5_free_key_data(keysets[i].n_key_data, keysets[i].key_data); + free(keysets); +} + +/* + * Decode keys from ldap search results. + * + * Arguments: + * - bvalues + * The ldap search results containing the key data. + * - mkvno + * The master kvno that the keys were encrypted with. + * - keysets_out + * The decoded keys in a ldap_seqof_key_data struct. Must be freed using + * free_ldap_seqof_key_data. + * - n_keysets_out + * The number of entries in keys_out. + * - total_keys_out + * An optional argument that if given will be set to the total number of + * keys found throughout all the entries: sum(keys_out.n_key_data) + * May be NULL. + */ +static krb5_error_code +decode_keys(struct berval **bvalues, ldap_seqof_key_data **keysets_out, + krb5_int16 *n_keysets_out, krb5_int16 *total_keys_out) +{ + krb5_error_code err = 0; + krb5_int16 n_keys, i, ki, total_keys; + ldap_seqof_key_data *keysets = NULL; + + *keysets_out = NULL; + *n_keysets_out = 0; + if (total_keys_out) + *total_keys_out = 0; + + /* Precount the number of keys. */ + for (n_keys = 0, i = 0; bvalues[i] != NULL; i++) { + if (bvalues[i]->bv_len > 0) + n_keys++; + } + + keysets = k5calloc(n_keys, sizeof(ldap_seqof_key_data), &err); + if (keysets == NULL) + goto cleanup; + memset(keysets, 0, n_keys * sizeof(ldap_seqof_key_data)); + + for (i = 0, ki = 0, total_keys = 0; bvalues[i] != NULL; i++) { + krb5_data in; + + if (bvalues[i]->bv_len == 0) + continue; + in.length = bvalues[i]->bv_len; + in.data = bvalues[i]->bv_val; + + err = asn1_decode_sequence_of_keys(&in, &keysets[ki]); + if (err) + goto cleanup; + + if (total_keys_out) + total_keys += keysets[ki].n_key_data; + ki++; + } + + if (total_keys_out) + *total_keys_out = total_keys; + + *n_keysets_out = n_keys; + *keysets_out = keysets; + keysets = NULL; + n_keys = 0; + +cleanup: + free_ldap_seqof_key_data(keysets, n_keys); + return err; +} + +krb5_error_code +krb5_decode_krbsecretkey(krb5_context context, krb5_db_entry *entries, + struct berval **bvalues, krb5_kvno *mkvno) +{ + krb5_key_data *key_data = NULL, *tmp; + krb5_error_code err = 0; + ldap_seqof_key_data *keysets = NULL; + krb5_int16 i, n_keysets = 0, total_keys = 0; + + err = decode_keys(bvalues, &keysets, &n_keysets, &total_keys); + if (err != 0) { + k5_prependmsg(context, err, + _("unable to decode stored principal key data")); + goto cleanup; + } + + key_data = k5calloc(total_keys, sizeof(krb5_key_data), &err); + if (key_data == NULL) + goto cleanup; + memset(key_data, 0, total_keys * sizeof(krb5_key_data)); + + if (n_keysets > 0) + *mkvno = keysets[0].mkvno; + + /* Transfer key data values from keysets to a flat list in entries. */ + tmp = key_data; + for (i = 0; i < n_keysets; i++) { + memcpy(tmp, keysets[i].key_data, + sizeof(krb5_key_data) * keysets[i].n_key_data); + tmp += keysets[i].n_key_data; + keysets[i].n_key_data = 0; + } + entries->n_key_data = total_keys; + entries->key_data = key_data; + key_data = NULL; + +cleanup: + free_ldap_seqof_key_data(keysets, n_keysets); + k5_free_key_data(total_keys, key_data); + return err; +} + +static int +compare_osa_pw_hist_ent(const void *left_in, const void *right_in) +{ + int kvno_left, kvno_right; + osa_pw_hist_ent *left = (osa_pw_hist_ent *)left_in; + osa_pw_hist_ent *right = (osa_pw_hist_ent *)right_in; + + kvno_left = left->n_key_data ? left->key_data[0].key_data_kvno : 0; + kvno_right = right->n_key_data ? right->key_data[0].key_data_kvno : 0; + return kvno_left - kvno_right; +} + +/* + * Decode the key history entries from an LDAP search. + * + * NOTE: the caller must free princ_ent->old_keys even on error. + */ +krb5_error_code +krb5_decode_histkey(krb5_context context, struct berval **bvalues, + osa_princ_ent_rec *princ_ent) +{ + krb5_error_code err = 0; + krb5_int16 i, n_keysets = 0; + ldap_seqof_key_data *keysets = NULL; + + err = decode_keys(bvalues, &keysets, &n_keysets, NULL); + if (err != 0) { + k5_prependmsg(context, err, + _("unable to decode stored principal pw history")); + goto cleanup; + } + + princ_ent->old_keys = k5calloc(n_keysets, sizeof(osa_pw_hist_ent), &err); + if (princ_ent->old_keys == NULL) + goto cleanup; + princ_ent->old_key_len = n_keysets; + + if (n_keysets > 0) + princ_ent->admin_history_kvno = keysets[0].mkvno; + + /* Transfer key data pointers from keysets to princ_ent. */ + for (i = 0; i < n_keysets; i++) { + princ_ent->old_keys[i].n_key_data = keysets[i].n_key_data; + princ_ent->old_keys[i].key_data = keysets[i].key_data; + keysets[i].n_key_data = 0; + keysets[i].key_data = NULL; + } + + /* Sort the principal entries by kvno in ascending order. */ + qsort(princ_ent->old_keys, princ_ent->old_key_len, sizeof(osa_pw_hist_ent), + &compare_osa_pw_hist_ent); + + princ_ent->aux_attributes |= KADM5_KEY_HIST; + + /* Set the next key to the end of the list. The queue will be lengthened + * if it isn't full yet; the first entry will be replaced if it is full. */ + princ_ent->old_key_next = princ_ent->old_key_len; + +cleanup: + free_ldap_seqof_key_data(keysets, n_keysets); + return err; +} + +static char * +getstringtime(krb5_timestamp epochtime) +{ + struct tm tme; + char *strtime=NULL; + time_t posixtime = ts2tt(epochtime); + + if (gmtime_r(&posixtime, &tme) == NULL) + return NULL; + + strtime = calloc(50, 1); + if (strtime == NULL) + return NULL; + if (strftime(strtime, 50, "%Y%m%d%H%M%SZ", &tme) == 0) { + free(strtime); + return NULL; + } + return strtime; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c new file mode 100644 index 00000000..838583a1 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c @@ -0,0 +1,469 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.c */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include "ldap_main.h" +#include "kdb_ldap.h" +#include "ldap_pwd_policy.h" +#include "ldap_err.h" + +static char *password_policy_attributes[] = { "cn", "krbmaxpwdlife", "krbminpwdlife", + "krbpwdmindiffchars", "krbpwdminlength", + "krbpwdhistorylength", "krbpwdmaxfailure", + "krbpwdfailurecountinterval", + "krbpwdlockoutduration", + "krbpwdattributes", + "krbpwdmaxlife", + "krbpwdmaxrenewablelife", + "krbpwdallowedkeysalts", NULL }; + +/* Fill in mods with LDAP operations for the fields of policy, using the + * modification type op. mods must be freed by the caller on error. */ +static krb5_error_code +add_policy_mods(krb5_context context, LDAPMod ***mods, osa_policy_ent_t policy, + int op) +{ + krb5_error_code st; + char *strval[2] = { NULL }; + + st = krb5_add_int_mem_ldap_mod(mods, "krbmaxpwdlife", op, + (int)policy->pw_max_life); + if (st) + return st; + + st = krb5_add_int_mem_ldap_mod(mods, "krbminpwdlife", op, + (int)policy->pw_min_life); + if (st) + return st; + + st = krb5_add_int_mem_ldap_mod(mods, "krbpwdmindiffchars", op, + (int)policy->pw_min_classes); + if (st) + return st; + + st = krb5_add_int_mem_ldap_mod(mods, "krbpwdminlength", op, + (int)policy->pw_min_length); + if (st) + return st; + + st = krb5_add_int_mem_ldap_mod(mods, "krbpwdhistorylength", op, + (int)policy->pw_history_num); + if (st) + return st; + + st = krb5_add_int_mem_ldap_mod(mods, "krbpwdmaxfailure", op, + (int)policy->pw_max_fail); + if (st) + return st; + + st = krb5_add_int_mem_ldap_mod(mods, "krbpwdfailurecountinterval", op, + (int)policy->pw_failcnt_interval); + if (st) + return st; + + st = krb5_add_int_mem_ldap_mod(mods, "krbpwdlockoutduration", op, + (int)policy->pw_lockout_duration); + if (st) + return st; + + st = krb5_add_int_mem_ldap_mod(mods, "krbpwdattributes", op, + (int)policy->attributes); + if (st) + return st; + + st = krb5_add_int_mem_ldap_mod(mods, "krbpwdmaxlife", op, + (int)policy->max_life); + if (st) + return st; + + st = krb5_add_int_mem_ldap_mod(mods, "krbpwdmaxrenewablelife", op, + (int)policy->max_renewable_life); + if (st) + return st; + + if (policy->allowed_keysalts != NULL) { + strval[0] = policy->allowed_keysalts; + st = krb5_add_str_mem_ldap_mod(mods, "krbpwdallowedkeysalts", + op, strval); + if (st) + return st; + } + + /* + * Each policy tl-data type we add should be explicitly marshalled here. + * Unlike principals, we do not marshal unrecognized policy tl-data. + */ + + return 0; +} + +/* + * Function to create password policy object. + */ + +krb5_error_code +krb5_ldap_create_password_policy(krb5_context context, osa_policy_ent_t policy) +{ + krb5_error_code st=0; + LDAP *ld=NULL; + LDAPMod **mods={NULL}; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + char *strval[2]={NULL}, *policy_dn=NULL; + + /* Clear the global error string */ + krb5_clear_error_message(context); + + /* validate the input parameters */ + if (policy == NULL || policy->name == NULL) + return EINVAL; + + SETUP_CONTEXT(); + GET_HANDLE(); + + st = krb5_ldap_name_to_policydn (context, policy->name, &policy_dn); + if (st != 0) + goto cleanup; + + strval[0] = policy->name; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0) + goto cleanup; + + strval[0] = "krbPwdPolicy"; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) + goto cleanup; + + st = add_policy_mods(context, &mods, policy, LDAP_MOD_ADD); + if (st) + goto cleanup; + + /* password policy object creation */ + if ((st=ldap_add_ext_s(ld, policy_dn, mods, NULL, NULL)) != LDAP_SUCCESS) { + st = set_ldap_error (context, st, OP_ADD); + goto cleanup; + } + +cleanup: + free(policy_dn); + ldap_mods_free(mods, 1); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return(st); +} + +/* + * Function to modify password policy object. + */ + +krb5_error_code +krb5_ldap_put_password_policy(krb5_context context, osa_policy_ent_t policy) +{ + char *policy_dn=NULL; + krb5_error_code st=0; + LDAP *ld=NULL; + LDAPMod **mods=NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + + /* Clear the global error string */ + krb5_clear_error_message(context); + + /* validate the input parameters */ + if (policy == NULL || policy->name == NULL) + return EINVAL; + + SETUP_CONTEXT(); + GET_HANDLE(); + + st = krb5_ldap_name_to_policydn (context, policy->name, &policy_dn); + if (st != 0) + goto cleanup; + + st = add_policy_mods(context, &mods, policy, LDAP_MOD_REPLACE); + if (st) + goto cleanup; + + /* modify the password policy object. */ + /* + * This will fail if the 'policy_dn' is anywhere other than under the realm + * container. This is correct behaviour. 'kdb5_ldap_util' will support + * management of only such policy objects. + */ + if ((st=ldap_modify_ext_s(ld, policy_dn, mods, NULL, NULL)) != LDAP_SUCCESS) { + st = set_ldap_error (context, st, OP_MOD); + goto cleanup; + } + +cleanup: + free(policy_dn); + ldap_mods_free(mods, 1); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return(st); +} + +static void +get_ui4(LDAP *ld, LDAPMessage *ent, char *name, krb5_ui_4 *out) +{ + int val; + + krb5_ldap_get_value(ld, ent, name, &val); + *out = val; +} + +static krb5_error_code +populate_policy(krb5_context context, + LDAP *ld, + LDAPMessage *ent, + char *pol_name, + osa_policy_ent_t pol_entry) +{ + int st = 0; + + pol_entry->name = strdup(pol_name); + CHECK_NULL(pol_entry->name); + pol_entry->version = 1; + + get_ui4(ld, ent, "krbmaxpwdlife", &pol_entry->pw_max_life); + get_ui4(ld, ent, "krbminpwdlife", &pol_entry->pw_min_life); + get_ui4(ld, ent, "krbpwdmindiffchars", &pol_entry->pw_min_classes); + get_ui4(ld, ent, "krbpwdminlength", &pol_entry->pw_min_length); + get_ui4(ld, ent, "krbpwdhistorylength", &pol_entry->pw_history_num); + get_ui4(ld, ent, "krbpwdmaxfailure", &pol_entry->pw_max_fail); + get_ui4(ld, ent, "krbpwdfailurecountinterval", + &pol_entry->pw_failcnt_interval); + get_ui4(ld, ent, "krbpwdlockoutduration", &pol_entry->pw_lockout_duration); + get_ui4(ld, ent, "krbpwdattributes", &pol_entry->attributes); + get_ui4(ld, ent, "krbpwdmaxlife", &pol_entry->max_life); + get_ui4(ld, ent, "krbpwdmaxrenewablelife", &pol_entry->max_renewable_life); + + st = krb5_ldap_get_string(ld, ent, "krbpwdallowedkeysalts", + &(pol_entry->allowed_keysalts), NULL); + if (st) + goto cleanup; + /* + * We don't store the policy refcnt, because principals might be maintained + * outside of kadmin. Instead, we will check for principal references when + * policies are deleted. + */ + pol_entry->policy_refcnt = 0; + +cleanup: + return st; +} + +static krb5_error_code +krb5_ldap_get_password_policy_from_dn(krb5_context context, char *pol_name, + char *pol_dn, osa_policy_ent_t *policy) +{ + krb5_error_code st=0, tempst=0; + LDAP *ld=NULL; + LDAPMessage *result=NULL,*ent=NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + + /* Clear the global error string */ + krb5_clear_error_message(context); + + /* validate the input parameters */ + if (pol_dn == NULL) + return EINVAL; + + *policy = NULL; + SETUP_CONTEXT(); + GET_HANDLE(); + + *(policy) = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec)); + if (*policy == NULL) { + st = ENOMEM; + goto cleanup; + } + memset(*policy, 0, sizeof(osa_policy_ent_rec)); + + LDAP_SEARCH(pol_dn, LDAP_SCOPE_BASE, "(objectclass=krbPwdPolicy)", password_policy_attributes); + + ent=ldap_first_entry(ld, result); + if (ent == NULL) { + st = KRB5_KDB_NOENTRY; + goto cleanup; + } + st = populate_policy(context, ld, ent, pol_name, *policy); + +cleanup: + ldap_msgfree(result); + if (st != 0) { + if (*policy != NULL) { + krb5_db_free_policy(context, *policy); + *policy = NULL; + } + } + + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + +/* + * Convert 'name' into a directory DN and call + * 'krb5_ldap_get_password_policy_from_dn' + */ +krb5_error_code +krb5_ldap_get_password_policy(krb5_context context, char *name, + osa_policy_ent_t *policy) +{ + krb5_error_code st = 0; + char *policy_dn = NULL; + + /* Clear the global error string */ + krb5_clear_error_message(context); + + /* validate the input parameters */ + if (name == NULL) { + st = EINVAL; + goto cleanup; + } + + st = krb5_ldap_name_to_policydn(context, name, &policy_dn); + if (st != 0) + goto cleanup; + + st = krb5_ldap_get_password_policy_from_dn(context, name, policy_dn, + policy); + +cleanup: + free(policy_dn); + return st; +} + +krb5_error_code +krb5_ldap_delete_password_policy(krb5_context context, char *policy) +{ + int mask = 0; + char *policy_dn = NULL, *class[] = {"krbpwdpolicy", NULL}; + krb5_error_code st=0; + LDAP *ld=NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + + /* Clear the global error string */ + krb5_clear_error_message(context); + + /* validate the input parameters */ + if (policy == NULL) + return EINVAL; + + SETUP_CONTEXT(); + GET_HANDLE(); + + st = krb5_ldap_name_to_policydn (context, policy, &policy_dn); + if (st != 0) + goto cleanup; + + /* Ensure that the object is a password policy */ + if ((st=checkattributevalue(ld, policy_dn, "objectclass", class, &mask)) != 0) + goto cleanup; + + if (mask == 0) { + st = KRB5_KDB_NOENTRY; + goto cleanup; + } + + if ((st=ldap_delete_ext_s(ld, policy_dn, NULL, NULL)) != LDAP_SUCCESS) { + st = set_ldap_error (context, st, OP_DEL); + goto cleanup; + } + +cleanup: + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + free(policy_dn); + + return st; +} + +krb5_error_code +krb5_ldap_iterate_password_policy(krb5_context context, char *match_expr, + void (*func)(krb5_pointer, osa_policy_ent_t), + krb5_pointer func_arg) +{ + osa_policy_ent_rec *entry=NULL; + char *policy=NULL; + krb5_error_code st=0, tempst=0; + LDAP *ld=NULL; + LDAPMessage *result=NULL, *ent=NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + + /* Clear the global error string */ + krb5_clear_error_message(context); + + SETUP_CONTEXT(); + GET_HANDLE(); + + if (ldap_context->lrparams->realmdn == NULL) { + st = EINVAL; + goto cleanup; + } + + LDAP_SEARCH(ldap_context->lrparams->realmdn, LDAP_SCOPE_ONELEVEL, "(objectclass=krbpwdpolicy)", password_policy_attributes); + for (ent=ldap_first_entry(ld, result); ent != NULL; ent=ldap_next_entry(ld, ent)) { + krb5_boolean attr_present; + + st = krb5_ldap_get_string(ld, ent, "cn", &policy, &attr_present); + if (st != 0) + goto cleanup; + if (attr_present == FALSE) + continue; + + entry = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec)); + CHECK_NULL(entry); + memset(entry, 0, sizeof(osa_policy_ent_rec)); + if ((st = populate_policy(context, ld, ent, policy, entry)) != 0) + goto cleanup; + + (*func)(func_arg, entry); + krb5_db_free_policy(context, entry); + entry = NULL; + + free(policy); + policy = NULL; + } + +cleanup: + free(entry); + free(policy); + ldap_msgfree(result); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h new file mode 100644 index 00000000..81c56596 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h @@ -0,0 +1,51 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_pwd_policy.h */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#ifndef _LDAP_KRBPWDPOLICY_H_ +#define _LDAP_KRBPWDPOLICY_H_ + +krb5_error_code +krb5_ldap_get_password_policy(krb5_context, char *, osa_policy_ent_t *); + +krb5_error_code +krb5_ldap_create_password_policy(krb5_context, osa_policy_ent_t); + +krb5_error_code +krb5_ldap_put_password_policy(krb5_context kcontext, osa_policy_ent_t policy); + +krb5_error_code +krb5_ldap_delete_password_policy (krb5_context kcontext, char *policy); + +krb5_error_code +krb5_ldap_iterate_password_policy(krb5_context, char *, + void (*)(krb5_pointer, osa_policy_ent_t), + krb5_pointer); + +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c new file mode 100644 index 00000000..753929b0 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c @@ -0,0 +1,926 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_realm.c */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#include "ldap_main.h" +#include "ldap_realm.h" +#include "ldap_principal.h" +#include "ldap_pwd_policy.h" +#include "ldap_err.h" + +#define END_OF_LIST -1 +char *realm_attributes[] = {"krbSearchScope","krbSubTrees", "krbPrincContainerRef", + "krbMaxTicketLife", "krbMaxRenewableAge", + "krbTicketFlags", "krbUpEnabled", + "krbLdapServers", + "krbKdcServers", "krbAdmServers", + "krbPwdServers", NULL}; + + +char *policy_attributes[] = { "krbMaxTicketLife", + "krbMaxRenewableAge", + "krbTicketFlags", + NULL }; + + + +char *policyclass[] = { "krbTicketPolicy", NULL }; +char *kdcclass[] = { "krbKdcService", NULL }; +char *adminclass[] = { "krbAdmService", NULL }; +char *pwdclass[] = { "krbPwdService", NULL }; +char *subtreeclass[] = { "Organization", "OrganizationalUnit", "Domain", "krbContainer", + "krbRealmContainer", "Country", "Locality", NULL }; + + +char *krbContainerRefclass[] = { "krbContainerRefAux", NULL}; + +/* + * list realms from eDirectory + */ + +/* Return a copy of in, quoting all characters which are special in an LDAP + * filter (RFC 4515) or DN string (RFC 4514). Return NULL on failure. */ +char * +ldap_filter_correct (char *in) +{ + size_t count; + const char special[] = "*()\\ #\"+,;<>"; + struct k5buf buf; + + k5_buf_init_dynamic(&buf); + while (TRUE) { + count = strcspn(in, special); + k5_buf_add_len(&buf, in, count); + in += count; + if (*in == '\0') + break; + k5_buf_add_fmt(&buf, "\\%2x", (unsigned char)*in++); + } + return k5_buf_cstring(&buf); +} + +static int +principal_in_realm_2(krb5_principal principal, char *realm) { + /* Cross realm trust ... */ + if (principal->length == 2 && + principal->data[0].length == sizeof ("krbtgt") && + strncasecmp (principal->data[0].data, "krbtgt", sizeof ("krbtgt")) && + principal->data[1].length == strlen (realm) && + strncasecmp (principal->data[1].data, realm, strlen (realm))) + return 0; + + if (strlen(realm) != principal->realm.length) + return 1; + + if (strncasecmp(realm, principal->realm.data, principal->realm.length) != 0) + return 1; + + return 0; +} + +/* + * Lists the realms in the Directory. + */ + +krb5_error_code +krb5_ldap_list_realm(krb5_context context, char ***realms) +{ + char **values = NULL; + unsigned int i = 0; + int count = 0; + krb5_error_code st = 0, tempst = 0; + LDAP *ld = NULL; + LDAPMessage *result = NULL, *ent = NULL; + kdb5_dal_handle *dal_handle = NULL; + krb5_ldap_context *ldap_context = NULL; + krb5_ldap_server_handle *ldap_server_handle = NULL; + + SETUP_CONTEXT (); + + /* get the kerberos container DN information */ + if (ldap_context->container_dn == NULL) { + if ((st = krb5_ldap_read_krbcontainer_dn(context, + &(ldap_context->container_dn))) != 0) + goto cleanup; + } + + /* get ldap handle */ + GET_HANDLE (); + + { + char *cn[] = {"cn", NULL}; + LDAP_SEARCH(ldap_context->container_dn, + LDAP_SCOPE_ONELEVEL, + "(objectclass=krbRealmContainer)", + cn); + } + + *realms = NULL; + + count = ldap_count_entries (ld, result); + if (count == -1) { + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &st); + st = set_ldap_error (context, st, OP_SEARCH); + goto cleanup; + } + + *realms = calloc((unsigned int) count+1, sizeof (char *)); + CHECK_NULL(*realms); + + for (ent = ldap_first_entry(ld, result), count = 0; ent != NULL; + ent = ldap_next_entry(ld, ent)) { + + if ((values = ldap_get_values (ld, ent, "cn")) != NULL) { + + (*realms)[count] = strdup(values[0]); + CHECK_NULL((*realms)[count]); + count += 1; + + ldap_value_free(values); + } + } /* for (ent= ... */ + +cleanup: + + /* some error, free up all the memory */ + if (st != 0) { + if (*realms) { + for (i=0; (*realms)[i] != NULL; ++i) { + free ((*realms)[i]); + } + free (*realms); + *realms = NULL; + } + } + + /* If there are no elements, still return a NULL terminated array */ + + ldap_msgfree(result); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + +/* + * Delete the realm along with the principals belonging to the realm in the Directory. + */ + +static void +delete_password_policy (krb5_pointer ptr, osa_policy_ent_t pol) +{ + krb5_ldap_delete_password_policy ((krb5_context)ptr, pol->name); +} + +krb5_error_code +krb5_ldap_delete_realm (krb5_context context, char *lrealm) +{ + LDAP *ld = NULL; + krb5_error_code st = 0, tempst=0; + char **values=NULL, **subtrees=NULL, **policy=NULL; + LDAPMessage **result_arr=NULL, *result = NULL, *ent = NULL; + krb5_principal principal; + unsigned int l=0, ntree=0; + int i=0, j=0, mask=0; + kdb5_dal_handle *dal_handle = NULL; + krb5_ldap_context *ldap_context = NULL; + krb5_ldap_server_handle *ldap_server_handle = NULL; + krb5_ldap_realm_params *rparam=NULL; + + SETUP_CONTEXT (); + + if (lrealm == NULL) { + st = EINVAL; + k5_setmsg(context, st, _("Realm information not available")); + goto cleanup; + } + + if ((st=krb5_ldap_read_realm_params(context, lrealm, &rparam, &mask)) != 0) + goto cleanup; + + /* get ldap handle */ + GET_HANDLE (); + + /* delete all the principals belonging to the realm in the tree */ + { + char *attr[] = {"krbprincipalname", NULL}, *realm=NULL, filter[256]; + krb5_ldap_context lcontext; + + realm = ldap_filter_correct (lrealm); + assert (sizeof (filter) >= sizeof ("(krbprincipalname=)") + + strlen (realm) + 2 /* "*@" */ + 1); + + snprintf (filter, sizeof(filter), "(krbprincipalname=*@%s)", realm); + free (realm); + + /* LDAP_SEARCH(NULL, LDAP_SCOPE_SUBTREE, filter, attr); */ + memset(&lcontext, 0, sizeof(krb5_ldap_context)); + lcontext.lrparams = rparam; + if ((st=krb5_get_subtree_info(&lcontext, &subtrees, &ntree)) != 0) + goto cleanup; + + result_arr = (LDAPMessage **) calloc((unsigned int)ntree+1, + sizeof(LDAPMessage *)); + if (result_arr == NULL) { + st = ENOMEM; + goto cleanup; + } + + for (l=0; l < ntree; ++l) { + LDAP_SEARCH(subtrees[l], rparam->search_scope, filter, attr); + result_arr[l] = result; + } + } + + /* NOTE: Here all the principals should be cached and the ldap handle should be freed, + * as a DAL-LDAP interface is called right down here. Caching might be constrained by + * availability of the memory. The caching is not done, however there would be limit + * on the minimum number of handles for a server and it is 2. As the DAL-LDAP is not + * thread-safe this should suffice. + */ + for (j=0; (result=result_arr[j]) != NULL; ++j) { + for (ent = ldap_first_entry (ld, result); ent != NULL; + ent = ldap_next_entry (ld, ent)) { + if ((values = ldap_get_values(ld, ent, "krbPrincipalName")) != NULL) { + for (i = 0; values[i] != NULL; ++i) { + krb5_parse_name(context, values[i], &principal); + if (principal_in_realm_2(principal, lrealm) == 0) { + st=krb5_ldap_delete_principal(context, principal); + if (st && st != KRB5_KDB_NOENTRY) + goto cleanup; + } + krb5_free_principal(context, principal); + } + ldap_value_free(values); + } + } + } + + /* Delete all password policies */ + krb5_ldap_iterate_password_policy (context, "*", delete_password_policy, context); + + /* Delete all ticket policies */ + { + if ((st = krb5_ldap_list_policy (context, ldap_context->lrparams->realmdn, &policy)) != 0) { + k5_prependmsg(context, st, _("Error reading ticket policy")); + goto cleanup; + } + + for (i = 0; policy [i] != NULL; i++) + krb5_ldap_delete_policy(context, policy[i]); + } + + /* Delete the realm object */ + if ((st=ldap_delete_ext_s(ld, ldap_context->lrparams->realmdn, NULL, NULL)) != LDAP_SUCCESS) { + int ost = st; + st = translate_ldap_error (st, OP_DEL); + k5_setmsg(context, st, _("Realm Delete FAILED: %s"), + ldap_err2string(ost)); + } + +cleanup: + if (subtrees) { + for (l=0; l < ntree; ++l) { + if (subtrees[l]) + free (subtrees[l]); + } + free (subtrees); + } + + if (result_arr != NULL) { + for (l = 0; l < ntree; l++) + ldap_msgfree(result_arr[l]); + free(result_arr); + } + + if (policy != NULL) { + for (i = 0; policy[i] != NULL; i++) + free (policy[i]); + free (policy); + } + + krb5_ldap_free_realm_params(rparam); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + + +/* + * Modify the realm attributes in the Directory. + */ + +krb5_error_code +krb5_ldap_modify_realm(krb5_context context, krb5_ldap_realm_params *rparams, + int mask) +{ + LDAP *ld=NULL; + krb5_error_code st=0; + char **strval=NULL, *strvalprc[5]={NULL}; + LDAPMod **mods = NULL; + int objectmask=0,k=0; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + + if (mask == 0) + return 0; + + if (rparams == NULL) { + st = EINVAL; + return st; + } + + SETUP_CONTEXT (); + + /* Check validity of arguments */ + if (ldap_context->container_dn == NULL || + rparams->tl_data == NULL || + rparams->tl_data->tl_data_contents == NULL || + ((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) || + ((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) || + 0) { + st = EINVAL; + goto cleanup; + } + + /* get ldap handle */ + GET_HANDLE (); + + /* SUBTREE ATTRIBUTE */ + if (mask & LDAP_REALM_SUBTREE) { + if ( rparams->subtree!=NULL) { + /*replace the subtrees with the present if the subtrees are present*/ + for(k=0;ksubtreecount && rparams->subtree[k]!=NULL;k++) { + if (strlen(rparams->subtree[k]) != 0) { + st = checkattributevalue(ld, rparams->subtree[k], "Objectclass", subtreeclass, + &objectmask); + CHECK_CLASS_VALIDITY(st, objectmask, _("subtree value: ")); + } + } + strval = rparams->subtree; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_REPLACE, + strval)) != 0) { + goto cleanup; + } + } + } + + /* CONTAINERREF ATTRIBUTE */ + if (mask & LDAP_REALM_CONTREF) { + if (strlen(rparams->containerref) != 0 ) { + st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass, + &objectmask); + CHECK_CLASS_VALIDITY(st, objectmask, + _("container reference value: ")); + strvalprc[0] = rparams->containerref; + strvalprc[1] = NULL; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_REPLACE, + strvalprc)) != 0) + goto cleanup; + } + } + + /* SEARCHSCOPE ATTRIBUTE */ + if (mask & LDAP_REALM_SEARCHSCOPE) { + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_REPLACE, + (rparams->search_scope == LDAP_SCOPE_ONELEVEL + || rparams->search_scope == LDAP_SCOPE_SUBTREE) ? + rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0) + goto cleanup; + } + + if (mask & LDAP_REALM_MAXRENEWLIFE) { + + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_REPLACE, + rparams->max_renewable_life)) != 0) + goto cleanup; + } + + /* krbMaxTicketLife ATTRIBUTE */ + + if (mask & LDAP_REALM_MAXTICKETLIFE) { + + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_REPLACE, + rparams->max_life)) != 0) + goto cleanup; + } + + /* krbTicketFlags ATTRIBUTE */ + + if (mask & LDAP_REALM_KRBTICKETFLAGS) { + + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_REPLACE, + rparams->tktflags)) != 0) + goto cleanup; + } + + + /* Realm modify operation */ + if (mods != NULL) { + if ((st=ldap_modify_ext_s(ld, rparams->realmdn, mods, NULL, NULL)) != LDAP_SUCCESS) { + st = set_ldap_error (context, st, OP_MOD); + goto cleanup; + } + } + +cleanup: + + ldap_mods_free(mods, 1); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + + + +/* + * Create the Kerberos container in the Directory if it does not exist + */ + +krb5_error_code +krb5_ldap_create_krbcontainer(krb5_context context, const char *dn) +{ + LDAP *ld=NULL; + char *strval[2]={NULL}, **rdns=NULL; + LDAPMod **mods = NULL; + krb5_error_code st=0; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + + SETUP_CONTEXT (); + + /* get ldap handle */ + GET_HANDLE (); + + if (dn == NULL) { + st = EINVAL; + k5_setmsg(context, st, _("Kerberos Container information is missing")); + goto cleanup; + } + + strval[0] = "krbContainer"; + strval[1] = NULL; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) + goto cleanup; + + rdns = ldap_explode_dn(dn, 1); + if (rdns == NULL) { + st = EINVAL; + k5_setmsg(context, st, _("Invalid Kerberos container DN")); + goto cleanup; + } + + strval[0] = rdns[0]; + strval[1] = NULL; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0) + goto cleanup; + + /* create the kerberos container */ + st = ldap_add_ext_s(ld, dn, mods, NULL, NULL); + if (st == LDAP_ALREADY_EXISTS) + st = LDAP_SUCCESS; + if (st != LDAP_SUCCESS) { + int ost = st; + st = translate_ldap_error (st, OP_ADD); + k5_setmsg(context, st, _("Kerberos Container create FAILED: %s"), + ldap_err2string(ost)); + goto cleanup; + } + +cleanup: + + if (rdns) + ldap_value_free (rdns); + + ldap_mods_free(mods, 1); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return(st); +} + +/* + * Delete the Kerberos container in the Directory + */ + +krb5_error_code +krb5_ldap_delete_krbcontainer(krb5_context context, const char *dn) +{ + LDAP *ld=NULL; + krb5_error_code st=0; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + + SETUP_CONTEXT (); + + /* get ldap handle */ + GET_HANDLE (); + + if (dn == NULL) { + st = EINVAL; + k5_setmsg(context, st, _("Kerberos Container information is missing")); + goto cleanup; + } + + /* delete the kerberos container */ + if ((st = ldap_delete_ext_s(ld, dn, NULL, NULL)) != LDAP_SUCCESS) { + int ost = st; + st = translate_ldap_error (st, OP_ADD); + k5_setmsg(context, st, _("Kerberos Container delete FAILED: %s"), + ldap_err2string(ost)); + goto cleanup; + } + +cleanup: + + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return(st); +} + + +/* + * Create Realm in eDirectory. This is used by kdb5_util + */ + +krb5_error_code +krb5_ldap_create_realm(krb5_context context, krb5_ldap_realm_params *rparams, + int mask) +{ + LDAP *ld=NULL; + krb5_error_code st=0; + char *dn=NULL; + char *strval[4]={NULL}; + char *contref[2]={NULL}; + LDAPMod **mods = NULL; + int i=0, objectmask=0, subtreecount=0; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + char *realm_name; + + SETUP_CONTEXT (); + + /* Check input validity ... */ + if (ldap_context->container_dn == NULL || + rparams == NULL || + rparams->realm_name == NULL || + ((mask & LDAP_REALM_SUBTREE) && rparams->subtree == NULL) || + ((mask & LDAP_REALM_CONTREF) && rparams->containerref == NULL) || + 0) { + st = EINVAL; + return st; + } + + /* get ldap handle */ + GET_HANDLE (); + + realm_name = rparams->realm_name; + + if (asprintf(&dn, "cn=%s,%s", realm_name, ldap_context->container_dn) < 0) + dn = NULL; + CHECK_NULL(dn); + + strval[0] = realm_name; + strval[1] = NULL; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0) + goto cleanup; + + strval[0] = "top"; + strval[1] = "krbrealmcontainer"; + strval[2] = "krbticketpolicyaux"; + strval[3] = NULL; + + if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) + goto cleanup; + + /* SUBTREE ATTRIBUTE */ + if (mask & LDAP_REALM_SUBTREE) { + if ( rparams->subtree!=NULL) { + subtreecount = rparams->subtreecount; + for (i=0; rparams->subtree[i]!=NULL && isubtree[i]) != 0) { + st = checkattributevalue(ld, rparams->subtree[i], "Objectclass", subtreeclass, + &objectmask); + CHECK_CLASS_VALIDITY(st, objectmask, + _("realm object value: ")); + } + } + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbsubtrees", LDAP_MOD_ADD, + rparams->subtree)) != 0) { + goto cleanup; + } + } + } + + /* CONTAINER REFERENCE ATTRIBUTE */ + if (mask & LDAP_REALM_CONTREF) { + if (strlen(rparams->containerref) != 0 ) { + st = checkattributevalue(ld, rparams->containerref, "Objectclass", subtreeclass, + &objectmask); + CHECK_CLASS_VALIDITY(st, objectmask, "realm object value: "); + contref[0] = rparams->containerref; + contref[1] = NULL; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbPrincContainerRef", LDAP_MOD_ADD, + contref)) != 0) + goto cleanup; + } + } + + /* SEARCHSCOPE ATTRIBUTE */ + if (mask & LDAP_REALM_SEARCHSCOPE) { + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbsearchscope", LDAP_MOD_ADD, + (rparams->search_scope == LDAP_SCOPE_ONELEVEL + || rparams->search_scope == LDAP_SCOPE_SUBTREE) ? + rparams->search_scope : LDAP_SCOPE_SUBTREE)) != 0) + goto cleanup; + } + if (mask & LDAP_REALM_MAXRENEWLIFE) { + + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxRenewableAge", LDAP_MOD_ADD, + rparams->max_renewable_life)) != 0) + goto cleanup; + } + + /* krbMaxTicketLife ATTRIBUTE */ + + if (mask & LDAP_REALM_MAXTICKETLIFE) { + + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbMaxTicketLife", LDAP_MOD_ADD, + rparams->max_life)) != 0) + goto cleanup; + } + + /* krbTicketFlags ATTRIBUTE */ + + if (mask & LDAP_REALM_KRBTICKETFLAGS) { + + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbTicketFlags", LDAP_MOD_ADD, + rparams->tktflags)) != 0) + goto cleanup; + } + + + /* realm creation operation */ + if ((st=ldap_add_ext_s(ld, dn, mods, NULL, NULL)) != LDAP_SUCCESS) { + st = set_ldap_error (context, st, OP_ADD); + goto cleanup; + } + +cleanup: + + if (dn) + free(dn); + + ldap_mods_free(mods, 1); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + +/* + * Read the realm container configuration from eDirectory for the specified realm. + */ + +krb5_error_code +krb5_ldap_read_realm_params(krb5_context context, char *lrealm, + krb5_ldap_realm_params **rlparamp, int *mask) +{ + char **values=NULL; + krb5_error_code st=0, tempst=0; + LDAP *ld=NULL; + LDAPMessage *result=NULL,*ent=NULL; + krb5_ldap_realm_params *rlparams=NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + int x=0; + + SETUP_CONTEXT (); + + /* validate the input parameter */ + if (lrealm == NULL || ldap_context->container_dn == NULL) { + st = EINVAL; + goto cleanup; + } + + /* get ldap handle */ + GET_HANDLE (); + + /* Initialize realm container structure */ + rlparams =(krb5_ldap_realm_params *) malloc(sizeof(krb5_ldap_realm_params)); + CHECK_NULL(rlparams); + memset(rlparams, 0, sizeof(krb5_ldap_realm_params)); + + /* allocate tl_data structure to store MASK information */ + rlparams->tl_data = malloc (sizeof(krb5_tl_data)); + if (rlparams->tl_data == NULL) { + st = ENOMEM; + goto cleanup; + } + memset(rlparams->tl_data, 0, sizeof(krb5_tl_data)); + rlparams->tl_data->tl_data_type = KDB_TL_USER_INFO; + + /* set the mask parameter to 0 */ + *mask = 0; + + /* set default values */ + rlparams->search_scope = LDAP_SCOPE_SUBTREE; + + if (asprintf(&rlparams->realmdn, "cn=%s,%s", lrealm, + ldap_context->container_dn) < 0) { + rlparams->realmdn = NULL; + st = ENOMEM; + goto cleanup; + } + + /* populate the realm name in the structure */ + rlparams->realm_name = strdup(lrealm); + CHECK_NULL(rlparams->realm_name); + + LDAP_SEARCH(rlparams->realmdn, LDAP_SCOPE_BASE, "(objectclass=krbRealmContainer)", realm_attributes); + + if ((st = ldap_count_entries(ld, result)) <= 0) { + /* This could happen when the DN used to bind and read the realm object + * does not have sufficient rights to read its attributes + */ + st = KRB5_KDB_ACCESS_ERROR; /* return some other error ? */ + goto cleanup; + } + + ent = ldap_first_entry (ld, result); + if (ent == NULL) { + ldap_get_option (ld, LDAP_OPT_ERROR_NUMBER, (void *) &st); + goto cleanup; + } + + /* Read the attributes */ + { + if ((values=ldap_get_values(ld, ent, "krbSubTrees")) != NULL) { + rlparams->subtreecount = ldap_count_values(values); + rlparams->subtree = (char **) malloc(sizeof(char *) * (rlparams->subtreecount + 1)); + if (rlparams->subtree == NULL) { + st = ENOMEM; + goto cleanup; + } + for (x=0; xsubtreecount; x++) { + rlparams->subtree[x] = strdup(values[x]); + if (rlparams->subtree[x] == NULL) { + st = ENOMEM; + goto cleanup; + } + } + rlparams->subtree[rlparams->subtreecount] = NULL; + *mask |= LDAP_REALM_SUBTREE; + ldap_value_free(values); + } + + if((values=ldap_get_values(ld, ent, "krbPrincContainerRef")) != NULL) { + rlparams->containerref = strdup(values[0]); + if(rlparams->containerref == NULL) { + st = ENOMEM; + goto cleanup; + } + *mask |= LDAP_REALM_CONTREF; + ldap_value_free(values); + } + + if ((values=ldap_get_values(ld, ent, "krbSearchScope")) != NULL) { + rlparams->search_scope=atoi(values[0]); + /* searchscope can be ONE-LEVEL or SUBTREE, else default to SUBTREE */ + if (!(rlparams->search_scope==1 || rlparams->search_scope==2)) + rlparams->search_scope = LDAP_SCOPE_SUBTREE; + *mask |= LDAP_REALM_SEARCHSCOPE; + ldap_value_free(values); + } + + if ((values=ldap_get_values(ld, ent, "krbMaxTicketLife")) != NULL) { + rlparams->max_life = atoi(values[0]); + *mask |= LDAP_REALM_MAXTICKETLIFE; + ldap_value_free(values); + } + + if ((values=ldap_get_values(ld, ent, "krbMaxRenewableAge")) != NULL) { + rlparams->max_renewable_life = atoi(values[0]); + *mask |= LDAP_REALM_MAXRENEWLIFE; + ldap_value_free(values); + } + + if ((values=ldap_get_values(ld, ent, "krbTicketFlags")) != NULL) { + rlparams->tktflags = atoi(values[0]); + *mask |= LDAP_REALM_KRBTICKETFLAGS; + ldap_value_free(values); + } + + } + + rlparams->mask = *mask; + *rlparamp = rlparams; + st = store_tl_data(rlparams->tl_data, KDB_TL_MASK, mask); + +cleanup: + + /* if there is an error, free allocated structures */ + if (st != 0) { + krb5_ldap_free_realm_params(rlparams); + *rlparamp=NULL; + } + ldap_msgfree(result); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + + +/* + Free the krb5_ldap_realm_params. +*/ +void +krb5_ldap_free_realm_params(krb5_ldap_realm_params *rparams) +{ + int i=0; + + if (rparams) { + if (rparams->realmdn) + free(rparams->realmdn); + + if (rparams->realm_name) + free(rparams->realm_name); + + if (rparams->subtree) { + for (i=0; isubtreecount && rparams->subtree[i] ; i++) + free(rparams->subtree[i]); + free(rparams->subtree); + } + + if (rparams->containerref) + free(rparams->containerref); + + if (rparams->kdcservers) { + for (i=0; rparams->kdcservers[i]; ++i) + free(rparams->kdcservers[i]); + free(rparams->kdcservers); + } + + if (rparams->adminservers) { + for (i=0; rparams->adminservers[i]; ++i) + free(rparams->adminservers[i]); + free(rparams->adminservers); + } + + if (rparams->passwdservers) { + for (i=0; rparams->passwdservers[i]; ++i) + free(rparams->passwdservers[i]); + free(rparams->passwdservers); + } + + if (rparams->tl_data) { + if (rparams->tl_data->tl_data_contents) + free(rparams->tl_data->tl_data_contents); + free(rparams->tl_data); + } + + free(rparams); + } + return; +} + +/* + * ****************************************************************************** + * DAL functions + * ****************************************************************************** + */ + +krb5_error_code +krb5_ldap_delete_realm_1(krb5_context kcontext, char *conf_section, + char **db_args) +{ + krb5_error_code status = KRB5_PLUGIN_OP_NOTSUPP; + k5_setmsg(kcontext, status, "LDAP %s", error_message(status)); + return status; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h new file mode 100644 index 00000000..2f1b7aaf --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.h @@ -0,0 +1,98 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_realm.h */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#ifndef _LDAP_REALM_H +#define _LDAP_REALM_H 1 + +/* realm specific mask */ +#define LDAP_REALM_SUBTREE 0x0001 +#define LDAP_REALM_SEARCHSCOPE 0x0002 +/* 0x0004 was LDAP_REALM_POLICYREFERENCE but it was unused */ +#define LDAP_REALM_UPENABLED 0x0008 +#define LDAP_REALM_LDAPSERVERS 0x0010 +#define LDAP_REALM_KDCSERVERS 0x0020 +#define LDAP_REALM_ADMINSERVERS 0x0040 +#define LDAP_REALM_PASSWDSERVERS 0x0080 +#define LDAP_REALM_MAXTICKETLIFE 0x0100 +#define LDAP_REALM_MAXRENEWLIFE 0x0200 +#define LDAP_REALM_KRBTICKETFLAGS 0x0400 +#define LDAP_REALM_CONTREF 0x0800 + +extern char *policy_attributes[]; + +extern char *realm_attributes[]; + +/* realm container structure */ + +typedef struct _krb5_ldap_realm_params { + char *realmdn; + char *realm_name; + char **subtree; + char *containerref; + int search_scope; + int upenabled; + int subtreecount; + krb5_int32 max_life; + krb5_int32 max_renewable_life; + krb5_int32 tktflags; + char **kdcservers; + char **adminservers; + char **passwdservers; + krb5_tl_data *tl_data; + long mask; +} krb5_ldap_realm_params; + + +krb5_error_code +krb5_ldap_list_realm(krb5_context , char ***); + +krb5_error_code +krb5_ldap_delete_realm(krb5_context, char *); + +krb5_error_code +krb5_ldap_modify_realm(krb5_context, krb5_ldap_realm_params *, int); + +krb5_error_code +krb5_ldap_create_realm(krb5_context, krb5_ldap_realm_params *, int); + +krb5_error_code +krb5_ldap_read_realm_params(krb5_context, char *, krb5_ldap_realm_params **, + int *); + +void +krb5_ldap_free_realm_params(krb5_ldap_realm_params *); + +krb5_error_code +krb5_ldap_delete_realm_1(krb5_context, char *, char **); + +char * +ldap_filter_correct(char *); + +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c new file mode 100644 index 00000000..cb30f4a7 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c @@ -0,0 +1,115 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "ldap_main.h" +#include "kdb_ldap.h" +#include "ldap_service_stash.h" +#include +#include + +/* Decode a password of the form {HEX}. */ +static krb5_error_code +dec_password(krb5_context context, const char *str, char **password_out) +{ + krb5_error_code ret; + uint8_t *bytes; + size_t len; + + *password_out = NULL; + + if (strncmp(str, "{HEX}", 5) != 0) { + k5_setmsg(context, EINVAL, _("Not a hexadecimal password")); + return EINVAL; + } + + ret = k5_hex_decode(str + 5, &bytes, &len); + if (ret) { + if (ret == EINVAL) + k5_setmsg(context, ret, _("Password corrupt")); + return ret; + } + + *password_out = (char *)bytes; + return 0; +} + +krb5_error_code +krb5_ldap_readpassword(krb5_context context, const char *filename, + const char *name, char **password_out) +{ + krb5_error_code ret; + char line[RECORDLEN], *end; + const char *start, *sep, *val = NULL; + int namelen = strlen(name); + FILE *fp; + + *password_out = NULL; + + fp = fopen(filename, "r"); + if (fp == NULL) { + ret = errno; + k5_setmsg(context, ret, _("Cannot open LDAP password file '%s': %s"), + filename, error_message(ret)); + return ret; + } + set_cloexec_file(fp); + + while (fgets(line, RECORDLEN, fp) != NULL) { + /* Remove trailing newline. */ + end = line + strlen(line); + if (end > line && end[-1] == '\n') + end[-1] = '\0'; + + /* Skip past leading whitespace. */ + for (start = line; isspace(*start); ++start); + + /* Ignore comment lines */ + if (*start == '!' || *start == '#') + continue; + + sep = strchr(start, '#'); + if (sep != NULL && sep - start == namelen && + strncasecmp(start, name, namelen) == 0) { + val = sep + 1; + break; + } + } + fclose(fp); + + if (val == NULL) { + k5_setmsg(context, KRB5_KDB_SERVER_INTERNAL_ERR, + _("Bind DN entry '%s' missing in LDAP password file '%s'"), + name, filename); + return KRB5_KDB_SERVER_INTERNAL_ERR; + } + + /* Extract the plain password information. */ + return dec_password(context, val, password_out); +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h new file mode 100644 index 00000000..03cf9a1f --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h @@ -0,0 +1,40 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.h */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#ifndef LDAP_SERVICE_STASH_H +#define LDAP_SERVICE_STASH_H 1 + +#define RECORDLEN 1024 + +krb5_error_code +krb5_ldap_readpassword(krb5_context context, const char *filename, + const char *name, char **password_out); + +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c new file mode 100644 index 00000000..4f48fd6a --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c @@ -0,0 +1,498 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#include "ldap_main.h" +#include "kdb_ldap.h" +#include "ldap_tkt_policy.h" +#include "ldap_err.h" + +/* Ticket policy object management */ + +static void +free_list(char **list) +{ + int i; + + for (i = 0; list != NULL && list[i] != NULL; i++) + free(list[i]); + free(list); +} + +/* + * create the Ticket policy object in Directory. + */ +krb5_error_code +krb5_ldap_create_policy(krb5_context context, krb5_ldap_policy_params *policy, + int mask) +{ + krb5_error_code st=0; + LDAP *ld=NULL; + char *strval[3]={NULL}, *policy_dn = NULL; + LDAPMod **mods=NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + + /* validate the input parameters */ + if (policy == NULL || policy->policy == NULL) { + st = EINVAL; + k5_setmsg(context, st, _("Ticket Policy Name missing")); + goto cleanup; + } + + SETUP_CONTEXT(); + GET_HANDLE(); + + if ((st = krb5_ldap_name_to_policydn (context, policy->policy, &policy_dn)) != 0) + goto cleanup; + + memset(strval, 0, sizeof(strval)); + strval[0] = policy->policy; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0) + goto cleanup; + + memset(strval, 0, sizeof(strval)); + strval[0] = "krbTicketPolicy"; + strval[1] = "krbTicketPolicyaux"; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) + goto cleanup; + + if (mask & LDAP_POLICY_MAXTKTLIFE) { + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_ADD, + policy->maxtktlife)) != 0) + goto cleanup; + } + + if (mask & LDAP_POLICY_MAXRENEWLIFE) { + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_ADD, + policy->maxrenewlife)) != 0) + goto cleanup; + } + + if (mask & LDAP_POLICY_TKTFLAGS) { + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_ADD, + policy->tktflags)) != 0) + goto cleanup; + } + + /* ldap add operation */ + if ((st=ldap_add_ext_s(ld, policy_dn, mods, NULL, NULL)) != LDAP_SUCCESS) { + st = set_ldap_error (context, st, OP_ADD); + goto cleanup; + } + +cleanup: + if (policy_dn != NULL) + free(policy_dn); + + ldap_mods_free(mods, 1); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + + +/* + * modify the Ticket policy object in Directory. + */ + +krb5_error_code +krb5_ldap_modify_policy(krb5_context context, krb5_ldap_policy_params *policy, + int mask) +{ + int objectmask=0; + krb5_error_code st=0; + LDAP *ld=NULL; + char *attrvalues[]={"krbTicketPolicy", "krbTicketPolicyAux", NULL}, *strval[2]={NULL}; + char *policy_dn = NULL; + LDAPMod **mods=NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + + /* validate the input parameters */ + if (policy == NULL || policy->policy==NULL) { + st = EINVAL; + k5_setmsg(context, st, _("Ticket Policy Name missing")); + goto cleanup; + } + + SETUP_CONTEXT(); + GET_HANDLE(); + + if ((st = krb5_ldap_name_to_policydn (context, policy->policy, &policy_dn)) != 0) + goto cleanup; + + /* the policydn object should be of the krbTicketPolicy object class */ + st = checkattributevalue(ld, policy_dn, "objectClass", attrvalues, &objectmask); + CHECK_CLASS_VALIDITY(st, objectmask, _("ticket policy object: ")); + + if ((objectmask & 0x02) == 0) { /* add krbticketpolicyaux to the object class list */ + memset(strval, 0, sizeof(strval)); + strval[0] = "krbTicketPolicyAux"; + if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0) + goto cleanup; + } + + if (mask & LDAP_POLICY_MAXTKTLIFE) { + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_REPLACE, + policy->maxtktlife)) != 0) + goto cleanup; + } + + if (mask & LDAP_POLICY_MAXRENEWLIFE) { + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_REPLACE, + policy->maxrenewlife)) != 0) + goto cleanup; + } + + if (mask & LDAP_POLICY_TKTFLAGS) { + if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_REPLACE, + policy->tktflags)) != 0) + goto cleanup; + } + + if ((st=ldap_modify_ext_s(ld, policy_dn, mods, NULL, NULL)) != LDAP_SUCCESS) { + st = set_ldap_error (context, st, OP_MOD); + goto cleanup; + } + +cleanup: + if (policy_dn != NULL) + free(policy_dn); + + ldap_mods_free(mods, 1); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + + +/* + * Read the policy object from the Directory and populate the krb5_ldap_policy_params + * structure. + */ + +krb5_error_code +krb5_ldap_read_policy(krb5_context context, char *policyname, + krb5_ldap_policy_params **policy, int *omask) +{ + krb5_error_code st=0, tempst=0; + int objectmask=0, val=0; + LDAP *ld=NULL; + LDAPMessage *result=NULL,*ent=NULL; + char *attributes[] = { "krbMaxTicketLife", "krbMaxRenewableAge", "krbTicketFlags", NULL}; + char *attrvalues[] = { "krbTicketPolicy", NULL}, *policy_dn = NULL; + krb5_ldap_policy_params *lpolicy=NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + + /* validate the input parameters */ + if (policyname == NULL || policy == NULL) { + st = EINVAL; + k5_setmsg(context, st, _("Ticket Policy Object information missing")); + goto cleanup; + } + + SETUP_CONTEXT(); + GET_HANDLE(); + + if ((st = krb5_ldap_name_to_policydn (context, policyname, &policy_dn)) != 0) + goto cleanup; + + /* the policydn object should be of the krbTicketPolicy object class */ + st = checkattributevalue(ld, policy_dn, "objectClass", attrvalues, &objectmask); + CHECK_CLASS_VALIDITY(st, objectmask, _("ticket policy object: ")); + + /* Initialize ticket policy structure */ + lpolicy =(krb5_ldap_policy_params *) malloc(sizeof(krb5_ldap_policy_params)); + CHECK_NULL(lpolicy); + memset(lpolicy, 0, sizeof(krb5_ldap_policy_params)); + + if ((lpolicy->policy = strdup (policyname)) == NULL) { + st = ENOMEM; + goto cleanup; + } + + lpolicy->tl_data = calloc (1, sizeof(*lpolicy->tl_data)); + CHECK_NULL(lpolicy->tl_data); + lpolicy->tl_data->tl_data_type = KDB_TL_USER_INFO; + + LDAP_SEARCH(policy_dn, LDAP_SCOPE_BASE, "(objectclass=krbTicketPolicy)", attributes); + + *omask = 0; + + ent=ldap_first_entry(ld, result); + if (ent != NULL) { + if (krb5_ldap_get_value(ld, ent, "krbmaxticketlife", &val) == 0) { + lpolicy->maxtktlife = val; + *omask |= LDAP_POLICY_MAXTKTLIFE; + } + if (krb5_ldap_get_value(ld, ent, "krbmaxrenewableage", &val) == 0) { + lpolicy->maxrenewlife = val; + *omask |= LDAP_POLICY_MAXRENEWLIFE; + } + if (krb5_ldap_get_value(ld, ent, "krbticketflags", &val) == 0) { + lpolicy->tktflags = val; + *omask |= LDAP_POLICY_TKTFLAGS; + } + } + + lpolicy->mask = *omask; + store_tl_data(lpolicy->tl_data, KDB_TL_MASK, omask); + *policy = lpolicy; + +cleanup: + if (st != 0) { + krb5_ldap_free_policy(context, lpolicy); + *policy = NULL; + } + free(policy_dn); + ldap_msgfree(result); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + + +/* + * Function to delete ticket policy object from the directory. Before + * calling this function krb5_ldap_read_policy should be called to + * check the existence of the object. This serves one major purpose, + * i.e., if the object to be is anything other than the ticket policy + * object then the krb5_ldap_read_policy returns an error and thus is + * not accidentally deleted in this function. + * + * NOTE: Other kerberos objects (user/realm object) might be having + * references to the policy object to be deleted. This situation is + * not handled here, instead is taken care of at all the places where + * the deleted policy object is read, to ignore a return status of + * LDAP_NO_SUCH_OBJECT and continue. + */ + +krb5_error_code +krb5_ldap_delete_policy(krb5_context context, char *policyname) +{ + int refcount = 0; + char *policy_dn = NULL; + krb5_error_code st = 0; + LDAP *ld = NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + + if (policyname == NULL) { + st = EINVAL; + k5_prependmsg(context, st, _("Ticket Policy Object DN missing")); + goto cleanup; + } + + + SETUP_CONTEXT(); + GET_HANDLE(); + + if ((st = krb5_ldap_name_to_policydn (context, policyname, &policy_dn)) != 0) + goto cleanup; + + /* Checking for policy count for 0 and will not permit delete if + * it is greater than 0. */ + + if ((st = krb5_ldap_get_reference_count (context, policy_dn, + "krbTicketPolicyReference", &refcount, ld)) != 0) + goto cleanup; + + if (refcount == 0) { + if ((st=ldap_delete_ext_s(ld, policy_dn, NULL, NULL)) != 0) { + k5_prependmsg(context, st, "%s", ldap_err2string(st)); + + goto cleanup; + } + } else { + st = EINVAL; + k5_prependmsg(context, st, + _("Delete Failed: One or more Principals associated " + "with the Ticket Policy")); + goto cleanup; + } + +cleanup: + if (policy_dn != NULL) + free (policy_dn); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} + + +/* + * list policy objects from Directory + */ + +krb5_error_code +krb5_ldap_list_policy(krb5_context context, char *containerdn, char ***policy) +{ + int i, j, count; + char **list = NULL; + char *policycontainerdn = containerdn; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_error_code st=0; + + SETUP_CONTEXT(); + if (policycontainerdn == NULL) { + policycontainerdn = ldap_context->lrparams->realmdn; + } + + if ((st = krb5_ldap_list(context, &list, "krbTicketPolicy", policycontainerdn)) != 0) + goto cleanup; + + for (i = 0; list[i] != NULL; i++); + + count = i; + + *policy = (char **) calloc ((unsigned) count + 1, sizeof(char *)); + if (*policy == NULL) { + st = ENOMEM; + goto cleanup; + } + + for (i = 0, j = 0; list[i] != NULL; i++, j++) { + int ret; + ret = krb5_ldap_policydn_to_name (context, list[i], &(*policy)[i]); + if (ret != 0) + j--; + } + +cleanup: + free_list(list); + return st; +} + +/* + * Function to free the ticket policy object structure. + * Note: this function assumes that memory of the policy structure is dynamically allocated and hence the whole + * structure is freed up. Care should be taken not to call this function on a static structure + */ + +krb5_error_code +krb5_ldap_free_policy(krb5_context context, krb5_ldap_policy_params *policy) +{ + + krb5_error_code st=0; + + if (policy == NULL) + return st; + + if (policy->policy) + free (policy->policy); + + if (policy->tl_data) { + if (policy->tl_data->tl_data_contents) + free (policy->tl_data->tl_data_contents); + free (policy->tl_data); + } + free (policy); + + return st; +} + +/* + * This function is general object listing routine. It is currently + * used for ticket policy object listing. + */ + +krb5_error_code +krb5_ldap_list(krb5_context context, char ***list, char *objectclass, + char *containerdn) +{ + char *filter=NULL, *dn=NULL; + krb5_error_code st=0, tempst=0; + int count=0, filterlen=0; + LDAP *ld=NULL; + LDAPMessage *result=NULL,*ent=NULL; + kdb5_dal_handle *dal_handle=NULL; + krb5_ldap_context *ldap_context=NULL; + krb5_ldap_server_handle *ldap_server_handle=NULL; + + SETUP_CONTEXT(); + GET_HANDLE(); + + /* check if the containerdn exists */ + if (containerdn) { + if ((st=checkattributevalue(ld, containerdn, NULL, NULL, NULL)) != 0) { + k5_prependmsg(context, st, _("Error reading container object")); + goto cleanup; + } + } + + /* set the filter for the search operation */ + filterlen = strlen("(objectclass=") + strlen(objectclass) + 1 + 1; + filter = malloc ((unsigned) filterlen); + if (filter == NULL) { + st = ENOMEM; + goto cleanup; + } + snprintf(filter, (unsigned) filterlen,"(objectclass=%s)",objectclass); + + LDAP_SEARCH(containerdn, LDAP_SCOPE_SUBTREE, filter, NULL); + + count = ldap_count_entries(ld, result); + if (count == -1) { + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &st); + st = set_ldap_error(context, st, OP_SEARCH); + goto cleanup; + } + *list = (char **) calloc ((unsigned) count+1, sizeof(char *)); + if (*list == NULL) { + st = ENOMEM; + goto cleanup; + } + + for (ent=ldap_first_entry(ld, result), count=0; ent != NULL; ent=ldap_next_entry(ld, ent), ++count) { + if ((dn=ldap_get_dn(ld, ent)) == NULL) + continue; + if (((*list)[count] = strdup(dn)) == NULL) { + ldap_memfree (dn); + st = ENOMEM; + goto cleanup; + } + ldap_memfree(dn); + } + +cleanup: + if (filter) + free (filter); + + /* some error, free up all the memory */ + if (st != 0) { + free_list(*list); + *list = NULL; + } + ldap_msgfree(result); + krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); + return st; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h new file mode 100644 index 00000000..712adae4 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h @@ -0,0 +1,75 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h */ +/* + * Copyright (c) 2004-2005, Novell, Inc. + * 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. + * * The copyright holder's name is not 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. + */ + +#ifndef _LDAP_POLICY_H +#define _LDAP_POLICY_H 1 + +/* policy specific mask */ + +#define LDAP_POLICY_MAXTKTLIFE 0x0001 +#define LDAP_POLICY_MAXRENEWLIFE 0x0002 +#define LDAP_POLICY_TKTFLAGS 0x0004 +#define LDAP_POLICY_COUNT 0x0008 +/* policy object structure */ + +typedef struct _krb5_ldap_policy_params { + char *policy; + long mask; + long maxtktlife; + long maxrenewlife; + long tktflags; + krb5_tl_data *tl_data; +}krb5_ldap_policy_params; + +krb5_error_code +krb5_ldap_create_policy(krb5_context, krb5_ldap_policy_params *, int); + +krb5_error_code +krb5_ldap_modify_policy(krb5_context, krb5_ldap_policy_params *, int); + +krb5_error_code +krb5_ldap_read_policy(krb5_context, char *, krb5_ldap_policy_params **, int *); + +krb5_error_code +krb5_ldap_delete_policy(krb5_context, char *); + +krb5_error_code +krb5_ldap_clear_policy(krb5_context, char *); + +krb5_error_code +krb5_ldap_list_policy(krb5_context, char *, char ***); + +krb5_error_code +krb5_ldap_free_policy(krb5_context, krb5_ldap_policy_params *); + +krb5_error_code +krb5_ldap_change_count(krb5_context, char *, int); + +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports new file mode 100644 index 00000000..5376d345 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/libkdb_ldap.exports @@ -0,0 +1,41 @@ +krb5_ldap_open +krb5_ldap_close +krb5_ldap_db_init +krb5_ldap_lib_init +krb5_ldap_lib_cleanup +krb5_ldap_get_age +krb5_ldap_read_server_params +krb5_ldap_put_principal +krb5_ldap_get_principal +krb5_ldap_delete_principal +krb5_ldap_rename_principal +krb5_ldap_iterate +krb5_ldap_read_krbcontainer_dn +krb5_ldap_list_realm +krb5_ldap_read_realm_params +krb5_ldap_free_realm_params +krb5_ldap_modify_realm +krb5_ldap_create_krbcontainer +krb5_ldap_create_realm +krb5_ldap_delete_realm +krb5_ldap_list_policy +krb5_ldap_free_policy +krb5_ldap_read_policy +krb5_ldap_modify_policy +krb5_ldap_delete_policy +krb5_ldap_create_policy +krb5_ldap_create_password_policy +krb5_ldap_put_password_policy +krb5_ldap_get_password_policy +krb5_ldap_delete_password_policy +krb5_ldap_iterate_password_policy +krb5_dbe_free_contents +krb5_ldap_free_server_params +krb5_ldap_free_server_context_params +krb5_ldap_delete_realm_1 +krb5_ldap_lock +krb5_ldap_unlock +krb5_ldap_create +krb5_ldap_check_policy_as +krb5_ldap_audit_as_req +krb5_ldap_check_allowed_to_delegate diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/lockout.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/lockout.c new file mode 100644 index 00000000..094b8902 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/lockout.c @@ -0,0 +1,220 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/ldap/libkdb_ldap/lockout.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include + +#include "kdb_ldap.h" +#include "princ_xdr.h" +#include "ldap_principal.h" +#include "ldap_pwd_policy.h" +#include "ldap_tkt_policy.h" + +static krb5_error_code +lookup_lockout_policy(krb5_context context, + krb5_db_entry *entry, + krb5_kvno *pw_max_fail, + krb5_deltat *pw_failcnt_interval, + krb5_deltat *pw_lockout_duration) +{ + krb5_tl_data tl_data; + krb5_error_code code; + osa_princ_ent_rec adb; + + *pw_max_fail = 0; + *pw_failcnt_interval = 0; + *pw_lockout_duration = 0; + + tl_data.tl_data_type = KRB5_TL_KADM_DATA; + + code = krb5_dbe_lookup_tl_data(context, entry, &tl_data); + if (code != 0 || tl_data.tl_data_length == 0) + return code; + + memset(&adb, 0, sizeof(adb)); + + code = krb5_lookup_tl_kadm_data(&tl_data, &adb); + if (code != 0) + return code; + + if (adb.policy != NULL) { + osa_policy_ent_t policy = NULL; + + code = krb5_ldap_get_password_policy(context, adb.policy, &policy); + if (code == 0) { + *pw_max_fail = policy->pw_max_fail; + *pw_failcnt_interval = policy->pw_failcnt_interval; + *pw_lockout_duration = policy->pw_lockout_duration; + } + krb5_db_free_policy(context, policy); + } + + ldap_osa_free_princ_ent(&adb); + + return 0; +} + +/* draft-behera-ldap-password-policy-10.txt 7.1 */ +static krb5_boolean +locked_check_p(krb5_context context, + krb5_timestamp stamp, + krb5_kvno max_fail, + krb5_timestamp lockout_duration, + krb5_db_entry *entry) +{ + krb5_timestamp unlock_time; + + /* If the entry was unlocked since the last failure, it's not locked. */ + if (krb5_dbe_lookup_last_admin_unlock(context, entry, &unlock_time) == 0 && + !ts_after(entry->last_failed, unlock_time)) + return FALSE; + + if (max_fail == 0 || entry->fail_auth_count < max_fail) + return FALSE; + + if (lockout_duration == 0) + return TRUE; /* principal permanently locked */ + + return ts_after(ts_incr(entry->last_failed, lockout_duration), stamp); +} + +krb5_error_code +krb5_ldap_lockout_check_policy(krb5_context context, + krb5_db_entry *entry, + krb5_timestamp stamp) +{ + krb5_error_code code; + kdb5_dal_handle *dal_handle; + krb5_ldap_context *ldap_context; + krb5_kvno max_fail = 0; + krb5_deltat failcnt_interval = 0; + krb5_deltat lockout_duration = 0; + + SETUP_CONTEXT(); + if (ldap_context->disable_lockout) + return 0; + + code = lookup_lockout_policy(context, entry, &max_fail, + &failcnt_interval, + &lockout_duration); + if (code != 0) + return code; + + if (locked_check_p(context, stamp, max_fail, lockout_duration, entry)) + return KRB5KDC_ERR_CLIENT_REVOKED; + + return 0; +} + +krb5_error_code +krb5_ldap_lockout_audit(krb5_context context, + krb5_db_entry *entry, + krb5_timestamp stamp, + krb5_error_code status) +{ + krb5_error_code code; + kdb5_dal_handle *dal_handle; + krb5_ldap_context *ldap_context; + krb5_kvno max_fail = 0; + krb5_deltat failcnt_interval = 0; + krb5_deltat lockout_duration = 0; + krb5_timestamp unlock_time; + + SETUP_CONTEXT(); + + switch (status) { + case 0: + case KRB5KDC_ERR_PREAUTH_FAILED: + case KRB5KRB_AP_ERR_BAD_INTEGRITY: + break; + default: + return 0; + } + + if (entry == NULL) + return 0; + + if (!ldap_context->disable_lockout) { + code = lookup_lockout_policy(context, entry, &max_fail, + &failcnt_interval, + &lockout_duration); + if (code != 0) + return code; + } + + /* + * Don't continue to modify the DB for an already locked account. + * (In most cases, status will be KRB5KDC_ERR_CLIENT_REVOKED, and + * this check is unneeded, but in rare cases, we can fail with an + * integrity error or preauth failure before a policy check.) + */ + if (locked_check_p(context, stamp, max_fail, lockout_duration, entry)) + return 0; + + entry->mask = 0; + + /* Only mark the authentication as successful if the entry + * required preauthentication, otherwise we have no idea. */ + if (status == 0 && (entry->attributes & KRB5_KDB_REQUIRES_PRE_AUTH)) { + if (!ldap_context->disable_lockout && entry->fail_auth_count != 0) { + entry->fail_auth_count = 0; + entry->mask |= KADM5_FAIL_AUTH_COUNT; + } + if (!ldap_context->disable_last_success) { + entry->last_success = stamp; + entry->mask |= KADM5_LAST_SUCCESS; + } + } else if (!ldap_context->disable_lockout && + (status == KRB5KDC_ERR_PREAUTH_FAILED || + status == KRB5KRB_AP_ERR_BAD_INTEGRITY)) { + if (krb5_dbe_lookup_last_admin_unlock(context, entry, + &unlock_time) == 0 && + !ts_after(entry->last_failed, unlock_time)) { + /* Reset fail_auth_count after administrative unlock. */ + entry->fail_auth_count = 0; + entry->mask |= KADM5_FAIL_AUTH_COUNT; + } + + if (failcnt_interval != 0 && + ts_after(stamp, ts_incr(entry->last_failed, failcnt_interval))) { + /* Reset fail_auth_count after failcnt_interval */ + entry->fail_auth_count = 0; + entry->mask |= KADM5_FAIL_AUTH_COUNT; + } + + entry->last_failed = stamp; + entry->mask |= KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT_INCREMENT; + } + + if (entry->mask) { + code = krb5_ldap_put_principal(context, entry, NULL); + if (code != 0) + return code; + } + + return 0; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.c b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.c new file mode 100644 index 00000000..20c399d9 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.c @@ -0,0 +1,55 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ + +#include "kdb_ldap.h" +#include "ldap_principal.h" +#include "princ_xdr.h" +#include +#include + +void +ldap_osa_free_princ_ent(osa_princ_ent_t val) +{ + XDR xdrs; + + xdrmem_create(&xdrs, NULL, 0, XDR_FREE); + xdr_osa_princ_ent_rec(&xdrs, val); + xdr_destroy(&xdrs); +} + +krb5_error_code +krb5_lookup_tl_kadm_data(krb5_tl_data *tl_data, osa_princ_ent_rec *princ_entry) +{ + + XDR xdrs; + + xdrmem_create(&xdrs, (caddr_t)tl_data->tl_data_contents, + tl_data->tl_data_length, XDR_DECODE); + if (!xdr_osa_princ_ent_rec(&xdrs, princ_entry)) { + xdr_destroy(&xdrs); + return KADM5_XDR_FAILURE; + } + xdr_destroy(&xdrs); + + return 0; +} + +krb5_error_code +krb5_update_tl_kadm_data(krb5_context context, krb5_db_entry *entry, + osa_princ_ent_rec *princ_entry) +{ + XDR xdrs; + krb5_tl_data tl_data; + krb5_error_code retval; + + xdralloc_create(&xdrs, XDR_ENCODE); + if (!xdr_osa_princ_ent_rec(&xdrs, princ_entry)) { + xdr_destroy(&xdrs); + return KADM5_XDR_FAILURE; + } + tl_data.tl_data_type = KRB5_TL_KADM_DATA; + tl_data.tl_data_length = xdr_getpos(&xdrs); + tl_data.tl_data_contents = (krb5_octet *)xdralloc_getdata(&xdrs); + retval = krb5_dbe_update_tl_data(context, entry, &tl_data); + xdr_destroy(&xdrs); + return retval; +} diff --git a/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.h b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.h new file mode 100644 index 00000000..29e9b80e --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/ldap/libkdb_ldap/princ_xdr.h @@ -0,0 +1,21 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ + +#ifndef _PRINC_XDR_H +#define _PRINC_XDR_H 1 + +#include +#include +#include + +void +ldap_osa_free_princ_ent(osa_princ_ent_t val); + +krb5_error_code +krb5_lookup_tl_kadm_data(krb5_tl_data *tl_data, + osa_princ_ent_rec *princ_entry); + +krb5_error_code +krb5_update_tl_kadm_data(krb5_context context, krb5_db_entry *entry, + osa_princ_ent_rec *princ_entry); + +#endif diff --git a/krb5-1.21.3/src/plugins/kdb/lmdb/Makefile.in b/krb5-1.21.3/src/plugins/kdb/lmdb/Makefile.in new file mode 100644 index 00000000..8e68b17d --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/lmdb/Makefile.in @@ -0,0 +1,27 @@ +mydir=plugins$(S)kdb$(S)lmdb +BUILDTOP=$(REL)..$(S)..$(S).. +MODULE_INSTALL_DIR = $(KRB5_DB_MODULE_DIR) + +LOCALINCLUDES = -I$(srcdir)/../../../lib/kdb + +LIBBASE=klmdb +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/kdb/lmdb +# Depends on libk5crypto and libkrb5 +# Also on gssrpc, for xdr stuff. +SHLIB_EXPDEPS = $(KADMSRV_DEPLIBS) $(KDB5_DEPLIBS) $(KRB5_BASE_DEPLIBS) +SHLIB_EXPLIBS = $(KADMSRV_LIBS) $(KRB5_BASE_LIBS) $(LMDB_LIBS) + +DBDIR = liblmdb + +SRCS=$(srcdir)/kdb_lmdb.c $(srcdir)/lockout.c $(srcdir)/marshal.c + +STLIBOBJS=kdb_lmdb.o lockout.o marshal.o + +all-unix: all-liblinks +install-unix: install-libs +clean-unix:: clean-liblinks clean-libs clean-libobjs + +@libnover_frag@ +@libobj_frag@ diff --git a/krb5-1.21.3/src/plugins/kdb/lmdb/deps b/krb5-1.21.3/src/plugins/kdb/lmdb/deps new file mode 100644 index 00000000..e4212f79 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/lmdb/deps @@ -0,0 +1,53 @@ +# +# Generated makefile dependencies follow. +# +kdb_lmdb.so kdb_lmdb.po $(OUTPRE)kdb_lmdb.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(srcdir)/../../../lib/kdb/kdb5.h \ + $(top_srcdir)/include/gssrpc/auth.h $(top_srcdir)/include/gssrpc/auth_gss.h \ + $(top_srcdir)/include/gssrpc/auth_unix.h $(top_srcdir)/include/gssrpc/clnt.h \ + $(top_srcdir)/include/gssrpc/rename.h $(top_srcdir)/include/gssrpc/rpc.h \ + $(top_srcdir)/include/gssrpc/rpc_msg.h $(top_srcdir)/include/gssrpc/svc.h \ + $(top_srcdir)/include/gssrpc/svc_auth.h $(top_srcdir)/include/gssrpc/xdr.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdb_lmdb.c klmdb-int.h +lockout.so lockout.po $(OUTPRE)lockout.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/admin_internal.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/kadm5/server_internal.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../../lib/kdb/kdb5.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + klmdb-int.h lockout.c +marshal.so marshal.po $(OUTPRE)marshal.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-input.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h klmdb-int.h marshal.c diff --git a/krb5-1.21.3/src/plugins/kdb/lmdb/kdb_lmdb.c b/krb5-1.21.3/src/plugins/kdb/lmdb/kdb_lmdb.c new file mode 100644 index 00000000..bd288e22 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/lmdb/kdb_lmdb.c @@ -0,0 +1,1143 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/lmdb/klmdb.c - KDB module using LMDB */ +/* + * Copyright (C) 2018 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. + */ + +/* + * Thread-safety note: unlike the other two in-tree KDB modules, this module + * performs no mutex locking to ensure thread safety. As the KDC and kadmind + * are single-threaded, and applications are not allowed to access the same + * krb5_context in multiple threads simultaneously, there is no current need + * for this code to be thread-safe. If a need arises in the future, mutex + * locking should be added around the read_txn and load_txn fields of + * lmdb_context to ensure that only one thread at a time accesses those + * transactions. + */ + +/* + * This KDB module stores principal and policy data using LMDB (Lightning + * Memory-Mapped Database). We use two LMDB environments, the first to hold + * the majority of principal and policy data (suffix ".mdb") in the "principal" + * and "policy" databases, and the second to hold the three non-replicated + * account lockout attributes (suffix ".lockout.mdb") in the "lockout" + * database. The KDC only needs to write to the lockout database. + * + * For iteration we create a read transaction in the main environment for the + * cursor. Because the iteration callback might need to create its own + * transactions for write operations (e.g. for kdb5_util + * update_princ_encryption), we set the MDB_NOTLS flag on the main environment, + * so that a thread can hold multiple transactions. + * + * To mitigate the overhead from MDB_NOTLS, we keep around a read_txn handle + * in the database context for get operations, using mdb_txn_reset() and + * mdb_txn_renew() between calls. + * + * For database loads, kdb5_util calls the create() method with the "temporary" + * db_arg, and then promotes the finished contents at the end with the + * promote_db() method. In this case we create or open the same LMDB + * environments as above, open a write_txn handle for the lifetime of the + * context, and empty out the principal and policy databases. On promote_db() + * we commit the transaction. We do not empty the lockout database and write + * to it non-transactionally during the load so that we don't block writes by + * the KDC; this isn't ideal if the load is aborted, but it shouldn't cause any + * practical issues. + * + * For iprop loads, kdb5_util also includes the "merge_nra" db_arg, signifying + * that the lockout attributes from existing principal entries should be + * preserved. This attribute is noted in the LMDB context, and put_principal + * operations will not write to the lockout database if an existing lockout + * entry is already present for the principal. + */ + +#include "k5-int.h" +#include +#include "kdb5.h" +#include "klmdb-int.h" +#include + +/* The presence of any of these mask bits indicates a change to one of the + * three principal lockout attributes. */ +#define LOCKOUT_MASK (KADM5_LAST_SUCCESS | KADM5_LAST_FAILED | \ + KADM5_FAIL_AUTH_COUNT) + +/* The default map size (for both environments) in megabytes. */ +#define DEFAULT_MAPSIZE 128 + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +typedef struct { + char *path; + char *lockout_path; + krb5_boolean temporary; /* save changes until promote_db */ + krb5_boolean merge_nra; /* preserve existing lockout attributes */ + krb5_boolean disable_last_success; + krb5_boolean disable_lockout; + krb5_boolean nosync; + size_t mapsize; + unsigned int maxreaders; + + MDB_env *env; + MDB_env *lockout_env; + MDB_dbi princ_db; + MDB_dbi policy_db; + MDB_dbi lockout_db; + + /* Used for get operations; each transaction is short-lived but we save the + * handle between calls to reduce overhead from MDB_NOTLS. */ + MDB_txn *read_txn; + + /* Write transaction for load operations (create() with the "temporary" + * db_arg). */ + MDB_txn *load_txn; +} klmdb_context; + +static krb5_error_code +klerr(krb5_context context, int err, const char *msg) +{ + krb5_error_code ret; + klmdb_context *dbc = context->dal_handle->db_context; + + /* Pass through system errors; map MDB errors to a com_err code. */ + ret = (err > 0) ? err : KRB5_KDB_ACCESS_ERROR; + + k5_setmsg(context, ret, _("%s (path: %s): %s"), msg, dbc->path, + mdb_strerror(err)); + return ret; +} + +/* Using db_args and the profile, create a DB context inside context and + * initialize its configurable parameters. */ +static krb5_error_code +configure_context(krb5_context context, const char *conf_section, + char *const *db_args) +{ + krb5_error_code ret; + klmdb_context *dbc; + char *pval = NULL; + const char *path = NULL; + profile_t profile = context->profile; + int i, bval, ival; + + dbc = k5alloc(sizeof(*dbc), &ret); + if (dbc == NULL) + return ret; + context->dal_handle->db_context = dbc; + + for (i = 0; db_args != NULL && db_args[i] != NULL; i++) { + if (strcmp(db_args[i], "temporary") == 0) { + dbc->temporary = TRUE; + } else if (strcmp(db_args[i], "merge_nra") == 0) { + dbc->merge_nra = TRUE; + } else if (strncmp(db_args[i], "dbname=", 7) == 0) { + path = db_args[i] + 7; + } else { + ret = EINVAL; + k5_setmsg(context, ret, _("Unsupported argument \"%s\" for LMDB"), + db_args[i]); + goto cleanup; + } + } + + if (path == NULL) { + /* Check for database_name in the db_module section. */ + ret = profile_get_string(profile, KDB_MODULE_SECTION, conf_section, + KRB5_CONF_DATABASE_NAME, NULL, &pval); + if (!ret && pval == NULL) { + /* For compatibility, check for database_name in the realm. */ + ret = profile_get_string(profile, KDB_REALM_SECTION, + KRB5_DB_GET_REALM(context), + KRB5_CONF_DATABASE_NAME, DEFAULT_KDB_FILE, + &pval); + } + if (ret) + goto cleanup; + path = pval; + } + + if (asprintf(&dbc->path, "%s.mdb", path) < 0) { + dbc->path = NULL; + ret = ENOMEM; + goto cleanup; + } + if (asprintf(&dbc->lockout_path, "%s.lockout.mdb", path) < 0) { + dbc->lockout_path = NULL; + ret = ENOMEM; + goto cleanup; + } + + ret = profile_get_boolean(profile, KDB_MODULE_SECTION, conf_section, + KRB5_CONF_DISABLE_LAST_SUCCESS, FALSE, &bval); + if (ret) + goto cleanup; + dbc->disable_last_success = bval; + + ret = profile_get_boolean(profile, KDB_MODULE_SECTION, conf_section, + KRB5_CONF_DISABLE_LOCKOUT, FALSE, &bval); + if (ret) + goto cleanup; + dbc->disable_lockout = bval; + + ret = profile_get_integer(profile, KDB_MODULE_SECTION, conf_section, + KRB5_CONF_MAPSIZE, DEFAULT_MAPSIZE, &ival); + if (ret) + goto cleanup; + dbc->mapsize = (size_t)ival * 1024 * 1024; + + ret = profile_get_integer(profile, KDB_MODULE_SECTION, conf_section, + KRB5_CONF_MAX_READERS, 0, &ival); + if (ret) + goto cleanup; + dbc->maxreaders = ival; + + ret = profile_get_boolean(profile, KDB_MODULE_SECTION, conf_section, + KRB5_CONF_NOSYNC, FALSE, &bval); + if (ret) + goto cleanup; + dbc->nosync = bval; + +cleanup: + profile_release_string(pval); + return ret; +} + +static krb5_error_code +open_lmdb_env(krb5_context context, klmdb_context *dbc, + krb5_boolean is_lockout, krb5_boolean readonly, + MDB_env **env_out) +{ + krb5_error_code ret; + const char *path = is_lockout ? dbc->lockout_path : dbc->path; + unsigned int flags; + MDB_env *env = NULL; + int err; + + *env_out = NULL; + + err = mdb_env_create(&env); + if (err) + goto lmdb_error; + + /* Use a pair of files instead of a subdirectory. */ + flags = MDB_NOSUBDIR; + + /* + * For the primary database, tie read transaction locktable slots to the + * transaction and not the thread, so read transactions for iteration + * cursors can coexist with short-lived transactions for operations invoked + * by the iteration callback.. + */ + if (!is_lockout) + flags |= MDB_NOTLS; + + if (readonly) + flags |= MDB_RDONLY; + + /* Durability for lockout records is never worth the performance penalty. + * For the primary environment it might be, so we make it configurable. */ + if (is_lockout || dbc->nosync) + flags |= MDB_NOSYNC; + + /* We use one database in the lockout env, two in the primary env. */ + err = mdb_env_set_maxdbs(env, is_lockout ? 1 : 2); + if (err) + goto lmdb_error; + + if (dbc->mapsize) { + err = mdb_env_set_mapsize(env, dbc->mapsize); + if (err) + goto lmdb_error; + } + + if (dbc->maxreaders) { + err = mdb_env_set_maxreaders(env, dbc->maxreaders); + if (err) + goto lmdb_error; + } + + err = mdb_env_open(env, path, flags, S_IRUSR | S_IWUSR); + if (err) + goto lmdb_error; + + *env_out = env; + return 0; + +lmdb_error: + ret = klerr(context, err, _("LMDB environment open failure")); + mdb_env_close(env); + return ret; +} + +/* Read a key from the primary environment, using a saved read transaction from + * the database context. Return KRB5_KDB_NOENTRY if the key is not found. */ +static krb5_error_code +fetch(krb5_context context, MDB_dbi db, MDB_val *key, MDB_val *val_out) +{ + krb5_error_code ret = 0; + klmdb_context *dbc = context->dal_handle->db_context; + int err; + + if (dbc->read_txn == NULL) + err = mdb_txn_begin(dbc->env, NULL, MDB_RDONLY, &dbc->read_txn); + else + err = mdb_txn_renew(dbc->read_txn); + + if (!err) + err = mdb_get(dbc->read_txn, db, key, val_out); + + if (err == MDB_NOTFOUND) + ret = KRB5_KDB_NOENTRY; + else if (err) + ret = klerr(context, err, _("LMDB read failure")); + + mdb_txn_reset(dbc->read_txn); + return ret; +} + +/* If we are using a lockout database, try to fetch the lockout attributes for + * key and set them in entry. */ +static void +fetch_lockout(krb5_context context, MDB_val *key, krb5_db_entry *entry) +{ + klmdb_context *dbc = context->dal_handle->db_context; + MDB_txn *txn = NULL; + MDB_val val; + int err; + + if (dbc->lockout_env == NULL) + return; + err = mdb_txn_begin(dbc->lockout_env, NULL, MDB_RDONLY, &txn); + if (!err) + err = mdb_get(txn, dbc->lockout_db, key, &val); + if (!err && val.mv_size >= LOCKOUT_RECORD_LEN) + klmdb_decode_princ_lockout(context, entry, val.mv_data); + mdb_txn_abort(txn); +} + +/* + * Store a value for key in the specified database within the primary + * environment. Use the saved load transaction if one is present, or a + * temporary write transaction if not. If no_overwrite is true and the key + * already exists, return KRB5_KDB_INUSE. If must_overwrite is true and the + * key does not already exist, return KRB5_KDB_NOENTRY. + */ +static krb5_error_code +put(krb5_context context, MDB_dbi db, char *keystr, uint8_t *bytes, size_t len, + krb5_boolean no_overwrite, krb5_boolean must_overwrite) +{ + klmdb_context *dbc = context->dal_handle->db_context; + unsigned int putflags = no_overwrite ? MDB_NOOVERWRITE : 0; + MDB_txn *temp_txn = NULL, *txn; + MDB_val key = { strlen(keystr), keystr }, val = { len, bytes }, dummy; + int err; + + if (dbc->load_txn != NULL) { + txn = dbc->load_txn; + } else { + err = mdb_txn_begin(dbc->env, NULL, 0, &temp_txn); + if (err) + goto error; + txn = temp_txn; + } + + if (must_overwrite && mdb_get(txn, db, &key, &dummy) == MDB_NOTFOUND) { + mdb_txn_abort(temp_txn); + return KRB5_KDB_NOENTRY; + } + + err = mdb_put(txn, db, &key, &val, putflags); + if (err) + goto error; + + if (temp_txn != NULL) { + err = mdb_txn_commit(temp_txn); + temp_txn = NULL; + if (err) + goto error; + } + + return 0; + +error: + mdb_txn_abort(temp_txn); + if (err == MDB_KEYEXIST) + return KRB5_KDB_INUSE; + else + return klerr(context, err, _("LMDB write failure")); +} + +/* Delete an entry from the specified env and database, using a temporary write + * transaction. Return KRB5_KDB_NOENTRY if the key does not exist. */ +static krb5_error_code +del(krb5_context context, MDB_env *env, MDB_dbi db, char *keystr) +{ + krb5_error_code ret = 0; + MDB_txn *txn = NULL; + MDB_val key = { strlen(keystr), keystr }; + int err; + + err = mdb_txn_begin(env, NULL, 0, &txn); + if (!err) + err = mdb_del(txn, db, &key, NULL); + if (!err) { + err = mdb_txn_commit(txn); + txn = NULL; + } + + if (err == MDB_NOTFOUND) + ret = KRB5_KDB_NOENTRY; + else if (err) + ret = klerr(context, err, _("LMDB delete failure")); + + mdb_txn_abort(txn); + return ret; +} + +/* Zero out and unlink filename. */ +static krb5_error_code +destroy_file(const char *filename) +{ + krb5_error_code ret; + struct stat st; + ssize_t len; + off_t pos; + uint8_t buf[BUFSIZ], zbuf[BUFSIZ] = { 0 }; + int fd; + + fd = open(filename, O_RDWR | O_CLOEXEC, 0); + if (fd < 0) + return errno; + set_cloexec_fd(fd); + if (fstat(fd, &st) == -1) + goto error; + + memset(zbuf, 0, BUFSIZ); + pos = 0; + while (pos < st.st_size) { + len = read(fd, buf, BUFSIZ); + if (len < 0) + goto error; + /* Only rewrite the block if it's not already zeroed, in case the file + * is sparse. */ + if (memcmp(buf, zbuf, len) != 0) { + (void)lseek(fd, pos, SEEK_SET); + len = write(fd, zbuf, len); + if (len < 0) + goto error; + } + pos += len; + } + close(fd); + + if (unlink(filename) != 0) + return errno; + return 0; + +error: + ret = errno; + close(fd); + return ret; +} + +static krb5_error_code +klmdb_lib_init() +{ + return 0; +} + +static krb5_error_code +klmdb_lib_cleanup() +{ + return 0; +} + +static krb5_error_code +klmdb_fini(krb5_context context) +{ + klmdb_context *dbc; + + dbc = context->dal_handle->db_context; + if (dbc == NULL) + return 0; + mdb_txn_abort(dbc->read_txn); + mdb_txn_abort(dbc->load_txn); + mdb_env_close(dbc->env); + mdb_env_close(dbc->lockout_env); + free(dbc->path); + free(dbc->lockout_path); + free(dbc); + context->dal_handle->db_context = NULL; + return 0; +} + +static krb5_error_code +klmdb_open(krb5_context context, char *conf_section, char **db_args, int mode) +{ + krb5_error_code ret; + klmdb_context *dbc; + krb5_boolean readonly; + MDB_txn *txn = NULL; + struct stat st; + int err; + + if (context->dal_handle->db_context != NULL) + return 0; + + ret = configure_context(context, conf_section, db_args); + if (ret) + return ret; + dbc = context->dal_handle->db_context; + + if (stat(dbc->path, &st) != 0) { + ret = ENOENT; + k5_setmsg(context, ret, _("LMDB file %s does not exist"), dbc->path); + goto error; + } + + /* Open the primary environment and databases. The KDC can open this + * environment read-only. */ + readonly = (mode & KRB5_KDB_OPEN_RO) || (mode & KRB5_KDB_SRV_TYPE_KDC); + ret = open_lmdb_env(context, dbc, FALSE, readonly, &dbc->env); + if (ret) + goto error; + err = mdb_txn_begin(dbc->env, NULL, MDB_RDONLY, &txn); + if (err) + goto lmdb_error; + err = mdb_dbi_open(txn, "principal", 0, &dbc->princ_db); + if (err) + goto lmdb_error; + err = mdb_dbi_open(txn, "policy", 0, &dbc->policy_db); + if (err) + goto lmdb_error; + err = mdb_txn_commit(txn); + txn = NULL; + if (err) + goto lmdb_error; + + /* Open the lockout environment and database if we will need it. */ + if (!dbc->disable_last_success || !dbc->disable_lockout) { + readonly = !!(mode & KRB5_KDB_OPEN_RO); + ret = open_lmdb_env(context, dbc, TRUE, readonly, &dbc->lockout_env); + if (ret) + goto error; + err = mdb_txn_begin(dbc->lockout_env, NULL, MDB_RDONLY, &txn); + if (err) + goto lmdb_error; + err = mdb_dbi_open(txn, "lockout", 0, &dbc->lockout_db); + if (err) + goto lmdb_error; + err = mdb_txn_commit(txn); + txn = NULL; + if (err) + goto lmdb_error; + } + + return 0; + +lmdb_error: + ret = klerr(context, err, _("LMDB open failure")); +error: + mdb_txn_abort(txn); + klmdb_fini(context); + return ret; +} + +static krb5_error_code +klmdb_create(krb5_context context, char *conf_section, char **db_args) +{ + krb5_error_code ret; + klmdb_context *dbc; + MDB_txn *txn = NULL; + struct stat st; + int err; + + if (context->dal_handle->db_context != NULL) + return 0; + + ret = configure_context(context, conf_section, db_args); + if (ret) + return ret; + dbc = context->dal_handle->db_context; + + if (!dbc->temporary) { + if (stat(dbc->path, &st) == 0) { + ret = ENOENT; + k5_setmsg(context, ret, _("LMDB file %s already exists"), + dbc->path); + goto error; + } + } + + /* Open (and create if necessary) the LMDB environments. */ + ret = open_lmdb_env(context, dbc, FALSE, FALSE, &dbc->env); + if (ret) + goto error; + ret = open_lmdb_env(context, dbc, TRUE, FALSE, &dbc->lockout_env); + if (ret) + goto error; + + /* Open the primary databases, creating them if they don't exist. */ + err = mdb_txn_begin(dbc->env, NULL, 0, &txn); + if (err) + goto lmdb_error; + err = mdb_dbi_open(txn, "principal", MDB_CREATE, &dbc->princ_db); + if (err) + goto lmdb_error; + err = mdb_dbi_open(txn, "policy", MDB_CREATE, &dbc->policy_db); + if (err) + goto lmdb_error; + err = mdb_txn_commit(txn); + txn = NULL; + if (err) + goto lmdb_error; + + /* Create the lockout database if it doesn't exist. */ + err = mdb_txn_begin(dbc->lockout_env, NULL, 0, &txn); + if (err) + goto lmdb_error; + err = mdb_dbi_open(txn, "lockout", MDB_CREATE, &dbc->lockout_db); + if (err) + goto lmdb_error; + err = mdb_txn_commit(txn); + txn = NULL; + if (err) + goto lmdb_error; + + if (dbc->temporary) { + /* Create a load transaction and empty the primary databases within + * it. */ + err = mdb_txn_begin(dbc->env, NULL, 0, &dbc->load_txn); + if (err) + goto lmdb_error; + err = mdb_drop(dbc->load_txn, dbc->princ_db, 0); + if (err) + goto lmdb_error; + err = mdb_drop(dbc->load_txn, dbc->policy_db, 0); + if (err) + goto lmdb_error; + } + + /* Close the lockout environment if we won't need it. */ + if (dbc->disable_last_success && dbc->disable_lockout) { + mdb_env_close(dbc->lockout_env); + dbc->lockout_env = NULL; + dbc->lockout_db = 0; + } + + return 0; + +lmdb_error: + ret = klerr(context, err, _("LMDB create error")); +error: + mdb_txn_abort(txn); + klmdb_fini(context); + return ret; +} + +/* Unlink the "-lock" extension of path. */ +static krb5_error_code +unlink_lock_file(krb5_context context, const char *path) +{ + char *lock_path; + int st; + + if (asprintf(&lock_path, "%s-lock", path) < 0) + return ENOMEM; + st = unlink(lock_path); + if (st) + k5_prependmsg(context, st, _("Could not unlink %s"), lock_path); + free(lock_path); + return st; +} + +static krb5_error_code +klmdb_destroy(krb5_context context, char *conf_section, char **db_args) +{ + krb5_error_code ret; + klmdb_context *dbc; + + if (context->dal_handle->db_context != NULL) + klmdb_fini(context); + ret = configure_context(context, conf_section, db_args); + if (ret) + goto cleanup; + dbc = context->dal_handle->db_context; + + ret = destroy_file(dbc->path); + if (ret) + goto cleanup; + ret = unlink_lock_file(context, dbc->path); + if (ret) + goto cleanup; + + ret = destroy_file(dbc->lockout_path); + if (ret) + goto cleanup; + ret = unlink_lock_file(context, dbc->lockout_path); + +cleanup: + klmdb_fini(context); + return ret; +} + +static krb5_error_code +klmdb_get_principal(krb5_context context, krb5_const_principal searchfor, + unsigned int flags, krb5_db_entry **entry_out) +{ + krb5_error_code ret; + klmdb_context *dbc = context->dal_handle->db_context; + MDB_val key, val; + char *name = NULL; + + *entry_out = NULL; + if (dbc == NULL) + return KRB5_KDB_DBNOTINITED; + + ret = krb5_unparse_name(context, searchfor, &name); + if (ret) + goto cleanup; + + key.mv_data = name; + key.mv_size = strlen(name); + ret = fetch(context, dbc->princ_db, &key, &val); + if (ret) + goto cleanup; + + ret = klmdb_decode_princ(context, name, strlen(name), + val.mv_data, val.mv_size, entry_out); + if (ret) + goto cleanup; + + fetch_lockout(context, &key, *entry_out); + +cleanup: + krb5_free_unparsed_name(context, name); + return ret; +} + +static krb5_error_code +klmdb_put_principal(krb5_context context, krb5_db_entry *entry, char **db_args) +{ + krb5_error_code ret; + klmdb_context *dbc = context->dal_handle->db_context; + MDB_val key, val, dummy; + MDB_txn *txn = NULL; + uint8_t lockout[LOCKOUT_RECORD_LEN], *enc; + size_t len; + char *name = NULL; + int err; + + if (db_args != NULL) { + /* This module does not support DB arguments for put_principal. */ + k5_setmsg(context, EINVAL, _("Unsupported argument \"%s\" for lmdb"), + db_args[0]); + return EINVAL; + } + + if (dbc == NULL) + return KRB5_KDB_DBNOTINITED; + + ret = krb5_unparse_name(context, entry->princ, &name); + if (ret) + goto cleanup; + + ret = klmdb_encode_princ(context, entry, &enc, &len); + if (ret) + goto cleanup; + ret = put(context, dbc->princ_db, name, enc, len, FALSE, FALSE); + free(enc); + if (ret) + goto cleanup; + + /* + * Write the lockout attributes to the lockout database if we are using + * one. During a load operation, changes to lockout attributes will become + * visible before the load is finished, which is an acceptable compromise + * on load atomicity. + */ + if (dbc->lockout_env != NULL && + (entry->mask & (LOCKOUT_MASK | KADM5_PRINCIPAL))) { + key.mv_data = name; + key.mv_size = strlen(name); + klmdb_encode_princ_lockout(context, entry, lockout); + val.mv_data = lockout; + val.mv_size = sizeof(lockout); + err = mdb_txn_begin(dbc->lockout_env, NULL, 0, &txn); + if (!err && dbc->merge_nra) { + /* During an iprop load, do not change existing lockout entries. */ + if (mdb_get(txn, dbc->lockout_db, &key, &dummy) == 0) + goto cleanup; + } + if (!err) + err = mdb_put(txn, dbc->lockout_db, &key, &val, 0); + if (!err) { + err = mdb_txn_commit(txn); + txn = NULL; + } + if (err) { + ret = klerr(context, err, _("LMDB lockout write failure")); + goto cleanup; + } + } + +cleanup: + mdb_txn_abort(txn); + krb5_free_unparsed_name(context, name); + return ret; +} + +static krb5_error_code +klmdb_delete_principal(krb5_context context, krb5_const_principal searchfor) +{ + krb5_error_code ret; + klmdb_context *dbc = context->dal_handle->db_context; + char *name; + + if (dbc == NULL) + return KRB5_KDB_DBNOTINITED; + + ret = krb5_unparse_name(context, searchfor, &name); + if (ret) + return ret; + + ret = del(context, dbc->env, dbc->princ_db, name); + if (!ret && dbc->lockout_env != NULL) + (void)del(context, dbc->lockout_env, dbc->lockout_db, name); + + krb5_free_unparsed_name(context, name); + return ret; +} + +static krb5_error_code +klmdb_iterate(krb5_context context, char *match_expr, + krb5_error_code (*func)(void *, krb5_db_entry *), void *arg, + krb5_flags iterflags) +{ + krb5_error_code ret; + klmdb_context *dbc = context->dal_handle->db_context; + krb5_db_entry *entry; + MDB_txn *txn = NULL; + MDB_cursor *cursor = NULL; + MDB_val key, val; + MDB_cursor_op op = (iterflags & KRB5_DB_ITER_REV) ? MDB_PREV : MDB_NEXT; + int err; + + if (dbc == NULL) + return KRB5_KDB_DBNOTINITED; + + err = mdb_txn_begin(dbc->env, NULL, MDB_RDONLY, &txn); + if (err) + goto lmdb_error; + err = mdb_cursor_open(txn, dbc->princ_db, &cursor); + if (err) + goto lmdb_error; + for (;;) { + err = mdb_cursor_get(cursor, &key, &val, op); + if (err == MDB_NOTFOUND) + break; + if (err) + goto lmdb_error; + ret = klmdb_decode_princ(context, key.mv_data, key.mv_size, + val.mv_data, val.mv_size, &entry); + if (ret) + goto cleanup; + fetch_lockout(context, &key, entry); + ret = (*func)(arg, entry); + krb5_db_free_principal(context, entry); + if (ret) + goto cleanup; + } + ret = 0; + goto cleanup; + +lmdb_error: + ret = klerr(context, err, _("LMDB principal iteration failure")); +cleanup: + mdb_cursor_close(cursor); + mdb_txn_abort(txn); + return ret; +} + +krb5_error_code +klmdb_get_policy(krb5_context context, char *name, osa_policy_ent_t *policy) +{ + krb5_error_code ret; + klmdb_context *dbc = context->dal_handle->db_context; + MDB_val key, val; + + *policy = NULL; + if (dbc == NULL) + return KRB5_KDB_DBNOTINITED; + + key.mv_data = name; + key.mv_size = strlen(name); + ret = fetch(context, dbc->policy_db, &key, &val); + if (ret) + return ret; + return klmdb_decode_policy(context, name, strlen(name), + val.mv_data, val.mv_size, policy); +} + +static krb5_error_code +klmdb_create_policy(krb5_context context, osa_policy_ent_t policy) +{ + krb5_error_code ret; + klmdb_context *dbc = context->dal_handle->db_context; + uint8_t *enc; + size_t len; + + if (dbc == NULL) + return KRB5_KDB_DBNOTINITED; + + ret = klmdb_encode_policy(context, policy, &enc, &len); + if (ret) + return ret; + ret = put(context, dbc->policy_db, policy->name, enc, len, TRUE, FALSE); + free(enc); + return ret; +} + +static krb5_error_code +klmdb_put_policy(krb5_context context, osa_policy_ent_t policy) +{ + krb5_error_code ret; + klmdb_context *dbc = context->dal_handle->db_context; + uint8_t *enc; + size_t len; + + if (dbc == NULL) + return KRB5_KDB_DBNOTINITED; + + ret = klmdb_encode_policy(context, policy, &enc, &len); + if (ret) + return ret; + ret = put(context, dbc->policy_db, policy->name, enc, len, FALSE, TRUE); + free(enc); + return ret; +} + +static krb5_error_code +klmdb_iter_policy(krb5_context context, char *match_entry, + osa_adb_iter_policy_func func, void *arg) +{ + krb5_error_code ret; + klmdb_context *dbc = context->dal_handle->db_context; + osa_policy_ent_t pol; + MDB_txn *txn = NULL; + MDB_cursor *cursor = NULL; + MDB_val key, val; + int err; + + if (dbc == NULL) + return KRB5_KDB_DBNOTINITED; + + err = mdb_txn_begin(dbc->env, NULL, MDB_RDONLY, &txn); + if (err) + goto lmdb_error; + err = mdb_cursor_open(txn, dbc->policy_db, &cursor); + if (err) + goto lmdb_error; + for (;;) { + err = mdb_cursor_get(cursor, &key, &val, MDB_NEXT); + if (err == MDB_NOTFOUND) + break; + if (err) + goto lmdb_error; + ret = klmdb_decode_policy(context, key.mv_data, key.mv_size, + val.mv_data, val.mv_size, &pol); + if (ret) + goto cleanup; + (*func)(arg, pol); + krb5_db_free_policy(context, pol); + } + ret = 0; + goto cleanup; + +lmdb_error: + ret = klerr(context, err, _("LMDB policy iteration failure")); +cleanup: + mdb_cursor_close(cursor); + mdb_txn_abort(txn); + return ret; +} + +static krb5_error_code +klmdb_delete_policy(krb5_context context, char *policy) +{ + klmdb_context *dbc = context->dal_handle->db_context; + + if (dbc == NULL) + return KRB5_KDB_DBNOTINITED; + return del(context, dbc->env, dbc->policy_db, policy); +} + +static krb5_error_code +klmdb_promote_db(krb5_context context, char *conf_section, char **db_args) +{ + krb5_error_code ret = 0; + klmdb_context *dbc = context->dal_handle->db_context; + int err; + + if (dbc == NULL) + return KRB5_KDB_DBNOTINITED; + if (dbc->load_txn == NULL) + return EINVAL; + err = mdb_txn_commit(dbc->load_txn); + dbc->load_txn = NULL; + if (err) + ret = klerr(context, err, _("LMDB transaction commit failure")); + klmdb_fini(context); + return ret; +} + +static krb5_error_code +klmdb_check_policy_as(krb5_context context, krb5_kdc_req *request, + krb5_db_entry *client, krb5_db_entry *server, + krb5_timestamp kdc_time, const char **status, + krb5_pa_data ***e_data) +{ + krb5_error_code ret; + klmdb_context *dbc = context->dal_handle->db_context; + + if (dbc->disable_lockout) + return 0; + + ret = klmdb_lockout_check_policy(context, client, kdc_time); + if (ret == KRB5KDC_ERR_CLIENT_REVOKED) + *status = "LOCKED_OUT"; + return ret; +} + +static void +klmdb_audit_as_req(krb5_context context, krb5_kdc_req *request, + const krb5_address *local_addr, + const krb5_address *remote_addr, krb5_db_entry *client, + krb5_db_entry *server, krb5_timestamp authtime, + krb5_error_code status) +{ + klmdb_context *dbc = context->dal_handle->db_context; + + (void)klmdb_lockout_audit(context, client, authtime, status, + dbc->disable_last_success, dbc->disable_lockout); +} + +krb5_error_code +klmdb_update_lockout(krb5_context context, krb5_db_entry *entry, + krb5_timestamp stamp, krb5_boolean zero_fail_count, + krb5_boolean set_last_success, + krb5_boolean set_last_failure) +{ + krb5_error_code ret; + klmdb_context *dbc = context->dal_handle->db_context; + krb5_db_entry dummy = { 0 }; + uint8_t lockout[LOCKOUT_RECORD_LEN]; + MDB_txn *txn = NULL; + MDB_val key, val; + char *name = NULL; + int err; + + if (dbc == NULL) + return KRB5_KDB_DBNOTINITED; + if (dbc->lockout_env == NULL) + return 0; + if (!zero_fail_count && !set_last_success && !set_last_failure) + return 0; + + ret = krb5_unparse_name(context, entry->princ, &name); + if (ret) + goto cleanup; + key.mv_data = name; + key.mv_size = strlen(name); + + err = mdb_txn_begin(dbc->lockout_env, NULL, 0, &txn); + if (err) + goto lmdb_error; + /* Fetch base lockout info within txn so we update transactionally. */ + err = mdb_get(txn, dbc->lockout_db, &key, &val); + if (!err && val.mv_size >= LOCKOUT_RECORD_LEN) { + klmdb_decode_princ_lockout(context, &dummy, val.mv_data); + } else { + dummy.last_success = entry->last_success; + dummy.last_failed = entry->last_failed; + dummy.fail_auth_count = entry->fail_auth_count; + } + + if (zero_fail_count) + dummy.fail_auth_count = 0; + if (set_last_success) + dummy.last_success = stamp; + if (set_last_failure) { + dummy.last_failed = stamp; + dummy.fail_auth_count++; + } + + klmdb_encode_princ_lockout(context, &dummy, lockout); + val.mv_data = lockout; + val.mv_size = sizeof(lockout); + err = mdb_put(txn, dbc->lockout_db, &key, &val, 0); + if (err) + goto lmdb_error; + err = mdb_txn_commit(txn); + txn = NULL; + if (err) + goto lmdb_error; + goto cleanup; + +lmdb_error: + ret = klerr(context, err, _("LMDB lockout update failure")); +cleanup: + krb5_free_unparsed_name(context, name); + mdb_txn_abort(txn); + return 0; +} + +kdb_vftabl PLUGIN_SYMBOL_NAME(krb5_lmdb, kdb_function_table) = { + .maj_ver = KRB5_KDB_DAL_MAJOR_VERSION, + .min_ver = 0, + .init_library = klmdb_lib_init, + .fini_library = klmdb_lib_cleanup, + .init_module = klmdb_open, + .fini_module = klmdb_fini, + .create = klmdb_create, + .destroy = klmdb_destroy, + .get_principal = klmdb_get_principal, + .put_principal = klmdb_put_principal, + .delete_principal = klmdb_delete_principal, + .iterate = klmdb_iterate, + .create_policy = klmdb_create_policy, + .get_policy = klmdb_get_policy, + .put_policy = klmdb_put_policy, + .iter_policy = klmdb_iter_policy, + .delete_policy = klmdb_delete_policy, + .promote_db = klmdb_promote_db, + .check_policy_as = klmdb_check_policy_as, + .audit_as_req = klmdb_audit_as_req +}; diff --git a/krb5-1.21.3/src/plugins/kdb/lmdb/klmdb-int.h b/krb5-1.21.3/src/plugins/kdb/lmdb/klmdb-int.h new file mode 100644 index 00000000..29bceae6 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/lmdb/klmdb-int.h @@ -0,0 +1,78 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/lmdb/klmdb-int.h - internal declarations for LMDB KDB module */ +/* + * Copyright (C) 2018 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. + */ + +#ifndef LMDB_INT_H +#define LMDB_INT_H + +/* Length of a principal lockout record (three 32-bit fields) */ +#define LOCKOUT_RECORD_LEN 12 + +krb5_error_code klmdb_encode_princ(krb5_context context, + const krb5_db_entry *entry, + uint8_t **enc_out, size_t *len_out); +void klmdb_encode_princ_lockout(krb5_context context, + const krb5_db_entry *entry, + uint8_t buf[LOCKOUT_RECORD_LEN]); +krb5_error_code klmdb_encode_policy(krb5_context context, + const osa_policy_ent_rec *pol, + uint8_t **enc_out, size_t *len_out); + +krb5_error_code klmdb_decode_princ(krb5_context context, + const void *key, size_t key_len, + const void *enc, size_t enc_len, + krb5_db_entry **entry_out); +void klmdb_decode_princ_lockout(krb5_context context, krb5_db_entry *entry, + const uint8_t buf[LOCKOUT_RECORD_LEN]); +krb5_error_code klmdb_decode_policy(krb5_context context, + const void *key, size_t key_len, + const void *enc, size_t enc_len, + osa_policy_ent_t *pol_out); + +krb5_error_code klmdb_lockout_check_policy(krb5_context context, + krb5_db_entry *entry, + krb5_timestamp stamp); +krb5_error_code klmdb_lockout_audit(krb5_context context, krb5_db_entry *entry, + krb5_timestamp stamp, + krb5_error_code status, + krb5_boolean disable_last_success, + krb5_boolean disable_lockout); +krb5_error_code klmdb_update_lockout(krb5_context context, + krb5_db_entry *entry, + krb5_timestamp stamp, + krb5_boolean zero_fail_count, + krb5_boolean set_last_success, + krb5_boolean set_last_failure); + +krb5_error_code klmdb_get_policy(krb5_context context, char *name, + osa_policy_ent_t *policy); + +#endif /* LMDB_INT_H */ diff --git a/krb5-1.21.3/src/plugins/kdb/lmdb/klmdb.exports b/krb5-1.21.3/src/plugins/kdb/lmdb/klmdb.exports new file mode 100644 index 00000000..f2b7c111 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/lmdb/klmdb.exports @@ -0,0 +1 @@ +kdb_function_table diff --git a/krb5-1.21.3/src/plugins/kdb/lmdb/lockout.c b/krb5-1.21.3/src/plugins/kdb/lmdb/lockout.c new file mode 100644 index 00000000..380d8b30 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/lmdb/lockout.c @@ -0,0 +1,180 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/lmdb/lockout.c */ +/* + * Copyright (C) 2009, 2018 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "kdb.h" +#include +#include "kdb5.h" +#include "klmdb-int.h" + +static krb5_error_code +lookup_lockout_policy(krb5_context context, krb5_db_entry *entry, + krb5_kvno *pw_max_fail, krb5_deltat *pw_failcnt_interval, + krb5_deltat *pw_lockout_duration) +{ + krb5_tl_data tl_data; + krb5_error_code code; + osa_princ_ent_rec adb; + XDR xdrs; + + *pw_max_fail = 0; + *pw_failcnt_interval = 0; + *pw_lockout_duration = 0; + + tl_data.tl_data_type = KRB5_TL_KADM_DATA; + + code = krb5_dbe_lookup_tl_data(context, entry, &tl_data); + if (code != 0 || tl_data.tl_data_length == 0) + return code; + + memset(&adb, 0, sizeof(adb)); + xdrmem_create(&xdrs, (char *)tl_data.tl_data_contents, + tl_data.tl_data_length, XDR_DECODE); + if (!xdr_osa_princ_ent_rec(&xdrs, &adb)) { + xdr_destroy(&xdrs); + return KADM5_XDR_FAILURE; + } + + if (adb.policy != NULL) { + osa_policy_ent_t policy = NULL; + + code = klmdb_get_policy(context, adb.policy, &policy); + if (code == 0) { + *pw_max_fail = policy->pw_max_fail; + *pw_failcnt_interval = policy->pw_failcnt_interval; + *pw_lockout_duration = policy->pw_lockout_duration; + krb5_db_free_policy(context, policy); + } + } + + xdr_destroy(&xdrs); + + xdrmem_create(&xdrs, NULL, 0, XDR_FREE); + xdr_osa_princ_ent_rec(&xdrs, &adb); + xdr_destroy(&xdrs); + + return 0; +} + +/* draft-behera-ldap-password-policy-10.txt 7.1 */ +static krb5_boolean +locked_check_p(krb5_context context, krb5_timestamp stamp, krb5_kvno max_fail, + krb5_timestamp lockout_duration, krb5_db_entry *entry) +{ + krb5_timestamp unlock_time; + + /* If the entry was unlocked since the last failure, it's not locked. */ + if (krb5_dbe_lookup_last_admin_unlock(context, entry, &unlock_time) == 0 && + !ts_after(entry->last_failed, unlock_time)) + return FALSE; + + if (max_fail == 0 || entry->fail_auth_count < max_fail) + return FALSE; + + if (lockout_duration == 0) + return TRUE; /* principal permanently locked */ + + return ts_after(ts_incr(entry->last_failed, lockout_duration), stamp); +} + +krb5_error_code +klmdb_lockout_check_policy(krb5_context context, krb5_db_entry *entry, + krb5_timestamp stamp) +{ + krb5_error_code code; + krb5_kvno max_fail = 0; + krb5_deltat failcnt_interval = 0; + krb5_deltat lockout_duration = 0; + + code = lookup_lockout_policy(context, entry, &max_fail, &failcnt_interval, + &lockout_duration); + if (code != 0) + return code; + + if (locked_check_p(context, stamp, max_fail, lockout_duration, entry)) + return KRB5KDC_ERR_CLIENT_REVOKED; + + return 0; +} + +krb5_error_code +klmdb_lockout_audit(krb5_context context, krb5_db_entry *entry, + krb5_timestamp stamp, krb5_error_code status, + krb5_boolean disable_last_success, + krb5_boolean disable_lockout) +{ + krb5_error_code ret; + krb5_kvno max_fail = 0; + krb5_deltat failcnt_interval = 0, lockout_duration = 0; + krb5_boolean zero_fail_count = FALSE; + krb5_boolean set_last_success = FALSE, set_last_failure = FALSE; + krb5_timestamp unlock_time; + + if (status != 0 && status != KRB5KDC_ERR_PREAUTH_FAILED && + status != KRB5KRB_AP_ERR_BAD_INTEGRITY) + return 0; + + if (!disable_lockout) { + ret = lookup_lockout_policy(context, entry, &max_fail, + &failcnt_interval, &lockout_duration); + if (ret) + return ret; + } + + /* + * Don't continue to modify the DB for an already locked account. + * (In most cases, status will be KRB5KDC_ERR_CLIENT_REVOKED, and + * this check is unneeded, but in rare cases, we can fail with an + * integrity error or preauth failure before a policy check.) + */ + if (locked_check_p(context, stamp, max_fail, lockout_duration, entry)) + return 0; + + /* Only mark the authentication as successful if the entry + * required preauthentication; otherwise we have no idea. */ + if (status == 0 && (entry->attributes & KRB5_KDB_REQUIRES_PRE_AUTH)) { + if (!disable_lockout && entry->fail_auth_count != 0) + zero_fail_count = TRUE; + if (!disable_last_success) + set_last_success = TRUE; + } else if (status != 0 && !disable_lockout) { + /* Reset the failure counter after an administrative unlock. */ + if (krb5_dbe_lookup_last_admin_unlock(context, entry, + &unlock_time) == 0 && + !ts_after(entry->last_failed, unlock_time)) + zero_fail_count = TRUE; + + /* Reset the failure counter after failcnt_interval. */ + if (failcnt_interval != 0 && + ts_after(stamp, ts_incr(entry->last_failed, failcnt_interval))) + zero_fail_count = TRUE; + + set_last_failure = TRUE; + } + + return klmdb_update_lockout(context, entry, stamp, zero_fail_count, + set_last_success, set_last_failure); +} diff --git a/krb5-1.21.3/src/plugins/kdb/lmdb/marshal.c b/krb5-1.21.3/src/plugins/kdb/lmdb/marshal.c new file mode 100644 index 00000000..433bb816 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/lmdb/marshal.c @@ -0,0 +1,321 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/kdb/kdb_xdr.c */ +/* + * Copyright (C) 2018 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. + */ + +#include "k5-int.h" +#include "k5-input.h" +#include +#include "klmdb-int.h" + +static void +put_tl_data(struct k5buf *buf, const krb5_tl_data *tl) +{ + for (; tl != NULL; tl = tl->tl_data_next) { + k5_buf_add_uint16_le(buf, tl->tl_data_type); + k5_buf_add_uint16_le(buf, tl->tl_data_length); + k5_buf_add_len(buf, tl->tl_data_contents, tl->tl_data_length); + } +} + +krb5_error_code +klmdb_encode_princ(krb5_context context, const krb5_db_entry *entry, + uint8_t **enc_out, size_t *len_out) +{ + struct k5buf buf; + const krb5_key_data *kd; + int i, j; + + *enc_out = NULL; + *len_out = 0; + + k5_buf_init_dynamic(&buf); + + k5_buf_add_uint32_le(&buf, entry->attributes); + k5_buf_add_uint32_le(&buf, entry->max_life); + k5_buf_add_uint32_le(&buf, entry->max_renewable_life); + k5_buf_add_uint32_le(&buf, entry->expiration); + k5_buf_add_uint32_le(&buf, entry->pw_expiration); + k5_buf_add_uint16_le(&buf, entry->n_tl_data); + k5_buf_add_uint16_le(&buf, entry->n_key_data); + put_tl_data(&buf, entry->tl_data); + for (i = 0; i < entry->n_key_data; i++) { + kd = &entry->key_data[i]; + k5_buf_add_uint16_le(&buf, kd->key_data_ver); + k5_buf_add_uint16_le(&buf, kd->key_data_kvno); + for (j = 0; j < kd->key_data_ver; j++) { + k5_buf_add_uint16_le(&buf, kd->key_data_type[j]); + k5_buf_add_uint16_le(&buf, kd->key_data_length[j]); + if (kd->key_data_length[j] > 0) { + k5_buf_add_len(&buf, kd->key_data_contents[j], + kd->key_data_length[j]); + } + } + } + + if (k5_buf_status(&buf) != 0) + return ENOMEM; + + *enc_out = buf.data; + *len_out = buf.len; + return 0; +} + +void +klmdb_encode_princ_lockout(krb5_context context, const krb5_db_entry *entry, + uint8_t buf[LOCKOUT_RECORD_LEN]) +{ + store_32_le(entry->last_success, buf); + store_32_le(entry->last_failed, buf + 4); + store_32_le(entry->fail_auth_count, buf + 8); +} + +krb5_error_code +klmdb_encode_policy(krb5_context context, const osa_policy_ent_rec *pol, + uint8_t **enc_out, size_t *len_out) +{ + struct k5buf buf; + + *enc_out = NULL; + *len_out = 0; + + k5_buf_init_dynamic(&buf); + k5_buf_add_uint32_le(&buf, pol->pw_min_life); + k5_buf_add_uint32_le(&buf, pol->pw_max_life); + k5_buf_add_uint32_le(&buf, pol->pw_min_length); + k5_buf_add_uint32_le(&buf, pol->pw_min_classes); + k5_buf_add_uint32_le(&buf, pol->pw_history_num); + k5_buf_add_uint32_le(&buf, pol->pw_max_fail); + k5_buf_add_uint32_le(&buf, pol->pw_failcnt_interval); + k5_buf_add_uint32_le(&buf, pol->pw_lockout_duration); + k5_buf_add_uint32_le(&buf, pol->attributes); + k5_buf_add_uint32_le(&buf, pol->max_life); + k5_buf_add_uint32_le(&buf, pol->max_renewable_life); + + if (pol->allowed_keysalts == NULL) { + k5_buf_add_uint32_le(&buf, 0); + } else { + k5_buf_add_uint32_le(&buf, strlen(pol->allowed_keysalts)); + k5_buf_add(&buf, pol->allowed_keysalts); + } + + k5_buf_add_uint16_le(&buf, pol->n_tl_data); + put_tl_data(&buf, pol->tl_data); + + if (k5_buf_status(&buf) != 0) + return ENOMEM; + + *enc_out = buf.data; + *len_out = buf.len; + return 0; +} + +static krb5_error_code +get_tl_data(struct k5input *in, size_t count, krb5_tl_data **tl) +{ + krb5_error_code ret; + const uint8_t *contents; + size_t i, len; + + for (i = 0; i < count; i++) { + *tl = k5alloc(sizeof(**tl), &ret); + if (*tl == NULL) + return ret; + (*tl)->tl_data_type = k5_input_get_uint16_le(in); + len = (*tl)->tl_data_length = k5_input_get_uint16_le(in); + contents = k5_input_get_bytes(in, len); + if (contents == NULL) + return KRB5_KDB_TRUNCATED_RECORD; + (*tl)->tl_data_contents = k5memdup(contents, len, &ret); + if ((*tl)->tl_data_contents == NULL) + return ret; + tl = &(*tl)->tl_data_next; + } + + return 0; +} + +krb5_error_code +klmdb_decode_princ(krb5_context context, const void *key, size_t key_len, + const void *enc, size_t enc_len, krb5_db_entry **entry_out) +{ + krb5_error_code ret; + struct k5input in; + krb5_db_entry *entry = NULL; + char *princname = NULL; + const uint8_t *contents; + int i, j; + size_t len; + krb5_key_data *kd; + + *entry_out = NULL; + + entry = k5alloc(sizeof(*entry), &ret); + if (entry == NULL) + goto cleanup; + + princname = k5memdup0(key, key_len, &ret); + if (princname == NULL) + goto cleanup; + ret = krb5_parse_name(context, princname, &entry->princ); + if (ret) + goto cleanup; + + k5_input_init(&in, enc, enc_len); + entry->attributes = k5_input_get_uint32_le(&in); + entry->max_life = k5_input_get_uint32_le(&in); + entry->max_renewable_life = k5_input_get_uint32_le(&in); + entry->expiration = k5_input_get_uint32_le(&in); + entry->pw_expiration = k5_input_get_uint32_le(&in); + entry->n_tl_data = k5_input_get_uint16_le(&in); + entry->n_key_data = k5_input_get_uint16_le(&in); + if (entry->n_tl_data < 0 || entry->n_key_data < 0) { + ret = KRB5_KDB_TRUNCATED_RECORD; + goto cleanup; + } + + ret = get_tl_data(&in, entry->n_tl_data, &entry->tl_data); + if (ret) + goto cleanup; + + if (entry->n_key_data > 0) { + entry->key_data = k5calloc(entry->n_key_data, sizeof(*entry->key_data), + &ret); + if (entry->key_data == NULL) + goto cleanup; + } + for (i = 0; i < entry->n_key_data; i++) { + kd = &entry->key_data[i]; + kd->key_data_ver = k5_input_get_uint16_le(&in); + kd->key_data_kvno = k5_input_get_uint16_le(&in); + if (kd->key_data_ver < 0 && + kd->key_data_ver > KRB5_KDB_V1_KEY_DATA_ARRAY) { + ret = KRB5_KDB_BAD_VERSION; + goto cleanup; + } + for (j = 0; j < kd->key_data_ver; j++) { + kd->key_data_type[j] = k5_input_get_uint16_le(&in); + len = kd->key_data_length[j] = k5_input_get_uint16_le(&in); + contents = k5_input_get_bytes(&in, len); + if (contents == NULL) { + ret = KRB5_KDB_TRUNCATED_RECORD; + goto cleanup; + } + if (len > 0) { + kd->key_data_contents[j] = k5memdup(contents, len, &ret); + if (kd->key_data_contents[j] == NULL) + goto cleanup; + } + } + } + + ret = in.status; + if (ret) + goto cleanup; + + entry->len = KRB5_KDB_V1_BASE_LENGTH; + *entry_out = entry; + entry = NULL; + +cleanup: + free(princname); + krb5_db_free_principal(context, entry); + return ret; +} + +void +klmdb_decode_princ_lockout(krb5_context context, krb5_db_entry *entry, + const uint8_t buf[LOCKOUT_RECORD_LEN]) +{ + entry->last_success = load_32_le(buf); + entry->last_failed = load_32_le(buf + 4); + entry->fail_auth_count = load_32_le(buf + 8); +} + +krb5_error_code +klmdb_decode_policy(krb5_context context, const void *key, size_t key_len, + const void *enc, size_t enc_len, osa_policy_ent_t *pol_out) +{ + krb5_error_code ret; + osa_policy_ent_t pol = NULL; + struct k5input in; + const char *str; + size_t len; + + *pol_out = NULL; + pol = k5alloc(sizeof(*pol), &ret); + if (pol == NULL) + goto error; + + pol->name = k5memdup0(key, key_len, &ret); + if (pol->name == NULL) + goto error; + + k5_input_init(&in, enc, enc_len); + pol->pw_min_life = k5_input_get_uint32_le(&in); + pol->pw_max_life = k5_input_get_uint32_le(&in); + pol->pw_min_length = k5_input_get_uint32_le(&in); + pol->pw_min_classes = k5_input_get_uint32_le(&in); + pol->pw_history_num = k5_input_get_uint32_le(&in); + pol->pw_max_fail = k5_input_get_uint32_le(&in); + pol->pw_failcnt_interval = k5_input_get_uint32_le(&in); + pol->pw_lockout_duration = k5_input_get_uint32_le(&in); + pol->attributes = k5_input_get_uint32_le(&in); + pol->max_life = k5_input_get_uint32_le(&in); + pol->max_renewable_life = k5_input_get_uint32_le(&in); + + len = k5_input_get_uint32_le(&in); + if (len > 0) { + str = (char *)k5_input_get_bytes(&in, len); + if (str == NULL) { + ret = KRB5_KDB_TRUNCATED_RECORD; + goto error; + } + pol->allowed_keysalts = k5memdup0(str, len, &ret); + if (pol->allowed_keysalts == NULL) + goto error; + } + + pol->n_tl_data = k5_input_get_uint16_le(&in); + ret = get_tl_data(&in, pol->n_tl_data, &pol->tl_data); + if (ret) + goto error; + + ret = in.status; + if (ret) + goto error; + + *pol_out = pol; + return 0; + +error: + krb5_db_free_policy(context, pol); + return ret; +} diff --git a/krb5-1.21.3/src/plugins/kdb/test/Makefile.in b/krb5-1.21.3/src/plugins/kdb/test/Makefile.in new file mode 100644 index 00000000..90060231 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/test/Makefile.in @@ -0,0 +1,21 @@ +mydir=plugins$(S)kdb$(S)test +BUILDTOP=$(REL)..$(S)..$(S).. + +LIBBASE=test +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/kdb/test +SHLIB_EXPDEPS=$(KADMSRV_DEPLIB) $(KRB5_BASE_DEPLIBS) +SHLIB_EXPLIBS=$(KADMSRV_LIBS) $(KRB5_BASE_LIBS) +LOCALINCLUDES=-I../../../lib/kdb -I$(srcdir)/../../../lib/kdb + +SRCS = $(srcdir)/kdb_test.c + +STLIBOBJS = kdb_test.o + +all-unix: all-liblinks +install-unix: +clean-unix:: clean-liblinks clean-libs clean-libobjs + +@libnover_frag@ +@libobj_frag@ diff --git a/krb5-1.21.3/src/plugins/kdb/test/deps b/krb5-1.21.3/src/plugins/kdb/test/deps new file mode 100644 index 00000000..fcd40b65 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/test/deps @@ -0,0 +1,15 @@ +# +# Generated makefile dependencies follow. +# +kdb_test.so kdb_test.po $(OUTPRE)kdb_test.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../../lib/kdb/kdb5.h $(top_srcdir)/include/adm_proto.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdb_test.c diff --git a/krb5-1.21.3/src/plugins/kdb/test/kdb_test.c b/krb5-1.21.3/src/plugins/kdb/test/kdb_test.c new file mode 100644 index 00000000..f4d4380d --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/test/kdb_test.c @@ -0,0 +1,820 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/kdb/test/kdb_test.c - Test KDB module */ +/* + * Copyright (C) 2015 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. + */ + +/* + * This is a read-only KDB module intended to help test KDC behavior which + * cannot be exercised with the DB2 module. Responses are read from the + * dbmodules subsection according to this example: + * + * [dbmodules] + * test = { + * alias = { + * aliasname = canonname + * # For cross-realm aliases, only the realm part will + * # matter to the client. + * aliasname = @FOREIGN_REALM + * enterprise@PRINC = @FOREIGN_REALM + * } + * princs = { + * krbtgt/KRBTEST.COM = { + * flags = +preauth +ok-to-auth-as-delegate + * maxlife = 1d + * maxrenewlife = 7d + * expiration = 14d # relative to current time + * pwexpiration = 1h + * # Initial number is kvno; defaults to 1. + * keys = 3 aes256-cts aes128-cts:normal + * keys = 2 rc4-hmac + * strings = key1:value1 + * strings = key2:value2 + * } + * } + * delegation = { + * # Traditional constrained delegation; target_service + * # must be in the same realm. + * intermediate_service = target_service + * } + * rbcd = { + * # Resource-based constrained delegation; + * # intermediate_service may be in a different realm. + * target_service = intermediate_service + * } + * } + * + * Key values are generated using a hash of the kvno, enctype, salt type, + * principal name, and lookup realm. This module does not use master key + * encryption, so it serves as a partial test of the DAL's ability to avoid + * that. + * + * Inbound cross-realm TGT entries are currently implicit; they will use the + * same configuration and key enctypes as the local krbtgt principal, although + * they will use different keys (because the lookup realm is hashed in). + * Outgoing cross-realm TGT entries must be added explicitly + * (krbtgt/OTHER_REALM). + */ + +#include "k5-int.h" +#include "kdb5.h" +#include "adm_proto.h" +#include + +#define TEST_AD_TYPE -456 + +#define IS_TGS_PRINC(p) ((p)->length == 2 && \ + data_eq_string((p)->data[0], KRB5_TGS_NAME)) + +typedef struct { + void *profile; + char *section; + const char *names[6]; +} *testhandle; + +static void * +ealloc(size_t sz) +{ + void *p = calloc(sz, 1); + + if (p == NULL) + abort(); + return p; +} + +static char * +estrdup(const char *s) +{ + char *copy = strdup(s); + + if (copy == NULL) + abort(); + return copy; +} + +static void +check(krb5_error_code code) +{ + if (code != 0) + abort(); +} + +/* Set up for a profile query using h->names. Look up s1 -> s2 -> s3 (some of + * which may be NULL) within this database's dbmodules section. */ +static void +set_names(testhandle h, const char *s1, const char *s2, const char *s3) +{ + h->names[0] = KDB_MODULE_SECTION; + h->names[1] = h->section; + h->names[2] = s1; + h->names[3] = s2; + h->names[4] = s3; + h->names[5] = NULL; +} + +/* Look up a string within this database's dbmodules section. */ +static char * +get_string(testhandle h, const char *s1, const char *s2, const char *s3) +{ + krb5_error_code ret; + char **values, *val; + + set_names(h, s1, s2, s3); + ret = profile_get_values(h->profile, h->names, &values); + if (ret == PROF_NO_RELATION) + return NULL; + if (ret) + abort(); + val = estrdup(values[0]); + profile_free_list(values); + return val; +} + +/* Look up a duration within this database's dbmodules section. */ +static krb5_deltat +get_duration(testhandle h, const char *s1, const char *s2, const char *s3) +{ + char *strval = get_string(h, s1, s2, s3); + krb5_deltat val; + + if (strval == NULL) + return 0; + check(krb5_string_to_deltat(strval, &val)); + free(strval); + return val; +} + +/* Look up an absolute time within this database's dbmodules section. The time + * is expressed in the profile as an interval relative to the current time. */ +static krb5_timestamp +get_time(testhandle h, const char *s1, const char *s2, const char *s3) +{ + char *strval = get_string(h, s1, s2, s3); + krb5_deltat val; + + if (strval == NULL) + return 0; + check(krb5_string_to_deltat(strval, &val)); + free(strval); + return val + time(NULL); +} + +/* Initialize kb_out with a key of type etype, using a hash of kvno, etype, + * salttype, and princstr for the key bytes. */ +static void +make_keyblock(krb5_kvno kvno, krb5_enctype etype, int32_t salttype, + const char *princstr, const krb5_data *realm, + krb5_keyblock *kb_out) +{ + size_t keybytes, keylength, pos, n; + char *hashstr; + krb5_data d, rndin; + krb5_checksum cksum; + + check(krb5_c_keylengths(NULL, etype, &keybytes, &keylength)); + alloc_data(&rndin, keybytes); + + /* Hash the kvno, enctype, salt type, and principal name together. */ + if (asprintf(&hashstr, "%d %d %d %s %.*s", (int)kvno, (int)etype, + (int)salttype, princstr, (int)realm->length, realm->data) < 0) + abort(); + d = string2data(hashstr); + check(krb5_c_make_checksum(NULL, CKSUMTYPE_SHA1, NULL, 0, &d, &cksum)); + + /* Make the appropriate number of input bytes from the hash result. */ + for (pos = 0; pos < keybytes; pos += n) { + n = (cksum.length < keybytes - pos) ? cksum.length : keybytes - pos; + memcpy(rndin.data + pos, cksum.contents, n); + } + + kb_out->enctype = etype; + kb_out->length = keylength; + kb_out->contents = ealloc(keylength); + check(krb5_c_random_to_key(NULL, etype, &rndin, kb_out)); + free(cksum.contents); + free(rndin.data); + free(hashstr); +} + +/* Return key data for the given key/salt tuple strings, using hashes of the + * enctypes, salts, and princstr for the key contents. */ +static void +make_keys(char **strings, const char *princstr, const krb5_data *realm, + krb5_db_entry *ent) +{ + krb5_key_data *key_data, *kd; + krb5_keyblock kb; + int32_t *ks_list_sizes, nstrings, nkeys, i, j; + krb5_key_salt_tuple **ks_lists, *ks; + krb5_kvno *kvnos; + char *s; + + for (nstrings = 0; strings[nstrings] != NULL; nstrings++); + ks_lists = ealloc(nstrings * sizeof(*ks_lists)); + ks_list_sizes = ealloc(nstrings * sizeof(*ks_list_sizes)); + kvnos = ealloc(nstrings * sizeof(*kvnos)); + + /* Convert each string into a key/salt tuple list and count the total + * number of key data structures needed. */ + nkeys = 0; + for (i = 0; i < nstrings; i++) { + s = strings[i]; + /* Read a leading kvno if present; otherwise assume kvno 1. */ + if (isdigit(*s)) { + kvnos[i] = strtol(s, &s, 10); + while (isspace(*s)) + s++; + } else { + kvnos[i] = 1; + } + check(krb5_string_to_keysalts(s, NULL, NULL, FALSE, &ks_lists[i], + &ks_list_sizes[i])); + nkeys += ks_list_sizes[i]; + } + + /* Turn each key/salt tuple into a key data entry. */ + kd = key_data = ealloc(nkeys * sizeof(*kd)); + for (i = 0; i < nstrings; i++) { + ks = ks_lists[i]; + for (j = 0; j < ks_list_sizes[i]; j++) { + make_keyblock(kvnos[i], ks[j].ks_enctype, ks[j].ks_salttype, + princstr, realm, &kb); + kd->key_data_ver = 2; + kd->key_data_kvno = kvnos[i]; + kd->key_data_type[0] = ks[j].ks_enctype; + kd->key_data_length[0] = kb.length; + kd->key_data_contents[0] = kb.contents; + kd->key_data_type[1] = ks[j].ks_salttype; + kd++; + } + } + + for (i = 0; i < nstrings; i++) + free(ks_lists[i]); + free(ks_lists); + free(ks_list_sizes); + free(kvnos); + ent->key_data = key_data; + ent->n_key_data = nkeys; +} + +static void +make_strings(char **stringattrs, krb5_db_entry *ent) +{ + struct k5buf buf; + char **p; + const char *str, *sep; + krb5_tl_data *tl; + + k5_buf_init_dynamic(&buf); + for (p = stringattrs; *p != NULL; p++) { + str = *p; + sep = strchr(str, ':'); + assert(sep != NULL); + k5_buf_add_len(&buf, str, sep - str); + k5_buf_add_len(&buf, "\0", 1); + k5_buf_add_len(&buf, sep + 1, strlen(sep + 1) + 1); + } + assert(buf.data != NULL); + + tl = ealloc(sizeof(*ent->tl_data)); + tl->tl_data_next = NULL; + tl->tl_data_type = KRB5_TL_STRING_ATTRS; + tl->tl_data_length = buf.len; + tl->tl_data_contents = buf.data; + ent->tl_data = tl; +} + +static krb5_error_code +test_init() +{ + return 0; +} + +static krb5_error_code +test_cleanup() +{ + return 0; +} + +static krb5_error_code +test_open(krb5_context context, char *conf_section, char **db_args, int mode) +{ + testhandle h; + + h = ealloc(sizeof(*h)); + h->profile = context->profile; + h->section = estrdup(conf_section); + context->dal_handle->db_context = h; + return 0; +} + +static krb5_error_code +test_close(krb5_context context) +{ + testhandle h = context->dal_handle->db_context; + + free(h->section); + free(h); + return 0; +} + +/* Return the principal name krbtgt/tgs_realm@our_realm. */ +static krb5_principal +tgtname(krb5_context context, const krb5_data *tgs_realm, + const krb5_data *our_realm) +{ + krb5_principal princ; + + check(krb5_build_principal_ext(context, &princ, + our_realm->length, our_realm->data, + KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, + tgs_realm->length, tgs_realm->data, 0)); + princ->type = KRB5_NT_SRV_INST; + return princ; +} + +/* Return true if search_for is within context's default realm or is an + * incoming cross-realm TGS name. */ +static krb5_boolean +request_for_us(krb5_context context, krb5_const_principal search_for) +{ + char *defrealm; + krb5_data realm; + krb5_boolean for_us; + krb5_principal local_tgs; + + check(krb5_get_default_realm(context, &defrealm)); + realm = string2data(defrealm); + local_tgs = tgtname(context, &realm, &realm); + krb5_free_default_realm(context, defrealm); + + for_us = krb5_realm_compare(context, local_tgs, search_for) || + krb5_principal_compare_any_realm(context, local_tgs, search_for); + krb5_free_principal(context, local_tgs); + return for_us; +} + +static krb5_error_code +test_get_principal(krb5_context context, krb5_const_principal search_for, + unsigned int flags, krb5_db_entry **entry) +{ + krb5_error_code ret; + krb5_principal princ = NULL, tgtprinc; + krb5_principal_data empty_princ = { KV5M_PRINCIPAL }; + testhandle h = context->dal_handle->db_context; + char *search_name = NULL, *canon = NULL, *flagstr; + char **names, **key_strings, **stringattrs; + const char *ename; + krb5_db_entry *ent; + + *entry = NULL; + + if (!request_for_us(context, search_for)) + return KRB5_KDB_NOENTRY; + + check(krb5_unparse_name_flags(context, search_for, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &search_name)); + canon = get_string(h, "alias", search_name, NULL); + if (canon != NULL) { + check(krb5_parse_name(context, canon, &princ)); + if (!krb5_realm_compare(context, search_for, princ)) { + /* Out of realm */ + if ((flags & KRB5_KDB_FLAG_CLIENT) && + (flags & KRB5_KDB_FLAG_REFERRAL_OK)) { + /* Return a client referral by creating an entry with only the + * principal set. */ + *entry = ealloc(sizeof(**entry)); + (*entry)->princ = princ; + princ = NULL; + ret = 0; + goto cleanup; + } else if (flags & KRB5_KDB_FLAG_REFERRAL_OK) { + /* Generate a server referral by looking up the TGT for the + * canonical name's realm. */ + tgtprinc = tgtname(context, &princ->realm, &search_for->realm); + krb5_free_principal(context, princ); + princ = tgtprinc; + + krb5_free_unparsed_name(context, search_name); + check(krb5_unparse_name_flags(context, princ, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &search_name)); + ename = search_name; + } else { + ret = KRB5_KDB_NOENTRY; + goto cleanup; + } + } else { + ename = canon; + } + } else { + check(krb5_copy_principal(context, search_for, &princ)); + ename = search_name; + } + + /* Check that the entry exists. */ + set_names(h, "princs", ename, NULL); + ret = profile_get_relation_names(h->profile, h->names, &names); + if (ret == PROF_NO_RELATION) { + ret = KRB5_KDB_NOENTRY; + goto cleanup; + } + profile_free_list(names); + + /* No error exits after this point. */ + + ent = ealloc(sizeof(*ent)); + ent->princ = princ; + princ = NULL; + + flagstr = get_string(h, "princs", ename, "flags"); + if (flagstr != NULL) { + check(krb5_flagspec_to_mask(flagstr, &ent->attributes, + &ent->attributes)); + } + free(flagstr); + + ent->max_life = get_duration(h, "princs", ename, "maxlife"); + ent->max_renewable_life = get_duration(h, "princs", ename, "maxrenewlife"); + ent->expiration = get_time(h, "princs", ename, "expiration"); + ent->pw_expiration = get_time(h, "princs", ename, "pwexpiration"); + + /* Leave last_success, last_failed, fail_auth_count zeroed. */ + /* Leave e_data empty. */ + + set_names(h, "princs", ename, "keys"); + ret = profile_get_values(h->profile, h->names, &key_strings); + if (ret != PROF_NO_RELATION) { + make_keys(key_strings, ename, &search_for->realm, ent); + profile_free_list(key_strings); + } + + set_names(h, "princs", ename, "strings"); + ret = profile_get_values(h->profile, h->names, &stringattrs); + if (ret != PROF_NO_RELATION) { + make_strings(stringattrs, ent); + profile_free_list(stringattrs); + } + + /* We must include mod-princ data or kadm5_get_principal() won't work and + * we can't extract keys with kadmin.local. */ + check(krb5_dbe_update_mod_princ_data(context, ent, 0, &empty_princ)); + + *entry = ent; + ret = 0; + +cleanup: + krb5_free_unparsed_name(context, search_name); + krb5_free_principal(context, princ); + free(canon); + return ret; +} + +static void +lookup_princ_by_cert(krb5_context context, const krb5_data *client_cert, + krb5_principal *princ) +{ + krb5_error_code ret; + char *cert_princ_name; + + /* The test client sends a principal string instead of a cert. */ + cert_princ_name = k5memdup0(client_cert->data, client_cert->length, &ret); + check(ret); + + check(krb5_parse_name_flags(context, cert_princ_name, + KRB5_PRINCIPAL_PARSE_ENTERPRISE, princ)); + free(cert_princ_name); +} + +static krb5_error_code +test_get_s4u_x509_principal(krb5_context context, const krb5_data *client_cert, + krb5_const_principal princ, unsigned int flags, + krb5_db_entry **entry) +{ + krb5_error_code ret; + krb5_principal cert_princ, canon_princ; + testhandle h = context->dal_handle->db_context; + krb5_boolean match; + char *canon, *princ_name; + + lookup_princ_by_cert(context, client_cert, &cert_princ); + + ret = test_get_principal(context, cert_princ, flags, entry); + krb5_free_principal(context, cert_princ); + if (ret || (flags & KRB5_KDB_FLAG_REFERRAL_OK)) + return ret; + + if (!krb5_realm_compare(context, princ, (*entry)->princ)) + abort(); + + if (princ->length == 0 || + krb5_principal_compare(context, princ, (*entry)->princ)) + return 0; + + match = FALSE; + check(krb5_unparse_name_flags(context, princ, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &princ_name)); + canon = get_string(h, "alias", princ_name, NULL); + krb5_free_unparsed_name(context, princ_name); + if (canon != NULL) { + check(krb5_parse_name(context, canon, &canon_princ)); + match = krb5_principal_compare(context, canon_princ, (*entry)->princ); + krb5_free_principal(context, canon_princ); + } + + free(canon); + return match ? 0 : KRB5KDC_ERR_CLIENT_NAME_MISMATCH; +} + +static krb5_error_code +test_fetch_master_key(krb5_context context, krb5_principal mname, + krb5_keyblock *key_out, krb5_kvno *kvno_out, + char *db_args) +{ + memset(key_out, 0, sizeof(*key_out)); + *kvno_out = 0; + return 0; +} + +static krb5_error_code +test_fetch_master_key_list(krb5_context context, krb5_principal mname, + const krb5_keyblock *key, + krb5_keylist_node **mkeys_out) +{ + /* krb5_dbe_get_mkvno() returns an error if we produce NULL, so return an + * empty node to make kadm5_get_principal() work. */ + *mkeys_out = ealloc(sizeof(**mkeys_out)); + return 0; +} + +static krb5_error_code +test_decrypt_key_data(krb5_context context, const krb5_keyblock *mkey, + const krb5_key_data *kd, krb5_keyblock *key_out, + krb5_keysalt *salt_out) +{ + key_out->magic = KV5M_KEYBLOCK; + key_out->enctype = kd->key_data_type[0]; + key_out->length = kd->key_data_length[0]; + key_out->contents = ealloc(key_out->length); + memcpy(key_out->contents, kd->key_data_contents[0], key_out->length); + if (salt_out != NULL) { + salt_out->type = (kd->key_data_ver > 1) ? kd->key_data_type[1] : + KRB5_KDB_SALTTYPE_NORMAL; + salt_out->data = empty_data(); + } + return 0; +} + +static krb5_error_code +test_encrypt_key_data(krb5_context context, const krb5_keyblock *mkey, + const krb5_keyblock *key, const krb5_keysalt *salt, + int kvno, krb5_key_data *kd_out) +{ + memset(kd_out, 0, sizeof(*kd_out)); + kd_out->key_data_ver = 2; + kd_out->key_data_kvno = kvno; + kd_out->key_data_type[0] = key->enctype; + kd_out->key_data_length[0] = key->length; + kd_out->key_data_contents[0] = ealloc(key->length); + memcpy(kd_out->key_data_contents[0], key->contents, key->length); + kd_out->key_data_type[1] = (salt != NULL) ? salt->type : + KRB5_KDB_SALTTYPE_NORMAL; + return 0; +} + +static void +change_auth_indicators(krb5_context context, krb5_data ***auth_indicators) +{ + krb5_data **inds, d; + int i, val; + + /* If we see an auth indicator "dbincrX", replace the whole indicator list + * with "dbincr{X+1}". */ + inds = *auth_indicators; + for (i = 0; inds != NULL && inds[i] != NULL; i++) { + if (inds[i]->length == 7 && memcmp(inds[i]->data, "dbincr", 6) == 0) { + val = inds[i]->data[6]; + k5_free_data_ptr_list(inds); + inds = ealloc(2 * sizeof(*inds)); + d = string2data("dbincr0"); + check(krb5_copy_data(context, &d, &inds[0])); + inds[0]->data[6] = val + 1; + inds[1] = NULL; + *auth_indicators = inds; + break; + } + } +} + +static krb5_error_code +test_issue_pac(krb5_context context, unsigned int flags, krb5_db_entry *client, + krb5_keyblock *replaced_reply_key, krb5_db_entry *server, + krb5_db_entry *krb5tgt, krb5_timestamp authtime, + krb5_pac old_pac, krb5_pac new_pac, + krb5_data ***auth_indicators) +{ + krb5_data data = empty_data(); + krb5_boolean found_logon_info = FALSE; + krb5_ui_4 *types = NULL; + size_t num_buffers = 0, i; + + change_auth_indicators(context, auth_indicators); + + if (old_pac == NULL || + (client != NULL && (flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION))) { + /* Generating an initial PAC. */ + assert(client != NULL); + data = string2data("fake"); + check(krb5_pac_add_buffer(context, new_pac, KRB5_PAC_LOGON_INFO, + &data)); + + if (replaced_reply_key != NULL) { + /* Add a fake PAC_CREDENTIALS_INFO buffer so we can test whether + * this parameter was set. */ + data = string2data("fake credinfo"); + check(krb5_pac_add_buffer(context, new_pac, + KRB5_PAC_CREDENTIALS_INFO, &data)); + } + return 0; + } else { + /* Field copying - my favorite! */ + if (old_pac != NULL) + check(krb5_pac_get_types(context, old_pac, &num_buffers, &types)); + + for (i = 0; i < num_buffers; i++) { + /* Skip buffer types handled by KDC. */ + if (types[i] == KRB5_PAC_SERVER_CHECKSUM || + types[i] == KRB5_PAC_PRIVSVR_CHECKSUM || + types[i] == KRB5_PAC_TICKET_CHECKSUM || + types[i] == KRB5_PAC_CLIENT_INFO || + types[i] == KRB5_PAC_DELEGATION_INFO) + continue; + + check(krb5_pac_get_buffer(context, old_pac, types[i], &data)); + + if (types[i] == KRB5_PAC_LOGON_INFO) { + found_logon_info = TRUE; + assert(data_eq_string(data, "fake")); + } + + check(krb5_pac_add_buffer(context, new_pac, types[i], &data)); + krb5_free_data_contents(context, &data); + } + + if (old_pac != NULL) + assert(found_logon_info); + + free(types); + } + + return 0; +} + +static krb5_boolean +match_in_table(krb5_context context, const char *table, const char *sprinc, + const char *tprinc) +{ + testhandle h = context->dal_handle->db_context; + krb5_error_code ret; + char **values, **v; + krb5_boolean found = FALSE; + + set_names(h, table, sprinc, NULL); + ret = profile_get_values(h->profile, h->names, &values); + assert(ret == 0 || ret == PROF_NO_RELATION); + if (ret) + return FALSE; + for (v = values; *v != NULL; v++) { + if (tprinc == NULL || strcmp(*v, tprinc) == 0) { + found = TRUE; + break; + } + } + profile_free_list(values); + return found; +} + +static krb5_error_code +test_check_allowed_to_delegate(krb5_context context, + krb5_const_principal client, + const krb5_db_entry *server, + krb5_const_principal proxy) +{ + char *sprinc, *tprinc = NULL; + krb5_boolean found = FALSE; + + check(krb5_unparse_name_flags(context, server->princ, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, &sprinc)); + if (proxy != NULL) { + check(krb5_unparse_name_flags(context, proxy, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &tprinc)); + } + found = match_in_table(context, "delegation", sprinc, tprinc); + krb5_free_unparsed_name(context, sprinc); + krb5_free_unparsed_name(context, tprinc); + return found ? 0 : KRB5KDC_ERR_BADOPTION; +} + +static krb5_error_code +test_allowed_to_delegate_from(krb5_context context, + krb5_const_principal client, + krb5_const_principal server, + krb5_pac server_pac, + const krb5_db_entry *proxy) +{ + char *proxy_princ, *server_princ, *pac_client_princ, *client_princ; + krb5_boolean found = FALSE; + + assert(server_pac != NULL); + + check(krb5_unparse_name(context, proxy->princ, &proxy_princ)); + check(krb5_unparse_name(context, server, &server_princ)); + check(krb5_unparse_name(context, client, &client_princ)); + + check(krb5_pac_get_client_info(context, server_pac, NULL, + &pac_client_princ)); + + /* Skip realm portion if not present in PAC. */ + assert(strncmp(pac_client_princ, server_princ, + strlen(pac_client_princ)) == 0); + + free(pac_client_princ); + + found = match_in_table(context, "rbcd", proxy_princ, server_princ); + krb5_free_unparsed_name(context, proxy_princ); + krb5_free_unparsed_name(context, server_princ); + krb5_free_unparsed_name(context, client_princ); + return found ? 0 : KRB5KDC_ERR_BADOPTION; +} + +kdb_vftabl PLUGIN_SYMBOL_NAME(krb5_test, kdb_function_table) = { + KRB5_KDB_DAL_MAJOR_VERSION, /* major version number */ + 0, /* minor version number */ + test_init, + test_cleanup, + test_open, + test_close, + NULL, /* create */ + NULL, /* destroy */ + NULL, /* get_age */ + NULL, /* lock */ + NULL, /* unlock */ + test_get_principal, + NULL, /* put_principal */ + NULL, /* delete_principal */ + NULL, /* rename_principal */ + NULL, /* iterate */ + NULL, /* create_policy */ + NULL, /* get_policy */ + NULL, /* put_policy */ + NULL, /* iter_policy */ + NULL, /* delete_policy */ + test_fetch_master_key, + test_fetch_master_key_list, + NULL, /* store_master_key_list */ + NULL, /* dbe_search_enctype */ + NULL, /* change_pwd */ + NULL, /* promote_db */ + test_decrypt_key_data, + test_encrypt_key_data, + NULL, /* check_transited_realms */ + NULL, /* check_policy_as */ + NULL, /* check_policy_tgs */ + NULL, /* audit_as_req */ + NULL, /* refresh_config */ + test_check_allowed_to_delegate, + NULL, /* free_principal_e_data */ + test_get_s4u_x509_principal, + test_allowed_to_delegate_from, + test_issue_pac, +}; diff --git a/krb5-1.21.3/src/plugins/kdb/test/test.exports b/krb5-1.21.3/src/plugins/kdb/test/test.exports new file mode 100644 index 00000000..f2b7c111 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdb/test/test.exports @@ -0,0 +1 @@ +kdb_function_table diff --git a/krb5-1.21.3/src/plugins/kdcpolicy/test/Makefile.in b/krb5-1.21.3/src/plugins/kdcpolicy/test/Makefile.in new file mode 100644 index 00000000..ea3484e1 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdcpolicy/test/Makefile.in @@ -0,0 +1,20 @@ +mydir=plugins$(S)kdcpolicy$(S)test +BUILDTOP=$(REL)..$(S)..$(S).. + +LIBBASE=kdcpolicy_test +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/kdcpolicy/test +SHLIB_EXPDEPS=$(KRB5_BASE_DEPLIBS) +SHLIB_EXPLIBS=$(KRB5_BASE_LIBS) + +STLIBOBJS=main.o + +SRCS=$(srcdir)/main.c + +all-unix: all-libs +install-unix: +clean-unix:: clean-libs clean-libobjs + +@libnover_frag@ +@libobj_frag@ diff --git a/krb5-1.21.3/src/plugins/kdcpolicy/test/deps b/krb5-1.21.3/src/plugins/kdcpolicy/test/deps new file mode 100644 index 00000000..4ecf533f --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdcpolicy/test/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +main.so main.po $(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kdcpolicy_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h main.c diff --git a/krb5-1.21.3/src/plugins/kdcpolicy/test/kdcpolicy_test.exports b/krb5-1.21.3/src/plugins/kdcpolicy/test/kdcpolicy_test.exports new file mode 100644 index 00000000..9682ec74 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdcpolicy/test/kdcpolicy_test.exports @@ -0,0 +1 @@ +kdcpolicy_test_initvt diff --git a/krb5-1.21.3/src/plugins/kdcpolicy/test/main.c b/krb5-1.21.3/src/plugins/kdcpolicy/test/main.c new file mode 100644 index 00000000..86c80895 --- /dev/null +++ b/krb5-1.21.3/src/plugins/kdcpolicy/test/main.c @@ -0,0 +1,111 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* include/krb5/kdcpolicy_plugin.h - KDC policy plugin interface */ +/* + * Copyright (C) 2017 by Red Hat, Inc. + * 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. + */ + +#include "k5-int.h" +#include "kdb.h" +#include + +static krb5_error_code +output_from_indicator(const char *const *auth_indicators, int divisor, + krb5_deltat *lifetime_out, + krb5_deltat *renew_lifetime_out, + const char **status) +{ + if (auth_indicators[0] == NULL) { + *status = NULL; + return 0; + } + + if (strcmp(auth_indicators[0], "ONE_HOUR") == 0) { + *lifetime_out = 3600 / divisor; + *renew_lifetime_out = *lifetime_out * 2; + return 0; + } else if (strcmp(auth_indicators[0], "SEVEN_HOURS") == 0) { + *lifetime_out = 7 * 3600 / divisor; + *renew_lifetime_out = *lifetime_out * 2; + return 0; + } + + *status = "LOCAL_POLICY"; + return KRB5KDC_ERR_POLICY; +} + +static krb5_error_code +test_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata, + const krb5_kdc_req *request, const krb5_db_entry *client, + const krb5_db_entry *server, const char *const *auth_indicators, + const char **status, krb5_deltat *lifetime_out, + krb5_deltat *renew_lifetime_out) +{ + if (request->client != NULL && request->client->length >= 1 && + data_eq_string(request->client->data[0], "fail")) { + *status = "LOCAL_POLICY"; + return KRB5KDC_ERR_POLICY; + } + return output_from_indicator(auth_indicators, 1, lifetime_out, + renew_lifetime_out, status); +} + +static krb5_error_code +test_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata, + const krb5_kdc_req *request, const krb5_db_entry *server, + const krb5_ticket *ticket, const char *const *auth_indicators, + const char **status, krb5_deltat *lifetime_out, + krb5_deltat *renew_lifetime_out) +{ + if (request->server != NULL && request->server->length >= 1 && + data_eq_string(request->server->data[0], "fail")) { + *status = "LOCAL_POLICY"; + return KRB5KDC_ERR_POLICY; + } + return output_from_indicator(auth_indicators, 2, lifetime_out, + renew_lifetime_out, status); +} + +krb5_error_code +kdcpolicy_test_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); +krb5_error_code +kdcpolicy_test_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_kdcpolicy_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + + vt = (krb5_kdcpolicy_vtable)vtable; + vt->name = "test"; + vt->check_as = test_check_as; + vt->check_tgs = test_check_tgs; + return 0; +} diff --git a/krb5-1.21.3/src/plugins/localauth/test/Makefile.in b/krb5-1.21.3/src/plugins/localauth/test/Makefile.in new file mode 100644 index 00000000..2a12d141 --- /dev/null +++ b/krb5-1.21.3/src/plugins/localauth/test/Makefile.in @@ -0,0 +1,20 @@ +mydir=plugins$(S)localauth$(S)test +BUILDTOP=$(REL)..$(S)..$(S).. + +LIBBASE=localauth_test +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/localauth/test +SHLIB_EXPDEPS=$(SUPPORT_DEPLIB) +SHLIB_EXPLIBS=$(SUPPORT_LIB) $(LIBS) + +STLIBOBJS=main.o + +SRCS=$(srcdir)/main.c + +all-unix: all-libs +install-unix: +clean-unix:: clean-libs clean-libobjs + +@libnover_frag@ +@libobj_frag@ diff --git a/krb5-1.21.3/src/plugins/localauth/test/deps b/krb5-1.21.3/src/plugins/localauth/test/deps new file mode 100644 index 00000000..0d3b2d82 --- /dev/null +++ b/krb5-1.21.3/src/plugins/localauth/test/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +main.so main.po $(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/localauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + main.c diff --git a/krb5-1.21.3/src/plugins/localauth/test/localauth_test.exports b/krb5-1.21.3/src/plugins/localauth/test/localauth_test.exports new file mode 100644 index 00000000..63c1396c --- /dev/null +++ b/krb5-1.21.3/src/plugins/localauth/test/localauth_test.exports @@ -0,0 +1,2 @@ +localauth_test1_initvt +localauth_test2_initvt diff --git a/krb5-1.21.3/src/plugins/localauth/test/main.c b/krb5-1.21.3/src/plugins/localauth/test/main.c new file mode 100644 index 00000000..9e96900b --- /dev/null +++ b/krb5-1.21.3/src/plugins/localauth/test/main.c @@ -0,0 +1,169 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/localauth/test/main.c - test modules for localauth interface */ +/* + * 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. + */ + +/* This file implements two testing localauth modules, each implementing + * clearly recognizable behavior for the localauth test script. */ + +#include "k5-int.h" +#include + +struct krb5_localauth_moddata_st { + int a; + int b; +}; + +static krb5_error_code +init_test(krb5_context context, krb5_localauth_moddata *data_out) +{ + krb5_localauth_moddata d; + + *data_out = NULL; + d = malloc(sizeof(*d)); + if (d == NULL) + return ENOMEM; + d->a = 3; + d->b = 4; + *data_out = d; + return 0; +} + +static void +fini_test(krb5_context context, krb5_localauth_moddata data) +{ + assert(data->a == 3); + assert(data->b == 4); + free(data); +} + +static krb5_error_code +an2ln_test(krb5_context context, krb5_localauth_moddata data, const char *type, + const char *residual, krb5_const_principal aname, char **lname_out) +{ + krb5_error_code ret; + char *lname = NULL; + + *lname_out = NULL; + if (data != NULL) { + assert(data->a == 3); + assert(data->b == 4); + } + if (type == NULL) { + /* Map any three-component test/___/___ principal to its realm name. */ + if (aname->length == 3 && data_eq_string(aname->data[0], "test")) { + lname = k5memdup0(aname->realm.data, aname->realm.length, &ret); + if (lname == NULL) + return ret; + } + } else if (strcmp(type, "TYPEA") == 0) { + /* Map any two-component principal to its second component. */ + if (aname->length == 2) { + lname = k5memdup0(aname->data[1].data, aname->data[1].length, + &ret); + if (lname == NULL) + return ret; + } + } else { + assert(strcmp(type, "TYPEB") == 0); + /* Map to the residual string. */ + lname = strdup(residual == NULL ? "(null)" : residual); + if (lname == NULL) + return ENOMEM; + } + if (lname == NULL) + return KRB5_LNAME_NOTRANS; + *lname_out = lname; + return 0; +} + +static krb5_error_code +userok_test(krb5_context context, krb5_localauth_moddata data, + krb5_const_principal aname, const char *lname) +{ + if (data != NULL) { + assert(data->a == 3); + assert(data->b == 4); + } + + /* Return success if the number of components in the principal is equal to + * the length of the local name. */ + if ((size_t)aname->length == strlen(lname)) + return 0; + + /* Pass control down if the first component is "pass". */ + if (aname->length >= 1 && data_eq_string(aname->data[0], "pass")) + return KRB5_PLUGIN_NO_HANDLE; + + /* Otherwise reject. */ + return EPERM; +} + +static void +freestr(krb5_context context, krb5_localauth_moddata data, char *str) +{ + free(str); +} + +krb5_error_code +localauth_test1_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); +krb5_error_code +localauth_test2_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +localauth_test1_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_localauth_vtable vt = (krb5_localauth_vtable)vtable; + + vt->init = init_test; + vt->fini = fini_test; + vt->name = "test1"; + vt->an2ln = an2ln_test; + vt->userok = userok_test; + vt->free_string = freestr; + return 0; +} + +krb5_error_code +localauth_test2_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_localauth_vtable vt = (krb5_localauth_vtable)vtable; + static const char *types[] = { "TYPEA", "TYPEB", NULL }; + + vt->name = "test2"; + vt->an2ln_types = types; + vt->an2ln = an2ln_test; + vt->free_string = freestr; + return 0; +} diff --git a/krb5-1.21.3/src/plugins/preauth/otp/Makefile.in b/krb5-1.21.3/src/plugins/preauth/otp/Makefile.in new file mode 100644 index 00000000..a5e137d9 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/otp/Makefile.in @@ -0,0 +1,31 @@ +mydir=plugins$(S)preauth$(S)otp +BUILDTOP=$(REL)..$(S)..$(S).. +MODULE_INSTALL_DIR = $(KRB5_PA_MODULE_DIR) + +LIBBASE=otp +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/preauth/otp + +SHLIB_EXPDEPS = $(VERTO_DEPLIBS) $(KRB5_BASE_DEPLIBS) \ + $(TOPLIBD)/libkrad$(SHLIBEXT) + +SHLIB_EXPLIBS= -lkrad $(VERTO_LIBS) $(KRB5_BASE_LIBS) + +STLIBOBJS = \ + otp_state.o \ + main.o + +SRCS = \ + $(srcdir)/otp_state.c \ + $(srcdir)/main.c + +all-unix: all-liblinks +install-unix: install-libs +clean-unix:: clean-liblinks clean-libs clean-libobjs + +clean: + $(RM) lib$(LIBBASE)$(SO_EXT) + +@libnover_frag@ +@libobj_frag@ diff --git a/krb5-1.21.3/src/plugins/preauth/otp/deps b/krb5-1.21.3/src/plugins/preauth/otp/deps new file mode 100644 index 00000000..d8e023bf --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/otp/deps @@ -0,0 +1,28 @@ +# +# Generated makefile dependencies follow. +# +otp_state.so otp_state.po $(OUTPRE)otp_state.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(VERTO_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-json.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krad.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h otp_state.c otp_state.h +main.so main.po $(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(VERTO_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-json.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/clpreauth_plugin.h $(top_srcdir)/include/krb5/kdcpreauth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + main.c otp_state.h diff --git a/krb5-1.21.3/src/plugins/preauth/otp/main.c b/krb5-1.21.3/src/plugins/preauth/otp/main.c new file mode 100644 index 00000000..0e682aae --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/otp/main.c @@ -0,0 +1,390 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/otp/main.c - OTP kdcpreauth module definition */ +/* + * Copyright 2011 NORDUnet A/S. All rights reserved. + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include "k5-int.h" +#include "k5-json.h" +#include +#include "otp_state.h" + +#include +#include + +static krb5_preauthtype otp_pa_type_list[] = + { KRB5_PADATA_OTP_REQUEST, 0 }; + +struct request_state { + krb5_context context; + krb5_kdcpreauth_verify_respond_fn respond; + void *arg; + krb5_enc_tkt_part *enc_tkt_reply; + krb5_kdcpreauth_callbacks preauth_cb; + krb5_kdcpreauth_rock rock; +}; + +static krb5_error_code +decrypt_encdata(krb5_context context, krb5_keyblock *armor_key, + krb5_pa_otp_req *req, krb5_data *out) +{ + krb5_error_code retval; + krb5_data plaintext; + + if (req == NULL) + return EINVAL; + + retval = alloc_data(&plaintext, req->enc_data.ciphertext.length); + if (retval) + return retval; + + retval = krb5_c_decrypt(context, armor_key, KRB5_KEYUSAGE_PA_OTP_REQUEST, + NULL, &req->enc_data, &plaintext); + if (retval != 0) { + com_err("otp", retval, "Unable to decrypt encData in PA-OTP-REQUEST"); + free(plaintext.data); + return retval; + } + + *out = plaintext; + return 0; +} + +static krb5_error_code +nonce_verify(krb5_context ctx, krb5_keyblock *armor_key, + const krb5_data *nonce) +{ + krb5_error_code retval; + krb5_timestamp ts; + krb5_data *er = NULL; + + if (armor_key == NULL || nonce->data == NULL) { + retval = EINVAL; + goto out; + } + + /* Decode the PA-OTP-ENC-REQUEST structure. */ + retval = decode_krb5_pa_otp_enc_req(nonce, &er); + if (retval != 0) + goto out; + + /* Make sure the nonce is exactly the same size as the one generated. */ + if (er->length != armor_key->length + sizeof(krb5_timestamp)) + goto out; + + /* Check to make sure the timestamp at the beginning is still valid. */ + ts = load_32_be(er->data); + retval = krb5_check_clockskew(ctx, ts); + +out: + krb5_free_data(ctx, er); + return retval; +} + +static krb5_error_code +timestamp_verify(krb5_context ctx, const krb5_data *nonce) +{ + krb5_error_code retval = EINVAL; + krb5_pa_enc_ts *et = NULL; + + if (nonce->data == NULL) + goto out; + + /* Decode the PA-ENC-TS-ENC structure. */ + retval = decode_krb5_pa_enc_ts(nonce, &et); + if (retval != 0) + goto out; + + /* Check the clockskew. */ + retval = krb5_check_clockskew(ctx, et->patimestamp); + +out: + krb5_free_pa_enc_ts(ctx, et); + return retval; +} + +static krb5_error_code +nonce_generate(krb5_context ctx, unsigned int length, krb5_data *nonce_out) +{ + krb5_data nonce; + krb5_error_code retval; + krb5_timestamp now; + + retval = krb5_timeofday(ctx, &now); + if (retval != 0) + return retval; + + retval = alloc_data(&nonce, sizeof(now) + length); + if (retval != 0) + return retval; + + retval = krb5_c_random_make_octets(ctx, &nonce); + if (retval != 0) { + free(nonce.data); + return retval; + } + + store_32_be(now, nonce.data); + *nonce_out = nonce; + return 0; +} + +static void +on_response(void *data, krb5_error_code retval, otp_response response, + char *const *indicators) +{ + struct request_state rs = *(struct request_state *)data; + krb5_context context = rs.context; + krb5_keyblock *armor_key; + char *const *ind; + + free(data); + + if (retval == 0 && response != otp_response_success) + retval = KRB5_PREAUTH_FAILED; + if (retval) + goto done; + + rs.enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; + armor_key = rs.preauth_cb->fast_armor(context, rs.rock); + if (armor_key == NULL) { + retval = ENOENT; + goto done; + } + + retval = rs.preauth_cb->replace_reply_key(context, rs.rock, armor_key, + FALSE); + if (retval) + goto done; + + for (ind = indicators; ind != NULL && *ind != NULL; ind++) { + retval = rs.preauth_cb->add_auth_indicator(context, rs.rock, *ind); + if (retval) + goto done; + } + +done: + rs.respond(rs.arg, retval, NULL, NULL, NULL); +} + +static krb5_error_code +otp_init(krb5_context context, krb5_kdcpreauth_moddata *moddata_out, + const char **realmnames) +{ + krb5_error_code retval; + otp_state *state; + + retval = otp_state_new(context, &state); + if (retval) + return retval; + *moddata_out = (krb5_kdcpreauth_moddata)state; + return 0; +} + +static void +otp_fini(krb5_context context, krb5_kdcpreauth_moddata moddata) +{ + otp_state_free((otp_state *)moddata); +} + +static int +otp_flags(krb5_context context, krb5_preauthtype pa_type) +{ + return PA_REPLACES_KEY; +} + +static void +otp_edata(krb5_context context, krb5_kdc_req *request, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type, + krb5_kdcpreauth_edata_respond_fn respond, void *arg) +{ + krb5_otp_tokeninfo ti, *tis[2] = { &ti, NULL }; + krb5_keyblock *armor_key = NULL; + krb5_pa_otp_challenge chl; + krb5_pa_data *pa = NULL; + krb5_error_code retval; + krb5_data *encoding, nonce = empty_data(); + char *config; + + /* Determine if otp is enabled for the user. */ + retval = cb->get_string(context, rock, "otp", &config); + if (retval == 0 && config == NULL) + retval = ENOENT; + if (retval != 0) + goto out; + cb->free_string(context, rock, config); + + /* Get the armor key. This indicates the length of random data to use in + * the nonce. */ + armor_key = cb->fast_armor(context, rock); + if (armor_key == NULL) { + retval = ENOENT; + goto out; + } + + /* Build the (mostly empty) challenge. */ + memset(&ti, 0, sizeof(ti)); + memset(&chl, 0, sizeof(chl)); + chl.tokeninfo = tis; + ti.format = -1; + ti.length = -1; + ti.iteration_count = -1; + + /* Generate the nonce. */ + retval = nonce_generate(context, armor_key->length, &nonce); + if (retval != 0) + goto out; + chl.nonce = nonce; + + /* Build the output pa-data. */ + retval = encode_krb5_pa_otp_challenge(&chl, &encoding); + if (retval != 0) + goto out; + pa = k5alloc(sizeof(krb5_pa_data), &retval); + if (pa == NULL) { + krb5_free_data(context, encoding); + goto out; + } + pa->pa_type = KRB5_PADATA_OTP_CHALLENGE; + pa->contents = (krb5_octet *)encoding->data; + pa->length = encoding->length; + free(encoding); + +out: + krb5_free_data_contents(context, &nonce); + (*respond)(arg, retval, pa); +} + +static void +otp_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, + krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *pa, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_verify_respond_fn respond, void *arg) +{ + krb5_keyblock *armor_key = NULL; + krb5_pa_otp_req *req = NULL; + struct request_state *rs; + krb5_error_code retval; + krb5_data d, plaintext; + char *config; + + /* Get the FAST armor key. */ + armor_key = cb->fast_armor(context, rock); + if (armor_key == NULL) { + retval = KRB5KDC_ERR_PREAUTH_FAILED; + com_err("otp", retval, "No armor key found when verifying padata"); + goto error; + } + + /* Decode the request. */ + d = make_data(pa->contents, pa->length); + retval = decode_krb5_pa_otp_req(&d, &req); + if (retval != 0) { + com_err("otp", retval, "Unable to decode OTP request"); + goto error; + } + + /* Decrypt the nonce from the request. */ + retval = decrypt_encdata(context, armor_key, req, &plaintext); + if (retval != 0) { + com_err("otp", retval, "Unable to decrypt nonce"); + goto error; + } + + /* Verify the nonce or timestamp. */ + retval = nonce_verify(context, armor_key, &plaintext); + if (retval != 0) + retval = timestamp_verify(context, &plaintext); + krb5_free_data_contents(context, &plaintext); + if (retval != 0) { + com_err("otp", retval, "Unable to verify nonce or timestamp"); + goto error; + } + + /* Create the request state. Save the response callback, and the + * enc_tkt_reply pointer so we can set the TKT_FLG_PRE_AUTH flag later. */ + rs = k5alloc(sizeof(struct request_state), &retval); + if (rs == NULL) + goto error; + rs->context = context; + rs->arg = arg; + rs->respond = respond; + rs->enc_tkt_reply = enc_tkt_reply; + rs->preauth_cb = cb; + rs->rock = rock; + + /* Get the principal's OTP configuration string. */ + retval = cb->get_string(context, rock, "otp", &config); + if (retval == 0 && config == NULL) + retval = KRB5_PREAUTH_FAILED; + if (retval != 0) { + free(rs); + goto error; + } + + /* Send the request. */ + otp_state_verify((otp_state *)moddata, cb->event_context(context, rock), + cb->client_name(context, rock), config, req, on_response, + rs); + cb->free_string(context, rock, config); + + k5_free_pa_otp_req(context, req); + return; + +error: + k5_free_pa_otp_req(context, req); + (*respond)(arg, retval, NULL, NULL, NULL); +} + +krb5_error_code +kdcpreauth_otp_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +kdcpreauth_otp_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_kdcpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "otp"; + vt->pa_type_list = otp_pa_type_list; + vt->init = otp_init; + vt->fini = otp_fini; + vt->flags = otp_flags; + vt->edata = otp_edata; + vt->verify = otp_verify; + + com_err("otp", 0, "Loaded"); + + return 0; +} diff --git a/krb5-1.21.3/src/plugins/preauth/otp/otp.exports b/krb5-1.21.3/src/plugins/preauth/otp/otp.exports new file mode 100644 index 00000000..26aa19d4 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/otp/otp.exports @@ -0,0 +1 @@ +kdcpreauth_otp_initvt diff --git a/krb5-1.21.3/src/plugins/preauth/otp/otp_state.c b/krb5-1.21.3/src/plugins/preauth/otp/otp_state.c new file mode 100644 index 00000000..20cd18ab --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/otp/otp_state.c @@ -0,0 +1,740 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/otp/otp_state.c - Verify OTP token values using RADIUS */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#include "otp_state.h" + +#include +#include + +#include + +#ifndef HOST_NAME_MAX +/* SUSv2 */ +#define HOST_NAME_MAX 255 +#endif + +#define DEFAULT_TYPE_NAME "DEFAULT" +#define DEFAULT_SOCKET_FMT KDC_RUN_DIR "/%s.socket" +#define DEFAULT_TIMEOUT 5 +#define DEFAULT_RETRIES 3 +#define MAX_SECRET_LEN 1024 + +typedef struct token_type_st { + char *name; + char *server; + char *secret; + int timeout; + size_t retries; + krb5_boolean strip_realm; + char **indicators; +} token_type; + +typedef struct token_st { + const token_type *type; + krb5_data username; + char **indicators; +} token; + +typedef struct request_st { + otp_state *state; + token *tokens; + ssize_t index; + otp_cb cb; + void *data; + krad_attrset *attrs; +} request; + +struct otp_state_st { + krb5_context ctx; + token_type *types; + krad_client *radius; + krad_attrset *attrs; +}; + +static void request_send(request *req); + +static krb5_error_code +read_secret_file(const char *secret_file, char **secret) +{ + char buf[MAX_SECRET_LEN]; + krb5_error_code retval; + char *filename = NULL; + FILE *file; + size_t i, j; + + *secret = NULL; + + retval = k5_path_join(KDC_DIR, secret_file, &filename); + if (retval != 0) { + com_err("otp", retval, "Unable to resolve secret file '%s'", filename); + goto cleanup; + } + + file = fopen(filename, "r"); + if (file == NULL) { + retval = errno; + com_err("otp", retval, "Unable to open secret file '%s'", filename); + goto cleanup; + } + + if (fgets(buf, sizeof(buf), file) == NULL) + retval = EIO; + fclose(file); + if (retval != 0) { + com_err("otp", retval, "Unable to read secret file '%s'", filename); + goto cleanup; + } + + /* Strip whitespace. */ + for (i = 0; buf[i] != '\0'; i++) { + if (!isspace(buf[i])) + break; + } + for (j = strlen(buf); j > i; j--) { + if (!isspace(buf[j - 1])) + break; + } + + *secret = k5memdup0(&buf[i], j - i, &retval); + +cleanup: + free(filename); + return retval; +} + +/* Free the contents of a single token type. */ +static void +token_type_free(token_type *type) +{ + if (type == NULL) + return; + + free(type->name); + free(type->server); + free(type->secret); + profile_free_list(type->indicators); +} + +/* Construct the internal default token type. */ +static krb5_error_code +token_type_default(token_type *out) +{ + char *name = NULL, *server = NULL, *secret = NULL; + + memset(out, 0, sizeof(*out)); + + name = strdup(DEFAULT_TYPE_NAME); + if (name == NULL) + goto oom; + if (asprintf(&server, DEFAULT_SOCKET_FMT, name) < 0) + goto oom; + secret = strdup(""); + if (secret == NULL) + goto oom; + + out->name = name; + out->server = server; + out->secret = secret; + out->timeout = DEFAULT_TIMEOUT * 1000; + out->retries = DEFAULT_RETRIES; + out->strip_realm = FALSE; + return 0; + +oom: + free(name); + free(server); + free(secret); + return ENOMEM; +} + +/* Decode a single token type from the profile. */ +static krb5_error_code +token_type_decode(profile_t profile, const char *name, token_type *out) +{ + char *server = NULL, *name_copy = NULL, *secret = NULL, *pstr = NULL; + char **indicators = NULL; + const char *keys[4]; + int strip_realm, timeout, retries; + krb5_error_code retval; + + memset(out, 0, sizeof(*out)); + + /* Set the name. */ + name_copy = strdup(name); + if (name_copy == NULL) + return ENOMEM; + + /* Set strip_realm. */ + retval = profile_get_boolean(profile, "otp", name, "strip_realm", TRUE, + &strip_realm); + if (retval != 0) + goto cleanup; + + /* Set the server. */ + retval = profile_get_string(profile, "otp", name, "server", NULL, &pstr); + if (retval != 0) + goto cleanup; + if (pstr != NULL) { + server = strdup(pstr); + profile_release_string(pstr); + if (server == NULL) { + retval = ENOMEM; + goto cleanup; + } + } else if (asprintf(&server, DEFAULT_SOCKET_FMT, name) < 0) { + retval = ENOMEM; + goto cleanup; + } + + /* Get the secret (optional for Unix-domain sockets). */ + retval = profile_get_string(profile, "otp", name, "secret", NULL, &pstr); + if (retval != 0) + goto cleanup; + if (pstr != NULL) { + retval = read_secret_file(pstr, &secret); + profile_release_string(pstr); + if (retval != 0) + goto cleanup; + } else { + if (server[0] != '/') { + com_err("otp", EINVAL, "Secret missing (token type '%s')", name); + retval = EINVAL; + goto cleanup; + } + + /* Use the default empty secret for UNIX domain stream sockets. */ + secret = strdup(""); + if (secret == NULL) { + retval = ENOMEM; + goto cleanup; + } + } + + /* Get the timeout (profile value in seconds, result in milliseconds). */ + retval = profile_get_integer(profile, "otp", name, "timeout", + DEFAULT_TIMEOUT, &timeout); + if (retval != 0) + goto cleanup; + timeout *= 1000; + + /* Get the number of retries. */ + retval = profile_get_integer(profile, "otp", name, "retries", + DEFAULT_RETRIES, &retries); + if (retval != 0) + goto cleanup; + + /* Get the authentication indicators to assert if this token is used. */ + keys[0] = "otp"; + keys[1] = name; + keys[2] = "indicator"; + keys[3] = NULL; + retval = profile_get_values(profile, keys, &indicators); + if (retval == PROF_NO_RELATION) + retval = 0; + if (retval != 0) + goto cleanup; + + out->name = name_copy; + out->server = server; + out->secret = secret; + out->timeout = timeout; + out->retries = retries; + out->strip_realm = strip_realm; + out->indicators = indicators; + name_copy = server = secret = NULL; + indicators = NULL; + +cleanup: + free(name_copy); + free(server); + free(secret); + profile_free_list(indicators); + return retval; +} + +/* Free an array of token types. */ +static void +token_types_free(token_type *types) +{ + size_t i; + + if (types == NULL) + return; + + for (i = 0; types[i].server != NULL; i++) + token_type_free(&types[i]); + + free(types); +} + +/* Decode an array of token types from the profile. */ +static krb5_error_code +token_types_decode(profile_t profile, token_type **out) +{ + const char *hier[2] = { "otp", NULL }; + token_type *types = NULL; + char **names = NULL; + krb5_error_code retval; + size_t i, pos; + krb5_boolean have_default = FALSE; + + retval = profile_get_subsection_names(profile, hier, &names); + if (retval != 0) + return retval; + + /* Check if any of the profile subsections overrides the default. */ + for (i = 0; names[i] != NULL; i++) { + if (strcmp(names[i], DEFAULT_TYPE_NAME) == 0) + have_default = TRUE; + } + + /* Leave space for the default (possibly) and the terminator. */ + types = k5calloc(i + 2, sizeof(token_type), &retval); + if (types == NULL) + goto cleanup; + + /* If no default has been specified, use our internal default. */ + pos = 0; + if (!have_default) { + retval = token_type_default(&types[pos++]); + if (retval != 0) + goto cleanup; + } + + /* Decode each profile section into a token type element. */ + for (i = 0; names[i] != NULL; i++) { + retval = token_type_decode(profile, names[i], &types[pos++]); + if (retval != 0) + goto cleanup; + } + + *out = types; + types = NULL; + +cleanup: + profile_free_list(names); + token_types_free(types); + return retval; +} + +/* Free a null-terminated array of strings. */ +static void +free_strings(char **list) +{ + char **p; + + for (p = list; p != NULL && *p != NULL; p++) + free(*p); + free(list); +} + +/* Free the contents of a single token. */ +static void +token_free_contents(token *t) +{ + if (t == NULL) + return; + free(t->username.data); + free_strings(t->indicators); +} + +/* Decode a JSON array of strings into a null-terminated list of C strings. */ +static krb5_error_code +indicators_decode(krb5_context ctx, k5_json_value val, char ***indicators_out) +{ + k5_json_array arr; + k5_json_value obj; + char **indicators; + size_t len, i; + + *indicators_out = NULL; + + if (k5_json_get_tid(val) != K5_JSON_TID_ARRAY) + return EINVAL; + arr = val; + len = k5_json_array_length(arr); + indicators = calloc(len + 1, sizeof(*indicators)); + if (indicators == NULL) + return ENOMEM; + + for (i = 0; i < len; i++) { + obj = k5_json_array_get(arr, i); + if (k5_json_get_tid(obj) != K5_JSON_TID_STRING) { + free_strings(indicators); + return EINVAL; + } + indicators[i] = strdup(k5_json_string_utf8(obj)); + if (indicators[i] == NULL) { + free_strings(indicators); + return ENOMEM; + } + } + + *indicators_out = indicators; + return 0; +} + +/* Decode a single token from a JSON token object. */ +static krb5_error_code +token_decode(krb5_context ctx, krb5_const_principal princ, + const token_type *types, k5_json_object obj, token *out) +{ + const char *typename = DEFAULT_TYPE_NAME; + const token_type *type = NULL; + char *username = NULL, **indicators = NULL; + krb5_error_code retval; + k5_json_value val; + size_t i; + int flags; + + memset(out, 0, sizeof(*out)); + + /* Find the token type. */ + val = k5_json_object_get(obj, "type"); + if (val != NULL && k5_json_get_tid(val) == K5_JSON_TID_STRING) + typename = k5_json_string_utf8(val); + for (i = 0; types[i].server != NULL; i++) { + if (strcmp(typename, types[i].name) == 0) + type = &types[i]; + } + if (type == NULL) + return EINVAL; + + /* Get the username, either from obj or from unparsing the principal. */ + val = k5_json_object_get(obj, "username"); + if (val != NULL && k5_json_get_tid(val) == K5_JSON_TID_STRING) { + username = strdup(k5_json_string_utf8(val)); + if (username == NULL) + return ENOMEM; + } else { + flags = type->strip_realm ? KRB5_PRINCIPAL_UNPARSE_NO_REALM : 0; + retval = krb5_unparse_name_flags(ctx, princ, flags, &username); + if (retval != 0) + return retval; + } + + /* Get the authentication indicators if specified. */ + val = k5_json_object_get(obj, "indicators"); + if (val != NULL) { + retval = indicators_decode(ctx, val, &indicators); + if (retval != 0) { + free(username); + return retval; + } + } + + out->type = type; + out->username = string2data(username); + out->indicators = indicators; + return 0; +} + +/* Free an array of tokens. */ +static void +tokens_free(token *tokens) +{ + size_t i; + + if (tokens == NULL) + return; + + for (i = 0; tokens[i].type != NULL; i++) + token_free_contents(&tokens[i]); + + free(tokens); +} + +/* Decode a principal config string into a JSON array. Treat an empty string + * or array as if it were "[{}]" which uses the default token type. */ +static krb5_error_code +decode_config_json(const char *config, k5_json_array *out) +{ + krb5_error_code retval; + k5_json_value val; + k5_json_object obj; + + *out = NULL; + + /* Decode the config string and make sure it's an array. */ + retval = k5_json_decode((config != NULL) ? config : "[{}]", &val); + if (retval != 0) + goto error; + if (k5_json_get_tid(val) != K5_JSON_TID_ARRAY) { + retval = EINVAL; + goto error; + } + + /* If the array is empty, add in an empty object. */ + if (k5_json_array_length(val) == 0) { + retval = k5_json_object_create(&obj); + if (retval != 0) + goto error; + retval = k5_json_array_add(val, obj); + k5_json_release(obj); + if (retval != 0) + goto error; + } + + *out = val; + return 0; + +error: + k5_json_release(val); + return retval; +} + +/* Decode an array of tokens from the configuration string. */ +static krb5_error_code +tokens_decode(krb5_context ctx, krb5_const_principal princ, + const token_type *types, const char *config, token **out) +{ + krb5_error_code retval; + k5_json_array arr = NULL; + k5_json_value obj; + token *tokens = NULL; + size_t len, i; + + retval = decode_config_json(config, &arr); + if (retval != 0) + return retval; + len = k5_json_array_length(arr); + + tokens = k5calloc(len + 1, sizeof(token), &retval); + if (tokens == NULL) + goto cleanup; + + for (i = 0; i < len; i++) { + obj = k5_json_array_get(arr, i); + if (k5_json_get_tid(obj) != K5_JSON_TID_OBJECT) { + retval = EINVAL; + goto cleanup; + } + retval = token_decode(ctx, princ, types, obj, &tokens[i]); + if (retval != 0) + goto cleanup; + } + + *out = tokens; + tokens = NULL; + +cleanup: + k5_json_release(arr); + tokens_free(tokens); + return retval; +} + +static void +request_free(request *req) +{ + if (req == NULL) + return; + + krad_attrset_free(req->attrs); + tokens_free(req->tokens); + free(req); +} + +krb5_error_code +otp_state_new(krb5_context ctx, otp_state **out) +{ + char hostname[HOST_NAME_MAX + 1]; + krb5_error_code retval; + profile_t profile; + krb5_data hndata; + otp_state *self; + + retval = gethostname(hostname, sizeof(hostname)); + if (retval != 0) + return retval; + + self = calloc(1, sizeof(otp_state)); + if (self == NULL) + return ENOMEM; + + retval = krb5_get_profile(ctx, &profile); + if (retval != 0) + goto error; + + retval = token_types_decode(profile, &self->types); + profile_abandon(profile); + if (retval != 0) + goto error; + + retval = krad_attrset_new(ctx, &self->attrs); + if (retval != 0) + goto error; + + hndata = make_data(hostname, strlen(hostname)); + retval = krad_attrset_add(self->attrs, + krad_attr_name2num("NAS-Identifier"), &hndata); + if (retval != 0) + goto error; + + retval = krad_attrset_add_number(self->attrs, + krad_attr_name2num("Service-Type"), + KRAD_SERVICE_TYPE_AUTHENTICATE_ONLY); + if (retval != 0) + goto error; + + self->ctx = ctx; + *out = self; + return 0; + +error: + otp_state_free(self); + return retval; +} + +void +otp_state_free(otp_state *self) +{ + if (self == NULL) + return; + + krad_attrset_free(self->attrs); + krad_client_free(self->radius); + token_types_free(self->types); + free(self); +} + +static void +callback(krb5_error_code retval, const krad_packet *rqst, + const krad_packet *resp, void *data) +{ + request *req = data; + token *tok = &req->tokens[req->index]; + char *const *indicators; + + req->index++; + + if (retval != 0) + goto error; + + /* If we received an accept packet, success! */ + if (krad_packet_get_code(resp) == + krad_code_name2num("Access-Accept")) { + indicators = tok->indicators; + if (indicators == NULL) + indicators = tok->type->indicators; + req->cb(req->data, retval, otp_response_success, indicators); + request_free(req); + return; + } + + /* If we have no more tokens to try, failure! */ + if (req->tokens[req->index].type == NULL) + goto error; + + /* Try the next token. */ + request_send(req); + return; + +error: + req->cb(req->data, retval, otp_response_fail, NULL); + request_free(req); +} + +static void +request_send(request *req) +{ + krb5_error_code retval; + token *tok = &req->tokens[req->index]; + const token_type *t = tok->type; + + retval = krad_attrset_add(req->attrs, krad_attr_name2num("User-Name"), + &tok->username); + if (retval != 0) + goto error; + + retval = krad_client_send(req->state->radius, + krad_code_name2num("Access-Request"), req->attrs, + t->server, t->secret, t->timeout, t->retries, + callback, req); + krad_attrset_del(req->attrs, krad_attr_name2num("User-Name"), 0); + if (retval != 0) + goto error; + + return; + +error: + req->cb(req->data, retval, otp_response_fail, NULL); + request_free(req); +} + +void +otp_state_verify(otp_state *state, verto_ctx *ctx, krb5_const_principal princ, + const char *config, const krb5_pa_otp_req *req, + otp_cb cb, void *data) +{ + krb5_error_code retval; + request *rqst = NULL; + char *name; + + if (state->radius == NULL) { + retval = krad_client_new(state->ctx, ctx, &state->radius); + if (retval != 0) + goto error; + } + + rqst = calloc(1, sizeof(request)); + if (rqst == NULL) { + (*cb)(data, ENOMEM, otp_response_fail, NULL); + return; + } + rqst->state = state; + rqst->data = data; + rqst->cb = cb; + + retval = krad_attrset_copy(state->attrs, &rqst->attrs); + if (retval != 0) + goto error; + + retval = krad_attrset_add(rqst->attrs, krad_attr_name2num("User-Password"), + &req->otp_value); + if (retval != 0) + goto error; + + retval = tokens_decode(state->ctx, princ, state->types, config, + &rqst->tokens); + if (retval != 0) { + if (krb5_unparse_name(state->ctx, princ, &name) == 0) { + com_err("otp", retval, + "Can't decode otp config string for principal '%s'", name); + krb5_free_unparsed_name(state->ctx, name); + } + goto error; + } + + request_send(rqst); + return; + +error: + (*cb)(data, retval, otp_response_fail, NULL); + request_free(rqst); +} diff --git a/krb5-1.21.3/src/plugins/preauth/otp/otp_state.h b/krb5-1.21.3/src/plugins/preauth/otp/otp_state.h new file mode 100644 index 00000000..da57ad9d --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/otp/otp_state.h @@ -0,0 +1,60 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/otp/otp_state.h - Internal declarations for OTP module */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +#ifndef OTP_H_ +#define OTP_H_ + +#include +#include + +#include + +typedef enum otp_response { + otp_response_fail = 0, + otp_response_success + /* Other values reserved for responses like next token or new pin. */ +} otp_response; + +typedef struct otp_state_st otp_state; +typedef void +(*otp_cb)(void *data, krb5_error_code retval, otp_response response, + char *const *indicators); + +krb5_error_code +otp_state_new(krb5_context ctx, otp_state **self); + +void +otp_state_free(otp_state *self); + +void +otp_state_verify(otp_state *state, verto_ctx *ctx, krb5_const_principal princ, + const char *config, const krb5_pa_otp_req *request, + otp_cb cb, void *data); + +#endif /* OTP_H_ */ diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/Makefile.in b/krb5-1.21.3/src/plugins/preauth/pkinit/Makefile.in new file mode 100644 index 00000000..86f143d7 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/Makefile.in @@ -0,0 +1,53 @@ +mydir=plugins$(S)preauth$(S)pkinit +BUILDTOP=$(REL)..$(S)..$(S).. +MODULE_INSTALL_DIR = $(KRB5_PA_MODULE_DIR) + +LIBBASE=pkinit +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/preauth/pkinit +# Depends on libk5crypto and libkrb5 +SHLIB_EXPDEPS = \ + $(TOPLIBD)/libk5crypto$(SHLIBEXT) \ + $(TOPLIBD)/libkrb5$(SHLIBEXT) +SHLIB_EXPLIBS= -lkrb5 $(COM_ERR_LIB) -lk5crypto -lcrypto $(DL_LIB) $(SUPPORT_LIB) $(LIBS) + +STLIBOBJS= \ + pkinit_accessor.o \ + pkinit_srv.o \ + pkinit_lib.o \ + pkinit_clnt.o \ + pkinit_constants.o \ + pkinit_profile.o \ + pkinit_identity.o \ + pkinit_matching.o \ + pkinit_crypto_openssl.o + +SRCS= \ + $(srcdir)/pkinit_accessor.c \ + $(srcdir)/pkinit_srv.c \ + $(srcdir)/pkinit_lib.c \ + $(srcdir)/pkinit_kdf_test.c \ + $(srcdir)/pkinit_constants.c \ + $(srcdir)/pkinit_clnt.c \ + $(srcdir)/pkinit_profile.c \ + $(srcdir)/pkinit_identity.c \ + $(srcdir)/pkinit_matching.c \ + $(srcdir)/pkinit_crypto_openssl.c + +all-unix: all-liblinks +install-unix: install-libs +clean-unix:: clean-liblinks clean-libs clean-libobjs + +clean: + $(RM) pkinit_kdf_test pkinit_kdf_test.o + +check-unix: pkinit_kdf_test + $(RUN_TEST) ./pkinit_kdf_test + +pkinit_kdf_test: pkinit_kdf_test.o $(STLIBOBJS) $(SHLIB_EXPDEPS) + $(CC_LINK) -o $@ pkinit_kdf_test.o $(STLIBOBJS) $(SHLIB_EXPLIBS) + +@libnover_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/deps b/krb5-1.21.3/src/plugins/preauth/pkinit/deps new file mode 100644 index 00000000..58320aa8 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/deps @@ -0,0 +1,115 @@ +# +# Generated makefile dependencies follow. +# +pkinit_accessor.so pkinit_accessor.po $(OUTPRE)pkinit_accessor.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + pkinit_accessor.c pkinit_accessor.h +pkinit_srv.so pkinit_srv.po $(OUTPRE)pkinit_srv.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/certauth_plugin.h \ + $(top_srcdir)/include/krb5/clpreauth_plugin.h $(top_srcdir)/include/krb5/kdcpreauth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + pkcs11.h pkinit.h pkinit_accessor.h pkinit_crypto.h \ + pkinit_srv.c pkinit_trace.h +pkinit_lib.so pkinit_lib.po $(OUTPRE)pkinit_lib.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5/clpreauth_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/krb5/preauth_plugin.h pkcs11.h \ + pkinit.h pkinit_accessor.h pkinit_crypto.h pkinit_lib.c \ + pkinit_trace.h +pkinit_kdf_test.so pkinit_kdf_test.po $(OUTPRE)pkinit_kdf_test.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5/clpreauth_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/krb5/preauth_plugin.h pkcs11.h \ + pkinit.h pkinit_accessor.h pkinit_crypto.h pkinit_kdf_test.c \ + pkinit_trace.h +pkinit_constants.so pkinit_constants.po $(OUTPRE)pkinit_constants.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5/clpreauth_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/krb5/preauth_plugin.h pkcs11.h \ + pkinit.h pkinit_accessor.h pkinit_constants.c pkinit_crypto.h \ + pkinit_trace.h +pkinit_clnt.so pkinit_clnt.po $(OUTPRE)pkinit_clnt.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-json.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/clpreauth_plugin.h $(top_srcdir)/include/krb5/kdcpreauth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + pkcs11.h pkinit.h pkinit_accessor.h pkinit_clnt.c pkinit_crypto.h \ + pkinit_trace.h +pkinit_profile.so pkinit_profile.po $(OUTPRE)pkinit_profile.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/clpreauth_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/krb5/preauth_plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h pkcs11.h pkinit.h \ + pkinit_accessor.h pkinit_crypto.h pkinit_profile.c \ + pkinit_trace.h +pkinit_identity.so pkinit_identity.po $(OUTPRE)pkinit_identity.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5/clpreauth_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/krb5/preauth_plugin.h pkcs11.h \ + pkinit.h pkinit_accessor.h pkinit_crypto.h pkinit_identity.c \ + pkinit_trace.h +pkinit_matching.so pkinit_matching.po $(OUTPRE)pkinit_matching.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5/clpreauth_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/krb5/preauth_plugin.h pkcs11.h \ + pkinit.h pkinit_accessor.h pkinit_crypto.h pkinit_matching.c \ + pkinit_trace.h +pkinit_crypto_openssl.so pkinit_crypto_openssl.po $(OUTPRE)pkinit_crypto_openssl.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-hex.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/clpreauth_plugin.h $(top_srcdir)/include/krb5/kdcpreauth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/krb5/preauth_plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + pkcs11.h pkinit.h pkinit_accessor.h pkinit_crypto.h \ + pkinit_crypto_openssl.c pkinit_crypto_openssl.h pkinit_trace.h diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkcs11.h b/krb5-1.21.3/src/plugins/preauth/pkinit/pkcs11.h new file mode 100644 index 00000000..e3d28463 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkcs11.h @@ -0,0 +1,1353 @@ +/* + Copyright 2006 g10 Code GmbH + Copyright 2006 Andreas Jellinghaus + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. */ + +/* Please submit changes back to the Scute project at + https://www.scute.org/ (or send them to marcus@g10code.com), so that + they can be picked up by other projects from there as well. */ + +/* This file is a modified implementation of the PKCS #11 standard by + RSA Security Inc. It is mostly a drop-in replacement, with the + following change: + + This header file does not require any macro definitions by the user + (like CK_DEFINE_FUNCTION etc). In fact, it defines those macros + for you (if useful, some are missing, let me know if you need + more). + + There is an additional API available that does comply better to the + GNU coding standard. It can be switched on by defining + CRYPTOKI_GNU before including this header file. For this, the + following changes are made to the specification: + + All structure types are changed to a "struct ck_foo" where CK_FOO + is the type name in PKCS #11. + + All non-structure types are changed to ck_foo_t where CK_FOO is the + lowercase version of the type name in PKCS #11. The basic types + (CK_ULONG et al.) are removed without substitute. + + All members of structures are modified in the following way: Type + indication prefixes are removed, and underscore characters are + inserted before words. Then the result is lowercased. + + Note that function names are still in the original case, as they + need for ABI compatibility. + + CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute. Use + . + + If CRYPTOKI_COMPAT is defined before including this header file, + then none of the API changes above take place, and the API is the + one defined by the PKCS #11 standard. */ + +#ifndef PKCS11_H +#define PKCS11_H 1 + +#if defined(__cplusplus) +extern "C" { +#endif + + +/* The version of cryptoki we implement. The revision is changed with + each modification of this file. If you do not use the "official" + version of this file, please consider deleting the revision macro + (you may use a macro with a different name to keep track of your + versions). */ +#define CRYPTOKI_VERSION_MAJOR 2 +#define CRYPTOKI_VERSION_MINOR 20 +#define CRYPTOKI_VERSION_REVISION 6 + + +/* Compatibility interface is default, unless CRYPTOKI_GNU is + given. */ +#ifndef CRYPTOKI_GNU +#ifndef CRYPTOKI_COMPAT +#define CRYPTOKI_COMPAT 1 +#endif +#endif + +/* System dependencies. */ + +#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) + +/* There is a matching pop below. */ +#pragma pack(push, cryptoki, 1) + +#ifdef CRYPTOKI_EXPORTS +#define CK_SPEC __declspec(dllexport) +#else +#define CK_SPEC __declspec(dllimport) +#endif + +#else + +#define CK_SPEC + +#endif + +#ifdef CRYPTOKI_COMPAT + /* If we are in compatibility mode, switch all exposed names to the + PKCS #11 variant. There are corresponding #undefs below. */ + +#define ck_flags_t CK_FLAGS +#define ck_version _CK_VERSION + +#define ck_info _CK_INFO +#define cryptoki_version cryptokiVersion +#define manufacturer_id manufacturerID +#define library_description libraryDescription +#define library_version libraryVersion + +#define ck_notification_t CK_NOTIFICATION +#define ck_slot_id_t CK_SLOT_ID + +#define ck_slot_info _CK_SLOT_INFO +#define slot_description slotDescription +#define hardware_version hardwareVersion +#define firmware_version firmwareVersion + +#define ck_token_info _CK_TOKEN_INFO +#define serial_number serialNumber +#define max_session_count ulMaxSessionCount +#define session_count ulSessionCount +#define max_rw_session_count ulMaxRwSessionCount +#define rw_session_count ulRwSessionCount +#define max_pin_len ulMaxPinLen +#define min_pin_len ulMinPinLen +#define total_public_memory ulTotalPublicMemory +#define free_public_memory ulFreePublicMemory +#define total_private_memory ulTotalPrivateMemory +#define free_private_memory ulFreePrivateMemory +#define utc_time utcTime + +#define ck_session_handle_t CK_SESSION_HANDLE +#define ck_user_type_t CK_USER_TYPE +#define ck_state_t CK_STATE + +#define ck_session_info _CK_SESSION_INFO +#define slot_id slotID +#define device_error ulDeviceError + +#define ck_object_handle_t CK_OBJECT_HANDLE +#define ck_object_class_t CK_OBJECT_CLASS +#define ck_hw_feature_type_t CK_HW_FEATURE_TYPE +#define ck_key_type_t CK_KEY_TYPE +#define ck_certificate_type_t CK_CERTIFICATE_TYPE +#define ck_attribute_type_t CK_ATTRIBUTE_TYPE + +#define ck_attribute _CK_ATTRIBUTE +#define value pValue +#define value_len ulValueLen + +#define ck_date _CK_DATE + +#define ck_mechanism_type_t CK_MECHANISM_TYPE + +#define ck_mechanism _CK_MECHANISM +#define parameter pParameter +#define parameter_len ulParameterLen + +#define ck_mechanism_info _CK_MECHANISM_INFO +#define min_key_size ulMinKeySize +#define max_key_size ulMaxKeySize + +#define ck_rv_t CK_RV +#define ck_notify_t CK_NOTIFY + +#define ck_function_list _CK_FUNCTION_LIST + +#define ck_createmutex_t CK_CREATEMUTEX +#define ck_destroymutex_t CK_DESTROYMUTEX +#define ck_lockmutex_t CK_LOCKMUTEX +#define ck_unlockmutex_t CK_UNLOCKMUTEX + +#define ck_c_initialize_args _CK_C_INITIALIZE_ARGS +#define create_mutex CreateMutex +#define destroy_mutex DestroyMutex +#define lock_mutex LockMutex +#define unlock_mutex UnlockMutex +#define reserved pReserved + +#endif /* CRYPTOKI_COMPAT */ + + +typedef unsigned long ck_flags_t; + +struct ck_version +{ + unsigned char major; + unsigned char minor; +}; + + +struct ck_info +{ + struct ck_version cryptoki_version; + unsigned char manufacturer_id[32]; + ck_flags_t flags; + unsigned char library_description[32]; + struct ck_version library_version; +}; + + +typedef unsigned long ck_notification_t; + +#define CKN_SURRENDER (0) + + +typedef unsigned long ck_slot_id_t; + + +struct ck_slot_info +{ + unsigned char slot_description[64]; + unsigned char manufacturer_id[32]; + ck_flags_t flags; + struct ck_version hardware_version; + struct ck_version firmware_version; +}; + + +#define CKF_TOKEN_PRESENT (1 << 0) +#define CKF_REMOVABLE_DEVICE (1 << 1) +#define CKF_HW_SLOT (1 << 2) +#define CKF_ARRAY_ATTRIBUTE (1 << 30) + + +struct ck_token_info +{ + unsigned char label[32]; + unsigned char manufacturer_id[32]; + unsigned char model[16]; + unsigned char serial_number[16]; + ck_flags_t flags; + unsigned long max_session_count; + unsigned long session_count; + unsigned long max_rw_session_count; + unsigned long rw_session_count; + unsigned long max_pin_len; + unsigned long min_pin_len; + unsigned long total_public_memory; + unsigned long free_public_memory; + unsigned long total_private_memory; + unsigned long free_private_memory; + struct ck_version hardware_version; + struct ck_version firmware_version; + unsigned char utc_time[16]; +}; + + +#define CKF_RNG (1 << 0) +#define CKF_WRITE_PROTECTED (1 << 1) +#define CKF_LOGIN_REQUIRED (1 << 2) +#define CKF_USER_PIN_INITIALIZED (1 << 3) +#define CKF_RESTORE_KEY_NOT_NEEDED (1 << 5) +#define CKF_CLOCK_ON_TOKEN (1 << 6) +#define CKF_PROTECTED_AUTHENTICATION_PATH (1 << 8) +#define CKF_DUAL_CRYPTO_OPERATIONS (1 << 9) +#define CKF_TOKEN_INITIALIZED (1 << 10) +#define CKF_SECONDARY_AUTHENTICATION (1 << 11) +#define CKF_USER_PIN_COUNT_LOW (1 << 16) +#define CKF_USER_PIN_FINAL_TRY (1 << 17) +#define CKF_USER_PIN_LOCKED (1 << 18) +#define CKF_USER_PIN_TO_BE_CHANGED (1 << 19) +#define CKF_SO_PIN_COUNT_LOW (1 << 20) +#define CKF_SO_PIN_FINAL_TRY (1 << 21) +#define CKF_SO_PIN_LOCKED (1 << 22) +#define CKF_SO_PIN_TO_BE_CHANGED (1 << 23) + +#define CK_UNAVAILABLE_INFORMATION ((unsigned long) -1) +#define CK_EFFECTIVELY_INFINITE (0) + + +typedef unsigned long ck_session_handle_t; + +#define CK_INVALID_HANDLE (0) + + +typedef unsigned long ck_user_type_t; + +#define CKU_SO (0) +#define CKU_USER (1) +#define CKU_CONTEXT_SPECIFIC (2) + + +typedef unsigned long ck_state_t; + +#define CKS_RO_PUBLIC_SESSION (0) +#define CKS_RO_USER_FUNCTIONS (1) +#define CKS_RW_PUBLIC_SESSION (2) +#define CKS_RW_USER_FUNCTIONS (3) +#define CKS_RW_SO_FUNCTIONS (4) + + +struct ck_session_info +{ + ck_slot_id_t slot_id; + ck_state_t state; + ck_flags_t flags; + unsigned long device_error; +}; + +#define CKF_RW_SESSION (1 << 1) +#define CKF_SERIAL_SESSION (1 << 2) + + +typedef unsigned long ck_object_handle_t; + + +typedef unsigned long ck_object_class_t; + +#define CKO_DATA (0) +#define CKO_CERTIFICATE (1) +#define CKO_PUBLIC_KEY (2) +#define CKO_PRIVATE_KEY (3) +#define CKO_SECRET_KEY (4) +#define CKO_HW_FEATURE (5) +#define CKO_DOMAIN_PARAMETERS (6) +#define CKO_MECHANISM (7) +#define CKO_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +typedef unsigned long ck_hw_feature_type_t; + +#define CKH_MONOTONIC_COUNTER (1) +#define CKH_CLOCK (2) +#define CKH_USER_INTERFACE (3) +#define CKH_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +typedef unsigned long ck_key_type_t; + +#define CKK_RSA (0) +#define CKK_DSA (1) +#define CKK_DH (2) +#define CKK_ECDSA (3) +#define CKK_EC (3) +#define CKK_X9_42_DH (4) +#define CKK_KEA (5) +#define CKK_GENERIC_SECRET (0x10) +#define CKK_RC2 (0x11) +#define CKK_RC4 (0x12) +#define CKK_DES (0x13) +#define CKK_DES2 (0x14) +#define CKK_DES3 (0x15) +#define CKK_CAST (0x16) +#define CKK_CAST3 (0x17) +#define CKK_CAST128 (0x18) +#define CKK_RC5 (0x19) +#define CKK_IDEA (0x1a) +#define CKK_SKIPJACK (0x1b) +#define CKK_BATON (0x1c) +#define CKK_JUNIPER (0x1d) +#define CKK_CDMF (0x1e) +#define CKK_AES (0x1f) +#define CKK_BLOWFISH (0x20) +#define CKK_TWOFISH (0x21) +#define CKK_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +typedef unsigned long ck_certificate_type_t; + +#define CKC_X_509 (0) +#define CKC_X_509_ATTR_CERT (1) +#define CKC_WTLS (2) +#define CKC_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +typedef unsigned long ck_attribute_type_t; + +#define CKA_CLASS (0) +#define CKA_TOKEN (1) +#define CKA_PRIVATE (2) +#define CKA_LABEL (3) +#define CKA_APPLICATION (0x10) +#define CKA_VALUE (0x11) +#define CKA_OBJECT_ID (0x12) +#define CKA_CERTIFICATE_TYPE (0x80) +#define CKA_ISSUER (0x81) +#define CKA_SERIAL_NUMBER (0x82) +#define CKA_AC_ISSUER (0x83) +#define CKA_OWNER (0x84) +#define CKA_ATTR_TYPES (0x85) +#define CKA_TRUSTED (0x86) +#define CKA_CERTIFICATE_CATEGORY (0x87) +#define CKA_JAVA_MIDP_SECURITY_DOMAIN (0x88) +#define CKA_URL (0x89) +#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8a) +#define CKA_HASH_OF_ISSUER_PUBLIC_KEY (0x8b) +#define CKA_CHECK_VALUE (0x90) +#define CKA_KEY_TYPE (0x100) +#define CKA_SUBJECT (0x101) +#define CKA_ID (0x102) +#define CKA_SENSITIVE (0x103) +#define CKA_ENCRYPT (0x104) +#define CKA_DECRYPT (0x105) +#define CKA_WRAP (0x106) +#define CKA_UNWRAP (0x107) +#define CKA_SIGN (0x108) +#define CKA_SIGN_RECOVER (0x109) +#define CKA_VERIFY (0x10a) +#define CKA_VERIFY_RECOVER (0x10b) +#define CKA_DERIVE (0x10c) +#define CKA_START_DATE (0x110) +#define CKA_END_DATE (0x111) +#define CKA_MODULUS (0x120) +#define CKA_MODULUS_BITS (0x121) +#define CKA_PUBLIC_EXPONENT (0x122) +#define CKA_PRIVATE_EXPONENT (0x123) +#define CKA_PRIME_1 (0x124) +#define CKA_PRIME_2 (0x125) +#define CKA_EXPONENT_1 (0x126) +#define CKA_EXPONENT_2 (0x127) +#define CKA_COEFFICIENT (0x128) +#define CKA_PRIME (0x130) +#define CKA_SUBPRIME (0x131) +#define CKA_BASE (0x132) +#define CKA_PRIME_BITS (0x133) +#define CKA_SUB_PRIME_BITS (0x134) +#define CKA_VALUE_BITS (0x160) +#define CKA_VALUE_LEN (0x161) +#define CKA_EXTRACTABLE (0x162) +#define CKA_LOCAL (0x163) +#define CKA_NEVER_EXTRACTABLE (0x164) +#define CKA_ALWAYS_SENSITIVE (0x165) +#define CKA_KEY_GEN_MECHANISM (0x166) +#define CKA_MODIFIABLE (0x170) +#define CKA_ECDSA_PARAMS (0x180) +#define CKA_EC_PARAMS (0x180) +#define CKA_EC_POINT (0x181) +#define CKA_SECONDARY_AUTH (0x200) +#define CKA_AUTH_PIN_FLAGS (0x201) +#define CKA_ALWAYS_AUTHENTICATE (0x202) +#define CKA_WRAP_WITH_TRUSTED (0x210) +#define CKA_HW_FEATURE_TYPE (0x300) +#define CKA_RESET_ON_INIT (0x301) +#define CKA_HAS_RESET (0x302) +#define CKA_PIXEL_X (0x400) +#define CKA_PIXEL_Y (0x401) +#define CKA_RESOLUTION (0x402) +#define CKA_CHAR_ROWS (0x403) +#define CKA_CHAR_COLUMNS (0x404) +#define CKA_COLOR (0x405) +#define CKA_BITS_PER_PIXEL (0x406) +#define CKA_CHAR_SETS (0x480) +#define CKA_ENCODING_METHODS (0x481) +#define CKA_MIME_TYPES (0x482) +#define CKA_MECHANISM_TYPE (0x500) +#define CKA_REQUIRED_CMS_ATTRIBUTES (0x501) +#define CKA_DEFAULT_CMS_ATTRIBUTES (0x502) +#define CKA_SUPPORTED_CMS_ATTRIBUTES (0x503) +#define CKA_WRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x211) +#define CKA_UNWRAP_TEMPLATE (CKF_ARRAY_ATTRIBUTE | 0x212) +#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE | 0x600) +#define CKA_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +struct ck_attribute +{ + ck_attribute_type_t type; + void *value; + unsigned long value_len; +}; + + +struct ck_date +{ + unsigned char year[4]; + unsigned char month[2]; + unsigned char day[2]; +}; + + +typedef unsigned long ck_mechanism_type_t; + +#define CKM_RSA_PKCS_KEY_PAIR_GEN (0) +#define CKM_RSA_PKCS (1) +#define CKM_RSA_9796 (2) +#define CKM_RSA_X_509 (3) +#define CKM_MD2_RSA_PKCS (4) +#define CKM_MD5_RSA_PKCS (5) +#define CKM_SHA1_RSA_PKCS (6) +#define CKM_RIPEMD128_RSA_PKCS (7) +#define CKM_RIPEMD160_RSA_PKCS (8) +#define CKM_RSA_PKCS_OAEP (9) +#define CKM_RSA_X9_31_KEY_PAIR_GEN (0xa) +#define CKM_RSA_X9_31 (0xb) +#define CKM_SHA1_RSA_X9_31 (0xc) +#define CKM_RSA_PKCS_PSS (0xd) +#define CKM_SHA1_RSA_PKCS_PSS (0xe) +#define CKM_DSA_KEY_PAIR_GEN (0x10) +#define CKM_DSA (0x11) +#define CKM_DSA_SHA1 (0x12) +#define CKM_DH_PKCS_KEY_PAIR_GEN (0x20) +#define CKM_DH_PKCS_DERIVE (0x21) +#define CKM_X9_42_DH_KEY_PAIR_GEN (0x30) +#define CKM_X9_42_DH_DERIVE (0x31) +#define CKM_X9_42_DH_HYBRID_DERIVE (0x32) +#define CKM_X9_42_MQV_DERIVE (0x33) +#define CKM_SHA256_RSA_PKCS (0x40) +#define CKM_SHA384_RSA_PKCS (0x41) +#define CKM_SHA512_RSA_PKCS (0x42) +#define CKM_SHA256_RSA_PKCS_PSS (0x43) +#define CKM_SHA384_RSA_PKCS_PSS (0x44) +#define CKM_SHA512_RSA_PKCS_PSS (0x45) +#define CKM_RC2_KEY_GEN (0x100) +#define CKM_RC2_ECB (0x101) +#define CKM_RC2_CBC (0x102) +#define CKM_RC2_MAC (0x103) +#define CKM_RC2_MAC_GENERAL (0x104) +#define CKM_RC2_CBC_PAD (0x105) +#define CKM_RC4_KEY_GEN (0x110) +#define CKM_RC4 (0x111) +#define CKM_DES_KEY_GEN (0x120) +#define CKM_DES_ECB (0x121) +#define CKM_DES_CBC (0x122) +#define CKM_DES_MAC (0x123) +#define CKM_DES_MAC_GENERAL (0x124) +#define CKM_DES_CBC_PAD (0x125) +#define CKM_DES2_KEY_GEN (0x130) +#define CKM_DES3_KEY_GEN (0x131) +#define CKM_DES3_ECB (0x132) +#define CKM_DES3_CBC (0x133) +#define CKM_DES3_MAC (0x134) +#define CKM_DES3_MAC_GENERAL (0x135) +#define CKM_DES3_CBC_PAD (0x136) +#define CKM_CDMF_KEY_GEN (0x140) +#define CKM_CDMF_ECB (0x141) +#define CKM_CDMF_CBC (0x142) +#define CKM_CDMF_MAC (0x143) +#define CKM_CDMF_MAC_GENERAL (0x144) +#define CKM_CDMF_CBC_PAD (0x145) +#define CKM_MD2 (0x200) +#define CKM_MD2_HMAC (0x201) +#define CKM_MD2_HMAC_GENERAL (0x202) +#define CKM_MD5 (0x210) +#define CKM_MD5_HMAC (0x211) +#define CKM_MD5_HMAC_GENERAL (0x212) +#define CKM_SHA_1 (0x220) +#define CKM_SHA_1_HMAC (0x221) +#define CKM_SHA_1_HMAC_GENERAL (0x222) +#define CKM_RIPEMD128 (0x230) +#define CKM_RIPEMD128_HMAC (0x231) +#define CKM_RIPEMD128_HMAC_GENERAL (0x232) +#define CKM_RIPEMD160 (0x240) +#define CKM_RIPEMD160_HMAC (0x241) +#define CKM_RIPEMD160_HMAC_GENERAL (0x242) +#define CKM_SHA256 (0x250) +#define CKM_SHA256_HMAC (0x251) +#define CKM_SHA256_HMAC_GENERAL (0x252) +#define CKM_SHA384 (0x260) +#define CKM_SHA384_HMAC (0x261) +#define CKM_SHA384_HMAC_GENERAL (0x262) +#define CKM_SHA512 (0x270) +#define CKM_SHA512_HMAC (0x271) +#define CKM_SHA512_HMAC_GENERAL (0x272) +#define CKM_CAST_KEY_GEN (0x300) +#define CKM_CAST_ECB (0x301) +#define CKM_CAST_CBC (0x302) +#define CKM_CAST_MAC (0x303) +#define CKM_CAST_MAC_GENERAL (0x304) +#define CKM_CAST_CBC_PAD (0x305) +#define CKM_CAST3_KEY_GEN (0x310) +#define CKM_CAST3_ECB (0x311) +#define CKM_CAST3_CBC (0x312) +#define CKM_CAST3_MAC (0x313) +#define CKM_CAST3_MAC_GENERAL (0x314) +#define CKM_CAST3_CBC_PAD (0x315) +#define CKM_CAST5_KEY_GEN (0x320) +#define CKM_CAST128_KEY_GEN (0x320) +#define CKM_CAST5_ECB (0x321) +#define CKM_CAST128_ECB (0x321) +#define CKM_CAST5_CBC (0x322) +#define CKM_CAST128_CBC (0x322) +#define CKM_CAST5_MAC (0x323) +#define CKM_CAST128_MAC (0x323) +#define CKM_CAST5_MAC_GENERAL (0x324) +#define CKM_CAST128_MAC_GENERAL (0x324) +#define CKM_CAST5_CBC_PAD (0x325) +#define CKM_CAST128_CBC_PAD (0x325) +#define CKM_RC5_KEY_GEN (0x330) +#define CKM_RC5_ECB (0x331) +#define CKM_RC5_CBC (0x332) +#define CKM_RC5_MAC (0x333) +#define CKM_RC5_MAC_GENERAL (0x334) +#define CKM_RC5_CBC_PAD (0x335) +#define CKM_IDEA_KEY_GEN (0x340) +#define CKM_IDEA_ECB (0x341) +#define CKM_IDEA_CBC (0x342) +#define CKM_IDEA_MAC (0x343) +#define CKM_IDEA_MAC_GENERAL (0x344) +#define CKM_IDEA_CBC_PAD (0x345) +#define CKM_GENERIC_SECRET_KEY_GEN (0x350) +#define CKM_CONCATENATE_BASE_AND_KEY (0x360) +#define CKM_CONCATENATE_BASE_AND_DATA (0x362) +#define CKM_CONCATENATE_DATA_AND_BASE (0x363) +#define CKM_XOR_BASE_AND_DATA (0x364) +#define CKM_EXTRACT_KEY_FROM_KEY (0x365) +#define CKM_SSL3_PRE_MASTER_KEY_GEN (0x370) +#define CKM_SSL3_MASTER_KEY_DERIVE (0x371) +#define CKM_SSL3_KEY_AND_MAC_DERIVE (0x372) +#define CKM_SSL3_MASTER_KEY_DERIVE_DH (0x373) +#define CKM_TLS_PRE_MASTER_KEY_GEN (0x374) +#define CKM_TLS_MASTER_KEY_DERIVE (0x375) +#define CKM_TLS_KEY_AND_MAC_DERIVE (0x376) +#define CKM_TLS_MASTER_KEY_DERIVE_DH (0x377) +#define CKM_SSL3_MD5_MAC (0x380) +#define CKM_SSL3_SHA1_MAC (0x381) +#define CKM_MD5_KEY_DERIVATION (0x390) +#define CKM_MD2_KEY_DERIVATION (0x391) +#define CKM_SHA1_KEY_DERIVATION (0x392) +#define CKM_PBE_MD2_DES_CBC (0x3a0) +#define CKM_PBE_MD5_DES_CBC (0x3a1) +#define CKM_PBE_MD5_CAST_CBC (0x3a2) +#define CKM_PBE_MD5_CAST3_CBC (0x3a3) +#define CKM_PBE_MD5_CAST5_CBC (0x3a4) +#define CKM_PBE_MD5_CAST128_CBC (0x3a4) +#define CKM_PBE_SHA1_CAST5_CBC (0x3a5) +#define CKM_PBE_SHA1_CAST128_CBC (0x3a5) +#define CKM_PBE_SHA1_RC4_128 (0x3a6) +#define CKM_PBE_SHA1_RC4_40 (0x3a7) +#define CKM_PBE_SHA1_DES3_EDE_CBC (0x3a8) +#define CKM_PBE_SHA1_DES2_EDE_CBC (0x3a9) +#define CKM_PBE_SHA1_RC2_128_CBC (0x3aa) +#define CKM_PBE_SHA1_RC2_40_CBC (0x3ab) +#define CKM_PKCS5_PBKD2 (0x3b0) +#define CKM_PBA_SHA1_WITH_SHA1_HMAC (0x3c0) +#define CKM_KEY_WRAP_LYNKS (0x400) +#define CKM_KEY_WRAP_SET_OAEP (0x401) +#define CKM_SKIPJACK_KEY_GEN (0x1000) +#define CKM_SKIPJACK_ECB64 (0x1001) +#define CKM_SKIPJACK_CBC64 (0x1002) +#define CKM_SKIPJACK_OFB64 (0x1003) +#define CKM_SKIPJACK_CFB64 (0x1004) +#define CKM_SKIPJACK_CFB32 (0x1005) +#define CKM_SKIPJACK_CFB16 (0x1006) +#define CKM_SKIPJACK_CFB8 (0x1007) +#define CKM_SKIPJACK_WRAP (0x1008) +#define CKM_SKIPJACK_PRIVATE_WRAP (0x1009) +#define CKM_SKIPJACK_RELAYX (0x100a) +#define CKM_KEA_KEY_PAIR_GEN (0x1010) +#define CKM_KEA_KEY_DERIVE (0x1011) +#define CKM_FORTEZZA_TIMESTAMP (0x1020) +#define CKM_BATON_KEY_GEN (0x1030) +#define CKM_BATON_ECB128 (0x1031) +#define CKM_BATON_ECB96 (0x1032) +#define CKM_BATON_CBC128 (0x1033) +#define CKM_BATON_COUNTER (0x1034) +#define CKM_BATON_SHUFFLE (0x1035) +#define CKM_BATON_WRAP (0x1036) +#define CKM_ECDSA_KEY_PAIR_GEN (0x1040) +#define CKM_EC_KEY_PAIR_GEN (0x1040) +#define CKM_ECDSA (0x1041) +#define CKM_ECDSA_SHA1 (0x1042) +#define CKM_ECDH1_DERIVE (0x1050) +#define CKM_ECDH1_COFACTOR_DERIVE (0x1051) +#define CKM_ECMQV_DERIVE (0x1052) +#define CKM_JUNIPER_KEY_GEN (0x1060) +#define CKM_JUNIPER_ECB128 (0x1061) +#define CKM_JUNIPER_CBC128 (0x1062) +#define CKM_JUNIPER_COUNTER (0x1063) +#define CKM_JUNIPER_SHUFFLE (0x1064) +#define CKM_JUNIPER_WRAP (0x1065) +#define CKM_FASTHASH (0x1070) +#define CKM_AES_KEY_GEN (0x1080) +#define CKM_AES_ECB (0x1081) +#define CKM_AES_CBC (0x1082) +#define CKM_AES_MAC (0x1083) +#define CKM_AES_MAC_GENERAL (0x1084) +#define CKM_AES_CBC_PAD (0x1085) +#define CKM_DSA_PARAMETER_GEN (0x2000) +#define CKM_DH_PKCS_PARAMETER_GEN (0x2001) +#define CKM_X9_42_DH_PARAMETER_GEN (0x2002) +#define CKM_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +struct ck_mechanism +{ + ck_mechanism_type_t mechanism; + void *parameter; + unsigned long parameter_len; +}; + + +struct ck_mechanism_info +{ + unsigned long min_key_size; + unsigned long max_key_size; + ck_flags_t flags; +}; + +#define CKF_HW (1 << 0) +#define CKF_ENCRYPT (1 << 8) +#define CKF_DECRYPT (1 << 9) +#define CKF_DIGEST (1 << 10) +#define CKF_SIGN (1 << 11) +#define CKF_SIGN_RECOVER (1 << 12) +#define CKF_VERIFY (1 << 13) +#define CKF_VERIFY_RECOVER (1 << 14) +#define CKF_GENERATE (1 << 15) +#define CKF_GENERATE_KEY_PAIR (1 << 16) +#define CKF_WRAP (1 << 17) +#define CKF_UNWRAP (1 << 18) +#define CKF_DERIVE (1 << 19) +#define CKF_EXTENSION ((unsigned long) (1 << 31)) + + +/* Flags for C_WaitForSlotEvent. */ +#define CKF_DONT_BLOCK (1) + + +typedef unsigned long ck_rv_t; + + +typedef ck_rv_t (*ck_notify_t) (ck_session_handle_t session, + ck_notification_t event, void *application); + +/* Forward reference. */ +struct ck_function_list; + +#define _CK_DECLARE_FUNCTION(name, args) \ +typedef ck_rv_t (*CK_ ## name) args; \ +ck_rv_t CK_SPEC name args + +_CK_DECLARE_FUNCTION (C_Initialize, (void *init_args)); +_CK_DECLARE_FUNCTION (C_Finalize, (void *reserved)); +_CK_DECLARE_FUNCTION (C_GetInfo, (struct ck_info *info)); +_CK_DECLARE_FUNCTION (C_GetFunctionList, + (struct ck_function_list **function_list)); + +_CK_DECLARE_FUNCTION (C_GetSlotList, + (unsigned char token_present, ck_slot_id_t *slot_list, + unsigned long *count)); +_CK_DECLARE_FUNCTION (C_GetSlotInfo, + (ck_slot_id_t slot_id, struct ck_slot_info *info)); +_CK_DECLARE_FUNCTION (C_GetTokenInfo, + (ck_slot_id_t slot_id, struct ck_token_info *info)); +_CK_DECLARE_FUNCTION (C_WaitForSlotEvent, + (ck_flags_t flags, ck_slot_id_t *slot, void *reserved)); +_CK_DECLARE_FUNCTION (C_GetMechanismList, + (ck_slot_id_t slot_id, + ck_mechanism_type_t *mechanism_list, + unsigned long *count)); +_CK_DECLARE_FUNCTION (C_GetMechanismInfo, + (ck_slot_id_t slot_id, ck_mechanism_type_t type, + struct ck_mechanism_info *info)); +_CK_DECLARE_FUNCTION (C_InitToken, + (ck_slot_id_t slot_id, unsigned char *pin, + unsigned long pin_len, unsigned char *label)); +_CK_DECLARE_FUNCTION (C_InitPIN, + (ck_session_handle_t session, unsigned char *pin, + unsigned long pin_len)); +_CK_DECLARE_FUNCTION (C_SetPIN, + (ck_session_handle_t session, unsigned char *old_pin, + unsigned long old_len, unsigned char *new_pin, + unsigned long new_len)); + +_CK_DECLARE_FUNCTION (C_OpenSession, + (ck_slot_id_t slot_id, ck_flags_t flags, + void *application, ck_notify_t notify, + ck_session_handle_t *session)); +_CK_DECLARE_FUNCTION (C_CloseSession, (ck_session_handle_t session)); +_CK_DECLARE_FUNCTION (C_CloseAllSessions, (ck_slot_id_t slot_id)); +_CK_DECLARE_FUNCTION (C_GetSessionInfo, + (ck_session_handle_t session, + struct ck_session_info *info)); +_CK_DECLARE_FUNCTION (C_GetOperationState, + (ck_session_handle_t session, + unsigned char *operation_state, + unsigned long *operation_state_len)); +_CK_DECLARE_FUNCTION (C_SetOperationState, + (ck_session_handle_t session, + unsigned char *operation_state, + unsigned long operation_state_len, + ck_object_handle_t encryption_key, + ck_object_handle_t authentiation_key)); +_CK_DECLARE_FUNCTION (C_Login, + (ck_session_handle_t session, ck_user_type_t user_type, + unsigned char *pin, unsigned long pin_len)); +_CK_DECLARE_FUNCTION (C_Logout, (ck_session_handle_t session)); + +_CK_DECLARE_FUNCTION (C_CreateObject, + (ck_session_handle_t session, + struct ck_attribute *templ, + unsigned long count, ck_object_handle_t *object)); +_CK_DECLARE_FUNCTION (C_CopyObject, + (ck_session_handle_t session, ck_object_handle_t object, + struct ck_attribute *templ, unsigned long count, + ck_object_handle_t *new_object)); +_CK_DECLARE_FUNCTION (C_DestroyObject, + (ck_session_handle_t session, + ck_object_handle_t object)); +_CK_DECLARE_FUNCTION (C_GetObjectSize, + (ck_session_handle_t session, + ck_object_handle_t object, + unsigned long *size)); +_CK_DECLARE_FUNCTION (C_GetAttributeValue, + (ck_session_handle_t session, + ck_object_handle_t object, + struct ck_attribute *templ, + unsigned long count)); +_CK_DECLARE_FUNCTION (C_SetAttributeValue, + (ck_session_handle_t session, + ck_object_handle_t object, + struct ck_attribute *templ, + unsigned long count)); +_CK_DECLARE_FUNCTION (C_FindObjectsInit, + (ck_session_handle_t session, + struct ck_attribute *templ, + unsigned long count)); +_CK_DECLARE_FUNCTION (C_FindObjects, + (ck_session_handle_t session, + ck_object_handle_t *object, + unsigned long max_object_count, + unsigned long *object_count)); +_CK_DECLARE_FUNCTION (C_FindObjectsFinal, + (ck_session_handle_t session)); + +_CK_DECLARE_FUNCTION (C_EncryptInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Encrypt, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *encrypted_data, + unsigned long *encrypted_data_len)); +_CK_DECLARE_FUNCTION (C_EncryptUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len, + unsigned char *encrypted_part, + unsigned long *encrypted_part_len)); +_CK_DECLARE_FUNCTION (C_EncryptFinal, + (ck_session_handle_t session, + unsigned char *last_encrypted_part, + unsigned long *last_encrypted_part_len)); + +_CK_DECLARE_FUNCTION (C_DecryptInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Decrypt, + (ck_session_handle_t session, + unsigned char *encrypted_data, + unsigned long encrypted_data_len, + unsigned char *data, unsigned long *data_len)); +_CK_DECLARE_FUNCTION (C_DecryptUpdate, + (ck_session_handle_t session, + unsigned char *encrypted_part, + unsigned long encrypted_part_len, + unsigned char *part, unsigned long *part_len)); +_CK_DECLARE_FUNCTION (C_DecryptFinal, + (ck_session_handle_t session, + unsigned char *last_part, + unsigned long *last_part_len)); + +_CK_DECLARE_FUNCTION (C_DigestInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism)); +_CK_DECLARE_FUNCTION (C_Digest, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *digest, + unsigned long *digest_len)); +_CK_DECLARE_FUNCTION (C_DigestUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len)); +_CK_DECLARE_FUNCTION (C_DigestKey, + (ck_session_handle_t session, ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_DigestFinal, + (ck_session_handle_t session, + unsigned char *digest, + unsigned long *digest_len)); + +_CK_DECLARE_FUNCTION (C_SignInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Sign, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *signature, + unsigned long *signature_len)); +_CK_DECLARE_FUNCTION (C_SignUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len)); +_CK_DECLARE_FUNCTION (C_SignFinal, + (ck_session_handle_t session, + unsigned char *signature, + unsigned long *signature_len)); +_CK_DECLARE_FUNCTION (C_SignRecoverInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_SignRecover, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *signature, + unsigned long *signature_len)); + +_CK_DECLARE_FUNCTION (C_VerifyInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_Verify, + (ck_session_handle_t session, + unsigned char *data, unsigned long data_len, + unsigned char *signature, + unsigned long signature_len)); +_CK_DECLARE_FUNCTION (C_VerifyUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len)); +_CK_DECLARE_FUNCTION (C_VerifyFinal, + (ck_session_handle_t session, + unsigned char *signature, + unsigned long signature_len)); +_CK_DECLARE_FUNCTION (C_VerifyRecoverInit, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t key)); +_CK_DECLARE_FUNCTION (C_VerifyRecover, + (ck_session_handle_t session, + unsigned char *signature, + unsigned long signature_len, + unsigned char *data, + unsigned long *data_len)); + +_CK_DECLARE_FUNCTION (C_DigestEncryptUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len, + unsigned char *encrypted_part, + unsigned long *encrypted_part_len)); +_CK_DECLARE_FUNCTION (C_DecryptDigestUpdate, + (ck_session_handle_t session, + unsigned char *encrypted_part, + unsigned long encrypted_part_len, + unsigned char *part, + unsigned long *part_len)); +_CK_DECLARE_FUNCTION (C_SignEncryptUpdate, + (ck_session_handle_t session, + unsigned char *part, unsigned long part_len, + unsigned char *encrypted_part, + unsigned long *encrypted_part_len)); +_CK_DECLARE_FUNCTION (C_DecryptVerifyUpdate, + (ck_session_handle_t session, + unsigned char *encrypted_part, + unsigned long encrypted_part_len, + unsigned char *part, + unsigned long *part_len)); + +_CK_DECLARE_FUNCTION (C_GenerateKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + struct ck_attribute *templ, + unsigned long count, + ck_object_handle_t *key)); +_CK_DECLARE_FUNCTION (C_GenerateKeyPair, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + struct ck_attribute *public_key_template, + unsigned long public_key_attribute_count, + struct ck_attribute *private_key_template, + unsigned long private_key_attribute_count, + ck_object_handle_t *public_key, + ck_object_handle_t *private_key)); +_CK_DECLARE_FUNCTION (C_WrapKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t wrapping_key, + ck_object_handle_t key, + unsigned char *wrapped_key, + unsigned long *wrapped_key_len)); +_CK_DECLARE_FUNCTION (C_UnwrapKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t unwrapping_key, + unsigned char *wrapped_key, + unsigned long wrapped_key_len, + struct ck_attribute *templ, + unsigned long attribute_count, + ck_object_handle_t *key)); +_CK_DECLARE_FUNCTION (C_DeriveKey, + (ck_session_handle_t session, + struct ck_mechanism *mechanism, + ck_object_handle_t base_key, + struct ck_attribute *templ, + unsigned long attribute_count, + ck_object_handle_t *key)); + +_CK_DECLARE_FUNCTION (C_SeedRandom, + (ck_session_handle_t session, unsigned char *seed, + unsigned long seed_len)); +_CK_DECLARE_FUNCTION (C_GenerateRandom, + (ck_session_handle_t session, + unsigned char *random_data, + unsigned long random_len)); + +_CK_DECLARE_FUNCTION (C_GetFunctionStatus, (ck_session_handle_t session)); +_CK_DECLARE_FUNCTION (C_CancelFunction, (ck_session_handle_t session)); + + +struct ck_function_list +{ + struct ck_version version; + CK_C_Initialize C_Initialize; + CK_C_Finalize C_Finalize; + CK_C_GetInfo C_GetInfo; + CK_C_GetFunctionList C_GetFunctionList; + CK_C_GetSlotList C_GetSlotList; + CK_C_GetSlotInfo C_GetSlotInfo; + CK_C_GetTokenInfo C_GetTokenInfo; + CK_C_GetMechanismList C_GetMechanismList; + CK_C_GetMechanismInfo C_GetMechanismInfo; + CK_C_InitToken C_InitToken; + CK_C_InitPIN C_InitPIN; + CK_C_SetPIN C_SetPIN; + CK_C_OpenSession C_OpenSession; + CK_C_CloseSession C_CloseSession; + CK_C_CloseAllSessions C_CloseAllSessions; + CK_C_GetSessionInfo C_GetSessionInfo; + CK_C_GetOperationState C_GetOperationState; + CK_C_SetOperationState C_SetOperationState; + CK_C_Login C_Login; + CK_C_Logout C_Logout; + CK_C_CreateObject C_CreateObject; + CK_C_CopyObject C_CopyObject; + CK_C_DestroyObject C_DestroyObject; + CK_C_GetObjectSize C_GetObjectSize; + CK_C_GetAttributeValue C_GetAttributeValue; + CK_C_SetAttributeValue C_SetAttributeValue; + CK_C_FindObjectsInit C_FindObjectsInit; + CK_C_FindObjects C_FindObjects; + CK_C_FindObjectsFinal C_FindObjectsFinal; + CK_C_EncryptInit C_EncryptInit; + CK_C_Encrypt C_Encrypt; + CK_C_EncryptUpdate C_EncryptUpdate; + CK_C_EncryptFinal C_EncryptFinal; + CK_C_DecryptInit C_DecryptInit; + CK_C_Decrypt C_Decrypt; + CK_C_DecryptUpdate C_DecryptUpdate; + CK_C_DecryptFinal C_DecryptFinal; + CK_C_DigestInit C_DigestInit; + CK_C_Digest C_Digest; + CK_C_DigestUpdate C_DigestUpdate; + CK_C_DigestKey C_DigestKey; + CK_C_DigestFinal C_DigestFinal; + CK_C_SignInit C_SignInit; + CK_C_Sign C_Sign; + CK_C_SignUpdate C_SignUpdate; + CK_C_SignFinal C_SignFinal; + CK_C_SignRecoverInit C_SignRecoverInit; + CK_C_SignRecover C_SignRecover; + CK_C_VerifyInit C_VerifyInit; + CK_C_Verify C_Verify; + CK_C_VerifyUpdate C_VerifyUpdate; + CK_C_VerifyFinal C_VerifyFinal; + CK_C_VerifyRecoverInit C_VerifyRecoverInit; + CK_C_VerifyRecover C_VerifyRecover; + CK_C_DigestEncryptUpdate C_DigestEncryptUpdate; + CK_C_DecryptDigestUpdate C_DecryptDigestUpdate; + CK_C_SignEncryptUpdate C_SignEncryptUpdate; + CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate; + CK_C_GenerateKey C_GenerateKey; + CK_C_GenerateKeyPair C_GenerateKeyPair; + CK_C_WrapKey C_WrapKey; + CK_C_UnwrapKey C_UnwrapKey; + CK_C_DeriveKey C_DeriveKey; + CK_C_SeedRandom C_SeedRandom; + CK_C_GenerateRandom C_GenerateRandom; + CK_C_GetFunctionStatus C_GetFunctionStatus; + CK_C_CancelFunction C_CancelFunction; + CK_C_WaitForSlotEvent C_WaitForSlotEvent; +}; + + +typedef ck_rv_t (*ck_createmutex_t) (void **mutex); +typedef ck_rv_t (*ck_destroymutex_t) (void *mutex); +typedef ck_rv_t (*ck_lockmutex_t) (void *mutex); +typedef ck_rv_t (*ck_unlockmutex_t) (void *mutex); + + +struct ck_c_initialize_args +{ + ck_createmutex_t create_mutex; + ck_destroymutex_t destroy_mutex; + ck_lockmutex_t lock_mutex; + ck_unlockmutex_t unlock_mutex; + ck_flags_t flags; + void *reserved; +}; + + +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS (1 << 0) +#define CKF_OS_LOCKING_OK (1 << 1) + +#define CKR_OK (0) +#define CKR_CANCEL (1) +#define CKR_HOST_MEMORY (2) +#define CKR_SLOT_ID_INVALID (3) +#define CKR_GENERAL_ERROR (5) +#define CKR_FUNCTION_FAILED (6) +#define CKR_ARGUMENTS_BAD (7) +#define CKR_NO_EVENT (8) +#define CKR_NEED_TO_CREATE_THREADS (9) +#define CKR_CANT_LOCK (0xa) +#define CKR_ATTRIBUTE_READ_ONLY (0x10) +#define CKR_ATTRIBUTE_SENSITIVE (0x11) +#define CKR_ATTRIBUTE_TYPE_INVALID (0x12) +#define CKR_ATTRIBUTE_VALUE_INVALID (0x13) +#define CKR_DATA_INVALID (0x20) +#define CKR_DATA_LEN_RANGE (0x21) +#define CKR_DEVICE_ERROR (0x30) +#define CKR_DEVICE_MEMORY (0x31) +#define CKR_DEVICE_REMOVED (0x32) +#define CKR_ENCRYPTED_DATA_INVALID (0x40) +#define CKR_ENCRYPTED_DATA_LEN_RANGE (0x41) +#define CKR_FUNCTION_CANCELED (0x50) +#define CKR_FUNCTION_NOT_PARALLEL (0x51) +#define CKR_FUNCTION_NOT_SUPPORTED (0x54) +#define CKR_KEY_HANDLE_INVALID (0x60) +#define CKR_KEY_SIZE_RANGE (0x62) +#define CKR_KEY_TYPE_INCONSISTENT (0x63) +#define CKR_KEY_NOT_NEEDED (0x64) +#define CKR_KEY_CHANGED (0x65) +#define CKR_KEY_NEEDED (0x66) +#define CKR_KEY_INDIGESTIBLE (0x67) +#define CKR_KEY_FUNCTION_NOT_PERMITTED (0x68) +#define CKR_KEY_NOT_WRAPPABLE (0x69) +#define CKR_KEY_UNEXTRACTABLE (0x6a) +#define CKR_MECHANISM_INVALID (0x70) +#define CKR_MECHANISM_PARAM_INVALID (0x71) +#define CKR_OBJECT_HANDLE_INVALID (0x82) +#define CKR_OPERATION_ACTIVE (0x90) +#define CKR_OPERATION_NOT_INITIALIZED (0x91) +#define CKR_PIN_INCORRECT (0xa0) +#define CKR_PIN_INVALID (0xa1) +#define CKR_PIN_LEN_RANGE (0xa2) +#define CKR_PIN_EXPIRED (0xa3) +#define CKR_PIN_LOCKED (0xa4) +#define CKR_SESSION_CLOSED (0xb0) +#define CKR_SESSION_COUNT (0xb1) +#define CKR_SESSION_HANDLE_INVALID (0xb3) +#define CKR_SESSION_PARALLEL_NOT_SUPPORTED (0xb4) +#define CKR_SESSION_READ_ONLY (0xb5) +#define CKR_SESSION_EXISTS (0xb6) +#define CKR_SESSION_READ_ONLY_EXISTS (0xb7) +#define CKR_SESSION_READ_WRITE_SO_EXISTS (0xb8) +#define CKR_SIGNATURE_INVALID (0xc0) +#define CKR_SIGNATURE_LEN_RANGE (0xc1) +#define CKR_TEMPLATE_INCOMPLETE (0xd0) +#define CKR_TEMPLATE_INCONSISTENT (0xd1) +#define CKR_TOKEN_NOT_PRESENT (0xe0) +#define CKR_TOKEN_NOT_RECOGNIZED (0xe1) +#define CKR_TOKEN_WRITE_PROTECTED (0xe2) +#define CKR_UNWRAPPING_KEY_HANDLE_INVALID (0xf0) +#define CKR_UNWRAPPING_KEY_SIZE_RANGE (0xf1) +#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT (0xf2) +#define CKR_USER_ALREADY_LOGGED_IN (0x100) +#define CKR_USER_NOT_LOGGED_IN (0x101) +#define CKR_USER_PIN_NOT_INITIALIZED (0x102) +#define CKR_USER_TYPE_INVALID (0x103) +#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN (0x104) +#define CKR_USER_TOO_MANY_TYPES (0x105) +#define CKR_WRAPPED_KEY_INVALID (0x110) +#define CKR_WRAPPED_KEY_LEN_RANGE (0x112) +#define CKR_WRAPPING_KEY_HANDLE_INVALID (0x113) +#define CKR_WRAPPING_KEY_SIZE_RANGE (0x114) +#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT (0x115) +#define CKR_RANDOM_SEED_NOT_SUPPORTED (0x120) +#define CKR_RANDOM_NO_RNG (0x121) +#define CKR_DOMAIN_PARAMS_INVALID (0x130) +#define CKR_BUFFER_TOO_SMALL (0x150) +#define CKR_SAVED_STATE_INVALID (0x160) +#define CKR_INFORMATION_SENSITIVE (0x170) +#define CKR_STATE_UNSAVEABLE (0x180) +#define CKR_CRYPTOKI_NOT_INITIALIZED (0x190) +#define CKR_CRYPTOKI_ALREADY_INITIALIZED (0x191) +#define CKR_MUTEX_BAD (0x1a0) +#define CKR_MUTEX_NOT_LOCKED (0x1a1) +#define CKR_FUNCTION_REJECTED (0x200) +#define CKR_VENDOR_DEFINED ((unsigned long) (1 << 31)) + + +/* Compatibility layer. */ + +#ifdef CRYPTOKI_COMPAT + +#undef CK_DEFINE_FUNCTION +#define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name + +/* For NULL. */ +#include + +typedef unsigned char CK_BYTE; +typedef unsigned char CK_CHAR; +typedef unsigned char CK_UTF8CHAR; +typedef unsigned char CK_BBOOL; +typedef unsigned long int CK_ULONG; +typedef long int CK_LONG; +typedef CK_BYTE *CK_BYTE_PTR; +typedef CK_CHAR *CK_CHAR_PTR; +typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR; +typedef CK_ULONG *CK_ULONG_PTR; +typedef void *CK_VOID_PTR; +typedef void **CK_VOID_PTR_PTR; +#define CK_FALSE 0 +#define CK_TRUE 1 +#ifndef CK_DISABLE_TRUE_FALSE +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#endif + +typedef struct ck_version CK_VERSION; +typedef struct ck_version *CK_VERSION_PTR; + +typedef struct ck_info CK_INFO; +typedef struct ck_info *CK_INFO_PTR; + +typedef ck_slot_id_t *CK_SLOT_ID_PTR; + +typedef struct ck_slot_info CK_SLOT_INFO; +typedef struct ck_slot_info *CK_SLOT_INFO_PTR; + +typedef struct ck_token_info CK_TOKEN_INFO; +typedef struct ck_token_info *CK_TOKEN_INFO_PTR; + +typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR; + +typedef struct ck_session_info CK_SESSION_INFO; +typedef struct ck_session_info *CK_SESSION_INFO_PTR; + +typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR; + +typedef ck_object_class_t *CK_OBJECT_CLASS_PTR; + +typedef struct ck_attribute CK_ATTRIBUTE; +typedef struct ck_attribute *CK_ATTRIBUTE_PTR; + +typedef struct ck_date CK_DATE; +typedef struct ck_date *CK_DATE_PTR; + +typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR; + +typedef struct ck_mechanism CK_MECHANISM; +typedef struct ck_mechanism *CK_MECHANISM_PTR; + +typedef struct ck_mechanism_info CK_MECHANISM_INFO; +typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR; + +typedef struct ck_function_list CK_FUNCTION_LIST; +typedef struct ck_function_list *CK_FUNCTION_LIST_PTR; +typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR; + +typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS; +typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR; + +#define NULL_PTR NULL + +/* Delete the helper macros defined at the top of the file. */ +#undef ck_flags_t +#undef ck_version + +#undef ck_info +#undef cryptoki_version +#undef manufacturer_id +#undef library_description +#undef library_version + +#undef ck_notification_t +#undef ck_slot_id_t + +#undef ck_slot_info +#undef slot_description +#undef hardware_version +#undef firmware_version + +#undef ck_token_info +#undef serial_number +#undef max_session_count +#undef session_count +#undef max_rw_session_count +#undef rw_session_count +#undef max_pin_len +#undef min_pin_len +#undef total_public_memory +#undef free_public_memory +#undef total_private_memory +#undef free_private_memory +#undef utc_time + +#undef ck_session_handle_t +#undef ck_user_type_t +#undef ck_state_t + +#undef ck_session_info +#undef slot_id +#undef device_error + +#undef ck_object_handle_t +#undef ck_object_class_t +#undef ck_hw_feature_type_t +#undef ck_key_type_t +#undef ck_certificate_type_t +#undef ck_attribute_type_t + +#undef ck_attribute +#undef value +#undef value_len + +#undef ck_date + +#undef ck_mechanism_type_t + +#undef ck_mechanism +#undef parameter +#undef parameter_len + +#undef ck_mechanism_info +#undef min_key_size +#undef max_key_size + +#undef ck_rv_t +#undef ck_notify_t + +#undef ck_function_list + +#undef ck_createmutex_t +#undef ck_destroymutex_t +#undef ck_lockmutex_t +#undef ck_unlockmutex_t + +#undef ck_c_initialize_args +#undef create_mutex +#undef destroy_mutex +#undef lock_mutex +#undef unlock_mutex +#undef reserved + +#endif /* CRYPTOKI_COMPAT */ + +/* System dependencies. */ +#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32) +#pragma pack(pop, cryptoki) +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* PKCS11_H */ diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit.exports b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit.exports new file mode 100644 index 00000000..e77fa3ef --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit.exports @@ -0,0 +1,2 @@ +clpreauth_pkinit_initvt +kdcpreauth_pkinit_initvt diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit.h b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit.h new file mode 100644 index 00000000..66f92d8f --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit.h @@ -0,0 +1,385 @@ +/* + * COPYRIGHT (C) 2006,2007 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#ifndef _PKINIT_H +#define _PKINIT_H + +#include +#include +#include +#include +#include +#include "pkinit_accessor.h" +#include "pkinit_trace.h" + +#ifndef WITHOUT_PKCS11 +#include "pkcs11.h" + +#define PK_SIGLEN_GUESS 1000 +#define PK_NOSLOT 999999 +#endif + +#define DH_PROTOCOL 1 +#define RSA_PROTOCOL 2 + +#define TD_TRUSTED_CERTIFIERS 104 +#define TD_INVALID_CERTIFICATES 105 +#define TD_DH_PARAMETERS 109 + +#define PKINIT_CTX_MAGIC 0x05551212 +#define PKINIT_REQ_CTX_MAGIC 0xdeadbeef +#define PKINIT_DEFERRED_ID_MAGIC 0x3ca20d21 + +#define PKINIT_DEFAULT_DH_MIN_BITS 2048 +#define PKINIT_DH_MIN_CONFIG_BITS 1024 + +#define KRB5_CONF_KDCDEFAULTS "kdcdefaults" +#define KRB5_CONF_LIBDEFAULTS "libdefaults" +#define KRB5_CONF_REALMS "realms" +#define KRB5_CONF_PKINIT_ALLOW_UPN "pkinit_allow_upn" +#define KRB5_CONF_PKINIT_ANCHORS "pkinit_anchors" +#define KRB5_CONF_PKINIT_INDICATOR "pkinit_indicator" +#define KRB5_CONF_PKINIT_CERT_MATCH "pkinit_cert_match" +#define KRB5_CONF_PKINIT_DH_MIN_BITS "pkinit_dh_min_bits" +#define KRB5_CONF_PKINIT_EKU_CHECKING "pkinit_eku_checking" +#define KRB5_CONF_PKINIT_IDENTITIES "pkinit_identities" +#define KRB5_CONF_PKINIT_IDENTITY "pkinit_identity" +#define KRB5_CONF_PKINIT_KDC_HOSTNAME "pkinit_kdc_hostname" +/* pkinit_kdc_ocsp has been removed */ +#define KRB5_CONF_PKINIT_KDC_OCSP "pkinit_kdc_ocsp" +#define KRB5_CONF_PKINIT_POOL "pkinit_pool" +#define KRB5_CONF_PKINIT_REQUIRE_CRL_CHECKING "pkinit_require_crl_checking" +#define KRB5_CONF_PKINIT_REQUIRE_FRESHNESS "pkinit_require_freshness" +#define KRB5_CONF_PKINIT_REVOKE "pkinit_revoke" + +/* Make pkiDebug(fmt,...) print, or not. */ +#ifdef DEBUG +#define pkiDebug printf +#else +/* Still evaluates for side effects. */ +static inline void pkiDebug (const char *fmt, ...) { } +/* This is better if the compiler doesn't inline variadic functions + well, but gcc will warn about "left-hand operand of comma + expression has no effect". Still evaluates for side effects. */ +/* #define pkiDebug (void) */ +#endif + +/* Solaris compiler doesn't grok __FUNCTION__ + * hack for now. Fix all the uses eventually. */ +#define __FUNCTION__ __func__ + +/* Macros to deal with converting between various data types... */ +#define PADATA_TO_KRB5DATA(pad, k5d) \ + (k5d)->length = (pad)->length; (k5d)->data = (char *)(pad)->contents; +#define OCTETDATA_TO_KRB5DATA(octd, k5d) \ + (k5d)->length = (octd)->length; (k5d)->data = (char *)(octd)->data; + +extern const krb5_data dh_oid; + +/* + * notes about crypto contexts: + * + * the basic idea is that there are crypto contexts that live at + * both the plugin level and request level. the identity context (that + * keeps info about your own certs and such) is separate because + * it is needed at different levels for the kdc and and the client. + * (the kdc's identity is at the plugin level, the client's identity + * information could change per-request.) + * the identity context is meant to have the entity's cert, + * a list of trusted and intermediate cas, a list of crls, and any + * pkcs11 information. the req context is meant to have the + * received certificate and the DH related information. the plugin + * context is meant to have global crypto information, i.e., OIDs + * and constant DH parameter information. + */ + +/* + * plugin crypto context should keep plugin common information, + * eg., OIDs, known DHparams + */ +typedef struct _pkinit_plg_crypto_context *pkinit_plg_crypto_context; + +/* + * request crypto context should keep reqyest common information, + * eg., received credentials, DH parameters of this request + */ +typedef struct _pkinit_req_crypto_context *pkinit_req_crypto_context; + +/* + * identity context should keep information about credentials + * for the request, eg., my credentials, trusted ca certs, + * intermediate ca certs, crls, pkcs11 info + */ +typedef struct _pkinit_identity_crypto_context *pkinit_identity_crypto_context; + +/* + * this structure keeps information about the config options + */ +typedef struct _pkinit_plg_opts { + int require_eku; /* require EKU checking (default is true) */ + int accept_secondary_eku;/* accept secondary EKU (default is false) */ + int allow_upn; /* allow UPN-SAN instead of pkinit-SAN */ + int dh_or_rsa; /* selects DH or RSA based pkinit */ + int require_crl_checking; /* require CRL for a CA (default is false) */ + int require_freshness; /* require freshness token (default is false) */ + int disable_freshness; /* disable freshness token on client for testing */ + int dh_min_bits; /* minimum DH modulus size allowed */ +} pkinit_plg_opts; + +/* + * this structure keeps options used for a given request + */ +typedef struct _pkinit_req_opts { + int require_eku; + int accept_secondary_eku; + int allow_upn; + int dh_or_rsa; + int require_crl_checking; + int dh_size; /* initial request DH modulus size (default=1024) */ + int require_hostname_match; + int disable_freshness; +} pkinit_req_opts; + +/* + * information about identity from config file or command line + */ + +typedef struct _pkinit_identity_opts { + char *identity; + char **identity_alt; + char **anchors; + char **intermediates; + char **crls; + int idtype; + char *cert_filename; + char *key_filename; +#ifndef WITHOUT_PKCS11 + char *p11_module_name; + CK_SLOT_ID slotid; + char *token_label; + char *cert_id_string; + char *cert_label; +#endif +} pkinit_identity_opts; + + +/* + * Client's plugin context + */ +struct _pkinit_context { + int magic; + pkinit_plg_crypto_context cryptoctx; + pkinit_plg_opts *opts; + pkinit_identity_opts *idopts; +}; +typedef struct _pkinit_context *pkinit_context; + +/* + * Client's per-request context + */ +struct _pkinit_req_context { + unsigned int magic; + pkinit_req_crypto_context cryptoctx; + pkinit_req_opts *opts; + pkinit_identity_crypto_context idctx; + pkinit_identity_opts *idopts; + int do_identity_matching; + krb5_preauthtype pa_type; + int rfc6112_kdc; + int identity_initialized; + int identity_prompted; + krb5_error_code identity_prompt_retval; + krb5_data *freshness_token; +}; +typedef struct _pkinit_req_context *pkinit_req_context; + +/* + * KDC's (per-realm) plugin context + */ +struct _pkinit_kdc_context { + int magic; + pkinit_plg_crypto_context cryptoctx; + pkinit_plg_opts *opts; + pkinit_identity_crypto_context idctx; + pkinit_identity_opts *idopts; + char *realmname; + unsigned int realmname_len; + char **auth_indicators; +}; +typedef struct _pkinit_kdc_context *pkinit_kdc_context; + +/* + * KDC's per-request context + */ +struct _pkinit_kdc_req_context { + int magic; + pkinit_req_crypto_context cryptoctx; + krb5_auth_pack *rcv_auth_pack; + krb5_preauthtype pa_type; +}; +typedef struct _pkinit_kdc_req_context *pkinit_kdc_req_context; + +/* + * Functions in pkinit_lib.c + */ + +krb5_error_code pkinit_init_req_opts(pkinit_req_opts **); +void pkinit_fini_req_opts(pkinit_req_opts *); + +krb5_error_code pkinit_init_plg_opts(pkinit_plg_opts **); +void pkinit_fini_plg_opts(pkinit_plg_opts *); + +krb5_error_code pkinit_init_identity_opts(pkinit_identity_opts **idopts); +void pkinit_fini_identity_opts(pkinit_identity_opts *idopts); +krb5_error_code pkinit_dup_identity_opts(pkinit_identity_opts *src_opts, + pkinit_identity_opts **dest_opts); + +/* + * Functions in pkinit_identity.c + */ +char * idtype2string(int idtype); +char * catype2string(int catype); + +krb5_error_code pkinit_identity_initialize + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_opts *idopts, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */ + krb5_clpreauth_callbacks cb, /* IN/OUT */ + krb5_clpreauth_rock rock, /* IN/OUT */ + krb5_principal princ); /* IN (optional) */ + +krb5_error_code pkinit_identity_prompt + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_opts *idopts, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */ + krb5_clpreauth_callbacks cb, /* IN/OUT */ + krb5_clpreauth_rock rock, /* IN/OUT */ + int do_matching, /* IN */ + krb5_principal princ); /* IN (optional) */ + +krb5_error_code pkinit_cert_matching + (krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_principal princ); + +krb5_error_code pkinit_client_cert_match + (krb5_context context, + pkinit_plg_crypto_context plgctx, + pkinit_req_crypto_context reqctx, + const char *match_rule, + krb5_boolean *matched); + +/* + * Client's list of identities for which it needs PINs or passwords + */ +struct _pkinit_deferred_id { + int magic; + char *identity; + unsigned long ck_flags; + char *password; +}; +typedef struct _pkinit_deferred_id *pkinit_deferred_id; + +krb5_error_code pkinit_set_deferred_id + (pkinit_deferred_id **identities, const char *identity, + unsigned long ck_flags, const char *password); +const char * pkinit_find_deferred_id + (pkinit_deferred_id *identities, const char *identity); +unsigned long pkinit_get_deferred_id_flags + (pkinit_deferred_id *identities, const char *identity); +void pkinit_free_deferred_ids(pkinit_deferred_id *identities); + +/* + * initialization and free functions + */ +void init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in); +void init_krb5_reply_key_pack(krb5_reply_key_pack **in); + +void init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in); + +void free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in); +void free_krb5_reply_key_pack(krb5_reply_key_pack **in); +void free_krb5_auth_pack(krb5_auth_pack **in); +void free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in); +void free_krb5_external_principal_identifier(krb5_external_principal_identifier ***in); +void free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in); +void free_krb5_algorithm_identifier(krb5_algorithm_identifier *in); +void free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in); +krb5_error_code pkinit_copy_krb5_data(krb5_data *dst, const krb5_data *src); + + +/* + * Functions in pkinit_profile.c + */ +krb5_error_code pkinit_kdcdefault_strings + (krb5_context context, const char *realmname, const char *option, + char ***ret_value); +krb5_error_code pkinit_kdcdefault_string + (krb5_context context, const char *realmname, const char *option, + char **ret_value); +krb5_error_code pkinit_kdcdefault_boolean + (krb5_context context, const char *realmname, const char *option, + int default_value, int *ret_value); +krb5_error_code pkinit_kdcdefault_integer + (krb5_context context, const char *realmname, const char *option, + int default_value, int *ret_value); + + +krb5_error_code pkinit_libdefault_strings + (krb5_context context, const krb5_data *realm, + const char *option, char ***ret_value); +krb5_error_code pkinit_libdefault_string + (krb5_context context, const krb5_data *realm, + const char *option, char **ret_value); +krb5_error_code pkinit_libdefault_boolean + (krb5_context context, const krb5_data *realm, const char *option, + int default_value, int *ret_value); +krb5_error_code pkinit_libdefault_integer + (krb5_context context, const krb5_data *realm, const char *option, + int default_value, int *ret_value); + +/* + * debugging functions + */ +void print_buffer(const unsigned char *, unsigned int); +void print_buffer_bin(unsigned char *, unsigned int, char *); + +/* + * Now get crypto function declarations + */ +#include "pkinit_crypto.h" + +#endif /* _PKINIT_H */ diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_accessor.c b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_accessor.c new file mode 100644 index 00000000..0908f1b9 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_accessor.c @@ -0,0 +1,110 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * COPYRIGHT (C) 2006,2007 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#include +#include "pkinit_accessor.h" + +#define DEF_FUNC_PTRS(type) \ + krb5_error_code (*k5int_encode_##type)(const type *, krb5_data **); \ + krb5_error_code (*k5int_decode_##type)(const krb5_data *, type **) + +#define DEF_FUNC_PTRS_ARRAY(type) \ + krb5_error_code (*k5int_encode_##type)(const type **, krb5_data **); \ + krb5_error_code (*k5int_decode_##type)(const krb5_data *, type ***) + +DEF_FUNC_PTRS(krb5_auth_pack); +DEF_FUNC_PTRS(krb5_kdc_dh_key_info); +DEF_FUNC_PTRS(krb5_pa_pk_as_rep); +DEF_FUNC_PTRS(krb5_pa_pk_as_req); +DEF_FUNC_PTRS(krb5_reply_key_pack); + +/* special cases... */ +krb5_error_code +(*k5int_decode_krb5_principal_name)(const krb5_data *, krb5_principal_data **); + +krb5_error_code +(*k5int_encode_krb5_td_dh_parameters)(krb5_algorithm_identifier *const *, + krb5_data **code); +krb5_error_code +(*k5int_decode_krb5_td_dh_parameters)(const krb5_data *, + krb5_algorithm_identifier ***); + +krb5_error_code +(*k5int_encode_krb5_td_trusted_certifiers) +(krb5_external_principal_identifier *const *, krb5_data **code); + +krb5_error_code +(*k5int_decode_krb5_td_trusted_certifiers) +(const krb5_data *, + krb5_external_principal_identifier ***); + +krb5_error_code +(*k5int_encode_krb5_kdc_req_body)(const krb5_kdc_req *rep, krb5_data **code); + +void KRB5_CALLCONV +(*k5int_krb5_free_kdc_req)(krb5_context, krb5_kdc_req * ); + +void +(*k5int_set_prompt_types)(krb5_context, krb5_prompt_type *); + + +/* + * Grab internal function pointers from the krb5int_accessor + * structure and make them available + */ +krb5_error_code +pkinit_accessor_init(void) +{ + krb5_error_code retval; + krb5int_access k5int; + + retval = krb5int_accessor(&k5int, KRB5INT_ACCESS_VERSION); + if (retval) + return retval; +#define SET_PTRS(type) \ + k5int_encode_##type = k5int.encode_##type; \ + k5int_decode_##type = k5int.decode_##type; + + SET_PTRS(krb5_auth_pack); + SET_PTRS(krb5_kdc_dh_key_info); + SET_PTRS(krb5_pa_pk_as_rep); + SET_PTRS(krb5_pa_pk_as_req); + SET_PTRS(krb5_reply_key_pack); + SET_PTRS(krb5_td_dh_parameters); + SET_PTRS(krb5_td_trusted_certifiers); + + /* special cases... */ + k5int_decode_krb5_principal_name = k5int.decode_krb5_principal_name; + k5int_encode_krb5_kdc_req_body = k5int.encode_krb5_kdc_req_body; + k5int_krb5_free_kdc_req = k5int.free_kdc_req; + k5int_set_prompt_types = k5int.set_prompt_types; + return 0; +} diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_accessor.h b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_accessor.h new file mode 100644 index 00000000..e510ab62 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_accessor.h @@ -0,0 +1,74 @@ +/* + * COPYRIGHT (C) 2006,2007 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#ifndef _PKINIT_ACCESSOR_H +#define _PKINIT_ACCESSOR_H + +/* + * Function prototypes + */ +krb5_error_code pkinit_accessor_init(void); + +#define DEF_EXT_FUNC_PTRS(type) \ +extern krb5_error_code (*k5int_encode_##type)(const type *, krb5_data **); \ +extern krb5_error_code (*k5int_decode_##type)(const krb5_data *, type **) + +#define DEF_EXT_FUNC_PTRS_ARRAY(type) \ +extern krb5_error_code (*k5int_encode_##type)(const type **, krb5_data **); \ +extern krb5_error_code (*k5int_decode_##type)(const krb5_data *, type ***) + +DEF_EXT_FUNC_PTRS(krb5_auth_pack); +DEF_EXT_FUNC_PTRS(krb5_kdc_dh_key_info); +DEF_EXT_FUNC_PTRS(krb5_pa_pk_as_rep); +DEF_EXT_FUNC_PTRS(krb5_pa_pk_as_req); +DEF_EXT_FUNC_PTRS(krb5_reply_key_pack); + +/* special cases... */ +extern krb5_error_code (*k5int_decode_krb5_principal_name) + (const krb5_data *, krb5_principal_data **); + +extern krb5_error_code (*k5int_encode_krb5_td_dh_parameters) + (krb5_algorithm_identifier *const *, krb5_data **code); +extern krb5_error_code (*k5int_decode_krb5_td_dh_parameters) + (const krb5_data *, krb5_algorithm_identifier ***); + +extern krb5_error_code (*k5int_encode_krb5_td_trusted_certifiers) + (krb5_external_principal_identifier *const *, krb5_data **code); +extern krb5_error_code (*k5int_decode_krb5_td_trusted_certifiers) + (const krb5_data *, krb5_external_principal_identifier ***); + +extern krb5_error_code (*k5int_encode_krb5_kdc_req_body) + (const krb5_kdc_req *rep, krb5_data **code); +extern void KRB5_CALLCONV (*k5int_krb5_free_kdc_req) + (krb5_context, krb5_kdc_req * ); +extern void (*k5int_set_prompt_types) + (krb5_context, krb5_prompt_type *); + +#endif /* _PKINIT_ACCESSOR_H */ diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_clnt.c b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_clnt.c new file mode 100644 index 00000000..725d5bc4 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_clnt.c @@ -0,0 +1,1514 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * COPYRIGHT (C) 2006,2007 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#include "k5-int.h" +#include "pkinit.h" +#include "k5-json.h" + +#include +#include + +/** + * Return true if we should use ContentInfo rather than SignedData. This + * happens if we are talking to what might be an old (pre-6112) MIT KDC and + * we're using anonymous. + */ +static int +use_content_info(krb5_context context, pkinit_req_context req, + krb5_principal client) +{ + if (req->rfc6112_kdc) + return 0; + if (krb5_principal_compare_any_realm(context, client, + krb5_anonymous_principal())) + return 1; + return 0; +} + +static krb5_error_code +pkinit_as_req_create(krb5_context context, pkinit_context plgctx, + pkinit_req_context reqctx, krb5_timestamp ctsec, + krb5_int32 cusec, krb5_ui_4 nonce, + const krb5_checksum *cksum, + krb5_principal client, krb5_principal server, + krb5_data **as_req); + +static krb5_error_code +pkinit_as_rep_parse(krb5_context context, pkinit_context plgctx, + pkinit_req_context reqctx, krb5_preauthtype pa_type, + krb5_kdc_req *request, const krb5_data *as_rep, + krb5_keyblock *key_block, krb5_enctype etype, krb5_data *); + +static void pkinit_client_plugin_fini(krb5_context context, + krb5_clpreauth_moddata moddata); + +static krb5_error_code +pa_pkinit_gen_req(krb5_context context, + pkinit_context plgctx, + pkinit_req_context reqctx, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, + krb5_kdc_req * request, + krb5_preauthtype pa_type, + krb5_pa_data *** out_padata, + krb5_prompter_fct prompter, + void *prompter_data, + krb5_get_init_creds_opt *gic_opt) +{ + + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + krb5_data *out_data = NULL; + krb5_timestamp ctsec = 0; + krb5_int32 cusec = 0; + krb5_ui_4 nonce = 0; + krb5_checksum cksum; + krb5_data *der_req = NULL; + krb5_pa_data **return_pa_data = NULL; + + memset(&cksum, 0, sizeof(cksum)); + reqctx->pa_type = pa_type; + + pkiDebug("kdc_options = 0x%x till = %d\n", + request->kdc_options, request->till); + /* If we don't have a client, we're done */ + if (request->client == NULL) { + pkiDebug("No request->client; aborting PKINIT\n"); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + + retval = pkinit_get_kdc_cert(context, plgctx->cryptoctx, reqctx->cryptoctx, + reqctx->idctx, request->server); + if (retval) { + pkiDebug("pkinit_get_kdc_cert returned %d\n", retval); + goto cleanup; + } + + /* checksum of the encoded KDC-REQ-BODY */ + retval = k5int_encode_krb5_kdc_req_body(request, &der_req); + if (retval) { + pkiDebug("encode_krb5_kdc_req_body returned %d\n", (int) retval); + goto cleanup; + } + + retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req, + &cksum); + if (retval) + goto cleanup; + TRACE_PKINIT_CLIENT_REQ_CHECKSUM(context, &cksum); +#ifdef DEBUG_CKSUM + pkiDebug("calculating checksum on buf size (%d)\n", der_req->length); + print_buffer(der_req->data, der_req->length); +#endif + + retval = cb->get_preauth_time(context, rock, TRUE, &ctsec, &cusec); + if (retval) + goto cleanup; + + /* XXX PKINIT RFC says that nonce in PKAuthenticator doesn't have be the + * same as in the AS_REQ. However, if we pick a different nonce, then we + * need to remember that info when AS_REP is returned. I'm choosing to + * reuse the AS_REQ nonce. + */ + nonce = request->nonce; + + retval = pkinit_as_req_create(context, plgctx, reqctx, ctsec, cusec, + nonce, &cksum, request->client, request->server, &out_data); + if (retval) { + pkiDebug("error %d on pkinit_as_req_create; aborting PKINIT\n", + (int) retval); + goto cleanup; + } + + return_pa_data = k5calloc(2, sizeof(*return_pa_data), &retval); + if (return_pa_data == NULL) + goto cleanup; + + return_pa_data[0] = k5alloc(sizeof(*return_pa_data[0]), &retval); + if (return_pa_data[0] == NULL) + goto cleanup; + + return_pa_data[0]->magic = KV5M_PA_DATA; + + return_pa_data[0]->pa_type = pa_type; + return_pa_data[0]->length = out_data->length; + return_pa_data[0]->contents = (krb5_octet *) out_data->data; + *out_data = empty_data(); + + *out_padata = return_pa_data; + return_pa_data = NULL; + cb->disable_fallback(context, rock); + +cleanup: + krb5_free_data(context, der_req); + krb5_free_checksum_contents(context, &cksum); + krb5_free_data(context, out_data); + krb5_free_pa_data(context, return_pa_data); + return retval; +} + +static krb5_error_code +pkinit_as_req_create(krb5_context context, + pkinit_context plgctx, + pkinit_req_context reqctx, + krb5_timestamp ctsec, + krb5_int32 cusec, + krb5_ui_4 nonce, + const krb5_checksum * cksum, + krb5_principal client, + krb5_principal server, + krb5_data ** as_req) +{ + krb5_error_code retval = ENOMEM; + krb5_data spki = empty_data(), *coded_auth_pack = NULL; + krb5_auth_pack auth_pack; + krb5_pa_pk_as_req *req = NULL; + krb5_algorithm_identifier **cmstypes = NULL; + int protocol = reqctx->opts->dh_or_rsa; + + pkiDebug("pkinit_as_req_create pa_type = %d\n", reqctx->pa_type); + + /* Create the authpack */ + memset(&auth_pack, 0, sizeof(auth_pack)); + auth_pack.pkAuthenticator.ctime = ctsec; + auth_pack.pkAuthenticator.cusec = cusec; + auth_pack.pkAuthenticator.nonce = nonce; + auth_pack.pkAuthenticator.paChecksum = *cksum; + if (!reqctx->opts->disable_freshness) + auth_pack.pkAuthenticator.freshnessToken = reqctx->freshness_token; + auth_pack.clientDHNonce.length = 0; + auth_pack.supportedKDFs = (krb5_data **)supported_kdf_alg_ids; + + /* add List of CMS algorithms */ + retval = create_krb5_supportedCMSTypes(context, plgctx->cryptoctx, + reqctx->cryptoctx, + reqctx->idctx, &cmstypes); + auth_pack.supportedCMSTypes = cmstypes; + if (retval) + goto cleanup; + + switch(protocol) { + case DH_PROTOCOL: + TRACE_PKINIT_CLIENT_REQ_DH(context); + pkiDebug("as_req: DH key transport algorithm\n"); + + /* create client-side DH keys */ + retval = client_create_dh(context, plgctx->cryptoctx, + reqctx->cryptoctx, reqctx->idctx, + reqctx->opts->dh_size, &spki); + auth_pack.clientPublicValue = spki; + if (retval != 0) { + pkiDebug("failed to create dh parameters\n"); + goto cleanup; + } + break; + case RSA_PROTOCOL: + TRACE_PKINIT_CLIENT_REQ_RSA(context); + pkiDebug("as_req: RSA key transport algorithm\n"); + break; + default: + pkiDebug("as_req: unknown key transport protocol %d\n", + protocol); + retval = -1; + goto cleanup; + } + + retval = k5int_encode_krb5_auth_pack(&auth_pack, &coded_auth_pack); + if (retval) { + pkiDebug("failed to encode the AuthPack %d\n", retval); + goto cleanup; + } +#ifdef DEBUG_ASN1 + print_buffer_bin((unsigned char *)coded_auth_pack->data, + coded_auth_pack->length, + "/tmp/client_auth_pack"); +#endif + + /* create PKCS7 object from authpack */ + init_krb5_pa_pk_as_req(&req); + if (req == NULL) { + retval = ENOMEM; + goto cleanup; + } + if (use_content_info(context, reqctx, client)) { + retval = cms_contentinfo_create(context, plgctx->cryptoctx, + reqctx->cryptoctx, reqctx->idctx, + CMS_SIGN_CLIENT, + (unsigned char *) + coded_auth_pack->data, + coded_auth_pack->length, + (unsigned char **) + &req->signedAuthPack.data, + &req->signedAuthPack.length); + } else { + retval = cms_signeddata_create(context, plgctx->cryptoctx, + reqctx->cryptoctx, reqctx->idctx, + CMS_SIGN_CLIENT, + (unsigned char *) + coded_auth_pack->data, + coded_auth_pack->length, + (unsigned char **) + &req->signedAuthPack.data, + &req->signedAuthPack.length); + } + +#ifdef DEBUG_ASN1 + print_buffer_bin((unsigned char *)req->signedAuthPack.data, + req->signedAuthPack.length, + "/tmp/client_signed_data"); +#endif + + krb5_free_data(context, coded_auth_pack); + if (retval) { + pkiDebug("failed to create pkcs7 signed data\n"); + goto cleanup; + } + + /* create a list of trusted CAs */ + retval = create_krb5_trustedCertifiers(context, plgctx->cryptoctx, + reqctx->cryptoctx, reqctx->idctx, + &req->trustedCertifiers); + if (retval) + goto cleanup; + retval = create_issuerAndSerial(context, plgctx->cryptoctx, + reqctx->cryptoctx, reqctx->idctx, + (unsigned char **)&req->kdcPkId.data, + &req->kdcPkId.length); + if (retval) + goto cleanup; + + /* Encode the as-req */ + retval = k5int_encode_krb5_pa_pk_as_req(req, as_req); + +#ifdef DEBUG_ASN1 + if (!retval) + print_buffer_bin((unsigned char *)(*as_req)->data, (*as_req)->length, + "/tmp/client_as_req"); +#endif + +cleanup: + free_krb5_algorithm_identifiers(&cmstypes); + free_krb5_pa_pk_as_req(&req); + krb5_free_data_contents(context, &spki); + + pkiDebug("pkinit_as_req_create retval=%d\n", (int) retval); + + return retval; +} + +static krb5_error_code +pa_pkinit_parse_rep(krb5_context context, + pkinit_context plgctx, + pkinit_req_context reqctx, + krb5_kdc_req * request, + krb5_pa_data * in_padata, + krb5_enctype etype, + krb5_keyblock * as_key, + krb5_data *encoded_request) +{ + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + krb5_data asRep = { 0, 0, NULL}; + + /* + * One way or the other - success or failure - no other PA systems can + * work if the server sent us a PKINIT reply, since only we know how to + * decrypt the key. + */ + if ((in_padata == NULL) || (in_padata->length == 0)) { + pkiDebug("pa_pkinit_parse_rep: no in_padata\n"); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + + asRep.data = (char *) in_padata->contents; + asRep.length = in_padata->length; + + retval = + pkinit_as_rep_parse(context, plgctx, reqctx, in_padata->pa_type, + request, &asRep, as_key, etype, encoded_request); + if (retval) { + pkiDebug("pkinit_as_rep_parse returned %d (%s)\n", + retval, error_message(retval)); + goto cleanup; + } + + retval = 0; + +cleanup: + + return retval; +} + +static krb5_error_code +verify_kdc_san(krb5_context context, + pkinit_context plgctx, + pkinit_req_context reqctx, + krb5_principal kdcprinc, + int *valid_san, + int *need_eku_checking) +{ + krb5_error_code retval; + char **certhosts = NULL, **cfghosts = NULL, **hostptr; + krb5_principal *princs = NULL; + unsigned char ***get_dns; + int i, j; + + *valid_san = 0; + *need_eku_checking = 1; + + retval = pkinit_libdefault_strings(context, + krb5_princ_realm(context, kdcprinc), + KRB5_CONF_PKINIT_KDC_HOSTNAME, + &cfghosts); + if (retval || cfghosts == NULL) { + pkiDebug("%s: No pkinit_kdc_hostname values found in config file\n", + __FUNCTION__); + get_dns = NULL; + } else { + pkiDebug("%s: pkinit_kdc_hostname values found in config file\n", + __FUNCTION__); + for (hostptr = cfghosts; *hostptr != NULL; hostptr++) + TRACE_PKINIT_CLIENT_SAN_CONFIG_DNSNAME(context, *hostptr); + get_dns = (unsigned char ***)&certhosts; + } + + retval = crypto_retrieve_cert_sans(context, plgctx->cryptoctx, + reqctx->cryptoctx, reqctx->idctx, + &princs, NULL, get_dns); + if (retval) { + pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__); + TRACE_PKINIT_CLIENT_SAN_ERR(context); + retval = KRB5KDC_ERR_KDC_NAME_MISMATCH; + goto out; + } + for (i = 0; princs != NULL && princs[i] != NULL; i++) + TRACE_PKINIT_CLIENT_SAN_KDCCERT_PRINC(context, princs[i]); + if (certhosts != NULL) { + for (hostptr = certhosts; *hostptr != NULL; hostptr++) + TRACE_PKINIT_CLIENT_SAN_KDCCERT_DNSNAME(context, *hostptr); + } + + pkiDebug("%s: Checking pkinit sans\n", __FUNCTION__); + for (i = 0; princs != NULL && princs[i] != NULL; i++) { + if (krb5_principal_compare(context, princs[i], kdcprinc)) { + TRACE_PKINIT_CLIENT_SAN_MATCH_PRINC(context, kdcprinc); + pkiDebug("%s: pkinit san match found\n", __FUNCTION__); + *valid_san = 1; + *need_eku_checking = 0; + retval = 0; + goto out; + } + } + pkiDebug("%s: no pkinit san match found\n", __FUNCTION__); + + if (certhosts == NULL) { + pkiDebug("%s: no certhosts (or we wouldn't accept them anyway)\n", + __FUNCTION__); + retval = KRB5KDC_ERR_KDC_NAME_MISMATCH; + goto out; + } + + for (i = 0; certhosts[i] != NULL; i++) { + for (j = 0; cfghosts != NULL && cfghosts[j] != NULL; j++) { + pkiDebug("%s: comparing cert name '%s' with config name '%s'\n", + __FUNCTION__, certhosts[i], cfghosts[j]); + if (strcasecmp(certhosts[i], cfghosts[j]) == 0) { + TRACE_PKINIT_CLIENT_SAN_MATCH_DNSNAME(context, certhosts[i]); + pkiDebug("%s: we have a dnsName match\n", __FUNCTION__); + *valid_san = 1; + retval = 0; + goto out; + } + } + } + TRACE_PKINIT_CLIENT_SAN_MATCH_NONE(context); + pkiDebug("%s: no dnsName san match found\n", __FUNCTION__); + + /* We found no match */ + retval = 0; + +out: + if (princs != NULL) { + for (i = 0; princs[i] != NULL; i++) + krb5_free_principal(context, princs[i]); + free(princs); + } + if (certhosts != NULL) { + for (i = 0; certhosts[i] != NULL; i++) + free(certhosts[i]); + free(certhosts); + } + if (cfghosts != NULL) + profile_free_list(cfghosts); + + pkiDebug("%s: returning retval %d, valid_san %d, need_eku_checking %d\n", + __FUNCTION__, retval, *valid_san, *need_eku_checking); + return retval; +} + +static krb5_error_code +verify_kdc_eku(krb5_context context, + pkinit_context plgctx, + pkinit_req_context reqctx, + int *eku_accepted) +{ + krb5_error_code retval; + + *eku_accepted = 0; + + if (reqctx->opts->require_eku == 0) { + TRACE_PKINIT_CLIENT_EKU_SKIP(context); + pkiDebug("%s: configuration requests no EKU checking\n", __FUNCTION__); + *eku_accepted = 1; + retval = 0; + goto out; + } + retval = crypto_check_cert_eku(context, plgctx->cryptoctx, + reqctx->cryptoctx, reqctx->idctx, + 1, /* kdc cert */ + reqctx->opts->accept_secondary_eku, + eku_accepted); + if (retval) { + pkiDebug("%s: Error from crypto_check_cert_eku %d (%s)\n", + __FUNCTION__, retval, error_message(retval)); + goto out; + } + +out: + if (*eku_accepted) + TRACE_PKINIT_CLIENT_EKU_ACCEPT(context); + else + TRACE_PKINIT_CLIENT_EKU_REJECT(context); + pkiDebug("%s: returning retval %d, eku_accepted %d\n", + __FUNCTION__, retval, *eku_accepted); + return retval; +} + +/* + * Parse PA-PK-AS-REP message. Optionally evaluates the message's + * certificate chain. + * Optionally returns various components. + */ +static krb5_error_code +pkinit_as_rep_parse(krb5_context context, + pkinit_context plgctx, + pkinit_req_context reqctx, + krb5_preauthtype pa_type, + krb5_kdc_req *request, + const krb5_data *as_rep, + krb5_keyblock *key_block, + krb5_enctype etype, + krb5_data *encoded_request) +{ + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + krb5_principal kdc_princ = NULL; + krb5_pa_pk_as_rep *kdc_reply = NULL; + krb5_kdc_dh_key_info *kdc_dh = NULL; + krb5_reply_key_pack *key_pack = NULL; + krb5_data dh_data = { 0, 0, NULL }; + unsigned char *client_key = NULL, *kdc_hostname = NULL; + unsigned int client_key_len = 0; + krb5_checksum cksum = {0, 0, 0, NULL}; + krb5_data k5data; + krb5_data secret; + int valid_san = 0; + int valid_eku = 0; + int need_eku_checking = 1; + + assert((as_rep != NULL) && (key_block != NULL)); + +#ifdef DEBUG_ASN1 + print_buffer_bin((unsigned char *)as_rep->data, as_rep->length, + "/tmp/client_as_rep"); +#endif + + if ((retval = k5int_decode_krb5_pa_pk_as_rep(as_rep, &kdc_reply))) { + pkiDebug("decode_krb5_as_rep failed %d\n", retval); + return retval; + } + + switch(kdc_reply->choice) { + case choice_pa_pk_as_rep_dhInfo: + pkiDebug("as_rep: DH key transport algorithm\n"); +#ifdef DEBUG_ASN1 + print_buffer_bin(kdc_reply->u.dh_Info.dhSignedData.data, + kdc_reply->u.dh_Info.dhSignedData.length, "/tmp/client_kdc_signeddata"); +#endif + if ((retval = cms_signeddata_verify(context, plgctx->cryptoctx, + reqctx->cryptoctx, reqctx->idctx, CMS_SIGN_SERVER, + reqctx->opts->require_crl_checking, + (unsigned char *) + kdc_reply->u.dh_Info.dhSignedData.data, + kdc_reply->u.dh_Info.dhSignedData.length, + (unsigned char **)&dh_data.data, + &dh_data.length, + NULL, NULL, NULL)) != 0) { + pkiDebug("failed to verify pkcs7 signed data\n"); + TRACE_PKINIT_CLIENT_REP_DH_FAIL(context); + goto cleanup; + } + TRACE_PKINIT_CLIENT_REP_DH(context); + break; + case choice_pa_pk_as_rep_encKeyPack: + pkiDebug("as_rep: RSA key transport algorithm\n"); + if ((retval = cms_envelopeddata_verify(context, plgctx->cryptoctx, + reqctx->cryptoctx, reqctx->idctx, pa_type, + reqctx->opts->require_crl_checking, + (unsigned char *) + kdc_reply->u.encKeyPack.data, + kdc_reply->u.encKeyPack.length, + (unsigned char **)&dh_data.data, + &dh_data.length)) != 0) { + pkiDebug("failed to verify pkcs7 enveloped data\n"); + TRACE_PKINIT_CLIENT_REP_RSA_FAIL(context); + goto cleanup; + } + TRACE_PKINIT_CLIENT_REP_RSA(context); + break; + default: + pkiDebug("unknown as_rep type %d\n", kdc_reply->choice); + retval = -1; + goto cleanup; + } + retval = krb5_build_principal_ext(context, &kdc_princ, + request->server->realm.length, + request->server->realm.data, + strlen(KRB5_TGS_NAME), KRB5_TGS_NAME, + request->server->realm.length, + request->server->realm.data, + 0); + if (retval) + goto cleanup; + retval = verify_kdc_san(context, plgctx, reqctx, kdc_princ, + &valid_san, &need_eku_checking); + if (retval) + goto cleanup; + if (!valid_san) { + pkiDebug("%s: did not find an acceptable SAN in KDC certificate\n", + __FUNCTION__); + retval = KRB5KDC_ERR_KDC_NAME_MISMATCH; + goto cleanup; + } + + if (need_eku_checking) { + retval = verify_kdc_eku(context, plgctx, reqctx, + &valid_eku); + if (retval) + goto cleanup; + if (!valid_eku) { + pkiDebug("%s: did not find an acceptable EKU in KDC certificate\n", + __FUNCTION__); + retval = KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE; + goto cleanup; + } + } else + pkiDebug("%s: skipping EKU check\n", __FUNCTION__); + + OCTETDATA_TO_KRB5DATA(&dh_data, &k5data); + + switch(kdc_reply->choice) { + case choice_pa_pk_as_rep_dhInfo: +#ifdef DEBUG_ASN1 + print_buffer_bin(dh_data.data, dh_data.length, + "/tmp/client_dh_key"); +#endif + if ((retval = k5int_decode_krb5_kdc_dh_key_info(&k5data, + &kdc_dh)) != 0) { + pkiDebug("failed to decode kdc_dh_key_info\n"); + goto cleanup; + } + + /* client after KDC reply */ + if ((retval = client_process_dh(context, plgctx->cryptoctx, + reqctx->cryptoctx, reqctx->idctx, + (unsigned char *) + kdc_dh->subjectPublicKey.data, + kdc_dh->subjectPublicKey.length, + &client_key, &client_key_len)) != 0) { + pkiDebug("failed to process dh params\n"); + goto cleanup; + } + + /* If we have a KDF algorithm ID, call the algorithm agility KDF... */ + if (kdc_reply->u.dh_Info.kdfID) { + secret.length = client_key_len; + secret.data = (char *)client_key; + + retval = pkinit_alg_agility_kdf(context, &secret, + kdc_reply->u.dh_Info.kdfID, + request->client, request->server, + etype, encoded_request, + (krb5_data *)as_rep, key_block); + + if (retval) { + pkiDebug("failed to create key pkinit_alg_agility_kdf %s\n", + error_message(retval)); + goto cleanup; + } + TRACE_PKINIT_CLIENT_KDF_ALG(context, kdc_reply->u.dh_Info.kdfID, + key_block); + + /* ...otherwise, use the older octetstring2key function. */ + } else { + + retval = pkinit_octetstring2key(context, etype, client_key, + client_key_len, key_block); + if (retval) { + pkiDebug("failed to create key pkinit_octetstring2key %s\n", + error_message(retval)); + goto cleanup; + } + TRACE_PKINIT_CLIENT_KDF_OS2K(context, key_block); + } + + break; + case choice_pa_pk_as_rep_encKeyPack: +#ifdef DEBUG_ASN1 + print_buffer_bin(dh_data.data, dh_data.length, + "/tmp/client_key_pack"); +#endif + retval = k5int_decode_krb5_reply_key_pack(&k5data, &key_pack); + if (retval) { + pkiDebug("failed to decode reply_key_pack\n"); + goto cleanup; + } + retval = krb5_c_make_checksum(context, + key_pack->asChecksum.checksum_type, + &key_pack->replyKey, + KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, + encoded_request, &cksum); + if (retval) { + pkiDebug("failed to make a checksum\n"); + goto cleanup; + } + + if ((cksum.length != key_pack->asChecksum.length) || + k5_bcmp(cksum.contents, key_pack->asChecksum.contents, + cksum.length) != 0) { + TRACE_PKINIT_CLIENT_REP_CHECKSUM_FAIL(context, &cksum, + &key_pack->asChecksum); + pkiDebug("failed to match the checksums\n"); +#ifdef DEBUG_CKSUM + pkiDebug("calculating checksum on buf size (%d)\n", + encoded_request->length); + print_buffer(encoded_request->data, encoded_request->length); + pkiDebug("encrypting key (%d)\n", key_pack->replyKey.length); + print_buffer(key_pack->replyKey.contents, + key_pack->replyKey.length); + pkiDebug("received checksum type=%d size=%d ", + key_pack->asChecksum.checksum_type, + key_pack->asChecksum.length); + print_buffer(key_pack->asChecksum.contents, + key_pack->asChecksum.length); + pkiDebug("expected checksum type=%d size=%d ", + cksum.checksum_type, cksum.length); + print_buffer(cksum.contents, cksum.length); +#endif + goto cleanup; + } else + pkiDebug("checksums match\n"); + + krb5_copy_keyblock_contents(context, &key_pack->replyKey, + key_block); + TRACE_PKINIT_CLIENT_REP_RSA_KEY(context, key_block, &cksum); + + break; + default: + pkiDebug("unknown as_rep type %d\n", kdc_reply->choice); + goto cleanup; + } + + retval = 0; + +cleanup: + free(dh_data.data); + krb5_free_principal(context, kdc_princ); + free(client_key); + free_krb5_kdc_dh_key_info(&kdc_dh); + free_krb5_pa_pk_as_rep(&kdc_reply); + + if (key_pack != NULL) { + free_krb5_reply_key_pack(&key_pack); + free(cksum.contents); + } + + free(kdc_hostname); + + pkiDebug("pkinit_as_rep_parse returning %d (%s)\n", + retval, error_message(retval)); + return retval; +} + +static void +pkinit_client_profile(krb5_context context, + pkinit_context plgctx, + pkinit_req_context reqctx, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, + const krb5_data *realm) +{ + const char *configured_identity; + char *eku_string = NULL; + + pkiDebug("pkinit_client_profile %p %p %p %p\n", + context, plgctx, reqctx, realm); + + pkinit_libdefault_boolean(context, realm, + KRB5_CONF_PKINIT_REQUIRE_CRL_CHECKING, + reqctx->opts->require_crl_checking, + &reqctx->opts->require_crl_checking); + pkinit_libdefault_integer(context, realm, + KRB5_CONF_PKINIT_DH_MIN_BITS, + reqctx->opts->dh_size, + &reqctx->opts->dh_size); + if (reqctx->opts->dh_size != 1024 && reqctx->opts->dh_size != 2048 + && reqctx->opts->dh_size != 4096) { + pkiDebug("%s: invalid value (%d) for pkinit_dh_min_bits, " + "using default value (%d) instead\n", __FUNCTION__, + reqctx->opts->dh_size, PKINIT_DEFAULT_DH_MIN_BITS); + reqctx->opts->dh_size = PKINIT_DEFAULT_DH_MIN_BITS; + } + pkinit_libdefault_string(context, realm, + KRB5_CONF_PKINIT_EKU_CHECKING, + &eku_string); + if (eku_string != NULL) { + if (strcasecmp(eku_string, "kpKDC") == 0) { + reqctx->opts->require_eku = 1; + reqctx->opts->accept_secondary_eku = 0; + } else if (strcasecmp(eku_string, "kpServerAuth") == 0) { + reqctx->opts->require_eku = 1; + reqctx->opts->accept_secondary_eku = 1; + } else if (strcasecmp(eku_string, "none") == 0) { + reqctx->opts->require_eku = 0; + reqctx->opts->accept_secondary_eku = 0; + } else { + pkiDebug("%s: Invalid value for pkinit_eku_checking: '%s'\n", + __FUNCTION__, eku_string); + } + free(eku_string); + } + + /* Only process anchors here if they were not specified on command line */ + if (reqctx->idopts->anchors == NULL) + pkinit_libdefault_strings(context, realm, + KRB5_CONF_PKINIT_ANCHORS, + &reqctx->idopts->anchors); + pkinit_libdefault_strings(context, realm, + KRB5_CONF_PKINIT_POOL, + &reqctx->idopts->intermediates); + pkinit_libdefault_strings(context, realm, + KRB5_CONF_PKINIT_REVOKE, + &reqctx->idopts->crls); + pkinit_libdefault_strings(context, realm, + KRB5_CONF_PKINIT_IDENTITIES, + &reqctx->idopts->identity_alt); + reqctx->do_identity_matching = TRUE; + + /* If we had a primary identity in the stored configuration, pick it up. */ + configured_identity = cb->get_cc_config(context, rock, + "X509_user_identity"); + if (configured_identity != NULL) { + free(reqctx->idopts->identity); + reqctx->idopts->identity = strdup(configured_identity); + reqctx->do_identity_matching = FALSE; + } +} + +/* + * Convert a PKCS11 token flags value to the subset that we're interested in + * passing along to our API callers. + */ +static long long +pkinit_client_get_token_flags(unsigned long pkcs11_token_flags) +{ + long long flags = 0; + + if (pkcs11_token_flags & CKF_USER_PIN_COUNT_LOW) + flags |= KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW; + if (pkcs11_token_flags & CKF_USER_PIN_FINAL_TRY) + flags |= KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY; + if (pkcs11_token_flags & CKF_USER_PIN_LOCKED) + flags |= KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED; + return flags; +} + +/* + * Phase one of loading client identity information - call + * identity_initialize() to load any identities which we can without requiring + * help from the calling user, and use their names of those which we can't load + * to construct the challenge for the responder callback. + */ +static krb5_error_code +pkinit_client_prep_questions(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, + krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, + krb5_kdc_req *request, + krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, + krb5_pa_data *pa_data) +{ + krb5_error_code retval; + pkinit_context plgctx = (pkinit_context)moddata; + pkinit_req_context reqctx = (pkinit_req_context)modreq; + int i, n; + const pkinit_deferred_id *deferred_ids; + const char *identity; + unsigned long ck_flags; + char *encoded; + k5_json_object jval = NULL; + k5_json_number jflag = NULL; + + /* Don't ask questions for the informational padata items or when the + * ticket is issued. */ + if (pa_data->pa_type != KRB5_PADATA_PK_AS_REQ) + return 0; + + if (!reqctx->identity_initialized) { + pkinit_client_profile(context, plgctx, reqctx, cb, rock, + &request->server->realm); + retval = pkinit_identity_initialize(context, plgctx->cryptoctx, + reqctx->cryptoctx, reqctx->idopts, + reqctx->idctx, cb, rock, + request->client); + if (retval != 0) { + TRACE_PKINIT_CLIENT_NO_IDENTITY(context); + pkiDebug("pkinit_identity_initialize returned %d (%s)\n", + retval, error_message(retval)); + } + + reqctx->identity_initialized = TRUE; + if (retval != 0) { + pkiDebug("%s: not asking responder question\n", __FUNCTION__); + retval = 0; + goto cleanup; + } + } + + deferred_ids = crypto_get_deferred_ids(context, reqctx->idctx); + for (i = 0; deferred_ids != NULL && deferred_ids[i] != NULL; i++) + continue; + n = i; + + /* Make sure we don't just return an empty challenge. */ + if (n == 0) { + pkiDebug("%s: no questions to ask\n", __FUNCTION__); + retval = 0; + goto cleanup; + } + + /* Create the top-level object. */ + retval = k5_json_object_create(&jval); + if (retval != 0) + goto cleanup; + + for (i = 0; i < n; i++) { + /* Add an entry to the top-level object for the identity. */ + identity = deferred_ids[i]->identity; + ck_flags = deferred_ids[i]->ck_flags; + /* Calculate the flags value for the bits that that we care about. */ + retval = k5_json_number_create(pkinit_client_get_token_flags(ck_flags), + &jflag); + if (retval != 0) + goto cleanup; + retval = k5_json_object_set(jval, identity, jflag); + if (retval != 0) + goto cleanup; + k5_json_release(jflag); + jflag = NULL; + } + + /* Encode and done. */ + retval = k5_json_encode(jval, &encoded); + if (retval == 0) { + cb->ask_responder_question(context, rock, + KRB5_RESPONDER_QUESTION_PKINIT, + encoded); + pkiDebug("%s: asking question '%s'\n", __FUNCTION__, encoded); + free(encoded); + } + +cleanup: + k5_json_release(jval); + k5_json_release(jflag); + + pkiDebug("%s returning %d\n", __FUNCTION__, retval); + + return retval; +} + +/* + * Parse data supplied by the application's responder callback, saving off any + * PINs and passwords for identities which we noted needed them. + */ +struct save_one_password_data { + krb5_context context; + krb5_clpreauth_modreq modreq; + const char *caller; +}; + +static void +save_one_password(void *arg, const char *key, k5_json_value val) +{ + struct save_one_password_data *data = arg; + pkinit_req_context reqctx = (pkinit_req_context)data->modreq; + const char *password; + + if (k5_json_get_tid(val) == K5_JSON_TID_STRING) { + password = k5_json_string_utf8(val); + pkiDebug("%s: \"%s\": %p\n", data->caller, key, password); + crypto_set_deferred_id(data->context, reqctx->idctx, key, password); + } +} + +static krb5_error_code +pkinit_client_parse_answers(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock) +{ + krb5_error_code retval; + const char *encoded; + k5_json_value jval; + struct save_one_password_data data; + + data.context = context; + data.modreq = modreq; + data.caller = __FUNCTION__; + + encoded = cb->get_responder_answer(context, rock, + KRB5_RESPONDER_QUESTION_PKINIT); + if (encoded == NULL) + return 0; + + pkiDebug("pkinit_client_parse_answers: %s\n", encoded); + + retval = k5_json_decode(encoded, &jval); + if (retval != 0) + goto cleanup; + + /* Expect that the top-level answer is an object. */ + if (k5_json_get_tid(jval) != K5_JSON_TID_OBJECT) { + retval = EINVAL; + goto cleanup; + } + + /* Store the passed-in per-identity passwords. */ + k5_json_object_iterate(jval, &save_one_password, &data); + retval = 0; + +cleanup: + if (jval != NULL) + k5_json_release(jval); + return retval; +} + +static krb5_error_code +pkinit_client_process(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, + krb5_get_init_creds_opt *gic_opt, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_kdc_req *request, krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, + krb5_pa_data *in_padata, + krb5_prompter_fct prompter, void *prompter_data, + krb5_pa_data ***out_padata) +{ + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + krb5_enctype enctype = -1; + int processing_request = 0; + pkinit_context plgctx = (pkinit_context)moddata; + pkinit_req_context reqctx = (pkinit_req_context)modreq; + krb5_keyblock as_key; + krb5_data d; + + pkiDebug("pkinit_client_process %p %p %p %p\n", + context, plgctx, reqctx, request); + + + if (plgctx == NULL || reqctx == NULL) + return EINVAL; + + switch ((int) in_padata->pa_type) { + case KRB5_PADATA_PKINIT_KX: + reqctx->rfc6112_kdc = 1; + return 0; + case KRB5_PADATA_AS_FRESHNESS: + TRACE_PKINIT_CLIENT_FRESHNESS_TOKEN(context); + krb5_free_data(context, reqctx->freshness_token); + reqctx->freshness_token = NULL; + d = make_data(in_padata->contents, in_padata->length); + return krb5_copy_data(context, &d, &reqctx->freshness_token); + case KRB5_PADATA_PK_AS_REQ: + pkiDebug("processing KRB5_PADATA_PK_AS_REQ\n"); + processing_request = 1; + break; + + case KRB5_PADATA_PK_AS_REP: + pkiDebug("processing KRB5_PADATA_PK_AS_REP\n"); + break; + default: + pkiDebug("unrecognized patype = %d for PKINIT\n", + in_padata->pa_type); + return EINVAL; + } + + if (processing_request) { + if (reqctx->idopts->anchors == NULL) { + krb5_set_error_message(context, KRB5_PREAUTH_FAILED, + _("No pkinit_anchors supplied")); + return KRB5_PREAUTH_FAILED; + } + /* Pull in PINs and passwords for identities which we deferred + * loading earlier. */ + retval = pkinit_client_parse_answers(context, moddata, modreq, + cb, rock); + if (retval) { + if (retval == KRB5KRB_ERR_GENERIC) + pkiDebug("pkinit responder answers were invalid\n"); + return retval; + } + if (!reqctx->identity_prompted) { + reqctx->identity_prompted = TRUE; + /* + * Load identities (again, potentially), prompting, if we can, for + * anything for which we didn't get an answer from the responder + * callback. + */ + pkinit_identity_set_prompter(reqctx->idctx, prompter, + prompter_data); + retval = pkinit_identity_prompt(context, plgctx->cryptoctx, + reqctx->cryptoctx, reqctx->idopts, + reqctx->idctx, cb, rock, + reqctx->do_identity_matching, + request->client); + pkinit_identity_set_prompter(reqctx->idctx, NULL, NULL); + reqctx->identity_prompt_retval = retval; + if (retval) { + TRACE_PKINIT_CLIENT_NO_IDENTITY(context); + pkiDebug("pkinit_identity_prompt returned %d (%s)\n", + retval, error_message(retval)); + return retval; + } + } else if (reqctx->identity_prompt_retval) { + retval = reqctx->identity_prompt_retval; + TRACE_PKINIT_CLIENT_NO_IDENTITY(context); + pkiDebug("pkinit_identity_prompt previously returned %d (%s)\n", + retval, error_message(retval)); + return retval; + } + retval = pa_pkinit_gen_req(context, plgctx, reqctx, cb, rock, request, + in_padata->pa_type, out_padata, prompter, + prompter_data, gic_opt); + } else { + /* + * Get the enctype of the reply. + */ + enctype = cb->get_etype(context, rock); + retval = pa_pkinit_parse_rep(context, plgctx, reqctx, request, + in_padata, enctype, &as_key, + encoded_previous_request); + if (retval == 0) { + retval = cb->set_as_key(context, rock, &as_key); + krb5_free_keyblock_contents(context, &as_key); + } + } + + pkiDebug("pkinit_client_process: returning %d (%s)\n", + retval, error_message(retval)); + return retval; +} + +static krb5_error_code +pkinit_client_tryagain(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, + krb5_get_init_creds_opt *gic_opt, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_kdc_req *request, krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, + krb5_preauthtype pa_type, krb5_error *err_reply, + krb5_pa_data **err_padata, krb5_prompter_fct prompter, + void *prompter_data, krb5_pa_data ***out_padata) +{ + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + pkinit_context plgctx = (pkinit_context)moddata; + pkinit_req_context reqctx = (pkinit_req_context)modreq; + krb5_pa_data *pa; + krb5_data scratch; + krb5_external_principal_identifier **certifiers = NULL; + krb5_algorithm_identifier **algId = NULL; + int do_again = 0; + + pkiDebug("pkinit_client_tryagain %p %p %p %p\n", + context, plgctx, reqctx, request); + + if (reqctx->pa_type != pa_type || err_padata == NULL) + return retval; + + for (; *err_padata != NULL && !do_again; err_padata++) { + pa = *err_padata; + PADATA_TO_KRB5DATA(pa, &scratch); + switch (pa->pa_type) { + case TD_TRUSTED_CERTIFIERS: + case TD_INVALID_CERTIFICATES: + retval = k5int_decode_krb5_td_trusted_certifiers(&scratch, + &certifiers); + if (retval) { + pkiDebug("failed to decode sequence of trusted certifiers\n"); + goto cleanup; + } + retval = pkinit_process_td_trusted_certifiers(context, + plgctx->cryptoctx, + reqctx->cryptoctx, + reqctx->idctx, + certifiers, + pa->pa_type); + if (!retval) + do_again = 1; + break; + case TD_DH_PARAMETERS: + retval = k5int_decode_krb5_td_dh_parameters(&scratch, &algId); + if (retval) { + pkiDebug("failed to decode td_dh_parameters\n"); + goto cleanup; + } + retval = pkinit_process_td_dh_params(context, plgctx->cryptoctx, + reqctx->cryptoctx, + reqctx->idctx, algId, + &reqctx->opts->dh_size); + if (!retval) + do_again = 1; + break; + default: + break; + } + } + + if (do_again) { + TRACE_PKINIT_CLIENT_TRYAGAIN(context); + retval = pa_pkinit_gen_req(context, plgctx, reqctx, cb, rock, request, + pa_type, out_padata, prompter, + prompter_data, gic_opt); + if (retval) + goto cleanup; + } + + retval = 0; +cleanup: + if (certifiers != NULL) + free_krb5_external_principal_identifier(&certifiers); + + if (algId != NULL) + free_krb5_algorithm_identifiers(&algId); + + pkiDebug("pkinit_client_tryagain: returning %d (%s)\n", + retval, error_message(retval)); + return retval; +} + +static int +pkinit_client_get_flags(krb5_context kcontext, krb5_preauthtype patype) +{ + if (patype == KRB5_PADATA_PKINIT_KX || patype == KRB5_PADATA_AS_FRESHNESS) + return PA_INFO; + return PA_REAL; +} + +/* + * We want to be notified about KRB5_PADATA_PKINIT_KX in addition to the actual + * pkinit patypes because RFC 6112 requires anonymous KDCs to send it. We use + * that to determine whether to use the broken MIT 1.9 behavior of sending + * ContentInfo rather than SignedData or the RFC 6112 behavior + */ +static krb5_preauthtype supported_client_pa_types[] = { + KRB5_PADATA_PK_AS_REP, + KRB5_PADATA_PK_AS_REQ, + KRB5_PADATA_PKINIT_KX, + KRB5_PADATA_AS_FRESHNESS, + 0 +}; + +static void +pkinit_client_req_init(krb5_context context, + krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq *modreq_out) +{ + krb5_error_code retval = ENOMEM; + pkinit_req_context reqctx = NULL; + pkinit_context plgctx = (pkinit_context)moddata; + + *modreq_out = NULL; + + reqctx = malloc(sizeof(*reqctx)); + if (reqctx == NULL) + return; + memset(reqctx, 0, sizeof(*reqctx)); + + reqctx->magic = PKINIT_REQ_CTX_MAGIC; + reqctx->cryptoctx = NULL; + reqctx->opts = NULL; + reqctx->idctx = NULL; + reqctx->idopts = NULL; + reqctx->freshness_token = NULL; + + retval = pkinit_init_req_opts(&reqctx->opts); + if (retval) + goto cleanup; + + reqctx->opts->require_eku = plgctx->opts->require_eku; + reqctx->opts->accept_secondary_eku = plgctx->opts->accept_secondary_eku; + reqctx->opts->dh_or_rsa = plgctx->opts->dh_or_rsa; + reqctx->opts->allow_upn = plgctx->opts->allow_upn; + reqctx->opts->require_crl_checking = plgctx->opts->require_crl_checking; + reqctx->opts->disable_freshness = plgctx->opts->disable_freshness; + + retval = pkinit_init_req_crypto(&reqctx->cryptoctx); + if (retval) + goto cleanup; + + retval = pkinit_init_identity_crypto(&reqctx->idctx); + if (retval) + goto cleanup; + + retval = pkinit_dup_identity_opts(plgctx->idopts, &reqctx->idopts); + if (retval) + goto cleanup; + + *modreq_out = (krb5_clpreauth_modreq)reqctx; + pkiDebug("%s: returning reqctx at %p\n", __FUNCTION__, reqctx); + +cleanup: + if (retval) { + if (reqctx->idctx != NULL) + pkinit_fini_identity_crypto(reqctx->idctx); + if (reqctx->cryptoctx != NULL) + pkinit_fini_req_crypto(reqctx->cryptoctx); + if (reqctx->opts != NULL) + pkinit_fini_req_opts(reqctx->opts); + if (reqctx->idopts != NULL) + pkinit_fini_identity_opts(reqctx->idopts); + free(reqctx); + } + + return; +} + +static void +pkinit_client_req_fini(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq) +{ + pkinit_req_context reqctx = (pkinit_req_context)modreq; + + pkiDebug("%s: received reqctx at %p\n", __FUNCTION__, reqctx); + if (reqctx == NULL) + return; + if (reqctx->magic != PKINIT_REQ_CTX_MAGIC) { + pkiDebug("%s: Bad magic value (%x) in req ctx\n", + __FUNCTION__, reqctx->magic); + return; + } + if (reqctx->opts != NULL) + pkinit_fini_req_opts(reqctx->opts); + + if (reqctx->cryptoctx != NULL) + pkinit_fini_req_crypto(reqctx->cryptoctx); + + if (reqctx->idctx != NULL) + pkinit_fini_identity_crypto(reqctx->idctx); + + if (reqctx->idopts != NULL) + pkinit_fini_identity_opts(reqctx->idopts); + + krb5_free_data(context, reqctx->freshness_token); + + free(reqctx); + return; +} + +static int +pkinit_client_plugin_init(krb5_context context, + krb5_clpreauth_moddata *moddata_out) +{ + krb5_error_code retval = ENOMEM; + pkinit_context ctx = NULL; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) + return ENOMEM; + memset(ctx, 0, sizeof(*ctx)); + ctx->magic = PKINIT_CTX_MAGIC; + ctx->opts = NULL; + ctx->cryptoctx = NULL; + ctx->idopts = NULL; + + retval = pkinit_accessor_init(); + if (retval) + goto errout; + + retval = pkinit_init_plg_opts(&ctx->opts); + if (retval) + goto errout; + + retval = pkinit_init_plg_crypto(&ctx->cryptoctx); + if (retval) + goto errout; + + retval = pkinit_init_identity_opts(&ctx->idopts); + if (retval) + goto errout; + + *moddata_out = (krb5_clpreauth_moddata)ctx; + + pkiDebug("%s: returning plgctx at %p\n", __FUNCTION__, ctx); + +errout: + if (retval) + pkinit_client_plugin_fini(context, (krb5_clpreauth_moddata)ctx); + + return retval; +} + +static void +pkinit_client_plugin_fini(krb5_context context, krb5_clpreauth_moddata moddata) +{ + pkinit_context ctx = (pkinit_context)moddata; + + if (ctx == NULL || ctx->magic != PKINIT_CTX_MAGIC) { + pkiDebug("pkinit_lib_fini: got bad plgctx (%p)!\n", ctx); + return; + } + pkiDebug("%s: got plgctx at %p\n", __FUNCTION__, ctx); + + pkinit_fini_identity_opts(ctx->idopts); + pkinit_fini_plg_crypto(ctx->cryptoctx); + pkinit_fini_plg_opts(ctx->opts); + free(ctx); + +} + +static krb5_error_code +add_string_to_array(krb5_context context, char ***array, const char *addition) +{ + char **a = *array; + size_t len; + + for (len = 0; a != NULL && a[len] != NULL; len++); + a = realloc(a, (len + 2) * sizeof(char *)); + if (a == NULL) + return ENOMEM; + *array = a; + a[len] = strdup(addition); + if (a[len] == NULL) + return ENOMEM; + a[len + 1] = NULL; + return 0; +} + +static krb5_error_code +handle_gic_opt(krb5_context context, + pkinit_context plgctx, + const char *attr, + const char *value) +{ + krb5_error_code retval; + + if (strcmp(attr, "X509_user_identity") == 0) { + if (plgctx->idopts->identity != NULL) { + krb5_set_error_message(context, KRB5_PREAUTH_FAILED, + "X509_user_identity can not be given twice\n"); + return KRB5_PREAUTH_FAILED; + } + plgctx->idopts->identity = strdup(value); + if (plgctx->idopts->identity == NULL) { + krb5_set_error_message(context, ENOMEM, + "Could not duplicate X509_user_identity value\n"); + return ENOMEM; + } + } else if (strcmp(attr, "X509_anchors") == 0) { + retval = add_string_to_array(context, &plgctx->idopts->anchors, value); + if (retval) + return retval; + } else if (strcmp(attr, "flag_RSA_PROTOCOL") == 0) { + if (strcmp(value, "yes") == 0) { + pkiDebug("Setting flag to use RSA_PROTOCOL\n"); + plgctx->opts->dh_or_rsa = RSA_PROTOCOL; + } + } else if (strcmp(attr, "disable_freshness") == 0) { + if (strcmp(value, "yes") == 0) + plgctx->opts->disable_freshness = 1; + } + return 0; +} + +static krb5_error_code +pkinit_client_gic_opt(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_get_init_creds_opt *gic_opt, + const char *attr, + const char *value) +{ + krb5_error_code retval; + pkinit_context plgctx = (pkinit_context)moddata; + + pkiDebug("(pkinit) received '%s' = '%s'\n", attr, value); + retval = handle_gic_opt(context, plgctx, attr, value); + if (retval) + return retval; + + return 0; +} + +krb5_error_code +clpreauth_pkinit_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +clpreauth_pkinit_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_clpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_clpreauth_vtable)vtable; + vt->name = "pkinit"; + vt->pa_type_list = supported_client_pa_types; + vt->init = pkinit_client_plugin_init; + vt->fini = pkinit_client_plugin_fini; + vt->flags = pkinit_client_get_flags; + vt->request_init = pkinit_client_req_init; + vt->prep_questions = pkinit_client_prep_questions; + vt->request_fini = pkinit_client_req_fini; + vt->process = pkinit_client_process; + vt->tryagain = pkinit_client_tryagain; + vt->gic_opts = pkinit_client_gic_opt; + return 0; +} diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_constants.c b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_constants.c new file mode 100644 index 00000000..1da482e0 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_constants.c @@ -0,0 +1,325 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/pkinit/pkinit_constants.c */ +/* + * Copyright (C) 2011,2021 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. + */ + +#include "pkinit.h" + +/* RFC 8636 id-pkinit-kdf-ah-sha1: iso(1) identified-organization(3) dod(6) + * internet(1) security(5) kerberosv5(2) pkinit(3) kdf(6) sha1(1) */ +static char sha1_oid[8] = { 0x2B, 0x06, 0x01, 0x05, 0x02, 0x03, 0x06, 0x01 }; +/* RFC 8636 id-pkinit-kdf-ah-sha256: iso(1) identified-organization(3) dod(6) + * internet(1) security(5) kerberosv5(2) pkinit(3) kdf(6) sha256(2) */ +static char sha256_oid[8] = { 0x2B, 0x06, 0x01, 0x05, 0x02, 0x03, 0x06, 0x02 }; +/* RFC 8636 id-pkinit-kdf-ah-sha512: iso(1) identified-organization(3) dod(6) + * internet(1) security(5) kerberosv5(2) pkinit(3) kdf(6) sha512(3) */ +static char sha512_oid[8] = { 0x2B, 0x06, 0x01, 0x05, 0x02, 0x03, 0x06, 0x03 }; + +const krb5_data sha1_id = { KV5M_DATA, sizeof(sha1_oid), sha1_oid }; +const krb5_data sha256_id = { KV5M_DATA, sizeof(sha256_oid), sha256_oid }; +const krb5_data sha512_id = { KV5M_DATA, sizeof(sha512_oid), sha512_oid }; + +krb5_data const * const supported_kdf_alg_ids[] = { + &sha256_id, + &sha1_id, + &sha512_id, + NULL +}; + +/* RFC 4055 sha256WithRSAEncryption: iso(1) member-body(2) us(840) + * rsadsi(113549) pkcs(1) 1 11 */ +static char sha256WithRSAEncr_oid[9] = { + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b +}; +/* RFC 4055 sha256WithRSAEncryption: iso(1) member-body(2) us(840) + * rsadsi(113549) pkcs(1) 1 13 */ +static char sha512WithRSAEncr_oid[9] = { + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d +}; + +const krb5_data sha256WithRSAEncr_id = { + KV5M_DATA, sizeof(sha256WithRSAEncr_oid), sha256WithRSAEncr_oid +}; +const krb5_data sha512WithRSAEncr_id = { + KV5M_DATA, sizeof(sha512WithRSAEncr_oid), sha512WithRSAEncr_oid +}; + +krb5_data const * const supported_cms_algs[] = { + &sha512WithRSAEncr_id, + &sha256WithRSAEncr_id, + NULL +}; + +/* RFC 2412 section E.2 (well-known group 2) parameters, DER-encoded as + * DomainParameters (RFC 3279 section 2.3.3). */ +static const uint8_t o1024[] = { + 0x30, 0x82, 0x01, 0x0A, 0x02, 0x81, 0x81, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x02, 0x01, 0x02, 0x02, 0x81, 0x80, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE4, 0x87, + 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, 0x62, 0x63, + 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, 0x94, 0x81, + 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, 0x01, 0x05, + 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, 0x28, 0xA5, + 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, 0xF7, 0xCA, + 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, 0x98, 0x15, + 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, 0xA7, 0xF0, + 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, 0xF2, 0x42, + 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, 0x7A, 0x26, + 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, 0x85, 0xFF, + 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, 0xF7, 0x1C, + 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, 0xD7, 0x4F, + 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, 0x24, 0x94, + 0x33, 0x28, 0xF6, 0x73, 0x29, 0xC0, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* RFC 3526 section 3 (2048-bit MODP Group), RFC 3279 encoding */ +static const uint8_t o2048[] = { + 0x30, 0x82, 0x02, 0x0C, 0x02, 0x82, 0x01, 0x01, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, + 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, + 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, + 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, + 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, + 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, + 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, + 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, + 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, + 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, + 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, + 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, + 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, + 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, + 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, + 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, + 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, + 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, + 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, + 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, + 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, + 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, + 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, + 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, + 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, + 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, + 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, + 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, + 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, + 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, + 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x02, 0x01, 0x02, 0x02, 0x82, 0x01, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE, + 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D, + 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01, + 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47, + 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, + 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, + 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72, + 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88, + 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x56, 0x55, 0x34, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +/* RFC 3526 section 5 (4096-bit MODP Group), RFC 3279 encoding */ +static const uint8_t o4096[] = { + 0x30, 0x82, 0x04, 0x0C, 0x02, 0x82, 0x02, 0x01, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, + 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, + 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, + 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, + 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, + 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, + 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, + 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, + 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, + 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, + 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, + 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, + 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, + 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, + 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, + 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, + 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, + 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, + 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, + 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, + 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, + 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, + 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, + 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, + 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, + 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, + 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, + 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, + 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, + 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, + 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, + 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, + 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, + 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, + 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, + 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, + 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, + 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, + 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, + 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, + 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, + 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, + 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, + 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, + 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, + 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, + 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, + 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, + 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, + 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, + 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, + 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, + 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, + 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, + 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, + 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, + 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, + 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, + 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, + 0xA9, 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, + 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, + 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, + 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x02, 0x01, 0x02, 0x02, 0x82, 0x02, 0x00, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xE4, 0x87, 0xED, 0x51, 0x10, 0xB4, 0x61, 0x1A, + 0x62, 0x63, 0x31, 0x45, 0xC0, 0x6E, 0x0E, 0x68, + 0x94, 0x81, 0x27, 0x04, 0x45, 0x33, 0xE6, 0x3A, + 0x01, 0x05, 0xDF, 0x53, 0x1D, 0x89, 0xCD, 0x91, + 0x28, 0xA5, 0x04, 0x3C, 0xC7, 0x1A, 0x02, 0x6E, + 0xF7, 0xCA, 0x8C, 0xD9, 0xE6, 0x9D, 0x21, 0x8D, + 0x98, 0x15, 0x85, 0x36, 0xF9, 0x2F, 0x8A, 0x1B, + 0xA7, 0xF0, 0x9A, 0xB6, 0xB6, 0xA8, 0xE1, 0x22, + 0xF2, 0x42, 0xDA, 0xBB, 0x31, 0x2F, 0x3F, 0x63, + 0x7A, 0x26, 0x21, 0x74, 0xD3, 0x1B, 0xF6, 0xB5, + 0x85, 0xFF, 0xAE, 0x5B, 0x7A, 0x03, 0x5B, 0xF6, + 0xF7, 0x1C, 0x35, 0xFD, 0xAD, 0x44, 0xCF, 0xD2, + 0xD7, 0x4F, 0x92, 0x08, 0xBE, 0x25, 0x8F, 0xF3, + 0x24, 0x94, 0x33, 0x28, 0xF6, 0x72, 0x2D, 0x9E, + 0xE1, 0x00, 0x3E, 0x5C, 0x50, 0xB1, 0xDF, 0x82, + 0xCC, 0x6D, 0x24, 0x1B, 0x0E, 0x2A, 0xE9, 0xCD, + 0x34, 0x8B, 0x1F, 0xD4, 0x7E, 0x92, 0x67, 0xAF, + 0xC1, 0xB2, 0xAE, 0x91, 0xEE, 0x51, 0xD6, 0xCB, + 0x0E, 0x31, 0x79, 0xAB, 0x10, 0x42, 0xA9, 0x5D, + 0xCF, 0x6A, 0x94, 0x83, 0xB8, 0x4B, 0x4B, 0x36, + 0xB3, 0x86, 0x1A, 0xA7, 0x25, 0x5E, 0x4C, 0x02, + 0x78, 0xBA, 0x36, 0x04, 0x65, 0x0C, 0x10, 0xBE, + 0x19, 0x48, 0x2F, 0x23, 0x17, 0x1B, 0x67, 0x1D, + 0xF1, 0xCF, 0x3B, 0x96, 0x0C, 0x07, 0x43, 0x01, + 0xCD, 0x93, 0xC1, 0xD1, 0x76, 0x03, 0xD1, 0x47, + 0xDA, 0xE2, 0xAE, 0xF8, 0x37, 0xA6, 0x29, 0x64, + 0xEF, 0x15, 0xE5, 0xFB, 0x4A, 0xAC, 0x0B, 0x8C, + 0x1C, 0xCA, 0xA4, 0xBE, 0x75, 0x4A, 0xB5, 0x72, + 0x8A, 0xE9, 0x13, 0x0C, 0x4C, 0x7D, 0x02, 0x88, + 0x0A, 0xB9, 0x47, 0x2D, 0x45, 0x55, 0x62, 0x16, + 0xD6, 0x99, 0x8B, 0x86, 0x82, 0x28, 0x3D, 0x19, + 0xD4, 0x2A, 0x90, 0xD5, 0xEF, 0x8E, 0x5D, 0x32, + 0x76, 0x7D, 0xC2, 0x82, 0x2C, 0x6D, 0xF7, 0x85, + 0x45, 0x75, 0x38, 0xAB, 0xAE, 0x83, 0x06, 0x3E, + 0xD9, 0xCB, 0x87, 0xC2, 0xD3, 0x70, 0xF2, 0x63, + 0xD5, 0xFA, 0xD7, 0x46, 0x6D, 0x84, 0x99, 0xEB, + 0x8F, 0x46, 0x4A, 0x70, 0x25, 0x12, 0xB0, 0xCE, + 0xE7, 0x71, 0xE9, 0x13, 0x0D, 0x69, 0x77, 0x35, + 0xF8, 0x97, 0xFD, 0x03, 0x6C, 0xC5, 0x04, 0x32, + 0x6C, 0x3B, 0x01, 0x39, 0x9F, 0x64, 0x35, 0x32, + 0x29, 0x0F, 0x95, 0x8C, 0x0B, 0xBD, 0x90, 0x06, + 0x5D, 0xF0, 0x8B, 0xAB, 0xBD, 0x30, 0xAE, 0xB6, + 0x3B, 0x84, 0xC4, 0x60, 0x5D, 0x6C, 0xA3, 0x71, + 0x04, 0x71, 0x27, 0xD0, 0x3A, 0x72, 0xD5, 0x98, + 0xA1, 0xED, 0xAD, 0xFE, 0x70, 0x7E, 0x88, 0x47, + 0x25, 0xC1, 0x68, 0x90, 0x54, 0x90, 0x84, 0x00, + 0x8D, 0x39, 0x1E, 0x09, 0x53, 0xC3, 0xF3, 0x6B, + 0xC4, 0x38, 0xCD, 0x08, 0x5E, 0xDD, 0x2D, 0x93, + 0x4C, 0xE1, 0x93, 0x8C, 0x35, 0x7A, 0x71, 0x1E, + 0x0D, 0x4A, 0x34, 0x1A, 0x5B, 0x0A, 0x85, 0xED, + 0x12, 0xC1, 0xF4, 0xE5, 0x15, 0x6A, 0x26, 0x74, + 0x6D, 0xDD, 0xE1, 0x6D, 0x82, 0x6F, 0x47, 0x7C, + 0x97, 0x47, 0x7E, 0x0A, 0x0F, 0xDF, 0x65, 0x53, + 0x14, 0x3E, 0x2C, 0xA3, 0xA7, 0x35, 0xE0, 0x2E, + 0xCC, 0xD9, 0x4B, 0x27, 0xD0, 0x48, 0x61, 0xD1, + 0x11, 0x9D, 0xD0, 0xC3, 0x28, 0xAD, 0xF3, 0xF6, + 0x8F, 0xB0, 0x94, 0xB8, 0x67, 0x71, 0x6B, 0xD7, + 0xDC, 0x0D, 0xEE, 0xBB, 0x10, 0xB8, 0x24, 0x0E, + 0x68, 0x03, 0x48, 0x93, 0xEA, 0xD8, 0x2D, 0x54, + 0xC9, 0xDA, 0x75, 0x4C, 0x46, 0xC7, 0xEE, 0xE0, + 0xC3, 0x7F, 0xDB, 0xEE, 0x48, 0x53, 0x60, 0x47, + 0xA6, 0xFA, 0x1A, 0xE4, 0x9A, 0x03, 0x18, 0xCC, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +const krb5_data oakley_1024 = { KV5M_DATA, sizeof(o1024), (char *)o1024 }; +const krb5_data oakley_2048 = { KV5M_DATA, sizeof(o2048), (char *)o2048 }; +const krb5_data oakley_4096 = { KV5M_DATA, sizeof(o4096), (char *)o4096 }; diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_crypto.h b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_crypto.h new file mode 100644 index 00000000..e22798f6 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_crypto.h @@ -0,0 +1,631 @@ +/* + * COPYRIGHT (C) 2007 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +/* + * This header defines the cryptographic interface + */ + +#ifndef _PKINIT_CRYPTO_H +#define _PKINIT_CRYPTO_H + +#include +#include +#include +#include +#include "pkinit_accessor.h" + +/* + * these describe the CMS message types + */ +enum cms_msg_types { + CMS_SIGN_CLIENT, + CMS_SIGN_SERVER, + CMS_ENVEL_SERVER +}; + +/* + * storage types for identity information + */ +#define IDTYPE_FILE 1 +#define IDTYPE_DIR 2 +#define IDTYPE_PKCS11 3 +#define IDTYPE_ENVVAR 4 +#define IDTYPE_PKCS12 5 + +/* + * ca/crl types + */ +#define CATYPE_ANCHORS 1 +#define CATYPE_INTERMEDIATES 2 +#define CATYPE_CRLS 3 + +/* + * The following represent Key Usage values that we + * may care about in a certificate + */ +#define PKINIT_KU_DIGITALSIGNATURE 0x80000000 +#define PKINIT_KU_KEYENCIPHERMENT 0x40000000 + +/* + * The following represent Extended Key Usage oid values + * that we may care about in a certificate + */ +#define PKINIT_EKU_PKINIT 0x80000000 +#define PKINIT_EKU_MSSCLOGIN 0x40000000 +#define PKINIT_EKU_CLIENTAUTH 0x20000000 +#define PKINIT_EKU_EMAILPROTECTION 0x10000000 + + +/* Handle to cert, opaque above crypto interface */ +typedef struct _pkinit_cert_info *pkinit_cert_handle; + +/* Handle to cert iteration information, opaque above crypto interface */ +typedef struct _pkinit_cert_iter_info *pkinit_cert_iter_handle; + +#define PKINIT_ITER_NO_MORE 0x11111111 /* XXX */ + +typedef struct _pkinit_cert_matching_data { + char *subject_dn; /* rfc2253-style subject name string */ + char *issuer_dn; /* rfc2253-style issuer name string */ + unsigned int ku_bits; /* key usage information */ + unsigned int eku_bits; /* extended key usage information */ + krb5_principal *sans; /* Null-terminated array of PKINIT SANs */ + char **upns; /* Null-terimnated array of UPN SANs */ +} pkinit_cert_matching_data; + +/* + * Functions to initialize and cleanup crypto contexts + */ +krb5_error_code pkinit_init_plg_crypto(pkinit_plg_crypto_context *); +void pkinit_fini_plg_crypto(pkinit_plg_crypto_context); + +krb5_error_code pkinit_init_req_crypto(pkinit_req_crypto_context *); +void pkinit_fini_req_crypto(pkinit_req_crypto_context); + +krb5_error_code pkinit_init_identity_crypto(pkinit_identity_crypto_context *); +void pkinit_fini_identity_crypto(pkinit_identity_crypto_context); +/**Create a pkinit ContentInfo*/ +krb5_error_code cms_contentinfo_create + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + int cms_msg_type, + unsigned char *in_data, unsigned int in_length, + unsigned char **out_data, unsigned int *out_data_len); + +/* + * this function creates a CMS message where eContentType is SignedData + */ +krb5_error_code cms_signeddata_create + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + int cms_msg_type, /* IN + specifies CMS_SIGN_CLIENT for client-side CMS message + and CMS_SIGN_SERVER for kdc-side */ + unsigned char *auth_pack, /* IN + contains DER encoded AuthPack (CMS_SIGN_CLIENT) + or DER encoded DHRepInfo (CMS_SIGN_SERVER) */ + unsigned int auth_pack_len, /* IN + contains length of auth_pack */ + unsigned char **signed_data, /* OUT + for CMS_SIGN_CLIENT receives DER encoded + SignedAuthPack (CMS_SIGN_CLIENT) or DER + encoded DHInfo (CMS_SIGN_SERVER) */ + unsigned int *signed_data_len); /* OUT + receives length of signed_data */ + +/* + * this function verifies a CMS message where eContentType is SignedData + */ +krb5_error_code cms_signeddata_verify + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + int cms_msg_type, /* IN + specifies CMS_SIGN_CLIENT for client-side + CMS message and CMS_SIGN_SERVER for kdc-side */ + int require_crl_checking, /* IN + specifies whether CRL checking should be + strictly enforced, i.e. if no CRLs available + for the CA then fail verification. + note, if the value is 0, crls are still + checked if present */ + unsigned char *signed_data, /* IN + contains DER encoded SignedAuthPack (CMS_SIGN_CLIENT) + or DER encoded DHInfo (CMS_SIGN_SERVER) */ + unsigned int signed_data_len, /* IN + contains length of signed_data*/ + unsigned char **auth_pack, /* OUT + receives DER encoded AuthPack (CMS_SIGN_CLIENT) + or DER encoded DHRepInfo (CMS_SIGN_SERVER)*/ + unsigned int *auth_pack_len, /* OUT + receives length of auth_pack */ + unsigned char **authz_data, /* OUT + receives required authorization data that + contains the verified certificate chain + (only used by the KDC) */ + unsigned int *authz_data_len, /* OUT + receives length of authz_data */ + int *is_signed); /* OUT + receives whether message is signed */ + +/* + * this function creates a CMS message where eContentType is EnvelopedData + */ +krb5_error_code cms_envelopeddata_create + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + krb5_preauthtype pa_type, /* IN */ + unsigned char *key_pack, /* IN + contains DER encoded ReplyKeyPack */ + unsigned int key_pack_len, /* IN + contains length of key_pack */ + unsigned char **envel_data, /* OUT + receives DER encoded encKeyPack */ + unsigned int *envel_data_len); /* OUT + receives length of envel_data */ + +/* + * this function creates a CMS message where eContentType is EnvelopedData + */ +krb5_error_code cms_envelopeddata_verify + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + krb5_preauthtype pa_type, /* IN */ + int require_crl_checking, /* IN + specifies whether CRL checking should be + strictly enforced */ + unsigned char *envel_data, /* IN + contains DER encoded encKeyPack */ + unsigned int envel_data_len, /* IN + contains length of envel_data */ + unsigned char **signed_data, /* OUT + receives ReplyKeyPack */ + unsigned int *signed_data_len); /* OUT + receives length of signed_data */ + +/* + * This function retrieves the signer's identity, in a form that could + * be passed back in to a future invocation of this module as a candidate + * client identity location. + */ +krb5_error_code crypto_retrieve_signer_identity + (krb5_context context, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + const char **identity); /* OUT */ + +/* + * this function returns SAN information found in the + * received certificate. at least one of pkinit_sans, + * upn_sans, or kdc_hostnames must be non-NULL. + */ +krb5_error_code crypto_retrieve_cert_sans + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + krb5_principal **pkinit_sans, /* OUT + if non-NULL, a null-terminated array of + id-pkinit-san values found in the certificate + are returned */ + char ***upn_sans, /* OUT + if non-NULL, a null-terminated array of + id-ms-upn-san values found in the certificate + are returned */ + unsigned char ***kdc_hostname); /* OUT + if non-NULL, a null-terminated array of + dNSName (hostname) SAN values found in the + certificate are returned */ + +/* + * this function checks for acceptable key usage values + * in the received certificate. + * + * when checking a received kdc certificate, it looks for + * the kpKdc key usage. if allow_secondary_usage is + * non-zero, it will also accept kpServerAuth. + * + * when checking a received user certificate, it looks for + * kpClientAuth key usage. if allow_secondary_usage is + * non-zero, it will also accept id-ms-sc-logon EKU. + * + * this function must also assert that the digitalSignature + * key usage is consistent. + */ +krb5_error_code crypto_check_cert_eku + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + int checking_kdc_cert, /* IN + specifies if the received certificate is + a KDC certificate (non-zero), + or a user certificate (zero) */ + int allow_secondary_usage, /* IN + specifies if the secondary key usage + should be accepted or not (see above) */ + int *eku_valid); /* OUT + receives non-zero if an acceptable EKU was found */ + +/* + * this functions takes in generated DH secret key and converts + * it in to a kerberos session key. it takes into the account the + * enc type and then follows the procedure specified in the RFC p 22. + */ +krb5_error_code pkinit_octetstring2key + (krb5_context context, /* IN */ + krb5_enctype etype, /* IN + specifies the enc type */ + unsigned char *key, /* IN + contains the DH secret key */ + unsigned int key_len, /* IN + contains length of key */ + krb5_keyblock * krb5key); /* OUT + receives kerberos session key */ + +/* + * this function implements clients first part of the DH protocol. + * client selects its DH parameters and pub key + */ +krb5_error_code client_create_dh + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + int dh_size, /* IN + specifies the DH modulous, eg 1024, 2048, or 4096 */ + krb5_data *spki_out); /* OUT + receives SubjectPublicKeyInfo encoding */ + +/* + * this function completes client's the DH protocol. client + * processes received DH pub key from the KDC and computes + * the DH secret key + */ +krb5_error_code client_process_dh + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + unsigned char *dh_pubkey, /* IN + contains client's DER encoded DH pub key */ + unsigned int dh_pubkey_len, /* IN + contains length of dh_pubkey */ + unsigned char **client_key_out, /* OUT + receives DH secret key */ + unsigned int *client_key_len_out); /* OUT + receives length of DH secret key */ + +/* + * this function implements the KDC first part of the DH protocol. + * it decodes the client's DH parameters and pub key and checks + * if they are acceptable. + */ +krb5_error_code server_check_dh + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + const krb5_data *client_spki, /* IN + SubjectPublicKeyInfo encoding from client */ + int minbits); /* IN + the minimum number of key bits acceptable */ + +/* + * this function completes the KDC's DH protocol. The KDC generates + * its DH pub key and computes the DH secret key + */ +krb5_error_code server_process_dh + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + unsigned char **dh_pubkey_out, /* OUT + receives KDC's DER encoded DH pub key */ + unsigned int *dh_pubkey_len_out, /* OUT + receives length of dh_pubkey */ + unsigned char **server_key_out, /* OUT + receives DH secret key */ + unsigned int *server_key_len_out); /* OUT + receives length of DH secret key */ + +/* + * this functions takes in crypto specific representation of + * supportedCMSTypes and creates a list of + * krb5_algorithm_identifier + */ +krb5_error_code create_krb5_supportedCMSTypes + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + krb5_algorithm_identifier ***supportedCMSTypes); /* OUT */ + +/* + * this functions takes in crypto specific representation of + * trustedCertifiers and creates a list of + * krb5_external_principal_identifier + */ +krb5_error_code create_krb5_trustedCertifiers + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + krb5_external_principal_identifier ***trustedCertifiers); /* OUT */ + +/* + * this functions takes in crypto specific representation of the + * KDC's certificate and creates a DER encoded kdcPKId + */ +krb5_error_code create_issuerAndSerial + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + unsigned char **kdcId_buf, /* OUT + receives DER encoded kdcPKId */ + unsigned int *kdcId_len); /* OUT + receives length of encoded kdcPKId */ + +/* + * These functions manipulate the deferred-identities list in the identity + * context, which is opaque outside of the crypto-specific bits. + */ +const pkinit_deferred_id * crypto_get_deferred_ids + (krb5_context context, pkinit_identity_crypto_context id_cryptoctx); +krb5_error_code crypto_set_deferred_id + (krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, + const char *identity, const char *password); + +/* + * process the values from idopts and obtain the cert(s) + * specified by those options, populating the id_cryptoctx. + */ +krb5_error_code crypto_load_certs + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_opts *idopts, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */ + krb5_principal princ, /* IN */ + krb5_boolean defer_id_prompts); /* IN */ + +/* + * Free up information held from crypto_load_certs() + */ +krb5_error_code crypto_free_cert_info + (krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx); + + +/* + * Get a null-terminated list of certificate matching data objects for the + * certificates loaded in id_cryptoctx. + */ +krb5_error_code +crypto_cert_get_matching_data(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + pkinit_cert_matching_data ***md_out); + +/* + * Free a matching data object. + */ +void +crypto_cert_free_matching_data(krb5_context context, + pkinit_cert_matching_data *md); + +/* + * Free a list of matching data objects. + */ +void +crypto_cert_free_matching_data_list(krb5_context context, + pkinit_cert_matching_data **matchdata); + +/* + * Choose one of the certificates loaded in idctx to use for PKINIT client + * operations. cred_index must be an index into the array of matching objects + * returned by crypto_cert_get_matching_data(). + */ +krb5_error_code +crypto_cert_select(krb5_context context, pkinit_identity_crypto_context idctx, + size_t cred_index); + +/* + * Select the default certificate as "the chosen one" + */ +krb5_error_code crypto_cert_select_default + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx); /* IN */ + +/* + * process the values from idopts and obtain the anchor or + * intermediate certificates, or crls specified by idtype, + * catype, and id + */ +krb5_error_code crypto_load_cas_and_crls + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_opts *idopts, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */ + int idtype, /* IN + defines the storage type (file, directory, etc) */ + int catype, /* IN + defines the ca type (anchor, intermediate, crls) */ + char *id); /* IN + defines the location (filename, directory name, etc) */ + +/* + * on the client, obtain the kdc's certificate to include + * in a request + */ +krb5_error_code pkinit_get_kdc_cert + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */ + krb5_principal princ); /* IN */ + +/* + * this function creates edata that contains TD-DH-PARAMETERS + */ +krb5_error_code pkinit_create_td_dh_parameters + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + pkinit_plg_opts *opts, /* IN */ + krb5_pa_data ***e_data_out); /* OUT */ + +/* + * this function processes edata that contains TD-DH-PARAMETERS. + * the client processes the received acceptable by KDC DH + * parameters and picks the first acceptable to it. it matches + * them against the known DH parameters. + */ +krb5_error_code pkinit_process_td_dh_params + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + krb5_algorithm_identifier **algId, /* IN */ + int *new_dh_size); /* OUT + receives the new DH modulus to use in the new AS-REQ */ + +/* + * this function creates edata that contains TD-INVALID-CERTIFICATES + */ +krb5_error_code pkinit_create_td_invalid_certificate + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + krb5_pa_data ***e_data_out); /* OUT */ + +/* + * this function creates edata that contains TD-TRUSTED-CERTIFIERS + */ +krb5_error_code pkinit_create_td_trusted_certifiers + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + krb5_pa_data ***e_data_out); /* OUT */ + +/* + * this function processes edata that contains either + * TD-TRUSTED-CERTIFICATES or TD-INVALID-CERTIFICATES. + * current implementation only decodes the received message + * but does not act on it + */ +krb5_error_code pkinit_process_td_trusted_certifiers + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + krb5_external_principal_identifier **trustedCertifiers, /* IN */ + int td_type); /* IN */ + +/* + * this function checks if the received kdcPKId matches + * the KDC's certificate + */ +krb5_error_code pkinit_check_kdc_pkid + (krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + unsigned char *pdid_buf, /* IN + contains DER encoded kdcPKId */ + unsigned int pkid_len, /* IN + contains length of pdid_buf */ + int *valid_kdcPkId); /* OUT + 1 if kdcPKId matches, otherwise 0 */ + +krb5_error_code pkinit_identity_set_prompter + (pkinit_identity_crypto_context id_cryptoctx, /* IN */ + krb5_prompter_fct prompter, /* IN */ + void *prompter_data); /* IN */ + +krb5_error_code +pkinit_alg_agility_kdf(krb5_context context, + krb5_data *secret, + krb5_data *alg_oid, + krb5_const_principal party_u_info, + krb5_const_principal party_v_info, + krb5_enctype enctype, + krb5_data *as_req, + krb5_data *pk_as_rep, + krb5_keyblock *key_block); + +extern const krb5_data sha1_id; +extern const krb5_data sha256_id; +extern const krb5_data sha512_id; +extern const krb5_data oakley_1024; +extern const krb5_data oakley_2048; +extern const krb5_data oakley_4096; + +/** + * An ordered set of OIDs, stored as krb5_data, of KDF algorithms + * supported by this implementation. The order of this array controls + * the order in which the server will pick. + */ +extern krb5_data const * const supported_kdf_alg_ids[]; + +/* CMS signature algorithms supported by this implementation, in order of + * decreasing preference. */ +extern krb5_data const * const supported_cms_algs[]; + +krb5_error_code +crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx, + uint8_t **der_out, size_t *der_len); + +krb5_error_code +crypto_req_cert_matching_data(krb5_context context, + pkinit_plg_crypto_context plgctx, + pkinit_req_crypto_context reqctx, + pkinit_cert_matching_data **md_out); + +#endif /* _PKINIT_CRYPTO_H */ diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c new file mode 100644 index 00000000..cb9c7962 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_crypto_openssl.c @@ -0,0 +1,5814 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * COPYRIGHT (C) 2006,2007 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#include "k5-int.h" +#include "pkinit_crypto_openssl.h" +#include "k5-buf.h" +#include "k5-err.h" +#include "k5-hex.h" +#include +#include +#include + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#include +#include +#endif + +static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context ); +static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ); + +static krb5_error_code pkinit_init_dh_params(pkinit_plg_crypto_context ); +static void pkinit_fini_dh_params(pkinit_plg_crypto_context ); + +static krb5_error_code pkinit_init_certs(pkinit_identity_crypto_context ctx); +static void pkinit_fini_certs(pkinit_identity_crypto_context ctx); + +static krb5_error_code pkinit_init_pkcs11(pkinit_identity_crypto_context ctx); +static void pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx); + +static krb5_error_code pkinit_sign_data +(krb5_context context, pkinit_identity_crypto_context cryptoctx, + unsigned char *data, unsigned int data_len, + unsigned char **sig, unsigned int *sig_len); + +static krb5_error_code create_signature +(unsigned char **, unsigned int *, unsigned char *, unsigned int, + EVP_PKEY *pkey); + +static krb5_error_code pkinit_decode_data +(krb5_context context, pkinit_identity_crypto_context cryptoctx, + const uint8_t *data, unsigned int data_len, uint8_t **decoded, + unsigned int *decoded_len); + +#ifdef DEBUG_DH +static void print_dh(DH *, char *); +static void print_pubkey(BIGNUM *, char *); +#endif + +static int prepare_enc_data +(const uint8_t *indata, int indata_len, uint8_t **outdata, int *outdata_len); + +static int openssl_callback (int, X509_STORE_CTX *); +static int openssl_callback_ignore_crls (int, X509_STORE_CTX *); + +static int pkcs7_decrypt +(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, PKCS7 *p7, + unsigned char **data_out, unsigned int *len_out); + +static ASN1_OBJECT * pkinit_pkcs7type2oid +(pkinit_plg_crypto_context plg_cryptoctx, int pkcs7_type); + +static krb5_error_code pkinit_create_sequence_of_principal_identifiers +(krb5_context context, pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + int type, krb5_pa_data ***e_data_out); + +#ifndef WITHOUT_PKCS11 +static krb5_error_code pkinit_find_private_key +(pkinit_identity_crypto_context, CK_ATTRIBUTE_TYPE usage, + CK_OBJECT_HANDLE *objp); +static krb5_error_code pkinit_login +(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, + CK_TOKEN_INFO *tip, const char *password); +static krb5_error_code pkinit_open_session +(krb5_context context, pkinit_identity_crypto_context id_cryptoctx); +#ifdef SILLYDECRYPT +CK_RV pkinit_C_Decrypt +(pkinit_identity_crypto_context id_cryptoctx, + CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); +#endif + +static krb5_error_code pkinit_sign_data_pkcs11 +(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, + unsigned char *data, unsigned int data_len, + unsigned char **sig, unsigned int *sig_len); +static krb5_error_code pkinit_decode_data_pkcs11 +(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, + const uint8_t *data, unsigned int data_len, uint8_t **decoded_data, + unsigned int *decoded_data_len); +#endif /* WITHOUT_PKCS11 */ + +static krb5_error_code pkinit_sign_data_fs +(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, + unsigned char *data, unsigned int data_len, + unsigned char **sig, unsigned int *sig_len); +static krb5_error_code pkinit_decode_data_fs +(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, + const uint8_t *data, unsigned int data_len, uint8_t **decoded_data, + unsigned int *decoded_data_len); + +static krb5_error_code +create_krb5_invalidCertificates(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_external_principal_identifier *** ids); + +static krb5_error_code +create_identifiers_from_stack(STACK_OF(X509) *sk, + krb5_external_principal_identifier *** ids); +static int +wrap_signeddata(unsigned char *data, unsigned int data_len, + unsigned char **out, unsigned int *out_len); + +static const char * +pkcs11err(int err); + + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + +/* 1.1 standardizes constructor and destructor names, renaming + * EVP_MD_CTX_{create,destroy} and deprecating ASN1_STRING_data. */ + +#define EVP_MD_CTX_new EVP_MD_CTX_create +#define EVP_MD_CTX_free EVP_MD_CTX_destroy +#define ASN1_STRING_get0_data ASN1_STRING_data + +/* + * 1.1 adds DHX support, which uses the RFC 3279 DomainParameters encoding we + * need for PKINIT. For 1.0 we must use the original DH type when creating + * EVP_PKEY objects. + */ +#define EVP_PKEY_DHX EVP_PKEY_DH + +/* 1.1 makes many handle types opaque and adds accessors. Add compatibility + * versions of the new accessors we use for pre-1.1. */ + +#define OBJ_get0_data(o) ((o)->data) +#define OBJ_length(o) ((o)->length) + +#define DH_set0_key compat_dh_set0_key +static int +compat_dh_set0_key(DH *dh, BIGNUM *pub, BIGNUM *priv) +{ + if (pub != NULL) { + BN_clear_free(dh->pub_key); + dh->pub_key = pub; + } + if (priv != NULL) { + BN_clear_free(dh->priv_key); + dh->priv_key = priv; + } + return 1; +} + +#define DH_get0_key compat_dh_get0_key +static void compat_dh_get0_key(const DH *dh, const BIGNUM **pub, + const BIGNUM **priv) +{ + if (pub != NULL) + *pub = dh->pub_key; + if (priv != NULL) + *priv = dh->priv_key; +} + +#define EVP_PKEY_get0_DH compat_get0_DH +static DH * +compat_get0_DH(const EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_DH) + return NULL; + return pkey->pkey.dh; + +} + +/* Return true if the cert c includes a key usage which doesn't include u. + * Define using direct member access for pre-1.1. */ +#define ku_reject(c, u) \ + (((c)->ex_flags & EXFLAG_KUSAGE) && !((c)->ex_kusage & (u))) + +#else /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ + +/* Return true if the cert x includes a key usage which doesn't include u. */ +#define ku_reject(c, u) (!(X509_get_key_usage(c) & (u))) + +#endif + +#if OPENSSL_VERSION_NUMBER < 0x30000000L +/* OpenSSL 3.0 changes several preferred function names. */ +#define EVP_PKEY_parameters_eq EVP_PKEY_cmp_parameters +#define EVP_MD_CTX_get0_md EVP_MD_CTX_md +#define EVP_PKEY_get_size EVP_PKEY_size +#define EVP_PKEY_get_bits EVP_PKEY_bits + +/* + * Convert *dh to an EVP_PKEY object, taking ownership of *dh and setting it to + * NULL. On error, return NULL and do not take ownership of or change *dh. + * OpenSSL 3.0 deprecates the low-level DH interfaces, so this helper will only + * be used with prior versions. + */ +static EVP_PKEY * +dh_to_pkey(DH **dh) +{ + EVP_PKEY *pkey; + + pkey = EVP_PKEY_new(); + if (pkey == NULL) + return NULL; + if (!EVP_PKEY_assign(pkey, EVP_PKEY_DHX, *dh)) { + EVP_PKEY_free(pkey); + return NULL; + } + *dh = NULL; + return pkey; +} +#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + +/* Encode a bignum as an ASN.1 integer in DER. */ +static int +encode_bn_der(const BIGNUM *bn, uint8_t **der_out, int *len_out) +{ + ASN1_INTEGER *intval; + int len; + uint8_t *der = NULL, *outptr; + + intval = BN_to_ASN1_INTEGER(bn, NULL); + if (intval == NULL) + return 0; + len = i2d_ASN1_INTEGER(intval, NULL); + if (len > 0 && (outptr = der = malloc(len)) != NULL) + (void)i2d_ASN1_INTEGER(intval, &outptr); + ASN1_INTEGER_free(intval); + if (der == NULL) + return 0; + *der_out = der; + *len_out = len; + return 1; +} + +/* Decode an ASN.1 integer, returning a bignum. */ +static BIGNUM * +decode_bn_der(const uint8_t *der, size_t len) +{ + ASN1_INTEGER *intval; + BIGNUM *bn; + + intval = d2i_ASN1_INTEGER(NULL, &der, len); + if (intval == NULL) + return NULL; + bn = ASN1_INTEGER_to_BN(intval, NULL); + ASN1_INTEGER_free(intval); + return bn; +} + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L +static int +params_valid(EVP_PKEY *params) +{ + EVP_PKEY_CTX *ctx; + int result; + + ctx = EVP_PKEY_CTX_new(params, NULL); + if (ctx == NULL) + return 0; + result = EVP_PKEY_param_check(ctx); + EVP_PKEY_CTX_free(ctx); + return result == 1; +} +#else +static int +params_valid(EVP_PKEY *params) +{ + DH *dh; + int codes; + + dh = EVP_PKEY_get0_DH(params); + return (dh == NULL) ? 0 : (DH_check(dh, &codes) && codes == 0); +} +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +static EVP_PKEY * +decode_dh_params(const krb5_data *params_der) +{ + EVP_PKEY *pkey = NULL; + const uint8_t *inptr = (uint8_t *)params_der->data; + size_t len = params_der->length; + OSSL_DECODER_CTX *dctx; + int ok; + + dctx = OSSL_DECODER_CTX_new_for_pkey(&pkey, "DER", "type-specific", "DHX", + EVP_PKEY_KEY_PARAMETERS, NULL, NULL); + if (dctx == NULL) + return NULL; + + ok = OSSL_DECODER_from_data(dctx, &inptr, &len); + OSSL_DECODER_CTX_free(dctx); + return ok ? pkey : NULL; +} +#else +static EVP_PKEY * +decode_dh_params(const krb5_data *params_der) +{ + const uint8_t *p = (uint8_t *)params_der->data; + DH *dh; + EVP_PKEY *pkey; + + dh = d2i_DHxparams(NULL, &p, params_der->length); + pkey = dh_to_pkey(&dh); + DH_free(dh); + return pkey; +} +#endif + +static krb5_error_code +encode_spki(EVP_PKEY *pkey, krb5_data *spki_out) +{ + krb5_error_code ret = ENOMEM; + int len; + uint8_t *outptr; + + len = i2d_PUBKEY(pkey, NULL); + ret = alloc_data(spki_out, len); + if (ret) + goto cleanup; + outptr = (uint8_t *)spki_out->data; + (void)i2d_PUBKEY(pkey, &outptr); + +cleanup: + return ret; +} + +static EVP_PKEY * +decode_spki(const krb5_data *spki) +{ + const uint8_t *inptr = (uint8_t *)spki->data; + + return d2i_PUBKEY(NULL, &inptr, spki->length); +} + +#else /* OPENSSL_VERSION_NUMBER < 0x10100000L */ + +/* + * OpenSSL 1.0 has no DHX support, so we need a custom decoder for RFC 3279 + * DomainParameters, and we need to use X509_PUBKEY values to marshal + * SubjectPublicKeyInfo. + */ + +typedef struct { + ASN1_BIT_STRING *seed; + BIGNUM *counter; +} int_dhvparams; + +typedef struct { + BIGNUM *p; + BIGNUM *q; + BIGNUM *g; + BIGNUM *j; + int_dhvparams *vparams; +} int_dhxparams; + +ASN1_SEQUENCE(int_dhvparams) = { + ASN1_SIMPLE(int_dhvparams, seed, ASN1_BIT_STRING), + ASN1_SIMPLE(int_dhvparams, counter, BIGNUM) +} ASN1_SEQUENCE_END(int_dhvparams); + +ASN1_SEQUENCE(int_dhxparams) = { + ASN1_SIMPLE(int_dhxparams, p, BIGNUM), + ASN1_SIMPLE(int_dhxparams, g, BIGNUM), + ASN1_SIMPLE(int_dhxparams, q, BIGNUM), + ASN1_OPT(int_dhxparams, j, BIGNUM), + ASN1_OPT(int_dhxparams, vparams, int_dhvparams) +} ASN1_SEQUENCE_END(int_dhxparams); + +static EVP_PKEY * +decode_dh_params(const krb5_data *params_der) +{ + int_dhxparams *params; + DH *dh; + EVP_PKEY *pkey; + const uint8_t *p; + + dh = DH_new(); + if (dh == NULL) + return NULL; + + p = (uint8_t *)params_der->data; + params = (int_dhxparams *)ASN1_item_d2i(NULL, &p, params_der->length, + ASN1_ITEM_rptr(int_dhxparams)); + if (params == NULL) { + DH_free(dh); + return NULL; + } + + /* Steal p, q, and g from dhparams for dh. Ignore j and vparams. */ + dh->p = params->p; + dh->q = params->q; + dh->g = params->g; + params->p = params->q = params->g = NULL; + ASN1_item_free((ASN1_VALUE *)params, ASN1_ITEM_rptr(int_dhxparams)); + pkey = dh_to_pkey(&dh); + DH_free(dh); + return pkey; +} + +static krb5_error_code +encode_spki(EVP_PKEY *pkey, krb5_data *spki_out) +{ + krb5_error_code ret = ENOMEM; + const DH *dh; + uint8_t *param_der = NULL, *pubkey_der = NULL, *outptr; + int param_der_len, pubkey_der_len, len; + X509_PUBKEY pubkey; + int_dhxparams dhxparams; + X509_ALGOR algor; + ASN1_OBJECT algorithm; + ASN1_TYPE parameter; + ASN1_STRING param_str, pubkey_str; + + dh = EVP_PKEY_get0_DH(pkey); + if (dh == NULL) + goto cleanup; + + dhxparams.p = dh->p; + dhxparams.q = dh->q; + dhxparams.g = dh->g; + dhxparams.j = NULL; + dhxparams.vparams = NULL; + param_der_len = ASN1_item_i2d((ASN1_VALUE *)&dhxparams, ¶m_der, + ASN1_ITEM_rptr(int_dhxparams)); + if (param_der_len < 0) + goto cleanup; + param_str.length = param_der_len; + param_str.type = V_ASN1_SEQUENCE; + param_str.data = param_der; + param_str.flags = 0; + parameter.type = V_ASN1_SEQUENCE; + parameter.value.sequence = ¶m_str; + + memset(&algorithm, 0, sizeof(algorithm)); + algorithm.data = (uint8_t *)dh_oid.data; + algorithm.length = dh_oid.length; + + algor.algorithm = &algorithm; + algor.parameter = ¶meter; + + if (!encode_bn_der(dh->pub_key, &pubkey_der, &pubkey_der_len)) + goto cleanup; + pubkey_str.length = pubkey_der_len; + pubkey_str.type = V_ASN1_BIT_STRING; + pubkey_str.data = pubkey_der; + pubkey_str.flags = ASN1_STRING_FLAG_BITS_LEFT; + + pubkey.algor = &algor; + pubkey.public_key = &pubkey_str; + len = i2d_X509_PUBKEY(&pubkey, NULL); + if (len < 0) + goto cleanup; + ret = alloc_data(spki_out, len); + if (ret) + goto cleanup; + outptr = (uint8_t *)spki_out->data; + i2d_X509_PUBKEY(&pubkey, &outptr); + +cleanup: + OPENSSL_free(param_der); + free(pubkey_der); + return ret; +} + +static EVP_PKEY * +decode_spki(const krb5_data *spki) +{ + X509_PUBKEY *pubkey = NULL; + const uint8_t *inptr; + DH *dh; + EVP_PKEY *pkey = NULL, *pkey_ret = NULL; + const ASN1_STRING *params; + const ASN1_BIT_STRING *public_key; + krb5_data d; + + inptr = (uint8_t *)spki->data; + pubkey = d2i_X509_PUBKEY(NULL, &inptr, spki->length); + if (pubkey == NULL) + goto cleanup; + + if (pubkey->algor->parameter->type != V_ASN1_SEQUENCE) + goto cleanup; + params = pubkey->algor->parameter->value.sequence; + d = make_data(params->data, params->length); + pkey = decode_dh_params(&d); + if (pkey == NULL) + goto cleanup; + dh = EVP_PKEY_get0_DH(pkey); + if (dh == NULL) + goto cleanup; + public_key = pubkey->public_key; + dh->pub_key = decode_bn_der(public_key->data, public_key->length); + if (dh->pub_key == NULL) + goto cleanup; + + pkey_ret = pkey; + pkey = NULL; + +cleanup: + X509_PUBKEY_free(pubkey); + EVP_PKEY_free(pkey); + return pkey_ret; +} + +#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ + +/* Attempt to specify padded Diffie-Hellman result derivation. Don't error out + * if this fails since we also detect short results and adjust them. */ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +static void +set_padded_derivation(EVP_PKEY_CTX *ctx) +{ + EVP_PKEY_CTX_set_dh_pad(ctx, 1); +} +#elif OPENSSL_VERSION_NUMBER >= 0x10100000L +static void +set_padded_derivation(EVP_PKEY_CTX *ctx) +{ + /* We would use EVP_PKEY_CTX_set_dh_pad() but it doesn't work with DHX. */ + EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DHX, EVP_PKEY_OP_DERIVE, + EVP_PKEY_CTRL_DH_PAD, 1, NULL); +} +#else +static void +set_padded_derivation(EVP_PKEY_CTX *ctx) +{ + /* There's no support for padded derivation in 1.0. */ +} +#endif + +static int +dh_result(EVP_PKEY *pkey, EVP_PKEY *peer, + uint8_t **result_out, unsigned int *len_out) +{ + EVP_PKEY_CTX *derive_ctx = NULL; + int ok = 0; + uint8_t *buf = NULL; + size_t len, dh_size = EVP_PKEY_get_size(pkey); + + *result_out = NULL; + *len_out = 0; + + derive_ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (derive_ctx == NULL) + goto cleanup; + if (EVP_PKEY_derive_init(derive_ctx) <= 0) + goto cleanup; + set_padded_derivation(derive_ctx); + if (EVP_PKEY_derive_set_peer(derive_ctx, peer) <= 0) + goto cleanup; + + buf = malloc(dh_size); + if (buf == NULL) + goto cleanup; + len = dh_size; + if (EVP_PKEY_derive(derive_ctx, buf, &len) <= 0) + goto cleanup; + if (len < dh_size) { /* only possible without padded derivation */ + memmove(buf + (dh_size - len), buf, len); + memset(buf, 0, dh_size - len); + } + + ok = 1; + *result_out = buf; + *len_out = dh_size; + buf = NULL; + +cleanup: + EVP_PKEY_CTX_free(derive_ctx); + free(buf); + return ok; +} + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +static int +dh_pubkey_der(EVP_PKEY *pkey, uint8_t **pubkey_out, unsigned int *len_out) +{ + BIGNUM *pubkey_bn = NULL; + int len, ok; + uint8_t *buf; + + if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, &pubkey_bn)) + return 0; + ok = encode_bn_der(pubkey_bn, &buf, &len); + BN_free(pubkey_bn); + if (ok) { + *pubkey_out = buf; + *len_out = len; + } + return ok; +} +#else +static int +dh_pubkey_der(EVP_PKEY *pkey, uint8_t **pubkey_out, unsigned int *len_out) +{ + const DH *dh; + const BIGNUM *pubkey_bn; + uint8_t *buf; + int len; + + dh = EVP_PKEY_get0_DH(pkey); + if (dh == NULL) + return 0; + DH_get0_key(dh, &pubkey_bn, NULL); + if (!encode_bn_der(pubkey_bn, &buf, &len)) + return 0; + *pubkey_out = buf; + *len_out = len; + return 1; +} +#endif + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L +/* OpenSSL 1.1 and later will copy the q parameter when generating keys. */ +static int +copy_q_openssl10(EVP_PKEY *src, EVP_PKEY *dest) +{ + return 1; +} +#else +/* OpenSSL 1.0 won't copy the q parameter, so we have to do it. */ +static int +copy_q_openssl10(EVP_PKEY *src, EVP_PKEY *dest) +{ + DH *dhsrc = EVP_PKEY_get0_DH(src), *dhdest = EVP_PKEY_get0_DH(dest); + + if (dhsrc == NULL || dhsrc->q == NULL || dhdest == NULL) + return 0; + if (dhdest->q != NULL) + return 1; + dhdest->q = BN_dup(dhsrc->q); + return dhdest->q != NULL; +} +#endif + +static EVP_PKEY * +generate_dh_pkey(EVP_PKEY *params) +{ + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + + ctx = EVP_PKEY_CTX_new(params, NULL); + if (ctx == NULL) + goto cleanup; + if (EVP_PKEY_keygen_init(ctx) <= 0) + goto cleanup; + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) + goto cleanup; + if (!copy_q_openssl10(params, pkey)) { + EVP_PKEY_free(pkey); + pkey = NULL; + } + +cleanup: + EVP_PKEY_CTX_free(ctx); + return pkey; +} + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + +static EVP_PKEY * +compose_dh_pkey(EVP_PKEY *params, const uint8_t *pubkey_der, size_t der_len) +{ + EVP_PKEY *pkey = NULL, *pkey_ret = NULL; + BIGNUM *pubkey_bn = NULL; + uint8_t *pubkey_bin = NULL; + int binlen; + + pkey = EVP_PKEY_dup(params); + if (pkey == NULL) + goto cleanup; + + pubkey_bn = decode_bn_der(pubkey_der, der_len); + if (pubkey_bn == NULL) + goto cleanup; + binlen = EVP_PKEY_get_size(pkey); + pubkey_bin = malloc(binlen); + if (pubkey_bin == NULL) + goto cleanup; + if (BN_bn2binpad(pubkey_bn, pubkey_bin, binlen) != binlen) + goto cleanup; + if (EVP_PKEY_set1_encoded_public_key(pkey, pubkey_bin, binlen) != 1) + goto cleanup; + + pkey_ret = pkey; + pkey = NULL; + +cleanup: + EVP_PKEY_free(pkey); + BN_free(pubkey_bn); + free(pubkey_bin); + return pkey_ret; +} + +#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L +static DH * +dup_dh_params(DH *src) +{ + return DHparams_dup(src); +} +#else +/* DHparams_dup() won't copy q in OpenSSL 1.0. */ +static DH * +dup_dh_params(DH *src) +{ + DH *dh; + + dh = DH_new(); + if (dh == NULL) + return NULL; + dh->p = BN_dup(src->p); + dh->q = BN_dup(src->q); + dh->g = BN_dup(src->g); + if (dh->p == NULL || dh->q == NULL || dh->g == NULL) { + DH_free(dh); + return NULL; + } + return dh; +} +#endif + +static EVP_PKEY * +compose_dh_pkey(EVP_PKEY *params, const uint8_t *pubkey_der, size_t der_len) +{ + DH *dhparams, *dh = NULL; + EVP_PKEY *pkey = NULL; + BIGNUM *pubkey_bn = NULL; + + pubkey_bn = decode_bn_der(pubkey_der, der_len); + if (pubkey_bn == NULL) + goto cleanup; + + dhparams = EVP_PKEY_get0_DH(params); + if (dhparams == NULL) + goto cleanup; + dh = dup_dh_params(dhparams); + if (dh == NULL) + goto cleanup; + if (!DH_set0_key(dh, pubkey_bn, NULL)) + goto cleanup; + pubkey_bn = NULL; + + pkey = dh_to_pkey(&dh); + +cleanup: + BN_free(pubkey_bn); + DH_free(dh); + return pkey; +} + +#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + +static struct pkcs11_errstrings { + short code; + char *text; +} pkcs11_errstrings[] = { + { 0x0, "ok" }, + { 0x1, "cancel" }, + { 0x2, "host memory" }, + { 0x3, "slot id invalid" }, + { 0x5, "general error" }, + { 0x6, "function failed" }, + { 0x7, "arguments bad" }, + { 0x8, "no event" }, + { 0x9, "need to create threads" }, + { 0xa, "cant lock" }, + { 0x10, "attribute read only" }, + { 0x11, "attribute sensitive" }, + { 0x12, "attribute type invalid" }, + { 0x13, "attribute value invalid" }, + { 0x20, "data invalid" }, + { 0x21, "data len range" }, + { 0x30, "device error" }, + { 0x31, "device memory" }, + { 0x32, "device removed" }, + { 0x40, "encrypted data invalid" }, + { 0x41, "encrypted data len range" }, + { 0x50, "function canceled" }, + { 0x51, "function not parallel" }, + { 0x54, "function not supported" }, + { 0x60, "key handle invalid" }, + { 0x62, "key size range" }, + { 0x63, "key type inconsistent" }, + { 0x64, "key not needed" }, + { 0x65, "key changed" }, + { 0x66, "key needed" }, + { 0x67, "key indigestible" }, + { 0x68, "key function not permitted" }, + { 0x69, "key not wrappable" }, + { 0x6a, "key unextractable" }, + { 0x70, "mechanism invalid" }, + { 0x71, "mechanism param invalid" }, + { 0x82, "object handle invalid" }, + { 0x90, "operation active" }, + { 0x91, "operation not initialized" }, + { 0xa0, "pin incorrect" }, + { 0xa1, "pin invalid" }, + { 0xa2, "pin len range" }, + { 0xa3, "pin expired" }, + { 0xa4, "pin locked" }, + { 0xb0, "session closed" }, + { 0xb1, "session count" }, + { 0xb3, "session handle invalid" }, + { 0xb4, "session parallel not supported" }, + { 0xb5, "session read only" }, + { 0xb6, "session exists" }, + { 0xb7, "session read only exists" }, + { 0xb8, "session read write so exists" }, + { 0xc0, "signature invalid" }, + { 0xc1, "signature len range" }, + { 0xd0, "template incomplete" }, + { 0xd1, "template inconsistent" }, + { 0xe0, "token not present" }, + { 0xe1, "token not recognized" }, + { 0xe2, "token write protected" }, + { 0xf0, "unwrapping key handle invalid" }, + { 0xf1, "unwrapping key size range" }, + { 0xf2, "unwrapping key type inconsistent" }, + { 0x100, "user already logged in" }, + { 0x101, "user not logged in" }, + { 0x102, "user pin not initialized" }, + { 0x103, "user type invalid" }, + { 0x104, "user another already logged in" }, + { 0x105, "user too many types" }, + { 0x110, "wrapped key invalid" }, + { 0x112, "wrapped key len range" }, + { 0x113, "wrapping key handle invalid" }, + { 0x114, "wrapping key size range" }, + { 0x115, "wrapping key type inconsistent" }, + { 0x120, "random seed not supported" }, + { 0x121, "random no rng" }, + { 0x130, "domain params invalid" }, + { 0x150, "buffer too small" }, + { 0x160, "saved state invalid" }, + { 0x170, "information sensitive" }, + { 0x180, "state unsaveable" }, + { 0x190, "cryptoki not initialized" }, + { 0x191, "cryptoki already initialized" }, + { 0x1a0, "mutex bad" }, + { 0x1a1, "mutex not locked" }, + { 0x200, "function rejected" }, + { -1, NULL } +}; + +MAKE_INIT_FUNCTION(pkinit_openssl_init); + +static krb5_error_code oerr(krb5_context context, krb5_error_code code, + const char *fmt, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 4))) +#endif + ; + +/* + * Set an error string containing the formatted arguments and the first pending + * OpenSSL error. Write the formatted arguments and all pending OpenSSL error + * messages to the trace log. Return code, or KRB5KDC_ERR_PREAUTH_FAILED if + * code is 0. + */ +static krb5_error_code +oerr(krb5_context context, krb5_error_code code, const char *fmt, ...) +{ + unsigned long err; + va_list ap; + char *str, buf[128]; + int r; + + if (!code) + code = KRB5KDC_ERR_PREAUTH_FAILED; + + va_start(ap, fmt); + r = vasprintf(&str, fmt, ap); + va_end(ap); + if (r < 0) + return code; + + err = ERR_peek_error(); + if (err) { + krb5_set_error_message(context, code, _("%s: %s"), str, + ERR_reason_error_string(err)); + } else { + krb5_set_error_message(context, code, "%s", str); + } + + TRACE_PKINIT_OPENSSL_ERROR(context, str); + while ((err = ERR_get_error()) != 0) { + ERR_error_string_n(err, buf, sizeof(buf)); + TRACE_PKINIT_OPENSSL_ERROR(context, buf); + } + + free(str); + return code; +} + +/* + * Set an appropriate error string containing msg for a certificate + * verification failure from certctx. Write the message and all pending + * OpenSSL error messages to the trace log. Return code, or + * KRB5KDC_ERR_PREAUTH_FAILED if code is 0. + */ +static krb5_error_code +oerr_cert(krb5_context context, krb5_error_code code, X509_STORE_CTX *certctx, + const char *msg) +{ + int depth = X509_STORE_CTX_get_error_depth(certctx); + int err = X509_STORE_CTX_get_error(certctx); + const char *errstr = X509_verify_cert_error_string(err); + + return oerr(context, code, _("%s (depth %d): %s"), msg, depth, errstr); +} + +krb5_error_code +pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx) +{ + krb5_error_code retval = ENOMEM; + pkinit_plg_crypto_context ctx = NULL; + + (void)CALL_INIT_FUNCTION(pkinit_openssl_init); + + ctx = malloc(sizeof(*ctx)); + if (ctx == NULL) + goto out; + memset(ctx, 0, sizeof(*ctx)); + + pkiDebug("%s: initializing openssl crypto context at %p\n", + __FUNCTION__, ctx); + retval = pkinit_init_pkinit_oids(ctx); + if (retval) + goto out; + + retval = pkinit_init_dh_params(ctx); + if (retval) + goto out; + + *cryptoctx = ctx; + +out: + if (retval && ctx != NULL) + pkinit_fini_plg_crypto(ctx); + + return retval; +} + +void +pkinit_fini_plg_crypto(pkinit_plg_crypto_context cryptoctx) +{ + pkiDebug("%s: freeing context at %p\n", __FUNCTION__, cryptoctx); + + if (cryptoctx == NULL) + return; + pkinit_fini_pkinit_oids(cryptoctx); + pkinit_fini_dh_params(cryptoctx); + free(cryptoctx); +} + +krb5_error_code +pkinit_init_identity_crypto(pkinit_identity_crypto_context *idctx) +{ + krb5_error_code retval = ENOMEM; + pkinit_identity_crypto_context ctx = NULL; + + ctx = malloc(sizeof(*ctx)); + if (ctx == NULL) + goto out; + memset(ctx, 0, sizeof(*ctx)); + + ctx->identity = NULL; + + retval = pkinit_init_certs(ctx); + if (retval) + goto out; + + retval = pkinit_init_pkcs11(ctx); + if (retval) + goto out; + + pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx); + *idctx = ctx; + +out: + if (retval) { + if (ctx) + pkinit_fini_identity_crypto(ctx); + } + + return retval; +} + +void +pkinit_fini_identity_crypto(pkinit_identity_crypto_context idctx) +{ + if (idctx == NULL) + return; + + pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, idctx); + if (idctx->deferred_ids != NULL) + pkinit_free_deferred_ids(idctx->deferred_ids); + free(idctx->identity); + pkinit_fini_certs(idctx); + pkinit_fini_pkcs11(idctx); + free(idctx); +} + +krb5_error_code +pkinit_init_req_crypto(pkinit_req_crypto_context *cryptoctx) +{ + krb5_error_code retval = ENOMEM; + pkinit_req_crypto_context ctx = NULL; + + ctx = malloc(sizeof(*ctx)); + if (ctx == NULL) + goto out; + memset(ctx, 0, sizeof(*ctx)); + + ctx->client_pkey = NULL; + ctx->received_params = NULL; + ctx->received_cert = NULL; + + *cryptoctx = ctx; + + pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx); + retval = 0; +out: + if (retval) + free(ctx); + + return retval; +} + +void +pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx) +{ + if (req_cryptoctx == NULL) + return; + + pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, req_cryptoctx); + EVP_PKEY_free(req_cryptoctx->client_pkey); + EVP_PKEY_free(req_cryptoctx->received_params); + X509_free(req_cryptoctx->received_cert); + + free(req_cryptoctx); +} + +static krb5_error_code +pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx) +{ + ctx->id_pkinit_san = OBJ_txt2obj("1.3.6.1.5.2.2", 1); + if (ctx->id_pkinit_san == NULL) + return ENOMEM; + + ctx->id_pkinit_authData = OBJ_txt2obj("1.3.6.1.5.2.3.1", 1); + if (ctx->id_pkinit_authData == NULL) + return ENOMEM; + + ctx->id_pkinit_DHKeyData = OBJ_txt2obj("1.3.6.1.5.2.3.2", 1); + if (ctx->id_pkinit_DHKeyData == NULL) + return ENOMEM; + + ctx->id_pkinit_rkeyData = OBJ_txt2obj("1.3.6.1.5.2.3.3", 1); + if (ctx->id_pkinit_rkeyData == NULL) + return ENOMEM; + + ctx->id_pkinit_KPClientAuth = OBJ_txt2obj("1.3.6.1.5.2.3.4", 1); + if (ctx->id_pkinit_KPClientAuth == NULL) + return ENOMEM; + + ctx->id_pkinit_KPKdc = OBJ_txt2obj("1.3.6.1.5.2.3.5", 1); + if (ctx->id_pkinit_KPKdc == NULL) + return ENOMEM; + + ctx->id_ms_kp_sc_logon = OBJ_txt2obj("1.3.6.1.4.1.311.20.2.2", 1); + if (ctx->id_ms_kp_sc_logon == NULL) + return ENOMEM; + + ctx->id_ms_san_upn = OBJ_txt2obj("1.3.6.1.4.1.311.20.2.3", 1); + if (ctx->id_ms_san_upn == NULL) + return ENOMEM; + + ctx->id_kp_serverAuth = OBJ_txt2obj("1.3.6.1.5.5.7.3.1", 1); + if (ctx->id_kp_serverAuth == NULL) + return ENOMEM; + + return 0; +} + +static krb5_error_code +get_cert(char *filename, X509 **retcert) +{ + X509 *cert = NULL; + BIO *tmp = NULL; + int code; + krb5_error_code retval; + + if (filename == NULL || retcert == NULL) + return EINVAL; + + *retcert = NULL; + + tmp = BIO_new(BIO_s_file()); + if (tmp == NULL) + return ENOMEM; + + code = BIO_read_filename(tmp, filename); + if (code == 0) { + retval = errno; + goto cleanup; + } + + cert = (X509 *) PEM_read_bio_X509(tmp, NULL, NULL, NULL); + if (cert == NULL) { + retval = EIO; + pkiDebug("failed to read certificate from %s\n", filename); + goto cleanup; + } + *retcert = cert; + retval = 0; +cleanup: + if (tmp != NULL) + BIO_free(tmp); + return retval; +} + +struct get_key_cb_data { + krb5_context context; + pkinit_identity_crypto_context id_cryptoctx; + const char *fsname; + char *filename; + const char *password; +}; + +static int +get_key_cb(char *buf, int size, int rwflag, void *userdata) +{ + struct get_key_cb_data *data = userdata; + pkinit_identity_crypto_context id_cryptoctx; + krb5_data rdat; + krb5_prompt kprompt; + krb5_prompt_type prompt_type; + krb5_error_code retval; + char *prompt; + + if (data->id_cryptoctx->defer_id_prompt) { + /* Supply the identity name to be passed to a responder callback. */ + pkinit_set_deferred_id(&data->id_cryptoctx->deferred_ids, + data->fsname, 0, NULL); + return -1; + } + if (data->password == NULL) { + /* We don't already have a password to use, so prompt for one. */ + if (data->id_cryptoctx->prompter == NULL) + return -1; + if (asprintf(&prompt, "%s %s", _("Pass phrase for"), + data->filename) < 0) + return -1; + rdat.data = buf; + rdat.length = size; + kprompt.prompt = prompt; + kprompt.hidden = 1; + kprompt.reply = &rdat; + prompt_type = KRB5_PROMPT_TYPE_PREAUTH; + + /* PROMPTER_INVOCATION */ + k5int_set_prompt_types(data->context, &prompt_type); + id_cryptoctx = data->id_cryptoctx; + retval = (data->id_cryptoctx->prompter)(data->context, + id_cryptoctx->prompter_data, + NULL, NULL, 1, &kprompt); + k5int_set_prompt_types(data->context, 0); + free(prompt); + if (retval != 0) + return -1; + } else { + /* Just use the already-supplied password. */ + rdat.length = strlen(data->password); + if ((int)rdat.length >= size) + return -1; + snprintf(buf, size, "%s", data->password); + } + return (int)rdat.length; +} + +static krb5_error_code +get_key(krb5_context context, pkinit_identity_crypto_context id_cryptoctx, + char *filename, const char *fsname, EVP_PKEY **retkey, + const char *password) +{ + EVP_PKEY *pkey = NULL; + BIO *tmp = NULL; + struct get_key_cb_data cb_data; + int code; + krb5_error_code retval; + + if (filename == NULL || retkey == NULL) + return EINVAL; + + tmp = BIO_new(BIO_s_file()); + if (tmp == NULL) + return ENOMEM; + + code = BIO_read_filename(tmp, filename); + if (code == 0) { + retval = errno; + goto cleanup; + } + cb_data.context = context; + cb_data.id_cryptoctx = id_cryptoctx; + cb_data.filename = filename; + cb_data.fsname = fsname; + cb_data.password = password; + pkey = PEM_read_bio_PrivateKey(tmp, NULL, get_key_cb, &cb_data); + if (pkey == NULL && !id_cryptoctx->defer_id_prompt) { + retval = EIO; + pkiDebug("failed to read private key from %s\n", filename); + goto cleanup; + } + *retkey = pkey; + retval = 0; +cleanup: + if (tmp != NULL) + BIO_free(tmp); + return retval; +} + +static void +pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx) +{ + if (ctx == NULL) + return; + ASN1_OBJECT_free(ctx->id_pkinit_san); + ASN1_OBJECT_free(ctx->id_pkinit_authData); + ASN1_OBJECT_free(ctx->id_pkinit_DHKeyData); + ASN1_OBJECT_free(ctx->id_pkinit_rkeyData); + ASN1_OBJECT_free(ctx->id_pkinit_KPClientAuth); + ASN1_OBJECT_free(ctx->id_pkinit_KPKdc); + ASN1_OBJECT_free(ctx->id_ms_kp_sc_logon); + ASN1_OBJECT_free(ctx->id_ms_san_upn); + ASN1_OBJECT_free(ctx->id_kp_serverAuth); +} + +static krb5_error_code +pkinit_init_dh_params(pkinit_plg_crypto_context plgctx) +{ + krb5_error_code retval = ENOMEM; + + plgctx->dh_1024 = decode_dh_params(&oakley_1024); + if (plgctx->dh_1024 == NULL) + goto cleanup; + + plgctx->dh_2048 = decode_dh_params(&oakley_2048); + if (plgctx->dh_2048 == NULL) + goto cleanup; + + plgctx->dh_4096 = decode_dh_params(&oakley_4096); + if (plgctx->dh_4096 == NULL) + goto cleanup; + + retval = 0; + +cleanup: + if (retval) + pkinit_fini_dh_params(plgctx); + + return retval; +} + +static void +pkinit_fini_dh_params(pkinit_plg_crypto_context plgctx) +{ + EVP_PKEY_free(plgctx->dh_1024); + EVP_PKEY_free(plgctx->dh_2048); + EVP_PKEY_free(plgctx->dh_4096); + plgctx->dh_1024 = plgctx->dh_2048 = plgctx->dh_4096 = NULL; +} + +static krb5_error_code +pkinit_init_certs(pkinit_identity_crypto_context ctx) +{ + krb5_error_code retval = ENOMEM; + int i; + + for (i = 0; i < MAX_CREDS_ALLOWED; i++) + ctx->creds[i] = NULL; + ctx->my_certs = NULL; + ctx->cert_index = 0; + ctx->my_key = NULL; + ctx->trustedCAs = NULL; + ctx->intermediateCAs = NULL; + ctx->revoked = NULL; + + retval = 0; + return retval; +} + +static void +pkinit_fini_certs(pkinit_identity_crypto_context ctx) +{ + if (ctx == NULL) + return; + + if (ctx->my_certs != NULL) + sk_X509_pop_free(ctx->my_certs, X509_free); + + if (ctx->my_key != NULL) + EVP_PKEY_free(ctx->my_key); + + if (ctx->trustedCAs != NULL) + sk_X509_pop_free(ctx->trustedCAs, X509_free); + + if (ctx->intermediateCAs != NULL) + sk_X509_pop_free(ctx->intermediateCAs, X509_free); + + if (ctx->revoked != NULL) + sk_X509_CRL_pop_free(ctx->revoked, X509_CRL_free); +} + +static krb5_error_code +pkinit_init_pkcs11(pkinit_identity_crypto_context ctx) +{ + krb5_error_code retval = ENOMEM; + +#ifndef WITHOUT_PKCS11 + ctx->p11_module_name = strdup(PKCS11_MODNAME); + if (ctx->p11_module_name == NULL) + return retval; + ctx->p11_module = NULL; + ctx->slotid = PK_NOSLOT; + ctx->token_label = NULL; + ctx->cert_label = NULL; + ctx->session = CK_INVALID_HANDLE; + ctx->p11 = NULL; +#endif + ctx->pkcs11_method = 0; + + retval = 0; + return retval; +} + +static void +pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx) +{ +#ifndef WITHOUT_PKCS11 + if (ctx == NULL) + return; + + if (ctx->p11 != NULL) { + if (ctx->session != CK_INVALID_HANDLE) { + ctx->p11->C_CloseSession(ctx->session); + ctx->session = CK_INVALID_HANDLE; + } + ctx->p11->C_Finalize(NULL_PTR); + ctx->p11 = NULL; + } + if (ctx->p11_module != NULL) { + krb5int_close_plugin(ctx->p11_module); + ctx->p11_module = NULL; + } + free(ctx->p11_module_name); + free(ctx->token_label); + free(ctx->cert_id); + free(ctx->cert_label); +#endif +} + +krb5_error_code +pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx, + krb5_prompter_fct prompter, + void *prompter_data) +{ + id_cryptoctx->prompter = prompter; + id_cryptoctx->prompter_data = prompter_data; + + return 0; +} + +/* Create a CMS ContentInfo of type oid containing the octet string in data. */ +static krb5_error_code +create_contentinfo(krb5_context context, ASN1_OBJECT *oid, + unsigned char *data, size_t data_len, PKCS7 **p7_out) +{ + PKCS7 *p7 = NULL; + ASN1_OCTET_STRING *ostr = NULL; + + *p7_out = NULL; + + ostr = ASN1_OCTET_STRING_new(); + if (ostr == NULL) + goto oom; + if (!ASN1_OCTET_STRING_set(ostr, (unsigned char *)data, data_len)) + goto oom; + + p7 = PKCS7_new(); + if (p7 == NULL) + goto oom; + p7->type = OBJ_dup(oid); + if (p7->type == NULL) + goto oom; + + p7->d.other = ASN1_TYPE_new(); + if (p7->d.other == NULL) + goto oom; + p7->d.other->type = V_ASN1_OCTET_STRING; + p7->d.other->value.octet_string = ostr; + + *p7_out = p7; + return 0; + +oom: + if (ostr != NULL) + ASN1_OCTET_STRING_free(ostr); + if (p7 != NULL) + PKCS7_free(p7); + return ENOMEM; +} + +krb5_error_code +cms_contentinfo_create(krb5_context context, /* IN */ + pkinit_plg_crypto_context plg_cryptoctx, /* IN */ + pkinit_req_crypto_context req_cryptoctx, /* IN */ + pkinit_identity_crypto_context id_cryptoctx, /* IN */ + int cms_msg_type, + unsigned char *data, unsigned int data_len, + unsigned char **out_data, unsigned int *out_data_len) +{ + krb5_error_code retval = ENOMEM; + ASN1_OBJECT *oid; + PKCS7 *p7 = NULL; + unsigned char *p; + + /* Pick the correct oid for the eContentInfo. */ + oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type); + if (oid == NULL) + goto cleanup; + retval = create_contentinfo(context, oid, data, data_len, &p7); + if (retval != 0) + goto cleanup; + *out_data_len = i2d_PKCS7(p7, NULL); + if (!(*out_data_len)) { + retval = oerr(context, 0, _("Failed to DER encode PKCS7")); + goto cleanup; + } + retval = ENOMEM; + if ((p = *out_data = malloc(*out_data_len)) == NULL) + goto cleanup; + + /* DER encode PKCS7 data */ + retval = i2d_PKCS7(p7, &p); + if (!retval) { + retval = oerr(context, 0, _("Failed to DER encode PKCS7")); + goto cleanup; + } + retval = 0; +cleanup: + if (p7) + PKCS7_free(p7); + return retval; +} + + + +krb5_error_code +cms_signeddata_create(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + int cms_msg_type, + unsigned char *data, + unsigned int data_len, + unsigned char **signed_data, + unsigned int *signed_data_len) +{ + krb5_error_code retval = ENOMEM; + PKCS7 *p7 = NULL, *inner_p7 = NULL; + PKCS7_SIGNED *p7s = NULL; + PKCS7_SIGNER_INFO *p7si = NULL; + unsigned char *p; + STACK_OF(X509) * cert_stack = NULL; + ASN1_OCTET_STRING *digest_attr = NULL; + EVP_MD_CTX *ctx; + const EVP_MD *md_tmp = NULL; + unsigned char md_data[EVP_MAX_MD_SIZE], md_data2[EVP_MAX_MD_SIZE]; + unsigned char *digestInfo_buf = NULL, *abuf = NULL; + unsigned int md_len, md_len2, alen, digestInfo_len; + STACK_OF(X509_ATTRIBUTE) * sk; + unsigned char *sig = NULL; + unsigned int sig_len = 0; + X509_ALGOR *alg = NULL; + ASN1_OCTET_STRING *digest = NULL; + unsigned int alg_len = 0, digest_len = 0; + unsigned char *y = NULL; + X509 *cert = NULL; + ASN1_OBJECT *oid = NULL, *oid_copy; + + /* Start creating PKCS7 data. */ + if ((p7 = PKCS7_new()) == NULL) + goto cleanup; + p7->type = OBJ_nid2obj(NID_pkcs7_signed); + + if ((p7s = PKCS7_SIGNED_new()) == NULL) + goto cleanup; + p7->d.sign = p7s; + if (!ASN1_INTEGER_set(p7s->version, 3)) + goto cleanup; + + /* pick the correct oid for the eContentInfo */ + oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type); + if (oid == NULL) + goto cleanup; + + if (id_cryptoctx->my_certs != NULL) { + X509_STORE *certstore = NULL; + X509_STORE_CTX *certctx; + STACK_OF(X509) *certstack = NULL; + char buf[DN_BUF_LEN]; + unsigned int i = 0, size = 0; + + /* create a cert chain */ + if ((cert_stack = sk_X509_new_null()) == NULL) + goto cleanup; + + cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index); + + certstore = X509_STORE_new(); + if (certstore == NULL) + goto cleanup; + pkiDebug("building certificate chain\n"); + X509_STORE_set_verify_cb(certstore, openssl_callback); + certctx = X509_STORE_CTX_new(); + if (certctx == NULL) + goto cleanup; + X509_STORE_CTX_init(certctx, certstore, cert, + id_cryptoctx->intermediateCAs); + X509_STORE_CTX_trusted_stack(certctx, id_cryptoctx->trustedCAs); + if (!X509_verify_cert(certctx)) { + retval = oerr_cert(context, 0, certctx, + _("Failed to verify own certificate")); + goto cleanup; + } + certstack = X509_STORE_CTX_get1_chain(certctx); + size = sk_X509_num(certstack); + for (i = 0; i < size - 1; i++) { + X509 *x = sk_X509_value(certstack, i); + X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf)); + TRACE_PKINIT_CERT_CHAIN_NAME(context, (int)i, buf); + sk_X509_push(cert_stack, X509_dup(x)); + } + X509_STORE_CTX_free(certctx); + X509_STORE_free(certstore); + sk_X509_pop_free(certstack, X509_free); + + p7s->cert = cert_stack; + + /* fill-in PKCS7_SIGNER_INFO */ + if ((p7si = PKCS7_SIGNER_INFO_new()) == NULL) + goto cleanup; + if (!ASN1_INTEGER_set(p7si->version, 1)) + goto cleanup; + if (!X509_NAME_set(&p7si->issuer_and_serial->issuer, + X509_get_issuer_name(cert))) + goto cleanup; + /* because ASN1_INTEGER_set is used to set a 'long' we will do + * things the ugly way. */ + ASN1_INTEGER_free(p7si->issuer_and_serial->serial); + if (!(p7si->issuer_and_serial->serial = + ASN1_INTEGER_dup(X509_get_serialNumber(cert)))) + goto cleanup; + + /* will not fill-out EVP_PKEY because it's on the smartcard */ + + /* Set digest algs */ + p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha256); + + if (p7si->digest_alg->parameter != NULL) + ASN1_TYPE_free(p7si->digest_alg->parameter); + if ((p7si->digest_alg->parameter = ASN1_TYPE_new()) == NULL) + goto cleanup; + p7si->digest_alg->parameter->type = V_ASN1_NULL; + + /* Set sig algs */ + if (p7si->digest_enc_alg->parameter != NULL) + ASN1_TYPE_free(p7si->digest_enc_alg->parameter); + p7si->digest_enc_alg->algorithm = + OBJ_nid2obj(NID_sha256WithRSAEncryption); + if (!(p7si->digest_enc_alg->parameter = ASN1_TYPE_new())) + goto cleanup; + p7si->digest_enc_alg->parameter->type = V_ASN1_NULL; + + /* add signed attributes */ + /* compute sha256 digest over the EncapsulatedContentInfo */ + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + goto cleanup; + EVP_DigestInit_ex(ctx, EVP_sha256(), NULL); + EVP_DigestUpdate(ctx, data, data_len); + md_tmp = EVP_MD_CTX_get0_md(ctx); + EVP_DigestFinal_ex(ctx, md_data, &md_len); + EVP_MD_CTX_free(ctx); + + /* create a message digest attr */ + digest_attr = ASN1_OCTET_STRING_new(); + ASN1_OCTET_STRING_set(digest_attr, md_data, (int)md_len); + PKCS7_add_signed_attribute(p7si, NID_pkcs9_messageDigest, + V_ASN1_OCTET_STRING, (char *)digest_attr); + + /* create a content-type attr */ + oid_copy = OBJ_dup(oid); + if (oid_copy == NULL) + goto cleanup2; + PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType, + V_ASN1_OBJECT, oid_copy); + + /* create the signature over signed attributes. get DER encoded value */ + /* This is the place where smartcard signature needs to be calculated */ + sk = p7si->auth_attr; + alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, + ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); + if (abuf == NULL) + goto cleanup2; + +#ifndef WITHOUT_PKCS11 + /* + * Some tokens can only do RSAEncryption without a hash. To compute + * sha256WithRSAEncryption, encode the algorithm ID for the hash + * function and the hash value into an ASN.1 value of type DigestInfo: + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ + if (id_cryptoctx->pkcs11_method == 1 && + id_cryptoctx->mech == CKM_RSA_PKCS) { + pkiDebug("mech = CKM_RSA_PKCS\n"); + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + goto cleanup; + EVP_DigestInit_ex(ctx, md_tmp, NULL); + EVP_DigestUpdate(ctx, abuf, alen); + EVP_DigestFinal_ex(ctx, md_data2, &md_len2); + EVP_MD_CTX_free(ctx); + + alg = X509_ALGOR_new(); + if (alg == NULL) + goto cleanup2; + X509_ALGOR_set0(alg, OBJ_nid2obj(NID_sha256), V_ASN1_NULL, NULL); + alg_len = i2d_X509_ALGOR(alg, NULL); + + digest = ASN1_OCTET_STRING_new(); + if (digest == NULL) + goto cleanup2; + ASN1_OCTET_STRING_set(digest, md_data2, (int)md_len2); + digest_len = i2d_ASN1_OCTET_STRING(digest, NULL); + + digestInfo_len = ASN1_object_size(1, (int)(alg_len + digest_len), + V_ASN1_SEQUENCE); + y = digestInfo_buf = malloc(digestInfo_len); + if (digestInfo_buf == NULL) + goto cleanup2; + ASN1_put_object(&y, 1, (int)(alg_len + digest_len), V_ASN1_SEQUENCE, + V_ASN1_UNIVERSAL); + i2d_X509_ALGOR(alg, &y); + i2d_ASN1_OCTET_STRING(digest, &y); +#ifdef DEBUG_SIG + pkiDebug("signing buffer\n"); + print_buffer(digestInfo_buf, digestInfo_len); + print_buffer_bin(digestInfo_buf, digestInfo_len, "/tmp/pkcs7_tosign"); +#endif + retval = pkinit_sign_data(context, id_cryptoctx, digestInfo_buf, + digestInfo_len, &sig, &sig_len); + } else +#endif + { + pkiDebug("mech = %s\n", + id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA256_RSA_PKCS" : "FS"); + retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen, + &sig, &sig_len); + } +#ifdef DEBUG_SIG + print_buffer(sig, sig_len); +#endif + free(abuf); + if (retval) + goto cleanup2; + + /* Add signature */ + if (!ASN1_STRING_set(p7si->enc_digest, (unsigned char *) sig, + (int)sig_len)) { + retval = oerr(context, 0, _("Failed to add digest attribute")); + goto cleanup2; + } + /* adder signer_info to pkcs7 signed */ + if (!PKCS7_add_signer(p7, p7si)) + goto cleanup2; + } /* we have a certificate */ + + /* start on adding data to the pkcs7 signed */ + retval = create_contentinfo(context, oid, data, data_len, &inner_p7); + if (p7s->contents != NULL) + PKCS7_free(p7s->contents); + p7s->contents = inner_p7; + + *signed_data_len = i2d_PKCS7(p7, NULL); + if (!(*signed_data_len)) { + retval = oerr(context, 0, _("Failed to DER encode PKCS7")); + goto cleanup2; + } + retval = ENOMEM; + if ((p = *signed_data = malloc(*signed_data_len)) == NULL) + goto cleanup2; + + /* DER encode PKCS7 data */ + retval = i2d_PKCS7(p7, &p); + if (!retval) { + retval = oerr(context, 0, _("Failed to DER encode PKCS7")); + goto cleanup2; + } + retval = 0; + +#ifdef DEBUG_ASN1 + if (cms_msg_type == CMS_SIGN_CLIENT) { + print_buffer_bin(*signed_data, *signed_data_len, + "/tmp/client_pkcs7_signeddata"); + } else { + print_buffer_bin(*signed_data, *signed_data_len, + "/tmp/kdc_pkcs7_signeddata"); + } +#endif + +cleanup2: + if (p7si) { +#ifndef WITHOUT_PKCS11 + if (id_cryptoctx->pkcs11_method == 1 && + id_cryptoctx->mech == CKM_RSA_PKCS) { + free(digestInfo_buf); + if (digest != NULL) + ASN1_OCTET_STRING_free(digest); + } +#endif + if (alg != NULL) + X509_ALGOR_free(alg); + } +cleanup: + if (p7 != NULL) + PKCS7_free(p7); + free(sig); + + return retval; +} + +krb5_error_code +cms_signeddata_verify(krb5_context context, + pkinit_plg_crypto_context plgctx, + pkinit_req_crypto_context reqctx, + pkinit_identity_crypto_context idctx, + int cms_msg_type, + int require_crl_checking, + unsigned char *signed_data, + unsigned int signed_data_len, + unsigned char **data, + unsigned int *data_len, + unsigned char **authz_data, + unsigned int *authz_data_len, + int *is_signed) +{ + /* + * Warning: Since most openssl functions do not set retval, large chunks of + * this function assume that retval is always a failure and may go to + * cleanup without setting retval explicitly. Make sure retval is not set + * to 0 or errors such as signature verification failure may be converted + * to success with significant security consequences. + */ + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + CMS_ContentInfo *cms = NULL; + BIO *out = NULL; + int flags = CMS_NO_SIGNER_CERT_VERIFY; + int valid_oid = 0; + unsigned int i = 0; + unsigned int vflags = 0, size = 0; + const unsigned char *p = signed_data; + STACK_OF(CMS_SignerInfo) *si_sk = NULL; + CMS_SignerInfo *si = NULL; + X509 *x = NULL; + X509_STORE *store = NULL; + X509_STORE_CTX *cert_ctx; + STACK_OF(X509) *signerCerts = NULL; + STACK_OF(X509) *intermediateCAs = NULL; + STACK_OF(X509_CRL) *signerRevoked = NULL; + STACK_OF(X509_CRL) *revoked = NULL; + STACK_OF(X509) *verified_chain = NULL; + ASN1_OBJECT *oid = NULL; + const ASN1_OBJECT *type = NULL, *etype = NULL; + ASN1_OCTET_STRING **octets; + krb5_external_principal_identifier **krb5_verified_chain = NULL; + krb5_data *authz = NULL; + char buf[DN_BUF_LEN]; + +#ifdef DEBUG_ASN1 + print_buffer_bin(signed_data, signed_data_len, + "/tmp/client_received_pkcs7_signeddata"); +#endif + if (is_signed) + *is_signed = 1; + + oid = pkinit_pkcs7type2oid(plgctx, cms_msg_type); + if (oid == NULL) + goto cleanup; + + /* decode received CMS message */ + if ((cms = d2i_CMS_ContentInfo(NULL, &p, (int)signed_data_len)) == NULL) { + retval = oerr(context, 0, _("Failed to decode CMS message")); + goto cleanup; + } + etype = CMS_get0_eContentType(cms); + + /* + * Prior to 1.10 the MIT client incorrectly emitted the pkinit structure + * directly in a CMS ContentInfo rather than using SignedData with no + * signers. Handle that case. + */ + type = CMS_get0_type(cms); + if (is_signed && !OBJ_cmp(type, oid)) { + unsigned char *d; + *is_signed = 0; + octets = CMS_get0_content(cms); + if (!octets || ((*octets)->type != V_ASN1_OCTET_STRING)) { + retval = KRB5KDC_ERR_PREAUTH_FAILED; + krb5_set_error_message(context, retval, + _("Invalid pkinit packet: octet string " + "expected")); + goto cleanup; + } + *data_len = ASN1_STRING_length(*octets); + d = malloc(*data_len); + if (d == NULL) { + retval = ENOMEM; + goto cleanup; + } + memcpy(d, ASN1_STRING_get0_data(*octets), *data_len); + *data = d; + goto out; + } else { + /* Verify that the received message is CMS SignedData message. */ + if (OBJ_obj2nid(type) != NID_pkcs7_signed) { + pkiDebug("Expected id-signedData CMS msg (received type = %d)\n", + OBJ_obj2nid(type)); + krb5_set_error_message(context, retval, _("wrong oid\n")); + goto cleanup; + } + } + + /* setup to verify X509 certificate used to sign CMS message */ + if (!(store = X509_STORE_new())) + goto cleanup; + + /* check if we are inforcing CRL checking */ + vflags = X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL; + if (require_crl_checking) + X509_STORE_set_verify_cb(store, openssl_callback); + else + X509_STORE_set_verify_cb(store, openssl_callback_ignore_crls); + X509_STORE_set_flags(store, vflags); + + /* + * Get the signer's information from the CMS message. Match signer ID + * against anchors and intermediate CAs in case no certs are present in the + * SignedData. If we start sending kdcPkId values in requests, we'll need + * to match against the source of that information too. + */ + CMS_set1_signers_certs(cms, NULL, 0); + CMS_set1_signers_certs(cms, idctx->trustedCAs, CMS_NOINTERN); + CMS_set1_signers_certs(cms, idctx->intermediateCAs, CMS_NOINTERN); + if (((si_sk = CMS_get0_SignerInfos(cms)) == NULL) || + ((si = sk_CMS_SignerInfo_value(si_sk, 0)) == NULL)) { + /* Not actually signed; anonymous case */ + if (!is_signed) + goto cleanup; + *is_signed = 0; + /* We cannot use CMS_dataInit because there may be no digest */ + octets = CMS_get0_content(cms); + if (octets) + out = BIO_new_mem_buf((*octets)->data, (*octets)->length); + if (out == NULL) + goto cleanup; + } else { + CMS_SignerInfo_get0_algs(si, NULL, &x, NULL, NULL); + if (x == NULL) + goto cleanup; + + /* create available CRL information (get local CRLs and include CRLs + * received in the CMS message + */ + signerRevoked = CMS_get1_crls(cms); + if (idctx->revoked == NULL) + revoked = signerRevoked; + else if (signerRevoked == NULL) + revoked = idctx->revoked; + else { + size = sk_X509_CRL_num(idctx->revoked); + revoked = sk_X509_CRL_new_null(); + for (i = 0; i < size; i++) + sk_X509_CRL_push(revoked, sk_X509_CRL_value(idctx->revoked, i)); + size = sk_X509_CRL_num(signerRevoked); + for (i = 0; i < size; i++) + sk_X509_CRL_push(revoked, sk_X509_CRL_value(signerRevoked, i)); + } + + /* create available intermediate CAs chains (get local intermediateCAs and + * include the CA chain received in the CMS message + */ + signerCerts = CMS_get1_certs(cms); + if (idctx->intermediateCAs == NULL) + intermediateCAs = signerCerts; + else if (signerCerts == NULL) + intermediateCAs = idctx->intermediateCAs; + else { + size = sk_X509_num(idctx->intermediateCAs); + intermediateCAs = sk_X509_new_null(); + for (i = 0; i < size; i++) { + sk_X509_push(intermediateCAs, + sk_X509_value(idctx->intermediateCAs, i)); + } + size = sk_X509_num(signerCerts); + for (i = 0; i < size; i++) { + sk_X509_push(intermediateCAs, sk_X509_value(signerCerts, i)); + } + } + + /* initialize x509 context with the received certificate and + * trusted and intermediate CA chains and CRLs + */ + cert_ctx = X509_STORE_CTX_new(); + if (cert_ctx == NULL) + goto cleanup; + if (!X509_STORE_CTX_init(cert_ctx, store, x, intermediateCAs)) + goto cleanup; + + X509_STORE_CTX_set0_crls(cert_ctx, revoked); + + /* add trusted CAs certificates for cert verification */ + if (idctx->trustedCAs != NULL) + X509_STORE_CTX_trusted_stack(cert_ctx, idctx->trustedCAs); + else { + pkiDebug("unable to find any trusted CAs\n"); + goto cleanup; + } +#ifdef DEBUG_CERTCHAIN + if (intermediateCAs != NULL) { + size = sk_X509_num(intermediateCAs); + pkiDebug("untrusted cert chain of size %d\n", size); + for (i = 0; i < size; i++) { + X509_NAME_oneline(X509_get_subject_name( + sk_X509_value(intermediateCAs, i)), buf, sizeof(buf)); + pkiDebug("cert #%d: %s\n", i, buf); + } + } + if (idctx->trustedCAs != NULL) { + size = sk_X509_num(idctx->trustedCAs); + pkiDebug("trusted cert chain of size %d\n", size); + for (i = 0; i < size; i++) { + X509_NAME_oneline(X509_get_subject_name( + sk_X509_value(idctx->trustedCAs, i)), buf, sizeof(buf)); + pkiDebug("cert #%d: %s\n", i, buf); + } + } + if (revoked != NULL) { + size = sk_X509_CRL_num(revoked); + pkiDebug("CRL chain of size %d\n", size); + for (i = 0; i < size; i++) { + X509_CRL *crl = sk_X509_CRL_value(revoked, i); + X509_NAME_oneline(X509_CRL_get_issuer(crl), buf, sizeof(buf)); + pkiDebug("crls by CA #%d: %s\n", i , buf); + } + } +#endif + + i = X509_verify_cert(cert_ctx); + if (i <= 0) { + int j = X509_STORE_CTX_get_error(cert_ctx); + X509 *cert; + + cert = X509_STORE_CTX_get_current_cert(cert_ctx); + reqctx->received_cert = X509_dup(cert); + switch(j) { + case X509_V_ERR_CERT_REVOKED: + retval = KRB5KDC_ERR_REVOKED_CERTIFICATE; + break; + case X509_V_ERR_UNABLE_TO_GET_CRL: + retval = KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN; + break; + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + retval = KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE; + break; + default: + retval = KRB5KDC_ERR_INVALID_CERTIFICATE; + } + (void)oerr_cert(context, retval, cert_ctx, + _("Failed to verify received certificate")); + if (reqctx->received_cert == NULL) + strlcpy(buf, "(none)", sizeof(buf)); + else + X509_NAME_oneline(X509_get_subject_name(reqctx->received_cert), + buf, sizeof(buf)); + pkiDebug("problem with cert DN = %s (error=%d) %s\n", buf, j, + X509_verify_cert_error_string(j)); +#ifdef DEBUG_CERTCHAIN + size = sk_X509_num(signerCerts); + pkiDebug("received cert chain of size %d\n", size); + for (j = 0; j < size; j++) { + X509 *tmp_cert = sk_X509_value(signerCerts, j); + X509_NAME_oneline(X509_get_subject_name(tmp_cert), buf, sizeof(buf)); + pkiDebug("cert #%d: %s\n", j, buf); + } +#endif + } else { + /* retrieve verified certificate chain */ + if (cms_msg_type == CMS_SIGN_CLIENT) + verified_chain = X509_STORE_CTX_get1_chain(cert_ctx); + } + X509_STORE_CTX_free(cert_ctx); + if (i <= 0) + goto cleanup; + out = BIO_new(BIO_s_mem()); + if (CMS_verify(cms, NULL, store, NULL, out, flags) == 0) { + if (ERR_peek_last_error() == CMS_R_VERIFICATION_FAILURE) + retval = KRB5KDC_ERR_INVALID_SIG; + else + retval = KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED; + (void)oerr(context, retval, _("Failed to verify CMS message")); + goto cleanup; + } + } /* message was signed */ + if (!OBJ_cmp(etype, oid)) + valid_oid = 1; + + if (valid_oid) + pkiDebug("CMS Verification successful\n"); + else { + pkiDebug("wrong oid in eContentType\n"); + print_buffer(OBJ_get0_data(etype), OBJ_length(etype)); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + krb5_set_error_message(context, retval, "wrong oid\n"); + goto cleanup; + } + + /* transfer the data from CMS message into return buffer */ + for (size = 0;;) { + int remain; + retval = ENOMEM; + if ((*data = realloc(*data, size + 1024 * 10)) == NULL) + goto cleanup; + remain = BIO_read(out, &((*data)[size]), 1024 * 10); + if (remain <= 0) + break; + else + size += remain; + } + *data_len = size; + + if (x) { + reqctx->received_cert = X509_dup(x); + + /* generate authorization data */ + if (cms_msg_type == CMS_SIGN_CLIENT) { + + if (authz_data == NULL || authz_data_len == NULL) + goto out; + + *authz_data = NULL; + retval = create_identifiers_from_stack(verified_chain, + &krb5_verified_chain); + if (retval) { + pkiDebug("create_identifiers_from_stack failed\n"); + goto cleanup; + } + + retval = k5int_encode_krb5_td_trusted_certifiers((krb5_external_principal_identifier *const *)krb5_verified_chain, &authz); + if (retval) { + pkiDebug("encode_krb5_td_trusted_certifiers failed\n"); + goto cleanup; + } +#ifdef DEBUG_ASN1 + print_buffer_bin((unsigned char *)authz->data, authz->length, + "/tmp/kdc_ad_initial_verified_cas"); +#endif + *authz_data = malloc(authz->length); + if (*authz_data == NULL) { + retval = ENOMEM; + goto cleanup; + } + memcpy(*authz_data, authz->data, authz->length); + *authz_data_len = authz->length; + } + } +out: + retval = 0; + +cleanup: + if (out != NULL) + BIO_free(out); + if (store != NULL) + X509_STORE_free(store); + if (cms != NULL) { + if (signerCerts != NULL) + sk_X509_pop_free(signerCerts, X509_free); + if (idctx->intermediateCAs != NULL && signerCerts) + sk_X509_free(intermediateCAs); + if (signerRevoked != NULL) + sk_X509_CRL_pop_free(signerRevoked, X509_CRL_free); + if (idctx->revoked != NULL && signerRevoked) + sk_X509_CRL_free(revoked); + CMS_ContentInfo_free(cms); + } + if (verified_chain != NULL) + sk_X509_pop_free(verified_chain, X509_free); + if (krb5_verified_chain != NULL) + free_krb5_external_principal_identifier(&krb5_verified_chain); + if (authz != NULL) + krb5_free_data(context, authz); + + return retval; +} + +krb5_error_code +cms_envelopeddata_create(krb5_context context, + pkinit_plg_crypto_context plgctx, + pkinit_req_crypto_context reqctx, + pkinit_identity_crypto_context idctx, + krb5_preauthtype pa_type, + unsigned char *key_pack, + unsigned int key_pack_len, + unsigned char **out, + unsigned int *out_len) +{ + + krb5_error_code retval = ENOMEM; + PKCS7 *p7 = NULL; + BIO *in = NULL; + unsigned char *p = NULL, *signed_data = NULL, *enc_data = NULL; + int signed_data_len = 0, enc_data_len = 0, flags = PKCS7_BINARY; + STACK_OF(X509) *encerts = NULL; + const EVP_CIPHER *cipher = NULL; + + retval = cms_signeddata_create(context, plgctx, reqctx, idctx, + CMS_ENVEL_SERVER, key_pack, key_pack_len, + &signed_data, + (unsigned int *)&signed_data_len); + if (retval) { + pkiDebug("failed to create pkcs7 signed data\n"); + goto cleanup; + } + + /* check we have client's certificate */ + if (reqctx->received_cert == NULL) { + retval = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + encerts = sk_X509_new_null(); + sk_X509_push(encerts, reqctx->received_cert); + + cipher = EVP_des_ede3_cbc(); + in = BIO_new(BIO_s_mem()); + prepare_enc_data(signed_data, signed_data_len, &enc_data, + &enc_data_len); + retval = BIO_write(in, enc_data, enc_data_len); + if (retval != enc_data_len) { + pkiDebug("BIO_write only wrote %d\n", retval); + goto cleanup; + } + + p7 = PKCS7_encrypt(encerts, in, cipher, flags); + if (p7 == NULL) { + retval = oerr(context, 0, _("Failed to encrypt PKCS7 object")); + goto cleanup; + } + p7->d.enveloped->enc_data->content_type = OBJ_nid2obj(NID_pkcs7_signed); + + *out_len = i2d_PKCS7(p7, NULL); + if (!*out_len || (p = *out = malloc(*out_len)) == NULL) { + retval = ENOMEM; + goto cleanup; + } + retval = i2d_PKCS7(p7, &p); + if (!retval) { + retval = oerr(context, 0, _("Failed to DER encode PKCS7")); + goto cleanup; + } + retval = 0; + +#ifdef DEBUG_ASN1 + print_buffer_bin(*out, *out_len, "/tmp/kdc_enveloped_data"); +#endif + +cleanup: + if (p7 != NULL) + PKCS7_free(p7); + if (in != NULL) + BIO_free(in); + free(signed_data); + free(enc_data); + if (encerts != NULL) + sk_X509_free(encerts); + + return retval; +} + +krb5_error_code +cms_envelopeddata_verify(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_preauthtype pa_type, + int require_crl_checking, + unsigned char *enveloped_data, + unsigned int enveloped_data_len, + unsigned char **data, + unsigned int *data_len) +{ + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + PKCS7 *p7 = NULL; + const unsigned char *p = enveloped_data; + unsigned int tmp_buf_len = 0, tmp_buf2_len = 0, vfy_buf_len = 0; + unsigned char *tmp_buf = NULL, *tmp_buf2 = NULL, *vfy_buf = NULL; + +#ifdef DEBUG_ASN1 + print_buffer_bin(enveloped_data, enveloped_data_len, + "/tmp/client_envelopeddata"); +#endif + /* decode received PKCS7 message */ + if ((p7 = d2i_PKCS7(NULL, &p, (int)enveloped_data_len)) == NULL) { + retval = oerr(context, 0, _("Failed to decode PKCS7")); + goto cleanup; + } + + /* verify that the received message is PKCS7 EnvelopedData message */ + if (OBJ_obj2nid(p7->type) != NID_pkcs7_enveloped || + p7->d.enveloped == NULL || + p7->d.enveloped->enc_data->enc_data == NULL) { + pkiDebug("Expected id-enveloped PKCS7 msg (received type = %d)\n", + OBJ_obj2nid(p7->type)); + krb5_set_error_message(context, retval, "wrong oid\n"); + goto cleanup; + } + + /* decrypt received PKCS7 message */ + if (pkcs7_decrypt(context, id_cryptoctx, p7, &tmp_buf, &tmp_buf_len)) { + pkiDebug("PKCS7 decryption successful\n"); + } else { + retval = oerr(context, 0, _("Failed to decrypt PKCS7 message")); + goto cleanup; + } + +#ifdef DEBUG_ASN1 + print_buffer_bin(tmp_buf, tmp_buf_len, "/tmp/client_enc_keypack"); +#endif + /* verify PKCS7 SignedData message */ + /* Wrap the signed data to make decoding easier in the verify routine. */ + retval = wrap_signeddata(tmp_buf, tmp_buf_len, &tmp_buf2, &tmp_buf2_len); + if (retval) { + pkiDebug("failed to encode signeddata\n"); + goto cleanup; + } + vfy_buf = tmp_buf2; + vfy_buf_len = tmp_buf2_len; + +#ifdef DEBUG_ASN1 + print_buffer_bin(vfy_buf, vfy_buf_len, "/tmp/client_enc_keypack2"); +#endif + + retval = cms_signeddata_verify(context, plg_cryptoctx, req_cryptoctx, + id_cryptoctx, CMS_ENVEL_SERVER, + require_crl_checking, + vfy_buf, vfy_buf_len, + data, data_len, NULL, NULL, NULL); + + if (!retval) + pkiDebug("PKCS7 Verification Success\n"); + else { + pkiDebug("PKCS7 Verification Failure\n"); + goto cleanup; + } + + retval = 0; + +cleanup: + + if (p7 != NULL) + PKCS7_free(p7); + free(tmp_buf); + free(tmp_buf2); + + return retval; +} + +static krb5_error_code +crypto_retrieve_X509_sans(krb5_context context, + pkinit_plg_crypto_context plgctx, + pkinit_req_crypto_context reqctx, + X509 *cert, + krb5_principal **princs_ret, char ***upn_ret, + unsigned char ***dns_ret) +{ + krb5_error_code retval = EINVAL; + char buf[DN_BUF_LEN]; + int p = 0, u = 0, d = 0, ret = 0, l; + krb5_principal *princs = NULL; + char **upns = NULL; + unsigned char **dnss = NULL; + unsigned int i, num_sans = 0; + X509_EXTENSION *ext = NULL; + GENERAL_NAMES *ialt = NULL; + GENERAL_NAME *gen = NULL; + + if (princs_ret != NULL) + *princs_ret = NULL; + if (upn_ret != NULL) + *upn_ret = NULL; + if (dns_ret != NULL) + *dns_ret = NULL; + + if (princs_ret == NULL && upn_ret == NULL && dns_ret == NULL) { + pkiDebug("%s: nowhere to return any values!\n", __FUNCTION__); + return retval; + } + + if (cert == NULL) { + pkiDebug("%s: no certificate!\n", __FUNCTION__); + return retval; + } + + X509_NAME_oneline(X509_get_subject_name(cert), + buf, sizeof(buf)); + + l = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1); + if (l < 0) + return 0; + + if (!(ext = X509_get_ext(cert, l)) || !(ialt = X509V3_EXT_d2i(ext))) { + TRACE_PKINIT_SAN_CERT_NONE(context, buf); + goto cleanup; + } + num_sans = sk_GENERAL_NAME_num(ialt); + + /* OK, we're likely returning something. Allocate return values */ + if (princs_ret != NULL) { + princs = calloc(num_sans + 1, sizeof(krb5_principal)); + if (princs == NULL) { + retval = ENOMEM; + goto cleanup; + } + } + if (upn_ret != NULL) { + upns = calloc(num_sans + 1, sizeof(*upns)); + if (upns == NULL) { + retval = ENOMEM; + goto cleanup; + } + } + if (dns_ret != NULL) { + dnss = calloc(num_sans + 1, sizeof(*dnss)); + if (dnss == NULL) { + retval = ENOMEM; + goto cleanup; + } + } + + for (i = 0; i < num_sans; i++) { + krb5_data name = { 0, 0, NULL }; + + gen = sk_GENERAL_NAME_value(ialt, i); + switch (gen->type) { + case GEN_OTHERNAME: + name.length = gen->d.otherName->value->value.sequence->length; + name.data = (char *)gen->d.otherName->value->value.sequence->data; + if (princs != NULL && + OBJ_cmp(plgctx->id_pkinit_san, + gen->d.otherName->type_id) == 0) { +#ifdef DEBUG_ASN1 + print_buffer_bin((unsigned char *)name.data, name.length, + "/tmp/pkinit_san"); +#endif + ret = k5int_decode_krb5_principal_name(&name, &princs[p]); + if (ret) { + pkiDebug("%s: failed decoding pkinit san value\n", + __FUNCTION__); + } else { + p++; + } + } else if (upns != NULL && + OBJ_cmp(plgctx->id_ms_san_upn, + gen->d.otherName->type_id) == 0) { + /* Prevent abuse of embedded null characters. */ + if (memchr(name.data, '\0', name.length)) + break; + upns[u] = k5memdup0(name.data, name.length, &ret); + if (upns[u] == NULL) + goto cleanup; + u++; + } else { + pkiDebug("%s: unrecognized othername oid in SAN\n", + __FUNCTION__); + continue; + } + + break; + case GEN_DNS: + if (dnss != NULL) { + /* Prevent abuse of embedded null characters. */ + if (memchr(gen->d.dNSName->data, '\0', gen->d.dNSName->length)) + break; + pkiDebug("%s: found dns name = %s\n", __FUNCTION__, + gen->d.dNSName->data); + dnss[d] = (unsigned char *) + strdup((char *)gen->d.dNSName->data); + if (dnss[d] == NULL) { + pkiDebug("%s: failed to duplicate dns name\n", + __FUNCTION__); + } else { + d++; + } + } + break; + default: + pkiDebug("%s: SAN type = %d expecting %d\n", __FUNCTION__, + gen->type, GEN_OTHERNAME); + } + } + sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free); + + TRACE_PKINIT_SAN_CERT_COUNT(context, (int)num_sans, p, u, d, buf); + + retval = 0; + if (princs != NULL && *princs != NULL) { + *princs_ret = princs; + princs = NULL; + } + if (upns != NULL && *upns != NULL) { + *upn_ret = upns; + upns = NULL; + } + if (dnss != NULL && *dnss != NULL) { + *dns_ret = dnss; + dnss = NULL; + } + +cleanup: + for (i = 0; princs != NULL && princs[i] != NULL; i++) + krb5_free_principal(context, princs[i]); + free(princs); + for (i = 0; upns != NULL && upns[i] != NULL; i++) + free(upns[i]); + free(upns); + for (i = 0; dnss != NULL && dnss[i] != NULL; i++) + free(dnss[i]); + free(dnss); + return retval; +} + +krb5_error_code +crypto_retrieve_signer_identity(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, + const char **identity) +{ + *identity = id_cryptoctx->identity; + if (*identity == NULL) + return ENOENT; + return 0; +} + +krb5_error_code +crypto_retrieve_cert_sans(krb5_context context, + pkinit_plg_crypto_context plgctx, + pkinit_req_crypto_context reqctx, + pkinit_identity_crypto_context idctx, + krb5_principal **princs_ret, char ***upn_ret, + unsigned char ***dns_ret) +{ + krb5_error_code retval = EINVAL; + + if (reqctx->received_cert == NULL) { + pkiDebug("%s: No certificate!\n", __FUNCTION__); + return retval; + } + + return crypto_retrieve_X509_sans(context, plgctx, reqctx, + reqctx->received_cert, princs_ret, + upn_ret, dns_ret); +} + +krb5_error_code +crypto_check_cert_eku(krb5_context context, + pkinit_plg_crypto_context plgctx, + pkinit_req_crypto_context reqctx, + pkinit_identity_crypto_context idctx, + int checking_kdc_cert, + int allow_secondary_usage, + int *valid_eku) +{ + char buf[DN_BUF_LEN]; + int found_eku = 0; + krb5_error_code retval = EINVAL; + int i; + + *valid_eku = 0; + if (reqctx->received_cert == NULL) + goto cleanup; + + X509_NAME_oneline(X509_get_subject_name(reqctx->received_cert), + buf, sizeof(buf)); + + if ((i = X509_get_ext_by_NID(reqctx->received_cert, + NID_ext_key_usage, -1)) >= 0) { + EXTENDED_KEY_USAGE *extusage; + + extusage = X509_get_ext_d2i(reqctx->received_cert, NID_ext_key_usage, + NULL, NULL); + if (extusage) { + pkiDebug("%s: found eku info in the cert\n", __FUNCTION__); + for (i = 0; found_eku == 0 && i < sk_ASN1_OBJECT_num(extusage); i++) { + ASN1_OBJECT *tmp_oid; + + tmp_oid = sk_ASN1_OBJECT_value(extusage, i); + pkiDebug("%s: checking eku %d of %d, allow_secondary = %d\n", + __FUNCTION__, i+1, sk_ASN1_OBJECT_num(extusage), + allow_secondary_usage); + if (checking_kdc_cert) { + if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPKdc) == 0) + || (allow_secondary_usage + && OBJ_cmp(tmp_oid, plgctx->id_kp_serverAuth) == 0)) + found_eku = 1; + } else { + if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPClientAuth) == 0) + || (allow_secondary_usage + && OBJ_cmp(tmp_oid, plgctx->id_ms_kp_sc_logon) == 0)) + found_eku = 1; + } + } + } + EXTENDED_KEY_USAGE_free(extusage); + + if (found_eku) { + ASN1_BIT_STRING *usage = NULL; + + /* check that digitalSignature KeyUsage is present */ + X509_check_ca(reqctx->received_cert); + if ((usage = X509_get_ext_d2i(reqctx->received_cert, + NID_key_usage, NULL, NULL))) { + + if (!ku_reject(reqctx->received_cert, + X509v3_KU_DIGITAL_SIGNATURE)) { + TRACE_PKINIT_EKU(context); + *valid_eku = 1; + } else + TRACE_PKINIT_EKU_NO_KU(context); + } + ASN1_BIT_STRING_free(usage); + } + } + retval = 0; +cleanup: + pkiDebug("%s: returning retval %d, valid_eku %d\n", + __FUNCTION__, retval, *valid_eku); + return retval; +} + +krb5_error_code +pkinit_octetstring2key(krb5_context context, + krb5_enctype etype, + unsigned char *key, + unsigned int dh_key_len, + krb5_keyblock *key_block) +{ + krb5_error_code retval; + unsigned char *buf = NULL; + unsigned char md[SHA_DIGEST_LENGTH]; + unsigned char counter; + size_t keybytes, keylength, offset; + krb5_data random_data; + EVP_MD_CTX *sha1_ctx = NULL; + + buf = k5alloc(dh_key_len, &retval); + if (buf == NULL) + goto cleanup; + + sha1_ctx = EVP_MD_CTX_new(); + if (sha1_ctx == NULL) { + retval = KRB5_CRYPTO_INTERNAL; + goto cleanup; + } + + counter = 0; + offset = 0; + do { + if (!EVP_DigestInit(sha1_ctx, EVP_sha1()) || + !EVP_DigestUpdate(sha1_ctx, &counter, 1) || + !EVP_DigestUpdate(sha1_ctx, key, dh_key_len) || + !EVP_DigestFinal(sha1_ctx, md, NULL)) { + retval = KRB5_CRYPTO_INTERNAL; + goto cleanup; + } + + if (dh_key_len - offset < sizeof(md)) + memcpy(buf + offset, md, dh_key_len - offset); + else + memcpy(buf + offset, md, sizeof(md)); + + offset += sizeof(md); + counter++; + } while (offset < dh_key_len); + + key_block->magic = 0; + key_block->enctype = etype; + + retval = krb5_c_keylengths(context, etype, &keybytes, &keylength); + if (retval) + goto cleanup; + + key_block->length = keylength; + key_block->contents = k5alloc(keylength, &retval); + if (key_block->contents == NULL) + goto cleanup; + + random_data.length = keybytes; + random_data.data = (char *)buf; + + retval = krb5_c_random_to_key(context, etype, &random_data, key_block); + +cleanup: + EVP_MD_CTX_free(sha1_ctx); + free(buf); + /* If this is an error return, free the allocated keyblock, if any */ + if (retval) { + krb5_free_keyblock_contents(context, key_block); + } + + return retval; +} + + +/* Return the OpenSSL descriptor for the given RFC 5652 OID specified in RFC + * 8636. RFC 8636 defines a SHA384 variant, but we don't use it. */ +static const EVP_MD * +algid_to_md(const krb5_data *alg_id) +{ + if (data_eq(*alg_id, sha1_id)) + return EVP_sha1(); + if (data_eq(*alg_id, sha256_id)) + return EVP_sha256(); + if (data_eq(*alg_id, sha512_id)) + return EVP_sha512(); + return NULL; +} + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + +#define sskdf openssl_sskdf +static krb5_error_code +openssl_sskdf(krb5_context context, const EVP_MD *md, krb5_data *key, + krb5_data *info, size_t len, krb5_data *out) +{ + krb5_error_code ret; + EVP_KDF *kdf = NULL; + EVP_KDF_CTX *kctx = NULL; + OSSL_PARAM params[4], *p = params; + + ret = alloc_data(out, len); + if (ret) + goto cleanup; + + kdf = EVP_KDF_fetch(NULL, "SSKDF", NULL); + if (kdf == NULL) { + ret = oerr(context, KRB5_CRYPTO_INTERNAL, _("Failed to fetch SSKDF")); + goto cleanup; + } + + kctx = EVP_KDF_CTX_new(kdf); + if (!kctx) { + ret = oerr(context, KRB5_CRYPTO_INTERNAL, + _("Failed to instantiate SSKDF")); + goto cleanup; + } + + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, + (char *)EVP_MD_get0_name(md), 0); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, + key->data, key->length); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO, + info->data, info->length); + *p = OSSL_PARAM_construct_end(); + if (EVP_KDF_derive(kctx, (uint8_t *)out->data, len, params) <= 0) { + ret = oerr(context, KRB5_CRYPTO_INTERNAL, + _("Failed to derive key using SSKDF")); + goto cleanup; + } + + ret = 0; + +cleanup: + EVP_KDF_free(kdf); + EVP_KDF_CTX_free(kctx); + return ret; +} + +#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + +#define sskdf builtin_sskdf +static krb5_error_code +builtin_sskdf(krb5_context context, const EVP_MD *md, krb5_data *key, + krb5_data *info, size_t len, krb5_data *out) +{ + krb5_error_code ret; + uint32_t counter = 1, reps; + uint8_t be_counter[4], *outptr; + EVP_MD_CTX *ctx = NULL; + unsigned int s, hash_len; + + hash_len = EVP_MD_size(md); + + /* 1. reps = keydatalen (K) / hash length (H) rounded up. */ + reps = (len + hash_len - 1) / hash_len; + + /* Allocate enough space in the random data buffer to hash directly into + * it, even if the last hash will make it bigger than the key length. */ + ret = alloc_data(out, reps * hash_len); + if (ret) + goto cleanup; + out->length = len; + + /* + * 2. Initialize a 32-bit, big-endian bit string counter as 1. + * 3. For i = 1 to reps by 1, do the following: + * - Compute Hashi = H(counter || Z || OtherInfo). + * - Increment counter (modulo 2^32) + * 4. Set key = Hash1 || Hash2 || ... so that length of key is K + * bytes. + */ + outptr = (uint8_t *)out->data; + for (counter = 1; counter <= reps; counter++) { + store_32_be(counter, be_counter); + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) { + ret = KRB5_CRYPTO_INTERNAL; + goto cleanup; + } + + /* - Compute Hashi = H(counter || Z || OtherInfo). */ + if (!EVP_DigestInit(ctx, md) || + !EVP_DigestUpdate(ctx, be_counter, 4) || + !EVP_DigestUpdate(ctx, key->data, key->length) || + !EVP_DigestUpdate(ctx, info->data, info->length) || + !EVP_DigestFinal(ctx, outptr, &s)) { + ret = oerr(context, KRB5_CRYPTO_INTERNAL, + _("Failed to compute digest")); + goto cleanup; + } + + assert(s == hash_len); + outptr += s; + + EVP_MD_CTX_free(ctx); + ctx = NULL; + } + +cleanup: + EVP_MD_CTX_free(ctx); + return ret; +} + +#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */ + +/* id-pkinit-kdf family, as specified by RFC 8636. */ +krb5_error_code +pkinit_alg_agility_kdf(krb5_context context, krb5_data *secret, + krb5_data *alg_oid, krb5_const_principal party_u_info, + krb5_const_principal party_v_info, + krb5_enctype enctype, krb5_data *as_req, + krb5_data *pk_as_rep, krb5_keyblock *key_block) +{ + krb5_error_code ret; + size_t rand_len = 0, key_len = 0; + const EVP_MD *md; + krb5_sp80056a_other_info other_info_fields; + krb5_pkinit_supp_pub_info supp_pub_info_fields; + krb5_data *other_info = NULL, *supp_pub_info = NULL; + krb5_data random_data = empty_data(); + krb5_algorithm_identifier alg_id; + char *hash_name = NULL; + + ret = krb5_c_keylengths(context, enctype, &rand_len, &key_len); + if (ret) + goto cleanup; + + /* Allocate and initialize the key block. */ + key_block->magic = 0; + key_block->enctype = enctype; + key_block->length = key_len; + key_block->contents = k5calloc(key_block->length, 1, &ret); + if (key_block->contents == NULL) + goto cleanup; + + /* If this is anonymous pkinit, use the anonymous principle for + * party_u_info. */ + if (party_u_info && + krb5_principal_compare_any_realm(context, party_u_info, + krb5_anonymous_principal())) { + party_u_info = (krb5_principal)krb5_anonymous_principal(); + } + + md = algid_to_md(alg_oid); + if (md == NULL) { + krb5_set_error_message(context, KRB5_ERR_BAD_S2K_PARAMS, + "Bad algorithm ID passed to PK-INIT KDF."); + return KRB5_ERR_BAD_S2K_PARAMS; + } + + /* Encode the ASN.1 octet string for "SuppPubInfo". */ + supp_pub_info_fields.enctype = enctype; + supp_pub_info_fields.as_req = *as_req; + supp_pub_info_fields.pk_as_rep = *pk_as_rep; + ret = encode_krb5_pkinit_supp_pub_info(&supp_pub_info_fields, + &supp_pub_info); + if (ret) + goto cleanup; + + /* Now encode the ASN.1 octet string for "OtherInfo". */ + memset(&alg_id, 0, sizeof(alg_id)); + alg_id.algorithm = *alg_oid; + other_info_fields.algorithm_identifier = alg_id; + other_info_fields.party_u_info = (krb5_principal)party_u_info; + other_info_fields.party_v_info = (krb5_principal)party_v_info; + other_info_fields.supp_pub_info = *supp_pub_info; + ret = encode_krb5_sp80056a_other_info(&other_info_fields, &other_info); + if (ret) + goto cleanup; + + ret = sskdf(context, md, secret, other_info, rand_len, &random_data); + if (ret) + goto cleanup; + + ret = krb5_c_random_to_key(context, enctype, &random_data, key_block); + +cleanup: + if (ret) + krb5_free_keyblock_contents(context, key_block); + free(hash_name); + zapfree(random_data.data, random_data.length); + krb5_free_data(context, other_info); + krb5_free_data(context, supp_pub_info); + return ret; +} + +krb5_error_code +client_create_dh(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + int dh_size, krb5_data *spki_out) +{ + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + EVP_PKEY *params = NULL, *pkey = NULL; + + *spki_out = empty_data(); + + if (cryptoctx->received_params != NULL) + params = cryptoctx->received_params; + else if (dh_size == 1024) + params = plg_cryptoctx->dh_1024; + else if (dh_size == 2048) + params = plg_cryptoctx->dh_2048; + else if (dh_size == 4096) + params = plg_cryptoctx->dh_4096; + else + goto cleanup; + + pkey = generate_dh_pkey(params); + if (pkey == NULL) + goto cleanup; + + retval = encode_spki(pkey, spki_out); + if (retval) + goto cleanup; + + EVP_PKEY_free(cryptoctx->client_pkey); + cryptoctx->client_pkey = pkey; + pkey = NULL; + +cleanup: + EVP_PKEY_free(pkey); + return retval; +} + +krb5_error_code +client_process_dh(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + unsigned char *subjectPublicKey_data, + unsigned int subjectPublicKey_length, + unsigned char **client_key_out, + unsigned int *client_key_len_out) +{ + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + EVP_PKEY *server_pkey = NULL; + uint8_t *client_key = NULL; + unsigned int client_key_len; + + *client_key_out = NULL; + *client_key_len_out = 0; + + server_pkey = compose_dh_pkey(cryptoctx->client_pkey, + subjectPublicKey_data, + subjectPublicKey_length); + if (server_pkey == NULL) + goto cleanup; + + if (!dh_result(cryptoctx->client_pkey, server_pkey, + &client_key, &client_key_len)) + goto cleanup; + +#ifdef DEBUG_DH + print_pubkey(server_pub_key, "server's pub_key="); + pkiDebug("client computed key (%d)= ", client_key_len); + print_buffer(client_key, client_key_len); +#endif + + *client_key_out = client_key; + *client_key_len_out = client_key_len; + client_key = NULL; + + retval = 0; + +cleanup: + EVP_PKEY_free(server_pkey); + free(client_key); + return retval; +} + +/* Return 1 if dh is a permitted well-known group, otherwise return 0. */ +static int +check_dh_wellknown(pkinit_plg_crypto_context cryptoctx, EVP_PKEY *pkey, + int nbits) +{ + if (nbits == 1024) + return EVP_PKEY_parameters_eq(cryptoctx->dh_1024, pkey) == 1; + else if (nbits == 2048) + return EVP_PKEY_parameters_eq(cryptoctx->dh_2048, pkey) == 1; + else if (nbits == 4096) + return EVP_PKEY_parameters_eq(cryptoctx->dh_4096, pkey) == 1; + return 0; +} + +krb5_error_code +server_check_dh(krb5_context context, + pkinit_plg_crypto_context cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + const krb5_data *client_spki, + int minbits) +{ + EVP_PKEY *client_pkey = NULL; + int dh_prime_bits; + krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + + client_pkey = decode_spki(client_spki); + if (client_pkey == NULL) { + pkiDebug("failed to decode dhparams\n"); + goto cleanup; + } + + /* KDC SHOULD check to see if the key parameters satisfy its policy */ + dh_prime_bits = EVP_PKEY_get_bits(client_pkey); + if (minbits && dh_prime_bits < minbits) { + pkiDebug("client sent dh params with %d bits, we require %d\n", + dh_prime_bits, minbits); + goto cleanup; + } + + if (check_dh_wellknown(cryptoctx, client_pkey, dh_prime_bits)) + retval = 0; + +cleanup: + if (retval == 0) + req_cryptoctx->client_pkey = client_pkey; + else + EVP_PKEY_free(client_pkey); + + return retval; +} + +/* kdc's dh function */ +krb5_error_code +server_process_dh(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + unsigned char **dh_pubkey_out, + unsigned int *dh_pubkey_len_out, + unsigned char **server_key_out, + unsigned int *server_key_len_out) +{ + krb5_error_code retval = ENOMEM; + EVP_PKEY *server_pkey = NULL; + unsigned char *dh_pubkey = NULL, *server_key = NULL; + unsigned int dh_pubkey_len = 0, server_key_len = 0; + + *dh_pubkey_out = *server_key_out = NULL; + *dh_pubkey_len_out = *server_key_len_out = 0; + + /* Generate a server DH key with the same parameters as the client key. */ + server_pkey = generate_dh_pkey(cryptoctx->client_pkey); + if (server_pkey == NULL) + goto cleanup; + + if (!dh_result(server_pkey, cryptoctx->client_pkey, &server_key, + &server_key_len)) + goto cleanup; + + if (!dh_pubkey_der(server_pkey, &dh_pubkey, &dh_pubkey_len)) + goto cleanup; + + *dh_pubkey_out = dh_pubkey; + *dh_pubkey_len_out = dh_pubkey_len; + *server_key_out = server_key; + *server_key_len_out = server_key_len; + dh_pubkey = server_key = NULL; + + retval = 0; + +cleanup: + EVP_PKEY_free(server_pkey); + free(dh_pubkey); + free(server_key); + + return retval; +} + +int +pkinit_openssl_init() +{ + /* Initialize OpenSSL. */ + ERR_load_crypto_strings(); + OpenSSL_add_all_algorithms(); + return 0; +} + +static krb5_error_code +pkinit_create_sequence_of_principal_identifiers( + krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + int type, + krb5_pa_data ***e_data_out) +{ + krb5_error_code retval = KRB5KRB_ERR_GENERIC; + krb5_external_principal_identifier **krb5_trusted_certifiers = NULL; + krb5_data *td_certifiers = NULL; + krb5_pa_data **pa_data = NULL; + + switch(type) { + case TD_TRUSTED_CERTIFIERS: + retval = create_krb5_trustedCertifiers(context, plg_cryptoctx, + req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers); + if (retval) { + pkiDebug("create_krb5_trustedCertifiers failed\n"); + goto cleanup; + } + break; + case TD_INVALID_CERTIFICATES: + retval = create_krb5_invalidCertificates(context, plg_cryptoctx, + req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers); + if (retval) { + pkiDebug("create_krb5_invalidCertificates failed\n"); + goto cleanup; + } + break; + default: + retval = -1; + goto cleanup; + } + + retval = k5int_encode_krb5_td_trusted_certifiers((krb5_external_principal_identifier *const *)krb5_trusted_certifiers, &td_certifiers); + if (retval) { + pkiDebug("encode_krb5_td_trusted_certifiers failed\n"); + goto cleanup; + } +#ifdef DEBUG_ASN1 + print_buffer_bin((unsigned char *)td_certifiers->data, + td_certifiers->length, "/tmp/kdc_td_certifiers"); +#endif + pa_data = malloc(2 * sizeof(krb5_pa_data *)); + if (pa_data == NULL) { + retval = ENOMEM; + goto cleanup; + } + pa_data[1] = NULL; + pa_data[0] = malloc(sizeof(krb5_pa_data)); + if (pa_data[0] == NULL) { + free(pa_data); + retval = ENOMEM; + goto cleanup; + } + pa_data[0]->pa_type = type; + pa_data[0]->length = td_certifiers->length; + pa_data[0]->contents = (krb5_octet *)td_certifiers->data; + *e_data_out = pa_data; + retval = 0; + +cleanup: + if (krb5_trusted_certifiers != NULL) + free_krb5_external_principal_identifier(&krb5_trusted_certifiers); + free(td_certifiers); + return retval; +} + +krb5_error_code +pkinit_create_td_trusted_certifiers(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_pa_data ***e_data_out) +{ + krb5_error_code retval = KRB5KRB_ERR_GENERIC; + + retval = pkinit_create_sequence_of_principal_identifiers(context, + plg_cryptoctx, req_cryptoctx, id_cryptoctx, + TD_TRUSTED_CERTIFIERS, e_data_out); + + return retval; +} + +krb5_error_code +pkinit_create_td_invalid_certificate( + krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_pa_data ***e_data_out) +{ + krb5_error_code retval = KRB5KRB_ERR_GENERIC; + + retval = pkinit_create_sequence_of_principal_identifiers(context, + plg_cryptoctx, req_cryptoctx, id_cryptoctx, + TD_INVALID_CERTIFICATES, e_data_out); + + return retval; +} + +krb5_error_code +pkinit_create_td_dh_parameters(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + pkinit_plg_opts *opts, + krb5_pa_data ***e_data_out) +{ + krb5_error_code ret; + int i; + krb5_pa_data **pa_data = NULL; + krb5_data *der_alglist = NULL; + krb5_algorithm_identifier alg_1024 = { dh_oid, oakley_1024 }; + krb5_algorithm_identifier alg_2048 = { dh_oid, oakley_2048 }; + krb5_algorithm_identifier alg_4096 = { dh_oid, oakley_4096 }; + krb5_algorithm_identifier *alglist[4]; + + if (opts->dh_min_bits > 4096) { + ret = KRB5KRB_ERR_GENERIC; + goto cleanup; + } + + i = 0; + if (opts->dh_min_bits <= 2048) + alglist[i++] = &alg_2048; + alglist[i++] = &alg_4096; + if (opts->dh_min_bits <= 1024) + alglist[i++] = &alg_1024; + alglist[i] = NULL; + + ret = k5int_encode_krb5_td_dh_parameters(alglist, &der_alglist); + if (ret) + goto cleanup; + + pa_data = k5calloc(2, sizeof(*pa_data), &ret); + if (pa_data == NULL) + goto cleanup; + pa_data[1] = NULL; + pa_data[0] = k5alloc(sizeof(*pa_data[0]), &ret); + if (pa_data[0] == NULL) { + free(pa_data); + goto cleanup; + } + pa_data[0]->pa_type = TD_DH_PARAMETERS; + pa_data[0]->length = der_alglist->length; + pa_data[0]->contents = (krb5_octet *)der_alglist->data; + der_alglist->data = NULL; + *e_data_out = pa_data; + +cleanup: + krb5_free_data(context, der_alglist); + return ret; +} + +krb5_error_code +pkinit_check_kdc_pkid(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + unsigned char *pdid_buf, + unsigned int pkid_len, + int *valid_kdcPkId) +{ + PKCS7_ISSUER_AND_SERIAL *is = NULL; + const unsigned char *p = pdid_buf; + int status = 1; + X509 *kdc_cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index); + + *valid_kdcPkId = 0; + pkiDebug("found kdcPkId in AS REQ\n"); + is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p, (int)pkid_len); + if (is == NULL) + return KRB5KDC_ERR_PREAUTH_FAILED; + + status = X509_NAME_cmp(X509_get_issuer_name(kdc_cert), is->issuer); + if (!status) { + status = ASN1_INTEGER_cmp(X509_get_serialNumber(kdc_cert), is->serial); + if (!status) + *valid_kdcPkId = 1; + } + + X509_NAME_free(is->issuer); + ASN1_INTEGER_free(is->serial); + free(is); + + return 0; +} + +krb5_error_code +pkinit_process_td_dh_params(krb5_context context, + pkinit_plg_crypto_context cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_algorithm_identifier **algId, + int *new_dh_size) +{ + krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + EVP_PKEY *params = NULL; + int i, dh_prime_bits, old_dh_size; + + pkiDebug("dh parameters\n"); + + EVP_PKEY_free(req_cryptoctx->received_params); + req_cryptoctx->received_params = NULL; + + old_dh_size = *new_dh_size; + + for (i = 0; algId[i] != NULL; i++) { + /* Free any parameters from the previous iteration. */ + EVP_PKEY_free(params); + params = NULL; + + /* Skip any parameters for algorithms other than DH. */ + if (algId[i]->algorithm.length != dh_oid.length || + memcmp(algId[i]->algorithm.data, dh_oid.data, dh_oid.length)) + continue; + + params = decode_dh_params(&algId[i]->parameters); + if (params == NULL) + continue; + dh_prime_bits = EVP_PKEY_get_bits(params); + /* Skip any parameters shorter than the previous size. */ + if (dh_prime_bits < old_dh_size) + continue; + pkiDebug("client sent %d DH bits server prefers %d DH bits\n", + *new_dh_size, dh_prime_bits); + + /* If this is one of our well-known groups, just save the new size; we + * will use our own copy of the parameters. */ + if (check_dh_wellknown(cryptoctx, params, dh_prime_bits)) { + *new_dh_size = dh_prime_bits; + retval = 0; + goto cleanup; + } + + /* If the parameters aren't well-known but check out, save them. */ + if (params_valid(params)) { + req_cryptoctx->received_params = params; + params = NULL; + retval = 0; + goto cleanup; + } + } + +cleanup: + EVP_PKEY_free(params); + return retval; +} + +static int +openssl_callback(int ok, X509_STORE_CTX * ctx) +{ +#ifdef DEBUG + if (!ok) { + X509 *cert = X509_STORE_CTX_get_current_cert(ctx); + int err = X509_STORE_CTX_get_error(ctx); + const char *errmsg = X509_verify_cert_error_string(err); + char buf[DN_BUF_LEN]; + + X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); + pkiDebug("cert = %s\n", buf); + pkiDebug("callback function: %d (%s)\n", err, errmsg); + } +#endif + return ok; +} + +static int +openssl_callback_ignore_crls(int ok, X509_STORE_CTX * ctx) +{ + if (ok) + return ok; + return X509_STORE_CTX_get_error(ctx) == X509_V_ERR_UNABLE_TO_GET_CRL; +} + +static ASN1_OBJECT * +pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type) +{ + switch (pkcs7_type) { + case CMS_SIGN_CLIENT: + return cryptoctx->id_pkinit_authData; + case CMS_SIGN_SERVER: + return cryptoctx->id_pkinit_DHKeyData; + case CMS_ENVEL_SERVER: + return cryptoctx->id_pkinit_rkeyData; + default: + return NULL; + } + +} + +static int +wrap_signeddata(unsigned char *data, unsigned int data_len, + unsigned char **out, unsigned int *out_len) +{ + + unsigned int orig_len = 0, oid_len = 0, tot_len = 0; + ASN1_OBJECT *oid = NULL; + unsigned char *p = NULL; + + /* Get length to wrap the original data with SEQUENCE tag */ + tot_len = orig_len = ASN1_object_size(1, (int)data_len, V_ASN1_SEQUENCE); + + /* Add the signedData OID and adjust lengths */ + oid = OBJ_nid2obj(NID_pkcs7_signed); + oid_len = i2d_ASN1_OBJECT(oid, NULL); + + tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE); + + p = *out = malloc(tot_len); + if (p == NULL) return -1; + + ASN1_put_object(&p, 1, (int)(orig_len+oid_len), + V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL); + + i2d_ASN1_OBJECT(oid, &p); + + ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC); + memcpy(p, data, data_len); + + *out_len = tot_len; + + return 0; +} + +static int +prepare_enc_data(const uint8_t *indata, int indata_len, uint8_t **outdata, + int *outdata_len) +{ + int tag, class; + long tlen, slen; + const uint8_t *p = indata, *oldp; + + if (ASN1_get_object(&p, &slen, &tag, &class, indata_len) & 0x80) + return EINVAL; + if (tag != V_ASN1_SEQUENCE) + return EINVAL; + + oldp = p; + if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80) + return EINVAL; + p += tlen; + slen -= (p - oldp); + + if (ASN1_get_object(&p, &tlen, &tag, &class, slen) & 0x80) + return EINVAL; + + *outdata = malloc(tlen); + if (*outdata == NULL) + return ENOMEM; + memcpy(*outdata, p, tlen); + *outdata_len = tlen; + return 0; +} + +#ifndef WITHOUT_PKCS11 +static struct plugin_file_handle * +load_pkcs11_module(krb5_context context, const char *modname, + CK_FUNCTION_LIST_PTR_PTR p11p) +{ + struct plugin_file_handle *handle = NULL; + CK_RV (*getflist)(CK_FUNCTION_LIST_PTR_PTR); + struct errinfo einfo = EMPTY_ERRINFO; + const char *errmsg = NULL; + void (*sym)(); + long err; + CK_RV rv; + + TRACE_PKINIT_PKCS11_OPEN(context, modname); + err = krb5int_open_plugin(modname, &handle, &einfo); + if (err) { + errmsg = k5_get_error(&einfo, err); + TRACE_PKINIT_PKCS11_OPEN_FAILED(context, errmsg); + goto error; + } + + err = krb5int_get_plugin_func(handle, "C_GetFunctionList", &sym, &einfo); + if (err) { + errmsg = k5_get_error(&einfo, err); + TRACE_PKINIT_PKCS11_GETSYM_FAILED(context, errmsg); + goto error; + } + + getflist = (CK_RV (*)())sym; + rv = (*getflist)(p11p); + if (rv != CKR_OK) { + TRACE_PKINIT_PKCS11_GETFLIST_FAILED(context, pkcs11err(rv)); + goto error; + } + + return handle; + +error: + k5_free_error(&einfo, errmsg); + k5_clear_error(&einfo); + if (handle != NULL) + krb5int_close_plugin(handle); + return NULL; +} + +static krb5_error_code +pkinit_login(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, + CK_TOKEN_INFO *tip, const char *password) +{ + krb5_data rdat; + char *prompt; + const char *warning; + krb5_prompt kprompt; + krb5_prompt_type prompt_type; + int r = 0; + + if (tip->flags & CKF_PROTECTED_AUTHENTICATION_PATH) { + rdat.data = NULL; + rdat.length = 0; + } else if (password != NULL) { + rdat.data = strdup(password); + rdat.length = strlen(password); + } else if (id_cryptoctx->prompter == NULL) { + r = KRB5_LIBOS_CANTREADPWD; + rdat.data = NULL; + } else { + if (tip->flags & CKF_USER_PIN_LOCKED) + warning = " (Warning: PIN locked)"; + else if (tip->flags & CKF_USER_PIN_FINAL_TRY) + warning = " (Warning: PIN final try)"; + else if (tip->flags & CKF_USER_PIN_COUNT_LOW) + warning = " (Warning: PIN count low)"; + else + warning = ""; + if (asprintf(&prompt, "%.*s PIN%s", (int) sizeof (tip->label), + tip->label, warning) < 0) + return ENOMEM; + rdat.data = malloc(tip->ulMaxPinLen + 2); + rdat.length = tip->ulMaxPinLen + 1; + + kprompt.prompt = prompt; + kprompt.hidden = 1; + kprompt.reply = &rdat; + prompt_type = KRB5_PROMPT_TYPE_PREAUTH; + + /* PROMPTER_INVOCATION */ + k5int_set_prompt_types(context, &prompt_type); + r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data, + NULL, NULL, 1, &kprompt); + k5int_set_prompt_types(context, 0); + free(prompt); + } + + if (r == 0) { + r = id_cryptoctx->p11->C_Login(id_cryptoctx->session, CKU_USER, + (u_char *) rdat.data, rdat.length); + + if (r != CKR_OK) { + TRACE_PKINIT_PKCS11_LOGIN_FAILED(context, pkcs11err(r)); + r = KRB5KDC_ERR_PREAUTH_FAILED; + } + } + free(rdat.data); + + return r; +} + +static krb5_error_code +pkinit_open_session(krb5_context context, + pkinit_identity_crypto_context cctx) +{ + CK_ULONG i, pret; + unsigned char *cp; + size_t label_len; + CK_ULONG count = 0; + CK_SLOT_ID_PTR slotlist = NULL; + CK_TOKEN_INFO tinfo; + char *p11name = NULL; + const char *password; + krb5_error_code ret; + + if (cctx->p11_module != NULL) + return 0; /* session already open */ + + /* Load module */ + cctx->p11_module = load_pkcs11_module(context, cctx->p11_module_name, + &cctx->p11); + if (cctx->p11_module == NULL) + return KRB5KDC_ERR_PREAUTH_FAILED; + + /* Init */ + pret = cctx->p11->C_Initialize(NULL); + if (pret != CKR_OK) { + pkiDebug("C_Initialize: %s\n", pkcs11err(pret)); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + + /* Get the list of available slots */ + if (cctx->p11->C_GetSlotList(TRUE, NULL, &count) != CKR_OK) + return KRB5KDC_ERR_PREAUTH_FAILED; + if (count == 0) { + TRACE_PKINIT_PKCS11_NO_TOKEN(context); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + slotlist = calloc(count, sizeof(CK_SLOT_ID)); + if (slotlist == NULL) + return ENOMEM; + if (cctx->p11->C_GetSlotList(TRUE, slotlist, &count) != CKR_OK) { + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + /* Look for the given token label, or if none given take the first one */ + for (i = 0; i < count; i++) { + /* Skip slots that don't match the specified slotid, if given. */ + if (cctx->slotid != PK_NOSLOT && cctx->slotid != slotlist[i]) + continue; + + /* Open session */ + pret = cctx->p11->C_OpenSession(slotlist[i], CKF_SERIAL_SESSION, + NULL, NULL, &cctx->session); + if (pret != CKR_OK) { + pkiDebug("C_OpenSession: %s\n", pkcs11err(pret)); + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + /* Get token info */ + pret = cctx->p11->C_GetTokenInfo(slotlist[i], &tinfo); + if (pret != CKR_OK) { + pkiDebug("C_GetTokenInfo: %s\n", pkcs11err(pret)); + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + /* tinfo.label is zero-filled but not necessarily zero-terminated. + * Find the length, ignoring any trailing spaces. */ + for (cp = tinfo.label + sizeof(tinfo.label); cp > tinfo.label; cp--) { + if (cp[-1] != '\0' && cp[-1] != ' ') + break; + } + label_len = cp - tinfo.label; + + TRACE_PKINIT_PKCS11_SLOT(context, (int)slotlist[i], (int)label_len, + tinfo.label); + if (cctx->token_label == NULL || + (strlen(cctx->token_label) == label_len && + memcmp(cctx->token_label, tinfo.label, label_len) == 0)) + break; + cctx->p11->C_CloseSession(cctx->session); + } + if (i >= count) { + TRACE_PKINIT_PKCS11_NO_MATCH_TOKEN(context); + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + cctx->slotid = slotlist[i]; + pkiDebug("open_session: slotid %d (%lu of %d)\n", (int)cctx->slotid, + i + 1, (int) count); + + /* Login if needed */ + if (tinfo.flags & CKF_LOGIN_REQUIRED) { + if (cctx->p11_module_name != NULL) { + if (cctx->slotid != PK_NOSLOT) { + if (asprintf(&p11name, + "PKCS11:module_name=%s:slotid=%ld:token=%.*s", + cctx->p11_module_name, (long)cctx->slotid, + (int)label_len, tinfo.label) < 0) + p11name = NULL; + } else { + if (asprintf(&p11name, + "PKCS11:module_name=%s,token=%.*s", + cctx->p11_module_name, + (int)label_len, tinfo.label) < 0) + p11name = NULL; + } + } + if (cctx->defer_id_prompt) { + /* Supply the identity name to be passed to the responder. */ + pkinit_set_deferred_id(&cctx->deferred_ids, + p11name, tinfo.flags, NULL); + ret = 0; + goto cleanup; + } + /* Look up a responder-supplied password for the token. */ + password = pkinit_find_deferred_id(cctx->deferred_ids, p11name); + ret = pkinit_login(context, cctx, &tinfo, password); + if (ret) + goto cleanup; + } + + ret = 0; +cleanup: + free(slotlist); + free(p11name); + return ret; +} + +/* + * Look for a key that's: + * 1. private + * 2. capable of the specified operation (usually signing or decrypting) + * 3. RSA (this may be wrong but it's all we can do for now) + * 4. matches the id of the cert we chose + * + * You must call pkinit_get_certs before calling pkinit_find_private_key + * (that's because we need the ID of the private key) + * + * pkcs11 says the id of the key doesn't have to match that of the cert, but + * I can't figure out any other way to decide which key to use. + * + * We should only find one key that fits all the requirements. + * If there are more than one, we just take the first one. + */ + +krb5_error_code +pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx, + CK_ATTRIBUTE_TYPE usage, + CK_OBJECT_HANDLE *objp) +{ + CK_OBJECT_CLASS cls; + CK_ATTRIBUTE attrs[4]; + CK_ULONG count; + CK_KEY_TYPE keytype; + unsigned int nattrs = 0; + int r; +#ifdef PKINIT_USE_KEY_USAGE + CK_BBOOL true_false; +#endif + + cls = CKO_PRIVATE_KEY; + attrs[nattrs].type = CKA_CLASS; + attrs[nattrs].pValue = &cls; + attrs[nattrs].ulValueLen = sizeof cls; + nattrs++; + +#ifdef PKINIT_USE_KEY_USAGE + /* + * Some cards get confused if you try to specify a key usage, + * so don't, and hope for the best. This will fail if you have + * several keys with the same id and different usages but I have + * not seen this on real cards. + */ + true_false = TRUE; + attrs[nattrs].type = usage; + attrs[nattrs].pValue = &true_false; + attrs[nattrs].ulValueLen = sizeof true_false; + nattrs++; +#endif + + keytype = CKK_RSA; + attrs[nattrs].type = CKA_KEY_TYPE; + attrs[nattrs].pValue = &keytype; + attrs[nattrs].ulValueLen = sizeof keytype; + nattrs++; + + attrs[nattrs].type = CKA_ID; + attrs[nattrs].pValue = id_cryptoctx->cert_id; + attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len; + nattrs++; + + r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs); + if (r != CKR_OK) { + pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n", + pkcs11err(r)); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + + r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count); + id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session); + pkiDebug("found %d private keys (%s)\n", (int)count, pkcs11err(r)); + if (r != CKR_OK || count < 1) + return KRB5KDC_ERR_PREAUTH_FAILED; + return 0; +} +#endif + +static krb5_error_code +pkinit_decode_data_fs(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, + const uint8_t *data, unsigned int data_len, + uint8_t **decoded_data, unsigned int *decoded_data_len) +{ + X509 *cert = sk_X509_value(id_cryptoctx->my_certs, + id_cryptoctx->cert_index); + EVP_PKEY *pkey = id_cryptoctx->my_key; + EVP_PKEY_CTX *ctx = NULL; + uint8_t *buf = NULL; + size_t buf_len = 0; + int ok; + + *decoded_data = NULL; + *decoded_data_len = 0; + + if (cert != NULL && !X509_check_private_key(cert, pkey)) { + pkiDebug("private key does not match certificate\n"); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ctx == NULL) + return KRB5KDC_ERR_PREAUTH_FAILED; + + ok = EVP_PKEY_decrypt_init(ctx); + if (!ok) + goto cleanup; + + /* Get the length of the eventual output. */ + ok = EVP_PKEY_decrypt(ctx, NULL, &buf_len, data, data_len); + if (!ok) { + pkiDebug("unable to decrypt received data\n"); + goto cleanup; + } + + buf = malloc(buf_len); + if (buf == NULL) { + ok = 0; + goto cleanup; + } + + ok = EVP_PKEY_decrypt(ctx, buf, &buf_len, data, data_len); + if (!ok) { + pkiDebug("unable to decrypt received data\n"); + goto cleanup; + } + + *decoded_data = buf; + *decoded_data_len = buf_len; + buf = NULL; +cleanup: + zapfree(buf, buf_len); + EVP_PKEY_CTX_free(ctx); + return ok ? 0 : KRB5KDC_ERR_PREAUTH_FAILED; +} + +#ifndef WITHOUT_PKCS11 +/* + * When using the ActivCard Linux pkcs11 library (v2.0.1), the decrypt function + * fails. By inserting an extra function call, which serves nothing but to + * change the stack, we were able to work around the issue. If the ActivCard + * library is fixed in the future, this function can be inlined back into the + * caller. + */ +static CK_RV +pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx, + CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pData, + CK_ULONG_PTR pulDataLen) +{ + CK_RV rv = CKR_OK; + + rv = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, pEncryptedData, + ulEncryptedDataLen, pData, pulDataLen); + if (rv == CKR_OK) { + pkiDebug("pData %p *pulDataLen %d\n", (void *) pData, + (int) *pulDataLen); + } + return rv; +} + +static krb5_error_code +pkinit_decode_data_pkcs11(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, + const uint8_t *data, unsigned int data_len, + uint8_t **decoded_data, + unsigned int *decoded_data_len) +{ + CK_OBJECT_HANDLE obj; + CK_ULONG len; + CK_MECHANISM mech; + uint8_t *cp; + int r; + + *decoded_data = NULL; + *decoded_data_len = 0; + + if (pkinit_open_session(context, id_cryptoctx)) { + pkiDebug("can't open pkcs11 session\n"); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + + pkinit_find_private_key(id_cryptoctx, CKA_DECRYPT, &obj); + + mech.mechanism = CKM_RSA_PKCS; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + if ((r = id_cryptoctx->p11->C_DecryptInit(id_cryptoctx->session, &mech, + obj)) != CKR_OK) { + pkiDebug("C_DecryptInit: 0x%x\n", (int) r); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + pkiDebug("data_len = %d\n", data_len); + cp = malloc((size_t) data_len); + if (cp == NULL) + return ENOMEM; + len = data_len; + pkiDebug("session %p edata %p edata_len %d data %p datalen @%p %d\n", + (void *) id_cryptoctx->session, (void *) data, (int) data_len, + (void *) cp, (void *) &len, (int) len); + r = pkinit_C_Decrypt(id_cryptoctx, (CK_BYTE_PTR) data, (CK_ULONG) data_len, + cp, &len); + if (r != CKR_OK) { + pkiDebug("C_Decrypt: %s\n", pkcs11err(r)); + if (r == CKR_BUFFER_TOO_SMALL) + pkiDebug("decrypt %d needs %d\n", (int) data_len, (int) len); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + pkiDebug("decrypt %d -> %d\n", (int) data_len, (int) len); + *decoded_data_len = len; + *decoded_data = cp; + + return 0; +} +#endif + +krb5_error_code +pkinit_decode_data(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, + const uint8_t *data, unsigned int data_len, + uint8_t **decoded_data, unsigned int *decoded_data_len) +{ + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + + *decoded_data = NULL; + *decoded_data_len = 0; + + if (id_cryptoctx->pkcs11_method != 1) + retval = pkinit_decode_data_fs(context, id_cryptoctx, data, data_len, + decoded_data, decoded_data_len); +#ifndef WITHOUT_PKCS11 + else + retval = pkinit_decode_data_pkcs11(context, id_cryptoctx, data, + data_len, decoded_data, decoded_data_len); +#endif + + return retval; +} + +static krb5_error_code +pkinit_sign_data_fs(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, + unsigned char *data, + unsigned int data_len, + unsigned char **sig, + unsigned int *sig_len) +{ + if (create_signature(sig, sig_len, data, data_len, + id_cryptoctx->my_key) != 0) { + pkiDebug("failed to create the signature\n"); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + return 0; +} + +#ifndef WITHOUT_PKCS11 +static krb5_error_code +pkinit_sign_data_pkcs11(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, + unsigned char *data, + unsigned int data_len, + unsigned char **sig, + unsigned int *sig_len) +{ + CK_OBJECT_HANDLE obj; + CK_ULONG len; + CK_MECHANISM mech; + unsigned char *cp; + int r; + + if (pkinit_open_session(context, id_cryptoctx)) { + pkiDebug("can't open pkcs11 session\n"); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + + pkinit_find_private_key(id_cryptoctx, CKA_SIGN, &obj); + + mech.mechanism = id_cryptoctx->mech; + mech.pParameter = NULL; + mech.ulParameterLen = 0; + + if ((r = id_cryptoctx->p11->C_SignInit(id_cryptoctx->session, &mech, + obj)) != CKR_OK) { + pkiDebug("C_SignInit: %s\n", pkcs11err(r)); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + + /* + * Key len would give an upper bound on sig size, but there's no way to + * get that. So guess, and if it's too small, re-malloc. + */ + len = PK_SIGLEN_GUESS; + cp = malloc((size_t) len); + if (cp == NULL) + return ENOMEM; + + r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data, + (CK_ULONG) data_len, cp, &len); + if (r == CKR_BUFFER_TOO_SMALL || (r == CKR_OK && len >= PK_SIGLEN_GUESS)) { + free(cp); + pkiDebug("C_Sign realloc %d\n", (int) len); + cp = malloc((size_t) len); + r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data, + (CK_ULONG) data_len, cp, &len); + } + if (r != CKR_OK) { + pkiDebug("C_Sign: %s\n", pkcs11err(r)); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + pkiDebug("sign %d -> %d\n", (int) data_len, (int) len); + *sig_len = len; + *sig = cp; + + return 0; +} +#endif + +krb5_error_code +pkinit_sign_data(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, + unsigned char *data, + unsigned int data_len, + unsigned char **sig, + unsigned int *sig_len) +{ + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + + if (id_cryptoctx == NULL || id_cryptoctx->pkcs11_method != 1) + retval = pkinit_sign_data_fs(context, id_cryptoctx, data, data_len, + sig, sig_len); +#ifndef WITHOUT_PKCS11 + else + retval = pkinit_sign_data_pkcs11(context, id_cryptoctx, data, data_len, + sig, sig_len); +#endif + + return retval; +} + + +static krb5_error_code +create_signature(unsigned char **sig, unsigned int *sig_len, + unsigned char *data, unsigned int data_len, EVP_PKEY *pkey) +{ + krb5_error_code retval = ENOMEM; + EVP_MD_CTX *ctx; + + if (pkey == NULL) + return retval; + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return ENOMEM; + EVP_SignInit(ctx, EVP_sha256()); + EVP_SignUpdate(ctx, data, data_len); + *sig_len = EVP_PKEY_size(pkey); + if ((*sig = malloc(*sig_len)) == NULL) + goto cleanup; + EVP_SignFinal(ctx, *sig, sig_len, pkey); + + retval = 0; + +cleanup: + EVP_MD_CTX_free(ctx); + + return retval; +} + +/* + * Note: + * This is not the routine the KDC uses to get its certificate. + * This routine is intended to be called by the client + * to obtain the KDC's certificate from some local storage + * to be sent as a hint in its request to the KDC. + */ +krb5_error_code +pkinit_get_kdc_cert(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_principal princ) +{ + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + + req_cryptoctx->received_cert = NULL; + retval = 0; + return retval; +} + +static char * +reassemble_pkcs12_name(const char *filename) +{ + char *ret; + + if (asprintf(&ret, "PKCS12:%s", filename) < 0) + return NULL; + return ret; +} + +static krb5_error_code +pkinit_get_certs_pkcs12(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_opts *idopts, + pkinit_identity_crypto_context id_cryptoctx, + krb5_principal princ) +{ + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + char *prompt_string = NULL; + X509 *x = NULL; + PKCS12 *p12 = NULL; + int ret; + FILE *fp; + EVP_PKEY *y = NULL; + + if (idopts->cert_filename == NULL) { + pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__); + goto cleanup; + } + + if (idopts->key_filename == NULL) { + pkiDebug("%s: failed to get user's private key location\n", __FUNCTION__); + goto cleanup; + } + + fp = fopen(idopts->cert_filename, "rb"); + if (fp == NULL) { + TRACE_PKINIT_PKCS_OPEN_FAIL(context, idopts->cert_filename, errno); + goto cleanup; + } + set_cloexec_file(fp); + + p12 = d2i_PKCS12_fp(fp, NULL); + fclose(fp); + if (p12 == NULL) { + TRACE_PKINIT_PKCS_DECODE_FAIL(context, idopts->cert_filename); + goto cleanup; + } + /* + * Try parsing with no pass phrase first. If that fails, + * prompt for the pass phrase and try again. + */ + ret = PKCS12_parse(p12, NULL, &y, &x, NULL); + if (ret == 0) { + krb5_data rdat; + krb5_prompt kprompt; + krb5_prompt_type prompt_type; + krb5_error_code r; + char prompt_reply[128]; + char *prompt_prefix = _("Pass phrase for"); + char *p12name = reassemble_pkcs12_name(idopts->cert_filename); + const char *tmp; + + TRACE_PKINIT_PKCS_PARSE_FAIL_FIRST(context); + + if (id_cryptoctx->defer_id_prompt) { + /* Supply the identity name to be passed to the responder. */ + pkinit_set_deferred_id(&id_cryptoctx->deferred_ids, p12name, 0, + NULL); + free(p12name); + retval = 0; + goto cleanup; + } + /* Try to read a responder-supplied password. */ + tmp = pkinit_find_deferred_id(id_cryptoctx->deferred_ids, p12name); + free(p12name); + if (tmp != NULL) { + /* Try using the responder-supplied password. */ + rdat.data = (char *)tmp; + rdat.length = strlen(tmp); + } else if (id_cryptoctx->prompter == NULL) { + /* We can't use a prompter. */ + goto cleanup; + } else { + /* Ask using a prompter. */ + memset(prompt_reply, '\0', sizeof(prompt_reply)); + rdat.data = prompt_reply; + rdat.length = sizeof(prompt_reply); + + if (asprintf(&prompt_string, "%s %s", prompt_prefix, + idopts->cert_filename) < 0) { + prompt_string = NULL; + goto cleanup; + } + kprompt.prompt = prompt_string; + kprompt.hidden = 1; + kprompt.reply = &rdat; + prompt_type = KRB5_PROMPT_TYPE_PREAUTH; + /* PROMPTER_INVOCATION */ + k5int_set_prompt_types(context, &prompt_type); + r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data, + NULL, NULL, 1, &kprompt); + k5int_set_prompt_types(context, 0); + if (r) { + TRACE_PKINIT_PKCS_PROMPT_FAIL(context); + goto cleanup; + } + } + + ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL); + if (ret == 0) { + TRACE_PKINIT_PKCS_PARSE_FAIL_SECOND(context); + goto cleanup; + } + } + id_cryptoctx->creds[0] = malloc(sizeof(struct _pkinit_cred_info)); + if (id_cryptoctx->creds[0] == NULL) + goto cleanup; + id_cryptoctx->creds[0]->name = + reassemble_pkcs12_name(idopts->cert_filename); + id_cryptoctx->creds[0]->cert = x; +#ifndef WITHOUT_PKCS11 + id_cryptoctx->creds[0]->cert_id = NULL; + id_cryptoctx->creds[0]->cert_id_len = 0; +#endif + id_cryptoctx->creds[0]->key = y; + id_cryptoctx->creds[1] = NULL; + + retval = 0; + +cleanup: + free(prompt_string); + if (p12) + PKCS12_free(p12); + if (retval) { + if (x != NULL) + X509_free(x); + if (y != NULL) + EVP_PKEY_free(y); + } + return retval; +} + +static char * +reassemble_files_name(const char *certfile, const char *keyfile) +{ + char *ret; + + if (keyfile != NULL) { + if (asprintf(&ret, "FILE:%s,%s", certfile, keyfile) < 0) + return NULL; + } else { + if (asprintf(&ret, "FILE:%s", certfile) < 0) + return NULL; + } + return ret; +} + +static krb5_error_code +pkinit_load_fs_cert_and_key(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, + char *certname, + char *keyname, + int cindex) +{ + krb5_error_code retval; + X509 *x = NULL; + EVP_PKEY *y = NULL; + char *fsname = NULL; + const char *password; + + fsname = reassemble_files_name(certname, keyname); + + /* Try to read a responder-supplied password. */ + password = pkinit_find_deferred_id(id_cryptoctx->deferred_ids, fsname); + + /* Load the certificate. */ + retval = get_cert(certname, &x); + if (retval) { + retval = oerr(context, retval, _("Cannot read certificate file '%s'"), + certname); + } + if (retval || x == NULL) + goto cleanup; + /* Load the key. */ + retval = get_key(context, id_cryptoctx, keyname, fsname, &y, password); + if (retval) + retval = oerr(context, retval, _("Cannot read key file '%s'"), fsname); + if (retval || y == NULL) + goto cleanup; + + id_cryptoctx->creds[cindex] = malloc(sizeof(struct _pkinit_cred_info)); + if (id_cryptoctx->creds[cindex] == NULL) { + retval = ENOMEM; + goto cleanup; + } + id_cryptoctx->creds[cindex]->name = reassemble_files_name(certname, + keyname); + id_cryptoctx->creds[cindex]->cert = x; +#ifndef WITHOUT_PKCS11 + id_cryptoctx->creds[cindex]->cert_id = NULL; + id_cryptoctx->creds[cindex]->cert_id_len = 0; +#endif + id_cryptoctx->creds[cindex]->key = y; + id_cryptoctx->creds[cindex+1] = NULL; + + retval = 0; + +cleanup: + free(fsname); + if (retval != 0 || y == NULL) { + if (x != NULL) + X509_free(x); + if (y != NULL) + EVP_PKEY_free(y); + } + return retval; +} + +static krb5_error_code +pkinit_get_certs_fs(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_opts *idopts, + pkinit_identity_crypto_context id_cryptoctx, + krb5_principal princ) +{ + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + + if (idopts->cert_filename == NULL) { + pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__); + goto cleanup; + } + + if (idopts->key_filename == NULL) { + TRACE_PKINIT_NO_PRIVKEY(context); + goto cleanup; + } + + retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx, + idopts->cert_filename, + idopts->key_filename, 0); +cleanup: + return retval; +} + +static krb5_error_code +pkinit_get_certs_dir(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_opts *idopts, + pkinit_identity_crypto_context id_cryptoctx, + krb5_principal princ) +{ + krb5_error_code retval = ENOMEM; + DIR *d = NULL; + struct dirent *dentry = NULL; + char certname[1024]; + char keyname[1024]; + int i = 0, len; + char *dirname, *suf; + + if (idopts->cert_filename == NULL) { + TRACE_PKINIT_NO_CERT(context); + return ENOENT; + } + + dirname = idopts->cert_filename; + d = opendir(dirname); + if (d == NULL) + return errno; + + /* + * We'll assume that certs are named XXX.crt and the corresponding + * key is named XXX.key + */ + while ((i < MAX_CREDS_ALLOWED) && (dentry = readdir(d)) != NULL) { + /* Ignore subdirectories and anything starting with a dot */ +#ifdef DT_DIR + if (dentry->d_type == DT_DIR) + continue; +#endif + if (dentry->d_name[0] == '.') + continue; + len = strlen(dentry->d_name); + if (len < 5) + continue; + suf = dentry->d_name + (len - 4); + if (strncmp(suf, ".crt", 4) != 0) + continue; + + /* Checked length */ + if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(certname)) { + pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n", + __FUNCTION__, dirname, dentry->d_name); + continue; + } + snprintf(certname, sizeof(certname), "%s/%s", dirname, dentry->d_name); + snprintf(keyname, sizeof(keyname), "%s/%s", dirname, dentry->d_name); + len = strlen(keyname); + keyname[len - 3] = 'k'; + keyname[len - 2] = 'e'; + keyname[len - 1] = 'y'; + + retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx, + certname, keyname, i); + if (retval == 0) { + TRACE_PKINIT_LOADED_CERT(context, dentry->d_name); + i++; + } + else + continue; + } + + if (!id_cryptoctx->defer_id_prompt && i == 0) { + TRACE_PKINIT_NO_CERT_AND_KEY(context, idopts->cert_filename); + retval = ENOENT; + goto cleanup; + } + + retval = 0; + +cleanup: + if (d) + closedir(d); + + return retval; +} + +#ifndef WITHOUT_PKCS11 +static char * +reassemble_pkcs11_name(pkinit_identity_opts *idopts) +{ + struct k5buf buf; + int n = 0; + + k5_buf_init_dynamic(&buf); + k5_buf_add(&buf, "PKCS11:"); + n = 0; + if (idopts->p11_module_name != NULL) { + k5_buf_add_fmt(&buf, "%smodule_name=%s", n++ ? ":" : "", + idopts->p11_module_name); + } + if (idopts->token_label != NULL) { + k5_buf_add_fmt(&buf, "%stoken=%s", n++ ? ":" : "", + idopts->token_label); + } + if (idopts->cert_label != NULL) { + k5_buf_add_fmt(&buf, "%scertlabel=%s", n++ ? ":" : "", + idopts->cert_label); + } + if (idopts->cert_id_string != NULL) { + k5_buf_add_fmt(&buf, "%scertid=%s", n++ ? ":" : "", + idopts->cert_id_string); + } + if (idopts->slotid != PK_NOSLOT) { + k5_buf_add_fmt(&buf, "%sslotid=%ld", n++ ? ":" : "", + (long)idopts->slotid); + } + return k5_buf_cstring(&buf); +} + +static krb5_error_code +load_one_cert(CK_FUNCTION_LIST_PTR p11, CK_SESSION_HANDLE session, + pkinit_identity_opts *idopts, pkinit_cred_info *cred_out) +{ + krb5_error_code ret; + CK_ATTRIBUTE attrs[2]; + CK_BYTE_PTR cert = NULL, cert_id = NULL; + CK_RV pret; + const unsigned char *cp; + CK_OBJECT_HANDLE obj; + CK_ULONG count; + X509 *x = NULL; + pkinit_cred_info cred; + + *cred_out = NULL; + + /* Look for X.509 cert. */ + pret = p11->C_FindObjects(session, &obj, 1, &count); + if (pret != CKR_OK || count <= 0) + return 0; + + /* Get cert and id len. */ + attrs[0].type = CKA_VALUE; + attrs[0].pValue = NULL; + attrs[0].ulValueLen = 0; + attrs[1].type = CKA_ID; + attrs[1].pValue = NULL; + attrs[1].ulValueLen = 0; + pret = p11->C_GetAttributeValue(session, obj, attrs, 2); + if (pret != CKR_OK && pret != CKR_BUFFER_TOO_SMALL) { + pkiDebug("C_GetAttributeValue: %s\n", pkcs11err(pret)); + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + /* Allocate buffers and read the cert and id. */ + cert = k5alloc(attrs[0].ulValueLen + 1, &ret); + if (cert == NULL) + goto cleanup; + cert_id = k5alloc(attrs[1].ulValueLen + 1, &ret); + if (cert_id == NULL) + goto cleanup; + attrs[0].type = CKA_VALUE; + attrs[0].pValue = cert; + attrs[1].type = CKA_ID; + attrs[1].pValue = cert_id; + pret = p11->C_GetAttributeValue(session, obj, attrs, 2); + if (pret != CKR_OK) { + pkiDebug("C_GetAttributeValue: %s\n", pkcs11err(pret)); + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + pkiDebug("cert: size %d, id %d, idlen %d\n", (int)attrs[0].ulValueLen, + (int)cert_id[0], (int)attrs[1].ulValueLen); + + cp = (unsigned char *)cert; + x = d2i_X509(NULL, &cp, (int)attrs[0].ulValueLen); + if (x == NULL) { + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + cred = k5alloc(sizeof(struct _pkinit_cred_info), &ret); + if (cred == NULL) + goto cleanup; + + cred->name = reassemble_pkcs11_name(idopts); + cred->cert = x; + cred->key = NULL; + cred->cert_id = cert_id; + cred->cert_id_len = attrs[1].ulValueLen; + + *cred_out = cred; + cert_id = NULL; + ret = 0; + +cleanup: + free(cert); + free(cert_id); + return ret; +} + +static krb5_error_code +pkinit_get_certs_pkcs11(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_opts *idopts, + pkinit_identity_crypto_context id_cryptoctx, + krb5_principal princ) +{ + CK_OBJECT_CLASS cls; + CK_ATTRIBUTE attrs[4]; + CK_CERTIFICATE_TYPE certtype; + int i; + unsigned int nattrs; + krb5_error_code ret; + CK_RV pret; + + /* Copy stuff from idopts -> id_cryptoctx */ + if (idopts->p11_module_name != NULL) { + free(id_cryptoctx->p11_module_name); + id_cryptoctx->p11_module_name = strdup(idopts->p11_module_name); + if (id_cryptoctx->p11_module_name == NULL) + return ENOMEM; + } + if (idopts->token_label != NULL) { + id_cryptoctx->token_label = strdup(idopts->token_label); + if (id_cryptoctx->token_label == NULL) + return ENOMEM; + } + if (idopts->cert_label != NULL) { + id_cryptoctx->cert_label = strdup(idopts->cert_label); + if (id_cryptoctx->cert_label == NULL) + return ENOMEM; + } + /* Convert the ascii cert_id string into a binary blob */ + if (idopts->cert_id_string != NULL) { + ret = k5_hex_decode(idopts->cert_id_string, &id_cryptoctx->cert_id, + &id_cryptoctx->cert_id_len); + if (ret) { + pkiDebug("Failed to convert certid string [%s]\n", + idopts->cert_id_string); + return ret; + } + } + id_cryptoctx->slotid = idopts->slotid; + id_cryptoctx->pkcs11_method = 1; + + ret = pkinit_open_session(context, id_cryptoctx); + if (ret) + return ret; + if (id_cryptoctx->defer_id_prompt) { + /* + * We need to reset all of the PKCS#11 state, so that the next time we + * poke at it, it'll be in as close to the state it was in after we + * loaded it the first time as we can make it. + */ + pkinit_fini_pkcs11(id_cryptoctx); + pkinit_init_pkcs11(id_cryptoctx); + return 0; + } + + /* + * We'd like to use CKM_SHA256_RSA_PKCS for signing if it's available, but + * historically many cards seem to be confused about whether they are + * capable of mechanisms or not. The safe thing seems to be to ignore the + * mechanism list, always use CKM_RSA_PKCS and calculate the sha256 digest + * ourselves. + */ + id_cryptoctx->mech = CKM_RSA_PKCS; + + cls = CKO_CERTIFICATE; + attrs[0].type = CKA_CLASS; + attrs[0].pValue = &cls; + attrs[0].ulValueLen = sizeof(cls); + + certtype = CKC_X_509; + attrs[1].type = CKA_CERTIFICATE_TYPE; + attrs[1].pValue = &certtype; + attrs[1].ulValueLen = sizeof(certtype); + + nattrs = 2; + + /* If a cert id and/or label were given, use them too */ + if (id_cryptoctx->cert_id_len > 0) { + attrs[nattrs].type = CKA_ID; + attrs[nattrs].pValue = id_cryptoctx->cert_id; + attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len; + nattrs++; + } + if (id_cryptoctx->cert_label != NULL) { + attrs[nattrs].type = CKA_LABEL; + attrs[nattrs].pValue = id_cryptoctx->cert_label; + attrs[nattrs].ulValueLen = strlen(id_cryptoctx->cert_label); + nattrs++; + } + + pret = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, + nattrs); + if (pret != CKR_OK) { + pkiDebug("C_FindObjectsInit: %s\n", pkcs11err(pret)); + return KRB5KDC_ERR_PREAUTH_FAILED; + } + + for (i = 0; i < MAX_CREDS_ALLOWED; i++) { + ret = load_one_cert(id_cryptoctx->p11, id_cryptoctx->session, idopts, + &id_cryptoctx->creds[i]); + if (ret) + return ret; + if (id_cryptoctx->creds[i] == NULL) + break; + } + if (i == MAX_CREDS_ALLOWED) + return KRB5KDC_ERR_PREAUTH_FAILED; + + id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session); + + /* Check if we found no certs. */ + if (id_cryptoctx->creds[0] == NULL) + return KRB5KDC_ERR_PREAUTH_FAILED; + return 0; +} + +#endif /* !WITHOUT_PKCS11 */ + + +static void +free_cred_info(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, + struct _pkinit_cred_info *cred) +{ + if (cred != NULL) { + if (cred->cert != NULL) + X509_free(cred->cert); + if (cred->key != NULL) + EVP_PKEY_free(cred->key); +#ifndef WITHOUT_PKCS11 + free(cred->cert_id); +#endif + free(cred->name); + free(cred); + } +} + +krb5_error_code +crypto_free_cert_info(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx) +{ + int i; + + if (id_cryptoctx == NULL) + return EINVAL; + + for (i = 0; i < MAX_CREDS_ALLOWED; i++) { + if (id_cryptoctx->creds[i] != NULL) { + free_cred_info(context, id_cryptoctx, id_cryptoctx->creds[i]); + id_cryptoctx->creds[i] = NULL; + } + } + return 0; +} + +krb5_error_code +crypto_load_certs(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_opts *idopts, + pkinit_identity_crypto_context id_cryptoctx, + krb5_principal princ, + krb5_boolean defer_id_prompts) +{ + krb5_error_code retval; + + id_cryptoctx->defer_id_prompt = defer_id_prompts; + + switch(idopts->idtype) { + case IDTYPE_FILE: + retval = pkinit_get_certs_fs(context, plg_cryptoctx, + req_cryptoctx, idopts, + id_cryptoctx, princ); + break; + case IDTYPE_DIR: + retval = pkinit_get_certs_dir(context, plg_cryptoctx, + req_cryptoctx, idopts, + id_cryptoctx, princ); + break; +#ifndef WITHOUT_PKCS11 + case IDTYPE_PKCS11: + retval = pkinit_get_certs_pkcs11(context, plg_cryptoctx, + req_cryptoctx, idopts, + id_cryptoctx, princ); + break; +#endif + case IDTYPE_PKCS12: + retval = pkinit_get_certs_pkcs12(context, plg_cryptoctx, + req_cryptoctx, idopts, + id_cryptoctx, princ); + break; + default: + retval = EINVAL; + } + if (retval) + goto cleanup; + +cleanup: + return retval; +} + +/* + * Get certificate Key Usage and Extended Key Usage + */ +static krb5_error_code +crypto_retrieve_X509_key_usage(krb5_context context, + pkinit_plg_crypto_context plgcctx, + pkinit_req_crypto_context reqcctx, + X509 *x, + unsigned int *ret_ku_bits, + unsigned int *ret_eku_bits) +{ + krb5_error_code retval = 0; + int i; + unsigned int eku_bits = 0, ku_bits = 0; + ASN1_BIT_STRING *usage = NULL; + + if (ret_ku_bits == NULL && ret_eku_bits == NULL) + return EINVAL; + + if (ret_eku_bits) + *ret_eku_bits = 0; + else { + pkiDebug("%s: EKUs not requested, not checking\n", __FUNCTION__); + goto check_kus; + } + + /* Start with Extended Key usage */ + i = X509_get_ext_by_NID(x, NID_ext_key_usage, -1); + if (i >= 0) { + EXTENDED_KEY_USAGE *eku; + + eku = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL); + if (eku) { + for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) { + ASN1_OBJECT *certoid; + certoid = sk_ASN1_OBJECT_value(eku, i); + if ((OBJ_cmp(certoid, plgcctx->id_pkinit_KPClientAuth)) == 0) + eku_bits |= PKINIT_EKU_PKINIT; + else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_ms_smartcard_login))) == 0) + eku_bits |= PKINIT_EKU_MSSCLOGIN; + else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_client_auth))) == 0) + eku_bits |= PKINIT_EKU_CLIENTAUTH; + else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_email_protect))) == 0) + eku_bits |= PKINIT_EKU_EMAILPROTECTION; + } + EXTENDED_KEY_USAGE_free(eku); + } + } + pkiDebug("%s: returning eku 0x%08x\n", __FUNCTION__, eku_bits); + *ret_eku_bits = eku_bits; + +check_kus: + /* Now the Key Usage bits */ + if (ret_ku_bits) + *ret_ku_bits = 0; + else { + pkiDebug("%s: KUs not requested, not checking\n", __FUNCTION__); + goto out; + } + + /* Make sure usage exists before checking bits */ + X509_check_ca(x); + usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL); + if (usage) { + if (!ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE)) + ku_bits |= PKINIT_KU_DIGITALSIGNATURE; + if (!ku_reject(x, X509v3_KU_KEY_ENCIPHERMENT)) + ku_bits |= PKINIT_KU_KEYENCIPHERMENT; + ASN1_BIT_STRING_free(usage); + } + + pkiDebug("%s: returning ku 0x%08x\n", __FUNCTION__, ku_bits); + *ret_ku_bits = ku_bits; + retval = 0; +out: + return retval; +} + +static krb5_error_code +rfc2253_name(X509_NAME *name, char **str_out) +{ + BIO *b = NULL; + char *str; + + *str_out = NULL; + b = BIO_new(BIO_s_mem()); + if (b == NULL) + return ENOMEM; + if (X509_NAME_print_ex(b, name, 0, XN_FLAG_SEP_COMMA_PLUS) < 0) + goto error; + str = calloc(BIO_number_written(b) + 1, 1); + if (str == NULL) + goto error; + BIO_read(b, str, BIO_number_written(b)); + BIO_free(b); + *str_out = str; + return 0; + +error: + BIO_free(b); + return ENOMEM; +} + +/* + * Get number of certificates available after crypto_load_certs() + */ +static krb5_error_code +crypto_cert_get_count(pkinit_identity_crypto_context id_cryptoctx, + int *cert_count) +{ + int count; + + *cert_count = 0; + if (id_cryptoctx == NULL || id_cryptoctx->creds[0] == NULL) + return EINVAL; + + for (count = 0; + count <= MAX_CREDS_ALLOWED && id_cryptoctx->creds[count] != NULL; + count++); + *cert_count = count; + return 0; +} + +void +crypto_cert_free_matching_data(krb5_context context, + pkinit_cert_matching_data *md) +{ + int i; + + if (md == NULL) + return; + free(md->subject_dn); + free(md->issuer_dn); + for (i = 0; md->sans != NULL && md->sans[i] != NULL; i++) + krb5_free_principal(context, md->sans[i]); + free(md->sans); + for (i = 0; md->upns != NULL && md->upns[i] != NULL; i++) + free(md->upns[i]); + free(md->upns); + free(md); +} + +/* + * Free certificate matching data. + */ +void +crypto_cert_free_matching_data_list(krb5_context context, + pkinit_cert_matching_data **list) +{ + int i; + + for (i = 0; list != NULL && list[i] != NULL; i++) + crypto_cert_free_matching_data(context, list[i]); + free(list); +} + +/* + * Get certificate matching data for cert. + */ +static krb5_error_code +get_matching_data(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, X509 *cert, + pkinit_cert_matching_data **md_out) +{ + krb5_error_code ret = ENOMEM; + pkinit_cert_matching_data *md = NULL; + + *md_out = NULL; + + md = calloc(1, sizeof(*md)); + if (md == NULL) + goto cleanup; + + ret = rfc2253_name(X509_get_subject_name(cert), &md->subject_dn); + if (ret) + goto cleanup; + ret = rfc2253_name(X509_get_issuer_name(cert), &md->issuer_dn); + if (ret) + goto cleanup; + + /* Get the SAN data. */ + ret = crypto_retrieve_X509_sans(context, plg_cryptoctx, req_cryptoctx, + cert, &md->sans, &md->upns, NULL); + if (ret) + goto cleanup; + + /* Get the KU and EKU data. */ + ret = crypto_retrieve_X509_key_usage(context, plg_cryptoctx, + req_cryptoctx, cert, &md->ku_bits, + &md->eku_bits); + if (ret) + goto cleanup; + + *md_out = md; + md = NULL; + +cleanup: + crypto_cert_free_matching_data(context, md); + return ret; +} + +krb5_error_code +crypto_cert_get_matching_data(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + pkinit_cert_matching_data ***md_out) +{ + krb5_error_code ret; + pkinit_cert_matching_data **md_list = NULL; + int count, i; + + ret = crypto_cert_get_count(id_cryptoctx, &count); + if (ret) + goto cleanup; + + md_list = calloc(count + 1, sizeof(*md_list)); + if (md_list == NULL) { + ret = ENOMEM; + goto cleanup; + } + + for (i = 0; i < count; i++) { + ret = get_matching_data(context, plg_cryptoctx, req_cryptoctx, + id_cryptoctx->creds[i]->cert, &md_list[i]); + if (ret) { + pkiDebug("%s: crypto_cert_get_matching_data error %d, %s\n", + __FUNCTION__, ret, error_message(ret)); + goto cleanup; + } + } + + *md_out = md_list; + md_list = NULL; + +cleanup: + crypto_cert_free_matching_data_list(context, md_list); + return ret; +} + +/* + * Set the certificate in idctx->creds[cred_index] as the selected certificate. + */ +krb5_error_code +crypto_cert_select(krb5_context context, pkinit_identity_crypto_context idctx, + size_t cred_index) +{ + pkinit_cred_info ci = NULL; + + if (cred_index >= MAX_CREDS_ALLOWED || idctx->creds[cred_index] == NULL) + return ENOENT; + + ci = idctx->creds[cred_index]; + /* copy the selected cert into our id_cryptoctx */ + if (idctx->my_certs != NULL) + sk_X509_pop_free(idctx->my_certs, X509_free); + idctx->my_certs = sk_X509_new_null(); + sk_X509_push(idctx->my_certs, ci->cert); + free(idctx->identity); + /* hang on to the selected credential name */ + if (ci->name != NULL) + idctx->identity = strdup(ci->name); + else + idctx->identity = NULL; + + ci->cert = NULL; /* Don't free it twice */ + idctx->cert_index = 0; + if (idctx->pkcs11_method != 1) { + idctx->my_key = ci->key; + ci->key = NULL; /* Don't free it twice */ + } +#ifndef WITHOUT_PKCS11 + else { + idctx->cert_id = ci->cert_id; + ci->cert_id = NULL; /* Don't free it twice */ + idctx->cert_id_len = ci->cert_id_len; + } +#endif + return 0; +} + +/* + * Choose the default certificate as "the chosen one" + */ +krb5_error_code +crypto_cert_select_default(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx) +{ + krb5_error_code retval; + int cert_count; + + retval = crypto_cert_get_count(id_cryptoctx, &cert_count); + if (retval) + goto errout; + + if (cert_count != 1) { + TRACE_PKINIT_NO_DEFAULT_CERT(context, cert_count); + retval = EINVAL; + goto errout; + } + /* copy the selected cert into our id_cryptoctx */ + if (id_cryptoctx->my_certs != NULL) { + sk_X509_pop_free(id_cryptoctx->my_certs, X509_free); + } + id_cryptoctx->my_certs = sk_X509_new_null(); + sk_X509_push(id_cryptoctx->my_certs, id_cryptoctx->creds[0]->cert); + id_cryptoctx->creds[0]->cert = NULL; /* Don't free it twice */ + id_cryptoctx->cert_index = 0; + /* hang on to the selected credential name */ + if (id_cryptoctx->creds[0]->name != NULL) + id_cryptoctx->identity = strdup(id_cryptoctx->creds[0]->name); + else + id_cryptoctx->identity = NULL; + + if (id_cryptoctx->pkcs11_method != 1) { + id_cryptoctx->my_key = id_cryptoctx->creds[0]->key; + id_cryptoctx->creds[0]->key = NULL; /* Don't free it twice */ + } +#ifndef WITHOUT_PKCS11 + else { + id_cryptoctx->cert_id = id_cryptoctx->creds[0]->cert_id; + id_cryptoctx->creds[0]->cert_id = NULL; /* Don't free it twice */ + id_cryptoctx->cert_id_len = id_cryptoctx->creds[0]->cert_id_len; + } +#endif + retval = 0; +errout: + return retval; +} + + + +static krb5_error_code +load_cas_and_crls(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + int catype, + char *filename) +{ + STACK_OF(X509_INFO) *sk = NULL; + STACK_OF(X509) *ca_certs = NULL; + STACK_OF(X509_CRL) *ca_crls = NULL; + BIO *in = NULL; + krb5_error_code retval = ENOMEM; + int i = 0; + + /* If there isn't already a stack in the context, + * create a temporary one now */ + switch(catype) { + case CATYPE_ANCHORS: + if (id_cryptoctx->trustedCAs != NULL) + ca_certs = id_cryptoctx->trustedCAs; + else { + ca_certs = sk_X509_new_null(); + if (ca_certs == NULL) + return ENOMEM; + } + break; + case CATYPE_INTERMEDIATES: + if (id_cryptoctx->intermediateCAs != NULL) + ca_certs = id_cryptoctx->intermediateCAs; + else { + ca_certs = sk_X509_new_null(); + if (ca_certs == NULL) + return ENOMEM; + } + break; + case CATYPE_CRLS: + if (id_cryptoctx->revoked != NULL) + ca_crls = id_cryptoctx->revoked; + else { + ca_crls = sk_X509_CRL_new_null(); + if (ca_crls == NULL) + return ENOMEM; + } + break; + default: + return ENOTSUP; + } + + if (!(in = BIO_new_file(filename, "r"))) { + retval = oerr(context, 0, _("Cannot open file '%s'"), filename); + goto cleanup; + } + + /* This loads from a file, a stack of x509/crl/pkey sets */ + if ((sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL)) == NULL) { + pkiDebug("%s: error reading file '%s'\n", __FUNCTION__, filename); + retval = oerr(context, 0, _("Cannot read file '%s'"), filename); + goto cleanup; + } + + /* scan over the stack created from loading the file contents, + * weed out duplicates, and push new ones onto the return stack + */ + for (i = 0; i < sk_X509_INFO_num(sk); i++) { + X509_INFO *xi = sk_X509_INFO_value(sk, i); + if (xi != NULL && xi->x509 != NULL && catype != CATYPE_CRLS) { + int j = 0, size = sk_X509_num(ca_certs), flag = 0; + + if (!size) { + sk_X509_push(ca_certs, xi->x509); + xi->x509 = NULL; + continue; + } + for (j = 0; j < size; j++) { + X509 *x = sk_X509_value(ca_certs, j); + flag = X509_cmp(x, xi->x509); + if (flag == 0) + break; + else + continue; + } + if (flag != 0) { + sk_X509_push(ca_certs, X509_dup(xi->x509)); + } + } else if (xi != NULL && xi->crl != NULL && catype == CATYPE_CRLS) { + int j = 0, size = sk_X509_CRL_num(ca_crls), flag = 0; + if (!size) { + sk_X509_CRL_push(ca_crls, xi->crl); + xi->crl = NULL; + continue; + } + for (j = 0; j < size; j++) { + X509_CRL *x = sk_X509_CRL_value(ca_crls, j); + flag = X509_CRL_cmp(x, xi->crl); + if (flag == 0) + break; + else + continue; + } + if (flag != 0) { + sk_X509_CRL_push(ca_crls, X509_CRL_dup(xi->crl)); + } + } + } + + /* If we added something and there wasn't a stack in the + * context before, add the temporary stack to the context. + */ + switch(catype) { + case CATYPE_ANCHORS: + if (sk_X509_num(ca_certs) == 0) { + TRACE_PKINIT_NO_CA_ANCHOR(context, filename); + if (id_cryptoctx->trustedCAs == NULL) + sk_X509_free(ca_certs); + } else { + if (id_cryptoctx->trustedCAs == NULL) + id_cryptoctx->trustedCAs = ca_certs; + } + break; + case CATYPE_INTERMEDIATES: + if (sk_X509_num(ca_certs) == 0) { + TRACE_PKINIT_NO_CA_INTERMEDIATE(context, filename); + if (id_cryptoctx->intermediateCAs == NULL) + sk_X509_free(ca_certs); + } else { + if (id_cryptoctx->intermediateCAs == NULL) + id_cryptoctx->intermediateCAs = ca_certs; + } + break; + case CATYPE_CRLS: + if (sk_X509_CRL_num(ca_crls) == 0) { + TRACE_PKINIT_NO_CRL(context, filename); + if (id_cryptoctx->revoked == NULL) + sk_X509_CRL_free(ca_crls); + } else { + if (id_cryptoctx->revoked == NULL) + id_cryptoctx->revoked = ca_crls; + } + break; + default: + /* Should have been caught above! */ + retval = EINVAL; + goto cleanup; + break; + } + + retval = 0; + +cleanup: + if (in != NULL) + BIO_free(in); + if (sk != NULL) + sk_X509_INFO_pop_free(sk, X509_INFO_free); + + return retval; +} + +static krb5_error_code +load_cas_and_crls_dir(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + int catype, + char *dirname) +{ + krb5_error_code retval = EINVAL; + DIR *d = NULL; + struct dirent *dentry = NULL; + char filename[1024]; + + if (dirname == NULL) + return EINVAL; + + d = opendir(dirname); + if (d == NULL) + return ENOENT; + + while ((dentry = readdir(d))) { + if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(filename)) { + pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n", + __FUNCTION__, dirname, dentry->d_name); + goto cleanup; + } + /* Ignore subdirectories and anything starting with a dot */ +#ifdef DT_DIR + if (dentry->d_type == DT_DIR) + continue; +#endif + if (dentry->d_name[0] == '.') + continue; + snprintf(filename, sizeof(filename), "%s/%s", dirname, dentry->d_name); + + retval = load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx, + id_cryptoctx, catype, filename); + if (retval) + goto cleanup; + } + + retval = 0; + +cleanup: + if (d != NULL) + closedir(d); + + return retval; +} + +krb5_error_code +crypto_load_cas_and_crls(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_opts *idopts, + pkinit_identity_crypto_context id_cryptoctx, + int idtype, + int catype, + char *id) +{ + switch (idtype) { + case IDTYPE_FILE: + TRACE_PKINIT_LOAD_FROM_FILE(context, id); + return load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx, + id_cryptoctx, catype, id); + break; + case IDTYPE_DIR: + TRACE_PKINIT_LOAD_FROM_DIR(context, id); + return load_cas_and_crls_dir(context, plg_cryptoctx, req_cryptoctx, + id_cryptoctx, catype, id); + break; + default: + return ENOTSUP; + break; + } +} + +static krb5_error_code +create_identifiers_from_stack(STACK_OF(X509) *sk, + krb5_external_principal_identifier *** ids) +{ + int i = 0, sk_size = sk_X509_num(sk); + krb5_external_principal_identifier **krb5_cas = NULL; + X509 *x = NULL; + X509_NAME *xn = NULL; + unsigned char *p = NULL; + int len = 0; + PKCS7_ISSUER_AND_SERIAL *is = NULL; + char buf[DN_BUF_LEN]; + + *ids = NULL; + + krb5_cas = calloc(sk_size + 1, sizeof(*krb5_cas)); + if (krb5_cas == NULL) + return ENOMEM; + + for (i = 0; i < sk_size; i++) { + krb5_cas[i] = malloc(sizeof(krb5_external_principal_identifier)); + + x = sk_X509_value(sk, i); + + X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf)); + pkiDebug("#%d cert= %s\n", i, buf); + + /* fill-in subjectName */ + krb5_cas[i]->subjectName.magic = 0; + krb5_cas[i]->subjectName.length = 0; + krb5_cas[i]->subjectName.data = NULL; + + xn = X509_get_subject_name(x); + len = i2d_X509_NAME(xn, NULL); + if ((p = malloc((size_t) len)) == NULL) + goto oom; + krb5_cas[i]->subjectName.data = (char *)p; + i2d_X509_NAME(xn, &p); + krb5_cas[i]->subjectName.length = len; + + /* fill-in issuerAndSerialNumber */ + krb5_cas[i]->issuerAndSerialNumber.length = 0; + krb5_cas[i]->issuerAndSerialNumber.magic = 0; + krb5_cas[i]->issuerAndSerialNumber.data = NULL; + + is = PKCS7_ISSUER_AND_SERIAL_new(); + if (is == NULL) + goto oom; + X509_NAME_set(&is->issuer, X509_get_issuer_name(x)); + ASN1_INTEGER_free(is->serial); + is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(x)); + if (is->serial == NULL) + goto oom; + len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL); + p = malloc(len); + if (p == NULL) + goto oom; + krb5_cas[i]->issuerAndSerialNumber.data = (char *)p; + i2d_PKCS7_ISSUER_AND_SERIAL(is, &p); + krb5_cas[i]->issuerAndSerialNumber.length = len; + + /* fill-in subjectKeyIdentifier */ + krb5_cas[i]->subjectKeyIdentifier.length = 0; + krb5_cas[i]->subjectKeyIdentifier.magic = 0; + krb5_cas[i]->subjectKeyIdentifier.data = NULL; + + if (X509_get_ext_by_NID(x, NID_subject_key_identifier, -1) >= 0) { + ASN1_OCTET_STRING *ikeyid; + + ikeyid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, + NULL); + if (ikeyid != NULL) { + len = i2d_ASN1_OCTET_STRING(ikeyid, NULL); + p = malloc(len); + if (p == NULL) + goto oom; + krb5_cas[i]->subjectKeyIdentifier.data = (char *)p; + i2d_ASN1_OCTET_STRING(ikeyid, &p); + krb5_cas[i]->subjectKeyIdentifier.length = len; + ASN1_OCTET_STRING_free(ikeyid); + } + } + PKCS7_ISSUER_AND_SERIAL_free(is); + is = NULL; + } + + *ids = krb5_cas; + return 0; + +oom: + free_krb5_external_principal_identifier(&krb5_cas); + PKCS7_ISSUER_AND_SERIAL_free(is); + return ENOMEM; +} + +static krb5_error_code +create_krb5_invalidCertificates(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_external_principal_identifier *** ids) +{ + + krb5_error_code retval = ENOMEM; + STACK_OF(X509) *sk = NULL; + + *ids = NULL; + if (req_cryptoctx->received_cert == NULL) + return KRB5KDC_ERR_PREAUTH_FAILED; + + sk = sk_X509_new_null(); + if (sk == NULL) + goto cleanup; + sk_X509_push(sk, req_cryptoctx->received_cert); + + retval = create_identifiers_from_stack(sk, ids); + + sk_X509_free(sk); +cleanup: + + return retval; +} + +krb5_error_code +create_krb5_supportedCMSTypes(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_algorithm_identifier ***algs_out) +{ + krb5_error_code ret; + krb5_algorithm_identifier **algs = NULL; + size_t i, count; + + *algs_out = NULL; + + /* Count supported OIDs and allocate list (including null terminator). */ + for (count = 0; supported_cms_algs[count] != NULL; count++); + algs = k5calloc(count + 1, sizeof(*algs), &ret); + if (algs == NULL) + goto cleanup; + + /* Add an algorithm identifier for each OID, with no parameters. */ + for (i = 0; i < count; i++) { + algs[i] = k5alloc(sizeof(*algs[i]), &ret); + if (algs[i] == NULL) + goto cleanup; + ret = krb5int_copy_data_contents(context, supported_cms_algs[i], + &algs[i]->algorithm); + if (ret) + goto cleanup; + algs[i]->parameters = empty_data(); + } + + *algs_out = algs; + algs = NULL; + +cleanup: + free_krb5_algorithm_identifiers(&algs); + return ret; +} + +krb5_error_code +create_krb5_trustedCertifiers(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_external_principal_identifier *** ids) +{ + + krb5_error_code retval = ENOMEM; + STACK_OF(X509) *sk = id_cryptoctx->trustedCAs; + + *ids = NULL; + if (id_cryptoctx->trustedCAs == NULL) + return KRB5KDC_ERR_PREAUTH_FAILED; + + retval = create_identifiers_from_stack(sk, ids); + + return retval; +} + +krb5_error_code +create_issuerAndSerial(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + unsigned char **out, + unsigned int *out_len) +{ + unsigned char *p = NULL; + PKCS7_ISSUER_AND_SERIAL *is = NULL; + int len = 0; + krb5_error_code retval = ENOMEM; + X509 *cert = req_cryptoctx->received_cert; + + *out = NULL; + *out_len = 0; + if (req_cryptoctx->received_cert == NULL) + return 0; + + is = PKCS7_ISSUER_AND_SERIAL_new(); + X509_NAME_set(&is->issuer, X509_get_issuer_name(cert)); + ASN1_INTEGER_free(is->serial); + is->serial = ASN1_INTEGER_dup(X509_get_serialNumber(cert)); + len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL); + if ((p = *out = malloc((size_t) len)) == NULL) + goto cleanup; + i2d_PKCS7_ISSUER_AND_SERIAL(is, &p); + *out_len = len; + retval = 0; + +cleanup: + X509_NAME_free(is->issuer); + ASN1_INTEGER_free(is->serial); + free(is); + + return retval; +} + +krb5_error_code +pkinit_process_td_trusted_certifiers( + krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_external_principal_identifier **krb5_trusted_certifiers, + int td_type) +{ + krb5_error_code retval = ENOMEM; + STACK_OF(X509_NAME) *sk_xn = NULL; + X509_NAME *xn = NULL; + PKCS7_ISSUER_AND_SERIAL *is = NULL; + ASN1_OCTET_STRING *id = NULL; + const unsigned char *p = NULL; + char buf[DN_BUF_LEN]; + int i = 0; + + if (td_type == TD_TRUSTED_CERTIFIERS) + pkiDebug("received trusted certifiers\n"); + else + pkiDebug("received invalid certificate\n"); + + sk_xn = sk_X509_NAME_new_null(); + while(krb5_trusted_certifiers[i] != NULL) { + if (krb5_trusted_certifiers[i]->subjectName.data != NULL) { + p = (unsigned char *)krb5_trusted_certifiers[i]->subjectName.data; + xn = d2i_X509_NAME(NULL, &p, + (int)krb5_trusted_certifiers[i]->subjectName.length); + if (xn == NULL) + goto cleanup; + X509_NAME_oneline(xn, buf, sizeof(buf)); + if (td_type == TD_TRUSTED_CERTIFIERS) + pkiDebug("#%d cert = %s is trusted by kdc\n", i, buf); + else + pkiDebug("#%d cert = %s is invalid\n", i, buf); + sk_X509_NAME_push(sk_xn, xn); + } + + if (krb5_trusted_certifiers[i]->issuerAndSerialNumber.data != NULL) { + p = (unsigned char *) + krb5_trusted_certifiers[i]->issuerAndSerialNumber.data; + is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p, + (int)krb5_trusted_certifiers[i]->issuerAndSerialNumber.length); + if (is == NULL) + goto cleanup; + X509_NAME_oneline(is->issuer, buf, sizeof(buf)); + if (td_type == TD_TRUSTED_CERTIFIERS) + pkiDebug("#%d issuer = %s serial = %ld is trusted bu kdc\n", i, + buf, ASN1_INTEGER_get(is->serial)); + else + pkiDebug("#%d issuer = %s serial = %ld is invalid\n", i, buf, + ASN1_INTEGER_get(is->serial)); + PKCS7_ISSUER_AND_SERIAL_free(is); + } + + if (krb5_trusted_certifiers[i]->subjectKeyIdentifier.data != NULL) { + p = (unsigned char *) + krb5_trusted_certifiers[i]->subjectKeyIdentifier.data; + id = d2i_ASN1_OCTET_STRING(NULL, &p, + (int)krb5_trusted_certifiers[i]->subjectKeyIdentifier.length); + if (id == NULL) + goto cleanup; + /* XXX */ + ASN1_OCTET_STRING_free(id); + } + i++; + } + /* XXX Since we not doing anything with received trusted certifiers + * return an error. this is the place where we can pick a different + * client certificate based on the information in td_trusted_certifiers + */ + retval = KRB5KDC_ERR_PREAUTH_FAILED; +cleanup: + if (sk_xn != NULL) + sk_X509_NAME_pop_free(sk_xn, X509_NAME_free); + + return retval; +} + +/* Originally based on OpenSSL's PKCS7_dataDecode(), now modified to remove the + * use of BIO objects and to fit the PKINIT internal interfaces. */ +static int +pkcs7_decrypt(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, PKCS7 *p7, + unsigned char **data_out, unsigned int *len_out) +{ + krb5_error_code ret; + int ok = 0, plaintext_len = 0, final_len; + unsigned int keylen = 0, eklen = 0, blocksize; + unsigned char *ek = NULL, *tkey = NULL, *plaintext = NULL, *use_key; + ASN1_OCTET_STRING *data_body = p7->d.enveloped->enc_data->enc_data; + const EVP_CIPHER *evp_cipher; + EVP_CIPHER_CTX *evp_ctx = NULL; + X509_ALGOR *enc_alg = p7->d.enveloped->enc_data->algorithm; + STACK_OF(PKCS7_RECIP_INFO) *rsk = p7->d.enveloped->recipientinfo; + PKCS7_RECIP_INFO *ri = NULL; + + *data_out = NULL; + *len_out = 0; + + p7->state = PKCS7_S_HEADER; + + /* RFC 4556 section 3.2.3.2 requires that there be exactly one + * recipientInfo. */ + if (sk_PKCS7_RECIP_INFO_num(rsk) != 1) { + pkiDebug("invalid number of EnvelopedData RecipientInfos\n"); + return 0; + } + ri = sk_PKCS7_RECIP_INFO_value(rsk, 0); + + evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); + if (evp_cipher == NULL) + goto cleanup; + keylen = EVP_CIPHER_key_length(evp_cipher); + blocksize = EVP_CIPHER_block_size(evp_cipher); + + evp_ctx = EVP_CIPHER_CTX_new(); + if (evp_ctx == NULL) + goto cleanup; + if (!EVP_DecryptInit(evp_ctx, evp_cipher, NULL, NULL) || + EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) <= 0) + goto cleanup; + + /* Generate a random symmetric key to avoid exposing timing data if RSA + * decryption fails the padding check. */ + tkey = malloc(keylen); + if (tkey == NULL || !EVP_CIPHER_CTX_rand_key(evp_ctx, tkey)) + goto cleanup; + + /* Decrypt the secret key with the private key. */ + ret = pkinit_decode_data(context, id_cryptoctx, + ASN1_STRING_get0_data(ri->enc_key), + ASN1_STRING_length(ri->enc_key), &ek, &eklen); + use_key = (ret || eklen != keylen) ? tkey : ek; + + /* Allocate a plaintext buffer and decrypt data_body into it. */ + plaintext = malloc(data_body->length + blocksize); + if (plaintext == NULL) + goto cleanup; + if (!EVP_DecryptInit(evp_ctx, NULL, use_key, NULL)) + goto cleanup; + if (!EVP_DecryptUpdate(evp_ctx, plaintext, &plaintext_len, + data_body->data, data_body->length)) + goto cleanup; + if (!EVP_DecryptFinal(evp_ctx, plaintext + plaintext_len, &final_len)) + goto cleanup; + plaintext_len += final_len; + + *len_out = plaintext_len; + *data_out = plaintext; + plaintext = NULL; + ok = 1; + +cleanup: + EVP_CIPHER_CTX_free(evp_ctx); + zapfree(plaintext, plaintext_len); + zapfree(ek, eklen); + zapfree(tkey, keylen); + return ok; +} + +#ifdef DEBUG_DH +static void +print_dh(DH * dh, char *msg) +{ + BIO *bio_err = NULL; + + bio_err = BIO_new(BIO_s_file()); + BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); + + if (msg) + BIO_puts(bio_err, (const char *)msg); + if (dh) + DHparams_print(bio_err, dh); + + BIO_puts(bio_err, "private key: "); + BN_print(bio_err, dh->priv_key); + BIO_puts(bio_err, (const char *)"\n"); + BIO_free(bio_err); + +} + +static void +print_pubkey(BIGNUM * key, char *msg) +{ + BIO *bio_err = NULL; + + bio_err = BIO_new(BIO_s_file()); + BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT); + + if (msg) + BIO_puts(bio_err, (const char *)msg); + if (key) + BN_print(bio_err, key); + BIO_puts(bio_err, "\n"); + + BIO_free(bio_err); + +} +#endif + +static const char * +pkcs11err(int err) +{ + int i; + + for (i = 0; pkcs11_errstrings[i].text != NULL; i++) + if (pkcs11_errstrings[i].code == err) + break; + if (pkcs11_errstrings[i].text != NULL) + return (pkcs11_errstrings[i].text); + + return "unknown PKCS11 error"; +} + +/* + * Add an item to the pkinit_identity_crypto_context's list of deferred + * identities. + */ +krb5_error_code +crypto_set_deferred_id(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx, + const char *identity, const char *password) +{ + unsigned long ck_flags; + + ck_flags = pkinit_get_deferred_id_flags(id_cryptoctx->deferred_ids, + identity); + return pkinit_set_deferred_id(&id_cryptoctx->deferred_ids, + identity, ck_flags, password); +} + +/* + * Retrieve a read-only copy of the pkinit_identity_crypto_context's list of + * deferred identities, sure to be valid only until the next time someone calls + * either pkinit_set_deferred_id() or crypto_set_deferred_id(). + */ +const pkinit_deferred_id * +crypto_get_deferred_ids(krb5_context context, + pkinit_identity_crypto_context id_cryptoctx) +{ + pkinit_deferred_id *deferred; + const pkinit_deferred_id *ret; + + deferred = id_cryptoctx->deferred_ids; + ret = (const pkinit_deferred_id *)deferred; + return ret; +} + +/* Return the received certificate as DER-encoded data. */ +krb5_error_code +crypto_encode_der_cert(krb5_context context, pkinit_req_crypto_context reqctx, + uint8_t **der_out, size_t *der_len) +{ + int len; + unsigned char *der, *p; + + *der_out = NULL; + *der_len = 0; + + if (reqctx->received_cert == NULL) + return EINVAL; + p = NULL; + len = i2d_X509(reqctx->received_cert, NULL); + if (len <= 0) + return EINVAL; + p = der = malloc(len); + if (der == NULL) + return ENOMEM; + if (i2d_X509(reqctx->received_cert, &p) <= 0) { + free(der); + return EINVAL; + } + *der_out = der; + *der_len = len; + return 0; +} + +/* + * Get the certificate matching data from the request certificate. + */ +krb5_error_code +crypto_req_cert_matching_data(krb5_context context, + pkinit_plg_crypto_context plgctx, + pkinit_req_crypto_context reqctx, + pkinit_cert_matching_data **md_out) +{ + *md_out = NULL; + + if (reqctx == NULL || reqctx->received_cert == NULL) + return ENOENT; + + return get_matching_data(context, plgctx, reqctx, reqctx->received_cert, + md_out); +} diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h new file mode 100644 index 00000000..c807f044 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_crypto_openssl.h @@ -0,0 +1,119 @@ +/* + * COPYRIGHT (C) 2006,2007 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#ifndef _PKINIT_CRYPTO_OPENSSL_H +#define _PKINIT_CRYPTO_OPENSSL_H + +#include "pkinit.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#include +#endif + +#define DN_BUF_LEN 256 +#define MAX_CREDS_ALLOWED 20 + +struct _pkinit_cred_info { + char *name; + X509 *cert; + EVP_PKEY *key; +#ifndef WITHOUT_PKCS11 + CK_BYTE_PTR cert_id; + int cert_id_len; +#endif +}; +typedef struct _pkinit_cred_info * pkinit_cred_info; + +struct _pkinit_identity_crypto_context { + pkinit_cred_info creds[MAX_CREDS_ALLOWED+1]; + STACK_OF(X509) *my_certs; /* available user certs */ + char *identity; /* identity name for user cert */ + int cert_index; /* cert to use out of available certs*/ + EVP_PKEY *my_key; /* available user keys if in filesystem */ + STACK_OF(X509) *trustedCAs; /* available trusted ca certs */ + STACK_OF(X509) *intermediateCAs; /* available intermediate ca certs */ + STACK_OF(X509_CRL) *revoked; /* available crls */ + int pkcs11_method; + krb5_prompter_fct prompter; + void *prompter_data; +#ifndef WITHOUT_PKCS11 + char *p11_module_name; + CK_SLOT_ID slotid; + char *token_label; + char *cert_label; + /* These are crypto-specific */ + struct plugin_file_handle *p11_module; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST_PTR p11; + uint8_t *cert_id; + size_t cert_id_len; + CK_MECHANISM_TYPE mech; +#endif + krb5_boolean defer_id_prompt; + pkinit_deferred_id *deferred_ids; +}; + +struct _pkinit_plg_crypto_context { + EVP_PKEY *dh_1024; + EVP_PKEY *dh_2048; + EVP_PKEY *dh_4096; + ASN1_OBJECT *id_pkinit_authData; + ASN1_OBJECT *id_pkinit_DHKeyData; + ASN1_OBJECT *id_pkinit_rkeyData; + ASN1_OBJECT *id_pkinit_san; + ASN1_OBJECT *id_ms_san_upn; + ASN1_OBJECT *id_pkinit_KPClientAuth; + ASN1_OBJECT *id_pkinit_KPKdc; + ASN1_OBJECT *id_ms_kp_sc_logon; + ASN1_OBJECT *id_kp_serverAuth; +}; + +struct _pkinit_req_crypto_context { + X509 *received_cert; + EVP_PKEY *client_pkey; + EVP_PKEY *received_params; +}; + +#endif /* _PKINIT_CRYPTO_OPENSSL_H */ diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_identity.c b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_identity.c new file mode 100644 index 00000000..a5a979f2 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_identity.c @@ -0,0 +1,791 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * COPYRIGHT (C) 2007 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#include "pkinit.h" +#include + +static void +free_list(char **list) +{ + int i; + + if (list == NULL) + return; + + for (i = 0; list[i] != NULL; i++) + free(list[i]); + free(list); +} + +static krb5_error_code +copy_list(char ***dst, char **src) +{ + int i; + char **newlist; + + if (dst == NULL) + return EINVAL; + *dst = NULL; + + if (src == NULL) + return 0; + + for (i = 0; src[i] != NULL; i++); + + newlist = calloc(1, (i + 1) * sizeof(*newlist)); + if (newlist == NULL) + return ENOMEM; + + for (i = 0; src[i] != NULL; i++) { + newlist[i] = strdup(src[i]); + if (newlist[i] == NULL) + goto cleanup; + } + newlist[i] = NULL; + *dst = newlist; + return 0; +cleanup: + free_list(newlist); + return ENOMEM; +} + +char * +idtype2string(int idtype) +{ + switch(idtype) { + case IDTYPE_FILE: return "FILE"; break; + case IDTYPE_DIR: return "DIR"; break; + case IDTYPE_PKCS11: return "PKCS11"; break; + case IDTYPE_PKCS12: return "PKCS12"; break; + case IDTYPE_ENVVAR: return "ENV"; break; + default: return "INVALID"; break; + } +} + +char * +catype2string(int catype) +{ + switch(catype) { + case CATYPE_ANCHORS: return "ANCHORS"; break; + case CATYPE_INTERMEDIATES: return "INTERMEDIATES"; break; + case CATYPE_CRLS: return "CRLS"; break; + default: return "INVALID"; break; + } +} + +krb5_error_code +pkinit_init_identity_opts(pkinit_identity_opts **idopts) +{ + pkinit_identity_opts *opts = NULL; + + *idopts = NULL; + opts = calloc(1, sizeof(pkinit_identity_opts)); + if (opts == NULL) + return ENOMEM; + + opts->identity = NULL; + opts->anchors = NULL; + opts->intermediates = NULL; + opts->crls = NULL; + + opts->cert_filename = NULL; + opts->key_filename = NULL; +#ifndef WITHOUT_PKCS11 + opts->p11_module_name = NULL; + opts->slotid = PK_NOSLOT; + opts->token_label = NULL; + opts->cert_id_string = NULL; + opts->cert_label = NULL; +#endif + + *idopts = opts; + + return 0; +} + +krb5_error_code +pkinit_dup_identity_opts(pkinit_identity_opts *src_opts, + pkinit_identity_opts **dest_opts) +{ + pkinit_identity_opts *newopts; + krb5_error_code retval; + + *dest_opts = NULL; + retval = pkinit_init_identity_opts(&newopts); + if (retval) + return retval; + + retval = ENOMEM; + + if (src_opts->identity != NULL) { + newopts->identity = strdup(src_opts->identity); + if (newopts->identity == NULL) + goto cleanup; + } + + retval = copy_list(&newopts->anchors, src_opts->anchors); + if (retval) + goto cleanup; + + retval = copy_list(&newopts->intermediates,src_opts->intermediates); + if (retval) + goto cleanup; + + retval = copy_list(&newopts->crls, src_opts->crls); + if (retval) + goto cleanup; + + if (src_opts->cert_filename != NULL) { + newopts->cert_filename = strdup(src_opts->cert_filename); + if (newopts->cert_filename == NULL) + goto cleanup; + } + + if (src_opts->key_filename != NULL) { + newopts->key_filename = strdup(src_opts->key_filename); + if (newopts->key_filename == NULL) + goto cleanup; + } + +#ifndef WITHOUT_PKCS11 + if (src_opts->p11_module_name != NULL) { + newopts->p11_module_name = strdup(src_opts->p11_module_name); + if (newopts->p11_module_name == NULL) + goto cleanup; + } + + newopts->slotid = src_opts->slotid; + + if (src_opts->token_label != NULL) { + newopts->token_label = strdup(src_opts->token_label); + if (newopts->token_label == NULL) + goto cleanup; + } + + if (src_opts->cert_id_string != NULL) { + newopts->cert_id_string = strdup(src_opts->cert_id_string); + if (newopts->cert_id_string == NULL) + goto cleanup; + } + + if (src_opts->cert_label != NULL) { + newopts->cert_label = strdup(src_opts->cert_label); + if (newopts->cert_label == NULL) + goto cleanup; + } +#endif + + + *dest_opts = newopts; + return 0; +cleanup: + pkinit_fini_identity_opts(newopts); + return retval; +} + +void +pkinit_fini_identity_opts(pkinit_identity_opts *idopts) +{ + if (idopts == NULL) + return; + + if (idopts->identity != NULL) + free(idopts->identity); + free_list(idopts->anchors); + free_list(idopts->intermediates); + free_list(idopts->crls); + free_list(idopts->identity_alt); + + free(idopts->cert_filename); + free(idopts->key_filename); +#ifndef WITHOUT_PKCS11 + free(idopts->p11_module_name); + free(idopts->token_label); + free(idopts->cert_id_string); + free(idopts->cert_label); +#endif + free(idopts); +} + +#ifndef WITHOUT_PKCS11 +static krb5_error_code +parse_pkcs11_options(krb5_context context, + pkinit_identity_opts *idopts, + const char *residual) +{ + char *s, *cp, *vp, *save; + krb5_error_code retval = ENOMEM; + + if (residual == NULL || residual[0] == '\0') + return 0; + + /* Split string into attr=value substrings */ + s = strdup(residual); + if (s == NULL) + return retval; + + for (cp = strtok_r(s, ":", &save); cp; cp = strtok_r(NULL, ":", &save)) { + vp = strchr(cp, '='); + + /* If there is no "=", this is a pkcs11 module name */ + if (vp == NULL) { + free(idopts->p11_module_name); + idopts->p11_module_name = strdup(cp); + if (idopts->p11_module_name == NULL) + goto cleanup; + continue; + } + *vp++ = '\0'; + if (!strcmp(cp, "module_name")) { + free(idopts->p11_module_name); + idopts->p11_module_name = strdup(vp); + if (idopts->p11_module_name == NULL) + goto cleanup; + } else if (!strcmp(cp, "slotid")) { + long slotid = strtol(vp, NULL, 10); + if ((slotid == LONG_MIN || slotid == LONG_MAX) && errno != 0) { + retval = EINVAL; + goto cleanup; + } + if ((long) (int) slotid != slotid) { + retval = EINVAL; + goto cleanup; + } + idopts->slotid = slotid; + } else if (!strcmp(cp, "token")) { + free(idopts->token_label); + idopts->token_label = strdup(vp); + if (idopts->token_label == NULL) + goto cleanup; + } else if (!strcmp(cp, "certid")) { + free(idopts->cert_id_string); + idopts->cert_id_string = strdup(vp); + if (idopts->cert_id_string == NULL) + goto cleanup; + } else if (!strcmp(cp, "certlabel")) { + free(idopts->cert_label); + idopts->cert_label = strdup(vp); + if (idopts->cert_label == NULL) + goto cleanup; + } + } + retval = 0; +cleanup: + free(s); + return retval; +} +#endif + +static krb5_error_code +parse_fs_options(krb5_context context, + pkinit_identity_opts *idopts, + const char *residual) +{ + char *certname, *keyname, *save; + char *copy = NULL, *cert_filename = NULL, *key_filename = NULL; + krb5_error_code retval = ENOMEM; + + if (residual == NULL || residual[0] == '\0' || residual[0] == ',') + return EINVAL; + + copy = strdup(residual); + if (copy == NULL) + goto cleanup; + + certname = strtok_r(copy, ",", &save); + if (certname == NULL) + goto cleanup; + keyname = strtok_r(NULL, ",", &save); + + cert_filename = strdup(certname); + if (cert_filename == NULL) + goto cleanup; + + key_filename = strdup((keyname != NULL) ? keyname : certname); + if (key_filename == NULL) + goto cleanup; + + free(idopts->cert_filename); + free(idopts->key_filename); + idopts->cert_filename = cert_filename; + idopts->key_filename = key_filename; + cert_filename = key_filename = NULL; + retval = 0; + +cleanup: + free(copy); + free(cert_filename); + free(key_filename); + return retval; +} + +static krb5_error_code +parse_pkcs12_options(krb5_context context, + pkinit_identity_opts *idopts, + const char *residual) +{ + krb5_error_code retval = ENOMEM; + + if (residual == NULL || residual[0] == '\0') + return 0; + + free(idopts->cert_filename); + idopts->cert_filename = strdup(residual); + if (idopts->cert_filename == NULL) + goto cleanup; + + free(idopts->key_filename); + idopts->key_filename = strdup(residual); + if (idopts->key_filename == NULL) + goto cleanup; + + pkiDebug("%s: cert_filename '%s' key_filename '%s'\n", + __FUNCTION__, idopts->cert_filename, + idopts->key_filename); + retval = 0; +cleanup: + return retval; +} + +static krb5_error_code +process_option_identity(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_opts *idopts, + pkinit_identity_crypto_context id_cryptoctx, + krb5_principal princ, const char *value) +{ + const char *residual; + int idtype; + krb5_error_code retval = 0; + + TRACE_PKINIT_IDENTITY_OPTION(context, value); + if (value == NULL) + return EINVAL; + + residual = strchr(value, ':'); + if (residual != NULL) { + unsigned int typelen; + residual++; /* skip past colon */ + typelen = residual - value; + if (strncmp(value, "FILE:", typelen) == 0) { + idtype = IDTYPE_FILE; +#ifndef WITHOUT_PKCS11 + } else if (strncmp(value, "PKCS11:", typelen) == 0) { + idtype = IDTYPE_PKCS11; +#endif + } else if (strncmp(value, "PKCS12:", typelen) == 0) { + idtype = IDTYPE_PKCS12; + } else if (strncmp(value, "DIR:", typelen) == 0) { + idtype = IDTYPE_DIR; + } else if (strncmp(value, "ENV:", typelen) == 0) { + idtype = IDTYPE_ENVVAR; + } else { + pkiDebug("%s: Unsupported type while processing '%s'\n", + __FUNCTION__, value); + krb5_set_error_message(context, KRB5_PREAUTH_FAILED, + _("Unsupported type while processing " + "'%s'\n"), value); + return KRB5_PREAUTH_FAILED; + } + } else { + idtype = IDTYPE_FILE; + residual = value; + } + + idopts->idtype = idtype; + pkiDebug("%s: idtype is %s\n", __FUNCTION__, idtype2string(idopts->idtype)); + switch (idtype) { + case IDTYPE_ENVVAR: + return process_option_identity(context, plg_cryptoctx, req_cryptoctx, + idopts, id_cryptoctx, princ, + secure_getenv(residual)); + break; + case IDTYPE_FILE: + retval = parse_fs_options(context, idopts, residual); + break; + case IDTYPE_PKCS12: + retval = parse_pkcs12_options(context, idopts, residual); + break; +#ifndef WITHOUT_PKCS11 + case IDTYPE_PKCS11: + retval = parse_pkcs11_options(context, idopts, residual); + break; +#endif + case IDTYPE_DIR: + free(idopts->cert_filename); + idopts->cert_filename = strdup(residual); + if (idopts->cert_filename == NULL) + retval = ENOMEM; + break; + default: + krb5_set_error_message(context, KRB5_PREAUTH_FAILED, + _("Internal error parsing " + "X509_user_identity\n")); + retval = EINVAL; + break; + } + if (retval) + return retval; + + retval = crypto_load_certs(context, plg_cryptoctx, req_cryptoctx, idopts, + id_cryptoctx, princ, TRUE); + if (retval) + return retval; + + crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx, id_cryptoctx); + return 0; +} + +static krb5_error_code +process_option_ca_crl(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_opts *idopts, + pkinit_identity_crypto_context id_cryptoctx, + const char *value, + int catype) +{ + char *residual; + unsigned int typelen; + int idtype; + + pkiDebug("%s: processing catype %s, value '%s'\n", + __FUNCTION__, catype2string(catype), value); + residual = strchr(value, ':'); + if (residual == NULL) { + pkiDebug("No type given for '%s'\n", value); + return EINVAL; + } + residual++; /* skip past colon */ + typelen = residual - value; + if (strncmp(value, "FILE:", typelen) == 0) { + idtype = IDTYPE_FILE; + } else if (strncmp(value, "DIR:", typelen) == 0) { + idtype = IDTYPE_DIR; + } else { + return ENOTSUP; + } + return crypto_load_cas_and_crls(context, + plg_cryptoctx, + req_cryptoctx, + idopts, id_cryptoctx, + idtype, catype, residual); +} + +/* + * Load any identity information which doesn't require us to ask a controlling + * user any questions, and record the names of anything else which would + * require us to ask questions. + */ +krb5_error_code +pkinit_identity_initialize(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_opts *idopts, + pkinit_identity_crypto_context id_cryptoctx, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, + krb5_principal princ) +{ + krb5_error_code retval = EINVAL; + int i; + + pkiDebug("%s: %p %p %p\n", __FUNCTION__, context, idopts, id_cryptoctx); + if (!(princ && + krb5_principal_compare_any_realm(context, princ, + krb5_anonymous_principal()))) { + if (idopts == NULL || id_cryptoctx == NULL) + goto errout; + + /* + * If identity was specified, use that. (For the kdc, this + * is specified as pkinit_identity in the kdc.conf. For users, + * this is specified on the command line via X509_user_identity.) + * If a user did not specify identity on the command line, + * then we will try alternatives which may have been specified + * in the config file. + */ + if (idopts->identity != NULL) { + retval = process_option_identity(context, plg_cryptoctx, + req_cryptoctx, idopts, + id_cryptoctx, princ, + idopts->identity); + } else if (idopts->identity_alt != NULL) { + for (i = 0; retval != 0 && idopts->identity_alt[i] != NULL; i++) { + retval = process_option_identity(context, plg_cryptoctx, + req_cryptoctx, idopts, + id_cryptoctx, princ, + idopts->identity_alt[i]); + } + } else { + retval = KRB5_PREAUTH_FAILED; + krb5_set_error_message(context, retval, + _("No user identity options specified")); + pkiDebug("%s: no user identity options specified\n", __FUNCTION__); + goto errout; + } + } else { + /* We're the anonymous principal. */ + retval = 0; + } + +errout: + return retval; +} + +/* + * Load identity information, including that which requires us to ask a + * controlling user any questions. If we have PIN/password values which + * correspond to a given identity, use that, otherwise, if one is available, + * we'll use the prompter callback. + */ +krb5_error_code +pkinit_identity_prompt(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_opts *idopts, + pkinit_identity_crypto_context id_cryptoctx, + krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, + int do_matching, + krb5_principal princ) +{ + krb5_error_code retval = 0; + const char *signer_identity; + krb5_boolean valid; + int i; + + pkiDebug("%s: %p %p %p\n", __FUNCTION__, context, idopts, id_cryptoctx); + if (!(princ && + krb5_principal_compare_any_realm(context, princ, + krb5_anonymous_principal()))) { + retval = crypto_load_certs(context, plg_cryptoctx, req_cryptoctx, + idopts, id_cryptoctx, princ, FALSE); + if (retval) + goto errout; + + if (do_matching) { + /* + * Try to select exactly one certificate based on matching + * criteria. Typical used for clients. + */ + retval = pkinit_cert_matching(context, plg_cryptoctx, + req_cryptoctx, id_cryptoctx, princ); + if (retval) { + crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx, + id_cryptoctx); + goto errout; + } + } else { + /* + * Tell crypto code to use the "default" identity. Typically used + * for KDCs. + */ + retval = crypto_cert_select_default(context, plg_cryptoctx, + req_cryptoctx, id_cryptoctx); + if (retval) { + crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx, + id_cryptoctx); + goto errout; + } + } + + if (rock != NULL && cb != NULL && retval == 0) { + /* Save the signer identity if we're the client. */ + if (crypto_retrieve_signer_identity(context, id_cryptoctx, + &signer_identity) == 0) { + cb->set_cc_config(context, rock, "X509_user_identity", + signer_identity); + } + } + + retval = crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx, + id_cryptoctx); + if (retval) + goto errout; + } /* Not anonymous principal */ + + /* Require at least one successful anchor if any are specified. */ + valid = FALSE; + for (i = 0; idopts->anchors != NULL && idopts->anchors[i] != NULL; i++) { + retval = process_option_ca_crl(context, plg_cryptoctx, req_cryptoctx, + idopts, id_cryptoctx, + idopts->anchors[i], CATYPE_ANCHORS); + if (!retval) + valid = TRUE; + } + if (retval && !valid) + goto errout; + krb5_clear_error_message(context); + retval = 0; + + /* Require at least one successful intermediate if any are specified. */ + valid = FALSE; + for (i = 0; idopts->intermediates != NULL + && idopts->intermediates[i] != NULL; i++) { + retval = process_option_ca_crl(context, plg_cryptoctx, req_cryptoctx, + idopts, id_cryptoctx, + idopts->intermediates[i], + CATYPE_INTERMEDIATES); + if (!retval) + valid = TRUE; + } + if (retval && !valid) + goto errout; + krb5_clear_error_message(context); + retval = 0; + + for (i = 0; idopts->crls != NULL && idopts->crls[i] != NULL; i++) { + retval = process_option_ca_crl(context, plg_cryptoctx, req_cryptoctx, + idopts, id_cryptoctx, idopts->crls[i], + CATYPE_CRLS); + if (retval) + goto errout; + } + +errout: + return retval; +} + +/* + * Create an entry in the passed-in list for the named identity, optionally + * with the specified token flag value and/or supplied password, replacing any + * existing entry with the same identity name. + */ +krb5_error_code +pkinit_set_deferred_id(pkinit_deferred_id **identities, + const char *identity, unsigned long ck_flags, + const char *password) +{ + int i; + pkinit_deferred_id *out = NULL, *ids; + char *tmp; + + /* Search for an entry that's already in the list. */ + ids = *identities; + for (i = 0; ids != NULL && ids[i] != NULL; i++) { + if (strcmp(ids[i]->identity, identity) == 0) { + /* Replace its password value, then we're done. */ + tmp = password ? strdup(password) : NULL; + if (password != NULL && tmp == NULL) + return ENOMEM; + ids[i]->ck_flags = ck_flags; + free(ids[i]->password); + ids[i]->password = tmp; + return 0; + } + } + + /* Resize the list. */ + out = realloc(ids, sizeof(*ids) * (i + 2)); + if (out == NULL) + goto oom; + *identities = out; + + /* Allocate the new final entry. */ + out[i] = malloc(sizeof(*(out[i]))); + if (out[i] == NULL) + goto oom; + + /* Populate the new entry. */ + out[i]->magic = PKINIT_DEFERRED_ID_MAGIC; + out[i]->identity = strdup(identity); + if (out[i]->identity == NULL) + goto oom; + + out[i]->ck_flags = ck_flags; + out[i]->password = password ? strdup(password) : NULL; + if (password != NULL && out[i]->password == NULL) + goto oom; + + /* Terminate the list. */ + out[i + 1] = NULL; + return 0; + +oom: + if (out != NULL && out[i] != NULL) { + free(out[i]->identity); + free(out[i]); + out[i] = NULL; + } + return ENOMEM; +} + +/* + * Return a password which we've associated with the named identity, if we've + * stored one. Otherwise return NULL. + */ +const char * +pkinit_find_deferred_id(pkinit_deferred_id *identities, + const char *identity) +{ + int i; + + for (i = 0; identities != NULL && identities[i] != NULL; i++) { + if (strcmp(identities[i]->identity, identity) == 0) + return identities[i]->password; + } + return NULL; +} + +/* + * Return the flags associated with the specified identity, or 0 if we don't + * have such an identity. + */ +unsigned long +pkinit_get_deferred_id_flags(pkinit_deferred_id *identities, + const char *identity) +{ + int i; + + for (i = 0; identities != NULL && identities[i] != NULL; i++) { + if (strcmp(identities[i]->identity, identity) == 0) + return identities[i]->ck_flags; + } + return 0; +} + +/* + * Free a deferred_id list. + */ +void +pkinit_free_deferred_ids(pkinit_deferred_id *identities) +{ + int i; + + for (i = 0; identities != NULL && identities[i] != NULL; i++) { + free(identities[i]->identity); + free(identities[i]->password); + free(identities[i]); + } + free(identities); +} diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_kdf_test.c b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_kdf_test.c new file mode 100644 index 00000000..7f38e849 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_kdf_test.c @@ -0,0 +1,227 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/pkinit/pkinit_kdf_test.c */ +/* + * Copyright (C) 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * pkinit_kdf_test.c -- Test to verify the correctness of the function + * pkinit_alg_agility_kdf() in pkinit_crypto_openssl, which implements + * the Key Derivation Function from the PKInit Algorithm Agility + * document, currently draft-ietf-krb-wg-pkinit-alg-agility-04.txt. + */ + +#include "k5-platform.h" +#include "pkinit.h" + +/** + * Initialize a krb5_data from @a s, a constant string. Note @a s is evaluated + * multiple times; this is acceptable for constants. + */ +#define DATA_FROM_STRING(s) \ + {0, sizeof(s)-1, (char *) s} + + +/* values from test vectors in the pkinit-alg-agility draft */ +int secret_len = 256; +char twenty_as[10]; +char eighteen_bs[9]; +char party_u_name[] = "lha@SU.SE"; +char party_v_name[] = "krbtgt/SU.SE@SU.SE"; +int enctype_aes = ENCTYPE_AES256_CTS_HMAC_SHA1_96; +int enctype_des3 = ENCTYPE_DES3_CBC_SHA1; +const krb5_data lha_data = DATA_FROM_STRING("lha"); + +krb5_octet key1_hex[] = +{0xe6, 0xAB, 0x38, 0xC9, 0x41, 0x3E, 0x03, 0x5B, + 0xB0, 0x79, 0x20, 0x1E, 0xD0, 0xB6, 0xB7, 0x3D, + 0x8D, 0x49, 0xA8, 0x14, 0xA7, 0x37, 0xC0, 0x4E, + 0xE6, 0x64, 0x96, 0x14, 0x20, 0x6F, 0x73, 0xAD}; + +krb5_octet key2_hex[] = +{0x77, 0xEF, 0x4E, 0x48, 0xC4, 0x20, 0xAE, 0x3F, + 0xEC, 0x75, 0x10, 0x9D, 0x79, 0x81, 0x69, 0x7E, + 0xED, 0x5D, 0x29, 0x5C, 0x90, 0xc6, 0x25, 0x64, + 0xF7, 0xBF, 0xD1, 0x01, 0xFA, 0x9b, 0xC1, 0xD5}; + +krb5_octet key3_hex[] = +{0xD3, 0xC7, 0x8A, 0x79, 0xD6, 0x52, 0x13, 0xEF, + 0xE9, 0xA8, 0x26, 0xF7, 0x5D, 0xFB, 0x01, 0xF7, + 0x23, 0x62, 0xFB, 0x16, 0xFB, 0x01, 0xDA, 0xD6}; + +int +main(int argc, char **argv) +{ + /* arguments for calls to pkinit_alg_agility_kdf() */ + krb5_context context = 0; + krb5_data secret; + krb5_algorithm_identifier alg_id; + krb5_data as_req; + krb5_data pk_as_rep; + krb5_keyblock key_block; + + /* other local variables */ + int retval = 0; + krb5_enctype enctype = 0; + krb5_principal u_principal = NULL; + krb5_principal v_principal = NULL; + + /* initialize variables that get malloc'ed, so cleanup is safe */ + krb5_init_context (&context); + memset(&alg_id, 0, sizeof(alg_id)); + memset(&as_req, 0, sizeof(as_req)); + memset(&pk_as_rep, 0, sizeof(pk_as_rep)); + memset(&key_block, 0, sizeof(key_block)); + + /* set up a 256-byte, ALL-ZEROS secret */ + if (NULL == (secret.data = malloc(secret_len))) { + printf("ERROR in pkinit_kdf_test: Memory allocation failed."); + retval = ENOMEM; + goto cleanup; + } + secret.length = secret_len; + memset(secret.data, 0, secret_len); + + /* set-up the partyUInfo and partyVInfo principals */ + if ((0 != (retval = krb5_parse_name(context, party_u_name, + &u_principal))) || + (0 != (retval = krb5_parse_name(context, party_v_name, + &v_principal)))) { + printf("ERROR in pkinit_kdf_test: Error parsing names, retval = %d", + retval); + goto cleanup; + } + + /* The test vectors in RFC 8636 implicitly use NT-PRINCIPAL names. */ + u_principal->type = KRB5_NT_PRINCIPAL; + v_principal->type = KRB5_NT_PRINCIPAL; + + /* set-up the as_req and and pk_as_rep data */ + memset(twenty_as, 0xaa, sizeof(twenty_as)); + memset(eighteen_bs, 0xbb, sizeof(eighteen_bs)); + as_req.length = sizeof(twenty_as); + as_req.data = twenty_as; + + pk_as_rep.length = sizeof(eighteen_bs); + pk_as_rep.data = eighteen_bs; + + /* TEST 1: SHA-1/AES */ + /* set up algorithm id */ + alg_id.algorithm = sha1_id; + + enctype = enctype_aes; + + /* call pkinit_alg_agility_kdf() with test vector values*/ + if (0 != (retval = pkinit_alg_agility_kdf(context, &secret, + &alg_id.algorithm, + u_principal, v_principal, + enctype, &as_req, &pk_as_rep, + &key_block))) { + printf("ERROR in pkinit_kdf_test: kdf call failed, retval = %d\n", + retval); + goto cleanup; + } + + /* compare key to expected key value */ + + if ((key_block.length == sizeof(key1_hex)) && + (0 == memcmp(key_block.contents, key1_hex, key_block.length))) { + printf("SUCCESS: TEST 1 (SHA-1/AES), Correct key value generated.\n"); + retval = 0; + /* free the keyblock contents, so we can use it for the next test */ + krb5_free_keyblock_contents(context, &key_block); + } else { + printf("FAILURE: TEST 1 (SHA-1/AES), Incorrect key value generated!\n"); + retval = 1; + goto cleanup; + } + + /* TEST 2: SHA-256/AES */ + /* set up algorithm id */ + alg_id.algorithm = sha256_id; + + enctype = enctype_aes; + + /* call pkinit_alg_agility_kdf() with test vector values*/ + if (0 != (retval = pkinit_alg_agility_kdf(context, &secret, + &alg_id.algorithm, + u_principal, v_principal, + enctype, &as_req, &pk_as_rep, + &key_block))) { + printf("ERROR in pkinit_kdf_test: kdf call failed, retval = %d\n", + retval); + goto cleanup; + } + + /* compare key to expected key value */ + + if ((key_block.length == sizeof(key2_hex)) && + (0 == memcmp(key_block.contents, key2_hex, key_block.length))) { + printf("SUCCESS: TEST 2 (SHA-256/AES), Correct key value generated.\n"); + retval = 0; + /* free the keyblock contents, so we can use it for the next test */ + krb5_free_keyblock_contents(context, &key_block); + } else { + printf("FAILURE: TEST 2 (SHA-256/AES), Incorrect key value generated!\n"); + retval = 1; + goto cleanup; + } + + /* TEST 3: SHA-512/DES3 */ + /* set up algorithm id */ + alg_id.algorithm = sha512_id; + + enctype = enctype_des3; + + /* call pkinit_alg_agility_kdf() with test vector values*/ + if (0 != (retval = pkinit_alg_agility_kdf(context, &secret, + &alg_id.algorithm, + u_principal, v_principal, + enctype, &as_req, &pk_as_rep, + &key_block))) { + printf("ERROR in pkinit_kdf_test: kdf call failed, retval = %d\n", + retval); + goto cleanup; + } + + /* compare key to expected key value */ + + if ((key_block.length == sizeof(key3_hex)) && + (0 == memcmp(key_block.contents, key3_hex, key_block.length))) { + printf("SUCCESS: TEST 3 (SHA-512/DES3), Correct key value generated.\n"); + retval = 0; + } else { + printf("FAILURE: TEST 2 (SHA-512/DES3), Incorrect key value generated!\n"); + retval = 1; + goto cleanup; + } + +cleanup: + /* release all allocated resources, whether good or bad return */ + free(secret.data); + krb5_free_principal(context, u_principal); + krb5_free_principal(context, v_principal); + krb5_free_keyblock_contents(context, &key_block); + krb5_free_context(context); + return retval ? 1 : 0; +} diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_lib.c b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_lib.c new file mode 100644 index 00000000..4c3d46bf --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_lib.c @@ -0,0 +1,290 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * COPYRIGHT (C) 2006,2007 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#include "pkinit.h" + +#define FAKECERT + +const krb5_data dh_oid = { 0, 7, "\x2A\x86\x48\xce\x3e\x02\x01" }; + + +krb5_error_code +pkinit_init_req_opts(pkinit_req_opts **reqopts) +{ + krb5_error_code retval = ENOMEM; + pkinit_req_opts *opts = NULL; + + *reqopts = NULL; + opts = calloc(1, sizeof(*opts)); + if (opts == NULL) + return retval; + + opts->require_eku = 1; + opts->accept_secondary_eku = 0; + opts->allow_upn = 0; + opts->dh_or_rsa = DH_PROTOCOL; + opts->require_crl_checking = 0; + opts->dh_size = PKINIT_DEFAULT_DH_MIN_BITS; + + *reqopts = opts; + + return 0; +} + +void +pkinit_fini_req_opts(pkinit_req_opts *opts) +{ + free(opts); + return; +} + +krb5_error_code +pkinit_init_plg_opts(pkinit_plg_opts **plgopts) +{ + krb5_error_code retval = ENOMEM; + pkinit_plg_opts *opts = NULL; + + *plgopts = NULL; + opts = calloc(1, sizeof(pkinit_plg_opts)); + if (opts == NULL) + return retval; + + opts->require_eku = 1; + opts->accept_secondary_eku = 0; + opts->dh_or_rsa = DH_PROTOCOL; + opts->allow_upn = 0; + opts->require_crl_checking = 0; + opts->require_freshness = 0; + opts->disable_freshness = 0; + + opts->dh_min_bits = PKINIT_DEFAULT_DH_MIN_BITS; + + *plgopts = opts; + + return 0; +} + +void +pkinit_fini_plg_opts(pkinit_plg_opts *opts) +{ + free(opts); + return; +} + +void +free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in) +{ + if (*in == NULL) return; + free((*in)->signedAuthPack.data); + if ((*in)->trustedCertifiers != NULL) + free_krb5_external_principal_identifier(&(*in)->trustedCertifiers); + free((*in)->kdcPkId.data); + free(*in); +} + +void +free_krb5_reply_key_pack(krb5_reply_key_pack **in) +{ + if (*in == NULL) return; + free((*in)->replyKey.contents); + free((*in)->asChecksum.contents); + free(*in); +} + +void +free_krb5_auth_pack(krb5_auth_pack **in) +{ + if ((*in) == NULL) return; + krb5_free_data_contents(NULL, &(*in)->clientPublicValue); + free((*in)->pkAuthenticator.paChecksum.contents); + krb5_free_data(NULL, (*in)->pkAuthenticator.freshnessToken); + if ((*in)->supportedCMSTypes != NULL) + free_krb5_algorithm_identifiers(&((*in)->supportedCMSTypes)); + if ((*in)->supportedKDFs) { + krb5_data **supportedKDFs = (*in)->supportedKDFs; + unsigned i; + for (i = 0; supportedKDFs[i]; i++) + krb5_free_data(NULL, supportedKDFs[i]); + free(supportedKDFs); + } + free(*in); +} + +void +free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in) +{ + if (*in == NULL) return; + switch ((*in)->choice) { + case choice_pa_pk_as_rep_dhInfo: + krb5_free_data(NULL, (*in)->u.dh_Info.kdfID); + free((*in)->u.dh_Info.dhSignedData.data); + break; + case choice_pa_pk_as_rep_encKeyPack: + free((*in)->u.encKeyPack.data); + break; + default: + break; + } + free(*in); +} + +void +free_krb5_external_principal_identifier(krb5_external_principal_identifier ***in) +{ + int i = 0; + if (*in == NULL) return; + while ((*in)[i] != NULL) { + free((*in)[i]->subjectName.data); + free((*in)[i]->issuerAndSerialNumber.data); + free((*in)[i]->subjectKeyIdentifier.data); + free((*in)[i]); + i++; + } + free(*in); +} + +void +free_krb5_algorithm_identifier(krb5_algorithm_identifier *in) +{ + if (in == NULL) + return; + free(in->algorithm.data); + free(in->parameters.data); + free(in); +} + +void +free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in) +{ + int i; + if (in == NULL || *in == NULL) + return; + for (i = 0; (*in)[i] != NULL; i++) { + free_krb5_algorithm_identifier((*in)[i]); + } + free(*in); +} + +void +free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in) +{ + if (*in == NULL) return; + free((*in)->subjectPublicKey.data); + free(*in); +} + +void +init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in) +{ + (*in) = malloc(sizeof(krb5_pa_pk_as_req)); + if ((*in) == NULL) return; + (*in)->signedAuthPack.data = NULL; + (*in)->signedAuthPack.length = 0; + (*in)->trustedCertifiers = NULL; + (*in)->kdcPkId.data = NULL; + (*in)->kdcPkId.length = 0; +} + +void +init_krb5_reply_key_pack(krb5_reply_key_pack **in) +{ + (*in) = malloc(sizeof(krb5_reply_key_pack)); + if ((*in) == NULL) return; + (*in)->replyKey.contents = NULL; + (*in)->replyKey.length = 0; + (*in)->asChecksum.contents = NULL; + (*in)->asChecksum.length = 0; +} + +void +init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in) +{ + (*in) = malloc(sizeof(krb5_pa_pk_as_rep)); + if ((*in) == NULL) return; + (*in)->u.dh_Info.serverDHNonce.length = 0; + (*in)->u.dh_Info.serverDHNonce.data = NULL; + (*in)->u.dh_Info.dhSignedData.length = 0; + (*in)->u.dh_Info.dhSignedData.data = NULL; + (*in)->u.encKeyPack.length = 0; + (*in)->u.encKeyPack.data = NULL; + (*in)->u.dh_Info.kdfID = NULL; +} + +krb5_error_code +pkinit_copy_krb5_data(krb5_data *dst, const krb5_data *src) +{ + if (dst == NULL || src == NULL) + return EINVAL; + if (src->data == NULL) { + dst->data = NULL; + dst->length = 0; + return 0; + } + dst->data = malloc(src->length); + if (dst->data == NULL) + return ENOMEM; + memcpy(dst->data, src->data, src->length); + dst->length = src->length; + return 0; +} + +/* debugging functions */ +void +print_buffer(const unsigned char *buf, unsigned int len) +{ + unsigned i = 0; + if (len <= 0) + return; + + for (i = 0; i < len; i++) + pkiDebug("%02x ", buf[i]); + pkiDebug("\n"); +} + +void +print_buffer_bin(unsigned char *buf, unsigned int len, char *filename) +{ + FILE *f = NULL; + unsigned int i = 0; + + if (len <= 0 || filename == NULL) + return; + + if ((f = fopen(filename, "w")) == NULL) + return; + + set_cloexec_file(f); + + for (i = 0; i < len; i++) + fputc(buf[i], f); + + fclose(f); +} diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_matching.c b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_matching.c new file mode 100644 index 00000000..b42485a5 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_matching.c @@ -0,0 +1,751 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * COPYRIGHT (C) 2007 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#include +#include +#include +#include +#include +#include +#include "pkinit.h" + +typedef struct _pkinit_cert_info pkinit_cert_info; + +typedef enum { + kw_undefined = 0, + kw_subject = 1, + kw_issuer = 2, + kw_san = 3, + kw_eku = 4, + kw_ku = 5 +} keyword_type; + +static char * +keyword2string(unsigned int kw) +{ + switch(kw) { + case kw_undefined: return "NONE"; break; + case kw_subject: return "SUBJECT"; break; + case kw_issuer: return "ISSUER"; break; + case kw_san: return "SAN"; break; + case kw_eku: return "EKU"; break; + case kw_ku: return "KU"; break; + default: return "INVALID"; break; + } +} +typedef enum { + relation_none = 0, + relation_and = 1, + relation_or = 2 +} relation_type; + +static char * +relation2string(unsigned int rel) +{ + switch(rel) { + case relation_none: return "NONE"; break; + case relation_and: return "AND"; break; + case relation_or: return "OR"; break; + default: return "INVALID"; break; + } +} + +typedef enum { + kwvaltype_undefined = 0, + kwvaltype_regexp = 1, + kwvaltype_list = 2 +} kw_value_type; + +static char * +kwval2string(unsigned int kwval) +{ + switch(kwval) { + case kwvaltype_undefined: return "NONE"; break; + case kwvaltype_regexp: return "REGEXP"; break; + case kwvaltype_list: return "LIST"; break; + default: return "INVALID"; break; + } +} + +struct keyword_desc { + const char *value; + size_t length; + keyword_type kwtype; + kw_value_type kwvaltype; +} matching_keywords[] = { + { "", 4, kw_ku, kwvaltype_list }, + { "", 5, kw_eku, kwvaltype_list }, + { "", 5, kw_san, kwvaltype_regexp }, + { "", 8, kw_issuer, kwvaltype_regexp }, + { "", 9, kw_subject, kwvaltype_regexp }, + { NULL, 0, kw_undefined, kwvaltype_undefined}, +}; + +struct ku_desc { + const char *value; + size_t length; + unsigned int bitval; +}; + +struct ku_desc ku_keywords[] = { + { "digitalSignature", 16, PKINIT_KU_DIGITALSIGNATURE }, + { "keyEncipherment", 15, PKINIT_KU_KEYENCIPHERMENT }, + { NULL, 0, 0 }, +}; + +struct ku_desc eku_keywords[] = { + { "pkinit", 6, PKINIT_EKU_PKINIT }, + { "msScLogin", 9, PKINIT_EKU_MSSCLOGIN }, + { "clientAuth", 10, PKINIT_EKU_CLIENTAUTH }, + { "emailProtection", 15, PKINIT_EKU_EMAILPROTECTION }, + { NULL, 0, 0 }, +}; + +/* Rule component */ +typedef struct _rule_component { + struct _rule_component *next; + keyword_type kw_type; + kw_value_type kwval_type; + regex_t regexp; /* Compiled regular expression */ + char *regsrc; /* The regular expression source (for debugging) */ + unsigned int ku_bits; + unsigned int eku_bits; +} rule_component; + +/* Set rule components */ +typedef struct _rule_set { + relation_type relation; + int num_crs; + rule_component *crs; +} rule_set; + +static krb5_error_code +free_rule_component(krb5_context context, + rule_component *rc) +{ + if (rc == NULL) + return 0; + + if (rc->kwval_type == kwvaltype_regexp) { + free(rc->regsrc); + regfree(&rc->regexp); + } + free(rc); + return 0; +} + +static krb5_error_code +free_rule_set(krb5_context context, + rule_set *rs) +{ + rule_component *rc, *trc; + + if (rs == NULL) + return 0; + for (rc = rs->crs; rc != NULL;) { + trc = rc->next; + free_rule_component(context, rc); + rc = trc; + } + free(rs); + return 0; +} + +static krb5_error_code +parse_list_value(krb5_context context, + keyword_type type, + char *value, + rule_component *rc) +{ + krb5_error_code retval; + char *comma; + struct ku_desc *ku = NULL; + int found; + size_t len; + unsigned int *bitptr; + + + if (value == NULL || value[0] == '\0') { + pkiDebug("%s: Missing or empty value for list keyword type %d\n", + __FUNCTION__, type); + retval = EINVAL; + goto out; + } + + if (type == kw_eku) { + bitptr = &rc->eku_bits; + } else if (type == kw_ku) { + bitptr = &rc->ku_bits; + } else { + pkiDebug("%s: Unknown list keyword type %d\n", __FUNCTION__, type); + retval = EINVAL; + goto out; + } + + do { + found = 0; + comma = strchr(value, ','); + if (comma != NULL) + len = comma - value; + else + len = strlen(value); + + if (type == kw_eku) { + ku = eku_keywords; + } else if (type == kw_ku) { + ku = ku_keywords; + } + + for (; ku->value != NULL; ku++) { + if (strncasecmp(value, ku->value, len) == 0) { + *bitptr |= ku->bitval; + found = 1; + pkiDebug("%s: Found value '%s', bitfield is now 0x%x\n", + __FUNCTION__, ku->value, *bitptr); + break; + } + } + if (found) { + value += ku->length; + if (*value == ',') + value += 1; + } else { + pkiDebug("%s: Urecognized value '%s'\n", __FUNCTION__, value); + retval = EINVAL; + goto out; + } + } while (found && *value != '\0'); + + retval = 0; +out: + pkiDebug("%s: returning %d\n", __FUNCTION__, retval); + return retval; +} + +static krb5_error_code +parse_rule_component(krb5_context context, + const char **rule, + int *remaining, + rule_component **ret_rule) +{ + krb5_error_code retval; + rule_component *rc = NULL; + keyword_type kw_type; + kw_value_type kwval_type; + char err_buf[128]; + int ret; + struct keyword_desc *kw, *nextkw; + char *nk; + int found_next_kw = 0; + char *value = NULL; + size_t len; + + for (kw = matching_keywords; kw->value != NULL; kw++) { + if (strncmp(*rule, kw->value, kw->length) == 0) { + kw_type = kw->kwtype; + kwval_type = kw->kwvaltype; + *rule += kw->length; + *remaining -= kw->length; + break; + } + } + if (kw->value == NULL) { + pkiDebug("%s: Missing or invalid keyword in rule '%s'\n", + __FUNCTION__, *rule); + retval = ENOENT; + goto out; + } + + pkiDebug("%s: found keyword '%s'\n", __FUNCTION__, kw->value); + + rc = calloc(1, sizeof(*rc)); + if (rc == NULL) { + retval = ENOMEM; + goto out; + } + rc->next = NULL; + rc->kw_type = kw_type; + rc->kwval_type = kwval_type; + + /* + * Before processing the value for this keyword, + * (compiling the regular expression or processing the list) + * we need to find the end of it. That means parsing for the + * beginning of the next keyword (or the end of the rule). + */ + nk = strchr(*rule, '<'); + while (nk != NULL) { + /* Possibly another keyword, check it out */ + for (nextkw = matching_keywords; nextkw->value != NULL; nextkw++) { + if (strncmp(nk, nextkw->value, nextkw->length) == 0) { + /* Found a keyword, nk points to the beginning */ + found_next_kw = 1; + break; /* Need to break out of the while! */ + } + } + if (!found_next_kw) + nk = strchr(nk+1, '<'); /* keep looking */ + else + break; + } + + if (nk != NULL && found_next_kw) + len = (nk - *rule); + else + len = (*remaining); + + if (len == 0) { + pkiDebug("%s: Missing value for keyword '%s'\n", + __FUNCTION__, kw->value); + retval = EINVAL; + goto out; + } + + value = calloc(1, len+1); + if (value == NULL) { + retval = ENOMEM; + goto out; + } + memcpy(value, *rule, len); + *remaining -= len; + *rule += len; + pkiDebug("%s: found value '%s'\n", __FUNCTION__, value); + + if (kw->kwvaltype == kwvaltype_regexp) { + ret = regcomp(&rc->regexp, value, REG_EXTENDED); + if (ret) { + regerror(ret, &rc->regexp, err_buf, sizeof(err_buf)); + pkiDebug("%s: Error compiling reg-exp '%s': %s\n", + __FUNCTION__, value, err_buf); + retval = ret; + goto out; + } + rc->regsrc = strdup(value); + if (rc->regsrc == NULL) { + retval = ENOMEM; + goto out; + } + } else if (kw->kwvaltype == kwvaltype_list) { + retval = parse_list_value(context, rc->kw_type, value, rc); + if (retval) { + pkiDebug("%s: Error %d, parsing list values for keyword %s\n", + __FUNCTION__, retval, kw->value); + goto out; + } + } + + *ret_rule = rc; + retval = 0; +out: + free(value); + if (retval && rc != NULL) + free_rule_component(context, rc); + pkiDebug("%s: returning %d\n", __FUNCTION__, retval); + return retval; +} + +static krb5_error_code +parse_rule_set(krb5_context context, + const char *rule_in, + rule_set **out_rs) +{ + const char *rule; + int remaining; + krb5_error_code ret, retval; + rule_component *rc = NULL, *trc; + rule_set *rs; + + + if (rule_in == NULL) + return EINVAL; + rule = rule_in; + remaining = strlen(rule); + + rs = calloc(1, sizeof(*rs)); + if (rs == NULL) { + retval = ENOMEM; + goto cleanup; + } + + rs->relation = relation_none; + if (remaining > 1) { + if (rule[0] == '&' && rule[1] == '&') { + rs->relation = relation_and; + rule += 2; + remaining -= 2; + } else if (rule_in[0] == '|' && rule_in[1] == '|') { + rs->relation = relation_or; + rule +=2; + remaining -= 2; + } + } + rs->num_crs = 0; + while (remaining > 0) { + if (rs->relation == relation_none && rs->num_crs > 0) { + pkiDebug("%s: Assuming AND relation for multiple components in rule '%s'\n", + __FUNCTION__, rule_in); + rs->relation = relation_and; + } + ret = parse_rule_component(context, &rule, &remaining, &rc); + if (ret) { + retval = ret; + goto cleanup; + } + pkiDebug("%s: After parse_rule_component, remaining %d, rule '%s'\n", + __FUNCTION__, remaining, rule); + rs->num_crs++; + + /* + * Chain the new component on the end (order matters since + * we can short-circuit an OR or an AND relation if an + * earlier check passes + */ + for (trc = rs->crs; trc != NULL && trc->next != NULL; trc = trc->next); + if (trc == NULL) + rs->crs = rc; + else { + trc->next = rc; + } + } + + *out_rs = rs; + + retval = 0; +cleanup: + if (retval && rs != NULL) { + free_rule_set(context, rs); + } + pkiDebug("%s: returning %d\n", __FUNCTION__, retval); + return retval; +} + +static int +regexp_match(krb5_context context, rule_component *rc, char *value, int idx) +{ + int code; + + code = regexec(&rc->regexp, value, 0, NULL, 0); + + if (code == 0) { + TRACE_PKINIT_REGEXP_MATCH(context, keyword2string(rc->kw_type), + rc->regsrc, value, idx); + } else { + TRACE_PKINIT_REGEXP_NOMATCH(context, keyword2string(rc->kw_type), + rc->regsrc, value, idx); + } + + return (code == 0 ? 1: 0); +} + +static int +component_match(krb5_context context, rule_component *rc, + pkinit_cert_matching_data *md, int idx) +{ + int match = 0; + int i; + char *princ_string; + + switch (rc->kwval_type) { + case kwvaltype_regexp: + switch (rc->kw_type) { + case kw_subject: + match = regexp_match(context, rc, md->subject_dn, idx); + break; + case kw_issuer: + match = regexp_match(context, rc, md->issuer_dn, idx); + break; + case kw_san: + for (i = 0; md->sans != NULL && md->sans[i] != NULL; i++) { + krb5_unparse_name(context, md->sans[i], &princ_string); + match = regexp_match(context, rc, princ_string, idx); + krb5_free_unparsed_name(context, princ_string); + if (match) + break; + } + for (i = 0; md->upns != NULL && md->upns[i] != NULL; i++) { + match = regexp_match(context, rc, md->upns[i], idx); + if (match) + break; + } + break; + default: + pkiDebug("%s: keyword %s, keyword value %s mismatch\n", + __FUNCTION__, keyword2string(rc->kw_type), + kwval2string(kwvaltype_regexp)); + break; + } + break; + case kwvaltype_list: + switch(rc->kw_type) { + case kw_eku: + pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n", + __FUNCTION__, keyword2string(rc->kw_type), + rc->eku_bits, md->eku_bits); + if ((rc->eku_bits & md->eku_bits) == rc->eku_bits) + match = 1; + break; + case kw_ku: + pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n", + __FUNCTION__, keyword2string(rc->kw_type), + rc->ku_bits, md->ku_bits); + if ((rc->ku_bits & md->ku_bits) == rc->ku_bits) + match = 1; + break; + default: + pkiDebug("%s: keyword %s, keyword value %s mismatch\n", + __FUNCTION__, keyword2string(rc->kw_type), + kwval2string(kwvaltype_regexp)); + break; + } + break; + default: + pkiDebug("%s: unknown keyword value type %d\n", + __FUNCTION__, rc->kwval_type); + break; + } + pkiDebug("%s: returning match = %d\n", __FUNCTION__, match); + return match; +} +/* + * Returns match_found == 1 only if exactly one certificate matches + * the given rule + */ +static krb5_error_code +check_all_certs(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_principal princ, + rule_set *rs, /* rule to check */ + pkinit_cert_matching_data **matchdata, + int *match_found, + size_t *match_index) +{ + krb5_error_code retval; + pkinit_cert_matching_data *md; + int i; + int comp_match = 0; + int total_cert_matches = 0; + rule_component *rc; + int certs_checked = 0; + size_t save_index = 0; + + if (match_found == NULL || match_index == NULL) + return EINVAL; + + *match_index = 0; + *match_found = 0; + + pkiDebug("%s: matching rule relation is %s with %d components\n", + __FUNCTION__, relation2string(rs->relation), rs->num_crs); + + /* + * Loop through all the certs available and count + * how many match the rule + */ + for (i = 0, md = matchdata[i]; md != NULL; md = matchdata[++i]) { + pkiDebug("%s: subject: '%s'\n", __FUNCTION__, md->subject_dn); + certs_checked++; + for (rc = rs->crs; rc != NULL; rc = rc->next) { + comp_match = component_match(context, rc, md, i); + if (comp_match) { + pkiDebug("%s: match for keyword type %s\n", + __FUNCTION__, keyword2string(rc->kw_type)); + } + if (comp_match && rs->relation == relation_or) { + pkiDebug("%s: cert matches rule (OR relation)\n", + __FUNCTION__); + total_cert_matches++; + save_index = i; + goto nextcert; + } + if (!comp_match && rs->relation == relation_and) { + pkiDebug("%s: cert does not match rule (AND relation)\n", + __FUNCTION__); + goto nextcert; + } + } + if (rc == NULL && comp_match) { + pkiDebug("%s: cert matches rule (AND relation)\n", __FUNCTION__); + total_cert_matches++; + save_index = i; + } + nextcert: + continue; + } + TRACE_PKINIT_CERT_NUM_MATCHING(context, certs_checked, total_cert_matches); + if (total_cert_matches == 1) { + *match_found = 1; + *match_index = save_index; + } + + retval = 0; + + pkiDebug("%s: returning %d, match_found %d\n", + __FUNCTION__, retval, *match_found); + return retval; +} + +krb5_error_code +pkinit_cert_matching(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_principal princ) +{ + + krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED; + int x; + char **rules = NULL; + rule_set *rs = NULL; + int match_found = 0; + pkinit_cert_matching_data **matchdata = NULL; + size_t match_index = 0; + + /* If no matching rules, select the default cert and we're done */ + pkinit_libdefault_strings(context, krb5_princ_realm(context, princ), + KRB5_CONF_PKINIT_CERT_MATCH, &rules); + if (rules == NULL) { + pkiDebug("%s: no matching rules found in config file\n", __FUNCTION__); + retval = crypto_cert_select_default(context, plg_cryptoctx, + req_cryptoctx, id_cryptoctx); + goto cleanup; + } + + /* parse each rule line one at a time and check all the certs against it */ + for (x = 0; rules[x] != NULL; x++) { + TRACE_PKINIT_CERT_RULE(context, rules[x]); + + /* Free rules from previous time through... */ + if (rs != NULL) { + free_rule_set(context, rs); + rs = NULL; + } + retval = parse_rule_set(context, rules[x], &rs); + if (retval) { + if (retval == EINVAL) { + TRACE_PKINIT_CERT_RULE_INVALID(context, rules[x]); + continue; + } + goto cleanup; + } + + /* + * Optimize so that we do not get cert info unless we have + * valid rules to check. Once obtained, keep it around + * until we are done. + */ + if (matchdata == NULL) { + retval = crypto_cert_get_matching_data(context, plg_cryptoctx, + req_cryptoctx, id_cryptoctx, + &matchdata); + if (retval || matchdata == NULL) { + pkiDebug("%s: Error %d obtaining certificate information\n", + __FUNCTION__, retval); + retval = ENOENT; + goto cleanup; + } + } + + retval = check_all_certs(context, plg_cryptoctx, req_cryptoctx, + id_cryptoctx, princ, rs, matchdata, + &match_found, &match_index); + if (retval) { + pkiDebug("%s: Error %d, checking certs against rule '%s'\n", + __FUNCTION__, retval, rules[x]); + goto cleanup; + } + if (match_found) { + pkiDebug("%s: We have an exact match with rule '%s'\n", + __FUNCTION__, rules[x]); + break; + } + } + + if (match_found) { + pkiDebug("%s: Selecting the matching cert!\n", __FUNCTION__); + retval = crypto_cert_select(context, id_cryptoctx, match_index); + if (retval) { + pkiDebug("%s: crypto_cert_select error %d, %s\n", + __FUNCTION__, retval, error_message(retval)); + goto cleanup; + } + } else { + TRACE_PKINIT_NO_MATCHING_CERT(context); + retval = ENOENT; /* XXX */ + goto cleanup; + } + + retval = 0; + +cleanup: + profile_free_list(rules); + free_rule_set(context, rs); + crypto_cert_free_matching_data_list(context, matchdata); + return retval; +} + +krb5_error_code +pkinit_client_cert_match(krb5_context context, + pkinit_plg_crypto_context plgctx, + pkinit_req_crypto_context reqctx, + const char *match_rule, + krb5_boolean *matched) +{ + krb5_error_code ret; + pkinit_cert_matching_data *md = NULL; + rule_component *rc = NULL; + int comp_match = 0; + rule_set *rs = NULL; + + *matched = FALSE; + ret = parse_rule_set(context, match_rule, &rs); + if (ret) + goto cleanup; + + ret = crypto_req_cert_matching_data(context, plgctx, reqctx, &md); + if (ret) + goto cleanup; + + for (rc = rs->crs; rc != NULL; rc = rc->next) { + comp_match = component_match(context, rc, md, 0); + if ((comp_match && rs->relation == relation_or) || + (!comp_match && rs->relation == relation_and)) { + break; + } + } + *matched = comp_match; + +cleanup: + free_rule_set(context, rs); + crypto_cert_free_matching_data(context, md); + return ret; +} diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_profile.c b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_profile.c new file mode 100644 index 00000000..334e54ab --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_profile.c @@ -0,0 +1,368 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * COPYRIGHT (C) 2006,2007 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#include "k5-int.h" +#include "pkinit.h" + +/* + * Routines for handling profile [config file] options + */ + +/* Forward prototypes */ +static int _krb5_conf_boolean(const char *s); + +/* + * XXX + * The following is duplicated verbatim from src/lib/krb5/krb/get_in_tkt.c, + * which is duplicated from somewhere else. :-/ + * XXX + */ +static const char *const conf_yes[] = { + "y", "yes", "true", "t", "1", "on", + 0, +}; + +static const char *const conf_no[] = { + "n", "no", "false", "nil", "0", "off", + 0, +}; + +static int +_krb5_conf_boolean(const char *s) +{ + const char *const *p; + + for(p=conf_yes; *p; p++) { + if (strcasecmp(*p,s) == 0) + return 1; + } + + for(p=conf_no; *p; p++) { + if (strcasecmp(*p,s) == 0) + return 0; + } + + /* Default to "no" */ + return 0; +} + +/* + * XXX + * End duplicated code from src/lib/krb5/krb/get_in_tkt.c + * XXX + */ + +/* + * The following are based on krb5_libdefault_* functions in + * src/lib/krb5/krb/get_in_tkt.c + * N.B. This assumes that context->default_realm has + * already been established. + */ +krb5_error_code +pkinit_kdcdefault_strings(krb5_context context, const char *realmname, + const char *option, char ***ret_value) +{ + profile_t profile = NULL; + const char *names[5]; + char **values = NULL; + krb5_error_code retval; + + if (context == NULL) + return KV5M_CONTEXT; + + profile = context->profile; + + if (realmname != NULL) { + /* + * Try number one: + * + * [realms] + * REALM = { + * option = + * } + */ + + names[0] = KRB5_CONF_REALMS; + names[1] = realmname; + names[2] = option; + names[3] = 0; + retval = profile_get_values(profile, names, &values); + if (retval == 0 && values != NULL) + goto goodbye; + } + + /* + * Try number two: + * + * [kdcdefaults] + * option = + */ + + names[0] = KRB5_CONF_KDCDEFAULTS; + names[1] = option; + names[2] = 0; + retval = profile_get_values(profile, names, &values); + if (retval == 0 && values != NULL) + goto goodbye; + +goodbye: + if (values == NULL) + retval = ENOENT; + + *ret_value = values; + + return retval; + +} + +krb5_error_code +pkinit_kdcdefault_string(krb5_context context, const char *realmname, + const char *option, char **ret_value) +{ + krb5_error_code retval; + char **values = NULL; + + retval = pkinit_kdcdefault_strings(context, realmname, option, &values); + if (retval) + return retval; + + if (values[0] == NULL) { + retval = ENOENT; + } else { + *ret_value = strdup(values[0]); + if (*ret_value == NULL) + retval = ENOMEM; + } + + profile_free_list(values); + return retval; +} + +krb5_error_code +pkinit_kdcdefault_boolean(krb5_context context, const char *realmname, + const char *option, int default_value, int *ret_value) +{ + char *string = NULL; + krb5_error_code retval; + + retval = pkinit_kdcdefault_string(context, realmname, option, &string); + + if (retval == 0) { + *ret_value = _krb5_conf_boolean(string); + free(string); + } else + *ret_value = default_value; + + return 0; +} + +krb5_error_code +pkinit_kdcdefault_integer(krb5_context context, const char *realmname, + const char *option, int default_value, int *ret_value) +{ + char *string = NULL; + krb5_error_code retval; + + retval = pkinit_kdcdefault_string(context, realmname, option, &string); + + if (retval == 0) { + char *endptr; + long l; + l = strtol(string, &endptr, 0); + if (endptr == string) + *ret_value = default_value; + else + *ret_value = l; + free(string); + } else + *ret_value = default_value; + + return 0; +} + + +/* + * krb5_libdefault_string() is defined as static in + * src/lib/krb5/krb/get_in_tkt.c. Create local versions of + * krb5_libdefault_* functions here. We need a libdefaults_strings() + * function which is not currently supported there anyway. Also, + * add the ability to supply a default value for the boolean and + * integer functions. + */ + +krb5_error_code +pkinit_libdefault_strings(krb5_context context, const krb5_data *realm, + const char *option, char ***ret_value) +{ + profile_t profile; + const char *names[5]; + char **values = NULL; + krb5_error_code retval; + char realmstr[1024]; + + if (realm != NULL && realm->length > sizeof(realmstr)-1) + return EINVAL; + + if (realm != NULL) { + strncpy(realmstr, realm->data, realm->length); + realmstr[realm->length] = '\0'; + } + + if (!context || (context->magic != KV5M_CONTEXT)) + return KV5M_CONTEXT; + + profile = context->profile; + + + if (realm != NULL) { + /* + * Try number one: + * + * [libdefaults] + * REALM = { + * option = + * } + */ + + names[0] = KRB5_CONF_LIBDEFAULTS; + names[1] = realmstr; + names[2] = option; + names[3] = 0; + retval = profile_get_values(profile, names, &values); + if (retval == 0 && values != NULL && values[0] != NULL) + goto goodbye; + + /* + * Try number two: + * + * [realms] + * REALM = { + * option = + * } + */ + + names[0] = KRB5_CONF_REALMS; + names[1] = realmstr; + names[2] = option; + names[3] = 0; + retval = profile_get_values(profile, names, &values); + if (retval == 0 && values != NULL && values[0] != NULL) + goto goodbye; + } + + /* + * Try number three: + * + * [libdefaults] + * option = + */ + + names[0] = KRB5_CONF_LIBDEFAULTS; + names[1] = option; + names[2] = 0; + retval = profile_get_values(profile, names, &values); + if (retval == 0 && values != NULL && values[0] != NULL) + goto goodbye; + +goodbye: + if (values == NULL) + return ENOENT; + + *ret_value = values; + + return retval; +} + +krb5_error_code +pkinit_libdefault_string(krb5_context context, const krb5_data *realm, + const char *option, char **ret_value) +{ + krb5_error_code retval; + char **values = NULL; + + retval = pkinit_libdefault_strings(context, realm, option, &values); + if (retval) + return retval; + + if (values[0] == NULL) { + retval = ENOENT; + } else { + *ret_value = strdup(values[0]); + if (*ret_value == NULL) + retval = ENOMEM; + } + + profile_free_list(values); + return retval; +} + +krb5_error_code +pkinit_libdefault_boolean(krb5_context context, const krb5_data *realm, + const char *option, int default_value, + int *ret_value) +{ + char *string = NULL; + krb5_error_code retval; + + retval = pkinit_libdefault_string(context, realm, option, &string); + + if (retval == 0) { + *ret_value = _krb5_conf_boolean(string); + free(string); + } else + *ret_value = default_value; + + return 0; +} + +krb5_error_code +pkinit_libdefault_integer(krb5_context context, const krb5_data *realm, + const char *option, int default_value, + int *ret_value) +{ + char *string = NULL; + krb5_error_code retval; + + retval = pkinit_libdefault_string(context, realm, option, &string); + + if (retval == 0) { + char *endptr; + long l; + l = strtol(string, &endptr, 0); + if (endptr == string) + *ret_value = default_value; + else + *ret_value = l; + free(string); + } + + return retval; +} diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_srv.c b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_srv.c new file mode 100644 index 00000000..1b3bf6d4 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_srv.c @@ -0,0 +1,1646 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * COPYRIGHT (C) 2006,2007 + * THE REGENTS OF THE UNIVERSITY OF MICHIGAN + * ALL RIGHTS RESERVED + * + * Permission is granted to use, copy, create derivative works + * and redistribute this software and such derivative works + * for any purpose, so long as the name of The University of + * Michigan is not used in any advertising or publicity + * pertaining to the use of distribution of this software + * without specific, written prior authorization. If the + * above copyright notice or any other identification of the + * University of Michigan is included in any copy of any + * portion of this software, then the disclaimer below must + * also be included. + * + * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION + * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY + * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF + * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING + * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE + * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE + * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING + * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN + * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. + */ + +#include +#include "pkinit.h" +#include "krb5/certauth_plugin.h" + +/* Aliases used by the built-in certauth modules */ +struct certauth_req_opts { + krb5_kdcpreauth_callbacks cb; + krb5_kdcpreauth_rock rock; + pkinit_kdc_context plgctx; + pkinit_kdc_req_context reqctx; +}; + +typedef struct certauth_module_handle_st { + struct krb5_certauth_vtable_st vt; + krb5_certauth_moddata moddata; +} *certauth_handle; + +struct krb5_kdcpreauth_moddata_st { + pkinit_kdc_context *realm_contexts; + certauth_handle *certauth_modules; +}; + +static krb5_error_code +pkinit_init_kdc_req_context(krb5_context, pkinit_kdc_req_context *blob); + +static void +pkinit_fini_kdc_req_context(krb5_context context, void *blob); + +static void +pkinit_server_plugin_fini_realm(krb5_context context, + pkinit_kdc_context plgctx); + +static void +pkinit_server_plugin_fini(krb5_context context, + krb5_kdcpreauth_moddata moddata); + +static pkinit_kdc_context +pkinit_find_realm_context(krb5_context context, + krb5_kdcpreauth_moddata moddata, + krb5_principal princ); + +static void +free_realm_contexts(krb5_context context, pkinit_kdc_context *realm_contexts) +{ + int i; + + if (realm_contexts == NULL) + return; + for (i = 0; realm_contexts[i] != NULL; i++) + pkinit_server_plugin_fini_realm(context, realm_contexts[i]); + pkiDebug("%s: freeing context at %p\n", __FUNCTION__, realm_contexts); + free(realm_contexts); +} + +static void +free_certauth_handles(krb5_context context, certauth_handle *list) +{ + int i; + + if (list == NULL) + return; + for (i = 0; list[i] != NULL; i++) { + if (list[i]->vt.fini != NULL) + list[i]->vt.fini(context, list[i]->moddata); + free(list[i]); + } + free(list); +} + +static krb5_error_code +pkinit_create_edata(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + pkinit_plg_opts *opts, + krb5_error_code err_code, + krb5_pa_data ***e_data_out) +{ + krb5_error_code retval = KRB5KRB_ERR_GENERIC; + + pkiDebug("pkinit_create_edata: creating edata for error %d (%s)\n", + err_code, error_message(err_code)); + switch(err_code) { + case KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE: + retval = pkinit_create_td_trusted_certifiers(context, + plg_cryptoctx, req_cryptoctx, id_cryptoctx, e_data_out); + break; + case KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED: + retval = pkinit_create_td_dh_parameters(context, plg_cryptoctx, + req_cryptoctx, id_cryptoctx, opts, e_data_out); + break; + case KRB5KDC_ERR_INVALID_CERTIFICATE: + case KRB5KDC_ERR_REVOKED_CERTIFICATE: + retval = pkinit_create_td_invalid_certificate(context, + plg_cryptoctx, req_cryptoctx, id_cryptoctx, e_data_out); + break; + default: + pkiDebug("no edata needed for error %d (%s)\n", + err_code, error_message(err_code)); + retval = 0; + goto cleanup; + } + +cleanup: + + return retval; +} + +static void +pkinit_server_get_edata(krb5_context context, + krb5_kdc_req *request, + krb5_kdcpreauth_callbacks cb, + krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, + krb5_preauthtype pa_type, + krb5_kdcpreauth_edata_respond_fn respond, + void *arg) +{ + krb5_error_code retval = 0; + pkinit_kdc_context plgctx = NULL; + + pkiDebug("pkinit_server_get_edata: entered!\n"); + + + /* + * If we don't have a realm context for the given realm, + * don't tell the client that we support pkinit! + */ + plgctx = pkinit_find_realm_context(context, moddata, request->server); + if (plgctx == NULL) + retval = EINVAL; + + /* Send a freshness token if the client requested one. */ + if (!retval) + cb->send_freshness_token(context, rock); + + (*respond)(arg, retval, NULL); +} + +static krb5_error_code +verify_client_san(krb5_context context, + pkinit_kdc_context plgctx, + pkinit_kdc_req_context reqctx, + krb5_kdcpreauth_callbacks cb, + krb5_kdcpreauth_rock rock, + krb5_const_principal client, + int *valid_san) +{ + krb5_error_code retval; + krb5_principal *princs = NULL, upn; + krb5_boolean match; + char **upns = NULL; + int i; +#ifdef DEBUG_SAN_INFO + char *client_string = NULL, *san_string; +#endif + + *valid_san = 0; + retval = crypto_retrieve_cert_sans(context, plgctx->cryptoctx, + reqctx->cryptoctx, plgctx->idctx, + &princs, + plgctx->opts->allow_upn ? &upns : NULL, + NULL); + if (retval) { + pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__); + retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH; + goto out; + } + + if (princs == NULL && upns == NULL) { + TRACE_PKINIT_SERVER_NO_SAN(context); + retval = ENOENT; + goto out; + } + +#ifdef DEBUG_SAN_INFO + krb5_unparse_name(context, client, &client_string); +#endif + pkiDebug("%s: Checking pkinit sans\n", __FUNCTION__); + for (i = 0; princs != NULL && princs[i] != NULL; i++) { +#ifdef DEBUG_SAN_INFO + krb5_unparse_name(context, princs[i], &san_string); + pkiDebug("%s: Comparing client '%s' to pkinit san value '%s'\n", + __FUNCTION__, client_string, san_string); + krb5_free_unparsed_name(context, san_string); +#endif + if (cb->match_client(context, rock, princs[i])) { + TRACE_PKINIT_SERVER_MATCHING_SAN_FOUND(context); + *valid_san = 1; + retval = 0; + goto out; + } + } + pkiDebug("%s: no pkinit san match found\n", __FUNCTION__); + /* + * XXX if cert has names but none match, should we + * be returning KRB5KDC_ERR_CLIENT_NAME_MISMATCH here? + */ + + if (upns == NULL) { + pkiDebug("%s: no upn sans (or we wouldn't accept them anyway)\n", + __FUNCTION__); + retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH; + goto out; + } + + pkiDebug("%s: Checking upn sans\n", __FUNCTION__); + for (i = 0; upns[i] != NULL; i++) { +#ifdef DEBUG_SAN_INFO + pkiDebug("%s: Comparing client '%s' to upn san value '%s'\n", + __FUNCTION__, client_string, upns[i]); +#endif + retval = krb5_parse_name_flags(context, upns[i], + KRB5_PRINCIPAL_PARSE_ENTERPRISE, &upn); + if (retval) { + TRACE_PKINIT_SERVER_UPN_PARSE_FAIL(context, upns[i], retval); + continue; + } + match = cb->match_client(context, rock, upn); + krb5_free_principal(context, upn); + if (match) { + TRACE_PKINIT_SERVER_MATCHING_UPN_FOUND(context); + *valid_san = 1; + retval = 0; + goto out; + } + } + pkiDebug("%s: no upn san match found\n", __FUNCTION__); + + retval = 0; +out: + if (princs != NULL) { + for (i = 0; princs[i] != NULL; i++) + krb5_free_principal(context, princs[i]); + free(princs); + } + if (upns != NULL) { + for (i = 0; upns[i] != NULL; i++) + free(upns[i]); + free(upns); + } +#ifdef DEBUG_SAN_INFO + if (client_string != NULL) + krb5_free_unparsed_name(context, client_string); +#endif + pkiDebug("%s: returning retval %d, valid_san %d\n", + __FUNCTION__, retval, *valid_san); + return retval; +} + +static krb5_error_code +verify_client_eku(krb5_context context, + pkinit_kdc_context plgctx, + pkinit_kdc_req_context reqctx, + int *eku_accepted) +{ + krb5_error_code retval; + + *eku_accepted = 0; + + if (plgctx->opts->require_eku == 0) { + TRACE_PKINIT_SERVER_EKU_SKIP(context); + *eku_accepted = 1; + retval = 0; + goto out; + } + + retval = crypto_check_cert_eku(context, plgctx->cryptoctx, + reqctx->cryptoctx, plgctx->idctx, + 0, /* kdc cert */ + plgctx->opts->accept_secondary_eku, + eku_accepted); + if (retval) { + pkiDebug("%s: Error from crypto_check_cert_eku %d (%s)\n", + __FUNCTION__, retval, error_message(retval)); + goto out; + } + +out: + pkiDebug("%s: returning retval %d, eku_accepted %d\n", + __FUNCTION__, retval, *eku_accepted); + return retval; +} + + +/* Run the received, verified certificate through certauth modules, to verify + * that it is authorized to authenticate as client. */ +static krb5_error_code +authorize_cert(krb5_context context, certauth_handle *certauth_modules, + pkinit_kdc_context plgctx, pkinit_kdc_req_context reqctx, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_principal client, krb5_boolean *hwauth_out) +{ + krb5_error_code ret; + certauth_handle h; + struct certauth_req_opts opts; + krb5_boolean accepted = FALSE, hwauth = FALSE; + uint8_t *cert; + size_t i, cert_len; + void *db_ent = NULL; + char **ais = NULL, **ai = NULL; + + /* Re-encode the received certificate into DER, which is extra work, but + * avoids creating an X.509 library dependency in the interface. */ + ret = crypto_encode_der_cert(context, reqctx->cryptoctx, &cert, &cert_len); + if (ret) + goto cleanup; + + /* Set options for the builtin module. */ + opts.plgctx = plgctx; + opts.reqctx = reqctx; + opts.cb = cb; + opts.rock = rock; + + db_ent = cb->client_entry(context, rock); + + /* + * Check the certificate against each certauth module. For the certificate + * to be authorized at least one module must return 0 or + * KRB5_CERTAUTH_HWAUTH, and no module can return an error code other than + * KRB5_PLUGIN_NO_HANDLE (pass) or KRB5_CERTAUTH_HWAUTH_PASS (pass but + * set hw-authent). Add indicators from all modules. + */ + ret = KRB5_PLUGIN_NO_HANDLE; + for (i = 0; certauth_modules != NULL && certauth_modules[i] != NULL; i++) { + h = certauth_modules[i]; + TRACE_PKINIT_SERVER_CERT_AUTH(context, h->vt.name); + ret = h->vt.authorize(context, h->moddata, cert, cert_len, client, + &opts, db_ent, &ais); + if (ret == 0) + accepted = TRUE; + else if (ret == KRB5_CERTAUTH_HWAUTH) + accepted = hwauth = TRUE; + else if (ret == KRB5_CERTAUTH_HWAUTH_PASS) + hwauth = TRUE; + else if (ret != KRB5_PLUGIN_NO_HANDLE) + goto cleanup; + + if (ais != NULL) { + /* Assert authentication indicators from the module. */ + for (ai = ais; *ai != NULL; ai++) { + ret = cb->add_auth_indicator(context, rock, *ai); + if (ret) + goto cleanup; + } + h->vt.free_ind(context, h->moddata, ais); + ais = NULL; + } + } + + *hwauth_out = hwauth; + ret = accepted ? 0 : KRB5KDC_ERR_CLIENT_NAME_MISMATCH; + +cleanup: + free(cert); + return ret; +} + +/* Return an error if freshness tokens are required and one was not received. + * Log an appropriate message indicating whether a valid token was received. */ +static krb5_error_code +check_log_freshness(krb5_context context, pkinit_kdc_context plgctx, + krb5_kdc_req *request, krb5_boolean valid_freshness_token) +{ + krb5_error_code ret; + char *name = NULL; + + ret = krb5_unparse_name(context, request->client, &name); + if (ret) + return ret; + if (plgctx->opts->require_freshness && !valid_freshness_token) { + com_err("", 0, _("PKINIT: no freshness token, rejecting auth from %s"), + name); + ret = KRB5KDC_ERR_PREAUTH_FAILED; + } else if (valid_freshness_token) { + com_err("", 0, _("PKINIT: freshness token received from %s"), name); + } else { + com_err("", 0, _("PKINIT: no freshness token received from %s"), name); + } + krb5_free_unparsed_name(context, name); + return ret; +} + +static void +pkinit_server_verify_padata(krb5_context context, + krb5_data *req_pkt, + krb5_kdc_req * request, + krb5_enc_tkt_part * enc_tkt_reply, + krb5_pa_data * data, + krb5_kdcpreauth_callbacks cb, + krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_verify_respond_fn respond, + void *arg) +{ + krb5_error_code retval = 0; + krb5_data authp_data = {0, 0, NULL}, krb5_authz = {0, 0, NULL}; + krb5_pa_pk_as_req *reqp = NULL; + krb5_auth_pack *auth_pack = NULL; + pkinit_kdc_context plgctx = NULL; + pkinit_kdc_req_context reqctx = NULL; + krb5_checksum cksum = {0, 0, 0, NULL}; + krb5_data *der_req = NULL; + krb5_data k5data, *ftoken; + int is_signed = 1; + krb5_pa_data **e_data = NULL; + krb5_kdcpreauth_modreq modreq = NULL; + krb5_boolean valid_freshness_token = FALSE, hwauth = FALSE; + char **sp; + + pkiDebug("pkinit_verify_padata: entered!\n"); + if (data == NULL || data->length <= 0 || data->contents == NULL) { + (*respond)(arg, EINVAL, NULL, NULL, NULL); + return; + } + + + if (moddata == NULL) { + (*respond)(arg, EINVAL, NULL, NULL, NULL); + return; + } + + plgctx = pkinit_find_realm_context(context, moddata, request->server); + if (plgctx == NULL) { + (*respond)(arg, EINVAL, NULL, NULL, NULL); + return; + } + +#ifdef DEBUG_ASN1 + print_buffer_bin(data->contents, data->length, "/tmp/kdc_as_req"); +#endif + /* create a per-request context */ + retval = pkinit_init_kdc_req_context(context, &reqctx); + if (retval) + goto cleanup; + reqctx->pa_type = data->pa_type; + + PADATA_TO_KRB5DATA(data, &k5data); + + if (data->pa_type != KRB5_PADATA_PK_AS_REQ) { + pkiDebug("unrecognized pa_type = %d\n", data->pa_type); + retval = EINVAL; + goto cleanup; + } + + TRACE_PKINIT_SERVER_PADATA_VERIFY(context); + retval = k5int_decode_krb5_pa_pk_as_req(&k5data, &reqp); + if (retval) { + pkiDebug("decode_krb5_pa_pk_as_req failed\n"); + goto cleanup; + } +#ifdef DEBUG_ASN1 + print_buffer_bin(reqp->signedAuthPack.data, reqp->signedAuthPack.length, + "/tmp/kdc_signed_data"); +#endif + retval = cms_signeddata_verify(context, plgctx->cryptoctx, + reqctx->cryptoctx, plgctx->idctx, + CMS_SIGN_CLIENT, + plgctx->opts->require_crl_checking, + (unsigned char *)reqp->signedAuthPack.data, + reqp->signedAuthPack.length, + (unsigned char **)&authp_data.data, + &authp_data.length, + (unsigned char **)&krb5_authz.data, + &krb5_authz.length, &is_signed); + if (retval) { + TRACE_PKINIT_SERVER_PADATA_VERIFY_FAIL(context); + goto cleanup; + } + if (is_signed) { + retval = authorize_cert(context, moddata->certauth_modules, plgctx, + reqctx, cb, rock, request->client, &hwauth); + if (retval) + goto cleanup; + + } else { /* !is_signed */ + if (!krb5_principal_compare(context, request->client, + krb5_anonymous_principal())) { + retval = KRB5KDC_ERR_PREAUTH_FAILED; + krb5_set_error_message(context, retval, + _("Pkinit request not signed, but client " + "not anonymous.")); + goto cleanup; + } + } +#ifdef DEBUG_ASN1 + print_buffer_bin(authp_data.data, authp_data.length, "/tmp/kdc_auth_pack"); +#endif + + OCTETDATA_TO_KRB5DATA(&authp_data, &k5data); + retval = k5int_decode_krb5_auth_pack(&k5data, &auth_pack); + if (retval) { + pkiDebug("failed to decode krb5_auth_pack\n"); + goto cleanup; + } + + retval = krb5_check_clockskew(context, auth_pack->pkAuthenticator.ctime); + if (retval) + goto cleanup; + + /* check dh parameters */ + if (auth_pack->clientPublicValue.length > 0) { + retval = server_check_dh(context, plgctx->cryptoctx, + reqctx->cryptoctx, plgctx->idctx, + &auth_pack->clientPublicValue, + plgctx->opts->dh_min_bits); + if (retval) { + pkiDebug("bad dh parameters\n"); + goto cleanup; + } + } else if (!is_signed) { + /*Anonymous pkinit requires DH*/ + retval = KRB5KDC_ERR_PREAUTH_FAILED; + krb5_set_error_message(context, retval, + _("Anonymous pkinit without DH public " + "value not supported.")); + goto cleanup; + } + der_req = cb->request_body(context, rock); + retval = krb5_c_make_checksum(context, CKSUMTYPE_SHA1, NULL, 0, der_req, + &cksum); + if (retval) { + pkiDebug("unable to calculate AS REQ checksum\n"); + goto cleanup; + } + if (cksum.length != auth_pack->pkAuthenticator.paChecksum.length || + k5_bcmp(cksum.contents, auth_pack->pkAuthenticator.paChecksum.contents, + cksum.length) != 0) { + pkiDebug("failed to match the checksum\n"); +#ifdef DEBUG_CKSUM + pkiDebug("calculating checksum on buf size (%d)\n", req_pkt->length); + print_buffer(req_pkt->data, req_pkt->length); + pkiDebug("received checksum type=%d size=%d ", + auth_pack->pkAuthenticator.paChecksum.checksum_type, + auth_pack->pkAuthenticator.paChecksum.length); + print_buffer(auth_pack->pkAuthenticator.paChecksum.contents, + auth_pack->pkAuthenticator.paChecksum.length); + pkiDebug("expected checksum type=%d size=%d ", + cksum.checksum_type, cksum.length); + print_buffer(cksum.contents, cksum.length); +#endif + + retval = KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED; + goto cleanup; + } + + ftoken = auth_pack->pkAuthenticator.freshnessToken; + if (ftoken != NULL) { + retval = cb->check_freshness_token(context, rock, ftoken); + if (retval) + goto cleanup; + valid_freshness_token = TRUE; + } + + /* check if kdcPkId present and match KDC's subjectIdentifier */ + if (reqp->kdcPkId.data != NULL) { + int valid_kdcPkId = 0; + retval = pkinit_check_kdc_pkid(context, plgctx->cryptoctx, + reqctx->cryptoctx, plgctx->idctx, + (unsigned char *)reqp->kdcPkId.data, + reqp->kdcPkId.length, &valid_kdcPkId); + if (retval) + goto cleanup; + if (!valid_kdcPkId) { + pkiDebug("kdcPkId in AS_REQ does not match KDC's cert; " + "RFC says to ignore and proceed\n"); + } + } + /* remember the decoded auth_pack for verify_padata routine */ + reqctx->rcv_auth_pack = auth_pack; + auth_pack = NULL; + + if (is_signed) { + retval = check_log_freshness(context, plgctx, request, + valid_freshness_token); + if (retval) + goto cleanup; + } + + if (is_signed && plgctx->auth_indicators != NULL) { + /* Assert configured authentication indicators. */ + for (sp = plgctx->auth_indicators; *sp != NULL; sp++) { + retval = cb->add_auth_indicator(context, rock, *sp); + if (retval) + goto cleanup; + } + } + + /* remember to set the PREAUTH flag in the reply */ + enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; + if (hwauth) + enc_tkt_reply->flags |= TKT_FLG_HW_AUTH; + modreq = (krb5_kdcpreauth_modreq)reqctx; + reqctx = NULL; + +cleanup: + if (retval && data->pa_type == KRB5_PADATA_PK_AS_REQ) { + pkiDebug("pkinit_verify_padata failed: creating e-data\n"); + if (pkinit_create_edata(context, plgctx->cryptoctx, reqctx->cryptoctx, + plgctx->idctx, plgctx->opts, retval, &e_data)) + pkiDebug("pkinit_create_edata failed\n"); + } + + free_krb5_pa_pk_as_req(&reqp); + free(cksum.contents); + free(authp_data.data); + free(krb5_authz.data); + if (reqctx != NULL) + pkinit_fini_kdc_req_context(context, reqctx); + free_krb5_auth_pack(&auth_pack); + + (*respond)(arg, retval, modreq, e_data, NULL); +} +static krb5_error_code +return_pkinit_kx(krb5_context context, krb5_kdc_req *request, + krb5_kdc_rep *reply, krb5_keyblock *encrypting_key, + krb5_pa_data **out_padata) +{ + krb5_error_code ret = 0; + krb5_keyblock *session = reply->ticket->enc_part2->session; + krb5_keyblock *new_session = NULL; + krb5_pa_data *pa = NULL; + krb5_enc_data enc; + krb5_data *scratch = NULL; + + *out_padata = NULL; + enc.ciphertext.data = NULL; + if (!krb5_principal_compare(context, request->client, + krb5_anonymous_principal())) + return 0; + /* + * The KDC contribution key needs to be a fresh key of an enctype supported + * by the client and server. The existing session key meets these + * requirements so we use it. + */ + ret = krb5_c_fx_cf2_simple(context, session, "PKINIT", + encrypting_key, "KEYEXCHANGE", + &new_session); + if (ret) + goto cleanup; + ret = encode_krb5_encryption_key( session, &scratch); + if (ret) + goto cleanup; + ret = krb5_encrypt_helper(context, encrypting_key, + KRB5_KEYUSAGE_PA_PKINIT_KX, scratch, &enc); + if (ret) + goto cleanup; + memset(scratch->data, 0, scratch->length); + krb5_free_data(context, scratch); + scratch = NULL; + ret = encode_krb5_enc_data(&enc, &scratch); + if (ret) + goto cleanup; + pa = malloc(sizeof(krb5_pa_data)); + if (pa == NULL) { + ret = ENOMEM; + goto cleanup; + } + pa->pa_type = KRB5_PADATA_PKINIT_KX; + pa->length = scratch->length; + pa->contents = (krb5_octet *) scratch->data; + *out_padata = pa; + scratch->data = NULL; + memset(session->contents, 0, session->length); + krb5_free_keyblock_contents(context, session); + *session = *new_session; + new_session->contents = NULL; +cleanup: + krb5_free_data_contents(context, &enc.ciphertext); + krb5_free_keyblock(context, new_session); + krb5_free_data(context, scratch); + return ret; +} + +static krb5_error_code +pkinit_pick_kdf_alg(krb5_context context, krb5_data **kdf_list, + krb5_data **alg_oid) +{ + krb5_error_code retval = 0; + krb5_data *req_oid = NULL; + const krb5_data *supp_oid = NULL; + krb5_data *tmp_oid = NULL; + int i, j = 0; + + /* if we don't find a match, return NULL value */ + *alg_oid = NULL; + + /* for each of the OIDs that the server supports... */ + for (i = 0; NULL != (supp_oid = supported_kdf_alg_ids[i]); i++) { + /* if the requested OID is in the client's list, use it. */ + for (j = 0; NULL != (req_oid = kdf_list[j]); j++) { + if ((req_oid->length == supp_oid->length) && + (0 == memcmp(req_oid->data, supp_oid->data, req_oid->length))) { + tmp_oid = k5alloc(sizeof(krb5_data), &retval); + if (retval) + goto cleanup; + tmp_oid->data = k5memdup(supp_oid->data, supp_oid->length, + &retval); + if (retval) + goto cleanup; + tmp_oid->length = supp_oid->length; + *alg_oid = tmp_oid; + /* don't free the OID in clean-up if we are returning it */ + tmp_oid = NULL; + goto cleanup; + } + } + } +cleanup: + if (tmp_oid) + krb5_free_data(context, tmp_oid); + return retval; +} + +static krb5_error_code +pkinit_server_return_padata(krb5_context context, + krb5_pa_data * padata, + krb5_data *req_pkt, + krb5_kdc_req * request, + krb5_kdc_rep * reply, + krb5_keyblock * encrypting_key, + krb5_pa_data ** send_pa, + krb5_kdcpreauth_callbacks cb, + krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq) +{ + krb5_error_code retval = 0; + krb5_data scratch = {0, 0, NULL}; + krb5_pa_pk_as_req *reqp = NULL; + int i = 0; + + unsigned char *dh_pubkey = NULL, *server_key = NULL; + unsigned int server_key_len = 0, dh_pubkey_len = 0; + krb5_keyblock reply_key = { 0 }; + + krb5_kdc_dh_key_info dhkey_info; + krb5_data *encoded_dhkey_info = NULL; + krb5_pa_pk_as_rep *rep = NULL; + krb5_data *out_data = NULL; + krb5_data secret; + + krb5_enctype enctype = -1; + + krb5_reply_key_pack *key_pack = NULL; + krb5_data *encoded_key_pack = NULL; + + pkinit_kdc_context plgctx; + pkinit_kdc_req_context reqctx; + + *send_pa = NULL; + if (padata->pa_type == KRB5_PADATA_PKINIT_KX) { + return return_pkinit_kx(context, request, reply, + encrypting_key, send_pa); + } + if (padata->length <= 0 || padata->contents == NULL) + return 0; + + if (modreq == NULL) { + pkiDebug("missing request context \n"); + return EINVAL; + } + + plgctx = pkinit_find_realm_context(context, moddata, request->server); + if (plgctx == NULL) { + pkiDebug("Unable to locate correct realm context\n"); + return ENOENT; + } + + TRACE_PKINIT_SERVER_RETURN_PADATA(context); + reqctx = (pkinit_kdc_req_context)modreq; + + for(i = 0; i < request->nktypes; i++) { + enctype = request->ktype[i]; + if (!krb5_c_valid_enctype(enctype)) + continue; + else { + pkiDebug("KDC picked etype = %d\n", enctype); + break; + } + } + + if (i == request->nktypes) { + retval = KRB5KDC_ERR_ETYPE_NOSUPP; + goto cleanup; + } + + init_krb5_pa_pk_as_rep(&rep); + if (rep == NULL) { + retval = ENOMEM; + goto cleanup; + } + /* let's assume it's RSA. we'll reset it to DH if needed */ + rep->choice = choice_pa_pk_as_rep_encKeyPack; + + if (reqctx->rcv_auth_pack != NULL && + reqctx->rcv_auth_pack->clientPublicValue.length > 0) { + rep->choice = choice_pa_pk_as_rep_dhInfo; + + pkiDebug("received DH key delivery AS REQ\n"); + retval = server_process_dh(context, plgctx->cryptoctx, + reqctx->cryptoctx, plgctx->idctx, + &dh_pubkey, &dh_pubkey_len, + &server_key, &server_key_len); + if (retval) { + pkiDebug("failed to process/create dh parameters\n"); + goto cleanup; + } + + /* + * This is DH, so don't generate the key until after we + * encode the reply, because the encoded reply is needed + * to generate the key in some cases. + */ + + dhkey_info.subjectPublicKey.length = dh_pubkey_len; + dhkey_info.subjectPublicKey.data = (char *)dh_pubkey; + dhkey_info.nonce = request->nonce; + dhkey_info.dhKeyExpiration = 0; + + retval = k5int_encode_krb5_kdc_dh_key_info(&dhkey_info, + &encoded_dhkey_info); + if (retval) { + pkiDebug("encode_krb5_kdc_dh_key_info failed\n"); + goto cleanup; + } +#ifdef DEBUG_ASN1 + print_buffer_bin((unsigned char *)encoded_dhkey_info->data, + encoded_dhkey_info->length, + "/tmp/kdc_dh_key_info"); +#endif + + retval = cms_signeddata_create(context, plgctx->cryptoctx, + reqctx->cryptoctx, plgctx->idctx, + CMS_SIGN_SERVER, + (unsigned char *) + encoded_dhkey_info->data, + encoded_dhkey_info->length, + (unsigned char **) + &rep->u.dh_Info.dhSignedData.data, + &rep->u.dh_Info.dhSignedData.length); + if (retval) { + pkiDebug("failed to create pkcs7 signed data\n"); + goto cleanup; + } + + } else { + pkiDebug("received RSA key delivery AS REQ\n"); + + init_krb5_reply_key_pack(&key_pack); + if (key_pack == NULL) { + retval = ENOMEM; + goto cleanup; + } + + retval = krb5_c_make_random_key(context, enctype, &key_pack->replyKey); + if (retval) { + pkiDebug("unable to make a session key\n"); + goto cleanup; + } + + retval = krb5_c_make_checksum(context, 0, &key_pack->replyKey, + KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, + req_pkt, &key_pack->asChecksum); + if (retval) { + pkiDebug("unable to calculate AS REQ checksum\n"); + goto cleanup; + } +#ifdef DEBUG_CKSUM + pkiDebug("calculating checksum on buf size = %d\n", req_pkt->length); + print_buffer(req_pkt->data, req_pkt->length); + pkiDebug("checksum size = %d\n", key_pack->asChecksum.length); + print_buffer(key_pack->asChecksum.contents, + key_pack->asChecksum.length); + pkiDebug("encrypting key (%d)\n", key_pack->replyKey.length); + print_buffer(key_pack->replyKey.contents, key_pack->replyKey.length); +#endif + + retval = k5int_encode_krb5_reply_key_pack(key_pack, + &encoded_key_pack); + if (retval) { + pkiDebug("failed to encode reply_key_pack\n"); + goto cleanup; + } + + rep->choice = choice_pa_pk_as_rep_encKeyPack; + retval = cms_envelopeddata_create(context, plgctx->cryptoctx, + reqctx->cryptoctx, plgctx->idctx, + padata->pa_type, + (unsigned char *) + encoded_key_pack->data, + encoded_key_pack->length, + (unsigned char **) + &rep->u.encKeyPack.data, + &rep->u.encKeyPack.length); + if (retval) { + pkiDebug("failed to create pkcs7 enveloped data: %s\n", + error_message(retval)); + goto cleanup; + } +#ifdef DEBUG_ASN1 + print_buffer_bin((unsigned char *)encoded_key_pack->data, + encoded_key_pack->length, + "/tmp/kdc_key_pack"); + print_buffer_bin(rep->u.encKeyPack.data, rep->u.encKeyPack.length, + "/tmp/kdc_enc_key_pack"); +#endif + + retval = cb->replace_reply_key(context, rock, &key_pack->replyKey, + FALSE); + if (retval) + goto cleanup; + } + + if (rep->choice == choice_pa_pk_as_rep_dhInfo && + ((reqctx->rcv_auth_pack != NULL && + reqctx->rcv_auth_pack->supportedKDFs != NULL))) { + + /* If using the alg-agility KDF, put the algorithm in the reply + * before encoding it. + */ + if (reqctx->rcv_auth_pack != NULL && + reqctx->rcv_auth_pack->supportedKDFs != NULL) { + retval = pkinit_pick_kdf_alg(context, reqctx->rcv_auth_pack->supportedKDFs, + &(rep->u.dh_Info.kdfID)); + if (retval) { + pkiDebug("pkinit_pick_kdf_alg failed: %s\n", + error_message(retval)); + goto cleanup; + } + } + } + + retval = k5int_encode_krb5_pa_pk_as_rep(rep, &out_data); + if (retval) { + pkiDebug("failed to encode AS_REP\n"); + goto cleanup; + } +#ifdef DEBUG_ASN1 + if (out_data != NULL) + print_buffer_bin((unsigned char *)out_data->data, out_data->length, + "/tmp/kdc_as_rep"); +#endif + + /* If this is DH, we haven't computed the key yet, so do it now. */ + if (rep->choice == choice_pa_pk_as_rep_dhInfo) { + + /* If mutually supported KDFs were found, use the algorithm agility + * KDF. */ + if (rep->u.dh_Info.kdfID) { + secret.data = (char *)server_key; + secret.length = server_key_len; + + retval = pkinit_alg_agility_kdf(context, &secret, + rep->u.dh_Info.kdfID, + request->client, request->server, + enctype, req_pkt, out_data, + &reply_key); + if (retval) { + pkiDebug("pkinit_alg_agility_kdf failed: %s\n", + error_message(retval)); + goto cleanup; + } + + /* Otherwise, use the older octetstring2key() function */ + } else { + retval = pkinit_octetstring2key(context, enctype, server_key, + server_key_len, &reply_key); + if (retval) { + pkiDebug("pkinit_octetstring2key failed: %s\n", + error_message(retval)); + goto cleanup; + } + } + retval = cb->replace_reply_key(context, rock, &reply_key, FALSE); + if (retval) + goto cleanup; + } + + *send_pa = malloc(sizeof(krb5_pa_data)); + if (*send_pa == NULL) { + retval = ENOMEM; + free(out_data->data); + free(out_data); + out_data = NULL; + goto cleanup; + } + (*send_pa)->magic = KV5M_PA_DATA; + (*send_pa)->pa_type = KRB5_PADATA_PK_AS_REP; + (*send_pa)->length = out_data->length; + (*send_pa)->contents = (krb5_octet *) out_data->data; + +cleanup: + free(scratch.data); + free(out_data); + if (encoded_dhkey_info != NULL) + krb5_free_data(context, encoded_dhkey_info); + if (encoded_key_pack != NULL) + krb5_free_data(context, encoded_key_pack); + free(dh_pubkey); + free(server_key); + free_krb5_pa_pk_as_req(&reqp); + free_krb5_pa_pk_as_rep(&rep); + free_krb5_reply_key_pack(&key_pack); + krb5_free_keyblock_contents(context, &reply_key); + + if (retval) + pkiDebug("pkinit_verify_padata failure"); + + return retval; +} + +static int +pkinit_server_get_flags(krb5_context kcontext, krb5_preauthtype patype) +{ + if (patype == KRB5_PADATA_PKINIT_KX) + return PA_INFO; + /* PKINIT does not normally set the hw-authent ticket flag, but a + * certauth module can cause it to do so. */ + return PA_SUFFICIENT | PA_REPLACES_KEY | PA_TYPED_E_DATA | PA_HARDWARE; +} + +static krb5_preauthtype supported_server_pa_types[] = { + KRB5_PADATA_PK_AS_REQ, + KRB5_PADATA_PKINIT_KX, + 0 +}; + +static void +pkinit_fini_kdc_profile(krb5_context context, pkinit_kdc_context plgctx) +{ + /* + * There is nothing currently allocated by pkinit_init_kdc_profile() + * which needs to be freed here. + */ +} + +static krb5_error_code +pkinit_init_kdc_profile(krb5_context context, pkinit_kdc_context plgctx) +{ + krb5_error_code retval; + char *eku_string = NULL, *ocsp_check = NULL; + + pkiDebug("%s: entered for realm %s\n", __FUNCTION__, plgctx->realmname); + retval = pkinit_kdcdefault_string(context, plgctx->realmname, + KRB5_CONF_PKINIT_IDENTITY, + &plgctx->idopts->identity); + if (retval != 0 || NULL == plgctx->idopts->identity) { + retval = EINVAL; + krb5_set_error_message(context, retval, + _("No pkinit_identity supplied for realm %s"), + plgctx->realmname); + goto errout; + } + + retval = pkinit_kdcdefault_strings(context, plgctx->realmname, + KRB5_CONF_PKINIT_ANCHORS, + &plgctx->idopts->anchors); + if (retval != 0 || NULL == plgctx->idopts->anchors) { + retval = EINVAL; + krb5_set_error_message(context, retval, + _("No pkinit_anchors supplied for realm %s"), + plgctx->realmname); + goto errout; + } + + pkinit_kdcdefault_strings(context, plgctx->realmname, + KRB5_CONF_PKINIT_POOL, + &plgctx->idopts->intermediates); + + pkinit_kdcdefault_strings(context, plgctx->realmname, + KRB5_CONF_PKINIT_REVOKE, + &plgctx->idopts->crls); + + pkinit_kdcdefault_string(context, plgctx->realmname, + KRB5_CONF_PKINIT_KDC_OCSP, + &ocsp_check); + if (ocsp_check != NULL) { + free(ocsp_check); + retval = ENOTSUP; + krb5_set_error_message(context, retval, + _("OCSP is not supported: (realm: %s)"), + plgctx->realmname); + goto errout; + } + + pkinit_kdcdefault_integer(context, plgctx->realmname, + KRB5_CONF_PKINIT_DH_MIN_BITS, + PKINIT_DEFAULT_DH_MIN_BITS, + &plgctx->opts->dh_min_bits); + if (plgctx->opts->dh_min_bits < PKINIT_DH_MIN_CONFIG_BITS) { + pkiDebug("%s: invalid value (%d < %d) for pkinit_dh_min_bits, " + "using default value (%d) instead\n", __FUNCTION__, + plgctx->opts->dh_min_bits, PKINIT_DH_MIN_CONFIG_BITS, + PKINIT_DEFAULT_DH_MIN_BITS); + plgctx->opts->dh_min_bits = PKINIT_DEFAULT_DH_MIN_BITS; + } + + pkinit_kdcdefault_boolean(context, plgctx->realmname, + KRB5_CONF_PKINIT_ALLOW_UPN, + 0, &plgctx->opts->allow_upn); + + pkinit_kdcdefault_boolean(context, plgctx->realmname, + KRB5_CONF_PKINIT_REQUIRE_CRL_CHECKING, + 0, &plgctx->opts->require_crl_checking); + + pkinit_kdcdefault_boolean(context, plgctx->realmname, + KRB5_CONF_PKINIT_REQUIRE_FRESHNESS, + 0, &plgctx->opts->require_freshness); + + pkinit_kdcdefault_string(context, plgctx->realmname, + KRB5_CONF_PKINIT_EKU_CHECKING, + &eku_string); + if (eku_string != NULL) { + if (strcasecmp(eku_string, "kpClientAuth") == 0) { + plgctx->opts->require_eku = 1; + plgctx->opts->accept_secondary_eku = 0; + } else if (strcasecmp(eku_string, "scLogin") == 0) { + plgctx->opts->require_eku = 1; + plgctx->opts->accept_secondary_eku = 1; + } else if (strcasecmp(eku_string, "none") == 0) { + plgctx->opts->require_eku = 0; + plgctx->opts->accept_secondary_eku = 0; + } else { + pkiDebug("%s: Invalid value for pkinit_eku_checking: '%s'\n", + __FUNCTION__, eku_string); + } + free(eku_string); + } + + pkinit_kdcdefault_strings(context, plgctx->realmname, + KRB5_CONF_PKINIT_INDICATOR, + &plgctx->auth_indicators); + + return 0; +errout: + pkinit_fini_kdc_profile(context, plgctx); + return retval; +} + +static pkinit_kdc_context +pkinit_find_realm_context(krb5_context context, + krb5_kdcpreauth_moddata moddata, + krb5_principal princ) +{ + int i; + pkinit_kdc_context *realm_contexts; + + if (moddata == NULL) + return NULL; + + realm_contexts = moddata->realm_contexts; + if (realm_contexts == NULL) + return NULL; + + for (i = 0; realm_contexts[i] != NULL; i++) { + pkinit_kdc_context p = realm_contexts[i]; + + if ((p->realmname_len == princ->realm.length) && + (strncmp(p->realmname, princ->realm.data, p->realmname_len) == 0)) { + pkiDebug("%s: returning context at %p for realm '%s'\n", + __FUNCTION__, p, p->realmname); + return p; + } + } + pkiDebug("%s: unable to find realm context for realm '%.*s'\n", + __FUNCTION__, princ->realm.length, princ->realm.data); + return NULL; +} + +static int +pkinit_server_plugin_init_realm(krb5_context context, const char *realmname, + pkinit_kdc_context *pplgctx) +{ + krb5_error_code retval = ENOMEM; + pkinit_kdc_context plgctx = NULL; + + *pplgctx = NULL; + + plgctx = calloc(1, sizeof(*plgctx)); + if (plgctx == NULL) + goto errout; + + pkiDebug("%s: initializing context at %p for realm '%s'\n", + __FUNCTION__, plgctx, realmname); + memset(plgctx, 0, sizeof(*plgctx)); + plgctx->magic = PKINIT_CTX_MAGIC; + + plgctx->realmname = strdup(realmname); + if (plgctx->realmname == NULL) + goto errout; + plgctx->realmname_len = strlen(plgctx->realmname); + + retval = pkinit_init_plg_crypto(&plgctx->cryptoctx); + if (retval) + goto errout; + + retval = pkinit_init_plg_opts(&plgctx->opts); + if (retval) + goto errout; + + retval = pkinit_init_identity_crypto(&plgctx->idctx); + if (retval) + goto errout; + + retval = pkinit_init_identity_opts(&plgctx->idopts); + if (retval) + goto errout; + + retval = pkinit_init_kdc_profile(context, plgctx); + if (retval) + goto errout; + + retval = pkinit_identity_initialize(context, plgctx->cryptoctx, NULL, + plgctx->idopts, plgctx->idctx, + NULL, NULL, NULL); + if (retval) + goto errout; + retval = pkinit_identity_prompt(context, plgctx->cryptoctx, NULL, + plgctx->idopts, plgctx->idctx, + NULL, NULL, 0, NULL); + if (retval) + goto errout; + + pkiDebug("%s: returning context at %p for realm '%s'\n", + __FUNCTION__, plgctx, realmname); + *pplgctx = plgctx; + retval = 0; + +errout: + if (retval) + pkinit_server_plugin_fini_realm(context, plgctx); + + return retval; +} + +static krb5_error_code +pkinit_san_authorize(krb5_context context, krb5_certauth_moddata moddata, + const uint8_t *cert, size_t cert_len, + krb5_const_principal princ, const void *opts, + const struct _krb5_db_entry_new *db_entry, + char ***authinds_out) +{ + krb5_error_code ret; + int valid_san; + const struct certauth_req_opts *req_opts = opts; + + *authinds_out = NULL; + + ret = verify_client_san(context, req_opts->plgctx, req_opts->reqctx, + req_opts->cb, req_opts->rock, princ, &valid_san); + if (ret == ENOENT) + return KRB5_PLUGIN_NO_HANDLE; + else if (ret) + return ret; + + if (!valid_san) { + TRACE_PKINIT_SERVER_SAN_REJECT(context); + return KRB5KDC_ERR_CLIENT_NAME_MISMATCH; + } + + return 0; +} + +static krb5_error_code +pkinit_eku_authorize(krb5_context context, krb5_certauth_moddata moddata, + const uint8_t *cert, size_t cert_len, + krb5_const_principal princ, const void *opts, + const struct _krb5_db_entry_new *db_entry, + char ***authinds_out) +{ + krb5_error_code ret; + int valid_eku; + const struct certauth_req_opts *req_opts = opts; + + *authinds_out = NULL; + + /* Verify the client EKU. */ + ret = verify_client_eku(context, req_opts->plgctx, req_opts->reqctx, + &valid_eku); + if (ret) + return ret; + + if (!valid_eku) { + TRACE_PKINIT_SERVER_EKU_REJECT(context); + return KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE; + } + + return KRB5_PLUGIN_NO_HANDLE; +} + +static krb5_error_code +certauth_pkinit_san_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_certauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_certauth_vtable)vtable; + vt->name = "pkinit_san"; + vt->authorize = pkinit_san_authorize; + return 0; +} + +static krb5_error_code +certauth_pkinit_eku_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_certauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_certauth_vtable)vtable; + vt->name = "pkinit_eku"; + vt->authorize = pkinit_eku_authorize; + return 0; +} + +/* + * Do certificate auth based on a match expression in the pkinit_cert_match + * attribute string. An expression should be in the same form as those used + * for the pkinit_cert_match configuration option. + */ +static krb5_error_code +dbmatch_authorize(krb5_context context, krb5_certauth_moddata moddata, + const uint8_t *cert, size_t cert_len, + krb5_const_principal princ, const void *opts, + const struct _krb5_db_entry_new *db_entry, + char ***authinds_out) +{ + krb5_error_code ret; + const struct certauth_req_opts *req_opts = opts; + char *pattern; + krb5_boolean matched; + + *authinds_out = NULL; + + /* Fetch the matching pattern. Pass if it isn't specified. */ + ret = req_opts->cb->get_string(context, req_opts->rock, + "pkinit_cert_match", &pattern); + if (ret) + return ret; + if (pattern == NULL) + return KRB5_PLUGIN_NO_HANDLE; + + /* Check the certificate against the match expression. */ + ret = pkinit_client_cert_match(context, req_opts->plgctx->cryptoctx, + req_opts->reqctx->cryptoctx, pattern, + &matched); + req_opts->cb->free_string(context, req_opts->rock, pattern); + if (ret) + return ret; + return matched ? 0 : KRB5KDC_ERR_CERTIFICATE_MISMATCH; +} + +static krb5_error_code +certauth_dbmatch_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_certauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_certauth_vtable)vtable; + vt->name = "dbmatch"; + vt->authorize = dbmatch_authorize; + return 0; +} + +static krb5_error_code +load_certauth_plugins(krb5_context context, const char *const *realmnames, + certauth_handle **handle_out) +{ + krb5_error_code ret; + krb5_plugin_initvt_fn *modules = NULL, *mod; + certauth_handle *list = NULL, h; + size_t count; + + /* Register the builtin modules. */ + ret = k5_plugin_register(context, PLUGIN_INTERFACE_CERTAUTH, + "pkinit_san", certauth_pkinit_san_initvt); + if (ret) + goto cleanup; + + ret = k5_plugin_register(context, PLUGIN_INTERFACE_CERTAUTH, + "pkinit_eku", certauth_pkinit_eku_initvt); + if (ret) + goto cleanup; + + ret = k5_plugin_register(context, PLUGIN_INTERFACE_CERTAUTH, "dbmatch", + certauth_dbmatch_initvt); + if (ret) + goto cleanup; + + ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_CERTAUTH, &modules); + if (ret) + goto cleanup; + + /* Allocate handle list. */ + for (count = 0; modules[count]; count++); + list = k5calloc(count + 1, sizeof(*list), &ret); + if (list == NULL) + goto cleanup; + + /* Initialize each module, ignoring ones that fail. */ + count = 0; + for (mod = modules; *mod != NULL; mod++) { + h = k5calloc(1, sizeof(*h), &ret); + if (h == NULL) + goto cleanup; + + ret = (*mod)(context, 1, 2, (krb5_plugin_vtable)&h->vt); + if (ret) { + TRACE_CERTAUTH_VTINIT_FAIL(context, ret); + free(h); + continue; + } + h->moddata = NULL; + if (h->vt.init_ex != NULL) + ret = h->vt.init_ex(context, realmnames, &h->moddata); + else if (h->vt.init != NULL) + ret = h->vt.init(context, &h->moddata); + if (ret) { + TRACE_CERTAUTH_INIT_FAIL(context, h->vt.name, ret); + free(h); + continue; + } + list[count++] = h; + list[count] = NULL; + } + list[count] = NULL; + + ret = 0; + *handle_out = list; + list = NULL; + +cleanup: + k5_plugin_free_modules(context, modules); + free_certauth_handles(context, list); + return ret; +} + +static int +pkinit_server_plugin_init(krb5_context context, + krb5_kdcpreauth_moddata *moddata_out, + const char **realmnames) +{ + krb5_error_code retval = ENOMEM; + pkinit_kdc_context plgctx, *realm_contexts = NULL; + certauth_handle *certauth_modules = NULL; + krb5_kdcpreauth_moddata moddata; + size_t i, j; + size_t numrealms; + + retval = pkinit_accessor_init(); + if (retval) + return retval; + + /* Determine how many realms we may need to support */ + for (i = 0; realmnames[i] != NULL; i++) {}; + numrealms = i; + + realm_contexts = calloc(numrealms+1, sizeof(pkinit_kdc_context)); + if (realm_contexts == NULL) + return ENOMEM; + + for (i = 0, j = 0; i < numrealms; i++) { + TRACE_PKINIT_SERVER_INIT_REALM(context, realmnames[i]); + krb5_clear_error_message(context); + retval = pkinit_server_plugin_init_realm(context, realmnames[i], + &plgctx); + if (retval) + TRACE_PKINIT_SERVER_INIT_FAIL(context, realmnames[i], retval); + else + realm_contexts[j++] = plgctx; + } + + if (j == 0) { + if (numrealms == 1) { + k5_prependmsg(context, retval, "PKINIT initialization failed"); + } else { + retval = EINVAL; + k5_setmsg(context, retval, + _("No realms configured correctly for pkinit support")); + } + goto errout; + } + + retval = load_certauth_plugins(context, realmnames, &certauth_modules); + if (retval) + goto errout; + + moddata = k5calloc(1, sizeof(*moddata), &retval); + if (moddata == NULL) + goto errout; + moddata->realm_contexts = realm_contexts; + moddata->certauth_modules = certauth_modules; + *moddata_out = moddata; + pkiDebug("%s: returning context at %p\n", __FUNCTION__, moddata); + return 0; + +errout: + free_realm_contexts(context, realm_contexts); + free_certauth_handles(context, certauth_modules); + return retval; +} + +static void +pkinit_server_plugin_fini_realm(krb5_context context, pkinit_kdc_context plgctx) +{ + char **sp; + + if (plgctx == NULL) + return; + + pkinit_fini_kdc_profile(context, plgctx); + pkinit_fini_identity_opts(plgctx->idopts); + pkinit_fini_identity_crypto(plgctx->idctx); + pkinit_fini_plg_crypto(plgctx->cryptoctx); + pkinit_fini_plg_opts(plgctx->opts); + for (sp = plgctx->auth_indicators; sp != NULL && *sp != NULL; sp++) + free(*sp); + free(plgctx->auth_indicators); + free(plgctx->realmname); + free(plgctx); +} + +static void +pkinit_server_plugin_fini(krb5_context context, + krb5_kdcpreauth_moddata moddata) +{ + if (moddata == NULL) + return; + free_realm_contexts(context, moddata->realm_contexts); + free_certauth_handles(context, moddata->certauth_modules); + free(moddata); +} + +static krb5_error_code +pkinit_init_kdc_req_context(krb5_context context, pkinit_kdc_req_context *ctx) +{ + krb5_error_code retval = ENOMEM; + pkinit_kdc_req_context reqctx = NULL; + + reqctx = malloc(sizeof(*reqctx)); + if (reqctx == NULL) + return retval; + memset(reqctx, 0, sizeof(*reqctx)); + reqctx->magic = PKINIT_CTX_MAGIC; + + retval = pkinit_init_req_crypto(&reqctx->cryptoctx); + if (retval) + goto cleanup; + reqctx->rcv_auth_pack = NULL; + + pkiDebug("%s: returning reqctx at %p\n", __FUNCTION__, reqctx); + *ctx = reqctx; + retval = 0; +cleanup: + if (retval) + pkinit_fini_kdc_req_context(context, reqctx); + + return retval; +} + +static void +pkinit_fini_kdc_req_context(krb5_context context, void *ctx) +{ + pkinit_kdc_req_context reqctx = (pkinit_kdc_req_context)ctx; + + if (reqctx == NULL || reqctx->magic != PKINIT_CTX_MAGIC) { + pkiDebug("pkinit_fini_kdc_req_context: got bad reqctx (%p)!\n", reqctx); + return; + } + pkiDebug("%s: freeing reqctx at %p\n", __FUNCTION__, reqctx); + + pkinit_fini_req_crypto(reqctx->cryptoctx); + if (reqctx->rcv_auth_pack != NULL) + free_krb5_auth_pack(&reqctx->rcv_auth_pack); + + free(reqctx); +} + +static void +pkinit_free_modreq(krb5_context context, krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_modreq modreq) +{ + pkinit_fini_kdc_req_context(context, modreq); +} + +krb5_error_code +kdcpreauth_pkinit_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +kdcpreauth_pkinit_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_kdcpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "pkinit"; + vt->pa_type_list = supported_server_pa_types; + vt->init = pkinit_server_plugin_init; + vt->fini = pkinit_server_plugin_fini; + vt->flags = pkinit_server_get_flags; + vt->edata = pkinit_server_get_edata; + vt->verify = pkinit_server_verify_padata; + vt->return_padata = pkinit_server_return_padata; + vt->free_modreq = pkinit_free_modreq; + return 0; +} diff --git a/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_trace.h b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_trace.h new file mode 100644 index 00000000..259e95c6 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/pkinit/pkinit_trace.h @@ -0,0 +1,214 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/pkinit/pkinit_trace.h - PKINIT tracing macros */ +/* + * Copyright (C) 2012 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. + */ + +#ifndef PKINIT_TRACE_H +#define PKINIT_TRACE_H + +#include "k5-trace.h" + +#define TRACE_PKINIT_CLIENT_EKU_ACCEPT(c) \ + TRACE(c, "PKINIT client found acceptable EKU in KDC cert") +#define TRACE_PKINIT_CLIENT_EKU_REJECT(c) \ + TRACE(c, "PKINIT client found no acceptable EKU in KDC cert") +#define TRACE_PKINIT_CLIENT_EKU_SKIP(c) \ + TRACE(c, "PKINIT client skipping EKU check due to configuration") +#define TRACE_PKINIT_CLIENT_FRESHNESS_TOKEN(c) \ + TRACE(c, "PKINIT client received freshness token from KDC") +#define TRACE_PKINIT_CLIENT_KDF_ALG(c, kdf, keyblock) \ + TRACE(c, "PKINIT client used KDF {hexdata} to compute reply key " \ + "{keyblock}", kdf, keyblock) +#define TRACE_PKINIT_CLIENT_KDF_OS2K(c, keyblock) \ + TRACE(c, "PKINIT client used octetstring2key to compute reply key " \ + "{keyblock}", keyblock) +#define TRACE_PKINIT_CLIENT_NO_IDENTITY(c) \ + TRACE(c, "PKINIT client has no configured identity; giving up") +#define TRACE_PKINIT_CLIENT_REP_CHECKSUM_FAIL(c, expected, received) \ + TRACE(c, "PKINIT client checksum mismatch: expected {cksum}, " \ + "received {cksum}", expected, received) +#define TRACE_PKINIT_CLIENT_REP_DH(c) \ + TRACE(c, "PKINIT client verified DH reply") +#define TRACE_PKINIT_CLIENT_REP_DH_FAIL(c) \ + TRACE(c, "PKINIT client could not verify DH reply") +#define TRACE_PKINIT_CLIENT_REP_RSA(c) \ + TRACE(c, "PKINIT client verified RSA reply") +#define TRACE_PKINIT_CLIENT_REP_RSA_KEY(c, keyblock, cksum) \ + TRACE(c, "PKINIT client retrieved reply key {keyblock} from RSA " \ + "reply (checksum {cksum})", keyblock, cksum) +#define TRACE_PKINIT_CLIENT_REP_RSA_FAIL(c) \ + TRACE(c, "PKINIT client could not verify RSA reply") +#define TRACE_PKINIT_CLIENT_REQ_CHECKSUM(c, cksum) \ + TRACE(c, "PKINIT client computed kdc-req-body checksum {cksum}", cksum) +#define TRACE_PKINIT_CLIENT_REQ_DH(c) \ + TRACE(c, "PKINIT client making DH request") +#define TRACE_PKINIT_CLIENT_REQ_RSA(c) \ + TRACE(c, "PKINIT client making RSA request") +#define TRACE_PKINIT_CLIENT_SAN_CONFIG_DNSNAME(c, host) \ + TRACE(c, "PKINIT client config accepts KDC dNSName SAN {str}", host) +#define TRACE_PKINIT_CLIENT_SAN_MATCH_DNSNAME(c, host) \ + TRACE(c, "PKINIT client matched KDC hostname {str} against " \ + "dNSName SAN; EKU check still required", host) +#define TRACE_PKINIT_CLIENT_SAN_MATCH_NONE(c) \ + TRACE(c, "PKINIT client found no acceptable SAN in KDC cert") +#define TRACE_PKINIT_CLIENT_SAN_MATCH_PRINC(c, princ) \ + TRACE(c, "PKINIT client matched KDC principal {princ} against " \ + "id-pkinit-san; no EKU check required", princ) +#define TRACE_PKINIT_CLIENT_SAN_ERR(c) \ + TRACE(c, "PKINIT client failed to decode SANs in KDC cert") +#define TRACE_PKINIT_CLIENT_SAN_KDCCERT_DNSNAME(c, host) \ + TRACE(c, "PKINIT client found dNSName SAN in KDC cert: {str}", host) +#define TRACE_PKINIT_CLIENT_SAN_KDCCERT_PRINC(c, princ) \ + TRACE(c, "PKINIT client found id-pkinit-san in KDC cert: {princ}", princ) +#define TRACE_PKINIT_CLIENT_TRYAGAIN(c) \ + TRACE(c, "PKINIT client trying again with KDC-provided parameters") + +#define TRACE_PKINIT_OPENSSL_ERROR(c, msg) \ + TRACE(c, "PKINIT OpenSSL error: {str}", msg) + +#define TRACE_PKINIT_PKCS11_GETFLIST_FAILED(c, errstr) \ + TRACE(c, "PKINIT PKCS11 C_GetFunctionList failed: {str}", errstr) +#define TRACE_PKINIT_PKCS11_GETSYM_FAILED(c, errstr) \ + TRACE(c, "PKINIT unable to find PKCS11 plugin symbol " \ + "C_GetFunctionList: {str}", errstr) +#define TRACE_PKINIT_PKCS11_LOGIN_FAILED(c, errstr) \ + TRACE(c, "PKINIT PKCS11 C_Login failed: {str}", errstr) +#define TRACE_PKINIT_PKCS11_NO_MATCH_TOKEN(c) \ + TRACE(c, "PKINIT PKCS#11 module has no matching tokens") +#define TRACE_PKINIT_PKCS11_NO_TOKEN(c) \ + TRACE(c, "PKINIT PKCS#11 module shows no slots with tokens") +#define TRACE_PKINIT_PKCS11_OPEN(c, name) \ + TRACE(c, "PKINIT opening PKCS#11 module \"{str}\"", name) +#define TRACE_PKINIT_PKCS11_OPEN_FAILED(c, errstr) \ + TRACE(c, "PKINIT PKCS#11 module open failed: {str}", errstr) +#define TRACE_PKINIT_PKCS11_SLOT(c, slot, len, label) \ + TRACE(c, "PKINIT PKCS#11 slotid {int} token {lenstr}", \ + slot, len, label) + +#define TRACE_PKINIT_SERVER_CERT_AUTH(c, modname) \ + TRACE(c, "PKINIT server authorizing cert with module {str}", \ + modname) +#define TRACE_PKINIT_SERVER_EKU_REJECT(c) \ + TRACE(c, "PKINIT server found no acceptable EKU in client cert") +#define TRACE_PKINIT_SERVER_EKU_SKIP(c) \ + TRACE(c, "PKINIT server skipping EKU check due to configuration") +#define TRACE_PKINIT_SERVER_INIT_REALM(c, realm) \ + TRACE(c, "PKINIT server initializing realm {str}", realm) +#define TRACE_PKINIT_SERVER_INIT_FAIL(c, realm, retval) \ + TRACE(c, "PKINIT server initialization failed for realm {str}: {kerr}", \ + realm, retval) +#define TRACE_PKINIT_SERVER_MATCHING_UPN_FOUND(c) \ + TRACE(c, "PKINIT server found a matching UPN SAN in client cert") +#define TRACE_PKINIT_SERVER_MATCHING_SAN_FOUND(c) \ + TRACE(c, "PKINIT server found a matching SAN in client cert") +#define TRACE_PKINIT_SERVER_NO_SAN(c) \ + TRACE(c, "PKINIT server found no SAN in client cert") +#define TRACE_PKINIT_SERVER_PADATA_VERIFY(c) \ + TRACE(c, "PKINIT server verifying KRB5_PADATA_PK_AS_REQ") +#define TRACE_PKINIT_SERVER_PADATA_VERIFY_FAIL(c) \ + TRACE(c, "PKINIT server failed to verify PA data") +#define TRACE_PKINIT_SERVER_RETURN_PADATA(c) \ + TRACE(c, "PKINIT server returning PA data") +#define TRACE_PKINIT_SERVER_SAN_REJECT(c) \ + TRACE(c, "PKINIT server found no acceptable SAN in client cert") +#define TRACE_PKINIT_SERVER_UPN_PARSE_FAIL(c, upn, ret) \ + TRACE(c, "PKINIT server could not parse UPN \"{str}\": {kerr}", \ + upn, ret) + +#define TRACE_PKINIT_CERT_CHAIN_NAME(c, index, name) \ + TRACE(c, "PKINIT chain cert #{int}: {str}", index, name) +#define TRACE_PKINIT_CERT_NUM_MATCHING(c, total, nummatch) \ + TRACE(c, "PKINIT client checked {int} certs, found {int} matches", \ + total, nummatch) +#define TRACE_PKINIT_CERT_RULE(c, rule) \ + TRACE(c, "PKINIT client matching rule '{str}' against certificates", rule) +#define TRACE_PKINIT_CERT_RULE_INVALID(c, rule) \ + TRACE(c, "PKINIT client ignoring invalid rule '{str}'", rule) + +#define TRACE_PKINIT_EKU(c) \ + TRACE(c, "PKINIT found acceptable EKU and digitalSignature KU") +#define TRACE_PKINIT_EKU_NO_KU(c) \ + TRACE(c, "PKINIT found acceptable EKU but no digitalSignature KU") +#define TRACE_PKINIT_IDENTITY_OPTION(c, name) \ + TRACE(c, "PKINIT loading identity {str}", name) +#define TRACE_PKINIT_LOADED_CERT(c, name) \ + TRACE(c, "PKINIT loaded cert and key for {str}", name) +#define TRACE_PKINIT_LOAD_FROM_FILE(c, name) \ + TRACE(c, "PKINIT loading CA certs and CRLs from FILE {str}", name) +#define TRACE_PKINIT_LOAD_FROM_DIR(c, name) \ + TRACE(c, "PKINIT loading CA certs and CRLs from DIR {str}", name) +#define TRACE_PKINIT_NO_CA_ANCHOR(c, file) \ + TRACE(c, "PKINIT no anchor CA in file {str}", file) +#define TRACE_PKINIT_NO_CA_INTERMEDIATE(c, file) \ + TRACE(c, "PKINIT no intermediate CA in file {str}", file) +#define TRACE_PKINIT_NO_CERT(c) \ + TRACE(c, "PKINIT no certificate provided") +#define TRACE_PKINIT_NO_CERT_AND_KEY(c, dirname) \ + TRACE(c, "PKINIT no cert and key pair found in directory {str}", \ + dirname) +#define TRACE_PKINIT_NO_CRL(c, file) \ + TRACE(c, "PKINIT no CRL in file {str}", file) +#define TRACE_PKINIT_NO_DEFAULT_CERT(c, count) \ + TRACE(c, "PKINIT error: There are {int} certs, but there must " \ + "be exactly one.", count) +#define TRACE_PKINIT_NO_MATCHING_CERT(c) \ + TRACE(c, "PKINIT no matching certificate found") +#define TRACE_PKINIT_NO_PRIVKEY(c) \ + TRACE(c, "PKINIT no private key provided") +#define TRACE_PKINIT_PKCS_DECODE_FAIL(c, name) \ + TRACE(c, "PKINIT failed to decode PKCS12 file {str} contents", name) +#define TRACE_PKINIT_PKCS_OPEN_FAIL(c, name, err) \ + TRACE(c, "PKINIT failed to open PKCS12 file {str}: err {errno}", \ + name, err) +#define TRACE_PKINIT_PKCS_PARSE_FAIL_FIRST(c) \ + TRACE(c, "PKINIT initial PKCS12_parse with no password failed") +#define TRACE_PKINIT_PKCS_PARSE_FAIL_SECOND(c) \ + TRACE(c, "PKINIT second PKCS12_parse with password failed") +#define TRACE_PKINIT_PKCS_PROMPT_FAIL(c) \ + TRACE(c, "PKINIT failed to prompt for PKCS12 password") +#define TRACE_PKINIT_REGEXP_MATCH(c, keyword, comp, value, idx) \ + TRACE(c, "PKINIT matched {str} rule '{str}' with " \ + "value '{str}' in cert #{int}", keyword, comp, value, (idx) + 1) +#define TRACE_PKINIT_REGEXP_NOMATCH(c, keyword, comp, value, idx) \ + TRACE(c, "PKINIT didn't match {str} rule '{str}' with " \ + "value '{str}' in cert #{int}", keyword, comp, value, (idx) + 1) +#define TRACE_PKINIT_SAN_CERT_COUNT(c, count, princ, upns, dns, cert) \ + TRACE(c, "PKINIT client found {int} SANs ({int} princs, {int} " \ + "UPNs, {int} DNS names) in certificate {str}", count, princ, \ + upns, dns, cert) +#define TRACE_PKINIT_SAN_CERT_NONE(c, cert) \ + TRACE(c, "PKINIT client found no SANs in certificate {str}", cert) + +#define TRACE_CERTAUTH_VTINIT_FAIL(c, ret) \ + TRACE(c, "certauth module failed to init vtable: {kerr}", ret) +#define TRACE_CERTAUTH_INIT_FAIL(c, name, ret) \ + TRACE(c, "certauth module {str} failed to init: {kerr}", name, ret) + +#endif /* PKINIT_TRACE_H */ diff --git a/krb5-1.21.3/src/plugins/preauth/securid_sam2/Makefile.in b/krb5-1.21.3/src/plugins/preauth/securid_sam2/Makefile.in new file mode 100644 index 00000000..af34c15a --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/securid_sam2/Makefile.in @@ -0,0 +1,27 @@ +mydir=plugins$(S)preauth$(S)securid_sam2 +BUILDTOP=$(REL)..$(S)..$(S).. +MODULE_INSTALL_DIR = $(KRB5_PA_MODULE_DIR) +DEFINES=-DARL_SECURID_PREAUTH + +LIBBASE=securid_sam2 +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/preauth/securid_sam2 +# Depends on libk5crypto and libkrb5 +SHLIB_EXPDEPS = \ + $(TOPLIBD)/libk5crypto$(SHLIBEXT) \ + $(TOPLIBD)/libkrb5$(SHLIBEXT) $(KADMSRV_DEPLIBS) +ACELIB= -laceclnt +SHLIB_EXPLIBS= -lkrb5 $(COM_ERR_LIB) -lk5crypto $(SUPPORT_LIB) \ + $(KADMSRV_LIBS) $(LIBS) $(ACELIB) + +STLIBOBJS=securid_sam2_main.o securid2.o grail.o + +SRCS= $(srcdir)/securid_sam2_main.c $(srcdir)/securid2.c $(srcdir)/grail.c + +all-unix: all-libs +install-unix: install-libs +clean-unix:: clean-libs clean-libobjs + +@libnover_frag@ +@libobj_frag@ diff --git a/krb5-1.21.3/src/plugins/preauth/securid_sam2/README b/krb5-1.21.3/src/plugins/preauth/securid_sam2/README new file mode 100644 index 00000000..8fc10284 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/securid_sam2/README @@ -0,0 +1,17 @@ +SecurID Preauth Support + +In order to build this library you will need the RSA 's ACE Agent +SDK. Set the LDFLAGS and CPPFLAGS environment variables to include the +appropriate paths for your SDK before running configure. If libaceclnt +is found then the plugin will be enabled. +For example: + +../src/configure CC='gcc -m32' CFLAGS=-g --prefix=/usr/local/krb5 \ + --disable-rpath LDFLAGS=-L/home/developer/ace/ACEAgentSDK/lib/lnx \ + CPPFLAGS=-I/home/developer/ace/ACEAgentSDK/inc + + +Once the plugin is installed, set the requires_preauth and potentially +requires_hwauth flags for a principal. Then create principal/SECURID +as a new principal with a random key. That principal will now require +SecurID authentication. diff --git a/krb5-1.21.3/src/plugins/preauth/securid_sam2/deps b/krb5-1.21.3/src/plugins/preauth/securid_sam2/deps new file mode 100644 index 00000000..e69de29b diff --git a/krb5-1.21.3/src/plugins/preauth/securid_sam2/extern.h b/krb5-1.21.3/src/plugins/preauth/securid_sam2/extern.h new file mode 100644 index 00000000..c8c76dd0 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/securid_sam2/extern.h @@ -0,0 +1,60 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/securid_sam2/extern.h */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * Declarations for SecurID SAM2 plugin. + */ + +krb5_error_code sam_get_db_entry(krb5_context , krb5_principal, + int *, krb5_db_entry **); + +krb5_error_code sam_make_challenge(krb5_context context, + krb5_sam_challenge_2_body *sc2b, + krb5_keyblock *cksum_key, + krb5_sam_challenge_2 *sc2_out); + +krb5_error_code get_securid_edata_2(krb5_context context, + krb5_db_entry *client, + krb5_keyblock *client_key, + krb5_sam_challenge_2 *sc2); + +krb5_error_code verify_securid_data_2(krb5_context context, + krb5_db_entry *client, + krb5_sam_response_2 *sr2, + krb5_enc_tkt_part *enc_tkt_reply, + krb5_pa_data *pa, + krb5_sam_challenge_2 **sc2_out); + +krb5_error_code get_grail_edata(krb5_context context, krb5_db_entry *client, + krb5_keyblock *client_key, + krb5_sam_challenge_2 *sc2_out); + +krb5_error_code verify_grail_data(krb5_context context, krb5_db_entry *client, + krb5_sam_response_2 *sr2, + krb5_enc_tkt_part *enc_tkt_reply, + krb5_pa_data *pa, + krb5_sam_challenge_2 **sc2_out); diff --git a/krb5-1.21.3/src/plugins/preauth/securid_sam2/grail.c b/krb5-1.21.3/src/plugins/preauth/securid_sam2/grail.c new file mode 100644 index 00000000..48b61b0d --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/securid_sam2/grail.c @@ -0,0 +1,272 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/securid_sam2/grail.c - Test method for SAM-2 preauth */ +/* + * Copyright (C) 2012 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. + */ + +/* + * This test method exists to exercise the client SAM-2 code and some of the + * KDC SAM-2 code. We make up a weakly random number and presents it to the + * client in the prompt (in plain text), as well as encrypted in the track ID. + * To verify, we compare the decrypted track ID to the entered value. + * + * Do not use this method in production; it is not secure. + */ + +#ifdef GRAIL_PREAUTH + +#include "k5-int.h" +#include +#include +#include +#include "extern.h" + +static krb5_error_code +get_grail_key(krb5_context context, krb5_db_entry *client, + krb5_keyblock *key_out) +{ + krb5_db_entry *grail_entry = NULL; + krb5_key_data *kd; + int sam_type = PA_SAM_TYPE_GRAIL; + krb5_error_code ret = 0; + + ret = sam_get_db_entry(context, client->princ, &sam_type, &grail_entry); + if (ret) + return KRB5_PREAUTH_NO_KEY; + ret = krb5_dbe_find_enctype(context, grail_entry, -1, -1, -1, &kd); + if (ret) + goto cleanup; + ret = krb5_dbe_decrypt_key_data(context, NULL, kd, key_out, NULL); + if (ret) + goto cleanup; + +cleanup: + if (grail_entry) + krb5_db_free_principal(context, grail_entry); + return ret; +} + +static krb5_error_code +decrypt_track_data(krb5_context context, krb5_db_entry *client, + krb5_data *enc_track_data, krb5_data *output) +{ + krb5_error_code ret; + krb5_keyblock sam_key; + krb5_enc_data enc; + krb5_data result = empty_data(); + + sam_key.contents = NULL; + *output = empty_data(); + + ret = get_grail_key(context, client, &sam_key); + if (ret != 0) + return ret; + enc.ciphertext = *enc_track_data; + enc.enctype = ENCTYPE_UNKNOWN; + enc.kvno = 0; + ret = alloc_data(&result, enc_track_data->length); + if (ret) + goto cleanup; + ret = krb5_c_decrypt(context, &sam_key, + KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID, 0, &enc, + &result); + if (ret) + goto cleanup; + + *output = result; + result = empty_data(); + +cleanup: + krb5_free_keyblock_contents(context, &sam_key); + krb5_free_data_contents(context, &result); + return ret; +} + +static krb5_error_code +encrypt_track_data(krb5_context context, krb5_db_entry *client, + krb5_data *track_data, krb5_data *output) +{ + krb5_error_code ret; + size_t olen; + krb5_keyblock sam_key; + krb5_enc_data enc; + + *output = empty_data(); + enc.ciphertext = empty_data(); + sam_key.contents = NULL; + + ret = get_grail_key(context, client, &sam_key); + if (ret != 0) + return ret; + + ret = krb5_c_encrypt_length(context, sam_key.enctype, + track_data->length, &olen); + if (ret != 0) + goto cleanup; + assert(olen <= 65536); + ret = alloc_data(&enc.ciphertext, olen); + if (ret) + goto cleanup; + enc.enctype = sam_key.enctype; + enc.kvno = 0; + + ret = krb5_c_encrypt(context, &sam_key, + KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID, 0, + track_data, &enc); + if (ret) + goto cleanup; + + *output = enc.ciphertext; + enc.ciphertext = empty_data(); + +cleanup: + krb5_free_keyblock_contents(context, &sam_key); + krb5_free_data_contents(context, &enc.ciphertext); + return ret; +} + +krb5_error_code +get_grail_edata(krb5_context context, krb5_db_entry *client, + krb5_keyblock *client_key, krb5_sam_challenge_2 *sc2_out) +{ + krb5_error_code ret; + krb5_data tmp_data, track_id = empty_data(); + int tval = time(NULL) % 77777; + krb5_sam_challenge_2_body sc2b; + char tval_string[256], prompt[256]; + + snprintf(tval_string, sizeof(tval_string), "%d", tval); + snprintf(prompt, sizeof(prompt), "Enter %d", tval); + + memset(&sc2b, 0, sizeof(sc2b)); + sc2b.magic = KV5M_SAM_CHALLENGE_2; + sc2b.sam_track_id = empty_data(); + sc2b.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD; + sc2b.sam_type_name = empty_data(); + sc2b.sam_challenge_label = empty_data(); + sc2b.sam_challenge = empty_data(); + sc2b.sam_response_prompt = string2data(prompt); + sc2b.sam_pk_for_sad = empty_data(); + sc2b.sam_type = PA_SAM_TYPE_GRAIL; + sc2b.sam_etype = client_key->enctype; + + tmp_data = string2data(tval_string); + ret = encrypt_track_data(context, client, &tmp_data, &track_id); + if (ret) + goto cleanup; + sc2b.sam_track_id = track_id; + + tmp_data = make_data(&sc2b.sam_nonce, sizeof(sc2b.sam_nonce)); + ret = krb5_c_random_make_octets(context, &tmp_data); + if (ret) + goto cleanup; + + ret = sam_make_challenge(context, &sc2b, client_key, sc2_out); + +cleanup: + krb5_free_data_contents(context, &track_id); + return ret; +} + +krb5_error_code +verify_grail_data(krb5_context context, krb5_db_entry *client, + krb5_sam_response_2 *sr2, krb5_enc_tkt_part *enc_tkt_reply, + krb5_pa_data *pa, krb5_sam_challenge_2 **sc2_out) +{ + krb5_error_code ret; + krb5_key_data *client_key_data = NULL; + krb5_keyblock client_key; + krb5_data scratch = empty_data(), track_id_data = empty_data(); + krb5_enc_sam_response_enc_2 *esre2 = NULL; + + *sc2_out = NULL; + memset(&client_key, 0, sizeof(client_key)); + + if ((sr2->sam_enc_nonce_or_sad.ciphertext.data == NULL) || + (sr2->sam_enc_nonce_or_sad.ciphertext.length <= 0)) + return KRB5KDC_ERR_PREAUTH_FAILED; + + ret = krb5_dbe_find_enctype(context, client, + sr2->sam_enc_nonce_or_sad.enctype, -1, + sr2->sam_enc_nonce_or_sad.kvno, + &client_key_data); + if (ret) + goto cleanup; + + ret = krb5_dbe_decrypt_key_data(context, NULL, client_key_data, + &client_key, NULL); + if (ret) + goto cleanup; + ret = alloc_data(&scratch, sr2->sam_enc_nonce_or_sad.ciphertext.length); + if (ret) + goto cleanup; + ret = krb5_c_decrypt(context, &client_key, KRB5_KEYUSAGE_PA_SAM_RESPONSE, + NULL, &sr2->sam_enc_nonce_or_sad, &scratch); + if (ret) + goto cleanup; + + ret = decode_krb5_enc_sam_response_enc_2(&scratch, &esre2); + if (ret) + goto cleanup; + + if (sr2->sam_nonce != esre2->sam_nonce) { + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + if (esre2->sam_sad.length == 0 || esre2->sam_sad.data == NULL) { + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + ret = decrypt_track_data(context, client, &sr2->sam_track_id, + &track_id_data); + if (ret) + goto cleanup; + + /* Some enctypes aren't length-preserving; try to work anyway. */ + while (track_id_data.length > 0 && + !isdigit(track_id_data.data[track_id_data.length - 1])) + track_id_data.length--; + + if (!data_eq(track_id_data, esre2->sam_sad)) { + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + enc_tkt_reply->flags |= (TKT_FLG_HW_AUTH | TKT_FLG_PRE_AUTH); + +cleanup: + krb5_free_keyblock_contents(context, &client_key); + krb5_free_data_contents(context, &scratch); + krb5_free_enc_sam_response_enc_2(context, esre2); + return ret; +} + +#endif /* GRAIL_PREAUTH */ diff --git a/krb5-1.21.3/src/plugins/preauth/securid_sam2/securid2.c b/krb5-1.21.3/src/plugins/preauth/securid_sam2/securid2.c new file mode 100644 index 00000000..ef7a8bfc --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/securid_sam2/securid2.c @@ -0,0 +1,669 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/securid_sam2/securid2.c */ +/* + * Copyright (C) 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (c) 2002 Naval Research Laboratory (NRL/CCS) + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the software, + * derivative works or modified versions, and any portions thereof. + * + * NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND + * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER + * RESULTING FROM THE USE OF THIS SOFTWARE. + */ + +#ifdef ARL_SECURID_PREAUTH + +#include "k5-int.h" +#include +#include +#include +#include +#include +#include +#include +#include "extern.h" + +#define KRB5_SAM_SECURID_NEXT_CHALLENGE_MAGIC 0x5ec1d000 +struct securid_track_data { + SDI_HANDLE handle; + char state; + char passcode[LENPRNST+1]; + long hostid; +}; + +#define SECURID_STATE_NEW_PIN 1 /* Ask for a new pin */ +#define SECURID_STATE_NEW_PIN_AGAIN 2 /* Ask for new pin again */ +#define SECURID_STATE_NEXT_CODE 3 /* Ask for the next pin code */ +#define SECURID_STATE_INITIAL 4 + +static char *PASSCODE_message = "SecurID Passcode"; +static char *NEXT_PASSCODE_message = "Next Passcode"; +static char *NEW_PIN_AGAIN_message = "New PIN Again"; +static char PIN_message[64]; /* Max length should be 50 chars */ + +/* + * krb5_error_code get_securid_key(): + * inputs: context: from KDC process + * client: database entry of client executing + * SecurID SAM preauthentication + * outputs: client_securid_key: pointer to krb5_keyblock + * which is key for the client's SecurID + * database entry. + * returns: 0 on success + * KRB5 error codes otherwise + * + * builds principal name with final instance of "SECURID" and + * finds the database entry, decrypts the key out of the database + * and passes the key back to the calling process + */ + +static krb5_error_code +get_securid_key(krb5_context context, krb5_db_entry *client, + krb5_keyblock *client_securid_key) +{ + krb5_db_entry *sam_securid_entry = NULL; + krb5_key_data *client_securid_key_data = NULL; + int sam_type = PA_SAM_TYPE_SECURID; + krb5_error_code retval = 0; + + if (!client_securid_key) + return KRB5_PREAUTH_NO_KEY; + + retval = sam_get_db_entry(context, client->princ, + &sam_type, &sam_securid_entry); + if (retval) + return KRB5_PREAUTH_NO_KEY; + + /* Find key with key_type = salt_type = kvno = -1. This finds the */ + /* latest kvno in the list. */ + + retval = krb5_dbe_find_enctype(context, sam_securid_entry, + -1, -1, -1, &client_securid_key_data); + if (retval) { + com_err("krb5kdc", retval, + "while getting key from client's SAM SecurID entry"); + goto cleanup; + } + retval = krb5_dbe_decrypt_key_data(context, NULL, client_securid_key_data, + client_securid_key, NULL); + if (retval) { + com_err("krb5kdc", retval, + "while decrypting key from client's SAM SecurID entry"); + goto cleanup; + } +cleanup: + if (sam_securid_entry) + krb5_db_free_principal(context, sam_securid_entry); + return retval; +} + +static krb5_error_code +securid_decrypt_track_data_2(krb5_context context, krb5_db_entry *client, + krb5_data *enc_track_data, krb5_data *output) +{ + krb5_error_code retval; + krb5_keyblock sam_key; + krb5_enc_data tmp_enc_data; + sam_key.contents = NULL; + + retval = get_securid_key(context, client, &sam_key); + if (retval != 0) + return retval; + + tmp_enc_data.ciphertext = *enc_track_data; + tmp_enc_data.enctype = ENCTYPE_UNKNOWN; + tmp_enc_data.kvno = 0; + + output->length = tmp_enc_data.ciphertext.length; + free(output->data); + output->data = k5alloc(output->length, &retval); + if (output->data == NULL) + goto cleanup; + retval = krb5_c_decrypt(context, &sam_key, + KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID, 0, + &tmp_enc_data, output); +cleanup: + krb5_free_keyblock_contents(context, &sam_key); + + if (retval) { + output->length = 0; + free(output->data); + output->data = NULL; + return retval; + } + + return 0; +} + +static krb5_error_code +securid_encrypt_track_data_2(krb5_context context, krb5_db_entry *client, + krb5_data *track_data, krb5_data *output) +{ + krb5_error_code retval; + size_t olen; + krb5_keyblock sam_key; + krb5_enc_data tmp_enc_data; + + output->data = NULL; + + retval = get_securid_key(context,client, &sam_key); + if (retval != 0) + return retval; + + retval = krb5_c_encrypt_length(context, sam_key.enctype, + track_data->length, &olen); + if (retval != 0) + goto cleanup; + assert(olen <= 65536); + output->length = olen; + output->data = k5alloc(output->length, &retval); + if (retval) + goto cleanup; + tmp_enc_data.ciphertext = *output; + tmp_enc_data.enctype = sam_key.enctype; + tmp_enc_data.kvno = 0; + + retval = krb5_c_encrypt(context, &sam_key, + KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID, 0, + track_data, &tmp_enc_data); +cleanup: + krb5_free_keyblock_contents(context, &sam_key); + + if (retval) { + output->length = 0; + free(output->data); + output->data = NULL; + return retval; + } + return 0; +} + + +krb5_error_code +get_securid_edata_2(krb5_context context, krb5_db_entry *client, + krb5_keyblock *client_key, krb5_sam_challenge_2 *sc2) +{ + krb5_error_code retval; + krb5_data scratch, track_id = empty_data(); + char *user = NULL; + char *def_user = ""; + struct securid_track_data sid_track_data; + krb5_data tmp_data; + krb5_sam_challenge_2_body sc2b; + + scratch.data = NULL; + + retval = krb5_unparse_name(context, client->princ, &user); + if (retval) + goto cleanup; + + memset(&sc2b, 0, sizeof(sc2b)); + sc2b.magic = KV5M_SAM_CHALLENGE_2; + sc2b.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD; + sc2b.sam_type_name.length = 0; + sc2b.sam_challenge_label.length = 0; + sc2b.sam_challenge.length = 0; + sc2b.sam_response_prompt.data = PASSCODE_message; + sc2b.sam_response_prompt.length = strlen(sc2b.sam_response_prompt.data); + sc2b.sam_pk_for_sad.length = 0; + sc2b.sam_type = PA_SAM_TYPE_SECURID; + + sid_track_data.state = SECURID_STATE_INITIAL; + sid_track_data.hostid = gethostid(); + tmp_data.data = (char *)&sid_track_data; + tmp_data.length = sizeof(sid_track_data); + retval = securid_encrypt_track_data_2(context, client, &tmp_data, + &track_id); + if (retval != 0) { + com_err("krb5kdc", retval, "while encrypting nonce track data"); + goto cleanup; + } + sc2b.sam_track_id = track_id; + + scratch.data = (char *)&sc2b.sam_nonce; + scratch.length = sizeof(sc2b.sam_nonce); + retval = krb5_c_random_make_octets(context, &scratch); + if (retval) { + com_err("krb5kdc", retval, + "while generating nonce data in get_securid_edata_2 (%s)", + user ? user : def_user); + goto cleanup; + } + + /* Get the client's key */ + sc2b.sam_etype = client_key->enctype; + + retval = sam_make_challenge(context, &sc2b, client_key, sc2); + if (retval) { + com_err("krb5kdc", retval, + "while making SAM_CHALLENGE_2 checksum (%s)", + user ? user : def_user); + } + +cleanup: + free(user); + krb5_free_data_contents(context, &track_id); + return retval; +} + +krb5_error_code +verify_securid_data_2(krb5_context context, krb5_db_entry *client, + krb5_sam_response_2 *sr2, + krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *pa, + krb5_sam_challenge_2 **sc2_out) +{ + krb5_error_code retval; + int new_pin = 0; + krb5_key_data *client_key_data = NULL; + krb5_keyblock client_key; + krb5_data scratch; + krb5_enc_sam_response_enc_2 *esre2 = NULL; + struct securid_track_data sid_track_data, *trackp = NULL; + krb5_data tmp_data; + SDI_HANDLE sd_handle = SDI_HANDLE_NONE; + krb5_sam_challenge_2 *sc2p = NULL; + char *cp, *user = NULL; + char *securid_user = NULL; + char passcode[LENPRNST+1]; + char max_pin_len, min_pin_len, alpha_pin; + + memset(&client_key, 0, sizeof(client_key)); + memset(&scratch, 0, sizeof(scratch)); + *sc2_out = NULL; + + retval = krb5_unparse_name(context, client->princ, &user); + if (retval != 0) { + com_err("krb5kdc", retval, + "while unparsing client name in verify_securid_data_2"); + return retval; + } + + if ((sr2->sam_enc_nonce_or_sad.ciphertext.data == NULL) || + (sr2->sam_enc_nonce_or_sad.ciphertext.length <= 0)) { + retval = KRB5KDC_ERR_PREAUTH_FAILED; + k5_setmsg(context, retval, + "No preauth data supplied in verify_securid_data_2 (%s)", + user); + goto cleanup; + } + + retval = krb5_dbe_find_enctype(context, client, + sr2->sam_enc_nonce_or_sad.enctype, -1, + sr2->sam_enc_nonce_or_sad.kvno, + &client_key_data); + if (retval) { + com_err("krb5kdc", retval, + "while getting client key in verify_securid_data_2 (%s)", + user); + goto cleanup; + } + + retval = krb5_dbe_decrypt_key_data(context, NULL, client_key_data, + &client_key, NULL); + if (retval != 0) { + com_err("krb5kdc", retval, + "while decrypting client key in verify_securid_data_2 (%s)", + user); + goto cleanup; + } + + scratch.length = sr2->sam_enc_nonce_or_sad.ciphertext.length; + scratch.data = k5alloc(scratch.length, &retval); + if (retval) + goto cleanup; + retval = krb5_c_decrypt(context, &client_key, + KRB5_KEYUSAGE_PA_SAM_RESPONSE, 0, + &sr2->sam_enc_nonce_or_sad, &scratch); + if (retval) { + com_err("krb5kdc", retval, + "while decrypting SAD in verify_securid_data_2 (%s)", user); + goto cleanup; + } + + retval = decode_krb5_enc_sam_response_enc_2(&scratch, &esre2); + if (retval) { + com_err("krb5kdc", retval, + "while decoding SAD in verify_securid_data_2 (%s)", user); + esre2 = NULL; + goto cleanup; + } + + if (sr2->sam_nonce != esre2->sam_nonce) { + com_err("krb5kdc", KRB5KDC_ERR_PREAUTH_FAILED, + "while checking nonce in verify_securid_data_2 (%s)", user); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + if (esre2->sam_sad.length == 0 || esre2->sam_sad.data == NULL) { + com_err("krb5kdc", KRB5KDC_ERR_PREAUTH_FAILED, + "No SecurID passcode in verify_securid_data_2 (%s)", user); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + /* Copy out SAD to null-terminated buffer */ + memset(passcode, 0, sizeof(passcode)); + if (esre2->sam_sad.length > (sizeof(passcode) - 1)) { + retval = KRB5KDC_ERR_PREAUTH_FAILED; + com_err("krb5kdc", retval, + "SecurID passcode/PIN too long (%d bytes) in " + "verify_securid_data_2 (%s)", + esre2->sam_sad.length, user); + goto cleanup; + } + if (esre2->sam_sad.length > 0) + memcpy(passcode, esre2->sam_sad.data, esre2->sam_sad.length); + + securid_user = strdup(user); + if (!securid_user) { + retval = ENOMEM; + com_err("krb5kdc", ENOMEM, + "while copying user name in verify_securid_data_2 (%s)", user); + goto cleanup; + } + cp = strchr(securid_user, '@'); + if (cp != NULL) + *cp = '\0'; + + /* Check for any track_id data that may have state from a previous attempt + * at SecurID authentication. */ + + if (sr2->sam_track_id.data && (sr2->sam_track_id.length > 0)) { + krb5_data track_id_data; + + memset(&track_id_data, 0, sizeof(track_id_data)); + retval = securid_decrypt_track_data_2(context, client, + &sr2->sam_track_id, + &track_id_data); + if (retval) { + com_err("krb5kdc", retval, + "while decrypting SecurID trackID in " + "verify_securid_data_2 (%s)", user); + goto cleanup; + } + if (track_id_data.length < sizeof (struct securid_track_data)) { + retval = KRB5KDC_ERR_PREAUTH_FAILED; + com_err("krb5kdc", retval, "Length of track data incorrect"); + goto cleanup; + } + trackp = (struct securid_track_data *)track_id_data.data; + + if(trackp->hostid != gethostid()) { + krb5_klog_syslog(LOG_INFO, "Unexpected challenge response"); + retval = KRB5KDC_ERR_DISCARD; + goto cleanup; + } + + switch(trackp->state) { + case SECURID_STATE_INITIAL: + goto initial; + break; + case SECURID_STATE_NEW_PIN_AGAIN: + { + int pin1_len, pin2_len; + + trackp->handle = ntohl(trackp->handle); + pin2_len = strlen(passcode); + pin1_len = strlen(trackp->passcode); + + if ((pin1_len != pin2_len) || + (memcmp(passcode, trackp->passcode, pin1_len) != 0)) { + retval = KRB5KDC_ERR_PREAUTH_FAILED; + krb5_klog_syslog(LOG_INFO, "New SecurID PIN Failed for user " + "%s: PIN mismatch", user); + break; + } + retval = SD_Pin(trackp->handle, passcode); + SD_Close(trackp->handle); + if (retval == ACM_NEW_PIN_ACCEPTED) { + enc_tkt_reply->flags|= TKT_FLG_HW_AUTH; + enc_tkt_reply->flags|= TKT_FLG_PRE_AUTH; + krb5_klog_syslog(LOG_INFO, "SecurID PIN Accepted for %s in " + "verify_securid_data_2", + securid_user); + retval = 0; + } else { + retval = KRB5KDC_ERR_PREAUTH_FAILED; + krb5_klog_syslog(LOG_INFO, + "SecurID PIN Failed for user %s (AceServer " + "returns %d) in verify_securid_data_2", + user, retval); + } + break; + } + case SECURID_STATE_NEW_PIN: { + krb5_sam_challenge_2_body sc2b; + sc2p = k5alloc(sizeof *sc2p, &retval); + if (retval) + goto cleanup; + memset(sc2p, 0, sizeof(*sc2p)); + memset(&sc2b, 0, sizeof(sc2b)); + sc2b.sam_type = PA_SAM_TYPE_SECURID; + sc2b.sam_response_prompt.data = NEW_PIN_AGAIN_message; + sc2b.sam_response_prompt.length = + strlen(sc2b.sam_response_prompt.data); + sc2b.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD; + sc2b.sam_etype = client_key.enctype; + + tmp_data.data = (char *)&sc2b.sam_nonce; + tmp_data.length = sizeof(sc2b.sam_nonce); + if ((retval = krb5_c_random_make_octets(context, &tmp_data))) { + com_err("krb5kdc", retval, + "while making nonce for SecurID new " + "PIN2 SAM_CHALLENGE_2 (%s)", user); + goto cleanup; + } + sid_track_data.state = SECURID_STATE_NEW_PIN_AGAIN; + sid_track_data.handle = trackp->handle; + sid_track_data.hostid = gethostid(); + /* Should we complain if sizes don't work ?? */ + memcpy(sid_track_data.passcode, passcode, + sizeof(sid_track_data.passcode)); + tmp_data.data = (char *)&sid_track_data; + tmp_data.length = sizeof(sid_track_data); + if ((retval = securid_encrypt_track_data_2(context, client, + &tmp_data, + &sc2b.sam_track_id))) { + com_err("krb5kdc", retval, + "while encrypting NEW PIN2 SecurID " + "track data for SAM_CHALLENGE_2 (%s)", + securid_user); + goto cleanup; + } + retval = sam_make_challenge(context, &sc2b, &client_key, sc2p); + if (retval) { + com_err("krb5kdc", retval, + "while making cksum for " + "SAM_CHALLENGE_2 (new PIN2) (%s)", securid_user); + goto cleanup; + } + krb5_klog_syslog(LOG_INFO, + "Requesting verification of new PIN for user %s", + securid_user); + *sc2_out = sc2p; + sc2p = NULL; + /*sc2_out may be set even on error path*/ + retval = KRB5KDC_ERR_PREAUTH_REQUIRED; + goto cleanup; + } + case SECURID_STATE_NEXT_CODE: + trackp->handle = ntohl(trackp->handle); + retval = SD_Next(trackp->handle, passcode); + SD_Close(trackp->handle); + if (retval == ACM_OK) { + enc_tkt_reply->flags |= TKT_FLG_HW_AUTH | TKT_FLG_PRE_AUTH; + + krb5_klog_syslog(LOG_INFO, "Next SecurID Code Accepted for " + "user %s", securid_user); + retval = 0; + } else { + krb5_klog_syslog(LOG_INFO, "Next SecurID Code Failed for user " + "%s (AceServer returns %d) in " + "verify_securid_data_2", user, retval); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + } + break; + } + } else { /* No track data, this is first of N attempts */ + initial: + retval = SD_Init(&sd_handle); + if (retval) { + com_err("krb5kdc", KRB5KDC_ERR_PREAUTH_FAILED, + "SD_Init() returns error %d in verify_securid_data_2 (%s)", + retval, securid_user); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + retval = SD_Lock(sd_handle, securid_user); + if (retval != ACM_OK) { + SD_Close(sd_handle); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + krb5_klog_syslog(LOG_INFO, + "SD_Lock() failed (AceServer returns %d) for %s", + retval, securid_user); + goto cleanup; + } + + retval = SD_Check(sd_handle, passcode, securid_user); + switch (retval) { + case ACM_OK: + SD_Close(sd_handle); + enc_tkt_reply->flags|= TKT_FLG_HW_AUTH; + enc_tkt_reply->flags|= TKT_FLG_PRE_AUTH; + krb5_klog_syslog(LOG_INFO, "SecurID passcode accepted for user %s", + user); + retval = 0; + break; + case ACM_ACCESS_DENIED: + SD_Close(sd_handle); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + krb5_klog_syslog(LOG_INFO, "AceServer returns Access Denied for " + "user %s (SAM2)", user); + goto cleanup; + case ACM_NEW_PIN_REQUIRED: + new_pin = 1; + /*fall through*/ + case ACM_NEXT_CODE_REQUIRED: { + krb5_sam_challenge_2_body sc2b; + sc2p = k5alloc(sizeof *sc2p, &retval); + if (retval) + goto cleanup; + + memset(sc2p, 0, sizeof(*sc2p)); + memset(&sc2b, 0, sizeof(sc2b)); + + sc2b.sam_type = PA_SAM_TYPE_SECURID; + sc2b.sam_response_prompt.data = NEXT_PASSCODE_message; + sc2b.sam_response_prompt.length = + strlen(sc2b.sam_response_prompt.data); + sc2b.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD; + sc2b.sam_etype = client_key.enctype; + if (new_pin) { + if ((AceGetMaxPinLen(sd_handle, &max_pin_len) == ACE_SUCCESS) + && (AceGetMinPinLen(sd_handle, + &min_pin_len) == ACE_SUCCESS) + && (AceGetAlphanumeric(sd_handle, + &alpha_pin) == ACE_SUCCESS)) { + sprintf(PIN_message, + "New PIN must contain %d to %d %sdigits", + min_pin_len, max_pin_len, + (alpha_pin == 0) ? "" : "alphanumeric "); + sc2b.sam_challenge_label.data = PIN_message; + sc2b.sam_challenge_label.length = + strlen(sc2b.sam_challenge_label.data); + } else { + sc2b.sam_challenge_label.length = 0; + } + } + + tmp_data.data = (char *)&sc2b.sam_nonce; + tmp_data.length = sizeof(sc2b.sam_nonce); + if ((retval = krb5_c_random_make_octets(context, &tmp_data))) { + com_err("krb5kdc", retval, + "while making nonce for SecurID SAM_CHALLENGE_2 (%s)", + user); + goto cleanup; + } + if (new_pin) + sid_track_data.state = SECURID_STATE_NEW_PIN; + else + sid_track_data.state = SECURID_STATE_NEXT_CODE; + sid_track_data.handle = htonl(sd_handle); + sid_track_data.hostid = gethostid(); + tmp_data.data = (char *)&sid_track_data; + tmp_data.length = sizeof(sid_track_data); + retval = securid_encrypt_track_data_2(context, client, &tmp_data, + &sc2b.sam_track_id); + if (retval) { + com_err("krb5kdc", retval, + "while encrypting SecurID track " + "data for SAM_CHALLENGE_2 (%s)", + securid_user); + goto cleanup; + } + retval = sam_make_challenge(context, &sc2b, &client_key, sc2p); + if (retval) { + com_err("krb5kdc", retval, + "while making cksum for SAM_CHALLENGE_2 (%s)", + securid_user); + } + if (new_pin) + krb5_klog_syslog(LOG_INFO, "New SecurID PIN required for " + "user %s", securid_user); + else + krb5_klog_syslog(LOG_INFO, "Next SecurID passcode required " + "for user %s", securid_user); + *sc2_out = sc2p; + sc2p = NULL; + retval = KRB5KDC_ERR_PREAUTH_REQUIRED; + /*sc2_out is permitted as an output on error path*/ + goto cleanup; + } + default: + com_err("krb5kdc", KRB5KDC_ERR_PREAUTH_FAILED, + "AceServer returns unknown error code %d " + "in verify_securid_data_2\n", retval); + retval = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + } /* no track_id data */ + +cleanup: + krb5_free_keyblock_contents(context, &client_key); + free(scratch.data); + krb5_free_enc_sam_response_enc_2(context, esre2); + free(user); + free(securid_user); + free(trackp); + krb5_free_sam_challenge_2(context, sc2p); + return retval; +} + +#endif /* ARL_SECURID_PREAUTH */ diff --git a/krb5-1.21.3/src/plugins/preauth/securid_sam2/securid_sam2.exports b/krb5-1.21.3/src/plugins/preauth/securid_sam2/securid_sam2.exports new file mode 100644 index 00000000..9abae919 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/securid_sam2/securid_sam2.exports @@ -0,0 +1 @@ +kdcpreauth_securid_sam2_initvt diff --git a/krb5-1.21.3/src/plugins/preauth/securid_sam2/securid_sam2_main.c b/krb5-1.21.3/src/plugins/preauth/securid_sam2/securid_sam2_main.c new file mode 100644 index 00000000..5dcd2ebf --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/securid_sam2/securid_sam2_main.c @@ -0,0 +1,378 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/securid_sam2/securid_sam2_main.c */ +/* + * Copyright (C) 2009, 2010 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ +/* + * Copyright (c) 2002 Naval Research Laboratory (NRL/CCS) + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the software, + * derivative works or modified versions, and any portions thereof. + * + * NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND + * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER + * RESULTING FROM THE USE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include "extern.h" + +static struct { + char* name; + int sam_type; +} *sam_ptr, sam_inst_map[] = { + { "SECURID", PA_SAM_TYPE_SECURID, }, + { "GRAIL", PA_SAM_TYPE_GRAIL, }, + { 0, 0 }, +}; + +krb5_error_code +sam_get_db_entry(krb5_context context, krb5_principal client, + int *sam_type, struct _krb5_db_entry_new **db_entry) +{ + struct _krb5_db_entry_new *assoc = NULL; + krb5_principal newp = NULL; + int probeslot; + void *ptr = NULL; + krb5_error_code retval; + + if (db_entry) + *db_entry = NULL; + retval = krb5_copy_principal(context, client, &newp); + if (retval) { + com_err("krb5kdc", retval, "copying client name for preauth probe"); + return retval; + } + + probeslot = krb5_princ_size(context, newp)++; + ptr = realloc(krb5_princ_name(context, newp), + krb5_princ_size(context, newp) * sizeof(krb5_data)); + if (ptr == NULL) { + retval = ENOMEM; + goto cleanup; + } + krb5_princ_name(context, newp) = ptr; + + for(sam_ptr = sam_inst_map; sam_ptr->name; sam_ptr++) { + if (*sam_type && *sam_type != sam_ptr->sam_type) + continue; + + krb5_princ_component(context,newp,probeslot)->data = sam_ptr->name; + krb5_princ_component(context,newp,probeslot)->length = + strlen(sam_ptr->name); + retval = krb5_db_get_principal(context, newp, 0, &assoc); + if (!retval) + break; + } +cleanup: + if (ptr) { + krb5_princ_component(context,newp,probeslot)->data = 0; + krb5_princ_component(context,newp,probeslot)->length = 0; + krb5_free_principal(context, newp); + } + if (probeslot) + krb5_princ_size(context, newp)--; + if (retval) + return retval; + if (sam_ptr->sam_type) { + /* Found entry of type sam_ptr->sam_type */ + if (sam_type) + *sam_type = sam_ptr->sam_type; + if (db_entry) + *db_entry = assoc; + else + krb5_db_free_principal(context, assoc); + return 0; + } else { + return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + } +} + +krb5_error_code +sam_make_challenge(krb5_context context, krb5_sam_challenge_2_body *sc2b, + krb5_keyblock *cksum_key, krb5_sam_challenge_2 *sc2_out) +{ + krb5_error_code retval; + krb5_checksum **cksum_array = NULL; + krb5_checksum *cksum = NULL; + krb5_cksumtype cksumtype; + krb5_data *encoded_challenge_body = NULL; + + if (!cksum_key) + return KRB5_PREAUTH_NO_KEY; + if (!sc2_out || !sc2b) + return KRB5KDC_ERR_PREAUTH_FAILED; + + retval = encode_krb5_sam_challenge_2_body(sc2b, &encoded_challenge_body); + if (retval || !encoded_challenge_body) { + encoded_challenge_body = NULL; + goto cksum_cleanup; + } + + cksum_array = calloc(2, sizeof(krb5_checksum *)); + if (!cksum_array) { + retval = ENOMEM; + goto cksum_cleanup; + } + + cksum = (krb5_checksum *)k5alloc(sizeof(krb5_checksum), &retval); + if (retval) + goto cksum_cleanup; + cksum_array[0] = cksum; + cksum_array[1] = NULL; + + retval = krb5int_c_mandatory_cksumtype(context, cksum_key->enctype, + &cksumtype); + if (retval) + goto cksum_cleanup; + + retval = krb5_c_make_checksum(context, cksumtype, cksum_key, + KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM, + encoded_challenge_body, cksum); + if (retval) + goto cksum_cleanup; + + sc2_out->sam_cksum = cksum_array; + sc2_out->sam_challenge_2_body = *encoded_challenge_body; + return 0; + +cksum_cleanup: + krb5_free_data(context, encoded_challenge_body); + free(cksum_array); + free(cksum); + return retval; +} + +static void +kdc_include_padata(krb5_context context, krb5_kdc_req *request, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type, + krb5_kdcpreauth_edata_respond_fn respond, void *arg) +{ + krb5_error_code retval; + krb5_keyblock *client_key = NULL; + krb5_sam_challenge_2 sc2; + int sam_type = 0; /* unknown */ + krb5_db_entry *sam_db_entry = NULL, *client; + krb5_data *encoded_challenge = NULL; + krb5_pa_data *pa_data = NULL; + + memset(&sc2, 0, sizeof(sc2)); + + client = cb->client_entry(context, rock); + retval = sam_get_db_entry(context, client->princ, &sam_type, + &sam_db_entry); + if (retval) + goto cleanup; + retval = cb->client_keys(context, rock, &client_key); + if (retval) + goto cleanup; + if (client_key->enctype == 0) { + retval = KRB5KDC_ERR_ETYPE_NOSUPP; + com_err("krb5kdc", retval, + "No client keys found in processing SAM2 challenge"); + goto cleanup; + } + + if (sam_type == 0) { + retval = KRB5_PREAUTH_BAD_TYPE; + goto cleanup; + } + + /* + * Defer getting the key for the SAM principal associated with the client + * until the mechanism-specific code. The mechanism may want to get a + * specific keytype. + */ + + switch (sam_type) { +#ifdef ARL_SECURID_PREAUTH + case PA_SAM_TYPE_SECURID: + retval = get_securid_edata_2(context, client, client_key, &sc2); + if (retval) + goto cleanup; + break; +#endif /* ARL_SECURID_PREAUTH */ +#ifdef GRAIL_PREAUTH + case PA_SAM_TYPE_GRAIL: + retval = get_grail_edata(context, client, client_key, &sc2); + if (retval) + goto cleanup; + break; +#endif /* GRAIL_PREAUTH */ + default: + retval = KRB5_PREAUTH_BAD_TYPE; + goto cleanup; + } + + retval = encode_krb5_sam_challenge_2(&sc2, &encoded_challenge); + if (retval) { + com_err("krb5kdc", retval, + "while encoding SECURID SAM_CHALLENGE_2"); + goto cleanup; + } + + pa_data = k5alloc(sizeof(*pa_data), &retval); + if (pa_data == NULL) + goto cleanup; + pa_data->magic = KV5M_PA_DATA; + pa_data->pa_type = KRB5_PADATA_SAM_CHALLENGE_2; + pa_data->contents = (krb5_octet *)encoded_challenge->data; + pa_data->length = encoded_challenge->length; + encoded_challenge->data = NULL; + +cleanup: + krb5_free_data(context, encoded_challenge); + if (sam_db_entry) + krb5_db_free_principal(context, sam_db_entry); + cb->free_keys(context, rock, client_key); + (*respond)(arg, retval, pa_data); +} + +static void +kdc_verify_preauth(krb5_context context, krb5_data *req_pkt, + krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply, + krb5_pa_data *pa_data, krb5_kdcpreauth_callbacks cb, + krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_verify_respond_fn respond, void *arg) +{ + krb5_error_code retval, saved_retval = 0; + krb5_sam_response_2 *sr2 = NULL; + krb5_data scratch, *scratch2, *e_data = NULL; + char *client_name = NULL; + krb5_sam_challenge_2 *out_sc2 = NULL; + krb5_db_entry *client = cb->client_entry(context, rock); + + scratch.data = (char *) pa_data->contents; + scratch.length = pa_data->length; + + retval = krb5_unparse_name(context, client->princ, &client_name); + if (retval) + goto cleanup; + + retval = decode_krb5_sam_response_2(&scratch, &sr2); + if (retval) { + com_err("krb5kdc", retval, + "while decoding SAM_RESPONSE_2 in verify_sam_response_2"); + sr2 = NULL; + goto cleanup; + } + + switch (sr2->sam_type) { +#ifdef ARL_SECURID_PREAUTH + case PA_SAM_TYPE_SECURID: + retval = verify_securid_data_2(context, client, sr2, enc_tkt_reply, + pa_data, &out_sc2); + if (retval) + goto cleanup; + break; +#endif /* ARL_SECURID_PREAUTH */ +#ifdef GRAIL_PREAUTH + case PA_SAM_TYPE_GRAIL: + retval = verify_grail_data(context, client, sr2, enc_tkt_reply, + pa_data, &out_sc2); + if (retval) + goto cleanup; + break; +#endif /* GRAIL_PREAUTH */ + default: + retval = KRB5_PREAUTH_BAD_TYPE; + com_err("krb5kdc", retval, "while verifying SAM 2 data"); + break; + } + + /* + * It is up to the method-specific verify routine to set the + * ticket flags to indicate TKT_FLG_HW_AUTH and/or + * TKT_FLG_PRE_AUTH. Some methods may require more than one round + * of dialog with the client and must return successfully from + * their verify routine. If does not set the TGT flags, the + * required_preauth conditions will not be met and it will try + * again to get enough preauth data from the client. Do not set + * TGT flags here. + */ +cleanup: + /* + * Note that e_data is an output even in error conditions. If we + * successfully encode the output e_data, we return whatever error is + * received above. Otherwise we return the encoding error. + */ + saved_retval = retval; + if (out_sc2) { + krb5_pa_data pa_out; + krb5_pa_data *pa_array[2]; + pa_array[0] = &pa_out; + pa_array[1] = NULL; + pa_out.pa_type = KRB5_PADATA_SAM_CHALLENGE_2; + retval = encode_krb5_sam_challenge_2(out_sc2, &scratch2); + krb5_free_sam_challenge_2(context, out_sc2); + if (retval) + goto encode_error; + pa_out.contents = (krb5_octet *) scratch2->data; + pa_out.length = scratch2->length; + retval = encode_krb5_padata_sequence(pa_array, &e_data); + krb5_free_data(context, scratch2); + } +encode_error: + krb5_free_sam_response_2(context, sr2); + free(client_name); + if (retval == 0) + retval = saved_retval; + + (*respond)(arg, retval, NULL, NULL, NULL); +} + + +static int +kdc_preauth_flags(krb5_context context, krb5_preauthtype patype) +{ + return PA_HARDWARE; +} + +krb5_preauthtype supported_pa_types[] = { + KRB5_PADATA_SAM_RESPONSE_2, 0}; + +krb5_error_code +kdcpreauth_securid_sam2_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +kdcpreauth_securid_sam2_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_kdcpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "securid_sam2"; + vt->pa_type_list = supported_pa_types; + vt->flags = kdc_preauth_flags; + vt->edata = kdc_include_padata; + vt->verify = kdc_verify_preauth; + return 0; +} diff --git a/krb5-1.21.3/src/plugins/preauth/spake/AUTHORS b/krb5-1.21.3/src/plugins/preauth/spake/AUTHORS new file mode 100644 index 00000000..31d71c21 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/AUTHORS @@ -0,0 +1,16 @@ +# This is the official list of fiat-crypto authors for copyright purposes. +# This file is distinct from the CONTRIBUTORS files. +# See the latter for an explanation. + +# Names should be added to this file as one of +# Organization's name +# Individual's name +# Individual's name +# See CONTRIBUTORS for the meaning of multiple email addresses. + +# Please keep the list sorted. + +Andres Erbsen +Google Inc. +Jade Philipoom +Massachusetts Institute of Technology diff --git a/krb5-1.21.3/src/plugins/preauth/spake/Makefile.in b/krb5-1.21.3/src/plugins/preauth/spake/Makefile.in new file mode 100644 index 00000000..b51d4d69 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/Makefile.in @@ -0,0 +1,60 @@ +mydir=plugins$(S)preauth$(S)spake +BUILDTOP=$(REL)..$(S)..$(S).. +MODULE_INSTALL_DIR = $(KRB5_PA_MODULE_DIR) + +# Like RUN_TEST, but use t_krb5.conf from this directory. +RUN_TEST_LOCAL_CONF=$(RUN_SETUP) KRB5_CONFIG=$(srcdir)/t_krb5.conf LC_ALL=C \ + $(VALGRIND) + +LIBBASE=spake +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/preauth/spake +SHLIB_EXPDEPS=$(KRB5_BASE_DEPLIBS) +SHLIB_EXPLIBS=$(KRB5_BASE_LIBS) $(SPAKE_OPENSSL_LIBS) + +WINLIBS = $(SLIB) $(KLIB) $(CLIB) + +STLIBOBJS=util.o iana.o groups.o openssl.o edwards25519.o \ + spake_client.o spake_kdc.o + +SRCS= \ + $(srcdir)/util.c \ + $(srcdir)/iana.c \ + $(srcdir)/groups.c \ + $(srcdir)/openssl.c \ + $(srcdir)/edwards25519.c \ + $(srcdir)/spake_client.c \ + $(srcdir)/spake_kdc.c + +# Don't include spake_kdc.c in the Windows object list since we don't +# need it. +OBJS= $(OUTPRE)util.$(OBJEXT) \ + $(OUTPRE)iana.$(OBJEXT) \ + $(OUTPRE)groups.$(OBJEXT) \ + $(OUTPRE)openssl.$(OBJEXT) \ + $(OUTPRE)edwards25519.$(OBJEXT) \ + $(OUTPRE)spake_client.$(OBJEXT) + +t_vectors: t_vectors.o $(STLIBOBJS) $(SHLIB_EXPDEPS) + $(CC_LINK) -o $@ t_vectors.o $(STLIBOBJS) $(SHLIB_EXPLIBS) + +all-unix: all-liblinks +install-unix: install-libs +clean-unix:: clean-liblinks clean-libs clean-libobjs + +clean: + $(RM) t_vectors t_vectors.o $(STLIBOBJS) + +check-unix: t_vectors + $(RUN_TEST_LOCAL_CONF) ./t_vectors + +all-windows: $(OUTPRE)$(SPAKELIB).dll +clean-windows:: + $(RM) $(OUTPRE)$(SPAKELIB).dll + +$(OUTPRE)$(SPAKELIB).dll: spake.def $(OBJS) + link /dll $(LOPTS) -def:spake.def -out:$*.dll $(OBJS) $(WINLIBS) + +@libnover_frag@ +@libobj_frag@ diff --git a/krb5-1.21.3/src/plugins/preauth/spake/deps b/krb5-1.21.3/src/plugins/preauth/spake/deps new file mode 100644 index 00000000..695ad973 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/deps @@ -0,0 +1,74 @@ +# +# Generated makefile dependencies follow. +# +util.so util.po $(OUTPRE)util.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h groups.h iana.h \ + trace.h util.c util.h +iana.so iana.po $(OUTPRE)iana.$(OBJEXT): iana.c iana.h +groups.so groups.po $(OUTPRE)groups.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h groups.c groups.h \ + iana.h trace.h +openssl.so openssl.po $(OUTPRE)openssl.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h groups.h iana.h \ + openssl.c +edwards25519.so edwards25519.po $(OUTPRE)edwards25519.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + edwards25519.c edwards25519_fiat.h edwards25519_tables.h \ + groups.h iana.h +spake_client.so spake_client.po $(OUTPRE)spake_client.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-spake.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/clpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + groups.h iana.h spake_client.c trace.h util.h +spake_kdc.so spake_kdc.po $(OUTPRE)spake_kdc.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-input.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-spake.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/kdcpreauth_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h groups.h iana.h \ + spake_kdc.c trace.h util.h diff --git a/krb5-1.21.3/src/plugins/preauth/spake/edwards25519.c b/krb5-1.21.3/src/plugins/preauth/spake/edwards25519.c new file mode 100644 index 00000000..20394115 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/edwards25519.c @@ -0,0 +1,1753 @@ +/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* This file is adapted from the SPAKE edwards25519 code in BoringSSL. */ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +/* + * Copyright (c) 2015-2016, Google Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * This code is adapted from the BoringSSL edwards25519 SPAKE2 implementation + * from third_party/fiat and crypto/spake25519.c, with the following + * adaptations: + * + * - The M and N points are the ones from draft-irtf-cfrg-spake2-05. The + * BoringSSL M and N points were determined similarly, but were not + * restricted to members of the generator subgroup, so they use only one hash + * iteration for both points. The intent in BoringSSL had been to multiply w + * by the cofactor so that wM and wN would be in the subgroup, but as that + * step was accidentally omitted, a hack had to be introduced after the fact + * to add multiples of the prime order to the scalar. That hack is not + * present in this code, and the SPAKE preauth spec does not multiply w by + * the cofactor as it is unnecessary if M and N are chosen from the subgroup. + * + * - The SPAKE code is modified to fit the groups.h interface and the SPAKE + * preauth spec. + * + * - The required declarations and code are all here in one file (except for + * the generator point table, which is still in a separate header), so all of + * the functions are declared static. + * + * - BORINGSSL_CURVE25519_64BIT is defined here using autoconf tests. + * + * - curve25519_32.h and curve25519_64.h are combined into edwards25519_fiat.h + * (conditionalized on BORINGSSL_CURVE25519_64BIT) for predictable dependency + * generation. The fiat_25519_selectznz and fiat_25519_carry_scmul_121666 + * functions were removed from both branches as they are not used here (the + * former because it is not used by the BoringSSL code and the latter because + * it is only used by the X25519 code). The fiat_25519_int128 and + * fiat_25519_uint128 typedefs were adjusted to work with older versions of + * gcc. + * + * - fe_cmov() has the initial "Silence an unused function warning" part + * removed, as we removed fiat_25519_selectznz instead. + * + * - The field element bounds assertion checks are disabled by default, as they + * slow the code down by roughly a factor of two. The + * OPENSSL_COMPILE_ASSERT() in fe_copy_lt() is changed to a regular assert + * and is also conditionalized. Do a build and "make check" with + * EDWARDS25519_ASSERTS defined when updating this code. + * + * - The copyright comments at the top are formatted the way we do so in other + * source files, for ease of extraction. + * + * - Declarations in for loops conflict with our compiler configuration in + * older versions of gcc, so they are moved outside of the for loop. + * + * - The preprocessor symbol OPENSSL_SMALL is changed to CONFIG_SMALL. + * + * - OPENSSL_memset and OPENSSL_memmove are changed to memset and memmove, in + * each case verifying that they are used with nonzero length arguments. + * + * - CRYPTO_memcmp is changed to k5_bcmp. + * + * - Functions used only by X25519 or Ed25519 interfaces but not SPAKE are + * removed, taking care to check for unused functions in both the 64-bit and + * 32-bit preprocessor branches. ge_p3_dbl() is unused here if CONFIG_SMALL + * is defined, so it is placed inside #ifndef CONFIG_SMALL. + */ + +// Some of this code is taken from the ref10 version of Ed25519 in SUPERCOP +// 20141124 (https://bench.cr.yp.to/supercop.html). That code is released as +// public domain but parts have been replaced with code generated by Fiat +// (https://github.com/mit-plv/fiat-crypto), which is MIT licensed. + +#include "groups.h" +#include "iana.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wdeclaration-after-statement" +#endif + +#if SIZEOF_SIZE_T >= 8 && defined(HAVE___INT128_T) && defined(HAVE___UINT128_T) +#define BORINGSSL_CURVE25519_64BIT +typedef __int128_t int128_t; +typedef __uint128_t uint128_t; +#endif + +/* From BoringSSL third-party/fiat/internal.h */ + +#if defined(BORINGSSL_CURVE25519_64BIT) +// fe means field element. Here the field is \Z/(2^255-19). An element t, +// entries t[0]...t[4], represents the integer t[0]+2^51 t[1]+2^102 t[2]+2^153 +// t[3]+2^204 t[4]. +// fe limbs are bounded by 1.125*2^51. +// Multiplication and carrying produce fe from fe_loose. +typedef struct fe { uint64_t v[5]; } fe; + +// fe_loose limbs are bounded by 3.375*2^51. +// Addition and subtraction produce fe_loose from (fe, fe). +typedef struct fe_loose { uint64_t v[5]; } fe_loose; +#else +// fe means field element. Here the field is \Z/(2^255-19). An element t, +// entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77 +// t[3]+2^102 t[4]+...+2^230 t[9]. +// fe limbs are bounded by 1.125*2^26,1.125*2^25,1.125*2^26,1.125*2^25,etc. +// Multiplication and carrying produce fe from fe_loose. +typedef struct fe { uint32_t v[10]; } fe; + +// fe_loose limbs are bounded by 3.375*2^26,3.375*2^25,3.375*2^26,3.375*2^25,etc. +// Addition and subtraction produce fe_loose from (fe, fe). +typedef struct fe_loose { uint32_t v[10]; } fe_loose; +#endif + +// ge means group element. +// +// Here the group is the set of pairs (x,y) of field elements (see fe.h) +// satisfying -x^2 + y^2 = 1 + d x^2y^2 +// where d = -121665/121666. +// +// Representations: +// ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z +// ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT +// ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T +// ge_precomp (Duif): (y+x,y-x,2dxy) + +typedef struct { + fe X; + fe Y; + fe Z; +} ge_p2; + +typedef struct { + fe X; + fe Y; + fe Z; + fe T; +} ge_p3; + +typedef struct { + fe_loose X; + fe_loose Y; + fe_loose Z; + fe_loose T; +} ge_p1p1; + +typedef struct { + fe_loose yplusx; + fe_loose yminusx; + fe_loose xy2d; +} ge_precomp; + +typedef struct { + fe_loose YplusX; + fe_loose YminusX; + fe_loose Z; + fe_loose T2d; +} ge_cached; + +#include "edwards25519_tables.h" +#include "edwards25519_fiat.h" + +/* From BoringSSL third-party/fiat/curve25519.c */ + +static uint64_t load_3(const uint8_t *in) { + uint64_t result; + result = (uint64_t)in[0]; + result |= ((uint64_t)in[1]) << 8; + result |= ((uint64_t)in[2]) << 16; + return result; +} + +static uint64_t load_4(const uint8_t *in) { + uint64_t result; + result = (uint64_t)in[0]; + result |= ((uint64_t)in[1]) << 8; + result |= ((uint64_t)in[2]) << 16; + result |= ((uint64_t)in[3]) << 24; + return result; +} + + +// Field operations. + +#if defined(BORINGSSL_CURVE25519_64BIT) + +typedef uint64_t fe_limb_t; +#define FE_NUM_LIMBS 5 + +// assert_fe asserts that |f| satisfies bounds: +// +// [[0x0 ~> 0x8cccccccccccc], +// [0x0 ~> 0x8cccccccccccc], +// [0x0 ~> 0x8cccccccccccc], +// [0x0 ~> 0x8cccccccccccc], +// [0x0 ~> 0x8cccccccccccc]] +// +// See comments in edwards25519_fiat.h for which functions use these bounds for +// inputs or outputs. +#define assert_fe(f) \ + do { \ + for (unsigned _assert_fe_i = 0; _assert_fe_i < 5; _assert_fe_i++) { \ + assert(f[_assert_fe_i] <= UINT64_C(0x8cccccccccccc)); \ + } \ + } while (0) + +// assert_fe_loose asserts that |f| satisfies bounds: +// +// [[0x0 ~> 0x1a666666666664], +// [0x0 ~> 0x1a666666666664], +// [0x0 ~> 0x1a666666666664], +// [0x0 ~> 0x1a666666666664], +// [0x0 ~> 0x1a666666666664]] +// +// See comments in edwards25519_fiat.h for which functions use these bounds for +// inputs or outputs. +#define assert_fe_loose(f) \ + do { \ + for (unsigned _assert_fe_i = 0; _assert_fe_i < 5; _assert_fe_i++) { \ + assert(f[_assert_fe_i] <= UINT64_C(0x1a666666666664)); \ + } \ + } while (0) + +#else + +typedef uint32_t fe_limb_t; +#define FE_NUM_LIMBS 10 + +// assert_fe asserts that |f| satisfies bounds: +// +// [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], +// [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], +// [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], +// [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], +// [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]] +// +// See comments in edwards25519_fiat.h for which functions use these bounds for +// inputs or outputs. +#define assert_fe(f) \ + do { \ + for (unsigned _assert_fe_i = 0; _assert_fe_i < 10; _assert_fe_i++) { \ + assert(f[_assert_fe_i] <= \ + ((_assert_fe_i & 1) ? 0x2333333u : 0x4666666u)); \ + } \ + } while (0) + +// assert_fe_loose asserts that |f| satisfies bounds: +// +// [[0x0 ~> 0xd333332], [0x0 ~> 0x6999999], +// [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], +// [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], +// [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], +// [0x0 ~> 0xd333332], [0x0 ~> 0x6999999]] +// +// See comments in edwards25519_fiat.h for which functions use these bounds for +// inputs or outputs. +#define assert_fe_loose(f) \ + do { \ + for (unsigned _assert_fe_i = 0; _assert_fe_i < 10; _assert_fe_i++) { \ + assert(f[_assert_fe_i] <= \ + ((_assert_fe_i & 1) ? 0x6999999u : 0xd333332u)); \ + } \ + } while (0) + +#endif // BORINGSSL_CURVE25519_64BIT + +#ifndef EDWARDS25519_ASSERTS +#undef assert_fe +#undef assert_fe_loose +#define assert_fe(f) +#define assert_fe_loose(f) +#endif + +static void fe_frombytes_strict(fe *h, const uint8_t s[32]) { + // |fiat_25519_from_bytes| requires the top-most bit be clear. + assert((s[31] & 0x80) == 0); + fiat_25519_from_bytes(h->v, s); + assert_fe(h->v); +} + +static void fe_frombytes(fe *h, const uint8_t s[32]) { + uint8_t s_copy[32]; + memcpy(s_copy, s, 32); + s_copy[31] &= 0x7f; + fe_frombytes_strict(h, s_copy); +} + +static void fe_tobytes(uint8_t s[32], const fe *f) { + assert_fe(f->v); + fiat_25519_to_bytes(s, f->v); +} + +// h = 0 +static void fe_0(fe *h) { + memset(h, 0, sizeof(fe)); +} + +static void fe_loose_0(fe_loose *h) { + memset(h, 0, sizeof(fe_loose)); +} + +// h = 1 +static void fe_1(fe *h) { + memset(h, 0, sizeof(fe)); + h->v[0] = 1; +} + +static void fe_loose_1(fe_loose *h) { + memset(h, 0, sizeof(fe_loose)); + h->v[0] = 1; +} + +// h = f + g +// Can overlap h with f or g. +static void fe_add(fe_loose *h, const fe *f, const fe *g) { + assert_fe(f->v); + assert_fe(g->v); + fiat_25519_add(h->v, f->v, g->v); + assert_fe_loose(h->v); +} + +// h = f - g +// Can overlap h with f or g. +static void fe_sub(fe_loose *h, const fe *f, const fe *g) { + assert_fe(f->v); + assert_fe(g->v); + fiat_25519_sub(h->v, f->v, g->v); + assert_fe_loose(h->v); +} + +static void fe_carry(fe *h, const fe_loose* f) { + assert_fe_loose(f->v); + fiat_25519_carry(h->v, f->v); + assert_fe(h->v); +} + +static void fe_mul_impl(fe_limb_t out[FE_NUM_LIMBS], + const fe_limb_t in1[FE_NUM_LIMBS], + const fe_limb_t in2[FE_NUM_LIMBS]) { + assert_fe_loose(in1); + assert_fe_loose(in2); + fiat_25519_carry_mul(out, in1, in2); + assert_fe(out); +} + +static void fe_mul_ltt(fe_loose *h, const fe *f, const fe *g) { + fe_mul_impl(h->v, f->v, g->v); +} + +static void fe_mul_llt(fe_loose *h, const fe_loose *f, const fe *g) { + fe_mul_impl(h->v, f->v, g->v); +} + +static void fe_mul_ttt(fe *h, const fe *f, const fe *g) { + fe_mul_impl(h->v, f->v, g->v); +} + +static void fe_mul_tlt(fe *h, const fe_loose *f, const fe *g) { + fe_mul_impl(h->v, f->v, g->v); +} + +static void fe_mul_ttl(fe *h, const fe *f, const fe_loose *g) { + fe_mul_impl(h->v, f->v, g->v); +} + +static void fe_mul_tll(fe *h, const fe_loose *f, const fe_loose *g) { + fe_mul_impl(h->v, f->v, g->v); +} + +static void fe_sq_tl(fe *h, const fe_loose *f) { + assert_fe_loose(f->v); + fiat_25519_carry_square(h->v, f->v); + assert_fe(h->v); +} + +static void fe_sq_tt(fe *h, const fe *f) { + assert_fe_loose(f->v); + fiat_25519_carry_square(h->v, f->v); + assert_fe(h->v); +} + +// h = -f +static void fe_neg(fe_loose *h, const fe *f) { + assert_fe(f->v); + fiat_25519_opp(h->v, f->v); + assert_fe_loose(h->v); +} + +// Replace (f,g) with (g,g) if b == 1; +// replace (f,g) with (f,g) if b == 0. +// +// Preconditions: b in {0,1}. +static void fe_cmov(fe_loose *f, const fe_loose *g, fe_limb_t b) { + b = 0-b; + unsigned i; + for (i = 0; i < FE_NUM_LIMBS; i++) { + fe_limb_t x = f->v[i] ^ g->v[i]; + x &= b; + f->v[i] ^= x; + } +} + +// h = f +static void fe_copy(fe *h, const fe *f) { + memmove(h, f, sizeof(fe)); +} + +static void fe_copy_lt(fe_loose *h, const fe *f) { +#ifdef EDWARDS25519_ASSERTS + assert(sizeof(fe_loose) == sizeof(fe)); +#endif + memmove(h, f, sizeof(fe)); +} +#if !defined(CONFIG_SMALL) +static void fe_copy_ll(fe_loose *h, const fe_loose *f) { + memmove(h, f, sizeof(fe_loose)); +} +#endif // !defined(CONFIG_SMALL) + +static void fe_loose_invert(fe *out, const fe_loose *z) { + fe t0; + fe t1; + fe t2; + fe t3; + int i; + + fe_sq_tl(&t0, z); + fe_sq_tt(&t1, &t0); + for (i = 1; i < 2; ++i) { + fe_sq_tt(&t1, &t1); + } + fe_mul_tlt(&t1, z, &t1); + fe_mul_ttt(&t0, &t0, &t1); + fe_sq_tt(&t2, &t0); + fe_mul_ttt(&t1, &t1, &t2); + fe_sq_tt(&t2, &t1); + for (i = 1; i < 5; ++i) { + fe_sq_tt(&t2, &t2); + } + fe_mul_ttt(&t1, &t2, &t1); + fe_sq_tt(&t2, &t1); + for (i = 1; i < 10; ++i) { + fe_sq_tt(&t2, &t2); + } + fe_mul_ttt(&t2, &t2, &t1); + fe_sq_tt(&t3, &t2); + for (i = 1; i < 20; ++i) { + fe_sq_tt(&t3, &t3); + } + fe_mul_ttt(&t2, &t3, &t2); + fe_sq_tt(&t2, &t2); + for (i = 1; i < 10; ++i) { + fe_sq_tt(&t2, &t2); + } + fe_mul_ttt(&t1, &t2, &t1); + fe_sq_tt(&t2, &t1); + for (i = 1; i < 50; ++i) { + fe_sq_tt(&t2, &t2); + } + fe_mul_ttt(&t2, &t2, &t1); + fe_sq_tt(&t3, &t2); + for (i = 1; i < 100; ++i) { + fe_sq_tt(&t3, &t3); + } + fe_mul_ttt(&t2, &t3, &t2); + fe_sq_tt(&t2, &t2); + for (i = 1; i < 50; ++i) { + fe_sq_tt(&t2, &t2); + } + fe_mul_ttt(&t1, &t2, &t1); + fe_sq_tt(&t1, &t1); + for (i = 1; i < 5; ++i) { + fe_sq_tt(&t1, &t1); + } + fe_mul_ttt(out, &t1, &t0); +} + +static void fe_invert(fe *out, const fe *z) { + fe_loose l; + fe_copy_lt(&l, z); + fe_loose_invert(out, &l); +} + +// return 0 if f == 0 +// return 1 if f != 0 +static int fe_isnonzero(const fe_loose *f) { + fe tight; + fe_carry(&tight, f); + uint8_t s[32]; + fe_tobytes(s, &tight); + + static const uint8_t zero[32] = {0}; + return k5_bcmp(s, zero, sizeof(zero)) != 0; +} + +// return 1 if f is in {1,3,5,...,q-2} +// return 0 if f is in {0,2,4,...,q-1} +static int fe_isnegative(const fe *f) { + uint8_t s[32]; + fe_tobytes(s, f); + return s[0] & 1; +} + +static void fe_sq2_tt(fe *h, const fe *f) { + // h = f^2 + fe_sq_tt(h, f); + + // h = h + h + fe_loose tmp; + fe_add(&tmp, h, h); + fe_carry(h, &tmp); +} + +static void fe_pow22523(fe *out, const fe *z) { + fe t0; + fe t1; + fe t2; + int i; + + fe_sq_tt(&t0, z); + fe_sq_tt(&t1, &t0); + for (i = 1; i < 2; ++i) { + fe_sq_tt(&t1, &t1); + } + fe_mul_ttt(&t1, z, &t1); + fe_mul_ttt(&t0, &t0, &t1); + fe_sq_tt(&t0, &t0); + fe_mul_ttt(&t0, &t1, &t0); + fe_sq_tt(&t1, &t0); + for (i = 1; i < 5; ++i) { + fe_sq_tt(&t1, &t1); + } + fe_mul_ttt(&t0, &t1, &t0); + fe_sq_tt(&t1, &t0); + for (i = 1; i < 10; ++i) { + fe_sq_tt(&t1, &t1); + } + fe_mul_ttt(&t1, &t1, &t0); + fe_sq_tt(&t2, &t1); + for (i = 1; i < 20; ++i) { + fe_sq_tt(&t2, &t2); + } + fe_mul_ttt(&t1, &t2, &t1); + fe_sq_tt(&t1, &t1); + for (i = 1; i < 10; ++i) { + fe_sq_tt(&t1, &t1); + } + fe_mul_ttt(&t0, &t1, &t0); + fe_sq_tt(&t1, &t0); + for (i = 1; i < 50; ++i) { + fe_sq_tt(&t1, &t1); + } + fe_mul_ttt(&t1, &t1, &t0); + fe_sq_tt(&t2, &t1); + for (i = 1; i < 100; ++i) { + fe_sq_tt(&t2, &t2); + } + fe_mul_ttt(&t1, &t2, &t1); + fe_sq_tt(&t1, &t1); + for (i = 1; i < 50; ++i) { + fe_sq_tt(&t1, &t1); + } + fe_mul_ttt(&t0, &t1, &t0); + fe_sq_tt(&t0, &t0); + for (i = 1; i < 2; ++i) { + fe_sq_tt(&t0, &t0); + } + fe_mul_ttt(out, &t0, z); +} + + +// Group operations. + +static void x25519_ge_tobytes(uint8_t s[32], const ge_p2 *h) { + fe recip; + fe x; + fe y; + + fe_invert(&recip, &h->Z); + fe_mul_ttt(&x, &h->X, &recip); + fe_mul_ttt(&y, &h->Y, &recip); + fe_tobytes(s, &y); + s[31] ^= fe_isnegative(&x) << 7; +} + +static int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t s[32]) { + fe u; + fe_loose v; + fe v3; + fe vxx; + fe_loose check; + + fe_frombytes(&h->Y, s); + fe_1(&h->Z); + fe_sq_tt(&v3, &h->Y); + fe_mul_ttt(&vxx, &v3, &d); + fe_sub(&v, &v3, &h->Z); // u = y^2-1 + fe_carry(&u, &v); + fe_add(&v, &vxx, &h->Z); // v = dy^2+1 + + fe_sq_tl(&v3, &v); + fe_mul_ttl(&v3, &v3, &v); // v3 = v^3 + fe_sq_tt(&h->X, &v3); + fe_mul_ttl(&h->X, &h->X, &v); + fe_mul_ttt(&h->X, &h->X, &u); // x = uv^7 + + fe_pow22523(&h->X, &h->X); // x = (uv^7)^((q-5)/8) + fe_mul_ttt(&h->X, &h->X, &v3); + fe_mul_ttt(&h->X, &h->X, &u); // x = uv^3(uv^7)^((q-5)/8) + + fe_sq_tt(&vxx, &h->X); + fe_mul_ttl(&vxx, &vxx, &v); + fe_sub(&check, &vxx, &u); + if (fe_isnonzero(&check)) { + fe_add(&check, &vxx, &u); + if (fe_isnonzero(&check)) { + return 0; + } + fe_mul_ttt(&h->X, &h->X, &sqrtm1); + } + + if (fe_isnegative(&h->X) != (s[31] >> 7)) { + fe_loose t; + fe_neg(&t, &h->X); + fe_carry(&h->X, &t); + } + + fe_mul_ttt(&h->T, &h->X, &h->Y); + return 1; +} + +static void ge_p2_0(ge_p2 *h) { + fe_0(&h->X); + fe_1(&h->Y); + fe_1(&h->Z); +} + +static void ge_p3_0(ge_p3 *h) { + fe_0(&h->X); + fe_1(&h->Y); + fe_1(&h->Z); + fe_0(&h->T); +} + +static void ge_cached_0(ge_cached *h) { + fe_loose_1(&h->YplusX); + fe_loose_1(&h->YminusX); + fe_loose_1(&h->Z); + fe_loose_0(&h->T2d); +} + +static void ge_precomp_0(ge_precomp *h) { + fe_loose_1(&h->yplusx); + fe_loose_1(&h->yminusx); + fe_loose_0(&h->xy2d); +} + +// r = p +static void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) { + fe_copy(&r->X, &p->X); + fe_copy(&r->Y, &p->Y); + fe_copy(&r->Z, &p->Z); +} + +// r = p +static void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p) { + fe_add(&r->YplusX, &p->Y, &p->X); + fe_sub(&r->YminusX, &p->Y, &p->X); + fe_copy_lt(&r->Z, &p->Z); + fe_mul_ltt(&r->T2d, &p->T, &d2); +} + +// r = p +static void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) { + fe_mul_tll(&r->X, &p->X, &p->T); + fe_mul_tll(&r->Y, &p->Y, &p->Z); + fe_mul_tll(&r->Z, &p->Z, &p->T); +} + +// r = p +static void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) { + fe_mul_tll(&r->X, &p->X, &p->T); + fe_mul_tll(&r->Y, &p->Y, &p->Z); + fe_mul_tll(&r->Z, &p->Z, &p->T); + fe_mul_tll(&r->T, &p->X, &p->Y); +} + +// r = p +static void ge_p1p1_to_cached(ge_cached *r, const ge_p1p1 *p) { + ge_p3 t; + x25519_ge_p1p1_to_p3(&t, p); + x25519_ge_p3_to_cached(r, &t); +} + +// r = 2 * p +static void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) { + fe trX, trZ, trT; + fe t0; + + fe_sq_tt(&trX, &p->X); + fe_sq_tt(&trZ, &p->Y); + fe_sq2_tt(&trT, &p->Z); + fe_add(&r->Y, &p->X, &p->Y); + fe_sq_tl(&t0, &r->Y); + + fe_add(&r->Y, &trZ, &trX); + fe_sub(&r->Z, &trZ, &trX); + fe_carry(&trZ, &r->Y); + fe_sub(&r->X, &t0, &trZ); + fe_carry(&trZ, &r->Z); + fe_sub(&r->T, &trT, &trZ); +} + +#ifndef CONFIG_SMALL +// r = 2 * p +static void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) { + ge_p2 q; + ge_p3_to_p2(&q, p); + ge_p2_dbl(r, &q); +} +#endif + +// r = p + q +static void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { + fe trY, trZ, trT; + + fe_add(&r->X, &p->Y, &p->X); + fe_sub(&r->Y, &p->Y, &p->X); + fe_mul_tll(&trZ, &r->X, &q->yplusx); + fe_mul_tll(&trY, &r->Y, &q->yminusx); + fe_mul_tlt(&trT, &q->xy2d, &p->T); + fe_add(&r->T, &p->Z, &p->Z); + fe_sub(&r->X, &trZ, &trY); + fe_add(&r->Y, &trZ, &trY); + fe_carry(&trZ, &r->T); + fe_add(&r->Z, &trZ, &trT); + fe_sub(&r->T, &trZ, &trT); +} + +// r = p + q +static void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { + fe trX, trY, trZ, trT; + + fe_add(&r->X, &p->Y, &p->X); + fe_sub(&r->Y, &p->Y, &p->X); + fe_mul_tll(&trZ, &r->X, &q->YplusX); + fe_mul_tll(&trY, &r->Y, &q->YminusX); + fe_mul_tlt(&trT, &q->T2d, &p->T); + fe_mul_ttl(&trX, &p->Z, &q->Z); + fe_add(&r->T, &trX, &trX); + fe_sub(&r->X, &trZ, &trY); + fe_add(&r->Y, &trZ, &trY); + fe_carry(&trZ, &r->T); + fe_add(&r->Z, &trZ, &trT); + fe_sub(&r->T, &trZ, &trT); +} + +// r = p - q +static void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { + fe trX, trY, trZ, trT; + + fe_add(&r->X, &p->Y, &p->X); + fe_sub(&r->Y, &p->Y, &p->X); + fe_mul_tll(&trZ, &r->X, &q->YminusX); + fe_mul_tll(&trY, &r->Y, &q->YplusX); + fe_mul_tlt(&trT, &q->T2d, &p->T); + fe_mul_ttl(&trX, &p->Z, &q->Z); + fe_add(&r->T, &trX, &trX); + fe_sub(&r->X, &trZ, &trY); + fe_add(&r->Y, &trZ, &trY); + fe_carry(&trZ, &r->T); + fe_sub(&r->Z, &trZ, &trT); + fe_add(&r->T, &trZ, &trT); +} + +static uint8_t equal(signed char b, signed char c) { + uint8_t ub = b; + uint8_t uc = c; + uint8_t x = ub ^ uc; // 0: yes; 1..255: no + uint32_t y = x; // 0: yes; 1..255: no + y -= 1; // 4294967295: yes; 0..254: no + y >>= 31; // 1: yes; 0: no + return y; +} + +static void cmov(ge_precomp *t, const ge_precomp *u, uint8_t b) { + fe_cmov(&t->yplusx, &u->yplusx, b); + fe_cmov(&t->yminusx, &u->yminusx, b); + fe_cmov(&t->xy2d, &u->xy2d, b); +} + +static void x25519_ge_scalarmult_small_precomp( + ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]) { + // precomp_table is first expanded into matching |ge_precomp| + // elements. + ge_precomp multiples[15]; + + unsigned i; + for (i = 0; i < 15; i++) { + // The precomputed table is assumed to already clear the top bit, so + // |fe_frombytes_strict| may be used directly. + const uint8_t *bytes = &precomp_table[i*(2 * 32)]; + fe x, y; + fe_frombytes_strict(&x, bytes); + fe_frombytes_strict(&y, bytes + 32); + + ge_precomp *out = &multiples[i]; + fe_add(&out->yplusx, &y, &x); + fe_sub(&out->yminusx, &y, &x); + fe_mul_ltt(&out->xy2d, &x, &y); + fe_mul_llt(&out->xy2d, &out->xy2d, &d2); + } + + // See the comment above |k25519SmallPrecomp| about the structure of the + // precomputed elements. This loop does 64 additions and 64 doublings to + // calculate the result. + ge_p3_0(h); + + for (i = 63; i < 64; i--) { + unsigned j; + signed char index = 0; + + for (j = 0; j < 4; j++) { + const uint8_t bit = 1 & (a[(8 * j) + (i / 8)] >> (i & 7)); + index |= (bit << j); + } + + ge_precomp e; + ge_precomp_0(&e); + + for (j = 1; j < 16; j++) { + cmov(&e, &multiples[j-1], equal(index, j)); + } + + ge_cached cached; + ge_p1p1 r; + x25519_ge_p3_to_cached(&cached, h); + x25519_ge_add(&r, h, &cached); + x25519_ge_p1p1_to_p3(h, &r); + + ge_madd(&r, h, &e); + x25519_ge_p1p1_to_p3(h, &r); + } +} + +#if defined(CONFIG_SMALL) + +static void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) { + x25519_ge_scalarmult_small_precomp(h, a, k25519SmallPrecomp); +} + +#else + +static uint8_t negative(signed char b) { + uint32_t x = b; + x >>= 31; // 1: yes; 0: no + return x; +} + +static void table_select(ge_precomp *t, int pos, signed char b) { + ge_precomp minust; + uint8_t bnegative = negative(b); + uint8_t babs = b - ((uint8_t)((-bnegative) & b) << 1); + + ge_precomp_0(t); + cmov(t, &k25519Precomp[pos][0], equal(babs, 1)); + cmov(t, &k25519Precomp[pos][1], equal(babs, 2)); + cmov(t, &k25519Precomp[pos][2], equal(babs, 3)); + cmov(t, &k25519Precomp[pos][3], equal(babs, 4)); + cmov(t, &k25519Precomp[pos][4], equal(babs, 5)); + cmov(t, &k25519Precomp[pos][5], equal(babs, 6)); + cmov(t, &k25519Precomp[pos][6], equal(babs, 7)); + cmov(t, &k25519Precomp[pos][7], equal(babs, 8)); + fe_copy_ll(&minust.yplusx, &t->yminusx); + fe_copy_ll(&minust.yminusx, &t->yplusx); + + // NOTE: the input table is canonical, but types don't encode it + fe tmp; + fe_carry(&tmp, &t->xy2d); + fe_neg(&minust.xy2d, &tmp); + + cmov(t, &minust, bnegative); +} + +// h = a * B +// where a = a[0]+256*a[1]+...+256^31 a[31] +// B is the Ed25519 base point (x,4/5) with x positive. +// +// Preconditions: +// a[31] <= 127 +static void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t *a) { + signed char e[64]; + signed char carry; + ge_p1p1 r; + ge_p2 s; + ge_precomp t; + int i; + + for (i = 0; i < 32; ++i) { + e[2 * i + 0] = (a[i] >> 0) & 15; + e[2 * i + 1] = (a[i] >> 4) & 15; + } + // each e[i] is between 0 and 15 + // e[63] is between 0 and 7 + + carry = 0; + for (i = 0; i < 63; ++i) { + e[i] += carry; + carry = e[i] + 8; + carry >>= 4; + e[i] -= carry << 4; + } + e[63] += carry; + // each e[i] is between -8 and 8 + + ge_p3_0(h); + for (i = 1; i < 64; i += 2) { + table_select(&t, i / 2, e[i]); + ge_madd(&r, h, &t); + x25519_ge_p1p1_to_p3(h, &r); + } + + ge_p3_dbl(&r, h); + x25519_ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); + x25519_ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); + x25519_ge_p1p1_to_p2(&s, &r); + ge_p2_dbl(&r, &s); + x25519_ge_p1p1_to_p3(h, &r); + + for (i = 0; i < 64; i += 2) { + table_select(&t, i / 2, e[i]); + ge_madd(&r, h, &t); + x25519_ge_p1p1_to_p3(h, &r); + } +} + +#endif + +static void cmov_cached(ge_cached *t, ge_cached *u, uint8_t b) { + fe_cmov(&t->YplusX, &u->YplusX, b); + fe_cmov(&t->YminusX, &u->YminusX, b); + fe_cmov(&t->Z, &u->Z, b); + fe_cmov(&t->T2d, &u->T2d, b); +} + +// r = scalar * A. +// where a = a[0]+256*a[1]+...+256^31 a[31]. +static void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, + const ge_p3 *A) { + ge_p2 Ai_p2[8]; + ge_cached Ai[16]; + ge_p1p1 t; + + ge_cached_0(&Ai[0]); + x25519_ge_p3_to_cached(&Ai[1], A); + ge_p3_to_p2(&Ai_p2[1], A); + + unsigned i; + for (i = 2; i < 16; i += 2) { + ge_p2_dbl(&t, &Ai_p2[i / 2]); + ge_p1p1_to_cached(&Ai[i], &t); + if (i < 8) { + x25519_ge_p1p1_to_p2(&Ai_p2[i], &t); + } + x25519_ge_add(&t, A, &Ai[i]); + ge_p1p1_to_cached(&Ai[i + 1], &t); + if (i < 7) { + x25519_ge_p1p1_to_p2(&Ai_p2[i + 1], &t); + } + } + + ge_p2_0(r); + ge_p3 u; + + for (i = 0; i < 256; i += 4) { + ge_p2_dbl(&t, r); + x25519_ge_p1p1_to_p2(r, &t); + ge_p2_dbl(&t, r); + x25519_ge_p1p1_to_p2(r, &t); + ge_p2_dbl(&t, r); + x25519_ge_p1p1_to_p2(r, &t); + ge_p2_dbl(&t, r); + x25519_ge_p1p1_to_p3(&u, &t); + + uint8_t index = scalar[31 - i/8]; + index >>= 4 - (i & 4); + index &= 0xf; + + unsigned j; + ge_cached selected; + ge_cached_0(&selected); + for (j = 0; j < 16; j++) { + cmov_cached(&selected, &Ai[j], equal(j, index)); + } + + x25519_ge_add(&t, &u, &selected); + x25519_ge_p1p1_to_p2(r, &t); + } +} + +// int64_lshift21 returns |a << 21| but is defined when shifting bits into the +// sign bit. This works around a language flaw in C. +static inline int64_t int64_lshift21(int64_t a) { + return (int64_t)((uint64_t)a << 21); +} + +// The set of scalars is \Z/l +// where l = 2^252 + 27742317777372353535851937790883648493. + +// Input: +// s[0]+256*s[1]+...+256^63*s[63] = s +// +// Output: +// s[0]+256*s[1]+...+256^31*s[31] = s mod l +// where l = 2^252 + 27742317777372353535851937790883648493. +// Overwrites s in place. +static void x25519_sc_reduce(uint8_t s[64]) { + int64_t s0 = 2097151 & load_3(s); + int64_t s1 = 2097151 & (load_4(s + 2) >> 5); + int64_t s2 = 2097151 & (load_3(s + 5) >> 2); + int64_t s3 = 2097151 & (load_4(s + 7) >> 7); + int64_t s4 = 2097151 & (load_4(s + 10) >> 4); + int64_t s5 = 2097151 & (load_3(s + 13) >> 1); + int64_t s6 = 2097151 & (load_4(s + 15) >> 6); + int64_t s7 = 2097151 & (load_3(s + 18) >> 3); + int64_t s8 = 2097151 & load_3(s + 21); + int64_t s9 = 2097151 & (load_4(s + 23) >> 5); + int64_t s10 = 2097151 & (load_3(s + 26) >> 2); + int64_t s11 = 2097151 & (load_4(s + 28) >> 7); + int64_t s12 = 2097151 & (load_4(s + 31) >> 4); + int64_t s13 = 2097151 & (load_3(s + 34) >> 1); + int64_t s14 = 2097151 & (load_4(s + 36) >> 6); + int64_t s15 = 2097151 & (load_3(s + 39) >> 3); + int64_t s16 = 2097151 & load_3(s + 42); + int64_t s17 = 2097151 & (load_4(s + 44) >> 5); + int64_t s18 = 2097151 & (load_3(s + 47) >> 2); + int64_t s19 = 2097151 & (load_4(s + 49) >> 7); + int64_t s20 = 2097151 & (load_4(s + 52) >> 4); + int64_t s21 = 2097151 & (load_3(s + 55) >> 1); + int64_t s22 = 2097151 & (load_4(s + 57) >> 6); + int64_t s23 = (load_4(s + 60) >> 3); + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + int64_t carry10; + int64_t carry11; + int64_t carry12; + int64_t carry13; + int64_t carry14; + int64_t carry15; + int64_t carry16; + + s11 += s23 * 666643; + s12 += s23 * 470296; + s13 += s23 * 654183; + s14 -= s23 * 997805; + s15 += s23 * 136657; + s16 -= s23 * 683901; + s23 = 0; + + s10 += s22 * 666643; + s11 += s22 * 470296; + s12 += s22 * 654183; + s13 -= s22 * 997805; + s14 += s22 * 136657; + s15 -= s22 * 683901; + s22 = 0; + + s9 += s21 * 666643; + s10 += s21 * 470296; + s11 += s21 * 654183; + s12 -= s21 * 997805; + s13 += s21 * 136657; + s14 -= s21 * 683901; + s21 = 0; + + s8 += s20 * 666643; + s9 += s20 * 470296; + s10 += s20 * 654183; + s11 -= s20 * 997805; + s12 += s20 * 136657; + s13 -= s20 * 683901; + s20 = 0; + + s7 += s19 * 666643; + s8 += s19 * 470296; + s9 += s19 * 654183; + s10 -= s19 * 997805; + s11 += s19 * 136657; + s12 -= s19 * 683901; + s19 = 0; + + s6 += s18 * 666643; + s7 += s18 * 470296; + s8 += s18 * 654183; + s9 -= s18 * 997805; + s10 += s18 * 136657; + s11 -= s18 * 683901; + s18 = 0; + + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= int64_lshift21(carry6); + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= int64_lshift21(carry8); + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= int64_lshift21(carry10); + carry12 = (s12 + (1 << 20)) >> 21; + s13 += carry12; + s12 -= int64_lshift21(carry12); + carry14 = (s14 + (1 << 20)) >> 21; + s15 += carry14; + s14 -= int64_lshift21(carry14); + carry16 = (s16 + (1 << 20)) >> 21; + s17 += carry16; + s16 -= int64_lshift21(carry16); + + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= int64_lshift21(carry7); + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= int64_lshift21(carry9); + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= int64_lshift21(carry11); + carry13 = (s13 + (1 << 20)) >> 21; + s14 += carry13; + s13 -= int64_lshift21(carry13); + carry15 = (s15 + (1 << 20)) >> 21; + s16 += carry15; + s15 -= int64_lshift21(carry15); + + s5 += s17 * 666643; + s6 += s17 * 470296; + s7 += s17 * 654183; + s8 -= s17 * 997805; + s9 += s17 * 136657; + s10 -= s17 * 683901; + s17 = 0; + + s4 += s16 * 666643; + s5 += s16 * 470296; + s6 += s16 * 654183; + s7 -= s16 * 997805; + s8 += s16 * 136657; + s9 -= s16 * 683901; + s16 = 0; + + s3 += s15 * 666643; + s4 += s15 * 470296; + s5 += s15 * 654183; + s6 -= s15 * 997805; + s7 += s15 * 136657; + s8 -= s15 * 683901; + s15 = 0; + + s2 += s14 * 666643; + s3 += s14 * 470296; + s4 += s14 * 654183; + s5 -= s14 * 997805; + s6 += s14 * 136657; + s7 -= s14 * 683901; + s14 = 0; + + s1 += s13 * 666643; + s2 += s13 * 470296; + s3 += s13 * 654183; + s4 -= s13 * 997805; + s5 += s13 * 136657; + s6 -= s13 * 683901; + s13 = 0; + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = (s0 + (1 << 20)) >> 21; + s1 += carry0; + s0 -= int64_lshift21(carry0); + carry2 = (s2 + (1 << 20)) >> 21; + s3 += carry2; + s2 -= int64_lshift21(carry2); + carry4 = (s4 + (1 << 20)) >> 21; + s5 += carry4; + s4 -= int64_lshift21(carry4); + carry6 = (s6 + (1 << 20)) >> 21; + s7 += carry6; + s6 -= int64_lshift21(carry6); + carry8 = (s8 + (1 << 20)) >> 21; + s9 += carry8; + s8 -= int64_lshift21(carry8); + carry10 = (s10 + (1 << 20)) >> 21; + s11 += carry10; + s10 -= int64_lshift21(carry10); + + carry1 = (s1 + (1 << 20)) >> 21; + s2 += carry1; + s1 -= int64_lshift21(carry1); + carry3 = (s3 + (1 << 20)) >> 21; + s4 += carry3; + s3 -= int64_lshift21(carry3); + carry5 = (s5 + (1 << 20)) >> 21; + s6 += carry5; + s5 -= int64_lshift21(carry5); + carry7 = (s7 + (1 << 20)) >> 21; + s8 += carry7; + s7 -= int64_lshift21(carry7); + carry9 = (s9 + (1 << 20)) >> 21; + s10 += carry9; + s9 -= int64_lshift21(carry9); + carry11 = (s11 + (1 << 20)) >> 21; + s12 += carry11; + s11 -= int64_lshift21(carry11); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; + s1 += carry0; + s0 -= int64_lshift21(carry0); + carry1 = s1 >> 21; + s2 += carry1; + s1 -= int64_lshift21(carry1); + carry2 = s2 >> 21; + s3 += carry2; + s2 -= int64_lshift21(carry2); + carry3 = s3 >> 21; + s4 += carry3; + s3 -= int64_lshift21(carry3); + carry4 = s4 >> 21; + s5 += carry4; + s4 -= int64_lshift21(carry4); + carry5 = s5 >> 21; + s6 += carry5; + s5 -= int64_lshift21(carry5); + carry6 = s6 >> 21; + s7 += carry6; + s6 -= int64_lshift21(carry6); + carry7 = s7 >> 21; + s8 += carry7; + s7 -= int64_lshift21(carry7); + carry8 = s8 >> 21; + s9 += carry8; + s8 -= int64_lshift21(carry8); + carry9 = s9 >> 21; + s10 += carry9; + s9 -= int64_lshift21(carry9); + carry10 = s10 >> 21; + s11 += carry10; + s10 -= int64_lshift21(carry10); + carry11 = s11 >> 21; + s12 += carry11; + s11 -= int64_lshift21(carry11); + + s0 += s12 * 666643; + s1 += s12 * 470296; + s2 += s12 * 654183; + s3 -= s12 * 997805; + s4 += s12 * 136657; + s5 -= s12 * 683901; + s12 = 0; + + carry0 = s0 >> 21; + s1 += carry0; + s0 -= int64_lshift21(carry0); + carry1 = s1 >> 21; + s2 += carry1; + s1 -= int64_lshift21(carry1); + carry2 = s2 >> 21; + s3 += carry2; + s2 -= int64_lshift21(carry2); + carry3 = s3 >> 21; + s4 += carry3; + s3 -= int64_lshift21(carry3); + carry4 = s4 >> 21; + s5 += carry4; + s4 -= int64_lshift21(carry4); + carry5 = s5 >> 21; + s6 += carry5; + s5 -= int64_lshift21(carry5); + carry6 = s6 >> 21; + s7 += carry6; + s6 -= int64_lshift21(carry6); + carry7 = s7 >> 21; + s8 += carry7; + s7 -= int64_lshift21(carry7); + carry8 = s8 >> 21; + s9 += carry8; + s8 -= int64_lshift21(carry8); + carry9 = s9 >> 21; + s10 += carry9; + s9 -= int64_lshift21(carry9); + carry10 = s10 >> 21; + s11 += carry10; + s10 -= int64_lshift21(carry10); + + s[0] = s0 >> 0; + s[1] = s0 >> 8; + s[2] = (s0 >> 16) | (s1 << 5); + s[3] = s1 >> 3; + s[4] = s1 >> 11; + s[5] = (s1 >> 19) | (s2 << 2); + s[6] = s2 >> 6; + s[7] = (s2 >> 14) | (s3 << 7); + s[8] = s3 >> 1; + s[9] = s3 >> 9; + s[10] = (s3 >> 17) | (s4 << 4); + s[11] = s4 >> 4; + s[12] = s4 >> 12; + s[13] = (s4 >> 20) | (s5 << 1); + s[14] = s5 >> 7; + s[15] = (s5 >> 15) | (s6 << 6); + s[16] = s6 >> 2; + s[17] = s6 >> 10; + s[18] = (s6 >> 18) | (s7 << 3); + s[19] = s7 >> 5; + s[20] = s7 >> 13; + s[21] = s8 >> 0; + s[22] = s8 >> 8; + s[23] = (s8 >> 16) | (s9 << 5); + s[24] = s9 >> 3; + s[25] = s9 >> 11; + s[26] = (s9 >> 19) | (s10 << 2); + s[27] = s10 >> 6; + s[28] = (s10 >> 14) | (s11 << 7); + s[29] = s11 >> 1; + s[30] = s11 >> 9; + s[31] = s11 >> 17; +} + +/* Loosely from BoringSSL crypto/curve25519/spake25519.c */ + +/* + * Here BoringSSL uses different points, not restricted to the generator + * subgroup, while we use the draft-irtf-cfrg-spake2-05 points. The Python + * code is modified to add the subgroup restriction. + */ + +// The following precomputation tables are for the following +// points: +// +// N (found in 7 iterations): +// x: 10742253510813957597047979962966927467575235974254765187031601461055699024931 +// y: 19796686047937480651099107989427797822652529149428697746066532921705571401683 +// encoded: d3bfb518f44f3430f29d0c92af503865a1ed3281dc69b35dd868ba85f886c4ab +// +// M (found in 21 iterations): +// x: 8158688967149231307266666683326742915289288280191350817196911733632187385319 +// y: 21622333750659878624441478467798461427617029906629724657331223068277098105040 +// encoded: d048032c6ea0b6d697ddc2e86bda85a33adac920f1bf18e1b0c6d166a5cecdaf +// +// These points and their precomputation tables are generated with the +// following Python code. + +/* +import hashlib +import ed25519 as E # https://ed25519.cr.yp.to/python/ed25519.py + +SEED_N = 'edwards25519 point generation seed (N)' +SEED_M = 'edwards25519 point generation seed (M)' + +def genpoint(seed): + v = hashlib.sha256(seed).digest() + it = 1 + while True: + try: + x,y = E.decodepoint(v) + if E.scalarmult((x,y), E.l) != [0, 1]: + raise Exception('point has wrong order') + except Exception, e: + print e + it += 1 + v = hashlib.sha256(v).digest() + continue + print "Found in %d iterations:" % it + print " x = %d" % x + print " y = %d" % y + print " Encoded (hex)" + print E.encodepoint((x,y)).encode('hex') + return (x,y) + +def gentable(P): + t = [] + for i in range(1,16): + k = (i >> 3 & 1) * (1 << 192) + \ + (i >> 2 & 1) * (1 << 128) + \ + (i >> 1 & 1) * (1 << 64) + \ + (i & 1) + t.append(E.scalarmult(P, k)) + return ''.join(E.encodeint(x) + E.encodeint(y) for (x,y) in t) + +def printtable(table, name): + print "static const uint8_t %s[15 * 2 * 32] = {" % name, + for i in range(15 * 2 * 32): + if i % 12 == 0: + print "\n ", + print " 0x%02x," % ord(table[i]), + print "\n};" + +if __name__ == "__main__": + print "Searching for N" + N = genpoint(SEED_N) + print "Generating precomputation table for N" + Ntable = gentable(N) + printtable(Ntable, "kSpakeNSmallPrecomp") + + print "Searching for M" + M = genpoint(SEED_M) + print "Generating precomputation table for M" + Mtable = gentable(M) + printtable(Mtable, "kSpakeMSmallPrecomp") +*/ + +static const uint8_t kSpakeNSmallPrecomp[15 * 2 * 32] = { + 0x23, 0xfc, 0x27, 0x6c, 0x55, 0xaf, 0xb3, 0x9c, 0xd8, 0x99, 0x3a, 0x0d, + 0x7f, 0x08, 0xc9, 0xeb, 0x4d, 0x6e, 0x90, 0x99, 0x2f, 0x3c, 0x15, 0x2b, + 0x89, 0x5a, 0x0f, 0xf2, 0x67, 0xe6, 0xbf, 0x17, 0xd3, 0xbf, 0xb5, 0x18, + 0xf4, 0x4f, 0x34, 0x30, 0xf2, 0x9d, 0x0c, 0x92, 0xaf, 0x50, 0x38, 0x65, + 0xa1, 0xed, 0x32, 0x81, 0xdc, 0x69, 0xb3, 0x5d, 0xd8, 0x68, 0xba, 0x85, + 0xf8, 0x86, 0xc4, 0x2b, 0x53, 0x93, 0xb1, 0x99, 0x90, 0x30, 0xca, 0xb0, + 0xbd, 0xea, 0x14, 0x4c, 0x6f, 0x2b, 0x81, 0x1e, 0x23, 0x45, 0xb2, 0x32, + 0x2e, 0x2d, 0xe6, 0xb8, 0x5d, 0xc5, 0x15, 0x91, 0x63, 0x39, 0x18, 0x5b, + 0x62, 0x63, 0x9b, 0xf4, 0x8b, 0xe0, 0x34, 0xa2, 0x95, 0x11, 0x92, 0x68, + 0x54, 0xb7, 0xf3, 0x91, 0xca, 0x22, 0xad, 0x08, 0xd8, 0x9c, 0xa2, 0xf0, + 0xdc, 0x9c, 0x2c, 0x84, 0x32, 0x26, 0xe0, 0x17, 0x89, 0x53, 0x6b, 0xfd, + 0x76, 0x97, 0x25, 0xea, 0x99, 0x94, 0xf8, 0x29, 0x7c, 0xc4, 0x53, 0xc0, + 0x98, 0x9a, 0x20, 0xdc, 0x70, 0x01, 0x50, 0xaa, 0x05, 0xa3, 0x40, 0x50, + 0x66, 0x87, 0x30, 0x19, 0x12, 0xc3, 0xb8, 0x2d, 0x28, 0x8b, 0x7b, 0x48, + 0xf7, 0x7b, 0xab, 0x45, 0x70, 0x2e, 0xbb, 0x85, 0xc1, 0x6c, 0xdd, 0x35, + 0x00, 0x83, 0x20, 0x13, 0x82, 0x08, 0xaa, 0xa3, 0x03, 0x0f, 0xca, 0x27, + 0x3e, 0x8b, 0x52, 0xc2, 0xd7, 0xb1, 0x8c, 0x22, 0xfe, 0x04, 0x4a, 0xf2, + 0xe8, 0xac, 0xee, 0x2e, 0xd7, 0x77, 0x34, 0x49, 0xf2, 0xe9, 0xeb, 0x8c, + 0xa6, 0xc8, 0xc6, 0xcd, 0x8a, 0x8f, 0x7c, 0x5d, 0x51, 0xc8, 0xfa, 0x6f, + 0xb3, 0x93, 0xdb, 0x71, 0xef, 0x3e, 0x6e, 0xa7, 0x85, 0xc7, 0xd4, 0x3e, + 0xa2, 0xe2, 0xc0, 0xaa, 0x17, 0xb3, 0xa4, 0x7c, 0xc2, 0x3f, 0x7c, 0x7a, + 0xdd, 0x26, 0xde, 0x3e, 0xf1, 0x99, 0x06, 0xf7, 0x69, 0x1b, 0xc9, 0x20, + 0x55, 0x4f, 0x86, 0x7a, 0x93, 0x89, 0x68, 0xe9, 0x2b, 0x2d, 0xbc, 0x08, + 0x15, 0x5d, 0x2d, 0x0b, 0x4f, 0x1a, 0xb3, 0xd4, 0x8e, 0x77, 0x79, 0x2a, + 0x25, 0xf9, 0xb6, 0x46, 0xfb, 0x87, 0x02, 0xa6, 0xe0, 0xd3, 0xba, 0x84, + 0xea, 0x3e, 0x58, 0xa5, 0x7f, 0x8f, 0x8c, 0x39, 0x79, 0x28, 0xb5, 0xcf, + 0xe4, 0xca, 0x63, 0xdc, 0xac, 0xed, 0x4b, 0x74, 0x1e, 0x94, 0x85, 0x8c, + 0xe5, 0xf4, 0x76, 0x6f, 0x20, 0x67, 0x8b, 0xd8, 0xd6, 0x4b, 0xe7, 0x2d, + 0xa0, 0xbd, 0xcc, 0x1f, 0xdf, 0x46, 0x9c, 0xa2, 0x49, 0x64, 0xdf, 0x24, + 0x00, 0x11, 0x11, 0x45, 0x62, 0x5c, 0xd7, 0x8a, 0x00, 0x02, 0xf5, 0x9b, + 0x4f, 0x53, 0x42, 0xc5, 0xd5, 0x55, 0x80, 0x73, 0x9a, 0x5b, 0x31, 0x5a, + 0xbd, 0x3a, 0x43, 0xe9, 0x33, 0xe5, 0xaf, 0x1d, 0x92, 0x5e, 0x59, 0x37, + 0xae, 0x57, 0xfa, 0x3b, 0xd2, 0x31, 0xae, 0xa6, 0xf9, 0xc9, 0xc1, 0x82, + 0xa6, 0xa5, 0xed, 0x24, 0x53, 0x4b, 0x38, 0x22, 0xf2, 0x85, 0x8d, 0x13, + 0xa6, 0x5e, 0xd6, 0x57, 0x17, 0xd3, 0x33, 0x38, 0x8d, 0x65, 0xd3, 0xcb, + 0x1a, 0xa2, 0x3a, 0x2b, 0xbb, 0x61, 0x53, 0xd7, 0xff, 0xcd, 0x20, 0xb6, + 0xbb, 0x8c, 0xab, 0x63, 0xef, 0xb8, 0x26, 0x7e, 0x81, 0x65, 0xaf, 0x90, + 0xfc, 0xd2, 0xb6, 0x72, 0xdb, 0xe9, 0x23, 0x78, 0x12, 0x04, 0xc0, 0x03, + 0x82, 0xa8, 0x7a, 0x0f, 0x48, 0x6f, 0x82, 0x7f, 0x81, 0xcd, 0xa7, 0x89, + 0xdd, 0x86, 0xea, 0x5e, 0xa1, 0x50, 0x14, 0x34, 0x17, 0x64, 0x82, 0x0f, + 0xc4, 0x40, 0x20, 0x1d, 0x8f, 0xfe, 0xfa, 0x99, 0xaf, 0x5b, 0xc1, 0x5d, + 0xc8, 0x47, 0x07, 0x54, 0x4a, 0x22, 0x56, 0x57, 0xf1, 0x2c, 0x3b, 0x62, + 0x7f, 0x12, 0x62, 0xaf, 0xfd, 0xf8, 0x04, 0x11, 0xa8, 0x51, 0xf0, 0x46, + 0x5d, 0x79, 0x66, 0xff, 0x8a, 0x06, 0xef, 0x54, 0x64, 0x1b, 0x84, 0x3e, + 0x41, 0xf3, 0xfe, 0x19, 0x51, 0xf7, 0x44, 0x9c, 0x16, 0xd3, 0x7a, 0x09, + 0x59, 0xf5, 0x47, 0x45, 0xd0, 0x31, 0xef, 0x96, 0x2c, 0xc5, 0xc0, 0xd0, + 0x56, 0xef, 0x3f, 0x07, 0x2b, 0xb7, 0x28, 0x49, 0xf5, 0xb1, 0x42, 0x18, + 0xcf, 0x77, 0xd8, 0x2b, 0x71, 0x74, 0x80, 0xba, 0x34, 0x52, 0xce, 0x11, + 0xfe, 0xc4, 0xb9, 0xeb, 0xf9, 0xc4, 0x5e, 0x1f, 0xd3, 0xde, 0x4b, 0x14, + 0xe3, 0x6e, 0xe7, 0xd7, 0x83, 0x59, 0x98, 0xe8, 0x3d, 0x8e, 0xd6, 0x7d, + 0xc0, 0x9a, 0x79, 0xb9, 0x83, 0xf1, 0xc1, 0x00, 0x5d, 0x16, 0x1b, 0x44, + 0xe9, 0x02, 0xce, 0x99, 0x1e, 0x77, 0xef, 0xca, 0xbc, 0xf0, 0x6a, 0xb9, + 0x65, 0x3f, 0x3c, 0xd9, 0xe1, 0x63, 0x0b, 0xbf, 0xaa, 0xa7, 0xe6, 0x6d, + 0x6d, 0x3f, 0x44, 0x29, 0xa3, 0x8b, 0x6d, 0xc4, 0x81, 0xa9, 0xc3, 0x5a, + 0x90, 0x55, 0x72, 0x61, 0x17, 0x22, 0x7f, 0x3e, 0x5f, 0xfc, 0xba, 0xb3, + 0x7a, 0x99, 0x76, 0xe9, 0x20, 0xe5, 0xc5, 0xe8, 0x55, 0x56, 0x0f, 0x7a, + 0x48, 0xe7, 0xbc, 0xe1, 0x13, 0xf4, 0x90, 0xef, 0x97, 0x6c, 0x02, 0x89, + 0x4d, 0x22, 0x48, 0xda, 0xd3, 0x52, 0x45, 0x31, 0x26, 0xcc, 0xe8, 0x9e, + 0x5d, 0xdd, 0x75, 0xe4, 0x1d, 0xbc, 0xb1, 0x08, 0x55, 0xaf, 0x54, 0x70, + 0x0d, 0x0c, 0xf3, 0x50, 0xbc, 0x40, 0x83, 0xee, 0xdc, 0x6d, 0x8b, 0x40, + 0x79, 0x62, 0x18, 0x37, 0xc4, 0x78, 0x02, 0x58, 0x7c, 0x78, 0xd3, 0x54, + 0xed, 0x31, 0xbd, 0x7d, 0x48, 0xcf, 0xb6, 0x11, 0x27, 0x37, 0x9c, 0x86, + 0xf7, 0x2e, 0x00, 0x7a, 0x48, 0x1b, 0xa6, 0x72, 0x70, 0x7b, 0x44, 0x45, + 0xeb, 0x49, 0xbf, 0xbe, 0x09, 0x78, 0x66, 0x71, 0x12, 0x7f, 0x3d, 0x78, + 0x51, 0x24, 0x82, 0xa2, 0xf0, 0x1e, 0x83, 0x81, 0x81, 0x45, 0x53, 0xfd, + 0x5e, 0xf3, 0x03, 0x74, 0xbd, 0x23, 0x35, 0xf6, 0x10, 0xdd, 0x7c, 0x73, + 0x46, 0x32, 0x09, 0x54, 0x99, 0x95, 0x91, 0x25, 0xb8, 0x32, 0x09, 0xd8, + 0x2f, 0x97, 0x50, 0xa3, 0xf5, 0xd6, 0xb1, 0xed, 0x97, 0x51, 0x06, 0x42, + 0x12, 0x0c, 0x69, 0x38, 0x09, 0xa0, 0xd8, 0x19, 0x70, 0xf7, 0x8f, 0x61, + 0x0d, 0x56, 0x43, 0x66, 0x22, 0x8b, 0x0e, 0x0e, 0xf9, 0x81, 0x9f, 0xac, + 0x6f, 0xbf, 0x7d, 0x04, 0x13, 0xf2, 0xe4, 0xeb, 0xfd, 0xbe, 0x4e, 0x56, + 0xda, 0xe0, 0x22, 0x6d, 0x1b, 0x25, 0xc8, 0xa5, 0x9c, 0x05, 0x45, 0x52, + 0x3c, 0x3a, 0xde, 0x6b, 0xac, 0x9b, 0xf8, 0x81, 0x97, 0x21, 0x46, 0xac, + 0x7e, 0x89, 0xf8, 0x49, 0x58, 0xbb, 0x45, 0xac, 0xa2, 0xc4, 0x90, 0x1f, + 0xb2, 0xb4, 0xf8, 0xe0, 0xcd, 0xa1, 0x9d, 0x1c, 0xf2, 0xf1, 0xdf, 0xfb, + 0x88, 0x4e, 0xe5, 0x41, 0xd8, 0x6e, 0xac, 0x07, 0x87, 0x95, 0x35, 0xa6, + 0x12, 0x08, 0x5d, 0x57, 0x5e, 0xaf, 0x71, 0x0f, 0x07, 0x4e, 0x81, 0x77, + 0xf1, 0xef, 0xb5, 0x35, 0x5c, 0xfa, 0xf4, 0x4e, 0x42, 0xdc, 0x19, 0xfe, + 0xe4, 0xd2, 0xb4, 0x27, 0xfb, 0x34, 0x1f, 0xb2, 0x6f, 0xf2, 0x95, 0xcc, + 0xd4, 0x47, 0x63, 0xdc, 0x7e, 0x4f, 0x97, 0x2b, 0x7a, 0xe0, 0x80, 0x31, +}; + +static const uint8_t kSpakeMSmallPrecomp[15 * 2 * 32] = { + 0xe7, 0x45, 0x7e, 0x47, 0x49, 0x69, 0xbd, 0x1b, 0x35, 0x1c, 0x2c, 0x98, + 0x03, 0xf3, 0xb3, 0x37, 0xde, 0x39, 0xa5, 0xda, 0xc0, 0x2e, 0xa4, 0xac, + 0x7d, 0x08, 0x26, 0xfc, 0x80, 0xa7, 0x09, 0x12, 0xd0, 0x48, 0x03, 0x2c, + 0x6e, 0xa0, 0xb6, 0xd6, 0x97, 0xdd, 0xc2, 0xe8, 0x6b, 0xda, 0x85, 0xa3, + 0x3a, 0xda, 0xc9, 0x20, 0xf1, 0xbf, 0x18, 0xe1, 0xb0, 0xc6, 0xd1, 0x66, + 0xa5, 0xce, 0xcd, 0x2f, 0x80, 0xa8, 0x4e, 0xc3, 0x81, 0xae, 0x68, 0x3b, + 0x0d, 0xdb, 0x56, 0x32, 0x2f, 0xa8, 0x97, 0xa0, 0x5c, 0x15, 0xc1, 0xcb, + 0x6f, 0x7a, 0x5f, 0xc5, 0x32, 0xfb, 0x49, 0x17, 0x18, 0xfa, 0x85, 0x08, + 0x85, 0xf1, 0xe3, 0x11, 0x8e, 0x3d, 0x70, 0x20, 0x38, 0x4e, 0x0c, 0x17, + 0xa1, 0xa8, 0x20, 0xd2, 0xb1, 0x1d, 0x05, 0x8d, 0x0f, 0xc9, 0x96, 0x18, + 0x9d, 0x8c, 0x89, 0x8f, 0x46, 0x6a, 0x6c, 0x6e, 0x72, 0x03, 0xb2, 0x75, + 0x87, 0xd8, 0xa9, 0x60, 0x93, 0x2b, 0x8b, 0x66, 0xee, 0xaf, 0xce, 0x98, + 0xcd, 0x6b, 0x7c, 0x6a, 0xbe, 0x19, 0xda, 0x66, 0x7c, 0xda, 0x53, 0xa0, + 0xe3, 0x9a, 0x0e, 0x53, 0x3a, 0x7c, 0x73, 0x4a, 0x37, 0xa6, 0x53, 0x23, + 0x67, 0x31, 0xce, 0x8a, 0xab, 0xee, 0x72, 0x76, 0xc2, 0xb5, 0x54, 0x42, + 0xcf, 0x4b, 0xc7, 0x53, 0x24, 0x59, 0xaf, 0x76, 0x53, 0x10, 0x7e, 0x25, + 0x94, 0x5c, 0x23, 0xa6, 0x5e, 0x05, 0xea, 0x14, 0xad, 0x2b, 0xce, 0x50, + 0x77, 0xb3, 0x7a, 0x88, 0x4c, 0xf7, 0x74, 0x04, 0x35, 0xa4, 0x0c, 0x9e, + 0xee, 0x6a, 0x4c, 0x3c, 0xc1, 0x6a, 0x35, 0x4d, 0x6d, 0x8f, 0x94, 0x95, + 0xe4, 0x10, 0xca, 0x46, 0x4e, 0xfa, 0x38, 0x40, 0xeb, 0x1a, 0x1b, 0x5a, + 0xff, 0x73, 0x4d, 0xe9, 0xf2, 0xbe, 0x89, 0xf5, 0xd1, 0x72, 0xd0, 0x1a, + 0x7b, 0x82, 0x08, 0x19, 0xda, 0x54, 0x44, 0xa5, 0x3d, 0xd8, 0x10, 0x1c, + 0xcf, 0x3b, 0xc7, 0x54, 0xd5, 0x11, 0xd7, 0x2a, 0x69, 0x3f, 0xa6, 0x58, + 0x74, 0xfd, 0x90, 0xb2, 0xf4, 0xc2, 0x0e, 0xf3, 0x19, 0x8f, 0x51, 0x7c, + 0x31, 0x12, 0x79, 0x61, 0x16, 0xb4, 0x2f, 0x2f, 0xd0, 0x88, 0x97, 0xf2, + 0xc3, 0x8c, 0xa6, 0xa3, 0x29, 0xff, 0x7e, 0x12, 0x46, 0x2a, 0x9c, 0x09, + 0x7c, 0x5f, 0x87, 0x07, 0x6b, 0xa1, 0x9a, 0x57, 0x55, 0x8e, 0xb0, 0x56, + 0x5d, 0xc9, 0x4c, 0x5b, 0xae, 0xd3, 0xd0, 0x8e, 0xb8, 0xac, 0xba, 0xe8, + 0x54, 0x45, 0x30, 0x14, 0xf6, 0x59, 0x20, 0xc4, 0x03, 0xb7, 0x7a, 0x5d, + 0x6b, 0x5a, 0xcb, 0x28, 0x60, 0xf8, 0xef, 0x61, 0x60, 0x78, 0x6b, 0xf5, + 0x21, 0x4b, 0x75, 0xc2, 0x77, 0xba, 0x0e, 0x38, 0x98, 0xe0, 0xfb, 0xb7, + 0x5f, 0x75, 0x87, 0x04, 0x0c, 0xb4, 0x5c, 0x09, 0x04, 0x00, 0x38, 0x4e, + 0x4f, 0x7b, 0x73, 0xe5, 0xdb, 0xdb, 0xf1, 0xf4, 0x5c, 0x64, 0x68, 0xfd, + 0xb1, 0x86, 0xe8, 0x89, 0xbe, 0x9c, 0xd4, 0x96, 0x1d, 0xcb, 0xdc, 0x5c, + 0xef, 0xd4, 0x33, 0x28, 0xb9, 0xb6, 0xaf, 0x3b, 0xcf, 0x8d, 0x30, 0xba, + 0xe8, 0x08, 0xcf, 0x84, 0xba, 0x61, 0x10, 0x9b, 0x62, 0xf6, 0x18, 0x79, + 0x66, 0x87, 0x82, 0x7c, 0xaa, 0x71, 0xac, 0xd0, 0xd0, 0x32, 0xb0, 0x54, + 0x03, 0xa4, 0xad, 0x3f, 0x72, 0xca, 0x22, 0xff, 0x01, 0x87, 0x08, 0x36, + 0x61, 0x22, 0xaa, 0x18, 0xab, 0x3a, 0xbc, 0xf2, 0x78, 0x05, 0xe1, 0x99, + 0xa3, 0x59, 0x98, 0xcc, 0x21, 0xc6, 0x2b, 0x51, 0x6d, 0x43, 0x0a, 0x46, + 0x50, 0xae, 0x11, 0x7e, 0xd5, 0x23, 0x56, 0xef, 0x83, 0xc8, 0xbf, 0x42, + 0xf0, 0x45, 0x52, 0x1f, 0x34, 0xbc, 0x2f, 0xb0, 0xf0, 0xce, 0xf0, 0xec, + 0xd0, 0x99, 0x59, 0x2e, 0x1f, 0xab, 0xa8, 0x1e, 0x4b, 0xce, 0x1b, 0x9a, + 0x75, 0xc6, 0xc4, 0x71, 0x86, 0xf0, 0x8d, 0xec, 0xb0, 0x30, 0xb9, 0x62, + 0xb3, 0xb7, 0xdd, 0x96, 0x29, 0xc8, 0xbf, 0xe9, 0xb0, 0x74, 0x78, 0x7b, + 0xf7, 0xea, 0xa3, 0x14, 0x12, 0x56, 0xe0, 0xf3, 0x35, 0x7a, 0x26, 0x4a, + 0x4c, 0xe6, 0xdf, 0x13, 0xb5, 0x52, 0xb0, 0x2a, 0x5f, 0x2e, 0xac, 0x34, + 0xab, 0x5f, 0x1a, 0x01, 0xe4, 0x15, 0x1a, 0xd1, 0xbf, 0xc9, 0x95, 0x0a, + 0xac, 0x1d, 0xe7, 0x53, 0x59, 0x8d, 0xc3, 0x21, 0x78, 0x5e, 0x12, 0x97, + 0x8f, 0x4e, 0x1d, 0xf9, 0xe5, 0xe2, 0xc2, 0xc4, 0xba, 0xfb, 0x50, 0x96, + 0x5b, 0x43, 0xe8, 0xf7, 0x0d, 0x1b, 0x64, 0x58, 0xbe, 0xd3, 0x95, 0x7f, + 0x8e, 0xf1, 0x85, 0x35, 0xba, 0x25, 0x55, 0x2e, 0x02, 0x46, 0x5c, 0xad, + 0x1f, 0xc5, 0x03, 0xcc, 0xd0, 0x43, 0x4c, 0xf2, 0x5e, 0x64, 0x0a, 0x89, + 0xd9, 0xfd, 0x23, 0x7d, 0x4f, 0xbe, 0x2f, 0x0f, 0x1e, 0x12, 0x4a, 0xd9, + 0xf8, 0x82, 0xde, 0x8f, 0x4f, 0x98, 0xb9, 0x90, 0xf6, 0xfa, 0xd1, 0x11, + 0xa6, 0xdc, 0x7e, 0x32, 0x48, 0x6a, 0x8a, 0x14, 0x5e, 0x73, 0xb9, 0x6c, + 0x0e, 0xc2, 0xf9, 0xcc, 0xf0, 0x32, 0xc8, 0xb5, 0x56, 0xaa, 0x5d, 0xd2, + 0x07, 0xf1, 0x6f, 0x33, 0x6f, 0x05, 0x70, 0x49, 0x60, 0x49, 0x23, 0x23, + 0x14, 0x0e, 0x4c, 0x58, 0x92, 0xad, 0xa9, 0x50, 0xb1, 0x59, 0x43, 0x96, + 0x7b, 0xc1, 0x51, 0x45, 0xef, 0x0d, 0xef, 0xd1, 0xe4, 0xd0, 0xce, 0xdf, + 0x6a, 0xbc, 0x1b, 0xbf, 0x7a, 0x87, 0x4e, 0x47, 0x17, 0x9c, 0x34, 0x38, + 0xb0, 0x3c, 0xa1, 0x04, 0xfb, 0xe2, 0x66, 0xce, 0xb6, 0x82, 0xbb, 0xad, + 0xc3, 0x8e, 0x12, 0x35, 0xbc, 0x17, 0xce, 0x01, 0x2d, 0xa3, 0xa6, 0xb9, + 0xfa, 0x84, 0xc2, 0x2f, 0x5a, 0x4a, 0x8c, 0x4c, 0x11, 0x4e, 0xa8, 0x14, + 0xcb, 0xb8, 0x99, 0xaa, 0x2e, 0x8c, 0xa0, 0xc9, 0x5f, 0x62, 0x2a, 0x84, + 0x66, 0x60, 0x0a, 0x7e, 0xdc, 0x93, 0x17, 0x45, 0x19, 0xb3, 0x93, 0x4c, + 0xdc, 0xd0, 0xd5, 0x5c, 0x25, 0xd2, 0xcd, 0x4e, 0x84, 0x4c, 0x73, 0xb3, + 0x90, 0xa4, 0x22, 0x05, 0x2c, 0x7c, 0x39, 0x2b, 0x70, 0xd9, 0x61, 0x76, + 0xb2, 0x03, 0x71, 0xe9, 0x0e, 0xf8, 0x57, 0x85, 0xad, 0xb1, 0x2f, 0x34, + 0xa5, 0x66, 0xb0, 0x0f, 0x75, 0x94, 0x6e, 0x26, 0x79, 0x99, 0xb4, 0xe2, + 0xe2, 0xa3, 0x58, 0xdd, 0xb4, 0xfb, 0x74, 0xf4, 0xa1, 0xca, 0xc3, 0x30, + 0xe7, 0x86, 0xb2, 0xa2, 0x2c, 0x11, 0xc9, 0x58, 0xe3, 0xc1, 0xa6, 0x5f, + 0x86, 0x6a, 0xe7, 0x75, 0xd5, 0xd8, 0x63, 0x95, 0x64, 0x59, 0xbc, 0xb8, + 0xb7, 0xf5, 0x12, 0xe3, 0x03, 0xc6, 0x17, 0xea, 0x4e, 0xcb, 0xee, 0x4c, + 0xae, 0x03, 0xd1, 0x33, 0xd0, 0x39, 0x36, 0x00, 0x0f, 0xf4, 0x9c, 0xbd, + 0x35, 0x96, 0xfd, 0x0d, 0x26, 0xb7, 0x9e, 0xf4, 0x4b, 0x6f, 0x4b, 0xf1, + 0xec, 0x11, 0x00, 0x16, 0x21, 0x1e, 0xd4, 0x43, 0x23, 0x8c, 0x4a, 0xfa, + 0x9e, 0xd4, 0x2b, 0x36, 0x9a, 0x43, 0x1e, 0x58, 0x31, 0xe8, 0x1f, 0x83, + 0x15, 0x20, 0x31, 0x68, 0xfe, 0x27, 0xd3, 0xd8, 0x9b, 0x43, 0x81, 0x8f, + 0x57, 0x32, 0x14, 0xe6, 0x9e, 0xbf, 0xd1, 0xfb, 0xdf, 0xad, 0x7a, 0x52, +}; + +/* left_shift_3 sets |n| to |n|*8, where |n| is represented in little-endian + * order. */ +static void left_shift_3(uint8_t n[32]) { + uint8_t carry = 0; + unsigned i; + + for (i = 0; i < 32; i++) { + const uint8_t next_carry = n[i] >> 5; + n[i] = (n[i] << 3) | carry; + carry = next_carry; + } +} + +static krb5_error_code +builtin_edwards25519_keygen(krb5_context context, groupdata *gdata, + const uint8_t *wbytes, krb5_boolean use_m, + uint8_t *priv_out, uint8_t *pub_out) +{ + uint8_t private[64]; + krb5_data data = make_data(private, 32); + krb5_error_code ret; + + /* Pick x or y uniformly from [0, p*h) divisible by h. */ + ret = krb5_c_random_make_octets(context, &data); + if (ret) + return ret; + memset(private + 32, 0, 32); + x25519_sc_reduce(private); + left_shift_3(private); + + /* Compute X=x*G or Y=y*G. */ + ge_p3 P; + x25519_ge_scalarmult_base(&P, private); + + /* Compute w mod p. */ + uint8_t wreduced[64]; + memcpy(wreduced, wbytes, 32); + memset(wreduced + 32, 0, 32); + x25519_sc_reduce(wreduced); + + /* Compute the mask, w*M or w*N. */ + ge_p3 mask; + x25519_ge_scalarmult_small_precomp(&mask, wreduced, + use_m ? kSpakeMSmallPrecomp : + kSpakeNSmallPrecomp); + + /* Compute the masked point T=w*M+X or S=w*N+Y. */ + ge_cached mask_cached; + x25519_ge_p3_to_cached(&mask_cached, &mask); + ge_p1p1 Pmasked; + x25519_ge_add(&Pmasked, &P, &mask_cached); + + /* Encode T or S into pub_out. */ + ge_p2 Pmasked_proj; + x25519_ge_p1p1_to_p2(&Pmasked_proj, &Pmasked); + x25519_ge_tobytes(pub_out, &Pmasked_proj); + + /* Remember the private key in priv_out. */ + memcpy(priv_out, private, 32); + return 0; +} + +static krb5_error_code +builtin_edwards25519_result(krb5_context context, groupdata *gdata, + const uint8_t *wbytes, const uint8_t *ourpriv, + const uint8_t *theirpub, krb5_boolean use_m, + uint8_t *elem_out) +{ + /* + * Check if the point received from peer is on the curve. This does not + * verify that it is in the generator subgroup, but since our private key is + * a multiple of the cofactor, the shared point will be in the generator + * subgroup even if a rogue peer sends a point which is not. + */ + ge_p3 Qmasked; + if (!x25519_ge_frombytes_vartime(&Qmasked, theirpub)) + return EINVAL; + + /* Compute w mod p. */ + uint8_t wreduced[64]; + memcpy(wreduced, wbytes, 32); + memset(wreduced + 32, 0, 32); + x25519_sc_reduce(wreduced); + + /* Compute the peer's mask, w*M or w*N. */ + ge_p3 peers_mask; + x25519_ge_scalarmult_small_precomp(&peers_mask, wreduced, + use_m ? kSpakeMSmallPrecomp : + kSpakeNSmallPrecomp); + + ge_cached peers_mask_cached; + x25519_ge_p3_to_cached(&peers_mask_cached, &peers_mask); + + /* Compute the peer's unmasked point, T-w*M or S-w*N. */ + ge_p1p1 Qcompl; + ge_p3 Qunmasked; + x25519_ge_sub(&Qcompl, &Qmasked, &peers_mask_cached); + x25519_ge_p1p1_to_p3(&Qunmasked, &Qcompl); + + /* Multiply by our private value to compute K=x*(S-w*N) or K=y*(T-w*M). */ + ge_p2 K; + x25519_ge_scalarmult(&K, ourpriv, &Qunmasked); + + /* Encode K into elem_out. */ + x25519_ge_tobytes(elem_out, &K); + return 0; +} + +static krb5_error_code +builtin_sha256(krb5_context context, groupdata *gdata, const krb5_data *dlist, + size_t ndata, uint8_t *result_out) +{ + return k5_sha256(dlist, ndata, result_out); +} + +groupdef builtin_edwards25519 = { + .reg = &spake_iana_edwards25519, + .keygen = builtin_edwards25519_keygen, + .result = builtin_edwards25519_result, + .hash = builtin_sha256 +}; diff --git a/krb5-1.21.3/src/plugins/preauth/spake/edwards25519_fiat.h b/krb5-1.21.3/src/plugins/preauth/spake/edwards25519_fiat.h new file mode 100644 index 00000000..48ade921 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/edwards25519_fiat.h @@ -0,0 +1,1289 @@ +#if defined(BORINGSSL_CURVE25519_64BIT) + +/* Autogenerated */ +/* curve description: 25519 */ +/* requested operations: carry_mul, carry_square, carry_scmul121666, carry, add, sub, opp, selectznz, to_bytes, from_bytes */ +/* n = 5 (from "5") */ +/* s = 0x8000000000000000000000000000000000000000000000000000000000000000 (from "2^255") */ +/* c = [(1, 19)] (from "1,19") */ +/* machine_wordsize = 64 (from "64") */ + +#include +typedef unsigned char fiat_25519_uint1; +typedef signed char fiat_25519_int1; +typedef int128_t fiat_25519_int128; +typedef uint128_t fiat_25519_uint128; + + +/* + * Input Bounds: + * arg1: [0x0 ~> 0x1] + * arg2: [0x0 ~> 0x7ffffffffffff] + * arg3: [0x0 ~> 0x7ffffffffffff] + * Output Bounds: + * out1: [0x0 ~> 0x7ffffffffffff] + * out2: [0x0 ~> 0x1] + */ +static void fiat_25519_addcarryx_u51(uint64_t* out1, fiat_25519_uint1* out2, fiat_25519_uint1 arg1, uint64_t arg2, uint64_t arg3) { + uint64_t x1 = ((arg1 + arg2) + arg3); + uint64_t x2 = (x1 & UINT64_C(0x7ffffffffffff)); + fiat_25519_uint1 x3 = (fiat_25519_uint1)(x1 >> 51); + *out1 = x2; + *out2 = x3; +} + +/* + * Input Bounds: + * arg1: [0x0 ~> 0x1] + * arg2: [0x0 ~> 0x7ffffffffffff] + * arg3: [0x0 ~> 0x7ffffffffffff] + * Output Bounds: + * out1: [0x0 ~> 0x7ffffffffffff] + * out2: [0x0 ~> 0x1] + */ +static void fiat_25519_subborrowx_u51(uint64_t* out1, fiat_25519_uint1* out2, fiat_25519_uint1 arg1, uint64_t arg2, uint64_t arg3) { + int64_t x1 = ((int64_t)(arg2 - (int64_t)arg1) - (int64_t)arg3); + fiat_25519_int1 x2 = (fiat_25519_int1)(x1 >> 51); + uint64_t x3 = (x1 & UINT64_C(0x7ffffffffffff)); + *out1 = x3; + *out2 = (fiat_25519_uint1)(0x0 - x2); +} + +/* + * Input Bounds: + * arg1: [0x0 ~> 0x1] + * arg2: [0x0 ~> 0xffffffffffffffff] + * arg3: [0x0 ~> 0xffffffffffffffff] + * Output Bounds: + * out1: [0x0 ~> 0xffffffffffffffff] + */ +static void fiat_25519_cmovznz_u64(uint64_t* out1, fiat_25519_uint1 arg1, uint64_t arg2, uint64_t arg3) { + fiat_25519_uint1 x1 = (!(!arg1)); + uint64_t x2 = ((fiat_25519_int1)(0x0 - x1) & UINT64_C(0xffffffffffffffff)); + uint64_t x3 = ((x2 & arg3) | ((~x2) & arg2)); + *out1 = x3; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664]] + * arg2: [[0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664]] + * Output Bounds: + * out1: [[0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc]] + */ +static void fiat_25519_carry_mul(uint64_t out1[5], const uint64_t arg1[5], const uint64_t arg2[5]) { + fiat_25519_uint128 x1 = ((fiat_25519_uint128)(arg1[4]) * ((arg2[4]) * (uint64_t)UINT8_C(0x13))); + fiat_25519_uint128 x2 = ((fiat_25519_uint128)(arg1[4]) * ((arg2[3]) * (uint64_t)UINT8_C(0x13))); + fiat_25519_uint128 x3 = ((fiat_25519_uint128)(arg1[4]) * ((arg2[2]) * (uint64_t)UINT8_C(0x13))); + fiat_25519_uint128 x4 = ((fiat_25519_uint128)(arg1[4]) * ((arg2[1]) * (uint64_t)UINT8_C(0x13))); + fiat_25519_uint128 x5 = ((fiat_25519_uint128)(arg1[3]) * ((arg2[4]) * (uint64_t)UINT8_C(0x13))); + fiat_25519_uint128 x6 = ((fiat_25519_uint128)(arg1[3]) * ((arg2[3]) * (uint64_t)UINT8_C(0x13))); + fiat_25519_uint128 x7 = ((fiat_25519_uint128)(arg1[3]) * ((arg2[2]) * (uint64_t)UINT8_C(0x13))); + fiat_25519_uint128 x8 = ((fiat_25519_uint128)(arg1[2]) * ((arg2[4]) * (uint64_t)UINT8_C(0x13))); + fiat_25519_uint128 x9 = ((fiat_25519_uint128)(arg1[2]) * ((arg2[3]) * (uint64_t)UINT8_C(0x13))); + fiat_25519_uint128 x10 = ((fiat_25519_uint128)(arg1[1]) * ((arg2[4]) * (uint64_t)UINT8_C(0x13))); + fiat_25519_uint128 x11 = ((fiat_25519_uint128)(arg1[4]) * (arg2[0])); + fiat_25519_uint128 x12 = ((fiat_25519_uint128)(arg1[3]) * (arg2[1])); + fiat_25519_uint128 x13 = ((fiat_25519_uint128)(arg1[3]) * (arg2[0])); + fiat_25519_uint128 x14 = ((fiat_25519_uint128)(arg1[2]) * (arg2[2])); + fiat_25519_uint128 x15 = ((fiat_25519_uint128)(arg1[2]) * (arg2[1])); + fiat_25519_uint128 x16 = ((fiat_25519_uint128)(arg1[2]) * (arg2[0])); + fiat_25519_uint128 x17 = ((fiat_25519_uint128)(arg1[1]) * (arg2[3])); + fiat_25519_uint128 x18 = ((fiat_25519_uint128)(arg1[1]) * (arg2[2])); + fiat_25519_uint128 x19 = ((fiat_25519_uint128)(arg1[1]) * (arg2[1])); + fiat_25519_uint128 x20 = ((fiat_25519_uint128)(arg1[1]) * (arg2[0])); + fiat_25519_uint128 x21 = ((fiat_25519_uint128)(arg1[0]) * (arg2[4])); + fiat_25519_uint128 x22 = ((fiat_25519_uint128)(arg1[0]) * (arg2[3])); + fiat_25519_uint128 x23 = ((fiat_25519_uint128)(arg1[0]) * (arg2[2])); + fiat_25519_uint128 x24 = ((fiat_25519_uint128)(arg1[0]) * (arg2[1])); + fiat_25519_uint128 x25 = ((fiat_25519_uint128)(arg1[0]) * (arg2[0])); + fiat_25519_uint128 x26 = (x25 + (x10 + (x9 + (x7 + x4)))); + uint64_t x27 = (uint64_t)(x26 >> 51); + uint64_t x28 = (uint64_t)(x26 & UINT64_C(0x7ffffffffffff)); + fiat_25519_uint128 x29 = (x21 + (x17 + (x14 + (x12 + x11)))); + fiat_25519_uint128 x30 = (x22 + (x18 + (x15 + (x13 + x1)))); + fiat_25519_uint128 x31 = (x23 + (x19 + (x16 + (x5 + x2)))); + fiat_25519_uint128 x32 = (x24 + (x20 + (x8 + (x6 + x3)))); + fiat_25519_uint128 x33 = (x27 + x32); + uint64_t x34 = (uint64_t)(x33 >> 51); + uint64_t x35 = (uint64_t)(x33 & UINT64_C(0x7ffffffffffff)); + fiat_25519_uint128 x36 = (x34 + x31); + uint64_t x37 = (uint64_t)(x36 >> 51); + uint64_t x38 = (uint64_t)(x36 & UINT64_C(0x7ffffffffffff)); + fiat_25519_uint128 x39 = (x37 + x30); + uint64_t x40 = (uint64_t)(x39 >> 51); + uint64_t x41 = (uint64_t)(x39 & UINT64_C(0x7ffffffffffff)); + fiat_25519_uint128 x42 = (x40 + x29); + uint64_t x43 = (uint64_t)(x42 >> 51); + uint64_t x44 = (uint64_t)(x42 & UINT64_C(0x7ffffffffffff)); + uint64_t x45 = (x43 * (uint64_t)UINT8_C(0x13)); + uint64_t x46 = (x28 + x45); + uint64_t x47 = (x46 >> 51); + uint64_t x48 = (x46 & UINT64_C(0x7ffffffffffff)); + uint64_t x49 = (x47 + x35); + uint64_t x50 = (x49 >> 51); + uint64_t x51 = (x49 & UINT64_C(0x7ffffffffffff)); + uint64_t x52 = (x50 + x38); + out1[0] = x48; + out1[1] = x51; + out1[2] = x52; + out1[3] = x41; + out1[4] = x44; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664]] + * Output Bounds: + * out1: [[0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc]] + */ +static void fiat_25519_carry_square(uint64_t out1[5], const uint64_t arg1[5]) { + uint64_t x1 = ((arg1[4]) * (uint64_t)UINT8_C(0x13)); + uint64_t x2 = (x1 * (uint64_t)0x2); + uint64_t x3 = ((arg1[4]) * (uint64_t)0x2); + uint64_t x4 = ((arg1[3]) * (uint64_t)UINT8_C(0x13)); + uint64_t x5 = (x4 * (uint64_t)0x2); + uint64_t x6 = ((arg1[3]) * (uint64_t)0x2); + uint64_t x7 = ((arg1[2]) * (uint64_t)0x2); + uint64_t x8 = ((arg1[1]) * (uint64_t)0x2); + fiat_25519_uint128 x9 = ((fiat_25519_uint128)(arg1[4]) * x1); + fiat_25519_uint128 x10 = ((fiat_25519_uint128)(arg1[3]) * x2); + fiat_25519_uint128 x11 = ((fiat_25519_uint128)(arg1[3]) * x4); + fiat_25519_uint128 x12 = ((fiat_25519_uint128)(arg1[2]) * x2); + fiat_25519_uint128 x13 = ((fiat_25519_uint128)(arg1[2]) * x5); + fiat_25519_uint128 x14 = ((fiat_25519_uint128)(arg1[2]) * (arg1[2])); + fiat_25519_uint128 x15 = ((fiat_25519_uint128)(arg1[1]) * x2); + fiat_25519_uint128 x16 = ((fiat_25519_uint128)(arg1[1]) * x6); + fiat_25519_uint128 x17 = ((fiat_25519_uint128)(arg1[1]) * x7); + fiat_25519_uint128 x18 = ((fiat_25519_uint128)(arg1[1]) * (arg1[1])); + fiat_25519_uint128 x19 = ((fiat_25519_uint128)(arg1[0]) * x3); + fiat_25519_uint128 x20 = ((fiat_25519_uint128)(arg1[0]) * x6); + fiat_25519_uint128 x21 = ((fiat_25519_uint128)(arg1[0]) * x7); + fiat_25519_uint128 x22 = ((fiat_25519_uint128)(arg1[0]) * x8); + fiat_25519_uint128 x23 = ((fiat_25519_uint128)(arg1[0]) * (arg1[0])); + fiat_25519_uint128 x24 = (x23 + (x15 + x13)); + uint64_t x25 = (uint64_t)(x24 >> 51); + uint64_t x26 = (uint64_t)(x24 & UINT64_C(0x7ffffffffffff)); + fiat_25519_uint128 x27 = (x19 + (x16 + x14)); + fiat_25519_uint128 x28 = (x20 + (x17 + x9)); + fiat_25519_uint128 x29 = (x21 + (x18 + x10)); + fiat_25519_uint128 x30 = (x22 + (x12 + x11)); + fiat_25519_uint128 x31 = (x25 + x30); + uint64_t x32 = (uint64_t)(x31 >> 51); + uint64_t x33 = (uint64_t)(x31 & UINT64_C(0x7ffffffffffff)); + fiat_25519_uint128 x34 = (x32 + x29); + uint64_t x35 = (uint64_t)(x34 >> 51); + uint64_t x36 = (uint64_t)(x34 & UINT64_C(0x7ffffffffffff)); + fiat_25519_uint128 x37 = (x35 + x28); + uint64_t x38 = (uint64_t)(x37 >> 51); + uint64_t x39 = (uint64_t)(x37 & UINT64_C(0x7ffffffffffff)); + fiat_25519_uint128 x40 = (x38 + x27); + uint64_t x41 = (uint64_t)(x40 >> 51); + uint64_t x42 = (uint64_t)(x40 & UINT64_C(0x7ffffffffffff)); + uint64_t x43 = (x41 * (uint64_t)UINT8_C(0x13)); + uint64_t x44 = (x26 + x43); + uint64_t x45 = (x44 >> 51); + uint64_t x46 = (x44 & UINT64_C(0x7ffffffffffff)); + uint64_t x47 = (x45 + x33); + uint64_t x48 = (x47 >> 51); + uint64_t x49 = (x47 & UINT64_C(0x7ffffffffffff)); + uint64_t x50 = (x48 + x36); + out1[0] = x46; + out1[1] = x49; + out1[2] = x50; + out1[3] = x39; + out1[4] = x42; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664]] + * Output Bounds: + * out1: [[0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc]] + */ +static void fiat_25519_carry(uint64_t out1[5], const uint64_t arg1[5]) { + uint64_t x1 = (arg1[0]); + uint64_t x2 = ((x1 >> 51) + (arg1[1])); + uint64_t x3 = ((x2 >> 51) + (arg1[2])); + uint64_t x4 = ((x3 >> 51) + (arg1[3])); + uint64_t x5 = ((x4 >> 51) + (arg1[4])); + uint64_t x6 = ((x1 & UINT64_C(0x7ffffffffffff)) + ((x5 >> 51) * (uint64_t)UINT8_C(0x13))); + uint64_t x7 = ((x6 >> 51) + (x2 & UINT64_C(0x7ffffffffffff))); + uint64_t x8 = (x6 & UINT64_C(0x7ffffffffffff)); + uint64_t x9 = (x7 & UINT64_C(0x7ffffffffffff)); + uint64_t x10 = ((x7 >> 51) + (x3 & UINT64_C(0x7ffffffffffff))); + uint64_t x11 = (x4 & UINT64_C(0x7ffffffffffff)); + uint64_t x12 = (x5 & UINT64_C(0x7ffffffffffff)); + out1[0] = x8; + out1[1] = x9; + out1[2] = x10; + out1[3] = x11; + out1[4] = x12; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc]] + * arg2: [[0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc]] + * Output Bounds: + * out1: [[0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664]] + */ +static void fiat_25519_add(uint64_t out1[5], const uint64_t arg1[5], const uint64_t arg2[5]) { + uint64_t x1 = ((arg1[0]) + (arg2[0])); + uint64_t x2 = ((arg1[1]) + (arg2[1])); + uint64_t x3 = ((arg1[2]) + (arg2[2])); + uint64_t x4 = ((arg1[3]) + (arg2[3])); + uint64_t x5 = ((arg1[4]) + (arg2[4])); + out1[0] = x1; + out1[1] = x2; + out1[2] = x3; + out1[3] = x4; + out1[4] = x5; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc]] + * arg2: [[0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc]] + * Output Bounds: + * out1: [[0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664]] + */ +static void fiat_25519_sub(uint64_t out1[5], const uint64_t arg1[5], const uint64_t arg2[5]) { + uint64_t x1 = ((UINT64_C(0xfffffffffffda) + (arg1[0])) - (arg2[0])); + uint64_t x2 = ((UINT64_C(0xffffffffffffe) + (arg1[1])) - (arg2[1])); + uint64_t x3 = ((UINT64_C(0xffffffffffffe) + (arg1[2])) - (arg2[2])); + uint64_t x4 = ((UINT64_C(0xffffffffffffe) + (arg1[3])) - (arg2[3])); + uint64_t x5 = ((UINT64_C(0xffffffffffffe) + (arg1[4])) - (arg2[4])); + out1[0] = x1; + out1[1] = x2; + out1[2] = x3; + out1[3] = x4; + out1[4] = x5; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc]] + * Output Bounds: + * out1: [[0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664], [0x0 ~> 0x1a666666666664]] + */ +static void fiat_25519_opp(uint64_t out1[5], const uint64_t arg1[5]) { + uint64_t x1 = (UINT64_C(0xfffffffffffda) - (arg1[0])); + uint64_t x2 = (UINT64_C(0xffffffffffffe) - (arg1[1])); + uint64_t x3 = (UINT64_C(0xffffffffffffe) - (arg1[2])); + uint64_t x4 = (UINT64_C(0xffffffffffffe) - (arg1[3])); + uint64_t x5 = (UINT64_C(0xffffffffffffe) - (arg1[4])); + out1[0] = x1; + out1[1] = x2; + out1[2] = x3; + out1[3] = x4; + out1[4] = x5; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc]] + * Output Bounds: + * out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x7f]] + */ +static void fiat_25519_to_bytes(uint8_t out1[32], const uint64_t arg1[5]) { + uint64_t x1; + fiat_25519_uint1 x2; + fiat_25519_subborrowx_u51(&x1, &x2, 0x0, (arg1[0]), UINT64_C(0x7ffffffffffed)); + uint64_t x3; + fiat_25519_uint1 x4; + fiat_25519_subborrowx_u51(&x3, &x4, x2, (arg1[1]), UINT64_C(0x7ffffffffffff)); + uint64_t x5; + fiat_25519_uint1 x6; + fiat_25519_subborrowx_u51(&x5, &x6, x4, (arg1[2]), UINT64_C(0x7ffffffffffff)); + uint64_t x7; + fiat_25519_uint1 x8; + fiat_25519_subborrowx_u51(&x7, &x8, x6, (arg1[3]), UINT64_C(0x7ffffffffffff)); + uint64_t x9; + fiat_25519_uint1 x10; + fiat_25519_subborrowx_u51(&x9, &x10, x8, (arg1[4]), UINT64_C(0x7ffffffffffff)); + uint64_t x11; + fiat_25519_cmovznz_u64(&x11, x10, 0x0, UINT64_C(0xffffffffffffffff)); + uint64_t x12; + fiat_25519_uint1 x13; + fiat_25519_addcarryx_u51(&x12, &x13, 0x0, (x11 & UINT64_C(0x7ffffffffffed)), x1); + uint64_t x14; + fiat_25519_uint1 x15; + fiat_25519_addcarryx_u51(&x14, &x15, x13, (x11 & UINT64_C(0x7ffffffffffff)), x3); + uint64_t x16; + fiat_25519_uint1 x17; + fiat_25519_addcarryx_u51(&x16, &x17, x15, (x11 & UINT64_C(0x7ffffffffffff)), x5); + uint64_t x18; + fiat_25519_uint1 x19; + fiat_25519_addcarryx_u51(&x18, &x19, x17, (x11 & UINT64_C(0x7ffffffffffff)), x7); + uint64_t x20; + fiat_25519_uint1 x21; + fiat_25519_addcarryx_u51(&x20, &x21, x19, (x11 & UINT64_C(0x7ffffffffffff)), x9); + uint64_t x22 = (x20 << 4); + uint64_t x23 = (x18 * (uint64_t)0x2); + uint64_t x24 = (x16 << 6); + uint64_t x25 = (x14 << 3); + uint64_t x26 = (x12 >> 8); + uint8_t x27 = (uint8_t)(x12 & UINT8_C(0xff)); + uint64_t x28 = (x26 >> 8); + uint8_t x29 = (uint8_t)(x26 & UINT8_C(0xff)); + uint64_t x30 = (x28 >> 8); + uint8_t x31 = (uint8_t)(x28 & UINT8_C(0xff)); + uint64_t x32 = (x30 >> 8); + uint8_t x33 = (uint8_t)(x30 & UINT8_C(0xff)); + uint64_t x34 = (x32 >> 8); + uint8_t x35 = (uint8_t)(x32 & UINT8_C(0xff)); + uint8_t x36 = (uint8_t)(x34 >> 8); + uint8_t x37 = (uint8_t)(x34 & UINT8_C(0xff)); + uint64_t x38 = (x36 + x25); + uint64_t x39 = (x38 >> 8); + uint8_t x40 = (uint8_t)(x38 & UINT8_C(0xff)); + uint64_t x41 = (x39 >> 8); + uint8_t x42 = (uint8_t)(x39 & UINT8_C(0xff)); + uint64_t x43 = (x41 >> 8); + uint8_t x44 = (uint8_t)(x41 & UINT8_C(0xff)); + uint64_t x45 = (x43 >> 8); + uint8_t x46 = (uint8_t)(x43 & UINT8_C(0xff)); + uint64_t x47 = (x45 >> 8); + uint8_t x48 = (uint8_t)(x45 & UINT8_C(0xff)); + uint8_t x49 = (uint8_t)(x47 >> 8); + uint8_t x50 = (uint8_t)(x47 & UINT8_C(0xff)); + uint64_t x51 = (x49 + x24); + uint64_t x52 = (x51 >> 8); + uint8_t x53 = (uint8_t)(x51 & UINT8_C(0xff)); + uint64_t x54 = (x52 >> 8); + uint8_t x55 = (uint8_t)(x52 & UINT8_C(0xff)); + uint64_t x56 = (x54 >> 8); + uint8_t x57 = (uint8_t)(x54 & UINT8_C(0xff)); + uint64_t x58 = (x56 >> 8); + uint8_t x59 = (uint8_t)(x56 & UINT8_C(0xff)); + uint64_t x60 = (x58 >> 8); + uint8_t x61 = (uint8_t)(x58 & UINT8_C(0xff)); + uint64_t x62 = (x60 >> 8); + uint8_t x63 = (uint8_t)(x60 & UINT8_C(0xff)); + fiat_25519_uint1 x64 = (fiat_25519_uint1)(x62 >> 8); + uint8_t x65 = (uint8_t)(x62 & UINT8_C(0xff)); + uint64_t x66 = (x64 + x23); + uint64_t x67 = (x66 >> 8); + uint8_t x68 = (uint8_t)(x66 & UINT8_C(0xff)); + uint64_t x69 = (x67 >> 8); + uint8_t x70 = (uint8_t)(x67 & UINT8_C(0xff)); + uint64_t x71 = (x69 >> 8); + uint8_t x72 = (uint8_t)(x69 & UINT8_C(0xff)); + uint64_t x73 = (x71 >> 8); + uint8_t x74 = (uint8_t)(x71 & UINT8_C(0xff)); + uint64_t x75 = (x73 >> 8); + uint8_t x76 = (uint8_t)(x73 & UINT8_C(0xff)); + uint8_t x77 = (uint8_t)(x75 >> 8); + uint8_t x78 = (uint8_t)(x75 & UINT8_C(0xff)); + uint64_t x79 = (x77 + x22); + uint64_t x80 = (x79 >> 8); + uint8_t x81 = (uint8_t)(x79 & UINT8_C(0xff)); + uint64_t x82 = (x80 >> 8); + uint8_t x83 = (uint8_t)(x80 & UINT8_C(0xff)); + uint64_t x84 = (x82 >> 8); + uint8_t x85 = (uint8_t)(x82 & UINT8_C(0xff)); + uint64_t x86 = (x84 >> 8); + uint8_t x87 = (uint8_t)(x84 & UINT8_C(0xff)); + uint64_t x88 = (x86 >> 8); + uint8_t x89 = (uint8_t)(x86 & UINT8_C(0xff)); + uint8_t x90 = (uint8_t)(x88 >> 8); + uint8_t x91 = (uint8_t)(x88 & UINT8_C(0xff)); + out1[0] = x27; + out1[1] = x29; + out1[2] = x31; + out1[3] = x33; + out1[4] = x35; + out1[5] = x37; + out1[6] = x40; + out1[7] = x42; + out1[8] = x44; + out1[9] = x46; + out1[10] = x48; + out1[11] = x50; + out1[12] = x53; + out1[13] = x55; + out1[14] = x57; + out1[15] = x59; + out1[16] = x61; + out1[17] = x63; + out1[18] = x65; + out1[19] = x68; + out1[20] = x70; + out1[21] = x72; + out1[22] = x74; + out1[23] = x76; + out1[24] = x78; + out1[25] = x81; + out1[26] = x83; + out1[27] = x85; + out1[28] = x87; + out1[29] = x89; + out1[30] = x91; + out1[31] = x90; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x7f]] + * Output Bounds: + * out1: [[0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc], [0x0 ~> 0x8cccccccccccc]] + */ +static void fiat_25519_from_bytes(uint64_t out1[5], const uint8_t arg1[32]) { + uint64_t x1 = ((uint64_t)(arg1[31]) << 44); + uint64_t x2 = ((uint64_t)(arg1[30]) << 36); + uint64_t x3 = ((uint64_t)(arg1[29]) << 28); + uint64_t x4 = ((uint64_t)(arg1[28]) << 20); + uint64_t x5 = ((uint64_t)(arg1[27]) << 12); + uint64_t x6 = ((uint64_t)(arg1[26]) << 4); + uint64_t x7 = ((uint64_t)(arg1[25]) << 47); + uint64_t x8 = ((uint64_t)(arg1[24]) << 39); + uint64_t x9 = ((uint64_t)(arg1[23]) << 31); + uint64_t x10 = ((uint64_t)(arg1[22]) << 23); + uint64_t x11 = ((uint64_t)(arg1[21]) << 15); + uint64_t x12 = ((uint64_t)(arg1[20]) << 7); + uint64_t x13 = ((uint64_t)(arg1[19]) << 50); + uint64_t x14 = ((uint64_t)(arg1[18]) << 42); + uint64_t x15 = ((uint64_t)(arg1[17]) << 34); + uint64_t x16 = ((uint64_t)(arg1[16]) << 26); + uint64_t x17 = ((uint64_t)(arg1[15]) << 18); + uint64_t x18 = ((uint64_t)(arg1[14]) << 10); + uint64_t x19 = ((uint64_t)(arg1[13]) << 2); + uint64_t x20 = ((uint64_t)(arg1[12]) << 45); + uint64_t x21 = ((uint64_t)(arg1[11]) << 37); + uint64_t x22 = ((uint64_t)(arg1[10]) << 29); + uint64_t x23 = ((uint64_t)(arg1[9]) << 21); + uint64_t x24 = ((uint64_t)(arg1[8]) << 13); + uint64_t x25 = ((uint64_t)(arg1[7]) << 5); + uint64_t x26 = ((uint64_t)(arg1[6]) << 48); + uint64_t x27 = ((uint64_t)(arg1[5]) << 40); + uint64_t x28 = ((uint64_t)(arg1[4]) << 32); + uint64_t x29 = ((uint64_t)(arg1[3]) << 24); + uint64_t x30 = ((uint64_t)(arg1[2]) << 16); + uint64_t x31 = ((uint64_t)(arg1[1]) << 8); + uint8_t x32 = (arg1[0]); + uint64_t x33 = (x32 + (x31 + (x30 + (x29 + (x28 + (x27 + x26)))))); + uint8_t x34 = (uint8_t)(x33 >> 51); + uint64_t x35 = (x33 & UINT64_C(0x7ffffffffffff)); + uint64_t x36 = (x6 + (x5 + (x4 + (x3 + (x2 + x1))))); + uint64_t x37 = (x12 + (x11 + (x10 + (x9 + (x8 + x7))))); + uint64_t x38 = (x19 + (x18 + (x17 + (x16 + (x15 + (x14 + x13)))))); + uint64_t x39 = (x25 + (x24 + (x23 + (x22 + (x21 + x20))))); + uint64_t x40 = (x34 + x39); + uint8_t x41 = (uint8_t)(x40 >> 51); + uint64_t x42 = (x40 & UINT64_C(0x7ffffffffffff)); + uint64_t x43 = (x41 + x38); + uint8_t x44 = (uint8_t)(x43 >> 51); + uint64_t x45 = (x43 & UINT64_C(0x7ffffffffffff)); + uint64_t x46 = (x44 + x37); + uint8_t x47 = (uint8_t)(x46 >> 51); + uint64_t x48 = (x46 & UINT64_C(0x7ffffffffffff)); + uint64_t x49 = (x47 + x36); + out1[0] = x35; + out1[1] = x42; + out1[2] = x45; + out1[3] = x48; + out1[4] = x49; +} + +#else /* defined(BORINGSSL_CURVE25519_64BIT) */ + +/* Autogenerated */ +/* curve description: 25519 */ +/* requested operations: carry_mul, carry_square, carry_scmul121666, carry, add, sub, opp, selectznz, to_bytes, from_bytes */ +/* n = 10 (from "10") */ +/* s = 0x8000000000000000000000000000000000000000000000000000000000000000 (from "2^255") */ +/* c = [(1, 19)] (from "1,19") */ +/* machine_wordsize = 32 (from "32") */ + +#include +typedef unsigned char fiat_25519_uint1; +typedef signed char fiat_25519_int1; + + +/* + * Input Bounds: + * arg1: [0x0 ~> 0x1] + * arg2: [0x0 ~> 0x3ffffff] + * arg3: [0x0 ~> 0x3ffffff] + * Output Bounds: + * out1: [0x0 ~> 0x3ffffff] + * out2: [0x0 ~> 0x1] + */ +static void fiat_25519_addcarryx_u26(uint32_t* out1, fiat_25519_uint1* out2, fiat_25519_uint1 arg1, uint32_t arg2, uint32_t arg3) { + uint32_t x1 = ((arg1 + arg2) + arg3); + uint32_t x2 = (x1 & UINT32_C(0x3ffffff)); + fiat_25519_uint1 x3 = (fiat_25519_uint1)(x1 >> 26); + *out1 = x2; + *out2 = x3; +} + +/* + * Input Bounds: + * arg1: [0x0 ~> 0x1] + * arg2: [0x0 ~> 0x3ffffff] + * arg3: [0x0 ~> 0x3ffffff] + * Output Bounds: + * out1: [0x0 ~> 0x3ffffff] + * out2: [0x0 ~> 0x1] + */ +static void fiat_25519_subborrowx_u26(uint32_t* out1, fiat_25519_uint1* out2, fiat_25519_uint1 arg1, uint32_t arg2, uint32_t arg3) { + int32_t x1 = ((int32_t)(arg2 - arg1) - (int32_t)arg3); + fiat_25519_int1 x2 = (fiat_25519_int1)(x1 >> 26); + uint32_t x3 = (x1 & UINT32_C(0x3ffffff)); + *out1 = x3; + *out2 = (fiat_25519_uint1)(0x0 - x2); +} + +/* + * Input Bounds: + * arg1: [0x0 ~> 0x1] + * arg2: [0x0 ~> 0x1ffffff] + * arg3: [0x0 ~> 0x1ffffff] + * Output Bounds: + * out1: [0x0 ~> 0x1ffffff] + * out2: [0x0 ~> 0x1] + */ +static void fiat_25519_addcarryx_u25(uint32_t* out1, fiat_25519_uint1* out2, fiat_25519_uint1 arg1, uint32_t arg2, uint32_t arg3) { + uint32_t x1 = ((arg1 + arg2) + arg3); + uint32_t x2 = (x1 & UINT32_C(0x1ffffff)); + fiat_25519_uint1 x3 = (fiat_25519_uint1)(x1 >> 25); + *out1 = x2; + *out2 = x3; +} + +/* + * Input Bounds: + * arg1: [0x0 ~> 0x1] + * arg2: [0x0 ~> 0x1ffffff] + * arg3: [0x0 ~> 0x1ffffff] + * Output Bounds: + * out1: [0x0 ~> 0x1ffffff] + * out2: [0x0 ~> 0x1] + */ +static void fiat_25519_subborrowx_u25(uint32_t* out1, fiat_25519_uint1* out2, fiat_25519_uint1 arg1, uint32_t arg2, uint32_t arg3) { + int32_t x1 = ((int32_t)(arg2 - arg1) - (int32_t)arg3); + fiat_25519_int1 x2 = (fiat_25519_int1)(x1 >> 25); + uint32_t x3 = (x1 & UINT32_C(0x1ffffff)); + *out1 = x3; + *out2 = (fiat_25519_uint1)(0x0 - x2); +} + +/* + * Input Bounds: + * arg1: [0x0 ~> 0x1] + * arg2: [0x0 ~> 0xffffffff] + * arg3: [0x0 ~> 0xffffffff] + * Output Bounds: + * out1: [0x0 ~> 0xffffffff] + */ +static void fiat_25519_cmovznz_u32(uint32_t* out1, fiat_25519_uint1 arg1, uint32_t arg2, uint32_t arg3) { + fiat_25519_uint1 x1 = (!(!arg1)); + uint32_t x2 = ((fiat_25519_int1)(0x0 - x1) & UINT32_C(0xffffffff)); + uint32_t x3 = ((x2 & arg3) | ((~x2) & arg2)); + *out1 = x3; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999]] + * arg2: [[0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999]] + * Output Bounds: + * out1: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]] + */ +static void fiat_25519_carry_mul(uint32_t out1[10], const uint32_t arg1[10], const uint32_t arg2[10]) { + uint64_t x1 = ((uint64_t)(arg1[9]) * ((arg2[9]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x2 = ((uint64_t)(arg1[9]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13))); + uint64_t x3 = ((uint64_t)(arg1[9]) * ((arg2[7]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x4 = ((uint64_t)(arg1[9]) * ((arg2[6]) * (uint32_t)UINT8_C(0x13))); + uint64_t x5 = ((uint64_t)(arg1[9]) * ((arg2[5]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x6 = ((uint64_t)(arg1[9]) * ((arg2[4]) * (uint32_t)UINT8_C(0x13))); + uint64_t x7 = ((uint64_t)(arg1[9]) * ((arg2[3]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x8 = ((uint64_t)(arg1[9]) * ((arg2[2]) * (uint32_t)UINT8_C(0x13))); + uint64_t x9 = ((uint64_t)(arg1[9]) * ((arg2[1]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x10 = ((uint64_t)(arg1[8]) * ((arg2[9]) * (uint32_t)UINT8_C(0x13))); + uint64_t x11 = ((uint64_t)(arg1[8]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13))); + uint64_t x12 = ((uint64_t)(arg1[8]) * ((arg2[7]) * (uint32_t)UINT8_C(0x13))); + uint64_t x13 = ((uint64_t)(arg1[8]) * ((arg2[6]) * (uint32_t)UINT8_C(0x13))); + uint64_t x14 = ((uint64_t)(arg1[8]) * ((arg2[5]) * (uint32_t)UINT8_C(0x13))); + uint64_t x15 = ((uint64_t)(arg1[8]) * ((arg2[4]) * (uint32_t)UINT8_C(0x13))); + uint64_t x16 = ((uint64_t)(arg1[8]) * ((arg2[3]) * (uint32_t)UINT8_C(0x13))); + uint64_t x17 = ((uint64_t)(arg1[8]) * ((arg2[2]) * (uint32_t)UINT8_C(0x13))); + uint64_t x18 = ((uint64_t)(arg1[7]) * ((arg2[9]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x19 = ((uint64_t)(arg1[7]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13))); + uint64_t x20 = ((uint64_t)(arg1[7]) * ((arg2[7]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x21 = ((uint64_t)(arg1[7]) * ((arg2[6]) * (uint32_t)UINT8_C(0x13))); + uint64_t x22 = ((uint64_t)(arg1[7]) * ((arg2[5]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x23 = ((uint64_t)(arg1[7]) * ((arg2[4]) * (uint32_t)UINT8_C(0x13))); + uint64_t x24 = ((uint64_t)(arg1[7]) * ((arg2[3]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x25 = ((uint64_t)(arg1[6]) * ((arg2[9]) * (uint32_t)UINT8_C(0x13))); + uint64_t x26 = ((uint64_t)(arg1[6]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13))); + uint64_t x27 = ((uint64_t)(arg1[6]) * ((arg2[7]) * (uint32_t)UINT8_C(0x13))); + uint64_t x28 = ((uint64_t)(arg1[6]) * ((arg2[6]) * (uint32_t)UINT8_C(0x13))); + uint64_t x29 = ((uint64_t)(arg1[6]) * ((arg2[5]) * (uint32_t)UINT8_C(0x13))); + uint64_t x30 = ((uint64_t)(arg1[6]) * ((arg2[4]) * (uint32_t)UINT8_C(0x13))); + uint64_t x31 = ((uint64_t)(arg1[5]) * ((arg2[9]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x32 = ((uint64_t)(arg1[5]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13))); + uint64_t x33 = ((uint64_t)(arg1[5]) * ((arg2[7]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x34 = ((uint64_t)(arg1[5]) * ((arg2[6]) * (uint32_t)UINT8_C(0x13))); + uint64_t x35 = ((uint64_t)(arg1[5]) * ((arg2[5]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x36 = ((uint64_t)(arg1[4]) * ((arg2[9]) * (uint32_t)UINT8_C(0x13))); + uint64_t x37 = ((uint64_t)(arg1[4]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13))); + uint64_t x38 = ((uint64_t)(arg1[4]) * ((arg2[7]) * (uint32_t)UINT8_C(0x13))); + uint64_t x39 = ((uint64_t)(arg1[4]) * ((arg2[6]) * (uint32_t)UINT8_C(0x13))); + uint64_t x40 = ((uint64_t)(arg1[3]) * ((arg2[9]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x41 = ((uint64_t)(arg1[3]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13))); + uint64_t x42 = ((uint64_t)(arg1[3]) * ((arg2[7]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x43 = ((uint64_t)(arg1[2]) * ((arg2[9]) * (uint32_t)UINT8_C(0x13))); + uint64_t x44 = ((uint64_t)(arg1[2]) * ((arg2[8]) * (uint32_t)UINT8_C(0x13))); + uint64_t x45 = ((uint64_t)(arg1[1]) * ((arg2[9]) * ((uint32_t)0x2 * UINT8_C(0x13)))); + uint64_t x46 = ((uint64_t)(arg1[9]) * (arg2[0])); + uint64_t x47 = ((uint64_t)(arg1[8]) * (arg2[1])); + uint64_t x48 = ((uint64_t)(arg1[8]) * (arg2[0])); + uint64_t x49 = ((uint64_t)(arg1[7]) * (arg2[2])); + uint64_t x50 = ((uint64_t)(arg1[7]) * ((arg2[1]) * (uint32_t)0x2)); + uint64_t x51 = ((uint64_t)(arg1[7]) * (arg2[0])); + uint64_t x52 = ((uint64_t)(arg1[6]) * (arg2[3])); + uint64_t x53 = ((uint64_t)(arg1[6]) * (arg2[2])); + uint64_t x54 = ((uint64_t)(arg1[6]) * (arg2[1])); + uint64_t x55 = ((uint64_t)(arg1[6]) * (arg2[0])); + uint64_t x56 = ((uint64_t)(arg1[5]) * (arg2[4])); + uint64_t x57 = ((uint64_t)(arg1[5]) * ((arg2[3]) * (uint32_t)0x2)); + uint64_t x58 = ((uint64_t)(arg1[5]) * (arg2[2])); + uint64_t x59 = ((uint64_t)(arg1[5]) * ((arg2[1]) * (uint32_t)0x2)); + uint64_t x60 = ((uint64_t)(arg1[5]) * (arg2[0])); + uint64_t x61 = ((uint64_t)(arg1[4]) * (arg2[5])); + uint64_t x62 = ((uint64_t)(arg1[4]) * (arg2[4])); + uint64_t x63 = ((uint64_t)(arg1[4]) * (arg2[3])); + uint64_t x64 = ((uint64_t)(arg1[4]) * (arg2[2])); + uint64_t x65 = ((uint64_t)(arg1[4]) * (arg2[1])); + uint64_t x66 = ((uint64_t)(arg1[4]) * (arg2[0])); + uint64_t x67 = ((uint64_t)(arg1[3]) * (arg2[6])); + uint64_t x68 = ((uint64_t)(arg1[3]) * ((arg2[5]) * (uint32_t)0x2)); + uint64_t x69 = ((uint64_t)(arg1[3]) * (arg2[4])); + uint64_t x70 = ((uint64_t)(arg1[3]) * ((arg2[3]) * (uint32_t)0x2)); + uint64_t x71 = ((uint64_t)(arg1[3]) * (arg2[2])); + uint64_t x72 = ((uint64_t)(arg1[3]) * ((arg2[1]) * (uint32_t)0x2)); + uint64_t x73 = ((uint64_t)(arg1[3]) * (arg2[0])); + uint64_t x74 = ((uint64_t)(arg1[2]) * (arg2[7])); + uint64_t x75 = ((uint64_t)(arg1[2]) * (arg2[6])); + uint64_t x76 = ((uint64_t)(arg1[2]) * (arg2[5])); + uint64_t x77 = ((uint64_t)(arg1[2]) * (arg2[4])); + uint64_t x78 = ((uint64_t)(arg1[2]) * (arg2[3])); + uint64_t x79 = ((uint64_t)(arg1[2]) * (arg2[2])); + uint64_t x80 = ((uint64_t)(arg1[2]) * (arg2[1])); + uint64_t x81 = ((uint64_t)(arg1[2]) * (arg2[0])); + uint64_t x82 = ((uint64_t)(arg1[1]) * (arg2[8])); + uint64_t x83 = ((uint64_t)(arg1[1]) * ((arg2[7]) * (uint32_t)0x2)); + uint64_t x84 = ((uint64_t)(arg1[1]) * (arg2[6])); + uint64_t x85 = ((uint64_t)(arg1[1]) * ((arg2[5]) * (uint32_t)0x2)); + uint64_t x86 = ((uint64_t)(arg1[1]) * (arg2[4])); + uint64_t x87 = ((uint64_t)(arg1[1]) * ((arg2[3]) * (uint32_t)0x2)); + uint64_t x88 = ((uint64_t)(arg1[1]) * (arg2[2])); + uint64_t x89 = ((uint64_t)(arg1[1]) * ((arg2[1]) * (uint32_t)0x2)); + uint64_t x90 = ((uint64_t)(arg1[1]) * (arg2[0])); + uint64_t x91 = ((uint64_t)(arg1[0]) * (arg2[9])); + uint64_t x92 = ((uint64_t)(arg1[0]) * (arg2[8])); + uint64_t x93 = ((uint64_t)(arg1[0]) * (arg2[7])); + uint64_t x94 = ((uint64_t)(arg1[0]) * (arg2[6])); + uint64_t x95 = ((uint64_t)(arg1[0]) * (arg2[5])); + uint64_t x96 = ((uint64_t)(arg1[0]) * (arg2[4])); + uint64_t x97 = ((uint64_t)(arg1[0]) * (arg2[3])); + uint64_t x98 = ((uint64_t)(arg1[0]) * (arg2[2])); + uint64_t x99 = ((uint64_t)(arg1[0]) * (arg2[1])); + uint64_t x100 = ((uint64_t)(arg1[0]) * (arg2[0])); + uint64_t x101 = (x100 + (x45 + (x44 + (x42 + (x39 + (x35 + (x30 + (x24 + (x17 + x9))))))))); + uint64_t x102 = (x101 >> 26); + uint32_t x103 = (uint32_t)(x101 & UINT32_C(0x3ffffff)); + uint64_t x104 = (x91 + (x82 + (x74 + (x67 + (x61 + (x56 + (x52 + (x49 + (x47 + x46))))))))); + uint64_t x105 = (x92 + (x83 + (x75 + (x68 + (x62 + (x57 + (x53 + (x50 + (x48 + x1))))))))); + uint64_t x106 = (x93 + (x84 + (x76 + (x69 + (x63 + (x58 + (x54 + (x51 + (x10 + x2))))))))); + uint64_t x107 = (x94 + (x85 + (x77 + (x70 + (x64 + (x59 + (x55 + (x18 + (x11 + x3))))))))); + uint64_t x108 = (x95 + (x86 + (x78 + (x71 + (x65 + (x60 + (x25 + (x19 + (x12 + x4))))))))); + uint64_t x109 = (x96 + (x87 + (x79 + (x72 + (x66 + (x31 + (x26 + (x20 + (x13 + x5))))))))); + uint64_t x110 = (x97 + (x88 + (x80 + (x73 + (x36 + (x32 + (x27 + (x21 + (x14 + x6))))))))); + uint64_t x111 = (x98 + (x89 + (x81 + (x40 + (x37 + (x33 + (x28 + (x22 + (x15 + x7))))))))); + uint64_t x112 = (x99 + (x90 + (x43 + (x41 + (x38 + (x34 + (x29 + (x23 + (x16 + x8))))))))); + uint64_t x113 = (x102 + x112); + uint64_t x114 = (x113 >> 25); + uint32_t x115 = (uint32_t)(x113 & UINT32_C(0x1ffffff)); + uint64_t x116 = (x114 + x111); + uint64_t x117 = (x116 >> 26); + uint32_t x118 = (uint32_t)(x116 & UINT32_C(0x3ffffff)); + uint64_t x119 = (x117 + x110); + uint64_t x120 = (x119 >> 25); + uint32_t x121 = (uint32_t)(x119 & UINT32_C(0x1ffffff)); + uint64_t x122 = (x120 + x109); + uint64_t x123 = (x122 >> 26); + uint32_t x124 = (uint32_t)(x122 & UINT32_C(0x3ffffff)); + uint64_t x125 = (x123 + x108); + uint64_t x126 = (x125 >> 25); + uint32_t x127 = (uint32_t)(x125 & UINT32_C(0x1ffffff)); + uint64_t x128 = (x126 + x107); + uint64_t x129 = (x128 >> 26); + uint32_t x130 = (uint32_t)(x128 & UINT32_C(0x3ffffff)); + uint64_t x131 = (x129 + x106); + uint64_t x132 = (x131 >> 25); + uint32_t x133 = (uint32_t)(x131 & UINT32_C(0x1ffffff)); + uint64_t x134 = (x132 + x105); + uint64_t x135 = (x134 >> 26); + uint32_t x136 = (uint32_t)(x134 & UINT32_C(0x3ffffff)); + uint64_t x137 = (x135 + x104); + uint64_t x138 = (x137 >> 25); + uint32_t x139 = (uint32_t)(x137 & UINT32_C(0x1ffffff)); + uint64_t x140 = (x138 * (uint64_t)UINT8_C(0x13)); + uint64_t x141 = (x103 + x140); + uint32_t x142 = (uint32_t)(x141 >> 26); + uint32_t x143 = (uint32_t)(x141 & UINT32_C(0x3ffffff)); + uint32_t x144 = (x142 + x115); + uint32_t x145 = (x144 >> 25); + uint32_t x146 = (x144 & UINT32_C(0x1ffffff)); + uint32_t x147 = (x145 + x118); + out1[0] = x143; + out1[1] = x146; + out1[2] = x147; + out1[3] = x121; + out1[4] = x124; + out1[5] = x127; + out1[6] = x130; + out1[7] = x133; + out1[8] = x136; + out1[9] = x139; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999]] + * Output Bounds: + * out1: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]] + */ +static void fiat_25519_carry_square(uint32_t out1[10], const uint32_t arg1[10]) { + uint32_t x1 = ((arg1[9]) * (uint32_t)UINT8_C(0x13)); + uint32_t x2 = (x1 * (uint32_t)0x2); + uint32_t x3 = ((arg1[9]) * (uint32_t)0x2); + uint32_t x4 = ((arg1[8]) * (uint32_t)UINT8_C(0x13)); + uint64_t x5 = (x4 * (uint64_t)0x2); + uint32_t x6 = ((arg1[8]) * (uint32_t)0x2); + uint32_t x7 = ((arg1[7]) * (uint32_t)UINT8_C(0x13)); + uint32_t x8 = (x7 * (uint32_t)0x2); + uint32_t x9 = ((arg1[7]) * (uint32_t)0x2); + uint32_t x10 = ((arg1[6]) * (uint32_t)UINT8_C(0x13)); + uint64_t x11 = (x10 * (uint64_t)0x2); + uint32_t x12 = ((arg1[6]) * (uint32_t)0x2); + uint32_t x13 = ((arg1[5]) * (uint32_t)UINT8_C(0x13)); + uint32_t x14 = ((arg1[5]) * (uint32_t)0x2); + uint32_t x15 = ((arg1[4]) * (uint32_t)0x2); + uint32_t x16 = ((arg1[3]) * (uint32_t)0x2); + uint32_t x17 = ((arg1[2]) * (uint32_t)0x2); + uint32_t x18 = ((arg1[1]) * (uint32_t)0x2); + uint64_t x19 = ((uint64_t)(arg1[9]) * (x1 * (uint32_t)0x2)); + uint64_t x20 = ((uint64_t)(arg1[8]) * x2); + uint64_t x21 = ((uint64_t)(arg1[8]) * x4); + uint64_t x22 = ((arg1[7]) * (x2 * (uint64_t)0x2)); + uint64_t x23 = ((arg1[7]) * x5); + uint64_t x24 = ((uint64_t)(arg1[7]) * (x7 * (uint32_t)0x2)); + uint64_t x25 = ((uint64_t)(arg1[6]) * x2); + uint64_t x26 = ((arg1[6]) * x5); + uint64_t x27 = ((uint64_t)(arg1[6]) * x8); + uint64_t x28 = ((uint64_t)(arg1[6]) * x10); + uint64_t x29 = ((arg1[5]) * (x2 * (uint64_t)0x2)); + uint64_t x30 = ((arg1[5]) * x5); + uint64_t x31 = ((arg1[5]) * (x8 * (uint64_t)0x2)); + uint64_t x32 = ((arg1[5]) * x11); + uint64_t x33 = ((uint64_t)(arg1[5]) * (x13 * (uint32_t)0x2)); + uint64_t x34 = ((uint64_t)(arg1[4]) * x2); + uint64_t x35 = ((arg1[4]) * x5); + uint64_t x36 = ((uint64_t)(arg1[4]) * x8); + uint64_t x37 = ((arg1[4]) * x11); + uint64_t x38 = ((uint64_t)(arg1[4]) * x14); + uint64_t x39 = ((uint64_t)(arg1[4]) * (arg1[4])); + uint64_t x40 = ((arg1[3]) * (x2 * (uint64_t)0x2)); + uint64_t x41 = ((arg1[3]) * x5); + uint64_t x42 = ((arg1[3]) * (x8 * (uint64_t)0x2)); + uint64_t x43 = ((uint64_t)(arg1[3]) * x12); + uint64_t x44 = ((uint64_t)(arg1[3]) * (x14 * (uint32_t)0x2)); + uint64_t x45 = ((uint64_t)(arg1[3]) * x15); + uint64_t x46 = ((uint64_t)(arg1[3]) * ((arg1[3]) * (uint32_t)0x2)); + uint64_t x47 = ((uint64_t)(arg1[2]) * x2); + uint64_t x48 = ((arg1[2]) * x5); + uint64_t x49 = ((uint64_t)(arg1[2]) * x9); + uint64_t x50 = ((uint64_t)(arg1[2]) * x12); + uint64_t x51 = ((uint64_t)(arg1[2]) * x14); + uint64_t x52 = ((uint64_t)(arg1[2]) * x15); + uint64_t x53 = ((uint64_t)(arg1[2]) * x16); + uint64_t x54 = ((uint64_t)(arg1[2]) * (arg1[2])); + uint64_t x55 = ((arg1[1]) * (x2 * (uint64_t)0x2)); + uint64_t x56 = ((uint64_t)(arg1[1]) * x6); + uint64_t x57 = ((uint64_t)(arg1[1]) * (x9 * (uint32_t)0x2)); + uint64_t x58 = ((uint64_t)(arg1[1]) * x12); + uint64_t x59 = ((uint64_t)(arg1[1]) * (x14 * (uint32_t)0x2)); + uint64_t x60 = ((uint64_t)(arg1[1]) * x15); + uint64_t x61 = ((uint64_t)(arg1[1]) * (x16 * (uint32_t)0x2)); + uint64_t x62 = ((uint64_t)(arg1[1]) * x17); + uint64_t x63 = ((uint64_t)(arg1[1]) * ((arg1[1]) * (uint32_t)0x2)); + uint64_t x64 = ((uint64_t)(arg1[0]) * x3); + uint64_t x65 = ((uint64_t)(arg1[0]) * x6); + uint64_t x66 = ((uint64_t)(arg1[0]) * x9); + uint64_t x67 = ((uint64_t)(arg1[0]) * x12); + uint64_t x68 = ((uint64_t)(arg1[0]) * x14); + uint64_t x69 = ((uint64_t)(arg1[0]) * x15); + uint64_t x70 = ((uint64_t)(arg1[0]) * x16); + uint64_t x71 = ((uint64_t)(arg1[0]) * x17); + uint64_t x72 = ((uint64_t)(arg1[0]) * x18); + uint64_t x73 = ((uint64_t)(arg1[0]) * (arg1[0])); + uint64_t x74 = (x73 + (x55 + (x48 + (x42 + (x37 + x33))))); + uint64_t x75 = (x74 >> 26); + uint32_t x76 = (uint32_t)(x74 & UINT32_C(0x3ffffff)); + uint64_t x77 = (x64 + (x56 + (x49 + (x43 + x38)))); + uint64_t x78 = (x65 + (x57 + (x50 + (x44 + (x39 + x19))))); + uint64_t x79 = (x66 + (x58 + (x51 + (x45 + x20)))); + uint64_t x80 = (x67 + (x59 + (x52 + (x46 + (x22 + x21))))); + uint64_t x81 = (x68 + (x60 + (x53 + (x25 + x23)))); + uint64_t x82 = (x69 + (x61 + (x54 + (x29 + (x26 + x24))))); + uint64_t x83 = (x70 + (x62 + (x34 + (x30 + x27)))); + uint64_t x84 = (x71 + (x63 + (x40 + (x35 + (x31 + x28))))); + uint64_t x85 = (x72 + (x47 + (x41 + (x36 + x32)))); + uint64_t x86 = (x75 + x85); + uint64_t x87 = (x86 >> 25); + uint32_t x88 = (uint32_t)(x86 & UINT32_C(0x1ffffff)); + uint64_t x89 = (x87 + x84); + uint64_t x90 = (x89 >> 26); + uint32_t x91 = (uint32_t)(x89 & UINT32_C(0x3ffffff)); + uint64_t x92 = (x90 + x83); + uint64_t x93 = (x92 >> 25); + uint32_t x94 = (uint32_t)(x92 & UINT32_C(0x1ffffff)); + uint64_t x95 = (x93 + x82); + uint64_t x96 = (x95 >> 26); + uint32_t x97 = (uint32_t)(x95 & UINT32_C(0x3ffffff)); + uint64_t x98 = (x96 + x81); + uint64_t x99 = (x98 >> 25); + uint32_t x100 = (uint32_t)(x98 & UINT32_C(0x1ffffff)); + uint64_t x101 = (x99 + x80); + uint64_t x102 = (x101 >> 26); + uint32_t x103 = (uint32_t)(x101 & UINT32_C(0x3ffffff)); + uint64_t x104 = (x102 + x79); + uint64_t x105 = (x104 >> 25); + uint32_t x106 = (uint32_t)(x104 & UINT32_C(0x1ffffff)); + uint64_t x107 = (x105 + x78); + uint64_t x108 = (x107 >> 26); + uint32_t x109 = (uint32_t)(x107 & UINT32_C(0x3ffffff)); + uint64_t x110 = (x108 + x77); + uint64_t x111 = (x110 >> 25); + uint32_t x112 = (uint32_t)(x110 & UINT32_C(0x1ffffff)); + uint64_t x113 = (x111 * (uint64_t)UINT8_C(0x13)); + uint64_t x114 = (x76 + x113); + uint32_t x115 = (uint32_t)(x114 >> 26); + uint32_t x116 = (uint32_t)(x114 & UINT32_C(0x3ffffff)); + uint32_t x117 = (x115 + x88); + uint32_t x118 = (x117 >> 25); + uint32_t x119 = (x117 & UINT32_C(0x1ffffff)); + uint32_t x120 = (x118 + x91); + out1[0] = x116; + out1[1] = x119; + out1[2] = x120; + out1[3] = x94; + out1[4] = x97; + out1[5] = x100; + out1[6] = x103; + out1[7] = x106; + out1[8] = x109; + out1[9] = x112; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999]] + * Output Bounds: + * out1: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]] + */ +static void fiat_25519_carry(uint32_t out1[10], const uint32_t arg1[10]) { + uint32_t x1 = (arg1[0]); + uint32_t x2 = ((x1 >> 26) + (arg1[1])); + uint32_t x3 = ((x2 >> 25) + (arg1[2])); + uint32_t x4 = ((x3 >> 26) + (arg1[3])); + uint32_t x5 = ((x4 >> 25) + (arg1[4])); + uint32_t x6 = ((x5 >> 26) + (arg1[5])); + uint32_t x7 = ((x6 >> 25) + (arg1[6])); + uint32_t x8 = ((x7 >> 26) + (arg1[7])); + uint32_t x9 = ((x8 >> 25) + (arg1[8])); + uint32_t x10 = ((x9 >> 26) + (arg1[9])); + uint32_t x11 = ((x1 & UINT32_C(0x3ffffff)) + ((x10 >> 25) * (uint32_t)UINT8_C(0x13))); + uint32_t x12 = ((x11 >> 26) + (x2 & UINT32_C(0x1ffffff))); + uint32_t x13 = (x11 & UINT32_C(0x3ffffff)); + uint32_t x14 = (x12 & UINT32_C(0x1ffffff)); + uint32_t x15 = ((x12 >> 25) + (x3 & UINT32_C(0x3ffffff))); + uint32_t x16 = (x4 & UINT32_C(0x1ffffff)); + uint32_t x17 = (x5 & UINT32_C(0x3ffffff)); + uint32_t x18 = (x6 & UINT32_C(0x1ffffff)); + uint32_t x19 = (x7 & UINT32_C(0x3ffffff)); + uint32_t x20 = (x8 & UINT32_C(0x1ffffff)); + uint32_t x21 = (x9 & UINT32_C(0x3ffffff)); + uint32_t x22 = (x10 & UINT32_C(0x1ffffff)); + out1[0] = x13; + out1[1] = x14; + out1[2] = x15; + out1[3] = x16; + out1[4] = x17; + out1[5] = x18; + out1[6] = x19; + out1[7] = x20; + out1[8] = x21; + out1[9] = x22; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]] + * arg2: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]] + * Output Bounds: + * out1: [[0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999]] + */ +static void fiat_25519_add(uint32_t out1[10], const uint32_t arg1[10], const uint32_t arg2[10]) { + uint32_t x1 = ((arg1[0]) + (arg2[0])); + uint32_t x2 = ((arg1[1]) + (arg2[1])); + uint32_t x3 = ((arg1[2]) + (arg2[2])); + uint32_t x4 = ((arg1[3]) + (arg2[3])); + uint32_t x5 = ((arg1[4]) + (arg2[4])); + uint32_t x6 = ((arg1[5]) + (arg2[5])); + uint32_t x7 = ((arg1[6]) + (arg2[6])); + uint32_t x8 = ((arg1[7]) + (arg2[7])); + uint32_t x9 = ((arg1[8]) + (arg2[8])); + uint32_t x10 = ((arg1[9]) + (arg2[9])); + out1[0] = x1; + out1[1] = x2; + out1[2] = x3; + out1[3] = x4; + out1[4] = x5; + out1[5] = x6; + out1[6] = x7; + out1[7] = x8; + out1[8] = x9; + out1[9] = x10; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]] + * arg2: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]] + * Output Bounds: + * out1: [[0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999]] + */ +static void fiat_25519_sub(uint32_t out1[10], const uint32_t arg1[10], const uint32_t arg2[10]) { + uint32_t x1 = ((UINT32_C(0x7ffffda) + (arg1[0])) - (arg2[0])); + uint32_t x2 = ((UINT32_C(0x3fffffe) + (arg1[1])) - (arg2[1])); + uint32_t x3 = ((UINT32_C(0x7fffffe) + (arg1[2])) - (arg2[2])); + uint32_t x4 = ((UINT32_C(0x3fffffe) + (arg1[3])) - (arg2[3])); + uint32_t x5 = ((UINT32_C(0x7fffffe) + (arg1[4])) - (arg2[4])); + uint32_t x6 = ((UINT32_C(0x3fffffe) + (arg1[5])) - (arg2[5])); + uint32_t x7 = ((UINT32_C(0x7fffffe) + (arg1[6])) - (arg2[6])); + uint32_t x8 = ((UINT32_C(0x3fffffe) + (arg1[7])) - (arg2[7])); + uint32_t x9 = ((UINT32_C(0x7fffffe) + (arg1[8])) - (arg2[8])); + uint32_t x10 = ((UINT32_C(0x3fffffe) + (arg1[9])) - (arg2[9])); + out1[0] = x1; + out1[1] = x2; + out1[2] = x3; + out1[3] = x4; + out1[4] = x5; + out1[5] = x6; + out1[6] = x7; + out1[7] = x8; + out1[8] = x9; + out1[9] = x10; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]] + * Output Bounds: + * out1: [[0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999], [0x0 ~> 0xd333332], [0x0 ~> 0x6999999]] + */ +static void fiat_25519_opp(uint32_t out1[10], const uint32_t arg1[10]) { + uint32_t x1 = (UINT32_C(0x7ffffda) - (arg1[0])); + uint32_t x2 = (UINT32_C(0x3fffffe) - (arg1[1])); + uint32_t x3 = (UINT32_C(0x7fffffe) - (arg1[2])); + uint32_t x4 = (UINT32_C(0x3fffffe) - (arg1[3])); + uint32_t x5 = (UINT32_C(0x7fffffe) - (arg1[4])); + uint32_t x6 = (UINT32_C(0x3fffffe) - (arg1[5])); + uint32_t x7 = (UINT32_C(0x7fffffe) - (arg1[6])); + uint32_t x8 = (UINT32_C(0x3fffffe) - (arg1[7])); + uint32_t x9 = (UINT32_C(0x7fffffe) - (arg1[8])); + uint32_t x10 = (UINT32_C(0x3fffffe) - (arg1[9])); + out1[0] = x1; + out1[1] = x2; + out1[2] = x3; + out1[3] = x4; + out1[4] = x5; + out1[5] = x6; + out1[6] = x7; + out1[7] = x8; + out1[8] = x9; + out1[9] = x10; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]] + * Output Bounds: + * out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x7f]] + */ +static void fiat_25519_to_bytes(uint8_t out1[32], const uint32_t arg1[10]) { + uint32_t x1; + fiat_25519_uint1 x2; + fiat_25519_subborrowx_u26(&x1, &x2, 0x0, (arg1[0]), UINT32_C(0x3ffffed)); + uint32_t x3; + fiat_25519_uint1 x4; + fiat_25519_subborrowx_u25(&x3, &x4, x2, (arg1[1]), UINT32_C(0x1ffffff)); + uint32_t x5; + fiat_25519_uint1 x6; + fiat_25519_subborrowx_u26(&x5, &x6, x4, (arg1[2]), UINT32_C(0x3ffffff)); + uint32_t x7; + fiat_25519_uint1 x8; + fiat_25519_subborrowx_u25(&x7, &x8, x6, (arg1[3]), UINT32_C(0x1ffffff)); + uint32_t x9; + fiat_25519_uint1 x10; + fiat_25519_subborrowx_u26(&x9, &x10, x8, (arg1[4]), UINT32_C(0x3ffffff)); + uint32_t x11; + fiat_25519_uint1 x12; + fiat_25519_subborrowx_u25(&x11, &x12, x10, (arg1[5]), UINT32_C(0x1ffffff)); + uint32_t x13; + fiat_25519_uint1 x14; + fiat_25519_subborrowx_u26(&x13, &x14, x12, (arg1[6]), UINT32_C(0x3ffffff)); + uint32_t x15; + fiat_25519_uint1 x16; + fiat_25519_subborrowx_u25(&x15, &x16, x14, (arg1[7]), UINT32_C(0x1ffffff)); + uint32_t x17; + fiat_25519_uint1 x18; + fiat_25519_subborrowx_u26(&x17, &x18, x16, (arg1[8]), UINT32_C(0x3ffffff)); + uint32_t x19; + fiat_25519_uint1 x20; + fiat_25519_subborrowx_u25(&x19, &x20, x18, (arg1[9]), UINT32_C(0x1ffffff)); + uint32_t x21; + fiat_25519_cmovznz_u32(&x21, x20, 0x0, UINT32_C(0xffffffff)); + uint32_t x22; + fiat_25519_uint1 x23; + fiat_25519_addcarryx_u26(&x22, &x23, 0x0, (x21 & UINT32_C(0x3ffffed)), x1); + uint32_t x24; + fiat_25519_uint1 x25; + fiat_25519_addcarryx_u25(&x24, &x25, x23, (x21 & UINT32_C(0x1ffffff)), x3); + uint32_t x26; + fiat_25519_uint1 x27; + fiat_25519_addcarryx_u26(&x26, &x27, x25, (x21 & UINT32_C(0x3ffffff)), x5); + uint32_t x28; + fiat_25519_uint1 x29; + fiat_25519_addcarryx_u25(&x28, &x29, x27, (x21 & UINT32_C(0x1ffffff)), x7); + uint32_t x30; + fiat_25519_uint1 x31; + fiat_25519_addcarryx_u26(&x30, &x31, x29, (x21 & UINT32_C(0x3ffffff)), x9); + uint32_t x32; + fiat_25519_uint1 x33; + fiat_25519_addcarryx_u25(&x32, &x33, x31, (x21 & UINT32_C(0x1ffffff)), x11); + uint32_t x34; + fiat_25519_uint1 x35; + fiat_25519_addcarryx_u26(&x34, &x35, x33, (x21 & UINT32_C(0x3ffffff)), x13); + uint32_t x36; + fiat_25519_uint1 x37; + fiat_25519_addcarryx_u25(&x36, &x37, x35, (x21 & UINT32_C(0x1ffffff)), x15); + uint32_t x38; + fiat_25519_uint1 x39; + fiat_25519_addcarryx_u26(&x38, &x39, x37, (x21 & UINT32_C(0x3ffffff)), x17); + uint32_t x40; + fiat_25519_uint1 x41; + fiat_25519_addcarryx_u25(&x40, &x41, x39, (x21 & UINT32_C(0x1ffffff)), x19); + uint32_t x42 = (x40 << 6); + uint32_t x43 = (x38 << 4); + uint32_t x44 = (x36 << 3); + uint32_t x45 = (x34 * (uint32_t)0x2); + uint32_t x46 = (x30 << 6); + uint32_t x47 = (x28 << 5); + uint32_t x48 = (x26 << 3); + uint32_t x49 = (x24 << 2); + uint32_t x50 = (x22 >> 8); + uint8_t x51 = (uint8_t)(x22 & UINT8_C(0xff)); + uint32_t x52 = (x50 >> 8); + uint8_t x53 = (uint8_t)(x50 & UINT8_C(0xff)); + uint8_t x54 = (uint8_t)(x52 >> 8); + uint8_t x55 = (uint8_t)(x52 & UINT8_C(0xff)); + uint32_t x56 = (x54 + x49); + uint32_t x57 = (x56 >> 8); + uint8_t x58 = (uint8_t)(x56 & UINT8_C(0xff)); + uint32_t x59 = (x57 >> 8); + uint8_t x60 = (uint8_t)(x57 & UINT8_C(0xff)); + uint8_t x61 = (uint8_t)(x59 >> 8); + uint8_t x62 = (uint8_t)(x59 & UINT8_C(0xff)); + uint32_t x63 = (x61 + x48); + uint32_t x64 = (x63 >> 8); + uint8_t x65 = (uint8_t)(x63 & UINT8_C(0xff)); + uint32_t x66 = (x64 >> 8); + uint8_t x67 = (uint8_t)(x64 & UINT8_C(0xff)); + uint8_t x68 = (uint8_t)(x66 >> 8); + uint8_t x69 = (uint8_t)(x66 & UINT8_C(0xff)); + uint32_t x70 = (x68 + x47); + uint32_t x71 = (x70 >> 8); + uint8_t x72 = (uint8_t)(x70 & UINT8_C(0xff)); + uint32_t x73 = (x71 >> 8); + uint8_t x74 = (uint8_t)(x71 & UINT8_C(0xff)); + uint8_t x75 = (uint8_t)(x73 >> 8); + uint8_t x76 = (uint8_t)(x73 & UINT8_C(0xff)); + uint32_t x77 = (x75 + x46); + uint32_t x78 = (x77 >> 8); + uint8_t x79 = (uint8_t)(x77 & UINT8_C(0xff)); + uint32_t x80 = (x78 >> 8); + uint8_t x81 = (uint8_t)(x78 & UINT8_C(0xff)); + uint8_t x82 = (uint8_t)(x80 >> 8); + uint8_t x83 = (uint8_t)(x80 & UINT8_C(0xff)); + uint8_t x84 = (uint8_t)(x82 & UINT8_C(0xff)); + uint32_t x85 = (x32 >> 8); + uint8_t x86 = (uint8_t)(x32 & UINT8_C(0xff)); + uint32_t x87 = (x85 >> 8); + uint8_t x88 = (uint8_t)(x85 & UINT8_C(0xff)); + fiat_25519_uint1 x89 = (fiat_25519_uint1)(x87 >> 8); + uint8_t x90 = (uint8_t)(x87 & UINT8_C(0xff)); + uint32_t x91 = (x89 + x45); + uint32_t x92 = (x91 >> 8); + uint8_t x93 = (uint8_t)(x91 & UINT8_C(0xff)); + uint32_t x94 = (x92 >> 8); + uint8_t x95 = (uint8_t)(x92 & UINT8_C(0xff)); + uint8_t x96 = (uint8_t)(x94 >> 8); + uint8_t x97 = (uint8_t)(x94 & UINT8_C(0xff)); + uint32_t x98 = (x96 + x44); + uint32_t x99 = (x98 >> 8); + uint8_t x100 = (uint8_t)(x98 & UINT8_C(0xff)); + uint32_t x101 = (x99 >> 8); + uint8_t x102 = (uint8_t)(x99 & UINT8_C(0xff)); + uint8_t x103 = (uint8_t)(x101 >> 8); + uint8_t x104 = (uint8_t)(x101 & UINT8_C(0xff)); + uint32_t x105 = (x103 + x43); + uint32_t x106 = (x105 >> 8); + uint8_t x107 = (uint8_t)(x105 & UINT8_C(0xff)); + uint32_t x108 = (x106 >> 8); + uint8_t x109 = (uint8_t)(x106 & UINT8_C(0xff)); + uint8_t x110 = (uint8_t)(x108 >> 8); + uint8_t x111 = (uint8_t)(x108 & UINT8_C(0xff)); + uint32_t x112 = (x110 + x42); + uint32_t x113 = (x112 >> 8); + uint8_t x114 = (uint8_t)(x112 & UINT8_C(0xff)); + uint32_t x115 = (x113 >> 8); + uint8_t x116 = (uint8_t)(x113 & UINT8_C(0xff)); + uint8_t x117 = (uint8_t)(x115 >> 8); + uint8_t x118 = (uint8_t)(x115 & UINT8_C(0xff)); + out1[0] = x51; + out1[1] = x53; + out1[2] = x55; + out1[3] = x58; + out1[4] = x60; + out1[5] = x62; + out1[6] = x65; + out1[7] = x67; + out1[8] = x69; + out1[9] = x72; + out1[10] = x74; + out1[11] = x76; + out1[12] = x79; + out1[13] = x81; + out1[14] = x83; + out1[15] = x84; + out1[16] = x86; + out1[17] = x88; + out1[18] = x90; + out1[19] = x93; + out1[20] = x95; + out1[21] = x97; + out1[22] = x100; + out1[23] = x102; + out1[24] = x104; + out1[25] = x107; + out1[26] = x109; + out1[27] = x111; + out1[28] = x114; + out1[29] = x116; + out1[30] = x118; + out1[31] = x117; +} + +/* + * Input Bounds: + * arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x7f]] + * Output Bounds: + * out1: [[0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333], [0x0 ~> 0x4666666], [0x0 ~> 0x2333333]] + */ +static void fiat_25519_from_bytes(uint32_t out1[10], const uint8_t arg1[32]) { + uint32_t x1 = ((uint32_t)(arg1[31]) << 18); + uint32_t x2 = ((uint32_t)(arg1[30]) << 10); + uint32_t x3 = ((uint32_t)(arg1[29]) << 2); + uint32_t x4 = ((uint32_t)(arg1[28]) << 20); + uint32_t x5 = ((uint32_t)(arg1[27]) << 12); + uint32_t x6 = ((uint32_t)(arg1[26]) << 4); + uint32_t x7 = ((uint32_t)(arg1[25]) << 21); + uint32_t x8 = ((uint32_t)(arg1[24]) << 13); + uint32_t x9 = ((uint32_t)(arg1[23]) << 5); + uint32_t x10 = ((uint32_t)(arg1[22]) << 23); + uint32_t x11 = ((uint32_t)(arg1[21]) << 15); + uint32_t x12 = ((uint32_t)(arg1[20]) << 7); + uint32_t x13 = ((uint32_t)(arg1[19]) << 24); + uint32_t x14 = ((uint32_t)(arg1[18]) << 16); + uint32_t x15 = ((uint32_t)(arg1[17]) << 8); + uint8_t x16 = (arg1[16]); + uint32_t x17 = ((uint32_t)(arg1[15]) << 18); + uint32_t x18 = ((uint32_t)(arg1[14]) << 10); + uint32_t x19 = ((uint32_t)(arg1[13]) << 2); + uint32_t x20 = ((uint32_t)(arg1[12]) << 19); + uint32_t x21 = ((uint32_t)(arg1[11]) << 11); + uint32_t x22 = ((uint32_t)(arg1[10]) << 3); + uint32_t x23 = ((uint32_t)(arg1[9]) << 21); + uint32_t x24 = ((uint32_t)(arg1[8]) << 13); + uint32_t x25 = ((uint32_t)(arg1[7]) << 5); + uint32_t x26 = ((uint32_t)(arg1[6]) << 22); + uint32_t x27 = ((uint32_t)(arg1[5]) << 14); + uint32_t x28 = ((uint32_t)(arg1[4]) << 6); + uint32_t x29 = ((uint32_t)(arg1[3]) << 24); + uint32_t x30 = ((uint32_t)(arg1[2]) << 16); + uint32_t x31 = ((uint32_t)(arg1[1]) << 8); + uint8_t x32 = (arg1[0]); + uint32_t x33 = (x32 + (x31 + (x30 + x29))); + uint8_t x34 = (uint8_t)(x33 >> 26); + uint32_t x35 = (x33 & UINT32_C(0x3ffffff)); + uint32_t x36 = (x3 + (x2 + x1)); + uint32_t x37 = (x6 + (x5 + x4)); + uint32_t x38 = (x9 + (x8 + x7)); + uint32_t x39 = (x12 + (x11 + x10)); + uint32_t x40 = (x16 + (x15 + (x14 + x13))); + uint32_t x41 = (x19 + (x18 + x17)); + uint32_t x42 = (x22 + (x21 + x20)); + uint32_t x43 = (x25 + (x24 + x23)); + uint32_t x44 = (x28 + (x27 + x26)); + uint32_t x45 = (x34 + x44); + uint8_t x46 = (uint8_t)(x45 >> 25); + uint32_t x47 = (x45 & UINT32_C(0x1ffffff)); + uint32_t x48 = (x46 + x43); + uint8_t x49 = (uint8_t)(x48 >> 26); + uint32_t x50 = (x48 & UINT32_C(0x3ffffff)); + uint32_t x51 = (x49 + x42); + uint8_t x52 = (uint8_t)(x51 >> 25); + uint32_t x53 = (x51 & UINT32_C(0x1ffffff)); + uint32_t x54 = (x52 + x41); + uint32_t x55 = (x54 & UINT32_C(0x3ffffff)); + uint8_t x56 = (uint8_t)(x40 >> 25); + uint32_t x57 = (x40 & UINT32_C(0x1ffffff)); + uint32_t x58 = (x56 + x39); + uint8_t x59 = (uint8_t)(x58 >> 26); + uint32_t x60 = (x58 & UINT32_C(0x3ffffff)); + uint32_t x61 = (x59 + x38); + uint8_t x62 = (uint8_t)(x61 >> 25); + uint32_t x63 = (x61 & UINT32_C(0x1ffffff)); + uint32_t x64 = (x62 + x37); + uint8_t x65 = (uint8_t)(x64 >> 26); + uint32_t x66 = (x64 & UINT32_C(0x3ffffff)); + uint32_t x67 = (x65 + x36); + out1[0] = x35; + out1[1] = x47; + out1[2] = x50; + out1[3] = x53; + out1[4] = x55; + out1[5] = x57; + out1[6] = x60; + out1[7] = x63; + out1[8] = x66; + out1[9] = x67; +} + +#endif /* not defined(BORINGSSL_CURVE25519_64BIT) */ diff --git a/krb5-1.21.3/src/plugins/preauth/spake/edwards25519_tables.h b/krb5-1.21.3/src/plugins/preauth/spake/edwards25519_tables.h new file mode 100644 index 00000000..c6c50137 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/edwards25519_tables.h @@ -0,0 +1,7881 @@ +/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil -*- */ +/* + * The MIT License (MIT) + * + * Copyright (c) 2015-2016 the fiat-crypto authors (see the AUTHORS file). + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* From BoringSSL third-party/fiat/curve25519_tables.h */ + +static const fe d = {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 929955233495203, 466365720129213, 1662059464998953, 2033849074728123, + 1442794654840575 +#else + 56195235, 13857412, 51736253, 6949390, 114729, 24766616, 60832955, 30306712, + 48412415, 21499315 +#endif +}}; + +static const fe sqrtm1 = {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1718705420411056, 234908883556509, 2233514472574048, 2117202627021982, + 765476049583133 +#else + 34513072, 25610706, 9377949, 3500415, 12389472, 33281959, 41962654, + 31548777, 326685, 11406482 +#endif +}}; + +static const fe d2 = {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1859910466990425, 932731440258426, 1072319116312658, 1815898335770999, + 633789495995903 +#else + 45281625, 27714825, 36363642, 13898781, 229458, 15978800, 54557047, + 27058993, 29715967, 9444199 +#endif +}}; + +#if defined(CONFIG_SMALL) + +// This block of code replaces the standard base-point table with a much smaller +// one. The standard table is 30,720 bytes while this one is just 960. +// +// This table contains 15 pairs of group elements, (x, y), where each field +// element is serialised with |fe_tobytes|. If |i| is the index of the group +// element then consider i+1 as a four-bit number: (i₀, i₁, i₂, i₃) (where i₀ +// is the most significant bit). The value of the group element is then: +// (i₀×2^192 + i₁×2^128 + i₂×2^64 + i₃)G, where G is the generator. +static const uint8_t k25519SmallPrecomp[15 * 2 * 32] = { + 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95, + 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, + 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21, 0x58, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x02, 0xa2, 0xed, 0xf4, 0x8f, 0x6b, 0x0b, 0x3e, + 0xeb, 0x35, 0x1a, 0xd5, 0x7e, 0xdb, 0x78, 0x00, 0x96, 0x8a, 0xa0, 0xb4, + 0xcf, 0x60, 0x4b, 0xd4, 0xd5, 0xf9, 0x2d, 0xbf, 0x88, 0xbd, 0x22, 0x62, + 0x13, 0x53, 0xe4, 0x82, 0x57, 0xfa, 0x1e, 0x8f, 0x06, 0x2b, 0x90, 0xba, + 0x08, 0xb6, 0x10, 0x54, 0x4f, 0x7c, 0x1b, 0x26, 0xed, 0xda, 0x6b, 0xdd, + 0x25, 0xd0, 0x4e, 0xea, 0x42, 0xbb, 0x25, 0x03, 0xa2, 0xfb, 0xcc, 0x61, + 0x67, 0x06, 0x70, 0x1a, 0xc4, 0x78, 0x3a, 0xff, 0x32, 0x62, 0xdd, 0x2c, + 0xab, 0x50, 0x19, 0x3b, 0xf2, 0x9b, 0x7d, 0xb8, 0xfd, 0x4f, 0x29, 0x9c, + 0xa7, 0x91, 0xba, 0x0e, 0x46, 0x5e, 0x51, 0xfe, 0x1d, 0xbf, 0xe5, 0xe5, + 0x9b, 0x95, 0x0d, 0x67, 0xf8, 0xd1, 0xb5, 0x5a, 0xa1, 0x93, 0x2c, 0xc3, + 0xde, 0x0e, 0x97, 0x85, 0x2d, 0x7f, 0xea, 0xab, 0x3e, 0x47, 0x30, 0x18, + 0x24, 0xe8, 0xb7, 0x60, 0xae, 0x47, 0x80, 0xfc, 0xe5, 0x23, 0xe7, 0xc2, + 0xc9, 0x85, 0xe6, 0x98, 0xa0, 0x29, 0x4e, 0xe1, 0x84, 0x39, 0x2d, 0x95, + 0x2c, 0xf3, 0x45, 0x3c, 0xff, 0xaf, 0x27, 0x4c, 0x6b, 0xa6, 0xf5, 0x4b, + 0x11, 0xbd, 0xba, 0x5b, 0x9e, 0xc4, 0xa4, 0x51, 0x1e, 0xbe, 0xd0, 0x90, + 0x3a, 0x9c, 0xc2, 0x26, 0xb6, 0x1e, 0xf1, 0x95, 0x7d, 0xc8, 0x6d, 0x52, + 0xe6, 0x99, 0x2c, 0x5f, 0x9a, 0x96, 0x0c, 0x68, 0x29, 0xfd, 0xe2, 0xfb, + 0xe6, 0xbc, 0xec, 0x31, 0x08, 0xec, 0xe6, 0xb0, 0x53, 0x60, 0xc3, 0x8c, + 0xbe, 0xc1, 0xb3, 0x8a, 0x8f, 0xe4, 0x88, 0x2b, 0x55, 0xe5, 0x64, 0x6e, + 0x9b, 0xd0, 0xaf, 0x7b, 0x64, 0x2a, 0x35, 0x25, 0x10, 0x52, 0xc5, 0x9e, + 0x58, 0x11, 0x39, 0x36, 0x45, 0x51, 0xb8, 0x39, 0x93, 0xfc, 0x9d, 0x6a, + 0xbe, 0x58, 0xcb, 0xa4, 0x0f, 0x51, 0x3c, 0x38, 0x05, 0xca, 0xab, 0x43, + 0x63, 0x0e, 0xf3, 0x8b, 0x41, 0xa6, 0xf8, 0x9b, 0x53, 0x70, 0x80, 0x53, + 0x86, 0x5e, 0x8f, 0xe3, 0xc3, 0x0d, 0x18, 0xc8, 0x4b, 0x34, 0x1f, 0xd8, + 0x1d, 0xbc, 0xf2, 0x6d, 0x34, 0x3a, 0xbe, 0xdf, 0xd9, 0xf6, 0xf3, 0x89, + 0xa1, 0xe1, 0x94, 0x9f, 0x5d, 0x4c, 0x5d, 0xe9, 0xa1, 0x49, 0x92, 0xef, + 0x0e, 0x53, 0x81, 0x89, 0x58, 0x87, 0xa6, 0x37, 0xf1, 0xdd, 0x62, 0x60, + 0x63, 0x5a, 0x9d, 0x1b, 0x8c, 0xc6, 0x7d, 0x52, 0xea, 0x70, 0x09, 0x6a, + 0xe1, 0x32, 0xf3, 0x73, 0x21, 0x1f, 0x07, 0x7b, 0x7c, 0x9b, 0x49, 0xd8, + 0xc0, 0xf3, 0x25, 0x72, 0x6f, 0x9d, 0xed, 0x31, 0x67, 0x36, 0x36, 0x54, + 0x40, 0x92, 0x71, 0xe6, 0x11, 0x28, 0x11, 0xad, 0x93, 0x32, 0x85, 0x7b, + 0x3e, 0xb7, 0x3b, 0x49, 0x13, 0x1c, 0x07, 0xb0, 0x2e, 0x93, 0xaa, 0xfd, + 0xfd, 0x28, 0x47, 0x3d, 0x8d, 0xd2, 0xda, 0xc7, 0x44, 0xd6, 0x7a, 0xdb, + 0x26, 0x7d, 0x1d, 0xb8, 0xe1, 0xde, 0x9d, 0x7a, 0x7d, 0x17, 0x7e, 0x1c, + 0x37, 0x04, 0x8d, 0x2d, 0x7c, 0x5e, 0x18, 0x38, 0x1e, 0xaf, 0xc7, 0x1b, + 0x33, 0x48, 0x31, 0x00, 0x59, 0xf6, 0xf2, 0xca, 0x0f, 0x27, 0x1b, 0x63, + 0x12, 0x7e, 0x02, 0x1d, 0x49, 0xc0, 0x5d, 0x79, 0x87, 0xef, 0x5e, 0x7a, + 0x2f, 0x1f, 0x66, 0x55, 0xd8, 0x09, 0xd9, 0x61, 0x38, 0x68, 0xb0, 0x07, + 0xa3, 0xfc, 0xcc, 0x85, 0x10, 0x7f, 0x4c, 0x65, 0x65, 0xb3, 0xfa, 0xfa, + 0xa5, 0x53, 0x6f, 0xdb, 0x74, 0x4c, 0x56, 0x46, 0x03, 0xe2, 0xd5, 0x7a, + 0x29, 0x1c, 0xc6, 0x02, 0xbc, 0x59, 0xf2, 0x04, 0x75, 0x63, 0xc0, 0x84, + 0x2f, 0x60, 0x1c, 0x67, 0x76, 0xfd, 0x63, 0x86, 0xf3, 0xfa, 0xbf, 0xdc, + 0xd2, 0x2d, 0x90, 0x91, 0xbd, 0x33, 0xa9, 0xe5, 0x66, 0x0c, 0xda, 0x42, + 0x27, 0xca, 0xf4, 0x66, 0xc2, 0xec, 0x92, 0x14, 0x57, 0x06, 0x63, 0xd0, + 0x4d, 0x15, 0x06, 0xeb, 0x69, 0x58, 0x4f, 0x77, 0xc5, 0x8b, 0xc7, 0xf0, + 0x8e, 0xed, 0x64, 0xa0, 0xb3, 0x3c, 0x66, 0x71, 0xc6, 0x2d, 0xda, 0x0a, + 0x0d, 0xfe, 0x70, 0x27, 0x64, 0xf8, 0x27, 0xfa, 0xf6, 0x5f, 0x30, 0xa5, + 0x0d, 0x6c, 0xda, 0xf2, 0x62, 0x5e, 0x78, 0x47, 0xd3, 0x66, 0x00, 0x1c, + 0xfd, 0x56, 0x1f, 0x5d, 0x3f, 0x6f, 0xf4, 0x4c, 0xd8, 0xfd, 0x0e, 0x27, + 0xc9, 0x5c, 0x2b, 0xbc, 0xc0, 0xa4, 0xe7, 0x23, 0x29, 0x02, 0x9f, 0x31, + 0xd6, 0xe9, 0xd7, 0x96, 0xf4, 0xe0, 0x5e, 0x0b, 0x0e, 0x13, 0xee, 0x3c, + 0x09, 0xed, 0xf2, 0x3d, 0x76, 0x91, 0xc3, 0xa4, 0x97, 0xae, 0xd4, 0x87, + 0xd0, 0x5d, 0xf6, 0x18, 0x47, 0x1f, 0x1d, 0x67, 0xf2, 0xcf, 0x63, 0xa0, + 0x91, 0x27, 0xf8, 0x93, 0x45, 0x75, 0x23, 0x3f, 0xd1, 0xf1, 0xad, 0x23, + 0xdd, 0x64, 0x93, 0x96, 0x41, 0x70, 0x7f, 0xf7, 0xf5, 0xa9, 0x89, 0xa2, + 0x34, 0xb0, 0x8d, 0x1b, 0xae, 0x19, 0x15, 0x49, 0x58, 0x23, 0x6d, 0x87, + 0x15, 0x4f, 0x81, 0x76, 0xfb, 0x23, 0xb5, 0xea, 0xcf, 0xac, 0x54, 0x8d, + 0x4e, 0x42, 0x2f, 0xeb, 0x0f, 0x63, 0xdb, 0x68, 0x37, 0xa8, 0xcf, 0x8b, + 0xab, 0xf5, 0xa4, 0x6e, 0x96, 0x2a, 0xb2, 0xd6, 0xbe, 0x9e, 0xbd, 0x0d, + 0xb4, 0x42, 0xa9, 0xcf, 0x01, 0x83, 0x8a, 0x17, 0x47, 0x76, 0xc4, 0xc6, + 0x83, 0x04, 0x95, 0x0b, 0xfc, 0x11, 0xc9, 0x62, 0xb8, 0x0c, 0x76, 0x84, + 0xd9, 0xb9, 0x37, 0xfa, 0xfc, 0x7c, 0xc2, 0x6d, 0x58, 0x3e, 0xb3, 0x04, + 0xbb, 0x8c, 0x8f, 0x48, 0xbc, 0x91, 0x27, 0xcc, 0xf9, 0xb7, 0x22, 0x19, + 0x83, 0x2e, 0x09, 0xb5, 0x72, 0xd9, 0x54, 0x1c, 0x4d, 0xa1, 0xea, 0x0b, + 0xf1, 0xc6, 0x08, 0x72, 0x46, 0x87, 0x7a, 0x6e, 0x80, 0x56, 0x0a, 0x8a, + 0xc0, 0xdd, 0x11, 0x6b, 0xd6, 0xdd, 0x47, 0xdf, 0x10, 0xd9, 0xd8, 0xea, + 0x7c, 0xb0, 0x8f, 0x03, 0x00, 0x2e, 0xc1, 0x8f, 0x44, 0xa8, 0xd3, 0x30, + 0x06, 0x89, 0xa2, 0xf9, 0x34, 0xad, 0xdc, 0x03, 0x85, 0xed, 0x51, 0xa7, + 0x82, 0x9c, 0xe7, 0x5d, 0x52, 0x93, 0x0c, 0x32, 0x9a, 0x5b, 0xe1, 0xaa, + 0xca, 0xb8, 0x02, 0x6d, 0x3a, 0xd4, 0xb1, 0x3a, 0xf0, 0x5f, 0xbe, 0xb5, + 0x0d, 0x10, 0x6b, 0x38, 0x32, 0xac, 0x76, 0x80, 0xbd, 0xca, 0x94, 0x71, + 0x7a, 0xf2, 0xc9, 0x35, 0x2a, 0xde, 0x9f, 0x42, 0x49, 0x18, 0x01, 0xab, + 0xbc, 0xef, 0x7c, 0x64, 0x3f, 0x58, 0x3d, 0x92, 0x59, 0xdb, 0x13, 0xdb, + 0x58, 0x6e, 0x0a, 0xe0, 0xb7, 0x91, 0x4a, 0x08, 0x20, 0xd6, 0x2e, 0x3c, + 0x45, 0xc9, 0x8b, 0x17, 0x79, 0xe7, 0xc7, 0x90, 0x99, 0x3a, 0x18, 0x25, +}; + +#else + +// k25519Precomp[i][j] = (j+1)*256^i*B +static const ge_precomp k25519Precomp[32][8] = { + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1288382639258501, 245678601348599, 269427782077623, + 1462984067271730, 137412439391563 +#else + 25967493, 19198397, 29566455, 3660896, 54414519, 4014786, + 27544626, 21800161, 61029707, 2047604 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 62697248952638, 204681361388450, 631292143396476, + 338455783676468, 1213667448819585 +#else + 54563134, 934261, 64385954, 3049989, 66381436, 9406985, + 12720692, 5043384, 19500929, 18085054 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 301289933810280, 1259582250014073, 1422107436869536, + 796239922652654, 1953934009299142 +#else + 58370664, 4489569, 9688441, 18769238, 10184608, 21191052, + 29287918, 11864899, 42594502, 29115885 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1380971894829527, 790832306631236, 2067202295274102, + 1995808275510000, 1566530869037010 +#else + 54292951, 20578084, 45527620, 11784319, 41753206, 30803714, + 55390960, 29739860, 66750418, 23343128 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 463307831301544, 432984605774163, 1610641361907204, + 750899048855000, 1894842303421586 +#else + 45405608, 6903824, 27185491, 6451973, 37531140, 24000426, + 51492312, 11189267, 40279186, 28235350 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 748439484463711, 1033211726465151, 1396005112841647, + 1611506220286469, 1972177495910992 +#else + 26966623, 11152617, 32442495, 15396054, 14353839, 20802097, + 63980037, 24013313, 51636816, 29387734 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1601611775252272, 1720807796594148, 1132070835939856, + 1260455018889551, 2147779492816911 +#else + 15636272, 23865875, 24204772, 25642034, 616976, 16869170, + 27787599, 18782243, 28944399, 32004408 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 316559037616741, 2177824224946892, 1459442586438991, + 1461528397712656, 751590696113597 +#else + 16568933, 4717097, 55552716, 32452109, 15682895, 21747389, + 16354576, 21778470, 7689661, 11199574 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1850748884277385, 1200145853858453, 1068094770532492, + 672251375690438, 1586055907191707 +#else + 30464137, 27578307, 55329429, 17883566, 23220364, 15915852, + 7512774, 10017326, 49359771, 23634074 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 934282339813791, 1846903124198670, 1172395437954843, + 1007037127761661, 1830588347719256 +#else + 50071967, 13921891, 10945806, 27521001, 27105051, 17470053, + 38182653, 15006022, 3284568, 27277892 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1694390458783935, 1735906047636159, 705069562067493, + 648033061693059, 696214010414170 +#else + 23599295, 25248385, 55915199, 25867015, 13236773, 10506355, + 7464579, 9656445, 13059162, 10374397 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1121406372216585, 192876649532226, 190294192191717, + 1994165897297032, 2245000007398739 +#else + 7798537, 16710257, 3033922, 2874086, 28997861, 2835604, + 32406664, 29715387, 66467155, 33453106 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 769950342298419, 132954430919746, 844085933195555, + 974092374476333, 726076285546016 +#else + 10861363, 11473154, 27284546, 1981175, 37044515, 12577860, + 32867885, 14515107, 51670560, 10819379 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 425251763115706, 608463272472562, 442562545713235, + 837766094556764, 374555092627893 +#else + 4708026, 6336745, 20377586, 9066809, 55836755, 6594695, + 41455196, 12483687, 54440373, 5581305 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1086255230780037, 274979815921559, 1960002765731872, + 929474102396301, 1190409889297339 +#else + 19563141, 16186464, 37722007, 4097518, 10237984, 29206317, + 28542349, 13850243, 43430843, 17738489 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1388594989461809, 316767091099457, 394298842192982, + 1230079486801005, 1440737038838979 +#else + 51736881, 20691677, 32573249, 4720197, 40672342, 5875510, + 47920237, 18329612, 57289923, 21468654 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 7380825640100, 146210432690483, 304903576448906, + 1198869323871120, 997689833219095 +#else + 58559652, 109982, 15149363, 2178705, 22900618, 4543417, 3044240, + 17864545, 1762327, 14866737 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1181317918772081, 114573476638901, 262805072233344, + 265712217171332, 294181933805782 +#else + 48909169, 17603008, 56635573, 1707277, 49922944, 3916100, + 38872452, 3959420, 27914454, 4383652 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 665000864555967, 2065379846933859, 370231110385876, + 350988370788628, 1233371373142985 +#else + 5153727, 9909285, 1723747, 30776558, 30523604, 5516873, + 19480852, 5230134, 43156425, 18378665 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2019367628972465, 676711900706637, 110710997811333, + 1108646842542025, 517791959672113 +#else + 36839857, 30090922, 7665485, 10083793, 28475525, 1649722, + 20654025, 16520125, 30598449, 7715701 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 965130719900578, 247011430587952, 526356006571389, + 91986625355052, 2157223321444601 +#else + 28881826, 14381568, 9657904, 3680757, 46927229, 7843315, + 35708204, 1370707, 29794553, 32145132 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2068619540119183, 1966274918058806, 957728544705549, + 729906502578991, 159834893065166 +#else + 14499471, 30824833, 33917750, 29299779, 28494861, 14271267, + 30290735, 10876454, 33954766, 2381725 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2073601412052185, 31021124762708, 264500969797082, + 248034690651703, 1030252227928288 +#else + 59913433, 30899068, 52378708, 462250, 39384538, 3941371, + 60872247, 3696004, 34808032, 15351954 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 551790716293402, 1989538725166328, 801169423371717, + 2052451893578887, 678432056995012 +#else + 27431194, 8222322, 16448760, 29646437, 48401861, 11938354, + 34147463, 30583916, 29551812, 10109425 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1368953770187805, 790347636712921, 437508475667162, + 2142576377050580, 1932081720066286 +#else + 53451805, 20399000, 35825113, 11777097, 21447386, 6519384, + 64730580, 31926875, 10092782, 28790261 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 953638594433374, 1092333936795051, 1419774766716690, + 805677984380077, 859228993502513 +#else + 27939166, 14210322, 4677035, 16277044, 44144402, 21156292, + 34600109, 12005537, 49298737, 12803509 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1200766035879111, 20142053207432, 1465634435977050, + 1645256912097844, 295121984874596 +#else + 17228999, 17892808, 65875336, 300139, 65883994, 21839654, + 30364212, 24516238, 18016356, 4397660 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1735718747031557, 1248237894295956, 1204753118328107, + 976066523550493, 65943769534592 +#else + 56150021, 25864224, 4776340, 18600194, 27850027, 17952220, + 40489757, 14544524, 49631360, 982638 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1060098822528990, 1586825862073490, 212301317240126, + 1975302711403555, 666724059764335 +#else + 29253598, 15796703, 64244882, 23645547, 10057022, 3163536, + 7332899, 29434304, 46061167, 9934962 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1091990273418756, 1572899409348578, 80968014455247, + 306009358661350, 1520450739132526 +#else + 5793284, 16271923, 42977250, 23438027, 29188559, 1206517, + 52360934, 4559894, 36984942, 22656481 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1480517209436112, 1511153322193952, 1244343858991172, + 304788150493241, 369136856496443 +#else + 39464912, 22061425, 16282656, 22517939, 28414020, 18542168, + 24191033, 4541697, 53770555, 5500567 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2151330273626164, 762045184746182, 1688074332551515, + 823046109005759, 907602769079491 +#else + 12650548, 32057319, 9052870, 11355358, 49428827, 25154267, + 49678271, 12264342, 10874051, 13524335 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2047386910586836, 168470092900250, 1552838872594810, + 340951180073789, 360819374702533 +#else + 25556948, 30508442, 714650, 2510400, 23394682, 23139102, + 33119037, 5080568, 44580805, 5376627 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1982622644432056, 2014393600336956, 128909208804214, + 1617792623929191, 105294281913815 +#else + 41020600, 29543379, 50095164, 30016803, 60382070, 1920896, + 44787559, 24106988, 4535767, 1569007 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 980234343912898, 1712256739246056, 588935272190264, + 204298813091998, 841798321043288 +#else + 64853442, 14606629, 45416424, 25514613, 28430648, 8775819, + 36614302, 3044289, 31848280, 12543772 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 197561292938973, 454817274782871, 1963754960082318, + 2113372252160468, 971377527342673 +#else + 45080285, 2943892, 35251351, 6777305, 13784462, 29262229, + 39731668, 31491700, 7718481, 14474653 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 164699448829328, 3127451757672, 1199504971548753, + 1766155447043652, 1899238924683527 +#else + 2385296, 2454213, 44477544, 46602, 62670929, 17874016, 656964, + 26317767, 24316167, 28300865 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 732262946680281, 1674412764227063, 2182456405662809, + 1350894754474250, 558458873295247 +#else + 13741529, 10911568, 33875447, 24950694, 46931033, 32521134, + 33040650, 20129900, 46379407, 8321685 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2103305098582922, 1960809151316468, 715134605001343, + 1454892949167181, 40827143824949 +#else + 21060490, 31341688, 15712756, 29218333, 1639039, 10656336, + 23845965, 21679594, 57124405, 608371 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1239289043050212, 1744654158124578, 758702410031698, + 1796762995074688, 1603056663766 +#else + 53436132, 18466845, 56219170, 25997372, 61071954, 11305546, + 1123968, 26773855, 27229398, 23887 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2232056027107988, 987343914584615, 2115594492994461, + 1819598072792159, 1119305654014850 +#else + 43864724, 33260226, 55364135, 14712570, 37643165, 31524814, + 12797023, 27114124, 65475458, 16678953 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 320153677847348, 939613871605645, 641883205761567, + 1930009789398224, 329165806634126 +#else + 37608244, 4770661, 51054477, 14001337, 7830047, 9564805, + 65600720, 28759386, 49939598, 4904952 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 980930490474130, 1242488692177893, 1251446316964684, + 1086618677993530, 1961430968465772 +#else + 24059538, 14617003, 19037157, 18514524, 19766092, 18648003, + 5169210, 16191880, 2128236, 29227599 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 276821765317453, 1536835591188030, 1305212741412361, + 61473904210175, 2051377036983058 +#else + 50127693, 4124965, 58568254, 22900634, 30336521, 19449185, + 37302527, 916032, 60226322, 30567899 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 833449923882501, 1750270368490475, 1123347002068295, + 185477424765687, 278090826653186 +#else + 44477957, 12419371, 59974635, 26081060, 50629959, 16739174, + 285431, 2763829, 15736322, 4143876 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 794524995833413, 1849907304548286, 53348672473145, + 1272368559505217, 1147304168324779 +#else + 2379333, 11839345, 62998462, 27565766, 11274297, 794957, 212801, + 18959769, 23527083, 17096164 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1504846112759364, 1203096289004681, 562139421471418, + 274333017451844, 1284344053775441 +#else + 33431108, 22423954, 49269897, 17927531, 8909498, 8376530, + 34483524, 4087880, 51919953, 19138217 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 483048732424432, 2116063063343382, 30120189902313, + 292451576741007, 1156379271702225 +#else + 1767664, 7197987, 53903638, 31531796, 54017513, 448825, 5799055, + 4357868, 62334673, 17231393 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 928372153029038, 2147692869914564, 1455665844462196, + 1986737809425946, 185207050258089 +#else + 6721966, 13833823, 43585476, 32003117, 26354292, 21691111, + 23365146, 29604700, 7390889, 2759800 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 137732961814206, 706670923917341, 1387038086865771, + 1965643813686352, 1384777115696347 +#else + 4409022, 2052381, 23373853, 10530217, 7676779, 20668478, + 21302352, 29290375, 1244379, 20634787 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 481144981981577, 2053319313589856, 2065402289827512, + 617954271490316, 1106602634668125 +#else + 62687625, 7169618, 4982368, 30596842, 30256824, 30776892, + 14086412, 9208236, 15886429, 16489664 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 696298019648792, 893299659040895, 1148636718636009, + 26734077349617, 2203955659340681 +#else + 1996056, 10375649, 14346367, 13311202, 60234729, 17116020, + 53415665, 398368, 36502409, 32841498 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 657390353372855, 998499966885562, 991893336905797, + 810470207106761, 343139804608786 +#else + 41801399, 9795879, 64331450, 14878808, 33577029, 14780362, + 13348553, 12076947, 36272402, 5113181 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 791736669492960, 934767652997115, 824656780392914, + 1759463253018643, 361530362383518 +#else + 49338080, 11797795, 31950843, 13929123, 41220562, 12288343, + 36767763, 26218045, 13847710, 5387222 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2022541353055597, 2094700262587466, 1551008075025686, + 242785517418164, 695985404963562 +#else + 48526701, 30138214, 17824842, 31213466, 22744342, 23111821, + 8763060, 3617786, 47508202, 10370990 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1287487199965223, 2215311941380308, 1552928390931986, + 1664859529680196, 1125004975265243 +#else + 20246567, 19185054, 22358228, 33010720, 18507282, 23140436, + 14554436, 24808340, 32232923, 16763880 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 677434665154918, 989582503122485, 1817429540898386, + 1052904935475344, 1143826298169798 +#else + 9648486, 10094563, 26416693, 14745928, 36734546, 27081810, + 11094160, 15689506, 3140038, 17044340 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 367266328308408, 318431188922404, 695629353755355, + 634085657580832, 24581612564426 +#else + 50948792, 5472694, 31895588, 4744994, 8823515, 10365685, + 39884064, 9448612, 38334410, 366294 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 773360688841258, 1815381330538070, 363773437667376, + 539629987070205, 783280434248437 +#else + 19153450, 11523972, 56012374, 27051289, 42461232, 5420646, + 28344573, 8041113, 719605, 11671788 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 180820816194166, 168937968377394, 748416242794470, + 1227281252254508, 1567587861004268 +#else + 8678006, 2694440, 60300850, 2517371, 4964326, 11152271, + 51675948, 18287915, 27000812, 23358879 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 478775558583645, 2062896624554807, 699391259285399, + 358099408427873, 1277310261461761 +#else + 51950941, 7134311, 8639287, 30739555, 59873175, 10421741, + 564065, 5336097, 6750977, 19033406 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1984740906540026, 1079164179400229, 1056021349262661, + 1659958556483663, 1088529069025527 +#else + 11836410, 29574944, 26297893, 16080799, 23455045, 15735944, + 1695823, 24735310, 8169719, 16220347 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 580736401511151, 1842931091388998, 1177201471228238, + 2075460256527244, 1301133425678027 +#else + 48993007, 8653646, 17578566, 27461813, 59083086, 17541668, + 55964556, 30926767, 61118155, 19388398 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1515728832059182, 1575261009617579, 1510246567196186, + 191078022609704, 116661716289141 +#else + 43800366, 22586119, 15213227, 23473218, 36255258, 22504427, + 27884328, 2847284, 2655861, 1738395 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1295295738269652, 1714742313707026, 545583042462581, + 2034411676262552, 1513248090013606 +#else + 39571412, 19301410, 41772562, 25551651, 57738101, 8129820, + 21651608, 30315096, 48021414, 22549153 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 230710545179830, 30821514358353, 760704303452229, + 390668103790604, 573437871383156 +#else + 1533110, 3437855, 23735889, 459276, 29970501, 11335377, + 26030092, 5821408, 10478196, 8544890 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1169380107545646, 263167233745614, 2022901299054448, + 819900753251120, 2023898464874585 +#else + 32173102, 17425121, 24896206, 3921497, 22579056, 30143578, + 19270448, 12217473, 17789017, 30158437 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2102254323485823, 1570832666216754, 34696906544624, + 1993213739807337, 70638552271463 +#else + 36555903, 31326030, 51530034, 23407230, 13243888, 517024, + 15479401, 29701199, 30460519, 1052596 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 894132856735058, 548675863558441, 845349339503395, + 1942269668326667, 1615682209874691 +#else + 55493970, 13323617, 32618793, 8175907, 51878691, 12596686, + 27491595, 28942073, 3179267, 24075541 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1287670217537834, 1222355136884920, 1846481788678694, + 1150426571265110, 1613523400722047 +#else + 31947050, 19187781, 62468280, 18214510, 51982886, 27514722, + 52352086, 17142691, 19072639, 24043372 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 793388516527298, 1315457083650035, 1972286999342417, + 1901825953052455, 338269477222410 +#else + 11685058, 11822410, 3158003, 19601838, 33402193, 29389366, + 5977895, 28339415, 473098, 5040608 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 550201530671806, 778605267108140, 2063911101902983, + 115500557286349, 2041641272971022 +#else + 46817982, 8198641, 39698732, 11602122, 1290375, 30754672, + 28326861, 1721092, 47550222, 30422825 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 717255318455100, 519313764361315, 2080406977303708, + 541981206705521, 774328150311600 +#else + 7881532, 10687937, 7578723, 7738378, 48157852, 31000479, + 21820785, 8076149, 39240368, 11538388 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 261715221532238, 1795354330069993, 1496878026850283, + 499739720521052, 389031152673770 +#else + 47173198, 3899860, 18283497, 26752864, 51380203, 22305220, + 8754524, 7446702, 61432810, 5797015 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1997217696294013, 1717306351628065, 1684313917746180, + 1644426076011410, 1857378133465451 +#else + 55813245, 29760862, 51326753, 25589858, 12708868, 25098233, + 2014098, 24503858, 64739691, 27677090 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1475434724792648, 76931896285979, 1116729029771667, + 2002544139318042, 725547833803938 +#else + 44636488, 21985690, 39426843, 1146374, 18956691, 16640559, + 1192730, 29840233, 15123618, 10811505 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2022306639183567, 726296063571875, 315345054448644, + 1058733329149221, 1448201136060677 +#else + 14352079, 30134717, 48166819, 10822654, 32750596, 4699007, + 67038501, 15776355, 38222085, 21579878 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1710065158525665, 1895094923036397, 123988286168546, + 1145519900776355, 1607510767693874 +#else + 38867681, 25481956, 62129901, 28239114, 29416930, 1847569, + 46454691, 17069576, 4714546, 23953777 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 561605375422540, 1071733543815037, 131496498800990, + 1946868434569999, 828138133964203 +#else + 15200332, 8368572, 19679101, 15970074, 35236190, 1959450, + 24611599, 29010600, 55362987, 12340219 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1548495173745801, 442310529226540, 998072547000384, + 553054358385281, 644824326376171 +#else + 12876937, 23074376, 33134380, 6590940, 60801088, 14872439, + 9613953, 8241152, 15370987, 9608631 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1445526537029440, 2225519789662536, 914628859347385, + 1064754194555068, 1660295614401091 +#else + 62965568, 21540023, 8446280, 33162829, 4407737, 13629032, + 59383996, 15866073, 38898243, 24740332 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1199690223111956, 24028135822341, 66638289244341, + 57626156285975, 565093967979607 +#else + 26660628, 17876777, 8393733, 358047, 59707573, 992987, 43204631, + 858696, 20571223, 8420556 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 876926774220824, 554618976488214, 1012056309841565, + 839961821554611, 1414499340307677 +#else + 14620696, 13067227, 51661590, 8264466, 14106269, 15080814, + 33531827, 12516406, 45534429, 21077682 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 703047626104145, 1266841406201770, 165556500219173, + 486991595001879, 1011325891650656 +#else + 236881, 10476226, 57258, 18877408, 6472997, 2466984, 17258519, + 7256740, 8791136, 15069930 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1622861044480487, 1156394801573634, 1869132565415504, + 327103985777730, 2095342781472284 +#else + 1276391, 24182514, 22949634, 17231625, 43615824, 27852245, + 14711874, 4874229, 36445724, 31223040 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 334886927423922, 489511099221528, 129160865966726, + 1720809113143481, 619700195649254 +#else + 5855666, 4990204, 53397016, 7294283, 59304582, 1924646, + 65685689, 25642053, 34039526, 9234252 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1646545795166119, 1758370782583567, 714746174550637, + 1472693650165135, 898994790308209 +#else + 20590503, 24535444, 31529743, 26201766, 64402029, 10650547, + 31559055, 21944845, 18979185, 13396066 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 333403773039279, 295772542452938, 1693106465353610, + 912330357530760, 471235657950362 +#else + 24474287, 4968103, 22267082, 4407354, 24063882, 25229252, + 48291976, 13594781, 33514650, 7021958 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1811196219982022, 1068969825533602, 289602974833439, + 1988956043611592, 863562343398367 +#else + 55541958, 26988926, 45743778, 15928891, 40950559, 4315420, + 41160136, 29637754, 45628383, 12868081 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 906282429780072, 2108672665779781, 432396390473936, + 150625823801893, 1708930497638539 +#else + 38473832, 13504660, 19988037, 31421671, 21078224, 6443208, + 45662757, 2244499, 54653067, 25465048 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 925664675702328, 21416848568684, 1831436641861340, + 601157008940113, 371818055044496 +#else + 36513336, 13793478, 61256044, 319135, 41385692, 27290532, + 33086545, 8957937, 51875216, 5540520 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1479786007267725, 1738881859066675, 68646196476567, + 2146507056100328, 1247662817535471 +#else + 55478669, 22050529, 58989363, 25911358, 2620055, 1022908, + 43398120, 31985447, 50980335, 18591624 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 52035296774456, 939969390708103, 312023458773250, + 59873523517659, 1231345905848899 +#else + 23152952, 775386, 27395463, 14006635, 57407746, 4649511, + 1689819, 892185, 55595587, 18348483 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 643355106415761, 290186807495774, 2013561737429023, + 319648069511546, 393736678496162 +#else + 9770129, 9586738, 26496094, 4324120, 1556511, 30004408, + 27453818, 4763127, 47929250, 5867133 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 129358342392716, 1932811617704777, 1176749390799681, + 398040349861790, 1170779668090425 +#else + 34343820, 1927589, 31726409, 28801137, 23962433, 17534932, + 27846558, 5931263, 37359161, 17445976 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2051980782668029, 121859921510665, 2048329875753063, + 1235229850149665, 519062146124755 +#else + 27461885, 30576896, 22380809, 1815854, 44075111, 30522493, + 7283489, 18406359, 47582163, 7734628 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1608170971973096, 415809060360428, 1350468408164766, + 2038620059057678, 1026904485989112 +#else + 59098600, 23963614, 55988460, 6196037, 29344158, 20123547, + 7585294, 30377806, 18549496, 15302069 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1837656083115103, 1510134048812070, 906263674192061, + 1821064197805734, 565375124676301 +#else + 34450527, 27383209, 59436070, 22502750, 6258877, 13504381, + 10458790, 27135971, 58236621, 8424745 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 578027192365650, 2034800251375322, 2128954087207123, + 478816193810521, 2196171989962750 +#else + 24687186, 8613276, 36441818, 30320886, 1863891, 31723888, + 19206233, 7134917, 55824382, 32725512 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1633188840273139, 852787172373708, 1548762607215796, + 1266275218902681, 1107218203325133 +#else + 11334899, 24336410, 8025292, 12707519, 17523892, 23078361, + 10243737, 18868971, 62042829, 16498836 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 462189358480054, 1784816734159228, 1611334301651368, + 1303938263943540, 707589560319424 +#else + 8911542, 6887158, 57524604, 26595841, 11145640, 24010752, + 17303924, 19430194, 6536640, 10543906 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1038829280972848, 38176604650029, 753193246598573, + 1136076426528122, 595709990562434 +#else + 38162480, 15479762, 49642029, 568875, 65611181, 11223453, + 64439674, 16928857, 39873154, 8876770 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1408451820859834, 2194984964010833, 2198361797561729, + 1061962440055713, 1645147963442934 +#else + 41365946, 20987567, 51458897, 32707824, 34082177, 32758143, + 33627041, 15824473, 66504438, 24514614 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 4701053362120, 1647641066302348, 1047553002242085, + 1923635013395977, 206970314902065 +#else + 10330056, 70051, 7957388, 24551765, 9764901, 15609756, 27698697, + 28664395, 1657393, 3084098 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1750479161778571, 1362553355169293, 1891721260220598, + 966109370862782, 1024913988299801 +#else + 10477963, 26084172, 12119565, 20303627, 29016246, 28188843, + 31280318, 14396151, 36875289, 15272408 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 212699049131723, 1117950018299775, 1873945661751056, + 1403802921984058, 130896082652698 +#else + 54820555, 3169462, 28813183, 16658753, 25116432, 27923966, + 41934906, 20918293, 42094106, 1950503 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 636808533673210, 1262201711667560, 390951380330599, + 1663420692697294, 561951321757406 +#else + 40928506, 9489186, 11053416, 18808271, 36055143, 5825629, + 58724558, 24786899, 15341278, 8373727 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 520731594438141, 1446301499955692, 273753264629267, + 1565101517999256, 1019411827004672 +#else + 28685821, 7759505, 52730348, 21551571, 35137043, 4079241, + 298136, 23321830, 64230656, 15190419 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 926527492029409, 1191853477411379, 734233225181171, + 184038887541270, 1790426146325343 +#else + 34175969, 13806335, 52771379, 17760000, 43104243, 10940927, + 8669718, 2742393, 41075551, 26679428 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1464651961852572, 1483737295721717, 1519450561335517, + 1161429831763785, 405914998179977 +#else + 65528476, 21825014, 41129205, 22109408, 49696989, 22641577, + 9291593, 17306653, 54954121, 6048604 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 996126634382301, 796204125879525, 127517800546509, + 344155944689303, 615279846169038 +#else + 36803549, 14843443, 1539301, 11864366, 20201677, 1900163, + 13934231, 5128323, 11213262, 9168384 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 738724080975276, 2188666632415296, 1961313708559162, + 1506545807547587, 1151301638969740 +#else + 40828332, 11007846, 19408960, 32613674, 48515898, 29225851, + 62020803, 22449281, 20470156, 17155731 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 622917337413835, 1218989177089035, 1284857712846592, + 970502061709359, 351025208117090 +#else + 43972811, 9282191, 14855179, 18164354, 59746048, 19145871, + 44324911, 14461607, 14042978, 5230683 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2067814584765580, 1677855129927492, 2086109782475197, + 235286517313238, 1416314046739645 +#else + 29969548, 30812838, 50396996, 25001989, 9175485, 31085458, + 21556950, 3506042, 61174973, 21104723 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 586844262630358, 307444381952195, 458399356043426, + 602068024507062, 1028548203415243 +#else + 63964118, 8744660, 19704003, 4581278, 46678178, 6830682, + 45824694, 8971512, 38569675, 15326562 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 678489922928203, 2016657584724032, 90977383049628, + 1026831907234582, 615271492942522 +#else + 47644235, 10110287, 49846336, 30050539, 43608476, 1355668, + 51585814, 15300987, 46594746, 9168259 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 301225714012278, 1094837270268560, 1202288391010439, + 644352775178361, 1647055902137983 +#else + 61755510, 4488612, 43305616, 16314346, 7780487, 17915493, + 38160505, 9601604, 33087103, 24543045 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1210746697896478, 1416608304244708, 686487477217856, + 1245131191434135, 1051238336855737 +#else + 47665694, 18041531, 46311396, 21109108, 37284416, 10229460, + 39664535, 18553900, 61111993, 15664671 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1135604073198207, 1683322080485474, 769147804376683, + 2086688130589414, 900445683120379 +#else + 23294591, 16921819, 44458082, 25083453, 27844203, 11461195, + 13099750, 31094076, 18151675, 13417686 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1971518477615628, 401909519527336, 448627091057375, + 1409486868273821, 1214789035034363 +#else + 42385932, 29377914, 35958184, 5988918, 40250079, 6685064, + 1661597, 21002991, 15271675, 18101767 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1364039144731711, 1897497433586190, 2203097701135459, + 145461396811251, 1349844460790699 +#else + 11433023, 20325767, 8239630, 28274915, 65123427, 32828713, + 48410099, 2167543, 60187563, 20114249 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1045230323257973, 818206601145807, 630513189076103, + 1672046528998132, 807204017562437 +#else + 35672693, 15575145, 30436815, 12192228, 44645511, 9395378, + 57191156, 24915434, 12215109, 12028277 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 439961968385997, 386362664488986, 1382706320807688, + 309894000125359, 2207801346498567 +#else + 14098381, 6555944, 23007258, 5757252, 51681032, 20603929, + 30123439, 4617780, 50208775, 32898803 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1229004686397588, 920643968530863, 123975893911178, + 681423993215777, 1400559197080973 +#else + 63082644, 18313596, 11893167, 13718664, 52299402, 1847384, + 51288865, 10154008, 23973261, 20869958 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2003766096898049, 170074059235165, 1141124258967971, + 1485419893480973, 1573762821028725 +#else + 40577025, 29858441, 65199965, 2534300, 35238307, 17004076, + 18341389, 22134481, 32013173, 23450893 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 729905708611432, 1270323270673202, 123353058984288, + 426460209632942, 2195574535456672 +#else + 41629544, 10876442, 55337778, 18929291, 54739296, 1838103, + 21911214, 6354752, 4425632, 32716610 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1271140255321235, 2044363183174497, 52125387634689, + 1445120246694705, 942541986339084 +#else + 56675475, 18941465, 22229857, 30463385, 53917697, 776728, + 49693489, 21533969, 4725004, 14044970 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1761608437466135, 583360847526804, 1586706389685493, + 2157056599579261, 1170692369685772 +#else + 19268631, 26250011, 1555348, 8692754, 45634805, 23643767, + 6347389, 32142648, 47586572, 17444675 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 871476219910823, 1878769545097794, 2241832391238412, + 548957640601001, 690047440233174 +#else + 42244775, 12986007, 56209986, 27995847, 55796492, 33405905, + 19541417, 8180106, 9282262, 10282508 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 297194732135507, 1366347803776820, 1301185512245601, + 561849853336294, 1533554921345731 +#else + 40903763, 4428546, 58447668, 20360168, 4098401, 19389175, + 15522534, 8372215, 5542595, 22851749 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 999628998628371, 1132836708493400, 2084741674517453, + 469343353015612, 678782988708035 +#else + 56546323, 14895632, 26814552, 16880582, 49628109, 31065071, + 64326972, 6993760, 49014979, 10114654 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2189427607417022, 699801937082607, 412764402319267, + 1478091893643349, 2244675696854460 +#else + 47001790, 32625013, 31422703, 10427861, 59998115, 6150668, + 38017109, 22025285, 25953724, 33448274 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1712292055966563, 204413590624874, 1405738637332841, + 408981300829763, 861082219276721 +#else + 62874467, 25515139, 57989738, 3045999, 2101609, 20947138, + 19390019, 6094296, 63793585, 12831124 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 508561155940631, 966928475686665, 2236717801150132, + 424543858577297, 2089272956986143 +#else + 51110167, 7578151, 5310217, 14408357, 33560244, 33329692, + 31575953, 6326196, 7381791, 31132593 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 221245220129925, 1156020201681217, 491145634799213, + 542422431960839, 828100817819207 +#else + 46206085, 3296810, 24736065, 17226043, 18374253, 7318640, + 6295303, 8082724, 51746375, 12339663 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 153756971240384, 1299874139923977, 393099165260502, + 1058234455773022, 996989038681183 +#else + 27724736, 2291157, 6088201, 19369634, 1792726, 5857634, + 13848414, 15768922, 25091167, 14856294 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 559086812798481, 573177704212711, 1629737083816402, + 1399819713462595, 1646954378266038 +#else + 48242193, 8331042, 24373479, 8541013, 66406866, 24284974, + 12927299, 20858939, 44926390, 24541532 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1887963056288059, 228507035730124, 1468368348640282, + 930557653420194, 613513962454686 +#else + 55685435, 28132841, 11632844, 3405020, 30536730, 21880393, + 39848098, 13866389, 30146206, 9142070 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1224529808187553, 1577022856702685, 2206946542980843, + 625883007765001, 279930793512158 +#else + 3924129, 18246916, 53291741, 23499471, 12291819, 32886066, + 39406089, 9326383, 58871006, 4171293 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1076287717051609, 1114455570543035, 187297059715481, + 250446884292121, 1885187512550540 +#else + 51186905, 16037936, 6713787, 16606682, 45496729, 2790943, + 26396185, 3731949, 345228, 28091483 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 902497362940219, 76749815795675, 1657927525633846, + 1420238379745202, 1340321636548352 +#else + 45781307, 13448258, 25284571, 1143661, 20614966, 24705045, + 2031538, 21163201, 50855680, 19972348 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1129576631190784, 1281994010027327, 996844254743018, + 257876363489249, 1150850742055018 +#else + 31016192, 16832003, 26371391, 19103199, 62081514, 14854136, + 17477601, 3842657, 28012650, 17149012 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 628740660038789, 1943038498527841, 467786347793886, + 1093341428303375, 235413859513003 +#else + 62033029, 9368965, 58546785, 28953529, 51858910, 6970559, + 57918991, 16292056, 58241707, 3507939 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 237425418909360, 469614029179605, 1512389769174935, + 1241726368345357, 441602891065214 +#else + 29439664, 3537914, 23333589, 6997794, 49553303, 22536363, + 51899661, 18503164, 57943934, 6580395 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1736417953058555, 726531315520508, 1833335034432527, + 1629442561574747, 624418919286085 +#else + 54923003, 25874643, 16438268, 10826160, 58412047, 27318820, + 17860443, 24280586, 65013061, 9304566 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1960754663920689, 497040957888962, 1909832851283095, + 1271432136996826, 2219780368020940 +#else + 20714545, 29217521, 29088194, 7406487, 11426967, 28458727, + 14792666, 18945815, 5289420, 33077305 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1537037379417136, 1358865369268262, 2130838645654099, + 828733687040705, 1999987652890901 +#else + 50443312, 22903641, 60948518, 20248671, 9192019, 31751970, + 17271489, 12349094, 26939669, 29802138 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 629042105241814, 1098854999137608, 887281544569320, + 1423102019874777, 7911258951561 +#else + 54218966, 9373457, 31595848, 16374215, 21471720, 13221525, + 39825369, 21205872, 63410057, 117886 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1811562332665373, 1501882019007673, 2213763501088999, + 359573079719636, 36370565049116 +#else + 22263325, 26994382, 3984569, 22379786, 51994855, 32987646, + 28311252, 5358056, 43789084, 541963 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 218907117361280, 1209298913016966, 1944312619096112, + 1130690631451061, 1342327389191701 +#else + 16259200, 3261970, 2309254, 18019958, 50223152, 28972515, + 24134069, 16848603, 53771797, 20002236 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1369976867854704, 1396479602419169, 1765656654398856, + 2203659200586299, 998327836117241 +#else + 9378160, 20414246, 44262881, 20809167, 28198280, 26310334, + 64709179, 32837080, 690425, 14876244 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2230701885562825, 1348173180338974, 2172856128624598, + 1426538746123771, 444193481326151 +#else + 24977353, 33240048, 58884894, 20089345, 28432342, 32378079, + 54040059, 21257083, 44727879, 6618998 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 784210426627951, 918204562375674, 1284546780452985, + 1324534636134684, 1872449409642708 +#else + 65570671, 11685645, 12944378, 13682314, 42719353, 19141238, + 8044828, 19737104, 32239828, 27901670 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 319638829540294, 596282656808406, 2037902696412608, + 1557219121643918, 341938082688094 +#else + 48505798, 4762989, 66182614, 8885303, 38696384, 30367116, + 9781646, 23204373, 32779358, 5095274 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1901860206695915, 2004489122065736, 1625847061568236, + 973529743399879, 2075287685312905 +#else + 34100715, 28339925, 34843976, 29869215, 9460460, 24227009, + 42507207, 14506723, 21639561, 30924196 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1371853944110545, 1042332820512553, 1949855697918254, + 1791195775521505, 37487364849293 +#else + 50707921, 20442216, 25239337, 15531969, 3987758, 29055114, + 65819361, 26690896, 17874573, 558605 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 687200189577855, 1082536651125675, 644224940871546, + 340923196057951, 343581346747396 +#else + 53508735, 10240080, 9171883, 16131053, 46239610, 9599699, + 33499487, 5080151, 2085892, 5119761 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2082717129583892, 27829425539422, 145655066671970, + 1690527209845512, 1865260509673478 +#else + 44903700, 31034903, 50727262, 414690, 42089314, 2170429, + 30634760, 25190818, 35108870, 27794547 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1059729620568824, 2163709103470266, 1440302280256872, + 1769143160546397, 869830310425069 +#else + 60263160, 15791201, 8550074, 32241778, 29928808, 21462176, + 27534429, 26362287, 44757485, 12961481 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1609516219779025, 777277757338817, 2101121130363987, + 550762194946473, 1905542338659364 +#else + 42616785, 23983660, 10368193, 11582341, 43711571, 31309144, + 16533929, 8206996, 36914212, 28394793 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2024821921041576, 426948675450149, 595133284085473, + 471860860885970, 600321679413000 +#else + 55987368, 30172197, 2307365, 6362031, 66973409, 8868176, + 50273234, 7031274, 7589640, 8945490 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 598474602406721, 1468128276358244, 1191923149557635, + 1501376424093216, 1281662691293476 +#else + 34956097, 8917966, 6661220, 21876816, 65916803, 17761038, + 7251488, 22372252, 24099108, 19098262 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1721138489890707, 1264336102277790, 433064545421287, + 1359988423149466, 1561871293409447 +#else + 5019539, 25646962, 4244126, 18840076, 40175591, 6453164, + 47990682, 20265406, 60876967, 23273695 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 719520245587143, 393380711632345, 132350400863381, + 1543271270810729, 1819543295798660 +#else + 10853575, 10721687, 26480089, 5861829, 44113045, 1972174, + 65242217, 22996533, 63745412, 27113307 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 396397949784152, 1811354474471839, 1362679985304303, + 2117033964846756, 498041172552279 +#else + 50106456, 5906789, 221599, 26991285, 7828207, 20305514, + 24362660, 31546264, 53242455, 7421391 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1812471844975748, 1856491995543149, 126579494584102, + 1036244859282620, 1975108050082550 +#else + 8139908, 27007935, 32257645, 27663886, 30375718, 1886181, + 45933756, 15441251, 28826358, 29431403 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 650623932407995, 1137551288410575, 2125223403615539, + 1725658013221271, 2134892965117796 +#else + 6267067, 9695052, 7709135, 16950835, 34239795, 31668296, + 14795159, 25714308, 13746020, 31812384 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 522584000310195, 1241762481390450, 1743702789495384, + 2227404127826575, 1686746002148897 +#else + 28584883, 7787108, 60375922, 18503702, 22846040, 25983196, + 63926927, 33190907, 4771361, 25134474 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 427904865186312, 1703211129693455, 1585368107547509, + 1436984488744336, 761188534613978 +#else + 24949256, 6376279, 39642383, 25379823, 48462709, 23623825, + 33543568, 21412737, 3569626, 11342593 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 318101947455002, 248138407995851, 1481904195303927, + 309278454311197, 1258516760217879 +#else + 26514970, 4740088, 27912651, 3697550, 19331575, 22082093, + 6809885, 4608608, 7325975, 18753361 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1275068538599310, 513726919533379, 349926553492294, + 688428871968420, 1702400196000666 +#else + 55490446, 19000001, 42787651, 7655127, 65739590, 5214311, + 39708324, 10258389, 49462170, 25367739 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1061864036265233, 961611260325381, 321859632700838, + 1045600629959517, 1985130202504038 +#else + 11431185, 15823007, 26570245, 14329124, 18029990, 4796082, + 35662685, 15580663, 9280358, 29580745 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1558816436882417, 1962896332636523, 1337709822062152, + 1501413830776938, 294436165831932 +#else + 66948081, 23228174, 44253547, 29249434, 46247496, 19933429, + 34297962, 22372809, 51563772, 4387440 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 818359826554971, 1862173000996177, 626821592884859, + 573655738872376, 1749691246745455 +#else + 46309467, 12194511, 3937617, 27748540, 39954043, 9340369, + 42594872, 8548136, 20617071, 26072431 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1988022651432119, 1082111498586040, 1834020786104821, + 1454826876423687, 692929915223122 +#else + 66170039, 29623845, 58394552, 16124717, 24603125, 27329039, + 53333511, 21678609, 24345682, 10325460 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2146513703733331, 584788900394667, 464965657279958, + 2183973639356127, 238371159456790 +#else + 47253587, 31985546, 44906155, 8714033, 14007766, 6928528, + 16318175, 32543743, 4766742, 3552007 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1129007025494441, 2197883144413266, 265142755578169, + 971864464758890, 1983715884903702 +#else + 45357481, 16823515, 1351762, 32751011, 63099193, 3950934, + 3217514, 14481909, 10988822, 29559670 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1291366624493075, 381456718189114, 1711482489312444, + 1815233647702022, 892279782992467 +#else + 15564307, 19242862, 3101242, 5684148, 30446780, 25503076, + 12677126, 27049089, 58813011, 13296004 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 444548969917454, 1452286453853356, 2113731441506810, + 645188273895859, 810317625309512 +#else + 57666574, 6624295, 36809900, 21640754, 62437882, 31497052, + 31521203, 9614054, 37108040, 12074673 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2242724082797924, 1373354730327868, 1006520110883049, + 2147330369940688, 1151816104883620 +#else + 4771172, 33419193, 14290748, 20464580, 27992297, 14998318, + 65694928, 31997715, 29832612, 17163397 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1745720200383796, 1911723143175317, 2056329390702074, + 355227174309849, 879232794371100 +#else + 7064884, 26013258, 47946901, 28486894, 48217594, 30641695, + 25825241, 5293297, 39986204, 13101589 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 163723479936298, 115424889803150, 1156016391581227, + 1894942220753364, 1970549419986329 +#else + 64810282, 2439669, 59642254, 1719964, 39841323, 17225986, + 32512468, 28236839, 36752793, 29363474 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 681981452362484, 267208874112496, 1374683991933094, + 638600984916117, 646178654558546 +#else + 37102324, 10162315, 33928688, 3981722, 50626726, 20484387, + 14413973, 9515896, 19568978, 9628812 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 13378654854251, 106237307029567, 1944412051589651, + 1841976767925457, 230702819835573 +#else + 33053803, 199357, 15894591, 1583059, 27380243, 28973997, + 49269969, 27447592, 60817077, 3437739 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 260683893467075, 854060306077237, 913639551980112, + 4704576840123, 280254810808712 +#else + 48129987, 3884492, 19469877, 12726490, 15913552, 13614290, + 44147131, 70103, 7463304, 4176122 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 715374893080287, 1173334812210491, 1806524662079626, + 1894596008000979, 398905715033393 +#else + 39984863, 10659916, 11482427, 17484051, 12771466, 26919315, + 34389459, 28231680, 24216881, 5944158 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 500026409727661, 1596431288195371, 1420380351989370, + 985211561521489, 392444930785633 +#else + 8894125, 7450974, 64444715, 23788679, 39028346, 21165316, + 19345745, 14680796, 11632993, 5847885 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2096421546958141, 1922523000950363, 789831022876840, + 427295144688779, 320923973161730 +#else + 26942781, 31239115, 9129563, 28647825, 26024104, 11769399, + 55590027, 6367193, 57381634, 4782139 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1927770723575450, 1485792977512719, 1850996108474547, + 551696031508956, 2126047405475647 +#else + 19916442, 28726022, 44198159, 22140040, 25606323, 27581991, + 33253852, 8220911, 6358847, 31680575 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2112099158080148, 742570803909715, 6484558077432, + 1951119898618916, 93090382703416 +#else + 801428, 31472730, 16569427, 11065167, 29875704, 96627, 7908388, + 29073952, 53570360, 1387154 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 383905201636970, 859946997631870, 855623867637644, + 1017125780577795, 794250831877809 +#else + 19646058, 5720633, 55692158, 12814208, 11607948, 12749789, + 14147075, 15156355, 45242033, 11835259 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 77571826285752, 999304298101753, 487841111777762, + 1038031143212339, 339066367948762 +#else + 19299512, 1155910, 28703737, 14890794, 2925026, 7269399, + 26121523, 15467869, 40548314, 5052482 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 674994775520533, 266035846330789, 826951213393478, + 1405007746162285, 1781791018620876 +#else + 64091413, 10058205, 1980837, 3964243, 22160966, 12322533, + 60677741, 20936246, 12228556, 26550755 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1001412661522686, 348196197067298, 1666614366723946, + 888424995032760, 580747687801357 +#else + 32944382, 14922211, 44263970, 5188527, 21913450, 24834489, + 4001464, 13238564, 60994061, 8653814 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1939560076207777, 1409892634407635, 552574736069277, + 383854338280405, 190706709864139 +#else + 22865569, 28901697, 27603667, 21009037, 14348957, 8234005, + 24808405, 5719875, 28483275, 2841751 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2177087163428741, 1439255351721944, 1208070840382793, + 2230616362004769, 1396886392021913 +#else + 50687877, 32441126, 66781144, 21446575, 21886281, 18001658, + 65220897, 33238773, 19932057, 20815229 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 676962063230039, 1880275537148808, 2046721011602706, + 888463247083003, 1318301552024067 +#else + 55452759, 10087520, 58243976, 28018288, 47830290, 30498519, + 3999227, 13239134, 62331395, 19644223 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1466980508178206, 617045217998949, 652303580573628, + 757303753529064, 207583137376902 +#else + 1382174, 21859713, 17266789, 9194690, 53784508, 9720080, + 20403944, 11284705, 53095046, 3093229 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1511056752906902, 105403126891277, 493434892772846, + 1091943425335976, 1802717338077427 +#else + 16650902, 22516500, 66044685, 1570628, 58779118, 7352752, + 66806440, 16271224, 43059443, 26862581 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1853982405405128, 1878664056251147, 1528011020803992, + 1019626468153565, 1128438412189035 +#else + 45197768, 27626490, 62497547, 27994275, 35364760, 22769138, + 24123613, 15193618, 45456747, 16815042 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1963939888391106, 293456433791664, 697897559513649, + 985882796904380, 796244541237972 +#else + 57172930, 29264984, 41829040, 4372841, 2087473, 10399484, + 31870908, 14690798, 17361620, 11864968 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 416770998629779, 389655552427054, 1314476859406756, + 1749382513022778, 1161905598739491 +#else + 55801235, 6210371, 13206574, 5806320, 38091172, 19587231, + 54777658, 26067830, 41530403, 17313742 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1428358296490651, 1027115282420478, 304840698058337, + 441410174026628, 1819358356278573 +#else + 14668443, 21284197, 26039038, 15305210, 25515617, 4542480, + 10453892, 6577524, 9145645, 27110552 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 204943430200135, 1554861433819175, 216426658514651, + 264149070665950, 2047097371738319 +#else + 5974855, 3053895, 57675815, 23169240, 35243739, 3225008, + 59136222, 3936127, 61456591, 30504127 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1934415182909034, 1393285083565062, 516409331772960, + 1157690734993892, 121039666594268 +#else + 30625386, 28825032, 41552902, 20761565, 46624288, 7695098, + 17097188, 17250936, 39109084, 1803631 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 662035583584445, 286736105093098, 1131773000510616, + 818494214211439, 472943792054479 +#else + 63555773, 9865098, 61880298, 4272700, 61435032, 16864731, + 14911343, 12196514, 45703375, 7047411 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 665784778135882, 1893179629898606, 808313193813106, + 276797254706413, 1563426179676396 +#else + 20093258, 9920966, 55970670, 28210574, 13161586, 12044805, + 34252013, 4124600, 34765036, 23296865 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 945205108984232, 526277562959295, 1324180513733566, + 1666970227868664, 153547609289173 +#else + 46320040, 14084653, 53577151, 7842146, 19119038, 19731827, + 4752376, 24839792, 45429205, 2288037 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2031433403516252, 203996615228162, 170487168837083, + 981513604791390, 843573964916831 +#else + 40289628, 30270716, 29965058, 3039786, 52635099, 2540456, + 29457502, 14625692, 42289247, 12570231 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1476570093962618, 838514669399805, 1857930577281364, + 2017007352225784, 317085545220047 +#else + 66045306, 22002608, 16920317, 12494842, 1278292, 27685323, + 45948920, 30055751, 55134159, 4724942 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1461557121912842, 1600674043318359, 2157134900399597, + 1670641601940616, 127765583803283 +#else + 17960970, 21778898, 62967895, 23851901, 58232301, 32143814, + 54201480, 24894499, 37532563, 1903855 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1293543509393474, 2143624609202546, 1058361566797508, + 214097127393994, 946888515472729 +#else + 23134274, 19275300, 56426866, 31942495, 20684484, 15770816, + 54119114, 3190295, 26955097, 14109738 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 357067959932916, 1290876214345711, 521245575443703, + 1494975468601005, 800942377643885 +#else + 15308788, 5320727, 36995055, 19235554, 22902007, 7767164, + 29425325, 22276870, 31960941, 11934971 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 566116659100033, 820247422481740, 994464017954148, + 327157611686365, 92591318111744 +#else + 39713153, 8435795, 4109644, 12222639, 42480996, 14818668, + 20638173, 4875028, 10491392, 1379718 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 617256647603209, 1652107761099439, 1857213046645471, + 1085597175214970, 817432759830522 +#else + 53949449, 9197840, 3875503, 24618324, 65725151, 27674630, + 33518458, 16176658, 21432314, 12180697 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 771808161440705, 1323510426395069, 680497615846440, + 851580615547985, 1320806384849017 +#else + 55321537, 11500837, 13787581, 19721842, 44678184, 10140204, + 1465425, 12689540, 56807545, 19681548 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1219260086131915, 647169006596815, 79601124759706, + 2161724213426748, 404861897060198 +#else + 5414091, 18168391, 46101199, 9643569, 12834970, 1186149, + 64485948, 32212200, 26128230, 6032912 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1327968293887866, 1335500852943256, 1401587164534264, + 558137311952440, 1551360549268902 +#else + 40771450, 19788269, 32496024, 19900513, 17847800, 20885276, + 3604024, 8316894, 41233830, 23117073 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 417621685193956, 1429953819744454, 396157358457099, + 1940470778873255, 214000046234152 +#else + 3296484, 6223048, 24680646, 21307972, 44056843, 5903204, + 58246567, 28915267, 12376616, 3188849 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1268047918491973, 2172375426948536, 1533916099229249, + 1761293575457130, 1590622667026765 +#else + 29190469, 18895386, 27549112, 32370916, 3520065, 22857131, + 32049514, 26245319, 50999629, 23702124 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1627072914981959, 2211603081280073, 1912369601616504, + 1191770436221309, 2187309757525860 +#else + 52364359, 24245275, 735817, 32955454, 46701176, 28496527, + 25246077, 17758763, 18640740, 32593455 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1149147819689533, 378692712667677, 828475842424202, + 2218619146419342, 70688125792186 +#else + 60180029, 17123636, 10361373, 5642961, 4910474, 12345252, + 35470478, 33060001, 10530746, 1053335 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1299739417079761, 1438616663452759, 1536729078504412, + 2053896748919838, 1008421032591246 +#else + 37842897, 19367626, 53570647, 21437058, 47651804, 22899047, + 35646494, 30605446, 24018830, 15026644 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2040723824657366, 399555637875075, 632543375452995, + 872649937008051, 1235394727030233 +#else + 44516310, 30409154, 64819587, 5953842, 53668675, 9425630, + 25310643, 13003497, 64794073, 18408815 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2211311599327900, 2139787259888175, 938706616835350, + 12609661139114, 2081897930719789 +#else + 39688860, 32951110, 59064879, 31885314, 41016598, 13987818, + 39811242, 187898, 43942445, 31022696 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1324994503390450, 336982330582631, 1183998925654177, + 1091654665913274, 48727673971319 +#else + 45364466, 19743956, 1844839, 5021428, 56674465, 17642958, + 9716666, 16266922, 62038647, 726098 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1845522914617879, 1222198248335542, 150841072760134, + 1927029069940982, 1189913404498011 +#else + 29370903, 27500434, 7334070, 18212173, 9385286, 2247707, + 53446902, 28714970, 30007387, 17731091 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1079559557592645, 2215338383666441, 1903569501302605, + 49033973033940, 305703433934152 +#else + 66172485, 16086690, 23751945, 33011114, 65941325, 28365395, + 9137108, 730663, 9835848, 4555336 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 94653405416909, 1386121349852999, 1062130477891762, + 36553947479274, 833669648948846 +#else + 43732429, 1410445, 44855111, 20654817, 30867634, 15826977, + 17693930, 544696, 55123566, 12422645 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1432015813136298, 440364795295369, 1395647062821501, + 1976874522764578, 934452372723352 +#else + 31117226, 21338698, 53606025, 6561946, 57231997, 20796761, + 61990178, 29457725, 29120152, 13924425 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1296625309219774, 2068273464883862, 1858621048097805, + 1492281814208508, 2235868981918946 +#else + 49707966, 19321222, 19675798, 30819676, 56101901, 27695611, + 57724924, 22236731, 7240930, 33317044 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1490330266465570, 1858795661361448, 1436241134969763, + 294573218899647, 1208140011028933 +#else + 35747106, 22207651, 52101416, 27698213, 44655523, 21401660, + 1222335, 4389483, 3293637, 18002689 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1282462923712748, 741885683986255, 2027754642827561, + 518989529541027, 1826610009555945 +#else + 50424044, 19110186, 11038543, 11054958, 53307689, 30215898, + 42789283, 7733546, 12796905, 27218610 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1525827120027511, 723686461809551, 1597702369236987, + 244802101764964, 1502833890372311 +#else + 58349431, 22736595, 41689999, 10783768, 36493307, 23807620, + 38855524, 3647835, 3222231, 22393970 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 113622036244513, 1233740067745854, 674109952278496, + 2114345180342965, 166764512856263 +#else + 18606113, 1693100, 41660478, 18384159, 4112352, 10045021, + 23603893, 31506198, 59558087, 2484984 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2041668749310338, 2184405322203901, 1633400637611036, + 2110682505536899, 2048144390084644 +#else + 9255298, 30423235, 54952701, 32550175, 13098012, 24339566, + 16377219, 31451620, 47306788, 30519729 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 503058759232932, 760293024620937, 2027152777219493, + 666858468148475, 1539184379870952 +#else + 44379556, 7496159, 61366665, 11329248, 19991973, 30206930, + 35390715, 9936965, 37011176, 22935634 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1916168475367211, 915626432541343, 883217071712575, + 363427871374304, 1976029821251593 +#else + 21878571, 28553135, 4338335, 13643897, 64071999, 13160959, + 19708896, 5415497, 59748361, 29445138 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 678039535434506, 570587290189340, 1605302676614120, + 2147762562875701, 1706063797091704 +#else + 27736842, 10103576, 12500508, 8502413, 63695848, 23920873, + 10436917, 32004156, 43449720, 25422331 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1439489648586438, 2194580753290951, 832380563557396, + 561521973970522, 584497280718389 +#else + 19492550, 21450067, 37426887, 32701801, 63900692, 12403436, + 30066266, 8367329, 13243957, 8709688 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 187989455492609, 681223515948275, 1933493571072456, + 1872921007304880, 488162364135671 +#else + 12015105, 2801261, 28198131, 10151021, 24818120, 28811299, + 55914672, 27908697, 5150967, 7274186 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1413466089534451, 410844090765630, 1397263346404072, + 408227143123410, 1594561803147811 +#else + 2831347, 21062286, 1478974, 6122054, 23825128, 20820846, + 31097298, 6083058, 31021603, 23760822 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2102170800973153, 719462588665004, 1479649438510153, + 1097529543970028, 1302363283777685 +#else + 64578913, 31324785, 445612, 10720828, 53259337, 22048494, + 43601132, 16354464, 15067285, 19406725 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 942065717847195, 1069313679352961, 2007341951411051, + 70973416446291, 1419433790163706 +#else + 7840923, 14037873, 33744001, 15934015, 66380651, 29911725, + 21403987, 1057586, 47729402, 21151211 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1146565545556377, 1661971299445212, 406681704748893, + 564452436406089, 1109109865829139 +#else + 915865, 17085158, 15608284, 24765302, 42751837, 6060029, + 49737545, 8410996, 59888403, 16527024 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2214421081775077, 1165671861210569, 1890453018796184, + 3556249878661, 442116172656317 +#else + 32922597, 32997445, 20336073, 17369864, 10903704, 28169945, + 16957573, 52992, 23834301, 6588044 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 753830546620811, 1666955059895019, 1530775289309243, + 1119987029104146, 2164156153857580 +#else + 32752011, 11232950, 3381995, 24839566, 22652987, 22810329, + 17159698, 16689107, 46794284, 32248439 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 615171919212796, 1523849404854568, 854560460547503, + 2067097370290715, 1765325848586042 +#else + 62419196, 9166775, 41398568, 22707125, 11576751, 12733943, + 7924251, 30802151, 1976122, 26305405 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1094538949313667, 1796592198908825, 870221004284388, + 2025558921863561, 1699010892802384 +#else + 21251203, 16309901, 64125849, 26771309, 30810596, 12967303, + 156041, 30183180, 12331344, 25317235 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1951351290725195, 1916457206844795, 198025184438026, + 1909076887557595, 1938542290318919 +#else + 8651595, 29077400, 51023227, 28557437, 13002506, 2950805, + 29054427, 28447462, 10008135, 28886531 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1014323197538413, 869150639940606, 1756009942696599, + 1334952557375672, 1544945379082874 +#else + 31486061, 15114593, 52847614, 12951353, 14369431, 26166587, + 16347320, 19892343, 8684154, 23021480 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 764055910920305, 1603590757375439, 146805246592357, + 1843313433854297, 954279890114939 +#else + 19443825, 11385320, 24468943, 23895364, 43189605, 2187568, + 40845657, 27467510, 31316347, 14219878 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 80113526615750, 764536758732259, 1055139345100233, + 469252651759390, 617897512431515 +#else + 38514374, 1193784, 32245219, 11392485, 31092169, 15722801, + 27146014, 6992409, 29126555, 9207390 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 74497112547268, 740094153192149, 1745254631717581, + 727713886503130, 1283034364416928 +#else + 32382916, 1110093, 18477781, 11028262, 39697101, 26006320, + 62128346, 10843781, 59151264, 19118701 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 525892105991110, 1723776830270342, 1476444848991936, + 573789489857760, 133864092632978 +#else + 2814918, 7836403, 27519878, 25686276, 46214848, 22000742, + 45614304, 8550129, 28346258, 1994730 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 542611720192581, 1986812262899321, 1162535242465837, + 481498966143464, 544600533583622 +#else + 47530565, 8085544, 53108345, 29605809, 2785837, 17323125, + 47591912, 7174893, 22628102, 8115180 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 64123227344372, 1239927720647794, 1360722983445904, + 222610813654661, 62429487187991 +#else + 36703732, 955510, 55975026, 18476362, 34661776, 20276352, + 41457285, 3317159, 57165847, 930271 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1793193323953132, 91096687857833, 70945970938921, + 2158587638946380, 1537042406482111 +#else + 51805164, 26720662, 28856489, 1357446, 23421993, 1057177, + 24091212, 32165462, 44343487, 22903716 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1895854577604609, 1394895708949416, 1728548428495944, + 1140864900240149, 563645333603061 +#else + 44357633, 28250434, 54201256, 20785565, 51297352, 25757378, + 52269845, 17000211, 65241845, 8398969 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 141358280486863, 91435889572504, 1087208572552643, + 1829599652522921, 1193307020643647 +#else + 35139535, 2106402, 62372504, 1362500, 12813763, 16200670, + 22981545, 27263159, 18009407, 17781660 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1611230858525381, 950720175540785, 499589887488610, + 2001656988495019, 88977313255908 +#else + 49887941, 24009210, 39324209, 14166834, 29815394, 7444469, + 29551787, 29827013, 19288548, 1325865 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1189080501479658, 2184348804772597, 1040818725742319, + 2018318290311834, 1712060030915354 +#else + 15100138, 17718680, 43184885, 32549333, 40658671, 15509407, + 12376730, 30075286, 33166106, 25511682 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 873966876953756, 1090638350350440, 1708559325189137, + 672344594801910, 1320437969700239 +#else + 20909212, 13023121, 57899112, 16251777, 61330449, 25459517, + 12412150, 10018715, 2213263, 19676059 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1508590048271766, 1131769479776094, 101550868699323, + 428297785557897, 561791648661744 +#else + 32529814, 22479743, 30361438, 16864679, 57972923, 1513225, + 22922121, 6382134, 61341936, 8371347 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 756417570499462, 237882279232602, 2136263418594016, + 1701968045454886, 703713185137472 +#else + 9923462, 11271500, 12616794, 3544722, 37110496, 31832805, + 12891686, 25361300, 40665920, 10486143 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1781187809325462, 1697624151492346, 1381393690939988, + 175194132284669, 1483054666415238 +#else + 44511638, 26541766, 8587002, 25296571, 4084308, 20584370, + 361725, 2610596, 43187334, 22099236 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2175517777364616, 708781536456029, 955668231122942, + 1967557500069555, 2021208005604118 +#else + 5408392, 32417741, 62139741, 10561667, 24145918, 14240566, + 31319731, 29318891, 19985174, 30118346 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1115135966606887, 224217372950782, 915967306279222, + 593866251291540, 561747094208006 +#else + 53114407, 16616820, 14549246, 3341099, 32155958, 13648976, + 49531796, 8849296, 65030, 8370684 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1443163092879439, 391875531646162, 2180847134654632, + 464538543018753, 1594098196837178 +#else + 58787919, 21504805, 31204562, 5839400, 46481576, 32497154, + 47665921, 6922163, 12743482, 23753914 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 850858855888869, 319436476624586, 327807784938441, + 740785849558761, 17128415486016 +#else + 64747493, 12678784, 28815050, 4759974, 43215817, 4884716, + 23783145, 11038569, 18800704, 255233 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2132756334090067, 536247820155645, 48907151276867, + 608473197600695, 1261689545022784 +#else + 61839187, 31780545, 13957885, 7990715, 23132995, 728773, + 13393847, 9066957, 19258688, 18800639 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1525176236978354, 974205476721062, 293436255662638, + 148269621098039, 137961998433963 +#else + 64172210, 22726896, 56676774, 14516792, 63468078, 4372540, + 35173943, 2209389, 65584811, 2055793 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1121075518299410, 2071745529082111, 1265567917414828, + 1648196578317805, 496232102750820 +#else + 580882, 16705327, 5468415, 30871414, 36182444, 18858431, + 59905517, 24560042, 37087844, 7394434 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 122321229299801, 1022922077493685, 2001275453369484, + 2017441881607947, 993205880778002 +#else + 23838809, 1822728, 51370421, 15242726, 8318092, 29821328, + 45436683, 30062226, 62287122, 14799920 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 654925550560074, 1168810995576858, 575655959430926, + 905758704861388, 496774564663534 +#else + 13345610, 9759151, 3371034, 17416641, 16353038, 8577942, + 31129804, 13496856, 58052846, 7402517 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1954109525779738, 2117022646152485, 338102630417180, + 1194140505732026, 107881734943492 +#else + 2286874, 29118501, 47066405, 31546095, 53412636, 5038121, + 11006906, 17794080, 8205060, 1607563 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1714785840001267, 2036500018681589, 1876380234251966, + 2056717182974196, 1645855254384642 +#else + 14414067, 25552300, 3331829, 30346215, 22249150, 27960244, + 18364660, 30647474, 30019586, 24525154 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 106431476499341, 62482972120563, 1513446655109411, + 807258751769522, 538491469114 +#else + 39420813, 1585952, 56333811, 931068, 37988643, 22552112, + 52698034, 12029092, 9944378, 8024 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2002850762893643, 1243624520538135, 1486040410574605, + 2184752338181213, 378495998083531 +#else + 4368715, 29844802, 29874199, 18531449, 46878477, 22143727, + 50994269, 32555346, 58966475, 5640029 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 922510868424903, 1089502620807680, 402544072617374, + 1131446598479839, 1290278588136533 +#else + 10299591, 13746483, 11661824, 16234854, 7630238, 5998374, + 9809887, 16859868, 15219797, 19226649 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1867998812076769, 715425053580701, 39968586461416, + 2173068014586163, 653822651801304 +#else + 27425505, 27835351, 3055005, 10660664, 23458024, 595578, + 51710259, 32381236, 48766680, 9742716 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 162892278589453, 182585796682149, 75093073137630, + 497037941226502, 133871727117371 +#else + 6744077, 2427284, 26042789, 2720740, 66260958, 1118973, + 32324614, 7406442, 12420155, 1994844 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1914596576579670, 1608999621851578, 1987629837704609, + 1519655314857977, 1819193753409464 +#else + 14012502, 28529712, 48724410, 23975962, 40623521, 29617992, + 54075385, 22644628, 24319928, 27108099 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1949315551096831, 1069003344994464, 1939165033499916, + 1548227205730856, 1933767655861407 +#else + 16412671, 29047065, 10772640, 15929391, 50040076, 28895810, + 10555944, 23070383, 37006495, 28815383 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1730519386931635, 1393284965610134, 1597143735726030, + 416032382447158, 1429665248828629 +#else + 22397363, 25786748, 57815702, 20761563, 17166286, 23799296, + 39775798, 6199365, 21880021, 21303672 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 360275475604565, 547835731063078, 215360904187529, + 596646739879007, 332709650425085 +#else + 62825557, 5368522, 35991846, 8163388, 36785801, 3209127, + 16557151, 8890729, 8840445, 4957760 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 47602113726801, 1522314509708010, 437706261372925, + 814035330438027, 335930650933545 +#else + 51661137, 709326, 60189418, 22684253, 37330941, 6522331, + 45388683, 12130071, 52312361, 5005756 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1291597595523886, 1058020588994081, 402837842324045, + 1363323695882781, 2105763393033193 +#else + 64994094, 19246303, 23019041, 15765735, 41839181, 6002751, + 10183197, 20315106, 50713577, 31378319 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 109521982566564, 1715257748585139, 1112231216891516, + 2046641005101484, 134249157157013 +#else + 48083108, 1632004, 13466291, 25559332, 43468412, 16573536, + 35094956, 30497327, 22208661, 2000468 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2156991030936798, 2227544497153325, 1869050094431622, + 754875860479115, 1754242344267058 +#else + 3065054, 32141671, 41510189, 33192999, 49425798, 27851016, + 58944651, 11248526, 63417650, 26140247 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1846089562873800, 98894784984326, 1412430299204844, + 171351226625762, 1100604760929008 +#else + 10379208, 27508878, 8877318, 1473647, 37817580, 21046851, + 16690914, 2553332, 63976176, 16400288 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 84172382130492, 499710970700046, 425749630620778, + 1762872794206857, 612842602127960 +#else + 15716668, 1254266, 48636174, 7446273, 58659946, 6344163, + 45011593, 26268851, 26894936, 9132066 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 868309334532756, 1703010512741873, 1952690008738057, + 4325269926064, 2071083554962116 +#else + 24158868, 12938817, 11085297, 25376834, 39045385, 29097348, + 36532400, 64451, 60291780, 30861549 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 523094549451158, 401938899487815, 1407690589076010, + 2022387426254453, 158660516411257 +#else + 13488534, 7794716, 22236231, 5989356, 25426474, 20976224, + 2350709, 30135921, 62420857, 2364225 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 612867287630009, 448212612103814, 571629077419196, + 1466796750919376, 1728478129663858 +#else + 16335033, 9132434, 25640582, 6678888, 1725628, 8517937, + 55301840, 21856974, 15445874, 25756331 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1723848973783452, 2208822520534681, 1718748322776940, + 1974268454121942, 1194212502258141 +#else + 29004188, 25687351, 28661401, 32914020, 54314860, 25611345, + 31863254, 29418892, 66830813, 17795152 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1254114807944608, 977770684047110, 2010756238954993, + 1783628927194099, 1525962994408256 +#else + 60986784, 18687766, 38493958, 14569918, 56250865, 29962602, + 10343411, 26578142, 37280576, 22738620 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 232464058235826, 1948628555342434, 1835348780427694, + 1031609499437291, 64472106918373 +#else + 27081650, 3463984, 14099042, 29036828, 1616302, 27348828, + 29542635, 15372179, 17293797, 960709 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 767338676040683, 754089548318405, 1523192045639075, + 435746025122062, 512692508440385 +#else + 20263915, 11434237, 61343429, 11236809, 13505955, 22697330, + 50997518, 6493121, 47724353, 7639713 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1255955808701983, 1700487367990941, 1166401238800299, + 1175121994891534, 1190934801395380 +#else + 64278047, 18715199, 25403037, 25339236, 58791851, 17380732, + 18006286, 17510682, 29994676, 17746311 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 349144008168292, 1337012557669162, 1475912332999108, + 1321618454900458, 47611291904320 +#else + 9769828, 5202651, 42951466, 19923039, 39057860, 21992807, + 42495722, 19693649, 35924288, 709463 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 877519947135419, 2172838026132651, 272304391224129, + 1655143327559984, 886229406429814 +#else + 12286395, 13076066, 45333675, 32377809, 42105665, 4057651, + 35090736, 24663557, 16102006, 13205847 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 375806028254706, 214463229793940, 572906353144089, + 572168269875638, 697556386112979 +#else + 13733362, 5599946, 10557076, 3195751, 61550873, 8536969, + 41568694, 8525971, 10151379, 10394400 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1168827102357844, 823864273033637, 2071538752104697, + 788062026895924, 599578340743362 +#else + 4024660, 17416881, 22436261, 12276534, 58009849, 30868332, + 19698228, 11743039, 33806530, 8934413 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1948116082078088, 2054898304487796, 2204939184983900, + 210526805152138, 786593586607626 +#else + 51229064, 29029191, 58528116, 30620370, 14634844, 32856154, + 57659786, 3137093, 55571978, 11721157 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1915320147894736, 156481169009469, 655050471180417, + 592917090415421, 2165897438660879 +#else + 17555920, 28540494, 8268605, 2331751, 44370049, 9761012, + 9319229, 8835153, 57903375, 32274386 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1726336468579724, 1119932070398949, 1929199510967666, + 33918788322959, 1836837863503150 +#else + 66647436, 25724417, 20614117, 16688288, 59594098, 28747312, + 22300303, 505429, 6108462, 27371017 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 829996854845988, 217061778005138, 1686565909803640, + 1346948817219846, 1723823550730181 +#else + 62038564, 12367916, 36445330, 3234472, 32617080, 25131790, + 29880582, 20071101, 40210373, 25686972 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 384301494966394, 687038900403062, 2211195391021739, + 254684538421383, 1245698430589680 +#else + 35133562, 5726538, 26934134, 10237677, 63935147, 32949378, + 24199303, 3795095, 7592688, 18562353 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1247567493562688, 1978182094455847, 183871474792955, + 806570235643435, 288461518067916 +#else + 21594432, 18590204, 17466407, 29477210, 32537083, 2739898, + 6407723, 12018833, 38852812, 4298411 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1449077384734201, 38285445457996, 2136537659177832, + 2146493000841573, 725161151123125 +#else + 46458361, 21592935, 39872588, 570497, 3767144, 31836892, + 13891941, 31985238, 13717173, 10805743 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1201928866368855, 800415690605445, 1703146756828343, + 997278587541744, 1858284414104014 +#else + 52432215, 17910135, 15287173, 11927123, 24177847, 25378864, + 66312432, 14860608, 40169934, 27690595 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 356468809648877, 782373916933152, 1718002439402870, + 1392222252219254, 663171266061951 +#else + 12962541, 5311799, 57048096, 11658279, 18855286, 25600231, + 13286262, 20745728, 62727807, 9882021 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 759628738230460, 1012693474275852, 353780233086498, + 246080061387552, 2030378857679162 +#else + 18512060, 11319350, 46985740, 15090308, 18818594, 5271736, + 44380960, 3666878, 43141434, 30255002 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2040672435071076, 888593182036908, 1298443657189359, + 1804780278521327, 354070726137060 +#else + 60319844, 30408388, 16192428, 13241070, 15898607, 19348318, + 57023983, 26893321, 64705764, 5276064 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1894938527423184, 1463213041477277, 474410505497651, + 247294963033299, 877975941029128 +#else + 30169808, 28236784, 26306205, 21803573, 27814963, 7069267, + 7152851, 3684982, 1449224, 13082861 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 207937160991127, 12966911039119, 820997788283092, + 1010440472205286, 1701372890140810 +#else + 10342807, 3098505, 2119311, 193222, 25702612, 12233820, + 23697382, 15056736, 46092426, 25352431 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 218882774543183, 533427444716285, 1233243976733245, + 435054256891319, 1509568989549904 +#else + 33958735, 3261607, 22745853, 7948688, 19370557, 18376767, + 40936887, 6482813, 56808784, 22494330 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1888838535711826, 1052177758340622, 1213553803324135, + 169182009127332, 463374268115872 +#else + 32869458, 28145887, 25609742, 15678670, 56421095, 18083360, + 26112420, 2521008, 44444576, 6904814 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 299137589460312, 1594371588983567, 868058494039073, + 257771590636681, 1805012993142921 +#else + 29506904, 4457497, 3377935, 23757988, 36598817, 12935079, + 1561737, 3841096, 38105225, 26896789 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1806842755664364, 2098896946025095, 1356630998422878, + 1458279806348064, 347755825962072 +#else + 10340844, 26924055, 48452231, 31276001, 12621150, 20215377, + 30878496, 21730062, 41524312, 5181965 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1402334161391744, 1560083671046299, 1008585416617747, + 1147797150908892, 1420416683642459 +#else + 25940096, 20896407, 17324187, 23247058, 58437395, 15029093, + 24396252, 17103510, 64786011, 21165857 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 665506704253369, 273770475169863, 799236974202630, + 848328990077558, 1811448782807931 +#else + 45343161, 9916822, 65808455, 4079497, 66080518, 11909558, + 1782390, 12641087, 20603771, 26992690 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1468412523962641, 771866649897997, 1931766110147832, + 799561180078482, 524837559150077 +#else + 48226577, 21881051, 24849421, 11501709, 13161720, 28785558, + 1925522, 11914390, 4662781, 7820689 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2223212657821850, 630416247363666, 2144451165500328, + 816911130947791, 1024351058410032 +#else + 12241050, 33128450, 8132690, 9393934, 32846760, 31954812, + 29749455, 12172924, 16136752, 15264020 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1266603897524861, 156378408858100, 1275649024228779, + 447738405888420, 253186462063095 +#else + 56758909, 18873868, 58896884, 2330219, 49446315, 19008651, + 10658212, 6671822, 19012087, 3772772 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2022215964509735, 136144366993649, 1800716593296582, + 1193970603800203, 871675847064218 +#else + 3753511, 30133366, 10617073, 2028709, 14841030, 26832768, + 28718731, 17791548, 20527770, 12988982 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1862751661970328, 851596246739884, 1519315554814041, + 1542798466547449, 1417975335901520 +#else + 52286360, 27757162, 63400876, 12689772, 66209881, 22639565, + 42925817, 22989488, 3299664, 21129479 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1228168094547481, 334133883362894, 587567568420081, + 433612590281181, 603390400373205 +#else + 50331161, 18301130, 57466446, 4978982, 3308785, 8755439, + 6943197, 6461331, 41525717, 8991217 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 121893973206505, 1843345804916664, 1703118377384911, + 497810164760654, 101150811654673 +#else + 49882601, 1816361, 65435576, 27467992, 31783887, 25378441, + 34160718, 7417949, 36866577, 1507264 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 458346255946468, 290909935619344, 1452768413850679, + 550922875254215, 1537286854336538 +#else + 29692644, 6829891, 56610064, 4334895, 20945975, 21647936, + 38221255, 8209390, 14606362, 22907359 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 584322311184395, 380661238802118, 114839394528060, + 655082270500073, 2111856026034852 +#else + 63627275, 8707080, 32188102, 5672294, 22096700, 1711240, + 34088169, 9761486, 4170404, 31469107 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 996965581008991, 2148998626477022, 1012273164934654, + 1073876063914522, 1688031788934939 +#else + 55521375, 14855944, 62981086, 32022574, 40459774, 15084045, + 22186522, 16002000, 52832027, 25153633 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 923487018849600, 2085106799623355, 528082801620136, + 1606206360876188, 735907091712524 +#else + 62297408, 13761028, 35404987, 31070512, 63796392, 7869046, + 59995292, 23934339, 13240844, 10965870 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1697697887804317, 1335343703828273, 831288615207040, + 949416685250051, 288760277392022 +#else + 59366301, 25297669, 52340529, 19898171, 43876480, 12387165, + 4498947, 14147411, 29514390, 4302863 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1419122478109648, 1325574567803701, 602393874111094, + 2107893372601700, 1314159682671307 +#else + 53695440, 21146572, 20757301, 19752600, 14785142, 8976368, + 62047588, 31410058, 17846987, 19582505 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2201150872731804, 2180241023425241, 97663456423163, + 1633405770247824, 848945042443986 +#else + 64864412, 32799703, 62511833, 32488122, 60861691, 1455298, + 45461136, 24339642, 61886162, 12650266 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1173339555550611, 818605084277583, 47521504364289, + 924108720564965, 735423405754506 +#else + 57202067, 17484121, 21134159, 12198166, 40044289, 708125, + 387813, 13770293, 47974538, 10958662 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 830104860549448, 1886653193241086, 1600929509383773, + 1475051275443631, 286679780900937 +#else + 22470984, 12369526, 23446014, 28113323, 45588061, 23855708, + 55336367, 21979976, 42025033, 4271861 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1577111294832995, 1030899169768747, 144900916293530, + 1964672592979567, 568390100955250 +#else + 41939299, 23500789, 47199531, 15361594, 61124506, 2159191, + 75375, 29275903, 34582642, 8469672 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 278388655910247, 487143369099838, 927762205508727, + 181017540174210, 1616886700741287 +#else + 15854951, 4148314, 58214974, 7259001, 11666551, 13824734, + 36577666, 2697371, 24154791, 24093489 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1191033906638969, 940823957346562, 1606870843663445, + 861684761499847, 658674867251089 +#else + 15446137, 17747788, 29759746, 14019369, 30811221, 23944241, + 35526855, 12840103, 24913809, 9815020 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1875032594195546, 1427106132796197, 724736390962158, + 901860512044740, 635268497268760 +#else + 62399578, 27940162, 35267365, 21265538, 52665326, 10799413, + 58005188, 13438768, 18735128, 9466238 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 622869792298357, 1903919278950367, 1922588621661629, + 1520574711600434, 1087100760174640 +#else + 11933045, 9281483, 5081055, 28370608, 64480701, 28648802, + 59381042, 22658328, 44380208, 16199063 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 25465949416618, 1693639527318811, 1526153382657203, + 125943137857169, 145276964043999 +#else + 14576810, 379472, 40322331, 25237195, 37682355, 22741457, + 67006097, 1876698, 30801119, 2164795 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 214739857969358, 920212862967915, 1939901550972269, + 1211862791775221, 85097515720120 +#else + 15995086, 3199873, 13672555, 13712240, 47730029, 28906785, + 54027253, 18058162, 53616056, 1268051 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2006245852772938, 734762734836159, 254642929763427, + 1406213292755966, 239303749517686 +#else + 56818250, 29895392, 63822271, 10948817, 23037027, 3794475, + 63638526, 20954210, 50053494, 3565903 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1619678837192149, 1919424032779215, 1357391272956794, + 1525634040073113, 1310226789796241 +#else + 29210069, 24135095, 61189071, 28601646, 10834810, 20226706, + 50596761, 22733718, 39946641, 19523900 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1040763709762123, 1704449869235352, 605263070456329, + 1998838089036355, 1312142911487502 +#else + 53946955, 15508587, 16663704, 25398282, 38758921, 9019122, + 37925443, 29785008, 2244110, 19552453 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1996723311435669, 1844342766567060, 985455700466044, + 1165924681400960, 311508689870129 +#else + 61955989, 29753495, 57802388, 27482848, 16243068, 14684434, + 41435776, 17373631, 13491505, 4641841 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 43173156290518, 2202883069785309, 1137787467085917, + 1733636061944606, 1394992037553852 +#else + 10813398, 643330, 47920349, 32825515, 30292061, 16954354, + 27548446, 25833190, 14476988, 20787001 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 670078326344559, 555655025059356, 471959386282438, + 2141455487356409, 849015953823125 +#else + 10292079, 9984945, 6481436, 8279905, 59857350, 7032742, + 27282937, 31910173, 39196053, 12651323 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2197214573372804, 794254097241315, 1030190060513737, + 267632515541902, 2040478049202624 +#else + 35923332, 32741048, 22271203, 11835308, 10201545, 15351028, + 17099662, 3988035, 21721536, 30405492 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1812516004670529, 1609256702920783, 1706897079364493, + 258549904773295, 996051247540686 +#else + 10202177, 27008593, 35735631, 23979793, 34958221, 25434748, + 54202543, 3852693, 13216206, 14842320 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1540374301420584, 1764656898914615, 1810104162020396, + 923808779163088, 664390074196579 +#else + 51293224, 22953365, 60569911, 26295436, 60124204, 26972653, + 35608016, 13765823, 39674467, 9900183 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1323460699404750, 1262690757880991, 871777133477900, + 1060078894988977, 1712236889662886 +#else + 14465486, 19721101, 34974879, 18815558, 39665676, 12990491, + 33046193, 15796406, 60056998, 25514317 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1696163952057966, 1391710137550823, 608793846867416, + 1034391509472039, 1780770894075012 +#else + 30924398, 25274812, 6359015, 20738097, 16508376, 9071735, + 41620263, 15413634, 9524356, 26535554 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1367603834210841, 2131988646583224, 890353773628144, + 1908908219165595, 270836895252891 +#else + 12274201, 20378885, 32627640, 31769106, 6736624, 13267305, + 5237659, 28444949, 15663515, 4035784 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 597536315471731, 40375058742586, 1942256403956049, + 1185484645495932, 312666282024145 +#else + 64157555, 8903984, 17349946, 601635, 50676049, 28941875, + 53376124, 17665097, 44850385, 4659090 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1919411405316294, 1234508526402192, 1066863051997083, + 1008444703737597, 1348810787701552 +#else + 50192582, 28601458, 36715152, 18395610, 20774811, 15897498, + 5736189, 15026997, 64930608, 20098846 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2102881477513865, 1570274565945361, 1573617900503708, + 18662635732583, 2232324307922098 +#else + 58249865, 31335375, 28571665, 23398914, 66634396, 23448733, + 63307367, 278094, 23440562, 33264224 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1853931367696942, 8107973870707, 350214504129299, + 775206934582587, 1752317649166792 +#else + 10226222, 27625730, 15139955, 120818, 52241171, 5218602, + 32937275, 11551483, 50536904, 26111567 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1417148368003523, 721357181628282, 505725498207811, + 373232277872983, 261634707184480 +#else + 17932739, 21117156, 43069306, 10749059, 11316803, 7535897, + 22503767, 5561594, 63462240, 3898660 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2186733281493267, 2250694917008620, 1014829812957440, + 479998161452389, 83566193876474 +#else + 7749907, 32584865, 50769132, 33537967, 42090752, 15122142, + 65535333, 7152529, 21831162, 1245233 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1268116367301224, 560157088142809, 802626839600444, + 2210189936605713, 1129993785579988 +#else + 26958440, 18896406, 4314585, 8346991, 61431100, 11960071, + 34519569, 32934396, 36706772, 16838219 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 615183387352312, 917611676109240, 878893615973325, + 978940963313282, 938686890583575 +#else + 54942968, 9166946, 33491384, 13673479, 29787085, 13096535, + 6280834, 14587357, 44770839, 13987524 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 522024729211672, 1045059315315808, 1892245413707790, + 1907891107684253, 2059998109500714 +#else + 42758936, 7778774, 21116000, 15572597, 62275598, 28196653, + 62807965, 28429792, 59639082, 30696363 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1799679152208884, 912132775900387, 25967768040979, + 432130448590461, 274568990261996 +#else + 9681908, 26817309, 35157219, 13591837, 60225043, 386949, + 31622781, 6439245, 52527852, 4091396 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 98698809797682, 2144627600856209, 1907959298569602, + 811491302610148, 1262481774981493 +#else + 58682418, 1470726, 38999185, 31957441, 3978626, 28430809, + 47486180, 12092162, 29077877, 18812444 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1791451399743152, 1713538728337276, 118349997257490, + 1882306388849954, 158235232210248 +#else + 5269168, 26694706, 53878652, 25533716, 25932562, 1763552, + 61502754, 28048550, 47091016, 2357888 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1217809823321928, 2173947284933160, 1986927836272325, + 1388114931125539, 12686131160169 +#else + 32264008, 18146780, 61721128, 32394338, 65017541, 29607531, + 23104803, 20684524, 5727337, 189038 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1650875518872272, 1136263858253897, 1732115601395988, + 734312880662190, 1252904681142109 +#else + 14609104, 24599962, 61108297, 16931650, 52531476, 25810533, + 40363694, 10942114, 41219933, 18669734 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 372986456113865, 525430915458171, 2116279931702135, + 501422713587815, 1907002872974925 +#else + 20513481, 5557931, 51504251, 7829530, 26413943, 31535028, + 45729895, 7471780, 13913677, 28416557 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 803147181835288, 868941437997146, 316299302989663, + 943495589630550, 571224287904572 +#else + 41534488, 11967825, 29233242, 12948236, 60354399, 4713226, + 58167894, 14059179, 12878652, 8511905 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 227742695588364, 1776969298667369, 628602552821802, + 457210915378118, 2041906378111140 +#else + 41452044, 3393630, 64153449, 26478905, 64858154, 9366907, + 36885446, 6812973, 5568676, 30426776 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 815000523470260, 913085688728307, 1052060118271173, + 1345536665214223, 541623413135555 +#else + 11630004, 12144454, 2116339, 13606037, 27378885, 15676917, + 49700111, 20050058, 52713667, 8070817 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1580216071604333, 1877997504342444, 857147161260913, + 703522726778478, 2182763974211603 +#else + 27117677, 23547054, 35826092, 27984343, 1127281, 12772488, + 37262958, 10483305, 55556115, 32525717 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1870080310923419, 71988220958492, 1783225432016732, + 615915287105016, 1035570475990230 +#else + 10637467, 27866368, 5674780, 1072708, 40765276, 26572129, + 65424888, 9177852, 39615702, 15431202 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 730987750830150, 857613889540280, 1083813157271766, + 1002817255970169, 1719228484436074 +#else + 20525126, 10892566, 54366392, 12779442, 37615830, 16150074, + 38868345, 14943141, 52052074, 25618500 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 377616581647602, 1581980403078513, 804044118130621, + 2034382823044191, 643844048472185 +#else + 37084402, 5626925, 66557297, 23573344, 753597, 11981191, + 25244767, 30314666, 63752313, 9594023 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 176957326463017, 1573744060478586, 528642225008045, + 1816109618372371, 1515140189765006 +#else + 43356201, 2636869, 61944954, 23450613, 585133, 7877383, + 11345683, 27062142, 13352334, 22577348 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1888911448245718, 1387110895611080, 1924503794066429, + 1731539523700949, 2230378382645454 +#else + 65177046, 28146973, 3304648, 20669563, 17015805, 28677341, + 37325013, 25801949, 53893326, 33235227 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 443392177002051, 233793396845137, 2199506622312416, + 1011858706515937, 974676837063129 +#else + 20239939, 6607058, 6203985, 3483793, 48721888, 32775202, + 46385121, 15077869, 44358105, 14523816 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1846351103143623, 1949984838808427, 671247021915253, + 1946756846184401, 1929296930380217 +#else + 27406023, 27512775, 27423595, 29057038, 4996213, 10002360, + 38266833, 29008937, 36936121, 28748764 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 849646212452002, 1410198775302919, 73767886183695, + 1641663456615812, 762256272452411 +#else + 11374242, 12660715, 17861383, 21013599, 10935567, 1099227, + 53222788, 24462691, 39381819, 11358503 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 692017667358279, 723305578826727, 1638042139863265, + 748219305990306, 334589200523901 +#else + 54378055, 10311866, 1510375, 10778093, 64989409, 24408729, + 32676002, 11149336, 40985213, 4985767 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 22893968530686, 2235758574399251, 1661465835630252, + 925707319443452, 1203475116966621 +#else + 48012542, 341146, 60911379, 33315398, 15756972, 24757770, + 66125820, 13794113, 47694557, 17933176 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 801299035785166, 1733292596726131, 1664508947088596, + 467749120991922, 1647498584535623 +#else + 6490062, 11940286, 25495923, 25828072, 8668372, 24803116, + 3367602, 6970005, 65417799, 24549641 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 903105258014366, 427141894933047, 561187017169777, + 1884330244401954, 1914145708422219 +#else + 1656478, 13457317, 15370807, 6364910, 13605745, 8362338, + 47934242, 28078708, 50312267, 28522993 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1344191060517578, 1960935031767890, 1518838929955259, + 1781502350597190, 1564784025565682 +#else + 44835530, 20030007, 67044178, 29220208, 48503227, 22632463, + 46537798, 26546453, 67009010, 23317098 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 673723351748086, 1979969272514923, 1175287312495508, + 1187589090978666, 1881897672213940 +#else + 17747446, 10039260, 19368299, 29503841, 46478228, 17513145, + 31992682, 17696456, 37848500, 28042460 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1917185587363432, 1098342571752737, 5935801044414, + 2000527662351839, 1538640296181569 +#else + 31932008, 28568291, 47496481, 16366579, 22023614, 88450, + 11371999, 29810185, 4882241, 22927527 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2495540013192, 678856913479236, 224998292422872, + 219635787698590, 1972465269000940 +#else + 29796488, 37186, 19818052, 10115756, 55279832, 3352735, + 18551198, 3272828, 61917932, 29392022 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 271413961212179, 1353052061471651, 344711291283483, + 2014925838520662, 2006221033113941 +#else + 12501267, 4044383, 58495907, 20162046, 34678811, 5136598, + 47878486, 30024734, 330069, 29895023 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 194583029968109, 514316781467765, 829677956235672, + 1676415686873082, 810104584395840 +#else + 6384877, 2899513, 17807477, 7663917, 64749976, 12363164, + 25366522, 24980540, 66837568, 12071498 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1980510813313589, 1948645276483975, 152063780665900, + 129968026417582, 256984195613935 +#else + 58743349, 29511910, 25133447, 29037077, 60897836, 2265926, + 34339246, 1936674, 61949167, 3829362 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1860190562533102, 1936576191345085, 461100292705964, + 1811043097042830, 957486749306835 +#else + 28425966, 27718999, 66531773, 28857233, 52891308, 6870929, + 7921550, 26986645, 26333139, 14267664 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 796664815624365, 1543160838872951, 1500897791837765, + 1667315977988401, 599303877030711 +#else + 56041645, 11871230, 27385719, 22994888, 62522949, 22365119, + 10004785, 24844944, 45347639, 8930323 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1151480509533204, 2136010406720455, 738796060240027, + 319298003765044, 1150614464349587 +#else + 45911060, 17158396, 25654215, 31829035, 12282011, 11008919, + 1541940, 4757911, 40617363, 17145491 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1731069268103150, 735642447616087, 1364750481334268, + 417232839982871, 927108269127661 +#else + 13537262, 25794942, 46504023, 10961926, 61186044, 20336366, + 53952279, 6217253, 51165165, 13814989 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1017222050227968, 1987716148359, 2234319589635701, + 621282683093392, 2132553131763026 +#else + 49686272, 15157789, 18705543, 29619, 24409717, 33293956, + 27361680, 9257833, 65152338, 31777517 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1567828528453324, 1017807205202360, 565295260895298, + 829541698429100, 307243822276582 +#else + 42063564, 23362465, 15366584, 15166509, 54003778, 8423555, + 37937324, 12361134, 48422886, 4578289 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 249079270936248, 1501514259790706, 947909724204848, + 944551802437487, 552658763982480 +#else + 24579768, 3711570, 1342322, 22374306, 40103728, 14124955, + 44564335, 14074918, 21964432, 8235257 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2089966982947227, 1854140343916181, 2151980759220007, + 2139781292261749, 158070445864917 +#else + 60580251, 31142934, 9442965, 27628844, 12025639, 32067012, + 64127349, 31885225, 13006805, 2355433 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1338766321464554, 1906702607371284, 1519569445519894, + 115384726262267, 1393058953390992 +#else + 50803946, 19949172, 60476436, 28412082, 16974358, 22643349, + 27202043, 1719366, 1141648, 20758196 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1364621558265400, 1512388234908357, 1926731583198686, + 2041482526432505, 920401122333774 +#else + 54244920, 20334445, 58790597, 22536340, 60298718, 28710537, + 13475065, 30420460, 32674894, 13715045 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1884844597333588, 601480070269079, 620203503079537, + 1079527400117915, 1202076693132015 +#else + 11423316, 28086373, 32344215, 8962751, 24989809, 9241752, + 53843611, 16086211, 38367983, 17912338 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 840922919763324, 727955812569642, 1303406629750194, + 522898432152867, 294161410441865 +#else + 65699196, 12530727, 60740138, 10847386, 19531186, 19422272, + 55399715, 7791793, 39862921, 4383346 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 353760790835310, 1598361541848743, 1122905698202299, + 1922533590158905, 419107700666580 +#else + 38137966, 5271446, 65842855, 23817442, 54653627, 16732598, + 62246457, 28647982, 27193556, 6245191 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 359856369838236, 180914355488683, 861726472646627, + 218807937262986, 575626773232501 +#else + 51914908, 5362277, 65324971, 2695833, 4960227, 12840725, + 23061898, 3260492, 22510453, 8577507 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 755467689082474, 909202735047934, 730078068932500, + 936309075711518, 2007798262842972 +#else + 54476394, 11257345, 34415870, 13548176, 66387860, 10879010, + 31168030, 13952092, 37537372, 29918525 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1609384177904073, 362745185608627, 1335318541768201, + 800965770436248, 547877979267412 +#else + 3877321, 23981693, 32416691, 5405324, 56104457, 19897796, + 3759768, 11935320, 5611860, 8164018 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 984339177776787, 815727786505884, 1645154585713747, + 1659074964378553, 1686601651984156 +#else + 50833043, 14667796, 15906460, 12155291, 44997715, 24514713, + 32003001, 24722143, 5773084, 25132323 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1697863093781930, 599794399429786, 1104556219769607, + 830560774794755, 12812858601017 +#else + 43320746, 25300131, 1950874, 8937633, 18686727, 16459170, + 66203139, 12376319, 31632953, 190926 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1168737550514982, 897832437380552, 463140296333799, + 302564600022547, 2008360505135501 +#else + 42515238, 17415546, 58684872, 13378745, 14162407, 6901328, + 58820115, 4508563, 41767309, 29926903 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1856930662813910, 678090852002597, 1920179140755167, + 1259527833759868, 55540971895511 +#else + 8884438, 27670423, 6023973, 10104341, 60227295, 28612898, + 18722940, 18768427, 65436375, 827624 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1158643631044921, 476554103621892, 178447851439725, + 1305025542653569, 103433927680625 +#else + 34388281, 17265135, 34605316, 7101209, 13354605, 2659080, + 65308289, 19446395, 42230385, 1541285 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2176793111709008, 1576725716350391, 2009350167273523, + 2012390194631546, 2125297410909580 +#else + 2901328, 32436745, 3880375, 23495044, 49487923, 29941650, + 45306746, 29986950, 20456844, 31669399 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 825403285195098, 2144208587560784, 1925552004644643, + 1915177840006985, 1015952128947864 +#else + 27019610, 12299467, 53450576, 31951197, 54247203, 28692960, + 47568713, 28538373, 29439640, 15138866 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1807108316634472, 1534392066433717, 347342975407218, + 1153820745616376, 7375003497471 +#else + 21536104, 26928012, 34661045, 22864223, 44700786, 5175813, + 61688824, 17193268, 7779327, 109896 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 983061001799725, 431211889901241, 2201903782961093, + 817393911064341, 2214616493042167 +#else + 30279725, 14648750, 59063993, 6425557, 13639621, 32810923, + 28698389, 12180118, 23177719, 33000357 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 228567918409756, 865093958780220, 358083886450556, + 159617889659320, 1360637926292598 +#else + 26572828, 3405927, 35407164, 12890904, 47843196, 5335865, + 60615096, 2378491, 4439158, 20275085 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 234147501399755, 2229469128637390, 2175289352258889, + 1397401514549353, 1885288963089922 +#else + 44392139, 3489069, 57883598, 33221678, 18875721, 32414337, + 14819433, 20822905, 49391106, 28092994 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1111762412951562, 252849572507389, 1048714233823341, + 146111095601446, 1237505378776770 +#else + 62052362, 16566550, 15953661, 3767752, 56672365, 15627059, + 66287910, 2177224, 8550082, 18440267 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1113790697840279, 1051167139966244, 1045930658550944, + 2011366241542643, 1686166824620755 +#else + 48635543, 16596774, 66727204, 15663610, 22860960, 15585581, + 39264755, 29971692, 43848403, 25125843 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1054097349305049, 1872495070333352, 182121071220717, + 1064378906787311, 100273572924182 +#else + 34628313, 15707274, 58902952, 27902350, 29464557, 2713815, + 44383727, 15860481, 45206294, 1494192 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1306410853171605, 1627717417672447, 50983221088417, + 1109249951172250, 870201789081392 +#else + 47546773, 19467038, 41524991, 24254879, 13127841, 759709, + 21923482, 16529112, 8742704, 12967017 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 104233794644221, 1548919791188248, 2224541913267306, + 2054909377116478, 1043803389015153 +#else + 38643965, 1553204, 32536856, 23080703, 42417258, 33148257, + 58194238, 30620535, 37205105, 15553882 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 216762189468802, 707284285441622, 190678557969733, + 973969342604308, 1403009538434867 +#else + 21877890, 3230008, 9881174, 10539357, 62311749, 2841331, + 11543572, 14513274, 19375923, 20906471 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1279024291038477, 344776835218310, 273722096017199, + 1834200436811442, 634517197663804 +#else + 8832269, 19058947, 13253510, 5137575, 5037871, 4078777, + 24880818, 27331716, 2862652, 9455043 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 343805853118335, 1302216857414201, 566872543223541, + 2051138939539004, 321428858384280 +#else + 29306751, 5123106, 20245049, 19404543, 9592565, 8447059, + 65031740, 30564351, 15511448, 4789663 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 470067171324852, 1618629234173951, 2000092177515639, + 7307679772789, 1117521120249968 +#else + 46429108, 7004546, 8824831, 24119455, 63063159, 29803695, + 61354101, 108892, 23513200, 16652362 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 278151578291475, 1810282338562947, 1771599529530998, + 1383659409671631, 685373414471841 +#else + 33852691, 4144781, 62632835, 26975308, 10770038, 26398890, + 60458447, 20618131, 48789665, 10212859 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 577009397403102, 1791440261786291, 2177643735971638, + 174546149911960, 1412505077782326 +#else + 2756062, 8598110, 7383731, 26694540, 22312758, 32449420, + 21179800, 2600940, 57120566, 21047965 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 893719721537457, 1201282458018197, 1522349501711173, + 58011597740583, 1130406465887139 +#else + 42463153, 13317461, 36659605, 17900503, 21365573, 22684775, + 11344423, 864440, 64609187, 16844368 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 412607348255453, 1280455764199780, 2233277987330768, + 14180080401665, 331584698417165 +#else + 40676061, 6148328, 49924452, 19080277, 18782928, 33278435, + 44547329, 211299, 2719757, 4940997 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 262483770854550, 990511055108216, 526885552771698, + 571664396646158, 354086190278723 +#else + 65784982, 3911312, 60160120, 14759764, 37081714, 7851206, + 21690126, 8518463, 26699843, 5276295 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1820352417585487, 24495617171480, 1547899057533253, + 10041836186225, 480457105094042 +#else + 53958991, 27125364, 9396248, 365013, 24703301, 23065493, + 1321585, 149635, 51656090, 7159368 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2023310314989233, 637905337525881, 2106474638900687, + 557820711084072, 1687858215057826 +#else + 9987761, 30149673, 17507961, 9505530, 9731535, 31388918, + 22356008, 8312176, 22477218, 25151047 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1144168702609745, 604444390410187, 1544541121756138, + 1925315550126027, 626401428894002 +#else + 18155857, 17049442, 19744715, 9006923, 15154154, 23015456, + 24256459, 28689437, 44560690, 9334108 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1922168257351784, 2018674099908659, 1776454117494445, + 956539191509034, 36031129147635 +#else + 2986088, 28642539, 10776627, 30080588, 10620589, 26471229, + 45695018, 14253544, 44521715, 536905 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 544644538748041, 1039872944430374, 876750409130610, + 710657711326551, 1216952687484972 +#else + 4377737, 8115836, 24567078, 15495314, 11625074, 13064599, + 7390551, 10589625, 10838060, 18134008 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 58242421545916, 2035812695641843, 2118491866122923, + 1191684463816273, 46921517454099 +#else + 47766460, 867879, 9277171, 30335973, 52677291, 31567988, + 19295825, 17757482, 6378259, 699185 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 272268252444639, 1374166457774292, 2230115177009552, + 1053149803909880, 1354288411641016 +#else + 7895007, 4057113, 60027092, 20476675, 49222032, 33231305, + 66392824, 15693154, 62063800, 20180469 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1857910905368338, 1754729879288912, 885945464109877, + 1516096106802166, 1602902393369811 +#else + 59371282, 27685029, 52542544, 26147512, 11385653, 13201616, + 31730678, 22591592, 63190227, 23885106 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1193437069800958, 901107149704790, 999672920611411, + 477584824802207, 364239578697845 +#else + 10188286, 17783598, 59772502, 13427542, 22223443, 14896287, + 30743455, 7116568, 45322357, 5427592 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 886299989548838, 1538292895758047, 1590564179491896, + 1944527126709657, 837344427345298 +#else + 696102, 13206899, 27047647, 22922350, 15285304, 23701253, + 10798489, 28975712, 19236242, 12477404 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 754558365378305, 1712186480903618, 1703656826337531, + 750310918489786, 518996040250900 +#else + 55879425, 11243795, 50054594, 25513566, 66320635, 25386464, + 63211194, 11180503, 43939348, 7733643 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1309847803895382, 1462151862813074, 211370866671570, + 1544595152703681, 1027691798954090 +#else + 17800790, 19518253, 40108434, 21787760, 23887826, 3149671, + 23466177, 23016261, 10322026, 15313801 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 803217563745370, 1884799722343599, 1357706345069218, + 2244955901722095, 730869460037413 +#else + 26246234, 11968874, 32263343, 28085704, 6830754, 20231401, + 51314159, 33452449, 42659621, 10890803 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 689299471295966, 1831210565161071, 1375187341585438, + 1106284977546171, 1893781834054269 +#else + 35743198, 10271362, 54448239, 27287163, 16690206, 20491888, + 52126651, 16484930, 25180797, 28219548 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 696351368613042, 1494385251239250, 738037133616932, + 636385507851544, 927483222611406 +#else + 66522290, 10376443, 34522450, 22268075, 19801892, 10997610, + 2276632, 9482883, 316878, 13820577 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1949114198209333, 1104419699537997, 783495707664463, + 1747473107602770, 2002634765788641 +#else + 57226037, 29044064, 64993357, 16457135, 56008783, 11674995, + 30756178, 26039378, 30696929, 29841583 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1607325776830197, 530883941415333, 1451089452727895, + 1581691157083423, 496100432831154 +#else + 32988917, 23951020, 12499365, 7910787, 56491607, 21622917, + 59766047, 23569034, 34759346, 7392472 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1068900648804224, 2006891997072550, 1134049269345549, + 1638760646180091, 2055396084625778 +#else + 58253184, 15927860, 9866406, 29905021, 64711949, 16898650, + 36699387, 24419436, 25112946, 30627788 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2222475519314561, 1870703901472013, 1884051508440561, + 1344072275216753, 1318025677799069 +#else + 64604801, 33117465, 25621773, 27875660, 15085041, 28074555, + 42223985, 20028237, 5537437, 19640113 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 155711679280656, 681100400509288, 389811735211209, + 2135723811340709, 408733211204125 +#else + 55883280, 2320284, 57524584, 10149186, 33664201, 5808647, + 52232613, 31824764, 31234589, 6090599 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 7813206966729, 194444201427550, 2071405409526507, + 1065605076176312, 1645486789731291 +#else + 57475529, 116425, 26083934, 2897444, 60744427, 30866345, 609720, + 15878753, 60138459, 24519663 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 16625790644959, 1647648827778410, 1579910185572704, + 436452271048548, 121070048451050 +#else + 39351007, 247743, 51914090, 24551880, 23288160, 23542496, + 43239268, 6503645, 20650474, 1804084 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1037263028552531, 568385780377829, 297953104144430, + 1558584511931211, 2238221839292471 +#else + 39519059, 15456423, 8972517, 8469608, 15640622, 4439847, + 3121995, 23224719, 27842615, 33352104 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 190565267697443, 672855706028058, 338796554369226, + 337687268493904, 853246848691734 +#else + 51801891, 2839643, 22530074, 10026331, 4602058, 5048462, + 28248656, 5031932, 55733782, 12714368 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1763863028400139, 766498079432444, 1321118624818005, + 69494294452268, 858786744165651 +#else + 20807691, 26283607, 29286140, 11421711, 39232341, 19686201, + 45881388, 1035545, 47375635, 12796919 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1292056768563024, 1456632109855638, 1100631247050184, + 1386133165675321, 1232898350193752 +#else + 12076880, 19253146, 58323862, 21705509, 42096072, 16400683, + 49517369, 20654993, 3480664, 18371617 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 366253102478259, 525676242508811, 1449610995265438, + 1183300845322183, 185960306491545 +#else + 34747315, 5457596, 28548107, 7833186, 7303070, 21600887, + 42745799, 17632556, 33734809, 2771024 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 28315355815982, 460422265558930, 1799675876678724, + 1969256312504498, 1051823843138725 +#else + 45719598, 421931, 26597266, 6860826, 22486084, 26817260, + 49971378, 29344205, 42556581, 15673396 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 156914999361983, 1606148405719949, 1665208410108430, + 317643278692271, 1383783705665320 +#else + 46924223, 2338215, 19788685, 23933476, 63107598, 24813538, + 46837679, 4733253, 3727144, 20619984 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 54684536365732, 2210010038536222, 1194984798155308, + 535239027773705, 1516355079301361 +#else + 6120100, 814863, 55314462, 32931715, 6812204, 17806661, 2019593, + 7975683, 31123697, 22595451 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1484387703771650, 198537510937949, 2186282186359116, + 617687444857508, 647477376402122 +#else + 30069250, 22119100, 30434653, 2958439, 18399564, 32578143, + 12296868, 9204260, 50676426, 9648164 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2147715541830533, 500032538445817, 646380016884826, + 352227855331122, 1488268620408052 +#else + 32705413, 32003455, 30705657, 7451065, 55303258, 9631812, + 3305266, 5248604, 41100532, 22176930 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 159386186465542, 1877626593362941, 618737197060512, + 1026674284330807, 1158121760792685 +#else + 17219846, 2375039, 35537917, 27978816, 47649184, 9219902, + 294711, 15298639, 2662509, 17257359 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1744544377739822, 1964054180355661, 1685781755873170, + 2169740670377448, 1286112621104591 +#else + 65935918, 25995736, 62742093, 29266687, 45762450, 25120105, + 32087528, 32331655, 32247247, 19164571 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 81977249784993, 1667943117713086, 1668983819634866, + 1605016835177615, 1353960708075544 +#else + 14312609, 1221556, 17395390, 24854289, 62163122, 24869796, + 38911119, 23916614, 51081240, 20175586 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1602253788689063, 439542044889886, 2220348297664483, + 657877410752869, 157451572512238 +#else + 65680039, 23875441, 57873182, 6549686, 59725795, 33085767, + 23046501, 9803137, 17597934, 2346211 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1029287186166717, 65860128430192, 525298368814832, + 1491902500801986, 1461064796385400 +#else + 18510781, 15337574, 26171504, 981392, 44867312, 7827555, + 43617730, 22231079, 3059832, 21771562 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 408216988729246, 2121095722306989, 913562102267595, + 1879708920318308, 241061448436731 +#else + 10141598, 6082907, 17829293, 31606789, 9830091, 13613136, + 41552228, 28009845, 33606651, 3592095 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1185483484383269, 1356339572588553, 584932367316448, + 102132779946470, 1792922621116791 +#else + 33114149, 17665080, 40583177, 20211034, 33076704, 8716171, + 1151462, 1521897, 66126199, 26716628 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1966196870701923, 2230044620318636, 1425982460745905, + 261167817826569, 46517743394330 +#else + 34169699, 29298616, 23947180, 33230254, 34035889, 21248794, + 50471177, 3891703, 26353178, 693168 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 107077591595359, 884959942172345, 27306869797400, + 2224911448949390, 964352058245223 +#else + 30374239, 1595580, 50224825, 13186930, 4600344, 406904, 9585294, + 33153764, 31375463, 14369965 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1730194207717538, 431790042319772, 1831515233279467, + 1372080552768581, 1074513929381760 +#else + 52738210, 25781902, 1510300, 6434173, 48324075, 27291703, + 32732229, 20445593, 17901440, 16011505 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1450880638731607, 1019861580989005, 1229729455116861, + 1174945729836143, 826083146840706 +#else + 18171223, 21619806, 54608461, 15197121, 56070717, 18324396, + 47936623, 17508055, 8764034, 12309598 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1899935429242705, 1602068751520477, 940583196550370, + 82431069053859, 1540863155745696 +#else + 5975889, 28311244, 47649501, 23872684, 55567586, 14015781, + 43443107, 1228318, 17544096, 22960650 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2136688454840028, 2099509000964294, 1690800495246475, + 1217643678575476, 828720645084218 +#else + 5811932, 31839139, 3442886, 31285122, 48741515, 25194890, + 49064820, 18144304, 61543482, 12348899 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 765548025667841, 462473984016099, 998061409979798, + 546353034089527, 2212508972466858 +#else + 35709185, 11407554, 25755363, 6891399, 63851926, 14872273, + 42259511, 8141294, 56476330, 32968952 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 46575283771160, 892570971573071, 1281983193144090, + 1491520128287375, 75847005908304 +#else + 54433560, 694025, 62032719, 13300343, 14015258, 19103038, + 57410191, 22225381, 30944592, 1130208 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1801436127943107, 1734436817907890, 1268728090345068, + 167003097070711, 2233597765834956 +#else + 8247747, 26843490, 40546482, 25845122, 52706924, 18905521, + 4652151, 2488540, 23550156, 33283200 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1997562060465113, 1048700225534011, 7615603985628, + 1855310849546841, 2242557647635213 +#else + 17294297, 29765994, 7026747, 15626851, 22990044, 113481, + 2267737, 27646286, 66700045, 33416712 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1161017320376250, 492624580169043, 2169815802355237, + 976496781732542, 1770879511019629 +#else + 16091066, 17300506, 18599251, 7340678, 2137637, 32332775, + 63744702, 14550935, 3260525, 26388161 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1357044908364776, 729130645262438, 1762469072918979, + 1365633616878458, 181282906404941 +#else + 62198760, 20221544, 18550886, 10864893, 50649539, 26262835, + 44079994, 20349526, 54360141, 2701325 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1080413443139865, 1155205815510486, 1848782073549786, + 622566975152580, 124965574467971 +#else + 58534169, 16099414, 4629974, 17213908, 46322650, 27548999, + 57090500, 9276970, 11329923, 1862132 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1184526762066993, 247622751762817, 692129017206356, + 820018689412496, 2188697339828085 +#else + 14763057, 17650824, 36190593, 3689866, 3511892, 10313526, + 45157776, 12219230, 58070901, 32614131 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2020536369003019, 202261491735136, 1053169669150884, + 2056531979272544, 778165514694311 +#else + 8894987, 30108338, 6150752, 3013931, 301220, 15693451, 35127648, + 30644714, 51670695, 11595569 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 237404399610207, 1308324858405118, 1229680749538400, + 720131409105291, 1958958863624906 +#else + 15214943, 3537601, 40870142, 19495559, 4418656, 18323671, + 13947275, 10730794, 53619402, 29190761 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 515583508038846, 17656978857189, 1717918437373989, + 1568052070792483, 46975803123923 +#else + 64570558, 7682792, 32759013, 263109, 37124133, 25598979, + 44776739, 23365796, 977107, 699994 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 281527309158085, 36970532401524, 866906920877543, + 2222282602952734, 1289598729589882 +#else + 54642373, 4195083, 57897332, 550903, 51543527, 12917919, + 19118110, 33114591, 36574330, 19216518 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1278207464902042, 494742455008756, 1262082121427081, + 1577236621659884, 1888786707293291 +#else + 31788442, 19046775, 4799988, 7372237, 8808585, 18806489, + 9408236, 23502657, 12493931, 28145115 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 353042527954210, 1830056151907359, 1111731275799225, + 174960955838824, 404312815582675 +#else + 41428258, 5260743, 47873055, 27269961, 63412921, 16566086, + 27218280, 2607121, 29375955, 6024730 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2064251142068628, 1666421603389706, 1419271365315441, + 468767774902855, 191535130366583 +#else + 842132, 30759739, 62345482, 24831616, 26332017, 21148791, + 11831879, 6985184, 57168503, 2854095 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1716987058588002, 1859366439773457, 1767194234188234, + 64476199777924, 1117233614485261 +#else + 62261602, 25585100, 2516241, 27706719, 9695690, 26333246, + 16512644, 960770, 12121869, 16648078 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 984292135520292, 135138246951259, 2220652137473167, + 1722843421165029, 190482558012909 +#else + 51890212, 14667095, 53772635, 2013716, 30598287, 33090295, + 35603941, 25672367, 20237805, 2838411 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 298845952651262, 1166086588952562, 1179896526238434, + 1347812759398693, 1412945390096208 +#else + 47820798, 4453151, 15298546, 17376044, 22115042, 17581828, + 12544293, 20083975, 1068880, 21054527 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1143239552672925, 906436640714209, 2177000572812152, + 2075299936108548, 325186347798433 +#else + 57549981, 17035596, 33238497, 13506958, 30505848, 32439836, + 58621956, 30924378, 12521377, 4845654 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 721024854374772, 684487861263316, 1373438744094159, + 2193186935276995, 1387043709851261 +#else + 38910324, 10744107, 64150484, 10199663, 7759311, 20465832, + 3409347, 32681032, 60626557, 20668561 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 418098668140962, 715065997721283, 1471916138376055, + 2168570337288357, 937812682637044 +#else + 43547042, 6230155, 46726851, 10655313, 43068279, 21933259, + 10477733, 32314216, 63995636, 13974497 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1043584187226485, 2143395746619356, 2209558562919611, + 482427979307092, 847556718384018 +#else + 12966261, 15550616, 35069916, 31939085, 21025979, 32924988, + 5642324, 7188737, 18895762, 12629579 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1248731221520759, 1465200936117687, 540803492710140, + 52978634680892, 261434490176109 +#else + 14741879, 18607545, 22177207, 21833195, 1279740, 8058600, + 11758140, 789443, 32195181, 3895677 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1057329623869501, 620334067429122, 461700859268034, + 2012481616501857, 297268569108938 +#else + 10758205, 15755439, 62598914, 9243697, 62229442, 6879878, + 64904289, 29988312, 58126794, 4429646 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1055352180870759, 1553151421852298, 1510903185371259, + 1470458349428097, 1226259419062731 +#else + 64654951, 15725972, 46672522, 23143759, 61304955, 22514211, + 59972993, 21911536, 18047435, 18272689 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1492988790301668, 790326625573331, 1190107028409745, + 1389394752159193, 1620408196604194 +#else + 41935844, 22247266, 29759955, 11776784, 44846481, 17733976, + 10993113, 20703595, 49488162, 24145963 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 47000654413729, 1004754424173864, 1868044813557703, + 173236934059409, 588771199737015 +#else + 21987233, 700364, 42603816, 14972007, 59334599, 27836036, + 32155025, 2581431, 37149879, 8773374 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 30498470091663, 1082245510489825, 576771653181956, + 806509986132686, 1317634017056939 +#else + 41540495, 454462, 53896929, 16126714, 25240068, 8594567, + 20656846, 12017935, 59234475, 19634276 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 420308055751555, 1493354863316002, 165206721528088, + 1884845694919786, 2065456951573059 +#else + 6028163, 6263078, 36097058, 22252721, 66289944, 2461771, + 35267690, 28086389, 65387075, 30777706 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1115636332012334, 1854340990964155, 83792697369514, + 1972177451994021, 457455116057587 +#else + 54829870, 16624276, 987579, 27631834, 32908202, 1248608, + 7719845, 29387734, 28408819, 6816612 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1698968457310898, 1435137169051090, 1083661677032510, + 938363267483709, 340103887207182 +#else + 56750770, 25316602, 19549650, 21385210, 22082622, 16147817, + 20613181, 13982702, 56769294, 5067942 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1995325341336574, 911500251774648, 164010755403692, + 855378419194762, 1573601397528842 +#else + 36602878, 29732664, 12074680, 13582412, 47230892, 2443950, + 47389578, 12746131, 5331210, 23448488 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 241719380661528, 310028521317150, 1215881323380194, + 1408214976493624, 2141142156467363 +#else + 30528792, 3601899, 65151774, 4619784, 39747042, 18118043, + 24180792, 20984038, 27679907, 31905504 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1315157046163473, 727368447885818, 1363466668108618, + 1668921439990361, 1398483384337907 +#else + 9402385, 19597367, 32834042, 10838634, 40528714, 20317236, + 26653273, 24868867, 22611443, 20839026 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 75029678299646, 1015388206460473, 1849729037055212, + 1939814616452984, 444404230394954 +#else + 22190590, 1118029, 22736441, 15130463, 36648172, 27563110, + 19189624, 28905490, 4854858, 6622139 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2053597130993710, 2024431685856332, 2233550957004860, + 2012407275509545, 872546993104440 +#else + 58798126, 30600981, 58846284, 30166382, 56707132, 33282502, + 13424425, 29987205, 26404408, 13001963 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1217269667678610, 599909351968693, 1390077048548598, + 1471879360694802, 739586172317596 +#else + 35867026, 18138731, 64114613, 8939345, 11562230, 20713762, + 41044498, 21932711, 51703708, 11020692 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1718318639380794, 1560510726633958, 904462881159922, + 1418028351780052, 94404349451937 +#else + 1866042, 25604943, 59210214, 23253421, 12483314, 13477547, + 3175636, 21130269, 28761761, 1406734 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2132502667405250, 214379346175414, 1502748313768060, + 1960071701057800, 1353971822643138 +#else + 66660290, 31776765, 13018550, 3194501, 57528444, 22392694, + 24760584, 29207344, 25577410, 20175752 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 319394212043702, 2127459436033571, 717646691535162, + 663366796076914, 318459064945314 +#else + 42818486, 4759344, 66418211, 31701615, 2066746, 10693769, + 37513074, 9884935, 57739938, 4745409 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 405989424923593, 1960452633787083, 667349034401665, + 1492674260767112, 1451061489880787 +#else + 57967561, 6049713, 47577803, 29213020, 35848065, 9944275, + 51646856, 22242579, 10931923, 21622501 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 947085906234007, 323284730494107, 1485778563977200, + 728576821512394, 901584347702286 +#else + 50547351, 14112679, 59096219, 4817317, 59068400, 22139825, + 44255434, 10856640, 46638094, 13434653 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1575783124125742, 2126210792434375, 1569430791264065, + 1402582372904727, 1891780248341114 +#else + 22759470, 23480998, 50342599, 31683009, 13637441, 23386341, + 1765143, 20900106, 28445306, 28189722 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 838432205560695, 1997703511451664, 1018791879907867, + 1662001808174331, 78328132957753 +#else + 29875063, 12493613, 2795536, 29768102, 1710619, 15181182, + 56913147, 24765756, 9074233, 1167180 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 739152638255629, 2074935399403557, 505483666745895, + 1611883356514088, 628654635394878 +#else + 40903181, 11014232, 57266213, 30918946, 40200743, 7532293, + 48391976, 24018933, 3843902, 9367684 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1822054032121349, 643057948186973, 7306757352712, + 577249257962099, 284735863382083 +#else + 56139269, 27150720, 9591133, 9582310, 11349256, 108879, + 16235123, 8601684, 66969667, 4242894 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1366558556363930, 1448606567552086, 1478881020944768, + 165803179355898, 1115718458123498 +#else + 22092954, 20363309, 65066070, 21585919, 32186752, 22037044, + 60534522, 2470659, 39691498, 16625500 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 204146226972102, 1630511199034723, 2215235214174763, + 174665910283542, 956127674017216 +#else + 56051142, 3042015, 13770083, 24296510, 584235, 33009577, + 59338006, 2602724, 39757248, 14247412 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1562934578796716, 1070893489712745, 11324610642270, + 958989751581897, 2172552325473805 +#else + 6314156, 23289540, 34336361, 15957556, 56951134, 168749, + 58490057, 14290060, 27108877, 32373552 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1770564423056027, 735523631664565, 1326060113795289, + 1509650369341127, 65892421582684 +#else + 58522267, 26383465, 13241781, 10960156, 34117849, 19759835, + 33547975, 22495543, 39960412, 981873 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 623682558650637, 1337866509471512, 990313350206649, + 1314236615762469, 1164772974270275 +#else + 22833421, 9293594, 34459416, 19935764, 57971897, 14756818, + 44180005, 19583651, 56629059, 17356469 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 223256821462517, 723690150104139, 1000261663630601, + 933280913953265, 254872671543046 +#else + 59340277, 3326785, 38997067, 10783823, 19178761, 14905060, + 22680049, 13906969, 51175174, 3797898 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1969087237026041, 624795725447124, 1335555107635969, + 2069986355593023, 1712100149341902 +#else + 21721337, 29341686, 54902740, 9310181, 63226625, 19901321, + 23740223, 30845200, 20491982, 25512280 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1236103475266979, 1837885883267218, 1026072585230455, + 1025865513954973, 1801964901432134 +#else + 9209251, 18419377, 53852306, 27386633, 66377847, 15289672, + 25947805, 15286587, 30997318, 26851369 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1115241013365517, 1712251818829143, 2148864332502771, + 2096001471438138, 2235017246626125 +#else + 7392013, 16618386, 23946583, 25514540, 53843699, 32020573, + 52911418, 31232855, 17649997, 33304352 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1299268198601632, 2047148477845621, 2165648650132450, + 1612539282026145, 514197911628890 +#else + 57807776, 19360604, 30609525, 30504889, 41933794, 32270679, + 51867297, 24028707, 64875610, 7662145 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 118352772338543, 1067608711804704, 1434796676193498, + 1683240170548391, 230866769907437 +#else + 49550191, 1763593, 33994528, 15908609, 37067994, 21380136, + 7335079, 25082233, 63934189, 3440182 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1850689576796636, 1601590730430274, 1139674615958142, + 1954384401440257, 76039205311 +#else + 47219164, 27577423, 42997570, 23865561, 10799742, 16982475, + 40449, 29122597, 4862399, 1133 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1723387471374172, 997301467038410, 533927635123657, + 20928644693965, 1756575222802513 +#else + 34252636, 25680474, 61686474, 14860949, 50789833, 7956141, + 7258061, 311861, 36513873, 26175010 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2146711623855116, 503278928021499, 625853062251406, + 1109121378393107, 1033853809911861 +#else + 63335436, 31988495, 28985339, 7499440, 24445838, 9325937, + 29727763, 16527196, 18278453, 15405622 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 571005965509422, 2005213373292546, 1016697270349626, + 56607856974274, 914438579435146 +#else + 62726958, 8508651, 47210498, 29880007, 61124410, 15149969, + 53795266, 843522, 45233802, 13626196 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1346698876211176, 2076651707527589, 1084761571110205, + 265334478828406, 1068954492309671 +#else + 2281448, 20067377, 56193445, 30944521, 1879357, 16164207, + 56324982, 3953791, 13340839, 15928663 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1769967932677654, 1695893319756416, 1151863389675920, + 1781042784397689, 400287774418285 +#else + 31727126, 26374577, 48671360, 25270779, 2875792, 17164102, + 41838969, 26539605, 43656557, 5964752 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1851867764003121, 403841933237558, 820549523771987, + 761292590207581, 1743735048551143 +#else + 4100401, 27594980, 49929526, 6017713, 48403027, 12227140, + 40424029, 11344143, 2538215, 25983677 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 410915148140008, 2107072311871739, 1004367461876503, + 99684895396761, 1180818713503224 +#else + 57675240, 6123112, 11159803, 31397824, 30016279, 14966241, + 46633881, 1485420, 66479608, 17595569 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 285945406881439, 648174397347453, 1098403762631981, + 1366547441102991, 1505876883139217 +#else + 40304287, 4260918, 11851389, 9658551, 35091757, 16367491, + 46903439, 20363143, 11659921, 22439314 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 672095903120153, 1675918957959872, 636236529315028, + 1569297300327696, 2164144194785875 +#else + 26180377, 10015009, 36264640, 24973138, 5418196, 9480663, + 2231568, 23384352, 33100371, 32248261 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1902708175321798, 1035343530915438, 1178560808893263, + 301095684058146, 1280977479761118 +#else + 15121094, 28352561, 56718958, 15427820, 39598927, 17561924, + 21670946, 4486675, 61177054, 19088051 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1615357281742403, 404257611616381, 2160201349780978, + 1160947379188955, 1578038619549541 +#else + 16166467, 24070699, 56004733, 6023907, 35182066, 32189508, + 2340059, 17299464, 56373093, 23514607 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2013087639791217, 822734930507457, 1785668418619014, + 1668650702946164, 389450875221715 +#else + 28042865, 29997343, 54982337, 12259705, 63391366, 26608532, + 6766452, 24864833, 18036435, 5803270 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 453918449698368, 106406819929001, 2072540975937135, + 308588860670238, 1304394580755385 +#else + 66291264, 6763911, 11803561, 1585585, 10958447, 30883267, + 23855390, 4598332, 60949433, 19436993 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1295082798350326, 2091844511495996, 1851348972587817, + 3375039684596, 789440738712837 +#else + 36077558, 19298237, 17332028, 31170912, 31312681, 27587249, + 696308, 50292, 47013125, 11763583 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2083069137186154, 848523102004566, 993982213589257, + 1405313299916317, 1532824818698468 +#else + 66514282, 31040148, 34874710, 12643979, 12650761, 14811489, + 665117, 20940800, 47335652, 22840869 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1495961298852430, 1397203457344779, 1774950217066942, + 139302743555696, 66603584342787 +#else + 30464590, 22291560, 62981387, 20819953, 19835326, 26448819, + 42712688, 2075772, 50088707, 992470 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1782411379088302, 1096724939964781, 27593390721418, + 542241850291353, 1540337798439873 +#else + 18357166, 26559999, 7766381, 16342475, 37783946, 411173, + 14578841, 8080033, 55534529, 22952821 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 693543956581437, 171507720360750, 1557908942697227, + 1074697073443438, 1104093109037196 +#else + 19598397, 10334610, 12555054, 2555664, 18821899, 23214652, + 21873262, 16014234, 26224780, 16452269 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 345288228393419, 1099643569747172, 134881908403743, + 1740551994106740, 248212179299770 +#else + 36884939, 5145195, 5944548, 16385966, 3976735, 2009897, + 55731060, 25936245, 46575034, 3698649 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 231429562203065, 1526290236421172, 2021375064026423, + 1520954495658041, 806337791525116 +#else + 14187449, 3448569, 56472628, 22743496, 44444983, 30120835, + 7268409, 22663988, 27394300, 12015369 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1079623667189886, 872403650198613, 766894200588288, + 2163700860774109, 2023464507911816 +#else + 19695742, 16087646, 28032085, 12999827, 6817792, 11427614, + 20244189, 32241655, 53849736, 30151970 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 854645372543796, 1936406001954827, 151460662541253, + 825325739271555, 1554306377287556 +#else + 30860084, 12735208, 65220619, 28854697, 50133957, 2256939, + 58942851, 12298311, 58558340, 23160969 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1497138821904622, 1044820250515590, 1742593886423484, + 1237204112746837, 849047450816987 +#else + 61389038, 22309106, 65198214, 15569034, 26642876, 25966672, + 61319509, 18435777, 62132699, 12651792 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 667962773375330, 1897271816877105, 1399712621683474, + 1143302161683099, 2081798441209593 +#else + 64260450, 9953420, 11531313, 28271553, 26895122, 20857343, + 53990043, 17036529, 9768697, 31021214 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 127147851567005, 1936114012888110, 1704424366552046, + 856674880716312, 716603621335359 +#else + 42389405, 1894650, 66821166, 28850346, 15348718, 25397902, + 32767512, 12765450, 4940095, 10678226 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1072409664800960, 2146937497077528, 1508780108920651, + 935767602384853, 1112800433544068 +#else + 18860224, 15980149, 48121624, 31991861, 40875851, 22482575, + 59264981, 13944023, 42736516, 16582018 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 333549023751292, 280219272863308, 2104176666454852, + 1036466864875785, 536135186520207 +#else + 51604604, 4970267, 37215820, 4175592, 46115652, 31354675, + 55404809, 15444559, 56105103, 7989036 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 373666279883137, 146457241530109, 304116267127857, + 416088749147715, 1258577131183391 +#else + 31490433, 5568061, 64696061, 2182382, 34772017, 4531685, + 35030595, 6200205, 47422751, 18754260 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1186115062588401, 2251609796968486, 1098944457878953, + 1153112761201374, 1791625503417267 +#else + 49800177, 17674491, 35586086, 33551600, 34221481, 16375548, + 8680158, 17182719, 28550067, 26697300 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1870078460219737, 2129630962183380, 852283639691142, + 292865602592851, 401904317342226 +#else + 38981977, 27866340, 16837844, 31733974, 60258182, 12700015, + 37068883, 4364037, 1155602, 5988841 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1361070124828035, 815664541425524, 1026798897364671, + 1951790935390647, 555874891834790 +#else + 21890435, 20281525, 54484852, 12154348, 59276991, 15300495, + 23148983, 29083951, 24618406, 8283181 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1546301003424277, 459094500062839, 1097668518375311, + 1780297770129643, 720763293687608 +#else + 33972757, 23041680, 9975415, 6841041, 35549071, 16356535, + 3070187, 26528504, 1466168, 10740210 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1212405311403990, 1536693382542438, 61028431067459, + 1863929423417129, 1223219538638038 +#else + 65599446, 18066246, 53605478, 22898515, 32799043, 909394, + 53169961, 27774712, 34944214, 18227391 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1294303766540260, 1183557465955093, 882271357233093, + 63854569425375, 2213283684565087 +#else + 3960804, 19286629, 39082773, 17636380, 47704005, 13146867, + 15567327, 951507, 63848543, 32980496 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 339050984211414, 601386726509773, 413735232134068, + 966191255137228, 1839475899458159 +#else + 24740822, 5052253, 37014733, 8961360, 25877428, 6165135, + 42740684, 14397371, 59728495, 27410326 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 235605972169408, 2174055643032978, 1538335001838863, + 1281866796917192, 1815940222628465 +#else + 38220480, 3510802, 39005586, 32395953, 55870735, 22922977, + 51667400, 19101303, 65483377, 27059617 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1632352921721536, 1833328609514701, 2092779091951987, + 1923956201873226, 2210068022482919 +#else + 793280, 24323954, 8836301, 27318725, 39747955, 31184838, + 33152842, 28669181, 57202663, 32932579 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 35271216625062, 1712350667021807, 983664255668860, + 98571260373038, 1232645608559836 +#else + 5666214, 525582, 20782575, 25516013, 42570364, 14657739, + 16099374, 1468826, 60937436, 18367850 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1998172393429622, 1798947921427073, 784387737563581, + 1589352214827263, 1589861734168180 +#else + 62249590, 29775088, 64191105, 26806412, 7778749, 11688288, + 36704511, 23683193, 65549940, 23690785 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1733739258725305, 31715717059538, 201969945218860, + 992093044556990, 1194308773174556 +#else + 10896313, 25834728, 824274, 472601, 47648556, 3009586, 25248958, + 14783338, 36527388, 17796587 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 846415389605137, 746163495539180, 829658752826080, + 592067705956946, 957242537821393 +#else + 10566929, 12612572, 35164652, 11118702, 54475488, 12362878, + 21752402, 8822496, 24003793, 14264025 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1758148849754419, 619249044817679, 168089007997045, + 1371497636330523, 1867101418880350 +#else + 27713843, 26198459, 56100623, 9227529, 27050101, 2504721, + 23886875, 20436907, 13958494, 27821979 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 326633984209635, 261759506071016, 1700682323676193, + 1577907266349064, 1217647663383016 +#else + 43627235, 4867225, 39861736, 3900520, 29838369, 25342141, + 35219464, 23512650, 7340520, 18144364 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1714182387328607, 1477856482074168, 574895689942184, + 2159118410227270, 1555532449716575 +#else + 4646495, 25543308, 44342840, 22021777, 23184552, 8566613, + 31366726, 32173371, 52042079, 23179239 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 853828206885131, 998498946036955, 1835887550391235, + 207627336608048, 258363815956050 +#else + 49838347, 12723031, 50115803, 14878793, 21619651, 27356856, + 27584816, 3093888, 58265170, 3849920 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 141141474651677, 1236728744905256, 643101419899887, + 1646615130509173, 1208239602291765 +#else + 58043933, 2103171, 25561640, 18428694, 61869039, 9582957, + 32477045, 24536477, 5002293, 18004173 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1501663228068911, 1354879465566912, 1444432675498247, + 897812463852601, 855062598754348 +#else + 55051311, 22376525, 21115584, 20189277, 8808711, 21523724, + 16489529, 13378448, 41263148, 12741425 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 714380763546606, 1032824444965790, 1774073483745338, + 1063840874947367, 1738680636537158 +#else + 61162478, 10645102, 36197278, 15390283, 63821882, 26435754, + 24306471, 15852464, 28834118, 25908360 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1640635546696252, 633168953192112, 2212651044092396, + 30590958583852, 368515260889378 +#else + 49773116, 24447374, 42577584, 9434952, 58636780, 32971069, + 54018092, 455840, 20461858, 5491305 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1171650314802029, 1567085444565577, 1453660792008405, + 757914533009261, 1619511342778196 +#else + 13669229, 17458950, 54626889, 23351392, 52539093, 21661233, + 42112877, 11293806, 38520660, 24132599 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 420958967093237, 971103481109486, 2169549185607107, + 1301191633558497, 1661514101014240 +#else + 28497909, 6272777, 34085870, 14470569, 8906179, 32328802, + 18504673, 19389266, 29867744, 24758489 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 907123651818302, 1332556122804146, 1824055253424487, + 1367614217442959, 1982558335973172 +#else + 50901822, 13517195, 39309234, 19856633, 24009063, 27180541, + 60741263, 20379039, 22853428, 29542421 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1121533090144639, 1021251337022187, 110469995947421, + 1511059774758394, 2110035908131662 +#else + 24191359, 16712145, 53177067, 15217830, 14542237, 1646131, + 18603514, 22516545, 12876622, 31441985 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 303213233384524, 2061932261128138, 352862124777736, + 40828818670255, 249879468482660 +#else + 17902668, 4518229, 66697162, 30725184, 26878216, 5258055, + 54248111, 608396, 16031844, 3723494 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 856559257852200, 508517664949010, 1378193767894916, + 1723459126947129, 1962275756614521 +#else + 38476072, 12763727, 46662418, 7577503, 33001348, 20536687, + 17558841, 25681542, 23896953, 29240187 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1445691340537320, 40614383122127, 402104303144865, + 485134269878232, 1659439323587426 +#else + 47103464, 21542479, 31520463, 605201, 2543521, 5991821, + 64163800, 7229063, 57189218, 24727572 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 20057458979482, 1183363722525800, 2140003847237215, + 2053873950687614, 2112017736174909 +#else + 28816026, 298879, 38943848, 17633493, 19000927, 31888542, + 54428030, 30605106, 49057085, 31471516 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2228654250927986, 1483591363415267, 1368661293910956, + 1076511285177291, 526650682059608 +#else + 16000882, 33209536, 3493091, 22107234, 37604268, 20394642, + 12577739, 16041268, 47393624, 7847706 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 709481497028540, 531682216165724, 316963769431931, + 1814315888453765, 258560242424104 +#else + 10151868, 10572098, 27312476, 7922682, 14825339, 4723128, + 34252933, 27035413, 57088296, 3852847 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1053447823660455, 1955135194248683, 1010900954918985, + 1182614026976701, 1240051576966610 +#else + 55678375, 15697595, 45987307, 29133784, 5386313, 15063598, + 16514493, 17622322, 29330898, 18478208 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1957943897155497, 1788667368028035, 137692910029106, + 1039519607062, 826404763313028 +#else + 41609129, 29175637, 51885955, 26653220, 16615730, 2051784, + 3303702, 15490, 39560068, 12314390 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1848942433095597, 1582009882530495, 1849292741020143, + 1068498323302788, 2001402229799484 +#else + 15683501, 27551389, 18109119, 23573784, 15337967, 27556609, + 50391428, 15921865, 16103996, 29823217 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1528282417624269, 2142492439828191, 2179662545816034, + 362568973150328, 1591374675250271 +#else + 43939021, 22773182, 13588191, 31925625, 63310306, 32479502, + 47835256, 5402698, 37293151, 23713330 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 160026679434388, 232341189218716, 2149181472355545, + 598041771119831, 183859001910173 +#else + 23190676, 2384583, 34394524, 3462153, 37205209, 32025299, + 55842007, 8911516, 41903005, 2739712 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2013278155187349, 662660471354454, 793981225706267, + 411706605985744, 804490933124791 +#else + 21374101, 30000182, 33584214, 9874410, 15377179, 11831242, + 33578960, 6134906, 4931255, 11987849 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2051892037280204, 488391251096321, 2230187337030708, + 930221970662692, 679002758255210 +#else + 67101132, 30575573, 50885377, 7277596, 105524, 33232381, + 35628324, 13861387, 37032554, 10117929 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1530723630438670, 875873929577927, 341560134269988, + 449903119530753, 1055551308214179 +#else + 37607694, 22809559, 40945095, 13051538, 41483300, 5089642, + 60783361, 6704078, 12890019, 15728940 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1461835919309432, 1955256480136428, 180866187813063, + 1551979252664528, 557743861963950 +#else + 45136504, 21783052, 66157804, 29135591, 14704839, 2695116, + 903376, 23126293, 12885166, 8311031 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 359179641731115, 1324915145732949, 902828372691474, + 294254275669987, 1887036027752957 +#else + 49592363, 5352193, 10384213, 19742774, 7506450, 13453191, + 26423267, 4384730, 1888765, 28119028 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2043271609454323, 2038225437857464, 1317528426475850, + 1398989128982787, 2027639881006861 +#else + 41291507, 30447119, 53614264, 30371925, 30896458, 19632703, + 34857219, 20846562, 47644429, 30214188 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2072902725256516, 312132452743412, 309930885642209, + 996244312618453, 1590501300352303 +#else + 43500868, 30888657, 66582772, 4651135, 5765089, 4618330, + 6092245, 14845197, 17151279, 23700316 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1397254305160710, 695734355138021, 2233992044438756, + 1776180593969996, 1085588199351115 +#else + 42278406, 20820711, 51942885, 10367249, 37577956, 33289075, + 22825804, 26467153, 50242379, 16176524 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 440567051331029, 254894786356681, 493869224930222, + 1556322069683366, 1567456540319218 +#else + 43525589, 6564960, 20063689, 3798228, 62368686, 7359224, + 2006182, 23191006, 38362610, 23356922 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1950722461391320, 1907845598854797, 1822757481635527, + 2121567704750244, 73811931471221 +#else + 56482264, 29068029, 53788301, 28429114, 3432135, 27161203, + 23632036, 31613822, 32808309, 1099883 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 387139307395758, 2058036430315676, 1220915649965325, + 1794832055328951, 1230009312169328 +#else + 15030958, 5768825, 39657628, 30667132, 60681485, 18193060, + 51830967, 26745081, 2051440, 18328567 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1765973779329517, 659344059446977, 19821901606666, + 1301928341311214, 1116266004075885 +#else + 63746541, 26315059, 7517889, 9824992, 23555850, 295369, 5148398, + 19400244, 44422509, 16633659 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1127572801181483, 1224743760571696, 1276219889847274, + 1529738721702581, 1589819666871853 +#else + 4577067, 16802144, 13249840, 18250104, 19958762, 19017158, + 18559669, 22794883, 8402477, 23690159 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2181229378964934, 2190885205260020, 1511536077659137, + 1246504208580490, 668883326494241 +#else + 38702534, 32502850, 40318708, 32646733, 49896449, 22523642, + 9453450, 18574360, 17983009, 9967138 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 437866655573314, 669026411194768, 81896997980338, + 523874406393178, 245052060935236 +#else + 41346370, 6524721, 26585488, 9969270, 24709298, 1220360, + 65430874, 7806336, 17507396, 3651560 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1975438052228868, 1071801519999806, 594652299224319, + 1877697652668809, 1489635366987285 +#else + 56688388, 29436320, 14584638, 15971087, 51340543, 8861009, + 26556809, 27979875, 48555541, 22197296 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 958592545673770, 233048016518599, 851568750216589, + 567703851596087, 1740300006094761 +#else + 2839082, 14284142, 4029895, 3472686, 14402957, 12689363, + 40466743, 8459446, 61503401, 25932490 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2014540178270324, 192672779514432, 213877182641530, + 2194819933853411, 1716422829364835 +#else + 62269556, 30018987, 9744960, 2871048, 25113978, 3187018, + 41998051, 32705365, 17258083, 25576693 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1540769606609725, 2148289943846077, 1597804156127445, + 1230603716683868, 815423458809453 +#else + 18164541, 22959256, 49953981, 32012014, 19237077, 23809137, + 23357532, 18337424, 26908269, 12150756 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1738560251245018, 1779576754536888, 1783765347671392, + 1880170990446751, 1088225159617541 +#else + 36843994, 25906566, 5112248, 26517760, 65609056, 26580174, + 43167, 28016731, 34806789, 16215818 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 659303913929492, 1956447718227573, 1830568515922666, + 841069049744408, 1669607124206368 +#else + 60209940, 9824393, 54804085, 29153342, 35711722, 27277596, + 32574488, 12532905, 59605792, 24879084 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1143465490433355, 1532194726196059, 1093276745494697, + 481041706116088, 2121405433561163 +#else + 39765323, 17038963, 39957339, 22831480, 946345, 16291093, + 254968, 7168080, 21676107, 31611404 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1686424298744462, 1451806974487153, 266296068846582, + 1834686947542675, 1720762336132256 +#else + 21260942, 25129680, 50276977, 21633609, 43430902, 3968120, + 63456915, 27338965, 63552672, 25641356 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 889217026388959, 1043290623284660, 856125087551909, + 1669272323124636, 1603340330827879 +#else + 16544735, 13250366, 50304436, 15546241, 62525861, 12757257, + 64646556, 24874095, 48201831, 23891632 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1206396181488998, 333158148435054, 1402633492821422, + 1120091191722026, 1945474114550509 +#else + 64693606, 17976703, 18312302, 4964443, 51836334, 20900867, + 26820650, 16690659, 25459437, 28989823 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 766720088232571, 1512222781191002, 1189719893490790, + 2091302129467914, 2141418006894941 +#else + 41964155, 11425019, 28423002, 22533875, 60963942, 17728207, + 9142794, 31162830, 60676445, 31909614 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 419663647306612, 1998875112167987, 1426599870253707, + 1154928355379510, 486538532138187 +#else + 44004212, 6253475, 16964147, 29785560, 41994891, 21257994, + 39651638, 17209773, 6335691, 7249989 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 938160078005954, 1421776319053174, 1941643234741774, + 180002183320818, 1414380336750546 +#else + 36775618, 13979674, 7503222, 21186118, 55152142, 28932738, + 36836594, 2682241, 25993170, 21075909 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 398001940109652, 1577721237663248, 1012748649830402, + 1540516006905144, 1011684812884559 +#else + 4364628, 5930691, 32304656, 23509878, 59054082, 15091130, + 22857016, 22955477, 31820367, 15075278 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1653276489969630, 6081825167624, 1921777941170836, + 1604139841794531, 861211053640641 +#else + 31879134, 24635739, 17258760, 90626, 59067028, 28636722, + 24162787, 23903546, 49138625, 12833044 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 996661541407379, 1455877387952927, 744312806857277, + 139213896196746, 1000282908547789 +#else + 19073683, 14851414, 42705695, 21694263, 7625277, 11091125, + 47489674, 2074448, 57694925, 14905376 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1450817495603008, 1476865707053229, 1030490562252053, + 620966950353376, 1744760161539058 +#else + 24483648, 21618865, 64589997, 22007013, 65555733, 15355505, + 41826784, 9253128, 27628530, 25998952 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 559728410002599, 37056661641185, 2038622963352006, + 1637244893271723, 1026565352238948 +#else + 17597607, 8340603, 19355617, 552187, 26198470, 30377849, + 4593323, 24396850, 52997988, 15297015 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 962165956135846, 1116599660248791, 182090178006815, + 1455605467021751, 196053588803284 +#else + 510886, 14337390, 35323607, 16638631, 6328095, 2713355, + 46891447, 21690211, 8683220, 2921426 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 796863823080135, 1897365583584155, 420466939481601, + 2165972651724672, 932177357788289 +#else + 18606791, 11874196, 27155355, 28272950, 43077121, 6265445, + 41930624, 32275507, 4674689, 13890525 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 877047233620632, 1375632631944375, 643773611882121, + 660022738847877, 19353932331831 +#else + 13609624, 13069022, 39736503, 20498523, 24360585, 9592974, + 14977157, 9835105, 4389687, 288396 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2216943882299338, 394841323190322, 2222656898319671, + 558186553950529, 1077236877025190 +#else + 9922506, 33035038, 13613106, 5883594, 48350519, 33120168, + 54804801, 8317627, 23388070, 16052080 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 801118384953213, 1914330175515892, 574541023311511, + 1471123787903705, 1526158900256288 +#else + 12719997, 11937594, 35138804, 28525742, 26900119, 8561328, + 46953177, 21921452, 52354592, 22741539 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 949617889087234, 2207116611267331, 912920039141287, + 501158539198789, 62362560771472 +#else + 15961858, 14150409, 26716931, 32888600, 44314535, 13603568, + 11829573, 7467844, 38286736, 929274 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1474518386765335, 1760793622169197, 1157399790472736, + 1622864308058898, 165428294422792 +#else + 11038231, 21972036, 39798381, 26237869, 56610336, 17246600, + 43629330, 24182562, 45715720, 2465073 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1961673048027128, 102619413083113, 1051982726768458, + 1603657989805485, 1941613251499678 +#else + 20017144, 29231206, 27915241, 1529148, 12396362, 15675764, + 13817261, 23896366, 2463390, 28932292 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1401939116319266, 335306339903072, 72046196085786, + 862423201496006, 850518754531384 +#else + 50749986, 20890520, 55043680, 4996453, 65852442, 1073571, + 9583558, 12851107, 4003896, 12673717 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1234706593321979, 1083343891215917, 898273974314935, + 1640859118399498, 157578398571149 +#else + 65377275, 18398561, 63845933, 16143081, 19294135, 13385325, + 14741514, 24450706, 7903885, 2348101 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1143483057726416, 1992614991758919, 674268662140796, + 1773370048077526, 674318359920189 +#else + 24536016, 17039225, 12715591, 29692277, 1511292, 10047386, + 63266518, 26425272, 38731325, 10048126 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1835401379538542, 173900035308392, 818247630716732, + 1762100412152786, 1021506399448291 +#else + 54486638, 27349611, 30718824, 2591312, 56491836, 12192839, + 18873298, 26257342, 34811107, 15221631 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1506632088156630, 2127481795522179, 513812919490255, + 140643715928370, 442476620300318 +#else + 40630742, 22450567, 11546243, 31701949, 9180879, 7656409, + 45764914, 2095754, 29769758, 6593415 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2056683376856736, 219094741662735, 2193541883188309, + 1841182310235800, 556477468664293 +#else + 35114656, 30646970, 4176911, 3264766, 12538965, 32686321, + 26312344, 27435754, 30958053, 8292160 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1315019427910827, 1049075855992603, 2066573052986543, + 266904467185534, 2040482348591520 +#else + 31429803, 19595316, 29173531, 15632448, 12174511, 30794338, + 32808830, 3977186, 26143136, 30405556 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 94096246544434, 922482381166992, 24517828745563, + 2139430508542503, 2097139044231004 +#else + 22648882, 1402143, 44308880, 13746058, 7936347, 365344, + 58440231, 31879998, 63350620, 31249806 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 537697207950515, 1399352016347350, 1563663552106345, + 2148749520888918, 549922092988516 +#else + 51616947, 8012312, 64594134, 20851969, 43143017, 23300402, + 65496150, 32018862, 50444388, 8194477 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1747985413252434, 680511052635695, 1809559829982725, + 594274250930054, 201673170745982 +#else + 27338066, 26047012, 59694639, 10140404, 48082437, 26964542, + 27277190, 8855376, 28572286, 3005164 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 323583936109569, 1973572998577657, 1192219029966558, + 79354804385273, 1374043025560347 +#else + 26287105, 4821776, 25476601, 29408529, 63344350, 17765447, + 49100281, 1182478, 41014043, 20474836 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 213277331329947, 416202017849623, 1950535221091783, + 1313441578103244, 2171386783823658 +#else + 59937691, 3178079, 23970071, 6201893, 49913287, 29065239, + 45232588, 19571804, 32208682, 32356184 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 189088804229831, 993969372859110, 895870121536987, + 1547301535298256, 1477373024911350 +#else + 50451143, 2817642, 56822502, 14811297, 6024667, 13349505, + 39793360, 23056589, 39436278, 22014573 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1620578418245010, 541035331188469, 2235785724453865, + 2154865809088198, 1974627268751826 +#else + 15941010, 24148500, 45741813, 8062054, 31876073, 33315803, + 51830470, 32110002, 15397330, 29424239 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1346805451740245, 1350981335690626, 942744349501813, + 2155094562545502, 1012483751693409 +#else + 8934485, 20068965, 43822466, 20131190, 34662773, 14047985, + 31170398, 32113411, 39603297, 15087183 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2107080134091762, 1132567062788208, 1824935377687210, + 769194804343737, 1857941799971888 +#else + 48751602, 31397940, 24524912, 16876564, 15520426, 27193656, + 51606457, 11461895, 16788528, 27685490 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1074666112436467, 249279386739593, 1174337926625354, + 1559013532006480, 1472287775519121 +#else + 65161459, 16013772, 21750665, 3714552, 49707082, 17498998, + 63338576, 23231111, 31322513, 21938797 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1872620123779532, 1892932666768992, 1921559078394978, + 1270573311796160, 1438913646755037 +#else + 21426636, 27904214, 53460576, 28206894, 38296674, 28633461, + 48833472, 18933017, 13040861, 21441484 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 837390187648199, 1012253300223599, 989780015893987, + 1351393287739814, 328627746545550 +#else + 11293895, 12478086, 39972463, 15083749, 37801443, 14748871, + 14555558, 20137329, 1613710, 4896935 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1028328827183114, 1711043289969857, 1350832470374933, + 1923164689604327, 1495656368846911 +#else + 41213962, 15323293, 58619073, 25496531, 25967125, 20128972, + 2825959, 28657387, 43137087, 22287016 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1900828492104143, 430212361082163, 687437570852799, + 832514536673512, 1685641495940794 +#else + 51184079, 28324551, 49665331, 6410663, 3622847, 10243618, + 20615400, 12405433, 43355834, 25118015 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 842632847936398, 605670026766216, 290836444839585, + 163210774892356, 2213815011799645 +#else + 60017550, 12556207, 46917512, 9025186, 50036385, 4333800, + 4378436, 2432030, 23097949, 32988414 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1176336383453996, 1725477294339771, 12700622672454, + 678015708818208, 162724078519879 +#else + 4565804, 17528778, 20084411, 25711615, 1724998, 189254, + 24767264, 10103221, 48596551, 2424777 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1448049969043497, 1789411762943521, 385587766217753, + 90201620913498, 832999441066823 +#else + 366633, 21577626, 8173089, 26664313, 30788633, 5745705, + 59940186, 1344108, 63466311, 12412658 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 516086333293313, 2240508292484616, 1351669528166508, + 1223255565316488, 750235824427138 +#else + 43107073, 7690285, 14929416, 33386175, 34898028, 20141445, + 24162696, 18227928, 63967362, 11179384 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1263624896582495, 1102602401673328, 526302183714372, + 2152015839128799, 1483839308490010 +#else + 18289503, 18829478, 8056944, 16430056, 45379140, 7842513, + 61107423, 32067534, 48424218, 22110928 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 442991718646863, 1599275157036458, 1925389027579192, + 899514691371390, 350263251085160 +#else + 476239, 6601091, 60956074, 23831056, 17503544, 28690532, + 27672958, 13403813, 11052904, 5219329 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1689713572022143, 593854559254373, 978095044791970, + 1985127338729499, 1676069120347625 +#else + 20678527, 25178694, 34436965, 8849122, 62099106, 14574751, + 31186971, 29580702, 9014761, 24975376 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1557207018622683, 340631692799603, 1477725909476187, + 614735951619419, 2033237123746766 +#else + 53464795, 23204192, 51146355, 5075807, 65594203, 22019831, + 34006363, 9160279, 8473550, 30297594 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 968764929340557, 1225534776710944, 662967304013036, + 1155521416178595, 791142883466590 +#else + 24900749, 14435722, 17209120, 18261891, 44516588, 9878982, + 59419555, 17218610, 42540382, 11788947 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1487081286167458, 993039441814934, 1792378982844640, + 698652444999874, 2153908693179754 +#else + 63990690, 22159237, 53306774, 14797440, 9652448, 26708528, + 47071426, 10410732, 42540394, 32095740 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1123181311102823, 685575944875442, 507605465509927, + 1412590462117473, 568017325228626 +#else + 51449703, 16736705, 44641714, 10215877, 58011687, 7563910, + 11871841, 21049238, 48595538, 8464117 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 560258797465417, 2193971151466401, 1824086900849026, + 579056363542056, 1690063960036441 +#else + 43708233, 8348506, 52522913, 32692717, 63158658, 27181012, + 14325288, 8628612, 33313881, 25183915 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1918407319222416, 353767553059963, 1930426334528099, + 1564816146005724, 1861342381708096 +#else + 46921872, 28586496, 22367355, 5271547, 66011747, 28765593, + 42303196, 23317577, 58168128, 27736162 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2131325168777276, 1176636658428908, 1756922641512981, + 1390243617176012, 1966325177038383 +#else + 60160060, 31759219, 34483180, 17533252, 32635413, 26180187, + 15989196, 20716244, 28358191, 29300528 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2063958120364491, 2140267332393533, 699896251574968, + 273268351312140, 375580724713232 +#else + 43547083, 30755372, 34757181, 31892468, 57961144, 10429266, + 50471180, 4072015, 61757200, 5596588 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2024297515263178, 416959329722687, 1079014235017302, + 171612225573183, 1031677520051053 +#else + 38872266, 30164383, 12312895, 6213178, 3117142, 16078565, + 29266239, 2557221, 1768301, 15373193 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2033900009388450, 1744902869870788, 2190580087917640, + 1949474984254121, 231049754293748 +#else + 59865506, 30307471, 62515396, 26001078, 66980936, 32642186, + 66017961, 29049440, 42448372, 3442909 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 343868674606581, 550155864008088, 1450580864229630, + 481603765195050, 896972360018042 +#else + 36898293, 5124042, 14181784, 8197961, 18964734, 21615339, + 22597930, 7176455, 48523386, 13365929 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2151139328380127, 314745882084928, 59756825775204, + 1676664391494651, 2048348075599360 +#else + 59231455, 32054473, 8324672, 4690079, 6261860, 890446, 24538107, + 24984246, 57419264, 30522764 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1528930066340597, 1605003907059576, 1055061081337675, + 1458319101947665, 1234195845213142 +#else + 25008885, 22782833, 62803832, 23916421, 16265035, 15721635, + 683793, 21730648, 15723478, 18390951 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 830430507734812, 1780282976102377, 1425386760709037, + 362399353095425, 2168861579799910 +#else + 57448220, 12374378, 40101865, 26528283, 59384749, 21239917, + 11879681, 5400171, 519526, 32318556 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1155762232730333, 980662895504006, 2053766700883521, + 490966214077606, 510405877041357 +#else + 22258397, 17222199, 59239046, 14613015, 44588609, 30603508, + 46754982, 7315966, 16648397, 7605640 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1683750316716132, 652278688286128, 1221798761193539, + 1897360681476669, 319658166027343 +#else + 59027556, 25089834, 58885552, 9719709, 19259459, 18206220, + 23994941, 28272877, 57640015, 4763277 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 618808732869972, 72755186759744, 2060379135624181, + 1730731526741822, 48862757828238 +#else + 45409620, 9220968, 51378240, 1084136, 41632757, 30702041, + 31088446, 25789909, 55752334, 728111 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1463171970593505, 1143040711767452, 614590986558883, + 1409210575145591, 1882816996436803 +#else + 26047201, 21802961, 60208540, 17032633, 24092067, 9158119, + 62835319, 20998873, 37743427, 28056159 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2230133264691131, 563950955091024, 2042915975426398, + 827314356293472, 672028980152815 +#else + 17510331, 33231575, 5854288, 8403524, 17133918, 30441820, + 38997856, 12327944, 10750447, 10014012 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 264204366029760, 1654686424479449, 2185050199932931, + 2207056159091748, 506015669043634 +#else + 56796096, 3936951, 9156313, 24656749, 16498691, 32559785, + 39627812, 32887699, 3424690, 7540221 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1784446333136569, 1973746527984364, 334856327359575, + 1156769775884610, 1023950124675478 +#else + 30322361, 26590322, 11361004, 29411115, 7433303, 4989748, + 60037442, 17237212, 57864598, 15258045 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2065270940578383, 31477096270353, 306421879113491, + 181958643936686, 1907105536686083 +#else + 13054543, 30774935, 19155473, 469045, 54626067, 4566041, + 5631406, 2711395, 1062915, 28418087 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1496516440779464, 1748485652986458, 872778352227340, + 818358834654919, 97932669284220 +#else + 47868616, 22299832, 37599834, 26054466, 61273100, 13005410, + 61042375, 12194496, 32960380, 1459310 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 471636015770351, 672455402793577, 1804995246884103, + 1842309243470804, 1501862504981682 +#else + 19852015, 7027924, 23669353, 10020366, 8586503, 26896525, + 394196, 27452547, 18638002, 22379495 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1013216974933691, 538921919682598, 1915776722521558, + 1742822441583877, 1886550687916656 +#else + 31395515, 15098109, 26581030, 8030562, 50580950, 28547297, + 9012485, 25970078, 60465776, 28111795 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2094270000643336, 303971879192276, 40801275554748, + 649448917027930, 1818544418535447 +#else + 57916680, 31207054, 65111764, 4529533, 25766844, 607986, + 67095642, 9677542, 34813975, 27098423 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2241737709499165, 549397817447461, 838180519319392, + 1725686958520781, 1705639080897747 +#else + 64664349, 33404494, 29348901, 8186665, 1873760, 12489863, + 36174285, 25714739, 59256019, 25416002 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1216074541925116, 50120933933509, 1565829004133810, + 721728156134580, 349206064666188 +#else + 51872508, 18120922, 7766469, 746860, 26346930, 23332670, + 39775412, 10754587, 57677388, 5203575 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 948617110470858, 346222547451945, 1126511960599975, + 1759386906004538, 493053284802266 +#else + 31834314, 14135496, 66338857, 5159117, 20917671, 16786336, + 59640890, 26216907, 31809242, 7347066 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1454933046815146, 874696014266362, 1467170975468588, + 1432316382418897, 2111710746366763 +#else + 57502122, 21680191, 20414458, 13033986, 13716524, 21862551, + 19797969, 21343177, 15192875, 31466942 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2105387117364450, 1996463405126433, 1303008614294500, + 851908115948209, 1353742049788635 +#else + 54445282, 31372712, 1168161, 29749623, 26747876, 19416341, + 10609329, 12694420, 33473243, 20172328 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 750300956351719, 1487736556065813, 15158817002104, + 1511998221598392, 971739901354129 +#else + 33184999, 11180355, 15832085, 22169002, 65475192, 225883, + 15089336, 22530529, 60973201, 14480052 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1874648163531693, 2124487685930551, 1810030029384882, + 918400043048335, 586348627300650 +#else + 31308717, 27934434, 31030839, 31657333, 15674546, 26971549, + 5496207, 13685227, 27595050, 8737275 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1235084464747900, 1166111146432082, 1745394857881591, + 1405516473883040, 4463504151617 +#else + 46790012, 18404192, 10933842, 17376410, 8335351, 26008410, + 36100512, 20943827, 26498113, 66511 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1663810156463827, 327797390285791, 1341846161759410, + 1964121122800605, 1747470312055380 +#else + 22644435, 24792703, 50437087, 4884561, 64003250, 19995065, + 30540765, 29267685, 53781076, 26039336 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 660005247548233, 2071860029952887, 1358748199950107, + 911703252219107, 1014379923023831 +#else + 39091017, 9834844, 18617207, 30873120, 63706907, 20246925, + 8205539, 13585437, 49981399, 15115438 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2206641276178231, 1690587809721504, 1600173622825126, + 2156096097634421, 1106822408548216 +#else + 23711543, 32881517, 31206560, 25191721, 6164646, 23844445, + 33572981, 32128335, 8236920, 16492939 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1344788193552206, 1949552134239140, 1735915881729557, + 675891104100469, 1834220014427292 +#else + 43198286, 20038905, 40809380, 29050590, 25005589, 25867162, + 19574901, 10071562, 6708380, 27332008 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1920949492387964, 158885288387530, 70308263664033, + 626038464897817, 1468081726101009 +#else + 2101372, 28624378, 19702730, 2367575, 51681697, 1047674, + 5301017, 9328700, 29955601, 21876122 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 622221042073383, 1210146474039168, 1742246422343683, + 1403839361379025, 417189490895736 +#else + 3096359, 9271816, 45488000, 18032587, 52260867, 25961494, + 41216721, 20918836, 57191288, 6216607 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 22727256592983, 168471543384997, 1324340989803650, + 1839310709638189, 504999476432775 +#else + 34493015, 338662, 41913253, 2510421, 37895298, 19734218, + 24822829, 27407865, 40341383, 7525078 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1313240518756327, 1721896294296942, 52263574587266, + 2065069734239232, 804910473424630 +#else + 44042215, 19568808, 16133486, 25658254, 63719298, 778787, + 66198528, 30771936, 47722230, 11994100 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1337466662091884, 1287645354669772, 2018019646776184, + 652181229374245, 898011753211715 +#else + 21691500, 19929806, 66467532, 19187410, 3285880, 30070836, + 42044197, 9718257, 59631427, 13381417 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1969792547910734, 779969968247557, 2011350094423418, + 1823964252907487, 1058949448296945 +#else + 18445390, 29352196, 14979845, 11622458, 65381754, 29971451, + 23111647, 27179185, 28535281, 15779576 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 207343737062002, 1118176942430253, 758894594548164, + 806764629546266, 1157700123092949 +#else + 30098034, 3089662, 57874477, 16662134, 45801924, 11308410, + 53040410, 12021729, 9955285, 17251076 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1273565321399022, 1638509681964574, 759235866488935, + 666015124346707, 897983460943405 +#else + 9734894, 18977602, 59635230, 24415696, 2060391, 11313496, + 48682835, 9924398, 20194861, 13380996 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1717263794012298, 1059601762860786, 1837819172257618, + 1054130665797229, 680893204263559 +#else + 40730762, 25589224, 44941042, 15789296, 49053522, 27385639, + 65123949, 15707770, 26342023, 10146099 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2237039662793603, 2249022333361206, 2058613546633703, + 149454094845279, 2215176649164582 +#else + 41091971, 33334488, 21339190, 33513044, 19745255, 30675732, + 37471583, 2227039, 21612326, 33008704 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 79472182719605, 1851130257050174, 1825744808933107, + 821667333481068, 781795293511946 +#else + 54031477, 1184227, 23562814, 27583990, 46757619, 27205717, + 25764460, 12243797, 46252298, 11649657 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 755822026485370, 152464789723500, 1178207602290608, + 410307889503239, 156581253571278 +#else + 57077370, 11262625, 27384172, 2271902, 26947504, 17556661, + 39943, 6114064, 33514190, 2333242 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1418185496130297, 484520167728613, 1646737281442950, + 1401487684670265, 1349185550126961 +#else + 45675257, 21132610, 8119781, 7219913, 45278342, 24538297, + 60429113, 20883793, 24350577, 20104431 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1495380034400429, 325049476417173, 46346894893933, + 1553408840354856, 828980101835683 +#else + 62992557, 22282898, 43222677, 4843614, 37020525, 690622, + 35572776, 23147595, 8317859, 12352766 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1280337889310282, 2070832742866672, 1640940617225222, + 2098284908289951, 450929509534434 +#else + 18200138, 19078521, 34021104, 30857812, 43406342, 24451920, + 43556767, 31266881, 20712162, 6719373 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 407703353998781, 126572141483652, 286039827513621, + 1999255076709338, 2030511179441770 +#else + 26656189, 6075253, 59250308, 1886071, 38764821, 4262325, + 11117530, 29791222, 26224234, 30256974 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1254958221100483, 1153235960999843, 942907704968834, + 637105404087392, 1149293270147267 +#else + 49939907, 18700334, 63713187, 17184554, 47154818, 14050419, + 21728352, 9493610, 18620611, 17125804 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 894249020470196, 400291701616810, 406878712230981, + 1599128793487393, 1145868722604026 +#else + 53785524, 13325348, 11432106, 5964811, 18609221, 6062965, + 61839393, 23828875, 36407290, 17074774 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1497955250203334, 110116344653260, 1128535642171976, + 1900106496009660, 129792717460909 +#else + 43248326, 22321272, 26961356, 1640861, 34695752, 16816491, + 12248508, 28313793, 13735341, 1934062 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 452487513298665, 1352120549024569, 1173495883910956, + 1999111705922009, 367328130454226 +#else + 25089769, 6742589, 17081145, 20148166, 21909292, 17486451, + 51972569, 29789085, 45830866, 5473615 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1717539401269642, 1475188995688487, 891921989653942, + 836824441505699, 1885988485608364 +#else + 31883658, 25593331, 1083431, 21982029, 22828470, 13290673, + 59983779, 12469655, 29111212, 28103418 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1241784121422547, 187337051947583, 1118481812236193, + 428747751936362, 30358898927325 +#else + 24244947, 18504025, 40845887, 2791539, 52111265, 16666677, + 24367466, 6388839, 56813277, 452382 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2022432361201842, 1088816090685051, 1977843398539868, + 1854834215890724, 564238862029357 +#else + 41468082, 30136590, 5217915, 16224624, 19987036, 29472163, + 42872612, 27639183, 15766061, 8407814 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 938868489100585, 1100285072929025, 1017806255688848, + 1957262154788833, 152787950560442 +#else + 46701865, 13990230, 15495425, 16395525, 5377168, 15166495, + 58191841, 29165478, 59040954, 2276717 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 867319417678923, 620471962942542, 226032203305716, + 342001443957629, 1761675818237336 +#else + 30157899, 12924066, 49396814, 9245752, 19895028, 3368142, + 43281277, 5096218, 22740376, 26251015 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1295072362439987, 931227904689414, 1355731432641687, + 922235735834035, 892227229410209 +#else + 2041139, 19298082, 7783686, 13876377, 41161879, 20201972, + 24051123, 13742383, 51471265, 13295221 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1680989767906154, 535362787031440, 2136691276706570, + 1942228485381244, 1267350086882274 +#else + 33338218, 25048699, 12532112, 7977527, 9106186, 31839181, + 49388668, 28941459, 62657506, 18884987 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 366018233770527, 432660629755596, 126409707644535, + 1973842949591662, 645627343442376 +#else + 47063583, 5454096, 52762316, 6447145, 28862071, 1883651, + 64639598, 29412551, 7770568, 9620597 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 535509430575217, 546885533737322, 1524675609547799, + 2138095752851703, 1260738089896827 +#else + 23208049, 7979712, 33071466, 8149229, 1758231, 22719437, + 30945527, 31860109, 33606523, 18786461 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1159906385590467, 2198530004321610, 714559485023225, + 81880727882151, 1484020820037082 +#else + 1439939, 17283952, 66028874, 32760649, 4625401, 10647766, + 62065063, 1220117, 30494170, 22113633 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1377485731340769, 2046328105512000, 1802058637158797, + 62146136768173, 1356993908853901 +#else + 62071265, 20526136, 64138304, 30492664, 15640973, 26852766, + 40369837, 926049, 65424525, 20220784 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2013612215646735, 1830770575920375, 536135310219832, + 609272325580394, 270684344495013 +#else + 13908495, 30005160, 30919927, 27280607, 45587000, 7989038, + 9021034, 9078865, 3353509, 4033511 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1237542585982777, 2228682050256790, 1385281931622824, + 593183794882890, 493654978552689 +#else + 37445433, 18440821, 32259990, 33209950, 24295848, 20642309, + 23161162, 8839127, 27485041, 7356032 +#endif + }}, + }, + }, + { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 47341488007760, 1891414891220257, 983894663308928, + 176161768286818, 1126261115179708 +#else + 9661008, 705443, 11980065, 28184278, 65480320, 14661172, + 60762722, 2625014, 28431036, 16782598 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1694030170963455, 502038567066200, 1691160065225467, + 949628319562187, 275110186693066 +#else + 43269631, 25243016, 41163352, 7480957, 49427195, 25200248, + 44562891, 14150564, 15970762, 4099461 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1124515748676336, 1661673816593408, 1499640319059718, + 1584929449166988, 558148594103306 +#else + 29262576, 16756590, 26350592, 24760869, 8529670, 22346382, + 13617292, 23617289, 11465738, 8317062 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1784525599998356, 1619698033617383, 2097300287550715, + 258265458103756, 1905684794832758 +#else + 41615764, 26591503, 32500199, 24135381, 44070139, 31252209, + 14898636, 3848455, 20969334, 28396916 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1288941072872766, 931787902039402, 190731008859042, + 2006859954667190, 1005931482221702 +#else + 46724414, 19206718, 48772458, 13884721, 34069410, 2842113, + 45498038, 29904543, 11177094, 14989547 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1465551264822703, 152905080555927, 680334307368453, + 173227184634745, 666407097159852 +#else + 42612143, 21838415, 16959895, 2278463, 12066309, 10137771, + 13515641, 2581286, 38621356, 9930239 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2111017076203943, 1378760485794347, 1248583954016456, + 1352289194864422, 1895180776543896 +#else + 49357223, 31456605, 16544299, 20545132, 51194056, 18605350, + 18345766, 20150679, 16291480, 28240394 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 171348223915638, 662766099800389, 462338943760497, + 466917763340314, 656911292869115 +#else + 33879670, 2553287, 32678213, 9875984, 8534129, 6889387, + 57432090, 6957616, 4368891, 9788741 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 488623681976577, 866497561541722, 1708105560937768, + 1673781214218839, 1506146329818807 +#else + 16660737, 7281060, 56278106, 12911819, 20108584, 25452756, + 45386327, 24941283, 16250551, 22443329 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 160425464456957, 950394373239689, 430497123340934, + 711676555398832, 320964687779005 +#else + 47343357, 2390525, 50557833, 14161979, 1905286, 6414907, + 4689584, 10604807, 36918461, 4782746 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 988979367990485, 1359729327576302, 1301834257246029, + 294141160829308, 29348272277475 +#else + 65754325, 14736940, 59741422, 20261545, 7710541, 19398842, + 57127292, 4383044, 22546403, 437323 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1434382743317910, 100082049942065, 221102347892623, + 186982837860588, 1305765053501834 +#else + 31665558, 21373968, 50922033, 1491338, 48740239, 3294681, + 27343084, 2786261, 36475274, 19457415 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2205916462268190, 499863829790820, 961960554686616, + 158062762756985, 1841471168298305 +#else + 52641566, 32870716, 33734756, 7448551, 19294360, 14334329, + 47418233, 2355318, 47824193, 27440058 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1191737341426592, 1847042034978363, 1382213545049056, + 1039952395710448, 788812858896859 +#else + 15121312, 17758270, 6377019, 27523071, 56310752, 20596586, + 18952176, 15496498, 37728731, 11754227 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1346965964571152, 1291881610839830, 2142916164336056, + 786821641205979, 1571709146321039 +#else + 64471568, 20071356, 8488726, 19250536, 12728760, 31931939, + 7141595, 11724556, 22761615, 23420291 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 787164375951248, 202869205373189, 1356590421032140, + 1431233331032510, 786341368775957 +#else + 16918416, 11729663, 49025285, 3022986, 36093132, 20214772, + 38367678, 21327038, 32851221, 11717399 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 492448143532951, 304105152670757, 1761767168301056, + 233782684697790, 1981295323106089 +#else + 11166615, 7338049, 60386341, 4531519, 37640192, 26252376, + 31474878, 3483633, 65915689, 29523600 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 665807507761866, 1343384868355425, 895831046139653, + 439338948736892, 1986828765695105 +#else + 66923210, 9921304, 31456609, 20017994, 55095045, 13348922, + 33142652, 6546660, 47123585, 29606055 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 756096210874553, 1721699973539149, 258765301727885, + 1390588532210645, 1212530909934781 +#else + 34648249, 11266711, 55911757, 25655328, 31703693, 3855903, + 58571733, 20721383, 36336829, 18068118 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 852891097972275, 1816988871354562, 1543772755726524, + 1174710635522444, 202129090724628 +#else + 49102387, 12709067, 3991746, 27075244, 45617340, 23004006, + 35973516, 17504552, 10928916, 3011958 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1205281565824323, 22430498399418, 992947814485516, + 1392458699738672, 688441466734558 +#else + 60151107, 17960094, 31696058, 334240, 29576716, 14796075, + 36277808, 20749251, 18008030, 10258577 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1050627428414972, 1955849529137135, 2171162376368357, + 91745868298214, 447733118757826 +#else + 44660220, 15655568, 7018479, 29144429, 36794597, 32352840, + 65255398, 1367119, 25127874, 6671743 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1287181461435438, 622722465530711, 880952150571872, + 741035693459198, 311565274989772 +#else + 29701166, 19180498, 56230743, 9279287, 67091296, 13127209, + 21382910, 11042292, 25838796, 4642684 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1003649078149734, 545233927396469, 1849786171789880, + 1318943684880434, 280345687170552 +#else + 46678630, 14955536, 42982517, 8124618, 61739576, 27563961, + 30468146, 19653792, 18423288, 4177476 +#endif + }}, + }, + }, +}; + +#endif // CONFIG_SMALL + +// Bi[i] = (2*i+1)*B +static const ge_precomp Bi[8] = { + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1288382639258501, 245678601348599, 269427782077623, + 1462984067271730, 137412439391563 +#else + 25967493, 19198397, 29566455, 3660896, 54414519, 4014786, 27544626, + 21800161, 61029707, 2047604 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 62697248952638, 204681361388450, 631292143396476, 338455783676468, + 1213667448819585 +#else + 54563134, 934261, 64385954, 3049989, 66381436, 9406985, 12720692, + 5043384, 19500929, 18085054 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 301289933810280, 1259582250014073, 1422107436869536, + 796239922652654, 1953934009299142 +#else + 58370664, 4489569, 9688441, 18769238, 10184608, 21191052, 29287918, + 11864899, 42594502, 29115885 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1601611775252272, 1720807796594148, 1132070835939856, + 1260455018889551, 2147779492816911 +#else + 15636272, 23865875, 24204772, 25642034, 616976, 16869170, 27787599, + 18782243, 28944399, 32004408 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 316559037616741, 2177824224946892, 1459442586438991, + 1461528397712656, 751590696113597 +#else + 16568933, 4717097, 55552716, 32452109, 15682895, 21747389, 16354576, + 21778470, 7689661, 11199574 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1850748884277385, 1200145853858453, 1068094770532492, + 672251375690438, 1586055907191707 +#else + 30464137, 27578307, 55329429, 17883566, 23220364, 15915852, 7512774, + 10017326, 49359771, 23634074 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 769950342298419, 132954430919746, 844085933195555, 974092374476333, + 726076285546016 +#else + 10861363, 11473154, 27284546, 1981175, 37044515, 12577860, 32867885, + 14515107, 51670560, 10819379 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 425251763115706, 608463272472562, 442562545713235, 837766094556764, + 374555092627893 +#else + 4708026, 6336745, 20377586, 9066809, 55836755, 6594695, 41455196, + 12483687, 54440373, 5581305 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1086255230780037, 274979815921559, 1960002765731872, + 929474102396301, 1190409889297339 +#else + 19563141, 16186464, 37722007, 4097518, 10237984, 29206317, 28542349, + 13850243, 43430843, 17738489 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 665000864555967, 2065379846933859, 370231110385876, 350988370788628, + 1233371373142985 +#else + 5153727, 9909285, 1723747, 30776558, 30523604, 5516873, 19480852, + 5230134, 43156425, 18378665 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2019367628972465, 676711900706637, 110710997811333, + 1108646842542025, 517791959672113 +#else + 36839857, 30090922, 7665485, 10083793, 28475525, 1649722, 20654025, + 16520125, 30598449, 7715701 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 965130719900578, 247011430587952, 526356006571389, 91986625355052, + 2157223321444601 +#else + 28881826, 14381568, 9657904, 3680757, 46927229, 7843315, 35708204, + 1370707, 29794553, 32145132 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1802695059465007, 1664899123557221, 593559490740857, + 2160434469266659, 927570450755031 +#else + 44589871, 26862249, 14201701, 24808930, 43598457, 8844725, 18474211, + 32192982, 54046167, 13821876 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1725674970513508, 1933645953859181, 1542344539275782, + 1767788773573747, 1297447965928905 +#else + 60653668, 25714560, 3374701, 28813570, 40010246, 22982724, 31655027, + 26342105, 18853321, 19333481 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1381809363726107, 1430341051343062, 2061843536018959, + 1551778050872521, 2036394857967624 +#else + 4566811, 20590564, 38133974, 21313742, 59506191, 30723862, 58594505, + 23123294, 2207752, 30344648 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1970894096313054, 528066325833207, 1619374932191227, + 2207306624415883, 1169170329061080 +#else + 41954014, 29368610, 29681143, 7868801, 60254203, 24130566, 54671499, + 32891431, 35997400, 17421995 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 2070390218572616, 1458919061857835, 624171843017421, + 1055332792707765, 433987520732508 +#else + 25576264, 30851218, 7349803, 21739588, 16472781, 9300885, 3844789, + 15725684, 171356, 6466918 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 893653801273833, 1168026499324677, 1242553501121234, + 1306366254304474, 1086752658510815 +#else + 23103977, 13316479, 9739013, 17404951, 817874, 18515490, 8965338, + 19466374, 36393951, 16193876 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 213454002618221, 939771523987438, 1159882208056014, 317388369627517, + 621213314200687 +#else + 33587053, 3180712, 64714734, 14003686, 50205390, 17283591, 17238397, + 4729455, 49034351, 9256799 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1971678598905747, 338026507889165, 762398079972271, 655096486107477, + 42299032696322 +#else + 41926547, 29380300, 32336397, 5036987, 45872047, 11360616, 22616405, + 9761698, 47281666, 630304 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 177130678690680, 1754759263300204, 1864311296286618, + 1180675631479880, 1292726903152791 +#else + 53388152, 2639452, 42871404, 26147950, 9494426, 27780403, 60554312, + 17593437, 64659607, 19263131 +#endif + }}, + }, + { + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1913163449625248, 460779200291993, 2193883288642314, + 1008900146920800, 1721983679009502 +#else + 63957664, 28508356, 9282713, 6866145, 35201802, 32691408, 48168288, + 15033783, 25105118, 25659556 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 1070401523076875, 1272492007800961, 1910153608563310, + 2075579521696771, 1191169788841221 +#else + 42782475, 15950225, 35307649, 18961608, 55446126, 28463506, 1573891, + 30928545, 2198789, 17749813 +#endif + }}, + {{ +#if defined(BORINGSSL_CURVE25519_64BIT) + 692896803108118, 500174642072499, 2068223309439677, + 1162190621851337, 1426986007309901 +#else + 64009494, 10324966, 64867251, 7453182, 61661885, 30818928, 53296841, + 17317989, 34647629, 21263748 +#endif + }}, + }, +}; diff --git a/krb5-1.21.3/src/plugins/preauth/spake/groups.c b/krb5-1.21.3/src/plugins/preauth/spake/groups.c new file mode 100644 index 00000000..a195cc19 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/groups.c @@ -0,0 +1,442 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/spake/groups.c - SPAKE group interfaces */ +/* + * Copyright (C) 2015 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. + */ + +/* + * The SPAKE2 algorithm works as follows: + * + * 1. The parties agree on a group, a base element G, and constant elements M + * and N. In this mechanism, these parameters are determined by the + * registered group number. + * 2. Both parties derive a scalar value w from the initial key. + * 3. The first party (the KDC, in this mechanism) chooses a random secret + * scalar x and sends T=xG+wM. + * 4. The second party (the client, in this mechanism) chooses a random + * secret scalar y and sends S=yG+wN. + * 5. The first party computes K=x(S-wN). + * 6. The second party computes the same value as K=y(T-wM). + * 7. Both parties derive a key from a random oracle whose input incorporates + * the party identities, w, T, S, and K. + * + * We implement the algorithm using a vtable for each group, where the primary + * vtable methods are "keygen" (corresponding to step 3 or 4) and "result" + * (corresponding to step 5 or 6). We use the term "private scalar" to refer + * to x or y, and "public element" to refer to S or T. + */ + +#include "iana.h" +#include "trace.h" +#include "groups.h" + +#define DEFAULT_GROUPS_CLIENT "edwards25519" +#define DEFAULT_GROUPS_KDC "" + +typedef struct groupent_st { + const groupdef *gdef; + groupdata *gdata; +} groupent; + +struct groupstate_st { + krb5_boolean is_kdc; + + /* Permitted and groups, from configuration */ + int32_t *permitted; + size_t npermitted; + + /* Optimistic challenge group, from configuration */ + int32_t challenge_group; + + /* Lazily-initialized list of gdata objects. */ + groupent *data; + size_t ndata; +}; + +extern groupdef builtin_edwards25519; +#ifdef SPAKE_OPENSSL +extern groupdef ossl_P256; +extern groupdef ossl_P384; +extern groupdef ossl_P521; +#endif + +static const groupdef *groupdefs[] = { + &builtin_edwards25519, +#ifdef SPAKE_OPENSSL + &ossl_P256, + &ossl_P384, + &ossl_P521, +#endif + NULL +}; + +/* Find a groupdef structure by group number. Return NULL on failure. */ +static const groupdef * +find_gdef(int32_t group) +{ + size_t i; + + for (i = 0; groupdefs[i] != NULL; i++) { + if (groupdefs[i]->reg->id == group) + return groupdefs[i]; + } + + return NULL; +} + +/* Find a group number by name. Return 0 on failure. */ +static int32_t +find_gnum(const char *name) +{ + size_t i; + + for (i = 0; groupdefs[i] != NULL; i++) { + if (strcasecmp(name, groupdefs[i]->reg->name) == 0) + return groupdefs[i]->reg->id; + } + return 0; +} + +static krb5_boolean +in_grouplist(const int32_t *list, size_t count, int32_t group) +{ + size_t i; + + for (i = 0; i < count; i++) { + if (list[i] == group) + return TRUE; + } + + return FALSE; +} + +/* Retrieve a group data object for group within gstate, lazily initializing it + * if necessary. */ +static krb5_error_code +get_gdata(krb5_context context, groupstate *gstate, const groupdef *gdef, + groupdata **gdata_out) +{ + krb5_error_code ret; + groupent *ent, *newptr; + + *gdata_out = NULL; + + /* Look for an existing entry. */ + for (ent = gstate->data; ent < gstate->data + gstate->ndata; ent++) { + if (ent->gdef == gdef) { + *gdata_out = ent->gdata; + return 0; + } + } + + /* Make a new entry. */ + newptr = realloc(gstate->data, (gstate->ndata + 1) * sizeof(groupent)); + if (newptr == NULL) + return ENOMEM; + gstate->data = newptr; + ent = &gstate->data[gstate->ndata]; + ent->gdef = gdef; + ent->gdata = NULL; + if (gdef->init != NULL) { + ret = gdef->init(context, gdef, &ent->gdata); + if (ret) + return ret; + } + gstate->ndata++; + *gdata_out = ent->gdata; + return 0; +} + +/* Destructively parse str into a list of group numbers. */ +static krb5_error_code +parse_groups(krb5_context context, char *str, int32_t **list_out, + size_t *count_out) +{ + const char *const delim = " \t\r\n,"; + char *token, *save = NULL; + int32_t group, *newptr, *list = NULL; + size_t count = 0; + + *list_out = NULL; + *count_out = 0; + + /* Walk through the words in profstr. */ + for (token = strtok_r(str, delim, &save); token != NULL; + token = strtok_r(NULL, delim, &save)) { + group = find_gnum(token); + if (!group) { + TRACE_SPAKE_UNKNOWN_GROUP(context, token); + continue; + } + if (in_grouplist(list, count, group)) + continue; + newptr = realloc(list, (count + 1) * sizeof(*list)); + if (newptr == NULL) { + free(list); + return ENOMEM; + } + list = newptr; + list[count++] = group; + } + + *list_out = list; + *count_out = count; + return 0; +} + +krb5_error_code +group_init_state(krb5_context context, krb5_boolean is_kdc, + groupstate **gstate_out) +{ + krb5_error_code ret; + groupstate *gstate; + const char *defgroups; + char *profstr1 = NULL, *profstr2 = NULL; + int32_t *permitted = NULL, challenge_group = 0; + size_t npermitted; + + *gstate_out = NULL; + + defgroups = is_kdc ? DEFAULT_GROUPS_KDC : DEFAULT_GROUPS_CLIENT; + ret = profile_get_string(context->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_SPAKE_PREAUTH_GROUPS, NULL, defgroups, + &profstr1); + if (ret) + goto cleanup; + ret = parse_groups(context, profstr1, &permitted, &npermitted); + if (ret) + goto cleanup; + if (npermitted == 0) { + ret = KRB5_PLUGIN_OP_NOTSUPP; + k5_setmsg(context, ret, _("No SPAKE preauth groups configured")); + goto cleanup; + } + + if (is_kdc) { + /* + * Check for a configured optimistic challenge group. If one is set, + * the KDC will send a challenge in the PREAUTH_REQUIRED method data, + * before receiving the list of supported groups. + */ + ret = profile_get_string(context->profile, KRB5_CONF_KDCDEFAULTS, + KRB5_CONF_SPAKE_PREAUTH_KDC_CHALLENGE, NULL, + NULL, &profstr2); + if (ret) + goto cleanup; + if (profstr2 != NULL) { + challenge_group = find_gnum(profstr2); + if (!in_grouplist(permitted, npermitted, challenge_group)) { + ret = KRB5_PLUGIN_OP_NOTSUPP; + k5_setmsg(context, ret, + _("SPAKE challenge group not a permitted group: %s"), + profstr2); + goto cleanup; + } + } + } + + gstate = k5alloc(sizeof(*gstate), &ret); + if (gstate == NULL) + goto cleanup; + gstate->is_kdc = is_kdc; + gstate->permitted = permitted; + gstate->npermitted = npermitted; + gstate->challenge_group = challenge_group; + permitted = NULL; + gstate->data = NULL; + gstate->ndata = 0; + *gstate_out = gstate; + +cleanup: + profile_release_string(profstr1); + profile_release_string(profstr2); + free(permitted); + return ret; +} + + +void +group_free_state(groupstate *gstate) +{ + groupent *ent; + + for (ent = gstate->data; ent < gstate->data + gstate->ndata; ent++) { + if (ent->gdata != NULL && ent->gdef->fini != NULL) + ent->gdef->fini(ent->gdata); + } + + free(gstate->permitted); + free(gstate->data); + free(gstate); +} + +krb5_boolean +group_is_permitted(groupstate *gstate, int32_t group) +{ + return in_grouplist(gstate->permitted, gstate->npermitted, group); +} + +void +group_get_permitted(groupstate *gstate, int32_t **list_out, int32_t *count_out) +{ + *list_out = gstate->permitted; + *count_out = gstate->npermitted; +} + +krb5_int32 +group_optimistic_challenge(groupstate *gstate) +{ + assert(gstate->is_kdc); + return gstate->challenge_group; +} + +krb5_error_code +group_mult_len(int32_t group, size_t *len_out) +{ + const groupdef *gdef; + + *len_out = 0; + gdef = find_gdef(group); + if (gdef == NULL) + return EINVAL; + *len_out = gdef->reg->mult_len; + return 0; +} + +krb5_error_code +group_keygen(krb5_context context, groupstate *gstate, int32_t group, + const krb5_data *wbytes, krb5_data *priv_out, krb5_data *pub_out) +{ + krb5_error_code ret; + const groupdef *gdef; + groupdata *gdata; + uint8_t *priv = NULL, *pub = NULL; + + *priv_out = empty_data(); + *pub_out = empty_data(); + gdef = find_gdef(group); + if (gdef == NULL || wbytes->length != gdef->reg->mult_len) + return EINVAL; + ret = get_gdata(context, gstate, gdef, &gdata); + if (ret) + return ret; + + priv = k5alloc(gdef->reg->mult_len, &ret); + if (priv == NULL) + goto cleanup; + pub = k5alloc(gdef->reg->elem_len, &ret); + if (pub == NULL) + goto cleanup; + + ret = gdef->keygen(context, gdata, (uint8_t *)wbytes->data, gstate->is_kdc, + priv, pub); + if (ret) + goto cleanup; + + *priv_out = make_data(priv, gdef->reg->mult_len); + *pub_out = make_data(pub, gdef->reg->elem_len); + priv = pub = NULL; + TRACE_SPAKE_KEYGEN(context, pub_out); + +cleanup: + zapfree(priv, gdef->reg->mult_len); + free(pub); + return ret; +} + +krb5_error_code +group_result(krb5_context context, groupstate *gstate, int32_t group, + const krb5_data *wbytes, const krb5_data *ourpriv, + const krb5_data *theirpub, krb5_data *spakeresult_out) +{ + krb5_error_code ret; + const groupdef *gdef; + groupdata *gdata; + uint8_t *spakeresult = NULL; + + *spakeresult_out = empty_data(); + gdef = find_gdef(group); + if (gdef == NULL || wbytes->length != gdef->reg->mult_len) + return EINVAL; + if (ourpriv->length != gdef->reg->mult_len || + theirpub->length != gdef->reg->elem_len) + return EINVAL; + ret = get_gdata(context, gstate, gdef, &gdata); + if (ret) + return ret; + + spakeresult = k5alloc(gdef->reg->elem_len, &ret); + if (spakeresult == NULL) + goto cleanup; + + /* Invert is_kdc here to use the other party's constant. */ + ret = gdef->result(context, gdata, (uint8_t *)wbytes->data, + (uint8_t *)ourpriv->data, (uint8_t *)theirpub->data, + !gstate->is_kdc, spakeresult); + if (ret) + goto cleanup; + + *spakeresult_out = make_data(spakeresult, gdef->reg->elem_len); + spakeresult = NULL; + TRACE_SPAKE_RESULT(context, spakeresult_out); + +cleanup: + zapfree(spakeresult, gdef->reg->elem_len); + return ret; +} + +krb5_error_code +group_hash_len(int32_t group, size_t *len_out) +{ + const groupdef *gdef; + + *len_out = 0; + gdef = find_gdef(group); + if (gdef == NULL) + return EINVAL; + *len_out = gdef->reg->hash_len; + return 0; +} + +krb5_error_code +group_hash(krb5_context context, groupstate *gstate, int32_t group, + const krb5_data *dlist, size_t ndata, uint8_t *result_out) +{ + krb5_error_code ret; + const groupdef *gdef; + groupdata *gdata; + + gdef = find_gdef(group); + if (gdef == NULL) + return EINVAL; + ret = get_gdata(context, gstate, gdef, &gdata); + if (ret) + return ret; + return gdef->hash(context, gdata, dlist, ndata, result_out); +} diff --git a/krb5-1.21.3/src/plugins/preauth/spake/groups.h b/krb5-1.21.3/src/plugins/preauth/spake/groups.h new file mode 100644 index 00000000..3add6949 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/groups.h @@ -0,0 +1,148 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/spake/groups.h - SPAKE group interfaces */ +/* + * Copyright (C) 2015 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. + */ + +#ifndef GROUPS_H +#define GROUPS_H + +#include "k5-int.h" +#include "iana.h" + +typedef struct groupstate_st groupstate; +typedef struct groupdata_st groupdata; +typedef struct groupdef_st groupdef; + +struct groupdef_st { + const spake_iana *reg; + + /* + * Optional: create a per-group data object to allow more efficient keygen + * and result computations. Saving a reference to gdef is okay; its + * lifetime will always be longer than the resulting object. + */ + krb5_error_code (*init)(krb5_context context, const groupdef *gdef, + groupdata **gdata_out); + + /* Optional: release a group data object. */ + void (*fini)(groupdata *gdata); + + /* + * Mandatory: generate a random private scalar (x or y) and a public + * element (T or S), using wbytes for the w value. If use_m is true, use + * the M element (generating T); otherwise use the N element (generating + * S). wbytes and priv_out have length reg->mult_len; pub_out has length + * reg->elem_len. priv_out and pub_out are caller-allocated. + */ + krb5_error_code (*keygen)(krb5_context context, groupdata *gdata, + const uint8_t *wbytes, krb5_boolean use_m, + uint8_t *priv_out, uint8_t *pub_out); + + /* + * Mandatory: compute K given a private scalar (x or y) and the other + * party's public element (S or T), using wbytes for the w value. If use_m + * is true, use the M element (computing K from y and T); otherwise use the + * N element (computing K from x and S). wbytes and ourpriv have length + * reg->mult_len; theirpub and elem_out have length reg->elem_len. + * elem_out is caller-allocated. + */ + krb5_error_code (*result)(krb5_context context, groupdata *gdata, + const uint8_t *wbytes, const uint8_t *ourpriv, + const uint8_t *theirpub, krb5_boolean use_m, + uint8_t *elem_out); + + /* + * Mandatory: compute the group's specified hash function over datas (with + * ndata elements), placing the result in result_out. result_out is + * caller-allocated with length reg->hash_len. + */ + krb5_error_code (*hash)(krb5_context context, groupdata *gdata, + const krb5_data *datas, size_t ndata, + uint8_t *result_out); +}; + +/* Initialize an object which holds group configuration and pre-computation + * state for each group. is_kdc is true for KDCs, false for clients. */ +krb5_error_code group_init_state(krb5_context context, krb5_boolean is_kdc, + groupstate **out); + +/* Release resources held by gstate. */ +void group_free_state(groupstate *gstate); + +/* Return true if group is permitted by configuration. */ +krb5_boolean group_is_permitted(groupstate *gstate, int32_t group); + +/* Set *list_out and *count_out to the list of groups permitted by + * configuration. */ +void group_get_permitted(groupstate *gstate, int32_t **list_out, + int32_t *count_out); + +/* Return the KDC optimistic challenge group if one is configured. Valid for + * KDC groupstate objects only. */ +krb5_int32 group_optimistic_challenge(groupstate *gstate); + +/* Set *len_out to the multiplier length for group. */ +krb5_error_code group_mult_len(int32_t group, size_t *len_out); + +/* + * Generate a SPAKE private scalar (x or y) and public element (T or S), given + * an input multiplier wbytes. Use constant M if gstate is a KDC groupstate + * object, N if it is a client object. Allocate storage and place the results + * in *priv_out and *pub_out. + */ +krb5_error_code group_keygen(krb5_context context, groupstate *gstate, + int32_t group, const krb5_data *wbytes, + krb5_data *priv_out, krb5_data *pub_out); + +/* + * Compute the SPAKE result K from our private scalar (x or y) and their public + * key (S or T), deriving the input scalar w from ikey. Use the other party's + * constant, N if gstate is a KDC groupstate object or M if it is a client + * object. Allocate storage and place the result in *spakeresult_out. + */ +krb5_error_code group_result(krb5_context context, groupstate *gstate, + int32_t group, const krb5_data *wbytes, + const krb5_data *ourpriv, + const krb5_data *theirpub, + krb5_data *spakeresult_out); + +/* Set *result_out to the hash output length for group. */ +krb5_error_code group_hash_len(int32_t group, size_t *result_out); + +/* + * Compute the group's specified hash function over dlist (with ndata + * elements). result_out is caller-allocated with enough bytes for the hash + * output as given by group_hash_len(). + */ +krb5_error_code group_hash(krb5_context context, groupstate *gstate, + int32_t group, const krb5_data *dlist, size_t ndata, + uint8_t *result_out); + +#endif /* GROUPS_H */ diff --git a/krb5-1.21.3/src/plugins/preauth/spake/iana.c b/krb5-1.21.3/src/plugins/preauth/spake/iana.c new file mode 100644 index 00000000..e7901ded --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/iana.c @@ -0,0 +1,108 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/spake/iana.c - SPAKE IANA registry contents */ +/* + * Copyright (C) 2015 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. + */ + +#include "iana.h" + +static uint8_t edwards25519_M[] = { + 0xD0, 0x48, 0x03, 0x2C, 0x6E, 0xA0, 0xB6, 0xD6, 0x97, 0xDD, 0xC2, 0xE8, + 0x6B, 0xDA, 0x85, 0xA3, 0x3A, 0xDA, 0xC9, 0x20, 0xF1, 0xBF, 0x18, 0xE1, + 0xB0, 0xC6, 0xD1, 0x66, 0xA5, 0xCE, 0xCD, 0xAF +}; + +static uint8_t edwards25519_N[] = { + 0xD3, 0xBF, 0xB5, 0x18, 0xF4, 0x4F, 0x34, 0x30, 0xF2, 0x9D, 0x0C, 0x92, + 0xAF, 0x50, 0x38, 0x65, 0xA1, 0xED, 0x32, 0x81, 0xDC, 0x69, 0xB3, 0x5D, + 0xD8, 0x68, 0xBA, 0x85, 0xF8, 0x86, 0xC4, 0xAB +}; + +static uint8_t P256_M[] = { + 0x02, 0x88, 0x6E, 0x2F, 0x97, 0xAC, 0xE4, 0x6E, 0x55, 0xBA, 0x9D, 0xD7, + 0x24, 0x25, 0x79, 0xF2, 0x99, 0x3B, 0x64, 0xE1, 0x6E, 0xF3, 0xDC, 0xAB, + 0x95, 0xAF, 0xD4, 0x97, 0x33, 0x3D, 0x8F, 0xA1, 0x2F +}; + +static uint8_t P256_N[] = { + 0x03, 0xD8, 0xBB, 0xD6, 0xC6, 0x39, 0xC6, 0x29, 0x37, 0xB0, 0x4D, 0x99, + 0x7F, 0x38, 0xC3, 0x77, 0x07, 0x19, 0xC6, 0x29, 0xD7, 0x01, 0x4D, 0x49, + 0xA2, 0x4B, 0x4F, 0x98, 0xBA, 0xA1, 0x29, 0x2B, 0x49 +}; + +static uint8_t P384_M[] = { + 0x03, 0x0F, 0xF0, 0x89, 0x5A, 0xE5, 0xEB, 0xF6, 0x18, 0x70, 0x80, 0xA8, + 0x2D, 0x82, 0xB4, 0x2E, 0x27, 0x65, 0xE3, 0xB2, 0xF8, 0x74, 0x9C, 0x7E, + 0x05, 0xEB, 0xA3, 0x66, 0x43, 0x4B, 0x36, 0x3D, 0x3D, 0xC3, 0x6F, 0x15, + 0x31, 0x47, 0x39, 0x07, 0x4D, 0x2E, 0xB8, 0x61, 0x3F, 0xCE, 0xEC, 0x28, + 0x53 +}; + +static uint8_t P384_N[] = { + 0x02, 0xC7, 0x2C, 0xF2, 0xE3, 0x90, 0x85, 0x3A, 0x1C, 0x1C, 0x4A, 0xD8, + 0x16, 0xA6, 0x2F, 0xD1, 0x58, 0x24, 0xF5, 0x60, 0x78, 0x91, 0x8F, 0x43, + 0xF9, 0x22, 0xCA, 0x21, 0x51, 0x8F, 0x9C, 0x54, 0x3B, 0xB2, 0x52, 0xC5, + 0x49, 0x02, 0x14, 0xCF, 0x9A, 0xA3, 0xF0, 0xBA, 0xAB, 0x4B, 0x66, 0x5C, + 0x10 +}; + +static uint8_t P521_M[] = { + 0x02, 0x00, 0x3F, 0x06, 0xF3, 0x81, 0x31, 0xB2, 0xBA, 0x26, 0x00, 0x79, + 0x1E, 0x82, 0x48, 0x8E, 0x8D, 0x20, 0xAB, 0x88, 0x9A, 0xF7, 0x53, 0xA4, + 0x18, 0x06, 0xC5, 0xDB, 0x18, 0xD3, 0x7D, 0x85, 0x60, 0x8C, 0xFA, 0xE0, + 0x6B, 0x82, 0xE4, 0xA7, 0x2C, 0xD7, 0x44, 0xC7, 0x19, 0x19, 0x35, 0x62, + 0xA6, 0x53, 0xEA, 0x1F, 0x11, 0x9E, 0xEF, 0x93, 0x56, 0x90, 0x7E, 0xDC, + 0x9B, 0x56, 0x97, 0x99, 0x62, 0xD7, 0xAA +}; + +static uint8_t P521_N[] = { + 0x02, 0x00, 0xC7, 0x92, 0x4B, 0x9E, 0xC0, 0x17, 0xF3, 0x09, 0x45, 0x62, + 0x89, 0x43, 0x36, 0xA5, 0x3C, 0x50, 0x16, 0x7B, 0xA8, 0xC5, 0x96, 0x38, + 0x76, 0x88, 0x05, 0x42, 0xBC, 0x66, 0x9E, 0x49, 0x4B, 0x25, 0x32, 0xD7, + 0x6C, 0x5B, 0x53, 0xDF, 0xB3, 0x49, 0xFD, 0xF6, 0x91, 0x54, 0xB9, 0xE0, + 0x04, 0x8C, 0x58, 0xA4, 0x2E, 0x8E, 0xD0, 0x4C, 0xEF, 0x05, 0x2A, 0x3B, + 0xC3, 0x49, 0xD9, 0x55, 0x75, 0xCD, 0x25 +}; + +const spake_iana spake_iana_edwards25519 = { + SPAKE_GROUP_EDWARDS25519, "edwards25519", 32, 32, + edwards25519_M, edwards25519_N, 32 +}; + +const spake_iana spake_iana_p256 = { + SPAKE_GROUP_P256, "P-256", 32, 33, P256_M, P256_N, 32 +}; + +const spake_iana spake_iana_p384 = { + SPAKE_GROUP_P384, "P-384", 48, 49, P384_M, P384_N, 48 +}; + +const spake_iana spake_iana_p521 = { + SPAKE_GROUP_P521, "P-521", 66, 67, P521_M, P521_N, 64 +}; diff --git a/krb5-1.21.3/src/plugins/preauth/spake/iana.h b/krb5-1.21.3/src/plugins/preauth/spake/iana.h new file mode 100644 index 00000000..1d99c4dd --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/iana.h @@ -0,0 +1,65 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/spake/iana.h - SPAKE IANA registry contents */ +/* + * Copyright (C) 2015 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. + */ + +#ifndef IANA_H +#define IANA_H + +#include +#include + +typedef enum { + SPAKE_SF_NONE = 1, +} spake_sf_type; + +typedef enum { + SPAKE_GROUP_EDWARDS25519 = 1, + SPAKE_GROUP_P256 = 2, + SPAKE_GROUP_P384 = 3, + SPAKE_GROUP_P521 = 4, +} spake_group; + +typedef struct { + int32_t id; + const char *name; + size_t mult_len; + size_t elem_len; + const uint8_t *m; + const uint8_t *n; + size_t hash_len; +} spake_iana; + +extern const spake_iana spake_iana_edwards25519; +extern const spake_iana spake_iana_p256; +extern const spake_iana spake_iana_p384; +extern const spake_iana spake_iana_p521; + +#endif /* IANA_H */ diff --git a/krb5-1.21.3/src/plugins/preauth/spake/openssl.c b/krb5-1.21.3/src/plugins/preauth/spake/openssl.c new file mode 100644 index 00000000..f2e4b53e --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/openssl.c @@ -0,0 +1,316 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/spake/openssl.c - SPAKE implementations using OpenSSL */ +/* + * Copyright (C) 2015 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. + */ + +#include "k5-int.h" + +#include "groups.h" +#include "iana.h" + +#ifdef SPAKE_OPENSSL +#include +#include +#include +#include + +/* OpenSSL 1.1 standardizes constructor and destructor names, renaming + * EVP_MD_CTX_create and EVP_MD_CTX_destroy. */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define EVP_MD_CTX_new EVP_MD_CTX_create +#define EVP_MD_CTX_free EVP_MD_CTX_destroy +#endif + +struct groupdata_st { + const groupdef *gdef; + EC_GROUP *group; + BIGNUM *order; + BN_CTX *ctx; + EC_POINT *M; + EC_POINT *N; + const EVP_MD *md; +}; + +static void +ossl_fini(groupdata *gd) +{ + if (gd == NULL) + return; + + EC_GROUP_free(gd->group); + EC_POINT_free(gd->M); + EC_POINT_free(gd->N); + BN_CTX_free(gd->ctx); + BN_free(gd->order); + free(gd); +} + +static krb5_error_code +ossl_init(krb5_context context, const groupdef *gdef, groupdata **gdata_out) +{ + const spake_iana *reg = gdef->reg; + const EVP_MD *md; + groupdata *gd; + int nid; + + switch (reg->id) { + case SPAKE_GROUP_P256: + nid = NID_X9_62_prime256v1; + md = EVP_sha256(); + break; + case SPAKE_GROUP_P384: + nid = NID_secp384r1; + md = EVP_sha384(); + break; + case SPAKE_GROUP_P521: + nid = NID_secp521r1; + md = EVP_sha512(); + break; + default: + return EINVAL; + }; + + gd = calloc(1, sizeof(*gd)); + if (gd == NULL) + return ENOMEM; + gd->gdef = gdef; + + gd->group = EC_GROUP_new_by_curve_name(nid); + if (gd->group == NULL) + goto error; + + gd->ctx = BN_CTX_new(); + if (gd->ctx == NULL) + goto error; + + gd->order = BN_new(); + if (gd->order == NULL) + goto error; + if (!EC_GROUP_get_order(gd->group, gd->order, gd->ctx)) + goto error; + + gd->M = EC_POINT_new(gd->group); + if (gd->M == NULL) + goto error; + if (!EC_POINT_oct2point(gd->group, gd->M, reg->m, reg->elem_len, gd->ctx)) + goto error; + + gd->N = EC_POINT_new(gd->group); + if (gd->N == NULL) + goto error; + if (!EC_POINT_oct2point(gd->group, gd->N, reg->n, reg->elem_len, gd->ctx)) + goto error; + + gd->md = md; + + *gdata_out = gd; + return 0; + +error: + ossl_fini(gd); + return ENOMEM; +} + +/* Convert pseudo-random bytes into a scalar value in constant time. + * Return NULL on failure. */ +static BIGNUM * +unmarshal_w(const groupdata *gdata, const uint8_t *wbytes) +{ + const spake_iana *reg = gdata->gdef->reg; + BIGNUM *w = NULL; + + w = BN_new(); + if (w == NULL) + return NULL; + + BN_set_flags(w, BN_FLG_CONSTTIME); + + if (BN_bin2bn(wbytes, reg->mult_len, w) && + BN_div(NULL, w, w, gdata->order, gdata->ctx)) + return w; + + BN_free(w); + return NULL; +} + +static krb5_error_code +ossl_keygen(krb5_context context, groupdata *gdata, const uint8_t *wbytes, + krb5_boolean use_m, uint8_t *priv_out, uint8_t *pub_out) +{ + const spake_iana *reg = gdata->gdef->reg; + const EC_POINT *constant = use_m ? gdata->M : gdata->N; + krb5_boolean success = FALSE; + EC_POINT *pub = NULL; + BIGNUM *priv = NULL, *w = NULL; + size_t len; + + w = unmarshal_w(gdata, wbytes); + if (w == NULL) + goto cleanup; + + pub = EC_POINT_new(gdata->group); + if (pub == NULL) + goto cleanup; + + priv = BN_new(); + if (priv == NULL) + goto cleanup; + + if (!BN_rand_range(priv, gdata->order)) + goto cleanup; + + /* Compute priv*G + w*constant; EC_POINT_mul() does this in one call. */ + if (!EC_POINT_mul(gdata->group, pub, priv, constant, w, gdata->ctx)) + goto cleanup; + + /* Marshal priv into priv_out. */ + memset(priv_out, 0, reg->mult_len); + BN_bn2bin(priv, &priv_out[reg->mult_len - BN_num_bytes(priv)]); + + /* Marshal pub into pub_out. */ + len = EC_POINT_point2oct(gdata->group, pub, POINT_CONVERSION_COMPRESSED, + pub_out, reg->elem_len, gdata->ctx); + if (len != reg->elem_len) + goto cleanup; + + success = TRUE; + +cleanup: + EC_POINT_free(pub); + BN_clear_free(priv); + BN_clear_free(w); + return success ? 0 : ENOMEM; +} + +static krb5_error_code +ossl_result(krb5_context context, groupdata *gdata, const uint8_t *wbytes, + const uint8_t *ourpriv, const uint8_t *theirpub, + krb5_boolean use_m, uint8_t *elem_out) +{ + const spake_iana *reg = gdata->gdef->reg; + const EC_POINT *constant = use_m ? gdata->M : gdata->N; + krb5_boolean success = FALSE, invalid = FALSE; + EC_POINT *result = NULL, *pub = NULL; + BIGNUM *priv = NULL, *w = NULL; + size_t len; + + w = unmarshal_w(gdata, wbytes); + if (w == NULL) + goto cleanup; + + priv = BN_bin2bn(ourpriv, reg->mult_len, NULL); + if (priv == NULL) + goto cleanup; + + pub = EC_POINT_new(gdata->group); + if (pub == NULL) + goto cleanup; + if (!EC_POINT_oct2point(gdata->group, pub, theirpub, reg->elem_len, + gdata->ctx)) { + invalid = TRUE; + goto cleanup; + } + + /* Compute result = priv*(pub - w*constant), using result to hold the + * intermediate steps. */ + result = EC_POINT_new(gdata->group); + if (result == NULL) + goto cleanup; + if (!EC_POINT_mul(gdata->group, result, NULL, constant, w, gdata->ctx)) + goto cleanup; + if (!EC_POINT_invert(gdata->group, result, gdata->ctx)) + goto cleanup; + if (!EC_POINT_add(gdata->group, result, pub, result, gdata->ctx)) + goto cleanup; + if (!EC_POINT_mul(gdata->group, result, NULL, result, priv, gdata->ctx)) + goto cleanup; + + /* Marshal result into elem_out. */ + len = EC_POINT_point2oct(gdata->group, result, POINT_CONVERSION_COMPRESSED, + elem_out, reg->elem_len, gdata->ctx); + if (len != reg->elem_len) + goto cleanup; + + success = TRUE; + +cleanup: + BN_clear_free(priv); + BN_clear_free(w); + EC_POINT_free(pub); + EC_POINT_clear_free(result); + return invalid ? EINVAL : (success ? 0 : ENOMEM); +} + +static krb5_error_code +ossl_hash(krb5_context context, groupdata *gdata, const krb5_data *dlist, + size_t ndata, uint8_t *result_out) +{ + EVP_MD_CTX *ctx; + size_t i; + int ok; + + ctx = EVP_MD_CTX_new(); + if (ctx == NULL) + return ENOMEM; + ok = EVP_DigestInit_ex(ctx, gdata->md, NULL); + for (i = 0; i < ndata; i++) + ok = ok && EVP_DigestUpdate(ctx, dlist[i].data, dlist[i].length); + ok = ok && EVP_DigestFinal_ex(ctx, result_out, NULL); + EVP_MD_CTX_free(ctx); + return ok ? 0 : ENOMEM; +} + +groupdef ossl_P256 = { + .reg = &spake_iana_p256, + .init = ossl_init, + .fini = ossl_fini, + .keygen = ossl_keygen, + .result = ossl_result, + .hash = ossl_hash, +}; + +groupdef ossl_P384 = { + .reg = &spake_iana_p384, + .init = ossl_init, + .fini = ossl_fini, + .keygen = ossl_keygen, + .result = ossl_result, + .hash = ossl_hash, +}; + +groupdef ossl_P521 = { + .reg = &spake_iana_p521, + .init = ossl_init, + .fini = ossl_fini, + .keygen = ossl_keygen, + .result = ossl_result, + .hash = ossl_hash, +}; +#endif /* SPAKE_OPENSSL */ diff --git a/krb5-1.21.3/src/plugins/preauth/spake/spake.def b/krb5-1.21.3/src/plugins/preauth/spake/spake.def new file mode 100644 index 00000000..1b2cf4dc --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/spake.def @@ -0,0 +1,3 @@ +EXPORTS + + clpreauth_spake_initvt diff --git a/krb5-1.21.3/src/plugins/preauth/spake/spake.exports b/krb5-1.21.3/src/plugins/preauth/spake/spake.exports new file mode 100644 index 00000000..81d10022 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/spake.exports @@ -0,0 +1,2 @@ +clpreauth_spake_initvt +kdcpreauth_spake_initvt diff --git a/krb5-1.21.3/src/plugins/preauth/spake/spake_client.c b/krb5-1.21.3/src/plugins/preauth/spake/spake_client.c new file mode 100644 index 00000000..00734a13 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/spake_client.c @@ -0,0 +1,388 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/spake/spake_client.c - SPAKE clpreauth module */ +/* + * Copyright (C) 2015 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. + */ + +#include "k5-int.h" +#include "k5-spake.h" +#include "trace.h" +#include "util.h" +#include "iana.h" +#include "groups.h" +#include + +typedef struct reqstate_st { + krb5_pa_spake *msg; /* set in prep_questions, used in process */ + krb5_keyblock *initial_key; + krb5_data *support; + krb5_data thash; + krb5_data spakeresult; +} reqstate; + +/* Return true if SF-NONE is present in factors. */ +static krb5_boolean +contains_sf_none(krb5_spake_factor **factors) +{ + int i; + + for (i = 0; factors != NULL && factors[i] != NULL; i++) { + if (factors[i]->type == SPAKE_SF_NONE) + return TRUE; + } + return FALSE; +} + +static krb5_error_code +spake_init(krb5_context context, krb5_clpreauth_moddata *moddata_out) +{ + krb5_error_code ret; + groupstate *gstate; + + ret = group_init_state(context, FALSE, &gstate); + if (ret) + return ret; + *moddata_out = (krb5_clpreauth_moddata)gstate; + return 0; +} + +static void +spake_fini(krb5_context context, krb5_clpreauth_moddata moddata) +{ + group_free_state((groupstate *)moddata); +} + +static void +spake_request_init(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq *modreq_out) +{ + *modreq_out = calloc(1, sizeof(reqstate)); +} + +static void +spake_request_fini(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq) +{ + reqstate *st = (reqstate *)modreq; + + k5_free_pa_spake(context, st->msg); + krb5_free_keyblock(context, st->initial_key); + krb5_free_data(context, st->support); + krb5_free_data_contents(context, &st->thash); + zapfree(st->spakeresult.data, st->spakeresult.length); + free(st); +} + +static krb5_error_code +spake_prep_questions(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, + krb5_get_init_creds_opt *opt, krb5_clpreauth_callbacks cb, + krb5_clpreauth_rock rock, krb5_kdc_req *req, + krb5_data *enc_req, krb5_data *enc_prev_req, + krb5_pa_data *pa_data) +{ + krb5_error_code ret; + groupstate *gstate = (groupstate *)moddata; + reqstate *st = (reqstate *)modreq; + krb5_data in_data; + krb5_spake_challenge *ch; + + if (st == NULL) + return ENOMEM; + + /* We don't need to ask any questions to send a support message. */ + if (pa_data->length == 0) + return 0; + + /* Decode the incoming message, replacing any previous one in the request + * state. If we can't decode it, we have no questions to ask. */ + k5_free_pa_spake(context, st->msg); + st->msg = NULL; + in_data = make_data(pa_data->contents, pa_data->length); + ret = decode_krb5_pa_spake(&in_data, &st->msg); + if (ret) + return (ret == ENOMEM) ? ENOMEM : 0; + + if (st->msg->choice == SPAKE_MSGTYPE_CHALLENGE) { + ch = &st->msg->u.challenge; + if (!group_is_permitted(gstate, ch->group)) + return 0; + /* When second factor support is implemented, we should ask questions + * based on the factors in the challenge. */ + if (!contains_sf_none(ch->factors)) + return 0; + /* We will need the AS key to respond to the challenge. */ + cb->need_as_key(context, rock); + } else if (st->msg->choice == SPAKE_MSGTYPE_ENCDATA) { + /* When second factor support is implemented, we should decrypt the + * encdata message and ask questions based on the factor data. */ + } + return 0; +} + +/* + * Output a PA-SPAKE support message indicating which groups we support. This + * may be done for optimistic preauth, in response to an empty message, or in + * response to a challenge using a group we do not support. Save the support + * message in st->support. + */ +static krb5_error_code +send_support(krb5_context context, groupstate *gstate, reqstate *st, + krb5_pa_data ***pa_out) +{ + krb5_error_code ret; + krb5_data *support; + krb5_pa_spake msg; + + msg.choice = SPAKE_MSGTYPE_SUPPORT; + group_get_permitted(gstate, &msg.u.support.groups, &msg.u.support.ngroups); + ret = encode_krb5_pa_spake(&msg, &support); + if (ret) + return ret; + + /* Save the support message for later use in the transcript hash. */ + ret = krb5_copy_data(context, support, &st->support); + if (ret) { + krb5_free_data(context, support); + return ret; + } + + TRACE_SPAKE_SEND_SUPPORT(context); + return convert_to_padata(support, pa_out); +} + +static krb5_error_code +process_challenge(krb5_context context, groupstate *gstate, reqstate *st, + krb5_spake_challenge *ch, const krb5_data *der_msg, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_prompter_fct prompter, void *prompter_data, + const krb5_data *der_req, krb5_pa_data ***pa_out) +{ + krb5_error_code ret; + krb5_keyblock *k0 = NULL, *k1 = NULL, *as_key; + krb5_spake_factor factor; + krb5_pa_spake msg; + krb5_data *der_factor = NULL, *response; + krb5_data clpriv = empty_data(), clpub = empty_data(); + krb5_data wbytes = empty_data(); + krb5_enc_data enc_factor; + + enc_factor.ciphertext = empty_data(); + + /* Not expected if we processed a challenge and didn't reject it. */ + if (st->initial_key != NULL) + return KRB5KDC_ERR_PREAUTH_FAILED; + + if (!group_is_permitted(gstate, ch->group)) { + TRACE_SPAKE_REJECT_CHALLENGE(context, ch->group); + /* No point in sending a second support message. */ + if (st->support != NULL) + return KRB5KDC_ERR_PREAUTH_FAILED; + return send_support(context, gstate, st, pa_out); + } + + /* Initialize and update the transcript with the concatenation of the + * support message (if we sent one) and the received challenge. */ + ret = update_thash(context, gstate, ch->group, &st->thash, st->support, + der_msg); + if (ret) + return ret; + + TRACE_SPAKE_RECEIVE_CHALLENGE(context, ch->group, &ch->pubkey); + + /* When second factor support is implemented, we should check for a + * supported factor type instead of just checking for SF-NONE. */ + if (!contains_sf_none(ch->factors)) + return KRB5KDC_ERR_PREAUTH_FAILED; + + ret = cb->get_as_key(context, rock, &as_key); + if (ret) + goto cleanup; + ret = krb5_copy_keyblock(context, as_key, &st->initial_key); + if (ret) + goto cleanup; + ret = derive_wbytes(context, ch->group, st->initial_key, &wbytes); + if (ret) + goto cleanup; + ret = group_keygen(context, gstate, ch->group, &wbytes, &clpriv, &clpub); + if (ret) + goto cleanup; + ret = group_result(context, gstate, ch->group, &wbytes, &clpriv, + &ch->pubkey, &st->spakeresult); + if (ret) + goto cleanup; + + ret = update_thash(context, gstate, ch->group, &st->thash, &clpub, NULL); + if (ret) + goto cleanup; + TRACE_SPAKE_CLIENT_THASH(context, &st->thash); + + /* Replace the reply key with K'[0]. */ + ret = derive_key(context, gstate, ch->group, st->initial_key, &wbytes, + &st->spakeresult, &st->thash, der_req, 0, &k0); + if (ret) + goto cleanup; + ret = cb->set_as_key(context, rock, k0); + if (ret) + goto cleanup; + + /* Encrypt a SPAKESecondFactor message with K'[1]. */ + ret = derive_key(context, gstate, ch->group, st->initial_key, &wbytes, + &st->spakeresult, &st->thash, der_req, 1, &k1); + if (ret) + goto cleanup; + /* When second factor support is implemented, we should construct an + * appropriate factor here instead of hardcoding SF-NONE. */ + factor.type = SPAKE_SF_NONE; + factor.data = NULL; + ret = encode_krb5_spake_factor(&factor, &der_factor); + if (ret) + goto cleanup; + ret = krb5_encrypt_helper(context, k1, KRB5_KEYUSAGE_SPAKE, der_factor, + &enc_factor); + if (ret) + goto cleanup; + + /* Encode and output a response message. */ + msg.choice = SPAKE_MSGTYPE_RESPONSE; + msg.u.response.pubkey = clpub; + msg.u.response.factor = enc_factor; + ret = encode_krb5_pa_spake(&msg, &response); + if (ret) + goto cleanup; + TRACE_SPAKE_SEND_RESPONSE(context); + ret = convert_to_padata(response, pa_out); + if (ret) + goto cleanup; + + cb->disable_fallback(context, rock); + +cleanup: + krb5_free_keyblock(context, k0); + krb5_free_keyblock(context, k1); + krb5_free_data_contents(context, &enc_factor.ciphertext); + krb5_free_data_contents(context, &clpub); + zapfree(clpriv.data, clpriv.length); + zapfree(wbytes.data, wbytes.length); + if (der_factor != NULL) { + zapfree(der_factor->data, der_factor->length); + free(der_factor); + } + return ret; +} + +static krb5_error_code +process_encdata(krb5_context context, reqstate *st, krb5_enc_data *enc, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_prompter_fct prompter, void *prompter_data, + const krb5_data *der_prev_req, const krb5_data *der_req, + krb5_pa_data ***pa_out) +{ + /* Not expected if we haven't sent a response yet. */ + if (st->initial_key == NULL || st->spakeresult.length == 0) + return KRB5KDC_ERR_PREAUTH_FAILED; + + /* + * When second factor support is implemented, we should process encdata + * messages according to the factor type. We should make sure to re-derive + * K'[0] and replace the reply key again, in case the request has changed. + * We should use der_prev_req to derive K'[n] to decrypt factor from the + * KDC. We should use der_req to derive K'[n+1] for the next message to + * send to the KDC. + */ + return KRB5_PLUGIN_OP_NOTSUPP; +} + +static krb5_error_code +spake_process(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_kdc_req *req, krb5_data *der_req, krb5_data *der_prev_req, + krb5_pa_data *pa_in, krb5_prompter_fct prompter, + void *prompter_data, krb5_pa_data ***pa_out) +{ + krb5_error_code ret; + groupstate *gstate = (groupstate *)moddata; + reqstate *st = (reqstate *)modreq; + krb5_data in_data; + + if (st == NULL) + return ENOMEM; + + if (pa_in->length == 0) { + /* Not expected if we already sent a support message. */ + if (st->support != NULL) + return KRB5KDC_ERR_PREAUTH_FAILED; + return send_support(context, gstate, st, pa_out); + } + + if (st->msg == NULL) { + /* The message failed to decode in spake_prep_questions(). */ + ret = KRB5KDC_ERR_PREAUTH_FAILED; + } else if (st->msg->choice == SPAKE_MSGTYPE_CHALLENGE) { + in_data = make_data(pa_in->contents, pa_in->length); + ret = process_challenge(context, gstate, st, &st->msg->u.challenge, + &in_data, cb, rock, prompter, prompter_data, + der_req, pa_out); + } else if (st->msg->choice == SPAKE_MSGTYPE_ENCDATA) { + ret = process_encdata(context, st, &st->msg->u.encdata, cb, rock, + prompter, prompter_data, der_prev_req, der_req, + pa_out); + } else { + /* Unexpected message type */ + ret = KRB5KDC_ERR_PREAUTH_FAILED; + } + + return ret; +} + +krb5_error_code +clpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +clpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_clpreauth_vtable vt; + static krb5_preauthtype pa_types[] = { KRB5_PADATA_SPAKE, 0 }; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_clpreauth_vtable)vtable; + vt->name = "spake"; + vt->pa_type_list = pa_types; + vt->init = spake_init; + vt->fini = spake_fini; + vt->request_init = spake_request_init; + vt->request_fini = spake_request_fini; + vt->process = spake_process; + vt->prep_questions = spake_prep_questions; + return 0; +} diff --git a/krb5-1.21.3/src/plugins/preauth/spake/spake_kdc.c b/krb5-1.21.3/src/plugins/preauth/spake/spake_kdc.c new file mode 100644 index 00000000..1a772d45 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/spake_kdc.c @@ -0,0 +1,562 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/spake/spake_kdc.c - SPAKE kdcpreauth module */ +/* + * Copyright (C) 2015 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. + */ + +#include "k5-int.h" +#include "k5-input.h" +#include "k5-spake.h" + +#include "groups.h" +#include "trace.h" +#include "iana.h" +#include "util.h" + +#include + +/* + * The SPAKE kdcpreauth module uses a secure cookie containing the following + * concatenated fields (all integer fields are big-endian): + * + * version (16-bit unsigned integer) + * stage (16-bit unsigned integer) + * group (32-bit signed integer) + * SPAKE value (32-bit unsigned length, followed by data) + * Transcript hash (32-bit unsigned length, followed by data) + * Zero or more instances of: + * second-factor number (32-bit signed integer) + * second-factor data (32-bit unsigned length, followed by data) + * + * The only currently supported version is 1. stage is 0 if the cookie was + * sent with a challenge message. stage is n>0 if the cookie was sent with an + * encdata message encrypted in K'[2n]. group indicates the group number used + * in the SPAKE challenge. The SPAKE value is the KDC private key for a + * stage-0 cookie, represented in the scalar marshalling form of the group; for + * other cookies, the SPAKE value is the SPAKE result K, represented in the + * group element marshalling form. The transcript hash is the intermediate + * hash after updating with the support and challenge messages for a stage-0 + * cookie, or the final hash for other cookies. For a stage 0 cookie, there + * may be any number of second-factor records, including none (no record is + * generated for SF-NONE); for other cookies, there must be exactly one + * second-factor record corresponding to the factor type chosen by the client. + */ + +/* From a k5input structure representing the remainder of a secure cookie + * plaintext, parse a four-byte length and data. */ +static void +parse_data(struct k5input *in, krb5_data *out) +{ + out->length = k5_input_get_uint32_be(in); + out->data = (char *)k5_input_get_bytes(in, out->length); + out->magic = KV5M_DATA; +} + +/* Parse a received cookie into its components. The pointers stored in the + * krb5_data outputs are aliases into cookie and should not be freed. */ +static krb5_error_code +parse_cookie(const krb5_data *cookie, int *stage_out, int32_t *group_out, + krb5_data *spake_out, krb5_data *thash_out, + krb5_data *factors_out) +{ + struct k5input in; + int version, stage; + int32_t group; + krb5_data thash, spake, factors; + + *spake_out = *thash_out = *factors_out = empty_data(); + k5_input_init(&in, cookie->data, cookie->length); + + /* Parse and check the version, and read the other integer fields. */ + version = k5_input_get_uint16_be(&in); + if (version != 1) + return KRB5KDC_ERR_PREAUTH_FAILED; + stage = k5_input_get_uint16_be(&in); + group = k5_input_get_uint32_be(&in); + + /* Parse the data fields. The factor data is anything remaining after the + * transcript hash. */ + parse_data(&in, &spake); + parse_data(&in, &thash); + if (in.status) + return in.status; + factors = make_data((char *)in.ptr, in.len); + + *stage_out = stage; + *group_out = group; + *spake_out = spake; + *thash_out = thash; + *factors_out = factors; + return 0; +} + +/* Marshal data into buf as a four-byte length followed by the contents. */ +static void +marshal_data(struct k5buf *buf, const krb5_data *data) +{ + k5_buf_add_uint32_be(buf, data->length); + k5_buf_add_len(buf, data->data, data->length); +} + +/* Marshal components into a cookie. */ +static krb5_error_code +make_cookie(int stage, int32_t group, const krb5_data *spake, + const krb5_data *thash, krb5_data *cookie_out) +{ + struct k5buf buf; + + *cookie_out = empty_data(); + k5_buf_init_dynamic_zap(&buf); + + /* Marshal the version, stage, and group. */ + k5_buf_add_uint16_be(&buf, 1); + k5_buf_add_uint16_be(&buf, stage); + k5_buf_add_uint32_be(&buf, group); + + /* Marshal the data fields. */ + marshal_data(&buf, spake); + marshal_data(&buf, thash); + + /* When second factor support is implemented, we should add factor data + * here. */ + + if (buf.data == NULL) + return ENOMEM; + *cookie_out = make_data(buf.data, buf.len); + return 0; +} + +/* Add authentication indicators if any are configured for SPAKE. */ +static krb5_error_code +add_indicators(krb5_context context, const krb5_data *realm, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock) +{ + krb5_error_code ret; + const char *keys[4]; + char *realmstr, **indicators, **ind; + + realmstr = k5memdup0(realm->data, realm->length, &ret); + if (realmstr == NULL) + return ret; + keys[0] = KRB5_CONF_REALMS; + keys[1] = realmstr; + keys[2] = KRB5_CONF_SPAKE_PREAUTH_INDICATOR; + keys[3] = NULL; + ret = profile_get_values(context->profile, keys, &indicators); + free(realmstr); + if (ret == PROF_NO_RELATION) + return 0; + if (ret) + return ret; + + for (ind = indicators; *ind != NULL && !ret; ind++) + ret = cb->add_auth_indicator(context, rock, *ind); + + profile_free_list(indicators); + return ret; +} + +/* Initialize a SPAKE module data object. */ +static krb5_error_code +spake_init(krb5_context context, krb5_kdcpreauth_moddata *moddata_out, + const char **realmnames) +{ + krb5_error_code ret; + groupstate *gstate; + + ret = group_init_state(context, TRUE, &gstate); + if (ret) + return ret; + *moddata_out = (krb5_kdcpreauth_moddata)gstate; + return 0; +} + +/* Release a SPAKE module data object. */ +static void +spake_fini(krb5_context context, krb5_kdcpreauth_moddata moddata) +{ + group_free_state((groupstate *)moddata); +} + +/* + * Generate a SPAKE challenge message for the specified group. Use cb and rock + * to retrieve the initial reply key and to set a stage-0 cookie. Invoke + * either erespond or vrespond with the result. + */ +static void +send_challenge(krb5_context context, groupstate *gstate, int32_t group, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + const krb5_data *support, + krb5_kdcpreauth_edata_respond_fn erespond, + krb5_kdcpreauth_verify_respond_fn vrespond, void *arg) +{ + krb5_error_code ret; + const krb5_keyblock *ikey; + krb5_pa_data **padata = NULL, *pa; + krb5_data kdcpriv = empty_data(), kdcpub = empty_data(), *der_msg = NULL; + krb5_data thash = empty_data(), cookie = empty_data(); + krb5_data wbytes = empty_data(); + krb5_spake_factor f, *flist[2]; + krb5_pa_spake msg; + + ikey = cb->client_keyblock(context, rock); + if (ikey == NULL) { + ret = KRB5KDC_ERR_ETYPE_NOSUPP; + goto cleanup; + } + + ret = derive_wbytes(context, group, ikey, &wbytes); + if (ret) + goto cleanup; + ret = group_keygen(context, gstate, group, &wbytes, &kdcpriv, &kdcpub); + if (ret) + goto cleanup; + + /* Encode the challenge. When second factor support is implemented, we + * should construct a factor list instead of hardcoding SF-NONE. */ + f.type = SPAKE_SF_NONE; + f.data = NULL; + flist[0] = &f; + flist[1] = NULL; + msg.choice = SPAKE_MSGTYPE_CHALLENGE; + msg.u.challenge.group = group; + msg.u.challenge.pubkey = kdcpub; + msg.u.challenge.factors = flist; + ret = encode_krb5_pa_spake(&msg, &der_msg); + if (ret) + goto cleanup; + + /* Initialize and update the transcript hash with the support message (if + * we received one) and challenge message. */ + ret = update_thash(context, gstate, group, &thash, support, der_msg); + if (ret) + goto cleanup; + + /* Save the group, transcript hash, and private key in a stage-0 cookie. + * When second factor support is implemented, also save factor state. */ + ret = make_cookie(0, group, &kdcpriv, &thash, &cookie); + if (ret) + goto cleanup; + ret = cb->set_cookie(context, rock, KRB5_PADATA_SPAKE, &cookie); + if (ret) + goto cleanup; + + ret = convert_to_padata(der_msg, &padata); + der_msg = NULL; + TRACE_SPAKE_SEND_CHALLENGE(context, group); + +cleanup: + zapfree(wbytes.data, wbytes.length); + zapfree(kdcpriv.data, kdcpriv.length); + zapfree(cookie.data, cookie.length); + krb5_free_data_contents(context, &kdcpub); + krb5_free_data_contents(context, &thash); + krb5_free_data(context, der_msg); + + if (erespond != NULL) { + assert(vrespond == NULL); + /* Grab the first pa-data element from the list, if we made one. */ + pa = (padata == NULL) ? NULL : padata[0]; + free(padata); + (*erespond)(arg, ret, pa); + } else { + assert(vrespond != NULL); + if (!ret) + ret = KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED; + (*vrespond)(arg, ret, NULL, padata, NULL); + } +} + +/* Generate the METHOD-DATA entry indicating support for SPAKE. Include an + * optimistic challenge if configured to do so. */ +static void +spake_edata(krb5_context context, krb5_kdc_req *req, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type, + krb5_kdcpreauth_edata_respond_fn respond, void *arg) +{ + const krb5_keyblock *ikey; + groupstate *gstate = (groupstate *)moddata; + krb5_data empty = empty_data(); + int32_t group; + + /* SPAKE requires a client key, which cannot be a single-DES key. */ + ikey = cb->client_keyblock(context, rock); + if (ikey == NULL) { + (*respond)(arg, KRB5KDC_ERR_ETYPE_NOSUPP, NULL); + return; + } + + group = group_optimistic_challenge(gstate); + if (group) { + send_challenge(context, gstate, group, cb, rock, &empty, respond, NULL, + arg); + } else { + /* No optimistic challenge configured; send an empty pa-data value. */ + (*respond)(arg, 0, NULL); + } +} + +/* Choose a group from the client's support message and generate a + * challenge. */ +static void +verify_support(krb5_context context, groupstate *gstate, + krb5_spake_support *support, const krb5_data *der_msg, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_verify_respond_fn respond, void *arg) +{ + krb5_error_code ret; + int32_t i, group; + + for (i = 0; i < support->ngroups; i++) { + if (group_is_permitted(gstate, support->groups[i])) + break; + } + if (i == support->ngroups) { + TRACE_SPAKE_REJECT_SUPPORT(context); + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto error; + } + group = support->groups[i]; + TRACE_SPAKE_RECEIVE_SUPPORT(context, group); + + send_challenge(context, gstate, group, cb, rock, der_msg, NULL, respond, + arg); + return; + +error: + (*respond)(arg, ret, NULL, NULL, NULL); +} + +/* + * From the client's response message, compute the SPAKE result and decrypt the + * factor reply. On success, either mark the reply as pre-authenticated and + * set a reply key in the pre-request module data, or generate an additional + * factor challenge and ask for another round of pre-authentication. + */ +static void +verify_response(krb5_context context, groupstate *gstate, + krb5_spake_response *resp, const krb5_data *realm, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_enc_tkt_part *enc_tkt_reply, + krb5_kdcpreauth_verify_respond_fn respond, void *arg) +{ + krb5_error_code ret; + const krb5_keyblock *ikey; + krb5_keyblock *k1 = NULL, *reply_key = NULL; + krb5_data cookie, thash_in, kdcpriv, factors, *der_req; + krb5_data thash = empty_data(), der_factor = empty_data(); + krb5_data wbytes = empty_data(), spakeresult = empty_data(); + krb5_spake_factor *factor = NULL; + int stage; + int32_t group; + + ikey = cb->client_keyblock(context, rock); + if (ikey == NULL) { + ret = KRB5KDC_ERR_ETYPE_NOSUPP; + goto cleanup; + } + + /* Fetch the stage-0 cookie and parse it. (All of the krb5_data results + * are aliases into memory owned by rock). */ + if (!cb->get_cookie(context, rock, KRB5_PADATA_SPAKE, &cookie)) { + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + ret = parse_cookie(&cookie, &stage, &group, &kdcpriv, &thash_in, &factors); + if (ret) + goto cleanup; + if (stage != 0) { + /* The received cookie wasn't sent with a challenge. */ + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + TRACE_SPAKE_RECEIVE_RESPONSE(context, &resp->pubkey); + + /* Update the transcript hash with the client public key. */ + ret = krb5int_copy_data_contents(context, &thash_in, &thash); + if (ret) + goto cleanup; + ret = update_thash(context, gstate, group, &thash, &resp->pubkey, NULL); + if (ret) + goto cleanup; + TRACE_SPAKE_KDC_THASH(context, &thash); + + ret = derive_wbytes(context, group, ikey, &wbytes); + if (ret) + goto cleanup; + ret = group_result(context, gstate, group, &wbytes, &kdcpriv, + &resp->pubkey, &spakeresult); + if (ret) + goto cleanup; + + /* Decrypt the response factor field using K'[1]. If the decryption + * integrity check fails, the client probably used the wrong password. */ + der_req = cb->request_body(context, rock); + ret = derive_key(context, gstate, group, ikey, &wbytes, &spakeresult, + &thash, der_req, 1, &k1); + if (ret) + goto cleanup; + ret = alloc_data(&der_factor, resp->factor.ciphertext.length); + if (ret) + goto cleanup; + ret = krb5_c_decrypt(context, k1, KRB5_KEYUSAGE_SPAKE, NULL, &resp->factor, + &der_factor); + if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) + ret = KRB5KDC_ERR_PREAUTH_FAILED; + if (ret) + goto cleanup; + ret = decode_krb5_spake_factor(&der_factor, &factor); + if (ret) + goto cleanup; + + /* + * When second factor support is implemented, we should verify the factor + * data here, and possibly generate an encdata message for another hop. + * This function may need to be split at this point to allow for + * asynchronous verification of the second-factor value. We might also + * need to collect authentication indicators from the second-factor module; + * alternatively the module could have access to cb and rock so that it can + * add indicators itself. + */ + if (factor->type != SPAKE_SF_NONE) { + ret = KRB5KDC_ERR_PREAUTH_FAILED; + goto cleanup; + } + + ret = add_indicators(context, realm, cb, rock); + if (ret) + goto cleanup; + + enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; + + ret = derive_key(context, gstate, group, ikey, &wbytes, &spakeresult, + &thash, der_req, 0, &reply_key); + if (ret) + goto cleanup; + + ret = cb->replace_reply_key(context, rock, reply_key, TRUE); + +cleanup: + zapfree(wbytes.data, wbytes.length); + zapfree(der_factor.data, der_factor.length); + zapfree(spakeresult.data, spakeresult.length); + krb5_free_data_contents(context, &thash); + krb5_free_keyblock(context, k1); + krb5_free_keyblock(context, reply_key); + k5_free_spake_factor(context, factor); + (*respond)(arg, ret, NULL, NULL, NULL); +} + +/* + * Decrypt and validate an additional second-factor reply. On success, either + * mark the reply as pre-authenticated and set a reply key in the pre-request + * module data, or generate an additional factor challenge and ask for another + * round of pre-authentication. + */ +static void +verify_encdata(krb5_context context, krb5_enc_data *enc, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_enc_tkt_part *enc_tkt_reply, + krb5_kdcpreauth_verify_respond_fn respond, void *arg) +{ + /* + * When second factor support is implemented, we should process encdata + * message according to the factor type recorded in the cookie. If the + * second factor exchange finishes successfully, we should set + * TKT_FLG_PRE_AUTH, set the reply key to K'[0], and add any auth + * indicators from configuration (with a call to add_indicators()) or the + * second factor module (unless the module has access to cb and rock and + * can add indicators itself). + */ + (*respond)(arg, KRB5KDC_ERR_PREAUTH_FAILED, NULL, NULL, NULL); +} + +/* + * Respond to a client padata message, either by generating a SPAKE challenge, + * generating an additional second-factor challenge, or marking the reply as + * pre-authenticated and setting an additional reply key in the pre-request + * module data. + */ +static void +spake_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, + krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *data, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_verify_respond_fn respond, void *arg) +{ + krb5_error_code ret; + krb5_pa_spake *pa_spake = NULL; + krb5_data in_data = make_data(data->contents, data->length); + groupstate *gstate = (groupstate *)moddata; + + ret = decode_krb5_pa_spake(&in_data, &pa_spake); + if (ret) { + (*respond)(arg, ret, NULL, NULL, NULL); + } else if (pa_spake->choice == SPAKE_MSGTYPE_SUPPORT) { + verify_support(context, gstate, &pa_spake->u.support, &in_data, cb, + rock, respond, arg); + } else if (pa_spake->choice == SPAKE_MSGTYPE_RESPONSE) { + verify_response(context, gstate, &pa_spake->u.response, + &request->server->realm, cb, rock, enc_tkt_reply, + respond, arg); + } else if (pa_spake->choice == SPAKE_MSGTYPE_ENCDATA) { + verify_encdata(context, &pa_spake->u.encdata, cb, rock, enc_tkt_reply, + respond, arg); + } else { + ret = KRB5KDC_ERR_PREAUTH_FAILED; + k5_setmsg(context, ret, _("Unknown SPAKE request type")); + (*respond)(arg, ret, NULL, NULL, NULL); + } + + k5_free_pa_spake(context, pa_spake); +} + +krb5_error_code +kdcpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +kdcpreauth_spake_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_kdcpreauth_vtable vt; + static krb5_preauthtype pa_types[] = { KRB5_PADATA_SPAKE, 0 }; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "spake"; + vt->pa_type_list = pa_types; + vt->init = spake_init; + vt->fini = spake_fini; + vt->edata = spake_edata; + vt->verify = spake_verify; + return 0; +} diff --git a/krb5-1.21.3/src/plugins/preauth/spake/t_krb5.conf b/krb5-1.21.3/src/plugins/preauth/spake/t_krb5.conf new file mode 100644 index 00000000..65fdaec6 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/t_krb5.conf @@ -0,0 +1,2 @@ +[libdefaults] + spake_preauth_groups = edwards25519 diff --git a/krb5-1.21.3/src/plugins/preauth/spake/t_vectors.c b/krb5-1.21.3/src/plugins/preauth/spake/t_vectors.c new file mode 100644 index 00000000..2279202d --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/t_vectors.c @@ -0,0 +1,476 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/spake/t_vectors.c - SPAKE test vector verification */ +/* + * Copyright (C) 2015 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. + */ + +#include "k5-int.h" +#include "k5-hex.h" +#include "groups.h" +#include "iana.h" +#include "util.h" +#include + +struct test { + krb5_enctype enctype; + int32_t group; + const char *ikey; + const char *w; + const char *x; + const char *y; + const char *T; + const char *S; + const char *K; + const char *support; + const char *challenge; + const char *thash; + const char *body; + const char *K0; + const char *K1; + const char *K2; + const char *K3; +} tests[] = { + { ENCTYPE_DES3_CBC_SHA1, SPAKE_GROUP_EDWARDS25519, + /* initial key, w, x, y, T, S, K */ + "850BB51358548CD05E86768C313E3BFEF7511937DCF72C3E", + "686D84730CB8679AE95416C6567C6A63F2C9CEF124F7A3371AE81E11CAD42A37", + "201012D07BFD48DDFA33C4AAC4FB1E229FB0D043CFE65EBFB14399091C71A723", + "500B294797B8B042ACA1BEDC0F5931A4F52C537B3608B2D05CC8A2372F439F25", + "18F511E750C97B592ACD30DB7D9E5FCA660389102E6BF610C1BFBED4616C8362", + "5D10705E0D1E43D5DBF30240CCFBDE4A0230C70D4C79147AB0B317EDAD2F8AE7", + "25BDE0D875F0FEB5755F45BA5E857889D916ECF7476F116AA31DC3E037EC4292", + /* support, challenge, thash, body */ + "A0093007A0053003020101", + "A1363034A003020101A122042018F511E750C97B592ACD30DB7D9E5FCA660389" + "102E6BF610C1BFBED4616C8362A20930073005A003020101", + "EAAA08807D0616026FF51C849EFBF35BA0CE3C5300E7D486DA46351B13D4605B", + "3075A00703050000000000A1143012A003020101A10B30091B07726165627572" + "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018" + "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730" + "303130313030303030305AA703020100A8053003020110", + /* K'[0], K'[1], K'[2], K'[3] */ + "BAF12FAE7CD958CBF1A29BFBC71F89CE49E03E295D89DAFD", + "64F73DD9C41908206BCEC1F719026B574F9D13463D7A2520", + "0454520B086B152C455829E6BAEFF78A61DFE9E3D04A895D", + "4A92260B25E3EF94C125D5C24C3E5BCED5B37976E67F25C4", + }, + + { ENCTYPE_ARCFOUR_HMAC, SPAKE_GROUP_EDWARDS25519, + /* initial key, w, x, y, T, S, K */ + "8846F7EAEE8FB117AD06BDD830B7586C", + "7C86659D29CF2B2EA93BFE79C3CEFB8850E82215B3EA6FCD896561D48048F49C", + "C8A62E7B626F44CAD807B2D695450697E020D230A738C5CD5691CC781DCE8754", + "18FE7C1512708C7FD06DB270361F04593775BC634CEAF45347E5C11C38AAE017", + "7DB465F1C08C64983A19F560BCE966FE5306C4B447F70A5BCA14612A92DA1D63", + "38F8D4568090148EBC9FD17C241B4CC2769505A7CA6F3F7104417B72B5B5CF54", + "03E75EDD2CD7E7677642DD68736E91700953AC55DC650E3C2A1B3B4ACDB800F8", + /* support, challenge, thash, body */ + "A0093007A0053003020101", + "A1363034A003020101A12204207DB465F1C08C64983A19F560BCE966FE5306C4" + "B447F70A5BCA14612A92DA1D63A20930073005A003020101", + "F4B208458017DE6EF7F6A307D47D87DB6C2AF1D291B726860F68BC08BFEF440A", + "3075A00703050000000000A1143012A003020101A10B30091B07726165627572" + "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018" + "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730" + "303130313030303030305AA703020100A8053003020117", + /* K'[0], K'[1], K'[2], K'[3] */ + "770B720C82384CBB693E85411EEDECBA", + "621DEEC88E2865837C4D3462BB50A1D5", + "1CC8F6333B9FA3B42662FD9914FBD5BB", + "EDB4032B7FC3806D5211A534DCBC390C", + }, + + { ENCTYPE_AES128_CTS_HMAC_SHA1_96, SPAKE_GROUP_EDWARDS25519, + /* initial key, w, x, y, T, S, K */ + "FCA822951813FB252154C883F5EE1CF4", + "0D591B197B667E083C2F5F98AC891D3C9F99E710E464E62F1FB7C9B67936F3EB", + "50BE049A5A570FA1459FB9F666E6FD80602E4E87790A0E567F12438A2C96C138", + "B877AFE8612B406D96BE85BD9F19D423E95BE96C0E1E0B5824127195C3ED5917", + "9E9311D985C1355E022D7C3C694AD8D6F7AD6D647B68A90B0FE46992818002DA", + "FBE08F7F96CD5D4139E7C9ECCB95E79B8ACE41E270A60198C007DF18525B628E", + "C2F7F99997C585E6B686CEB62DB42F17CC70932DEF3BB4CF009E36F22EA5473D", + /* support, challenge, thash, body */ + "A0093007A0053003020101", + "A1363034A003020101A12204209E9311D985C1355E022D7C3C694AD8D6F7AD6D" + "647B68A90B0FE46992818002DAA20930073005A003020101", + "951285F107C87F0169B9C918A1F51F60CB1A75B9F8BB799A99F53D03ADD94B5F", + "3075A00703050000000000A1143012A003020101A10B30091B07726165627572" + "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018" + "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730" + "303130313030303030305AA703020100A8053003020111", + /* K'[0], K'[1], K'[2], K'[3] */ + "548022D58A7C47EAE8C49DCCF6BAA407", + "B2C9BA0E13FC8AB3A9D96B51B601CF4A", + "69F0EE5FDB6C237E7FCD38D9F87DF1BD", + "78F91E2240B5EE528A5CC8D7CBEBFBA5", + }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, SPAKE_GROUP_EDWARDS25519, + /* initial key, w, x, y, T, S, K */ + "01B897121D933AB44B47EB5494DB15E50EB74530DBDAE9B634D65020FF5D88C1", + "E902341590A1B4BB4D606A1C643CCCB3F2108F1B6AA97B381012B9400C9E3F4E", + "88C6C0A4F0241EF217C9788F02C32D00B72E4310748CD8FB5F94717607E6417D", + "88B859DF58EF5C69BACDFE681C582754EAAB09A74DC29CFF50B328613C232F55", + "6F301AACAE1220E91BE42868C163C5009AEEA1E9D9E28AFCFC339CDA5E7105B5", + "9E2CC32908FC46273279EC75354B4AEAFA70C3D99A4D507175ED70D80B255DDA", + "CF57F58F6E60169D2ECC8F20BB923A8E4C16E5BC95B9E64B5DC870DA7026321B", + /* support, challenge, thash, body */ + "A0093007A0053003020101", + "A1363034A003020101A12204206F301AACAE1220E91BE42868C163C5009AEEA1" + "E9D9E28AFCFC339CDA5E7105B5A20930073005A003020101", + "1C605649D4658B58CBE79A5FAF227ACC16C355C58B7DADE022F90C158FE5ED8E", + "3075A00703050000000000A1143012A003020101A10B30091B07726165627572" + "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018" + "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730" + "303130313030303030305AA703020100A8053003020112", + /* K'[0], K'[1], K'[2], K'[3] */ + "A9BFA71C95C575756F922871524B65288B3F695573CCC0633E87449568210C23", + "1865A9EE1EF0640EC28AC007391CAC624C42639C714767A974E99AA10003015F", + "E57781513FEFDB978E374E156B0DA0C1A08148F5EB26B8E157AC3C077E28BF49", + "008E6487293C3CC9FABBBCDD8B392D6DCB88222317FD7FE52D12FBC44FA047F1", + }, + +#ifdef SPAKE_OPENSSL + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, SPAKE_GROUP_P256, + /* initial key, w, x, y, T, S, K */ + "01B897121D933AB44B47EB5494DB15E50EB74530DBDAE9B634D65020FF5D88C1", + "EB2984AF18703F94DD5288B8596CD36988D0D4E83BFB2B44DE14D0E95E2090BD", + "935DDD725129FB7C6288E1A5CC45782198A6416D1775336D71EACD0549A3E80E", + "E07405EB215663ABC1F254B8ADC0DA7A16FEBAA011AF923D79FDEF7C42930B33", + "024F62078CEB53840D02612195494D0D0D88DE21FEEB81187C71CBF3D01E71788D", + "021D07DC31266FC7CFD904CE2632111A169B7EC730E5F74A7E79700F86638E13C8", + "0268489D7A9983F2FDE69C6E6A1307E9D252259264F5F2DFC32F58CCA19671E79B", + /* support, challenge, thash, body */ + "A0093007A0053003020102", + "A1373035A003020102A1230421024F62078CEB53840D02612195494D0D0D88DE" + "21FEEB81187C71CBF3D01E71788DA20930073005A003020101", + "20AD3C1A9A90FC037D1963A1C4BFB15AB4484D7B6CF07B12D24984F14652DE60", + "3075A00703050000000000A1143012A003020101A10B30091B07726165627572" + "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018" + "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730" + "303130313030303030305AA703020100A8053003020112", + /* K'[0], K'[1], K'[2], K'[3] */ + "7D3B906F7BE49932DB22CD3463F032D06C9C078BE4B1D076D201FC6E61EF531E", + "17D74E36F8993841FBB7FEB12FA4F011243D3AE4D2ACE55B39379294BBC4DB2C", + "D192C9044081A2AA6A97A6C69E2724E8E5671C2C9CE073DD439CDBAF96D7DAB0", + "41E5BAD6B67F12C53CE0E2720DD6A9887F877BF9463C2D5209C74C36F8D776B7", + }, + + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, SPAKE_GROUP_P384, + /* initial key, w, x, y, T, S, K */ + "01B897121D933AB44B47EB5494DB15E50EB74530DBDAE9B634D65020FF5D88C1", + "0304CFC55151C6BBE889653DB96DBFE0BA4ACAFC024C1E8840CB3A486F6D80C1" + "6E1B8974016AA4B7FA43042A9B3825B1", + "F323CA74D344749096FD35D0ADF20806E521460637176E84D977E9933C49D76F" + "CFC6E62585940927468FF53D864A7A50", + "5B7C709ACB175A5AFB82860DEABCA8D0B341FACDFF0AC0F1A425799AA905D750" + "7E1EA9C573581A81467437419466E472", + "02A1524603EF14F184696F854229D3397507A66C63F841BA748451056BE07879" + "AC298912387B1C5CDFF6381C264701BE57", + "020D5ADFDB92BC377041CF5837412574C5D13E0F4739208A4F0C859A0A302BC6" + "A533440A245B9D97A0D34AF5016A20053D", + "0264AA8C61DA9600DFB0BEB5E46550D63740E4EF29E73F1A30D543EB43C25499" + "037AD16538586552761B093CF0E37C703A", + /* support, challenge, thash, body */ + "A0093007A0053003020103", + "A1473045A003020103A133043102A1524603EF14F184696F854229D3397507A6" + "6C63F841BA748451056BE07879AC298912387B1C5CDFF6381C264701BE57A209" + "30073005A003020101", + "5AC0D99EF9E5A73998797FE64F074673E3952DEC4C7D1AACCE8B75F64D2B0276" + "A901CB8539B4E8ED69E4DB0CE805B47B", + "3075A00703050000000000A1143012A003020101A10B30091B07726165627572" + "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018" + "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730" + "303130313030303030305AA703020100A8053003020112", + /* K'[0], K'[1], K'[2], K'[3] */ + "B917D37C16DD1D8567FBE379F64E1EE36CA3FD127AA4E60F97E4AFA3D9E56D91", + "93D40079DAB229B9C79366829F4E7E7282E6A4B943AC7BAC69922D516673F49A", + "BFC4F16F12F683E71589F9A888E232875EF293AC9793DB6C919567CD7B94BCD4", + "3630E2B5B99938E7506733141E8EC344166F6407E5FC2EF107C156E764D1BC20", + }, + + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, SPAKE_GROUP_P521, + /* initial key, w, x, y, T, S, K */ + "01B897121D933AB44B47EB5494DB15E50EB74530DBDAE9B634D65020FF5D88C1", + "DE3A095A2B2386EFF3EB15B735398DA1CAF95BC8425665D82370AFF58B0471F3" + "4A57BCCDDF1EBF0A2965B58A93EE5B45E85D1A5435D1C8C83662999722D54283" + "1F9A", + "017C38701A14B490B6081DFC83524562BE7FBB42E0B20426465E3E37952D30BC" + "AB0ED857010255D44936A1515607964A870C7C879B741D878F9F9CDF5A865306" + "F3F5", + "003E2E2950656FA231E959ACDD984D125E7FA59CEC98126CBC8F3888447911EB" + "CD49428A1C22D5FDB76A19FBEB1D9EDFA3DA6CF55B158B53031D05D51433ADE9" + "B2B4", + "02017D3DE19A3EC53D0174905665EF37947D142535102CD9809C0DFBD0DFE007" + "353D54CF406CE2A59950F2BB540DF6FBE75F8BBBEF811C9BA06CC275ADBD9675" + "6696EC", + "02004D142D87477841F6BA053C8F651F3395AD264B7405CA5911FB9A55ABD454" + "FEF658A5F9ED97D1EFAC68764E9092FA15B9E0050880D78E95FD03ABF5931791" + "6822B5", + "03007C303F62F09282CC849490805BD4457A6793A832CBEB55DF427DB6A31E99" + "B055D5DC99756D24D47B70AD8B6015B0FB8742A718462ED423B90FA3FE631AC1" + "3FA916", + /* support, challenge, thash, body */ + "A0093007A0053003020104", + "A1593057A003020104A145044302017D3DE19A3EC53D0174905665EF37947D14" + "2535102CD9809C0DFBD0DFE007353D54CF406CE2A59950F2BB540DF6FBE75F8B" + "BBEF811C9BA06CC275ADBD96756696ECA20930073005A003020101", + "8D6A89AE4D80CC4E47B6F4E48EA3E57919CC69598D0D3DC7C8BD49B6F1DB1409" + "CA0312944CD964E213ABA98537041102237CFF5B331E5347A0673869B412302E", + "3075A00703050000000000A1143012A003020101A10B30091B07726165627572" + "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018" + "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730" + "303130313030303030305AA703020100A8053003020112", + /* K'[0], K'[1], K'[2], K'[3] */ + "1EB3D10BEE8FAB483ADCD3EB38F3EBF1F4FEB8DB96ECC035F563CF2E1115D276", + "482B92781CE57F49176E4C94153CC622FE247A7DBE931D1478315F856F085890", + "A2C215126DD3DF280AAB5A27E1E0FB7E594192CBFF8D6D8E1B6F1818D9BB8FAC", + "CC06603DE984324013A01F888DE6D43B410A4DA2DEA53509F30E433C352FB668", + }, +#endif /* SPAKE_OPENSSL */ + + /* Successful optimistic challenge (no support message in transcript) */ + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, SPAKE_GROUP_EDWARDS25519, + /* initial key, w, x, y, T, S, K */ + "01B897121D933AB44B47EB5494DB15E50EB74530DBDAE9B634D65020FF5D88C1", + "E902341590A1B4BB4D606A1C643CCCB3F2108F1B6AA97B381012B9400C9E3F4E", + "70937207344CAFBC53C8A55070E399C584CBAFCE00B836980DD4E7E74FAD2A64", + "785D6801A2490DF028903AC6449B105F2FF0DB895B252953CDC2076649526103", + "83523B35F1565006CBFC4F159885467C2FB9BC6FE23D36CB1DA43D199F1A3118", + "2A8F70F46CEE9030700037B77F22CEC7970DCC238E3E066D9D726BAF183992C6", + "D3C5E4266AA6D1B2873A97CE8AF91C7E4D7A7AC456ACCED7908D34C561AD8FA6", + /* support, challenge, thash, body */ + NULL, + "A1363034A003020101A122042083523B35F1565006CBFC4F159885467C2FB9BC" + "6FE23D36CB1DA43D199F1A3118A20930073005A003020101", + "26F07F9F8965307434D11EA855461D41E0CBABCC0A1BAB48ECEE0C6C1A4292B7", + "3075A00703050000000000A1143012A003020101A10B30091B07726165627572" + "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018" + "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730" + "303130313030303030305AA703020100A8053003020112", + /* K'[0], K'[1], K'[2], K'[3] */ + "4569EC08B5DE5C3CC19D941725913ACE8D74524B521A341DC746ACD5C3784D92", + "0D96CE1A4AC0F2E280A0CFC31742B06461D83D04AE45433DB2D80478DD882A4C", + "58018C19315A1BA5D5BB9813B58029F0AEC18A6F9CA59E0847DE1C60BC25945C", + "ED7E9BFFD68C54D86FB19CD3C03F317F88A71AD9A5E94C28581D93FC4EC72B6A", + }, + +#ifdef SPAKE_OPENSSL + /* Rejected optimistic challenge (no support message in transcript), + * falling back from edwards25519 to P-521 */ + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, SPAKE_GROUP_P521, + /* initial key, w, x, y, T, S, K */ + "01B897121D933AB44B47EB5494DB15E50EB74530DBDAE9B634D65020FF5D88C1", + "DE3A095A2B2386EFF3EB15B735398DA1CAF95BC8425665D82370AFF58B0471F3" + "4A57BCCDDF1EBF0A2965B58A93EE5B45E85D1A5435D1C8C83662999722D54283" + "1F9A", + "01687B59051BF40048D7C31D5A973D792FA12284B7A447E7F5938B5885CA0BB2" + "C3F0BD30291A55FEA08E143E2E04BDD7D19B753C7C99032F06CAB0D9C2AA8F83" + "7EF7", + "01DED675EBF74FE30C9A53710F577E9CF84F09F6048FE245A4600004884CC167" + "733F9A9E43108FB83BABE8754CD37CBD7025E28BC9FF870F084C7244F536285E" + "25B4", + "02014CB2E5B592ECE5990F0EF30D308C061DE1598BC4272B4A6599BED466FD15" + "21693642ABCF4DBE36CE1A2D13967DE45F6C4F8D0FA8E14428BF03FB96EF5F1E" + "D3E645", + "02016C64995E804416F748FD5FA3AA678CBC7CBB596A4F523132DC8AF7CE84E5" + "41F484A2C74808C6B21DCF7775BAEFA6753398425BECC7B838B210AC5DAA0CB0" + "B710E2", + "0200997F4848AE2E7A98C23D14AC662030743AB37FCCC2A45F1C721114F40BCC" + "80FE6EC6ABA49868F8AEA1AA994D50E81B86D3E4D3C1130C8695B68907C673D9" + "E5886A", + /* support, challenge, thash, body */ + "A0093007A0053003020104", + "A1593057A003020104A145044302014CB2E5B592ECE5990F0EF30D308C061DE1" + "598BC4272B4A6599BED466FD1521693642ABCF4DBE36CE1A2D13967DE45F6C4F" + "8D0FA8E14428BF03FB96EF5F1ED3E645A20930073005A003020101", + "D0EFED5E3E2C39C26034756D92A66FEC3082AD793D0197F3F89AD36026F146A3" + "996E548AA3FC49E2E82F8CAC5D132C505AA475B39E7BE79CDED22C26C41AA777", + "3075A00703050000000000A1143012A003020101A10B30091B07726165627572" + "6EA2101B0E415448454E412E4D49542E454455A3233021A003020102A11A3018" + "1B066B72627467741B0E415448454E412E4D49542E454455A511180F31393730" + "303130313030303030305AA703020100A8053003020112", + /* K'[0], K'[1], K'[2], K'[3] */ + "631FCC8596E7F40E59045950D72AA0B7BAC2810A07B767050E983841CF3A2D4C", + "881464920117074DBC67155A8F3341D1121EF65F78EA0380BFA81A134C1C47B1", + "377B72AC3AF2CAAD582D73AE4682FD56B531EE56706200DD6C38C42B8219837A", + "35AD8E4D580ED3F0D15AD928329773C081BD19F9A56363F3A5F77C7E66108C26", + }, +#endif /* SPAKE_OPENSSL */ +}; + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + assert(errmsg != NULL); + abort(); + } +} + +static void +check_key_equal(const krb5_keyblock *kb1, const krb5_keyblock *kb2) +{ + assert(kb1->enctype == kb2->enctype); + assert(kb1->length == kb2->length); + assert(memcmp(kb1->contents, kb2->contents, kb1->length) == 0); +} + +static krb5_data * +decode_data(const char *s) +{ + uint8_t *bytes; + size_t len; + krb5_data *d; + + if (k5_hex_decode(s, &bytes, &len) != 0) + abort(); + d = malloc(sizeof(*d)); + assert(d != NULL); + *d = make_data(bytes, len); + return d; +} + +static krb5_keyblock * +decode_keyblock(krb5_enctype enctype, const char *s) +{ + uint8_t *bytes; + size_t len; + krb5_keyblock *kb; + + if (k5_hex_decode(s, &bytes, &len) != 0) + abort(); + kb = malloc(sizeof(*kb)); + kb->magic = KV5M_KEYBLOCK; + kb->enctype = enctype; + kb->length = len; + kb->contents = bytes; + return kb; +} + +static void +run_test(const struct test *t) +{ + groupstate *gstate; + krb5_keyblock *ikey, *K0, *K1, *K2, *K3, *kb; + krb5_data *w, *x, *y, *T, *S, *K, *support, *challenge, *thash; + krb5_data *body, wbytes, result, hash, empty = empty_data(); + + /* Decode hex strings into keyblocks and byte strings. */ + ikey = decode_keyblock(t->enctype, t->ikey); + w = decode_data(t->w); + x = decode_data(t->x); + y = decode_data(t->y); + T = decode_data(t->T); + S = decode_data(t->S); + K = decode_data(t->K); + support = (t->support != NULL) ? decode_data(t->support) : NULL; + challenge = decode_data(t->challenge); + thash = decode_data(t->thash); + body = decode_data(t->body); + K0 = decode_keyblock(t->enctype, t->K0); + K1 = decode_keyblock(t->enctype, t->K1); + K2 = decode_keyblock(t->enctype, t->K2); + K3 = decode_keyblock(t->enctype, t->K3); + + check(derive_wbytes(ctx, t->group, ikey, &wbytes)); + assert(data_eq(*w, wbytes)); + + /* Verify KDC-side result computation. */ + check(group_init_state(ctx, TRUE, &gstate)); + check(group_result(ctx, gstate, t->group, &wbytes, x, S, &result)); + assert(data_eq(*K, result)); + krb5_free_data_contents(ctx, &result); + group_free_state(gstate); + + /* Verify client-side result computation. */ + check(group_init_state(ctx, FALSE, &gstate)); + check(group_result(ctx, gstate, t->group, &wbytes, y, T, &result)); + assert(data_eq(*K, result)); + krb5_free_data_contents(ctx, &result); + + /* Verify transcript hash. */ + hash = empty_data(); + check(update_thash(ctx, gstate, t->group, &hash, support, challenge)); + check(update_thash(ctx, gstate, t->group, &hash, S, &empty)); + assert(data_eq(*thash, hash)); + krb5_free_data_contents(ctx, &hash); + + /* Verify derived keys. */ + check(derive_key(ctx, gstate, t->group, ikey, &wbytes, K, thash, body, 0, + &kb)); + check_key_equal(K0, kb); + krb5_free_keyblock(ctx, kb); + check(derive_key(ctx, gstate, t->group, ikey, &wbytes, K, thash, body, 1, + &kb)); + check_key_equal(K1, kb); + krb5_free_keyblock(ctx, kb); + check(derive_key(ctx, gstate, t->group, ikey, &wbytes, K, thash, body, 2, + &kb)); + check_key_equal(K2, kb); + krb5_free_keyblock(ctx, kb); + check(derive_key(ctx, gstate, t->group, ikey, &wbytes, K, thash, body, 3, + &kb)); + check_key_equal(K3, kb); + krb5_free_keyblock(ctx, kb); + + group_free_state(gstate); + krb5_free_data_contents(ctx, &wbytes); + krb5_free_keyblock(ctx, ikey); + krb5_free_data(ctx, w); + krb5_free_data(ctx, x); + krb5_free_data(ctx, y); + krb5_free_data(ctx, T); + krb5_free_data(ctx, S); + krb5_free_data(ctx, K); + krb5_free_data(ctx, support); + krb5_free_data(ctx, challenge); + krb5_free_data(ctx, thash); + krb5_free_data(ctx, body); + krb5_free_keyblock(ctx, K0); + krb5_free_keyblock(ctx, K1); + krb5_free_keyblock(ctx, K2); + krb5_free_keyblock(ctx, K3); +} + +int +main() +{ + size_t i; + + check(krb5_init_context(&ctx)); + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) + run_test(&tests[i]); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/plugins/preauth/spake/trace.h b/krb5-1.21.3/src/plugins/preauth/spake/trace.h new file mode 100644 index 00000000..c6e01087 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/trace.h @@ -0,0 +1,74 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/spake/internal.h - SPAKE internal function declarations */ +/* + * Copyright (C) 2015 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. + */ + +#ifndef TRACE_H +#define TRACE_H + +#include "k5-int.h" + +/* + * Possible improvements at the cost of more code: + * - Groups could be displayed by name instead of number + * - We could display the group list when tracing support messages + */ + +#define TRACE_SPAKE_CLIENT_THASH(c, thash) \ + TRACE(c, "SPAKE final transcript hash: {hexdata}", thash) +#define TRACE_SPAKE_DERIVE_KEY(c, n, kb) \ + TRACE(c, "SPAKE derived K'[{int}] = {keyblock}", n, kb) +#define TRACE_SPAKE_KDC_THASH(c, thash) \ + TRACE(c, "SPAKE final transcript hash: {hexdata}", thash) +#define TRACE_SPAKE_KEYGEN(c, pubkey) \ + TRACE(c, "SPAKE key generated with pubkey {hexdata}", pubkey) +#define TRACE_SPAKE_RECEIVE_CHALLENGE(c, group, pubkey) \ + TRACE(c, "SPAKE challenge received with group {int}, pubkey {hexdata}", \ + group, pubkey) +#define TRACE_SPAKE_RECEIVE_RESPONSE(c, pubkey) \ + TRACE(c, "SPAKE response received with pubkey {hexdata}", pubkey) +#define TRACE_SPAKE_RECEIVE_SUPPORT(c, group) \ + TRACE(c, "SPAKE support message received, selected group {int}", group) +#define TRACE_SPAKE_REJECT_CHALLENGE(c, group) \ + TRACE(c, "SPAKE challenge with group {int} rejected", (int)group) +#define TRACE_SPAKE_REJECT_SUPPORT(c) \ + TRACE(c, "SPAKE support message rejected") +#define TRACE_SPAKE_RESULT(c, result) \ + TRACE(c, "SPAKE algorithm result: {hexdata}", result) +#define TRACE_SPAKE_SEND_CHALLENGE(c, group) \ + TRACE(c, "Sending SPAKE challenge with group {int}", group) +#define TRACE_SPAKE_SEND_RESPONSE(c) \ + TRACE(c, "Sending SPAKE response") +#define TRACE_SPAKE_SEND_SUPPORT(c) \ + TRACE(c, "Sending SPAKE support message") +#define TRACE_SPAKE_UNKNOWN_GROUP(c, name) \ + TRACE(c, "Unrecognized SPAKE group name: {str}", name) + +#endif /* TRACE_H */ diff --git a/krb5-1.21.3/src/plugins/preauth/spake/util.c b/krb5-1.21.3/src/plugins/preauth/spake/util.c new file mode 100644 index 00000000..b72ae67f --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/util.c @@ -0,0 +1,212 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/spake/util.c - Utility functions for SPAKE preauth module */ +/* + * Copyright (C) 2015 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. + */ + +#include "k5-int.h" +#include "trace.h" +#include "util.h" +#include "groups.h" + +/* Use data to construct a single-element pa-data list of type + * KRB5_PADATA_SPAKE. Claim data's memory on success or failure. */ +krb5_error_code +convert_to_padata(krb5_data *data, krb5_pa_data ***pa_out) +{ + krb5_pa_data *pa = NULL, **list = NULL; + + list = calloc(2, sizeof(*list)); + if (list == NULL) + goto fail; + pa = calloc(1, sizeof(*pa)); + if (pa == NULL) + goto fail; + pa->magic = KV5M_PA_DATA; + pa->pa_type = KRB5_PADATA_SPAKE; + pa->length = data->length; + pa->contents = (uint8_t *)data->data; + list[0] = pa; + list[1] = NULL; + *pa_out = list; + free(data); + return 0; + +fail: + free(list); + free(pa); + free(data->data); + free(data); + return ENOMEM; +} + +/* + * Update the transcript hash thash with its current value and the + * concatenation of data1 and data2, using the hash function for group. Either + * data1 or data2 may be NULL to omit it. Allocate thash if it is empty. + */ +krb5_error_code +update_thash(krb5_context context, groupstate *gstate, int32_t group, + krb5_data *thash, const krb5_data *data1, const krb5_data *data2) +{ + krb5_error_code ret; + size_t hashlen; + krb5_data dlist[3]; + const krb5_data empty = empty_data(); + + if (thash->length == 0) { + /* Initialize the transcript hash to all zeros. */ + ret = group_hash_len(group, &hashlen); + if (ret) + return ret; + ret = alloc_data(thash, hashlen); + if (ret) + return ret; + } + + /* Set up the data array and hash it with the group's hash function. */ + dlist[0] = *thash; + dlist[1] = (data1 != NULL) ? *data1 : empty; + dlist[2] = (data2 != NULL) ? *data2 : empty; + return group_hash(context, gstate, group, dlist, 3, + (uint8_t *)thash->data); +} + +/* Derive a byte vector for the SPAKE w multiplier input from ikey. Place + * result in allocated storage in *wbytes_out. */ +krb5_error_code +derive_wbytes(krb5_context context, int32_t group, const krb5_keyblock *ikey, + krb5_data *wbytes_out) +{ + krb5_error_code ret; + const char prefix[] = "SPAKEsecret"; + size_t mult_len, prefix_len = sizeof(prefix) - 1; + krb5_data prf_input = empty_data(), wbytes = empty_data(); + + *wbytes_out = empty_data(); + + /* Allocate space for a multiplier. */ + ret = group_mult_len(group, &mult_len); + if (ret) + goto cleanup; + ret = alloc_data(&wbytes, mult_len); + if (ret) + goto cleanup; + + /* Compose the PRF input string. */ + ret = alloc_data(&prf_input, prefix_len + 4); + if (ret) + goto cleanup; + memcpy(prf_input.data, prefix, prefix_len); + store_32_be(group, prf_input.data + prefix_len); + + /* Derive the SPAKE input from the initial reply key with PRF+. */ + ret = krb5_c_prfplus(context, ikey, &prf_input, &wbytes); + if (ret) + goto cleanup; + + *wbytes_out = wbytes; + wbytes = empty_data(); + +cleanup: + free(prf_input.data); + zapfree(wbytes.data, wbytes.length); + return ret; +} + +/* + * Derive K'[n] from the group number, the initial key enctype, the initial + * multiplier, the SPAKE result, the transcript hash, and the encoded + * KDC-REQ-BODY. Place the result in allocated storage in *out. + */ +krb5_error_code +derive_key(krb5_context context, groupstate *gstate, int32_t group, + const krb5_keyblock *ikey, const krb5_data *wbytes, + const krb5_data *spakeresult, const krb5_data *thash, + const krb5_data *der_req, uint32_t n, krb5_keyblock **out) +{ + krb5_error_code ret; + krb5_data dlist[9], seed = empty_data(), d; + uint8_t groupnbuf[4], etypenbuf[4], nbuf[4], bcount; + size_t hashlen, seedlen, keylen, nblocks, i; + size_t ndata = sizeof(dlist) / sizeof(*dlist); + krb5_keyblock *hkey = NULL; + + *out = NULL; + + store_32_be(group, groupnbuf); + store_32_be(n, nbuf); + store_32_be(ikey->enctype, etypenbuf); + dlist[0] = string2data("SPAKEkey"); + dlist[1] = make_data(groupnbuf, sizeof(groupnbuf)); + dlist[2] = make_data(etypenbuf, sizeof(etypenbuf)); + dlist[3] = *wbytes; + dlist[4] = *spakeresult; + dlist[5] = *thash; + dlist[6] = *der_req; + dlist[7] = make_data(nbuf, sizeof(nbuf)); + dlist[8] = make_data(&bcount, 1); + + /* Count the number of hash blocks required (should be 1 for all current + * scenarios) and allocate space. */ + ret = group_hash_len(group, &hashlen); + if (ret) + goto cleanup; + ret = krb5_c_keylengths(context, ikey->enctype, &seedlen, &keylen); + if (ret) + goto cleanup; + nblocks = (seedlen + hashlen - 1) / hashlen; + ret = alloc_data(&seed, nblocks * hashlen); + if (ret) + goto cleanup; + + /* Compute and concatenate hash blocks to fill the seed buffer. */ + for (i = 0; i < nblocks; i++) { + bcount = i + 1; + ret = group_hash(context, gstate, group, dlist, ndata, + (uint8_t *)seed.data + i * hashlen); + if (ret) + goto cleanup; + } + + ret = krb5_init_keyblock(context, ikey->enctype, keylen, &hkey); + if (ret) + goto cleanup; + d = make_data(seed.data, seedlen); + ret = krb5_c_random_to_key(context, ikey->enctype, &d, hkey); + if (ret) + goto cleanup; + + ret = krb5_c_fx_cf2_simple(context, ikey, "SPAKE", hkey, "keyderiv", out); + +cleanup: + zapfree(seed.data, seed.length); + krb5_free_keyblock(context, hkey); + return ret; +} diff --git a/krb5-1.21.3/src/plugins/preauth/spake/util.h b/krb5-1.21.3/src/plugins/preauth/spake/util.h new file mode 100644 index 00000000..3ab2bead --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/spake/util.h @@ -0,0 +1,56 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/spake/internal.h - SPAKE internal function declarations */ +/* + * Copyright (C) 2015 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. + */ + +#ifndef UTIL_H +#define UTIL_H + +#include "k5-int.h" +#include "groups.h" + +krb5_error_code convert_to_padata(krb5_data *data, krb5_pa_data ***pa_out); + +krb5_error_code update_thash(krb5_context context, groupstate *gstate, + int32_t group, krb5_data *thash, + const krb5_data *data1, const krb5_data *data2); + +krb5_error_code derive_wbytes(krb5_context context, int32_t group, + const krb5_keyblock *ikey, + krb5_data *wbytes_out); + +krb5_error_code derive_key(krb5_context context, groupstate *gstate, + int32_t group, const krb5_keyblock *ikey, + const krb5_data *wbytes, + const krb5_data *spakeresult, + const krb5_data *thash, const krb5_data *der_req, + uint32_t n, krb5_keyblock **out); + +#endif /* UTIL_H */ diff --git a/krb5-1.21.3/src/plugins/preauth/test/Makefile.in b/krb5-1.21.3/src/plugins/preauth/test/Makefile.in new file mode 100644 index 00000000..77321b60 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/test/Makefile.in @@ -0,0 +1,21 @@ +mydir=plugins$(S)preauth$(S)test +BUILDTOP=$(REL)..$(S)..$(S).. +MODULE_INSTALL_DIR = $(KRB5_PA_MODULE_DIR) + +LIBBASE=test +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/preauth/test +SHLIB_EXPDEPS=$(KRB5_BASE_DEPLIBS) +SHLIB_EXPLIBS=$(KRB5_BASE_LIBS) + +STLIBOBJS=cltest.o kdctest.o common.o + +SRCS= $(srcdir)/cltest.c $(srcdir)/kdctest.c $(srcdir)/common.c + +all-unix: all-liblinks +install-unix: install-libs +clean-unix:: clean-liblinks clean-libs clean-libobjs + +@libnover_frag@ +@libobj_frag@ diff --git a/krb5-1.21.3/src/plugins/preauth/test/cltest.c b/krb5-1.21.3/src/plugins/preauth/test/cltest.c new file mode 100644 index 00000000..51b84848 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/test/cltest.c @@ -0,0 +1,253 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/test/cltest.c - Test clpreauth module */ +/* + * Copyright (C) 2015, 2017 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. + */ + +/* + * This module is used to test preauth interface features. At this time, the + * clpreauth module does the following: + * + * - It decrypts a message from the initial KDC pa-data using the reply key and + * prints it to stdout. (The unencrypted message "no key" can also be + * displayed.) + * + * - If a second round trip is requested, it prints the pa-data contents + * accompanying the second round trip request. + * + * - It pulls an "indicators" attribute from the gic preauth options and sends + * it to the server, instructing the kdcpreauth module to assert one or more + * space-separated authentication indicators. (This string is sent on both + * round trips if a second round trip is requested.) + * + * - If a KDC_ERR_ENCTYPE_NOSUPP error with e-data is received, it prints the + * accompanying error padata and sends a follow-up request containing + * "tryagain". + * + * - If the "fail_optimistic", "fail_2rt", or "fail_tryagain" gic options are + * set, it fails with a recognizable error string at the requested point in + * processing. + * + * - If the "disable_fallback" gic option is set, fallback is disabled when a + * client message is generated. + */ + +#include "k5-int.h" +#include +#include "common.h" + +static krb5_preauthtype pa_types[] = { TEST_PA_TYPE, 0 }; + +struct client_state { + char *indicators; + krb5_boolean fail_optimistic; + krb5_boolean fail_2rt; + krb5_boolean fail_tryagain; + krb5_boolean disable_fallback; +}; + +struct client_request_state { + krb5_boolean second_round_trip; +}; + +static krb5_error_code +test_init(krb5_context context, krb5_clpreauth_moddata *moddata_out) +{ + struct client_state *st; + + st = malloc(sizeof(*st)); + assert(st != NULL); + st->indicators = NULL; + st->fail_optimistic = st->fail_2rt = st->fail_tryagain = FALSE; + st->disable_fallback = FALSE; + *moddata_out = (krb5_clpreauth_moddata)st; + return 0; +} + +static void +test_fini(krb5_context context, krb5_clpreauth_moddata moddata) +{ + struct client_state *st = (struct client_state *)moddata; + + free(st->indicators); + free(st); +} + +static void +test_request_init(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq *modreq_out) +{ + struct client_request_state *reqst; + + reqst = malloc(sizeof(*reqst)); + assert(reqst != NULL); + reqst->second_round_trip = FALSE; + *modreq_out = (krb5_clpreauth_modreq)reqst; +} + +static void +test_request_fini(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq) +{ + free(modreq); +} + +static krb5_error_code +test_process(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_kdc_req *request, krb5_data *encoded_request_body, + krb5_data *encoded_previous_request, krb5_pa_data *pa_data, + krb5_prompter_fct prompter, void *prompter_data, + krb5_pa_data ***out_pa_data) +{ + struct client_state *st = (struct client_state *)moddata; + struct client_request_state *reqst = (struct client_request_state *)modreq; + krb5_error_code ret; + krb5_keyblock *k; + krb5_enc_data enc; + krb5_data plain; + const char *indstr; + + if (pa_data->length == 0) { + /* This is an optimistic preauth test. Send a recognizable padata + * value so the KDC knows not to expect a cookie. */ + if (st->fail_optimistic) { + k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced optimistic fail"); + return KRB5_PREAUTH_FAILED; + } + *out_pa_data = make_pa_list("optimistic", 10); + if (st->disable_fallback) + cb->disable_fallback(context, rock); + return 0; + } else if (reqst->second_round_trip) { + printf("2rt: %.*s\n", pa_data->length, pa_data->contents); + if (st->fail_2rt) { + k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced 2rt fail"); + return KRB5_PREAUTH_FAILED; + } + } else if (pa_data->length == 6 && + memcmp(pa_data->contents, "no key", 6) == 0) { + printf("no key\n"); + } else { + /* This fails during s4u_identify_user(), so don't assert. */ + ret = cb->get_as_key(context, rock, &k); + if (ret) + return ret; + ret = alloc_data(&plain, pa_data->length); + assert(!ret); + enc.enctype = k->enctype; + enc.ciphertext = make_data(pa_data->contents, pa_data->length); + ret = krb5_c_decrypt(context, k, 1024, NULL, &enc, &plain); + assert(!ret); + printf("%.*s\n", plain.length, plain.data); + free(plain.data); + } + reqst->second_round_trip = TRUE; + + indstr = (st->indicators != NULL) ? st->indicators : ""; + *out_pa_data = make_pa_list(indstr, strlen(indstr)); + if (st->disable_fallback) + cb->disable_fallback(context, rock); + return 0; +} + +static krb5_error_code +test_tryagain(krb5_context context, krb5_clpreauth_moddata moddata, + krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt, + krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock, + krb5_kdc_req *request, krb5_data *enc_req, krb5_data *enc_prev, + krb5_preauthtype pa_type, krb5_error *error, + krb5_pa_data **padata, krb5_prompter_fct prompter, + void *prompter_data, krb5_pa_data ***padata_out) +{ + struct client_state *st = (struct client_state *)moddata; + int i; + + *padata_out = NULL; + if (st->fail_tryagain) { + k5_setmsg(context, KRB5_PREAUTH_FAILED, "induced tryagain fail"); + return KRB5_PREAUTH_FAILED; + } + if (error->error != KDC_ERR_ENCTYPE_NOSUPP) + return KRB5_PREAUTH_FAILED; + for (i = 0; padata[i] != NULL; i++) { + if (padata[i]->pa_type == TEST_PA_TYPE) + printf("tryagain: %.*s\n", padata[i]->length, padata[i]->contents); + } + *padata_out = make_pa_list("tryagain", 8); + return 0; +} + +static krb5_error_code +test_gic_opt(krb5_context kcontext, krb5_clpreauth_moddata moddata, + krb5_get_init_creds_opt *opt, const char *attr, const char *value) +{ + struct client_state *st = (struct client_state *)moddata; + + if (strcmp(attr, "indicators") == 0) { + free(st->indicators); + st->indicators = strdup(value); + assert(st->indicators != NULL); + } else if (strcmp(attr, "fail_optimistic") == 0) { + st->fail_optimistic = TRUE; + } else if (strcmp(attr, "fail_2rt") == 0) { + st->fail_2rt = TRUE; + } else if (strcmp(attr, "fail_tryagain") == 0) { + st->fail_tryagain = TRUE; + } else if (strcmp(attr, "disable_fallback") == 0) { + st->disable_fallback = TRUE; + } + return 0; +} + +krb5_error_code +clpreauth_test_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); + +krb5_error_code +clpreauth_test_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) +{ + krb5_clpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_clpreauth_vtable)vtable; + vt->name = "test"; + vt->pa_type_list = pa_types; + vt->init = test_init; + vt->fini = test_fini; + vt->request_init = test_request_init; + vt->request_fini = test_request_fini; + vt->process = test_process; + vt->tryagain = test_tryagain; + vt->gic_opts = test_gic_opt; + return 0; +} diff --git a/krb5-1.21.3/src/plugins/preauth/test/common.c b/krb5-1.21.3/src/plugins/preauth/test/common.c new file mode 100644 index 00000000..4d1f49df --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/test/common.c @@ -0,0 +1,61 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/test/common.c - common functions for test preauth module */ +/* + * Copyright (C) 2017 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. + */ + +#include "k5-int.h" +#include "common.h" + +krb5_pa_data * +make_pa(const char *contents, size_t len) +{ + krb5_error_code ret; + krb5_pa_data *pa; + + pa = calloc(1, sizeof(*pa)); + assert(pa != NULL); + pa->pa_type = TEST_PA_TYPE; + pa->contents = k5memdup(contents, len, &ret); + assert(!ret); + pa->length = len; + return pa; +} + +/* Make a one-element padata list of type TEST_PA_TYPE. */ +krb5_pa_data ** +make_pa_list(const char *contents, size_t len) +{ + krb5_pa_data **list; + + list = calloc(2, sizeof(*list)); + assert(list != NULL); + list[0] = make_pa(contents, len); + return list; +} diff --git a/krb5-1.21.3/src/plugins/preauth/test/common.h b/krb5-1.21.3/src/plugins/preauth/test/common.h new file mode 100644 index 00000000..b748e087 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/test/common.h @@ -0,0 +1,41 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/test/common.h - Declarations for test preauth module */ +/* + * Copyright (C) 2017 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. + */ + +#ifndef COMMON_H +#define COMMON_H + +#define TEST_PA_TYPE -123 + +krb5_pa_data *make_pa(const char *contents, size_t len); +krb5_pa_data **make_pa_list(const char *contents, size_t len); + +#endif /* COMMON_H */ diff --git a/krb5-1.21.3/src/plugins/preauth/test/deps b/krb5-1.21.3/src/plugins/preauth/test/deps new file mode 100644 index 00000000..b1429e9e --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/test/deps @@ -0,0 +1,35 @@ +# +# Generated makefile dependencies follow. +# +cltest.so cltest.po $(OUTPRE)cltest.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/clpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + cltest.c common.h +kdctest.so kdctest.po $(OUTPRE)kdctest.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/kdcpreauth_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + common.h kdctest.c +common.so common.po $(OUTPRE)common.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h common.c common.h diff --git a/krb5-1.21.3/src/plugins/preauth/test/kdctest.c b/krb5-1.21.3/src/plugins/preauth/test/kdctest.c new file mode 100644 index 00000000..66b77969 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/test/kdctest.c @@ -0,0 +1,220 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/preauth/test/kdctest.c - Test kdcpreauth module */ +/* + * Copyright (C) 2015, 2017 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. + */ + +/* + * This module is used to test preauth interface features. Currently, the + * kdcpreauth module does the following: + * + * - When generating initial method-data, it retrieves the "teststring" + * attribute from the client principal and sends it to the client, encrypted + * in the reply key. (The plain text "no key" is sent if there is no reply + * key; the encrypted message "no attr" is sent if there is no string + * attribute.) It also sets a cookie containing "method-data". + * + * - If the "err" attribute is set on the client principal, the verify method + * returns an KDC_ERR_ETYPE_NOSUPP error on the first try, with the contents + * of the err attribute as pa-data. If the client tries again with the + * padata value "tryagain", the verify method preuthenticates successfully + * with no additional processing. + * + * - If the "failopt" attribute is set on the client principal, the verify + * method returns KDC_ERR_PREAUTH_FAILED on optimistic preauth attempts. + * + * - If the "2rt" attribute is set on client principal, the verify method sends + * the client a KDC_ERR_MORE_PREAUTH_DATA_REQUIRED error with the contents of + * the 2rt attribute as pa-data, and sets a cookie containing "more". If the + * "fail2rt" attribute is set on the client principal, the client's second + * try results in a KDC_ERR_PREAUTH_FAILED error. + * + * - It receives a space-separated list from the clpreauth module and asserts + * each string as an authentication indicator. It always succeeds in + * pre-authenticating the request. + */ + +#include "k5-int.h" +#include +#include "common.h" + +#define TEST_PA_TYPE -123 + +static krb5_preauthtype pa_types[] = { TEST_PA_TYPE, 0 }; + +static void +test_edata(krb5_context context, krb5_kdc_req *req, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type, + krb5_kdcpreauth_edata_respond_fn respond, void *arg) +{ + krb5_error_code ret; + const krb5_keyblock *k = cb->client_keyblock(context, rock); + krb5_pa_data *pa; + size_t enclen; + krb5_enc_data enc; + krb5_data d; + char *attr; + + ret = cb->get_string(context, rock, "teststring", &attr); + assert(!ret); + if (k != NULL) { + d = string2data((attr != NULL) ? attr : "no attr"); + ret = krb5_c_encrypt_length(context, k->enctype, d.length, &enclen); + assert(!ret); + ret = alloc_data(&enc.ciphertext, enclen); + assert(!ret); + ret = krb5_c_encrypt(context, k, 1024, NULL, &d, &enc); + assert(!ret); + pa = make_pa(enc.ciphertext.data, enc.ciphertext.length); + free(enc.ciphertext.data); + } else { + pa = make_pa("no key", 6); + } + + /* Exercise setting a cookie information from the edata method. */ + d = string2data("method-data"); + ret = cb->set_cookie(context, rock, TEST_PA_TYPE, &d); + assert(!ret); + + cb->free_string(context, rock, attr); + (*respond)(arg, 0, pa); +} + +static void +test_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, + krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *data, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, + krb5_kdcpreauth_verify_respond_fn respond, void *arg) +{ + krb5_error_code ret; + krb5_boolean second_round_trip = FALSE, optimistic = FALSE; + krb5_pa_data **list = NULL; + krb5_data cookie_data, d; + char *str, *ind, *toksave = NULL; + char *attr_err, *attr_2rt, *attr_fail2rt, *attr_failopt; + + ret = cb->get_string(context, rock, "err", &attr_err); + assert(!ret); + ret = cb->get_string(context, rock, "2rt", &attr_2rt); + assert(!ret); + ret = cb->get_string(context, rock, "fail2rt", &attr_fail2rt); + assert(!ret); + ret = cb->get_string(context, rock, "failopt", &attr_failopt); + assert(!ret); + + /* Check the incoming cookie value. */ + if (!cb->get_cookie(context, rock, TEST_PA_TYPE, &cookie_data)) { + /* Make sure we are seeing optimistic preauth and not a lost cookie. */ + d = make_data(data->contents, data->length); + assert(data_eq_string(d, "optimistic")); + optimistic = TRUE; + } else if (data_eq_string(cookie_data, "more")) { + second_round_trip = TRUE; + } else { + assert(data_eq_string(cookie_data, "method-data") || + data_eq_string(cookie_data, "err")); + } + + if (attr_err != NULL) { + d = make_data(data->contents, data->length); + if (data_eq_string(d, "tryagain")) { + /* Authenticate successfully. */ + enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; + } else { + d = string2data("err"); + ret = cb->set_cookie(context, rock, TEST_PA_TYPE, &d); + assert(!ret); + ret = KRB5KDC_ERR_ETYPE_NOSUPP; + list = make_pa_list(attr_err, strlen(attr_err)); + } + } else if (attr_2rt != NULL && !second_round_trip) { + d = string2data("more"); + ret = cb->set_cookie(context, rock, TEST_PA_TYPE, &d); + assert(!ret); + ret = KRB5KDC_ERR_MORE_PREAUTH_DATA_REQUIRED; + list = make_pa_list(attr_2rt, strlen(attr_2rt)); + } else if ((attr_fail2rt != NULL && second_round_trip) || + (attr_failopt != NULL && optimistic)) { + ret = KRB5KDC_ERR_PREAUTH_FAILED; + } else { + /* Parse and assert the indicators. */ + str = k5memdup0(data->contents, data->length, &ret); + if (ret) + abort(); + ind = strtok_r(str, " ", &toksave); + while (ind != NULL) { + cb->add_auth_indicator(context, rock, ind); + ind = strtok_r(NULL, " ", &toksave); + } + free(str); + enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH; + } + + cb->free_string(context, rock, attr_err); + cb->free_string(context, rock, attr_2rt); + cb->free_string(context, rock, attr_fail2rt); + cb->free_string(context, rock, attr_failopt); + (*respond)(arg, ret, NULL, list, NULL); +} + +static krb5_error_code +test_return(krb5_context context, krb5_pa_data *padata, krb5_data *req_pkt, + krb5_kdc_req *request, krb5_kdc_rep *reply, + krb5_keyblock *encrypting_key, krb5_pa_data **send_pa_out, + krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, + krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq) +{ + const krb5_keyblock *k = cb->client_keyblock(context, rock); + + assert(k == encrypting_key || k == NULL); + return 0; +} + +krb5_error_code +kdcpreauth_test_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable); + +krb5_error_code +kdcpreauth_test_initvt(krb5_context context, int maj_ver, + int min_ver, krb5_plugin_vtable vtable) +{ + krb5_kdcpreauth_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_kdcpreauth_vtable)vtable; + vt->name = "test"; + vt->pa_type_list = pa_types; + vt->edata = test_edata; + vt->verify = test_verify; + vt->return_padata = test_return; + return 0; +} diff --git a/krb5-1.21.3/src/plugins/preauth/test/test.exports b/krb5-1.21.3/src/plugins/preauth/test/test.exports new file mode 100644 index 00000000..94ba3749 --- /dev/null +++ b/krb5-1.21.3/src/plugins/preauth/test/test.exports @@ -0,0 +1,2 @@ +clpreauth_test_initvt +kdcpreauth_test_initvt diff --git a/krb5-1.21.3/src/plugins/pwqual/test/Makefile.in b/krb5-1.21.3/src/plugins/pwqual/test/Makefile.in new file mode 100644 index 00000000..12725035 --- /dev/null +++ b/krb5-1.21.3/src/plugins/pwqual/test/Makefile.in @@ -0,0 +1,21 @@ +mydir=plugins$(S)pwqual$(S)test +BUILDTOP=$(REL)..$(S)..$(S).. + +LIBBASE=pwqual_test +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/pwqual/test +# Depends on libkrb5 and possibly libkrb5support +SHLIB_EXPDEPS= $(KRB5_BASE_DEPLIBS) +SHLIB_EXPLIBS= $(KRB5_BASE_LIBS) + +STLIBOBJS=main.o + +SRCS= $(srcdir)/main.c + +all-unix: all-libs +install-unix: +clean-unix:: clean-liblinks clean-libs clean-libobjs + +@libnover_frag@ +@libobj_frag@ diff --git a/krb5-1.21.3/src/plugins/pwqual/test/deps b/krb5-1.21.3/src/plugins/pwqual/test/deps new file mode 100644 index 00000000..85372e09 --- /dev/null +++ b/krb5-1.21.3/src/plugins/pwqual/test/deps @@ -0,0 +1,16 @@ +# +# Generated makefile dependencies follow. +# +main.so main.po $(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/krb5/pwqual_plugin.h main.c diff --git a/krb5-1.21.3/src/plugins/pwqual/test/main.c b/krb5-1.21.3/src/plugins/pwqual/test/main.c new file mode 100644 index 00000000..e1e39c72 --- /dev/null +++ b/krb5-1.21.3/src/plugins/pwqual/test/main.c @@ -0,0 +1,220 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/pwqual/test/main.c - test module for password quality interface */ +/* + * Copyright (C) 2010,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. + */ + +/* + * This file implements a module named "combo" which tests whether a password + * matches a pair of words in the dictionary. It also implements several dummy + * modules named "dyn1", "dyn2", and "dyn3" which are used for ordering tests. + */ + +#include +#include +#include +#include +#include +#include + +typedef struct combo_moddata_st { + const char **word_list; /* list of word pointers */ + char *word_block; /* actual word data */ +} *combo_moddata; + +static krb5_error_code +init_dict(combo_moddata dict, const char *dict_file) +{ + int fd; + size_t count, len, i; + char *p, *t; + struct stat sb; + + /* Read the dictionary file into memory in one blob. */ + if (dict_file == NULL) + return 0; + fd = open(dict_file, O_RDONLY); + if (fd == -1) + return (errno == ENOENT) ? 0 : errno; + if (fstat(fd, &sb) == -1) { + close(fd); + return errno; + } + dict->word_block = malloc(sb.st_size + 1); + if (dict->word_block == NULL) + return ENOMEM; + if (read(fd, dict->word_block, sb.st_size) != sb.st_size) + return errno; + close(fd); + dict->word_block[sb.st_size] = '\0'; + + /* Decompose the blob into newline-separated words. */ + p = dict->word_block; + len = sb.st_size; + count = 0; + while (len > 0 && (t = memchr(p, '\n', len)) != NULL) { + *t = '\0'; + len -= t - p + 1; + p = t + 1; + count++; + } + dict->word_list = calloc(count + 1, sizeof(char *)); + if (dict->word_list == NULL) + return ENOMEM; + p = dict->word_block; + for (i = 0; i < count; i++) { + dict->word_list[i] = p; + p += strlen(p) + 1; + } + return 0; +} + +static void +destroy_dict(combo_moddata dict) +{ + if (dict == NULL) + return; + free(dict->word_list); + free(dict->word_block); + free(dict); +} + +static krb5_error_code +combo_open(krb5_context context, const char *dict_file, + krb5_pwqual_moddata *data) +{ + krb5_error_code ret; + combo_moddata dict; + + *data = NULL; + + /* Allocate and initialize a dictionary structure. */ + dict = malloc(sizeof(*dict)); + if (dict == NULL) + return ENOMEM; + dict->word_list = NULL; + dict->word_block = NULL; + + /* Fill in the dictionary structure with data from dict_file. */ + ret = init_dict(dict, dict_file); + if (ret != 0) { + destroy_dict(dict); + return ret; + } + + *data = (krb5_pwqual_moddata)dict; + return 0; +} + +static krb5_error_code +combo_check(krb5_context context, krb5_pwqual_moddata data, + const char *password, const char *policy_name, + krb5_principal princ, const char **languages) +{ + combo_moddata dict = (combo_moddata)data; + const char *remainder, **word1, **word2; + + if (dict->word_list == NULL) + return 0; + + for (word1 = dict->word_list; *word1 != NULL; word1++) { + if (strncasecmp(password, *word1, strlen(*word1)) != 0) + continue; + remainder = password + strlen(*word1); + for (word2 = dict->word_list; *word2 != NULL; word2++) { + if (strcasecmp(remainder, *word2) == 0) { + krb5_set_error_message(context, KADM5_PASS_Q_DICT, + "Password may not be a pair of " + "dictionary words"); + return KADM5_PASS_Q_DICT; + } + } + } + + return 0; +} + +static void +combo_close(krb5_context context, krb5_pwqual_moddata data) +{ + destroy_dict((combo_moddata)data); +} + +krb5_error_code +pwqual_combo_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); +krb5_error_code +pwqual_dyn1_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); +krb5_error_code +pwqual_dyn2_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); +krb5_error_code +pwqual_dyn3_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +pwqual_combo_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + krb5_pwqual_vtable vt; + + if (maj_ver != 1) + return KRB5_PLUGIN_VER_NOTSUPP; + vt = (krb5_pwqual_vtable)vtable; + vt->name = "combo"; + vt->open = combo_open; + vt->check = combo_check; + vt->close = combo_close; + return 0; +} + +krb5_error_code +pwqual_dyn1_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + ((krb5_pwqual_vtable)vtable)->name = "dyn1"; + return 0; +} + +krb5_error_code +pwqual_dyn2_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + ((krb5_pwqual_vtable)vtable)->name = "dyn2"; + return 0; +} + +krb5_error_code +pwqual_dyn3_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + ((krb5_pwqual_vtable)vtable)->name = "dyn3"; + return 0; +} diff --git a/krb5-1.21.3/src/plugins/pwqual/test/pwqual_test.exports b/krb5-1.21.3/src/plugins/pwqual/test/pwqual_test.exports new file mode 100644 index 00000000..8a5638ce --- /dev/null +++ b/krb5-1.21.3/src/plugins/pwqual/test/pwqual_test.exports @@ -0,0 +1,4 @@ +pwqual_combo_initvt +pwqual_dyn1_initvt +pwqual_dyn2_initvt +pwqual_dyn3_initvt diff --git a/krb5-1.21.3/src/plugins/tls/k5tls/Makefile.in b/krb5-1.21.3/src/plugins/tls/k5tls/Makefile.in new file mode 100644 index 00000000..9f2de7dd --- /dev/null +++ b/krb5-1.21.3/src/plugins/tls/k5tls/Makefile.in @@ -0,0 +1,22 @@ +mydir=plugins$(S)tls$(S)k5tls +BUILDTOP=$(REL)..$(S)..$(S).. +MODULE_INSTALL_DIR = $(KRB5_TLS_MODULE_DIR) +LOCALINCLUDES= $(TLS_IMPL_CFLAGS) + +LIBBASE=k5tls +LIBMAJOR=0 +LIBMINOR=0 +RELDIR=../plugins/tls/k5tls +SHLIB_EXPDEPS= $(KRB5_DEPLIB) $(SUPPORT_DEPLIB) +SHLIB_EXPLIBS= $(KRB5_LIB) $(SUPPORT_LIB) $(TLS_IMPL_LIBS) + +STLIBOBJS=openssl.o notls.o + +SRCS=$(srcdir)/openssl.c $(srcdir)/notls.c + +all-unix: all-liblinks +install-unix: install-libs +clean-unix:: clean-liblinks clean-libs clean-libobjs + +@libnover_frag@ +@libobj_frag@ diff --git a/krb5-1.21.3/src/plugins/tls/k5tls/deps b/krb5-1.21.3/src/plugins/tls/k5tls/deps new file mode 100644 index 00000000..a6088a7f --- /dev/null +++ b/krb5-1.21.3/src/plugins/tls/k5tls/deps @@ -0,0 +1,25 @@ +# +# Generated makefile dependencies follow. +# +openssl.so openssl.po $(OUTPRE)openssl.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-tls.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h openssl.c +notls.so notls.po $(OUTPRE)notls.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-tls.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h notls.c diff --git a/krb5-1.21.3/src/plugins/tls/k5tls/k5tls.exports b/krb5-1.21.3/src/plugins/tls/k5tls/k5tls.exports new file mode 100644 index 00000000..d67d928c --- /dev/null +++ b/krb5-1.21.3/src/plugins/tls/k5tls/k5tls.exports @@ -0,0 +1 @@ +tls_k5tls_initvt diff --git a/krb5-1.21.3/src/plugins/tls/k5tls/notls.c b/krb5-1.21.3/src/plugins/tls/k5tls/notls.c new file mode 100644 index 00000000..357af811 --- /dev/null +++ b/krb5-1.21.3/src/plugins/tls/k5tls/notls.c @@ -0,0 +1,53 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plus/tls/k5tls/none.c - Stub TLS module implementation */ +/* + * Copyright (C) 2014 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. + */ + +/* This dummy module is used if no TLS implemented is selected. */ + +#include "k5-int.h" +#include "k5-utf8.h" +#include "k5-tls.h" + +#ifdef TLS_IMPL_NONE + +krb5_error_code +tls_k5tls_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +tls_k5tls_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + /* Leave all vtable functions nulled. */ + return 0; +} + +#endif /* TLS_IMPL_NONE */ diff --git a/krb5-1.21.3/src/plugins/tls/k5tls/openssl.c b/krb5-1.21.3/src/plugins/tls/k5tls/openssl.c new file mode 100644 index 00000000..99fda7ff --- /dev/null +++ b/krb5-1.21.3/src/plugins/tls/k5tls/openssl.c @@ -0,0 +1,585 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* plugins/tls/k5tls/openssl.c - OpenSSL TLS module implementation */ +/* + * Copyright 2013,2014 Red Hat, Inc. + * + * 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. + * + * 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. + */ + +#include "k5-int.h" +#include "k5-utf8.h" +#include "k5-tls.h" + +#ifdef TLS_IMPL_OPENSSL +#include +#include +#include +#include +#include + +struct k5_tls_handle_st { + SSL *ssl; + char *servername; +}; + +static int ex_context_id = -1; +static int ex_handle_id = -1; + +MAKE_INIT_FUNCTION(init_openssl); + +int +init_openssl() +{ + SSL_library_init(); + SSL_load_error_strings(); + OpenSSL_add_all_algorithms(); + ex_context_id = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); + ex_handle_id = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); + return 0; +} + +static void +flush_errors(krb5_context context) +{ + unsigned long err; + char buf[128]; + + while ((err = ERR_get_error()) != 0) { + ERR_error_string_n(err, buf, sizeof(buf)); + TRACE_TLS_ERROR(context, buf); + } +} + +/* Return the passed-in character, lower-cased if it's an ASCII character. */ +static inline char +ascii_tolower(char p) +{ + if (KRB5_UPPER(p)) + return p + ('a' - 'A'); + return p; +} + +/* + * Check a single label. If allow_wildcard is true, and the presented name + * includes a wildcard, return true and note that we matched a wildcard. + * Otherwise, for both the presented and expected values, do a case-insensitive + * comparison of ASCII characters, and a case-sensitive comparison of + * everything else. + */ +static krb5_boolean +label_match(const char *presented, size_t plen, const char *expected, + size_t elen, krb5_boolean allow_wildcard, krb5_boolean *wildcard) +{ + unsigned int i; + + if (allow_wildcard && plen == 1 && presented[0] == '*') { + *wildcard = TRUE; + return TRUE; + } + + if (plen != elen) + return FALSE; + + for (i = 0; i < elen; i++) { + if (ascii_tolower(presented[i]) != ascii_tolower(expected[i])) + return FALSE; + } + return TRUE; +} + +/* Break up the two names and check them, label by label. */ +static krb5_boolean +domain_match(const char *presented, size_t plen, const char *expected) +{ + const char *p, *q, *r, *s; + int n_label; + krb5_boolean used_wildcard = FALSE; + + n_label = 0; + p = presented; + r = expected; + while (p < presented + plen && *r != '\0') { + q = memchr(p, '.', plen - (p - presented)); + if (q == NULL) + q = presented + plen; + s = r + strcspn(r, "."); + if (!label_match(p, q - p, r, s - r, n_label == 0, &used_wildcard)) + return FALSE; + p = q < presented + plen ? q + 1 : q; + r = *s ? s + 1 : s; + n_label++; + } + if (used_wildcard && n_label <= 2) + return FALSE; + if (p == presented + plen && *r == '\0') + return TRUE; + return FALSE; +} + +/* Fetch the list of subjectAltNames from a certificate. */ +static GENERAL_NAMES * +get_cert_sans(X509 *x) +{ + int ext; + X509_EXTENSION *san_ext; + + ext = X509_get_ext_by_NID(x, NID_subject_alt_name, -1); + if (ext < 0) + return NULL; + san_ext = X509_get_ext(x, ext); + if (san_ext == NULL) + return NULL; + return X509V3_EXT_d2i(san_ext); +} + +/* Fetch a CN value from the subjct name field, returning its length, or -1 if + * there is no subject name or it contains no CN value. */ +static int +get_cert_cn(X509 *x, char *buf, size_t bufsize) +{ + X509_NAME *name; + + name = X509_get_subject_name(x); + if (name == NULL) + return -1; + return X509_NAME_get_text_by_NID(name, NID_commonName, buf, bufsize); +} + +/* Return true if text matches any of the addresses we can recover from x. */ +static krb5_boolean +check_cert_address(X509 *x, const char *text) +{ + char buf[1024]; + GENERAL_NAMES *sans; + GENERAL_NAME *san = NULL; + ASN1_OCTET_STRING *ip; + krb5_boolean found_ip_san = FALSE, matched = FALSE; + int n_sans, i; + int name_length; + struct in_addr sin; + struct in6_addr sin6; + + /* Parse the IP address into an octet string. */ + ip = ASN1_OCTET_STRING_new(); + if (ip == NULL) + return FALSE; + if (inet_pton(AF_INET, text, &sin)) { + ASN1_OCTET_STRING_set(ip, (unsigned char *)&sin, sizeof(sin)); + } else if (inet_pton(AF_INET6, text, &sin6)) { + ASN1_OCTET_STRING_set(ip, (unsigned char *)&sin6, sizeof(sin6)); + } else { + ASN1_OCTET_STRING_free(ip); + return FALSE; + } + + /* Check for matches in ipaddress subjectAltName values. */ + sans = get_cert_sans(x); + if (sans != NULL) { + n_sans = sk_GENERAL_NAME_num(sans); + for (i = 0; i < n_sans; i++) { + san = sk_GENERAL_NAME_value(sans, i); + if (san->type != GEN_IPADD) + continue; + found_ip_san = TRUE; + matched = (ASN1_OCTET_STRING_cmp(ip, san->d.iPAddress) == 0); + if (matched) + break; + } + sk_GENERAL_NAME_pop_free(sans, GENERAL_NAME_free); + } + ASN1_OCTET_STRING_free(ip); + + if (found_ip_san) + return matched; + + /* Check for a match against the CN value in the peer's subject name. */ + name_length = get_cert_cn(x, buf, sizeof(buf)); + if (name_length >= 0) { + /* Do a string compare to check if it's an acceptable value. */ + return strlen(text) == (size_t)name_length && + strncmp(text, buf, name_length) == 0; + } + + /* We didn't find a match. */ + return FALSE; +} + +/* Return true if expected matches any of the names we can recover from x. */ +static krb5_boolean +check_cert_servername(X509 *x, const char *expected) +{ + char buf[1024]; + GENERAL_NAMES *sans; + GENERAL_NAME *san = NULL; + unsigned char *dnsname; + krb5_boolean found_dns_san = FALSE, matched = FALSE; + int name_length, n_sans, i; + + /* Check for matches in dnsname subjectAltName values. */ + sans = get_cert_sans(x); + if (sans != NULL) { + n_sans = sk_GENERAL_NAME_num(sans); + for (i = 0; i < n_sans; i++) { + san = sk_GENERAL_NAME_value(sans, i); + if (san->type != GEN_DNS) + continue; + found_dns_san = TRUE; + dnsname = NULL; + name_length = ASN1_STRING_to_UTF8(&dnsname, san->d.dNSName); + if (dnsname == NULL) + continue; + matched = domain_match((char *)dnsname, name_length, expected); + OPENSSL_free(dnsname); + if (matched) + break; + } + sk_GENERAL_NAME_pop_free(sans, GENERAL_NAME_free); + } + + if (matched) + return TRUE; + if (found_dns_san) + return matched; + + /* Check for a match against the CN value in the peer's subject name. */ + name_length = get_cert_cn(x, buf, sizeof(buf)); + if (name_length >= 0) + return domain_match(buf, name_length, expected); + + /* We didn't find a match. */ + return FALSE; +} + +static krb5_boolean +check_cert_name_or_ip(X509 *x, const char *expected_name) +{ + struct in_addr in; + struct in6_addr in6; + + if (inet_pton(AF_INET, expected_name, &in) != 0 || + inet_pton(AF_INET6, expected_name, &in6) != 0) { + return check_cert_address(x, expected_name); + } else { + return check_cert_servername(x, expected_name); + } +} + +static int +verify_callback(int preverify_ok, X509_STORE_CTX *store_ctx) +{ + X509 *x; + SSL *ssl; + BIO *bio; + krb5_context context; + int err, depth; + k5_tls_handle handle; + const char *cert = NULL, *errstr, *expected_name; + size_t count; + + ssl = X509_STORE_CTX_get_ex_data(store_ctx, + SSL_get_ex_data_X509_STORE_CTX_idx()); + context = SSL_get_ex_data(ssl, ex_context_id); + handle = SSL_get_ex_data(ssl, ex_handle_id); + assert(context != NULL && handle != NULL); + /* We do have the peer's cert, right? */ + x = X509_STORE_CTX_get_current_cert(store_ctx); + if (x == NULL) { + TRACE_TLS_NO_REMOTE_CERTIFICATE(context); + return 0; + } + /* Figure out where we are. */ + depth = X509_STORE_CTX_get_error_depth(store_ctx); + if (depth < 0) + return 0; + /* If there's an error at this level that we're not ignoring, fail. */ + err = X509_STORE_CTX_get_error(store_ctx); + if (err != X509_V_OK) { + bio = BIO_new(BIO_s_mem()); + if (bio != NULL) { + X509_NAME_print_ex(bio, X509_get_subject_name(x), 0, 0); + count = BIO_get_mem_data(bio, &cert); + errstr = X509_verify_cert_error_string(err); + TRACE_TLS_CERT_ERROR(context, depth, count, cert, err, errstr); + BIO_free(bio); + } + return 0; + } + /* If we're not looking at the peer, we're done and everything's ok. */ + if (depth != 0) + return 1; + /* Check if the name we expect to find is in the certificate. */ + expected_name = handle->servername; + if (check_cert_name_or_ip(x, expected_name)) { + TRACE_TLS_SERVER_NAME_MATCH(context, expected_name); + return 1; + } else { + TRACE_TLS_SERVER_NAME_MISMATCH(context, expected_name); + } + /* The name didn't match. */ + return 0; +} + +static krb5_error_code +load_anchor_file(X509_STORE *store, const char *path) +{ + FILE *fp; + STACK_OF(X509_INFO) *sk = NULL; + X509_INFO *xi; + int i; + + fp = fopen(path, "r"); + if (fp == NULL) + return errno; + sk = PEM_X509_INFO_read(fp, NULL, NULL, NULL); + fclose(fp); + if (sk == NULL) + return ENOENT; + for (i = 0; i < sk_X509_INFO_num(sk); i++) { + xi = sk_X509_INFO_value(sk, i); + if (xi->x509 != NULL) + X509_STORE_add_cert(store, xi->x509); + } + sk_X509_INFO_pop_free(sk, X509_INFO_free); + return 0; +} + +static krb5_error_code +load_anchor_dir(X509_STORE *store, const char *path) +{ + DIR *d = NULL; + struct dirent *dentry = NULL; + char filename[1024]; + krb5_boolean found_any = FALSE; + + d = opendir(path); + if (d == NULL) + return ENOENT; + while ((dentry = readdir(d)) != NULL) { + if (dentry->d_name[0] != '.') { + snprintf(filename, sizeof(filename), "%s/%s", + path, dentry->d_name); + if (load_anchor_file(store, filename) == 0) + found_any = TRUE; + } + } + closedir(d); + return found_any ? 0 : ENOENT; +} + +static krb5_error_code +load_anchor(SSL_CTX *ctx, const char *location) +{ + X509_STORE *store; + const char *envloc; + + store = SSL_CTX_get_cert_store(ctx); + if (strncmp(location, "FILE:", 5) == 0) { + return load_anchor_file(store, location + 5); + } else if (strncmp(location, "DIR:", 4) == 0) { + return load_anchor_dir(store, location + 4); + } else if (strncmp(location, "ENV:", 4) == 0) { + envloc = secure_getenv(location + 4); + if (envloc == NULL) + return ENOENT; + return load_anchor(ctx, envloc); + } + return EINVAL; +} + +static krb5_error_code +load_anchors(krb5_context context, char **anchors, SSL_CTX *sctx) +{ + unsigned int i; + krb5_error_code ret; + + if (anchors != NULL) { + for (i = 0; anchors[i] != NULL; i++) { + ret = load_anchor(sctx, anchors[i]); + if (ret) + return ret; + } + } else { + /* Use the library defaults. */ + if (SSL_CTX_set_default_verify_paths(sctx) != 1) + return ENOENT; + } + + return 0; +} + +static krb5_error_code +setup(krb5_context context, SOCKET fd, const char *servername, + char **anchors, k5_tls_handle *handle_out) +{ + int e; + long options = SSL_OP_NO_SSLv2; + SSL_CTX *ctx = NULL; + SSL *ssl = NULL; + k5_tls_handle handle = NULL; + + *handle_out = NULL; + + (void)CALL_INIT_FUNCTION(init_openssl); + if (ex_context_id == -1 || ex_handle_id == -1) + return KRB5_PLUGIN_OP_NOTSUPP; + + /* Do general SSL library setup. */ + ctx = SSL_CTX_new(SSLv23_client_method()); + if (ctx == NULL) + goto error; + +#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF + /* + * For OpenSSL 3 and later, mark close_notify alerts as optional. We don't + * need to worry about truncation attacks because the protocols this module + * is used with (Kerberos and change-password) receive a single + * length-delimited message from the server. For prior versions of OpenSSL + * we check for SSL_ERROR_SYSCALL when reading instead (this error changes + * to SSL_ERROR_SSL in OpenSSL 3). + */ + options |= SSL_OP_IGNORE_UNEXPECTED_EOF; +#endif + SSL_CTX_set_options(ctx, options); + + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback); + X509_STORE_set_flags(SSL_CTX_get_cert_store(ctx), 0); + e = load_anchors(context, anchors, ctx); + if (e != 0) + goto error; + + ssl = SSL_new(ctx); + if (ssl == NULL) + goto error; + + if (!SSL_set_fd(ssl, fd)) + goto error; +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + if (!SSL_set_tlsext_host_name(ssl, servername)) + goto error; +#endif + SSL_set_connect_state(ssl); + + /* Create a handle and allow verify_callback to access it. */ + handle = malloc(sizeof(*handle)); + if (handle == NULL || !SSL_set_ex_data(ssl, ex_handle_id, handle)) + goto error; + + handle->ssl = ssl; + handle->servername = strdup(servername); + if (handle->servername == NULL) + goto error; + *handle_out = handle; + SSL_CTX_free(ctx); + return 0; + +error: + flush_errors(context); + free(handle); + SSL_free(ssl); + SSL_CTX_free(ctx); + return KRB5_PLUGIN_OP_NOTSUPP; +} + +static k5_tls_status +write_tls(krb5_context context, k5_tls_handle handle, const void *data, + size_t len) +{ + int nwritten, e; + + /* Try to transmit our request; allow verify_callback to access context. */ + if (!SSL_set_ex_data(handle->ssl, ex_context_id, context)) + return ERROR_TLS; + nwritten = SSL_write(handle->ssl, data, len); + (void)SSL_set_ex_data(handle->ssl, ex_context_id, NULL); + if (nwritten > 0) + return DONE; + + e = SSL_get_error(handle->ssl, nwritten); + if (e == SSL_ERROR_WANT_READ) + return WANT_READ; + else if (e == SSL_ERROR_WANT_WRITE) + return WANT_WRITE; + flush_errors(context); + return ERROR_TLS; +} + +static k5_tls_status +read_tls(krb5_context context, k5_tls_handle handle, void *data, + size_t data_size, size_t *len_out) +{ + ssize_t nread; + int e; + + *len_out = 0; + + /* Try to read response data; allow verify_callback to access context. */ + if (!SSL_set_ex_data(handle->ssl, ex_context_id, context)) + return ERROR_TLS; + nread = SSL_read(handle->ssl, data, data_size); + (void)SSL_set_ex_data(handle->ssl, ex_context_id, NULL); + if (nread > 0) { + *len_out = nread; + return DATA_READ; + } + + e = SSL_get_error(handle->ssl, nread); + if (e == SSL_ERROR_WANT_READ) + return WANT_READ; + else if (e == SSL_ERROR_WANT_WRITE) + return WANT_WRITE; + + if (e == SSL_ERROR_ZERO_RETURN || (e == SSL_ERROR_SYSCALL && nread == 0)) + return DONE; + + flush_errors(context); + return ERROR_TLS; +} + +static void +free_handle(krb5_context context, k5_tls_handle handle) +{ + SSL_free(handle->ssl); + free(handle->servername); + free(handle); +} + +krb5_error_code +tls_k5tls_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable); + +krb5_error_code +tls_k5tls_initvt(krb5_context context, int maj_ver, int min_ver, + krb5_plugin_vtable vtable) +{ + k5_tls_vtable vt; + + vt = (k5_tls_vtable)vtable; + vt->setup = setup; + vt->write = write_tls; + vt->read = read_tls; + vt->free_handle = free_handle; + return 0; +} + +#endif /* TLS_IMPL_OPENSSL */ diff --git a/krb5-1.21.3/src/po/Makefile.in b/krb5-1.21.3/src/po/Makefile.in new file mode 100644 index 00000000..055a93a5 --- /dev/null +++ b/krb5-1.21.3/src/po/Makefile.in @@ -0,0 +1,52 @@ +mydir=po +BUILDTOP=$(REL).. +VER=@PACKAGE_VERSION@ + +DOMAIN=mit-krb5 +POTFILE=$(srcdir)/$(DOMAIN).pot +XGETTEXT=xgettext --foreign-user --package-name=mit-krb5 \ + --package-version=$(VER) --copyright-holder=MIT +ETSRCS= $(BUILDTOP)/lib/gssapi/generic/gssapi_err_generic.c \ + $(BUILDTOP)/lib/gssapi/krb5/gssapi_err_krb5.c \ + $(BUILDTOP)/lib/kadm5/chpass_util_strings.c \ + $(BUILDTOP)/lib/kadm5/kadm_err.c \ + $(BUILDTOP)/lib/kdb/adb_err.c \ + $(BUILDTOP)/lib/krb5/error_tables/k5e1_err.c \ + $(BUILDTOP)/lib/krb5/error_tables/krb5_err.c \ + $(BUILDTOP)/lib/krb5/error_tables/kdb5_err.c \ + $(BUILDTOP)/lib/krb5/error_tables/asn1_err.c \ + $(BUILDTOP)/lib/krb5/error_tables/kv5m_err.c \ + $(BUILDTOP)/lib/krb5/error_tables/krb524_err.c +CATALOGS=en_US.mo de.mo ka.mo + +.SUFFIXES: .po .mo +.po.mo: + msgfmt -o $@ $< + +all: $(CATALOGS) + +update-po: csrcs check_et_@COM_ERR_VERSION@ + $(XGETTEXT) -k_ -kN_ -o $(POTFILE) -f csrcs + $(XGETTEXT) -kN_ -j -o $(POTFILE) $(ETSRCS) + +csrcs: always + find $(top_srcdir) -name "*.c" -print | LC_ALL=C sort > $@ + +check_et_k5 check_et_intlsys: +check_et_sys: + @echo 1>&2 error: cannot update po file with this version of compile_et + @exit 1 + +always: + +install: + for c in $(CATALOGS); do \ + lang=`basename $$c .mo`; \ + $(top_srcdir)/config/mkinstalldirs \ + $(DESTDIR)$(KRB5_LOCALEDIR)/$$lang/LC_MESSAGES; \ + $(INSTALL_DATA) $$c \ + $(DESTDIR)$(KRB5_LOCALEDIR)/$$lang/LC_MESSAGES/$(DOMAIN).mo; \ + done + +clean: + $(RM) $(CATALOGS) diff --git a/krb5-1.21.3/src/po/de.po b/krb5-1.21.3/src/po/de.po new file mode 100644 index 00000000..6c48f35f --- /dev/null +++ b/krb5-1.21.3/src/po/de.po @@ -0,0 +1,9300 @@ +# German translation of mit-krb5. +# This file is distributed under the same license as the mit-krb5 package. +# Copyright (C) 1985-2013 by the Massachusetts Institute of Technology. +# Copyright (C) of this file 2014-2016 Chris Leick . +# +msgid "" +msgstr "" +"Project-Id-Version: mit-krb5 13.2\n" +"Report-Msgid-Bugs-To: krbdev@mit.edu\n" +"POT-Creation-Date: 2015-05-06 14:59-0400\n" +"PO-Revision-Date: 2016-04-07 08:15+0200\n" +"Last-Translator: Chris Leick \n" +"Language-Team: German \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: ../../src/clients/kdestroy/kdestroy.c:62 +#, c-format +msgid "Usage: %s [-A] [-q] [-c cache_name]\n" +msgstr "Aufruf: %s [-A] [-q] [-c Zwischenspeichername]\n" + +#: ../../src/clients/kdestroy/kdestroy.c:63 +#, c-format +msgid "\t-A destroy all credential caches in collection\n" +msgstr "\t-A vernichtet alle Anmeldedatenzwischenspeicher in der Sammlung.\n" + +#: ../../src/clients/kdestroy/kdestroy.c:64 +#, c-format +msgid "\t-q quiet mode\n" +msgstr "\t-q stiller Modus\n" + +#: ../../src/clients/kdestroy/kdestroy.c:65 +#: ../../src/clients/kswitch/kswitch.c:45 +#, c-format +msgid "\t-c specify name of credentials cache\n" +msgstr "\t-c gibt den Namen des Zwischenspeichers für Anmeldedaten an.\n" + +#: ../../src/clients/kdestroy/kdestroy.c:98 +#: ../../src/clients/kinit/kinit.c:383 ../../src/clients/ksu/main.c:284 +#, c-format +msgid "Only one -c option allowed\n" +msgstr "Nur eine »-c«-Option ist erlaubt.\n" + +#: ../../src/clients/kdestroy/kdestroy.c:105 +#: ../../src/clients/kinit/kinit.c:412 ../../src/clients/klist/klist.c:182 +#, c-format +msgid "Kerberos 4 is no longer supported\n" +msgstr "Kerberos 4 wird nicht mehr unterstützt.\n" + +#: ../../src/clients/kdestroy/kdestroy.c:126 +#: ../../src/clients/klist/klist.c:253 ../../src/clients/ksu/main.c:131 +#: ../../src/clients/ksu/main.c:137 ../../src/clients/kswitch/kswitch.c:97 +#: ../../src/kadmin/ktutil/ktutil.c:52 ../../src/kdc/main.c:926 +#: ../../src/slave/kprop.c:102 ../../src/slave/kpropd.c:1052 +msgid "while initializing krb5" +msgstr "beim Initialisieren von Krb5" + +#: ../../src/clients/kdestroy/kdestroy.c:133 +msgid "while listing credential caches" +msgstr "beim Auflisten der Anmeldedatenzwischenspeicher" + +#: ../../src/clients/kdestroy/kdestroy.c:140 +msgid "composing ccache name" +msgstr "Ccache-Name wird zusammengesetzt." + +#: ../../src/clients/kdestroy/kdestroy.c:145 +#, c-format +msgid "while destroying cache %s" +msgstr "beim Zerstören des Zwischenspeichers %s" + +#: ../../src/clients/kdestroy/kdestroy.c:157 +#: ../../src/clients/kswitch/kswitch.c:104 +#, c-format +msgid "while resolving %s" +msgstr "beim Auflösen von %s" + +#: ../../src/clients/kdestroy/kdestroy.c:163 +#: ../../src/clients/kinit/kinit.c:501 ../../src/clients/klist/klist.c:460 +msgid "while getting default ccache" +msgstr "beim Holen des Standard-Ccaches" + +#: ../../src/clients/kdestroy/kdestroy.c:170 ../../src/clients/ksu/main.c:986 +msgid "while destroying cache" +msgstr "beim Zerstören des Zwischenspeichers" + +#: ../../src/clients/kdestroy/kdestroy.c:173 +#, c-format +msgid "Ticket cache NOT destroyed!\n" +msgstr "Ticketzwischenspeicher NICHT vernichtet!\n" + +#: ../../src/clients/kdestroy/kdestroy.c:175 +#, c-format +msgid "Ticket cache %cNOT%c destroyed!\n" +msgstr "Ticketzwischenspeicher %cNICHT%c vernichtet!\n" + +#: ../../src/clients/kinit/kinit.c:213 +#, c-format +msgid "\t-V verbose\n" +msgstr "\t-V detaillierte Ausgabe\n" + +#: ../../src/clients/kinit/kinit.c:214 +#, c-format +msgid "\t-l lifetime\n" +msgstr "\t-l Lebensdauer\n" + +#: ../../src/clients/kinit/kinit.c:215 +#, c-format +msgid "\t-s start time\n" +msgstr "\t-s Startzeit\n" + +#: ../../src/clients/kinit/kinit.c:216 +#, c-format +msgid "\t-r renewable lifetime\n" +msgstr "\t-r verlängerbare Lebensdauer\n" + +#: ../../src/clients/kinit/kinit.c:217 +#, c-format +msgid "\t-f forwardable\n" +msgstr "\t-f weiterleitbar\n" + +#: ../../src/clients/kinit/kinit.c:218 +#, c-format +msgid "\t-F not forwardable\n" +msgstr "\t-F nicht weiterleitbar\n" + +#: ../../src/clients/kinit/kinit.c:219 +#, c-format +msgid "\t-p proxiable\n" +msgstr "\t-p Proxy nutzbar\n" + +#: ../../src/clients/kinit/kinit.c:220 +#, c-format +msgid "\t-P not proxiable\n" +msgstr "\t-P Proxy nicht nutzbar\n" + +#: ../../src/clients/kinit/kinit.c:221 +#, c-format +msgid "\t-n anonymous\n" +msgstr "\t-n anonym\n" + +#: ../../src/clients/kinit/kinit.c:222 +#, c-format +msgid "\t-a include addresses\n" +msgstr "\t-a bezieht Adressen ein.\n" + +#: ../../src/clients/kinit/kinit.c:223 +#, c-format +msgid "\t-A do not include addresses\n" +msgstr "\t-a bezieht Adressen nicht ein.\n" + +#: ../../src/clients/kinit/kinit.c:224 +#, c-format +msgid "\t-v validate\n" +msgstr "\t-v überprüft\n" + +#: ../../src/clients/kinit/kinit.c:225 +#, c-format +msgid "\t-R renew\n" +msgstr "\t-R erneuert\n" + +#: ../../src/clients/kinit/kinit.c:226 +#, c-format +msgid "\t-C canonicalize\n" +msgstr "\t-C bringt in Normalform\n" + +#: ../../src/clients/kinit/kinit.c:227 +#, c-format +msgid "\t-E client is enterprise principal name\n" +msgstr "\t-E Client ist der Principal-Name des Unternehmens\n" + +#: ../../src/clients/kinit/kinit.c:228 +#, c-format +msgid "\t-k use keytab\n" +msgstr "\t-k verwendet Schlüsseltabelle\n" + +#: ../../src/clients/kinit/kinit.c:229 +#, c-format +msgid "\t-i use default client keytab (with -k)\n" +msgstr "\t-i verwendet die Standardschlüsseltabelle des Clients (mit -k).\n" + +#: ../../src/clients/kinit/kinit.c:230 +#, c-format +msgid "\t-t filename of keytab to use\n" +msgstr "\t-t Dateiname der zu verwendenden Schlüsseltabelle\n" + +#: ../../src/clients/kinit/kinit.c:231 +#, c-format +msgid "\t-c Kerberos 5 cache name\n" +msgstr "\t-c Kerberos-5-Zwischenspeichername\n" + +#: ../../src/clients/kinit/kinit.c:232 +#, c-format +msgid "\t-S service\n" +msgstr "\t-S Dienst\n" + +#: ../../src/clients/kinit/kinit.c:233 +#, c-format +msgid "\t-T armor credential cache\n" +msgstr "\t-T gehärteter Anmeldedatenzwischenspeicher\n" + +#: ../../src/clients/kinit/kinit.c:234 +#, c-format +msgid "\t-X [=]\n" +msgstr "\t-X [=]\n" + +#: ../../src/clients/kinit/kinit.c:301 ../../src/clients/kinit/kinit.c:309 +#, c-format +msgid "Bad lifetime value %s\n" +msgstr "falscher Wert für die Lebensdauer %s\n" + +#: ../../src/clients/kinit/kinit.c:343 +#, c-format +msgid "Bad start time value %s\n" +msgstr "falscher Wert für die Startzeit %s\n" + +#: ../../src/clients/kinit/kinit.c:362 +#, c-format +msgid "Only one -t option allowed.\n" +msgstr "Nur eine -t-Option ist erlaubt.\n" + +#: ../../src/clients/kinit/kinit.c:370 +#, c-format +msgid "Only one armor_ccache\n" +msgstr "nur ein gehärteter Ccache\n" + +#: ../../src/clients/kinit/kinit.c:391 +#, c-format +msgid "Only one -I option allowed\n" +msgstr "Nur eine -I-Option ist erlaubt.\n" + +#: ../../src/clients/kinit/kinit.c:401 +msgid "while adding preauth option" +msgstr "beim Hinzufügen der Option »preauth«" + +#: ../../src/clients/kinit/kinit.c:425 +#, c-format +msgid "Only one of -f and -F allowed\n" +msgstr "Nur eine der Optionen -f und -F ist erlaubt.\n" + +#: ../../src/clients/kinit/kinit.c:430 +#, c-format +msgid "Only one of -p and -P allowed\n" +msgstr "Nur eine der Optionen -p und -P ist erlaubt.\n" + +#: ../../src/clients/kinit/kinit.c:435 +#, c-format +msgid "Only one of -a and -A allowed\n" +msgstr "Nur eine der Optionen -a und -A ist erlaubt.\n" + +#: ../../src/clients/kinit/kinit.c:440 +#, c-format +msgid "Only one of -t and -i allowed\n" +msgstr "Nur eine der Optionen -t und-i ist erlaubt.\n" + +#: ../../src/clients/kinit/kinit.c:447 +#, c-format +msgid "keytab specified, forcing -k\n" +msgstr "Schlüsseltabelle angegeben, -k wird erzwungen\n" + +#: ../../src/clients/kinit/kinit.c:451 ../../src/clients/klist/klist.c:221 +#, c-format +msgid "Extra arguments (starting with \"%s\").\n" +msgstr "zusätzliche Argumente (beginnend mit »%s«)\n" + +#: ../../src/clients/kinit/kinit.c:480 +msgid "while initializing Kerberos 5 library" +msgstr "beim Initialisieren der Kerberos-5-Bibliothek" + +#: ../../src/clients/kinit/kinit.c:488 ../../src/clients/kinit/kinit.c:644 +#, c-format +msgid "resolving ccache %s" +msgstr "Ccache %s wird ermittelt" + +#: ../../src/clients/kinit/kinit.c:493 +#, c-format +msgid "Using specified cache: %s\n" +msgstr "Angegebener Zwischenspeicher wird verwendet: %s\n" + +#: ../../src/clients/kinit/kinit.c:515 ../../src/clients/kinit/kinit.c:595 +#: ../../src/clients/kpasswd/kpasswd.c:28 ../../src/clients/ksu/main.c:238 +#, c-format +msgid "when parsing name %s" +msgstr "wenn der Name %s ausgewertet wird" + +#: ../../src/clients/kinit/kinit.c:523 ../../src/kadmin/dbutil/kdb5_util.c:307 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:391 +#: ../../src/slave/kprop.c:203 +msgid "while getting default realm" +msgstr "beim Holen des Standard-Realms" + +#: ../../src/clients/kinit/kinit.c:535 +msgid "while building principal" +msgstr "beim Erstellen des Principals" + +#: ../../src/clients/kinit/kinit.c:543 +msgid "When resolving the default client keytab" +msgstr "beim Auflösen der Standardschlüsseltabelle des Clients" + +#: ../../src/clients/kinit/kinit.c:550 +msgid "When determining client principal name from keytab" +msgstr "beim Bestimmen des Dienst-Principal-Namens anhand der Schlüsseltabelle" + +#: ../../src/clients/kinit/kinit.c:559 +msgid "when creating default server principal name" +msgstr "wenn der Standard-Principal-Name des Servers erstellt wird" + +#: ../../src/clients/kinit/kinit.c:566 +#, c-format +msgid "(principal %s)" +msgstr "(Principal %s)" + +#: ../../src/clients/kinit/kinit.c:569 +msgid "for local services" +msgstr "für lokale Dienste" + +#: ../../src/clients/kinit/kinit.c:590 ../../src/clients/kpasswd/kpasswd.c:42 +#, c-format +msgid "Unable to identify user\n" +msgstr "Benutzer kann nicht identifiziert werden\n" + +#: ../../src/clients/kinit/kinit.c:605 ../../src/clients/kswitch/kswitch.c:116 +#, c-format +msgid "while searching for ccache for %s" +msgstr "beim Suchen nach Ccache für %s" + +#: ../../src/clients/kinit/kinit.c:611 +#, c-format +msgid "Using existing cache: %s\n" +msgstr "Existierender Zwischenspeicher wird verwendet: %s\n" + +#: ../../src/clients/kinit/kinit.c:620 +msgid "while generating new ccache" +msgstr "beim Erstellen von neuem Ccache" + +#: ../../src/clients/kinit/kinit.c:624 +#, c-format +msgid "Using new cache: %s\n" +msgstr "Neuer Zwischenspeicher wird verwendet: %s\n" + +#: ../../src/clients/kinit/kinit.c:636 +#, c-format +msgid "Using default cache: %s\n" +msgstr "Standardzwischenspeicher wird verwendet: %s\n" + +#: ../../src/clients/kinit/kinit.c:649 +#, c-format +msgid "Using specified input cache: %s\n" +msgstr "Angegebener Eingabezwischenspeicher wird verwendet: %s\n" + +#: ../../src/clients/kinit/kinit.c:657 ../../src/clients/ksu/krb_auth_su.c:160 +msgid "when unparsing name" +msgstr "beim Rückgängigmachen der Auswertung des Namens" + +#: ../../src/clients/kinit/kinit.c:661 +#, c-format +msgid "Using principal: %s\n" +msgstr "verwendeter Principal: %s\n" + +#: ../../src/clients/kinit/kinit.c:752 +msgid "getting local addresses" +msgstr "Lokale Adressen werden geholt." + +#: ../../src/clients/kinit/kinit.c:771 +#, c-format +msgid "while setting up KDB keytab for realm %s" +msgstr "beim Einrichten der KDB-Schlüsseltabelle für Realm %s" + +#: ../../src/clients/kinit/kinit.c:780 ../../src/clients/kvno/kvno.c:201 +#, c-format +msgid "resolving keytab %s" +msgstr "Schlüsseltabelle wird ermittelt: %s" + +#: ../../src/clients/kinit/kinit.c:785 +#, c-format +msgid "Using keytab: %s\n" +msgstr "Schlüsseltabelle wird verwendet: %s\n" + +#: ../../src/clients/kinit/kinit.c:789 +msgid "resolving default client keytab" +msgstr "Standardschlüsseltabelle des Clients wird ermittelt." + +#: ../../src/clients/kinit/kinit.c:799 +#, c-format +msgid "while setting '%s'='%s'" +msgstr "beim Setzen von »%s«=»%s«" + +#: ../../src/clients/kinit/kinit.c:804 +#, c-format +msgid "PA Option %s = %s\n" +msgstr "PA-Option %s = %s\n" + +#: ../../src/clients/kinit/kinit.c:849 +msgid "getting initial credentials" +msgstr "Anfängliche Anmeldedaten werden geholt." + +#: ../../src/clients/kinit/kinit.c:852 +msgid "validating credentials" +msgstr "Anmeldedaten werden geprüft." + +#: ../../src/clients/kinit/kinit.c:855 +msgid "renewing credentials" +msgstr "Anmeldedaten werden erneuert." + +#: ../../src/clients/kinit/kinit.c:860 +#, c-format +msgid "%s: Password incorrect while %s\n" +msgstr "%s: Passwort bei %s falsch\n" + +#: ../../src/clients/kinit/kinit.c:863 +#, c-format +msgid "while %s" +msgstr "bei %s" + +#: ../../src/clients/kinit/kinit.c:871 ../../src/slave/kprop.c:224 +#, c-format +msgid "when initializing cache %s" +msgstr "beim Initialisieren des Zwischenspeichers %s" + +#: ../../src/clients/kinit/kinit.c:876 +#, c-format +msgid "Initialized cache\n" +msgstr "initialisierter Zwischenspeicher\n" + +#: ../../src/clients/kinit/kinit.c:880 +msgid "while storing credentials" +msgstr "beim Speichern der Anmeldedaten" + +#: ../../src/clients/kinit/kinit.c:884 +#, c-format +msgid "Stored credentials\n" +msgstr "gespeicherte Anmeldedaten\n" + +#: ../../src/clients/kinit/kinit.c:891 +msgid "while switching to new ccache" +msgstr "beim Wechsel zum neuen Ccache" + +#: ../../src/clients/kinit/kinit.c:946 +#, c-format +msgid "Authenticated to Kerberos v5\n" +msgstr "Authentifiziert für Kerberos v5\n" + +#: ../../src/clients/klist/klist.c:91 +#, c-format +msgid "" +"Usage: %s [-e] [-V] [[-c] [-l] [-A] [-d] [-f] [-s] [-a [-n]]] [-k [-t] [-K]] " +"[name]\n" +msgstr "" +"Aufruf: %s [-e] [-V] [[-c] [-l] [-A] [-d] [-f] [-s] [-a [-n]]] [-k [-t] [-" +"K]] [Name]\n" + +#: ../../src/clients/klist/klist.c:93 +#, c-format +msgid "\t-c specifies credentials cache\n" +msgstr "\t-c gibt den Anmeldedatenzwischenspeicher an\n" + +#: ../../src/clients/klist/klist.c:94 +#, c-format +msgid "\t-k specifies keytab\n" +msgstr "\t-k gibt die Schlüsseltabelle an.\n" + +#: ../../src/clients/klist/klist.c:95 +#, c-format +msgid "\t (Default is credentials cache)\n" +msgstr "\t (Voreinstellung ist Anmeldedatenzwischenspeicher)\n" + +#: ../../src/clients/klist/klist.c:96 +#, c-format +msgid "\t-i uses default client keytab if no name given\n" +msgstr "" +"\t-i verwendet die Standardschlüsseltabelle des Clients, falls kein Name " +"angegeben wurde.\n" + +#: ../../src/clients/klist/klist.c:97 +#, c-format +msgid "\t-l lists credential caches in collection\n" +msgstr "\t-l listet gesammelte Anmeldedatenzwischenspeicher auf.\n" + +#: ../../src/clients/klist/klist.c:98 +#, c-format +msgid "\t-A shows content of all credential caches\n" +msgstr "\t-A zeigt den Inhalt aller Anmeldedatenzwischenspeicher an.\n" + +#: ../../src/clients/klist/klist.c:99 +#, c-format +msgid "\t-e shows the encryption type\n" +msgstr "\t-e zeigt den Verschlüsselungstyp.\n" + +#: ../../src/clients/klist/klist.c:100 +#, c-format +msgid "\t-V shows the Kerberos version and exits\n" +msgstr "\t-V zeigt die Kerberos-Version und wird beendet.\n" + +#: ../../src/clients/klist/klist.c:101 +#, c-format +msgid "\toptions for credential caches:\n" +msgstr "\tOptionen für Anmeldedatenzwischenspeicher:\n" + +#: ../../src/clients/klist/klist.c:102 +#, c-format +msgid "\t\t-d shows the submitted authorization data types\n" +msgstr "\t\t-d zeigt die übertragenen Autorisierungsdatentypen.\n" + +#: ../../src/clients/klist/klist.c:104 +#, c-format +msgid "\t\t-f shows credentials flags\n" +msgstr "t\t-f zeigt die Anmeldedatenschalter.\n" + +#: ../../src/clients/klist/klist.c:105 +#, c-format +msgid "\t\t-s sets exit status based on valid tgt existence\n" +msgstr "" +"\t\t-s setzt den Exit-Status auf Basis der Existenz eines gültigen TGTs.\n" + +#: ../../src/clients/klist/klist.c:107 +#, c-format +msgid "\t\t-a displays the address list\n" +msgstr "\t\t-a zeigt die Adressliste.\n" + +#: ../../src/clients/klist/klist.c:108 +#, c-format +msgid "\t\t\t-n do not reverse-resolve\n" +msgstr "\t\t\t-n löst nicht rückwärts auf.\n" + +#: ../../src/clients/klist/klist.c:109 +#, c-format +msgid "\toptions for keytabs:\n" +msgstr "\tOptionen für Schlüsseltabellen:\n" + +#: ../../src/clients/klist/klist.c:110 +#, c-format +msgid "\t\t-t shows keytab entry timestamps\n" +msgstr "\t\t-t zeigt die Zeitstempel der Schlüsseltabelleneinträge.\n" + +#: ../../src/clients/klist/klist.c:111 +#, c-format +msgid "\t\t-K shows keytab entry keys\n" +msgstr "\t\t-K zeigt die Schlüssel der Schlüsseltabelleneinträge.\n" + +#: ../../src/clients/klist/klist.c:230 +#, c-format +msgid "%s version %s\n" +msgstr "%s Version %s\n" + +#: ../../src/clients/klist/klist.c:282 +msgid "while getting default client keytab" +msgstr "beim Holen der Standardschlüsseltabelle des Clients" + +#: ../../src/clients/klist/klist.c:287 +msgid "while getting default keytab" +msgstr "beim Holen der Standardschlüsseltabelle" + +#: ../../src/clients/klist/klist.c:292 ../../src/kadmin/cli/keytab.c:108 +#, c-format +msgid "while resolving keytab %s" +msgstr "beim Ermitteln der Schlüsseltabelle %s" + +#: ../../src/clients/klist/klist.c:298 ../../src/kadmin/cli/keytab.c:92 +msgid "while getting keytab name" +msgstr "beim Holen des Schlüsseltabellennamens" + +#: ../../src/clients/klist/klist.c:305 ../../src/kadmin/cli/keytab.c:399 +msgid "while starting keytab scan" +msgstr "beim Start des Schlüsseltabellen-Scans" + +#: ../../src/clients/klist/klist.c:326 ../../src/clients/klist/klist.c:500 +#: ../../src/clients/ksu/ccache.c:465 ../../src/kadmin/dbutil/dump.c:550 +msgid "while unparsing principal name" +msgstr "beim Rückgängigmachen des Auswertens des Principal-Namens" + +#: ../../src/clients/klist/klist.c:350 ../../src/kadmin/cli/keytab.c:443 +msgid "while scanning keytab" +msgstr "beim Scannen der Schlüsseltabelle" + +#: ../../src/clients/klist/klist.c:354 ../../src/kadmin/cli/keytab.c:448 +msgid "while ending keytab scan" +msgstr "beim Beenden des Schlüsseltabellen-Scans" + +#: ../../src/clients/klist/klist.c:371 ../../src/clients/klist/klist.c:434 +msgid "while listing ccache collection" +msgstr "beim Aufführen der Ccache-Sammlung" + +#: ../../src/clients/klist/klist.c:411 +msgid "(Expired)" +msgstr "(abgelaufen)" + +#: ../../src/clients/klist/klist.c:466 +#, c-format +msgid "while resolving ccache %s" +msgstr "beim Ermitteln des Ccaches %s" + +#: ../../src/clients/klist/klist.c:504 +#, c-format +msgid "" +"Ticket cache: %s:%s\n" +"Default principal: %s\n" +"\n" +msgstr "" +"Ticketzwischenspeicher: %s:%s\n" +"Standard-Principal: %s\n" +"\n" + +#: ../../src/clients/klist/klist.c:518 +msgid "while starting to retrieve tickets" +msgstr "während das Abfragen der Tickets beginnt" + +#: ../../src/clients/klist/klist.c:539 +msgid "while finishing ticket retrieval" +msgstr "während das Abfragem der Tickets endet" + +#: ../../src/clients/klist/klist.c:545 +msgid "while closing ccache" +msgstr "beim Schließen des Ccaches" + +#: ../../src/clients/klist/klist.c:555 +msgid "while retrieving a ticket" +msgstr "beim Abfragen eines Tickets" + +#: ../../src/clients/klist/klist.c:667 ../../src/clients/ksu/ccache.c:450 +#: ../../src/slave/kpropd.c:1225 ../../src/slave/kpropd.c:1285 +msgid "while unparsing client name" +msgstr "beim Rückgängigmachen des Auswertens des Client-Namens" + +#: ../../src/clients/klist/klist.c:672 ../../src/clients/ksu/ccache.c:455 +#: ../../src/slave/kprop.c:240 +msgid "while unparsing server name" +msgstr "beim Rückgängigmachen des Auswertens des Server-Namens" + +#: ../../src/clients/klist/klist.c:701 ../../src/clients/ksu/ccache.c:480 +#, c-format +msgid "\tfor client %s" +msgstr "\tfür Client %s" + +#: ../../src/clients/klist/klist.c:713 ../../src/clients/ksu/ccache.c:489 +msgid "renew until " +msgstr "erneuern bis " + +#: ../../src/clients/klist/klist.c:730 ../../src/clients/ksu/ccache.c:499 +#, c-format +msgid "Flags: %s" +msgstr "Schalter: %s" + +#: ../../src/clients/klist/klist.c:749 +#, c-format +msgid "Etype (skey, tkt): %s, " +msgstr "Etype (Skey, TKT): %s, " + +#: ../../src/clients/klist/klist.c:766 +#, c-format +msgid "AD types: " +msgstr "AD-Typen" + +#: ../../src/clients/klist/klist.c:783 +#, c-format +msgid "\tAddresses: (none)\n" +msgstr "\tAdressen: (keine)\n" + +#: ../../src/clients/klist/klist.c:785 +#, c-format +msgid "\tAddresses: " +msgstr "\tAdressen: " + +#: ../../src/clients/klist/klist.c:818 +#, c-format +msgid "broken address (type %d length %d)" +msgstr "kaputte Adresse (Typ %d Länge %d)" + +#: ../../src/clients/klist/klist.c:838 +#, c-format +msgid "unknown addrtype %d" +msgstr "unbekannter »addrtype« %d" + +#: ../../src/clients/klist/klist.c:847 +#, c-format +msgid "unprintable address (type %d, error %d %s)" +msgstr "nicht druckbare Adresse (Typ %d Fehler %d %s)" + +#: ../../src/clients/kpasswd/kpasswd.c:12 ../../src/lib/krb5/krb/gic_pwd.c:396 +msgid "Enter new password" +msgstr "Geben Sie ein neues Passwort ein." + +#: ../../src/clients/kpasswd/kpasswd.c:13 ../../src/lib/krb5/krb/gic_pwd.c:404 +msgid "Enter it again" +msgstr "Geben Sie es erneut ein." + +#: ../../src/clients/kpasswd/kpasswd.c:33 +#, c-format +msgid "Unable to identify user from password file\n" +msgstr "" +"Der Benutzer kann nicht anhand der Passwortdatei identifiziert werden.\n" + +#: ../../src/clients/kpasswd/kpasswd.c:65 +#, c-format +msgid "usage: %s [principal]\n" +msgstr "Aufruf: %s [Principal]\n" + +#: ../../src/clients/kpasswd/kpasswd.c:73 +msgid "initializing kerberos library" +msgstr "Kerberos-Bibliothek wird initialisiert." + +#: ../../src/clients/kpasswd/kpasswd.c:77 +msgid "allocating krb5_get_init_creds_opt" +msgstr "krb5_get_init_creds_opt wird reserviert." + +#: ../../src/clients/kpasswd/kpasswd.c:92 +msgid "opening default ccache" +msgstr "Standard-Ccache wird geöffnet." + +#: ../../src/clients/kpasswd/kpasswd.c:97 +msgid "getting principal from ccache" +msgstr "Principal wird vom Ccache geholt." + +#: ../../src/clients/kpasswd/kpasswd.c:104 +msgid "while setting FAST ccache" +msgstr "beim Setzen des FAST-Ccaches" + +#: ../../src/clients/kpasswd/kpasswd.c:111 +msgid "closing ccache" +msgstr "Ccache wird geschlossen." + +#: ../../src/clients/kpasswd/kpasswd.c:118 +msgid "parsing client name" +msgstr "Client-Name wird ausgewertet." + +#: ../../src/clients/kpasswd/kpasswd.c:135 +msgid "Password incorrect while getting initial ticket" +msgstr "Passwort beim Holen des anfänglichen Tickets falsch" + +#: ../../src/clients/kpasswd/kpasswd.c:137 +msgid "getting initial ticket" +msgstr "Anfängliches Ticket wird geholt." + +#: ../../src/clients/kpasswd/kpasswd.c:144 +msgid "while reading password" +msgstr "beim Lesen des Passworts" + +#: ../../src/clients/kpasswd/kpasswd.c:152 +msgid "changing password" +msgstr "Passwort wird geändert." + +#: ../../src/clients/kpasswd/kpasswd.c:174 +#: ../lib/kadm5/chpass_util_strings.c:30 +#, c-format +msgid "Password changed.\n" +msgstr "Passwort geändert\n" + +#: ../../src/clients/ksu/authorization.c:369 +#, c-format +msgid "" +"Error: bad entry - %s in %s file, must be either full path or just the cmd " +"name\n" +msgstr "" +"Fehler: falscher Eintrag – %s in Datei %s muss entweder ein vollständiger " +"Pfad oder nur ein Befehlsname sein.\n" + +#: ../../src/clients/ksu/authorization.c:377 +#, c-format +msgid "" +"Error: bad entry - %s in %s file, since %s is just the cmd name, CMD_PATH " +"must be defined \n" +msgstr "" +"Fehler: falscher Eintrag – %s in Datei %s. Da %s nur ein Befehlsname ist, " +"muss CMD_PATH definiert sein.\n" + +#: ../../src/clients/ksu/authorization.c:392 +#, c-format +msgid "Error: bad entry - %s in %s file, CMD_PATH contains no paths \n" +msgstr "" +"Fehler: falscher Eintrag – %s in Datei %s. CMD_PATH enthält keine Pfade.\n" + +#: ../../src/clients/ksu/authorization.c:401 +#, c-format +msgid "Error: bad path %s in CMD_PATH for %s must start with '/' \n" +msgstr "Fehler: falscher Pfad %s in CMD_PATH für %s muss mit »/« beginnen\n" + +#: ../../src/clients/ksu/authorization.c:517 +msgid "Error: not found -> " +msgstr "Fehler: nicht gefunden -> " + +#: ../../src/clients/ksu/authorization.c:723 +#, c-format +msgid "home directory name `%s' too long, can't search for .k5login\n" +msgstr "" +"Name des Home-Verzeichnisses »%s« ist zu lang, Suche nach .k5login nicht " +"möglich\n" + +#: ../../src/clients/ksu/ccache.c:368 +#, c-format +msgid "home directory path for %s too long\n" +msgstr "Home-Verzeichnispfad für %s zu lang\n" + +#: ../../src/clients/ksu/ccache.c:461 +msgid "while retrieving principal name" +msgstr "beim Abfragen des Principal-Namens" + +#: ../../src/clients/ksu/krb_auth_su.c:57 +#: ../../src/clients/ksu/krb_auth_su.c:62 ../../src/slave/kprop.c:247 +msgid "while copying client principal" +msgstr "beim Kopieren des Client-Principals" + +#: ../../src/clients/ksu/krb_auth_su.c:69 +msgid "while creating tgt for local realm" +msgstr "beim Erstellen des TGTs für lokalen Realm" + +#: ../../src/clients/ksu/krb_auth_su.c:84 +msgid "while retrieving creds from cache" +msgstr "beim Abfragen der Anmeldedaten aus dem Zwischenspeicher" + +#: ../../src/clients/ksu/krb_auth_su.c:95 +msgid "while switching to target uid" +msgstr "beim Umschalten auf die Ziel-UID" + +#: ../../src/clients/ksu/krb_auth_su.c:100 +#, c-format +msgid "" +"WARNING: Your password may be exposed if you enter it here and are logged \n" +msgstr "" +"WARNUNG: Ihr Passwort könnte offengelegt werden, falls Sie es hier eingeben " +"und\n" + +#: ../../src/clients/ksu/krb_auth_su.c:102 +#, c-format +msgid " in remotely using an unsecure (non-encrypted) channel. \n" +msgstr "" +" in der Ferne mittels eines unsicheren (unverschlüsselten) Kanals\n" +" angemeldet sind.\n" + +#: ../../src/clients/ksu/krb_auth_su.c:114 ../../src/clients/ksu/main.c:464 +msgid "while reclaiming root uid" +msgstr "beim erneuten Beanspruchen der Root-UID" + +#: ../../src/clients/ksu/krb_auth_su.c:121 +#, c-format +msgid "does not have any appropriate tickets in the cache.\n" +msgstr "hat keine geeigneten Tickets im Zwischenspeicher.\n" + +#: ../../src/clients/ksu/krb_auth_su.c:133 +msgid "while verifying ticket for server" +msgstr "beim Prüfen des Tickets für Server" + +#: ../../src/clients/ksu/krb_auth_su.c:167 +msgid "while getting time of day" +msgstr "beim Holen der Tageszeit" + +#: ../../src/clients/ksu/krb_auth_su.c:171 +#, c-format +msgid "Kerberos password for %s: " +msgstr "Kerberos-Passwort für %s: " + +#: ../../src/clients/ksu/krb_auth_su.c:175 +#, c-format +msgid "principal name %s too long for internal buffer space\n" +msgstr "Principal-Name %s für den internen Pufferbereich zu groß\n" + +#: ../../src/clients/ksu/krb_auth_su.c:184 +#, c-format +msgid "while reading password for '%s'\n" +msgstr "beim Lesen des Passworts für »%s«\n" + +#: ../../src/clients/ksu/krb_auth_su.c:191 +#, c-format +msgid "No password given\n" +msgstr "kein Passwort angegeben\n" + +#: ../../src/clients/ksu/krb_auth_su.c:204 +#, c-format +msgid "%s: Password incorrect\n" +msgstr "%s: Passwort falsch\n" + +#: ../../src/clients/ksu/krb_auth_su.c:206 +msgid "while getting initial credentials" +msgstr "beim Holen der Anfangsanmeldedaten" + +#: ../../src/clients/ksu/krb_auth_su.c:226 +#: ../../src/clients/ksu/krb_auth_su.c:240 +#, c-format +msgid " %s while unparsing name\n" +msgstr "%s beim Rückgängigmachen der Namensauswertung\n" + +#: ../../src/clients/ksu/main.c:68 +#, c-format +msgid "" +"Usage: %s [target user] [-n principal] [-c source cachename] [-k] [-D] [-r " +"time] [-pf] [-l lifetime] [-zZ] [-q] [-e command [args... ] ] [-a " +"[args... ] ]\n" +msgstr "" +"Aufruf: %s [Zielbenutzer] [-n Principal] [-c Quellenzwischenspeichername] [-" +"k] [-D] [-r Zeit] [-pf] [-l Lebensdauer] [-zZ] [-q] [-e Befehl [Argumente " +"…] ] [-a [Argumente …] ]\n" + +#: ../../src/clients/ksu/main.c:147 +msgid "" +"program name too long - quitting to avoid triggering system logging bugs" +msgstr "" +"Programmname zu lang – wird beendet, um das Auslösen von " +"Systemprotokollierungsfehlern zu vermeiden" + +#: ../../src/clients/ksu/main.c:173 +msgid "while allocating memory" +msgstr "bei Reservieren von Speicher" + +#: ../../src/clients/ksu/main.c:186 +msgid "while setting euid to source user" +msgstr "beim Setzen der EUID auf dem Quellbenutzer" + +#: ../../src/clients/ksu/main.c:196 ../../src/clients/ksu/main.c:231 +#, c-format +msgid "Bad lifetime value (%s hours?)\n" +msgstr "falscher Wert für Lebensdauer (%s Stunden?)\n" + +#: ../../src/clients/ksu/main.c:208 ../../src/clients/ksu/main.c:292 +msgid "when gathering parameters" +msgstr "beim Zusammenstellen der Parameter" + +#: ../../src/clients/ksu/main.c:251 +#, c-format +msgid "-z option is mutually exclusive with -Z.\n" +msgstr "Die Optionen -z und -Z schließen sich gegenseitig aus.\n" + +#: ../../src/clients/ksu/main.c:259 +#, c-format +msgid "-Z option is mutually exclusive with -z.\n" +msgstr "Die Optionen -Z und -z schließen sich gegenseitig aus.\n" + +#: ../../src/clients/ksu/main.c:272 +#, c-format +msgid "while looking for credentials cache %s" +msgstr "beim Suchen nach dem Anmeldedatenzwischenspeicher %s" + +#: ../../src/clients/ksu/main.c:278 +#, c-format +msgid "malformed credential cache name %s\n" +msgstr "falsch gebildeter Anmeldedatenzwischenspeichername %s\n" + +# ksu ist eine Kerberos-Variante von su +#: ../../src/clients/ksu/main.c:336 +#, c-format +msgid "ksu: who are you?\n" +msgstr "ksu: Wer sind Sie?\n" + +#: ../../src/clients/ksu/main.c:340 +#, c-format +msgid "Your uid doesn't match your passwd entry?!\n" +msgstr "Ihre UID passt nicht zu Ihrem Passworteintrag.\n" + +#: ../../src/clients/ksu/main.c:355 +#, c-format +msgid "ksu: unknown login %s\n" +msgstr "ksu: unbekannter Anmeldename %s\n" + +#: ../../src/clients/ksu/main.c:375 +msgid "while getting source cache" +msgstr "beim Holen des Quellenzwischenspeichers" + +#: ../../src/clients/ksu/main.c:381 ../../src/clients/kvno/kvno.c:194 +msgid "while opening ccache" +msgstr "beim Öffnen des Ccaches" + +#: ../../src/clients/ksu/main.c:389 +msgid "while selecting the best principal" +msgstr "beim Auswählen des besten Principals" + +#: ../../src/clients/ksu/main.c:397 +msgid "while returning to source uid after finding best principal" +msgstr "" +"bei der Rückkehr zur Quell-UID, nachdem der beste Principal gefunden wurde" + +#: ../../src/clients/ksu/main.c:417 +#, c-format +msgid "account %s: authorization failed\n" +msgstr "Konto %s: Autorisierung fehlgeschlagen\n" + +#: ../../src/clients/ksu/main.c:442 +msgid "while parsing temporary name" +msgstr "beim Auswertens des temporären Namens" + +#: ../../src/clients/ksu/main.c:447 +msgid "while creating temporary cache" +msgstr "bei Erstellen des temporären Zwischenspeichers" + +#: ../../src/clients/ksu/main.c:453 ../../src/clients/ksu/main.c:693 +#, c-format +msgid "while copying cache %s to %s" +msgstr "beim Kopieren des Zwischenspeichers %s nach %s" + +#: ../../src/clients/ksu/main.c:471 +#, c-format +msgid "" +"WARNING: Your password may be exposed if you enter it here and are logged\n" +msgstr "" +"WARNUNG: Ihr Passwort könnte offengelegt werden, falls Sie es hier eingeben " +"und\n" + +#: ../../src/clients/ksu/main.c:473 +#, c-format +msgid " in remotely using an unsecure (non-encrypted) channel.\n" +msgstr "" +" in der Ferne über einen unsicheren (unverschlüsselten) Kanal " +"angemeldet\n" +"sind.\n" + +#: ../../src/clients/ksu/main.c:479 +#, c-format +msgid "Goodbye\n" +msgstr "Auf Wiedersehen\n" + +#: ../../src/clients/ksu/main.c:483 +#, c-format +msgid "Could not get a tgt for " +msgstr "Es konnte kein TGT geholt werden für " + +#: ../../src/clients/ksu/main.c:505 +#, c-format +msgid "Authentication failed.\n" +msgstr "Authentifizierung fehlgeschlagen.\n" + +#: ../../src/clients/ksu/main.c:513 +msgid "When unparsing name" +msgstr "beim Rückgängigmachen der Namensauswertung" + +#: ../../src/clients/ksu/main.c:517 +#, c-format +msgid "Authenticated %s\n" +msgstr "Authentifiziert %s\n" + +#: ../../src/clients/ksu/main.c:524 +msgid "while switching to target for authorization check" +msgstr "beim Wechsel des Ziels der Autorisierungsprüfung" + +#: ../../src/clients/ksu/main.c:531 +msgid "while checking authorization" +msgstr "beim Prüfen der Autorisierung" + +#: ../../src/clients/ksu/main.c:537 +msgid "while switching back from target after authorization check" +msgstr "beim Zurückwechsel vom Ziel nach der Autorisierungsprüfung" + +#: ../../src/clients/ksu/main.c:544 +#, c-format +msgid "Account %s: authorization for %s for execution of\n" +msgstr "Konto %s: Autorisierung für %s zum Ausführen von\n" + +#: ../../src/clients/ksu/main.c:546 +#, c-format +msgid " %s successful\n" +msgstr " %s erfolgreich\n" + +#: ../../src/clients/ksu/main.c:552 +#, c-format +msgid "Account %s: authorization for %s successful\n" +msgstr "Konto %s: Autorisierung für %s erfolgreich\n" + +#: ../../src/clients/ksu/main.c:564 +#, c-format +msgid "Account %s: authorization for %s for execution of %s failed\n" +msgstr "Konto %s: Autorisierung für %s zum Ausführen von %s fehlgeschlagen\n" + +#: ../../src/clients/ksu/main.c:572 +#, c-format +msgid "Account %s: authorization of %s failed\n" +msgstr "Konto %s: Autorisierung von %s fehlgeschlagen\n" + +#: ../../src/clients/ksu/main.c:587 +msgid "while calling cc_filter" +msgstr "beim Aufruf von »cc_filter«" + +#: ../../src/clients/ksu/main.c:595 +msgid "while erasing target cache" +msgstr "bei Löschen des Zielzwischenspeichers" + +#: ../../src/clients/ksu/main.c:615 +#, c-format +msgid "ksu: permission denied (shell).\n" +msgstr "ksu: Zugriff verweigert (Shell)\n" + +#: ../../src/clients/ksu/main.c:624 +#, c-format +msgid "ksu: couldn't set environment variable USER\n" +msgstr "ksu: Umgebungsvariable USER kann nicht gesetzt werden\n" + +#: ../../src/clients/ksu/main.c:630 +#, c-format +msgid "ksu: couldn't set environment variable HOME\n" +msgstr "ksu: Umgebungsvariable HOME kann nicht gesetzt werden\n" + +#: ../../src/clients/ksu/main.c:635 +#, c-format +msgid "ksu: couldn't set environment variable SHELL\n" +msgstr "ksu: Umgebungsvariable SHELL kann nicht gesetzt werden\n" + +#: ../../src/clients/ksu/main.c:646 +#, c-format +msgid "ksu: initgroups failed.\n" +msgstr "ksu: »initgroups« fehlgeschlagen\n" + +#: ../../src/clients/ksu/main.c:651 +#, c-format +msgid "Leaving uid as %s (%ld)\n" +msgstr "UID bleibt %s (%ld)\n" + +#: ../../src/clients/ksu/main.c:654 +#, c-format +msgid "Changing uid to %s (%ld)\n" +msgstr "UID wird zu %s (%ld) geändert\n" + +#: ../../src/clients/ksu/main.c:680 +msgid "while getting name of target ccache" +msgstr "beim Holen des Ziel-Ccache-Namens" + +#: ../../src/clients/ksu/main.c:700 +#, c-format +msgid "%s does not have correct permissions for %s, %s aborted" +msgstr "%s hat nicht die korrekten Rechte für %s, %s wird abgebrochen." + +#: ../../src/clients/ksu/main.c:721 +#, c-format +msgid "Internal error: command %s did not get resolved\n" +msgstr "Interner Fehler: Befehl %s wurde nicht aufgelöst\n" + +#: ../../src/clients/ksu/main.c:738 ../../src/clients/ksu/main.c:774 +#, c-format +msgid "while trying to execv %s" +msgstr "beim Versuch von »execv %s«" + +#: ../../src/clients/ksu/main.c:764 +msgid "while calling waitpid" +msgstr "beim Aufruf von »waitpid«" + +#: ../../src/clients/ksu/main.c:769 +msgid "while trying to fork." +msgstr "beim Versuch zu verzweigen." + +#: ../../src/clients/ksu/main.c:791 +msgid "while reading cache name from ccache" +msgstr "beim Lesen des Zwischenspeichernamens aus dem Ccache" + +#: ../../src/clients/ksu/main.c:797 +#, c-format +msgid "ksu: couldn't set environment variable %s\n" +msgstr "ksu: Umgebungsvariable %s kann nicht gesetzt werden\n" + +#: ../../src/clients/ksu/main.c:820 +#, c-format +msgid "while clearing the value of %s" +msgstr "beim Leeren des Werts von %s" + +#: ../../src/clients/ksu/main.c:828 +msgid "while resetting target ccache name" +msgstr "beim Zurücksetzen des Ziel-Ccache-Namens" + +#: ../../src/clients/ksu/main.c:842 +msgid "while determining target ccache name" +msgstr "beim Bestimmen des Ziel-Ccache-Namens" + +#: ../../src/clients/ksu/main.c:881 +msgid "while generating part of the target ccache name" +msgstr "beim Erzeugen eines Teils des Ziel-Ccache-Namens" + +#: ../../src/clients/ksu/main.c:887 +msgid "while allocating memory for the target ccache name" +msgstr "beim Reservieren von Speicher für den Ziel-Ccache-Namen" + +#: ../../src/clients/ksu/main.c:906 +msgid "while creating new target ccache" +msgstr "bei Erstellen von neuem Ziel-Ccache" + +#: ../../src/clients/ksu/main.c:912 +msgid "while initializing target cache" +msgstr "beim Initialisieren des Zielzwischenspeichers" + +#: ../../src/clients/ksu/main.c:952 +#, c-format +msgid "terminal name %s too long\n" +msgstr "Terminal-Name %s ist zu lang.\n" + +#: ../../src/clients/ksu/main.c:980 +msgid "while changing to target uid for destroying ccache" +msgstr "beim Ändern der Ziel-UID für das Zerstören von Ccache" + +#: ../../src/clients/kswitch/kswitch.c:44 +#, c-format +msgid "Usage: %s {-c cache_name | -p principal}\n" +msgstr "Aufruf: %s {-c Zwischenspeichername | -p Principal}\n" + +#: ../../src/clients/kswitch/kswitch.c:46 +#, c-format +msgid "\t-p specify name of principal\n" +msgstr "\t-p gibt den Namen des Principals an.\n" + +#: ../../src/clients/kswitch/kswitch.c:69 +#, c-format +msgid "Only one -c or -p option allowed\n" +msgstr "Nur eine der Optionen -c oder -p ist erlaubt.\n" + +#: ../../src/clients/kswitch/kswitch.c:88 +#, c-format +msgid "One of -c or -p must be specified\n" +msgstr "Entweder -c oder -p muss angegeben werden.\n" + +#: ../../src/clients/kswitch/kswitch.c:110 ../../src/clients/kvno/kvno.c:211 +#: ../../src/clients/kvno/kvno.c:245 ../../src/kadmin/cli/keytab.c:350 +#: ../../src/kadmin/dbutil/kdb5_util.c:576 +#, c-format +msgid "while parsing principal name %s" +msgstr "beim Auswerten des Principal-Namens %s" + +#: ../../src/clients/kswitch/kswitch.c:124 +msgid "while switching to credential cache" +msgstr "beim Wechsel auf den Anmeldedatenzwischenspeicher" + +#: ../../src/clients/kvno/kvno.c:46 +#, c-format +msgid "usage: %s [-C] [-u] [-c ccache] [-e etype]\n" +msgstr "Aufruf: %s [-C] [-u] [-c Ccache] [-e Etype]\n" + +#: ../../src/clients/kvno/kvno.c:47 +#, c-format +msgid "\t[-k keytab] [-S sname] [-U for_user [-P]]\n" +msgstr "\t[-k Schlüsseltabelle] [-S Sname] [-U für_Benutzer [-P]]\n" + +#: ../../src/clients/kvno/kvno.c:48 +#, c-format +msgid "\tservice1 service2 ...\n" +msgstr "\tDienst1 Dienst2 …\n" + +#: ../../src/clients/kvno/kvno.c:103 ../../src/clients/kvno/kvno.c:111 +#, c-format +msgid "Options -u and -S are mutually exclusive\n" +msgstr "Die Optionen -u und -S schließen sich gegenseitig aus.\n" + +#: ../../src/clients/kvno/kvno.c:126 +#, c-format +msgid "Option -P (constrained delegation) requires keytab to be specified\n" +msgstr "" +"Die Option -P (eingeschränkte Abtretung) erfordert zur Angabe eine " +"Schlüsseltabelle.\n" + +#: ../../src/clients/kvno/kvno.c:130 +#, c-format +msgid "" +"Option -P (constrained delegation) requires option -U (protocol transition)\n" +msgstr "" +"Die Option -P (eingeschränkte Abtretung) erfordert die Option -U " +"(Protokollübergang)\n" + +#: ../../src/clients/kvno/kvno.c:175 ../../src/kadmin/cli/kadmin.c:280 +msgid "while initializing krb5 library" +msgstr "beim Initialisieren der Krb5-Bibliothek" + +#: ../../src/clients/kvno/kvno.c:182 +msgid "while converting etype" +msgstr "bei der Etype-Umwandlung" + +#: ../../src/clients/kvno/kvno.c:218 +msgid "while getting client principal name" +msgstr "beim Holen des Client-Principal-Namens" + +#: ../../src/clients/kvno/kvno.c:256 +#, c-format +msgid "while formatting parsed principal name for '%s'" +msgstr "beim Formatieren des ausgewerteten Principal-Namens für »%s«" + +#: ../../src/clients/kvno/kvno.c:267 +msgid "client and server principal names must match" +msgstr "Die Principal-Namen von Client und Server müssen übereinstimmen." + +#: ../../src/clients/kvno/kvno.c:284 +#, c-format +msgid "while getting credentials for %s" +msgstr "beim Holen der Anmeldedaten für %s" + +#: ../../src/clients/kvno/kvno.c:291 +#, c-format +msgid "while decoding ticket for %s" +msgstr "beim Dekodieren des Tickets für %s" + +#: ../../src/clients/kvno/kvno.c:302 +#, c-format +msgid "while decrypting ticket for %s" +msgstr "beim Entschlüsseln des Tickets für %s" + +#: ../../src/clients/kvno/kvno.c:306 +#, c-format +msgid "%s: kvno = %d, keytab entry valid\n" +msgstr "%s: KVNO = %d, Schlüsseltabelleneintrag gültig\n" + +#: ../../src/clients/kvno/kvno.c:324 +#, c-format +msgid "%s: constrained delegation failed" +msgstr "%s: eingeschränkte Abtretung fehlgeschlagen" + +#: ../../src/clients/kvno/kvno.c:330 +#, c-format +msgid "%s: kvno = %d\n" +msgstr "%s: KVNO = %d\n" + +#: ../../src/kadmin/cli/kadmin.c:118 +#, c-format +msgid "" +"Usage: %s [-r realm] [-p principal] [-q query] [clnt|local args]\n" +"\tclnt args: [-s admin_server[:port]] [[-c ccache]|[-k [-t keytab]]]|[-n]\n" +"\tlocal args: [-x db_args]* [-d dbname] [-e \"enc:salt ...\"] [-m]\n" +"where,\n" +"\t[-x db_args]* - any number of database specific arguments.\n" +"\t\t\tLook at each database documentation for supported arguments\n" +msgstr "" +"Aufruf: %s [-r Realm] [-p Principal] [-q Abfrage] [clnt|lokale Argumente]\n" +"\tclnt Argumente: [-s Admin-Server[:Port]] [[-c Ccache]|\n" +"\t[-k [-t Schlüsseltabelle]]]|[-n] lokale Argumente: [-x DB-Argumente]*\n" +"\t[-d Datenbankname] [-e \"enc:Salt …\"] [-m]\n" +"wobei\n" +"\t[-x DB-Argumente]* - eine beliebige Anzahl datenbankspezifischer " +"Argumente\n" +"\tist. Die unterstützten Argumente finden Sie in den jeweiligen " +"\tDatenbankdokumentationen\n" + +#: ../../src/kadmin/cli/kadmin.c:292 ../../src/kadmin/cli/kadmin.c:333 +#, c-format +msgid "%s: Cannot initialize. Not enough memory\n" +msgstr "%s: Zu wenig Speicher zum Initialisieren\n" + +#: ../../src/kadmin/cli/kadmin.c:353 ../../src/kadmin/cli/kadmin.c:804 +#: ../../src/kadmin/cli/kadmin.c:1084 ../../src/kadmin/cli/kadmin.c:1634 +#: ../../src/kadmin/cli/keytab.c:159 ../../src/kadmin/dbutil/kdb5_util.c:591 +#, c-format +msgid "while parsing keysalts %s" +msgstr "beim Auswerten der Schlüssel-Salts %s" + +#: ../../src/kadmin/cli/kadmin.c:376 +#, c-format +msgid "%s: unable to get default realm\n" +msgstr "%s: Standard-Realm kann nicht geholt werden\n" + +#: ../../src/kadmin/cli/kadmin.c:396 +msgid "while opening default credentials cache" +msgstr "beim Öffnen des Standardanmeldedatenzwischenspeichers" + +#: ../../src/kadmin/cli/kadmin.c:402 +#, c-format +msgid "while opening credentials cache %s" +msgstr "beim Öffnen des Anmeldedatenzwischenspeichers %s" + +#: ../../src/kadmin/cli/kadmin.c:424 ../../src/kadmin/cli/kadmin.c:479 +#: ../../src/kadmin/cli/kadmin.c:487 ../../src/kadmin/cli/kadmin.c:494 +#, c-format +msgid "%s: out of memory\n" +msgstr "%s: Speicherplatz reicht nicht aus\n" + +#: ../../src/kadmin/cli/kadmin.c:433 ../../src/kadmin/cli/kadmin.c:448 +#: ../../src/slave/kpropd.c:681 +msgid "while canonicalizing principal name" +msgstr "während der Principal-Name in die normale Form gebracht wird" + +#: ../../src/kadmin/cli/kadmin.c:442 +msgid "creating host service principal" +msgstr "Principal des Rechnerdienstes wird erstellt" + +#: ../../src/kadmin/cli/kadmin.c:455 +#, c-format +msgid "%s: unable to canonicalize principal\n" +msgstr "%s: Principal kann nicht in die normale Form gebracht werden\n" + +#: ../../src/kadmin/cli/kadmin.c:499 +#, c-format +msgid "%s: unable to figure out a principal name\n" +msgstr "%s: Es kann kein Principal-Name herausgefunden werden.\n" + +#: ../../src/kadmin/cli/kadmin.c:507 +msgid "while setting up logging" +msgstr "beim Einrichten der Protokollierung" + +#: ../../src/kadmin/cli/kadmin.c:516 +#, c-format +msgid "Authenticating as principal %s with existing credentials.\n" +msgstr "Authentifizierung als Principal %s mit existierenden Anmeldedaten\n" + +#: ../../src/kadmin/cli/kadmin.c:522 +#, c-format +msgid "Authenticating as principal %s with password; anonymous requested.\n" +msgstr "" +"Authentifizierung als Principal %s mit Passwort; Anonymität erwünscht\n" + +#: ../../src/kadmin/cli/kadmin.c:529 +#, c-format +msgid "Authenticating as principal %s with keytab %s.\n" +msgstr "Authentifizierung als Principal %s mit Schlüsseltabelle %s\n" + +#: ../../src/kadmin/cli/kadmin.c:532 +#, c-format +msgid "Authenticating as principal %s with default keytab.\n" +msgstr "Authentifizierung als Principal %s mit Standardschlüsseltabelle\n" + +#: ../../src/kadmin/cli/kadmin.c:538 +#, c-format +msgid "Authenticating as principal %s with password.\n" +msgstr "Authentifizierung als Principal %s mit Passwort\n" + +#: ../../src/kadmin/cli/kadmin.c:546 ../../src/slave/kpropd.c:728 +#, c-format +msgid "while initializing %s interface" +msgstr "beim Initialisieren der Schnittstelle %s" + +#: ../../src/kadmin/cli/kadmin.c:560 +#, c-format +msgid "while closing ccache %s" +msgstr "beim Schließen von Ccache %s" + +#: ../../src/kadmin/cli/kadmin.c:566 +msgid "while mapping update log" +msgstr "beim Abbilden des Aktualisierungsprotokolls" + +#: ../../src/kadmin/cli/kadmin.c:581 +msgid "while unlocking locked database" +msgstr "beim Entsperren der Datenbank" + +#: ../../src/kadmin/cli/kadmin.c:590 +msgid "Administration credentials NOT DESTROYED.\n" +msgstr "Verwaltungsanmeldedaten NICHT VERNICHTET\n" + +#: ../../src/kadmin/cli/kadmin.c:639 +#, c-format +msgid "usage: delete_principal [-force] principal\n" +msgstr "Aufruf: delete_principal [-force] Principal\n" + +#: ../../src/kadmin/cli/kadmin.c:644 ../../src/kadmin/cli/kadmin.c:819 +msgid "while parsing principal name" +msgstr "beim Auswerten des Principal-Namens" + +#: ../../src/kadmin/cli/kadmin.c:650 ../../src/kadmin/cli/kadmin.c:825 +#: ../../src/kadmin/cli/kadmin.c:1217 ../../src/kadmin/cli/kadmin.c:1339 +#: ../../src/kadmin/cli/kadmin.c:1409 ../../src/kadmin/cli/kadmin.c:1858 +#: ../../src/kadmin/cli/kadmin.c:1902 ../../src/kadmin/cli/kadmin.c:1948 +#: ../../src/kadmin/cli/kadmin.c:1988 +msgid "while canonicalizing principal" +msgstr "während der Principal in die normale Form gebracht wird" + +#: ../../src/kadmin/cli/kadmin.c:654 +#, c-format +msgid "Are you sure you want to delete the principal \"%s\"? (yes/no): " +msgstr "" +"Sind Sie sicher, dass Sie den Principal »%s« löschen möchten? (yes/no): " + +#: ../../src/kadmin/cli/kadmin.c:658 +#, c-format +msgid "Principal \"%s\" not deleted\n" +msgstr "Principal »%s« nicht gelöscht\n" + +#: ../../src/kadmin/cli/kadmin.c:665 +#, c-format +msgid "while deleting principal \"%s\"" +msgstr "beim Löschen von Principal »%s«" + +#: ../../src/kadmin/cli/kadmin.c:668 +#, c-format +msgid "Principal \"%s\" deleted.\n" +msgstr "Principal »%s« gelöscht\n" + +#: ../../src/kadmin/cli/kadmin.c:669 +#, c-format +msgid "" +"Make sure that you have removed this principal from all ACLs before " +"reusing.\n" +msgstr "" +"Stellen Sie sicher, dass Sie diesen Principal aus allen ACLs entfernt haben, " +"bevor Sie ihn erneut benutzen.\n" + +#: ../../src/kadmin/cli/kadmin.c:686 +#, c-format +msgid "usage: rename_principal [-force] old_principal new_principal\n" +msgstr "Aufruf: rename_principal [-force] alter_Principal neuer_Principal\n" + +#: ../../src/kadmin/cli/kadmin.c:693 +msgid "while parsing old principal name" +msgstr "beim Auswerten des alten Principal-Namens" + +#: ../../src/kadmin/cli/kadmin.c:699 +msgid "while parsing new principal name" +msgstr "beim Auswerten des neuen Principal-Namens" + +#: ../../src/kadmin/cli/kadmin.c:705 +msgid "while canonicalizing old principal" +msgstr "während der alte Principal in die normale Form gebracht wird" + +#: ../../src/kadmin/cli/kadmin.c:711 +msgid "while canonicalizing new principal" +msgstr "während der neue Principal in die normale Form gebracht wird" + +#: ../../src/kadmin/cli/kadmin.c:715 +#, c-format +msgid "" +"Are you sure you want to rename the principal \"%s\" to \"%s\"? (yes/no): " +msgstr "" +"Sind Sie sicher, dass Sie den Principal »%s« in »%s« umbenennen möchten? " +"(yes/no): " + +#: ../../src/kadmin/cli/kadmin.c:719 +#, c-format +msgid "Principal \"%s\" not renamed\n" +msgstr "Principal »%s« wurde nicht umbenannt.\n" + +#: ../../src/kadmin/cli/kadmin.c:726 +#, c-format +msgid "while renaming principal \"%s\" to \"%s\"" +msgstr "beim Umbenennen von Principal »%s« in »%s«" + +#: ../../src/kadmin/cli/kadmin.c:730 +#, c-format +msgid "Principal \"%s\" renamed to \"%s\".\n" +msgstr "Principal »%s« wurde in »%s« umbenannt.\n" + +#: ../../src/kadmin/cli/kadmin.c:731 +#, c-format +msgid "" +"Make sure that you have removed the old principal from all ACLs before " +"reusing.\n" +msgstr "" +"Stellen Sie sicher, dass Sie den alten Principal aus allen ACLs entfernt " +"haben, bevor Sie ihn erneut benutzen.\n" + +#: ../../src/kadmin/cli/kadmin.c:746 +#, c-format +msgid "" +"usage: change_password [-randkey] [-keepold] [-e keysaltlist] [-pw password] " +"principal\n" +msgstr "" +"Aufruf: change_password [-randkey] [-keepold] [-e Schlüssel-Salt-Liste] [-pw " +"Passwort] Principal\n" + +#: ../../src/kadmin/cli/kadmin.c:772 +msgid "change_password: missing db argument" +msgstr "change_password: fehlendes Datenbankargument" + +#: ../../src/kadmin/cli/kadmin.c:778 +#, c-format +msgid "change_password: Not enough memory\n" +msgstr "change_password: zu wenig Speicher\n" + +#: ../../src/kadmin/cli/kadmin.c:786 +msgid "change_password: missing password arg" +msgstr "change_password: fehlendes Passwortargument" + +#: ../../src/kadmin/cli/kadmin.c:797 +msgid "change_password: missing keysaltlist arg" +msgstr "change_password: fehlendes Schlüssel-Salt-Listenargument" + +#: ../../src/kadmin/cli/kadmin.c:813 +msgid "missing principal name" +msgstr "fehlender Principal-Name" + +#: ../../src/kadmin/cli/kadmin.c:837 ../../src/kadmin/cli/kadmin.c:874 +#, c-format +msgid "while changing password for \"%s\"." +msgstr "beim Ändern des Passworts von »%s«." + +#: ../../src/kadmin/cli/kadmin.c:840 ../../src/kadmin/cli/kadmin.c:877 +#, c-format +msgid "Password for \"%s\" changed.\n" +msgstr "Passwort von »%s« geändert\n" + +#: ../../src/kadmin/cli/kadmin.c:846 ../../src/kadmin/cli/kadmin.c:1290 +#, c-format +msgid "while randomizing key for \"%s\"." +msgstr "beim Erzeugen eines zufälligen Schlüssels für »%s«." + +#: ../../src/kadmin/cli/kadmin.c:849 +#, c-format +msgid "Key for \"%s\" randomized.\n" +msgstr "Es wurde ein zufälliger Schlüssel für %s erzeugt\n" + +#: ../../src/kadmin/cli/kadmin.c:854 ../../src/kadmin/cli/kadmin.c:1250 +#, c-format +msgid "Enter password for principal \"%s\"" +msgstr "Geben Sie das Passwort für Principal »%s« ein." + +#: ../../src/kadmin/cli/kadmin.c:856 ../../src/kadmin/cli/kadmin.c:1252 +#, c-format +msgid "Re-enter password for principal \"%s\"" +msgstr "Geben Sie das Passwort für Principal »%s« erneut ein." + +#: ../../src/kadmin/cli/kadmin.c:861 ../../src/kadmin/cli/kadmin.c:1256 +#, c-format +msgid "while reading password for \"%s\"." +msgstr "beim Lesen des Passworts von »%s«." + +#: ../../src/kadmin/cli/kadmin.c:915 +#, c-format +msgid "Not enough memory\n" +msgstr "Speicher reicht nicht aus\n" + +#: ../../src/kadmin/cli/kadmin.c:945 ../../src/kadmin/dbutil/kdb5_util.c:623 +msgid "while getting time" +msgstr "beim Holen der Zeit" + +#: ../../src/kadmin/cli/kadmin.c:994 ../../src/kadmin/cli/kadmin.c:1007 +#: ../../src/kadmin/cli/kadmin.c:1020 ../../src/kadmin/cli/kadmin.c:1033 +#: ../../src/kadmin/cli/kadmin.c:1546 ../../src/kadmin/cli/kadmin.c:1558 +#: ../../src/kadmin/cli/kadmin.c:1601 ../../src/kadmin/cli/kadmin.c:1618 +#, c-format +msgid "Invalid date specification \"%s\".\n" +msgstr "ungültige Datumsangabe »%s«\n" + +#: ../../src/kadmin/cli/kadmin.c:1118 ../../src/kadmin/cli/kadmin.c:1333 +#: ../../src/kadmin/cli/kadmin.c:1404 ../../src/kadmin/cli/kadmin.c:1852 +#: ../../src/kadmin/cli/kadmin.c:1896 ../../src/kadmin/cli/kadmin.c:1942 +#: ../../src/kadmin/cli/kadmin.c:1982 +msgid "while parsing principal" +msgstr "beim Auswerten des Principals" + +#: ../../src/kadmin/cli/kadmin.c:1127 +#, c-format +msgid "usage: add_principal [options] principal\n" +msgstr "Aufruf: add_principal [Optionen] Principal\n" + +#: ../../src/kadmin/cli/kadmin.c:1128 ../../src/kadmin/cli/kadmin.c:1155 +#: ../../src/kadmin/cli/kadmin.c:1657 +#, c-format +msgid "\toptions are:\n" +msgstr "\tEs gibt folgende Optionen:\n" + +#: ../../src/kadmin/cli/kadmin.c:1130 +#, c-format +msgid "" +"\t\t[-randkey|-nokey] [-x db_princ_args]* [-expire expdate] [-pwexpire " +"pwexpdate] [-maxlife maxtixlife]\n" +"\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n" +"\t\t[-pw password] [-maxrenewlife maxrenewlife]\n" +"\t\t[-e keysaltlist]\n" +"\t\t[{+|-}attribute]\n" +msgstr "" +"\t\t[-randkey|-nokey] [-x DB-Principal-Argumente]* [-expire Ablaufdatum] [-" +"pwexpire Passwortablaufdatum] [-maxlife maximale_Ticketlebensdauer]\n" +"\t\t[-kvno KVNO] [-policy Richtlinie] [-clearpolicy]\n" +"\t\t[-pw Passwort] [-maxrenewlife maximale_Dauer_bis_zum_Erneuern]\n" +"\t\t[-e Schlüssel-Salt-Liste]\n" +"\t\t[{+|-}Attribut]\n" + +#: ../../src/kadmin/cli/kadmin.c:1136 +#, c-format +msgid "\tattributes are:\n" +msgstr "\tEs gibt folgende Attribute:\n" + +#: ../../src/kadmin/cli/kadmin.c:1138 ../../src/kadmin/cli/kadmin.c:1164 +#, c-format +msgid "" +"\t\tallow_postdated allow_forwardable allow_tgs_req allow_renewable\n" +"\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n" +"\t\trequires_hwauth needchange allow_svr password_changing_service\n" +"\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n" +"\n" +"where,\n" +"\t[-x db_princ_args]* - any number of database specific arguments.\n" +"\t\t\tLook at each database documentation for supported arguments\n" +msgstr "" +"\t\tallow_postdated allow_forwardable allow_tgs_req allow_renewable\n" +"\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n" +"\t\trequires_hwauth needchange allow_svr password_changing_service\n" +"\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n" +"\n" +"wobei\n" +"\t[-x DB-Principal-Argumente]* - eine beliebige Zahl\n" +"\tdatenbankspezifischer Argumente ist.\n" +"\t\t\tDie unterstützten Argumente finden Sie in der jeweiligen\n" +"Datenbankdokumentation.\n" + +#: ../../src/kadmin/cli/kadmin.c:1154 +#, c-format +msgid "usage: modify_principal [options] principal\n" +msgstr "Aufruf: modify_principal [Optionen] Principal\n" + +#: ../../src/kadmin/cli/kadmin.c:1157 +#, c-format +msgid "" +"\t\t[-x db_princ_args]* [-expire expdate] [-pwexpire pwexpdate] [-maxlife " +"maxtixlife]\n" +"\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n" +"\t\t[-maxrenewlife maxrenewlife] [-unlock] [{+|-}attribute]\n" +msgstr "" +"\t\t[-x DB-Principal-Argumente]* [-expire Ablaufdatum] [-pwexpire " +"Passwortablaufdatum] [-maxlife maximale_Ticketlebensdauer]\n" +"\t\t[-kvno KVNO] [-policy Richtlinie] [-clearpolicy]\n" +"\t\t[-maxrenewlife maximale_Dauer_bis_zum_Erneuern] [-unlock] [{+|-}" +"Attribut]\n" + +#: ../../src/kadmin/cli/kadmin.c:1224 ../../src/kadmin/cli/kadmin.c:1362 +#, c-format +msgid "WARNING: policy \"%s\" does not exist\n" +msgstr "WARNUNG: Richtlinie »%s« existiert nicht.\n" + +#: ../../src/kadmin/cli/kadmin.c:1230 +#, c-format +msgid "No policy specified for %s; assigning \"default\"\n" +msgstr "" +"Für %s wurde keine Richtlinie angegeben, es wird »default« " +"zugewiesen\n" + +#: ../../src/kadmin/cli/kadmin.c:1235 +#, c-format +msgid "No policy specified for %s; defaulting to no policy\n" +msgstr "" +"Für %s wurde keine Richtlinie angegeben, es wird die Vorgabe " +"»keine\n" +"Richtlinie« verwandt.\n" + +#: ../../src/kadmin/cli/kadmin.c:1276 +#, c-format +msgid "Admin server does not support -nokey while creating \"%s\"\n" +msgstr "" +"Der Administrationsrechner unterstützt beim Erstellen von »%s« kein -nokey\n" + +#: ../../src/kadmin/cli/kadmin.c:1298 +#, c-format +msgid "while clearing DISALLOW_ALL_TIX for \"%s\"." +msgstr "beim Löschen von DISALLOW_ALL_TIX für »%s«." + +#: ../../src/kadmin/cli/kadmin.c:1345 +#, c-format +msgid "while getting \"%s\"." +msgstr "beim Holen von »%s«." + +#: ../../src/kadmin/cli/kadmin.c:1371 +#, c-format +msgid "while modifying \"%s\"." +msgstr "beim Ändern von »%s«." + +#: ../../src/kadmin/cli/kadmin.c:1375 +#, c-format +msgid "Principal \"%s\" modified.\n" +msgstr "Principal »%s« wurde geändert.\n" + +#: ../../src/kadmin/cli/kadmin.c:1396 +#, c-format +msgid "usage: get_principal [-terse] principal\n" +msgstr "Aufruf: get_principal [-terse] Principal\n" + +#: ../../src/kadmin/cli/kadmin.c:1415 +#, c-format +msgid "while retrieving \"%s\"." +msgstr "beim Abfragen von »%s«." + +#: ../../src/kadmin/cli/kadmin.c:1420 ../../src/kadmin/cli/kadmin.c:1425 +msgid "while unparsing principal" +msgstr "beim Rückgängigmachen der Auswertung des Principals" + +#: ../../src/kadmin/cli/kadmin.c:1429 +#, c-format +msgid "Principal: %s\n" +msgstr "Principal: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1430 +#, c-format +msgid "Expiration date: %s\n" +msgstr "Ablaufdatum: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1431 ../../src/kadmin/cli/kadmin.c:1433 +#: ../../src/kadmin/cli/kadmin.c:1444 +msgid "[never]" +msgstr "[niemals]" + +#: ../../src/kadmin/cli/kadmin.c:1432 +#, c-format +msgid "Last password change: %s\n" +msgstr "Letzte Passwortänderung: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1434 +#, c-format +msgid "Password expiration date: %s\n" +msgstr "Passwortablaufdatum: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1436 ../../src/kadmin/cli/kadmin.c:1478 +msgid "[none]" +msgstr "[keins]" + +#: ../../src/kadmin/cli/kadmin.c:1437 +#, c-format +msgid "Maximum ticket life: %s\n" +msgstr "maximale Ticketlebensdauer: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1438 +#, c-format +msgid "Maximum renewable life: %s\n" +msgstr "maximale verlängerbare Lebensdauer: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1440 +#, c-format +msgid "Last modified: %s (%s)\n" +msgstr "zuletzt geändert: %s (%s)\n" + +#: ../../src/kadmin/cli/kadmin.c:1442 +#, c-format +msgid "Last successful authentication: %s\n" +msgstr "letzte erfolgreiche Authentifizierung: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1448 +#, c-format +msgid "Failed password attempts: %d\n" +msgstr "Fehlgeschlagene Anmeldeversuche: %d\n" + +#: ../../src/kadmin/cli/kadmin.c:1450 +#, c-format +msgid "Number of keys: %d\n" +msgstr "Anzahl der Schlüssel: %d\n" + +#: ../../src/kadmin/cli/kadmin.c:1457 +#, c-format +msgid "" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1464 +#, c-format +msgid "" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1470 +#, c-format +msgid "MKey: vno %d\n" +msgstr "MKey: vno %d\n" + +#: ../../src/kadmin/cli/kadmin.c:1472 +#, c-format +msgid "Attributes:" +msgstr "Attribute:" + +#: ../../src/kadmin/cli/kadmin.c:1480 +msgid " [does not exist]" +msgstr " [existiert nicht]" + +#: ../../src/kadmin/cli/kadmin.c:1481 +#, c-format +msgid "Policy: %s%s\n" +msgstr "Richtlinie: %s%s\n" + +#: ../../src/kadmin/cli/kadmin.c:1517 +#, c-format +msgid "usage: get_principals [expression]\n" +msgstr "Aufruf: get_principals [Ausdruck]\n" + +#: ../../src/kadmin/cli/kadmin.c:1522 ../../src/kadmin/cli/kadmin.c:1794 +msgid "while retrieving list." +msgstr "beim Abfragen der Liste." + +#: ../../src/kadmin/cli/kadmin.c:1647 +#, c-format +msgid "%s: parser lost count!\n" +msgstr "%s: Auswertungsprogramm verlor Anzahl!\n" + +#: ../../src/kadmin/cli/kadmin.c:1656 +#, c-format +msgid "usage; %s [options] policy\n" +msgstr "Aufruf: %s [Optionen] Richtlinie\n" + +#: ../../src/kadmin/cli/kadmin.c:1659 +#, c-format +msgid "" +"\t\t[-maxlife time] [-minlife time] [-minlength length]\n" +"\t\t[-minclasses number] [-history number]\n" +"\t\t[-maxfailure number] [-failurecountinterval time]\n" +"\t\t[-allowedkeysalts keysalts]\n" +msgstr "" +"\t\t[-maxlife Zeit] [-minlife Zeit] [-minlength Länge]\n" +"\t\t[-minclasses Anzahl] [-history Nummer]\n" +"\t\t[-maxfailure Anzahl] [-failurecountinterval Zeit]\n" +"\t\t[-allowedkeysalts Schlüssel-Salts]\n" + +#: ../../src/kadmin/cli/kadmin.c:1663 +#, c-format +msgid "\t\t[-lockoutduration time]\n" +msgstr "\t\t[-lockoutduration Dauer]\n" + +#: ../../src/kadmin/cli/kadmin.c:1682 +#, c-format +msgid "while creating policy \"%s\"." +msgstr "beim Erstellen der Richtlinie »%s«" + +#: ../../src/kadmin/cli/kadmin.c:1703 +#, c-format +msgid "while modifying policy \"%s\"." +msgstr "beim Ändern der Richtlinie »%s«" + +#: ../../src/kadmin/cli/kadmin.c:1715 +#, c-format +msgid "usage: delete_policy [-force] policy\n" +msgstr "Aufruf: delete_policy [-force] Richtlinie\n" + +#: ../../src/kadmin/cli/kadmin.c:1719 +#, c-format +msgid "Are you sure you want to delete the policy \"%s\"? (yes/no): " +msgstr "" +"Sind Sie sicher, dass Sie die Richtlinie »%s« löschen möchten? (yes/no): " + +#: ../../src/kadmin/cli/kadmin.c:1723 +#, c-format +msgid "Policy \"%s\" not deleted.\n" +msgstr "Richtlinie »%s« nicht gelöscht\n" + +#: ../../src/kadmin/cli/kadmin.c:1729 +#, c-format +msgid "while deleting policy \"%s\"" +msgstr "bei Löschen der Richtlinie »%s«" + +#: ../../src/kadmin/cli/kadmin.c:1741 +#, c-format +msgid "usage: get_policy [-terse] policy\n" +msgstr "Aufruf: get_policy [-terse] Richtlinie\n" + +#: ../../src/kadmin/cli/kadmin.c:1746 +#, c-format +msgid "while retrieving policy \"%s\"." +msgstr "beim Abfragen der Richtlinie »%s«." + +#: ../../src/kadmin/cli/kadmin.c:1751 +#, c-format +msgid "Policy: %s\n" +msgstr "Richtlinie: »%s«\n" + +#: ../../src/kadmin/cli/kadmin.c:1752 +#, c-format +msgid "Maximum password life: %ld\n" +msgstr "maximale Passwortlebensdauer: %ld\n" + +#: ../../src/kadmin/cli/kadmin.c:1753 +#, c-format +msgid "Minimum password life: %ld\n" +msgstr "minimale Passwortlebensdauer: %ld\n" + +#: ../../src/kadmin/cli/kadmin.c:1754 +#, c-format +msgid "Minimum password length: %ld\n" +msgstr "minimale Passwortlänge: %ld\n" + +#: ../../src/kadmin/cli/kadmin.c:1755 +#, c-format +msgid "Minimum number of password character classes: %ld\n" +msgstr "minimale Anzahl von Passwortzeichenklassen: %ld\n" + +#: ../../src/kadmin/cli/kadmin.c:1757 +#, c-format +msgid "Number of old keys kept: %ld\n" +msgstr "Anzahl aufbewahrter alter Schlüssel: %ld\n" + +#: ../../src/kadmin/cli/kadmin.c:1758 +#, c-format +msgid "Maximum password failures before lockout: %lu\n" +msgstr "maximale Anzahl falscher Passworteingaben vor dem Sperren: %lu\n" + +#: ../../src/kadmin/cli/kadmin.c:1760 +#, c-format +msgid "Password failure count reset interval: %s\n" +msgstr "Rücksetzintervall für zu viele falsch eingebene Passwörter: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1762 +#, c-format +msgid "Password lockout duration: %s\n" +msgstr "Passwortsperrdauer: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1765 +#, c-format +msgid "Allowed key/salt types: %s\n" +msgstr "erlaubte Schlüssel-/Salt-Typen: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1789 +#, c-format +msgid "usage: get_policies [expression]\n" +msgstr "Aufruf: get_policies [Ausdruck]\n" + +#: ../../src/kadmin/cli/kadmin.c:1811 +#, c-format +msgid "usage: get_privs\n" +msgstr "Aufruf: get_privs\n" + +#: ../../src/kadmin/cli/kadmin.c:1816 +msgid "while retrieving privileges" +msgstr "beim Abfragen von Rechten" + +#: ../../src/kadmin/cli/kadmin.c:1819 +#, c-format +msgid "current privileges:" +msgstr "aktuelle Rechte:" + +#: ../../src/kadmin/cli/kadmin.c:1845 +#, c-format +msgid "usage: purgekeys [-all|-keepkvno oldest_kvno_to_keep] principal\n" +msgstr "" +"Aufruf: purgekeys [-all|-keepkvno älteste_KVNO_die_behalten_wird] Principal\n" + +#: ../../src/kadmin/cli/kadmin.c:1865 +#, c-format +msgid "while purging keys for principal \"%s\"" +msgstr "beim vollständigen Löschen der Schlüssel für Principal »%s«" + +#: ../../src/kadmin/cli/kadmin.c:1870 +#, c-format +msgid "All keys for principal \"%s\" removed.\n" +msgstr "Alle Schlüssel für Principal »%s« wurden entfernt.\n" + +#: ../../src/kadmin/cli/kadmin.c:1872 +#, c-format +msgid "Old keys for principal \"%s\" purged.\n" +msgstr "Alte Schlüssel für Principal »%s« wurden entfernt.\n" + +#: ../../src/kadmin/cli/kadmin.c:1889 +#, c-format +msgid "usage: get_strings principal\n" +msgstr "Aufruf: get_strings Principal\n" + +#: ../../src/kadmin/cli/kadmin.c:1909 +#, c-format +msgid "while getting attributes for principal \"%s\"" +msgstr "beim Holen von Attributen für Principal »%s«" + +#: ../../src/kadmin/cli/kadmin.c:1914 +#, c-format +msgid "(No string attributes.)\n" +msgstr "(keine Zeichenkettenattribute)\n" + +#: ../../src/kadmin/cli/kadmin.c:1933 +#, c-format +msgid "usage: set_string principal key value\n" +msgstr "Aufruf: set_string Principal Schlüssel Wert\n" + +#: ../../src/kadmin/cli/kadmin.c:1955 +#, c-format +msgid "while setting attribute on principal \"%s\"" +msgstr "beim Setzen eines Attributes für Principal »%s«" + +#: ../../src/kadmin/cli/kadmin.c:1959 +#, c-format +msgid "Attribute set for principal \"%s\".\n" +msgstr "Attribute für Principal »%s« wurden gesetzt.\n" + +#: ../../src/kadmin/cli/kadmin.c:1974 +#, c-format +msgid "usage: del_string principal key\n" +msgstr "Aufruf: del_string Principal Schlüssel\n" + +#: ../../src/kadmin/cli/kadmin.c:1995 +#, c-format +msgid "while deleting attribute from principal \"%s\"" +msgstr "beim Löschen eines Attributs von Principal »%s«" + +#: ../../src/kadmin/cli/kadmin.c:1999 +#, c-format +msgid "Attribute removed from principal \"%s\".\n" +msgstr "Attribut von Principal »%s« wurde gelöscht.\n" + +#: ../../src/kadmin/cli/keytab.c:56 +#, c-format +msgid "" +"Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [-norandkey] " +"[principal | -glob princ-exp] [...]\n" +msgstr "" +"Aufruf: ktadd [-k[eytab] Schlüsseltabelle] [-q] [-e Schlüssel-Salt-Liste] [-" +"norandkey] [Principal | -glob Principal-Ausdruck] […]\n" + +#: ../../src/kadmin/cli/keytab.c:59 +#, c-format +msgid "" +"Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [principal | -glob " +"princ-exp] [...]\n" +msgstr "" +"Aufruf: ktadd [-k[eytab] Schlüsseltabelle] [-q] [-e Schlüssel-Salt-Liste] " +"[Principal | -glob Principal-Ausdruck] […]\n" + +#: ../../src/kadmin/cli/keytab.c:67 +#, c-format +msgid "" +"Usage: ktremove [-k[eytab] keytab] [-q] principal [kvno|\"all\"|\"old\"]\n" +msgstr "" +"Aufruf: ktremove [-k[eytab] Schlüsseltabelle] [-q] Principal " +"[kvno|»all«|»old«]\n" + +#: ../../src/kadmin/cli/keytab.c:81 ../../src/kadmin/cli/keytab.c:102 +msgid "while creating keytab name" +msgstr "beim Erstellen des Schlüsseltabellennamens" + +#: ../../src/kadmin/cli/keytab.c:86 +msgid "while opening default keytab" +msgstr "beim Öffnen der Standardschlüsseltabelle" + +#: ../../src/kadmin/cli/keytab.c:147 +#, c-format +msgid "-norandkey option only valid for kadmin.local\n" +msgstr "Die Option »-norandkey« ist nur für »kadmin.local« gültig.\n" + +#: ../../src/kadmin/cli/keytab.c:176 +#, c-format +msgid "cannot specify keysaltlist when not changing key\n" +msgstr "" +"Schlüssel-Salt-Liste kann nicht angegeben werden, wenn der Schlüssel nicht " +"geändert wird\n" + +#: ../../src/kadmin/cli/keytab.c:192 +#, c-format +msgid "while expanding expression \"%s\"." +msgstr "beim Expandieren des Ausdrucks »%s«." + +#: ../../src/kadmin/cli/keytab.c:211 ../../src/kadmin/cli/keytab.c:251 +msgid "while closing keytab" +msgstr "beim Schließen der Schlüsseltabelle" + +#: ../../src/kadmin/cli/keytab.c:275 +#, c-format +msgid "while parsing -add principal name %s" +msgstr "beim Auswerten von »-add Principal-Name %s«" + +#: ../../src/kadmin/cli/keytab.c:289 +#, c-format +msgid "%s: Principal %s does not exist.\n" +msgstr "%s: Principal %s existiert nicht.\n" + +#: ../../src/kadmin/cli/keytab.c:292 +#, c-format +msgid "while changing %s's key" +msgstr "beim Ändern des Schlüssels von %s" + +#: ../../src/kadmin/cli/keytab.c:299 +msgid "while retrieving principal" +msgstr "beim Abfragen des Principals" + +#: ../../src/kadmin/cli/keytab.c:311 +msgid "while adding key to keytab" +msgstr "beim Hinzufügen des Schlüssels zur Schlüsseltabelle" + +#: ../../src/kadmin/cli/keytab.c:317 +#, c-format +msgid "" +"Entry for principal %s with kvno %d, encryption type %s added to keytab %s.\n" +msgstr "" +"Der Eintrag für Principal %s mit KVNO %d und Verschlüsselungstyp %s wurde " +"der Schlüsseltabelle %s hinzugefügt.\n" + +#: ../../src/kadmin/cli/keytab.c:326 +msgid "while freeing principal entry" +msgstr "beim Freigeben des Principal-Eintrags" + +#: ../../src/kadmin/cli/keytab.c:373 +#, c-format +msgid "%s: Keytab %s does not exist.\n" +msgstr "%s: Schlüsseltabelle %s existiert nicht.\n" + +#: ../../src/kadmin/cli/keytab.c:377 +#, c-format +msgid "%s: No entry for principal %s exists in keytab %s\n" +msgstr "" +"%s: Für Principal %s existiert kein Eintrag in der Schlüsseltabelle %s.\n" + +#: ../../src/kadmin/cli/keytab.c:381 +#, c-format +msgid "%s: No entry for principal %s with kvno %d exists in keytab %s\n" +msgstr "" +"%s: Für den Principal %s mit der KVNO %d existiert kein Eintrag in der " +"Schlüsseltabelle %s.\n" + +#: ../../src/kadmin/cli/keytab.c:387 +msgid "while retrieving highest kvno from keytab" +msgstr "beim Abfragen der höchsten KVNO der Schlüsseltabelle" + +#: ../../src/kadmin/cli/keytab.c:420 +msgid "while temporarily ending keytab scan" +msgstr "beim Unterbrechen des Schlüsseltabellen-Scans" + +#: ../../src/kadmin/cli/keytab.c:425 +msgid "while deleting entry from keytab" +msgstr "beim Löschen eines Eintrags aus der Schlüsseltabelle" + +#: ../../src/kadmin/cli/keytab.c:430 +msgid "while restarting keytab scan" +msgstr "bei der Wiederaufnahme des Schlüsseltabellen-Scans" + +#: ../../src/kadmin/cli/keytab.c:436 +#, c-format +msgid "Entry for principal %s with kvno %d removed from keytab %s.\n" +msgstr "" +"Der Eintrag für Principal %s mit KVNO %d wurde aus der Schlüsseltabelle %s " +"entfernt.\n" + +#: ../../src/kadmin/cli/keytab.c:458 +#, c-format +msgid "%s: There is only one entry for principal %s in keytab %s\n" +msgstr "" +"%s: Es gibt nur einen Eintrag für Principal %s in der Schlüsseltabelle %s.\n" + +#: ../../src/kadmin/cli/ss_wrapper.c:49 ../../src/kadmin/ktutil/ktutil.c:58 +msgid "creating invocation" +msgstr "Aufruf wird erstellt" + +#: ../../src/kadmin/dbutil/dump.c:165 +msgid "while allocating temporary filename dump" +msgstr "beim Reservieren des temporären Dateinamenspeicherauszugs" + +#: ../../src/kadmin/dbutil/dump.c:176 +msgid "while renaming dump file into place" +msgstr "während das Umbenennen der Auszugsdateien Gestalt annimmt" + +#: ../../src/kadmin/dbutil/dump.c:192 +msgid "while allocating dump_ok filename" +msgstr "beim Reservieren des »dump_ok«-Dateinamens" + +#: ../../src/kadmin/dbutil/dump.c:199 +#, c-format +msgid "while creating 'ok' file, '%s'" +msgstr "beim Erstellen der Datei »ok«, »%s«" + +#: ../../src/kadmin/dbutil/dump.c:206 +#, c-format +msgid "while locking 'ok' file, '%s'" +msgstr "beim Sperren der Datei »ok«, »%s«" + +#: ../../src/kadmin/dbutil/dump.c:248 ../../src/kadmin/dbutil/dump.c:277 +#, c-format +msgid "%s: regular expression error: %s\n" +msgstr "%s: Fehler im regulären Ausdruck: %s\n" + +#: ../../src/kadmin/dbutil/dump.c:260 +#, c-format +msgid "%s: regular expression match error: %s\n" +msgstr "%s: Fehler beim Abgleich mit regulärem Ausdruck: %s\n" + +#: ../../src/kadmin/dbutil/dump.c:361 +#, c-format +msgid "%s: tagged data list inconsistency for %s (counted %d, stored %d)\n" +msgstr "" +"%s: Unstimmigkeit in der markierten Datenliste für %s (%d gezählt, %d " +"gespeichert)\n" + +#: ../../src/kadmin/dbutil/dump.c:519 +#, c-format +msgid "" +"Warning! Multiple DES-CBC-CRC keys for principal %s; skipping duplicates.\n" +msgstr "" +"Warnung! Mehrere DES-CBC-CRC-Schlüssel für Principal %s, Duplikate werden " +"übersprungen.\n" + +#: ../../src/kadmin/dbutil/dump.c:530 +#, c-format +msgid "" +"Warning! No DES-CBC-CRC key for principal %s, cannot generate OV-compatible " +"record; skipping\n" +msgstr "" +"Warnung! Kein DES-CBC-CRC-Schlüssel für Principal %s, es kann kein OV-" +"kompatibler Datensatz erzeugt werden, wird übersprungen\n" + +#: ../../src/kadmin/dbutil/dump.c:558 +#, c-format +msgid "while converting %s to new master key" +msgstr "beim Umwandeln von %s in den neuen Hauptschlüssel" + +#: ../../src/kadmin/dbutil/dump.c:579 +#, c-format +msgid "%s(%d): %s\n" +msgstr "%s(%d): %s\n" + +#: ../../src/kadmin/dbutil/dump.c:622 +#, c-format +msgid "%s(%d): ignoring trash at end of line: " +msgstr "%s(%d): Müll am Zeilenende wird ignoriert: " + +#: ../../src/kadmin/dbutil/dump.c:685 +msgid "cannot read tagged data type and length" +msgstr "Markierter Datentyp und Länge können nicht gelesen werden." + +#: ../../src/kadmin/dbutil/dump.c:692 +msgid "cannot read tagged data contents" +msgstr "Inhalt der markierten Daten kann nicht gelesen werden." + +#: ../../src/kadmin/dbutil/dump.c:726 +msgid "cannot match size tokens" +msgstr "Größenmerkmale können nicht zugeordnet werden." + +#: ../../src/kadmin/dbutil/dump.c:755 +msgid "cannot read name string" +msgstr "Namenszeichenkette kann nicht gelesen werden." + +#: ../../src/kadmin/dbutil/dump.c:760 +#, c-format +msgid "while parsing name %s" +msgstr "beim Auswerten des Namens %s" + +#: ../../src/kadmin/dbutil/dump.c:768 +msgid "cannot read principal attributes" +msgstr "Principal-Attribute können nicht gelesen werden." + +#: ../../src/kadmin/dbutil/dump.c:821 +msgid "cannot read key size and version" +msgstr "Schlüssellänge und -version können nicht gelesen werden." + +#: ../../src/kadmin/dbutil/dump.c:832 +msgid "cannot read key type and length" +msgstr "Schlüsseltyp und -länge können nicht gelesen werden." + +#: ../../src/kadmin/dbutil/dump.c:838 +msgid "cannot read key data" +msgstr "Schlüsseldaten können nicht gelesen werden." + +#: ../../src/kadmin/dbutil/dump.c:848 +msgid "cannot read extra data" +msgstr "Zusätzliche Daten können nicht gelesen werden." + +#: ../../src/kadmin/dbutil/dump.c:857 +#, c-format +msgid "while storing %s" +msgstr "beim Speichern von %s" + +#: ../../src/kadmin/dbutil/dump.c:896 ../../src/kadmin/dbutil/dump.c:935 +#: ../../src/kadmin/dbutil/dump.c:981 +#, c-format +msgid "cannot parse policy (%d read)\n" +msgstr "Richtlinie kann nicht ausgewertet werden (%d gelesen)\n" + +#: ../../src/kadmin/dbutil/dump.c:904 ../../src/kadmin/dbutil/dump.c:943 +#: ../../src/kadmin/dbutil/dump.c:1001 +msgid "while creating policy" +msgstr "beim Erstellen der Richtlinie" + +#: ../../src/kadmin/dbutil/dump.c:908 +#, c-format +msgid "created policy %s\n" +msgstr "erstellte Richtlinie %s\n" + +#: ../../src/kadmin/dbutil/dump.c:1038 +#, c-format +msgid "unknown record type \"%s\"\n" +msgstr "unbekannter Datensatztyp »%s«\n" + +#: ../../src/kadmin/dbutil/dump.c:1167 +#, c-format +msgid "%s: Unknown iprop dump version %d\n" +msgstr "%s: unbekannte Iprop-Auszugsversion %d\n" + +#: ../../src/kadmin/dbutil/dump.c:1270 ../../src/kadmin/dbutil/dump.c:1498 +#, c-format +msgid "Iprop not enabled\n" +msgstr "Iprop nicht aktiviert\n" + +#: ../../src/kadmin/dbutil/dump.c:1308 +msgid "Conditional dump is an undocumented option for use only for iprop dumps" +msgstr "" +"Bedingter Auszug ist eine nicht dokumentierte Option, die nur für Iprop-" +"Auszüge benutzt wird." + +#: ../../src/kadmin/dbutil/dump.c:1321 +msgid "Database not currently opened!" +msgstr "Die Datenbank ist zur Zeit nicht geöffnet!" + +#: ../../src/kadmin/dbutil/dump.c:1335 +#: ../../src/kadmin/dbutil/kdb5_stash.c:116 +#: ../../src/kadmin/dbutil/kdb5_util.c:479 +msgid "while reading master key" +msgstr "beim Lesen des Hauptschlüssels" + +#: ../../src/kadmin/dbutil/dump.c:1341 +msgid "while verifying master key" +msgstr "beim Prüfen des Hauptschlüssels" + +#: ../../src/kadmin/dbutil/dump.c:1360 ../../src/kadmin/dbutil/dump.c:1370 +msgid "while reading new master key" +msgstr "beim Lesen des neuen Hauptschlüssels" + +#: ../../src/kadmin/dbutil/dump.c:1364 +#, c-format +msgid "Please enter new master key....\n" +msgstr "Bitte geben Sie den neuen Hauptschlüssel ein …\n" + +#: ../../src/kadmin/dbutil/dump.c:1388 +#, c-format +msgid "while opening %s for writing" +msgstr "beim Öffnen von %s zum Schreiben" + +#: ../../src/kadmin/dbutil/dump.c:1403 +msgid "while reading update log header" +msgstr "beim Lesen der Aktualisierungsprotokollkopfzeilen" + +#: ../../src/kadmin/dbutil/dump.c:1418 ../../src/kadmin/dbutil/dump.c:1425 +#, c-format +msgid "performing %s dump" +msgstr "Auszug von %s wird durchgeführt" + +#: ../../src/kadmin/dbutil/dump.c:1455 +#, c-format +msgid "%s: error processing line %d of %s\n" +msgstr "%s: Fehler beim Verarbeiten von Zeile %d von %s\n" + +#: ../../src/kadmin/dbutil/dump.c:1507 +msgid "while parsing options" +msgstr "beim Auswerten der Optionen" + +#: ../../src/kadmin/dbutil/dump.c:1522 +#, c-format +msgid "while opening %s" +msgstr "beim Öffnen von %s" + +#: ../../src/kadmin/dbutil/dump.c:1527 ../../src/kadmin/dbutil/dump.c:1626 +msgid "standard input" +msgstr "Standardeingabe" + +#: ../../src/kadmin/dbutil/dump.c:1532 +#, c-format +msgid "%s: can't read dump header in %s\n" +msgstr "%s: Kopfzeilen des Auszugs in %s können nicht gelesen werden.\n" + +#: ../../src/kadmin/dbutil/dump.c:1540 ../../src/kadmin/dbutil/dump.c:1557 +#, c-format +msgid "%s: dump header bad in %s\n" +msgstr "%s: falsche Kopfzeilen des Auszugs in %s\n" + +#: ../../src/kadmin/dbutil/dump.c:1566 +#, c-format +msgid "Could not open iprop ulog\n" +msgstr "Iprop-Ulog kann nicht geöffnet werden.\n" + +#: ../../src/kadmin/dbutil/dump.c:1571 +#, c-format +msgid "%s: dump version %s can only be loaded with the -update flag\n" +msgstr "" +"%s: Die Auszugsversion %s kann nur mit dem Schalter -update geladen werden.\n" + +#: ../../src/kadmin/dbutil/dump.c:1580 ../../src/kadmin/dbutil/dump.c:1585 +msgid "computing parameters for database" +msgstr "Parameter für die Datenbank werden berechnet." + +#: ../../src/kadmin/dbutil/dump.c:1591 +msgid "while creating database" +msgstr "beim Erstellen der Datenbank" + +#: ../../src/kadmin/dbutil/dump.c:1600 +msgid "while opening database" +msgstr "beim Öffnen der Datenbank" + +#: ../../src/kadmin/dbutil/dump.c:1610 +msgid "while permanently locking database" +msgstr "beim dauerhaften Sperren der Datenbank" + +#: ../../src/kadmin/dbutil/dump.c:1628 +#, c-format +msgid "%s: %s restore failed\n" +msgstr "%s: Wiederherstellen von %s fehlgeschlagen\n" + +#: ../../src/kadmin/dbutil/dump.c:1633 +msgid "while unlocking database" +msgstr "beim Aufheben der Datenbanksperre" + +#: ../../src/kadmin/dbutil/dump.c:1643 ../../src/kadmin/dbutil/dump.c:1662 +msgid "while reinitializing update log" +msgstr "beim erneuten Initialisieren des Aktualisierungsprotokolls" + +#: ../../src/kadmin/dbutil/dump.c:1653 +msgid "while making newly loaded database live" +msgstr "beim Aktivieren der neu geladenen Datenbank" + +#: ../../src/kadmin/dbutil/dump.c:1669 +msgid "while writing update log header" +msgstr "beim Schreiben der Aktualisierungsprotokollkopfzeilen" + +#: ../../src/kadmin/dbutil/dump.c:1683 +#, c-format +msgid "while deleting bad database %s" +msgstr "beim Löschen der falschen Datenbank %s" + +#: ../../src/kadmin/dbutil/kadm5_create.c:84 +msgid "while looking up the Kerberos configuration" +msgstr "beim Nachschlagen der Kerberos-Konfiguration" + +#: ../../src/kadmin/dbutil/kadm5_create.c:111 +msgid "while initializing the Kerberos admin interface" +msgstr "beim Initialisieren der Kerberos-Administrationsoberfläche" + +#: ../../src/kadmin/dbutil/kadm5_create.c:169 +#, c-format +msgid "getaddrinfo(%s): Cannot determine canonical hostname.\n" +msgstr "" +"getaddrinfo(%s): Die Normalform des Rechnernamens kann nicht bestimmt " +"werden.\n" + +#: ../../src/kadmin/dbutil/kadm5_create.c:190 +#: ../../src/kadmin/dbutil/kadm5_create.c:196 +#, c-format +msgid "Out of memory\n" +msgstr "Speicherplatz reicht nicht aus.\n" + +#: ../../src/kadmin/dbutil/kadm5_create.c:270 +msgid "while appending realm to principal" +msgstr "beim Anhängen des Realms an den Principal" + +#: ../../src/kadmin/dbutil/kadm5_create.c:275 +msgid "while parsing admin principal name" +msgstr "beim Auswerten des Principal-Namens des Administrators" + +#: ../../src/kadmin/dbutil/kadm5_create.c:286 +#, c-format +msgid "while creating principal %s" +msgstr "beim Erstellen des Principals %s" + +#: ../../src/kadmin/dbutil/kdb5_create.c:175 +#: ../../src/kadmin/dbutil/kdb5_util.c:241 +#: ../../src/kadmin/dbutil/kdb5_util.c:248 +msgid "while parsing command arguments\n" +msgstr "beim Auswerten der Befehlsargumente\n" + +#: ../../src/kadmin/dbutil/kdb5_create.c:198 +#, c-format +msgid "Loading random data\n" +msgstr "Zufällige Daten werden geladen.\n" + +#: ../../src/kadmin/dbutil/kdb5_create.c:201 +msgid "Loading random data" +msgstr "Zufällige Daten werden geladen." + +#: ../../src/kadmin/dbutil/kdb5_create.c:211 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:242 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:435 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:591 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1149 +#: ../../src/kadmin/dbutil/kdb5_util.c:423 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:606 +msgid "while setting up master key name" +msgstr "beim Einrichten des Hauptschlüsselnamens" + +#: ../../src/kadmin/dbutil/kdb5_create.c:222 +#, c-format +msgid "" +"Initializing database '%s' for realm '%s',\n" +"master key name '%s'\n" +msgstr "" +"Datenbank »%s« für Realm »%s« wird initialisiert,\n" +"Hauptschlüsselname »%s«\n" + +#: ../../src/kadmin/dbutil/kdb5_create.c:227 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:516 +#, c-format +msgid "You will be prompted for the database Master Password.\n" +msgstr "Sie werden nach dem Master-Passwort der Datenbank gefragt.\n" + +#: ../../src/kadmin/dbutil/kdb5_create.c:228 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:260 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:517 +#, c-format +msgid "It is important that you NOT FORGET this password.\n" +msgstr "Es ist wichtig, dass Sie dieses Passwort NICHT VERGESSEN.\n" + +#: ../../src/kadmin/dbutil/kdb5_create.c:234 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:266 +msgid "while creating new master key" +msgstr "beim Erstellen des neuen Hauptschlüssels" + +#: ../../src/kadmin/dbutil/kdb5_create.c:242 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:527 +msgid "while reading master key from keyboard" +msgstr "beim Lesen des Hauptschlüssels von der Tastatur" + +#: ../../src/kadmin/dbutil/kdb5_create.c:252 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:285 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:618 +msgid "while calculating master key salt" +msgstr "beim Berechnen des Hauptschlüssel-Salts" + +#: ../../src/kadmin/dbutil/kdb5_create.c:260 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:294 +#: ../../src/kadmin/dbutil/kdb5_util.c:465 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:630 +msgid "while transforming master key from password" +msgstr "beim Umwandeln des Hauptschlüssels vom Passwort" + +#: ../../src/kadmin/dbutil/kdb5_create.c:270 +msgid "while initializing random key generator" +msgstr "beim Initialisieren des Zufallsschlüsselgenerators" + +#: ../../src/kadmin/dbutil/kdb5_create.c:275 +#, c-format +msgid "while creating database '%s'" +msgstr "beim Erstellen der Datenbank »%s«" + +#: ../../src/kadmin/dbutil/kdb5_create.c:293 +msgid "while creating update log" +msgstr "beim Erstellen des Aktualisierungsprotokolls" + +#: ../../src/kadmin/dbutil/kdb5_create.c:304 +msgid "while initializing update log" +msgstr "beim Initialisieren des Aktualisierungsprotokolls" + +#: ../../src/kadmin/dbutil/kdb5_create.c:320 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:642 +msgid "while adding entries to the database" +msgstr "beim Hinzufügen von Einträgen in die Datenbank" + +#: ../../src/kadmin/dbutil/kdb5_create.c:348 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:339 +#: ../../src/kadmin/dbutil/kdb5_stash.c:133 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:667 +msgid "while storing key" +msgstr "beim Speichern des Schlüssels" + +#: ../../src/kadmin/dbutil/kdb5_create.c:349 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:340 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:668 +#, c-format +msgid "Warning: couldn't stash master key.\n" +msgstr "Warnung: Hauptschlüssel kann nicht gelagert werden.\n" + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:57 +msgid "while initializing krb5_context" +msgstr "beim Initialisieren von »krb5_context«" + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:63 +#: ../../src/kadmin/dbutil/kdb5_util.c:259 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:291 +msgid "while setting default realm name" +msgstr "beim Einstellen des Standard-Realm-Namens" + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:83 +#, c-format +msgid "Deleting KDC database stored in '%s', are you sure?\n" +msgstr "" +"Die in »%s« gespeicherte KDC-Datenbank wird gelöscht. Sind Sie sicher?\n" + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:85 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1166 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:360 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1482 +#, c-format +msgid "(type 'yes' to confirm)? " +msgstr "(Geben Sie als Bestätigung »yes« ein)? " + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:92 +#, c-format +msgid "OK, deleting database '%s'...\n" +msgstr "OK, Datenbank »%s« wird gelöscht …\n" + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:97 +#, c-format +msgid "deleting database '%s'" +msgstr "Datenbank »%s« wird gelöscht." + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:106 +#, c-format +msgid "** Database '%s' destroyed.\n" +msgstr "** Datenbank »%s« vernichtet\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:218 +#, c-format +msgid "%s is an invalid enctype" +msgstr "%s ist ein ungültiger Verschlüsselungstyp" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:250 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:443 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:599 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:986 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1157 +#, c-format +msgid "while getting master key principal %s" +msgstr "beim Holen des Hauptschlüssels von Principal %s" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:256 +#, c-format +msgid "Creating new master key for master key principal '%s'\n" +msgstr "" +"Es wird ein neuer Hauptschlüssel für den Hauptschlüssel-Principal »%s« " +"erstellt.\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:259 +#, c-format +msgid "You will be prompted for a new database Master Password.\n" +msgstr "Sie werden nach einem neuen Datenbank-Master-Passwort gefragt.\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:275 +msgid "while reading new master key from keyboard" +msgstr "beim Lesen des neuen Hauptschlüssels von der Tastatur" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:304 +msgid "adding new master key to master principal" +msgstr "dem Haupt-Principal wird ein neuer Hauptschlüssel hinzugefügt" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:310 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:402 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:843 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1356 +msgid "while getting current time" +msgstr "beim Holen der aktuellen Zeit" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:317 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:544 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1363 +msgid "while updating the master key principal modification time" +msgstr "beim Aktulisieren der Änderungszeit des Hauptschlüssel-Principals" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:325 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:553 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1374 +msgid "while adding master key entry to the database" +msgstr "beim Hinzufügen des Hauptschlüsseleintrags zur Datenbank" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:383 +msgid "0 is an invalid KVNO value" +msgstr "0 ist kein gültiger KVNO-Wert" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:394 +#, c-format +msgid "%d is an invalid KVNO value" +msgstr "%d ist kein gültiger KVNO-Wert" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:410 +#, c-format +msgid "could not parse date-time string '%s'" +msgstr "»date-time«-Zeichenkette »%s« konnte nicht ausgewertet werden" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:452 +msgid "while looking up active version of master key" +msgstr "beim Nachschlagen der aktiven Version des Hauptschlüssels" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:491 +msgid "while adding new master key" +msgstr "beim Hinzufügen eines neuen Hauptschlüssels" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:529 +msgid "there must be one master key currently active" +msgstr "ein Hauptschlüssel muss derzeit aktiv sein" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:537 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1342 +msgid "while updating actkvno data for master principal entry" +msgstr "beim Aktualisieren der Actkvno-Daten für den Haupt-Principal-Eintrag" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:581 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:948 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1116 +msgid "master keylist not initialized" +msgstr "Hauptschlüsselliste ist nicht initialisiert" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:607 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:994 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1254 +msgid "while looking up active kvno list" +msgstr "beim Nachschlagen der Liste aktiver KVNOs" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:615 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1002 +msgid "while looking up active master key" +msgstr "beim Nachschlagen des aktiven Hauptschlüssels" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:627 +msgid "while getting enctype description" +msgstr "beim Holen des Verschlüsselungsbeschreibung" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:644 +#, c-format +msgid "KVNO: %d, Enctype: %s, Active on: %s *\n" +msgstr "KVNO: %d, Verschlüsselungstyp: %s, aktiviert auf: %s *\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:649 +#, c-format +msgid "KVNO: %d, Enctype: %s, Active on: %s\n" +msgstr "KVNO: %d, Verschlüsselungstyp: %s, aktiviert auf: %s\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:653 +#, c-format +msgid "KVNO: %d, Enctype: %s, No activate time set\n" +msgstr "KVNO: %d, Verschlüsselungstyp: %s, keine Aktivierungszeit gesetzt\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:658 +msgid "asprintf could not allocate enough memory to hold output" +msgstr "" +"Asprintf konnte nicht genug Speicher reservieren, um die Ausgabe " +"bereitzuhalten" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:793 +msgid "getting string representation of principal name" +msgstr "Principal-Name wird im Klartext geholt" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:817 +#, c-format +msgid "determining master key used for principal '%s'" +msgstr "Hauptschlüssel, der für Principal »%s« benutzt wird, wird bestimmt" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:823 +#, c-format +msgid "would skip: %s\n" +msgstr "würde übersprungen: %s\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:825 +#, c-format +msgid "skipping: %s\n" +msgstr "wird übersprungen: %s\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:831 +#, c-format +msgid "would update: %s\n" +msgstr "würde aktualisiert: %s\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:835 +#, c-format +msgid "updating: %s\n" +msgstr "wird aktualisiert: %s\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:839 +#, c-format +msgid "error re-encrypting key for principal '%s'" +msgstr "Fehler beim erneuten Verschlüsseln des Schlüssels für Principal »%s«" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:850 +#, c-format +msgid "while updating principal '%s' modification time" +msgstr "beim Aktualisieren der Änderungszeit von Principal »%s«" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:857 +#, c-format +msgid "while updating principal '%s' key data in the database" +msgstr "" +"beim Aktualisieren der Schlüsseldaten von Principal »%s« in der Datenbank" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:889 +#, c-format +msgid "" +"\n" +"(type 'yes' to confirm)? " +msgstr "" +"\n" +"(Geben Sie als Bestätigung »yes« ein) " + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:942 +msgid "while formatting master principal name" +msgstr "beim Formatieren des Haupt-Principal-Namens" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:959 +#, c-format +msgid "converting glob pattern '%s' to regular expression" +msgstr "Platzhalter »%s« wird in einen regulären Ausdruck umgewandelt" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:977 +#, c-format +msgid "error compiling converted regexp '%s'" +msgstr "Fehler beim Kompilieren des umgewandelten regulären Ausdrucks »%s«" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1010 +#, c-format +msgid "Re-encrypt all keys not using master key vno %u?" +msgstr "" +"Sollen alle Schlüssel neu verschlüsselt werden, die nicht die Hauptschlüssel-" +"VNO %u verwenden?" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1012 +#, c-format +msgid "OK, doing nothing.\n" +msgstr "Ok, es wird nichts getan.\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1018 +#, c-format +msgid "Principals whose keys WOULD BE re-encrypted to master key vno %u:\n" +msgstr "" +"Principals, deren Schlüssel mit dem Hauptschlüssel VNO %u neu verschlüsselt " +"WÜRDEN:\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1021 +#, c-format +msgid "" +"Principals whose keys are being re-encrypted to master key vno %u if " +"necessary:\n" +msgstr "" +"Principals, deren Schlüssel mit dem Hauptschlüssel VNO %u neu verschlüsselt " +"werden, falls nötig:\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1037 +msgid "trying to process principal database" +msgstr "es wird versucht, die Principal-Datenbank zu verarbeiten" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1042 +#, c-format +msgid "%u principals processed: %u would be updated, %u already current\n" +msgstr "" +"%u Principals verarbeitet: %u würden aktualisiert, %u bereits aktuell\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1046 +#, c-format +msgid "%u principals processed: %u updated, %u already current\n" +msgstr "%u Principals verarbeitet: %u aktualisiert, %u bereits aktuell\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1164 +#, c-format +msgid "" +"Will purge all unused master keys stored in the '%s' principal, are you " +"sure?\n" +msgstr "" +"Sind Sie sicher, dass alle nicht verwendeten Hauptschlüssel, die für " +"Principal »%s« gespeichert sind, vollständig entfernt werden sollen?\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1175 +#, c-format +msgid "OK, purging unused master keys from '%s'...\n" +msgstr "" +"Ok, die nicht verwendeten Hauptschlüssel von »%s« werden vollständig " +"entfernt …\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1183 +#, c-format +msgid "There is only one master key which can not be purged.\n" +msgstr "" +"Es gibt nur einen einzigen Hauptschlüssel, der nicht vollständig entfernt " +"werden kann.\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1192 +msgid "while allocating args.kvnos" +msgstr "beim Reservieren von »args.kvnos«" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1208 +msgid "while finding master keys in use" +msgstr "bei der Suche nach den gerade verwendeten Hauptschlüsseln" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1217 +#, c-format +msgid "Would purge the following master key(s) from %s:\n" +msgstr "" +"Der/Die folgende(n) Hauptschlüssel würden/würde von %s vollständig " +"entfernt:\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1220 +#, c-format +msgid "Purging the following master key(s) from %s:\n" +msgstr "" +"Der/Die folgende(n) Hauptschlüssel werden/wird von %s vollständig entfernt:\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1232 +msgid "master key stash file needs updating, command aborting" +msgstr "" +"Ablagedatei des Hauptschlüssels erfordert Aktualisierung, Befehl abgebrochen" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1238 +#, c-format +msgid "KVNO: %d\n" +msgstr "KVNO: %d\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1243 +#, c-format +msgid "All keys in use, nothing purged.\n" +msgstr "Alle Schlüssel sind in Gebrauch, keiner wurde vollständig entfernt.\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1248 +#, c-format +msgid "%d key(s) would be purged.\n" +msgstr "%d Schlüssel würde(n) vollständig entfernt.\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1261 +msgid "while looking up mkey aux data list" +msgstr "beim Nachschlagen der Mkey-Aux-Datenliste" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1269 +msgid "while allocating key_data" +msgstr "beim Reservieren von »key_data«" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1350 +msgid "while updating mkey_aux data for master principal entry" +msgstr "beim Aktualisieren der Mkey-Aux-Daten für den Haupt-Principal-Eintrag" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1378 +#, c-format +msgid "%d key(s) purged.\n" +msgstr "%d Schlüssel vollständig entfernt\n" + +#: ../../src/kadmin/dbutil/kdb5_stash.c:97 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:538 +#, c-format +msgid "while setting up enctype %d" +msgstr "beim Einrichten des Verschlüsselungstyps %d" + +#: ../../src/kadmin/dbutil/kdb5_stash.c:123 +msgid "while getting master key list" +msgstr "beim Holen der Hauptschlüsselliste" + +#: ../../src/kadmin/dbutil/kdb5_stash.c:127 +#, c-format +msgid "Using existing stashed keys to update stash file.\n" +msgstr "" +"Zur Aktualisierung der Ablagedatei werden existierende gelagert Schlüssel " +"verwendet.\n" + +#: ../../src/kadmin/dbutil/kdb5_util.c:80 +#, c-format +msgid "" +"Usage: kdb5_util [-x db_args]* [-r realm] [-d dbname] [-k mkeytype] [-M " +"mkeyname]\n" +"\t [-kv mkeyVNO] [-sf stashfilename] [-m] cmd [cmd_options]\n" +"\tcreate [-s]\n" +"\tdestroy [-f]\n" +"\tstash [-f keyfile]\n" +"\tdump [-old|-ov|-b6|-b7|-r13|-r18] [-verbose]\n" +"\t [-mkey_convert] [-new_mkey_file mkey_file]\n" +"\t [-rev] [-recurse] [filename [princs...]]\n" +"\tload [-old|-ov|-b6|-b7|-r13|-r18] [-verbose] [-update] filename\n" +"\tark [-e etype_list] principal\n" +"\tadd_mkey [-e etype] [-s]\n" +"\tuse_mkey kvno [time]\n" +"\tlist_mkeys\n" +msgstr "" +"Aufruf: kdb5_util [-x Datenbankargumente]* [-r Realm] [-d Datenbankname] [-k " +"Mkeytype] [-M Mkeyname]\n" +"\t [-kv MkeyVNO] [-sf Ablagedateiname] [-m] Befehl [Befehlsoptionen]\n" +"\tcreate [-s]\n" +"\tdestroy [-f]\n" +"\tstash [-f Schlüsseldatei]\n" +"\tdump [-old|-ov|-b6|-b7|-r13|-r18] [-verbose]\n" +"\t [-mkey_convert] [-new_mkey_file mkey-Datei]\n" +"\t [-rev] [-recurse] [Dateiname [Principals …]]\n" +"\tload [-old|-ov|-b6|-b7|-r13|-r18] [-verbose] [-update] Dateiname\n" +"\tark [-e Etype-Liste] Principal\n" +"\tadd_mkey [-e Etype] [-s]\n" +"\tuse_mkey kvno [Zeit]\n" +"\tlist_mkeys\n" + +#: ../../src/kadmin/dbutil/kdb5_util.c:98 +#, c-format +msgid "" +"\tupdate_princ_encryption [-f] [-n] [-v] [princ-pattern]\n" +"\tpurge_mkeys [-f] [-n] [-v]\n" +"\n" +"where,\n" +"\t[-x db_args]* - any number of database specific arguments.\n" +"\t\t\tLook at each database documentation for supported arguments\n" +msgstr "" +"\tupdate_princ_encryption [-f] [-n] [-v] [Principal-Muster]\n" +"\tpurge_mkeys [-f] [-n] [-v]\n" +"\n" +"dabei sind\n" +"\t[-x Datenbankargumente]* - eine beliebige Anzahl datenbankspezifischer " +"Argumente.\n" +"\t\t\tWelche Argumente unterstützt werden, finden Sie in der Dokumentation " +"der jeweiligen Datenbank.\n" + +#: ../../src/kadmin/dbutil/kdb5_util.c:211 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:260 +msgid "while initializing Kerberos code" +msgstr "beim Initialisieren von Kerberos-Code" + +#: ../../src/kadmin/dbutil/kdb5_util.c:217 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:267 +msgid "while creating sub-command arguments" +msgstr "beim Erstellen von Unterbefehlsargumenten" + +#: ../../src/kadmin/dbutil/kdb5_util.c:235 +msgid "while parsing command arguments" +msgstr "beim Auswerten von Befehlsargumenten" + +#: ../../src/kadmin/dbutil/kdb5_util.c:264 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:298 +#, c-format +msgid ": %s is an invalid enctype" +msgstr ": %s ist kein gültiger Verschlüsselungstyp" + +#: ../../src/kadmin/dbutil/kdb5_util.c:272 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:307 +#, c-format +msgid ": %s is an invalid mkeyVNO" +msgstr ": %s ist kein gültiger MkeyVNO" + +# FIXME s/retreiving/retrieving/ +#: ../../src/kadmin/dbutil/kdb5_util.c:317 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:431 +msgid "while retreiving configuration parameters" +msgstr "beim Abfragen der Konfigurationsparameter" + +#: ../../src/kadmin/dbutil/kdb5_util.c:368 +msgid "Too few arguments" +msgstr "zu wenige Argumente" + +#: ../../src/kadmin/dbutil/kdb5_util.c:369 +#, c-format +msgid "Usage: %s dbpathname realmname" +msgstr "Aufruf: %s Datenbankpfadname Realm-Name" + +#: ../../src/kadmin/dbutil/kdb5_util.c:375 +msgid "while closing previous database" +msgstr "beim Schließen der vorherigen Datenbank" + +#: ../../src/kadmin/dbutil/kdb5_util.c:412 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:877 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1497 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:564 +msgid "while initializing database" +msgstr "beim Initialisieren der Datenbank" + +#: ../../src/kadmin/dbutil/kdb5_util.c:429 +msgid "while retrieving master entry" +msgstr "beim Abfragen des Haupteintrags" + +#: ../../src/kadmin/dbutil/kdb5_util.c:448 +msgid "while calculated master key salt" +msgstr "beim Berechnen des Hauptschlüssel-Salts" + +#: ../../src/kadmin/dbutil/kdb5_util.c:480 +msgid "Warning: proceeding without master key" +msgstr "Warnung: Es wird ohne Hauptschlüssel fortgefahren" + +#: ../../src/kadmin/dbutil/kdb5_util.c:498 +msgid "while seeding random number generator" +msgstr "beim Erzeugen des Startwerts des Zufallszahlengenerators" + +#: ../../src/kadmin/dbutil/kdb5_util.c:508 +#, c-format +msgid "%s: Could not map log\n" +msgstr "%s: Protokolldatei konnte nicht abgebildet werden\n" + +#: ../../src/kadmin/dbutil/kdb5_util.c:535 +msgid "while closing database" +msgstr "beim Schließen der Datenbank" + +#: ../../src/kadmin/dbutil/kdb5_util.c:582 +#, c-format +msgid "while fetching principal %s" +msgstr "beim Abrufen von Principal %s" + +#: ../../src/kadmin/dbutil/kdb5_util.c:605 +msgid "while finding mkey" +msgstr "beim Suchen nach Mkey" + +#: ../../src/kadmin/dbutil/kdb5_util.c:630 +msgid "while setting changetime" +msgstr "beim Setzen der Änderungszeit der Datei" + +#: ../../src/kadmin/dbutil/kdb5_util.c:638 +#, c-format +msgid "while saving principal %s" +msgstr "beim Speichern von Principal %s" + +#: ../../src/kadmin/dbutil/kdb5_util.c:642 +#, c-format +msgid "%s changed\n" +msgstr "%s geändert\n" + +#: ../../src/kadmin/ktutil/ktutil.c:73 +#, c-format +msgid "%s: invalid arguments\n" +msgstr "%s: ungültige Argumente\n" + +#: ../../src/kadmin/ktutil/ktutil.c:78 +msgid "while freeing ktlist" +msgstr "beim Freigeben von »ktlist«" + +#: ../../src/kadmin/ktutil/ktutil.c:89 +#, c-format +msgid "%s: must specify keytab to read\n" +msgstr "" +"%s: Die Schlüsseltabelle, die gelesen werden soll, muss angegeben werden.\n" + +#: ../../src/kadmin/ktutil/ktutil.c:94 +#, c-format +msgid "while reading keytab \"%s\"" +msgstr "beim Lesen der Schlüsseltabelle »%s«" + +#: ../../src/kadmin/ktutil/ktutil.c:104 +#, c-format +msgid "%s: must specify the srvtab to read\n" +msgstr "%s: Die zu lesende Dienstschlüsseltabelle muss angegeben werden.\n" + +#: ../../src/kadmin/ktutil/ktutil.c:109 +#, c-format +msgid "while reading srvtab \"%s\"" +msgstr "beim Lesen der Dienstschlüsseltabelle »%s«" + +#: ../../src/kadmin/ktutil/ktutil.c:119 +#, c-format +msgid "%s: must specify keytab to write\n" +msgstr "%s: Die zu schreibende Schlüsseltabelle muss angegeben werden.\n" + +#: ../../src/kadmin/ktutil/ktutil.c:124 +#, c-format +msgid "while writing keytab \"%s\"" +msgstr "beim Schreiben der Schlüsseltabelle »%s«" + +#: ../../src/kadmin/ktutil/ktutil.c:131 +#, c-format +msgid "%s: writing srvtabs is no longer supported\n" +msgstr "" +"%s: Schreiben der Dienstschlüsseltabelle wird nicht länger unterstützt\n" + +#: ../../src/kadmin/ktutil/ktutil.c:169 +#, c-format +msgid "usage: %s (-key | -password) -p principal -k kvno -e enctype\n" +msgstr "" +"Aufruf: %s (-key | -password) -p Principal -k KVNO -e Verschlüsselungstyp\n" + +#: ../../src/kadmin/ktutil/ktutil.c:176 +msgid "while adding new entry" +msgstr "beim Hinzufügen eines neuen Eintrags" + +#: ../../src/kadmin/ktutil/ktutil.c:186 +#, c-format +msgid "%s: must specify entry to delete\n" +msgstr "%s: zu löschender Eintrag muss angegeben werden\n" + +#: ../../src/kadmin/ktutil/ktutil.c:191 +#, c-format +msgid "while deleting entry %d" +msgstr "beim Löschen von Eintrag %d" + +#: ../../src/kadmin/ktutil/ktutil.c:219 +#, c-format +msgid "%s: usage: %s [-t] [-k] [-e]\n" +msgstr "%s: Aufruf: %s [-t] [-k] [-e]\n" + +#: ../../src/kadmin/ktutil/ktutil.c:259 +msgid "While converting enctype to string" +msgstr "beim Umwandeln des Verschlüsselungstyps in eine Zeichenkette" + +#: ../../src/kadmin/ktutil/ktutil_funcs.c:162 +#, c-format +msgid "Password for %.1000s" +msgstr "Passwort für %.1000s" + +#: ../../src/kadmin/ktutil/ktutil_funcs.c:179 +#, c-format +msgid "Key for %s (hex): " +msgstr "Schlüssel für %s (hexadezimal): " + +#: ../../src/kadmin/ktutil/ktutil_funcs.c:191 +#, c-format +msgid "addent: Error reading key.\n" +msgstr "addent: Fehler beim Lesen des Schlüssels\n" + +#: ../../src/kadmin/ktutil/ktutil_funcs.c:206 +#, c-format +msgid "addent: Illegal character in key.\n" +msgstr "addent: unerlaubtes Zeichen im Schlüssel\n" + +#: ../../src/kadmin/server/ipropd_svc.c:48 +#, c-format +msgid "Unauthorized request: %s, client=%s, service=%s, addr=%s" +msgstr "unberechtigte Anfrage: %s, Client=%s, Dienst=%s, Adresse=%s" + +#: ../../src/kadmin/server/ipropd_svc.c:49 +#: ../../src/kadmin/server/ipropd_svc.c:212 +#, c-format +msgid "Request: %s, %s, %s, client=%s, service=%s, addr=%s" +msgstr "Anfrage: %s, %s, %s, Client=%s, Dienst=%s, Adresse=%s" + +#: ../../src/kadmin/server/ipropd_svc.c:146 +#: ../../src/kadmin/server/ipropd_svc.c:271 +#, c-format +msgid "%s: server handle is NULL" +msgstr "%s: Server-Identifikator ist NULL" + +#: ../../src/kadmin/server/ipropd_svc.c:156 +#: ../../src/kadmin/server/ipropd_svc.c:284 +#, c-format +msgid "%s: setup_gss_names failed" +msgstr "%s: setup_gss_names fehlgeschlagen" + +#: ../../src/kadmin/server/ipropd_svc.c:166 +#: ../../src/kadmin/server/ipropd_svc.c:295 +#, c-format +msgid "%s: out of memory recording principal names" +msgstr "%s: Speicher reicht nicht zur Aufzeichnung der Principal-Namen aus" + +#: ../../src/kadmin/server/ipropd_svc.c:195 +#, c-format +msgid "%s; Incoming SerialNo=%lu; Outgoing SerialNo=%lu" +msgstr "%s; eingehende Seriennummer=%lu; ausgehende Seriennummer=%lu" + +#: ../../src/kadmin/server/ipropd_svc.c:201 +#, c-format +msgid "%s; Incoming SerialNo=%lu; Outgoing SerialNo=N/A" +msgstr "%s; eingehende Seriennummer=%lu; ausgehende Seriennummer=N/A" + +#: ../../src/kadmin/server/ipropd_svc.c:320 +#, c-format +msgid "%s: getclhoststr failed" +msgstr "%s: getclhoststr fehlgeschlagen" + +#: ../../src/kadmin/server/ipropd_svc.c:342 +#, c-format +msgid "%s: cannot construct kdb5 util dump string too long; out of memory" +msgstr "" +"Ausgabenzeichenkette des KDB5-Hilfswerkzeugs nicht konstruierbar, da zu " +"lang; Speicher reicht nicht aus.%s: Die Ausgabezeichenkette des KDB5-" +"Hilfswerkzeugs kann nicht erstellt werden, weil sie zu lang ist. Der " +"Speicherplatz reicht nicht aus." + +#: ../../src/kadmin/server/ipropd_svc.c:362 +#, c-format +msgid "%s: fork failed: %s" +msgstr "%s: Verzweigen fehlgeschlagen: %s" + +#: ../../src/kadmin/server/ipropd_svc.c:374 +#, c-format +msgid "%s: popen failed: %s" +msgstr "%s: popen fehlgeschlagen: %s" + +#: ../../src/kadmin/server/ipropd_svc.c:388 +#, c-format +msgid "%s: pclose(popen) failed: %s" +msgstr "%s: pclose(popen) fehlgeschlagen: %s" + +#: ../../src/kadmin/server/ipropd_svc.c:405 +#, c-format +msgid "%s: exec failed: %s" +msgstr "%s: exec fehlgeschlagen: %s" + +#: ../../src/kadmin/server/ipropd_svc.c:421 +#, c-format +msgid "Request: %s, spawned resync process %d, client=%s, service=%s, addr=%s" +msgstr "" +"Anfrage: %s, hervorgebrachter Neusynchronisationsprozess %d, Client=%s, " +"Dienst=%s, Adresse=%s" + +#: ../../src/kadmin/server/ipropd_svc.c:485 +#: ../../src/kadmin/server/kadm_rpc_svc.c:275 +#, c-format +msgid "check_rpcsec_auth: failed inquire_context, stat=%u" +msgstr "check_rpcsec_auth: inquire_context fehlgeschlagen, Stat=%u" + +#: ../../src/kadmin/server/ipropd_svc.c:515 +#: ../../src/kadmin/server/kadm_rpc_svc.c:304 +#, c-format +msgid "bad service principal %.*s%s" +msgstr "falscher Dienst-Principal %.*s%s" + +#: ../../src/kadmin/server/ipropd_svc.c:538 +#, c-format +msgid "authentication attempt failed: %s, RPC authentication flavor %d" +msgstr "" +"Authentifizierungsversuche gescheitert: %s, PRC-Authentifizierungsvariante %d" + +#: ../../src/kadmin/server/ipropd_svc.c:572 +#, c-format +msgid "RPC unknown request: %d (%s)" +msgstr "unbekannte PRC-Anfrage: %d (%s)" + +#: ../../src/kadmin/server/ipropd_svc.c:580 +#, c-format +msgid "RPC svc_getargs failed (%s)" +msgstr "RPC-»svc_getargs« fehlgeschlagen (%s)" + +#: ../../src/kadmin/server/ipropd_svc.c:590 +#, c-format +msgid "RPC svc_sendreply failed (%s)" +msgstr "RPC-»svc_sendreply« fehlgeschlagen (%s)" + +#: ../../src/kadmin/server/ipropd_svc.c:596 +#, c-format +msgid "RPC svc_freeargs failed (%s)" +msgstr "RPC-»svc_freeargs« fehlgeschlagen (%s)" + +#: ../../src/kadmin/server/kadm_rpc_svc.c:325 +#, c-format +msgid "gss_to_krb5_name: failed display_name status %d" +msgstr "gss_to_krb5_name: display_name fehlgeschlagen, Status %d" + +#: ../../src/kadmin/server/ovsec_kadmd.c:86 +#, c-format +msgid "" +"Usage: kadmind [-x db_args]* [-r realm] [-m] [-nofork] [-port port-number]\n" +"\t\t[-proponly] [-p path-to-kdb5_util] [-F dump-file]\n" +"\t\t[-K path-to-kprop] [-P pid_file]\n" +"\n" +"where,\n" +"\t[-x db_args]* - any number of database specific arguments.\n" +"\t\t\tLook at each database documentation for supported arguments\n" +msgstr "" +"Aufruf: kadmind [-x Datenbankargumente]* [-r Realm] [-m] [-nofork]\n" +"\t\t[-port Portummer] [-p Pfad_zum_KDB5-Hilfswerkzeug] [-F Auszugsdatei]\n" +"\t\t[-K Pfad_zu_Kprop] [-P PID-Datei]\n" +"\n" +"dabei sind\n" +"\t[-x Datenbankargumente]* - eine beliebige Anzahl datenbankspezifischer " +"Argumente.\n" +"\t\t\tWelche Argumente unterstützt werden, finden Sie in der Dokumentation " +"der jeweiligen Datenbank.\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:111 +#, c-format +msgid "%s: %s while %s, aborting\n" +msgstr "%s: %s bei %s, wird abgebrochen\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:113 +#, c-format +msgid "%s while %s, aborting\n" +msgstr "%s bei %s, wird abgebrochen\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:115 +#, c-format +msgid "%s: %s, aborting\n" +msgstr "%s: %s, wird abgebrochen\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:116 +#, c-format +msgid "%s, aborting" +msgstr "%s, wird abgebrochen" + +#: ../../src/kadmin/server/ovsec_kadmd.c:282 +#, c-format +msgid "" +"WARNING! Forged/garbled request: %s, claimed client = %.*s%s, server = %.*s" +"%s, addr = %s" +msgstr "" +"WARNUNG! Gefälschte/verstümmelte Anfrage: %s, geforderter Client = %.*s%s, " +"Server = %.*s%s, Adresse = %s" + +#: ../../src/kadmin/server/ovsec_kadmd.c:288 +#, c-format +msgid "" +"WARNING! Forged/garbled request: %d, claimed client = %.*s%s, server = %.*s" +"%s, addr = %s" +msgstr "" +"WARNUNG! Gefälschte/verstümmelte Anfrage: %d, Client = %.*s%s, Server = " +"%.*s%s, Adresse = %s" + +#: ../../src/kadmin/server/ovsec_kadmd.c:302 +#, c-format +msgid "Miscellaneous RPC error: %s, %s" +msgstr "sonstiger PRC-Fehler: %s, %s" + +#: ../../src/kadmin/server/ovsec_kadmd.c:318 +#, c-format +msgid "%s Cannot decode status %d" +msgstr "%s: Status %d kann nicht dekodiert werden" + +#: ../../src/kadmin/server/ovsec_kadmd.c:336 +#, c-format +msgid "Authentication attempt failed: %s, GSS-API error strings are:" +msgstr "Authentifizierungsversuch fehlgeschlagen: %s, GSS-API-Fehlermeldungen:" + +#: ../../src/kadmin/server/ovsec_kadmd.c:341 +msgid " GSS-API error strings complete." +msgstr " GSS-API-Fehlermeldungen vollständig" + +#: ../../src/kadmin/server/ovsec_kadmd.c:378 +#, c-format +msgid "%s: cannot initialize. Not enough memory\n" +msgstr "%s: kann nicht initialisiert werden: Speicher reicht nicht aus.\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:445 +#, c-format +msgid "%s: %s while initializing context, aborting\n" +msgstr "%s: %s beim Initialisieren des Kontextes, wird abgebrochen\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:456 +msgid "initializing" +msgstr "wird initialisiert" + +#: ../../src/kadmin/server/ovsec_kadmd.c:460 +msgid "getting config parameters" +msgstr "beim Holen der Konfigurationsparameter" + +#: ../../src/kadmin/server/ovsec_kadmd.c:462 +msgid "Missing required realm configuration" +msgstr "erforderliche Realm-Konfiguration fehlt" + +#: ../../src/kadmin/server/ovsec_kadmd.c:464 +msgid "Missing required ACL file configuration" +msgstr "erforderliche ACL-Dateikonfiguration fehlt" + +#: ../../src/kadmin/server/ovsec_kadmd.c:468 +msgid "initializing network" +msgstr "Netzwerk wird initialisiert" + +#: ../../src/kadmin/server/ovsec_kadmd.c:473 +msgid "Cannot build GSSAPI auth names" +msgstr "GSS-API-Authentifizierungsnamen können nicht gebildet werden." + +#: ../../src/kadmin/server/ovsec_kadmd.c:477 +msgid "Cannot set up KDB keytab" +msgstr "Die KDB-Schlüsseltabelle kann nicht eingerichtet werden." + +#: ../../src/kadmin/server/ovsec_kadmd.c:480 +msgid "Cannot set GSSAPI authentication names" +msgstr "GSS-API-Authentifizierungsnamen können nicht gesetzt werden." + +#: ../../src/kadmin/server/ovsec_kadmd.c:497 +msgid "Cannot initialize GSSAPI service name" +msgstr "GSSAPI-Dienstname kann nicht initialisiert werden" + +#: ../../src/kadmin/server/ovsec_kadmd.c:501 +msgid "initializing ACL file" +msgstr "ACL-Datei wird initialisiert" + +#: ../../src/kadmin/server/ovsec_kadmd.c:504 +msgid "spawning daemon process" +msgstr "Daemon-Prozess wird erzeugt" + +#: ../../src/kadmin/server/ovsec_kadmd.c:508 +msgid "creating PID file" +msgstr "PID-Datei wird erstellt" + +#: ../../src/kadmin/server/ovsec_kadmd.c:511 +msgid "Seeding random number generator" +msgstr "Startwert des Zufallszahlengenerators wird erzeugt" + +#: ../../src/kadmin/server/ovsec_kadmd.c:514 +msgid "getting random seed" +msgstr "Zufallsstartwert wird geholt" + +#: ../../src/kadmin/server/ovsec_kadmd.c:521 +msgid "mapping update log" +msgstr "Aktualisierungsprotokoll wird abgebildet" + +#: ../../src/kadmin/server/ovsec_kadmd.c:525 +#, c-format +msgid "%s: create IPROP svc (PROG=%d, VERS=%d)\n" +msgstr "%s: IPROP-Dienst wird erstellt (PROG=%d, VERS=%d)\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:530 +msgid "starting" +msgstr "startet" + +#: ../../src/kadmin/server/ovsec_kadmd.c:532 ../../src/kdc/main.c:1061 +#, c-format +msgid "%s: starting...\n" +msgstr "%s: startet …\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:535 +msgid "finished, exiting" +msgstr "fertig, wird beendet" + +#: ../../src/kadmin/server/schpw.c:282 +#, c-format +msgid "setpw request from %s by %.*s%s for %.*s%s: %s" +msgstr "»setpw«-Anfrage von %s durch %.*s%s für %.*s%s: %s" + +#: ../../src/kadmin/server/schpw.c:287 +#, c-format +msgid "chpw request from %s for %.*s%s: %s" +msgstr "»chpw«-Anfrage von %s für %.*s%s: %s" + +#: ../../src/kadmin/server/schpw.c:464 +#, c-format +msgid "chpw: Couldn't open admin keytab %s" +msgstr "chpw«: Administratorschlüsseltabelle %s konnte nicht geöffnet werden" + +#: ../../src/kadmin/server/server_stubs.c:293 +#, c-format +msgid "" +"Unauthorized request: %s, %.*s%s, client=%.*s%s, service=%.*s%s, addr=%s" +msgstr "" +"Unauthorisierte Anfrage: %s, %.*s%s, Client=%.*s%s, Dienst=%.*s%s, Adresse=%s" + +#: ../../src/kadmin/server/server_stubs.c:314 +#: ../../src/kadmin/server/server_stubs.c:649 +#: ../../src/kadmin/server/server_stubs.c:1792 +msgid "success" +msgstr "erfolgreich" + +#: ../../src/kadmin/server/server_stubs.c:324 +#, c-format +msgid "Request: %s, %.*s%s, %s, client=%.*s%s, service=%.*s%s, addr=%s" +msgstr "Anfrage: %s, %.*s%s, %s, Client=%.*s%s, Dienst=%.*s%s, Adresse=%s" + +#: ../../src/kadmin/server/server_stubs.c:628 +#, c-format +msgid "" +"Unauthorized request: kadm5_rename_principal, %.*s%s to %.*s%s, client=%.*s" +"%s, service=%.*s%s, addr=%s" +msgstr "" +"Unauthorisierte Anfrage: kadm5_rename_principal, %.*s%s bis %.*s%s, Client=" +"%.*s%s, Dienst=%.*s%s, Adresse=%s" + +#: ../../src/kadmin/server/server_stubs.c:644 +#, c-format +msgid "" +"Request: kadm5_rename_principal, %.*s%s to %.*s%s, %s, client=%.*s%s, " +"service=%.*s%s, addr=%s" +msgstr "" +"Anfrage: kadm5_rename_principal, %.*s%s bis %.*s%s, %s, Client=%.*s%s, " +"Dienst=%.*s%s, Adresse=%s" + +#: ../../src/kadmin/server/server_stubs.c:1788 +#, c-format +msgid "" +"Request: kadm5_init, %.*s%s, %s, client=%.*s%s, service=%.*s%s, addr=%s, " +"vers=%d, flavor=%d" +msgstr "" +"Anfrage: kadm5_init, %.*s%s, %s, Client=%.*s%s, Dienst=%.*s%s, Adresse=%s, " +"Version=%d, Variante=%d" + +#: ../../src/kdc/do_as_req.c:273 +#, c-format +msgid "AS_REQ : handle_authdata (%d)" +msgstr "AS_REQ: handle_authdata (%d)" + +#: ../../src/kdc/do_tgs_req.c:593 +#, c-format +msgid "TGS_REQ : handle_authdata (%d)" +msgstr "TGS_REQ: handle_authdata (%d)" + +#: ../../src/kdc/do_tgs_req.c:655 +msgid "not checking transit path" +msgstr "Übergangspfad wird nicht geprüft" + +#: ../../src/kdc/fast_util.c:62 +#, c-format +msgid "%s while handling ap-request armor" +msgstr "%s bei der Handhabung des »ap-request«-Schutzes" + +#: ../../src/kdc/fast_util.c:71 +msgid "ap-request armor for something other than the local TGS" +msgstr "»ap-request«-Schutz für etwas anderes als den lokalen TGS" + +#: ../../src/kdc/fast_util.c:80 +msgid "ap-request armor without subkey" +msgstr "»ap-request«-Schutz ohne Unterschlüssel" + +#: ../../src/kdc/fast_util.c:162 +msgid "Ap-request armor not permitted with TGS" +msgstr "»ap-request«-Schutz nicht mit TGS gestattet" + +#: ../../src/kdc/fast_util.c:169 +#, c-format +msgid "Unknown FAST armor type %d" +msgstr "unbekanntet FAST-Schutztyp %d" + +#: ../../src/kdc/fast_util.c:183 +msgid "No armor key but FAST armored request present" +msgstr "Es gibt keinen Schutzschlüssel aber eine FAST-geschützte Anfrage" + +#: ../../src/kdc/fast_util.c:219 +msgid "FAST req_checksum invalid; request modified" +msgstr "FAST-»req_checksum« ungültig; Anfrage geändert" + +#: ../../src/kdc/fast_util.c:225 +msgid "Unkeyed checksum used in fast_req" +msgstr "in fast_req wurde eine Prüfsumme ohne Schlüssel benutzt" + +#: ../../src/kdc/kdc_audit.c:110 +#, c-format +msgid "audit plugin %s failed to open. error=%i" +msgstr "Öffnen der Audit-Erweiterung %s fehlgeschlagen. Fehler=%i" + +#: ../../src/kdc/kdc_authdata.c:292 ../../src/kdc/kdc_authdata.c:328 +#, c-format +msgid "authdata %s failed to initialize: %s" +msgstr "Initialisieren von »authdata« %s fehlgeschlagen: %s" + +#: ../../src/kdc/kdc_authdata.c:779 +#, c-format +msgid "authdata (%s) handling failure: %s" +msgstr "Handhabung von »authdata« %s fehlgeschlagen: %s" + +#: ../../src/kdc/kdc_log.c:82 +#, c-format +msgid "AS_REQ (%s) %s: ISSUE: authtime %d, %s, %s for %s" +msgstr "AS_REQ (%s) %s: PROBLEM: Authentifizierungszeit %d, %s, %s für %s" + +#: ../../src/kdc/kdc_log.c:88 +#, c-format +msgid "AS_REQ (%s) %s: %s: %s for %s%s%s" +msgstr "AS_REQ (%s) %s: %s: %s für %s%s%s" + +#: ../../src/kdc/kdc_log.c:159 +#, c-format +msgid "TGS_REQ (%s) %s: %s: authtime %d, %s%s %s for %s%s%s" +msgstr "TGS_REQ (%s) %s: %s: Authentifizierungszeit %d, %s%s %s für %s%s%s" + +#: ../../src/kdc/kdc_log.c:166 +#, c-format +msgid "... PROTOCOL-TRANSITION s4u-client=%s" +msgstr "… PROTOKOLLÜBERGANG s4u-client=%s" + +#: ../../src/kdc/kdc_log.c:170 +#, c-format +msgid "... CONSTRAINED-DELEGATION s4u-client=%s" +msgstr "… EINHESCHRÄNKTE DELEGIERUNG s4u-client=%s" + +#: ../../src/kdc/kdc_log.c:174 +#, c-format +msgid "TGS_REQ %s: %s: authtime %d, %s for %s, 2nd tkt client %s" +msgstr "TGS_REQ %s: %s: Authentifizierungszeit %d, %s für %s, 2. TKT-Client %s" + +#: ../../src/kdc/kdc_log.c:208 +#, c-format +msgid "bad realm transit path from '%s' to '%s' via '%.*s%s'" +msgstr "falscher Realm-Übergangspfad von »%s« zu »%s« über »%.*s%s«" + +#: ../../src/kdc/kdc_log.c:214 +#, c-format +msgid "unexpected error checking transit from '%s' to '%s' via '%.*s%s': %s" +msgstr "" +"unerwarteter Fehler bei der Prüfung des Übergangs von »%s« zu »%s« über »%.*s" +"%s«: %s" + +#: ../../src/kdc/kdc_log.c:232 +msgid "TGS_REQ: issuing alternate TGT" +msgstr "TGS_REQ: alternativer TGT wird erstellt" + +#: ../../src/kdc/kdc_log.c:235 +#, c-format +msgid "TGS_REQ: issuing TGT %s" +msgstr "TGS_REQ: TGT %s wird erstellt" + +#: ../../src/kdc/kdc_preauth.c:328 +#, c-format +msgid "preauth %s failed to initialize: %s" +msgstr "Initialisieren von »preauth« %s fehlgeschlagen: %s" + +#: ../../src/kdc/kdc_preauth.c:339 +#, c-format +msgid "preauth %s failed to setup loop: %s" +msgstr "Einrichten der Schleife von »preauth« %s fehlgeschlagen: %s" + +#: ../../src/kdc/kdc_preauth.c:760 +#, c-format +msgid "%spreauth required but hint list is empty" +msgstr "%spreauth benötigt, aber Hinweisliste ist leer" + +#: ../../src/kdc/kdc_preauth_ec.c:75 +msgid "Encrypted Challenge used outside of FAST tunnel" +msgstr "verschlüsselte Aufforderung wurde außerhalb des FAST-Tunnels verwendet" + +#: ../../src/kdc/kdc_preauth_ec.c:110 +msgid "Incorrect password in encrypted challenge" +msgstr "falsches Passwort in verschlüsselter Aufforderung" + +#: ../../src/kdc/kdc_util.c:236 +msgid "TGS_REQ: SESSION KEY or MUTUAL" +msgstr "TGS_REQ: SITZUNGSSCHLÜSSEL oder BEIDERSEITIG" + +#: ../../src/kdc/kdc_util.c:314 +msgid "PROCESS_TGS: failed lineage check" +msgstr "PROCESS_TGS: Abstammungsprüfung fehlgeschlagen" + +#: ../../src/kdc/kdc_util.c:468 +#, c-format +msgid "TGS_REQ: UNKNOWN SERVER: server='%s'" +msgstr "TGS_REQ: UNBEKANNTER SERVER: Server=»%s«" + +#: ../../src/kdc/main.c:231 +#, c-format +msgid "while getting context for realm %s" +msgstr "beim Holen des Kontextes für Realm %s" + +#: ../../src/kdc/main.c:329 +#, c-format +msgid "while setting default realm to %s" +msgstr "beim Setzen des Standard-Realms auf %s" + +#: ../../src/kdc/main.c:337 +#, c-format +msgid "while initializing database for realm %s" +msgstr "beim Initialisieren der Datenbank für Realm %s" + +#: ../../src/kdc/main.c:346 +#, c-format +msgid "while setting up master key name %s for realm %s" +msgstr "beim Einrichten des Hauptschlüsselnamens %s für Realm %s" + +#: ../../src/kdc/main.c:359 +#, c-format +msgid "while fetching master key %s for realm %s" +msgstr "beim Abholen des Hauptschlüssels %s für Realm %s" + +#: ../../src/kdc/main.c:367 +#, c-format +msgid "while fetching master keys list for realm %s" +msgstr "beim Abholen der Hauptschlüsselliste für Realm %s" + +#: ../../src/kdc/main.c:376 +#, c-format +msgid "while resolving kdb keytab for realm %s" +msgstr "beim Ermitteln der KDB-Schlüsseltabelle für Realm %s" + +#: ../../src/kdc/main.c:385 +#, c-format +msgid "while building TGS name for realm %s" +msgstr "beim Bilden des TGS-Namens für Realm %s" + +#: ../../src/kdc/main.c:503 +#, c-format +msgid "creating %d worker processes" +msgstr "%d Arbeitsprozesse werden erzeugt" + +#: ../../src/kdc/main.c:513 +msgid "Unable to reinitialize main loop" +msgstr "Hauptschleife konnte nicht neu initialisiert werden" + +#: ../../src/kdc/main.c:518 +#, c-format +msgid "Unable to initialize signal handlers in pid %d" +msgstr "" +"Signalbehandlungsprogramme in PID %d konnten nicht initialisiert werden" + +#: ../../src/kdc/main.c:548 +#, c-format +msgid "worker %ld exited with status %d" +msgstr "Arbeitsprozess %ld endete mit Status %d" + +#: ../../src/kdc/main.c:572 +#, c-format +msgid "signal %d received in supervisor" +msgstr "Überwachungsprogramm empfing Signal %d" + +#: ../../src/kdc/main.c:591 +#, c-format +msgid "" +"usage: %s [-x db_args]* [-d dbpathname] [-r dbrealmname]\n" +"\t\t[-R replaycachename] [-m] [-k masterenctype]\n" +"\t\t[-M masterkeyname] [-p port] [-P pid_file]\n" +"\t\t[-n] [-w numworkers] [/]\n" +"\n" +"where,\n" +"\t[-x db_args]* - Any number of database specific arguments.\n" +"\t\t\tLook at each database module documentation for \t\t\tsupported " +"arguments\n" +msgstr "" +"Aufruf: %s [-x Datenbankargumente]* [-d Datenbankpfadname]\n" +"\t\t[-r Datenbank-Realm-Name] [-m] [-k Hauptverschlüsselungstyp]\n" +"\t\t[-M Hauptschlüsselname] [-p Port] [-P PID-Datei]\n" +"\t\t[-n] [-w Arbeitsprozessanzahl] [/]\n" +"\n" +"dabei sind\n" +"\t[-x Datenbankargumente]* - eine beliebige Anzahl datenbankspezifischer " +"Argumente.\n" +"\t\t\tWelche Argumente unterstützt werden, finden Sie in der Dokumentation " +"der jeweiligen Datenbank.\n" + +#: ../../src/kdc/main.c:653 ../../src/kdc/main.c:660 ../../src/kdc/main.c:774 +#, c-format +msgid " KDC cannot initialize. Not enough memory\n" +msgstr "KDC kann nicht initialisiert werden. Speicher reicht nicht aus\n" + +#: ../../src/kdc/main.c:679 ../../src/kdc/main.c:722 ../../src/kdc/main.c:733 +#, c-format +msgid "%s: KDC cannot initialize. Not enough memory\n" +msgstr "%s: KDC kann nicht initialisiert werden. Speicher reicht nicht aus\n" + +#: ../../src/kdc/main.c:699 ../../src/kdc/main.c:816 +#, c-format +msgid "%s: cannot initialize realm %s - see log file for details\n" +msgstr "" +"%s: Realm %s kann nicht initialisiert werden - Einzelheiten finden Sie in " +"der Protokolldatei\n" + +#: ../../src/kdc/main.c:710 +#, c-format +msgid "%s: cannot initialize realm %s. Not enough memory\n" +msgstr "" +"%s: Realm %s kann nicht initialisiert werden. Speicher reicht nicht aus\n" + +#: ../../src/kdc/main.c:761 +#, c-format +msgid "invalid enctype %s" +msgstr "ungültiger Verschlüsselungstyp %s" + +#: ../../src/kdc/main.c:804 +msgid "while attempting to retrieve default realm" +msgstr "beim Versuch, den Standard-Realm abzufragen" + +#: ../../src/kdc/main.c:806 +#, c-format +msgid "%s: %s, attempting to retrieve default realm\n" +msgstr "%s: %s, es wird versucht, den Standard-Realm abzufragen\n" + +#: ../../src/kdc/main.c:912 +#, c-format +msgid "%s: cannot get memory for realm list\n" +msgstr "%s: Speicher für die Realm-Liste kann nicht erlangt werden\n" + +#: ../../src/kdc/main.c:947 +msgid "while initializing lookaside cache" +msgstr "beim Initialisieren des Lookaside-Zwischenspeichers" + +#: ../../src/kdc/main.c:955 +msgid "while creating main loop" +msgstr "beim Erzeugen der Hauptschleife" + +# SAM=Security Accounts Manager +#: ../../src/kdc/main.c:965 +msgid "while initializing SAM" +msgstr "beim Initialisieren des SAMs" + +#: ../../src/kdc/main.c:1011 +msgid "while initializing routing socket" +msgstr "beim Initialisieren des Routing-Sockets" + +#: ../../src/kdc/main.c:1017 +msgid "while initializing signal handlers" +msgstr "beim Initialisieren des Signalbehandlungsprogramms" + +#: ../../src/kdc/main.c:1024 +msgid "while initializing network" +msgstr "beim Initialisieren des Netzwerks" + +#: ../../src/kdc/main.c:1029 +msgid "while detaching from tty" +msgstr "beim Lösen vom Terminal" + +#: ../../src/kdc/main.c:1036 +msgid "while creating PID file" +msgstr "beim Erstellen der PID-Datei" + +#: ../../src/kdc/main.c:1045 +msgid "creating worker processes" +msgstr "Arbeitsprozesse werden erzeugt" + +#: ../../src/kdc/main.c:1055 +msgid "while loading audit plugin module(s)" +msgstr "beim Laden des/der Auditerweiterungsmoduls/Auditerweiterungsmodule" + +#: ../../src/kdc/main.c:1059 +msgid "commencing operation" +msgstr "Aktion wird begonnen" + +#: ../../src/kdc/main.c:1067 +msgid "shutting down" +msgstr "wird heruntergefahren" + +#: ../../src/lib/apputils/net-server.c:258 +msgid "Got signal to request exit" +msgstr "Signal zur Anfrage des Beendens empfangen" + +#: ../../src/lib/apputils/net-server.c:272 +msgid "Got signal to reset" +msgstr "Signal zum Zurücksetzen empfangen" + +#: ../../src/lib/apputils/net-server.c:429 +#, c-format +msgid "closing down fd %d" +msgstr "Dateideskriptor %d wird geschlossen" + +#: ../../src/lib/apputils/net-server.c:443 +#, c-format +msgid "descriptor %d closed but still in svc_fdset" +msgstr "Deskriptor %d geschlossen, aber immer noch in »svc_fdset«" + +#: ../../src/lib/apputils/net-server.c:469 +msgid "cannot create io event" +msgstr "E/A-Ereignis kann nicht erzeugt werden" + +#: ../../src/lib/apputils/net-server.c:475 +msgid "cannot save event" +msgstr "Ereignis kann nicht gesichert werden" + +#: ../../src/lib/apputils/net-server.c:495 +#, c-format +msgid "file descriptor number %d too high" +msgstr "Dateideskriptornummer %d zu hoch" + +#: ../../src/lib/apputils/net-server.c:503 +msgid "cannot allocate storage for connection info" +msgstr "Speicher für Verbindungsinformation kann nicht reserviert werden" + +#: ../../src/lib/apputils/net-server.c:562 +#, c-format +msgid "Cannot create TCP server socket on %s" +msgstr "Auf %s kann kein TCP-Server-Socket erstellt werden." + +#: ../../src/lib/apputils/net-server.c:571 +#, c-format +msgid "TCP socket fd number %d (for %s) too high" +msgstr "TCP-Socket-Deskriptornummer %d (für %s) zu hoch" + +#: ../../src/lib/apputils/net-server.c:579 +#, c-format +msgid "Cannot enable SO_REUSEADDR on fd %d" +msgstr "SO_REUSEADDR kann nicht für Dateideskriptor %d aktiviert werden" + +#: ../../src/lib/apputils/net-server.c:586 +#, c-format +msgid "setsockopt(%d,IPV6_V6ONLY,1) failed" +msgstr "setsockopt(%d,IPV6_V6ONLY,1) fehlgeschlagen" + +#: ../../src/lib/apputils/net-server.c:588 +#, c-format +msgid "setsockopt(%d,IPV6_V6ONLY,1) worked" +msgstr "setsockopt(%d,IPV6_V6ONLY,1) funktioniert" + +#: ../../src/lib/apputils/net-server.c:591 +msgid "no IPV6_V6ONLY socket option support" +msgstr "keine Socket-Option für IPV6_V6ONLY unterstützt" + +#: ../../src/lib/apputils/net-server.c:597 +#, c-format +msgid "Cannot bind server socket on %s" +msgstr "Server-Socket kann nicht an %s gebunden werden" + +#: ../../src/lib/apputils/net-server.c:624 +#, c-format +msgid "Cannot create RPC service: %s; continuing" +msgstr "RPC-Dienst kann nicht erstellt werden: %s; es wird fortgefahren" + +#: ../../src/lib/apputils/net-server.c:633 +#, c-format +msgid "Cannot register RPC service: %s; continuing" +msgstr "RPC-Dienst kann nicht registriert werden: %s; es wird fortgefahren" + +#: ../../src/lib/apputils/net-server.c:682 +#, c-format +msgid "Cannot listen on TCP server socket on %s" +msgstr "" +"Auf dem TCP-Server-Socket kann nicht auf eine Verbindung gewartet werden auf " +"%s." + +#: ../../src/lib/apputils/net-server.c:688 +#, c-format +msgid "cannot set listening tcp socket on %s non-blocking" +msgstr "" +"Das auf eine Verbindung wartende TCP-Socket kann nicht auf nicht-" +"blockierendes %s gesetzt werden." + +#: ../../src/lib/apputils/net-server.c:695 +#, c-format +msgid "disabling SO_LINGER on TCP socket on %s" +msgstr "SO_LINGER auf dem TCP-Socket auf %s wird deaktiviert" + +#: ../../src/lib/apputils/net-server.c:743 +#: ../../src/lib/apputils/net-server.c:752 +#, c-format +msgid "listening on fd %d: tcp %s" +msgstr "auf Dateideskriptor %d wird auf eine Verbindung gewartet: TCP %s" + +#: ../../src/lib/apputils/net-server.c:757 +msgid "assuming IPv6 socket accepts IPv4" +msgstr "es wird davon ausgegangen, dass das IPv6-Socket IPv4 akzeptiert" + +#: ../../src/lib/apputils/net-server.c:791 +#: ../../src/lib/apputils/net-server.c:804 +#, c-format +msgid "listening on fd %d: rpc %s" +msgstr "auf Dateideskriptor %d wird auf eine Verbindung gewartet: RPC %s" + +#: ../../src/lib/apputils/net-server.c:883 +#, c-format +msgid "Cannot request packet info for udp socket address %s port %d" +msgstr "" +"Paketinformation für UDP-Socket-Adresse %s, Port %d, kann nicht abgefragt " +"werden" + +#: ../../src/lib/apputils/net-server.c:889 +#, c-format +msgid "listening on fd %d: udp %s%s" +msgstr "auf Dateideskriptor %d wird auf eine Verbindung gewartet: UDP %s%s" + +#: ../../src/lib/apputils/net-server.c:918 +msgid "Failed to reconfigure network, exiting" +msgstr "Neukonfiguration des Netzwerks fehlgeschlagen, wird beendet" + +#: ../../src/lib/apputils/net-server.c:979 +#, c-format +msgid "" +"unhandled routing message type %d, will reconfigure just for the fun of it" +msgstr "" +"nicht behandelter Routing-Meldungstyp %d, es wird es nur zum Spaß neu " +"konfiguriert" + +#: ../../src/lib/apputils/net-server.c:1013 +#, c-format +msgid "short read (%d/%d) from routing socket" +msgstr "ungenügende Daten (%d/%d) vom Routing-Socket gelesen" + +#: ../../src/lib/apputils/net-server.c:1023 +#, c-format +msgid "read %d from routing socket but msglen is %d" +msgstr "%d vom Routing-Socket gelesen, Nachrichtenlänge ist jedoch %d" + +#: ../../src/lib/apputils/net-server.c:1055 +#, c-format +msgid "couldn't set up routing socket: %s" +msgstr "Routing-Socket konnte nicht eingerichtet werden: %s" + +#: ../../src/lib/apputils/net-server.c:1058 +#, c-format +msgid "routing socket is fd %d" +msgstr "Das Routing-Socket hat den Dateideskriptor %d." + +#: ../../src/lib/apputils/net-server.c:1084 +msgid "setting up network..." +msgstr "Netzwerk wird eingerichtet …" + +#: ../../src/lib/apputils/net-server.c:1101 +#, c-format +msgid "set up %d sockets" +msgstr "%d Sockets werden eingerichtet" + +#: ../../src/lib/apputils/net-server.c:1103 +msgid "no sockets set up?" +msgstr "keine Sockets eingerichtet?" + +#: ../../src/lib/apputils/net-server.c:1351 +#: ../../src/lib/apputils/net-server.c:1405 +msgid "while dispatching (udp)" +msgstr "beim Versenden (UDP)" + +#: ../../src/lib/apputils/net-server.c:1380 +#, c-format +msgid "while sending reply to %s/%s from %s" +msgstr "beim Senden der Antwort zu %s/%s von %s" + +#: ../../src/lib/apputils/net-server.c:1385 +#, c-format +msgid "short reply write %d vs %d\n" +msgstr "ungenügende Ausgabe der Antwort %d gegenüber %d\n" + +#: ../../src/lib/apputils/net-server.c:1430 +msgid "while receiving from network" +msgstr "beim Empfangen vom Netzwerk" + +#: ../../src/lib/apputils/net-server.c:1446 +#, c-format +msgid "pktinfo says local addr is %s" +msgstr "Pktinfo sagt, die lokale Adresse sei %s" + +#: ../../src/lib/apputils/net-server.c:1479 +msgid "too many connections" +msgstr "zu viele Verbindungen" + +#: ../../src/lib/apputils/net-server.c:1502 +#, c-format +msgid "dropping %s fd %d from %s" +msgstr "%s Dateideskriptor %d von %s wird verworfen" + +#: ../../src/lib/apputils/net-server.c:1580 +#, c-format +msgid "allocating buffer for new TCP session from %s" +msgstr "Puffer für neue TCP-Sitzung von %s wird reserviert" + +#: ../../src/lib/apputils/net-server.c:1610 +msgid "while dispatching (tcp)" +msgstr "beim Versenden (TCP)" + +#: ../../src/lib/apputils/net-server.c:1642 +msgid "error allocating tcp dispatch private!" +msgstr "Fehler beim Reservieren zum nicht öffentlichen TCP-Versand!" + +#: ../../src/lib/apputils/net-server.c:1689 +#, c-format +msgid "TCP client %s wants %lu bytes, cap is %lu" +msgstr "TCP-Client %s will %lu Byte, Cap ist %lu" + +#: ../../src/lib/apputils/net-server.c:1697 +#, c-format +msgid "error constructing KRB_ERR_FIELD_TOOLONG error! %s" +msgstr "Fehler beim Erzeugen des KRB_ERR_FIELD_TOOLONG-Fehlers! %s" + +#: ../../src/lib/apputils/net-server.c:1876 +#, c-format +msgid "accepted RPC connection on socket %d from %s" +msgstr "akzeptierte PRC-Verbindung auf Socket %d von %s" + +# pseudo random function +#: ../../src/lib/crypto/krb/cf2.c:114 +#, c-format +msgid "Enctype %d has no PRF" +msgstr "Verschlüsselungstyp %d hat keine PRF" + +#: ../../src/lib/crypto/krb/prng_fortuna.c:428 +msgid "Random number generator could not be seeded" +msgstr "Zufallszahlengenerator konnte kein Startwert zugewiesen werden" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:43 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:165 +msgid "A required input parameter could not be read" +msgstr "Ein benötigter Eingabeparameter konnte nicht gelesen werden." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:44 +msgid "A required input parameter could not be written" +msgstr "Ein benötigter Eingabeparameter konnte nicht geschrieben werden." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:45 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:175 +msgid "A parameter was malformed" +msgstr "Ein Parameter hatte eine falsche Form" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:48 +msgid "calling error" +msgstr "Aufruffehler" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:59 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:195 +msgid "An unsupported mechanism was requested" +msgstr "Ein nicht unterstützter Mechanismus wurde angefordert." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:60 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:199 +msgid "An invalid name was supplied" +msgstr "Ein ungültiger Name wurde übergeben." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:61 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:203 +msgid "A supplied name was of an unsupported type" +msgstr "Ein übergebener Name hatte einen nicht unterstützten Typ." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:62 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:208 +msgid "Incorrect channel bindings were supplied" +msgstr "Falsche Kanalbindungen wurden übergeben." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:63 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:179 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:274 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:334 +msgid "An invalid status code was supplied" +msgstr "Ein ungültiger Statuscode wurde übergeben." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:64 +msgid "A token had an invalid signature" +msgstr "Ein Merkmal hatte eine ungültige Signatur." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:65 +msgid "No credentials were supplied" +msgstr "Es wurden keine Anmeldedaten übergeben." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:66 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:223 +msgid "No context has been established" +msgstr "Es wurde keine Kontext etabliert." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:67 +msgid "A token was invalid" +msgstr "Ein Merkmal war ungültig." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:68 +msgid "A credential was invalid" +msgstr "Eine der Anmeldedaten war ungültig." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:69 +msgid "The referenced credentials have expired" +msgstr "Die referenzierten Anmeldedaten sind abgelaufen." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:70 +msgid "The context has expired" +msgstr "Der Kontext ist abgelaufen." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:71 +msgid "Miscellaneous failure" +msgstr "sonstiger Fehlschlag" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:72 +msgid "The quality-of-protection requested could not be provided" +msgstr "" +"Die angeforderte Qualität des Schutzes konnte nicht bereitgestellt werden." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:73 +msgid "The operation is forbidden by the local security policy" +msgstr "Die Aktion wird durch die lokale Sicherheitsrichtinie verboten." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:74 +msgid "The operation or option is not available" +msgstr "Die Aktion oder Option ist nicht verfügbar." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:77 +msgid "routine error" +msgstr "Fehler in einer Routine" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:89 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:311 +msgid "The routine must be called again to complete its function" +msgstr "" +"Die Routine muss erneut aufgerufen werden, um ihre Funktion zu " +"vervollständigen." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:90 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:316 +msgid "The token was a duplicate of an earlier token" +msgstr "Das Merkmal war ein Zweitexemplar eines früheren Merkmals." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:91 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:321 +msgid "The token's validity period has expired" +msgstr "Die Gültigkeitsperiode des Merkmals ist abgelaufen." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:92 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:325 +msgid "A later token has already been processed" +msgstr "Es wurde bereits ein neueres Merkmal verarbeitet." + +#: ../../src/lib/gssapi/generic/disp_major_status.c:95 +msgid "supplementary info code" +msgstr "zusätzlicher Informationscode" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:106 +#: ../lib/krb5/error_tables/krb5_err.c:23 +msgid "No error" +msgstr "kein Fehler" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:107 +#, c-format +msgid "Unknown %s (field = %d)" +msgstr "%s unbekannt (Feld = %d)" + +#: ../../src/lib/gssapi/krb5/acquire_cred.c:165 +#, c-format +msgid "No key table entry found matching %s" +msgstr "Es wurde kein zu %s passender Schlüsseltabelleneintrag gefunden." + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:161 +msgid "The routine completed successfully" +msgstr "Die Routine wurde erfolgreich abgeschlossen" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:170 +msgid "A required output parameter could not be written" +msgstr "Ein erforderlicher Ausgabeparameter konnte nicht geschrieben werden." + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:212 +msgid "A token had an invalid Message Integrity Check (MIC)" +msgstr "" +"Ein Merkmal hatte eine ungültige Meldungsintegritätsprüfung (Message " +"Integrity Check/MIC)." + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:217 +msgid "" +"No credentials were supplied, or the credentials were unavailable or " +"inaccessible" +msgstr "" +"Es wurden keine Anmeldedaten übergeben oder die Anmeldedaten waren nicht " +"verfügbar bzw. ein Zugriff darauf nicht möglich." + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:227 +msgid "Invalid token was supplied" +msgstr "Es wurde ein ungültiges Token übergeben." + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:231 +msgid "Invalid credential was supplied" +msgstr "ungültige Anmeldedaten wurden übergeben" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:235 +msgid "The referenced credential has expired" +msgstr "Die referenzierten Anmeldedaten sind abgelaufen." + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:239 +msgid "The referenced context has expired" +msgstr "Der referenzierte Kontext ist abgelaufen." + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:243 +msgid "Unspecified GSS failure. Minor code may provide more information" +msgstr "" +"nicht spezifizierter GSS-Fehlschlag. Möglicherweise stellt der " +"untergeordnete Code weitere Informationen bereit." + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:248 +msgid "The quality-of-protection (QOP) requested could not be provided" +msgstr "" +"Die Qualität des Schutzes (quality-of-protection/QOP) konnte nicht " +"bereitgestellt werden." + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:253 +msgid "The operation is forbidden by local security policy" +msgstr "Die Aktion wird durch die lokale Sicherheitsrichtinie verboten." + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:258 +msgid "The operation or option is not available or unsupported" +msgstr "" +"Die Aktion oder Option ist nicht verfügbar oder wird nicht unterstützt." + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:263 +msgid "The requested credential element already exists" +msgstr "Das angeforderte Anmeldedatenelement existiert bereits." + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:268 +msgid "The provided name was not mechanism specific (MN)" +msgstr "Der bereitgestellte Name war nicht mechanismusspezifisch (MN)." + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:329 +msgid "An expected per-message token was not received" +msgstr "Ein erwartetes nachrichtenspezifisches Token wurde nicht empfangen." + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1860 +msgid "SPNEGO cannot find mechanisms to negotiate" +msgstr "SPNEGO kann keine Mechanismen zum Aushandeln finden." + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1865 +msgid "SPNEGO failed to acquire creds" +msgstr "SPNEGO ist beim Beschaffen von Anmeldedaten gescheitert" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1870 +msgid "SPNEGO acceptor did not select a mechanism" +msgstr "SPNEGO-Abnehmer hat keinen Mechanismus ausgewählt" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1875 +msgid "SPNEGO failed to negotiate a mechanism" +msgstr "SPNEGO ist beim Aushandeln eines Mechanismus gescheitert." + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1880 +msgid "SPNEGO acceptor did not return a valid token" +msgstr "SPNEGO-Abnehmer hat kein gültiges Token zurückgeliefert" + +#: ../../src/lib/kadm5/alt_prof.c:854 +#, c-format +msgid "Cannot resolve address of admin server \"%s\" for realm \"%s\"" +msgstr "" +"Adresse des Admin-Servers »%s« für Realm »%s« kann nicht ermittelt werden" + +#: ../../src/lib/kadm5/logger.c:56 +#, c-format +msgid "%s: cannot parse <%s>\n" +msgstr "%s: <%s> kann nicht ausgewertet werden\n" + +#: ../../src/lib/kadm5/logger.c:57 +#, c-format +msgid "%s: warning - logging entry syntax error\n" +msgstr "%s: Warnung – Syntaxfehler bei Protokolleintrag\n" + +#: ../../src/lib/kadm5/logger.c:58 +#, c-format +msgid "%s: error writing to %s\n" +msgstr "%s: Fehler beim Schreiben auf %s\n" + +#: ../../src/lib/kadm5/logger.c:59 +#, c-format +msgid "%s: error writing to %s device\n" +msgstr "%s: Fehler beim Schreiben auf Gerät %s\n" + +#: ../../src/lib/kadm5/logger.c:61 +msgid "EMERGENCY" +msgstr "NOTFALL" + +#: ../../src/lib/kadm5/logger.c:62 +msgid "ALERT" +msgstr "ALARM" + +#: ../../src/lib/kadm5/logger.c:63 +msgid "CRITICAL" +msgstr "KRITISCH" + +#: ../../src/lib/kadm5/logger.c:64 +msgid "Error" +msgstr "Fehler" + +#: ../../src/lib/kadm5/logger.c:65 +msgid "Warning" +msgstr "Warnung" + +#: ../../src/lib/kadm5/logger.c:66 +msgid "Notice" +msgstr "Hinweis" + +#: ../../src/lib/kadm5/logger.c:67 +msgid "info" +msgstr "Information" + +#: ../../src/lib/kadm5/logger.c:68 +msgid "debug" +msgstr "Fehlersuchmeldung" + +#: ../../src/lib/kadm5/logger.c:967 +#, c-format +msgid "Couldn't open log file %s: %s\n" +msgstr "Protokolldatei %s konnte nicht geöffnet werden: %s\n" + +#: ../../src/lib/kadm5/srv/kadm5_hook.c:119 +#, c-format +msgid "kadm5_hook %s failed postcommit %s: %s" +msgstr "»kadm5_hook« %s ist beim Nach-Commit %s gescheitert: %s" + +#: ../../src/lib/kadm5/srv/pwqual_dict.c:106 +msgid "No dictionary file specified, continuing without one." +msgstr "keine Wörterbuchdatei angegeben, es wird ohne fortgefahren" + +#: ../../src/lib/kadm5/srv/pwqual_dict.c:113 +#, c-format +msgid "WARNING! Cannot find dictionary file %s, continuing without one." +msgstr "" +"WARNUNG! Wörterbuchdatei %s kann nicht gefunden werden, es wird ohne " +"fortgefahren" + +#: ../../src/lib/kadm5/srv/pwqual_empty.c:42 +msgid "Empty passwords are not allowed" +msgstr "Leere Passwörter sind nicht erlaubt." + +#: ../../src/lib/kadm5/srv/pwqual_hesiod.c:114 +msgid "Password may not match user information." +msgstr "Das Passwort darf keinen Anwenderdaten entsprechen." + +#: ../../src/lib/kadm5/srv/pwqual_princ.c:54 +msgid "Password may not match principal name" +msgstr "Das Passwort darf nicht mit dem Principal-Namen übereinstimmen." + +#: ../../src/lib/kadm5/srv/server_acl.c:89 +#, c-format +msgid "%s: line %d too long, truncated" +msgstr "%s: Zeile %d zu lang, wurde gekürzt" + +#: ../../src/lib/kadm5/srv/server_acl.c:90 +#, c-format +msgid "Unrecognized ACL operation '%c' in %s" +msgstr "unbekannte ACL-Aktion »%c« in %s" + +#: ../../src/lib/kadm5/srv/server_acl.c:92 +#, c-format +msgid "%s: syntax error at line %d <%10s...>" +msgstr "%s: Syntaxfehler in Zeile %d <%10s …>" + +#: ../../src/lib/kadm5/srv/server_acl.c:94 +#, c-format +msgid "%s while opening ACL file %s" +msgstr "%s beim Öffnen der ACL-Datei %s" + +#: ../../src/lib/kadm5/srv/server_acl.c:353 +#, c-format +msgid "%s: invalid restrictions: %s" +msgstr "%s: ungültige Beschränkung: %s" + +#: ../../src/lib/kadm5/srv/server_kdb.c:192 +msgid "History entry contains no key data" +msgstr "Chronikeintrag enthält keine Schlüsseldaten" + +#: ../../src/lib/kadm5/srv/server_misc.c:128 +#, c-format +msgid "password quality module %s rejected password for %s: %s" +msgstr "" +"Das Modul %s für Passwortqualität hat das Passwort für %s abgelehnt: %s" + +#: ../../src/lib/kadm5/str_conv.c:80 +msgid "Not Postdateable" +msgstr "nicht vordatierbar" + +#: ../../src/lib/kadm5/str_conv.c:81 +msgid "Not Forwardable" +msgstr "nicht weiterleitbar" + +#: ../../src/lib/kadm5/str_conv.c:82 +msgid "No TGT-based requests" +msgstr "keine TGT-basierten Anfragen" + +#: ../../src/lib/kadm5/str_conv.c:83 +msgid "Not renewable" +msgstr "nicht erneuerbar" + +#: ../../src/lib/kadm5/str_conv.c:84 +msgid "Not proxiable" +msgstr "Proxy nicht nutzbar" + +#: ../../src/lib/kadm5/str_conv.c:85 +msgid "No DUP_SKEY requests" +msgstr "keine DUP_SKEY-Anfragen" + +#: ../../src/lib/kadm5/str_conv.c:86 +msgid "All Tickets Disallowed" +msgstr "keine Tickets erlaubt" + +#: ../../src/lib/kadm5/str_conv.c:87 +msgid "Preauthentication required" +msgstr "Vorauthentifizierung erforderlich" + +#: ../../src/lib/kadm5/str_conv.c:88 +msgid "HW authentication required" +msgstr "HW-Authentifizierung erforderlich" + +#: ../../src/lib/kadm5/str_conv.c:89 +msgid "OK as Delegate" +msgstr "OK als Vertreter" + +#: ../../src/lib/kadm5/str_conv.c:90 +msgid "Password Change required" +msgstr "Passwortänderung erforderlich" + +#: ../../src/lib/kadm5/str_conv.c:91 +msgid "Service Disabled" +msgstr "Dienst deaktiviert" + +#: ../../src/lib/kadm5/str_conv.c:92 +msgid "Password Changing Service" +msgstr "Passwortänderungsdienst" + +#: ../../src/lib/kadm5/str_conv.c:93 +msgid "RSA-MD5 supported" +msgstr "RSA-MD5 unterstützt" + +#: ../../src/lib/kadm5/str_conv.c:94 +msgid "Protocol transition with delegation allowed" +msgstr "Protokollübergang mit Vertretung erlaubt" + +#: ../../src/lib/kadm5/str_conv.c:95 +msgid "No authorization data required" +msgstr "keine Autorisierungsdaten erforderlich" + +#: ../../src/lib/kdb/kdb5.c:219 +msgid "No default realm set; cannot initialize KDB" +msgstr "kein Standard-Realm gesetzt; KDB kann nicht initialisiert werden" + +#: ../../src/lib/kdb/kdb5.c:324 ../../src/lib/kdb/kdb5.c:406 +#, c-format +msgid "Unable to find requested database type: %s" +msgstr "angeforderter Datenbanktyp kann nicht gefunden werden. %s" + +#: ../../src/lib/kdb/kdb5.c:416 +#, c-format +msgid "plugin symbol 'kdb_function_table' lookup failed: %s" +msgstr "" +"Nachschlagen des Erweiterungssymbols »kdb_function_table« fehlgeschlagen: %s" + +#: ../../src/lib/kdb/kdb5.c:426 +#, c-format +msgid "" +"Unable to load requested database module '%s': plugin symbol " +"'kdb_function_table' not found" +msgstr "" +"angefordertes Datenbankmodul »%s« kann nicht geladen werden: " +"Erweiterungssymbol »kdb_function_table« nicht gefunden" + +#: ../../src/lib/kdb/kdb5.c:1650 +#, c-format +msgid "Illegal version number for KRB5_TL_MKEY_AUX %d\n" +msgstr "Ungültige Versionsnummer für KRB5_TL_MKEY_AUX %d\n" + +#: ../../src/lib/kdb/kdb5.c:1819 +#, c-format +msgid "Illegal version number for KRB5_TL_ACTKVNO %d\n" +msgstr "Ungültige Versionsnummer für KRB5_TL_ACTKVNO %d\n" + +#: ../../src/lib/kdb/kdb_default.c:164 +#, c-format +msgid "keyfile (%s) is not a regular file: %s" +msgstr "Schlüsseldatei (%s) ist keine normale Datei: %s" + +#: ../../src/lib/kdb/kdb_default.c:177 +msgid "Could not create temp keytab file name." +msgstr "Temporärer Schlüsseltabellendateiname konnte nicht erstellt werden." + +#: ../../src/lib/kdb/kdb_default.c:202 +#, c-format +msgid "Temporary stash file already exists: %s." +msgstr "Temporäre Ablagedatei existiert bereits: %s." + +#: ../../src/lib/kdb/kdb_default.c:230 +#, c-format +msgid "rename of temporary keyfile (%s) to (%s) failed: %s" +msgstr "" +"Umbenennen von temporärer Schlüsseldatei (%s) in (%s) fehlgeschlagen: %s" + +#: ../../src/lib/kdb/kdb_default.c:419 +#, c-format +msgid "Can not fetch master key (error: %s)." +msgstr "Hauptschlüssel kann nicht abgeholt werden (Fehler: %s)" + +#: ../../src/lib/kdb/kdb_default.c:482 +msgid "Unable to decrypt latest master key with the provided master key\n" +msgstr "" +"Letzter Hauptschlüssel kann nicht mit dem bereitgestellten Hauptschlüssel " +"entschlüsselt werden.\n" + +#: ../../src/lib/kdb/kdb_log.c:83 +msgid "could not sync ulog header to disk" +msgstr "Ulog-Kopfzeilen konnten nicht auf die Platte synchronisiert werden" + +#: ../../src/lib/krb5/ccache/cc_dir.c:122 +#, c-format +msgid "Subsidiary cache path %s has no parent directory" +msgstr "" +"Ergänzender Zwischenspeicherpfad %s hat kein übergeordnetes Verzeichnis." + +#: ../../src/lib/krb5/ccache/cc_dir.c:128 +#, c-format +msgid "Subsidiary cache path %s filename does not begin with \"tkt\"" +msgstr "" +"Dateiname des ergänzenden Zwischenspeicherpfads %s beginnt nicht mit »tkt«" + +#: ../../src/lib/krb5/ccache/cc_dir.c:169 +#, c-format +msgid "%s contains invalid filename" +msgstr "%s enthält einen ungültigen Dateinamen." + +#: ../../src/lib/krb5/ccache/cc_dir.c:229 +#, c-format +msgid "Credential cache directory %s does not exist" +msgstr "Anmeldedatenzwischenspeicherverzeichnis %s existiert nicht." + +#: ../../src/lib/krb5/ccache/cc_dir.c:235 +#, c-format +msgid "Credential cache directory %s exists but is not a directory" +msgstr "" +"Anmeldedatenzwischenspeicherverzeichnis %s existiert, ist jedoch kein " +"Verzeichnis" + +#: ../../src/lib/krb5/ccache/cc_dir.c:400 +msgid "" +"Can't create new subsidiary cache because default cache is not a directory " +"collection" +msgstr "" +"Der neue ergänzende Zwischenspeicher kann nicht erstellt werden, da der " +"Standardzwischenspeicher keine Ansammlung von Verzeichnissen ist." + +#: ../../src/lib/krb5/ccache/cc_file.c:569 +#, c-format +msgid "Credentials cache file '%s' not found" +msgstr "Anmeldedatenzwischenspeicherdatei »%s« nicht gefunden" + +#: ../../src/lib/krb5/ccache/cc_file.c:1575 +#, c-format +msgid "Credentials cache I/O operation failed (%s)" +msgstr "Anmeldedatenzwischenspeicher-E/A-Aktion fehlgeschlagen (%s)" + +#: ../../src/lib/krb5/ccache/cc_keyring.c:1151 +msgid "" +"Can't create new subsidiary cache because default cache is already a " +"subsidiary" +msgstr "" +"Der neue ergänzende Zwischenspeicher kann nicht erstellt werden, da der " +"Standardzwischenspeicher bereits eine Ergänzung ist." + +#: ../../src/lib/krb5/ccache/cc_keyring.c:1219 +#, c-format +msgid "Credentials cache keyring '%s' not found" +msgstr "Schlüsselbund %s des Anmeldedatenzwischenspeichers nicht gefunden" + +#: ../../src/lib/krb5/ccache/cccursor.c:212 +#, c-format +msgid "Can't find client principal %s in cache collection" +msgstr "" +"Client-Principal %s kann nicht in der Zwischenspeicheransammlung gefunden " +"werden" + +#: ../../src/lib/krb5/ccache/cccursor.c:253 +msgid "No Kerberos credentials available" +msgstr "keine Kerberos-Anmeldedaten verfügbar" + +#: ../../src/lib/krb5/keytab/kt_file.c:398 +#, c-format +msgid "No key table entry found for %s" +msgstr "Für %s wurde kein Schlüsseltabelleneintrag gefunden." + +#: ../../src/lib/krb5/keytab/kt_file.c:815 +#: ../../src/lib/krb5/keytab/kt_file.c:848 +msgid "Cannot change keytab with keytab iterators active" +msgstr "" +"Schlüsseltabelle mit aktiven Schlüsseltabelleniteratoren kann nicht geändert " +"werden" + +#: ../../src/lib/krb5/keytab/kt_file.c:1047 +#, c-format +msgid "Key table file '%s' not found" +msgstr "Schlüsseltabellendatei »%s« nicht gefunden" + +#: ../../src/lib/krb5/keytab/ktfns.c:127 +#, c-format +msgid "Keytab %s is nonexistent or empty" +msgstr "Schlüsseltabelle %s existiert nicht oder ist leer" + +#: ../../src/lib/krb5/krb/chpw.c:251 +msgid "Malformed request error" +msgstr "Fehler wegen Anfrage in falscher Form" + +#: ../../src/lib/krb5/krb/chpw.c:254 ../lib/krb5/error_tables/kdb5_err.c:58 +msgid "Server error" +msgstr "Serverfehler" + +#: ../../src/lib/krb5/krb/chpw.c:257 +msgid "Authentication error" +msgstr "Authentifizierungsfehler" + +#: ../../src/lib/krb5/krb/chpw.c:260 +msgid "Password change rejected" +msgstr "Passwortänderung abgelehnt" + +#: ../../src/lib/krb5/krb/chpw.c:263 +msgid "Access denied" +msgstr "Zugriff verweigert" + +#: ../../src/lib/krb5/krb/chpw.c:266 +msgid "Wrong protocol version" +msgstr "falsche Protokollversion" + +#: ../../src/lib/krb5/krb/chpw.c:269 +msgid "Initial password required" +msgstr "Erstpasswort erforderlich" + +#: ../../src/lib/krb5/krb/chpw.c:272 +msgid "Success" +msgstr "Erfolg" + +#: ../../src/lib/krb5/krb/chpw.c:275 ../lib/krb5/error_tables/krb5_err.c:257 +msgid "Password change failed" +msgstr "Ändern des Passworts fehlgeschlagen" + +#: ../../src/lib/krb5/krb/chpw.c:433 +msgid "" +"The password must include numbers or symbols. Don't include any part of " +"your name in the password." +msgstr "" +"Das Passwort muss Zahlen oder Symbole enthalten. Fügen Sie keinen Teil Ihres " +"Namens in das Passwort ein." + +#: ../../src/lib/krb5/krb/chpw.c:439 +#, c-format +msgid "The password must contain at least %d character." +msgid_plural "The password must contain at least %d characters." +msgstr[0] "Das Passwort muss mindestens %d Zeichen enthalten." +msgstr[1] "Das Passwort muss mindestens %d Zeichen enthalten." + +#: ../../src/lib/krb5/krb/chpw.c:448 +#, c-format +msgid "The password must be different from the previous password." +msgid_plural "The password must be different from the previous %d passwords." +msgstr[0] "Das Passwort muss sich vom vorhergehenden Passwort unterscheiden." +msgstr[1] "" +"Das Passwort muss sich von den vorhergehenden %d Passwörtern unterscheiden." + +#: ../../src/lib/krb5/krb/chpw.c:460 +#, c-format +msgid "The password can only be changed once a day." +msgid_plural "The password can only be changed every %d days." +msgstr[0] "Das Passwort kann nur einmal täglich geändert werden." +msgstr[1] "Das Passwort kann nur alle %d Tage geändert werden." + +#: ../../src/lib/krb5/krb/chpw.c:506 +msgid "Try a more complex password, or contact your administrator." +msgstr "" +"Versuchen Sie es mit einem etwas komplexeren Passwort oder wenden Sie sich " +"an Ihren Administrator." + +#: ../../src/lib/krb5/krb/fast.c:217 +#, c-format +msgid "%s constructing AP-REQ armor" +msgstr "%s-Konstruktion von AP-REQ-Schutz" + +#: ../../src/lib/krb5/krb/fast.c:399 +#, c-format +msgid "%s while decrypting FAST reply" +msgstr "%s beim Entschlüsseln der FAST-Antwort" + +#: ../../src/lib/krb5/krb/fast.c:408 +msgid "nonce modified in FAST response: KDC response modified" +msgstr "" +"Nummer für einmaligen Gebrauch in der FAST-Anwort geändert: KDC-Anwort " +"geändert" + +#: ../../src/lib/krb5/krb/fast.c:474 +msgid "Expecting FX_ERROR pa-data inside FAST container" +msgstr "Innerhalb des FAST-Containers wird »FX_ERROR pa-data« erwartet." + +#: ../../src/lib/krb5/krb/fast.c:545 +msgid "FAST response missing finish message in KDC reply" +msgstr "Der FAST-Anwort fehlt die Beendigungsnachricht in der KDC-Anwort" + +#: ../../src/lib/krb5/krb/fast.c:558 +msgid "Ticket modified in KDC reply" +msgstr "Ticket in der KDC-Antwort verändert" + +#: ../../src/lib/krb5/krb/gc_via_tkt.c:208 +#, c-format +msgid "KDC returned error string: %.*s" +msgstr "KDC gab eine Fehlermeldung zurück: %.*s" + +#: ../../src/lib/krb5/krb/gc_via_tkt.c:217 +#, c-format +msgid "Server %s not found in Kerberos database" +msgstr "Server %s wurde nicht in der Kerberos-Datenbank gefunden" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:133 +msgid "Reply has wrong form of session key for anonymous request" +msgstr "" +"Antwort hat die falsche Form des Sitzungschlüssels für eine anonyme Anfrage" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1628 +#, c-format +msgid "%s while storing credentials" +msgstr "%s beim Speichern der Anmeldedaten" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1715 +#, c-format +msgid "Client '%s' not found in Kerberos database" +msgstr "Client »%s« wurde nicht in der Kerberos-Datenbank gefunden" + +#: ../../src/lib/krb5/krb/gic_keytab.c:207 +#, c-format +msgid "Keytab contains no suitable keys for %s" +msgstr "Schlüsseltabelle enthält keine passenden Schlüssel für %s" + +#: ../../src/lib/krb5/krb/gic_pwd.c:75 +#, c-format +msgid "Password for %s" +msgstr "Passwort für %s" + +#: ../../src/lib/krb5/krb/gic_pwd.c:227 +#, c-format +msgid "Warning: Your password will expire in less than one hour on %s" +msgstr "" +"Warnung: Ihr Passwort auf %s wird in weniger als einer Stunde ablaufen." + +# FIXME in German impossible; plural without »s« +#: ../../src/lib/krb5/krb/gic_pwd.c:231 +#, c-format +msgid "Warning: Your password will expire in %d hour%s on %s" +msgstr "Warnung: Ihr Passwort wird in %d Stunden%s am %s ablaufen." + +#: ../../src/lib/krb5/krb/gic_pwd.c:235 +#, c-format +msgid "Warning: Your password will expire in %d days on %s" +msgstr "Warnung: Ihr Passwort wird in %d Tagen am %s ablaufen." + +#: ../../src/lib/krb5/krb/gic_pwd.c:409 +msgid "Password expired. You must change it now." +msgstr "Passwort abgelaufen. Sie müssen es nun ändern." + +#: ../../src/lib/krb5/krb/gic_pwd.c:428 ../../src/lib/krb5/krb/gic_pwd.c:432 +#, c-format +msgid "%s. Please try again." +msgstr "%s. Bitte versuchen Sie es erneut." + +#: ../../src/lib/krb5/krb/gic_pwd.c:471 +#, c-format +msgid "%.*s%s%s. Please try again.\n" +msgstr "%.*s%s%s. Bitte versuchen Sie es erneut.\n" + +#: ../../src/lib/krb5/krb/parse.c:203 +#, c-format +msgid "Principal %s is missing required realm" +msgstr "Principal %s fehlt erforderlicher Realm" + +#: ../../src/lib/krb5/krb/parse.c:215 +#, c-format +msgid "Principal %s has realm present" +msgstr "Für Principal %s ist Realm vorhanden" + +#: ../../src/lib/krb5/krb/plugin.c:165 +#, c-format +msgid "Invalid module specifier %s" +msgstr "ungültiger Modulbezeichner %s" + +#: ../../src/lib/krb5/krb/plugin.c:402 +#, c-format +msgid "Could not find %s plugin module named '%s'" +msgstr "Das Erweiterungsmodul %s namens »%s« konnte nicht gefunden werden." + +#: ../../src/lib/krb5/krb/preauth2.c:1018 +msgid "Unable to initialize preauth context" +msgstr "Vorauthentifizierungskontext konnte nicht initialisiert werden." + +#: ../../src/lib/krb5/krb/preauth2.c:1032 +#, c-format +msgid "Preauth module %s: %s" +msgstr "Vorauthentifizierungsmodul %s: %s" + +#: ../../src/lib/krb5/krb/preauth_otp.c:510 +msgid "Please choose from the following:\n" +msgstr "Bitte wählen Sie aus dem Folgenden aus:\n" + +#: ../../src/lib/krb5/krb/preauth_otp.c:511 +msgid "Vendor:" +msgstr "Anbieter:" + +#: ../../src/lib/krb5/krb/preauth_otp.c:523 +msgid "Enter #" +msgstr "Geben Sie # ein" + +#: ../../src/lib/krb5/krb/preauth_otp.c:559 +msgid "OTP Challenge:" +msgstr "Anforderung des Einwegpassworts:" + +#: ../../src/lib/krb5/krb/preauth_otp.c:588 +msgid "OTP Token PIN" +msgstr "Einwegpasswort-Token-PIN" + +#: ../../src/lib/krb5/krb/preauth_otp.c:702 +msgid "OTP value doesn't match any token formats" +msgstr "Wert des Einwegpassworts entspricht keinem Token-Format" + +#: ../../src/lib/krb5/krb/preauth_otp.c:769 +msgid "Enter OTP Token Value" +msgstr "Geben Sie den Wert des Einwegpasswort-Tokens an" + +#: ../../src/lib/krb5/krb/preauth_otp.c:914 +msgid "No supported tokens" +msgstr "keine unterstützten Token" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:49 +msgid "Challenge for Enigma Logic mechanism" +msgstr "Anforderung für Enigma-Logic-Mechanismus" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:53 +msgid "Challenge for Digital Pathways mechanism" +msgstr "Anforderung für Digital-Pathway-Mechanismus" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:57 +msgid "Challenge for Activcard mechanism" +msgstr "Anforderung für Activcard-Mechanismus" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:60 +msgid "Challenge for Enhanced S/Key mechanism" +msgstr "Anforderung für erweiterten S/Key-Mechanismus" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:63 +msgid "Challenge for Traditional S/Key mechanism" +msgstr "Anforderung für traditionellen S/Key-Mechanismus" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:66 +#: ../../src/lib/krb5/krb/preauth_sam2.c:69 +msgid "Challenge for Security Dynamics mechanism" +msgstr "Anforderung für Security-Dynamics-Mechanismus" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:72 +msgid "Challenge from authentication server" +msgstr "Anforderung vom Authentifizierungsserver" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:166 +msgid "SAM Authentication" +msgstr "SAM-Authentifizierung" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:145 +#, c-format +msgid "Cannot find key for %s kvno %d in keytab" +msgstr "" +"Schlüssel für %s-KNVO %d kann nicht in der Schlüsseltabelle gefunden werden" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:150 +#, c-format +msgid "Cannot find key for %s kvno %d in keytab (request ticket server %s)" +msgstr "" +"Schlüssel für %s-KNVO %d kann nicht in der Schlüsseltabelle gefunden werden " +"(angefragter Ticketserver %s)" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:175 +#, c-format +msgid "Cannot decrypt ticket for %s using keytab key for %s" +msgstr "" +"Ticket für %s kann nicht mittels des Schlüsseltabellenschlüssels für %s " +"entschlüsselt werden" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:197 +#, c-format +msgid "Server principal %s does not match request ticket server %s" +msgstr "Server-Principal %s passt nicht zum abgefragten Ticketserver %s" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:226 +msgid "No keys in keytab" +msgstr "keine Schlüssel in der Schlüsseltabelle" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:229 +#, c-format +msgid "Server principal %s does not match any keys in keytab" +msgstr "" +"Server-Principal %s hat keinen passenden Schlüssel in der Schlüsseltabelle" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:236 +#, c-format +msgid "" +"Request ticket server %s found in keytab but does not match server principal " +"%s" +msgstr "" +"abgefragter Ticketserver %s wurde in der Schlüsseltabelle gefunden, er passte " +"jedoch nicht zu Server-Principal %s" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:241 +#, c-format +msgid "Request ticket server %s not found in keytab (ticket kvno %d)" +msgstr "" +"Abgefragter Ticketserver %s wurde nicht in der Schlüsseltabelle gefunden " +"(Ticket KVNO %d)." + +#: ../../src/lib/krb5/krb/rd_req_dec.c:247 +#, c-format +msgid "" +"Request ticket server %s kvno %d not found in keytab; ticket is likely out " +"of date" +msgstr "" +"Abgefragter Ticketserver %s KVNO %d wurde nicht in der Schlüsseltabelle " +"gefunden; Ticket ist wahrscheinlich abgelaufen." + +#: ../../src/lib/krb5/krb/rd_req_dec.c:252 +#, c-format +msgid "" +"Request ticket server %s kvno %d not found in keytab; keytab is likely out " +"of date" +msgstr "" +"Abgefragter Ticketserver %s KVNO %d wurde nicht in der Schlüsseltabelle " +"gefunden; Schlüsseltabelle ist wahrscheinlich nicht mehr aktuell." + +#: ../../src/lib/krb5/krb/rd_req_dec.c:261 +#, c-format +msgid "" +"Request ticket server %s kvno %d found in keytab but not with enctype %s" +msgstr "" +"Abgefragter Ticketserver %s KVNO %d wurde in der Schlüsseltabelle gefunden, " +"jedoch nicht mit Verschlüsselungstyp %s." + +#: ../../src/lib/krb5/krb/rd_req_dec.c:266 +#, c-format +msgid "" +"Request ticket server %s kvno %d enctype %s found in keytab but cannot " +"decrypt ticket" +msgstr "" +"Abgefragter Ticketserver %s KVNO %d mit Verschlüsselungstyp %s in der " +"Schlüsseltabelle gefunden, Ticket kann jedoch nicht entschlüsselt werden." + +#: ../../src/lib/krb5/krb/rd_req_dec.c:897 +#, c-format +msgid "Encryption type %s not permitted" +msgstr "Verschlüsselungstyp %s nicht erlaubt" + +#: ../../src/lib/krb5/os/expand_path.c:316 +#, c-format +msgid "Can't find username for uid %lu" +msgstr "Zu UID %lu kann kein Benutzername gefunden werden." + +#: ../../src/lib/krb5/os/expand_path.c:405 +#: ../../src/lib/krb5/os/expand_path.c:421 +msgid "Invalid token" +msgstr "ungültiges Token" + +#: ../../src/lib/krb5/os/expand_path.c:506 +msgid "variable missing }" +msgstr "Variable fehlt }" + +#: ../../src/lib/krb5/os/locate_kdc.c:660 +#, c-format +msgid "Cannot find KDC for realm \"%.*s\"" +msgstr "KDC für Realm »%.*s« kann nicht gefunden werden" + +#: ../../src/lib/krb5/os/sendto_kdc.c:475 +#, c-format +msgid "Cannot contact any KDC for realm '%.*s'" +msgstr "für Realm »%.*s« kann nicht KDC kontaktiert werden" + +#: ../../src/lib/krb5/rcache/rc_io.c:106 +#, c-format +msgid "Cannot fstat replay cache file %s: %s" +msgstr "»fstat« für Antwortzwischenspeicherdatei %s nicht möglich: %s" + +#: ../../src/lib/krb5/rcache/rc_io.c:112 +#, c-format +msgid "" +"Insecure mkstemp() file mode for replay cache file %s; try running this " +"program with umask 077" +msgstr "" +"unsicherer mkstemp()-Dateimodus für Antwortzwischenspeicherdatei %s; " +"versuchen Sie, dieses Programm mit der Umask 077 auszuführen" + +#: ../../src/lib/krb5/rcache/rc_io.c:144 +#, c-format +msgid "Cannot %s replay cache file %s: %s" +msgstr "%s der Wiederholungszwischenspeicherdatei %s nicht möglich: %s" + +#: ../../src/lib/krb5/rcache/rc_io.c:149 +#, c-format +msgid "Cannot %s replay cache: %s" +msgstr "%s des Wiederholungszwischenspeichers nicht möglich: %s" + +#: ../../src/lib/krb5/rcache/rc_io.c:272 +#, c-format +msgid "Insecure file mode for replay cache file %s" +msgstr "unsicherer Dateimodus für Wiederholungszwischenspeicherdatei %s" + +#: ../../src/lib/krb5/rcache/rc_io.c:278 +#, c-format +msgid "rcache not owned by %d" +msgstr "Rcache gehört nicht %d" + +#: ../../src/lib/krb5/rcache/rc_io.c:402 ../../src/lib/krb5/rcache/rc_io.c:406 +#: ../../src/lib/krb5/rcache/rc_io.c:411 +#, c-format +msgid "Can't write to replay cache: %s" +msgstr "" +"in Wiederholungszwischenspeicherdatei kann nicht geschrieben werden: %s" + +#: ../../src/lib/krb5/rcache/rc_io.c:432 +#, c-format +msgid "Cannot sync replay cache file: %s" +msgstr "" +"Wiederholungszwischenspeicherdatei kann nicht synchronisiert werden: %s" + +#: ../../src/lib/krb5/rcache/rc_io.c:451 +#, c-format +msgid "Can't read from replay cache: %s" +msgstr "aus dem Wiederholungszwischenspeicher kann nicht gelesen werden: %s" + +#: ../../src/lib/krb5/rcache/rc_io.c:482 ../../src/lib/krb5/rcache/rc_io.c:488 +#: ../../src/lib/krb5/rcache/rc_io.c:493 +#, c-format +msgid "Can't destroy replay cache: %s" +msgstr "Wiederholungszwischenspeicher kann nicht vernichtet werden: %s" + +#: ../../src/plugins/kdb/db2/kdb_db2.c:245 +#: ../../src/plugins/kdb/db2/kdb_db2.c:830 +#, c-format +msgid "Unsupported argument \"%s\" for db2" +msgstr "nicht unterstütztes Argument »%s« für DB2" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:69 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:887 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1088 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1507 +msgid "while reading kerberos container information" +msgstr "beim Lesen der Kerberos-Container-Information" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:129 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:143 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:504 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:518 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:151 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:166 +msgid "while providing time specification" +msgstr "beim Bereitstellen der Zeitspezifikation" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:268 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:304 +msgid "while creating policy object" +msgstr "beim Erstellen des Richtlinienobjekts" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:279 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1515 +msgid "while reading realm information" +msgstr "beim Lesen der Realm-Information" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:348 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:407 +msgid "while destroying policy object" +msgstr "beim Zerstören des Richtlinienobjekts" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:358 +#, c-format +msgid "This will delete the policy object '%s', are you sure?\n" +msgstr "Dies wird das Richtlinienobjekt »%s« löschen, sind Sie sicher?\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:473 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:663 +msgid "while modifying policy object" +msgstr "beim Ändern des Richtlinienobjekts" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:487 +#, c-format +msgid "while reading information of policy '%s'" +msgstr "beim Lesen der Information der Richtlinie »%s«" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:692 +msgid "while viewing policy" +msgstr "beim Betrachten der Richtlinie" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:701 +#, c-format +msgid "while viewing policy '%s'" +msgstr "beim Betrachten der Richtlinie »%s«" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:835 +msgid "while listing policy objects" +msgstr "beim Auflisten der Richtlinienobjekte" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:453 +#, c-format +msgid "for subtree while creating realm '%s'" +msgstr "für einen Teilbaum beim Erstellen von Realm »%s«" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:465 +#, c-format +msgid "for container reference while creating realm '%s'" +msgstr "für Container-Bezug beim Erstellen von Realm »%s«" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:489 +#, c-format +msgid "invalid search scope while creating realm '%s'" +msgstr "ungültiger Suchbereich beim Erstellen von Realm »%s«" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:504 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:823 +#, c-format +msgid "'%s' is an invalid option\n" +msgstr "»%s« ist keine gültige Option\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:512 +#, c-format +msgid "Initializing database for realm '%s'\n" +msgstr "Datenbank für Realm »%s« wird initialisiert\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:536 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:696 +#, c-format +msgid "while creating realm '%s'" +msgstr "beim Erstellen von Realm »%s«" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:556 +#, c-format +msgid "Enter DN of Kerberos container: " +msgstr "Geben Sie die den DN des Kerberos-Containers ein: " + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:591 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:894 +#, c-format +msgid "while reading information of realm '%s'" +msgstr "beim Lesen der Information von Realm »%s«" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:733 +msgid "while reading Kerberos container information" +msgstr "beim Lesen der Kerberos-Container-Information" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:774 +#, c-format +msgid "for subtree while modifying realm '%s'" +msgstr "für einen Teilbaum beim Ändern von Realm »%s«" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:785 +#, c-format +msgid "for container reference while modifying realm '%s'" +msgstr "für Container-Bezug beim Ändern von Realm »%s«" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:812 +#, c-format +msgid "specified for search scope while modifying information of realm '%s'" +msgstr "" +"angegeben für Suchbereich, während die Information für Realm »%s« geändert " +"wird" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:851 +#, c-format +msgid "while modifying information of realm '%s'" +msgstr "beim Ändern der Information von Realm »%s«" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:940 +msgid "Realm Name" +msgstr "Realm-Name" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:943 +msgid "Subtree" +msgstr "Teilbaum" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:946 +msgid "Principal Container Reference" +msgstr "Principal-Container-Bezug" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:951 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:953 +msgid "SearchScope" +msgstr "Suchbereich" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:951 +msgid "Invalid !" +msgstr "ungültig!" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:958 +msgid "KDC Services" +msgstr "KDC-Dienste" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:973 +msgid "Admin Services" +msgstr "Administratordienste" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:988 +msgid "Passwd Services" +msgstr "Passwortdienste" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1004 +msgid "Maximum Ticket Life" +msgstr "maximale Ticketlebensdauer" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1009 +msgid "Maximum Renewable Life" +msgstr "maximale verlängerbare Lebensdauer" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1016 +msgid "Ticket flags" +msgstr "Ticket-Flags" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1095 +msgid "while listing realms" +msgstr "beim Auflisten der Realms" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1439 +msgid "while adding entries to database" +msgstr "beim Hinzufügen von Einträgen zur Datenbank" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1480 +#, c-format +msgid "Deleting KDC database of '%s', are you sure?\n" +msgstr "" +"Sind Sie sicher, dass die KDC-Datenbank von »%s« gelöscht werden soll?\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1491 +#, c-format +msgid "OK, deleting database of '%s'...\n" +msgstr "OK, die Datenbank von »%s« wird gelöscht …\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1524 +#, c-format +msgid "deleting database of '%s'" +msgstr "Die Datenbank von »%s« wird gelöscht." + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1529 +#, c-format +msgid "** Database of '%s' destroyed.\n" +msgstr "** Datenbank von »%s« vernichtet\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:81 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:88 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:96 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:104 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:120 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:148 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:227 +msgid "while setting service object password" +msgstr "beim Setzen des Passworts für das Dienstobjekt" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:140 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:477 +#, c-format +msgid "Password for \"%s\"" +msgstr "Passwort für »%s«" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:143 +#, c-format +msgid "Re-enter password for \"%s\"" +msgstr "Geben Sie das Passwort für »%s« erneut ein." + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:154 +#, c-format +msgid "%s: Invalid password\n" +msgstr "%s: ungültiges Passwort\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:170 +msgid "Failed to convert the password to hexadecimal" +msgstr "Das Umwandeln des Passworts in Dezimalschreibweise ist fehlgeschlagen." + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:183 +#, c-format +msgid "Failed to open file %s: %s" +msgstr "Datei %s konnte nicht geöffnet werden: %s" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:205 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:247 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:256 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:283 +msgid "Failed to write service object password to file" +msgstr "" +"Schreiben des Passworts für das Dienstobjekt in eine Datei fehlgeschlagen" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:211 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:268 +msgid "Error reading service object password file" +msgstr "Fehler beim Lesen der Passwortdatei für das Dienstobjekt" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:236 +#, c-format +msgid "Error creating file %s" +msgstr "Fehler beim Erstellen der Datei %s" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:105 +#, c-format +msgid "" +"Usage: kdb5_ldap_util [-D user_dn [-w passwd]] [-H ldapuri]\n" +"\tcmd [cmd_options]\n" +"create [-subtrees subtree_dn_list] [-sscope search_scope] [-" +"containerref container_reference_dn]\n" +"\t\t[-m|-P password|-sf stashfilename] [-k mkeytype] [-kv mkeyVNO] [-s]\n" +"\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n" +"\t\t[ticket_flags] [-r realm]\n" +"modify [-subtrees subtree_dn_list] [-sscope search_scope] [-" +"containerref container_reference_dn]\n" +"\t\t[-maxtktlife max_ticket_life] [-maxrenewlife max_renewable_ticket_life]\n" +"\t\t[ticket_flags] [-r realm]\n" +"view [-r realm]\n" +"destroy [-f] [-r realm]\n" +"list\n" +"stashsrvpw [-f filename] service_dn\n" +"create_policy [-r realm] [-maxtktlife max_ticket_life]\n" +"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n" +"modify_policy [-r realm] [-maxtktlife max_ticket_life]\n" +"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n" +"view_policy [-r realm] policy\n" +"destroy_policy [-r realm] [-force] policy\n" +"list_policy [-r realm]\n" +msgstr "" +"Aufruf: kdb5_ldap_util [-D Benutzer-DN [-w Passwort]] [-H LDAP-URI]\n" +"\tcmd [Befehlsoptionen]\n" +"create [-subtrees DN-Liste_Teilbäume] [-sscope Suchbereich] [-" +"containerref Container-Bezug-DN]\n" +"\t\t[-m|-P Passwort|-sf Ablagedateiname] [-k mkeytype] [-kv mkeyVNO] [-s]\n" +"\t\t[-maxtktlife maximale_Ticketlebensdauer]\n" +"\t\t[-maxrenewlife maximale_Dauer_bis_zum_Erneuern_des_Tickets]\n" +"\t\t[Ticket_Flags] [-r Realm]\n" +"modify [-subtrees DN-Liste_Teilbäume] [-sscope Suchbereich] [-" +"containerref Container-Bezug-DN]\n" +"\t\t[-maxtktlife maximale_Ticketlebensdauer]\n" +"\t\t[-maxrenewlife maximale_Dauer_bis_zum_Erneuern_des_Tickets]\n" +"\t\t[Ticket_Flags] [-r Realm]\n" +"view [-r Realm]\n" +"destroy [-f] [-r Realm]\n" +"list\n" +"stashsrvpw [-f Dateiname] Dienst-DN\n" +"create_policy [-r Realm] [-maxtktlife maximale_Ticketlebensdauer]\n" +"\t\t[-maxrenewlife maximale_Dauer_bis_zum_Erneuern_des_Tickets]\n" +"\t\t[Ticket_Flags] Richtlinie\n" +"modify_policy [-r Realm] [-maxtktlife maximale_Ticketlebensdauer]\n" +"\t\t[-maxrenewlife maximale_Dauer_bis_zum_Erneuern_des_Tickets]\n" +"\t\t[Ticket_Flags] Richtlinie\n" +"view_policy [-r Realm] Richtlinie\n" +"destroy_policy [-r Realm] [-force] Richtlinie\n" +"list_policy [-r Realm]\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:325 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:333 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:341 +msgid "while reading ldap parameters" +msgstr "beim Lesen der LDAP-Parameter" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:439 +msgid "while initializing error handling" +msgstr "beim Initialisieren der Fehlerbehandlung" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:447 +msgid "while initializing ldap handle" +msgstr "beim Initialisieren des LDAP-Identifikators" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:461 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:470 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:483 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:525 +msgid "while retrieving ldap configuration" +msgstr "beim Abfragen der LDAP-Konfiguration" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:500 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:507 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:516 +msgid "while initializing server list" +msgstr "beim Initialisieren der Serverliste" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:547 +msgid "while setting up lib handle" +msgstr "ein Einrichten der BibliotheksIdentifikators" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:556 +msgid "while reading ldap configuration" +msgstr "beim Lesen der LDAP-Konfiguration" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:68 +msgid "Unable to read Kerberos container" +msgstr "Kerberos-Container kann nicht gelesen werden" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:74 +msgid "Unable to read Realm" +msgstr "Realm kann nicht gelesen werden" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:215 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c:73 +msgid "Error processing LDAP DB params:" +msgstr "Fehler beim Verarbeiten der LDAP-Datenbankparameter:" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:222 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c:80 +msgid "Error reading LDAP server params:" +msgstr "Fehler beim Lesen der LDAP-Server-Parameters:" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:64 +msgid "LDAP bind dn value missing" +msgstr "LDAP-Bindungs-DN-Wert fehlt" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:69 +msgid "LDAP bind password value missing" +msgstr "LDAP-Bindungs-Passwortwert fehlt" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:77 +msgid "Error reading password from stash: " +msgstr "Fehler beim Lesen des Passworts aus der Ablage: " + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:85 +msgid "Service password length is zero" +msgstr "Länge des Dienstpassworts ist Null" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:145 +#, c-format +msgid "Cannot bind to LDAP server '%s' with SASL mechanism '%s': %s" +msgstr "" +"mit LDAP-Server »%s« kann keine Verbindung mit SASL-Mechanismus »%s« " +"hergestellt werden: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:158 +#, c-format +msgid "Cannot bind to LDAP server '%s' as '%s': %s" +msgstr "" +"mit LDAP-Server »%s« kann keine Verbindung als »%s« hergestellt werden: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:183 +#, c-format +msgid "Cannot create LDAP handle for '%s': %s" +msgstr "LDAP-Identifikator für »%s« kann nicht erstellt werden: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c:131 +msgid "could not complete roll-back, error deleting Kerberos Container" +msgstr "" +"Zurücksetzen kann nicht abgeschlossen werden, Fehler beim Löschen des " +"Kerberos-Containers" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c:56 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c:67 +msgid "Error reading kerberos container location from krb5.conf" +msgstr "" +"Fehler beim Lesen des Kerberos-Container-Speicherorts aus der »krb5.conf«." + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c:75 +msgid "Kerberos container location not specified" +msgstr "Kerberos-Container-Speicherort nicht angegeben" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:55 +#, c-format +msgid "Error reading '%s' attribute: %s" +msgstr "Fehler beim Lesen des Attributs »%s«: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:218 +msgid "KDB module requires -update argument" +msgstr "KDB-Modul benötigt Argument »-update«" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:224 +#, c-format +msgid "'%s' value missing" +msgstr "Wert »%s« fehlt" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:282 +#, c-format +msgid "unknown option '%s'" +msgstr "unbekannte Option »%s«" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:342 +msgid "Minimum connections required per server is 2" +msgstr "Die benötigte Mindestanzahl von Verbindungen pro Server ist zwei" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c:159 +msgid "Default realm not set" +msgstr "Standard-Realm nicht gesetzt" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c:262 +msgid "DN information missing" +msgstr "DN-Information fehlt" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:108 +msgid "Principal does not belong to realm" +msgstr "Principal gehört nicht zum Realm" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:278 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:287 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:295 +#, c-format +msgid "%s option not supported" +msgstr "Option %s wird nicht unterstützt" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:302 +#, c-format +msgid "unknown option: %s" +msgstr "unbekannte Option: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:309 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:316 +#, c-format +msgid "%s option value missing" +msgstr "Wert der Option %s fehlt" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:542 +msgid "Principal does not belong to the default realm" +msgstr "Principal gehört nicht zum Standard-Realm" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:610 +#, c-format +msgid "" +"operation can not continue, more than one entry with principal name \"%s\" " +"found" +msgstr "" +"Die Aktion kann nicht fortfahren, da mehr als ein Principal namens »%s« " +"gefunden wurde." + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:673 +#, c-format +msgid "'%s' not found: " +msgstr "»%s« nicht gefunden: " + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:751 +msgid "DN is out of the realm subtree" +msgstr "DN liegt außerhalb ders Teilbaums des Realms" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:807 +#, c-format +msgid "ldap object is already kerberized" +msgstr "LDAP-Objekt ist bereits an Kerberos angepasst" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:827 +#, c-format +msgid "" +"link information can not be set/updated as the kerberos principal belongs to " +"an ldap object" +msgstr "" +"Verweisinformation kann nicht eingerichtet/aktualisiert werden, da der " +"Kerberos-Principal zu einem LDAP-Objekt gehört." + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:842 +#, c-format +msgid "Failed getting object references" +msgstr "Holen von Objektbezügen fehlgeschlagen" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:849 +#, c-format +msgid "kerberos principal is already linked to a ldap object" +msgstr "Kerberos-Principal ist bereits mit einem LDAP-Objekt verknüpft" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1167 +msgid "ticket policy object value: " +msgstr "Wert des Ticket-Richtlinienobjekts: " + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1215 +#, c-format +msgid "Principal delete failed (trying to replace entry): %s" +msgstr "" +"Löschen des Principals fehlgeschlagen (es wird versucht, den Eintrag zu " +"ersetzen): %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1225 +#, c-format +msgid "Principal add failed: %s" +msgstr "Hinzufügen des Principals fehlgeschlagen: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1263 +#, c-format +msgid "User modification failed: %s" +msgstr "Änderung des Benutzers fehlgeschlagen: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1336 +msgid "Error reading ticket policy. " +msgstr "Fehler beim Lesen der Ticket-Richtlinie" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1402 +#, c-format +msgid "unable to decode stored principal key data (%s)" +msgstr "" +"Die gespeicherten Schlüsseldaten des Principals (%s) konnten nicht " +"dekodiert werden." + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:223 +msgid "Realm information not available" +msgstr "Realm-Information nicht verfügbar" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:294 +msgid "Error reading ticket policy: " +msgstr "Fehler beim Lesen der Ticket-Richtlinie:" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:307 +#, c-format +msgid "Realm Delete FAILED: %s" +msgstr "Löschen des Realms FEHLGESCHLAGEN: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:387 +msgid "subtree value: " +msgstr "Wert des Teilbaums: " + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:404 +msgid "container reference value: " +msgstr "Wert des Container-Bezugs: " + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:487 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:550 +msgid "Kerberos Container information is missing" +msgstr "Kerberos-Container-Information fehlt" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:499 +msgid "Invalid Kerberos container DN" +msgstr "ungültiger Kerberos-Container-DN" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:515 +#, c-format +msgid "Kerberos Container create FAILED: %s" +msgstr "Erstellen des Kerberos-Containers FEHLGESCHLAGEN: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:558 +#, c-format +msgid "Kerberos Container delete FAILED: %s" +msgstr "Löschen des Kerberos-Containers FEHLGESCHLAGEN: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:634 +msgid "realm object value: " +msgstr "Wert des Realm-Objekts: " + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:48 +msgid "Not a hexadecimal password" +msgstr "kein hexadezimales Passwort" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:55 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:66 +msgid "Password corrupt" +msgstr "Passwort beschädigt" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:93 +#, c-format +msgid "Cannot open LDAP password file '%s': %s" +msgstr "LDAP-Passwortdatei »%s« kann nicht geöffnet werden: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:123 +#, c-format +msgid "Bind DN entry '%s' missing in LDAP password file '%s'" +msgstr "Bind-DN-Eintrag »%s« fehlt in der LDAP-Passwortdatei »%s«" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:56 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:132 +msgid "Ticket Policy Name missing" +msgstr "Ticket-Richtlinienname fehlt" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:144 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:221 +msgid "ticket policy object: " +msgstr "Ticket-Richtlinienobjekt: " + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:209 +msgid "Ticket Policy Object information missing" +msgstr "Ticket-Richtlinienobjekt-Information fehlt" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:300 +msgid "Ticket Policy Object DN missing" +msgstr "DN des Ticket-Richtlinienobjekts fehlt" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:327 +msgid "Delete Failed: One or more Principals associated with the Ticket Policy" +msgstr "" +"Löschen fehlgeschlagen: Ein oder mehrere Principals gehören zur Ticket-" +"Richtlinie." + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:435 +msgid "Error reading container object: " +msgstr "Fehler beim Lesen des Container-Objekts: " + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_nss.c:667 +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:652 +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:4153 +msgid "Pass phrase for" +msgstr "Passphrase für" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1081 +#, c-format +msgid "Cannot create cert chain: %s" +msgstr "Zertifikatskette kann nicht erstellt werden: %s" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1408 +msgid "Invalid pkinit packet: octet string expected" +msgstr "ungültiges Pkinit-Paket: Achtbit-Zeichenkette erwartet" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1427 +msgid "wrong oid\n" +msgstr "falsche OID\n" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:5994 +#, c-format +msgid "unknown code 0x%x" +msgstr "unbekannter Code 0x%x" + +#: ../../src/plugins/preauth/pkinit/pkinit_identity.c:424 +#, c-format +msgid "Unsupported type while processing '%s'\n" +msgstr "nicht unterstützter Typ bei der Verarbeitung von »%s«\n" + +#: ../../src/plugins/preauth/pkinit/pkinit_identity.c:465 +msgid "Internal error parsing X509_user_identity\n" +msgstr "interner Fehler beim Auswerten von »X509_user_identity«\n" + +#: ../../src/plugins/preauth/pkinit/pkinit_identity.c:560 +msgid "No user identity options specified" +msgstr "keine Optionen der Nutzeridentität angegeben" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:414 +msgid "Pkinit request not signed, but client not anonymous." +msgstr "Pkinit-Anfrage nicht signiert, Client ist jedoch nicht anonym" + +# DH = Diffie-Hellman +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:447 +msgid "Anonymous pkinit without DH public value not supported." +msgstr "Anonymes Pkinit wird nicht ohne öffentlichen DH-Wert unterstützt." + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1147 +#, c-format +msgid "No pkinit_identity supplied for realm %s" +msgstr "Für Realm %s wird keine »pkinit_identity« bereitgestellt." + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1158 +#, c-format +msgid "No pkinit_anchors supplied for realm %s" +msgstr "Für Realm %s werden keine »pkinit_anchors« bereitgestellt." + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1346 +msgid "No realms configured correctly for pkinit support" +msgstr "Für Pkinit-Unterstützung wurden keine Realms korrekt konfiguriert." + +#: ../../src/slave/kprop.c:85 +#, c-format +msgid "" +"\n" +"Usage: %s [-r realm] [-f file] [-d] [-P port] [-s srvtab] slave_host\n" +"\n" +msgstr "" +"\n" +"Aufruf: %s [-r Realm] [-f Datei] [-d] [-P Port] [-s Dienstschlüsseltabelle] " +"untergeordneter_Rechner\n" +"\n" + +#: ../../src/slave/kprop.c:114 +#, c-format +msgid "Database propagation to %s: SUCCEEDED\n" +msgstr "Datenbankverbreitung auf %s: ERFOLGREICH\n" + +#: ../../src/slave/kprop.c:187 +msgid "while setting client principal name" +msgstr "beim Setzen des Client-Principal-Namens" + +#: ../../src/slave/kprop.c:194 ../../src/slave/kprop.c:209 +msgid "while setting client principal realm" +msgstr "beim Setzen des Client-Principal-Realms" + +#: ../../src/slave/kprop.c:217 +#, c-format +msgid "while opening credential cache %s" +msgstr "beim Öffnen des Anmeldedatenzwischenspeichers %s" + +#: ../../src/slave/kprop.c:233 +msgid "while setting server principal name" +msgstr "beim Setzen des Server-Principal-Namens" + +#: ../../src/slave/kprop.c:255 +msgid "while resolving keytab" +msgstr "beim Ermitteln der Schlüsseltabelle" + +#: ../../src/slave/kprop.c:264 +msgid "while getting initial credentials\n" +msgstr "beim Holen der Anfangsanmeldedaten\n" + +#: ../../src/slave/kprop.c:301 +msgid "while creating socket" +msgstr "beim Erstellen eines Sockets" + +#: ../../src/slave/kprop.c:317 +msgid "while converting server address" +msgstr "beim Umwandeln der Server-Adresse" + +#: ../../src/slave/kprop.c:327 +msgid "while connecting to server" +msgstr "beim Verbinden mit dem Server" + +#: ../../src/slave/kprop.c:334 ../../src/slave/kpropd.c:1215 +msgid "while getting local socket address" +msgstr "beim Holen der lokalen Socket-Adresse" + +#: ../../src/slave/kprop.c:339 +msgid "while converting local address" +msgstr "beim Umwandeln der lokalen Socket-Adresse" + +#: ../../src/slave/kprop.c:362 +msgid "in krb5_auth_con_setaddrs" +msgstr "in »krb5_auth_con_setaddrs«" + +#: ../../src/slave/kprop.c:370 +msgid "while authenticating to server" +msgstr "beim Authentifizieren am Server" + +#: ../../src/slave/kprop.c:374 ../../src/slave/kprop.c:573 +#: ../../src/slave/kpropd.c:1521 +#, c-format +msgid "Generic remote error: %s\n" +msgstr "allgemeiner ferner Fehler: %s\n" + +#: ../../src/slave/kprop.c:380 ../../src/slave/kprop.c:579 +msgid "signalled from server" +msgstr "signalisiert vom Server" + +#: ../../src/slave/kprop.c:382 ../../src/slave/kprop.c:581 +#, c-format +msgid "Error text from server: %s\n" +msgstr "Fehlermeldung vom Server: %s\n" + +#: ../../src/slave/kprop.c:410 +#, c-format +msgid "allocating database file name '%s'" +msgstr "Datenbankdateiname »%s« wird reserviert" + +#: ../../src/slave/kprop.c:416 +#, c-format +msgid "while trying to open %s" +msgstr "beim Versuch, %s zu öffnen" + +#: ../../src/slave/kprop.c:423 +msgid "database locked" +msgstr "Datenbank gesperrt" + +#: ../../src/slave/kprop.c:426 ../../src/slave/kpropd.c:525 +#, c-format +msgid "while trying to lock '%s'" +msgstr "beim Versuch, »%s« zu sperren" + +#: ../../src/slave/kprop.c:430 ../../src/slave/kprop.c:438 +#, c-format +msgid "while trying to stat %s" +msgstr "beim Versuch, »stat« für %s auszuführen" + +#: ../../src/slave/kprop.c:434 +msgid "while trying to malloc data_ok_fn" +msgstr "beim Versuch, Speicher für »data_ok_fn« zu reservieren" + +#: ../../src/slave/kprop.c:443 +#, c-format +msgid "'%s' more recent than '%s'." +msgstr "»%s« ist aktueller als »%s«." + +#: ../../src/slave/kprop.c:459 +#, c-format +msgid "while unlocking database '%s'" +msgstr "beim Entsperren von Datenbank »%s«" + +#: ../../src/slave/kprop.c:492 ../../src/slave/kprop.c:493 +msgid "while encoding database size" +msgstr "beim Aufbereiten der Datenbankgröße" + +#: ../../src/slave/kprop.c:501 +msgid "while sending database size" +msgstr "beim Senden der Datenbankgröße" + +#: ../../src/slave/kprop.c:511 +msgid "while allocating i_vector" +msgstr "beim Reservieren von »i_vector«" + +#: ../../src/slave/kprop.c:534 +#, c-format +msgid "while sending database block starting at %d" +msgstr "beim Senden des Datenbankblocks, der bei %d beginnt" + +#: ../../src/slave/kprop.c:544 +msgid "Premature EOF found for database file!" +msgstr "vorzeitiges EOF für Datenbankdatei gefunden!" + +#: ../../src/slave/kprop.c:557 +msgid "while reading response from server" +msgstr "beim Lesen der Antwort vom Servers" + +#: ../../src/slave/kprop.c:568 +msgid "while decoding error response from server" +msgstr "beim Aufschlüsseln der Fehlerantwort vom Server" + +#: ../../src/slave/kprop.c:599 +#, c-format +msgid "Kpropd sent database size %d, expecting %d" +msgstr "Kpropd sendet Datenbankgröße %d, erwartet wurde %d" + +#: ../../src/slave/kprop.c:643 +msgid "while allocating filename for update_last_prop_file" +msgstr "beim Reservieren des Dateinamens für »update_last_prop_file«" + +#: ../../src/slave/kprop.c:648 +#, c-format +msgid "while creating 'last_prop' file, '%s'" +msgstr "beim Erstellen der Datei »last_prop«, »%s«" + +#: ../../src/slave/kpropd.c:170 +#, c-format +msgid "" +"\n" +"Usage: %s [-r realm] [-s srvtab] [-dS] [-f slave_file]\n" +msgstr "" +"\n" +"Aufruf: %s [-r Realm] [-s Dienstschlüsseltabelle] [-dS] [-f " +"untergeordnete_Datei]\n" + +#: ../../src/slave/kpropd.c:172 +#, c-format +msgid "\t[-F kerberos_db_file ] [-p kdb5_util_pathname]\n" +msgstr "\t[-F Kerberos-Datenbankdatei ] [-p KDB5-Hilfswerkzeugpfadname]\n" + +#: ../../src/slave/kpropd.c:173 +#, c-format +msgid "\t[-x db_args]* [-P port] [-a acl_file]\n" +msgstr "\t[-x Datenbankargumente]* [-P Port] [-a ACL-Datei]\n" + +#: ../../src/slave/kpropd.c:174 +#, c-format +msgid "\t[-A admin_server]\n" +msgstr "\t[-A Serveradministrator]\n" + +#: ../../src/slave/kpropd.c:215 +#, c-format +msgid "Killing fullprop child (%d)\n" +msgstr "Beenden des Fullprop-Kindprozesses (%d) wird erzwungen\n" + +#: ../../src/slave/kpropd.c:244 +msgid "while checking if stdin is a socket" +msgstr "beim Prüfen, ob die Standardeingabe ein Socket ist" + +#: ../../src/slave/kpropd.c:262 +#, c-format +msgid "ready\n" +msgstr "bereit\n" + +#: ../../src/slave/kpropd.c:272 +#, c-format +msgid "Could not open /dev/null: %s" +msgstr "/dev/null konnte nicht geöffnet werden: %s" + +#: ../../src/slave/kpropd.c:279 +#, c-format +msgid "Could not dup the inetd socket: %s" +msgstr "Das Inetd-Socket konnte nicht dupliziert werden: %s" + +#: ../../src/slave/kpropd.c:314 ../../src/slave/kpropd.c:327 +msgid "do_iprop failed.\n" +msgstr "»do_iprop« fehlgeschlagen\n" + +#: ../../src/slave/kpropd.c:366 +#, c-format +msgid "getaddrinfo: %s\n" +msgstr "getaddrinfo: %s\n" + +#: ../../src/slave/kpropd.c:372 +msgid "while obtaining socket" +msgstr "beim Erlangen des Sockets" + +#: ../../src/slave/kpropd.c:378 +msgid "while setting SO_REUSEADDR option" +msgstr "beim Setzen der Option SO_REUSEADDR" + +#: ../../src/slave/kpropd.c:386 +msgid "while unsetting IPV6_V6ONLY option" +msgstr "beim Entfernen der Option IPV6_V6ONLY" + +#: ../../src/slave/kpropd.c:391 +msgid "while binding listener socket" +msgstr "beim Anbinden an das auf Verbindung wartende Socket" + +#: ../../src/slave/kpropd.c:402 +#, c-format +msgid "waiting for a kprop connection\n" +msgstr "warten auf Kprop-Verbindung\n" + +#: ../../src/slave/kpropd.c:408 +msgid "while accepting connection" +msgstr "beim Akzeptieren der Verbindung" + +#: ../../src/slave/kpropd.c:414 +msgid "while forking" +msgstr "beim Erzeugen eines Kindprozesses" + +#: ../../src/slave/kpropd.c:429 +#, c-format +msgid "waitpid() failed to wait for doit() (%d %s)\n" +msgstr "waitpid() schlug beim Warten auf doit() fehl (%d %s)\n" + +#: ../../src/slave/kpropd.c:433 +msgid "while waiting to receive database" +msgstr "beim Warten auf den Erhalt der Datenbank" + +#: ../../src/slave/kpropd.c:437 +#, c-format +msgid "Database load process for full propagation completed.\n" +msgstr "" +"Der Datenbankladeprozess für eine vollständige Verbreitung ist " +"abgeschlossen.\n" + +#: ../../src/slave/kpropd.c:471 +#, c-format +msgid "" +"%s: Standard input does not appear to be a network socket.\n" +"\t(Not run from inetd, and missing the -S option?)\n" +msgstr "" +"%s: Bei der Standardeingabe scheint es sich nicht um ein Netzwerk-Socket zu\n" +"\thandeln (läuft nicht aus Inetd und die Option -S fehlt?).\n" + +#: ../../src/slave/kpropd.c:485 +msgid "while attempting setsockopt (SO_KEEPALIVE)" +msgstr "beim Versuch, »setsockopt« auszuführen (SO_KEEPALIVE)" + +#: ../../src/slave/kpropd.c:490 +#, c-format +msgid "Connection from %s" +msgstr "Verbindung von %s" + +#: ../../src/slave/kpropd.c:510 +#, c-format +msgid "Rejected connection from unauthorized principal %s\n" +msgstr "Zurückgewiesene Verbindung von nicht autorisiertem Principal %s\n" + +#: ../../src/slave/kpropd.c:514 +#, c-format +msgid "Rejected connection from unauthorized principal %s" +msgstr "Zurückgewiesene Verbindung von nicht authorisiertem Principal %s" + +#: ../../src/slave/kpropd.c:531 +#, c-format +msgid "while opening database file, '%s'" +msgstr "beim Öffnen der Datenbankdatei, »%s«" + +#: ../../src/slave/kpropd.c:537 +#, c-format +msgid "while renaming %s to %s" +msgstr "beim Umbenennen von %s in %s" + +#: ../../src/slave/kpropd.c:543 +#, c-format +msgid "while downgrading lock on '%s'" +msgstr "beim Downgrade der Sperre auf »%s«" + +#: ../../src/slave/kpropd.c:550 +#, c-format +msgid "while unlocking '%s'" +msgstr "beim Aufheben der Sperre »%s«" + +#: ../../src/slave/kpropd.c:562 +msgid "while sending # of received bytes" +msgstr "beim Senden n empfangener Byte" + +#: ../../src/slave/kpropd.c:568 +msgid "while trying to close database file" +msgstr "beim Versuch, die Datenbankdatei zu schließen" + +#: ../../src/slave/kpropd.c:624 +#, c-format +msgid "Incremental propagation enabled\n" +msgstr "inkrementelle Verbreitung aktiviert\n" + +#: ../../src/slave/kpropd.c:634 +msgid "Unable to get default realm" +msgstr "Standard-Realm kann nicht geholt werden" + +#: ../../src/slave/kpropd.c:647 +#, c-format +msgid "%s: unable to get kiprop host based service name for realm %s\n" +msgstr "" +"%s: Kiprop-rechnerbasierter Dienstname für Realm %s kann nicht geholt " +"werden\n" + +#: ../../src/slave/kpropd.c:658 +msgid "while trying to construct host service principal" +msgstr "beim Versuch, den Rechnerdienst-Principal zu erstellen" + +#: ../../src/slave/kpropd.c:672 +msgid "while determining local service principal name" +msgstr "beim Bestimmen des lokalen Dienst-Principal-Namens" + +#: ../../src/slave/kpropd.c:692 +#, c-format +msgid "Initializing kadm5 as client %s\n" +msgstr "Kadm5 wird als Client %s initialisiert\n" + +#: ../../src/slave/kpropd.c:706 +#, c-format +msgid "kadm5 initialization failed!\n" +msgstr "Initialisierung von Kadm5 fehlgeschlagen!\n" + +#: ../../src/slave/kpropd.c:715 +msgid "while attempting to connect to master KDC ... retrying" +msgstr "" +"beim Versuch, eine Verbindung zum Master-KDC aufzubauen … wird erneut " +"versucht" + +#: ../../src/slave/kpropd.c:719 +#, c-format +msgid "Sleeping %d seconds to re-initialize kadm5 (RPC ERROR)\n" +msgstr "" +"Um Kadm5 neu zu initialisieren, wird %d Sekunden gewartet (RPC-FEHLER).\n" + +#: ../../src/slave/kpropd.c:735 +#, c-format +msgid "while initializing %s interface, retrying" +msgstr "beim Initialisieren der Schnittstelle %s, wird erneut versucht" + +#: ../../src/slave/kpropd.c:739 +#, c-format +msgid "Sleeping %d seconds to re-initialize kadm5 (krb5kdc not running?)\n" +msgstr "" +"Um Kadm5 neu zu initialisieren, wird %d Sekunden gewartet (läuft Krb5kdc " +"nicht?).\n" + +#: ../../src/slave/kpropd.c:749 +#, c-format +msgid "kadm5 initialization succeeded\n" +msgstr "Initialisieren von Kadm5 erfolgreich\n" + +#: ../../src/slave/kpropd.c:771 +msgid "reading update log header" +msgstr "Aktualisierungsprotokollkopfzeilen werden gelesen" + +#: ../../src/slave/kpropd.c:782 +#, c-format +msgid "Calling iprop_get_updates_1 (sno=%u sec=%u usec=%u)\n" +msgstr "»iprop_get_updates_1()« wird aufgerufen (sno=%u sec=%u usec=%u)\n" + +#: ../../src/slave/kpropd.c:792 +msgid "iprop_get_updates call failed" +msgstr "Aufruf von »iprop_get_updates« fehlgeschlagen" + +#: ../../src/slave/kpropd.c:798 +#, c-format +msgid "Reinitializing iprop because get updates failed\n" +msgstr "" +"Iprop wird neu initialisiert, da Aktualisierungen fehlgeschlagen sind\n" + +#: ../../src/slave/kpropd.c:819 +#, c-format +msgid "Still waiting for full resync\n" +msgstr "" +"Es wird immer noch auf das vollständige erneute Synchronisieren gewartet.\n" + +#: ../../src/slave/kpropd.c:824 +#, c-format +msgid "Full resync needed\n" +msgstr "erneutes vollständiges Synchronisieren erforderlich\n" + +#: ../../src/slave/kpropd.c:825 +msgid "kpropd: Full resync needed." +msgstr "Kpropd: erneutes vollständiges Synchronisieren erforderlich" + +#: ../../src/slave/kpropd.c:830 +msgid "iprop_full_resync call failed" +msgstr "Aufruf von »iprop_full_resync« fehlgeschlagen" + +#: ../../src/slave/kpropd.c:841 +#, c-format +msgid "Full resync request granted\n" +msgstr "Anfrage nach vollständigem erneuten Synchronisieren genehmigt\n" + +#: ../../src/slave/kpropd.c:842 +msgid "Full resync request granted." +msgstr "Anfrage nach vollständigem erneuten Synchronisieren genehmigt" + +# FIXME s/backoff/back-off/ +#: ../../src/slave/kpropd.c:851 +#, c-format +msgid "Exponential backoff\n" +msgstr "exponentieller Wartezyklus\n" + +#: ../../src/slave/kpropd.c:857 +#, c-format +msgid "Full resync permission denied\n" +msgstr "vollständiges erneutes Synchronisieren nicht gestattet\n" + +#: ../../src/slave/kpropd.c:858 +msgid "Full resync, permission denied." +msgstr "vollständiges erneutes Synchronisieren, nicht gestattet" + +#: ../../src/slave/kpropd.c:863 +#, c-format +msgid "Full resync error from master\n" +msgstr "Fehler beim vollständigen erneuten Synchronisieren vom Master\n" + +#: ../../src/slave/kpropd.c:864 +msgid " Full resync, error returned from master KDC." +msgstr "" +"vollständiges erneutes Synchronisieren, das Master-KDC gab einen Fehler " +"zurück" + +#: ../../src/slave/kpropd.c:872 +#, c-format +msgid "Full resync invalid result from master\n" +msgstr "" +"Beim vollständigen erneuten Synchronisieren gab der Master ein ungültiges " +"Ergebnis zurück.\n" + +#: ../../src/slave/kpropd.c:874 +msgid "Full resync, invalid return from master KDC." +msgstr "" +"vollständiges erneutes Synchronisieren, ungültiger Rückgabewert vom Master-" +"KDC" + +#: ../../src/slave/kpropd.c:890 +#, c-format +msgid "Got incremental updates (sno=%u sec=%u usec=%u)\n" +msgstr "" +"inkrementelle Aktualisierungen erhalten (sno=%u sec=%u usec=%u)\n" + +#: ../../src/slave/kpropd.c:902 +#, c-format +msgid "ulog_replay failed (%s), updates not registered\n" +msgstr "" +"»ulog_replay« fehlgeschlagen (%s), Aktualisierungen nicht registriert\n" + +#: ../../src/slave/kpropd.c:905 +#, c-format +msgid "ulog_replay failed (%s), updates not registered." +msgstr "»ulog_replay« fehlgeschlagen (%s), Aktualisierungen nicht registriert" + +#: ../../src/slave/kpropd.c:914 +#, c-format +msgid "Incremental updates: %d updates / %lu us" +msgstr "inkrementelle Aktualisierungen: %d Aktualisierungen / %lu us" + +#: ../../src/slave/kpropd.c:917 +#, c-format +msgid "Incremental updates: %d updates / %lu us\n" +msgstr "inkrementelle Aktualisierungen: %d Aktualisierungen / %lu us\n" + +#: ../../src/slave/kpropd.c:925 +#, c-format +msgid "get_updates permission denied\n" +msgstr "Zugriff bei »get_updates« verweigert\n" + +#: ../../src/slave/kpropd.c:926 +msgid "get_updates, permission denied." +msgstr "»get_updates«, Zugriff verweigert" + +#: ../../src/slave/kpropd.c:931 +#, c-format +msgid "get_updates error from master\n" +msgstr "»get_updates«-Fehler vom Master\n" + +#: ../../src/slave/kpropd.c:932 +msgid "get_updates, error returned from master KDC." +msgstr "Vom Master-KDC wurde ein »get_updates«-Fehler zurückgegeben." + +# FIXME s/backoff/back-off/ +#: ../../src/slave/kpropd.c:940 +#, c-format +msgid "get_updates master busy; backoff\n" +msgstr "»get_updates«-Master ausgelastet; hält sich zurück\n" + +#: ../../src/slave/kpropd.c:949 +#, c-format +msgid "KDC is synchronized with master.\n" +msgstr "KDC wurde mit dem Master synchronisiert.\n" + +#: ../../src/slave/kpropd.c:957 +#, c-format +msgid "get_updates invalid result from master\n" +msgstr "ungültiges »get_updates«-Ergebnis vom Master\n" + +#: ../../src/slave/kpropd.c:958 +msgid "get_updates, invalid return from master KDC." +msgstr "»get_updates«, ungültiger Rückgabewert vom Master-KDC" + +# FIXME s/backoff/back-off/ +#: ../../src/slave/kpropd.c:973 +#, c-format +msgid "Busy signal received from master, backoff for %d secs\n" +msgstr "" +"Vom Master wurde ein Signal empfangen, dass er ausgelastet ist, " +"Zurückhaltung für %d Sekunden\n" + +#: ../../src/slave/kpropd.c:980 +#, c-format +msgid "Waiting for %d seconds before checking for updates again\n" +msgstr "" +"vor der erneuten Prufung auf Aktualisierungen wird %d Sekunden gewartet\n" + +#: ../../src/slave/kpropd.c:991 +#, c-format +msgid "ERROR returned by master, bailing\n" +msgstr "FEHLER vom Master zurückgegeben, Ausstieg\n" + +#: ../../src/slave/kpropd.c:992 +msgid "ERROR returned by master KDC, bailing.\n" +msgstr "FEHLER vom Master-KDC zurückgegeben, Ausstieg\n" + +#: ../../src/slave/kpropd.c:1134 +msgid "copying db args" +msgstr "Datenbankargumente werden kopiert" + +#: ../../src/slave/kpropd.c:1161 +msgid "while trying to construct my service name" +msgstr "beim Versuch, meinen Dienstnamen zu erstellen" + +#: ../../src/slave/kpropd.c:1167 +msgid "while constructing my service realm" +msgstr "beim Erstellen meines Dienst-Realms" + +#: ../../src/slave/kpropd.c:1175 +msgid "while allocating filename for temp file" +msgstr "beim Reservieren des Dateinamens für die temporäre Datei" + +#: ../../src/slave/kpropd.c:1181 +msgid "while initializing" +msgstr "bei der Initialisierung" + +#: ../../src/slave/kpropd.c:1189 +msgid "Unable to map log!\n" +msgstr "Protokoll kann nicht abgebildet werden!\n" + +#: ../../src/slave/kpropd.c:1235 +#, c-format +msgid "Error in krb5_auth_con_ini: %s" +msgstr "Fehler in »krb5_auth_con_ini«: %s" + +#: ../../src/slave/kpropd.c:1243 +#, c-format +msgid "Error in krb5_auth_con_setflags: %s" +msgstr "Fehler in »krb5_auth_con_setflags«: %s" + +#: ../../src/slave/kpropd.c:1251 +#, c-format +msgid "Error in krb5_auth_con_setaddrs: %s" +msgstr "Fehler in »krb5_auth_con_setaddrs«: %s" + +#: ../../src/slave/kpropd.c:1259 +#, c-format +msgid "Error in krb5_kt_resolve: %s" +msgstr "Fehler in »krb5_kt_resolve«: %s" + +#: ../../src/slave/kpropd.c:1268 +#, c-format +msgid "Error in krb5_recvauth: %s" +msgstr "Fehler in »krb5_recvauth«: %s" + +#: ../../src/slave/kpropd.c:1275 +#, c-format +msgid "Error in krb5_copy_prinicpal: %s" +msgstr "Fehler in »krb5_copy_prinicpal«: %s" + +#: ../../src/slave/kpropd.c:1291 +msgid "while unparsing ticket etype" +msgstr "beim Rückgängigmachen der Auswertung des »etype«s des Tickets" + +#: ../../src/slave/kpropd.c:1295 +#, c-format +msgid "authenticated client: %s (etype == %s)\n" +msgstr "Authentifizierter Client: %s (etype == %s)\n" + +#: ../../src/slave/kpropd.c:1374 +msgid "while reading size of database from client" +msgstr "beim Lesen der Datenbankgröße vom Client" + +#: ../../src/slave/kpropd.c:1384 +msgid "while decoding database size from client" +msgstr "beim Dekodieren der Datenbankgröße vom Client" + +#: ../../src/slave/kpropd.c:1397 +msgid "while initializing i_vector" +msgstr "beim Initialisieren von »i_vector«" + +#: ../../src/slave/kpropd.c:1402 +#, c-format +msgid "Full propagation transfer started.\n" +msgstr "vollständige Verbreitungsübertragung gestartet\n" + +#: ../../src/slave/kpropd.c:1455 +#, c-format +msgid "Full propagation transfer finished.\n" +msgstr "vollständige Verbreitungsübertragung beendet\n" + +#: ../../src/slave/kpropd.c:1516 +msgid "while decoding error packet from client" +msgstr "beim Dekodieren des Fehlerpakets vom Client" + +#: ../../src/slave/kpropd.c:1525 +msgid "signaled from server" +msgstr "signalisiert vom Server" + +#: ../../src/slave/kpropd.c:1527 +#, c-format +msgid "Error text from client: %s\n" +msgstr "Fehlermeldung vom Client: %s\n" + +#: ../../src/slave/kpropd.c:1576 +#, c-format +msgid "while trying to fork %s" +msgstr "beim Versuch, einen Kindprozess von %s zu erzeugen" + +#: ../../src/slave/kpropd.c:1580 +#, c-format +msgid "while trying to exec %s" +msgstr "beim Versuch, %s auszuführen" + +#: ../../src/slave/kpropd.c:1587 +#, c-format +msgid "while waiting for %s" +msgstr "beim Warten auf %s" + +#: ../../src/slave/kpropd.c:1593 +#, c-format +msgid "%s load terminated" +msgstr "Laden von %s beendet" + +#: ../../src/slave/kpropd.c:1599 +#, c-format +msgid "%s returned a bad exit status (%d)" +msgstr "%s gab einen falschen Exit-Status (%d) zurück" + +#: ../../src/slave/kproplog.c:27 +#, c-format +msgid "" +"\n" +"Usage: %s [-h] [-v] [-v] [-e num]\n" +"\t%s -R\n" +"\n" +msgstr "" +"\n" +"Aufruf: %s [-h] [-v] [-v] [-e Zahl]\n" +"\t%s -R\n" +"\n" + +#: ../../src/slave/kproplog.c:129 +#, c-format +msgid "" +"\n" +"Couldn't allocate memory" +msgstr "" +"\n" +"Speicher konnte nicht reserviert werden" + +#: ../../src/slave/kproplog.c:223 +#, c-format +msgid "\t\tAttribute flags\n" +msgstr "\t\tAttributschalter\n" + +#: ../../src/slave/kproplog.c:228 +#, c-format +msgid "\t\tMaximum ticket life\n" +msgstr "\t\tmaximale Ticketlebensdauer\n" + +#: ../../src/slave/kproplog.c:233 +#, c-format +msgid "\t\tMaximum renewable life\n" +msgstr "\t\tmaximale verlängerbare Lebensdauer\n" + +#: ../../src/slave/kproplog.c:238 +#, c-format +msgid "\t\tPrincipal expiration\n" +msgstr "\t\tAblauf des Principals\n" + +#: ../../src/slave/kproplog.c:243 +#, c-format +msgid "\t\tPassword expiration\n" +msgstr "\t\tAblauf des Passworts\n" + +#: ../../src/slave/kproplog.c:248 +#, c-format +msgid "\t\tLast successful auth\n" +msgstr "\t\tletzte erfolgreiche Authentifizierung\n" + +#: ../../src/slave/kproplog.c:253 +#, c-format +msgid "\t\tLast failed auth\n" +msgstr "\t\tletzte fehlgeschlagene Authentifizierung\n" + +#: ../../src/slave/kproplog.c:258 +#, c-format +msgid "\t\tFailed passwd attempt\n" +msgstr "\t\tfehlgeschlagener Passwortversuch\n" + +#: ../../src/slave/kproplog.c:263 +#, c-format +msgid "\t\tPrincipal\n" +msgstr "\t\tPrincipal\n" + +#: ../../src/slave/kproplog.c:268 +#, c-format +msgid "\t\tKey data\n" +msgstr "\t\tSchlüsseldaten\n" + +#: ../../src/slave/kproplog.c:275 +#, c-format +msgid "\t\tTL data\n" +msgstr "\t\tTL-Daten\n" + +#: ../../src/slave/kproplog.c:282 +#, c-format +msgid "\t\tLength\n" +msgstr "\t\tLänge\n" + +#: ../../src/slave/kproplog.c:287 +#, c-format +msgid "\t\tPassword last changed\n" +msgstr "\t\tletzte Passwortänderung\n" + +#: ../../src/slave/kproplog.c:292 +#, c-format +msgid "\t\tModifying principal\n" +msgstr "\t\ttPrincipal wird geändert\n" + +#: ../../src/slave/kproplog.c:297 +#, c-format +msgid "\t\tModification time\n" +msgstr "\t\tÄnderungszeit\n" + +#: ../../src/slave/kproplog.c:302 +#, c-format +msgid "\t\tModified where\n" +msgstr "\t\tGeändert wobei\n" + +#: ../../src/slave/kproplog.c:307 +#, c-format +msgid "\t\tPassword policy\n" +msgstr "\t\tPasswortrichtlinie\n" + +#: ../../src/slave/kproplog.c:312 +#, c-format +msgid "\t\tPassword policy switch\n" +msgstr "\t\tPasswortrichtlinienumschalter\n" + +#: ../../src/slave/kproplog.c:317 +#, c-format +msgid "\t\tPassword history KVNO\n" +msgstr "\t\tPasswortchronik KVNO\n" + +#: ../../src/slave/kproplog.c:322 +#, c-format +msgid "\t\tPassword history\n" +msgstr "\t\tPasswortchronik\n" + +#: ../../src/slave/kproplog.c:356 +#, c-format +msgid "" +"Corrupt update entry\n" +"\n" +msgstr "" +"beschädigter Aktualisierungseintrag\n" +"\n" + +#: ../../src/slave/kproplog.c:364 +#, c-format +msgid "" +"Entry data decode failure\n" +"\n" +msgstr "" +"Dekodieren der eingetragenen Daten fehlgeschlagen\n" +"\n" + +#: ../../src/slave/kproplog.c:369 +#, c-format +msgid "Update Entry\n" +msgstr "Aktualisierungseintrag\n" + +#: ../../src/slave/kproplog.c:371 +#, c-format +msgid "\tUpdate serial # : %u\n" +msgstr "\tAktualisierung der Seriennummer: %u\n" + +#: ../../src/slave/kproplog.c:373 +#, c-format +msgid "\tUpdate operation : " +msgstr "\tAktualisierungsaktion: " + +#: ../../src/slave/kproplog.c:375 +#, c-format +msgid "Delete\n" +msgstr "Löschen\n" + +#: ../../src/slave/kproplog.c:377 +#, c-format +msgid "Add\n" +msgstr "Hinzufügen\n" + +#: ../../src/slave/kproplog.c:381 +#, c-format +msgid "" +"Could not allocate principal name\n" +"\n" +msgstr "" +"Der Principal-Name konnte nicht reserviert werden.\n" +"\n" + +#: ../../src/slave/kproplog.c:387 +#, c-format +msgid "\tUpdate principal : %s\n" +msgstr "\tAktualisierung des Principals: %s\n" + +#: ../../src/slave/kproplog.c:389 +#, c-format +msgid "\tUpdate size : %u\n" +msgstr "\tGröße der Aktualisierung: %u\n" + +#: ../../src/slave/kproplog.c:390 +#, c-format +msgid "\tUpdate committed : %s\n" +msgstr "\tAktualisierung übergeben: %s\n" + +#: ../../src/slave/kproplog.c:394 +#, c-format +msgid "\tUpdate time stamp : None\n" +msgstr "\tZeitstempel der Aktualisierung: keiner\n" + +#: ../../src/slave/kproplog.c:396 +#, c-format +msgid "\tUpdate time stamp : %s" +msgstr "\tZeitstempel der Aktualisierung: %s" + +#: ../../src/slave/kproplog.c:400 +#, c-format +msgid "\tAttributes changed : %d\n" +msgstr "\tgeänderte Attribute: %d\n" + +#: ../../src/slave/kproplog.c:465 +#, c-format +msgid "" +"Unable to initialize Kerberos\n" +"\n" +msgstr "" +"Kerberos kann nicht initialisiert werden\n" +"\n" + +#: ../../src/slave/kproplog.c:472 +#, c-format +msgid "" +"Couldn't read database_name\n" +"\n" +msgstr "" +"»database_name« kann nicht gelesen werden\n" +"\n" + +#: ../../src/slave/kproplog.c:476 +#, c-format +msgid "" +"\n" +"Kerberos update log (%s)\n" +msgstr "" +"\n" +"Kerberos-Aktualisierungsprotokoll (%s)\n" + +#: ../../src/slave/kproplog.c:480 ../../src/slave/kproplog.c:495 +#, c-format +msgid "" +"Unable to map log file %s\n" +"\n" +msgstr "" +"Protokolldatei %s kann nicht abgebildet werden\n" +"\n" + +#: ../../src/slave/kproplog.c:485 +#, c-format +msgid "" +"Couldn't reinitialize ulog file %s\n" +"\n" +msgstr "" +"Ulog-Datei %s konnte nicht neu initialisiert werden\n" +"\n" + +#: ../../src/slave/kproplog.c:489 +#, c-format +msgid "Reinitialized the ulog.\n" +msgstr "Das Ulog wurde neu initialisiert.\n" + +#: ../../src/slave/kproplog.c:501 +#, c-format +msgid "" +"Corrupt header log, exiting\n" +"\n" +msgstr "" +"beschädigtes Kopfzeilenprotokoll, wird beendet\n" +"\n" + +#: ../../src/slave/kproplog.c:505 +#, c-format +msgid "Update log dump :\n" +msgstr "Aktualisierungsprotokollauszug :\n" + +#: ../../src/slave/kproplog.c:506 +#, c-format +msgid "\tLog version # : %u\n" +msgstr "\tProtokollversion #: %u\n" + +#: ../../src/slave/kproplog.c:507 +#, c-format +msgid "\tLog state : " +msgstr "\tProtokollstatus: " + +#: ../../src/slave/kproplog.c:510 +#, c-format +msgid "Stable\n" +msgstr "stabil\n" + +#: ../../src/slave/kproplog.c:513 +#, c-format +msgid "Unstable\n" +msgstr "instabil\n" + +#: ../../src/slave/kproplog.c:516 +#, c-format +msgid "Corrupt\n" +msgstr "beschädigt\n" + +#: ../../src/slave/kproplog.c:519 +#, c-format +msgid "Unknown state: %d\n" +msgstr "unbekannter Status: %d\n" + +#: ../../src/slave/kproplog.c:522 +#, c-format +msgid "\tEntry block size : %u\n" +msgstr "\tBlockgrößeneintrag: %u\n" + +#: ../../src/slave/kproplog.c:523 +#, c-format +msgid "\tNumber of entries : %u\n" +msgstr "\tAnzahl der Einträge: %u\n" + +#: ../../src/slave/kproplog.c:526 +#, c-format +msgid "\tLast serial # : None\n" +msgstr "\tletzte Seriennummer: keine\n" + +#: ../../src/slave/kproplog.c:529 +#, c-format +msgid "\tFirst serial # : None\n" +msgstr "\terste Seriennummer: keine\n" + +#: ../../src/slave/kproplog.c:531 +#, c-format +msgid "\tFirst serial # : " +msgstr "\terste Seriennummer: " + +#: ../../src/slave/kproplog.c:535 +#, c-format +msgid "\tLast serial # : " +msgstr "\tletzte Seriennummer: " + +#: ../../src/slave/kproplog.c:540 +#, c-format +msgid "\tLast time stamp : None\n" +msgstr "\tletzter Zeitstempel: keiner\n" + +#: ../../src/slave/kproplog.c:543 +#, c-format +msgid "\tFirst time stamp : None\n" +msgstr "\terster Zeitstempel: keiner\n" + +#: ../../src/slave/kproplog.c:545 +#, c-format +msgid "\tFirst time stamp : %s" +msgstr "\terster Zeitstempel: %s" + +#: ../../src/slave/kproplog.c:549 +#, c-format +msgid "\tLast time stamp : %s\n" +msgstr "\tletzter Zeitstempel: %s\n" + +#: ../../src/util/support/errors.c:77 +msgid "Kerberos library initialization failure" +msgstr "Initialisieren der Kerberos-Bibliothek fehlgeschlagen" + +#: ../../src/util/support/errors.c:93 +#, c-format +msgid "error %ld" +msgstr "Fehler %ld" + +#: ../../src/util/support/plugins.c:186 +#, c-format +msgid "unable to find plugin [%s]: %s" +msgstr "Erweiterung [%s] konnte nicht gefunden werden: %s" + +#: ../../src/util/support/plugins.c:274 +msgid "unknown failure" +msgstr "unbekannter Fehlschlag" + +#: ../../src/util/support/plugins.c:277 +#, c-format +msgid "unable to load plugin [%s]: %s" +msgstr "Erweiterung [%s] konnte nicht geladen werden: %s" + +#: ../../src/util/support/plugins.c:300 +#, c-format +msgid "unable to load DLL [%s]" +msgstr "DLL [%s] konnte nicht geladen werden" + +#: ../../src/util/support/plugins.c:316 +#, c-format +msgid "plugin unavailable: %s" +msgstr "Erweiterung nicht verfügbar: %s" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:23 +msgid "No @ in SERVICE-NAME name string" +msgstr "keine @ in der Namenszeichenkette SERVICE-NAME" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:24 +msgid "STRING-UID-NAME contains nondigits" +msgstr "STRING-UID-NAME enthält etwas anderes als Ziffern" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:25 +msgid "UID does not resolve to username" +msgstr "UID lässt sich nicht zu Benutzernamen ermitteln" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:26 +msgid "Validation error" +msgstr "Überprüfungsfehler" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:27 +msgid "Couldn't allocate gss_buffer_t data" +msgstr "»gss_buffer_t«-Daten konnten reserviert werden" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:28 +msgid "Message context invalid" +msgstr "Nachrichtenkontext ungültig" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:29 +msgid "Buffer is the wrong size" +msgstr "Puffer hat die falsche Größe" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:30 +msgid "Credential usage type is unknown" +msgstr "Typ des Anmeldedatenaufrufs ist unbekannt" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:31 +msgid "Unknown quality of protection specified" +msgstr "unbekannte Schutzqualität angegeben" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:32 +msgid "Local host name could not be determined" +msgstr "lokaler Rechnername konnte nicht bestimmt werden" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:33 +msgid "Hostname in SERVICE-NAME string could not be canonicalized" +msgstr "" +"Rechnername in der Zeichenkette »SERVICE-NAME« konnte nicht in Normalform " +"gebracht werden" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:34 +msgid "Mechanism is incorrect" +msgstr "Mechanismus ist nicht korrekt" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:35 +msgid "Token header is malformed or corrupt" +msgstr "Token-Kopfzeilen haben die falsche Form oder sind beschädigt" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:36 +msgid "Packet was replayed in wrong direction" +msgstr "Paket wurde in falscher Richtung erneut abgespielt" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:37 +msgid "Token is missing data" +msgstr "dem Token fehlen Daten" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:38 +msgid "Token was reflected" +msgstr "Token wurde zurückgeworfen" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:39 +msgid "Received token ID does not match expected token ID" +msgstr "Die empfangene Token-Kennung passt nicht zur erwarteten Token-Kennung." + +#: ../lib/gssapi/generic/gssapi_err_generic.c:40 +msgid "The given credential's usage does not match the requested usage" +msgstr "" +"Die Verwendung der angegebenen Anmeldedaten passt nicht zur angeforderten " +"Verwendung." + +#: ../lib/gssapi/generic/gssapi_err_generic.c:41 +msgid "Storing of acceptor credentials is not supported by the mechanism" +msgstr "" +"Das Speichern von Abnehmeranmeldedaten wird nicht durch den Mechanismus " +"unterstützt." + +#: ../lib/gssapi/generic/gssapi_err_generic.c:42 +msgid "Storing of non-default credentials is not supported by the mechanism" +msgstr "" +"Das Speichern von Nichtstandardanmeldedaten wird nicht durch den Mechanismus " +"unterstützt." + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:23 +msgid "Principal in credential cache does not match desired name" +msgstr "" +"Principal im Anmeldedatenzwischenspeicher entspricht nicht dem gewünschten " +"Namen" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:24 +msgid "No principal in keytab matches desired name" +msgstr "Kein Principal in der Schlüsseltabelle passt zum gewünschten Namen." + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:25 +msgid "Credential cache has no TGT" +msgstr "Anmeldedatenzwischenspeicher hat kein TGT" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:26 +msgid "Authenticator has no subkey" +msgstr "Schlüsselziffer hat keinen Unterschlüssel" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:27 +msgid "Context is already fully established" +msgstr "Kontext wurde bereits vollständig eingerichtet" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:28 +msgid "Unknown signature type in token" +msgstr "unbekannter Signaturtyp im Token" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:29 +msgid "Invalid field length in token" +msgstr "falsche Feldlänge im Token" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:30 +msgid "Attempt to use incomplete security context" +msgstr "" +"Es wurde versucht, einen unvollständigen Sicherheitskontext zu verwenden." + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:31 +msgid "Bad magic number for krb5_gss_ctx_id_t" +msgstr "falsche magische Zahl für »krb5_gss_ctx_id_t«" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:32 +msgid "Bad magic number for krb5_gss_cred_id_t" +msgstr "falsche magische Zahl für »krb5_gss_cred_id_t«" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:33 +msgid "Bad magic number for krb5_gss_enc_desc" +msgstr "falsche magische Zahl für »krb5_gss_enc_desc«" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:34 +msgid "Sequence number in token is corrupt" +msgstr "Sequnznummer im Token ist beschädigt" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:35 +msgid "Credential cache is empty" +msgstr "Anmeldedatenzwischenspeicher ist leer" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:36 +msgid "Acceptor and Initiator share no checksum types" +msgstr "Abnehmer und Initiator haben keinen gemeinsamen Prüfsummentyp" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:37 +msgid "Requested lucid context version not supported" +msgstr "angeforderte »lucid«-Kontextversion nicht unterstützt" + +# PRF = Pseudo Random Function +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:38 +msgid "PRF input too long" +msgstr "PRF-Eingabe zu lang" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:39 +msgid "Bad magic number for iakerb_ctx_id_t" +msgstr "falsche magische Zahl für »iakerb_ctx_id_t«" + +#: ../lib/kadm5/chpass_util_strings.c:23 +msgid "while getting policy info." +msgstr "beim Holen der Richtlinieninformation." + +#: ../lib/kadm5/chpass_util_strings.c:24 +msgid "while getting principal info." +msgstr "beim Holen der Principal-Information." + +#: ../lib/kadm5/chpass_util_strings.c:25 +msgid "New passwords do not match - password not changed.\n" +msgstr "neue Passwörter stimmen nicht überein – Passwort nicht geändert\n" + +#: ../lib/kadm5/chpass_util_strings.c:26 +msgid "New password" +msgstr "neues Passwort" + +#: ../lib/kadm5/chpass_util_strings.c:27 +msgid "New password (again)" +msgstr "neues Passwort (erneut)" + +#: ../lib/kadm5/chpass_util_strings.c:28 +msgid "" +"You must type a password. Passwords must be at least one character long.\n" +msgstr "" +"Sie müssen ein Passwort eingeben. Passwörter müssen mindestens ein Zeichen " +"lang sein.\n" + +#: ../lib/kadm5/chpass_util_strings.c:29 +msgid "yet no policy set! Contact your system security administrator." +msgstr "" +"noch keine Richtlinie gesetzt! Kontaktieren Sie Ihren " +"Systemsicherheitsadministrator" + +#: ../lib/kadm5/chpass_util_strings.c:31 +msgid "" +"New password was found in a dictionary of possible passwords and\n" +"therefore may be easily guessed. Please choose another password.\n" +"See the kpasswd man page for help in choosing a good password." +msgstr "" +"Das neue Passwort wurde in einem Wörterbuch mit möglichen Passwörtern " +"gefunden\n" +"und kann daher leicht erraten werden. Bitte wählen Sie ein anderes " +"Passwort.\n" +"Hilfe bei der Wahl guter Passwörter finden Sie in der Handbuchseite von\n" +"»kpasswd«." + +#: ../lib/kadm5/chpass_util_strings.c:32 +msgid "Password not changed." +msgstr "Passwort nicht geändert" + +#: ../lib/kadm5/chpass_util_strings.c:33 +#, c-format +msgid "" +"New password is too short.\n" +"Please choose a password which is at least %d characters long." +msgstr "" +"Das neue Passwort ist zu kurz.\n" +"Bitte wählen Sie ein Passwort, das mindestens %d Zeichen lang ist." + +#: ../lib/kadm5/chpass_util_strings.c:34 +#, c-format +msgid "" +"New password does not have enough character classes.\n" +"The character classes are:\n" +"\t- lower-case letters,\n" +"\t- upper-case letters,\n" +"\t- digits,\n" +"\t- punctuation, and\n" +"\t- all other characters (e.g., control characters).\n" +"Please choose a password with at least %d character classes." +msgstr "" +"Das neue Passwort besteht aus zu wenigen Zeichenklassen.\n" +"Die Zeichenklassen sind:\n" +"\t- Kleinbuchstaben,\n" +"\t- Großbuchstaben,\n" +"\t- Ziffern,\n" +"\t- Satzzeichen und\n" +"\t- alle anderen Zeichen (z.B. Steuerzeichen).\n" +"Bitte wählen Sie ein Passwort mit mindestens %d Zeichenklassen." + +#: ../lib/kadm5/chpass_util_strings.c:35 +#, c-format +msgid "" +"Password cannot be changed because it was changed too recently.\n" +"Please wait until %s before you change it.\n" +"If you need to change your password before then, contact your system\n" +"security administrator." +msgstr "" +"Das Passwort kann nicht geändert werden, da es erst vor kurzem geändert " +"wurde.\n" +"Bitte warten Sie bis %s, ehe Sie es ändern.\n" +"Falls Sie es vorher ändern müssen, kontaktieren Sie Ihren\n" +"Systemsicherheitsadministrator." + +#: ../lib/kadm5/chpass_util_strings.c:36 +msgid "New password was used previously. Please choose a different password." +msgstr "" +"Das neue Passwort wurde zuvor schon benutzt. Bitte wählen Sie ein anderes " +"Passwort." + +#: ../lib/kadm5/chpass_util_strings.c:37 +msgid "while trying to change password." +msgstr "beim Versuch, das Passwort zu ändern." + +#: ../lib/kadm5/chpass_util_strings.c:38 +msgid "while reading new password." +msgstr "beim Lesen des neuen Passworts." + +#: ../lib/kadm5/kadm_err.c:23 +msgid "Operation failed for unspecified reason" +msgstr "Aktion aus nicht näher beschriebenem Grund fehlgeschlagen" + +#: ../lib/kadm5/kadm_err.c:24 +msgid "Operation requires ``get'' privilege" +msgstr "Aktion erfordert »get«-Recht" + +#: ../lib/kadm5/kadm_err.c:25 +msgid "Operation requires ``add'' privilege" +msgstr "Aktion erfordert »add«-Recht" + +#: ../lib/kadm5/kadm_err.c:26 +msgid "Operation requires ``modify'' privilege" +msgstr "Aktion erfordert »modify«-Recht" + +#: ../lib/kadm5/kadm_err.c:27 +msgid "Operation requires ``delete'' privilege" +msgstr "Aktion erfordert »delete«-Recht" + +#: ../lib/kadm5/kadm_err.c:28 +msgid "Insufficient authorization for operation" +msgstr "unzureichende Berechtigung für diese Aktion" + +#: ../lib/kadm5/kadm_err.c:29 ../lib/kdb/adb_err.c:29 +msgid "Database inconsistency detected" +msgstr "Datenbankinkonsistenz entdeckt" + +#: ../lib/kadm5/kadm_err.c:30 ../lib/kdb/adb_err.c:24 +msgid "Principal or policy already exists" +msgstr "Principal oder Richtlinie existiert bereits" + +#: ../lib/kadm5/kadm_err.c:31 +msgid "Communication failure with server" +msgstr "Kommunikation mit dem Server fehlgeschlagen" + +#: ../lib/kadm5/kadm_err.c:32 +msgid "No administration server found for realm" +msgstr "kein Administrationsserver für den Realm gefunden" + +#: ../lib/kadm5/kadm_err.c:33 +msgid "Password history principal key version mismatch" +msgstr "Die Passwortchronikschlüssel des Principals passen nicht zusammen." + +#: ../lib/kadm5/kadm_err.c:34 +msgid "Connection to server not initialized" +msgstr "Verbindung zum Server nicht initialisiert" + +#: ../lib/kadm5/kadm_err.c:35 +msgid "Principal does not exist" +msgstr "Principal existiert nicht" + +#: ../lib/kadm5/kadm_err.c:36 +msgid "Policy does not exist" +msgstr "Richtlinie existiert nicht" + +#: ../lib/kadm5/kadm_err.c:37 +msgid "Invalid field mask for operation" +msgstr "ungültige Feldmaske für Aktion" + +#: ../lib/kadm5/kadm_err.c:38 +msgid "Invalid number of character classes" +msgstr "ungültige Anzahl von Zeichenklassen" + +#: ../lib/kadm5/kadm_err.c:39 +msgid "Invalid password length" +msgstr "ungültige Passwortlänge" + +#: ../lib/kadm5/kadm_err.c:40 +msgid "Illegal policy name" +msgstr "unzulässiger Richtlinienname" + +#: ../lib/kadm5/kadm_err.c:41 +msgid "Illegal principal name" +msgstr "unzulässiger Principal-Name" + +# FIXME s/auxillary/auxilary/ +#: ../lib/kadm5/kadm_err.c:42 +msgid "Invalid auxillary attributes" +msgstr "ungültige Zusatzattribute" + +#: ../lib/kadm5/kadm_err.c:43 +msgid "Invalid password history count" +msgstr "ungültige Passwortchronikanzahl" + +#: ../lib/kadm5/kadm_err.c:44 +msgid "Password minimum life is greater than password maximum life" +msgstr "Die minimale Lebensdauer des Passworts ist größer als die maximale." + +#: ../lib/kadm5/kadm_err.c:45 +msgid "Password is too short" +msgstr "Das Passwort ist zu kurz." + +#: ../lib/kadm5/kadm_err.c:46 +msgid "Password does not contain enough character classes" +msgstr "Das Passwort enthält nicht genug Zeichenklassen." + +#: ../lib/kadm5/kadm_err.c:47 +msgid "Password is in the password dictionary" +msgstr "Das Passwort steht im Passwortwörterbuch." + +#: ../lib/kadm5/kadm_err.c:48 +msgid "Cannot reuse password" +msgstr "Das Passwort kann nicht erneut verwendet werden." + +#: ../lib/kadm5/kadm_err.c:49 +msgid "Current password's minimum life has not expired" +msgstr "Die aktuell minimale Lebensdauer des Passworts ist nicht abgelaufen." + +#: ../lib/kadm5/kadm_err.c:50 ../lib/krb5/error_tables/kdb5_err.c:67 +msgid "Policy is in use" +msgstr "Richtlinie ist in Benutzung" + +#: ../lib/kadm5/kadm_err.c:51 +msgid "Connection to server already initialized" +msgstr "Verbindung zum Server ist bereits initialisiert" + +#: ../lib/kadm5/kadm_err.c:52 +msgid "Incorrect password" +msgstr "falsches Passwort" + +#: ../lib/kadm5/kadm_err.c:53 +msgid "Cannot change protected principal" +msgstr "geschützter Principal kann nicht geändert werden" + +#: ../lib/kadm5/kadm_err.c:54 +msgid "Programmer error! Bad Admin server handle" +msgstr "Fehler des Programmierers! Falscher Admin-Server-Identifikator" + +#: ../lib/kadm5/kadm_err.c:55 +msgid "Programmer error! Bad API structure version" +msgstr "Fehler des Programmierers! Falsche API-Strukturversion" + +#: ../lib/kadm5/kadm_err.c:56 +msgid "" +"API structure version specified by application is no longer supported (to " +"fix, recompile application against current KADM5 API header files and " +"libraries)" +msgstr "" +"Die von der Anwendung angegebene Version der API-Struktur wird nicht länger " +"unterstützt. (Kompilieren Sie die Anwendung mit den aktuellen KADM5-API-" +"Header-Dateien und -Bibliotheken, um dies zu beheben.)" + +#: ../lib/kadm5/kadm_err.c:57 +msgid "" +"API structure version specified by application is unknown to libraries (to " +"fix, obtain current KADM5 API header files and libraries and recompile " +"application)" +msgstr "" +"Die von der Anwendung angegebene Version der API-Struktur ist den " +"Bibliotheken unbekannt. (Besorgen Sie sich die aktuellen KADM5-API-Header-" +"Dateien und -Bibliotheken und kompilieren Sie die Anwendung neu, um dies zu " +"beheben.)" + +#: ../lib/kadm5/kadm_err.c:58 +msgid "Programmer error! Bad API version" +msgstr "Fehler des Programmierers! Falsche API-Version" + +#: ../lib/kadm5/kadm_err.c:59 +msgid "" +"API version specified by application is no longer supported by libraries (to " +"fix, update application to adhere to current API version and recompile)" +msgstr "" +"Die von der Anwendung angegebene Version der API-Struktur wird nicht länger " +"von den Bibliotheken unterstützt. (Aktualisieren Sie die Anwendung, dass sie " +"zu der aktuellen API-Version passt, und kompilieren Sie sie, um dies zu " +"beheben.)" + +#: ../lib/kadm5/kadm_err.c:60 +msgid "" +"API version specified by application is no longer supported by server (to " +"fix, update application to adhere to current API version and recompile)" +msgstr "" +"Die von der Anwendung angegebene Version der API-Struktur wird nicht länger " +"vom Server unterstützt. (Aktualisieren Sie die Anwendung, dass sie zu der " +"aktuellen API-Version passt, und kompilieren Sie sie, um dies zu beheben.)" + +#: ../lib/kadm5/kadm_err.c:61 +msgid "" +"API version specified by application is unknown to libraries (to fix, obtain " +"current KADM5 API header files and libraries and recompile application)" +msgstr "" +"Die von der Anwendung angegebenene API-Version ist den Bibliotheken " +"unbekannt. (Besorgen Sie sich die aktuellen KADM5-API-Header-Dateien und -" +"Bibliotheken und kompilieren Sie die Anwendung neu, um dies zu beheben.)" + +#: ../lib/kadm5/kadm_err.c:62 +msgid "" +"API version specified by application is unknown to server (to fix, obtain " +"and install newest KADM5 Admin Server)" +msgstr "" +"Die von der Anwendung angegebene API-Version ist dem Server unbekannt. " +"(Besorgen und installieren Sie sich den neuesten KADM5-Admin-Server, um dies " +"zu beheben.)" + +#: ../lib/kadm5/kadm_err.c:63 +msgid "Database error! Required KADM5 principal missing" +msgstr "Datenbankfehler! Erforderlicher KADM5-Principal fehlt" + +#: ../lib/kadm5/kadm_err.c:64 +msgid "The salt type of the specified principal does not support renaming" +msgstr "Der Salt-Typ des angegebenen Principals unterstützt kein Umbenennen." + +#: ../lib/kadm5/kadm_err.c:65 +msgid "Illegal configuration parameter for remote KADM5 client" +msgstr "widerrechtlicher Konfigurationsparameter für fernen KADM5-Client" + +#: ../lib/kadm5/kadm_err.c:66 +msgid "Illegal configuration parameter for local KADM5 client" +msgstr "widerrechtlicher Konfigurationsparameter für lokalen KADM5-Client" + +#: ../lib/kadm5/kadm_err.c:67 +msgid "Operation requires ``list'' privilege" +msgstr "Aktion erfordert das »list«-Recht" + +#: ../lib/kadm5/kadm_err.c:68 +msgid "Operation requires ``change-password'' privilege" +msgstr "Aktion erfordert das »change-password«-Recht" + +#: ../lib/kadm5/kadm_err.c:69 +msgid "GSS-API (or Kerberos) error" +msgstr "GSS-API- (oder Kerberos-) Fehler" + +#: ../lib/kadm5/kadm_err.c:70 +msgid "Programmer error! Illegal tagged data list type" +msgstr "" +"Fehler des Programmierers! Widerrechlicher Listentyp für gekennzeichnete " +"Daten" + +#: ../lib/kadm5/kadm_err.c:71 +msgid "Required parameters in kdc.conf missing" +msgstr "erforderliche Parameter in »kdc.conf« fehlen" + +#: ../lib/kadm5/kadm_err.c:72 +msgid "Bad krb5 admin server hostname" +msgstr "falscher Rechnername des KRB5-Admin-Servers" + +#: ../lib/kadm5/kadm_err.c:73 +msgid "Operation requires ``set-key'' privilege" +msgstr "Aktion erfordert das »set-key«-Recht" + +#: ../lib/kadm5/kadm_err.c:74 +msgid "Multiple values for single or folded enctype" +msgstr "" +"mehrere Werte für einzelnen Verschlüsselungstyp oder Verschlüsselungstyp mit " +"Salt" + +#: ../lib/kadm5/kadm_err.c:75 +msgid "Invalid enctype for setv4key" +msgstr "widerrechtlicher Verschlüsselungstyp für Setv4key" + +#: ../lib/kadm5/kadm_err.c:76 +msgid "Mismatched enctypes for setkey3" +msgstr "nicht zusammenpassende Verschlüsselungstypen für Setkey3" + +#: ../lib/kadm5/kadm_err.c:77 +msgid "Missing parameters in krb5.conf required for kadmin client" +msgstr "für Kadmin-Client benötigte Parameter fehlen in »krb5.conf«" + +#: ../lib/kadm5/kadm_err.c:78 ../lib/kdb/adb_err.c:30 +msgid "XDR encoding error" +msgstr "XDR-Verschlüsselungsfehler" + +#: ../lib/kadm5/kadm_err.c:79 +msgid "Cannot resolve network address for admin server in requested realm" +msgstr "" +"Die Netzwerkadresse für den Admin-Server im angeforderten Realm kann nicht " +"aufgelöst werden." + +#: ../lib/kadm5/kadm_err.c:80 +msgid "Unspecified password quality failure" +msgstr "nicht näher angegebener Passwortqualitätsfehlschlag" + +#: ../lib/kadm5/kadm_err.c:81 +msgid "Invalid key/salt tuples" +msgstr "ungültige Schlüssel-/Salt-Tupel" + +#: ../lib/kdb/adb_err.c:23 +msgid "No Error" +msgstr "kein Fehler" + +#: ../lib/kdb/adb_err.c:25 +msgid "Principal or policy does not exist" +msgstr "Principal oder Richtlinie existiert nicht" + +#: ../lib/kdb/adb_err.c:26 +msgid "Database not initialized" +msgstr "Datenbank nicht initialisiert" + +#: ../lib/kdb/adb_err.c:27 +msgid "Invalid policy name" +msgstr "ungültiger Richtlinienname" + +#: ../lib/kdb/adb_err.c:28 +msgid "Invalid principal name" +msgstr "ungültiger Principal-Name" + +#: ../lib/kdb/adb_err.c:31 +msgid "Failure!" +msgstr "Fehlschlag!" + +#: ../lib/kdb/adb_err.c:32 +msgid "Bad lock mode" +msgstr "falscher Sperrmodus" + +#: ../lib/kdb/adb_err.c:33 +msgid "Cannot lock database" +msgstr "Datenbank kann nicht gesperrt werden" + +#: ../lib/kdb/adb_err.c:34 +msgid "Database not locked" +msgstr "Datenbank nicht gesperrt" + +#: ../lib/kdb/adb_err.c:35 +msgid "KADM5 administration database lock file missing" +msgstr "Sperrdatei der KADM5-Verwaltungsdatenbank fehlt" + +#: ../lib/kdb/adb_err.c:36 +msgid "Insufficient permission to lock file" +msgstr "keine ausreichenden Rechte zum Sperren der Datei" + +#: ../lib/krb5/error_tables/k5e1_err.c:23 +msgid "Plugin does not support interface version" +msgstr "Erweiterung unterstützt nicht die Schnittstellenversion" + +#: ../lib/krb5/error_tables/k5e1_err.c:24 +msgid "Invalid module specifier" +msgstr "ungültige Modulangabe" + +#: ../lib/krb5/error_tables/k5e1_err.c:25 +msgid "Plugin module name not found" +msgstr "Erweiterungsmodulname nicht gefunden" + +#: ../lib/krb5/error_tables/k5e1_err.c:26 +msgid "The KDC should discard this request" +msgstr "Das KDC sollte diese Anfrage verwerfen" + +#: ../lib/krb5/error_tables/k5e1_err.c:27 +msgid "Can't create new subsidiary cache" +msgstr "Der neue ergänzende Zwischenspeicher kann nicht erzeugt werden" + +#: ../lib/krb5/error_tables/k5e1_err.c:28 +msgid "Invalid keyring anchor name" +msgstr "ungültiger Schlüsselbundverankerungsname" + +#: ../lib/krb5/error_tables/k5e1_err.c:29 +msgid "Unknown keyring collection version" +msgstr "unbekannte Schlüsselbundsammlungsversion" + +#: ../lib/krb5/error_tables/k5e1_err.c:30 +msgid "Invalid UID in persistent keyring name" +msgstr "ungültige UID im beständigen Schlüsselbundnamen" + +#: ../lib/krb5/error_tables/k5e1_err.c:31 +msgid "Malformed reply from KCM daemon" +msgstr "Antwort des KCM-Daemons hat die falsche Form" + +#: ../lib/krb5/error_tables/k5e1_err.c:32 +msgid "Mach RPC error communicating with KCM daemon" +msgstr "Mach-RPC-Fehler beim der Kommunikation mit dem KCM-Daemon" + +#: ../lib/krb5/error_tables/k5e1_err.c:33 +msgid "KCM daemon reply too big" +msgstr "Antwort des KCM-Daemons zu groß" + +#: ../lib/krb5/error_tables/k5e1_err.c:34 +msgid "No KCM server found" +msgstr "Kein KCM-Server gefunden" + +#: ../lib/krb5/error_tables/krb5_err.c:24 +msgid "Client's entry in database has expired" +msgstr "Eintrag des Clients in der Datenbank ist abgelaufen" + +#: ../lib/krb5/error_tables/krb5_err.c:25 +msgid "Server's entry in database has expired" +msgstr "Eintrag des Servers in der Datenbank ist abgelaufen" + +#: ../lib/krb5/error_tables/krb5_err.c:26 +msgid "Requested protocol version not supported" +msgstr "angeforderte Protokollversion nicht unterstützt" + +#: ../lib/krb5/error_tables/krb5_err.c:27 +msgid "Client's key is encrypted in an old master key" +msgstr "" +"Der Schlüssel des Clients wurde mit einem alten Hauptschlüssel verschlüsselt." + +#: ../lib/krb5/error_tables/krb5_err.c:28 +msgid "Server's key is encrypted in an old master key" +msgstr "" +"Der Schlüssel des Servers wurde mit einem alten Hauptschlüssel verschlüsselt." + +#: ../lib/krb5/error_tables/krb5_err.c:29 +msgid "Client not found in Kerberos database" +msgstr "Client nicht in der Kerberos-Datenbank gefunden" + +#: ../lib/krb5/error_tables/krb5_err.c:30 +msgid "Server not found in Kerberos database" +msgstr "Server nicht in der Kerberos-Datenbank gefunden" + +#: ../lib/krb5/error_tables/krb5_err.c:31 +msgid "Principal has multiple entries in Kerberos database" +msgstr "Principal hat in der Kerberos-Datenbank mehrere Einträge" + +#: ../lib/krb5/error_tables/krb5_err.c:32 +msgid "Client or server has a null key" +msgstr "Client oder Server hat einen Nullschlüssel" + +#: ../lib/krb5/error_tables/krb5_err.c:33 +msgid "Ticket is ineligible for postdating" +msgstr "Ticket ist zum Vordatieren ungeeignet" + +#: ../lib/krb5/error_tables/krb5_err.c:34 +msgid "Requested effective lifetime is negative or too short" +msgstr "Die angeforderte effektive Lebensdauer ist negativ oder zu kurz." + +#: ../lib/krb5/error_tables/krb5_err.c:35 +msgid "KDC policy rejects request" +msgstr "KDC-Richtlinie weist die Anfrage zurück" + +#: ../lib/krb5/error_tables/krb5_err.c:36 +msgid "KDC can't fulfill requested option" +msgstr "KDC kann erforderliche Option nicht erfüllen" + +#: ../lib/krb5/error_tables/krb5_err.c:37 +msgid "KDC has no support for encryption type" +msgstr "KDC unterstützt diesen Verschlüsselungstyp nicht" + +#: ../lib/krb5/error_tables/krb5_err.c:38 +msgid "KDC has no support for checksum type" +msgstr "KDC unterstützt diesen Prüfsummentyp nicht" + +#: ../lib/krb5/error_tables/krb5_err.c:39 +msgid "KDC has no support for padata type" +msgstr "KDC unterstützt diesen Padata-Typ nicht" + +#: ../lib/krb5/error_tables/krb5_err.c:40 +msgid "KDC has no support for transited type" +msgstr "KDC unterstützt diesen Übergangstyp nicht" + +#: ../lib/krb5/error_tables/krb5_err.c:41 +msgid "Clients credentials have been revoked" +msgstr "Anmeldedaten des Clients wurden widerrufen" + +#: ../lib/krb5/error_tables/krb5_err.c:42 +msgid "Credentials for server have been revoked" +msgstr "Anmeldedaten für den Server wurden widerrufen" + +#: ../lib/krb5/error_tables/krb5_err.c:43 +msgid "TGT has been revoked" +msgstr "TGT wurde widerrufen" + +#: ../lib/krb5/error_tables/krb5_err.c:44 +msgid "Client not yet valid - try again later" +msgstr "Client noch nicht gültig – versuchen Sie es später noch einmal" + +#: ../lib/krb5/error_tables/krb5_err.c:45 +msgid "Server not yet valid - try again later" +msgstr "Server noch nicht gültig – versuchen Sie es später noch einmal" + +#: ../lib/krb5/error_tables/krb5_err.c:46 +msgid "Password has expired" +msgstr "Passwort ist abgelaufen" + +#: ../lib/krb5/error_tables/krb5_err.c:47 +msgid "Preauthentication failed" +msgstr "Vorauthentifizierung fehlgeschlagen" + +#: ../lib/krb5/error_tables/krb5_err.c:48 +msgid "Additional pre-authentication required" +msgstr "zusätzlich Vorauthentifizierung erforderlich" + +#: ../lib/krb5/error_tables/krb5_err.c:49 +msgid "Requested server and ticket don't match" +msgstr "abgefragter Server und Ticket passen nicht zusammen" + +#: ../lib/krb5/error_tables/krb5_err.c:50 +msgid "Server principal valid for user2user only" +msgstr "Der Server-Principal ist nur für »user2user« gültig" + +#: ../lib/krb5/error_tables/krb5_err.c:51 +msgid "KDC policy rejects transited path" +msgstr "KDC-Richtlinie verwirft durchgereichten Pfad" + +#: ../lib/krb5/error_tables/krb5_err.c:52 +msgid "A service is not available that is required to process the request" +msgstr "" +"Ein Dienst, der zum Verarbeiten der Abfrage erforderlich ist, ist nicht " +"verfügbar." + +#: ../lib/krb5/error_tables/krb5_err.c:53 +msgid "KRB5 error code 30" +msgstr "KRB5-Fehlercode 30" + +#: ../lib/krb5/error_tables/krb5_err.c:54 +msgid "Decrypt integrity check failed" +msgstr "Entschlüsselungsintegritätsprüfung fehlgeschlagen" + +#: ../lib/krb5/error_tables/krb5_err.c:55 +msgid "Ticket expired" +msgstr "Ticket abgelaufen" + +#: ../lib/krb5/error_tables/krb5_err.c:56 +msgid "Ticket not yet valid" +msgstr "Ticket noch nicht gültig" + +#: ../lib/krb5/error_tables/krb5_err.c:57 +msgid "Request is a replay" +msgstr "Anfrage ist eine Wiederholung" + +#: ../lib/krb5/error_tables/krb5_err.c:58 +msgid "The ticket isn't for us" +msgstr "Das Ticket ist nicht für uns." + +#: ../lib/krb5/error_tables/krb5_err.c:59 +msgid "Ticket/authenticator don't match" +msgstr "Ticket/Schlüsselziffer passen nicht zueinander" + +#: ../lib/krb5/error_tables/krb5_err.c:60 +msgid "Clock skew too great" +msgstr "Uhrzeitabweichung zu groß" + +#: ../lib/krb5/error_tables/krb5_err.c:61 +msgid "Incorrect net address" +msgstr "falsche Netzwerkadresse" + +#: ../lib/krb5/error_tables/krb5_err.c:62 +msgid "Protocol version mismatch" +msgstr "Protokollversion passt nicht" + +#: ../lib/krb5/error_tables/krb5_err.c:63 +msgid "Invalid message type" +msgstr "ungültiger Nachrichtentyp" + +#: ../lib/krb5/error_tables/krb5_err.c:64 +msgid "Message stream modified" +msgstr "Nachrichtendatenstrom geändert" + +#: ../lib/krb5/error_tables/krb5_err.c:65 +msgid "Message out of order" +msgstr "Nachricht nicht in Ordnung" + +#: ../lib/krb5/error_tables/krb5_err.c:66 +msgid "Illegal cross-realm ticket" +msgstr "Widerrechliches Realm-übergreifendes Ticket" + +#: ../lib/krb5/error_tables/krb5_err.c:67 +msgid "Key version is not available" +msgstr "Schlüsselversion ist nicht verfügbar" + +#: ../lib/krb5/error_tables/krb5_err.c:68 +msgid "Service key not available" +msgstr "Dienstschlüssel nicht verfügbar" + +#: ../lib/krb5/error_tables/krb5_err.c:69 +#: ../lib/krb5/error_tables/krb5_err.c:181 +msgid "Mutual authentication failed" +msgstr "gegenseitige Authentifizierung fehlgeschlagen" + +#: ../lib/krb5/error_tables/krb5_err.c:70 +msgid "Incorrect message direction" +msgstr "falsche Nachrichtenrichtung" + +#: ../lib/krb5/error_tables/krb5_err.c:71 +msgid "Alternative authentication method required" +msgstr "alternative Authentifizierungsmethode erforderlich" + +#: ../lib/krb5/error_tables/krb5_err.c:72 +msgid "Incorrect sequence number in message" +msgstr "falsche Sequenznummer in der Nachricht" + +#: ../lib/krb5/error_tables/krb5_err.c:73 +msgid "Inappropriate type of checksum in message" +msgstr "ungeeigneter Prüfsummentyp in der Nachricht" + +#: ../lib/krb5/error_tables/krb5_err.c:74 +msgid "Policy rejects transited path" +msgstr "Richtlinie verwirft durchgereichten Pfad" + +#: ../lib/krb5/error_tables/krb5_err.c:75 +msgid "Response too big for UDP, retry with TCP" +msgstr "Antwort für UDP zu groß, erneuter Versuch mit TCP" + +#: ../lib/krb5/error_tables/krb5_err.c:76 +msgid "KRB5 error code 53" +msgstr "KRB5-Fehlercode 53" + +#: ../lib/krb5/error_tables/krb5_err.c:77 +msgid "KRB5 error code 54" +msgstr "KRB5-Fehlercode 54" + +#: ../lib/krb5/error_tables/krb5_err.c:78 +msgid "KRB5 error code 55" +msgstr "KRB5-Fehlercode 55" + +#: ../lib/krb5/error_tables/krb5_err.c:79 +msgid "KRB5 error code 56" +msgstr "KRB5-Fehlercode 56" + +#: ../lib/krb5/error_tables/krb5_err.c:80 +msgid "KRB5 error code 57" +msgstr "KRB5-Fehlercode 57" + +#: ../lib/krb5/error_tables/krb5_err.c:81 +msgid "KRB5 error code 58" +msgstr "KRB5-Fehlercode 58" + +#: ../lib/krb5/error_tables/krb5_err.c:82 +msgid "KRB5 error code 59" +msgstr "KRB5-Fehlercode 59" + +#: ../lib/krb5/error_tables/krb5_err.c:83 +msgid "Generic error (see e-text)" +msgstr "allgemeiner Fehler (siehe E-Text)" + +#: ../lib/krb5/error_tables/krb5_err.c:84 +msgid "Field is too long for this implementation" +msgstr "Feld ist für diese Implementierung zu lang" + +#: ../lib/krb5/error_tables/krb5_err.c:85 +msgid "Client not trusted" +msgstr "Client nicht vertrauenswürdig" + +#: ../lib/krb5/error_tables/krb5_err.c:86 +msgid "KDC not trusted" +msgstr "KDC nicht vertrauenswürdig" + +#: ../lib/krb5/error_tables/krb5_err.c:87 +msgid "Invalid signature" +msgstr "ungültige Signatur" + +#: ../lib/krb5/error_tables/krb5_err.c:88 +msgid "Key parameters not accepted" +msgstr "Schlüsselparameter nicht akzeptiert" + +#: ../lib/krb5/error_tables/krb5_err.c:89 +msgid "Certificate mismatch" +msgstr "Zertifikat passt nicht" + +#: ../lib/krb5/error_tables/krb5_err.c:90 +msgid "No ticket granting ticket" +msgstr "kein ticketgewährendes Ticket" + +#: ../lib/krb5/error_tables/krb5_err.c:91 +msgid "Realm not local to KDC" +msgstr "Realm für KDC nicht lokal" + +#: ../lib/krb5/error_tables/krb5_err.c:92 +msgid "User to user required" +msgstr "Benutzer-zu-Benutzer erforderlich" + +#: ../lib/krb5/error_tables/krb5_err.c:93 +msgid "Can't verify certificate" +msgstr "Zertifikat kann nicht überprüft werden" + +#: ../lib/krb5/error_tables/krb5_err.c:94 +msgid "Invalid certificate" +msgstr "ungültiges Zertifikat" + +#: ../lib/krb5/error_tables/krb5_err.c:95 +msgid "Revoked certificate" +msgstr "widerrufenes Zertifikat" + +#: ../lib/krb5/error_tables/krb5_err.c:96 +msgid "Revocation status unknown" +msgstr "Widerrufsstatus unbekannt" + +#: ../lib/krb5/error_tables/krb5_err.c:97 +msgid "Revocation status unavailable" +msgstr "Widerrufsstatus nicht verfügbar" + +#: ../lib/krb5/error_tables/krb5_err.c:98 +msgid "Client name mismatch" +msgstr "Client-Name passt nicht" + +#: ../lib/krb5/error_tables/krb5_err.c:99 +msgid "KDC name mismatch" +msgstr "KDC-Name passt nicht" + +#: ../lib/krb5/error_tables/krb5_err.c:100 +msgid "Inconsistent key purpose" +msgstr "inkonstistenter Schlüsselzweck" + +#: ../lib/krb5/error_tables/krb5_err.c:101 +msgid "Digest in certificate not accepted" +msgstr "Kurzfassung im Zertifikat nicht akzeptiert" + +#: ../lib/krb5/error_tables/krb5_err.c:102 +msgid "Checksum must be included" +msgstr "Prüfsumme muss enthalten sein" + +#: ../lib/krb5/error_tables/krb5_err.c:103 +msgid "Digest in signed-data not accepted" +msgstr "Kurzfassung in signierten Daten nicht akzeptiert" + +#: ../lib/krb5/error_tables/krb5_err.c:104 +msgid "Public key encryption not supported" +msgstr "Asymetrische Verschlüsselung nicht unterstützt" + +#: ../lib/krb5/error_tables/krb5_err.c:105 +msgid "KRB5 error code 82" +msgstr "KRB5-Fehlercode 82" + +#: ../lib/krb5/error_tables/krb5_err.c:106 +msgid "KRB5 error code 83" +msgstr "KRB5-Fehlercode 83" + +#: ../lib/krb5/error_tables/krb5_err.c:107 +msgid "KRB5 error code 84" +msgstr "KRB5-Fehlercode 84" + +#: ../lib/krb5/error_tables/krb5_err.c:108 +msgid "The IAKERB proxy could not find a KDC" +msgstr "Der IAKERB-Proxy konnte kein KDC finden." + +#: ../lib/krb5/error_tables/krb5_err.c:109 +msgid "The KDC did not respond to the IAKERB proxy" +msgstr "Das KDC anwortete dem IAKERB-Proxy nicht." + +#: ../lib/krb5/error_tables/krb5_err.c:110 +msgid "KRB5 error code 87" +msgstr "KRB5-Fehlercode 87" + +#: ../lib/krb5/error_tables/krb5_err.c:111 +msgid "KRB5 error code 88" +msgstr "KRB5-Fehlercode 88" + +#: ../lib/krb5/error_tables/krb5_err.c:112 +msgid "KRB5 error code 89" +msgstr "KRB5-Fehlercode 89" + +#: ../lib/krb5/error_tables/krb5_err.c:113 +msgid "KRB5 error code 90" +msgstr "KRB5-Fehlercode 90" + +#: ../lib/krb5/error_tables/krb5_err.c:114 +msgid "KRB5 error code 91" +msgstr "KRB5-Fehlercode 91" + +#: ../lib/krb5/error_tables/krb5_err.c:115 +msgid "KRB5 error code 92" +msgstr "KRB5-Fehlercode 92" + +#: ../lib/krb5/error_tables/krb5_err.c:116 +msgid "An unsupported critical FAST option was requested" +msgstr "Es wurde eine nicht unterstützte kritische FAST-Aktion angefordert." + +#: ../lib/krb5/error_tables/krb5_err.c:117 +msgid "KRB5 error code 94" +msgstr "KRB5-Fehlercode 94" + +#: ../lib/krb5/error_tables/krb5_err.c:118 +msgid "KRB5 error code 95" +msgstr "KRB5-Fehlercode 95" + +#: ../lib/krb5/error_tables/krb5_err.c:119 +msgid "KRB5 error code 96" +msgstr "KRB5-Fehlercode 96" + +#: ../lib/krb5/error_tables/krb5_err.c:120 +msgid "KRB5 error code 97" +msgstr "KRB5-Fehlercode 97" + +#: ../lib/krb5/error_tables/krb5_err.c:121 +msgid "KRB5 error code 98" +msgstr "KRB5-Fehlercode 98" + +#: ../lib/krb5/error_tables/krb5_err.c:122 +msgid "KRB5 error code 99" +msgstr "KRB5-Fehlercode 99" + +#: ../lib/krb5/error_tables/krb5_err.c:123 +msgid "No acceptable KDF offered" +msgstr "kein akzeptables KDF angeboten" + +#: ../lib/krb5/error_tables/krb5_err.c:124 +msgid "KRB5 error code 101" +msgstr "KRB5-Fehlercode 101" + +#: ../lib/krb5/error_tables/krb5_err.c:125 +msgid "KRB5 error code 102" +msgstr "KRB5-Fehlercode 102" + +#: ../lib/krb5/error_tables/krb5_err.c:126 +msgid "KRB5 error code 103" +msgstr "KRB5-Fehlercode 103" + +#: ../lib/krb5/error_tables/krb5_err.c:127 +msgid "KRB5 error code 104" +msgstr "KRB5-Fehlercode 104" + +#: ../lib/krb5/error_tables/krb5_err.c:128 +msgid "KRB5 error code 105" +msgstr "KRB5-Fehlercode 105" + +#: ../lib/krb5/error_tables/krb5_err.c:129 +msgid "KRB5 error code 106" +msgstr "KRB5-Fehlercode 106" + +#: ../lib/krb5/error_tables/krb5_err.c:130 +msgid "KRB5 error code 107" +msgstr "KRB5-Fehlercode 107" + +#: ../lib/krb5/error_tables/krb5_err.c:131 +msgid "KRB5 error code 108" +msgstr "KRB5-Fehlercode 108" + +#: ../lib/krb5/error_tables/krb5_err.c:132 +msgid "KRB5 error code 109" +msgstr "KRB5-Fehlercode 109" + +#: ../lib/krb5/error_tables/krb5_err.c:133 +msgid "KRB5 error code 110" +msgstr "KRB5-Fehlercode 110" + +#: ../lib/krb5/error_tables/krb5_err.c:134 +msgid "KRB5 error code 111" +msgstr "KRB5-Fehlercode 111" + +#: ../lib/krb5/error_tables/krb5_err.c:135 +msgid "KRB5 error code 112" +msgstr "KRB5-Fehlercode 112" + +#: ../lib/krb5/error_tables/krb5_err.c:136 +msgid "KRB5 error code 113" +msgstr "KRB5-Fehlercode 113" + +#: ../lib/krb5/error_tables/krb5_err.c:137 +msgid "KRB5 error code 114" +msgstr "KRB5-Fehlercode 114" + +#: ../lib/krb5/error_tables/krb5_err.c:138 +msgid "KRB5 error code 115" +msgstr "KRB5-Fehlercode 115" + +#: ../lib/krb5/error_tables/krb5_err.c:139 +msgid "KRB5 error code 116" +msgstr "KRB5-Fehlercode 116" + +#: ../lib/krb5/error_tables/krb5_err.c:140 +msgid "KRB5 error code 117" +msgstr "KRB5-Fehlercode 117" + +#: ../lib/krb5/error_tables/krb5_err.c:141 +msgid "KRB5 error code 118" +msgstr "KRB5-Fehlercode 118" + +#: ../lib/krb5/error_tables/krb5_err.c:142 +msgid "KRB5 error code 119" +msgstr "KRB5-Fehlercode 119" + +#: ../lib/krb5/error_tables/krb5_err.c:143 +msgid "KRB5 error code 120" +msgstr "KRB5-Fehlercode 120" + +#: ../lib/krb5/error_tables/krb5_err.c:144 +msgid "KRB5 error code 121" +msgstr "KRB5-Fehlercode 121" + +#: ../lib/krb5/error_tables/krb5_err.c:145 +msgid "KRB5 error code 122" +msgstr "KRB5-Fehlercode 122" + +#: ../lib/krb5/error_tables/krb5_err.c:146 +msgid "KRB5 error code 123" +msgstr "KRB5-Fehlercode 123" + +#: ../lib/krb5/error_tables/krb5_err.c:147 +msgid "KRB5 error code 124" +msgstr "KRB5-Fehlercode 124" + +#: ../lib/krb5/error_tables/krb5_err.c:148 +msgid "KRB5 error code 125" +msgstr "KRB5-Fehlercode 125" + +#: ../lib/krb5/error_tables/krb5_err.c:149 +msgid "KRB5 error code 126" +msgstr "KRB5-Fehlercode 126" + +#: ../lib/krb5/error_tables/krb5_err.c:150 +msgid "KRB5 error code 127" +msgstr "KRB5-Fehlercode 127" + +#: ../lib/krb5/error_tables/krb5_err.c:151 +#: ../lib/krb5/error_tables/kdb5_err.c:23 +msgid "$Id$" +msgstr "$Id$" + +#: ../lib/krb5/error_tables/krb5_err.c:152 +msgid "Invalid flag for file lock mode" +msgstr "ungültiger Schalter für den Datei-Sperrmodus" + +#: ../lib/krb5/error_tables/krb5_err.c:153 +msgid "Cannot read password" +msgstr "Passwort kann nicht gelesen werden" + +#: ../lib/krb5/error_tables/krb5_err.c:154 +msgid "Password mismatch" +msgstr "Passwort stimmt nicht überein" + +#: ../lib/krb5/error_tables/krb5_err.c:155 +msgid "Password read interrupted" +msgstr "Lesen des Passworts unterbrochen" + +#: ../lib/krb5/error_tables/krb5_err.c:156 +msgid "Illegal character in component name" +msgstr "ungültiges Zeichen in Komponentenname" + +#: ../lib/krb5/error_tables/krb5_err.c:157 +msgid "Malformed representation of principal" +msgstr "Darstellung des Principals in falscher Form" + +#: ../lib/krb5/error_tables/krb5_err.c:158 +msgid "Can't open/find Kerberos configuration file" +msgstr "Kerberos-Konfigurationsdatei kann nicht geöffnet/gefunden werden" + +#: ../lib/krb5/error_tables/krb5_err.c:159 +msgid "Improper format of Kerberos configuration file" +msgstr "Format der Kerberos-Konfigurationsdatei ist ungeeignet" + +#: ../lib/krb5/error_tables/krb5_err.c:160 +msgid "Insufficient space to return complete information" +msgstr "Platz reicht nicht zur Rückgabe aller Informationen aus" + +#: ../lib/krb5/error_tables/krb5_err.c:161 +msgid "Invalid message type specified for encoding" +msgstr "der zum Kodieren angegebene Nachrichtentyp ist ungültig" + +#: ../lib/krb5/error_tables/krb5_err.c:162 +msgid "Credential cache name malformed" +msgstr "falsche Form des Anmeldedatenzwischenspeichernamens" + +#: ../lib/krb5/error_tables/krb5_err.c:163 +msgid "Unknown credential cache type" +msgstr "unbekannter Anmeldedatenzwischenspeichertyp" + +#: ../lib/krb5/error_tables/krb5_err.c:164 +msgid "Matching credential not found" +msgstr "keine passenden Anmeldedaten gefunden" + +#: ../lib/krb5/error_tables/krb5_err.c:165 +msgid "End of credential cache reached" +msgstr "Ende des Anmeldedatenzwischenspeichers erreicht" + +#: ../lib/krb5/error_tables/krb5_err.c:166 +msgid "Request did not supply a ticket" +msgstr "Anfrage lieferte kein Ticket" + +#: ../lib/krb5/error_tables/krb5_err.c:167 +msgid "Wrong principal in request" +msgstr "falscher Principal in der Anfrage" + +#: ../lib/krb5/error_tables/krb5_err.c:168 +msgid "Ticket has invalid flag set" +msgstr "Das Ticket hat einen falsch gesetzten Schalter." + +#: ../lib/krb5/error_tables/krb5_err.c:169 +msgid "Requested principal and ticket don't match" +msgstr "angeforderter Principal und Ticket passen nicht zusammen" + +#: ../lib/krb5/error_tables/krb5_err.c:170 +msgid "KDC reply did not match expectations" +msgstr "KDC-Antwort entsprach nicht den Erwartungen" + +#: ../lib/krb5/error_tables/krb5_err.c:171 +msgid "Clock skew too great in KDC reply" +msgstr "Zeitversatz in der KDC-Antwort zu groß" + +#: ../lib/krb5/error_tables/krb5_err.c:172 +msgid "Client/server realm mismatch in initial ticket request" +msgstr "" +"Client-/Server-Realm passen in der anfänglichen Ticketanfrage nicht zusammen." + +#: ../lib/krb5/error_tables/krb5_err.c:173 +msgid "Program lacks support for encryption type" +msgstr "" +"Dem Programm fehlt es an der Unterstützung für den Verschlüsselungstyp." + +#: ../lib/krb5/error_tables/krb5_err.c:174 +msgid "Program lacks support for key type" +msgstr "Dem Programm fehlt es an der Unterstützung für den Schlüsseltyp." + +#: ../lib/krb5/error_tables/krb5_err.c:175 +msgid "Requested encryption type not used in message" +msgstr "" +"Der angeforderte Verschlüsselungstyp wird in der Nachricht nicht verwendet." + +#: ../lib/krb5/error_tables/krb5_err.c:176 +msgid "Program lacks support for checksum type" +msgstr "Dem Programm fehlt es an der Unterstützung für den Prüfsummentyp." + +#: ../lib/krb5/error_tables/krb5_err.c:177 +msgid "Cannot find KDC for requested realm" +msgstr "KDC für angeforderten Realm kann nicht gefunden werden" + +#: ../lib/krb5/error_tables/krb5_err.c:178 +msgid "Kerberos service unknown" +msgstr "Kerberos-Dienst unbekannt" + +#: ../lib/krb5/error_tables/krb5_err.c:179 +msgid "Cannot contact any KDC for requested realm" +msgstr "Für den angeforderten Realm kann kein KDC kontaktiert werden." + +#: ../lib/krb5/error_tables/krb5_err.c:180 +msgid "No local name found for principal name" +msgstr "Für den Principal-Namen wurde kein lokaler Name gefunden." + +#: ../lib/krb5/error_tables/krb5_err.c:182 +msgid "Replay cache type is already registered" +msgstr "Wiederholungszwischenspeichertyp ist bereits registriert" + +#: ../lib/krb5/error_tables/krb5_err.c:183 +msgid "No more memory to allocate (in replay cache code)" +msgstr "" +"kein Speicher mehr zu reservieren (im Wiederholungszwischenspeichercode)" + +#: ../lib/krb5/error_tables/krb5_err.c:184 +msgid "Replay cache type is unknown" +msgstr "Wiederholungszwischenspeichertyp ist unbekannt" + +#: ../lib/krb5/error_tables/krb5_err.c:185 +msgid "Generic unknown RC error" +msgstr "allgemeiner unbekannter Wiederholungszwischenspeicherfehler" + +#: ../lib/krb5/error_tables/krb5_err.c:186 +msgid "Message is a replay" +msgstr "Nachricht ist eine Wiederholung" + +#: ../lib/krb5/error_tables/krb5_err.c:187 +msgid "Replay cache I/O operation failed" +msgstr "Wiederholungszwischenspeicher-E/A-Aktion fehlgeschlagen" + +#: ../lib/krb5/error_tables/krb5_err.c:188 +msgid "Replay cache type does not support non-volatile storage" +msgstr "" +"Wiederholungszwischenspeichertyp unterstützt keinen beständigen Speicher" + +#: ../lib/krb5/error_tables/krb5_err.c:189 +msgid "Replay cache name parse/format error" +msgstr "Auswerte-/Formatfehler im Wiederholungszwischenspeichernamens" + +#: ../lib/krb5/error_tables/krb5_err.c:190 +msgid "End-of-file on replay cache I/O" +msgstr "Dateiende bei der E/A des Wiederholungszwischenspeichers" + +#: ../lib/krb5/error_tables/krb5_err.c:191 +msgid "No more memory to allocate (in replay cache I/O code)" +msgstr "" +"kein weiterer Speicher reservierbar (im Wiederholungszwischenspeicher-E/A-" +"Code)" + +#: ../lib/krb5/error_tables/krb5_err.c:192 +msgid "Permission denied in replay cache code" +msgstr "Zugriff im Wiederholungszwischenspeichercode verweigert" + +#: ../lib/krb5/error_tables/krb5_err.c:193 +msgid "I/O error in replay cache i/o code" +msgstr "E/A-Fehler im Wiederholungszwischenspeicher-E/A-Code" + +#: ../lib/krb5/error_tables/krb5_err.c:194 +msgid "Generic unknown RC/IO error" +msgstr "allgemeiner unbekannter Wiederholungszwischenspeicher-/E/A-Fehler" + +#: ../lib/krb5/error_tables/krb5_err.c:195 +msgid "Insufficient system space to store replay information" +msgstr "" +"Platz im System reicht nicht zum Speichern der Wiederholungsinformationen" + +#: ../lib/krb5/error_tables/krb5_err.c:196 +msgid "Can't open/find realm translation file" +msgstr "Realm-Übersetzungsdatei kann nicht geöffnet/gefunden werden" + +#: ../lib/krb5/error_tables/krb5_err.c:197 +msgid "Improper format of realm translation file" +msgstr "Format der Realm-Übersetzungsdatei ist ungeeignet" + +#: ../lib/krb5/error_tables/krb5_err.c:198 +msgid "Can't open/find lname translation database" +msgstr "die Lname-Übersetzungsdatenbank kann nicht geöffnet/gefunden werden" + +#: ../lib/krb5/error_tables/krb5_err.c:199 +msgid "No translation available for requested principal" +msgstr "Für den angeforderten Principal ist keine Übersetzung verfügbar." + +#: ../lib/krb5/error_tables/krb5_err.c:200 +msgid "Improper format of translation database entry" +msgstr "Format des Eintrags der Übersetzungsdatenbank ist ungeeignet" + +#: ../lib/krb5/error_tables/krb5_err.c:201 +msgid "Cryptosystem internal error" +msgstr "interner Fehler des Verschlüsselungssystems" + +#: ../lib/krb5/error_tables/krb5_err.c:202 +msgid "Key table name malformed" +msgstr "falsche Form des Schlüsseltabellennamens" + +#: ../lib/krb5/error_tables/krb5_err.c:203 +msgid "Unknown Key table type" +msgstr "unbekannter Schlüsseltabellentyp" + +#: ../lib/krb5/error_tables/krb5_err.c:204 +msgid "Key table entry not found" +msgstr "Schlüsseltabelleneintrag nicht gefunden" + +#: ../lib/krb5/error_tables/krb5_err.c:205 +msgid "End of key table reached" +msgstr "Ende der Schlüsseltabelle erreicht" + +#: ../lib/krb5/error_tables/krb5_err.c:206 +msgid "Cannot write to specified key table" +msgstr "in angegebene Schlüsseltabelle kann nicht geschrieben werden" + +#: ../lib/krb5/error_tables/krb5_err.c:207 +msgid "Error writing to key table" +msgstr "Fehler beim Schreiben in Schlüsseltabelle" + +#: ../lib/krb5/error_tables/krb5_err.c:208 +msgid "Cannot find ticket for requested realm" +msgstr "Ticket für angeforderten Realm kann nicht gefunden werden" + +#: ../lib/krb5/error_tables/krb5_err.c:209 +msgid "DES key has bad parity" +msgstr "DES-Schlüssel hat falsche Parität" + +#: ../lib/krb5/error_tables/krb5_err.c:210 +msgid "DES key is a weak key" +msgstr "DES-Schlüssel ist schwach" + +#: ../lib/krb5/error_tables/krb5_err.c:211 +msgid "Bad encryption type" +msgstr "falscher Verschlüsselungstyp" + +#: ../lib/krb5/error_tables/krb5_err.c:212 +msgid "Key size is incompatible with encryption type" +msgstr "Schlüssellänge ist nicht mit dem Verschlüsselungstyp kompatibel" + +#: ../lib/krb5/error_tables/krb5_err.c:213 +msgid "Message size is incompatible with encryption type" +msgstr "Nachrichtengröße ist nicht mit Verschlüsselungstyp kompatibel" + +#: ../lib/krb5/error_tables/krb5_err.c:214 +msgid "Credentials cache type is already registered." +msgstr "Anmeldedatenzwischenspeichertyp ist bereits registriert" + +#: ../lib/krb5/error_tables/krb5_err.c:215 +msgid "Key table type is already registered." +msgstr "Schlüsseltabellentyp ist bereits registriert" + +#: ../lib/krb5/error_tables/krb5_err.c:216 +msgid "Credentials cache I/O operation failed XXX" +msgstr "E/A-Aktion für Anmeldedatenzwischenspeicher fehlgeschlagen XXX" + +#: ../lib/krb5/error_tables/krb5_err.c:217 +msgid "Credentials cache permissions incorrect" +msgstr "Anmeldedatenzwischenspeicherrechte nicht korrekt" + +#: ../lib/krb5/error_tables/krb5_err.c:218 +msgid "No credentials cache found" +msgstr "kein Anmeldedatenzwischenspeicher gefunden" + +#: ../lib/krb5/error_tables/krb5_err.c:219 +msgid "Internal credentials cache error" +msgstr "interner Anmeldedatenzwischenspeicherfehler" + +#: ../lib/krb5/error_tables/krb5_err.c:220 +msgid "Error writing to credentials cache" +msgstr "Fehler beim Schreiben in den Anmeldedatenzwischenspeicher" + +#: ../lib/krb5/error_tables/krb5_err.c:221 +msgid "No more memory to allocate (in credentials cache code)" +msgstr "" +"kein weiterer Speicher zu reservieren (im Anmeldedatenzwischenspeichercode)" + +#: ../lib/krb5/error_tables/krb5_err.c:222 +msgid "Bad format in credentials cache" +msgstr "falsches Format im Anmeldedatenzwischenspeicher" + +#: ../lib/krb5/error_tables/krb5_err.c:223 +msgid "No credentials found with supported encryption types" +msgstr "keine Anmeldedaten mit unterstützten Verschlüsselungstypen gefunden" + +#: ../lib/krb5/error_tables/krb5_err.c:224 +msgid "Invalid KDC option combination (library internal error)" +msgstr "ungültige Kombination von KDC-Optionen (interner Bibliotheksfehler)" + +#: ../lib/krb5/error_tables/krb5_err.c:225 +msgid "Request missing second ticket" +msgstr "Der Anfrage fehlt das zweite Ticket." + +#: ../lib/krb5/error_tables/krb5_err.c:226 +msgid "No credentials supplied to library routine" +msgstr "der Bibliotheks-Routine wurden keine Anmeldedaten geliefert" + +#: ../lib/krb5/error_tables/krb5_err.c:227 +msgid "Bad sendauth version was sent" +msgstr "Es wurde eine falsche Sendauth-Version verschickt" + +#: ../lib/krb5/error_tables/krb5_err.c:228 +msgid "Bad application version was sent (via sendauth)" +msgstr "Es wurde eine falsche Anwendungsversion (über Sendauth) verschickt" + +#: ../lib/krb5/error_tables/krb5_err.c:229 +msgid "Bad response (during sendauth exchange)" +msgstr "falsche Antwort (beim Sendauth-Austausch)" + +#: ../lib/krb5/error_tables/krb5_err.c:230 +msgid "Server rejected authentication (during sendauth exchange)" +msgstr "Server wies Authentifizierung (beim Sendauth-Austausch) zurück" + +#: ../lib/krb5/error_tables/krb5_err.c:231 +msgid "Unsupported preauthentication type" +msgstr "nicht unterstützter Vorauthentifizierungstyp" + +#: ../lib/krb5/error_tables/krb5_err.c:232 +msgid "Required preauthentication key not supplied" +msgstr "erforderlicher Vorauthentifizierungsschlüssel nicht bereitgestellt" + +#: ../lib/krb5/error_tables/krb5_err.c:233 +msgid "Generic preauthentication failure" +msgstr "allgemeiner Fehlschlag der Vorauthentifizierung" + +#: ../lib/krb5/error_tables/krb5_err.c:234 +msgid "Unsupported replay cache format version number" +msgstr "" +"nicht unterstütztes Versionsnummernformat des Wiederholungszwischenspeichers" + +#: ../lib/krb5/error_tables/krb5_err.c:235 +msgid "Unsupported credentials cache format version number" +msgstr "" +"nicht unterstütztes Versionsnummernformat des Anmeldedatenzwischenspeichers" + +#: ../lib/krb5/error_tables/krb5_err.c:236 +msgid "Unsupported key table format version number" +msgstr "nicht unterstütztes Versionsnummernformat der Schlüsseltabelle" + +#: ../lib/krb5/error_tables/krb5_err.c:237 +msgid "Program lacks support for address type" +msgstr "Dem Programm fehlt es an der Unterstützung des Adresstyps." + +#: ../lib/krb5/error_tables/krb5_err.c:238 +msgid "Message replay detection requires rcache parameter" +msgstr "Erkennung der Antwortnachricht erfordert den Parameter »rcache«" + +#: ../lib/krb5/error_tables/krb5_err.c:239 +msgid "Hostname cannot be canonicalized" +msgstr "Rechnername kann nicht in Normalform gebracht werden" + +#: ../lib/krb5/error_tables/krb5_err.c:240 +msgid "Cannot determine realm for host" +msgstr "Realm für Rechner kann nicht bestimmt werden" + +#: ../lib/krb5/error_tables/krb5_err.c:241 +msgid "Conversion to service principal undefined for name type" +msgstr "Umwandlung in Dienst-Principal für Namenstyp nicht definiert" + +#: ../lib/krb5/error_tables/krb5_err.c:242 +msgid "Initial Ticket response appears to be Version 4 error" +msgstr "anfängliche Ticket-Antwort scheint ein Fehler der Version 4 zu sein" + +#: ../lib/krb5/error_tables/krb5_err.c:243 +msgid "Cannot resolve network address for KDC in requested realm" +msgstr "" +"Netzwerkadresse für KDC im angeforderten Realm kann nicht aufgelöst werden" + +#: ../lib/krb5/error_tables/krb5_err.c:244 +msgid "Requesting ticket can't get forwardable tickets" +msgstr "anforderndes Ticket kann keine weiterleitbaren Tickets holen" + +#: ../lib/krb5/error_tables/krb5_err.c:245 +msgid "Bad principal name while trying to forward credentials" +msgstr "falscher Principal beim Versuch, Anmeldedaten weiterzuleiten" + +#: ../lib/krb5/error_tables/krb5_err.c:246 +msgid "Looping detected inside krb5_get_in_tkt" +msgstr "Schleife innerhalb von »krb5_get_in_tkt« entdeckt" + +#: ../lib/krb5/error_tables/krb5_err.c:247 +msgid "Configuration file does not specify default realm" +msgstr "Konfigurationsdatei gibt keinen Standard-Realm an" + +#: ../lib/krb5/error_tables/krb5_err.c:248 +msgid "Bad SAM flags in obtain_sam_padata" +msgstr "falsche SAM-Schalter in »obtain_sam_padata«" + +#: ../lib/krb5/error_tables/krb5_err.c:249 +msgid "Invalid encryption type in SAM challenge" +msgstr "ungültiger Verschlüsselungstyp in der SAM-Aufforderung" + +#: ../lib/krb5/error_tables/krb5_err.c:250 +msgid "Missing checksum in SAM challenge" +msgstr "fehlende Prüfsumme in der SAM-Aufforderung" + +#: ../lib/krb5/error_tables/krb5_err.c:251 +msgid "Bad checksum in SAM challenge" +msgstr "falsche Prüfsumme in der SAM-Aufforderung" + +#: ../lib/krb5/error_tables/krb5_err.c:252 +msgid "Keytab name too long" +msgstr "Schlüsseltabellennamen zu lang" + +#: ../lib/krb5/error_tables/krb5_err.c:253 +msgid "Key version number for principal in key table is incorrect" +msgstr "" +"Schlüsselversionsnummer des Principals in der Schlüsseltabelle ist nicht " +"korrekt" + +#: ../lib/krb5/error_tables/krb5_err.c:254 +msgid "This application has expired" +msgstr "Diese Anwendung ist abgelaufen." + +#: ../lib/krb5/error_tables/krb5_err.c:255 +msgid "This Krb5 library has expired" +msgstr "Diese Krb5-Bibliothek ist abgelaufen." + +#: ../lib/krb5/error_tables/krb5_err.c:256 +msgid "New password cannot be zero length" +msgstr "Das neue Passwort kann nicht die Länge Null haben." + +#: ../lib/krb5/error_tables/krb5_err.c:258 +msgid "Bad format in keytab" +msgstr "falsches Format in der Schlüsseltabelle" + +#: ../lib/krb5/error_tables/krb5_err.c:259 +msgid "Encryption type not permitted" +msgstr "Verschlüsselungstyp nicht erlaubt" + +#: ../lib/krb5/error_tables/krb5_err.c:260 +msgid "No supported encryption types (config file error?)" +msgstr "" +"keine unterstützten Verschlüsselungstypen (Fehler in der " +"Konfigurationsdatei?)" + +#: ../lib/krb5/error_tables/krb5_err.c:261 +msgid "Program called an obsolete, deleted function" +msgstr "Das Programm rief eine veraltete, gelöschte Funktion auf." + +#: ../lib/krb5/error_tables/krb5_err.c:262 +msgid "unknown getaddrinfo failure" +msgstr "unbekannter Getaddrinfo-Fehlschlag" + +#: ../lib/krb5/error_tables/krb5_err.c:263 +msgid "no data available for host/domain name" +msgstr "keine Daten für Rechner/Domain-Namen verfügbar" + +#: ../lib/krb5/error_tables/krb5_err.c:264 +msgid "host/domain name not found" +msgstr "Rechner/Domain-Name nicht gefunden" + +#: ../lib/krb5/error_tables/krb5_err.c:265 +msgid "service name unknown" +msgstr "Dienstname unbekannt" + +#: ../lib/krb5/error_tables/krb5_err.c:266 +msgid "Cannot determine realm for numeric host address" +msgstr "Realm für numerische Rechneradresse kann nicht bestimmt werden" + +#: ../lib/krb5/error_tables/krb5_err.c:267 +msgid "Invalid key generation parameters from KDC" +msgstr "ungültige Parameter zum Erzeugen von Schlüsseln vom KDC" + +#: ../lib/krb5/error_tables/krb5_err.c:268 +msgid "service not available" +msgstr "Dienst nicht verfügbar" + +#: ../lib/krb5/error_tables/krb5_err.c:269 +msgid "Ccache function not supported: read-only ccache type" +msgstr "Ccache-Funktion nicht unterstützt: Ccache-Typ nur lesbar" + +#: ../lib/krb5/error_tables/krb5_err.c:270 +msgid "Ccache function not supported: not implemented" +msgstr "Ccache-Funktion nicht unterstützt: nicht implementiert" + +#: ../lib/krb5/error_tables/krb5_err.c:271 +msgid "Invalid format of Kerberos lifetime or clock skew string" +msgstr "" +"ungültiges Format der Kerberos-Lebensdauer oder der Zeitversatzzeichenkette" + +#: ../lib/krb5/error_tables/krb5_err.c:272 +msgid "Supplied data not handled by this plugin" +msgstr "" +"Die bereitgestellten Daten werden nicht von dieser Erweiterung behandelt." + +#: ../lib/krb5/error_tables/krb5_err.c:273 +msgid "Plugin does not support the operation" +msgstr "Erweiterung unterstützt diese Aktion nicht" + +#: ../lib/krb5/error_tables/krb5_err.c:274 +msgid "Invalid UTF-8 string" +msgstr "ungültige UTF-8-Zeichenkette" + +#: ../lib/krb5/error_tables/krb5_err.c:275 +msgid "FAST protected pre-authentication required but not supported by KDC" +msgstr "" +"FAST-geschützte Vorauthentifizierung erforderlich, aber nicht vom KDC " +"unterstützt" + +#: ../lib/krb5/error_tables/krb5_err.c:276 +msgid "Auth context must contain local address" +msgstr "Authentifizierungskontext muss lokale Adresse enthalten" + +#: ../lib/krb5/error_tables/krb5_err.c:277 +msgid "Auth context must contain remote address" +msgstr "Authentifizierungskontext muss ferne Adresse enthalten" + +#: ../lib/krb5/error_tables/krb5_err.c:278 +msgid "Tracing unsupported" +msgstr "Verfolgung nicht unterstützt" + +#: ../lib/krb5/error_tables/kdb5_err.c:24 +msgid "Entry already exists in database" +msgstr "Eintrag existiert bereits in der Datenbank" + +#: ../lib/krb5/error_tables/kdb5_err.c:25 +msgid "Database store error" +msgstr "Datenbank-Speicherfehler" + +#: ../lib/krb5/error_tables/kdb5_err.c:26 +msgid "Database read error" +msgstr "Datenbank-Lesefehler" + +#: ../lib/krb5/error_tables/kdb5_err.c:27 +msgid "Insufficient access to perform requested operation" +msgstr "Zugriffsrechte reichen nicht zur Durchführung der angeforderten Aktion" + +#: ../lib/krb5/error_tables/kdb5_err.c:28 +msgid "No such entry in the database" +msgstr "kein derartiger Eintrag in der Datenbank" + +#: ../lib/krb5/error_tables/kdb5_err.c:29 +msgid "Illegal use of wildcard" +msgstr "ungültige Verwendung eines Platzhalters" + +#: ../lib/krb5/error_tables/kdb5_err.c:30 +msgid "Database is locked or in use--try again later" +msgstr "" +"Datenbank ist gesperrt oder wird gerade benutzt – versuchen Sie es später " +"wieder" + +#: ../lib/krb5/error_tables/kdb5_err.c:31 +msgid "Database was modified during read" +msgstr "Datenbank wurde während des Lesens geändert" + +#: ../lib/krb5/error_tables/kdb5_err.c:32 +msgid "Database record is incomplete or corrupted" +msgstr "Datensatz ist unvollständig oder beschädigt" + +#: ../lib/krb5/error_tables/kdb5_err.c:33 +msgid "Attempt to lock database twice" +msgstr "Es wurde zweimal versucht, die Datenbank zu sperren." + +#: ../lib/krb5/error_tables/kdb5_err.c:34 +msgid "Attempt to unlock database when not locked" +msgstr "" +"Es wurde versucht, die Datenbank zu entsperren, obwohl sie nicht gesperrt " +"ist." + +#: ../lib/krb5/error_tables/kdb5_err.c:35 +msgid "Invalid kdb lock mode" +msgstr "ungültiger KDB-Sperrmodus" + +#: ../lib/krb5/error_tables/kdb5_err.c:36 +msgid "Database has not been initialized" +msgstr "Datenbank wurde nicht initialisiert" + +#: ../lib/krb5/error_tables/kdb5_err.c:37 +msgid "Database has already been initialized" +msgstr "Datenbank wurde bereits initialisiert" + +#: ../lib/krb5/error_tables/kdb5_err.c:38 +msgid "Bad direction for converting keys" +msgstr "falsche Richtung zum Umwandeln von Schlüsseln" + +#: ../lib/krb5/error_tables/kdb5_err.c:39 +msgid "Cannot find master key record in database" +msgstr "Hauptschlüsseldatensatz kann nicht in der Datenbank gefunden werden" + +#: ../lib/krb5/error_tables/kdb5_err.c:40 +msgid "Master key does not match database" +msgstr "Hauptschlüssel passt nicht zur Datenbank" + +#: ../lib/krb5/error_tables/kdb5_err.c:41 +msgid "Key size in database is invalid" +msgstr "Die Schlüssellänge in der Datenbank ist ungültig," + +#: ../lib/krb5/error_tables/kdb5_err.c:42 +msgid "Cannot find/read stored master key" +msgstr "Der gespeicherte Hauptschlüssel kann nicht gefunden/gelesen werden." + +#: ../lib/krb5/error_tables/kdb5_err.c:43 +msgid "Stored master key is corrupted" +msgstr "Der gespeicherte Hauptschlüssel ist beschädigt." + +#: ../lib/krb5/error_tables/kdb5_err.c:44 +msgid "Cannot find active master key" +msgstr "Der aktive Hauptschlüssel kann nicht gefunden werden." + +#: ../lib/krb5/error_tables/kdb5_err.c:45 +msgid "KVNO of new master key does not match expected value" +msgstr "KVNO des neuen Hauptschlüssels passt nicht zum erwarteten Wert" + +#: ../lib/krb5/error_tables/kdb5_err.c:46 +msgid "Stored master key is not current" +msgstr "gespeicherter Hauptschlüssel ist nicht aktuell" + +#: ../lib/krb5/error_tables/kdb5_err.c:47 +msgid "Insufficient access to lock database" +msgstr "keine ausreichenden Zugriffsrechte zum Sperren der Datenbank" + +#: ../lib/krb5/error_tables/kdb5_err.c:48 +msgid "Database format error" +msgstr "fehlerhaftes Datenbankformat" + +#: ../lib/krb5/error_tables/kdb5_err.c:49 +msgid "Unsupported version in database entry" +msgstr "nicht unterstützte Version im Datenbankeintrag" + +#: ../lib/krb5/error_tables/kdb5_err.c:50 +msgid "Unsupported salt type" +msgstr "nicht unterstützter Salt-Typ" + +#: ../lib/krb5/error_tables/kdb5_err.c:51 +msgid "Unsupported encryption type" +msgstr "nicht unterstützter Verschlüsselungstyp" + +#: ../lib/krb5/error_tables/kdb5_err.c:52 +msgid "Bad database creation flags" +msgstr "falsche Schalter zum Erstellen der Datenbank" + +#: ../lib/krb5/error_tables/kdb5_err.c:53 +msgid "No matching key in entry having a permitted enctype" +msgstr "" +"kein passender Schlüssel in einem Eintrag mit erlaubtem Verschlüsselungstyp" + +#: ../lib/krb5/error_tables/kdb5_err.c:54 +msgid "No matching key in entry" +msgstr "kein passender Schlüssel im Eintrag" + +#: ../lib/krb5/error_tables/kdb5_err.c:55 +msgid "Unable to find requested database type" +msgstr "angeforderter Datenbanktyp kann nicht gefunden werden" + +#: ../lib/krb5/error_tables/kdb5_err.c:56 +msgid "Database type not supported" +msgstr "Datenbanktyp nicht unterstützt" + +#: ../lib/krb5/error_tables/kdb5_err.c:57 +msgid "Database library failed to initialize" +msgstr "Initialisieren der Datenbankbibliothek fehlgeschlagen" + +#: ../lib/krb5/error_tables/kdb5_err.c:59 +msgid "Unable to access Kerberos database" +msgstr "auf die Kerberos-Datenbank kann nicht zugegriffen werden" + +#: ../lib/krb5/error_tables/kdb5_err.c:60 +msgid "Kerberos database internal error" +msgstr "interner Kerberos-Datenbankfehler" + +#: ../lib/krb5/error_tables/kdb5_err.c:61 +msgid "Kerberos database constraints violated" +msgstr "Kerberos-Datenbankbeschränkungen verletzt" + +#: ../lib/krb5/error_tables/kdb5_err.c:62 +msgid "Update log conversion error" +msgstr "Fehler beim Umwandeln des Aktualisierungsprotokolls" + +#: ../lib/krb5/error_tables/kdb5_err.c:63 +msgid "Update log is unstable" +msgstr "Aktualisierungsprotokoll ist instabil" + +#: ../lib/krb5/error_tables/kdb5_err.c:64 +msgid "Update log is corrupt" +msgstr "Aktualisierungsprotokoll ist beschädigt" + +#: ../lib/krb5/error_tables/kdb5_err.c:65 +msgid "Generic update log error" +msgstr "allgemeiner Aktualisierungsprotokollfehler" + +#: ../lib/krb5/error_tables/kdb5_err.c:66 +msgid "Database module does not match KDC version" +msgstr "Datenbankmodul passt nicht zur KDC-Version" + +#: ../lib/krb5/error_tables/kdb5_err.c:68 +msgid "Too much string mapping data" +msgstr "zu viele zeichenkettenabbildenden Daten" + +#: ../lib/krb5/error_tables/asn1_err.c:23 +msgid "ASN.1 failed call to system time library" +msgstr "ASN.1 beim Aufruf der Systemzeitbibliothek gescheitert" + +#: ../lib/krb5/error_tables/asn1_err.c:24 +msgid "ASN.1 structure is missing a required field" +msgstr "ein erforderliches Feld fehlt in der ASN.1-Struktur" + +#: ../lib/krb5/error_tables/asn1_err.c:25 +msgid "ASN.1 unexpected field number" +msgstr "ASN.1 unerwartete Feldnummer" + +#: ../lib/krb5/error_tables/asn1_err.c:26 +msgid "ASN.1 type numbers are inconsistent" +msgstr "ASN.1-Typnummern sind inkonsistent" + +#: ../lib/krb5/error_tables/asn1_err.c:27 +msgid "ASN.1 value too large" +msgstr "ASN.1-Wert zu groß" + +#: ../lib/krb5/error_tables/asn1_err.c:28 +msgid "ASN.1 encoding ended unexpectedly" +msgstr "ASN.1-Kodierung endete unerwartet" + +#: ../lib/krb5/error_tables/asn1_err.c:29 +msgid "ASN.1 identifier doesn't match expected value" +msgstr "ASN.1-Bezeichner passt nicht zum erwarteten Wert" + +#: ../lib/krb5/error_tables/asn1_err.c:30 +msgid "ASN.1 length doesn't match expected value" +msgstr "Länge von ASN.1 passt nicht zum erwarteten Wert" + +#: ../lib/krb5/error_tables/asn1_err.c:31 +msgid "ASN.1 badly-formatted encoding" +msgstr "fehlerhaft formatierte ASN.1-Kodierung" + +#: ../lib/krb5/error_tables/asn1_err.c:32 +msgid "ASN.1 parse error" +msgstr "ASN.1-Auswertungsfehler" + +#: ../lib/krb5/error_tables/asn1_err.c:33 +msgid "ASN.1 bad return from gmtime" +msgstr "ASN.1 falscher Rückgabewert von Gmtime" + +#: ../lib/krb5/error_tables/asn1_err.c:34 +msgid "ASN.1 non-constructed indefinite encoding" +msgstr "nicht konstruierte unbestimmte ASN.1-Kodierung" + +#: ../lib/krb5/error_tables/asn1_err.c:35 +msgid "ASN.1 missing expected EOC" +msgstr "ASN.1 fehlt erwartetes EOC" + +#: ../lib/krb5/error_tables/asn1_err.c:36 +msgid "ASN.1 object omitted in sequence" +msgstr "ASN.1-Objekt in Sequenz ausgelassen" + +#: ../lib/krb5/error_tables/kv5m_err.c:23 +msgid "Kerberos V5 magic number table" +msgstr "Tabelle magischer Zahlen von Kerberos V5" + +#: ../lib/krb5/error_tables/kv5m_err.c:24 +msgid "Bad magic number for krb5_principal structure" +msgstr "falsche magische Zahl für Krb5_principal-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:25 +msgid "Bad magic number for krb5_data structure" +msgstr "falsche magische Zahl für Krb5_data-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:26 +msgid "Bad magic number for krb5_keyblock structure" +msgstr "falsche magische Zahl für Krb5_krb5_keyblock-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:27 +msgid "Bad magic number for krb5_checksum structure" +msgstr "falsche magische Zahl für Krb5_krb5_checksum-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:28 +msgid "Bad magic number for krb5_encrypt_block structure" +msgstr "falsche magische Zahl für Krb5_encrypt_bloc-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:29 +msgid "Bad magic number for krb5_enc_data structure" +msgstr "falsche magische Zahl für Krb5_enc_data-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:30 +msgid "Bad magic number for krb5_cryptosystem_entry structure" +msgstr "falsche magische Zahl für Krb5_cryptosystem_entry-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:31 +msgid "Bad magic number for krb5_cs_table_entry structure" +msgstr "falsche magische Zahl für Krb5_cs_table_entry-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:32 +msgid "Bad magic number for krb5_checksum_entry structure" +msgstr "falsche magische Zahl für Krb5_checksum_entry-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:33 +msgid "Bad magic number for krb5_authdata structure" +msgstr "falsche magische Zahl für Krb5_authdata-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:34 +msgid "Bad magic number for krb5_transited structure" +msgstr "falsche magische Zahl für Krb5_transited-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:35 +msgid "Bad magic number for krb5_enc_tkt_part structure" +msgstr "falsche magische Zahl für Krb5_enc_tkt_part-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:36 +msgid "Bad magic number for krb5_ticket structure" +msgstr "falsche magische Zahl für Krb5_ticket-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:37 +msgid "Bad magic number for krb5_authenticator structure" +msgstr "falsche magische Zahl für Krb5_authenticator-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:38 +msgid "Bad magic number for krb5_tkt_authent structure" +msgstr "falsche magische Zahl für Krb5_tkt_authent-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:39 +msgid "Bad magic number for krb5_creds structure" +msgstr "falsche magische Zahl für Krb5_creds-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:40 +msgid "Bad magic number for krb5_last_req_entry structure" +msgstr "falsche magische Zahl für Krb5_last_req_entry-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:41 +msgid "Bad magic number for krb5_pa_data structure" +msgstr "falsche magische Zahl für Krb5_pa_data-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:42 +msgid "Bad magic number for krb5_kdc_req structure" +msgstr "falsche magische Zahl für Krb5_kdc_req-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:43 +msgid "Bad magic number for krb5_enc_kdc_rep_part structure" +msgstr "falsche magische Zahl für Krb5_enc_kdc_rep_part-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:44 +msgid "Bad magic number for krb5_kdc_rep structure" +msgstr "falsche magische Zahl für Krb5_kdc_rep-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:45 +msgid "Bad magic number for krb5_error structure" +msgstr "falsche magische Zahl für Krb5_error-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:46 +msgid "Bad magic number for krb5_ap_req structure" +msgstr "falsche magische Zahl für Krb5_ap_req-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:47 +msgid "Bad magic number for krb5_ap_rep structure" +msgstr "falsche magische Zahl für Krb5_ap_rep-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:48 +msgid "Bad magic number for krb5_ap_rep_enc_part structure" +msgstr "falsche magische Zahl für Krb5_ap_rep_enc_part-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:49 +msgid "Bad magic number for krb5_response structure" +msgstr "falsche magische Zahl für Krb5_response-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:50 +msgid "Bad magic number for krb5_safe structure" +msgstr "falsche magische Zahl für Krb5_safe-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:51 +msgid "Bad magic number for krb5_priv structure" +msgstr "falsche magische Zahl für Krb5_priv-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:52 +msgid "Bad magic number for krb5_priv_enc_part structure" +msgstr "falsche magische Zahl für Krb5_priv_enc_part-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:53 +msgid "Bad magic number for krb5_cred structure" +msgstr "falsche magische Zahl für Krb5_cred-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:54 +msgid "Bad magic number for krb5_cred_info structure" +msgstr "falsche magische Zahl für Krb5_cred_info-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:55 +msgid "Bad magic number for krb5_cred_enc_part structure" +msgstr "falsche magische Zahl für Krb5_cred_enc_part-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:56 +msgid "Bad magic number for krb5_pwd_data structure" +msgstr "falsche magische Zahl für Krb5_pwd_data-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:57 +msgid "Bad magic number for krb5_address structure" +msgstr "falsche magische Zahl für Krb5_address-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:58 +msgid "Bad magic number for krb5_keytab_entry structure" +msgstr "falsche magische Zahl für Krb5_keytab_entry-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:59 +msgid "Bad magic number for krb5_context structure" +msgstr "falsche magische Zahl für Krb5_context-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:60 +msgid "Bad magic number for krb5_os_context structure" +msgstr "falsche magische Zahl für Krb5_os_context-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:61 +msgid "Bad magic number for krb5_alt_method structure" +msgstr "falsche magische Zahl für Krb5_alt_method-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:62 +msgid "Bad magic number for krb5_etype_info_entry structure" +msgstr "falsche magische Zahl für Krb5_etype_info_entry-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:63 +msgid "Bad magic number for krb5_db_context structure" +msgstr "falsche magische Zahl für Krb5_db_context-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:64 +msgid "Bad magic number for krb5_auth_context structure" +msgstr "falsche magische Zahl für Krb5_auth_context-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:65 +msgid "Bad magic number for krb5_keytab structure" +msgstr "falsche magische Zahl für Krb5_keytab-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:66 +msgid "Bad magic number for krb5_rcache structure" +msgstr "falsche magische Zahl für Krb5_rcache-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:67 +msgid "Bad magic number for krb5_ccache structure" +msgstr "falsche magische Zahl für Krb5_ccache-Struktur" + +#: ../lib/krb5/error_tables/kv5m_err.c:68 +msgid "Bad magic number for krb5_preauth_ops" +msgstr "falsche magische Zahl für Krb5_preauth_ops" + +#: ../lib/krb5/error_tables/kv5m_err.c:69 +msgid "Bad magic number for krb5_sam_challenge" +msgstr "falsche magische Zahl für Krb5_sam_challenge" + +#: ../lib/krb5/error_tables/kv5m_err.c:70 +msgid "Bad magic number for krb5_sam_challenge_2" +msgstr "falsche magische Zahl für Krb5_sam_challenge_2" + +#: ../lib/krb5/error_tables/kv5m_err.c:71 +msgid "Bad magic number for krb5_sam_key" +msgstr "falsche magische Zahl für Krb5_sam_key" + +#: ../lib/krb5/error_tables/kv5m_err.c:72 +#: ../lib/krb5/error_tables/kv5m_err.c:73 +msgid "Bad magic number for krb5_enc_sam_response_enc" +msgstr "falsche magische Zahl für Krb5_enc_sam_response_enc" + +#: ../lib/krb5/error_tables/kv5m_err.c:74 +msgid "Bad magic number for krb5_sam_response" +msgstr "falsche magische Zahl für Krb5_sam_response" + +#: ../lib/krb5/error_tables/kv5m_err.c:75 +msgid "Bad magic number for krb5_sam_response 2" +msgstr "falsche magische Zahl für Krb5_sam_response 2" + +#: ../lib/krb5/error_tables/kv5m_err.c:76 +msgid "Bad magic number for krb5_predicted_sam_response" +msgstr "falsche magische Zahl für Krb5_predicted_sam_response" + +#: ../lib/krb5/error_tables/kv5m_err.c:77 +msgid "Bad magic number for passwd_phrase_element" +msgstr "falsche magische Zahl für Passwd_phrase_element" + +#: ../lib/krb5/error_tables/kv5m_err.c:78 +msgid "Bad magic number for GSSAPI OID" +msgstr "falsche magische Zahl für GSSAPI OID" + +#: ../lib/krb5/error_tables/kv5m_err.c:79 +msgid "Bad magic number for GSSAPI QUEUE" +msgstr "falsche magische Zahl für GSSAPI QUEUE" + +#: ../lib/krb5/error_tables/kv5m_err.c:80 +msgid "Bad magic number for fast armored request" +msgstr "falsche magische Zahl für per FAST geschützte Anfrage" + +#: ../lib/krb5/error_tables/kv5m_err.c:81 +msgid "Bad magic number for FAST request" +msgstr "falsche magische Zahl für FAST-Anfrage" + +#: ../lib/krb5/error_tables/kv5m_err.c:82 +msgid "Bad magic number for FAST response" +msgstr "falsche magische Zahl für FAST-Antwort" + +#: ../lib/krb5/error_tables/kv5m_err.c:83 +msgid "Bad magic number for krb5_authdata_context" +msgstr "falsche magische Zahl für Krb5_authdata_context" + +#: ../lib/krb5/error_tables/krb524_err.c:23 +msgid "Cannot convert V5 keyblock" +msgstr "V5-Schlüsselblock kann nicht umgewandelt werden" + +#: ../lib/krb5/error_tables/krb524_err.c:24 +msgid "Cannot convert V5 address information" +msgstr "V5-Adressinformationen können nicht umgewandelt werden" + +#: ../lib/krb5/error_tables/krb524_err.c:25 +msgid "Cannot convert V5 principal" +msgstr "V5-Principal kann nicht umgewandelt werden" + +#: ../lib/krb5/error_tables/krb524_err.c:26 +msgid "V5 realm name longer than V4 maximum" +msgstr "V5-Realm-Name ist länger als die V4-Maximallänge" + +#: ../lib/krb5/error_tables/krb524_err.c:27 +msgid "Kerberos V4 error" +msgstr "Kerberos-V4-Fehler" + +#: ../lib/krb5/error_tables/krb524_err.c:28 +msgid "Encoding too large" +msgstr "Kodierung zu lang" + +#: ../lib/krb5/error_tables/krb524_err.c:29 +msgid "Decoding out of data" +msgstr "Dekodieren außerhalb der Daten" + +#: ../lib/krb5/error_tables/krb524_err.c:30 +msgid "Service not responding" +msgstr "Dienst antwortet nicht" + +#: ../lib/krb5/error_tables/krb524_err.c:31 +msgid "Kerberos version 4 support is disabled" +msgstr "Kerberos 4 Unterstützung ist deaktiviert" + +#~ msgid "while creating server %s principal name" +#~ msgstr "beim Erstellen des Principal-Namens für Server %s" + +# KDC = Key Distribution Center +#~ msgid "while getting credentials from kdc" +#~ msgstr "beim Holen der Anmeldedaten vom KDC" + +# FIXME s/Retrieving/retrieving/ +#~ msgid "while Retrieving credentials" +#~ msgstr "beim Abfragen der Anmeldedaten" + +#~ msgid "while copying principal" +#~ msgstr "beim Kopieren des Principals" + +#~ msgid "%s does not have correct permissions for %s\n" +#~ msgstr "%s hat nicht die erforderlichen Zugriffsrechte für %s\n" + +#~ msgid "no salt\n" +#~ msgstr "kein Salt\n" + +#~ msgid "%s: Couldn't grab lock\n" +#~ msgstr "%s: Es konnte keine Sperre erlangt werden.\n" + +#~ msgid "%s: Loads disallowed when iprop is enabled and a ulog is present\n" +#~ msgstr "" +#~ "%s: Wenn Iprop aktiviert und Ulog vorhanden ist, ist Laden nicht " +#~ "möglich.\n" + +#~ msgid "trying to lock database" +#~ msgstr "es wird versucht, die Datenbank zu sperren" + +#~ msgid "GSS-API error %s: %s\n" +#~ msgstr "GSS-API-Fehler %s: %s\n" + +#~ msgid "Couldn't create KRB5 Name NameType OID\n" +#~ msgstr "KRB5 Name NameType OID konnte nicht erstellt werden.\n" + +#~ msgid "%s: %s while initializing, aborting" +#~ msgstr "%s: %s beim Initialisieren, wird abgebrochen" + +#~ msgid "" +#~ "%s: Missing required configuration values (%lx) while initializing, " +#~ "aborting" +#~ msgstr "" +#~ "%s: Beim Initialisieren fehlen die erforderlichen Konfigurationswerte " +#~ "(%lx), wird abgebrochen" + +#~ msgid "" +#~ "%s: Missing required configuration values (%lx) while initializing, " +#~ "aborting\n" +#~ msgstr "" +#~ "%s: Beim Initialisieren fehlen die erforderlichen Konfigurationswerte " +#~ "(%lx), wird abgebrochen\n" + +#~ msgid "%s: could not initialize loop, aborting" +#~ msgstr "%s: Schleife konnte nicht initialisiert werden, wird abgebrochen" + +#~ msgid "%s: could not initialize loop, aborting\n" +#~ msgstr "%s: Schleife konnte nicht initialisiert werden, wird abgebrochen\n" + +#~ msgid "%s: %s while initializing signal handlers, aborting" +#~ msgstr "" +#~ "%s: %s beim Initialisieren des Signalbehandlungsprogramms, wird " +#~ "abgebrochen" + +#~ msgid "%s: %s while initializing signal handlers, aborting\n" +#~ msgstr "" +#~ "%s: %s beim Initialisieren des Signalbehandlungsprogramms, wird " +#~ "abgebrochen\n" + +#~ msgid "%s: %s while initializing network, aborting" +#~ msgstr "%s: %s beim Initialisieren des Netzwerks, wird abgebrochen" + +#~ msgid "%s: %s while initializing network, aborting\n" +#~ msgstr "%s: %s beim Initialisieren des Netzwerks, wird abgebrochen\n" + +#~ msgid "Cannot build GSS-API authentication names, failing." +#~ msgstr "" +#~ "GSS-API-Authentifizierungsnamen können nicht gebildet werden, " +#~ "fehlgeschlagen" + +#~ msgid "Can't set kdb keytab's internal context." +#~ msgstr "" +#~ "Der interne Kontext von KDBs Schlüsseltabelle kann nicht gesetzt werden." + +#~ msgid "Can't register kdb keytab." +#~ msgstr "Die KDB-Schlüsseltabelle kann nicht registriert werden." + +#~ msgid "Can't register acceptor keytab." +#~ msgstr "Die Empfängerschlüsseltabelle kann nicht registriert werden." + +#~ msgid "" +#~ "Cannot set GSS-API authentication names (keytab not present?), failing." +#~ msgstr "" +#~ "GSS-API-Authentifizierungsnamen können nicht gesetzt werden " +#~ "(Schlüsseltabelle nicht vorhanden?), fehlgeschlagen" + +#~ msgid "Cannot initialize acl file: %s" +#~ msgstr "ACL-Datei kann nicht initialisiert werden: %s" + +#~ msgid "%s: Cannot initialize acl file: %s\n" +#~ msgstr "%s: ACL-Datei kann nicht initialisiert werden: %s\n" + +#~ msgid "Cannot detach from tty: %s" +#~ msgstr "kann nicht vom Terminal gelöst werden: %s" + +#~ msgid "Cannot create PID file %s: %s" +#~ msgstr "PID-Datei %s kann nicht erstellt werden: %s" + +#~ msgid "%s: %s while mapping update log (`%s.ulog')\n" +#~ msgstr "%s: %s beim Abbilden des Aktualisierungsprotokolls (»%s.ulog«)\n" + +#~ msgid "%s while mapping update log (`%s.ulog')" +#~ msgstr "%s beim Abbilden des Aktualisierungsprotokolls (»%s.ulog«)" + +#~ msgid "%s: Cannot create IProp RPC service (PROG=%d, VERS=%d)\n" +#~ msgstr "" +#~ "%s: IProp-RPC-Dienst kann nicht erstellt werden (PROG=%d, VERS=%d)\n" + +#~ msgid "Cannot create IProp RPC service (PROG=%d, VERS=%d), failing." +#~ msgstr "" +#~ "IProp-RPC-Dienst kann nicht erstellt werden (PROG=%d, VERS=%d), " +#~ "fehlgeschlagen" + +#~ msgid "%s while getting IProp svc name, failing" +#~ msgstr "%s beim Holen des IProp-Dienstnamens, fehlgeschlagen" + +#~ msgid "%s: %s while getting IProp svc name, failing\n" +#~ msgstr "%s: %s beim Holen des IProp-Dienstnamens, fehlgeschlagen\n" + +#~ msgid "Unable to set RPCSEC_GSS service name (`%s'), failing." +#~ msgstr "" +#~ "der RPCSEC_GSS-Dienstname (»%s«) kann nicht gesetzt werden, fehlgeschlagen" + +#~ msgid "%s: Unable to set RPCSEC_GSS service name (`%s'), failing.\n" +#~ msgstr "" +#~ "%s: der RPCSEC_GSS-Dienstname (»%s«) kann nicht gesetzt werden, " +#~ "fehlgeschlagen\n" + +#~ msgid "GSS-API authentication error %.*s: recursive failure!" +#~ msgstr "GSS-API-Authentifizierungsfehler %.*s: rekursiver Fehlschlag!" + +#~ msgid "skipping unrecognized local address family %d" +#~ msgstr "nicht erkannte lokale Adressfamilie %d wird übersprungen" + +#~ msgid "got routing msg type %d(%s) v%d" +#~ msgstr "Routing-Meldungstyp %d(%s) v%d erhalten" + +#~ msgid "Could not create temp stash file: %s" +#~ msgstr "Temporäre Ablagedatei konnte nicht erstellt werden: %s" + +#~ msgid "ulog_sync_header: could not sync to disk" +#~ msgstr "ulog_sync_header: kann nicht auf Platte sychronisiert werden" + +#~ msgid "%s: attempt to convert non-extended krb5_get_init_creds_opt" +#~ msgstr "" +#~ "%s: Es wird versucht, nicht erweiterte »krb5_get_init_creds_opt« " +#~ "umzuwandeln" + +#~ msgid "krb5_sname_to_principal, while adding entries to the database" +#~ msgstr "" +#~ "»krb5_sname_to_principal« beim Hinzufügen von Einträgen zur Datenbank" + +#~ msgid "krb5_copy_principal, while adding entries to the database" +#~ msgstr "»krb5_copy_principal« beim Hinzufügen von Einträgen zur Datenbank" + +#~ msgid "" +#~ "Unable to check if SASL EXTERNAL mechanism is supported by LDAP server. " +#~ "Proceeding anyway ..." +#~ msgstr "" +#~ "Es konnte nicht geprüft werden, ob der Mechanismus SASL EXTERNAL vom LDAP-" +#~ "Server unterstützt wird. Es wird trotzdem fortgesetzt …" + +#~ msgid "" +#~ "SASL EXTERNAL mechanism not supported by LDAP server. Can't perform " +#~ "certificate-based bind." +#~ msgstr "" +#~ "Der Mechanismus SASL EXTERNAL wird nicht vom LDAP-Server unterstützt. Es " +#~ "kann keine zertifikatbasierte Verbindung hergestellt werden." + +#~ msgid "Error reading 'ldap_servers' attribute" +#~ msgstr "Fehler beim Lesen des Attributs »ldap_servers«" + +#~ msgid "Stash file entry corrupt" +#~ msgstr "Eintrag in der Ablagedatei beschädigt" + +#~ msgid "while setting server principal realm" +#~ msgstr "beim Setzen des Server-Principal-Realms" + +#~ msgid "while getting initial ticket\n" +#~ msgstr "beim Holen eines Anfangs-Tickets\n" + +#~ msgid "while destroying ticket cache" +#~ msgstr "beim Zerstören des Ticket-Zwischenspeichers" + +#~ msgid "while closing default ccache" +#~ msgstr "beim Schließen des Standard-Ccaches" diff --git a/krb5-1.21.3/src/po/deps b/krb5-1.21.3/src/po/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/po/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/po/en_US.po b/krb5-1.21.3/src/po/en_US.po new file mode 100644 index 00000000..7e11d679 --- /dev/null +++ b/krb5-1.21.3/src/po/en_US.po @@ -0,0 +1,17 @@ +# English translations for Kerberos 5 package. +# Copyright (C) 2011 MIT +# This file is distributed under the same license as the Kerberos 5 package. +# Greg Hudson , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: mit-krb5 1.10-prerelease\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2011-06-06 00:34-0400\n" +"PO-Revision-Date: 2011-06-06 00:35-0400\n" +"Last-Translator: Greg Hudson \n" +"Language-Team: English\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" diff --git a/krb5-1.21.3/src/po/ka.po b/krb5-1.21.3/src/po/ka.po new file mode 100644 index 00000000..397d2416 --- /dev/null +++ b/krb5-1.21.3/src/po/ka.po @@ -0,0 +1,9188 @@ +# Georgian translation for Kerberos. +# Copyright (C) 2022 MIT +# This file is distributed under the same license as the mit-krb5 package. +# Temuri Doghonadze , 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: mit-krb5 1.21-prerelease\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-04-26 17:09-0400\n" +"PO-Revision-Date: 2022-11-09 08:11+0100\n" +"Last-Translator: Temuri Doghonadze \n" +"Language-Team: Georgian <(nothing)>\n" +"Language: ka\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 3.2\n" + +#: ../../src/clients/kdestroy/kdestroy.c:52 +#, c-format +msgid "Usage: %s [-A] [-q] [-c cache_name] [-p princ_name]\n" +msgstr "გამოყენება: %s [-A] [-q] [-c ქეშის_სახელი] [-p პრინც_სახელი]\n" + +#: ../../src/clients/kdestroy/kdestroy.c:54 +#, c-format +msgid "\t-A destroy all credential caches in collection\n" +msgstr "\t-A კოლექციაში ავტორიზაციის დეტალების ყველა ქეშის განადგურება\n" + +#: ../../src/clients/kdestroy/kdestroy.c:55 +#, c-format +msgid "\t-q quiet mode\n" +msgstr "\t-q ჩუმი რეჟიმი\n" + +#: ../../src/clients/kdestroy/kdestroy.c:56 +#: ../../src/clients/kswitch/kswitch.c:42 +#, c-format +msgid "\t-c specify name of credentials cache\n" +msgstr "\t-c ავტორიზაციის დეტალების ქეშის სახელის მითითება\n" + +#: ../../src/clients/kdestroy/kdestroy.c:57 +#, c-format +msgid "\t-p specify principal name within collection\n" +msgstr "\t-p კოლექციაში პრინციპალის სახელის მითითება \n" + +#: ../../src/clients/kdestroy/kdestroy.c:71 +#: ../../src/clients/kdestroy/kdestroy.c:165 +msgid "while listing credential caches" +msgstr "ავტორიზაციის დეტალების ქეშების ჩამოთვლისას" + +#: ../../src/clients/kdestroy/kdestroy.c:78 +#, c-format +msgid "Other credential caches present, use -A to destroy all\n" +msgstr "" +"არსებობს სხვა ავტორიზაიცის დეტალის ქეშებიც. გასანადგურებლად გამოიყენეთ -A\n" + +#: ../../src/clients/kdestroy/kdestroy.c:110 +#: ../../src/clients/kinit/kinit.c:332 ../../src/clients/ksu/main.c:296 +#, c-format +msgid "Only one -c option allowed\n" +msgstr "-c პარამეტრის მითითება ნებადართულია მხოლოდ ერთხელ\n" + +#: ../../src/clients/kdestroy/kdestroy.c:118 +#, c-format +msgid "Only one -p option allowed\n" +msgstr "-p პარამეტრის მითითება ნებადართულია მხოლოდ ერთხელ\n" + +#: ../../src/clients/kdestroy/kdestroy.c:125 +#: ../../src/clients/kinit/kinit.c:360 ../../src/clients/klist/klist.c:178 +#, c-format +msgid "Kerberos 4 is no longer supported\n" +msgstr "" +"Kerberos 4 უკვე მხარდაუჭერელია\n" +"\n" + +#: ../../src/clients/kdestroy/kdestroy.c:138 +#, c-format +msgid "-A option is exclusive with -p option\n" +msgstr "-A პარამეტრი ექსკლუზიურად -p -სთან ერთად უნდა იქნას გამოყენებული\n" + +#: ../../src/clients/kdestroy/kdestroy.c:150 +#: ../../src/clients/klist/klist.c:241 ../../src/clients/ksu/main.c:135 +#: ../../src/clients/ksu/main.c:141 ../../src/clients/kswitch/kswitch.c:94 +#: ../../src/kadmin/ktutil/ktutil.c:52 ../../src/kdc/main.c:929 +#: ../../src/kprop/kprop.c:103 ../../src/kprop/kpropd.c:1058 +msgid "while initializing krb5" +msgstr "krb5-ის ინიციალიზაციისას" + +#: ../../src/clients/kdestroy/kdestroy.c:157 +#: ../../src/clients/klist/klist.c:248 +msgid "while setting default cache name" +msgstr "ნაგულისხმები ქეშის სახელის დაყენებისას" + +#: ../../src/clients/kdestroy/kdestroy.c:172 +msgid "composing ccache name" +msgstr "ccache-ს სახელის შედგენა" + +#: ../../src/clients/kdestroy/kdestroy.c:177 +#, c-format +msgid "while destroying cache %s" +msgstr "ქეშის (%s) განადგურებისას" + +#: ../../src/clients/kdestroy/kdestroy.c:190 +#: ../../src/clients/kswitch/kswitch.c:107 ../../src/clients/kvno/kvno.c:311 +#: ../../src/clients/kvno/kvno.c:517 ../../src/kadmin/cli/keytab.c:373 +#: ../../src/kadmin/dbutil/kdb5_util.c:544 +#, c-format +msgid "while parsing principal name %s" +msgstr "პრინციპალის სახელის (%s) დამუშავებისას" + +#: ../../src/clients/kdestroy/kdestroy.c:196 +#, c-format +msgid "while finding cache for %s" +msgstr "%s-სთვის ქეშის ძებნისას" + +#: ../../src/clients/kdestroy/kdestroy.c:204 +#: ../../src/clients/klist/klist.c:462 +msgid "while resolving ccache" +msgstr "ccache-ის ამოხსნისას" + +#: ../../src/clients/kdestroy/kdestroy.c:211 ../../src/clients/ksu/main.c:1026 +msgid "while destroying cache" +msgstr "ქეშის განადგურებისას" + +#: ../../src/clients/kdestroy/kdestroy.c:214 +#, c-format +msgid "Ticket cache NOT destroyed!\n" +msgstr "ბილეთის ქეში არ განადგურებულა!\n" + +#: ../../src/clients/kdestroy/kdestroy.c:216 +#, c-format +msgid "Ticket cache %cNOT%c destroyed!\n" +msgstr "ბილეთის ქეში %cNOT%c განადგურებულა!\n" + +#: ../../src/clients/kinit/kinit.c:143 +#, c-format +msgid "" +"Usage: %s [-V] [-l lifetime] [-s start_time] [-r renewable_life]\n" +"\t[-f | -F] [-p | -P] [-n] [-a | -A] [-C] [-E]\n" +"\t[--request-pac | --no-request-pac]\n" +"\t[-v] [-R] [-k [-i|-t keytab_file]] [-c cachename]\n" +"\t[-S service_name] [-I input_ccache] [-T ticket_armor_cache]\n" +"\t[-X [=]] [principal]\n" +"\n" +msgstr "" +"Usage: %s [-V] [-l lifetime] [-s start_time] [-r renewable_life]\n" +"\t[-f | -F] [-p | -P] [-n] [-a | -A] [-C] [-E]\n" +"\t[--request-pac | --no-request-pac]\n" +"\t[-v] [-R] [-k [-i|-t keytab_ფაილი]] [-c ქეშისსახელი]\n" +"\t[-S სერვისის_სახელი] [-I შეყვანის_ccache] [-T ბილეთის_armor_cache]\n" +"\t[-X <ატრიბუტი>[=<მნიშვნელობა>]] [პრინციპალი]\n" +"\n" + +#: ../../src/clients/kinit/kinit.c:153 +#, c-format +msgid "\t-V verbose\n" +msgstr "\t-V დამატებითი შეტყობინებები\n" + +#: ../../src/clients/kinit/kinit.c:154 +#, c-format +msgid "\t-l lifetime\n" +msgstr "\t-l სიცოცხლისდრო\n" + +#: ../../src/clients/kinit/kinit.c:155 +#, c-format +msgid "\t-s start time\n" +msgstr "\t-s გაშვების დრო\n" + +#: ../../src/clients/kinit/kinit.c:156 +#, c-format +msgid "\t-r renewable lifetime\n" +msgstr "\t-r განახლებადი სიცოცხლის დრო\n" + +#: ../../src/clients/kinit/kinit.c:157 +#, c-format +msgid "\t-f forwardable\n" +msgstr "\t-f გადაგზავნადი\n" + +#: ../../src/clients/kinit/kinit.c:158 +#, c-format +msgid "\t-F not forwardable\n" +msgstr "\t-F არაგადაგზავნადი\n" + +#: ../../src/clients/kinit/kinit.c:159 +#, c-format +msgid "\t-p proxiable\n" +msgstr "\t-p პროქსირებადი\n" + +#: ../../src/clients/kinit/kinit.c:160 +#, c-format +msgid "\t-P not proxiable\n" +msgstr "\t-P არაპროქსირებადი\n" + +#: ../../src/clients/kinit/kinit.c:161 +#, c-format +msgid "\t-n anonymous\n" +msgstr "\t-n ანონიმური\n" + +#: ../../src/clients/kinit/kinit.c:162 +#, c-format +msgid "\t-a include addresses\n" +msgstr "\t-a მისამართების ჩათვლით\n" + +#: ../../src/clients/kinit/kinit.c:163 +#, c-format +msgid "\t-A do not include addresses\n" +msgstr "\t-A მისამართები არ ჩაითვლება\n" + +#: ../../src/clients/kinit/kinit.c:164 +#, c-format +msgid "\t-v validate\n" +msgstr "\t-v გადამოწმება\n" + +#: ../../src/clients/kinit/kinit.c:165 +#, c-format +msgid "\t-R renew\n" +msgstr "\t-R განახლება\n" + +#: ../../src/clients/kinit/kinit.c:166 +#, c-format +msgid "\t-C canonicalize\n" +msgstr "\t-C კანონიკალიზაცია\n" + +#: ../../src/clients/kinit/kinit.c:167 +#, c-format +msgid "\t-E client is enterprise principal name\n" +msgstr "\t-E კლიენტი საწარმოო პრინციპალის სახელია\n" + +#: ../../src/clients/kinit/kinit.c:168 +#, c-format +msgid "\t-k use keytab\n" +msgstr "\t-k keytab-ის გამოყენება\n" + +#: ../../src/clients/kinit/kinit.c:169 +#, c-format +msgid "\t-i use default client keytab (with -k)\n" +msgstr "\t-i კლიენტის ნაგულისხმები keytab -ის გამოყენება (-k-ით)\n" + +#: ../../src/clients/kinit/kinit.c:170 +#, c-format +msgid "\t-t filename of keytab to use\n" +msgstr "\t-t keytab -ის ფაილის სახელი\n" + +#: ../../src/clients/kinit/kinit.c:171 +#, c-format +msgid "\t-c Kerberos 5 cache name\n" +msgstr "\t-c Kerberos 5 -ის ქეშის სახელი\n" + +#: ../../src/clients/kinit/kinit.c:172 +#, c-format +msgid "\t-S service\n" +msgstr "\t-S სერვისი\n" + +#: ../../src/clients/kinit/kinit.c:173 +#, c-format +msgid "\t-I input credential cache\n" +msgstr "\t-I შეყვანის ავტორიზაციის დეტალების ქეში\n" + +#: ../../src/clients/kinit/kinit.c:174 +#, c-format +msgid "\t-T armor credential cache\n" +msgstr "\t-T აბჯრის ავტორიზაციის ქეში\n" + +#: ../../src/clients/kinit/kinit.c:175 +#, c-format +msgid "\t-X [=]\n" +msgstr "\t-X <ატრიბუტი>[=<მნიშვნელობა>]\n" + +#: ../../src/clients/kinit/kinit.c:177 +#, c-format +msgid "\t--{,no}-request-pac request KDC include/exclude a PAC\n" +msgstr "\t--{,no}-request-pac KDC -ში PAC -ის ჩასმა/ამოღების მოთხოვნა\n" + +#: ../../src/clients/kinit/kinit.c:250 ../../src/clients/kinit/kinit.c:258 +#, c-format +msgid "Bad lifetime value %s\n" +msgstr "სიცოცხლის დროის არასწორი მნიშვნელობა %s\n" + +#: ../../src/clients/kinit/kinit.c:292 +#, c-format +msgid "Bad start time value %s\n" +msgstr "დაწყების დროის არასწორი მნიშვნელობა %s\n" + +#: ../../src/clients/kinit/kinit.c:310 +#, c-format +msgid "Only one -t option allowed.\n" +msgstr "-t პარამეტრის მითითება ნებადართულია მხოლოდ ერთხელ\n" + +#: ../../src/clients/kinit/kinit.c:318 +#, c-format +msgid "Only one armor_ccache\n" +msgstr "მხოლოდ ერთი armor_ccache\n" + +#: ../../src/clients/kinit/kinit.c:340 +#, c-format +msgid "Only one -I option allowed\n" +msgstr "-l პარამეტრის მითითება ნებადართულია მხოლოდ ერთხელ\n" + +#: ../../src/clients/kinit/kinit.c:349 +msgid "while adding preauth option" +msgstr "preauth პარამეტრის დამატებისას" + +#: ../../src/clients/kinit/kinit.c:375 +#, c-format +msgid "Only one of -f and -F allowed\n" +msgstr "-f და -F პარამეტრებიდან მხოლოდ ერთ-ერთი მათგანის მითითება შეგიძლიათ\n" + +#: ../../src/clients/kinit/kinit.c:379 +#, c-format +msgid "Only one of -p and -P allowed\n" +msgstr "-p და -P პარამეტრებიდან მხოლოდ ერთი უნდა იყოს მითითებული\n" + +#: ../../src/clients/kinit/kinit.c:383 +#, c-format +msgid "Only one of --request-pac and --no-request-pac allowed\n" +msgstr "" +"--request-pac და --no-request-pac პარამეტრებიდან მხოლოდ ერთ-ერთი მათგანის " +"მითითება შეგიძლიათ\n" + +#: ../../src/clients/kinit/kinit.c:388 +#, c-format +msgid "Only one of -a and -A allowed\n" +msgstr "-a და -A პარამეტრებიდან მხოლოდ ერთ-ერთი მათგანის მითითება შეგიძლიათ\n" + +#: ../../src/clients/kinit/kinit.c:392 +#, c-format +msgid "Only one of -t and -i allowed\n" +msgstr "-t და -i პარამეტრებიდან მხოლოდ ერთ-ერთი მათგანის მითითება შეგიძლიათ\n" + +#: ../../src/clients/kinit/kinit.c:398 +#, c-format +msgid "keytab specified, forcing -k\n" +msgstr "keytab მითითებულია. -k ნაძალადევია\n" + +#: ../../src/clients/kinit/kinit.c:401 ../../src/clients/klist/klist.c:216 +#, c-format +msgid "Extra arguments (starting with \"%s\").\n" +msgstr "დამატებითი არგუმენტები (\"%s\"-ით დაწყებული).\n" + +#: ../../src/clients/kinit/kinit.c:427 +msgid "while initializing Kerberos 5 library" +msgstr "kerberos5 ბიბლიოთეკის ინიციალიზაციისას" + +#: ../../src/clients/kinit/kinit.c:435 ../../src/clients/kinit/kinit.c:578 +#, c-format +msgid "resolving ccache %s" +msgstr "ccache-ის (%s) ამოხსნა" + +#: ../../src/clients/kinit/kinit.c:440 +#, c-format +msgid "Using specified cache: %s\n" +msgstr "გამოიყენება მითითებული ქეში: %s\n" + +#: ../../src/clients/kinit/kinit.c:448 +msgid "while getting default ccache" +msgstr "ნაგულისხმები ccache-ის მიღებისას" + +#: ../../src/clients/kinit/kinit.c:462 ../../src/clients/kinit/kinit.c:530 +#: ../../src/clients/kpasswd/kpasswd.c:30 ../../src/clients/ksu/main.c:249 +#, c-format +msgid "when parsing name %s" +msgstr "სახელის (%s) დამუშავებისას" + +#: ../../src/clients/kinit/kinit.c:470 ../../src/kadmin/dbutil/kdb5_util.c:309 +#: ../../src/kprop/kprop.c:157 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:395 +msgid "while getting default realm" +msgstr "ნაგულისხმები რეალმის მიღებისას" + +#: ../../src/clients/kinit/kinit.c:481 +msgid "while building principal" +msgstr "პრინციპალის აგებისას" + +#: ../../src/clients/kinit/kinit.c:489 +msgid "When resolving the default client keytab" +msgstr "ნაგულისხმები კლიენტის keytab-ის ამოხსნისას" + +#: ../../src/clients/kinit/kinit.c:496 +msgid "When determining client principal name from keytab" +msgstr "კლიენტის პრინციპალის keytab-დან დადგენისას" + +#: ../../src/clients/kinit/kinit.c:505 +msgid "when creating default server principal name" +msgstr "ნაგულისხმები სერვერის პრინციპალის სახელის შექმნისას" + +#: ../../src/clients/kinit/kinit.c:525 ../../src/clients/kpasswd/kpasswd.c:43 +#, c-format +msgid "Unable to identify user\n" +msgstr "მომხმარებლის იდენტიფიკაცია შეუძლებელია\n" + +#: ../../src/clients/kinit/kinit.c:539 ../../src/clients/kswitch/kswitch.c:113 +#, c-format +msgid "while searching for ccache for %s" +msgstr "ccache-ში %s-ის ძებნისას" + +#: ../../src/clients/kinit/kinit.c:545 +#, c-format +msgid "Using existing cache: %s\n" +msgstr "არსებული ქეშის გამოყენება: %s\n" + +#: ../../src/clients/kinit/kinit.c:554 +msgid "while generating new ccache" +msgstr "ახალი ccache-ის გენერირებისას" + +#: ../../src/clients/kinit/kinit.c:558 +#, c-format +msgid "Using new cache: %s\n" +msgstr "გამოიყენება ახალი ქეში: %s\n" + +#: ../../src/clients/kinit/kinit.c:570 +#, c-format +msgid "Using default cache: %s\n" +msgstr "გამოიყენება ნაგულისხმები ქეში: %s\n" + +#: ../../src/clients/kinit/kinit.c:583 +#, c-format +msgid "Using specified input cache: %s\n" +msgstr "გამოიყენება შეყვანის მითითებული ქეში: %s\n" + +#: ../../src/clients/kinit/kinit.c:590 ../../src/clients/ksu/krb_auth_su.c:160 +msgid "when unparsing name" +msgstr "სახელის დამუშავების გაუქმებისას" + +#: ../../src/clients/kinit/kinit.c:594 +#, c-format +msgid "Using principal: %s\n" +msgstr "გამოიყენება პრინციპალი: %s\n" + +#: ../../src/clients/kinit/kinit.c:677 +msgid "getting local addresses" +msgstr "ლოკალური მისამართების მიღება" + +#: ../../src/clients/kinit/kinit.c:701 +#, c-format +msgid "while setting up KDB keytab for realm %s" +msgstr "რეალმისთვის (%s) KBD keytab-ის მორგებისას" + +#: ../../src/clients/kinit/kinit.c:710 ../../src/clients/kvno/kvno.c:508 +#, c-format +msgid "resolving keytab %s" +msgstr "keytab-ის (%s) ამოხსნა" + +#: ../../src/clients/kinit/kinit.c:715 +#, c-format +msgid "Using keytab: %s\n" +msgstr "გამოიყენება kytab: %s\n" + +#: ../../src/clients/kinit/kinit.c:719 +msgid "resolving default client keytab" +msgstr "ნაგულისხმები კლიენტის keytab-ის ამოხსნა" + +#: ../../src/clients/kinit/kinit.c:729 +#, c-format +msgid "while setting '%s'='%s'" +msgstr "დაყენებისას '%s'='%s'" + +#: ../../src/clients/kinit/kinit.c:734 +#, c-format +msgid "PA Option %s = %s\n" +msgstr "PA პარამეტრი %s = %s\n" + +#: ../../src/clients/kinit/kinit.c:775 +msgid "getting initial credentials" +msgstr "საწყისი ავტორიზაციის დეტალების მიღება" + +#: ../../src/clients/kinit/kinit.c:778 +msgid "validating credentials" +msgstr "ავტორიზაციის დეტალების გადამოწმება" + +#: ../../src/clients/kinit/kinit.c:781 +msgid "renewing credentials" +msgstr "ავტორიზაციის დეტალების განახლება" + +#: ../../src/clients/kinit/kinit.c:789 +#, c-format +msgid "%s: Password incorrect while %s\n" +msgstr "%s: %s-ისას პაროლი არასწორია\n" + +#: ../../src/clients/kinit/kinit.c:792 +#, c-format +msgid "while %s" +msgstr "%s-სას" + +#: ../../src/clients/kinit/kinit.c:803 +msgid "when creating temporary cache" +msgstr "დროებითი ქეშის შექმნისას" + +#: ../../src/clients/kinit/kinit.c:807 +#, c-format +msgid "Initialized cache\n" +msgstr "ქეში ინიციალიზებულია\n" + +#: ../../src/clients/kinit/kinit.c:811 +msgid "while storing credentials" +msgstr "ავტორიზაციის დეტალების დამახსოვრებისას" + +#: ../../src/clients/kinit/kinit.c:816 +#, c-format +msgid "while saving to cache %s" +msgstr "ქეშში (%s) შენახვისას" + +#: ../../src/clients/kinit/kinit.c:822 +#, c-format +msgid "Stored credentials\n" +msgstr "დამახსოვრებული ავტორიზაციის დეტალები\n" + +#: ../../src/clients/kinit/kinit.c:828 +msgid "while switching to new ccache" +msgstr "ახალ ccache-ზე გადართვისას" + +#: ../../src/clients/kinit/kinit.c:885 +#, c-format +msgid "Authenticated to Kerberos v5\n" +msgstr "Kerberos v5-თან ავტორიზაცია წარმატებულია\n" + +#: ../../src/clients/klist/klist.c:85 +#, c-format +msgid "" +"Usage: %s [-e] [-V] [[-c] [-l] [-A] [-d] [-f] [-s] [-a [-n]]] [-k [-i] [-t] " +"[-K]] [-C] [name]\n" +msgstr "" +"გამოყენება: %s [-e] [-V] [[-c] [-l] [-A] [-d] [-f] [-s] [-a [-n]]] [-k [-i] " +"[-t] [-K]] [-C] [სახელი]\n" + +#: ../../src/clients/klist/klist.c:88 +#, c-format +msgid "\t-c specifies credentials cache\n" +msgstr "\t-c მიუთითებს ავტორიზაციის დეტალების ქეშს\n" + +#: ../../src/clients/klist/klist.c:89 +#, c-format +msgid "\t-k specifies keytab\n" +msgstr "\t-k keytab-ის მითითება\n" + +#: ../../src/clients/klist/klist.c:90 +#, c-format +msgid "\t (Default is credentials cache)\n" +msgstr "\t (ნაგულისხმებია ავტორიზაციის დეტალების ქეში)\n" + +#: ../../src/clients/klist/klist.c:91 +#, c-format +msgid "\t-i uses default client keytab if no name given\n" +msgstr "" +"\t-i თუ სახელი მითითებული არაა, ნაგულისხმები კლიენტის keytab -ის გამოყენება\n" + +#: ../../src/clients/klist/klist.c:92 +#, c-format +msgid "\t-l lists credential caches in collection\n" +msgstr "\t-l კოლექციაში ავტორიზაციის დეტალების ქეშების ჩამონათვალის გამოტანა\n" + +#: ../../src/clients/klist/klist.c:93 +#, c-format +msgid "\t-A shows content of all credential caches\n" +msgstr "\t-A ყველა ავტორიზაციის დეტალის ქეშის შემცველობის გამოტანა\n" + +#: ../../src/clients/klist/klist.c:94 +#, c-format +msgid "\t-e shows the encryption type\n" +msgstr "\t-e დაშიფვრის ტიპის ჩვენება\n" + +#: ../../src/clients/klist/klist.c:95 +#, c-format +msgid "\t-V shows the Kerberos version and exits\n" +msgstr "\t-V Kerberos -ის ვერსიის გამოტანა და გასვლა\n" + +#: ../../src/clients/klist/klist.c:96 +#, c-format +msgid "\toptions for credential caches:\n" +msgstr "\tპარამეტრები ავტორიზაციის დეტალების ქეშებისთვის:\n" + +#: ../../src/clients/klist/klist.c:97 +#, c-format +msgid "\t\t-d shows the submitted authorization data types\n" +msgstr "\t\t-d აჩვენებს გადაცემულ ავტორიზაციის მონაცემების ტიპებს\n" + +#: ../../src/clients/klist/klist.c:99 +#, c-format +msgid "\t\t-f shows credentials flags\n" +msgstr "\t\t-f ავტორიზაციის დეტალების ალმების ჩვენება\n" + +#: ../../src/clients/klist/klist.c:100 +#, c-format +msgid "\t\t-s sets exit status based on valid tgt existence\n" +msgstr "\t\t-s სწორი სამიზნის არსებობისას გასვლის სტატუსის დაყენება\n" + +#: ../../src/clients/klist/klist.c:102 +#, c-format +msgid "\t\t-a displays the address list\n" +msgstr "\t\t-a მისამართების სიის ჩვენება\n" + +#: ../../src/clients/klist/klist.c:103 +#, c-format +msgid "\t\t\t-n do not reverse-resolve\n" +msgstr "\t\t\t-n უკუ-ამოხსნა არ მოხდება\n" + +#: ../../src/clients/klist/klist.c:104 +#, c-format +msgid "\toptions for keytabs:\n" +msgstr "\tkeytab-ის პარამეტრები:\n" + +#: ../../src/clients/klist/klist.c:105 +#, c-format +msgid "\t\t-t shows keytab entry timestamps\n" +msgstr "\t\t-t keytab -ის ჩანაწერების დროის შტამპების ჩვენება\n" + +#: ../../src/clients/klist/klist.c:106 +#, c-format +msgid "\t\t-K shows keytab entry keys\n" +msgstr "\t\t-K keytab ჩანაწერის გასაღებების ჩვენება\n" + +#: ../../src/clients/klist/klist.c:107 +#, c-format +msgid "\t\t-C includes configuration data entries\n" +msgstr "\t\t-C კონფიგურაციის მონაცემების ჩანაწერების ჩათვლა\n" + +#: ../../src/clients/klist/klist.c:225 +#, c-format +msgid "%s version %s\n" +msgstr "%s ვერსია %s\n" + +#: ../../src/clients/klist/klist.c:278 +msgid "while getting default client keytab" +msgstr "ნაგულისხმები კლიენტის keytab-ის მიღებისას" + +#: ../../src/clients/klist/klist.c:284 +msgid "while getting default keytab" +msgstr "ნაგულისხმები keytab-ის მიღებისას" + +#: ../../src/clients/klist/klist.c:290 ../../src/kadmin/cli/keytab.c:103 +#, c-format +msgid "while resolving keytab %s" +msgstr "keytab-ის (%s) ამოხსნისას" + +#: ../../src/clients/klist/klist.c:297 ../../src/kadmin/cli/keytab.c:87 +msgid "while getting keytab name" +msgstr "keytab-ის სახელის მიღებისას" + +#: ../../src/clients/klist/klist.c:305 ../../src/kadmin/cli/keytab.c:422 +msgid "while starting keytab scan" +msgstr "keytab-ის სკანირების გაშვებისას" + +#: ../../src/clients/klist/klist.c:328 ../../src/clients/klist/klist.c:484 +#: ../../src/clients/ksu/ccache.c:455 ../../src/kadmin/dbutil/dump.c:487 +#: ../../src/kadmin/dbutil/tabdump.c:549 +msgid "while unparsing principal name" +msgstr "პრინციპალის სახელის დამუშავების გაუქმებისას" + +#: ../../src/clients/klist/klist.c:350 ../../src/kadmin/cli/keytab.c:466 +msgid "while scanning keytab" +msgstr "keytab-ის სკანირებისას" + +#: ../../src/clients/klist/klist.c:355 ../../src/kadmin/cli/keytab.c:471 +msgid "while ending keytab scan" +msgstr "keytab-ის სკანირების დასრულებისას" + +#: ../../src/clients/klist/klist.c:372 ../../src/clients/klist/klist.c:435 +msgid "while listing ccache collection" +msgstr "ccache-ის კოლექციის ჩამოთვლისას" + +#: ../../src/clients/klist/klist.c:411 +msgid "(Expired)" +msgstr "(ვადაგასულია)" + +#: ../../src/clients/klist/klist.c:488 +#, c-format +msgid "" +"Ticket cache: %s:%s\n" +"Default principal: %s\n" +"\n" +msgstr "" +"ბილეთების ქეში: %s:%s\n" +"ნაგულისხმები პრინციპალი: %s\n" +"\n" + +#: ../../src/clients/klist/klist.c:500 +msgid "while starting to retrieve tickets" +msgstr "ბილეთების მიღების დაწყებისას" + +#: ../../src/clients/klist/klist.c:514 +msgid "while finishing ticket retrieval" +msgstr "ბილეთების მიღების დასრულებისას" + +#: ../../src/clients/klist/klist.c:519 +msgid "while retrieving a ticket" +msgstr "ბილეთის მიღებისას" + +#: ../../src/clients/klist/klist.c:674 ../../src/clients/ksu/ccache.c:440 +#: ../../src/kprop/kpropd.c:1205 ../../src/kprop/kpropd.c:1270 +msgid "while unparsing client name" +msgstr "კლიენტის სახელის დამუშავების გაუქმებისას" + +#: ../../src/clients/klist/klist.c:679 ../../src/clients/ksu/ccache.c:445 +#: ../../src/kprop/kprop.c:191 +msgid "while unparsing server name" +msgstr "სერვერის სახელის დამუშავების გაუქმებისას" + +#: ../../src/clients/klist/klist.c:710 ../../src/clients/ksu/ccache.c:470 +#, c-format +msgid "\tfor client %s" +msgstr "\tკლიენტისთვის %s" + +#: ../../src/clients/klist/klist.c:722 ../../src/clients/ksu/ccache.c:479 +msgid "renew until " +msgstr "განაახლეთ ვადამდე " + +#: ../../src/clients/klist/klist.c:734 ../../src/clients/ksu/ccache.c:489 +#, c-format +msgid "Flags: %s" +msgstr "ალმები: %s" + +#: ../../src/clients/klist/klist.c:749 +#, c-format +msgid "Etype (skey, tkt): %s, " +msgstr "Etype (skey, ბლთ): %s, " + +#: ../../src/clients/klist/klist.c:761 +#, c-format +msgid "AD types: " +msgstr "AD ტიპები: " + +#: ../../src/clients/klist/klist.c:777 +#, c-format +msgid "\tAddresses: (none)\n" +msgstr "\tმისამართები: (არცერთი)\n" + +#: ../../src/clients/klist/klist.c:779 +#, c-format +msgid "\tAddresses: " +msgstr "\tმისამართები: " + +#: ../../src/clients/klist/klist.c:797 +msgid "while unparsing ticket server name" +msgstr "ბილეთის სერვერის სახელის დამუშავების გაუქმებისას" + +#: ../../src/clients/klist/klist.c:800 +#, c-format +msgid "\tTicket server: %s\n" +msgstr "\tბილეთის სერვერი: %s\n" + +#: ../../src/clients/klist/klist.c:828 ../../src/clients/klist/klist.c:838 +#, c-format +msgid "broken address (type %d length %d)" +msgstr "არასწორი მისამართი (ტიპი %d სიგრძე %d)" + +#: ../../src/clients/klist/klist.c:847 +#, c-format +msgid "unknown addrtype %d" +msgstr "მისამართის უცნობი ტიპი %d" + +#: ../../src/clients/klist/klist.c:856 +#, c-format +msgid "unprintable address (type %d, error %d %s)" +msgstr "მისამართის დაბეჭდვა შეუძლებელია (ტიპი %d, შეცდომა %d %s)" + +#: ../../src/clients/kpasswd/kpasswd.c:13 ../../src/lib/krb5/krb/gic_pwd.c:288 +msgid "Enter new password" +msgstr "შეიყვანეთ ახალი პაროლი" + +#: ../../src/clients/kpasswd/kpasswd.c:14 ../../src/lib/krb5/krb/gic_pwd.c:296 +msgid "Enter it again" +msgstr "შეიყვანეთ კიდევ ერთხელ" + +#: ../../src/clients/kpasswd/kpasswd.c:34 +#, c-format +msgid "Unable to identify user from password file\n" +msgstr "მომხმარების იდენტიფიკაცია პაროლის ფაილიდან შეუძლებელია\n" + +#: ../../src/clients/kpasswd/kpasswd.c:64 +#, c-format +msgid "usage: %s [principal]\n" +msgstr "გამოყენება: %s [პრინციპალი]\n" + +#: ../../src/clients/kpasswd/kpasswd.c:72 +msgid "initializing kerberos library" +msgstr "kerberos -ის ბიბლიოთეკის ინიციალიზაცია" + +#: ../../src/clients/kpasswd/kpasswd.c:77 +msgid "allocating krb5_get_init_creds_opt" +msgstr "krb5_get_init_creds_opt-ის გამოყოფა" + +#: ../../src/clients/kpasswd/kpasswd.c:93 +msgid "opening default ccache" +msgstr "ნაგულისხმები ccache-ის გახსნა" + +#: ../../src/clients/kpasswd/kpasswd.c:98 +msgid "getting principal from ccache" +msgstr "ccache-დან პრინციპალის მიღება" + +#: ../../src/clients/kpasswd/kpasswd.c:103 +msgid "while setting FAST ccache" +msgstr "ccache-ზე FAST-ის დაყენებისას" + +#: ../../src/clients/kpasswd/kpasswd.c:109 +msgid "closing ccache" +msgstr "ccache-ის დახურვა" + +#: ../../src/clients/kpasswd/kpasswd.c:117 +msgid "parsing client name" +msgstr "კლიენტის სახელის დამუშავება" + +#: ../../src/clients/kpasswd/kpasswd.c:135 +msgid "Password incorrect while getting initial ticket" +msgstr "საწყისი ბილეთის მიღებისას პაროლი არასწორია" + +#: ../../src/clients/kpasswd/kpasswd.c:137 +msgid "getting initial ticket" +msgstr "საწყისი ბილეთის მიღება" + +#: ../../src/clients/kpasswd/kpasswd.c:147 +msgid "while reading password" +msgstr "პაროლის კითხვისას" + +#: ../../src/clients/kpasswd/kpasswd.c:155 +msgid "changing password" +msgstr "პაროლის შეცვლა" + +#: ../../src/clients/kpasswd/kpasswd.c:175 +#: ../lib/kadm5/chpass_util_strings.c:30 +#, c-format +msgid "Password changed.\n" +msgstr "პაროლი შეიცვალა.\n" + +#: ../../src/clients/ksu/authorization.c:352 +#, c-format +msgid "" +"Error: bad entry - %s in %s file, must be either full path or just the cmd " +"name\n" +msgstr "" +"შეცდომა: არასწორი ჩანაწერი - %s %s ფაილში, ან სრული ბილიკი უნდა იყოს, ან " +"მხოლოდ ბრძანების სახელი\n" + +#: ../../src/clients/ksu/authorization.c:360 +#, c-format +msgid "" +"Error: bad entry - %s in %s file, since %s is just the cmd name, CMD_PATH " +"must be defined \n" +msgstr "" +"შეცდომა: არასწორი ჩანაწერი - %s %s ფაილში, რადგან %s უბრალოდ ბრძანების " +"სახელია, CMD_PATH აღწერილი უნდა იყოს \n" + +#: ../../src/clients/ksu/authorization.c:375 +#, c-format +msgid "Error: bad entry - %s in %s file, CMD_PATH contains no paths \n" +msgstr "" +"შეცდომა: არასწორი ჩანაწერი - %s %s ფაილში, CMD_PATH ბილიკებს არ შეიცავს \n" + +#: ../../src/clients/ksu/authorization.c:384 +#, c-format +msgid "Error: bad path %s in CMD_PATH for %s must start with '/' \n" +msgstr "" +"შეცდომა: არასწორი ბილიკი %s CMD_PATH -ში %s -სთვის '/' -ით უნდა იწყებოდეს \n" + +#: ../../src/clients/ksu/authorization.c:500 +msgid "Error: not found -> " +msgstr "შეცდომა: ვერ ვიპოვე -> " + +#: ../../src/clients/ksu/authorization.c:706 +#, c-format +msgid "home directory name `%s' too long, can't search for .k5login\n" +msgstr "" +"საწყისი საქაღალდის სახელი '%s' ძალიან გრძელია. .k5login-მდე ვერ მივედი\n" + +#: ../../src/clients/ksu/ccache.c:358 +#, c-format +msgid "home directory path for %s too long\n" +msgstr "საწყისი საქაღალდის ბილიკი %s-სთვის ძალიან გრძელია\n" + +#: ../../src/clients/ksu/ccache.c:451 +msgid "while retrieving principal name" +msgstr "პრინციპალის სახელის მიღებისას" + +#: ../../src/clients/ksu/krb_auth_su.c:57 +#: ../../src/clients/ksu/krb_auth_su.c:62 +msgid "while copying client principal" +msgstr "კლიენტის პრინციპალის კოპირებისას" + +#: ../../src/clients/ksu/krb_auth_su.c:69 +msgid "while creating tgt for local realm" +msgstr "ლოკალური რეალმისთვის სამიზნის შექმნსიას" + +#: ../../src/clients/ksu/krb_auth_su.c:84 +msgid "while retrieving creds from cache" +msgstr "ქეშიდან ავტ.დეტ-ების მიღებისას" + +#: ../../src/clients/ksu/krb_auth_su.c:95 +msgid "while switching to target uid" +msgstr "სამიზნე uid-ზე გადართვისას" + +#: ../../src/clients/ksu/krb_auth_su.c:100 +#, c-format +msgid "" +"WARNING: Your password may be exposed if you enter it here and are logged \n" +msgstr "" +"გაფრთხილება: თქვენი პაროლი შეიძლება გამოჩნდეს, თუ აქ აკრეფთ და ის ჟურნალშიც " +"შეინახება\n" + +#: ../../src/clients/ksu/krb_auth_su.c:102 +#, c-format +msgid " in remotely using an unsecure (non-encrypted) channel. \n" +msgstr " დაუცველი (არადაშიფრული) არხის გამოყენებაში. \n" + +#: ../../src/clients/ksu/krb_auth_su.c:114 ../../src/clients/ksu/main.c:481 +msgid "while reclaiming root uid" +msgstr "root-ის uid-ის გამოთხოვისას" + +#: ../../src/clients/ksu/krb_auth_su.c:121 +#, c-format +msgid "does not have any appropriate tickets in the cache.\n" +msgstr "ქეშში შესაბამისი ბილეთები არ გაგაჩნიათ.\n" + +#: ../../src/clients/ksu/krb_auth_su.c:133 +msgid "while verifying ticket for server" +msgstr "სერვერისთვის ბილეთის გადამოწმებისას" + +#: ../../src/clients/ksu/krb_auth_su.c:167 +msgid "while getting time of day" +msgstr "დროის მიღებისას" + +#: ../../src/clients/ksu/krb_auth_su.c:171 +#, c-format +msgid "Kerberos password for %s: " +msgstr "Kerberos -ის პაროლი %s-სთვის: " + +#: ../../src/clients/ksu/krb_auth_su.c:175 +#, c-format +msgid "principal name %s too long for internal buffer space\n" +msgstr "პრინციპალის სახელი %s ძალიან გრძელია შიდა ბუფერის სივრცისთვის\n" + +#: ../../src/clients/ksu/krb_auth_su.c:184 +#, c-format +msgid "while reading password for '%s'\n" +msgstr "'%s'-სთვის პაროლის წაკითხვისას\n" + +#: ../../src/clients/ksu/krb_auth_su.c:190 +#, c-format +msgid "No password given\n" +msgstr "პაროლი მითითებული არაა\n" + +#: ../../src/clients/ksu/krb_auth_su.c:203 +#, c-format +msgid "%s: Password incorrect\n" +msgstr "%s: პაროლი არასწორია\n" + +#: ../../src/clients/ksu/krb_auth_su.c:205 +msgid "while getting initial credentials" +msgstr "საწყისი ავტორიზაციის დეტალების მიღებისას" + +#: ../../src/clients/ksu/krb_auth_su.c:225 +#: ../../src/clients/ksu/krb_auth_su.c:239 +#, c-format +msgid " %s while unparsing name\n" +msgstr " %s სახელის დამუშავების გაუქმებისას\n" + +#: ../../src/clients/ksu/main.c:69 +#, c-format +msgid "" +"Usage: %s [target user] [-n principal] [-c source cachename] [-k] [-r time] " +"[-p|-P] [-f|-F] [-l lifetime] [-zZ] [-q] [-e command [args... ] ] [-a " +"[args... ] ]\n" +msgstr "" +"გამოყენება: %s [სამიზნე მომხმარებელი] [-n პრინციპალი] [-c საწყისი ქეშის " +"სახელი] [-k] [-r დრო] [-p|-P] [-f|-F] [-l სიცოცხლის დრო] [-zZ] [-q] [-e " +"ბრძანება [არგუმენტები... ] ] [-a [არგუმენტები... ] ]\n" + +#: ../../src/clients/ksu/main.c:151 +msgid "" +"program name too long - quitting to avoid triggering system logging bugs" +msgstr "" +"პროგრამის სახელი ძალიან გრძელია - მუშაობის დასრულება სისტემის ჟურნალის " +"შეცდომების აღძვრის თავიდან ასაცილებლად" + +#: ../../src/clients/ksu/main.c:177 +msgid "while allocating memory" +msgstr "მეხსიერების გამოყოფისას" + +#: ../../src/clients/ksu/main.c:190 +msgid "while setting euid to source user" +msgstr "საწყის მომხმარებელზე euid-ის დაყენებისას" + +#: ../../src/clients/ksu/main.c:201 ../../src/clients/ksu/main.c:242 +#, c-format +msgid "Bad lifetime value (%s hours?)\n" +msgstr "სიცოცხლის დროის არასწორი მნიშვნელობა (%s საათი?)\n" + +#: ../../src/clients/ksu/main.c:213 ../../src/clients/ksu/main.c:304 +msgid "when gathering parameters" +msgstr "პარამეტრების შეგროვებისას" + +#: ../../src/clients/ksu/main.c:263 +#, c-format +msgid "-z option is mutually exclusive with -Z.\n" +msgstr "-z ორმხრივად გამორიცხავს -Z -ის მითითებას.\n" + +#: ../../src/clients/ksu/main.c:271 +#, c-format +msgid "-Z option is mutually exclusive with -z.\n" +msgstr "-Z ორმხრივად გამორიცხავს -z -ის მითითებას.\n" + +#: ../../src/clients/ksu/main.c:284 +#, c-format +msgid "while looking for credentials cache %s" +msgstr "ავტორიზაციის ქეშში (%s) ძებნისას" + +#: ../../src/clients/ksu/main.c:290 +#, c-format +msgid "malformed credential cache name %s\n" +msgstr "არასწორად ფორმირებული ავტორიზაციის დეტალების ქეშის სახელი %s\n" + +#: ../../src/clients/ksu/main.c:348 +#, c-format +msgid "ksu: who are you?\n" +msgstr "ksu: ვინ ბრძანდებით?\n" + +#: ../../src/clients/ksu/main.c:352 +#, c-format +msgid "Your uid doesn't match your passwd entry?!\n" +msgstr "თქვენი uid -ი passwd ფაილის ჩანაწერს არ ემთხვევა?!\n" + +#: ../../src/clients/ksu/main.c:367 +#, c-format +msgid "ksu: unknown login %s\n" +msgstr "ksu: უცნობი მომხმარებელი %s\n" + +#: ../../src/clients/ksu/main.c:387 +msgid "while getting source cache" +msgstr "საწყისი ქეშის მიღებისას" + +#: ../../src/clients/ksu/main.c:396 +msgid "while selecting the best principal" +msgstr "საუკეთესო პრინციპალის არჩევისას" + +#: ../../src/clients/ksu/main.c:404 +msgid "while returning to source uid after finding best principal" +msgstr "საუკეთესო პრინციპალის არჩევის შემდეგ საწყის uid-ზე დაბრუნებისას" + +#: ../../src/clients/ksu/main.c:424 +#, c-format +msgid "account %s: authorization failed\n" +msgstr "ანგარიში %s: ავტორიზაციის შეცდომა\n" + +#: ../../src/clients/ksu/main.c:459 +msgid "while parsing temporary name" +msgstr "დროებითი სახელის დამუშავებისას" + +#: ../../src/clients/ksu/main.c:464 +msgid "while creating temporary cache" +msgstr "დროებითი ქეშის შექმნისას" + +#: ../../src/clients/ksu/main.c:470 ../../src/clients/ksu/main.c:710 +#, c-format +msgid "while copying cache %s to %s" +msgstr "ქეშის %s-დან %s-მდე კოპირებისას" + +#: ../../src/clients/ksu/main.c:488 +#, c-format +msgid "" +"WARNING: Your password may be exposed if you enter it here and are logged\n" +msgstr "" +"გაფრთხილება: თქვენი პაროლი შეიძლება გამოჩნდეს, თუ აქ აკრეფთ და ის ჟურნალშიც " +"შეინახება\n" + +#: ../../src/clients/ksu/main.c:490 +#, c-format +msgid " in remotely using an unsecure (non-encrypted) channel.\n" +msgstr " დაუცველი (არადაშიფრული) არხის გამოყენებაში.\n" + +#: ../../src/clients/ksu/main.c:496 +#, c-format +msgid "Goodbye\n" +msgstr "ნახვამდის\n" + +#: ../../src/clients/ksu/main.c:500 +#, c-format +msgid "Could not get a tgt for " +msgstr "სამიზნის მიღება შეუძლებელია " + +#: ../../src/clients/ksu/main.c:522 +#, c-format +msgid "Authentication failed.\n" +msgstr "ავთენტიკაციის შეცდომა.\n" + +#: ../../src/clients/ksu/main.c:530 +msgid "When unparsing name" +msgstr "სახელის დამუშავების გაუქმებისას" + +#: ../../src/clients/ksu/main.c:534 +#, c-format +msgid "Authenticated %s\n" +msgstr "ავთენტიფიცირებული %s\n" + +#: ../../src/clients/ksu/main.c:541 +msgid "while switching to target for authorization check" +msgstr "ავთორიზაციის შემოწმებისთვის სამიზნის გადართვისას" + +#: ../../src/clients/ksu/main.c:548 +msgid "while checking authorization" +msgstr "ავტორიზაციის შემოწმებისას" + +#: ../../src/clients/ksu/main.c:554 +msgid "while switching back from target after authorization check" +msgstr "ავტორიზაციის შემოწმების შემდეგ სამიზნეზე დაბრუნებისას" + +#: ../../src/clients/ksu/main.c:561 +#, c-format +msgid "Account %s: authorization for %s for execution of\n" +msgstr "ანგარიში %s: ავტორიზაცია %s-სთვის, რომ შესრულდეს\n" + +#: ../../src/clients/ksu/main.c:563 +#, c-format +msgid " %s successful\n" +msgstr " %s წარმატებულია\n" + +#: ../../src/clients/ksu/main.c:569 +#, c-format +msgid "Account %s: authorization for %s successful\n" +msgstr "ანგარიში %s: ავტორიზაცია %s-სთვის წარმატებულია\n" + +#: ../../src/clients/ksu/main.c:581 +#, c-format +msgid "Account %s: authorization for %s for execution of %s failed\n" +msgstr "ანგარიში %s: ავტორიზაციის შეცდომა %s-სთვის, %s-ის შესასრულებლად\n" + +#: ../../src/clients/ksu/main.c:589 +#, c-format +msgid "Account %s: authorization of %s failed\n" +msgstr "ანგარიშის %s: %s-ის ავტორიზაციის შეცდომა\n" + +#: ../../src/clients/ksu/main.c:604 +msgid "while calling cc_filter" +msgstr "cc_filter-ის გამოძახებისას" + +#: ../../src/clients/ksu/main.c:612 +msgid "while erasing target cache" +msgstr "სამიზნე ქეშის წაშლისას" + +#: ../../src/clients/ksu/main.c:632 +#, c-format +msgid "ksu: permission denied (shell).\n" +msgstr "ksu: წვდომა აკრძალულია (გარსი).\n" + +#: ../../src/clients/ksu/main.c:641 +#, c-format +msgid "ksu: couldn't set environment variable USER\n" +msgstr "ksu: გარემოს ცვლადის დაყენების შეცდომა: USER\n" + +#: ../../src/clients/ksu/main.c:647 +#, c-format +msgid "ksu: couldn't set environment variable HOME\n" +msgstr "ksu: გარემოს ცვლადის დაყენების შეცდომა: HOME\n" + +#: ../../src/clients/ksu/main.c:652 +#, c-format +msgid "ksu: couldn't set environment variable SHELL\n" +msgstr "ksu: გარემოს ცვლადის დაყენების შეცდომა: SHELL\n" + +#: ../../src/clients/ksu/main.c:663 +#, c-format +msgid "ksu: initgroups failed.\n" +msgstr "ksu: initgroups -ის შეცდომა.\n" + +#: ../../src/clients/ksu/main.c:668 +#, c-format +msgid "Leaving uid as %s (%ld)\n" +msgstr "UID-ი დარჩება %s (%ld)\n" + +#: ../../src/clients/ksu/main.c:671 +#, c-format +msgid "Changing uid to %s (%ld)\n" +msgstr "UID-ის შეცვლა %s-ზე (%ld)\n" + +#: ../../src/clients/ksu/main.c:697 +msgid "while getting name of target ccache" +msgstr "სამიზნე ccache-ის სახელის მიღებისას" + +#: ../../src/clients/ksu/main.c:717 +#, c-format +msgid "%s does not have correct permissions for %s, %s aborted" +msgstr "%s-ს %s-სთვის სწორი წვდომები არ გააჩნია. %s ავარიულად დასრულდა" + +#: ../../src/clients/ksu/main.c:738 +#, c-format +msgid "Internal error: command %s did not get resolved\n" +msgstr "შიდა შეცდომა: ბრძანება %s\n" + +#: ../../src/clients/ksu/main.c:755 ../../src/clients/ksu/main.c:791 +#, c-format +msgid "while trying to execv %s" +msgstr "%s-ის execv-ისას" + +#: ../../src/clients/ksu/main.c:781 +msgid "while calling waitpid" +msgstr "waitpid-ის გამოძახებისას" + +#: ../../src/clients/ksu/main.c:786 +msgid "while trying to fork." +msgstr "fork-ის მცდელობისას." + +#: ../../src/clients/ksu/main.c:836 +msgid "while reading cache name from ccache" +msgstr "ქეშის სახელის ccache-დან წაკითხვისას" + +#: ../../src/clients/ksu/main.c:842 +#, c-format +msgid "ksu: couldn't set environment variable %s\n" +msgstr "ksu: შეცდომა გარემოს ცვლადის დაყენებისას %s\n" + +#: ../../src/clients/ksu/main.c:868 +msgid "while resetting target ccache name" +msgstr "სამიზნის ccache-ის სახელის საწყის მნიშვნელობაზე დაყენებისას" + +#: ../../src/clients/ksu/main.c:882 +msgid "while determining target ccache name" +msgstr "სამიზნის ccache-ის სახელის დადგენისას" + +#: ../../src/clients/ksu/main.c:921 +msgid "while generating part of the target ccache name" +msgstr "სამიზნე ccache-ის სახელის ნაწილის გენერირებისას" + +#: ../../src/clients/ksu/main.c:927 +msgid "while allocating memory for the target ccache name" +msgstr "სამიზნე ccache-ის სახელისთვის მეხსიერების გამოყოფისას" + +#: ../../src/clients/ksu/main.c:946 +msgid "while creating new target ccache" +msgstr "ახალი სამიზნე ccache-ის შექმნისას" + +#: ../../src/clients/ksu/main.c:952 +msgid "while initializing target cache" +msgstr "სამიზნე ქეშის ინიციალიზაციისას" + +#: ../../src/clients/ksu/main.c:992 +#, c-format +msgid "terminal name %s too long\n" +msgstr "საბოლოო სახელი %s ძალიან გრძელია\n" + +#: ../../src/clients/ksu/main.c:1020 +msgid "while changing to target uid for destroying ccache" +msgstr "ccache-ის გასანადგურებლად სამიზნე uid-ზე გადართვისას" + +#: ../../src/clients/kswitch/kswitch.c:41 +#, c-format +msgid "Usage: %s {-c cache_name | -p principal}\n" +msgstr "გამოყენება: %s {-c ქეშის სახელი | -p პრინციპალი}\n" + +#: ../../src/clients/kswitch/kswitch.c:43 +#, c-format +msgid "\t-p specify name of principal\n" +msgstr "\t-p მიუთითეთ პრინციპალის სახელი\n" + +#: ../../src/clients/kswitch/kswitch.c:66 +#, c-format +msgid "Only one -c or -p option allowed\n" +msgstr "-p და -c პარამეტრებიდან მხოლოდ ერთ-ერთი მათგანის მითითება შეგიძლიათ\n" + +#: ../../src/clients/kswitch/kswitch.c:85 +#, c-format +msgid "One of -c or -p must be specified\n" +msgstr "-p და -c პარამეტრებიდან მხოლოდ ერთი მათგანიუნდა იყოს მითითებული\n" + +#: ../../src/clients/kswitch/kswitch.c:101 +#, c-format +msgid "while resolving %s" +msgstr "%s-ის ამოხსნისას" + +#: ../../src/clients/kswitch/kswitch.c:122 +msgid "while switching to credential cache" +msgstr "ავტორიზაციის დეტალების ქეშის გადართვისას" + +#: ../../src/clients/kvno/kvno.c:44 +#, c-format +msgid "" +"usage: %s [-c ccache] [-e etype] [-k keytab] [-q] [-u | -S sname]\n" +"\t[[{-F cert_file | {-I | -U} for_user} [-P]] | --u2u ccache]\n" +"\t[--cached-only] [--no-store] [--out-cache] service1 service2 ...\n" +msgstr "" +"გამოყენება: %s [-c ccache] [-e etype] [-k keytab] [-q] [-u | -S sname]\n" +"\t[[{-F სერტ_ფაილი | {-I | -U} მომხმარებლისთვის} [-P]] | --u2u ccache]\n" +"\t[--cached-only] [--no-store] [--out-cache] სერვისი1 სერვისი2 ...\n" + +#: ../../src/clients/kvno/kvno.c:117 ../../src/clients/kvno/kvno.c:125 +#, c-format +msgid "Options -u and -S are mutually exclusive\n" +msgstr "-u და -S ურთიერთგამომრიცხავი პარამეტრებია\n" + +#: ../../src/clients/kvno/kvno.c:159 +#, c-format +msgid "Options --u2u and -I|-U|-F are mutually exclusive\n" +msgstr "--u2u და -I|-U|-F ურთიერთგამომრიცხავი პარამეტრებია\n" + +#: ../../src/clients/kvno/kvno.c:165 +#, c-format +msgid "" +"Option -P (constrained delegation) requires option -I|-U|-F (protocol " +"transition)\n" +msgstr "" +"პარამეტრს -P (შეზღუდული დელეგაცია) -I|-U|-F პარამეტრებიდან ერთერთი " +"(პროტოკოლის გადაცემა) ესაჭიროება\n" + +#: ../../src/clients/kvno/kvno.c:240 +msgid "No begin line not found" +msgstr "ხაზის დასაწყისი ნაპოვნი არაა" + +#: ../../src/clients/kvno/kvno.c:252 +msgid "No end line found" +msgstr "ხაზის ბოლო ნაპოვნი არაა" + +#: ../../src/clients/kvno/kvno.c:263 +msgid "Unexpected header line" +msgstr "მოულოდნელი თავსართის საზი" + +#: ../../src/clients/kvno/kvno.c:273 +msgid "Invalid base64" +msgstr "არასწორი base64" + +#: ../../src/clients/kvno/kvno.c:319 +#, c-format +msgid "while formatting parsed principal name for '%s'" +msgstr "'%s'-სთვის დამუშავებული პრინციპალის სახელის ფორმატირებისას" + +#: ../../src/clients/kvno/kvno.c:333 +msgid "client and server principal names must match" +msgstr "კლიენტისა და სერვერის პრინციპალის სახელები უნდა ემთხვეოდეს" + +#: ../../src/clients/kvno/kvno.c:349 +#, c-format +msgid "while getting credentials for %s" +msgstr "%s-სთვის ავტორიზაციის დეტალების მიღებისას" + +#: ../../src/clients/kvno/kvno.c:356 +#, c-format +msgid "while decoding ticket for %s" +msgstr "%s-სთვის ბილეთის დეკოდირებისას" + +#: ../../src/clients/kvno/kvno.c:367 +#, c-format +msgid "while decrypting ticket for %s" +msgstr "%s-სთვის ბილეთის გაშიფვრისას" + +#: ../../src/clients/kvno/kvno.c:371 +#, c-format +msgid "%s: kvno = %d, keytab entry valid\n" +msgstr "%s: kvno = %d, keytab -ის ჩანაწერი არასწორია \n" + +#: ../../src/clients/kvno/kvno.c:376 +#, c-format +msgid "%s: kvno = %d\n" +msgstr "%s: kvno = %d\n" + +#: ../../src/clients/kvno/kvno.c:391 +#, c-format +msgid "%s: constrained delegation failed" +msgstr "%s: შეზღუდული დელეგირების შეცდომა" + +#: ../../src/clients/kvno/kvno.c:474 ../../src/kadmin/cli/kadmin.c:311 +msgid "while initializing krb5 library" +msgstr "krb5-ის ბიბლიოთეკის ინიციალიზაციისას" + +#: ../../src/clients/kvno/kvno.c:481 +msgid "while converting etype" +msgstr "etype-ის გარდაქმნისას" + +#: ../../src/clients/kvno/kvno.c:493 +msgid "while opening ccache" +msgstr "ccache-ის გახნისას" + +#: ../../src/clients/kvno/kvno.c:500 +msgid "while resolving output ccache" +msgstr "გამოტანის ccache-ის ამოხსნისას" + +#: ../../src/clients/kvno/kvno.c:525 +#, c-format +msgid "while reading certificate file %s" +msgstr "ფაილისთვის %s სერტიფიკატის წაკითხვისას" + +#: ../../src/clients/kvno/kvno.c:535 +#, c-format +msgid "while getting user-to-user ticket from %s" +msgstr "მომხმარებლიდან-მომხმარებლამდე ბილეთის %s-სგან მიღებისას" + +#: ../../src/clients/kvno/kvno.c:544 +msgid "while getting client principal name" +msgstr "კლიენტის პრინციპალის სახელის მიღებისას" + +#: ../../src/clients/kvno/kvno.c:551 +msgid "while creating temporary output ccache" +msgstr "დროებითი გამოტანის ccache-ის შექმნისას" + +#: ../../src/clients/kvno/kvno.c:565 +msgid "while initializing output ccache" +msgstr "გამოტანის ccache-ის ინიციალიზაციისას" + +#: ../../src/clients/kvno/kvno.c:575 +msgid "while storing creds in output ccache" +msgstr "ავტორიზაციის დეტალების გამოტანის ccache-ში შენახვისას" + +#: ../../src/clients/kvno/kvno.c:586 +msgid "while writing output ccache" +msgstr "გამოტანის ccache-ის შენახვისას" + +#: ../../src/kadmin/cli/kadmin.c:103 +#, c-format +msgid "" +"Usage: %s [-r realm] [-p principal] [-q query] [clnt|local args]\n" +" [command args...]\n" +"\tclnt args: [-s admin_server[:port]] [[-c ccache]|[-k [-t keytab]]]|[-n] [-" +"O | -N]\n" +"\tlocal args: [-x db_args]* [-d dbname] [-e \"enc:salt ...\"] [-m] [-w " +"password] where,\n" +"\t[-x db_args]* - any number of database specific arguments.\n" +"\t\t\tLook at each database documentation for supported arguments\n" +msgstr "" +"გამოყენება: %s [-r რეალმი] [-p პრინციპალი] [-q მოთხოვნა] [კლიენტი|ლოკალური " +"არგუმენტები]\n" +" [ბრძანების არგუმენტები...]\n" +"\tკლიენტის არგუმენტები: [-s ადმინ_სერვერი[:პორტი]] [[-c ccache]|[-k [-t " +"keytab]]]|[-n] [-O | -N]\n" +"\tლოკალური არგუმენტები: [-x ბაზის_არგუმენტები]* [-d ბაზსსახელი] [-e \"შიფრი:" +"მარილი ...\"] [-m] [-w პაროლი] სად,\n" +"\t[-x ბაზის_არგუმენტები]* - ბაზის ნებისმიერი პარამეტრი.\n" +"\t\t\tმხარდაჭერილი არგუმენტებისთვის მიმართეთ ბაზის დოკუმენტაციას\n" + +#: ../../src/kadmin/cli/kadmin.c:164 +#, c-format +msgid "Invalid date specification \"%s\".\n" +msgstr "არასწორი მონაცემების სპეციფიკაცია \"%s\".\n" + +#: ../../src/kadmin/cli/kadmin.c:192 +#, c-format +msgid "Interval specification \"%s\" is in the past.\n" +msgstr "ინტერვალის სპეციფიკაცია \"%s\" წარსულშია.\n" + +#: ../../src/kadmin/cli/kadmin.c:322 ../../src/kadmin/cli/kadmin.c:361 +#, c-format +msgid "%s: Cannot initialize. Not enough memory\n" +msgstr "%s: ინიციალიზაციის შეცდომა. არასაკმარისი მეხსიერება\n" + +#: ../../src/kadmin/cli/kadmin.c:380 ../../src/kadmin/cli/kadmin.c:840 +#: ../../src/kadmin/cli/kadmin.c:1109 ../../src/kadmin/cli/kadmin.c:1630 +#: ../../src/kadmin/cli/keytab.c:148 ../../src/kadmin/dbutil/kdb5_util.c:559 +#, c-format +msgid "while parsing keysalts %s" +msgstr "keysalt %s-ის დამუშავებისას" + +#: ../../src/kadmin/cli/kadmin.c:403 +#, c-format +msgid "%s: -q is exclusive with command-line query" +msgstr "%s: -q ბრძანების სტრიქონიდან გამოთხოვისთვის ექსკლუზიურია" + +#: ../../src/kadmin/cli/kadmin.c:411 +#, c-format +msgid "%s: unable to get default realm\n" +msgstr "%s: ნაგულისხმები რეალმის მიღების შეცდომა\n" + +#: ../../src/kadmin/cli/kadmin.c:431 +msgid "while opening default credentials cache" +msgstr "ნაგულისხმები ავტორიზაციის დეტალების ქეშის გახსნისას" + +#: ../../src/kadmin/cli/kadmin.c:437 +#, c-format +msgid "while opening credentials cache %s" +msgstr "ავტორიზაციის დეტალების ქეშის (%s) გახსნისას" + +#: ../../src/kadmin/cli/kadmin.c:459 ../../src/kadmin/cli/kadmin.c:513 +#: ../../src/kadmin/cli/kadmin.c:521 ../../src/kadmin/cli/kadmin.c:528 +#, c-format +msgid "%s: out of memory\n" +msgstr "%s: არასაკმარისი მეხსიერება\n" + +#: ../../src/kadmin/cli/kadmin.c:468 ../../src/kadmin/cli/kadmin.c:483 +#: ../../src/kprop/kpropd.c:677 +msgid "while canonicalizing principal name" +msgstr "პრინციპალის სახელის კანონიკალიზირებისას" + +#: ../../src/kadmin/cli/kadmin.c:477 +msgid "creating host service principal" +msgstr "ჰოსტის სერვისის პრინციპალის შექმნა" + +#: ../../src/kadmin/cli/kadmin.c:490 +#, c-format +msgid "%s: unable to canonicalize principal\n" +msgstr "%s: პრინციპალის კანონიკალიზაციის შეცდომა\n" + +#: ../../src/kadmin/cli/kadmin.c:533 +#, c-format +msgid "%s: unable to figure out a principal name\n" +msgstr "%s: პრინციპალის სახელის გარკვევის შეცდომა\n" + +#: ../../src/kadmin/cli/kadmin.c:540 +msgid "while setting up logging" +msgstr "ჟურნალის მორგებისას" + +#: ../../src/kadmin/cli/kadmin.c:549 +#, c-format +msgid "Authenticating as principal %s with existing credentials.\n" +msgstr "ავთენტიკაცია, როგორც პრინციპალი %s, არსებული ავტორიზაციის დეტალებით.\n" + +#: ../../src/kadmin/cli/kadmin.c:555 +#, c-format +msgid "Authenticating as principal %s with password; anonymous requested.\n" +msgstr "ავთენტიკაცია, როგორც პრინციპალი %s, პაროლით: ანონიმური მოთხოვნილია.\n" + +#: ../../src/kadmin/cli/kadmin.c:562 +#, c-format +msgid "Authenticating as principal %s with keytab %s.\n" +msgstr "ავთენტიკაცია, როგორც პრინციპალი %s, keytab-ით %s.\n" + +#: ../../src/kadmin/cli/kadmin.c:565 +#, c-format +msgid "Authenticating as principal %s with default keytab.\n" +msgstr "ავთენტიკაცია, როგორც პრინციპალი %s, ნაგულისხმები keytab-ით.\n" + +#: ../../src/kadmin/cli/kadmin.c:572 +#, c-format +msgid "Authenticating as principal %s with password.\n" +msgstr "ავთენტიკაცია, როგორც პრინციპალი %s, პაროლით.\n" + +#: ../../src/kadmin/cli/kadmin.c:580 ../../src/kprop/kpropd.c:722 +#, c-format +msgid "while initializing %s interface" +msgstr "%s ინტერფეისის ინიციალიზაციისას" + +#: ../../src/kadmin/cli/kadmin.c:595 +#, c-format +msgid "while closing ccache %s" +msgstr "ccache -ის (%s) დახურვისას" + +#: ../../src/kadmin/cli/kadmin.c:601 +msgid "while mapping update log" +msgstr "განახლების ჟურნალის მიბმიბსას" + +#: ../../src/kadmin/cli/kadmin.c:617 +msgid "while unlocking locked database" +msgstr "დაბლოკილიბაზის განბლოკვისას" + +#: ../../src/kadmin/cli/kadmin.c:626 +msgid "Administration credentials NOT DESTROYED.\n" +msgstr "ადმინისტრატორის ავტორიზაციის დეტალები არ განადგურებულა\n" + +#: ../../src/kadmin/cli/kadmin.c:675 +msgid "usage: delete_principal [-force] principal\n" +msgstr "გამოყენება: delete_principal [-force] პრინციპალი\n" + +#: ../../src/kadmin/cli/kadmin.c:680 ../../src/kadmin/cli/kadmin.c:859 +msgid "while parsing principal name" +msgstr "პრინციპალის სახელის დამუშავებისას" + +#: ../../src/kadmin/cli/kadmin.c:686 ../../src/kadmin/cli/kadmin.c:865 +#: ../../src/kadmin/cli/kadmin.c:1218 ../../src/kadmin/cli/kadmin.c:1343 +#: ../../src/kadmin/cli/kadmin.c:1413 ../../src/kadmin/cli/kadmin.c:1853 +#: ../../src/kadmin/cli/kadmin.c:1897 ../../src/kadmin/cli/kadmin.c:1943 +#: ../../src/kadmin/cli/kadmin.c:1983 +msgid "while canonicalizing principal" +msgstr "პრინციპალის სახელის კანონიკალიზირებისას" + +#: ../../src/kadmin/cli/kadmin.c:690 +#, c-format +msgid "Are you sure you want to delete the principal \"%s\"? (yes/no): " +msgstr "" +"დარწმუნებული ბრძანდებით რომ გნებავთ პრინციპალი \"%s\"-ის საბოლოოდ წაშლა " +"(yes(დიახ)/no(არა)): " + +#: ../../src/kadmin/cli/kadmin.c:694 +#, c-format +msgid "Principal \"%s\" not deleted\n" +msgstr "პრინციპალი \"%s\" არ წაშლილა\n" + +#: ../../src/kadmin/cli/kadmin.c:701 +#, c-format +msgid "while deleting principal \"%s\"" +msgstr "პრინციპალი \"%s\"-ის წაშლისას" + +#: ../../src/kadmin/cli/kadmin.c:704 +#, c-format +msgid "Principal \"%s\" deleted.\n" +msgstr "პრინციპალი \"%s\" წაიშალა\n" + +#: ../../src/kadmin/cli/kadmin.c:705 +msgid "" +"Make sure that you have removed this principal from all ACLs before " +"reusing.\n" +msgstr "" +"დარწმუნდით, რომ თავიდან გამოყენებამდე პრინციპალი ყველა ACL-დან წაშალეთ\n" + +#: ../../src/kadmin/cli/kadmin.c:722 +msgid "usage: rename_principal [-force] old_principal new_principal\n" +msgstr "" +"გამოყენება: rename_principal [-force] ძველი_პრინციპალი ახალი_პრინციპალი\n" + +#: ../../src/kadmin/cli/kadmin.c:729 +msgid "while parsing old principal name" +msgstr "ძველი პრინციპალის სახელის დამუშავებისას" + +#: ../../src/kadmin/cli/kadmin.c:735 +msgid "while parsing new principal name" +msgstr "ახალი პრინციპალის სახელის დამუშავებისას" + +#: ../../src/kadmin/cli/kadmin.c:741 +msgid "while canonicalizing old principal" +msgstr "ძველი პრინციპალის კანონიკალიზირებისას" + +#: ../../src/kadmin/cli/kadmin.c:747 +msgid "while canonicalizing new principal" +msgstr "ახალი პრინციპალის კანონიკალიზირებისას" + +#: ../../src/kadmin/cli/kadmin.c:751 +#, c-format +msgid "" +"Are you sure you want to rename the principal \"%s\" to \"%s\"? (yes/no): " +msgstr "" +"დარწმუნებული ბრძანდებით რომ გნებავთ, პრინციპალის სახელის \"%s\"-დან %s-მდე " +"გადარქმევა (yes(დიახ)/no(არა)): " + +#: ../../src/kadmin/cli/kadmin.c:755 +#, c-format +msgid "Principal \"%s\" not renamed\n" +msgstr "პრინციპალი '%s\"-ის სახელი არ შეცვლილა\n" + +#: ../../src/kadmin/cli/kadmin.c:762 +#, c-format +msgid "while renaming principal \"%s\" to \"%s\"" +msgstr "პრინციპალის სახელის \"%s\"-დან \"%s\"-მდე გადარქმევისას" + +#: ../../src/kadmin/cli/kadmin.c:766 +#, c-format +msgid "Principal \"%s\" renamed to \"%s\".\n" +msgstr "პრინციპალი \"%s\" -ის სახელი \"%s\"-ზე შეიცვალა.\n" + +#: ../../src/kadmin/cli/kadmin.c:767 +msgid "" +"Make sure that you have removed the old principal from all ACLs before " +"reusing.\n" +msgstr "" +"დარწმუნდით, რომ თავიდან გამოყენებამდე ძველი პრინციპალი ყველა ACL-დან " +"წაშალეთ\n" + +#: ../../src/kadmin/cli/kadmin.c:782 +msgid "" +"usage: change_password [-randkey] [-keepold] [-e keysaltlist] [-pw password] " +"principal\n" +msgstr "" +"გამოყენება: change_password [-randkey] [-keepold] [-e keysaltlist] [-pw " +"პაროლი] პრინციპალი\n" + +#: ../../src/kadmin/cli/kadmin.c:808 +msgid "change_password: missing db argument" +msgstr "change_password: ბაზის არგუმენტის გაერშე" + +#: ../../src/kadmin/cli/kadmin.c:814 +msgid "change_password: Not enough memory\n" +msgstr "change_password: არასაკმარისი მეხსიერება\n" + +#: ../../src/kadmin/cli/kadmin.c:822 +msgid "change_password: missing password arg" +msgstr "change_password: აკლია პაროლის არგუმენტი" + +#: ../../src/kadmin/cli/kadmin.c:833 +msgid "change_password: missing keysaltlist arg" +msgstr "change_password: აკლია keysaltlist არგუმენტი" + +#: ../../src/kadmin/cli/kadmin.c:844 +#, c-format +msgid "unrecognized option %s" +msgstr "უცნობი პარამეტრი %s" + +#: ../../src/kadmin/cli/kadmin.c:851 +msgid "missing principal name" +msgstr "აკლია პრინციპალის სახელი" + +#: ../../src/kadmin/cli/kadmin.c:853 +msgid "too many arguments" +msgstr "მეტისმეტად ბევრი არგუმენტი" + +#: ../../src/kadmin/cli/kadmin.c:877 ../../src/kadmin/cli/kadmin.c:914 +#, c-format +msgid "while changing password for \"%s\"." +msgstr "\"%s\"-სთვის პაროლის ცვლილებისას." + +#: ../../src/kadmin/cli/kadmin.c:880 ../../src/kadmin/cli/kadmin.c:917 +#, c-format +msgid "Password for \"%s\" changed.\n" +msgstr "%s-ის პაროლი შეიცვალა.\n" + +#: ../../src/kadmin/cli/kadmin.c:886 ../../src/kadmin/cli/kadmin.c:1294 +#, c-format +msgid "while randomizing key for \"%s\"." +msgstr "\"%s\"-ის გასაღების რანდომიზებისას." + +#: ../../src/kadmin/cli/kadmin.c:889 +#, c-format +msgid "Key for \"%s\" randomized.\n" +msgstr "\"%s\"-ის გასაღები რანდომიზებულია.\n" + +#: ../../src/kadmin/cli/kadmin.c:894 ../../src/kadmin/cli/kadmin.c:1254 +#, c-format +msgid "Enter password for principal \"%s\"" +msgstr "შეყვანეთ პაროლი პრინციპალისთვის \"%s\"" + +#: ../../src/kadmin/cli/kadmin.c:896 ../../src/kadmin/cli/kadmin.c:1256 +#, c-format +msgid "Re-enter password for principal \"%s\"" +msgstr "ხელახლა შეიყვანეთ პაროლი პრინციპალისთვის \"%s\"" + +#: ../../src/kadmin/cli/kadmin.c:901 ../../src/kadmin/cli/kadmin.c:1260 +#, c-format +msgid "while reading password for \"%s\"." +msgstr "%s-ის პაროლის წაკითხვისას." + +#: ../../src/kadmin/cli/kadmin.c:955 +msgid "Not enough memory\n" +msgstr "არასაკმარისი მეხსიერება\n" + +#: ../../src/kadmin/cli/kadmin.c:985 ../../src/kadmin/dbutil/kdb5_util.c:591 +msgid "while getting time" +msgstr "დროის მიღებისას" + +#: ../../src/kadmin/cli/kadmin.c:1126 ../../src/kadmin/cli/kadmin.c:1337 +#: ../../src/kadmin/cli/kadmin.c:1408 ../../src/kadmin/cli/kadmin.c:1847 +#: ../../src/kadmin/cli/kadmin.c:1891 ../../src/kadmin/cli/kadmin.c:1937 +#: ../../src/kadmin/cli/kadmin.c:1977 +msgid "while parsing principal" +msgstr "პრინციპალის დამუშავებისას" + +#: ../../src/kadmin/cli/kadmin.c:1135 +msgid "usage: add_principal [options] principal\n" +msgstr "გამოყენება: add_principal [პარამეტრები] პრინციპალი\n" + +#: ../../src/kadmin/cli/kadmin.c:1136 ../../src/kadmin/cli/kadmin.c:1160 +#: ../../src/kadmin/cli/kadmin.c:1653 +msgid "\toptions are:\n" +msgstr "\tპარამეტრებია:\n" + +#: ../../src/kadmin/cli/kadmin.c:1137 +msgid "" +"\t\t[-randkey|-nokey] [-x db_princ_args]* [-expire expdate] [-pwexpire " +"pwexpdate] [-maxlife maxtixlife]\n" +"\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n" +"\t\t[-pw password] [-maxrenewlife maxrenewlife]\n" +"\t\t[-e keysaltlist]\n" +"\t\t[{+|-}attribute]\n" +msgstr "" +"\t\t[-randkey|-nokey] [-x ბაზის_პრინც_არგუმენტები]* [-expire ვადის_თარიღი] [-" +"pwexpire პაროლის_ვადა] [-maxlife maxtixlife]\n" +"\t\t[-kvno kvno] [-policy პოლიტიკა] [-clearpolicy]\n" +"\t\t[-pw პაროლი] [-maxrenewlife maxrenewlife]\n" +"\t\t[-e გასაღების_მარილის_სია]\n" +"\t\t[{+|-}ატრიბუტი]\n" + +#: ../../src/kadmin/cli/kadmin.c:1142 ../../src/kadmin/cli/kadmin.c:1165 +msgid "\tattributes are:\n" +msgstr "\tატრიბუტებია:\n" + +#: ../../src/kadmin/cli/kadmin.c:1143 ../../src/kadmin/cli/kadmin.c:1166 +msgid "" +"\t\tallow_postdated allow_forwardable allow_tgs_req allow_renewable\n" +"\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n" +"\t\trequires_hwauth needchange allow_svr password_changing_service\n" +"\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n" +"\t\tlockdown_keys\n" +"\n" +"where,\n" +"\t[-x db_princ_args]* - any number of database specific arguments.\n" +"\t\t\tLook at each database documentation for supported arguments\n" +msgstr "" +"\t\tallow_postdated allow_forwardable allow_tgs_req allow_renewable\n" +"\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n" +"\t\trequires_hwauth needchange allow_svr password_changing_service\n" +"\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n" +"\t\tlockdown_keys\n" +"\n" +"სადაც,\n" +"\t[-x ბაზის_პრინციპული_არგუმენტები]* - ბაზისთვის გადაცემული არგუმენტები.\n" +"\t\t\tმხარდაჭერილი არგუმენტების სანახავად მიმართეთ ბაზის დოკუმენტაციას\n" + +#: ../../src/kadmin/cli/kadmin.c:1159 +msgid "usage: modify_principal [options] principal\n" +msgstr "გამოყენება: modify_principal [პარამეტრები] პრინციპალი\n" + +#: ../../src/kadmin/cli/kadmin.c:1161 +msgid "" +"\t\t[-x db_princ_args]* [-expire expdate] [-pwexpire pwexpdate] [-maxlife " +"maxtixlife]\n" +"\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n" +"\t\t[-maxrenewlife maxrenewlife] [-unlock] [{+|-}attribute]\n" +msgstr "" +"\t\t[-x ბაზის_პრინციპული_არგუმენტები]* [-expire ვადა] [-pwexpire " +"პაროლის_ვადა] [-maxlife maxtixlife]\n" +"\t\t[-kvno kvno] [-policy პოლიტიკა] [-clearpolicy]\n" +"\t\t[-maxrenewlife maxrenewlife] [-unlock] [{+|-}ატრიბუტი]\n" + +#: ../../src/kadmin/cli/kadmin.c:1225 ../../src/kadmin/cli/kadmin.c:1366 +#, c-format +msgid "WARNING: policy \"%s\" does not exist\n" +msgstr "გაფრთხილება: პოლიტიკა \"%s\" არ არსებობს\n" + +#: ../../src/kadmin/cli/kadmin.c:1232 +#, c-format +msgid "No policy specified for %s; assigning \"default\"\n" +msgstr "%s-სთვის პოლიტიკა მითითებული არაა. \"ნაგულისხმების\" მინიჭება\n" + +#: ../../src/kadmin/cli/kadmin.c:1238 +#, c-format +msgid "No policy specified for %s; defaulting to no policy\n" +msgstr "" +"%s-სთვის პოლიტიკა მითიტებული არაა. ნაგულისხმებად პოლიტიკა მინიჭებული არ " +"იქნება\n" + +#: ../../src/kadmin/cli/kadmin.c:1280 +#, c-format +msgid "Admin server does not support -nokey while creating \"%s\"\n" +msgstr "ადმინის სერვერს \"%s\"-ის შექმნისას -nokey -ის მხარდაჭერა არ გააჩნია\n" + +#: ../../src/kadmin/cli/kadmin.c:1302 +#, c-format +msgid "while clearing DISALLOW_ALL_TIX for \"%s\"." +msgstr "\"%s\"-სთვის DISALLOW_ALL_TIX -ის გასუფთავებისას." + +#: ../../src/kadmin/cli/kadmin.c:1349 +#, c-format +msgid "while getting \"%s\"." +msgstr "\"%s\"-ის მიღებისას." + +#: ../../src/kadmin/cli/kadmin.c:1375 +#, c-format +msgid "while modifying \"%s\"." +msgstr "\"%s\"-ის ცვლილებისას." + +#: ../../src/kadmin/cli/kadmin.c:1379 +#, c-format +msgid "Principal \"%s\" modified.\n" +msgstr "პრინციპალი \"%s\" შეიცვალა.\n" + +#: ../../src/kadmin/cli/kadmin.c:1400 +msgid "usage: get_principal [-terse] principal\n" +msgstr "გამოყენება: get_principal [-terse] პრინციპალი\n" + +#: ../../src/kadmin/cli/kadmin.c:1419 +#, c-format +msgid "while retrieving \"%s\"." +msgstr "\"%s\"-ის მიღებისას." + +#: ../../src/kadmin/cli/kadmin.c:1424 ../../src/kadmin/cli/kadmin.c:1429 +msgid "while unparsing principal" +msgstr "პრინციპალის დამუშავების გაუქმებისას" + +#: ../../src/kadmin/cli/kadmin.c:1433 +#, c-format +msgid "Principal: %s\n" +msgstr "პრინციპალი: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1434 +#, c-format +msgid "Expiration date: %s\n" +msgstr "ვადის თარიღი: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1435 ../../src/kadmin/cli/kadmin.c:1437 +#: ../../src/kadmin/cli/kadmin.c:1440 ../../src/kadmin/cli/kadmin.c:1448 +msgid "[never]" +msgstr "[არასდროს]" + +#: ../../src/kadmin/cli/kadmin.c:1436 +#, c-format +msgid "Last password change: %s\n" +msgstr "პაროლის ბოლო ცვლილება: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1438 +#, c-format +msgid "Password expiration date: %s\n" +msgstr "პაროლის ამოწურვის ვადა: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1441 +#, c-format +msgid "Maximum ticket life: %s\n" +msgstr "ბილეთის მაქსიმალური სიცოცხლე: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1442 +#, c-format +msgid "Maximum renewable life: %s\n" +msgstr "მაქსიმალური განახლებადი სიცოცხლე: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1444 +#, c-format +msgid "Last modified: %s (%s)\n" +msgstr "ბოლო ცვლილება: %s (%s)\n" + +#: ../../src/kadmin/cli/kadmin.c:1446 +#, c-format +msgid "Last successful authentication: %s\n" +msgstr "ბოლო წარმატებული ავთენტიკაცია: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1452 +#, c-format +msgid "Failed password attempts: %d\n" +msgstr "პაროლის წარუმატებელი მცდელობები: %d\n" + +#: ../../src/kadmin/cli/kadmin.c:1454 +#, c-format +msgid "Number of keys: %d\n" +msgstr "გასაღებების რაოდენობა: %d\n" + +#: ../../src/kadmin/cli/kadmin.c:1462 +#, c-format +msgid "" +msgstr "<შიფრაციის ტიპი 0x%x>" + +#: ../../src/kadmin/cli/kadmin.c:1474 +#, c-format +msgid "" +msgstr "<მარილის ტიპი 0x%x>" + +#: ../../src/kadmin/cli/kadmin.c:1480 +#, c-format +msgid "MKey: vno %d\n" +msgstr "MKey: vno %d\n" + +#: ../../src/kadmin/cli/kadmin.c:1482 +#, c-format +msgid "Attributes:" +msgstr "ატრიბუტები:" + +#: ../../src/kadmin/cli/kadmin.c:1485 +msgid "while printing flags" +msgstr "ალმების გამოტანისას" + +#: ../../src/kadmin/cli/kadmin.c:1494 +msgid "[none]" +msgstr "[არცერთი]" + +#: ../../src/kadmin/cli/kadmin.c:1496 +msgid " [does not exist]" +msgstr " [არ არსებობს]" + +#: ../../src/kadmin/cli/kadmin.c:1497 +#, c-format +msgid "Policy: %s%s\n" +msgstr "პოლიტიკა: %s%s\n" + +#: ../../src/kadmin/cli/kadmin.c:1533 +msgid "usage: get_principals [expression]\n" +msgstr "გამოყენება: get_principals [გამოსახულება]\n" + +#: ../../src/kadmin/cli/kadmin.c:1538 ../../src/kadmin/cli/kadmin.c:1789 +msgid "while retrieving list." +msgstr "სიის მიღებისას." + +#: ../../src/kadmin/cli/kadmin.c:1643 +#, c-format +msgid "%s: parser lost count!\n" +msgstr "%s: დამმუშავებელმა სათვალავი დაკარგა!\n" + +#: ../../src/kadmin/cli/kadmin.c:1652 +#, c-format +msgid "usage; %s [options] policy\n" +msgstr "გამოყენება; %s [პარამეტრები] პოლიტიკა\n" + +#: ../../src/kadmin/cli/kadmin.c:1654 +msgid "" +"\t\t[-maxlife time] [-minlife time] [-minlength length]\n" +"\t\t[-minclasses number] [-history number]\n" +"\t\t[-maxfailure number] [-failurecountinterval time]\n" +"\t\t[-allowedkeysalts keysalts]\n" +msgstr "" +"\t\t[-maxlife დრო] [-minlife დრო] [-minlength სიგრძე]\n" +"\t\t[-minclasses რიცხვი] [-history რიცხვი]\n" +"\t\t[-maxfailure რიცხვი] [-failurecountinterval დრო]\n" +"\t\t[-allowedkeysalts keysalts]\n" + +#: ../../src/kadmin/cli/kadmin.c:1658 +msgid "\t\t[-lockoutduration time]\n" +msgstr "\t\t[-lockoutduration დრო]\n" + +#: ../../src/kadmin/cli/kadmin.c:1677 +#, c-format +msgid "while creating policy \"%s\"." +msgstr "პოლიტიკის (\"%s\") შექმნისას." + +#: ../../src/kadmin/cli/kadmin.c:1698 +#, c-format +msgid "while modifying policy \"%s\"." +msgstr "პოლიტიკის (\"%s\") ცვლილებისას." + +#: ../../src/kadmin/cli/kadmin.c:1710 +msgid "usage: delete_policy [-force] policy\n" +msgstr "გამოყენება: delete_policy [-force] პოლიტიკა\n" + +#: ../../src/kadmin/cli/kadmin.c:1714 +#, c-format +msgid "Are you sure you want to delete the policy \"%s\"? (yes/no): " +msgstr "" +"დარწმუნებული ბრძანდებით რომ გნებავთ პოლიკიტიკს \"%s\" საბოლოოდ წაშლა? " +"(yes(დიახ)/no(არა)): " + +#: ../../src/kadmin/cli/kadmin.c:1718 +#, c-format +msgid "Policy \"%s\" not deleted.\n" +msgstr "პოლიტიკა \"%s\" არ წაშლილა\n" + +#: ../../src/kadmin/cli/kadmin.c:1724 +#, c-format +msgid "while deleting policy \"%s\"" +msgstr "პოლიტიკის \"%s\" წაშლისას" + +#: ../../src/kadmin/cli/kadmin.c:1736 +msgid "usage: get_policy [-terse] policy\n" +msgstr "გამოყენება: get_policy [-terse] პოლიტიკა\n" + +#: ../../src/kadmin/cli/kadmin.c:1741 +#, c-format +msgid "while retrieving policy \"%s\"." +msgstr "პოლიტიკის (\"%s\") მიღებისას." + +#: ../../src/kadmin/cli/kadmin.c:1746 +#, c-format +msgid "Policy: %s\n" +msgstr "პოლიტიკა: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1747 +#, c-format +msgid "Maximum password life: %s\n" +msgstr "პაროლის მაქსიმალური სიცოცხლე: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1748 +#, c-format +msgid "Minimum password life: %s\n" +msgstr "პაროლის მინიმალური სიცოცხლე: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1749 +#, c-format +msgid "Minimum password length: %ld\n" +msgstr "პაროლის მინიმალური სიგრძე: %ld\n" + +#: ../../src/kadmin/cli/kadmin.c:1750 +#, c-format +msgid "Minimum number of password character classes: %ld\n" +msgstr "პაროლის სიმბოლოების კლასების მინიმალური რიცხვი: %ld\n" + +#: ../../src/kadmin/cli/kadmin.c:1752 +#, c-format +msgid "Number of old keys kept: %ld\n" +msgstr "დამახსოვრებული ძველი გასაღებები: %ld\n" + +#: ../../src/kadmin/cli/kadmin.c:1753 +#, c-format +msgid "Maximum password failures before lockout: %lu\n" +msgstr "დაბლოკვამდე პაროლის არასწორად შეყვანების რაოდენობა: %lu\n" + +#: ../../src/kadmin/cli/kadmin.c:1755 +#, c-format +msgid "Password failure count reset interval: %s\n" +msgstr "პაროლის არასწორად შეყვანისას დაბლოკვის განბლოკვის ინტერვალი: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1757 +#, c-format +msgid "Password lockout duration: %s\n" +msgstr "პაროლის დაბლოკვის ხანგრძლივობა: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1760 +#, c-format +msgid "Allowed key/salt types: %s\n" +msgstr "მარილის/გასაღების დასაშვები ტიპები: %s\n" + +#: ../../src/kadmin/cli/kadmin.c:1784 +msgid "usage: get_policies [expression]\n" +msgstr "გამოყენება: get_policies [გამოსახულება]\n" + +#: ../../src/kadmin/cli/kadmin.c:1806 +msgid "usage: get_privs\n" +msgstr "გამოყენება: get_privs\n" + +#: ../../src/kadmin/cli/kadmin.c:1811 +msgid "while retrieving privileges" +msgstr "პრივილეგიების მიღებისას" + +#: ../../src/kadmin/cli/kadmin.c:1814 +#, c-format +msgid "current privileges:" +msgstr "მიმდინარე პრივილეგიები:" + +#: ../../src/kadmin/cli/kadmin.c:1840 +msgid "usage: purgekeys [-all|-keepkvno oldest_kvno_to_keep] principal\n" +msgstr "" +"გამოყენება: purgekeys [-all|-keepkvno უძველესი_დასატოვებელი_kvno] " +"პრინციპალი\n" + +#: ../../src/kadmin/cli/kadmin.c:1860 +#, c-format +msgid "while purging keys for principal \"%s\"" +msgstr "პრინციპალისთვის \"%s\" გასაღებების წაშლისას" + +#: ../../src/kadmin/cli/kadmin.c:1865 +#, c-format +msgid "All keys for principal \"%s\" removed.\n" +msgstr "პრინციპალისთვის \"%s\" ყველა გასაღები წაშლილია.\n" + +#: ../../src/kadmin/cli/kadmin.c:1867 +#, c-format +msgid "Old keys for principal \"%s\" purged.\n" +msgstr "პრინციპალისთვის \"%s\" ძველი გასაღებები წაშლილია.\n" + +#: ../../src/kadmin/cli/kadmin.c:1884 +msgid "usage: get_strings principal\n" +msgstr "გამოყენება: get_strings პრინციპალი\n" + +#: ../../src/kadmin/cli/kadmin.c:1904 +#, c-format +msgid "while getting attributes for principal \"%s\"" +msgstr "ატრიბუტების მიღებისას პრინციპალისთვის \"%s\"" + +#: ../../src/kadmin/cli/kadmin.c:1909 +#, c-format +msgid "(No string attributes.)\n" +msgstr "(სტრიქონული ატრიბუტების გარეშე.)\n" + +#: ../../src/kadmin/cli/kadmin.c:1928 +msgid "usage: set_string principal key value\n" +msgstr "გამოყენება: set_string პრინციპალი გასაღები მნიშვნელობა\n" + +#: ../../src/kadmin/cli/kadmin.c:1950 +#, c-format +msgid "while setting attribute on principal \"%s\"" +msgstr "პრინციპალზე (\"%s\") ატრიბუტის დაყენებისას" + +#: ../../src/kadmin/cli/kadmin.c:1954 +#, c-format +msgid "Attribute set for principal \"%s\".\n" +msgstr "პრინციპალზე (\"%s\") ატრიბუტი დაყენებულია.\n" + +#: ../../src/kadmin/cli/kadmin.c:1969 +msgid "usage: del_string principal key\n" +msgstr "გამოყენება: del_string პრინციპალი გასაღები\n" + +#: ../../src/kadmin/cli/kadmin.c:1990 +#, c-format +msgid "while deleting attribute from principal \"%s\"" +msgstr "პრინციპალიდან (\"%s\") ატრიბუტის წაშლისას" + +#: ../../src/kadmin/cli/kadmin.c:1994 +#, c-format +msgid "Attribute removed from principal \"%s\".\n" +msgstr "პრინციპალიდან (\"%s\") ატრიბუტი წაშლილია\n" + +#: ../../src/kadmin/cli/keytab.c:55 +#, c-format +msgid "" +"Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [-norandkey] " +"[principal | -glob princ-exp] [...]\n" +msgstr "" +"გამოყენება: ktadd [-k[eytab] keytab] [-q] [-e გასაღებისმარილებისსია] [-" +"norandkey] [პრინციპალი | -glob princ-exp] [...]\n" + +#: ../../src/kadmin/cli/keytab.c:62 +#, c-format +msgid "" +"Usage: ktremove [-k[eytab] keytab] [-q] principal [kvno|\"all\"|\"old\"]\n" +msgstr "" +"გამოყენება: ktremove [-k[eytab] keytab] [-q] პრინციპალი [kvno|\"all\"(ყველა)|" +"\"old\"(ძველი)]\n" + +#: ../../src/kadmin/cli/keytab.c:76 ../../src/kadmin/cli/keytab.c:97 +msgid "while creating keytab name" +msgstr "keytab-ის სახელის შექმნისას" + +#: ../../src/kadmin/cli/keytab.c:81 +msgid "while opening default keytab" +msgstr "ნაგულისხმები keytab-ის გახსნისას" + +#: ../../src/kadmin/cli/keytab.c:165 +#, c-format +msgid "cannot specify keysaltlist when not changing key\n" +msgstr "როცა გასაღბს არ ცვლით, keysaltlist-ს ვერ მიუთითებთ\n" + +#: ../../src/kadmin/cli/keytab.c:181 +#, c-format +msgid "while expanding expression \"%s\"." +msgstr "გამოსახულების (\"%s\") გაფართოებისას." + +#: ../../src/kadmin/cli/keytab.c:200 ../../src/kadmin/cli/keytab.c:240 +msgid "while closing keytab" +msgstr "keytab-ის დახურვისას" + +#: ../../src/kadmin/cli/keytab.c:314 +#, c-format +msgid "while parsing -add principal name %s" +msgstr "-add პრინციპალის სახელის %s დამუშავებისას" + +#: ../../src/kadmin/cli/keytab.c:328 +#, c-format +msgid "%s: Principal %s does not exist.\n" +msgstr "%s: პრინციპალი %s არ არსებობს.\n" + +#: ../../src/kadmin/cli/keytab.c:331 +#, c-format +msgid "while changing %s's key" +msgstr "%s-ის გასაღების შეცვლისას" + +#: ../../src/kadmin/cli/keytab.c:343 +msgid "while adding key to keytab" +msgstr "გასაღების keytab-ში ჩამატებისას" + +#: ../../src/kadmin/cli/keytab.c:348 +#, c-format +msgid "" +"Entry for principal %s with kvno %d, encryption type %s added to keytab %s.\n" +msgstr "" +"ჩანაწერი პრინციპალისთვის %s kvno-ით %d, დაშიფვრის ტიპი %s დამატებულია keytab-" +"ში %s.\n" + +#: ../../src/kadmin/cli/keytab.c:396 +#, c-format +msgid "%s: Keytab %s does not exist.\n" +msgstr "%s: Keytab-ი %s არ არსებობს.\n" + +#: ../../src/kadmin/cli/keytab.c:400 +#, c-format +msgid "%s: No entry for principal %s exists in keytab %s\n" +msgstr "%s: პრინციპალისთვის %s keytab-ში %s ჩანაწერი არ არსებობს\n" + +#: ../../src/kadmin/cli/keytab.c:404 +#, c-format +msgid "%s: No entry for principal %s with kvno %d exists in keytab %s\n" +msgstr "%s: პრინციპალისთვის %s kvno-ით %d, keytab-ში %s ჩანაწერი არ არსებობს\n" + +#: ../../src/kadmin/cli/keytab.c:410 +msgid "while retrieving highest kvno from keytab" +msgstr "keytab-დან უმაღლესი kvno-ის მიღებისას" + +#: ../../src/kadmin/cli/keytab.c:443 +msgid "while temporarily ending keytab scan" +msgstr "keytab-ის სკანირების დროებით დასრულებისას" + +#: ../../src/kadmin/cli/keytab.c:448 +msgid "while deleting entry from keytab" +msgstr "keytab-დან ჩანაწერის წაშლისას" + +#: ../../src/kadmin/cli/keytab.c:453 +msgid "while restarting keytab scan" +msgstr "keytab-ის სკანირების თავიდან გაშვებისას" + +#: ../../src/kadmin/cli/keytab.c:459 +#, c-format +msgid "Entry for principal %s with kvno %d removed from keytab %s.\n" +msgstr "ჩანაწერი პრინციპალისთვის %s kvno-ით %d წაშლილია keytab-დან %s.\n" + +#: ../../src/kadmin/cli/keytab.c:481 +#, c-format +msgid "%s: There is only one entry for principal %s in keytab %s\n" +msgstr "%s: პრინციპალისთვის %s keytab-ში %s მხოლოდ ერთი ჩანაწერი არსებობს\n" + +#: ../../src/kadmin/cli/ss_wrapper.c:53 ../../src/kadmin/ktutil/ktutil.c:58 +msgid "creating invocation" +msgstr "ჩაწოდების შექმნა" + +#: ../../src/kadmin/dbutil/dump.c:165 +msgid "while allocating temporary filename dump" +msgstr "დროებითი ფაილის სახელის დამპის გამოყოფისას" + +#: ../../src/kadmin/dbutil/dump.c:176 +msgid "while renaming dump file into place" +msgstr "დამპის ფაილის ადგილზე სახელის გადარქმევისას" + +#: ../../src/kadmin/dbutil/dump.c:196 +msgid "while allocating dump_ok filename" +msgstr "dump_ok ფაილის სახელის გამოყოფისას" + +#: ../../src/kadmin/dbutil/dump.c:202 +#, c-format +msgid "while creating 'ok' file, '%s'" +msgstr "'ok' ფაილის შექმნისას, '%s'" + +#: ../../src/kadmin/dbutil/dump.c:207 +#, c-format +msgid "while locking 'ok' file, '%s'" +msgstr "'ok' ფაილის დაბლოკვისას. '%s'" + +#: ../../src/kadmin/dbutil/dump.c:260 ../../src/kadmin/dbutil/dump.c:289 +#, c-format +msgid "%s: regular expression error: %s\n" +msgstr "%s: რეგულარული გამოსახულების შეცდომა: %s\n" + +#: ../../src/kadmin/dbutil/dump.c:272 +#, c-format +msgid "%s: regular expression match error: %s\n" +msgstr "%s: რეგულარული გამოსახულების დამთხვევის შეცდომა: %s\n" + +#: ../../src/kadmin/dbutil/dump.c:373 +#, c-format +msgid "%s: tagged data list inconsistency for %s (counted %d, stored %d)\n" +msgstr "" +"%s ჭდის მქონე მონაცემების სია არათანამიმდევრულია %s-სთვის (დათვლილია %d, " +"დამახსოვრებულია %d)\n" + +#: ../../src/kadmin/dbutil/dump.c:495 +#, c-format +msgid "while converting %s to new master key" +msgstr "%s -ის ახალ მთავარ გასაღებზე გადაყვანისას" + +#: ../../src/kadmin/dbutil/dump.c:516 +#, c-format +msgid "%s(%d): %s\n" +msgstr "%s(%d): %s\n" + +#: ../../src/kadmin/dbutil/dump.c:559 +#, c-format +msgid "%s(%d): ignoring trash at end of line: " +msgstr "%s(%d): ბოლოში ნაგავი იგნორირებულია: " + +#: ../../src/kadmin/dbutil/dump.c:622 +msgid "cannot read tagged data type and length" +msgstr "ჭდის მქონე მონაცემების ტიპის და სიგრძის წაკითხვის შეცდომა" + +#: ../../src/kadmin/dbutil/dump.c:626 +msgid "data type or length overflowed" +msgstr "მონაცემების ტიპი ან სიგრძე გადავსებულია" + +#: ../../src/kadmin/dbutil/dump.c:633 +msgid "cannot read tagged data contents" +msgstr "ჭდის მქონე მონაცემების შემცველობის წაკითხვის შეცდომა" + +#: ../../src/kadmin/dbutil/dump.c:666 +msgid "cannot match size tokens" +msgstr "კოდის ზომები არ ემთხვევა" + +#: ../../src/kadmin/dbutil/dump.c:672 +msgid "cannot allocate principal (too large)" +msgstr "პრინციპალის გამოყოფის შეცდომა (ძალიან დიდია)" + +#: ../../src/kadmin/dbutil/dump.c:681 +msgid "cannot allocate tl_data (too large)" +msgstr "tl_data-ის გამოყოფის შეცდომა (ძალიან დიდია)" + +#: ../../src/kadmin/dbutil/dump.c:690 +msgid "invalid key_data size" +msgstr "key_data-ის არასწორი ზომა" + +#: ../../src/kadmin/dbutil/dump.c:707 +msgid "cannot read name string" +msgstr "სახელის სტრიქონის წაკითხვის შეცდომა" + +#: ../../src/kadmin/dbutil/dump.c:712 +#, c-format +msgid "while parsing name %s" +msgstr "სახელის (%s) დამუშავებისას" + +#: ../../src/kadmin/dbutil/dump.c:720 +msgid "cannot read principal attributes" +msgstr "პრინციპალის ატრიბუტების წაკითხვის შეცდომა" + +#: ../../src/kadmin/dbutil/dump.c:773 +msgid "cannot read key size and version" +msgstr "გასაღების ზომისა და ვერსიის წაკითხვის შეცდომა" + +#: ../../src/kadmin/dbutil/dump.c:777 +msgid "unsupported key_data_ver version" +msgstr "key_data_ver -ის მხარდაუჭერელი ვერსია" + +#: ../../src/kadmin/dbutil/dump.c:781 +msgid "invalid kvno" +msgstr "არასწორი kvno" + +#: ../../src/kadmin/dbutil/dump.c:792 +msgid "cannot read key type and length" +msgstr "გასაღების ტიპისა და სიგრძის წაკითხვის შეცდომა" + +#: ../../src/kadmin/dbutil/dump.c:798 +msgid "cannot read key data" +msgstr "გასაღების მონაცემების წაკითხვის შეცდომა" + +#: ../../src/kadmin/dbutil/dump.c:808 +msgid "cannot read extra data" +msgstr "დამატებითი მონაცემების წაკითხვის შეცდომა" + +#: ../../src/kadmin/dbutil/dump.c:817 +#, c-format +msgid "while storing %s" +msgstr "%s-ის შენახვისას" + +#: ../../src/kadmin/dbutil/dump.c:856 ../../src/kadmin/dbutil/dump.c:895 +#: ../../src/kadmin/dbutil/dump.c:941 ../../src/kadmin/dbutil/dump.c:960 +#, c-format +msgid "cannot parse policy (%d read)\n" +msgstr "პოლიტიკის დამუშავების შეცდომა (%d წაკითხულია)\n" + +#: ../../src/kadmin/dbutil/dump.c:864 ../../src/kadmin/dbutil/dump.c:903 +#: ../../src/kadmin/dbutil/dump.c:981 +msgid "while creating policy" +msgstr "პოლიტიკის შექმნისას" + +#: ../../src/kadmin/dbutil/dump.c:868 +#, c-format +msgid "created policy %s\n" +msgstr "შეიქმნა პოლიტიკა %s\n" + +#: ../../src/kadmin/dbutil/dump.c:1018 +#, c-format +msgid "unknown record type \"%s\"\n" +msgstr "ჩანაწერის უცნობი ტიპი \"%s\"\n" + +#: ../../src/kadmin/dbutil/dump.c:1129 +#, c-format +msgid "%s: Unknown iprop dump version %d\n" +msgstr "%s: iprop-ის დამპის უცნობი ვერსია %d\n" + +#: ../../src/kadmin/dbutil/dump.c:1207 ../../src/kadmin/dbutil/dump.c:1443 +#, c-format +msgid "OV dump format not supported\n" +msgstr "OV დამპის ფორმატი მხარდაუჭერელია\n" + +#: ../../src/kadmin/dbutil/dump.c:1229 ../../src/kadmin/dbutil/dump.c:1455 +#, c-format +msgid "Iprop not enabled\n" +msgstr "Iprop ჩართული არაა\n" + +#: ../../src/kadmin/dbutil/dump.c:1266 +msgid "Conditional dump is an undocumented option for use only for iprop dumps" +msgstr "" +"პირობითი დამპი არადოკუმენტირებული პარამეტრია, რომელიც მხოლოდ iprop-ის " +"დამპებისთვის გამოიყენება" + +#: ../../src/kadmin/dbutil/dump.c:1279 +msgid "Database not currently opened!" +msgstr "ბაზა ამჟამად ღია არაა!" + +#: ../../src/kadmin/dbutil/dump.c:1293 ../../src/kadmin/dbutil/kdb5_stash.c:116 +#: ../../src/kadmin/dbutil/kdb5_util.c:445 +msgid "while reading master key" +msgstr "მთავარი გასაღების წაკითხვისას" + +#: ../../src/kadmin/dbutil/dump.c:1299 +msgid "while verifying master key" +msgstr "მთავარი გასაღების გადამოწმებისას" + +#: ../../src/kadmin/dbutil/dump.c:1318 ../../src/kadmin/dbutil/dump.c:1328 +msgid "while reading new master key" +msgstr "ახალი მთავარი გასაღების წაკითხვისას" + +#: ../../src/kadmin/dbutil/dump.c:1322 +#, c-format +msgid "Please enter new master key....\n" +msgstr "შეიყვანეთ ახალი მთავარი გასაღები...\n" + +#: ../../src/kadmin/dbutil/dump.c:1346 +#, c-format +msgid "while opening %s for writing" +msgstr "%s-ის ჩასაწერად გახსნისას" + +#: ../../src/kadmin/dbutil/dump.c:1361 +msgid "while reading update log header" +msgstr "განახლების ჟურნალის თავსართის წაკითხვისას" + +#: ../../src/kadmin/dbutil/dump.c:1376 ../../src/kadmin/dbutil/dump.c:1384 +#, c-format +msgid "performing %s dump" +msgstr "მიმდინარეობს %s-ის დამპი" + +#: ../../src/kadmin/dbutil/dump.c:1414 +#, c-format +msgid "%s: error processing line %d of %s\n" +msgstr "%s: შეცდომა %d ხაზის დამუშავებისას, %s-დან\n" + +#: ../../src/kadmin/dbutil/dump.c:1464 +msgid "while parsing options" +msgstr "პარამეტრების დამუშავებისას" + +#: ../../src/kadmin/dbutil/dump.c:1479 +#, c-format +msgid "while opening %s" +msgstr "\"%s\"-ის გახსნისას" + +#: ../../src/kadmin/dbutil/dump.c:1484 ../../src/kadmin/dbutil/dump.c:1580 +msgid "standard input" +msgstr "სტანდარტული შეყვანა" + +#: ../../src/kadmin/dbutil/dump.c:1489 +#, c-format +msgid "%s: can't read dump header in %s\n" +msgstr "%s: %s-ში დამპის თავსართის წაკითხვის შეცდომა\n" + +#: ../../src/kadmin/dbutil/dump.c:1497 ../../src/kadmin/dbutil/dump.c:1511 +#, c-format +msgid "%s: dump header bad in %s\n" +msgstr "%s: დამპის არასწორი თავსართი %s-ში\n" + +#: ../../src/kadmin/dbutil/dump.c:1520 +#, c-format +msgid "Could not open iprop ulog\n" +msgstr "შეცდომა iprop ulog-ის გახსნისას\n" + +#: ../../src/kadmin/dbutil/dump.c:1525 +#, c-format +msgid "%s: dump version %s can only be loaded with the -update flag\n" +msgstr "%s: დამპის ვერსია %s მხოლოდ -update ალმით შეიძლება ჩაიტვირთოს\n" + +#: ../../src/kadmin/dbutil/dump.c:1534 ../../src/kadmin/dbutil/dump.c:1539 +msgid "computing parameters for database" +msgstr "ბაზისთვის პარამეტრების გამოთვლა" + +#: ../../src/kadmin/dbutil/dump.c:1545 +msgid "while creating database" +msgstr "ბაზის შექმნისას" + +#: ../../src/kadmin/dbutil/dump.c:1554 +msgid "while opening database" +msgstr "ბაზის გახსნისას" + +#: ../../src/kadmin/dbutil/dump.c:1564 +msgid "while permanently locking database" +msgstr "ბაზის სამუდამოდ დაბლოკვისას" + +#: ../../src/kadmin/dbutil/dump.c:1582 +#, c-format +msgid "%s: %s restore failed\n" +msgstr "%s: %s აღდგენის შეცდომა\n" + +#: ../../src/kadmin/dbutil/dump.c:1587 +msgid "while unlocking database" +msgstr "ბაზის განბლოკვისას" + +#: ../../src/kadmin/dbutil/dump.c:1597 ../../src/kadmin/dbutil/dump.c:1616 +msgid "while reinitializing update log" +msgstr "განახლების ჟურნალის თავიდან ინიციალიზაციისას" + +#: ../../src/kadmin/dbutil/dump.c:1607 +msgid "while making newly loaded database live" +msgstr "ახლად ჩატვირთული ბაზის სამუშაო რეჟიმში გადართვისას" + +#: ../../src/kadmin/dbutil/dump.c:1623 +msgid "while writing update log header" +msgstr "განახლების ჟურნალის თავსართის ჩაწერისას" + +#: ../../src/kadmin/dbutil/dump.c:1637 +#, c-format +msgid "while deleting bad database %s" +msgstr "ცუდი ბაზის (%s) წაშლისას" + +#: ../../src/kadmin/dbutil/kadm5_create.c:79 +msgid "while looking up the Kerberos configuration" +msgstr "kerberos-ის კონფიგურაციის ძებნისას" + +#: ../../src/kadmin/dbutil/kadm5_create.c:105 +msgid "while initializing the Kerberos admin interface" +msgstr "kerberos-ის ადმინისტრირების ინტერფეისის ინიციალიზაციისას" + +#: ../../src/kadmin/dbutil/kadm5_create.c:197 +msgid "while appending realm to principal" +msgstr "რეალმის პრინციპალზე მიწერისას" + +#: ../../src/kadmin/dbutil/kadm5_create.c:203 +msgid "while parsing admin principal name" +msgstr "ადმინის პრინციპალის სახელის დამუშავებისას" + +#: ../../src/kadmin/dbutil/kadm5_create.c:215 +#, c-format +msgid "while creating principal %s" +msgstr "პრინციპალი \"%s\"-ის შექმნისას" + +#: ../../src/kadmin/dbutil/kdb5_create.c:186 +#: ../../src/kadmin/dbutil/kdb5_util.c:389 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:574 +msgid "while setting up master key name" +msgstr "მთავარი გასაღების სახელის დაყენებისას" + +#: ../../src/kadmin/dbutil/kdb5_create.c:197 +#, c-format +msgid "" +"Initializing database '%s' for realm '%s',\n" +"master key name '%s'\n" +msgstr "" +"ბაზის (\"%s\") ინიციალიზაცია რეალმისთვის '%s'.\n" +"მთავარი გასაღებს სახელია '%s'\n" + +#: ../../src/kadmin/dbutil/kdb5_create.c:202 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:483 +#, c-format +msgid "You will be prompted for the database Master Password.\n" +msgstr "ბაზის მთავარ პაროლს შეგეკითხებით.\n" + +#: ../../src/kadmin/dbutil/kdb5_create.c:203 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:255 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:484 +#, c-format +msgid "It is important that you NOT FORGET this password.\n" +msgstr "ძალიან მნიშვნელოვანია, რომ ეს პაროლი *არასდროს დაგავიწყდეთ*.\n" + +#: ../../src/kadmin/dbutil/kdb5_create.c:209 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:261 +msgid "while creating new master key" +msgstr "ახალი მთავარი გასაღების შექმნისას" + +#: ../../src/kadmin/dbutil/kdb5_create.c:217 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:494 +msgid "while reading master key from keyboard" +msgstr "მთავარი გასაღების კლავიატურიდან წაკითხვისას" + +#: ../../src/kadmin/dbutil/kdb5_create.c:227 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:280 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:586 +msgid "while calculating master key salt" +msgstr "მთავარი გასაღების მარილის გამოთვლისას" + +#: ../../src/kadmin/dbutil/kdb5_create.c:235 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:289 +#: ../../src/kadmin/dbutil/kdb5_util.c:431 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:598 +msgid "while transforming master key from password" +msgstr "მთავარი გასაღების პაროლიდან გარდაქმნისას" + +#: ../../src/kadmin/dbutil/kdb5_create.c:245 +msgid "while initializing random key generator" +msgstr "შემთხვევითი რიცხვების გენერატორის ინიციალიზაციისას" + +#: ../../src/kadmin/dbutil/kdb5_create.c:250 +#, c-format +msgid "while creating database '%s'" +msgstr "ბაზის (\"%s\") შექმნისას" + +#: ../../src/kadmin/dbutil/kdb5_create.c:268 +msgid "while creating update log" +msgstr "განახლების ჟურნალის შექმნისას" + +#: ../../src/kadmin/dbutil/kdb5_create.c:279 +msgid "while initializing update log" +msgstr "განახლების ჟურნალის ინიციალიზაციისას" + +#: ../../src/kadmin/dbutil/kdb5_create.c:294 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:610 +msgid "while adding entries to the database" +msgstr "ბაზაში ჩანაწერების დამატებისას" + +#: ../../src/kadmin/dbutil/kdb5_create.c:322 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:333 +#: ../../src/kadmin/dbutil/kdb5_stash.c:133 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:635 +msgid "while storing key" +msgstr "გასაღების შენახვისას" + +#: ../../src/kadmin/dbutil/kdb5_create.c:323 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:334 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:636 +#, c-format +msgid "Warning: couldn't stash master key.\n" +msgstr "გაფრთხილება: მთავარი გასაღების მოგროვების შეცდომა.\n" + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:69 +#, c-format +msgid "Deleting KDC database stored in '%s', are you sure?\n" +msgstr "" +"წაიშლება KDC-ის ბაზა, დამახსოვრებული '%s'-ში. დარწმუნებული ბრძანდებით?\n" + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:71 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1111 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:360 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1442 +#, c-format +msgid "(type 'yes' to confirm)? " +msgstr "(დასადასტურებლად აკრიფეთ 'yes' (დიახ)? " + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:78 +#, c-format +msgid "OK, deleting database '%s'...\n" +msgstr "კარგი, მიმდინარეობს ბაზის წაშლა '%s'...\n" + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:83 +#, c-format +msgid "deleting database '%s'" +msgstr "ბაზის წაშლა '%s'..." + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:92 +#, c-format +msgid "** Database '%s' destroyed.\n" +msgstr "** ბაზა '%s' განადგურდა.\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:223 +#, c-format +msgid "%s is an invalid enctype" +msgstr "%s არასწორი enctype-ა" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:245 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:421 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:564 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:941 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1102 +#, c-format +msgid "while getting master key principal %s" +msgstr "მთავარი გასაღების პრინციპალის (%s) მიღებისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:251 +#, c-format +msgid "Creating new master key for master key principal '%s'\n" +msgstr "ახალი მთავარი გასაღების დამატება მთავარი პრინციპალისთვის '%s'\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:254 +#, c-format +msgid "You will be prompted for a new database Master Password.\n" +msgstr "ბაზის ახალ მთავარ პაროლს შეგეკითხებით.\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:270 +msgid "while reading new master key from keyboard" +msgstr "ახალი მთავარი გასაღების კლავიატურიდან წაკითხვისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:299 +msgid "adding new master key to master principal" +msgstr "ახალი მთავარი გასაღების მთავარი პრინციპალისთვის დამატება" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:305 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:390 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:806 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1305 +msgid "while getting current time" +msgstr "მიმდინარე დროის მიღებისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:312 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:522 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1312 +msgid "while updating the master key principal modification time" +msgstr "მთავარი გასაღების პრინციპალის ცვლილების დროის განახლებისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:319 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:530 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1322 +msgid "while adding master key entry to the database" +msgstr "მთავარი გასაღების ჩანაწერის ბაზაში ჩამატებისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:371 +msgid "0 is an invalid KVNO value" +msgstr "0 KVNO-ის არასწორი მნიშვნელობაა" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:382 +#, c-format +msgid "%d is an invalid KVNO value" +msgstr "%d KVNO-ის არასწორი მნიშვნელობაა" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:398 +#, c-format +msgid "could not parse date-time string '%s'" +msgstr "თარითი-დროის სტრიქონის \"%s\" დამუშავების შეცდომა" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:430 +msgid "while looking up active version of master key" +msgstr "მთავარი გასაღების აქტიური ვერსიის მოძებნისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:469 +msgid "while adding new master key" +msgstr "ახალი მთავარი გასაღების დამატებისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:507 +msgid "there must be one master key currently active" +msgstr "მიმდინარე დროს ერთი მთავარი გასაღები ყოველთვის უნდა იყოს აქტიური" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:515 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1291 +msgid "while updating actkvno data for master principal entry" +msgstr "მთავარი პრინციპალის ცანაწერის actkvno-ის მონაცემების განახლებისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:556 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:903 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1072 +msgid "master keylist not initialized" +msgstr "მთავარი keylist ინიციალიზებული არაა" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:572 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:949 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1199 +msgid "while looking up active kvno list" +msgstr "აქტიური kvno-ის სიის ძებნისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:580 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:957 +msgid "while looking up active master key" +msgstr "აქტიური მთავარი გასაღების ძებნისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:592 +msgid "while getting enctype description" +msgstr "enctype-ის აღწერის მიღებისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:609 +#, c-format +msgid "KVNO: %d, Enctype: %s, Active on: %s *\n" +msgstr "KVNO: %d, Enctype: %s, აქტიურია: %s *\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:614 +#, c-format +msgid "KVNO: %d, Enctype: %s, Active on: %s\n" +msgstr "KVNO: %d, Enctype: %s, აქტიურია: %s\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:618 +#, c-format +msgid "KVNO: %d, Enctype: %s, No activate time set\n" +msgstr "KVNO: %d, Enctype: %s, აქტივირების დრო მითითებული არაა\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:623 +msgid "asprintf could not allocate enough memory to hold output" +msgstr "" +"asprintf -ის შეცდომა გამოტანის შეკავებისთვის საკმარისი მეხსიერების " +"გამოყოფისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:756 +msgid "getting string representation of principal name" +msgstr "კლიენტის პრინციპალის სახელის სტრიქონის სახით მიღება" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:780 +#, c-format +msgid "determining master key used for principal '%s'" +msgstr "პრინციპალისთვის (%s) გამოყენებული მთავარი გასაღების განსაზღვრა" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:786 +#, c-format +msgid "would skip: %s\n" +msgstr "გამოვტოვებდი: %s\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:788 +#, c-format +msgid "skipping: %s\n" +msgstr "გამოტოვება: %s\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:794 +#, c-format +msgid "would update: %s\n" +msgstr "განვაახლებდი: %s\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:798 +#, c-format +msgid "updating: %s\n" +msgstr "განახლება: %s\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:802 +#, c-format +msgid "error re-encrypting key for principal '%s'" +msgstr "შეცდომა პრინციპალისთვის ('%s') გასაღების თავიდან დაშიფვრისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:813 +#, c-format +msgid "while updating principal '%s' modification time" +msgstr "პრინციპალის (%s) ცვლილების დროის განახლებისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:820 +#, c-format +msgid "while updating principal '%s' key data in the database" +msgstr "ბააში პრინციპალის (%s) გასაღების მონაცემების განახლებისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:852 +#, c-format +msgid "" +"\n" +"(type 'yes' to confirm)? " +msgstr "" +"\n" +"(დასადასტურებლად აკრიფეთ 'yes' (დიახ)? " + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:914 +#, c-format +msgid "converting glob pattern '%s' to regular expression" +msgstr "გლობის შაბლონის (%s) რეგულარულ გამოსახულებად გარდაქმნა" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:932 +#, c-format +msgid "error compiling converted regexp '%s'" +msgstr "გარდაქმნილი რეგულარული გამოსახულების (%s) კომპილაციის შეცდომა" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:965 +#, c-format +msgid "Re-encrypt all keys not using master key vno %u?" +msgstr "" +"გადავშიფრო ყველა გასაღები, რომელიც მთავარ გასაღებს vno %u -ს არ იყენებს?" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:967 +#, c-format +msgid "OK, doing nothing.\n" +msgstr "კარგი, არაფერს ვაკეთებ.\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:973 +#, c-format +msgid "Principals whose keys WOULD BE re-encrypted to master key vno %u:\n" +msgstr "" +"პრინციპალები, რომლის გასაღებებიც გადაშიფვრადია მთავარი გასაღებით vno %u: \n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:976 +#, c-format +msgid "" +"Principals whose keys are being re-encrypted to master key vno %u if " +"necessary:\n" +msgstr "" +"პრინციპალები, რომლის გასაღებებიც, საჭიროების შემთხვევაში, გადაიშიფრება " +"მთავარი გასაღებით vno %u:\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:992 +msgid "trying to process principal database" +msgstr "პრინციპალის ბაზის დამუშავების მცდელობა" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:996 +#, c-format +msgid "%u principals processed: %u would be updated, %u already current\n" +msgstr "დამუშავებულია %u პრინციპალი: %u განახლებადია, %u უკვე განახლებულია\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1000 +#, c-format +msgid "%u principals processed: %u updated, %u already current\n" +msgstr "დამუშავებულია %u პრინციპალი: %u განახლებულია, %u უკვე მიმდინარეა\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1109 +#, c-format +msgid "" +"Will purge all unused master keys stored in the '%s' principal, are you " +"sure?\n" +msgstr "" +"ყველა გამოუყენებელი მთავარი გასაღები, დამახსოვრებული %s პრინციპალში, " +"წაიშლება. დარწმუნებული ბრძანდებით?\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1120 +#, c-format +msgid "OK, purging unused master keys from '%s'...\n" +msgstr "" +"კარგი. მიმდინარეობს გამოუყენებელი მთავარი გასაღებების %s-დან წაშლა...\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1128 +#, c-format +msgid "There is only one master key which can not be purged.\n" +msgstr "არსებობს მხოლოდ ერთი მთავარი გასაღები და მისი წაშლა აკრძალულია.\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1137 +msgid "while allocating args.kvnos" +msgstr "args.kvnos -ის გამოყოფისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1153 +msgid "while finding master keys in use" +msgstr "გამოყენებული მთავარი გასაღებების ძებნისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1162 +#, c-format +msgid "Would purge the following master key(s) from %s:\n" +msgstr "%s-დან შემდეგი მთავარი გასაღებები წაიშლება:\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1165 +#, c-format +msgid "Purging the following master key(s) from %s:\n" +msgstr "%s-დან შემდეგი მთავარი გასაღებების წაშლა:\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1177 +msgid "master key stash file needs updating, command aborting" +msgstr "" +"მთავარი გასაღების შესაგროვებელ ფაილს განახლება სჭირდება. ბრძანების მუშაობის " +"დასასრული" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1183 +#, c-format +msgid "KVNO: %d\n" +msgstr "KVNO: %d\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1188 +#, c-format +msgid "All keys in use, nothing purged.\n" +msgstr "ყველა გასაღები გამოიყენება. არაფერი წაშლილა.\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1193 +#, c-format +msgid "%d key(s) would be purged.\n" +msgstr "წაიშლებოდა %d გასაღები.\n" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1206 +msgid "while looking up mkey aux data list" +msgstr "mkey-ის დამატებითი მონაცემების სიის ძებნისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1214 +msgid "while allocating key_data" +msgstr "key_data-ის გამოყოფისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1299 +msgid "while updating mkey_aux data for master principal entry" +msgstr "" +"mkey_aux-ის მონაცემების მხოლოდ მთავარი პრინციპალის ჩანაწერის განახლებისას" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1326 +#, c-format +msgid "%d key(s) purged.\n" +msgstr "%d გასაღები წაიშალა.\n" + +#: ../../src/kadmin/dbutil/kdb5_stash.c:97 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:542 +#, c-format +msgid "while setting up enctype %d" +msgstr "enctype %d-ის მორგებისას" + +#: ../../src/kadmin/dbutil/kdb5_stash.c:123 +msgid "while getting master key list" +msgstr "მთავარი გასაღებების სიის მიღებისას" + +#: ../../src/kadmin/dbutil/kdb5_stash.c:127 +#, c-format +msgid "Using existing stashed keys to update stash file.\n" +msgstr "" +"არშებული მოგროვებული გასაღებების გამოყენება დაგროვების ფაილის გასაახლებლად.\n" + +#: ../../src/kadmin/dbutil/kdb5_util.c:80 +#, c-format +msgid "" +"Usage: kdb5_util [-r realm] [-d dbname] [-k mkeytype] [-kv mkeyVNO]\n" +"\t [-M mkeyname] [-m] [-sf stashfilename] [-P password]\n" +"\t [-x db_args]* cmd [cmd_options]\n" +"\tcreate [-s]\n" +"\tdestroy [-f]\n" +"\tstash [-f keyfile]\n" +"\tdump [-b7|-r13|-r18] [-verbose]\n" +"\t [-mkey_convert] [-new_mkey_file mkey_file]\n" +"\t [-rev] [-recurse] [filename [princs...]]\n" +"\tload [-b7|-r13|-r18] [-hash] [-verbose] [-update] filename\n" +"\tark [-e etype_list] principal\n" +"\tadd_mkey [-e etype] [-s]\n" +"\tuse_mkey kvno [time]\n" +"\tlist_mkeys\n" +msgstr "" +"გამოყენება: kdb5_util [-r რეალმი] [-d ბაზის_სახელი] [-k mkeytype] [-kv " +"mkeyVNO]\n" +"\t [-M mkeyname] [-m] [-sf შესაგროვებელიფაილი] [-P პაროლი]\n" +"\t [-x ბაზის_პარამეტრები]* ბრძნბ [ბრძანების_პარამეტრები]\n" +"\tcreate [-s]\n" +"\tdestroy [-f]\n" +"\tstash [-f keyfile]\n" +"\tdump [-b7|-r13|-r18] [-verbose]\n" +"\t [-mkey_convert] [-new_mkey_file mkey_file]\n" +"\t [-rev] [-recurse] [ფაილსი სახელი [პრინციპალები...]]\n" +"\tload [-b7|-r13|-r18] [-hash] [-verbose] [-update] ფაილის სახელი\n" +"\tark [-e etype_list] პრინციპალი\n" +"\tadd_mkey [-e etype] [-s]\n" +"\tuse_mkey kvno [დრო]\n" +"\tlist_mkeys\n" + +#: ../../src/kadmin/dbutil/kdb5_util.c:99 +#, c-format +msgid "" +"\tupdate_princ_encryption [-f] [-n] [-v] [princ-pattern]\n" +"\tpurge_mkeys [-f] [-n] [-v]\n" +"\ttabdump [-H] [-c] [-e] [-n] [-o outfile] dumptype\n" +"\n" +"where,\n" +"\t[-x db_args]* - any number of database specific arguments.\n" +"\t\t\tLook at each database documentation for supported arguments\n" +msgstr "" +"\tupdate_princ_encryption [-f] [-n] [-v] [princ-pattern]\n" +"\tpurge_mkeys [-f] [-n] [-v]\n" +"\ttabdump [-H] [-c] [-e] [-n] [-o outfile] dumptype\n" +"\n" +"სადაც,\n" +"\t[-x ბაზის_არგუმენტები]* - ბაზის არგუმენტების ნებისმიერი რაოდენობა\n" +"\t\t\tმარდაჭერილი არგუმენტების სანახავად მიმართეთ ბაზის დოკუმენტაციას\n" + +#: ../../src/kadmin/dbutil/kdb5_util.c:215 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:264 +msgid "while initializing Kerberos code" +msgstr "kerberos-ის კოდის ინიციალიზაციისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:221 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:271 +msgid "while creating sub-command arguments" +msgstr "ქვებრძანების არგუმენტის შექმნისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:239 +msgid "while parsing command arguments" +msgstr "ბრძანების არგუმენტების დამუშავებისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:245 +#: ../../src/kadmin/dbutil/kdb5_util.c:252 +msgid "while parsing command arguments\n" +msgstr "ბრძანების არგუმენტების დამუშავებისას\n" + +#: ../../src/kadmin/dbutil/kdb5_util.c:263 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:295 +msgid "while setting default realm name" +msgstr "ნაგულისხმები რეალმის სახელის დაყენებისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:268 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:302 +#, c-format +msgid ": %s is an invalid enctype" +msgstr ": %s არასწორი enctype-ა" + +#: ../../src/kadmin/dbutil/kdb5_util.c:276 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:311 +#, c-format +msgid ": %s is an invalid mkeyVNO" +msgstr ": %s არასწორი mkeyVNO -ია" + +#: ../../src/kadmin/dbutil/kdb5_util.c:319 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:435 +msgid "while retrieving configuration parameters" +msgstr "კონფიგურაციის პარამეტრების მიღებისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:378 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:849 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1457 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:568 +msgid "while initializing database" +msgstr "ბაზის ინიციალიზაციისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:395 +msgid "while retrieving master entry" +msgstr "მთავარი ჩანაწერის მიღებისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:414 +msgid "while calculated master key salt" +msgstr "მთავარი გასაღების მარილის გამოთვლისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:446 +msgid "Warning: proceeding without master key" +msgstr "გაფრთხილება: ვაგრძელებ მთავარი გასაღების გარეშე" + +#: ../../src/kadmin/dbutil/kdb5_util.c:464 +msgid "while seeding random number generator" +msgstr "შემთხვევითი რიცხვების გენერატორის თესლის გადაცემისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:474 +#, c-format +msgid "%s: Could not map log\n" +msgstr "%s: ჟურნალის მიბმის შეცომა\n" + +#: ../../src/kadmin/dbutil/kdb5_util.c:503 +msgid "while closing database" +msgstr "ბაზის დახურვისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:550 +#, c-format +msgid "while fetching principal %s" +msgstr "პრინციპალის (%s) გამოთხოვისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:573 +msgid "while finding mkey" +msgstr "mkey-ის ძებნისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:598 +msgid "while setting changetime" +msgstr "changetime-ის დაყენებისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:606 +#, c-format +msgid "while saving principal %s" +msgstr "პრინციპალის (%s) შენახვისას" + +#: ../../src/kadmin/dbutil/kdb5_util.c:610 +#, c-format +msgid "%s changed\n" +msgstr "%s შეიცვალა\n" + +#: ../../src/kadmin/dbutil/tabdump.c:573 +#, c-format +msgid "opening %s for writing" +msgstr "%s-ის ჩასაწერად გახსნა" + +#: ../../src/kadmin/dbutil/tabdump.c:655 +msgid "performing tabular dump" +msgstr "მიმდინარეობს ტაბულარული დამპი" + +#: ../../src/kadmin/ktutil/ktutil.c:73 +#, c-format +msgid "%s: invalid arguments\n" +msgstr "%s: არასწორი არგუმენტები\n" + +#: ../../src/kadmin/ktutil/ktutil.c:78 +msgid "while freeing ktlist" +msgstr "ktlist-ის გათავისუფლებისას" + +#: ../../src/kadmin/ktutil/ktutil.c:89 +#, c-format +msgid "%s: must specify keytab to read\n" +msgstr "%s: წასაკითხი keytab -ის მითითება აუცილებელია\n" + +#: ../../src/kadmin/ktutil/ktutil.c:94 +#, c-format +msgid "while reading keytab \"%s\"" +msgstr "keytab-ის (%s) კითხვისას" + +#: ../../src/kadmin/ktutil/ktutil.c:101 +#, c-format +msgid "%s: reading srvtabs is no longer supported\n" +msgstr "%s: srvtabs -ების წაკითხვა მხარდაჭერილი აღარაა\n" + +#: ../../src/kadmin/ktutil/ktutil.c:112 +#, c-format +msgid "%s: must specify keytab to write\n" +msgstr "%s: ჩასაწერი keytab -ის მითითება აუცილებელია\n" + +#: ../../src/kadmin/ktutil/ktutil.c:117 +#, c-format +msgid "while writing keytab \"%s\"" +msgstr "keytab-ის \"%s\" ჩაწერისას" + +#: ../../src/kadmin/ktutil/ktutil.c:124 +#, c-format +msgid "%s: writing srvtabs is no longer supported\n" +msgstr "%s: srvtabs -ების ჩაწერა მხარდაჭერილი აღარაა\n" + +#: ../../src/kadmin/ktutil/ktutil.c:171 +#, c-format +msgid "" +"usage: %s (-key | -password) -p principal -k kvno [-e enctype] [-f|-s salt]\n" +msgstr "" +"გამოყენება: %s (-key | -პაროლი) -p პრინციპალი -k kvno [-e enctype] [-f|-s " +"მარილი]\n" + +#: ../../src/kadmin/ktutil/ktutil.c:176 +#, c-format +msgid "enctype must be specified if not using -f\n" +msgstr "თუ -f -ს არ იყენებთ, enctype-ის მითითება აუცილებელია\n" + +#: ../../src/kadmin/ktutil/ktutil.c:183 +msgid "while adding new entry" +msgstr "ახალი ჩანაწერის დამატებისას" + +#: ../../src/kadmin/ktutil/ktutil.c:193 +#, c-format +msgid "%s: must specify entry to delete\n" +msgstr "%s: წასაშლელი ჩანაწერის მითითება აუცილებელია\n" + +#: ../../src/kadmin/ktutil/ktutil.c:198 +#, c-format +msgid "while deleting entry %d" +msgstr "%d ჩანაწერის წაშლისას" + +#: ../../src/kadmin/ktutil/ktutil.c:226 +#, c-format +msgid "%s: usage: %s [-t] [-k] [-e]\n" +msgstr "%s: გამოყენება: %s [-t] [-k] [-e]\n" + +#: ../../src/kadmin/ktutil/ktutil.c:265 +msgid "While converting enctype to string" +msgstr "Enctype-ის სტრიქონად გარდაქმნისას" + +#: ../../src/kadmin/ktutil/ktutil_funcs.c:196 +#, c-format +msgid "Password for %.1000s" +msgstr "პაროლი %.1000s" + +#: ../../src/kadmin/ktutil/ktutil_funcs.c:214 +#, c-format +msgid "Key for %s (hex): " +msgstr "გასაღები %s -სთვის (თექვსმეტობითი): " + +#: ../../src/kadmin/ktutil/ktutil_funcs.c:226 +#, c-format +msgid "addent: Error reading key.\n" +msgstr "addent: გასაღების წაკითხვის შეცდომა.\n" + +#: ../../src/kadmin/ktutil/ktutil_funcs.c:234 +#, c-format +msgid "addent: Illegal character in key.\n" +msgstr "addent: გასაღები დაუშვებელ სიმბოლოს შეიცავს.\n" + +#: ../../src/kadmin/server/auth_acl.c:240 +#, c-format +msgid "%s: invalid restrictions: %s" +msgstr "%s: არასწორი შეზღუდვა: %s" + +#: ../../src/kadmin/server/auth_acl.c:288 +#, c-format +msgid "Unrecognized ACL operation '%c' in %s" +msgstr "ACL -ის უცნობი ოპერაცია'%c' -ი %s-ში" + +#: ../../src/kadmin/server/auth_acl.c:296 +#, c-format +msgid "Cannot parse client principal '%s'" +msgstr "კლიენტის პრინციპალის (%s) დამუშავების შეცდომა" + +#: ../../src/kadmin/server/auth_acl.c:304 +#, c-format +msgid "Cannot parse target principal '%s'" +msgstr "სამიზნის პრინციპალის (%s) დამუშავების შეცდომა" + +#: ../../src/kadmin/server/auth_acl.c:400 +#, c-format +msgid "%s while opening ACL file %s" +msgstr "%s ACL ფაილის (%s) გახსნისას" + +#: ../../src/kadmin/server/auth_acl.c:403 +#, c-format +msgid "Cannot open %s: %s" +msgstr "%s-ის გახსნის შეცდომა: %s" + +#: ../../src/kadmin/server/auth_acl.c:419 +#: ../../src/kadmin/server/auth_acl.c:422 +#, c-format +msgid "%s: syntax error at line %d <%.10s...>" +msgstr "%s: სინტაქსის შეცდომა ხაზზე %d <%.10s...>" + +#: ../../src/kadmin/server/ipropd_svc.c:49 +#, c-format +msgid "Unauthorized request: %s, client=%s, service=%s, addr=%s" +msgstr "არაავტორიზებული მოთხოვნა: %s, კლიენტი=%s, სერვისი=%s, მისამართი=%s" + +#: ../../src/kadmin/server/ipropd_svc.c:50 +#: ../../src/kadmin/server/ipropd_svc.c:224 +#, c-format +msgid "Request: %s, %s, %s, client=%s, service=%s, addr=%s" +msgstr "მოთხოვნა: %s, %s, %s, კლიენტი=%s, სერვისი=%s, მისამართი=%s" + +#: ../../src/kadmin/server/ipropd_svc.c:164 +#: ../../src/kadmin/server/ipropd_svc.c:281 +#, c-format +msgid "%s: server handle is NULL" +msgstr "%s: სერვერის დამმუშავებელი ნულოვანია" + +#: ../../src/kadmin/server/ipropd_svc.c:174 +#: ../../src/kadmin/server/ipropd_svc.c:294 +#, c-format +msgid "%s: setup_gss_names failed" +msgstr "%s: setup_gss_names -ის შეცდომა" + +#: ../../src/kadmin/server/ipropd_svc.c:182 +#: ../../src/kadmin/server/ipropd_svc.c:303 +#, c-format +msgid "%s: out of memory recording principal names" +msgstr "%s: არასაკმარისი მეხსიერება პრინციპალის სახელების ჩაწერისას" + +#: ../../src/kadmin/server/ipropd_svc.c:207 +#, c-format +msgid "%s; Incoming SerialNo=%lu; Outgoing SerialNo=%lu" +msgstr "%s; შემომავალი SerialNo=%lu; გამავალი SerialNo=%lu" + +#: ../../src/kadmin/server/ipropd_svc.c:213 +#, c-format +msgid "%s; Incoming SerialNo=%lu; Outgoing SerialNo=N/A" +msgstr "%s; შემომავალი SerialNo=%lu; გამავალი SerialNo=N/A" + +#: ../../src/kadmin/server/ipropd_svc.c:324 +#, c-format +msgid "%s: getclhoststr failed" +msgstr "%s: getclhoststr -ის შეცდომა" + +#: ../../src/kadmin/server/ipropd_svc.c:346 +#, c-format +msgid "%s: cannot construct kdb5 util dump string too long; out of memory" +msgstr "" +"%s kdb5 პროგრამის დამპის სტრიქონის აგების შეცდომა: ის ძალიან დიდია: " +"არასაკმარისი მეხსიერება" + +#: ../../src/kadmin/server/ipropd_svc.c:366 +#, c-format +msgid "%s: fork failed: %s" +msgstr "%s: განტოტვის შეცდომა: %s" + +#: ../../src/kadmin/server/ipropd_svc.c:378 +#, c-format +msgid "%s: popen failed: %s" +msgstr "%s: popen -ის შეცდომა: %s" + +#: ../../src/kadmin/server/ipropd_svc.c:392 +#, c-format +msgid "%s: pclose(popen) failed: %s" +msgstr "%s: pclose(popen) -ის შეცდომა: %s" + +#: ../../src/kadmin/server/ipropd_svc.c:412 +#, c-format +msgid "%s: exec failed: %s" +msgstr "%s: შესრულების შეცდომა: %s" + +#: ../../src/kadmin/server/ipropd_svc.c:428 +#, c-format +msgid "Request: %s, spawned resync process %d, client=%s, service=%s, addr=%s" +msgstr "" +"მოთხოვნა: %s, გაჩენილი რესინქრონიზაციის პროცესი %d, კლიენტი=%s, სერვისი=%s, " +"მისამართი=%s" + +#: ../../src/kadmin/server/ipropd_svc.c:490 +#: ../../src/kadmin/server/kadm_rpc_svc.c:299 +#, c-format +msgid "check_rpcsec_auth: failed inquire_context, stat=%u" +msgstr "check_rpcsec_auth: inquire_context-ის შეცდომა, სტატ=%u" + +#: ../../src/kadmin/server/ipropd_svc.c:520 +#: ../../src/kadmin/server/kadm_rpc_svc.c:328 +#, c-format +msgid "bad service principal %.*s%s" +msgstr "არასწორი სერვისის პრინციპალი %.*s%s" + +#: ../../src/kadmin/server/ipropd_svc.c:543 +#, c-format +msgid "authentication attempt failed: %s, RPC authentication flavor %d" +msgstr "ავთენტიკაციის მცდელობა წარუმატებელია: %s RPC ავთენტიკაციის ტიპი %d" + +#: ../../src/kadmin/server/ipropd_svc.c:577 +#, c-format +msgid "RPC unknown request: %d (%s)" +msgstr "RPC უცნობი მოთხოვნა: %d (%s)" + +#: ../../src/kadmin/server/ipropd_svc.c:585 +#, c-format +msgid "RPC svc_getargs failed (%s)" +msgstr "RPC svc_getargs -ის შეცდომა (%s)" + +#: ../../src/kadmin/server/ipropd_svc.c:595 +#, c-format +msgid "RPC svc_sendreply failed (%s)" +msgstr "RPC svc_sendreply -ის შეცდომა (%s)" + +#: ../../src/kadmin/server/ipropd_svc.c:601 +#, c-format +msgid "RPC svc_freeargs failed (%s)" +msgstr "RPC svc_freeargs -ის შეცდომა (%s)" + +#: ../../src/kadmin/server/kadm_rpc_svc.c:349 +#, c-format +msgid "gss_to_krb5_name: failed display_name status %d" +msgstr "gss_to_krb5_name: display_name -ის არასწორი სტატუსი%d" + +#: ../../src/kadmin/server/ovsec_kadmd.c:82 +#, c-format +msgid "" +"Usage: kadmind [-x db_args]* [-r realm] [-m] [-nofork] [-port port-number]\n" +"\t\t[-proponly] [-p path-to-kdb5_util] [-F dump-file]\n" +"\t\t[-K path-to-kprop] [-k kprop-port] [-P pid_file]\n" +"\n" +"where,\n" +"\t[-x db_args]* - any number of database specific arguments.\n" +"\t\t\tLook at each database documentation for supported arguments\n" +msgstr "" +"გამოყენება: kadmind [-x ბაზის_არგუმენტები]* [-r რეალმი] [-m] [-nofork] [-" +"port პორტის-ნომერი]\n" +"\t\t[-proponly] [-p ბილიკი kdb5_util-მდე] [-F დამპის_ფაილი]\n" +"\t\t[-K ბილიკი-kprop-მდე] [-k kprop-ის-პორტი] [-P pid_ფაილი]\n" +"\n" +"სადაც,\n" +"\t[-x ბაზის_არგუმენტები]* - ბაზის არგუმენტების ნებისმიერი რაოდენობა.\n" +"\t\t\tთითოეული ბაზის მიერ მხარდაჭერილი არგუმენტების სანახავად იხილეთ მათი " +"დოკუმენტაცია \n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:106 +#, c-format +msgid "%s: %s while %s, aborting\n" +msgstr "%s: %s-ი %s-სას, ავარიული დასასრული\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:108 +#, c-format +msgid "%s while %s, aborting\n" +msgstr "%s-ი %s-სას, ავარიული დასასრული\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:110 +#, c-format +msgid "%s: %s, aborting\n" +msgstr "%s: %s, ავარიული დასასრული\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:111 +#, c-format +msgid "%s, aborting" +msgstr "%s, ავარიული დასასრული" + +#: ../../src/kadmin/server/ovsec_kadmd.c:278 +#, c-format +msgid "" +"WARNING! Forged/garbled request: %s, claimed client = %.*s%s, server = %.*s" +"%s, addr = %s" +msgstr "" +"გაფრთხილება! ყალბი/შექმნილი მოთხოვნა: %s, ნამტკიცები კლიენტი = %.*s%s, " +"სერვერი = %.*s%s, მისამართი = %s" + +#: ../../src/kadmin/server/ovsec_kadmd.c:284 +#, c-format +msgid "" +"WARNING! Forged/garbled request: %d, claimed client = %.*s%s, server = %.*s" +"%s, addr = %s" +msgstr "" +"გაფრთხილება! ყალბი/შექმნილი მოთხოვნა: %d, ნამტკიცები კლიენტი = %.*s%s, " +"სერვერი = %.*s%s, მისამართი = %s" + +#: ../../src/kadmin/server/ovsec_kadmd.c:298 +#, c-format +msgid "Miscellaneous RPC error: %s, %s" +msgstr "სხვადასხვა RPC შეცდომა: %s, %s" + +#: ../../src/kadmin/server/ovsec_kadmd.c:314 +#, c-format +msgid "%s Cannot decode status %d" +msgstr "%s სტატუსის გაშიფვრა შეუძლებელია %d" + +#: ../../src/kadmin/server/ovsec_kadmd.c:332 +#, c-format +msgid "Authentication attempt failed: %s, GSS-API error strings are:" +msgstr "" +"ავთენტიკაციის მცდელობა წარუმატებელია: %s, GSS-API-ის შეცდომის სტრიქონებია:" + +#: ../../src/kadmin/server/ovsec_kadmd.c:337 +msgid " GSS-API error strings complete." +msgstr " GSS-API -ის შეცდომის სრული სტრიქონები." + +#: ../../src/kadmin/server/ovsec_kadmd.c:375 +#, c-format +msgid "%s: cannot initialize. Not enough memory\n" +msgstr "%s: ინიციალიზაციის შეცდომა. არასაკმარისი მეხსიერება\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:443 +#, c-format +msgid "%s: %s while initializing context, aborting\n" +msgstr "%s: %s კონტექსტის ინიციალიზაციისას. სამუშაოს დასრულება\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:454 +#: ../../src/kadmin/server/ovsec_kadmd.c:523 +msgid "initializing" +msgstr "ინიციალიზაცია" + +#: ../../src/kadmin/server/ovsec_kadmd.c:458 +msgid "getting config parameters" +msgstr "კონფიგურაციის პარამეტრების მიღება" + +#: ../../src/kadmin/server/ovsec_kadmd.c:460 +msgid "Missing required realm configuration" +msgstr "აკლია რეალმის კონფიგურაციის საჭირო პარამეტრები" + +#: ../../src/kadmin/server/ovsec_kadmd.c:462 +msgid "Missing required ACL file configuration" +msgstr "აკლია ACL ფაილის აუცილებელი კონფიგურაცია" + +#: ../../src/kadmin/server/ovsec_kadmd.c:464 +msgid "-proponly can only be used when iprop_enable is true" +msgstr "" +"-proponly -ის გამოყენება მხოლოდ მაშინ შეგიძლიათ, როცა iprop_enable ჭეშმარიტია" + +#: ../../src/kadmin/server/ovsec_kadmd.c:470 +msgid "initializing network" +msgstr "ქსელის ინიციალიზაცია" + +#: ../../src/kadmin/server/ovsec_kadmd.c:475 +msgid "Cannot build GSSAPI auth names" +msgstr "GSSAPI-ის ავთენტიკაციის სახელების აგება შეუძლებელია" + +#: ../../src/kadmin/server/ovsec_kadmd.c:479 +msgid "Cannot set up KDB keytab" +msgstr "KDB Keytab-ის მორგების შეცდომა" + +#: ../../src/kadmin/server/ovsec_kadmd.c:482 +msgid "Cannot set GSSAPI authentication names" +msgstr "GSSAPI-ის ავთენტიკაციის სახელების დაყენება შეუძლებელია" + +#: ../../src/kadmin/server/ovsec_kadmd.c:499 +msgid "Cannot initialize GSSAPI service name" +msgstr "GSSAPI-ის სერვისის სახელის ინიციალიზაციის შეცდომა" + +#: ../../src/kadmin/server/ovsec_kadmd.c:504 +msgid "initializing ACL file" +msgstr "acl ფაილის ინიციალიზაცია" + +#: ../../src/kadmin/server/ovsec_kadmd.c:512 +msgid "spawning daemon process" +msgstr "დემონის პროცესის გაშვება" + +#: ../../src/kadmin/server/ovsec_kadmd.c:516 +msgid "creating PID file" +msgstr "pid ფაილის შექმნა" + +#: ../../src/kadmin/server/ovsec_kadmd.c:530 +msgid "mapping update log" +msgstr "განახლების ჟურნალის მიბმა" + +#: ../../src/kadmin/server/ovsec_kadmd.c:534 +#, c-format +msgid "%s: create IPROP svc (PROG=%d, VERS=%d)\n" +msgstr "%s: IPROP სერვისის შექმნა (პროგ=%d, ვერს=%d)\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:542 +msgid "starting" +msgstr "გაშვება" + +#: ../../src/kadmin/server/ovsec_kadmd.c:544 ../../src/kdc/main.c:1040 +#, c-format +msgid "%s: starting...\n" +msgstr "%s: გაშვება...\n" + +#: ../../src/kadmin/server/ovsec_kadmd.c:547 +msgid "finished, exiting" +msgstr "დასასრული. გავდივარ" + +#: ../../src/kadmin/server/schpw.c:273 +#, c-format +msgid "setpw request from %s by %.*s%s for %.*s%s: %s" +msgstr "setpw მოთხოვნა %s-ი %.*s%s-სგან %.*s%s: %s-სთვის" + +#: ../../src/kadmin/server/schpw.c:278 +#, c-format +msgid "chpw request from %s for %.*s%s: %s" +msgstr "chpw მოთხოვნა %s-ი %.*s%s: %s-სთვის" + +#: ../../src/kadmin/server/schpw.c:446 +#, c-format +msgid "chpw: Couldn't open admin keytab %s" +msgstr "chpw: ადმინის keytab-ის გახსნის შეცდომა %s" + +#: ../../src/kadmin/server/server_stubs.c:396 +#, c-format +msgid "" +"Unauthorized request: %s, %.*s%s, client=%.*s%s, service=%.*s%s, addr=%s" +msgstr "" +"არაავტორიზებული მოთხოვნა: %s, %.*s%s, კლიენტი=%.*s%s, სერვისი=%.*s%s, " +"მისამართი=%s" + +#: ../../src/kadmin/server/server_stubs.c:417 +#: ../../src/kadmin/server/server_stubs.c:695 +#: ../../src/kadmin/server/server_stubs.c:1570 +msgid "success" +msgstr "წარმატება" + +#: ../../src/kadmin/server/server_stubs.c:427 +#, c-format +msgid "Request: %s, %.*s%s, %s, client=%.*s%s, service=%.*s%s, addr=%s" +msgstr "მოთხოვნა: %s, %.*s%s, %s, კლიენტი=%.*s%s, სერვისი=%.*s%s, მისამართი=%s" + +#: ../../src/kadmin/server/server_stubs.c:675 +#, c-format +msgid "" +"Unauthorized request: kadm5_rename_principal, %.*s%s to %.*s%s, client=%.*s" +"%s, service=%.*s%s, addr=%s" +msgstr "" +"არაავტორიზებული მოთხოვნა: kadm5_rename_principal, %.*s%s to %.*s%s, კლიენტი=" +"%.*s%s, სერვისი=%.*s%s, მისამართი=%s" + +#: ../../src/kadmin/server/server_stubs.c:690 +#, c-format +msgid "" +"Request: kadm5_rename_principal, %.*s%s to %.*s%s, %s, client=%.*s%s, " +"service=%.*s%s, addr=%s" +msgstr "" +"მოთხოვნა: kadm5_rename_principal, %.*s%s to %.*s%s, %s, კლიენტი=%.*s%s, " +"სერვისი=%.*s%s, მისამართი=%s" + +#: ../../src/kadmin/server/server_stubs.c:1566 +#, c-format +msgid "" +"Request: kadm5_init, %.*s%s, %s, client=%.*s%s, service=%.*s%s, addr=%s, " +"vers=%d, flavor=%d" +msgstr "" +"მოთხოვნა: kadm5_init, %.*s%s, %s, კლიენტი=%.*s%s, სერვისი=%.*s%s, მისამართი=" +"%s, vers=%d, ტიპი=%d" + +#: ../../src/kdc/do_as_req.c:277 +#, c-format +msgid "AS_REQ : handle_authdata (%d)" +msgstr "AS_REQ : handle_authdata (%d)" + +#: ../../src/kdc/do_tgs_req.c:581 +msgid "not checking transit path" +msgstr "ტრანზიტის ბილიკი არ შემოწმდება" + +#: ../../src/kdc/do_tgs_req.c:598 +#, c-format +msgid "TGS_REQ : handle_authdata (%d)" +msgstr "TGS_REQ : handle_authdata (%d)" + +#: ../../src/kdc/fast_util.c:56 +#, c-format +msgid "%s while handling ap-request armor" +msgstr "%s ap-request -ის ჯავშნის დამუშავებისას" + +#: ../../src/kdc/fast_util.c:65 +msgid "ap-request armor for something other than the local TGS" +msgstr "ap-request -ის ჯავშანი რამისთვის, TGS-ის გარდა" + +#: ../../src/kdc/fast_util.c:74 +msgid "ap-request armor without subkey" +msgstr "ap-request -ის ჯავშანი subkey-ის გარეშე" + +#: ../../src/kdc/fast_util.c:162 +msgid "Ap-request armor not permitted with TGS" +msgstr "Ap-request -ის ჯავშანი ნებადაურთველია TGS-თან ერთად" + +#: ../../src/kdc/fast_util.c:169 +#, c-format +msgid "Unknown FAST armor type %d" +msgstr "უცნობი FAST ჯავშნის ტიპი %d" + +#: ../../src/kdc/fast_util.c:183 +msgid "No armor key but FAST armored request present" +msgstr "ჯავშნის გასაღები არ არსებობს, მაგრამ FAST დაჯავშნული მოთხოვნა - კი" + +#: ../../src/kdc/fast_util.c:218 +msgid "FAST req_checksum invalid; request modified" +msgstr "FAST req_checksum არასწორია. მოთხოვნა შეიცვალა" + +#: ../../src/kdc/fast_util.c:224 +msgid "Unkeyed checksum used in fast_req" +msgstr "Fast_req-ში გამოყენებული საკონტროლო ჯამი გასაღების გარეშეა" + +#: ../../src/kdc/kdc_audit.c:110 +#, c-format +msgid "audit plugin %s failed to open. error=%i" +msgstr "აუდიტის დამატების %s გახსნა შეუძლებელია. შეცდომა=%i" + +#: ../../src/kdc/kdc_authdata.c:78 +#, c-format +msgid "while loading authdata module %s" +msgstr "authdata მოდულის (%s) ჩატვირთვისას" + +#: ../../src/kdc/kdc_log.c:83 +#, c-format +msgid "AS_REQ (%s) %s: ISSUE: authtime %u, %s, %s for %s" +msgstr "AS_REQ (%s) %s: პრობლემა: authtime %u, %s, %s-ი %s-სთვის" + +#: ../../src/kdc/kdc_log.c:91 +#, c-format +msgid "AS_REQ (%s) %s: %s: %s for %s%s%s" +msgstr "AS_REQ (%s) %s: %s: %s-ი %s%s%s-თვის" + +#: ../../src/kdc/kdc_log.c:153 +#, c-format +msgid "TGS_REQ (%s) %s: %s: authtime %u, %s%s %s for %s%s%s" +msgstr "TGS_REQ (%s) %s: %s: authtime %u, %s%s %s -ი %s%s%s-თვის" + +#: ../../src/kdc/kdc_log.c:162 +#, c-format +msgid "... PROTOCOL-TRANSITION s4u-client=%s" +msgstr "... PROTOCOL-TRANSITION s4u-client=%s" + +#: ../../src/kdc/kdc_log.c:166 +#, c-format +msgid "... CONSTRAINED-DELEGATION s4u-client=%s" +msgstr "... CONSTRAINED-DELEGATION s4u-client=%s" + +#: ../../src/kdc/kdc_log.c:170 +#, c-format +msgid "TGS_REQ %s: %s: authtime %u, %s for %s, 2nd tkt client %s" +msgstr "TGS_REQ %s: %s: authtime %u, %s for %s, მეორე ბილეთის კლიენტი %s" + +#: ../../src/kdc/kdc_log.c:203 +#, c-format +msgid "bad realm transit path from '%s' to '%s' via '%.*s%s'" +msgstr "არასწორი რეალმის გადაცემის ბილიკი '%s'-დან '%s'-მდე '%.*s%s'-ის გავლით" + +#: ../../src/kdc/kdc_log.c:209 +#, c-format +msgid "unexpected error checking transit from '%s' to '%s' via '%.*s%s': %s" +msgstr "" +"შეცდომა გადაცემის შემოწმებისას: '%s' -ი '%s' -მდე '%.*s%s': %s-ის გავლით" + +#: ../../src/kdc/kdc_log.c:227 +msgid "TGS_REQ: issuing alternate TGT" +msgstr "TGS_REQ: გამოიცემა ალტერნატიული <დაუმუშავებლადი> TGT" + +#: ../../src/kdc/kdc_log.c:230 +#, c-format +msgid "TGS_REQ: issuing TGT %s" +msgstr "TGS_REQ: გამოცემა: TGT %s" + +#: ../../src/kdc/kdc_preauth.c:215 +#, c-format +msgid "preauth %s failed to initialize: %s" +msgstr "პრეავტორიზაციის (%s) ინიციალიზაციის შეცდომა: %s" + +#: ../../src/kdc/kdc_preauth.c:226 +#, c-format +msgid "preauth %s failed to setup loop: %s" +msgstr "პრეავტორიზაციის (%s) შეცდომა მარყუჟის აწყობისას: %s" + +#: ../../src/kdc/kdc_preauth.c:903 +#, c-format +msgid "%spreauth required but hint list is empty" +msgstr "%sპრეავტორიზაცია აუცილებელია, მაგრამ მითითებების სია ცარიელია" + +#: ../../src/kdc/kdc_preauth_ec.c:74 +msgid "Encrypted Challenge used outside of FAST tunnel" +msgstr "დაშიფრული გამოწვევა FAST გვირაბის გარეთ გამოიყენება" + +#: ../../src/kdc/kdc_preauth_ec.c:117 +msgid "Incorrect password in encrypted challenge" +msgstr "დაშიფრული გამოწვევის არასწორი პაროლი" + +#: ../../src/kdc/kdc_util.c:182 +msgid "TGS_REQ: SESSION KEY or MUTUAL" +msgstr "TGS_REQ: SESSION KEY ან MUTUAL" + +#: ../../src/kdc/kdc_util.c:380 +#, c-format +msgid "TGS_REQ: UNKNOWN SERVER: server='%s'" +msgstr "TGS_REQ: უცნობი სერვერი: სერვერი='%s'" + +#: ../../src/kdc/kdc_util.c:842 +#, c-format +msgid "Required auth indicators not present in ticket: %s" +msgstr "ავთენტიკაციის აუცილებელი ინდიკატორები არ არსებობს ბილეთში: %s" + +#: ../../src/kdc/main.c:225 +#, c-format +msgid "Requested master password enctype %s in %s is DEPRECATED!\n" +msgstr "მოთხოვნილი მთავარი პაროლის დაშიფვრის ტიპი %s-ი %s-ში მოძველებულია!\n" + +#: ../../src/kdc/main.c:241 +#, c-format +msgid "while getting context for realm %s" +msgstr "რეალმისთვისთვის (%s) შემცველობის მიღებისას" + +#: ../../src/kdc/main.c:348 +#, c-format +msgid "while setting default realm to %s" +msgstr "ნაგულისხმები რეალმის %s-ზე დაყენებისას" + +#: ../../src/kdc/main.c:356 +#, c-format +msgid "while initializing database for realm %s" +msgstr "რეალმისთვის (%s) ბაზის ინიციალიზაციისას" + +#: ../../src/kdc/main.c:365 +#, c-format +msgid "while setting up master key name %s for realm %s" +msgstr "მთავარი გასაღების სახელის (%s) რეალმისთვის (%s) მორგებისას" + +#: ../../src/kdc/main.c:378 +#, c-format +msgid "while fetching master key %s for realm %s" +msgstr "მთავარი გასაღების (%s) რეალმისთვის (%s) გამოთხოვისას" + +#: ../../src/kdc/main.c:387 +#, c-format +msgid "Stash file %s uses DEPRECATED enctype %s!\n" +msgstr "Stash ფაილი %s მოძველებულ enctype %s-ს იყენებს!\n" + +#: ../../src/kdc/main.c:394 +#, c-format +msgid "while fetching master keys list for realm %s" +msgstr "რეალმისთვის (%s) მთავარი გასაღებების სიის მიღებისას" + +#: ../../src/kdc/main.c:403 +#, c-format +msgid "while resolving kdb keytab for realm %s" +msgstr "რეალმისთვის (%s) kdb keytab-ის ამოხსნისას" + +#: ../../src/kdc/main.c:412 +#, c-format +msgid "while building TGS name for realm %s" +msgstr "რეალმისტვის (%s) TGS -ის სახელის აგებისას" + +#: ../../src/kdc/main.c:502 +#, c-format +msgid "creating %d worker processes" +msgstr "%d დამხმარე პროცესის შექმნა" + +#: ../../src/kdc/main.c:512 +msgid "Unable to reinitialize main loop" +msgstr "მთავარი მარყუჟის თავიდან ინიციალიზაცია შეუძლებელია" + +#: ../../src/kdc/main.c:517 +#, c-format +msgid "Unable to initialize signal handlers in pid %d" +msgstr "PID-ში %d სიგნალების დამმუშავებლის ინიციალიზაციის შეცდომა" + +#: ../../src/kdc/main.c:547 +#, c-format +msgid "worker %ld exited with status %d" +msgstr "დამხმარე პროცესმა %ld მუშაობა სტატუსით %d დაასრულა" + +#: ../../src/kdc/main.c:571 +#, c-format +msgid "signal %d received in supervisor" +msgstr "სიგნალი %d მიღებულია სუპერვაიზორში" + +#: ../../src/kdc/main.c:583 +#, c-format +msgid "" +"usage: %s [-x db_args]* [-d dbpathname] [-r dbrealmname]\n" +"\t\t[-T time_offset] [-m] [-k masterenctype]\n" +"\t\t[-M masterkeyname] [-p port] [-P pid_file]\n" +"\t\t[-n] [-w numworkers] [/]\n" +"\n" +"where,\n" +"\t[-x db_args]* - Any number of database specific arguments.\n" +"\t\t\tLook at each database module documentation for \t\t\tsupported " +"arguments\n" +msgstr "" +"გამოყენება: %s [-x ბაზის_არგუმენტები]* [-d ბაზისბილიკისსახელი] [-r " +"ბაზისნამდვილისახელი]\n" +"\t\t[-T დროის_წანაცვლება] [-m] [-k მთავარიდაშიფვრისტიპი]\n" +"\t\t[-M მთავარიგასაღებისსახელი] [-p პორტი] [-P pid_ფაილი]\n" +"\t\t[-n] [-w დამხმ_პროცეს_რაოდენობა] [/]\n" +"\n" +"სადაც,\n" +"\t[-x ბაზის_არგუმენტები]* - ბაზის არგუმენტების ნებისმიერი რაოდენობა\n" +"\t\t\tმხარდაჭერილი არგუმენტების სიისთვის \t\t\tბაზის დოკუმენტაციას მიმართეთ\n" + +#: ../../src/kdc/main.c:658 ../../src/kdc/main.c:665 ../../src/kdc/main.c:780 +#, c-format +msgid " KDC cannot initialize. Not enough memory\n" +msgstr " KDC-ის ინიციალიზაციის შეცდომა. არასაკმარისი მეხსიერება\n" + +#: ../../src/kdc/main.c:684 ../../src/kdc/main.c:727 ../../src/kdc/main.c:738 +#, c-format +msgid "%s: KDC cannot initialize. Not enough memory\n" +msgstr "%s: KDC-ის ინიციალიზაციის შეცდომა. არასაკმარისი მეხსიერება\n" + +#: ../../src/kdc/main.c:704 ../../src/kdc/main.c:817 +#, c-format +msgid "%s: cannot initialize realm %s - see log file for details\n" +msgstr "" +"%s: რეალმის %s ინიციალიზაცია შეუძლებელია- დეტალებისთვის იხილეთ ჟურნალის " +"ფაილი\n" + +#: ../../src/kdc/main.c:715 +#, c-format +msgid "%s: cannot initialize realm %s. Not enough memory\n" +msgstr "%s: რეალმის (%s) ინიციალიზაციის შეცდომა. არასაკმარისი მეხსიერება\n" + +#: ../../src/kdc/main.c:766 +#, c-format +msgid "invalid enctype %s" +msgstr "არასწორი enctype %s" + +#: ../../src/kdc/main.c:805 +msgid "while attempting to retrieve default realm" +msgstr "ნაგულისხმები რეალმის მიღების მცდელობისას" + +#: ../../src/kdc/main.c:807 +#, c-format +msgid "%s: %s, attempting to retrieve default realm\n" +msgstr "%s: %s, ნაგულისხმები რეალმის მიღების მცდელობა\n" + +#: ../../src/kdc/main.c:915 +#, c-format +msgid "%s: cannot get memory for realm list\n" +msgstr "%s: რეალმის სიისთვის მეხსიერების მიღების შეცდომა\n" + +#: ../../src/kdc/main.c:950 +msgid "while initializing lookaside cache" +msgstr "გვერდზე გახედვის ქეშის ინიციალიზაციისას" + +#: ../../src/kdc/main.c:958 +msgid "while creating main loop" +msgstr "მთავარი მარყუჟის შექმნისას" + +#: ../../src/kdc/main.c:967 +msgid "while loading KDC policy plugin" +msgstr "kdc-ის პოლიტიკის დამატების ჩატვირთვისას" + +#: ../../src/kdc/main.c:992 +msgid "while initializing signal handlers" +msgstr "სიგნალის დამმუშავებლების ინიციალიზაციისას" + +#: ../../src/kdc/main.c:1000 +msgid "while initializing network" +msgstr "ქსელის ინიციალიზაციისას" + +#: ../../src/kdc/main.c:1010 +msgid "while detaching from tty" +msgstr "tty-დან მოხსნისას" + +#: ../../src/kdc/main.c:1016 +msgid "while creating PID file" +msgstr "pid ფაილის შექმნისას" + +#: ../../src/kdc/main.c:1024 +msgid "creating worker processes" +msgstr "მიმდინარეობს დამხმარე პროცესების შექმნა" + +#: ../../src/kdc/main.c:1034 +msgid "while loading audit plugin module(s)" +msgstr "აუდიტის დამატების მოდულების ჩატვირთვისას" + +#: ../../src/kdc/main.c:1038 +msgid "commencing operation" +msgstr "ოპერაციის დასაწყისი" + +#: ../../src/kdc/main.c:1046 +msgid "shutting down" +msgstr "მიმდინარეობს გამორთვა" + +#: ../../src/kdc/policy.c:230 +#, c-format +msgid "while loading policy module %s" +msgstr "პოლიტიკის მოდულის (%s) ჩატვირთვისას" + +#: ../../src/kprop/kprop.c:85 +#, c-format +msgid "" +"\n" +"Usage: %s [-r realm] [-f file] [-d] [-P port] [-s keytab] replica_host\n" +"\n" +msgstr "" +"\n" +"გამოყენება: %s [-r რეალმი] [-f ფაილი] [-d] [-P პორტი] [-s keytab] " +"რეპლიკის_ჰოსტი\n" +"\n" + +#: ../../src/kprop/kprop.c:115 +#, c-format +msgid "Database propagation to %s: SUCCEEDED\n" +msgstr "ბაზის %s-მდე გავრცელება: წარმატებულია\n" + +#: ../../src/kprop/kprop.c:176 +msgid "while setting client principal name" +msgstr "კლიენტის პრინციპალის სახელის დაყენებისას" + +#: ../../src/kprop/kprop.c:185 +msgid "while setting server principal name" +msgstr "სერვერის პრინციპალის სახელის დაყენებისას" + +#: ../../src/kprop/kprop.c:198 +msgid "while resolving keytab" +msgstr "keytab-ის ამოხსნისას" + +#: ../../src/kprop/kprop.c:206 +msgid "while getting initial credentials\n" +msgstr "საწყისი ავტორიზაციის დეტალების მიღებისას\n" + +#: ../../src/kprop/kprop.c:242 +msgid "while creating socket" +msgstr "სოკეტის შეერთებისას" + +#: ../../src/kprop/kprop.c:262 +msgid "while connecting to server" +msgstr "სერვერთან მიერთებისას" + +#: ../../src/kprop/kprop.c:269 ../../src/kprop/kpropd.c:1195 +msgid "while getting local socket address" +msgstr "ლოკალური სოკეტის მისამართის მიღებისას" + +#: ../../src/kprop/kprop.c:274 +msgid "while converting local address" +msgstr "ლოკალური მისამართის გარდაქმნისას" + +#: ../../src/kprop/kprop.c:296 +msgid "in krb5_auth_con_setaddrs" +msgstr "krb5_auth_con_setaddrs-ში" + +#: ../../src/kprop/kprop.c:304 +msgid "while authenticating to server" +msgstr "სერვერთან ავთენტიკაციისას" + +#: ../../src/kprop/kprop.c:308 ../../src/kprop/kprop.c:506 +#: ../../src/kprop/kpropd.c:1515 +#, c-format +msgid "Generic remote error: %s\n" +msgstr "ზოგადი დაშორებული შეცდომა: %s\n" + +#: ../../src/kprop/kprop.c:314 ../../src/kprop/kprop.c:512 +msgid "signalled from server" +msgstr "სიგნალი სერვერიდან" + +#: ../../src/kprop/kprop.c:316 ../../src/kprop/kprop.c:514 +#, c-format +msgid "Error text from server: %s\n" +msgstr "შეცდომის ტექსტი სერვერიდან: %s\n" + +#: ../../src/kprop/kprop.c:344 +#, c-format +msgid "allocating database file name '%s'" +msgstr "ბაზის ფაილის სახელის ('%s') გამოყოფა" + +#: ../../src/kprop/kprop.c:350 +#, c-format +msgid "while trying to open %s" +msgstr "%s-ის გახსნის მცდელობისას" + +#: ../../src/kprop/kprop.c:357 +msgid "database locked" +msgstr "ბაზა დაბლოკილია" + +#: ../../src/kprop/kprop.c:360 ../../src/kprop/kpropd.c:552 +#, c-format +msgid "while trying to lock '%s'" +msgstr "'%s'-ის დაბლოკვისას" + +#: ../../src/kprop/kprop.c:364 ../../src/kprop/kprop.c:372 +#, c-format +msgid "while trying to stat %s" +msgstr "%s-ის აღმოჩენის მცდელობისას" + +#: ../../src/kprop/kprop.c:368 +msgid "while trying to malloc data_ok_fn" +msgstr "data_ok_fn-ის malloc-ის მცდელობიას" + +#: ../../src/kprop/kprop.c:377 +#, c-format +msgid "'%s' more recent than '%s'." +msgstr "'%s' უფრო ახალია, ვიდრე '%s'." + +#: ../../src/kprop/kprop.c:393 +#, c-format +msgid "while unlocking database '%s'" +msgstr "ბაზის ('%s') განბლოკვისას" + +#: ../../src/kprop/kprop.c:425 ../../src/kprop/kprop.c:426 +msgid "while encoding database size" +msgstr "ბაზის ზომის დაშიფვრისას" + +#: ../../src/kprop/kprop.c:434 +msgid "while sending database size" +msgstr "ბაზის ზომის გაგზავნისას" + +#: ../../src/kprop/kprop.c:444 +msgid "while allocating i_vector" +msgstr "i_vector-ის გამოყოფისას" + +#: ../../src/kprop/kprop.c:467 +#, c-format +msgid "while sending database block starting at %" +msgstr "ბაზის ბლოკის, რომელიც %-ზე იწყება, გაგზავნისას" + +#: ../../src/kprop/kprop.c:477 +msgid "Premature EOF found for database file!" +msgstr "ბაზის ფაილში აღმოჩენილია ნაადრევი EOF!" + +#: ../../src/kprop/kprop.c:490 +msgid "while reading response from server" +msgstr "შეცდომა სერვერის პასუხის წაკიხვისას" + +#: ../../src/kprop/kprop.c:501 +msgid "while decoding error response from server" +msgstr "სერვერის შეცდომის შეტყობინების დეკოდირებისას" + +#: ../../src/kprop/kprop.c:531 +msgid "malformed sent database size message" +msgstr "არასწორად გაგზავნილი ბაზის ზომის შეტყობინება" + +#: ../../src/kprop/kprop.c:535 +#, c-format +msgid "Kpropd sent database size %, expecting %" +msgstr "Kpropd გაგზავნილი ბაზის ზომა %, მოველოდი %" + +#: ../../src/kprop/kprop.c:581 +msgid "while allocating filename for update_last_prop_file" +msgstr "update_last_prop_file-სთვის ფაილის სახელის გამოყოფისას" + +#: ../../src/kprop/kprop.c:586 +#, c-format +msgid "while creating 'last_prop' file, '%s'" +msgstr "'last_prop' ფაილის შექმნისას, '%s'" + +#: ../../src/kprop/kpropd.c:171 +#, c-format +msgid "" +"\n" +"Usage: %s [-r realm] [-s keytab] [-d] [-D] [-S]\n" +"\t[-f replica_file] [-F kerberos_db_file ]\n" +"\t[-p kdb5_util_pathname] [-x db_args]* [-P port]\n" +"\t[-a acl_file] [-A admin_server] [--pid-file=pid_file]\n" +msgstr "" +"\n" +"გამოყენება: %s [-r რეალმი] [-s keytab] [-d] [-D] [-S]\n" +"\t[-f რეპლიკის_ფაილი] [-F kerberos_ის_ბაზის_ფაილი ]\n" +"\t[-p kdb5_პროგრამის_ბილიკი] [-x ბაზის_არგუმენტები]* [-P პორტი]\n" +"\t[-a acl_ფაილი] [-A ადმინ_სერვერი] [--pid-file=pid_ფაილი]\n" + +#: ../../src/kprop/kpropd.c:231 +#, c-format +msgid "Killing fullprop child (%d)\n" +msgstr "Fullprop შვილის მოკვლა (%d)\n" + +#: ../../src/kprop/kpropd.c:260 +msgid "while checking if stdin is a socket" +msgstr "შემოწმებისას, წარმოადგენს თუ არა stdin სოკეტს" + +#: ../../src/kprop/kpropd.c:278 +#, c-format +msgid "ready\n" +msgstr "მზადაა\n" + +#: ../../src/kprop/kpropd.c:284 +#, c-format +msgid "Could not write pid file %s: %s" +msgstr "PID ფაილში (%s) ჩაწერის შეცდომა: %s" + +#: ../../src/kprop/kpropd.c:296 +#, c-format +msgid "Could not open /dev/null: %s" +msgstr "/dev/null-ის გასნის შეცდომა: %s" + +#: ../../src/kprop/kpropd.c:303 +#, c-format +msgid "Could not dup the inetd socket: %s" +msgstr "შეცდომა inetd-ის სოკეტის გახნისას: %s" + +#: ../../src/kprop/kpropd.c:338 ../../src/kprop/kpropd.c:351 +msgid "do_iprop failed.\n" +msgstr "do_iprop -ის შეცდომა.\n" + +#: ../../src/kprop/kpropd.c:390 +#, c-format +msgid "getaddrinfo: %s\n" +msgstr "getaddrinfo: %s\n" + +#: ../../src/kprop/kpropd.c:396 +msgid "while obtaining socket" +msgstr "სოკეტის მიღებისას" + +#: ../../src/kprop/kpropd.c:402 +msgid "while setting SO_REUSEADDR option" +msgstr "პარამეტრის SO_REUSEADDR დაყენებისას" + +#: ../../src/kprop/kpropd.c:410 +msgid "while unsetting IPV6_V6ONLY option" +msgstr "პარამეტრის IPV6_V6ONLY დაყენებისას" + +#: ../../src/kprop/kpropd.c:415 +msgid "while binding listener socket" +msgstr "მომსმენ სოკეტთან მიბმისას" + +#: ../../src/kprop/kpropd.c:426 +#, c-format +msgid "waiting for a kprop connection\n" +msgstr "kprop მიერთების მოლოდინი\n" + +#: ../../src/kprop/kpropd.c:432 +msgid "while accepting connection" +msgstr "შერთების მიღებისას" + +#: ../../src/kprop/kpropd.c:438 +msgid "while forking" +msgstr "განტოტვისას" + +#: ../../src/kprop/kpropd.c:453 +#, c-format +msgid "waitpid() failed to wait for doit() (%d %s)\n" +msgstr "waitpid() ვერ დაელოდა doit()-ს (%d %s)\n" + +#: ../../src/kprop/kpropd.c:457 +msgid "while waiting to receive database" +msgstr "ბაზის მიღების მოლოდინისას" + +#: ../../src/kprop/kpropd.c:461 +#, c-format +msgid "Database load process for full propagation completed.\n" +msgstr "ბაზის ჩატვირთვის პროცესი სრულად გავრცელებისთვის დასრულებულია.\n" + +#: ../../src/kprop/kpropd.c:499 +#, c-format +msgid "" +"%s: Standard input does not appear to be a network socket.\n" +"\t(Not run from inetd, and missing the -S option?)\n" +msgstr "" +"%s: სტანდარტული შეყვანა ქსელის სოკეტს არ წააგავს.\n" +"\t(არაა გაშვებული inetd-დან და აკლია -S პარამეტრი?)\n" + +#: ../../src/kprop/kpropd.c:512 +msgid "while attempting setsockopt (SO_KEEPALIVE)" +msgstr "setsockopt (SO_KEEPALIVE)-ის მცდელობისას" + +#: ../../src/kprop/kpropd.c:517 +#, c-format +msgid "Connection from %s" +msgstr "შეერთება %s -დან" + +#: ../../src/kprop/kpropd.c:537 +#, c-format +msgid "Rejected connection from unauthorized principal %s\n" +msgstr "მიერთება უარყოფილია არაავტორიზებული პრინციპალისთვის %s\n" + +#: ../../src/kprop/kpropd.c:541 +#, c-format +msgid "Rejected connection from unauthorized principal %s" +msgstr "მიერთება უარყოფილია არაავტორიზებული პრინციპალისთვის %s" + +#: ../../src/kprop/kpropd.c:558 +#, c-format +msgid "while opening database file, '%s'" +msgstr "ბაზის ფაილის, '%s', გახსნისას" + +#: ../../src/kprop/kpropd.c:564 +#, c-format +msgid "while renaming %s to %s" +msgstr "სახელის \"%s\"-დან \"%s\"-მდე გადარქმევისას" + +#: ../../src/kprop/kpropd.c:570 +#, c-format +msgid "while downgrading lock on '%s'" +msgstr "'%s'-ზე ბლოკის დაქვეითებისას" + +#: ../../src/kprop/kpropd.c:577 +#, c-format +msgid "while unlocking '%s'" +msgstr "'%s'-ის განბლოკვისას" + +#: ../../src/kprop/kpropd.c:589 +msgid "while sending # of received bytes" +msgstr "მიღებული ბაიტების #-ის გაგზავნისას" + +#: ../../src/kprop/kpropd.c:595 +msgid "while trying to close database file" +msgstr "ბაზის ფაილის დახურვის მცდელობისას" + +#: ../../src/kprop/kpropd.c:650 +#, c-format +msgid "Incremental propagation enabled\n" +msgstr "ინკრემენტული გავრცელება ჩართულია\n" + +#: ../../src/kprop/kpropd.c:659 +#, c-format +msgid "%s: unable to get kiprop host based service name for realm %s\n" +msgstr "" +"%s: რეალმისთვის (%s) kipropz-ის ჰოსტზე ბაზირებული სერვისის სახელის მიღების " +"შეცდომა\n" + +#: ../../src/kprop/kpropd.c:669 +msgid "while trying to construct host service principal" +msgstr "ჰოსტის სერვისის პრინციპალის აშენების მცდელობისას" + +#: ../../src/kprop/kpropd.c:686 +#, c-format +msgid "Initializing kadm5 as client %s\n" +msgstr "Kadm5-ის, როგორც %s კლიენტის ინიციალიზაცია\n" + +#: ../../src/kprop/kpropd.c:700 +#, c-format +msgid "kadm5 initialization failed!\n" +msgstr "kadm5 -ის ინიციალიზაციის შეცდომა!\n" + +#: ../../src/kprop/kpropd.c:709 +msgid "while attempting to connect to primary KDC ... retrying" +msgstr "ძირითად KDC-სთან მიერთების მცდელობისას ... თავიდან ცდა" + +#: ../../src/kprop/kpropd.c:713 +#, c-format +msgid "Sleeping %d seconds to re-initialize kadm5 (RPC ERROR)\n" +msgstr "%d -წამიანი ძილი kadm5-ის რეინიციალიზაციისთვის (RPC-ის შეცდომა)\n" + +#: ../../src/kprop/kpropd.c:729 +#, c-format +msgid "while initializing %s interface, retrying" +msgstr "%s ინტერფეისის ინიციალიზაციისას. თავიდან ცდა" + +#: ../../src/kprop/kpropd.c:733 +#, c-format +msgid "Sleeping %d seconds to re-initialize kadm5 (krb5kdc not running?)\n" +msgstr "" +"%d -წამიანი ძილი kadm5-ის რეინიციალიზაციისთვის (გაშვებულია თუ არა krb4kdc?)\n" + +#: ../../src/kprop/kpropd.c:743 +#, c-format +msgid "kadm5 initialization succeeded\n" +msgstr "kadm5 -ის ინიციალიზაცია წარმატებულია\n" + +#: ../../src/kprop/kpropd.c:765 +msgid "reading update log header" +msgstr "განახლების ჟურნალის თავსართის წაკთხვა" + +#: ../../src/kprop/kpropd.c:776 +#, c-format +msgid "Calling iprop_get_updates_1 (sno=%u sec=%u usec=%u)\n" +msgstr "" +"მიმდინარეობს iprop_get_updates_1-ის გამოძახება (sno=%u sec=%u usec=%u)\n" + +#: ../../src/kprop/kpropd.c:786 +msgid "iprop_get_updates call failed" +msgstr "iprop_get_updates -ის გამოძახების შეცდომა" + +#: ../../src/kprop/kpropd.c:792 +#, c-format +msgid "Reinitializing iprop because get updates failed\n" +msgstr "" +"განახლებების მიღების შეცდომის გამო მიმდინარეობს iprop-ის რეინიციალიზაცია\n" + +#: ../../src/kprop/kpropd.c:813 +#, c-format +msgid "Still waiting for full resync\n" +msgstr "სრულ რესინქრონიზაციას ჯერ კიდევ ველოდები\n" + +#: ../../src/kprop/kpropd.c:818 +#, c-format +msgid "Full resync needed\n" +msgstr "საჭიროა სრული რესინქრონიზაცია\n" + +#: ../../src/kprop/kpropd.c:819 +msgid "kpropd: Full resync needed." +msgstr "kpropd: საჭიროა სრული რესინქრონიზაცია." + +#: ../../src/kprop/kpropd.c:824 +msgid "iprop_full_resync call failed" +msgstr "iprop_full_resync -ის გამოძახების შეცდომა" + +#: ../../src/kprop/kpropd.c:835 +#, c-format +msgid "Full resync request granted\n" +msgstr "სრული ხელახალი სინქრონიზაციის მოთხოვნა დაკმაყოფილებულია\n" + +#: ../../src/kprop/kpropd.c:836 +msgid "Full resync request granted." +msgstr "სრული ხელახალი სინქრონიზაციის მოთხოვნა დაკმაყოფილებულია." + +#: ../../src/kprop/kpropd.c:845 +#, c-format +msgid "Exponential backoff\n" +msgstr "ექსპონენტური დაბრუნება\n" + +#: ../../src/kprop/kpropd.c:851 +#, c-format +msgid "Full resync permission denied\n" +msgstr "სრული რესინქრონიზაციის წვდომა აკრძალულია\n" + +#: ../../src/kprop/kpropd.c:852 +msgid "Full resync, permission denied." +msgstr "სრული რესინქრონიზაცია, წვდომა აკრძალულია." + +#: ../../src/kprop/kpropd.c:857 +#, c-format +msgid "Full resync error from primary\n" +msgstr "" +"სრული რესინქრონიზაციის შეცდომა ძირითადიდან\n" +"\n" + +#: ../../src/kprop/kpropd.c:858 +msgid " Full resync, error returned from primary KDC." +msgstr " სრული რესინქრონიზაცია, ძირითადმა KDC-მა შეცდომა დააბრუნა." + +#: ../../src/kprop/kpropd.c:866 +#, c-format +msgid "Full resync invalid result from primary\n" +msgstr "სრული რექსინქრონიზაცია. არასწორი პასუხი ძირითადიდან\n" + +#: ../../src/kprop/kpropd.c:868 +msgid "Full resync, invalid return from primary KDC." +msgstr "სრული რესინქრონიზაცია. არასწორი პასუხი ძირითადი KDC-დან." + +#: ../../src/kprop/kpropd.c:884 +#, c-format +msgid "Got incremental updates (sno=%u sec=%u usec=%u)\n" +msgstr "მიღებულია ინკრემენტული განახლებები (sno=%u sec=%u usec=%u)\n" + +#: ../../src/kprop/kpropd.c:896 +#, c-format +msgid "ulog_replay failed (%s), updates not registered\n" +msgstr "ulog_replay -ის შეცდომა (%s), განახლებები არ დარეგისტრირებულა\n" + +#: ../../src/kprop/kpropd.c:899 +#, c-format +msgid "ulog_replay failed (%s), updates not registered." +msgstr "ulog_replay -ის შეცდომა (%s), განახლებები არ დარეგისტრირებულა." + +#: ../../src/kprop/kpropd.c:908 +#, c-format +msgid "Incremental updates: %d updates / %lu us" +msgstr "ინკრემენტული განახლებები: %d განახლება / %lu მწმ" + +#: ../../src/kprop/kpropd.c:911 +#, c-format +msgid "Incremental updates: %d updates / %lu us\n" +msgstr "ინკრემენტული განახლებები: %d განახლება / %lu მწმ\n" + +#: ../../src/kprop/kpropd.c:919 +#, c-format +msgid "get_updates permission denied\n" +msgstr "get_updates წვდომა აკრძალულია\n" + +#: ../../src/kprop/kpropd.c:920 +msgid "get_updates, permission denied." +msgstr "get_updates წვდომა აკრძალულია." + +#: ../../src/kprop/kpropd.c:925 +#, c-format +msgid "get_updates error from primary\n" +msgstr "get_updates შეცდომა ძირითადიდან\n" + +#: ../../src/kprop/kpropd.c:927 +msgid "get_updates, error returned from primary KDC." +msgstr "get_updates, ძირითადმა KDC-მა შეცდომა დააბრუნა." + +#: ../../src/kprop/kpropd.c:935 +#, c-format +msgid "get_updates primary busy; backoff\n" +msgstr "get_updates მთავარიდ აკავებულია; დაბრუნება\n" + +#: ../../src/kprop/kpropd.c:944 +#, c-format +msgid "KDC is synchronized with primary.\n" +msgstr "KDC სინქრონიზებულია ძირითადთან.\n" + +#: ../../src/kprop/kpropd.c:953 +#, c-format +msgid "get_updates invalid result from primary\n" +msgstr "get_updates არასწორი პასუხი ძირითადიდან\n" + +#: ../../src/kprop/kpropd.c:956 +msgid "get_updates, invalid return from primary KDC." +msgstr "get_updates, არასწორი პასუხი ძირითადი KDC -დან." + +#: ../../src/kprop/kpropd.c:971 +#, c-format +msgid "Busy signal received from primary, backoff for %d secs\n" +msgstr "მთავარიდან მიღებულია დაკავებულობის სიგნალი. დაბრუნება %d წამით\n" + +#: ../../src/kprop/kpropd.c:978 +#, c-format +msgid "Waiting for %d seconds before checking for updates again\n" +msgstr "%d წამის მოლოდინი განახლებების თავის შემოწმებამდე\n" + +#: ../../src/kprop/kpropd.c:989 +#, c-format +msgid "ERROR returned by primary, bailing\n" +msgstr "მთავარმა შეცდომა დააბრუნა, დანებება\n" + +#: ../../src/kprop/kpropd.c:990 +msgid "ERROR returned by primary KDC, bailing.\n" +msgstr "მთავარმა KDC-მა შეცდომა დააბრუნა. დანებება.\n" + +#: ../../src/kprop/kpropd.c:1108 +msgid "copying db args" +msgstr "ბაზის არგუმენტების კოპირება" + +#: ../../src/kprop/kpropd.c:1133 +msgid "Unable to get default realm" +msgstr "ნაგულისხმები რეალმის მიღების შეცდომა" + +#: ../../src/kprop/kpropd.c:1140 +msgid "Unable to set default realm" +msgstr "ნაგულისხმები რეალმის დაყენების შეცდომა" + +#: ../../src/kprop/kpropd.c:1150 +msgid "while trying to construct my service name" +msgstr "ჩემი სერვისის სახელის აწყობის მცდელობისას" + +#: ../../src/kprop/kpropd.c:1157 +msgid "while allocating filename for temp file" +msgstr "დროებითი ფაილის სახელის გამოყოფისას" + +#: ../../src/kprop/kpropd.c:1165 +msgid "while initializing" +msgstr "ინიციალიზაციისას" + +#: ../../src/kprop/kpropd.c:1173 +msgid "Unable to map log!\n" +msgstr "ჟურნალის მიბმის შეცდომა!\n" + +#: ../../src/kprop/kpropd.c:1215 +#, c-format +msgid "Error in krb5_auth_con_ini: %s" +msgstr "შეცდომა krb5_auth_con_ini-ში: %s" + +#: ../../src/kprop/kpropd.c:1223 +#, c-format +msgid "Error in krb5_auth_con_setflags: %s" +msgstr "შეცდომა krb5_auth_con_setflags-ში: %s" + +#: ../../src/kprop/kpropd.c:1236 +#, c-format +msgid "Error in krb5_auth_con_setaddrs: %s" +msgstr "შეცდომა krb5_auth_con_setaddrs-ში: %s" + +#: ../../src/kprop/kpropd.c:1244 +#, c-format +msgid "Error in krb5_kt_resolve: %s" +msgstr "შეცდომა krb5_kt_resolve-ში: %s" + +#: ../../src/kprop/kpropd.c:1253 +#, c-format +msgid "Error in krb5_recvauth: %s" +msgstr "შეცდომა krb5_recvauth -ში: %s" + +#: ../../src/kprop/kpropd.c:1260 +#, c-format +msgid "Error in krb5_copy_prinicpal: %s" +msgstr "შეცდომა krb5_copy_prinicpal-ში: %s" + +#: ../../src/kprop/kpropd.c:1277 +msgid "while unparsing ticket etype" +msgstr "ბილეთის etype-ის დამუშავების გაუქმებისას" + +#: ../../src/kprop/kpropd.c:1281 +#, c-format +msgid "authenticated client: %s (etype == %s)\n" +msgstr "კლიენტი ავტორიზებულია: %s (etype == %s)\n" + +#: ../../src/kprop/kpropd.c:1361 +msgid "while reading size of database from client" +msgstr "კლიენტიდან ბაზის ზომის კითხვისას" + +#: ../../src/kprop/kpropd.c:1371 +msgid "while decoding database size from client" +msgstr "კლიენტიდან ბაზის ზომის დეკოდირებისას" + +#: ../../src/kprop/kpropd.c:1379 +msgid "malformed database size message from client" +msgstr "კლიენტიდან მიღებული ბაზის ზომის შეტყობინება არასწორია" + +#: ../../src/kprop/kpropd.c:1391 +msgid "while initializing i_vector" +msgstr "i_vector-ის ინიციალიზაციისას" + +#: ../../src/kprop/kpropd.c:1396 +#, c-format +msgid "Full propagation transfer started.\n" +msgstr "სრული გავრცელების გადაცემა დაწყებულია.\n" + +#: ../../src/kprop/kpropd.c:1450 +#, c-format +msgid "Full propagation transfer finished.\n" +msgstr "სრული გავრცელების გადაცემა დასრულდა.\n" + +#: ../../src/kprop/kpropd.c:1510 +msgid "while decoding error packet from client" +msgstr "კლიენტიდან მიღებული შეცდომის პაკეტის დეკოდირებისას" + +#: ../../src/kprop/kpropd.c:1519 +msgid "signaled from server" +msgstr "სიგნალი სერვერიდან" + +#: ../../src/kprop/kpropd.c:1521 +#, c-format +msgid "Error text from client: %s\n" +msgstr "შეცდომის ტექსტი კლიენტიდან: %s\n" + +#: ../../src/kprop/kpropd.c:1570 +#, c-format +msgid "while trying to fork %s" +msgstr "%s-ის განტოტვისას" + +#: ../../src/kprop/kpropd.c:1574 +#, c-format +msgid "while trying to exec %s" +msgstr "%s-ის exec-ის მცდელობისას" + +#: ../../src/kprop/kpropd.c:1581 +#, c-format +msgid "while waiting for %s" +msgstr "%s-ის მოლოდინისას" + +#: ../../src/kprop/kpropd.c:1587 +#, c-format +msgid "%s load terminated" +msgstr "%s-ის ჩატვირთვა შეწყვეტილია" + +#: ../../src/kprop/kpropd.c:1593 +#, c-format +msgid "%s returned a bad exit status (%d)" +msgstr "%s -მა გასვლის არასწორი სტატუსი დააბრუნა (%d)" + +#: ../../src/kprop/kproplog.c:29 +#, c-format +msgid "" +"\n" +"Usage: %s [-h] [-v] [-v] [-e num]\n" +"\t%s -R\n" +"\n" +msgstr "" +"\n" +"გამოყენება: %s [-h] [-v] [-v] [-e რიცხვი]\n" +"\t%s -R\n" +"\n" + +#: ../../src/kprop/kproplog.c:112 +#, c-format +msgid "" +"\n" +"Couldn't allocate memory" +msgstr "" +"\n" +"მეხსიერების გამოყოფის შეცდომა" + +#: ../../src/kprop/kproplog.c:206 +#, c-format +msgid "\t\tAttribute flags\n" +msgstr "\t\tატრიბუტის ალმები\n" + +#: ../../src/kprop/kproplog.c:211 +#, c-format +msgid "\t\tMaximum ticket life\n" +msgstr "\t\tბილეთის მაქსიმალური სიცოცხლე\n" + +#: ../../src/kprop/kproplog.c:216 +#, c-format +msgid "\t\tMaximum renewable life\n" +msgstr "\t\tმაქსიმალური განახლებადი სიცოცხლე\n" + +#: ../../src/kprop/kproplog.c:221 +#, c-format +msgid "\t\tPrincipal expiration\n" +msgstr "\t\tპრინციპალის ვადა\n" + +#: ../../src/kprop/kproplog.c:226 +#, c-format +msgid "\t\tPassword expiration\n" +msgstr "\t\tპაროლის ვადა\n" + +#: ../../src/kprop/kproplog.c:231 +#, c-format +msgid "\t\tLast successful auth\n" +msgstr "\t\tბოლო წარმატებული ავთენტიკაცია\n" + +#: ../../src/kprop/kproplog.c:236 +#, c-format +msgid "\t\tLast failed auth\n" +msgstr "\t\tბოლო წარუმატებელი ავთენტიკაცია\n" + +#: ../../src/kprop/kproplog.c:241 +#, c-format +msgid "\t\tFailed passwd attempt\n" +msgstr "\t\tწარუმატებელი პაროლის მცდელობა\n" + +#: ../../src/kprop/kproplog.c:246 +#, c-format +msgid "\t\tPrincipal\n" +msgstr "\t\tპრინციპალი\n" + +#: ../../src/kprop/kproplog.c:251 +#, c-format +msgid "\t\tKey data\n" +msgstr "\t\tგასაღების შემცველობა\n" + +#: ../../src/kprop/kproplog.c:258 +#, c-format +msgid "\t\tTL data\n" +msgstr "\t\tTL -ის მონაცემები\n" + +#: ../../src/kprop/kproplog.c:265 +#, c-format +msgid "\t\tLength\n" +msgstr "\t\tსიგრძე\n" + +#: ../../src/kprop/kproplog.c:270 +#, c-format +msgid "\t\tPassword last changed\n" +msgstr "\t\tპაროლი ბოლოს შეიცვალა\n" + +#: ../../src/kprop/kproplog.c:275 +#, c-format +msgid "\t\tModifying principal\n" +msgstr "\t\tპრინციპალის შეცვლა\n" + +#: ../../src/kprop/kproplog.c:280 +#, c-format +msgid "\t\tModification time\n" +msgstr "\t\tცვლილების დრო\n" + +#: ../../src/kprop/kproplog.c:285 +#, c-format +msgid "\t\tModified where\n" +msgstr "\t\tცვლილების ადგილი\n" + +#: ../../src/kprop/kproplog.c:290 +#, c-format +msgid "\t\tPassword policy\n" +msgstr "\t\tპაროლის პოლიტიკა\n" + +#: ../../src/kprop/kproplog.c:295 +#, c-format +msgid "\t\tPassword policy switch\n" +msgstr "\t\tპაროლის პოლიტიკის გადართვა\n" + +#: ../../src/kprop/kproplog.c:300 +#, c-format +msgid "\t\tPassword history KVNO\n" +msgstr "\t\tპაროლის ისტორია KVNO\n" + +#: ../../src/kprop/kproplog.c:305 +#, c-format +msgid "\t\tPassword history\n" +msgstr "\t\tპაროლის ისტორია\n" + +#: ../../src/kprop/kproplog.c:339 +#, c-format +msgid "" +"Corrupt update entry\n" +"\n" +msgstr "" +"დაზიანებული ჩანაწერის განახლება\n" +"\n" + +#: ../../src/kprop/kproplog.c:344 +#, c-format +msgid "Update Entry\n" +msgstr "ჩანაწერის განახლება\n" + +#: ../../src/kprop/kproplog.c:346 +#, c-format +msgid "\tUpdate serial # : %u\n" +msgstr "\tსერიალის განახლება # : %u\n" + +#: ../../src/kprop/kproplog.c:350 +#, c-format +msgid "\tDummy entry\n" +msgstr "\tცარიელი ჩანაწერი\n" + +#: ../../src/kprop/kproplog.c:358 +#, c-format +msgid "" +"Entry data decode failure\n" +"\n" +msgstr "" +"ჩანაწერის მონაცემების დეკოდირების შეცდომა\n" +"\n" + +#: ../../src/kprop/kproplog.c:362 +#, c-format +msgid "\tUpdate operation : " +msgstr "\tოპერაციის განახლება : " + +#: ../../src/kprop/kproplog.c:364 +#, c-format +msgid "Delete\n" +msgstr "წაშლა\n" + +#: ../../src/kprop/kproplog.c:366 +#, c-format +msgid "Add\n" +msgstr "დამატება\n" + +#: ../../src/kprop/kproplog.c:370 +#, c-format +msgid "" +"Could not allocate principal name\n" +"\n" +msgstr "" +"პრინციპალის სახელის გამოყოფის შეცდომა\n" +"\n" + +#: ../../src/kprop/kproplog.c:376 +#, c-format +msgid "\tUpdate principal : %s\n" +msgstr "\tპრინციალის განახლება : %s\n" + +#: ../../src/kprop/kproplog.c:378 +#, c-format +msgid "\tUpdate size : %u\n" +msgstr "\tგანახლების ზომა : %u\n" + +#: ../../src/kprop/kproplog.c:379 +#, c-format +msgid "\tUpdate committed : %s\n" +msgstr "\tგანახლება გადაცემულია : %s\n" + +#: ../../src/kprop/kproplog.c:383 +#, c-format +msgid "\tUpdate time stamp : None\n" +msgstr "\tგანახლების დროის შტამპი : არცერთი\n" + +#: ../../src/kprop/kproplog.c:385 +#, c-format +msgid "\tUpdate time stamp : %s" +msgstr "\tგანახლების დროის შტამპი : %s" + +#: ../../src/kprop/kproplog.c:389 +#, c-format +msgid "\tAttributes changed : %d\n" +msgstr "\tატრიბუტები შეიცვალა : %d\n" + +#: ../../src/kprop/kproplog.c:462 +#, c-format +msgid "" +"Unable to initialize Kerberos\n" +"\n" +msgstr "" +"Kerberos-ის ინიციალიზაციის შეცდომა\n" +"\n" + +#: ../../src/kprop/kproplog.c:469 +#, c-format +msgid "" +"Couldn't read database_name\n" +"\n" +msgstr "" +"შეცდომა database_name-ის წაკითხვისას\n" +"\n" + +#: ../../src/kprop/kproplog.c:473 +#, c-format +msgid "" +"\n" +"Kerberos update log (%s)\n" +msgstr "" +"\n" +"Kerberos -ის განახლების ჟურნალი (%s)\n" + +#: ../../src/kprop/kproplog.c:477 ../../src/kprop/kproplog.c:493 +#, c-format +msgid "" +"Unable to map log file %s\n" +"\n" +msgstr "" +"ჟურნალის ფაილის %s მიბმის შეცდომა\n" +"\n" + +#: ../../src/kprop/kproplog.c:482 +#, c-format +msgid "" +"Couldn't reinitialize ulog file %s\n" +"\n" +msgstr "" +"შეცდომა ulog ფაილის %s რეინიციალიზაციისას\n" +"\n" + +#: ../../src/kprop/kproplog.c:486 +#, c-format +msgid "Reinitialized the ulog.\n" +msgstr "Ulog-ის რეინიციალიზაცია წარმატებულია.\n" + +#: ../../src/kprop/kproplog.c:499 +#, c-format +msgid "" +"Corrupt header log, exiting\n" +"\n" +msgstr "" +"ჟურნალის თავსართი დაზიანებულია. გასვლა\n" +"\n" + +#: ../../src/kprop/kproplog.c:503 +#, c-format +msgid "Update log dump :\n" +msgstr "განახლების ჟურნალის დამპი :\n" + +#: ../../src/kprop/kproplog.c:504 +#, c-format +msgid "\tLog version # : %u\n" +msgstr "\tჟურნალის ვერსია # : %u\n" + +#: ../../src/kprop/kproplog.c:505 +#, c-format +msgid "\tLog state : " +msgstr "\tჟურნალის მდგომარეობა : " + +#: ../../src/kprop/kproplog.c:508 +#, c-format +msgid "Stable\n" +msgstr "სტაბილური\n" + +#: ../../src/kprop/kproplog.c:511 +#, c-format +msgid "Unstable\n" +msgstr "არასტაბილური\n" + +#: ../../src/kprop/kproplog.c:514 +#, c-format +msgid "Corrupt\n" +msgstr "დაზიანებული\n" + +#: ../../src/kprop/kproplog.c:517 +#, c-format +msgid "Unknown state: %d\n" +msgstr "უცნობი მდგომარეობა: %d\n" + +#: ../../src/kprop/kproplog.c:520 +#, c-format +msgid "\tEntry block size : %u\n" +msgstr "\tჩანაწერის ბლოკის ზომა : %u\n" + +#: ../../src/kprop/kproplog.c:521 +#, c-format +msgid "\tNumber of entries : %u\n" +msgstr "\tჩანაწერების რაოდენობა : %u\n" + +#: ../../src/kprop/kproplog.c:524 +#, c-format +msgid "\tLast serial # : None\n" +msgstr "\tბოლო სერიული # : არცერთი\n" + +#: ../../src/kprop/kproplog.c:527 +#, c-format +msgid "\tFirst serial # : None\n" +msgstr "\tპირველი სერიული # : არცერთი\n" + +#: ../../src/kprop/kproplog.c:529 +#, c-format +msgid "\tFirst serial # : " +msgstr "\tპირველი სერიული # : " + +#: ../../src/kprop/kproplog.c:533 +#, c-format +msgid "\tLast serial # : " +msgstr "\tბოლო სერიული # : " + +#: ../../src/kprop/kproplog.c:538 +#, c-format +msgid "\tLast time stamp : None\n" +msgstr "\tბოლო დროის შტამპი : არცერთი\n" + +#: ../../src/kprop/kproplog.c:541 +#, c-format +msgid "\tFirst time stamp : None\n" +msgstr "\tპირველი დროის შტამპი : არცერთი\n" + +#: ../../src/kprop/kproplog.c:543 +#, c-format +msgid "\tFirst time stamp : %s" +msgstr "\tპირველი დროის შტამპი : %s" + +#: ../../src/kprop/kproplog.c:547 +#, c-format +msgid "\tLast time stamp : %s\n" +msgstr "\tბოლო დროის შტამპი : %s\n" + +#: ../../src/lib/apputils/net-server.c:231 +msgid "Got signal to request exit" +msgstr "მიღებულია სიგნალი გასვლის მოთხოვნისთვის" + +#: ../../src/lib/apputils/net-server.c:245 +msgid "Got signal to reset" +msgstr "მიღებულია სიგნალი საწყის მნიშვნელობებზე დასაბრუნებლად" + +#: ../../src/lib/apputils/net-server.c:311 +#, c-format +msgid "Invalid port %d" +msgstr "არასწორი პორტი %d" + +#: ../../src/lib/apputils/net-server.c:324 +#, c-format +msgid "Removing address %s since wildcard address is being added" +msgstr "მისამართი %s წაიშლება, რადგან საჭიროა ვაილდკარდი მისმართის დამატება" + +#: ../../src/lib/apputils/net-server.c:331 +msgid "Address already added to server" +msgstr "მისამართი სერვერზე უკვე დამატებულია" + +#: ../../src/lib/apputils/net-server.c:494 +#, c-format +msgid "closing down fd %d" +msgstr "fd %d-ის დახურვა" + +#: ../../src/lib/apputils/net-server.c:508 +#, c-format +msgid "descriptor %d closed but still in svc_fdset" +msgstr "დესკრიპტორი %d დახურულია, მაგრამ ჯერ კიდევ svc_fdset -შია" + +#: ../../src/lib/apputils/net-server.c:534 +msgid "cannot create io event" +msgstr "io მოვლენის შექმნის შეცდომა" + +#: ../../src/lib/apputils/net-server.c:539 +msgid "cannot save event" +msgstr "მოვლენის შენახვის შეცდომა" + +#: ../../src/lib/apputils/net-server.c:559 +#, c-format +msgid "file descriptor number %d too high" +msgstr "ფაილის დესკრიპტორის ნომერი %d ძალიან მაღალია" + +#: ../../src/lib/apputils/net-server.c:566 +msgid "cannot allocate storage for connection info" +msgstr "შეერთების ინფორმაციისთვის საცავის გამოყოფის შეცდომა" + +#: ../../src/lib/apputils/net-server.c:601 +#, c-format +msgid "Cannot create TCP server socket on %s" +msgstr "%s-ზე TCP სერვერის სოკეტის შექმნა შეუძლებელია" + +#: ../../src/lib/apputils/net-server.c:610 +#, c-format +msgid "TCP socket fd number %d (for %s) too high" +msgstr "TCP სოკეტის fd -ის ნომერი %d (%s-სთვის) ძალიან მაღალია" + +#: ../../src/lib/apputils/net-server.c:617 +#, c-format +msgid "Cannot enable SO_REUSEADDR on fd %d" +msgstr "SO_REUSEADDR-ის დაყენების შეცდომა fd-ზე %d" + +#: ../../src/lib/apputils/net-server.c:622 +#, c-format +msgid "setsockopt(%d,IPV6_V6ONLY,1) failed" +msgstr "setsockopt(%d,IPV6_V6ONLY,1) -ის შეცდომა" + +#: ../../src/lib/apputils/net-server.c:625 +#, c-format +msgid "setsockopt(%d,IPV6_V6ONLY,1) worked" +msgstr "setsockopt(%d,IPV6_V6ONLY,1) მუშაობს" + +#: ../../src/lib/apputils/net-server.c:628 +msgid "no IPV6_V6ONLY socket option support" +msgstr "სოკეტს IPV6_V6ONLY პარამეტრის მხარდაჭერა არ გააჩნია" + +#: ../../src/lib/apputils/net-server.c:634 +#, c-format +msgid "Cannot bind server socket on %s" +msgstr "სერვერის სოკეტზე მიბმის შეცდომა %s-ზე" + +#: ../../src/lib/apputils/net-server.c:704 +#, c-format +msgid "Setting up %s socket for address %s" +msgstr "%s სოკეტის მორგება მისამართისთვის %s" + +#: ../../src/lib/apputils/net-server.c:717 +#, c-format +msgid "Cannot listen on %s server socket on %s" +msgstr "%s სერვერის სოკეტზე მოსმენის შეცდომა %s-ზე" + +#: ../../src/lib/apputils/net-server.c:726 +#, c-format +msgid "cannot set listening %s socket on %s non-blocking" +msgstr "მოსმენის %s სოკეტის %s არაბლოკირებადზე დაყენების შეცდომა" + +#: ../../src/lib/apputils/net-server.c:734 +#, c-format +msgid "cannot set SO_LINGER on %s socket on %s" +msgstr "%s სოკეტზე %s-ზე SO_LINGER-ის დაყენების შეცდომა" + +#: ../../src/lib/apputils/net-server.c:741 +#, c-format +msgid "Setting pktinfo on socket %s" +msgstr "სოკეტზე %s pktinfo-ის დაყენება" + +#: ../../src/lib/apputils/net-server.c:746 +#, c-format +msgid "Cannot request packet info for UDP socket address %s port %d" +msgstr "" +"UDP სოკეტის მისამართის %s პორტის %d პაკეტის ინფორმაციის მოთხოვნის შეცდომა" + +#: ../../src/lib/apputils/net-server.c:748 +msgid "" +"System does not support pktinfo yet binding to a wildcard address. Packets " +"are not guaranteed to return on the received address." +msgstr "" +"სისტემას pktinfo-ის ვაილდკარდ მისამართზე მიბმის მხარდაჭერა არ გააჩნია. " +"გარანტია, რომ პაკეტები მიმღებ მისამართზე დაბრუნდება, არ არსებობს." + +#: ../../src/lib/apputils/net-server.c:760 +msgid "Error attempting to add verto event" +msgstr "შეცდომა verto მოვლენის დამატების მცდელობისას" + +#: ../../src/lib/apputils/net-server.c:769 +#, c-format +msgid "Cannot create RPC service: %s" +msgstr "RPC სერვისის შექმნის შეცდომა: %s" + +#: ../../src/lib/apputils/net-server.c:779 +#, c-format +msgid "Cannot register RPC service: %s" +msgstr "RPC სერვისის რეგისტრაციის შეცდომა: %s" + +#: ../../src/lib/apputils/net-server.c:823 +msgid "No addresses added to the net server" +msgstr "Net სერვერზე მისამართი არ დამატებულა" + +#: ../../src/lib/apputils/net-server.c:842 +#, c-format +msgid "Failed getting address info (for %s): %s" +msgstr "%s-სთვის მისამართის ინფორმაციის მიღების შეცდომა: %s" + +#: ../../src/lib/apputils/net-server.c:872 +#, c-format +msgid "Failed setting up a %s socket (for %s)" +msgstr "%s სოკეტის მორგებისას (%s-სთვის)" + +#: ../../src/lib/apputils/net-server.c:913 +msgid "setting up network..." +msgstr "ქსელის მორგება..." + +#: ../../src/lib/apputils/net-server.c:916 +msgid "Error setting up network" +msgstr "ქსელის მორგების შეცდომა" + +#: ../../src/lib/apputils/net-server.c:919 +#, c-format +msgid "set up %d sockets" +msgstr "მორგებულია %d სოკეტი" + +#: ../../src/lib/apputils/net-server.c:922 +msgid "no sockets set up?" +msgstr "სოკეტები ჩართული არაა?" + +#: ../../src/lib/apputils/net-server.c:985 +#: ../../src/lib/apputils/net-server.c:1039 +msgid "while dispatching (udp)" +msgstr "გაგზავნისას (udp)" + +#: ../../src/lib/apputils/net-server.c:1014 +#, c-format +msgid "while sending reply to %s/%s from %s" +msgstr "%s/%s -სთვის %s-დან პასუხის გაგზავნისას" + +#: ../../src/lib/apputils/net-server.c:1019 +#, c-format +msgid "short reply write %d vs %d\n" +msgstr "მოკლე პასუხის ჩაწერა %d-ი %d-ის წინააღმდეგ\n" + +#: ../../src/lib/apputils/net-server.c:1064 +msgid "while receiving from network" +msgstr "ქსელიდან მიღებისას" + +#: ../../src/lib/apputils/net-server.c:1107 +msgid "too many connections" +msgstr "მეტისმეტად ბევრი მიერთება" + +#: ../../src/lib/apputils/net-server.c:1125 +#, c-format +msgid "dropping %s fd %d from %s" +msgstr "%s fd-ის მოცილება %d-ი %s-დან" + +#: ../../src/lib/apputils/net-server.c:1195 +#, c-format +msgid "allocating buffer for new TCP session from %s" +msgstr "%s-დან მიღებული სესიისთვის ბუფერის გამოყოფა" + +#: ../../src/lib/apputils/net-server.c:1227 +msgid "while dispatching (tcp)" +msgstr "გაგზავნისას (tcp)" + +#: ../../src/lib/apputils/net-server.c:1259 +msgid "error allocating tcp dispatch private!" +msgstr "tcp გასაგზავნი პირის გამოყოფის შეცდომა!" + +#: ../../src/lib/apputils/net-server.c:1306 +#, c-format +msgid "TCP client %s wants %lu bytes, cap is %lu" +msgstr "TCP კლიენტს %s სურს %lu ბაიტი, ზღვარია %lu" + +#: ../../src/lib/apputils/net-server.c:1314 +#, c-format +msgid "error constructing KRB_ERR_FIELD_TOOLONG error! %s" +msgstr "შეცდომა KRB_ERR_FIELD_TOOLONG შეცდომის აწყოებისას! %s" + +#: ../../src/lib/apputils/net-server.c:1353 +#, c-format +msgid "getsockname failed: %s" +msgstr "getsockname -ის შეცდომა: %s" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:43 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:165 +msgid "A required input parameter could not be read" +msgstr "აუცილებელი შეყვანის პარამეტრის წაკითხვა შეუძლებელია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:44 +msgid "A required input parameter could not be written" +msgstr "აუცილებელი შეყვანის პარამეტრის ჩაწერა შეუძლებელია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:45 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:175 +msgid "A parameter was malformed" +msgstr "პარამეტრი არასწორია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:48 +msgid "calling error" +msgstr "გამოძახების შეცდომა" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:59 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:195 +msgid "An unsupported mechanism was requested" +msgstr "მოთხოვნილი მექანიზმი მხარდაუჭერელია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:60 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:199 +msgid "An invalid name was supplied" +msgstr "მიწოდებული სახელი არასწორია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:61 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:203 +msgid "A supplied name was of an unsupported type" +msgstr "მითითებული სახელის ტიპი მხარდაუჭერელია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:62 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:208 +msgid "Incorrect channel bindings were supplied" +msgstr "მიწოდებული არხების მიბმა არასწორია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:63 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:179 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:274 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:334 +msgid "An invalid status code was supplied" +msgstr "მიწოდებული სტატუსის კოდი არასწორია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:64 +msgid "A token had an invalid signature" +msgstr "კოდის ხელმოწერა არასწორია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:65 +msgid "No credentials were supplied" +msgstr "ავტორიზაციის დეტალები მიწოდებული არაა" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:66 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:223 +msgid "No context has been established" +msgstr "კონტექსტი აწყობილი არაა" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:67 +msgid "A token was invalid" +msgstr "კოდი არასწორია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:68 +msgid "A credential was invalid" +msgstr "ავტორიზაციის დეტალები არასწორია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:69 +msgid "The referenced credentials have expired" +msgstr "მიმართული ავტორიზაციის დეტალები ვადაგასულია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:70 +msgid "The context has expired" +msgstr "კონტექსტი ვადაგასულია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:71 +msgid "Miscellaneous failure" +msgstr "სხვადასხვა შეცდომა" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:72 +msgid "The quality-of-protection requested could not be provided" +msgstr "მოთხოვნილი quality-of-protection -ის მიწოდება შეუძლებელია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:73 +msgid "The operation is forbidden by the local security policy" +msgstr "ოპერაცია ლოკალური უსაფრთხოების პოლიტიკის მიერაა აკრძალული" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:74 +msgid "The operation or option is not available" +msgstr "ოპერაცია ან პარამეტრი ხელმისაწვდომი არაა" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:77 +msgid "routine error" +msgstr "ქვეპროგრამის შეცდომა" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:89 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:311 +msgid "The routine must be called again to complete its function" +msgstr "მისი ფუნქციის დასასრულებლად ქვეპროგრამა კიდევ ერთხელ უნდა გამოიძახოთ" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:90 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:316 +msgid "The token was a duplicate of an earlier token" +msgstr "ეს კოდი ძველი კოდის ასლს წარმოადგენდა" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:91 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:321 +msgid "The token's validity period has expired" +msgstr "კოდის ვარგისიანობის ვადა ამოწურულია" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:92 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:325 +msgid "A later token has already been processed" +msgstr "უფრო ახალი კოდი უკვე დამუშავდა" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:95 +msgid "supplementary info code" +msgstr "დამატებითი ინფორმაციის კოდი" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:106 +#: ../lib/krb5/error_tables/krb5_err.c:23 +msgid "No error" +msgstr "შეცდომის გარეშე" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:107 +#, c-format +msgid "Unknown %s (field = %d)" +msgstr "უცნობი %s (ველი = %d)" + +#: ../../src/lib/gssapi/krb5/acquire_cred.c:148 +#, c-format +msgid "No key table entry found matching %s" +msgstr "%s-ის შესაბამისი გასაღების ცხრილის ჩანაწერი არ არსებობს" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:161 +msgid "The routine completed successfully" +msgstr "ქვეპროგრამა წარმატებით დასრულდა" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:170 +msgid "A required output parameter could not be written" +msgstr "გამოტანის აუცილებელი პარამეტრის ჩაწერა შეუძლებელია" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:212 +msgid "A token had an invalid Message Integrity Check (MIC)" +msgstr "კოდის *შეტყობინების მთლიანობის შემოწმება\" (MIC) არასწორია" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:217 +msgid "" +"No credentials were supplied, or the credentials were unavailable or " +"inaccessible" +msgstr "ავტორიზაციის დეტალები მიწოდებული არაა, ან ისინი მიუწვდომელია" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:227 +msgid "Invalid token was supplied" +msgstr "მიწოდებული კოდი არასწორია" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:231 +msgid "Invalid credential was supplied" +msgstr "მიწოდებული ავტორიზაციის დეტალები არასწორია" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:235 +msgid "The referenced credential has expired" +msgstr "მიმართვის ავტორიზაციის დეტალების ვადა ამოწურულია" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:239 +msgid "The referenced context has expired" +msgstr "მიმართვის კონტექსტის ვადა ამოწურულია" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:243 +msgid "Unspecified GSS failure. Minor code may provide more information" +msgstr "" +"GSS-ის უცნობი შეცდომა. მცირე კოდს დამატებითი ინფორმაციის მოწოდება შეუძლია" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:248 +msgid "The quality-of-protection (QOP) requested could not be provided" +msgstr "მოთხოვნილი quality-of-protection -ის (QOP) მიწოდება შეუძლებელია" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:253 +msgid "The operation is forbidden by local security policy" +msgstr "ოპერაცია ლოკალური უსაფრთხოების პოლიტიკის მიერაა აკრძალული" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:258 +msgid "The operation or option is not available or unsupported" +msgstr "ოპერაცია ან პარამეტრი ხელმიუწვდომელი ან მხარდაუჭერელია" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:263 +msgid "The requested credential element already exists" +msgstr "ავტორიზაციის დეტალების ელემენტი უკვე არსებობს" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:268 +msgid "The provided name was not mechanism specific (MN)" +msgstr "მოწოდებული სახელი მექანიზმზე მიბმული (MN) არაა" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:329 +msgid "An expected per-message token was not received" +msgstr "თითოეული შეტყობინების მოსალოდნელი კოდი მიღებული არაა" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1824 +msgid "SPNEGO cannot find mechanisms to negotiate" +msgstr "SPNEGO -მა მოსალაპარაკებელი მექანიზმები ვერ იპოვა" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1826 +msgid "SPNEGO failed to acquire creds" +msgstr "SPNEGO ავტ.დეტალების მიღების შეცდომა" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1828 +msgid "SPNEGO acceptor did not select a mechanism" +msgstr "SPNEGO აქსეპტორმა მექანიზმი არ აირჩია" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1830 +msgid "SPNEGO failed to negotiate a mechanism" +msgstr "SPNEGO -მა მექანიზმის შეთანხმება ვერ შეძლო" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1832 +msgid "SPNEGO acceptor did not return a valid token" +msgstr "SPNEGO აქსეპტორმა სწორი კოდი არ დააბრუნა" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1834 +msgid "Invalid NegoEx signature" +msgstr "არასწორი NegoEx ხელმოწერია" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1836 +msgid "Invalid NegoEx message type" +msgstr "არასწორი NegoEx შეტყობინების ტიპი" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1838 +msgid "Invalid NegoEx message size" +msgstr "არასწორი NegoEx შეტყობინების ზომა" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1840 +msgid "Invalid NegoEx conversation ID" +msgstr "არასწორი NegoEx საუბრის ID" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1842 +msgid "NegoEx authentication scheme not found" +msgstr "NegoEx -ის ავთენტიკაციის სქემა ნაპოვნი არაა" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1844 +msgid "Missing NegoEx negotiate message" +msgstr "NegoEx-ის მოლაპარაკების შეტყობინება ვერ ვიპოვე" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1846 +msgid "Missing NegoEx authentication protocol request message" +msgstr "NegoEx -ის ავთენტიკაციის პროტოკოლის მოთხოვნის შეტყობინება ვერ ვიპოვე" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1848 +msgid "No mutually supported NegoEx authentication schemes" +msgstr "ორმხრივად მხარდაჭერილი NegoEx-ის ავთენტიკაციის სქემების გარეშე" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1850 +msgid "No NegoEx verify key" +msgstr "NegoEx -ის გასაღების გადამოწმების გარეშე" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1852 +msgid "Unknown NegoEx checksum scheme" +msgstr "NegoEx -ის საკონტროლო ჯამის უცნობი სქემა" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1854 +msgid "Invalid NegoEx checksum" +msgstr "NegoEx -ის საკონტროლო ჯამი არასწორია" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1856 +msgid "Unsupported critical NegoEx extension" +msgstr "მხარდაუჭერელი კრიტიკული NegoEx -ის გაფართოება" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1858 +msgid "Unsupported NegoEx version" +msgstr "NegoEx -ის მხარდაუჭერელი ვერსია" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1860 +msgid "NegoEx message out of sequence" +msgstr "NegoEx -ის შეტყობინება მიმდევრობის გარეთაა" + +#: ../../src/lib/kadm5/logger.c:54 +#, c-format +msgid "%s: cannot parse <%s>\n" +msgstr "%s: <%s>-ის დამუშავების შეცდომა\n" + +#: ../../src/lib/kadm5/logger.c:55 +#, c-format +msgid "%s: warning - logging entry syntax error\n" +msgstr "%s: გაფრთხილება - ჟურნალის ჩანაწერის სინტაქსის შეცდომა\n" + +#: ../../src/lib/kadm5/logger.c:56 +#, c-format +msgid "%s: error writing to %s\n" +msgstr "%s: %s-ში ჩაწერის შეცდომა\n" + +#: ../../src/lib/kadm5/logger.c:57 +#, c-format +msgid "%s: error writing to %s device\n" +msgstr "%s: შეცდომა %s მოწყობილობაში ჩაწერისას\n" + +#: ../../src/lib/kadm5/logger.c:59 +msgid "EMERGENCY" +msgstr "გადაუდებელი" + +#: ../../src/lib/kadm5/logger.c:60 +msgid "ALERT" +msgstr "განგაში" + +#: ../../src/lib/kadm5/logger.c:61 +msgid "CRITICAL" +msgstr "კრიტიკული" + +#: ../../src/lib/kadm5/logger.c:62 +msgid "Error" +msgstr "შეცდომა" + +#: ../../src/lib/kadm5/logger.c:63 +msgid "Warning" +msgstr "ყურადღება" + +#: ../../src/lib/kadm5/logger.c:64 +msgid "Notice" +msgstr "გაფრთხილება" + +#: ../../src/lib/kadm5/logger.c:65 +msgid "info" +msgstr "ინფო" + +#: ../../src/lib/kadm5/logger.c:66 +msgid "debug" +msgstr "გამართვა" + +#: ../../src/lib/kadm5/logger.c:784 +#, c-format +msgid "Couldn't open log file %s: %s\n" +msgstr "ჟურნალის ფაილის (%s) გახსნის შეცდომა: %s\n" + +#: ../../src/lib/kadm5/srv/kadm5_hook.c:120 +#, c-format +msgid "kadm5_hook %s failed postcommit %s: %s" +msgstr "kadm5_hook %s postcommit-ის შეცდომა %s: %s" + +#: ../../src/lib/kadm5/srv/pwqual_dict.c:106 +msgid "No dictionary file specified, continuing without one." +msgstr "ლექსიკონის ფაილი მითითებული არაა. მის გარეშე გავაგრძელებ." + +#: ../../src/lib/kadm5/srv/pwqual_dict.c:113 +#, c-format +msgid "WARNING! Cannot find dictionary file %s, continuing without one." +msgstr "გაფრთხილება! ლექსიკონი %s ვერ ვიპოვე. მის გარეშე გავაგრძელებ." + +#: ../../src/lib/kadm5/srv/pwqual_empty.c:42 +msgid "Empty passwords are not allowed" +msgstr "ცარიელი პაროლები დაუშვებელია" + +#: ../../src/lib/kadm5/srv/pwqual_hesiod.c:114 +msgid "Password may not match user information." +msgstr "პაროლი არ შეიძლება მომხმარებლის ინფორმაციას ემთხვეოდეს." + +#: ../../src/lib/kadm5/srv/pwqual_princ.c:54 +msgid "Password may not match principal name" +msgstr "პაროლი არ შეიძლება პრინციპალის სახელს შეიცავდეს" + +#: ../../src/lib/kadm5/srv/server_kdb.c:197 +msgid "History entry contains no key data" +msgstr "ისტორიის ჩანაწერი გასაღების მონაცემებს არ შეიცავს" + +#: ../../src/lib/kadm5/srv/server_misc.c:128 +#, c-format +msgid "password quality module %s rejected password for %s: %s" +msgstr "პაროლის ხარისხის მოდულმა %s %s-ის პაროლი უარყო: %s" + +#: ../../src/lib/kdb/kdb5.c:216 +msgid "No default realm set; cannot initialize KDB" +msgstr "ნაგულისხმები რეალმი დაყენებული არაა. KDB-ის ინიციალიზაციის შეცდომა" + +#: ../../src/lib/kdb/kdb5.c:370 +#, c-format +msgid "Unable to find requested database type: %s" +msgstr "მოთხოვნილი ბაზის ტიპის პოვნა შეუძლებელია: %s" + +#: ../../src/lib/kdb/kdb5.c:450 ../lib/krb5/error_tables/kdb5_err.c:55 +msgid "Unable to find requested database type" +msgstr "მოთხოვნილი ბაზის ტიპის პოვნა შეუძლებელია" + +#: ../../src/lib/kdb/kdb5.c:458 +msgid "plugin symbol 'kdb_function_table' lookup failed" +msgstr "დამატების სიმბოლოს 'kdb_function_table' -ის მოძებნის შეცდომა" + +#: ../../src/lib/kdb/kdb5.c:466 +#, c-format +msgid "" +"Unable to load requested database module '%s': plugin symbol " +"'kdb_function_table' not found" +msgstr "" +"მოთხოვნილი ბაზის მოდულის '%s' ჩატვირთვის შეცდომა: დამატების სიმბოლო " +"'kdb_function_table' ვერ ვიპოვე" + +#: ../../src/lib/kdb/kdb5.c:604 +msgid "Cannot initialize database library" +msgstr "ბაზის ბიბლიოთეკის ინიციალიზაციის შეცდომა" + +#: ../../src/lib/kdb/kdb5.c:1770 +#, c-format +msgid "Illegal version number for KRB5_TL_MKEY_AUX %d\n" +msgstr "KRB5_TL_MKEY_AUX -ის ვერსიის არასწორი ნომერი %d\n" + +#: ../../src/lib/kdb/kdb5.c:1942 +#, c-format +msgid "Illegal version number for KRB5_TL_ACTKVNO %d\n" +msgstr "KRB5_TL_ACTKVNO -ის ვერსიის არასწორი ნომერი %d\n" + +#: ../../src/lib/kdb/kdb_default.c:137 +#, c-format +msgid "keyfile (%s) is not a regular file: %s" +msgstr "keyfile (%s) ჩვეულებრივი ფაილი არაა: %s" + +#: ../../src/lib/kdb/kdb_default.c:150 +msgid "Could not create temp keytab file name." +msgstr "დროებითი keytab ფაილის სახელის შექმნის შეცდომა." + +#: ../../src/lib/kdb/kdb_default.c:175 +#, c-format +msgid "Temporary stash file already exists: %s." +msgstr "დროებითი Stash ფაილი უკვე არსებობს: %s." + +#: ../../src/lib/kdb/kdb_default.c:203 +#, c-format +msgid "rename of temporary keyfile (%s) to (%s) failed: %s" +msgstr "დროებითი keyfile-ის (%s)-ის სახელის (%s)-ზე გადარქმევის შეცდომა: %s" + +#: ../../src/lib/kdb/kdb_default.c:388 +#, c-format +msgid "Can not fetch master key (error: %s)." +msgstr "მთავარი გასაღების მოთხოვნის შეცდომა (შეცდომა: %s)" + +#: ../../src/lib/kdb/kdb_default.c:456 +msgid "Unable to decrypt latest master key with the provided master key\n" +msgstr "" +"მიწოდებული მთავარი გასაღებით უახლესი მთავარი გასაღების გაშიფვრა შეუძლებელია\n" + +#: ../../src/lib/kdb/kdb_log.c:87 +msgid "could not sync ulog update to disk" +msgstr "ulog-ის განახლების დისკთან სინქრონიზაციის შეცდომა" + +#: ../../src/lib/kdb/kdb_log.c:101 +msgid "could not sync ulog header to disk" +msgstr "ulog-ის თავსართის დისკთან სინქრონიზაციის შეცდომა" + +#: ../../src/lib/krb5/ccache/cc_dir.c:122 +#, c-format +msgid "Subsidiary cache path %s has no parent directory" +msgstr "შვილობილი ქეშის ბილიკს %s მშობელი საქაღალდე არ გააჩნია" + +#: ../../src/lib/krb5/ccache/cc_dir.c:128 +#, c-format +msgid "Subsidiary cache path %s filename does not begin with \"tkt\"" +msgstr "შვილობილი ქეშის ბილიკის %s ფაილის სახელი \"tkt\"-ით არ იწყება" + +#: ../../src/lib/krb5/ccache/cc_dir.c:169 +#, c-format +msgid "%s contains invalid filename" +msgstr "%s არასწორ ფაილის სახელს შეიცავს" + +#: ../../src/lib/krb5/ccache/cc_dir.c:229 +#, c-format +msgid "Credential cache directory %s does not exist" +msgstr "ავტორიზაციის დეტალების ქეშის საქაღალდე %s არ არსებობს" + +#: ../../src/lib/krb5/ccache/cc_dir.c:235 +#, c-format +msgid "Credential cache directory %s exists but is not a directory" +msgstr "" +"ავტორიზაციის დეტალების ქეშის საქაღალდე %s არსებობს, მაგრამ საქაღალდე არაა" + +#: ../../src/lib/krb5/ccache/cc_dir.c:400 +msgid "" +"Can't create new subsidiary cache because default cache is not a directory " +"collection" +msgstr "" +"ახალი შვილობილი ქეშის შექმნა შეუძლებელია იმიტომ, რომ ნაგულისხმები ქეში " +"საქაღალდეების კოლექციას არ წარმოადგენს" + +#: ../../src/lib/krb5/ccache/cc_kcm.c:908 +#, c-format +msgid "Credentials cache 'KCM:%s' not found" +msgstr "ავტორიზაციის დეტალების ქეში 'KCM:%s' ვერ ვიპოვე" + +#: ../../src/lib/krb5/ccache/cc_keyring.c:1149 +msgid "" +"Can't create new subsidiary cache because default cache is already a " +"subsidiary" +msgstr "" +"ახალი შვილობილი ქეშის შექმნა შეუძლებელია იმიტომ, რომ ნაგულისხმები ქეში უკვე " +"შვილობილია" + +#: ../../src/lib/krb5/ccache/cc_keyring.c:1217 +#, c-format +msgid "Credentials cache keyring '%s' not found" +msgstr "ავტორიზაციის დეტალების ბრელოკი '%s' არ არსებობს" + +#: ../../src/lib/krb5/ccache/cccursor.c:207 +#, c-format +msgid "Can't find client principal %s in cache collection" +msgstr "კლიენტის პრინციპალი %s ქეშის კოლექციაში არ არსებობს" + +#: ../../src/lib/krb5/ccache/cccursor.c:270 +msgid "No Kerberos credentials available" +msgstr "Kerberos-ის ავტორიზაციის დეტალები ხელმიუწვდომელია" + +#: ../../src/lib/krb5/ccache/cccursor.c:276 +#, c-format +msgid "No Kerberos credentials available (default cache: %s)" +msgstr "Kerberos-ის ავტორიზაციის დეტალები მიუწვდომელია (ნაგულისხმები ქეში: %s)" + +#: ../../src/lib/krb5/keytab/kt_file.c:389 +#, c-format +msgid "No key table entry found for %s" +msgstr "გასაღებების ცხრილის ჩანაწერი %s-სთვის არ არსებობს" + +#: ../../src/lib/krb5/keytab/kt_file.c:537 +#: ../../src/lib/krb5/keytab/kt_file.c:570 +msgid "Cannot change keytab with keytab iterators active" +msgstr "Keytab-ის შეცვლა, თუ keutab-ის იტერაცია ჩართულია, შეუძლებელია" + +#: ../../src/lib/krb5/keytab/kt_file.c:757 +#, c-format +msgid "Key table file '%s' not found" +msgstr "გასაღებების ცხრილის ფაილი \"%s\" არ არსებობს" + +#: ../../src/lib/krb5/keytab/ktfns.c:129 +#, c-format +msgid "Keytab %s is nonexistent or empty" +msgstr "Keytab %s არ არსებობს ან ცარიელია" + +#: ../../src/lib/krb5/krb/chpw.c:250 +msgid "Malformed request error" +msgstr "არასწორი მოთხოვნის შეცდომა" + +#: ../../src/lib/krb5/krb/chpw.c:253 ../lib/krb5/error_tables/kdb5_err.c:58 +msgid "Server error" +msgstr "სერვერის შეცდომა" + +#: ../../src/lib/krb5/krb/chpw.c:256 +msgid "Authentication error" +msgstr "ავთენტიკაციის შეცდომა" + +#: ../../src/lib/krb5/krb/chpw.c:259 +msgid "Password change rejected" +msgstr "პაროლის შეცვლა უარყოფილია" + +#: ../../src/lib/krb5/krb/chpw.c:262 +msgid "Access denied" +msgstr "წვდომა აკრძალულია" + +#: ../../src/lib/krb5/krb/chpw.c:265 +msgid "Wrong protocol version" +msgstr "არასწორი პროტოკოლის ვერსია" + +#: ../../src/lib/krb5/krb/chpw.c:268 +msgid "Initial password required" +msgstr "საჭიროა საწყისი პაროლი" + +#: ../../src/lib/krb5/krb/chpw.c:271 +msgid "Success" +msgstr "წარმატება" + +#: ../../src/lib/krb5/krb/chpw.c:274 ../lib/krb5/error_tables/krb5_err.c:257 +msgid "Password change failed" +msgstr "პაროლის შეცვლის შეცდომა" + +#: ../../src/lib/krb5/krb/chpw.c:431 +msgid "" +"The password must include numbers or symbols. Don't include any part of " +"your name in the password." +msgstr "" +"პაროლი რიცხვები ან სიმბოლოებს აუცილებლად უნდა შეიცავდეს. თქვენს სახელს " +"პაროლის ნურც ერთ ნაწილს ნუ მიაწერთ." + +#: ../../src/lib/krb5/krb/chpw.c:437 +#, c-format +msgid "The password must contain at least %d character." +msgid_plural "The password must contain at least %d characters." +msgstr[0] "პაროლი მინიმუმ %d სიმბოლოს უნდა შეიცავდეს ." +msgstr[1] "პაროლი მინიმუმ %d სიმბოლოს უნდა შეიცავდეს ." + +#: ../../src/lib/krb5/krb/chpw.c:446 +#, c-format +msgid "The password must be different from the previous password." +msgid_plural "The password must be different from the previous %d passwords." +msgstr[0] "ახალი პაროლი წინასგან უნდა განსხვავდებოდეს." +msgstr[1] "ახალი პაროლი წინა %d პაროლისგან უნდა განსხვავდებოდეს." + +#: ../../src/lib/krb5/krb/chpw.c:458 +#, c-format +msgid "The password can only be changed once a day." +msgid_plural "The password can only be changed every %d days." +msgstr[0] "პაროლი მხოლოდ დღეში ერთხელ შეგიძლიათ შეცვალოთ." +msgstr[1] "პაროლი მხოლოდ %d დღეში ერთხელ შეგიძლიათ შეცვალოთ." + +#: ../../src/lib/krb5/krb/chpw.c:504 +msgid "Try a more complex password, or contact your administrator." +msgstr "სცადეთ უფრო რთული პაროლი ან დაუკავშირდით ადმინისტრატორს." + +#: ../../src/lib/krb5/krb/fast.c:216 +msgid "Error constructing AP-REQ armor" +msgstr "შეცდომა AP-REQ აბჯრის აწყობისას" + +#: ../../src/lib/krb5/krb/fast.c:394 +msgid "Failed to decrypt FAST reply" +msgstr "შეცდომა FAST პასუხის გაშიფვრისას" + +#: ../../src/lib/krb5/krb/fast.c:400 +msgid "nonce modified in FAST response: KDC response modified" +msgstr "მითითებულ დროს შესწორება FAST პასუხში: KDC-ის პასუხი შეიცვალა" + +#: ../../src/lib/krb5/krb/fast.c:466 +msgid "Expecting FX_ERROR pa-data inside FAST container" +msgstr "FAST კონტენერში FX_ERROR pa-data-ს მოველოდი" + +#: ../../src/lib/krb5/krb/fast.c:537 +msgid "FAST response missing finish message in KDC reply" +msgstr "KDC-ის გამოხმაურებაში FAST პასუხს დასრულების შეტყობინება აკლია" + +#: ../../src/lib/krb5/krb/fast.c:550 +msgid "Ticket modified in KDC reply" +msgstr "KDC-ის პასუხში ბილეთი შეიცვალა" + +#: ../../src/lib/krb5/krb/gc_via_tkt.c:198 +#, c-format +msgid "KDC returned error string: %.*s" +msgstr "KDC -ის მიერ დაბრუნებული შეცდომის სტრიქონი: %.*s" + +#: ../../src/lib/krb5/krb/gc_via_tkt.c:207 +#, c-format +msgid "Server %s not found in Kerberos database" +msgstr "სერვერი %s Kerberos-ის ბაზაში არ არსებობს" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:202 +msgid "Reply has wrong form of session key for anonymous request" +msgstr "პასუხს ანონიმური მოთხოვნისთვის სესიის გასაღების არასწორი ფორმა გააჩნია" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1570 +#, c-format +msgid "Warning: Your password will expire in less than one hour on %s" +msgstr "გაფრთხილება: თქვენს პაროლს ვადა ერთ საათზე ნაკლებში, %s-ზე გაუვა" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1574 +#, c-format +msgid "Warning: Your password will expire in %d hour%s on %s" +msgstr "გაფრთხილება: თქვენს პაროლს ვადა %d საათში%s %s-ზე გაუვა" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1578 +#, c-format +msgid "Warning: Your password will expire in %d days on %s" +msgstr "გაფრთხილება: თქვენს პაროლს ვადა %d დღეში, %s-ზე გაუვა" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1600 +msgid "" +"Warning: encryption type des3-cbc-sha1 used for authentication is weak and " +"will be disabled" +msgstr "" +"გაფრთხილება: ავთენტიკაციისთვის გამოყენებული დაშიფვრის ტიპი des3-cbc-sha1 " +"სუსტია და გაითიშება" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1844 +msgid "Failed to store credentials" +msgstr "ავტორიზაციის დეტალების დამახსოვრების შეცდომა" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1939 +#, c-format +msgid "Client '%s' not found in Kerberos database" +msgstr "კლიენტი '%s' Kerberos-ის ბაზაში ვერ ვიპოვე" + +#: ../../src/lib/krb5/krb/gic_keytab.c:225 +#, c-format +msgid "Keytab contains no suitable keys for %s" +msgstr "Keytab-ი %s-სთვის შესაბამის გასაღებებს არ შეიცავს" + +#: ../../src/lib/krb5/krb/gic_pwd.c:75 +#, c-format +msgid "Password for %s" +msgstr "პაროლი \"%s\" -სთვის" + +#: ../../src/lib/krb5/krb/gic_pwd.c:301 +msgid "Password expired. You must change it now." +msgstr "პაროლის ვადა ამოიწურა. ის ახლავე უნდა შეცვალოთ." + +#: ../../src/lib/krb5/krb/gic_pwd.c:320 ../../src/lib/krb5/krb/gic_pwd.c:324 +#, c-format +msgid "%s. Please try again." +msgstr "%s. თავიდან სცადეთ." + +#: ../../src/lib/krb5/krb/gic_pwd.c:365 +#, c-format +msgid "%.*s%s%s. Please try again.\n" +msgstr "%.*s%s%s. თავიდან სცადეთ.\n" + +#: ../../src/lib/krb5/krb/parse.c:202 +#, c-format +msgid "Principal %s is missing required realm" +msgstr "პრინციპალს %s აუცილებელი რეალმი არ გააჩნია" + +#: ../../src/lib/krb5/krb/parse.c:214 +#, c-format +msgid "Principal %s has realm present" +msgstr "პრინციპალს %s რეალმი გააჩნია" + +#: ../../src/lib/krb5/krb/plugin.c:169 +#, c-format +msgid "Invalid module specifier %s" +msgstr "მოდულის არასწორი მიმთითებელი %s" + +#: ../../src/lib/krb5/krb/plugin.c:416 +#, c-format +msgid "Could not find %s plugin module named '%s'" +msgstr "%s დამატების მოდული, სახელით '%s' ვერ ვიპოვე" + +#: ../../src/lib/krb5/krb/preauth2.c:309 +msgid "krb5_init_creds calls must use same library context" +msgstr "" +"krb5_init_creds -ის გამოძახებებმა იგივე ბიბლიოთეკის კონტექსტი უნდა გამოიყენონ" + +#: ../../src/lib/krb5/krb/preauth2.c:717 +msgid "Pre-authentication failed" +msgstr "პრე-ავთენტიკაციის შეცდომა" + +#: ../../src/lib/krb5/krb/preauth2.c:1046 +msgid "Unable to initialize preauth context" +msgstr "პრეავთენტიკაციის კონტექსტის ინციალიზაციის შეცდომა" + +#: ../../src/lib/krb5/krb/preauth2.c:1059 +#, c-format +msgid "Preauth module %s" +msgstr "Preauth მოდული %s" + +#: ../../src/lib/krb5/krb/preauth_encts.c:71 +msgid "Encrypted timestamp is disabled" +msgstr "დაშიფრული დროის შტამპი გათიშულია" + +#: ../../src/lib/krb5/krb/preauth_otp.c:514 +msgid "Please choose from the following:\n" +msgstr "აირჩიეთ შემდეგი სიიდან:\n" + +#: ../../src/lib/krb5/krb/preauth_otp.c:516 +msgid "Vendor:" +msgstr "მომწოდებელი:" + +#: ../../src/lib/krb5/krb/preauth_otp.c:525 +msgid "Enter #" +msgstr "შეიყვანეთ #" + +#: ../../src/lib/krb5/krb/preauth_otp.c:561 +msgid "OTP Challenge:" +msgstr "OTP გამოწვევა:" + +#: ../../src/lib/krb5/krb/preauth_otp.c:590 +msgid "OTP Token PIN" +msgstr "OTP კოდის PIN" + +#: ../../src/lib/krb5/krb/preauth_otp.c:704 +msgid "OTP value doesn't match any token formats" +msgstr "OTP-ის მნიშვნელობა კოდის არც ერთ ფორმატს არ ემთხვევა" + +#: ../../src/lib/krb5/krb/preauth_otp.c:771 +msgid "Enter OTP Token Value" +msgstr "შეიყვანეთ OTP კოდის მნიშვნელობა" + +#: ../../src/lib/krb5/krb/preauth_otp.c:917 +msgid "No supported tokens" +msgstr "მხარდაჭერილი კოდების გარეშე" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:49 +msgid "Challenge for Enigma Logic mechanism" +msgstr "გამოწვევა Enigma Logic მექანიზმისთვის" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:53 +msgid "Challenge for Digital Pathways mechanism" +msgstr "გამოწვევა Digital Pathways მექანიზმისთვის" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:57 +msgid "Challenge for Activcard mechanism" +msgstr "გამოწვევა Activcard მექანიზმისთვის" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:60 +msgid "Challenge for Enhanced S/Key mechanism" +msgstr "გამოწვევა გაფართოებული S/Key მექანიზმისთვის" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:63 +msgid "Challenge for Traditional S/Key mechanism" +msgstr "გამოწვევა ტრადიციული S/Key მექანიზმისთვის" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:66 +#: ../../src/lib/krb5/krb/preauth_sam2.c:69 +msgid "Challenge for Security Dynamics mechanism" +msgstr "გამოწვევა Security Dynamics მექანიზმისთვის" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:72 +msgid "Challenge from authentication server" +msgstr "გამოწვევა ავთენტიკაციის სერვერიდან" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:164 +msgid "SAM Authentication" +msgstr "SAM ავთენტიკაცია" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:146 +#, c-format +msgid "Cannot find key for %s kvno %d in keytab" +msgstr "შეცდომა გასაღების მოძებნისას %s kvno %d Keytab-ში" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:151 +#, c-format +msgid "Cannot find key for %s kvno %d in keytab (request ticket server %s)" +msgstr "" +"Keytab-ში %s kvno %d-სთვის გასაღები ვერ ვიპოვე (მოთხოვნის ბილეთის სერვერი %s)" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:176 +#, c-format +msgid "Cannot decrypt ticket for %s using keytab key for %s" +msgstr "" +"%s-სთვის ბილეთის გაშიფვრა keytab-ის %s-სთვის განკუთვნილი გასაღებით " +"შეუძლებელია" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:198 +#, c-format +msgid "Server principal %s does not match request ticket server %s" +msgstr "სერვერის პრინციპალი %s ბილეთების სერვერს %s არ ემთხვევა" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:227 +msgid "No keys in keytab" +msgstr "Keytab-ში გასაღებები არაა" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:230 +#, c-format +msgid "Server principal %s does not match any keys in keytab" +msgstr "სერვერის პრინციპალი %s keytab-ის არც ერთ გასაღებს არ ემთხვევა" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:237 +#, c-format +msgid "" +"Request ticket server %s found in keytab but does not match server principal " +"%s" +msgstr "" +"მოთხოვნის ბილეთის სერვერი %s keytab-ში არსებობს, მაგრამ სერვერის პრინციპალს " +"%s არ ემთხვევა" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:242 +#, c-format +msgid "Request ticket server %s not found in keytab (ticket kvno %d)" +msgstr "მოთხოვნილი ბილეთის სერვერი %s keytab-ში ვერ ვიპოვე (ბილეთის kvno %d)" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:248 +#, c-format +msgid "" +"Request ticket server %s kvno %d not found in keytab; ticket is likely out " +"of date" +msgstr "" +"მოთხოვნის ბილეთის სერვერი %s kvno %d keytab-ში ვერ ვიპოვე. ბილეთი, როგორც " +"ჩანს, ვადაგასულია" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:253 +#, c-format +msgid "" +"Request ticket server %s kvno %d not found in keytab; keytab is likely out " +"of date" +msgstr "" +"მოთხოვნის ბილეთის სერვერი %s kvno %d keytab-ში ვერ ვიპოვე. keytab-ი, როგორც " +"ჩანს, ვადაგასულია" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:262 +#, c-format +msgid "" +"Request ticket server %s kvno %d found in keytab but not with enctype %s" +msgstr "" +"მოთხოვნილი ბილეთის სერვერი %s kvno %d keytab-ში ვიპოვე, მაგრამ მისი enctype " +"%s არაა" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:267 +#, c-format +msgid "" +"Request ticket server %s kvno %d enctype %s found in keytab but cannot " +"decrypt ticket" +msgstr "" +"მოთხოვნის ბილეთის სერვერი %s kvno %d enctype %s keytab-ში ვიპოვე, მაგრამ " +"ბილეთის გაშიფვრა შეუძლებელია" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:884 +#, c-format +msgid "Encryption type %s not permitted" +msgstr "დაშიფვრის ტიპი %s დაუშვებელია" + +#: ../../src/lib/krb5/krb/s4u_creds.c:1043 +msgid "Realm specified but S4U2Proxy must use referral realm" +msgstr "" +"რეალმი მითითებულია, მაგრამ S4U2Proxy -მა მიმართული რეალმი უნდა გამოიყენოს" + +#: ../../src/lib/krb5/os/expand_path.c:316 +#, c-format +msgid "Can't find username for uid %lu" +msgstr "მომხმარებლის სახელის პოვნა uid %lu-სთვის შეუძლებელია" + +#: ../../src/lib/krb5/os/expand_path.c:405 +#: ../../src/lib/krb5/os/expand_path.c:421 +msgid "Invalid token" +msgstr "არასწორი კოდი" + +#: ../../src/lib/krb5/os/expand_path.c:506 +msgid "variable missing }" +msgstr "ცვლადს აკლია }" + +#: ../../src/lib/krb5/os/locate_kdc.c:818 +#, c-format +msgid "Cannot find KDC for realm \"%.*s\"" +msgstr "შეცდომა KDC -ის ძებნისას რეალმისთვის \"%.*s\"" + +#: ../../src/lib/krb5/os/sendto_kdc.c:519 +#, c-format +msgid "Cannot contact any KDC for realm '%.*s'" +msgstr "შეცდომა ყველა KDC-სთან მიერთებისას რეალმისთვის '%.*s'" + +#: ../../src/plugins/kdb/db2/kdb_db2.c:245 +#: ../../src/plugins/kdb/db2/kdb_db2.c:819 +#, c-format +msgid "Unsupported argument \"%s\" for db2" +msgstr "DB2-ის მხარდაუჭერელი არგუმენტი \"%s\"" + +#: ../../src/plugins/kdb/db2/kdb_db2.c:387 +#, c-format +msgid "Cannot open DB2 database '%s'" +msgstr "შეცდომა DB2-ის ბაზის '%s' გახსნისას" + +#: ../../src/plugins/kdb/db2/kdb_db2.c:989 +msgid "Recursive iteration is not supported for hash databases" +msgstr "ჰეშ-ბაზებისთვის რეკურსიული იტერაცია მხარდაუჭერელია" + +#: ../../src/plugins/kdb/db2/kdb_db2.c:996 +msgid "Recursive iteration not supported in this version of libdb" +msgstr "Libdb-ის ამ ვერსიაში რეკურსიული იტერაცია მხარდაჭერილი არაა" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:69 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:859 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1060 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1467 +msgid "while reading kerberos container information" +msgstr "kerberos-ის კონტეინერის ინფორმაციის წაკითხვსას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:129 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:143 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:504 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:518 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:150 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:165 +msgid "while providing time specification" +msgstr "დროის სპეციფიკაციის მიწოდებისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:268 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:304 +msgid "while creating policy object" +msgstr "პოლიტიკის ობიექტის შექმნისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:279 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1475 +msgid "while reading realm information" +msgstr "რეალმის ინფორმაციის წაკითხვისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:348 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:407 +msgid "while destroying policy object" +msgstr "პოლიტიკის ობიექტის განადგურებისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:358 +#, c-format +msgid "This will delete the policy object '%s', are you sure?\n" +msgstr "ეს წაშლის პოლიტიკის ობიექტს '%s'. დარწმუნებული ბრძანდებით?\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:473 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:663 +msgid "while modifying policy object" +msgstr "პოლიტიკის ობიექტის შეცვლისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:487 +#, c-format +msgid "while reading information of policy '%s'" +msgstr "პოლიტიკის \"%s\" ინფორმაციის წაკითხვისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:692 +msgid "while viewing policy" +msgstr "პოლიტიკის დათვალიერებისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:701 +#, c-format +msgid "while viewing policy '%s'" +msgstr "პოლიტიკის ('%s') დათვალიერებისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:835 +msgid "while listing policy objects" +msgstr "პოლიტიკის ობიექტების ჩამოთვლიას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:419 +#, c-format +msgid "for subtree while creating realm '%s'" +msgstr "ქვეხისთვის რეალმის '%s' შექმნისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:431 +#, c-format +msgid "for container reference while creating realm '%s'" +msgstr "კონტეინერის მიმართვისთვის რეალმის ('%s') შექმნისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:456 +#, c-format +msgid "invalid search scope while creating realm '%s'" +msgstr "ძებნის არასწორი დიაპაზონი რეალმის '%s' შექმნისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:471 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:795 +#, c-format +msgid "'%s' is an invalid option\n" +msgstr "'%s' არასწორი პარამეტრია \n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:479 +#, c-format +msgid "Initializing database for realm '%s'\n" +msgstr "ბაზის ინიციალიზაცია რეალმისთვის '%s'\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:503 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:664 +#, c-format +msgid "while creating realm '%s'" +msgstr "რეალმის \"%s\" შექმნისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:523 +#, c-format +msgid "Enter DN of Kerberos container: " +msgstr "შეიყვანეთ Kerberos-ის კონტეინერის DN: " + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:558 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:866 +#, c-format +msgid "while reading information of realm '%s'" +msgstr "რეალმის '%s' ინფორმაციის წაკითხვისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:702 +msgid "while reading Kerberos container information" +msgstr "kerberos-ის კონტეინერის ინფორმაციის წაკითხვსას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:745 +#, c-format +msgid "for subtree while modifying realm '%s'" +msgstr "ქვეხისთვის რეალმის '%s' ცვლილებისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:756 +#, c-format +msgid "for container reference while modifying realm '%s'" +msgstr "კონტეინერის მიმართვისთვის რეალმის ('%s') ცვლილებისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:784 +#, c-format +msgid "specified for search scope while modifying information of realm '%s'" +msgstr "მითითებულია ძებნის დიაპაზონისთვის რეალმის '%s' ინფორმაციის შეცვლისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:823 +#, c-format +msgid "while modifying information of realm '%s'" +msgstr "რეალმის '%s' ინფორმაციის შეცვლისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:912 +msgid "Realm Name" +msgstr "რეალმის სახელი" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:915 +msgid "Subtree" +msgstr "ქვეხე" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:918 +msgid "Principal Container Reference" +msgstr "პრინციპალის კონტეინერის მიმართვა" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:923 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:925 +msgid "SearchScope" +msgstr "ძებნისდიაპაზონი" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:923 +msgid "Invalid !" +msgstr "არასწორია !" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:930 +msgid "KDC Services" +msgstr "KDC სერვისები" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:945 +msgid "Admin Services" +msgstr "ადმინის სერვისები" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:960 +msgid "Passwd Services" +msgstr "Passwd -ის სერვისები" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:976 +msgid "Maximum Ticket Life" +msgstr "ბილეთის მაქსიმალური სიცოცხლე" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:981 +msgid "Maximum Renewable Life" +msgstr "მაქსიმალური განახლებადი სიცოცხლე" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:988 +msgid "Ticket flags" +msgstr "ბილეთის ალმები" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1067 +msgid "while listing realms" +msgstr "რეალმების სიის გამოტანისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1399 +msgid "while adding entries to database" +msgstr "ბაზაში ჩანაწერების დამატებისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1440 +#, c-format +msgid "Deleting KDC database of '%s', are you sure?\n" +msgstr "წაიშლება '%s'-ის KDC-ის ბაზა. დარწმუნებული ბრძანდებით?\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1451 +#, c-format +msgid "OK, deleting database of '%s'...\n" +msgstr "კარგი, მიმდინარეობს ბაზის წაშლა '%s'...\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1484 +#, c-format +msgid "deleting database of '%s'" +msgstr "%s-ის ბაზის წაშლა" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1489 +#, c-format +msgid "** Database of '%s' destroyed.\n" +msgstr "** ბაზა '%s' განადგურდა.\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:79 +msgid "ldap_service_password_file not configured" +msgstr "ldap_service_password_file მორგებული არაა" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:124 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:131 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:141 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:169 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:239 +msgid "while setting service object password" +msgstr "სერვისის ობიექტის პაროლის დაყენებისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:148 +msgid "while getting service password filename" +msgstr "სერვისის პაროლის ფაილის სახელის მიღებისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:161 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:481 +#, c-format +msgid "Password for \"%s\"" +msgstr "პაროლი \"%s\" -სთვის" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:164 +#, c-format +msgid "Re-enter password for \"%s\"" +msgstr "ხელახლა შეიყვანეთ ახალი პაროლი \"%s\"-სთვის" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:175 +#, c-format +msgid "%s: Invalid password\n" +msgstr "%s: არასწორი პაროლი\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:185 +msgid "Failed to convert the password to hexadecimal" +msgstr "პაროლის თექვსმეტობითში გადაყვანის შეცდომა" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:195 +#, c-format +msgid "Failed to open file %s: %s" +msgstr "ფაილის (%s) გახსნა შეუძლებელია: %s" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:217 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:259 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:268 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:295 +msgid "Failed to write service object password to file" +msgstr "სერვისის ობიექტის პაროლის ფაილში ჩაწერის შეცდომა" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:223 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:280 +msgid "Error reading service object password file" +msgstr "შეცდომა სერვისის ობიეტქის პაროლის ფაილის წაკითხვისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:248 +#, c-format +msgid "Error creating file %s" +msgstr "ფაილის შექმნის შეცდომა: %s" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:105 +#, c-format +msgid "" +"Usage: kdb5_ldap_util [-D user_dn [-w passwd]] [-H ldapuri] [-r realm]\n" +"\tcmd [cmd_options]\n" +"create [-subtrees subtree_dn_list] [-sscope search_scope]\n" +"\t\t[-containerref container_reference_dn]\n" +"\t\t[-m|-P password|-sf stashfilename] [-s]\n" +"\t\t[-k mkeytype] [-kv mkeyVNO] [-M mkeyname]\n" +"\t\t[-maxtktlife max_ticket_life]\n" +"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags]\n" +"modify [-subtrees subtree_dn_list] [-sscope search_scope]\n" +"\t\t[-containerref container_reference_dn]\n" +"\t\t[-maxtktlife max_ticket_life]\n" +"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags]\n" +"view\n" +"destroy [-f]\n" +"list\n" +"stashsrvpw [-f filename] service_dn\n" +"create_policy [-maxtktlife max_ticket_life]\n" +"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n" +"modify_policy [-maxtktlife max_ticket_life]\n" +"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n" +"view_policy policy\n" +"destroy_policy [-force] policy\n" +"list_policy\n" +msgstr "" +"გამოყენება: kdb5_ldap_util [-D მომხმარებლის_dn [-w პაროლი]] [-H ldapuri] [-r " +"რეალმი]\n" +"\tბრძანება [ბრძანებისპარამეტრები]\n" +"create [-subtrees ქვეხის_dn_ის_სია\t] [-sscope ძებნის_დიაპაზონი]\n" +"\t\t[-containerref კონტეინერის_მიმართვის_dn]\n" +"\t\t[-m|-P პაროლი|-sf stash_ფაილისსახელი] [-s]\n" +"\t\t[-k mkeytype] [-kv mkeyVNO] [-M mგასაღებისსახელი]\n" +"\t\t[-maxtktlife ბილეთის_მაქს_სიცოცხლის_ხანგრძლ]\n" +"\t\t[-maxrenewlife ბილეთის_მაქს_განახლებადი_სიცოცხლის_ხანგრძლ] " +"[ბილეთის_ალმები]\n" +"modify [-subtrees ქვეხის_dn_ის_სია] [-sscope ძებნის_დიაპაზონი]\n" +"\t\t[-containerref კონტეინერის_მიმართვის_dn]\n" +"\t\t[-maxtktlife ბილეთის_მაქს_სიცოცხლის_ხანგრძლ]\n" +"\t\t[-maxrenewlife ბილეთის_მაქს_განახლებადი_სიცოცხლის_ხანგრძლ] " +"[ბილეთის_ალმები]\n" +"view\n" +"destroy [-f]\n" +"list\n" +"stashsrvpw [-f ფაილისსახელი] სერვისის_dn\n" +"create_policy [-maxtktlife ბილეთის_მაქს_სიცოცხლის_ხანგრძლ]\n" +"\t\t[-maxrenewlife ბილეთის_მაქს_განახლებადი_სიცოცხლის_ხანგრძლ] " +"[ბილეთის_ალმები] პოლიტიკა\n" +"modify_policy [-maxtktlife ბილეთის_მაქს_სიცოცხლის_ხანგრძლ]\n" +"\t\t[-maxrenewlife ბილეთის_მაქს_განახლებადი_სიცოცხლის_ხანგრძლ] " +"[ბილეთის_ალმები] პოლიტიკა\n" +"view_policy პოლიტიკა\n" +"destroy_policy [-force] პოლიტიკა\n" +"list_policy\n" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:329 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:337 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:345 +msgid "while reading ldap parameters" +msgstr "ldap-ის პარამეტრების წაკითხვისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:443 +msgid "while initializing error handling" +msgstr "შეცდომების დამუშავებლის ინიციალიზაციისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:451 +msgid "while initializing ldap handle" +msgstr "ldap-ის დამმუშავებლის ინიციალიზაციისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:465 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:474 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:487 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:529 +msgid "while retrieving ldap configuration" +msgstr "ldap-ის კონფიგურაციის მიღებისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:504 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:511 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:520 +msgid "while initializing server list" +msgstr "სერვერების სიის ინიციალიზაციისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:551 +msgid "while setting up lib handle" +msgstr "ბიბლიოთეკის დამმუშავებლის მორგებისას" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:560 +msgid "while reading ldap configuration" +msgstr "ldap-ის კონფიგურაციის წაკითხვისას" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:68 +msgid "Unable to read Kerberos container" +msgstr "Kerberos-ის კონტეინერის წაკითხვის შეცდომა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:73 +msgid "Unable to read Realm" +msgstr "რეალმის წაკითხვის შეცდომა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:214 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c:71 +msgid "Error processing LDAP DB params" +msgstr "შეცდომა LDAP DB-ის პარამეტრების დამუშავებისას" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:220 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c:77 +msgid "Error reading LDAP server params" +msgstr "შეცდომა LDAP სერვერის პარამეტრების წაკითხვისას" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:64 +msgid "LDAP bind dn value missing" +msgstr "LDAP-ის მისამაგრებელი DN-ის მნიშვნელობა მითითებული არაა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:69 +msgid "LDAP bind password value missing" +msgstr "LDAP-ის მისამაგრებელი პაროლის მნიშვნელობა მითითებული არაა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:78 +msgid "Error reading password from stash" +msgstr "Stash ფაილიდან პაროლის წაიკითხვის შეცდომა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:85 +msgid "Service password length is zero" +msgstr "სერვისის პაროლის სიგრძე ნულოვანია" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:145 +#, c-format +msgid "Cannot bind to LDAP server '%s' with SASL mechanism '%s': %s" +msgstr "LDAP სერვერთან '%s' SASL მექანიზმით '%s' მიბმის შეცდომა: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:158 +#, c-format +msgid "Cannot bind to LDAP server '%s' as '%s': %s" +msgstr "შეცდომა LDAP სერვერთან '%s' მიბმისას, როგორც '%s': %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:183 +#, c-format +msgid "Cannot create LDAP handle for '%s': %s" +msgstr "'%s'-სთვის LDAP დამმუშავებლის შექმნის შეცდომა: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c:56 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c:67 +msgid "Error reading kerberos container location from krb5.conf" +msgstr "Krb5.conf-დან Kerbreros-ის კონტეინერის მდებარეობის წაკითხვის შეცდომა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c:75 +msgid "Kerberos container location not specified" +msgstr "Kerberos-ის კონტეინერის მდებარეობა მითითებული არაა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:56 +#, c-format +msgid "Error reading '%s' attribute: %s" +msgstr "შეცდომა %s ატრიბუტის წაკითხვისას: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:219 +msgid "KDB module requires -update argument" +msgstr "KDB მოდულისთვის -update არგუმენტი აუცილებელია" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:225 +#, c-format +msgid "'%s' value missing" +msgstr "'%s' მნიშვნელობა აკლია" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:283 +#, c-format +msgid "unknown option '%s'" +msgstr "უცნობი პარამეტრი '%s'" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:343 +msgid "Minimum connections required per server is 2" +msgstr "თითოეულ სერვერთან მიერთების მინიმალური რაოდენობა ორის ტოლია" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c:160 +msgid "Default realm not set" +msgstr "ნაგულისხმები რეალმი დაყენებული არაა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c:264 +msgid "DN information missing" +msgstr "DN ინფორმაცია აკლია" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c:476 +msgid "dn information missing" +msgstr "dn ინფორმაცია აკლია" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:137 +msgid "Principal does not belong to realm" +msgstr "პრინციპალი რეალმს არ ეკუთვნის" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:305 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:314 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:322 +#, c-format +msgid "%s option not supported" +msgstr "%s პარამეტრი მხარდაუჭერელია" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:329 +#, c-format +msgid "unknown option: %s" +msgstr "უცნობი პარამეტრი: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:336 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:343 +#, c-format +msgid "%s option value missing" +msgstr "%s პარამეტრის მნიშვნელობა მითითებული არაა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:676 +msgid "DN is out of the realm subtree" +msgstr "DN რეალმის ქვეხის გარეთაა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:708 +msgid "ldap object is already kerberized" +msgstr "ldap ობიექტი უკვე kerberos-ის მართვის ქვეშაა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:803 +msgid "Principal does not belong to the default realm" +msgstr "პრინციპალი ნაგულისხმებ რეალმს არ ეკუთვნის" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:869 +#, c-format +msgid "" +"operation can not continue, more than one entry with principal name \"%s\" " +"found" +msgstr "" +"ოპერაციის გაგრძელება შეუძლებელია. ნაპოვნია პრინციპალის სახელის \"%s\" მქონე " +"ერთზე მეტი ჩანაწერი" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:928 +#, c-format +msgid "'%s' not found" +msgstr "'%s' არ არსებობს" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:992 +#, c-format +msgid "" +"link information can not be set/updated as the kerberos principal belongs to " +"an ldap object" +msgstr "" +"ბმულის ინფორმაციის დაყენება/განახლება შეუძლებელია, რადგან kerberos-ის " +"პრინციპალი ldap ობიექტს ეკუთვნის" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1007 +#, c-format +msgid "Failed getting object references" +msgstr "ობიექტის მიმართვის მიღების შეცდომა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1014 +#, c-format +msgid "kerberos principal is already linked to a ldap object" +msgstr "kerberos-ის პრინციპალი ldap ობიექტზე უკვე მიბმულია" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1340 +msgid "ticket policy object value: " +msgstr "ბილეტის პოლიტიკის ობიექტის მნიშვნელობა: " + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1388 +#, c-format +msgid "Principal delete failed (trying to replace entry): %s" +msgstr "პრინციპალის წაშლის შეცდომა (ჩანაწერის ჩანაცვლებისას): %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1398 +#, c-format +msgid "Principal add failed: %s" +msgstr "პრინციპალის დამატების შეცდომა: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1436 +#, c-format +msgid "User modification failed: %s" +msgstr "მომხმარებლის ცვლილების შეცდომა: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1510 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:294 +msgid "Error reading ticket policy" +msgstr "ბილეტის პოლიტიკის წაკითხვის შეცდომა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1640 +msgid "unable to decode stored principal key data" +msgstr "დამახსოვრებული პრინციპალის გასაღების მონაცემების გაშიფვრის შეცდომა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1698 +msgid "unable to decode stored principal pw history" +msgstr "დამახსოვრებული პრინციპალის პაროლის ისტორიის გაშიფვრის შეცდომა" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:223 +msgid "Realm information not available" +msgstr "რეალმის ინფორმაცია მიუწვდომელია" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:306 +#, c-format +msgid "Realm Delete FAILED: %s" +msgstr "რეალმის წაშლის შეცდომა: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:386 +msgid "subtree value: " +msgstr "ქვეხის მნიშვნელობა: " + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:403 +msgid "container reference value: " +msgstr "შემცველობის მითითების მნიშვნელობა: " + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:486 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:549 +msgid "Kerberos Container information is missing" +msgstr "Kerberos -ის კონტეიერის ინფორმაცია არ არსებობს" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:498 +msgid "Invalid Kerberos container DN" +msgstr "არასწორი Kerberos-ის შემცველი DN" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:514 +#, c-format +msgid "Kerberos Container create FAILED: %s" +msgstr "Kerberos-ის კონტეინერის შექმნის შეცდომა: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:557 +#, c-format +msgid "Kerberos Container delete FAILED: %s" +msgstr "Kerberos-ის კონტეინერის წაშლის შეცდომა: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:633 +msgid "realm object value: " +msgstr "რეალმის ობიექტის მნიშვნელობა: " + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:48 +msgid "Not a hexadecimal password" +msgstr "თექვსმეტობით პაროლს არ წარმოადგენს" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:55 +msgid "Password corrupt" +msgstr "პაროლი დაზიანებულია" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:78 +#, c-format +msgid "Cannot open LDAP password file '%s': %s" +msgstr "შეცდომა LDAP-ის პაროლის ფაილის ('%s') გახსნისას: %s" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:108 +#, c-format +msgid "Bind DN entry '%s' missing in LDAP password file '%s'" +msgstr "მისაბმელი DN-ის ჩანაწერი '%s' LDAP პაროლებს ფაილში '%s' ვერ ვიპოვე" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:66 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:142 +msgid "Ticket Policy Name missing" +msgstr "აკლია ბილეთის პოლიტიკის სახელი" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:154 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:231 +msgid "ticket policy object: " +msgstr "ბილეთის პოლიტიკის ობიექტი: " + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:219 +msgid "Ticket Policy Object information missing" +msgstr "აკლია ბილეთის პოლიტიკის ობიექტის ინფორმაცია" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:311 +msgid "Ticket Policy Object DN missing" +msgstr "აკლია ბილეთის პოლიტიკის ობიექტის DN" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:338 +msgid "Delete Failed: One or more Principals associated with the Ticket Policy" +msgstr "" +"წაშლის შეცდომა: ბილეთის პოლიტიკასთან ერთი ან მეტი პრინციპალია ასოცირებული" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:447 +msgid "Error reading container object" +msgstr "შემცველი ობიექტის გახსნის შეცდომა" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:132 +#, c-format +msgid "%s (path: %s): %s" +msgstr "%s (ბილიკი: %s): %s" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:164 +#, c-format +msgid "Unsupported argument \"%s\" for LMDB" +msgstr "LMDB-ის მხარდაუჭერელი არგუმენტი '%s'" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:294 +msgid "LMDB environment open failure" +msgstr "LMDB გარემოს გახსნის შეცდომა" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:319 +msgid "LMDB read failure" +msgstr "LMDB გახსნის შეცდომა" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:394 +msgid "LMDB write failure" +msgstr "LMDB ჩაწერის შეცდომა" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:418 +msgid "LMDB delete failure" +msgstr "LMDB წაშლის შეცდომა" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:521 +#, c-format +msgid "LMDB file %s does not exist" +msgstr "LMDB ფაილი %s არ არსებობს" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:566 +msgid "LMDB open failure" +msgstr "LMDB გახსნის შეცდომა" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:593 +#, c-format +msgid "LMDB file %s already exists" +msgstr "LMDB ფაილი %s უკვე არსებობს" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:658 +msgid "LMDB create error" +msgstr "LMDB შექმნის შეცდომა" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:676 +#, c-format +msgid "Could not unlink %s" +msgstr "ბმის %s მოხსნის შეცდომა" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:760 +#, c-format +msgid "Unsupported argument \"%s\" for lmdb" +msgstr "მხარდაუჭერელი არგუმენტი \"%s\" lmdb-სთვის" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:806 +msgid "LMDB lockout write failure" +msgstr "LMDB-ის ბლოკის ჩაწერის შეცდომა" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:882 +msgid "LMDB principal iteration failure" +msgstr "LMDB პრინციპალის იტერაციის შეცდომა" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:985 +msgid "LMDB policy iteration failure" +msgstr "LMDB პოლიტიკის იტერაციის შეცდომა" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:1016 +msgid "LMDB transaction commit failure" +msgstr "LMDB ტრანზაქციის გადაცემის შეცდომა" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:1115 +msgid "LMDB lockout update failure" +msgstr "LMDB -ის ბლოკის განახლების შეცდომა" + +#: ../../src/plugins/preauth/pkinit/pkinit_clnt.c:1088 +msgid "No pkinit_anchors supplied" +msgstr "\"pkinit_anchors\" მითითებული არაა" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:957 +#, c-format +msgid "%s: %s" +msgstr "%s: %s" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:987 +#, c-format +msgid "%s (depth %d): %s" +msgstr "%s (სიღრმე %d): %s" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1230 +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:4180 +msgid "Pass phrase for" +msgstr "საკვანძო ფრაზა" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1516 +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1526 +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1784 +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1794 +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2271 +msgid "Failed to DER encode PKCS7" +msgstr "PKCS7-ის DER-ით დაშიფვრის შეცდომა" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1617 +msgid "Failed to verify own certificate" +msgstr "საკუთარი სერტიფიკატის გადამოწმების შეცდომა" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1768 +msgid "Failed to add digest attribute" +msgstr "დაიჯესტის ატრიბუტის დამატების შეცდომა" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1890 +msgid "Failed to decode CMS message" +msgstr "შეცდომა CMS-შეტყობინების დეკოდირებისას" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1908 +msgid "Invalid pkinit packet: octet string expected" +msgstr "არასწორი pkinit პაკეტი: მოველოდი ოქტეტ სტრიქონს" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1926 +msgid "wrong oid\n" +msgstr "არასწორი oid\n" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2078 +msgid "Failed to verify received certificate" +msgstr "მიღებული სერტიფიკატის გადამოწმება შეუძლებელია" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2114 +msgid "Failed to verify CMS message" +msgstr "CMS შეტყობინების გადამოწმება შეუძლებელია" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2259 +msgid "Failed to encrypt PKCS7 object" +msgstr "PKCS7 ობიექტის დაშიფვრის შეცდომა" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2317 +msgid "Failed to decode PKCS7" +msgstr "PKCS7-ის გაშიფვრის შეცდომა" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2333 +msgid "Failed to decrypt PKCS7 message" +msgstr "PKCS7 შეტყობინების გაშიფვრის შეცდომა" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2756 +msgid "Failed to fetch SSKDF" +msgstr "SSKDF-ის გამოთხოვის შეცდომა" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2763 +msgid "Failed to instantiate SSKDF" +msgstr "SSKDF-ის კონკრეტული მაგალითის მოყვანის შეცდომა" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2776 +msgid "Failed to derive key using SSKDF" +msgstr "შეცდომა SSKDF-ის საშუალებით გასაღების მიღებისას" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2838 +msgid "Failed to compute digest" +msgstr "დაიჯესტის გამოთვლის შეცდომა" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:4300 +#, c-format +msgid "Cannot read certificate file '%s'" +msgstr "სერტიფიკატის ფაილის წაკითხვის შეცდომა \"%s\"" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:4308 +#, c-format +msgid "Cannot read key file '%s'" +msgstr "გასაღების ფაილის წაკითხვის შეცდომა \"%s\"" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:5165 +#, c-format +msgid "Cannot open file '%s'" +msgstr "ფაილის გახსნის შეცდომა: %s" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:5172 +#, c-format +msgid "Cannot read file '%s'" +msgstr "ფაილის წაკითხვის შეცდომა \"%s\"" + +#: ../../src/plugins/preauth/pkinit/pkinit_identity.c:415 +#, c-format +msgid "Unsupported type while processing '%s'\n" +msgstr "არასწორი ტიპი '%s'-ის დამუშავებისას\n" + +#: ../../src/plugins/preauth/pkinit/pkinit_identity.c:451 +msgid "Internal error parsing X509_user_identity\n" +msgstr "შიდა შეცდომა X509_user_identity-ის დამუშავებისას\n" + +#: ../../src/plugins/preauth/pkinit/pkinit_identity.c:552 +msgid "No user identity options specified" +msgstr "მომხმარებლის იდენტიფიკაციის პარამეტრები მითითებული არაა" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:403 +#, c-format +msgid "PKINIT: no freshness token, rejecting auth from %s" +msgstr "PKINIT: კოდი მოძველებულია. ავთენტიკაცია %s -დან უარყოფილია" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:407 +#, c-format +msgid "PKINIT: freshness token received from %s" +msgstr "PKINIT: ახალი კოდი მიღებულია წყაროდან: %s" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:409 +#, c-format +msgid "PKINIT: no freshness token received from %s" +msgstr "PKINIT: %s-დან ახალი კოდი მიღებული არაა" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:512 +msgid "Pkinit request not signed, but client not anonymous." +msgstr "Pkinit მოთხოვნა ხელმოწერილი არაა, მაგრამ კლიენტი ანონიმური არაა." + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:546 +msgid "Anonymous pkinit without DH public value not supported." +msgstr "ანონიმური pkinit-ი DH-ის საჯარო მნიშვნელობის გარეშე მხარდაუჭერელია." + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1083 +#, c-format +msgid "No pkinit_identity supplied for realm %s" +msgstr "\"pkinit_identity\" რეალმისთვის %s მითითებული არაა" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1094 +#, c-format +msgid "No pkinit_anchors supplied for realm %s" +msgstr "\"pkinit_anchors\" რეალმისთვის %s მითითებული არაა" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1114 +#, c-format +msgid "OCSP is not supported: (realm: %s)" +msgstr "OCSP მხარდაუჭერელია: (რეალმი: %s)" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1515 +msgid "No realms configured correctly for pkinit support" +msgstr "" +"\"pkinit\"-ის მხარდაჭერისთვის სწორად მორგებული რეალმები აღმოჩენილი არაა" + +#: ../../src/plugins/preauth/spake/groups.c:237 +msgid "No SPAKE preauth groups configured" +msgstr "SPAKE პრეავთენტიკაციის ჯგუფები მითითებული არაა" + +#: ../../src/plugins/preauth/spake/groups.c:257 +#, c-format +msgid "SPAKE challenge group not a permitted group: %s" +msgstr "SPAKE გამოწვევის ჯგუფი ნებადართულ ჯგუფს არ წარმოადგენს: %s" + +#: ../../src/plugins/preauth/spake/spake_kdc.c:533 +msgid "Unknown SPAKE request type" +msgstr "SPAKE-ის მოთხოვნის უცნობი ტიპი" + +#: ../../src/util/support/errors.c:77 +msgid "Kerberos library initialization failure" +msgstr "Kerberos -ის ბიბლიოთეკის ინიციალიზაციის შეცდომა" + +#: ../../src/util/support/errors.c:83 +msgid "Error code translation unavailable" +msgstr "შეცდომის კოდის თარგმანი მიუწვდომელია" + +#: ../../src/util/support/errors.c:92 +#, c-format +msgid "error %ld" +msgstr "შეცდომა %ld" + +#: ../../src/util/support/plugins.c:200 +#, c-format +msgid "unable to find plugin [%s]: %s" +msgstr "დამატების პოვნის შეცდომა [%s]: %s" + +#: ../../src/util/support/plugins.c:288 +msgid "unknown failure" +msgstr "უცნობი შეცდომა" + +#: ../../src/util/support/plugins.c:291 +#, c-format +msgid "unable to load plugin [%s]: %s" +msgstr "დამატების ჩატვირთვის შეცდომა [%s]: %s" + +#: ../../src/util/support/plugins.c:314 +#, c-format +msgid "unable to load DLL [%s]" +msgstr "dll-ის ჩატვირთვის შეცდომა [%s]" + +#: ../../src/util/support/plugins.c:330 +#, c-format +msgid "plugin unavailable: %s" +msgstr "დამატება ხელმიუწვდომელია: %s" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:23 +msgid "No @ in SERVICE-NAME name string" +msgstr "SERVICE-NAME სახელი-სტრიქონში @ არ არსებობს" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:24 +msgid "STRING-UID-NAME contains nondigits" +msgstr "STRING-UID-NAME არაციფრულ მონაცემებს შეიცავს" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:25 +msgid "UID does not resolve to username" +msgstr "UID-ი მომხმარებლის სახელში არ ითარგმნება" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:26 +msgid "Validation error" +msgstr "შემოწმების შეცდომა" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:27 +msgid "Couldn't allocate gss_buffer_t data" +msgstr "შეცდომა gss_buffer_t-ის მონაცემების გამოყოფისას" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:28 +msgid "Message context invalid" +msgstr "შეტყობინების კონტექსტი არასწორია" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:29 +msgid "Buffer is the wrong size" +msgstr "ბუფერს არასწორი ზომა" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:30 +msgid "Credential usage type is unknown" +msgstr "ავტორიზაციის დეტალების გამოყენების ტიპი უცნობია" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:31 +msgid "Unknown quality of protection specified" +msgstr "მითითებულია დაცვის ხარისხი უცნობია" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:32 +msgid "Local host name could not be determined" +msgstr "ლოკალური ჰოსტის სახელის დადგენა შეუძლებელია" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:33 +msgid "Hostname in SERVICE-NAME string could not be canonicalized" +msgstr "SERVICE-NAME სტრიქონში ჰოსტის სახელის კანონიკალიზება შეუძლებელია" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:34 +msgid "Mechanism is incorrect" +msgstr "მექანიზმი არასწორია" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:35 +msgid "Token header is malformed or corrupt" +msgstr "კოდის თავსართი არასწორი ან დაზიანებულია" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:36 +msgid "Packet was replayed in wrong direction" +msgstr "პაკეტის გადაცემის მისამართი არასწორია" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:37 +msgid "Token is missing data" +msgstr "კოდს მონაცემები აკლია" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:38 +msgid "Token was reflected" +msgstr "კოდი აირეკლა" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:39 +msgid "Received token ID does not match expected token ID" +msgstr "მიღებული კოდის ID მოსალოდნელი კოდის ID-ს არ ემთხვევა" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:40 +msgid "The given credential's usage does not match the requested usage" +msgstr "" +"მითითებული ავტორიზაციის დეტალების გამოყენება მოთხოვნილ გამოყენებას არ " +"ემთხვევა" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:41 +msgid "Storing of acceptor credentials is not supported by the mechanism" +msgstr "" +"აქსეპტორის ავტორიზაციის დეტალების დამახსოვრება მექანიზმის მიერ მხარდაჭერილი " +"არაა" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:42 +msgid "Storing of non-default credentials is not supported by the mechanism" +msgstr "" +"არანაგულისხმები ავტორიზაციის დეტალების დამახსოვრება მექანიზმის მიერ " +"მხარდაჭერილი არაა" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:23 +msgid "Principal in credential cache does not match desired name" +msgstr "" +"ავტორიზაციის დეტალების ქეშში არსებული პრინციპალი სასურველ სახელს არ ემთხვევა" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:24 +msgid "No principal in keytab matches desired name" +msgstr "Keytab-ში არც ერთი პრინციპალი სასურველ სახელს არ ემთხვევა" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:25 +msgid "Credential cache has no TGT" +msgstr "ავტორიზაციის დეტალების ქეშს TGT არ გააჩნია" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:26 +msgid "Authenticator has no subkey" +msgstr "ავთენტიკატორს ქვეგასაღები არ გააჩნია" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:27 +msgid "Context is already fully established" +msgstr "კონტექსტი უკვე სრულად აწყობილია" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:28 +msgid "Unknown signature type in token" +msgstr "კოდში არსებული ხელმოწერის ტიპი უცნობია" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:29 +msgid "Invalid field length in token" +msgstr "კოდში ველის არასწორი სიგრძე" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:30 +msgid "Attempt to use incomplete security context" +msgstr "არასრული უსაფრთხოების კონტექსტის გამოყენების მცდელობა" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:31 +msgid "Bad magic number for krb5_gss_ctx_id_t" +msgstr "არასწორი ჯადოსნური რიცხვი krb5_gss_ctx_id_t-სთვის" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:32 +msgid "Bad magic number for krb5_gss_cred_id_t" +msgstr "არასწორი ჯადოსნური რიცხვი krb5_gss_cred_id_t-სთვის" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:33 +msgid "Bad magic number for krb5_gss_enc_desc" +msgstr "არასწორი ჯადოსნური რიცხვი krb5_gss_enc_desc-სთვის" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:34 +msgid "Sequence number in token is corrupt" +msgstr "კოდში მიმდევრობის ნომერი არასწორია" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:35 +msgid "Credential cache is empty" +msgstr "ავტორიზაციის დეტალების ქეში ცარიელია" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:36 +msgid "Acceptor and Initiator share no checksum types" +msgstr "აქცეპტანტის და ინიციატორის საკონტროლო ჯამის ტიპები განსხვავდება" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:37 +msgid "Requested lucid context version not supported" +msgstr "მოთხოვნილი lucid-ის კონტექსტის ვერსია მხარდაუჭერელია" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:38 +msgid "PRF input too long" +msgstr "PRF შეყვანა ძალიან გრძელია" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:39 +msgid "Bad magic number for iakerb_ctx_id_t" +msgstr "არასწორი ჯადოსნური რიცხვი iakerb_ctx_id_t -სთვის" + +#: ../lib/kadm5/chpass_util_strings.c:23 +msgid "while getting policy info." +msgstr "პოლიტიკის ინფორმაციის მიღებისას." + +#: ../lib/kadm5/chpass_util_strings.c:24 +msgid "while getting principal info." +msgstr "პრინციპალის ინფორმაციის მიღებისას." + +#: ../lib/kadm5/chpass_util_strings.c:25 +msgid "New passwords do not match - password not changed.\n" +msgstr "ახალი პაროლები არ ემთხვევა - პაროლი არ შეცვლილა.\n" + +#: ../lib/kadm5/chpass_util_strings.c:26 +msgid "New password" +msgstr "ახალი პაროლი" + +#: ../lib/kadm5/chpass_util_strings.c:27 +msgid "New password (again)" +msgstr "ახალი პაროლი(თავიდან)" + +#: ../lib/kadm5/chpass_util_strings.c:28 +msgid "" +"You must type a password. Passwords must be at least one character long.\n" +msgstr "" +"პაროლის აკრეფა აუცილებელია. პაროლი მინიმუმ ერთი სიმბოლოს სიგრძის უნდა იყოს.\n" + +#: ../lib/kadm5/chpass_util_strings.c:29 +msgid "yet no policy set! Contact your system security administrator." +msgstr "" +"პოლიტიკა ჯერ დაყენებული არაა! დაუკავშირდით თქვენი სისტემის უსაფრთხოების " +"ადმინისტრატორს." + +#: ../lib/kadm5/chpass_util_strings.c:31 +msgid "" +"New password was found in a dictionary of possible passwords and\n" +"therefore may be easily guessed. Please choose another password.\n" +"See the kpasswd man page for help in choosing a good password." +msgstr "" +"ახალი პაროლი შესაძლო პაროლების ლექსიკონშია აღმოჩენილი და\n" +"ამიტომ შეიძლება ადვილად გაარტყან. აირჩიეთ სხვა პაროლი.\n" +"კარგი პაროლის შედგენაში დასახმარებლად იხილეთ kpasswd-ის man გვერდი." + +#: ../lib/kadm5/chpass_util_strings.c:32 +msgid "Password not changed." +msgstr "პაროლი არ შეცვლილა." + +#: ../lib/kadm5/chpass_util_strings.c:33 +#, c-format +msgid "" +"New password is too short.\n" +"Please choose a password which is at least %d characters long." +msgstr "" +"ახალი პაროლი მეტისმეტად მოკლეა.\n" +"გთხოვთ, აირჩიოთ პაროლი, რომელიც სულ ცოტა %d სიმბოლოს შეიცავს." + +#: ../lib/kadm5/chpass_util_strings.c:34 +#, c-format +msgid "" +"New password does not have enough character classes.\n" +"The character classes are:\n" +"\t- lower-case letters,\n" +"\t- upper-case letters,\n" +"\t- digits,\n" +"\t- punctuation, and\n" +"\t- all other characters (e.g., control characters).\n" +"Please choose a password with at least %d character classes." +msgstr "" +"ახალ პაროლს სიმბოლოს საკმარისი კლასები არ გააჩნია.\n" +"სიმბოლოს კლასებია:\n" +"\t- დაბალი რეგისტრის სიმბოლოები (პატარა ასოები),\n" +"\t- მაღალი რეგისტრის სიმბოლოები (დიდი ასოები),\n" +"\t- ციფრები,\n" +"\t- პუნქტუაციის ნიშნები და\n" +"\t- სხვა ყველა სიმბოლო (მაგ: კონტროლის სიმბოლოები).\n" +"შეიყვანეთ პაროლი, რომელიც, ყველაზე ცოტა, %d სიმბოლოს კლასს შეიცავს." + +#: ../lib/kadm5/chpass_util_strings.c:35 +#, c-format +msgid "" +"Password cannot be changed because it was changed too recently.\n" +"Please wait until %s before you change it.\n" +"If you need to change your password before then, contact your system\n" +"security administrator." +msgstr "" +"პაროლს ვერ შეცვლით, რადგან ის სულ ცოტა ხნის წინ შეიცვალა.\n" +"მოითმინეთ %s-მდე, სანამ მისი შეცვლის უფლება გექნებათ.\n" +"თუ გჭირდებათ, რომ პაროლი მითითებულ თარიღამდე შეცვალოთ,\n" +"თქვენს უსაფრთხოების ადმინისტრატორს დაუკავშირდით." + +#: ../lib/kadm5/chpass_util_strings.c:36 +msgid "New password was used previously. Please choose a different password." +msgstr "ახალი პაროლი უკვე იყო გამოყენებული. აირჩიეთ სხვა პაროლი." + +#: ../lib/kadm5/chpass_util_strings.c:37 +msgid "while trying to change password." +msgstr "პაროლის შეცვლის მცდელობისას." + +#: ../lib/kadm5/chpass_util_strings.c:38 +msgid "while reading new password." +msgstr "ახალი პაროლის წაკითხვისას." + +#: ../lib/kadm5/kadm_err.c:23 +msgid "Operation failed for unspecified reason" +msgstr "ოპერაცია მიუთითებელი მიზეზით ავარიულად დასრულდა" + +#: ../lib/kadm5/kadm_err.c:24 +msgid "Operation requires ``get'' privilege" +msgstr "ოპერაციას \"get\" პრივილეგია ესაჭიროება" + +#: ../lib/kadm5/kadm_err.c:25 +msgid "Operation requires ``add'' privilege" +msgstr "ოპერაციას \"add\" პრივილეგია ესაჭიროება" + +#: ../lib/kadm5/kadm_err.c:26 +msgid "Operation requires ``modify'' privilege" +msgstr "ოპერაციას \"modify\" პრივილეგია ესაჭიროება" + +#: ../lib/kadm5/kadm_err.c:27 +msgid "Operation requires ``delete'' privilege" +msgstr "ოპერაციას \"delete\" პრივილეგია ესაჭიროება" + +#: ../lib/kadm5/kadm_err.c:28 +msgid "Insufficient authorization for operation" +msgstr "ოპერაციისთვის არასაკმარისი ავტორიზაცია" + +#: ../lib/kadm5/kadm_err.c:29 ../lib/kdb/adb_err.c:29 +msgid "Database inconsistency detected" +msgstr "აღმოჩენილია ბაზის არამდგრადობა" + +#: ../lib/kadm5/kadm_err.c:30 ../lib/kdb/adb_err.c:24 +msgid "Principal or policy already exists" +msgstr "პრინციპალი ან პოლიტიკა უკვე არსებობს" + +#: ../lib/kadm5/kadm_err.c:31 +msgid "Communication failure with server" +msgstr "სერვერთან ურთიერთობის შეცდომა" + +#: ../lib/kadm5/kadm_err.c:32 +msgid "No administration server found for realm" +msgstr "რეალმისთვის ადმინისტრირების სერვერი ვერ ვიპოვე" + +#: ../lib/kadm5/kadm_err.c:33 +msgid "Password history principal key version mismatch" +msgstr "პაროლის ისტორიის პრინციპალის გასაღების ვერსია არ ემთხვევა" + +#: ../lib/kadm5/kadm_err.c:34 +msgid "Connection to server not initialized" +msgstr "სერვერთან მიერთება ინიციალიზებული არაა" + +#: ../lib/kadm5/kadm_err.c:35 +msgid "Principal does not exist" +msgstr "პრინციპალი არ არსებობს" + +#: ../lib/kadm5/kadm_err.c:36 +msgid "Policy does not exist" +msgstr "პოლიტიკა არ არსებობს" + +#: ../lib/kadm5/kadm_err.c:37 +msgid "Invalid field mask for operation" +msgstr "ველის ნიღაბი ოპერაციისთვის არასწორია" + +#: ../lib/kadm5/kadm_err.c:38 +msgid "Invalid number of character classes" +msgstr "სიმბოლოს კლასების არასწორი რაოდენობა" + +#: ../lib/kadm5/kadm_err.c:39 +msgid "Invalid password length" +msgstr "არასწორი პაროლის სიგრძე" + +#: ../lib/kadm5/kadm_err.c:40 +msgid "Illegal policy name" +msgstr "პოლიტიკის დაუშვებელი სახელი" + +#: ../lib/kadm5/kadm_err.c:41 +msgid "Illegal principal name" +msgstr "პრინციპალის დაუშვებელი სახელი" + +#: ../lib/kadm5/kadm_err.c:42 +msgid "Invalid auxiliary attributes" +msgstr "არასწორი დამხმარე ატრიბუტები" + +#: ../lib/kadm5/kadm_err.c:43 +msgid "Invalid password history count" +msgstr "არასწორი პაროლის ისტორიის რაოდენობა" + +#: ../lib/kadm5/kadm_err.c:44 +msgid "Password minimum life is greater than password maximum life" +msgstr "პაროლის მინიმალური სიცოცხლე მაქსიმალურ სიცოცხლეზე დიდია" + +#: ../lib/kadm5/kadm_err.c:45 +msgid "Password is too short" +msgstr "პაროლი ძალიან მოკლეა" + +#: ../lib/kadm5/kadm_err.c:46 +msgid "Password does not contain enough character classes" +msgstr "პაროლი სიმბოლოების საკმარის კლასებს არ შეიცავს" + +#: ../lib/kadm5/kadm_err.c:47 +msgid "Password is in the password dictionary" +msgstr "პაროლი პაროლების ლექსიკონშია" + +#: ../lib/kadm5/kadm_err.c:48 +msgid "Cannot reuse password" +msgstr "პაროლს თავიდან ვერ გამოიყენებთ" + +#: ../lib/kadm5/kadm_err.c:49 +msgid "Current password's minimum life has not expired" +msgstr "მიმდინარე პაროლის სიცოცხლის მინიმალური ვადა არ ამოწურულა" + +#: ../lib/kadm5/kadm_err.c:50 ../lib/krb5/error_tables/kdb5_err.c:67 +msgid "Policy is in use" +msgstr "პოლიტიკა უკვე გამოიყენება" + +#: ../lib/kadm5/kadm_err.c:51 +msgid "Connection to server already initialized" +msgstr "სერვერამდე მიერთება უკვე ინიციალიზებულია" + +#: ../lib/kadm5/kadm_err.c:52 +msgid "Incorrect password" +msgstr "არასწორი პაროლი" + +#: ../lib/kadm5/kadm_err.c:53 +msgid "Cannot change protected principal" +msgstr "დაცული პრინციპალის შეცვლა შეუძლებელია" + +#: ../lib/kadm5/kadm_err.c:54 +msgid "Programmer error! Bad Admin server handle" +msgstr "პროგრამისტის შეცდომა! ადმინისტრირების სერვერის დამმუშავებელი არასწორია" + +#: ../lib/kadm5/kadm_err.c:55 +msgid "Programmer error! Bad API structure version" +msgstr "პროგრამისტის შეცდომა! API-ის სტრუქტურის ვერსია არასწორია" + +#: ../lib/kadm5/kadm_err.c:56 +msgid "" +"API structure version specified by application is no longer supported (to " +"fix, recompile application against current KADM5 API header files and " +"libraries)" +msgstr "" +"API-ის სტრუქტურის ვერსია, რომელიც აპლიკაციას სჭირდება, მხარდაჭერილი აღარაა " +"(პრობლემის გამოსასწორებლად საჭიროა აპლიკაციის თავიდან აგება მიმდინარე KADM5 " +"API-ის თავსართის ფაილებისა და ბიბლიოთეკების გამოყენებით.)" + +#: ../lib/kadm5/kadm_err.c:57 +msgid "" +"API structure version specified by application is unknown to libraries (to " +"fix, obtain current KADM5 API header files and libraries and recompile " +"application)" +msgstr "" +"API-ის სტრუქტურის ვერსია, რომელიც აპლიკაციას სჭირდება, უცნობია (პრობლემის " +"გამოსასწორებლად საჭიროა აპლიკაციის თავიდან აგება მიმდინარე KADM5 API-ის " +"თავსართის ფაილებისა და ბიბლიოთეკების გამოყენებით.)" + +#: ../lib/kadm5/kadm_err.c:58 +msgid "Programmer error! Bad API version" +msgstr "პროგრამისტის შეცდომა! API-ის ვერსია არასწორია" + +#: ../lib/kadm5/kadm_err.c:59 +msgid "" +"API version specified by application is no longer supported by libraries (to " +"fix, update application to adhere to current API version and recompile)" +msgstr "" +"API-ის ვერსია, რომელიც აპლიკაციას სჭირდება, მხარდაჭერილი აღარაა (პრობლემის " +"გამოსასწორებლად საჭიროა აპლიკაციის თავიდან აგება მიმდინარე KADM5 API-ის " +"თავსართის ფაილებისა და ბიბლიოთეკების გამოყენებით.)" + +#: ../lib/kadm5/kadm_err.c:60 +msgid "" +"API version specified by application is no longer supported by server (to " +"fix, update application to adhere to current API version and recompile)" +msgstr "" +"API-ის ვერსია, რომელიც აპლიკაციას სჭირდება, სერვერის მიერ მხარდაჭერილი " +"აღარაა (პრობლემის გამოსასწორებლად აპლიკაციის განახლება, რომ მიმდინარე KADM5 " +"API-ის თავსართის ფაილებისა და ბიბლიოთეკების იყენებდეს და აპლიკაციის თავიდან " +"კომპილაციაა საჭირო)" + +#: ../lib/kadm5/kadm_err.c:61 +msgid "" +"API version specified by application is unknown to libraries (to fix, obtain " +"current KADM5 API header files and libraries and recompile application)" +msgstr "" +"API-ის ვერსია, რომელიც აპლიკაციას სჭირდება, უცნობია. (პრობლემის " +"გამოსასწორებლად გადმოწერეთ მიმდინარე KADM5 API-ის თავსართის ფაილები და " +"ბიბლიოთეკები და აპლიკაცია თავიდან დააკომპილეთ)" + +#: ../lib/kadm5/kadm_err.c:62 +msgid "" +"API version specified by application is unknown to server (to fix, obtain " +"and install newest KADM5 Admin Server)" +msgstr "" +"API-ს ვერსია, რომელიც აპლიკაციას სჭირდება, სერვერისთვის უცნობია (პრობლემის " +"გამოსასწორებლად KADM5 ადმინ სერვერის უახლესი ვერსიის დაყენებაა საჭირო)" + +#: ../lib/kadm5/kadm_err.c:63 +msgid "Database error! Required KADM5 principal missing" +msgstr "ბაზის შეცდომა! აუცილებელი KADM5 პრინციპალი არ არსებობს" + +#: ../lib/kadm5/kadm_err.c:64 +msgid "The salt type of the specified principal does not support renaming" +msgstr "" +"მითითებული პრინციპალის მარილის ტიპს სახელის გადარქმევის მხარდაჭერა არ გააჩნია" + +#: ../lib/kadm5/kadm_err.c:65 +msgid "Illegal configuration parameter for remote KADM5 client" +msgstr "არასწორი კონფიგურაციის პარამეტრი დაშორებული KADM5 კლიენტისთვის" + +#: ../lib/kadm5/kadm_err.c:66 +msgid "Illegal configuration parameter for local KADM5 client" +msgstr "არასწორი კონფიგურაციის პარამეტრი ლოკალური KADM5 კლიენტისთვის" + +#: ../lib/kadm5/kadm_err.c:67 +msgid "Operation requires ``list'' privilege" +msgstr "ოპერაციას \"list\" პრივილეგია ესაჭიროება" + +#: ../lib/kadm5/kadm_err.c:68 +msgid "Operation requires ``change-password'' privilege" +msgstr "ოპერაციას \"change-password\" პრივილეგია ესაჭიროება" + +#: ../lib/kadm5/kadm_err.c:69 +msgid "GSS-API (or Kerberos) error" +msgstr "GSS-API-ის (ან Kerberos-ის) შეცდომა" + +#: ../lib/kadm5/kadm_err.c:70 +msgid "Programmer error! Illegal tagged data list type" +msgstr "პროგრამისტის შეცდომა! ჭდის მქონე მონაცემების სიის ტიპი არასწორია" + +#: ../lib/kadm5/kadm_err.c:71 +msgid "Required parameters in kdc.conf missing" +msgstr "შეცდომა kdc.conf-ში საჭირო პარამეტრების ძებნისას" + +#: ../lib/kadm5/kadm_err.c:72 +msgid "Bad krb5 admin server hostname" +msgstr "Krb5-ის ადმინისტრირების სერვერის არასწორი ჰოსტის სახელი" + +#: ../lib/kadm5/kadm_err.c:73 +msgid "Operation requires ``set-key'' privilege" +msgstr "ოპერაციას \"set-key\" პრივილეგია ესაჭიროება" + +#: ../lib/kadm5/kadm_err.c:74 +msgid "Multiple values for single or folded enctype" +msgstr "ერთი ან დაკეცილი enctype-ის მრავალი მნიშვნელობა" + +#: ../lib/kadm5/kadm_err.c:75 +msgid "Invalid enctype for setv4key" +msgstr "Setv4key-ის არასწორი enctype" + +#: ../lib/kadm5/kadm_err.c:76 +msgid "Mismatched enctypes for setkey3" +msgstr "Setkey3-თვის შეუთავსებელი enctype-ები" + +#: ../lib/kadm5/kadm_err.c:77 +msgid "Missing parameters in krb5.conf required for kadmin client" +msgstr "Krb5.conf-ში kadmin-ის კლიენტისთვის აუცილებელი პარამეტრები არ არსებობს" + +#: ../lib/kadm5/kadm_err.c:78 ../lib/kdb/adb_err.c:30 +msgid "XDR encoding error" +msgstr "XDR კოდირების შეცდომა" + +#: ../lib/kadm5/kadm_err.c:79 +msgid "Cannot resolve network address for admin server in requested realm" +msgstr "" +"მოთხოვნის რეალმში ადმინის სერვერისთვის ქსელის მისამართის ამოხსნის შეცდომა" + +#: ../lib/kadm5/kadm_err.c:80 +msgid "Unspecified password quality failure" +msgstr "პაროლის ხარისხის მიუთითებელი შეცდომა" + +#: ../lib/kadm5/kadm_err.c:81 +msgid "Invalid key/salt tuples" +msgstr "არასწორი გასაღები/მარილის კორტეჟები" + +#: ../lib/kadm5/kadm_err.c:82 +msgid "Invalid multiple or duplicate kvnos in setkey operation" +msgstr "Setkey ოპერაციაში არასწორი მრავალი ან დუბლირებული ოპერაციაა აღმოჩენილი" + +#: ../lib/kadm5/kadm_err.c:83 +msgid "Operation requires ``extract-keys'' privilege" +msgstr "ოპერაციას \"extract-keys\" პრივილეგია ესაჭიროება" + +#: ../lib/kadm5/kadm_err.c:84 +msgid "Principal keys are locked down" +msgstr "პრინციპალის გასაღებები დაბლოკილია" + +#: ../lib/kadm5/kadm_err.c:85 +msgid "Operation requires initial ticket" +msgstr "ოპერაციას საწყისი გასაღები ესაჭიროება" + +#: ../lib/kdb/adb_err.c:23 +msgid "No Error" +msgstr "შეცდომის გარეშე" + +#: ../lib/kdb/adb_err.c:25 +msgid "Principal or policy does not exist" +msgstr "პოლიტიკა ან პრინციპალი არ არსებობს" + +#: ../lib/kdb/adb_err.c:26 +msgid "Database not initialized" +msgstr "ბაზა ინიციალიზებული არაა" + +#: ../lib/kdb/adb_err.c:27 +msgid "Invalid policy name" +msgstr "პოლიტიკის დაუშვებელი სახელი" + +#: ../lib/kdb/adb_err.c:28 +msgid "Invalid principal name" +msgstr "პრინციპალის დაუშვებელი სახელი" + +#: ../lib/kdb/adb_err.c:31 +msgid "Failure!" +msgstr "შეცდომა!" + +#: ../lib/kdb/adb_err.c:32 +msgid "Bad lock mode" +msgstr "დაბლოკვის არასწორი რეჟიმი" + +#: ../lib/kdb/adb_err.c:33 +msgid "Cannot lock database" +msgstr "ბაზის დაბლოკვა შეუძლებელია" + +#: ../lib/kdb/adb_err.c:34 +msgid "Database not locked" +msgstr "ბაზა დაბლოკილი არაა" + +#: ../lib/kdb/adb_err.c:35 +msgid "KADM5 administration database lock file missing" +msgstr "KADM5 ადმინისტრირების ბაზის ბლოკის ფაილი ვერ ვიპოვე" + +#: ../lib/kdb/adb_err.c:36 +msgid "Insufficient permission to lock file" +msgstr "თქვენი წვდომები ფაილის დასაბლოკად საკმარისი არაა" + +#: ../lib/krb5/error_tables/k5e1_err.c:23 +msgid "Plugin does not support interface version" +msgstr "დამატებას ინტერფეისის ვერსიის მხარდაჭერა არ გააჩნია" + +#: ../lib/krb5/error_tables/k5e1_err.c:24 +msgid "Invalid module specifier" +msgstr "მოდულის არასწორი მიმთითებელი" + +#: ../lib/krb5/error_tables/k5e1_err.c:25 +msgid "Plugin module name not found" +msgstr "დამატების მოდულის სახელი ვერ ვიპოვე" + +#: ../lib/krb5/error_tables/k5e1_err.c:26 +msgid "The KDC should discard this request" +msgstr "KDC-ს უნდა მოეცილებინა ეს მოთხოვნა" + +#: ../lib/krb5/error_tables/k5e1_err.c:27 +msgid "Can't create new subsidiary cache" +msgstr "დამხმარე ქეშის შექმნის შეცდომა" + +#: ../lib/krb5/error_tables/k5e1_err.c:28 +msgid "Invalid keyring anchor name" +msgstr "არასწორი ბრელოკის სამაგრის სახელი" + +#: ../lib/krb5/error_tables/k5e1_err.c:29 +msgid "Unknown keyring collection version" +msgstr "ბრელოკის კოლექციის უცნობი ვერსია" + +#: ../lib/krb5/error_tables/k5e1_err.c:30 +msgid "Invalid UID in persistent keyring name" +msgstr "არასწორი UID-ი მუდმივი ბრელოკის სახელში" + +#: ../lib/krb5/error_tables/k5e1_err.c:31 +msgid "Malformed reply from KCM daemon" +msgstr "KCM დემონის არასწორად ჩამოყალიბებული პასუხი" + +#: ../lib/krb5/error_tables/k5e1_err.c:32 +msgid "Mach RPC error communicating with KCM daemon" +msgstr "Mac RPC-ის შეცდომა KCM დემონთან ურთიერთობისას" + +#: ../lib/krb5/error_tables/k5e1_err.c:33 +msgid "KCM daemon reply too big" +msgstr "KCM დემონის პასუხი ძალიან დიდია" + +#: ../lib/krb5/error_tables/k5e1_err.c:34 +msgid "No KCM server found" +msgstr "KCM სერვერი ვერ ვიპოვე" + +#: ../lib/krb5/error_tables/k5e1_err.c:35 +msgid "Authorize and set hw-authent ticket flag" +msgstr "ავტორიზაცია და hw-authent ბილეთის ალმის დაყენება" + +#: ../lib/krb5/error_tables/k5e1_err.c:36 +msgid "Set hw-authent ticket flag but do not authorize" +msgstr "\"hw-authent\" ალმის დაყენება, მაგრამ ავტორიზაციის გარეშე" + +#: ../lib/krb5/error_tables/krb5_err.c:24 +msgid "Client's entry in database has expired" +msgstr "ბაზაში კლიენტის ჩანაწერი ვადაგასულია" + +#: ../lib/krb5/error_tables/krb5_err.c:25 +msgid "Server's entry in database has expired" +msgstr "ბაზაში სერვერის ჩანაწერი ვადაგასულია" + +#: ../lib/krb5/error_tables/krb5_err.c:26 +msgid "Requested protocol version not supported" +msgstr "მოთხოვნილი პროტოკოლის ვერსია მხარდაუჭერელია" + +#: ../lib/krb5/error_tables/krb5_err.c:27 +msgid "Client's key is encrypted in an old master key" +msgstr "კლიენტის გასაღები ძველი მთავარი გასაღებია" + +#: ../lib/krb5/error_tables/krb5_err.c:28 +msgid "Server's key is encrypted in an old master key" +msgstr "სერვერის გასაღები ძველი მთავარი გასაღებია" + +#: ../lib/krb5/error_tables/krb5_err.c:29 +msgid "Client not found in Kerberos database" +msgstr "კლიენტი Kerberos-ის ბაზაში ვერ ვიპოვე" + +#: ../lib/krb5/error_tables/krb5_err.c:30 +msgid "Server not found in Kerberos database" +msgstr "სერვერი Kerberos-ის ბაზაში ვერ ვიპოვე" + +#: ../lib/krb5/error_tables/krb5_err.c:31 +msgid "Principal has multiple entries in Kerberos database" +msgstr "პრინციპალს Kerberos-ის ბაზაში ერთზე მეტი ჩანაწერი გააჩნია" + +#: ../lib/krb5/error_tables/krb5_err.c:32 +msgid "Client or server has a null key" +msgstr "სერვერის ან კლიენტის გასაღები ნულოვანია" + +#: ../lib/krb5/error_tables/krb5_err.c:33 +msgid "Ticket is ineligible for postdating" +msgstr "ბილეთი მორიგი რიცხვით ჩაწერისთვის შეუფერებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:34 +msgid "Requested effective lifetime is negative or too short" +msgstr "მოთხოვნილი ეფექტური სიცოცხლის დრო უარყოფითი ან მეტისმეტად მოკლეა" + +#: ../lib/krb5/error_tables/krb5_err.c:35 +msgid "KDC policy rejects request" +msgstr "KDC პოლიტიკა მოთხოვნას უარყოფს" + +#: ../lib/krb5/error_tables/krb5_err.c:36 +msgid "KDC can't fulfill requested option" +msgstr "KDC მოთხოვნილი პარამეტრის შევსება შეუძლებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:37 +msgid "KDC has no support for encryption type" +msgstr "KDC -ს დაშიფვრის ტიპის მხარდაჭერა არ გააჩნია" + +#: ../lib/krb5/error_tables/krb5_err.c:38 +msgid "KDC has no support for checksum type" +msgstr "KDC -ს საკონტროლო ჯამის ტიპის მხარდაჭერა არ გააჩნია" + +#: ../lib/krb5/error_tables/krb5_err.c:39 +msgid "KDC has no support for padata type" +msgstr "KDC -ს padata ტიპის მხარდაჭერა არ გააჩნია" + +#: ../lib/krb5/error_tables/krb5_err.c:40 +msgid "KDC has no support for transited type" +msgstr "KDC -ს transited ტიპის მხარდაჭერა არ გააჩნია" + +#: ../lib/krb5/error_tables/krb5_err.c:41 +msgid "Client's credentials have been revoked" +msgstr "კლიენტის ავტორიზაციის დეტალები გაუქმდა" + +#: ../lib/krb5/error_tables/krb5_err.c:42 +msgid "Credentials for server have been revoked" +msgstr "სერვერის ავტორიზაციის დეტალები გაუქმდა" + +#: ../lib/krb5/error_tables/krb5_err.c:43 +msgid "TGT has been revoked" +msgstr "TGT გაუქმებულია" + +#: ../lib/krb5/error_tables/krb5_err.c:44 +msgid "Client not yet valid - try again later" +msgstr "კლიენტი ჯერ არასწორია - მოგვიანებით სცადეთ" + +#: ../lib/krb5/error_tables/krb5_err.c:45 +msgid "Server not yet valid - try again later" +msgstr "სერვერი ჯერ არასწორია - მოგვიანებით სცადეთ" + +#: ../lib/krb5/error_tables/krb5_err.c:46 +msgid "Password has expired" +msgstr "პაროლს ვადა გაუვიდა" + +#: ../lib/krb5/error_tables/krb5_err.c:47 +msgid "Preauthentication failed" +msgstr "პრეავთენტიკაციის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:48 +msgid "Additional pre-authentication required" +msgstr "დამატებითი პრე-ავთენტიკაცია აუცილებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:49 +msgid "Requested server and ticket don't match" +msgstr "მოთხოვნილი სერვერი და ბილეთი არ ემთხვევა" + +#: ../lib/krb5/error_tables/krb5_err.c:50 +msgid "Server principal valid for user2user only" +msgstr "სერვერის პრინციპალი მხოლოდ მომხმარებლიდან მომხმარებლამდეა ძალაში" + +#: ../lib/krb5/error_tables/krb5_err.c:51 +msgid "KDC policy rejects transited path" +msgstr "KDC-ის პოლიტიკა ტრანზიტულ ბილიკს უარყოფს" + +#: ../lib/krb5/error_tables/krb5_err.c:52 +msgid "A service is not available that is required to process the request" +msgstr "მოთხოვნის დასამუშავებლად საჭირო სერვისი ხელმიუწვდომელია" + +#: ../lib/krb5/error_tables/krb5_err.c:53 +msgid "KRB5 error code 30" +msgstr "KRB5 შეცდომის კოდი 30" + +#: ../lib/krb5/error_tables/krb5_err.c:54 +msgid "Decrypt integrity check failed" +msgstr "გაშიფვრის მთლიანობის შემოწმების შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:55 +msgid "Ticket expired" +msgstr "ბილეთი ვადაგასულია" + +#: ../lib/krb5/error_tables/krb5_err.c:56 +msgid "Ticket not yet valid" +msgstr "ბილეთი ჯერ არასწორია" + +#: ../lib/krb5/error_tables/krb5_err.c:57 +msgid "Request is a replay" +msgstr "პასუხის მოთხოვნა" + +#: ../lib/krb5/error_tables/krb5_err.c:58 +msgid "The ticket isn't for us" +msgstr "ბილეტი ჩვენთვის არაა" + +#: ../lib/krb5/error_tables/krb5_err.c:59 +msgid "Ticket/authenticator don't match" +msgstr "ბილეთი/ავთენტიკატორი არ ემთხვევიან" + +#: ../lib/krb5/error_tables/krb5_err.c:60 +msgid "Clock skew too great" +msgstr "საათის აცდენა მეტისმეტად დიდია" + +#: ../lib/krb5/error_tables/krb5_err.c:61 +msgid "Incorrect net address" +msgstr "არასწორი ქსელური მისამართი" + +#: ../lib/krb5/error_tables/krb5_err.c:62 +msgid "Protocol version mismatch" +msgstr "პროტოკოლის ვერსია არ ემთხვევა" + +#: ../lib/krb5/error_tables/krb5_err.c:63 +msgid "Invalid message type" +msgstr "შეტყობინების არასწორი ტიპი" + +#: ../lib/krb5/error_tables/krb5_err.c:64 +msgid "Message stream modified" +msgstr "შეტყობინების ნაკადი შეიცვალა" + +#: ../lib/krb5/error_tables/krb5_err.c:65 +msgid "Message out of order" +msgstr "შეტყობინება რიგს გარეთაა" + +#: ../lib/krb5/error_tables/krb5_err.c:66 +msgid "Illegal cross-realm ticket" +msgstr "არასწორი რეალმთშორისი ბილეთი" + +#: ../lib/krb5/error_tables/krb5_err.c:67 +msgid "Key version is not available" +msgstr "გასაღების ვერსია მიუწვდომელია" + +#: ../lib/krb5/error_tables/krb5_err.c:68 +msgid "Service key not available" +msgstr "სერვერის გასაღები ხელმიუწვდომელია" + +#: ../lib/krb5/error_tables/krb5_err.c:69 +#: ../lib/krb5/error_tables/krb5_err.c:181 +msgid "Mutual authentication failed" +msgstr "ორმხრივი ავთენტიკაციის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:70 +msgid "Incorrect message direction" +msgstr "შეტყობინების არასწორი მიმართულება" + +#: ../lib/krb5/error_tables/krb5_err.c:71 +msgid "Alternative authentication method required" +msgstr "ალტერნატიული ავთენტიკაციის მეთოდი აუცილებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:72 +msgid "Incorrect sequence number in message" +msgstr "მიმდევრობის არასწორი რიცხვი შეტყობინებაში" + +#: ../lib/krb5/error_tables/krb5_err.c:73 +msgid "Inappropriate type of checksum in message" +msgstr "საკონტროლო ჯამის შეუთავსებელი ტიპი შეტყობინებაში" + +#: ../lib/krb5/error_tables/krb5_err.c:74 +msgid "Policy rejects transited path" +msgstr "პოლიტიკა ტრანზიტულ ბილიკს უარყოფს" + +#: ../lib/krb5/error_tables/krb5_err.c:75 +msgid "Response too big for UDP, retry with TCP" +msgstr "პასუხი UDP-სთვის ძალიან დიდია. TCP-ით სცადეთ" + +#: ../lib/krb5/error_tables/krb5_err.c:76 +msgid "KRB5 error code 53" +msgstr "KRB5 შეცდომის კოდი 53" + +#: ../lib/krb5/error_tables/krb5_err.c:77 +msgid "KRB5 error code 54" +msgstr "KRB5 შეცდომის კოდი 54" + +#: ../lib/krb5/error_tables/krb5_err.c:78 +msgid "KRB5 error code 55" +msgstr "KRB5 შეცდომის კოდი 55" + +#: ../lib/krb5/error_tables/krb5_err.c:79 +msgid "KRB5 error code 56" +msgstr "KRB5 შეცდომის კოდი 56" + +#: ../lib/krb5/error_tables/krb5_err.c:80 +msgid "KRB5 error code 57" +msgstr "KRB5 შეცდომის კოდი 57" + +#: ../lib/krb5/error_tables/krb5_err.c:81 +msgid "KRB5 error code 58" +msgstr "KRB5 შეცდომის კოდი 58" + +#: ../lib/krb5/error_tables/krb5_err.c:82 +msgid "KRB5 error code 59" +msgstr "KRB5 შეცდომის კოდი 59" + +#: ../lib/krb5/error_tables/krb5_err.c:83 +msgid "Generic error (see e-text)" +msgstr "ზოგადი შეცდომა (იხილეთ e-text)" + +#: ../lib/krb5/error_tables/krb5_err.c:84 +msgid "Field is too long for this implementation" +msgstr "ამ განხორციელებისთვის ველი ძალიან გრძელია" + +#: ../lib/krb5/error_tables/krb5_err.c:85 +msgid "Client not trusted" +msgstr "კლიენტი სანდო არაა" + +#: ../lib/krb5/error_tables/krb5_err.c:86 +msgid "KDC not trusted" +msgstr "KDC სანდო არაა" + +#: ../lib/krb5/error_tables/krb5_err.c:87 +msgid "Invalid signature" +msgstr "არასწორი ხელმოწერა" + +#: ../lib/krb5/error_tables/krb5_err.c:88 +msgid "Key parameters not accepted" +msgstr "გასაღების პარამეტრები მიუღებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:89 +msgid "Certificate mismatch" +msgstr "სერტიფიკატები არ ემთხვევა" + +#: ../lib/krb5/error_tables/krb5_err.c:90 +msgid "No ticket granting ticket" +msgstr "ბილეთის მიმნიჭებელი ბილეთის გარეშე" + +#: ../lib/krb5/error_tables/krb5_err.c:91 +msgid "Realm not local to KDC" +msgstr "რეალმი KDC-სთვის ლოკალური არაა" + +#: ../lib/krb5/error_tables/krb5_err.c:92 +msgid "User to user required" +msgstr "მომხმარებლისდან მომხმარებლამდე აუცილებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:93 +msgid "Can't verify certificate" +msgstr "სერტიფიკატის შემოწმება შეუძლებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:94 +msgid "Invalid certificate" +msgstr "არასწორი სერტიფიკატი" + +#: ../lib/krb5/error_tables/krb5_err.c:95 +msgid "Revoked certificate" +msgstr "გაუქმებული სერტიფიკატი" + +#: ../lib/krb5/error_tables/krb5_err.c:96 +msgid "Revocation status unknown" +msgstr "გაუქმების სტატუსი უცნობია" + +#: ../lib/krb5/error_tables/krb5_err.c:97 +msgid "Revocation status unavailable" +msgstr "გაუქმების სტატუსი მიუწვდომელია" + +#: ../lib/krb5/error_tables/krb5_err.c:98 +msgid "Client name mismatch" +msgstr "კლიენტის სახელი არ ემთხვევა" + +#: ../lib/krb5/error_tables/krb5_err.c:99 +msgid "KDC name mismatch" +msgstr "KDC-ის სახელი არ ემთხვევა" + +#: ../lib/krb5/error_tables/krb5_err.c:100 +msgid "Inconsistent key purpose" +msgstr "გასაღების დანიშნულება არამდგრადია" + +#: ../lib/krb5/error_tables/krb5_err.c:101 +msgid "Digest in certificate not accepted" +msgstr "სერტიფიკატის დაიჯესტი მიუღებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:102 +msgid "Checksum must be included" +msgstr "საკონტროლო ჯამის ქონა აუცილებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:103 +msgid "Digest in signed-data not accepted" +msgstr "ხელმოწერილ-მონაცემებში გამოყენებული დაიჯესტი მიუღებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:104 +msgid "Public key encryption not supported" +msgstr "საჯარო გასაღების დაშიფვრა მხარდაუჭერელია" + +#: ../lib/krb5/error_tables/krb5_err.c:105 +msgid "KRB5 error code 82" +msgstr "KRB5 შეცდომის კოდი 82" + +#: ../lib/krb5/error_tables/krb5_err.c:106 +msgid "KRB5 error code 83" +msgstr "KRB5 შეცდომის კოდი 83" + +#: ../lib/krb5/error_tables/krb5_err.c:107 +msgid "KRB5 error code 84" +msgstr "KRB5 შეცდომის კოდი 84" + +#: ../lib/krb5/error_tables/krb5_err.c:108 +msgid "The IAKERB proxy could not find a KDC" +msgstr "IAKERB პროქსიმ KDC ვერ იპოვა" + +#: ../lib/krb5/error_tables/krb5_err.c:109 +msgid "The KDC did not respond to the IAKERB proxy" +msgstr "KDC-მა IAKERB პროქსის არ უპასუხა" + +#: ../lib/krb5/error_tables/krb5_err.c:110 +msgid "KRB5 error code 87" +msgstr "KRB5 შეცდომის კოდი 87" + +#: ../lib/krb5/error_tables/krb5_err.c:111 +msgid "KRB5 error code 88" +msgstr "KRB5 შეცდომის კოდი 88" + +#: ../lib/krb5/error_tables/krb5_err.c:112 +msgid "KRB5 error code 89" +msgstr "KRB5 შეცდომის კოდი 89" + +#: ../lib/krb5/error_tables/krb5_err.c:113 +msgid "Preauthentication expired" +msgstr "პრეავთენტიკაცია ვადაგასულია" + +#: ../lib/krb5/error_tables/krb5_err.c:114 +msgid "More preauthentication data is required" +msgstr "აუცილებელია პრეავთენტიკაციის მონაცემები" + +#: ../lib/krb5/error_tables/krb5_err.c:115 +msgid "KRB5 error code 92" +msgstr "KRB5 შეცდომის კოდი 92" + +#: ../lib/krb5/error_tables/krb5_err.c:116 +msgid "An unsupported critical FAST option was requested" +msgstr "მოთხოვნილია მხარდაუჭერელი კრიტიკული FAST პარამეტრი" + +#: ../lib/krb5/error_tables/krb5_err.c:117 +msgid "KRB5 error code 94" +msgstr "KRB5 შეცდომის კოდი 94" + +#: ../lib/krb5/error_tables/krb5_err.c:118 +msgid "KRB5 error code 95" +msgstr "KRB5 შეცდომის კოდი 95" + +#: ../lib/krb5/error_tables/krb5_err.c:119 +msgid "KRB5 error code 96" +msgstr "KRB5 შეცდომის კოდი 96" + +#: ../lib/krb5/error_tables/krb5_err.c:120 +msgid "KRB5 error code 97" +msgstr "KRB5 შეცდომის კოდი 97" + +#: ../lib/krb5/error_tables/krb5_err.c:121 +msgid "KRB5 error code 98" +msgstr "KRB5 შეცდომის კოდი 98" + +#: ../lib/krb5/error_tables/krb5_err.c:122 +msgid "KRB5 error code 99" +msgstr "KRB5 შეცდომის კოდი 99" + +#: ../lib/krb5/error_tables/krb5_err.c:123 +msgid "No acceptable KDF offered" +msgstr "დამაკმაყოფილებელი KDF შემოთავაზებული არ ყოფილა" + +#: ../lib/krb5/error_tables/krb5_err.c:124 +msgid "KRB5 error code 101" +msgstr "KRB5 შეცდომის კოდი 101" + +#: ../lib/krb5/error_tables/krb5_err.c:125 +msgid "KRB5 error code 102" +msgstr "KRB5 შეცდომის კოდი 102" + +#: ../lib/krb5/error_tables/krb5_err.c:126 +msgid "KRB5 error code 103" +msgstr "KRB5 შეცდომის კოდი 103" + +#: ../lib/krb5/error_tables/krb5_err.c:127 +msgid "KRB5 error code 104" +msgstr "KRB5 შეცდომის კოდი 104" + +#: ../lib/krb5/error_tables/krb5_err.c:128 +msgid "KRB5 error code 105" +msgstr "KRB5 შეცდომის კოდი 105" + +#: ../lib/krb5/error_tables/krb5_err.c:129 +msgid "KRB5 error code 106" +msgstr "KRB5 შეცდომის კოდი 106" + +#: ../lib/krb5/error_tables/krb5_err.c:130 +msgid "KRB5 error code 107" +msgstr "KRB5 შეცდომის კოდი 107" + +#: ../lib/krb5/error_tables/krb5_err.c:131 +msgid "KRB5 error code 108" +msgstr "KRB5 შეცდომის კოდი 108" + +#: ../lib/krb5/error_tables/krb5_err.c:132 +msgid "KRB5 error code 109" +msgstr "KRB5 შეცდომის კოდი 109" + +#: ../lib/krb5/error_tables/krb5_err.c:133 +msgid "KRB5 error code 110" +msgstr "KRB5 შეცდომის კოდი 110" + +#: ../lib/krb5/error_tables/krb5_err.c:134 +msgid "KRB5 error code 111" +msgstr "KRB5 შეცდომის კოდი 111" + +#: ../lib/krb5/error_tables/krb5_err.c:135 +msgid "KRB5 error code 112" +msgstr "KRB5 შეცდომის კოდი 112" + +#: ../lib/krb5/error_tables/krb5_err.c:136 +msgid "KRB5 error code 113" +msgstr "KRB5 შეცდომის კოდი 113" + +#: ../lib/krb5/error_tables/krb5_err.c:137 +msgid "KRB5 error code 114" +msgstr "KRB5 შეცდომის კოდი 114" + +#: ../lib/krb5/error_tables/krb5_err.c:138 +msgid "KRB5 error code 115" +msgstr "KRB5 შეცდომის კოდი 115" + +#: ../lib/krb5/error_tables/krb5_err.c:139 +msgid "KRB5 error code 116" +msgstr "KRB5 შეცდომის კოდი 116" + +#: ../lib/krb5/error_tables/krb5_err.c:140 +msgid "KRB5 error code 117" +msgstr "KRB5 შეცდომის კოდი 117" + +#: ../lib/krb5/error_tables/krb5_err.c:141 +msgid "KRB5 error code 118" +msgstr "KRB5 შეცდომის კოდი 118" + +#: ../lib/krb5/error_tables/krb5_err.c:142 +msgid "KRB5 error code 119" +msgstr "KRB5 შეცდომის კოდი 119" + +#: ../lib/krb5/error_tables/krb5_err.c:143 +msgid "KRB5 error code 120" +msgstr "KRB5 შეცდომის კოდი 120" + +#: ../lib/krb5/error_tables/krb5_err.c:144 +msgid "KRB5 error code 121" +msgstr "KRB5 შეცდომის კოდი 121" + +#: ../lib/krb5/error_tables/krb5_err.c:145 +msgid "KRB5 error code 122" +msgstr "KRB5 შეცდომის კოდი 122" + +#: ../lib/krb5/error_tables/krb5_err.c:146 +msgid "KRB5 error code 123" +msgstr "KRB5 შეცდომის კოდი 123" + +#: ../lib/krb5/error_tables/krb5_err.c:147 +msgid "KRB5 error code 124" +msgstr "KRB5 შეცდომის კოდი 124" + +#: ../lib/krb5/error_tables/krb5_err.c:148 +msgid "KRB5 error code 125" +msgstr "KRB5 შეცდომის კოდი 125" + +#: ../lib/krb5/error_tables/krb5_err.c:149 +msgid "KRB5 error code 126" +msgstr "KRB5 შეცდომის კოდი 126" + +#: ../lib/krb5/error_tables/krb5_err.c:150 +msgid "KRB5 error code 127" +msgstr "KRB5 შეცდომის კოდი 127" + +#: ../lib/krb5/error_tables/krb5_err.c:151 +#: ../lib/krb5/error_tables/kdb5_err.c:23 +msgid "$Id$" +msgstr "$Id$" + +#: ../lib/krb5/error_tables/krb5_err.c:152 +msgid "Invalid flag for file lock mode" +msgstr "ფაილის დაბლოკვის რეჟიმის არასწორი ალამი" + +#: ../lib/krb5/error_tables/krb5_err.c:153 +msgid "Cannot read password" +msgstr "პაროლის წაკითხვის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:154 +msgid "Password mismatch" +msgstr "პაროლი არ ემთხვევა" + +#: ../lib/krb5/error_tables/krb5_err.c:155 +msgid "Password read interrupted" +msgstr "პაროლის წაკითხვა შეწყვეტილია" + +#: ../lib/krb5/error_tables/krb5_err.c:156 +msgid "Illegal character in component name" +msgstr "კომპონენტის სახელი დაუშვებელ სიმბოლოს შეიცავს" + +#: ../lib/krb5/error_tables/krb5_err.c:157 +msgid "Malformed representation of principal" +msgstr "პრინციპალის წარმოდგენა არასწორია" + +#: ../lib/krb5/error_tables/krb5_err.c:158 +msgid "Can't open/find Kerberos configuration file" +msgstr "Kernberos-ის კონფიგურაციის ფაილის გახსნის/პოვნის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:159 +msgid "Improper format of Kerberos configuration file" +msgstr "Kerberos-ის კონფიგურაციის ფაილის არასწორი ფორმატი" + +#: ../lib/krb5/error_tables/krb5_err.c:160 +msgid "Insufficient space to return complete information" +msgstr "სრული ინფორმაციის დასაბრუნებლად ადგილი საკმარისი არაა" + +#: ../lib/krb5/error_tables/krb5_err.c:161 +msgid "Invalid message type specified for encoding" +msgstr "კოდირებისთვის მითითებული შეტყობინების ტიპი არასწორია" + +#: ../lib/krb5/error_tables/krb5_err.c:162 +msgid "Credential cache name malformed" +msgstr "არასწორად ფორმირებული ავტორიზაციის დეტალების ქეშის სახელი" + +#: ../lib/krb5/error_tables/krb5_err.c:163 +msgid "Unknown credential cache type" +msgstr "ავტორიზაციის დეტალების ქეშის არასწორი ტიპი" + +#: ../lib/krb5/error_tables/krb5_err.c:164 +msgid "Matching credential not found" +msgstr "შესაბამისი ავტორიზაციის დეტალები ნაპოვნი არაა" + +#: ../lib/krb5/error_tables/krb5_err.c:165 +msgid "End of credential cache reached" +msgstr "მივაღწიეთ ავტორიზაციის დეტალების ქეშის ბოლოს" + +#: ../lib/krb5/error_tables/krb5_err.c:166 +msgid "Request did not supply a ticket" +msgstr "მოთხოვნას ბილეთი არ მოუწოდებია" + +#: ../lib/krb5/error_tables/krb5_err.c:167 +msgid "Wrong principal in request" +msgstr "მოთხოვნაში მითითებული პრინციპალი არასწორია" + +#: ../lib/krb5/error_tables/krb5_err.c:168 +msgid "Ticket has invalid flag set" +msgstr "ბილეთზე დაყენებული ალმები არასწორია" + +#: ../lib/krb5/error_tables/krb5_err.c:169 +msgid "Requested principal and ticket don't match" +msgstr "მოთხოვნილი პრინციპალი და ბილეთი არ ემთხვევა" + +#: ../lib/krb5/error_tables/krb5_err.c:170 +msgid "KDC reply did not match expectations" +msgstr "KDC-ის პასუხი მოსალოდნელს არ ემთხვევა" + +#: ../lib/krb5/error_tables/krb5_err.c:171 +msgid "Clock skew too great in KDC reply" +msgstr "KDC-ის პასუხისთვის საათის აცდენა მეტისმეტად დიდია" + +#: ../lib/krb5/error_tables/krb5_err.c:172 +msgid "Client/server realm mismatch in initial ticket request" +msgstr "" +"ბილეთის საწყის მოთხოვნაში კლიენტისა და სერვერის რეალმები ერთმანეთს არ " +"ემთხვევა" + +#: ../lib/krb5/error_tables/krb5_err.c:173 +msgid "Program lacks support for encryption type" +msgstr "პროგრამას დაშიფვრის ტიპის მხარდაჭერა არ გააჩნია" + +#: ../lib/krb5/error_tables/krb5_err.c:174 +msgid "Program lacks support for key type" +msgstr "პროგრამას გასაღების ტიპის მხარდაჭერა არ გააჩნია" + +#: ../lib/krb5/error_tables/krb5_err.c:175 +msgid "Requested encryption type not used in message" +msgstr "შეტყობინებაში მოთხოვნილი დაშიფვრის ტიპი არ გამოიყენება" + +#: ../lib/krb5/error_tables/krb5_err.c:176 +msgid "Program lacks support for checksum type" +msgstr "პროგრამას საკონტროლო ჯამის ტიპის მხარდაჭერა არ გააჩნია" + +#: ../lib/krb5/error_tables/krb5_err.c:177 +msgid "Cannot find KDC for requested realm" +msgstr "მოთხოვნილი რეალმისთვის KDC ვერ ვიპოვე" + +#: ../lib/krb5/error_tables/krb5_err.c:178 +msgid "Kerberos service unknown" +msgstr "Kerberos -ის უცნობი სერვისი" + +#: ../lib/krb5/error_tables/krb5_err.c:179 +msgid "Cannot contact any KDC for requested realm" +msgstr "მოთხოვნილი რეალმისთვის ვერც ერთ KDC-ს ვერ დავუკავშირდი" + +#: ../lib/krb5/error_tables/krb5_err.c:180 +msgid "No local name found for principal name" +msgstr "პრინციპალის სახელისთვის ლოკალური სახელი ვერ ვიპოვე" + +#: ../lib/krb5/error_tables/krb5_err.c:182 +msgid "Replay cache type is already registered" +msgstr "საპასუხო ქეშის ტიპი უკვე რეგისტრირებულია" + +#: ../lib/krb5/error_tables/krb5_err.c:183 +msgid "No more memory to allocate (in replay cache code)" +msgstr "გამოსაყოფი მეხსიერება არ არსებობს (პასუხის ქეშის კოდში)" + +#: ../lib/krb5/error_tables/krb5_err.c:184 +msgid "Replay cache type is unknown" +msgstr "პასუხის ქეშის ტიპი უცნობია" + +#: ../lib/krb5/error_tables/krb5_err.c:185 +msgid "Generic unknown RC error" +msgstr "ზოგადი უცნობი RC შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:186 +msgid "Message is a replay" +msgstr "შეტყობინება პასუხია" + +#: ../lib/krb5/error_tables/krb5_err.c:187 +msgid "Replay cache I/O operation failed" +msgstr "პასუხის ქეშთან მიმოცვლის ოპერაციის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:188 +msgid "Replay cache type does not support non-volatile storage" +msgstr "პასუხის ქეშის ტიპს არააქროლადი საცავის მხარდაჭერა არ გააჩნია" + +#: ../lib/krb5/error_tables/krb5_err.c:189 +msgid "Replay cache name parse/format error" +msgstr "პასუხის ქეშის სახელის დამუშავების/ფორმატის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:190 +msgid "End-of-file on replay cache I/O" +msgstr "ფაილის-ბოლო პასუხის ქეშთან მიმოცვლისას" + +#: ../lib/krb5/error_tables/krb5_err.c:191 +msgid "No more memory to allocate (in replay cache I/O code)" +msgstr "გამოსაყოფი მეხსიერება არ არსებობს (პასუხის ქეშთან მიმოცვლის კოდში)" + +#: ../lib/krb5/error_tables/krb5_err.c:192 +msgid "Permission denied in replay cache code" +msgstr "პასუხის ქეშის კოდის წვდომა აკრძალულია" + +#: ../lib/krb5/error_tables/krb5_err.c:193 +msgid "I/O error in replay cache i/o code" +msgstr "მიმოცვლის შეცდომა პასუხის ქეშის მიმოცვლის კოდში" + +#: ../lib/krb5/error_tables/krb5_err.c:194 +msgid "Generic unknown RC/IO error" +msgstr "ზოგადი უცნობი RC/IO შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:195 +msgid "Insufficient system space to store replay information" +msgstr "პასუხის ინფორმაციის დასამახსოვრებლად სისტემური ადგილი საკმარისი არაა" + +#: ../lib/krb5/error_tables/krb5_err.c:196 +msgid "Can't open/find realm translation file" +msgstr "რეალმის თარგმნის ფაილის გახსნის/პოვნის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:197 +msgid "Improper format of realm translation file" +msgstr "რეალმის თარგმანის ფაილის არასწორი ფორმატი" + +#: ../lib/krb5/error_tables/krb5_err.c:198 +msgid "Can't open/find lname translation database" +msgstr "Lname-ის თარგმანის ბაზის პოვნის/გახსნის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:199 +msgid "No translation available for requested principal" +msgstr "მოთხოვნილი პრინციპალისთვის თარგმანი არ არსებობს" + +#: ../lib/krb5/error_tables/krb5_err.c:200 +msgid "Improper format of translation database entry" +msgstr "თარგმანის ბაზის ჩანაწერის არასწორი ფორმატი" + +#: ../lib/krb5/error_tables/krb5_err.c:201 +msgid "Cryptosystem internal error" +msgstr "კრიპტოსისტემის შიდა შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:202 +msgid "Key table name malformed" +msgstr "გასაღების ცხრილის სახელი არასწორია" + +#: ../lib/krb5/error_tables/krb5_err.c:203 +msgid "Unknown Key table type" +msgstr "გასაღების ცხრილის უცნობი ტიპი" + +#: ../lib/krb5/error_tables/krb5_err.c:204 +msgid "Key table entry not found" +msgstr "გასაღების ცხრილის ჩანაწერი ვერ ვპოვე" + +#: ../lib/krb5/error_tables/krb5_err.c:205 +msgid "End of key table reached" +msgstr "მიღწეულია გასაღების ცხრილის ბოლო" + +#: ../lib/krb5/error_tables/krb5_err.c:206 +msgid "Cannot write to specified key table" +msgstr "მითითებული გასაღების ცხრილში ჩაწერის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:207 +msgid "Error writing to key table" +msgstr "გასაღებების ცხრილში ჩაწერის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:208 +msgid "Cannot find ticket for requested realm" +msgstr "მოთხოვნილი რეალმისთვის ბილეთის პოვნის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:209 +msgid "DES key has bad parity" +msgstr "DES გასაღებსი არასწორი პარიტეტი" + +#: ../lib/krb5/error_tables/krb5_err.c:210 +msgid "DES key is a weak key" +msgstr "DES გასაღები სუსტია" + +#: ../lib/krb5/error_tables/krb5_err.c:211 +msgid "Bad encryption type" +msgstr "არასწორი დაშიფვრის ტიპი" + +#: ../lib/krb5/error_tables/krb5_err.c:212 +msgid "Key size is incompatible with encryption type" +msgstr "გასაღების ზომა დაშიფვრის ტიპთან შეუთავსებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:213 +msgid "Message size is incompatible with encryption type" +msgstr "შეტყობინების ზომა დაშიფვრის ტიპთან შეუთავსებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:214 +msgid "Credentials cache type is already registered." +msgstr "ავტორიზაციის დეტალების ქეშის ტიპი უკვე რეგისტრირებულია." + +#: ../lib/krb5/error_tables/krb5_err.c:215 +msgid "Key table type is already registered." +msgstr "გასაღებების ცხრილის ტიპი უკვე რეგისტრირებულია." + +#: ../lib/krb5/error_tables/krb5_err.c:216 +msgid "Credentials cache I/O operation failed" +msgstr "ავტორიზაციის დეტალების ქეშთან მიმოცვლის ოპერაციის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:217 +msgid "Credentials cache permissions incorrect" +msgstr "ავტორიზაციის დეტალების ქეშის წვდომები არასწორია" + +#: ../lib/krb5/error_tables/krb5_err.c:218 +msgid "No credentials cache found" +msgstr "ავტორიზაციის დეტალების ქეში არ არსებობს" + +#: ../lib/krb5/error_tables/krb5_err.c:219 +msgid "Internal credentials cache error" +msgstr "შიდა ავტორიზაციის დეტალების ქეშის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:220 +msgid "Error writing to credentials cache" +msgstr "ავტორიზაციის დეტალების ქეშში ჩაწერის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:221 +msgid "No more memory to allocate (in credentials cache code)" +msgstr "გამოსაყოფი მეხსიერება აღარ დარჩა (ავტორიზაციის დეტალების ქეშის კოდში)" + +#: ../lib/krb5/error_tables/krb5_err.c:222 +msgid "Bad format in credentials cache" +msgstr "არასწორი ფორმატი ავტორიზაციის დეტალების ქეშში" + +#: ../lib/krb5/error_tables/krb5_err.c:223 +msgid "No credentials found with supported encryption types" +msgstr "მხარდაჭერილი დაშიფვრის ტიპების მქონე ავტორიზაციის დეტალები ვერ ვიპოვე" + +#: ../lib/krb5/error_tables/krb5_err.c:224 +msgid "Invalid KDC option combination (library internal error)" +msgstr "KDC-ის პარამეტრების არასწორი კომბინაცია (ბიბლიოთეკის შიდა შეცდომა)" + +#: ../lib/krb5/error_tables/krb5_err.c:225 +msgid "Request missing second ticket" +msgstr "მოთხოვნას მეორე ბილეთი აკლია" + +#: ../lib/krb5/error_tables/krb5_err.c:226 +msgid "No credentials supplied to library routine" +msgstr "ბიბლიოთეკის ქვეპროგრამისთვის ავტორიზაციის დეტალები მიწოდებული არაა" + +#: ../lib/krb5/error_tables/krb5_err.c:227 +msgid "Bad sendauth version was sent" +msgstr "გაგზავნილი sendauth ვერსია არასწორია" + +#: ../lib/krb5/error_tables/krb5_err.c:228 +msgid "Bad application version was sent (via sendauth)" +msgstr "აპლიკაციის გაგზავნილი ვერსია არასწორია (sendauth-ით)" + +#: ../lib/krb5/error_tables/krb5_err.c:229 +msgid "Bad response (during sendauth exchange)" +msgstr "არასწორი პასუხი (sendauth-ით გაცვლისას)" + +#: ../lib/krb5/error_tables/krb5_err.c:230 +msgid "Server rejected authentication (during sendauth exchange)" +msgstr "სერვერმა ავტორიზაცია უარყო (sendauth-ით გაცვლისას)" + +#: ../lib/krb5/error_tables/krb5_err.c:231 +msgid "Unsupported preauthentication type" +msgstr "პრეავთენტიკაციის მხარდაუჭერელი ტიპი" + +#: ../lib/krb5/error_tables/krb5_err.c:232 +msgid "Required preauthentication key not supplied" +msgstr "პრეავთენტიკაცის გასაღების მიწოდება აუცილებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:233 +msgid "Generic preauthentication failure" +msgstr "პრეავთენტიკაციის ზოგადი შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:234 +msgid "Unsupported replay cache format version number" +msgstr "პასუხის ქეშის ფორმატის ვერსიის ნომერი მხარდაუჭერელია" + +#: ../lib/krb5/error_tables/krb5_err.c:235 +msgid "Unsupported credentials cache format version number" +msgstr "ავტორიზაციის დეტალების ქეშის ფორმატის ვერსიის არასწორი ნომერი" + +#: ../lib/krb5/error_tables/krb5_err.c:236 +msgid "Unsupported key table format version number" +msgstr "გასაღებების ცხრილის ფორმატის ვერსიის არასწორი ნომერი" + +#: ../lib/krb5/error_tables/krb5_err.c:237 +msgid "Program lacks support for address type" +msgstr "პროგრამას მისამართის ტიპის მხარდაჭერა არ გააჩნია" + +#: ../lib/krb5/error_tables/krb5_err.c:238 +msgid "Message replay detection requires rcache parameter" +msgstr "შეტყობინებაზე პასუხის აღმოჩენას rcache პარამეტრი სჭირდება" + +#: ../lib/krb5/error_tables/krb5_err.c:239 +msgid "Hostname cannot be canonicalized" +msgstr "ჰოსტის სახელის კანონიკალიზება სეუძლებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:240 +msgid "Cannot determine realm for host" +msgstr "ჰოსტისთვის რეალმის დადგენის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:241 +msgid "Conversion to service principal undefined for name type" +msgstr "სერვისის პრინციპალზე გარდაქმნა სახელის ტიისთვის შეუძლებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:242 +msgid "Initial Ticket response appears to be Version 4 error" +msgstr "საწყისი ბილეთის პასუხი მეოთხე ვერსიის შეცდომას წააგავს" + +#: ../lib/krb5/error_tables/krb5_err.c:243 +msgid "Cannot resolve network address for KDC in requested realm" +msgstr "მოთხოვნილ რეალმში KDC-ის ქსელური მისამართის ამოხსნის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:244 +msgid "Requesting ticket can't get forwardable tickets" +msgstr "მომთხოვნი ბილეთები გადამისამართებადი ბილეთები ვერ იქნება" + +#: ../lib/krb5/error_tables/krb5_err.c:245 +msgid "Bad principal name while trying to forward credentials" +msgstr "ავტორიზაციის დეტალების გადაგზავნისას პრინციპალის სახელი არასწორია" + +#: ../lib/krb5/error_tables/krb5_err.c:246 +msgid "Looping detected inside krb5_get_in_tkt" +msgstr "Krb5_get_in_tkt_ის შიგნით მარყუჟი ვიპოვე" + +#: ../lib/krb5/error_tables/krb5_err.c:247 +msgid "Configuration file does not specify default realm" +msgstr "კონფიგურაციის ფაილში ნაგულისხმები რეალმი მითითებული არაა" + +#: ../lib/krb5/error_tables/krb5_err.c:248 +msgid "Bad SAM flags in obtain_sam_padata" +msgstr "არასწორი SAM ალმები obtain_sam_padata-ში" + +#: ../lib/krb5/error_tables/krb5_err.c:249 +msgid "Invalid encryption type in SAM challenge" +msgstr "არასწორი დაშიფვრის ტიპი SAM გამოწვევაში" + +#: ../lib/krb5/error_tables/krb5_err.c:250 +msgid "Missing checksum in SAM challenge" +msgstr "SAM გამოწვევაში საკონტროლო ჯამი ვერ ვიპოვე" + +#: ../lib/krb5/error_tables/krb5_err.c:251 +msgid "Bad checksum in SAM challenge" +msgstr "არასწორი საკონტროლო ჯამი SAM გამოწვევაში" + +#: ../lib/krb5/error_tables/krb5_err.c:252 +msgid "Keytab name too long" +msgstr "Keytab -ის სახელი ძალიან გრძელია" + +#: ../lib/krb5/error_tables/krb5_err.c:253 +msgid "Key version number for principal in key table is incorrect" +msgstr "პრინციპალისთვის გასაღებების ცხრილში გასაღების ვერსიის ნომერი არასწორია" + +#: ../lib/krb5/error_tables/krb5_err.c:254 +msgid "This application has expired" +msgstr "ეს აპლიკაცია ვადაგასულია" + +#: ../lib/krb5/error_tables/krb5_err.c:255 +msgid "This Krb5 library has expired" +msgstr "ეს Krb5 ბიბლიოთეკა ვადაგასულია" + +#: ../lib/krb5/error_tables/krb5_err.c:256 +msgid "New password cannot be zero length" +msgstr "ახალი პაროლი ნულოვანი სიგრძის ვერ იქნება" + +#: ../lib/krb5/error_tables/krb5_err.c:258 +msgid "Bad format in keytab" +msgstr "Keytab-ის არასწორი ფორმატი" + +#: ../lib/krb5/error_tables/krb5_err.c:259 +msgid "Encryption type not permitted" +msgstr "დაშიფვრის ტიპი დაუშვებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:260 +msgid "No supported encryption types (config file error?)" +msgstr "მხარდაჭერილი დაშიფვრის ტიპების გარეშე (კონფიგურაციის ფაილის შეცდომა?)" + +#: ../lib/krb5/error_tables/krb5_err.c:261 +msgid "Program called an obsolete, deleted function" +msgstr "პროგრამამ მოძველებული, წაშლილი ფუნქცია გამოიძახა" + +#: ../lib/krb5/error_tables/krb5_err.c:262 +msgid "unknown getaddrinfo failure" +msgstr "getaddrinfo-ის უცნობი შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:263 +msgid "no data available for host/domain name" +msgstr "ჰოსტის/დომენის სახელისთვის მონაცემები ხელმიუწვდომელია" + +#: ../lib/krb5/error_tables/krb5_err.c:264 +msgid "host/domain name not found" +msgstr "ჰოსტის/დომენის სახელი ვერ ვიპოვე" + +#: ../lib/krb5/error_tables/krb5_err.c:265 +msgid "service name unknown" +msgstr "სერვისის სახელი უცნობია" + +#: ../lib/krb5/error_tables/krb5_err.c:266 +msgid "Cannot determine realm for numeric host address" +msgstr "რიცხვითი ჰოსტის მისამართისთვის რეალმის განსაზღვრის შეცდომა" + +#: ../lib/krb5/error_tables/krb5_err.c:267 +msgid "Invalid key generation parameters from KDC" +msgstr "KDC-დან მიღებული გასაღების გენერაციის პარამეტრები არასწორია" + +#: ../lib/krb5/error_tables/krb5_err.c:268 +msgid "service not available" +msgstr "სერვისი ხელმიუწვდომელია" + +#: ../lib/krb5/error_tables/krb5_err.c:269 +msgid "Ccache function not supported: read-only ccache type" +msgstr "" +"Ccache-ის ფუნქცია განხორციელებული არაა: ccache-ის ტიპი მხოლოდ წაკითხვადია" + +#: ../lib/krb5/error_tables/krb5_err.c:270 +msgid "Ccache function not supported: not implemented" +msgstr "Ccache-ის ფუნქცია განხორციელებული არაა: განხორციელებული არაა" + +#: ../lib/krb5/error_tables/krb5_err.c:271 +msgid "Invalid format of Kerberos lifetime or clock skew string" +msgstr "" +"Kerberos-ის სიცოცხლის დროის არასწორი ფორმატი ან დროის აცდენა მეტისმეტად დიდია" + +#: ../lib/krb5/error_tables/krb5_err.c:272 +msgid "Supplied data not handled by this plugin" +msgstr "მოწოდებული მონაცემები ამ დამატების მიერ არ მუშავდება" + +#: ../lib/krb5/error_tables/krb5_err.c:273 +msgid "Plugin does not support the operation" +msgstr "დამატებას ამ ოპერაციის მხარდაჭერა არ გააჩნია" + +#: ../lib/krb5/error_tables/krb5_err.c:274 +msgid "Invalid UTF-8 string" +msgstr "არასწორი UTF-8 სტრიქონი" + +#: ../lib/krb5/error_tables/krb5_err.c:275 +msgid "FAST protected pre-authentication required but not supported by KDC" +msgstr "" +"FAST-ით დაცული პრე-ავთენტიკაცია აუცილებელია, მაგრამ მხარდაუჭერელია KDC-ის " +"მიერ" + +#: ../lib/krb5/error_tables/krb5_err.c:276 +msgid "Auth context must contain local address" +msgstr "ავთენტიკაციის კონტექსტისთვის ლოკალური მისამართი აუცილებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:277 +msgid "Auth context must contain remote address" +msgstr "ავთენტიკაციის კონტექსტისთვის დაშორებული მისამართი აუცილებელია" + +#: ../lib/krb5/error_tables/krb5_err.c:278 +msgid "Tracing unsupported" +msgstr "ტრეისინგი მხარდაუჭერელია" + +#: ../lib/krb5/error_tables/kdb5_err.c:24 +msgid "Entry already exists in database" +msgstr "ჩანაწერის ბაზაში უფრო არსებობს" + +#: ../lib/krb5/error_tables/kdb5_err.c:25 +msgid "Database store error" +msgstr "ბაზის შენახვის შეცდომა" + +#: ../lib/krb5/error_tables/kdb5_err.c:26 +msgid "Database read error" +msgstr "ბაზის წაკითხვის შეცდომა" + +#: ../lib/krb5/error_tables/kdb5_err.c:27 +msgid "Insufficient access to perform requested operation" +msgstr "არასაკმარისი წვდომები მოთხოვნილი ქმედების განსახორციელებლად" + +#: ../lib/krb5/error_tables/kdb5_err.c:28 +msgid "No such entry in the database" +msgstr "ბაზაში ასეთი ჩანაწერი არ არსებობს" + +#: ../lib/krb5/error_tables/kdb5_err.c:29 +msgid "Illegal use of wildcard" +msgstr "ვაილდ კარდის არასწორი გამოყენება" + +#: ../lib/krb5/error_tables/kdb5_err.c:30 +msgid "Database is locked or in use--try again later" +msgstr "ბაზა დაბლოკილია ან გამოიყენება--მოგვიანებით სცადეთ" + +#: ../lib/krb5/error_tables/kdb5_err.c:31 +msgid "Database was modified during read" +msgstr "ბაზა წაკითხვისას შეიცვალა" + +#: ../lib/krb5/error_tables/kdb5_err.c:32 +msgid "Database record is incomplete or corrupted" +msgstr "ბაზის ჩანაწერი დაუსრულებელი ან დაზიანებულია" + +#: ../lib/krb5/error_tables/kdb5_err.c:33 +msgid "Attempt to lock database twice" +msgstr "ბაზის ორჯერ დაბლოკვის მცდელობა" + +#: ../lib/krb5/error_tables/kdb5_err.c:34 +msgid "Attempt to unlock database when not locked" +msgstr "ბაზის, რომელიც დაბლოკილი არაა, განბლოკვის შეცდომა" + +#: ../lib/krb5/error_tables/kdb5_err.c:35 +msgid "Invalid kdb lock mode" +msgstr "KDB-ის ბლოკირებს არასწორი რეჟიმი" + +#: ../lib/krb5/error_tables/kdb5_err.c:36 +msgid "Database has not been initialized" +msgstr "ბაზა ინიციალიზებული არაა" + +#: ../lib/krb5/error_tables/kdb5_err.c:37 +msgid "Database has already been initialized" +msgstr "ბაზა უკვე ინიციალიზებულია" + +#: ../lib/krb5/error_tables/kdb5_err.c:38 +msgid "Bad direction for converting keys" +msgstr "გასაღებების გარდაქმნის არასწორი მიმართულება" + +#: ../lib/krb5/error_tables/kdb5_err.c:39 +msgid "Cannot find master key record in database" +msgstr "ბაზაში მთავარი გასაღების ჩანაწერის პოვნა შეუძლებელია" + +#: ../lib/krb5/error_tables/kdb5_err.c:40 +msgid "Master key does not match database" +msgstr "მთავარი გასაღები ბაზას არ ემთხვევა" + +#: ../lib/krb5/error_tables/kdb5_err.c:41 +msgid "Key size in database is invalid" +msgstr "ბაზაში ჩაწერილი გასაღების ზომა არასწორია" + +#: ../lib/krb5/error_tables/kdb5_err.c:42 +msgid "Cannot find/read stored master key" +msgstr "დამახსოვრებული მთავარი გასაღების პოვნის/წაკითხვის შეცდომა" + +#: ../lib/krb5/error_tables/kdb5_err.c:43 +msgid "Stored master key is corrupted" +msgstr "დამახსოვრებული მთავარი გასაღები დაზიანებულია" + +#: ../lib/krb5/error_tables/kdb5_err.c:44 +msgid "Cannot find active master key" +msgstr "აქტიური მთავარი გასაღების პოვნა შეუძლებელია" + +#: ../lib/krb5/error_tables/kdb5_err.c:45 +msgid "KVNO of new master key does not match expected value" +msgstr "ახალი მთავარი გასაღების KVNO მოსალოდნელ მნიშვნელობას არ ემთხვევა" + +#: ../lib/krb5/error_tables/kdb5_err.c:46 +msgid "Stored master key is not current" +msgstr "დამახსოვერებული მთავარი გასაღები მიმდინარე არაა" + +#: ../lib/krb5/error_tables/kdb5_err.c:47 +msgid "Insufficient access to lock database" +msgstr "არასაკმარისი წვდომები ბაზის დასაბლოკად" + +#: ../lib/krb5/error_tables/kdb5_err.c:48 +msgid "Database format error" +msgstr "ბაზის ფორმატის შეცდომა" + +#: ../lib/krb5/error_tables/kdb5_err.c:49 +msgid "Unsupported version in database entry" +msgstr "ბაზის ჩანაწერის მხარდაუჭერელი ვერსია" + +#: ../lib/krb5/error_tables/kdb5_err.c:50 +msgid "Unsupported salt type" +msgstr "მარილის მხარდაუჭერელი ტიპი" + +#: ../lib/krb5/error_tables/kdb5_err.c:51 +msgid "Unsupported encryption type" +msgstr "დაშიფვრის მხარდაუჭერელი ტიპი" + +#: ../lib/krb5/error_tables/kdb5_err.c:52 +msgid "Bad database creation flags" +msgstr "ბაზის შექმნის არასწორი ალმები" + +#: ../lib/krb5/error_tables/kdb5_err.c:53 +msgid "No matching key in entry having a permitted enctype" +msgstr "ჩანაწერში დაშვებული enctype-ის მქონე გასრები არ არსებობს" + +#: ../lib/krb5/error_tables/kdb5_err.c:54 +msgid "No matching key in entry" +msgstr "ჩანაწერში შესაბამისი გასაღები არ არსებობს" + +#: ../lib/krb5/error_tables/kdb5_err.c:56 +msgid "Database type not supported" +msgstr "ბაზის ტიპი მხარდაუჭერელია" + +#: ../lib/krb5/error_tables/kdb5_err.c:57 +msgid "Database library failed to initialize" +msgstr "ბაზის ბიბლიოთეკის ინიციალიზაციის შეცდომა" + +#: ../lib/krb5/error_tables/kdb5_err.c:59 +msgid "Unable to access Kerberos database" +msgstr "შეცდომა Kerberos-ის ბაზასთან წვდომისას" + +#: ../lib/krb5/error_tables/kdb5_err.c:60 +msgid "Kerberos database internal error" +msgstr "Kerberos-ის ბაზის შიდა შეცდომა" + +#: ../lib/krb5/error_tables/kdb5_err.c:61 +msgid "Kerberos database constraints violated" +msgstr "დარღვეულია Kerberos-ის ბაზის შეზღუდვები" + +#: ../lib/krb5/error_tables/kdb5_err.c:62 +msgid "Update log conversion error" +msgstr "განახლების ჟურნალის გარდაქმნის შეცდომა" + +#: ../lib/krb5/error_tables/kdb5_err.c:63 +msgid "Update log is unstable" +msgstr "განახლების ჟურნალი არასტაბილურია" + +#: ../lib/krb5/error_tables/kdb5_err.c:64 +msgid "Update log is corrupt" +msgstr "განახლების ჟურნალი დაზიანებული" + +#: ../lib/krb5/error_tables/kdb5_err.c:65 +msgid "Generic update log error" +msgstr "განახლების ჟურნალის საერთო შეცდომა" + +#: ../lib/krb5/error_tables/kdb5_err.c:66 +msgid "Database module does not match KDC version" +msgstr "ბაზის მოდული KDC-ის ვერსიას არ ემთხვევა" + +#: ../lib/krb5/error_tables/kdb5_err.c:68 +msgid "Too much string mapping data" +msgstr "მეტისმეტად ბევრი სტრიქონების გადაბმის მონაცემები" + +#: ../lib/krb5/error_tables/asn1_err.c:23 +msgid "ASN.1 failed call to system time library" +msgstr "ASN.1 -ის შეცდომა სისტემური დროის ბიბლიოთეკის გამოძახებისას" + +#: ../lib/krb5/error_tables/asn1_err.c:24 +msgid "ASN.1 structure is missing a required field" +msgstr "ASN.1 -ის სტრუქტურას აუცილებელი ველი აკლია" + +#: ../lib/krb5/error_tables/asn1_err.c:25 +msgid "ASN.1 unexpected field number" +msgstr "ASN.1 ველის მოულოდნელი ნომერი" + +#: ../lib/krb5/error_tables/asn1_err.c:26 +msgid "ASN.1 type numbers are inconsistent" +msgstr "ASN.1 ტიპის ნომრები არამდგრადია" + +#: ../lib/krb5/error_tables/asn1_err.c:27 +msgid "ASN.1 value too large" +msgstr "ASN.1 მნიშვნელობა ძალიან დიდია" + +#: ../lib/krb5/error_tables/asn1_err.c:28 +msgid "ASN.1 encoding ended unexpectedly" +msgstr "ASN.1 დაშიფვრა მოულოდნელად დასრულდა" + +#: ../lib/krb5/error_tables/asn1_err.c:29 +msgid "ASN.1 identifier doesn't match expected value" +msgstr "ASN.1 იდენტიფიკატორი მოსალოდნელ მნიშვნელობას არ ემთხვევა" + +#: ../lib/krb5/error_tables/asn1_err.c:30 +msgid "ASN.1 length doesn't match expected value" +msgstr "ASN.1 სიგრძე მოსალოდნელ მნიშვნელობას არ ემთხევა" + +#: ../lib/krb5/error_tables/asn1_err.c:31 +msgid "ASN.1 badly-formatted encoding" +msgstr "ASN.1 ცუდი ფორმატის მქონე დაშიფვრა" + +#: ../lib/krb5/error_tables/asn1_err.c:32 +msgid "ASN.1 parse error" +msgstr "ASN.1 დამუშავების შეცდომა" + +#: ../lib/krb5/error_tables/asn1_err.c:33 +msgid "ASN.1 bad return from gmtime" +msgstr "ASN.1 არასწორი დაბრუნება gmtime-დან" + +#: ../lib/krb5/error_tables/asn1_err.c:34 +msgid "ASN.1 indefinite encoding" +msgstr "ASN.1 დაუდგენელი დაშიფვრა" + +#: ../lib/krb5/error_tables/asn1_err.c:35 +msgid "ASN.1 missing expected EOC" +msgstr "ASN.1 აკლია მოსალოდნელი EOC" + +#: ../lib/krb5/error_tables/asn1_err.c:36 +msgid "ASN.1 object omitted in sequence" +msgstr "ASN.1 მიმდევრობაში ობიექტი ამოღებულია" + +#: ../lib/krb5/error_tables/kv5m_err.c:23 +msgid "Kerberos V5 magic number table" +msgstr "Kerberos V5 ჯადოსნური რიცხვების ცხრილი" + +#: ../lib/krb5/error_tables/kv5m_err.c:24 +msgid "Bad magic number for krb5_principal structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_principal" + +#: ../lib/krb5/error_tables/kv5m_err.c:25 +msgid "Bad magic number for krb5_data structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_data" + +#: ../lib/krb5/error_tables/kv5m_err.c:26 +msgid "Bad magic number for krb5_keyblock structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_keyblock" + +#: ../lib/krb5/error_tables/kv5m_err.c:27 +msgid "Bad magic number for krb5_checksum structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_checksum" + +#: ../lib/krb5/error_tables/kv5m_err.c:28 +msgid "Bad magic number for krb5_encrypt_block structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_encrypt_block" + +#: ../lib/krb5/error_tables/kv5m_err.c:29 +msgid "Bad magic number for krb5_enc_data structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_enc_data" + +#: ../lib/krb5/error_tables/kv5m_err.c:30 +msgid "Bad magic number for krb5_cryptosystem_entry structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_cryptosystem_entry" + +#: ../lib/krb5/error_tables/kv5m_err.c:31 +msgid "Bad magic number for krb5_cs_table_entry structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_cs_table_entry" + +#: ../lib/krb5/error_tables/kv5m_err.c:32 +msgid "Bad magic number for krb5_checksum_entry structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_checksum_entry" + +#: ../lib/krb5/error_tables/kv5m_err.c:33 +msgid "Bad magic number for krb5_authdata structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_authdata" + +#: ../lib/krb5/error_tables/kv5m_err.c:34 +msgid "Bad magic number for krb5_transited structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_tansited" + +#: ../lib/krb5/error_tables/kv5m_err.c:35 +msgid "Bad magic number for krb5_enc_tkt_part structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_enc_tkt_part" + +#: ../lib/krb5/error_tables/kv5m_err.c:36 +msgid "Bad magic number for krb5_ticket structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_ticket" + +#: ../lib/krb5/error_tables/kv5m_err.c:37 +msgid "Bad magic number for krb5_authenticator structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_authenticator" + +#: ../lib/krb5/error_tables/kv5m_err.c:38 +msgid "Bad magic number for krb5_tkt_authent structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_tkt_authent" + +#: ../lib/krb5/error_tables/kv5m_err.c:39 +msgid "Bad magic number for krb5_creds structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_creds" + +#: ../lib/krb5/error_tables/kv5m_err.c:40 +msgid "Bad magic number for krb5_last_req_entry structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_last_req_entry" + +#: ../lib/krb5/error_tables/kv5m_err.c:41 +msgid "Bad magic number for krb5_pa_data structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_enc_data" + +#: ../lib/krb5/error_tables/kv5m_err.c:42 +msgid "Bad magic number for krb5_kdc_req structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_kdc_req" + +#: ../lib/krb5/error_tables/kv5m_err.c:43 +msgid "Bad magic number for krb5_enc_kdc_rep_part structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_enc_kdc_rep_part" + +#: ../lib/krb5/error_tables/kv5m_err.c:44 +msgid "Bad magic number for krb5_kdc_rep structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_kdc_rep" + +#: ../lib/krb5/error_tables/kv5m_err.c:45 +msgid "Bad magic number for krb5_error structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_error" + +#: ../lib/krb5/error_tables/kv5m_err.c:46 +msgid "Bad magic number for krb5_ap_req structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_ap_req" + +#: ../lib/krb5/error_tables/kv5m_err.c:47 +msgid "Bad magic number for krb5_ap_rep structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_ap_rep" + +#: ../lib/krb5/error_tables/kv5m_err.c:48 +msgid "Bad magic number for krb5_ap_rep_enc_part structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_ap_rep_enc_part" + +#: ../lib/krb5/error_tables/kv5m_err.c:49 +msgid "Bad magic number for krb5_response structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_response" + +#: ../lib/krb5/error_tables/kv5m_err.c:50 +msgid "Bad magic number for krb5_safe structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_safe" + +#: ../lib/krb5/error_tables/kv5m_err.c:51 +msgid "Bad magic number for krb5_priv structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_priv" + +#: ../lib/krb5/error_tables/kv5m_err.c:52 +msgid "Bad magic number for krb5_priv_enc_part structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_priv_enc_part" + +#: ../lib/krb5/error_tables/kv5m_err.c:53 +msgid "Bad magic number for krb5_cred structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_cred" + +#: ../lib/krb5/error_tables/kv5m_err.c:54 +msgid "Bad magic number for krb5_cred_info structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_cred_info" + +#: ../lib/krb5/error_tables/kv5m_err.c:55 +msgid "Bad magic number for krb5_cred_enc_part structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_cred_enc_part" + +#: ../lib/krb5/error_tables/kv5m_err.c:56 +msgid "Bad magic number for krb5_pwd_data structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_pwd_data" + +#: ../lib/krb5/error_tables/kv5m_err.c:57 +msgid "Bad magic number for krb5_address structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_address" + +#: ../lib/krb5/error_tables/kv5m_err.c:58 +msgid "Bad magic number for krb5_keytab_entry structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_keytab_entry" + +#: ../lib/krb5/error_tables/kv5m_err.c:59 +msgid "Bad magic number for krb5_context structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_context" + +#: ../lib/krb5/error_tables/kv5m_err.c:60 +msgid "Bad magic number for krb5_os_context structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_os_context" + +#: ../lib/krb5/error_tables/kv5m_err.c:61 +msgid "Bad magic number for krb5_alt_method structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_alt_method" + +#: ../lib/krb5/error_tables/kv5m_err.c:62 +msgid "Bad magic number for krb5_etype_info_entry structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_etype_info_entry" + +#: ../lib/krb5/error_tables/kv5m_err.c:63 +msgid "Bad magic number for krb5_db_context structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_db_context" + +#: ../lib/krb5/error_tables/kv5m_err.c:64 +msgid "Bad magic number for krb5_auth_context structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_auth_context" + +#: ../lib/krb5/error_tables/kv5m_err.c:65 +msgid "Bad magic number for krb5_keytab structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_keytab" + +#: ../lib/krb5/error_tables/kv5m_err.c:66 +msgid "Bad magic number for krb5_rcache structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_rcache" + +#: ../lib/krb5/error_tables/kv5m_err.c:67 +msgid "Bad magic number for krb5_ccache structure" +msgstr "არასწორი ჯადოსნური რიცხვი სტრუქტურისთვის krb5_ccache" + +#: ../lib/krb5/error_tables/kv5m_err.c:68 +msgid "Bad magic number for krb5_preauth_ops" +msgstr "არასწორი ჯადოსნური რიცხვი krb_preauth_ops -სთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:69 +msgid "Bad magic number for krb5_sam_challenge" +msgstr "არასწორი ჯადოსნური რიცხვი krb5_sam_challenge-სთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:70 +msgid "Bad magic number for krb5_sam_challenge_2" +msgstr "არასწორი ჯადოსნური რიცხვი krb5_sam_challenge_2-სთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:71 +msgid "Bad magic number for krb5_sam_key" +msgstr "არასწორი ჯადოსნური რიცხვი krb5_sam_key-სთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:72 +#: ../lib/krb5/error_tables/kv5m_err.c:73 +msgid "Bad magic number for krb5_enc_sam_response_enc" +msgstr "არასწორი ჯადოსნური რიცხვი krb5_enc_sam_reponse_enc-სთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:74 +msgid "Bad magic number for krb5_sam_response" +msgstr "არასწორი ჯადოსნური რიცხვი krb5_sam_response-სთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:75 +msgid "Bad magic number for krb5_sam_response 2" +msgstr "არასწორი ჯადოსნური რიცხვი krb5_sam_response 2-სთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:76 +msgid "Bad magic number for krb5_predicted_sam_response" +msgstr "არასწორი ჯადოსნური რიცხვი krb5_predicted_sam_reponse-სთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:77 +msgid "Bad magic number for passwd_phrase_element" +msgstr "არასწორი ჯადოსნური რიცხვი passwd_phrase_element-სთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:78 +msgid "Bad magic number for GSSAPI OID" +msgstr "არასწორი ჯადოსნური რიცხვი GSSAPI OID-სთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:79 +msgid "Bad magic number for GSSAPI QUEUE" +msgstr "არასწორი ჯადოსნური რიცხვი GSSAPI QUEUE-სთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:80 +msgid "Bad magic number for fast armored request" +msgstr "არასწორი ჯადოსნური რიცხვი სწრაფი დაჯავშნული მოთხოვნისთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:81 +msgid "Bad magic number for FAST request" +msgstr "არასწორი ჯადოსნური რიცხვი სწრაფი მოთხოვნისთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:82 +msgid "Bad magic number for FAST response" +msgstr "არასწორი ჯადოსნური რიცხვი სწრაფი პასუხისთვის" + +#: ../lib/krb5/error_tables/kv5m_err.c:83 +msgid "Bad magic number for krb5_authdata_context" +msgstr "არასწორი ჯადოსნური რიცხვი krb5_authdata_context-სთვის" + +#: ../lib/krb5/error_tables/krb524_err.c:23 +msgid "Cannot convert V5 keyblock" +msgstr "გადაყვანა შეუძლებელია V5 keyblock" + +#: ../lib/krb5/error_tables/krb524_err.c:24 +msgid "Cannot convert V5 address information" +msgstr "გადაყვანა შეუძლებელია V5 მისამართის ინფორმაცია" + +#: ../lib/krb5/error_tables/krb524_err.c:25 +msgid "Cannot convert V5 principal" +msgstr "გადაყვანა შეუძლებელია V5 პრინციპალი" + +#: ../lib/krb5/error_tables/krb524_err.c:26 +msgid "V5 realm name longer than V4 maximum" +msgstr "V5 რეალმის სახელი V4-ის მაქსიმუმზე გრძელია" + +#: ../lib/krb5/error_tables/krb524_err.c:27 +msgid "Kerberos V4 error" +msgstr "Kerberos V4 -ის შეცდომა" + +#: ../lib/krb5/error_tables/krb524_err.c:28 +msgid "Encoding too large" +msgstr "დაშიფვრა ძალიან დიდია" + +#: ../lib/krb5/error_tables/krb524_err.c:29 +msgid "Decoding out of data" +msgstr "დეკოდერს მონაცემები არ ყოფნის" + +#: ../lib/krb5/error_tables/krb524_err.c:30 +msgid "Service not responding" +msgstr "სერვისი არ პასუხობს" + +#: ../lib/krb5/error_tables/krb524_err.c:31 +msgid "Kerberos version 4 support is disabled" +msgstr "Kerberos ვერსია 4 -ის მხარდაჭერა გათიშულია" diff --git a/krb5-1.21.3/src/po/mit-krb5.pot b/krb5-1.21.3/src/po/mit-krb5.pot new file mode 100644 index 00000000..52a3fb78 --- /dev/null +++ b/krb5-1.21.3/src/po/mit-krb5.pot @@ -0,0 +1,8855 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR MIT +# This file is distributed under the same license as the mit-krb5 package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: mit-krb5 1.21.3\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-06-26 13:09-0400\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +#: ../../src/clients/kdestroy/kdestroy.c:52 +#, c-format +msgid "Usage: %s [-A] [-q] [-c cache_name] [-p princ_name]\n" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:54 +#, c-format +msgid "\t-A destroy all credential caches in collection\n" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:55 +#, c-format +msgid "\t-q quiet mode\n" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:56 +#: ../../src/clients/kswitch/kswitch.c:42 +#, c-format +msgid "\t-c specify name of credentials cache\n" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:57 +#, c-format +msgid "\t-p specify principal name within collection\n" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:71 +#: ../../src/clients/kdestroy/kdestroy.c:165 +msgid "while listing credential caches" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:78 +#, c-format +msgid "Other credential caches present, use -A to destroy all\n" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:110 +#: ../../src/clients/kinit/kinit.c:332 ../../src/clients/ksu/main.c:296 +#, c-format +msgid "Only one -c option allowed\n" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:118 +#, c-format +msgid "Only one -p option allowed\n" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:125 +#: ../../src/clients/kinit/kinit.c:360 ../../src/clients/klist/klist.c:178 +#, c-format +msgid "Kerberos 4 is no longer supported\n" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:138 +#, c-format +msgid "-A option is exclusive with -p option\n" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:150 +#: ../../src/clients/klist/klist.c:241 ../../src/clients/ksu/main.c:135 +#: ../../src/clients/ksu/main.c:141 ../../src/clients/kswitch/kswitch.c:94 +#: ../../src/kadmin/ktutil/ktutil.c:52 ../../src/kdc/main.c:925 +#: ../../src/kprop/kprop.c:103 ../../src/kprop/kpropd.c:1059 +msgid "while initializing krb5" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:157 +#: ../../src/clients/klist/klist.c:248 +msgid "while setting default cache name" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:172 +msgid "composing ccache name" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:177 +#, c-format +msgid "while destroying cache %s" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:190 +#: ../../src/clients/kswitch/kswitch.c:107 ../../src/clients/kvno/kvno.c:316 +#: ../../src/clients/kvno/kvno.c:522 ../../src/kadmin/cli/keytab.c:373 +#: ../../src/kadmin/dbutil/kdb5_util.c:544 +#, c-format +msgid "while parsing principal name %s" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:196 +#, c-format +msgid "while finding cache for %s" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:204 +#: ../../src/clients/klist/klist.c:462 +msgid "while resolving ccache" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:211 ../../src/clients/ksu/main.c:1026 +msgid "while destroying cache" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:214 +#, c-format +msgid "Ticket cache NOT destroyed!\n" +msgstr "" + +#: ../../src/clients/kdestroy/kdestroy.c:216 +#, c-format +msgid "Ticket cache %cNOT%c destroyed!\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:143 +#, c-format +msgid "" +"Usage: %s [-V] [-l lifetime] [-s start_time] [-r renewable_life]\n" +"\t[-f | -F] [-p | -P] [-n] [-a | -A] [-C] [-E]\n" +"\t[--request-pac | --no-request-pac]\n" +"\t[-v] [-R] [-k [-i|-t keytab_file]] [-c cachename]\n" +"\t[-S service_name] [-I input_ccache] [-T ticket_armor_cache]\n" +"\t[-X [=]] [principal]\n" +"\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:153 +#, c-format +msgid "\t-V verbose\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:154 +#, c-format +msgid "\t-l lifetime\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:155 +#, c-format +msgid "\t-s start time\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:156 +#, c-format +msgid "\t-r renewable lifetime\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:157 +#, c-format +msgid "\t-f forwardable\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:158 +#, c-format +msgid "\t-F not forwardable\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:159 +#, c-format +msgid "\t-p proxiable\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:160 +#, c-format +msgid "\t-P not proxiable\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:161 +#, c-format +msgid "\t-n anonymous\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:162 +#, c-format +msgid "\t-a include addresses\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:163 +#, c-format +msgid "\t-A do not include addresses\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:164 +#, c-format +msgid "\t-v validate\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:165 +#, c-format +msgid "\t-R renew\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:166 +#, c-format +msgid "\t-C canonicalize\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:167 +#, c-format +msgid "\t-E client is enterprise principal name\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:168 +#, c-format +msgid "\t-k use keytab\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:169 +#, c-format +msgid "\t-i use default client keytab (with -k)\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:170 +#, c-format +msgid "\t-t filename of keytab to use\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:171 +#, c-format +msgid "\t-c Kerberos 5 cache name\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:172 +#, c-format +msgid "\t-S service\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:173 +#, c-format +msgid "\t-I input credential cache\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:174 +#, c-format +msgid "\t-T armor credential cache\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:175 +#, c-format +msgid "\t-X [=]\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:177 +#, c-format +msgid "\t--{,no}-request-pac request KDC include/exclude a PAC\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:250 ../../src/clients/kinit/kinit.c:258 +#, c-format +msgid "Bad lifetime value %s\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:292 +#, c-format +msgid "Bad start time value %s\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:310 +#, c-format +msgid "Only one -t option allowed.\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:318 +#, c-format +msgid "Only one armor_ccache\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:340 +#, c-format +msgid "Only one -I option allowed\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:349 +msgid "while adding preauth option" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:375 +#, c-format +msgid "Only one of -f and -F allowed\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:379 +#, c-format +msgid "Only one of -p and -P allowed\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:383 +#, c-format +msgid "Only one of --request-pac and --no-request-pac allowed\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:388 +#, c-format +msgid "Only one of -a and -A allowed\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:392 +#, c-format +msgid "Only one of -t and -i allowed\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:398 +#, c-format +msgid "keytab specified, forcing -k\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:401 ../../src/clients/klist/klist.c:216 +#, c-format +msgid "Extra arguments (starting with \"%s\").\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:427 +msgid "while initializing Kerberos 5 library" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:435 ../../src/clients/kinit/kinit.c:578 +#, c-format +msgid "resolving ccache %s" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:440 +#, c-format +msgid "Using specified cache: %s\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:448 +msgid "while getting default ccache" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:462 ../../src/clients/kinit/kinit.c:530 +#: ../../src/clients/kpasswd/kpasswd.c:30 ../../src/clients/ksu/main.c:249 +#, c-format +msgid "when parsing name %s" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:470 ../../src/kadmin/dbutil/kdb5_util.c:309 +#: ../../src/kprop/kprop.c:157 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:395 +msgid "while getting default realm" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:481 +msgid "while building principal" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:489 +msgid "When resolving the default client keytab" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:496 +msgid "When determining client principal name from keytab" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:505 +msgid "when creating default server principal name" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:525 ../../src/clients/kpasswd/kpasswd.c:43 +#, c-format +msgid "Unable to identify user\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:539 ../../src/clients/kswitch/kswitch.c:113 +#, c-format +msgid "while searching for ccache for %s" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:545 +#, c-format +msgid "Using existing cache: %s\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:554 +msgid "while generating new ccache" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:558 +#, c-format +msgid "Using new cache: %s\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:570 +#, c-format +msgid "Using default cache: %s\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:583 +#, c-format +msgid "Using specified input cache: %s\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:590 ../../src/clients/ksu/krb_auth_su.c:160 +msgid "when unparsing name" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:594 +#, c-format +msgid "Using principal: %s\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:677 +msgid "getting local addresses" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:701 +#, c-format +msgid "while setting up KDB keytab for realm %s" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:710 ../../src/clients/kvno/kvno.c:513 +#, c-format +msgid "resolving keytab %s" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:715 +#, c-format +msgid "Using keytab: %s\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:719 +msgid "resolving default client keytab" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:729 +#, c-format +msgid "while setting '%s'='%s'" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:734 +#, c-format +msgid "PA Option %s = %s\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:775 +msgid "getting initial credentials" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:778 +msgid "validating credentials" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:781 +msgid "renewing credentials" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:789 +#, c-format +msgid "%s: Password incorrect while %s\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:792 +#, c-format +msgid "while %s" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:803 +msgid "when creating temporary cache" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:807 +#, c-format +msgid "Initialized cache\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:811 +msgid "while storing credentials" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:816 +#, c-format +msgid "while saving to cache %s" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:822 +#, c-format +msgid "Stored credentials\n" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:828 +msgid "while switching to new ccache" +msgstr "" + +#: ../../src/clients/kinit/kinit.c:885 +#, c-format +msgid "Authenticated to Kerberos v5\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:85 +#, c-format +msgid "" +"Usage: %s [-e] [-V] [[-c] [-l] [-A] [-d] [-f] [-s] [-a [-n]]] [-k [-i] [-t] " +"[-K]] [-C] [name]\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:88 +#, c-format +msgid "\t-c specifies credentials cache\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:89 +#, c-format +msgid "\t-k specifies keytab\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:90 +#, c-format +msgid "\t (Default is credentials cache)\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:91 +#, c-format +msgid "\t-i uses default client keytab if no name given\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:92 +#, c-format +msgid "\t-l lists credential caches in collection\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:93 +#, c-format +msgid "\t-A shows content of all credential caches\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:94 +#, c-format +msgid "\t-e shows the encryption type\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:95 +#, c-format +msgid "\t-V shows the Kerberos version and exits\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:96 +#, c-format +msgid "\toptions for credential caches:\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:97 +#, c-format +msgid "\t\t-d shows the submitted authorization data types\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:99 +#, c-format +msgid "\t\t-f shows credentials flags\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:100 +#, c-format +msgid "\t\t-s sets exit status based on valid tgt existence\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:102 +#, c-format +msgid "\t\t-a displays the address list\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:103 +#, c-format +msgid "\t\t\t-n do not reverse-resolve\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:104 +#, c-format +msgid "\toptions for keytabs:\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:105 +#, c-format +msgid "\t\t-t shows keytab entry timestamps\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:106 +#, c-format +msgid "\t\t-K shows keytab entry keys\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:107 +#, c-format +msgid "\t\t-C includes configuration data entries\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:225 +#, c-format +msgid "%s version %s\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:278 +msgid "while getting default client keytab" +msgstr "" + +#: ../../src/clients/klist/klist.c:284 +msgid "while getting default keytab" +msgstr "" + +#: ../../src/clients/klist/klist.c:290 ../../src/kadmin/cli/keytab.c:103 +#, c-format +msgid "while resolving keytab %s" +msgstr "" + +#: ../../src/clients/klist/klist.c:297 ../../src/kadmin/cli/keytab.c:87 +msgid "while getting keytab name" +msgstr "" + +#: ../../src/clients/klist/klist.c:305 ../../src/kadmin/cli/keytab.c:422 +msgid "while starting keytab scan" +msgstr "" + +#: ../../src/clients/klist/klist.c:328 ../../src/clients/klist/klist.c:484 +#: ../../src/clients/ksu/ccache.c:455 ../../src/kadmin/dbutil/dump.c:487 +#: ../../src/kadmin/dbutil/tabdump.c:549 +msgid "while unparsing principal name" +msgstr "" + +#: ../../src/clients/klist/klist.c:350 ../../src/kadmin/cli/keytab.c:466 +msgid "while scanning keytab" +msgstr "" + +#: ../../src/clients/klist/klist.c:355 ../../src/kadmin/cli/keytab.c:471 +msgid "while ending keytab scan" +msgstr "" + +#: ../../src/clients/klist/klist.c:372 ../../src/clients/klist/klist.c:435 +msgid "while listing ccache collection" +msgstr "" + +#: ../../src/clients/klist/klist.c:411 +msgid "(Expired)" +msgstr "" + +#: ../../src/clients/klist/klist.c:488 +#, c-format +msgid "" +"Ticket cache: %s:%s\n" +"Default principal: %s\n" +"\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:500 +msgid "while starting to retrieve tickets" +msgstr "" + +#: ../../src/clients/klist/klist.c:514 +msgid "while finishing ticket retrieval" +msgstr "" + +#: ../../src/clients/klist/klist.c:519 +msgid "while retrieving a ticket" +msgstr "" + +#: ../../src/clients/klist/klist.c:674 ../../src/clients/ksu/ccache.c:440 +#: ../../src/kprop/kpropd.c:1206 ../../src/kprop/kpropd.c:1271 +msgid "while unparsing client name" +msgstr "" + +#: ../../src/clients/klist/klist.c:679 ../../src/clients/ksu/ccache.c:445 +#: ../../src/kprop/kprop.c:191 +msgid "while unparsing server name" +msgstr "" + +#: ../../src/clients/klist/klist.c:710 ../../src/clients/ksu/ccache.c:470 +#, c-format +msgid "\tfor client %s" +msgstr "" + +#: ../../src/clients/klist/klist.c:722 ../../src/clients/ksu/ccache.c:479 +msgid "renew until " +msgstr "" + +#: ../../src/clients/klist/klist.c:734 ../../src/clients/ksu/ccache.c:489 +#, c-format +msgid "Flags: %s" +msgstr "" + +#: ../../src/clients/klist/klist.c:749 +#, c-format +msgid "Etype (skey, tkt): %s, " +msgstr "" + +#: ../../src/clients/klist/klist.c:761 +#, c-format +msgid "AD types: " +msgstr "" + +#: ../../src/clients/klist/klist.c:777 +#, c-format +msgid "\tAddresses: (none)\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:779 +#, c-format +msgid "\tAddresses: " +msgstr "" + +#: ../../src/clients/klist/klist.c:797 +msgid "while unparsing ticket server name" +msgstr "" + +#: ../../src/clients/klist/klist.c:800 +#, c-format +msgid "\tTicket server: %s\n" +msgstr "" + +#: ../../src/clients/klist/klist.c:828 ../../src/clients/klist/klist.c:838 +#, c-format +msgid "broken address (type %d length %d)" +msgstr "" + +#: ../../src/clients/klist/klist.c:847 +#, c-format +msgid "unknown addrtype %d" +msgstr "" + +#: ../../src/clients/klist/klist.c:856 +#, c-format +msgid "unprintable address (type %d, error %d %s)" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:13 ../../src/lib/krb5/krb/gic_pwd.c:288 +msgid "Enter new password" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:14 ../../src/lib/krb5/krb/gic_pwd.c:296 +msgid "Enter it again" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:34 +#, c-format +msgid "Unable to identify user from password file\n" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:64 +#, c-format +msgid "usage: %s [principal]\n" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:72 +msgid "initializing kerberos library" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:77 +msgid "allocating krb5_get_init_creds_opt" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:93 +msgid "opening default ccache" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:98 +msgid "getting principal from ccache" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:103 +msgid "while setting FAST ccache" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:109 +msgid "closing ccache" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:117 +msgid "parsing client name" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:135 +msgid "Password incorrect while getting initial ticket" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:137 +msgid "getting initial ticket" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:147 +msgid "while reading password" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:155 +msgid "changing password" +msgstr "" + +#: ../../src/clients/kpasswd/kpasswd.c:175 +#: ../lib/kadm5/chpass_util_strings.c:30 +#, c-format +msgid "Password changed.\n" +msgstr "" + +#: ../../src/clients/ksu/authorization.c:352 +#, c-format +msgid "" +"Error: bad entry - %s in %s file, must be either full path or just the cmd " +"name\n" +msgstr "" + +#: ../../src/clients/ksu/authorization.c:360 +#, c-format +msgid "" +"Error: bad entry - %s in %s file, since %s is just the cmd name, CMD_PATH " +"must be defined \n" +msgstr "" + +#: ../../src/clients/ksu/authorization.c:375 +#, c-format +msgid "Error: bad entry - %s in %s file, CMD_PATH contains no paths \n" +msgstr "" + +#: ../../src/clients/ksu/authorization.c:384 +#, c-format +msgid "Error: bad path %s in CMD_PATH for %s must start with '/' \n" +msgstr "" + +#: ../../src/clients/ksu/authorization.c:500 +msgid "Error: not found -> " +msgstr "" + +#: ../../src/clients/ksu/authorization.c:706 +#, c-format +msgid "home directory name `%s' too long, can't search for .k5login\n" +msgstr "" + +#: ../../src/clients/ksu/ccache.c:358 +#, c-format +msgid "home directory path for %s too long\n" +msgstr "" + +#: ../../src/clients/ksu/ccache.c:451 +msgid "while retrieving principal name" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:57 +#: ../../src/clients/ksu/krb_auth_su.c:62 +msgid "while copying client principal" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:69 +msgid "while creating tgt for local realm" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:84 +msgid "while retrieving creds from cache" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:95 +msgid "while switching to target uid" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:100 +#, c-format +msgid "" +"WARNING: Your password may be exposed if you enter it here and are logged \n" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:102 +#, c-format +msgid " in remotely using an unsecure (non-encrypted) channel. \n" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:114 ../../src/clients/ksu/main.c:481 +msgid "while reclaiming root uid" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:121 +#, c-format +msgid "does not have any appropriate tickets in the cache.\n" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:133 +msgid "while verifying ticket for server" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:167 +msgid "while getting time of day" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:171 +#, c-format +msgid "Kerberos password for %s: " +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:175 +#, c-format +msgid "principal name %s too long for internal buffer space\n" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:184 +#, c-format +msgid "while reading password for '%s'\n" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:190 +#, c-format +msgid "No password given\n" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:203 +#, c-format +msgid "%s: Password incorrect\n" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:205 +msgid "while getting initial credentials" +msgstr "" + +#: ../../src/clients/ksu/krb_auth_su.c:225 +#: ../../src/clients/ksu/krb_auth_su.c:239 +#, c-format +msgid " %s while unparsing name\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:69 +#, c-format +msgid "" +"Usage: %s [target user] [-n principal] [-c source cachename] [-k] [-r time] " +"[-p|-P] [-f|-F] [-l lifetime] [-zZ] [-q] [-e command [args... ] ] [-a " +"[args... ] ]\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:151 +msgid "" +"program name too long - quitting to avoid triggering system logging bugs" +msgstr "" + +#: ../../src/clients/ksu/main.c:177 +msgid "while allocating memory" +msgstr "" + +#: ../../src/clients/ksu/main.c:190 +msgid "while setting euid to source user" +msgstr "" + +#: ../../src/clients/ksu/main.c:201 ../../src/clients/ksu/main.c:242 +#, c-format +msgid "Bad lifetime value (%s hours?)\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:213 ../../src/clients/ksu/main.c:304 +msgid "when gathering parameters" +msgstr "" + +#: ../../src/clients/ksu/main.c:263 +#, c-format +msgid "-z option is mutually exclusive with -Z.\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:271 +#, c-format +msgid "-Z option is mutually exclusive with -z.\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:284 +#, c-format +msgid "while looking for credentials cache %s" +msgstr "" + +#: ../../src/clients/ksu/main.c:290 +#, c-format +msgid "malformed credential cache name %s\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:348 +#, c-format +msgid "ksu: who are you?\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:352 +#, c-format +msgid "Your uid doesn't match your passwd entry?!\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:367 +#, c-format +msgid "ksu: unknown login %s\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:387 +msgid "while getting source cache" +msgstr "" + +#: ../../src/clients/ksu/main.c:396 +msgid "while selecting the best principal" +msgstr "" + +#: ../../src/clients/ksu/main.c:404 +msgid "while returning to source uid after finding best principal" +msgstr "" + +#: ../../src/clients/ksu/main.c:424 +#, c-format +msgid "account %s: authorization failed\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:459 +msgid "while parsing temporary name" +msgstr "" + +#: ../../src/clients/ksu/main.c:464 +msgid "while creating temporary cache" +msgstr "" + +#: ../../src/clients/ksu/main.c:470 ../../src/clients/ksu/main.c:710 +#, c-format +msgid "while copying cache %s to %s" +msgstr "" + +#: ../../src/clients/ksu/main.c:488 +#, c-format +msgid "" +"WARNING: Your password may be exposed if you enter it here and are logged\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:490 +#, c-format +msgid " in remotely using an unsecure (non-encrypted) channel.\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:496 +#, c-format +msgid "Goodbye\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:500 +#, c-format +msgid "Could not get a tgt for " +msgstr "" + +#: ../../src/clients/ksu/main.c:522 +#, c-format +msgid "Authentication failed.\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:530 +msgid "When unparsing name" +msgstr "" + +#: ../../src/clients/ksu/main.c:534 +#, c-format +msgid "Authenticated %s\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:541 +msgid "while switching to target for authorization check" +msgstr "" + +#: ../../src/clients/ksu/main.c:548 +msgid "while checking authorization" +msgstr "" + +#: ../../src/clients/ksu/main.c:554 +msgid "while switching back from target after authorization check" +msgstr "" + +#: ../../src/clients/ksu/main.c:561 +#, c-format +msgid "Account %s: authorization for %s for execution of\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:563 +#, c-format +msgid " %s successful\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:569 +#, c-format +msgid "Account %s: authorization for %s successful\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:581 +#, c-format +msgid "Account %s: authorization for %s for execution of %s failed\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:589 +#, c-format +msgid "Account %s: authorization of %s failed\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:604 +msgid "while calling cc_filter" +msgstr "" + +#: ../../src/clients/ksu/main.c:612 +msgid "while erasing target cache" +msgstr "" + +#: ../../src/clients/ksu/main.c:632 +#, c-format +msgid "ksu: permission denied (shell).\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:641 +#, c-format +msgid "ksu: couldn't set environment variable USER\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:647 +#, c-format +msgid "ksu: couldn't set environment variable HOME\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:652 +#, c-format +msgid "ksu: couldn't set environment variable SHELL\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:663 +#, c-format +msgid "ksu: initgroups failed.\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:668 +#, c-format +msgid "Leaving uid as %s (%ld)\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:671 +#, c-format +msgid "Changing uid to %s (%ld)\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:697 +msgid "while getting name of target ccache" +msgstr "" + +#: ../../src/clients/ksu/main.c:717 +#, c-format +msgid "%s does not have correct permissions for %s, %s aborted" +msgstr "" + +#: ../../src/clients/ksu/main.c:738 +#, c-format +msgid "Internal error: command %s did not get resolved\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:755 ../../src/clients/ksu/main.c:791 +#, c-format +msgid "while trying to execv %s" +msgstr "" + +#: ../../src/clients/ksu/main.c:781 +msgid "while calling waitpid" +msgstr "" + +#: ../../src/clients/ksu/main.c:786 +msgid "while trying to fork." +msgstr "" + +#: ../../src/clients/ksu/main.c:836 +msgid "while reading cache name from ccache" +msgstr "" + +#: ../../src/clients/ksu/main.c:842 +#, c-format +msgid "ksu: couldn't set environment variable %s\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:868 +msgid "while resetting target ccache name" +msgstr "" + +#: ../../src/clients/ksu/main.c:882 +msgid "while determining target ccache name" +msgstr "" + +#: ../../src/clients/ksu/main.c:921 +msgid "while generating part of the target ccache name" +msgstr "" + +#: ../../src/clients/ksu/main.c:927 +msgid "while allocating memory for the target ccache name" +msgstr "" + +#: ../../src/clients/ksu/main.c:946 +msgid "while creating new target ccache" +msgstr "" + +#: ../../src/clients/ksu/main.c:952 +msgid "while initializing target cache" +msgstr "" + +#: ../../src/clients/ksu/main.c:992 +#, c-format +msgid "terminal name %s too long\n" +msgstr "" + +#: ../../src/clients/ksu/main.c:1020 +msgid "while changing to target uid for destroying ccache" +msgstr "" + +#: ../../src/clients/kswitch/kswitch.c:41 +#, c-format +msgid "Usage: %s {-c cache_name | -p principal}\n" +msgstr "" + +#: ../../src/clients/kswitch/kswitch.c:43 +#, c-format +msgid "\t-p specify name of principal\n" +msgstr "" + +#: ../../src/clients/kswitch/kswitch.c:66 +#, c-format +msgid "Only one -c or -p option allowed\n" +msgstr "" + +#: ../../src/clients/kswitch/kswitch.c:85 +#, c-format +msgid "One of -c or -p must be specified\n" +msgstr "" + +#: ../../src/clients/kswitch/kswitch.c:101 +#, c-format +msgid "while resolving %s" +msgstr "" + +#: ../../src/clients/kswitch/kswitch.c:122 +msgid "while switching to credential cache" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:44 +#, c-format +msgid "" +"usage: %s [-c ccache] [-e etype] [-k keytab] [-q] [-u | -S sname]\n" +"\t[[{-F cert_file | {-I | -U} for_user} [-P]] | --u2u ccache]\n" +"\t[--cached-only] [--no-store] [--out-cache] service1 service2 ...\n" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:117 ../../src/clients/kvno/kvno.c:125 +#, c-format +msgid "Options -u and -S are mutually exclusive\n" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:159 +#, c-format +msgid "Options --u2u and -I|-U|-F are mutually exclusive\n" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:165 +#, c-format +msgid "" +"Option -P (constrained delegation) requires option -I|-U|-F (protocol " +"transition)\n" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:240 +msgid "No begin line not found" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:252 +msgid "No end line found" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:263 +msgid "Unexpected header line" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:278 +msgid "Invalid base64" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:324 +#, c-format +msgid "while formatting parsed principal name for '%s'" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:338 +msgid "client and server principal names must match" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:354 +#, c-format +msgid "while getting credentials for %s" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:361 +#, c-format +msgid "while decoding ticket for %s" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:372 +#, c-format +msgid "while decrypting ticket for %s" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:376 +#, c-format +msgid "%s: kvno = %d, keytab entry valid\n" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:381 +#, c-format +msgid "%s: kvno = %d\n" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:396 +#, c-format +msgid "%s: constrained delegation failed" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:479 ../../src/kadmin/cli/kadmin.c:311 +msgid "while initializing krb5 library" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:486 +msgid "while converting etype" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:498 +msgid "while opening ccache" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:505 +msgid "while resolving output ccache" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:530 +#, c-format +msgid "while reading certificate file %s" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:540 +#, c-format +msgid "while getting user-to-user ticket from %s" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:549 +msgid "while getting client principal name" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:556 +msgid "while creating temporary output ccache" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:570 +msgid "while initializing output ccache" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:580 +msgid "while storing creds in output ccache" +msgstr "" + +#: ../../src/clients/kvno/kvno.c:591 +msgid "while writing output ccache" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:103 +#, c-format +msgid "" +"Usage: %s [-r realm] [-p principal] [-q query] [clnt|local args]\n" +" [command args...]\n" +"\tclnt args: [-s admin_server[:port]] [[-c ccache]|[-k [-t keytab]]]|[-n] [-" +"O | -N]\n" +"\tlocal args: [-x db_args]* [-d dbname] [-e \"enc:salt ...\"] [-m] [-w " +"password] where,\n" +"\t[-x db_args]* - any number of database specific arguments.\n" +"\t\t\tLook at each database documentation for supported arguments\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:164 +#, c-format +msgid "Invalid date specification \"%s\".\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:192 +#, c-format +msgid "Interval specification \"%s\" is in the past.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:322 ../../src/kadmin/cli/kadmin.c:361 +#, c-format +msgid "%s: Cannot initialize. Not enough memory\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:380 ../../src/kadmin/cli/kadmin.c:840 +#: ../../src/kadmin/cli/kadmin.c:1109 ../../src/kadmin/cli/kadmin.c:1630 +#: ../../src/kadmin/cli/keytab.c:148 ../../src/kadmin/dbutil/kdb5_util.c:559 +#, c-format +msgid "while parsing keysalts %s" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:403 +#, c-format +msgid "%s: -q is exclusive with command-line query" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:411 +#, c-format +msgid "%s: unable to get default realm\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:431 +msgid "while opening default credentials cache" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:437 +#, c-format +msgid "while opening credentials cache %s" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:459 ../../src/kadmin/cli/kadmin.c:513 +#: ../../src/kadmin/cli/kadmin.c:521 ../../src/kadmin/cli/kadmin.c:528 +#, c-format +msgid "%s: out of memory\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:468 ../../src/kadmin/cli/kadmin.c:483 +#: ../../src/kprop/kpropd.c:677 +msgid "while canonicalizing principal name" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:477 +msgid "creating host service principal" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:490 +#, c-format +msgid "%s: unable to canonicalize principal\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:533 +#, c-format +msgid "%s: unable to figure out a principal name\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:540 +msgid "while setting up logging" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:549 +#, c-format +msgid "Authenticating as principal %s with existing credentials.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:555 +#, c-format +msgid "Authenticating as principal %s with password; anonymous requested.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:562 +#, c-format +msgid "Authenticating as principal %s with keytab %s.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:565 +#, c-format +msgid "Authenticating as principal %s with default keytab.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:572 +#, c-format +msgid "Authenticating as principal %s with password.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:580 ../../src/kprop/kpropd.c:722 +#, c-format +msgid "while initializing %s interface" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:595 +#, c-format +msgid "while closing ccache %s" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:601 +msgid "while mapping update log" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:617 +msgid "while unlocking locked database" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:626 +msgid "Administration credentials NOT DESTROYED.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:675 +msgid "usage: delete_principal [-force] principal\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:680 ../../src/kadmin/cli/kadmin.c:859 +msgid "while parsing principal name" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:686 ../../src/kadmin/cli/kadmin.c:865 +#: ../../src/kadmin/cli/kadmin.c:1218 ../../src/kadmin/cli/kadmin.c:1343 +#: ../../src/kadmin/cli/kadmin.c:1413 ../../src/kadmin/cli/kadmin.c:1853 +#: ../../src/kadmin/cli/kadmin.c:1897 ../../src/kadmin/cli/kadmin.c:1943 +#: ../../src/kadmin/cli/kadmin.c:1983 +msgid "while canonicalizing principal" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:690 +#, c-format +msgid "Are you sure you want to delete the principal \"%s\"? (yes/no): " +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:694 +#, c-format +msgid "Principal \"%s\" not deleted\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:701 +#, c-format +msgid "while deleting principal \"%s\"" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:704 +#, c-format +msgid "Principal \"%s\" deleted.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:705 +msgid "" +"Make sure that you have removed this principal from all ACLs before " +"reusing.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:722 +msgid "usage: rename_principal [-force] old_principal new_principal\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:729 +msgid "while parsing old principal name" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:735 +msgid "while parsing new principal name" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:741 +msgid "while canonicalizing old principal" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:747 +msgid "while canonicalizing new principal" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:751 +#, c-format +msgid "" +"Are you sure you want to rename the principal \"%s\" to \"%s\"? (yes/no): " +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:755 +#, c-format +msgid "Principal \"%s\" not renamed\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:762 +#, c-format +msgid "while renaming principal \"%s\" to \"%s\"" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:766 +#, c-format +msgid "Principal \"%s\" renamed to \"%s\".\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:767 +msgid "" +"Make sure that you have removed the old principal from all ACLs before " +"reusing.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:782 +msgid "" +"usage: change_password [-randkey] [-keepold] [-e keysaltlist] [-pw password] " +"principal\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:808 +msgid "change_password: missing db argument" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:814 +msgid "change_password: Not enough memory\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:822 +msgid "change_password: missing password arg" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:833 +msgid "change_password: missing keysaltlist arg" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:844 +#, c-format +msgid "unrecognized option %s" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:851 +msgid "missing principal name" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:853 +msgid "too many arguments" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:877 ../../src/kadmin/cli/kadmin.c:914 +#, c-format +msgid "while changing password for \"%s\"." +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:880 ../../src/kadmin/cli/kadmin.c:917 +#, c-format +msgid "Password for \"%s\" changed.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:886 ../../src/kadmin/cli/kadmin.c:1294 +#, c-format +msgid "while randomizing key for \"%s\"." +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:889 +#, c-format +msgid "Key for \"%s\" randomized.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:894 ../../src/kadmin/cli/kadmin.c:1254 +#, c-format +msgid "Enter password for principal \"%s\"" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:896 ../../src/kadmin/cli/kadmin.c:1256 +#, c-format +msgid "Re-enter password for principal \"%s\"" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:901 ../../src/kadmin/cli/kadmin.c:1260 +#, c-format +msgid "while reading password for \"%s\"." +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:955 +msgid "Not enough memory\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:985 ../../src/kadmin/dbutil/kdb5_util.c:591 +msgid "while getting time" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1126 ../../src/kadmin/cli/kadmin.c:1337 +#: ../../src/kadmin/cli/kadmin.c:1408 ../../src/kadmin/cli/kadmin.c:1847 +#: ../../src/kadmin/cli/kadmin.c:1891 ../../src/kadmin/cli/kadmin.c:1937 +#: ../../src/kadmin/cli/kadmin.c:1977 +msgid "while parsing principal" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1135 +msgid "usage: add_principal [options] principal\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1136 ../../src/kadmin/cli/kadmin.c:1160 +#: ../../src/kadmin/cli/kadmin.c:1653 +msgid "\toptions are:\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1137 +msgid "" +"\t\t[-randkey|-nokey] [-x db_princ_args]* [-expire expdate] [-pwexpire " +"pwexpdate] [-maxlife maxtixlife]\n" +"\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n" +"\t\t[-pw password] [-maxrenewlife maxrenewlife]\n" +"\t\t[-e keysaltlist]\n" +"\t\t[{+|-}attribute]\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1142 ../../src/kadmin/cli/kadmin.c:1165 +msgid "\tattributes are:\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1143 ../../src/kadmin/cli/kadmin.c:1166 +msgid "" +"\t\tallow_postdated allow_forwardable allow_tgs_req allow_renewable\n" +"\t\tallow_proxiable allow_dup_skey allow_tix requires_preauth\n" +"\t\trequires_hwauth needchange allow_svr password_changing_service\n" +"\t\tok_as_delegate ok_to_auth_as_delegate no_auth_data_required\n" +"\t\tlockdown_keys\n" +"\n" +"where,\n" +"\t[-x db_princ_args]* - any number of database specific arguments.\n" +"\t\t\tLook at each database documentation for supported arguments\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1159 +msgid "usage: modify_principal [options] principal\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1161 +msgid "" +"\t\t[-x db_princ_args]* [-expire expdate] [-pwexpire pwexpdate] [-maxlife " +"maxtixlife]\n" +"\t\t[-kvno kvno] [-policy policy] [-clearpolicy]\n" +"\t\t[-maxrenewlife maxrenewlife] [-unlock] [{+|-}attribute]\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1225 ../../src/kadmin/cli/kadmin.c:1366 +#, c-format +msgid "WARNING: policy \"%s\" does not exist\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1232 +#, c-format +msgid "No policy specified for %s; assigning \"default\"\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1238 +#, c-format +msgid "No policy specified for %s; defaulting to no policy\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1280 +#, c-format +msgid "Admin server does not support -nokey while creating \"%s\"\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1302 +#, c-format +msgid "while clearing DISALLOW_ALL_TIX for \"%s\"." +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1349 +#, c-format +msgid "while getting \"%s\"." +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1375 +#, c-format +msgid "while modifying \"%s\"." +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1379 +#, c-format +msgid "Principal \"%s\" modified.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1400 +msgid "usage: get_principal [-terse] principal\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1419 +#, c-format +msgid "while retrieving \"%s\"." +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1424 ../../src/kadmin/cli/kadmin.c:1429 +msgid "while unparsing principal" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1433 +#, c-format +msgid "Principal: %s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1434 +#, c-format +msgid "Expiration date: %s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1435 ../../src/kadmin/cli/kadmin.c:1437 +#: ../../src/kadmin/cli/kadmin.c:1440 ../../src/kadmin/cli/kadmin.c:1448 +msgid "[never]" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1436 +#, c-format +msgid "Last password change: %s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1438 +#, c-format +msgid "Password expiration date: %s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1441 +#, c-format +msgid "Maximum ticket life: %s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1442 +#, c-format +msgid "Maximum renewable life: %s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1444 +#, c-format +msgid "Last modified: %s (%s)\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1446 +#, c-format +msgid "Last successful authentication: %s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1452 +#, c-format +msgid "Failed password attempts: %d\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1454 +#, c-format +msgid "Number of keys: %d\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1462 +#, c-format +msgid "" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1474 +#, c-format +msgid "" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1480 +#, c-format +msgid "MKey: vno %d\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1482 +#, c-format +msgid "Attributes:" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1485 +msgid "while printing flags" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1494 +msgid "[none]" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1496 +msgid " [does not exist]" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1497 +#, c-format +msgid "Policy: %s%s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1533 +msgid "usage: get_principals [expression]\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1538 ../../src/kadmin/cli/kadmin.c:1789 +msgid "while retrieving list." +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1643 +#, c-format +msgid "%s: parser lost count!\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1652 +#, c-format +msgid "usage; %s [options] policy\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1654 +msgid "" +"\t\t[-maxlife time] [-minlife time] [-minlength length]\n" +"\t\t[-minclasses number] [-history number]\n" +"\t\t[-maxfailure number] [-failurecountinterval time]\n" +"\t\t[-allowedkeysalts keysalts]\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1658 +msgid "\t\t[-lockoutduration time]\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1677 +#, c-format +msgid "while creating policy \"%s\"." +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1698 +#, c-format +msgid "while modifying policy \"%s\"." +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1710 +msgid "usage: delete_policy [-force] policy\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1714 +#, c-format +msgid "Are you sure you want to delete the policy \"%s\"? (yes/no): " +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1718 +#, c-format +msgid "Policy \"%s\" not deleted.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1724 +#, c-format +msgid "while deleting policy \"%s\"" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1736 +msgid "usage: get_policy [-terse] policy\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1741 +#, c-format +msgid "while retrieving policy \"%s\"." +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1746 +#, c-format +msgid "Policy: %s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1747 +#, c-format +msgid "Maximum password life: %s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1748 +#, c-format +msgid "Minimum password life: %s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1749 +#, c-format +msgid "Minimum password length: %ld\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1750 +#, c-format +msgid "Minimum number of password character classes: %ld\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1752 +#, c-format +msgid "Number of old keys kept: %ld\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1753 +#, c-format +msgid "Maximum password failures before lockout: %lu\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1755 +#, c-format +msgid "Password failure count reset interval: %s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1757 +#, c-format +msgid "Password lockout duration: %s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1760 +#, c-format +msgid "Allowed key/salt types: %s\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1784 +msgid "usage: get_policies [expression]\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1806 +msgid "usage: get_privs\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1811 +msgid "while retrieving privileges" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1814 +#, c-format +msgid "current privileges:" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1840 +msgid "usage: purgekeys [-all|-keepkvno oldest_kvno_to_keep] principal\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1860 +#, c-format +msgid "while purging keys for principal \"%s\"" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1865 +#, c-format +msgid "All keys for principal \"%s\" removed.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1867 +#, c-format +msgid "Old keys for principal \"%s\" purged.\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1884 +msgid "usage: get_strings principal\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1904 +#, c-format +msgid "while getting attributes for principal \"%s\"" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1909 +#, c-format +msgid "(No string attributes.)\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1928 +msgid "usage: set_string principal key value\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1950 +#, c-format +msgid "while setting attribute on principal \"%s\"" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1954 +#, c-format +msgid "Attribute set for principal \"%s\".\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1969 +msgid "usage: del_string principal key\n" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1990 +#, c-format +msgid "while deleting attribute from principal \"%s\"" +msgstr "" + +#: ../../src/kadmin/cli/kadmin.c:1994 +#, c-format +msgid "Attribute removed from principal \"%s\".\n" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:55 +#, c-format +msgid "" +"Usage: ktadd [-k[eytab] keytab] [-q] [-e keysaltlist] [-norandkey] " +"[principal | -glob princ-exp] [...]\n" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:62 +#, c-format +msgid "" +"Usage: ktremove [-k[eytab] keytab] [-q] principal [kvno|\"all\"|\"old\"]\n" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:76 ../../src/kadmin/cli/keytab.c:97 +msgid "while creating keytab name" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:81 +msgid "while opening default keytab" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:165 +#, c-format +msgid "cannot specify keysaltlist when not changing key\n" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:181 +#, c-format +msgid "while expanding expression \"%s\"." +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:200 ../../src/kadmin/cli/keytab.c:240 +msgid "while closing keytab" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:314 +#, c-format +msgid "while parsing -add principal name %s" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:328 +#, c-format +msgid "%s: Principal %s does not exist.\n" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:331 +#, c-format +msgid "while changing %s's key" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:343 +msgid "while adding key to keytab" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:348 +#, c-format +msgid "" +"Entry for principal %s with kvno %d, encryption type %s added to keytab %s.\n" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:396 +#, c-format +msgid "%s: Keytab %s does not exist.\n" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:400 +#, c-format +msgid "%s: No entry for principal %s exists in keytab %s\n" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:404 +#, c-format +msgid "%s: No entry for principal %s with kvno %d exists in keytab %s\n" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:410 +msgid "while retrieving highest kvno from keytab" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:443 +msgid "while temporarily ending keytab scan" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:448 +msgid "while deleting entry from keytab" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:453 +msgid "while restarting keytab scan" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:459 +#, c-format +msgid "Entry for principal %s with kvno %d removed from keytab %s.\n" +msgstr "" + +#: ../../src/kadmin/cli/keytab.c:481 +#, c-format +msgid "%s: There is only one entry for principal %s in keytab %s\n" +msgstr "" + +#: ../../src/kadmin/cli/ss_wrapper.c:53 ../../src/kadmin/ktutil/ktutil.c:58 +msgid "creating invocation" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:165 +msgid "while allocating temporary filename dump" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:176 +msgid "while renaming dump file into place" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:196 +msgid "while allocating dump_ok filename" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:202 +#, c-format +msgid "while creating 'ok' file, '%s'" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:207 +#, c-format +msgid "while locking 'ok' file, '%s'" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:260 ../../src/kadmin/dbutil/dump.c:289 +#, c-format +msgid "%s: regular expression error: %s\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:272 +#, c-format +msgid "%s: regular expression match error: %s\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:373 +#, c-format +msgid "%s: tagged data list inconsistency for %s (counted %d, stored %d)\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:495 +#, c-format +msgid "while converting %s to new master key" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:516 +#, c-format +msgid "%s(%d): %s\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:559 +#, c-format +msgid "%s(%d): ignoring trash at end of line: " +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:622 +msgid "cannot read tagged data type and length" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:626 +msgid "data type or length overflowed" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:633 +msgid "cannot read tagged data contents" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:666 +msgid "cannot match size tokens" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:672 +msgid "cannot allocate principal (too large)" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:681 +msgid "cannot allocate tl_data (too large)" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:690 +msgid "invalid key_data size" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:707 +msgid "cannot read name string" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:712 +#, c-format +msgid "while parsing name %s" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:720 +msgid "cannot read principal attributes" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:773 +msgid "cannot read key size and version" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:777 +msgid "unsupported key_data_ver version" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:781 +msgid "invalid kvno" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:792 +msgid "cannot read key type and length" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:798 +msgid "cannot read key data" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:808 +msgid "cannot read extra data" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:817 +#, c-format +msgid "while storing %s" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:856 ../../src/kadmin/dbutil/dump.c:895 +#: ../../src/kadmin/dbutil/dump.c:941 ../../src/kadmin/dbutil/dump.c:960 +#, c-format +msgid "cannot parse policy (%d read)\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:864 ../../src/kadmin/dbutil/dump.c:903 +#: ../../src/kadmin/dbutil/dump.c:981 +msgid "while creating policy" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:868 +#, c-format +msgid "created policy %s\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1018 +#, c-format +msgid "unknown record type \"%s\"\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1129 +#, c-format +msgid "%s: Unknown iprop dump version %d\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1207 ../../src/kadmin/dbutil/dump.c:1443 +#, c-format +msgid "OV dump format not supported\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1229 ../../src/kadmin/dbutil/dump.c:1455 +#, c-format +msgid "Iprop not enabled\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1266 +msgid "Conditional dump is an undocumented option for use only for iprop dumps" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1279 +msgid "Database not currently opened!" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1293 ../../src/kadmin/dbutil/kdb5_stash.c:116 +#: ../../src/kadmin/dbutil/kdb5_util.c:445 +msgid "while reading master key" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1299 +msgid "while verifying master key" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1318 ../../src/kadmin/dbutil/dump.c:1328 +msgid "while reading new master key" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1322 +#, c-format +msgid "Please enter new master key....\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1346 +#, c-format +msgid "while opening %s for writing" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1361 +msgid "while reading update log header" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1376 ../../src/kadmin/dbutil/dump.c:1384 +#, c-format +msgid "performing %s dump" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1414 +#, c-format +msgid "%s: error processing line %d of %s\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1464 +msgid "while parsing options" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1479 +#, c-format +msgid "while opening %s" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1484 ../../src/kadmin/dbutil/dump.c:1580 +msgid "standard input" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1489 +#, c-format +msgid "%s: can't read dump header in %s\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1497 ../../src/kadmin/dbutil/dump.c:1511 +#, c-format +msgid "%s: dump header bad in %s\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1520 +#, c-format +msgid "Could not open iprop ulog\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1525 +#, c-format +msgid "%s: dump version %s can only be loaded with the -update flag\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1534 ../../src/kadmin/dbutil/dump.c:1539 +msgid "computing parameters for database" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1545 +msgid "while creating database" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1554 +msgid "while opening database" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1564 +msgid "while permanently locking database" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1582 +#, c-format +msgid "%s: %s restore failed\n" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1587 +msgid "while unlocking database" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1597 ../../src/kadmin/dbutil/dump.c:1616 +msgid "while reinitializing update log" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1607 +msgid "while making newly loaded database live" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1623 +msgid "while writing update log header" +msgstr "" + +#: ../../src/kadmin/dbutil/dump.c:1637 +#, c-format +msgid "while deleting bad database %s" +msgstr "" + +#: ../../src/kadmin/dbutil/kadm5_create.c:79 +msgid "while looking up the Kerberos configuration" +msgstr "" + +#: ../../src/kadmin/dbutil/kadm5_create.c:105 +msgid "while initializing the Kerberos admin interface" +msgstr "" + +#: ../../src/kadmin/dbutil/kadm5_create.c:197 +msgid "while appending realm to principal" +msgstr "" + +#: ../../src/kadmin/dbutil/kadm5_create.c:203 +msgid "while parsing admin principal name" +msgstr "" + +#: ../../src/kadmin/dbutil/kadm5_create.c:215 +#, c-format +msgid "while creating principal %s" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:186 +#: ../../src/kadmin/dbutil/kdb5_util.c:389 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:566 +msgid "while setting up master key name" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:197 +#, c-format +msgid "" +"Initializing database '%s' for realm '%s',\n" +"master key name '%s'\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:202 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:475 +#, c-format +msgid "You will be prompted for the database Master Password.\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:203 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:255 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:476 +#, c-format +msgid "It is important that you NOT FORGET this password.\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:209 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:261 +msgid "while creating new master key" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:217 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:486 +msgid "while reading master key from keyboard" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:227 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:280 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:578 +msgid "while calculating master key salt" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:235 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:289 +#: ../../src/kadmin/dbutil/kdb5_util.c:431 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:590 +msgid "while transforming master key from password" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:245 +msgid "while initializing random key generator" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:250 +#, c-format +msgid "while creating database '%s'" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:268 +msgid "while creating update log" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:279 +msgid "while initializing update log" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:294 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:602 +msgid "while adding entries to the database" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:322 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:333 +#: ../../src/kadmin/dbutil/kdb5_stash.c:133 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:627 +msgid "while storing key" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_create.c:323 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:334 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:628 +#, c-format +msgid "Warning: couldn't stash master key.\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:69 +#, c-format +msgid "Deleting KDC database stored in '%s', are you sure?\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:71 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1111 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:360 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1434 +#, c-format +msgid "(type 'yes' to confirm)? " +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:78 +#, c-format +msgid "OK, deleting database '%s'...\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:83 +#, c-format +msgid "deleting database '%s'" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_destroy.c:92 +#, c-format +msgid "** Database '%s' destroyed.\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:223 +#, c-format +msgid "%s is an invalid enctype" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:245 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:421 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:564 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:941 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1102 +#, c-format +msgid "while getting master key principal %s" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:251 +#, c-format +msgid "Creating new master key for master key principal '%s'\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:254 +#, c-format +msgid "You will be prompted for a new database Master Password.\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:270 +msgid "while reading new master key from keyboard" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:299 +msgid "adding new master key to master principal" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:305 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:390 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:806 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1305 +msgid "while getting current time" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:312 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:522 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1312 +msgid "while updating the master key principal modification time" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:319 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:530 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1322 +msgid "while adding master key entry to the database" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:371 +msgid "0 is an invalid KVNO value" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:382 +#, c-format +msgid "%d is an invalid KVNO value" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:398 +#, c-format +msgid "could not parse date-time string '%s'" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:430 +msgid "while looking up active version of master key" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:469 +msgid "while adding new master key" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:507 +msgid "there must be one master key currently active" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:515 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1291 +msgid "while updating actkvno data for master principal entry" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:556 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:903 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1072 +msgid "master keylist not initialized" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:572 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:949 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1199 +msgid "while looking up active kvno list" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:580 +#: ../../src/kadmin/dbutil/kdb5_mkey.c:957 +msgid "while looking up active master key" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:592 +msgid "while getting enctype description" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:609 +#, c-format +msgid "KVNO: %d, Enctype: %s, Active on: %s *\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:614 +#, c-format +msgid "KVNO: %d, Enctype: %s, Active on: %s\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:618 +#, c-format +msgid "KVNO: %d, Enctype: %s, No activate time set\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:623 +msgid "asprintf could not allocate enough memory to hold output" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:756 +msgid "getting string representation of principal name" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:780 +#, c-format +msgid "determining master key used for principal '%s'" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:786 +#, c-format +msgid "would skip: %s\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:788 +#, c-format +msgid "skipping: %s\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:794 +#, c-format +msgid "would update: %s\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:798 +#, c-format +msgid "updating: %s\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:802 +#, c-format +msgid "error re-encrypting key for principal '%s'" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:813 +#, c-format +msgid "while updating principal '%s' modification time" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:820 +#, c-format +msgid "while updating principal '%s' key data in the database" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:852 +#, c-format +msgid "" +"\n" +"(type 'yes' to confirm)? " +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:914 +#, c-format +msgid "converting glob pattern '%s' to regular expression" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:932 +#, c-format +msgid "error compiling converted regexp '%s'" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:965 +#, c-format +msgid "Re-encrypt all keys not using master key vno %u?" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:967 +#, c-format +msgid "OK, doing nothing.\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:973 +#, c-format +msgid "Principals whose keys WOULD BE re-encrypted to master key vno %u:\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:976 +#, c-format +msgid "" +"Principals whose keys are being re-encrypted to master key vno %u if " +"necessary:\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:992 +msgid "trying to process principal database" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:996 +#, c-format +msgid "%u principals processed: %u would be updated, %u already current\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1000 +#, c-format +msgid "%u principals processed: %u updated, %u already current\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1109 +#, c-format +msgid "" +"Will purge all unused master keys stored in the '%s' principal, are you " +"sure?\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1120 +#, c-format +msgid "OK, purging unused master keys from '%s'...\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1128 +#, c-format +msgid "There is only one master key which can not be purged.\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1137 +msgid "while allocating args.kvnos" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1153 +msgid "while finding master keys in use" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1162 +#, c-format +msgid "Would purge the following master key(s) from %s:\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1165 +#, c-format +msgid "Purging the following master key(s) from %s:\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1177 +msgid "master key stash file needs updating, command aborting" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1183 +#, c-format +msgid "KVNO: %d\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1188 +#, c-format +msgid "All keys in use, nothing purged.\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1193 +#, c-format +msgid "%d key(s) would be purged.\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1206 +msgid "while looking up mkey aux data list" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1214 +msgid "while allocating key_data" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1299 +msgid "while updating mkey_aux data for master principal entry" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_mkey.c:1326 +#, c-format +msgid "%d key(s) purged.\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_stash.c:97 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:542 +#, c-format +msgid "while setting up enctype %d" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_stash.c:123 +msgid "while getting master key list" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_stash.c:127 +#, c-format +msgid "Using existing stashed keys to update stash file.\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:80 +#, c-format +msgid "" +"Usage: kdb5_util [-r realm] [-d dbname] [-k mkeytype] [-kv mkeyVNO]\n" +"\t [-M mkeyname] [-m] [-sf stashfilename] [-P password]\n" +"\t [-x db_args]* cmd [cmd_options]\n" +"\tcreate [-s]\n" +"\tdestroy [-f]\n" +"\tstash [-f keyfile]\n" +"\tdump [-b7|-r13|-r18] [-verbose]\n" +"\t [-mkey_convert] [-new_mkey_file mkey_file]\n" +"\t [-rev] [-recurse] [filename [princs...]]\n" +"\tload [-b7|-r13|-r18] [-hash] [-verbose] [-update] filename\n" +"\tark [-e etype_list] principal\n" +"\tadd_mkey [-e etype] [-s]\n" +"\tuse_mkey kvno [time]\n" +"\tlist_mkeys\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:99 +#, c-format +msgid "" +"\tupdate_princ_encryption [-f] [-n] [-v] [princ-pattern]\n" +"\tpurge_mkeys [-f] [-n] [-v]\n" +"\ttabdump [-H] [-c] [-e] [-n] [-o outfile] dumptype\n" +"\n" +"where,\n" +"\t[-x db_args]* - any number of database specific arguments.\n" +"\t\t\tLook at each database documentation for supported arguments\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:215 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:264 +msgid "while initializing Kerberos code" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:221 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:271 +msgid "while creating sub-command arguments" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:239 +msgid "while parsing command arguments" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:245 +#: ../../src/kadmin/dbutil/kdb5_util.c:252 +msgid "while parsing command arguments\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:263 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:295 +msgid "while setting default realm name" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:268 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:302 +#, c-format +msgid ": %s is an invalid enctype" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:276 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:311 +#, c-format +msgid ": %s is an invalid mkeyVNO" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:319 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:435 +msgid "while retrieving configuration parameters" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:378 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:841 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1449 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:568 +msgid "while initializing database" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:395 +msgid "while retrieving master entry" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:414 +msgid "while calculated master key salt" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:446 +msgid "Warning: proceeding without master key" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:464 +msgid "while seeding random number generator" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:474 +#, c-format +msgid "%s: Could not map log\n" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:503 +msgid "while closing database" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:550 +#, c-format +msgid "while fetching principal %s" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:573 +msgid "while finding mkey" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:598 +msgid "while setting changetime" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:606 +#, c-format +msgid "while saving principal %s" +msgstr "" + +#: ../../src/kadmin/dbutil/kdb5_util.c:610 +#, c-format +msgid "%s changed\n" +msgstr "" + +#: ../../src/kadmin/dbutil/tabdump.c:573 +#, c-format +msgid "opening %s for writing" +msgstr "" + +#: ../../src/kadmin/dbutil/tabdump.c:655 +msgid "performing tabular dump" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:73 +#, c-format +msgid "%s: invalid arguments\n" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:78 +msgid "while freeing ktlist" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:89 +#, c-format +msgid "%s: must specify keytab to read\n" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:94 +#, c-format +msgid "while reading keytab \"%s\"" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:101 +#, c-format +msgid "%s: reading srvtabs is no longer supported\n" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:112 +#, c-format +msgid "%s: must specify keytab to write\n" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:117 +#, c-format +msgid "while writing keytab \"%s\"" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:124 +#, c-format +msgid "%s: writing srvtabs is no longer supported\n" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:171 +#, c-format +msgid "" +"usage: %s (-key | -password) -p principal -k kvno [-e enctype] [-f|-s salt]\n" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:176 +#, c-format +msgid "enctype must be specified if not using -f\n" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:183 +msgid "while adding new entry" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:193 +#, c-format +msgid "%s: must specify entry to delete\n" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:198 +#, c-format +msgid "while deleting entry %d" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:226 +#, c-format +msgid "%s: usage: %s [-t] [-k] [-e]\n" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil.c:265 +msgid "While converting enctype to string" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil_funcs.c:196 +#, c-format +msgid "Password for %.1000s" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil_funcs.c:214 +#, c-format +msgid "Key for %s (hex): " +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil_funcs.c:226 +#, c-format +msgid "addent: Error reading key.\n" +msgstr "" + +#: ../../src/kadmin/ktutil/ktutil_funcs.c:234 +#, c-format +msgid "addent: Illegal character in key.\n" +msgstr "" + +#: ../../src/kadmin/server/auth_acl.c:240 +#, c-format +msgid "%s: invalid restrictions: %s" +msgstr "" + +#: ../../src/kadmin/server/auth_acl.c:288 +#, c-format +msgid "Unrecognized ACL operation '%c' in %s" +msgstr "" + +#: ../../src/kadmin/server/auth_acl.c:296 +#, c-format +msgid "Cannot parse client principal '%s'" +msgstr "" + +#: ../../src/kadmin/server/auth_acl.c:304 +#, c-format +msgid "Cannot parse target principal '%s'" +msgstr "" + +#: ../../src/kadmin/server/auth_acl.c:400 +#, c-format +msgid "%s while opening ACL file %s" +msgstr "" + +#: ../../src/kadmin/server/auth_acl.c:403 +#, c-format +msgid "Cannot open %s: %s" +msgstr "" + +#: ../../src/kadmin/server/auth_acl.c:419 +#: ../../src/kadmin/server/auth_acl.c:422 +#, c-format +msgid "%s: syntax error at line %d <%.10s...>" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:49 +#, c-format +msgid "Unauthorized request: %s, client=%s, service=%s, addr=%s" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:50 +#: ../../src/kadmin/server/ipropd_svc.c:224 +#, c-format +msgid "Request: %s, %s, %s, client=%s, service=%s, addr=%s" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:164 +#: ../../src/kadmin/server/ipropd_svc.c:281 +#, c-format +msgid "%s: server handle is NULL" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:174 +#: ../../src/kadmin/server/ipropd_svc.c:294 +#, c-format +msgid "%s: setup_gss_names failed" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:182 +#: ../../src/kadmin/server/ipropd_svc.c:303 +#, c-format +msgid "%s: out of memory recording principal names" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:207 +#, c-format +msgid "%s; Incoming SerialNo=%lu; Outgoing SerialNo=%lu" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:213 +#, c-format +msgid "%s; Incoming SerialNo=%lu; Outgoing SerialNo=N/A" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:324 +#, c-format +msgid "%s: getclhoststr failed" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:346 +#, c-format +msgid "%s: cannot construct kdb5 util dump string too long; out of memory" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:366 +#, c-format +msgid "%s: fork failed: %s" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:378 +#, c-format +msgid "%s: popen failed: %s" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:392 +#, c-format +msgid "%s: pclose(popen) failed: %s" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:412 +#, c-format +msgid "%s: exec failed: %s" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:428 +#, c-format +msgid "Request: %s, spawned resync process %d, client=%s, service=%s, addr=%s" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:490 +#: ../../src/kadmin/server/kadm_rpc_svc.c:299 +#, c-format +msgid "check_rpcsec_auth: failed inquire_context, stat=%u" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:520 +#: ../../src/kadmin/server/kadm_rpc_svc.c:328 +#, c-format +msgid "bad service principal %.*s%s" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:543 +#, c-format +msgid "authentication attempt failed: %s, RPC authentication flavor %d" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:577 +#, c-format +msgid "RPC unknown request: %d (%s)" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:585 +#, c-format +msgid "RPC svc_getargs failed (%s)" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:595 +#, c-format +msgid "RPC svc_sendreply failed (%s)" +msgstr "" + +#: ../../src/kadmin/server/ipropd_svc.c:601 +#, c-format +msgid "RPC svc_freeargs failed (%s)" +msgstr "" + +#: ../../src/kadmin/server/kadm_rpc_svc.c:349 +#, c-format +msgid "gss_to_krb5_name: failed display_name status %d" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:82 +#, c-format +msgid "" +"Usage: kadmind [-x db_args]* [-r realm] [-m] [-nofork] [-port port-number]\n" +"\t\t[-proponly] [-p path-to-kdb5_util] [-F dump-file]\n" +"\t\t[-K path-to-kprop] [-k kprop-port] [-P pid_file]\n" +"\n" +"where,\n" +"\t[-x db_args]* - any number of database specific arguments.\n" +"\t\t\tLook at each database documentation for supported arguments\n" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:106 +#, c-format +msgid "%s: %s while %s, aborting\n" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:108 +#, c-format +msgid "%s while %s, aborting\n" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:110 +#, c-format +msgid "%s: %s, aborting\n" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:111 +#, c-format +msgid "%s, aborting" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:278 +#, c-format +msgid "" +"WARNING! Forged/garbled request: %s, claimed client = %.*s%s, server = " +"%.*s%s, addr = %s" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:284 +#, c-format +msgid "" +"WARNING! Forged/garbled request: %d, claimed client = %.*s%s, server = " +"%.*s%s, addr = %s" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:298 +#, c-format +msgid "Miscellaneous RPC error: %s, %s" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:314 +#, c-format +msgid "%s Cannot decode status %d" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:332 +#, c-format +msgid "Authentication attempt failed: %s, GSS-API error strings are:" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:337 +msgid " GSS-API error strings complete." +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:375 +#, c-format +msgid "%s: cannot initialize. Not enough memory\n" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:443 +#, c-format +msgid "%s: %s while initializing context, aborting\n" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:454 +#: ../../src/kadmin/server/ovsec_kadmd.c:523 +msgid "initializing" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:458 +msgid "getting config parameters" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:460 +msgid "Missing required realm configuration" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:462 +msgid "Missing required ACL file configuration" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:464 +msgid "-proponly can only be used when iprop_enable is true" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:470 +msgid "initializing network" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:475 +msgid "Cannot build GSSAPI auth names" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:479 +msgid "Cannot set up KDB keytab" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:482 +msgid "Cannot set GSSAPI authentication names" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:499 +msgid "Cannot initialize GSSAPI service name" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:504 +msgid "initializing ACL file" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:512 +msgid "spawning daemon process" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:516 +msgid "creating PID file" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:530 +msgid "mapping update log" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:534 +#, c-format +msgid "%s: create IPROP svc (PROG=%d, VERS=%d)\n" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:542 +msgid "starting" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:544 ../../src/kdc/main.c:1036 +#, c-format +msgid "%s: starting...\n" +msgstr "" + +#: ../../src/kadmin/server/ovsec_kadmd.c:547 +msgid "finished, exiting" +msgstr "" + +#: ../../src/kadmin/server/schpw.c:273 +#, c-format +msgid "setpw request from %s by %.*s%s for %.*s%s: %s" +msgstr "" + +#: ../../src/kadmin/server/schpw.c:278 +#, c-format +msgid "chpw request from %s for %.*s%s: %s" +msgstr "" + +#: ../../src/kadmin/server/schpw.c:446 +#, c-format +msgid "chpw: Couldn't open admin keytab %s" +msgstr "" + +#: ../../src/kadmin/server/server_stubs.c:396 +#, c-format +msgid "" +"Unauthorized request: %s, %.*s%s, client=%.*s%s, service=%.*s%s, addr=%s" +msgstr "" + +#: ../../src/kadmin/server/server_stubs.c:417 +#: ../../src/kadmin/server/server_stubs.c:695 +#: ../../src/kadmin/server/server_stubs.c:1570 +msgid "success" +msgstr "" + +#: ../../src/kadmin/server/server_stubs.c:427 +#, c-format +msgid "Request: %s, %.*s%s, %s, client=%.*s%s, service=%.*s%s, addr=%s" +msgstr "" + +#: ../../src/kadmin/server/server_stubs.c:675 +#, c-format +msgid "" +"Unauthorized request: kadm5_rename_principal, %.*s%s to %.*s%s, " +"client=%.*s%s, service=%.*s%s, addr=%s" +msgstr "" + +#: ../../src/kadmin/server/server_stubs.c:690 +#, c-format +msgid "" +"Request: kadm5_rename_principal, %.*s%s to %.*s%s, %s, client=%.*s%s, " +"service=%.*s%s, addr=%s" +msgstr "" + +#: ../../src/kadmin/server/server_stubs.c:1566 +#, c-format +msgid "" +"Request: kadm5_init, %.*s%s, %s, client=%.*s%s, service=%.*s%s, addr=%s, " +"vers=%d, flavor=%d" +msgstr "" + +#: ../../src/kdc/do_as_req.c:278 +#, c-format +msgid "AS_REQ : handle_authdata (%d)" +msgstr "" + +#: ../../src/kdc/do_tgs_req.c:938 +msgid "not checking transit path" +msgstr "" + +#: ../../src/kdc/do_tgs_req.c:1045 +#, c-format +msgid "TGS_REQ : handle_authdata (%d)" +msgstr "" + +#: ../../src/kdc/fast_util.c:57 +#, c-format +msgid "%s while handling ap-request armor" +msgstr "" + +#: ../../src/kdc/fast_util.c:65 +msgid "ap-request armor for something other than the local TGS" +msgstr "" + +#: ../../src/kdc/fast_util.c:74 +msgid "ap-request armor without subkey" +msgstr "" + +#: ../../src/kdc/fast_util.c:162 +msgid "Ap-request armor not permitted with TGS" +msgstr "" + +#: ../../src/kdc/fast_util.c:169 +#, c-format +msgid "Unknown FAST armor type %d" +msgstr "" + +#: ../../src/kdc/fast_util.c:183 +msgid "No armor key but FAST armored request present" +msgstr "" + +#: ../../src/kdc/fast_util.c:216 +msgid "FAST req_checksum invalid; request modified" +msgstr "" + +#: ../../src/kdc/fast_util.c:222 +msgid "Unkeyed checksum used in fast_req" +msgstr "" + +#: ../../src/kdc/kdc_audit.c:110 +#, c-format +msgid "audit plugin %s failed to open. error=%i" +msgstr "" + +#: ../../src/kdc/kdc_authdata.c:78 +#, c-format +msgid "while loading authdata module %s" +msgstr "" + +#: ../../src/kdc/kdc_log.c:83 +#, c-format +msgid "AS_REQ (%s) %s: ISSUE: authtime %u, %s, %s for %s" +msgstr "" + +#: ../../src/kdc/kdc_log.c:91 +#, c-format +msgid "AS_REQ (%s) %s: %s: %s for %s%s%s" +msgstr "" + +#: ../../src/kdc/kdc_log.c:154 +#, c-format +msgid "TGS_REQ (%s) %s: %s: authtime %u, %s%s %s for %s%s%s" +msgstr "" + +#: ../../src/kdc/kdc_log.c:163 +#, c-format +msgid "... PROTOCOL-TRANSITION s4u-client=%s" +msgstr "" + +#: ../../src/kdc/kdc_log.c:167 +#, c-format +msgid "... CONSTRAINED-DELEGATION s4u-client=%s" +msgstr "" + +#: ../../src/kdc/kdc_log.c:171 +#, c-format +msgid "TGS_REQ %s: %s: authtime %u, %s for %s, 2nd tkt client %s" +msgstr "" + +#: ../../src/kdc/kdc_log.c:204 +#, c-format +msgid "bad realm transit path from '%s' to '%s' via '%.*s%s'" +msgstr "" + +#: ../../src/kdc/kdc_log.c:210 +#, c-format +msgid "unexpected error checking transit from '%s' to '%s' via '%.*s%s': %s" +msgstr "" + +#: ../../src/kdc/kdc_log.c:228 +msgid "TGS_REQ: issuing alternate TGT" +msgstr "" + +#: ../../src/kdc/kdc_log.c:231 +#, c-format +msgid "TGS_REQ: issuing TGT %s" +msgstr "" + +#: ../../src/kdc/kdc_preauth.c:215 +#, c-format +msgid "preauth %s failed to initialize: %s" +msgstr "" + +#: ../../src/kdc/kdc_preauth.c:226 +#, c-format +msgid "preauth %s failed to setup loop: %s" +msgstr "" + +#: ../../src/kdc/kdc_preauth.c:903 +#, c-format +msgid "%spreauth required but hint list is empty" +msgstr "" + +#: ../../src/kdc/kdc_preauth_ec.c:74 +msgid "Encrypted Challenge used outside of FAST tunnel" +msgstr "" + +#: ../../src/kdc/kdc_preauth_ec.c:117 +msgid "Incorrect password in encrypted challenge" +msgstr "" + +#: ../../src/kdc/kdc_util.c:179 +msgid "TGS_REQ: SESSION KEY or MUTUAL" +msgstr "" + +#: ../../src/kdc/kdc_util.c:378 +#, c-format +msgid "TGS_REQ: UNKNOWN SERVER: server='%s'" +msgstr "" + +#: ../../src/kdc/kdc_util.c:541 +#, c-format +msgid "Invalid pac_privsvr_enctype value %s" +msgstr "" + +#: ../../src/kdc/kdc_util.c:882 +#, c-format +msgid "Required auth indicators not present in ticket: %s" +msgstr "" + +#: ../../src/kdc/main.c:225 +#, c-format +msgid "Requested master password enctype %s in %s is DEPRECATED!\n" +msgstr "" + +#: ../../src/kdc/main.c:241 +#, c-format +msgid "while getting context for realm %s" +msgstr "" + +#: ../../src/kdc/main.c:348 +#, c-format +msgid "while setting default realm to %s" +msgstr "" + +#: ../../src/kdc/main.c:356 +#, c-format +msgid "while initializing database for realm %s" +msgstr "" + +#: ../../src/kdc/main.c:365 +#, c-format +msgid "while setting up master key name %s for realm %s" +msgstr "" + +#: ../../src/kdc/main.c:378 +#, c-format +msgid "while fetching master key %s for realm %s" +msgstr "" + +#: ../../src/kdc/main.c:387 +#, c-format +msgid "Stash file %s uses DEPRECATED enctype %s!\n" +msgstr "" + +#: ../../src/kdc/main.c:394 +#, c-format +msgid "while fetching master keys list for realm %s" +msgstr "" + +#: ../../src/kdc/main.c:403 +#, c-format +msgid "while resolving kdb keytab for realm %s" +msgstr "" + +#: ../../src/kdc/main.c:412 +#, c-format +msgid "while building TGS name for realm %s" +msgstr "" + +#: ../../src/kdc/main.c:502 +#, c-format +msgid "creating %d worker processes" +msgstr "" + +#: ../../src/kdc/main.c:512 +msgid "Unable to reinitialize main loop" +msgstr "" + +#: ../../src/kdc/main.c:517 +#, c-format +msgid "Unable to initialize signal handlers in pid %d" +msgstr "" + +#: ../../src/kdc/main.c:547 +#, c-format +msgid "worker %ld exited with status %d" +msgstr "" + +#: ../../src/kdc/main.c:571 +#, c-format +msgid "signal %d received in supervisor" +msgstr "" + +#: ../../src/kdc/main.c:583 +#, c-format +msgid "" +"usage: %s [-x db_args]* [-d dbpathname] [-r dbrealmname]\n" +"\t\t[-T time_offset] [-m] [-k masterenctype]\n" +"\t\t[-M masterkeyname] [-p port] [-P pid_file]\n" +"\t\t[-n] [-w numworkers] [/]\n" +"\n" +"where,\n" +"\t[-x db_args]* - Any number of database specific arguments.\n" +"\t\t\tLook at each database module documentation for \t\t\tsupported " +"arguments\n" +msgstr "" + +#: ../../src/kdc/main.c:656 ../../src/kdc/main.c:663 ../../src/kdc/main.c:778 +#, c-format +msgid " KDC cannot initialize. Not enough memory\n" +msgstr "" + +#: ../../src/kdc/main.c:682 ../../src/kdc/main.c:725 ../../src/kdc/main.c:736 +#, c-format +msgid "%s: KDC cannot initialize. Not enough memory\n" +msgstr "" + +#: ../../src/kdc/main.c:702 ../../src/kdc/main.c:815 +#, c-format +msgid "%s: cannot initialize realm %s - see log file for details\n" +msgstr "" + +#: ../../src/kdc/main.c:713 +#, c-format +msgid "%s: cannot initialize realm %s. Not enough memory\n" +msgstr "" + +#: ../../src/kdc/main.c:764 +#, c-format +msgid "invalid enctype %s" +msgstr "" + +#: ../../src/kdc/main.c:803 +msgid "while attempting to retrieve default realm" +msgstr "" + +#: ../../src/kdc/main.c:805 +#, c-format +msgid "%s: %s, attempting to retrieve default realm\n" +msgstr "" + +#: ../../src/kdc/main.c:911 +#, c-format +msgid "%s: cannot get memory for realm list\n" +msgstr "" + +#: ../../src/kdc/main.c:946 +msgid "while initializing lookaside cache" +msgstr "" + +#: ../../src/kdc/main.c:954 +msgid "while creating main loop" +msgstr "" + +#: ../../src/kdc/main.c:963 +msgid "while loading KDC policy plugin" +msgstr "" + +#: ../../src/kdc/main.c:988 +msgid "while initializing signal handlers" +msgstr "" + +#: ../../src/kdc/main.c:996 +msgid "while initializing network" +msgstr "" + +#: ../../src/kdc/main.c:1006 +msgid "while detaching from tty" +msgstr "" + +#: ../../src/kdc/main.c:1012 +msgid "while creating PID file" +msgstr "" + +#: ../../src/kdc/main.c:1020 +msgid "creating worker processes" +msgstr "" + +#: ../../src/kdc/main.c:1030 +msgid "while loading audit plugin module(s)" +msgstr "" + +#: ../../src/kdc/main.c:1034 +msgid "commencing operation" +msgstr "" + +#: ../../src/kdc/main.c:1041 +msgid "shutting down" +msgstr "" + +#: ../../src/kdc/policy.c:230 +#, c-format +msgid "while loading policy module %s" +msgstr "" + +#: ../../src/kprop/kprop.c:85 +#, c-format +msgid "" +"\n" +"Usage: %s [-r realm] [-f file] [-d] [-P port] [-s keytab] replica_host\n" +"\n" +msgstr "" + +#: ../../src/kprop/kprop.c:115 +#, c-format +msgid "Database propagation to %s: SUCCEEDED\n" +msgstr "" + +#: ../../src/kprop/kprop.c:176 +msgid "while setting client principal name" +msgstr "" + +#: ../../src/kprop/kprop.c:185 +msgid "while setting server principal name" +msgstr "" + +#: ../../src/kprop/kprop.c:198 +msgid "while resolving keytab" +msgstr "" + +#: ../../src/kprop/kprop.c:206 +msgid "while getting initial credentials\n" +msgstr "" + +#: ../../src/kprop/kprop.c:242 +msgid "while creating socket" +msgstr "" + +#: ../../src/kprop/kprop.c:262 +msgid "while connecting to server" +msgstr "" + +#: ../../src/kprop/kprop.c:269 ../../src/kprop/kpropd.c:1196 +msgid "while getting local socket address" +msgstr "" + +#: ../../src/kprop/kprop.c:274 +msgid "while converting local address" +msgstr "" + +#: ../../src/kprop/kprop.c:296 +msgid "in krb5_auth_con_setaddrs" +msgstr "" + +#: ../../src/kprop/kprop.c:304 +msgid "while authenticating to server" +msgstr "" + +#: ../../src/kprop/kprop.c:308 ../../src/kprop/kprop.c:506 +#: ../../src/kprop/kpropd.c:1516 +#, c-format +msgid "Generic remote error: %s\n" +msgstr "" + +#: ../../src/kprop/kprop.c:314 ../../src/kprop/kprop.c:512 +msgid "signalled from server" +msgstr "" + +#: ../../src/kprop/kprop.c:316 ../../src/kprop/kprop.c:514 +#, c-format +msgid "Error text from server: %s\n" +msgstr "" + +#: ../../src/kprop/kprop.c:344 +#, c-format +msgid "allocating database file name '%s'" +msgstr "" + +#: ../../src/kprop/kprop.c:350 +#, c-format +msgid "while trying to open %s" +msgstr "" + +#: ../../src/kprop/kprop.c:357 +msgid "database locked" +msgstr "" + +#: ../../src/kprop/kprop.c:360 ../../src/kprop/kpropd.c:552 +#, c-format +msgid "while trying to lock '%s'" +msgstr "" + +#: ../../src/kprop/kprop.c:364 ../../src/kprop/kprop.c:372 +#, c-format +msgid "while trying to stat %s" +msgstr "" + +#: ../../src/kprop/kprop.c:368 +msgid "while trying to malloc data_ok_fn" +msgstr "" + +#: ../../src/kprop/kprop.c:377 +#, c-format +msgid "'%s' more recent than '%s'." +msgstr "" + +#: ../../src/kprop/kprop.c:393 +#, c-format +msgid "while unlocking database '%s'" +msgstr "" + +#: ../../src/kprop/kprop.c:425 ../../src/kprop/kprop.c:426 +msgid "while encoding database size" +msgstr "" + +#: ../../src/kprop/kprop.c:434 +msgid "while sending database size" +msgstr "" + +#: ../../src/kprop/kprop.c:444 +msgid "while allocating i_vector" +msgstr "" + +#: ../../src/kprop/kprop.c:467 +#, c-format +msgid "while sending database block starting at %" +msgstr "" + +#: ../../src/kprop/kprop.c:477 +msgid "Premature EOF found for database file!" +msgstr "" + +#: ../../src/kprop/kprop.c:490 +msgid "while reading response from server" +msgstr "" + +#: ../../src/kprop/kprop.c:501 +msgid "while decoding error response from server" +msgstr "" + +#: ../../src/kprop/kprop.c:531 +msgid "malformed sent database size message" +msgstr "" + +#: ../../src/kprop/kprop.c:535 +#, c-format +msgid "Kpropd sent database size %, expecting %" +msgstr "" + +#: ../../src/kprop/kprop.c:581 +msgid "while allocating filename for update_last_prop_file" +msgstr "" + +#: ../../src/kprop/kprop.c:586 +#, c-format +msgid "while creating 'last_prop' file, '%s'" +msgstr "" + +#: ../../src/kprop/kpropd.c:171 +#, c-format +msgid "" +"\n" +"Usage: %s [-r realm] [-s keytab] [-d] [-D] [-S]\n" +"\t[-f replica_file] [-F kerberos_db_file ]\n" +"\t[-p kdb5_util_pathname] [-x db_args]* [-P port]\n" +"\t[-a acl_file] [-A admin_server] [--pid-file=pid_file]\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:231 +#, c-format +msgid "Killing fullprop child (%d)\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:260 +msgid "while checking if stdin is a socket" +msgstr "" + +#: ../../src/kprop/kpropd.c:278 +#, c-format +msgid "ready\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:284 +#, c-format +msgid "Could not write pid file %s: %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:296 +#, c-format +msgid "Could not open /dev/null: %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:303 +#, c-format +msgid "Could not dup the inetd socket: %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:338 ../../src/kprop/kpropd.c:351 +msgid "do_iprop failed.\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:390 +#, c-format +msgid "getaddrinfo: %s\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:396 +msgid "while obtaining socket" +msgstr "" + +#: ../../src/kprop/kpropd.c:402 +msgid "while setting SO_REUSEADDR option" +msgstr "" + +#: ../../src/kprop/kpropd.c:410 +msgid "while unsetting IPV6_V6ONLY option" +msgstr "" + +#: ../../src/kprop/kpropd.c:415 +msgid "while binding listener socket" +msgstr "" + +#: ../../src/kprop/kpropd.c:426 +#, c-format +msgid "waiting for a kprop connection\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:432 +msgid "while accepting connection" +msgstr "" + +#: ../../src/kprop/kpropd.c:438 +msgid "while forking" +msgstr "" + +#: ../../src/kprop/kpropd.c:453 +#, c-format +msgid "waitpid() failed to wait for doit() (%d %s)\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:457 +msgid "while waiting to receive database" +msgstr "" + +#: ../../src/kprop/kpropd.c:461 +#, c-format +msgid "Database load process for full propagation completed.\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:499 +#, c-format +msgid "" +"%s: Standard input does not appear to be a network socket.\n" +"\t(Not run from inetd, and missing the -S option?)\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:512 +msgid "while attempting setsockopt (SO_KEEPALIVE)" +msgstr "" + +#: ../../src/kprop/kpropd.c:517 +#, c-format +msgid "Connection from %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:537 +#, c-format +msgid "Rejected connection from unauthorized principal %s\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:541 +#, c-format +msgid "Rejected connection from unauthorized principal %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:558 +#, c-format +msgid "while opening database file, '%s'" +msgstr "" + +#: ../../src/kprop/kpropd.c:564 +#, c-format +msgid "while renaming %s to %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:570 +#, c-format +msgid "while downgrading lock on '%s'" +msgstr "" + +#: ../../src/kprop/kpropd.c:577 +#, c-format +msgid "while unlocking '%s'" +msgstr "" + +#: ../../src/kprop/kpropd.c:589 +msgid "while sending # of received bytes" +msgstr "" + +#: ../../src/kprop/kpropd.c:595 +msgid "while trying to close database file" +msgstr "" + +#: ../../src/kprop/kpropd.c:650 +#, c-format +msgid "Incremental propagation enabled\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:659 +#, c-format +msgid "%s: unable to get kiprop host based service name for realm %s\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:669 +msgid "while trying to construct host service principal" +msgstr "" + +#: ../../src/kprop/kpropd.c:686 +#, c-format +msgid "Initializing kadm5 as client %s\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:700 +#, c-format +msgid "kadm5 initialization failed!\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:709 +msgid "while attempting to connect to primary KDC ... retrying" +msgstr "" + +#: ../../src/kprop/kpropd.c:713 +#, c-format +msgid "Sleeping %d seconds to re-initialize kadm5 (RPC ERROR)\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:729 +#, c-format +msgid "while initializing %s interface, retrying" +msgstr "" + +#: ../../src/kprop/kpropd.c:733 +#, c-format +msgid "Sleeping %d seconds to re-initialize kadm5 (krb5kdc not running?)\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:743 +#, c-format +msgid "kadm5 initialization succeeded\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:765 +msgid "reading update log header" +msgstr "" + +#: ../../src/kprop/kpropd.c:776 +#, c-format +msgid "Calling iprop_get_updates_1 (sno=%u sec=%u usec=%u)\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:786 +msgid "iprop_get_updates call failed" +msgstr "" + +#: ../../src/kprop/kpropd.c:792 +#, c-format +msgid "Reinitializing iprop because get updates failed\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:813 +#, c-format +msgid "Still waiting for full resync\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:818 +#, c-format +msgid "Full resync needed\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:819 +msgid "kpropd: Full resync needed." +msgstr "" + +#: ../../src/kprop/kpropd.c:824 +msgid "iprop_full_resync call failed" +msgstr "" + +#: ../../src/kprop/kpropd.c:835 +#, c-format +msgid "Full resync request granted\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:836 +msgid "Full resync request granted." +msgstr "" + +#: ../../src/kprop/kpropd.c:845 +#, c-format +msgid "Exponential backoff\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:851 +#, c-format +msgid "Full resync permission denied\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:852 +msgid "Full resync, permission denied." +msgstr "" + +#: ../../src/kprop/kpropd.c:857 +#, c-format +msgid "Full resync error from primary\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:858 +msgid " Full resync, error returned from primary KDC." +msgstr "" + +#: ../../src/kprop/kpropd.c:866 +#, c-format +msgid "Full resync invalid result from primary\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:868 +msgid "Full resync, invalid return from primary KDC." +msgstr "" + +#: ../../src/kprop/kpropd.c:884 +#, c-format +msgid "Got incremental updates (sno=%u sec=%u usec=%u)\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:896 +#, c-format +msgid "ulog_replay failed (%s), updates not registered\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:899 +#, c-format +msgid "ulog_replay failed (%s), updates not registered." +msgstr "" + +#: ../../src/kprop/kpropd.c:908 +#, c-format +msgid "Incremental updates: %d updates / %lu us" +msgstr "" + +#: ../../src/kprop/kpropd.c:911 +#, c-format +msgid "Incremental updates: %d updates / %lu us\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:919 +#, c-format +msgid "get_updates permission denied\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:920 +msgid "get_updates, permission denied." +msgstr "" + +#: ../../src/kprop/kpropd.c:925 +#, c-format +msgid "get_updates error from primary\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:927 +msgid "get_updates, error returned from primary KDC." +msgstr "" + +#: ../../src/kprop/kpropd.c:935 +#, c-format +msgid "get_updates primary busy; backoff\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:944 +#, c-format +msgid "KDC is synchronized with primary.\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:953 +#, c-format +msgid "get_updates invalid result from primary\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:956 +msgid "get_updates, invalid return from primary KDC." +msgstr "" + +#: ../../src/kprop/kpropd.c:971 +#, c-format +msgid "Busy signal received from primary, backoff for %d secs\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:978 +#, c-format +msgid "Waiting for %d seconds before checking for updates again\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:989 +#, c-format +msgid "ERROR returned by primary, bailing\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:990 +msgid "ERROR returned by primary KDC, bailing.\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:1109 +msgid "copying db args" +msgstr "" + +#: ../../src/kprop/kpropd.c:1134 +msgid "Unable to get default realm" +msgstr "" + +#: ../../src/kprop/kpropd.c:1141 +msgid "Unable to set default realm" +msgstr "" + +#: ../../src/kprop/kpropd.c:1151 +msgid "while trying to construct my service name" +msgstr "" + +#: ../../src/kprop/kpropd.c:1158 +msgid "while allocating filename for temp file" +msgstr "" + +#: ../../src/kprop/kpropd.c:1166 +msgid "while initializing" +msgstr "" + +#: ../../src/kprop/kpropd.c:1174 +msgid "Unable to map log!\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:1216 +#, c-format +msgid "Error in krb5_auth_con_ini: %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:1224 +#, c-format +msgid "Error in krb5_auth_con_setflags: %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:1237 +#, c-format +msgid "Error in krb5_auth_con_setaddrs: %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:1245 +#, c-format +msgid "Error in krb5_kt_resolve: %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:1254 +#, c-format +msgid "Error in krb5_recvauth: %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:1261 +#, c-format +msgid "Error in krb5_copy_prinicpal: %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:1278 +msgid "while unparsing ticket etype" +msgstr "" + +#: ../../src/kprop/kpropd.c:1282 +#, c-format +msgid "authenticated client: %s (etype == %s)\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:1362 +msgid "while reading size of database from client" +msgstr "" + +#: ../../src/kprop/kpropd.c:1372 +msgid "while decoding database size from client" +msgstr "" + +#: ../../src/kprop/kpropd.c:1380 +msgid "malformed database size message from client" +msgstr "" + +#: ../../src/kprop/kpropd.c:1392 +msgid "while initializing i_vector" +msgstr "" + +#: ../../src/kprop/kpropd.c:1397 +#, c-format +msgid "Full propagation transfer started.\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:1451 +#, c-format +msgid "Full propagation transfer finished.\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:1511 +msgid "while decoding error packet from client" +msgstr "" + +#: ../../src/kprop/kpropd.c:1520 +msgid "signaled from server" +msgstr "" + +#: ../../src/kprop/kpropd.c:1522 +#, c-format +msgid "Error text from client: %s\n" +msgstr "" + +#: ../../src/kprop/kpropd.c:1571 +#, c-format +msgid "while trying to fork %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:1575 +#, c-format +msgid "while trying to exec %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:1582 +#, c-format +msgid "while waiting for %s" +msgstr "" + +#: ../../src/kprop/kpropd.c:1588 +#, c-format +msgid "%s load terminated" +msgstr "" + +#: ../../src/kprop/kpropd.c:1594 +#, c-format +msgid "%s returned a bad exit status (%d)" +msgstr "" + +#: ../../src/kprop/kproplog.c:29 +#, c-format +msgid "" +"\n" +"Usage: %s [-h] [-v] [-v] [-e num]\n" +"\t%s -R\n" +"\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:112 +#, c-format +msgid "" +"\n" +"Couldn't allocate memory" +msgstr "" + +#: ../../src/kprop/kproplog.c:206 +#, c-format +msgid "\t\tAttribute flags\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:211 +#, c-format +msgid "\t\tMaximum ticket life\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:216 +#, c-format +msgid "\t\tMaximum renewable life\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:221 +#, c-format +msgid "\t\tPrincipal expiration\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:226 +#, c-format +msgid "\t\tPassword expiration\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:231 +#, c-format +msgid "\t\tLast successful auth\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:236 +#, c-format +msgid "\t\tLast failed auth\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:241 +#, c-format +msgid "\t\tFailed passwd attempt\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:246 +#, c-format +msgid "\t\tPrincipal\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:251 +#, c-format +msgid "\t\tKey data\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:258 +#, c-format +msgid "\t\tTL data\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:265 +#, c-format +msgid "\t\tLength\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:270 +#, c-format +msgid "\t\tPassword last changed\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:275 +#, c-format +msgid "\t\tModifying principal\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:280 +#, c-format +msgid "\t\tModification time\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:285 +#, c-format +msgid "\t\tModified where\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:290 +#, c-format +msgid "\t\tPassword policy\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:295 +#, c-format +msgid "\t\tPassword policy switch\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:300 +#, c-format +msgid "\t\tPassword history KVNO\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:305 +#, c-format +msgid "\t\tPassword history\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:339 +#, c-format +msgid "" +"Corrupt update entry\n" +"\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:344 +#, c-format +msgid "Update Entry\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:346 +#, c-format +msgid "\tUpdate serial # : %u\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:350 +#, c-format +msgid "\tDummy entry\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:358 +#, c-format +msgid "" +"Entry data decode failure\n" +"\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:362 +#, c-format +msgid "\tUpdate operation : " +msgstr "" + +#: ../../src/kprop/kproplog.c:364 +#, c-format +msgid "Delete\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:366 +#, c-format +msgid "Add\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:370 +#, c-format +msgid "" +"Could not allocate principal name\n" +"\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:376 +#, c-format +msgid "\tUpdate principal : %s\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:378 +#, c-format +msgid "\tUpdate size : %u\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:379 +#, c-format +msgid "\tUpdate committed : %s\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:383 +#, c-format +msgid "\tUpdate time stamp : None\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:385 +#, c-format +msgid "\tUpdate time stamp : %s" +msgstr "" + +#: ../../src/kprop/kproplog.c:389 +#, c-format +msgid "\tAttributes changed : %d\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:462 +#, c-format +msgid "" +"Unable to initialize Kerberos\n" +"\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:469 +#, c-format +msgid "" +"Couldn't read database_name\n" +"\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:473 +#, c-format +msgid "" +"\n" +"Kerberos update log (%s)\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:477 ../../src/kprop/kproplog.c:493 +#, c-format +msgid "" +"Unable to map log file %s\n" +"\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:482 +#, c-format +msgid "" +"Couldn't reinitialize ulog file %s\n" +"\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:486 +#, c-format +msgid "Reinitialized the ulog.\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:499 +#, c-format +msgid "" +"Corrupt header log, exiting\n" +"\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:503 +#, c-format +msgid "Update log dump :\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:504 +#, c-format +msgid "\tLog version # : %u\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:505 +#, c-format +msgid "\tLog state : " +msgstr "" + +#: ../../src/kprop/kproplog.c:508 +#, c-format +msgid "Stable\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:511 +#, c-format +msgid "Unstable\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:514 +#, c-format +msgid "Corrupt\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:517 +#, c-format +msgid "Unknown state: %d\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:520 +#, c-format +msgid "\tEntry block size : %u\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:521 +#, c-format +msgid "\tNumber of entries : %u\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:524 +#, c-format +msgid "\tLast serial # : None\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:527 +#, c-format +msgid "\tFirst serial # : None\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:529 +#, c-format +msgid "\tFirst serial # : " +msgstr "" + +#: ../../src/kprop/kproplog.c:533 +#, c-format +msgid "\tLast serial # : " +msgstr "" + +#: ../../src/kprop/kproplog.c:538 +#, c-format +msgid "\tLast time stamp : None\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:541 +#, c-format +msgid "\tFirst time stamp : None\n" +msgstr "" + +#: ../../src/kprop/kproplog.c:543 +#, c-format +msgid "\tFirst time stamp : %s" +msgstr "" + +#: ../../src/kprop/kproplog.c:547 +#, c-format +msgid "\tLast time stamp : %s\n" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:231 +msgid "Got signal to request exit" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:245 +msgid "Got signal to reset" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:311 +#, c-format +msgid "Invalid port %d" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:324 +#, c-format +msgid "Removing address %s since wildcard address is being added" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:331 +msgid "Address already added to server" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:494 +#, c-format +msgid "closing down fd %d" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:508 +#, c-format +msgid "descriptor %d closed but still in svc_fdset" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:534 +msgid "cannot create io event" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:539 +msgid "cannot save event" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:559 +#, c-format +msgid "file descriptor number %d too high" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:566 +msgid "cannot allocate storage for connection info" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:601 +#, c-format +msgid "Cannot create TCP server socket on %s" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:610 +#, c-format +msgid "TCP socket fd number %d (for %s) too high" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:617 +#, c-format +msgid "Cannot enable SO_REUSEADDR on fd %d" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:622 +#, c-format +msgid "setsockopt(%d,IPV6_V6ONLY,1) failed" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:625 +#, c-format +msgid "setsockopt(%d,IPV6_V6ONLY,1) worked" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:628 +msgid "no IPV6_V6ONLY socket option support" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:634 +#, c-format +msgid "Cannot bind server socket on %s" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:704 +#, c-format +msgid "Setting up %s socket for address %s" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:717 +#, c-format +msgid "Cannot listen on %s server socket on %s" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:726 +#, c-format +msgid "cannot set listening %s socket on %s non-blocking" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:734 +#, c-format +msgid "cannot set SO_LINGER on %s socket on %s" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:741 +#, c-format +msgid "Setting pktinfo on socket %s" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:746 +#, c-format +msgid "Cannot request packet info for UDP socket address %s port %d" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:748 +msgid "" +"System does not support pktinfo yet binding to a wildcard address. Packets " +"are not guaranteed to return on the received address." +msgstr "" + +#: ../../src/lib/apputils/net-server.c:760 +msgid "Error attempting to add verto event" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:769 +#, c-format +msgid "Cannot create RPC service: %s" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:779 +#, c-format +msgid "Cannot register RPC service: %s" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:823 +msgid "No addresses added to the net server" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:845 +#, c-format +msgid "Failed getting address info (for %s): %s" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:875 +#, c-format +msgid "Failed setting up a %s socket (for %s)" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:916 +msgid "setting up network..." +msgstr "" + +#: ../../src/lib/apputils/net-server.c:919 +msgid "Error setting up network" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:922 +#, c-format +msgid "set up %d sockets" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:925 +msgid "no sockets set up?" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:988 +#: ../../src/lib/apputils/net-server.c:1042 +msgid "while dispatching (udp)" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:1017 +#, c-format +msgid "while sending reply to %s/%s from %s" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:1022 +#, c-format +msgid "short reply write %d vs %d\n" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:1067 +msgid "while receiving from network" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:1110 +msgid "too many connections" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:1128 +#, c-format +msgid "dropping %s fd %d from %s" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:1198 +#, c-format +msgid "allocating buffer for new TCP session from %s" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:1230 +msgid "while dispatching (tcp)" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:1262 +msgid "error allocating tcp dispatch private!" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:1309 +#, c-format +msgid "TCP client %s wants %lu bytes, cap is %lu" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:1317 +#, c-format +msgid "error constructing KRB_ERR_FIELD_TOOLONG error! %s" +msgstr "" + +#: ../../src/lib/apputils/net-server.c:1356 +#, c-format +msgid "getsockname failed: %s" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:43 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:165 +msgid "A required input parameter could not be read" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:44 +msgid "A required input parameter could not be written" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:45 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:175 +msgid "A parameter was malformed" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:48 +msgid "calling error" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:59 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:195 +msgid "An unsupported mechanism was requested" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:60 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:199 +msgid "An invalid name was supplied" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:61 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:203 +msgid "A supplied name was of an unsupported type" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:62 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:208 +msgid "Incorrect channel bindings were supplied" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:63 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:179 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:274 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:334 +msgid "An invalid status code was supplied" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:64 +msgid "A token had an invalid signature" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:65 +msgid "No credentials were supplied" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:66 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:223 +msgid "No context has been established" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:67 +msgid "A token was invalid" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:68 +msgid "A credential was invalid" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:69 +msgid "The referenced credentials have expired" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:70 +msgid "The context has expired" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:71 +msgid "Miscellaneous failure" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:72 +msgid "The quality-of-protection requested could not be provided" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:73 +msgid "The operation is forbidden by the local security policy" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:74 +msgid "The operation or option is not available" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:77 +msgid "routine error" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:89 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:311 +msgid "The routine must be called again to complete its function" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:90 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:316 +msgid "The token was a duplicate of an earlier token" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:91 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:321 +msgid "The token's validity period has expired" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:92 +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:325 +msgid "A later token has already been processed" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:95 +msgid "supplementary info code" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:106 +#: ../lib/krb5/error_tables/krb5_err.c:23 +msgid "No error" +msgstr "" + +#: ../../src/lib/gssapi/generic/disp_major_status.c:107 +#, c-format +msgid "Unknown %s (field = %d)" +msgstr "" + +#: ../../src/lib/gssapi/krb5/acquire_cred.c:148 +#, c-format +msgid "No key table entry found matching %s" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:161 +msgid "The routine completed successfully" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:170 +msgid "A required output parameter could not be written" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:212 +msgid "A token had an invalid Message Integrity Check (MIC)" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:217 +msgid "" +"No credentials were supplied, or the credentials were unavailable or " +"inaccessible" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:227 +msgid "Invalid token was supplied" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:231 +msgid "Invalid credential was supplied" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:235 +msgid "The referenced credential has expired" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:239 +msgid "The referenced context has expired" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:243 +msgid "Unspecified GSS failure. Minor code may provide more information" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:248 +msgid "The quality-of-protection (QOP) requested could not be provided" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:253 +msgid "The operation is forbidden by local security policy" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:258 +msgid "The operation or option is not available or unsupported" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:263 +msgid "The requested credential element already exists" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:268 +msgid "The provided name was not mechanism specific (MN)" +msgstr "" + +#: ../../src/lib/gssapi/mechglue/g_dsp_status.c:329 +msgid "An expected per-message token was not received" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1750 +msgid "SPNEGO cannot find mechanisms to negotiate" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1752 +msgid "SPNEGO failed to acquire creds" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1754 +msgid "SPNEGO acceptor did not select a mechanism" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1756 +msgid "SPNEGO failed to negotiate a mechanism" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1758 +msgid "SPNEGO acceptor did not return a valid token" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1760 +msgid "Invalid NegoEx signature" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1762 +msgid "Invalid NegoEx message type" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1764 +msgid "Invalid NegoEx message size" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1766 +msgid "Invalid NegoEx conversation ID" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1768 +msgid "NegoEx authentication scheme not found" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1770 +msgid "Missing NegoEx negotiate message" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1772 +msgid "Missing NegoEx authentication protocol request message" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1774 +msgid "No mutually supported NegoEx authentication schemes" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1776 +msgid "No NegoEx verify key" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1778 +msgid "Unknown NegoEx checksum scheme" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1780 +msgid "Invalid NegoEx checksum" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1782 +msgid "Unsupported critical NegoEx extension" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1784 +msgid "Unsupported NegoEx version" +msgstr "" + +#: ../../src/lib/gssapi/spnego/spnego_mech.c:1786 +msgid "NegoEx message out of sequence" +msgstr "" + +#: ../../src/lib/kadm5/logger.c:54 +#, c-format +msgid "%s: cannot parse <%s>\n" +msgstr "" + +#: ../../src/lib/kadm5/logger.c:55 +#, c-format +msgid "%s: warning - logging entry syntax error\n" +msgstr "" + +#: ../../src/lib/kadm5/logger.c:56 +#, c-format +msgid "%s: error writing to %s\n" +msgstr "" + +#: ../../src/lib/kadm5/logger.c:57 +#, c-format +msgid "%s: error writing to %s device\n" +msgstr "" + +#: ../../src/lib/kadm5/logger.c:59 +msgid "EMERGENCY" +msgstr "" + +#: ../../src/lib/kadm5/logger.c:60 +msgid "ALERT" +msgstr "" + +#: ../../src/lib/kadm5/logger.c:61 +msgid "CRITICAL" +msgstr "" + +#: ../../src/lib/kadm5/logger.c:62 +msgid "Error" +msgstr "" + +#: ../../src/lib/kadm5/logger.c:63 +msgid "Warning" +msgstr "" + +#: ../../src/lib/kadm5/logger.c:64 +msgid "Notice" +msgstr "" + +#: ../../src/lib/kadm5/logger.c:65 +msgid "info" +msgstr "" + +#: ../../src/lib/kadm5/logger.c:66 +msgid "debug" +msgstr "" + +#: ../../src/lib/kadm5/logger.c:785 +#, c-format +msgid "Couldn't open log file %s: %s\n" +msgstr "" + +#: ../../src/lib/kadm5/srv/kadm5_hook.c:120 +#, c-format +msgid "kadm5_hook %s failed postcommit %s: %s" +msgstr "" + +#: ../../src/lib/kadm5/srv/pwqual_dict.c:106 +msgid "No dictionary file specified, continuing without one." +msgstr "" + +#: ../../src/lib/kadm5/srv/pwqual_dict.c:113 +#, c-format +msgid "WARNING! Cannot find dictionary file %s, continuing without one." +msgstr "" + +#: ../../src/lib/kadm5/srv/pwqual_empty.c:42 +msgid "Empty passwords are not allowed" +msgstr "" + +#: ../../src/lib/kadm5/srv/pwqual_hesiod.c:114 +msgid "Password may not match user information." +msgstr "" + +#: ../../src/lib/kadm5/srv/pwqual_princ.c:54 +msgid "Password may not match principal name" +msgstr "" + +#: ../../src/lib/kadm5/srv/server_kdb.c:197 +msgid "History entry contains no key data" +msgstr "" + +#: ../../src/lib/kadm5/srv/server_misc.c:128 +#, c-format +msgid "password quality module %s rejected password for %s: %s" +msgstr "" + +#: ../../src/lib/kdb/kdb5.c:216 +msgid "No default realm set; cannot initialize KDB" +msgstr "" + +#: ../../src/lib/kdb/kdb5.c:370 +#, c-format +msgid "Unable to find requested database type: %s" +msgstr "" + +#: ../../src/lib/kdb/kdb5.c:450 ../lib/krb5/error_tables/kdb5_err.c:55 +msgid "Unable to find requested database type" +msgstr "" + +#: ../../src/lib/kdb/kdb5.c:458 +msgid "plugin symbol 'kdb_function_table' lookup failed" +msgstr "" + +#: ../../src/lib/kdb/kdb5.c:466 +#, c-format +msgid "" +"Unable to load requested database module '%s': plugin symbol " +"'kdb_function_table' not found" +msgstr "" + +#: ../../src/lib/kdb/kdb5.c:604 +msgid "Cannot initialize database library" +msgstr "" + +#: ../../src/lib/kdb/kdb5.c:1770 +#, c-format +msgid "Illegal version number for KRB5_TL_MKEY_AUX %d\n" +msgstr "" + +#: ../../src/lib/kdb/kdb5.c:1942 +#, c-format +msgid "Illegal version number for KRB5_TL_ACTKVNO %d\n" +msgstr "" + +#: ../../src/lib/kdb/kdb_default.c:137 +#, c-format +msgid "keyfile (%s) is not a regular file: %s" +msgstr "" + +#: ../../src/lib/kdb/kdb_default.c:150 +msgid "Could not create temp keytab file name." +msgstr "" + +#: ../../src/lib/kdb/kdb_default.c:175 +#, c-format +msgid "Temporary stash file already exists: %s." +msgstr "" + +#: ../../src/lib/kdb/kdb_default.c:203 +#, c-format +msgid "rename of temporary keyfile (%s) to (%s) failed: %s" +msgstr "" + +#: ../../src/lib/kdb/kdb_default.c:388 +#, c-format +msgid "Can not fetch master key (error: %s)." +msgstr "" + +#: ../../src/lib/kdb/kdb_default.c:456 +msgid "Unable to decrypt latest master key with the provided master key\n" +msgstr "" + +#: ../../src/lib/kdb/kdb_log.c:87 +msgid "could not sync ulog update to disk" +msgstr "" + +#: ../../src/lib/kdb/kdb_log.c:101 +msgid "could not sync ulog header to disk" +msgstr "" + +#: ../../src/lib/krb5/ccache/cc_dir.c:122 +#, c-format +msgid "Subsidiary cache path %s has no parent directory" +msgstr "" + +#: ../../src/lib/krb5/ccache/cc_dir.c:128 +#, c-format +msgid "Subsidiary cache path %s filename does not begin with \"tkt\"" +msgstr "" + +#: ../../src/lib/krb5/ccache/cc_dir.c:169 +#, c-format +msgid "%s contains invalid filename" +msgstr "" + +#: ../../src/lib/krb5/ccache/cc_dir.c:229 +#, c-format +msgid "Credential cache directory %s does not exist" +msgstr "" + +#: ../../src/lib/krb5/ccache/cc_dir.c:235 +#, c-format +msgid "Credential cache directory %s exists but is not a directory" +msgstr "" + +#: ../../src/lib/krb5/ccache/cc_dir.c:400 +msgid "" +"Can't create new subsidiary cache because default cache is not a directory " +"collection" +msgstr "" + +#: ../../src/lib/krb5/ccache/cc_kcm.c:946 +#, c-format +msgid "Credentials cache 'KCM:%s' not found" +msgstr "" + +#: ../../src/lib/krb5/ccache/cc_keyring.c:1149 +msgid "" +"Can't create new subsidiary cache because default cache is already a " +"subsidiary" +msgstr "" + +#: ../../src/lib/krb5/ccache/cc_keyring.c:1217 +#, c-format +msgid "Credentials cache keyring '%s' not found" +msgstr "" + +#: ../../src/lib/krb5/ccache/cccursor.c:207 +#, c-format +msgid "Can't find client principal %s in cache collection" +msgstr "" + +#: ../../src/lib/krb5/ccache/cccursor.c:271 +msgid "No Kerberos credentials available" +msgstr "" + +#: ../../src/lib/krb5/ccache/cccursor.c:277 +#, c-format +msgid "No Kerberos credentials available (default cache: %s)" +msgstr "" + +#: ../../src/lib/krb5/keytab/kt_file.c:389 +#, c-format +msgid "No key table entry found for %s" +msgstr "" + +#: ../../src/lib/krb5/keytab/kt_file.c:537 +#: ../../src/lib/krb5/keytab/kt_file.c:570 +msgid "Cannot change keytab with keytab iterators active" +msgstr "" + +#: ../../src/lib/krb5/keytab/kt_file.c:757 +#, c-format +msgid "Key table file '%s' not found" +msgstr "" + +#: ../../src/lib/krb5/keytab/ktfns.c:129 +#, c-format +msgid "Keytab %s is nonexistent or empty" +msgstr "" + +#: ../../src/lib/krb5/krb/chpw.c:250 +msgid "Malformed request error" +msgstr "" + +#: ../../src/lib/krb5/krb/chpw.c:253 ../lib/krb5/error_tables/kdb5_err.c:58 +msgid "Server error" +msgstr "" + +#: ../../src/lib/krb5/krb/chpw.c:256 +msgid "Authentication error" +msgstr "" + +#: ../../src/lib/krb5/krb/chpw.c:259 +msgid "Password change rejected" +msgstr "" + +#: ../../src/lib/krb5/krb/chpw.c:262 +msgid "Access denied" +msgstr "" + +#: ../../src/lib/krb5/krb/chpw.c:265 +msgid "Wrong protocol version" +msgstr "" + +#: ../../src/lib/krb5/krb/chpw.c:268 +msgid "Initial password required" +msgstr "" + +#: ../../src/lib/krb5/krb/chpw.c:271 +msgid "Success" +msgstr "" + +#: ../../src/lib/krb5/krb/chpw.c:274 ../lib/krb5/error_tables/krb5_err.c:257 +msgid "Password change failed" +msgstr "" + +#: ../../src/lib/krb5/krb/chpw.c:432 +msgid "" +"The password must include numbers or symbols. Don't include any part of " +"your name in the password." +msgstr "" + +#: ../../src/lib/krb5/krb/chpw.c:438 +#, c-format +msgid "The password must contain at least %d character." +msgid_plural "The password must contain at least %d characters." +msgstr[0] "" +msgstr[1] "" + +#: ../../src/lib/krb5/krb/chpw.c:447 +#, c-format +msgid "The password must be different from the previous password." +msgid_plural "The password must be different from the previous %d passwords." +msgstr[0] "" +msgstr[1] "" + +#: ../../src/lib/krb5/krb/chpw.c:459 +#, c-format +msgid "The password can only be changed once a day." +msgid_plural "The password can only be changed every %d days." +msgstr[0] "" +msgstr[1] "" + +#: ../../src/lib/krb5/krb/chpw.c:503 +msgid "Try a more complex password, or contact your administrator." +msgstr "" + +#: ../../src/lib/krb5/krb/fast.c:216 +msgid "Error constructing AP-REQ armor" +msgstr "" + +#: ../../src/lib/krb5/krb/fast.c:394 +msgid "Failed to decrypt FAST reply" +msgstr "" + +#: ../../src/lib/krb5/krb/fast.c:400 +msgid "nonce modified in FAST response: KDC response modified" +msgstr "" + +#: ../../src/lib/krb5/krb/fast.c:466 +msgid "Expecting FX_ERROR pa-data inside FAST container" +msgstr "" + +#: ../../src/lib/krb5/krb/fast.c:537 +msgid "FAST response missing finish message in KDC reply" +msgstr "" + +#: ../../src/lib/krb5/krb/fast.c:550 +msgid "Ticket modified in KDC reply" +msgstr "" + +#: ../../src/lib/krb5/krb/gc_via_tkt.c:198 +#, c-format +msgid "KDC returned error string: %.*s" +msgstr "" + +#: ../../src/lib/krb5/krb/gc_via_tkt.c:207 +#, c-format +msgid "Server %s not found in Kerberos database" +msgstr "" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:202 +msgid "Reply has wrong form of session key for anonymous request" +msgstr "" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1569 +#, c-format +msgid "Warning: Your password will expire in less than one hour on %s" +msgstr "" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1573 +#, c-format +msgid "Warning: Your password will expire in %d hour%s on %s" +msgstr "" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1577 +#, c-format +msgid "Warning: Your password will expire in %d days on %s" +msgstr "" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1607 +#, c-format +msgid "" +"Warning: encryption type %s used for authentication is deprecated and will " +"be disabled" +msgstr "" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1852 +msgid "Failed to store credentials" +msgstr "" + +#: ../../src/lib/krb5/krb/get_in_tkt.c:1947 +#, c-format +msgid "Client '%s' not found in Kerberos database" +msgstr "" + +#: ../../src/lib/krb5/krb/gic_keytab.c:221 +#, c-format +msgid "Keytab contains no suitable keys for %s" +msgstr "" + +#: ../../src/lib/krb5/krb/gic_pwd.c:75 +#, c-format +msgid "Password for %s" +msgstr "" + +#: ../../src/lib/krb5/krb/gic_pwd.c:301 +msgid "Password expired. You must change it now." +msgstr "" + +#: ../../src/lib/krb5/krb/gic_pwd.c:320 ../../src/lib/krb5/krb/gic_pwd.c:324 +#, c-format +msgid "%s. Please try again." +msgstr "" + +#: ../../src/lib/krb5/krb/gic_pwd.c:365 +#, c-format +msgid "%.*s%s%s. Please try again.\n" +msgstr "" + +#: ../../src/lib/krb5/krb/parse.c:202 +#, c-format +msgid "Principal %s is missing required realm" +msgstr "" + +#: ../../src/lib/krb5/krb/parse.c:214 +#, c-format +msgid "Principal %s has realm present" +msgstr "" + +#: ../../src/lib/krb5/krb/plugin.c:169 +#, c-format +msgid "Invalid module specifier %s" +msgstr "" + +#: ../../src/lib/krb5/krb/plugin.c:416 +#, c-format +msgid "Could not find %s plugin module named '%s'" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth2.c:313 +msgid "krb5_init_creds calls must use same library context" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth2.c:721 +msgid "Pre-authentication failed" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth2.c:1050 +msgid "Unable to initialize preauth context" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth2.c:1063 +#, c-format +msgid "Preauth module %s" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_encts.c:71 +msgid "Encrypted timestamp is disabled" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_otp.c:514 +msgid "Please choose from the following:\n" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_otp.c:516 +msgid "Vendor:" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_otp.c:526 +msgid "Enter #" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_otp.c:562 +msgid "OTP Challenge:" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_otp.c:591 +msgid "OTP Token PIN" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_otp.c:705 +msgid "OTP value doesn't match any token formats" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_otp.c:772 +msgid "Enter OTP Token Value" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_otp.c:918 +msgid "No supported tokens" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:49 +msgid "Challenge for Enigma Logic mechanism" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:53 +msgid "Challenge for Digital Pathways mechanism" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:57 +msgid "Challenge for Activcard mechanism" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:60 +msgid "Challenge for Enhanced S/Key mechanism" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:63 +msgid "Challenge for Traditional S/Key mechanism" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:66 +#: ../../src/lib/krb5/krb/preauth_sam2.c:69 +msgid "Challenge for Security Dynamics mechanism" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:72 +msgid "Challenge from authentication server" +msgstr "" + +#: ../../src/lib/krb5/krb/preauth_sam2.c:164 +msgid "SAM Authentication" +msgstr "" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:146 +#, c-format +msgid "Cannot find key for %s kvno %d in keytab" +msgstr "" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:151 +#, c-format +msgid "Cannot find key for %s kvno %d in keytab (request ticket server %s)" +msgstr "" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:176 +#, c-format +msgid "Cannot decrypt ticket for %s using keytab key for %s" +msgstr "" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:198 +#, c-format +msgid "Server principal %s does not match request ticket server %s" +msgstr "" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:227 +msgid "No keys in keytab" +msgstr "" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:230 +#, c-format +msgid "Server principal %s does not match any keys in keytab" +msgstr "" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:237 +#, c-format +msgid "" +"Request ticket server %s found in keytab but does not match server principal " +"%s" +msgstr "" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:242 +#, c-format +msgid "Request ticket server %s not found in keytab (ticket kvno %d)" +msgstr "" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:248 +#, c-format +msgid "" +"Request ticket server %s kvno %d not found in keytab; ticket is likely out " +"of date" +msgstr "" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:253 +#, c-format +msgid "" +"Request ticket server %s kvno %d not found in keytab; keytab is likely out " +"of date" +msgstr "" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:262 +#, c-format +msgid "" +"Request ticket server %s kvno %d found in keytab but not with enctype %s" +msgstr "" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:267 +#, c-format +msgid "" +"Request ticket server %s kvno %d enctype %s found in keytab but cannot " +"decrypt ticket" +msgstr "" + +#: ../../src/lib/krb5/krb/rd_req_dec.c:884 +#, c-format +msgid "Encryption type %s not permitted" +msgstr "" + +#: ../../src/lib/krb5/krb/s4u_creds.c:1043 +msgid "Realm specified but S4U2Proxy must use referral realm" +msgstr "" + +#: ../../src/lib/krb5/os/expand_path.c:316 +#, c-format +msgid "Can't find username for uid %lu" +msgstr "" + +#: ../../src/lib/krb5/os/expand_path.c:405 +#: ../../src/lib/krb5/os/expand_path.c:421 +msgid "Invalid token" +msgstr "" + +#: ../../src/lib/krb5/os/expand_path.c:506 +msgid "variable missing }" +msgstr "" + +#: ../../src/lib/krb5/os/locate_kdc.c:818 +#, c-format +msgid "Cannot find KDC for realm \"%.*s\"" +msgstr "" + +#: ../../src/lib/krb5/os/sendto_kdc.c:519 +#, c-format +msgid "Cannot contact any KDC for realm '%.*s'" +msgstr "" + +#: ../../src/plugins/kdb/db2/kdb_db2.c:245 +#: ../../src/plugins/kdb/db2/kdb_db2.c:819 +#, c-format +msgid "Unsupported argument \"%s\" for db2" +msgstr "" + +#: ../../src/plugins/kdb/db2/kdb_db2.c:387 +#, c-format +msgid "Cannot open DB2 database '%s'" +msgstr "" + +#: ../../src/plugins/kdb/db2/kdb_db2.c:989 +msgid "Recursive iteration is not supported for hash databases" +msgstr "" + +#: ../../src/plugins/kdb/db2/kdb_db2.c:996 +msgid "Recursive iteration not supported in this version of libdb" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:69 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:851 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1052 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1459 +msgid "while reading kerberos container information" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:129 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:143 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:504 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:518 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:147 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:162 +msgid "while providing time specification" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:268 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:304 +msgid "while creating policy object" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:279 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1467 +msgid "while reading realm information" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:348 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:407 +msgid "while destroying policy object" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:358 +#, c-format +msgid "This will delete the policy object '%s', are you sure?\n" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:473 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:663 +msgid "while modifying policy object" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:487 +#, c-format +msgid "while reading information of policy '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:692 +msgid "while viewing policy" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:701 +#, c-format +msgid "while viewing policy '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_policy.c:835 +msgid "while listing policy objects" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:411 +#, c-format +msgid "for subtree while creating realm '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:423 +#, c-format +msgid "for container reference while creating realm '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:448 +#, c-format +msgid "invalid search scope while creating realm '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:463 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:787 +#, c-format +msgid "'%s' is an invalid option\n" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:471 +#, c-format +msgid "Initializing database for realm '%s'\n" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:495 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:656 +#, c-format +msgid "while creating realm '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:515 +#, c-format +msgid "Enter DN of Kerberos container: " +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:550 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:858 +#, c-format +msgid "while reading information of realm '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:694 +msgid "while reading Kerberos container information" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:737 +#, c-format +msgid "for subtree while modifying realm '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:748 +#, c-format +msgid "for container reference while modifying realm '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:776 +#, c-format +msgid "specified for search scope while modifying information of realm '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:815 +#, c-format +msgid "while modifying information of realm '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:904 +msgid "Realm Name" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:907 +msgid "Subtree" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:910 +msgid "Principal Container Reference" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:915 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:917 +msgid "SearchScope" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:915 +msgid "Invalid !" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:922 +msgid "KDC Services" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:937 +msgid "Admin Services" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:952 +msgid "Passwd Services" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:968 +msgid "Maximum Ticket Life" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:973 +msgid "Maximum Renewable Life" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:980 +msgid "Ticket flags" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1059 +msgid "while listing realms" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1391 +msgid "while adding entries to database" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1432 +#, c-format +msgid "Deleting KDC database of '%s', are you sure?\n" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1443 +#, c-format +msgid "OK, deleting database of '%s'...\n" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1476 +#, c-format +msgid "deleting database of '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_realm.c:1481 +#, c-format +msgid "** Database of '%s' destroyed.\n" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:79 +msgid "ldap_service_password_file not configured" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:124 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:131 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:141 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:169 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:239 +msgid "while setting service object password" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:148 +msgid "while getting service password filename" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:161 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:481 +#, c-format +msgid "Password for \"%s\"" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:164 +#, c-format +msgid "Re-enter password for \"%s\"" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:175 +#, c-format +msgid "%s: Invalid password\n" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:185 +msgid "Failed to convert the password to hexadecimal" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:195 +#, c-format +msgid "Failed to open file %s: %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:217 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:259 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:268 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:295 +msgid "Failed to write service object password to file" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:223 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:280 +msgid "Error reading service object password file" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_services.c:248 +#, c-format +msgid "Error creating file %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:105 +#, c-format +msgid "" +"Usage: kdb5_ldap_util [-D user_dn [-w passwd]] [-H ldapuri] [-r realm]\n" +"\tcmd [cmd_options]\n" +"create [-subtrees subtree_dn_list] [-sscope search_scope]\n" +"\t\t[-containerref container_reference_dn]\n" +"\t\t[-m|-P password|-sf stashfilename] [-s]\n" +"\t\t[-k mkeytype] [-kv mkeyVNO] [-M mkeyname]\n" +"\t\t[-maxtktlife max_ticket_life]\n" +"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags]\n" +"modify [-subtrees subtree_dn_list] [-sscope search_scope]\n" +"\t\t[-containerref container_reference_dn]\n" +"\t\t[-maxtktlife max_ticket_life]\n" +"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags]\n" +"view\n" +"destroy [-f]\n" +"list\n" +"stashsrvpw [-f filename] service_dn\n" +"create_policy [-maxtktlife max_ticket_life]\n" +"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n" +"modify_policy [-maxtktlife max_ticket_life]\n" +"\t\t[-maxrenewlife max_renewable_ticket_life] [ticket_flags] policy\n" +"view_policy policy\n" +"destroy_policy [-force] policy\n" +"list_policy\n" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:329 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:337 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:345 +msgid "while reading ldap parameters" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:443 +msgid "while initializing error handling" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:451 +msgid "while initializing ldap handle" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:465 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:474 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:487 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:529 +msgid "while retrieving ldap configuration" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:504 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:511 +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:520 +msgid "while initializing server list" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:551 +msgid "while setting up lib handle" +msgstr "" + +#: ../../src/plugins/kdb/ldap/ldap_util/kdb5_ldap_util.c:560 +msgid "while reading ldap configuration" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:68 +msgid "Unable to read Kerberos container" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:73 +msgid "Unable to read Realm" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:214 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c:71 +msgid "Error processing LDAP DB params" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c:220 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_create.c:77 +msgid "Error reading LDAP server params" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:64 +msgid "LDAP bind dn value missing" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:69 +msgid "LDAP bind password value missing" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:78 +msgid "Error reading password from stash" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:85 +msgid "Service password length is zero" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:145 +#, c-format +msgid "Cannot bind to LDAP server '%s' with SASL mechanism '%s': %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:158 +#, c-format +msgid "Cannot bind to LDAP server '%s' as '%s': %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c:183 +#, c-format +msgid "Cannot create LDAP handle for '%s': %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c:56 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c:67 +msgid "Error reading kerberos container location from krb5.conf" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_krbcontainer.c:75 +msgid "Kerberos container location not specified" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:56 +#, c-format +msgid "Error reading '%s' attribute: %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:219 +msgid "KDB module requires -update argument" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:225 +#, c-format +msgid "'%s' value missing" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:283 +#, c-format +msgid "unknown option '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c:343 +msgid "Minimum connections required per server is 2" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c:160 +msgid "Default realm not set" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c:264 +msgid "DN information missing" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c:476 +msgid "dn information missing" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:137 +msgid "Principal does not belong to realm" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:305 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:314 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:322 +#, c-format +msgid "%s option not supported" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:329 +#, c-format +msgid "unknown option: %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:336 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:343 +#, c-format +msgid "%s option value missing" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:676 +msgid "DN is out of the realm subtree" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:708 +msgid "ldap object is already kerberized" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:803 +msgid "Principal does not belong to the default realm" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:869 +#, c-format +msgid "" +"operation can not continue, more than one entry with principal name \"%s\" " +"found" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:928 +#, c-format +msgid "'%s' not found" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:992 +#, c-format +msgid "" +"link information can not be set/updated as the kerberos principal belongs to " +"an ldap object" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1007 +#, c-format +msgid "Failed getting object references" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1014 +#, c-format +msgid "kerberos principal is already linked to a ldap object" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1340 +msgid "ticket policy object value: " +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1388 +#, c-format +msgid "Principal delete failed (trying to replace entry): %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1398 +#, c-format +msgid "Principal add failed: %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1436 +#, c-format +msgid "User modification failed: %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1510 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:294 +msgid "Error reading ticket policy" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1640 +msgid "unable to decode stored principal key data" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_principal2.c:1698 +msgid "unable to decode stored principal pw history" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:223 +msgid "Realm information not available" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:306 +#, c-format +msgid "Realm Delete FAILED: %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:386 +msgid "subtree value: " +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:403 +msgid "container reference value: " +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:486 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:549 +msgid "Kerberos Container information is missing" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:498 +msgid "Invalid Kerberos container DN" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:514 +#, c-format +msgid "Kerberos Container create FAILED: %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:557 +#, c-format +msgid "Kerberos Container delete FAILED: %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_realm.c:633 +msgid "realm object value: " +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:48 +msgid "Not a hexadecimal password" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:55 +msgid "Password corrupt" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:78 +#, c-format +msgid "Cannot open LDAP password file '%s': %s" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_service_stash.c:108 +#, c-format +msgid "Bind DN entry '%s' missing in LDAP password file '%s'" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:66 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:142 +msgid "Ticket Policy Name missing" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:154 +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:231 +msgid "ticket policy object: " +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:219 +msgid "Ticket Policy Object information missing" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:311 +msgid "Ticket Policy Object DN missing" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:338 +msgid "Delete Failed: One or more Principals associated with the Ticket Policy" +msgstr "" + +#: ../../src/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c:447 +msgid "Error reading container object" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:132 +#, c-format +msgid "%s (path: %s): %s" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:164 +#, c-format +msgid "Unsupported argument \"%s\" for LMDB" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:294 +msgid "LMDB environment open failure" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:319 +msgid "LMDB read failure" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:394 +msgid "LMDB write failure" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:418 +msgid "LMDB delete failure" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:521 +#, c-format +msgid "LMDB file %s does not exist" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:566 +msgid "LMDB open failure" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:593 +#, c-format +msgid "LMDB file %s already exists" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:658 +msgid "LMDB create error" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:676 +#, c-format +msgid "Could not unlink %s" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:760 +#, c-format +msgid "Unsupported argument \"%s\" for lmdb" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:806 +msgid "LMDB lockout write failure" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:882 +msgid "LMDB principal iteration failure" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:985 +msgid "LMDB policy iteration failure" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:1016 +msgid "LMDB transaction commit failure" +msgstr "" + +#: ../../src/plugins/kdb/lmdb/kdb_lmdb.c:1115 +msgid "LMDB lockout update failure" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_clnt.c:1088 +msgid "No pkinit_anchors supplied" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:920 +#, c-format +msgid "%s: %s" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:950 +#, c-format +msgid "%s (depth %d): %s" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1193 +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:4135 +msgid "Pass phrase for" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1479 +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1489 +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1743 +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1753 +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2224 +msgid "Failed to DER encode PKCS7" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1576 +msgid "Failed to verify own certificate" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1727 +msgid "Failed to add digest attribute" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1849 +msgid "Failed to decode CMS message" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1867 +msgid "Invalid pkinit packet: octet string expected" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:1885 +msgid "wrong oid\n" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2037 +msgid "Failed to verify received certificate" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2068 +msgid "Failed to verify CMS message" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2212 +msgid "Failed to encrypt PKCS7 object" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2270 +msgid "Failed to decode PKCS7" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2288 +msgid "Failed to decrypt PKCS7 message" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2711 +msgid "Failed to fetch SSKDF" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2718 +msgid "Failed to instantiate SSKDF" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2731 +msgid "Failed to derive key using SSKDF" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:2793 +msgid "Failed to compute digest" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:4255 +#, c-format +msgid "Cannot read certificate file '%s'" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:4263 +#, c-format +msgid "Cannot read key file '%s'" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:5114 +#, c-format +msgid "Cannot open file '%s'" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_crypto_openssl.c:5121 +#, c-format +msgid "Cannot read file '%s'" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_identity.c:415 +#, c-format +msgid "Unsupported type while processing '%s'\n" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_identity.c:451 +msgid "Internal error parsing X509_user_identity\n" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_identity.c:552 +msgid "No user identity options specified" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:403 +#, c-format +msgid "PKINIT: no freshness token, rejecting auth from %s" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:407 +#, c-format +msgid "PKINIT: freshness token received from %s" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:409 +#, c-format +msgid "PKINIT: no freshness token received from %s" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:512 +msgid "Pkinit request not signed, but client not anonymous." +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:546 +msgid "Anonymous pkinit without DH public value not supported." +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1082 +#, c-format +msgid "No pkinit_identity supplied for realm %s" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1093 +#, c-format +msgid "No pkinit_anchors supplied for realm %s" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1113 +#, c-format +msgid "OCSP is not supported: (realm: %s)" +msgstr "" + +#: ../../src/plugins/preauth/pkinit/pkinit_srv.c:1516 +msgid "No realms configured correctly for pkinit support" +msgstr "" + +#: ../../src/plugins/preauth/spake/groups.c:237 +msgid "No SPAKE preauth groups configured" +msgstr "" + +#: ../../src/plugins/preauth/spake/groups.c:257 +#, c-format +msgid "SPAKE challenge group not a permitted group: %s" +msgstr "" + +#: ../../src/plugins/preauth/spake/spake_kdc.c:534 +msgid "Unknown SPAKE request type" +msgstr "" + +#: ../../src/util/support/errors.c:77 +msgid "Kerberos library initialization failure" +msgstr "" + +#: ../../src/util/support/errors.c:83 +msgid "Error code translation unavailable" +msgstr "" + +#: ../../src/util/support/errors.c:92 +#, c-format +msgid "error %ld" +msgstr "" + +#: ../../src/util/support/plugins.c:94 ../../src/util/support/plugins.c:116 +msgid "unknown failure" +msgstr "" + +#: ../../src/util/support/plugins.c:96 +#, c-format +msgid "unable to load plugin [%s]: %s" +msgstr "" + +#: ../../src/util/support/plugins.c:142 +#, c-format +msgid "unable to load DLL [%s]" +msgstr "" + +#: ../../src/util/support/plugins.c:166 +#, c-format +msgid "unable to get DLL Symbol: %s" +msgstr "" + +#: ../../src/util/support/plugins.c:190 +msgid "plugin loading unavailable" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:23 +msgid "No @ in SERVICE-NAME name string" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:24 +msgid "STRING-UID-NAME contains nondigits" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:25 +msgid "UID does not resolve to username" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:26 +msgid "Validation error" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:27 +msgid "Couldn't allocate gss_buffer_t data" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:28 +msgid "Message context invalid" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:29 +msgid "Buffer is the wrong size" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:30 +msgid "Credential usage type is unknown" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:31 +msgid "Unknown quality of protection specified" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:32 +msgid "Local host name could not be determined" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:33 +msgid "Hostname in SERVICE-NAME string could not be canonicalized" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:34 +msgid "Mechanism is incorrect" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:35 +msgid "Token header is malformed or corrupt" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:36 +msgid "Packet was replayed in wrong direction" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:37 +msgid "Token is missing data" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:38 +msgid "Token was reflected" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:39 +msgid "Received token ID does not match expected token ID" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:40 +msgid "The given credential's usage does not match the requested usage" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:41 +msgid "Storing of acceptor credentials is not supported by the mechanism" +msgstr "" + +#: ../lib/gssapi/generic/gssapi_err_generic.c:42 +msgid "Storing of non-default credentials is not supported by the mechanism" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:23 +msgid "Principal in credential cache does not match desired name" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:24 +msgid "No principal in keytab matches desired name" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:25 +msgid "Credential cache has no TGT" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:26 +msgid "Authenticator has no subkey" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:27 +msgid "Context is already fully established" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:28 +msgid "Unknown signature type in token" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:29 +msgid "Invalid field length in token" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:30 +msgid "Attempt to use incomplete security context" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:31 +msgid "Bad magic number for krb5_gss_ctx_id_t" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:32 +msgid "Bad magic number for krb5_gss_cred_id_t" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:33 +msgid "Bad magic number for krb5_gss_enc_desc" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:34 +msgid "Sequence number in token is corrupt" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:35 +msgid "Credential cache is empty" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:36 +msgid "Acceptor and Initiator share no checksum types" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:37 +msgid "Requested lucid context version not supported" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:38 +msgid "PRF input too long" +msgstr "" + +#: ../lib/gssapi/krb5/gssapi_err_krb5.c:39 +msgid "Bad magic number for iakerb_ctx_id_t" +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:23 +msgid "while getting policy info." +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:24 +msgid "while getting principal info." +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:25 +msgid "New passwords do not match - password not changed.\n" +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:26 +msgid "New password" +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:27 +msgid "New password (again)" +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:28 +msgid "" +"You must type a password. Passwords must be at least one character long.\n" +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:29 +msgid "yet no policy set! Contact your system security administrator." +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:31 +msgid "" +"New password was found in a dictionary of possible passwords and\n" +"therefore may be easily guessed. Please choose another password.\n" +"See the kpasswd man page for help in choosing a good password." +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:32 +msgid "Password not changed." +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:33 +#, c-format +msgid "" +"New password is too short.\n" +"Please choose a password which is at least %d characters long." +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:34 +#, c-format +msgid "" +"New password does not have enough character classes.\n" +"The character classes are:\n" +"\t- lower-case letters,\n" +"\t- upper-case letters,\n" +"\t- digits,\n" +"\t- punctuation, and\n" +"\t- all other characters (e.g., control characters).\n" +"Please choose a password with at least %d character classes." +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:35 +#, c-format +msgid "" +"Password cannot be changed because it was changed too recently.\n" +"Please wait until %s before you change it.\n" +"If you need to change your password before then, contact your system\n" +"security administrator." +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:36 +msgid "New password was used previously. Please choose a different password." +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:37 +msgid "while trying to change password." +msgstr "" + +#: ../lib/kadm5/chpass_util_strings.c:38 +msgid "while reading new password." +msgstr "" + +#: ../lib/kadm5/kadm_err.c:23 +msgid "Operation failed for unspecified reason" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:24 +msgid "Operation requires ``get'' privilege" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:25 +msgid "Operation requires ``add'' privilege" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:26 +msgid "Operation requires ``modify'' privilege" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:27 +msgid "Operation requires ``delete'' privilege" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:28 +msgid "Insufficient authorization for operation" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:29 ../lib/kdb/adb_err.c:29 +msgid "Database inconsistency detected" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:30 ../lib/kdb/adb_err.c:24 +msgid "Principal or policy already exists" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:31 +msgid "Communication failure with server" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:32 +msgid "No administration server found for realm" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:33 +msgid "Password history principal key version mismatch" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:34 +msgid "Connection to server not initialized" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:35 +msgid "Principal does not exist" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:36 +msgid "Policy does not exist" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:37 +msgid "Invalid field mask for operation" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:38 +msgid "Invalid number of character classes" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:39 +msgid "Invalid password length" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:40 +msgid "Illegal policy name" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:41 +msgid "Illegal principal name" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:42 +msgid "Invalid auxiliary attributes" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:43 +msgid "Invalid password history count" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:44 +msgid "Password minimum life is greater than password maximum life" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:45 +msgid "Password is too short" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:46 +msgid "Password does not contain enough character classes" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:47 +msgid "Password is in the password dictionary" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:48 +msgid "Cannot reuse password" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:49 +msgid "Current password's minimum life has not expired" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:50 ../lib/krb5/error_tables/kdb5_err.c:67 +msgid "Policy is in use" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:51 +msgid "Connection to server already initialized" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:52 +msgid "Incorrect password" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:53 +msgid "Cannot change protected principal" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:54 +msgid "Programmer error! Bad Admin server handle" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:55 +msgid "Programmer error! Bad API structure version" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:56 +msgid "" +"API structure version specified by application is no longer supported (to " +"fix, recompile application against current KADM5 API header files and " +"libraries)" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:57 +msgid "" +"API structure version specified by application is unknown to libraries (to " +"fix, obtain current KADM5 API header files and libraries and recompile " +"application)" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:58 +msgid "Programmer error! Bad API version" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:59 +msgid "" +"API version specified by application is no longer supported by libraries (to " +"fix, update application to adhere to current API version and recompile)" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:60 +msgid "" +"API version specified by application is no longer supported by server (to " +"fix, update application to adhere to current API version and recompile)" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:61 +msgid "" +"API version specified by application is unknown to libraries (to fix, obtain " +"current KADM5 API header files and libraries and recompile application)" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:62 +msgid "" +"API version specified by application is unknown to server (to fix, obtain " +"and install newest KADM5 Admin Server)" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:63 +msgid "Database error! Required KADM5 principal missing" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:64 +msgid "The salt type of the specified principal does not support renaming" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:65 +msgid "Illegal configuration parameter for remote KADM5 client" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:66 +msgid "Illegal configuration parameter for local KADM5 client" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:67 +msgid "Operation requires ``list'' privilege" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:68 +msgid "Operation requires ``change-password'' privilege" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:69 +msgid "GSS-API (or Kerberos) error" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:70 +msgid "Programmer error! Illegal tagged data list type" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:71 +msgid "Required parameters in kdc.conf missing" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:72 +msgid "Bad krb5 admin server hostname" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:73 +msgid "Operation requires ``set-key'' privilege" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:74 +msgid "Multiple values for single or folded enctype" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:75 +msgid "Invalid enctype for setv4key" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:76 +msgid "Mismatched enctypes for setkey3" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:77 +msgid "Missing parameters in krb5.conf required for kadmin client" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:78 ../lib/kdb/adb_err.c:30 +msgid "XDR encoding error" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:79 +msgid "Cannot resolve network address for admin server in requested realm" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:80 +msgid "Unspecified password quality failure" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:81 +msgid "Invalid key/salt tuples" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:82 +msgid "Invalid multiple or duplicate kvnos in setkey operation" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:83 +msgid "Operation requires ``extract-keys'' privilege" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:84 +msgid "Principal keys are locked down" +msgstr "" + +#: ../lib/kadm5/kadm_err.c:85 +msgid "Operation requires initial ticket" +msgstr "" + +#: ../lib/kdb/adb_err.c:23 +msgid "No Error" +msgstr "" + +#: ../lib/kdb/adb_err.c:25 +msgid "Principal or policy does not exist" +msgstr "" + +#: ../lib/kdb/adb_err.c:26 +msgid "Database not initialized" +msgstr "" + +#: ../lib/kdb/adb_err.c:27 +msgid "Invalid policy name" +msgstr "" + +#: ../lib/kdb/adb_err.c:28 +msgid "Invalid principal name" +msgstr "" + +#: ../lib/kdb/adb_err.c:31 +msgid "Failure!" +msgstr "" + +#: ../lib/kdb/adb_err.c:32 +msgid "Bad lock mode" +msgstr "" + +#: ../lib/kdb/adb_err.c:33 +msgid "Cannot lock database" +msgstr "" + +#: ../lib/kdb/adb_err.c:34 +msgid "Database not locked" +msgstr "" + +#: ../lib/kdb/adb_err.c:35 +msgid "KADM5 administration database lock file missing" +msgstr "" + +#: ../lib/kdb/adb_err.c:36 +msgid "Insufficient permission to lock file" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:23 +msgid "Plugin does not support interface version" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:24 +msgid "Invalid module specifier" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:25 +msgid "Plugin module name not found" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:26 +msgid "The KDC should discard this request" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:27 +msgid "Can't create new subsidiary cache" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:28 +msgid "Invalid keyring anchor name" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:29 +msgid "Unknown keyring collection version" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:30 +msgid "Invalid UID in persistent keyring name" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:31 +msgid "Malformed reply from KCM daemon" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:32 +msgid "Mach RPC error communicating with KCM daemon" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:33 +msgid "KCM daemon reply too big" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:34 +msgid "No KCM server found" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:35 +msgid "Authorize and set hw-authent ticket flag" +msgstr "" + +#: ../lib/krb5/error_tables/k5e1_err.c:36 +msgid "Set hw-authent ticket flag but do not authorize" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:24 +msgid "Client's entry in database has expired" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:25 +msgid "Server's entry in database has expired" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:26 +msgid "Requested protocol version not supported" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:27 +msgid "Client's key is encrypted in an old master key" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:28 +msgid "Server's key is encrypted in an old master key" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:29 +msgid "Client not found in Kerberos database" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:30 +msgid "Server not found in Kerberos database" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:31 +msgid "Principal has multiple entries in Kerberos database" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:32 +msgid "Client or server has a null key" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:33 +msgid "Ticket is ineligible for postdating" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:34 +msgid "Requested effective lifetime is negative or too short" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:35 +msgid "KDC policy rejects request" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:36 +msgid "KDC can't fulfill requested option" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:37 +msgid "KDC has no support for encryption type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:38 +msgid "KDC has no support for checksum type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:39 +msgid "KDC has no support for padata type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:40 +msgid "KDC has no support for transited type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:41 +msgid "Client's credentials have been revoked" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:42 +msgid "Credentials for server have been revoked" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:43 +msgid "TGT has been revoked" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:44 +msgid "Client not yet valid - try again later" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:45 +msgid "Server not yet valid - try again later" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:46 +msgid "Password has expired" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:47 +msgid "Preauthentication failed" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:48 +msgid "Additional pre-authentication required" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:49 +msgid "Requested server and ticket don't match" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:50 +msgid "Server principal valid for user2user only" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:51 +msgid "KDC policy rejects transited path" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:52 +msgid "A service is not available that is required to process the request" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:53 +msgid "KRB5 error code 30" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:54 +msgid "Decrypt integrity check failed" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:55 +msgid "Ticket expired" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:56 +msgid "Ticket not yet valid" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:57 +msgid "Request is a replay" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:58 +msgid "The ticket isn't for us" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:59 +msgid "Ticket/authenticator don't match" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:60 +msgid "Clock skew too great" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:61 +msgid "Incorrect net address" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:62 +msgid "Protocol version mismatch" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:63 +msgid "Invalid message type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:64 +msgid "Message stream modified" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:65 +msgid "Message out of order" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:66 +msgid "Illegal cross-realm ticket" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:67 +msgid "Key version is not available" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:68 +msgid "Service key not available" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:69 +#: ../lib/krb5/error_tables/krb5_err.c:181 +msgid "Mutual authentication failed" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:70 +msgid "Incorrect message direction" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:71 +msgid "Alternative authentication method required" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:72 +msgid "Incorrect sequence number in message" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:73 +msgid "Inappropriate type of checksum in message" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:74 +msgid "Policy rejects transited path" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:75 +msgid "Response too big for UDP, retry with TCP" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:76 +msgid "KRB5 error code 53" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:77 +msgid "KRB5 error code 54" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:78 +msgid "KRB5 error code 55" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:79 +msgid "KRB5 error code 56" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:80 +msgid "KRB5 error code 57" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:81 +msgid "KRB5 error code 58" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:82 +msgid "KRB5 error code 59" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:83 +msgid "Generic error (see e-text)" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:84 +msgid "Field is too long for this implementation" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:85 +msgid "Client not trusted" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:86 +msgid "KDC not trusted" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:87 +msgid "Invalid signature" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:88 +msgid "Key parameters not accepted" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:89 +msgid "Certificate mismatch" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:90 +msgid "No ticket granting ticket" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:91 +msgid "Realm not local to KDC" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:92 +msgid "User to user required" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:93 +msgid "Can't verify certificate" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:94 +msgid "Invalid certificate" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:95 +msgid "Revoked certificate" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:96 +msgid "Revocation status unknown" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:97 +msgid "Revocation status unavailable" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:98 +msgid "Client name mismatch" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:99 +msgid "KDC name mismatch" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:100 +msgid "Inconsistent key purpose" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:101 +msgid "Digest in certificate not accepted" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:102 +msgid "Checksum must be included" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:103 +msgid "Digest in signed-data not accepted" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:104 +msgid "Public key encryption not supported" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:105 +msgid "KRB5 error code 82" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:106 +msgid "KRB5 error code 83" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:107 +msgid "KRB5 error code 84" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:108 +msgid "The IAKERB proxy could not find a KDC" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:109 +msgid "The KDC did not respond to the IAKERB proxy" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:110 +msgid "KRB5 error code 87" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:111 +msgid "KRB5 error code 88" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:112 +msgid "KRB5 error code 89" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:113 +msgid "Preauthentication expired" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:114 +msgid "More preauthentication data is required" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:115 +msgid "KRB5 error code 92" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:116 +msgid "An unsupported critical FAST option was requested" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:117 +msgid "KRB5 error code 94" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:118 +msgid "KRB5 error code 95" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:119 +msgid "KRB5 error code 96" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:120 +msgid "KRB5 error code 97" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:121 +msgid "KRB5 error code 98" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:122 +msgid "KRB5 error code 99" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:123 +msgid "No acceptable KDF offered" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:124 +msgid "KRB5 error code 101" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:125 +msgid "KRB5 error code 102" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:126 +msgid "KRB5 error code 103" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:127 +msgid "KRB5 error code 104" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:128 +msgid "KRB5 error code 105" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:129 +msgid "KRB5 error code 106" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:130 +msgid "KRB5 error code 107" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:131 +msgid "KRB5 error code 108" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:132 +msgid "KRB5 error code 109" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:133 +msgid "KRB5 error code 110" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:134 +msgid "KRB5 error code 111" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:135 +msgid "KRB5 error code 112" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:136 +msgid "KRB5 error code 113" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:137 +msgid "KRB5 error code 114" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:138 +msgid "KRB5 error code 115" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:139 +msgid "KRB5 error code 116" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:140 +msgid "KRB5 error code 117" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:141 +msgid "KRB5 error code 118" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:142 +msgid "KRB5 error code 119" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:143 +msgid "KRB5 error code 120" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:144 +msgid "KRB5 error code 121" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:145 +msgid "KRB5 error code 122" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:146 +msgid "KRB5 error code 123" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:147 +msgid "KRB5 error code 124" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:148 +msgid "KRB5 error code 125" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:149 +msgid "KRB5 error code 126" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:150 +msgid "KRB5 error code 127" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:151 +#: ../lib/krb5/error_tables/kdb5_err.c:23 +msgid "$Id$" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:152 +msgid "Invalid flag for file lock mode" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:153 +msgid "Cannot read password" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:154 +msgid "Password mismatch" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:155 +msgid "Password read interrupted" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:156 +msgid "Illegal character in component name" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:157 +msgid "Malformed representation of principal" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:158 +msgid "Can't open/find Kerberos configuration file" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:159 +msgid "Improper format of Kerberos configuration file" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:160 +msgid "Insufficient space to return complete information" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:161 +msgid "Invalid message type specified for encoding" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:162 +msgid "Credential cache name malformed" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:163 +msgid "Unknown credential cache type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:164 +msgid "Matching credential not found" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:165 +msgid "End of credential cache reached" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:166 +msgid "Request did not supply a ticket" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:167 +msgid "Wrong principal in request" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:168 +msgid "Ticket has invalid flag set" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:169 +msgid "Requested principal and ticket don't match" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:170 +msgid "KDC reply did not match expectations" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:171 +msgid "Clock skew too great in KDC reply" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:172 +msgid "Client/server realm mismatch in initial ticket request" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:173 +msgid "Program lacks support for encryption type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:174 +msgid "Program lacks support for key type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:175 +msgid "Requested encryption type not used in message" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:176 +msgid "Program lacks support for checksum type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:177 +msgid "Cannot find KDC for requested realm" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:178 +msgid "Kerberos service unknown" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:179 +msgid "Cannot contact any KDC for requested realm" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:180 +msgid "No local name found for principal name" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:182 +msgid "Replay cache type is already registered" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:183 +msgid "No more memory to allocate (in replay cache code)" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:184 +msgid "Replay cache type is unknown" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:185 +msgid "Generic unknown RC error" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:186 +msgid "Message is a replay" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:187 +msgid "Replay cache I/O operation failed" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:188 +msgid "Replay cache type does not support non-volatile storage" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:189 +msgid "Replay cache name parse/format error" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:190 +msgid "End-of-file on replay cache I/O" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:191 +msgid "No more memory to allocate (in replay cache I/O code)" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:192 +msgid "Permission denied in replay cache code" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:193 +msgid "I/O error in replay cache i/o code" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:194 +msgid "Generic unknown RC/IO error" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:195 +msgid "Insufficient system space to store replay information" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:196 +msgid "Can't open/find realm translation file" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:197 +msgid "Improper format of realm translation file" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:198 +msgid "Can't open/find lname translation database" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:199 +msgid "No translation available for requested principal" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:200 +msgid "Improper format of translation database entry" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:201 +msgid "Cryptosystem internal error" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:202 +msgid "Key table name malformed" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:203 +msgid "Unknown Key table type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:204 +msgid "Key table entry not found" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:205 +msgid "End of key table reached" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:206 +msgid "Cannot write to specified key table" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:207 +msgid "Error writing to key table" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:208 +msgid "Cannot find ticket for requested realm" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:209 +msgid "DES key has bad parity" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:210 +msgid "DES key is a weak key" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:211 +msgid "Bad encryption type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:212 +msgid "Key size is incompatible with encryption type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:213 +msgid "Message size is incompatible with encryption type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:214 +msgid "Credentials cache type is already registered." +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:215 +msgid "Key table type is already registered." +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:216 +msgid "Credentials cache I/O operation failed" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:217 +msgid "Credentials cache permissions incorrect" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:218 +msgid "No credentials cache found" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:219 +msgid "Internal credentials cache error" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:220 +msgid "Error writing to credentials cache" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:221 +msgid "No more memory to allocate (in credentials cache code)" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:222 +msgid "Bad format in credentials cache" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:223 +msgid "No credentials found with supported encryption types" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:224 +msgid "Invalid KDC option combination (library internal error)" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:225 +msgid "Request missing second ticket" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:226 +msgid "No credentials supplied to library routine" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:227 +msgid "Bad sendauth version was sent" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:228 +msgid "Bad application version was sent (via sendauth)" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:229 +msgid "Bad response (during sendauth exchange)" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:230 +msgid "Server rejected authentication (during sendauth exchange)" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:231 +msgid "Unsupported preauthentication type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:232 +msgid "Required preauthentication key not supplied" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:233 +msgid "Generic preauthentication failure" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:234 +msgid "Unsupported replay cache format version number" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:235 +msgid "Unsupported credentials cache format version number" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:236 +msgid "Unsupported key table format version number" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:237 +msgid "Program lacks support for address type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:238 +msgid "Message replay detection requires rcache parameter" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:239 +msgid "Hostname cannot be canonicalized" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:240 +msgid "Cannot determine realm for host" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:241 +msgid "Conversion to service principal undefined for name type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:242 +msgid "Initial Ticket response appears to be Version 4 error" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:243 +msgid "Cannot resolve network address for KDC in requested realm" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:244 +msgid "Requesting ticket can't get forwardable tickets" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:245 +msgid "Bad principal name while trying to forward credentials" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:246 +msgid "Looping detected inside krb5_get_in_tkt" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:247 +msgid "Configuration file does not specify default realm" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:248 +msgid "Bad SAM flags in obtain_sam_padata" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:249 +msgid "Invalid encryption type in SAM challenge" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:250 +msgid "Missing checksum in SAM challenge" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:251 +msgid "Bad checksum in SAM challenge" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:252 +msgid "Keytab name too long" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:253 +msgid "Key version number for principal in key table is incorrect" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:254 +msgid "This application has expired" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:255 +msgid "This Krb5 library has expired" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:256 +msgid "New password cannot be zero length" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:258 +msgid "Bad format in keytab" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:259 +msgid "Encryption type not permitted" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:260 +msgid "No supported encryption types (config file error?)" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:261 +msgid "Program called an obsolete, deleted function" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:262 +msgid "unknown getaddrinfo failure" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:263 +msgid "no data available for host/domain name" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:264 +msgid "host/domain name not found" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:265 +msgid "service name unknown" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:266 +msgid "Cannot determine realm for numeric host address" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:267 +msgid "Invalid key generation parameters from KDC" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:268 +msgid "service not available" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:269 +msgid "Ccache function not supported: read-only ccache type" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:270 +msgid "Ccache function not supported: not implemented" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:271 +msgid "Invalid format of Kerberos lifetime or clock skew string" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:272 +msgid "Supplied data not handled by this plugin" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:273 +msgid "Plugin does not support the operation" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:274 +msgid "Invalid UTF-8 string" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:275 +msgid "FAST protected pre-authentication required but not supported by KDC" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:276 +msgid "Auth context must contain local address" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:277 +msgid "Auth context must contain remote address" +msgstr "" + +#: ../lib/krb5/error_tables/krb5_err.c:278 +msgid "Tracing unsupported" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:24 +msgid "Entry already exists in database" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:25 +msgid "Database store error" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:26 +msgid "Database read error" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:27 +msgid "Insufficient access to perform requested operation" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:28 +msgid "No such entry in the database" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:29 +msgid "Illegal use of wildcard" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:30 +msgid "Database is locked or in use--try again later" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:31 +msgid "Database was modified during read" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:32 +msgid "Database record is incomplete or corrupted" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:33 +msgid "Attempt to lock database twice" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:34 +msgid "Attempt to unlock database when not locked" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:35 +msgid "Invalid kdb lock mode" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:36 +msgid "Database has not been initialized" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:37 +msgid "Database has already been initialized" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:38 +msgid "Bad direction for converting keys" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:39 +msgid "Cannot find master key record in database" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:40 +msgid "Master key does not match database" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:41 +msgid "Key size in database is invalid" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:42 +msgid "Cannot find/read stored master key" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:43 +msgid "Stored master key is corrupted" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:44 +msgid "Cannot find active master key" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:45 +msgid "KVNO of new master key does not match expected value" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:46 +msgid "Stored master key is not current" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:47 +msgid "Insufficient access to lock database" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:48 +msgid "Database format error" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:49 +msgid "Unsupported version in database entry" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:50 +msgid "Unsupported salt type" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:51 +msgid "Unsupported encryption type" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:52 +msgid "Bad database creation flags" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:53 +msgid "No matching key in entry having a permitted enctype" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:54 +msgid "No matching key in entry" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:56 +msgid "Database type not supported" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:57 +msgid "Database library failed to initialize" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:59 +msgid "Unable to access Kerberos database" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:60 +msgid "Kerberos database internal error" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:61 +msgid "Kerberos database constraints violated" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:62 +msgid "Update log conversion error" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:63 +msgid "Update log is unstable" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:64 +msgid "Update log is corrupt" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:65 +msgid "Generic update log error" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:66 +msgid "Database module does not match KDC version" +msgstr "" + +#: ../lib/krb5/error_tables/kdb5_err.c:68 +msgid "Too much string mapping data" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:23 +msgid "ASN.1 failed call to system time library" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:24 +msgid "ASN.1 structure is missing a required field" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:25 +msgid "ASN.1 unexpected field number" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:26 +msgid "ASN.1 type numbers are inconsistent" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:27 +msgid "ASN.1 value too large" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:28 +msgid "ASN.1 encoding ended unexpectedly" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:29 +msgid "ASN.1 identifier doesn't match expected value" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:30 +msgid "ASN.1 length doesn't match expected value" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:31 +msgid "ASN.1 badly-formatted encoding" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:32 +msgid "ASN.1 parse error" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:33 +msgid "ASN.1 bad return from gmtime" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:34 +msgid "ASN.1 indefinite encoding" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:35 +msgid "ASN.1 missing expected EOC" +msgstr "" + +#: ../lib/krb5/error_tables/asn1_err.c:36 +msgid "ASN.1 object omitted in sequence" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:23 +msgid "Kerberos V5 magic number table" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:24 +msgid "Bad magic number for krb5_principal structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:25 +msgid "Bad magic number for krb5_data structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:26 +msgid "Bad magic number for krb5_keyblock structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:27 +msgid "Bad magic number for krb5_checksum structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:28 +msgid "Bad magic number for krb5_encrypt_block structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:29 +msgid "Bad magic number for krb5_enc_data structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:30 +msgid "Bad magic number for krb5_cryptosystem_entry structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:31 +msgid "Bad magic number for krb5_cs_table_entry structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:32 +msgid "Bad magic number for krb5_checksum_entry structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:33 +msgid "Bad magic number for krb5_authdata structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:34 +msgid "Bad magic number for krb5_transited structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:35 +msgid "Bad magic number for krb5_enc_tkt_part structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:36 +msgid "Bad magic number for krb5_ticket structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:37 +msgid "Bad magic number for krb5_authenticator structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:38 +msgid "Bad magic number for krb5_tkt_authent structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:39 +msgid "Bad magic number for krb5_creds structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:40 +msgid "Bad magic number for krb5_last_req_entry structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:41 +msgid "Bad magic number for krb5_pa_data structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:42 +msgid "Bad magic number for krb5_kdc_req structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:43 +msgid "Bad magic number for krb5_enc_kdc_rep_part structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:44 +msgid "Bad magic number for krb5_kdc_rep structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:45 +msgid "Bad magic number for krb5_error structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:46 +msgid "Bad magic number for krb5_ap_req structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:47 +msgid "Bad magic number for krb5_ap_rep structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:48 +msgid "Bad magic number for krb5_ap_rep_enc_part structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:49 +msgid "Bad magic number for krb5_response structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:50 +msgid "Bad magic number for krb5_safe structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:51 +msgid "Bad magic number for krb5_priv structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:52 +msgid "Bad magic number for krb5_priv_enc_part structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:53 +msgid "Bad magic number for krb5_cred structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:54 +msgid "Bad magic number for krb5_cred_info structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:55 +msgid "Bad magic number for krb5_cred_enc_part structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:56 +msgid "Bad magic number for krb5_pwd_data structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:57 +msgid "Bad magic number for krb5_address structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:58 +msgid "Bad magic number for krb5_keytab_entry structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:59 +msgid "Bad magic number for krb5_context structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:60 +msgid "Bad magic number for krb5_os_context structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:61 +msgid "Bad magic number for krb5_alt_method structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:62 +msgid "Bad magic number for krb5_etype_info_entry structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:63 +msgid "Bad magic number for krb5_db_context structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:64 +msgid "Bad magic number for krb5_auth_context structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:65 +msgid "Bad magic number for krb5_keytab structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:66 +msgid "Bad magic number for krb5_rcache structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:67 +msgid "Bad magic number for krb5_ccache structure" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:68 +msgid "Bad magic number for krb5_preauth_ops" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:69 +msgid "Bad magic number for krb5_sam_challenge" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:70 +msgid "Bad magic number for krb5_sam_challenge_2" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:71 +msgid "Bad magic number for krb5_sam_key" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:72 +#: ../lib/krb5/error_tables/kv5m_err.c:73 +msgid "Bad magic number for krb5_enc_sam_response_enc" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:74 +msgid "Bad magic number for krb5_sam_response" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:75 +msgid "Bad magic number for krb5_sam_response 2" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:76 +msgid "Bad magic number for krb5_predicted_sam_response" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:77 +msgid "Bad magic number for passwd_phrase_element" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:78 +msgid "Bad magic number for GSSAPI OID" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:79 +msgid "Bad magic number for GSSAPI QUEUE" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:80 +msgid "Bad magic number for fast armored request" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:81 +msgid "Bad magic number for FAST request" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:82 +msgid "Bad magic number for FAST response" +msgstr "" + +#: ../lib/krb5/error_tables/kv5m_err.c:83 +msgid "Bad magic number for krb5_authdata_context" +msgstr "" + +#: ../lib/krb5/error_tables/krb524_err.c:23 +msgid "Cannot convert V5 keyblock" +msgstr "" + +#: ../lib/krb5/error_tables/krb524_err.c:24 +msgid "Cannot convert V5 address information" +msgstr "" + +#: ../lib/krb5/error_tables/krb524_err.c:25 +msgid "Cannot convert V5 principal" +msgstr "" + +#: ../lib/krb5/error_tables/krb524_err.c:26 +msgid "V5 realm name longer than V4 maximum" +msgstr "" + +#: ../lib/krb5/error_tables/krb524_err.c:27 +msgid "Kerberos V4 error" +msgstr "" + +#: ../lib/krb5/error_tables/krb524_err.c:28 +msgid "Encoding too large" +msgstr "" + +#: ../lib/krb5/error_tables/krb524_err.c:29 +msgid "Decoding out of data" +msgstr "" + +#: ../lib/krb5/error_tables/krb524_err.c:30 +msgid "Service not responding" +msgstr "" + +#: ../lib/krb5/error_tables/krb524_err.c:31 +msgid "Kerberos version 4 support is disabled" +msgstr "" diff --git a/krb5-1.21.3/src/prototype/prototype.c b/krb5-1.21.3/src/prototype/prototype.c new file mode 100644 index 00000000..77cc8c21 --- /dev/null +++ b/krb5-1.21.3/src/prototype/prototype.c @@ -0,0 +1,35 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* prototype/prototype.c - <<< One-line description of file >>> */ +/* + * Copyright (C) 2024 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. + */ + +/* + * <<< Longer description of file >>> + */ diff --git a/krb5-1.21.3/src/prototype/prototype.h b/krb5-1.21.3/src/prototype/prototype.h new file mode 100644 index 00000000..c6d42417 --- /dev/null +++ b/krb5-1.21.3/src/prototype/prototype.h @@ -0,0 +1,40 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* prototype/prototype.h - <<< One-line description of file >>> */ +/* + * Copyright (C) 2024 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. + */ + +/* + * <<< Longer description of file >>> + */ + +#ifndef <<< include blocker>>>__ +#define <<< include blocker>>>__ + +#endif /* __<<< include blocker>>>__ */ diff --git a/krb5-1.21.3/src/tests/Makefile.in b/krb5-1.21.3/src/tests/Makefile.in new file mode 100644 index 00000000..e7cf64e0 --- /dev/null +++ b/krb5-1.21.3/src/tests/Makefile.in @@ -0,0 +1,201 @@ +mydir=tests +BUILDTOP=$(REL).. +SUBDIRS = asn.1 create hammer verify gssapi shlib gss-threads misc threads \ + softpkcs11 + +RUN_DB_TEST = $(RUN_SETUP) KRB5_KDC_PROFILE=kdc.conf KRB5_CONFIG=krb5.conf \ + GSS_MECH_CONFIG=mech.conf LC_ALL=C $(VALGRIND) + +OBJS= adata.o conccache.o etinfo.o forward.o gcred.o hist.o hooks.o hrealm.o \ + icinterleave.o icred.o kdbtest.o localauth.o plugorder.o rdreq.o \ + replay.o responder.o s2p.o s4u2self.o s4u2proxy.o t_inetd.o \ + unlockiter.o +EXTRADEPSRCS= adata.c conccache.c etinfo.c forward.c gcred.c hist.c hooks.c \ + hrealm.c icinterleave.c icred.c kdbtest.c localauth.c plugorder.c \ + rdreq.c replay.c responder.c s2p.c s4u2self.c s4u2proxy.c t_inetd.c \ + unlockiter.c + +TEST_DB = ./testdb +TEST_REALM = FOO.TEST.REALM +TEST_MKEY = footes +TEST_NUM = 65 +TEST_DEPTH = 5 +TEST_PREFIX = "foo bar" + +KADMIN_OPTS= -d $(TEST_DB) -r $(TEST_REALM) -P $(TEST_MKEY) +KTEST_OPTS= $(KADMIN_OPTS) -p $(TEST_PREFIX) -n $(TEST_NUM) -D $(TEST_DEPTH) + +adata: adata.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ adata.o $(KRB5_BASE_LIBS) + +conccache: conccache.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ conccache.o $(KRB5_BASE_LIBS) + +etinfo: etinfo.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ etinfo.o $(KRB5_BASE_LIBS) + +forward: forward.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ forward.o $(KRB5_BASE_LIBS) + +gcred: gcred.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ gcred.o $(KRB5_BASE_LIBS) + +hist: hist.o $(KDB5_DEPLIBS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ hist.o $(KDB5_LIBS) $(KADMSRV_LIBS) $(KRB5_BASE_LIBS) + +hooks: hooks.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ hooks.o $(KRB5_BASE_LIBS) + +hrealm: hrealm.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ hrealm.o $(KRB5_BASE_LIBS) + +icinterleave: icinterleave.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ icinterleave.o $(KRB5_BASE_LIBS) + +icred: icred.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ icred.o $(KRB5_BASE_LIBS) + +kdbtest: kdbtest.o $(KDB5_DEPLIBS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ kdbtest.o $(KDB5_LIBS) $(KADMSRV_LIBS) \ + $(KRB5_BASE_LIBS) + +localauth: localauth.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ localauth.o $(KRB5_BASE_LIBS) + +plugorder: plugorder.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ plugorder.o $(KRB5_BASE_LIBS) + +rdreq: rdreq.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ rdreq.o $(KRB5_BASE_LIBS) + +replay: replay.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ replay.o $(KRB5_BASE_LIBS) + +responder: responder.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ responder.o $(KRB5_BASE_LIBS) + +s2p: s2p.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ s2p.o $(KRB5_BASE_LIBS) + +s4u2self: s4u2self.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ s4u2self.o $(KRB5_BASE_LIBS) + +s4u2proxy: s4u2proxy.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ s4u2proxy.o $(KRB5_BASE_LIBS) + +t_inetd: t_inetd.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ t_inetd.o $(LIBS) $(KRB5_BASE_LIBS) + +unlockiter: unlockiter.o $(KDB5_DEPLIBS) $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o $@ unlockiter.o $(KDB5_LIBS) $(KADMSRV_LIBS) \ + $(KRB5_BASE_LIBS) + +all-unix: t_inetd + +check-unix: kdb_check + +kdc.conf: Makefile + rm -rf kdc.conf + @echo "[realms]" > kdc.conf + @echo "$(TEST_REALM) = {" >> kdc.conf + @echo " key_stash_file = `pwd`/stash_file" >> kdc.conf + @echo "}" >> kdc.conf + +krb5.conf: Makefile + cat $(top_srcdir)/config-files/krb5.conf > krb5.new + echo "[dbmodules]" >> krb5.new + echo " db_module_dir = `pwd`/../plugins/kdb" >> krb5.new + mv krb5.new krb5.conf + +kdb_check: kdc.conf krb5.conf + $(RM) $(TEST_DB)* + $(RUN_DB_TEST) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) create -W + $(RUN_DB_TEST) ../tests/create/kdb5_mkdums $(KTEST_OPTS) + $(RUN_DB_TEST) ../tests/verify/kdb5_verify $(KTEST_OPTS) + $(RUN_DB_TEST) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) dump $(TEST_DB).dump + $(RUN_DB_TEST) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) destroy -f + @echo "====> NOTE!" + @echo "The following 'create' command is needed due to a change" + @echo "in functionality caused by DAL integration. See ticket 3973." + @echo ==== + $(RUN_DB_TEST) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) create -W + $(RUN_DB_TEST) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) load $(TEST_DB).dump + $(RUN_DB_TEST) ../tests/verify/kdb5_verify $(KTEST_OPTS) + $(RUN_DB_TEST) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) dump $(TEST_DB).dump2 + sort $(TEST_DB).dump > $(TEST_DB).sort + sort $(TEST_DB).dump2 > $(TEST_DB).sort2 + cmp $(TEST_DB).sort $(TEST_DB).sort2 + $(RUN_DB_TEST) ../kadmin/dbutil/kdb5_util $(KADMIN_OPTS) destroy -f + $(RM) $(TEST_DB)* stash_file + +check-pytests: adata conccache etinfo forward gcred hist hooks hrealm +check-pytests: icinterleave icred kdbtest localauth plugorder rdreq replay +check-pytests: responder s2p s4u2proxy unlockiter s4u2self + $(RUNPYTEST) $(srcdir)/t_general.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_hooks.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_dump.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_iprop.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kprop.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_policy.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_changepw.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_pkinit.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_otp.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_spake.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_localauth.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kadm5_hook.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kadm5_auth.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_pwqual.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_hostrealm.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kdb_locking.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_keyrollover.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_renew.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_renprinc.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_ccache.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_stringattr.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_sesskeynego.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_crossrealm.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_referral.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_skew.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_keytab.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kadmin.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kadmin_acl.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kadmin_parsing.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kdb.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_keydata.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_mkey.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_rdreq.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_sn2princ.py $(PYTESTFLAGS) $(OFFLINE) + $(RUNPYTEST) $(srcdir)/t_cve-2012-1014.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_cve-2012-1015.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_cve-2013-1416.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_cve-2013-1417.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_cve-2021-36222.py $(PYTESTFLAGS) + $(RM) au.log + $(RUNPYTEST) $(srcdir)/t_audit.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/jsonwalker.py -d $(srcdir)/au_dict.json \ + -i au.log + $(RUNPYTEST) $(srcdir)/t_salt.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_etype_info.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_bogus_kdc_req.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kdc_log.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_proxy.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_unlockiter.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_errmsg.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_authdata.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_preauth.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_princflags.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_tabdump.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_certauth.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_y2038.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kdcpolicy.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_u2u.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_kdcoptions.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_replay.py $(PYTESTFLAGS) + +clean: + $(RM) adata conccache etinfo forward gcred hist hooks hrealm + $(RM) icinterleave icred kdbtest localauth plugorder rdreq replay + $(RM) responder s2p s4u2proxy s4u2self t_inetd unlockiter + $(RM) krb5.conf kdc.conf + $(RM) -rf kdc_realm/sandbox ldap + $(RM) au.log diff --git a/krb5-1.21.3/src/tests/adata.c b/krb5-1.21.3/src/tests/adata.c new file mode 100644 index 00000000..58981c97 --- /dev/null +++ b/krb5-1.21.3/src/tests/adata.c @@ -0,0 +1,381 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/adata.c - Test harness for KDC authorization data */ +/* + * Copyright (C) 2014 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. + */ + +/* + * Usage: ./adata [-c ccname] [-p clientprinc] serviceprinc + * [ad-type ad-contents ...] + * + * This program acquires credentials for the specified service principal, using + * the specified or default ccache, possibly including requested authdata. The + * resulting ticket is decrypted using the default keytab, and the authdata in + * the ticket are displayed to stdout. + * + * In the requested authdata types, the type may be prefixed with '?' for an + * AD-IF-RELEVANT container, '!' for an AD-MANDATORY-FOR-KDC container, or '^' + * for an AD-KDC-ISSUED container checksummed with a random AES256 key. + * Multiple prefixes may be specified for nested container. + * + * In the output, authdata containers will be flattened and displayed with the + * above prefixes or '+' for an AD-CAMMAC container. AD-KDC-ISSUED and + * AD-CAMMAC containers will be verified with the appropriate key. Nested + * containers only display the prefix for the innermost container. + */ + +#include +#include + +static krb5_context ctx; + +static void display_authdata_list(krb5_authdata **list, + krb5_enc_tkt_part *enc_tkt, + krb5_keyblock *tktkey, char prefix_byte, + krb5_boolean pac_ok); + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +static krb5_authdatatype +get_type_for_prefix(int prefix_byte) +{ + if (prefix_byte == '?') + return KRB5_AUTHDATA_IF_RELEVANT; + if (prefix_byte == '!') + return KRB5_AUTHDATA_MANDATORY_FOR_KDC; + if (prefix_byte == '^') + return KRB5_AUTHDATA_KDC_ISSUED; + if (prefix_byte == '+') + return KRB5_AUTHDATA_CAMMAC; + abort(); +} + +static int +get_prefix_byte(krb5_authdata *ad) +{ + if (ad->ad_type == KRB5_AUTHDATA_IF_RELEVANT) + return '?'; + if (ad->ad_type == KRB5_AUTHDATA_MANDATORY_FOR_KDC) + return '!'; + if (ad->ad_type == KRB5_AUTHDATA_KDC_ISSUED) + return '^'; + if (ad->ad_type == KRB5_AUTHDATA_CAMMAC) + return '+'; + abort(); +} + +/* Construct a container of type ad_type for the single authdata element + * content. For KDC-ISSUED containers, use a random checksum key. */ +static krb5_authdata * +make_container(krb5_authdatatype ad_type, krb5_authdata *content) +{ + krb5_authdata *list[2], **enclist, *ad; + krb5_keyblock kb; + + list[0] = content; + list[1] = NULL; + + if (ad_type == KRB5_AUTHDATA_KDC_ISSUED) { + check(krb5_c_make_random_key(ctx, ENCTYPE_AES256_CTS_HMAC_SHA1_96, + &kb)); + check(krb5_make_authdata_kdc_issued(ctx, &kb, NULL, list, &enclist)); + krb5_free_keyblock_contents(ctx, &kb); + } else { + check(krb5_encode_authdata_container(ctx, ad_type, list, &enclist)); + } + + /* Grab the first element from the encoded list and free the array. */ + ad = enclist[0]; + free(enclist); + return ad; +} + +/* Parse typestr and contents into an authdata element. */ +static krb5_authdata * +make_authdata(const char *typestr, const char *contents) +{ + krb5_authdata *inner_ad, *ad; + + if (*typestr == '?' || *typestr == '!' || *typestr == '^') { + inner_ad = make_authdata(typestr + 1, contents); + ad = make_container(get_type_for_prefix(*typestr), inner_ad); + free(inner_ad->contents); + free(inner_ad); + return ad; + } + + ad = malloc(sizeof(*ad)); + assert(ad != NULL); + ad->magic = KV5M_AUTHDATA; + ad->ad_type = atoi(typestr); + ad->length = strlen(contents); + ad->contents = (unsigned char *)strdup(contents); + assert(ad->contents != NULL); + return ad; +} + +static krb5_authdata ** +get_container_contents(krb5_authdata *ad, krb5_keyblock *skey, + krb5_keyblock *tktkey) +{ + krb5_authdata **inner_ad; + + if (ad->ad_type == KRB5_AUTHDATA_KDC_ISSUED) + check(krb5_verify_authdata_kdc_issued(ctx, skey, ad, NULL, &inner_ad)); + else if (ad->ad_type == KRB5_AUTHDATA_CAMMAC) + check(k5_unwrap_cammac_svc(ctx, ad, tktkey, &inner_ad)); + else + check(krb5_decode_authdata_container(ctx, ad->ad_type, ad, &inner_ad)); + return inner_ad; +} + +static int +compare_uint32(const void *p1, const void *p2) +{ + uint32_t t1 = *(uint32_t *)p1, t2 = *(uint32_t *)p2; + + return (t1 > t2) ? 1 : (t1 == t2) ? 0 : -1; +} + +static void +display_pac(krb5_authdata *ad, krb5_enc_tkt_part *enc_tkt, + krb5_keyblock *tktkey) +{ + krb5_pac pac; + size_t tlen, i; + uint32_t *types; + + assert(ad->ad_type == KRB5_AUTHDATA_WIN2K_PAC); + check(krb5_pac_parse(ctx, ad->contents, ad->length, &pac)); + + check(krb5_pac_verify(ctx, pac, enc_tkt->times.authtime, enc_tkt->client, + tktkey, NULL)); + + check(krb5_pac_get_types(ctx, pac, &tlen, &types)); + qsort(types, tlen, sizeof(*types), compare_uint32); + + printf("["); + for (i = 0; i < tlen; i++) { + printf("%d", (int)types[i]); + if (i + 1 < tlen) + printf(", "); + } + printf("]"); + + free(types); + krb5_pac_free(ctx, pac); +} + +/* Decode and display authentication indicator authdata. */ +static void +display_auth_indicator(krb5_authdata *ad) +{ + krb5_data **strs = NULL, **p; + + check(k5_authind_decode(ad, &strs)); + assert(strs != NULL); + + printf("["); + for (p = strs; *p != NULL; p++) { + printf("%.*s", (int)(*p)->length, (*p)->data); + if (*(p + 1) != NULL) + printf(", "); + } + printf("]"); + k5_free_data_ptr_list(strs); +} + +/* Display ad as either a hex dump or ASCII text. */ +static void +display_binary_or_ascii(krb5_authdata *ad) +{ + krb5_boolean binary = FALSE; + unsigned char *p; + + for (p = ad->contents; p < ad->contents + ad->length; p++) { + if (!isascii(*p) || !isprint(*p)) + binary = TRUE; + } + if (binary) { + for (p = ad->contents; p < ad->contents + ad->length; p++) + printf("%02X", *p); + } else { + printf("%.*s", (int)ad->length, ad->contents); + } +} + +/* Display the contents of an authdata element, prefixed by prefix_byte. skey + * must be the ticket session key. */ +static void +display_authdata(krb5_authdata *ad, krb5_enc_tkt_part *enc_tkt, + krb5_keyblock *tktkey, int prefix_byte, krb5_boolean pac_ok) +{ + krb5_authdata **inner_ad; + + if (ad->ad_type == KRB5_AUTHDATA_IF_RELEVANT || + ad->ad_type == KRB5_AUTHDATA_MANDATORY_FOR_KDC || + ad->ad_type == KRB5_AUTHDATA_KDC_ISSUED || + ad->ad_type == KRB5_AUTHDATA_CAMMAC) { + if (ad->ad_type != KRB5_AUTHDATA_IF_RELEVANT) + pac_ok = FALSE; + /* Decode and display the contents. */ + inner_ad = get_container_contents(ad, enc_tkt->session, tktkey); + display_authdata_list(inner_ad, enc_tkt, tktkey, get_prefix_byte(ad), + pac_ok); + krb5_free_authdata(ctx, inner_ad); + return; + } + + assert(pac_ok || ad->ad_type != KRB5_AUTHDATA_WIN2K_PAC); + + printf("%c", prefix_byte); + printf("%d: ", (int)ad->ad_type); + + if (ad->ad_type == KRB5_AUTHDATA_WIN2K_PAC) + display_pac(ad, enc_tkt, tktkey); + else if (ad->ad_type == KRB5_AUTHDATA_AUTH_INDICATOR) + display_auth_indicator(ad); + else + display_binary_or_ascii(ad); + printf("\n"); +} + +static void +display_authdata_list(krb5_authdata **list, krb5_enc_tkt_part *tkt_enc, + krb5_keyblock *tktkey, char prefix_byte, + krb5_boolean pac_ok) +{ + if (list == NULL) + return; + /* Only expect a PAC in the first element, if at all. */ + for (; *list != NULL; list++) { + display_authdata(*list, tkt_enc, tktkey, prefix_byte, pac_ok); + pac_ok = FALSE; + } +} + +int +main(int argc, char **argv) +{ + const char *ccname = NULL, *clientname = NULL; + krb5_principal client, server; + krb5_ccache ccache; + krb5_keytab keytab; + krb5_creds in_creds, *creds; + krb5_ticket *ticket; + krb5_authdata **req_authdata = NULL, *ad; + krb5_keytab_entry ktent; + size_t count; + int c; + + check(krb5_init_context(&ctx)); + + while ((c = getopt(argc, argv, "+c:p:")) != -1) { + switch (c) { + case 'c': + ccname = optarg; + break; + case 'p': + clientname = optarg; + break; + default: + abort(); + } + } + argv += optind; + /* Parse arguments. */ + assert(*argv != NULL); + check(krb5_parse_name(ctx, *argv++, &server)); + + count = 0; + for (; argv[0] != NULL && argv[1] != NULL; argv += 2) { + ad = make_authdata(argv[0], argv[1]); + req_authdata = realloc(req_authdata, + (count + 2) * sizeof(*req_authdata)); + assert(req_authdata != NULL); + req_authdata[count++] = ad; + req_authdata[count] = NULL; + } + assert(*argv == NULL); + + if (ccname != NULL) + check(krb5_cc_resolve(ctx, ccname, &ccache)); + else + check(krb5_cc_default(ctx, &ccache)); + + if (clientname != NULL) + check(krb5_parse_name(ctx, clientname, &client)); + else + check(krb5_cc_get_principal(ctx, ccache, &client)); + + memset(&in_creds, 0, sizeof(in_creds)); + in_creds.client = client; + in_creds.server = server; + in_creds.authdata = req_authdata; + + check(krb5_get_credentials(ctx, KRB5_GC_NO_STORE, ccache, &in_creds, + &creds)); + + assert(in_creds.authdata == NULL || creds->authdata != NULL); + + check(krb5_decode_ticket(&creds->ticket, &ticket)); + check(krb5_kt_default(ctx, &keytab)); + check(krb5_kt_get_entry(ctx, keytab, ticket->server, ticket->enc_part.kvno, + ticket->enc_part.enctype, &ktent)); + check(krb5_decrypt_tkt_part(ctx, &ktent.key, ticket)); + + display_authdata_list(ticket->enc_part2->authorization_data, + ticket->enc_part2, &ktent.key, ' ', TRUE); + + while (count > 0) { + free(req_authdata[--count]->contents); + free(req_authdata[count]); + } + free(req_authdata); + krb5_free_keytab_entry_contents(ctx, &ktent); + krb5_free_creds(ctx, creds); + krb5_free_ticket(ctx, ticket); + krb5_free_principal(ctx, client); + krb5_free_principal(ctx, server); + krb5_cc_close(ctx, ccache); + krb5_kt_close(ctx, keytab); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/asn.1/Makefile.in b/krb5-1.21.3/src/tests/asn.1/Makefile.in new file mode 100644 index 00000000..eabe0bd0 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/Makefile.in @@ -0,0 +1,98 @@ +mydir=tests$(S)asn.1 +BUILDTOP=$(REL)..$(S).. +LDAP=@LDAP@ + +SRCS= $(srcdir)/krb5_encode_test.c $(srcdir)/krb5_decode_test.c \ + $(srcdir)/krb5_decode_leak.c $(srcdir)/ktest.c \ + $(srcdir)/ktest_equal.c $(srcdir)/utility.c \ + $(srcdir)/trval.c $(srcdir)/t_trval.c + +ASN1SRCS= $(srcdir)/krb5.asn1 $(srcdir)/pkix.asn1 $(srcdir)/otp.asn1 \ + $(srcdir)/pkinit.asn1 $(srcdir)/pkinit-agility.asn1 \ + $(srcdir)/cammac.asn1 $(srcdir)/spake.asn1 + +all: krb5_encode_test krb5_decode_test krb5_decode_leak t_trval + +ENCOBJS = krb5_encode_test.o ktest.o ktest_equal.o utility.o trval.o + +krb5_encode_test: $(ENCOBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o krb5_encode_test $(ENCOBJS) $(KRB5_BASE_LIBS) + +DECOBJS = krb5_decode_test.o ktest.o ktest_equal.o utility.o + +krb5_decode_test: $(DECOBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o krb5_decode_test $(DECOBJS) $(KRB5_BASE_LIBS) + +LEAKOBJS = krb5_decode_leak.o ktest.o ktest_equal.o utility.o + +krb5_decode_leak: $(LEAKOBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o krb5_decode_leak $(LEAKOBJS) $(KRB5_BASE_LIBS) + +t_trval: t_trval.o + $(CC) -o t_trval $(ALL_CFLAGS) t_trval.o + +check: check-encode check-encode-trval check-decode check-leak + +# Does not actually test for leaks unless using valgrind or a similar +# tool, but does exercise a bunch of code. +check-leak: krb5_decode_leak + $(RUN_TEST) ./krb5_decode_leak + +check-decode: krb5_decode_test + $(RUN_TEST) ./krb5_decode_test + +PKINIT_ENCODE_OUT=$(PKINIT_ENCODE_OUT-@PKINIT@) +PKINIT_ENCODE_OUT-yes=$(srcdir)/pkinit_encode.out +PKINIT_ENCODE_OUT-no= +LDAP_ENCODE_OUT=$(LDAP_ENCODE_OUT-@LDAP@) +LDAP_ENCODE_OUT-yes=$(srcdir)/ldap_encode.out +LDAP_ENCODE_OUT-no= +expected_encode.out: reference_encode.out pkinit_encode.out ldap_encode.out + cat $(srcdir)/reference_encode.out $(PKINIT_ENCODE_OUT) \ + $(LDAP_ENCODE_OUT) > $@ + +PKINIT_TRVAL_OUT=$(PKINIT_TRVAL_OUT-@PKINIT@) +PKINIT_TRVAL_OUT-yes=$(srcdir)/pkinit_trval.out +PKINIT_TRVAL_OUT-no= +LDAP_TRVAL_OUT=$(LDAP_TRVAL_OUT-@LDAP@) +LDAP_TRVAL_OUT-yes=$(srcdir)/ldap_trval.out +LDAP_TRVAL_OUT-no= +expected_trval.out: trval_reference.out pkinit_trval.out ldap_trval.out + cat $(srcdir)/trval_reference.out $(PKINIT_TRVAL_OUT) \ + $(LDAP_TRVAL_OUT) > $@ + +check-encode: krb5_encode_test expected_encode.out + $(RUN_TEST) ./krb5_encode_test > test.out + cmp test.out expected_encode.out + +check-encode-trval: krb5_encode_test expected_trval.out + $(RUN_TEST) ./krb5_encode_test -t > trval.out + cmp trval.out expected_trval.out + +# This target uses asn1c to generate encodings of sample objects, to +# help ensure that our implementation is correct. asn1c must be in the +# path for this to work. +test-vectors: + $(RM) -r vectors + mkdir vectors + cp $(ASN1SRCS) $(srcdir)/make-vectors.c vectors + (cd vectors && asn1c *.asn1 && rm converter-sample.c) + (cd vectors && $(CC) -I. -w *.c -o make-vectors) + (cd vectors && ./make-vectors) + +install: + +clean: + rm -f *~ *.o krb5_encode_test krb5_decode_test krb5_decode_leak test.out trval t_trval expected_encode.out expected_trval.out trval.out + + +################ Dependencies ################ +krb5_decode_test.o: ktest.h utility.h ktest_equal.h debug.h +krb5_encode_test.o: utility.h ktest.h debug.h +trval.o: trval.c +ktest.o: ktest.h utility.h +ktest_equal.o: ktest_equal.h +#utility.o: utility.h +#utility.h: krbasn1.h asn1buf.h +############################################## + diff --git a/krb5-1.21.3/src/tests/asn.1/README b/krb5-1.21.3/src/tests/asn.1/README new file mode 100644 index 00000000..2c0c0980 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/README @@ -0,0 +1,28 @@ +krb5_encode_test runs through all the functions declared in + src/include/krb5/asn.1/krb5_encode.h. It passes various sample + inputs to each function and prints the result to standard + output. This output should match the contents of the file + "reference_encode.out". + + Each function is first run with a relatively simple, contrived + sample structure. Then if the structure has any optional parts, + these parts are cleared and another run is made. + + Some structures (namely, those containing a krb5_kdc_req_body) + have a third run, due to the fact that two of the kdc_req_body's + optional fields have mutually exclusive conditions under which + they may be omitted. + + +krb5_decode_test runs through all the functions declared in + src/include/krb5/asn.1/krb5_decode.h. It has the encodings in + reference_encode.out hard-coded into itself. It sets up the + krb5 structures the same way krb5_encode_test does, then passes + its hard-coded encoding strings through the krb5 decoders. + + The outputs of these functions are compared to the previously + set-up structures in memory, and the results are reported to + standard output. If every line comes out prefixed by "OK: ", + then the decoders are working properly. If any decoder produces + an anomalous output, then its output line will be prefixed by + "ERROR: " diff --git a/krb5-1.21.3/src/tests/asn.1/cammac.asn1 b/krb5-1.21.3/src/tests/asn.1/cammac.asn1 new file mode 100644 index 00000000..2fc99760 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/cammac.asn1 @@ -0,0 +1,30 @@ +KerberosV5CAMMAC DEFINITIONS EXPLICIT TAGS ::= BEGIN + +IMPORTS + AuthorizationData, PrincipalName, Checksum, UInt32, Int32 + FROM KerberosV5Spec2 { iso(1) identified-organization(3) + dod(6) internet(1) security(5) kerberosV5(2) + modules(4) krb5spec2(2) }; + -- as defined in RFC 4120. + +AD-CAMMAC ::= SEQUENCE { + elements [0] AuthorizationData, + kdc-verifier [1] Verifier-MAC OPTIONAL, + svc-verifier [2] Verifier-MAC OPTIONAL, + other-verifiers [3] SEQUENCE (SIZE (1..MAX)) + OF Verifier OPTIONAL +} + +Verifier ::= CHOICE { + mac Verifier-MAC, + ... +} + +Verifier-MAC ::= SEQUENCE { + identifier [0] PrincipalName OPTIONAL, + kvno [1] UInt32 OPTIONAL, + enctype [2] Int32 OPTIONAL, + mac [3] Checksum +} + +END diff --git a/krb5-1.21.3/src/tests/asn.1/debug.h b/krb5-1.21.3/src/tests/asn.1/debug.h new file mode 100644 index 00000000..12020164 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/debug.h @@ -0,0 +1,46 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/asn.1/debug.h */ +/* + * Copyright (C) 1994 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +/* + assert utility macro for test programs: + If the predicate (pred) is true, then + OK: is printed. Otherwise, + ERROR: is printed. + + message should be a printf format string. +*/ + +#include + +#define test(pred,message) \ + if(pred) printf("OK: "); \ + else { printf("ERROR: "); error_count++; } \ + printf(message); + +#endif diff --git a/krb5-1.21.3/src/tests/asn.1/deps b/krb5-1.21.3/src/tests/asn.1/deps new file mode 100644 index 00000000..0b44f44a --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/deps @@ -0,0 +1,75 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)krb5_encode_test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-spake.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h debug.h krb5_encode_test.c \ + ktest.h utility.h +$(OUTPRE)krb5_decode_test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-spake.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h debug.h krb5_decode_test.c \ + ktest.h ktest_equal.h utility.h +$(OUTPRE)krb5_decode_leak.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-spake.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h debug.h krb5_decode_leak.c \ + ktest.h utility.h +$(OUTPRE)ktest.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-spake.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h ktest.c ktest.h \ + utility.h +$(OUTPRE)ktest_equal.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-spake.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h ktest_equal.c \ + ktest_equal.h +$(OUTPRE)utility.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h utility.c utility.h +$(OUTPRE)trval.$(OBJEXT): trval.c +$(OUTPRE)t_trval.$(OBJEXT): t_trval.c trval.c diff --git a/krb5-1.21.3/src/tests/asn.1/krb5.asn1 b/krb5-1.21.3/src/tests/asn.1/krb5.asn1 new file mode 100644 index 00000000..f58637a6 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/krb5.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 diff --git a/krb5-1.21.3/src/tests/asn.1/krb5_decode_leak.c b/krb5-1.21.3/src/tests/asn.1/krb5_decode_leak.c new file mode 100644 index 00000000..2a5313b0 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/krb5_decode_leak.c @@ -0,0 +1,676 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/asn.1/krb5_decode_leak.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This program is intended to help detect memory leaks in the ASN.1 + * decoder functions by exercising their failure paths. The setup + * code for the test cases is copied from krb5_encode_test.c. + * + * This code does not actually detect leaks by itself; it must be run + * through a leak-detection tool such as valgrind to do so. Simply + * running the program will exercise a bunch of ASN.1 encoder and + * decoder code paths but won't validate the results. + */ + +#include "k5-int.h" +#include "com_err.h" +#include "utility.h" +#include "ktest.h" +#include "debug.h" + +krb5_context test_context; + +/* + * Contrary to our usual convention, krb5_free_cred_enc_part is a + * contents-only free function (and is assumed to be by mk_cred and + * rd_cred) and we have no whole-structure free function for that data + * type. So create one here. + */ +static void +free_cred_enc_part_whole(krb5_context ctx, + krb5_cred_enc_part *val) +{ + krb5_free_cred_enc_part(ctx, val); + free(val); +} + +int +main(int argc, char **argv) +{ + krb5_data *code; + krb5_error_code retval; + unsigned int i; + + retval = krb5_init_context(&test_context); + if (retval) { + com_err(argv[0], retval, "while initializing krb5"); + exit(1); + } + init_access(argv[0]); + +#define encode_run(value,type,typestring,description,encoder) + + /* + * Encode a value. Then attempt to trigger most failure paths of + * the decoder function by passing in corrupt encodings, which we + * generate by perturbing each byte of the encoding in turn. Some + * of the perturbed encodings are expected to decode successfully, + * so we need a free function to discard successful results. Make + * sure to define a pointer named "tmp" of the correct type in the + * enclosing block. + */ +#define leak_test(value, encoder, decoder, freefn) \ + retval = encoder(&(value),&(code)); \ + if (retval) { \ + com_err("krb5_decode_leak", retval, "while encoding"); \ + exit(1); \ + } \ + for (i = 0; i < code->length; i++) { \ + code->data[i] = (char)~((unsigned char)code->data[i]); \ + retval = decoder(code, &tmp); \ + code->data[i] = (char)~((unsigned char)code->data[i]); \ + if (retval == 0) \ + freefn(test_context, tmp); \ + } \ + krb5_free_data(test_context, code); + + /****************************************************************/ + /* encode_krb5_authenticator */ + { + krb5_authenticator authent, *tmp; + + ktest_make_sample_authenticator(&authent); + leak_test(authent, encode_krb5_authenticator, + decode_krb5_authenticator, krb5_free_authenticator); + + ktest_destroy_checksum(&(authent.checksum)); + ktest_destroy_keyblock(&(authent.subkey)); + authent.seq_number = 0; + ktest_empty_authorization_data(authent.authorization_data); + leak_test(authent, encode_krb5_authenticator, + decode_krb5_authenticator, krb5_free_authenticator); + + ktest_destroy_authorization_data(&(authent.authorization_data)); + leak_test(authent, encode_krb5_authenticator, + decode_krb5_authenticator, krb5_free_authenticator); + ktest_empty_authenticator(&authent); + } + + /****************************************************************/ + /* encode_krb5_ticket */ + { + krb5_ticket tkt, *tmp; + + ktest_make_sample_ticket(&tkt); + leak_test(tkt, encode_krb5_ticket, decode_krb5_ticket, + krb5_free_ticket); + ktest_empty_ticket(&tkt); + } + + /****************************************************************/ + /* encode_krb5_encryption_key */ + { + krb5_keyblock keyblk, *tmp; + + ktest_make_sample_keyblock(&keyblk); + leak_test(keyblk, encode_krb5_encryption_key, + decode_krb5_encryption_key, krb5_free_keyblock); + ktest_empty_keyblock(&keyblk); + } + + /****************************************************************/ + /* encode_krb5_enc_tkt_part */ + { + krb5_ticket tkt; + krb5_enc_tkt_part *tmp; + + memset(&tkt, 0, sizeof(krb5_ticket)); + tkt.enc_part2 = ealloc(sizeof(krb5_enc_tkt_part)); + ktest_make_sample_enc_tkt_part(tkt.enc_part2); + + leak_test(*(tkt.enc_part2), encode_krb5_enc_tkt_part, + decode_krb5_enc_tkt_part, krb5_free_enc_tkt_part); + + tkt.enc_part2->times.starttime = 0; + tkt.enc_part2->times.renew_till = 0; + ktest_destroy_address(&(tkt.enc_part2->caddrs[1])); + ktest_destroy_address(&(tkt.enc_part2->caddrs[0])); + ktest_destroy_authdata(&(tkt.enc_part2->authorization_data[1])); + ktest_destroy_authdata(&(tkt.enc_part2->authorization_data[0])); + + /* ISODE version fails on the empty caddrs field */ + ktest_destroy_addresses(&(tkt.enc_part2->caddrs)); + ktest_destroy_authorization_data(&(tkt.enc_part2->authorization_data)); + + leak_test(*(tkt.enc_part2), encode_krb5_enc_tkt_part, + decode_krb5_enc_tkt_part, krb5_free_enc_tkt_part); + ktest_empty_ticket(&tkt); + } + + /****************************************************************/ + /* encode_krb5_enc_kdc_rep_part */ + { + krb5_kdc_rep kdcr; + krb5_enc_kdc_rep_part *tmp; + + memset(&kdcr, 0, sizeof(kdcr)); + + kdcr.enc_part2 = ealloc(sizeof(krb5_enc_kdc_rep_part)); + ktest_make_sample_enc_kdc_rep_part(kdcr.enc_part2); + + leak_test(*(kdcr.enc_part2), encode_krb5_enc_kdc_rep_part, + decode_krb5_enc_kdc_rep_part, krb5_free_enc_kdc_rep_part); + + kdcr.enc_part2->key_exp = 0; + kdcr.enc_part2->times.starttime = 0; + kdcr.enc_part2->flags &= ~TKT_FLG_RENEWABLE; + ktest_destroy_addresses(&(kdcr.enc_part2->caddrs)); + + leak_test(*(kdcr.enc_part2), encode_krb5_enc_kdc_rep_part, + decode_krb5_enc_kdc_rep_part, krb5_free_enc_kdc_rep_part); + + ktest_empty_kdc_rep(&kdcr); + } + + /****************************************************************/ + /* encode_krb5_as_rep */ + { + krb5_kdc_rep kdcr, *tmp; + + ktest_make_sample_kdc_rep(&kdcr); + kdcr.msg_type = KRB5_AS_REP; + leak_test(kdcr, encode_krb5_as_rep, decode_krb5_as_rep, + krb5_free_kdc_rep); + + ktest_destroy_pa_data_array(&(kdcr.padata)); + leak_test(kdcr, encode_krb5_as_rep, decode_krb5_as_rep, + krb5_free_kdc_rep); + + ktest_empty_kdc_rep(&kdcr); + + } + + /****************************************************************/ + /* encode_krb5_tgs_rep */ + { + krb5_kdc_rep kdcr, *tmp; + + ktest_make_sample_kdc_rep(&kdcr); + kdcr.msg_type = KRB5_TGS_REP; + leak_test(kdcr, encode_krb5_tgs_rep, decode_krb5_tgs_rep, + krb5_free_kdc_rep); + + ktest_destroy_pa_data_array(&(kdcr.padata)); + leak_test(kdcr, encode_krb5_tgs_rep, decode_krb5_tgs_rep, + krb5_free_kdc_rep); + + ktest_empty_kdc_rep(&kdcr); + + } + + /****************************************************************/ + /* encode_krb5_ap_req */ + { + krb5_ap_req apreq, *tmp; + + ktest_make_sample_ap_req(&apreq); + leak_test(apreq, encode_krb5_ap_req, decode_krb5_ap_req, + krb5_free_ap_req); + ktest_empty_ap_req(&apreq); + } + + /****************************************************************/ + /* encode_krb5_ap_rep */ + { + krb5_ap_rep aprep, *tmp; + + ktest_make_sample_ap_rep(&aprep); + leak_test(aprep, encode_krb5_ap_rep, decode_krb5_ap_rep, + krb5_free_ap_rep); + ktest_empty_ap_rep(&aprep); + } + + /****************************************************************/ + /* encode_krb5_ap_rep_enc_part */ + { + krb5_ap_rep_enc_part apenc, *tmp; + + ktest_make_sample_ap_rep_enc_part(&apenc); + leak_test(apenc, encode_krb5_ap_rep_enc_part, + decode_krb5_ap_rep_enc_part, krb5_free_ap_rep_enc_part); + + ktest_destroy_keyblock(&(apenc.subkey)); + apenc.seq_number = 0; + leak_test(apenc, encode_krb5_ap_rep_enc_part, + decode_krb5_ap_rep_enc_part, krb5_free_ap_rep_enc_part); + ktest_empty_ap_rep_enc_part(&apenc); + } + + /****************************************************************/ + /* encode_krb5_as_req */ + { + krb5_kdc_req asreq, *tmp; + + ktest_make_sample_kdc_req(&asreq); + asreq.msg_type = KRB5_AS_REQ; + asreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + leak_test(asreq, encode_krb5_as_req, decode_krb5_as_req, + krb5_free_kdc_req); + + ktest_destroy_pa_data_array(&(asreq.padata)); + ktest_destroy_principal(&(asreq.client)); +#ifndef ISODE_SUCKS + ktest_destroy_principal(&(asreq.server)); +#endif + asreq.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY; + asreq.from = 0; + asreq.rtime = 0; + ktest_destroy_addresses(&(asreq.addresses)); + ktest_destroy_enc_data(&(asreq.authorization_data)); + leak_test(asreq, encode_krb5_as_req, decode_krb5_as_req, + krb5_free_kdc_req); + + ktest_destroy_sequence_of_ticket(&(asreq.second_ticket)); +#ifndef ISODE_SUCKS + ktest_make_sample_principal(&(asreq.server)); +#endif + asreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + leak_test(asreq, encode_krb5_as_req, decode_krb5_as_req, + krb5_free_kdc_req); + ktest_empty_kdc_req(&asreq); + } + + /****************************************************************/ + /* encode_krb5_tgs_req */ + { + krb5_kdc_req tgsreq, *tmp; + + ktest_make_sample_kdc_req(&tgsreq); + tgsreq.msg_type = KRB5_TGS_REQ; + tgsreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + leak_test(tgsreq, encode_krb5_tgs_req, decode_krb5_tgs_req, + krb5_free_kdc_req); + + ktest_destroy_pa_data_array(&(tgsreq.padata)); + ktest_destroy_principal(&(tgsreq.client)); +#ifndef ISODE_SUCKS + ktest_destroy_principal(&(tgsreq.server)); +#endif + tgsreq.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY; + tgsreq.from = 0; + tgsreq.rtime = 0; + ktest_destroy_addresses(&(tgsreq.addresses)); + ktest_destroy_enc_data(&(tgsreq.authorization_data)); + leak_test(tgsreq, encode_krb5_tgs_req, decode_krb5_tgs_req, + krb5_free_kdc_req); + + ktest_destroy_sequence_of_ticket(&(tgsreq.second_ticket)); +#ifndef ISODE_SUCKS + ktest_make_sample_principal(&(tgsreq.server)); +#endif + tgsreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + leak_test(tgsreq, encode_krb5_tgs_req, decode_krb5_tgs_req, + krb5_free_kdc_req); + ktest_empty_kdc_req(&tgsreq); + } + + /****************************************************************/ + /* encode_krb5_kdc_req_body */ + { + krb5_kdc_req kdcrb, *tmp; + + memset(&kdcrb, 0, sizeof(kdcrb)); + ktest_make_sample_kdc_req_body(&kdcrb); + kdcrb.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + leak_test(kdcrb, encode_krb5_kdc_req_body, decode_krb5_kdc_req_body, + krb5_free_kdc_req); + + ktest_destroy_principal(&(kdcrb.client)); +#ifndef ISODE_SUCKS + ktest_destroy_principal(&(kdcrb.server)); +#endif + kdcrb.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY; + kdcrb.from = 0; + kdcrb.rtime = 0; + ktest_destroy_addresses(&(kdcrb.addresses)); + ktest_destroy_enc_data(&(kdcrb.authorization_data)); + leak_test(kdcrb, encode_krb5_kdc_req_body, decode_krb5_kdc_req_body, + krb5_free_kdc_req); + + ktest_destroy_sequence_of_ticket(&(kdcrb.second_ticket)); +#ifndef ISODE_SUCKS + ktest_make_sample_principal(&(kdcrb.server)); +#endif + kdcrb.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + leak_test(kdcrb, encode_krb5_kdc_req_body, decode_krb5_kdc_req_body, + krb5_free_kdc_req); + ktest_empty_kdc_req(&kdcrb); + } + + /****************************************************************/ + /* encode_krb5_safe */ + { + krb5_safe s, *tmp; + + ktest_make_sample_safe(&s); + leak_test(s, encode_krb5_safe, decode_krb5_safe, krb5_free_safe); + + s.timestamp = 0; + /* s.usec should be opted out by the timestamp */ + s.seq_number = 0; + ktest_destroy_address(&(s.r_address)); + leak_test(s, encode_krb5_safe, decode_krb5_safe, krb5_free_safe); + ktest_empty_safe(&s); + } + + /****************************************************************/ + /* encode_krb5_priv */ + { + krb5_priv p, *tmp; + + ktest_make_sample_priv(&p); + leak_test(p, encode_krb5_priv, decode_krb5_priv, krb5_free_priv); + ktest_empty_priv(&p); + } + + /****************************************************************/ + /* encode_krb5_enc_priv_part */ + { + krb5_priv_enc_part ep, *tmp; + + ktest_make_sample_priv_enc_part(&ep); + leak_test(ep, encode_krb5_enc_priv_part, decode_krb5_enc_priv_part, + krb5_free_priv_enc_part); + + ep.timestamp = 0; + /* ep.usec should be opted out along with timestamp */ + ep.seq_number = 0; + ktest_destroy_address(&(ep.r_address)); + leak_test(ep, encode_krb5_enc_priv_part, decode_krb5_enc_priv_part, + krb5_free_priv_enc_part); + ktest_empty_priv_enc_part(&ep); + } + + /****************************************************************/ + /* encode_krb5_cred */ + { + krb5_cred c, *tmp; + + ktest_make_sample_cred(&c); + leak_test(c, encode_krb5_cred, decode_krb5_cred, krb5_free_cred); + ktest_empty_cred(&c); + } + + /****************************************************************/ + /* encode_krb5_enc_cred_part */ + { + krb5_cred_enc_part cep, *tmp; + + ktest_make_sample_cred_enc_part(&cep); + leak_test(cep, encode_krb5_enc_cred_part, decode_krb5_enc_cred_part, + free_cred_enc_part_whole); + + ktest_destroy_principal(&(cep.ticket_info[0]->client)); + ktest_destroy_principal(&(cep.ticket_info[0]->server)); + cep.ticket_info[0]->flags = 0; + cep.ticket_info[0]->times.authtime = 0; + cep.ticket_info[0]->times.starttime = 0; + cep.ticket_info[0]->times.endtime = 0; + cep.ticket_info[0]->times.renew_till = 0; + ktest_destroy_addresses(&(cep.ticket_info[0]->caddrs)); + cep.nonce = 0; + cep.timestamp = 0; + ktest_destroy_address(&(cep.s_address)); + ktest_destroy_address(&(cep.r_address)); + leak_test(cep, encode_krb5_enc_cred_part, decode_krb5_enc_cred_part, + free_cred_enc_part_whole); + ktest_empty_cred_enc_part(&cep); + } + + /****************************************************************/ + /* encode_krb5_error */ + { + krb5_error kerr, *tmp; + + ktest_make_sample_error(&kerr); + leak_test(kerr, encode_krb5_error, decode_krb5_error, krb5_free_error); + + kerr.ctime = 0; + ktest_destroy_principal(&(kerr.client)); + ktest_empty_data(&(kerr.text)); + ktest_empty_data(&(kerr.e_data)); + leak_test(kerr, encode_krb5_error, decode_krb5_error, krb5_free_error); + + ktest_empty_error(&kerr); + } + + /****************************************************************/ + /* encode_krb5_authdata */ + { + krb5_authdata **ad, **tmp; + + ktest_make_sample_authorization_data(&ad); + leak_test(*ad, encode_krb5_authdata, decode_krb5_authdata, + krb5_free_authdata); + ktest_destroy_authorization_data(&ad); + } + + /****************************************************************/ + /* encode_padata_sequence and encode_typed_data */ + { + krb5_pa_data **pa, **tmp; + + ktest_make_sample_pa_data_array(&pa); + leak_test(*pa, encode_krb5_padata_sequence, + decode_krb5_padata_sequence, krb5_free_pa_data); + leak_test(*pa, encode_krb5_typed_data, + decode_krb5_typed_data, krb5_free_pa_data); + ktest_destroy_pa_data_array(&pa); + } + + /****************************************************************/ + /* encode_padata_sequence (empty) */ + { + krb5_pa_data **pa, **tmp; + + ktest_make_sample_empty_pa_data_array(&pa); + leak_test(*pa, encode_krb5_padata_sequence, + decode_krb5_padata_sequence, krb5_free_pa_data); + ktest_destroy_pa_data_array(&pa); + } + + /****************************************************************/ + /* encode_etype_info */ + { + krb5_etype_info_entry **info, **tmp; + + ktest_make_sample_etype_info(&info); + leak_test(*info, encode_krb5_etype_info, decode_krb5_etype_info, + krb5_free_etype_info); + + ktest_destroy_etype_info_entry(info[2]); info[2] = 0; + ktest_destroy_etype_info_entry(info[1]); info[1] = 0; + leak_test(*info, encode_krb5_etype_info, decode_krb5_etype_info, + krb5_free_etype_info); + + ktest_destroy_etype_info_entry(info[0]); info[0] = 0; + leak_test(*info, encode_krb5_etype_info, decode_krb5_etype_info, + krb5_free_etype_info); + + ktest_destroy_etype_info(info); + } + + /* encode_etype_info 2*/ + { + krb5_etype_info_entry **info, **tmp; + + ktest_make_sample_etype_info2(&info); + leak_test(*info, encode_krb5_etype_info2, decode_krb5_etype_info2, + krb5_free_etype_info); + + ktest_destroy_etype_info_entry(info[2]); info[2] = 0; + ktest_destroy_etype_info_entry(info[1]); info[1] = 0; + leak_test(*info, encode_krb5_etype_info2, decode_krb5_etype_info2, + krb5_free_etype_info); + + ktest_destroy_etype_info(info); + } + + /****************************************************************/ + /* encode_pa_enc_ts */ + { + krb5_pa_enc_ts pa_enc, *tmp; + + ktest_make_sample_pa_enc_ts(&pa_enc); + leak_test(pa_enc, encode_krb5_pa_enc_ts, decode_krb5_pa_enc_ts, + krb5_free_pa_enc_ts); + pa_enc.pausec = 0; + leak_test(pa_enc, encode_krb5_pa_enc_ts, decode_krb5_pa_enc_ts, + krb5_free_pa_enc_ts); + } + + /****************************************************************/ + /* encode_enc_data */ + { + krb5_enc_data enc_data, *tmp; + + ktest_make_sample_enc_data(&enc_data); + leak_test(enc_data, encode_krb5_enc_data, decode_krb5_enc_data, + krb5_free_enc_data); + ktest_destroy_enc_data(&enc_data); + } + /****************************************************************/ + /* encode_krb5_sam_challenge_2 */ + { + krb5_sam_challenge_2 sam_ch2, *tmp; + + ktest_make_sample_sam_challenge_2(&sam_ch2); + leak_test(sam_ch2, encode_krb5_sam_challenge_2, + decode_krb5_sam_challenge_2, krb5_free_sam_challenge_2); + ktest_empty_sam_challenge_2(&sam_ch2); + } + /****************************************************************/ + /* encode_krb5_sam_challenge_2 */ + { + krb5_sam_challenge_2_body body, *tmp; + + ktest_make_sample_sam_challenge_2_body(&body); + leak_test(body, encode_krb5_sam_challenge_2_body, + decode_krb5_sam_challenge_2_body, + krb5_free_sam_challenge_2_body); + ktest_empty_sam_challenge_2_body(&body); + } + /****************************************************************/ + /* encode_krb5_sam_response_2 */ + { + krb5_sam_response_2 sam_ch2, *tmp; + + ktest_make_sample_sam_response_2(&sam_ch2); + leak_test(sam_ch2, encode_krb5_sam_response_2, + decode_krb5_sam_response_2, krb5_free_sam_response_2); + ktest_empty_sam_response_2(&sam_ch2); + } + /****************************************************************/ + /* encode_krb5_sam_response_enc_2 */ + { + krb5_enc_sam_response_enc_2 sam_ch2, *tmp; + + ktest_make_sample_enc_sam_response_enc_2(&sam_ch2); + leak_test(sam_ch2, encode_krb5_enc_sam_response_enc_2, + decode_krb5_enc_sam_response_enc_2, + krb5_free_enc_sam_response_enc_2); + ktest_empty_enc_sam_response_enc_2(&sam_ch2); + } + /****************************************************************/ + /* encode_krb5_pa_for_user */ + { + krb5_pa_for_user foru, *tmp; + ktest_make_sample_pa_for_user(&foru); + leak_test(foru, encode_krb5_pa_for_user, decode_krb5_pa_for_user, + krb5_free_pa_for_user); + ktest_empty_pa_for_user(&foru); + } + /****************************************************************/ + /* encode_krb5_pa_s4u_x509_user */ + { + krb5_pa_s4u_x509_user s4u, *tmp; + ktest_make_sample_pa_s4u_x509_user(&s4u); + leak_test(s4u, encode_krb5_pa_s4u_x509_user, + decode_krb5_pa_s4u_x509_user, + krb5_free_pa_s4u_x509_user); + ktest_empty_pa_s4u_x509_user(&s4u); + } + /****************************************************************/ + /* encode_krb5_ad_kdcissued */ + { + krb5_ad_kdcissued kdci, *tmp; + ktest_make_sample_ad_kdcissued(&kdci); + leak_test(kdci, encode_krb5_ad_kdcissued, + decode_krb5_ad_kdcissued, + krb5_free_ad_kdcissued); + ktest_empty_ad_kdcissued(&kdci); + } + /****************************************************************/ + /* encode_krb5_iakerb_header */ + { + krb5_iakerb_header ih, *tmp; + ktest_make_sample_iakerb_header(&ih); + leak_test(ih, encode_krb5_iakerb_header, + decode_krb5_iakerb_header, + krb5_free_iakerb_header); + ktest_empty_iakerb_header(&ih); + } + /****************************************************************/ + /* encode_krb5_iakerb_finished */ + { + krb5_iakerb_finished ih, *tmp; + ktest_make_sample_iakerb_finished(&ih); + leak_test(ih, encode_krb5_iakerb_finished, + decode_krb5_iakerb_finished, + krb5_free_iakerb_finished); + ktest_empty_iakerb_finished(&ih); + } + /****************************************************************/ + /* encode_krb5_fast_response */ + { + krb5_fast_response fr, *tmp; + ktest_make_sample_fast_response(&fr); + leak_test(fr, encode_krb5_fast_response, decode_krb5_fast_response, + krb5_free_fast_response); + ktest_empty_fast_response(&fr); + } + /****************************************************************/ + /* encode_krb5_pa_fx_fast_reply */ + { + krb5_enc_data enc, *tmp; + ktest_make_sample_enc_data(&enc); + leak_test(enc, encode_krb5_pa_fx_fast_reply, + decode_krb5_pa_fx_fast_reply, krb5_free_enc_data); + ktest_destroy_enc_data(&enc); + } + krb5_free_context(test_context); + return 0; +} diff --git a/krb5-1.21.3/src/tests/asn.1/krb5_decode_test.c b/krb5-1.21.3/src/tests/asn.1/krb5_decode_test.c new file mode 100644 index 00000000..926aa947 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/krb5_decode_test.c @@ -0,0 +1,1301 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/asn.1/krb5_decode_test.c */ +/* + * Copyright (C) 1994 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "k5-spake.h" +#include "ktest.h" +#include "com_err.h" +#include "utility.h" +#include "ktest_equal.h" + +#include "debug.h" +#include + +krb5_context test_context; +int error_count = 0; + +void krb5_ktest_free_enc_data(krb5_context context, krb5_enc_data *val); + +#ifndef DISABLE_PKINIT +static int equal_principal(krb5_principal *ref, krb5_principal var); +static void ktest_free_auth_pack(krb5_context context, krb5_auth_pack *val); +static void ktest_free_kdc_dh_key_info(krb5_context context, + krb5_kdc_dh_key_info *val); +static void ktest_free_pa_pk_as_req(krb5_context context, + krb5_pa_pk_as_req *val); +static void ktest_free_pa_pk_as_rep(krb5_context context, + krb5_pa_pk_as_rep *val); +static void ktest_free_reply_key_pack(krb5_context context, + krb5_reply_key_pack *val); +#endif +static void ktest_free_kkdcp_message(krb5_context context, + krb5_kkdcp_message *val); + +int main(argc, argv) + int argc; + char **argv; +{ + krb5_data code; + krb5_error_code retval; + + retval = krb5_init_context(&test_context); + if (retval) { + com_err(argv[0], retval, "while initializing krb5"); + exit(1); + } + init_access(argv[0]); + + +#define setup(type,constructor) \ + type ref, *var; \ + constructor(&ref); \ + do {} while (0) + +#define decode_run(typestring,description,encoding,decoder,comparator,cleanup) do { \ + retval = krb5_data_hex_parse(&code,encoding); \ + if (retval) { \ + com_err("krb5_decode_test", retval, "while parsing %s", typestring); \ + exit(1); \ + } \ + retval = decoder(&code,&var); \ + if (retval) { \ + com_err("krb5_decode_test", retval, "while decoding %s", typestring); \ + error_count++; \ + } \ + test(comparator(&ref,var),typestring); \ + printf("%s\n",description); \ + krb5_free_data_contents(test_context, &code); \ + cleanup(test_context, var); \ +} while (0) + +#define decode_fail(err,typestring,description,encoding,decoder) do { \ + retval = krb5_data_hex_parse(&code,encoding); \ + if (retval) { \ + com_err("krb5_decode_test", retval, "while parsing %s", typestring); \ + exit(1); \ + } \ + retval = decoder(&code,&var); \ + if (retval != (err)) { \ + com_err("krb5_decode_test", retval, "while decoding %s", typestring); \ + error_count++; \ + } \ + test(1,typestring); \ + printf("%s\n",description); \ + krb5_free_data_contents(test_context, &code); \ +} while (0) + + /****************************************************************/ + /* decode_krb5_authenticator */ + { + setup(krb5_authenticator,ktest_make_sample_authenticator); + + decode_run("authenticator","","62 81 A1 30 81 9E A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A4 05 02 03 01 E2 40 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A7 03 02 01 11 A8 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72",decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator); + + ref.seq_number = 0xffffff80; + decode_run("authenticator","(80 -> seq-number 0xffffff80)", + "62 81 A1 30 81 9E" + " A0 03 02 01 05" + " A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55" + " A2 1A 30 18" + " A0 03 02 01 01" + " A1 11 30 0F" + " 1B 06 68 66 74 73 61 69" + " 1B 05 65 78 74 72 61" + " A3 0F 30 0D" + " A0 03 02 01 01" + " A1 06 04 04 31 32 33 34" + " A4 05 02 03 01 E2 40" + " A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A" + " A6 13 30 11" + " A0 03 02 01 01" + " A1 0A 04 08 31 32 33 34 35 36 37 38" + " A7 03 02 01 80" + " A8 24 30 22" + " 30 0F" + " A0 03 02 01 01" + " A1 08 04 06 66 6F 6F 62 61 72" + " 30 0F" + " A0 03 02 01 01" + " A1 08 04 06 66 6F 6F 62 61 72" + ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator); + + ref.seq_number = 0xffffffff; + decode_run("authenticator","(FF -> seq-number 0xffffffff)", + "62 81 A1 30 81 9E" + " A0 03 02 01 05" + " A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55" + " A2 1A 30 18" + " A0 03 02 01 01" + " A1 11 30 0F" + " 1B 06 68 66 74 73 61 69" + " 1B 05 65 78 74 72 61" + " A3 0F 30 0D" + " A0 03 02 01 01" + " A1 06 04 04 31 32 33 34" + " A4 05 02 03 01 E2 40" + " A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A" + " A6 13 30 11" + " A0 03 02 01 01" + " A1 0A 04 08 31 32 33 34 35 36 37 38" + " A7 03 02 01 FF" + " A8 24 30 22" + " 30 0F" + " A0 03 02 01 01" + " A1 08 04 06 66 6F 6F 62 61 72" + " 30 0F" + " A0 03 02 01 01" + " A1 08 04 06 66 6F 6F 62 61 72" + ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator); + + ref.seq_number = 0xff; + decode_run("authenticator","(00FF -> seq-number 0xff)", + "62 81 A2 30 81 9F" + " A0 03 02 01 05" + " A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55" + " A2 1A 30 18" + " A0 03 02 01 01" + " A1 11 30 0F" + " 1B 06 68 66 74 73 61 69" + " 1B 05 65 78 74 72 61" + " A3 0F 30 0D" + " A0 03 02 01 01" + " A1 06 04 04 31 32 33 34" + " A4 05 02 03 01 E2 40" + " A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A" + " A6 13 30 11" + " A0 03 02 01 01" + " A1 0A 04 08 31 32 33 34 35 36 37 38" + " A7 04 02 02 00 FF" + " A8 24 30 22" + " 30 0F" + " A0 03 02 01 01" + " A1 08 04 06 66 6F 6F 62 61 72" + " 30 0F" + " A0 03 02 01 01" + " A1 08 04 06 66 6F 6F 62 61 72" + ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator); + + ref.seq_number = 0xffffffff; + decode_run("authenticator","(00FFFFFFFF -> seq-number 0xffffffff)", + "62 81 A5 30 81 A2" + " A0 03 02 01 05" + " A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55" + " A2 1A 30 18" + " A0 03 02 01 01" + " A1 11 30 0F" + " 1B 06 68 66 74 73 61 69" + " 1B 05 65 78 74 72 61" + " A3 0F 30 0D" + " A0 03 02 01 01" + " A1 06 04 04 31 32 33 34" + " A4 05 02 03 01 E2 40" + " A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A" + " A6 13 30 11" + " A0 03 02 01 01" + " A1 0A 04 08 31 32 33 34 35 36 37 38" + " A7 07 02 05 00 FF FF FF FF" + " A8 24 30 22" + " 30 0F" + " A0 03 02 01 01" + " A1 08 04 06 66 6F 6F 62 61 72" + " 30 0F" + " A0 03 02 01 01" + " A1 08 04 06 66 6F 6F 62 61 72" + ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator); + + ref.seq_number = 0x7fffffff; + decode_run("authenticator","(7FFFFFFF -> seq-number 0x7fffffff)", + "62 81 A4 30 81 A1" + " A0 03 02 01 05" + " A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55" + " A2 1A 30 18" + " A0 03 02 01 01" + " A1 11 30 0F" + " 1B 06 68 66 74 73 61 69" + " 1B 05 65 78 74 72 61" + " A3 0F 30 0D" + " A0 03 02 01 01" + " A1 06 04 04 31 32 33 34" + " A4 05 02 03 01 E2 40" + " A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A" + " A6 13 30 11" + " A0 03 02 01 01" + " A1 0A 04 08 31 32 33 34 35 36 37 38" + " A7 06 02 04 7F FF FF FF" + " A8 24 30 22" + " 30 0F" + " A0 03 02 01 01" + " A1 08 04 06 66 6F 6F 62 61 72" + " 30 0F" + " A0 03 02 01 01" + " A1 08 04 06 66 6F 6F 62 61 72" + ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator); + + ref.seq_number = 0xffffffff; + decode_run("authenticator","(FFFFFFFF -> seq-number 0xffffffff)", + "62 81 A4 30 81 A1" + " A0 03 02 01 05" + " A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55" + " A2 1A 30 18" + " A0 03 02 01 01" + " A1 11 30 0F" + " 1B 06 68 66 74 73 61 69" + " 1B 05 65 78 74 72 61" + " A3 0F 30 0D" + " A0 03 02 01 01" + " A1 06 04 04 31 32 33 34" + " A4 05 02 03 01 E2 40" + " A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A" + " A6 13 30 11" + " A0 03 02 01 01" + " A1 0A 04 08 31 32 33 34 35 36 37 38" + " A7 06 02 04 FF FF FF FF" + " A8 24 30 22" + " 30 0F" + " A0 03 02 01 01" + " A1 08 04 06 66 6F 6F 62 61 72" + " 30 0F" + " A0 03 02 01 01" + " A1 08 04 06 66 6F 6F 62 61 72" + ,decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator); + + ktest_destroy_checksum(&(ref.checksum)); + ktest_destroy_keyblock(&(ref.subkey)); + ref.seq_number = 0; + ktest_empty_authorization_data(ref.authorization_data); + decode_run("authenticator","(optionals empty)","62 4F 30 4D A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 05 02 03 01 E2 40 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator); + + ktest_destroy_authorization_data(&(ref.authorization_data)); + + decode_run("authenticator","(optionals NULL)","62 4F 30 4D A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 05 02 03 01 E2 40 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_authenticator,ktest_equal_authenticator,krb5_free_authenticator); + + ktest_empty_authenticator(&ref); + } + + /****************************************************************/ + /* decode_krb5_ticket */ + { + setup(krb5_ticket,ktest_make_sample_ticket); + decode_run("ticket","","61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_ticket,ktest_equal_ticket,krb5_free_ticket); + decode_run("ticket","(+ trailing [4] INTEGER","61 61 30 5F A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A4 03 02 01 01",decode_krb5_ticket,ktest_equal_ticket,krb5_free_ticket); + +/* + "61 80 30 80 " + " A0 03 02 01 05 " + " A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 " + " A2 80 30 80 " + " A0 03 02 01 01 " + " A1 80 30 80 " + " 1B 06 68 66 74 73 61 69 " + " 1B 05 65 78 74 72 61 " + " 00 00 00 00 " + " 00 00 00 00 " + " A3 80 30 80 " + " A0 03 02 01 00 " + " A1 03 02 01 05 " + " A2 17 04 15 6B 72 62 41 53 4E 2E 31 " + " 20 74 65 73 74 20 6D 65 73 73 61 67 65 " + " 00 00 00 00" + "00 00 00 00" +*/ + decode_fail(ASN1_INDEF,"ticket","(indefinite lengths)", "61 80 30 80 A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 80 30 80 A0 03 02 01 01 A1 80 30 80 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 00 00 00 00 00 00 00 00 A3 80 30 80 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 00 00 00 00 00 00 00 00" ,decode_krb5_ticket); +/* + "61 80 30 80 " + " A0 03 02 01 05 " + " A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 " + " A2 80 30 80 " + " A0 03 02 01 01 " + " A1 80 30 80 " + " 1B 06 68 66 74 73 61 69 " + " 1B 05 65 78 74 72 61 " + " 00 00 00 00 " + " 00 00 00 00 " + " A3 80 30 80 " + " A0 03 02 01 00 " + " A1 03 02 01 05 " + " A2 17 04 15 6B 72 62 41 53 4E 2E 31 " + " 20 74 65 73 74 20 6D 65 73 73 61 67 65 " + " 00 00 00 00" + " A4 03 02 01 01 " + "00 00 00 00" +*/ + decode_fail(ASN1_INDEF,"ticket","(indefinite lengths + trailing [4] INTEGER)", "61 80 30 80 A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 80 30 80 A0 03 02 01 01 A1 80 30 80 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 00 00 00 00 00 00 00 00 A3 80 30 80 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 00 00 00 00 A4 03 02 01 01 00 00 00 00",decode_krb5_ticket); + + ktest_empty_ticket(&ref); + + } + + /****************************************************************/ + /* decode_krb5_encryption_key */ + { + setup(krb5_keyblock,ktest_make_sample_keyblock); + + decode_run("encryption_key","","30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock); + + decode_run("encryption_key","(+ trailing [2] INTEGER)","30 16 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 03 02 01 01",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock); + decode_run("encryption_key","(+ trailing [2] SEQUENCE {[0] INTEGER})","30 1A A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 07 30 05 A0 03 02 01 01",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock); + decode_fail(ASN1_INDEF,"encryption_key","(indefinite lengths)","30 80 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 00 00",decode_krb5_encryption_key); + decode_fail(ASN1_INDEF,"encryption_key","(indefinite lengths + trailing [2] INTEGER)","30 80 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 03 02 01 01 00 00",decode_krb5_encryption_key); + decode_fail(ASN1_INDEF,"encryption_key","(indefinite lengths + trailing [2] SEQUENCE {[0] INTEGER})","30 80 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 80 30 80 A0 03 02 01 01 00 00 00 00 00 00",decode_krb5_encryption_key); + decode_fail(ASN1_INDEF,"encryption_key","(indefinite lengths + trailing SEQUENCE {[0] INTEGER})","30 80 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 30 80 A0 03 02 01 01 00 00 00 00",decode_krb5_encryption_key); + ref.enctype = -1; + decode_run("encryption_key","(enctype = -1)","30 11 A0 03 02 01 FF A1 0A 04 08 31 32 33 34 35 36 37 38",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock); + ref.enctype = -255; + decode_run("encryption_key","(enctype = -255)","30 12 A0 04 02 02 FF 01 A1 0A 04 08 31 32 33 34 35 36 37 38",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock); + ref.enctype = 255; + decode_run("encryption_key","(enctype = 255)","30 12 A0 04 02 02 00 FF A1 0A 04 08 31 32 33 34 35 36 37 38",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock); + ref.enctype = -2147483648U; + decode_run("encryption_key","(enctype = -2147483648)","30 14 A0 06 02 04 80 00 00 00 A1 0A 04 08 31 32 33 34 35 36 37 38",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock); + ref.enctype = 2147483647; + decode_run("encryption_key","(enctype = 2147483647)","30 14 A0 06 02 04 7F FF FF FF A1 0A 04 08 31 32 33 34 35 36 37 38",decode_krb5_encryption_key,ktest_equal_encryption_key,krb5_free_keyblock); + + ktest_empty_keyblock(&ref); + } + + /****************************************************************/ + /* decode_krb5_enc_tkt_part */ + { + setup(krb5_enc_tkt_part,ktest_make_sample_enc_tkt_part); + decode_run("enc_tkt_part","","63 82 01 14 30 82 01 10 A0 07 03 05 00 FE DC BA 98 A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72",decode_krb5_enc_tkt_part,ktest_equal_enc_tkt_part,krb5_free_enc_tkt_part); + + ref.times.starttime = 0; + ref.times.renew_till = 0; + ktest_destroy_address(&(ref.caddrs[1])); + ktest_destroy_address(&(ref.caddrs[0])); + ktest_destroy_authdata(&(ref.authorization_data[1])); + ktest_destroy_authdata(&(ref.authorization_data[0])); + /* ISODE version fails on the empty caddrs field */ + ktest_destroy_addresses(&(ref.caddrs)); + ktest_destroy_authorization_data(&(ref.authorization_data)); + + decode_run("enc_tkt_part","(optionals NULL)","63 81 A5 30 81 A2 A0 07 03 05 00 FE DC BA 98 A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_enc_tkt_part,ktest_equal_enc_tkt_part, krb5_free_enc_tkt_part); + + decode_run("enc_tkt_part","(optionals NULL + bitstring enlarged to 38 bits)","63 81 A6 30 81 A3 A0 08 03 06 02 FE DC BA 98 DC A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_enc_tkt_part,ktest_equal_enc_tkt_part,krb5_free_enc_tkt_part); + + decode_run("enc_tkt_part","(optionals NULL + bitstring enlarged to 40 bits)","63 81 A6 30 81 A3 A0 08 03 06 00 FE DC BA 98 DE A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_enc_tkt_part,ktest_equal_enc_tkt_part,krb5_free_enc_tkt_part); + + decode_run("enc_tkt_part","(optionals NULL + bitstring reduced to 29 bits)","63 81 A5 30 81 A2 A0 07 03 05 03 FE DC BA 98 A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_enc_tkt_part,ktest_equal_enc_tkt_part,krb5_free_enc_tkt_part); + + ref.flags &= 0xFFFFFF00; + + decode_run("enc_tkt_part","(optionals NULL + bitstring reduced to 24 bits)","63 81 A4 30 81 A1 A0 06 03 04 00 FE DC BA A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_enc_tkt_part,ktest_equal_enc_tkt_part,krb5_free_enc_tkt_part); + + ktest_empty_enc_tkt_part(&ref); + } + + /****************************************************************/ + /* decode_krb5_enc_kdc_rep_part */ + { + setup(krb5_enc_kdc_rep_part,ktest_make_sample_enc_kdc_rep_part); + + decode_run("enc_kdc_rep_part","","7A 82 01 0E 30 82 01 0A A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 36 30 34 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A4 07 03 05 00 FE DC BA 98 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AB 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23",decode_krb5_enc_kdc_rep_part,ktest_equal_enc_kdc_rep_part,krb5_free_enc_kdc_rep_part); + + ref.key_exp = 0; + /* ref.times.starttime = 0;*/ + ref.times.starttime = ref.times.authtime; + ref.times.renew_till = 0; + ref.flags &= ~TKT_FLG_RENEWABLE; + ktest_destroy_addresses(&(ref.caddrs)); + + decode_run("enc_kdc_rep_part","(optionals NULL)","7A 81 B2 30 81 AF A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 36 30 34 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A4 07 03 05 00 FE 5C BA 98 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61",decode_krb5_enc_kdc_rep_part,ktest_equal_enc_kdc_rep_part,krb5_free_enc_kdc_rep_part); + + ktest_empty_enc_kdc_rep_part(&ref); + } + + /****************************************************************/ + /* decode_krb5_as_rep */ + { + setup(krb5_kdc_rep,ktest_make_sample_kdc_rep); + ref.msg_type = KRB5_AS_REP; + + decode_run("as_rep","","6B 81 EA 30 81 E7 A0 03 02 01 05 A1 03 02 01 0B A2 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_as_rep,ktest_equal_as_rep,krb5_free_kdc_rep); + +/* + 6B 80 30 80 + A0 03 02 01 05 + A1 03 02 01 0B + A2 80 30 80 + 30 80 + A1 03 02 01 0D + A2 09 04 07 70 61 2D 64 61 74 61 + 00 00 + 30 80 + A1 03 02 01 0D + A2 09 04 07 70 61 2D 64 61 74 61 + 00 00 + 00 00 00 00 + A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 + A4 80 30 80 + A0 03 02 01 01 + A1 80 30 80 + 1B 06 68 66 74 73 61 69 + 1B 05 65 78 74 72 61 + 00 00 00 00 + 00 00 00 00 + A5 80 61 80 30 80 + A0 03 02 01 05 + A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 + A2 80 30 80 + A0 03 02 01 01 + A1 80 30 80 + 1B 06 68 66 74 73 61 69 + 1B 05 65 78 74 72 61 + 00 00 00 00 + 00 00 00 00 + A3 80 30 80 + A0 03 02 01 00 + A1 03 02 01 05 + A2 17 04 15 6B 72 62 41 53 4E 2E 31 + 20 74 65 73 74 20 6D 65 + 73 73 61 67 65 + 00 00 00 00 + 00 00 00 00 00 00 + A6 80 30 80 + A0 03 02 01 00 + A1 03 02 01 05 + A2 17 04 15 6B 72 62 41 53 4E 2E 31 + 20 74 65 73 74 20 6D 65 + 73 73 61 67 65 + 00 00 00 00 + 00 00 00 00 +*/ + decode_fail(ASN1_INDEF,"as_rep","(indefinite lengths)","6B 80 30 80 A0 03 02 01 05 A1 03 02 01 0B A2 80 30 80 30 80 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 00 00 30 80 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 00 00 00 00 00 00 A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 80 30 80 A0 03 02 01 01 A1 80 30 80 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 00 00 00 00 00 00 00 00 A5 80 61 80 30 80 A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 80 30 80 A0 03 02 01 01 A1 80 30 80 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 00 00 00 00 00 00 00 00 A3 80 30 80 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 00 00 00 00 00 00 00 00 00 00 A6 80 30 80 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 00 00 00 00 00 00 00 00",decode_krb5_as_rep); + ktest_destroy_pa_data_array(&(ref.padata)); + decode_run("as_rep","(optionals NULL)","6B 81 C2 30 81 BF A0 03 02 01 05 A1 03 02 01 0B A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_as_rep,ktest_equal_as_rep,krb5_free_kdc_rep); + + ktest_empty_kdc_rep(&ref); + } + + /****************************************************************/ + /* decode_krb5_tgs_rep */ + { + setup(krb5_kdc_rep,ktest_make_sample_kdc_rep); + ref.msg_type = KRB5_TGS_REP; + + decode_run("tgs_rep","","6D 81 EA 30 81 E7 A0 03 02 01 05 A1 03 02 01 0D A2 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_tgs_rep,ktest_equal_tgs_rep,krb5_free_kdc_rep); + + ktest_destroy_pa_data_array(&(ref.padata)); + decode_run("tgs_rep","(optionals NULL)","6D 81 C2 30 81 BF A0 03 02 01 05 A1 03 02 01 0D A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_tgs_rep,ktest_equal_tgs_rep,krb5_free_kdc_rep); + + ktest_empty_kdc_rep(&ref); + } + + /****************************************************************/ + /* decode_krb5_ap_req */ + { + setup(krb5_ap_req,ktest_make_sample_ap_req); + decode_run("ap_req","","6E 81 9D 30 81 9A A0 03 02 01 05 A1 03 02 01 0E A2 07 03 05 00 FE DC BA 98 A3 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A4 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_ap_req,ktest_equal_ap_req,krb5_free_ap_req); + ktest_empty_ap_req(&ref); + + } + + /****************************************************************/ + /* decode_krb5_ap_rep */ + { + setup(krb5_ap_rep,ktest_make_sample_ap_rep); + decode_run("ap_rep","","6F 33 30 31 A0 03 02 01 05 A1 03 02 01 0F A2 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_ap_rep,ktest_equal_ap_rep,krb5_free_ap_rep); + ktest_empty_ap_rep(&ref); + } + + /****************************************************************/ + /* decode_krb5_ap_rep_enc_part */ + { + setup(krb5_ap_rep_enc_part,ktest_make_sample_ap_rep_enc_part); + + decode_run("ap_rep_enc_part","","7B 36 30 34 A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40 A2 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A3 03 02 01 11",decode_krb5_ap_rep_enc_part,ktest_equal_ap_rep_enc_part,krb5_free_ap_rep_enc_part); + + ktest_destroy_keyblock(&(ref.subkey)); + ref.seq_number = 0; + decode_run("ap_rep_enc_part","(optionals NULL)","7B 1C 30 1A A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40",decode_krb5_ap_rep_enc_part,ktest_equal_ap_rep_enc_part,krb5_free_ap_rep_enc_part); + + retval = krb5_data_hex_parse(&code, "7B 06 30 04 A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40"); + if (retval) { + com_err("krb5_decode_test", retval, "while parsing"); + exit(1); + } + retval = decode_krb5_ap_rep_enc_part(&code, &var); + if (retval != ASN1_OVERRUN) { + printf("ERROR: "); + error_count++; + } else { + printf("OK: "); + } + printf("ap_rep_enc_part(optionals NULL + expect ASN1_OVERRUN for inconsistent length of timestamp)\n"); + krb5_free_data_contents(test_context, &code); + krb5_free_ap_rep_enc_part(test_context, var); + + ktest_empty_ap_rep_enc_part(&ref); + } + + /****************************************************************/ + /* decode_krb5_as_req */ + { + setup(krb5_kdc_req,ktest_make_sample_kdc_req); + ref.msg_type = KRB5_AS_REQ; + + ref.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + decode_run("as_req","","6A 82 01 E4 30 82 01 E0 A1 03 02 01 05 A2 03 02 01 0A A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A4 82 01 AA 30 82 01 A6 A0 07 03 05 00 FE DC BA 90 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_as_req,ktest_equal_as_req,krb5_free_kdc_req); + + ktest_destroy_pa_data_array(&(ref.padata)); + ktest_destroy_principal(&(ref.client)); +#ifndef ISODE_SUCKS + ktest_destroy_principal(&(ref.server)); +#endif + ref.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY; + ref.from = 0; + ref.rtime = 0; + ktest_destroy_addresses(&(ref.addresses)); + ktest_destroy_enc_data(&(ref.authorization_data)); + decode_run("as_req","(optionals NULL except second_ticket)","6A 82 01 14 30 82 01 10 A1 03 02 01 05 A2 03 02 01 0A A4 82 01 02 30 81 FF A0 07 03 05 00 FE DC BA 98 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_as_req,ktest_equal_as_req,krb5_free_kdc_req); + ktest_destroy_sequence_of_ticket(&(ref.second_ticket)); +#ifndef ISODE_SUCKS + ktest_make_sample_principal(&(ref.server)); +#endif + ref.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + decode_run("as_req","(optionals NULL except server)","6A 69 30 67 A1 03 02 01 05 A2 03 02 01 0A A4 5B 30 59 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01",decode_krb5_as_req,ktest_equal_as_req,krb5_free_kdc_req); + + ktest_empty_kdc_req(&ref); + + } + + + /****************************************************************/ + /* decode_krb5_tgs_req */ + { + setup(krb5_kdc_req,ktest_make_sample_kdc_req); + ref.msg_type = KRB5_TGS_REQ; + + ref.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + decode_run("tgs_req","","6C 82 01 E4 30 82 01 E0 A1 03 02 01 05 A2 03 02 01 0C A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A4 82 01 AA 30 82 01 A6 A0 07 03 05 00 FE DC BA 90 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_tgs_req,ktest_equal_tgs_req,krb5_free_kdc_req); + + ktest_destroy_pa_data_array(&(ref.padata)); + ktest_destroy_principal(&(ref.client)); +#ifndef ISODE_SUCKS + ktest_destroy_principal(&(ref.server)); +#endif + ref.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY; + ref.from = 0; + ref.rtime = 0; + ktest_destroy_addresses(&(ref.addresses)); + ktest_destroy_enc_data(&(ref.authorization_data)); + decode_run("tgs_req","(optionals NULL except second_ticket)","6C 82 01 14 30 82 01 10 A1 03 02 01 05 A2 03 02 01 0C A4 82 01 02 30 81 FF A0 07 03 05 00 FE DC BA 98 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_tgs_req,ktest_equal_tgs_req,krb5_free_kdc_req); + + ktest_destroy_sequence_of_ticket(&(ref.second_ticket)); +#ifndef ISODE_SUCKS + ktest_make_sample_principal(&(ref.server)); +#endif + ref.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + decode_run("tgs_req","(optionals NULL except server)","6C 69 30 67 A1 03 02 01 05 A2 03 02 01 0C A4 5B 30 59 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01",decode_krb5_tgs_req,ktest_equal_tgs_req,krb5_free_kdc_req); + + ktest_empty_kdc_req(&ref); + } + + /****************************************************************/ + /* decode_krb5_kdc_req_body */ + { + krb5_kdc_req ref, *var; + memset(&ref, 0, sizeof(krb5_kdc_req)); + ktest_make_sample_kdc_req_body(&ref); + ref.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + decode_run("kdc_req_body","","30 82 01 A6 A0 07 03 05 00 FE DC BA 90 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_kdc_req_body,ktest_equal_kdc_req_body,krb5_free_kdc_req); + + ktest_destroy_principal(&(ref.client)); +#ifndef ISODE_SUCKS + ktest_destroy_principal(&(ref.server)); +#endif + ref.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY; + ref.from = 0; + ref.rtime = 0; + ktest_destroy_addresses(&(ref.addresses)); + ktest_destroy_enc_data(&(ref.authorization_data)); + decode_run("kdc_req_body","(optionals NULL except second_ticket)","30 81 FF A0 07 03 05 00 FE DC BA 98 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_kdc_req_body,ktest_equal_kdc_req_body,krb5_free_kdc_req); + + ktest_destroy_sequence_of_ticket(&(ref.second_ticket)); +#ifndef ISODE_SUCKS + ktest_make_sample_principal(&(ref.server)); +#endif + ref.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + decode_run("kdc_req_body","(optionals NULL except server)","30 59 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01",decode_krb5_kdc_req_body,ktest_equal_kdc_req_body,krb5_free_kdc_req); + ref.nktypes = 0; + free(ref.ktype); + ref.ktype = NULL; + decode_run("kdc_req_body","(optionals NULL except server; zero-length etypes)","30 53 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 02 30 00",decode_krb5_kdc_req_body,ktest_equal_kdc_req_body,krb5_free_kdc_req); + + ktest_empty_kdc_req(&ref); + } + + + /****************************************************************/ + /* decode_krb5_safe */ + { + setup(krb5_safe,ktest_make_sample_safe); + decode_run("safe","","74 6E 30 6C A0 03 02 01 05 A1 03 02 01 14 A2 4F 30 4D A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 05 02 03 01 E2 40 A3 03 02 01 11 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A5 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A3 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34",decode_krb5_safe,ktest_equal_safe,krb5_free_safe); + + ref.timestamp = 0; + ref.usec = 0; + ref.seq_number = 0; + ktest_destroy_address(&(ref.r_address)); + decode_run("safe","(optionals NULL)","74 3E 30 3C A0 03 02 01 05 A1 03 02 01 14 A2 1F 30 1D A0 0A 04 08 6B 72 62 35 64 61 74 61 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A3 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34",decode_krb5_safe,ktest_equal_safe,krb5_free_safe); + + ktest_empty_safe(&ref); + } + + /****************************************************************/ + /* decode_krb5_priv */ + { + setup(krb5_priv,ktest_make_sample_priv); + decode_run("priv","","75 33 30 31 A0 03 02 01 05 A1 03 02 01 15 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_priv,ktest_equal_priv,krb5_free_priv); + ktest_empty_priv(&ref); + } + + /****************************************************************/ + /* decode_krb5_enc_priv_part */ + { + setup(krb5_priv_enc_part,ktest_make_sample_priv_enc_part); + decode_run("enc_priv_part","","7C 4F 30 4D A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 05 02 03 01 E2 40 A3 03 02 01 11 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A5 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23",decode_krb5_enc_priv_part,ktest_equal_enc_priv_part,krb5_free_priv_enc_part); + + ref.timestamp = 0; + ref.usec = 0; + ref.seq_number = 0; + ktest_destroy_address(&(ref.r_address)); + decode_run("enc_priv_part","(optionals NULL)","7C 1F 30 1D A0 0A 04 08 6B 72 62 35 64 61 74 61 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23",decode_krb5_enc_priv_part,ktest_equal_enc_priv_part,krb5_free_priv_enc_part); + ktest_empty_priv_enc_part(&ref); + } + + /****************************************************************/ + /* decode_krb5_cred */ + { + setup(krb5_cred,ktest_make_sample_cred); + decode_run("cred","","76 81 F6 30 81 F3 A0 03 02 01 05 A1 03 02 01 16 A2 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_cred,ktest_equal_cred,krb5_free_cred); + ktest_empty_cred(&ref); + } + + /****************************************************************/ + /* decode_krb5_enc_cred_part */ + { + setup(krb5_cred_enc_part,ktest_make_sample_cred_enc_part); + decode_run("enc_cred_part","","7D 82 02 23 30 82 02 1F A0 82 01 DA 30 82 01 D6 30 81 E8 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 07 03 05 00 FE DC BA 98 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A9 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AA 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 81 E8 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 07 03 05 00 FE DC BA 98 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A9 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AA 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A1 03 02 01 2A A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A3 05 02 03 01 E2 40 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A5 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23",decode_krb5_enc_cred_part,ktest_equal_enc_cred_part,krb5_free_cred_enc_part); + /* free_cred_enc_part does not free the pointer */ + free(var); + ktest_destroy_principal(&(ref.ticket_info[0]->client)); + ktest_destroy_principal(&(ref.ticket_info[0]->server)); + ref.ticket_info[0]->flags = 0; + ref.ticket_info[0]->times.authtime = 0; + ref.ticket_info[0]->times.starttime = 0; + ref.ticket_info[0]->times.endtime = 0; + ref.ticket_info[0]->times.renew_till = 0; + ktest_destroy_addresses(&(ref.ticket_info[0]->caddrs)); + ref.nonce = 0; + ref.timestamp = 0; + ref.usec = 0; + ktest_destroy_address(&(ref.s_address)); + ktest_destroy_address(&(ref.r_address)); + decode_run("enc_cred_part","(optionals NULL)","7D 82 01 0E 30 82 01 0A A0 82 01 06 30 82 01 02 30 15 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 30 81 E8 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 07 03 05 00 FE DC BA 98 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A9 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AA 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23",decode_krb5_enc_cred_part,ktest_equal_enc_cred_part,krb5_free_cred_enc_part); + /* free_cred_enc_part does not free the pointer */ + free(var); + + ktest_empty_cred_enc_part(&ref); + } + + /****************************************************************/ + /* decode_krb5_error */ + { + setup(krb5_error,ktest_make_sample_error); + decode_run("error","","7E 81 BA 30 81 B7 A0 03 02 01 05 A1 03 02 01 1E A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A3 05 02 03 01 E2 40 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 05 02 03 01 E2 40 A6 03 02 01 3C A7 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A8 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AB 0A 1B 08 6B 72 62 35 64 61 74 61 AC 0A 04 08 6B 72 62 35 64 61 74 61",decode_krb5_error,ktest_equal_error,krb5_free_error); + + ref.ctime = 0; + ktest_destroy_principal(&(ref.client)); + ktest_empty_data(&(ref.text)); + ktest_empty_data(&(ref.e_data)); + decode_run("error","(optionals NULL)","7E 60 30 5E A0 03 02 01 05 A1 03 02 01 1E A3 05 02 03 01 E2 40 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 05 02 03 01 E2 40 A6 03 02 01 3C A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61",decode_krb5_error,ktest_equal_error,krb5_free_error); + + ktest_empty_error(&ref); + } + + /****************************************************************/ + /* decode_krb5_authdata and krb5int_get_authdata_containee_types */ + { + krb5_authdata **ref, **var, tmp; + unsigned int count; + krb5_authdatatype *types = NULL; + ktest_make_sample_authorization_data(&ref); + retval = krb5_data_hex_parse(&code,"30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72"); + if (retval) { + com_err("parsing authorization_data",retval,""); + exit(1); + } + retval = decode_krb5_authdata(&code,&var); + if (retval) com_err("decoding authorization_data",retval,""); + test(ktest_equal_authorization_data(ref,var),"authorization_data\n"); + tmp.length = code.length; + tmp.contents = (krb5_octet *)code.data; + retval = krb5int_get_authdata_containee_types(test_context, &tmp, + &count, &types); + if (retval) com_err("reading authdata types",retval,""); + test(count == 2 && types[0] == 1 && types[1] == 1, + "authorization_data(types only)\n"); + free(types); + krb5_free_data_contents(test_context, &code); + krb5_free_authdata(test_context, var); + ktest_destroy_authorization_data(&ref); + } + + /****************************************************************/ + /* decode_krb5_padata_sequence and decode_krb5_typed_data */ + { + krb5_pa_data **ref, **var; + ktest_make_sample_pa_data_array(&ref); + retval = krb5_data_hex_parse(&code,"30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61"); + if (retval) { + com_err("parsing padata_sequence",retval,""); + exit(1); + } + retval = decode_krb5_padata_sequence(&code,&var); + if (retval) com_err("decoding padata_sequence",retval,""); + test(ktest_equal_sequence_of_pa_data(ref,var),"pa_data\n"); + krb5_free_pa_data(test_context, var); + krb5_free_data_contents(test_context, &code); + retval = krb5_data_hex_parse(&code,"30 24 30 10 A0 03 02 01 0D A1 09 04 07 70 61 2D 64 61 74 61 30 10 A0 03 02 01 0D A1 09 04 07 70 61 2D 64 61 74 61"); + if (retval) { + com_err("parsing padata_sequence",retval,""); + exit(1); + } + retval = decode_krb5_typed_data(&code,&var); + if (retval) com_err("decoding typed_data",retval,""); + test(ktest_equal_sequence_of_pa_data(ref,var),"typed_data\n"); + krb5_free_pa_data(test_context, var); + krb5_free_data_contents(test_context, &code); + ktest_destroy_pa_data_array(&ref); + } + + /****************************************************************/ + /* decode_krb5_padata_sequence (empty) */ + { + krb5_pa_data **ref, **var; + ktest_make_sample_empty_pa_data_array(&ref); + retval = krb5_data_hex_parse(&code,"30 00"); + if (retval) { + com_err("parsing padata_sequence (empty)",retval,""); + exit(1); + } + retval = decode_krb5_padata_sequence(&code,&var); + if (retval) com_err("decoding padata_sequence (empty)",retval,""); + test(ktest_equal_sequence_of_pa_data(ref,var),"pa_data (empty)\n"); + krb5_free_pa_data(test_context, var); + krb5_free_data_contents(test_context, &code); + ktest_destroy_pa_data_array(&ref); + } + + /****************************************************************/ + /* decode_etype_info */ + { + krb5_etype_info ref, var; + + ktest_make_sample_etype_info(&ref); + retval = krb5_data_hex_parse(&code,"30 33 30 14 A0 03 02 01 00 A1 0D 04 0B 4D 6F 72 74 6F 6E 27 73 20 23 30 30 05 A0 03 02 01 01 30 14 A0 03 02 01 02 A1 0D 04 0B 4D 6F 72 74 6F 6E 27 73 20 23 32"); + if (retval) { + com_err("krb5_decode_test", retval, "while parsing etype_info"); + exit(1); + } + retval = decode_krb5_etype_info(&code,&var); + if (retval) { + com_err("krb5_decode_test", retval, "while decoding etype_info"); + } + test(ktest_equal_etype_info(ref,var),"etype_info\n"); + + ktest_destroy_etype_info(var); + ktest_destroy_etype_info_entry(ref[2]); ref[2] = 0; + ktest_destroy_etype_info_entry(ref[1]); ref[1] = 0; + krb5_free_data_contents(test_context, &code); + + retval = krb5_data_hex_parse(&code,"30 16 30 14 A0 03 02 01 00 A1 0D 04 0B 4D 6F 72 74 6F 6E 27 73 20 23 30"); + if (retval) { + com_err("krb5_decode_test", retval, + "while parsing etype_info (only one)"); + exit(1); + } + retval = decode_krb5_etype_info(&code,&var); + if (retval) { + com_err("krb5_decode_test", retval, + "while decoding etype_info (only one)"); + } + test(ktest_equal_etype_info(ref,var),"etype_info (only one)\n"); + + ktest_destroy_etype_info(var); + ktest_destroy_etype_info_entry(ref[0]); ref[0] = 0; + krb5_free_data_contents(test_context, &code); + + retval = krb5_data_hex_parse(&code,"30 00"); + if (retval) { + com_err("krb5_decode_test", retval, + "while parsing etype_info (no info)"); + exit(1); + } + retval = decode_krb5_etype_info(&code,&var); + if (retval) { + com_err("krb5_decode_test", retval, + "while decoding etype_info (no info)"); + } + test(ktest_equal_etype_info(ref,var),"etype_info (no info)\n"); + + krb5_free_data_contents(test_context, &code); + ktest_destroy_etype_info(var); + ktest_destroy_etype_info(ref); + } + + /****************************************************************/ + /* decode_etype_info2 */ + { + krb5_etype_info ref, var; + + ktest_make_sample_etype_info2(&ref); + retval = krb5_data_hex_parse(&code,"30 51 30 1E A0 03 02 01 00 A1 0D 1B 0B 4D 6F 72 74 6F 6E 27 73 20 23 30 A2 08 04 06 73 32 6B 3A 20 30 30 0F A0 03 02 01 01 A2 08 04 06 73 32 6B 3A 20 31 30 1E A0 03 02 01 02 A1 0D 1B 0B 4D 6F 72 74 6F 6E 27 73 20 23 32 A2 08 04 06 73 32 6B 3A 20 32"); + if (retval) { + com_err("krb5_decode_test", retval, "while parsing etype_info2"); + exit(1); + } + retval = decode_krb5_etype_info2(&code,&var); + if (retval) { + com_err("krb5_decode_test", retval, "while decoding etype_info2"); + } + test(ktest_equal_etype_info(ref,var),"etype_info2\n"); + + ktest_destroy_etype_info(var); + ktest_destroy_etype_info_entry(ref[2]); ref[2] = 0; + ktest_destroy_etype_info_entry(ref[1]); ref[1] = 0; + krb5_free_data_contents(test_context, &code); + + retval = krb5_data_hex_parse(&code,"30 20 30 1E A0 03 02 01 00 A1 0D 1B 0B 4D 6F 72 74 6F 6E 27 73 20 23 30 A2 08 04 06 73 32 6B 3A 20 30"); + if (retval) { + com_err("krb5_decode_test", retval, + "while parsing etype_info2 (only one)"); + exit(1); + } + retval = decode_krb5_etype_info2(&code,&var); + if (retval) { + com_err("krb5_decode_test", retval, + "while decoding etype_info2 (only one)"); + } + test(ktest_equal_etype_info(ref,var),"etype_info2 (only one)\n"); + + krb5_free_data_contents(test_context, &code); + ktest_destroy_etype_info(var); + ktest_destroy_etype_info(ref); + } + + /****************************************************************/ + /* decode_pa_enc_ts */ + { + setup(krb5_pa_enc_ts,ktest_make_sample_pa_enc_ts); + decode_run("pa_enc_ts","","30 1A A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40",decode_krb5_pa_enc_ts,ktest_equal_krb5_pa_enc_ts,krb5_free_pa_enc_ts); + ref.pausec = 0; + decode_run("pa_enc_ts (no usec)","","30 13 A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A",decode_krb5_pa_enc_ts,ktest_equal_krb5_pa_enc_ts,krb5_free_pa_enc_ts); + } + + /****************************************************************/ + /* decode_enc_data */ + { + setup(krb5_enc_data,ktest_make_sample_enc_data); + decode_run("enc_data","","30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_enc_data,ktest_equal_enc_data,krb5_ktest_free_enc_data); + ref.kvno = 0xFF000000; + decode_run("enc_data","(MSB-set kvno)","30 26 A0 03 02 01 00 A1 06 02 04 FF 00 00 00 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_enc_data,ktest_equal_enc_data,krb5_ktest_free_enc_data); + ref.kvno = 0xFFFFFFFF; + decode_run("enc_data","(kvno=-1)","30 23 A0 03 02 01 00 A1 03 02 01 FF A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_enc_data,ktest_equal_enc_data,krb5_ktest_free_enc_data); + ktest_destroy_enc_data(&ref); + } + + /****************************************************************/ + /* decode_sam_challenge_2 */ + { + setup(krb5_sam_challenge_2,ktest_make_sample_sam_challenge_2); + decode_run("sam_challenge_2","","30 22 A0 0D 30 0B 04 09 63 68 61 6C 6C 65 6E 67 65 A1 11 30 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34",decode_krb5_sam_challenge_2,ktest_equal_sam_challenge_2,krb5_free_sam_challenge_2); + ktest_empty_sam_challenge_2(&ref); + + } + + /****************************************************************/ + /* decode_sam_challenge_2_body */ + { + setup(krb5_sam_challenge_2_body,ktest_make_sample_sam_challenge_2_body); + decode_run("sam_challenge_2_body","","30 64 A0 03 02 01 2A A1 07 03 05 00 80 00 00 00 A2 0B 04 09 74 79 70 65 20 6E 61 6D 65 A4 11 04 0F 63 68 61 6C 6C 65 6E 67 65 20 6C 61 62 65 6C A5 10 04 0E 63 68 61 6C 6C 65 6E 67 65 20 69 70 73 65 A6 16 04 14 72 65 73 70 6F 6E 73 65 5F 70 72 6F 6D 70 74 20 69 70 73 65 A8 05 02 03 54 32 10 A9 03 02 01 14",decode_krb5_sam_challenge_2_body,ktest_equal_sam_challenge_2_body,krb5_free_sam_challenge_2_body); + ktest_empty_sam_challenge_2_body(&ref); + + } + + /****************************************************************/ + /* decode_pa_for_user */ + { + setup(krb5_pa_for_user,ktest_make_sample_pa_for_user); + decode_run("pa_for_user","","30 4B A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A3 0A 1B 08 6B 72 62 35 64 61 74 61",decode_krb5_pa_for_user,ktest_equal_pa_for_user,krb5_free_pa_for_user); + ktest_empty_pa_for_user(&ref); + } + + /****************************************************************/ + /* decode_pa_s4u_x509_user */ + { + setup(krb5_pa_s4u_x509_user,ktest_make_sample_pa_s4u_x509_user); + decode_run("pa_s4u_x509_user","","30 68 A0 55 30 53 A0 06 02 04 00 CA 14 9A A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 12 04 10 70 61 5F 73 34 75 5F 78 35 30 39 5F 75 73 65 72 A4 07 03 05 00 80 00 00 00 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34",decode_krb5_pa_s4u_x509_user,ktest_equal_pa_s4u_x509_user,krb5_free_pa_s4u_x509_user); + ktest_empty_pa_s4u_x509_user(&ref); + } + + /****************************************************************/ + /* decode_pa_pac_req */ + { + /* This type has no encoder and is very simple. Test two + * hand-generated encodings. */ + krb5_pa_pac_req *req1 = NULL, *req2 = NULL; + code = make_data("\x30\x05\xA0\x03\x01\x01\x00", 7); + retval = decode_krb5_pa_pac_req(&code, &req1); + if (retval) { + com_err(argv[0], retval, "while decoding PA-PAC-REQ"); + exit(1); + } + code = make_data("\x30\x05\xA0\x03\x01\x01\xFF", 7); + retval = decode_krb5_pa_pac_req(&code, &req2); + if (retval) { + com_err(argv[0], retval, "while decoding PA-PAC-REQ"); + exit(1); + } + if (req1->include_pac != 0 || req2->include_pac != 1) { + printf("ERROR: "); + error_count++; + } else { + printf("OK: "); + } + printf("pa_pac_rec\n"); + free(req1); + free(req2); + } + + /****************************************************************/ + /* decode_ad_kdcissued */ + { + setup(krb5_ad_kdcissued,ktest_make_sample_ad_kdcissued); + decode_run("ad_kdcissued","","30 65 A0 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72",decode_krb5_ad_kdcissued,ktest_equal_ad_kdcissued,krb5_free_ad_kdcissued); + ktest_empty_ad_kdcissued(&ref); + } + + /****************************************************************/ + /* decode_iakerb_header */ + { + setup(krb5_iakerb_header,ktest_make_sample_iakerb_header); + decode_run("iakerb_header","","30 18 A1 0A 04 08 6B 72 62 35 64 61 74 61 A2 0A 04 08 6B 72 62 35 64 61 74 61",decode_krb5_iakerb_header,ktest_equal_iakerb_header,krb5_free_iakerb_header); + ktest_empty_iakerb_header(&ref); + } + + /****************************************************************/ + /* decode_iakerb_finished */ + { + setup(krb5_iakerb_finished,ktest_make_sample_iakerb_finished); + decode_run("iakerb_finished","","30 11 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34",decode_krb5_iakerb_finished,ktest_equal_iakerb_finished,krb5_free_iakerb_finished); + ktest_empty_iakerb_finished(&ref); + } + + /****************************************************************/ + /* decode_fast_response */ + { + setup(krb5_fast_response,ktest_make_sample_fast_response); + decode_run("fast_response","","30 81 9F A0 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 5B 30 59 A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A3 03 02 01 2A",decode_krb5_fast_response,ktest_equal_fast_response,krb5_free_fast_response); + ktest_empty_fast_response(&ref); + } + + /****************************************************************/ + /* decode_pa_fx_fast_reply */ + { + setup(krb5_enc_data,ktest_make_sample_enc_data); + decode_run("pa_fx_fast_reply","","A0 29 30 27 A0 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_pa_fx_fast_reply,ktest_equal_enc_data,krb5_free_enc_data); + ktest_destroy_enc_data(&ref); + } + + /****************************************************************/ + /* decode_krb5_otp_tokeninfo */ + { + setup(krb5_otp_tokeninfo,ktest_make_minimal_otp_tokeninfo); + decode_run("otp_tokeninfo","(optionals NULL)","30 07 80 05 00 00 00 00 00",decode_krb5_otp_tokeninfo,ktest_equal_otp_tokeninfo,k5_free_otp_tokeninfo); + ktest_empty_otp_tokeninfo(&ref); + } + { + setup(krb5_otp_tokeninfo,ktest_make_maximal_otp_tokeninfo); + decode_run("otp_tokeninfo","","30 72 80 05 00 77 00 00 00 81 0B 45 78 61 6D 70 6C 65 63 6F 72 70 82 05 68 61 72 6B 21 83 01 0A 84 01 02 85 09 79 6F 75 72 74 6F 6B 65 6E 86 28 75 72 6E 3A 69 65 74 66 3A 70 61 72 61 6D 73 3A 78 6D 6C 3A 6E 73 3A 6B 65 79 70 72 6F 76 3A 70 73 6B 63 3A 68 6F 74 70 A7 16 30 0B 06 09 60 86 48 01 65 03 04 02 01 30 07 06 05 2B 0E 03 02 1A 88 02 03 E8",decode_krb5_otp_tokeninfo,ktest_equal_otp_tokeninfo,k5_free_otp_tokeninfo); + ktest_empty_otp_tokeninfo(&ref); + } + + /****************************************************************/ + /* decode_krb5_pa_otp_challenge */ + { + setup(krb5_pa_otp_challenge,ktest_make_minimal_pa_otp_challenge); + decode_run("pa_otp_challenge","(optionals NULL)","30 15 80 08 6D 69 6E 6E 6F 6E 63 65 A2 09 30 07 80 05 00 00 00 00 00",decode_krb5_pa_otp_challenge,ktest_equal_pa_otp_challenge,k5_free_pa_otp_challenge); + ktest_empty_pa_otp_challenge(&ref); + } + { + setup(krb5_pa_otp_challenge,ktest_make_maximal_pa_otp_challenge); + decode_run("pa_otp_challenge","","30 81 A5 80 08 6D 61 78 6E 6F 6E 63 65 81 0B 74 65 73 74 73 65 72 76 69 63 65 A2 7D 30 07 80 05 00 00 00 00 00 30 72 80 05 00 77 00 00 00 81 0B 45 78 61 6D 70 6C 65 63 6F 72 70 82 05 68 61 72 6B 21 83 01 0A 84 01 02 85 09 79 6F 75 72 74 6F 6B 65 6E 86 28 75 72 6E 3A 69 65 74 66 3A 70 61 72 61 6D 73 3A 78 6D 6C 3A 6E 73 3A 6B 65 79 70 72 6F 76 3A 70 73 6B 63 3A 68 6F 74 70 A7 16 30 0B 06 09 60 86 48 01 65 03 04 02 01 30 07 06 05 2B 0E 03 02 1A 88 02 03 E8 83 07 6B 65 79 73 61 6C 74 84 04 31 32 33 34",decode_krb5_pa_otp_challenge,ktest_equal_pa_otp_challenge,k5_free_pa_otp_challenge); + ktest_empty_pa_otp_challenge(&ref); + } + + /****************************************************************/ + /* decode_krb5_pa_otp_req */ + { + setup(krb5_pa_otp_req,ktest_make_minimal_pa_otp_req); + decode_run("pa_otp_req","(optionals NULL)","30 2C 80 05 00 00 00 00 00 A2 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_pa_otp_req,ktest_equal_pa_otp_req,k5_free_pa_otp_req); + ktest_empty_pa_otp_req(&ref); + } + { + setup(krb5_pa_otp_req,ktest_make_maximal_pa_otp_req); + decode_run("pa_otp_req","","30 81 B9 80 05 00 60 00 00 00 81 05 6E 6F 6E 63 65 A2 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A3 0B 06 09 60 86 48 01 65 03 04 02 01 84 02 03 E8 85 05 66 72 6F 67 73 86 0A 6D 79 66 69 72 73 74 70 69 6E 87 05 68 61 72 6B 21 88 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A 89 03 33 34 36 8A 01 02 8B 09 79 6F 75 72 74 6F 6B 65 6E 8C 28 75 72 6E 3A 69 65 74 66 3A 70 61 72 61 6D 73 3A 78 6D 6C 3A 6E 73 3A 6B 65 79 70 72 6F 76 3A 70 73 6B 63 3A 68 6F 74 70 8D 0B 45 78 61 6D 70 6C 65 63 6F 72 70",decode_krb5_pa_otp_req,ktest_equal_pa_otp_req,k5_free_pa_otp_req); + ktest_empty_pa_otp_req(&ref); + } + + /****************************************************************/ + /* decode_krb5_pa_otp_enc_req */ + { + setup(krb5_data,ktest_make_sample_data); + decode_run("pa_otp_enc_req","","30 0A 80 08 6B 72 62 35 64 61 74 61",decode_krb5_pa_otp_enc_req,ktest_equal_data,krb5_free_data); + ktest_empty_data(&ref); + } + + /****************************************************************/ + /* decode_krb5_kkdcp_message */ + { + setup(krb5_kkdcp_message,ktest_make_sample_kkdcp_message); + decode_run("kkdcp_message","","30 82 01 FC A0 82 01 EC 04 82 01 E8 6A 82 01 E4 30 82 01 E0 A1 03 02 01 05 A2 03 02 01 0A A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A4 82 01 AA 30 82 01 A6 A0 07 03 05 00 FE DC BA 98 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A1 0A 1B 08 6B 72 62 35 64 61 74 61",decode_krb5_kkdcp_message,ktest_equal_kkdcp_message,ktest_free_kkdcp_message); + ktest_empty_kkdcp_message(&ref); + } + + /****************************************************************/ + /* decode_krb5_cammac */ + { + setup(krb5_cammac,ktest_make_minimal_cammac); + decode_run("cammac","(optionals NULL)","30 12 A0 10 30 0E 30 0C A0 03 02 01 01 A1 05 04 03 61 64 31",decode_krb5_cammac,ktest_equal_cammac,k5_free_cammac); + ktest_empty_cammac(&ref); + } + { + setup(krb5_cammac,ktest_make_maximal_cammac); + decode_run("cammac","","30 81 F2 A0 1E 30 1C 30 0C A0 03 02 01 01 A1 05 04 03 61 64 31 30 0C A0 03 02 01 02 A1 05 04 03 61 64 32 A1 3D 30 3B A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 03 02 01 05 A2 03 02 01 10 A3 13 30 11 A0 03 02 01 01 A1 0A 04 08 63 6B 73 75 6D 6B 64 63 A2 3D 30 3B A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 03 02 01 05 A2 03 02 01 10 A3 13 30 11 A0 03 02 01 01 A1 0A 04 08 63 6B 73 75 6D 73 76 63 A3 52 30 50 30 13 A3 11 30 0F A0 03 02 01 01 A1 08 04 06 63 6B 73 75 6D 31 30 39 A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 03 02 01 05 A2 03 02 01 10 A3 11 30 0F A0 03 02 01 01 A1 08 04 06 63 6B 73 75 6D 32",decode_krb5_cammac,ktest_equal_cammac,k5_free_cammac); + ktest_empty_cammac(&ref); + } + + /****************************************************************/ + /* decode_krb5_secure_cookie */ + { + setup(krb5_secure_cookie,ktest_make_sample_secure_cookie); + decode_run("secure_cookie","","30 2C 02 04 2D F8 02 25 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61",decode_krb5_secure_cookie,ktest_equal_secure_cookie,k5_free_secure_cookie); + ktest_empty_secure_cookie(&ref); + } + + /****************************************************************/ + /* decode_krb5_spake_factor */ + { + setup(krb5_spake_factor,ktest_make_minimal_spake_factor); + decode_run("spake_factor","(optionals NULL)","30 05 A0 03 02 01 01",decode_krb5_spake_factor,ktest_equal_spake_factor,k5_free_spake_factor); + ktest_empty_spake_factor(&ref); + } + { + setup(krb5_spake_factor,ktest_make_maximal_spake_factor); + decode_run("spake_factor","","30 0E A0 03 02 01 02 A1 07 04 05 66 64 61 74 61",decode_krb5_spake_factor,ktest_equal_spake_factor,k5_free_spake_factor); + ktest_empty_spake_factor(&ref); + } + + /****************************************************************/ + /* decode_krb5_pa_spake */ + { + setup(krb5_pa_spake,ktest_make_support_pa_spake); + decode_run("pa_spake","(support)","A0 0C 30 0A A0 08 30 06 02 01 01 02 01 02",decode_krb5_pa_spake,ktest_equal_pa_spake,k5_free_pa_spake); + ktest_empty_pa_spake(&ref); + } + { + setup(krb5_pa_spake,ktest_make_challenge_pa_spake); + decode_run("pa_spake","(challenge)","A1 2D 30 2B A0 03 02 01 01 A1 09 04 07 54 20 76 61 6C 75 65 A2 19 30 17 30 05 A0 03 02 01 01 30 0E A0 03 02 01 02 A1 07 04 05 66 64 61 74 61",decode_krb5_pa_spake,ktest_equal_pa_spake,k5_free_pa_spake); + ktest_empty_pa_spake(&ref); + } + { + setup(krb5_pa_spake,ktest_make_response_pa_spake); + decode_run("pa_spake","(response)","A2 34 30 32 A0 09 04 07 53 20 76 61 6C 75 65 A1 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_pa_spake,ktest_equal_pa_spake,k5_free_pa_spake); + ktest_empty_pa_spake(&ref); + } + { + setup(krb5_pa_spake,ktest_make_encdata_pa_spake); + decode_run("pa_spake","(encdata)","A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65",decode_krb5_pa_spake,ktest_equal_pa_spake,k5_free_pa_spake); + ktest_empty_pa_spake(&ref); + } + +#ifndef DISABLE_PKINIT + + /****************************************************************/ + /* decode_krb5_pa_pk_as_req */ + { + setup(krb5_pa_pk_as_req,ktest_make_sample_pa_pk_as_req); + decode_run("krb5_pa_pk_as_req","","30 38 80 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 1E 80 08 6B 72 62 35 64 61 74 61 81 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61", + acc.decode_krb5_pa_pk_as_req, + ktest_equal_pa_pk_as_req,ktest_free_pa_pk_as_req); + ktest_empty_pa_pk_as_req(&ref); + } + + /****************************************************************/ + /* decode_krb5_pa_pk_as_rep */ + { + setup(krb5_pa_pk_as_rep,ktest_make_sample_pa_pk_as_rep_dhInfo); + decode_run("krb5_pa_pk_as_rep","(dhInfo)","A0 28 30 26 80 08 6B 72 62 35 64 61 74 61 A1 0A 04 08 6B 72 62 35 64 61 74 61 A2 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61", + acc.decode_krb5_pa_pk_as_rep, + ktest_equal_pa_pk_as_rep,ktest_free_pa_pk_as_rep); + ktest_empty_pa_pk_as_rep(&ref); + } + { + setup(krb5_pa_pk_as_rep,ktest_make_sample_pa_pk_as_rep_encKeyPack); + decode_run("krb5_pa_pk_as_rep","(encKeyPack)","81 08 6B 72 62 35 64 61 74 61", + acc.decode_krb5_pa_pk_as_rep, + ktest_equal_pa_pk_as_rep,ktest_free_pa_pk_as_rep); + ktest_empty_pa_pk_as_rep(&ref); + } + + /****************************************************************/ + /* decode_krb5_auth_pack */ + { + setup(krb5_auth_pack,ktest_make_sample_auth_pack); + decode_run("krb5_auth_pack","","30 81 85 A0 35 30 33 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 06 04 04 31 32 33 34 A4 0A 04 08 6B 72 62 35 64 61 74 61 A1 08 04 06 70 76 61 6C 75 65 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61", + acc.decode_krb5_auth_pack, + ktest_equal_auth_pack,ktest_free_auth_pack); + ktest_empty_auth_pack(&ref); + } + + /****************************************************************/ + /* decode_krb5_kdc_dh_key_info */ + { + setup(krb5_kdc_dh_key_info,ktest_make_sample_kdc_dh_key_info); + decode_run("krb5_kdc_dh_key_info","","30 25 A0 0B 03 09 00 6B 72 62 35 64 61 74 61 A1 03 02 01 2A A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A", + acc.decode_krb5_kdc_dh_key_info, + ktest_equal_kdc_dh_key_info,ktest_free_kdc_dh_key_info); + ktest_empty_kdc_dh_key_info(&ref); + } + + /****************************************************************/ + /* decode_krb5_reply_key_pack */ + { + setup(krb5_reply_key_pack,ktest_make_sample_reply_key_pack); + decode_run("krb5_reply_key_pack","","30 26 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34", + acc.decode_krb5_reply_key_pack, + ktest_equal_reply_key_pack,ktest_free_reply_key_pack); + ktest_empty_reply_key_pack(&ref); + } + + /****************************************************************/ + /* decode_krb5_principal_name */ + /* We have no encoder for this type (KerberosName from RFC 4556); the + * encoding is hand-generated. */ + { + krb5_principal ref, var; + + ktest_make_sample_principal(&ref); + decode_run("krb5_principal_name","","30 2E A0 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61", + acc.decode_krb5_principal_name,equal_principal,krb5_free_principal); + } + +#endif /* not DISABLE_PKINIT */ + +#ifdef ENABLE_LDAP + /* ldap sequence_of_keys */ + { + setup(ldap_seqof_key_data,ktest_make_sample_ldap_seqof_key_data); + decode_run("ldap_seqof_key_data","","30 81 87 A0 03 02 01 01 A1 03 02 01 01 A2 03 02 01 2A A3 03 02 01 0E A4 71 30 6F 30 23 A0 10 30 0E A0 03 02 01 00 A1 07 04 05 73 61 6C 74 30 A1 0F 30 0D A0 03 02 01 02 A1 06 04 04 6B 65 79 30 30 23 A0 10 30 0E A0 03 02 01 01 A1 07 04 05 73 61 6C 74 31 A1 0F 30 0D A0 03 02 01 02 A1 06 04 04 6B 65 79 31 30 23 A0 10 30 0E A0 03 02 01 02 A1 07 04 05 73 61 6C 74 32 A1 0F 30 0D A0 03 02 01 02 A1 06 04 04 6B 65 79 32",acc.asn1_ldap_decode_sequence_of_keys,ktest_equal_ldap_sequence_of_keys,ktest_empty_ldap_seqof_key_data); + ktest_empty_ldap_seqof_key_data(test_context, &ref); + } + +#endif + + krb5_free_context(test_context); + exit(error_count); + return(error_count); +} + + +void krb5_ktest_free_enc_data(krb5_context context, krb5_enc_data *val) +{ + if (val) { + krb5_free_data_contents(context, &(val->ciphertext)); + free(val); + } +} + +#ifndef DISABLE_PKINIT + +/* Glue function to make ktest_equal_principal_data look like what decode_run + * expects. */ +static int +equal_principal(krb5_principal *ref, krb5_principal var) +{ + return ktest_equal_principal_data(*ref, var); +} + +static void +ktest_free_auth_pack(krb5_context context, krb5_auth_pack *val) +{ + if (val) + ktest_empty_auth_pack(val); + free(val); +} + +static void +ktest_free_kdc_dh_key_info(krb5_context context, krb5_kdc_dh_key_info *val) +{ + if (val) + ktest_empty_kdc_dh_key_info(val); + free(val); +} + +static void +ktest_free_pa_pk_as_req(krb5_context context, krb5_pa_pk_as_req *val) +{ + if (val) + ktest_empty_pa_pk_as_req(val); + free(val); +} + +static void +ktest_free_pa_pk_as_rep(krb5_context context, krb5_pa_pk_as_rep *val) +{ + if (val) + ktest_empty_pa_pk_as_rep(val); + free(val); +} + +static void +ktest_free_reply_key_pack(krb5_context context, krb5_reply_key_pack *val) +{ + if (val) + ktest_empty_reply_key_pack(val); + free(val); +} + +#endif /* not DISABLE_PKINIT */ + +static void +ktest_free_kkdcp_message(krb5_context context, + krb5_kkdcp_message *val) +{ + if (val) + ktest_empty_kkdcp_message(val); + free(val); +} diff --git a/krb5-1.21.3/src/tests/asn.1/krb5_encode_test.c b/krb5-1.21.3/src/tests/asn.1/krb5_encode_test.c new file mode 100644 index 00000000..26c064e6 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/krb5_encode_test.c @@ -0,0 +1,853 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/asn.1/krb5_encode_test.c */ +/* + * Copyright (C) 1994 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "com_err.h" +#include "utility.h" + +#include "ktest.h" +#include "debug.h" + +extern int current_appl_type; + +krb5_context test_context; +int error_count = 0; +int do_trval = 0; +int first_trval = 1; +int trval2(); + +static void +encoder_print_results(krb5_data *code, char *typestring, char *description) +{ + char *code_string = NULL; + int r, rlen; + + if (do_trval) { + if (first_trval) + first_trval = 0; + else + printf("\n"); + printf("encode_krb5_%s%s:\n", typestring, description); + r = trval2(stdout, code->data, code->length, 0, &rlen); + printf("\n"); + if (rlen < 0 || (unsigned int) rlen != code->length) { + printf("Error: length mismatch: was %d, parsed %d\n", + code->length, rlen); + exit(1); + } + if (r != 0) { + printf("Error: Return from trval2 is %d.\n", r); + exit(1); + } + current_appl_type = -1; /* Reset type */ + } else { + asn1_krb5_data_unparse(code,&(code_string)); + printf("encode_krb5_%s%s: %s\n", typestring, description, + code_string); + free(code_string); + } + ktest_destroy_data(&code); +} + +static void PRS(argc, argv) + int argc; + char **argv; +{ + extern char *optarg; + int optchar; + extern int print_types, print_krb5_types, print_id_and_len, + print_constructed_length, print_skip_context, + print_skip_tagnum, print_context_shortcut; + + while ((optchar = getopt(argc, argv, "tp:")) != -1) { + switch(optchar) { + case 't': + do_trval = 1; + break; + case 'p': + sample_principal_name = optarg; + break; + case '?': + default: + fprintf(stderr, "Usage: %s [-t] [-p principal]\n", + argv[0]); + exit(1); + } + } + print_types = 1; + print_krb5_types = 1; + print_id_and_len = 0; + print_constructed_length = 0; + print_skip_context = 1; + print_skip_tagnum = 1; + print_context_shortcut = 1; +} + +int +main(argc, argv) + int argc; + char **argv; +{ + krb5_data *code; + krb5_error_code retval; + + PRS(argc, argv); + + retval = krb5_init_context(&test_context); + if (retval) { + com_err(argv[0], retval, "while initializing krb5"); + exit(1); + } + init_access(argv[0]); + +#define encode_run(value,typestring,description,encoder) \ + retval = encoder(&(value),&(code)); \ + if (retval) { \ + com_err("krb5_encode_test", retval,"while encoding %s", typestring); \ + exit(1); \ + } \ + encoder_print_results(code, typestring, description); + + /****************************************************************/ + /* encode_krb5_authenticator */ + { + krb5_authenticator authent; + ktest_make_sample_authenticator(&authent); + + encode_run(authent, "authenticator", "", encode_krb5_authenticator); + + ktest_destroy_checksum(&(authent.checksum)); + ktest_destroy_keyblock(&(authent.subkey)); + authent.seq_number = 0; + ktest_empty_authorization_data(authent.authorization_data); + encode_run(authent, "authenticator", "(optionals empty)", + encode_krb5_authenticator); + + ktest_destroy_authorization_data(&(authent.authorization_data)); + encode_run(authent, "authenticator", "(optionals NULL)", + encode_krb5_authenticator); + ktest_empty_authenticator(&authent); + } + + /****************************************************************/ + /* encode_krb5_ticket */ + { + krb5_ticket tkt; + ktest_make_sample_ticket(&tkt); + encode_run(tkt, "ticket", "", encode_krb5_ticket); + ktest_empty_ticket(&tkt); + } + + /****************************************************************/ + /* encode_krb5_encryption_key */ + { + krb5_keyblock keyblk; + ktest_make_sample_keyblock(&keyblk); + current_appl_type = 1005; + encode_run(keyblk, "keyblock", "", encode_krb5_encryption_key); + ktest_empty_keyblock(&keyblk); + } + + /****************************************************************/ + /* encode_krb5_enc_tkt_part */ + { + krb5_ticket tkt; + memset(&tkt, 0, sizeof(krb5_ticket)); + tkt.enc_part2 = ealloc(sizeof(krb5_enc_tkt_part)); + ktest_make_sample_enc_tkt_part(tkt.enc_part2); + + encode_run(*tkt.enc_part2, "enc_tkt_part", "", + encode_krb5_enc_tkt_part); + + tkt.enc_part2->times.starttime = 0; + tkt.enc_part2->times.renew_till = 0; + ktest_destroy_address(&(tkt.enc_part2->caddrs[1])); + ktest_destroy_address(&(tkt.enc_part2->caddrs[0])); + ktest_destroy_authdata(&(tkt.enc_part2->authorization_data[1])); + ktest_destroy_authdata(&(tkt.enc_part2->authorization_data[0])); + + /* ISODE version fails on the empty caddrs field */ + ktest_destroy_addresses(&(tkt.enc_part2->caddrs)); + ktest_destroy_authorization_data(&(tkt.enc_part2->authorization_data)); + + encode_run(*tkt.enc_part2, "enc_tkt_part", "(optionals NULL)", + encode_krb5_enc_tkt_part); + ktest_empty_ticket(&tkt); + } + + /****************************************************************/ + /* encode_krb5_enc_kdc_rep_part */ + { + krb5_kdc_rep kdcr; + + memset(&kdcr, 0, sizeof(kdcr)); + + kdcr.enc_part2 = ealloc(sizeof(krb5_enc_kdc_rep_part)); + ktest_make_sample_enc_kdc_rep_part(kdcr.enc_part2); + + encode_run(*kdcr.enc_part2, "enc_kdc_rep_part", "", + encode_krb5_enc_kdc_rep_part); + + kdcr.enc_part2->key_exp = 0; + kdcr.enc_part2->times.starttime = 0; + kdcr.enc_part2->flags &= ~TKT_FLG_RENEWABLE; + ktest_destroy_addresses(&(kdcr.enc_part2->caddrs)); + + encode_run(*kdcr.enc_part2, "enc_kdc_rep_part", "(optionals NULL)", + encode_krb5_enc_kdc_rep_part); + + ktest_empty_kdc_rep(&kdcr); + } + + /****************************************************************/ + /* encode_krb5_as_rep */ + { + krb5_kdc_rep kdcr; + ktest_make_sample_kdc_rep(&kdcr); + +/* kdcr.msg_type = KRB5_TGS_REP; + test(encode_krb5_as_rep(&kdcr,&code) == KRB5_BADMSGTYPE, + "encode_krb5_as_rep type check\n"); + ktest_destroy_data(&code);*/ + + kdcr.msg_type = KRB5_AS_REP; + encode_run(kdcr, "as_rep", "", encode_krb5_as_rep); + + ktest_destroy_pa_data_array(&(kdcr.padata)); + encode_run(kdcr, "as_rep", "(optionals NULL)", encode_krb5_as_rep); + + ktest_empty_kdc_rep(&kdcr); + + } + + /****************************************************************/ + /* encode_krb5_tgs_rep */ + { + krb5_kdc_rep kdcr; + ktest_make_sample_kdc_rep(&kdcr); + +/* kdcr.msg_type = KRB5_AS_REP; + test(encode_krb5_tgs_rep(&kdcr,&code) == KRB5_BADMSGTYPE, + "encode_krb5_tgs_rep type check\n");*/ + + kdcr.msg_type = KRB5_TGS_REP; + encode_run(kdcr, "tgs_rep", "", encode_krb5_tgs_rep); + + ktest_destroy_pa_data_array(&(kdcr.padata)); + encode_run(kdcr, "tgs_rep", "(optionals NULL)", encode_krb5_tgs_rep); + + ktest_empty_kdc_rep(&kdcr); + + } + + /****************************************************************/ + /* encode_krb5_ap_req */ + { + krb5_ap_req apreq; + ktest_make_sample_ap_req(&apreq); + encode_run(apreq, "ap_req", "", encode_krb5_ap_req); + ktest_empty_ap_req(&apreq); + } + + /****************************************************************/ + /* encode_krb5_ap_rep */ + { + krb5_ap_rep aprep; + ktest_make_sample_ap_rep(&aprep); + encode_run(aprep, "ap_rep", "", encode_krb5_ap_rep); + ktest_empty_ap_rep(&aprep); + } + + /****************************************************************/ + /* encode_krb5_ap_rep_enc_part */ + { + krb5_ap_rep_enc_part apenc; + ktest_make_sample_ap_rep_enc_part(&apenc); + encode_run(apenc, "ap_rep_enc_part", "", encode_krb5_ap_rep_enc_part); + + ktest_destroy_keyblock(&(apenc.subkey)); + apenc.seq_number = 0; + encode_run(apenc, "ap_rep_enc_part", "(optionals NULL)", + encode_krb5_ap_rep_enc_part); + ktest_empty_ap_rep_enc_part(&apenc); + } + + /****************************************************************/ + /* encode_krb5_as_req */ + { + krb5_kdc_req asreq; + ktest_make_sample_kdc_req(&asreq); + asreq.msg_type = KRB5_AS_REQ; + asreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + encode_run(asreq, "as_req", "", encode_krb5_as_req); + + ktest_destroy_pa_data_array(&(asreq.padata)); + ktest_destroy_principal(&(asreq.client)); +#ifndef ISODE_SUCKS + ktest_destroy_principal(&(asreq.server)); +#endif + asreq.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY; + asreq.from = 0; + asreq.rtime = 0; + ktest_destroy_addresses(&(asreq.addresses)); + ktest_destroy_enc_data(&(asreq.authorization_data)); + encode_run(asreq, "as_req", "(optionals NULL except second_ticket)", + encode_krb5_as_req); + ktest_destroy_sequence_of_ticket(&(asreq.second_ticket)); +#ifndef ISODE_SUCKS + ktest_make_sample_principal(&(asreq.server)); +#endif + asreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + encode_run(asreq, "as_req", "(optionals NULL except server)", + encode_krb5_as_req); + ktest_empty_kdc_req(&asreq); + } + + /****************************************************************/ + /* encode_krb5_tgs_req */ + { + krb5_kdc_req tgsreq; + ktest_make_sample_kdc_req(&tgsreq); + tgsreq.msg_type = KRB5_TGS_REQ; + tgsreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + encode_run(tgsreq, "tgs_req", "", encode_krb5_tgs_req); + + ktest_destroy_pa_data_array(&(tgsreq.padata)); + ktest_destroy_principal(&(tgsreq.client)); +#ifndef ISODE_SUCKS + ktest_destroy_principal(&(tgsreq.server)); +#endif + tgsreq.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY; + tgsreq.from = 0; + tgsreq.rtime = 0; + ktest_destroy_addresses(&(tgsreq.addresses)); + ktest_destroy_enc_data(&(tgsreq.authorization_data)); + encode_run(tgsreq, "tgs_req", "(optionals NULL except second_ticket)", + encode_krb5_tgs_req); + + ktest_destroy_sequence_of_ticket(&(tgsreq.second_ticket)); +#ifndef ISODE_SUCKS + ktest_make_sample_principal(&(tgsreq.server)); +#endif + tgsreq.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + encode_run(tgsreq, "tgs_req", "(optionals NULL except server)", + encode_krb5_tgs_req); + + ktest_empty_kdc_req(&tgsreq); + } + + /****************************************************************/ + /* encode_krb5_kdc_req_body */ + { + krb5_kdc_req kdcrb; + memset(&kdcrb, 0, sizeof(kdcrb)); + ktest_make_sample_kdc_req_body(&kdcrb); + kdcrb.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + current_appl_type = 1007; /* Force interpretation as kdc-req-body */ + encode_run(kdcrb, "kdc_req_body", "", encode_krb5_kdc_req_body); + + ktest_destroy_principal(&(kdcrb.client)); +#ifndef ISODE_SUCKS + ktest_destroy_principal(&(kdcrb.server)); +#endif + kdcrb.kdc_options |= KDC_OPT_ENC_TKT_IN_SKEY; + kdcrb.from = 0; + kdcrb.rtime = 0; + ktest_destroy_addresses(&(kdcrb.addresses)); + ktest_destroy_enc_data(&(kdcrb.authorization_data)); + current_appl_type = 1007; /* Force interpretation as kdc-req-body */ + encode_run(kdcrb, "kdc_req_body", + "(optionals NULL except second_ticket)", + encode_krb5_kdc_req_body); + + ktest_destroy_sequence_of_ticket(&(kdcrb.second_ticket)); +#ifndef ISODE_SUCKS + ktest_make_sample_principal(&(kdcrb.server)); +#endif + kdcrb.kdc_options &= ~KDC_OPT_ENC_TKT_IN_SKEY; + current_appl_type = 1007; /* Force interpretation as kdc-req-body */ + encode_run(kdcrb, "kdc_req_body", "(optionals NULL except server)", + encode_krb5_kdc_req_body); + + ktest_empty_kdc_req(&kdcrb); + } + + /****************************************************************/ + /* encode_krb5_safe */ + { + krb5_safe s; + ktest_make_sample_safe(&s); + encode_run(s, "safe", "", encode_krb5_safe); + + s.timestamp = 0; + /* s.usec should be opted out by the timestamp */ + s.seq_number = 0; + ktest_destroy_address(&(s.r_address)); + encode_run(s, "safe", "(optionals NULL)", encode_krb5_safe); + + ktest_empty_safe(&s); + } + + /****************************************************************/ + /* encode_krb5_priv */ + { + krb5_priv p; + ktest_make_sample_priv(&p); + encode_run(p, "priv", "", encode_krb5_priv); + ktest_empty_priv(&p); + } + + /****************************************************************/ + /* encode_krb5_enc_priv_part */ + { + krb5_priv_enc_part ep; + ktest_make_sample_priv_enc_part(&ep); + encode_run(ep, "enc_priv_part", "", encode_krb5_enc_priv_part); + + ep.timestamp = 0; + /* ep.usec should be opted out along with timestamp */ + ep.seq_number = 0; + ktest_destroy_address(&(ep.r_address)); + encode_run(ep, "enc_priv_part", "(optionals NULL)", + encode_krb5_enc_priv_part); + + ktest_empty_priv_enc_part(&ep); + } + + /****************************************************************/ + /* encode_krb5_cred */ + { + krb5_cred c; + ktest_make_sample_cred(&c); + encode_run(c, "cred", "", encode_krb5_cred); + ktest_empty_cred(&c); + } + + /****************************************************************/ + /* encode_krb5_enc_cred_part */ + { + krb5_cred_enc_part cep; + ktest_make_sample_cred_enc_part(&cep); + encode_run(cep, "enc_cred_part", "", encode_krb5_enc_cred_part); + + ktest_destroy_principal(&(cep.ticket_info[0]->client)); + ktest_destroy_principal(&(cep.ticket_info[0]->server)); + cep.ticket_info[0]->flags = 0; + cep.ticket_info[0]->times.authtime = 0; + cep.ticket_info[0]->times.starttime = 0; + cep.ticket_info[0]->times.endtime = 0; + cep.ticket_info[0]->times.renew_till = 0; + ktest_destroy_addresses(&(cep.ticket_info[0]->caddrs)); + cep.nonce = 0; + cep.timestamp = 0; + ktest_destroy_address(&(cep.s_address)); + ktest_destroy_address(&(cep.r_address)); + encode_run(cep, "enc_cred_part", "(optionals NULL)", + encode_krb5_enc_cred_part); + + ktest_empty_cred_enc_part(&cep); + } + + /****************************************************************/ + /* encode_krb5_error */ + { + krb5_error kerr; + ktest_make_sample_error(&kerr); + encode_run(kerr, "error", "", encode_krb5_error); + + kerr.ctime = 0; + ktest_destroy_principal(&(kerr.client)); + ktest_empty_data(&(kerr.text)); + ktest_empty_data(&(kerr.e_data)); + encode_run(kerr, "error", "(optionals NULL)", encode_krb5_error); + + ktest_empty_error(&kerr); + } + + /****************************************************************/ + /* encode_krb5_authdata */ + { + krb5_authdata **ad; + ktest_make_sample_authorization_data(&ad); + + retval = encode_krb5_authdata(ad,&(code)); + if (retval) { + com_err("encoding authorization_data",retval,""); + exit(1); + } + current_appl_type = 1004; /* Force type to be authdata */ + encoder_print_results(code, "authorization_data", ""); + + ktest_destroy_authorization_data(&ad); + } + + /****************************************************************/ + /* encode_padata_sequence and encode_krb5_typed_data */ + { + krb5_pa_data **pa; + + ktest_make_sample_pa_data_array(&pa); + encode_run(*pa, "padata_sequence", "", encode_krb5_padata_sequence); + encode_run(*pa, "typed_data", "", encode_krb5_typed_data); + ktest_destroy_pa_data_array(&pa); + + ktest_make_sample_empty_pa_data_array(&pa); + encode_run(*pa, "padata_sequence", "(empty)", + encode_krb5_padata_sequence); + ktest_destroy_pa_data_array(&pa); + } + + /****************************************************************/ + /* encode_etype_info */ + { + krb5_etype_info_entry **info; + + ktest_make_sample_etype_info(&info); + encode_run(*info, "etype_info", "", encode_krb5_etype_info); + + ktest_destroy_etype_info_entry(info[2]); info[2] = 0; + ktest_destroy_etype_info_entry(info[1]); info[1] = 0; + encode_run(*info, "etype_info", "(only 1)", encode_krb5_etype_info); + + ktest_destroy_etype_info_entry(info[0]); info[0] = 0; + encode_run(*info, "etype_info", "(no info)", encode_krb5_etype_info); + + ktest_destroy_etype_info(info); + } + + /* encode_etype_info2 */ + { + krb5_etype_info_entry **info; + + ktest_make_sample_etype_info2(&info); + encode_run(*info, "etype_info2", "", encode_krb5_etype_info2); + + ktest_destroy_etype_info_entry(info[2]); info[2] = 0; + ktest_destroy_etype_info_entry(info[1]); info[1] = 0; + encode_run(*info, "etype_info2", "(only 1)", encode_krb5_etype_info2); + + /* etype_info2 sequences aren't allowed to be empty. */ + + ktest_destroy_etype_info(info); + } + + /****************************************************************/ + /* encode_pa_enc_ts */ + { + krb5_pa_enc_ts pa_enc; + ktest_make_sample_pa_enc_ts(&pa_enc); + encode_run(pa_enc, "pa_enc_ts", "", encode_krb5_pa_enc_ts); + pa_enc.pausec = 0; + encode_run(pa_enc, "pa_enc_ts (no usec)", "", encode_krb5_pa_enc_ts); + } + + /****************************************************************/ + /* encode_enc_data */ + { + krb5_enc_data enc_data; + ktest_make_sample_enc_data(&enc_data); + current_appl_type = 1001; + encode_run(enc_data, "enc_data", "", encode_krb5_enc_data); + enc_data.kvno = 0xFF000000; + current_appl_type = 1001; + encode_run(enc_data, "enc_data", "(MSB-set kvno)", + encode_krb5_enc_data); + enc_data.kvno = 0xFFFFFFFF; + current_appl_type = 1001; + encode_run(enc_data, "enc_data", "(kvno=-1)", encode_krb5_enc_data); + ktest_destroy_enc_data(&enc_data); + } + /****************************************************************/ + /* encode_krb5_sam_challenge_2 */ + { + krb5_sam_challenge_2 sam_ch2; + ktest_make_sample_sam_challenge_2(&sam_ch2); + encode_run(sam_ch2, "sam_challenge_2", "", + encode_krb5_sam_challenge_2); + ktest_empty_sam_challenge_2(&sam_ch2); + } + /****************************************************************/ + /* encode_krb5_sam_challenge_2_body */ + { + krb5_sam_challenge_2_body body; + ktest_make_sample_sam_challenge_2_body(&body); + encode_run(body, "sam_challenge_2_body", "", + encode_krb5_sam_challenge_2_body); + ktest_empty_sam_challenge_2_body(&body); + } + /****************************************************************/ + /* encode_krb5_sam_response_2 */ + { + krb5_sam_response_2 sam_ch2; + ktest_make_sample_sam_response_2(&sam_ch2); + encode_run(sam_ch2, "sam_response_2", "", encode_krb5_sam_response_2); + ktest_empty_sam_response_2(&sam_ch2); + } + /****************************************************************/ + /* encode_krb5_sam_response_enc_2 */ + { + krb5_enc_sam_response_enc_2 sam_ch2; + ktest_make_sample_enc_sam_response_enc_2(&sam_ch2); + encode_run(sam_ch2, "enc_sam_response_enc_2", "", + encode_krb5_enc_sam_response_enc_2); + ktest_empty_enc_sam_response_enc_2(&sam_ch2); + } + /****************************************************************/ + /* encode_krb5_pa_for_user */ + { + krb5_pa_for_user s4u; + ktest_make_sample_pa_for_user(&s4u); + encode_run(s4u, "pa_for_user", "", encode_krb5_pa_for_user); + ktest_empty_pa_for_user(&s4u); + } + /****************************************************************/ + /* encode_krb5_pa_s4u_x509_user */ + { + krb5_pa_s4u_x509_user s4u; + ktest_make_sample_pa_s4u_x509_user(&s4u); + encode_run(s4u, "pa_s4u_x509_user", "", encode_krb5_pa_s4u_x509_user); + ktest_empty_pa_s4u_x509_user(&s4u); + } + /****************************************************************/ + /* encode_krb5_ad_kdcissued */ + { + krb5_ad_kdcissued kdci; + ktest_make_sample_ad_kdcissued(&kdci); + encode_run(kdci, "ad_kdcissued", "", encode_krb5_ad_kdcissued); + ktest_empty_ad_kdcissued(&kdci); + } + /****************************************************************/ + /* encode_krb5_iakerb_header */ + { + krb5_iakerb_header ih; + ktest_make_sample_iakerb_header(&ih); + encode_run(ih, "iakerb_header", "", encode_krb5_iakerb_header); + ktest_empty_iakerb_header(&ih); + } + /****************************************************************/ + /* encode_krb5_iakerb_finished */ + { + krb5_iakerb_finished ih; + ktest_make_sample_iakerb_finished(&ih); + encode_run(ih, "iakerb_finished", "", encode_krb5_iakerb_finished); + ktest_empty_iakerb_finished(&ih); + } + /****************************************************************/ + /* encode_krb5_fast_response */ + { + krb5_fast_response fr; + ktest_make_sample_fast_response(&fr); + encode_run(fr, "fast_response", "", encode_krb5_fast_response); + ktest_empty_fast_response(&fr); + } + /****************************************************************/ + /* encode_krb5_pa_fx_fast_reply */ + { + krb5_enc_data enc_data; + ktest_make_sample_enc_data(&enc_data); + encode_run(enc_data, "pa_fx_fast_reply", "", + encode_krb5_pa_fx_fast_reply); + ktest_destroy_enc_data(&enc_data); + } + /****************************************************************/ + /* encode_krb5_otp_tokeninfo */ + { + krb5_otp_tokeninfo ti; + ktest_make_minimal_otp_tokeninfo(&ti); + encode_run(ti, "otp_tokeninfo", "(optionals NULL)", + encode_krb5_otp_tokeninfo); + ktest_empty_otp_tokeninfo(&ti); + ktest_make_maximal_otp_tokeninfo(&ti); + encode_run(ti, "otp_tokeninfo", "", encode_krb5_otp_tokeninfo); + ktest_empty_otp_tokeninfo(&ti); + } + /****************************************************************/ + /* encode_krb5_pa_otp_challenge */ + { + krb5_pa_otp_challenge ch; + ktest_make_minimal_pa_otp_challenge(&ch); + encode_run(ch, "pa_otp_challenge", "(optionals NULL)", + encode_krb5_pa_otp_challenge); + ktest_empty_pa_otp_challenge(&ch); + ktest_make_maximal_pa_otp_challenge(&ch); + encode_run(ch, "pa_otp_challenge", "", encode_krb5_pa_otp_challenge); + ktest_empty_pa_otp_challenge(&ch); + } + /****************************************************************/ + /* encode_krb5_pa_otp_req */ + { + krb5_pa_otp_req req; + ktest_make_minimal_pa_otp_req(&req); + encode_run(req, "pa_otp_req", "(optionals NULL)", + encode_krb5_pa_otp_req); + ktest_empty_pa_otp_req(&req); + ktest_make_maximal_pa_otp_req(&req); + encode_run(req, "pa_otp_req", "", encode_krb5_pa_otp_req); + ktest_empty_pa_otp_req(&req); + } + /****************************************************************/ + /* encode_krb5_pa_otp_enc_request */ + { + krb5_data d; + ktest_make_sample_data(&d); + encode_run(d, "pa_otp_enc_req", "", encode_krb5_pa_otp_enc_req); + ktest_empty_data(&d); + } + /****************************************************************/ + /* encode_krb5_kkdcp_message */ + { + krb5_kkdcp_message info; + ktest_make_sample_kkdcp_message(&info); + encode_run(info, "kkdcp_message", "", encode_krb5_kkdcp_message); + ktest_empty_kkdcp_message(&info); + } + /* encode_krb5_cammac */ + { + krb5_cammac req; + ktest_make_minimal_cammac(&req); + encode_run(req, "cammac", "(optionals NULL)", encode_krb5_cammac); + ktest_empty_cammac(&req); + ktest_make_maximal_cammac(&req); + encode_run(req, "cammac", "", encode_krb5_cammac); + ktest_empty_cammac(&req); + } + /****************************************************************/ + /* encode_krb5_secure_cookie */ + { + krb5_secure_cookie cookie; + ktest_make_sample_secure_cookie(&cookie); + encode_run(cookie, "secure_cookie", "", encode_krb5_secure_cookie); + ktest_empty_secure_cookie(&cookie); + } + /****************************************************************/ + /* encode_krb5_spake_factor */ + { + krb5_spake_factor factor; + ktest_make_minimal_spake_factor(&factor); + encode_run(factor, "spake_factor", "(optionals NULL)", + encode_krb5_spake_factor); + ktest_empty_spake_factor(&factor); + ktest_make_maximal_spake_factor(&factor); + encode_run(factor, "spake_factor", "", encode_krb5_spake_factor); + ktest_empty_spake_factor(&factor); + } + /****************************************************************/ + /* encode_krb5_pa_spake */ + { + krb5_pa_spake pa_spake; + ktest_make_support_pa_spake(&pa_spake); + encode_run(pa_spake, "pa_spake", "(support)", encode_krb5_pa_spake); + ktest_empty_pa_spake(&pa_spake); + ktest_make_challenge_pa_spake(&pa_spake); + encode_run(pa_spake, "pa_spake", "(challenge)", encode_krb5_pa_spake); + ktest_empty_pa_spake(&pa_spake); + ktest_make_response_pa_spake(&pa_spake); + encode_run(pa_spake, "pa_spake", "(response)", encode_krb5_pa_spake); + ktest_empty_pa_spake(&pa_spake); + ktest_make_encdata_pa_spake(&pa_spake); + encode_run(pa_spake, "pa_spake", "(encdata)", encode_krb5_pa_spake); + ktest_empty_pa_spake(&pa_spake); + } +#ifndef DISABLE_PKINIT + /****************************************************************/ + /* encode_krb5_pa_pk_as_req */ + { + krb5_pa_pk_as_req req; + ktest_make_sample_pa_pk_as_req(&req); + encode_run(req, "pa_pk_as_req", "", acc.encode_krb5_pa_pk_as_req); + ktest_empty_pa_pk_as_req(&req); + } + /****************************************************************/ + /* encode_krb5_pa_pk_as_rep */ + { + krb5_pa_pk_as_rep rep; + ktest_make_sample_pa_pk_as_rep_dhInfo(&rep); + encode_run(rep, "pa_pk_as_rep", "(dhInfo)", + acc.encode_krb5_pa_pk_as_rep); + ktest_empty_pa_pk_as_rep(&rep); + ktest_make_sample_pa_pk_as_rep_encKeyPack(&rep); + encode_run(rep, "pa_pk_as_rep", "(encKeyPack)", + acc.encode_krb5_pa_pk_as_rep); + ktest_empty_pa_pk_as_rep(&rep); + } + /****************************************************************/ + /* encode_krb5_auth_pack */ + { + krb5_auth_pack pack; + ktest_make_sample_auth_pack(&pack); + encode_run(pack, "auth_pack", "", acc.encode_krb5_auth_pack); + ktest_empty_auth_pack(&pack); + } + /****************************************************************/ + /* encode_krb5_kdc_dh_key_info */ + { + krb5_kdc_dh_key_info ki; + ktest_make_sample_kdc_dh_key_info(&ki); + encode_run(ki, "kdc_dh_key_info", "", acc.encode_krb5_kdc_dh_key_info); + ktest_empty_kdc_dh_key_info(&ki); + } + /****************************************************************/ + /* encode_krb5_reply_key_pack */ + { + krb5_reply_key_pack pack; + ktest_make_sample_reply_key_pack(&pack); + encode_run(pack, "reply_key_pack", "", acc.encode_krb5_reply_key_pack); + ktest_empty_reply_key_pack(&pack); + } + /****************************************************************/ + /* encode_krb5_sp80056a_other_info */ + { + krb5_sp80056a_other_info info; + ktest_make_sample_sp80056a_other_info(&info); + encode_run(info, "sp80056a_other_info", "", + encode_krb5_sp80056a_other_info); + ktest_empty_sp80056a_other_info(&info); + } + /****************************************************************/ + /* encode_krb5_pkinit_supp_pub_info */ + { + krb5_pkinit_supp_pub_info info; + ktest_make_sample_pkinit_supp_pub_info(&info); + encode_run(info, "pkinit_supp_pub_info", "", + encode_krb5_pkinit_supp_pub_info); + ktest_empty_pkinit_supp_pub_info(&info); + } +#endif /* not DISABLE_PKINIT */ +#ifdef ENABLE_LDAP + { + ldap_seqof_key_data skd; + + ktest_make_sample_ldap_seqof_key_data(&skd); + encode_run(skd, "ldap_seqof_key_data", "", + acc.asn1_ldap_encode_sequence_of_keys); + ktest_empty_ldap_seqof_key_data(test_context, &skd); + } +#endif + + krb5_free_context(test_context); + exit(error_count); + return(error_count); +} diff --git a/krb5-1.21.3/src/tests/asn.1/ktest.c b/krb5-1.21.3/src/tests/asn.1/ktest.c new file mode 100644 index 00000000..d37e4fa7 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/ktest.c @@ -0,0 +1,1799 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/asn.1/ktest.c */ +/* + * Copyright (C) 1994 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ktest.h" +#include "utility.h" +#include + +char *sample_principal_name = "hftsai/extra@ATHENA.MIT.EDU"; + +void +ktest_make_sample_authenticator(krb5_authenticator *a) +{ + ktest_make_sample_principal(&a->client); + a->checksum = ealloc(sizeof(krb5_checksum)); + ktest_make_sample_checksum(a->checksum); + a->cusec = SAMPLE_USEC; + a->ctime = SAMPLE_TIME; + a->subkey = ealloc(sizeof(krb5_keyblock)); + ktest_make_sample_keyblock(a->subkey); + a->seq_number = SAMPLE_SEQ_NUMBER; + ktest_make_sample_authorization_data(&a->authorization_data); +} + +void +ktest_make_sample_principal(krb5_principal *p) +{ + if (krb5_parse_name(test_context, sample_principal_name, p)) + abort(); +} + +void +ktest_make_sample_checksum(krb5_checksum *cs) +{ + cs->checksum_type = 1; + cs->length = 4; + cs->contents = ealloc(4); + memcpy(cs->contents,"1234",4); +} + +void +ktest_make_sample_keyblock(krb5_keyblock *kb) +{ + kb->magic = KV5M_KEYBLOCK; + kb->enctype = 1; + kb->length = 8; + kb->contents = ealloc(8); + memcpy(kb->contents,"12345678",8); +} + +void +ktest_make_sample_ticket(krb5_ticket *tkt) +{ + ktest_make_sample_principal(&tkt->server); + ktest_make_sample_enc_data(&tkt->enc_part); + tkt->enc_part2 = NULL; +} + +void +ktest_make_sample_enc_data(krb5_enc_data *ed) +{ + ed->kvno = 5; + ed->enctype = 0; + krb5_data_parse(&ed->ciphertext, "krbASN.1 test message"); +} + +void +ktest_make_sample_enc_tkt_part(krb5_enc_tkt_part *etp) +{ + etp->flags = SAMPLE_FLAGS; + etp->session = ealloc(sizeof(krb5_keyblock)); + ktest_make_sample_keyblock(etp->session); + ktest_make_sample_principal(&etp->client); + ktest_make_sample_transited(&etp->transited); + ktest_make_sample_ticket_times(&etp->times); + ktest_make_sample_addresses(&etp->caddrs); + ktest_make_sample_authorization_data(&etp->authorization_data); +} + +void +ktest_make_sample_addresses(krb5_address ***caddrs) +{ + int i; + + *caddrs = ealloc(3 * sizeof(krb5_address *)); + for (i = 0; i < 2; i++) { + (*caddrs)[i] = ealloc(sizeof(krb5_address)); + ktest_make_sample_address((*caddrs)[i]); + } + (*caddrs)[2] = NULL; +} + +void +ktest_make_sample_authorization_data(krb5_authdata ***ad) +{ + int i; + + *ad = ealloc(3 * sizeof(krb5_authdata *)); + for (i = 0; i <= 1; i++) { + (*ad)[i] = ealloc(sizeof(krb5_authdata)); + ktest_make_sample_authdata((*ad)[i]); + } + (*ad)[2] = NULL; +} + +void +ktest_make_sample_transited(krb5_transited *t) +{ + t->tr_type = 1; + krb5_data_parse(&t->tr_contents, "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS."); +} + +void +ktest_make_sample_ticket_times(krb5_ticket_times *tt) +{ + tt->authtime = SAMPLE_TIME; + tt->starttime = SAMPLE_TIME; + tt->endtime = SAMPLE_TIME; + tt->renew_till = SAMPLE_TIME; +} + +void +ktest_make_sample_address(krb5_address *a) +{ + a->addrtype = ADDRTYPE_INET; + a->length = 4; + a->contents = ealloc(4 * sizeof(krb5_octet)); + a->contents[0] = 18; + a->contents[1] = 208; + a->contents[2] = 0; + a->contents[3] = 35; +} + +void +ktest_make_sample_authdata(krb5_authdata *ad) +{ + ad->ad_type = 1; + ad->length = 6; + ad->contents = ealloc(6 * sizeof(krb5_octet)); + memcpy(ad->contents, "foobar", 6); +} + +void +ktest_make_sample_enc_kdc_rep_part(krb5_enc_kdc_rep_part *ekr) +{ + ekr->session = ealloc(sizeof(krb5_keyblock)); + ktest_make_sample_keyblock(ekr->session); + ktest_make_sample_last_req(&ekr->last_req); + ekr->nonce = SAMPLE_NONCE; + ekr->key_exp = SAMPLE_TIME; + ekr->flags = SAMPLE_FLAGS; + ekr->times.authtime = SAMPLE_TIME; + ekr->times.starttime = SAMPLE_TIME; + ekr->times.endtime = SAMPLE_TIME; + ekr->times.renew_till = SAMPLE_TIME; + ktest_make_sample_principal(&ekr->server); + ktest_make_sample_addresses(&ekr->caddrs); +} + +void +ktest_make_sample_last_req(krb5_last_req_entry ***lr) +{ + int i; + + *lr = ealloc(3 * sizeof(krb5_last_req_entry *)); + for (i = 0; i <= 1; i++) + ktest_make_sample_last_req_entry(&(*lr)[i]); + (*lr)[2] = NULL; +} + +void +ktest_make_sample_last_req_entry(krb5_last_req_entry **lre) +{ + *lre = ealloc(sizeof(krb5_last_req_entry)); + (*lre)->lr_type = -5; + (*lre)->value = SAMPLE_TIME; +} + +void +ktest_make_sample_kdc_rep(krb5_kdc_rep *kdcr) +{ + ktest_make_sample_pa_data_array(&kdcr->padata); + ktest_make_sample_principal(&kdcr->client); + kdcr->ticket = ealloc(sizeof(krb5_ticket)); + ktest_make_sample_ticket(kdcr->ticket); + ktest_make_sample_enc_data(&kdcr->enc_part); + kdcr->enc_part2 = NULL; +} + +void +ktest_make_sample_pa_data_array(krb5_pa_data ***pad) +{ + int i; + + *pad = ealloc(3 * sizeof(krb5_pa_data *)); + for (i = 0; i <= 1; i++) { + (*pad)[i] = ealloc(sizeof(krb5_pa_data)); + ktest_make_sample_pa_data((*pad)[i]); + } + (*pad)[2] = NULL; +} + +void +ktest_make_sample_empty_pa_data_array(krb5_pa_data ***pad) +{ + *pad = ealloc(sizeof(krb5_pa_data *)); + (*pad)[0] = NULL; +} + +void +ktest_make_sample_pa_data(krb5_pa_data *pad) +{ + pad->pa_type = 13; + pad->length = 7; + pad->contents = ealloc(7); + memcpy(pad->contents, "pa-data", 7); +} + +void +ktest_make_sample_ap_req(krb5_ap_req *ar) +{ + ar->ap_options = SAMPLE_FLAGS; + ar->ticket = ealloc(sizeof(krb5_ticket)); + ktest_make_sample_ticket(ar->ticket); + ktest_make_sample_enc_data(&(ar->authenticator)); +} + +void +ktest_make_sample_ap_rep(krb5_ap_rep *ar) +{ + ktest_make_sample_enc_data(&ar->enc_part); +} + +void +ktest_make_sample_ap_rep_enc_part(krb5_ap_rep_enc_part *arep) +{ + arep->ctime = SAMPLE_TIME; + arep->cusec = SAMPLE_USEC; + arep->subkey = ealloc(sizeof(krb5_keyblock)); + ktest_make_sample_keyblock(arep->subkey); + arep->seq_number = SAMPLE_SEQ_NUMBER; +} + +void +ktest_make_sample_kdc_req(krb5_kdc_req *kr) +{ + /* msg_type is left up to the calling procedure */ + ktest_make_sample_pa_data_array(&kr->padata); + kr->kdc_options = SAMPLE_FLAGS; + ktest_make_sample_principal(&(kr->client)); + ktest_make_sample_principal(&(kr->server)); + kr->from = SAMPLE_TIME; + kr->till = SAMPLE_TIME; + kr->rtime = SAMPLE_TIME; + kr->nonce = SAMPLE_NONCE; + kr->nktypes = 2; + kr->ktype = ealloc(2 * sizeof(krb5_enctype)); + kr->ktype[0] = 0; + kr->ktype[1] = 1; + ktest_make_sample_addresses(&kr->addresses); + ktest_make_sample_enc_data(&kr->authorization_data); + ktest_make_sample_authorization_data(&kr->unenc_authdata); + ktest_make_sample_sequence_of_ticket(&kr->second_ticket); +} + +void +ktest_make_sample_kdc_req_body(krb5_kdc_req *krb) +{ + krb->kdc_options = SAMPLE_FLAGS; + ktest_make_sample_principal(&krb->client); + ktest_make_sample_principal(&krb->server); + krb->from = SAMPLE_TIME; + krb->till = SAMPLE_TIME; + krb->rtime = SAMPLE_TIME; + krb->nonce = SAMPLE_NONCE; + krb->nktypes = 2; + krb->ktype = (krb5_enctype*)calloc(2,sizeof(krb5_enctype)); + krb->ktype[0] = 0; + krb->ktype[1] = 1; + ktest_make_sample_addresses(&krb->addresses); + ktest_make_sample_enc_data(&krb->authorization_data); + ktest_make_sample_authorization_data(&krb->unenc_authdata); + ktest_make_sample_sequence_of_ticket(&krb->second_ticket); +} + +void +ktest_make_sample_safe(krb5_safe *s) +{ + ktest_make_sample_data(&s->user_data); + s->timestamp = SAMPLE_TIME; + s->usec = SAMPLE_USEC; + s->seq_number = SAMPLE_SEQ_NUMBER; + s->s_address = ealloc(sizeof(krb5_address)); + ktest_make_sample_address(s->s_address); + s->r_address = ealloc(sizeof(krb5_address)); + ktest_make_sample_address(s->r_address); + s->checksum = ealloc(sizeof(krb5_checksum)); + ktest_make_sample_checksum(s->checksum); +} + +void +ktest_make_sample_priv(krb5_priv *p) +{ + ktest_make_sample_enc_data(&p->enc_part); +} + +void +ktest_make_sample_priv_enc_part(krb5_priv_enc_part *pep) +{ + ktest_make_sample_data(&(pep->user_data)); + pep->timestamp = SAMPLE_TIME; + pep->usec = SAMPLE_USEC; + pep->seq_number = SAMPLE_SEQ_NUMBER; + pep->s_address = ealloc(sizeof(krb5_address)); + ktest_make_sample_address(pep->s_address); + pep->r_address = ealloc(sizeof(krb5_address)); + ktest_make_sample_address(pep->r_address); +} + +void +ktest_make_sample_cred(krb5_cred *c) +{ + ktest_make_sample_sequence_of_ticket(&c->tickets); + ktest_make_sample_enc_data(&c->enc_part); +} + +void +ktest_make_sample_sequence_of_ticket(krb5_ticket ***sot) +{ + int i; + + *sot = ealloc(3 * sizeof(krb5_ticket *)); + for (i = 0; i < 2; i++) { + (*sot)[i] = ealloc(sizeof(krb5_ticket)); + ktest_make_sample_ticket((*sot)[i]); + } + (*sot)[2] = NULL; +} + +void +ktest_make_sample_cred_enc_part(krb5_cred_enc_part *cep) +{ + cep->nonce = SAMPLE_NONCE; + cep->timestamp = SAMPLE_TIME; + cep->usec = SAMPLE_USEC; + cep->s_address = ealloc(sizeof(krb5_address)); + ktest_make_sample_address(cep->s_address); + cep->r_address = ealloc(sizeof(krb5_address)); + ktest_make_sample_address(cep->r_address); + ktest_make_sequence_of_cred_info(&cep->ticket_info); +} + +void +ktest_make_sequence_of_cred_info(krb5_cred_info ***soci) +{ + int i; + + *soci = ealloc(3 * sizeof(krb5_cred_info *)); + for (i = 0; i < 2; i++) { + (*soci)[i] = ealloc(sizeof(krb5_cred_info)); + ktest_make_sample_cred_info((*soci)[i]); + } + (*soci)[2] = NULL; +} + +void +ktest_make_sample_cred_info(krb5_cred_info *ci) +{ + ci->session = ealloc(sizeof(krb5_keyblock)); + ktest_make_sample_keyblock(ci->session); + ktest_make_sample_principal(&ci->client); + ktest_make_sample_principal(&ci->server); + ci->flags = SAMPLE_FLAGS; + ci->times.authtime = SAMPLE_TIME; + ci->times.starttime = SAMPLE_TIME; + ci->times.endtime = SAMPLE_TIME; + ci->times.renew_till = SAMPLE_TIME; + ktest_make_sample_addresses(&ci->caddrs); +} + +void +ktest_make_sample_error(krb5_error *kerr) +{ + kerr->ctime = SAMPLE_TIME; + kerr->cusec = SAMPLE_USEC; + kerr->susec = SAMPLE_USEC; + kerr->stime = SAMPLE_TIME; + kerr->error = SAMPLE_ERROR; + ktest_make_sample_principal(&kerr->client); + ktest_make_sample_principal(&kerr->server); + ktest_make_sample_data(&kerr->text); + ktest_make_sample_data(&kerr->e_data); +} + +void +ktest_make_sample_data(krb5_data *d) +{ + krb5_data_parse(d, "krb5data"); +} + +void +ktest_make_sample_etype_info(krb5_etype_info_entry ***p) +{ + krb5_etype_info_entry **info; + int i, len; + char *str; + + info = ealloc(4 * sizeof(krb5_etype_info_entry *)); + for (i = 0; i < 3; i++) { + info[i] = ealloc(sizeof(krb5_etype_info_entry)); + info[i]->etype = i; + len = asprintf(&str, "Morton's #%d", i); + if (len < 0) + abort(); + info[i]->salt = (krb5_octet *)str; + info[i]->length = len; + info[i]->s2kparams.data = NULL; + info[i]->s2kparams.length = 0; + info[i]->magic = KV5M_ETYPE_INFO_ENTRY; + } + free(info[1]->salt); + info[1]->length = KRB5_ETYPE_NO_SALT; + info[1]->salt = 0; + *p = info; +} + + +void +ktest_make_sample_etype_info2(krb5_etype_info_entry ***p) +{ + krb5_etype_info_entry **info; + int i, len; + char *str; + + info = ealloc(4 * sizeof(krb5_etype_info_entry *)); + for (i = 0; i < 3; i++) { + info[i] = ealloc(sizeof(krb5_etype_info_entry)); + info[i]->etype = i; + len = asprintf(&str, "Morton's #%d", i); + if (len < 0) + abort(); + info[i]->salt = (krb5_octet *)str; + info[i]->length = (unsigned int)len; + len = asprintf(&info[i]->s2kparams.data, "s2k: %d", i); + if (len < 0) + abort(); + info[i]->s2kparams.length = (unsigned int) len; + info[i]->magic = KV5M_ETYPE_INFO_ENTRY; + } + free(info[1]->salt); + info[1]->length = KRB5_ETYPE_NO_SALT; + info[1]->salt = 0; + *p = info; +} + + +void +ktest_make_sample_pa_enc_ts(krb5_pa_enc_ts *pa_enc) +{ + pa_enc->patimestamp = SAMPLE_TIME; + pa_enc->pausec = SAMPLE_USEC; +} + +void +ktest_make_sample_sam_challenge_2(krb5_sam_challenge_2 *p) +{ + /* Need a valid DER sequence encoding here; this one contains the OCTET + * STRING "challenge". */ + krb5_data_parse(&p->sam_challenge_2_body, "\x30\x0B\x04\x09" "challenge"); + p->sam_cksum = ealloc(2 * sizeof(krb5_checksum *)); + p->sam_cksum[0] = ealloc(sizeof(krb5_checksum)); + ktest_make_sample_checksum(p->sam_cksum[0]); + p->sam_cksum[1] = NULL; +} + +void +ktest_make_sample_sam_challenge_2_body(krb5_sam_challenge_2_body *p) +{ + p->sam_type = 42; + p->sam_flags = KRB5_SAM_USE_SAD_AS_KEY; + krb5_data_parse(&p->sam_type_name, "type name"); + p->sam_track_id = empty_data(); + krb5_data_parse(&p->sam_challenge_label, "challenge label"); + krb5_data_parse(&p->sam_challenge, "challenge ipse"); + krb5_data_parse(&p->sam_response_prompt, "response_prompt ipse"); + p->sam_pk_for_sad = empty_data(); + p->sam_nonce = 0x543210; + p->sam_etype = ENCTYPE_AES256_CTS_HMAC_SHA384_192; +} + +void +ktest_make_sample_sam_response_2(krb5_sam_response_2 *p) +{ + p->magic = KV5M_SAM_RESPONSE; + p->sam_type = 43; /* information */ + p->sam_flags = KRB5_SAM_USE_SAD_AS_KEY; /* KRB5_SAM_* values */ + krb5_data_parse(&p->sam_track_id, "track data"); + krb5_data_parse(&p->sam_enc_nonce_or_sad.ciphertext, "nonce or sad"); + p->sam_enc_nonce_or_sad.enctype = ENCTYPE_AES256_CTS_HMAC_SHA384_192; + p->sam_enc_nonce_or_sad.kvno = 3382; + p->sam_nonce = 0x543210; +} + +void +ktest_make_sample_enc_sam_response_enc_2(krb5_enc_sam_response_enc_2 *p) +{ + p->magic = 83; + p->sam_nonce = 88; + krb5_data_parse(&p->sam_sad, "enc_sam_response_enc_2"); +} + +void +ktest_make_sample_pa_for_user(krb5_pa_for_user *p) +{ + ktest_make_sample_principal(&p->user); + ktest_make_sample_checksum(&p->cksum); + ktest_make_sample_data(&p->auth_package); +} + +void +ktest_make_sample_pa_s4u_x509_user(krb5_pa_s4u_x509_user *p) +{ + krb5_s4u_userid *u = &p->user_id; + + u->nonce = 13243546; + ktest_make_sample_principal(&u->user); + krb5_data_parse(&u->subject_cert, "pa_s4u_x509_user"); + u->options = 0x80000000; + ktest_make_sample_checksum(&p->cksum); +} + +void +ktest_make_sample_ad_kdcissued(krb5_ad_kdcissued *p) +{ + ktest_make_sample_checksum(&p->ad_checksum); + ktest_make_sample_principal(&p->i_principal); + ktest_make_sample_authorization_data(&p->elements); +} + +void +ktest_make_sample_iakerb_header(krb5_iakerb_header *ih) +{ + ktest_make_sample_data(&(ih->target_realm)); + ih->cookie = ealloc(sizeof(krb5_data)); + ktest_make_sample_data(ih->cookie); +} + +void +ktest_make_sample_iakerb_finished(krb5_iakerb_finished *ih) +{ + ktest_make_sample_checksum(&ih->checksum); +} + +static void +ktest_make_sample_fast_finished(krb5_fast_finished *p) +{ + p->timestamp = SAMPLE_TIME; + p->usec = SAMPLE_USEC; + ktest_make_sample_principal(&p->client); + ktest_make_sample_checksum(&p->ticket_checksum); +} + +void +ktest_make_sample_fast_response(krb5_fast_response *p) +{ + ktest_make_sample_pa_data_array(&p->padata); + p->strengthen_key = ealloc(sizeof(krb5_keyblock)); + ktest_make_sample_keyblock(p->strengthen_key); + p->finished = ealloc(sizeof(krb5_fast_finished)); + ktest_make_sample_fast_finished(p->finished); + p->nonce = SAMPLE_NONCE; +} + +void +ktest_make_sha256_alg(krb5_algorithm_identifier *p) +{ + /* { 2 16 840 1 101 3 4 2 1 } */ + krb5_data_parse(&p->algorithm, "\x60\x86\x48\x01\x65\x03\x04\x02\x01"); + p->parameters = empty_data(); +} + +void +ktest_make_sha1_alg(krb5_algorithm_identifier *p) +{ + /* { 1 3 14 3 2 26 } */ + krb5_data_parse(&p->algorithm, "\x2b\x0e\x03\x02\x1a"); + p->parameters = empty_data(); +} + +void +ktest_make_minimal_otp_tokeninfo(krb5_otp_tokeninfo *p) +{ + memset(p, 0, sizeof(*p)); + p->length = p->format = p->iteration_count = -1; +} + +void +ktest_make_maximal_otp_tokeninfo(krb5_otp_tokeninfo *p) +{ + p->flags = KRB5_OTP_FLAG_NEXTOTP | KRB5_OTP_FLAG_COMBINE | + KRB5_OTP_FLAG_COLLECT_PIN | KRB5_OTP_FLAG_ENCRYPT_NONCE | + KRB5_OTP_FLAG_SEPARATE_PIN | KRB5_OTP_FLAG_CHECK_DIGIT; + krb5_data_parse(&p->vendor, "Examplecorp"); + krb5_data_parse(&p->challenge, "hark!"); + p->length = 10; + p->format = 2; + krb5_data_parse(&p->token_id, "yourtoken"); + krb5_data_parse(&p->alg_id, "urn:ietf:params:xml:ns:keyprov:pskc:hotp"); + p->supported_hash_alg = ealloc(3 * sizeof(*p->supported_hash_alg)); + p->supported_hash_alg[0] = ealloc(sizeof(*p->supported_hash_alg[0])); + ktest_make_sha256_alg(p->supported_hash_alg[0]); + p->supported_hash_alg[1] = ealloc(sizeof(*p->supported_hash_alg[1])); + ktest_make_sha1_alg(p->supported_hash_alg[1]); + p->supported_hash_alg[2] = NULL; + p->iteration_count = 1000; +} + +void +ktest_make_minimal_pa_otp_challenge(krb5_pa_otp_challenge *p) +{ + memset(p, 0, sizeof(*p)); + krb5_data_parse(&p->nonce, "minnonce"); + p->tokeninfo = ealloc(2 * sizeof(*p->tokeninfo)); + p->tokeninfo[0] = ealloc(sizeof(*p->tokeninfo[0])); + ktest_make_minimal_otp_tokeninfo(p->tokeninfo[0]); + p->tokeninfo[1] = NULL; +} + +void +ktest_make_maximal_pa_otp_challenge(krb5_pa_otp_challenge *p) +{ + krb5_data_parse(&p->nonce, "maxnonce"); + krb5_data_parse(&p->service, "testservice"); + p->tokeninfo = ealloc(3 * sizeof(*p->tokeninfo)); + p->tokeninfo[0] = ealloc(sizeof(*p->tokeninfo[0])); + ktest_make_minimal_otp_tokeninfo(p->tokeninfo[0]); + p->tokeninfo[1] = ealloc(sizeof(*p->tokeninfo[1])); + ktest_make_maximal_otp_tokeninfo(p->tokeninfo[1]); + p->tokeninfo[2] = NULL; + krb5_data_parse(&p->salt, "keysalt"); + krb5_data_parse(&p->s2kparams, "1234"); +} + +void +ktest_make_minimal_pa_otp_req(krb5_pa_otp_req *p) +{ + memset(p, 0, sizeof(*p)); + p->iteration_count = -1; + p->format = -1; + ktest_make_sample_enc_data(&p->enc_data); +} + +void +ktest_make_maximal_pa_otp_req(krb5_pa_otp_req *p) +{ + p->flags = KRB5_OTP_FLAG_NEXTOTP | KRB5_OTP_FLAG_COMBINE; + krb5_data_parse(&p->nonce, "nonce"); + ktest_make_sample_enc_data(&p->enc_data); + p->hash_alg = ealloc(sizeof(*p->hash_alg)); + ktest_make_sha256_alg(p->hash_alg); + p->iteration_count = 1000; + krb5_data_parse(&p->otp_value, "frogs"); + krb5_data_parse(&p->pin, "myfirstpin"); + krb5_data_parse(&p->challenge, "hark!"); + p->time = SAMPLE_TIME; + krb5_data_parse(&p->counter, "346"); + p->format = 2; + krb5_data_parse(&p->token_id, "yourtoken"); + krb5_data_parse(&p->alg_id, "urn:ietf:params:xml:ns:keyprov:pskc:hotp"); + krb5_data_parse(&p->vendor, "Examplecorp"); +} + +#ifndef DISABLE_PKINIT + +static void +ktest_make_sample_pk_authenticator(krb5_pk_authenticator *p) +{ + p->cusec = SAMPLE_USEC; + p->ctime = SAMPLE_TIME; + p->nonce = SAMPLE_NONCE; + ktest_make_sample_checksum(&p->paChecksum); + /* We don't encode the checksum type, only the contents. */ + p->paChecksum.checksum_type = 0; + p->freshnessToken = ealloc(sizeof(krb5_data)); + ktest_make_sample_data(p->freshnessToken); +} + +static void +ktest_make_sample_oid(krb5_data *p) +{ + krb5_data_parse(p, "\052\206\110\206\367\022\001\002\002"); +} + +static void +ktest_make_sample_algorithm_identifier(krb5_algorithm_identifier *p) +{ + ktest_make_sample_oid(&p->algorithm); + /* Need a valid DER encoding here; this is the OCTET STRING "params". */ + krb5_data_parse(&p->parameters, "\x04\x06" "params"); +} + +static void +ktest_make_sample_algorithm_identifier_no_params(krb5_algorithm_identifier *p) +{ + ktest_make_sample_oid(&p->algorithm); + p->parameters = empty_data(); +} + +static void +ktest_make_sample_external_principal_identifier( + krb5_external_principal_identifier *p) +{ + ktest_make_sample_data(&p->subjectName); + ktest_make_sample_data(&p->issuerAndSerialNumber); + ktest_make_sample_data(&p->subjectKeyIdentifier); +} + +void +ktest_make_sample_pa_pk_as_req(krb5_pa_pk_as_req *p) +{ + ktest_make_sample_data(&p->signedAuthPack); + p->trustedCertifiers = + ealloc(2 * sizeof(krb5_external_principal_identifier *)); + p->trustedCertifiers[0] = + ealloc(sizeof(krb5_external_principal_identifier)); + ktest_make_sample_external_principal_identifier(p->trustedCertifiers[0]); + p->trustedCertifiers[1] = NULL; + ktest_make_sample_data(&p->kdcPkId); +} + +static void +ktest_make_sample_dh_rep_info(krb5_dh_rep_info *p) +{ + ktest_make_sample_data(&p->dhSignedData); + ktest_make_sample_data(&p->serverDHNonce); + p->kdfID = ealloc(sizeof(krb5_data)); + ktest_make_sample_data(p->kdfID); +} + +void +ktest_make_sample_pa_pk_as_rep_dhInfo(krb5_pa_pk_as_rep *p) +{ + p->choice = choice_pa_pk_as_rep_dhInfo; + ktest_make_sample_dh_rep_info(&p->u.dh_Info); +} + +void +ktest_make_sample_pa_pk_as_rep_encKeyPack(krb5_pa_pk_as_rep *p) +{ + p->choice = choice_pa_pk_as_rep_encKeyPack; + ktest_make_sample_data(&p->u.encKeyPack); +} + +void +ktest_make_sample_auth_pack(krb5_auth_pack *p) +{ + ktest_make_sample_pk_authenticator(&p->pkAuthenticator); + /* Need a valid DER encoding here; this is the OCTET STRING "pvalue". */ + krb5_data_parse(&p->clientPublicValue, "\x04\x06" "pvalue"); + p->supportedCMSTypes = ealloc(3 * sizeof(krb5_algorithm_identifier *)); + p->supportedCMSTypes[0] = ealloc(sizeof(krb5_algorithm_identifier)); + ktest_make_sample_algorithm_identifier(p->supportedCMSTypes[0]); + p->supportedCMSTypes[1] = ealloc(sizeof(krb5_algorithm_identifier)); + ktest_make_sample_algorithm_identifier_no_params(p->supportedCMSTypes[1]); + p->supportedCMSTypes[2] = NULL; + ktest_make_sample_data(&p->clientDHNonce); + p->supportedKDFs = ealloc(2 * sizeof(krb5_data *)); + p->supportedKDFs[0] = ealloc(sizeof(krb5_data)); + ktest_make_sample_data(p->supportedKDFs[0]); + p->supportedKDFs[1] = NULL; +} + +void +ktest_make_sample_kdc_dh_key_info(krb5_kdc_dh_key_info *p) +{ + ktest_make_sample_data(&p->subjectPublicKey); + p->nonce = SAMPLE_NONCE; + p->dhKeyExpiration = SAMPLE_TIME; +} + +void +ktest_make_sample_reply_key_pack(krb5_reply_key_pack *p) +{ + ktest_make_sample_keyblock(&p->replyKey); + ktest_make_sample_checksum(&p->asChecksum); +} + +void +ktest_make_sample_sp80056a_other_info(krb5_sp80056a_other_info *p) +{ + ktest_make_sample_algorithm_identifier_no_params(&p->algorithm_identifier); + ktest_make_sample_principal(&p->party_u_info); + ktest_make_sample_principal(&p->party_v_info); + ktest_make_sample_data(&p->supp_pub_info); +} + +void +ktest_make_sample_pkinit_supp_pub_info(krb5_pkinit_supp_pub_info *p) +{ + p->enctype = ENCTYPE_AES256_CTS_HMAC_SHA384_192; + ktest_make_sample_data(&p->as_req); + ktest_make_sample_data(&p->pk_as_rep); +} + +#endif /* not DISABLE_PKINIT */ + +#ifdef ENABLE_LDAP +static void +ktest_make_sample_key_data(krb5_key_data *p, int i) +{ + char *str; + int len; + + len = asprintf(&str, "key%d", i); + if (len < 0) + abort(); + p->key_data_ver = 2; + p->key_data_type[0] = 2; + p->key_data_length[0] = (unsigned int) len; + p->key_data_contents[0] = (krb5_octet *)str; + len = asprintf(&str, "salt%d", i); + if (len < 0) + abort(); + p->key_data_type[1] = i; + p->key_data_length[1] = (unsigned int) len; + p->key_data_contents[1] = (krb5_octet *)str; +} + +void +ktest_make_sample_ldap_seqof_key_data(ldap_seqof_key_data *p) +{ + int i; + + p->mkvno = 14; + p->n_key_data = 3; + p->key_data = calloc(3,sizeof(krb5_key_data)); + p->kvno = 42; + for (i = 0; i < 3; i++) + ktest_make_sample_key_data(&p->key_data[i], i); +} +#endif + +void +ktest_make_sample_kkdcp_message(krb5_kkdcp_message *p) +{ + krb5_kdc_req req; + krb5_data *message; + + ktest_make_sample_kdc_req(&req); + req.msg_type = KRB5_AS_REQ; + encode_krb5_as_req(&req, &message); + p->kerb_message = *message; + free(message); + ktest_empty_kdc_req(&req); + ktest_make_sample_data(&(p->target_domain)); + p->dclocator_hint = 0; +} + +static krb5_authdata * +make_ad_element(krb5_authdatatype ad_type, const char *str) +{ + krb5_authdata *ad; + + ad = ealloc(sizeof(*ad)); + ad->ad_type = ad_type; + ad->length = strlen(str); + ad->contents = ealloc(ad->length); + memcpy(ad->contents, str, ad->length); + return ad; +} + +static krb5_verifier_mac * +make_vmac(krb5_boolean include_princ, krb5_kvno kvno, krb5_enctype enctype, + const char *cksumstr) +{ + krb5_verifier_mac *vmac; + + vmac = ealloc(sizeof(*vmac)); + if (include_princ) { + ktest_make_sample_principal(&vmac->princ); + (void)krb5_set_principal_realm(NULL, vmac->princ, ""); + } else { + vmac->princ = NULL; + } + vmac->kvno = kvno; + vmac->enctype = enctype; + vmac->checksum.checksum_type = 1; + vmac->checksum.length = strlen(cksumstr); + vmac->checksum.contents = ealloc(vmac->checksum.length); + memcpy(vmac->checksum.contents, cksumstr, vmac->checksum.length); + return vmac; +} + +void +ktest_make_minimal_cammac(krb5_cammac *p) +{ + memset(p, 0, sizeof(*p)); + p->elements = ealloc(2 * sizeof(*p->elements)); + p->elements[0] = make_ad_element(1, "ad1"); + p->elements[1] = NULL; +} + +void +ktest_make_maximal_cammac(krb5_cammac *p) +{ + p->elements = ealloc(3 * sizeof(*p->elements)); + p->elements[0] = make_ad_element(1, "ad1"); + p->elements[1] = make_ad_element(2, "ad2"); + p->elements[2] = NULL; + p->kdc_verifier = make_vmac(TRUE, 5, 16, "cksumkdc"); + p->svc_verifier = make_vmac(TRUE, 5, 16, "cksumsvc"); + p->other_verifiers = ealloc(3 * sizeof(*p->other_verifiers)); + p->other_verifiers[0] = make_vmac(FALSE, 0, 0, "cksum1"); + p->other_verifiers[1] = make_vmac(TRUE, 5, 16, "cksum2"); + p->other_verifiers[2] = NULL; +} + +void +ktest_make_sample_secure_cookie(krb5_secure_cookie *p) +{ + ktest_make_sample_pa_data_array(&p->data); + p->time = SAMPLE_TIME; +} + +void +ktest_make_minimal_spake_factor(krb5_spake_factor *p) +{ + p->type = 1; + p->data = NULL; +} + +void +ktest_make_maximal_spake_factor(krb5_spake_factor *p) +{ + p->type = 2; + p->data = ealloc(sizeof(*p->data)); + krb5_data_parse(p->data, "fdata"); +} + +void +ktest_make_support_pa_spake(krb5_pa_spake *p) +{ + krb5_spake_support *s = &p->u.support; + + s->ngroups = 2; + s->groups = ealloc(s->ngroups * sizeof(*s->groups)); + s->groups[0] = 1; + s->groups[1] = 2; + p->choice = SPAKE_MSGTYPE_SUPPORT; +} + +void +ktest_make_challenge_pa_spake(krb5_pa_spake *p) +{ + krb5_spake_challenge *c = &p->u.challenge; + + c->group = 1; + krb5_data_parse(&c->pubkey, "T value"); + c->factors = ealloc(3 * sizeof(*c->factors)); + c->factors[0] = ealloc(sizeof(*c->factors[0])); + ktest_make_minimal_spake_factor(c->factors[0]); + c->factors[1] = ealloc(sizeof(*c->factors[1])); + ktest_make_maximal_spake_factor(c->factors[1]); + c->factors[2] = NULL; + p->choice = SPAKE_MSGTYPE_CHALLENGE; +} + +void +ktest_make_response_pa_spake(krb5_pa_spake *p) +{ + krb5_spake_response *r = &p->u.response; + + krb5_data_parse(&r->pubkey, "S value"); + ktest_make_sample_enc_data(&r->factor); + p->choice = SPAKE_MSGTYPE_RESPONSE; +} + +void +ktest_make_encdata_pa_spake(krb5_pa_spake *p) +{ + ktest_make_sample_enc_data(&p->u.encdata); + p->choice = SPAKE_MSGTYPE_ENCDATA; +} + +/****************************************************************/ +/* destructors */ + +void +ktest_destroy_data(krb5_data **d) +{ + if (*d != NULL) { + free((*d)->data); + free(*d); + *d = NULL; + } +} + +void +ktest_empty_data(krb5_data *d) +{ + if (d->data != NULL) { + free(d->data); + d->data = NULL; + d->length = 0; + } +} + +static void +ktest_empty_checksum(krb5_checksum *cs) +{ + free(cs->contents); + cs->contents = NULL; +} + +void +ktest_destroy_checksum(krb5_checksum **cs) +{ + if (*cs != NULL) { + free((*cs)->contents); + free(*cs); + *cs = NULL; + } +} + +void +ktest_empty_keyblock(krb5_keyblock *kb) +{ + if (kb != NULL) { + if (kb->contents) { + free(kb->contents); + kb->contents = NULL; + } + } +} + +void +ktest_destroy_keyblock(krb5_keyblock **kb) +{ + if (*kb != NULL) { + free((*kb)->contents); + free(*kb); + *kb = NULL; + } +} + +void +ktest_empty_authorization_data(krb5_authdata **ad) +{ + int i; + + if (*ad != NULL) { + for (i=0; ad[i] != NULL; i++) + ktest_destroy_authdata(&ad[i]); + } +} + +void +ktest_destroy_authorization_data(krb5_authdata ***ad) +{ + ktest_empty_authorization_data(*ad); + free(*ad); + *ad = NULL; +} + +void +ktest_destroy_authdata(krb5_authdata **ad) +{ + if (*ad != NULL) { + free((*ad)->contents); + free(*ad); + *ad = NULL; + } +} + +void +ktest_empty_pa_data_array(krb5_pa_data **pad) +{ + int i; + + for (i=0; pad[i] != NULL; i++) + ktest_destroy_pa_data(&pad[i]); +} + +void +ktest_destroy_pa_data_array(krb5_pa_data ***pad) +{ + ktest_empty_pa_data_array(*pad); + free(*pad); + *pad = NULL; +} + +void +ktest_destroy_pa_data(krb5_pa_data **pad) +{ + if (*pad != NULL) { + free((*pad)->contents); + free(*pad); + *pad = NULL; + } +} + +void +ktest_destroy_address(krb5_address **a) +{ + if (*a != NULL) { + free((*a)->contents); + free(*a); + *a = NULL; + } +} + +void +ktest_empty_addresses(krb5_address **a) +{ + int i; + + for (i=0; a[i] != NULL; i++) + ktest_destroy_address(&a[i]); +} + +void +ktest_destroy_addresses(krb5_address ***a) +{ + ktest_empty_addresses(*a); + free(*a); + *a = NULL; +} + +void +ktest_destroy_principal(krb5_principal *p) +{ + int i; + + if (*p == NULL) + return; + for (i=0; i<(*p)->length; i++) + ktest_empty_data(&(*p)->data[i]); + ktest_empty_data(&(*p)->realm); + free((*p)->data); + free(*p); + *p = NULL; +} + +void +ktest_destroy_sequence_of_integer(long **soi) +{ + free(*soi); + *soi = NULL; +} + +void +ktest_destroy_sequence_of_ticket(krb5_ticket ***sot) +{ + int i; + + for (i=0; (*sot)[i] != NULL; i++) + ktest_destroy_ticket(&(*sot)[i]); + free(*sot); + *sot = NULL; +} + +void +ktest_destroy_ticket(krb5_ticket **tkt) +{ + ktest_destroy_principal(&(*tkt)->server); + ktest_destroy_enc_data(&(*tkt)->enc_part); + /* ktest_empty_enc_tkt_part(((*tkt)->enc_part2));*/ + free(*tkt); + *tkt = NULL; +} + +void +ktest_empty_ticket(krb5_ticket *tkt) +{ + if (tkt->server) + ktest_destroy_principal(&tkt->server); + ktest_destroy_enc_data(&tkt->enc_part); + if (tkt->enc_part2) + ktest_destroy_enc_tkt_part(&tkt->enc_part2); +} + +void +ktest_destroy_enc_data(krb5_enc_data *ed) +{ + ktest_empty_data(&ed->ciphertext); + ed->kvno = 0; +} + +void +ktest_destroy_etype_info_entry(krb5_etype_info_entry *i) +{ + if (i->salt) + free(i->salt); + ktest_empty_data(&i->s2kparams); + free(i); +} + +void +ktest_destroy_etype_info(krb5_etype_info_entry **info) +{ + int i; + + for (i = 0; info[i] != NULL; i++) + ktest_destroy_etype_info_entry(info[i]); + free(info); +} + +void +ktest_empty_kdc_req(krb5_kdc_req *kr) +{ + if (kr->padata) + ktest_destroy_pa_data_array(&kr->padata); + + if (kr->client) + ktest_destroy_principal(&kr->client); + + if (kr->server) + ktest_destroy_principal(&kr->server); + free(kr->ktype); + if (kr->addresses) + ktest_destroy_addresses(&kr->addresses); + ktest_destroy_enc_data(&kr->authorization_data); + if (kr->unenc_authdata) + ktest_destroy_authorization_data(&kr->unenc_authdata); + if (kr->second_ticket) + ktest_destroy_sequence_of_ticket(&kr->second_ticket); + +} + +void +ktest_empty_kdc_rep(krb5_kdc_rep *kr) +{ + if (kr->padata) + ktest_destroy_pa_data_array(&kr->padata); + + if (kr->client) + ktest_destroy_principal(&kr->client); + + if (kr->ticket) + ktest_destroy_ticket(&kr->ticket); + + ktest_destroy_enc_data(&kr->enc_part); + + if (kr->enc_part2) { + ktest_empty_enc_kdc_rep_part(kr->enc_part2); + free(kr->enc_part2); + kr->enc_part2 = NULL; + } +} + +void +ktest_empty_authenticator(krb5_authenticator *a) +{ + if (a->client) + ktest_destroy_principal(&a->client); + if (a->checksum) + ktest_destroy_checksum(&a->checksum); + if (a->subkey) + ktest_destroy_keyblock(&a->subkey); + if (a->authorization_data) + ktest_destroy_authorization_data(&a->authorization_data); +} + +void +ktest_empty_enc_tkt_part(krb5_enc_tkt_part *etp) +{ + if (etp->session) + ktest_destroy_keyblock(&etp->session); + if (etp->client) + ktest_destroy_principal(&etp->client); + if (etp->caddrs) + ktest_destroy_addresses(&etp->caddrs); + if (etp->authorization_data) + ktest_destroy_authorization_data(&etp->authorization_data); + ktest_destroy_transited(&etp->transited); +} + +void +ktest_destroy_enc_tkt_part(krb5_enc_tkt_part **etp) +{ + if (*etp) { + ktest_empty_enc_tkt_part(*etp); + free(*etp); + *etp = NULL; + } +} + +void +ktest_empty_enc_kdc_rep_part(krb5_enc_kdc_rep_part *ekr) +{ + if (ekr->session) + ktest_destroy_keyblock(&ekr->session); + + if (ekr->server) + ktest_destroy_principal(&ekr->server); + + if (ekr->caddrs) + ktest_destroy_addresses(&ekr->caddrs); + ktest_destroy_last_req(&ekr->last_req); +} + +void +ktest_destroy_transited(krb5_transited *t) +{ + if (t->tr_contents.data) + ktest_empty_data(&t->tr_contents); +} + +void +ktest_empty_ap_rep(krb5_ap_rep *ar) +{ + ktest_destroy_enc_data(&ar->enc_part); +} + +void +ktest_empty_ap_req(krb5_ap_req *ar) +{ + if (ar->ticket) + ktest_destroy_ticket(&ar->ticket); + ktest_destroy_enc_data(&ar->authenticator); +} + +void +ktest_empty_cred_enc_part(krb5_cred_enc_part *cep) +{ + if (cep->s_address) + ktest_destroy_address(&cep->s_address); + if (cep->r_address) + ktest_destroy_address(&cep->r_address); + if (cep->ticket_info) + ktest_destroy_sequence_of_cred_info(&cep->ticket_info); +} + +void +ktest_destroy_cred_info(krb5_cred_info **ci) +{ + if ((*ci)->session) + ktest_destroy_keyblock(&(*ci)->session); + if ((*ci)->client) + ktest_destroy_principal(&(*ci)->client); + if ((*ci)->server) + ktest_destroy_principal(&(*ci)->server); + if ((*ci)->caddrs) + ktest_destroy_addresses(&(*ci)->caddrs); + free(*ci); + *ci = NULL; +} + +void +ktest_destroy_sequence_of_cred_info(krb5_cred_info ***soci) +{ + int i; + + for (i = 0; (*soci)[i] != NULL; i++) + ktest_destroy_cred_info(&(*soci)[i]); + free(*soci); + *soci = NULL; +} + +void +ktest_empty_safe(krb5_safe *s) +{ + ktest_empty_data(&s->user_data); + ktest_destroy_address(&s->s_address); + ktest_destroy_address(&s->r_address); + ktest_destroy_checksum(&s->checksum); +} + +void +ktest_empty_priv_enc_part(krb5_priv_enc_part *pep) +{ + ktest_empty_data(&pep->user_data); + ktest_destroy_address(&pep->s_address); + ktest_destroy_address(&pep->r_address); +} + +void +ktest_empty_priv(krb5_priv *p) +{ + ktest_destroy_enc_data(&p->enc_part); +} + +void +ktest_empty_cred(krb5_cred *c) +{ + ktest_destroy_sequence_of_ticket(&c->tickets); + ktest_destroy_enc_data(&c->enc_part); + /* enc_part2 */ +} + +void +ktest_destroy_last_req(krb5_last_req_entry ***lr) +{ + int i; + + if (*lr) { + for (i=0; (*lr)[i] != NULL; i++) + free((*lr)[i]); + + free(*lr); + } +} + +void +ktest_empty_error(krb5_error *kerr) +{ + if (kerr->client) + ktest_destroy_principal(&kerr->client); + if (kerr->server) + ktest_destroy_principal(&kerr->server); + ktest_empty_data(&kerr->text); + ktest_empty_data(&kerr->e_data); +} + +void +ktest_empty_ap_rep_enc_part(krb5_ap_rep_enc_part *arep) +{ + ktest_destroy_keyblock(&(arep)->subkey); +} + +void +ktest_empty_sam_challenge_2(krb5_sam_challenge_2 *p) +{ + krb5_checksum **ck; + + ktest_empty_data(&p->sam_challenge_2_body); + if (p->sam_cksum != NULL) { + for (ck = p->sam_cksum; *ck != NULL; ck++) + ktest_destroy_checksum(ck); + free(p->sam_cksum); + p->sam_cksum = NULL; + } +} + +void +ktest_empty_sam_challenge_2_body(krb5_sam_challenge_2_body *p) +{ + ktest_empty_data(&p->sam_type_name); + ktest_empty_data(&p->sam_track_id); + ktest_empty_data(&p->sam_challenge_label); + ktest_empty_data(&p->sam_challenge); + ktest_empty_data(&p->sam_response_prompt); + ktest_empty_data(&p->sam_pk_for_sad); +} + +void +ktest_empty_sam_response_2(krb5_sam_response_2 *p) +{ + ktest_empty_data(&p->sam_track_id); + ktest_empty_data(&p->sam_enc_nonce_or_sad.ciphertext); +} + +void +ktest_empty_enc_sam_response_enc_2(krb5_enc_sam_response_enc_2 *p) +{ + ktest_empty_data(&p->sam_sad); +} + +void +ktest_empty_pa_for_user(krb5_pa_for_user *p) +{ + ktest_destroy_principal(&p->user); + ktest_empty_checksum(&p->cksum); + ktest_empty_data(&p->auth_package); +} + +void +ktest_empty_pa_s4u_x509_user(krb5_pa_s4u_x509_user *p) +{ + ktest_destroy_principal(&p->user_id.user); + ktest_empty_data(&p->user_id.subject_cert); + free(p->cksum.contents); +} + +void +ktest_empty_ad_kdcissued(krb5_ad_kdcissued *p) +{ + free(p->ad_checksum.contents); + ktest_destroy_principal(&p->i_principal); + ktest_destroy_authorization_data(&p->elements); +} + +void +ktest_empty_iakerb_header(krb5_iakerb_header *p) +{ + krb5_free_data_contents(NULL, &p->target_realm); + krb5_free_data(NULL, p->cookie); +} + +void +ktest_empty_iakerb_finished(krb5_iakerb_finished *p) +{ + krb5_free_checksum_contents(NULL, &p->checksum); +} + +static void +ktest_empty_fast_finished(krb5_fast_finished *p) +{ + ktest_destroy_principal(&p->client); + ktest_empty_checksum(&p->ticket_checksum); +} + +void +ktest_empty_fast_response(krb5_fast_response *p) +{ + ktest_destroy_pa_data_array(&p->padata); + ktest_destroy_keyblock(&p->strengthen_key); + if (p->finished != NULL) { + ktest_empty_fast_finished(p->finished); + free(p->finished); + p->finished = NULL; + } +} + +static void +ktest_empty_algorithm_identifier(krb5_algorithm_identifier *p) +{ + ktest_empty_data(&p->algorithm); + ktest_empty_data(&p->parameters); +} + +void +ktest_empty_otp_tokeninfo(krb5_otp_tokeninfo *p) +{ + krb5_algorithm_identifier **alg; + + p->flags = 0; + krb5_free_data_contents(NULL, &p->vendor); + krb5_free_data_contents(NULL, &p->challenge); + krb5_free_data_contents(NULL, &p->token_id); + krb5_free_data_contents(NULL, &p->alg_id); + for (alg = p->supported_hash_alg; alg != NULL && *alg != NULL; alg++) { + ktest_empty_algorithm_identifier(*alg); + free(*alg); + } + free(p->supported_hash_alg); + p->supported_hash_alg = NULL; + p->length = p->format = p->iteration_count = -1; +} + +void +ktest_empty_pa_otp_challenge(krb5_pa_otp_challenge *p) +{ + krb5_otp_tokeninfo **ti; + + krb5_free_data_contents(NULL, &p->nonce); + krb5_free_data_contents(NULL, &p->service); + for (ti = p->tokeninfo; *ti != NULL; ti++) { + ktest_empty_otp_tokeninfo(*ti); + free(*ti); + } + free(p->tokeninfo); + p->tokeninfo = NULL; + krb5_free_data_contents(NULL, &p->salt); + krb5_free_data_contents(NULL, &p->s2kparams); +} + +void +ktest_empty_pa_otp_req(krb5_pa_otp_req *p) +{ + p->flags = 0; + krb5_free_data_contents(NULL, &p->nonce); + ktest_destroy_enc_data(&p->enc_data); + if (p->hash_alg != NULL) + ktest_empty_algorithm_identifier(p->hash_alg); + free(p->hash_alg); + p->hash_alg = NULL; + p->iteration_count = -1; + krb5_free_data_contents(NULL, &p->otp_value); + krb5_free_data_contents(NULL, &p->pin); + krb5_free_data_contents(NULL, &p->challenge); + p->time = 0; + krb5_free_data_contents(NULL, &p->counter); + p->format = -1; + krb5_free_data_contents(NULL, &p->token_id); + krb5_free_data_contents(NULL, &p->alg_id); + krb5_free_data_contents(NULL, &p->vendor); +} + +#ifndef DISABLE_PKINIT + +static void +ktest_empty_pk_authenticator(krb5_pk_authenticator *p) +{ + ktest_empty_checksum(&p->paChecksum); + p->paChecksum.contents = NULL; + krb5_free_data(NULL, p->freshnessToken); + p->freshnessToken = NULL; +} + +static void +ktest_empty_external_principal_identifier( + krb5_external_principal_identifier *p) +{ + ktest_empty_data(&p->subjectName); + ktest_empty_data(&p->issuerAndSerialNumber); + ktest_empty_data(&p->subjectKeyIdentifier); +} + +void +ktest_empty_pa_pk_as_req(krb5_pa_pk_as_req *p) +{ + krb5_external_principal_identifier **pi; + + ktest_empty_data(&p->signedAuthPack); + for (pi = p->trustedCertifiers; *pi != NULL; pi++) { + ktest_empty_external_principal_identifier(*pi); + free(*pi); + } + free(p->trustedCertifiers); + p->trustedCertifiers = NULL; + ktest_empty_data(&p->kdcPkId); +} + +static void +ktest_empty_dh_rep_info(krb5_dh_rep_info *p) +{ + ktest_empty_data(&p->dhSignedData); + ktest_empty_data(&p->serverDHNonce); + ktest_destroy_data(&p->kdfID); +} + +void +ktest_empty_pa_pk_as_rep(krb5_pa_pk_as_rep *p) +{ + if (p->choice == choice_pa_pk_as_rep_dhInfo) + ktest_empty_dh_rep_info(&p->u.dh_Info); + else if (p->choice == choice_pa_pk_as_rep_encKeyPack) + ktest_empty_data(&p->u.encKeyPack); + p->choice = choice_pa_pk_as_rep_UNKNOWN; +} + +void +ktest_empty_auth_pack(krb5_auth_pack *p) +{ + krb5_algorithm_identifier **ai; + krb5_data **d; + + ktest_empty_pk_authenticator(&p->pkAuthenticator); + ktest_empty_data(&p->clientPublicValue); + if (p->supportedCMSTypes != NULL) { + for (ai = p->supportedCMSTypes; *ai != NULL; ai++) { + ktest_empty_algorithm_identifier(*ai); + free(*ai); + } + free(p->supportedCMSTypes); + p->supportedCMSTypes = NULL; + } + ktest_empty_data(&p->clientDHNonce); + if (p->supportedKDFs != NULL) { + for (d = p->supportedKDFs; *d != NULL; d++) { + ktest_empty_data(*d); + free(*d); + } + free(p->supportedKDFs); + p->supportedKDFs = NULL; + } +} + +void +ktest_empty_kdc_dh_key_info(krb5_kdc_dh_key_info *p) +{ + ktest_empty_data(&p->subjectPublicKey); +} + +void +ktest_empty_reply_key_pack(krb5_reply_key_pack *p) +{ + ktest_empty_keyblock(&p->replyKey); + ktest_empty_checksum(&p->asChecksum); +} + +void ktest_empty_sp80056a_other_info(krb5_sp80056a_other_info *p) +{ + ktest_empty_algorithm_identifier(&p->algorithm_identifier); + ktest_destroy_principal(&p->party_u_info); + ktest_destroy_principal(&p->party_v_info); + ktest_empty_data(&p->supp_pub_info); +} + +void ktest_empty_pkinit_supp_pub_info(krb5_pkinit_supp_pub_info *p) +{ + ktest_empty_data(&p->as_req); + ktest_empty_data(&p->pk_as_rep); +} + +#endif /* not DISABLE_PKINIT */ + +#ifdef ENABLE_LDAP +void +ktest_empty_ldap_seqof_key_data(krb5_context ctx, ldap_seqof_key_data *p) +{ + int i; + + for (i = 0; i < p->n_key_data; i++) { + free(p->key_data[i].key_data_contents[0]); + free(p->key_data[i].key_data_contents[1]); + } + free(p->key_data); +} +#endif + +void +ktest_empty_kkdcp_message(krb5_kkdcp_message *p) +{ + ktest_empty_data(&p->kerb_message); + ktest_empty_data(&p->target_domain); + p->dclocator_hint = -1; +} + +static void +destroy_verifier_mac(krb5_verifier_mac **vmac) +{ + if (*vmac == NULL) + return; + ktest_destroy_principal(&(*vmac)->princ); + ktest_empty_checksum(&(*vmac)->checksum); + free(*vmac); + *vmac = NULL; +} + +void +ktest_empty_cammac(krb5_cammac *p) +{ + krb5_verifier_mac **vmacp; + + ktest_destroy_authorization_data(&p->elements); + destroy_verifier_mac(&p->kdc_verifier); + destroy_verifier_mac(&p->svc_verifier); + for (vmacp = p->other_verifiers; vmacp != NULL && *vmacp != NULL; vmacp++) + destroy_verifier_mac(vmacp); + free(p->other_verifiers); + p->other_verifiers = NULL; +} + +void +ktest_empty_secure_cookie(krb5_secure_cookie *p) +{ + ktest_empty_pa_data_array(p->data); +} + +void +ktest_empty_spake_factor(krb5_spake_factor *p) +{ + krb5_free_data(NULL, p->data); + p->data = NULL; +} + +void +ktest_empty_pa_spake(krb5_pa_spake *p) +{ + krb5_spake_factor **f; + + switch (p->choice) { + case SPAKE_MSGTYPE_SUPPORT: + free(p->u.support.groups); + break; + case SPAKE_MSGTYPE_CHALLENGE: + ktest_empty_data(&p->u.challenge.pubkey); + for (f = p->u.challenge.factors; *f != NULL; f++) { + ktest_empty_spake_factor(*f); + free(*f); + } + free(p->u.challenge.factors); + break; + case SPAKE_MSGTYPE_RESPONSE: + ktest_empty_data(&p->u.response.pubkey); + ktest_destroy_enc_data(&p->u.response.factor); + break; + case SPAKE_MSGTYPE_ENCDATA: + ktest_destroy_enc_data(&p->u.encdata); + break; + default: + break; + } + p->choice = SPAKE_MSGTYPE_UNKNOWN; +} diff --git a/krb5-1.21.3/src/tests/asn.1/ktest.h b/krb5-1.21.3/src/tests/asn.1/ktest.h new file mode 100644 index 00000000..53180ab8 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/ktest.h @@ -0,0 +1,210 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/asn.1/ktest.h */ +/* + * Copyright (C) 1994 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __KTEST_H__ +#define __KTEST_H__ + +#include "k5-int.h" +#include "k5-spake.h" +#include "kdb.h" + +#define SAMPLE_USEC 123456 +#define SAMPLE_TIME 771228197 /* Fri Jun 10 6:03:17 GMT 1994 */ +#define SAMPLE_SEQ_NUMBER 17 +#define SAMPLE_NONCE 42 +#define SAMPLE_FLAGS 0xFEDCBA98 +#define SAMPLE_ERROR 0x3C; + +void ktest_make_sample_data(krb5_data *d); +void ktest_make_sample_authenticator(krb5_authenticator *a); +void ktest_make_sample_principal(krb5_principal *p); +void ktest_make_sample_checksum(krb5_checksum *cs); +void ktest_make_sample_keyblock(krb5_keyblock *kb); +void ktest_make_sample_ticket(krb5_ticket *tkt); +void ktest_make_sample_enc_data(krb5_enc_data *ed); +void ktest_make_sample_enc_tkt_part(krb5_enc_tkt_part *etp); +void ktest_make_sample_transited(krb5_transited *t); +void ktest_make_sample_ticket_times(krb5_ticket_times *tt); +void ktest_make_sample_addresses(krb5_address ***caddrs); +void ktest_make_sample_address(krb5_address *a); +void ktest_make_sample_authorization_data(krb5_authdata ***ad); +void ktest_make_sample_authdata(krb5_authdata *ad); +void ktest_make_sample_enc_kdc_rep_part(krb5_enc_kdc_rep_part *ekr); +void ktest_make_sample_kdc_req(krb5_kdc_req *kr); + +void ktest_make_sample_last_req(krb5_last_req_entry ***lr); +void ktest_make_sample_last_req_entry(krb5_last_req_entry **lre); +void ktest_make_sample_kdc_rep(krb5_kdc_rep *kdcr); +void ktest_make_sample_pa_data_array(krb5_pa_data ***pad); +void ktest_make_sample_empty_pa_data_array(krb5_pa_data ***pad); +void ktest_make_sample_pa_data(krb5_pa_data *pad); +void ktest_make_sample_ap_req(krb5_ap_req *ar); +void ktest_make_sample_ap_rep(krb5_ap_rep *ar); +void ktest_make_sample_ap_rep_enc_part(krb5_ap_rep_enc_part *arep); +void ktest_make_sample_kdc_req_body(krb5_kdc_req *krb); +void ktest_make_sample_safe(krb5_safe *s); +void ktest_make_sample_priv(krb5_priv *p); +void ktest_make_sample_priv_enc_part(krb5_priv_enc_part *pep); +void ktest_make_sample_cred(krb5_cred *c); +void ktest_make_sample_cred_enc_part(krb5_cred_enc_part *cep); +void ktest_make_sample_sequence_of_ticket(krb5_ticket ***sot); +void ktest_make_sample_error(krb5_error *kerr); +void ktest_make_sequence_of_cred_info(krb5_cred_info ***soci); +void ktest_make_sample_cred_info(krb5_cred_info *ci); + +void ktest_make_sample_etype_info(krb5_etype_info_entry ***p); +void ktest_make_sample_etype_info2(krb5_etype_info_entry ***p); +void ktest_make_sample_pa_enc_ts(krb5_pa_enc_ts *am); +void ktest_make_sample_sam_challenge_2(krb5_sam_challenge_2 *p); +void ktest_make_sample_sam_challenge_2_body(krb5_sam_challenge_2_body *p); +void ktest_make_sample_sam_response_2(krb5_sam_response_2 *p); +void ktest_make_sample_enc_sam_response_enc_2(krb5_enc_sam_response_enc_2 *p); +void ktest_make_sample_pa_for_user(krb5_pa_for_user *p); +void ktest_make_sample_pa_s4u_x509_user(krb5_pa_s4u_x509_user *p); +void ktest_make_sample_ad_kdcissued(krb5_ad_kdcissued *p); +void ktest_make_sample_iakerb_header(krb5_iakerb_header *p); +void ktest_make_sample_iakerb_finished(krb5_iakerb_finished *p); +void ktest_make_sample_fast_response(krb5_fast_response *p); +void ktest_make_sha256_alg(krb5_algorithm_identifier *p); +void ktest_make_sha1_alg(krb5_algorithm_identifier *p); +void ktest_make_minimal_otp_tokeninfo(krb5_otp_tokeninfo *p); +void ktest_make_maximal_otp_tokeninfo(krb5_otp_tokeninfo *p); +void ktest_make_minimal_pa_otp_challenge(krb5_pa_otp_challenge *p); +void ktest_make_maximal_pa_otp_challenge(krb5_pa_otp_challenge *p); +void ktest_make_minimal_pa_otp_req(krb5_pa_otp_req *p); +void ktest_make_maximal_pa_otp_req(krb5_pa_otp_req *p); + +#ifndef DISABLE_PKINIT +void ktest_make_sample_pa_pk_as_req(krb5_pa_pk_as_req *p); +void ktest_make_sample_pa_pk_as_rep_dhInfo(krb5_pa_pk_as_rep *p); +void ktest_make_sample_pa_pk_as_rep_encKeyPack(krb5_pa_pk_as_rep *p); +void ktest_make_sample_auth_pack(krb5_auth_pack *p); +void ktest_make_sample_kdc_dh_key_info(krb5_kdc_dh_key_info *p); +void ktest_make_sample_reply_key_pack(krb5_reply_key_pack *p); +void ktest_make_sample_sp80056a_other_info(krb5_sp80056a_other_info *p); +void ktest_make_sample_pkinit_supp_pub_info(krb5_pkinit_supp_pub_info *p); +#endif + +#ifdef ENABLE_LDAP +void ktest_make_sample_ldap_seqof_key_data(ldap_seqof_key_data *p); +#endif + +void ktest_make_sample_kkdcp_message(krb5_kkdcp_message *p); +void ktest_make_minimal_cammac(krb5_cammac *p); +void ktest_make_maximal_cammac(krb5_cammac *p); +void ktest_make_sample_secure_cookie(krb5_secure_cookie *p); +void ktest_make_minimal_spake_factor(krb5_spake_factor *p); +void ktest_make_maximal_spake_factor(krb5_spake_factor *p); +void ktest_make_support_pa_spake(krb5_pa_spake *p); +void ktest_make_challenge_pa_spake(krb5_pa_spake *p); +void ktest_make_response_pa_spake(krb5_pa_spake *p); +void ktest_make_encdata_pa_spake(krb5_pa_spake *p); + +/*----------------------------------------------------------------------*/ + +void ktest_empty_authorization_data(krb5_authdata **ad); +void ktest_destroy_authorization_data(krb5_authdata ***ad); +void ktest_destroy_authorization_data(krb5_authdata ***ad); +void ktest_empty_addresses(krb5_address **a); +void ktest_destroy_addresses(krb5_address ***a); +void ktest_destroy_address(krb5_address **a); +void ktest_empty_pa_data_array(krb5_pa_data **pad); +void ktest_destroy_pa_data_array(krb5_pa_data ***pad); +void ktest_destroy_pa_data(krb5_pa_data **pad); + +void ktest_destroy_data(krb5_data **d); +void ktest_empty_data(krb5_data *d); +void ktest_destroy_principal(krb5_principal *p); +void ktest_destroy_checksum(krb5_checksum **cs); +void ktest_empty_keyblock(krb5_keyblock *kb); +void ktest_destroy_keyblock(krb5_keyblock **kb); +void ktest_destroy_authdata(krb5_authdata **ad); +void ktest_destroy_sequence_of_integer(long **soi); +void ktest_destroy_sequence_of_ticket(krb5_ticket ***sot); +void ktest_destroy_ticket(krb5_ticket **tkt); +void ktest_empty_ticket(krb5_ticket *tkt); +void ktest_destroy_enc_data(krb5_enc_data *ed); +void ktest_empty_error(krb5_error *kerr); +void ktest_destroy_etype_info_entry(krb5_etype_info_entry *i); +void ktest_destroy_etype_info(krb5_etype_info_entry **info); + +void ktest_empty_kdc_req(krb5_kdc_req *kr); +void ktest_empty_kdc_rep(krb5_kdc_rep *kr); + +void ktest_empty_authenticator(krb5_authenticator *a); +void ktest_empty_enc_tkt_part(krb5_enc_tkt_part *etp); +void ktest_destroy_enc_tkt_part(krb5_enc_tkt_part **etp); +void ktest_empty_enc_kdc_rep_part(krb5_enc_kdc_rep_part *ekr); +void ktest_destroy_transited(krb5_transited *t); +void ktest_empty_ap_rep(krb5_ap_rep *ar); +void ktest_empty_ap_req(krb5_ap_req *ar); +void ktest_empty_cred_enc_part(krb5_cred_enc_part *cep); +void ktest_destroy_cred_info(krb5_cred_info **ci); +void ktest_destroy_sequence_of_cred_info(krb5_cred_info ***soci); +void ktest_empty_safe(krb5_safe *s); +void ktest_empty_priv(krb5_priv *p); +void ktest_empty_priv_enc_part(krb5_priv_enc_part *pep); +void ktest_empty_cred(krb5_cred *c); +void ktest_destroy_last_req(krb5_last_req_entry ***lr); +void ktest_empty_ap_rep_enc_part(krb5_ap_rep_enc_part *arep); +void ktest_empty_sam_challenge_2(krb5_sam_challenge_2 *p); +void ktest_empty_sam_challenge_2_body(krb5_sam_challenge_2_body *p); +void ktest_empty_sam_response_2(krb5_sam_response_2 *p); +void ktest_empty_enc_sam_response_enc_2(krb5_enc_sam_response_enc_2 *p); +void ktest_empty_pa_for_user(krb5_pa_for_user *p); +void ktest_empty_pa_s4u_x509_user(krb5_pa_s4u_x509_user *p); +void ktest_empty_ad_kdcissued(krb5_ad_kdcissued *p); +void ktest_empty_iakerb_header(krb5_iakerb_header *p); +void ktest_empty_iakerb_finished(krb5_iakerb_finished *p); +void ktest_empty_fast_response(krb5_fast_response *p); +void ktest_empty_otp_tokeninfo(krb5_otp_tokeninfo *p); +void ktest_empty_pa_otp_challenge(krb5_pa_otp_challenge *p); +void ktest_empty_pa_otp_req(krb5_pa_otp_req *p); + +#ifndef DISABLE_PKINIT +void ktest_empty_pa_pk_as_req(krb5_pa_pk_as_req *p); +void ktest_empty_pa_pk_as_rep(krb5_pa_pk_as_rep *p); +void ktest_empty_auth_pack(krb5_auth_pack *p); +void ktest_empty_kdc_dh_key_info(krb5_kdc_dh_key_info *p); +void ktest_empty_reply_key_pack(krb5_reply_key_pack *p); +void ktest_empty_sp80056a_other_info(krb5_sp80056a_other_info *p); +void ktest_empty_pkinit_supp_pub_info(krb5_pkinit_supp_pub_info *p); +#endif + +#ifdef ENABLE_LDAP +void ktest_empty_ldap_seqof_key_data(krb5_context, ldap_seqof_key_data *p); +#endif + +void ktest_empty_kkdcp_message(krb5_kkdcp_message *p); +void ktest_empty_cammac(krb5_cammac *p); +void ktest_empty_secure_cookie(krb5_secure_cookie *p); +void ktest_empty_spake_factor(krb5_spake_factor *p); +void ktest_empty_pa_spake(krb5_pa_spake *p); + +extern krb5_context test_context; +extern char *sample_principal_name; + +#endif diff --git a/krb5-1.21.3/src/tests/asn.1/ktest_equal.c b/krb5-1.21.3/src/tests/asn.1/ktest_equal.c new file mode 100644 index 00000000..b48a0285 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/ktest_equal.c @@ -0,0 +1,1054 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/asn.1/ktest_equal.c */ +/* + * Copyright (C) 1994 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include "ktest_equal.h" + +#define FALSE 0 +#define TRUE 1 + +#define struct_equal(field,comparator) \ + comparator(&(ref->field),&(var->field)) + +#define ptr_equal(field,comparator) \ + comparator(ref->field,var->field) + +#define scalar_equal(field) \ + ((ref->field) == (var->field)) + +#define len_equal(length,field,comparator) \ + ((ref->length == var->length) && \ + comparator(ref->length,ref->field,var->field)) + +int +ktest_equal_authenticator(krb5_authenticator *ref, krb5_authenticator *var) +{ + int p = TRUE; + + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && ptr_equal(client,ktest_equal_principal_data); + p = p && ptr_equal(checksum,ktest_equal_checksum); + p = p && scalar_equal(cusec); + p = p && scalar_equal(ctime); + p = p && ptr_equal(subkey,ktest_equal_keyblock); + p = p && scalar_equal(seq_number); + p = p && ptr_equal(authorization_data,ktest_equal_authorization_data); + return p; +} + +int +ktest_equal_principal_data(krb5_principal_data *ref, krb5_principal_data *var) +{ + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + return(struct_equal(realm,ktest_equal_data) && + len_equal(length,data,ktest_equal_array_of_data) && + scalar_equal(type)); +} + +int +ktest_equal_authdata(krb5_authdata *ref, krb5_authdata *var) +{ + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + return(scalar_equal(ad_type) && + len_equal(length,contents,ktest_equal_array_of_octet)); +} + +int +ktest_equal_checksum(krb5_checksum *ref, krb5_checksum *var) +{ + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + return(scalar_equal(checksum_type) && len_equal(length,contents,ktest_equal_array_of_octet)); +} + +int +ktest_equal_keyblock(krb5_keyblock *ref, krb5_keyblock *var) +{ + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + return(scalar_equal(enctype) && len_equal(length,contents,ktest_equal_array_of_octet)); +} + +int +ktest_equal_data(krb5_data *ref, krb5_data *var) +{ + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + return(len_equal(length,data,ktest_equal_array_of_char)); +} + +int +ktest_equal_ticket(krb5_ticket *ref, krb5_ticket *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && ptr_equal(server,ktest_equal_principal_data); + p = p && struct_equal(enc_part,ktest_equal_enc_data); + /* enc_part2 is irrelevant, as far as the ASN.1 code is concerned */ + return p; +} + +int +ktest_equal_enc_data(krb5_enc_data *ref, krb5_enc_data *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(enctype); + p = p && scalar_equal(kvno); + p = p && struct_equal(ciphertext,ktest_equal_data); + return p; +} + +int +ktest_equal_encryption_key(krb5_keyblock *ref, krb5_keyblock *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(enctype); + p = p && len_equal(length,contents,ktest_equal_array_of_octet); + return p; +} + +int +ktest_equal_enc_tkt_part(krb5_enc_tkt_part *ref, krb5_enc_tkt_part *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(flags); + p = p && ptr_equal(session,ktest_equal_encryption_key); + p = p && ptr_equal(client,ktest_equal_principal_data); + p = p && struct_equal(transited,ktest_equal_transited); + p = p && struct_equal(times,ktest_equal_ticket_times); + p = p && ptr_equal(caddrs,ktest_equal_addresses); + p = p && ptr_equal(authorization_data,ktest_equal_authorization_data); + return p; +} + +int +ktest_equal_transited(krb5_transited *ref, krb5_transited *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(tr_type); + p = p && struct_equal(tr_contents,ktest_equal_data); + return p; +} + +int +ktest_equal_ticket_times(krb5_ticket_times *ref, krb5_ticket_times *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(authtime); + p = p && scalar_equal(starttime); + p = p && scalar_equal(endtime); + p = p && scalar_equal(renew_till); + return p; +} + +int +ktest_equal_address(krb5_address *ref, krb5_address *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(addrtype); + p = p && len_equal(length,contents,ktest_equal_array_of_octet); + return p; +} + +int +ktest_equal_enc_kdc_rep_part(krb5_enc_kdc_rep_part *ref, + krb5_enc_kdc_rep_part *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && ptr_equal(session,ktest_equal_keyblock); + p = p && ptr_equal(last_req,ktest_equal_last_req); + p = p && scalar_equal(nonce); + p = p && scalar_equal(key_exp); + p = p && scalar_equal(flags); + p = p && struct_equal(times,ktest_equal_ticket_times); + p = p && ptr_equal(server,ktest_equal_principal_data); + p = p && ptr_equal(caddrs,ktest_equal_addresses); + return p; +} + +int +ktest_equal_priv(krb5_priv *ref, krb5_priv *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(enc_part,ktest_equal_enc_data); + return p; +} + +int +ktest_equal_cred(krb5_cred *ref, krb5_cred *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && ptr_equal(tickets,ktest_equal_sequence_of_ticket); + p = p && struct_equal(enc_part,ktest_equal_enc_data); + return p; +} + +int +ktest_equal_error(krb5_error *ref, krb5_error *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(ctime); + p = p && scalar_equal(cusec); + p = p && scalar_equal(susec); + p = p && scalar_equal(stime); + p = p && scalar_equal(error); + p = p && ptr_equal(client,ktest_equal_principal_data); + p = p && ptr_equal(server,ktest_equal_principal_data); + p = p && struct_equal(text,ktest_equal_data); + p = p && struct_equal(e_data,ktest_equal_data); + return p; +} + +int +ktest_equal_ap_req(krb5_ap_req *ref, krb5_ap_req *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(ap_options); + p = p && ptr_equal(ticket,ktest_equal_ticket); + p = p && struct_equal(authenticator,ktest_equal_enc_data); + return p; +} + +int +ktest_equal_ap_rep(krb5_ap_rep *ref, krb5_ap_rep *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(enc_part,ktest_equal_enc_data); + return p; +} + +int +ktest_equal_ap_rep_enc_part(krb5_ap_rep_enc_part *ref, + krb5_ap_rep_enc_part *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(ctime); + p = p && scalar_equal(cusec); + p = p && ptr_equal(subkey,ktest_equal_encryption_key); + p = p && scalar_equal(seq_number); + return p; +} + +int +ktest_equal_safe(krb5_safe *ref, krb5_safe *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(user_data,ktest_equal_data); + p = p && scalar_equal(timestamp); + p = p && scalar_equal(usec); + p = p && scalar_equal(seq_number); + p = p && ptr_equal(s_address,ktest_equal_address); + p = p && ptr_equal(r_address,ktest_equal_address); + p = p && ptr_equal(checksum,ktest_equal_checksum); + return p; +} + + +int +ktest_equal_enc_cred_part(krb5_cred_enc_part *ref, krb5_cred_enc_part *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(nonce); + p = p && scalar_equal(timestamp); + p = p && scalar_equal(usec); + p = p && ptr_equal(s_address,ktest_equal_address); + p = p && ptr_equal(r_address,ktest_equal_address); + p = p && ptr_equal(ticket_info,ktest_equal_sequence_of_cred_info); + return p; +} + +int +ktest_equal_enc_priv_part(krb5_priv_enc_part *ref, krb5_priv_enc_part *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(user_data,ktest_equal_data); + p = p && scalar_equal(timestamp); + p = p && scalar_equal(usec); + p = p && scalar_equal(seq_number); + p = p && ptr_equal(s_address,ktest_equal_address); + p = p && ptr_equal(r_address,ktest_equal_address); + return p; +} + +int +ktest_equal_as_rep(krb5_kdc_rep *ref, krb5_kdc_rep *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(msg_type); + p = p && ptr_equal(padata,ktest_equal_sequence_of_pa_data); + p = p && ptr_equal(client,ktest_equal_principal_data); + p = p && ptr_equal(ticket,ktest_equal_ticket); + p = p && struct_equal(enc_part,ktest_equal_enc_data); + p = p && ptr_equal(enc_part2,ktest_equal_enc_kdc_rep_part); + return p; +} + +int +ktest_equal_tgs_rep(krb5_kdc_rep *ref, krb5_kdc_rep *var) +{ + return ktest_equal_as_rep(ref,var); +} + +int +ktest_equal_as_req(krb5_kdc_req *ref, krb5_kdc_req *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(msg_type); + p = p && ptr_equal(padata,ktest_equal_sequence_of_pa_data); + p = p && scalar_equal(kdc_options); + p = p && ptr_equal(client,ktest_equal_principal_data); + p = p && ptr_equal(server,ktest_equal_principal_data); + p = p && scalar_equal(from); + p = p && scalar_equal(till); + p = p && scalar_equal(rtime); + p = p && scalar_equal(nonce); + p = p && len_equal(nktypes,ktype,ktest_equal_array_of_enctype); + p = p && ptr_equal(addresses,ktest_equal_addresses); + p = p && struct_equal(authorization_data,ktest_equal_enc_data); +/* This field isn't actually in the ASN.1 encoding. */ +/* p = p && ptr_equal(unenc_authdata,ktest_equal_authorization_data); */ + return p; +} + +int +ktest_equal_tgs_req(krb5_kdc_req *ref, krb5_kdc_req *var) +{ + return ktest_equal_as_req(ref,var); +} + +int +ktest_equal_kdc_req_body(krb5_kdc_req *ref, krb5_kdc_req *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(kdc_options); + p = p && ptr_equal(client,ktest_equal_principal_data); + p = p && ptr_equal(server,ktest_equal_principal_data); + p = p && scalar_equal(from); + p = p && scalar_equal(till); + p = p && scalar_equal(rtime); + p = p && scalar_equal(nonce); + p = p && len_equal(nktypes,ktype,ktest_equal_array_of_enctype); + p = p && ptr_equal(addresses,ktest_equal_addresses); + p = p && struct_equal(authorization_data,ktest_equal_enc_data); + /* This isn't part of the ASN.1 encoding. */ + /* p = p && ptr_equal(unenc_authdata,ktest_equal_authorization_data); */ + return p; +} + +int +ktest_equal_last_req_entry(krb5_last_req_entry *ref, krb5_last_req_entry *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(lr_type); + p = p && scalar_equal(value); + return p; +} + +int +ktest_equal_pa_data(krb5_pa_data *ref, krb5_pa_data *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(pa_type); + p = p && len_equal(length,contents,ktest_equal_array_of_octet); + return p; +} + +int +ktest_equal_cred_info(krb5_cred_info *ref, krb5_cred_info *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && ptr_equal(session,ktest_equal_keyblock); + p = p && ptr_equal(client,ktest_equal_principal_data); + p = p && ptr_equal(server,ktest_equal_principal_data); + p = p && scalar_equal(flags); + p = p && struct_equal(times,ktest_equal_ticket_times); + p = p && ptr_equal(caddrs,ktest_equal_addresses); + + return p; +} + +int +ktest_equal_krb5_etype_info_entry(krb5_etype_info_entry *ref, + krb5_etype_info_entry *var) +{ + if (ref->etype != var->etype) + return FALSE; + if (ref->length != var->length) + return FALSE; + if (ref->length > 0 && ref->length != KRB5_ETYPE_NO_SALT) + if (memcmp(ref->salt, var->salt, ref->length) != 0) + return FALSE; + return TRUE; +} + +int +ktest_equal_krb5_pa_enc_ts(krb5_pa_enc_ts *ref, krb5_pa_enc_ts *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(patimestamp); + p = p && scalar_equal(pausec); + return p; +} + +#define equal_str(f) struct_equal(f,ktest_equal_data) + +int +ktest_equal_sam_challenge_2_body(krb5_sam_challenge_2_body *ref, + krb5_sam_challenge_2_body *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(sam_type); + p = p && scalar_equal(sam_flags); + p = p && equal_str(sam_type_name); + p = p && equal_str(sam_track_id); + p = p && equal_str(sam_challenge_label); + p = p && equal_str(sam_challenge); + p = p && equal_str(sam_response_prompt); + p = p && equal_str(sam_pk_for_sad); + p = p && scalar_equal(sam_nonce); + p = p && scalar_equal(sam_etype); + return p; +} + +int +ktest_equal_sam_challenge_2(krb5_sam_challenge_2 *ref, + krb5_sam_challenge_2 *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && equal_str(sam_challenge_2_body); + p = p && ptr_equal(sam_cksum,ktest_equal_sequence_of_checksum); + return p; +} + +int +ktest_equal_pa_for_user(krb5_pa_for_user *ref, krb5_pa_for_user *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && ptr_equal(user, ktest_equal_principal_data); + p = p && struct_equal(cksum, ktest_equal_checksum); + p = p && equal_str(auth_package); + return p; +} + +int +ktest_equal_pa_s4u_x509_user(krb5_pa_s4u_x509_user *ref, + krb5_pa_s4u_x509_user *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(user_id.nonce); + p = p && ptr_equal(user_id.user,ktest_equal_principal_data); + p = p && struct_equal(user_id.subject_cert,ktest_equal_data); + p = p && scalar_equal(user_id.options); + p = p && struct_equal(cksum,ktest_equal_checksum); + return p; +} + +int +ktest_equal_ad_kdcissued(krb5_ad_kdcissued *ref, krb5_ad_kdcissued *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(ad_checksum,ktest_equal_checksum); + p = p && ptr_equal(i_principal,ktest_equal_principal_data); + p = p && ptr_equal(elements,ktest_equal_authorization_data); + return p; +} + +int +ktest_equal_iakerb_header(krb5_iakerb_header *ref, krb5_iakerb_header *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(target_realm,ktest_equal_data); + p = p && ptr_equal(cookie,ktest_equal_data); + return p; +} + +int +ktest_equal_iakerb_finished(krb5_iakerb_finished *ref, + krb5_iakerb_finished *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(checksum,ktest_equal_checksum); + return p; +} + +static int +ktest_equal_fast_finished(krb5_fast_finished *ref, krb5_fast_finished *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(timestamp); + p = p && scalar_equal(usec); + p = p && ptr_equal(client, ktest_equal_principal_data); + p = p && struct_equal(ticket_checksum, ktest_equal_checksum); + return p; +} + +int +ktest_equal_fast_response(krb5_fast_response *ref, krb5_fast_response *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && ptr_equal(padata, ktest_equal_sequence_of_pa_data); + p = p && ptr_equal(strengthen_key, ktest_equal_keyblock); + p = p && ptr_equal(finished, ktest_equal_fast_finished); + p = p && scalar_equal(nonce); + return p; +} + +static int +ktest_equal_algorithm_identifier(krb5_algorithm_identifier *ref, + krb5_algorithm_identifier *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && equal_str(algorithm); + p = p && equal_str(parameters); + return p; +} + +int +ktest_equal_otp_tokeninfo(krb5_otp_tokeninfo *ref, krb5_otp_tokeninfo *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(flags); + p = p && equal_str(vendor); + p = p && equal_str(challenge); + p = p && scalar_equal(length); + p = p && scalar_equal(format); + p = p && equal_str(token_id); + p = p && equal_str(alg_id); + p = p && ptr_equal(supported_hash_alg, + ktest_equal_sequence_of_algorithm_identifier); + p = p && scalar_equal(iteration_count); + return p; +} + +int +ktest_equal_pa_otp_challenge(krb5_pa_otp_challenge *ref, + krb5_pa_otp_challenge *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && equal_str(nonce); + p = p && equal_str(service); + p = p && ptr_equal(tokeninfo, ktest_equal_sequence_of_otp_tokeninfo); + p = p && equal_str(salt); + p = p && equal_str(s2kparams); + return p; +} + +int +ktest_equal_pa_otp_req(krb5_pa_otp_req *ref, krb5_pa_otp_req *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(flags); + p = p && equal_str(nonce); + p = p && struct_equal(enc_data, ktest_equal_enc_data); + p = p && ptr_equal(hash_alg, ktest_equal_algorithm_identifier); + p = p && scalar_equal(iteration_count); + p = p && equal_str(otp_value); + p = p && equal_str(pin); + p = p && equal_str(challenge); + p = p && scalar_equal(time); + p = p && equal_str(counter); + p = p && scalar_equal(format); + p = p && equal_str(token_id); + p = p && equal_str(alg_id); + p = p && equal_str(vendor); + return p; +} + +#ifdef ENABLE_LDAP +static int +equal_key_data(krb5_key_data *ref, krb5_key_data *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(key_data_type[0]); + p = p && scalar_equal(key_data_type[1]); + p = p && len_equal(key_data_length[0],key_data_contents[0], + ktest_equal_array_of_octet); + p = p && len_equal(key_data_length[1],key_data_contents[1], + ktest_equal_array_of_octet); + return p; +} + +static int +equal_key_data_array(int n, krb5_key_data *ref, krb5_key_data *val) +{ + int i, p = TRUE; + for (i = 0; i < n; i++) { + p = p && equal_key_data(ref+i, val+i); + } + return p; +} + +int +ktest_equal_ldap_sequence_of_keys(ldap_seqof_key_data *ref, + ldap_seqof_key_data *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(mkvno); + p = p && scalar_equal(kvno); + p = p && len_equal(n_key_data,key_data,equal_key_data_array); + return p; +} +#endif + +/**** arrays ****************************************************************/ + +int +ktest_equal_array_of_data(int length, krb5_data *ref, krb5_data *var) +{ + int i,p = TRUE; + + if (length == 0 || ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + for (i=0; i<(length); i++) { + p = p && ktest_equal_data(&(ref[i]),&(var[i])); + } + return p; +} + +int +ktest_equal_array_of_octet(unsigned int length, krb5_octet *ref, + krb5_octet *var) +{ + unsigned int i, p = TRUE; + + if (length == 0 || ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + for (i=0; ichoice != var->choice) return FALSE; + if (ref->choice == choice_pa_pk_as_rep_dhInfo) + p = p && struct_equal(u.dh_Info, ktest_equal_dh_rep_info); + else if (ref->choice == choice_pa_pk_as_rep_encKeyPack) + p = p && equal_str(u.encKeyPack); + return p; +} + +static int +ktest_equal_sequence_of_data(krb5_data **ref, krb5_data **var) +{ + array_compare(ktest_equal_data); +} + +int +ktest_equal_auth_pack(krb5_auth_pack *ref, krb5_auth_pack *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(pkAuthenticator, ktest_equal_pk_authenticator); + p = p && equal_str(clientPublicValue); + p = p && ptr_equal(supportedCMSTypes, + ktest_equal_sequence_of_algorithm_identifier); + p = p && equal_str(clientDHNonce); + p = p && ptr_equal(supportedKDFs, ktest_equal_sequence_of_data); + return p; +} + +int +ktest_equal_kdc_dh_key_info(krb5_kdc_dh_key_info *ref, + krb5_kdc_dh_key_info *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && equal_str(subjectPublicKey); + p = p && scalar_equal(nonce); + p = p && scalar_equal(dhKeyExpiration); + return p; +} + +int +ktest_equal_reply_key_pack(krb5_reply_key_pack *ref, krb5_reply_key_pack *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(replyKey, ktest_equal_keyblock); + p = p && struct_equal(asChecksum, ktest_equal_checksum); + return p; +} + +#endif /* not DISABLE_PKINIT */ + +int +ktest_equal_kkdcp_message(krb5_kkdcp_message *ref, krb5_kkdcp_message *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && data_eq(ref->kerb_message, var->kerb_message); + p = p && data_eq(ref->target_domain, var->target_domain); + p = p && scalar_equal(dclocator_hint); + return p; +} + +static int +vmac_eq(krb5_verifier_mac *ref, krb5_verifier_mac *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && ptr_equal(princ, ktest_equal_principal_data); + p = p && scalar_equal(kvno); + p = p && scalar_equal(enctype); + p = p && struct_equal(checksum, ktest_equal_checksum); + return p; +} + +static int +vmac_list_eq(krb5_verifier_mac **ref, krb5_verifier_mac **var) +{ + array_compare(vmac_eq); +} + +int +ktest_equal_cammac(krb5_cammac *ref, krb5_cammac *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && ptr_equal(elements, ktest_equal_authorization_data); + p = p && ptr_equal(kdc_verifier, vmac_eq); + p = p && ptr_equal(svc_verifier, vmac_eq); + p = p && ptr_equal(other_verifiers, vmac_list_eq); + return p; +} + +int +ktest_equal_secure_cookie(krb5_secure_cookie *ref, krb5_secure_cookie *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && ktest_equal_sequence_of_pa_data(ref->data, var->data); + p = p && scalar_equal(time); + return p; +} + +int +ktest_equal_spake_factor(krb5_spake_factor *ref, krb5_spake_factor *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(type); + p = p && ptr_equal(data,ktest_equal_data); + return p; +} + +int +ktest_equal_pa_spake(krb5_pa_spake *ref, krb5_pa_spake *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + else if (ref->choice != var->choice) return FALSE; + switch (ref->choice) { + case SPAKE_MSGTYPE_SUPPORT: + p = p && scalar_equal(u.support.ngroups); + p = p && (memcmp(ref->u.support.groups,var->u.support.groups, + ref->u.support.ngroups * sizeof(int32_t)) == 0); + break; + case SPAKE_MSGTYPE_CHALLENGE: + p = p && struct_equal(u.challenge.pubkey,ktest_equal_data); + p = p && ptr_equal(u.challenge.factors, + ktest_equal_sequence_of_spake_factor); + break; + case SPAKE_MSGTYPE_RESPONSE: + p = p && struct_equal(u.response.pubkey,ktest_equal_data); + p = p && struct_equal(u.response.factor,ktest_equal_enc_data); + break; + case SPAKE_MSGTYPE_ENCDATA: + p = p && struct_equal(u.encdata,ktest_equal_enc_data); + break; + default: + break; + } + return p; +} diff --git a/krb5-1.21.3/src/tests/asn.1/ktest_equal.h b/krb5-1.21.3/src/tests/asn.1/ktest_equal.h new file mode 100644 index 00000000..8c15cc0c --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/ktest_equal.h @@ -0,0 +1,154 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/asn.1/ktest_equal.h */ +/* + * Copyright (C) 1994 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __KTEST_EQUAL_H__ +#define __KTEST_EQUAL_H__ + +#include "k5-int.h" +#include "k5-spake.h" +#include "kdb.h" + +/* int ktest_equal_structure(krb5_structure *ref, *var) */ +/* effects Returns true (non-zero) if ref and var are + semantically equivalent (i.e. have the same values, + but aren't necessarily the same object). + Returns false (zero) if ref and var differ. */ + +#define generic(funcname,type)\ +int funcname (type *ref, type *var) + +#define len_array(funcname,type)\ +int funcname (int length, type *ref, type *var) +#define len_unsigned_array(funcname,type)\ +int funcname (unsigned int length, type *ref, type *var) + +generic(ktest_equal_authenticator,krb5_authenticator); +generic(ktest_equal_principal_data,krb5_principal_data); +generic(ktest_equal_checksum,krb5_checksum); +generic(ktest_equal_keyblock,krb5_keyblock); +generic(ktest_equal_data,krb5_data); +generic(ktest_equal_authdata,krb5_authdata); +generic(ktest_equal_ticket,krb5_ticket); +generic(ktest_equal_enc_tkt_part,krb5_enc_tkt_part); +generic(ktest_equal_transited,krb5_transited); +generic(ktest_equal_ticket_times,krb5_ticket_times); +generic(ktest_equal_address,krb5_address); +generic(ktest_equal_enc_data,krb5_enc_data); + +generic(ktest_equal_enc_kdc_rep_part,krb5_enc_kdc_rep_part); +generic(ktest_equal_priv,krb5_priv); +generic(ktest_equal_cred,krb5_cred); +generic(ktest_equal_error,krb5_error); +generic(ktest_equal_ap_req,krb5_ap_req); +generic(ktest_equal_ap_rep,krb5_ap_rep); +generic(ktest_equal_ap_rep_enc_part,krb5_ap_rep_enc_part); +generic(ktest_equal_safe,krb5_safe); + +generic(ktest_equal_last_req_entry,krb5_last_req_entry); +generic(ktest_equal_pa_data,krb5_pa_data); +generic(ktest_equal_cred_info,krb5_cred_info); + +generic(ktest_equal_enc_cred_part,krb5_cred_enc_part); +generic(ktest_equal_enc_priv_part,krb5_priv_enc_part); +generic(ktest_equal_as_rep,krb5_kdc_rep); +generic(ktest_equal_tgs_rep,krb5_kdc_rep); +generic(ktest_equal_as_req,krb5_kdc_req); +generic(ktest_equal_tgs_req,krb5_kdc_req); +generic(ktest_equal_kdc_req_body,krb5_kdc_req); +generic(ktest_equal_encryption_key,krb5_keyblock); + +generic(ktest_equal_krb5_pa_enc_ts,krb5_pa_enc_ts); + +generic(ktest_equal_sam_challenge_2,krb5_sam_challenge_2); +generic(ktest_equal_sam_challenge_2_body,krb5_sam_challenge_2_body); + +int ktest_equal_last_req(krb5_last_req_entry **ref, krb5_last_req_entry **var); +int ktest_equal_sequence_of_ticket(krb5_ticket **ref, krb5_ticket **var); +int ktest_equal_sequence_of_pa_data(krb5_pa_data **ref, krb5_pa_data **var); +int ktest_equal_sequence_of_cred_info(krb5_cred_info **ref, + krb5_cred_info **var); +int ktest_equal_sequence_of_principal(krb5_principal *ref, + krb5_principal *var); +int ktest_equal_sequence_of_checksum(krb5_checksum **ref, krb5_checksum **var); +int +ktest_equal_sequence_of_algorithm_identifier(krb5_algorithm_identifier **ref, + krb5_algorithm_identifier **var); +int ktest_equal_sequence_of_otp_tokeninfo(krb5_otp_tokeninfo **ref, + krb5_otp_tokeninfo **var); +int ktest_equal_sequence_of_spake_factor(krb5_spake_factor **ref, + krb5_spake_factor **var); + +len_array(ktest_equal_array_of_enctype,krb5_enctype); +len_array(ktest_equal_array_of_data,krb5_data); +len_unsigned_array(ktest_equal_array_of_octet,krb5_octet); + +int ktest_equal_authorization_data(krb5_authdata **ref, krb5_authdata **var); +int ktest_equal_addresses(krb5_address **ref, krb5_address **var); +int ktest_equal_array_of_char(const unsigned int length, char *ref, char *var); + +int ktest_equal_etype_info(krb5_etype_info_entry **ref, + krb5_etype_info_entry **var); + +int ktest_equal_krb5_etype_info_entry(krb5_etype_info_entry *ref, + krb5_etype_info_entry *var); +int ktest_equal_pa_for_user(krb5_pa_for_user *ref, krb5_pa_for_user *var); +int ktest_equal_pa_s4u_x509_user(krb5_pa_s4u_x509_user *ref, + krb5_pa_s4u_x509_user *var); +int ktest_equal_ad_kdcissued(krb5_ad_kdcissued *ref, krb5_ad_kdcissued *var); +int ktest_equal_iakerb_header(krb5_iakerb_header *ref, + krb5_iakerb_header *var); +int ktest_equal_iakerb_finished(krb5_iakerb_finished *ref, + krb5_iakerb_finished *var); +int ktest_equal_fast_response(krb5_fast_response *ref, + krb5_fast_response *var); +int ktest_equal_otp_tokeninfo(krb5_otp_tokeninfo *ref, + krb5_otp_tokeninfo *var); +int ktest_equal_pa_otp_challenge(krb5_pa_otp_challenge *ref, + krb5_pa_otp_challenge *var); +int ktest_equal_pa_otp_req(krb5_pa_otp_req *ref, krb5_pa_otp_req *var); + +int ktest_equal_ldap_sequence_of_keys(ldap_seqof_key_data *ref, + ldap_seqof_key_data *var); + +#ifndef DISABLE_PKINIT +generic(ktest_equal_pa_pk_as_req, krb5_pa_pk_as_req); +generic(ktest_equal_pa_pk_as_rep, krb5_pa_pk_as_rep); +generic(ktest_equal_auth_pack, krb5_auth_pack); +generic(ktest_equal_kdc_dh_key_info, krb5_kdc_dh_key_info); +generic(ktest_equal_reply_key_pack, krb5_reply_key_pack); +#endif /* not DISABLE_PKINIT */ + +int ktest_equal_kkdcp_message(krb5_kkdcp_message *ref, + krb5_kkdcp_message *var); +int ktest_equal_cammac(krb5_cammac *ref, krb5_cammac *var); + +int ktest_equal_secure_cookie(krb5_secure_cookie *ref, + krb5_secure_cookie *var); + +generic(ktest_equal_spake_factor, krb5_spake_factor); +generic(ktest_equal_pa_spake, krb5_pa_spake); + +#endif diff --git a/krb5-1.21.3/src/tests/asn.1/ldap_encode.out b/krb5-1.21.3/src/tests/asn.1/ldap_encode.out new file mode 100644 index 00000000..41dbc1e6 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/ldap_encode.out @@ -0,0 +1 @@ +encode_krb5_ldap_seqof_key_data: 30 81 87 A0 03 02 01 01 A1 03 02 01 01 A2 03 02 01 2A A3 03 02 01 0E A4 71 30 6F 30 23 A0 10 30 0E A0 03 02 01 00 A1 07 04 05 73 61 6C 74 30 A1 0F 30 0D A0 03 02 01 02 A1 06 04 04 6B 65 79 30 30 23 A0 10 30 0E A0 03 02 01 01 A1 07 04 05 73 61 6C 74 31 A1 0F 30 0D A0 03 02 01 02 A1 06 04 04 6B 65 79 31 30 23 A0 10 30 0E A0 03 02 01 02 A1 07 04 05 73 61 6C 74 32 A1 0F 30 0D A0 03 02 01 02 A1 06 04 04 6B 65 79 32 diff --git a/krb5-1.21.3/src/tests/asn.1/ldap_trval.out b/krb5-1.21.3/src/tests/asn.1/ldap_trval.out new file mode 100644 index 00000000..16ea7371 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/ldap_trval.out @@ -0,0 +1,30 @@ + +encode_krb5_ldap_seqof_key_data: + +[Sequence/Sequence Of] +. [0] [Integer] 1 +. [1] [Integer] 1 +. [2] [Integer] 42 +. [3] [Integer] 14 +. [4] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [0] [Sequence/Sequence Of] +. . . . [0] [Integer] 0 +. . . . [1] [Octet String] "salt0" +. . . [1] [Sequence/Sequence Of] +. . . . [0] [Integer] 2 +. . . . [1] [Octet String] "key0" +. . [Sequence/Sequence Of] +. . . [0] [Sequence/Sequence Of] +. . . . [0] [Integer] 1 +. . . . [1] [Octet String] "salt1" +. . . [1] [Sequence/Sequence Of] +. . . . [0] [Integer] 2 +. . . . [1] [Octet String] "key1" +. . [Sequence/Sequence Of] +. . . [0] [Sequence/Sequence Of] +. . . . [0] [Integer] 2 +. . . . [1] [Octet String] "salt2" +. . . [1] [Sequence/Sequence Of] +. . . . [0] [Integer] 2 +. . . . [1] [Octet String] "key2" diff --git a/krb5-1.21.3/src/tests/asn.1/make-vectors.c b/krb5-1.21.3/src/tests/asn.1/make-vectors.c new file mode 100644 index 00000000..2fc85466 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/make-vectors.c @@ -0,0 +1,333 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/asn.1/make-vectors.c - Generate ASN.1 test vectors using asn1c */ +/* + * Copyright (C) 2011 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * This program generates test vectors using asn1c, to be included in other + * test programs which exercise the krb5 ASN.1 encoder and decoder functions. + * It is intended to be used via "make test-vectors". Currently, test vectors + * are only generated for a subset of newer ASN.1 objects. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned char buf[8192]; +static size_t buf_pos; + +/* PrincipalName and KRB5PrincipalName */ +static KerberosString_t comp_1 = { "hftsai", 6 }; +static KerberosString_t comp_2 = { "extra", 5 }; +static KerberosString_t *comps[] = { &comp_1, &comp_2 }; +static PrincipalName_t princ = { 1, { comps, 2, 2 } }; +static KRB5PrincipalName_t krb5princ = { { "ATHENA.MIT.EDU", 14 }, + { 1, { comps, 2, 2 } } }; + +/* OtherInfo */ +static unsigned int krb5_arcs[] = { 1, 2, 840, 113554, 1, 2, 2 }; +static OCTET_STRING_t krb5data_ostring = { "krb5data", 8 }; +static OtherInfo_t other_info = { + { 0 }, { 0 }, { 0 }, /* Initialized in main() */ + &krb5data_ostring, NULL +}; + +/* PkinitSuppPubInfo */ +static PkinitSuppPubInfo_t supp_pub_info = { 1, { "krb5data", 8 }, + { "krb5data", 8 } }; + +/* Minimal OTP-TOKENINFO */ +static OTP_TOKENINFO_t token_info_1 = { { "\0\0\0\0", 4, 0 } }; + +/* Maximal OTP-TOKENINFO */ +static UTF8String_t vendor = { "Examplecorp", 11 }; +static OCTET_STRING_t challenge = { "hark!", 5 }; +static Int32_t otp_length = 10; +static OTPFormat_t otp_format; /* Initialized to 2 in main(). */ +static OCTET_STRING_t token_id = { "yourtoken", 9 }; +static AnyURI_t otp_alg = { "urn:ietf:params:xml:ns:keyprov:pskc:hotp", 40 }; +static unsigned int sha256_arcs[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 }; +static unsigned int sha1_arcs[] = { 1, 3, 14, 3, 2, 26 }; +static AlgorithmIdentifier_t alg_sha256, alg_sha1; /* Initialized in main(). */ +static AlgorithmIdentifier_t *algs[] = { &alg_sha256, &alg_sha1 }; +static struct supportedHashAlg hash_algs = { algs, 2, 2 }; +static Int32_t iter_count = 1000; +/* Flags are nextOTP | combine | collect-pin | must-encrypt-nonce | + * separate-pin-required | check-digit */ +static OTP_TOKENINFO_t token_info_2 = { { "\x77\0\0\0", 4, 0 }, &vendor, + &challenge, &otp_length, &otp_format, + &token_id, &otp_alg, &hash_algs, + &iter_count }; + +/* Minimal PA-OTP-CHALLENGE */ +static OTP_TOKENINFO_t *tinfo_1[] = { &token_info_1 }; +static PA_OTP_CHALLENGE_t challenge_1 = { { "minnonce", 8 }, NULL, + { { tinfo_1, 1, 1 } } }; + +/* Maximal PA-OTP-CHALLENGE */ +static OTP_TOKENINFO_t *tinfo_2[] = { &token_info_1, &token_info_2 }; +static UTF8String_t service = { "testservice", 11 }; +static KerberosString_t salt = { "keysalt", 7 }; +static OCTET_STRING_t s2kparams = { "1234", 4 }; +static PA_OTP_CHALLENGE_t challenge_2 = { { "maxnonce", 8 }, &service, + { { tinfo_2, 2, 2 } }, &salt, + &s2kparams }; + +/* Minimal PA-OTP-REQUEST */ +static UInt32_t kvno = 5; +static PA_OTP_REQUEST_t request_1 = { { "\0\0\0\0", 4, 0 }, NULL, + { 0, &kvno, + { "krbASN.1 test message", 21 } } }; + +/* Maximal PA-OTP-REQUEST */ +/* Flags are nextOTP | combine */ +static OCTET_STRING_t nonce = { "nonce", 5 }; +static OCTET_STRING_t otp_value = { "frogs", 5 }; +static UTF8String_t otp_pin = { "myfirstpin", 10 }; +/* Corresponds to Unix time 771228197 */ +static KerberosTime_t otp_time = { "19940610060317Z", 15 }; +static OCTET_STRING_t counter = { "346", 3 }; +static PA_OTP_REQUEST_t request_2 = { { "\x60\0\0\0", 4, 0 }, &nonce, + { 0, &kvno, + { "krbASN.1 test message", 21 } }, + &alg_sha256, &iter_count, &otp_value, + &otp_pin, &challenge, &otp_time, + &counter, &otp_format, &token_id, + &otp_alg, &vendor }; + +/* PA-OTP-ENC-REQUEST */ +static PA_OTP_ENC_REQUEST_t enc_request = { { "krb5data", 8 } }; + +/* + * There is no ASN.1 name for a single authorization data element, so asn1c + * declares it as "struct Member" in an inner scope. This structure must be + * laid out identically to that one. + */ +struct ad_element { + Int32_t ad_type; + OCTET_STRING_t ad_data; + asn_struct_ctx_t _asn_ctx; +}; + +/* Authorization data elements and lists, for use in CAMMAC */ +static struct ad_element ad_1 = { 1, { "ad1", 3 } }; +static struct ad_element ad_2 = { 2, { "ad2", 3 } }; +static struct ad_element *adlist_1[] = { &ad_1 }; +static struct ad_element *adlist_2[] = { &ad_1, &ad_2 }; + +/* Minimal Verifier */ +static Verifier_t verifier_1 = { Verifier_PR_mac, + { { NULL, NULL, NULL, + { 1, { "cksum1", 6 } } } } }; + +/* Maximal Verifier */ +static Int32_t enctype = 16; +static Verifier_t verifier_2 = { Verifier_PR_mac, + { { &princ, &kvno, &enctype, + { 1, { "cksum2", 6 } } } } }; + +/* Minimal CAMMAC */ +static AD_CAMMAC_t cammac_1 = { { { (void *)adlist_1, 1, 1 } }, + NULL, NULL, NULL }; + +/* Maximal CAMMAC */ +static Verifier_MAC_t vmac_1 = { &princ, &kvno, &enctype, + { 1, { "cksumkdc", 8 } } }; +static Verifier_MAC_t vmac_2 = { &princ, &kvno, &enctype, + { 1, { "cksumsvc", 8 } } }; +static Verifier_t *verifiers[] = { &verifier_1, &verifier_2 }; +static struct other_verifiers overfs = { { verifiers, 2, 2 } }; +static AD_CAMMAC_t cammac_2 = { { { (void *)adlist_2, 2, 2 } }, + &vmac_1, &vmac_2, &overfs }; + +/* SPAKESecondFactor */ +static SPAKESecondFactor_t factor_1 = { 1, NULL }; +static OCTET_STRING_t factor_data = { "fdata", 5 }; +static SPAKESecondFactor_t factor_2 = { 2, &factor_data }; + +/* PA-SPAKE (support) */ +static Int32_t group_1 = 1, group_2 = 2, *groups[] = { &group_1, &group_2 }; +static PA_SPAKE_t pa_spake_1 = { PA_SPAKE_PR_support, + { .support = { { groups, 2, 2 } } } }; + +/* PA-SPAKE (challenge) */ +static SPAKESecondFactor_t *factors[2] = { &factor_1, &factor_2 }; +static PA_SPAKE_t pa_spake_2 = { PA_SPAKE_PR_challenge, + { .challenge = { 1, { "T value", 7 }, + { factors, 2, 2 } } } }; + +/* PA-SPAKE (response) */ +UInt32_t enctype_5 = 5; +static PA_SPAKE_t pa_spake_3 = { PA_SPAKE_PR_response, + { .response = { { "S value", 7 }, + { 0, &enctype_5, + { "krbASN.1 test message", + 21 } } } } }; + +/* PA-SPAKE (encdata) */ +static PA_SPAKE_t pa_spake_4 = { PA_SPAKE_PR_encdata, + { .encdata = { 0, &enctype_5, + { "krbASN.1 test message", + 21 } } } }; + +static int +consume(const void *data, size_t size, void *dummy) +{ + memcpy(buf + buf_pos, data, size); + buf_pos += size; + return 0; +} + +/* Display a C string literal representing the contents of buf, and + * reinitialize buf_pos for the next encoding operation. */ +static void +printbuf(void) +{ + size_t i; + + for (i = 0; i < buf_pos; i++) { + printf("%02X", buf[i]); + if (i + 1 < buf_pos) + printf(" "); + } + buf_pos = 0; +} + +int +main() +{ + /* Initialize values which can't use static initializers. */ + asn_long2INTEGER(&otp_format, 2); /* Alphanumeric */ + OBJECT_IDENTIFIER_set_arcs(&alg_sha256.algorithm, sha256_arcs, + sizeof(*sha256_arcs), + sizeof(sha256_arcs) / sizeof(*sha256_arcs)); + OBJECT_IDENTIFIER_set_arcs(&alg_sha1.algorithm, sha1_arcs, + sizeof(*sha1_arcs), + sizeof(sha1_arcs) / sizeof(*sha1_arcs)); + OBJECT_IDENTIFIER_set_arcs(&other_info.algorithmID.algorithm, krb5_arcs, + sizeof(*krb5_arcs), + sizeof(krb5_arcs) / sizeof(*krb5_arcs)); + + printf("PrincipalName:\n"); + der_encode(&asn_DEF_PrincipalName, &princ, consume, NULL); + printbuf(); + + /* Print this encoding and also use it to initialize two fields of + * other_info. */ + printf("\nKRB5PrincipalName:\n"); + der_encode(&asn_DEF_KRB5PrincipalName, &krb5princ, consume, NULL); + OCTET_STRING_fromBuf(&other_info.partyUInfo, buf, buf_pos); + OCTET_STRING_fromBuf(&other_info.partyVInfo, buf, buf_pos); + printbuf(); + + printf("\nOtherInfo:\n"); + der_encode(&asn_DEF_OtherInfo, &other_info, consume, NULL); + printbuf(); + free(other_info.partyUInfo.buf); + free(other_info.partyVInfo.buf); + + printf("\nPkinitSuppPubInfo:\n"); + der_encode(&asn_DEF_PkinitSuppPubInfo, &supp_pub_info, consume, NULL); + printbuf(); + + printf("\nMinimal OTP-TOKEN-INFO:\n"); + der_encode(&asn_DEF_OTP_TOKENINFO, &token_info_1, consume, NULL); + printbuf(); + + printf("\nMaximal OTP-TOKEN-INFO:\n"); + der_encode(&asn_DEF_OTP_TOKENINFO, &token_info_2, consume, NULL); + printbuf(); + + printf("\nMinimal PA-OTP-CHALLENGE:\n"); + der_encode(&asn_DEF_PA_OTP_CHALLENGE, &challenge_1, consume, NULL); + printbuf(); + + printf("\nMaximal PA-OTP-CHALLENGE:\n"); + der_encode(&asn_DEF_PA_OTP_CHALLENGE, &challenge_2, consume, NULL); + printbuf(); + + printf("\nMinimal PA-OTP-REQUEST:\n"); + der_encode(&asn_DEF_PA_OTP_REQUEST, &request_1, consume, NULL); + printbuf(); + + printf("\nMaximal PA-OTP-REQUEST:\n"); + der_encode(&asn_DEF_PA_OTP_REQUEST, &request_2, consume, NULL); + printbuf(); + + printf("\nPA-OTP-ENC-REQUEST:\n"); + der_encode(&asn_DEF_PA_OTP_ENC_REQUEST, &enc_request, consume, NULL); + printbuf(); + + printf("\nMinimal Verifier:\n"); + der_encode(&asn_DEF_Verifier, &verifier_1, consume, NULL); + printbuf(); + + printf("\nMaximal Verifier:\n"); + der_encode(&asn_DEF_Verifier, &verifier_2, consume, NULL); + printbuf(); + + printf("\nMinimal AD-CAMMAC:\n"); + der_encode(&asn_DEF_AD_CAMMAC, &cammac_1, consume, NULL); + printbuf(); + + printf("\nMaximal AD-CAMMAC:\n"); + der_encode(&asn_DEF_AD_CAMMAC, &cammac_2, consume, NULL); + printbuf(); + + printf("\nMinimal SPAKESecondFactor:\n"); + der_encode(&asn_DEF_SPAKESecondFactor, &factor_1, consume, NULL); + printbuf(); + + printf("\nMaximal SPAKESecondFactor:\n"); + der_encode(&asn_DEF_SPAKESecondFactor, &factor_2, consume, NULL); + printbuf(); + + printf("\nPA-SPAKE (support):\n"); + der_encode(&asn_DEF_PA_SPAKE, &pa_spake_1, consume, NULL); + printbuf(); + + printf("\nPA-SPAKE (challenge):\n"); + der_encode(&asn_DEF_PA_SPAKE, &pa_spake_2, consume, NULL); + printbuf(); + + printf("\nPA-SPAKE (response):\n"); + der_encode(&asn_DEF_PA_SPAKE, &pa_spake_3, consume, NULL); + printbuf(); + + printf("\nPA-SPAKE (encdata):\n"); + der_encode(&asn_DEF_PA_SPAKE, &pa_spake_4, consume, NULL); + printbuf(); + + printf("\n"); + return 0; +} diff --git a/krb5-1.21.3/src/tests/asn.1/otp.asn1 b/krb5-1.21.3/src/tests/asn.1/otp.asn1 new file mode 100644 index 00000000..2e324322 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/otp.asn1 @@ -0,0 +1,109 @@ + OTPKerberos + DEFINITIONS IMPLICIT TAGS ::= + BEGIN + + IMPORTS + + KerberosTime, KerberosFlags, EncryptionKey, Int32, + EncryptedData, LastReq, KerberosString + FROM KerberosV5Spec2 {iso(1) identified-organization(3) + dod(6) internet(1) security(5) + kerberosV5(2) modules(4) krb5spec2(2)} + -- as defined in RFC 4120. + AlgorithmIdentifier + FROM PKIX1Explicit88 { iso (1) identified-organization (3) + dod (6) internet (1) + security (5) mechanisms (5) pkix (7) + id-mod (0) id-pkix1-explicit (18) }; + -- As defined in RFC 5280. + + PA-OTP-CHALLENGE ::= SEQUENCE { + nonce [0] OCTET STRING, + otp-service [1] UTF8String OPTIONAL, + otp-tokenInfo [2] SEQUENCE (SIZE(1..MAX)) OF + OTP-TOKENINFO, + salt [3] KerberosString OPTIONAL, + s2kparams [4] OCTET STRING OPTIONAL, + ... + } + + OTP-TOKENINFO ::= SEQUENCE { + flags [0] OTPFlags, + otp-vendor [1] UTF8String OPTIONAL, + otp-challenge [2] OCTET STRING (SIZE(1..MAX)) + OPTIONAL, + otp-length [3] Int32 OPTIONAL, + otp-format [4] OTPFormat OPTIONAL, + otp-tokenID [5] OCTET STRING OPTIONAL, + otp-algID [6] AnyURI OPTIONAL, + supportedHashAlg [7] SEQUENCE OF AlgorithmIdentifier + OPTIONAL, + iterationCount [8] Int32 OPTIONAL, + ... + } + + OTPFormat ::= INTEGER { + decimal(0), + hexadecimal(1), + alphanumeric(2), + binary(3), + base64(4) + } + + OTPFlags ::= KerberosFlags + -- reserved(0), + -- nextOTP(1), + -- combine(2), + -- collect-pin(3), + -- do-not-collect-pin(4), + -- must-encrypt-nonce (5), + -- separate-pin-required (6), + -- check-digit (7) + + PA-OTP-REQUEST ::= SEQUENCE { + flags [0] OTPFlags, + nonce [1] OCTET STRING OPTIONAL, + encData [2] EncryptedData, + -- PA-OTP-ENC-REQUEST or PA-ENC-TS-ENC + -- Key usage of KEY_USAGE_OTP_REQUEST + hashAlg [3] AlgorithmIdentifier OPTIONAL, + iterationCount [4] Int32 OPTIONAL, + otp-value [5] OCTET STRING OPTIONAL, + otp-pin [6] UTF8String OPTIONAL, + otp-challenge [7] OCTET STRING (SIZE(1..MAX)) OPTIONAL, + otp-time [8] KerberosTime OPTIONAL, + otp-counter [9] OCTET STRING OPTIONAL, + otp-format [10] OTPFormat OPTIONAL, + otp-tokenID [11] OCTET STRING OPTIONAL, + otp-algID [12] AnyURI OPTIONAL, + otp-vendor [13] UTF8String OPTIONAL, + ... + } + + PA-OTP-ENC-REQUEST ::= SEQUENCE { + nonce [0] OCTET STRING, + ... + } + + + PA-OTP-PIN-CHANGE ::= SEQUENCE { + flags [0] PinFlags, + pin [1] UTF8String OPTIONAL, + minLength [2] INTEGER OPTIONAL, + maxLength [3] INTEGER OPTIONAL, + last-req [4] LastReq OPTIONAL, + format [5] OTPFormat OPTIONAL, + ... + } + + PinFlags ::= KerberosFlags + -- reserved(0), + -- systemSetPin(1), + -- mandatory(2) + + AnyURI ::= UTF8String + (CONSTRAINED BY { + -- MUST be a valid URI in accordance with IETF RFC 2396 + }) + + END diff --git a/krb5-1.21.3/src/tests/asn.1/pkinit-agility.asn1 b/krb5-1.21.3/src/tests/asn.1/pkinit-agility.asn1 new file mode 100644 index 00000000..ea9095b0 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/pkinit-agility.asn1 @@ -0,0 +1,99 @@ +KerberosV5-PK-INIT-Agility-SPEC { + iso(1) identified-organization(3) dod(6) internet(1) + security(5) kerberosV5(2) modules(4) pkinit(5) agility (1) +} DEFINITIONS EXPLICIT TAGS ::= BEGIN + +IMPORTS + AlgorithmIdentifier, SubjectPublicKeyInfo + FROM PKIX1Explicit88 { iso (1) + identified-organization (3) dod (6) internet (1) + security (5) mechanisms (5) pkix (7) id-mod (0) + id-pkix1-explicit (18) } + -- As defined in RFC 3280. + + Ticket, Int32, Realm, EncryptionKey, Checksum + FROM KerberosV5Spec2 { iso(1) identified-organization(3) + dod(6) internet(1) security(5) kerberosV5(2) + modules(4) krb5spec2(2) } + -- as defined in RFC 4120. + + PKAuthenticator, DHNonce + FROM KerberosV5-PK-INIT-SPEC { + iso(1) identified-organization(3) dod(6) internet(1) + security(5) kerberosV5(2) modules(4) pkinit(5) }; + -- as defined in RFC 4556. + +TD-CMS-DIGEST-ALGORITHMS-DATA ::= SEQUENCE OF + AlgorithmIdentifier + -- Contains the list of CMS algorithm [RFC3852] + -- identifiers that identify the digest algorithms + -- acceptable by the KDC for signing CMS data in + -- the order of decreasing preference. + +TD-CERT-DIGEST-ALGORITHMS-DATA ::= SEQUENCE { + allowedAlgorithms [0] SEQUENCE OF AlgorithmIdentifier, + -- Contains the list of CMS algorithm [RFC3852] + -- identifiers that identify the digest algorithms + -- that are used by the CA to sign the client's + -- X.509 certificate and acceptable by the KDC in + -- the process of validating the client's X.509 + -- certificate, in the order of decreasing + -- preference. + rejectedAlgorithm [1] AlgorithmIdentifier OPTIONAL, + -- This identifies the digest algorithm that was + -- used to sign the client's X.509 certificate and + -- has been rejected by the KDC in the process of + -- validating the client's X.509 certificate + -- [RFC3280]. + ... +} + +OtherInfo ::= SEQUENCE { + algorithmID AlgorithmIdentifier, + partyUInfo [0] OCTET STRING, + partyVInfo [1] OCTET STRING, + suppPubInfo [2] OCTET STRING OPTIONAL, + suppPrivInfo [3] OCTET STRING OPTIONAL +} + +PkinitSuppPubInfo ::= SEQUENCE { + enctype [0] Int32, + -- The enctype of the AS reply key. + as-REQ [1] OCTET STRING, + -- This contains the AS-REQ in the request. + pk-as-rep [2] OCTET STRING, + -- Contains the DER encoding of the type + -- PA-PK-AS-REP [RFC4556] in the KDC reply. + ... +} + +-- Renamed from AuthPack to allow asn1c to process this and pkinit.asn1 +AuthPack2 ::= SEQUENCE { + pkAuthenticator [0] PKAuthenticator, + clientPublicValue [1] SubjectPublicKeyInfo OPTIONAL, + supportedCMSTypes [2] SEQUENCE OF AlgorithmIdentifier + OPTIONAL, + clientDHNonce [3] DHNonce OPTIONAL, + ..., + supportedKDFs [4] SEQUENCE OF KDFAlgorithmId OPTIONAL, + -- Contains an unordered set of KDFs supported by the + -- client. + ... +} + +KDFAlgorithmId ::= SEQUENCE { + kdf-id [0] OBJECT IDENTIFIER, + -- The object identifier of the KDF + ... +} + +-- Renamed from DHRepInfo to allow asn1c to process this and pkinit.asn1 +DHRepInfo2 ::= SEQUENCE { + dhSignedData [0] IMPLICIT OCTET STRING, + serverDHNonce [1] DHNonce OPTIONAL, + ..., + kdf [2] KDFAlgorithmId OPTIONAL, + -- The KDF picked by the KDC. + ... +} +END diff --git a/krb5-1.21.3/src/tests/asn.1/pkinit.asn1 b/krb5-1.21.3/src/tests/asn.1/pkinit.asn1 new file mode 100644 index 00000000..8f9d8dda --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/pkinit.asn1 @@ -0,0 +1,253 @@ +KerberosV5-PK-INIT-SPEC { + iso(1) identified-organization(3) dod(6) internet(1) + security(5) kerberosV5(2) modules(4) pkinit(5) +} DEFINITIONS EXPLICIT TAGS ::= BEGIN + +IMPORTS + + SubjectPublicKeyInfo, AlgorithmIdentifier + FROM PKIX1Explicit88 { iso (1) + identified-organization (3) dod (6) internet (1) + security (5) mechanisms (5) pkix (7) id-mod (0) + id-pkix1-explicit (18) } + -- As defined in RFC 3280. + + KerberosTime, PrincipalName, Realm, EncryptionKey, Checksum + FROM KerberosV5Spec2 { iso(1) identified-organization(3) + dod(6) internet(1) security(5) kerberosV5(2) + modules(4) krb5spec2(2) }; + -- as defined in RFC 4120. + +id-pkinit OBJECT IDENTIFIER ::= + { iso(1) identified-organization(3) dod(6) internet(1) + security(5) kerberosv5(2) pkinit (3) } + +id-pkinit-authData OBJECT IDENTIFIER ::= { id-pkinit 1 } +id-pkinit-DHKeyData OBJECT IDENTIFIER ::= { id-pkinit 2 } +id-pkinit-rkeyData OBJECT IDENTIFIER ::= { id-pkinit 3 } +id-pkinit-KPClientAuth OBJECT IDENTIFIER ::= { id-pkinit 4 } +id-pkinit-KPKdc OBJECT IDENTIFIER ::= { id-pkinit 5 } + +id-pkinit-san OBJECT IDENTIFIER ::= + { iso(1) org(3) dod(6) internet(1) security(5) kerberosv5(2) + x509SanAN (2) } + +pa-pk-as-req INTEGER ::= 16 +pa-pk-as-rep INTEGER ::= 17 + +ad-initial-verified-cas INTEGER ::= 9 + +td-trusted-certifiers INTEGER ::= 104 +td-invalid-certificates INTEGER ::= 105 +td-dh-parameters INTEGER ::= 109 + +PA-PK-AS-REQ ::= SEQUENCE { + signedAuthPack [0] IMPLICIT OCTET STRING, + -- Contains a CMS type ContentInfo encoded + -- according to [RFC3852]. + -- The contentType field of the type ContentInfo + -- is id-signedData (1.2.840.113549.1.7.2), + -- and the content field is a SignedData. + -- The eContentType field for the type SignedData is + -- id-pkinit-authData (1.3.6.1.5.2.3.1), and the + -- eContent field contains the DER encoding of the + -- type AuthPack. + -- AuthPack is defined below. + trustedCertifiers [1] SEQUENCE OF + ExternalPrincipalIdentifier OPTIONAL, + -- Contains a list of CAs, trusted by the client, + -- that can be used to certify the KDC. + -- Each ExternalPrincipalIdentifier identifies a CA + -- or a CA certificate (thereby its public key). + -- The information contained in the + -- trustedCertifiers SHOULD be used by the KDC as + -- hints to guide its selection of an appropriate + -- certificate chain to return to the client. + kdcPkId [2] IMPLICIT OCTET STRING + OPTIONAL, + -- Contains a CMS type SignerIdentifier encoded + -- according to [RFC3852]. + -- Identifies, if present, a particular KDC + -- public key that the client already has. + ... +} + +DHNonce ::= OCTET STRING + +ExternalPrincipalIdentifier ::= SEQUENCE { + subjectName [0] IMPLICIT OCTET STRING OPTIONAL, + -- Contains a PKIX type Name encoded according to + -- [RFC3280]. + -- Identifies the certificate subject by the + -- distinguished subject name. + -- REQUIRED when there is a distinguished subject + -- name present in the certificate. + issuerAndSerialNumber [1] IMPLICIT OCTET STRING OPTIONAL, + -- Contains a CMS type IssuerAndSerialNumber encoded + -- according to [RFC3852]. + -- Identifies a certificate of the subject. + -- REQUIRED for TD-INVALID-CERTIFICATES and + -- TD-TRUSTED-CERTIFIERS. + subjectKeyIdentifier [2] IMPLICIT OCTET STRING OPTIONAL, + -- Identifies the subject's public key by a key + -- identifier. When an X.509 certificate is + -- referenced, this key identifier matches the X.509 + -- subjectKeyIdentifier extension value. When other + -- certificate formats are referenced, the documents + -- that specify the certificate format and their use + -- with the CMS must include details on matching the + -- key identifier to the appropriate certificate + -- field. + -- RECOMMENDED for TD-TRUSTED-CERTIFIERS. + ... +} + +AuthPack ::= SEQUENCE { + pkAuthenticator [0] PKAuthenticator, + clientPublicValue [1] SubjectPublicKeyInfo OPTIONAL, + -- Type SubjectPublicKeyInfo is defined in + -- [RFC3280]. + -- Specifies Diffie-Hellman domain parameters + -- and the client's public key value [IEEE1363]. + -- The DH public key value is encoded as a BIT + -- STRING according to [RFC3279]. + -- This field is present only if the client wishes + -- to use the Diffie-Hellman key agreement method. + supportedCMSTypes [2] SEQUENCE OF AlgorithmIdentifier + OPTIONAL, + -- Type AlgorithmIdentifier is defined in + -- [RFC3280]. + -- List of CMS algorithm [RFC3370] identifiers + -- that identify key transport algorithms, or + -- content encryption algorithms, or signature + -- algorithms supported by the client in order of + -- (decreasing) preference. + clientDHNonce [3] DHNonce OPTIONAL, + -- Present only if the client indicates that it + -- wishes to reuse DH keys or to allow the KDC to + -- do so. + ... +} + +PKAuthenticator ::= SEQUENCE { + cusec [0] INTEGER (0..999999), + ctime [1] KerberosTime, + -- cusec and ctime are used as in [RFC4120], for + -- replay prevention. + nonce [2] INTEGER (0..4294967295), + -- Chosen randomly; this nonce does not need to + -- match with the nonce in the KDC-REQ-BODY. + paChecksum [3] OCTET STRING OPTIONAL, + -- MUST be present. + -- Contains the SHA1 checksum, performed over + -- KDC-REQ-BODY. + ... +} + +TD-TRUSTED-CERTIFIERS ::= SEQUENCE OF + ExternalPrincipalIdentifier + -- Identifies a list of CAs trusted by the KDC. + -- Each ExternalPrincipalIdentifier identifies a CA + -- or a CA certificate (thereby its public key). + +TD-INVALID-CERTIFICATES ::= SEQUENCE OF + ExternalPrincipalIdentifier + -- Each ExternalPrincipalIdentifier identifies a + -- certificate (sent by the client) with an invalid + -- signature. + +KRB5PrincipalName ::= SEQUENCE { + realm [0] Realm, + principalName [1] PrincipalName +} + +AD-INITIAL-VERIFIED-CAS ::= SEQUENCE OF + ExternalPrincipalIdentifier + -- Identifies the certification path based on which + -- the client certificate was validated. + -- Each ExternalPrincipalIdentifier identifies a CA + -- or a CA certificate (thereby its public key). + +PA-PK-AS-REP ::= CHOICE { + dhInfo [0] DHRepInfo, + -- Selected when Diffie-Hellman key exchange is + -- used. + encKeyPack [1] IMPLICIT OCTET STRING, + -- Selected when public key encryption is used. + -- Contains a CMS type ContentInfo encoded + -- according to [RFC3852]. + -- The contentType field of the type ContentInfo is + -- id-envelopedData (1.2.840.113549.1.7.3). + -- The content field is an EnvelopedData. + -- The contentType field for the type EnvelopedData + -- is id-signedData (1.2.840.113549.1.7.2). + -- The eContentType field for the inner type + -- SignedData (when unencrypted) is + -- id-pkinit-rkeyData (1.3.6.1.5.2.3.3) and the + -- eContent field contains the DER encoding of the + -- type ReplyKeyPack. + -- ReplyKeyPack is defined below. + ... +} + +DHRepInfo ::= SEQUENCE { + dhSignedData [0] IMPLICIT OCTET STRING, + -- Contains a CMS type ContentInfo encoded according + -- to [RFC3852]. + -- The contentType field of the type ContentInfo is + -- id-signedData (1.2.840.113549.1.7.2), and the + -- content field is a SignedData. + -- The eContentType field for the type SignedData is + -- id-pkinit-DHKeyData (1.3.6.1.5.2.3.2), and the + -- eContent field contains the DER encoding of the + -- type KDCDHKeyInfo. + -- KDCDHKeyInfo is defined below. + serverDHNonce [1] DHNonce OPTIONAL, + -- Present if and only if dhKeyExpiration is + -- present. + ... +} + +KDCDHKeyInfo ::= SEQUENCE { + subjectPublicKey [0] BIT STRING, + -- The KDC's DH public key. + -- The DH public key value is encoded as a BIT + -- STRING according to [RFC3279]. + nonce [1] INTEGER (0..4294967295), + -- Contains the nonce in the pkAuthenticator field + -- in the request if the DH keys are NOT reused, + -- 0 otherwise. + dhKeyExpiration [2] KerberosTime OPTIONAL, + -- Expiration time for KDC's key pair, + -- present if and only if the DH keys are reused. + -- If present, the KDC's DH public key MUST not be + -- used past the point of this expiration time. + -- If this field is omitted then the serverDHNonce + -- field MUST also be omitted. + ... +} + +ReplyKeyPack ::= SEQUENCE { + replyKey [0] EncryptionKey, + -- Contains the session key used to encrypt the + -- enc-part field in the AS-REP, i.e., the + -- AS reply key. + asChecksum [1] Checksum, + -- Contains the checksum of the AS-REQ + -- corresponding to the containing AS-REP. + -- The checksum is performed over the type AS-REQ. + -- The protocol key [RFC3961] of the checksum is the + -- replyKey and the key usage number is 6. + -- If the replyKey's enctype is "newer" [RFC4120] + -- [RFC4121], the checksum is the required + -- checksum operation [RFC3961] for that enctype. + -- The client MUST verify this checksum upon receipt + -- of the AS-REP. + ... +} + +TD-DH-PARAMETERS ::= SEQUENCE OF AlgorithmIdentifier + -- Each AlgorithmIdentifier specifies a set of + -- Diffie-Hellman domain parameters [IEEE1363]. + -- This list is in decreasing preference order. +END diff --git a/krb5-1.21.3/src/tests/asn.1/pkinit_encode.out b/krb5-1.21.3/src/tests/asn.1/pkinit_encode.out new file mode 100644 index 00000000..6ec7aaa3 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/pkinit_encode.out @@ -0,0 +1,8 @@ +encode_krb5_pa_pk_as_req: 30 38 80 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 1E 80 08 6B 72 62 35 64 61 74 61 81 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61 +encode_krb5_pa_pk_as_rep(dhInfo): A0 28 30 26 80 08 6B 72 62 35 64 61 74 61 A1 0A 04 08 6B 72 62 35 64 61 74 61 A2 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61 +encode_krb5_pa_pk_as_rep(encKeyPack): 81 08 6B 72 62 35 64 61 74 61 +encode_krb5_auth_pack: 30 81 85 A0 35 30 33 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 06 04 04 31 32 33 34 A4 0A 04 08 6B 72 62 35 64 61 74 61 A1 08 04 06 70 76 61 6C 75 65 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61 +encode_krb5_kdc_dh_key_info: 30 25 A0 0B 03 09 00 6B 72 62 35 64 61 74 61 A1 03 02 01 2A A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A +encode_krb5_reply_key_pack: 30 26 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 +encode_krb5_sp80056a_other_info: 30 81 81 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A0 32 04 30 30 2E A0 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 32 04 30 30 2E A0 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 0A 04 08 6B 72 62 35 64 61 74 61 +encode_krb5_pkinit_supp_pub_info: 30 1D A0 03 02 01 14 A1 0A 04 08 6B 72 62 35 64 61 74 61 A2 0A 04 08 6B 72 62 35 64 61 74 61 diff --git a/krb5-1.21.3/src/tests/asn.1/pkinit_trval.out b/krb5-1.21.3/src/tests/asn.1/pkinit_trval.out new file mode 100644 index 00000000..46f4a341 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/pkinit_trval.out @@ -0,0 +1,97 @@ + +encode_krb5_pa_pk_as_req: + +[Sequence/Sequence Of] +. [0] <8> + 6b 72 62 35 64 61 74 61 krb5data +. [1] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [0] <8> + 6b 72 62 35 64 61 74 61 krb5data +. . . [1] <8> + 6b 72 62 35 64 61 74 61 krb5data +. . . [2] <8> + 6b 72 62 35 64 61 74 61 krb5data +. [2] <8> + 6b 72 62 35 64 61 74 61 krb5data + +encode_krb5_pa_pk_as_rep(dhInfo): + +[CONT 0] +. [Sequence/Sequence Of] +. . [0] <8> + 6b 72 62 35 64 61 74 61 krb5data +. . [1] [Octet String] "krb5data" +. . [2] [Sequence/Sequence Of] +. . . [0] [Object Identifier] <8> + 6b 72 62 35 64 61 74 61 krb5data + +encode_krb5_pa_pk_as_rep(encKeyPack): + +[CONT 1] <8> + 6b 72 62 35 64 61 74 61 krb5data + +encode_krb5_auth_pack: + +[Sequence/Sequence Of] +. [0] [Sequence/Sequence Of] +. . [0] [Integer] 123456 +. . [1] [Generalized Time] "19940610060317Z" +. . [2] [Integer] 42 +. . [3] [Octet String] "1234" +. . [4] [Octet String] "krb5data" +. [1] [Octet String] "pvalue" +. [2] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [Object Identifier] <9> + 2a 86 48 86 f7 12 01 02 02 *.H...... +. . . [Octet String] "params" +. . [Sequence/Sequence Of] +. . . [Object Identifier] <9> + 2a 86 48 86 f7 12 01 02 02 *.H...... +. [3] [Octet String] "krb5data" +. [4] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [0] [Object Identifier] <8> + 6b 72 62 35 64 61 74 61 krb5data + +encode_krb5_kdc_dh_key_info: + +[Sequence/Sequence Of] +. [0] [Bit String] <9> + 00 6b 72 62 35 64 61 74 61 .krb5data +. [1] [Integer] 42 +. [2] [Generalized Time] "19940610060317Z" + +encode_krb5_reply_key_pack: + +[Sequence/Sequence Of] +. [0] [Sequence/Sequence Of] +. . [0] [Integer] 1 +. . [1] [Octet String] "12345678" +. [1] [Sequence/Sequence Of] +. . [0] [Integer] 1 +. . [1] [Octet String] "1234" + +encode_krb5_sp80056a_other_info: + +[Sequence/Sequence Of] +. [Sequence/Sequence Of] +. . [Object Identifier] <9> + 2a 86 48 86 f7 12 01 02 02 *.H...... +. [0] [Octet String] <48> + 30 2e a0 10 1b 0e 41 54 48 45 4e 41 2e 4d 49 54 0.....ATHENA.MIT + 2e 45 44 55 a1 1a 30 18 a0 03 02 01 01 a1 11 30 .EDU..0........0 + 0f 1b 06 68 66 74 73 61 69 1b 05 65 78 74 72 61 ...hftsai..extra +. [1] [Octet String] <48> + 30 2e a0 10 1b 0e 41 54 48 45 4e 41 2e 4d 49 54 0.....ATHENA.MIT + 2e 45 44 55 a1 1a 30 18 a0 03 02 01 01 a1 11 30 .EDU..0........0 + 0f 1b 06 68 66 74 73 61 69 1b 05 65 78 74 72 61 ...hftsai..extra +. [2] [Octet String] "krb5data" + +encode_krb5_pkinit_supp_pub_info: + +[Sequence/Sequence Of] +. [0] [Integer] 20 +. [1] [Octet String] "krb5data" +. [2] [Octet String] "krb5data" diff --git a/krb5-1.21.3/src/tests/asn.1/pkix.asn1 b/krb5-1.21.3/src/tests/asn.1/pkix.asn1 new file mode 100644 index 00000000..03981883 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/pkix.asn1 @@ -0,0 +1,654 @@ +PKIX1Explicit88 { iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-explicit(18) } + +DEFINITIONS EXPLICIT TAGS ::= + +BEGIN + +-- EXPORTS ALL -- + +-- IMPORTS NONE -- + +-- UNIVERSAL Types defined in 1993 and 1998 ASN.1 +-- and required by this specification +-- (Commented out for krb5 source tree) + +-- UniversalString ::= [UNIVERSAL 28] IMPLICIT OCTET STRING + -- UniversalString is defined in ASN.1:1993 + +-- BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING + -- BMPString is the subtype of UniversalString and models + -- the Basic Multilingual Plane of ISO/IEC 10646 + +--UTF8String ::= [UNIVERSAL 12] IMPLICIT OCTET STRING + -- The content of this type conforms to RFC 3629. + +-- PKIX specific OIDs + +id-pkix OBJECT IDENTIFIER ::= + { iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) } + +-- PKIX arcs + +id-pe OBJECT IDENTIFIER ::= { id-pkix 1 } + -- arc for private certificate extensions +id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } + -- arc for policy qualifier types +id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } + -- arc for extended key purpose OIDS +id-ad OBJECT IDENTIFIER ::= { id-pkix 48 } + -- arc for access descriptors + +-- policyQualifierIds for Internet policy qualifiers + +id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } + -- OID for CPS qualifier +id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } + -- OID for user notice qualifier + +-- access descriptor definitions + +id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 } +id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 } +id-ad-timeStamping OBJECT IDENTIFIER ::= { id-ad 3 } +id-ad-caRepository OBJECT IDENTIFIER ::= { id-ad 5 } + +-- attribute data types + +Attribute ::= SEQUENCE { + type AttributeType, + values SET OF AttributeValue } + -- at least one value is required + +AttributeType ::= OBJECT IDENTIFIER + +AttributeValue ::= ANY -- DEFINED BY AttributeType + +AttributeTypeAndValue ::= SEQUENCE { + type AttributeType, + value AttributeValue } + +-- suggested naming attributes: Definition of the following +-- information object set may be augmented to meet local +-- requirements. Note that deleting members of the set may +-- prevent interoperability with conforming implementations. +-- presented in pairs: the AttributeType followed by the +-- type definition for the corresponding AttributeValue + +-- Arc for standard naming attributes + +id-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 } + +-- Naming attributes of type X520name + +id-at-name AttributeType ::= { id-at 41 } +id-at-surname AttributeType ::= { id-at 4 } +id-at-givenName AttributeType ::= { id-at 42 } +id-at-initials AttributeType ::= { id-at 43 } +id-at-generationQualifier AttributeType ::= { id-at 44 } + +-- Naming attributes of type X520Name: +-- X520name ::= DirectoryString (SIZE (1..ub-name)) +-- +-- Expanded to avoid parameterized type: +X520name ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-name)), + printableString PrintableString (SIZE (1..ub-name)), + universalString UniversalString (SIZE (1..ub-name)), + utf8String UTF8String (SIZE (1..ub-name)), + bmpString BMPString (SIZE (1..ub-name)) } + +-- Naming attributes of type X520CommonName + +id-at-commonName AttributeType ::= { id-at 3 } + +-- Naming attributes of type X520CommonName: +-- X520CommonName ::= DirectoryName (SIZE (1..ub-common-name)) +-- +-- Expanded to avoid parameterized type: +X520CommonName ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-common-name)), + printableString PrintableString (SIZE (1..ub-common-name)), + universalString UniversalString (SIZE (1..ub-common-name)), + utf8String UTF8String (SIZE (1..ub-common-name)), + bmpString BMPString (SIZE (1..ub-common-name)) } + +-- Naming attributes of type X520LocalityName + +id-at-localityName AttributeType ::= { id-at 7 } + +-- Naming attributes of type X520LocalityName: +-- X520LocalityName ::= DirectoryName (SIZE (1..ub-locality-name)) +-- +-- Expanded to avoid parameterized type: +X520LocalityName ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-locality-name)), + printableString PrintableString (SIZE (1..ub-locality-name)), + universalString UniversalString (SIZE (1..ub-locality-name)), + utf8String UTF8String (SIZE (1..ub-locality-name)), + bmpString BMPString (SIZE (1..ub-locality-name)) } + +-- Naming attributes of type X520StateOrProvinceName + +id-at-stateOrProvinceName AttributeType ::= { id-at 8 } + +-- Naming attributes of type X520StateOrProvinceName: +-- X520StateOrProvinceName ::= DirectoryName (SIZE (1..ub-state-name)) +-- +-- Expanded to avoid parameterized type: +X520StateOrProvinceName ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-state-name)), + printableString PrintableString (SIZE (1..ub-state-name)), + universalString UniversalString (SIZE (1..ub-state-name)), + utf8String UTF8String (SIZE (1..ub-state-name)), + bmpString BMPString (SIZE (1..ub-state-name)) } + +-- Naming attributes of type X520OrganizationName + +id-at-organizationName AttributeType ::= { id-at 10 } + +-- Naming attributes of type X520OrganizationName: +-- X520OrganizationName ::= +-- DirectoryName (SIZE (1..ub-organization-name)) +-- +-- Expanded to avoid parameterized type: +X520OrganizationName ::= CHOICE { + teletexString TeletexString + (SIZE (1..ub-organization-name)), + printableString PrintableString + (SIZE (1..ub-organization-name)), + universalString UniversalString + (SIZE (1..ub-organization-name)), + utf8String UTF8String + (SIZE (1..ub-organization-name)), + bmpString BMPString + (SIZE (1..ub-organization-name)) } + +-- Naming attributes of type X520OrganizationalUnitName + +id-at-organizationalUnitName AttributeType ::= { id-at 11 } + +-- Naming attributes of type X520OrganizationalUnitName: +-- X520OrganizationalUnitName ::= +-- DirectoryName (SIZE (1..ub-organizational-unit-name)) +-- +-- Expanded to avoid parameterized type: +X520OrganizationalUnitName ::= CHOICE { + teletexString TeletexString + (SIZE (1..ub-organizational-unit-name)), + printableString PrintableString + (SIZE (1..ub-organizational-unit-name)), + universalString UniversalString + (SIZE (1..ub-organizational-unit-name)), + utf8String UTF8String + (SIZE (1..ub-organizational-unit-name)), + bmpString BMPString + (SIZE (1..ub-organizational-unit-name)) } + +-- Naming attributes of type X520Title + +id-at-title AttributeType ::= { id-at 12 } + +-- Naming attributes of type X520Title: +-- X520Title ::= DirectoryName (SIZE (1..ub-title)) +-- +-- Expanded to avoid parameterized type: +X520Title ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-title)), + printableString PrintableString (SIZE (1..ub-title)), + universalString UniversalString (SIZE (1..ub-title)), + utf8String UTF8String (SIZE (1..ub-title)), + bmpString BMPString (SIZE (1..ub-title)) } + +-- Naming attributes of type X520dnQualifier + +id-at-dnQualifier AttributeType ::= { id-at 46 } + +X520dnQualifier ::= PrintableString + +-- Naming attributes of type X520countryName (digraph from IS 3166) + +id-at-countryName AttributeType ::= { id-at 6 } + +X520countryName ::= PrintableString (SIZE (2)) + +-- Naming attributes of type X520SerialNumber + +id-at-serialNumber AttributeType ::= { id-at 5 } + +X520SerialNumber ::= PrintableString (SIZE (1..ub-serial-number)) + +-- Naming attributes of type X520Pseudonym + +id-at-pseudonym AttributeType ::= { id-at 65 } + +-- Naming attributes of type X520Pseudonym: +-- X520Pseudonym ::= DirectoryName (SIZE (1..ub-pseudonym)) +-- +-- Expanded to avoid parameterized type: +X520Pseudonym ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-pseudonym)), + printableString PrintableString (SIZE (1..ub-pseudonym)), + universalString UniversalString (SIZE (1..ub-pseudonym)), + utf8String UTF8String (SIZE (1..ub-pseudonym)), + bmpString BMPString (SIZE (1..ub-pseudonym)) } + +-- Naming attributes of type DomainComponent (from RFC 4519) + +id-domainComponent AttributeType ::= { 0 9 2342 19200300 100 1 25 } + +DomainComponent ::= IA5String + +-- Legacy attributes + +pkcs-9 OBJECT IDENTIFIER ::= + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } + +id-emailAddress AttributeType ::= { pkcs-9 1 } + +EmailAddress ::= IA5String (SIZE (1..ub-emailaddress-length)) + +-- naming data types -- + +Name ::= CHOICE { -- only one possibility for now -- + rdnSequence RDNSequence } + +RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + +DistinguishedName ::= RDNSequence + +RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue + +-- Directory string type -- + +DirectoryString ::= CHOICE { + teletexString TeletexString (SIZE (1..MAX)), + printableString PrintableString (SIZE (1..MAX)), + universalString UniversalString (SIZE (1..MAX)), + utf8String UTF8String (SIZE (1..MAX)), + bmpString BMPString (SIZE (1..MAX)) } + +-- certificate and CRL specific structures begin here + +Certificate ::= SEQUENCE { + tbsCertificate TBSCertificate, + signatureAlgorithm AlgorithmIdentifier, + signature BIT STRING } + +TBSCertificate ::= SEQUENCE { + version [0] Version DEFAULT v1, + serialNumber CertificateSerialNumber, + signature AlgorithmIdentifier, + issuer Name, + validity Validity, + subject Name, + subjectPublicKeyInfo SubjectPublicKeyInfo, + issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + -- If present, version MUST be v2 or v3 + subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + -- If present, version MUST be v2 or v3 + extensions [3] Extensions OPTIONAL + -- If present, version MUST be v3 -- } + +Version ::= INTEGER { v1(0), v2(1), v3(2) } + +CertificateSerialNumber ::= INTEGER + +Validity ::= SEQUENCE { + notBefore Time, + notAfter Time } + +Time ::= CHOICE { + utcTime UTCTime, + generalTime GeneralizedTime } + +UniqueIdentifier ::= BIT STRING + +SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING } + +Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + +Extension ::= SEQUENCE { + extnID OBJECT IDENTIFIER, + critical BOOLEAN DEFAULT FALSE, + extnValue OCTET STRING + -- contains the DER encoding of an ASN.1 value + -- corresponding to the extension type identified + -- by extnID + } + +-- CRL structures + +CertificateList ::= SEQUENCE { + tbsCertList TBSCertList, + signatureAlgorithm AlgorithmIdentifier, + signature BIT STRING } + +TBSCertList ::= SEQUENCE { + version Version OPTIONAL, + -- if present, MUST be v2 + signature AlgorithmIdentifier, + issuer Name, + thisUpdate Time, + nextUpdate Time OPTIONAL, + revokedCertificates SEQUENCE OF SEQUENCE { + userCertificate CertificateSerialNumber, + revocationDate Time, + crlEntryExtensions Extensions OPTIONAL + -- if present, version MUST be v2 + } OPTIONAL, + crlExtensions [0] Extensions OPTIONAL } + -- if present, version MUST be v2 + +-- Version, Time, CertificateSerialNumber, and Extensions were +-- defined earlier for use in the certificate structure + +AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm OPTIONAL } + -- contains a value of the type + -- registered for use with the + -- algorithm object identifier value + +-- X.400 address syntax starts here + +ORAddress ::= SEQUENCE { + built-in-standard-attributes BuiltInStandardAttributes, + built-in-domain-defined-attributes + BuiltInDomainDefinedAttributes OPTIONAL, + -- see also teletex-domain-defined-attributes + extension-attributes ExtensionAttributes OPTIONAL } + +-- Built-in Standard Attributes + +BuiltInStandardAttributes ::= SEQUENCE { + country-name CountryName OPTIONAL, + administration-domain-name AdministrationDomainName OPTIONAL, + network-address [0] IMPLICIT NetworkAddress OPTIONAL, + -- see also extended-network-address + terminal-identifier [1] IMPLICIT TerminalIdentifier OPTIONAL, + private-domain-name [2] PrivateDomainName OPTIONAL, + organization-name [3] IMPLICIT OrganizationName OPTIONAL, + -- see also teletex-organization-name + numeric-user-identifier [4] IMPLICIT NumericUserIdentifier + OPTIONAL, + personal-name [5] IMPLICIT PersonalName OPTIONAL, + -- see also teletex-personal-name + organizational-unit-names [6] IMPLICIT OrganizationalUnitNames + OPTIONAL } + -- see also teletex-organizational-unit-names + +CountryName ::= [APPLICATION 1] CHOICE { + x121-dcc-code NumericString + (SIZE (ub-country-name-numeric-length)), + iso-3166-alpha2-code PrintableString + (SIZE (ub-country-name-alpha-length)) } + +AdministrationDomainName ::= [APPLICATION 2] CHOICE { + numeric NumericString (SIZE (0..ub-domain-name-length)), + printable PrintableString (SIZE (0..ub-domain-name-length)) } + +NetworkAddress ::= X121Address -- see also extended-network-address + +X121Address ::= NumericString (SIZE (1..ub-x121-address-length)) + +TerminalIdentifier ::= PrintableString (SIZE (1..ub-terminal-id-length)) + +PrivateDomainName ::= CHOICE { + numeric NumericString (SIZE (1..ub-domain-name-length)), + printable PrintableString (SIZE (1..ub-domain-name-length)) } + +OrganizationName ::= PrintableString + (SIZE (1..ub-organization-name-length)) + -- see also teletex-organization-name + +NumericUserIdentifier ::= NumericString + (SIZE (1..ub-numeric-user-id-length)) + +PersonalName ::= SET { + surname [0] IMPLICIT PrintableString + (SIZE (1..ub-surname-length)), + given-name [1] IMPLICIT PrintableString + (SIZE (1..ub-given-name-length)) OPTIONAL, + initials [2] IMPLICIT PrintableString + (SIZE (1..ub-initials-length)) OPTIONAL, + generation-qualifier [3] IMPLICIT PrintableString + (SIZE (1..ub-generation-qualifier-length)) + OPTIONAL } + -- see also teletex-personal-name + +OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units) + OF OrganizationalUnitName + -- see also teletex-organizational-unit-names + +OrganizationalUnitName ::= PrintableString (SIZE + (1..ub-organizational-unit-name-length)) + +-- Built-in Domain-defined Attributes + +BuiltInDomainDefinedAttributes ::= SEQUENCE SIZE + (1..ub-domain-defined-attributes) OF + BuiltInDomainDefinedAttribute + +BuiltInDomainDefinedAttribute ::= SEQUENCE { + type PrintableString (SIZE + (1..ub-domain-defined-attribute-type-length)), + value PrintableString (SIZE + (1..ub-domain-defined-attribute-value-length)) } + +-- Extension Attributes + +ExtensionAttributes ::= SET SIZE (1..ub-extension-attributes) OF + ExtensionAttribute + +ExtensionAttribute ::= SEQUENCE { + extension-attribute-type [0] IMPLICIT INTEGER + (0..ub-extension-attributes), + extension-attribute-value [1] + ANY DEFINED BY extension-attribute-type } + +-- Extension types and attribute values + +common-name INTEGER ::= 1 + +CommonName ::= PrintableString (SIZE (1..ub-common-name-length)) + +teletex-common-name INTEGER ::= 2 + +TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length)) + +teletex-organization-name INTEGER ::= 3 + +TeletexOrganizationName ::= + TeletexString (SIZE (1..ub-organization-name-length)) + +teletex-personal-name INTEGER ::= 4 + +TeletexPersonalName ::= SET { + surname [0] IMPLICIT TeletexString + (SIZE (1..ub-surname-length)), + given-name [1] IMPLICIT TeletexString + (SIZE (1..ub-given-name-length)) OPTIONAL, + initials [2] IMPLICIT TeletexString + (SIZE (1..ub-initials-length)) OPTIONAL, + generation-qualifier [3] IMPLICIT TeletexString + (SIZE (1..ub-generation-qualifier-length)) + OPTIONAL } + +teletex-organizational-unit-names INTEGER ::= 5 + +TeletexOrganizationalUnitNames ::= SEQUENCE SIZE + (1..ub-organizational-units) OF TeletexOrganizationalUnitName + +TeletexOrganizationalUnitName ::= TeletexString + (SIZE (1..ub-organizational-unit-name-length)) + +pds-name INTEGER ::= 7 + +PDSName ::= PrintableString (SIZE (1..ub-pds-name-length)) + +physical-delivery-country-name INTEGER ::= 8 + +PhysicalDeliveryCountryName ::= CHOICE { + x121-dcc-code NumericString (SIZE (ub-country-name-numeric-length)), + iso-3166-alpha2-code PrintableString + (SIZE (ub-country-name-alpha-length)) } + +postal-code INTEGER ::= 9 + +PostalCode ::= CHOICE { + numeric-code NumericString (SIZE (1..ub-postal-code-length)), + printable-code PrintableString (SIZE (1..ub-postal-code-length)) } + +physical-delivery-office-name INTEGER ::= 10 +PhysicalDeliveryOfficeName ::= PDSParameter + +physical-delivery-office-number INTEGER ::= 11 + +PhysicalDeliveryOfficeNumber ::= PDSParameter + +extension-OR-address-components INTEGER ::= 12 + +ExtensionORAddressComponents ::= PDSParameter + +physical-delivery-personal-name INTEGER ::= 13 + +PhysicalDeliveryPersonalName ::= PDSParameter + +physical-delivery-organization-name INTEGER ::= 14 + +PhysicalDeliveryOrganizationName ::= PDSParameter + +extension-physical-delivery-address-components INTEGER ::= 15 + +ExtensionPhysicalDeliveryAddressComponents ::= PDSParameter + +unformatted-postal-address INTEGER ::= 16 + +UnformattedPostalAddress ::= SET { + printable-address SEQUENCE SIZE (1..ub-pds-physical-address-lines) + OF PrintableString (SIZE (1..ub-pds-parameter-length)) OPTIONAL, + teletex-string TeletexString + (SIZE (1..ub-unformatted-address-length)) OPTIONAL } + +street-address INTEGER ::= 17 + +StreetAddress ::= PDSParameter + +post-office-box-address INTEGER ::= 18 + +PostOfficeBoxAddress ::= PDSParameter + +poste-restante-address INTEGER ::= 19 + +PosteRestanteAddress ::= PDSParameter + +unique-postal-name INTEGER ::= 20 + +UniquePostalName ::= PDSParameter + +local-postal-attributes INTEGER ::= 21 + +LocalPostalAttributes ::= PDSParameter + +PDSParameter ::= SET { + printable-string PrintableString + (SIZE(1..ub-pds-parameter-length)) OPTIONAL, + teletex-string TeletexString + (SIZE(1..ub-pds-parameter-length)) OPTIONAL } + +extended-network-address INTEGER ::= 22 + +ExtendedNetworkAddress ::= CHOICE { + e163-4-address SEQUENCE { + number [0] IMPLICIT NumericString + (SIZE (1..ub-e163-4-number-length)), + sub-address [1] IMPLICIT NumericString + (SIZE (1..ub-e163-4-sub-address-length)) + OPTIONAL }, + psap-address [0] IMPLICIT PresentationAddress } + +PresentationAddress ::= SEQUENCE { + pSelector [0] EXPLICIT OCTET STRING OPTIONAL, + sSelector [1] EXPLICIT OCTET STRING OPTIONAL, + tSelector [2] EXPLICIT OCTET STRING OPTIONAL, + nAddresses [3] EXPLICIT SET SIZE (1..MAX) OF OCTET STRING } + +terminal-type INTEGER ::= 23 + +TerminalType ::= INTEGER { + telex (3), + teletex (4), + g3-facsimile (5), + g4-facsimile (6), + ia5-terminal (7), + videotex (8) } (0..ub-integer-options) + +-- Extension Domain-defined Attributes + +teletex-domain-defined-attributes INTEGER ::= 6 + +TeletexDomainDefinedAttributes ::= SEQUENCE SIZE + (1..ub-domain-defined-attributes) OF TeletexDomainDefinedAttribute + +TeletexDomainDefinedAttribute ::= SEQUENCE { + type TeletexString + (SIZE (1..ub-domain-defined-attribute-type-length)), + value TeletexString + (SIZE (1..ub-domain-defined-attribute-value-length)) } + +-- specifications of Upper Bounds MUST be regarded as mandatory +-- from Annex B of ITU-T X.411 Reference Definition of MTS Parameter +-- Upper Bounds + +-- Upper Bounds +ub-name INTEGER ::= 32768 +ub-common-name INTEGER ::= 64 +ub-locality-name INTEGER ::= 128 +ub-state-name INTEGER ::= 128 +ub-organization-name INTEGER ::= 64 +ub-organizational-unit-name INTEGER ::= 64 +ub-title INTEGER ::= 64 +ub-serial-number INTEGER ::= 64 +ub-match INTEGER ::= 128 +ub-emailaddress-length INTEGER ::= 255 +ub-common-name-length INTEGER ::= 64 +ub-country-name-alpha-length INTEGER ::= 2 +ub-country-name-numeric-length INTEGER ::= 3 +ub-domain-defined-attributes INTEGER ::= 4 +ub-domain-defined-attribute-type-length INTEGER ::= 8 +ub-domain-defined-attribute-value-length INTEGER ::= 128 +ub-domain-name-length INTEGER ::= 16 +ub-extension-attributes INTEGER ::= 256 +ub-e163-4-number-length INTEGER ::= 15 +ub-e163-4-sub-address-length INTEGER ::= 40 +ub-generation-qualifier-length INTEGER ::= 3 +ub-given-name-length INTEGER ::= 16 +ub-initials-length INTEGER ::= 5 +ub-integer-options INTEGER ::= 256 +ub-numeric-user-id-length INTEGER ::= 32 +ub-organization-name-length INTEGER ::= 64 +ub-organizational-unit-name-length INTEGER ::= 32 +ub-organizational-units INTEGER ::= 4 +ub-pds-name-length INTEGER ::= 16 +ub-pds-parameter-length INTEGER ::= 30 +ub-pds-physical-address-lines INTEGER ::= 6 +ub-postal-code-length INTEGER ::= 16 +ub-pseudonym INTEGER ::= 128 +ub-surname-length INTEGER ::= 40 +ub-terminal-id-length INTEGER ::= 24 +ub-unformatted-address-length INTEGER ::= 180 +ub-x121-address-length INTEGER ::= 16 + +-- Note - upper bounds on string types, such as TeletexString, are +-- measured in characters. Excepting PrintableString or IA5String, a +-- significantly greater number of octets will be required to hold +-- such a value. As a minimum, 16 octets, or twice the specified +-- upper bound, whichever is the larger, should be allowed for +-- TeletexString. For UTF8String or UniversalString at least four +-- times the upper bound should be allowed. + +END diff --git a/krb5-1.21.3/src/tests/asn.1/reference_encode.out b/krb5-1.21.3/src/tests/asn.1/reference_encode.out new file mode 100644 index 00000000..faa3dbab --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/reference_encode.out @@ -0,0 +1,78 @@ +encode_krb5_authenticator: 62 81 A1 30 81 9E A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A4 05 02 03 01 E2 40 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A7 03 02 01 11 A8 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 +encode_krb5_authenticator(optionals empty): 62 4F 30 4D A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 05 02 03 01 E2 40 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A +encode_krb5_authenticator(optionals NULL): 62 4F 30 4D A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 05 02 03 01 E2 40 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A +encode_krb5_ticket: 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_keyblock: 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 +encode_krb5_enc_tkt_part: 63 82 01 14 30 82 01 10 A0 07 03 05 00 FE DC BA 98 A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 +encode_krb5_enc_tkt_part(optionals NULL): 63 81 A5 30 81 A2 A0 07 03 05 00 FE DC BA 98 A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 2E 30 2C A0 03 02 01 01 A1 25 04 23 45 44 55 2C 4D 49 54 2E 2C 41 54 48 45 4E 41 2E 2C 57 41 53 48 49 4E 47 54 4F 4E 2E 45 44 55 2C 43 53 2E A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A +encode_krb5_enc_kdc_rep_part: 7A 82 01 0E 30 82 01 0A A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 36 30 34 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A4 07 03 05 00 FE DC BA 98 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AB 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 +encode_krb5_enc_kdc_rep_part(optionals NULL): 7A 81 B2 30 81 AF A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 36 30 34 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A 30 18 A0 03 02 01 FB A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A4 07 03 05 00 FE 5C BA 98 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 +encode_krb5_as_rep: 6B 81 EA 30 81 E7 A0 03 02 01 05 A1 03 02 01 0B A2 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_as_rep(optionals NULL): 6B 81 C2 30 81 BF A0 03 02 01 05 A1 03 02 01 0B A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_tgs_rep: 6D 81 EA 30 81 E7 A0 03 02 01 05 A1 03 02 01 0D A2 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_tgs_rep(optionals NULL): 6D 81 C2 30 81 BF A0 03 02 01 05 A1 03 02 01 0D A3 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A4 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A6 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_ap_req: 6E 81 9D 30 81 9A A0 03 02 01 05 A1 03 02 01 0E A2 07 03 05 00 FE DC BA 98 A3 5E 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A4 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_ap_rep: 6F 33 30 31 A0 03 02 01 05 A1 03 02 01 0F A2 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_ap_rep_enc_part: 7B 36 30 34 A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40 A2 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A3 03 02 01 11 +encode_krb5_ap_rep_enc_part(optionals NULL): 7B 1C 30 1A A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40 +encode_krb5_as_req: 6A 82 01 E4 30 82 01 E0 A1 03 02 01 05 A2 03 02 01 0A A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A4 82 01 AA 30 82 01 A6 A0 07 03 05 00 FE DC BA 90 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_as_req(optionals NULL except second_ticket): 6A 82 01 14 30 82 01 10 A1 03 02 01 05 A2 03 02 01 0A A4 82 01 02 30 81 FF A0 07 03 05 00 FE DC BA 98 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_as_req(optionals NULL except server): 6A 69 30 67 A1 03 02 01 05 A2 03 02 01 0A A4 5B 30 59 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 +encode_krb5_tgs_req: 6C 82 01 E4 30 82 01 E0 A1 03 02 01 05 A2 03 02 01 0C A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A4 82 01 AA 30 82 01 A6 A0 07 03 05 00 FE DC BA 90 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_tgs_req(optionals NULL except second_ticket): 6C 82 01 14 30 82 01 10 A1 03 02 01 05 A2 03 02 01 0C A4 82 01 02 30 81 FF A0 07 03 05 00 FE DC BA 98 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_tgs_req(optionals NULL except server): 6C 69 30 67 A1 03 02 01 05 A2 03 02 01 0C A4 5B 30 59 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 +encode_krb5_kdc_req_body: 30 82 01 A6 A0 07 03 05 00 FE DC BA 90 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_kdc_req_body(optionals NULL except second_ticket): 30 81 FF A0 07 03 05 00 FE DC BA 98 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_kdc_req_body(optionals NULL except server): 30 59 A0 07 03 05 00 FE DC BA 90 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 +encode_krb5_safe: 74 6E 30 6C A0 03 02 01 05 A1 03 02 01 14 A2 4F 30 4D A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 05 02 03 01 E2 40 A3 03 02 01 11 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A5 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A3 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 +encode_krb5_safe(optionals NULL): 74 3E 30 3C A0 03 02 01 05 A1 03 02 01 14 A2 1F 30 1D A0 0A 04 08 6B 72 62 35 64 61 74 61 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A3 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 +encode_krb5_priv: 75 33 30 31 A0 03 02 01 05 A1 03 02 01 15 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_enc_priv_part: 7C 4F 30 4D A0 0A 04 08 6B 72 62 35 64 61 74 61 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 05 02 03 01 E2 40 A3 03 02 01 11 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A5 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 +encode_krb5_enc_priv_part(optionals NULL): 7C 1F 30 1D A0 0A 04 08 6B 72 62 35 64 61 74 61 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 +encode_krb5_cred: 76 81 F6 30 81 F3 A0 03 02 01 05 A1 03 02 01 16 A2 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_enc_cred_part: 7D 82 02 23 30 82 02 1F A0 82 01 DA 30 82 01 D6 30 81 E8 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 07 03 05 00 FE DC BA 98 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A9 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AA 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 81 E8 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 07 03 05 00 FE DC BA 98 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A9 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AA 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A1 03 02 01 2A A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A3 05 02 03 01 E2 40 A4 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 A5 0F 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 +encode_krb5_enc_cred_part(optionals NULL): 7D 82 01 0E 30 82 01 0A A0 82 01 06 30 82 01 02 30 15 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 30 81 E8 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 07 03 05 00 FE DC BA 98 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A8 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A9 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AA 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 +encode_krb5_error: 7E 81 BA 30 81 B7 A0 03 02 01 05 A1 03 02 01 1E A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A3 05 02 03 01 E2 40 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 05 02 03 01 E2 40 A6 03 02 01 3C A7 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A8 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 AB 0A 1B 08 6B 72 62 35 64 61 74 61 AC 0A 04 08 6B 72 62 35 64 61 74 61 +encode_krb5_error(optionals NULL): 7E 60 30 5E A0 03 02 01 05 A1 03 02 01 1E A3 05 02 03 01 E2 40 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 05 02 03 01 E2 40 A6 03 02 01 3C A9 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 AA 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 +encode_krb5_authorization_data: 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 +encode_krb5_padata_sequence: 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 +encode_krb5_typed_data: 30 24 30 10 A0 03 02 01 0D A1 09 04 07 70 61 2D 64 61 74 61 30 10 A0 03 02 01 0D A1 09 04 07 70 61 2D 64 61 74 61 +encode_krb5_padata_sequence(empty): 30 00 +encode_krb5_etype_info: 30 33 30 14 A0 03 02 01 00 A1 0D 04 0B 4D 6F 72 74 6F 6E 27 73 20 23 30 30 05 A0 03 02 01 01 30 14 A0 03 02 01 02 A1 0D 04 0B 4D 6F 72 74 6F 6E 27 73 20 23 32 +encode_krb5_etype_info(only 1): 30 16 30 14 A0 03 02 01 00 A1 0D 04 0B 4D 6F 72 74 6F 6E 27 73 20 23 30 +encode_krb5_etype_info(no info): 30 00 +encode_krb5_etype_info2: 30 51 30 1E A0 03 02 01 00 A1 0D 1B 0B 4D 6F 72 74 6F 6E 27 73 20 23 30 A2 08 04 06 73 32 6B 3A 20 30 30 0F A0 03 02 01 01 A2 08 04 06 73 32 6B 3A 20 31 30 1E A0 03 02 01 02 A1 0D 1B 0B 4D 6F 72 74 6F 6E 27 73 20 23 32 A2 08 04 06 73 32 6B 3A 20 32 +encode_krb5_etype_info2(only 1): 30 20 30 1E A0 03 02 01 00 A1 0D 1B 0B 4D 6F 72 74 6F 6E 27 73 20 23 30 A2 08 04 06 73 32 6B 3A 20 30 +encode_krb5_pa_enc_ts: 30 1A A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40 +encode_krb5_pa_enc_ts (no usec): 30 13 A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A +encode_krb5_enc_data: 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_enc_data(MSB-set kvno): 30 26 A0 03 02 01 00 A1 06 02 04 FF 00 00 00 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_enc_data(kvno=-1): 30 23 A0 03 02 01 00 A1 03 02 01 FF A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_sam_challenge_2: 30 22 A0 0D 30 0B 04 09 63 68 61 6C 6C 65 6E 67 65 A1 11 30 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 +encode_krb5_sam_challenge_2_body: 30 64 A0 03 02 01 2A A1 07 03 05 00 80 00 00 00 A2 0B 04 09 74 79 70 65 20 6E 61 6D 65 A4 11 04 0F 63 68 61 6C 6C 65 6E 67 65 20 6C 61 62 65 6C A5 10 04 0E 63 68 61 6C 6C 65 6E 67 65 20 69 70 73 65 A6 16 04 14 72 65 73 70 6F 6E 73 65 5F 70 72 6F 6D 70 74 20 69 70 73 65 A8 05 02 03 54 32 10 A9 03 02 01 14 +encode_krb5_sam_response_2: 30 42 A0 03 02 01 2B A1 07 03 05 00 80 00 00 00 A2 0C 04 0A 74 72 61 63 6B 20 64 61 74 61 A3 1D 30 1B A0 03 02 01 14 A1 04 02 02 0D 36 A2 0E 04 0C 6E 6F 6E 63 65 20 6F 72 20 73 61 64 A4 05 02 03 54 32 10 +encode_krb5_enc_sam_response_enc_2: 30 1F A0 03 02 01 58 A1 18 04 16 65 6E 63 5F 73 61 6D 5F 72 65 73 70 6F 6E 73 65 5F 65 6E 63 5F 32 +encode_krb5_pa_for_user: 30 4B A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A3 0A 1B 08 6B 72 62 35 64 61 74 61 +encode_krb5_pa_s4u_x509_user: 30 68 A0 55 30 53 A0 06 02 04 00 CA 14 9A A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 12 04 10 70 61 5F 73 34 75 5F 78 35 30 39 5F 75 73 65 72 A4 07 03 05 00 80 00 00 00 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 +encode_krb5_ad_kdcissued: 30 65 A0 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 24 30 22 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 30 0F A0 03 02 01 01 A1 08 04 06 66 6F 6F 62 61 72 +encode_krb5_iakerb_header: 30 18 A1 0A 04 08 6B 72 62 35 64 61 74 61 A2 0A 04 08 6B 72 62 35 64 61 74 61 +encode_krb5_iakerb_finished: 30 11 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 +encode_krb5_fast_response: 30 81 9F A0 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A1 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A2 5B 30 59 A0 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A1 05 02 03 01 E2 40 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34 A3 03 02 01 2A +encode_krb5_pa_fx_fast_reply: A0 29 30 27 A0 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_otp_tokeninfo(optionals NULL): 30 07 80 05 00 00 00 00 00 +encode_krb5_otp_tokeninfo: 30 72 80 05 00 77 00 00 00 81 0B 45 78 61 6D 70 6C 65 63 6F 72 70 82 05 68 61 72 6B 21 83 01 0A 84 01 02 85 09 79 6F 75 72 74 6F 6B 65 6E 86 28 75 72 6E 3A 69 65 74 66 3A 70 61 72 61 6D 73 3A 78 6D 6C 3A 6E 73 3A 6B 65 79 70 72 6F 76 3A 70 73 6B 63 3A 68 6F 74 70 A7 16 30 0B 06 09 60 86 48 01 65 03 04 02 01 30 07 06 05 2B 0E 03 02 1A 88 02 03 E8 +encode_krb5_pa_otp_challenge(optionals NULL): 30 15 80 08 6D 69 6E 6E 6F 6E 63 65 A2 09 30 07 80 05 00 00 00 00 00 +encode_krb5_pa_otp_challenge: 30 81 A5 80 08 6D 61 78 6E 6F 6E 63 65 81 0B 74 65 73 74 73 65 72 76 69 63 65 A2 7D 30 07 80 05 00 00 00 00 00 30 72 80 05 00 77 00 00 00 81 0B 45 78 61 6D 70 6C 65 63 6F 72 70 82 05 68 61 72 6B 21 83 01 0A 84 01 02 85 09 79 6F 75 72 74 6F 6B 65 6E 86 28 75 72 6E 3A 69 65 74 66 3A 70 61 72 61 6D 73 3A 78 6D 6C 3A 6E 73 3A 6B 65 79 70 72 6F 76 3A 70 73 6B 63 3A 68 6F 74 70 A7 16 30 0B 06 09 60 86 48 01 65 03 04 02 01 30 07 06 05 2B 0E 03 02 1A 88 02 03 E8 83 07 6B 65 79 73 61 6C 74 84 04 31 32 33 34 +encode_krb5_pa_otp_req(optionals NULL): 30 2C 80 05 00 00 00 00 00 A2 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_pa_otp_req: 30 81 B9 80 05 00 60 00 00 00 81 05 6E 6F 6E 63 65 A2 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A3 0B 06 09 60 86 48 01 65 03 04 02 01 84 02 03 E8 85 05 66 72 6F 67 73 86 0A 6D 79 66 69 72 73 74 70 69 6E 87 05 68 61 72 6B 21 88 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A 89 03 33 34 36 8A 01 02 8B 09 79 6F 75 72 74 6F 6B 65 6E 8C 28 75 72 6E 3A 69 65 74 66 3A 70 61 72 61 6D 73 3A 78 6D 6C 3A 6E 73 3A 6B 65 79 70 72 6F 76 3A 70 73 6B 63 3A 68 6F 74 70 8D 0B 45 78 61 6D 70 6C 65 63 6F 72 70 +encode_krb5_pa_otp_enc_req: 30 0A 80 08 6B 72 62 35 64 61 74 61 +encode_krb5_kkdcp_message: 30 82 01 FC A0 82 01 EC 04 82 01 E8 6A 82 01 E4 30 82 01 E0 A1 03 02 01 05 A2 03 02 01 0A A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A4 82 01 AA 30 82 01 A6 A0 07 03 05 00 FE DC BA 98 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A1 0A 1B 08 6B 72 62 35 64 61 74 61 +encode_krb5_cammac(optionals NULL): 30 12 A0 10 30 0E 30 0C A0 03 02 01 01 A1 05 04 03 61 64 31 +encode_krb5_cammac: 30 81 F2 A0 1E 30 1C 30 0C A0 03 02 01 01 A1 05 04 03 61 64 31 30 0C A0 03 02 01 02 A1 05 04 03 61 64 32 A1 3D 30 3B A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 03 02 01 05 A2 03 02 01 10 A3 13 30 11 A0 03 02 01 01 A1 0A 04 08 63 6B 73 75 6D 6B 64 63 A2 3D 30 3B A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 03 02 01 05 A2 03 02 01 10 A3 13 30 11 A0 03 02 01 01 A1 0A 04 08 63 6B 73 75 6D 73 76 63 A3 52 30 50 30 13 A3 11 30 0F A0 03 02 01 01 A1 08 04 06 63 6B 73 75 6D 31 30 39 A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 03 02 01 05 A2 03 02 01 10 A3 11 30 0F A0 03 02 01 01 A1 08 04 06 63 6B 73 75 6D 32 +encode_krb5_secure_cookie: 30 2C 02 04 2D F8 02 25 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 +encode_krb5_spake_factor(optionals NULL): 30 05 A0 03 02 01 01 +encode_krb5_spake_factor: 30 0E A0 03 02 01 02 A1 07 04 05 66 64 61 74 61 +encode_krb5_pa_spake(support): A0 0C 30 0A A0 08 30 06 02 01 01 02 01 02 +encode_krb5_pa_spake(challenge): A1 2D 30 2B A0 03 02 01 01 A1 09 04 07 54 20 76 61 6C 75 65 A2 19 30 17 30 05 A0 03 02 01 01 30 0E A0 03 02 01 02 A1 07 04 05 66 64 61 74 61 +encode_krb5_pa_spake(response): A2 34 30 32 A0 09 04 07 53 20 76 61 6C 75 65 A1 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 +encode_krb5_pa_spake(encdata): A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 diff --git a/krb5-1.21.3/src/tests/asn.1/spake.asn1 b/krb5-1.21.3/src/tests/asn.1/spake.asn1 new file mode 100644 index 00000000..50718d8a --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/spake.asn1 @@ -0,0 +1,44 @@ +KerberosV5SPAKE { + iso(1) identified-organization(3) dod(6) internet(1) + security(5) kerberosV5(2) modules(4) spake(8) +} DEFINITIONS EXPLICIT TAGS ::= BEGIN + +IMPORTS + EncryptedData, Int32 + FROM KerberosV5Spec2 { iso(1) identified-organization(3) + dod(6) internet(1) security(5) kerberosV5(2) modules(4) + krb5spec2(2) }; + -- as defined in RFC 4120. + +SPAKESupport ::= SEQUENCE { + groups [0] SEQUENCE (SIZE(1..MAX)) OF Int32, + ... +} + +SPAKEChallenge ::= SEQUENCE { + group [0] Int32, + pubkey [1] OCTET STRING, + factors [2] SEQUENCE (SIZE(1..MAX)) OF SPAKESecondFactor, + ... +} + +SPAKESecondFactor ::= SEQUENCE { + type [0] Int32, + data [1] OCTET STRING OPTIONAL +} + +SPAKEResponse ::= SEQUENCE { + pubkey [0] OCTET STRING, + factor [1] EncryptedData, -- SPAKESecondFactor + ... +} + +PA-SPAKE ::= CHOICE { + support [0] SPAKESupport, + challenge [1] SPAKEChallenge, + response [2] SPAKEResponse, + encdata [3] EncryptedData, + ... +} + +END diff --git a/krb5-1.21.3/src/tests/asn.1/t_trval.c b/krb5-1.21.3/src/tests/asn.1/t_trval.c new file mode 100644 index 00000000..57d82538 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/t_trval.c @@ -0,0 +1,107 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1992,1993 Trusted Information Systems, Inc. + * + * Permission to include this software in the Kerberos V5 distribution + * was graciously provided by Trusted Information Systems. + * + * Trusted Information Systems makes no representation about the + * suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * Copyright (C) 1994 Massachusetts Institute of Technology + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Split out from "#ifdef STANDALONE" code previously in trval.c, so + that trval.o could be linked into other tests too without the + -DSTANDALONE code. */ +#include "trval.c" + +static void usage() +{ + fprintf(stderr, "Usage: trval [--types] [--krb5] [--krb5decode] [--hex] [-notypebytes] [file]\n"); + exit(1); +} + +/* + * Returns true if the option was selected. Allow "-option" and + * "--option" syntax, since we used to accept only "-option" + */ +static +int check_option(word, option) + char *word; + char *option; +{ + if (word[0] != '-') + return 0; + if (word[1] == '-') + word++; + if (strcmp(word+1, option)) + return 0; + return 1; +} + +int main(argc, argv) + int argc; + char **argv; +{ + int optflg = 1; + FILE *fp; + int r = 0; + + while (--argc > 0) { + argv++; + if (optflg && *(argv)[0] == '-') { + if (check_option(*argv, "help")) + usage(); + else if (check_option(*argv, "types")) + print_types = 1; + else if (check_option(*argv, "notypes")) + print_types = 0; + else if (check_option(*argv, "krb5")) + print_krb5_types = 1; + else if (check_option(*argv, "hex")) + do_hex = 1; + else if (check_option(*argv, "notypebytes")) + print_id_and_len = 0; + else if (check_option(*argv, "krb5decode")) { + print_id_and_len = 0; + print_krb5_types = 1; + print_types = 1; + } else { + fprintf(stderr,"trval: unknown option: %s\n", *argv); + usage(); + } + } else { + optflg = 0; + if ((fp = fopen(*argv,"r")) == NULL) { + fprintf(stderr,"trval: unable to open %s\n", *argv); + continue; + } + r = trval(fp, stdout); + fclose(fp); + } + } + if (optflg) r = trval(stdin, stdout); + + exit(r); +} diff --git a/krb5-1.21.3/src/tests/asn.1/trval.c b/krb5-1.21.3/src/tests/asn.1/trval.c new file mode 100644 index 00000000..c14bcdeb --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/trval.c @@ -0,0 +1,769 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1992,1993 Trusted Information Systems, Inc. + * + * Permission to include this software in the Kerberos V5 distribution + * was graciously provided by Trusted Information Systems. + * + * Trusted Information Systems makes no representation about the + * suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + */ +/* + * Copyright (C) 1994 Massachusetts Institute of Technology + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/***************************************************************************** + * trval.c.c + *****************************************************************************/ + +#include +#include +#include +#include +#include + +#define OK 0 +#define NOTOK (-1) + +/* IDENTIFIER OCTET = TAG CLASS | FORM OF ENCODING | TAG NUMBER */ + +/* TAG CLASSES */ +#define ID_CLASS 0xc0 /* bits 8 and 7 */ +#define CLASS_UNIV 0x00 /* 0 = universal */ +#define CLASS_APPL 0x40 /* 1 = application */ +#define CLASS_CONT 0x80 /* 2 = context-specific */ +#define CLASS_PRIV 0xc0 /* 3 = private */ + +/* FORM OF ENCODING */ +#define ID_FORM 0x20 /* bit 6 */ +#define FORM_PRIM 0x00 /* 0 = primitive */ +#define FORM_CONS 0x20 /* 1 = constructed */ + +/* TAG NUMBERS */ +#define ID_TAG 0x1f /* bits 5-1 */ +#define PRIM_BOOL 0x01 /* Boolean */ +#define PRIM_INT 0x02 /* Integer */ +#define PRIM_BITS 0x03 /* Bit String */ +#define PRIM_OCTS 0x04 /* Octet String */ +#define PRIM_NULL 0x05 /* Null */ +#define PRIM_OID 0x06 /* Object Identifier */ +#define PRIM_ODE 0x07 /* Object Descriptor */ +#define CONS_EXTN 0x08 /* External */ +#define PRIM_REAL 0x09 /* Real */ +#define PRIM_ENUM 0x0a /* Enumerated type */ +#define PRIM_ENCR 0x0b /* Encrypted */ +#define CONS_SEQ 0x10 /* SEQUENCE/SEQUENCE OF */ +#define CONS_SET 0x11 /* SET/SET OF */ +#define DEFN_NUMS 0x12 /* Numeric String */ +#define DEFN_PRTS 0x13 /* Printable String */ +#define DEFN_T61S 0x14 /* T.61 String */ +#define DEFN_VTXS 0x15 /* Videotex String */ +#define DEFN_IA5S 0x16 /* IA5 String */ +#define DEFN_UTCT 0x17 /* UTCTime */ +#define DEFN_GENT 0x18 /* Generalized Time */ +#define DEFN_GFXS 0x19 /* Graphics string (ISO2375) */ +#define DEFN_VISS 0x1a /* Visible string */ +#define DEFN_GENS 0x1b /* General string */ +#define DEFN_CHRS 0x1c /* Character string */ + +#define LEN_XTND 0x80 /* long or indefinite form */ +#define LEN_SMAX 127 /* largest short form */ +#define LEN_MASK 0x7f /* mask to get number of bytes in length */ +#define LEN_INDF (-1) /* indefinite length */ + +#define KRB5 /* Do krb5 application types */ + +int print_types = 0; +int print_id_and_len = 1; +int print_constructed_length = 1; +int print_primitive_length = 1; +int print_skip_context = 0; +int print_skip_tagnum = 1; +int print_context_shortcut = 0; +int do_hex = 0; +#ifdef KRB5 +int print_krb5_types = 0; +#endif + +int current_appl_type = -1; + +int decode_len (FILE *, unsigned char *, int); +int do_prim (FILE *, int, unsigned char *, int, int); +int do_cons (FILE *, unsigned char *, int, int, int *); +int do_prim_bitstring (FILE *, int, unsigned char *, int, int); +int do_prim_int (FILE *, int, unsigned char *, int, int); +int do_prim_string (FILE *, int, unsigned char *, int, int); +void print_tag_type (FILE *, int, int); +int trval (FILE *, FILE *); +int trval2 (FILE *, unsigned char *, int, int, int *); + + +/****************************************************************************/ + +static int convert_nibble(int ch) +{ + if (isdigit(ch)) + return (ch - '0'); + if (ch >= 'a' && ch <= 'f') + return (ch - 'a' + 10); + if (ch >= 'A' && ch <= 'F') + return (ch - 'A' + 10); + return -1; +} + +int trval(fin, fout) + FILE *fin; + FILE *fout; +{ + unsigned char *p; + unsigned int maxlen; + int len; + int cc, cc2, n1, n2; + int r; + int rlen; + + maxlen = BUFSIZ; + p = (unsigned char *)malloc(maxlen); + len = 0; + while ((cc = fgetc(fin)) != EOF) { + if ((unsigned int) len == maxlen) { + maxlen += BUFSIZ; + p = (unsigned char *)realloc(p, maxlen); + } + if (do_hex) { + if (cc == ' ' || cc == '\n' || cc == '\t') + continue; + cc2 = fgetc(fin); + if (cc2 == EOF) + break; + n1 = convert_nibble(cc); + n2 = convert_nibble(cc2); + cc = (n1 << 4) + n2; + } + p[len++] = cc; + } + fprintf(fout, "<%d>", len); + r = trval2(fout, p, len, 0, &rlen); + fprintf(fout, "\n"); + (void) free(p); + return(r); +} + +int trval2(fp, enc, len, lev, rlen) + FILE *fp; + unsigned char *enc; + int len; + int lev; + int *rlen; +{ + int l, eid, elen, xlen, r, rlen2 = 0; + int rlen_ext = 0; + + r = OK; + *rlen = -1; + + if (len < 2) { + fprintf(fp, "missing id and length octets (%d)\n", len); + return(NOTOK); + } + + fprintf(fp, "\n"); + for (l=0; l len - 2) { + fprintf(fp, "extended length too long (%d > %d - 2)\n", xlen, len); + return(NOTOK); + } + elen = decode_len(fp, enc+2, xlen); + } + + if (elen > len - 2 - xlen) { + fprintf(fp, "length too long (%d > %d - 2 - %d)\n", elen, len, xlen); + return(NOTOK); + } + + print_tag_type(fp, eid, lev); + + if (print_context_shortcut && (eid & ID_CLASS) == CLASS_CONT && + (eid & ID_FORM) == FORM_CONS && lev > 0) { + rlen_ext += 2 + xlen; + enc += 2 + xlen; + fprintf(fp, " "); + goto context_restart; + } + + switch(eid & ID_FORM) { + case FORM_PRIM: + r = do_prim(fp, eid & ID_TAG, enc+2+xlen, elen, lev+1); + *rlen = 2 + xlen + elen + rlen_ext; + break; + case FORM_CONS: + if (print_constructed_length) { + fprintf(fp, " constr"); + fprintf(fp, " <%d>", elen); + } + r = do_cons(fp, enc+2+xlen, elen, lev+1, &rlen2); + *rlen = 2 + xlen + rlen2 + rlen_ext; + break; + } + + return(r); +} + +int decode_len(fp, enc, len) + FILE *fp; + unsigned char *enc; + int len; +{ + int rlen; + int i; + + if (print_id_and_len) + fprintf(fp, "%02x ", enc[0]); + rlen = enc[0]; + for (i=1; i 5) + return 0; + + for (i=1; i < len; i++) { + num = num << 8; + num += enc[i]; + } + + fprintf(fp, " 0x%lx", num); + if (enc[0]) + fprintf(fp, " (%d unused bits)", enc[0]); + return 1; +} + +/* + * This is the printing function for integers + */ +int do_prim_int(fp, tag, enc, len, lev) + FILE *fp; + int tag; + unsigned char *enc; + int len; + int lev; +{ + int i; + long num = 0; + + if (tag != PRIM_INT || len > 4) + return 0; + + if (enc[0] & 0x80) + num = -1; + + for (i=0; i < len; i++) { + num = num << 8; + num += enc[i]; + } + + fprintf(fp, " %ld", num); + return 1; +} + + +/* + * This is the printing function which we use if it's a string or + * other other type which is best printed as a string + */ +int do_prim_string(fp, tag, enc, len, lev) + FILE *fp; + int tag; + unsigned char *enc; + int len; + int lev; +{ + int i; + + /* + * Only try this printing function with "reasonable" types + */ + if ((tag < DEFN_NUMS) && (tag != PRIM_OCTS)) + return 0; + + for (i=0; i < len; i++) + if (!isprint(enc[i])) + return 0; + fprintf(fp, " \"%.*s\"", len, enc); + return 1; +} + +int do_prim(fp, tag, enc, len, lev) + FILE *fp; + int tag; + unsigned char *enc; + int len; + int lev; +{ + int n; + int i; + int j; + int width; + + if (do_prim_string(fp, tag, enc, len, lev)) + return OK; + if (do_prim_int(fp, tag, enc, len, lev)) + return OK; + if (do_prim_bitstring(fp, tag, enc, len, lev)) + return OK; + + if (print_primitive_length) + fprintf(fp, " <%d>", len); + + width = (80 - (lev * 3) - 8) / 4; + + for (n = 0; n < len; n++) { + if ((n % width) == 0) { + fprintf(fp, "\n"); + for (i=0; ik1 > 0; ent++) { + if ((ent->k1 == key1) && + (ent->k2 == key2)) { + if (ent->new_appl) + current_appl_type = ent->new_appl; + return ent->str; + } + } + return 0; +} + + +struct typestring_table univ_types[] = { + { PRIM_BOOL, -1, "Boolean"}, + { PRIM_INT, -1, "Integer"}, + { PRIM_BITS, -1, "Bit String"}, + { PRIM_OCTS, -1, "Octet String"}, + { PRIM_NULL, -1, "Null"}, + { PRIM_OID, -1, "Object Identifier"}, + { PRIM_ODE, -1, "Object Descriptor"}, + { CONS_EXTN, -1, "External"}, + { PRIM_REAL, -1, "Real"}, + { PRIM_ENUM, -1, "Enumerated type"}, + { PRIM_ENCR, -1, "Encrypted"}, + { CONS_SEQ, -1, "Sequence/Sequence Of"}, + { CONS_SET, -1, "Set/Set Of"}, + { DEFN_NUMS, -1, "Numeric String"}, + { DEFN_PRTS, -1, "Printable String"}, + { DEFN_T61S, -1, "T.61 String"}, + { DEFN_VTXS, -1, "Videotex String"}, + { DEFN_IA5S, -1, "IA5 String"}, + { DEFN_UTCT, -1, "UTCTime"}, + { DEFN_GENT, -1, "Generalized Time"}, + { DEFN_GFXS, -1, "Graphics string (ISO2375)"}, + { DEFN_VISS, -1, "Visible string"}, + { DEFN_GENS, -1, "General string"}, + { DEFN_CHRS, -1, "Character string"}, + { -1, -1, 0} +}; + +#ifdef KRB5 +struct typestring_table krb5_types[] = { + { 1, -1, "Krb5 Ticket"}, + { 2, -1, "Krb5 Authenticator"}, + { 3, -1, "Krb5 Encrypted ticket part"}, + { 10, -1, "Krb5 AS-REQ packet"}, + { 11, -1, "Krb5 AS-REP packet"}, + { 12, -1, "Krb5 TGS-REQ packet"}, + { 13, -1, "Krb5 TGS-REP packet"}, + { 14, -1, "Krb5 AP-REQ packet"}, + { 15, -1, "Krb5 AP-REP packet"}, + { 20, -1, "Krb5 SAFE packet"}, + { 21, -1, "Krb5 PRIV packet"}, + { 22, -1, "Krb5 CRED packet"}, + { 30, -1, "Krb5 ERROR packet"}, + { 25, -1, "Krb5 Encrypted AS-REP part"}, + { 26, -1, "Krb5 Encrypted TGS-REP part"}, + { 27, -1, "Krb5 Encrypted AP-REP part"}, + { 28, -1, "Krb5 Encrypted PRIV part"}, + { 29, -1, "Krb5 Encrypted CRED part"}, + { -1, -1, 0} +}; + +struct typestring_table krb5_fields[] = { + { 1000, 0, "name-type"}, /* PrincipalName */ + { 1000, 1, "name-string"}, + + { 1001, 0, "etype"}, /* Encrypted data */ + { 1001, 1, "kvno"}, + { 1001, 2, "cipher"}, + + { 1002, 0, "addr-type"}, /* HostAddress */ + { 1002, 1, "address"}, + + { 1003, 0, "addr-type"}, /* HostAddresses */ + { 1003, 1, "address"}, + + { 1004, 0, "ad-type"}, /* AuthorizationData */ + { 1004, 1, "ad-data"}, + + { 1005, 0, "keytype"}, /* EncryptionKey */ + { 1005, 1, "keyvalue"}, + + { 1006, 0, "cksumtype"}, /* Checksum */ + { 1006, 1, "checksum"}, + + { 1007, 0, "kdc-options"}, /* KDC-REQ-BODY */ + { 1007, 1, "cname", 1000}, + { 1007, 2, "realm"}, + { 1007, 3, "sname", 1000}, + { 1007, 4, "from"}, + { 1007, 5, "till"}, + { 1007, 6, "rtime"}, + { 1007, 7, "nonce"}, + { 1007, 8, "etype"}, + { 1007, 9, "addresses", 1003}, + { 1007, 10, "enc-authorization-data", 1001}, + { 1007, 11, "additional-tickets"}, + + { 1008, 1, "padata-type"}, /* PA-DATA */ + { 1008, 2, "pa-data"}, + + { 1009, 0, "user-data"}, /* KRB-SAFE-BODY */ + { 1009, 1, "timestamp"}, + { 1009, 2, "usec"}, + { 1009, 3, "seq-number"}, + { 1009, 4, "s-address", 1002}, + { 1009, 5, "r-address", 1002}, + + { 1010, 0, "lr-type"}, /* LastReq */ + { 1010, 1, "lr-value"}, + + { 1011, 0, "key", 1005}, /* KRB-CRED-INFO */ + { 1011, 1, "prealm"}, + { 1011, 2, "pname", 1000}, + { 1011, 3, "flags"}, + { 1011, 4, "authtime"}, + { 1011, 5, "startime"}, + { 1011, 6, "endtime"}, + { 1011, 7, "renew-till"}, + { 1011, 8, "srealm"}, + { 1011, 9, "sname", 1000}, + { 1011, 10, "caddr", 1002}, + + { 1, 0, "tkt-vno"}, /* Ticket */ + { 1, 1, "realm"}, + { 1, 2, "sname", 1000}, + { 1, 3, "tkt-enc-part", 1001}, + + { 2, 0, "authenticator-vno"}, /* Authenticator */ + { 2, 1, "crealm"}, + { 2, 2, "cname", 1000}, + { 2, 3, "cksum", 1006}, + { 2, 4, "cusec"}, + { 2, 5, "ctime"}, + { 2, 6, "subkey", 1005}, + { 2, 7, "seq-number"}, + { 2, 8, "authorization-data", 1004}, + + { 3, 0, "flags"}, /* EncTicketPart */ + { 3, 1, "key", 1005}, + { 3, 2, "crealm"}, + { 3, 3, "cname", 1000}, + { 3, 4, "transited"}, + { 3, 5, "authtime"}, + { 3, 6, "starttime"}, + { 3, 7, "endtime"}, + { 3, 8, "renew-till"}, + { 3, 9, "caddr", 1003}, + { 3, 10, "authorization-data", 1004}, + + { 10, 1, "pvno"}, /* AS-REQ */ + { 10, 2, "msg-type"}, + { 10, 3, "padata", 1008}, + { 10, 4, "req-body", 1007}, + + { 11, 0, "pvno"}, /* AS-REP */ + { 11, 1, "msg-type"}, + { 11, 2, "padata", 1008}, + { 11, 3, "crealm"}, + { 11, 4, "cname", 1000}, + { 11, 5, "ticket"}, + { 11, 6, "enc-part", 1001}, + + { 12, 1, "pvno"}, /* TGS-REQ */ + { 12, 2, "msg-type"}, + { 12, 3, "padata", 1008}, + { 12, 4, "req-body", 1007}, + + { 13, 0, "pvno"}, /* TGS-REP */ + { 13, 1, "msg-type"}, + { 13, 2, "padata", 1008}, + { 13, 3, "crealm"}, + { 13, 4, "cname", 1000}, + { 13, 5, "ticket"}, + { 13, 6, "enc-part", 1001}, + + { 14, 0, "pvno"}, /* AP-REQ */ + { 14, 1, "msg-type"}, + { 14, 2, "ap-options"}, + { 14, 3, "ticket"}, + { 14, 4, "authenticator", 1001}, + + { 15, 0, "pvno"}, /* AP-REP */ + { 15, 1, "msg-type"}, + { 15, 2, "enc-part", 1001}, + + { 20, 0, "pvno"}, /* KRB-SAFE */ + { 20, 1, "msg-type"}, + { 20, 2, "safe-body", 1009}, + { 20, 3, "cksum", 1006}, + + { 21, 0, "pvno"}, /* KRB-PRIV */ + { 21, 1, "msg-type"}, + { 21, 2, "enc-part", 1001}, + + { 22, 0, "pvno"}, /* KRB-CRED */ + { 22, 1, "msg-type"}, + { 22, 2, "tickets"}, + { 22, 3, "enc-part", 1001}, + + { 25, 0, "key", 1005}, /* EncASRepPart */ + { 25, 1, "last-req", 1010}, + { 25, 2, "nonce"}, + { 25, 3, "key-expiration"}, + { 25, 4, "flags"}, + { 25, 5, "authtime"}, + { 25, 6, "starttime"}, + { 25, 7, "enddtime"}, + { 25, 8, "renew-till"}, + { 25, 9, "srealm"}, + { 25, 10, "sname", 1000}, + { 25, 11, "caddr", 1003}, + + { 26, 0, "key", 1005}, /* EncTGSRepPart */ + { 26, 1, "last-req", 1010}, + { 26, 2, "nonce"}, + { 26, 3, "key-expiration"}, + { 26, 4, "flags"}, + { 26, 5, "authtime"}, + { 26, 6, "starttime"}, + { 26, 7, "enddtime"}, + { 26, 8, "renew-till"}, + { 26, 9, "srealm"}, + { 26, 10, "sname", 1000}, + { 26, 11, "caddr", 1003}, + + { 27, 0, "ctime"}, /* EncApRepPart */ + { 27, 1, "cusec"}, + { 27, 2, "subkey", 1005}, + { 27, 3, "seq-number"}, + + { 28, 0, "user-data"}, /* EncKrbPrivPart */ + { 28, 1, "timestamp"}, + { 28, 2, "usec"}, + { 28, 3, "seq-number"}, + { 28, 4, "s-address", 1002}, + { 28, 5, "r-address", 1002}, + + { 29, 0, "ticket-info", 1011}, /* EncKrbCredPart */ + { 29, 1, "nonce"}, + { 29, 2, "timestamp"}, + { 29, 3, "usec"}, + { 29, 4, "s-address", 1002}, + { 29, 5, "r-address", 1002}, + + { 30, 0, "pvno"}, /* KRB-ERROR */ + { 30, 1, "msg-type"}, + { 30, 2, "ctime"}, + { 30, 3, "cusec"}, + { 30, 4, "stime"}, + { 30, 5, "susec"}, + { 30, 6, "error-code"}, + { 30, 7, "crealm"}, + { 30, 8, "cname", 1000}, + { 30, 9, "realm"}, + { 30, 10, "sname", 1000}, + { 30, 11, "e-text"}, + { 30, 12, "e-data"}, + + { -1, -1, 0} +}; +#endif + +void print_tag_type(fp, eid, lev) + FILE *fp; + int eid; + int lev; +{ + int tag = eid & ID_TAG; + int do_space = 1; + char *str; + + fprintf(fp, "["); + + switch(eid & ID_CLASS) { + case CLASS_UNIV: + if (print_types && print_skip_tagnum) + do_space = 0; + else + fprintf(fp, "UNIV %d", tag); + break; + case CLASS_APPL: + current_appl_type = tag; +#ifdef KRB5 + if (print_krb5_types) { + str = lookup_typestring(krb5_types, tag, -1); + if (str) { + fputs(str, fp); + break; + } + } +#endif + fprintf(fp, "APPL %d", tag); + break; + case CLASS_CONT: +#ifdef KRB5 + if (print_krb5_types && current_appl_type) { + str = lookup_typestring(krb5_fields, + current_appl_type, tag); + if (str) { + fputs(str, fp); + break; + } + } +#endif + if (print_skip_context && lev) + fprintf(fp, "%d", tag); + else + fprintf(fp, "CONT %d", tag); + break; + case CLASS_PRIV: + fprintf(fp, "PRIV %d", tag); + break; + } + + if (print_types && ((eid & ID_CLASS) == CLASS_UNIV)) { + if (do_space) + fputs(" ", fp); + str = lookup_typestring(univ_types, eid & ID_TAG, -1); + if (str) + fputs(str, fp); + else + fprintf(fp, "UNIV %d???", eid & ID_TAG); + } + + fprintf(fp, "]"); + +} + +/*****************************************************************************/ diff --git a/krb5-1.21.3/src/tests/asn.1/trval_reference.out b/krb5-1.21.3/src/tests/asn.1/trval_reference.out new file mode 100644 index 00000000..9bedad49 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/trval_reference.out @@ -0,0 +1,1587 @@ +encode_krb5_authenticator: + +[Krb5 Authenticator] +. [Sequence/Sequence Of] +. . [authenticator-vno] [Integer] 5 +. . [crealm] [General string] "ATHENA.MIT.EDU" +. . [cname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [cksum] [Sequence/Sequence Of] +. . . [cksumtype] [Integer] 1 +. . . [checksum] [Octet String] "1234" +. . [cusec] [Integer] 123456 +. . [ctime] [Generalized Time] "19940610060317Z" +. . [subkey] [Sequence/Sequence Of] +. . . [keytype] [Integer] 1 +. . . [keyvalue] [Octet String] "12345678" +. . [seq-number] [Integer] 17 +. . [authorization-data] [Sequence/Sequence Of] +. . . [Sequence/Sequence Of] +. . . . [ad-type] [Integer] 1 +. . . . [ad-data] [Octet String] "foobar" +. . . [Sequence/Sequence Of] +. . . . [ad-type] [Integer] 1 +. . . . [ad-data] [Octet String] "foobar" + +encode_krb5_authenticator(optionals empty): + +[Krb5 Authenticator] +. [Sequence/Sequence Of] +. . [authenticator-vno] [Integer] 5 +. . [crealm] [General string] "ATHENA.MIT.EDU" +. . [cname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [cusec] [Integer] 123456 +. . [ctime] [Generalized Time] "19940610060317Z" + +encode_krb5_authenticator(optionals NULL): + +[Krb5 Authenticator] +. [Sequence/Sequence Of] +. . [authenticator-vno] [Integer] 5 +. . [crealm] [General string] "ATHENA.MIT.EDU" +. . [cname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [cusec] [Integer] 123456 +. . [ctime] [Generalized Time] "19940610060317Z" + +encode_krb5_ticket: + +[Krb5 Ticket] +. [Sequence/Sequence Of] +. . [tkt-vno] [Integer] 5 +. . [realm] [General string] "ATHENA.MIT.EDU" +. . [sname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [tkt-enc-part] [Sequence/Sequence Of] +. . . [etype] [Integer] 0 +. . . [kvno] [Integer] 5 +. . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_keyblock: + +[Sequence/Sequence Of] +. [keytype] [Integer] 1 +. [keyvalue] [Octet String] "12345678" + +encode_krb5_enc_tkt_part: + +[Krb5 Encrypted ticket part] +. [Sequence/Sequence Of] +. . [flags] [Bit String] 0xfedcba98 +. . [key] [Sequence/Sequence Of] +. . . [keytype] [Integer] 1 +. . . [keyvalue] [Octet String] "12345678" +. . [crealm] [General string] "ATHENA.MIT.EDU" +. . [cname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [transited] [Sequence/Sequence Of] +. . . [flags] [Integer] 1 +. . . [key] [Octet String] "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS." +. . [authtime] [Generalized Time] "19940610060317Z" +. . [starttime] [Generalized Time] "19940610060317Z" +. . [endtime] [Generalized Time] "19940610060317Z" +. . [renew-till] [Generalized Time] "19940610060317Z" +. . [caddr] [Sequence/Sequence Of] +. . . [Sequence/Sequence Of] +. . . . [addr-type] [Integer] 2 +. . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . . [Sequence/Sequence Of] +. . . . [addr-type] [Integer] 2 +. . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . [authorization-data] [Sequence/Sequence Of] +. . . [Sequence/Sequence Of] +. . . . [ad-type] [Integer] 1 +. . . . [ad-data] [Octet String] "foobar" +. . . [Sequence/Sequence Of] +. . . . [ad-type] [Integer] 1 +. . . . [ad-data] [Octet String] "foobar" + +encode_krb5_enc_tkt_part(optionals NULL): + +[Krb5 Encrypted ticket part] +. [Sequence/Sequence Of] +. . [flags] [Bit String] 0xfedcba98 +. . [key] [Sequence/Sequence Of] +. . . [keytype] [Integer] 1 +. . . [keyvalue] [Octet String] "12345678" +. . [crealm] [General string] "ATHENA.MIT.EDU" +. . [cname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [transited] [Sequence/Sequence Of] +. . . [flags] [Integer] 1 +. . . [key] [Octet String] "EDU,MIT.,ATHENA.,WASHINGTON.EDU,CS." +. . [authtime] [Generalized Time] "19940610060317Z" +. . [endtime] [Generalized Time] "19940610060317Z" + +encode_krb5_enc_kdc_rep_part: + +[Krb5 Encrypted TGS-REP part] +. [Sequence/Sequence Of] +. . [key] [Sequence/Sequence Of] +. . . [keytype] [Integer] 1 +. . . [keyvalue] [Octet String] "12345678" +. . [last-req] [Sequence/Sequence Of] +. . . [Sequence/Sequence Of] +. . . . [lr-type] [Integer] -5 +. . . . [lr-value] [Generalized Time] "19940610060317Z" +. . . [Sequence/Sequence Of] +. . . . [lr-type] [Integer] -5 +. . . . [lr-value] [Generalized Time] "19940610060317Z" +. . [nonce] [Integer] 42 +. . [key-expiration] [Generalized Time] "19940610060317Z" +. . [flags] [Bit String] 0xfedcba98 +. . [authtime] [Generalized Time] "19940610060317Z" +. . [starttime] [Generalized Time] "19940610060317Z" +. . [enddtime] [Generalized Time] "19940610060317Z" +. . [renew-till] [Generalized Time] "19940610060317Z" +. . [srealm] [General string] "ATHENA.MIT.EDU" +. . [sname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [caddr] [Sequence/Sequence Of] +. . . [Sequence/Sequence Of] +. . . . [addr-type] [Integer] 2 +. . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . . [Sequence/Sequence Of] +. . . . [addr-type] [Integer] 2 +. . . . [address] [Octet String] <4> + 12 d0 00 23 ...# + +encode_krb5_enc_kdc_rep_part(optionals NULL): + +[Krb5 Encrypted TGS-REP part] +. [Sequence/Sequence Of] +. . [key] [Sequence/Sequence Of] +. . . [keytype] [Integer] 1 +. . . [keyvalue] [Octet String] "12345678" +. . [last-req] [Sequence/Sequence Of] +. . . [Sequence/Sequence Of] +. . . . [lr-type] [Integer] -5 +. . . . [lr-value] [Generalized Time] "19940610060317Z" +. . . [Sequence/Sequence Of] +. . . . [lr-type] [Integer] -5 +. . . . [lr-value] [Generalized Time] "19940610060317Z" +. . [nonce] [Integer] 42 +. . [flags] [Bit String] 0xfe5cba98 +. . [authtime] [Generalized Time] "19940610060317Z" +. . [enddtime] [Generalized Time] "19940610060317Z" +. . [srealm] [General string] "ATHENA.MIT.EDU" +. . [sname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" + +encode_krb5_as_rep: + +[Krb5 AS-REP packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 11 +. . [padata] [Sequence/Sequence Of] +. . . [Sequence/Sequence Of] +. . . . [padata-type] [Integer] 13 +. . . . [pa-data] [Octet String] "pa-data" +. . . [Sequence/Sequence Of] +. . . . [padata-type] [Integer] 13 +. . . . [pa-data] [Octet String] "pa-data" +. . [crealm] [General string] "ATHENA.MIT.EDU" +. . [cname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [ticket] [Krb5 Ticket] +. . . [Sequence/Sequence Of] +. . . . [tkt-vno] [Integer] 5 +. . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . [sname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . [etype] [Integer] 0 +. . . . . [kvno] [Integer] 5 +. . . . . [cipher] [Octet String] "krbASN.1 test message" +. . [enc-part] [Sequence/Sequence Of] +. . . [etype] [Integer] 0 +. . . [kvno] [Integer] 5 +. . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_as_rep(optionals NULL): + +[Krb5 AS-REP packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 11 +. . [crealm] [General string] "ATHENA.MIT.EDU" +. . [cname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [ticket] [Krb5 Ticket] +. . . [Sequence/Sequence Of] +. . . . [tkt-vno] [Integer] 5 +. . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . [sname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . [etype] [Integer] 0 +. . . . . [kvno] [Integer] 5 +. . . . . [cipher] [Octet String] "krbASN.1 test message" +. . [enc-part] [Sequence/Sequence Of] +. . . [etype] [Integer] 0 +. . . [kvno] [Integer] 5 +. . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_tgs_rep: + +[Krb5 TGS-REP packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 13 +. . [padata] [Sequence/Sequence Of] +. . . [Sequence/Sequence Of] +. . . . [padata-type] [Integer] 13 +. . . . [pa-data] [Octet String] "pa-data" +. . . [Sequence/Sequence Of] +. . . . [padata-type] [Integer] 13 +. . . . [pa-data] [Octet String] "pa-data" +. . [crealm] [General string] "ATHENA.MIT.EDU" +. . [cname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [ticket] [Krb5 Ticket] +. . . [Sequence/Sequence Of] +. . . . [tkt-vno] [Integer] 5 +. . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . [sname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . [etype] [Integer] 0 +. . . . . [kvno] [Integer] 5 +. . . . . [cipher] [Octet String] "krbASN.1 test message" +. . [enc-part] [Sequence/Sequence Of] +. . . [etype] [Integer] 0 +. . . [kvno] [Integer] 5 +. . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_tgs_rep(optionals NULL): + +[Krb5 TGS-REP packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 13 +. . [crealm] [General string] "ATHENA.MIT.EDU" +. . [cname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [ticket] [Krb5 Ticket] +. . . [Sequence/Sequence Of] +. . . . [tkt-vno] [Integer] 5 +. . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . [sname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . [etype] [Integer] 0 +. . . . . [kvno] [Integer] 5 +. . . . . [cipher] [Octet String] "krbASN.1 test message" +. . [enc-part] [Sequence/Sequence Of] +. . . [etype] [Integer] 0 +. . . [kvno] [Integer] 5 +. . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_ap_req: + +[Krb5 AP-REQ packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 14 +. . [ap-options] [Bit String] 0xfedcba98 +. . [ticket] [Krb5 Ticket] +. . . [Sequence/Sequence Of] +. . . . [tkt-vno] [Integer] 5 +. . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . [sname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . [etype] [Integer] 0 +. . . . . [kvno] [Integer] 5 +. . . . . [cipher] [Octet String] "krbASN.1 test message" +. . [authenticator] [Sequence/Sequence Of] +. . . [etype] [Integer] 0 +. . . [kvno] [Integer] 5 +. . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_ap_rep: + +[Krb5 AP-REP packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 15 +. . [enc-part] [Sequence/Sequence Of] +. . . [etype] [Integer] 0 +. . . [kvno] [Integer] 5 +. . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_ap_rep_enc_part: + +[Krb5 Encrypted AP-REP part] +. [Sequence/Sequence Of] +. . [ctime] [Generalized Time] "19940610060317Z" +. . [cusec] [Integer] 123456 +. . [subkey] [Sequence/Sequence Of] +. . . [keytype] [Integer] 1 +. . . [keyvalue] [Octet String] "12345678" +. . [seq-number] [Integer] 17 + +encode_krb5_ap_rep_enc_part(optionals NULL): + +[Krb5 Encrypted AP-REP part] +. [Sequence/Sequence Of] +. . [ctime] [Generalized Time] "19940610060317Z" +. . [cusec] [Integer] 123456 + +encode_krb5_as_req: + +[Krb5 AS-REQ packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 10 +. . [padata] [Sequence/Sequence Of] +. . . [Sequence/Sequence Of] +. . . . [padata-type] [Integer] 13 +. . . . [pa-data] [Octet String] "pa-data" +. . . [Sequence/Sequence Of] +. . . . [padata-type] [Integer] 13 +. . . . [pa-data] [Octet String] "pa-data" +. . [req-body] [Sequence/Sequence Of] +. . . [kdc-options] [Bit String] 0xfedcba90 +. . . [cname] [Sequence/Sequence Of] +. . . . [name-type] [Integer] 1 +. . . . [name-string] [Sequence/Sequence Of] +. . . . . [General string] "hftsai" +. . . . . [General string] "extra" +. . . [realm] [General string] "ATHENA.MIT.EDU" +. . . [sname] [Sequence/Sequence Of] +. . . . [name-type] [Integer] 1 +. . . . [name-string] [Sequence/Sequence Of] +. . . . . [General string] "hftsai" +. . . . . [General string] "extra" +. . . [from] [Generalized Time] "19940610060317Z" +. . . [till] [Generalized Time] "19940610060317Z" +. . . [rtime] [Generalized Time] "19940610060317Z" +. . . [nonce] [Integer] 42 +. . . [etype] [Sequence/Sequence Of] +. . . . [Integer] 0 +. . . . [Integer] 1 +. . . [addresses] [Sequence/Sequence Of] +. . . . [Sequence/Sequence Of] +. . . . . [addr-type] [Integer] 2 +. . . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . . . [Sequence/Sequence Of] +. . . . . [addr-type] [Integer] 2 +. . . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . . [enc-authorization-data] [Sequence/Sequence Of] +. . . . [etype] [Integer] 0 +. . . . [kvno] [Integer] 5 +. . . . [cipher] [Octet String] "krbASN.1 test message" +. . . [additional-tickets] [Sequence/Sequence Of] +. . . . [Krb5 Ticket] +. . . . . [Sequence/Sequence Of] +. . . . . . [tkt-vno] [Integer] 5 +. . . . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . . . [sname] [Sequence/Sequence Of] +. . . . . . . [name-type] [Integer] 1 +. . . . . . . [name-string] [Sequence/Sequence Of] +. . . . . . . . [General string] "hftsai" +. . . . . . . . [General string] "extra" +. . . . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . . . [etype] [Integer] 0 +. . . . . . . [kvno] [Integer] 5 +. . . . . . . [cipher] [Octet String] "krbASN.1 test message" +. . . . [Krb5 Ticket] +. . . . . [Sequence/Sequence Of] +. . . . . . [tkt-vno] [Integer] 5 +. . . . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . . . [sname] [Sequence/Sequence Of] +. . . . . . . [name-type] [Integer] 1 +. . . . . . . [name-string] [Sequence/Sequence Of] +. . . . . . . . [General string] "hftsai" +. . . . . . . . [General string] "extra" +. . . . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . . . [etype] [Integer] 0 +. . . . . . . [kvno] [Integer] 5 +. . . . . . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_as_req(optionals NULL except second_ticket): + +[Krb5 AS-REQ packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 10 +. . [req-body] [Sequence/Sequence Of] +. . . [kdc-options] [Bit String] 0xfedcba98 +. . . [realm] [General string] "ATHENA.MIT.EDU" +. . . [till] [Generalized Time] "19940610060317Z" +. . . [nonce] [Integer] 42 +. . . [etype] [Sequence/Sequence Of] +. . . . [Integer] 0 +. . . . [Integer] 1 +. . . [additional-tickets] [Sequence/Sequence Of] +. . . . [Krb5 Ticket] +. . . . . [Sequence/Sequence Of] +. . . . . . [tkt-vno] [Integer] 5 +. . . . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . . . [sname] [Sequence/Sequence Of] +. . . . . . . [name-type] [Integer] 1 +. . . . . . . [name-string] [Sequence/Sequence Of] +. . . . . . . . [General string] "hftsai" +. . . . . . . . [General string] "extra" +. . . . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . . . [etype] [Integer] 0 +. . . . . . . [kvno] [Integer] 5 +. . . . . . . [cipher] [Octet String] "krbASN.1 test message" +. . . . [Krb5 Ticket] +. . . . . [Sequence/Sequence Of] +. . . . . . [tkt-vno] [Integer] 5 +. . . . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . . . [sname] [Sequence/Sequence Of] +. . . . . . . [name-type] [Integer] 1 +. . . . . . . [name-string] [Sequence/Sequence Of] +. . . . . . . . [General string] "hftsai" +. . . . . . . . [General string] "extra" +. . . . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . . . [etype] [Integer] 0 +. . . . . . . [kvno] [Integer] 5 +. . . . . . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_as_req(optionals NULL except server): + +[Krb5 AS-REQ packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 10 +. . [req-body] [Sequence/Sequence Of] +. . . [kdc-options] [Bit String] 0xfedcba90 +. . . [realm] [General string] "ATHENA.MIT.EDU" +. . . [sname] [Sequence/Sequence Of] +. . . . [name-type] [Integer] 1 +. . . . [name-string] [Sequence/Sequence Of] +. . . . . [General string] "hftsai" +. . . . . [General string] "extra" +. . . [till] [Generalized Time] "19940610060317Z" +. . . [nonce] [Integer] 42 +. . . [etype] [Sequence/Sequence Of] +. . . . [Integer] 0 +. . . . [Integer] 1 + +encode_krb5_tgs_req: + +[Krb5 TGS-REQ packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 12 +. . [padata] [Sequence/Sequence Of] +. . . [Sequence/Sequence Of] +. . . . [padata-type] [Integer] 13 +. . . . [pa-data] [Octet String] "pa-data" +. . . [Sequence/Sequence Of] +. . . . [padata-type] [Integer] 13 +. . . . [pa-data] [Octet String] "pa-data" +. . [req-body] [Sequence/Sequence Of] +. . . [kdc-options] [Bit String] 0xfedcba90 +. . . [cname] [Sequence/Sequence Of] +. . . . [name-type] [Integer] 1 +. . . . [name-string] [Sequence/Sequence Of] +. . . . . [General string] "hftsai" +. . . . . [General string] "extra" +. . . [realm] [General string] "ATHENA.MIT.EDU" +. . . [sname] [Sequence/Sequence Of] +. . . . [name-type] [Integer] 1 +. . . . [name-string] [Sequence/Sequence Of] +. . . . . [General string] "hftsai" +. . . . . [General string] "extra" +. . . [from] [Generalized Time] "19940610060317Z" +. . . [till] [Generalized Time] "19940610060317Z" +. . . [rtime] [Generalized Time] "19940610060317Z" +. . . [nonce] [Integer] 42 +. . . [etype] [Sequence/Sequence Of] +. . . . [Integer] 0 +. . . . [Integer] 1 +. . . [addresses] [Sequence/Sequence Of] +. . . . [Sequence/Sequence Of] +. . . . . [addr-type] [Integer] 2 +. . . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . . . [Sequence/Sequence Of] +. . . . . [addr-type] [Integer] 2 +. . . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . . [enc-authorization-data] [Sequence/Sequence Of] +. . . . [etype] [Integer] 0 +. . . . [kvno] [Integer] 5 +. . . . [cipher] [Octet String] "krbASN.1 test message" +. . . [additional-tickets] [Sequence/Sequence Of] +. . . . [Krb5 Ticket] +. . . . . [Sequence/Sequence Of] +. . . . . . [tkt-vno] [Integer] 5 +. . . . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . . . [sname] [Sequence/Sequence Of] +. . . . . . . [name-type] [Integer] 1 +. . . . . . . [name-string] [Sequence/Sequence Of] +. . . . . . . . [General string] "hftsai" +. . . . . . . . [General string] "extra" +. . . . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . . . [etype] [Integer] 0 +. . . . . . . [kvno] [Integer] 5 +. . . . . . . [cipher] [Octet String] "krbASN.1 test message" +. . . . [Krb5 Ticket] +. . . . . [Sequence/Sequence Of] +. . . . . . [tkt-vno] [Integer] 5 +. . . . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . . . [sname] [Sequence/Sequence Of] +. . . . . . . [name-type] [Integer] 1 +. . . . . . . [name-string] [Sequence/Sequence Of] +. . . . . . . . [General string] "hftsai" +. . . . . . . . [General string] "extra" +. . . . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . . . [etype] [Integer] 0 +. . . . . . . [kvno] [Integer] 5 +. . . . . . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_tgs_req(optionals NULL except second_ticket): + +[Krb5 TGS-REQ packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 12 +. . [req-body] [Sequence/Sequence Of] +. . . [kdc-options] [Bit String] 0xfedcba98 +. . . [realm] [General string] "ATHENA.MIT.EDU" +. . . [till] [Generalized Time] "19940610060317Z" +. . . [nonce] [Integer] 42 +. . . [etype] [Sequence/Sequence Of] +. . . . [Integer] 0 +. . . . [Integer] 1 +. . . [additional-tickets] [Sequence/Sequence Of] +. . . . [Krb5 Ticket] +. . . . . [Sequence/Sequence Of] +. . . . . . [tkt-vno] [Integer] 5 +. . . . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . . . [sname] [Sequence/Sequence Of] +. . . . . . . [name-type] [Integer] 1 +. . . . . . . [name-string] [Sequence/Sequence Of] +. . . . . . . . [General string] "hftsai" +. . . . . . . . [General string] "extra" +. . . . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . . . [etype] [Integer] 0 +. . . . . . . [kvno] [Integer] 5 +. . . . . . . [cipher] [Octet String] "krbASN.1 test message" +. . . . [Krb5 Ticket] +. . . . . [Sequence/Sequence Of] +. . . . . . [tkt-vno] [Integer] 5 +. . . . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . . . [sname] [Sequence/Sequence Of] +. . . . . . . [name-type] [Integer] 1 +. . . . . . . [name-string] [Sequence/Sequence Of] +. . . . . . . . [General string] "hftsai" +. . . . . . . . [General string] "extra" +. . . . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . . . [etype] [Integer] 0 +. . . . . . . [kvno] [Integer] 5 +. . . . . . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_tgs_req(optionals NULL except server): + +[Krb5 TGS-REQ packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 12 +. . [req-body] [Sequence/Sequence Of] +. . . [kdc-options] [Bit String] 0xfedcba90 +. . . [realm] [General string] "ATHENA.MIT.EDU" +. . . [sname] [Sequence/Sequence Of] +. . . . [name-type] [Integer] 1 +. . . . [name-string] [Sequence/Sequence Of] +. . . . . [General string] "hftsai" +. . . . . [General string] "extra" +. . . [till] [Generalized Time] "19940610060317Z" +. . . [nonce] [Integer] 42 +. . . [etype] [Sequence/Sequence Of] +. . . . [Integer] 0 +. . . . [Integer] 1 + +encode_krb5_kdc_req_body: + +[Sequence/Sequence Of] +. [kdc-options] [Bit String] 0xfedcba90 +. [cname] [Sequence/Sequence Of] +. . [name-type] [Integer] 1 +. . [name-string] [Sequence/Sequence Of] +. . . [General string] "hftsai" +. . . [General string] "extra" +. [realm] [General string] "ATHENA.MIT.EDU" +. [sname] [Sequence/Sequence Of] +. . [name-type] [Integer] 1 +. . [name-string] [Sequence/Sequence Of] +. . . [General string] "hftsai" +. . . [General string] "extra" +. [from] [Generalized Time] "19940610060317Z" +. [till] [Generalized Time] "19940610060317Z" +. [rtime] [Generalized Time] "19940610060317Z" +. [nonce] [Integer] 42 +. [etype] [Sequence/Sequence Of] +. . [Integer] 0 +. . [Integer] 1 +. [addresses] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [addr-type] [Integer] 2 +. . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . [Sequence/Sequence Of] +. . . [addr-type] [Integer] 2 +. . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. [enc-authorization-data] [Sequence/Sequence Of] +. . [etype] [Integer] 0 +. . [kvno] [Integer] 5 +. . [cipher] [Octet String] "krbASN.1 test message" +. [additional-tickets] [Sequence/Sequence Of] +. . [Krb5 Ticket] +. . . [Sequence/Sequence Of] +. . . . [tkt-vno] [Integer] 5 +. . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . [sname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . [etype] [Integer] 0 +. . . . . [kvno] [Integer] 5 +. . . . . [cipher] [Octet String] "krbASN.1 test message" +. . [Krb5 Ticket] +. . . [Sequence/Sequence Of] +. . . . [tkt-vno] [Integer] 5 +. . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . [sname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . [etype] [Integer] 0 +. . . . . [kvno] [Integer] 5 +. . . . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_kdc_req_body(optionals NULL except second_ticket): + +[Sequence/Sequence Of] +. [kdc-options] [Bit String] 0xfedcba98 +. [realm] [General string] "ATHENA.MIT.EDU" +. [till] [Generalized Time] "19940610060317Z" +. [nonce] [Integer] 42 +. [etype] [Sequence/Sequence Of] +. . [Integer] 0 +. . [Integer] 1 +. [additional-tickets] [Sequence/Sequence Of] +. . [Krb5 Ticket] +. . . [Sequence/Sequence Of] +. . . . [tkt-vno] [Integer] 5 +. . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . [sname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . [etype] [Integer] 0 +. . . . . [kvno] [Integer] 5 +. . . . . [cipher] [Octet String] "krbASN.1 test message" +. . [Krb5 Ticket] +. . . [Sequence/Sequence Of] +. . . . [tkt-vno] [Integer] 5 +. . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . [sname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . [etype] [Integer] 0 +. . . . . [kvno] [Integer] 5 +. . . . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_kdc_req_body(optionals NULL except server): + +[Sequence/Sequence Of] +. [kdc-options] [Bit String] 0xfedcba90 +. [realm] [General string] "ATHENA.MIT.EDU" +. [sname] [Sequence/Sequence Of] +. . [name-type] [Integer] 1 +. . [name-string] [Sequence/Sequence Of] +. . . [General string] "hftsai" +. . . [General string] "extra" +. [till] [Generalized Time] "19940610060317Z" +. [nonce] [Integer] 42 +. [etype] [Sequence/Sequence Of] +. . [Integer] 0 +. . [Integer] 1 + +encode_krb5_safe: + +[Krb5 SAFE packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 20 +. . [safe-body] [Sequence/Sequence Of] +. . . [user-data] [Octet String] "krb5data" +. . . [timestamp] [Generalized Time] "19940610060317Z" +. . . [usec] [Integer] 123456 +. . . [seq-number] [Integer] 17 +. . . [s-address] [Sequence/Sequence Of] +. . . . [addr-type] [Integer] 2 +. . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . . [r-address] [Sequence/Sequence Of] +. . . . [addr-type] [Integer] 2 +. . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . [cksum] [Sequence/Sequence Of] +. . . [cksumtype] [Integer] 1 +. . . [checksum] [Octet String] "1234" + +encode_krb5_safe(optionals NULL): + +[Krb5 SAFE packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 20 +. . [safe-body] [Sequence/Sequence Of] +. . . [user-data] [Octet String] "krb5data" +. . . [s-address] [Sequence/Sequence Of] +. . . . [addr-type] [Integer] 2 +. . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . [cksum] [Sequence/Sequence Of] +. . . [cksumtype] [Integer] 1 +. . . [checksum] [Octet String] "1234" + +encode_krb5_priv: + +[Krb5 PRIV packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 21 +. . [3] [Sequence/Sequence Of] +. . . [pvno] [Integer] 0 +. . . [msg-type] [Integer] 5 +. . . [enc-part] [Octet String] "krbASN.1 test message" + +encode_krb5_enc_priv_part: + +[Krb5 Encrypted PRIV part] +. [Sequence/Sequence Of] +. . [user-data] [Octet String] "krb5data" +. . [timestamp] [Generalized Time] "19940610060317Z" +. . [usec] [Integer] 123456 +. . [seq-number] [Integer] 17 +. . [s-address] [Sequence/Sequence Of] +. . . [addr-type] [Integer] 2 +. . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . [r-address] [Sequence/Sequence Of] +. . . [addr-type] [Integer] 2 +. . . [address] [Octet String] <4> + 12 d0 00 23 ...# + +encode_krb5_enc_priv_part(optionals NULL): + +[Krb5 Encrypted PRIV part] +. [Sequence/Sequence Of] +. . [user-data] [Octet String] "krb5data" +. . [s-address] [Sequence/Sequence Of] +. . . [addr-type] [Integer] 2 +. . . [address] [Octet String] <4> + 12 d0 00 23 ...# + +encode_krb5_cred: + +[Krb5 CRED packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 22 +. . [tickets] [Sequence/Sequence Of] +. . . [Krb5 Ticket] +. . . . [Sequence/Sequence Of] +. . . . . [tkt-vno] [Integer] 5 +. . . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . . [sname] [Sequence/Sequence Of] +. . . . . . [name-type] [Integer] 1 +. . . . . . [name-string] [Sequence/Sequence Of] +. . . . . . . [General string] "hftsai" +. . . . . . . [General string] "extra" +. . . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . . [etype] [Integer] 0 +. . . . . . [kvno] [Integer] 5 +. . . . . . [cipher] [Octet String] "krbASN.1 test message" +. . . [Krb5 Ticket] +. . . . [Sequence/Sequence Of] +. . . . . [tkt-vno] [Integer] 5 +. . . . . [realm] [General string] "ATHENA.MIT.EDU" +. . . . . [sname] [Sequence/Sequence Of] +. . . . . . [name-type] [Integer] 1 +. . . . . . [name-string] [Sequence/Sequence Of] +. . . . . . . [General string] "hftsai" +. . . . . . . [General string] "extra" +. . . . . [tkt-enc-part] [Sequence/Sequence Of] +. . . . . . [etype] [Integer] 0 +. . . . . . [kvno] [Integer] 5 +. . . . . . [cipher] [Octet String] "krbASN.1 test message" +. . [enc-part] [Sequence/Sequence Of] +. . . [etype] [Integer] 0 +. . . [kvno] [Integer] 5 +. . . [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_enc_cred_part: + +[Krb5 Encrypted CRED part] +. [Sequence/Sequence Of] +. . [ticket-info] [Sequence/Sequence Of] +. . . [Sequence/Sequence Of] +. . . . [key] [Sequence/Sequence Of] +. . . . . [keytype] [Integer] 1 +. . . . . [keyvalue] [Octet String] "12345678" +. . . . [prealm] [General string] "ATHENA.MIT.EDU" +. . . . [pname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [flags] [Bit String] 0xfedcba98 +. . . . [authtime] [Generalized Time] "19940610060317Z" +. . . . [startime] [Generalized Time] "19940610060317Z" +. . . . [endtime] [Generalized Time] "19940610060317Z" +. . . . [renew-till] [Generalized Time] "19940610060317Z" +. . . . [srealm] [General string] "ATHENA.MIT.EDU" +. . . . [sname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [caddr] [Sequence/Sequence Of] +. . . . . [Sequence/Sequence Of] +. . . . . . [addr-type] [Integer] 2 +. . . . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . . . . [Sequence/Sequence Of] +. . . . . . [addr-type] [Integer] 2 +. . . . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . . [Sequence/Sequence Of] +. . . . [key] [Sequence/Sequence Of] +. . . . . [keytype] [Integer] 1 +. . . . . [keyvalue] [Octet String] "12345678" +. . . . [prealm] [General string] "ATHENA.MIT.EDU" +. . . . [pname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [flags] [Bit String] 0xfedcba98 +. . . . [authtime] [Generalized Time] "19940610060317Z" +. . . . [startime] [Generalized Time] "19940610060317Z" +. . . . [endtime] [Generalized Time] "19940610060317Z" +. . . . [renew-till] [Generalized Time] "19940610060317Z" +. . . . [srealm] [General string] "ATHENA.MIT.EDU" +. . . . [sname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [caddr] [Sequence/Sequence Of] +. . . . . [Sequence/Sequence Of] +. . . . . . [addr-type] [Integer] 2 +. . . . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . . . . [Sequence/Sequence Of] +. . . . . . [addr-type] [Integer] 2 +. . . . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . [nonce] [Integer] 42 +. . [timestamp] [Generalized Time] "19940610060317Z" +. . [usec] [Integer] 123456 +. . [s-address] [Sequence/Sequence Of] +. . . [addr-type] [Integer] 2 +. . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . [r-address] [Sequence/Sequence Of] +. . . [addr-type] [Integer] 2 +. . . [address] [Octet String] <4> + 12 d0 00 23 ...# + +encode_krb5_enc_cred_part(optionals NULL): + +[Krb5 Encrypted CRED part] +. [Sequence/Sequence Of] +. . [ticket-info] [Sequence/Sequence Of] +. . . [Sequence/Sequence Of] +. . . . [key] [Sequence/Sequence Of] +. . . . . [keytype] [Integer] 1 +. . . . . [keyvalue] [Octet String] "12345678" +. . . [Sequence/Sequence Of] +. . . . [key] [Sequence/Sequence Of] +. . . . . [keytype] [Integer] 1 +. . . . . [keyvalue] [Octet String] "12345678" +. . . . [prealm] [General string] "ATHENA.MIT.EDU" +. . . . [pname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [flags] [Bit String] 0xfedcba98 +. . . . [authtime] [Generalized Time] "19940610060317Z" +. . . . [startime] [Generalized Time] "19940610060317Z" +. . . . [endtime] [Generalized Time] "19940610060317Z" +. . . . [renew-till] [Generalized Time] "19940610060317Z" +. . . . [srealm] [General string] "ATHENA.MIT.EDU" +. . . . [sname] [Sequence/Sequence Of] +. . . . . [name-type] [Integer] 1 +. . . . . [name-string] [Sequence/Sequence Of] +. . . . . . [General string] "hftsai" +. . . . . . [General string] "extra" +. . . . [caddr] [Sequence/Sequence Of] +. . . . . [Sequence/Sequence Of] +. . . . . . [addr-type] [Integer] 2 +. . . . . . [address] [Octet String] <4> + 12 d0 00 23 ...# +. . . . . [Sequence/Sequence Of] +. . . . . . [addr-type] [Integer] 2 +. . . . . . [address] [Octet String] <4> + 12 d0 00 23 ...# + +encode_krb5_error: + +[Krb5 ERROR packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 30 +. . [ctime] [Generalized Time] "19940610060317Z" +. . [cusec] [Integer] 123456 +. . [stime] [Generalized Time] "19940610060317Z" +. . [susec] [Integer] 123456 +. . [error-code] [Integer] 60 +. . [crealm] [General string] "ATHENA.MIT.EDU" +. . [cname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [realm] [General string] "ATHENA.MIT.EDU" +. . [sname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [e-text] [General string] "krb5data" +. . [e-data] [Octet String] "krb5data" + +encode_krb5_error(optionals NULL): + +[Krb5 ERROR packet] +. [Sequence/Sequence Of] +. . [pvno] [Integer] 5 +. . [msg-type] [Integer] 30 +. . [cusec] [Integer] 123456 +. . [stime] [Generalized Time] "19940610060317Z" +. . [susec] [Integer] 123456 +. . [error-code] [Integer] 60 +. . [realm] [General string] "ATHENA.MIT.EDU" +. . [sname] [Sequence/Sequence Of] +. . . [name-type] [Integer] 1 +. . . [name-string] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" + +encode_krb5_authorization_data: + +[Sequence/Sequence Of] +. [Sequence/Sequence Of] +. . [ad-type] [Integer] 1 +. . [ad-data] [Octet String] "foobar" +. [Sequence/Sequence Of] +. . [ad-type] [Integer] 1 +. . [ad-data] [Octet String] "foobar" + +encode_krb5_padata_sequence: + +[Sequence/Sequence Of] +. [Sequence/Sequence Of] +. . [1] [Integer] 13 +. . [2] [Octet String] "pa-data" +. [Sequence/Sequence Of] +. . [1] [Integer] 13 +. . [2] [Octet String] "pa-data" + +encode_krb5_typed_data: + +[Sequence/Sequence Of] +. [Sequence/Sequence Of] +. . [0] [Integer] 13 +. . [1] [Octet String] "pa-data" +. [Sequence/Sequence Of] +. . [0] [Integer] 13 +. . [1] [Octet String] "pa-data" + +encode_krb5_padata_sequence(empty): + +[Sequence/Sequence Of] + +encode_krb5_etype_info: + +[Sequence/Sequence Of] +. [Sequence/Sequence Of] +. . [0] [Integer] 0 +. . [1] [Octet String] "Morton's #0" +. [Sequence/Sequence Of] +. . [0] [Integer] 1 +. [Sequence/Sequence Of] +. . [0] [Integer] 2 +. . [1] [Octet String] "Morton's #2" + +encode_krb5_etype_info(only 1): + +[Sequence/Sequence Of] +. [Sequence/Sequence Of] +. . [0] [Integer] 0 +. . [1] [Octet String] "Morton's #0" + +encode_krb5_etype_info(no info): + +[Sequence/Sequence Of] + +encode_krb5_etype_info2: + +[Sequence/Sequence Of] +. [Sequence/Sequence Of] +. . [0] [Integer] 0 +. . [1] [General string] "Morton's #0" +. . [2] [Octet String] "s2k: 0" +. [Sequence/Sequence Of] +. . [0] [Integer] 1 +. . [2] [Octet String] "s2k: 1" +. [Sequence/Sequence Of] +. . [0] [Integer] 2 +. . [1] [General string] "Morton's #2" +. . [2] [Octet String] "s2k: 2" + +encode_krb5_etype_info2(only 1): + +[Sequence/Sequence Of] +. [Sequence/Sequence Of] +. . [0] [Integer] 0 +. . [1] [General string] "Morton's #0" +. . [2] [Octet String] "s2k: 0" + +encode_krb5_pa_enc_ts: + +[Sequence/Sequence Of] +. [0] [Generalized Time] "19940610060317Z" +. [1] [Integer] 123456 + +encode_krb5_pa_enc_ts (no usec): + +[Sequence/Sequence Of] +. [0] [Generalized Time] "19940610060317Z" + +encode_krb5_enc_data: + +[Sequence/Sequence Of] +. [etype] [Integer] 0 +. [kvno] [Integer] 5 +. [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_enc_data(MSB-set kvno): + +[Sequence/Sequence Of] +. [etype] [Integer] 0 +. [kvno] [Integer] -16777216 +. [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_enc_data(kvno=-1): + +[Sequence/Sequence Of] +. [etype] [Integer] 0 +. [kvno] [Integer] -1 +. [cipher] [Octet String] "krbASN.1 test message" + +encode_krb5_sam_challenge_2: + +[Sequence/Sequence Of] +. [0] [Sequence/Sequence Of] +. . [Octet String] "challenge" +. [1] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Octet String] "1234" + +encode_krb5_sam_challenge_2_body: + +[Sequence/Sequence Of] +. [0] [Integer] 42 +. [1] [Bit String] 0x80000000 +. [2] [Octet String] "type name" +. [4] [Octet String] "challenge label" +. [5] [Octet String] "challenge ipse" +. [6] [Octet String] "response_prompt ipse" +. [8] [Integer] 5517840 +. [9] [Integer] 20 + +encode_krb5_sam_response_2: + +[Sequence/Sequence Of] +. [0] [Integer] 43 +. [1] [Bit String] 0x80000000 +. [2] [Octet String] "track data" +. [3] [Sequence/Sequence Of] +. . [0] [Integer] 20 +. . [1] [Integer] 3382 +. . [2] [Octet String] "nonce or sad" +. [4] [Integer] 5517840 + +encode_krb5_enc_sam_response_enc_2: + +[Sequence/Sequence Of] +. [0] [Integer] 88 +. [1] [Octet String] "enc_sam_response_enc_2" + +encode_krb5_pa_for_user: + +[Sequence/Sequence Of] +. [0] [Sequence/Sequence Of] +. . [0] [Integer] 1 +. . [1] [Sequence/Sequence Of] +. . . [General string] "hftsai" +. . . [General string] "extra" +. [1] [General string] "ATHENA.MIT.EDU" +. [2] [Sequence/Sequence Of] +. . [0] [Integer] 1 +. . [1] [Octet String] "1234" +. [3] [General string] "krb5data" + +encode_krb5_pa_s4u_x509_user: + +[Sequence/Sequence Of] +. [0] [Sequence/Sequence Of] +. . [0] [Integer] 13243546 +. . [1] [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [2] [General string] "ATHENA.MIT.EDU" +. . [3] [Octet String] "pa_s4u_x509_user" +. . [4] [Bit String] 0x80000000 +. [1] [Sequence/Sequence Of] +. . [0] [Integer] 1 +. . [1] [Octet String] "1234" + +encode_krb5_ad_kdcissued: + +[Sequence/Sequence Of] +. [0] [Sequence/Sequence Of] +. . [0] [Integer] 1 +. . [1] [Octet String] "1234" +. [1] [General string] "ATHENA.MIT.EDU" +. [2] [Sequence/Sequence Of] +. . [0] [Integer] 1 +. . [1] [Sequence/Sequence Of] +. . . [General string] "hftsai" +. . . [General string] "extra" +. [3] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Octet String] "foobar" +. . [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Octet String] "foobar" + +encode_krb5_iakerb_header: + +[Sequence/Sequence Of] +. [1] [Octet String] "krb5data" +. [2] [Octet String] "krb5data" + +encode_krb5_iakerb_finished: + +[Sequence/Sequence Of] +. [1] [Sequence/Sequence Of] +. . [0] [Integer] 1 +. . [1] [Octet String] "1234" + +encode_krb5_fast_response: + +[Sequence/Sequence Of] +. [0] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [1] [Integer] 13 +. . . [2] [Octet String] "pa-data" +. . [Sequence/Sequence Of] +. . . [1] [Integer] 13 +. . . [2] [Octet String] "pa-data" +. [1] [Sequence/Sequence Of] +. . [0] [Integer] 1 +. . [1] [Octet String] "12345678" +. [2] [Sequence/Sequence Of] +. . [0] [Generalized Time] "19940610060317Z" +. . [1] [Integer] 123456 +. . [2] [General string] "ATHENA.MIT.EDU" +. . [3] [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [4] [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Octet String] "1234" +. [3] [Integer] 42 + +encode_krb5_pa_fx_fast_reply: + +[CONT 0] +. [Sequence/Sequence Of] +. . [0] [Sequence/Sequence Of] +. . . [0] [Integer] 0 +. . . [1] [Integer] 5 +. . . [2] [Octet String] "krbASN.1 test message" + +encode_krb5_otp_tokeninfo(optionals NULL): + +[Sequence/Sequence Of] +. [0] <5> + 00 00 00 00 00 ..... + +encode_krb5_otp_tokeninfo: + +[Sequence/Sequence Of] +. [0] <5> + 00 77 00 00 00 .w... +. [1] <11> + 45 78 61 6d 70 6c 65 63 6f 72 70 Examplecorp +. [2] <5> + 68 61 72 6b 21 hark! +. [3] 0x0 (10 unused bits) +. [4] <1> + 02 . +. [5] <9> + 79 6f 75 72 74 6f 6b 65 6e yourtoken +. [6] <40> + 75 72 6e 3a 69 65 74 66 3a 70 61 72 61 6d 73 3a urn:ietf:params: + 78 6d 6c 3a 6e 73 3a 6b 65 79 70 72 6f 76 3a 70 xml:ns:keyprov:p + 73 6b 63 3a 68 6f 74 70 skc:hotp +. [7] [Sequence/Sequence Of] +. . [Object Identifier] <9> + 60 86 48 01 65 03 04 02 01 `.H.e.... +. [Sequence/Sequence Of] +. . [Object Identifier] <5> + 2b 0e 03 02 1a +.... +. [8] <2> + 03 e8 .. + +encode_krb5_pa_otp_challenge(optionals NULL): + +[Sequence/Sequence Of] +. [0] <8> + 6d 69 6e 6e 6f 6e 63 65 minnonce +. [2] [Sequence/Sequence Of] +. . [0] <5> + 00 00 00 00 00 ..... + +encode_krb5_pa_otp_challenge: + +[Sequence/Sequence Of] +. [0] <8> + 6d 61 78 6e 6f 6e 63 65 maxnonce +. [1] <11> + 74 65 73 74 73 65 72 76 69 63 65 testservice +. [2] [Sequence/Sequence Of] +. . [0] <5> + 00 00 00 00 00 ..... +. [Sequence/Sequence Of] +. . [0] <5> + 00 77 00 00 00 .w... +. . [1] <11> + 45 78 61 6d 70 6c 65 63 6f 72 70 Examplecorp +. . [2] <5> + 68 61 72 6b 21 hark! +. . [3] 0x0 (10 unused bits) +. . [4] <1> + 02 . +. . [5] <9> + 79 6f 75 72 74 6f 6b 65 6e yourtoken +. . [6] <40> + 75 72 6e 3a 69 65 74 66 3a 70 61 72 61 6d 73 urn:ietf:params + 3a 78 6d 6c 3a 6e 73 3a 6b 65 79 70 72 6f 76 :xml:ns:keyprov + 3a 70 73 6b 63 3a 68 6f 74 70 :pskc:hotp +. . [7] [Sequence/Sequence Of] +. . . [Object Identifier] <9> + 60 86 48 01 65 03 04 02 01 `.H.e.... +. . [Sequence/Sequence Of] +. . . [Object Identifier] <5> + 2b 0e 03 02 1a +.... +. . [8] <2> + 03 e8 .. +. [3] <7> + 6b 65 79 73 61 6c 74 keysalt +. [4] "1234" + +encode_krb5_pa_otp_req(optionals NULL): + +[Sequence/Sequence Of] +. [0] <5> + 00 00 00 00 00 ..... +. [2] [0] [Integer] 0 +. [1] [Integer] 5 +. [2] [Octet String] "krbASN.1 test message" + +encode_krb5_pa_otp_req: + +[Sequence/Sequence Of] +. [0] <5> + 00 60 00 00 00 .`... +. [1] <5> + 6e 6f 6e 63 65 nonce +. [2] [0] [Integer] 0 +. [1] [Integer] 5 +. [2] [Octet String] "krbASN.1 test message" +. [3] [Object Identifier] <9> + 60 86 48 01 65 03 04 02 01 `.H.e.... +. [4] <2> + 03 e8 .. +. [5] <5> + 66 72 6f 67 73 frogs +. [6] <10> + 6d 79 66 69 72 73 74 70 69 6e myfirstpin +. [7] <5> + 68 61 72 6b 21 hark! +. [8] <15> + 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5a 19940610060317Z +. [9] <3> + 33 34 36 346 +. [10] <1> + 02 . +. [11] <9> + 79 6f 75 72 74 6f 6b 65 6e yourtoken +. [12] <40> + 75 72 6e 3a 69 65 74 66 3a 70 61 72 61 6d 73 3a urn:ietf:params: + 78 6d 6c 3a 6e 73 3a 6b 65 79 70 72 6f 76 3a 70 xml:ns:keyprov:p + 73 6b 63 3a 68 6f 74 70 skc:hotp +. [13] <11> + 45 78 61 6d 70 6c 65 63 6f 72 70 Examplecorp + +encode_krb5_pa_otp_enc_req: + +[Sequence/Sequence Of] +. [0] <8> + 6b 72 62 35 64 61 74 61 krb5data + +encode_krb5_kkdcp_message: + +[Sequence/Sequence Of] +. [0] [Octet String] <488> + 6a 82 01 e4 30 82 01 e0 a1 03 02 01 05 a2 03 02 j...0........... + 01 0a a3 26 30 24 30 10 a1 03 02 01 0d a2 09 04 ...&0$0......... + 07 70 61 2d 64 61 74 61 30 10 a1 03 02 01 0d a2 .pa-data0....... + 09 04 07 70 61 2d 64 61 74 61 a4 82 01 aa 30 82 ...pa-data....0. + 01 a6 a0 07 03 05 00 fe dc ba 98 a1 1a 30 18 a0 .............0.. + 03 02 01 01 a1 11 30 0f 1b 06 68 66 74 73 61 69 ......0...hftsai + 1b 05 65 78 74 72 61 a2 10 1b 0e 41 54 48 45 4e ..extra....ATHEN + 41 2e 4d 49 54 2e 45 44 55 a3 1a 30 18 a0 03 02 A.MIT.EDU..0.... + 01 01 a1 11 30 0f 1b 06 68 66 74 73 61 69 1b 05 ....0...hftsai.. + 65 78 74 72 61 a4 11 18 0f 31 39 39 34 30 36 31 extra....1994061 + 30 30 36 30 33 31 37 5a a5 11 18 0f 31 39 39 34 0060317Z....1994 + 30 36 31 30 30 36 30 33 31 37 5a a6 11 18 0f 31 0610060317Z....1 + 39 39 34 30 36 31 30 30 36 30 33 31 37 5a a7 03 9940610060317Z.. + 02 01 2a a8 08 30 06 02 01 00 02 01 01 a9 20 30 ..*..0........ 0 + 1e 30 0d a0 03 02 01 02 a1 06 04 04 12 d0 00 23 .0.............# + 30 0d a0 03 02 01 02 a1 06 04 04 12 d0 00 23 aa 0.............#. + 25 30 23 a0 03 02 01 00 a1 03 02 01 05 a2 17 04 %0#............. + 15 6b 72 62 41 53 4e 2e 31 20 74 65 73 74 20 6d .krbASN.1 test m + 65 73 73 61 67 65 ab 81 bf 30 81 bc 61 5c 30 5a essage...0..a\0Z + a0 03 02 01 05 a1 10 1b 0e 41 54 48 45 4e 41 2e .........ATHENA. + 4d 49 54 2e 45 44 55 a2 1a 30 18 a0 03 02 01 01 MIT.EDU..0...... + a1 11 30 0f 1b 06 68 66 74 73 61 69 1b 05 65 78 ..0...hftsai..ex + 74 72 61 a3 25 30 23 a0 03 02 01 00 a1 03 02 01 tra.%0#......... + 05 a2 17 04 15 6b 72 62 41 53 4e 2e 31 20 74 65 .....krbASN.1 te + 73 74 20 6d 65 73 73 61 67 65 61 5c 30 5a a0 03 st messagea\0Z.. + 02 01 05 a1 10 1b 0e 41 54 48 45 4e 41 2e 4d 49 .......ATHENA.MI + 54 2e 45 44 55 a2 1a 30 18 a0 03 02 01 01 a1 11 T.EDU..0........ + 30 0f 1b 06 68 66 74 73 61 69 1b 05 65 78 74 72 0...hftsai..extr + 61 a3 25 30 23 a0 03 02 01 00 a1 03 02 01 05 a2 a.%0#........... + 17 04 15 6b 72 62 41 53 4e 2e 31 20 74 65 73 74 ...krbASN.1 test + 20 6d 65 73 73 61 67 65 message +. [1] [General string] "krb5data" + +encode_krb5_cammac(optionals NULL): + +[Sequence/Sequence Of] +. [0] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Octet String] "ad1" + +encode_krb5_cammac: + +[Sequence/Sequence Of] +. [0] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Octet String] "ad1" +. . [Sequence/Sequence Of] +. . . [0] [Integer] 2 +. . . [1] [Octet String] "ad2" +. [1] [Sequence/Sequence Of] +. . [0] [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [1] [Integer] 5 +. . [2] [Integer] 16 +. . [3] [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Octet String] "cksumkdc" +. [2] [Sequence/Sequence Of] +. . [0] [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Sequence/Sequence Of] +. . . . [General string] "hftsai" +. . . . [General string] "extra" +. . [1] [Integer] 5 +. . [2] [Integer] 16 +. . [3] [Sequence/Sequence Of] +. . . [0] [Integer] 1 +. . . [1] [Octet String] "cksumsvc" +. [3] [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [3] [Sequence/Sequence Of] +. . . . [0] [Integer] 1 +. . . . [1] [Octet String] "cksum1" +. . [Sequence/Sequence Of] +. . . [0] [Sequence/Sequence Of] +. . . . [0] [Integer] 1 +. . . . [1] [Sequence/Sequence Of] +. . . . . [General string] "hftsai" +. . . . . [General string] "extra" +. . . [1] [Integer] 5 +. . . [2] [Integer] 16 +. . . [3] [Sequence/Sequence Of] +. . . . [0] [Integer] 1 +. . . . [1] [Octet String] "cksum2" + +encode_krb5_secure_cookie: + +[Sequence/Sequence Of] +. [Integer] 771228197 +. [Sequence/Sequence Of] +. . [Sequence/Sequence Of] +. . . [1] [Integer] 13 +. . . [2] [Octet String] "pa-data" +. . [Sequence/Sequence Of] +. . . [1] [Integer] 13 +. . . [2] [Octet String] "pa-data" + +encode_krb5_spake_factor(optionals NULL): + +[Sequence/Sequence Of] +. [0] [Integer] 1 + +encode_krb5_spake_factor: + +[Sequence/Sequence Of] +. [0] [Integer] 2 +. [1] [Octet String] "fdata" + +encode_krb5_pa_spake(support): + +[CONT 0] +. [Sequence/Sequence Of] +. . [0] [Sequence/Sequence Of] +. . . [Integer] 1 +. . . [Integer] 2 + +encode_krb5_pa_spake(challenge): + +[CONT 1] +. [Sequence/Sequence Of] +. . [0] [Integer] 1 +. . [1] [Octet String] "T value" +. . [2] [Sequence/Sequence Of] +. . . [Sequence/Sequence Of] +. . . . [0] [Integer] 1 +. . . [Sequence/Sequence Of] +. . . . [0] [Integer] 2 +. . . . [1] [Octet String] "fdata" + +encode_krb5_pa_spake(response): + +[CONT 2] +. [Sequence/Sequence Of] +. . [0] [Octet String] "S value" +. . [1] [Sequence/Sequence Of] +. . . [0] [Integer] 0 +. . . [1] [Integer] 5 +. . . [2] [Octet String] "krbASN.1 test message" + +encode_krb5_pa_spake(encdata): + +[CONT 3] +. [Sequence/Sequence Of] +. . [0] [Integer] 0 +. . [1] [Integer] 5 +. . [2] [Octet String] "krbASN.1 test message" diff --git a/krb5-1.21.3/src/tests/asn.1/utility.c b/krb5-1.21.3/src/tests/asn.1/utility.c new file mode 100644 index 00000000..b1eb902a --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/utility.c @@ -0,0 +1,142 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/asn.1/utility.c */ +/* + * Copyright (C) 1994 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "utility.h" +#include "krb5.h" +#include +#include +#include + +krb5int_access acc; + +char hexchar (const unsigned int digit); + +void * +ealloc(size_t size) +{ + void *ptr = calloc(1, size); + + if (ptr == NULL) + abort(); + return ptr; +} + +char * +estrdup(const char *str) +{ + char *newstr = strdup(str); + + if (newstr == NULL) + abort(); + return newstr; +} + +void +asn1_krb5_data_unparse(const krb5_data *code, char **s) +{ + if (*s != NULL) free(*s); + + if (code==NULL) { + *s = estrdup(""); + } else if (code->data == NULL || ((int) code->length) <= 0) { + *s = estrdup(""); + } else { + unsigned int i; + + *s = ealloc(3 * code->length); + for (i = 0; i < code->length; i++) { + (*s)[3*i] = hexchar((unsigned char) (((code->data)[i]&0xF0)>>4)); + (*s)[3*i+1] = hexchar((unsigned char) ((code->data)[i]&0x0F)); + (*s)[3*i+2] = ' '; + } + (*s)[3*(code->length)-1] = '\0'; + } +} + +char +hexchar(const unsigned int digit) +{ + if (digit<=9) + return '0'+digit; + else if (digit<=15) + return 'A'+digit-10; + else + return 'X'; +} + +void +krb5_data_parse(krb5_data *d, const char *s) +{ + d->length = strlen(s); + d->data = ealloc(d->length); + memcpy(d->data, s, d->length); +} + +krb5_error_code +krb5_data_hex_parse(krb5_data *d, const char *s) +{ + int lo; + long v; + const char *cp; + char *dp; + char buf[2]; + + d->data = ealloc(strlen(s) / 2 + 1); + d->length = 0; + buf[1] = '\0'; + for (lo = 0, dp = d->data, cp = s; *cp; cp++) { + if (*cp < 0) + return ASN1_PARSE_ERROR; + else if (isspace((unsigned char) *cp)) + continue; + else if (isxdigit((unsigned char) *cp)) { + buf[0] = *cp; + v = strtol(buf, NULL, 16); + } else + return ASN1_PARSE_ERROR; + if (lo) { + *dp++ |= v; + lo = 0; + } else { + *dp = v << 4; + lo = 1; + } + } + + d->length = dp - d->data; + return 0; +} + +void +init_access(const char *progname) +{ + krb5_error_code ret; + ret = krb5int_accessor(&acc, KRB5INT_ACCESS_VERSION); + if (ret) { + com_err(progname, ret, "while initializing accessor"); + exit(1); + } +} diff --git a/krb5-1.21.3/src/tests/asn.1/utility.h b/krb5-1.21.3/src/tests/asn.1/utility.h new file mode 100644 index 00000000..e14507a0 --- /dev/null +++ b/krb5-1.21.3/src/tests/asn.1/utility.h @@ -0,0 +1,57 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/asn.1/utility.h */ +/* + * Copyright (C) 1994 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __UTILITY_H__ +#define __UTILITY_H__ + +#include "k5-int.h" + +/* Aborts on failure. ealloc returns zero-filled memory. */ +void *ealloc(size_t size); +char *estrdup(const char *str); + +void asn1_krb5_data_unparse(const krb5_data *code, char **s); +/* modifies *s; + effects Instantiates *s with a string representation of the series + of hex octets in *code. (e.g. "02 02 00 7F") If code==NULL, + the string rep is "". If code is empty (it contains no + data or has length <= 0), the string rep is "". + If *s is non-NULL, then its currently-allocated storage + will be freed prior to the instantiation. + Returns ENOMEM or the string rep cannot be created. */ + +void krb5_data_parse(krb5_data *d, const char *s); +/* effects Parses character string *s into krb5_data *d. */ + +krb5_error_code krb5_data_hex_parse(krb5_data *d, const char *s); +/* requires *s is the string representation of a sequence of + hexadecimal octets. (e.g. "02 01 00") + effects Parses *s into krb5_data *d. */ + +extern krb5int_access acc; +extern void init_access(const char *progname); + +#endif diff --git a/krb5-1.21.3/src/tests/au_dict.json b/krb5-1.21.3/src/tests/au_dict.json new file mode 100644 index 00000000..032d6019 --- /dev/null +++ b/krb5-1.21.3/src/tests/au_dict.json @@ -0,0 +1,64 @@ +{ +"event_name":"", +"event_success":0, +"evidence_tkt_id":"", +"fromport":0, +"fromaddr":{ + "type":0, + "length":0, + "ip":[]}, +"kdc_status":"", +"rep_etype":0, +"rep.ticket":{ + "authtime":0, + "cname":{ + "components":[], + "realm":"", + "length":0, + "type":0}, + "end":0, + "flags":0, + "sess_etype":0, + "srv_etype":0, + "sname":{ + "components":[], + "realm":"", + "length":0, + "type":0}}, +"req.avail_etypes":[], +"req.client":{ + "components":[], + "realm":"", + "length":0, + "type":0}, +"req_id":"", +"req.kdc_options":0, +"req.pa_type":[], +"req.server":{ + "components":[], + "realm":"", + "length":0, + "type":0}, +"req.tkt_end":0, +"s4u2proxy_user":{ + "components":[], + "realm":"", + "length":0, + "type":0}, +"s4u2self_user":{ + "components":[], + "realm":"", + "length":0, + "type":0}, +"stage":1, +"tkt_in_id":"", +"tkt_renewed":0, +"tkt_out_id":"", +"tkt_validated":0, +"u2u_user":{ + "components":[], + "realm":"", + "length":0, + "type":0}, +"violation":0 +} diff --git a/krb5-1.21.3/src/tests/conccache.c b/krb5-1.21.3/src/tests/conccache.c new file mode 100644 index 00000000..7b0ca630 --- /dev/null +++ b/krb5-1.21.3/src/tests/conccache.c @@ -0,0 +1,190 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/conccache.c - ccache concurrent get_creds/refresh test program */ +/* + * Copyright (C) 2021 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. + */ + +/* + * Usage: conccache ccname clientprinc serverprinc + * + * This program spawns two subprocesses. One repeatedly runs + * krb5_get_credentials() on ccname, and the other repeatedly refreshes ccname + * from the default keytab. If either subprocess fails, the program exits with + * status 1. The goal is to expose time windows where cache refreshes cause + * get_cred operations to fail. + */ + +#include "k5-platform.h" +#include +#include +#include +#include + +/* Run this many iterations of each operation. */ +static const int iterations = 200; + +/* Saved command-line arguments. */ +static const char *ccname, *server_name, *client_name; + +static void +check(krb5_error_code code) +{ + if (code) + abort(); +} + +static krb5_boolean +get_cred(krb5_context context) +{ + krb5_error_code ret; + krb5_ccache cc; + krb5_principal client, server; + krb5_creds mcred, *cred; + + check(krb5_cc_resolve(context, ccname, &cc)); + check(krb5_parse_name(context, client_name, &client)); + check(krb5_parse_name(context, server_name, &server)); + + memset(&mcred, 0, sizeof(mcred)); + mcred.client = client; + mcred.server = server; + ret = krb5_get_credentials(context, 0, cc, &mcred, &cred); + + krb5_free_creds(context, cred); + krb5_free_principal(context, client); + krb5_free_principal(context, server); + krb5_cc_close(context, cc); + + return ret == 0; +} + +static krb5_boolean +refresh_cache(krb5_context context) +{ + krb5_error_code ret; + krb5_ccache cc; + krb5_principal client; + krb5_get_init_creds_opt *opt; + krb5_creds cred; + + check(krb5_cc_resolve(context, ccname, &cc)); + check(krb5_parse_name(context, client_name, &client)); + + check(krb5_get_init_creds_opt_alloc(context, &opt)); + check(krb5_get_init_creds_opt_set_out_ccache(context, opt, cc)); + ret = krb5_get_init_creds_keytab(context, &cred, client, NULL, 0, NULL, + opt); + + krb5_get_init_creds_opt_free(context, opt); + krb5_free_cred_contents(context, &cred); + krb5_free_principal(context, client); + krb5_cc_close(context, cc); + + return ret == 0; +} + +static pid_t +spawn_cred_subprocess() +{ + krb5_context context; + pid_t pid; + int i; + + pid = fork(); + assert(pid >= 0); + if (pid > 0) + return pid; + + check(krb5_init_context(&context)); + for (i = 0; i < iterations; i++) { + if (!get_cred(context)) { + fprintf(stderr, "cred worker failed after %d successes\n", i); + exit(1); + } + } + krb5_free_context(context); + exit(0); +} + +static pid_t +spawn_refresh_subprocess() +{ + krb5_context context; + pid_t pid; + int i; + + pid = fork(); + assert(pid >= 0); + if (pid > 0) + return pid; + + check(krb5_init_context(&context)); + for (i = 0; i < iterations; i++) { + if (!refresh_cache(context)) { + fprintf(stderr, "refresh worker failed after %d successes\n", i); + exit(1); + } + } + krb5_free_context(context); + exit(0); +} + +int +main(int argc, char *argv[]) +{ + krb5_context context; + pid_t cred_pid, refresh_pid, pid; + int cstatus, rstatus; + + assert(argc == 4); + ccname = argv[1]; + client_name = argv[2]; + server_name = argv[3]; + + /* Begin with an initialized cache. */ + check(krb5_init_context(&context)); + refresh_cache(context); + krb5_free_context(context); + + cred_pid = spawn_cred_subprocess(); + refresh_pid = spawn_refresh_subprocess(); + + pid = waitpid(cred_pid, &cstatus, 0); + if (pid == -1) + abort(); + pid = waitpid(refresh_pid, &rstatus, 0); + if (pid == -1) + abort(); + + if (!WIFEXITED(cstatus) || WEXITSTATUS(cstatus) != 0) + return 1; + if (!WIFEXITED(rstatus) || WEXITSTATUS(rstatus) != 0) + return 1; + return 0; +} diff --git a/krb5-1.21.3/src/tests/create/Makefile.in b/krb5-1.21.3/src/tests/create/Makefile.in new file mode 100644 index 00000000..5a44dfd8 --- /dev/null +++ b/krb5-1.21.3/src/tests/create/Makefile.in @@ -0,0 +1,17 @@ +mydir=tests$(S)create +BUILDTOP=$(REL)..$(S).. +SRCS=$(srcdir)/kdb5_mkdums.c +KDB5_DEP_LIBS=$(THREAD_LINKOPTS) $(DL_LIB) + +all: kdb5_mkdums + +kdb5_mkdums: kdb5_mkdums.o $(KDB5_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o kdb5_mkdums kdb5_mkdums.o $(KDB5_DEP_LIBS) $(KDB5_LIBS) $(KRB5_BASE_LIBS) + +all: kdb5_mkdums + +install: + +clean: + $(RM) kdb5_mkdums.o kdb5_mkdums + diff --git a/krb5-1.21.3/src/tests/create/deps b/krb5-1.21.3/src/tests/create/deps new file mode 100644 index 00000000..a8e5e285 --- /dev/null +++ b/krb5-1.21.3/src/tests/create/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kdb5_mkdums.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SS_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdb5_mkdums.c diff --git a/krb5-1.21.3/src/tests/create/kdb5_mkdums.c b/krb5-1.21.3/src/tests/create/kdb5_mkdums.c new file mode 100644 index 00000000..7c066660 --- /dev/null +++ b/krb5-1.21.3/src/tests/create/kdb5_mkdums.c @@ -0,0 +1,406 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/create/kdb5_mkdums.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * + * Edit a KDC database. + */ + +#include "k5-int.h" +#include "kdb.h" +#include "com_err.h" +#include +#include + + +#define REALM_SEP '@' +#define REALM_SEP_STR "@" + +struct mblock { + krb5_deltat max_life; + krb5_deltat max_rlife; + krb5_timestamp expiration; + krb5_flags flags; + krb5_kvno mkvno; +} mblock = { /* XXX */ + KRB5_KDB_MAX_LIFE, + KRB5_KDB_MAX_RLIFE, + KRB5_KDB_EXPIRATION, + KRB5_KDB_DEF_FLAGS, + 1 +}; + +int set_dbname_help (char *, char *); + +static void +usage(who, status) + char *who; + int status; +{ + fprintf(stderr, + "usage: %s -p prefix -n num_to_create [-d dbpathname] [-r realmname]\n", + who); + fprintf(stderr, "\t [-D depth] [-k enctype] [-M mkeyname]\n"); + + exit(status); +} + +int master_princ_set = 0; +krb5_keyblock master_keyblock; +krb5_principal master_princ; +krb5_pointer master_random; +krb5_context test_context; + +static char *progname; +static char *cur_realm = 0; +static char *mkey_name = 0; +static char *mkey_password = 0; +static krb5_boolean manual_mkey = FALSE; + +void add_princ (krb5_context, char *); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + int optchar, i, n; + char tmp[4096], tmp2[BUFSIZ], *str_newprinc; + + krb5_error_code retval; + char *dbname = 0; + int enctypedone = 0; + int num_to_create; + char principal_string[BUFSIZ]; + char *suffix = 0; + size_t suffix_size = 0; + int depth; + + krb5_init_context(&test_context); + + if (strrchr(argv[0], '/')) + argv[0] = strrchr(argv[0], '/')+1; + + progname = argv[0]; + + memset(principal_string, 0, sizeof(principal_string)); + num_to_create = 0; + depth = 1; + + while ((optchar = getopt(argc, argv, "D:P:p:n:d:r:k:M:e:m")) != -1) { + switch(optchar) { + case 'D': + depth = atoi(optarg); /* how deep to go */ + break; + case 'P': /* Only used for testing!!! */ + mkey_password = optarg; + break; + case 'p': /* prefix name to create */ + strncpy(principal_string, optarg, sizeof(principal_string) - 1); + principal_string[sizeof(principal_string) - 1] = '\0'; + suffix = principal_string + strlen(principal_string); + suffix_size = sizeof(principal_string) - + (suffix - principal_string); + break; + case 'n': /* how many to create */ + num_to_create = atoi(optarg); + break; + case 'd': /* set db name */ + dbname = optarg; + break; + case 'r': + cur_realm = optarg; + break; + case 'k': + master_keyblock.enctype = atoi(optarg); + enctypedone++; + break; + case 'M': /* master key name in DB */ + mkey_name = optarg; + break; + case 'm': + manual_mkey = TRUE; + break; + case '?': + default: + usage(progname, 1); + /*NOTREACHED*/ + } + } + + if (!(num_to_create && suffix)) usage(progname, 1); + + if (!enctypedone) + master_keyblock.enctype = DEFAULT_KDC_ENCTYPE; + + if (!krb5_c_valid_enctype(master_keyblock.enctype)) { + com_err(progname, KRB5_PROG_ETYPE_NOSUPP, + "while setting up enctype %d", master_keyblock.enctype); + exit(1); + } + + if (!dbname) + dbname = DEFAULT_KDB_FILE; /* XXX? */ + + if (!cur_realm) { + if ((retval = krb5_get_default_realm(test_context, &cur_realm))) { + com_err(progname, retval, "while retrieving default realm name"); + exit(1); + } + } + if ((retval = set_dbname_help(progname, dbname))) + exit(retval); + + for (n = 1; n <= num_to_create; n++) { + /* build the new principal name */ + /* we can't pick random names because we need to generate all the names + again given a prefix and count to test the db lib and kdb */ + (void) snprintf(suffix, suffix_size, "%d", n); + (void) snprintf(tmp, sizeof(tmp), "%s-DEPTH-1", principal_string); + tmp[sizeof(tmp) - 1] = '\0'; + str_newprinc = tmp; + add_princ(test_context, str_newprinc); + + for (i = 2; i <= depth; i++) { + (void) snprintf(tmp2, sizeof(tmp2), "/%s-DEPTH-%d", + principal_string, i); + tmp2[sizeof(tmp2) - 1] = '\0'; + strncat(tmp, tmp2, sizeof(tmp) - 1 - strlen(tmp)); + str_newprinc = tmp; + add_princ(test_context, str_newprinc); + } + } + + retval = krb5_db_fini(test_context); + memset(master_keyblock.contents, 0, + (size_t) master_keyblock.length); + if (retval && retval != KRB5_KDB_DBNOTINITED) { + com_err(progname, retval, "while closing database"); + exit(1); + } + if (master_princ_set) + krb5_free_principal(test_context, master_princ); + krb5_free_context(test_context); + exit(0); +} + +void +add_princ(context, str_newprinc) + krb5_context context; + char * str_newprinc; +{ + krb5_error_code retval; + krb5_principal newprinc; + krb5_db_entry *newentry; + char princ_name[4096]; + + newentry = calloc(1, sizeof(*newentry)); + if (newentry == NULL) { + com_err(progname, ENOMEM, "while allocating DB entry"); + return; + } + snprintf(princ_name, sizeof(princ_name), "%s@%s", str_newprinc, cur_realm); + if ((retval = krb5_parse_name(context, princ_name, &newprinc))) { + com_err(progname, retval, "while parsing '%s'", princ_name); + return; + } + + /* Add basic data */ + newentry->len = KRB5_KDB_V1_BASE_LENGTH; + newentry->attributes = mblock.flags; + newentry->max_life = mblock.max_life; + newentry->max_renewable_life = mblock.max_rlife; + newentry->expiration = mblock.expiration; + newentry->pw_expiration = mblock.expiration; + + /* Add princ to db entry */ + if ((retval = krb5_copy_principal(context, newprinc, &newentry->princ))) { + com_err(progname, retval, "while encoding princ to db entry for '%s'", + princ_name); + krb5_free_principal(context, newprinc); + goto error; + } + + { + /* Add mod princ to db entry */ + krb5_timestamp now; + + retval = krb5_timeofday(context, &now); + if (retval) { + com_err(progname, retval, "while fetching date"); + krb5_free_principal(context, newprinc); + goto error; + } + retval = krb5_dbe_update_mod_princ_data(context, newentry, now, + master_princ); + if (retval) { + com_err(progname, retval, "while encoding mod_princ data"); + krb5_free_principal(context, newprinc); + goto error; + } + } + + { /* Add key and salt data to db entry */ + krb5_data pwd, salt; + krb5_keyblock key; + + if ((retval = krb5_principal2salt(context, newprinc, &salt))) { + com_err(progname, retval, "while converting princ to salt for '%s'", + princ_name); + krb5_free_principal(context, newprinc); + goto error; + } + + krb5_free_principal(context, newprinc); + + pwd.length = strlen(princ_name); + pwd.data = princ_name; /* must be able to regenerate */ + if ((retval = krb5_c_string_to_key(context, master_keyblock.enctype, + &pwd, &salt, &key))) { + com_err(progname,retval,"while converting password to key for '%s'", + princ_name); + krb5_free_data_contents(context, &salt); + goto error; + } + krb5_free_data_contents(context, &salt); + + if ((retval = krb5_dbe_create_key_data(context, newentry))) { + com_err(progname, retval, "while creating key_data for '%s'", + princ_name); + free(key.contents); + goto error; + } + + if ((retval = krb5_dbe_encrypt_key_data(context, &master_keyblock, + &key, NULL, 1, + newentry->key_data))) { + com_err(progname, retval, "while encrypting key for '%s'", + princ_name); + free(key.contents); + goto error; + } + free(key.contents); + } + + if ((retval = krb5_db_put_principal(context, newentry))) { + com_err(progname, retval, "while storing principal date"); + goto error; + } + +error: /* Do cleanup of newentry regardless of error */ + krb5_db_free_principal(context, newentry); + return; +} + +int +set_dbname_help(pname, dbname) + char *pname; + char *dbname; +{ + krb5_error_code retval; + krb5_data pwd, scratch; + char *args[2]; + krb5_db_entry *master_entry; + + /* assemble & parse the master key name */ + + if ((retval = krb5_db_setup_mkey_name(test_context, mkey_name, cur_realm, + 0, &master_princ))) { + com_err(pname, retval, "while setting up master key name"); + return(1); + } + master_princ_set = 1; + if (mkey_password) { + pwd.data = mkey_password; + pwd.length = strlen(mkey_password); + retval = krb5_principal2salt(test_context, master_princ, &scratch); + if (retval) { + com_err(pname, retval, "while calculated master key salt"); + return(1); + } + if ((retval = krb5_c_string_to_key(test_context, + master_keyblock.enctype, + &pwd, &scratch, + &master_keyblock))) { + com_err(pname, retval, + "while transforming master key from password"); + return(1); + } + free(scratch.data); + } else { + if ((retval = krb5_db_fetch_mkey(test_context, master_princ, + master_keyblock.enctype, manual_mkey, + FALSE, 0, NULL, NULL, + &master_keyblock))) { + com_err(pname, retval, "while reading master key"); + return(1); + } + } + + /* Ick! Current DAL interface requires that the default_realm + field be set in the krb5_context. */ + if ((retval = krb5_set_default_realm(test_context, cur_realm))) { + com_err(pname, retval, "setting default realm"); + return 1; + } + /* Pathname is passed to db2 via 'args' parameter. */ + args[1] = NULL; + if (asprintf(&args[0], "dbname=%s", dbname) < 0) { + com_err(pname, errno, "while setting up db parameters"); + return 1; + } + + if ((retval = krb5_db_open(test_context, args, KRB5_KDB_OPEN_RO))) { + com_err(pname, retval, "while initializing database"); + return(1); + } + /* Done with args */ + free(args[0]); + + if ((retval = krb5_db_fetch_mkey_list(test_context, master_princ, + &master_keyblock))){ + com_err(pname, retval, "while verifying master key"); + (void) krb5_db_fini(test_context); + return(1); + } + if ((retval = krb5_db_get_principal(test_context, master_princ, 0, + &master_entry))) { + com_err(pname, retval, "while retrieving master entry"); + (void) krb5_db_fini(test_context); + return(1); + } + + mblock.max_life = master_entry->max_life; + mblock.max_rlife = master_entry->max_renewable_life; + mblock.expiration = master_entry->expiration; + + /* don't set flags, master has some extra restrictions */ + mblock.mkvno = master_entry->key_data[0].key_data_kvno; + + krb5_db_free_principal(test_context, master_entry); + return 0; +} diff --git a/krb5-1.21.3/src/tests/deps b/krb5-1.21.3/src/tests/deps new file mode 100644 index 00000000..13eb3312 --- /dev/null +++ b/krb5-1.21.3/src/tests/deps @@ -0,0 +1,181 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)adata.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h adata.c +$(OUTPRE)conccache.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ + conccache.c +$(OUTPRE)etinfo.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h etinfo.c +$(OUTPRE)forward.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h forward.c +$(OUTPRE)gcred.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h gcred.c +$(OUTPRE)hist.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + hist.c +$(OUTPRE)hooks.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h hooks.c +$(OUTPRE)hrealm.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h hrealm.c +$(OUTPRE)icinterleave.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h icinterleave.c +$(OUTPRE)icred.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ + icred.c +$(OUTPRE)kdbtest.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h kdbtest.c +$(OUTPRE)localauth.$(OBJEXT): $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h localauth.c +$(OUTPRE)plugorder.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssrpc/types.h \ + $(BUILDTOP)/include/kadm5/admin.h $(BUILDTOP)/include/kadm5/chpass_util_strings.h \ + $(BUILDTOP)/include/kadm5/kadm_err.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/kdb.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/krb5/pwqual_plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h plugorder.c +$(OUTPRE)rdreq.$(OBJEXT): $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h rdreq.c +$(OUTPRE)replay.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h replay.c +$(OUTPRE)responder.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-json.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/krb5.h responder.c +$(OUTPRE)s2p.$(OBJEXT): $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h s2p.c +$(OUTPRE)s4u2self.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h s4u2self.c +$(OUTPRE)s4u2proxy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h s4u2proxy.c +$(OUTPRE)t_inetd.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(COM_ERR_DEPS) t_inetd.c +$(OUTPRE)unlockiter.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h unlockiter.c diff --git a/krb5-1.21.3/src/tests/dump.c b/krb5-1.21.3/src/tests/dump.c new file mode 100644 index 00000000..b8e52b98 --- /dev/null +++ b/krb5-1.21.3/src/tests/dump.c @@ -0,0 +1,42 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/dump.c */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Dump a krb5_data to stderr (for debugging purposes). */ + +#include +#include "krb5.h" + +void dump_data (data) + krb5_data *data; +{ + unsigned char *ptr = (unsigned char *)data->data; + int i; + for (i=0; ilength; i++) { + fprintf(stderr, "%02x ", ptr[i]); + if ((i % 16) == 15) fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); +} diff --git a/krb5-1.21.3/src/tests/dumpfiles/dump b/krb5-1.21.3/src/tests/dumpfiles/dump new file mode 100644 index 00000000..15ff8788 --- /dev/null +++ b/krb5-1.21.3/src/tests/dumpfiles/dump @@ -0,0 +1,11 @@ +kdb5_util load_dump version 7 +princ 38 15 3 1 0 K/M@KRBTEST.COM 64 86400 0 0 0 0 0 0 8 2 0100 9 8 0100010000000000 2 28 b93e105164625f6372656174696f6e404b5242544553542e434f4d00 1 1 18 62 2000408c027c250e8cc3b81476414f2214d57c1ce38891e29792e87258247c73547df4d5756266931dd6686b62270e656895a31ec66bfe913b4f15226227 -1; +princ 38 36 4 4 0 host/equal-rites.mit.edu@KRBTEST.COM 0 86400 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 30 b93e105167687564736f6e2f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 20009b7f9e9edd44559c5ffb2b52beb92e57586f9bdf59ae0be7010ffa8b628928bebc7d6015211977bc34325be853e5f1eb5826ce75575414bc2696bc16 1 1 17 46 10001bfaf4d8ddd6e8767194a190e9dec2617dbc90883db767fa464325b76b97ea98f3b61c4d4234ff9aee6314a4 1 1 16 54 18008291ce8c2ccde958c2739e93ce499b088b1b8c304bce95097bd6c1bd92c3c9f64e92950767f7806d890b386ba586fdb7f8433f1c 1 1 23 46 1000a460520a9e39b1539e703a51793967247999a9a0bb7c59a61ca2b5e64a58c3b9cf8217daeddd71caae9d7fbb -1; +princ 38 24 4 4 0 kadmin/admin@KRBTEST.COM 4 10800 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 26 b93e10516b6462355f7574696c404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 20005ea70b11f3337975c5463baedc68b234cadf72f89828d98e3c16cb8640bba7c5ed48a4bcf7649a73a9a410e96234924bfacd4bb38f08982db02c5c5b 1 1 17 46 10001b678f8b9bb6913397202c259702c1941fd5d2892f42349a92ca908de248cd041465bb3d16d27efce1f63e30 1 1 16 54 18009ed81fe14b19549918acad7b1158b86f5971ab3bd77b2359c29147af35730167210157e510dda65f691c312ac398850d7e228c40 1 1 23 46 10001d15a249bbea104208ae0b3d83337d4c06f6edef6a6ac60ec3df7b52aeeeb388c7233a9b1e3de646949ed540 -1; +princ 38 27 4 4 0 kadmin/changepw@KRBTEST.COM 8196 300 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 26 b93e10516b6462355f7574696c404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 200015daf7bc8073eae166b03231330b81b78cfd6021d3dcf3700862dc98725c5bb549a72aa2ae8eef37dc2db5acc59cc62600f72052c6238ef216dd24a5 1 1 17 46 1000c1e176f253d6292fe4e34b2edfbdd5ff81ff3e17b38c2a674bd738d20fc40a4ed38a02351f4a9872123fb865 1 1 16 54 18008bf3418871e7d117af489798fbbcc031c534e095b4e4ed6cb110c7d87a91e5fb6c080c77616618db80ed37589fcc0ca8328406ef 1 1 23 46 10007a522025d2e7126dc48d76218e9efb3ff4326a3b5969be0deac108657a9d23c7827ec39b828fd43e51ea114b -1; +princ 38 38 4 4 0 kadmin/equal-rites.mit.edu@KRBTEST.COM 4 10800 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 26 b93e10516b6462355f7574696c404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 200045a2e5b79c5787bfc68700d3abc0034cc91d48f10636c35e1a571c41c4e6892caceeda8808bfa46aa4050a6d33d99cb64d237f645af6741e90c723ff 1 1 17 46 100073b99fecd81b4fe113b10852065c15e75ed7d256d2d242b3cca57317c28c7fece4bda797f116309ea5bc2eb1 1 1 16 54 1800bd05672170b5d04cb62394498988f3844b744a0793ac435d044e67ed0ee50d20c408b30cec599c169378b0ad2a4967f42aef38e5 1 1 23 46 1000a1a515e0fe322980f319752bf85dd405ca2bdda148009654584b70f50d38c532df1c2d0a3c56f9758775b007 -1; +princ 38 30 1 4 0 krbtgt/KRBTEST.COM@KRBTEST.COM 0 86400 0 0 0 0 0 0 2 28 b93e105164625f6372656174696f6e404b5242544553542e434f4d00 1 1 18 62 2000582c9aaf26c4a0abf13600baf37718c91e15dca02385e346cf5d2730d28b2302677f23d02791299548b45e1ced0b05cd30062617bff7532885d7889c 1 1 17 46 1000122eb47263d7837771ebbf7ad82163cc2ea7674a417944c0cbf186522fc0e74a73affd4a42fb9fda287be4f8 1 1 16 54 18008cd8064aea468f13f36ae13ecd4f993d87ef6bafcb2dc5101ad903200ffe3d5c265b2f0c71a6c07ec60d259b6862825cc77a70b2 1 1 23 46 10001699ad0304644456106328fbd733bd5c524f20d4b5d8b8e370eff196803b5990ee7e9eb4b6c2214cf327f59b -1; +princ 38 18 4 0 0 nokeys@KRBTEST.COM 0 86400 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 27 d931dc51757365722f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 d931dc51 -1; +princ 38 22 4 4 0 user/admin@KRBTEST.COM 0 86400 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 30 b93e105167687564736f6e2f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 20002db4cd2b0824c44a17cdbb2d180a1ec9956db35d74741826ed0d77eaef9abdb20c481d5ab9f511d5a3e6b8def443382f03d247568d81529e5dd17fae 1 1 17 46 100011d7cc3627468d565d398cffd735a3cc9d3705cd9846cede198c7d07f4e8209cd9192bc6c5f127169c00f373 1 1 16 54 18002bd9dc3388c90055844b3b4c5c2a814d73758f226d44d7dc5e35ef3b65e7d80cd604a4ef2a5769106818c3d813956bbad1813cb2 1 1 23 46 1000409681c3ff356fb7d28a9f71957c3465ea42ec4eee5019a662f7d367042527b76ae783cfbd0dccbd7529d090 -1; +princ 38 16 4 4 0 user@KRBTEST.COM 0 86400 0 0 0 0 0 0 3 32 12345c010000000874657374706f6c0000000800000000000000000200000000 2 27 d73e1051757365722f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 2000aec451aae295389f92d177e61b5154941386c70d75d382393e556dfa61bd77d112a777420a99030b56649d366bba83a5c40aa17fa4522222d2e78e10 1 1 17 46 10009c8ab7b3f89ccf3ca3ad98352a461b7f4f1b0c495605117591d9ad52ba4da0adef7a902126973ed2bdc3ffbf 1 1 16 54 18002b87a46d6c4de954a316b5ce28a99886f2abb6b0307190e577b81171dfb7a067139835be8625bc36b0edaaed357609107d85d335 1 1 23 46 1000c01fcdb3050a2270f82dbafbe4c1adc868377bf7133ee7a1bcaf85817abe541beb8008b91c54b99e93d2e0f5 -1; +policy testpol 0 0 1 3 1 0 0 0 0 0 0 0 - 0 diff --git a/krb5-1.21.3/src/tests/dumpfiles/dump.16 b/krb5-1.21.3/src/tests/dumpfiles/dump.16 new file mode 100644 index 00000000..bea2ff6b --- /dev/null +++ b/krb5-1.21.3/src/tests/dumpfiles/dump.16 @@ -0,0 +1,7 @@ +kdb5_util load_dump version 5 +princ 38 15 1 1 0 K/M@KRBTEST.COM 64 36000 604800 0 0 0 0 0 2 28 18de675264625f6372656174696f6e404b5242544553542e434f4d00 1 1 16 54 180001361a6c58b3a273e484574c6c5739fb114ffe7d2298e767b545f332e3bda573021c97728028e7ec4942708f23f4445d4419f4ad -1; +princ 38 24 3 2 0 kadmin/admin@KRBTEST.COM 4 10800 604800 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 26 18de67526b6462355f7574696c404b5242544553542e434f4d00 1 4 18de6752 1 2 16 54 1800555ff1892cdb7dd7c62b659f9659981205ebb4f9fd4446e5243f58dfc0b99a4f096080d435702e052793a90c66aea062c8b8964e 1 2 1 38 0800ca62598d281381a22fc6d5bdf25653002b6afeb8f24af6ea01c9301359527304a08bb8f5 -1; +princ 38 27 3 2 0 kadmin/changepw@KRBTEST.COM 8196 300 604800 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 26 18de67526b6462355f7574696c404b5242544553542e434f4d00 1 4 18de6752 1 2 16 54 1800237a5df1fc3295e08ba18986f51f553c2d0dfff3fb8e17d19ac7777a1cd516713e5496521ba362261ab61c063090705ecf7bca01 1 2 1 38 0800685d1f82188b712b2947b63a259269b1fe53bf383bb05cdc802e2cb9d680631e512af4d4 -1; +princ 38 38 3 2 0 kadmin/equal-rites.mit.edu@KRBTEST.COM 4 10800 604800 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 26 18de67526b6462355f7574696c404b5242544553542e434f4d00 1 4 18de6752 1 2 16 54 1800ed9ad2e91940a41abc9b05d7dfb736c353e3ff18272b1d3bc31e5ebc3204e15d5fd9c3caa0c57be4736831b6f03c1741d5423ff1 1 2 1 38 0800eb82c30aa8e1f5a10f0f099372e2ff3385cb5437b41abee02491673cf45c79b2c4466364 -1; +princ 38 26 3 1 0 kadmin/history@KRBTEST.COM 0 64 604800 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 26 18de67526b6462355f7574696c404b5242544553542e434f4d00 1 4 18de6752 1 2 16 54 180070b4f132c63aa7d8b91f1323daa8d59bf2e04663b9b8931bcbe9a953c4fab6dda7c820db0cf9922af5ebfb7bd09101849e81f054 -1; +princ 38 30 1 2 0 krbtgt/KRBTEST.COM@KRBTEST.COM 0 36000 604800 0 0 0 0 0 2 28 18de675264625f6372656174696f6e404b5242544553542e434f4d00 1 1 16 54 1800010572e45515fc5ee028a59a48bc86896ab5014c265304b2340d37a46c0185312e475e9245e70df0f6874c9348a2ca4389c7168f 1 1 1 38 0800d8b88190a5e7f49cdca68c0e018bafd971f1606f9af2f2e3d9e31c69071556896443ade2 -1; diff --git a/krb5-1.21.3/src/tests/dumpfiles/dump.b7 b/krb5-1.21.3/src/tests/dumpfiles/dump.b7 new file mode 100644 index 00000000..8d534011 --- /dev/null +++ b/krb5-1.21.3/src/tests/dumpfiles/dump.b7 @@ -0,0 +1,11 @@ +kdb5_util load_dump version 4 +princ 38 15 3 1 0 K/M@KRBTEST.COM 64 86400 0 0 0 0 0 0 8 2 0100 9 8 0100010000000000 2 28 b93e105164625f6372656174696f6e404b5242544553542e434f4d00 1 1 18 62 2000408c027c250e8cc3b81476414f2214d57c1ce38891e29792e87258247c73547df4d5756266931dd6686b62270e656895a31ec66bfe913b4f15226227 -1; +princ 38 36 3 4 0 host/equal-rites.mit.edu@KRBTEST.COM 0 86400 0 0 0 0 0 0 2 30 b93e105167687564736f6e2f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 20009b7f9e9edd44559c5ffb2b52beb92e57586f9bdf59ae0be7010ffa8b628928bebc7d6015211977bc34325be853e5f1eb5826ce75575414bc2696bc16 1 1 17 46 10001bfaf4d8ddd6e8767194a190e9dec2617dbc90883db767fa464325b76b97ea98f3b61c4d4234ff9aee6314a4 1 1 16 54 18008291ce8c2ccde958c2739e93ce499b088b1b8c304bce95097bd6c1bd92c3c9f64e92950767f7806d890b386ba586fdb7f8433f1c 1 1 23 46 1000a460520a9e39b1539e703a51793967247999a9a0bb7c59a61ca2b5e64a58c3b9cf8217daeddd71caae9d7fbb -1; +princ 38 24 3 4 0 kadmin/admin@KRBTEST.COM 4 10800 0 0 0 0 0 0 2 26 b93e10516b6462355f7574696c404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 20005ea70b11f3337975c5463baedc68b234cadf72f89828d98e3c16cb8640bba7c5ed48a4bcf7649a73a9a410e96234924bfacd4bb38f08982db02c5c5b 1 1 17 46 10001b678f8b9bb6913397202c259702c1941fd5d2892f42349a92ca908de248cd041465bb3d16d27efce1f63e30 1 1 16 54 18009ed81fe14b19549918acad7b1158b86f5971ab3bd77b2359c29147af35730167210157e510dda65f691c312ac398850d7e228c40 1 1 23 46 10001d15a249bbea104208ae0b3d83337d4c06f6edef6a6ac60ec3df7b52aeeeb388c7233a9b1e3de646949ed540 -1; +princ 38 27 3 4 0 kadmin/changepw@KRBTEST.COM 8196 300 0 0 0 0 0 0 2 26 b93e10516b6462355f7574696c404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 200015daf7bc8073eae166b03231330b81b78cfd6021d3dcf3700862dc98725c5bb549a72aa2ae8eef37dc2db5acc59cc62600f72052c6238ef216dd24a5 1 1 17 46 1000c1e176f253d6292fe4e34b2edfbdd5ff81ff3e17b38c2a674bd738d20fc40a4ed38a02351f4a9872123fb865 1 1 16 54 18008bf3418871e7d117af489798fbbcc031c534e095b4e4ed6cb110c7d87a91e5fb6c080c77616618db80ed37589fcc0ca8328406ef 1 1 23 46 10007a522025d2e7126dc48d76218e9efb3ff4326a3b5969be0deac108657a9d23c7827ec39b828fd43e51ea114b -1; +princ 38 38 3 4 0 kadmin/equal-rites.mit.edu@KRBTEST.COM 4 10800 0 0 0 0 0 0 2 26 b93e10516b6462355f7574696c404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 200045a2e5b79c5787bfc68700d3abc0034cc91d48f10636c35e1a571c41c4e6892caceeda8808bfa46aa4050a6d33d99cb64d237f645af6741e90c723ff 1 1 17 46 100073b99fecd81b4fe113b10852065c15e75ed7d256d2d242b3cca57317c28c7fece4bda797f116309ea5bc2eb1 1 1 16 54 1800bd05672170b5d04cb62394498988f3844b744a0793ac435d044e67ed0ee50d20c408b30cec599c169378b0ad2a4967f42aef38e5 1 1 23 46 1000a1a515e0fe322980f319752bf85dd405ca2bdda148009654584b70f50d38c532df1c2d0a3c56f9758775b007 -1; +princ 38 30 1 4 0 krbtgt/KRBTEST.COM@KRBTEST.COM 0 86400 0 0 0 0 0 0 2 28 b93e105164625f6372656174696f6e404b5242544553542e434f4d00 1 1 18 62 2000582c9aaf26c4a0abf13600baf37718c91e15dca02385e346cf5d2730d28b2302677f23d02791299548b45e1ced0b05cd30062617bff7532885d7889c 1 1 17 46 1000122eb47263d7837771ebbf7ad82163cc2ea7674a417944c0cbf186522fc0e74a73affd4a42fb9fda287be4f8 1 1 16 54 18008cd8064aea468f13f36ae13ecd4f993d87ef6bafcb2dc5101ad903200ffe3d5c265b2f0c71a6c07ec60d259b6862825cc77a70b2 1 1 23 46 10001699ad0304644456106328fbd733bd5c524f20d4b5d8b8e370eff196803b5990ee7e9eb4b6c2214cf327f59b -1; +princ 38 18 3 0 0 nokeys@KRBTEST.COM 0 86400 0 0 0 0 0 0 2 27 d931dc51757365722f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 d931dc51 -1; +princ 38 22 3 4 0 user/admin@KRBTEST.COM 0 86400 0 0 0 0 0 0 2 30 b93e105167687564736f6e2f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 20002db4cd2b0824c44a17cdbb2d180a1ec9956db35d74741826ed0d77eaef9abdb20c481d5ab9f511d5a3e6b8def443382f03d247568d81529e5dd17fae 1 1 17 46 100011d7cc3627468d565d398cffd735a3cc9d3705cd9846cede198c7d07f4e8209cd9192bc6c5f127169c00f373 1 1 16 54 18002bd9dc3388c90055844b3b4c5c2a814d73758f226d44d7dc5e35ef3b65e7d80cd604a4ef2a5769106818c3d813956bbad1813cb2 1 1 23 46 1000409681c3ff356fb7d28a9f71957c3465ea42ec4eee5019a662f7d367042527b76ae783cfbd0dccbd7529d090 -1; +princ 38 16 3 4 0 user@KRBTEST.COM 0 86400 0 0 0 0 0 0 2 27 d73e1051757365722f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 2000aec451aae295389f92d177e61b5154941386c70d75d382393e556dfa61bd77d112a777420a99030b56649d366bba83a5c40aa17fa4522222d2e78e10 1 1 17 46 10009c8ab7b3f89ccf3ca3ad98352a461b7f4f1b0c495605117591d9ad52ba4da0adef7a902126973ed2bdc3ffbf 1 1 16 54 18002b87a46d6c4de954a316b5ce28a99886f2abb6b0307190e577b81171dfb7a067139835be8625bc36b0edaaed357609107d85d335 1 1 23 46 1000c01fcdb3050a2270f82dbafbe4c1adc868377bf7133ee7a1bcaf85817abe541beb8008b91c54b99e93d2e0f5 -1; +policy testpol 0 0 1 3 1 0 diff --git a/krb5-1.21.3/src/tests/dumpfiles/dump.ov b/krb5-1.21.3/src/tests/dumpfiles/dump.ov new file mode 100644 index 00000000..285bef97 --- /dev/null +++ b/krb5-1.21.3/src/tests/dumpfiles/dump.ov @@ -0,0 +1,9 @@ +OpenV*Secure V1.0 +princ host/equal-rites.mit.edu@KRBTEST.COM 0 0 0 2 +princ kadmin/admin@KRBTEST.COM 0 0 0 2 +princ kadmin/changepw@KRBTEST.COM 0 0 0 2 +princ kadmin/equal-rites.mit.edu@KRBTEST.COM 0 0 0 2 +princ nokeys@KRBTEST.COM 0 0 0 2 +princ user/admin@KRBTEST.COM 0 0 0 2 +princ user@KRBTEST.COM testpol 800 0 0 2 +policy testpol 0 0 1 3 1 0 diff --git a/krb5-1.21.3/src/tests/dumpfiles/dump.r13 b/krb5-1.21.3/src/tests/dumpfiles/dump.r13 new file mode 100644 index 00000000..c15a75e9 --- /dev/null +++ b/krb5-1.21.3/src/tests/dumpfiles/dump.r13 @@ -0,0 +1,11 @@ +kdb5_util load_dump version 5 +princ 38 15 3 1 0 K/M@KRBTEST.COM 64 86400 0 0 0 0 0 0 8 2 0100 9 8 0100010000000000 2 28 b93e105164625f6372656174696f6e404b5242544553542e434f4d00 1 1 18 62 2000408c027c250e8cc3b81476414f2214d57c1ce38891e29792e87258247c73547df4d5756266931dd6686b62270e656895a31ec66bfe913b4f15226227 -1; +princ 38 36 4 4 0 host/equal-rites.mit.edu@KRBTEST.COM 0 86400 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 30 b93e105167687564736f6e2f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 20009b7f9e9edd44559c5ffb2b52beb92e57586f9bdf59ae0be7010ffa8b628928bebc7d6015211977bc34325be853e5f1eb5826ce75575414bc2696bc16 1 1 17 46 10001bfaf4d8ddd6e8767194a190e9dec2617dbc90883db767fa464325b76b97ea98f3b61c4d4234ff9aee6314a4 1 1 16 54 18008291ce8c2ccde958c2739e93ce499b088b1b8c304bce95097bd6c1bd92c3c9f64e92950767f7806d890b386ba586fdb7f8433f1c 1 1 23 46 1000a460520a9e39b1539e703a51793967247999a9a0bb7c59a61ca2b5e64a58c3b9cf8217daeddd71caae9d7fbb -1; +princ 38 24 4 4 0 kadmin/admin@KRBTEST.COM 4 10800 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 26 b93e10516b6462355f7574696c404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 20005ea70b11f3337975c5463baedc68b234cadf72f89828d98e3c16cb8640bba7c5ed48a4bcf7649a73a9a410e96234924bfacd4bb38f08982db02c5c5b 1 1 17 46 10001b678f8b9bb6913397202c259702c1941fd5d2892f42349a92ca908de248cd041465bb3d16d27efce1f63e30 1 1 16 54 18009ed81fe14b19549918acad7b1158b86f5971ab3bd77b2359c29147af35730167210157e510dda65f691c312ac398850d7e228c40 1 1 23 46 10001d15a249bbea104208ae0b3d83337d4c06f6edef6a6ac60ec3df7b52aeeeb388c7233a9b1e3de646949ed540 -1; +princ 38 27 4 4 0 kadmin/changepw@KRBTEST.COM 8196 300 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 26 b93e10516b6462355f7574696c404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 200015daf7bc8073eae166b03231330b81b78cfd6021d3dcf3700862dc98725c5bb549a72aa2ae8eef37dc2db5acc59cc62600f72052c6238ef216dd24a5 1 1 17 46 1000c1e176f253d6292fe4e34b2edfbdd5ff81ff3e17b38c2a674bd738d20fc40a4ed38a02351f4a9872123fb865 1 1 16 54 18008bf3418871e7d117af489798fbbcc031c534e095b4e4ed6cb110c7d87a91e5fb6c080c77616618db80ed37589fcc0ca8328406ef 1 1 23 46 10007a522025d2e7126dc48d76218e9efb3ff4326a3b5969be0deac108657a9d23c7827ec39b828fd43e51ea114b -1; +princ 38 38 4 4 0 kadmin/equal-rites.mit.edu@KRBTEST.COM 4 10800 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 26 b93e10516b6462355f7574696c404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 200045a2e5b79c5787bfc68700d3abc0034cc91d48f10636c35e1a571c41c4e6892caceeda8808bfa46aa4050a6d33d99cb64d237f645af6741e90c723ff 1 1 17 46 100073b99fecd81b4fe113b10852065c15e75ed7d256d2d242b3cca57317c28c7fece4bda797f116309ea5bc2eb1 1 1 16 54 1800bd05672170b5d04cb62394498988f3844b744a0793ac435d044e67ed0ee50d20c408b30cec599c169378b0ad2a4967f42aef38e5 1 1 23 46 1000a1a515e0fe322980f319752bf85dd405ca2bdda148009654584b70f50d38c532df1c2d0a3c56f9758775b007 -1; +princ 38 30 1 4 0 krbtgt/KRBTEST.COM@KRBTEST.COM 0 86400 0 0 0 0 0 0 2 28 b93e105164625f6372656174696f6e404b5242544553542e434f4d00 1 1 18 62 2000582c9aaf26c4a0abf13600baf37718c91e15dca02385e346cf5d2730d28b2302677f23d02791299548b45e1ced0b05cd30062617bff7532885d7889c 1 1 17 46 1000122eb47263d7837771ebbf7ad82163cc2ea7674a417944c0cbf186522fc0e74a73affd4a42fb9fda287be4f8 1 1 16 54 18008cd8064aea468f13f36ae13ecd4f993d87ef6bafcb2dc5101ad903200ffe3d5c265b2f0c71a6c07ec60d259b6862825cc77a70b2 1 1 23 46 10001699ad0304644456106328fbd733bd5c524f20d4b5d8b8e370eff196803b5990ee7e9eb4b6c2214cf327f59b -1; +princ 38 18 4 0 0 nokeys@KRBTEST.COM 0 86400 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 27 d931dc51757365722f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 d931dc51 -1; +princ 38 22 4 4 0 user/admin@KRBTEST.COM 0 86400 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 30 b93e105167687564736f6e2f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 20002db4cd2b0824c44a17cdbb2d180a1ec9956db35d74741826ed0d77eaef9abdb20c481d5ab9f511d5a3e6b8def443382f03d247568d81529e5dd17fae 1 1 17 46 100011d7cc3627468d565d398cffd735a3cc9d3705cd9846cede198c7d07f4e8209cd9192bc6c5f127169c00f373 1 1 16 54 18002bd9dc3388c90055844b3b4c5c2a814d73758f226d44d7dc5e35ef3b65e7d80cd604a4ef2a5769106818c3d813956bbad1813cb2 1 1 23 46 1000409681c3ff356fb7d28a9f71957c3465ea42ec4eee5019a662f7d367042527b76ae783cfbd0dccbd7529d090 -1; +princ 38 16 4 4 0 user@KRBTEST.COM 0 86400 0 0 0 0 0 0 3 32 12345c010000000874657374706f6c0000000800000000000000000200000000 2 27 d73e1051757365722f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 2000aec451aae295389f92d177e61b5154941386c70d75d382393e556dfa61bd77d112a777420a99030b56649d366bba83a5c40aa17fa4522222d2e78e10 1 1 17 46 10009c8ab7b3f89ccf3ca3ad98352a461b7f4f1b0c495605117591d9ad52ba4da0adef7a902126973ed2bdc3ffbf 1 1 16 54 18002b87a46d6c4de954a316b5ce28a99886f2abb6b0307190e577b81171dfb7a067139835be8625bc36b0edaaed357609107d85d335 1 1 23 46 1000c01fcdb3050a2270f82dbafbe4c1adc868377bf7133ee7a1bcaf85817abe541beb8008b91c54b99e93d2e0f5 -1; +policy testpol 0 0 1 3 1 0 diff --git a/krb5-1.21.3/src/tests/dumpfiles/dump.r18 b/krb5-1.21.3/src/tests/dumpfiles/dump.r18 new file mode 100644 index 00000000..b352fa28 --- /dev/null +++ b/krb5-1.21.3/src/tests/dumpfiles/dump.r18 @@ -0,0 +1,11 @@ +kdb5_util load_dump version 6 +princ 38 15 3 1 0 K/M@KRBTEST.COM 64 86400 0 0 0 0 0 0 8 2 0100 9 8 0100010000000000 2 28 b93e105164625f6372656174696f6e404b5242544553542e434f4d00 1 1 18 62 2000408c027c250e8cc3b81476414f2214d57c1ce38891e29792e87258247c73547df4d5756266931dd6686b62270e656895a31ec66bfe913b4f15226227 -1; +princ 38 36 4 4 0 host/equal-rites.mit.edu@KRBTEST.COM 0 86400 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 30 b93e105167687564736f6e2f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 20009b7f9e9edd44559c5ffb2b52beb92e57586f9bdf59ae0be7010ffa8b628928bebc7d6015211977bc34325be853e5f1eb5826ce75575414bc2696bc16 1 1 17 46 10001bfaf4d8ddd6e8767194a190e9dec2617dbc90883db767fa464325b76b97ea98f3b61c4d4234ff9aee6314a4 1 1 16 54 18008291ce8c2ccde958c2739e93ce499b088b1b8c304bce95097bd6c1bd92c3c9f64e92950767f7806d890b386ba586fdb7f8433f1c 1 1 23 46 1000a460520a9e39b1539e703a51793967247999a9a0bb7c59a61ca2b5e64a58c3b9cf8217daeddd71caae9d7fbb -1; +princ 38 24 4 4 0 kadmin/admin@KRBTEST.COM 4 10800 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 26 b93e10516b6462355f7574696c404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 20005ea70b11f3337975c5463baedc68b234cadf72f89828d98e3c16cb8640bba7c5ed48a4bcf7649a73a9a410e96234924bfacd4bb38f08982db02c5c5b 1 1 17 46 10001b678f8b9bb6913397202c259702c1941fd5d2892f42349a92ca908de248cd041465bb3d16d27efce1f63e30 1 1 16 54 18009ed81fe14b19549918acad7b1158b86f5971ab3bd77b2359c29147af35730167210157e510dda65f691c312ac398850d7e228c40 1 1 23 46 10001d15a249bbea104208ae0b3d83337d4c06f6edef6a6ac60ec3df7b52aeeeb388c7233a9b1e3de646949ed540 -1; +princ 38 27 4 4 0 kadmin/changepw@KRBTEST.COM 8196 300 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 26 b93e10516b6462355f7574696c404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 200015daf7bc8073eae166b03231330b81b78cfd6021d3dcf3700862dc98725c5bb549a72aa2ae8eef37dc2db5acc59cc62600f72052c6238ef216dd24a5 1 1 17 46 1000c1e176f253d6292fe4e34b2edfbdd5ff81ff3e17b38c2a674bd738d20fc40a4ed38a02351f4a9872123fb865 1 1 16 54 18008bf3418871e7d117af489798fbbcc031c534e095b4e4ed6cb110c7d87a91e5fb6c080c77616618db80ed37589fcc0ca8328406ef 1 1 23 46 10007a522025d2e7126dc48d76218e9efb3ff4326a3b5969be0deac108657a9d23c7827ec39b828fd43e51ea114b -1; +princ 38 38 4 4 0 kadmin/equal-rites.mit.edu@KRBTEST.COM 4 10800 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 26 b93e10516b6462355f7574696c404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 200045a2e5b79c5787bfc68700d3abc0034cc91d48f10636c35e1a571c41c4e6892caceeda8808bfa46aa4050a6d33d99cb64d237f645af6741e90c723ff 1 1 17 46 100073b99fecd81b4fe113b10852065c15e75ed7d256d2d242b3cca57317c28c7fece4bda797f116309ea5bc2eb1 1 1 16 54 1800bd05672170b5d04cb62394498988f3844b744a0793ac435d044e67ed0ee50d20c408b30cec599c169378b0ad2a4967f42aef38e5 1 1 23 46 1000a1a515e0fe322980f319752bf85dd405ca2bdda148009654584b70f50d38c532df1c2d0a3c56f9758775b007 -1; +princ 38 30 1 4 0 krbtgt/KRBTEST.COM@KRBTEST.COM 0 86400 0 0 0 0 0 0 2 28 b93e105164625f6372656174696f6e404b5242544553542e434f4d00 1 1 18 62 2000582c9aaf26c4a0abf13600baf37718c91e15dca02385e346cf5d2730d28b2302677f23d02791299548b45e1ced0b05cd30062617bff7532885d7889c 1 1 17 46 1000122eb47263d7837771ebbf7ad82163cc2ea7674a417944c0cbf186522fc0e74a73affd4a42fb9fda287be4f8 1 1 16 54 18008cd8064aea468f13f36ae13ecd4f993d87ef6bafcb2dc5101ad903200ffe3d5c265b2f0c71a6c07ec60d259b6862825cc77a70b2 1 1 23 46 10001699ad0304644456106328fbd733bd5c524f20d4b5d8b8e370eff196803b5990ee7e9eb4b6c2214cf327f59b -1; +princ 38 18 4 0 0 nokeys@KRBTEST.COM 0 86400 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 27 d931dc51757365722f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 d931dc51 -1; +princ 38 22 4 4 0 user/admin@KRBTEST.COM 0 86400 0 0 0 0 0 0 3 24 12345c010000000000000000000000000000000200000000 2 30 b93e105167687564736f6e2f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 20002db4cd2b0824c44a17cdbb2d180a1ec9956db35d74741826ed0d77eaef9abdb20c481d5ab9f511d5a3e6b8def443382f03d247568d81529e5dd17fae 1 1 17 46 100011d7cc3627468d565d398cffd735a3cc9d3705cd9846cede198c7d07f4e8209cd9192bc6c5f127169c00f373 1 1 16 54 18002bd9dc3388c90055844b3b4c5c2a814d73758f226d44d7dc5e35ef3b65e7d80cd604a4ef2a5769106818c3d813956bbad1813cb2 1 1 23 46 1000409681c3ff356fb7d28a9f71957c3465ea42ec4eee5019a662f7d367042527b76ae783cfbd0dccbd7529d090 -1; +princ 38 16 4 4 0 user@KRBTEST.COM 0 86400 0 0 0 0 0 0 3 32 12345c010000000874657374706f6c0000000800000000000000000200000000 2 27 d73e1051757365722f61646d696e404b5242544553542e434f4d00 8 2 0100 1 4 b93e1051 1 1 18 62 2000aec451aae295389f92d177e61b5154941386c70d75d382393e556dfa61bd77d112a777420a99030b56649d366bba83a5c40aa17fa4522222d2e78e10 1 1 17 46 10009c8ab7b3f89ccf3ca3ad98352a461b7f4f1b0c495605117591d9ad52ba4da0adef7a902126973ed2bdc3ffbf 1 1 16 54 18002b87a46d6c4de954a316b5ce28a99886f2abb6b0307190e577b81171dfb7a067139835be8625bc36b0edaaed357609107d85d335 1 1 23 46 1000c01fcdb3050a2270f82dbafbe4c1adc868377bf7133ee7a1bcaf85817abe541beb8008b91c54b99e93d2e0f5 -1; +policy testpol 0 0 1 3 1 0 0 0 0 diff --git a/krb5-1.21.3/src/tests/etinfo.c b/krb5-1.21.3/src/tests/etinfo.c new file mode 100644 index 00000000..6b8a4f33 --- /dev/null +++ b/krb5-1.21.3/src/tests/etinfo.c @@ -0,0 +1,172 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/etinfo.c - Test harness for KDC etype-info behavior */ +/* + * Copyright (C) 2015 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. + */ + +/* + * Send an AS-REQ to the KDC for a specified principal, with an optionally + * specified request enctype list. Decode the output as either an AS-REP or a + * KRB-ERROR and display the PA-ETYPE-INFO2, PA-ETYPE-INFO, and PA-PW-SALT + * padata in the following format: + * + * error/asrep etype-info2/etype-info/pw-salt enctype salt [s2kparams] + * + * enctype is omitted for PA-PW-SALT entries. salt is displayed directly; + * s2kparams is displayed in uppercase hex. + */ + +#include "k5-int.h" + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +static void +display_etinfo(krb5_etype_info_entry **list, const char *l1, const char *l2) +{ + krb5_etype_info_entry *info; + char etname[256]; + unsigned int i; + + for (; *list != NULL; list++) { + info = *list; + check(krb5_enctype_to_name(info->etype, TRUE, etname, sizeof(etname))); + printf("%s %s %s ", l1, l2, etname); + if (info->length != KRB5_ETYPE_NO_SALT) + printf("%.*s", info->length, info->salt); + else + printf("(default)"); + if (info->s2kparams.length > 0) { + printf(" "); + for (i = 0; i < info->s2kparams.length; i++) + printf("%02X", (unsigned char)info->s2kparams.data[i]); + } + printf("\n"); + } +} + +static void +display_padata(krb5_pa_data **pa_list, const char *label) +{ + krb5_pa_data *pa; + krb5_data d; + krb5_etype_info_entry **etinfo_list; + + for (; pa_list != NULL && *pa_list != NULL; pa_list++) { + pa = *pa_list; + d = make_data(pa->contents, pa->length); + if (pa->pa_type == KRB5_PADATA_ETYPE_INFO2) { + check(decode_krb5_etype_info2(&d, &etinfo_list)); + display_etinfo(etinfo_list, label, "etype_info2"); + krb5_free_etype_info(ctx, etinfo_list); + } else if (pa->pa_type == KRB5_PADATA_ETYPE_INFO) { + check(decode_krb5_etype_info(&d, &etinfo_list)); + display_etinfo(etinfo_list, label, "etype_info"); + krb5_free_etype_info(ctx, etinfo_list); + } else if (pa->pa_type == KRB5_PADATA_PW_SALT) { + printf("%s pw_salt %.*s\n", label, (int)d.length, d.data); + } else if (pa->pa_type == KRB5_PADATA_AFS3_SALT) { + printf("%s afs3_salt %.*s\n", label, (int)d.length, d.data); + } + } +} + +int +main(int argc, char **argv) +{ + krb5_principal client; + krb5_get_init_creds_opt *opt; + krb5_init_creds_context icc; + krb5_data reply, request, realm; + krb5_error *error; + krb5_kdc_rep *asrep; + krb5_pa_data **padata; + krb5_preauthtype pa_type = KRB5_PADATA_NONE; + unsigned int flags; + int primary = 0; + + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: %s princname [patype]\n", argv[0]); + exit(1); + } + check(krb5_init_context(&ctx)); + check(krb5_parse_name(ctx, argv[1], &client)); + if (argc >= 3) + pa_type = atoi(argv[2]); + + check(krb5_get_init_creds_opt_alloc(ctx, &opt)); + if (pa_type != KRB5_PADATA_NONE) + krb5_get_init_creds_opt_set_preauth_list(opt, &pa_type, 1); + + check(krb5_init_creds_init(ctx, client, NULL, NULL, 0, opt, &icc)); + reply = empty_data(); + check(krb5_init_creds_step(ctx, icc, &reply, &request, &realm, &flags)); + assert(flags == KRB5_INIT_CREDS_STEP_FLAG_CONTINUE); + check(krb5_sendto_kdc(ctx, &request, &realm, &reply, &primary, 0)); + + if (decode_krb5_error(&reply, &error) == 0) { + decode_krb5_padata_sequence(&error->e_data, &padata); + if (error->error == KDC_ERR_PREAUTH_REQUIRED) { + display_padata(padata, "error"); + } else if (error->error == KDC_ERR_MORE_PREAUTH_DATA_REQUIRED) { + display_padata(padata, "more"); + } else { + fprintf(stderr, "Unexpected error %d\n", (int)error->error); + return 1; + } + krb5_free_pa_data(ctx, padata); + krb5_free_error(ctx, error); + } else if (decode_krb5_as_rep(&reply, &asrep) == 0) { + display_padata(asrep->padata, "asrep"); + krb5_free_kdc_rep(ctx, asrep); + } else { + abort(); + } + + krb5_free_data_contents(ctx, &request); + krb5_free_data_contents(ctx, &reply); + krb5_free_data_contents(ctx, &realm); + krb5_get_init_creds_opt_free(ctx, opt); + krb5_init_creds_free(ctx, icc); + krb5_free_principal(ctx, client); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/forward.c b/krb5-1.21.3/src/tests/forward.c new file mode 100644 index 00000000..7327cc9e --- /dev/null +++ b/krb5-1.21.3/src/tests/forward.c @@ -0,0 +1,93 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/forward.c - test harness for getting forwarded creds */ +/* + * Copyright (C) 2016 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. + */ + +/* This test program overwrites the default credential cache with a forwarded + * TGT obtained using the TGT presently in the cache. */ + +#include "k5-int.h" + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +int +main() +{ + krb5_ccache cc; + krb5_creds mcred, tgt, *fcred; + krb5_principal client, tgtprinc; + krb5_flags options; + + /* Open the default ccache and get the client and TGT principal names. */ + check(krb5_init_context(&ctx)); + check(krb5_cc_default(ctx, &cc)); + check(krb5_cc_get_principal(ctx, cc, &client)); + check(krb5_build_principal_ext(ctx, &tgtprinc, client->realm.length, + client->realm.data, KRB5_TGS_NAME_SIZE, + KRB5_TGS_NAME, client->realm.length, + client->realm.data, 0)); + + /* Fetch the TGT credential. */ + memset(&mcred, 0, sizeof(mcred)); + mcred.client = client; + mcred.server = tgtprinc; + check(krb5_cc_retrieve_cred(ctx, cc, 0, &mcred, &tgt)); + + /* Get a forwarded TGT. */ + mcred.times = tgt.times; + mcred.times.starttime = 0; + options = (tgt.ticket_flags & KDC_TKT_COMMON_MASK) | KDC_OPT_FORWARDED; + check(krb5_get_cred_via_tkt(ctx, &tgt, options, NULL, &mcred, &fcred)); + + /* Reinitialize the default ccache with the forwarded TGT. */ + check(krb5_cc_initialize(ctx, cc, client)); + check(krb5_cc_store_cred(ctx, cc, fcred)); + + krb5_free_creds(ctx, fcred); + krb5_free_cred_contents(ctx, &tgt); + krb5_free_principal(ctx, tgtprinc); + krb5_free_principal(ctx, client); + krb5_cc_close(ctx, cc); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gcred.c b/krb5-1.21.3/src/tests/gcred.c new file mode 100644 index 00000000..1efb9339 --- /dev/null +++ b/krb5-1.21.3/src/tests/gcred.c @@ -0,0 +1,124 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gcred.c - Test harness for referrals */ +/* + * Copyright (C) 2012 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. + */ + +/* + * This program is intended to be run from a python script as: + * + * gcred [-f] [-t] nametype princname + * + * where nametype is one of "unknown", "principal", "srv-inst", and "srv-hst", + * and princname is the name of the service principal. gcred acquires + * credentials for the specified server principal. On success, gcred displays + * the server principal name of the obtained credentials to stdout and exits + * with status 0. On failure, gcred displays the error message for the failed + * operation to stderr and exits with status 1. + * + * The -f and -t flags set the KRB5_GC_FORWARDABLE and KRB5_GC_NO_TRANSIT_CHECK + * options respectively. + */ + +#include "k5-int.h" + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +int +main(int argc, char **argv) +{ + krb5_principal client, server; + krb5_ccache ccache; + krb5_creds in_creds, *creds; + krb5_ticket *ticket; + krb5_flags options = 0; + char *name; + int c; + + check(krb5_init_context(&ctx)); + + while ((c = getopt(argc, argv, "ft")) != -1) { + switch (c) { + case 'f': + options |= KRB5_GC_FORWARDABLE; + break; + case 't': + options |= KRB5_GC_NO_TRANSIT_CHECK; + break; + default: + abort(); + } + } + argc -= optind; + argv += optind; + assert(argc == 2); + check(krb5_parse_name(ctx, argv[1], &server)); + if (strcmp(argv[0], "unknown") == 0) + server->type = KRB5_NT_UNKNOWN; + else if (strcmp(argv[0], "principal") == 0) + server->type = KRB5_NT_PRINCIPAL; + else if (strcmp(argv[0], "srv-inst") == 0) + server->type = KRB5_NT_SRV_INST; + else if (strcmp(argv[0], "srv-hst") == 0) + server->type = KRB5_NT_SRV_HST; + else + abort(); + + check(krb5_cc_default(ctx, &ccache)); + check(krb5_cc_get_principal(ctx, ccache, &client)); + memset(&in_creds, 0, sizeof(in_creds)); + in_creds.client = client; + in_creds.server = server; + check(krb5_get_credentials(ctx, options, ccache, &in_creds, &creds)); + check(krb5_decode_ticket(&creds->ticket, &ticket)); + check(krb5_unparse_name(ctx, ticket->server, &name)); + printf("%s\n", name); + + krb5_free_ticket(ctx, ticket); + krb5_free_unparsed_name(ctx, name); + krb5_free_creds(ctx, creds); + krb5_free_principal(ctx, client); + krb5_free_principal(ctx, server); + krb5_cc_close(ctx, ccache); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gss-threads/Makefile.in b/krb5-1.21.3/src/tests/gss-threads/Makefile.in new file mode 100644 index 00000000..fe2f33b7 --- /dev/null +++ b/krb5-1.21.3/src/tests/gss-threads/Makefile.in @@ -0,0 +1,34 @@ +# Derived from appl/gss-sample, January 2005. + +mydir=tests$(S)gss-threads +BUILDTOP=$(REL)..$(S).. +DEFINES = -DUSE_AUTOCONF_H -DGSSAPI_V2 +PTHREAD_LIBS=@PTHREAD_LIBS@ + +SRCS= $(srcdir)/gss-client.c $(srcdir)/gss-misc.c $(srcdir)/gss-server.c + +OBJS= gss-client.o gss-misc.o gss-server.o + +all-unix: all-unix-@THREAD_SUPPORT@ +all-unix-1: gss-server gss-client +all-unix-0: +all-windows: $(OUTPRE)gss-server.exe $(OUTPRE)gss-client.exe + +gss-server: gss-server.o gss-misc.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) $(PTHREAD_CFLAGS) -o gss-server gss-server.o gss-misc.o $(GSS_LIBS) $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS) + +gss-client: gss-client.o gss-misc.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) $(PTHREAD_CFLAGS) -o gss-client gss-client.o gss-misc.o $(GSS_LIBS) $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS) + +$(OUTPRE)gss-server.exe: $(OUTPRE)gss-server.obj $(OUTPRE)gss-misc.obj $(GLIB) $(KLIB) + link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib + +$(OUTPRE)gss-client.exe: $(OUTPRE)gss-client.obj $(OUTPRE)gss-misc.obj $(GLIB) $(KLIB) + link $(EXE_LINKOPTS) -out:$@ $** ws2_32.lib + +clean-unix:: + $(RM) gss-server gss-client + +install-unix: +# $(INSTALL_PROGRAM) gss-client $(DESTDIR)$(CLIENT_BINDIR)/gss-tclient +# $(INSTALL_PROGRAM) gss-server $(DESTDIR)$(SERVER_BINDIR)/gss-tserver diff --git a/krb5-1.21.3/src/tests/gss-threads/README b/krb5-1.21.3/src/tests/gss-threads/README new file mode 100644 index 00000000..f555b3e3 --- /dev/null +++ b/krb5-1.21.3/src/tests/gss-threads/README @@ -0,0 +1,165 @@ +[Out of date; needs updating for thread safety test support. -- KR 2005-02-09] + +# Copyright 1993 by OpenVision Technologies, Inc. +# +# Permission to use, copy, modify, distribute, and sell this software +# and its documentation for any purpose is hereby granted without fee, +# provided that the above copyright notice appears in all copies and +# that both that copyright notice and this permission notice appear in +# supporting documentation, and that the name of OpenVision not be used +# in advertising or publicity pertaining to distribution of the software +# without specific, written prior permission. OpenVision makes no +# representations about the suitability of this software for any +# purpose. It is provided "as is" without express or implied warranty. +# +# OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. + +This directory contains a sample GSS-API client and server +application. In addition to serving as an example of GSS-API +programming, this application is also intended to be a tool for +testing the performance of GSS-API implementations. + +Each time the client is invoked, it performs one or more exchanges +with the server. Each exchange with the server consists primarily of +the following steps: + + 1. A TCP/IP connection is established. + + 2. (optional, on by default) The client and server establish a + GSS-API context, and the server prints the identify of the + client. + + / 3. The client sends a message to the server. The message may + / be plaintext, cryptographically "signed" but not encrypted, + | or encrypted (default). + | +0 or | 4. The server decrypts the message (if necessary), verifies +more | its signature (if there is one) and prints it. +times| + | 5. The server sends either a signature block (the default) or an + | empty token back to the client to acknowledge the message. + \ + \ 6. If the server sent a signature block, the client verifies + it and prints a message indicating that it was verified. + + 7. The client sends an empty block to the server to tell it + that the exchange is finished. + + 8. The client and server close the TCP/IP connection and + destroy the GSS-API context. + +The client also supports the -v1 flag which uses an older exchange +format compatible with previous releases of Kerberos and with samples +shipped in the Microsoft SDK. + +The server's command line usage is + + gss-server [-port port] [-verbose] [-once] [-inetd] [-export] + [-logfile file] service_name + +where service_name is a GSS-API service name of the form +"service@host" (or just "service", in which case the local host name +is used). The command-line options have the following meanings: + +-port The TCP port on which to accept connections. Default is 4444. + +-once Tells the server to exit after a single exchange, rather than + persisting. + +-inetd Tells the server that it is running out of inetd, so it should + interact with the client on stdin rather than binding to a + network port. Implies "-once". + +-export Tells the server to test the gss_export_sec_context function + after establishing a context with a client. + +-logfile + The file to which the server should append its output, rather + than sending it to stdout. + +The client's command line usage is + + gss-client [-port port] [-mech mechanism] [-d] [-f] [-q] + [-seq] [-noreplay] [-nomutual] + [-ccount count] [-mcount count] [-na] [-nw] [-nx] [-nm] + host service_name msg + +where host is the host running the server, service_name is the service +name that the server will establish connections as (if you don't +specify the host name in the service name when running gss-server, and +it's running on a different machine from gss-client, make sure to +specify the server's host name in the service name you specify to +gss-client!) and msg is the message. The command-line options have +the following meanings: + +-port The TCP port to which to connect. Default is 4444. + +-mech The OID of the GSS-API mechanism to use. + +-d Tells the client to delegate credentials to the server. For + the Kerberos GSS-API mechanism, this means that a forwardable + TGT will be sent to the server, which will put it in its + credential cache (you must have acquired your tickets with + "kinit -f" for this to work). + +-seq Tells the client to enforce ordered message delivery via + sequencing. + +-noreplay Tells the client to disable the use of replay + detection. + +-nomutual Tells the client to disable the use of mutual authentication. + +-f Tells the client that the "msg" argument is actually the name + of a file whose contents should be used as the message. + +-q Tells the client to be quiet, i.e., to only print error + messages. + +-ccount Specifies how many sessions the client should initiate with + the server (the "connection count"). + +-mcount Specifies how many times the message should be sent to the + server in each session (the "message count"). + +-na Tells the client not to do any authentication with the + server. Implies "-nw", "-nx" and "-nm". + +-nw Tells the client not to "wrap" messages. Implies "-nx". + +-nx Tells the client not to encrypt messages. + +-nm Tells the client not to ask the server to send back a + cryptographic checksum ("MIC"). + +To run the server on a host, you need to make sure that the principal +corresponding to service_name is in the default keytab on the server +host, and that the gss-server process can read the keytab. For +example, the service name "host@server" corresponds to the Kerberos +principal "host/server.domain.com@REALM". + +This sample application uses the following GSS-API functions: + + gss_accept_sec_context gss_inquire_names_for_mech + gss_acquire_cred gss_oid_to_str + gss_delete_sec_context gss_release_buffer + gss_display_name gss_release_cred + gss_display_status gss_release_name + gss_export_sec_context gss_release_oid + gss_get_mic gss_release_oid_set + gss_import_name gss_str_to_oid + gss_import_sec_context gss_unwrap + gss_init_sec_context gss_verify_mic + gss_inquire_context gss_wrap + +This application was originally written by Barry Jaspan of OpenVision +Technologies, Inc. It was updated significantly by Jonathan Kamens of +OpenVision Technologies, Inc. + +$Id$ diff --git a/krb5-1.21.3/src/tests/gss-threads/deps b/krb5-1.21.3/src/tests/gss-threads/deps new file mode 100644 index 00000000..e1c17a06 --- /dev/null +++ b/krb5-1.21.3/src/tests/gss-threads/deps @@ -0,0 +1,15 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)gss-client.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \ + $(top_srcdir)/include/fake-addrinfo.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h gss-client.c gss-misc.h +$(OUTPRE)gss-misc.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + gss-misc.c gss-misc.h +$(OUTPRE)gss-server.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_generic.h \ + $(top_srcdir)/include/port-sockets.h gss-misc.h gss-server.c diff --git a/krb5-1.21.3/src/tests/gss-threads/gss-client.c b/krb5-1.21.3/src/tests/gss-threads/gss-client.c new file mode 100644 index 00000000..c0cf25dd --- /dev/null +++ b/krb5-1.21.3/src/tests/gss-threads/gss-client.c @@ -0,0 +1,865 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1994 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (C) 2003, 2004, 2008 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-platform.h" +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include "gss-misc.h" +#include "port-sockets.h" +#include "fake-addrinfo.h" + +static int verbose = 1; + +static void +usage() +{ + fprintf(stderr, "Usage: gss-client [-port port] [-mech mechanism] [-d]\n"); + fprintf(stderr, " [-seq] [-noreplay] [-nomutual]"); + fprintf(stderr, " [-threads num]"); + fprintf(stderr, "\n"); + fprintf(stderr, " [-f] [-q] [-ccount count] [-mcount count]\n"); + fprintf(stderr, " [-v1] [-na] [-nw] [-nx] [-nm] host service msg\n"); + exit(1); +} + +/* + * Function: get_server_info + * + * Purpose: Sets up a socket address for the named host and port. + * + * Arguments: + * + * host (r) the target host name + * port (r) the target port, in host byte order + * + * Returns: 0 on success, or -1 on failure + * + * Effects: + * + * The host name is resolved with gethostbyname(), and "saddr" is set + * to the desired socket address. If an error occurs, an error + * message is displayed and -1 is returned. + */ +struct sockaddr_in saddr; +static int +get_server_info(char *host, u_short port) +{ + struct hostent *hp; + + hp = gethostbyname(host); + if (hp == NULL) { + fprintf(stderr, "Unknown host: %s\n", host); + return -1; + } + + saddr.sin_family = hp->h_addrtype; + memcpy(&saddr.sin_addr, hp->h_addr, sizeof(saddr.sin_addr)); + saddr.sin_port = htons(port); + return 0; +} + +/* + * Function: connect_to_server + * + * Purpose: Opens a TCP connection to the name host and port. + * + * Arguments: + * + * host (r) the target host name + * port (r) the target port, in host byte order + * + * Returns: the established socket file descriptor, or -1 on failure + * + * Effects: + * + * The host name is resolved with gethostbyname(), and the socket is + * opened and connected. If an error occurs, an error message is + * displayed and -1 is returned. + */ +static int +connect_to_server() +{ + int s; + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) { + perror("creating socket"); + return -1; + } + if (connect(s, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { + perror("connecting to server"); + (void)closesocket(s); + return -1; + } + return s; +} + +/* + * Function: client_establish_context + * + * Purpose: establishes a GSS-API context with a specified service and + * returns the context handle + * + * Arguments: + * + * s (r) an established TCP connection to the service + * service_name (r) the ASCII service name of the service + * gss_flags (r) GSS-API delegation flag (if any) + * auth_flag (r) whether to actually do authentication + * v1_format (r) whether the v1 sample protocol should be used + * oid (r) OID of the mechanism to use + * context (w) the established GSS-API context + * ret_flags (w) the returned flags from init_sec_context + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * service_name is imported as a GSS-API name and a GSS-API context is + * established with the corresponding service; the service should be + * listening on the TCP connection s. The default GSS-API mechanism + * is used, and mutual authentication and replay detection are + * requested. + * + * If successful, the context handle is returned in context. If + * unsuccessful, the GSS-API error messages are displayed on stderr + * and -1 is returned. + */ +static int +client_establish_context(int s, char *service_name, OM_uint32 gss_flags, + int auth_flag, int v1_format, gss_OID oid, + gss_ctx_id_t *gss_context, OM_uint32 *ret_flags) +{ + if (auth_flag) { + gss_buffer_desc send_tok, recv_tok, *token_ptr; + gss_name_t target_name; + OM_uint32 maj_stat, min_stat, init_sec_min_stat; + int token_flags; + + /* + * Import the name into target_name. Use send_tok to save + * local variable space. + */ + send_tok.value = service_name; + send_tok.length = strlen(service_name); + maj_stat = gss_import_name(&min_stat, &send_tok, + (gss_OID)gss_nt_service_name, &target_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("parsing name", maj_stat, min_stat); + return -1; + } + + if (!v1_format) { + if (send_token(s, TOKEN_NOOP | TOKEN_CONTEXT_NEXT, + empty_token) < 0) { + (void)gss_release_name(&min_stat, &target_name); + return -1; + } + } + + /* + * Perform the context-establishement loop. + * + * On each pass through the loop, token_ptr points to the token + * to send to the server (or GSS_C_NO_BUFFER on the first pass). + * Every generated token is stored in send_tok which is then + * transmitted to the server; every received token is stored in + * recv_tok, which token_ptr is then set to, to be processed by + * the next call to gss_init_sec_context. + * + * GSS-API guarantees that send_tok's length will be non-zero + * if and only if the server is expecting another token from us, + * and that gss_init_sec_context returns GSS_S_CONTINUE_NEEDED if + * and only if the server has another token to send us. + */ + + token_ptr = GSS_C_NO_BUFFER; + *gss_context = GSS_C_NO_CONTEXT; + + do { + maj_stat = gss_init_sec_context(&init_sec_min_stat, + GSS_C_NO_CREDENTIAL, gss_context, + target_name, oid, gss_flags, 0, + NULL, token_ptr, NULL, &send_tok, + ret_flags, NULL); + + if (token_ptr != GSS_C_NO_BUFFER) + free(recv_tok.value); + + if (send_tok.length != 0) { + if (verbose) { + printf("Sending init_sec_context token (size=%d)...", + (int)send_tok.length); + } + if (send_token(s, v1_format ? 0 : TOKEN_CONTEXT, + &send_tok) < 0) { + (void)gss_release_buffer(&min_stat, &send_tok); + (void)gss_release_name(&min_stat, &target_name); + if (*gss_context != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&min_stat, gss_context, + GSS_C_NO_BUFFER); + *gss_context = GSS_C_NO_CONTEXT; + } + return -1; + } + } + (void)gss_release_buffer(&min_stat, &send_tok); + + if (maj_stat != GSS_S_COMPLETE && + maj_stat != GSS_S_CONTINUE_NEEDED) { + display_status("initializing context", maj_stat, + init_sec_min_stat); + (void)gss_release_name(&min_stat, &target_name); + if (*gss_context != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&min_stat, gss_context, + GSS_C_NO_BUFFER); + } + return -1; + } + + if (maj_stat == GSS_S_CONTINUE_NEEDED) { + if (verbose) + printf("continue needed..."); + if (recv_token(s, &token_flags, &recv_tok) < 0) { + (void)gss_release_name(&min_stat, &target_name); + return -1; + } + token_ptr = &recv_tok; + } + if (verbose) + printf("\n"); + } while (maj_stat == GSS_S_CONTINUE_NEEDED); + + (void)gss_release_name(&min_stat, &target_name); + } else if (send_token(s, TOKEN_NOOP, empty_token) < 0) { + return -1; + } + + return 0; +} + +static void +read_file(char *file_name, gss_buffer_t in_buf) +{ + int fd, count; + struct stat stat_buf; + + fd = open(file_name, O_RDONLY, 0); + if (fd < 0) { + perror("open"); + fprintf(stderr, "Couldn't open file %s\n", file_name); + exit(2); + } + if (fstat(fd, &stat_buf) < 0) { + perror("fstat"); + exit(3); + } + in_buf->length = stat_buf.st_size; + + if (in_buf->length == 0) { + in_buf->value = NULL; + return; + } + + in_buf->value = malloc(in_buf->length); + if (in_buf->value == NULL) { + fprintf(stderr, "Couldn't allocate %d byte buffer for reading file\n", + (int)in_buf->length); + exit(4); + } + + /* This code used to check for incomplete reads, but you can't get + * an incomplete read on any file for which fstat() is meaningful. */ + + count = read(fd, in_buf->value, in_buf->length); + if (count < 0) { + perror("read"); + exit(5); + } + if ((size_t)count < in_buf->length) { + fprintf(stderr, "Warning, only read in %d bytes, expected %d\n", + count, (int)in_buf->length); + } +} + +/* + * Function: call_server + * + * Purpose: Call the "sign" service. + * + * Arguments: + * + * host (r) the host providing the service + * port (r) the port to connect to on host + * service_name (r) the GSS-API service name to authenticate to + * gss_flags (r) GSS-API delegation flag (if any) + * auth_flag (r) whether to do authentication + * wrap_flag (r) whether to do message wrapping at all + * encrypt_flag (r) whether to do encryption while wrapping + * mic_flag (r) whether to request a MIC from the server + * msg (r) the message to have "signed" + * use_file (r) whether to treat msg as an input file name + * mcount (r) the number of times to send the message + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * call_server opens a TCP connection to and establishes a + * GSS-API context with service_name over the connection. It then + * seals msg in a GSS-API token with gss_wrap, sends it to the server, + * reads back a GSS-API signature block for msg from the server, and + * verifies it with gss_verify. -1 is returned if any step fails, + * otherwise 0 is returned. + */ +static int +call_server(char *host, u_short port, gss_OID oid, char *service_name, + OM_uint32 gss_flags, int auth_flag, int wrap_flag, + int encrypt_flag, int mic_flag, int v1_format, char *msg, + int use_file, size_t mcount) +{ + gss_ctx_id_t context; + gss_buffer_desc in_buf, out_buf, sname, tname, oid_name; + int s, state, is_local, is_open, flags, token_flags; + OM_uint32 ret_flags, maj_stat, min_stat, lifetime, context_flags; + gss_name_t src_name, targ_name; + gss_OID mechanism, name_type; + gss_qop_t qop_state; + gss_OID_set mech_names; + size_t i; + + /* Open connection. */ + s = connect_to_server(); + if (s < 0) + return -1; + + /* Establish context. */ + if (client_establish_context(s, service_name, gss_flags, auth_flag, + v1_format, oid, &context, &ret_flags) < 0) { + (void)closesocket(s); + return -1; + } + + if (auth_flag && verbose) { + /* Display the flags. */ + display_ctx_flags(ret_flags); + + /* Get context information. */ + maj_stat = gss_inquire_context(&min_stat, context, &src_name, + &targ_name, &lifetime, &mechanism, + &context_flags, &is_local, &is_open); + if (maj_stat != GSS_S_COMPLETE) { + display_status("inquiring context", maj_stat, min_stat); + return -1; + } + + maj_stat = gss_display_name(&min_stat, src_name, &sname, &name_type); + if (maj_stat != GSS_S_COMPLETE) { + display_status("displaying source name", maj_stat, min_stat); + return -1; + } + maj_stat = gss_display_name(&min_stat, targ_name, &tname, NULL); + if (maj_stat != GSS_S_COMPLETE) { + display_status("displaying target name", maj_stat, min_stat); + return -1; + } + printf("\"%.*s\" to \"%.*s\", lifetime %d, flags %x, %s, %s\n", + (int)sname.length, (char *)sname.value, + (int)tname.length, (char *)tname.value, lifetime, context_flags, + is_local ? "locally initiated" : "remotely initiated", + is_open ? "open" : "closed"); + + (void)gss_release_name(&min_stat, &src_name); + (void)gss_release_name(&min_stat, &targ_name); + (void)gss_release_buffer(&min_stat, &sname); + (void)gss_release_buffer(&min_stat, &tname); + + maj_stat = gss_oid_to_str(&min_stat, name_type, &oid_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("converting oid->string", maj_stat, min_stat); + return -1; + } + printf("Name type of source name is %.*s.\n", (int)oid_name.length, + (char *)oid_name.value); + (void)gss_release_buffer(&min_stat, &oid_name); + + /* Now get the names supported by the mechanism. */ + maj_stat = gss_inquire_names_for_mech(&min_stat, mechanism, + &mech_names); + if (maj_stat != GSS_S_COMPLETE) { + display_status("inquiring mech names", maj_stat, min_stat); + return -1; + } + + maj_stat = gss_oid_to_str(&min_stat, mechanism, &oid_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("converting oid->string", maj_stat, min_stat); + return -1; + } + printf("Mechanism %.*s supports %d names\n", (int)oid_name.length, + (char *)oid_name.value, (int)mech_names->count); + (void)gss_release_buffer(&min_stat, &oid_name); + + for (i = 0; i < mech_names->count; i++) { + maj_stat = gss_oid_to_str(&min_stat, &mech_names->elements[i], + &oid_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("converting oid->string", maj_stat, min_stat); + return -1; + } + printf(" %d: %.*s\n", (int)i, (int)oid_name.length, + (char *)oid_name.value); + + (void)gss_release_buffer(&min_stat, &oid_name); + } + (void)gss_release_oid_set(&min_stat, &mech_names); + } + + if (use_file) { + read_file(msg, &in_buf); + } else { + /* Seal the message. */ + in_buf.value = msg; + in_buf.length = strlen(msg); + } + + for (i = 0; i < mcount; i++) { + if (wrap_flag) { + maj_stat = gss_wrap(&min_stat, context, encrypt_flag, + GSS_C_QOP_DEFAULT, &in_buf, &state, &out_buf); + if (maj_stat != GSS_S_COMPLETE) { + display_status("wrapping message", maj_stat, min_stat); + (void)closesocket(s); + (void)gss_delete_sec_context(&min_stat, &context, + GSS_C_NO_BUFFER); + return -1; + } else if (encrypt_flag && !state) { + fprintf(stderr, "Warning! Message not encrypted.\n"); + } + } else { + out_buf = in_buf; + } + + /* Send to server. */ + flags = 0; + if (!v1_format) { + flags = TOKEN_DATA | (wrap_flag ? TOKEN_WRAPPED : 0) | + (encrypt_flag ? TOKEN_ENCRYPTED : 0) | + (mic_flag ? TOKEN_SEND_MIC : 0); + } + if (send_token(s, flags, &out_buf) < 0) { + (void)closesocket(s); + (void)gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER); + return -1; + } + if (out_buf.value != in_buf.value) + (void)gss_release_buffer(&min_stat, &out_buf); + + /* Read signature block into out_buf. */ + if (recv_token(s, &token_flags, &out_buf) < 0) { + (void)closesocket(s); + (void)gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER); + return -1; + } + + if (mic_flag) { + /* Verify signature block. */ + maj_stat = gss_verify_mic(&min_stat, context, &in_buf, &out_buf, + &qop_state); + if (maj_stat != GSS_S_COMPLETE) { + display_status("verifying signature", maj_stat, min_stat); + (void)closesocket(s); + (void)gss_delete_sec_context(&min_stat, &context, + GSS_C_NO_BUFFER); + return -1; + } + + if (verbose) + printf("Signature verified.\n"); + } else if (verbose) { + printf("Response received.\n"); + } + + free(out_buf.value); + } + + if (use_file) + free(in_buf.value); + + /* Send NOOP. */ + if (!v1_format) + (void)send_token(s, TOKEN_NOOP, empty_token); + + if (auth_flag) { + /* Delete context. */ + maj_stat = gss_delete_sec_context(&min_stat, &context, &out_buf); + if (maj_stat != GSS_S_COMPLETE) { + display_status("deleting context", maj_stat, min_stat); + (void)closesocket(s); + (void)gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER); + return -1; + } + + (void)gss_release_buffer(&min_stat, &out_buf); + } + + (void)closesocket(s); + return 0; +} + +static void +parse_oid(char *mechanism, gss_OID *oid) +{ + char *mechstr = 0, *cp; + gss_buffer_desc tok; + OM_uint32 maj_stat, min_stat; + + if (isdigit((unsigned char)mechanism[0])) { + if (asprintf(&mechstr, "{ %s }", mechanism) < 0) { + fprintf(stderr, "Couldn't allocate mechanism scratch!\n"); + return; + } + for (cp = mechstr; *cp; cp++) { + if (*cp == '.') + *cp = ' '; + } + tok.value = mechstr; + } else { + tok.value = mechanism; + } + tok.length = strlen(tok.value); + maj_stat = gss_str_to_oid(&min_stat, &tok, oid); + if (maj_stat != GSS_S_COMPLETE) { + display_status("str_to_oid", maj_stat, min_stat); + return; + } + if (mechstr) + free(mechstr); +} + +static int max_threads = 1; + +#ifdef _WIN32 +static thread_count = 0; +static HANDLE hMutex = NULL; +static HANDLE hEvent = NULL; + +void +init_handles(void) +{ + hMutex = CreateMutex(NULL, FALSE, NULL); + hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); +} + +void +cleanup_handles(void) +{ + CloseHandle(hMutex); + CloseHandle(hEvent); +} + +BOOL +wait_and_increment_thread_counter(void) +{ + for (;;) { + if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) { + if (thread_count < max_threads) { + thread_count++; + ReleaseMutex(hMutex); + return TRUE; + } else { + ReleaseMutex(hMutex); + + if (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0) + continue; + else + return FALSE; + } + } else { + return FALSE; + } + } +} + +BOOL +decrement_and_signal_thread_counter(void) +{ + if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) { + if (thread_count == max_threads) + SetEvent(hEvent); + thread_count--; + ReleaseMutex(hMutex); + return TRUE; + } else { + return FALSE; + } +} + +#else /* assume pthread */ + +static pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t counter_cond = PTHREAD_COND_INITIALIZER; +int counter = 0; + +static int +wait_and_increment_thread_counter(void) +{ + int err; + + err = pthread_mutex_lock(&counter_mutex); + if (err) { + perror("pthread_mutex_lock"); + return 0; + } + if (counter == max_threads) { + err = pthread_cond_wait(&counter_cond, &counter_mutex); + if (err) { + pthread_mutex_unlock(&counter_mutex); + perror("pthread_cond_wait"); + return 0; + } + } + counter++; + pthread_mutex_unlock(&counter_mutex); + return 1; +} + +static void +decrement_and_signal_thread_counter(void) +{ + int err; + + sleep(1); + err = pthread_mutex_lock(&counter_mutex); + if (err) { + perror("pthread_mutex_lock"); + return; + } + if (counter == max_threads) + pthread_cond_broadcast(&counter_cond); + counter--; + pthread_mutex_unlock(&counter_mutex); +} + +#endif + +static char *service_name, *server_host, *msg; +static char *mechanism = 0; +static u_short port = 4444; +static int use_file = 0; +static OM_uint32 gss_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG; +static OM_uint32 min_stat; +static gss_OID oid = GSS_C_NULL_OID; +static int mcount = 1, ccount = 1; +static int auth_flag, wrap_flag, encrypt_flag, mic_flag, v1_format; + +static void * +worker_bee(void *unused) +{ + printf("worker bee!\n"); + if (call_server(server_host, port, oid, service_name, + gss_flags, auth_flag, wrap_flag, encrypt_flag, mic_flag, + v1_format, msg, use_file, mcount) < 0) { + if (max_threads == 1) + exit(6); + } + + if (max_threads > 1) + decrement_and_signal_thread_counter(); + free(unused); + return NULL; +} + +int +main(int argc, char **argv) +{ + int i; + + display_file = stdout; + auth_flag = wrap_flag = encrypt_flag = mic_flag = 1; + v1_format = 0; + + /* Parse arguments. */ + argc--; + argv++; + while (argc) { + if (strcmp(*argv, "-port") == 0) { + argc--; + argv++; + if (!argc) + usage(); + port = atoi(*argv); + } else if (strcmp(*argv, "-mech") == 0) { + argc--; + argv++; + if (!argc) + usage(); + mechanism = *argv; + } else if (strcmp(*argv, "-threads") == 0) { + argc--; + argv++; + if (!argc) + usage(); + max_threads = atoi(*argv); + } else if (strcmp(*argv, "-d") == 0) { + gss_flags |= GSS_C_DELEG_FLAG; + } else if (strcmp(*argv, "-seq") == 0) { + gss_flags |= GSS_C_SEQUENCE_FLAG; + } else if (strcmp(*argv, "-noreplay") == 0) { + gss_flags &= ~GSS_C_REPLAY_FLAG; + } else if (strcmp(*argv, "-nomutual") == 0) { + gss_flags &= ~GSS_C_MUTUAL_FLAG; + } else if (strcmp(*argv, "-f") == 0) { + use_file = 1; + } else if (strcmp(*argv, "-q") == 0) { + verbose = 0; + } else if (strcmp(*argv, "-ccount") == 0) { + argc--; + argv++; + if (!argc) + usage(); + ccount = atoi(*argv); + if (ccount <= 0) + usage(); + } else if (strcmp(*argv, "-mcount") == 0) { + argc--; + argv++; + if (!argc) + usage(); + mcount = atoi(*argv); + if (mcount < 0) + usage(); + } else if (strcmp(*argv, "-na") == 0) { + auth_flag = wrap_flag = encrypt_flag = mic_flag = 0; + } else if (strcmp(*argv, "-nw") == 0) { + wrap_flag = 0; + } else if (strcmp(*argv, "-nx") == 0) { + encrypt_flag = 0; + } else if (strcmp(*argv, "-nm") == 0) { + mic_flag = 0; + } else if (strcmp(*argv, "-v1") == 0) { + v1_format = 1; + } else { + break; + } + argc--; + argv++; + } + if (argc != 3) + usage(); + +#ifdef _WIN32 + if (max_threads < 1) { + fprintf(stderr, "warning: there must be at least one thread\n"); + max_threads = 1; + } + + init_handles(); + SetEnvironmentVariable("KERBEROSLOGIN_NEVER_PROMPT", "1"); +#endif + + server_host = *argv++; + service_name = *argv++; + msg = *argv++; + + if (mechanism) + parse_oid(mechanism, &oid); + + if (get_server_info(server_host, port) < 0) + exit(1); + + if (max_threads == 1) { + for (i = 0; i < ccount; i++) + worker_bee(0); + } else { + for (i = 0; i < ccount; i++) { + if (wait_and_increment_thread_counter()) { +#ifdef _WIN32 + uintptr_t handle = _beginthread(worker_bee, 0, (void *)NULL); + if (handle == (uintptr_t)-1) + exit(7); +#else + int err; + pthread_t thr; + err = pthread_create(&thr, 0, worker_bee, malloc(12)); + if (err) { + perror("pthread_create"); + exit(7); + } + (void)pthread_detach(thr); +#endif + } else { + exit(8); + } + } + } + + if (oid != GSS_C_NULL_OID) + (void)gss_release_oid(&min_stat, &oid); + +#ifdef _WIN32 + cleanup_handles(); +#else + if (max_threads > 1) + sleep(10); +#endif + + return 0; +} diff --git a/krb5-1.21.3/src/tests/gss-threads/gss-misc.c b/krb5-1.21.3/src/tests/gss-threads/gss-misc.c new file mode 100644 index 00000000..4dd1b5dc --- /dev/null +++ b/krb5-1.21.3/src/tests/gss-threads/gss-misc.c @@ -0,0 +1,410 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1994 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (C) 2003, 2004 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "autoconf.h" +#include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#endif +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include + +/* need struct timeval */ +#include +#if HAVE_SYS_TIME_H +#include +#endif + +#include +#include "gss-misc.h" +/* for store_32_be */ +#include "k5-platform.h" + +#ifdef HAVE_STDLIB_H +#include +#else +extern char *malloc(); +#endif + +FILE *display_file; + +gss_buffer_desc empty_token_buf = { 0, (void *)"" }; +gss_buffer_t empty_token = &empty_token_buf; + +static void display_status_1(char *m, OM_uint32 code, int type); + +static int +write_all(int fildes, char *buf, unsigned int nbyte) +{ + int ret; + char *ptr; + + for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) { + ret = send(fildes, ptr, nbyte, 0); + if (ret < 0) { + if (errno == EINTR) + continue; + return ret; + } else if (ret == 0) { + return ptr - buf; + } + } + + return ptr - buf; +} + +static int +read_all(int fildes, char *buf, unsigned int nbyte) +{ + int ret; + char *ptr; + fd_set rfds; + struct timeval tv; + + FD_ZERO(&rfds); + FD_SET(fildes, &rfds); + tv.tv_sec = 10; + tv.tv_usec = 0; + + for (ptr = buf; nbyte; ptr += ret, nbyte -= ret) { + if (select(FD_SETSIZE, &rfds, NULL, NULL, &tv) <= 0 || + !FD_ISSET(fildes, &rfds)) + return ptr - buf; + ret = recv(fildes, ptr, nbyte, 0); + if (ret < 0) { + if (errno == EINTR) + continue; + return ret; + } else if (ret == 0) { + return ptr - buf; + } + } + + return ptr - buf; +} + +/* + * Function: send_token + * + * Purpose: Writes a token to a file descriptor. + * + * Arguments: + * + * s (r) an open file descriptor + * flags (r) the flags to write + * tok (r) the token to write + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * If the flags are non-null, send_token writes the token flags (a + * single byte, even though they're passed in in an integer). Next, + * the token length (as a network long) and then the token data are + * written to the file descriptor s. It returns 0 on success, and -1 + * if an error occurs or if it could not write all the data. + */ +int +send_token(int s, int flags, gss_buffer_t tok) +{ + int ret; + unsigned char char_flags = (unsigned char)flags; + unsigned char lenbuf[4]; + + if (char_flags) { + ret = write_all(s, (char *)&char_flags, 1); + if (ret != 1) { + perror("sending token flags"); + return -1; + } + } + if (tok->length > 0xffffffffUL) + abort(); + store_32_be(tok->length, lenbuf); + ret = write_all(s, (char *)lenbuf, 4); + if (ret < 0) { + perror("sending token length"); + return -1; + } else if (ret != 4) { + if (display_file) { + fprintf(display_file, + "sending token length: %d of %d bytes written\n", ret, 4); + } + return -1; + } + + ret = write_all(s, tok->value, tok->length); + if (ret < 0) { + perror("sending token data"); + return -1; + } else if ((size_t)ret != tok->length) { + if (display_file) { + fprintf(display_file, + "sending token data: %d of %d bytes written\n", + ret, (int)tok->length); + } + return -1; + } + + return 0; +} + +/* + * Function: recv_token + * + * Purpose: Reads a token from a file descriptor. + * + * Arguments: + * + * s (r) an open file descriptor + * flags (w) the read flags + * tok (w) the read token + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * recv_token reads the token flags (a single byte, even though + * they're stored into an integer, then reads the token length (as a + * network long), allocates memory to hold the data, and then reads + * the token data from the file descriptor s. It blocks to read the + * length and data, if necessary. On a successful return, the token + * should be freed with gss_release_buffer. It returns 0 on success, + * and -1 if an error occurs or if it could not read all the data. + */ +int +recv_token(int s, int *flags, gss_buffer_t tok) +{ + int ret; + unsigned char char_flags; + unsigned char lenbuf[4]; + + ret = read_all(s, (char *)&char_flags, 1); + if (ret < 0) { + perror("reading token flags"); + return -1; + } else if (!ret) { + if (display_file) + fputs("reading token flags: 0 bytes read\n", display_file); + return -1; + } else { + *flags = char_flags; + } + + if (char_flags == 0) { + lenbuf[0] = 0; + ret = read_all(s, (char *)&lenbuf[1], 3); + if (ret < 0) { + perror("reading token length"); + return -1; + } else if (ret != 3) { + if (display_file) { + fprintf(display_file, + "reading token length: %d of %d bytes read\n", ret, 3); + } + return -1; + } + } else { + ret = read_all(s, (char *)lenbuf, 4); + if (ret < 0) { + perror("reading token length"); + return -1; + } else if (ret != 4) { + if (display_file) { + fprintf(display_file, + "reading token length: %d of %d bytes read\n", ret, 4); + } + return -1; + } + } + + tok->length = load_32_be(lenbuf); + tok->value = malloc(tok->length ? tok->length : 1); + if (tok->length && tok->value == NULL) { + if (display_file) + fprintf(display_file, "Out of memory allocating token data\n"); + return -1; + } + + ret = read_all(s, (char *)tok->value, tok->length); + if (ret < 0) { + perror("reading token data"); + free(tok->value); + return -1; + } else if ((size_t)ret != tok->length) { + fprintf(stderr, "sending token data: %d of %d bytes written\n", + ret, (int)tok->length); + free(tok->value); + return -1; + } + + return 0; +} + +static void +display_status_1(char *m, OM_uint32 code, int type) +{ + OM_uint32 min_stat; + gss_buffer_desc msg; + OM_uint32 msg_ctx; + + msg_ctx = 0; + while (1) { + (void)gss_display_status(&min_stat, code, type, GSS_C_NULL_OID, + &msg_ctx, &msg); + if (display_file) { + fprintf(display_file, "GSS-API error %s: %s\n", m, + (char *)msg.value); + } + (void)gss_release_buffer(&min_stat, &msg); + + if (!msg_ctx) + break; + } +} + +/* + * Function: display_status + * + * Purpose: displays GSS-API messages + * + * Arguments: + * + * msg a string to be displayed with the message + * maj_stat the GSS-API major status code + * min_stat the GSS-API minor status code + * + * Effects: + * + * The GSS-API messages associated with maj_stat and min_stat are + * displayed on stderr, each preceded by "GSS-API error : " and + * followed by a newline. + */ +void +display_status(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat) +{ + display_status_1(msg, maj_stat, GSS_C_GSS_CODE); + display_status_1(msg, min_stat, GSS_C_MECH_CODE); +} + +/* + * Function: display_ctx_flags + * + * Purpose: displays the flags returned by context initiation in + * a human-readable form + * + * Arguments: + * + * int ret_flags + * + * Effects: + * + * Strings corresponding to the context flags are printed on + * stdout, preceded by "context flag: " and followed by a newline + */ + +void +display_ctx_flags(OM_uint32 flags) +{ + if (flags & GSS_C_DELEG_FLAG) + fprintf(display_file, "context flag: GSS_C_DELEG_FLAG\n"); + if (flags & GSS_C_MUTUAL_FLAG) + fprintf(display_file, "context flag: GSS_C_MUTUAL_FLAG\n"); + if (flags & GSS_C_REPLAY_FLAG) + fprintf(display_file, "context flag: GSS_C_REPLAY_FLAG\n"); + if (flags & GSS_C_SEQUENCE_FLAG) + fprintf(display_file, "context flag: GSS_C_SEQUENCE_FLAG\n"); + if (flags & GSS_C_CONF_FLAG) + fprintf(display_file, "context flag: GSS_C_CONF_FLAG \n"); + if (flags & GSS_C_INTEG_FLAG) + fprintf(display_file, "context flag: GSS_C_INTEG_FLAG \n"); +} + +void +print_token(gss_buffer_t tok) +{ + size_t i; + unsigned char *p = tok->value; + + if (!display_file) + return; + for (i = 0; i < tok->length; i++, p++) { + fprintf(display_file, "%02x ", *p); + if (i % 16 == 15) { + fprintf(display_file, "\n"); + } + } + fprintf(display_file, "\n"); + fflush(display_file); +} + +#ifdef _WIN32 +#include +#include + +int +gettimeofday(struct timeval *tv, void *ignore_tz) +{ + struct _timeb tb; + + _tzset(); + _ftime(&tb); + if (tv) { + tv->tv_sec = tb.time; + tv->tv_usec = tb.millitm * 1000; + } + return 0; +} + +#endif /* _WIN32 */ diff --git a/krb5-1.21.3/src/tests/gss-threads/gss-misc.h b/krb5-1.21.3/src/tests/gss-threads/gss-misc.h new file mode 100644 index 00000000..1ed8fb6c --- /dev/null +++ b/krb5-1.21.3/src/tests/gss-threads/gss-misc.h @@ -0,0 +1,51 @@ +/* + * Copyright 1994 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _GSSMISC_H_ +#define _GSSMISC_H_ + +#include +#include + +extern FILE *display_file; + +int send_token(int s, int flags, gss_buffer_t tok); +int recv_token(int s, int *flags, gss_buffer_t tok); +void display_status(char *msg, OM_uint32 maj_stat, OM_uint32 min_stat); +void display_ctx_flags(OM_uint32 flags); +void print_token(gss_buffer_t tok); + +/* Token types */ +#define TOKEN_NOOP (1<<0) +#define TOKEN_CONTEXT (1<<1) +#define TOKEN_DATA (1<<2) +#define TOKEN_MIC (1<<3) + +/* Token flags */ +#define TOKEN_CONTEXT_NEXT (1<<4) +#define TOKEN_WRAPPED (1<<5) +#define TOKEN_ENCRYPTED (1<<6) +#define TOKEN_SEND_MIC (1<<7) + +extern gss_buffer_t empty_token; + +#endif diff --git a/krb5-1.21.3/src/tests/gss-threads/gss-server.c b/krb5-1.21.3/src/tests/gss-threads/gss-server.c new file mode 100644 index 00000000..a9f980ed --- /dev/null +++ b/krb5-1.21.3/src/tests/gss-threads/gss-server.c @@ -0,0 +1,850 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1994 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (C) 2004,2008 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "autoconf.h" +#include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +#include +#include "gss-misc.h" +#include "port-sockets.h" + +#ifdef HAVE_STRING_H +#include +#else +#include +#endif + +static void +usage() +{ + fprintf(stderr, "Usage: gss-server [-port port] [-verbose] [-once]"); +#ifdef _WIN32 + fprintf(stderr, " [-threads num]"); +#endif + fprintf(stderr, "\n"); + fprintf(stderr, " [-inetd] [-export] [-logfile file] " + "service_name\n"); + exit(1); +} + +FILE *logfile; + +int verbose = 0; + +/* + * Function: server_acquire_creds + * + * Purpose: imports a service name and acquires credentials for it + * + * Arguments: + * + * service_name (r) the ASCII service name + * server_creds (w) the GSS-API service credentials + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * The service name is imported with gss_import_name, and service + * credentials are acquired with gss_acquire_cred. If either operation + * fails, an error message is displayed and -1 is returned; otherwise, + * 0 is returned. + */ +static int +server_acquire_creds(char *service_name, gss_cred_id_t *server_creds) +{ + gss_buffer_desc name_buf; + gss_name_t server_name; + OM_uint32 maj_stat, min_stat; + + name_buf.value = service_name; + name_buf.length = strlen(name_buf.value) + 1; + maj_stat = gss_import_name(&min_stat, &name_buf, + (gss_OID)gss_nt_service_name, &server_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("importing name", maj_stat, min_stat); + return -1; + } + + maj_stat = gss_acquire_cred(&min_stat, server_name, 0, + GSS_C_NULL_OID_SET, GSS_C_ACCEPT, + server_creds, NULL, NULL); + if (maj_stat != GSS_S_COMPLETE) { + display_status("acquiring credentials", maj_stat, min_stat); + return -1; + } + + (void)gss_release_name(&min_stat, &server_name); + + return 0; +} + +/* + * Function: server_establish_context + * + * Purpose: establishses a GSS-API context as a specified service with + * an incoming client, and returns the context handle and associated + * client name + * + * Arguments: + * + * s (r) an established TCP connection to the client + * service_creds (r) server credentials, from gss_acquire_cred + * context (w) the established GSS-API context + * client_name (w) the client's ASCII name + * + * Returns: 0 on success, -1 on failure + * + * Effects: + * + * Any valid client request is accepted. If a context is established, + * its handle is returned in context and the client name is returned + * in client_name and 0 is returned. If unsuccessful, an error + * message is displayed and -1 is returned. + */ +static int +server_establish_context(int s, gss_cred_id_t server_creds, + gss_ctx_id_t *context, gss_buffer_t client_name, + OM_uint32 *ret_flags) +{ + gss_buffer_desc send_tok, recv_tok, oid_name; + gss_name_t client; + gss_OID doid; + OM_uint32 maj_stat, min_stat, acc_sec_min_stat; + int token_flags; + + if (recv_token(s, &token_flags, &recv_tok) < 0) + return -1; + + if (recv_tok.value) { + free(recv_tok.value); + recv_tok.value = NULL; + } + + if (!(token_flags & TOKEN_NOOP)) { + if (logfile) { + fprintf(logfile, "Expected NOOP token, got %d token instead\n", + token_flags); + } + return -1; + } + + *context = GSS_C_NO_CONTEXT; + + if (token_flags & TOKEN_CONTEXT_NEXT) { + do { + if (recv_token(s, &token_flags, &recv_tok) < 0) + return -1; + + if (verbose && logfile) { + fprintf(logfile, "Received token (size=%d): \n", + (int)recv_tok.length); + print_token(&recv_tok); + } + + maj_stat = gss_accept_sec_context(&acc_sec_min_stat, context, + server_creds, &recv_tok, + GSS_C_NO_CHANNEL_BINDINGS, + &client, &doid, &send_tok, + ret_flags, NULL, NULL); + + if (recv_tok.value) { + free(recv_tok.value); + recv_tok.value = NULL; + } + + if (send_tok.length != 0) { + if (verbose && logfile) { + fprintf(logfile, + "Sending accept_sec_context token (size=%d):\n", + (int)send_tok.length); + print_token(&send_tok); + } + if (send_token(s, TOKEN_CONTEXT, &send_tok) < 0) { + if (logfile) + fprintf(logfile, "failure sending token\n"); + return -1; + } + + (void)gss_release_buffer(&min_stat, &send_tok); + } + if (maj_stat != GSS_S_COMPLETE && + maj_stat != GSS_S_CONTINUE_NEEDED) { + display_status("accepting context", maj_stat, + acc_sec_min_stat); + if (*context != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&min_stat, context, + GSS_C_NO_BUFFER); + } + return -1; + } + + if (verbose && logfile) { + if (maj_stat == GSS_S_CONTINUE_NEEDED) + fprintf(logfile, "continue needed...\n"); + else + fprintf(logfile, "\n"); + fflush(logfile); + } + } while (maj_stat == GSS_S_CONTINUE_NEEDED); + + /* display the flags */ + display_ctx_flags(*ret_flags); + + if (verbose && logfile) { + maj_stat = gss_oid_to_str(&min_stat, doid, &oid_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("converting oid->string", maj_stat, min_stat); + return -1; + } + fprintf(logfile, "Accepted connection using mechanism OID %.*s.\n", + (int)oid_name.length, (char *)oid_name.value); + (void)gss_release_buffer(&min_stat, &oid_name); + } + + maj_stat = gss_display_name(&min_stat, client, client_name, &doid); + if (maj_stat != GSS_S_COMPLETE) { + display_status("displaying name", maj_stat, min_stat); + return -1; + } + maj_stat = gss_release_name(&min_stat, &client); + if (maj_stat != GSS_S_COMPLETE) { + display_status("releasing name", maj_stat, min_stat); + return -1; + } + } else { + client_name->length = *ret_flags = 0; + + if (logfile) + fprintf(logfile, "Accepted unauthenticated connection.\n"); + } + + return 0; +} + +/* + * Function: create_socket + * + * Purpose: Opens a listening TCP socket. + * + * Arguments: + * + * port (r) the port number on which to listen + * + * Returns: the listening socket file descriptor, or -1 on failure + * + * Effects: + * + * A listening socket on the specified port and created and returned. + * On error, an error message is displayed and -1 is returned. + */ +static int +create_socket(u_short port) +{ + struct sockaddr_in saddr; + int s, on = 1; + + saddr.sin_family = AF_INET; + saddr.sin_port = htons(port); + saddr.sin_addr.s_addr = INADDR_ANY; + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) { + perror("creating socket"); + return -1; + } + /* Let the socket be reused right away. */ + (void)setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); + if (bind(s, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { + perror("binding socket"); + (void)close(s); + return -1; + } + if (listen(s, 5) < 0) { + perror("listening on socket"); + (void)close(s); + return -1; + } + return s; +} + +static float +timeval_subtract(struct timeval *tv1, struct timeval *tv2) +{ + return ((tv1->tv_sec - tv2->tv_sec) + + ((float)(tv1->tv_usec - tv2->tv_usec)) / 1000000); +} + +/* + * Yes, yes, this isn't the best place for doing this test. + * DO NOT REMOVE THIS UNTIL A BETTER TEST HAS BEEN WRITTEN, THOUGH. + * -TYT + */ +static int +test_import_export_context(gss_ctx_id_t *context) +{ + OM_uint32 min_stat, maj_stat; + gss_buffer_desc context_token, copied_token; + struct timeval tm1, tm2; + + /* Attempt to save and then restore the context. */ + gettimeofday(&tm1, (struct timezone *)0); + maj_stat = gss_export_sec_context(&min_stat, context, &context_token); + if (maj_stat != GSS_S_COMPLETE) { + display_status("exporting context", maj_stat, min_stat); + return 1; + } + gettimeofday(&tm2, NULL); + if (verbose && logfile) { + fprintf(logfile, "Exported context: %d bytes, %7.4f seconds\n", + (int)context_token.length, timeval_subtract(&tm2, &tm1)); + } + copied_token.length = context_token.length; + copied_token.value = malloc(context_token.length); + if (copied_token.value == 0) { + if (logfile) { + fprintf(logfile, "Couldn't allocate memory to copy context " + "token.\n"); + } + return 1; + } + memcpy(copied_token.value, context_token.value, copied_token.length); + maj_stat = gss_import_sec_context(&min_stat, &copied_token, context); + if (maj_stat != GSS_S_COMPLETE) { + display_status("importing context", maj_stat, min_stat); + return 1; + } + free(copied_token.value); + gettimeofday(&tm1, NULL); + if (verbose && logfile) { + fprintf(logfile, "Importing context: %7.4f seconds\n", + timeval_subtract(&tm1, &tm2)); + } + (void)gss_release_buffer(&min_stat, &context_token); + return 0; +} + +/* + * Function: sign_server + * + * Purpose: Performs the "sign" service. + * + * Arguments: + * + * s (r) a TCP socket on which a connection has been + * accept()ed + * service_name (r) the ASCII name of the GSS-API service to + * establish a context as + * export (r) whether to test context exporting + * + * Returns: -1 on error + * + * Effects: + * + * sign_server establishes a context, and performs a single sign request. + * + * A sign request is a single GSS-API sealed token. The token is + * unsealed and a signature block, produced with gss_sign, is returned + * to the sender. The context is the destroyed and the connection + * closed. + * + * If any error occurs, -1 is returned. + */ +static int +sign_server(int s, gss_cred_id_t server_creds, int export) +{ + gss_buffer_desc client_name, xmit_buf, msg_buf; + gss_ctx_id_t context; + OM_uint32 maj_stat, min_stat, ret_flags; + int i, conf_state, token_flags; + char *cp; + + /* Establish a context with the client */ + if (server_establish_context(s, server_creds, &context, &client_name, + &ret_flags) < 0) + return -1; + + if (context == GSS_C_NO_CONTEXT) { + printf("Accepted unauthenticated connection.\n"); + } else { + printf("Accepted connection: \"%.*s\"\n", (int)client_name.length, + (char *)client_name.value); + (void)gss_release_buffer(&min_stat, &client_name); + + if (export) { + for (i = 0; i < 3; i++) { + if (test_import_export_context(&context)) + return -1; + } + } + } + + do { + /* Receive the message token */ + if (recv_token(s, &token_flags, &xmit_buf) < 0) + return -1; + + if (token_flags & TOKEN_NOOP) { + if (logfile) + fprintf(logfile, "NOOP token\n"); + if (xmit_buf.value) { + free(xmit_buf.value); + xmit_buf.value = 0; + } + break; + } + + if (verbose && logfile) { + fprintf(logfile, "Message token (flags=%d):\n", token_flags); + print_token(&xmit_buf); + } + + if (context == GSS_C_NO_CONTEXT && + (token_flags & + (TOKEN_WRAPPED | TOKEN_ENCRYPTED | TOKEN_SEND_MIC))) { + if (logfile) { + fprintf(logfile, "Unauthenticated client requested " + "authenticated services!\n"); + } + if (xmit_buf.value) { + free(xmit_buf.value); + xmit_buf.value = 0; + } + return -1; + } + + if (token_flags & TOKEN_WRAPPED) { + maj_stat = gss_unwrap(&min_stat, context, &xmit_buf, &msg_buf, + &conf_state, NULL); + if (maj_stat != GSS_S_COMPLETE) { + display_status("unsealing message", maj_stat, min_stat); + if (xmit_buf.value) { + free(xmit_buf.value); + xmit_buf.value = 0; + } + return -1; + } else if (!conf_state && (token_flags & TOKEN_ENCRYPTED)) { + fprintf(stderr, "Warning! Message not encrypted.\n"); + } + + if (xmit_buf.value) { + free(xmit_buf.value); + xmit_buf.value = 0; + } + } else { + msg_buf = xmit_buf; + } + + if (logfile) { + fprintf(logfile, "Received message: "); + cp = msg_buf.value; + if (isprint((unsigned char)cp[0]) && + isprint((unsigned char)cp[1])) { + fprintf(logfile, "\"%.*s\"\n", (int)msg_buf.length, + (char *)msg_buf.value); + } else { + fprintf(logfile, "\n"); + print_token(&msg_buf); + } + } + + if (token_flags & TOKEN_SEND_MIC) { + /* Produce a signature block for the message. */ + maj_stat = gss_get_mic(&min_stat, context, GSS_C_QOP_DEFAULT, + &msg_buf, &xmit_buf); + if (maj_stat != GSS_S_COMPLETE) { + display_status("signing message", maj_stat, min_stat); + return -1; + } + + if (msg_buf.value) { + free(msg_buf.value); + msg_buf.value = 0; + } + + /* Send the signature block to the client. */ + if (send_token(s, TOKEN_MIC, &xmit_buf) < 0) + return -1; + + if (xmit_buf.value) { + free(xmit_buf.value); + xmit_buf.value = 0; + } + } else { + if (msg_buf.value) { + free(msg_buf.value); + msg_buf.value = 0; + } + if (send_token(s, TOKEN_NOOP, empty_token) < 0) + return -1; + } + } while (1 /* loop will break if NOOP received */); + + if (context != GSS_C_NO_CONTEXT) { + /* Delete context. */ + maj_stat = gss_delete_sec_context(&min_stat, &context, NULL); + if (maj_stat != GSS_S_COMPLETE) { + display_status("deleting context", maj_stat, min_stat); + return -1; + } + } + + if (logfile) + fflush(logfile); + + return 0; +} + +static int max_threads = 1; + +#ifdef _WIN32 +static thread_count = 0; +static HANDLE hMutex = NULL; +static HANDLE hEvent = NULL; + +void +init_handles(void) +{ + hMutex = CreateMutex(NULL, FALSE, NULL); + hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); +} + +void +cleanup_handles(void) +{ + CloseHandle(hMutex); + CloseHandle(hEvent); +} + +BOOL +wait_and_increment_thread_counter(void) +{ + for (;;) { + if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) { + if (thread_count < max_threads) { + thread_count++; + ReleaseMutex(hMutex); + return TRUE; + } else { + ReleaseMutex(hMutex); + + if (WaitForSingleObject(hEvent, INFINITE) == WAIT_OBJECT_0) + continue; + else + return FALSE; + } + } else { + return FALSE; + } + } +} + +BOOL +decrement_and_signal_thread_counter(void) +{ + if (WaitForSingleObject(hMutex, INFINITE) == WAIT_OBJECT_0) { + if (thread_count == max_threads) + SetEvent(hEvent); + thread_count--; + ReleaseMutex(hMutex); + return TRUE; + } else { + return FALSE; + } +} + +#else /* assume pthread */ + +static pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t counter_cond = PTHREAD_COND_INITIALIZER; +int counter = 0; + +static int +wait_and_increment_thread_counter(void) +{ + int err; + + err = pthread_mutex_lock(&counter_mutex); + if (err) { + perror("pthread_mutex_lock"); + return 0; + } + if (counter == max_threads) { + err = pthread_cond_wait(&counter_cond, &counter_mutex); + if (err) { + pthread_mutex_unlock(&counter_mutex); + perror("pthread_cond_wait"); + return 0; + } + } + counter++; + pthread_mutex_unlock(&counter_mutex); + return 1; +} + +static void +decrement_and_signal_thread_counter(void) +{ + int err; + + err = pthread_mutex_lock(&counter_mutex); + if (err) { + perror("pthread_mutex_lock"); + return; + } + if (counter == max_threads) + pthread_cond_broadcast(&counter_cond); + counter--; + pthread_mutex_unlock(&counter_mutex); +} + +#endif + +struct _work_plan { + int s; + gss_cred_id_t server_creds; + int export; +}; + +static void * +worker_bee(void *param) +{ + struct _work_plan *work = param; + + /* This return value is not checked, because there's not really anything to + * do if it fails. */ + sign_server(work->s, work->server_creds, work->export); + closesocket(work->s); + free(work); + +#if defined _WIN32 || 1 + if (max_threads > 1) + decrement_and_signal_thread_counter(); +#endif + return NULL; +} + +int +main(int argc, char **argv) +{ + char *service_name; + gss_cred_id_t server_creds; + OM_uint32 min_stat; + u_short port = 4444; + int once = 0; + int do_inetd = 0; + int export = 0; + + signal(SIGPIPE, SIG_IGN); + logfile = stdout; + display_file = stdout; + argc--; + argv++; + while (argc) { + if (strcmp(*argv, "-port") == 0) { + argc--; + argv++; + if (!argc) + usage(); + port = atoi(*argv); + } else if (strcmp(*argv, "-threads") == 0) { + argc--; + argv++; + if (!argc) + usage(); + max_threads = atoi(*argv); + } else if (strcmp(*argv, "-verbose") == 0) { + verbose = 1; + } else if (strcmp(*argv, "-once") == 0) { + once = 1; + } else if (strcmp(*argv, "-inetd") == 0) { + do_inetd = 1; + } else if (strcmp(*argv, "-export") == 0) { + export = 1; + } else if (strcmp(*argv, "-logfile") == 0) { + argc--; + argv++; + if (!argc) + usage(); + /* + * Gross hack, but it makes it unnecessary to add an extra argument + * to disable logging, and makes the code more efficient because it + * doesn't actually write data to /dev/null. + */ + if (!strcmp(*argv, "/dev/null")) { + logfile = display_file = NULL; + } else { + logfile = fopen(*argv, "a"); + display_file = logfile; + if (!logfile) { + perror(*argv); + exit(1); + } + } + } else { + break; + } + argc--; + argv++; + } + if (argc != 1) + usage(); + + if ((*argv)[0] == '-') + usage(); + +#ifdef _WIN32 + if (max_threads < 1) { + fprintf(stderr, "warning: there must be at least one thread\n"); + max_threads = 1; + } + + if (max_threads > 1 && do_inetd) { + fprintf(stderr, "warning: one thread may be used in conjunction " + "with inetd\n"); + } + + init_handles(); +#endif + + service_name = *argv; + + if (server_acquire_creds(service_name, &server_creds) < 0) + return -1; + + if (do_inetd) { + close(1); + close(2); + + sign_server(0, server_creds, export); + close(0); + } else { + int stmp; + + stmp = create_socket(port); + if (stmp >= 0) { + do { + struct _work_plan * work = malloc(sizeof(struct _work_plan)); + + if (work == NULL) { + fprintf(stderr, "fatal error: out of memory"); + break; + } + + /* Accept a TCP connection */ + work->s = accept(stmp, NULL, 0); + if (work->s < 0) { + perror("accepting connection"); + continue; + } + + work->server_creds = server_creds; + work->export = export; + + if (max_threads == 1) { + worker_bee(work); + } else { + if (wait_and_increment_thread_counter()) { +#ifdef _WIN32 + uintptr_t handle = _beginthread(worker_bee, 0, work); + if (handle == (uintptr_t)-1) { + closesocket(work->s); + free(work); + } +#else + int err; + pthread_t thr; + err = pthread_create(&thr, 0, worker_bee, work); + if (err) { + perror("pthread_create"); + closesocket(work->s); + free(work); + } + (void)pthread_detach(thr); +#endif + } else { + fprintf(stderr, "fatal error incrementing thread " + "counter"); + closesocket(work->s); + free(work); + break; + } + } + } while (!once); + + closesocket(stmp); + } + } + + (void)gss_release_cred(&min_stat, &server_creds); + +#ifdef _WIN32 + cleanup_handles(); +#else + if (max_threads > 1) { + while (1) + sleep(999999); + } +#endif + + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/Makefile.in b/krb5-1.21.3/src/tests/gssapi/Makefile.in new file mode 100644 index 00000000..33047c35 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/Makefile.in @@ -0,0 +1,138 @@ +mydir=tests$(S)gssapi +BUILDTOP=$(REL)..$(S).. +DEFINES = -DUSE_AUTOCONF_H + +# For t_prf.c +LOCALINCLUDES = -I$(srcdir)/../../lib/gssapi/mechglue \ + -I$(srcdir)/../../lib/gssapi/krb5 \ + -I$(srcdir)/../../lib/gssapi/generic -I../../lib/gssapi/krb5 \ + -I../../lib/gssapi/generic + +SRCS= $(srcdir)/ccinit.c $(srcdir)/ccrefresh.c $(srcdir)/common.c \ + $(srcdir)/reload.c $(srcdir)/t_accname.c $(srcdir)/t_add_cred.c \ + $(srcdir)/t_bindings.c $(srcdir)/t_ccselect.c $(srcdir)/t_ciflags.c \ + $(srcdir)/t_context.c $(srcdir)/t_credstore.c $(srcdir)/t_enctypes.c \ + $(srcdir)/t_err.c $(srcdir)/t_export_cred.c $(srcdir)/t_export_name.c \ + $(srcdir)/t_gssexts.c $(srcdir)/t_imp_cred.c $(srcdir)/t_imp_name.c \ + $(srcdir)/t_invalid.c $(srcdir)/t_inq_cred.c $(srcdir)/t_inq_ctx.c \ + $(srcdir)/t_inq_mechs_name.c $(srcdir)/t_iov.c \ + $(srcdir)/t_lifetime.c $(srcdir)/t_namingexts.c $(srcdir)/t_oid.c \ + $(srcdir)/t_pcontok.c $(srcdir)/t_prf.c $(srcdir)/t_s4u.c \ + $(srcdir)/t_s4u2proxy_krb5.c $(srcdir)/t_saslname.c \ + $(srcdir)/t_spnego.c $(srcdir)/t_srcattrs.c $(srcdir)/t_store_cred.c + +OBJS= ccinit.o ccrefresh.o common.o reload.o t_accname.o t_add_cred.o \ + t_bindings.o t_ccselect.o t_ciflags.o t_context.o t_credstore.o \ + t_enctypes.o t_err.o t_export_cred.o t_export_name.o t_gssexts.o \ + t_imp_cred.o t_imp_name.o t_invalid.o t_inq_cred.o t_inq_ctx.o \ + t_inq_mechs_name.o t_iov.o t_lifetime.o t_namingexts.o t_oid.o \ + t_pcontok.o t_prf.o t_s4u.o t_s4u2proxy_krb5.o t_saslname.o \ + t_spnego.o t_srcattrs.o t_store_cred.o + +COMMON_DEPS= common.o $(GSS_DEPLIBS) $(KRB5_BASE_DEPLIBS) +COMMON_LIBS= common.o $(GSS_LIBS) $(KRB5_BASE_LIBS) + +all: ccinit ccrefresh t_accname t_add_cred t_bindings t_ccselect t_ciflags \ + t_context t_credstore t_enctypes t_err t_export_cred t_export_name \ + t_gssexts t_imp_cred t_imp_name t_invalid t_inq_cred t_inq_ctx \ + t_inq_mechs_name t_iov t_lifetime t_namingexts t_oid t_pcontok t_prf \ + t_s4u t_s4u2proxy_krb5 t_saslname t_spnego t_srcattrs t_store_cred + +check-unix: t_oid reload + $(RUN_TEST) ./t_invalid + $(RUN_TEST) ./t_oid + $(RUN_TEST) ./t_prf + $(RUN_TEST) ./t_imp_name + if [ -r $(TOPLIBD)/libgssapi_krb5.so ]; then $(RUN_TEST) ./reload; fi + +check-pytests: ccinit ccrefresh t_accname t_add_cred t_bindings t_ccselect \ + t_ciflags t_context t_credstore t_enctypes t_err t_export_cred \ + t_export_name t_imp_cred t_inq_cred t_inq_ctx t_inq_mechs_name t_iov \ + t_lifetime t_pcontok t_s4u t_s4u2proxy_krb5 t_spnego t_srcattrs \ + t_store_cred + $(RUNPYTEST) $(srcdir)/t_gssapi.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_store_cred.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_credstore.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_bindings.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_ccselect.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_client_keytab.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_enctypes.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_export_cred.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_s4u.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_authind.py $(PYTESTFLAGS) + $(RUNPYTEST) $(srcdir)/t_negoex.py $(PYTESTFLAGS) + +ccinit: ccinit.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o ccinit ccinit.o $(KRB5_BASE_LIBS) +ccrefresh: ccrefresh.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o ccrefresh ccrefresh.o $(KRB5_BASE_LIBS) +reload: reload.o + $(CC_LINK) -o $@ reload.o $(LIBS) $(DL_LIB) +t_accname: t_accname.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_accname.o $(COMMON_LIBS) +t_add_cred: t_add_cred.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_add_cred.o $(COMMON_LIBS) +t_bindings: t_bindings.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_bindings.o $(COMMON_LIBS) +t_ccselect: t_ccselect.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_ccselect.o $(COMMON_LIBS) +t_ciflags: t_ciflags.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_ciflags.o $(COMMON_LIBS) +t_context: t_context.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_context.o $(COMMON_LIBS) +t_credstore: t_credstore.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_credstore.o $(COMMON_LIBS) +t_enctypes: t_enctypes.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_enctypes.o $(COMMON_LIBS) +t_err: t_err.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_err.o $(COMMON_LIBS) +t_export_cred: t_export_cred.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_export_cred.o $(COMMON_LIBS) +t_export_name: t_export_name.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_export_name.o $(COMMON_LIBS) +t_gssexts: t_gssexts.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_gssexts.o $(COMMON_LIBS) +t_imp_cred: t_imp_cred.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_imp_cred.o $(COMMON_LIBS) +t_imp_name: t_imp_name.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_imp_name.o $(COMMON_LIBS) +t_invalid: t_invalid.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_invalid.o $(COMMON_LIBS) +t_inq_cred: t_inq_cred.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_inq_cred.o $(COMMON_LIBS) +t_inq_ctx: t_inq_ctx.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_inq_ctx.o $(COMMON_LIBS) +t_inq_mechs_name: t_inq_mechs_name.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_inq_mechs_name.o $(COMMON_LIBS) +t_iov: t_iov.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_iov.o $(COMMON_LIBS) +t_lifetime: t_lifetime.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_lifetime.o $(COMMON_LIBS) +t_namingexts: t_namingexts.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_namingexts.o $(COMMON_LIBS) +t_pcontok: t_pcontok.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_pcontok.o $(COMMON_LIBS) +t_oid: t_oid.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_oid.o $(COMMON_LIBS) +t_prf: t_prf.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_prf.o $(COMMON_LIBS) +t_s4u: t_s4u.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_s4u.o $(COMMON_LIBS) +t_s4u2proxy_krb5: t_s4u2proxy_krb5.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_s4u2proxy_krb5.o $(COMMON_LIBS) +t_saslname: t_saslname.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_saslname.o $(COMMON_LIBS) +t_spnego: t_spnego.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_spnego.o $(COMMON_LIBS) +t_srcattrs: t_srcattrs.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_srcattrs.o $(COMMON_LIBS) +t_store_cred: t_store_cred.o $(COMMON_DEPS) + $(CC_LINK) -o $@ t_store_cred.o $(COMMON_LIBS) + +clean: + $(RM) ccinit ccrefresh reload t_accname t_add_cred t_bindings + $(RM) t_ccselect t_ciflags t_context t_credstore t_enctypes t_err + $(RM) t_export_cred t_export_name t_gssexts t_imp_cred t_imp_name + $(RM) t_invalid t_inq_cred t_inq_ctx t_inq_mechs_name t_iov t_lifetime + $(RM) t_namingexts t_oid t_pcontok t_prf t_s4u t_s4u2proxy_krb5 + $(RM) t_saslname t_spnego t_srcattrs t_store_cred diff --git a/krb5-1.21.3/src/tests/gssapi/ccinit.c b/krb5-1.21.3/src/tests/gssapi/ccinit.c new file mode 100644 index 00000000..b06f0440 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/ccinit.c @@ -0,0 +1,72 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/ccinit.c - Initialize an empty ccache */ +/* + * Copyright (C) 2012 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. + */ + +/* + * This program initializes a ccache without attempting to get credentials in + * it. It is used to test some finer points of gss_acquire_cred behavior. + */ + +#include "k5-int.h" + +static void +check(krb5_error_code code) +{ + if (code != 0) { + com_err("ccinit", code, NULL); + abort(); + } +} + +int +main(int argc, char **argv) +{ + const char *ccname, *princname; + krb5_context context; + krb5_principal princ; + krb5_ccache ccache; + + if (argc != 3) { + fprintf(stderr, "Usage: %s ccname princname\n", argv[0]); + return 1; + } + ccname = argv[1]; + princname = argv[2]; + + check(krb5_init_context(&context)); + check(krb5_parse_name(context, princname, &princ)); + check(krb5_cc_resolve(context, ccname, &ccache)); + check(krb5_cc_initialize(context, ccache, princ)); + krb5_cc_close(context, ccache); + krb5_free_principal(context, princ); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/ccrefresh.c b/krb5-1.21.3/src/tests/gssapi/ccrefresh.c new file mode 100644 index 00000000..e1f04ed2 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/ccrefresh.c @@ -0,0 +1,80 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/ccrefresh.c - Get or set refresh time on a ccache */ +/* + * Copyright (C) 2012 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. + */ + +/* + * This program sets the refresh time of an existing ccache to 1, forcing a + * refresh. + */ + +#include "k5-int.h" + +static void +check(krb5_error_code code) +{ + if (code != 0) { + com_err("ccrefresh", code, NULL); + abort(); + } +} + +int +main(int argc, char **argv) +{ + const char *ccname, *value = NULL; + krb5_context context; + krb5_ccache ccache; + krb5_data d; + + if (argc != 2 && argc != 3) { + fprintf(stderr, "Usage: %s ccname [value]\n", argv[0]); + return 1; + } + ccname = argv[1]; + if (argc == 3) + value = argv[2]; + + check(krb5_init_context(&context)); + check(krb5_cc_resolve(context, ccname, &ccache)); + if (value != NULL) { + d = string2data((char *)value); + check(krb5_cc_set_config(context, ccache, NULL, + KRB5_CC_CONF_REFRESH_TIME, &d)); + } else { + check(krb5_cc_get_config(context, ccache, NULL, + KRB5_CC_CONF_REFRESH_TIME, &d)); + printf("%.*s\n", (int)d.length, d.data); + krb5_free_data_contents(context, &d); + } + krb5_cc_close(context, ccache); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/common.c b/krb5-1.21.3/src/tests/gssapi/common.c new file mode 100644 index 00000000..34f34f7a --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/common.c @@ -0,0 +1,282 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/common.c - Common utility functions for GSSAPI test programs */ +/* + * Copyright (C) 2012 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. + */ + +#include +#include +#include "common.h" + +gss_OID_desc mech_krb5 = { 9, "\052\206\110\206\367\022\001\002\002" }; +gss_OID_desc mech_spnego = { 6, "\053\006\001\005\005\002" }; +gss_OID_desc mech_iakerb = { 6, "\053\006\001\005\002\005" }; +gss_OID_set_desc mechset_krb5 = { 1, &mech_krb5 }; +gss_OID_set_desc mechset_spnego = { 1, &mech_spnego }; +gss_OID_set_desc mechset_iakerb = { 1, &mech_iakerb }; + +static void +display_status(const char *msg, OM_uint32 code, int type) +{ + OM_uint32 min_stat, msg_ctx = 0; + gss_buffer_desc buf; + + do { + (void)gss_display_status(&min_stat, code, type, GSS_C_NULL_OID, + &msg_ctx, &buf); + fprintf(stderr, "%s: %.*s\n", msg, (int)buf.length, (char *)buf.value); + (void)gss_release_buffer(&min_stat, &buf); + } while (msg_ctx != 0); +} + +void +check_gsserr(const char *msg, OM_uint32 major, OM_uint32 minor) +{ + if (GSS_ERROR(major)) { + display_status(msg, major, GSS_C_GSS_CODE); + display_status(msg, minor, GSS_C_MECH_CODE); + exit(1); + } +} + +void +check_k5err(krb5_context context, const char *msg, krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(context, code); + printf("%s: %s\n", msg, errmsg); + krb5_free_error_message(context, errmsg); + exit(1); + } +} + +void +errout(const char *msg) +{ + fprintf(stderr, "%s\n", msg); + exit(1); +} + +gss_name_t +import_name(const char *str) +{ + OM_uint32 major, minor; + gss_name_t name; + gss_buffer_desc buf; + gss_OID nametype = NULL; + + if (*str == 'u') + nametype = GSS_C_NT_USER_NAME; + else if (*str == 'p') + nametype = (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME; + else if (*str == 'e') + nametype = (gss_OID)GSS_KRB5_NT_ENTERPRISE_NAME; + else if (*str == 'c') + nametype = (gss_OID)GSS_KRB5_NT_X509_CERT; + else if (*str == 'h') + nametype = GSS_C_NT_HOSTBASED_SERVICE; + if (nametype == NULL || str[1] != ':') + errout("names must begin with u: or p: or e: or c: or h:"); + buf.value = (char *)str + 2; + buf.length = strlen(str) - 2; + major = gss_import_name(&minor, &buf, nametype, &name); + check_gsserr("gss_import_name", major, minor); + return name; +} + +void +establish_contexts(gss_OID imech, gss_cred_id_t icred, gss_cred_id_t acred, + gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ictx, + gss_ctx_id_t *actx, gss_name_t *src_name, gss_OID *amech, + gss_cred_id_t *deleg_cred) +{ + establish_contexts_ex(imech, icred, acred, tname, flags, ictx, actx, + GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_CHANNEL_BINDINGS, + NULL, src_name, amech, deleg_cred); +} + +void +establish_contexts_ex(gss_OID imech, gss_cred_id_t icred, gss_cred_id_t acred, + gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ictx, + gss_ctx_id_t *actx, gss_channel_bindings_t icb, + gss_channel_bindings_t acb, OM_uint32 *aret_flags, + gss_name_t *src_name, gss_OID *amech, + gss_cred_id_t *deleg_cred) +{ + OM_uint32 minor, imaj, amaj; + gss_buffer_desc itok, atok; + + *ictx = *actx = GSS_C_NO_CONTEXT; + imaj = amaj = GSS_S_CONTINUE_NEEDED; + itok.value = atok.value = NULL; + itok.length = atok.length = 0; + for (;;) { + (void)gss_release_buffer(&minor, &itok); + imaj = gss_init_sec_context(&minor, icred, ictx, tname, imech, flags, + GSS_C_INDEFINITE, icb, &atok, NULL, &itok, + NULL, NULL); + check_gsserr("gss_init_sec_context", imaj, minor); + if (amaj == GSS_S_COMPLETE) + break; + + (void)gss_release_buffer(&minor, &atok); + amaj = gss_accept_sec_context(&minor, actx, acred, &itok, acb, + src_name, amech, &atok, aret_flags, NULL, + deleg_cred); + check_gsserr("gss_accept_sec_context", amaj, minor); + (void)gss_release_buffer(&minor, &itok); + if (imaj == GSS_S_COMPLETE) + break; + } + + if (imaj != GSS_S_COMPLETE || amaj != GSS_S_COMPLETE) + errout("One side wants to continue after the other is done"); + + (void)gss_release_buffer(&minor, &itok); + (void)gss_release_buffer(&minor, &atok); +} + +void +export_import_cred(gss_cred_id_t *cred) +{ + OM_uint32 major, minor; + gss_buffer_desc buf; + + major = gss_export_cred(&minor, *cred, &buf); + check_gsserr("gss_export_cred", major, minor); + (void)gss_release_cred(&minor, cred); + major = gss_import_cred(&minor, &buf, cred); + check_gsserr("gss_import_cred", major, minor); + (void)gss_release_buffer(&minor, &buf); +} + +void +display_canon_name(const char *tag, gss_name_t name, gss_OID mech) +{ + gss_name_t canon; + OM_uint32 major, minor; + gss_buffer_desc buf; + + major = gss_canonicalize_name(&minor, name, mech, &canon); + check_gsserr("gss_canonicalize_name", major, minor); + + major = gss_display_name(&minor, canon, &buf, NULL); + check_gsserr("gss_display_name", major, minor); + + printf("%s:\t%.*s\n", tag, (int)buf.length, (char *)buf.value); + + (void)gss_release_name(&minor, &canon); + (void)gss_release_buffer(&minor, &buf); +} + +void +display_oid(const char *tag, gss_OID oid) +{ + OM_uint32 major, minor; + gss_buffer_desc buf; + + major = gss_oid_to_str(&minor, oid, &buf); + check_gsserr("gss_oid_to_str", major, minor); + if (tag != NULL) + printf("%s:\t", tag); + printf("%.*s\n", (int)buf.length, (char *)buf.value); + (void)gss_release_buffer(&minor, &buf); +} + +static void +dump_attribute(gss_name_t name, gss_buffer_t attribute, int noisy) +{ + OM_uint32 major, minor; + gss_buffer_desc value; + gss_buffer_desc display_value; + int authenticated = 0; + int complete = 0; + int more = -1; + unsigned int i; + + while (more != 0) { + value.value = NULL; + display_value.value = NULL; + + major = gss_get_name_attribute(&minor, name, attribute, &authenticated, + &complete, &value, &display_value, + &more); + check_gsserr("gss_get_name_attribute", major, minor); + + printf("Attribute %.*s %s %s\n\n%.*s\n", + (int)attribute->length, (char *)attribute->value, + authenticated ? "Authenticated" : "", + complete ? "Complete" : "", + (int)display_value.length, (char *)display_value.value); + + if (noisy) { + for (i = 0; i < value.length; i++) { + if ((i % 32) == 0) + printf("\n"); + printf("%02x", ((char *)value.value)[i] & 0xFF); + } + printf("\n\n"); + } + + (void)gss_release_buffer(&minor, &value); + (void)gss_release_buffer(&minor, &display_value); + } +} + +void +enumerate_attributes(gss_name_t name, int noisy) +{ + OM_uint32 major, minor; + int is_mechname; + gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET; + size_t i; + + major = gss_inquire_name(&minor, name, &is_mechname, NULL, &attrs); + check_gsserr("gss_inquire_name", major, minor); + + if (attrs != GSS_C_NO_BUFFER_SET) { + for (i = 0; i < attrs->count; i++) + dump_attribute(name, &attrs->elements[i], noisy); + } + + (void)gss_release_buffer_set(&minor, &attrs); +} + +void +print_hex(FILE *fp, gss_buffer_t buf) +{ + size_t i; + const unsigned char *bytes = buf->value; + + for (i = 0; i < buf->length; i++) + printf("%02X", bytes[i]); + printf("\n"); +} diff --git a/krb5-1.21.3/src/tests/gssapi/common.h b/krb5-1.21.3/src/tests/gssapi/common.h new file mode 100644 index 00000000..a5c8f87e --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/common.h @@ -0,0 +1,90 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/common.h - Declarations for GSSAPI test utility functions */ +/* + * Copyright (C) 2012 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. + */ + +#ifndef COMMON_H +#define COMMON_H + +#include + +extern gss_OID_desc mech_krb5; +extern gss_OID_desc mech_spnego; +extern gss_OID_desc mech_iakerb; +extern gss_OID_set_desc mechset_krb5; +extern gss_OID_set_desc mechset_spnego; +extern gss_OID_set_desc mechset_iakerb; + +/* Display an error message (containing msg) and exit if major is an error. */ +void check_gsserr(const char *msg, OM_uint32 major, OM_uint32 minor); + +/* Display an error message (containing msg) and exit if code is an error. */ +void check_k5err(krb5_context context, const char *msg, krb5_error_code code); + +/* Display an error message containing msg and exit. */ +void errout(const char *msg); + +/* Import a GSSAPI name based on a string of the form 'u:username', + * 'p:principalname', or 'h:host@service' (or just 'h:service'). */ +gss_name_t import_name(const char *str); + +/* Establish contexts using gss_init_sec_context and gss_accept_sec_context. */ +void establish_contexts(gss_OID imech, gss_cred_id_t icred, + gss_cred_id_t acred, gss_name_t tname, OM_uint32 flags, + gss_ctx_id_t *ictx, gss_ctx_id_t *actx, + gss_name_t *src_name, gss_OID *amech, + gss_cred_id_t *deleg_cred); + +/* Establish contexts with channel bindings. */ +void establish_contexts_ex(gss_OID imech, gss_cred_id_t icred, + gss_cred_id_t acred, gss_name_t tname, + OM_uint32 flags, gss_ctx_id_t *ictx, + gss_ctx_id_t *actx, gss_channel_bindings_t icb, + gss_channel_bindings_t acb, OM_uint32 *aret_flags, + gss_name_t *src_name, gss_OID *amech, + gss_cred_id_t *deleg_cred); + +/* Export *cred to a token, then release *cred and replace it by re-importing + * the token. */ +void export_import_cred(gss_cred_id_t *cred); + +/* Display name as canonicalized to mech, preceded by tag. */ +void display_canon_name(const char *tag, gss_name_t name, gss_OID mech); + +/* Display oid in printable form, preceded by tag (if not NULL). */ +void display_oid(const char *tag, gss_OID oid); + +/* Display attributes of name, including hex value if noisy is true. */ +void enumerate_attributes(gss_name_t name, int noisy); + +/* Display the contents of buf to fp in hex, followed by a newline. */ +void print_hex(FILE *fp, gss_buffer_t buf); + +#endif /* COMMON_H */ diff --git a/krb5-1.21.3/src/tests/gssapi/deps b/krb5-1.21.3/src/tests/gssapi/deps new file mode 100644 index 00000000..67742f20 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/deps @@ -0,0 +1,198 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)ccinit.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h ccinit.c +$(OUTPRE)ccrefresh.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h ccrefresh.c +$(OUTPRE)common.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.c common.h +$(OUTPRE)reload.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + reload.c +$(OUTPRE)t_accname.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_accname.c +$(OUTPRE)t_add_cred.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_add_cred.c +$(OUTPRE)t_bindings.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_bindings.c +$(OUTPRE)t_ccselect.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_ccselect.c +$(OUTPRE)t_ciflags.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_ciflags.c +$(OUTPRE)t_context.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_context.c +$(OUTPRE)t_credstore.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_credstore.c +$(OUTPRE)t_enctypes.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(srcdir)/../../lib/gssapi/generic/gssapi_ext.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + common.h t_enctypes.c +$(OUTPRE)t_err.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_err.c +$(OUTPRE)t_export_cred.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_export_cred.c +$(OUTPRE)t_export_name.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_export_name.c +$(OUTPRE)t_gssexts.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_gssexts.c +$(OUTPRE)t_imp_cred.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ + common.h t_imp_cred.c +$(OUTPRE)t_imp_name.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_imp_name.c +$(OUTPRE)t_invalid.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(BUILDTOP)/lib/gssapi/generic/gssapi_err_generic.h \ + $(BUILDTOP)/lib/gssapi/krb5/gssapi_err_krb5.h $(COM_ERR_DEPS) \ + $(srcdir)/../../lib/gssapi/generic/gssapiP_generic.h \ + $(srcdir)/../../lib/gssapi/generic/gssapi_ext.h $(srcdir)/../../lib/gssapi/generic/gssapi_generic.h \ + $(srcdir)/../../lib/gssapi/krb5/gssapiP_krb5.h $(srcdir)/../../lib/gssapi/krb5/gssapi_krb5.h \ + $(srcdir)/../../lib/gssapi/mechglue/mechglue.h $(srcdir)/../../lib/gssapi/mechglue/mglueP.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + common.h t_invalid.c +$(OUTPRE)t_inq_cred.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_inq_cred.c +$(OUTPRE)t_inq_ctx.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_inq_ctx.c +$(OUTPRE)t_inq_mechs_name.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_inq_mechs_name.c +$(OUTPRE)t_iov.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_iov.c +$(OUTPRE)t_lifetime.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_lifetime.c +$(OUTPRE)t_namingexts.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_namingexts.c +$(OUTPRE)t_oid.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_oid.c +$(OUTPRE)t_pcontok.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \ + $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \ + common.h t_pcontok.c +$(OUTPRE)t_prf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_alloc.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(BUILDTOP)/lib/gssapi/generic/gssapi_err_generic.h \ + $(BUILDTOP)/lib/gssapi/krb5/gssapi_err_krb5.h $(COM_ERR_DEPS) \ + $(srcdir)/../../lib/gssapi/generic/gssapiP_generic.h \ + $(srcdir)/../../lib/gssapi/generic/gssapi_ext.h $(srcdir)/../../lib/gssapi/generic/gssapi_generic.h \ + $(srcdir)/../../lib/gssapi/krb5/gssapiP_krb5.h $(srcdir)/../../lib/gssapi/krb5/gssapi_krb5.h \ + $(srcdir)/../../lib/gssapi/mechglue/mechglue.h $(srcdir)/../../lib/gssapi/mechglue/mglueP.h \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-hex.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h common.h t_prf.c +$(OUTPRE)t_s4u.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_s4u.c +$(OUTPRE)t_s4u2proxy_krb5.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_s4u2proxy_krb5.c +$(OUTPRE)t_saslname.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_saslname.c +$(OUTPRE)t_spnego.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_spnego.c +$(OUTPRE)t_srcattrs.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssapi/gssapi_ext.h $(BUILDTOP)/include/gssapi/gssapi_krb5.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + common.h t_srcattrs.c +$(OUTPRE)t_store_cred.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ + $(BUILDTOP)/include/gssapi/gssapi_krb5.h $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ + common.h t_store_cred.c diff --git a/krb5-1.21.3/src/tests/gssapi/reload.c b/krb5-1.21.3/src/tests/gssapi/reload.c new file mode 100644 index 00000000..4fe35654 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/reload.c @@ -0,0 +1,83 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/reload.c - test loading libgssapi_krb5 twice */ +/* + * Copyright (C) 2020 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. + */ + +/* + * This is a regression test for ticket #8614. It ensures that libgssapi_krb5 + * can be loaded multiple times in the same process when libkrb5support is held + * open by another library. + */ + +#include +#include +#include +#include + +/* Load libgssapi_krb5, briefly use it (to force the initializer to run), and + * close it. */ +static void +load_gssapi(void) +{ + void *gssapi; + OM_uint32 (*indmechs)(OM_uint32 *, gss_OID_set *); + OM_uint32 (*reloidset)(OM_uint32 *, gss_OID_set *); + OM_uint32 major, minor; + gss_OID_set mechs; + + gssapi = dlopen("libgssapi_krb5.so", RTLD_NOW | RTLD_LOCAL); + assert(gssapi != NULL); + indmechs = dlsym(gssapi, "gss_indicate_mechs"); + reloidset = dlsym(gssapi, "gss_release_oid_set"); + assert(indmechs != NULL && reloidset != NULL); + major = (*indmechs)(&minor, &mechs); + assert(major == 0); + (*reloidset)(&minor, &mechs); + dlclose(gssapi); +} + +int +main() +{ + void *support; + + /* Hold open libkrb5support to ensure that thread-local state remains */ + support = dlopen("libkrb5support.so", RTLD_NOW | RTLD_LOCAL); + if (support == NULL) { + fprintf(stderr, "Error loading libkrb5support: %s\n", dlerror()); + return 1; + } + + load_gssapi(); + load_gssapi(); + + dlclose(support); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_accname.c b/krb5-1.21.3/src/tests/gssapi/t_accname.c new file mode 100644 index 00000000..30b5db54 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_accname.c @@ -0,0 +1,93 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2011 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include + +#include "common.h" + +/* + * Test program for acceptor names, intended to be run from a Python test + * script. Establishes contexts with the default initiator name, a specified + * principal name as target name, and a specified host-based name as acceptor + * name (or GSS_C_NO_NAME if no acceptor name is given). If the exchange is + * successful, queries the context for the acceptor name and prints it. If any + * call is unsuccessful, displays an error message. Exits with status 0 if all + * operations are successful, or 1 if not. + * + * Usage: ./t_accname targetname [acceptorname] + */ + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major, flags; + gss_cred_id_t acceptor_cred; + gss_name_t target_name, acceptor_name = GSS_C_NO_NAME, real_acceptor_name; + gss_buffer_desc namebuf; + gss_ctx_id_t initiator_context, acceptor_context; + + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: %s targetname [acceptorname]\n", argv[0]); + return 1; + } + + /* Import target and acceptor names. */ + target_name = import_name(argv[1]); + if (argc >= 3) + acceptor_name = import_name(argv[2]); + + /* Get acceptor cred. */ + major = gss_acquire_cred(&minor, acceptor_name, GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, GSS_C_ACCEPT, + &acceptor_cred, NULL, NULL); + check_gsserr("gss_acquire_cred", major, minor); + + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + establish_contexts(&mech_krb5, GSS_C_NO_CREDENTIAL, acceptor_cred, + target_name, flags, &initiator_context, + &acceptor_context, NULL, NULL, NULL); + + major = gss_inquire_context(&minor, acceptor_context, NULL, + &real_acceptor_name, NULL, NULL, NULL, NULL, + NULL); + check_gsserr("gss_inquire_context", major, minor); + + namebuf.value = NULL; + namebuf.length = 0; + major = gss_display_name(&minor, real_acceptor_name, &namebuf, NULL); + check_gsserr("gss_display_name", major, minor); + + printf("%.*s\n", (int)namebuf.length, (char *)namebuf.value); + + (void)gss_release_name(&minor, &target_name); + (void)gss_release_name(&minor, &acceptor_name); + (void)gss_release_name(&minor, &real_acceptor_name); + (void)gss_release_cred(&minor, &acceptor_cred); + (void)gss_delete_sec_context(&minor, &initiator_context, NULL); + (void)gss_delete_sec_context(&minor, &acceptor_context, NULL); + (void)gss_release_buffer(&minor, &namebuf); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_add_cred.c b/krb5-1.21.3/src/tests/gssapi/t_add_cred.c new file mode 100644 index 00000000..68b37e3e --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_add_cred.c @@ -0,0 +1,137 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_add_cred.c - gss_add_cred() tests */ +/* + * Copyright (C) 2018 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. + */ + +/* + * This program tests the mechglue behavior of gss_add_cred(). It relies on a + * krb5 keytab and credentials being present so that initiator and acceptor + * credentials can be acquired, but does not use them to initiate or accept any + * requests. + */ + +#include +#include + +#include "common.h" + +int +main() +{ + OM_uint32 minor, major; + gss_cred_id_t cred1, cred2; + gss_cred_usage_t usage; + gss_name_t name; + + /* Check that we get the expected error if we pass neither an input nor an + * output cred handle. */ + major = gss_add_cred(&minor, GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, + &mech_krb5, GSS_C_INITIATE, GSS_C_INDEFINITE, + GSS_C_INDEFINITE, NULL, NULL, NULL, NULL); + assert(major == (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED)); + + /* Regression test for #8737: make sure that desired_name is honored when + * creating a credential by passing in a non-matching name. */ + name = import_name("p:does/not/match@WRONG_REALM"); + major = gss_add_cred(&minor, GSS_C_NO_CREDENTIAL, name, &mech_krb5, + GSS_C_INITIATE, GSS_C_INDEFINITE, GSS_C_INDEFINITE, + &cred1, NULL, NULL, NULL); + assert(major == GSS_S_NO_CRED); + gss_release_name(&minor, &name); + + /* Create cred1 with a krb5 initiator cred by passing an output handle but + * no input handle. */ + major = gss_add_cred(&minor, GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, + &mech_krb5, GSS_C_INITIATE, GSS_C_INDEFINITE, + GSS_C_INDEFINITE, &cred1, NULL, NULL, NULL); + assert(major == GSS_S_COMPLETE); + + /* Verify that cred1 has the expected mechanism creds. */ + major = gss_inquire_cred_by_mech(&minor, cred1, &mech_krb5, NULL, NULL, + NULL, &usage); + assert(major == GSS_S_COMPLETE && usage == GSS_C_INITIATE); + major = gss_inquire_cred_by_mech(&minor, cred1, &mech_iakerb, NULL, NULL, + NULL, &usage); + assert(major == GSS_S_NO_CRED); + + /* Check that we get the expected error if we try to add another krb5 mech + * cred to cred1. */ + major = gss_add_cred(&minor, cred1, GSS_C_NO_NAME, &mech_krb5, + GSS_C_INITIATE, GSS_C_INDEFINITE, GSS_C_INDEFINITE, + NULL, NULL, NULL, NULL); + assert(major == GSS_S_DUPLICATE_ELEMENT); + + /* Add an IAKERB acceptor mech cred to cred1. */ + major = gss_add_cred(&minor, cred1, GSS_C_NO_NAME, &mech_iakerb, + GSS_C_ACCEPT, GSS_C_INDEFINITE, GSS_C_INDEFINITE, + NULL, NULL, NULL, NULL); + assert(major == GSS_S_COMPLETE); + + /* Verify cred1 mechanism creds. */ + major = gss_inquire_cred_by_mech(&minor, cred1, &mech_krb5, NULL, NULL, + NULL, &usage); + assert(major == GSS_S_COMPLETE && usage == GSS_C_INITIATE); + major = gss_inquire_cred_by_mech(&minor, cred1, &mech_iakerb, NULL, NULL, + NULL, &usage); + assert(major == GSS_S_COMPLETE && usage == GSS_C_ACCEPT); + + /* Start over with another new cred. */ + gss_release_cred(&minor, &cred1); + major = gss_add_cred(&minor, GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, + &mech_krb5, GSS_C_ACCEPT, GSS_C_INDEFINITE, + GSS_C_INDEFINITE, &cred1, NULL, NULL, NULL); + assert(major == GSS_S_COMPLETE); + + /* Create an expanded cred by passing both an output handle and an input + * handle. */ + major = gss_add_cred(&minor, cred1, GSS_C_NO_NAME, &mech_iakerb, + GSS_C_INITIATE, GSS_C_INDEFINITE, GSS_C_INDEFINITE, + &cred2, NULL, NULL, NULL); + assert(major == GSS_S_COMPLETE); + + /* Verify mechanism creds in cred1 and cred2. */ + major = gss_inquire_cred_by_mech(&minor, cred1, &mech_krb5, NULL, NULL, + NULL, &usage); + assert(major == GSS_S_COMPLETE && usage == GSS_C_ACCEPT); + major = gss_inquire_cred_by_mech(&minor, cred1, &mech_iakerb, NULL, NULL, + NULL, &usage); + assert(major == GSS_S_NO_CRED); + major = gss_inquire_cred_by_mech(&minor, cred2, &mech_krb5, NULL, NULL, + NULL, &usage); + assert(major == GSS_S_COMPLETE && usage == GSS_C_ACCEPT); + major = gss_inquire_cred_by_mech(&minor, cred2, &mech_iakerb, NULL, NULL, + NULL, &usage); + assert(major == GSS_S_COMPLETE && usage == GSS_C_INITIATE); + + gss_release_cred(&minor, &cred1); + gss_release_cred(&minor, &cred2); + + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_authind.py b/krb5-1.21.3/src/tests/gssapi/t_authind.py new file mode 100644 index 00000000..e9f129de --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_authind.py @@ -0,0 +1,51 @@ +from k5test import * + +# Test authentication indicators. Load the test preauth module so we +# can control the indicators asserted. +testpreauth = os.path.join(buildtop, 'plugins', 'preauth', 'test', 'test.so') +conf = {'plugins': {'kdcpreauth': {'module': 'test:' + testpreauth}, + 'clpreauth': {'module': 'test:' + testpreauth}}} +realm = K5Realm(krb5_conf=conf) +realm.run([kadminl, 'addprinc', '-randkey', 'service/1']) +realm.run([kadminl, 'addprinc', '-randkey', 'service/2']) +realm.run([kadminl, 'modprinc', '+requires_preauth', realm.user_princ]) +realm.run([kadminl, 'setstr', 'service/1', 'require_auth', 'superstrong']) +realm.run([kadminl, 'setstr', 'service/2', 'require_auth', 'one two']) +realm.run([kadminl, 'xst', 'service/1']) +realm.run([kadminl, 'xst', 'service/2']) + +realm.kinit(realm.user_princ, password('user'), + ['-X', 'indicators=superstrong']) +out = realm.run(['./t_srcattrs', 'p:service/1']) +if ('Attribute auth-indicators Authenticated Complete') not in out: + fail('Expected attribute type data not seen') +# UTF8 "superstrong" +if '73757065727374726f6e67' not in out: + fail('Expected auth indicator not seen in name attributes') + +msg = 'gss_init_sec_context: KDC policy rejects request' +realm.run(['./t_srcattrs', 'p:service/2'], expected_code=1, expected_msg=msg) + +realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=one two']) +out = realm.run(['./t_srcattrs', 'p:service/2']) +# Hexadecimal "one" and "two" +if '6f6e65' not in out or '74776f' not in out: + fail('Expected auth indicator not seen in name attributes') + +realm.stop() + +# Test the FAST encrypted challenge auth indicator. +kdcconf = {'realms': {'$realm': {'encrypted_challenge_indicator': 'fast'}}} +realm = K5Realm(kdc_conf=kdcconf) +realm.run([kadminl, 'modprinc', '+requires_preauth', realm.user_princ]) +realm.run([kadminl, 'xst', realm.host_princ]) +realm.kinit(realm.user_princ, password('user')) +realm.kinit(realm.user_princ, password('user'), ['-T', realm.ccache]) +out = realm.run(['./t_srcattrs', 'p:' + realm.host_princ]) +if ('Attribute auth-indicators Authenticated Complete') not in out: + fail('Expected attribute type not seen') +if '66617374' not in out: + fail('Expected auth indicator not seen in name attributes') + +realm.stop() +success('GSSAPI auth indicator tests') diff --git a/krb5-1.21.3/src/tests/gssapi/t_bindings.c b/krb5-1.21.3/src/tests/gssapi/t_bindings.c new file mode 100644 index 00000000..e8906715 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_bindings.c @@ -0,0 +1,111 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2020 by Red Hat, Inc. + * 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. + */ + +#include +#include +#include + +#include "common.h" + +/* + * Establish contexts (without and with GSS_C_DCE_STYLE) with the default + * initiator name, a specified principal name as target name, initiator + * bindings, and acceptor bindings. If any call is unsuccessful, display an + * error message. Output "yes" or "no" to indicate whether the contexts were + * reported as channel-bound on the acceptor. Exit with status 0 if all + * operations are successful, or 1 if not. + * + * Usage: ./t_bindings [-s] targetname icb acb + * + * An icb or abc value of "-" will not specify channel bindings. + */ + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, flags1, flags2; + gss_name_t target_name; + gss_ctx_id_t ictx, actx; + struct gss_channel_bindings_struct icb_data = {0}, acb_data = {0}; + gss_channel_bindings_t icb = GSS_C_NO_CHANNEL_BINDINGS; + gss_channel_bindings_t acb = GSS_C_NO_CHANNEL_BINDINGS; + gss_OID_desc *mech; + + argv++; + argc--; + if (*argv != NULL && strcmp(*argv, "-s") == 0) { + mech = &mech_spnego; + argv++; + argc--; + } else { + mech = &mech_krb5; + } + + if (argc != 3) { + fprintf(stderr, "Usage: t_bindings [-s] targetname icb acb\n"); + return 1; + } + + target_name = import_name(argv[0]); + + if (strcmp(argv[1], "-") != 0) { + icb_data.application_data.length = strlen(argv[1]); + icb_data.application_data.value = argv[1]; + icb = &icb_data; + } + + if (strcmp(argv[2], "-") != 0) { + acb_data.application_data.length = strlen(argv[2]); + acb_data.application_data.value = argv[2]; + acb = &acb_data; + } + + establish_contexts_ex(mech, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, + target_name, 0, &ictx, &actx, icb, acb, &flags1, + NULL, NULL, NULL); + + /* Try again with GSS_C_DCE_STYLE */ + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + + establish_contexts_ex(mech, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, + target_name, GSS_C_DCE_STYLE, &ictx, &actx, icb, acb, + &flags2, NULL, NULL, NULL); + assert((flags1 & GSS_C_CHANNEL_BOUND_FLAG) == + (flags2 & GSS_C_CHANNEL_BOUND_FLAG)); + printf("%s\n", (flags1 & GSS_C_CHANNEL_BOUND_FLAG) ? "yes" : "no"); + + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + (void)gss_release_name(&minor, &target_name); + + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_bindings.py b/krb5-1.21.3/src/tests/gssapi/t_bindings.py new file mode 100644 index 00000000..f377977b --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_bindings.py @@ -0,0 +1,43 @@ +from k5test import * + +realm = K5Realm() +server = 'p:' + realm.host_princ + +mark('krb5 channel bindings') +realm.run(['./t_bindings', server, '-', '-'], expected_msg='no') +realm.run(['./t_bindings', server, 'a', '-'], expected_msg='no') +realm.run(['./t_bindings', server, 'a', 'a'], expected_msg='yes') +realm.run(['./t_bindings', server, '-', 'a'], expected_msg='no') +realm.run(['./t_bindings', server, 'a', 'x'], + expected_code=1, expected_msg='Incorrect channel bindings') + +mark('SPNEGO channel bindings') +realm.run(['./t_bindings', '-s', server, '-', '-'], expected_msg='no') +realm.run(['./t_bindings', '-s', server, 'a', '-'], expected_msg='no') +realm.run(['./t_bindings', '-s', server, 'a', 'a'], expected_msg='yes') +realm.run(['./t_bindings', '-s', server, '-', 'a'], expected_msg='no') +realm.run(['./t_bindings', '-s', server, 'a', 'x'], + expected_code=1, expected_msg='Incorrect channel bindings') + +client_aware_conf = {'libdefaults': {'client_aware_channel_bindings': 'true'}} +e = realm.special_env('cb_aware', False, krb5_conf=client_aware_conf) + +mark('krb5 client_aware_channel_bindings') +realm.run(['./t_bindings', server, '-', '-'], env=e, expected_msg='no') +realm.run(['./t_bindings', server, 'a', '-'], env=e, expected_msg='no') +realm.run(['./t_bindings', server, 'a', 'a'], env=e, expected_msg='yes') +realm.run(['./t_bindings', server, '-', 'a'], env=e, + expected_code=1, expected_msg='Incorrect channel bindings') +realm.run(['./t_bindings', server, 'a', 'x'], env=e, + expected_code=1, expected_msg='Incorrect channel bindings') + +mark('SPNEGO client_aware_channel_bindings') +realm.run(['./t_bindings', '-s', server, '-', '-'], env=e, expected_msg='no') +realm.run(['./t_bindings', '-s', server, 'a', '-'], env=e, expected_msg='no') +realm.run(['./t_bindings', '-s', server, 'a', 'a'], env=e, expected_msg='yes') +realm.run(['./t_bindings', '-s', server, '-', 'a'], env=e, + expected_code=1, expected_msg='Incorrect channel bindings') +realm.run(['./t_bindings', '-s', server, 'a', 'x'], env=e, + expected_code=1, expected_msg='Incorrect channel bindings') + +success('channel bindings tests') diff --git a/krb5-1.21.3/src/tests/gssapi/t_ccselect.c b/krb5-1.21.3/src/tests/gssapi/t_ccselect.c new file mode 100644 index 00000000..cc4f73a1 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_ccselect.c @@ -0,0 +1,90 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_ccselect.c - Test program for GSSAPI cred selection */ +/* + * Copyright 2011 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include + +#include "common.h" + +/* + * Test program for client credential selection, intended to be run from a + * Python test script. Establishes contexts with an optionally specified + * initiator name, a specified target name, and the default acceptor cred. If + * the exchange is successful, prints the initiator name as seen by the + * acceptor. If any call is unsuccessful, displays an error message. Exits + * with status 0 if all operations are successful, or 1 if not. + * + * Usage: ./t_ccselect targetname [initiatorname|-] + */ + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major, flags; + gss_cred_id_t initiator_cred = GSS_C_NO_CREDENTIAL; + gss_name_t target_name, initiator_name = GSS_C_NO_NAME; + gss_name_t real_initiator_name; + gss_buffer_desc namebuf; + gss_ctx_id_t initiator_context, acceptor_context; + + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: %s targetname [initiatorname|-]\n", argv[0]); + return 1; + } + + target_name = import_name(argv[1]); + + if (argc >= 3) { + /* Get initiator cred. */ + if (strcmp(argv[2], "-") != 0) + initiator_name = import_name(argv[2]); + major = gss_acquire_cred(&minor, initiator_name, GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, GSS_C_INITIATE, + &initiator_cred, NULL, NULL); + check_gsserr("gss_acquire_cred", major, minor); + } + + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + establish_contexts(&mech_krb5, initiator_cred, GSS_C_NO_CREDENTIAL, + target_name, flags, &initiator_context, + &acceptor_context, &real_initiator_name, NULL, NULL); + + namebuf.value = NULL; + namebuf.length = 0; + major = gss_display_name(&minor, real_initiator_name, &namebuf, NULL); + check_gsserr("gss_display_name(initiator)", major, minor); + printf("%.*s\n", (int)namebuf.length, (char *)namebuf.value); + + (void)gss_release_name(&minor, &target_name); + (void)gss_release_name(&minor, &initiator_name); + (void)gss_release_name(&minor, &real_initiator_name); + (void)gss_release_cred(&minor, &initiator_cred); + (void)gss_delete_sec_context(&minor, &initiator_context, NULL); + (void)gss_delete_sec_context(&minor, &acceptor_context, NULL); + (void)gss_release_buffer(&minor, &namebuf); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_ccselect.py b/krb5-1.21.3/src/tests/gssapi/t_ccselect.py new file mode 100755 index 00000000..c93be672 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_ccselect.py @@ -0,0 +1,164 @@ +# Copyright (C) 2011 by the Massachusetts Institute of Technology. +# All rights reserved. + +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +from k5test import * + +# Create two independent realms (no cross-realm TGTs). For the +# fallback realm tests we need to control the precise server hostname, +# so turn off DNS canonicalization and shortname qualification. +conf = {'libdefaults': {'dns_canonicalize_hostname': 'false', + 'qualify_shortname': ''}} +r1 = K5Realm(create_user=False, krb5_conf=conf) +r2 = K5Realm(create_user=False, krb5_conf=conf, realm='KRBTEST2.COM', + portbase=62000, testdir=os.path.join(r1.testdir, 'r2')) + +host1 = 'p:' + r1.host_princ +host2 = 'p:' + r2.host_princ +foo = 'foo.krbtest.com' +foo2 = 'foo.krbtest2.com' +foobar = "foo.bar.krbtest.com" + +# These strings specify the target as a GSS name. The resulting +# principal will have the host-based type, with the referral realm +# (since k5test realms have no domain-realm mapping by default). +# krb5_cc_select() will use the fallback realm, which is either the +# uppercased parent domain, or the default realm if the hostname is a +# single component. +gssserver = 'h:host@' + foo +gssserver2 = 'h:host@' + foo2 +gssserver_bar = 'h:host@' + foobar +gsslocal = 'h:host@localhost' + +# refserver specifies the target as a principal in the referral realm. +# The principal won't be treated as a host principal by the +# .k5identity rules since it has unknown type. +refserver = 'p:host/' + hostname + '@' + +# Verify that we can't get initiator creds with no credentials in the +# collection. +r1.run(['./t_ccselect', host1, '-'], expected_code=1, + expected_msg='No Kerberos credentials available') + +# Make a directory collection and use it for client commands in both realms. +ccdir = os.path.join(r1.testdir, 'cc') +ccname = 'DIR:' + ccdir +r1.env['KRB5CCNAME'] = ccname +r2.env['KRB5CCNAME'] = ccname + +# Use .k5identity from testdir and not from the tester's homedir. +r1.env['HOME'] = r1.testdir +r2.env['HOME'] = r1.testdir + +# Create two users in r1 and one in r2. +alice='alice@KRBTEST.COM' +bob='bob@KRBTEST.COM' +zaphod='zaphod@KRBTEST2.COM' +r1.addprinc(alice, password('alice')) +r1.addprinc(bob, password('bob')) +r2.addprinc(zaphod, password('zaphod')) + +# Create host principals and keytabs for fallback realm tests. +if hostname != 'localhost': + r1.addprinc('host/localhost') + r2.addprinc('host/localhost') +r1.addprinc('host/' + foo) +r2.addprinc('host/' + foo2) +r1.addprinc('host/' + foobar) +r1.extract_keytab('host/localhost', r1.keytab) +r2.extract_keytab('host/localhost', r2.keytab) +r1.extract_keytab('host/' + foo, r1.keytab) +r2.extract_keytab('host/' + foo2, r2.keytab) +r1.extract_keytab('host/' + foobar, r1.keytab) + +# Get tickets for one user in each realm (zaphod will be primary). +r1.kinit(alice, password('alice')) +r2.kinit(zaphod, password('zaphod')) + +# Check that we can find a cache for a specified client principal. +output = r1.run(['./t_ccselect', host1, 'p:' + alice]) +if output != (alice + '\n'): + fail('alice not chosen when specified') +output = r2.run(['./t_ccselect', host2, 'p:' + zaphod]) +if output != (zaphod + '\n'): + fail('zaphod not chosen when specified') + +# Check that we can guess a cache based on the service realm. +output = r1.run(['./t_ccselect', host1]) +if output != (alice + '\n'): + fail('alice not chosen as default initiator cred for server in r1') +output = r1.run(['./t_ccselect', host1, '-']) +if output != (alice + '\n'): + fail('alice not chosen as default initiator name for server in r1') +output = r2.run(['./t_ccselect', host2]) +if output != (zaphod + '\n'): + fail('zaphod not chosen as default initiator cred for server in r1') +output = r2.run(['./t_ccselect', host2, '-']) +if output != (zaphod + '\n'): + fail('zaphod not chosen as default initiator name for server in r1') + +# Check that primary cache is used if server realm is unknown. +output = r2.run(['./t_ccselect', refserver]) +if output != (zaphod + '\n'): + fail('zaphod not chosen via primary cache for unknown server realm') +r1.run(['./t_ccselect', gssserver2], expected_code=1) +# Check ccache selection using a fallback realm. +output = r1.run(['./t_ccselect', gssserver]) +if output != (alice + '\n'): + fail('alice not chosen via parent domain fallback') +output = r2.run(['./t_ccselect', gssserver2]) +if output != (zaphod + '\n'): + fail('zaphod not chosen via parent domain fallback') +# Check ccache selection using a fallback realm (default realm). +output = r1.run(['./t_ccselect', gsslocal]) +if output != (alice + '\n'): + fail('alice not chosen via default realm fallback') +output = r2.run(['./t_ccselect', gsslocal]) +if output != (zaphod + '\n'): + fail('zaphod not chosen via default realm fallback') + +# Check that realm ccselect fallback works correctly +r1.run(['./t_ccselect', gssserver_bar], expected_msg=alice) +r2.kinit(zaphod, password('zaphod')) +r1.run(['./t_ccselect', gssserver_bar], expected_msg=alice) + +# Get a second cred in r1 (bob will be primary). +r1.kinit(bob, password('bob')) + +# Try some cache selections using .k5identity. +k5id = open(os.path.join(r1.testdir, '.k5identity'), 'w') +k5id.write('%s realm=%s\n' % (alice, r1.realm)) +k5id.write('%s service=ho*t host=localhost\n' % zaphod) +k5id.write('noprinc service=bogus') +k5id.close() +output = r1.run(['./t_ccselect', host1]) +if output != (alice + '\n'): + fail('alice not chosen via .k5identity realm line.') +output = r2.run(['./t_ccselect', gsslocal]) +if output != (zaphod + '\n'): + fail('zaphod not chosen via .k5identity service/host line.') +output = r1.run(['./t_ccselect', refserver]) +if output != (bob + '\n'): + fail('bob not chosen via primary cache when no .k5identity line matches.') +r1.run(['./t_ccselect', 'h:bogus@' + foo2], expected_code=1, + expected_msg="Can't find client principal noprinc") + +success('GSSAPI credential selection tests') diff --git a/krb5-1.21.3/src/tests/gssapi/t_ciflags.c b/krb5-1.21.3/src/tests/gssapi/t_ciflags.c new file mode 100644 index 00000000..315062c9 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_ciflags.c @@ -0,0 +1,120 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_ciflags.c - GSS_KRB5_CRED_NO_CI_FLAGS_X tests */ +/* + * Copyright (C) 2015 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. + */ + +#include +#include +#include + +#include "common.h" + +static void +flagtest(gss_OID mech, gss_cred_id_t icred, gss_name_t tname, + OM_uint32 inflags, OM_uint32 expflags) +{ + gss_ctx_id_t ictx, actx; + OM_uint32 major, minor, flags; + + establish_contexts(mech, icred, GSS_C_NO_CREDENTIAL, tname, inflags, &ictx, + &actx, NULL, NULL, NULL); + + major = gss_inquire_context(&minor, actx, NULL, NULL, NULL, NULL, &flags, + NULL, NULL); + check_gsserr("gss_inquire_context", major, minor); + assert(flags == expflags); + + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major; + gss_cred_id_t icred; + gss_name_t tname; + gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER; + + if (argc != 2) { + fprintf(stderr, "Usage: %s targetname\n", argv[0]); + return 1; + } + tname = import_name(argv[1]); + + /* With no flags, the initiator asserts conf, integ, trans */ + flagtest(&mech_krb5, GSS_C_NO_CREDENTIAL, tname, 0, + GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_TRANS_FLAG); + flagtest(&mech_spnego, GSS_C_NO_CREDENTIAL, tname, 0, + GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_TRANS_FLAG); + + /* The initiator also asserts most flags specified by the caller. */ + flagtest(&mech_krb5, GSS_C_NO_CREDENTIAL, tname, GSS_C_SEQUENCE_FLAG, + GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_TRANS_FLAG | + GSS_C_SEQUENCE_FLAG); + flagtest(&mech_spnego, GSS_C_NO_CREDENTIAL, tname, GSS_C_SEQUENCE_FLAG, + GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_TRANS_FLAG | + GSS_C_SEQUENCE_FLAG); + + /* Get a normal initiator cred and re-test with no flags. */ + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, GSS_C_INITIATE, &icred, NULL, + NULL); + check_gsserr("gss_acquire_cred", major, minor); + flagtest(&mech_krb5, icred, tname, 0, + GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_TRANS_FLAG); + flagtest(&mech_spnego, icred, tname, 0, + GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_TRANS_FLAG); + + /* Suppress confidentiality and integrity flags on the initiator cred and + * check that they are suppressed, but can still be asserted explicitly. */ + major = gss_set_cred_option(&minor, &icred, + (gss_OID)GSS_KRB5_CRED_NO_CI_FLAGS_X, + &empty_buffer); + check_gsserr("gss_set_cred_option", major, minor); + flagtest(&mech_krb5, icred, tname, 0, GSS_C_TRANS_FLAG); + flagtest(&mech_krb5, icred, tname, GSS_C_CONF_FLAG, + GSS_C_CONF_FLAG | GSS_C_TRANS_FLAG); + flagtest(&mech_krb5, icred, tname, GSS_C_INTEG_FLAG, + GSS_C_INTEG_FLAG | GSS_C_TRANS_FLAG); + flagtest(&mech_krb5, icred, tname, GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG, + GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_TRANS_FLAG); + flagtest(&mech_spnego, icred, tname, 0, GSS_C_TRANS_FLAG); + flagtest(&mech_spnego, icred, tname, GSS_C_INTEG_FLAG, + GSS_C_INTEG_FLAG | GSS_C_TRANS_FLAG); + flagtest(&mech_spnego, icred, tname, GSS_C_CONF_FLAG, + GSS_C_CONF_FLAG | GSS_C_TRANS_FLAG); + flagtest(&mech_spnego, icred, tname, GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG, + GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_TRANS_FLAG); + + (void)gss_release_name(&minor, &tname); + (void)gss_release_cred(&minor, &icred); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_client_keytab.py b/krb5-1.21.3/src/tests/gssapi/t_client_keytab.py new file mode 100755 index 00000000..8fdf89e4 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_client_keytab.py @@ -0,0 +1,189 @@ +from k5test import * + +# Set up a basic realm and a client keytab containing two user principals. +# Point HOME at realm.testdir for tests using .k5identity. +realm = K5Realm(get_creds=False) +bob = 'bob@' + realm.realm +phost = 'p:' + realm.host_princ +puser = 'p:' + realm.user_princ +pbob = 'p:' + bob +gssserver = 'h:host@' + hostname +realm.env['HOME'] = realm.testdir +realm.addprinc(bob, password('bob')) +realm.extract_keytab(realm.user_princ, realm.client_keytab) +realm.extract_keytab(bob, realm.client_keytab) + +# Test 1: no name/cache specified, pick first principal from client keytab +realm.run(['./t_ccselect', phost], expected_msg=realm.user_princ) +realm.run([kdestroy]) + +# Test 2: no name/cache specified, pick principal from k5identity +k5idname = os.path.join(realm.testdir, '.k5identity') +k5id = open(k5idname, 'w') +k5id.write('%s service=host host=%s\n' % (bob, hostname)) +k5id.close() +realm.run(['./t_ccselect', gssserver], expected_msg=bob) +os.remove(k5idname) +realm.run([kdestroy]) + +# Test 3: no name/cache specified, default ccache has name but no creds +realm.run(['./ccinit', realm.ccache, bob]) +realm.run(['./t_ccselect', phost], expected_msg=bob) +# Leave tickets for next test. + +# Test 4: name specified, non-collectable default cache doesn't match +msg = 'Principal in credential cache does not match desired name' +realm.run(['./t_ccselect', phost, puser], expected_code=1, expected_msg=msg) +realm.run([kdestroy]) + +# Test 5: name specified, nonexistent default cache +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) +# Leave tickets for next test. + +# Test 6: name specified, matches default cache, time to refresh +realm.run(['./ccrefresh', realm.ccache, '1']) +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) +out = realm.run(['./ccrefresh', realm.ccache]) +if int(out) < 1000: + fail('Credentials apparently not refreshed') +realm.run([kdestroy]) + +# Test 7: empty ccache specified, pick first principal from client keytab +realm.run(['./t_imp_cred', phost]) +realm.klist(realm.user_princ) +realm.run([kdestroy]) + +# Test 8: ccache specified with name but no creds; name not in client keytab +realm.run(['./ccinit', realm.ccache, realm.host_princ]) +realm.run(['./t_imp_cred', phost], expected_code=1, + expected_msg='Credential cache is empty') +realm.run([kdestroy]) + +# Test 9: ccache specified with name but no creds; name in client keytab +realm.run(['./ccinit', realm.ccache, bob]) +realm.run(['./t_imp_cred', phost]) +realm.klist(bob) +# Leave tickets for next test. + +# Test 10: ccache specified with creds, time to refresh +realm.run(['./ccrefresh', realm.ccache, '1']) +realm.run(['./t_imp_cred', phost]) +realm.klist(bob) +out = realm.run(['./ccrefresh', realm.ccache]) +if int(out) < 1000: + fail('Credentials apparently not refreshed') +realm.run([kdestroy]) + +# Test 11: gss_import_cred_from with client_keytab value +store_keytab = os.path.join(realm.testdir, 'store_keytab') +os.rename(realm.client_keytab, store_keytab) +realm.run(['./t_credstore', '-i', 'p:' + realm.user_princ, 'client_keytab', + store_keytab]) +realm.klist(realm.user_princ) +os.rename(store_keytab, realm.client_keytab) + +# Use a cache collection for the remaining tests. +ccdir = os.path.join(realm.testdir, 'cc') +ccname = 'DIR:' + ccdir +os.mkdir(ccdir) +realm.env['KRB5CCNAME'] = ccname + +# Test 12: name specified, matching cache in collection with no creds +bobcache = os.path.join(ccdir, 'tktbob') +realm.run(['./ccinit', bobcache, bob]) +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) +# Leave tickets for next test. + +# Test 13: name specified, matching cache in collection, time to refresh +realm.run(['./ccrefresh', bobcache, '1']) +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) +out = realm.run(['./ccrefresh', bobcache]) +if int(out) < 1000: + fail('Credentials apparently not refreshed') +realm.run([kdestroy, '-A']) + +# Test 14: name specified, collection has default for different principal +realm.kinit(realm.user_princ, password('user')) +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) +msg = 'Default principal: %s\n' % realm.user_princ +realm.run([klist], expected_msg=msg) +realm.run([kdestroy, '-A']) + +# Test 15: name specified, collection has no default cache +realm.run(['./t_ccselect', phost, pbob], expected_msg=bob) +# Make sure the tickets we acquired didn't become the default +realm.run([klist], expected_code=1, expected_msg='No credentials cache found') +realm.run([kdestroy, '-A']) + +# Test 16: default client keytab cannot be resolved, but valid +# credentials exist in ccache. +conf = {'libdefaults': {'default_client_keytab_name': '%{'}} +bad_cktname = realm.special_env('bad_cktname', False, krb5_conf=conf) +del bad_cktname['KRB5_CLIENT_KTNAME'] +realm.kinit(realm.user_princ, password('user')) +realm.run(['./t_ccselect', phost], env=bad_cktname, + expected_msg=realm.user_princ) + +mark('refresh of manually acquired creds') + +# Test 17: no name/ccache specified, manually acquired creds which +# will expire soon. Verify that creds are refreshed using the current +# client name, with refresh_time set in the refreshed ccache. +realm.kinit('bob', password('bob'), ['-l', '15s']) +realm.run(['./t_ccselect', phost], expected_msg='bob') +realm.run([klist, '-C'], expected_msg='refresh_time = ') + +# Test 18: no name/ccache specified, manually acquired creds with a +# client principal not present in the client keytab. A refresh is +# attempted but fails, and an expired ticket error results. +realm.kinit(realm.admin_princ, password('admin'), ['-l', '-10s']) +msgs = ('Getting initial credentials for user/admin@KRBTEST.COM', + '/Matching credential not found') +realm.run(['./t_ccselect', phost], expected_code=1, + expected_msg='Ticket expired', expected_trace=msgs) +realm.run([kdestroy, '-A']) + +# Test 19: host-based initiator name +mark('host-based initiator name') +hsvc = 'h:svc@' + hostname +svcprinc = 'svc/%s@%s' % (hostname, realm.realm) +realm.addprinc(svcprinc) +realm.extract_keytab(svcprinc, realm.client_keytab) +# On the first run we match against the keytab while getting tickets, +# substituting the default realm. +msgs = ('/Can\'t find client principal svc/%s@ in' % hostname, + 'Getting initial credentials for svc/%s@' % hostname, + 'Found entries for %s in keytab' % svcprinc, + 'Retrieving %s from FILE:%s' % (svcprinc, realm.client_keytab), + 'Storing %s -> %s in' % (svcprinc, realm.krbtgt_princ), + 'Retrieving %s -> %s from' % (svcprinc, realm.krbtgt_princ), + 'authenticator for %s -> %s' % (svcprinc, realm.host_princ)) +realm.run(['./t_ccselect', phost, hsvc], expected_trace=msgs) +# On the second run we match against the collection. +msgs = ('Matching svc/%s@ in collection with result: 0' % hostname, + 'Getting credentials %s -> %s' % (svcprinc, realm.host_princ), + 'authenticator for %s -> %s' % (svcprinc, realm.host_princ)) +realm.run(['./t_ccselect', phost, hsvc], expected_trace=msgs) +realm.run([kdestroy, '-A']) + +# Test 20: host-based initiator name with fallback +mark('host-based fallback initiator name') +canonname = canonicalize_hostname(hostname) +if canonname != hostname: + hfsvc = 'h:fsvc@' + hostname + canonprinc = 'fsvc/%s@%s' % (canonname, realm.realm) + realm.addprinc(canonprinc) + realm.extract_keytab(canonprinc, realm.client_keytab) + msgs = ('/Can\'t find client principal fsvc/%s@ in' % hostname, + 'Found entries for %s in keytab' % canonprinc, + 'authenticator for %s -> %s' % (canonprinc, realm.host_princ)) + realm.run(['./t_ccselect', phost, hfsvc], expected_trace=msgs) + msgs = ('Matching fsvc/%s@ in collection with result: 0' % hostname, + 'Getting credentials %s -> %s' % (canonprinc, realm.host_princ)) + realm.run(['./t_ccselect', phost, hfsvc], expected_trace=msgs) + realm.run([kdestroy, '-A']) +else: + skipped('GSS initiator name fallback test', + '%s does not canonicalize to a different name' % hostname) + +success('Client keytab tests') diff --git a/krb5-1.21.3/src/tests/gssapi/t_context.c b/krb5-1.21.3/src/tests/gssapi/t_context.c new file mode 100644 index 00000000..65381aca --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_context.c @@ -0,0 +1,60 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_context.c - Simple context establishment harness */ +/* + * Copyright (C) 2019 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. + */ + +#include +#include + +#include "common.h" + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, flags; + gss_name_t tname; + gss_ctx_id_t ictx, actx; + + if (argc < 2) { + fprintf(stderr, "Usage: %s targetname [acceptorname]\n", argv[0]); + return 1; + } + + tname = import_name(argv[1]); + + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + establish_contexts(&mech_spnego, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, + tname, flags, &ictx, &actx, NULL, NULL, NULL); + + (void)gss_release_name(&minor, &tname); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_credstore.c b/krb5-1.21.3/src/tests/gssapi/t_credstore.c new file mode 100644 index 00000000..1e363699 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_credstore.c @@ -0,0 +1,140 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2011 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +#include "common.h" + +static void +usage(void) +{ + fprintf(stderr, + "Usage: t_credstore [-sabi] principal [{key value} ...]\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major; + gss_key_value_set_desc store; + gss_name_t name = GSS_C_NO_NAME; + gss_cred_usage_t cred_usage = GSS_C_BOTH; + gss_OID_set mechs = GSS_C_NO_OID_SET; + gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; + gss_ctx_id_t ictx = GSS_C_NO_CONTEXT, actx = GSS_C_NO_CONTEXT; + gss_buffer_desc itok, atok; + krb5_boolean store_creds = FALSE, replay = FALSE; + char opt; + + /* Parse options. */ + for (argv++; *argv != NULL && **argv == '-'; argv++) { + opt = (*argv)[1]; + if (opt == 's') + store_creds = TRUE; + else if (opt == 'r') + replay = TRUE; + else if (opt == 'a') + cred_usage = GSS_C_ACCEPT; + else if (opt == 'b') + cred_usage = GSS_C_BOTH; + else if (opt == 'i') + cred_usage = GSS_C_INITIATE; + else + usage(); + } + + /* Get the principal name. */ + if (*argv == NULL) + usage(); + if (**argv != '\0') + name = import_name(*argv); + argv++; + + /* Put any remaining arguments into the store. */ + store.elements = calloc(argc, sizeof(struct gss_key_value_element_struct)); + if (!store.elements) + errout("OOM"); + store.count = 0; + while (*argv != NULL) { + if (*(argv + 1) == NULL) + usage(); + store.elements[store.count].key = *argv; + store.elements[store.count].value = *(argv + 1); + store.count++; + argv += 2; + } + + if (store_creds) { + /* Acquire default creds and try to store them in the cred store. */ + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, 0, GSS_C_NO_OID_SET, + GSS_C_INITIATE, &cred, NULL, NULL); + check_gsserr("gss_acquire_cred", major, minor); + + major = gss_store_cred_into(&minor, cred, GSS_C_INITIATE, + GSS_C_NO_OID, 1, 0, &store, NULL, NULL); + check_gsserr("gss_store_cred_into", major, minor); + + gss_release_cred(&minor, &cred); + } + + /* Try to acquire creds from store. */ + major = gss_acquire_cred_from(&minor, name, 0, mechs, cred_usage, + &store, &cred, NULL, NULL); + check_gsserr("gss_acquire_cred_from", major, minor); + + if (replay) { + /* Induce a replay using cred as the acceptor cred, to test the replay + * cache indicated by the store. */ + major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ictx, name, + &mech_krb5, 0, GSS_C_INDEFINITE, + GSS_C_NO_CHANNEL_BINDINGS, + GSS_C_NO_BUFFER, NULL, &itok, NULL, NULL); + check_gsserr("gss_init_sec_context", major, minor); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + + major = gss_accept_sec_context(&minor, &actx, cred, &itok, + GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL, + &atok, NULL, NULL, NULL); + check_gsserr("gss_accept_sec_context(1)", major, minor); + (void)gss_release_buffer(&minor, &atok); + (void)gss_delete_sec_context(&minor, &actx, NULL); + + major = gss_accept_sec_context(&minor, &actx, cred, &itok, + GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL, + &atok, NULL, NULL, NULL); + check_gsserr("gss_accept_sec_context(2)", major, minor); + (void)gss_release_buffer(&minor, &itok); + (void)gss_release_buffer(&minor, &atok); + (void)gss_delete_sec_context(&minor, &actx, NULL); + } + + gss_release_name(&minor, &name); + gss_release_cred(&minor, &cred); + free(store.elements); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_credstore.py b/krb5-1.21.3/src/tests/gssapi/t_credstore.py new file mode 100644 index 00000000..ec59dd8d --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_credstore.py @@ -0,0 +1,97 @@ +from k5test import * + +realm = K5Realm() + +mark('gss_store_cred_into() and ccache/keytab') +storagecache = 'FILE:' + os.path.join(realm.testdir, 'user_store') +servicekeytab = os.path.join(realm.testdir, 'kt') +service_cs = 'service/cs@%s' % realm.realm +realm.addprinc(service_cs) +realm.extract_keytab(service_cs, servicekeytab) +realm.kinit(service_cs, None, ['-k', '-t', servicekeytab]) +msgs = ('Storing %s -> %s in MEMORY:' % (service_cs, realm.krbtgt_princ), + 'Moving ccache MEMORY:', + 'Retrieving %s from FILE:%s' % (service_cs, servicekeytab)) +realm.run(['./t_credstore', '-s', 'p:' + service_cs, 'ccache', storagecache, + 'keytab', servicekeytab], expected_trace=msgs) + +mark('matching') +scc = 'FILE:' + os.path.join(realm.testdir, 'service_cache') +realm.kinit(realm.host_princ, flags=['-k', '-c', scc]) +realm.run(['./t_credstore', '-i', 'p:' + realm.host_princ, 'ccache', scc]) +realm.run(['./t_credstore', '-i', 'h:host', 'ccache', scc]) +realm.run(['./t_credstore', '-i', 'h:host@' + hostname, 'ccache', scc]) +realm.run(['./t_credstore', '-i', 'p:wrong', 'ccache', scc], + expected_code=1, expected_msg='does not match desired name') +realm.run(['./t_credstore', '-i', 'h:host@-nomatch-', 'ccache', scc], + expected_code=1, expected_msg='does not match desired name') +realm.run(['./t_credstore', '-i', 'h:svc', 'ccache', scc], + expected_code=1, expected_msg='does not match desired name') + +mark('matching (fallback)') +canonname = canonicalize_hostname(hostname) +if canonname != hostname: + canonprinc = 'host/%s@%s' % (canonname, realm.realm) + realm.addprinc(canonprinc) + realm.extract_keytab(canonprinc, realm.keytab) + realm.kinit(canonprinc, flags=['-k', '-c', scc]) + realm.run(['./t_credstore', '-i', 'h:host', 'ccache', scc]) + realm.run(['./t_credstore', '-i', 'h:host@' + hostname, 'ccache', scc]) + realm.run(['./t_credstore', '-i', 'h:host@' + canonname, 'ccache', scc]) + realm.run(['./t_credstore', '-i', 'p:' + canonprinc, 'ccache', scc]) + realm.run(['./t_credstore', '-i', 'p:' + realm.host_princ, 'ccache', scc], + expected_code=1, expected_msg='does not match desired name') + realm.run(['./t_credstore', '-i', 'h:host@-nomatch-', 'ccache', scc], + expected_code=1, expected_msg='does not match desired name') +else: + skipped('fallback matching test', + '%s does not canonicalize to a different name' % hostname) + +mark('rcache') +# t_credstore -r should produce a replay error normally, but not with +# rcache set to "none:". +realm.run(['./t_credstore', '-r', '-a', 'p:' + realm.host_princ], + expected_code=1, + expected_msg='gss_accept_sec_context(2): Request is a replay') +realm.run(['./t_credstore', '-r', '-a', 'p:' + realm.host_princ, + 'rcache', 'none:']) + +# Test password feature. +mark('password') +# Must be used with a desired name. +realm.run(['./t_credstore', '-i', '', 'password', 'pw'], + expected_code=1, expected_msg='An invalid name was supplied') +# Must not be used with a client keytab. +realm.run(['./t_credstore', '-i', 'u:' + realm.user_princ, + 'password', 'pw', 'client_keytab', servicekeytab], + expected_code=1, expected_msg='Credential usage type is unknown') +# Must not be used with a ccache. +realm.run(['./t_credstore', '-i', 'u:' + realm.user_princ, + 'password', 'pw', 'ccache', storagecache], + expected_code=1, expected_msg='Credential usage type is unknown') +# Must be acquiring initiator credentials. +realm.run(['./t_credstore', '-a', 'u:' + realm.user_princ, 'password', 'pw'], + expected_code=1, expected_msg='Credential usage type is unknown') +msgs = ('Getting initial credentials for %s' % realm.user_princ, + 'Storing %s -> %s in MEMORY:' % (realm.user_princ, realm.krbtgt_princ), + 'Destroying ccache MEMORY:') +realm.run(['./t_credstore', '-i', 'u:' + realm.user_princ, 'password', + password('user')], expected_trace=msgs) + +mark('verify') +msgs = ('Getting initial credentials for %s' % realm.user_princ, + 'Storing %s -> %s in MEMORY:' % (realm.user_princ, realm.krbtgt_princ), + 'Getting credentials %s -> %s' % (realm.user_princ, service_cs), + 'Storing %s -> %s in MEMORY:' % (realm.user_princ, service_cs)) +realm.run(['./t_credstore', '-i', 'u:' + realm.user_princ, 'password', + password('user'), 'keytab', servicekeytab, 'verify', + service_cs], expected_trace=msgs) +# Try again with verification failing due to key mismatch. +realm.run([kadminl, 'cpw', '-randkey', service_cs]) +realm.run([kadminl, 'modprinc', '-kvno', '1', service_cs]) +errmsg = 'Cannot decrypt ticket for %s' % service_cs +realm.run(['./t_credstore', '-i', 'u:' + realm.user_princ, 'password', + password('user'), 'keytab', servicekeytab, 'verify', + service_cs], expected_code=1, expected_msg=errmsg) + +success('Credential store tests') diff --git a/krb5-1.21.3/src/tests/gssapi/t_enctypes.c b/krb5-1.21.3/src/tests/gssapi/t_enctypes.c new file mode 100644 index 00000000..3fd31e2f --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_enctypes.c @@ -0,0 +1,205 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_enctypes.c - gss_krb5_set_allowable_enctypes test */ +/* + * 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. + */ + +#include "k5-int.h" +#include "common.h" +#include "gssapi_ext.h" + +/* + * This test program establishes contexts with the krb5 mech, the default + * initiator name, a specified target name, and the default acceptor name. + * Before the exchange, gss_set_allowable_enctypes is called for the initiator + * and the acceptor cred if requested. If the exchange is successful, the + * resulting contexts are exported with gss_krb5_export_lucid_sec_context, + * checked for mismatches, and the GSS protocol and keys are displayed. Exits + * with status 0 if all operations are successful, or 1 if not. + * + * Usage: ./t_enctypes [-i initenctypes] [-a accenctypes] targetname + */ + +static void +usage() +{ + errout("Usage: t_enctypes [-i initenctypes] [-a accenctypes] " + "targetname"); +} + +/* Error out if ikey is not the same as akey. */ +static void +check_key_match(gss_krb5_lucid_key_t *ikey, gss_krb5_lucid_key_t *akey) +{ + if (ikey->type != akey->type || ikey->length != akey->length || + memcmp(ikey->data, akey->data, ikey->length) != 0) + errout("Initiator and acceptor keys do not match"); +} + +/* Display the name of enctype. */ +static void +display_enctype(krb5_enctype enctype) +{ + char ename[128]; + + if (krb5_enctype_to_name(enctype, FALSE, ename, sizeof(ename)) == 0) + fputs(ename, stdout); + else + fputs("(unknown)", stdout); +} + +int +main(int argc, char *argv[]) +{ + krb5_error_code ret; + krb5_context kctx = NULL; + krb5_enctype *ienc = NULL, *aenc = NULL, zero = 0; + OM_uint32 minor, major, flags; + gss_name_t tname; + gss_cred_id_t icred = GSS_C_NO_CREDENTIAL, acred = GSS_C_NO_CREDENTIAL; + gss_ctx_id_t ictx, actx; + gss_krb5_lucid_context_v1_t *ilucid, *alucid; + gss_krb5_rfc1964_keydata_t *i1964, *a1964; + gss_krb5_cfx_keydata_t *icfx, *acfx; + gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET; + gss_OID ssf_oid = GSS_C_SEC_CONTEXT_SASL_SSF; + unsigned int ssf; + size_t count; + void *lptr; + int c; + + ret = krb5_init_context(&kctx); + check_k5err(kctx, "krb5_init_context", ret); + + /* Parse arguments. */ + while ((c = getopt(argc, argv, "i:a:")) != -1) { + switch (c) { + case 'i': + ret = krb5int_parse_enctype_list(kctx, "", optarg, &zero, &ienc); + check_k5err(kctx, "krb5_parse_enctype_list(initiator)", ret); + break; + case 'a': + ret = krb5int_parse_enctype_list(kctx, "", optarg, &zero, &aenc); + check_k5err(kctx, "krb5_parse_enctype_list(acceptor)", ret); + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + if (argc != 1) + usage(); + tname = import_name(*argv); + + if (ienc != NULL) { + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE, + &mechset_krb5, GSS_C_INITIATE, &icred, NULL, + NULL); + check_gsserr("gss_acquire_cred(initiator)", major, minor); + + for (count = 0; ienc[count]; count++); + major = gss_krb5_set_allowable_enctypes(&minor, icred, count, ienc); + check_gsserr("gss_krb5_set_allowable_enctypes(init)", major, minor); + } + if (aenc != NULL) { + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE, + &mechset_krb5, GSS_C_ACCEPT, &acred, NULL, + NULL); + check_gsserr("gss_acquire_cred(acceptor)", major, minor); + + for (count = 0; aenc[count]; count++); + major = gss_krb5_set_allowable_enctypes(&minor, acred, count, aenc); + check_gsserr("gss_krb5_set_allowable_enctypes(acc)", major, minor); + } + + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_MUTUAL_FLAG; + establish_contexts(&mech_krb5, icred, acred, tname, flags, &ictx, &actx, + NULL, NULL, NULL); + + /* Query the SSF value and range-check the result. */ + major = gss_inquire_sec_context_by_oid(&minor, ictx, ssf_oid, &bufset); + check_gsserr("gss_inquire_sec_context_by_oid(ssf)", major, minor); + if (bufset->elements[0].length != 4) + errout("SSF buffer has unexpected length"); + ssf = load_32_be(bufset->elements[0].value); + if (ssf < 56 || ssf > 256) + errout("SSF value not within acceptable range (56-256)"); + (void)gss_release_buffer_set(&minor, &bufset); + + /* Export to lucid contexts. */ + major = gss_krb5_export_lucid_sec_context(&minor, &ictx, 1, &lptr); + check_gsserr("gss_export_lucid_sec_context(initiator)", major, minor); + ilucid = lptr; + major = gss_krb5_export_lucid_sec_context(&minor, &actx, 1, &lptr); + check_gsserr("gss_export_lucid_sec_context(acceptor)", major, minor); + alucid = lptr; + + /* Grab the session keys and make sure they match. */ + if (ilucid->protocol != alucid->protocol) + errout("Initiator/acceptor protocol mismatch"); + if (ilucid->protocol) { + icfx = &ilucid->cfx_kd; + acfx = &alucid->cfx_kd; + if (icfx->have_acceptor_subkey != acfx->have_acceptor_subkey) + errout("Initiator/acceptor have_acceptor_subkey mismatch"); + check_key_match(&icfx->ctx_key, &acfx->ctx_key); + if (icfx->have_acceptor_subkey) + check_key_match(&icfx->acceptor_subkey, &acfx->acceptor_subkey); + fputs("cfx ", stdout); + display_enctype(icfx->ctx_key.type); + if (icfx->have_acceptor_subkey) { + fputs(" ", stdout); + display_enctype(icfx->acceptor_subkey.type); + } + fputs("\n", stdout); + } else { + i1964 = &ilucid->rfc1964_kd; + a1964 = &alucid->rfc1964_kd; + if (i1964->sign_alg != a1964->sign_alg || + i1964->seal_alg != a1964->seal_alg) + errout("Initiator/acceptor sign or seal alg mismatch"); + check_key_match(&i1964->ctx_key, &a1964->ctx_key); + fputs("rfc1964 ", stdout); + display_enctype(i1964->ctx_key.type); + fputs("\n", stdout); + } + + krb5_free_context(kctx); + free(ienc); + free(aenc); + (void)gss_release_name(&minor, &tname); + (void)gss_release_cred(&minor, &icred); + (void)gss_release_cred(&minor, &acred); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + (void)gss_krb5_free_lucid_sec_context(&minor, ilucid); + (void)gss_krb5_free_lucid_sec_context(&minor, alucid); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_enctypes.py b/krb5-1.21.3/src/tests/gssapi/t_enctypes.py new file mode 100755 index 00000000..f5f11842 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_enctypes.py @@ -0,0 +1,147 @@ +from k5test import * + +# Define some convenience abbreviations for enctypes we will see in +# test program output. For background, aes256 and aes128 are "CFX +# enctypes", meaning that they imply support for RFC 4121, while des3 +# and rc4 are not. DES3 keys will appear as 'des3-cbc-raw' in +# t_enctypes output because that's how GSSAPI does raw triple-DES +# encryption without the RFC3961 framing. +aes256 = 'aes256-cts-hmac-sha1-96' +aes128 = 'aes128-cts-hmac-sha1-96' +des3 = 'des3-cbc-sha1' +d_des3 = 'DEPRECATED:des3-cbc-sha1' +des3raw = 'des3-cbc-raw' +d_des3raw = 'DEPRECATED:des3-cbc-raw' +rc4 = 'arcfour-hmac' +d_rc4 = 'DEPRECATED:arcfour-hmac' + +# These tests make assumptions about the default enctype lists, so set +# them explicitly rather than relying on the library defaults. +supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal' +conf = {'libdefaults': {'permitted_enctypes': 'aes des3 rc4', + 'allow_des3': 'true', 'allow_rc4': 'true'}, + 'realms': {'$realm': {'supported_enctypes': supp}}} +realm = K5Realm(krb5_conf=conf) +shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save')) + +# Return an argument list for running t_enctypes with optional initiator +# and acceptor enctype lists. +def cmdline(ienc, aenc): + iflags = ienc and ['-i', ienc] or [] + aflags = aenc and ['-a', aenc] or [] + return ['./t_enctypes'] + iflags + aflags + ['p:' + realm.host_princ] + + +# Run t_enctypes with optional initiator and acceptor enctype lists, +# and check that it succeeds with the expected output. Also check +# that the ticket we got has the expected encryption key and session +# key. +def test(msg, ienc, aenc, tktenc='', tktsession='', proto='', isubkey='', + asubkey=None): + shutil.copyfile(os.path.join(realm.testdir, 'save'), realm.ccache) + # Run the test program and check its output. + out = realm.run(cmdline(ienc, aenc)).split() + if out[0] != proto or out[1] != isubkey: + fail(msg) + if asubkey is not None and (len(out) < 3 or out[2] != asubkey): + fail(msg) + lines = realm.run([klist, '-e']).splitlines() + for ind, line in enumerate(lines): + if realm.host_princ in line: + if lines[ind + 1].strip() != ('Etype (skey, tkt): %s, %s' % + (tktsession, tktenc)): + fail(msg) + break + +# Run t_enctypes with optional initiator and acceptor enctype lists, +# and check that it fails with the expected error message. +def test_err(msg, ienc, aenc, expected_err): + shutil.copyfile(os.path.join(realm.testdir, 'save'), realm.ccache) + realm.run(cmdline(ienc, aenc), expected_code=1, expected_msg=expected_err) + + +# By default, all of the key enctypes should be aes256. +test('noargs', None, None, + tktenc=aes256, tktsession=aes256, + proto='cfx', isubkey=aes256, asubkey=aes256) + +# When the initiator constrains the permitted session enctypes to +# aes128, the ticket encryption key should remain aes256. The client +# initiator will not send an RFC 4537 upgrade list because it sees no +# other permitted enctypes, so the acceptor subkey will not be +# upgraded from aes128. +test('init aes128', 'aes128-cts', None, + tktenc=aes256, tktsession=aes128, + proto='cfx', isubkey=aes128, asubkey=aes128) + +# If the initiator and acceptor both constrain the permitted session +# enctypes to aes128, we should see the same keys as above. This +# tests that the acceptor does not mistakenly contrain the ticket +# encryption key. +test('both aes128', 'aes128-cts', 'aes128-cts', + tktenc=aes256, tktsession=aes128, + proto='cfx', isubkey=aes128, asubkey=aes128) + +# If only the acceptor constrains the permitted session enctypes to +# aes128, subkey negotiation fails because the acceptor considers the +# aes256 session key to be non-permitted. +test_err('acc aes128', None, 'aes128-cts', + 'Encryption type aes256-cts-hmac-sha1-96 not permitted') + +# If the initiator constrains the permitted session enctypes to des3, +# no acceptor subkey will be generated because we can't upgrade to a +# CFX enctype. +test('init des3', 'des3', None, + tktenc=aes256, tktsession=d_des3, + proto='rfc1964', isubkey=des3raw, asubkey=None) + +# Force the ticket session key to be rc4, so we can test some subkey +# upgrade cases. The ticket encryption key remains aes256. +realm.run([kadminl, 'setstr', realm.host_princ, 'session_enctypes', 'rc4']) + +# With no arguments, the initiator should send an upgrade list of +# [aes256 aes128 des3] and the acceptor should upgrade to an aes256 +# subkey. +test('upgrade noargs', None, None, + tktenc=aes256, tktsession=d_rc4, + proto='cfx', isubkey=rc4, asubkey=aes256) + +# If the initiator won't permit rc4 as a session key, it won't be able +# to get a ticket. +test_err('upgrade init aes', 'aes', None, 'no support for encryption type') + +# If the initiator permits rc4 but prefers aes128, it will send an +# upgrade list of [aes128] and the acceptor will upgrade to aes128. +test('upgrade init aes128+rc4', 'aes128-cts rc4', None, + tktenc=aes256, tktsession=d_rc4, + proto='cfx', isubkey=rc4, asubkey=aes128) + +# If the initiator permits rc4 but prefers des3, it will send an +# upgrade list of [des3], but the acceptor won't generate a subkey +# because des3 isn't a CFX enctype. +test('upgrade init des3+rc4', 'des3 rc4', None, + tktenc=aes256, tktsession=d_rc4, + proto='rfc1964', isubkey=rc4, asubkey=None) + +# If the acceptor permits only aes128, subkey negotiation will fail +# because the ticket session key and initiator subkey are +# non-permitted. (This is unfortunate if the acceptor's restriction +# is only for the sake of the kernel, since we could upgrade to an +# aes128 subkey, but it's the current semantics.) +test_err('upgrade acc aes128', None, 'aes128-cts', + 'Encryption type arcfour-hmac not permitted') + +# If the acceptor permits rc4 but prefers aes128, it will negotiate an +# upgrade to aes128. +test('upgrade acc aes128 rc4', None, 'aes128-cts rc4', + tktenc=aes256, tktsession=d_rc4, + proto='cfx', isubkey=rc4, asubkey=aes128) + +# In this test, the initiator and acceptor each prefer an AES enctype +# to rc4, but they can't agree on which one, so no subkey is +# generated. +test('upgrade mismatch', 'aes128-cts rc4', 'aes256-cts rc4', + tktenc=aes256, tktsession=d_rc4, + proto='rfc1964', isubkey=rc4, asubkey=None) + +success('gss_krb5_set_allowable_enctypes tests') diff --git a/krb5-1.21.3/src/tests/gssapi/t_err.c b/krb5-1.21.3/src/tests/gssapi/t_err.c new file mode 100644 index 00000000..3a9c47bd --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_err.c @@ -0,0 +1,126 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_err.c - Test accept_sec_context error generation */ +/* + * 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. + */ + +/* + * This test program verifies that the krb5 gss_accept_sec_context can produce + * error tokens and that gss_init_sec_context can interpret them. + */ + +#include +#include +#include +#include + +#include "common.h" + +static void +check_replay_error(const char *msg, OM_uint32 major, OM_uint32 minor) +{ + OM_uint32 tmpmin, msg_ctx = 0; + const char *replay = "Request is a replay"; + gss_buffer_desc m; + + if (major != GSS_S_FAILURE) { + fprintf(stderr, "%s: expected major code GSS_S_FAILURE\n", msg); + check_gsserr(msg, major, minor); + exit(1); + } + + (void)gss_display_status(&tmpmin, minor, GSS_C_MECH_CODE, GSS_C_NULL_OID, + &msg_ctx, &m); + if (m.length != strlen(replay) || memcmp(m.value, replay, m.length) != 0) { + fprintf(stderr, "%s: expected replay error; got %.*s\n", msg, + (int)m.length, (char *)m.value); + exit(1); + } + (void)gss_release_buffer(&tmpmin, &m); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major, flags; + gss_OID mech = &mech_krb5; + gss_name_t tname; + gss_buffer_desc itok, atok; + gss_ctx_id_t ictx = GSS_C_NO_CONTEXT, actx = GSS_C_NO_CONTEXT; + + argv++; + if (*argv != NULL && strcmp(*argv, "--spnego") == 0) { + mech = &mech_spnego; + argv++; + } + if (*argv == NULL || argv[1] != NULL) { + fprintf(stderr, "Usage: t_err targetname\n"); + return 1; + } + tname = import_name(*argv); + + /* Get the initial context token. */ + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_MUTUAL_FLAG; + major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ictx, tname, + mech, flags, GSS_C_INDEFINITE, + GSS_C_NO_CHANNEL_BINDINGS, GSS_C_NO_BUFFER, + NULL, &itok, NULL, NULL); + check_gsserr("gss_init_sec_context(1)", major, minor); + assert(major == GSS_S_CONTINUE_NEEDED); + + /* Process this token into an acceptor context, then discard it. */ + major = gss_accept_sec_context(&minor, &actx, GSS_C_NO_CREDENTIAL, &itok, + GSS_C_NO_CHANNEL_BINDINGS, NULL, + NULL, &atok, NULL, NULL, NULL); + check_gsserr("gss_accept_sec_context(1)", major, minor); + (void)gss_release_buffer(&minor, &atok); + (void)gss_delete_sec_context(&minor, &actx, NULL); + + /* Process the same token again, producing a replay error. */ + major = gss_accept_sec_context(&minor, &actx, GSS_C_NO_CREDENTIAL, &itok, + GSS_C_NO_CHANNEL_BINDINGS, NULL, + NULL, &atok, NULL, NULL, NULL); + check_replay_error("gss_accept_sec_context(2)", major, minor); + assert(atok.length != 0); + + /* Send the error token back the initiator. */ + (void)gss_release_buffer(&minor, &itok); + major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ictx, tname, + mech, flags, GSS_C_INDEFINITE, + GSS_C_NO_CHANNEL_BINDINGS, &atok, + NULL, &itok, NULL, NULL); + check_replay_error("gss_init_sec_context(2)", major, minor); + + (void)gss_release_name(&minor, &tname); + (void)gss_release_buffer(&minor, &itok); + (void)gss_release_buffer(&minor, &atok); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_export_cred.c b/krb5-1.21.3/src/tests/gssapi/t_export_cred.c new file mode 100644 index 00000000..4d7c028e --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_export_cred.c @@ -0,0 +1,115 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2011 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include + +#include "common.h" + +/* Display a usage error message and exit. */ +static void +usage(void) +{ + fprintf(stderr, "Usage: t_export_cred [-k|-s] [-i initiatorname] " + "[-a acceptorname] targetname\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 major, minor, flags; + gss_name_t initiator_name = GSS_C_NO_NAME, acceptor_name = GSS_C_NO_NAME; + gss_name_t target_name; + gss_cred_id_t initiator_cred, acceptor_cred, delegated_cred; + gss_ctx_id_t initiator_context = GSS_C_NO_CONTEXT; + gss_ctx_id_t acceptor_context = GSS_C_NO_CONTEXT; + gss_OID mech = GSS_C_NO_OID; + gss_OID_set mechs = GSS_C_NO_OID_SET; + char optchar; + + /* Parse arguments. */ + argv++; + while (*argv != NULL && **argv == '-') { + optchar = (*argv)[1]; + argv++; + if (optchar == 'i') { + if (*argv == NULL) + usage(); + initiator_name = import_name(*argv++); + } else if (optchar == 'a') { + if (*argv == NULL) + usage(); + acceptor_name = import_name(*argv++); + } else if (optchar == 'k') { + mech = &mech_krb5; + mechs = &mechset_krb5; + } else if (optchar == 's') { + mech = &mech_spnego; + mechs = &mechset_spnego; + } else { + usage(); + } + } + if (*argv == NULL || *(argv + 1) != NULL) + usage(); + target_name = import_name(argv[0]); + + /* Get initiator cred and export/import it. */ + major = gss_acquire_cred(&minor, initiator_name, GSS_C_INDEFINITE, mechs, + GSS_C_INITIATE, &initiator_cred, NULL, NULL); + check_gsserr("gss_acquire_cred(initiator)", major, minor); + export_import_cred(&initiator_cred); + + /* Get acceptor cred and export/import it. */ + major = gss_acquire_cred(&minor, acceptor_name, GSS_C_INDEFINITE, mechs, + GSS_C_ACCEPT, &acceptor_cred, NULL, NULL); + check_gsserr("gss_acquire_cred(acceptor)", major, minor); + export_import_cred(&acceptor_cred); + + /* Initiate and accept a security context (one-token exchange only), + * delegating credentials. */ + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG | + GSS_C_INTEG_FLAG | GSS_C_DELEG_FLAG; + establish_contexts(mech, initiator_cred, acceptor_cred, target_name, flags, + &initiator_context, &acceptor_context, NULL, NULL, + &delegated_cred); + + /* Import, release, export, and store delegated creds */ + export_import_cred(&delegated_cred); + major = gss_store_cred(&minor, delegated_cred, GSS_C_INITIATE, + GSS_C_NULL_OID, 1, 1, NULL, NULL); + check_gsserr("gss_store_cred", major, minor); + + (void)gss_release_name(&minor, &initiator_name); + (void)gss_release_name(&minor, &acceptor_name); + (void)gss_release_name(&minor, &target_name); + (void)gss_release_cred(&minor, &initiator_cred); + (void)gss_release_cred(&minor, &acceptor_cred); + (void)gss_release_cred(&minor, &delegated_cred); + (void)gss_delete_sec_context(&minor, &initiator_context, NULL); + (void)gss_delete_sec_context(&minor, &acceptor_context, NULL); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_export_cred.py b/krb5-1.21.3/src/tests/gssapi/t_export_cred.py new file mode 100755 index 00000000..89167bcc --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_export_cred.py @@ -0,0 +1,50 @@ +from k5test import * + +# Test gss_export_cred and gss_import_cred for initiator creds, +# acceptor creds, and traditional delegated creds. t_s4u.py tests +# exporting and importing a synthesized S4U2Proxy delegated +# credential. + +# Make up a filename to hold user's initial credentials. +def ccache_savefile(realm): + return os.path.join(realm.testdir, 'ccache.copy') + +# Move user's initial credentials into the save file. +def ccache_save(realm): + os.rename(realm.ccache, ccache_savefile(realm)) + +# Copy user's initial credentials from the save file into the ccache. +def ccache_restore(realm): + shutil.copyfile(ccache_savefile(realm), realm.ccache) + +# Run t_export_cred with the saved ccache and verify that it stores a +# forwarded cred into the default ccache. +def check(realm, args): + ccache_restore(realm) + realm.run(['./t_export_cred'] + args) + realm.run([klist, '-f'], expected_msg='Flags: Ff') + +# Check a given set of arguments with no specified mech and with krb5 +# and SPNEGO as the specified mech. +def check_mechs(realm, args): + check(realm, args) + check(realm, ['-k'] + args) + check(realm, ['-s'] + args) + +# Make a realm, get forwardable tickets, and save a copy for each test. +realm = K5Realm(get_creds=False) +realm.kinit(realm.user_princ, password('user'), ['-f']) +ccache_save(realm) + +# Test with default initiator and acceptor cred. +tname = 'p:' + realm.host_princ +check_mechs(realm, [tname]) + +# Test with principal-named initiator and acceptor cred. +iname = 'p:' + realm.user_princ +check_mechs(realm, ['-i', iname, '-a', tname, tname]) + +# Test with host-based acceptor cred. +check_mechs(realm, ['-a', 'h:host', tname]) + +success('gss_export_cred/gss_import_cred tests') diff --git a/krb5-1.21.3/src/tests/gssapi/t_export_name.c b/krb5-1.21.3/src/tests/gssapi/t_export_name.c new file mode 100644 index 00000000..b7eebd4e --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_export_name.c @@ -0,0 +1,119 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_export_name.c - Test program for gss_export_name behavior */ +/* + * Copyright 2012 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Test program for gss_export_name, intended to be run from a Python test + * script. Imports a name, canonicalizes it to a mech, exports it, + * re-imports/exports it to compare results, and then prints the hex form of + * the exported name followed by a newline. + * + * Usage: ./t_export_name [-k|-s] user:username|krb5:princ|host:service@host + * + * The name is imported as a username, krb5 principal, or hostbased name. + * By default or with -k, the name is canonicalized to the krb5 mech; -s + * indicates SPNEGO instead. + */ + +#include +#include +#include + +#include "common.h" + +static void +usage(void) +{ + fprintf(stderr, "Usage: t_export_name [-k|-s] name\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major; + gss_OID mech = (gss_OID)gss_mech_krb5; + gss_name_t name, mechname, impname; + gss_buffer_desc buf, buf2; + krb5_boolean use_composite = FALSE; + gss_OID ntype; + const char *name_arg; + char opt; + + /* Parse arguments. */ + while (argc > 1 && argv[1][0] == '-') { + opt = argv[1][1]; + argc--, argv++; + if (opt == 'k') + mech = &mech_krb5; + else if (opt == 's') + mech = &mech_spnego; + else if (opt == 'c') + use_composite = TRUE; + else + usage(); + } + if (argc != 2) + usage(); + name_arg = argv[1]; + + /* Import the name. */ + name = import_name(name_arg); + + /* Canonicalize and export the name. */ + major = gss_canonicalize_name(&minor, name, mech, &mechname); + check_gsserr("gss_canonicalize_name", major, minor); + if (use_composite) + major = gss_export_name_composite(&minor, mechname, &buf); + else + major = gss_export_name(&minor, mechname, &buf); + check_gsserr("gss_export_name", major, minor); + + /* Import and re-export the name, and compare the results. */ + ntype = use_composite ? GSS_C_NT_COMPOSITE_EXPORT : GSS_C_NT_EXPORT_NAME; + major = gss_import_name(&minor, &buf, ntype, &impname); + check_gsserr("gss_import_name", major, minor); + if (use_composite) + major = gss_export_name_composite(&minor, impname, &buf2); + else + major = gss_export_name(&minor, impname, &buf2); + check_gsserr("gss_export_name", major, minor); + if (buf.length != buf2.length || + memcmp(buf.value, buf2.value, buf.length) != 0) { + fprintf(stderr, "Mismatched results:\n"); + print_hex(stderr, &buf); + print_hex(stderr, &buf2); + return 1; + } + + print_hex(stdout, &buf); + + (void)gss_release_name(&minor, &name); + (void)gss_release_name(&minor, &mechname); + (void)gss_release_name(&minor, &impname); + (void)gss_release_buffer(&minor, &buf); + (void)gss_release_buffer(&minor, &buf2); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_gssapi.py b/krb5-1.21.3/src/tests/gssapi/t_gssapi.py new file mode 100755 index 00000000..5f093a19 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_gssapi.py @@ -0,0 +1,226 @@ +from k5test import * + +# Test krb5 negotiation under SPNEGO for all enctype configurations. Also +# test IOV wrap/unwrap with and without SPNEGO. +for realm in multipass_realms(): + realm.run(['./t_spnego','p:' + realm.host_princ, realm.keytab]) + realm.run(['./t_iov', 'p:' + realm.host_princ]) + realm.run(['./t_iov', '-s', 'p:' + realm.host_princ]) + realm.run(['./t_pcontok', 'p:' + realm.host_princ]) + +realm = K5Realm() + +# Test gss_add_cred(). +realm.run(['./t_add_cred']) + +### Test acceptor name behavior. + +# Create some host-based principals and put most of them into the +# keytab. Rename one principal so that the keytab name matches the +# key but not the client name. +realm.run([kadminl, 'addprinc', '-randkey', 'service1/abraham']) +realm.run([kadminl, 'addprinc', '-randkey', 'service1/barack']) +realm.run([kadminl, 'addprinc', '-randkey', 'service2/calvin']) +realm.run([kadminl, 'addprinc', '-randkey', 'service2/dwight']) +realm.run([kadminl, 'addprinc', '-randkey', 'host/-nomatch-']) +realm.run([kadminl, 'addprinc', '-randkey', 'http/localhost']) +realm.run([kadminl, 'xst', 'service1/abraham']) +realm.run([kadminl, 'xst', 'service1/barack']) +realm.run([kadminl, 'xst', 'service2/calvin']) +realm.run([kadminl, 'xst', 'http/localhost']) +realm.run([kadminl, 'renprinc', 'service1/abraham', 'service1/andrew']) + +# Test with no default realm and no dots in the server name. +realm.run(['./t_accname', 'h:http@localhost'], expected_msg='http/localhost') +remove_default = {'libdefaults': {'default_realm': None}} +no_default = realm.special_env('no_default', False, krb5_conf=remove_default) +realm.run(['./t_accname', 'h:http@localhost'], expected_msg='http/localhost', + env=no_default) + +# Test with no acceptor name, including client/keytab principal +# mismatch (non-fatal) and missing keytab entry (fatal). +realm.run(['./t_accname', 'p:service1/andrew'], + expected_msg='service1/abraham') +realm.run(['./t_accname', 'p:service1/barack'], expected_msg='service1/barack') +realm.run(['./t_accname', 'p:service2/calvin'], expected_msg='service2/calvin') +realm.run(['./t_accname', 'p:service2/dwight'], expected_code=1, + expected_msg=' not found in keytab') + +# Test with acceptor name containing service only, including +# client/keytab hostname mismatch (non-fatal) and service name +# mismatch (fatal). +realm.run(['./t_accname', 'p:service1/andrew', 'h:service1'], + expected_msg='service1/abraham') +realm.run(['./t_accname', 'p:service1/andrew', 'h:service2'], expected_code=1, + expected_msg=' not found in keytab') +realm.run(['./t_accname', 'p:service2/calvin', 'h:service2'], + expected_msg='service2/calvin') +realm.run(['./t_accname', 'p:service2/calvin', 'h:service1'], expected_code=1, + expected_msg=' found in keytab but does not match server principal') +# Regression test for #8892 (trailing @ in name). +realm.run(['./t_accname', 'p:service1/andrew', 'h:service1@'], + expected_msg='service1/abraham') + +# Test with acceptor name containing service and host. Use the +# client's un-canonicalized hostname as acceptor input to mirror what +# many servers do. +realm.run(['./t_accname', 'p:' + realm.host_princ, + 'h:host@%s' % socket.gethostname()], expected_msg=realm.host_princ) +realm.run(['./t_accname', 'p:host/-nomatch-', + 'h:host@%s' % socket.gethostname()], expected_code=1, + expected_msg=' not found in keytab') + +# If possible, test with an acceptor name requiring fallback to match +# against a keytab entry. +canonname = canonicalize_hostname(hostname) +if canonname != hostname: + os.rename(realm.keytab, realm.keytab + '.save') + canonprinc = 'host/' + canonname + realm.run([kadminl, 'addprinc', '-randkey', canonprinc]) + realm.extract_keytab(canonprinc, realm.keytab) + # Use the canonical name for the initiator's target name, since + # host/hostname exists in the KDB (but not the keytab). + realm.run(['./t_accname', 'h:host@' + canonname, 'h:host@' + hostname]) + os.rename(realm.keytab + '.save', realm.keytab) +else: + skipped('GSS acceptor name fallback test', + '%s does not canonicalize to a different name' % hostname) + +# Test krb5_gss_import_cred. +realm.run(['./t_imp_cred', 'p:service1/barack']) +realm.run(['./t_imp_cred', 'p:service1/barack', 'service1/barack']) +realm.run(['./t_imp_cred', 'p:service1/andrew', 'service1/abraham']) +realm.run(['./t_imp_cred', 'p:service2/dwight'], expected_code=1, + expected_msg=' not found in keytab') + +# Verify that we can't acquire acceptor creds without a keytab. +os.remove(realm.keytab) +out = realm.run(['./t_accname', 'p:abc'], expected_code=1) +if ('gss_acquire_cred: Keytab' not in out or + 'nonexistent or empty' not in out): + fail('Expected error message not seen for nonexistent keytab') + +realm.stop() + +# Re-run the last acceptor name test with ignore_acceptor_hostname set +# and the principal for the mismatching hostname in the keytab. +ignore_conf = {'libdefaults': {'ignore_acceptor_hostname': 'true'}} +realm = K5Realm(krb5_conf=ignore_conf) +realm.run([kadminl, 'addprinc', '-randkey', 'host/-nomatch-']) +realm.run([kadminl, 'xst', 'host/-nomatch-']) +realm.run(['./t_accname', 'p:host/-nomatch-', + 'h:host@%s' % socket.gethostname()], expected_msg='host/-nomatch-') + +realm.stop() + +# Make sure a GSSAPI acceptor can handle cross-realm tickets with a +# transited field. (Regression test for #7639.) +r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)), + create_user=False, create_host=False, + args=[{'realm': 'A.X', 'create_user': True}, + {'realm': 'X'}, + {'realm': 'B.X', 'create_host': True}]) +os.rename(r3.keytab, r1.keytab) +r1.run(['./t_accname', 'p:' + r3.host_princ, 'h:host']) +r1.stop() +r2.stop() +r3.stop() + +### Test gss_inquire_cred behavior. + +realm = K5Realm() + +# Test deferred resolution of the default ccache for initiator creds. +realm.run(['./t_inq_cred'], expected_msg=realm.user_princ) +realm.run(['./t_inq_cred', '-k'], expected_msg=realm.user_princ) +realm.run(['./t_inq_cred', '-s'], expected_msg=realm.user_princ) + +# Test picking a name from the keytab for acceptor creds. +realm.run(['./t_inq_cred', '-a'], expected_msg=realm.host_princ) +realm.run(['./t_inq_cred', '-k', '-a'], expected_msg=realm.host_princ) +realm.run(['./t_inq_cred', '-s', '-a'], expected_msg=realm.host_princ) + +# Test client keytab initiation (non-deferred) with a specified name. +realm.extract_keytab(realm.user_princ, realm.client_keytab) +os.remove(realm.ccache) +realm.run(['./t_inq_cred', '-k'], expected_msg=realm.user_princ) + +# Test deferred client keytab initiation and GSS_C_BOTH cred usage. +os.remove(realm.client_keytab) +os.remove(realm.ccache) +shutil.copyfile(realm.keytab, realm.client_keytab) +realm.run(['./t_inq_cred', '-k', '-b'], expected_msg=realm.host_princ) + +# Test gss_export_name behavior. +realm.run(['./t_export_name', 'u:x'], expected_msg=\ + '0401000B06092A864886F7120102020000000D78404B5242544553542E434F4D\n') +realm.run(['./t_export_name', '-s', 'u:xyz'], + expected_msg='0401000806062B06010505020000000378797A\n') +realm.run(['./t_export_name', 'p:a@b'], + expected_msg='0401000B06092A864886F71201020200000003614062\n') +realm.run(['./t_export_name', '-s', 'p:a@b'], + expected_msg='0401000806062B060105050200000003614062\n') + +# Test that composite-export tokens can be imported. +realm.run(['./t_export_name', '-c', 'p:a@b'], expected_msg= + '0402000B06092A864886F7120102020000000361406200000000\n') + +# Test gss_inquire_mechs_for_name behavior. +krb5_mech = '{ 1 2 840 113554 1 2 2 }' +spnego_mech = '{ 1 3 6 1 5 5 2 }' +out = realm.run(['./t_inq_mechs_name', 'p:a@b']) +if krb5_mech not in out: + fail('t_inq_mechs_name (principal)') +out = realm.run(['./t_inq_mechs_name', 'u:x']) +if krb5_mech not in out or spnego_mech not in out: + fail('t_inq_mecs_name (user)') +out = realm.run(['./t_inq_mechs_name', 'h:host']) +if krb5_mech not in out or spnego_mech not in out: + fail('t_inq_mecs_name (hostbased)') + +# Test that accept_sec_context can produce an error token and +# init_sec_context can interpret it. +realm.run(['./t_err', 'p:' + realm.host_princ]) +realm.run(['./t_err', '--spnego', 'p:' + realm.host_princ]) + +# Test the GSS_KRB5_CRED_NO_CI_FLAGS_X cred option. +realm.run(['./t_ciflags', 'p:' + realm.host_princ]) + +# Test that inquire_context works properly, even on incomplete +# contexts. +realm.run(['./t_inq_ctx', 'user', password('user'), 'p:%s' % realm.host_princ]) + +if runenv.sizeof_time_t <= 4: + skip_rest('y2038 GSSAPI tests', 'platform has 32-bit time_t') + +# Test lifetime results, using a realm with a large maximum lifetime +# so that we can test ticket end dates after y2038. +realm.stop() +conf = {'realms': {'$realm': {'max_life': '9000d'}}} +realm = K5Realm(kdc_conf=conf, get_creds=False) + +# Check a lifetime string result against an expected number value (or None). +# Allow some variance due to time elapsed during the tests. +def check_lifetime(msg, val, expected): + if expected is None and val != 'indefinite': + fail('%s: expected indefinite, got %s' % (msg, val)) + if expected is not None and val == 'indefinite': + fail('%s: expected %d, got indefinite' % (msg, expected)) + if expected is not None and abs(int(val) - expected) > 100: + fail('%s: expected %d, got %s' % (msg, expected, val)) + +realm.kinit(realm.user_princ, password('user'), flags=['-l', '8500d']) +out = realm.run(['./t_lifetime', 'p:' + realm.host_princ, str(8000 * 86400)]) +ln = out.split('\n') +check_lifetime('icred gss_acquire_cred', ln[0], 8500 * 86400) +check_lifetime('icred gss_inquire_cred', ln[1], 8500 * 86400) +check_lifetime('acred gss_acquire_cred', ln[2], None) +check_lifetime('acred gss_inquire_cred', ln[3], None) +check_lifetime('ictx gss_init_sec_context', ln[4], 8000 * 86400) +check_lifetime('ictx gss_inquire_context', ln[5], 8000 * 86400) +check_lifetime('ictx gss_context_time', ln[6], 8000 * 86400) +check_lifetime('actx gss_accept_sec_context', ln[7], 8000 * 86400 + 300) +check_lifetime('actx gss_inquire_context', ln[8], 8000 * 86400 + 300) +check_lifetime('actx gss_context_time', ln[9], 8000 * 86400 + 300) + +success('GSSAPI tests') diff --git a/krb5-1.21.3/src/tests/gssapi/t_gssexts.c b/krb5-1.21.3/src/tests/gssapi/t_gssexts.c new file mode 100644 index 00000000..41d62b92 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_gssexts.c @@ -0,0 +1,247 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include + +#include "common.h" + +/* + * Test program for protocol transition (S4U2Self) and constrained delegation + * (S4U2Proxy) + * + * Note: because of name canonicalization, the following tips may help + * when configuring with Active Directory: + * + * - Create a computer account FOO$ + * - Set the UPN to host/foo.domain (no suffix); this is necessary to + * be able to send an AS-REQ as this principal, otherwise you would + * need to use the canonical name (FOO$), which will cause principal + * comparison errors in gss_accept_sec_context(). + * - Add a SPN of host/foo.domain + * - Configure the computer account to support constrained delegation with + * protocol transition (Trust this computer for delegation to specified + * services only / Use any authentication protocol) + * - Add host/foo.domain to the keytab (possibly easiest to do this + * with ktadd) + * + * For S4U2Proxy to work the TGT must be forwardable too. + * + * Usage eg: + * + * kinit -k -t test.keytab -f 'host/test.win.mit.edu@WIN.MIT.EDU' + * ./t_s4u p:delegtest@WIN.MIT.EDU p:HOST/WIN-EQ7E4AA2WR8.win.mit.edu@WIN.MIT.EDU test.keytab + */ + +static int use_spnego = 0; + +static void +test_prf(gss_ctx_id_t initiatorContext, gss_ctx_id_t acceptorContext, + int flags) +{ + gss_buffer_desc constant; + OM_uint32 major, minor; + unsigned int i; + gss_buffer_desc initiatorPrf; + gss_buffer_desc acceptorPrf; + + constant.value = "gss prf test"; + constant.length = strlen((char *)constant.value); + + initiatorPrf.value = NULL; + acceptorPrf.value = NULL; + + major = gss_pseudo_random(&minor, initiatorContext, flags, &constant, 19, + &initiatorPrf); + check_gsserr("gss_pseudo_random", major, minor); + + printf("%s\n", flags == GSS_C_PRF_KEY_FULL ? + "PRF_KEY_FULL" : "PRF_KEY_PARTIAL"); + + printf("Initiator PRF: "); + for (i = 0; i < initiatorPrf.length; i++) + printf("%02x ", ((char *)initiatorPrf.value)[i] & 0xFF); + printf("\n"); + + major = gss_pseudo_random(&minor, acceptorContext, flags, &constant, 19, + &acceptorPrf); + check_gsserr("gss_pseudo_random", major, minor); + + printf("Acceptor PRF: "); + for (i = 0; i < acceptorPrf.length; i++) + printf("%02x ", ((char *)acceptorPrf.value)[i] & 0xFF); + printf("\n"); + + if (acceptorPrf.length != initiatorPrf.length || + memcmp(acceptorPrf.value, initiatorPrf.value, initiatorPrf.length)) { + fprintf(stderr, "Initiator and acceptor PRF output does not match\n"); + exit(1); + } + + (void)gss_release_buffer(&minor, &initiatorPrf); + (void)gss_release_buffer(&minor, &acceptorPrf); +} + +static void +init_accept_sec_context(gss_cred_id_t claimant_cred_handle, + gss_cred_id_t verifier_cred_handle, + gss_cred_id_t *deleg_cred_handle) +{ + OM_uint32 major, minor, flags; + gss_name_t source_name = GSS_C_NO_NAME, target_name = GSS_C_NO_NAME; + gss_ctx_id_t initiator_context, acceptor_context; + gss_OID mech; + + *deleg_cred_handle = GSS_C_NO_CREDENTIAL; + + major = gss_inquire_cred(&minor, verifier_cred_handle, &target_name, NULL, + NULL, NULL); + check_gsserr("gss_inquire_cred", major, minor); + display_canon_name("Target name", target_name, &mech_krb5); + + mech = use_spnego ? &mech_spnego : &mech_krb5; + display_oid("Target mech", mech); + + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + establish_contexts(mech, claimant_cred_handle, verifier_cred_handle, + target_name, flags, &initiator_context, + &acceptor_context, &source_name, NULL, + deleg_cred_handle); + + test_prf(initiator_context, acceptor_context, GSS_C_PRF_KEY_FULL); + test_prf(initiator_context, acceptor_context, GSS_C_PRF_KEY_PARTIAL); + + (void)gss_release_name(&minor, &source_name); + (void)gss_delete_sec_context(&minor, &acceptor_context, NULL); + (void)gss_delete_sec_context(&minor, &initiator_context, NULL); +} + +static void +get_default_cred(const char *keytab_name, gss_OID_set mechs, + gss_cred_id_t *impersonator_cred_handle) +{ + OM_uint32 major = GSS_S_FAILURE, minor; + krb5_error_code ret; + krb5_context context = NULL; + krb5_keytab keytab = NULL; + krb5_principal keytab_principal = NULL; + krb5_ccache ccache = NULL; + + if (keytab_name != NULL) { + ret = krb5_init_context(&context); + check_k5err(context, "krb5_init_context", ret); + + ret = krb5_kt_resolve(context, keytab_name, &keytab); + check_k5err(context, "krb5_kt_resolve", ret); + + ret = krb5_cc_default(context, &ccache); + check_k5err(context, "krb5_cc_default", ret); + + ret = krb5_cc_get_principal(context, ccache, &keytab_principal); + check_k5err(context, "krb5_cc_get_principal", ret); + + major = gss_krb5_import_cred(&minor, ccache, keytab_principal, keytab, + impersonator_cred_handle); + check_gsserr("gss_krb5_import_cred", major, minor); + + krb5_free_principal(context, keytab_principal); + krb5_cc_close(context, ccache); + krb5_kt_close(context, keytab); + krb5_free_context(context); + } else { + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE, + mechs, GSS_C_BOTH, impersonator_cred_handle, + NULL, NULL); + check_gsserr("gss_acquire_cred", major, minor); + } +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major; + gss_cred_id_t impersonator_cred_handle = GSS_C_NO_CREDENTIAL; + gss_cred_id_t user_cred_handle = GSS_C_NO_CREDENTIAL; + gss_cred_id_t delegated_cred_handle = GSS_C_NO_CREDENTIAL; + gss_name_t user = GSS_C_NO_NAME, target = GSS_C_NO_NAME; + gss_OID_set mechs, actual_mechs = GSS_C_NO_OID_SET; + uid_t uid; + + if (argc < 2 || argc > 5) { + fprintf(stderr, "Usage: %s [--spnego] [user] " + "[proxy-target] [keytab]\n", argv[0]); + fprintf(stderr, " proxy-target and keytab are optional\n"); + exit(1); + } + + if (strcmp(argv[1], "--spnego") == 0) { + use_spnego++; + argc--; + argv++; + } + + user = import_name(argv[1]); + + major = gss_pname_to_uid(&minor, user, NULL, &uid); + check_gsserr("gss_pname_to_uid(user)", major, minor); + + if (argc > 2 && strcmp(argv[2], "-") != 0) + target = import_name(argv[2]); + + mechs = use_spnego ? &mechset_spnego : &mechset_krb5; + + get_default_cred((argc > 3) ? argv[3] : NULL, mechs, + &impersonator_cred_handle); + + printf("Protocol transition tests follow\n"); + printf("-----------------------------------\n\n"); + + /* get S4U2Self cred */ + major = gss_acquire_cred_impersonate_name(&minor, impersonator_cred_handle, + user, GSS_C_INDEFINITE, mechs, + GSS_C_INITIATE, + &user_cred_handle, &actual_mechs, + NULL); + check_gsserr("gss_acquire_cred_impersonate_name", major, minor); + + /* Try to store it in default ccache */ + major = gss_store_cred(&minor, user_cred_handle, GSS_C_INITIATE, + &mechs->elements[0], 1, 1, NULL, NULL); + check_gsserr("gss_store_cred", major, minor); + + init_accept_sec_context(user_cred_handle, impersonator_cred_handle, + &delegated_cred_handle); + + printf("\n"); + + (void)gss_release_name(&minor, &user); + (void)gss_release_name(&minor, &target); + (void)gss_release_cred(&minor, &delegated_cred_handle); + (void)gss_release_cred(&minor, &impersonator_cred_handle); + (void)gss_release_cred(&minor, &user_cred_handle); + (void)gss_release_oid_set(&minor, &actual_mechs); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_imp_cred.c b/krb5-1.21.3/src/tests/gssapi/t_imp_cred.c new file mode 100644 index 00000000..a2aa5fba --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_imp_cred.c @@ -0,0 +1,101 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_imp_cred.c - krb5_gss_import_cred test harness */ +/* + * Copyright 2011 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Test program for krb5_gss_import_cred, intended to be run from a Python test + * script. Creates an initiator credential for the default ccache and an + * acceptor principal for the default keytab (possibly using a specified keytab + * principal), and performs a one-token context exchange using a specified + * target principal. If the exchange is successful, queries the context for + * the acceptor name and prints it. If any call is unsuccessful, displays an + * error message. Exits with status 0 if all operations are successful, or 1 + * if not. + * + * Usage: ./t_imp_cred target-princ [keytab-princ] + */ + +#include "k5-platform.h" +#include + +#include "common.h" + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major, flags; + gss_cred_id_t initiator_cred, acceptor_cred; + gss_ctx_id_t initiator_context, acceptor_context; + gss_name_t target_name; + krb5_context context = NULL; + krb5_ccache cc; + krb5_keytab kt; + krb5_principal princ = NULL; + krb5_error_code ret; + + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: %s targetname [acceptorprinc]\n", argv[0]); + return 1; + } + + /* Import the target name. */ + target_name = import_name(argv[1]); + + /* Acquire the krb5 objects we need. */ + ret = krb5_init_context(&context); + check_k5err(context, "krb5_init_context", ret); + ret = krb5_cc_default(context, &cc); + check_k5err(context, "krb5_cc_default", ret); + ret = krb5_kt_default(context, &kt); + check_k5err(context, "krb5_kt_default", ret); + if (argc >= 3) { + ret = krb5_parse_name(context, argv[2], &princ); + check_k5err(context, "krb5_parse_name", ret); + } + + /* Get initiator cred. */ + major = gss_krb5_import_cred(&minor, cc, NULL, NULL, &initiator_cred); + check_gsserr("gss_krb5_import_cred (initiator)", major, minor); + + /* Get acceptor cred. */ + major = gss_krb5_import_cred(&minor, NULL, princ, kt, &acceptor_cred); + check_gsserr("gss_krb5_import_cred (acceptor)", major, minor); + + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + establish_contexts(&mech_krb5, initiator_cred, acceptor_cred, target_name, + flags, &initiator_context, &acceptor_context, NULL, + NULL, NULL); + + krb5_cc_close(context, cc); + krb5_kt_close(context, kt); + krb5_free_principal(context, princ); + krb5_free_context(context); + (void)gss_release_name(&minor, &target_name); + (void)gss_release_cred(&minor, &initiator_cred); + (void)gss_release_cred(&minor, &acceptor_cred); + (void)gss_delete_sec_context(&minor, &initiator_context, NULL); + (void)gss_delete_sec_context(&minor, &acceptor_context, NULL); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_imp_name.c b/krb5-1.21.3/src/tests/gssapi/t_imp_name.c new file mode 100644 index 00000000..e7dbcc42 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_imp_name.c @@ -0,0 +1,94 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1996, Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Simple test program for testing how GSSAPI import name works. (May + * be made into a more full-fledged test program later.) + */ + +#include +#include + +#include "common.h" + +static const char * +oid_str(char type) +{ + switch (type) { + case 'p': /* GSS_KRB5_NT_PRINCIPAL_NAME */ + return "{ 1 2 840 113554 1 2 2 1 }"; + case 'e': /* GSS_KRB5_NT_ENTERPRISE_NAME */ + return "{ 1 2 840 113554 1 2 2 6 }"; + case 'c': /* GSS_KRB5_NT_X509_CERT */ + return "{ 1 2 840 113554 1 2 2 7 }"; + case 'h': /* GSS_C_NT_HOSTBASED_SERVICE */ + return "{ 1 2 840 113554 1 2 1 4 }"; + } + return "no_oid"; +} + +/* Return true if buf has the same contents as str, plus a zero byte if + * indicated by buf_includes_nullterm. */ +static int +buf_eq_str(gss_buffer_t buf, const char *str, int buf_includes_nullterm) +{ + size_t len = strlen(str) + (buf_includes_nullterm ? 1 : 0); + + return (buf->length == len && memcmp(buf->value, str, len) == 0); +} + +static void +test_import_name(const char *name) +{ + OM_uint32 major, minor; + gss_name_t gss_name; + gss_buffer_desc buf; + gss_OID name_oid; + + gss_name = import_name(name); + + major = gss_display_name(&minor, gss_name, &buf, &name_oid); + check_gsserr("gss_display_name", major, minor); + if (!buf_eq_str(&buf, name + 2, 0)) + errout("wrong name string"); + (void)gss_release_buffer(&minor, &buf); + + major = gss_oid_to_str(&minor, name_oid, &buf); + check_gsserr("gss_oid_to_str", major, minor); + if (!buf_eq_str(&buf, oid_str(*name), 1)) + errout("wrong name type"); + (void)gss_release_buffer(&minor, &buf); + (void)gss_release_name(&minor, &gss_name); +} + +int +main(int argc, char **argv) +{ + test_import_name("p:user@MIT.EDU"); + test_import_name("e:enterprise@mit.edu@MIT.EDU"); + test_import_name("h:HOST@dc1.mit.edu"); + + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_inq_cred.c b/krb5-1.21.3/src/tests/gssapi/t_inq_cred.c new file mode 100644 index 00000000..8dd331d6 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_inq_cred.c @@ -0,0 +1,116 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_inq_cred.c - Test program for gss_inquire_cred behavior */ +/* + * Copyright 2012 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Test program for gss_inquire_cred, intended to be run from a Python test + * script. Acquires credentials, inquires them, and prints the resulting name + * and lifetime. + * + * Usage: ./t_inq_cred [-k|-s] [-a|-b|-i] [initiatorname] + * + * By default no mechanism is specified when acquiring credentials; -k + * indicates the krb5 mech and -s indicates SPNEGO. By default or with -i, + * initiator credentials are acquired; -a indicates acceptor credentials and -b + * indicates credentials of both types. The credential is acquired with no + * name by default; a krb5 principal name or host-based name (prefixed with + * "gss:") may be supplied as an argument. + */ + +#include +#include +#include + +#include "common.h" + +static void +usage(void) +{ + fprintf(stderr, + "Usage: t_inq_cred [-k|-s] [-a|-b|-i] [princ|gss:service@host]\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major, lifetime; + gss_cred_usage_t cred_usage = GSS_C_INITIATE; + gss_OID_set mechs = GSS_C_NO_OID_SET; + gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; + gss_name_t name = GSS_C_NO_NAME; + gss_buffer_desc buf; + const char *name_arg = NULL; + char opt; + + while (argc > 1 && argv[1][0] == '-') { + opt = argv[1][1]; + argc--, argv++; + if (opt == 'a') + cred_usage = GSS_C_ACCEPT; + else if (opt == 'b') + cred_usage = GSS_C_BOTH; + else if (opt == 'i') + cred_usage = GSS_C_INITIATE; + else if (opt == 'k') + mechs = &mechset_krb5; + else if (opt == 's') + mechs = &mechset_spnego; + else + usage(); + } + if (argc > 2) + usage(); + if (argc > 1) + name_arg = argv[1]; + + /* Import the name, if given. */ + if (name_arg != NULL) + name = import_name(name_arg); + + /* Acquire a credential. */ + major = gss_acquire_cred(&minor, name, GSS_C_INDEFINITE, mechs, cred_usage, + &cred, NULL, NULL); + check_gsserr("gss_acquire_cred", major, minor); + + /* Inquire about the credential. */ + (void)gss_release_name(&minor, &name); + major = gss_inquire_cred(&minor, cred, &name, &lifetime, NULL, NULL); + check_gsserr("gss_inquire_cred", major, minor); + + /* Get a display form of the name. */ + buf.value = NULL; + buf.length = 0; + major = gss_display_name(&minor, name, &buf, NULL); + check_gsserr("gss_display_name", major, minor); + + printf("name: %.*s\n", (int)buf.length, (char *)buf.value); + printf("lifetime: %d\n", (int)lifetime); + + (void)gss_release_cred(&minor, &cred); + (void)gss_release_name(&minor, &name); + (void)gss_release_buffer(&minor, &buf); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_inq_ctx.c b/krb5-1.21.3/src/tests/gssapi/t_inq_ctx.c new file mode 100644 index 00000000..c59ca382 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_inq_ctx.c @@ -0,0 +1,241 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2015 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include +#include + +#include "common.h" + + +/* + * Test program for inquiring about a security context, intended to be run from + * a Python test script. Partially establishes a context to test inquiring + * about an incomplete context, and then establishes full contexts and inquires + * them. Exits with status 0 if all operations are successful, or 1 if not. + * + * Usage: ./t_inq_ctx target_name + */ + +static void +check_inq_context(gss_ctx_id_t context, int incomplete, gss_OID expected_mech, + OM_uint32 expected_flags, int expected_locally_init) +{ + OM_uint32 major, minor; + gss_name_t out_init_name, out_accept_name; + OM_uint32 out_lifetime; + gss_OID out_mech_type; + OM_uint32 out_flags; + int out_locally_init; + int out_open; + + major = gss_inquire_context(&minor, context, &out_init_name, + &out_accept_name, &out_lifetime, + &out_mech_type, &out_flags, &out_locally_init, + &out_open); + check_gsserr("gss_inquire_context", major, minor); + + assert(gss_oid_equal(out_mech_type, expected_mech)); + assert(out_flags == expected_flags); + assert(out_locally_init == expected_locally_init); + if (incomplete) { + assert(!out_open); + assert(out_lifetime == 0); + assert(out_init_name == GSS_C_NO_NAME); + assert(out_accept_name == GSS_C_NO_NAME); + } else { + assert(out_open); + assert(out_lifetime > 0); + assert(out_init_name != GSS_C_NO_NAME); + assert(out_accept_name != GSS_C_NO_NAME); + } + + (void)gss_release_name(&minor, &out_accept_name); + (void)gss_release_name(&minor, &out_init_name); +} + +/* Call gss_init_sec_context() once to create an initiator context (which will + * be partial if flags includes GSS_C_MUTUAL_FLAG and the mech is krb5). */ +static void +start_init_context(gss_OID mech, gss_cred_id_t cred, gss_name_t tname, + OM_uint32 flags, gss_ctx_id_t *ctx) +{ + OM_uint32 major, minor; + gss_buffer_desc itok = GSS_C_EMPTY_BUFFER; + + *ctx = GSS_C_NO_CONTEXT; + major = gss_init_sec_context(&minor, cred, ctx, tname, mech, flags, + GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, + NULL, NULL, &itok, NULL, NULL); + check_gsserr("gss_init_sec_context", major, minor); + (void)gss_release_buffer(&minor, &itok); +} + +/* Call gss_init_sec_context() and gss_accept_sec_context() once to create an + * acceptor context. */ +static void +start_accept_context(gss_OID mech, gss_cred_id_t icred, gss_cred_id_t acred, + gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ctx) +{ + OM_uint32 major, minor; + gss_ctx_id_t ictx = GSS_C_NO_CONTEXT; + gss_buffer_desc itok = GSS_C_EMPTY_BUFFER, atok = GSS_C_EMPTY_BUFFER; + + major = gss_init_sec_context(&minor, icred, &ictx, tname, mech, flags, + GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, + NULL, NULL, &itok, NULL, NULL); + check_gsserr("gss_init_sec_context", major, minor); + + *ctx = GSS_C_NO_CONTEXT; + major = gss_accept_sec_context(&minor, ctx, acred, &itok, + GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL, + &atok, NULL, NULL, NULL); + check_gsserr("gss_accept_sec_context", major, minor); + + (void)gss_release_buffer(&minor, &itok); + (void)gss_release_buffer(&minor, &atok); + (void)gss_delete_sec_context(&minor, &ictx, NULL); +} + +static void +partial_iakerb_acceptor(const char *username, const char *password, + gss_name_t tname, OM_uint32 flags, gss_ctx_id_t *ctx) +{ + OM_uint32 major, minor; + gss_name_t name; + gss_buffer_desc ubuf, pwbuf; + gss_OID_set_desc mechlist; + gss_cred_id_t icred, acred; + + mechlist.count = 1; + mechlist.elements = &mech_iakerb; + + /* Import the username. */ + ubuf.value = (void *)username; + ubuf.length = strlen(username); + major = gss_import_name(&minor, &ubuf, GSS_C_NT_USER_NAME, &name); + check_gsserr("gss_import_name", major, minor); + + /* Create an IAKERB initiator cred with the username and password. */ + pwbuf.value = (void *)password; + pwbuf.length = strlen(password); + major = gss_acquire_cred_with_password(&minor, name, &pwbuf, 0, + &mechlist, GSS_C_INITIATE, &icred, + NULL, NULL); + check_gsserr("gss_acquire_cred_with_password", major, minor); + + /* Create an acceptor cred with support for IAKERB. */ + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE, + &mechlist, GSS_C_ACCEPT, &acred, NULL, NULL); + check_gsserr("gss_acquire_cred", major, minor); + + /* Begin context establishment to get a partial acceptor context. */ + start_accept_context(&mech_iakerb, icred, acred, tname, flags, ctx); + + (void)gss_release_name(&minor, &name); + (void)gss_release_cred(&minor, &icred); + (void)gss_release_cred(&minor, &acred); +} + +/* Create a partially established SPNEGO acceptor. */ +static void +partial_spnego_acceptor(gss_name_t tname, gss_ctx_id_t *ctx) +{ + OM_uint32 major, minor; + gss_buffer_desc itok = GSS_C_EMPTY_BUFFER, atok; + + /* + * We could construct a fixed SPNEGO initiator token which forces a + * renegotiation, but a simpler approach is to pass an empty token to + * gss_accept_sec_context(), taking advantage of our compatibility support + * for SPNEGO NegHints. + */ + *ctx = GSS_C_NO_CONTEXT; + major = gss_accept_sec_context(&minor, ctx, GSS_C_NO_CREDENTIAL, &itok, + GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL, + &atok, NULL, NULL, NULL); + check_gsserr("gss_accept_sec_context(neghints)", major, minor); + + (void)gss_release_buffer(&minor, &atok); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, flags, dce_flags; + gss_name_t tname; + gss_ctx_id_t ictx, actx; + const char *username, *password; + + if (argc != 4) { + fprintf(stderr, "Usage: %s username password targetname\n", argv[0]); + return 1; + } + username = argv[1]; + password = argv[2]; + tname = import_name(argv[3]); + + flags = GSS_C_SEQUENCE_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_CONF_FLAG | + GSS_C_INTEG_FLAG; + start_init_context(&mech_krb5, GSS_C_NO_CREDENTIAL, tname, flags, &ictx); + check_inq_context(ictx, 1, &mech_krb5, flags | GSS_C_TRANS_FLAG, 1); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + + start_init_context(&mech_iakerb, GSS_C_NO_CREDENTIAL, tname, flags, &ictx); + check_inq_context(ictx, 1, &mech_iakerb, flags, 1); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + + start_init_context(&mech_spnego, GSS_C_NO_CREDENTIAL, tname, flags, &ictx); + check_inq_context(ictx, 1, &mech_spnego, flags, 1); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + + dce_flags = flags | GSS_C_DCE_STYLE; + start_accept_context(&mech_krb5, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, + tname, dce_flags, &actx); + check_inq_context(actx, 1, &mech_krb5, dce_flags | GSS_C_TRANS_FLAG, 0); + (void)gss_delete_sec_context(&minor, &actx, NULL); + + partial_iakerb_acceptor(username, password, tname, flags, &actx); + check_inq_context(actx, 1, &mech_iakerb, 0, 0); + (void)gss_delete_sec_context(&minor, &actx, NULL); + + partial_spnego_acceptor(tname, &actx); + check_inq_context(actx, 1, &mech_spnego, 0, 0); + (void)gss_delete_sec_context(&minor, &actx, NULL); + + establish_contexts(&mech_krb5, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, + tname, flags, &ictx, &actx, NULL, NULL, NULL); + + check_inq_context(ictx, 0, &mech_krb5, flags | GSS_C_TRANS_FLAG, 1); + check_inq_context(actx, 0, &mech_krb5, + flags | GSS_C_TRANS_FLAG | GSS_C_PROT_READY_FLAG, 0); + + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + + (void)gss_release_name(&minor, &tname); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_inq_mechs_name.c b/krb5-1.21.3/src/tests/gssapi/t_inq_mechs_name.c new file mode 100644 index 00000000..9f4ae4e1 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_inq_mechs_name.c @@ -0,0 +1,64 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_inq_mechs_name.c - Exercise gss_inquire_mechs_for_name */ +/* + * Copyright (C) 2012 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. + */ + +/* + * Test program to exercise gss_inquire_mechs_for_name by importing a name and + * reporting the mech OIDs which are reported as being able to process it. + * + * Usage: ./t_inq_mechs_name name + */ + +#include + +#include "common.h" + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major; + gss_name_t name; + gss_OID_set mechs; + size_t i; + + if (argc != 2) { + fprintf(stderr, "Usage: t_inq_mechs_for_name name\n"); + return 1; + } + name = import_name(argv[1]); + major = gss_inquire_mechs_for_name(&minor, name, &mechs); + check_gsserr("gss_inquire_mechs_for_name", major, minor); + for (i = 0; i < mechs->count; i++) + display_oid(NULL, &mechs->elements[i]); + (void)gss_release_oid_set(&minor, &mechs); + (void)gss_release_name(&minor, &name); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_invalid.c b/krb5-1.21.3/src/tests/gssapi/t_invalid.c new file mode 100644 index 00000000..882e1636 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_invalid.c @@ -0,0 +1,615 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_invalid.c - Invalid message token regression tests */ +/* + * Copyright (C) 2014 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. + */ + +/* + * This file contains regression tests for some GSSAPI invalid token + * vulnerabilities. + * + * 1. A pre-CFX wrap or MIC token processed with a CFX-only context causes a + * null pointer dereference. (The token must use SEAL_ALG_NONE or it will + * be rejected.) This vulnerability also applies to IOV unwrap. + * + * 2. A CFX wrap token with a different value of EC between the plaintext and + * encrypted copies will be erroneously accepted, which allows a message + * truncation attack. This vulnerability also applies to IOV unwrap. + * + * 3. A CFX wrap token with a plaintext length fewer than 16 bytes causes an + * access before the beginning of the input buffer, possibly leading to a + * crash. + * + * 4. A CFX wrap token with a plaintext EC value greater than the plaintext + * length - 16 causes an integer underflow when computing the result length, + * likely causing a crash. + * + * 5. An IOV unwrap operation will overrun the header buffer if an ASN.1 + * wrapper longer than the header buffer is present. + * + * 6. A pre-CFX wrap or MIC token with fewer than 24 bytes after the ASN.1 + * header causes an input buffer overrun, usually leading to either a segv + * or a GSS_S_DEFECTIVE_TOKEN error due to garbage algorithm, filler, or + * sequence number values. This vulnerability also applies to IOV unwrap. + * + * 7. A pre-CFX wrap token with fewer than 16 + cksumlen bytes after the ASN.1 + * header causes an integer underflow when computing the ciphertext length, + * leading to an allocation error on 32-bit platforms or a segv on 64-bit + * platforms. A pre-CFX MIC token of this size causes an input buffer + * overrun when comparing the checksum, perhaps leading to a segv. + * + * 8. A pre-CFX wrap token with fewer than conflen + padlen bytes in the + * ciphertext (where padlen is the last byte of the decrypted ciphertext) + * causes an integer underflow when computing the original message length, + * leading to an allocation error. + * + * 9. In the mechglue, truncated encapsulation in the initial context token can + * cause input buffer overruns in gss_accept_sec_context(). + */ + +#include "k5-int.h" +#include "common.h" +#include "mglueP.h" +#include "gssapiP_krb5.h" + +/* + * The following samples contain context parameters and otherwise valid seal + * tokens where the plain text is padded with byte value 100 instead of the + * proper value 1. + */ +struct test { + krb5_enctype enctype; + krb5_enctype encseq_enctype; + int sealalg; + int signalg; + size_t cksum_size; + size_t keylen; + const char *keydata; + size_t toklen; + const char *token; +} tests[] = { + { + ENCTYPE_DES3_CBC_SHA1, ENCTYPE_DES3_CBC_RAW, + SEAL_ALG_DES3KD, SGN_ALG_HMAC_SHA1_DES3_KD, 20, + 24, + "\x4F\xEA\x19\x19\x5E\x0E\x10\xDF\x3D\x29\xB5\x13\x8F\x01\xC7\xA7" + "\x92\x3D\x38\xF7\x26\x73\x0D\x6D", + 65, + "\x60\x3F\x06\x09\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x02\x01\x04" + "\x00\x02\x00\xFF\xFF\xEB\xF3\x9A\x89\x24\x57\xB8\x63\x95\x25\xE8" + "\x6E\x8E\x79\xE6\x2E\xCA\xD3\xFF\x57\x9F\x8C\xAB\xEF\xDD\x28\x10" + "\x2F\x93\x21\x2E\xF2\x52\xB6\x6F\xA8\xBB\x8A\x6D\xAA\x6F\xB7\xF4\xD4" + }, + { + ENCTYPE_ARCFOUR_HMAC, ENCTYPE_ARCFOUR_HMAC, + SEAL_ALG_MICROSOFT_RC4, SGN_ALG_HMAC_MD5, 8, + 16, + "\x66\x64\x41\x64\x55\x78\x21\xD0\xD0\xFD\x05\x6A\xFF\x6F\xE8\x09", + 53, + "\x60\x33\x06\x09\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x02\x01\x11" + "\x00\x10\x00\xFF\xFF\x35\xD4\x79\xF3\x8C\x47\x8F\x6E\x23\x6F\x3E" + "\xCC\x5E\x57\x5C\x6A\x89\xF0\xA2\x03\x4F\x0B\x51\x11\xEE\x89\x7E" + "\xD6\xF6\xB5\xD6\x51" + } +}; + +static void * +ealloc(size_t len) +{ + void *ptr = calloc(len, 1); + + if (ptr == NULL) + abort(); + return ptr; +} + +/* Fake up enough of a CFX GSS context for gss_unwrap, using an AES key. + * The context takes ownership of subkey. */ +static gss_ctx_id_t +make_fake_cfx_context(krb5_key subkey) +{ + gss_union_ctx_id_t uctx; + krb5_gss_ctx_id_t kgctx; + + kgctx = ealloc(sizeof(*kgctx)); + kgctx->established = 1; + kgctx->proto = 1; + if (g_seqstate_init(&kgctx->seqstate, 0, 0, 0, 0) != 0) + abort(); + kgctx->mech_used = &mech_krb5; + kgctx->sealalg = -1; + kgctx->signalg = -1; + + kgctx->subkey = subkey; + kgctx->cksumtype = CKSUMTYPE_HMAC_SHA1_96_AES128; + + uctx = ealloc(sizeof(*uctx)); + uctx->mech_type = &mech_krb5; + uctx->internal_ctx_id = (gss_ctx_id_t)kgctx; + return (gss_ctx_id_t)uctx; +} + +/* Fake up enough of a GSS context for gss_unwrap, using keys from test. */ +static gss_ctx_id_t +make_fake_context(const struct test *test) +{ + gss_union_ctx_id_t uctx; + krb5_gss_ctx_id_t kgctx; + krb5_keyblock kb; + + kgctx = ealloc(sizeof(*kgctx)); + kgctx->established = 1; + if (g_seqstate_init(&kgctx->seqstate, 0, 0, 0, 0) != 0) + abort(); + kgctx->mech_used = &mech_krb5; + kgctx->sealalg = test->sealalg; + kgctx->signalg = test->signalg; + kgctx->cksum_size = test->cksum_size; + + kb.enctype = test->enctype; + kb.length = test->keylen; + kb.contents = (unsigned char *)test->keydata; + if (krb5_k_create_key(NULL, &kb, &kgctx->subkey) != 0) + abort(); + + kb.enctype = test->encseq_enctype; + if (krb5_k_create_key(NULL, &kb, &kgctx->seq) != 0) + abort(); + + if (krb5_k_create_key(NULL, &kb, &kgctx->enc) != 0) + abort(); + + uctx = ealloc(sizeof(*uctx)); + uctx->mech_type = &mech_krb5; + uctx->internal_ctx_id = (gss_ctx_id_t)kgctx; + return (gss_ctx_id_t)uctx; +} + +/* Free a context created by make_fake_context. */ +static void +free_fake_context(gss_ctx_id_t ctx) +{ + gss_union_ctx_id_t uctx = (gss_union_ctx_id_t)ctx; + krb5_gss_ctx_id_t kgctx = (krb5_gss_ctx_id_t)uctx->internal_ctx_id; + + free(kgctx->seqstate); + krb5_k_free_key(NULL, kgctx->subkey); + krb5_k_free_key(NULL, kgctx->seq); + krb5_k_free_key(NULL, kgctx->enc); + free(kgctx); + free(uctx); +} + +/* Prefix a token (starting at the two-byte ID) with an ASN.1 header and return + * it in an allocated block to facilitate checking by valgrind or similar. */ +static void +make_token(unsigned char *token, size_t len, gss_buffer_t out) +{ + char *wrapped; + + assert(mech_krb5.length == 9); + assert(len + 11 < 128); + wrapped = ealloc(len + 13); + wrapped[0] = 0x60; + wrapped[1] = len + 11; + wrapped[2] = 0x06; + wrapped[3] = 9; + memcpy(wrapped + 4, mech_krb5.elements, 9); + memcpy(wrapped + 13, token, len); + out->length = len + 13; + out->value = wrapped; +} + +/* Create a 16-byte header for a CFX confidential wrap token to be processed by + * the fake CFX context. */ +static void +write_cfx_header(uint16_t ec, uint8_t *out) +{ + memset(out, 0, 16); + store_16_be(KG2_TOK_WRAP_MSG, out); + out[2] = FLAG_WRAP_CONFIDENTIAL; + out[3] = 0xFF; + store_16_be(ec, out + 4); +} + +/* Unwrap a superficially valid RFC 1964 token with a CFX-only context, with + * regular and IOV unwrap. */ +static void +test_bogus_1964_token(gss_ctx_id_t ctx) +{ + OM_uint32 minor, major; + unsigned char tokbuf[128]; + gss_buffer_desc in, out; + gss_iov_buffer_desc iov; + + store_16_be(KG_TOK_SIGN_MSG, tokbuf); + store_16_le(SGN_ALG_HMAC_MD5, tokbuf + 2); + store_16_le(SEAL_ALG_NONE, tokbuf + 4); + store_16_le(0xFFFF, tokbuf + 6); + memset(tokbuf + 8, 0, 16); + make_token(tokbuf, 24, &in); + + major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + (void)gss_release_buffer(&minor, &out); + + iov.type = GSS_IOV_BUFFER_TYPE_HEADER; + iov.buffer = in; + major = gss_unwrap_iov(&minor, ctx, NULL, NULL, &iov, 1); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + + free(in.value); +} + +static void +test_cfx_altered_ec(gss_ctx_id_t ctx, krb5_key subkey) +{ + OM_uint32 major, minor; + uint8_t tokbuf[128], plainbuf[24]; + krb5_data plain; + krb5_enc_data cipher; + gss_buffer_desc in, out; + gss_iov_buffer_desc iov[2]; + + /* Construct a header with a plaintext EC value of 3. */ + write_cfx_header(3, tokbuf); + + /* Encrypt a plaintext and a copy of the header with the EC value 0. */ + memcpy(plainbuf, "truncate", 8); + memcpy(plainbuf + 8, tokbuf, 16); + store_16_be(0, plainbuf + 12); + plain = make_data(plainbuf, 24); + cipher.ciphertext.data = (char *)tokbuf + 16; + cipher.ciphertext.length = sizeof(tokbuf) - 16; + cipher.enctype = subkey->keyblock.enctype; + if (krb5_k_encrypt(NULL, subkey, KG_USAGE_INITIATOR_SEAL, NULL, + &plain, &cipher) != 0) + abort(); + + /* Verify that the token is rejected by gss_unwrap(). */ + in.value = tokbuf; + in.length = 16 + cipher.ciphertext.length; + major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + (void)gss_release_buffer(&minor, &out); + + /* Verify that the token is rejected by gss_unwrap_iov(). */ + iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM; + iov[0].buffer = in; + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + major = gss_unwrap_iov(&minor, ctx, NULL, NULL, iov, 2); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); +} + +static void +test_cfx_short_plaintext(gss_ctx_id_t ctx, krb5_key subkey) +{ + OM_uint32 major, minor; + uint8_t tokbuf[128], zerobyte = 0; + krb5_data plain; + krb5_enc_data cipher; + gss_buffer_desc in, out; + + write_cfx_header(0, tokbuf); + + /* Encrypt a single byte, with no copy of the header. */ + plain = make_data(&zerobyte, 1); + cipher.ciphertext.data = (char *)tokbuf + 16; + cipher.ciphertext.length = sizeof(tokbuf) - 16; + cipher.enctype = subkey->keyblock.enctype; + if (krb5_k_encrypt(NULL, subkey, KG_USAGE_INITIATOR_SEAL, NULL, + &plain, &cipher) != 0) + abort(); + + /* Verify that the token is rejected by gss_unwrap(). */ + in.value = tokbuf; + in.length = 16 + cipher.ciphertext.length; + major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + (void)gss_release_buffer(&minor, &out); +} + +static void +test_cfx_large_ec(gss_ctx_id_t ctx, krb5_key subkey) +{ + OM_uint32 major, minor; + uint8_t tokbuf[128] = { 0 }, plainbuf[20]; + krb5_data plain; + krb5_enc_data cipher; + gss_buffer_desc in, out; + + /* Construct a header with an EC value of 5. */ + write_cfx_header(5, tokbuf); + + /* Encrypt a 4-byte plaintext plus the header. */ + memcpy(plainbuf, "abcd", 4); + memcpy(plainbuf + 4, tokbuf, 16); + plain = make_data(plainbuf, 20); + cipher.ciphertext.data = (char *)tokbuf + 16; + cipher.ciphertext.length = sizeof(tokbuf) - 16; + cipher.enctype = subkey->keyblock.enctype; + if (krb5_k_encrypt(NULL, subkey, KG_USAGE_INITIATOR_SEAL, NULL, + &plain, &cipher) != 0) + abort(); + + /* Verify that the token is rejected by gss_unwrap(). */ + in.value = tokbuf; + in.length = 16 + cipher.ciphertext.length; + major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + (void)gss_release_buffer(&minor, &out); +} + +static void +test_iov_large_asn1_wrapper(gss_ctx_id_t ctx) +{ + OM_uint32 minor, major; + uint8_t databuf[10] = { 0 }; + gss_iov_buffer_desc iov[2]; + + /* + * In this IOV array, the header contains a DER tag with a dangling eight + * bytes of length field. The data IOV indicates a total token length + * sufficient to contain the length bytes. + */ + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[0].buffer.value = ealloc(2); + iov[0].buffer.length = 2; + memcpy(iov[0].buffer.value, "\x60\x88", 2); + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[1].buffer.value = databuf; + iov[1].buffer.length = 10; + major = gss_unwrap_iov(&minor, ctx, NULL, NULL, iov, 2); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + free(iov[0].buffer.value); +} + +/* Process wrap and MIC tokens with incomplete headers. */ +static void +test_short_header(gss_ctx_id_t ctx) +{ + OM_uint32 minor, major; + unsigned char tokbuf[128]; + gss_buffer_desc in, out, empty = GSS_C_EMPTY_BUFFER; + + /* Seal token, 2-24 bytes */ + store_16_be(KG_TOK_SEAL_MSG, tokbuf); + make_token(tokbuf, 2, &in); + major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + free(in.value); + (void)gss_release_buffer(&minor, &out); + + /* Sign token, 2-24 bytes */ + store_16_be(KG_TOK_SIGN_MSG, tokbuf); + make_token(tokbuf, 2, &in); + major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + free(in.value); + (void)gss_release_buffer(&minor, &out); + + /* MIC token, 2-24 bytes */ + store_16_be(KG_TOK_MIC_MSG, tokbuf); + make_token(tokbuf, 2, &in); + major = gss_verify_mic(&minor, ctx, &empty, &in, NULL); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + free(in.value); +} + +/* Process wrap and MIC tokens with incomplete headers. */ +static void +test_short_header_iov(gss_ctx_id_t ctx, const struct test *test) +{ + OM_uint32 minor, major; + unsigned char tokbuf[128]; + gss_iov_buffer_desc iov; + + /* IOV seal token, 16-23 bytes */ + store_16_be(KG_TOK_SEAL_MSG, tokbuf); + store_16_le(test->signalg, tokbuf + 2); + store_16_le(test->sealalg, tokbuf + 4); + store_16_be(0xFFFF, tokbuf + 6); + memset(tokbuf + 8, 0, 8); + iov.type = GSS_IOV_BUFFER_TYPE_HEADER; + make_token(tokbuf, 16, &iov.buffer); + major = gss_unwrap_iov(&minor, ctx, NULL, NULL, &iov, 1); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + free(iov.buffer.value); + + /* IOV sign token, 16-23 bytes */ + store_16_be(KG_TOK_SIGN_MSG, tokbuf); + store_16_le(test->signalg, tokbuf + 2); + store_16_le(SEAL_ALG_NONE, tokbuf + 4); + store_16_le(0xFFFF, tokbuf + 6); + memset(tokbuf + 8, 0, 8); + iov.type = GSS_IOV_BUFFER_TYPE_HEADER; + make_token(tokbuf, 16, &iov.buffer); + major = gss_unwrap_iov(&minor, ctx, NULL, NULL, &iov, 1); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + free(iov.buffer.value); + + /* IOV MIC token, 16-23 bytes */ + store_16_be(KG_TOK_MIC_MSG, tokbuf); + store_16_be(test->signalg, tokbuf + 2); + store_16_le(SEAL_ALG_NONE, tokbuf + 4); + store_16_le(0xFFFF, tokbuf + 6); + memset(tokbuf + 8, 0, 8); + iov.type = GSS_IOV_BUFFER_TYPE_MIC_TOKEN; + make_token(tokbuf, 16, &iov.buffer); + major = gss_verify_mic_iov(&minor, ctx, NULL, &iov, 1); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + free(iov.buffer.value); +} + +/* Process wrap and MIC tokens with incomplete checksums. */ +static void +test_short_checksum(gss_ctx_id_t ctx, const struct test *test) +{ + OM_uint32 minor, major; + unsigned char tokbuf[128]; + gss_buffer_desc in, out, empty = GSS_C_EMPTY_BUFFER; + + /* Can only do this with the DES3 checksum, as we can't easily get past + * retrieving the sequence number when the checksum is only eight bytes. */ + if (test->cksum_size <= 8) + return; + /* Seal token, fewer than 16 + cksum_size bytes. Use the token from the + * test data to get a valid sequence number. */ + make_token((unsigned char *)test->token + 13, 24, &in); + major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + free(in.value); + (void)gss_release_buffer(&minor, &out); + + /* Sign token, fewer than 16 + cksum_size bytes. */ + memcpy(tokbuf, test->token + 13, 24); + store_16_be(KG_TOK_SIGN_MSG, tokbuf); + store_16_le(SEAL_ALG_NONE, tokbuf + 4); + make_token(tokbuf, 24, &in); + major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + free(in.value); + (void)gss_release_buffer(&minor, &out); + + /* MIC token, fewer than 16 + cksum_size bytes. */ + memcpy(tokbuf, test->token + 13, 24); + store_16_be(KG_TOK_MIC_MSG, tokbuf); + store_16_le(SEAL_ALG_NONE, tokbuf + 4); + make_token(tokbuf, 24, &in); + major = gss_verify_mic(&minor, ctx, &empty, &in, NULL); + if (major != GSS_S_DEFECTIVE_TOKEN) + abort(); + free(in.value); +} + +/* Unwrap a token with a bogus padding byte in the decrypted ciphertext. */ +static void +test_bad_pad(gss_ctx_id_t ctx, const struct test *test) +{ + OM_uint32 minor, major; + gss_buffer_desc in, out; + + in.length = test->toklen; + in.value = (char *)test->token; + major = gss_unwrap(&minor, ctx, &in, &out, NULL, NULL); + if (major != GSS_S_BAD_SIG) + abort(); + (void)gss_release_buffer(&minor, &out); +} + +static void +try_accept(void *value, size_t len) +{ + OM_uint32 minor; + gss_buffer_desc in, out; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + + /* Copy the provided value to make input overruns more obvious. */ + in.value = ealloc(len); + memcpy(in.value, value, len); + in.length = len; + (void)gss_accept_sec_context(&minor, &ctx, GSS_C_NO_CREDENTIAL, &in, + GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL, + &out, NULL, NULL, NULL); + gss_release_buffer(&minor, &out); + gss_delete_sec_context(&minor, &ctx, GSS_C_NO_BUFFER); + free(in.value); +} + +/* Accept contexts using superficially valid but truncated encapsulations. */ +static void +test_short_encapsulation() +{ + /* Include just the initial application tag, to see if we overrun reading + * the sequence length. */ + try_accept("\x60", 1); + + /* Indicate four additional sequence length bytes, to see if we overrun + * reading them (or skipping them and reading the next byte). */ + try_accept("\x60\x84", 2); + + /* Include an object identifier tag but no length, to see if we overrun + * reading the length. */ + try_accept("\x60\x40\x06", 3); + + /* Include an object identifier tag with a length matching the krb5 mech, + * but no OID bytes, to see if we overrun comparing against mechs. */ + try_accept("\x60\x40\x06\x09", 4); +} + +int +main(int argc, char **argv) +{ + krb5_keyblock kb; + krb5_key cfx_subkey; + gss_ctx_id_t ctx; + size_t i; + + kb.enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96; + kb.length = 16; + kb.contents = (unsigned char *)"1234567887654321"; + if (krb5_k_create_key(NULL, &kb, &cfx_subkey) != 0) + abort(); + + ctx = make_fake_cfx_context(cfx_subkey); + test_bogus_1964_token(ctx); + test_cfx_altered_ec(ctx, cfx_subkey); + test_cfx_short_plaintext(ctx, cfx_subkey); + test_cfx_large_ec(ctx, cfx_subkey); + test_iov_large_asn1_wrapper(ctx); + free_fake_context(ctx); + + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { + ctx = make_fake_context(&tests[i]); + test_short_header(ctx); + test_short_header_iov(ctx, &tests[i]); + test_short_checksum(ctx, &tests[i]); + test_bad_pad(ctx, &tests[i]); + free_fake_context(ctx); + } + + test_short_encapsulation(); + + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_iov.c b/krb5-1.21.3/src/tests/gssapi/t_iov.c new file mode 100644 index 00000000..f900b883 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_iov.c @@ -0,0 +1,547 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_iov.c - Test program for IOV functions */ +/* + * 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. + */ + +#include +#include +#include +#include +#include "common.h" + +/* Concatenate iov (except for sign-only buffers) into a contiguous token. */ +static void +concat_iov(gss_iov_buffer_desc *iov, size_t iovlen, char **buf_out, + size_t *len_out) +{ + size_t len, i; + char *buf; + + /* Concatenate the result into a contiguous buffer. */ + len = 0; + for (i = 0; i < iovlen; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) != GSS_IOV_BUFFER_TYPE_SIGN_ONLY) + len += iov[i].buffer.length; + } + buf = malloc(len); + if (buf == NULL) + errout("malloc failed"); + len = 0; + for (i = 0; i < iovlen; i++) { + if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_SIGN_ONLY) + continue; + memcpy(buf + len, iov[i].buffer.value, iov[i].buffer.length); + len += iov[i].buffer.length; + } + *buf_out = buf; + *len_out = len; +} + +static void +check_encrypted(const char *msg, int conf, const char *buf, const char *plain) +{ + int same = memcmp(buf, plain, strlen(plain)) == 0; + + if ((conf && same) || (!conf && !same)) + errout(msg); +} + +/* + * Wrap str in standard form (HEADER | DATA | PADDING | TRAILER) using the + * caller-provided array iov, which must have space for four elements. Library + * allocation will be used for the header/padding/trailer buffers, so the + * caller must check and free them. + */ +static void +wrap_std(gss_ctx_id_t ctx, char *str, gss_iov_buffer_desc *iov, int conf) +{ + OM_uint32 minor, major; + int oconf; + + /* Lay out iov array. */ + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE; + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[1].buffer.value = str; + iov[1].buffer.length = strlen(str); + iov[2].type = GSS_IOV_BUFFER_TYPE_PADDING | GSS_IOV_BUFFER_FLAG_ALLOCATE; + iov[3].type = GSS_IOV_BUFFER_TYPE_TRAILER | GSS_IOV_BUFFER_FLAG_ALLOCATE; + + /* Wrap. This will allocate header/padding/trailer buffers as necessary + * and encrypt str in place. */ + major = gss_wrap_iov(&minor, ctx, conf, GSS_C_QOP_DEFAULT, &oconf, iov, 4); + check_gsserr("gss_wrap_iov(std)", major, minor); + if (oconf != conf) + errout("gss_wrap_iov(std) conf"); +} + +/* Create standard tokens using gss_wrap_iov and ctx1, and make sure we can + * unwrap them using ctx2 in all of the supported ways. */ +static void +test_standard_wrap(gss_ctx_id_t ctx1, gss_ctx_id_t ctx2, int conf) +{ + OM_uint32 major, minor; + gss_iov_buffer_desc iov[4], stiov[2]; + gss_qop_t qop; + gss_buffer_desc input, output; + const char *string1 = "The swift brown fox jumped over the lazy dog."; + const char *string2 = "Now is the time!"; + const char *string3 = "x"; + const char *string4 = "!@#"; + char data[1024], *fulltoken; + size_t len; + int oconf; + ptrdiff_t offset; + + /* Wrap a standard token and unwrap it using the iov array. */ + memcpy(data, string1, strlen(string1) + 1); + wrap_std(ctx1, data, iov, conf); + check_encrypted("gss_wrap_iov(std1) encryption", conf, data, string1); + major = gss_unwrap_iov(&minor, ctx2, &oconf, &qop, iov, 4); + check_gsserr("gss_unwrap_iov(std1)", major, minor); + if (oconf != conf || qop != GSS_C_QOP_DEFAULT) + errout("gss_unwrap_iov(std1) conf/qop"); + if (iov[1].buffer.value != data || iov[1].buffer.length != strlen(string1)) + errout("gss_unwrap_iov(std1) data buffer"); + if (memcmp(data, string1, iov[1].buffer.length) != 0) + errout("gss_unwrap_iov(std1) decryption"); + (void)gss_release_iov_buffer(&minor, iov, 4); + + /* Wrap a standard token and unwrap it using gss_unwrap(). */ + memcpy(data, string2, strlen(string2) + 1); + wrap_std(ctx1, data, iov, conf); + concat_iov(iov, 4, &fulltoken, &len); + input.value = fulltoken; + input.length = len; + major = gss_unwrap(&minor, ctx2, &input, &output, &oconf, &qop); + check_gsserr("gss_unwrap(std2)", major, minor); + if (oconf != conf || qop != GSS_C_QOP_DEFAULT) + errout("gss_unwrap(std2) conf/qop"); + if (output.length != strlen(string2) || + memcmp(output.value, string2, output.length) != 0) + errout("gss_unwrap(std2) decryption"); + (void)gss_release_buffer(&minor, &output); + (void)gss_release_iov_buffer(&minor, iov, 4); + free(fulltoken); + + /* Wrap a standard token and unwrap it using a stream buffer. */ + memcpy(data, string3, strlen(string3) + 1); + wrap_std(ctx1, data, iov, conf); + concat_iov(iov, 4, &fulltoken, &len); + stiov[0].type = GSS_IOV_BUFFER_TYPE_STREAM; + stiov[0].buffer.value = fulltoken; + stiov[0].buffer.length = len; + stiov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + major = gss_unwrap_iov(&minor, ctx2, &oconf, &qop, stiov, 2); + check_gsserr("gss_unwrap_iov(std3)", major, minor); + if (oconf != conf || qop != GSS_C_QOP_DEFAULT) + errout("gss_unwrap_iov(std3) conf/qop"); + if (stiov[1].buffer.length != strlen(string3) || + memcmp(stiov[1].buffer.value, string3, strlen(string3)) != 0) + errout("gss_unwrap_iov(std3) decryption"); + offset = (char *)stiov[1].buffer.value - fulltoken; + if (offset < 0 || (size_t)offset > len) + errout("gss_unwrap_iov(std3) offset"); + (void)gss_release_iov_buffer(&minor, iov, 4); + free(fulltoken); + + /* Wrap a token using gss_wrap and unwrap it using a stream buffer with + * allocation and copying. */ + input.value = (char *)string4; + input.length = strlen(string4); + major = gss_wrap(&minor, ctx1, conf, GSS_C_QOP_DEFAULT, &input, &oconf, + &output); + check_gsserr("gss_wrap(std4)", major, minor); + if (oconf != conf) + errout("gss_wrap(std4) conf"); + stiov[0].type = GSS_IOV_BUFFER_TYPE_STREAM; + stiov[0].buffer = output; + stiov[1].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE; + major = gss_unwrap_iov(&minor, ctx2, &oconf, &qop, stiov, 2); + check_gsserr("gss_unwrap_iov(std4)", major, minor); + if (!(GSS_IOV_BUFFER_FLAGS(stiov[1].type) & GSS_IOV_BUFFER_FLAG_ALLOCATED)) + errout("gss_unwrap_iov(std4) allocated"); + if (oconf != conf || qop != GSS_C_QOP_DEFAULT) + errout("gss_unwrap_iov(std4) conf/qop"); + if (stiov[1].buffer.length != strlen(string4) || + memcmp(stiov[1].buffer.value, string4, strlen(string4)) != 0) + errout("gss_unwrap_iov(std4) decryption"); + (void)gss_release_buffer(&minor, &output); + (void)gss_release_iov_buffer(&minor, stiov, 2); +} + +/* + * Wrap an AEAD token (HEADER | SIGN_ONLY | DATA | PADDING | TRAILER) using the + * caller-provided array iov, which must have space for five elements, and the + * caller-provided buffer data, which must be big enough to handle the test + * inputs. Library allocation will not be used. + */ +static void +wrap_aead(gss_ctx_id_t ctx, const char *sign, const char *wrap, + gss_iov_buffer_desc *iov, char *data, int conf) +{ + OM_uint32 major, minor; + int oconf; + char *ptr; + + /* Lay out iov array. */ + iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER; + iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[1].buffer.value = (char *)sign; + iov[1].buffer.length = strlen(sign); + iov[2].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[2].buffer.value = (char *)wrap; + iov[2].buffer.length = strlen(wrap); + iov[3].type = GSS_IOV_BUFFER_TYPE_PADDING; + iov[4].type = GSS_IOV_BUFFER_TYPE_TRAILER; + + /* Get header/padding/trailer lengths. */ + major = gss_wrap_iov_length(&minor, ctx, conf, GSS_C_QOP_DEFAULT, &oconf, + iov, 5); + check_gsserr("gss_wrap_iov_length(aead)", major, minor); + if (oconf != conf) + errout("gss_wrap_iov_length(aead) conf"); + if (iov[1].buffer.value != sign || iov[1].buffer.length != strlen(sign)) + errout("gss_wrap_iov_length(aead) sign-only buffer"); + if (iov[2].buffer.value != wrap || iov[2].buffer.length != strlen(wrap)) + errout("gss_wrap_iov_length(aead) data buffer"); + + /* Set iov buffer pointers using returned lengths. */ + iov[0].buffer.value = data; + ptr = data + iov[0].buffer.length; + memcpy(ptr, wrap, strlen(wrap)); + iov[2].buffer.value = ptr; + ptr += iov[2].buffer.length; + iov[3].buffer.value = ptr; + ptr += iov[3].buffer.length; + iov[4].buffer.value = ptr; + + /* Wrap the AEAD token. */ + major = gss_wrap_iov(&minor, ctx, conf, GSS_C_QOP_DEFAULT, &oconf, iov, 5); + check_gsserr("gss_wrap_iov(aead)", major, minor); + if (oconf != conf) + errout("gss_wrap_iov(aead) conf"); + if (iov[1].buffer.value != sign || iov[1].buffer.length != strlen(sign)) + errout("gss_wrap_iov(aead) sign-only buffer"); + if (iov[2].buffer.length != strlen(wrap)) + errout("gss_wrap_iov(aead) data buffer"); + check_encrypted("gss_wrap_iov(aead) encryption", conf, iov[2].buffer.value, + wrap); +} + +/* Create AEAD tokens using gss_wrap_iov and ctx1, and make sure we can unwrap + * them using ctx2 in all of the supported ways. */ +static void +test_aead(gss_ctx_id_t ctx1, gss_ctx_id_t ctx2, int conf) +{ + OM_uint32 major, minor; + gss_iov_buffer_desc iov[5], stiov[3]; + gss_qop_t qop; + gss_buffer_desc input, assoc, output; + const char *sign = "This data is only signed."; + const char *wrap = "This data is wrapped in-place."; + char data[1024], *fulltoken; + size_t len; + int oconf; + ptrdiff_t offset; + + /* Wrap an AEAD token and unwrap it using the IOV array. */ + wrap_aead(ctx1, sign, wrap, iov, data, conf); + major = gss_unwrap_iov(&minor, ctx2, &oconf, &qop, iov, 5); + check_gsserr("gss_unwrap_iov(aead1)", major, minor); + if (oconf != conf || qop != GSS_C_QOP_DEFAULT) + errout("gss_unwrap_iov(aead1) conf/qop"); + if (iov[1].buffer.value != sign || iov[1].buffer.length != strlen(sign)) + errout("gss_unwrap_iov(aead1) sign-only buffer"); + if (iov[2].buffer.length != strlen(wrap) || + memcmp(iov[2].buffer.value, wrap, iov[2].buffer.length) != 0) + errout("gss_unwrap_iov(aead1) decryption"); + + /* Wrap an AEAD token and unwrap it using gss_unwrap_aead. */ + wrap_aead(ctx1, sign, wrap, iov, data, conf); + concat_iov(iov, 5, &fulltoken, &len); + input.value = fulltoken; + input.length = len; + assoc.value = (char *)sign; + assoc.length = strlen(sign); + major = gss_unwrap_aead(&minor, ctx2, &input, &assoc, &output, &oconf, + &qop); + check_gsserr("gss_unwrap_aead(aead2)", major, minor); + if (output.length != strlen(wrap) || + memcmp(output.value, wrap, output.length) != 0) + errout("gss_unwrap_aead(aead2) decryption"); + free(fulltoken); + (void)gss_release_buffer(&minor, &output); + + /* Wrap an AEAD token and unwrap it using a stream buffer. */ + wrap_aead(ctx1, sign, wrap, iov, data, conf); + concat_iov(iov, 5, &fulltoken, &len); + stiov[0].type = GSS_IOV_BUFFER_TYPE_STREAM; + stiov[0].buffer.value = fulltoken; + stiov[0].buffer.length = len; + stiov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + stiov[1].buffer.value = (char *)sign; + stiov[1].buffer.length = strlen(sign); + stiov[2].type = GSS_IOV_BUFFER_TYPE_DATA; + major = gss_unwrap_iov(&minor, ctx2, &oconf, &qop, stiov, 3); + check_gsserr("gss_unwrap_iov(aead3)", major, minor); + if (oconf != conf || qop != GSS_C_QOP_DEFAULT) + errout("gss_unwrap_iov(aead3) conf/qop"); + if (stiov[2].buffer.length != strlen(wrap) || + memcmp(stiov[2].buffer.value, wrap, strlen(wrap)) != 0) + errout("gss_unwrap_iov(aead3) decryption"); + offset = (char *)stiov[2].buffer.value - fulltoken; + if (offset < 0 || (size_t)offset > len) + errout("gss_unwrap_iov(aead3) offset"); + free(fulltoken); + (void)gss_release_iov_buffer(&minor, iov, 4); + + /* Wrap a token using gss_wrap_aead and unwrap it using a stream buffer + * with allocation and copying. */ + input.value = (char *)wrap; + input.length = strlen(wrap); + assoc.value = (char *)sign; + assoc.length = strlen(sign); + major = gss_wrap_aead(&minor, ctx1, conf, GSS_C_QOP_DEFAULT, &assoc, + &input, &oconf, &output); + check_gsserr("gss_wrap_aead(aead4)", major, minor); + if (oconf != conf) + errout("gss_wrap(aead4) conf"); + stiov[0].type = GSS_IOV_BUFFER_TYPE_STREAM; + stiov[0].buffer = output; + stiov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + stiov[1].buffer = assoc; + stiov[2].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE; + major = gss_unwrap_iov(&minor, ctx2, &oconf, &qop, stiov, 3); + check_gsserr("gss_unwrap_iov(aead4)", major, minor); + if (!(GSS_IOV_BUFFER_FLAGS(stiov[2].type) & GSS_IOV_BUFFER_FLAG_ALLOCATED)) + errout("gss_unwrap_iov(aead4) allocated"); + if (oconf != conf || qop != GSS_C_QOP_DEFAULT) + errout("gss_unwrap_iov(aead4) conf/qop"); + if (stiov[2].buffer.length != strlen(wrap) || + memcmp(stiov[2].buffer.value, wrap, strlen(wrap)) != 0) + errout("gss_unwrap_iov(aead4) decryption"); + (void)gss_release_buffer(&minor, &output); + (void)gss_release_iov_buffer(&minor, stiov, 3); +} + +/* + * Get a MIC for sign1, sign2, and sign3 using the caller-provided array iov, + * which must have space for four elements, and the caller-provided buffer + * data, which must be big enough for the MIC. If data is NULL, the library + * will be asked to allocate the MIC buffer. The MIC will be located in + * iov[3].buffer. + */ +static void +mic(gss_ctx_id_t ctx, const char *sign1, const char *sign2, const char *sign3, + gss_iov_buffer_desc *iov, char *data) +{ + OM_uint32 minor, major; + krb5_boolean allocated; + + /* Lay out iov array. */ + iov[0].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[0].buffer.value = (char *)sign1; + iov[0].buffer.length = strlen(sign1); + iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[1].buffer.value = (char *)sign2; + iov[1].buffer.length = strlen(sign2); + iov[2].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[2].buffer.value = (char *)sign3; + iov[2].buffer.length = strlen(sign3); + iov[3].type = GSS_IOV_BUFFER_TYPE_MIC_TOKEN; + if (data == NULL) { + /* Ask the library to allocate the MIC buffer. */ + iov[3].type |= GSS_IOV_BUFFER_FLAG_ALLOCATE; + } else { + /* Get the MIC length and use the caller-provided buffer. */ + major = gss_get_mic_iov_length(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 4); + check_gsserr("gss_get_mic_iov_length", major, minor); + iov[3].buffer.value = data; + } + major = gss_get_mic_iov(&minor, ctx, GSS_C_QOP_DEFAULT, iov, 4); + check_gsserr("gss_get_mic_iov", major, minor); + allocated = (GSS_IOV_BUFFER_FLAGS(iov[3].type) & + GSS_IOV_BUFFER_FLAG_ALLOCATED) != 0; + if (allocated != (data == NULL)) + errout("gss_get_mic_iov allocated"); +} + +static void +test_mic(gss_ctx_id_t ctx1, gss_ctx_id_t ctx2) +{ + OM_uint32 major, minor; + gss_iov_buffer_desc iov[4]; + gss_qop_t qop; + gss_buffer_desc concatbuf, micbuf; + const char *sign1 = "Data and sign-only "; + const char *sign2 = "buffers are treated "; + const char *sign3 = "equally by gss_get_mic_iov"; + char concat[1024], data[1024]; + + (void)snprintf(concat, sizeof(concat), "%s%s%s", sign1, sign2, sign3); + concatbuf.value = concat; + concatbuf.length = strlen(concat); + + /* MIC with a caller-provided buffer and verify with the IOV array. */ + mic(ctx1, sign1, sign2, sign3, iov, data); + major = gss_verify_mic_iov(&minor, ctx2, &qop, iov, 4); + check_gsserr("gss_verify_mic_iov(mic1)", major, minor); + if (qop != GSS_C_QOP_DEFAULT) + errout("gss_verify_mic_iov(mic1) qop"); + + /* MIC with an allocated buffer and verify with gss_verify_mic. */ + mic(ctx1, sign1, sign2, sign3, iov, NULL); + major = gss_verify_mic(&minor, ctx2, &concatbuf, &iov[3].buffer, &qop); + check_gsserr("gss_verify_mic(mic2)", major, minor); + if (qop != GSS_C_QOP_DEFAULT) + errout("gss_verify_mic(mic2) qop"); + (void)gss_release_iov_buffer(&minor, iov, 4); + + /* MIC with gss_c_get_mic and verify using the IOV array (which is still + * mostly set up from the last call to mic(). */ + major = gss_get_mic(&minor, ctx1, GSS_C_QOP_DEFAULT, &concatbuf, &micbuf); + check_gsserr("gss_get_mic(mic3)", major, minor); + iov[3].buffer = micbuf; + major = gss_verify_mic_iov(&minor, ctx2, &qop, iov, 4); + check_gsserr("gss_verify_mic_iov(mic3)", major, minor); + if (qop != GSS_C_QOP_DEFAULT) + errout("gss_verify_mic_iov(mic3) qop"); + (void)gss_release_buffer(&minor, &micbuf); +} + +/* Create a DCE-style token and make sure we can unwrap it. */ +static void +test_dce(gss_ctx_id_t ctx1, gss_ctx_id_t ctx2, int conf) +{ + OM_uint32 major, minor; + gss_iov_buffer_desc iov[4]; + gss_qop_t qop; + const char *sign1 = "First data to be signed"; + const char *sign2 = "Second data to be signed"; + const char *wrap = "This data must align to 16 bytes"; + int oconf; + char data[1024]; + + /* Wrap a SIGN_ONLY_1 | DATA | SIGN_ONLY_2 | HEADER token. */ + memcpy(data, wrap, strlen(wrap) + 1); + iov[0].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[0].buffer.value = (char *)sign1; + iov[0].buffer.length = strlen(sign1); + iov[1].type = GSS_IOV_BUFFER_TYPE_DATA; + iov[1].buffer.value = data; + iov[1].buffer.length = strlen(wrap); + iov[2].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY; + iov[2].buffer.value = (char *)sign2; + iov[2].buffer.length = strlen(sign2); + iov[3].type = GSS_IOV_BUFFER_TYPE_HEADER | GSS_IOV_BUFFER_FLAG_ALLOCATE; + major = gss_wrap_iov(&minor, ctx1, conf, GSS_C_QOP_DEFAULT, &oconf, iov, + 4); + check_gsserr("gss_wrap_iov(dce)", major, minor); + if (oconf != conf) + errout("gss_wrap_iov(dce) conf"); + if (iov[0].buffer.value != sign1 || iov[0].buffer.length != strlen(sign1)) + errout("gss_wrap_iov(dce) sign1 buffer"); + if (iov[1].buffer.value != data || iov[1].buffer.length != strlen(wrap)) + errout("gss_wrap_iov(dce) data buffer"); + if (iov[2].buffer.value != sign2 || iov[2].buffer.length != strlen(sign2)) + errout("gss_wrap_iov(dce) sign2 buffer"); + check_encrypted("gss_wrap_iov(dce) encryption", conf, data, wrap); + + /* Make sure we can unwrap it. */ + major = gss_unwrap_iov(&minor, ctx2, &oconf, &qop, iov, 4); + check_gsserr("gss_unwrap_iov(std1)", major, minor); + if (oconf != conf || qop != GSS_C_QOP_DEFAULT) + errout("gss_unwrap_iov(std1) conf/qop"); + if (iov[0].buffer.value != sign1 || iov[0].buffer.length != strlen(sign1)) + errout("gss_unwrap_iov(dce) sign1 buffer"); + if (iov[1].buffer.value != data || iov[1].buffer.length != strlen(wrap)) + errout("gss_unwrap_iov(dce) data buffer"); + if (iov[2].buffer.value != sign2 || iov[2].buffer.length != strlen(sign2)) + errout("gss_unwrap_iov(dce) sign2 buffer"); + if (memcmp(data, wrap, iov[1].buffer.length) != 0) + errout("gss_unwrap_iov(dce) decryption"); + (void)gss_release_iov_buffer(&minor, iov, 4); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, flags; + gss_OID mech = &mech_krb5; + gss_name_t tname; + gss_ctx_id_t ictx, actx; + + /* Parse arguments. */ + argv++; + if (*argv != NULL && strcmp(*argv, "-s") == 0) { + mech = &mech_spnego; + argv++; + } + if (*argv == NULL || *(argv + 1) != NULL) + errout("Usage: t_iov [-s] targetname"); + tname = import_name(*argv); + + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_MUTUAL_FLAG; + establish_contexts(mech, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, tname, + flags, &ictx, &actx, NULL, NULL, NULL); + + /* Test standard token wrapping and unwrapping in both directions, with and + * without confidentiality. */ + test_standard_wrap(ictx, actx, 0); + test_standard_wrap(ictx, actx, 1); + test_standard_wrap(actx, ictx, 0); + test_standard_wrap(actx, ictx, 1); + + /* Test AEAD wrapping. */ + test_aead(ictx, actx, 0); + test_aead(ictx, actx, 1); + test_aead(actx, ictx, 0); + test_aead(actx, ictx, 1); + + /* Test MIC tokens. */ + test_mic(ictx, actx); + test_mic(actx, ictx); + + /* Test DCE wrapping with DCE-style contexts. */ + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_DCE_STYLE; + establish_contexts(mech, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, tname, + flags, &ictx, &actx, NULL, NULL, NULL); + test_dce(ictx, actx, 0); + test_dce(ictx, actx, 1); + test_dce(actx, ictx, 0); + test_dce(actx, ictx, 1); + + (void)gss_release_name(&minor, &tname); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_lifetime.c b/krb5-1.21.3/src/tests/gssapi/t_lifetime.c new file mode 100644 index 00000000..8dcf1862 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_lifetime.c @@ -0,0 +1,140 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_lifetime.c - display cred and context lifetimes */ +/* + * Copyright (C) 2017 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. + */ + +#include +#include +#include +#include "common.h" + +/* + * Using the default credential, exercise the GSS functions which accept or + * produce lifetimes. Display the following results, one per line, as ASCII + * integers or the string "indefinite": + * + * initiator cred lifetime according to gss_acquire_cred() + * initiator cred lifetime according to gss_inquire_cred() + * acceptor cred lifetime according to gss_acquire_cred() + * acceptor cred lifetime according to gss_inquire_cred() + * initiator context lifetime according to gss_init_sec_context() + * initiator context lifetime according to gss_inquire_context() + * initiator context lifetime according to gss_context_time() + * acceptor context lifetime according to gss_init_sec_context() + * acceptor context lifetime according to gss_inquire_context() + * acceptor context lifetime according to gss_context_time() + */ + +static void +display_time(OM_uint32 tval) +{ + if (tval == GSS_C_INDEFINITE) + puts("indefinite"); + else + printf("%u\n", (unsigned int)tval); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major; + gss_cred_id_t icred, acred; + gss_name_t tname; + gss_ctx_id_t ictx = GSS_C_NO_CONTEXT, actx = GSS_C_NO_CONTEXT; + gss_buffer_desc itok = GSS_C_EMPTY_BUFFER, atok = GSS_C_EMPTY_BUFFER; + OM_uint32 time_req = GSS_C_INDEFINITE, time_rec; + + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: %s targetname [time_req]\n", argv[0]); + return 1; + } + tname = import_name(argv[1]); + if (argc >= 3) + time_req = atoll(argv[2]); + + /* Get initiator cred and display its lifetime according to + * gss_acquire_cred and gss_inquire_cred. */ + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, time_req, &mechset_krb5, + GSS_C_INITIATE, &icred, NULL, &time_rec); + check_gsserr("gss_acquire_cred(initiate)", major, minor); + display_time(time_rec); + major = gss_inquire_cred(&minor, icred, NULL, &time_rec, NULL, NULL); + check_gsserr("gss_inquire_cred(initiate)", major, minor); + display_time(time_rec); + + /* Get acceptor cred and display its lifetime according to gss_acquire_cred + * and gss_inquire_cred. */ + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, time_req, &mechset_krb5, + GSS_C_ACCEPT, &acred, NULL, &time_rec); + check_gsserr("gss_acquire_cred(accept)", major, minor); + display_time(time_rec); + major = gss_inquire_cred(&minor, acred, NULL, &time_rec, NULL, NULL); + check_gsserr("gss_inquire_cred(accept)", major, minor); + display_time(time_rec); + + /* Make an initiator context and display its lifetime according to + * gss_init_sec_context, gss_inquire_context, and gss_context_time. */ + major = gss_init_sec_context(&minor, icred, &ictx, tname, &mech_krb5, 0, + time_req, GSS_C_NO_CHANNEL_BINDINGS, &atok, + NULL, &itok, NULL, &time_rec); + check_gsserr("gss_init_sec_context", major, minor); + assert(major == GSS_S_COMPLETE); + display_time(time_rec); + major = gss_inquire_context(&minor, ictx, NULL, NULL, &time_rec, NULL, + NULL, NULL, NULL); + check_gsserr("gss_inquire_context(initiate)", major, minor); + display_time(time_rec); + major = gss_context_time(&minor, ictx, &time_rec); + check_gsserr("gss_context_time(initiate)", major, minor); + display_time(time_rec); + + major = gss_accept_sec_context(&minor, &actx, acred, &itok, + GSS_C_NO_CHANNEL_BINDINGS, NULL, + NULL, &atok, NULL, &time_rec, NULL); + check_gsserr("gss_accept_sec_context", major, minor); + assert(major == GSS_S_COMPLETE); + display_time(time_rec); + major = gss_inquire_context(&minor, actx, NULL, NULL, &time_rec, NULL, + NULL, NULL, NULL); + check_gsserr("gss_inquire_context(accept)", major, minor); + display_time(time_rec); + major = gss_context_time(&minor, actx, &time_rec); + check_gsserr("gss_context_time(accept)", major, minor); + display_time(time_rec); + + (void)gss_release_buffer(&minor, &itok); + (void)gss_release_buffer(&minor, &atok); + (void)gss_release_name(&minor, &tname); + (void)gss_release_cred(&minor, &icred); + (void)gss_release_cred(&minor, &acred); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_namingexts.c b/krb5-1.21.3/src/tests/gssapi/t_namingexts.c new file mode 100644 index 00000000..739592b9 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_namingexts.c @@ -0,0 +1,227 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include + +#include "common.h" + +static int use_spnego = 0; + +static void +display_name(const char *tag, gss_name_t name) +{ + OM_uint32 major, minor; + gss_buffer_desc buf; + + major = gss_display_name(&minor, name, &buf, NULL); + check_gsserr("gss_display_name", major, minor); + + printf("%s:\t%.*s\n", tag, (int)buf.length, (char *)buf.value); + + (void)gss_release_buffer(&minor, &buf); +} + +static void +test_export_import_name(gss_name_t name) +{ + OM_uint32 major, minor; + gss_buffer_desc exported_name = GSS_C_EMPTY_BUFFER; + gss_name_t imported_name = GSS_C_NO_NAME; + gss_name_t imported_name_comp = GSS_C_NO_NAME; + unsigned int i; + + major = gss_export_name_composite(&minor, name, &exported_name); + check_gsserr("gss_export_name_composite", major, minor); + + printf("Exported name:\n"); + for (i = 0; i < exported_name.length; i++) { + if ((i % 32) == 0) + printf("\n"); + printf("%02x", ((char *)exported_name.value)[i] & 0xFF); + } + printf("\n"); + + major = gss_import_name(&minor, &exported_name, GSS_C_NT_EXPORT_NAME, + &imported_name); + check_gsserr("gss_import_name", major, minor); + + major = gss_import_name(&minor, &exported_name, GSS_C_NT_COMPOSITE_EXPORT, + &imported_name_comp); + check_gsserr("gss_import_name", major, minor); + (void)gss_release_buffer(&minor, &exported_name); + + printf("\n"); + display_canon_name("Re-imported name", imported_name, &mech_krb5); + printf("Re-imported attributes:\n\n"); + enumerate_attributes(imported_name, 0); + + display_name("Re-imported (as composite) name", imported_name_comp); + printf("Re-imported (as composite) attributes:\n\n"); + enumerate_attributes(imported_name_comp, 0); + + (void)gss_release_name(&minor, &imported_name); + (void)gss_release_name(&minor, &imported_name_comp); +} + +static void +test_greet_authz_data(gss_name_t name) +{ + OM_uint32 major, minor; + gss_buffer_desc attr; + gss_buffer_desc value; + + attr.value = "urn:greet:greeting"; + attr.length = strlen((char *)attr.value); + + major = gss_delete_name_attribute(&minor, name, &attr); + if (major == GSS_S_UNAVAILABLE) { + fprintf(stderr, "Warning: greet_client plugin not installed\n"); + exit(1); + } + check_gsserr("gss_delete_name_attribute", major, minor); + + value.value = "Hello, acceptor world!"; + value.length = strlen((char *)value.value); + major = gss_set_name_attribute(&minor, name, 1, &attr, &value); + if (major == GSS_S_UNAVAILABLE) + return; + check_gsserr("gss_set_name_attribute", major, minor); +} + +static void +test_map_name_to_any(gss_name_t name) +{ + OM_uint32 major, minor; + gss_buffer_desc type_id; + krb5_pac pac; + krb5_context context = NULL; + krb5_error_code ret; + size_t len, i; + krb5_ui_4 *types; + + type_id.value = "mspac"; + type_id.length = strlen((char *)type_id.value); + + major = gss_map_name_to_any(&minor, name, 1, &type_id, (gss_any_t *)&pac); + if (major == GSS_S_UNAVAILABLE) + return; + check_gsserr("gss_map_name_to_any", major, minor); + + ret = krb5_init_context(&context); + check_k5err(context, "krb5_init_context", ret); + + if (krb5_pac_get_types(context, pac, &len, &types) == 0) { + printf("PAC buffer types:"); + for (i = 0; i < len; i++) + printf(" %d", types[i]); + printf("\n"); + free(types); + } + + (void)gss_release_any_name_mapping(&minor, name, &type_id, + (gss_any_t *)&pac); +} + +static void +init_accept_sec_context(gss_cred_id_t verifier_cred_handle) +{ + OM_uint32 major, minor, flags; + gss_name_t source_name = GSS_C_NO_NAME, target_name = GSS_C_NO_NAME; + gss_ctx_id_t initiator_context, acceptor_context; + gss_OID mech = use_spnego ? &mech_spnego : &mech_krb5; + + major = gss_inquire_cred(&minor, verifier_cred_handle, &target_name, NULL, + NULL, NULL); + check_gsserr("gss_inquire_cred", major, minor); + + display_canon_name("Target name", target_name, &mech_krb5); + + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + establish_contexts(mech, verifier_cred_handle, verifier_cred_handle, + target_name, flags, &initiator_context, + &acceptor_context, &source_name, NULL, NULL); + + display_canon_name("Source name", source_name, &mech_krb5); + enumerate_attributes(source_name, 1); + test_export_import_name(source_name); + test_map_name_to_any(source_name); + + (void)gss_release_name(&minor, &source_name); + (void)gss_release_name(&minor, &target_name); + (void)gss_delete_sec_context(&minor, &initiator_context, NULL); + (void)gss_delete_sec_context(&minor, &acceptor_context, NULL); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major; + gss_cred_id_t cred_handle = GSS_C_NO_CREDENTIAL; + gss_OID_set mechs, actual_mechs = GSS_C_NO_OID_SET; + gss_name_t tmp_name, name; + + if (argc > 1 && strcmp(argv[1], "--spnego") == 0) { + use_spnego++; + argc--; + argv++; + } + + if (argc < 2) { + fprintf(stderr, "Usage: %s [--spnego] principal [keytab]\n", argv[0]); + exit(1); + } + + tmp_name = import_name(argv[1]); + major = gss_canonicalize_name(&minor, tmp_name, &mech_krb5, &name); + check_gsserr("gss_canonicalze_name", major, minor); + (void)gss_release_name(&minor, &tmp_name); + + test_greet_authz_data(name); + + if (argc >= 3) { + major = krb5_gss_register_acceptor_identity(argv[2]); + check_gsserr("krb5_gss_register_acceptor_identity", major, minor); + } + + mechs = use_spnego ? &mechset_spnego : &mechset_krb5; + + /* get default cred */ + major = gss_acquire_cred(&minor, name, GSS_C_INDEFINITE, mechs, GSS_C_BOTH, + &cred_handle, &actual_mechs, NULL); + check_gsserr("gss_acquire_cred", major, minor); + + (void)gss_release_oid_set(&minor, &actual_mechs); + + init_accept_sec_context(cred_handle); + + printf("\n"); + + (void)gss_release_cred(&minor, &cred_handle); + (void)gss_release_oid_set(&minor, &actual_mechs); + (void)gss_release_name(&minor, &name); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_negoex.py b/krb5-1.21.3/src/tests/gssapi/t_negoex.py new file mode 100644 index 00000000..a218899c --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_negoex.py @@ -0,0 +1,149 @@ +from k5test import * + +# The next arc after 2.25 is supposed to be a single-integer UUID, but +# since our gss_str_to_oid() can't handle arc values that don't fit in +# an unsigned long, we use random unsigned 32-bit integers instead. +# The final octet if the OID encoding will be used to identify the +# mechanism when changing the behavior of just one mech. +nxtest_oid1 = '2.25.1414534758' # final octet is 102 (0x66) +nxtest_oid2 = '2.25.1175737388' # final octet is 44 (0x2C) +nxtest_path = os.path.join(buildtop, 'plugins', 'gssapi', 'negoextest', + 'gss_negoextest.so') + +# Test gss_add_cred(). +realm = K5Realm(create_kdb=False) +with open(realm.gss_mech_config, 'w') as f: + f.write('negoextest %s %s\n' % (nxtest_oid1, nxtest_path)) + f.write('negoextest %s %s\n' % (nxtest_oid2, nxtest_path)) + +def test(envvars, **kw): + # Python 3.5: e = {**realm.env, **vars} + e = realm.env.copy() + e.update(envvars) + realm.run(['./t_context', 'h:host'], env=e, **kw) + +# Test varying numbers of hops, and spot-check that messages are sent +# in the appropriate sequence. + +mark('One hop') +msgs = ('sending [0]INITIATOR_NEGO: c0a28569-66ac-0000-0000-000000000000 ' + 'd1b08469-2ca8-0000-0000-000000000000', + 'sending [1]INITIATOR_META_DATA: c0a28569-66ac', + 'sending [2]INITIATOR_META_DATA: d1b08469-2ca8', + 'sending [3]AP_REQUEST: c0a28569-66ac', + 'sending [4]VERIFY: c0a28569-66ac', + 'received [0]INITIATOR_NEGO: c0a28569-66ac-0000-0000-000000000000 ' + 'd1b08469-2ca8-0000-0000-000000000000', + 'received [1]INITIATOR_META_DATA: c0a28569-66ac', + 'received [2]INITIATOR_META_DATA: d1b08469-2ca8', + 'received [3]AP_REQUEST: c0a28569-66ac', + 'received [4]VERIFY: c0a28569-66ac', + 'sending [5]ACCEPTOR_NEGO: c0a28569-66ac-0000-0000-000000000000 ' + 'd1b08469-2ca8-0000-0000-000000000000', + 'sending [6]ACCEPTOR_META_DATA: c0a28569-66ac', + 'sending [7]ACCEPTOR_META_DATA: d1b08469-2ca8', + 'sending [8]VERIFY: c0a28569-66ac', + 'received [5]ACCEPTOR_NEGO: c0a28569-66ac-0000-0000-000000000000 ' + 'd1b08469-2ca8-0000-0000-000000000000', + 'received [6]ACCEPTOR_META_DATA: c0a28569-66ac', + 'received [7]ACCEPTOR_META_DATA: d1b08469-2ca8', + 'received [8]VERIFY: c0a28569-66ac') +test({'HOPS': '1'}, expected_trace=msgs) + +mark('Two hops') +msgs = ('sending [7]CHALLENGE', 'sending [8]VERIFY', 'received [8]VERIFY', + 'sending [9]VERIFY') +test({'HOPS': '2'}, expected_trace=msgs) + +mark('Three hops') +msgs = ('sending [8]AP_REQUEST', 'sending [9]VERIFY', 'received [8]AP_REQUEST', + 'sending [10]VERIFY') +test({'HOPS': '3'}, expected_trace=msgs) + +mark('Four hops') +msgs = ('sending [9]CHALLENGE', 'sending [10]VERIFY', 'received [9]CHALLENGE', + 'sending [11]VERIFY') +test({'HOPS': '4'}, expected_trace=msgs) + +mark('Early keys, three hops') +msgs = ('sending [4]VERIFY', 'sending [9]VERIFY', 'sending [10]AP_REQUEST') +test({'HOPS': '3', 'KEY': 'always'}, expected_trace=msgs) + +mark('Early keys, four hops') +msgs = ('sending [4]VERIFY', 'sending [9]VERIFY', 'sending [10]AP_REQUEST', + 'sending [11]CHALLENGE') +test({'HOPS': '4', 'KEY': 'always'}, expected_trace=msgs) + +mark('No keys') +test({'KEY': 'never'}, expected_code=1, expected_msg='No NegoEx verify key') + +mark('No optimistic token') +msgs = ('sending [3]ACCEPTOR_NEGO', 'sending [6]AP_REQUEST', + 'sending [7]VERIFY', 'sending [8]VERIFY') +test({'NEGOEX_NO_OPTIMISTIC_TOKEN': ''}, expected_trace=msgs) + +mark('First mech initiator query fail') +msgs = ('sending [0]INITIATOR_NEGO: d1b08469-2ca8-0000-0000-000000000000', + 'sending [2]AP_REQUEST', 'sending [3]VERIFY', + 'sending [4]ACCEPTOR_NEGO: d1b08469-2ca8-0000-0000-000000000000', + 'sending [6]VERIFY') +test({'INIT_QUERY_FAIL': '102'}, expected_trace=msgs) + +mark('First mech acceptor query fail') +msgs = ('sending [0]INITIATOR_NEGO: c0a28569-66ac-0000-0000-000000000000 ' + 'd1b08469-2ca8-0000-0000-000000000000', + 'sending [3]AP_REQUEST: c0a28569-66ac', + 'sending [4]VERIFY: c0a28569-66ac', + 'sending [5]ACCEPTOR_NEGO: d1b08469-2ca8-0000-0000-000000000000', + 'sending [7]AP_REQUEST: d1b08469-2ca8', + 'sending [8]VERIFY: d1b08469-2ca8', + 'sending [9]VERIFY: d1b08469-2ca8') +test({'ACCEPT_QUERY_FAIL': '102'}, expected_trace=msgs) + +# Same messages as previous test. +mark('First mech acceptor exchange fail') +test({'ACCEPT_EXCHANGE_FAIL': '102'}, expected_trace=msgs) + +# Fail the optimistic mech's gss_exchange_meta_data() in the +# initiator. Since the acceptor has effectively selected the +# optimistic mech, this causes the authentication to fail. +mark('First mech initiator exchange fail, one hop') +test({'HOPS': '1', 'INIT_EXCHANGE_FAIL': '102'}, expected_code=1, + expected_msg='No mutually supported NegoEx authentication schemes') +mark('First mech initiator exchange fail, two hops, early keys') +test({'HOPS': '2', 'INIT_EXCHANGE_FAIL': '102', 'KEY': 'always'}, + expected_code=1, + expected_msg='No mutually supported NegoEx authentication schemes') +mark('First mech initiator exchange fail, two hops') +test({'HOPS': '2', 'INIT_EXCHANGE_FAIL': '102'}, expected_code=1, + expected_msg='No mutually supported NegoEx authentication schemes') + +mark('First mech init_sec_context fail') +msgs = ('sending [0]INITIATOR_NEGO: d1b08469-2ca8-0000-0000-000000000000', + 'sending [2]AP_REQUEST', 'sending [3]VERIFY', 'sending [6]VERIFY') +test({'INIT_FAIL': '102'}, expected_trace=msgs) + +mark('First mech accept_sec_context fail') +test({'HOPS': '2', 'ACCEPT_FAIL': '102'}, expected_code=1, + expected_msg='failure from acceptor') + +mark('ALERT from acceptor to initiator') +msgs = ('sending [3]AP_REQUEST', 'sending [4]VERIFY', 'sending [8]CHALLENGE', + 'sending [9]ALERT', 'received [9]ALERT', 'sending [10]AP_REQUEST', + 'sending [11]VERIFY', 'sending [12]VERIFY') +test({'HOPS': '3', 'KEY': 'init-always'}, expected_trace=msgs) + +mark('ALERT from initiator to acceptor') +msgs = ('sending [3]AP_REQUEST', 'sending [7]CHALLENGE', 'sending [8]VERIFY', + 'sending [9]AP_REQUEST', 'sending [10]ALERT', 'received [10]ALERT', + 'sending [11]CHALLENGE', 'sending [12]VERIFY', 'sending [13]VERIFY') +test({'HOPS': '4', 'KEY': 'accept-always'}, expected_trace=()) + +mark('channel bindings') +e = realm.env.copy() +e.update({'HOPS': '1', 'GSS_INIT_BINDING': 'a', 'GSS_ACCEPT_BINDING': 'b'}) +# The test mech will verify that the bindings are communicated to the +# mech, but does not set the channel-bound flag. +realm.run(['./t_bindings', '-s', 'h:host', 'a', 'b'], env=e, expected_msg='no') + +success('NegoEx tests') diff --git a/krb5-1.21.3/src/tests/gssapi/t_oid.c b/krb5-1.21.3/src/tests/gssapi/t_oid.c new file mode 100644 index 00000000..1c9d3941 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_oid.c @@ -0,0 +1,224 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_oid.c - Test OID manipulation functions */ +/* + * Copyright (C) 2012 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. + */ + +#include +#include +#include + +#include "common.h" + +static struct { + char *canonical; + char *variant; + gss_OID_desc oid; +} tests[] = { + /* GSS_C_NT_USER_NAME */ + { "{ 1 2 840 113554 1 2 1 1 }", "1.2.840.113554.1.2.1.1", + { 10, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x01\x01" } }, + /* GSS_C_NT_MACHINE_UID_NAME */ + { "{ 1 2 840 113554 1 2 1 2 }", "1 2 840 113554 1 2 1 2", + { 10, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x01\x02" } }, + /* GSS_C_NT_STRING_UID_NAME */ + { "{ 1 2 840 113554 1 2 1 3 }", "{1 2 840 113554 1 2 1 3}", + { 10, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x01\x03" } }, + /* GSS_C_NT_HOSTBASED_SERVICE_X */ + { "{ 1 3 6 1 5 6 2 }", "{ 1 3 6 1 5 6 2 }", + { 6, "\x2B\x06\x01\x05\x06\x02" } }, + /* GSS_C_NT_ANONYMOUS */ + { "{ 1 3 6 1 5 6 3 }", "{ 01 03 06 01 05 06 03 }", + { 6, "\x2B\x06\x01\x05\x06\x03" } }, + /* GSS_KRB5_NT_PRINCIPAL_NAME */ + { "{ 1 2 840 113554 1 2 2 1 }", " {01 2 840 113554 1 2 2 1 } ", + { 10, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x01" } }, + /* GSS_KRB5_NT_ENTERPRISE_NAME */ + { "{ 1 2 840 113554 1 2 2 6 }", " {1.2.840.113554.1.2.2.6} ", + { 10, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x06" } }, + /* gss_krb5_nt_principal */ + { "{ 1 2 840 113554 1 2 2 2 }", "{1.2.840.113554.1.2.2.2}", + { 10, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x02" } }, + /* gss_mech_krb5 */ + { "{ 1 2 840 113554 1 2 2 }", "{ 1.2.840.113554.1.2.2 }", + { 9, "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02" } }, + /* gss_mech_krb5_old */ + { "{ 1 3 5 1 5 2 }", "001 . 003 . 005 . 001 . 005 . 002", + { 5, "\x2B\x05\x01\x05\x02" } }, + /* gss_mech_krb5_wrong */ + { "{ 1 2 840 48018 1 2 2 }", "1.2.840.48018.1.2.2 trailing garbage", + { 9, "\x2A\x86\x48\x82\xF7\x12\x01\x02\x02" } }, + /* gss_mech_iakerb */ + { "{ 1 3 6 1 5 2 5 }", "{ 1 3 6 1 5 2 5 } trailing garbage", + { 6, "\x2B\x06\x01\x05\x02\x05" } }, + /* SPNEGO */ + { "{ 1 3 6 1 5 5 2 }", "{1 3 6 1 5 5 2} trailing garbage", + { 6, "\x2B\x06\x01\x05\x05\x02" } }, + /* Edge cases for the first two arcs */ + { "{ 0 0 }", NULL, { 1, "\x00" } }, + { "{ 0 39 }", NULL, { 1, "\x27" } }, + { "{ 1 0 }", NULL, { 1, "\x28" } }, + { "{ 1 39 }", NULL, { 1, "\x4F" } }, + { "{ 2 0 }", NULL, { 1, "\x50" } }, + { "{ 2 40 }", NULL, { 1, "\x78" } }, + { "{ 2 47 }", NULL, { 1, "\x7F" } }, + { "{ 2 48 }", NULL, { 2, "\x81\x00" } }, + { "{ 2 16304 }", NULL, { 3, "\x81\x80\x00" } }, + /* Zero-valued arcs */ + { "{ 0 0 0 }", NULL, { 2, "\x00\x00" } }, + { "{ 0 0 1 0 }", NULL, { 3, "\x00\x01\x00" } }, + { "{ 0 0 128 0 }", NULL, { 4, "\x00\x81\x00\x00 " } }, + { "{ 0 0 0 1 }", NULL, { 3, "\x00\x00\x01" } }, + { "{ 0 0 128 0 1 0 128 }", NULL, + { 8, "\x00\x81\x00\x00\x01\x00\x81\x00 " } } +}; + +static char *invalid_strings[] = { + "", + "{}", + "{", + "}", + " ", + " { } ", + "x", + "+1 1", + "-1.1", + "1.+0", + "+0.1", + "{ 1 garbage }", + "{ 1 }", + "{ 0 40 }", + "{ 1 40 }", + "{ 1 128 }", + "{ 1 1", + "{ 1 2 3 4 +5 }", + "{ 1.2.-3.4.5 }" +}; + +static int +oid_equal(gss_OID o1, gss_OID o2) +{ + return o1->length == o2->length && + memcmp(o1->elements, o2->elements, o1->length) == 0; +} + +int +main() +{ + size_t i; + OM_uint32 major, minor; + gss_buffer_desc buf; + gss_OID oid; + gss_OID_set set; + int status = 0, present; + + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { + /* Check that this test's OID converts to its canonical string form. */ + major = gss_oid_to_str(&minor, &tests[i].oid, &buf); + check_gsserr("gss_oid_to_str", major, minor); + if (buf.length != strlen(tests[i].canonical) + 1 || + memcmp(buf.value, tests[i].canonical, buf.length) != 0) { + status = 1; + printf("test %d: OID converts to %.*s, wanted %s\n", (int)i, + (int)buf.length, (char *)buf.value, tests[i].canonical); + } + (void)gss_release_buffer(&minor, &buf); + + /* Check that this test's canonical string form converts to its OID. */ + buf.value = tests[i].canonical; + buf.length = strlen(tests[i].canonical); + major = gss_str_to_oid(&minor, &buf, &oid); + check_gsserr("gss_str_to_oid", major, minor); + if (!oid_equal(oid, &tests[i].oid)) { + status = 1; + printf("test %d: %s converts to wrong OID\n", (int)i, + tests[i].canonical); + display_oid("wanted", &tests[i].oid); + display_oid("actual", oid); + } + (void)gss_release_oid(&minor, &oid); + + /* Check that this test's variant string form converts to its OID. */ + if (tests[i].variant == NULL) + continue; + buf.value = tests[i].variant; + buf.length = strlen(tests[i].variant); + major = gss_str_to_oid(&minor, &buf, &oid); + check_gsserr("gss_str_to_oid", major, minor); + if (!oid_equal(oid, &tests[i].oid)) { + status = 1; + printf("test %d: %s converts to wrong OID\n", (int)i, + tests[i].variant); + display_oid("wanted", &tests[i].oid); + display_oid("actual", oid); + } + (void)gss_release_oid(&minor, &oid); + } + + for (i = 0; i < sizeof(invalid_strings) / sizeof(*invalid_strings); i++) { + buf.value = invalid_strings[i]; + buf.length = strlen(invalid_strings[i]); + major = gss_str_to_oid(&minor, &buf, &oid); + if (major == GSS_S_COMPLETE) { + status = 1; + printf("invalid %d: %s converted when it should not have\n", + (int)i, invalid_strings[i]); + (void)gss_release_oid(&minor, &oid); + } + } + + major = gss_create_empty_oid_set(&minor, &set); + check_gsserr("gss_create_empty_oid_set", major, minor); + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { + major = gss_add_oid_set_member(&minor, &tests[i].oid, &set); + check_gsserr("gss_add_oid_set_member", major, minor); + } + if (set->count != i) { + status = 1; + printf("oid set has wrong size: wanted %d, actual %d\n", (int)i, + (int)set->count); + } + for (i = 0; i < set->count; i++) { + if (!oid_equal(&set->elements[i], &tests[i].oid)) { + status = 1; + printf("oid set has wrong element %d\n", (int)i); + display_oid("wanted", &tests[i].oid); + display_oid("actual", &set->elements[i]); + } + major = gss_test_oid_set_member(&minor, &tests[i].oid, set, &present); + check_gsserr("gss_test_oid_set_member", major, minor); + if (!present) { + status = 1; + printf("oid set does not contain OID %d\n", (int)i); + display_oid("wanted", &tests[i].oid); + } + } + (void)gss_release_oid_set(&minor, &set); + return status; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_pcontok.c b/krb5-1.21.3/src/tests/gssapi/t_pcontok.c new file mode 100644 index 00000000..7368f752 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_pcontok.c @@ -0,0 +1,190 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_pcontok.c - gss_process_context_token tests */ +/* + * Copyright (C) 2014 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. + */ + +/* + * This test program exercises krb5 gss_process_context_token. It first + * establishes a context to a named target. Then, if the resulting context + * uses RFC 1964, it creates a context deletion token from the acceptor to the + * initiator and passes it to the initiator using gss_process_context_token. + * If the established context uses RFC 4121, this program feeds a made-up + * context token to gss_process_context_token and checks for the expected + * error. + */ + +#include "k5-int.h" +#include "common.h" + +#define SGN_ALG_HMAC_SHA1_DES3_KD 0x04 +#define SGN_ALG_HMAC_MD5 0x11 + +/* + * Create a valid RFC 1964 context deletion token using the information in * + * lctx. We must do this by hand since we no longer create context deletion + * tokens from gss_delete_sec_context. + */ +static void +make_delete_token(gss_krb5_lucid_context_v1_t *lctx, gss_buffer_desc *out) +{ + krb5_error_code ret; + krb5_context context; + krb5_keyblock seqkb; + krb5_key seq; + krb5_checksum cksum; + krb5_cksumtype cktype; + krb5_keyusage ckusage; + krb5_crypto_iov iov; + krb5_data d; + size_t cksize, tlen; + unsigned char *token, *ptr, iv[8]; + gss_krb5_lucid_key_t *lkey = &lctx->rfc1964_kd.ctx_key; + int signalg = lctx->rfc1964_kd.sign_alg; + + ret = krb5_init_context(&context); + check_k5err(context, "krb5_init_context", ret); + + seqkb.enctype = lkey->type; + seqkb.length = lkey->length; + seqkb.contents = lkey->data; + ret = krb5_k_create_key(context, &seqkb, &seq); + check_k5err(context, "krb5_k_create_key", ret); + + if (signalg == SGN_ALG_HMAC_SHA1_DES3_KD) { + cktype = CKSUMTYPE_HMAC_SHA1_DES3; + cksize = 20; + ckusage = 23; + } else if (signalg == SGN_ALG_HMAC_MD5) { + cktype = CKSUMTYPE_HMAC_MD5_ARCFOUR; + cksize = 8; + ckusage = 15; + } else { + abort(); + } + + tlen = 20 + mech_krb5.length + cksize; + token = malloc(tlen); + assert(token != NULL); + + /* Create the ASN.1 wrapper (4 + mech_krb5.length bytes). Assume the ASN.1 + * lengths fit in one byte since deletion tokens are short. */ + ptr = token; + *ptr++ = 0x60; + *ptr++ = tlen - 2; + *ptr++ = 0x06; + *ptr++ = mech_krb5.length; + memcpy(ptr, mech_krb5.elements, mech_krb5.length); + ptr += mech_krb5.length; + + /* Create the RFC 1964 token header (8 bytes). */ + *ptr++ = 0x01; + *ptr++ = 0x02; + store_16_le(signalg, ptr); + ptr += 2; + *ptr++ = 0xFF; + *ptr++ = 0xFF; + *ptr++ = 0xFF; + *ptr++ = 0xFF; + + /* Create the checksum (cksize bytes at offset 8 from the header). */ + d = make_data(ptr - 8, 8); + ret = krb5_k_make_checksum(context, cktype, seq, ckusage, &d, &cksum); + check_k5err(context, "krb5_k_make_checksum", ret); + memcpy(ptr + 8, cksum.contents, cksize); + + /* Create the sequence number (8 bytes). */ + iov.flags = KRB5_CRYPTO_TYPE_DATA; + iov.data = make_data(ptr, 8); + ptr[4] = ptr[5] = ptr[6] = ptr[7] = lctx->initiate ? 0 : 0xFF; + memcpy(iv, ptr + 8, 8); + d = make_data(iv, 8); + if (signalg == SGN_ALG_HMAC_MD5) { + store_32_be(lctx->send_seq, ptr); + ret = krb5int_arcfour_gsscrypt(&seq->keyblock, 0, &d, &iov, 1); + check_k5err(context, "krb5int_arcfour_gsscrypt(seq)", ret); + } else { + store_32_le(lctx->send_seq, ptr); + ret = krb5_k_encrypt_iov(context, seq, 24, &d, &iov, 1); + check_k5err(context, "krb5_k_encrypt_iov(seq)", ret); + } + + krb5_free_checksum_contents(context, &cksum); + krb5_k_free_key(context, seq); + krb5_free_context(context); + + out->length = tlen; + out->value = token; +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major, flags; + gss_name_t tname; + gss_buffer_desc token, in = GSS_C_EMPTY_BUFFER, out; + gss_ctx_id_t ictx, actx; + gss_krb5_lucid_context_v1_t *lctx; + void *lptr; + + assert(argc == 2); + tname = import_name(argv[1]); + + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + establish_contexts(&mech_krb5, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, + tname, flags, &ictx, &actx, NULL, NULL, NULL); + + /* Export the acceptor context to a lucid context so we can look inside. */ + major = gss_krb5_export_lucid_sec_context(&minor, &actx, 1, &lptr); + check_gsserr("gss_export_lucid_sec_context", major, minor); + lctx = lptr; + if (!lctx->protocol) { + /* Make an RFC 1964 context deletion token and pass it to + * gss_process_context_token. */ + make_delete_token(lctx, &token); + major = gss_process_context_token(&minor, ictx, &token); + free(token.value); + check_gsserr("gss_process_context_token", major, minor); + /* Check for the appropriate major code from gss_wrap. */ + major = gss_wrap(&minor, ictx, 1, GSS_C_QOP_DEFAULT, &in, NULL, &out); + assert(major == GSS_S_NO_CONTEXT); + } else { + /* RFC 4121 defines no context deletion token, so try passing something + * arbitrary and check for the appropriate major code. */ + token.value = "abcd"; + token.length = 4; + major = gss_process_context_token(&minor, ictx, &token); + assert(major == GSS_S_DEFECTIVE_TOKEN); + } + + (void)gss_release_name(&minor, &tname); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_krb5_free_lucid_sec_context(&minor, lptr); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_prf.c b/krb5-1.21.3/src/tests/gssapi/t_prf.c new file mode 100644 index 00000000..f71774cd --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_prf.c @@ -0,0 +1,190 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2014 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "k5-hex.h" +#include "common.h" +#include "mglueP.h" +#include "gssapiP_krb5.h" + +static const char inputstr[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz123456789"; + +/* For each test, out1 corresponds to key1 with an empty input, and out2 + * corresponds to key2 with the above 61-byte input string. */ +static struct { + krb5_enctype enctype; + const char *key1; + const char *out1; + const char *key2; + const char *out2; +} tests[] = { + { ENCTYPE_DES3_CBC_SHA1, + "70378A19CD64134580C27C0115D6B34A1CF2FEECEF9886A2", + "9F8D127C520BB826BFF3E0FE5EF352389C17E0C073D9" + "AC4A333D644D21BA3EF24F4A886D143F85AC9F6377FB", + "3452A167DF1094BA1089E0A20E9E51ABEF1525922558B69E", + "6BF24FABC858F8DD9752E4FCD331BB831F238B5BE190" + "4EEA42E38F7A60C588F075C5C96A67E7F8B7BD0AECF4" }, + { ENCTYPE_ARCFOUR_HMAC, + "3BB3AE288C12B3B9D06B208A4151B3B6", + "9AEA11A3BCF3C53F1F91F5A0BA2132E2501ADF5F3C28" + "3C8A983AB88757CE865A22132D6100EAD63E9E291AFA", + "6DB7B33A01BD2B72F7655CB7B3D5FA0B", + "CDA9A544869FC84873B692663A82AFDA101C8611498B" + "A46138B01E927C9B95EEC953B562807434037837DDDF" }, + { ENCTYPE_AES128_CTS_HMAC_SHA1_96, + "6C742096EB896230312B73972FA28B5D", + "94208D982FC1BB7778128BDD77904420B45C9DA699F3" + "117BCE66E39602128EF0296611A6D191A5828530F20F", + "FA61138C109D834A477D24C7311BE6DA", + "0FAEDF0F842CC834FEE750487E1B622739286B975FE5" + "B7F45AB053143C75CA0DF5D3D4BBB80F6A616C7C9027" }, + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, + "08FCDAFD5832611B73BA7B497FEBFF8C954B4B58031CAD9B977C3B8C25192FD6", + "E627EFC14EF5B6D629F830C7109DEA0D3D7D36E8CD57" + "A1F301C5452494A1928F05AFFBEE3360232209D3BE0D", + "F5B68B7823D8944F33F41541B4E4D38C9B2934F8D16334A796645B066152B4BE", + "112F2B2D878590653CCC7DE278E9F0AA46FA5A380B62" + "59F774CB7C134FCD37F61A50FD0D9F89BF8FE1A6B593" }, + { ENCTYPE_CAMELLIA128_CTS_CMAC, + "866E0466A178279A32AC0BDA92B72AEB", + "97FBB354BF341C3A160DCC86A7A910FDA824601DF677" + "68797BACEEBF5D250AE929DEC9760772084267F50A54", + "D4893FD37DA1A211E12DD1E03E0F03B7", + "1DEE2FF126CA563A2A2326B9DD3F0095013257414C83" + "FAD4398901013D55F367C82681186B7B2FE62F746BA4" }, + { ENCTYPE_CAMELLIA256_CTS_CMAC, + "203071B1AE77BD3D6FCE70174AF95C225B1CED46B35CF52B6479EFEB47E6B063", + "9B30020634C10FDA28420CEE7B96B70A90A771CED43A" + "D8346554163E5949CBAE2FB8EF36AFB6B32CE75116A0", + "A171AD582C1AFBBAD52ABD622EE6B6A14D19BF95C6914B2BA40FFD99A88EC660", + "A47CBB6E104DCC77E4DB48A7A474B977F2FB6A7A1AB6" + "52317D50508AE72B7BE2E4E4BA24164E029CBACF786B" }, + { ENCTYPE_AES128_CTS_HMAC_SHA256_128, + "089BCA48B105EA6EA77CA5D2F39DC5E7", + "ED1736209B7C59C9F6A3AE8CCC8A7C97ADFDD11688AD" + "F304F2F74252CBACD311A2D9253211FDA49745CE4F62", + "3705D96080C17728A0E800EAB6E0D23C", + "2BB41B183D76D8D5B30CBB049A7EFE9F350EFA058DC2" + "C4D868308D354A7B199BE6FD1F22B53C038BC6036581" }, + { ENCTYPE_AES256_CTS_HMAC_SHA384_192, + "45BD806DBF6A833A9CFFC1C94589A222367A79BC21C413718906E9F578A78467", + "1C613AE8B77A3B4D783F3DCE6C9178FC025E87F48A44" + "784A69CB5FC697FE266A6141905067EF78566D309085", + "6D404D37FAF79F9DF0D33568D320669800EB4836472EA8A026D16B7182460C52", + "D15944B0A44508D1E61213F6455F292A02298F870C01" + "A3F74AD0345A4A6651EBE101976E933F32D44F0B5947" }, +}; + +/* Decode hexstr into out. No length checking. */ +static size_t +fromhex(const char *hexstr, unsigned char *out) +{ + uint8_t *bytes; + size_t len; + + if (k5_hex_decode(hexstr, &bytes, &len) != 0) + abort(); + memcpy(out, bytes, len); + free(bytes); + return len; +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major; + gss_ctx_id_t context; + gss_union_ctx_id_desc uctx; + krb5_gss_ctx_id_rec kgctx; + krb5_key k1, k2; + krb5_keyblock kb1, kb2; + gss_buffer_desc in, out; + unsigned char k1buf[32], k2buf[32], outbuf[44]; + size_t i; + + /* + * Fake up just enough of a krb5 GSS context to make gss_pseudo_random + * work, with chosen subkeys and acceptor subkeys. If we implement + * gss_import_lucid_sec_context, we can rewrite this to use public + * interfaces and stop using private headers and internal knowledge of the + * implementation. + */ + context = (gss_ctx_id_t)&uctx; + memset(&uctx, 0, sizeof(uctx)); + uctx.mech_type = &mech_krb5; + uctx.internal_ctx_id = (gss_ctx_id_t)&kgctx; + memset(&kgctx, 0, sizeof(kgctx)); + kgctx.k5_context = NULL; + kgctx.established = 1; + kgctx.have_acceptor_subkey = 1; + kb1.contents = k1buf; + kb2.contents = k2buf; + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { + /* Set up the keys for this test. */ + kb1.enctype = tests[i].enctype; + kb1.length = fromhex(tests[i].key1, k1buf); + check_k5err(NULL, "create_key", krb5_k_create_key(NULL, &kb1, &k1)); + kgctx.subkey = k1; + kb2.enctype = tests[i].enctype; + kb2.length = fromhex(tests[i].key2, k2buf); + check_k5err(NULL, "create_key", krb5_k_create_key(NULL, &kb2, &k2)); + kgctx.acceptor_subkey = k2; + + /* Generate a PRF value with the subkey and an empty input, and compare + * it to the first expected output. */ + in.length = 0; + in.value = NULL; + major = gss_pseudo_random(&minor, context, GSS_C_PRF_KEY_PARTIAL, &in, + 44, &out); + check_gsserr("gss_pseudo_random", major, minor); + (void)fromhex(tests[i].out1, outbuf); + assert(out.length == 44 && memcmp(out.value, outbuf, 44) == 0); + (void)gss_release_buffer(&minor, &out); + + /* Generate a PRF value with the acceptor subkey and the 61-byte input + * string, and compare it to the second expected output. */ + in.length = strlen(inputstr); + in.value = (char *)inputstr; + major = gss_pseudo_random(&minor, context, GSS_C_PRF_KEY_FULL, &in, 44, + &out); + check_gsserr("gss_pseudo_random", major, minor); + (void)fromhex(tests[i].out2, outbuf); + assert(out.length == 44 && memcmp(out.value, outbuf, 44) == 0); + (void)gss_release_buffer(&minor, &out); + + /* Also check that generating zero bytes of output works. */ + major = gss_pseudo_random(&minor, context, GSS_C_PRF_KEY_FULL, &in, 0, + &out); + check_gsserr("gss_pseudo_random", major, minor); + assert(out.length == 0); + (void)gss_release_buffer(&minor, &out); + + krb5_k_free_key(NULL, k1); + krb5_k_free_key(NULL, k2); + } + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_s4u.c b/krb5-1.21.3/src/tests/gssapi/t_s4u.c new file mode 100644 index 00000000..0400f8f6 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_s4u.c @@ -0,0 +1,334 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * Test program for protocol transition (S4U2Self) and constrained delegation + * (S4U2Proxy) + * + * Note: because of name canonicalization, the following tips may help + * when configuring with Active Directory: + * + * - Create a computer account FOO$ + * - Set the UPN to host/foo.domain (no suffix); this is necessary to + * be able to send an AS-REQ as this principal, otherwise you would + * need to use the canonical name (FOO$), which will cause principal + * comparison errors in gss_accept_sec_context(). + * - Add a SPN of host/foo.domain + * - Configure the computer account to support constrained delegation with + * protocol transition (Trust this computer for delegation to specified + * services only / Use any authentication protocol) + * - Add host/foo.domain to the keytab (possibly easiest to do this + * with ktadd) + * + * For S4U2Proxy to work the TGT must be forwardable too. + * + * Usage eg: + * + * kinit -k -t test.keytab -f 'host/test.win.mit.edu@WIN.MIT.EDU' + * ./t_s4u p:delegtest@WIN.MIT.EDU p:HOST/WIN-EQ7E4AA2WR8.win.mit.edu@WIN.MIT.EDU test.keytab + */ + +#include +#include +#include + +#include "common.h" + +static int use_spnego = 0; + +static void +test_greet_authz_data(gss_name_t *name) +{ + OM_uint32 major, minor; + gss_buffer_desc attr; + gss_buffer_desc value; + gss_name_t canon; + + major = gss_canonicalize_name(&minor, *name, &mech_krb5, &canon); + check_gsserr("gss_canonicalize_name", major, minor); + + attr.value = "greet:greeting"; + attr.length = strlen((char *)attr.value); + + value.value = "Hello, acceptor world!"; + value.length = strlen((char *)value.value); + + major = gss_set_name_attribute(&minor, canon, 1, &attr, &value); + if (major == GSS_S_UNAVAILABLE) { + (void)gss_release_name(&minor, &canon); + return; + } + check_gsserr("gss_set_name_attribute", major, minor); + gss_release_name(&minor, name); + *name = canon; +} + +static void +init_accept_sec_context(gss_cred_id_t claimant_cred_handle, + gss_cred_id_t verifier_cred_handle, + gss_cred_id_t *deleg_cred_handle) +{ + OM_uint32 major, minor, flags; + gss_name_t source_name = GSS_C_NO_NAME, target_name = GSS_C_NO_NAME; + gss_ctx_id_t initiator_context, acceptor_context; + gss_OID mech = GSS_C_NO_OID; + + *deleg_cred_handle = GSS_C_NO_CREDENTIAL; + + major = gss_inquire_cred(&minor, verifier_cred_handle, &target_name, NULL, + NULL, NULL); + check_gsserr("gss_inquire_cred", major, minor); + + display_canon_name("Target name", target_name, &mech_krb5); + + mech = use_spnego ? &mech_spnego : &mech_krb5; + display_oid("Target mech", mech); + + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + establish_contexts(mech, claimant_cred_handle, verifier_cred_handle, + target_name, flags, &initiator_context, + &acceptor_context, &source_name, &mech, + deleg_cred_handle); + + display_canon_name("Source name", source_name, &mech_krb5); + display_oid("Source mech", mech); + enumerate_attributes(source_name, 1); + + (void)gss_release_name(&minor, &source_name); + (void)gss_release_name(&minor, &target_name); + (void)gss_delete_sec_context(&minor, &initiator_context, NULL); + (void)gss_delete_sec_context(&minor, &acceptor_context, NULL); +} + +static void +check_ticket_count(gss_cred_id_t cred, int expected) +{ + krb5_error_code ret; + krb5_context context = NULL; + krb5_creds kcred; + krb5_cc_cursor cur; + krb5_ccache ccache; + int count = 0; + gss_key_value_set_desc store; + gss_key_value_element_desc elem; + OM_uint32 major, minor; + const char *ccname = "MEMORY:count"; + + store.count = 1; + store.elements = &elem; + elem.key = "ccache"; + elem.value = ccname; + major = gss_store_cred_into(&minor, cred, GSS_C_INITIATE, &mech_krb5, 1, 0, + &store, NULL, NULL); + check_gsserr("gss_store_cred_into", major, minor); + + ret = krb5_init_context(&context); + check_k5err(context, "krb5_init_context", ret); + + ret = krb5_cc_resolve(context, ccname, &ccache); + check_k5err(context, "krb5_cc_resolve", ret); + + ret = krb5_cc_start_seq_get(context, ccache, &cur); + check_k5err(context, "krb5_cc_start_seq_get", ret); + + while (!krb5_cc_next_cred(context, ccache, &cur, &kcred)) { + if (!krb5_is_config_principal(context, kcred.server)) + count++; + krb5_free_cred_contents(context, &kcred); + } + + ret = krb5_cc_end_seq_get(context, ccache, &cur); + check_k5err(context, "krb5_cc_end_seq_get", ret); + + if (expected != count) { + printf("Expected %d tickets but got %d\n", expected, count); + exit(1); + } + + krb5_cc_destroy(context, ccache); + krb5_free_context(context); +} + +static void +constrained_delegate(gss_OID_set desired_mechs, gss_name_t target, + gss_cred_id_t delegated_cred_handle, + gss_cred_id_t verifier_cred_handle) +{ + OM_uint32 major, minor; + gss_ctx_id_t initiator_context = GSS_C_NO_CONTEXT; + gss_name_t cred_name = GSS_C_NO_NAME; + OM_uint32 time_rec, lifetime; + gss_cred_usage_t usage; + gss_buffer_desc token; + gss_OID_set mechs; + + printf("Constrained delegation tests follow\n"); + printf("-----------------------------------\n\n"); + + if (gss_inquire_cred(&minor, verifier_cred_handle, &cred_name, + &lifetime, &usage, NULL) == GSS_S_COMPLETE) { + display_canon_name("Proxy name", cred_name, &mech_krb5); + (void)gss_release_name(&minor, &cred_name); + } + display_canon_name("Target name", target, &mech_krb5); + if (gss_inquire_cred(&minor, delegated_cred_handle, &cred_name, + &lifetime, &usage, &mechs) == GSS_S_COMPLETE) { + display_canon_name("Delegated name", cred_name, &mech_krb5); + display_oid("Delegated mech", &mechs->elements[0]); + (void)gss_release_name(&minor, &cred_name); + } + + printf("\n"); + + major = gss_init_sec_context(&minor, delegated_cred_handle, + &initiator_context, target, + mechs ? &mechs->elements[0] : &mech_krb5, + GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG, + GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, + GSS_C_NO_BUFFER, NULL, &token, NULL, + &time_rec); + check_gsserr("gss_init_sec_context", major, minor); + + (void)gss_release_buffer(&minor, &token); + (void)gss_delete_sec_context(&minor, &initiator_context, NULL); + + /* Ensure a second call does not acquire new ticket. */ + major = gss_init_sec_context(&minor, delegated_cred_handle, + &initiator_context, target, + mechs ? &mechs->elements[0] : &mech_krb5, + GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG, + GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, + GSS_C_NO_BUFFER, NULL, &token, NULL, + &time_rec); + check_gsserr("gss_init_sec_context", major, minor); + + (void)gss_release_buffer(&minor, &token); + (void)gss_delete_sec_context(&minor, &initiator_context, NULL); + (void)gss_release_oid_set(&minor, &mechs); + + /* We expect three tickets: our TGT, the evidence ticket, and the ticket to + * the target service. */ + check_ticket_count(delegated_cred_handle, 3); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major; + gss_cred_id_t impersonator_cred_handle = GSS_C_NO_CREDENTIAL; + gss_cred_id_t user_cred_handle = GSS_C_NO_CREDENTIAL; + gss_cred_id_t delegated_cred_handle = GSS_C_NO_CREDENTIAL; + gss_name_t user = GSS_C_NO_NAME, target = GSS_C_NO_NAME; + gss_OID_set mechs; + gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET; + + if (argc < 2 || argc > 5) { + fprintf(stderr, "Usage: %s [--spnego] [user] " + "[proxy-target] [keytab]\n", argv[0]); + fprintf(stderr, " proxy-target and keytab are optional\n"); + exit(1); + } + + if (strcmp(argv[1], "--spnego") == 0) { + use_spnego++; + argc--; + argv++; + } + + user = import_name(argv[1]); + + if (argc > 2 && strcmp(argv[2], "-")) + target = import_name(argv[2]); + + if (argc > 3) { + major = krb5_gss_register_acceptor_identity(argv[3]); + check_gsserr("krb5_gss_register_acceptor_identity", major, 0); + } + + /* Get default cred. */ + mechs = use_spnego ? &mechset_spnego : &mechset_krb5; + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE, mechs, + GSS_C_BOTH, &impersonator_cred_handle, NULL, + NULL); + check_gsserr("gss_acquire_cred", major, minor); + + printf("Protocol transition tests follow\n"); + printf("-----------------------------------\n\n"); + + test_greet_authz_data(&user); + + /* Get S4U2Self cred. */ + major = gss_acquire_cred_impersonate_name(&minor, impersonator_cred_handle, + user, GSS_C_INDEFINITE, mechs, + GSS_C_INITIATE, + &user_cred_handle, NULL, NULL); + check_gsserr("gss_acquire_cred_impersonate_name", major, minor); + + init_accept_sec_context(user_cred_handle, impersonator_cred_handle, + &delegated_cred_handle); + printf("\n"); + + if (target != GSS_C_NO_NAME && + delegated_cred_handle != GSS_C_NO_CREDENTIAL) { + constrained_delegate(mechs, target, delegated_cred_handle, + impersonator_cred_handle); + } else if (target != GSS_C_NO_NAME) { + fprintf(stderr, "Warning: no delegated cred handle returned\n\n"); + fprintf(stderr, "Verify:\n\n"); + fprintf(stderr, " - The TGT for the impersonating service is " + "forwardable\n"); + fprintf(stderr, " - The T2A4D flag set on the impersonating service's " + "UAC\n"); + fprintf(stderr, " - The user is not marked sensitive and cannot be " + "delegated\n"); + fprintf(stderr, "\n"); + } + + if (delegated_cred_handle != GSS_C_NO_CREDENTIAL) { + /* Inquire impersonator status. */ + major = gss_inquire_cred_by_oid(&minor, user_cred_handle, + GSS_KRB5_GET_CRED_IMPERSONATOR, + &bufset); + check_gsserr("gss_inquire_cred_by_oid", major, minor); + if (bufset->count == 0) + errout("gss_inquire_cred_by_oid(user) returned NO impersonator"); + (void)gss_release_buffer_set(&minor, &bufset); + + major = gss_inquire_cred_by_oid(&minor, impersonator_cred_handle, + GSS_KRB5_GET_CRED_IMPERSONATOR, + &bufset); + check_gsserr("gss_inquire_cred_by_oid", major, minor); + if (bufset->count != 0) + errout("gss_inquire_cred_by_oid(svc) returned an impersonator"); + (void)gss_release_buffer_set(&minor, &bufset); + } + + (void)gss_release_name(&minor, &user); + (void)gss_release_name(&minor, &target); + (void)gss_release_cred(&minor, &delegated_cred_handle); + (void)gss_release_cred(&minor, &impersonator_cred_handle); + (void)gss_release_cred(&minor, &user_cred_handle); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_s4u.py b/krb5-1.21.3/src/tests/gssapi/t_s4u.py new file mode 100755 index 00000000..4a1cdb23 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_s4u.py @@ -0,0 +1,403 @@ +from k5test import * +from base64 import b64encode +import shutil + +realm = K5Realm(create_host=False, get_creds=False) +usercache = 'FILE:' + os.path.join(realm.testdir, 'usercache') +storagecache = 'FILE:' + os.path.join(realm.testdir, 'save') + +# Create two service principals with keys in the default keytab. +service1 = 'service/1@%s' % realm.realm +realm.addprinc(service1) +realm.extract_keytab(service1, realm.keytab) +service2 = 'service/2@%s' % realm.realm +realm.addprinc(service2) +realm.extract_keytab(service2, realm.keytab) + +puser = 'p:' + realm.user_princ +pservice1 = 'p:' + service1 +pservice2 = 'p:' + service2 + +# Get forwardable creds for service1 in the default cache. +realm.kinit(service1, None, ['-f', '-k']) + +# Try S4U2Self for user with a restricted password. +realm.run([kadminl, 'modprinc', '+needchange', realm.user_princ]) +realm.run(['./t_s4u', 'e:user', '-']) +realm.run([kadminl, 'modprinc', '-needchange', + '-pwexpire', '1/1/2000', realm.user_princ]) +realm.run(['./t_s4u', 'e:user', '-']) +realm.run([kadminl, 'modprinc', '-pwexpire', 'never', realm.user_princ]) + +# Try krb5 -> S4U2Proxy with forwardable user creds. This should fail +# at the S4U2Proxy step since the DB2 back end currently has no +# support for allowing it. +realm.kinit(realm.user_princ, password('user'), ['-f', '-c', usercache]) +output = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, '-', + pservice1, pservice2], expected_code=1) +if ('auth1: ' + realm.user_princ not in output or + 'KDC can\'t fulfill requested option' not in output): + fail('krb5 -> s4u2proxy') + +# Again with SPNEGO. +output = realm.run(['./t_s4u2proxy_krb5', '--spnego', usercache, storagecache, + '-', pservice1, pservice2], + expected_code=1) +if ('auth1: ' + realm.user_princ not in output or + 'KDC can\'t fulfill requested option' not in output): + fail('krb5 -> s4u2proxy (SPNEGO)') + +# Try krb5 -> S4U2Proxy without forwardable user creds. +realm.kinit(realm.user_princ, password('user'), ['-c', usercache]) +output = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, pservice1, + pservice1, pservice2], expected_code=1) +if ('auth1: ' + realm.user_princ not in output or + 'KDC can\'t fulfill requested option' not in output): + fail('krb5 -> s4u2proxy not-forwardable') + +# Try S4U2Self. Ask for an S4U2Proxy step; this won't succeed because +# service/1 isn't allowed to get a forwardable S4U2Self ticket. +realm.run(['./t_s4u', puser, pservice2], expected_code=1, + expected_msg='KDC can\'t fulfill requested option') +realm.run(['./t_s4u', '--spnego', puser, pservice2], expected_code=1, + expected_msg='KDC can\'t fulfill requested option') + +# Correct that problem and try again. As above, the S4U2Proxy step +# won't actually succeed since we don't support that in DB2. +realm.run([kadminl, 'modprinc', '+ok_to_auth_as_delegate', service1]) +realm.run(['./t_s4u', puser, pservice2], expected_code=1, + expected_msg='KDC can\'t fulfill requested option') + +# Again with SPNEGO. This uses SPNEGO for the initial authentication, +# but still uses krb5 for S4U2Proxy--the delegated cred is returned as +# a krb5 cred, not a SPNEGO cred, and t_s4u uses the delegated cred +# directly rather than saving and reacquiring it. +realm.run(['./t_s4u', '--spnego', puser, pservice2], expected_code=1, + expected_msg='KDC can\'t fulfill requested option') + +realm.stop() + +# Set up a realm using the test KDB module so that we can do +# successful S4U2Proxy delegations. +testprincs = {'krbtgt/KRBTEST.COM': {'keys': 'aes128-cts'}, + 'user': {'keys': 'aes128-cts'}, + 'service/1': {'flags': '+ok-to-auth-as-delegate', + 'keys': 'aes128-cts'}, + 'service/2': {'keys': 'aes128-cts'}} +conf = {'realms': {'$realm': {'database_module': 'test'}}, + 'dbmodules': {'test': {'db_library': 'test', + 'princs': testprincs, + 'delegation': {'service/1': 'service/2'}}}} +realm = K5Realm(create_kdb=False, kdc_conf=conf) +userkeytab = 'FILE:' + os.path.join(realm.testdir, 'userkeytab') +realm.extract_keytab(realm.user_princ, userkeytab) +realm.extract_keytab(service1, realm.keytab) +realm.extract_keytab(service2, realm.keytab) +realm.start_kdc() + +# Get forwardable creds for service1 in the default cache. +realm.kinit(service1, None, ['-f', '-k']) + +# Successful krb5 -> S4U2Proxy, with krb5 and SPNEGO mechs. +realm.kinit(realm.user_princ, None, ['-f', '-k', '-c', usercache, + '-t', userkeytab]) +out = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, '-', + pservice1, pservice2]) +if 'auth1: user@' not in out or 'auth2: user@' not in out: + fail('krb5 -> s4u2proxy') +out = realm.run(['./t_s4u2proxy_krb5', '--spnego', usercache, storagecache, + '-', pservice1, pservice2]) +if 'auth1: user@' not in out or 'auth2: user@' not in out: + fail('krb5 -> s4u2proxy') + +# Successful S4U2Self -> S4U2Proxy. +out = realm.run(['./t_s4u', puser, pservice2]) + +# Regression test for #8139: get a user ticket directly for service1 and +# try krb5 -> S4U2Proxy. +realm.kinit(realm.user_princ, None, ['-f', '-k', '-c', usercache, + '-t', userkeytab, '-S', service1]) +out = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, '-', + pservice1, pservice2]) +if 'auth1: user@' not in out or 'auth2: user@' not in out: + fail('krb5 -> s4u2proxy') + +# Simulate a krbtgt rollover and verify that the user ticket can still +# be validated. +realm.stop_kdc() +newtgt_keys = ['2 aes128-cts', '1 aes128-cts'] +newtgt_princs = {'krbtgt/KRBTEST.COM': {'keys': newtgt_keys}} +newtgt_conf = {'dbmodules': {'test': {'princs': newtgt_princs}}} +newtgt_env = realm.special_env('newtgt', True, kdc_conf=newtgt_conf) +realm.start_kdc(env=newtgt_env) +out = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, '-', + pservice1, pservice2]) +if 'auth1: user@' not in out or 'auth2: user@' not in out: + fail('krb5 -> s4u2proxy') + +# Get a user ticket after the krbtgt rollover and verify that +# S4U2Proxy delegation works (also a #8139 regression test). +realm.kinit(realm.user_princ, None, ['-f', '-k', '-c', usercache, + '-t', userkeytab]) +out = realm.run(['./t_s4u2proxy_krb5', usercache, storagecache, '-', + pservice1, pservice2]) +if 'auth1: user@' not in out or 'auth2: user@' not in out: + fail('krb5 -> s4u2proxy') + +realm.stop() + +mark('S4U2Self with various enctypes') +for realm in multipass_realms(create_host=False, get_creds=False): + service1 = 'service/1@%s' % realm.realm + realm.addprinc(service1) + realm.extract_keytab(service1, realm.keytab) + realm.kinit(service1, None, ['-k']) + realm.run(['./t_s4u', 'e:user', '-']) + +# Test cross realm S4U2Self using server referrals. +mark('cross-realm S4U2Self') +testprincs = {'krbtgt/SREALM': {'keys': 'aes128-cts'}, + 'krbtgt/UREALM': {'keys': 'aes128-cts'}, + 'user': {'keys': 'aes128-cts', 'flags': '+preauth'}, + 'other': {'keys': 'aes128-cts'}} +kdcconf1 = {'realms': {'$realm': {'database_module': 'test'}}, + 'dbmodules': {'test': {'db_library': 'test', + 'princs': testprincs, + 'alias': {'enterprise@abc': '@UREALM', + 'user@UREALM': '@UREALM'}}}} +kdcconf2 = {'realms': {'$realm': {'database_module': 'test'}}, + 'dbmodules': {'test': {'db_library': 'test', + 'princs': testprincs, + 'alias': {'user@SREALM': '@SREALM', + 'user@UREALM': 'user', + 'enterprise@abc': 'user'}}}} +r1, r2 = cross_realms(2, xtgts=(), + args=({'realm': 'SREALM', 'kdc_conf': kdcconf1}, + {'realm': 'UREALM', 'kdc_conf': kdcconf2}), + create_kdb=False) + +r1.start_kdc() +r2.start_kdc() +r1.extract_keytab(r1.user_princ, r1.keytab) +r1.kinit(r1.user_princ, None, ['-k', '-t', r1.keytab]) +savefile = r1.ccache + '.save' +shutil.copyfile(r1.ccache, savefile) + +# Include a regression test for #8741 by unsetting the default realm. +remove_default = {'libdefaults': {'default_realm': None}} +no_default = r1.special_env('no_default', False, krb5_conf=remove_default) +msgs = ('Getting credentials user@UREALM -> user@SREALM', + '/Matching credential not found', + 'Getting credentials user@SREALM -> krbtgt/UREALM@SREALM', + 'Received creds for desired service krbtgt/UREALM@SREALM', + 'via TGT krbtgt/UREALM@SREALM after requesting user\\@SREALM@UREALM', + 'krbtgt/SREALM@UREALM differs from requested user\\@SREALM@UREALM', + 'via TGT krbtgt/SREALM@UREALM after requesting user@SREALM', + 'TGS reply is for user@UREALM -> user@SREALM') +r1.run(['./t_s4u', 'p:' + r2.user_princ, '-', r1.keytab], env=no_default, + expected_trace=msgs) + +# Test realm identification of enterprise principal names ([MS-SFU] +# 3.1.5.1.1.1). Attach a bogus realm to the enterprise name to verify +# that we start at the server realm. +mark('cross-realm S4U2Self with enterprise name') +msgs = ('Getting initial credentials for enterprise\\@abc@SREALM', + 'Sending unauthenticated request', + '/Realm not local to KDC', + 'Following referral to realm UREALM', + 'Sending unauthenticated request', + '/Additional pre-authentication required', + 'Identified realm of client principal as UREALM', + 'Getting credentials enterprise\\@abc@UREALM -> user@SREALM', + 'TGS reply is for enterprise\\@abc@UREALM -> user@SREALM') +r1.run(['./t_s4u', 'e:enterprise@abc@NOREALM', '-', r1.keytab], + expected_trace=msgs) + +mark('S4U2Self using X509 certificate') + +# Encode name as a PEM certificate file (sort of) for use by kvno. +def princ_cert(name): + enc = b64encode(name.encode('ascii')).decode('ascii') + return '-----BEGIN CERTIFICATE-----\n%s\n-----END y\n' % enc + +cert_path = os.path.join(r1.testdir, 'fake_cert') +with open(cert_path, "w") as cert_file: + cert_file.write(princ_cert('other')) + +shutil.copyfile(savefile, r1.ccache) +msgs = ('Getting initial credentials for @SREALM', + 'Identified realm of client principal as SREALM', + 'TGS reply is for other@SREALM', + 'Getting credentials other@SREALM', + 'Storing other@SREALM') +r1.run([kvno, '-F', cert_path, r1.user_princ], expected_trace=msgs) + +shutil.copyfile(savefile, r1.ccache) +msgs = ('Getting credentials other@SREALM', + 'TGS reply is for other@SREALM', + 'Storing other@SREALM') +r1.run([kvno, '-I', 'other', '-F', cert_path, r1.user_princ], + expected_trace=msgs) + +shutil.copyfile(savefile, r1.ccache) +msgs = ('Getting initial credentials for other@SREALM', + 'Identified realm of client principal as SREALM', + 'Getting credentials other@SREALM', + 'TGS reply is for other@SREALM', + 'Storing other@SREALM') +r1.run([kvno, '-U', 'other', '-F', cert_path, r1.user_princ], + expected_trace=msgs) + +mark('cross-realm S4U2Self using X509 certificate') + +with open(cert_path, "w") as cert_file: + cert_file.write(princ_cert('user@UREALM')) + +shutil.copyfile(savefile, r1.ccache) +msgs = ('Getting initial credentials for @SREALM', + 'Identified realm of client principal as UREALM', + 'TGS reply is for user@UREALM', + 'Getting credentials user@UREALM', + 'Storing user@UREALM') +r1.run([kvno, '-F', cert_path, r1.user_princ], expected_trace=msgs) + +shutil.copyfile(savefile, r1.ccache) +msgs = ('Getting credentials user@UREALM', + 'TGS reply is for user@UREALM', + 'Storing user@UREALM') +r1.run([kvno, '-I', 'user@UREALM', '-F', cert_path, r1.user_princ], + expected_trace=msgs) + +shutil.copyfile(savefile, r1.ccache) +msgs = ('Getting initial credentials for enterprise\\@abc@SREALM', + 'Identified realm of client principal as UREALM', + 'Getting credentials enterprise\\@abc@UREALM', + 'TGS reply is for enterprise\\@abc@UREALM', + 'Storing enterprise\\@abc@UREALM') +r1.run([kvno, '-U', 'enterprise@abc', '-F', cert_path, r1.user_princ], + expected_trace=msgs) + +shutil.copyfile(savefile, r1.ccache) + +mark('S4U2Self using X509 certificate (GSSAPI)') + +r1.run(['./t_s4u', 'c:other', '-', r1.keytab]) +r1.run(['./t_s4u', 'c:user@UREALM', '-', r1.keytab]) + +r1.run(['./t_s4u', '--spnego', 'c:other', '-', r1.keytab]) +r1.run(['./t_s4u', '--spnego', 'c:user@UREALM', '-', r1.keytab]) + +r1.stop() +r2.stop() + +mark('Resource-based constrained delegation') + +a_princs = {'krbtgt/A': {'keys': 'aes128-cts'}, + 'krbtgt/B': {'keys': 'aes128-cts'}, + 'user': {'keys': 'aes128-cts', 'flags': '+preauth'}, + 'sensitive': {'keys': 'aes128-cts', + 'flags': '+disallow_forwardable'}, + 'impersonator': {'keys': 'aes128-cts'}, + 'service1': {'keys': 'aes128-cts'}, + 'rb2': {'keys': 'aes128-cts'}, + 'rb': {'keys': 'aes128-cts'}} +a_kconf = {'realms': {'$realm': {'database_module': 'test'}}, + 'dbmodules': {'test': {'db_library': 'test', + 'princs': a_princs, + 'rbcd': {'rb@A': 'impersonator@A', + 'rb2@A': 'service1@A'}, + 'delegation': {'service1': 'rb2'}, + 'alias': {'rb@A': 'rb', + 'rb@B': '@B', + 'rb@C': '@B', + 'service/rb.a': 'rb', + 'service/rb.b': '@B', + 'service/rb.c': '@B' }}}} + +b_princs = {'krbtgt/B': {'keys': 'aes128-cts'}, + 'krbtgt/A': {'keys': 'aes128-cts'}, + 'krbtgt/C': {'keys': 'aes128-cts'}, + 'user': {'keys': 'aes128-cts', 'flags': '+preauth'}, + 'rb': {'keys': 'aes128-cts'}} +b_kconf = {'realms': {'$realm': {'database_module': 'test'}}, + 'dbmodules': {'test': {'db_library': 'test', + 'princs': b_princs, + 'rbcd': {'rb@B': 'impersonator@A'}, + 'alias': {'rb@B': 'rb', + 'service/rb.b': 'rb', + 'rb@C': '@C', + 'impersonator@A': '@A', + 'service/rb.c': '@C'}}}} + +c_princs = {'krbtgt/C': {'keys': 'aes128-cts'}, + 'krbtgt/B': {'keys': 'aes128-cts'}, + 'rb': {'keys': 'aes128-cts'}} +c_kconf = {'realms': {'$realm': {'database_module': 'test'}}, + 'capaths': { 'A' : { 'C' : 'B' }}, + 'dbmodules': {'test': {'db_library': 'test', + 'princs': c_princs, + 'rbcd': {'rb@C': ['impersonator@A', + 'service1@A']}, + 'alias': {'rb@C': 'rb', + 'service/rb.c': 'rb' }}}} + +ra, rb, rc = cross_realms(3, xtgts=(), + args=({'realm': 'A', 'kdc_conf': a_kconf}, + {'realm': 'B', 'kdc_conf': b_kconf}, + {'realm': 'C', 'kdc_conf': c_kconf}), + create_kdb=False) + +ra.start_kdc() +rb.start_kdc() +rc.start_kdc() + +domain_realm = {'domain_realm': {'.a':'A', '.b':'B', '.c':'C'}} +domain_conf = ra.special_env('domain_conf', False, krb5_conf=domain_realm) + +ra.extract_keytab('impersonator@A', ra.keytab) +ra.kinit('impersonator@A', None, ['-f', '-k', '-t', ra.keytab]) + +mark('Local-realm RBCD') +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'p:rb']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'p:rb@A']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@A']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@A@']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@A@A']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'h:service@rb.a']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'h:service@rb.a'], env=domain_conf) +ra.run(['./t_s4u', 'p:' + 'sensitive@A', 'h:service@rb.a'], expected_code=1) +ra.run(['./t_s4u', 'p:' + rb.user_princ, 'h:service@rb.a']) + +mark('Cross-realm RBCD') +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@B']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@B@']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@B@A']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'h:service@rb.b']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'h:service@rb.b'], env=domain_conf) +ra.run(['./t_s4u', 'p:' + 'sensitive@A', 'h:service@rb.b'], expected_code=1) +ra.run(['./t_s4u', 'p:' + rb.user_princ, 'h:service@rb.b']) + +mark('RBCD transitive trust') +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@C']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@C@']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb@C@A']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'h:service@rb.c']) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'h:service@rb.c'], env=domain_conf) +ra.run(['./t_s4u', 'p:' + 'sensitive@A', 'h:service@rb.c'], expected_code=1) +ra.run(['./t_s4u', 'p:' + rb.user_princ, 'h:service@rb.c']) + +# Although service1 has RBCD delegation privileges to rb2@A, it does +# not have ok-to-auth-as-delegate and does have traditional delegation +# privileges, so it cannot get a forwardable S4U2Self ticket. +mark('RBCD forwardable blocked by forward delegation privileges') +ra.extract_keytab('service1@A', ra.keytab) +ra.kinit('service1@A', None, ['-f', '-k', '-t', ra.keytab]) +ra.run(['./t_s4u', 'p:' + ra.user_princ, 'e:rb2@A'], expected_code=1, + expected_msg='KDC can\'t fulfill requested option') + +ra.stop() +rb.stop() +rc.stop() + +success('S4U test cases') diff --git a/krb5-1.21.3/src/tests/gssapi/t_s4u2proxy_krb5.c b/krb5-1.21.3/src/tests/gssapi/t_s4u2proxy_krb5.c new file mode 100644 index 00000000..0027f1f3 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_s4u2proxy_krb5.c @@ -0,0 +1,164 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_s4u2proxy_deleg.c - Test S4U2Proxy after krb5 auth */ +/* + * Copyright 2011 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include + +#include "common.h" + +/* + * Usage: ./t_s4u2proxy_krb5 [--spnego] client_cache storage_cache + * [accname|-] service1 service2 + * + * This program performs a regular Kerberos or SPNEGO authentication from the + * default principal of client_cache to service1. If that authentication + * yields delegated credentials, the program stores those credentials in + * sorage_ccache and uses that cache to perform a second authentication to + * service2 using S4U2Proxy. + * + * The default keytab must contain keys for service1 and service2. The default + * ccache must contain a TGT for service1. This program assumes that krb5 or + * SPNEGO authentication requires only one token exchange. + */ + +int +main(int argc, char *argv[]) +{ + const char *client_ccname, *storage_ccname, *accname, *service1, *service2; + krb5_context context = NULL; + krb5_error_code ret; + krb5_boolean use_spnego = FALSE; + krb5_ccache storage_ccache = NULL; + krb5_principal client_princ = NULL; + OM_uint32 minor, major, flags; + gss_buffer_desc buf = GSS_C_EMPTY_BUFFER; + gss_OID mech; + gss_OID_set mechs; + gss_name_t acceptor_name = GSS_C_NO_NAME, client_name = GSS_C_NO_NAME; + gss_name_t service1_name = GSS_C_NO_NAME, service2_name = GSS_C_NO_NAME; + gss_cred_id_t service1_cred = GSS_C_NO_CREDENTIAL; + gss_cred_id_t deleg_cred = GSS_C_NO_CREDENTIAL; + gss_ctx_id_t initiator_context, acceptor_context; + + /* Parse arguments. */ + if (argc >= 2 && strcmp(argv[1], "--spnego") == 0) { + use_spnego = TRUE; + argc--; + argv++; + } + if (argc != 6) { + fprintf(stderr, "./t_s4u2proxy_krb5 [--spnego] client_ccache " + "storage_ccache [accname|-] service1 service2\n"); + return 1; + } + client_ccname = argv[1]; + storage_ccname = argv[2]; + accname = argv[3]; + service1 = argv[4]; + service2 = argv[5]; + + mech = use_spnego ? &mech_spnego : &mech_krb5; + mechs = use_spnego ? &mechset_spnego : &mechset_krb5; + ret = krb5_init_context(&context); + check_k5err(context, "krb5_init_context", ret); + + /* Get GSS_C_BOTH acceptor credentials, using the default ccache. */ + acceptor_name = GSS_C_NO_NAME; + if (strcmp(accname, "-") != 0) + acceptor_name = import_name(service1); + major = gss_acquire_cred(&minor, acceptor_name, GSS_C_INDEFINITE, + mechs, GSS_C_BOTH, &service1_cred, NULL, NULL); + check_gsserr("gss_acquire_cred(service1)", major, minor); + + /* Establish contexts using the client ccache. */ + service1_name = import_name(service1); + major = gss_krb5_ccache_name(&minor, client_ccname, NULL); + check_gsserr("gss_krb5_ccache_name(1)", major, minor); + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + establish_contexts(mech, GSS_C_NO_CREDENTIAL, service1_cred, service1_name, + flags, &initiator_context, &acceptor_context, + &client_name, NULL, &deleg_cred); + + /* Display and remember the client principal. */ + major = gss_display_name(&minor, client_name, &buf, NULL); + check_gsserr("gss_display_name(1)", major, minor); + printf("auth1: %.*s\n", (int)buf.length, (char *)buf.value); + /* Assumes buffer is null-terminated, which in our implementation it is. */ + ret = krb5_parse_name(context, buf.value, &client_princ); + check_k5err(context, "krb5_parse_name", ret); + (void)gss_release_buffer(&minor, &buf); + + if (deleg_cred == GSS_C_NO_CREDENTIAL) { + printf("no credential delegated.\n"); + goto cleanup; + } + + /* Take the opportunity to test cred export/import on the synthesized + * S4U2Proxy delegated cred. */ + export_import_cred(&deleg_cred); + + /* Store the delegated credentials. */ + ret = krb5_cc_resolve(context, storage_ccname, &storage_ccache); + check_k5err(context, "krb5_cc_resolve", ret); + ret = krb5_cc_initialize(context, storage_ccache, client_princ); + check_k5err(context, "krb5_cc_initialize", ret); + major = gss_krb5_copy_ccache(&minor, deleg_cred, storage_ccache); + check_gsserr("gss_krb5_copy_ccache", major, minor); + ret = krb5_cc_close(context, storage_ccache); + check_k5err(context, "krb5_cc_close", ret); + + (void)gss_delete_sec_context(&minor, &initiator_context, GSS_C_NO_BUFFER); + (void)gss_delete_sec_context(&minor, &acceptor_context, GSS_C_NO_BUFFER); + (void)gss_release_name(&minor, &client_name); + (void)gss_release_cred(&minor, &deleg_cred); + + /* Establish contexts using the storage ccache. */ + service2_name = import_name(service2); + major = gss_krb5_ccache_name(&minor, storage_ccname, NULL); + check_gsserr("gss_krb5_ccache_name(2)", major, minor); + establish_contexts(mech, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, + service2_name, flags, &initiator_context, + &acceptor_context, &client_name, NULL, &deleg_cred); + + major = gss_display_name(&minor, client_name, &buf, NULL); + check_gsserr("gss_display_name(2)", major, minor); + printf("auth2: %.*s\n", (int)buf.length, (char *)buf.value); + (void)gss_release_buffer(&minor, &buf); + +cleanup: + (void)gss_release_name(&minor, &acceptor_name); + (void)gss_release_name(&minor, &client_name); + (void)gss_release_name(&minor, &service1_name); + (void)gss_release_name(&minor, &service2_name); + (void)gss_release_cred(&minor, &service1_cred); + (void)gss_release_cred(&minor, &deleg_cred); + (void)gss_delete_sec_context(&minor, &initiator_context, GSS_C_NO_BUFFER); + (void)gss_delete_sec_context(&minor, &acceptor_context, GSS_C_NO_BUFFER); + krb5_free_principal(context, client_princ); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_saslname.c b/krb5-1.21.3/src/tests/gssapi/t_saslname.c new file mode 100644 index 00000000..b874caf9 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_saslname.c @@ -0,0 +1,165 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2009 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include + +#include "common.h" + +static void +dump_known_mech_attrs(gss_OID mech) +{ + OM_uint32 major, minor; + gss_OID_set mech_attrs = GSS_C_NO_OID_SET; + gss_OID_set known_attrs = GSS_C_NO_OID_SET; + size_t i; + + major = gss_inquire_attrs_for_mech(&minor, mech, &mech_attrs, + &known_attrs); + check_gsserr("gss_inquire_attrs_for_mech", major, minor); + + printf("Known attributes\n"); + printf("----------------\n"); + for (i = 0; i < known_attrs->count; i++) { + gss_buffer_desc name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc short_desc = GSS_C_EMPTY_BUFFER; + gss_buffer_desc long_desc = GSS_C_EMPTY_BUFFER; + + major = gss_display_mech_attr(&minor, &known_attrs->elements[i], + &name, &short_desc, &long_desc); + check_gsserr("gss_display_mech_attr", major, minor); + printf("%.*s (%.*s): %.*s\n", (int)short_desc.length, + (char *)short_desc.value, (int)name.length, (char *)name.value, + (int)long_desc.length, (char *)long_desc.value); + (void)gss_release_buffer(&minor, &name); + (void)gss_release_buffer(&minor, &short_desc); + (void)gss_release_buffer(&minor, &long_desc); + } + printf("\n"); + (void)gss_release_oid_set(&minor, &mech_attrs); + (void)gss_release_oid_set(&minor, &known_attrs); +} + +static void +dump_mech_attrs(gss_OID mech) +{ + OM_uint32 major, minor; + gss_OID_set mech_attrs = GSS_C_NO_OID_SET; + gss_OID_set known_attrs = GSS_C_NO_OID_SET; + size_t i; + + major = gss_inquire_attrs_for_mech(&minor, mech, &mech_attrs, + &known_attrs); + check_gsserr("gss_inquire_attrs_for_mech", major, minor); + + printf("Mech attrs: "); + + for (i = 0; i < mech_attrs->count; i++) { + gss_buffer_desc name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc short_desc = GSS_C_EMPTY_BUFFER; + gss_buffer_desc long_desc = GSS_C_EMPTY_BUFFER; + + major = gss_display_mech_attr(&minor, &mech_attrs->elements[i], + &name, &short_desc, &long_desc); + check_gsserr("gss_display_mech_attr", major, minor); + printf("%.*s ", (int)name.length, (char *)name.value); + (void)gss_release_buffer(&minor, &name); + (void)gss_release_buffer(&minor, &short_desc); + (void)gss_release_buffer(&minor, &long_desc); + } + printf("\n"); + + (void)gss_release_oid_set(&minor, &mech_attrs); + (void)gss_release_oid_set(&minor, &known_attrs); +} + +int +main(int argc, char *argv[]) +{ + gss_OID_set mechs; + OM_uint32 major, minor; + size_t i; + + major = gss_indicate_mechs(&minor, &mechs); + check_gsserr("gss_indicate_mechs", major, minor); + if (mechs->count > 0) + dump_known_mech_attrs(mechs->elements); + + for (i = 0; i < mechs->count; i++) { + gss_buffer_desc oidstr = GSS_C_EMPTY_BUFFER; + gss_buffer_desc sasl_mech_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc mech_name = GSS_C_EMPTY_BUFFER; + gss_buffer_desc mech_description = GSS_C_EMPTY_BUFFER; + gss_OID oid = GSS_C_NO_OID; + + major = gss_oid_to_str(&minor, &mechs->elements[i], &oidstr); + if (GSS_ERROR(major)) + continue; + + major = gss_inquire_saslname_for_mech(&minor, &mechs->elements[i], + &sasl_mech_name, &mech_name, + &mech_description); + if (GSS_ERROR(major)) { + gss_release_buffer(&minor, &oidstr); + continue; + } + + printf("-------------------------------------------------------------" + "-----------------\n"); + printf("OID : %.*s\n", (int)oidstr.length, + (char *)oidstr.value); + printf("SASL mech : %.*s\n", (int)sasl_mech_name.length, + (char *)sasl_mech_name.value); + printf("Mech name : %.*s\n", (int)mech_name.length, + (char *)mech_name.value); + printf("Mech desc : %.*s\n", (int)mech_description.length, + (char *)mech_description.value); + dump_mech_attrs(&mechs->elements[i]); + printf("-------------------------------------------------------------" + "-----------------\n"); + + major = gss_inquire_mech_for_saslname(&minor, &sasl_mech_name, &oid); + check_gsserr("gss_inquire_mech_for_saslname", major, minor); + + if (oid == GSS_C_NO_OID || + (oid->length != mechs->elements[i].length && + memcmp(oid->elements, mechs->elements[i].elements, + oid->length) != 0)) { + (void)gss_release_buffer(&minor, &oidstr); + (void)gss_oid_to_str(&minor, oid, &oidstr); + fprintf(stderr, "Got different OID %.*s for mechanism %.*s\n", + (int)oidstr.length, (char *)oidstr.value, + (int)sasl_mech_name.length, (char *)sasl_mech_name.value); + } + (void)gss_release_buffer(&minor, &oidstr); + (void)gss_release_buffer(&minor, &sasl_mech_name); + (void)gss_release_buffer(&minor, &mech_name); + (void)gss_release_buffer(&minor, &mech_description); + } + + (void)gss_release_oid_set(&minor, &mechs); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_spnego.c b/krb5-1.21.3/src/tests/gssapi/t_spnego.c new file mode 100644 index 00000000..2483228b --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_spnego.c @@ -0,0 +1,314 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 2010 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +#include +#include +#include +#include + +#include "common.h" + +static gss_OID_desc mech_krb5_wrong = { + 9, "\052\206\110\202\367\022\001\002\002" +}; +gss_OID_set_desc mechset_krb5_wrong = { 1, &mech_krb5_wrong }; + +/* + * Test program for SPNEGO and gss_set_neg_mechs + * + * Example usage: + * + * kinit testuser + * ./t_spnego host/test.host@REALM testhost.keytab + */ + +/* Replace *tok and *len with the concatenation of prefix and *tok. */ +static void +prepend(const void *prefix, size_t plen, uint8_t **tok, size_t *len) +{ + uint8_t *newtok; + + newtok = malloc(plen + *len); + assert(newtok != NULL); + memcpy(newtok, prefix, plen); + memcpy(newtok + plen, *tok, *len); + free(*tok); + *tok = newtok; + *len = plen + *len; +} + +/* Replace *tok and *len with *tok wrapped in a DER tag with the given tag + * byte. *len must be less than 2^16. */ +static void +der_wrap(uint8_t tag, uint8_t **tok, size_t *len) +{ + char lenbuf[3]; + uint8_t *wrapped; + size_t llen; + + if (*len < 128) { + lenbuf[0] = *len; + llen = 1; + } else if (*len < 256) { + lenbuf[0] = 0x81; + lenbuf[1] = *len; + llen = 2; + } else { + assert(*len >> 16 == 0); + lenbuf[0] = 0x82; + lenbuf[1] = *len >> 8; + lenbuf[2] = *len & 0xFF; + llen = 3; + } + wrapped = malloc(1 + llen + *len); + assert(wrapped != NULL); + *wrapped = tag; + memcpy(wrapped + 1, lenbuf, llen); + memcpy(wrapped + 1 + llen, *tok, *len); + free(*tok); + *tok = wrapped; + *len = 1 + llen + *len; +} + +/* + * Create a SPNEGO initiator token for the erroneous Microsoft krb5 mech OID, + * wrapping a krb5 token ktok. The token should look like: + * + * 60 (GSS framing sequence) + * 06 06 2B 06 01 05 05 02 (SPNEGO OID) + * A0 (NegotiationToken choice 0, negTokenInit) + * 30 (sequence) + * A0 0D (context tag 0, mechTypes) + * 30 0B (sequence of) + * 06 09 2A 86 48 82 F7 12 01 02 02 (wrong krb5 OID) + * A2 (context tag 2, mechToken) + * 04 (octet string) + * + */ +static void +create_mskrb5_spnego_token(gss_buffer_t ktok, gss_buffer_desc *tok_out) +{ + uint8_t *tok; + size_t len; + + len = ktok->length; + tok = malloc(len); + assert(tok != NULL); + memcpy(tok, ktok->value, len); + /* Wrap the krb5 token in OCTET STRING and [2] tags. */ + der_wrap(0x04, &tok, &len); + der_wrap(0xA2, &tok, &len); + /* Prepend the wrong krb5 OID inside OBJECT IDENTIFIER and [0] tags. */ + prepend("\xA0\x0D\x30\x0B\x06\x09\x2A\x86\x48\x82\xF7\x12\x01\x02\x02", 15, + &tok, &len); + /* Wrap the previous two things in SEQUENCE and [0] tags. */ + der_wrap(0x30, &tok, &len); + der_wrap(0xA0, &tok, &len); + /* Prepend the SPNEGO OID in an OBJECT IDENTIFIER tag. */ + prepend("\x06\x06\x2B\x06\x01\x05\x05\x02", 8, &tok, &len); + /* Wrap the whole thing in an [APPLICATION 0] tag. */ + der_wrap(0x60, &tok, &len); + tok_out->value = tok; + tok_out->length = len; +} + +/* + * Test that the SPNEGO acceptor code accepts and properly reflects back the + * erroneous Microsoft mech OID in the supportedMech field of the NegTokenResp + * message. Use acred as the verifier cred handle. + */ +static void +test_mskrb_oid(gss_name_t tname, gss_cred_id_t acred) +{ + OM_uint32 major, minor; + gss_ctx_id_t ictx = GSS_C_NO_CONTEXT, actx = GSS_C_NO_CONTEXT; + gss_buffer_desc atok = GSS_C_EMPTY_BUFFER, ktok = GSS_C_EMPTY_BUFFER, stok; + const unsigned char *atok_oid; + + /* + * Our SPNEGO mech no longer acquires creds for the wrong mech OID, so we + * have to construct a SPNEGO token ourselves. + */ + major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &ictx, tname, + &mech_krb5, 0, GSS_C_INDEFINITE, + GSS_C_NO_CHANNEL_BINDINGS, &atok, NULL, &ktok, + NULL, NULL); + check_gsserr("gss_init_sec_context(mskrb)", major, minor); + assert(major == GSS_S_COMPLETE); + create_mskrb5_spnego_token(&ktok, &stok); + + /* + * Look directly at the DER encoding of the response token. Since we + * didn't request mutual authentication, the SPNEGO reply will contain no + * underlying mech token; therefore, the encoding of the correct + * NegotiationToken response is completely predictable: + * + * A1 14 (choice 1, length 20, meaning negTokenResp) + * 30 12 (sequence, length 18) + * A0 03 (context tag 0, length 3) + * 0A 01 00 (enumerated value 0, meaning accept-completed) + * A1 0B (context tag 1, length 11) + * 06 09 (object identifier, length 9) + * 2A 86 48 82 F7 12 01 02 02 (the erroneous krb5 OID) + * + * So we can just compare the length to 22 and the nine bytes at offset 13 + * to the expected OID. + */ + major = gss_accept_sec_context(&minor, &actx, acred, &stok, + GSS_C_NO_CHANNEL_BINDINGS, NULL, + NULL, &atok, NULL, NULL, NULL); + check_gsserr("gss_accept_sec_context(mskrb)", major, minor); + assert(atok.length == 22); + atok_oid = (unsigned char *)atok.value + 13; + assert(memcmp(atok_oid, mech_krb5_wrong.elements, 9) == 0); + + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + (void)gss_release_buffer(&minor, &ktok); + (void)gss_release_buffer(&minor, &atok); + free(stok.value); +} + +/* Check that we return a compatibility NegTokenInit2 message containing + * NegHints for an empty initiator token. */ +static void +test_neghints() +{ + OM_uint32 major, minor; + gss_buffer_desc itok = GSS_C_EMPTY_BUFFER, atok; + gss_ctx_id_t actx = GSS_C_NO_CONTEXT; + const char *expected = + /* RFC 2743 token framing: [APPLICATION 0] IMPLICIT SEQUENCE followed + * by OBJECT IDENTIFIER and the SPNEGO OID */ + "\x60\x47\x06\x06" "\x2B\x06\x01\x05\x05\x02" + /* [0] SEQUENCE for the NegotiationToken negtokenInit choice */ + "\xA0\x3D\x30\x3B" + /* [0] MechTypeList containing the krb5 OID */ + "\xA0\x0D\x30\x0B\x06\x09" "\x2A\x86\x48\x86\xF7\x12\x01\x02\x02" + /* [3] NegHints containing [0] GeneralString containing the dummy + * hintName string defined in [MS-SPNG] */ + "\xA3\x2A\x30\x28\xA0\x26\x1B\x24" + "not_defined_in_RFC4178@please_ignore"; + + /* Produce a hint token. */ + major = gss_accept_sec_context(&minor, &actx, GSS_C_NO_CREDENTIAL, &itok, + GSS_C_NO_CHANNEL_BINDINGS, NULL, NULL, + &atok, NULL, NULL, NULL); + check_gsserr("gss_accept_sec_context(neghints)", major, minor); + + /* Verify it against the expected contents, which are fixed as long as we + * only list the krb5 mech in the token. */ + assert(atok.length == strlen(expected)); + assert(memcmp(atok.value, expected, atok.length) == 0); + + (void)gss_release_buffer(&minor, &atok); + (void)gss_delete_sec_context(&minor, &actx, NULL); +} + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, major, flags; + gss_cred_id_t verifier_cred_handle = GSS_C_NO_CREDENTIAL; + gss_cred_id_t initiator_cred_handle = GSS_C_NO_CREDENTIAL; + gss_OID_set actual_mechs = GSS_C_NO_OID_SET; + gss_ctx_id_t initiator_context, acceptor_context; + gss_name_t target_name, source_name = GSS_C_NO_NAME; + gss_OID mech = GSS_C_NO_OID; + gss_OID_desc pref_oids[2]; + gss_OID_set_desc pref_mechs; + + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: %s target_name [keytab]\n", argv[0]); + exit(1); + } + + target_name = import_name(argv[1]); + + if (argc >= 3) { + major = krb5_gss_register_acceptor_identity(argv[2]); + check_gsserr("krb5_gss_register_acceptor_identity", major, 0); + } + + /* Get default initiator cred. */ + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE, + &mechset_spnego, GSS_C_INITIATE, + &initiator_cred_handle, NULL, NULL); + check_gsserr("gss_acquire_cred(initiator)", major, minor); + + /* + * The following test is designed to exercise SPNEGO reselection on the + * client and server. Unfortunately, it no longer does so after tickets + * #8217 and #8021, since SPNEGO now only acquires a single krb5 cred and + * there is no way to expand the underlying creds with gss_set_neg_mechs(). + * To fix this we need gss_acquire_cred_with_cred() or some other way to + * turn a cred with a specifically requested mech set into a SPNEGO cred. + */ + + /* Make the initiator prefer IAKERB and offer krb5 as an alternative. */ + pref_oids[0] = mech_iakerb; + pref_oids[1] = mech_krb5; + pref_mechs.count = 2; + pref_mechs.elements = pref_oids; + major = gss_set_neg_mechs(&minor, initiator_cred_handle, &pref_mechs); + check_gsserr("gss_set_neg_mechs(initiator)", major, minor); + + /* Get default acceptor cred. */ + major = gss_acquire_cred(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE, + &mechset_spnego, GSS_C_ACCEPT, + &verifier_cred_handle, &actual_mechs, NULL); + check_gsserr("gss_acquire_cred(acceptor)", major, minor); + + /* Restrict the acceptor to krb5 (which will force a reselection). */ + major = gss_set_neg_mechs(&minor, verifier_cred_handle, &mechset_krb5); + check_gsserr("gss_set_neg_mechs(acceptor)", major, minor); + + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + establish_contexts(&mech_spnego, initiator_cred_handle, + verifier_cred_handle, target_name, flags, + &initiator_context, &acceptor_context, &source_name, + &mech, NULL); + + display_canon_name("Source name", source_name, &mech_krb5); + display_oid("Source mech", mech); + + /* Test acceptance of the erroneous Microsoft krb5 OID, with and without an + * acceptor cred. */ + test_mskrb_oid(target_name, verifier_cred_handle); + test_mskrb_oid(target_name, GSS_C_NO_CREDENTIAL); + + test_neghints(); + + (void)gss_delete_sec_context(&minor, &initiator_context, NULL); + (void)gss_delete_sec_context(&minor, &acceptor_context, NULL); + (void)gss_release_name(&minor, &source_name); + (void)gss_release_name(&minor, &target_name); + (void)gss_release_cred(&minor, &initiator_cred_handle); + (void)gss_release_cred(&minor, &verifier_cred_handle); + (void)gss_release_oid_set(&minor, &actual_mechs); + + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_srcattrs.c b/krb5-1.21.3/src/tests/gssapi/t_srcattrs.c new file mode 100644 index 00000000..e83c3569 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_srcattrs.c @@ -0,0 +1,63 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* src/tests/gssapi/t_accname_authind.c - test harness for auth indicators */ +/* + * Copyright (C) 2016 by Red Hat, Inc. + * 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. + */ + +#include +#include +#include "common.h" + +/* Establish a context to the given target name and enumerate the attributes of + * the source name. */ + +int +main(int argc, char *argv[]) +{ + OM_uint32 minor, flags; + gss_name_t tname, sname; + gss_ctx_id_t ictx, actx; + + if (argc != 2) { + fprintf(stderr, "Usage: %s targetname\n", argv[0]); + return 1; + } + tname = import_name(argv[1]); + + flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + establish_contexts(&mech_krb5, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, + tname, flags, &ictx, &actx, &sname, NULL, NULL); + enumerate_attributes(sname, 1); + + (void)gss_release_name(&minor, &tname); + (void)gss_release_name(&minor, &sname); + (void)gss_delete_sec_context(&minor, &ictx, NULL); + (void)gss_delete_sec_context(&minor, &actx, NULL); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_store_cred.c b/krb5-1.21.3/src/tests/gssapi/t_store_cred.c new file mode 100644 index 00000000..b053e524 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_store_cred.c @@ -0,0 +1,114 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/gssapi/t_store_cred.c - gss_store_cred() test harness */ +/* + * Copyright (C) 2021 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. + */ + +/* + * Usage: t_store_cred [-d] [-i] [-o] src_ccname [dest_ccname] + * + * Acquires creds from src_ccname using gss_acquire_cred_from() and then stores + * them, using gss_store_cred_into() if -i is specified or gss_store_cred() + * otherwise. If dest_ccname is specified with -i, it is included in the cred + * store for the store operation; if it is specified without -i, it is set with + * gss_krb5_ccache_name() before the store operation. If -d and/or -o are + * specified they set the default_cred and overwrite_cred flags to true + * respectively. + */ + +#include "k5-platform.h" +#include +#include "common.h" + +int +main(int argc, char *argv[]) +{ + OM_uint32 major, minor; + gss_key_value_set_desc store; + gss_key_value_element_desc elem; + gss_cred_id_t cred; + krb5_boolean def = FALSE, into = FALSE, overwrite = FALSE; + const char *src_ccname, *dest_ccname; + int c; + + /* Parse arguments. */ + while ((c = getopt(argc, argv, "dio")) != -1) { + switch (c) { + case 'd': + def = TRUE; + break; + case 'i': + into = TRUE; + break; + case 'o': + overwrite = TRUE; + break; + default: + abort(); + } + } + argc -= optind; + argv += optind; + assert(argc == 1 || argc == 2); + src_ccname = argv[0]; + dest_ccname = argv[1]; + + elem.key = "ccache"; + elem.value = src_ccname; + store.count = 1; + store.elements = &elem; + major = gss_acquire_cred_from(&minor, GSS_C_NO_NAME, GSS_C_INDEFINITE, + &mechset_krb5, GSS_C_INITIATE, &store, &cred, + NULL, NULL); + check_gsserr("acquire_cred", major, minor); + + if (into) { + if (dest_ccname != NULL) { + elem.key = "ccache"; + elem.value = dest_ccname; + store.count = 1; + } else { + store.count = 0; + } + major = gss_store_cred_into(&minor, cred, GSS_C_INITIATE, &mech_krb5, + overwrite, def, &store, NULL, NULL); + check_gsserr("store_cred_into", major, minor); + } else { + if (dest_ccname != NULL) { + major = gss_krb5_ccache_name(&minor, dest_ccname, NULL); + check_gsserr("ccache_name", major, minor); + } + major = gss_store_cred(&minor, cred, GSS_C_INITIATE, &mech_krb5, + overwrite, def, NULL, NULL); + check_gsserr("store_cred", major, minor); + } + + gss_release_cred(&minor, &cred); + return 0; +} diff --git a/krb5-1.21.3/src/tests/gssapi/t_store_cred.py b/krb5-1.21.3/src/tests/gssapi/t_store_cred.py new file mode 100644 index 00000000..00e80cf3 --- /dev/null +++ b/krb5-1.21.3/src/tests/gssapi/t_store_cred.py @@ -0,0 +1,80 @@ +from k5test import * + +realm = K5Realm(create_user=False) + +alice = 'alice@' + realm.realm +bob = 'bob@' + realm.realm +cc_alice = realm.ccache + '.alice' +cc_bob = realm.ccache + '.bob' +realm.addprinc(alice) +realm.addprinc(bob) +realm.extract_keytab(alice, realm.keytab) +realm.extract_keytab(bob, realm.keytab) +realm.kinit(alice, flags=['-k', '-c', cc_alice]) +realm.kinit(bob, flags=['-k', '-c', cc_bob]) + +mark('FILE, default output ccache') +realm.run(['./t_store_cred', cc_alice]) +realm.klist(alice) +# Overwriting should fail by default, whether or not the principal matches. +realm.run(['./t_store_cred', cc_alice], expected_code=1, + expected_msg='The requested credential element already exists') +realm.run(['./t_store_cred', cc_bob], expected_code=1, + expected_msg='The requested credential element already exists') +# Overwriting should succeed with overwrite_cred set. +realm.run(['./t_store_cred', '-o', cc_bob]) +realm.klist(bob) +# default_cred has no effect without a collection. +realm.run(['./t_store_cred', '-d', '-o', cc_alice]) +realm.klist(alice) + +mark('FILE, gss_krb5_ccache_name()') +cc_alternate = realm.ccache + '.alternate' +realm.run(['./t_store_cred', cc_alice, cc_alternate]) +realm.klist(alice, ccache=cc_alternate) +realm.run(['./t_store_cred', cc_bob, cc_alternate], expected_code=1, + expected_msg='The requested credential element already exists') + +mark('FILE, gss_store_cred_into()') +os.remove(cc_alternate) +realm.run(['./t_store_cred', '-i', cc_alice, cc_alternate]) +realm.klist(alice, ccache=cc_alternate) +realm.run(['./t_store_cred', '-i', cc_bob, cc_alternate], expected_code=1, + expected_msg='The requested credential element already exists') + +mark('DIR, gss_krb5_ccache_name()') +cc_dir = 'DIR:' + os.path.join(realm.testdir, 'cc') +realm.run(['./t_store_cred', cc_alice, cc_dir]) +realm.run([klist, '-c', cc_dir], expected_code=1, + expected_msg='No credentials cache found') +realm.run([klist, '-l', '-c', cc_dir], expected_msg=alice) +realm.run(['./t_store_cred', cc_alice, cc_dir], expected_code=1, + expected_msg='The requested credential element already exists') +realm.run(['./t_store_cred', '-o', cc_alice, cc_dir]) +realm.run([klist, '-c', cc_dir], expected_code=1, + expected_msg='No credentials cache found') +realm.run([klist, '-l', cc_dir], expected_msg=alice) +realm.run(['./t_store_cred', '-d', cc_bob, cc_dir]) +# The k5test klist method does not currently work with a collection name. +realm.run([klist, cc_dir], expected_msg=bob) +realm.run([klist, '-l', cc_dir], expected_msg=alice) +realm.run(['./t_store_cred', '-o', '-d', cc_alice, cc_dir]) +realm.run([klist, cc_dir], expected_msg=alice) +realm.run([kdestroy, '-A', '-c', cc_dir]) + +mark('DIR, gss_store_cred_into()') +realm.run(['./t_store_cred', '-i', cc_alice, cc_dir]) +realm.run(['./t_store_cred', '-i', '-d', cc_bob, cc_dir]) +realm.run([klist, cc_dir], expected_msg=bob) +realm.run([klist, '-l', cc_dir], expected_msg=alice) +realm.run([kdestroy, '-A', '-c', cc_dir]) + +mark('DIR, default output ccache') +realm.ccache = cc_dir +realm.env['KRB5CCNAME'] = cc_dir +realm.run(['./t_store_cred', '-i', cc_alice, cc_dir]) +realm.run(['./t_store_cred', '-i', '-d', cc_bob, cc_dir]) +realm.run([klist], expected_msg=bob) +realm.run([klist, '-l'], expected_msg=alice) + +success('gss_store_cred() tests') diff --git a/krb5-1.21.3/src/tests/hammer/Makefile.in b/krb5-1.21.3/src/tests/hammer/Makefile.in new file mode 100644 index 00000000..3f0c4354 --- /dev/null +++ b/krb5-1.21.3/src/tests/hammer/Makefile.in @@ -0,0 +1,15 @@ +mydir=tests$(S)hammer +BUILDTOP=$(REL)..$(S).. + +SRCS=$(srcdir)/kdc5_hammer.c + +all: kdc5_hammer + +kdc5_hammer: kdc5_hammer.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o kdc5_hammer kdc5_hammer.o $(KRB5_BASE_LIBS) + +install: + +clean: + $(RM) kdc5_hammer.o kdc5_hammer + diff --git a/krb5-1.21.3/src/tests/hammer/deps b/krb5-1.21.3/src/tests/hammer/deps new file mode 100644 index 00000000..f9357763 --- /dev/null +++ b/krb5-1.21.3/src/tests/hammer/deps @@ -0,0 +1,13 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kdc5_hammer.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdc5_hammer.c diff --git a/krb5-1.21.3/src/tests/hammer/kdc5_hammer.c b/krb5-1.21.3/src/tests/hammer/kdc5_hammer.c new file mode 100644 index 00000000..8220fd97 --- /dev/null +++ b/krb5-1.21.3/src/tests/hammer/kdc5_hammer.c @@ -0,0 +1,507 @@ +/* tests/hammer/kdc5_hammer.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "com_err.h" +#include + +#define KRB5_DEFAULT_OPTIONS 0 +#define KRB5_DEFAULT_LIFE 60*60*8 /* 8 hours */ +#define KRB5_RENEWABLE_LIFE 60*60*2 /* 2 hours */ + +struct h_timer { + float ht_cumulative; + float ht_min; + float ht_max; + krb5_int32 ht_observations; +}; + +extern int optind; +extern char *optarg; +char *prog; + +static int brief; +static char *cur_realm = 0; +static int do_timer = 0; + +krb5_data tgtname = { + 0, + KRB5_TGS_NAME_SIZE, + KRB5_TGS_NAME +}; + +int verify_cs_pair + (krb5_context, + char *, + krb5_principal, + char *, + char *, + int, int, int, + krb5_ccache); + +int get_tgt + (krb5_context, + char *, + krb5_principal *, + krb5_ccache); + +static void +usage(who, status) +char *who; +int status; +{ + fprintf(stderr, + "usage: %s -p prefix -n num_to_check [-c cachename] [-r realmname]\n", + who); + fprintf(stderr, "\t [-D depth]\n"); + fprintf(stderr, "\t [-P preauth type] [-R repeat_count] [-t] [-b] [-v] \n"); + + exit(status); +} + +static krb5_preauthtype * patype = NULL, patypedata[2] = { 0, -1 }; +static krb5_context test_context; + +struct timeval tstart_time, tend_time; +struct timezone dontcare; + +struct h_timer in_tkt_times = { 0.0, 1000000.0, -1.0, 0 }; +struct h_timer tgs_req_times = { 0.0, 1000000.0, -1.0, 0 }; +/* + * Timer macros. + */ +#define swatch_on() ((void) gettimeofday(&tstart_time, &dontcare)) +#define swatch_eltime() ((gettimeofday(&tend_time, &dontcare)) ? -1.0 : \ + (((float) (tend_time.tv_sec - \ + tstart_time.tv_sec)) + \ + (((float) (tend_time.tv_usec - \ + tstart_time.tv_usec))/1000000.0))) + +int +main(argc, argv) + int argc; + char **argv; +{ + krb5_ccache ccache = NULL; + char *cache_name = NULL; /* -f option */ + int option; + int errflg = 0; + krb5_error_code code; + int num_to_check, n, i, j, repeat_count, counter; + int n_tried, errors; + char prefix[BUFSIZ], client[4096], server[4096]; + int depth; + char ctmp[4096], ctmp2[BUFSIZ], stmp[4096], stmp2[BUFSIZ]; + krb5_principal client_princ; + krb5_error_code retval; + + krb5_init_context(&test_context); + + if (strrchr(argv[0], '/')) + prog = strrchr(argv[0], '/')+1; + else + prog = argv[0]; + + num_to_check = 0; + depth = 1; + repeat_count = 1; + brief = 0; + n_tried = 0; + errors = 0; + + while ((option = getopt(argc, argv, "D:p:n:c:R:P:e:bvr:t")) != -1) { + switch (option) { + case 't': + do_timer = 1; + break; + case 'b': + brief = 1; + break; + case 'v': + brief = 0; + break; + case 'R': + repeat_count = atoi(optarg); /* how many times? */ + break; + case 'r': + cur_realm = optarg; + break; + case 'D': + depth = atoi(optarg); /* how deep to go */ + break; + case 'p': /* prefix name to check */ + strncpy(prefix, optarg, sizeof(prefix) - 1); + prefix[sizeof(prefix) - 1] = '\0'; + break; + case 'n': /* how many to check */ + num_to_check = atoi(optarg); + break; + case 'P': + patypedata[0] = atoi(optarg); + patype = patypedata; + break; + case 'c': + if (ccache == NULL) { + cache_name = optarg; + + code = krb5_cc_resolve (test_context, cache_name, &ccache); + if (code != 0) { + com_err (prog, code, "resolving %s", cache_name); + errflg++; + } + } else { + fprintf(stderr, "Only one -c option allowed\n"); + errflg++; + } + break; + case '?': + default: + errflg++; + break; + } + } + + if (!(num_to_check && prefix[0])) usage(prog, 1); + + if (!cur_realm) { + if ((retval = krb5_get_default_realm(test_context, &cur_realm))) { + com_err(prog, retval, "while retrieving default realm name"); + exit(1); + } + } + + if (ccache == NULL) { + if ((code = krb5_cc_default(test_context, &ccache))) { + com_err(prog, code, "while getting default ccache"); + exit(1); + } + } + + memset(ctmp, 0, sizeof(ctmp)); + memset(stmp, 0, sizeof(stmp)); + + for (counter = 0; counter < repeat_count; counter++) { + fprintf(stderr, "\nRound %d\n", counter); + + for (n = 1; n <= num_to_check; n++) { + /* build the new principal name */ + /* we can't pick random names because we need to generate all the names + again given a prefix and count to test the db lib and kdb */ + ctmp[0] = '\0'; + for (i = 1; i <= depth; i++) { + (void) snprintf(ctmp2, sizeof(ctmp2), "%s%s%d-DEPTH-%d", + (i != 1) ? "/" : "", prefix, n, i); + ctmp2[sizeof(ctmp2) - 1] = '\0'; + strncat(ctmp, ctmp2, sizeof(ctmp) - 1 - strlen(ctmp)); + ctmp[sizeof(ctmp) - 1] = '\0'; + snprintf(client, sizeof(client), "%s@%s", ctmp, cur_realm); + + if (get_tgt (test_context, client, &client_princ, ccache)) { + errors++; + n_tried++; + continue; + } + n_tried++; + + stmp[0] = '\0'; + for (j = 1; j <= depth; j++) { + (void) snprintf(stmp2, sizeof(stmp2), "%s%s%d-DEPTH-%d", + (j != 1) ? "/" : "", prefix, n, j); + stmp2[sizeof (stmp2) - 1] = '\0'; + strncat(stmp, stmp2, sizeof(stmp) - 1 - strlen(stmp)); + stmp[sizeof(stmp) - 1] = '\0'; + snprintf(server, sizeof(server), "%s@%s", stmp, cur_realm); + if (verify_cs_pair(test_context, client, client_princ, + stmp, cur_realm, n, i, j, ccache)) + errors++; + n_tried++; + } + krb5_free_principal(test_context, client_princ); + } + } + } + fprintf (stderr, "\nTried %d. Got %d errors.\n", n_tried, errors); + if (do_timer) { + if (in_tkt_times.ht_observations) + fprintf(stderr, + "%8d AS_REQ requests: %9.6f average (min: %9.6f, max:%9.6f)\n", + in_tkt_times.ht_observations, + in_tkt_times.ht_cumulative / + (float) in_tkt_times.ht_observations, + in_tkt_times.ht_min, + in_tkt_times.ht_max); + if (tgs_req_times.ht_observations) + fprintf(stderr, + "%8d TGS_REQ requests: %9.6f average (min: %9.6f, max:%9.6f)\n", + tgs_req_times.ht_observations, + tgs_req_times.ht_cumulative / + (float) tgs_req_times.ht_observations, + tgs_req_times.ht_min, + tgs_req_times.ht_max); + } + + (void) krb5_cc_close(test_context, ccache); + + krb5_free_context(test_context); + + exit(errors); + } + + +static krb5_error_code +get_server_key(context, server, enctype, key) + krb5_context context; + krb5_principal server; + krb5_enctype enctype; + krb5_keyblock ** key; +{ + krb5_error_code retval; + krb5_encrypt_block eblock; + char * string; + krb5_data salt; + krb5_data pwd; + + *key = NULL; + + if ((retval = krb5_principal2salt(context, server, &salt))) + return retval; + + if ((retval = krb5_unparse_name(context, server, &string))) + goto cleanup_salt; + + pwd.data = string; + pwd.length = strlen(string); + + if ((*key = (krb5_keyblock *)malloc(sizeof(krb5_keyblock)))) { + krb5_use_enctype(context, &eblock, enctype); + retval = krb5_string_to_key(context, &eblock, *key, &pwd, &salt); + if (retval) { + free(*key); + *key = NULL; + } + } else + retval = ENOMEM; + + free(string); + +cleanup_salt: + free(salt.data); + return retval; +} + +int verify_cs_pair(context, p_client_str, p_client, service, hostname, + p_num, c_depth, s_depth, ccache) + krb5_context context; + char *p_client_str; + krb5_principal p_client; + char * service; + char * hostname; + int p_num, c_depth, s_depth; + krb5_ccache ccache; +{ + krb5_error_code retval; + krb5_creds creds; + krb5_creds * credsp = NULL; + krb5_ticket * ticket = NULL; + krb5_keyblock * keyblock = NULL; + krb5_auth_context auth_context = NULL; + krb5_data request_data = empty_data(); + char * sname; + float dt; + + if (brief) + fprintf(stderr, "\tprinc (%d) client (%d) for server (%d)\n", + p_num, c_depth, s_depth); + else + fprintf(stderr, "\tclient %s for server %s\n", p_client_str, + service); + + /* Initialize variables */ + memset(&creds, 0, sizeof(creds)); + + /* Do client side */ + if (asprintf(&sname, "%s@%s", service, hostname) >= 0) { + retval = krb5_parse_name(context, sname, &creds.server); + free(sname); + } + else + retval = ENOMEM; + if (retval) + return(retval); + + /* obtain ticket & session key */ + if ((retval = krb5_cc_get_principal(context, ccache, &creds.client))) { + com_err(prog, retval, "while getting client princ for %s", hostname); + return retval; + } + + if ((retval = krb5_get_credentials(context, 0, + ccache, &creds, &credsp))) { + com_err(prog, retval, "while getting creds for %s", hostname); + return retval; + } + + if (do_timer) + swatch_on(); + + if ((retval = krb5_mk_req_extended(context, &auth_context, 0, NULL, + credsp, &request_data))) { + com_err(prog, retval, "while preparing AP_REQ for %s", hostname); + goto cleanup; + } + + krb5_auth_con_free(context, auth_context); + auth_context = NULL; + + /* Do server side now */ + if ((retval = get_server_key(context, credsp->server, + credsp->keyblock.enctype, &keyblock))) { + com_err(prog, retval, "while getting server key for %s", hostname); + goto cleanup; + } + + if (krb5_auth_con_init(context, &auth_context)) { + com_err(prog, retval, "while creating auth_context for %s", hostname); + goto cleanup; + } + + if (krb5_auth_con_setuseruserkey(context, auth_context, keyblock)) { + com_err(prog, retval, "while setting auth_context key %s", hostname); + goto cleanup; + } + + if ((retval = krb5_rd_req(context, &auth_context, &request_data, + NULL /* server */, 0, NULL, &ticket))) { + com_err(prog, retval, "while decoding AP_REQ for %s", hostname); + goto cleanup; + } + + if (do_timer) { + dt = swatch_eltime(); + tgs_req_times.ht_cumulative += dt; + tgs_req_times.ht_observations++; + if (dt > tgs_req_times.ht_max) + tgs_req_times.ht_max = dt; + if (dt < tgs_req_times.ht_min) + tgs_req_times.ht_min = dt; + } + + if (!(krb5_principal_compare(context,ticket->enc_part2->client,p_client))){ + char *returned_client; + if ((retval = krb5_unparse_name(context, ticket->enc_part2->client, + &returned_client))) + com_err (prog, retval, + "Client not as expected, but cannot unparse client name"); + else + com_err (prog, 0, "Client not as expected (%s).", returned_client); + retval = KRB5_PRINC_NOMATCH; + free(returned_client); + } else { + retval = 0; + } + +cleanup: + krb5_free_cred_contents(context, &creds); + krb5_free_ticket(context, ticket); + krb5_auth_con_free(context, auth_context); + krb5_free_keyblock(context, keyblock); + krb5_free_data_contents(context, &request_data); + krb5_free_creds(context, credsp); + + return retval; +} + +int get_tgt (context, p_client_str, p_client, ccache) + krb5_context context; + char *p_client_str; + krb5_principal *p_client; + krb5_ccache ccache; +{ + long lifetime = KRB5_DEFAULT_LIFE; /* -l option */ + krb5_error_code code; + krb5_creds my_creds; + krb5_timestamp start; + float dt; + krb5_get_init_creds_opt *options; + + if (!brief) + fprintf(stderr, "\tgetting TGT for %s\n", p_client_str); + + if ((code = krb5_timeofday(context, &start))) { + com_err(prog, code, "while getting time of day"); + return(-1); + } + + memset(&my_creds, 0, sizeof(my_creds)); + + if ((code = krb5_parse_name (context, p_client_str, p_client))) { + com_err (prog, code, "when parsing name %s", p_client_str); + return(-1); + } + + code = krb5_cc_initialize (context, ccache, *p_client); + if (code != 0) { + com_err (prog, code, "when initializing cache"); + return(-1); + } + + if (do_timer) + swatch_on(); + + code = krb5_get_init_creds_opt_alloc(context, &options); + if (code != 0) { + com_err(prog, code, "when allocating init cred options"); + return(-1); + } + + krb5_get_init_creds_opt_set_tkt_life(options, lifetime); + + code = krb5_get_init_creds_opt_set_out_ccache(context, options, ccache); + if (code != 0) { + com_err(prog, code, "when setting init cred output ccache"); + return(-1); + } + + code = krb5_get_init_creds_password(context, &my_creds, *p_client, + p_client_str, NULL, NULL, 0, NULL, + options); + if (do_timer) { + dt = swatch_eltime(); + in_tkt_times.ht_cumulative += dt; + in_tkt_times.ht_observations++; + if (dt > in_tkt_times.ht_max) + in_tkt_times.ht_max = dt; + if (dt < in_tkt_times.ht_min) + in_tkt_times.ht_min = dt; + } + krb5_get_init_creds_opt_free(context, options); + krb5_free_cred_contents(context, &my_creds); + if (code != 0) { + com_err (prog, code, "while getting initial credentials"); + return(-1); + } + + return(0); +} diff --git a/krb5-1.21.3/src/tests/hammer/pp.c b/krb5-1.21.3/src/tests/hammer/pp.c new file mode 100644 index 00000000..5da1fac0 --- /dev/null +++ b/krb5-1.21.3/src/tests/hammer/pp.c @@ -0,0 +1,27 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/hammer/pp.c */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * For copying and distribution information, please see the file + * . + */ + +#include "krb5.h" + +void +print_principal(p) + krb5_principal p; +{ + char *buf; + krb5_error_code retval; + + if (retval = krb5_unparse_name(p, &buf)) { + com_err("DEBUG: Print_principal", retval, + "while unparsing name"); + exit(1); + } + printf("%s\n", buf); + free(buf); +} diff --git a/krb5-1.21.3/src/tests/hist.c b/krb5-1.21.3/src/tests/hist.c new file mode 100644 index 00000000..6bab968e --- /dev/null +++ b/krb5-1.21.3/src/tests/hist.c @@ -0,0 +1,99 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/hist.c - Perform unusual operations on history keys */ +/* + * Copyright (C) 2012 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. + */ + +/* + * This program is invoked from t_pwhist.py to simulate some conditions + * normally only seen in databases created before krb5 1.3. With the "make" + * argument, the history key is rolled over to a kvno containing two keys + * (since krb5 1.3 we ordinarily ensure that there's only one). With the + * "swap" argument, the two history keys are swapped in order; we use this + * operation to simulate the case where krb5 1.7 or earlier chose something + * other than the first history key to create password history entries. + */ + +#include +#include + +static void +check(krb5_error_code ret) +{ + if (ret) { + fprintf(stderr, "Unexpected failure, aborting\n"); + abort(); + } +} + +int +main(int argc, char **argv) +{ + krb5_context ctx; + krb5_db_entry *ent; + krb5_principal hprinc; + kadm5_principal_ent_rec kent; + krb5_key_salt_tuple ks[2]; + krb5_key_data kd; + kadm5_config_params params = { 0 }; + void *handle; + char *realm; + long mask = KADM5_PRINCIPAL | KADM5_MAX_LIFE | KADM5_ATTRIBUTES; + + check(kadm5_init_krb5_context(&ctx)); + check(krb5_parse_name(ctx, "kadmin/history", &hprinc)); + check(krb5_get_default_realm(ctx, &realm)); + params.mask |= KADM5_CONFIG_REALM; + params.realm = realm; + check(kadm5_init(ctx, "user", "", "", ¶ms, KADM5_STRUCT_VERSION, + KADM5_API_VERSION_4, NULL, &handle)); + if (strcmp(argv[1], "make") == 0) { + memset(&kent, 0, sizeof(kent)); + kent.principal = hprinc; + kent.max_life = KRB5_KDB_DISALLOW_ALL_TIX; + kent.attributes = 0; + ks[0].ks_enctype = ENCTYPE_AES256_CTS_HMAC_SHA1_96; + ks[0].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL; + ks[1].ks_enctype = ENCTYPE_AES128_CTS_HMAC_SHA1_96; + ks[1].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL; + check(kadm5_create_principal_3(handle, &kent, mask, 2, ks, NULL)); + } else if (strcmp(argv[1], "swap") == 0) { + check(krb5_db_get_principal(ctx, hprinc, 0, &ent)); + kd = ent->key_data[0]; + ent->key_data[0] = ent->key_data[1]; + ent->key_data[1] = kd; + check(krb5_db_put_principal(ctx, ent)); + krb5_db_free_principal(ctx, ent); + } + krb5_free_default_realm(ctx, realm); + kadm5_destroy(handle); + krb5_free_principal(ctx, hprinc); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/hooks.c b/krb5-1.21.3/src/tests/hooks.c new file mode 100644 index 00000000..fabdb898 --- /dev/null +++ b/krb5-1.21.3/src/tests/hooks.c @@ -0,0 +1,253 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/hooks.c - test harness for KDC send and recv hooks */ +/* + * Copyright (C) 2016 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. + */ + +#include "k5-int.h" + +static krb5_context ctx; + +static void +check_code(krb5_error_code code, const char *file, int line) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s:%d -- %s (code=%d)\n", file, line, errmsg, + (int)code); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +#define check(code) check_code((code), __FILE__, __LINE__) + +/* Verify that the canonicalize bit is set in an AS-REQ and remove it. */ +static krb5_error_code +test_send_as_req(krb5_context context, void *data, const krb5_data *realm, + const krb5_data *message, krb5_data **new_message_out, + krb5_data **reply_out) +{ + krb5_kdc_req *as_req; + int cmp; + + assert(krb5_is_as_req(message)); + check(decode_krb5_as_req(message, &as_req)); + + assert(as_req->msg_type == KRB5_AS_REQ); + assert(as_req->kdc_options & KDC_OPT_CANONICALIZE); + assert(as_req->client->realm.length == realm->length); + cmp = memcmp(as_req->client->realm.data, realm->data, realm->length); + assert(cmp == 0); + + /* Remove the canonicalize flag and create a new message. */ + as_req->kdc_options &= ~KDC_OPT_CANONICALIZE; + check(encode_krb5_as_req(as_req, new_message_out)); + + krb5_free_kdc_req(context, as_req); + return 0; +} + +/* Verify that reply is an AS-REP with kvno 1 and a valid enctype. */ +static krb5_error_code +test_recv_as_rep(krb5_context context, void *data, krb5_error_code code, + const krb5_data *realm, const krb5_data *message, + const krb5_data *reply, krb5_data **new_reply) +{ + krb5_kdc_rep *as_rep; + + assert(code == 0); + assert(krb5_is_as_rep(reply)); + check(decode_krb5_as_rep(reply, &as_rep)); + + assert(as_rep->msg_type == KRB5_AS_REP); + assert(as_rep->ticket->enc_part.kvno == 1); + assert(krb5_c_valid_enctype(as_rep->ticket->enc_part.enctype)); + + krb5_free_kdc_rep(context, as_rep); + return 0; +} + +/* Create a fake error reply. */ +static krb5_error_code +test_send_error(krb5_context context, void *data, const krb5_data *realm, + const krb5_data *message, krb5_data **new_message_out, + krb5_data **reply_out) +{ + krb5_error_code ret; + krb5_error err; + krb5_principal client, server; + char *realm_str, *princ_str; + int r; + + realm_str = k5memdup0(realm->data, realm->length, &ret); + check(ret); + + r = asprintf(&princ_str, "invalid@%s", realm_str); + assert(r > 0); + check(krb5_parse_name(ctx, princ_str, &client)); + free(princ_str); + + r = asprintf(&princ_str, "krbtgt@%s", realm_str); + assert(r > 0); + check(krb5_parse_name(ctx, princ_str, &server)); + free(princ_str); + free(realm_str); + + err.magic = KV5M_ERROR; + err.ctime = 1971196337; + err.cusec = 0; + err.susec = 97008; + err.stime = 1458219390; + err.error = 6; + err.client = client; + err.server = server; + err.text = string2data("CLIENT_NOT_FOUND"); + err.e_data = empty_data(); + check(encode_krb5_error(&err, reply_out)); + + krb5_free_principal(ctx, client); + krb5_free_principal(ctx, server); + return 0; +} + +static krb5_error_code +test_recv_error(krb5_context context, void *data, krb5_error_code code, + const krb5_data *realm, const krb5_data *message, + const krb5_data *reply, krb5_data **new_reply) +{ + /* The send hook created a reply, so this hook should not be executed. */ + abort(); +} + +/* Modify an AS-REP reply, change the msg_type to KRB5_TGS_REP. */ +static krb5_error_code +test_recv_modify_reply(krb5_context context, void *data, krb5_error_code code, + const krb5_data *realm, const krb5_data *message, + const krb5_data *reply, krb5_data **new_reply) +{ + krb5_kdc_rep *as_rep; + + assert(code == 0); + assert(krb5_is_as_rep(reply)); + check(decode_krb5_as_rep(reply, &as_rep)); + + as_rep->msg_type = KRB5_TGS_REP; + check(encode_krb5_as_rep(as_rep, new_reply)); + + krb5_free_kdc_rep(context, as_rep); + return 0; +} + +/* Return an error given by the callback data argument. */ +static krb5_error_code +test_send_return_value(krb5_context context, void *data, + const krb5_data *realm, const krb5_data *message, + krb5_data **new_message_out, krb5_data **reply_out) +{ + assert(data != NULL); + return *(krb5_error_code *)data; +} + +/* Return an error given by the callback argument. */ +static krb5_error_code +test_recv_return_value(krb5_context context, void *data, krb5_error_code code, + const krb5_data *realm, const krb5_data *message, + const krb5_data *reply, krb5_data **new_reply) +{ + assert(data != NULL); + return *(krb5_error_code *)data; +} + +int +main(int argc, char *argv[]) +{ + const char *principal, *password; + krb5_principal client; + krb5_get_init_creds_opt *opts; + krb5_creds creds; + krb5_error_code ret, test_return_code; + + if (argc != 3) { + fprintf(stderr, "Usage: %s princname password\n", argv[0]); + exit(1); + } + principal = argv[1]; + password = argv[2]; + + check(krb5_init_context(&ctx)); + check(krb5_parse_name(ctx, principal, &client)); + + /* Use a send hook to modify an outgoing AS-REQ. The library will detect + * the modification in the reply. */ + check(krb5_get_init_creds_opt_alloc(ctx, &opts)); + krb5_get_init_creds_opt_set_canonicalize(opts, 1); + krb5_set_kdc_send_hook(ctx, test_send_as_req, NULL); + krb5_set_kdc_recv_hook(ctx, test_recv_as_rep, NULL); + ret = krb5_get_init_creds_password(ctx, &creds, client, password, NULL, + NULL, 0, NULL, opts); + assert(ret == KRB5_KDCREP_MODIFIED); + krb5_get_init_creds_opt_free(ctx, opts); + + /* Use a send hook to synthesize a KRB-ERROR reply. */ + krb5_set_kdc_send_hook(ctx, test_send_error, NULL); + krb5_set_kdc_recv_hook(ctx, test_recv_error, NULL); + ret = krb5_get_init_creds_password(ctx, &creds, client, password, NULL, + NULL, 0, NULL, NULL); + assert(ret == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN); + + /* Use a recv hook to modify a KDC reply. */ + krb5_set_kdc_send_hook(ctx, NULL, NULL); + krb5_set_kdc_recv_hook(ctx, test_recv_modify_reply, NULL); + ret = krb5_get_init_creds_password(ctx, &creds, client, password, NULL, + NULL, 0, NULL, NULL); + assert(ret == KRB5KRB_AP_ERR_MSG_TYPE); + + /* Verify that the user data pointer works in the send hook. */ + test_return_code = KRB5KDC_ERR_PREAUTH_FAILED; + krb5_set_kdc_send_hook(ctx, test_send_return_value, &test_return_code); + krb5_set_kdc_recv_hook(ctx, NULL, NULL); + ret = krb5_get_init_creds_password(ctx, &creds, client, password, NULL, + NULL, 0, NULL, NULL); + assert(ret == KRB5KDC_ERR_PREAUTH_FAILED); + + /* Verify that the user data pointer works in the recv hook. */ + test_return_code = KRB5KDC_ERR_NULL_KEY; + krb5_set_kdc_send_hook(ctx, NULL, NULL); + krb5_set_kdc_recv_hook(ctx, test_recv_return_value, &test_return_code); + ret = krb5_get_init_creds_password(ctx, &creds, client, password, NULL, + NULL, 0, NULL, NULL); + assert(ret == KRB5KDC_ERR_NULL_KEY); + + krb5_free_principal(ctx, client); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/hrealm.c b/krb5-1.21.3/src/tests/hrealm.c new file mode 100644 index 00000000..f464c8fd --- /dev/null +++ b/krb5-1.21.3/src/tests/hrealm.c @@ -0,0 +1,99 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/hrealm.c - Test harness for host-realm interfaces */ +/* + * Copyright (C) 2012 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. + */ + +/* + * This program is intended to be run from a python script as: + * + * hrealm -h|-f|-d [hostname] + * + * Calls krb5_get_host_realm, krb5_get_fallback_host_realm, or + * krb5_default_realm depending on the option given. For the first two + * choices, hostname or NULL is passed as the argument. The results are + * displayed one per line. + */ + +#include "k5-int.h" + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +static void +display(char **realms) +{ + while (realms != NULL && *realms != NULL) + printf("%s\n", *realms++); +} + +int +main(int argc, char **argv) +{ + krb5_data d; + char **realms, *realm; + + check(krb5_init_context(&ctx)); + + /* Parse arguments. */ + if (argc < 2 || argc > 3) + abort(); + + if (strcmp(argv[1], "-d") == 0) { + check(krb5_get_default_realm(ctx, &realm)); + printf("%s\n", realm); + krb5_free_default_realm(ctx, realm); + } else if (strcmp(argv[1], "-h") == 0) { + check(krb5_get_host_realm(ctx, argv[2], &realms)); + display(realms); + krb5_free_host_realm(ctx, realms); + } else if (strcmp(argv[1], "-f") == 0) { + assert(argc == 3); + d = string2data(argv[2]); + check(krb5_get_fallback_host_realm(ctx, &d, &realms)); + display(realms); + krb5_free_host_realm(ctx, realms); + } else { + abort(); + } + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/icinterleave.c b/krb5-1.21.3/src/tests/icinterleave.c new file mode 100644 index 00000000..bcc87c7c --- /dev/null +++ b/krb5-1.21.3/src/tests/icinterleave.c @@ -0,0 +1,128 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/icinterleave.c - interleaved init_creds_step test harness */ +/* + * Copyright (C) 2017 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. + */ + +/* + * This test harness performs multiple initial creds operations using + * krb5_init_creds_step(), interleaving the operations to test the scoping of + * the preauth state. All principals must have the same password (or not + * require a password). + */ + +#include "k5-int.h" + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +int +main(int argc, char **argv) +{ + const char *password; + char **princstrs; + krb5_principal client; + krb5_init_creds_context *iccs; + krb5_data req, *reps, realm; + krb5_boolean any_left; + int i, nclients, primary; + unsigned int flags; + + if (argc < 3) { + fprintf(stderr, "Usage: icinterleave password princ1 princ2 ...\n"); + exit(1); + } + password = argv[1]; + princstrs = argv + 2; + nclients = argc - 2; + + check(krb5_init_context(&ctx)); + + /* Create an initial creds context for each client principal. */ + iccs = calloc(nclients, sizeof(*iccs)); + assert(iccs != NULL); + for (i = 0; i < nclients; i++) { + check(krb5_parse_name(ctx, princstrs[i], &client)); + check(krb5_init_creds_init(ctx, client, NULL, NULL, 0, NULL, + &iccs[i])); + check(krb5_init_creds_set_password(ctx, iccs[i], password)); + krb5_free_principal(ctx, client); + } + + reps = calloc(nclients, sizeof(*reps)); + assert(reps != NULL); + + any_left = TRUE; + while (any_left) { + any_left = FALSE; + for (i = 0; i < nclients; i++) { + if (iccs[i] == NULL) + continue; + any_left = TRUE; + + printf("step %d\n", i + 1); + + req = empty_data(); + realm = empty_data(); + check(krb5_init_creds_step(ctx, iccs[i], &reps[i], &req, &realm, + &flags)); + if (!(flags & KRB5_INIT_CREDS_STEP_FLAG_CONTINUE)) { + printf("finish %d\n", i + 1); + krb5_init_creds_free(ctx, iccs[i]); + iccs[i] = NULL; + continue; + } + + primary = 0; + krb5_free_data_contents(ctx, &reps[i]); + check(krb5_sendto_kdc(ctx, &req, &realm, &reps[i], &primary, 0)); + krb5_free_data_contents(ctx, &req); + krb5_free_data_contents(ctx, &realm); + } + } + + for (i = 0; i < nclients; i++) + krb5_free_data_contents(ctx, &reps[i]); + free(reps); + free(iccs); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/icred.c b/krb5-1.21.3/src/tests/icred.c new file mode 100644 index 00000000..d6ce1d5d --- /dev/null +++ b/krb5-1.21.3/src/tests/icred.c @@ -0,0 +1,144 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/icred.c - test harness for getting initial creds */ +/* + * 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. + */ + +/* This program exercises the init_creds APIs in ways kinit doesn't. */ + +#include "k5-platform.h" +#include + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +int +main(int argc, char **argv) +{ + const char *ktname = NULL, *sname = NULL, *princstr, *password; + krb5_principal client; + krb5_init_creds_context icc; + krb5_get_init_creds_opt *opt; + krb5_keytab keytab = NULL; + krb5_creds creds; + krb5_boolean stepwise = FALSE; + krb5_preauthtype ptypes[64]; + int c, nptypes = 0; + char *val; + + check(krb5_init_context(&ctx)); + check(krb5_get_init_creds_opt_alloc(ctx, &opt)); + + while ((c = getopt(argc, argv, "k:so:S:X:")) != -1) { + switch (c) { + case 'k': + ktname = optarg; + break; + case 's': + stepwise = TRUE; + break; + case 'o': + assert(nptypes < 64); + ptypes[nptypes++] = atoi(optarg); + break; + case 'S': + sname = optarg; + break; + case 'X': + val = strchr(optarg, '='); + if (val != NULL) + *val++ = '\0'; + else + val = "yes"; + check(krb5_get_init_creds_opt_set_pa(ctx, opt, optarg, val)); + break; + default: + abort(); + } + } + + argc -= optind; + argv += optind; + if (argc != 1 && argc != 2) + abort(); + princstr = argv[0]; + password = argv[1]; + + if (sname != NULL) { + check(krb5_sname_to_principal(ctx, princstr, sname, KRB5_NT_SRV_HST, + &client)); + } else { + check(krb5_parse_name(ctx, princstr, &client)); + } + + if (ktname != NULL) + check(krb5_kt_resolve(ctx, ktname, &keytab)); + + if (nptypes > 0) + krb5_get_init_creds_opt_set_preauth_list(opt, ptypes, nptypes); + + if (stepwise) { + /* Use the stepwise interface. */ + check(krb5_init_creds_init(ctx, client, NULL, NULL, 0, NULL, &icc)); + if (keytab != NULL) + check(krb5_init_creds_set_keytab(ctx, icc, keytab)); + if (password != NULL) + check(krb5_init_creds_set_password(ctx, icc, password)); + check(krb5_init_creds_get(ctx, icc)); + krb5_init_creds_free(ctx, icc); + } else if (keytab != NULL) { + check(krb5_get_init_creds_keytab(ctx, &creds, client, keytab, 0, NULL, + opt)); + krb5_free_cred_contents(ctx, &creds); + } else { + /* Use the traditional one-shot interface. */ + check(krb5_get_init_creds_password(ctx, &creds, client, password, NULL, + NULL, 0, NULL, opt)); + krb5_free_cred_contents(ctx, &creds); + } + + if (keytab != NULL) + krb5_kt_close(ctx, keytab); + krb5_get_init_creds_opt_free(ctx, opt); + krb5_free_principal(ctx, client); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/jsonwalker.py b/krb5-1.21.3/src/tests/jsonwalker.py new file mode 100644 index 00000000..0dbdadd6 --- /dev/null +++ b/krb5-1.21.3/src/tests/jsonwalker.py @@ -0,0 +1,105 @@ +import sys +import json +from collections import defaultdict +from optparse import OptionParser + +class Parser(object): + DEFAULTS = {int:0, + str:'', + list:[]} + + def __init__(self, defconf=None): + self.defaults = None + if defconf is not None: + self.defaults = self.flatten(defconf) + + def run(self, logs, verbose=None): + result = self.parse(logs) + if len(result) != len(self.defaults): + diff = set(self.defaults.keys()).difference(result.keys()) + print('Test failed.') + print('The following attributes were not set:') + for it in diff: + print(it) + sys.exit(1) + + def flatten(self, defaults): + """ + Flattens paths to attributes. + + Parameters + ---------- + defaults : a dictionaries populated with default values + + Returns : + dict : with flattened attributes + """ + result = dict() + for path,value in self._walk(defaults): + if path in result: + print('Warning: attribute path %s already exists' % path) + result[path] = value + + return result + + def parse(self, logs): + result = defaultdict(list) + for msg in logs: + # each message is treated as a dictionary of dictionaries + for a,v in self._walk(msg): + # see if path is registered in defaults + if a in self.defaults: + dv = self.defaults.get(a) + if dv is None: + # determine default value by type + if v is not None: + dv = self.DEFAULTS[type(v)] + else: + print('Warning: attribute %s is set to None' % a) + continue + # by now we have default value + if v != dv: + # test passed + result[a].append(v) + return result + + def _walk(self, adict): + """ + Generator that works through dictionary. + """ + for a,v in adict.items(): + if isinstance(v,dict): + for (attrpath,u) in self._walk(v): + yield (a+'.'+attrpath,u) + else: + yield (a,v) + + +if __name__ == '__main__': + + parser = OptionParser() + parser.add_option("-i", "--logfile", dest="filename", + help="input log file in json fmt", metavar="FILE") + parser.add_option("-d", "--defaults", dest="defaults", + help="dictionary with defaults", metavar="FILE") + + (options, args) = parser.parse_args() + if options.filename is not None: + with open(options.filename, 'r') as f: + content = list() + for l in f: + content.append(json.loads(l.rstrip())) + f.close() + else: + print('Input file in JSON format is required') + exit() + + defaults = None + if options.defaults is not None: + with open(options.defaults, 'r') as f: + defaults = json.load(f) + + # run test + p = Parser(defaults) + p.run(content) + exit() diff --git a/krb5-1.21.3/src/tests/kcmserver.py b/krb5-1.21.3/src/tests/kcmserver.py new file mode 100644 index 00000000..f6dfcb71 --- /dev/null +++ b/krb5-1.21.3/src/tests/kcmserver.py @@ -0,0 +1,336 @@ +# This is a simple KCM test server, used to exercise the KCM ccache +# client code. It will generally throw an uncaught exception if the +# client sends anything unexpected, so is unsuitable for production. +# (It also imposes no namespace or access constraints, and blocks +# while reading requests and writing responses.) + +# This code knows nothing about how to marshal and unmarshal principal +# names and credentials as is required in the KCM protocol; instead, +# it just remembers the marshalled forms and replays them to the +# client when asked. This works because marshalled creds and +# principal names are always the last part of marshalled request +# arguments, and because we don't need to implement remove_cred (which +# would need to know how to match a cred tag against previously stored +# credentials). + +# The following code is useful for debugging if anything appears to be +# going wrong in the server, since daemon output is generally not +# visible in Python test scripts. +# +# import sys, traceback +# def ehook(etype, value, tb): +# with open('/tmp/exception', 'w') as f: +# traceback.print_exception(etype, value, tb, file=f) +# sys.excepthook = ehook + +import optparse +import select +import socket +import struct +import sys + +caches = {} +cache_uuidmap = {} +defname = b'default' +next_unique = 1 +next_uuid = 1 + +class KCMOpcodes(object): + GEN_NEW = 3 + INITIALIZE = 4 + DESTROY = 5 + STORE = 6 + RETRIEVE = 7 + GET_PRINCIPAL = 8 + GET_CRED_UUID_LIST = 9 + GET_CRED_BY_UUID = 10 + REMOVE_CRED = 11 + GET_CACHE_UUID_LIST = 18 + GET_CACHE_BY_UUID = 19 + GET_DEFAULT_CACHE = 20 + SET_DEFAULT_CACHE = 21 + GET_KDC_OFFSET = 22 + SET_KDC_OFFSET = 23 + GET_CRED_LIST = 13001 + REPLACE = 13002 + + +class KRB5Errors(object): + KRB5_CC_NOTFOUND = -1765328243 + KRB5_CC_END = -1765328242 + KRB5_CC_NOSUPP = -1765328137 + KRB5_FCC_NOFILE = -1765328189 + KRB5_FCC_INTERNAL = -1765328188 + + +def make_uuid(): + global next_uuid + uuid = bytes(12) + struct.pack('>L', next_uuid) + next_uuid = next_uuid + 1 + return uuid + + +class Cache(object): + def __init__(self, name): + self.name = name + self.princ = None + self.uuid = make_uuid() + self.cred_uuids = [] + self.creds = {} + self.time_offset = 0 + + +def get_cache(name): + if name in caches: + return caches[name] + cache = Cache(name) + caches[name] = cache + cache_uuidmap[cache.uuid] = cache + return cache + + +def unmarshal_name(argbytes): + offset = argbytes.find(b'\0') + return argbytes[0:offset], argbytes[offset+1:] + + +# Find the bounds of a marshalled principal, returning it and the +# remainder of argbytes. +def extract_princ(argbytes): + ncomps, rlen = struct.unpack('>LL', argbytes[4:12]) + pos = 12 + rlen + for i in range(ncomps): + clen, = struct.unpack('>L', argbytes[pos:pos+4]) + pos += 4 + clen + return argbytes[0:pos], argbytes[pos:] + + +# Return true if the marshalled principals p1 and p2 name the same +# principal. +def princ_eq(p1, p2): + # Ignore the name-types at bytes 0..3. The remaining bytes should + # be identical if the principals are the same. + return p1[4:] == p2[4:] + + +def op_gen_new(argbytes): + # Does not actually check for uniqueness. + global next_unique + name = b'unique' + str(next_unique).encode('ascii') + next_unique += 1 + return 0, name + b'\0' + + +def op_initialize(argbytes): + name, princ = unmarshal_name(argbytes) + cache = get_cache(name) + cache.princ = princ + cache.cred_uuids = [] + cache.creds = {} + cache.time_offset = 0 + return 0, b'' + + +def op_destroy(argbytes): + name, rest = unmarshal_name(argbytes) + cache = get_cache(name) + del cache_uuidmap[cache.uuid] + del caches[name] + return 0, b'' + + +def op_store(argbytes): + name, cred = unmarshal_name(argbytes) + cache = get_cache(name) + uuid = make_uuid() + cache.creds[uuid] = cred + cache.cred_uuids.append(uuid) + return 0, b'' + + +def op_retrieve(argbytes): + name, rest = unmarshal_name(argbytes) + # Ignore the flags at rest[0:4] and the header at rest[4:8]. + # Assume there are client and server creds in the tag and match + # only against them. + cprinc, rest = extract_princ(rest[8:]) + sprinc, rest = extract_princ(rest) + cache = get_cache(name) + for cred in (cache.creds[u] for u in cache.cred_uuids): + cred_cprinc, rest = extract_princ(cred) + cred_sprinc, rest = extract_princ(rest) + if princ_eq(cred_cprinc, cprinc) and princ_eq(cred_sprinc, sprinc): + return 0, cred + return KRB5Errors.KRB5_CC_NOTFOUND, b'' + + +def op_get_principal(argbytes): + name, rest = unmarshal_name(argbytes) + cache = get_cache(name) + if cache.princ is None: + return KRB5Errors.KRB5_FCC_NOFILE, b'' + return 0, cache.princ + b'\0' + + +def op_get_cred_uuid_list(argbytes): + name, rest = unmarshal_name(argbytes) + cache = get_cache(name) + return 0, b''.join(cache.cred_uuids) + + +def op_get_cred_by_uuid(argbytes): + name, uuid = unmarshal_name(argbytes) + cache = get_cache(name) + if uuid not in cache.creds: + return KRB5Errors.KRB5_CC_END, b'' + return 0, cache.creds[uuid] + + +def op_remove_cred(argbytes): + return KRB5Errors.KRB5_CC_NOSUPP, b'' + + +def op_get_cache_uuid_list(argbytes): + return 0, b''.join(cache_uuidmap.keys()) + + +def op_get_cache_by_uuid(argbytes): + uuid = argbytes + if uuid not in cache_uuidmap: + return KRB5Errors.KRB5_CC_END, b'' + return 0, cache_uuidmap[uuid].name + b'\0' + + +def op_get_default_cache(argbytes): + return 0, defname + b'\0' + + +def op_set_default_cache(argbytes): + global defname + defname, rest = unmarshal_name(argbytes) + return 0, b'' + + +def op_get_kdc_offset(argbytes): + name, rest = unmarshal_name(argbytes) + cache = get_cache(name) + return 0, struct.pack('>l', cache.time_offset) + + +def op_set_kdc_offset(argbytes): + name, obytes = unmarshal_name(argbytes) + cache = get_cache(name) + cache.time_offset, = struct.unpack('>l', obytes) + return 0, b'' + + +def op_get_cred_list(argbytes): + name, rest = unmarshal_name(argbytes) + cache = get_cache(name) + creds = [cache.creds[u] for u in cache.cred_uuids] + return 0, (struct.pack('>L', len(creds)) + + b''.join(struct.pack('>L', len(c)) + c for c in creds)) + + +def op_replace(argbytes): + name, rest = unmarshal_name(argbytes) + offset, = struct.unpack('>L', rest[0:4]) + princ, rest = extract_princ(rest[4:]) + ncreds, = struct.unpack('>L', rest[0:4]) + rest = rest[4:] + creds = [] + for i in range(ncreds): + len, = struct.unpack('>L', rest[0:4]) + creds.append(rest[4:4+len]) + rest = rest[4+len:] + + cache = get_cache(name) + cache.princ = princ + cache.cred_uuids = [] + cache.creds = {} + cache.time_offset = offset + for i in range(ncreds): + uuid = make_uuid() + cache.creds[uuid] = creds[i] + cache.cred_uuids.append(uuid) + + return 0, b'' + + +ophandlers = { + KCMOpcodes.GEN_NEW : op_gen_new, + KCMOpcodes.INITIALIZE : op_initialize, + KCMOpcodes.DESTROY : op_destroy, + KCMOpcodes.STORE : op_store, + KCMOpcodes.RETRIEVE : op_retrieve, + KCMOpcodes.GET_PRINCIPAL : op_get_principal, + KCMOpcodes.GET_CRED_UUID_LIST : op_get_cred_uuid_list, + KCMOpcodes.GET_CRED_BY_UUID : op_get_cred_by_uuid, + KCMOpcodes.REMOVE_CRED : op_remove_cred, + KCMOpcodes.GET_CACHE_UUID_LIST : op_get_cache_uuid_list, + KCMOpcodes.GET_CACHE_BY_UUID : op_get_cache_by_uuid, + KCMOpcodes.GET_DEFAULT_CACHE : op_get_default_cache, + KCMOpcodes.SET_DEFAULT_CACHE : op_set_default_cache, + KCMOpcodes.GET_KDC_OFFSET : op_get_kdc_offset, + KCMOpcodes.SET_KDC_OFFSET : op_set_kdc_offset, + KCMOpcodes.GET_CRED_LIST : op_get_cred_list, + KCMOpcodes.REPLACE : op_replace +} + +# Read and respond to a request from the socket s. +def service_request(s): + lenbytes = b'' + while len(lenbytes) < 4: + lenbytes += s.recv(4 - len(lenbytes)) + if lenbytes == b'': + return False + + reqlen, = struct.unpack('>L', lenbytes) + req = b'' + while len(req) < reqlen: + req += s.recv(reqlen - len(req)) + + majver, minver, op = struct.unpack('>BBH', req[:4]) + argbytes = req[4:] + + if op in ophandlers: + code, payload = ophandlers[op](argbytes) + else: + code, payload = KRB5Errors.KRB5_FCC_INTERNAL, b'' + + # The KCM response is the code (4 bytes) and the response payload. + # The Heimdal IPC response is the length of the KCM response (4 + # bytes), a status code which is essentially always 0 (4 bytes), + # and the KCM response. + kcm_response = struct.pack('>l', code) + payload + hipc_response = struct.pack('>LL', len(kcm_response), 0) + kcm_response + s.sendall(hipc_response) + return True + +parser = optparse.OptionParser() +parser.add_option('-f', '--fallback', action='store_true', dest='fallback', + default=False, + help='Do not support RETRIEVE/GET_CRED_LIST/REPLACE') +(options, args) = parser.parse_args() +if options.fallback: + del ophandlers[KCMOpcodes.RETRIEVE] + del ophandlers[KCMOpcodes.GET_CRED_LIST] + del ophandlers[KCMOpcodes.REPLACE] + +server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +server.bind(args[0]) +server.listen(5) +select_input = [server,] +sys.stderr.write('starting...\n') +sys.stderr.flush() + +while True: + iready, oready, xready = select.select(select_input, [], []) + for s in iready: + if s == server: + client, addr = server.accept() + select_input.append(client) + else: + if not service_request(s): + select_input.remove(s) + s.close() diff --git a/krb5-1.21.3/src/tests/kdbtest.c b/krb5-1.21.3/src/tests/kdbtest.c new file mode 100644 index 00000000..3f61f3e8 --- /dev/null +++ b/krb5-1.21.3/src/tests/kdbtest.c @@ -0,0 +1,403 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/kdbtest.c - test program to exercise KDB modules */ +/* + * Copyright (C) 2012 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. + */ + +/* + * This test program uses libkdb5 APIs to exercise as much of the LDAP and DB2 + * back ends. + */ + +#include +#include +#include + +static krb5_context ctx; + +#define CHECK(code) check(code, __LINE__) +#define CHECK_COND(val) check_cond(val, __LINE__) + +static void +check(krb5_error_code code, int lineno) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "Unexpected error at line %d: %s\n", lineno, errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +static void +check_cond(int value, int lineno) +{ + if (!value) { + fprintf(stderr, "Unexpected result at line %d\n", lineno); + exit(1); + } +} + +static krb5_data princ_data[2] = { + { KV5M_DATA, 6, "xy*(z)" }, + { KV5M_DATA, 12, "+<> *()\\#\",;" } +}; + +static krb5_principal_data sample_princ = { + KV5M_PRINCIPAL, + { KV5M_DATA, 11, "KRBTEST.COM" }, + princ_data, 2, KRB5_NT_UNKNOWN +}; + +static krb5_principal_data xrealm_princ = { + KV5M_PRINCIPAL, + { KV5M_DATA, 12, "KRBTEST2.COM" }, + princ_data, 2, KRB5_NT_UNKNOWN +}; + +#define U(x) (unsigned char *)x + +/* + * tl1 through tl4 are normalized to attributes in the LDAP back end. tl5 is + * stored as untranslated tl-data. tl3 contains an encoded osa_princ_ent with + * a policy reference to "". + */ +static krb5_tl_data tl5 = { NULL, KRB5_TL_MKVNO, 2, U("\0\1") }; +static krb5_tl_data tl4 = { &tl5, KRB5_TL_LAST_ADMIN_UNLOCK, 4, + U("\6\0\0\0") }; +static krb5_tl_data tl3 = { &tl4, KRB5_TL_KADM_DATA, 32, + U("\x12\x34\x5C\x01\x00\x00\x00\x08" + "\x3C\x74\x65\x73\x74\x2A\x3E\x00" + "\x00\x00\x08\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00") }; +static krb5_tl_data tl2 = { &tl3, KRB5_TL_MOD_PRINC, 8, U("\5\6\7\0x@Y\0") }; +static krb5_tl_data tl1 = { &tl2, KRB5_TL_LAST_PWD_CHANGE, 4, U("\1\2\3\4") }; + +/* An encoded osa_print_enc with no policy reference. */ +static krb5_tl_data tl_no_policy = { NULL, KRB5_TL_KADM_DATA, 24, + U("\x12\x34\x5C\x01\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x02\x00\x00\x00\x00") }; + +static krb5_key_data keys[] = { + { + 2, /* key_data_ver */ + 2, /* key_data_kvno */ + { ENCTYPE_AES256_CTS_HMAC_SHA1_96, KRB5_KDB_SALTTYPE_SPECIAL }, + { 32, 7 }, + { U("\x17\xF2\x75\xF2\x95\x4F\x2E\xD1" + "\xF9\x0C\x37\x7B\xA7\xF4\xD6\xA3" + "\x69\xAA\x01\x36\xE0\xBF\x0C\x92" + "\x7A\xD6\x13\x3C\x69\x37\x59\xA9"), + U("expsalt") } + }, + { + 2, /* key_data_ver */ + 2, /* key_data_kvno */ + { ENCTYPE_AES128_CTS_HMAC_SHA1_96, 0 }, + { 16, 0 }, + { U("\xDC\xEE\xB7\x0B\x3D\xE7\x65\x62" + "\xE6\x89\x22\x6C\x76\x42\x91\x48"), + NULL } + } +}; +#undef U + +static char polname[] = ""; + +static krb5_db_entry sample_entry = { + 0, + KRB5_KDB_V1_BASE_LENGTH, + /* mask */ + KADM5_PRINCIPAL | KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION | + KADM5_ATTRIBUTES | KADM5_MAX_LIFE | KADM5_POLICY | KADM5_MAX_RLIFE | + KADM5_LAST_SUCCESS | KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT | + KADM5_KEY_DATA | KADM5_TL_DATA, + /* attributes */ + KRB5_KDB_REQUIRES_PRE_AUTH | KRB5_KDB_REQUIRES_HW_AUTH | + KRB5_KDB_DISALLOW_SVR, + 1234, /* max_life */ + 5678, /* max_renewable_life */ + 9012, /* expiration */ + 3456, /* pw_expiration */ + 1, /* last_success */ + 5, /* last_failed */ + 2, /* fail_auth_count */ + 5, /* n_tl_data */ + 2, /* n_key_data */ + 0, NULL, /* e_length, e_data */ + &sample_princ, + &tl1, + keys +}; + +static osa_policy_ent_rec sample_policy = { + 0, /* version */ + polname, /* name */ + 1357, /* pw_min_life */ + 100, /* pw_max_life */ + 6, /* pw_min_length */ + 2, /* pw_min_classes */ + 3, /* pw_history_num */ + 0, /* policy_refcnt */ + 2, /* pw_max_fail */ + 60, /* pw_failcnt_interval */ + 120, /* pw_lockout_duration */ + 0, /* attributes */ + 2468, /* max_life */ + 3579, /* max_renewable_life */ + "aes", /* allowed_keysalts */ + 0, NULL /* n_tl_data, tl_data */ +}; + +/* Compare pol against sample_policy. */ +static void +check_policy(osa_policy_ent_t pol) +{ + CHECK_COND(strcmp(pol->name, sample_policy.name) == 0); + CHECK_COND(pol->pw_min_life == sample_policy.pw_min_life); + CHECK_COND(pol->pw_max_life == sample_policy.pw_max_life); + CHECK_COND(pol->pw_min_length == sample_policy.pw_min_length); + CHECK_COND(pol->pw_min_classes == sample_policy.pw_min_classes); + CHECK_COND(pol->pw_history_num == sample_policy.pw_history_num); + CHECK_COND(pol->pw_max_life == sample_policy.pw_max_life); + CHECK_COND(pol->pw_failcnt_interval == sample_policy.pw_failcnt_interval); + CHECK_COND(pol->pw_lockout_duration == sample_policy.pw_lockout_duration); + CHECK_COND(pol->attributes == sample_policy.attributes); + CHECK_COND(pol->max_life == sample_policy.max_life); + CHECK_COND(pol->max_renewable_life == sample_policy.max_renewable_life); + CHECK_COND(strcmp(pol->allowed_keysalts, + sample_policy.allowed_keysalts) == 0); +} + +/* Compare ent against sample_entry. */ +static void +check_entry(krb5_db_entry *ent) +{ + krb5_int16 i, j; + krb5_key_data *k1, *k2; + krb5_tl_data *tl, etl; + + CHECK_COND(ent->attributes == sample_entry.attributes); + CHECK_COND(ent->max_life == sample_entry.max_life); + CHECK_COND(ent->max_renewable_life == sample_entry.max_renewable_life); + CHECK_COND(ent->expiration == sample_entry.expiration); + CHECK_COND(ent->pw_expiration == sample_entry.pw_expiration); + CHECK_COND(ent->last_success == sample_entry.last_success); + CHECK_COND(ent->last_failed == sample_entry.last_failed); + CHECK_COND(ent->fail_auth_count == sample_entry.fail_auth_count); + CHECK_COND(krb5_principal_compare(ctx, ent->princ, sample_entry.princ)); + CHECK_COND(ent->n_key_data == sample_entry.n_key_data); + for (i = 0; i < ent->n_key_data; i++) { + k1 = &ent->key_data[i]; + k2 = &sample_entry.key_data[i]; + CHECK_COND(k1->key_data_ver == k2->key_data_ver); + CHECK_COND(k1->key_data_kvno == k2->key_data_kvno); + for (j = 0; j < k1->key_data_ver; j++) { + CHECK_COND(k1->key_data_type[j] == k2->key_data_type[j]); + CHECK_COND(k1->key_data_length[j] == k2->key_data_length[j]); + CHECK_COND(memcmp(k1->key_data_contents[j], + k2->key_data_contents[j], + k1->key_data_length[j]) == 0); + } + } + for (tl = sample_entry.tl_data; tl != NULL; tl = tl->tl_data_next) { + etl.tl_data_type = tl->tl_data_type; + CHECK(krb5_dbe_lookup_tl_data(ctx, ent, &etl)); + CHECK_COND(tl->tl_data_length == etl.tl_data_length); + CHECK_COND(memcmp(tl->tl_data_contents, etl.tl_data_contents, + tl->tl_data_length) == 0); + } +} + +/* Audit a successful or failed preauth attempt for *entp. Then reload *entp + * (by fetching sample_princ) so we can see the effect. */ +static void +sim_preauth(krb5_timestamp authtime, krb5_boolean ok, krb5_db_entry **entp) +{ + /* Both back ends ignore the request, local_addr, and remote_addr + * parameters for now. */ + krb5_db_audit_as_req(ctx, NULL, NULL, NULL, *entp, *entp, authtime, + ok ? 0 : KRB5KDC_ERR_PREAUTH_FAILED); + krb5_db_free_principal(ctx, *entp); + CHECK(krb5_db_get_principal(ctx, &sample_princ, 0, entp)); +} + +static krb5_error_code +iter_princ_handler(void *data, krb5_db_entry *ent) +{ + int *count = data; + + CHECK_COND(krb5_principal_compare(ctx, ent->princ, sample_entry.princ)); + (*count)++; + return 0; +} + +static void +iter_pol_handler(void *data, osa_policy_ent_t pol) +{ + int *count = data; + + CHECK_COND(strcmp(pol->name, sample_policy.name) == 0); + (*count)++; +} + +int +main() +{ + krb5_db_entry *ent; + osa_policy_ent_t pol; + krb5_pa_data **e_data; + const char *status; + int count; + + CHECK(krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_KDC, &ctx)); + + /* If we can, revert to requiring all entries match sample_princ in + * iter_princ_handler */ + CHECK_COND(krb5_db_inited(ctx) != 0); + CHECK(krb5_db_create(ctx, NULL)); + CHECK(krb5_db_inited(ctx)); + CHECK(krb5_db_fini(ctx)); + CHECK_COND(krb5_db_inited(ctx) != 0); + + CHECK_COND(krb5_db_inited(ctx) != 0); + CHECK(krb5_db_open(ctx, NULL, KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN)); + CHECK(krb5_db_inited(ctx)); + + /* Manipulate a policy, leaving it in place at the end. */ + CHECK_COND(krb5_db_put_policy(ctx, &sample_policy) != 0); + CHECK_COND(krb5_db_delete_policy(ctx, polname) != 0); + CHECK_COND(krb5_db_get_policy(ctx, polname, &pol) == KRB5_KDB_NOENTRY); + CHECK(krb5_db_create_policy(ctx, &sample_policy)); + CHECK_COND(krb5_db_create_policy(ctx, &sample_policy) != 0); + CHECK(krb5_db_get_policy(ctx, polname, &pol)); + check_policy(pol); + pol->pw_min_length--; + CHECK(krb5_db_put_policy(ctx, pol)); + krb5_db_free_policy(ctx, pol); + CHECK(krb5_db_get_policy(ctx, polname, &pol)); + CHECK_COND(pol->pw_min_length == sample_policy.pw_min_length - 1); + krb5_db_free_policy(ctx, pol); + CHECK(krb5_db_delete_policy(ctx, polname)); + CHECK_COND(krb5_db_put_policy(ctx, &sample_policy) != 0); + CHECK_COND(krb5_db_delete_policy(ctx, polname) != 0); + CHECK_COND(krb5_db_get_policy(ctx, polname, &pol) == KRB5_KDB_NOENTRY); + CHECK(krb5_db_create_policy(ctx, &sample_policy)); + count = 0; + CHECK(krb5_db_iter_policy(ctx, NULL, iter_pol_handler, &count)); + CHECK_COND(count == 1); + + /* Create a principal. */ + CHECK_COND(krb5_db_delete_principal(ctx, &sample_princ) == + KRB5_KDB_NOENTRY); + CHECK_COND(krb5_db_get_principal(ctx, &xrealm_princ, 0, &ent) == + KRB5_KDB_NOENTRY); + CHECK(krb5_db_put_principal(ctx, &sample_entry)); + /* Putting again will fail with LDAP (due to KADM5_PRINCIPAL in mask) + * but succeed with DB2, so don't check the result. */ + (void)krb5_db_put_principal(ctx, &sample_entry); + /* But it should succeed in both back ends with KADM5_LOAD in mask. */ + sample_entry.mask |= KADM5_LOAD; + CHECK(krb5_db_put_principal(ctx, &sample_entry)); + sample_entry.mask &= ~KADM5_LOAD; + /* Fetch and compare the added principal. */ + CHECK(krb5_db_get_principal(ctx, &sample_princ, 0, &ent)); + check_entry(ent); + + /* We can't set up a successful allowed-to-delegate check through existing + * APIs yet, but we can make a failed check. */ + CHECK_COND(krb5_db_check_allowed_to_delegate(ctx, &sample_princ, ent, + &sample_princ) != 0); + + /* Exercise lockout code. */ + /* Policy params: max_fail 2, failcnt_interval 60, lockout_duration 120 */ + /* Initial state: last_success 1, last_failed 5, fail_auth_count 2, + * last admin unlock 6 */ + /* Check succeeds due to last admin unlock. */ + CHECK(krb5_db_check_policy_as(ctx, NULL, ent, ent, 7, &status, &e_data)); + /* Failure count resets to 1 due to last admin unlock. */ + sim_preauth(8, FALSE, &ent); + CHECK_COND(ent->fail_auth_count == 1 && ent->last_failed == 8); + /* Failure count resets to 1 due to failcnt_interval */ + sim_preauth(70, FALSE, &ent); + CHECK_COND(ent->fail_auth_count == 1 && ent->last_failed == 70); + /* Failure count resets to 0 due to successful preauth. */ + sim_preauth(75, TRUE, &ent); + CHECK_COND(ent->fail_auth_count == 0 && ent->last_success == 75); + /* Failure count increments to 2 and stops incrementing. */ + sim_preauth(80, FALSE, &ent); + CHECK_COND(ent->fail_auth_count == 1 && ent->last_failed == 80); + sim_preauth(100, FALSE, &ent); + CHECK_COND(ent->fail_auth_count == 2 && ent->last_failed == 100); + sim_preauth(110, FALSE, &ent); + CHECK_COND(ent->fail_auth_count == 2 && ent->last_failed == 100); + /* Check fails due to reaching maximum failure count. */ + CHECK_COND(krb5_db_check_policy_as(ctx, NULL, ent, ent, 170, &status, + &e_data) == KRB5KDC_ERR_CLIENT_REVOKED); + /* Check succeeds after lockout_duration has passed. */ + CHECK(krb5_db_check_policy_as(ctx, NULL, ent, ent, 230, &status, &e_data)); + /* Failure count resets to 1 on next failure. */ + sim_preauth(240, FALSE, &ent); + CHECK_COND(ent->fail_auth_count == 1 && ent->last_failed == 240); + + /* Exercise LDAP code to clear a policy reference and to set the key + * data on an existing principal. */ + CHECK(krb5_dbe_update_tl_data(ctx, ent, &tl_no_policy)); + ent->mask = KADM5_POLICY_CLR | KADM5_KEY_DATA; + CHECK(krb5_db_put_principal(ctx, ent)); + CHECK(krb5_db_delete_policy(ctx, polname)); + + /* Put the modified entry again (with KDB_TL_USER_INFO tl-data for LDAP) as + * from a load operation. */ + ent->mask = (sample_entry.mask & ~KADM5_POLICY) | KADM5_LOAD; + CHECK(krb5_db_put_principal(ctx, ent)); + + /* Exercise LDAP code to create a new principal at a DN from + * KDB_TL_USER_INFO tl-data. */ + CHECK(krb5_db_delete_principal(ctx, &sample_princ)); + CHECK(krb5_db_put_principal(ctx, ent)); + krb5_db_free_principal(ctx, ent); + + /* Exercise principal iteration code. */ + count = 0; + CHECK(krb5_db_iterate(ctx, "xy*", iter_princ_handler, &count, 0)); + CHECK_COND(count == 1); + + CHECK(krb5_db_fini(ctx)); + CHECK_COND(krb5_db_inited(ctx) != 0); + + /* It might be nice to exercise krb5_db_destroy here, but the LDAP module + * doesn't support it. */ + + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/localauth.c b/krb5-1.21.3/src/tests/localauth.c new file mode 100644 index 00000000..a3f7e15c --- /dev/null +++ b/krb5-1.21.3/src/tests/localauth.c @@ -0,0 +1,72 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/localauth.c - test harness for kuserok and aname_to_lname */ +/* + * 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. + */ + +#include +#include + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +int +main(int argc, char **argv) +{ + krb5_principal princ; + char buf[1024]; + + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: localauth principal [localuser]\n"); + return 1; + } + check(krb5_init_context(&ctx)); + check(krb5_parse_name(ctx, argv[1], &princ)); + if (argc == 3) { + printf("%s\n", krb5_kuserok(ctx, princ, argv[2]) ? "yes" : "no"); + } else { + check(krb5_aname_to_localname(ctx, princ, sizeof(buf), buf)); + printf("%s\n", buf); + } + krb5_free_principal(ctx, princ); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/misc/Makefile.in b/krb5-1.21.3/src/tests/misc/Makefile.in new file mode 100644 index 00000000..81feb1d8 --- /dev/null +++ b/krb5-1.21.3/src/tests/misc/Makefile.in @@ -0,0 +1,58 @@ +mydir=tests$(S)misc +BUILDTOP=$(REL)..$(S).. + +OBJS=\ + test_getpw.o \ + test_chpw_message.o + +SRCS=\ + $(srcdir)/test_getpw.c \ + $(srcdir)/test_chpw_message.c \ + $(srcdir)/test_getsockname.c \ + $(srcdir)/test_cxx_krb5.cpp \ + $(srcdir)/test_cxx_k5int.cpp \ + $(srcdir)/test_cxx_gss.cpp \ + $(srcdir)/test_cxx_rpc.cpp \ + $(srcdir)/test_cxx_kadm5.cpp + +all: test_getpw test_chpw_message + +check: test_getpw test_chpw_message test_cxx_krb5 test_cxx_gss test_cxx_rpc test_cxx_k5int test_cxx_kadm5 + $(RUN_TEST) ./test_getpw + $(RUN_TEST) ./test_chpw_message + $(RUN_TEST) ./test_cxx_krb5 + $(RUN_TEST) ./test_cxx_k5int + $(RUN_TEST) ./test_cxx_gss + $(RUN_TEST) ./test_cxx_rpc + $(RUN_TEST) ./test_cxx_kadm5 + +test_getpw: $(OUTPRE)test_getpw.$(OBJEXT) $(SUPPORT_DEPLIB) + $(CC_LINK) $(ALL_CFLAGS) -o test_getpw $(OUTPRE)test_getpw.$(OBJEXT) $(SUPPORT_LIB) + +test_chpw_message: $(OUTPRE)test_chpw_message.$(OBJEXT) $(SUPPORT_DEPLIB) + $(CC_LINK) $(ALL_CFLAGS) -o test_chpw_message $(OUTPRE)test_chpw_message.$(OBJEXT) $(KRB5_BASE_LIBS) $(LIBS) + +test_getsockname: $(OUTPRE)test_getsockname.$(OBJEXT) + $(CC_LINK) $(ALL_CFLAGS) -o test_getsockname $(OUTPRE)test_getsockname.$(OBJEXT) $(LIBS) + +test_cxx_krb5: $(OUTPRE)test_cxx_krb5.$(OBJEXT) $(KRB5_DEPLIB) + $(CXX_LINK) $(ALL_CXXFLAGS) -o test_cxx_krb5 $(OUTPRE)test_cxx_krb5.$(OBJEXT) $(KRB5_BASE_LIBS) $(LIBS) +test_cxx_k5int: $(OUTPRE)test_cxx_k5int.$(OBJEXT) $(KRB5_DEPLIB) + $(CXX_LINK) $(ALL_CXXFLAGS) -o test_cxx_k5int $(OUTPRE)test_cxx_k5int.$(OBJEXT) $(KRB5_BASE_LIBS) $(LIBS) +test_cxx_gss: $(OUTPRE)test_cxx_gss.$(OBJEXT) + $(CXX_LINK) $(ALL_CXXFLAGS) -o test_cxx_gss $(OUTPRE)test_cxx_gss.$(OBJEXT) $(LIBS) +test_cxx_rpc: $(OUTPRE)test_cxx_rpc.$(OBJEXT) $(GSSRPC_DEPLIBS) + $(CXX_LINK) $(ALL_CXXFLAGS) -o test_cxx_rpc $(OUTPRE)test_cxx_rpc.$(OBJEXT) $(GSSRPC_LIBS) $(KRB5_BASE_LIBS) $(LIBS) +test_cxx_kadm5: $(OUTPRE)test_cxx_kadm5.$(OBJEXT) $(KADMCLNT_DEPLIBS) + $(CXX_LINK) $(ALL_CXXFLAGS) -o test_cxx_kadm5 $(OUTPRE)test_cxx_kadm5.$(OBJEXT) $(KADMCLNT_LIBS) $(KRB5_BASE_LIBS) $(LIBS) + +test_cxx_krb5.$(OBJEXT): test_cxx_krb5.cpp +test_cxx_gss.$(OBJEXT): test_cxx_gss.cpp +test_cxx_rpc.$(OBJEXT): test_cxx_rpc.cpp +test_cxx_kadm5.$(OBJEXT): test_cxx_kadm5.cpp + +install: + +clean: + $(RM) test_getpw test_chpw_message test_cxx_krb5 test_cxx_gss test_cxx_k5int test_cxx_rpc test_cxx_kadm5 *.o + diff --git a/krb5-1.21.3/src/tests/misc/deps b/krb5-1.21.3/src/tests/misc/deps new file mode 100644 index 00000000..2572f0c3 --- /dev/null +++ b/krb5-1.21.3/src/tests/misc/deps @@ -0,0 +1,44 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)test_getpw.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + test_getpw.c +$(OUTPRE)test_chpw_message.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + test_chpw_message.c +$(OUTPRE)test_getsockname.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + test_getsockname.c +$(OUTPRE)test_cxx_krb5.$(OBJEXT): $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + $(top_srcdir)/include/krb5/locate_plugin.h test_cxx_krb5.cpp +$(OUTPRE)test_cxx_k5int.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-ipc_stream.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/k5-utf8.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h test_cxx_k5int.cpp +$(OUTPRE)test_cxx_gss.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + test_cxx_gss.cpp +$(OUTPRE)test_cxx_rpc.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h test_cxx_rpc.cpp +$(OUTPRE)test_cxx_kadm5.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/gssrpc/types.h $(BUILDTOP)/include/kadm5/admin.h \ + $(BUILDTOP)/include/kadm5/chpass_util_strings.h $(BUILDTOP)/include/kadm5/kadm_err.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/gssrpc/auth.h \ + $(top_srcdir)/include/gssrpc/auth_gss.h $(top_srcdir)/include/gssrpc/auth_unix.h \ + $(top_srcdir)/include/gssrpc/clnt.h $(top_srcdir)/include/gssrpc/rename.h \ + $(top_srcdir)/include/gssrpc/rpc.h $(top_srcdir)/include/gssrpc/rpc_msg.h \ + $(top_srcdir)/include/gssrpc/svc.h $(top_srcdir)/include/gssrpc/svc_auth.h \ + $(top_srcdir)/include/gssrpc/xdr.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h test_cxx_kadm5.cpp diff --git a/krb5-1.21.3/src/tests/misc/test_chpw_message.c b/krb5-1.21.3/src/tests/misc/test_chpw_message.c new file mode 100644 index 00000000..c6fdaa13 --- /dev/null +++ b/krb5-1.21.3/src/tests/misc/test_chpw_message.c @@ -0,0 +1,174 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/misc/test_getpw.c */ +/* + * Copyright (C) 2012 by the Red Hat Inc. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "autoconf.h" +#include "krb5.h" + +#include +#include +#include +#include +#include +#include + +static krb5_data result_utf8 = { + 0, 23, "This is a valid string.", +}; + +static krb5_data result_invalid_utf8 = { + 0, 19, "\0This is not valid.", +}; + +static krb5_data result_ad_complex = { + 0, 30, + "\0\0" /* zero bytes */ + "\0\0\0\0" /* min length */ + "\0\0\0\0" /* history */ + "\0\0\0\1" /* properties, complex */ + "\0\0\0\0\0\0\0\0" /* expire */ + "\0\0\0\0\0\0\0\0" /* min age */ +}; + +static krb5_data result_ad_length = { + 0, 30, + "\0\0" /* zero bytes */ + "\0\0\0\x0d" /* min length, 13 characters */ + "\0\0\0\0" /* history */ + "\0\0\0\0" /* properties */ + "\0\0\0\0\0\0\0\0" /* expire */ + "\0\0\0\0\0\0\0\0" /* min age */ +}; + +static krb5_data result_ad_history = { + 0, 30, + "\0\0" /* zero bytes */ + "\0\0\0\0" /* min length */ + "\0\0\0\x09" /* history, 9 passwords */ + "\0\0\0\0" /* properties */ + "\0\0\0\0\0\0\0\0" /* expire */ + "\0\0\0\0\0\0\0\0" /* min age */ +}; + +static krb5_data result_ad_age = { + 0, 30, + "\0\0" /* zero bytes */ + "\0\0\0\0" /* min length */ + "\0\0\0\0" /* history, 9 passwords */ + "\0\0\0\0" /* properties */ + "\0\0\0\0\0\0\0\0" /* expire */ + "\0\0\x01\x92\x54\xd3\x80\0" /* min age, 2 days */ +}; + +static krb5_data result_ad_all = { + 0, 30, + "\0\0" /* zero bytes */ + "\0\0\0\x05" /* min length, 5 characters */ + "\0\0\0\x0D" /* history, 13 passwords */ + "\0\0\0\x01" /* properties, complex */ + "\0\0\0\0\0\0\0\0" /* expire */ + "\0\0\0\xc9\x2a\x69\xc0\0" /* min age, 1 day */ +}; + +static void +check(krb5_error_code code) +{ + if (code != 0) { + com_err("t_vfy_increds", code, ""); + abort(); + } +} + +static void +check_msg(const char *real, const char *expected) +{ + if (strstr(real, expected) == NULL) { + fprintf(stderr, "Expected to see: %s\n", expected); + abort(); + } +} + +int +main(void) +{ + krb5_context context; + char *msg; + + setlocale(LC_ALL, "C"); + + check(krb5_init_context(&context)); + + /* Valid utf-8 data in the result should be returned as is */ + check(krb5_chpw_message(context, &result_utf8, &msg)); + printf(" UTF8 valid: %s\n", msg); + check_msg(msg, "This is a valid string."); + free(msg); + + /* Invalid data should have a generic message. */ + check(krb5_chpw_message(context, &result_invalid_utf8, &msg)); + printf(" UTF8 invalid: %s\n", msg); + check_msg(msg, "contact your administrator"); + free(msg); + + /* AD data with complex data requirement */ + check(krb5_chpw_message(context, &result_ad_complex, &msg)); + printf(" AD complex: %s\n", msg); + check_msg(msg, "The password must include numbers or symbols."); + check_msg(msg, "Don't include any part of your name in the password."); + free(msg); + + /* AD data with min password length */ + check(krb5_chpw_message(context, &result_ad_length, &msg)); + printf(" AD length: %s\n", msg); + check_msg(msg, "The password must contain at least 13 characters."); + free(msg); + + /* AD data with history requirements */ + check(krb5_chpw_message(context, &result_ad_history, &msg)); + printf(" AD history: %s\n", msg); + check_msg(msg, "The password must be different from the previous 9 " + "passwords."); + free(msg); + + /* AD data with minimum age */ + check(krb5_chpw_message(context, &result_ad_age, &msg)); + printf(" AD min age: %s\n", msg); + check_msg(msg, "The password can only be changed every 2 days."); + free(msg); + + /* AD data with all */ + check(krb5_chpw_message(context, &result_ad_all, &msg)); + printf(" AD all: %s\n", msg); + check_msg(msg, "The password can only be changed once a day."); + check_msg(msg, "The password must be different from the previous 13 " + "passwords."); + check_msg(msg, "The password must contain at least 5 characters."); + check_msg(msg, "The password must include numbers or symbols."); + check_msg(msg, "Don't include any part of your name in the password."); + free(msg); + + krb5_free_context(context); + exit(0); +} diff --git a/krb5-1.21.3/src/tests/misc/test_cxx_gss.cpp b/krb5-1.21.3/src/tests/misc/test_cxx_gss.cpp new file mode 100644 index 00000000..91622cd8 --- /dev/null +++ b/krb5-1.21.3/src/tests/misc/test_cxx_gss.cpp @@ -0,0 +1,10 @@ +// Test that the gssapi.h header is compatible with C++ application code. + +#include +#include "gssapi/gssapi.h" + +int main () +{ + printf("hello, world\n"); + return 0; +} diff --git a/krb5-1.21.3/src/tests/misc/test_cxx_k5int.cpp b/krb5-1.21.3/src/tests/misc/test_cxx_k5int.cpp new file mode 100644 index 00000000..bb6005f6 --- /dev/null +++ b/krb5-1.21.3/src/tests/misc/test_cxx_k5int.cpp @@ -0,0 +1,20 @@ +// Test that the krb5 internal headers are compatible with C++ code. +// (Some Windows-specific code is in C++ in this source tree.) + +#include +#include "k5-int.h" +#include "k5-ipc_stream.h" +#include "k5-utf8.h" + +int main (int argc, char *argv[]) +{ + krb5_context ctx; + + if (krb5_init_context(&ctx) != 0) { + printf("krb5_init_context returned an error\n"); + return 1; + } + printf("hello, world\n"); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/misc/test_cxx_kadm5.cpp b/krb5-1.21.3/src/tests/misc/test_cxx_kadm5.cpp new file mode 100644 index 00000000..59422ed1 --- /dev/null +++ b/krb5-1.21.3/src/tests/misc/test_cxx_kadm5.cpp @@ -0,0 +1,15 @@ +// Test that the kadm5 header is compatible with C++ application code. + +#include "kadm5/admin.h" + +krb5_context ctx; +kadm5_config_params p_in, p_out; +int main (int argc, char *argv[]) +{ + if (argc == 47 && kadm5_get_config_params(ctx, 1, &p_in, &p_out)) { + printf("error\n"); + return 1; + } + printf("hello, world\n"); + return 0; +} diff --git a/krb5-1.21.3/src/tests/misc/test_cxx_krb5.cpp b/krb5-1.21.3/src/tests/misc/test_cxx_krb5.cpp new file mode 100644 index 00000000..002120bf --- /dev/null +++ b/krb5-1.21.3/src/tests/misc/test_cxx_krb5.cpp @@ -0,0 +1,19 @@ +// Test that the krb5.h header is compatible with C++ application code. + +#include +#include "krb5.h" +#include "krb5/locate_plugin.h" +#include "profile.h" + +int main (int argc, char *argv[]) +{ + krb5_context ctx; + + if (krb5_init_context(&ctx) != 0) { + printf("krb5_init_context returned an error\n"); + return 1; + } + printf("hello, world\n"); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/misc/test_cxx_rpc.cpp b/krb5-1.21.3/src/tests/misc/test_cxx_rpc.cpp new file mode 100644 index 00000000..a7194878 --- /dev/null +++ b/krb5-1.21.3/src/tests/misc/test_cxx_rpc.cpp @@ -0,0 +1,14 @@ +// Test that the rpc.h header is compatible with C++ application code. + +#include "gssrpc/rpc.h" + +struct sockaddr_in s_in; +int main (int argc, char *argv[]) +{ + if (argc == 47 && get_myaddress (&s_in)) { + printf("error\n"); + return 1; + } + printf("hello, world\n"); + return 0; +} diff --git a/krb5-1.21.3/src/tests/misc/test_getpw.c b/krb5-1.21.3/src/tests/misc/test_getpw.c new file mode 100644 index 00000000..6031e150 --- /dev/null +++ b/krb5-1.21.3/src/tests/misc/test_getpw.c @@ -0,0 +1,51 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/misc/test_getpw.c */ +/* + * Copyright (C) 2005 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "autoconf.h" +#include "k5-platform.h" +#include +#include +#include +#include +#include + +int main() +{ + uid_t my_uid; + struct passwd *pwd, pwx; + char pwbuf[BUFSIZ]; + int x; + + my_uid = getuid(); + printf("my uid: %ld\n", (long) my_uid); + + x = k5_getpwuid_r(my_uid, &pwx, pwbuf, sizeof(pwbuf), &pwd); + printf("k5_getpwuid_r returns %d\n", x); + if (x != 0) + exit(1); + printf(" username is '%s'\n", pwd->pw_name); + exit(0); +} diff --git a/krb5-1.21.3/src/tests/misc/test_getsockname.c b/krb5-1.21.3/src/tests/misc/test_getsockname.c new file mode 100644 index 00000000..4fb875fa --- /dev/null +++ b/krb5-1.21.3/src/tests/misc/test_getsockname.c @@ -0,0 +1,117 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/misc/test_getsockname.c */ +/* + * Copyright (C) 1995 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * test_getsockname.c + * + * This routine demonstrates a bug in the socket emulation library of + * Solaris and other monstrosities that uses STREAMS. On other + * machines with a real networking layer, it prints the local + * interface address that is used to send a message to a specific + * host. On Solaris, it prints out 0.0.0.0. + */ + +#include "autoconf.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int sock; + GETSOCKNAME_ARG3_TYPE i; + struct hostent *host; + struct sockaddr_in s_sock; /* server address */ + struct sockaddr_in c_sock; /* client address */ + + char *hostname; + + if (argc == 2) { + hostname = argv[1]; + } else { + fprintf(stderr, "Usage: %s hostname\n", argv[0]); + exit(1); + } + + /* Look up server host */ + if ((host = gethostbyname(hostname)) == (struct hostent *) 0) { + fprintf(stderr, "%s: unknown host\n", hostname); + exit(1); + } + + /* Set server's address */ + (void) memset(&s_sock, 0, sizeof(s_sock)); + + memcpy(&s_sock.sin_addr, host->h_addr, sizeof(s_sock.sin_addr)); +#ifdef DEBUG + printf("s_sock.sin_addr is %s\n", inet_ntoa(s_sock.sin_addr)); +#endif + s_sock.sin_family = AF_INET; + s_sock.sin_port = htons(5555); + + /* Open a socket */ + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + exit(1); + } + + memset(&c_sock, 0, sizeof(c_sock)); + c_sock.sin_family = AF_INET; + + /* Bind it to set the address; kernel will fill in port # */ + if (bind(sock, (struct sockaddr *)&c_sock, sizeof(c_sock)) < 0) { + perror("bind"); + exit(1); + } + + /* "connect" the datagram socket; this is necessary to get a local address + properly bound for getsockname() below. */ + if (connect(sock, (struct sockaddr *)&s_sock, sizeof(s_sock)) == -1) { + perror("connect"); + exit(1); + } + + /* Get my address */ + memset(&c_sock, 0, sizeof(c_sock)); + i = sizeof(c_sock); + if (getsockname(sock, (struct sockaddr *)&c_sock, &i) < 0) { + perror("getsockname"); + exit(1); + } + + printf("My interface address is: %s\n", inet_ntoa(c_sock.sin_addr)); + + exit(0); +} diff --git a/krb5-1.21.3/src/tests/misc/test_nfold.c b/krb5-1.21.3/src/tests/misc/test_nfold.c new file mode 100644 index 00000000..e72502d6 --- /dev/null +++ b/krb5-1.21.3/src/tests/misc/test_nfold.c @@ -0,0 +1,66 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int inlen, outlen, i; + unsigned char *instr, *outstr; + + if (argc != 3) { + fprintf(stderr, "%s: instr outlen\n", argv[0]); + exit(1); + } + + instr = (unsigned char *) argv[1]; + inlen = strlen(instr)*8; + outlen = atoi(argv[2]); + if (outlen%8) { + fprintf(stderr, "outlen must be a multiple of 8\n"); + exit(1); + } + + if ((outstr = (unsigned char *) malloc(outlen/8)) == NULL) { + fprintf(stderr, "ENOMEM\n"); + exit(1); + } + + krb5int_nfold(inlen,instr,outlen,outstr); + + printf("%d-fold(",outlen); + for (i=0; i<(inlen/8); i++) + printf("%02x",instr[i]); + printf(") = "); + for (i=0; i<(outlen/8); i++) + printf("%02x",outstr[i]); + printf("\n"); + + exit(0); +} diff --git a/krb5-1.21.3/src/tests/pkinit-certs/ca.pem b/krb5-1.21.3/src/tests/pkinit-certs/ca.pem new file mode 100644 index 00000000..63d31c1f --- /dev/null +++ b/krb5-1.21.3/src/tests/pkinit-certs/ca.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE5TCCA82gAwIBAgIBATANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz +dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug +b3RoZXJ3aXNlMB4XDTIxMTAwODIxMTEzMFoXDTMyMDkyMDIxMTEzMFowgacxCzAJ +BgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRIwEAYDVQQHDAlDYW1i +cmlkZ2UxDDAKBgNVBAoMA01JVDEpMCcGA1UECwwgSW5zZWN1cmUgUEtJTklUIEtl +cmJlcm9zIHRlc3QgQ0ExMzAxBgNVBAMMKnBraW5pdCB0ZXN0IHN1aXRlIENBOyBk +byBub3QgdXNlIG90aGVyd2lzZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAM+lV5iaVats0yBFN4FBe6bovloNe3d0F9qMuhKqlECv6cFra75gSGmHJz6t +GTK8zITU7sni429azTZC9IQnUt/2lW8dWzpZD1T5Vt1DYvYFqVzjhNfzeEDK88ig +ENfzaX/cY2P76arJr0cewGaauzaux8heYW1CjBxWmk6kWq4aD+5jggchvBeOGEE2 +NkV3MPbXut8fu+3NzuuIG7Z0ilwQv+KUvQ8QQb9VCwdsDh/ERsQ4loC9P4jtuWCJ +ikIE78GxDcOMoC1ftJtW/mBCS2iCHipXrp2BDDJMyHxZjHpl0VoDR7koWGtD3sos +EwUkXVvWIuKs432h2dXQ+u8HaBsCAwEAAaOCARgwggEUMB0GA1UdDgQWBBT0F6X7 +1QRftDiSeNSY3bks3nK0IzCB1AYDVR0jBIHMMIHJgBT0F6X71QRftDiSeNSY3bks +3nK0I6GBraSBqjCBpzELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0 +dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoGA1UECgwDTUlUMSkwJwYDVQQLDCBJ +bnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVzdCBDQTEzMDEGA1UEAwwqcGtpbml0 +IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ugb3RoZXJ3aXNlggEBMAsGA1UdDwQE +AwIB/jAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBT2FJVPS+U +0MXa1HUOETuUPrVff7VeIvyAPm9IgX1zNbCvktCc4d7ErNB3P5ng8aZz4MKqwzuX +HVhUxbF7JKfyUI41lcixPG+k+U9mzBJaozWT+K1OhdUF//mGPxaxe5jyUhDiQArD +/6vulX0/B+1iuIa1sCfoeelzqQcYHqhZdWn6bBdcDWNARHIXWs5zPeKA975+d5TW +rofE7T8nNQJvcZoVjCSfcYXhP82D/0sA+wPCt3fgbBZdvJ89xwvIlzBtiwC++Zbe +37Rt5av0+ykpR7nmh2jyG+ItzE73nYKdBrUI5J6JLSbUcQTw4jeXHwDULUHZ6fXg +TBEM2v1VW4Df +-----END CERTIFICATE----- diff --git a/krb5-1.21.3/src/tests/pkinit-certs/generic.p12 b/krb5-1.21.3/src/tests/pkinit-certs/generic.p12 new file mode 100644 index 0000000000000000000000000000000000000000..35c27415bcb07c479990133882655bce3fe3bd72 GIT binary patch literal 2469 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 literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/src/tests/pkinit-certs/generic.pem b/krb5-1.21.3/src/tests/pkinit-certs/generic.pem new file mode 100644 index 00000000..55ebb3db --- /dev/null +++ b/krb5-1.21.3/src/tests/pkinit-certs/generic.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDazCCAlOgAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz +dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug +b3RoZXJ3aXNlMB4XDTIxMTAwODIxMTEzMVoXDTMyMDkyMDIxMTEzMVowSjELMAkG +A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF +U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAz6VXmJpVq2zTIEU3gUF7pui+Wg17d3QX2oy6EqqUQK/pwWtrvmBIaYcn +Pq0ZMrzMhNTuyeLjb1rNNkL0hCdS3/aVbx1bOlkPVPlW3UNi9gWpXOOE1/N4QMrz +yKAQ1/Npf9xjY/vpqsmvRx7AZpq7Nq7HyF5hbUKMHFaaTqRarhoP7mOCByG8F44Y +QTY2RXcw9te63x+77c3O64gbtnSKXBC/4pS9DxBBv1ULB2wOH8RGxDiWgL0/iO25 +YImKQgTvwbENw4ygLV+0m1b+YEJLaIIeKleunYEMMkzIfFmMemXRWgNHuShYa0Pe +yiwTBSRdW9Yi4qzjfaHZ1dD67wdoGwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCS +OTfZununxFDxuThhIFDWEZ9p2qSqTrxKtKx4CDvdckz4kaKybiNZTW7Dlh6IwWta +60eq98WrMHXYlSaN87r95lU0ug2RFJh4uLdq3a5NM/daIIjO0Bo86oC+8EBM961Q +mCMe7dn9ngFK92msdqO+wfpAfvhSpBPtAjQovigirheiEoER/ov9t9/3mRi5OTkY +8YfKT/z6XJrnOUIB3AgCdGyzSRvWLqLrbh7iAFVrm6Pq6D2nNr+mE9r5u7uFl3r8 +QeDgp0Unwd1ISWTHZlrP4bq29w7y2O+/2KV04Og8z+4zoGD4nRinuJBUdNqwAXVz +dz6pXFWgLRD+9ddI5jB0 +-----END CERTIFICATE----- diff --git a/krb5-1.21.3/src/tests/pkinit-certs/kdc.pem b/krb5-1.21.3/src/tests/pkinit-certs/kdc.pem new file mode 100644 index 00000000..e46afc17 --- /dev/null +++ b/krb5-1.21.3/src/tests/pkinit-certs/kdc.pem @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE4TCCA8mgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz +dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug +b3RoZXJ3aXNlMB4XDTIxMTAwODIxMTEzMFoXDTMyMDkyMDIxMTEzMFowSTELMAkG +A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF +U1QuQ09NMQwwCgYDVQQDDANLREMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQDPpVeYmlWrbNMgRTeBQXum6L5aDXt3dBfajLoSqpRAr+nBa2u+YEhphyc+ +rRkyvMyE1O7J4uNvWs02QvSEJ1Lf9pVvHVs6WQ9U+VbdQ2L2Balc44TX83hAyvPI +oBDX82l/3GNj++mqya9HHsBmmrs2rsfIXmFtQowcVppOpFquGg/uY4IHIbwXjhhB +NjZFdzD217rfH7vtzc7riBu2dIpcEL/ilL0PEEG/VQsHbA4fxEbEOJaAvT+I7blg +iYpCBO/BsQ3DjKAtX7SbVv5gQktogh4qV66dgQwyTMh8WYx6ZdFaA0e5KFhrQ97K +LBMFJF1b1iLirON9odnV0PrvB2gbAgMBAAGjggFzMIIBbzAdBgNVHQ4EFgQU9Bel ++9UEX7Q4knjUmN25LN5ytCMwgdQGA1UdIwSBzDCByYAU9Bel+9UEX7Q4knjUmN25 +LN5ytCOhga2kgaowgacxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNl +dHRzMRIwEAYDVQQHDAlDYW1icmlkZ2UxDDAKBgNVBAoMA01JVDEpMCcGA1UECwwg +SW5zZWN1cmUgUEtJTklUIEtlcmJlcm9zIHRlc3QgQ0ExMzAxBgNVBAMMKnBraW5p +dCB0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVyd2lzZYIBATALBgNVHQ8E +BAMCA+gwDAYDVR0TAQH/BAIwADBIBgNVHREEQTA/oD0GBisGAQUCAqAzMDGgDRsL +S1JCVEVTVC5DT02hIDAeoAMCAQKhFzAVGwZrcmJ0Z3QbC0tSQlRFU1QuQ09NMBIG +A1UdJQQLMAkGBysGAQUCAwUwDQYJKoZIhvcNAQELBQADggEBAJZd7v5ZOMs8Y3ht +Kmtql8rKs0Jee73gVHYw3LXxJfHjIiNGdexxuWJ6Hy9gFnfwSco+15HP3MxMBkau +TKo3i1+Kwf+lc7gIZ0g/CEnYOx2smHGd9yGudWypunYLjGWfH/2M8/Wu1gZDTxQ1 +pNMQZ2pPLL/C6c6vYpVQJ5cA0RSh/SC5IbOESUpZaFFMYxF5TNz+28/lDr/rN41O +miklos6cH5EkJyI0WUqJMk04HHjREl/9RTak8mo/eaqjUMTAOyweSwpaYRCddBOo +y1ix9yH0fSBib1+WQ3MAHZHgbgVnu7V2GnB6qMNqRLHoGa03x+5Q1X0QuKxP6iYo +9tiGt3k= +-----END CERTIFICATE----- diff --git a/krb5-1.21.3/src/tests/pkinit-certs/make-certs.sh b/krb5-1.21.3/src/tests/pkinit-certs/make-certs.sh new file mode 100755 index 00000000..5284f425 --- /dev/null +++ b/krb5-1.21.3/src/tests/pkinit-certs/make-certs.sh @@ -0,0 +1,172 @@ +#!/bin/sh -e + +NAMETYPE=1 +KRBTGT_NAMETYPE=2 +KEYSIZE=2048 +DAYS=4000 +REALM=KRBTEST.COM +LOWREALM=krbtest.com +KRB5_PRINCIPAL_SAN=1.3.6.1.5.2.2 +KRB5_UPN_SAN=1.3.6.1.4.1.311.20.2.3 +PKINIT_KDC_EKU=1.3.6.1.5.2.3.5 +PKINIT_CLIENT_EKU=1.3.6.1.5.2.3.4 +TLS_SERVER_EKU=1.3.6.1.5.5.7.3.1 +TLS_CLIENT_EKU=1.3.6.1.5.5.7.3.2 +EMAIL_PROTECTION_EKU=1.3.6.1.5.5.7.3.4 +# Add TLS EKUs to these if we're testing with NSS and we still have to +# piggy-back on the TLS trust settings. +KDC_EKU_LIST=$PKINIT_KDC_EKU +CLIENT_EKU_LIST=$PKINIT_CLIENT_EKU + +cat > openssl.cnf << EOF +[req] +prompt = no +distinguished_name = \$ENV::SUBJECT + +[ca] +CN = test CA certificate +C = US +ST = Massachusetts +L = Cambridge +O = MIT +OU = Insecure PKINIT Kerberos test CA +CN = pkinit test suite CA; do not use otherwise + +[kdc] +C = US +ST = Massachusetts +O = KRBTEST.COM +CN = KDC + +[user] +C = US +ST = Massachusetts +O = KRBTEST.COM +CN = user + +[exts_ca] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation,digitalSignature,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign +basicConstraints = critical,CA:TRUE + +[components_kdc] +0.component=GeneralString:krbtgt +1.component=GeneralString:$REALM + +[princ_kdc] +nametype=EXPLICIT:0,INTEGER:$KRBTGT_NAMETYPE +components=EXPLICIT:1,SEQUENCE:components_kdc + +[krb5princ_kdc] +realm=EXPLICIT:0,GeneralString:$REALM +princ=EXPLICIT:1,SEQUENCE:princ_kdc + +[exts_kdc] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement +basicConstraints = critical,CA:FALSE +subjectAltName = otherName:$KRB5_PRINCIPAL_SAN;SEQUENCE:krb5princ_kdc +extendedKeyUsage = $KDC_EKU_LIST + +[components_client] +component=GeneralString:user + +[princ_client] +nametype=EXPLICIT:0,INTEGER:$NAMETYPE +components=EXPLICIT:1,SEQUENCE:components_client + +[krb5princ_client] +realm=EXPLICIT:0,GeneralString:$REALM +princ=EXPLICIT:1,SEQUENCE:princ_client + +[exts_client] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement +basicConstraints = critical,CA:FALSE +subjectAltName = otherName:$KRB5_PRINCIPAL_SAN;SEQUENCE:krb5princ_client +extendedKeyUsage = $CLIENT_EKU_LIST + +[exts_upn_client] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement +basicConstraints = critical,CA:FALSE +subjectAltName = otherName:$KRB5_UPN_SAN;UTF8:user@$LOWREALM +extendedKeyUsage = $CLIENT_EKU_LIST + +[exts_upn2_client] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement +basicConstraints = critical,CA:FALSE +subjectAltName = otherName:$KRB5_UPN_SAN;UTF8:user +extendedKeyUsage = $CLIENT_EKU_LIST + +[exts_upn3_client] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement +basicConstraints = critical,CA:FALSE +subjectAltName = otherName:$KRB5_UPN_SAN;UTF8:user@$REALM +extendedKeyUsage = $CLIENT_EKU_LIST + +[exts_none] +EOF + +# Generate a private key. +openssl genrsa $KEYSIZE > privkey.pem +openssl rsa -in privkey.pem -out privkey-enc.pem -des3 -passout pass:encrypted + +# Generate a "CA" certificate. +SUBJECT=ca openssl req -config openssl.cnf -new -x509 -extensions exts_ca \ + -set_serial 1 -days $DAYS -key privkey.pem -out ca.pem + +serial=2 +gen_cert() { + SUBJECT=$1 openssl req -config openssl.cnf -new -key privkey.pem -out csr + SUBJECT=$1 openssl x509 -extfile openssl.cnf -extensions $2 \ + -set_serial $serial -days $DAYS -req -CA ca.pem -CAkey privkey.pem \ + -in csr -out $3 + serial=$((serial + 1)) + rm -f csr +} + +gen_pkcs12() { + # Use -descert to make OpenSSL 1.1 generate files OpenSSL 3.0 can + # read (the default uses RC2, which is only available in the + # legacy provider in OpenSSL 3). This option causes an algorithm + # downgrade with OpenSSL 3.0 (AES to DES3), but that isn't + # important for test certs. + openssl pkcs12 -export -descert -in "$1" -inkey privkey.pem -out "$2" \ + -passout pass:"$3" +} + +# Generate a KDC certificate. +gen_cert kdc exts_kdc kdc.pem + +# Generate a client certificate and PKCS#12 bundles. +gen_cert user exts_client user.pem +gen_pkcs12 user.pem user.p12 +gen_pkcs12 user.pem user-enc.p12 encrypted + +# Generate a client certificate and PKCS#12 bundle with a UPN SAN. +gen_cert user exts_upn_client user-upn.pem +gen_pkcs12 user-upn.pem user-upn.p12 + +# Same, but with no realm in the UPN SAN. +gen_cert user exts_upn2_client user-upn2.pem +gen_pkcs12 user-upn2.pem user-upn2.p12 + +# Same, but with an uppercase realm in the UPN SAN. +gen_cert user exts_upn3_client user-upn3.pem +gen_pkcs12 user-upn3.pem user-upn3.p12 + +# Generate a client certificate and PKCS#12 bundle with no PKINIT extensions. +gen_cert user exts_none generic.pem +gen_pkcs12 generic.pem generic.p12 + +# Clean up. +rm -f openssl.cnf diff --git a/krb5-1.21.3/src/tests/pkinit-certs/privkey-enc.pem b/krb5-1.21.3/src/tests/pkinit-certs/privkey-enc.pem new file mode 100644 index 00000000..29d2f3d3 --- /dev/null +++ b/krb5-1.21.3/src/tests/pkinit-certs/privkey-enc.pem @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,5FFF1E71BFFB65E3 + +p89x5YEL+Mb6IPZXEkkr0KC4Wj+JtgE3VKdTT0wEcRD74QVv+dbbZt62WgmpJtId +ph0Ial2z5Mws8L/aTkPdW2H/bEroApLu4TfUV+w67KcWgrc8gOg73d6gEObqx8li +qGbs7FC1cI1WfDfnNOnCbD66e5+bTI8fDuchaieNRqzROd9RHhmlBHgylTmf55us +laGuwLq2cZk/+Xz0M8PPx07uauGkAK0fyfifn/JR3PsGsE9s334osVQMjbjyT0VE +rm8HGm3PvZHHDUnkOh7AGKyEtsIa5fJAULUjugp2lQJqOigC4HVn8a33xfLI0F1+ +2nH9MZ+Ap1rtI1cJX8CDn/Ij9oFt01scLxynYekYej11zFiR6qHC0sspxu0Yi8l0 +puBPXCI0GzyF9I53ukjGeibTtssz5yw1r+2oVasR4bvfXczPjqTQCBsPSUayNNhw +RgT7k4QTY2OlrK/5XdILBzBlsvfndXgGOwEDw4YE7PMzMmz69vPMK7CfedUqtuXq +bGBks58tzeOa4NSfVDOuFLI+LMkoYWMSjPGD/I0trX41xCU+O6PZOnDyt5ZWl1Tm +klJpsB7rUcwsP8d4w4QGhyyV6Mo2MTlnTILr4CwwvmDMBch3yzwbfKdeywsFQh0S +NMrG3aYNO7csRRTD6aGvYcBCbavWq7Ujsb/fV7SOIS26f4VEqewvOFlFEXm66zaz +GJ0IcjtNHYNIIIW4690djxPqlGgbIZTblBSBlT+iOW5HrhXvrLeMmwAPxInU5dK+ +ypk2MGc4SzemkDi8H9jDW3dwbgcvVD9wn0glhVLQKWvP6F73UUdVEXMCZ+960xnR +gxeEwDdIpzXNadWdON1kRbqI2KesRY/XQErGHDOvf2gNSM9V2gPz+5humvcu3mXY +r4537On4+IdzetEVtI7D0slgojs+jN8waigpkLFB5RVl8PnzblMuWOkHNA86rrp+ +h6wNqv9kHLgPjpAyB1l/7w4VqXLXeC4PdaGc2fcpdNWOncUnHROmDmYvdTocqhIF +bAsEFV7QZoTgDB7J6vLsmbtfawtHMSb81V/wTJWRrtY/gJCrkJXR2pTYAZlPX6vK +aK7K2NuhJFMnrQD+kxsrloSEyfsZmHtk0mAVXJw4wSxlH3eGQ+Jphb/M2wtsnWV1 +w0fehxL2Vd5SyBBctAGhUirhRngbOO/E8IioymrziQ88vJZs2DxvbuNG4WKTuTwj +CIggXohCNKdqrwL2HAynm2FVEWhbKrQwe4kjZc64WjccR4cy9vv+dxFfrKl+vZ1o +Wvb0WXND7fiSBrPo7OfaYM5HjrcvIRP1AtMuArhuQYVARmawUG0l7dFLN97Rh9M+ +Ud9vBIfQYlubnTGVVm/5xrUh2isQbp2vrZLfMrUNXMQm0vSxKgGkAxqNUuklJC06 +LvCtEWMYXiBmB1zP4khwCHmHB+/E1gHBAutCzhpPu86ayEtNHBHIFkqKvZSg/UuZ ++ygDdTJV00I2neIdeQcyG+vPg6huIDIHpG5u6eQn5sLqVkhr+apeNcskMWpdkpFS +Lo62KUZDR3yB83ne63c3IGex0hWhVojJOAxykpGp6OD9uFn6Xn7x2Q== +-----END RSA PRIVATE KEY----- diff --git a/krb5-1.21.3/src/tests/pkinit-certs/privkey.pem b/krb5-1.21.3/src/tests/pkinit-certs/privkey.pem new file mode 100644 index 00000000..007b6275 --- /dev/null +++ b/krb5-1.21.3/src/tests/pkinit-certs/privkey.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEoAIBAAKCAQEAz6VXmJpVq2zTIEU3gUF7pui+Wg17d3QX2oy6EqqUQK/pwWtr +vmBIaYcnPq0ZMrzMhNTuyeLjb1rNNkL0hCdS3/aVbx1bOlkPVPlW3UNi9gWpXOOE +1/N4QMrzyKAQ1/Npf9xjY/vpqsmvRx7AZpq7Nq7HyF5hbUKMHFaaTqRarhoP7mOC +ByG8F44YQTY2RXcw9te63x+77c3O64gbtnSKXBC/4pS9DxBBv1ULB2wOH8RGxDiW +gL0/iO25YImKQgTvwbENw4ygLV+0m1b+YEJLaIIeKleunYEMMkzIfFmMemXRWgNH +uShYa0PeyiwTBSRdW9Yi4qzjfaHZ1dD67wdoGwIDAQABAoIBAEpnKYMR0h6xyNjo +VGIpT6BYB1UHPbVo0N9Ly6TCoIqpPe5DioDVyTye5A4OQlgu1G3ISqPme6478ApA +ZZMw7/42QgdlknnOzbKaAWkZK02Sa8RP9hrXL8CvuDisOjzXCHd7RdXevzSmPfsS +5sgdK3YFnKqMPwbCcKf61CHXvHJjWGuTIHIRh8P7gJelA4ahO0kYQ8aRXv3ldquO +ukSI5gyk9CN+aAHqt25kEmt9oOgk+8kfKpnk+5gkOCY2YOFDDckD7nL1VIIrDxwG +SmU598qjVwycDairWUY8uSuPCOLgbvDM9N8cERDMsyNQL63GE8ZZyHZsJ3Pbwdfs +JVHh5ekCgYEA/CwhaT9D0WQ49GQdeI7aqazHEYDmqPdE2/qbmr67tPMZzX8AAk9j +r4aMT+oIdtIMPdoQNNcBP6NYZLlAoMbLoAzHmWJnF5/YWLnS2Wg9OuXUOBn3jk1l +SWelJfAKGeBld5fpSLTdHjRAwJrNCX+mc0IZIiEw2IvGUPgKGX08bX8CgYEA0swx +xCDgvfoaKueInw/rUIcKxrSxK3pDhaR01Dg2pwSo7Vj9W01zf33qe+mjma6+U2SB +fk+/O2VXDuEOmVDLwvp6PkmUeRE5PyH7urTMEjy5ELNGiZd9zHoG/zJnRgPwTjuW +yguvjVGJwI1IvmODuA7Xc7iHFlvGNuxXZjPkS2UCgYA0nFxoIdvbTsaXLl/7rAow +xixOGY+GBvil0HYwZcSxrtpeRjXRRZDtqOuTLKeRaqdFLD6fV5AaH9EsSn4STQdk +n+XwuVf61M2FTVeRJi9IH3UUM06zsLAGDYqmDJt+5JMmzVnNYnaTe6FazbEjXy9x +8oNd3IDdXOQGNomc4cT+rwKBgBbABOr25Wp7cJGK1XrdO/c/69DQNYLMujbVLeqt +enCCFz0uaoGNFVcAHutqpsZyToYvha49KxVc9Y1cirfPOX58i+7nAAgk7Lm8kC9x +Tcj2Fr8PqiA1YlVMIi8uoGi1Ch1XXwnFQxgMYcKPPPeXQ+L8bxJFKwcltnm8/h3A +ofXlAn9AW6fYZLSzOfNQTMnuukhuAtZcEW9NlJHbej305zK89J66S8wroQs5iOla +5GG+S4YaZh5sVGw+mnS+FCw7cQCUk40kXwX3yTrxlX1qGSCFCQnFdJow+5NVg4D+ +dzDKzniH71OZZFxTqiiz76XxiaW/rS1uOfP/WSVR9NBLpV5n +-----END RSA PRIVATE KEY----- diff --git a/krb5-1.21.3/src/tests/pkinit-certs/user-enc.p12 b/krb5-1.21.3/src/tests/pkinit-certs/user-enc.p12 new file mode 100644 index 0000000000000000000000000000000000000000..1cc3aa3da67160fd9298b9e2d624a80c5225245b GIT binary patch literal 2829 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 literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/src/tests/pkinit-certs/user-upn.pem b/krb5-1.21.3/src/tests/pkinit-certs/user-upn.pem new file mode 100644 index 00000000..14a11831 --- /dev/null +++ b/krb5-1.21.3/src/tests/pkinit-certs/user-upn.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz +dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug +b3RoZXJ3aXNlMB4XDTIxMTAwODIxMTEzMVoXDTMyMDkyMDIxMTEzMVowSjELMAkG +A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF +U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAz6VXmJpVq2zTIEU3gUF7pui+Wg17d3QX2oy6EqqUQK/pwWtrvmBIaYcn +Pq0ZMrzMhNTuyeLjb1rNNkL0hCdS3/aVbx1bOlkPVPlW3UNi9gWpXOOE1/N4QMrz +yKAQ1/Npf9xjY/vpqsmvRx7AZpq7Nq7HyF5hbUKMHFaaTqRarhoP7mOCByG8F44Y +QTY2RXcw9te63x+77c3O64gbtnSKXBC/4pS9DxBBv1ULB2wOH8RGxDiWgL0/iO25 +YImKQgTvwbENw4ygLV+0m1b+YEJLaIIeKleunYEMMkzIfFmMemXRWgNHuShYa0Pe +yiwTBSRdW9Yi4qzjfaHZ1dD67wdoGwIDAQABo4IBVjCCAVIwHQYDVR0OBBYEFPQX +pfvVBF+0OJJ41JjduSzecrQjMIHUBgNVHSMEgcwwgcmAFPQXpfvVBF+0OJJ41Jjd +uSzecrQjoYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz +ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM +IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu +aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P +BAQDAgPoMAwGA1UdEwEB/wQCMAAwKwYDVR0RBCQwIqAgBgorBgEEAYI3FAIDoBIM +EHVzZXJAa3JidGVzdC5jb20wEgYDVR0lBAswCQYHKwYBBQIDBDANBgkqhkiG9w0B +AQsFAAOCAQEAYTW8tzURX2s8vuDawXEJt2as5q2MnvhUmG0YPIvK4n2fODkMW/I9 +XENFhK8wwQJNdzvBUwXUXzEGjFcGPs672ZVzykRb7sAfGlNu1f15z0KrjyUj82oz +/gWoLwdYwZnO8jqtKjGtnLi2MeWjVCoiUW5ypUGwtEdcyZUG0PeRUrdrZu5cm+iZ +1B1exR4lepR1iSAPYTNhp5VF6T8BSLf2BO2IKTgFnF4Xx1vyZZTsY10mruZ8S1ZR +XiajBVdHkN1BpWWyFKt1BCt0dpRx9W7CihC3Ln9fBCsY8QA969EjRhszG2i09Xxw +0M6/UgIQRU6hy7QTlcmehDKY0zvVJ2/RLw== +-----END CERTIFICATE----- diff --git a/krb5-1.21.3/src/tests/pkinit-certs/user-upn2.p12 b/krb5-1.21.3/src/tests/pkinit-certs/user-upn2.p12 new file mode 100644 index 0000000000000000000000000000000000000000..69ca648aab9f1c5ffe34387459d45eb45bb04922 GIT binary patch literal 2805 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 QeR)c_?5HwV^xr!E3zY&wM*si- literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/src/tests/pkinit-certs/user-upn3.pem b/krb5-1.21.3/src/tests/pkinit-certs/user-upn3.pem new file mode 100644 index 00000000..000d567d --- /dev/null +++ b/krb5-1.21.3/src/tests/pkinit-certs/user-upn3.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBBjANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz +dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug +b3RoZXJ3aXNlMB4XDTIxMTAwODIxMTEzMVoXDTMyMDkyMDIxMTEzMVowSjELMAkG +A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF +U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAz6VXmJpVq2zTIEU3gUF7pui+Wg17d3QX2oy6EqqUQK/pwWtrvmBIaYcn +Pq0ZMrzMhNTuyeLjb1rNNkL0hCdS3/aVbx1bOlkPVPlW3UNi9gWpXOOE1/N4QMrz +yKAQ1/Npf9xjY/vpqsmvRx7AZpq7Nq7HyF5hbUKMHFaaTqRarhoP7mOCByG8F44Y +QTY2RXcw9te63x+77c3O64gbtnSKXBC/4pS9DxBBv1ULB2wOH8RGxDiWgL0/iO25 +YImKQgTvwbENw4ygLV+0m1b+YEJLaIIeKleunYEMMkzIfFmMemXRWgNHuShYa0Pe +yiwTBSRdW9Yi4qzjfaHZ1dD67wdoGwIDAQABo4IBVjCCAVIwHQYDVR0OBBYEFPQX +pfvVBF+0OJJ41JjduSzecrQjMIHUBgNVHSMEgcwwgcmAFPQXpfvVBF+0OJJ41Jjd +uSzecrQjoYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz +ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM +IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu +aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P +BAQDAgPoMAwGA1UdEwEB/wQCMAAwKwYDVR0RBCQwIqAgBgorBgEEAYI3FAIDoBIM +EHVzZXJAS1JCVEVTVC5DT00wEgYDVR0lBAswCQYHKwYBBQIDBDANBgkqhkiG9w0B +AQsFAAOCAQEApwXjFJ86RLM4MzbScqk0JGqm+jzaFZ6h5oyt0rlaxdhOl7kqOmIE +sLhXtvZm75roA+UULZHumB6xg3Y0p7cc6VBAYYycWoNkhWXZMdQ8Q33vMos5cwLY +kXjl4oTDK53goh8IlriRMV7Tv/QpJ8wh+7iqQn3lak0Tv51JexYGwp5sJREYm8q5 +rr3ChlgH7SWF8mhbu2EEiipm0whEqA4tlNKGBsTQBslnm8sK0VfVDcmLOGbMNjRs +r+Hkd8yVvhIJ9M+WAp/OeF2vUzPBJtAfIaJBxcZmKtNI5Jk8cK/vScJZboa0qAAz +2Y1uC9rP830mpOe0juhV2mMPron0hi1HaA== +-----END CERTIFICATE----- diff --git a/krb5-1.21.3/src/tests/pkinit-certs/user.p12 b/krb5-1.21.3/src/tests/pkinit-certs/user.p12 new file mode 100644 index 0000000000000000000000000000000000000000..e5520110248530c55338c80fd44414eaa262c4a8 GIT binary patch literal 2829 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 literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/src/tests/pkinit-certs/user.pem b/krb5-1.21.3/src/tests/pkinit-certs/user.pem new file mode 100644 index 00000000..182ea599 --- /dev/null +++ b/krb5-1.21.3/src/tests/pkinit-certs/user.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBpzELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSkwJwYDVQQLDCBJbnNlY3VyZSBQS0lOSVQgS2VyYmVyb3MgdGVz +dCBDQTEzMDEGA1UEAwwqcGtpbml0IHRlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ug +b3RoZXJ3aXNlMB4XDTIxMTAwODIxMTEzMFoXDTMyMDkyMDIxMTEzMFowSjELMAkG +A1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxFDASBgNVBAoMC0tSQlRF +U1QuQ09NMQ0wCwYDVQQDDAR1c2VyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAz6VXmJpVq2zTIEU3gUF7pui+Wg17d3QX2oy6EqqUQK/pwWtrvmBIaYcn +Pq0ZMrzMhNTuyeLjb1rNNkL0hCdS3/aVbx1bOlkPVPlW3UNi9gWpXOOE1/N4QMrz +yKAQ1/Npf9xjY/vpqsmvRx7AZpq7Nq7HyF5hbUKMHFaaTqRarhoP7mOCByG8F44Y +QTY2RXcw9te63x+77c3O64gbtnSKXBC/4pS9DxBBv1ULB2wOH8RGxDiWgL0/iO25 +YImKQgTvwbENw4ygLV+0m1b+YEJLaIIeKleunYEMMkzIfFmMemXRWgNHuShYa0Pe +yiwTBSRdW9Yi4qzjfaHZ1dD67wdoGwIDAQABo4IBZDCCAWAwHQYDVR0OBBYEFPQX +pfvVBF+0OJJ41JjduSzecrQjMIHUBgNVHSMEgcwwgcmAFPQXpfvVBF+0OJJ41Jjd +uSzecrQjoYGtpIGqMIGnMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVz +ZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxKTAnBgNVBAsM +IEluc2VjdXJlIFBLSU5JVCBLZXJiZXJvcyB0ZXN0IENBMTMwMQYDVQQDDCpwa2lu +aXQgdGVzdCBzdWl0ZSBDQTsgZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0P +BAQDAgPoMAwGA1UdEwEB/wQCMAAwOQYDVR0RBDIwMKAuBgYrBgEFAgKgJDAioA0b +C0tSQlRFU1QuQ09NoREwD6ADAgEBoQgwBhsEdXNlcjASBgNVHSUECzAJBgcrBgEF +AgMEMA0GCSqGSIb3DQEBCwUAA4IBAQAOBeCDK6Eg6Cu8TZ7xeAw2AbTpaW04nNSV +Fmm0aIskMgLl2a5KEmalG7rnArRXv5IZVYFjJ6X0MzjOx+BgaGUCvN8jz1fuO3Hp +iGhxPDzKjFMWJeY/z5bQRueSI6RCC8DzH8iPdlPUQ8ZhnukhY1Vt47wqraf197uT +0XP21qQr1uRY+ZcLSBKZuKe9ZP3ijh57MOLvYDdAFxVp77JLznpk+oU18ujAtYgZ +7naIGYtSQRkIi970jk82hSpc9B/KN8UcDuo+DQHWPQaDf39s30qoxooZBoue5ipp +LQHuVaX5Hoi83cWbsVluce/JsW8GfbuC8+8CosAmzJly183f8++9 +-----END CERTIFICATE----- diff --git a/krb5-1.21.3/src/tests/plugorder.c b/krb5-1.21.3/src/tests/plugorder.c new file mode 100644 index 00000000..e1245e47 --- /dev/null +++ b/krb5-1.21.3/src/tests/plugorder.c @@ -0,0 +1,96 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/plugorder.c - Test harness to display the order of loaded plugins */ +/* + * 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. + */ + +/* + * This file registers a few dummy built-in pwqual modules, then prints out the + * order of pwqual modules returned by k5_plugin_load_all. The choice of the + * pwqual interface is mostly arbitrary; it is an interface which libkrb5 + * itself doesn't use, for which we have a test module. + */ + +#include "k5-int.h" +#include + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +static krb5_error_code +blt1(krb5_context context, int maj_ver, int min_ver, krb5_plugin_vtable vtable) +{ + ((krb5_pwqual_vtable)vtable)->name = "blt1"; + return 0; +} + +static krb5_error_code +blt2(krb5_context context, int maj_ver, int min_ver, krb5_plugin_vtable vtable) +{ + ((krb5_pwqual_vtable)vtable)->name = "blt2"; + return 0; +} + +static krb5_error_code +blt3(krb5_context context, int maj_ver, int min_ver, krb5_plugin_vtable vtable) +{ + ((krb5_pwqual_vtable)vtable)->name = "blt3"; + return 0; +} + +int +main() +{ + krb5_plugin_initvt_fn *modules = NULL, *mod; + struct krb5_pwqual_vtable_st vt; + + check(krb5_init_context(&ctx)); + check(k5_plugin_register(ctx, PLUGIN_INTERFACE_PWQUAL, "blt1", blt1)); + check(k5_plugin_register(ctx, PLUGIN_INTERFACE_PWQUAL, "blt2", blt2)); + check(k5_plugin_register(ctx, PLUGIN_INTERFACE_PWQUAL, "blt3", blt3)); + check(k5_plugin_load_all(ctx, PLUGIN_INTERFACE_PWQUAL, &modules)); + for (mod = modules; *mod != NULL; mod++) { + check((*mod)(ctx, 1, 1, (krb5_plugin_vtable)&vt)); + printf("%s\n", vt.name); + } + k5_plugin_free_modules(ctx, modules); + return 0; +} diff --git a/krb5-1.21.3/src/tests/proxy-certs/ca.pem b/krb5-1.21.3/src/tests/proxy-certs/ca.pem new file mode 100644 index 00000000..ee24cba8 --- /dev/null +++ b/krb5-1.21.3/src/tests/proxy-certs/ca.pem @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE----- +MIIEuzCCA6OgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSIwIAYDVQQLDBlJbnNlY3VyZSBLZXJiZXJvcyB0ZXN0IENBMSww +KgYDVQQDDCN0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVyd2lzZTAeFw0x +OTExMTIxODMwMzRaFw0zMDEwMjUxODMwMzRaMIGZMQswCQYDVQQGEwJVUzEWMBQG +A1UECAwNTWFzc2FjaHVzZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQK +DANNSVQxIjAgBgNVBAsMGUluc2VjdXJlIEtlcmJlcm9zIHRlc3QgQ0ExLDAqBgNV +BAMMI3Rlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ugb3RoZXJ3aXNlMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA54HCeTTUe127pqjK8r28NGMw2r2x+hWK +KayH5NmqOqnwnzRHkZE5UjkazQ/h97S6LZ6Yb8w3mJEyX1PdcNARDw2mbOPFk5N9 +uXnBb6AZog7hh9wMe//g9a7PpKanfw69fSVgAr49TFFiLoKuyTgHiJOB7YgP0bTH +EO4lLqusPQM16lRDSdoXg42udAh3uBY+QDs23snLSiB+9vt8gt6gXiaYb3BBOWs9 +B3PKs374N9kOPsgcj+8kyR/M+q+RfK5biqS3ce/sxvPV0Kseh//1uJxlbQCwOiBd +3TLWHLhW9F7rzEcvzn1Mfck35s0XDDRlGxRGGDy+ZCKmxf8Zu/8SwwIDAQABo4IB +CjCCAQYwHQYDVR0OBBYEFPf/vJvFMCwrABeCC0sq7RGfYeIiMIHGBgNVHSMEgb4w +gbuAFPf/vJvFMCwrABeCC0sq7RGfYeIioYGfpIGcMIGZMQswCQYDVQQGEwJVUzEW +MBQGA1UECAwNTWFzc2FjaHVzZXR0czESMBAGA1UEBwwJQ2FtYnJpZGdlMQwwCgYD +VQQKDANNSVQxIjAgBgNVBAsMGUluc2VjdXJlIEtlcmJlcm9zIHRlc3QgQ0ExLDAq +BgNVBAMMI3Rlc3Qgc3VpdGUgQ0E7IGRvIG5vdCB1c2Ugb3RoZXJ3aXNlggEBMAsG +A1UdDwQEAwIB/jAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBz +q/t9amz4ahTFNc0v69NZrfCBgo7DWBHxXuE0Gov2/RBPwP/+Efrd4+1Tl5fSv6We +N/cttEUTTM3Z7wtof3mkSQwkozwWpaHXm31St+0FbTuHNpN4i0Uae5lsO8/pTz/L +VqsVLjGGpkZKP831BO9oJJbwUASNc2dpLs94pojlSlSZzf/u/T+k0wltgZexnQpU +5IrdPIqteB32ym2XjZWSCS29jL3zoZ/y8UAPIOR/Zi77wNCehOuBx2bzc/P6RNLa +CuuPMhDu8PPYVB3rfJInmF5wT5jQ9YX4UUb0qYXDRff5/l26fEjLHQSrA/iMqdIW +dsDwkqTcy1lOjcP3xOMq +-----END CERTIFICATE----- diff --git a/krb5-1.21.3/src/tests/proxy-certs/make-certs.sh b/krb5-1.21.3/src/tests/proxy-certs/make-certs.sh new file mode 100755 index 00000000..7a40e2b9 --- /dev/null +++ b/krb5-1.21.3/src/tests/proxy-certs/make-certs.sh @@ -0,0 +1,124 @@ +#!/bin/sh -e + +PWD=`pwd` +NAMETYPE=1 +KEYSIZE=2048 +DAYS=4000 +REALM=KRBTEST.COM +TLS_SERVER_EKU=1.3.6.1.5.5.7.3.1 +PROXY_EKU_LIST=$TLS_SERVER_EKU + +cat > openssl.cnf << EOF +[req] +prompt = no +distinguished_name = \$ENV::SUBJECT + +[ca] +default_ca = test_ca + +[test_ca] +new_certs_dir = $PWD +serial = $PWD/ca.srl +database = $PWD/ca.db +certificate = $PWD/ca.pem +private_key = $PWD/privkey.pem +default_days = $DAYS +x509_extensions = exts_proxy +policy = proxyname +default_md = sha256 +unique_subject = no +email_in_dn = no + +[signer] +CN = test CA certificate +C = US +ST = Massachusetts +L = Cambridge +O = MIT +OU = Insecure Kerberos test CA +CN = test suite CA; do not use otherwise + +[proxy] +C = US +ST = Massachusetts +O = KRBTEST.COM +CN = PROXYinSubject + +[localhost] +C = US +ST = Massachusetts +O = KRBTEST.COM +CN = localhost + +[proxyname] +C = supplied +ST = supplied +O = supplied +CN = supplied + +[exts_ca] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation,digitalSignature,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign +basicConstraints = critical,CA:TRUE + +[exts_proxy] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement +basicConstraints = critical,CA:FALSE +subjectAltName = DNS:proxyŠubjectÄltÑame,DNS:proxySubjectAltName,IP:127.0.0.1,IP:::1,DNS:localhost +extendedKeyUsage = $PROXY_EKU_LIST + +[exts_proxy_no_san] +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +keyUsage = nonRepudiation,digitalSignature,keyEncipherment,keyAgreement +basicConstraints = critical,CA:FALSE +extendedKeyUsage = $PROXY_EKU_LIST +EOF + +# Generate a private key. +openssl genrsa $KEYSIZE > privkey.pem + +# Generate a "CA" certificate. +SUBJECT=signer openssl req -config openssl.cnf -new -x509 -extensions exts_ca \ + -set_serial 1 -days $DAYS -key privkey.pem -out ca.pem + +# Generate proxy certificate signing requests. +SUBJECT=proxy openssl req -config openssl.cnf -new -key privkey.pem \ + -out proxy.csr +SUBJECT=localhost openssl req -config openssl.cnf -new -key privkey.pem \ + -out localhost.csr + +# Issue the certificate with the right name in a subjectAltName. +echo 02 > ca.srl +cat /dev/null > ca.db +SUBJECT=proxy openssl ca -config openssl.cnf -extensions exts_proxy \ + -batch -days $DAYS -notext -out tmp.pem -in proxy.csr +cat privkey.pem tmp.pem > proxy-san.pem + +# Issue a certificate that only has the name in the subject field +SUBJECT=proxy openssl ca -config openssl.cnf -extensions exts_proxy_no_san \ + -batch -days $DAYS -notext -out tmp.pem -in localhost.csr +cat privkey.pem tmp.pem > proxy-subject.pem + +# Issue a certificate that doesn't include any matching name values. +SUBJECT=proxy openssl ca -config openssl.cnf -extensions exts_proxy_no_san \ + -batch -days $DAYS -notext -out tmp.pem -in proxy.csr +cat privkey.pem tmp.pem > proxy-no-match.pem + +# Issue a certificate that contains all matching name values. +SUBJECT=proxy openssl ca -config openssl.cnf -extensions exts_proxy \ + -batch -days $DAYS -notext -out tmp.pem -in localhost.csr +cat privkey.pem tmp.pem > proxy-ideal.pem + +# Corrupt the signature on the certificate. +SUBJECT=proxy openssl x509 -outform der -in proxy-ideal.pem -out bad.der +length=`od -Ad bad.der | tail -n 1 | awk '{print $1}'` +dd if=/dev/zero bs=1 of=bad.der count=16 seek=`expr $length - 16` +SUBJECT=proxy openssl x509 -inform der -in bad.der -out tmp.pem +cat privkey.pem tmp.pem > proxy-badsig.pem + +# Clean up. +rm -f openssl.cnf proxy.csr localhost.csr privkey.pem ca.db ca.db.old ca.srl ca.srl.old ca.db.attr ca.db.attr.old 02.pem 03.pem 04.pem 05.pem tmp.pem bad.der diff --git a/krb5-1.21.3/src/tests/proxy-certs/proxy-badsig.pem b/krb5-1.21.3/src/tests/proxy-certs/proxy-badsig.pem new file mode 100644 index 00000000..40001d97 --- /dev/null +++ b/krb5-1.21.3/src/tests/proxy-certs/proxy-badsig.pem @@ -0,0 +1,56 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA54HCeTTUe127pqjK8r28NGMw2r2x+hWKKayH5NmqOqnwnzRH +kZE5UjkazQ/h97S6LZ6Yb8w3mJEyX1PdcNARDw2mbOPFk5N9uXnBb6AZog7hh9wM +e//g9a7PpKanfw69fSVgAr49TFFiLoKuyTgHiJOB7YgP0bTHEO4lLqusPQM16lRD +SdoXg42udAh3uBY+QDs23snLSiB+9vt8gt6gXiaYb3BBOWs9B3PKs374N9kOPsgc +j+8kyR/M+q+RfK5biqS3ce/sxvPV0Kseh//1uJxlbQCwOiBd3TLWHLhW9F7rzEcv +zn1Mfck35s0XDDRlGxRGGDy+ZCKmxf8Zu/8SwwIDAQABAoIBAGxzOBQpsIReQ6Lu +HaybP4hXEzLVfIOIBaJCJaMKaJl0tLkP95r0qiKfh7OahiPRMQpf6k8tHrpFApDv +q6PGhMdFgLov9YWNqW7y37AYEwn86KAJcHvCQbM2AiXCwGJgGFqA4LpIPlT7JwBc +zd6LddQALfSFMcvuYPbIaPi1CUnGy/AAyxGjUrc60KO57NbI+dHSTOwTHO1QjOz9 +ESk4fb34beUuZQzR6s/s1N0k09GJyklLpAAblRs5M6w9IlAn781eRLUAHTafLm4b +21J9k2Q2UaOofn0Cvh8ggyJMiYqAJ0CsRy5pJroEyboA51WU+8THNFkNtRX5SxY5 +YY3xE7ECgYEA/qkq7BPMkr/SnBPm32G1Eux5eLVd65qbox0oTLodZbusuxutqXTp +1MseDPQtHlrq6CQBizwElx//pdKnIiU9iBS/QkMR9CviitMTt+WrWRrM54/A4CJP +AU2Jg7b2DmhW1ombHHiBZ1tWzyiv9zxrtwR8kmKqv9aTOuPn4l7jY5kCgYEA6Llr +47pQjp/YhkBBvlriRwM9RXek++ythgsWvEswORaUalnaZ9gxZOKKas35GLDDuVyT +RnEhIqVlTg9iz6x5fXRtm6VzQvy9yFLzPMnlwsiSnRNOfMVIETUTOhNgm45tYY8f +lN5bcdY6k6VZ/g/N3zqddnxkjocrd6lAayjjIrsCgYEAyZLYAcPuQx6JM7fhIGIz +tQXvZKeS7yITHbq/onQTPuqd4AEZpi9/w0r/v1srt4JZvGR7wF1CeOkAL56dYr69 +hNB/T5DNTkvKZv6K9h5aUg6PsJ8uGXuus6ZPOi4BeAgI7IpBd/i+3TQEc7eOCZIO +5PAtNqXY6D6NjajGbH2VWckCgYA2KRDmyrF8v86QT9v9BQGsLSDRTerjhk1L6MC9 +yXHLl2mq5oZhrHqyU9aKzKywBlNGjDjqJ+HiQkO1SvdgBW+wtqvbkUGl0VQJjuR0 +vTfvgOY+EAQwHWmMN6Hl3iSZjyf9kGV1K9p0P7saKV0sN1leHjIPJRvx35tKGeWY +CsfxiQKBgQCVUvsX/HeWyc4bxxMuzw8JniUG2JftZqIC1haHEFNElASjt4hARM7Y +X/dkpYPXOZaN+qfvP949rS1WPXRtwMjt7bYzm7MGbXW7OiGGY3LV2CuVmbXJupvr +Usvi+YnpqKDY/miOYd+541NJm76AQTSgQ8K7XitX7Beddh1U9e17mg== +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIE3TCCA8WgAwIBAgIBBTANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSIwIAYDVQQLDBlJbnNlY3VyZSBLZXJiZXJvcyB0ZXN0IENBMSww +KgYDVQQDDCN0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVyd2lzZTAeFw0x +OTExMTIxODMwMzRaFw0zMDEwMjUxODMwMzRaME8xCzAJBgNVBAYTAlVTMRYwFAYD +VQQIDA1NYXNzYWNodXNldHRzMRQwEgYDVQQKDAtLUkJURVNULkNPTTESMBAGA1UE +AwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA54HC +eTTUe127pqjK8r28NGMw2r2x+hWKKayH5NmqOqnwnzRHkZE5UjkazQ/h97S6LZ6Y +b8w3mJEyX1PdcNARDw2mbOPFk5N9uXnBb6AZog7hh9wMe//g9a7PpKanfw69fSVg +Ar49TFFiLoKuyTgHiJOB7YgP0bTHEO4lLqusPQM16lRDSdoXg42udAh3uBY+QDs2 +3snLSiB+9vt8gt6gXiaYb3BBOWs9B3PKs374N9kOPsgcj+8kyR/M+q+RfK5biqS3 +ce/sxvPV0Kseh//1uJxlbQCwOiBd3TLWHLhW9F7rzEcvzn1Mfck35s0XDDRlGxRG +GDy+ZCKmxf8Zu/8SwwIDAQABo4IBdzCCAXMwHQYDVR0OBBYEFPf/vJvFMCwrABeC +C0sq7RGfYeIiMIHGBgNVHSMEgb4wgbuAFPf/vJvFMCwrABeCC0sq7RGfYeIioYGf +pIGcMIGZMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVzZXR0czESMBAG +A1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxIjAgBgNVBAsMGUluc2VjdXJl +IEtlcmJlcm9zIHRlc3QgQ0ExLDAqBgNVBAMMI3Rlc3Qgc3VpdGUgQ0E7IGRvIG5v +dCB1c2Ugb3RoZXJ3aXNlggEBMAsGA1UdDwQEAwID6DAMBgNVHRMBAf8EAjAAMFkG +A1UdEQRSMFCCFnByb3h5xaB1YmplY3TDhGx0w5FhbWWCE3Byb3h5U3ViamVjdEFs +dE5hbWWHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAGCCWxvY2FsaG9zdDATBgNVHSUE +DDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAQEAsMRJnxdbnpm5VlCFwNyU +8ra1wCjj+ZH0POVCM4iXQ77bV6UBpcqlaQUvR7R/H1Bt5t3Cp0ycN/dy+RcXtj+5 +FA84bRM767rsakxTEwjOjWw6GiK6bGjBfQ4F6Q97ELmiM0OZgmW8D56UHZxrI+o7 +QrKWBpFf1UA8n/BmupHBtyW3gudtJS9a71u6lBRydPFqJ4l8YxHckbgPFceSRbRj +x7E2pQVQ0p2nvG/NVyuC+2L29p81KAsG3vPzwOOfr1Tnpl1/B4R0+XEIy33KHpbz +Ceyitz6k16fOVNxMI59W2OACPTQ/s99kygh+cARRPfEUAAAAAAAAAAAAAAAAAAAA +AA== +-----END CERTIFICATE----- diff --git a/krb5-1.21.3/src/tests/proxy-certs/proxy-ideal.pem b/krb5-1.21.3/src/tests/proxy-certs/proxy-ideal.pem new file mode 100644 index 00000000..3bb09dc9 --- /dev/null +++ b/krb5-1.21.3/src/tests/proxy-certs/proxy-ideal.pem @@ -0,0 +1,56 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA54HCeTTUe127pqjK8r28NGMw2r2x+hWKKayH5NmqOqnwnzRH +kZE5UjkazQ/h97S6LZ6Yb8w3mJEyX1PdcNARDw2mbOPFk5N9uXnBb6AZog7hh9wM +e//g9a7PpKanfw69fSVgAr49TFFiLoKuyTgHiJOB7YgP0bTHEO4lLqusPQM16lRD +SdoXg42udAh3uBY+QDs23snLSiB+9vt8gt6gXiaYb3BBOWs9B3PKs374N9kOPsgc +j+8kyR/M+q+RfK5biqS3ce/sxvPV0Kseh//1uJxlbQCwOiBd3TLWHLhW9F7rzEcv +zn1Mfck35s0XDDRlGxRGGDy+ZCKmxf8Zu/8SwwIDAQABAoIBAGxzOBQpsIReQ6Lu +HaybP4hXEzLVfIOIBaJCJaMKaJl0tLkP95r0qiKfh7OahiPRMQpf6k8tHrpFApDv +q6PGhMdFgLov9YWNqW7y37AYEwn86KAJcHvCQbM2AiXCwGJgGFqA4LpIPlT7JwBc +zd6LddQALfSFMcvuYPbIaPi1CUnGy/AAyxGjUrc60KO57NbI+dHSTOwTHO1QjOz9 +ESk4fb34beUuZQzR6s/s1N0k09GJyklLpAAblRs5M6w9IlAn781eRLUAHTafLm4b +21J9k2Q2UaOofn0Cvh8ggyJMiYqAJ0CsRy5pJroEyboA51WU+8THNFkNtRX5SxY5 +YY3xE7ECgYEA/qkq7BPMkr/SnBPm32G1Eux5eLVd65qbox0oTLodZbusuxutqXTp +1MseDPQtHlrq6CQBizwElx//pdKnIiU9iBS/QkMR9CviitMTt+WrWRrM54/A4CJP +AU2Jg7b2DmhW1ombHHiBZ1tWzyiv9zxrtwR8kmKqv9aTOuPn4l7jY5kCgYEA6Llr +47pQjp/YhkBBvlriRwM9RXek++ythgsWvEswORaUalnaZ9gxZOKKas35GLDDuVyT +RnEhIqVlTg9iz6x5fXRtm6VzQvy9yFLzPMnlwsiSnRNOfMVIETUTOhNgm45tYY8f +lN5bcdY6k6VZ/g/N3zqddnxkjocrd6lAayjjIrsCgYEAyZLYAcPuQx6JM7fhIGIz +tQXvZKeS7yITHbq/onQTPuqd4AEZpi9/w0r/v1srt4JZvGR7wF1CeOkAL56dYr69 +hNB/T5DNTkvKZv6K9h5aUg6PsJ8uGXuus6ZPOi4BeAgI7IpBd/i+3TQEc7eOCZIO +5PAtNqXY6D6NjajGbH2VWckCgYA2KRDmyrF8v86QT9v9BQGsLSDRTerjhk1L6MC9 +yXHLl2mq5oZhrHqyU9aKzKywBlNGjDjqJ+HiQkO1SvdgBW+wtqvbkUGl0VQJjuR0 +vTfvgOY+EAQwHWmMN6Hl3iSZjyf9kGV1K9p0P7saKV0sN1leHjIPJRvx35tKGeWY +CsfxiQKBgQCVUvsX/HeWyc4bxxMuzw8JniUG2JftZqIC1haHEFNElASjt4hARM7Y +X/dkpYPXOZaN+qfvP949rS1WPXRtwMjt7bYzm7MGbXW7OiGGY3LV2CuVmbXJupvr +Usvi+YnpqKDY/miOYd+541NJm76AQTSgQ8K7XitX7Beddh1U9e17mg== +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIE3TCCA8WgAwIBAgIBBTANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSIwIAYDVQQLDBlJbnNlY3VyZSBLZXJiZXJvcyB0ZXN0IENBMSww +KgYDVQQDDCN0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVyd2lzZTAeFw0x +OTExMTIxODMwMzRaFw0zMDEwMjUxODMwMzRaME8xCzAJBgNVBAYTAlVTMRYwFAYD +VQQIDA1NYXNzYWNodXNldHRzMRQwEgYDVQQKDAtLUkJURVNULkNPTTESMBAGA1UE +AwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA54HC +eTTUe127pqjK8r28NGMw2r2x+hWKKayH5NmqOqnwnzRHkZE5UjkazQ/h97S6LZ6Y +b8w3mJEyX1PdcNARDw2mbOPFk5N9uXnBb6AZog7hh9wMe//g9a7PpKanfw69fSVg +Ar49TFFiLoKuyTgHiJOB7YgP0bTHEO4lLqusPQM16lRDSdoXg42udAh3uBY+QDs2 +3snLSiB+9vt8gt6gXiaYb3BBOWs9B3PKs374N9kOPsgcj+8kyR/M+q+RfK5biqS3 +ce/sxvPV0Kseh//1uJxlbQCwOiBd3TLWHLhW9F7rzEcvzn1Mfck35s0XDDRlGxRG +GDy+ZCKmxf8Zu/8SwwIDAQABo4IBdzCCAXMwHQYDVR0OBBYEFPf/vJvFMCwrABeC +C0sq7RGfYeIiMIHGBgNVHSMEgb4wgbuAFPf/vJvFMCwrABeCC0sq7RGfYeIioYGf +pIGcMIGZMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVzZXR0czESMBAG +A1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxIjAgBgNVBAsMGUluc2VjdXJl +IEtlcmJlcm9zIHRlc3QgQ0ExLDAqBgNVBAMMI3Rlc3Qgc3VpdGUgQ0E7IGRvIG5v +dCB1c2Ugb3RoZXJ3aXNlggEBMAsGA1UdDwQEAwID6DAMBgNVHRMBAf8EAjAAMFkG +A1UdEQRSMFCCFnByb3h5xaB1YmplY3TDhGx0w5FhbWWCE3Byb3h5U3ViamVjdEFs +dE5hbWWHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAGCCWxvY2FsaG9zdDATBgNVHSUE +DDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAQEAsMRJnxdbnpm5VlCFwNyU +8ra1wCjj+ZH0POVCM4iXQ77bV6UBpcqlaQUvR7R/H1Bt5t3Cp0ycN/dy+RcXtj+5 +FA84bRM767rsakxTEwjOjWw6GiK6bGjBfQ4F6Q97ELmiM0OZgmW8D56UHZxrI+o7 +QrKWBpFf1UA8n/BmupHBtyW3gudtJS9a71u6lBRydPFqJ4l8YxHckbgPFceSRbRj +x7E2pQVQ0p2nvG/NVyuC+2L29p81KAsG3vPzwOOfr1Tnpl1/B4R0+XEIy33KHpbz +Ceyitz6k16fOVNxMI59W2OACPTQ/s99kygh+cARRPfEUPjDcJpS1gRZ6kDKRh6Np +ig== +-----END CERTIFICATE----- diff --git a/krb5-1.21.3/src/tests/proxy-certs/proxy-no-match.pem b/krb5-1.21.3/src/tests/proxy-certs/proxy-no-match.pem new file mode 100644 index 00000000..7464e40d --- /dev/null +++ b/krb5-1.21.3/src/tests/proxy-certs/proxy-no-match.pem @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA54HCeTTUe127pqjK8r28NGMw2r2x+hWKKayH5NmqOqnwnzRH +kZE5UjkazQ/h97S6LZ6Yb8w3mJEyX1PdcNARDw2mbOPFk5N9uXnBb6AZog7hh9wM +e//g9a7PpKanfw69fSVgAr49TFFiLoKuyTgHiJOB7YgP0bTHEO4lLqusPQM16lRD +SdoXg42udAh3uBY+QDs23snLSiB+9vt8gt6gXiaYb3BBOWs9B3PKs374N9kOPsgc +j+8kyR/M+q+RfK5biqS3ce/sxvPV0Kseh//1uJxlbQCwOiBd3TLWHLhW9F7rzEcv +zn1Mfck35s0XDDRlGxRGGDy+ZCKmxf8Zu/8SwwIDAQABAoIBAGxzOBQpsIReQ6Lu +HaybP4hXEzLVfIOIBaJCJaMKaJl0tLkP95r0qiKfh7OahiPRMQpf6k8tHrpFApDv +q6PGhMdFgLov9YWNqW7y37AYEwn86KAJcHvCQbM2AiXCwGJgGFqA4LpIPlT7JwBc +zd6LddQALfSFMcvuYPbIaPi1CUnGy/AAyxGjUrc60KO57NbI+dHSTOwTHO1QjOz9 +ESk4fb34beUuZQzR6s/s1N0k09GJyklLpAAblRs5M6w9IlAn781eRLUAHTafLm4b +21J9k2Q2UaOofn0Cvh8ggyJMiYqAJ0CsRy5pJroEyboA51WU+8THNFkNtRX5SxY5 +YY3xE7ECgYEA/qkq7BPMkr/SnBPm32G1Eux5eLVd65qbox0oTLodZbusuxutqXTp +1MseDPQtHlrq6CQBizwElx//pdKnIiU9iBS/QkMR9CviitMTt+WrWRrM54/A4CJP +AU2Jg7b2DmhW1ombHHiBZ1tWzyiv9zxrtwR8kmKqv9aTOuPn4l7jY5kCgYEA6Llr +47pQjp/YhkBBvlriRwM9RXek++ythgsWvEswORaUalnaZ9gxZOKKas35GLDDuVyT +RnEhIqVlTg9iz6x5fXRtm6VzQvy9yFLzPMnlwsiSnRNOfMVIETUTOhNgm45tYY8f +lN5bcdY6k6VZ/g/N3zqddnxkjocrd6lAayjjIrsCgYEAyZLYAcPuQx6JM7fhIGIz +tQXvZKeS7yITHbq/onQTPuqd4AEZpi9/w0r/v1srt4JZvGR7wF1CeOkAL56dYr69 +hNB/T5DNTkvKZv6K9h5aUg6PsJ8uGXuus6ZPOi4BeAgI7IpBd/i+3TQEc7eOCZIO +5PAtNqXY6D6NjajGbH2VWckCgYA2KRDmyrF8v86QT9v9BQGsLSDRTerjhk1L6MC9 +yXHLl2mq5oZhrHqyU9aKzKywBlNGjDjqJ+HiQkO1SvdgBW+wtqvbkUGl0VQJjuR0 +vTfvgOY+EAQwHWmMN6Hl3iSZjyf9kGV1K9p0P7saKV0sN1leHjIPJRvx35tKGeWY +CsfxiQKBgQCVUvsX/HeWyc4bxxMuzw8JniUG2JftZqIC1haHEFNElASjt4hARM7Y +X/dkpYPXOZaN+qfvP949rS1WPXRtwMjt7bYzm7MGbXW7OiGGY3LV2CuVmbXJupvr +Usvi+YnpqKDY/miOYd+541NJm76AQTSgQ8K7XitX7Beddh1U9e17mg== +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIEhzCCA2+gAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSIwIAYDVQQLDBlJbnNlY3VyZSBLZXJiZXJvcyB0ZXN0IENBMSww +KgYDVQQDDCN0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVyd2lzZTAeFw0x +OTExMTIxODMwMzRaFw0zMDEwMjUxODMwMzRaMFQxCzAJBgNVBAYTAlVTMRYwFAYD +VQQIDA1NYXNzYWNodXNldHRzMRQwEgYDVQQKDAtLUkJURVNULkNPTTEXMBUGA1UE +AwwOUFJPWFlpblN1YmplY3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDngcJ5NNR7XbumqMryvbw0YzDavbH6FYoprIfk2ao6qfCfNEeRkTlSORrND+H3 +tLotnphvzDeYkTJfU91w0BEPDaZs48WTk325ecFvoBmiDuGH3Ax7/+D1rs+kpqd/ +Dr19JWACvj1MUWIugq7JOAeIk4HtiA/RtMcQ7iUuq6w9AzXqVENJ2heDja50CHe4 +Fj5AOzbeyctKIH72+3yC3qBeJphvcEE5az0Hc8qzfvg32Q4+yByP7yTJH8z6r5F8 +rluKpLdx7+zG89XQqx6H//W4nGVtALA6IF3dMtYcuFb0XuvMRy/OfUx9yTfmzRcM +NGUbFEYYPL5kIqbF/xm7/xLDAgMBAAGjggEcMIIBGDAdBgNVHQ4EFgQU9/+8m8Uw +LCsAF4ILSyrtEZ9h4iIwgcYGA1UdIwSBvjCBu4AU9/+8m8UwLCsAF4ILSyrtEZ9h +4iKhgZ+kgZwwgZkxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRz +MRIwEAYDVQQHDAlDYW1icmlkZ2UxDDAKBgNVBAoMA01JVDEiMCAGA1UECwwZSW5z +ZWN1cmUgS2VyYmVyb3MgdGVzdCBDQTEsMCoGA1UEAwwjdGVzdCBzdWl0ZSBDQTsg +ZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0PBAQDAgPoMAwGA1UdEwEB/wQC +MAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAI0Ons8g +6aXdZsKSmp1hbwNUvsY5GNl/QHVJIMQbe9zNVkW9Hp286fzkMar6peTB9MEnhzJ5 +5mbJM9DkugzgJeG0+HwsSdjAQCOcG4jSQ3SaASETOo58LsaG/yssIaZiZdJBrzNb +1D5fJVVpopZMZ/mKUNB/2ofUVGVBZCdfyOoIbVSkkm1UHJ9liLFK1ZNPDTX60613 +YNl4BydTiXtEg+IOYgmFXuZj310dDZUMHuYdzAM5j+6i2JaIcK4PgDE+yG9Oj9N+ +uKjj0iHWyoZW49y9Hq/oiMegi2X4XZBtbZlEUu4OkpBJ1QG0MTaz/vN94sHiLOzS +81b7+2BMgHd51+E= +-----END CERTIFICATE----- diff --git a/krb5-1.21.3/src/tests/proxy-certs/proxy-san.pem b/krb5-1.21.3/src/tests/proxy-certs/proxy-san.pem new file mode 100644 index 00000000..8eaeceec --- /dev/null +++ b/krb5-1.21.3/src/tests/proxy-certs/proxy-san.pem @@ -0,0 +1,56 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA54HCeTTUe127pqjK8r28NGMw2r2x+hWKKayH5NmqOqnwnzRH +kZE5UjkazQ/h97S6LZ6Yb8w3mJEyX1PdcNARDw2mbOPFk5N9uXnBb6AZog7hh9wM +e//g9a7PpKanfw69fSVgAr49TFFiLoKuyTgHiJOB7YgP0bTHEO4lLqusPQM16lRD +SdoXg42udAh3uBY+QDs23snLSiB+9vt8gt6gXiaYb3BBOWs9B3PKs374N9kOPsgc +j+8kyR/M+q+RfK5biqS3ce/sxvPV0Kseh//1uJxlbQCwOiBd3TLWHLhW9F7rzEcv +zn1Mfck35s0XDDRlGxRGGDy+ZCKmxf8Zu/8SwwIDAQABAoIBAGxzOBQpsIReQ6Lu +HaybP4hXEzLVfIOIBaJCJaMKaJl0tLkP95r0qiKfh7OahiPRMQpf6k8tHrpFApDv +q6PGhMdFgLov9YWNqW7y37AYEwn86KAJcHvCQbM2AiXCwGJgGFqA4LpIPlT7JwBc +zd6LddQALfSFMcvuYPbIaPi1CUnGy/AAyxGjUrc60KO57NbI+dHSTOwTHO1QjOz9 +ESk4fb34beUuZQzR6s/s1N0k09GJyklLpAAblRs5M6w9IlAn781eRLUAHTafLm4b +21J9k2Q2UaOofn0Cvh8ggyJMiYqAJ0CsRy5pJroEyboA51WU+8THNFkNtRX5SxY5 +YY3xE7ECgYEA/qkq7BPMkr/SnBPm32G1Eux5eLVd65qbox0oTLodZbusuxutqXTp +1MseDPQtHlrq6CQBizwElx//pdKnIiU9iBS/QkMR9CviitMTt+WrWRrM54/A4CJP +AU2Jg7b2DmhW1ombHHiBZ1tWzyiv9zxrtwR8kmKqv9aTOuPn4l7jY5kCgYEA6Llr +47pQjp/YhkBBvlriRwM9RXek++ythgsWvEswORaUalnaZ9gxZOKKas35GLDDuVyT +RnEhIqVlTg9iz6x5fXRtm6VzQvy9yFLzPMnlwsiSnRNOfMVIETUTOhNgm45tYY8f +lN5bcdY6k6VZ/g/N3zqddnxkjocrd6lAayjjIrsCgYEAyZLYAcPuQx6JM7fhIGIz +tQXvZKeS7yITHbq/onQTPuqd4AEZpi9/w0r/v1srt4JZvGR7wF1CeOkAL56dYr69 +hNB/T5DNTkvKZv6K9h5aUg6PsJ8uGXuus6ZPOi4BeAgI7IpBd/i+3TQEc7eOCZIO +5PAtNqXY6D6NjajGbH2VWckCgYA2KRDmyrF8v86QT9v9BQGsLSDRTerjhk1L6MC9 +yXHLl2mq5oZhrHqyU9aKzKywBlNGjDjqJ+HiQkO1SvdgBW+wtqvbkUGl0VQJjuR0 +vTfvgOY+EAQwHWmMN6Hl3iSZjyf9kGV1K9p0P7saKV0sN1leHjIPJRvx35tKGeWY +CsfxiQKBgQCVUvsX/HeWyc4bxxMuzw8JniUG2JftZqIC1haHEFNElASjt4hARM7Y +X/dkpYPXOZaN+qfvP949rS1WPXRtwMjt7bYzm7MGbXW7OiGGY3LV2CuVmbXJupvr +Usvi+YnpqKDY/miOYd+541NJm76AQTSgQ8K7XitX7Beddh1U9e17mg== +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIE4jCCA8qgAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSIwIAYDVQQLDBlJbnNlY3VyZSBLZXJiZXJvcyB0ZXN0IENBMSww +KgYDVQQDDCN0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVyd2lzZTAeFw0x +OTExMTIxODMwMzRaFw0zMDEwMjUxODMwMzRaMFQxCzAJBgNVBAYTAlVTMRYwFAYD +VQQIDA1NYXNzYWNodXNldHRzMRQwEgYDVQQKDAtLUkJURVNULkNPTTEXMBUGA1UE +AwwOUFJPWFlpblN1YmplY3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDngcJ5NNR7XbumqMryvbw0YzDavbH6FYoprIfk2ao6qfCfNEeRkTlSORrND+H3 +tLotnphvzDeYkTJfU91w0BEPDaZs48WTk325ecFvoBmiDuGH3Ax7/+D1rs+kpqd/ +Dr19JWACvj1MUWIugq7JOAeIk4HtiA/RtMcQ7iUuq6w9AzXqVENJ2heDja50CHe4 +Fj5AOzbeyctKIH72+3yC3qBeJphvcEE5az0Hc8qzfvg32Q4+yByP7yTJH8z6r5F8 +rluKpLdx7+zG89XQqx6H//W4nGVtALA6IF3dMtYcuFb0XuvMRy/OfUx9yTfmzRcM +NGUbFEYYPL5kIqbF/xm7/xLDAgMBAAGjggF3MIIBczAdBgNVHQ4EFgQU9/+8m8Uw +LCsAF4ILSyrtEZ9h4iIwgcYGA1UdIwSBvjCBu4AU9/+8m8UwLCsAF4ILSyrtEZ9h +4iKhgZ+kgZwwgZkxCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRz +MRIwEAYDVQQHDAlDYW1icmlkZ2UxDDAKBgNVBAoMA01JVDEiMCAGA1UECwwZSW5z +ZWN1cmUgS2VyYmVyb3MgdGVzdCBDQTEsMCoGA1UEAwwjdGVzdCBzdWl0ZSBDQTsg +ZG8gbm90IHVzZSBvdGhlcndpc2WCAQEwCwYDVR0PBAQDAgPoMAwGA1UdEwEB/wQC +MAAwWQYDVR0RBFIwUIIWcHJveHnFoHViamVjdMOEbHTDkWFtZYITcHJveHlTdWJq +ZWN0QWx0TmFtZYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAAYIJbG9jYWxob3N0MBMG +A1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IBAQDQI1/zeNAWvXAG +CTJk+hFLNx7xzd28/vWGkumK60rSmLVLZNDlvfmNJZ/kd7d0YZFvZDvbzhugXigI +5N54664XreRwXA7QkgD2laFd/Rzq+6NdhyMCno7V6j1VZUm6/FWgfYjfGEBvbGNv +Ue50fyRSQBmFv3p87Av/Zc0OMjted0zOYUxUPH0OL+2e4BL/suo05Q5DZq+J8Dni +7SJbDC0fp5mKVLQ500zIRwUF2y5TE4olBsYBoaMDxQl+HoG6XpzaVslTKXAvzFMk +8beI2BmqUId1OSLa3TOKnbsK8K/MPnSnB5StINt1+ZtTjjV+dY3xB6ZC+G1Pl6Ta +00C7EWul +-----END CERTIFICATE----- diff --git a/krb5-1.21.3/src/tests/proxy-certs/proxy-subject.pem b/krb5-1.21.3/src/tests/proxy-certs/proxy-subject.pem new file mode 100644 index 00000000..3846aece --- /dev/null +++ b/krb5-1.21.3/src/tests/proxy-certs/proxy-subject.pem @@ -0,0 +1,54 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA54HCeTTUe127pqjK8r28NGMw2r2x+hWKKayH5NmqOqnwnzRH +kZE5UjkazQ/h97S6LZ6Yb8w3mJEyX1PdcNARDw2mbOPFk5N9uXnBb6AZog7hh9wM +e//g9a7PpKanfw69fSVgAr49TFFiLoKuyTgHiJOB7YgP0bTHEO4lLqusPQM16lRD +SdoXg42udAh3uBY+QDs23snLSiB+9vt8gt6gXiaYb3BBOWs9B3PKs374N9kOPsgc +j+8kyR/M+q+RfK5biqS3ce/sxvPV0Kseh//1uJxlbQCwOiBd3TLWHLhW9F7rzEcv +zn1Mfck35s0XDDRlGxRGGDy+ZCKmxf8Zu/8SwwIDAQABAoIBAGxzOBQpsIReQ6Lu +HaybP4hXEzLVfIOIBaJCJaMKaJl0tLkP95r0qiKfh7OahiPRMQpf6k8tHrpFApDv +q6PGhMdFgLov9YWNqW7y37AYEwn86KAJcHvCQbM2AiXCwGJgGFqA4LpIPlT7JwBc +zd6LddQALfSFMcvuYPbIaPi1CUnGy/AAyxGjUrc60KO57NbI+dHSTOwTHO1QjOz9 +ESk4fb34beUuZQzR6s/s1N0k09GJyklLpAAblRs5M6w9IlAn781eRLUAHTafLm4b +21J9k2Q2UaOofn0Cvh8ggyJMiYqAJ0CsRy5pJroEyboA51WU+8THNFkNtRX5SxY5 +YY3xE7ECgYEA/qkq7BPMkr/SnBPm32G1Eux5eLVd65qbox0oTLodZbusuxutqXTp +1MseDPQtHlrq6CQBizwElx//pdKnIiU9iBS/QkMR9CviitMTt+WrWRrM54/A4CJP +AU2Jg7b2DmhW1ombHHiBZ1tWzyiv9zxrtwR8kmKqv9aTOuPn4l7jY5kCgYEA6Llr +47pQjp/YhkBBvlriRwM9RXek++ythgsWvEswORaUalnaZ9gxZOKKas35GLDDuVyT +RnEhIqVlTg9iz6x5fXRtm6VzQvy9yFLzPMnlwsiSnRNOfMVIETUTOhNgm45tYY8f +lN5bcdY6k6VZ/g/N3zqddnxkjocrd6lAayjjIrsCgYEAyZLYAcPuQx6JM7fhIGIz +tQXvZKeS7yITHbq/onQTPuqd4AEZpi9/w0r/v1srt4JZvGR7wF1CeOkAL56dYr69 +hNB/T5DNTkvKZv6K9h5aUg6PsJ8uGXuus6ZPOi4BeAgI7IpBd/i+3TQEc7eOCZIO +5PAtNqXY6D6NjajGbH2VWckCgYA2KRDmyrF8v86QT9v9BQGsLSDRTerjhk1L6MC9 +yXHLl2mq5oZhrHqyU9aKzKywBlNGjDjqJ+HiQkO1SvdgBW+wtqvbkUGl0VQJjuR0 +vTfvgOY+EAQwHWmMN6Hl3iSZjyf9kGV1K9p0P7saKV0sN1leHjIPJRvx35tKGeWY +CsfxiQKBgQCVUvsX/HeWyc4bxxMuzw8JniUG2JftZqIC1haHEFNElASjt4hARM7Y +X/dkpYPXOZaN+qfvP949rS1WPXRtwMjt7bYzm7MGbXW7OiGGY3LV2CuVmbXJupvr +Usvi+YnpqKDY/miOYd+541NJm76AQTSgQ8K7XitX7Beddh1U9e17mg== +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIEgjCCA2qgAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UEBhMCVVMx +FjAUBgNVBAgMDU1hc3NhY2h1c2V0dHMxEjAQBgNVBAcMCUNhbWJyaWRnZTEMMAoG +A1UECgwDTUlUMSIwIAYDVQQLDBlJbnNlY3VyZSBLZXJiZXJvcyB0ZXN0IENBMSww +KgYDVQQDDCN0ZXN0IHN1aXRlIENBOyBkbyBub3QgdXNlIG90aGVyd2lzZTAeFw0x +OTExMTIxODMwMzRaFw0zMDEwMjUxODMwMzRaME8xCzAJBgNVBAYTAlVTMRYwFAYD +VQQIDA1NYXNzYWNodXNldHRzMRQwEgYDVQQKDAtLUkJURVNULkNPTTESMBAGA1UE +AwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA54HC +eTTUe127pqjK8r28NGMw2r2x+hWKKayH5NmqOqnwnzRHkZE5UjkazQ/h97S6LZ6Y +b8w3mJEyX1PdcNARDw2mbOPFk5N9uXnBb6AZog7hh9wMe//g9a7PpKanfw69fSVg +Ar49TFFiLoKuyTgHiJOB7YgP0bTHEO4lLqusPQM16lRDSdoXg42udAh3uBY+QDs2 +3snLSiB+9vt8gt6gXiaYb3BBOWs9B3PKs374N9kOPsgcj+8kyR/M+q+RfK5biqS3 +ce/sxvPV0Kseh//1uJxlbQCwOiBd3TLWHLhW9F7rzEcvzn1Mfck35s0XDDRlGxRG +GDy+ZCKmxf8Zu/8SwwIDAQABo4IBHDCCARgwHQYDVR0OBBYEFPf/vJvFMCwrABeC +C0sq7RGfYeIiMIHGBgNVHSMEgb4wgbuAFPf/vJvFMCwrABeCC0sq7RGfYeIioYGf +pIGcMIGZMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVzZXR0czESMBAG +A1UEBwwJQ2FtYnJpZGdlMQwwCgYDVQQKDANNSVQxIjAgBgNVBAsMGUluc2VjdXJl +IEtlcmJlcm9zIHRlc3QgQ0ExLDAqBgNVBAMMI3Rlc3Qgc3VpdGUgQ0E7IGRvIG5v +dCB1c2Ugb3RoZXJ3aXNlggEBMAsGA1UdDwQEAwID6DAMBgNVHRMBAf8EAjAAMBMG +A1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IBAQBdg7Gk/RqQpTfD +vyFB1GPWRcLYpYW4GQh3e/dcesmwjwT8Nsd4Mzq9mA9TzJIXwffUQ8de85L5+9Oh +k4yiwRS3vDCP0fr+GZMpBqkBVunJIHQnm+RWxT42+0kBxxmO/fqp5ztND8gGBLiW +QPHb+mSCFgmgwnRuW+UI3TZ965oZfd2oRjjHjr51cgxcXndqnNws/kakMpxSM+KT ++ICHNz5og79nC7zpVqu0Cd56stPXbrFeU+bnN5UT9sOZNOYstWZmS8u+ddDuJwhS +ijJZgtQNOIuBfD2TLfDmg/QfLeh5hhgBVyXC5o8g6KEtjPgm+44OF3vNZeuwVPaf +L58YyPcO +-----END CERTIFICATE----- diff --git a/krb5-1.21.3/src/tests/rdreq.c b/krb5-1.21.3/src/tests/rdreq.c new file mode 100644 index 00000000..52bec18c --- /dev/null +++ b/krb5-1.21.3/src/tests/rdreq.c @@ -0,0 +1,118 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/rdreq.c - Test harness for krb5_rd_req */ +/* + * Copyright (C) 2014 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. + */ + +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_principal client_princ, tkt_princ, server_princ; + krb5_ccache ccache; + krb5_creds *cred, mcred; + krb5_auth_context auth_con; + krb5_data apreq; + krb5_error_code ret, code; + const char *tkt_name, *server_name, *emsg; + + /* Parse arguments. */ + if (argc < 2 || argc > 3) { + fprintf(stderr, "Usage: rdreq tktname [servername]\n"); + exit(1); + } + tkt_name = argv[1]; + server_name = argv[2]; + + if (krb5_init_context(&context) != 0) + abort(); + + /* Parse the requested principal names. */ + if (krb5_parse_name(context, tkt_name, &tkt_princ) != 0) + abort(); + if (server_name != NULL) { + if (krb5_parse_name(context, server_name, &server_princ) != 0) + abort(); + server_princ->type = KRB5_NT_SRV_HST; + } else { + server_princ = NULL; + } + + /* Produce an AP-REQ message. */ + if (krb5_cc_default(context, &ccache) != 0) + abort(); + if (krb5_cc_get_principal(context, ccache, &client_princ) != 0) + abort(); + memset(&mcred, 0, sizeof(mcred)); + mcred.client = client_princ; + mcred.server = tkt_princ; + if (krb5_get_credentials(context, 0, ccache, &mcred, &cred) != 0) + abort(); + auth_con = NULL; + if (krb5_mk_req_extended(context, &auth_con, 0, NULL, cred, &apreq) != 0) + abort(); + + /* Consume the AP-REQ message without using a replay cache. */ + krb5_auth_con_free(context, auth_con); + if (krb5_auth_con_init(context, &auth_con) != 0) + abort(); + if (krb5_auth_con_setflags(context, auth_con, 0) != 0) + abort(); + ret = krb5_rd_req(context, &auth_con, &apreq, server_princ, NULL, NULL, + NULL); + + /* Display the result. */ + if (ret) { + code = ret - ERROR_TABLE_BASE_krb5; + if (code < 0 || code > 127) + code = 60; /* KRB_ERR_GENERIC */ + emsg = krb5_get_error_message(context, ret); + printf("%d %s\n", code, emsg); + krb5_free_error_message(context, emsg); + } else { + printf("0 success\n"); + } + + krb5_free_data_contents(context, &apreq); + assert(apreq.length == 0); + krb5_auth_con_free(context, auth_con); + krb5_free_creds(context, cred); + krb5_cc_close(context, ccache); + krb5_free_principal(context, client_princ); + krb5_free_principal(context, tkt_princ); + krb5_free_principal(context, server_princ); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/tests/replay.c b/krb5-1.21.3/src/tests/replay.c new file mode 100644 index 00000000..1703123d --- /dev/null +++ b/krb5-1.21.3/src/tests/replay.c @@ -0,0 +1,172 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/replay.c - test replay cache using libkrb5 functions */ +/* + * Copyright (C) 2019 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. + */ + +#include "k5-int.h" + +int +main(int argc, char **argv) +{ + krb5_error_code ret; + krb5_context ctx; + krb5_auth_context c_authcon, s_authcon, s_authcon2; + krb5_rcache rc; + krb5_ccache cc; + krb5_principal client, server; + krb5_creds mcred, *cred, **tmpcreds; + krb5_data der_apreq, der_krbsafe, der_krbpriv, *der_krbcred, tmpdata; + krb5_address addr; + struct in_addr inaddr; + const char *server_name; + + assert(argc == 2); + server_name = argv[1]; + + /* Create client and server auth contexts. (They will use a replay cache + * by default.) */ + ret = krb5_init_context(&ctx); + assert(ret == 0); + ret = krb5_auth_con_init(ctx, &c_authcon); + assert(ret == 0); + ret = krb5_auth_con_init(ctx, &s_authcon); + assert(ret == 0); + + /* Set dummy addresses for the auth contexts. */ + memset(&inaddr, 0, sizeof(inaddr)); + addr.addrtype = ADDRTYPE_INET; + addr.length = sizeof(inaddr); + addr.contents = (uint8_t *)&inaddr; + ret = krb5_auth_con_setaddrs(ctx, c_authcon, &addr, &addr); + assert(ret == 0); + ret = krb5_auth_con_setaddrs(ctx, s_authcon, &addr, &addr); + assert(ret == 0); + + /* Set up replay caches for the auth contexts. */ + tmpdata = string2data("testclient"); + ret = krb5_get_server_rcache(ctx, &tmpdata, &rc); + assert(ret == 0); + ret = krb5_auth_con_setrcache(ctx, c_authcon, rc); + assert(ret == 0); + tmpdata = string2data("testserver"); + ret = krb5_get_server_rcache(ctx, &tmpdata, &rc); + assert(ret == 0); + ret = krb5_auth_con_setrcache(ctx, s_authcon, rc); + assert(ret == 0); + + /* Construct the client and server principal names. */ + ret = krb5_cc_default(ctx, &cc); + assert(ret == 0); + ret = krb5_cc_get_principal(ctx, cc, &client); + assert(ret == 0); + ret = krb5_parse_name(ctx, server_name, &server); + assert(ret == 0); + + /* Get credentials for the client. */ + memset(&mcred, 0, sizeof(mcred)); + mcred.client = client; + mcred.server = server; + ret = krb5_get_credentials(ctx, 0, cc, &mcred, &cred); + assert(ret == 0); + + /* Send an AP-REP to establish the sessions. */ + ret = krb5_mk_req_extended(ctx, &c_authcon, 0, NULL, cred, &der_apreq); + assert(ret == 0); + ret = krb5_rd_req(ctx, &s_authcon, &der_apreq, NULL, NULL, NULL, NULL); + assert(ret == 0); + + /* Set up another server auth context with the same rcache name and replay + * the AP-REQ. */ + ret = krb5_auth_con_init(ctx, &s_authcon2); + assert(ret == 0); + tmpdata = string2data("testserver"); + ret = krb5_get_server_rcache(ctx, &tmpdata, &rc); + assert(ret == 0); + ret = krb5_auth_con_setrcache(ctx, s_authcon2, rc); + assert(ret == 0); + ret = krb5_rd_req(ctx, &s_authcon2, &der_apreq, NULL, NULL, NULL, NULL); + assert(ret == KRB5KRB_AP_ERR_REPEAT); + krb5_auth_con_free(ctx, s_authcon2); + + /* Make a KRB-SAFE message with the client auth context. */ + tmpdata = string2data("safemsg"); + ret = krb5_mk_safe(ctx, c_authcon, &tmpdata, &der_krbsafe, NULL); + assert(ret == 0); + /* Play it back to the client to detect a reflection. */ + ret = krb5_rd_safe(ctx, c_authcon, &der_krbsafe, &tmpdata, NULL); + assert(ret == KRB5KRB_AP_ERR_REPEAT); + /* Send it to the server auth context twice, to detect a replay. */ + ret = krb5_rd_safe(ctx, s_authcon, &der_krbsafe, &tmpdata, NULL); + assert(ret == 0); + krb5_free_data_contents(ctx, &tmpdata); + ret = krb5_rd_safe(ctx, s_authcon, &der_krbsafe, &tmpdata, NULL); + assert(ret == KRB5KRB_AP_ERR_REPEAT); + + /* Make a KRB-PRIV message with the client auth context. */ + tmpdata = string2data("safemsg"); + ret = krb5_mk_priv(ctx, c_authcon, &tmpdata, &der_krbpriv, NULL); + assert(ret == 0); + /* Play it back to the client to detect a reflection. */ + ret = krb5_rd_priv(ctx, c_authcon, &der_krbpriv, &tmpdata, NULL); + assert(ret == KRB5KRB_AP_ERR_REPEAT); + /* Send it to the server auth context twice, to detect a replay. */ + ret = krb5_rd_priv(ctx, s_authcon, &der_krbpriv, &tmpdata, NULL); + assert(ret == 0); + krb5_free_data_contents(ctx, &tmpdata); + ret = krb5_rd_priv(ctx, s_authcon, &der_krbpriv, &tmpdata, NULL); + assert(ret == KRB5KRB_AP_ERR_REPEAT); + + /* Make a KRB-CRED message with the client auth context. */ + tmpdata = string2data("safemsg"); + ret = krb5_mk_1cred(ctx, c_authcon, cred, &der_krbcred, NULL); + assert(ret == 0); + /* Play it back to the client to detect a reflection. */ + ret = krb5_rd_cred(ctx, c_authcon, der_krbcred, &tmpcreds, NULL); + assert(ret == KRB5KRB_AP_ERR_REPEAT); + /* Send it to the server auth context twice, to detect a replay. */ + ret = krb5_rd_cred(ctx, s_authcon, der_krbcred, &tmpcreds, NULL); + assert(ret == 0); + krb5_free_tgt_creds(ctx, tmpcreds); + ret = krb5_rd_cred(ctx, s_authcon, der_krbcred, &tmpcreds, NULL); + assert(ret == KRB5KRB_AP_ERR_REPEAT); + + krb5_free_data_contents(ctx, &der_apreq); + krb5_free_data_contents(ctx, &der_krbsafe); + krb5_free_data_contents(ctx, &der_krbpriv); + krb5_free_data(ctx, der_krbcred); + krb5_free_creds(ctx, cred); + krb5_cc_close(ctx, cc); + krb5_free_principal(ctx, client); + krb5_free_principal(ctx, server); + krb5_auth_con_free(ctx, c_authcon); + krb5_auth_con_free(ctx, s_authcon); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/responder.c b/krb5-1.21.3/src/tests/responder.c new file mode 100644 index 00000000..82f870ea --- /dev/null +++ b/krb5-1.21.3/src/tests/responder.c @@ -0,0 +1,431 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/responder.c - Test harness for responder callbacks and the like. */ +/* + * Copyright 2013 Red Hat, Inc. 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. + * + * 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. + */ + +/* + * A helper for testing PKINIT and responder callbacks. + * + * This test helper takes multiple options and one argument. + * + * responder [options] principal + * -X preauth_option -> preauth options, as for kinit + * -x challenge -> expected responder challenge, of the form + * "question=challenge" + * -r response -> provide a reponder answer, in the form + * "question=answer" + * -c -> print the pkinit challenge + * -p identity=pin -> provide a pkinit answer, in the form "identity=pin" + * -o index=value:pin -> provide an OTP answer, in the form "index=value:pin" + * principal -> client principal name + * + * If the responder callback isn't called, that's treated as an error. + * + * If an expected responder challenge is specified, when the responder + * callback is called, the challenge associated with the specified question is + * compared against the specified value. If the value provided to the + * callback doesn't parse as JSON, a literal string compare is performed, + * otherwise both values are parsed as JSON and then re-encoded before + * comparison. In either case, the comparison must succeed. + * + * Any missing data or mismatches are treated as errors. + */ + +#include +#include +#include +#include +#include + +struct responder_data { + krb5_boolean called; + krb5_boolean print_pkinit_challenge; + const char *challenge; + const char *response; + const char *pkinit_answer; + const char *otp_answer; +}; + +static krb5_error_code +responder(krb5_context ctx, void *rawdata, krb5_responder_context rctx) +{ + krb5_error_code err; + char *key, *value, *pin, *encoded1, *encoded2; + const char *challenge; + k5_json_value decoded1, decoded2; + k5_json_object ids; + k5_json_number val; + krb5_int32 token_flags; + struct responder_data *data = rawdata; + krb5_responder_pkinit_challenge *chl; + krb5_responder_otp_challenge *ochl; + unsigned int i, n; + + data->called = TRUE; + + /* Check that a particular challenge has the specified expected value. */ + if (data->challenge != NULL) { + /* Separate the challenge name and its expected value. */ + key = strdup(data->challenge); + if (key == NULL) + exit(ENOMEM); + value = key + strcspn(key, "="); + if (*value != '\0') + *value++ = '\0'; + /* Read the challenge. */ + challenge = krb5_responder_get_challenge(ctx, rctx, key); + err = k5_json_decode(value, &decoded1); + /* Check for "no challenge". */ + if (challenge == NULL && *value == '\0') { + fprintf(stderr, "OK: (no challenge) == (no challenge)\n"); + } else if (err != 0) { + /* It's not JSON, so assume we're just after a string compare. */ + if (strcmp(challenge, value) == 0) { + fprintf(stderr, "OK: \"%s\" == \"%s\"\n", challenge, value); + } else { + fprintf(stderr, "ERROR: \"%s\" != \"%s\"\n", challenge, value); + exit(1); + } + } else { + /* Assume we're after a JSON compare - decode the actual value. */ + err = k5_json_decode(challenge, &decoded2); + if (err != 0) { + fprintf(stderr, "error decoding \"%s\"\n", challenge); + exit(1); + } + /* Re-encode the expected challenge and the actual challenge... */ + err = k5_json_encode(decoded1, &encoded1); + if (err != 0) { + fprintf(stderr, "error encoding json data\n"); + exit(1); + } + err = k5_json_encode(decoded2, &encoded2); + if (err != 0) { + fprintf(stderr, "error encoding json data\n"); + exit(1); + } + k5_json_release(decoded1); + k5_json_release(decoded2); + /* ... and see if they look the same. */ + if (strcmp(encoded1, encoded2) == 0) { + fprintf(stderr, "OK: \"%s\" == \"%s\"\n", encoded1, encoded2); + } else { + fprintf(stderr, "ERROR: \"%s\" != \"%s\"\n", encoded1, + encoded2); + exit(1); + } + free(encoded1); + free(encoded2); + } + free(key); + } + + /* Provide a particular response for a challenge. */ + if (data->response != NULL) { + /* Separate the challenge and its data content... */ + key = strdup(data->response); + if (key == NULL) + exit(ENOMEM); + value = key + strcspn(key, "="); + if (*value != '\0') + *value++ = '\0'; + /* ... and pass it in. */ + err = krb5_responder_set_answer(ctx, rctx, key, value); + if (err != 0) { + fprintf(stderr, "error setting response\n"); + exit(1); + } + free(key); + } + + if (data->print_pkinit_challenge) { + /* Read the PKINIT challenge, formatted as a structure. */ + err = krb5_responder_pkinit_get_challenge(ctx, rctx, &chl); + if (err != 0) { + fprintf(stderr, "error getting pkinit challenge\n"); + exit(1); + } + if (chl != NULL) { + for (n = 0; chl->identities[n] != NULL; n++) + continue; + for (i = 0; chl->identities[i] != NULL; i++) { + if (chl->identities[i]->token_flags != -1) { + printf("identity %u/%u: %s (flags=0x%lx)\n", i + 1, n, + chl->identities[i]->identity, + (long)chl->identities[i]->token_flags); + } else { + printf("identity %u/%u: %s\n", i + 1, n, + chl->identities[i]->identity); + } + } + } + krb5_responder_pkinit_challenge_free(ctx, rctx, chl); + } + + /* Provide a particular response for the PKINIT challenge. */ + if (data->pkinit_answer != NULL) { + /* Read the PKINIT challenge, formatted as a structure. */ + err = krb5_responder_pkinit_get_challenge(ctx, rctx, &chl); + if (err != 0) { + fprintf(stderr, "error getting pkinit challenge\n"); + exit(1); + } + /* + * In case order matters, if the identity starts with "FILE:", exercise + * the set_answer function, with the real answer second. + */ + if (chl != NULL && + chl->identities != NULL && + chl->identities[0] != NULL) { + if (strncmp(chl->identities[0]->identity, "FILE:", 5) == 0) + krb5_responder_pkinit_set_answer(ctx, rctx, "foo", "bar"); + } + /* Provide the real answer. */ + key = strdup(data->pkinit_answer); + if (key == NULL) + exit(ENOMEM); + value = strrchr(key, '='); + if (value != NULL) + *value++ = '\0'; + else + value = ""; + err = krb5_responder_pkinit_set_answer(ctx, rctx, key, value); + if (err != 0) { + fprintf(stderr, "error setting response\n"); + exit(1); + } + free(key); + /* + * In case order matters, if the identity starts with "PKCS12:", + * exercise the set_answer function, with the real answer first. + */ + if (chl != NULL && + chl->identities != NULL && + chl->identities[0] != NULL) { + if (strncmp(chl->identities[0]->identity, "PKCS12:", 7) == 0) + krb5_responder_pkinit_set_answer(ctx, rctx, "foo", "bar"); + } + krb5_responder_pkinit_challenge_free(ctx, rctx, chl); + } + + /* + * Something we always check: read the PKINIT challenge, both as a + * structure and in JSON form, reconstruct the JSON form from the + * structure's contents, and check that they're the same. + */ + challenge = krb5_responder_get_challenge(ctx, rctx, + KRB5_RESPONDER_QUESTION_PKINIT); + if (challenge != NULL) { + krb5_responder_pkinit_get_challenge(ctx, rctx, &chl); + if (chl == NULL) { + fprintf(stderr, "pkinit raw challenge set, " + "but structure is NULL\n"); + exit(1); + } + if (k5_json_object_create(&ids) != 0) { + fprintf(stderr, "error creating json objects\n"); + exit(1); + } + for (i = 0; chl->identities[i] != NULL; i++) { + token_flags = chl->identities[i]->token_flags; + if (k5_json_number_create(token_flags, &val) != 0) { + fprintf(stderr, "error creating json number\n"); + exit(1); + } + if (k5_json_object_set(ids, chl->identities[i]->identity, + val) != 0) { + fprintf(stderr, "error adding json number to object\n"); + exit(1); + } + k5_json_release(val); + } + /* Encode the structure... */ + err = k5_json_encode(ids, &encoded1); + if (err != 0) { + fprintf(stderr, "error encoding json data\n"); + exit(1); + } + k5_json_release(ids); + /* ... and see if they look the same. */ + if (strcmp(encoded1, challenge) != 0) { + fprintf(stderr, "\"%s\" != \"%s\"\n", encoded1, challenge); + exit(1); + } + krb5_responder_pkinit_challenge_free(ctx, rctx, chl); + free(encoded1); + } + + /* Provide a particular response for an OTP challenge. */ + if (data->otp_answer != NULL) { + if (krb5_responder_otp_get_challenge(ctx, rctx, &ochl) == 0) { + key = strchr(data->otp_answer, '='); + if (key != NULL) { + /* Make a copy of the answer that we can chop up. */ + key = strdup(data->otp_answer); + if (key == NULL) + return ENOMEM; + /* Isolate the ti value. */ + value = strchr(key, '='); + *value++ = '\0'; + n = atoi(key); + /* Break the value and PIN apart. */ + pin = strchr(value, ':'); + if (pin != NULL) + *pin++ = '\0'; + err = krb5_responder_otp_set_answer(ctx, rctx, n, value, pin); + if (err != 0) { + fprintf(stderr, "error setting response\n"); + exit(1); + } + free(key); + } + krb5_responder_otp_challenge_free(ctx, rctx, ochl); + } + } + + return 0; +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_ccache ccache; + krb5_get_init_creds_opt *opts; + krb5_principal principal; + krb5_creds creds; + krb5_error_code err; + const char *errmsg; + char *opt, *val; + struct responder_data response; + int c; + + err = krb5_init_context(&context); + if (err != 0) { + fprintf(stderr, "error starting Kerberos: %s\n", error_message(err)); + return err; + } + err = krb5_get_init_creds_opt_alloc(context, &opts); + if (err != 0) { + fprintf(stderr, "error initializing options: %s\n", + error_message(err)); + return err; + } + err = krb5_cc_default(context, &ccache); + if (err != 0) { + fprintf(stderr, "error resolving default ccache: %s\n", + error_message(err)); + return err; + } + err = krb5_get_init_creds_opt_set_out_ccache(context, opts, ccache); + if (err != 0) { + fprintf(stderr, "error setting output ccache: %s\n", + error_message(err)); + return err; + } + + memset(&response, 0, sizeof(response)); + while ((c = getopt(argc, argv, "X:x:cr:p:")) != -1) { + switch (c) { + case 'X': + /* Like kinit, set a generic preauth option. */ + opt = strdup(optarg); + val = opt + strcspn(opt, "="); + if (*val != '\0') { + *val++ = '\0'; + } + err = krb5_get_init_creds_opt_set_pa(context, opts, opt, val); + if (err != 0) { + fprintf(stderr, "error setting option \"%s\": %s\n", opt, + error_message(err)); + return err; + } + free(opt); + break; + case 'x': + /* Check that a particular question has a specific challenge. */ + response.challenge = optarg; + break; + case 'c': + /* Note that we want a dump of the PKINIT challenge structure. */ + response.print_pkinit_challenge = TRUE; + break; + case 'r': + /* Set a verbatim response for a verbatim challenge. */ + response.response = optarg; + break; + case 'p': + /* Set a PKINIT answer for a specific PKINIT identity. */ + response.pkinit_answer = optarg; + break; + case 'o': + /* Set an OTP answer for a specific OTP tokeninfo. */ + response.otp_answer = optarg; + break; + } + } + + if (argc > optind) { + err = krb5_parse_name(context, argv[optind], &principal); + if (err != 0) { + fprintf(stderr, "error parsing name \"%s\": %s", argv[optind], + error_message(err)); + return err; + } + } else { + fprintf(stderr, "error: no principal name provided\n"); + return -1; + } + + err = krb5_get_init_creds_opt_set_responder(context, opts, + responder, &response); + if (err != 0) { + fprintf(stderr, "error setting responder: %s\n", error_message(err)); + return err; + } + memset(&creds, 0, sizeof(creds)); + err = krb5_get_init_creds_password(context, &creds, principal, NULL, + NULL, NULL, 0, NULL, opts); + if (err == 0) + krb5_free_cred_contents(context, &creds); + krb5_free_principal(context, principal); + krb5_get_init_creds_opt_free(context, opts); + krb5_cc_close(context, ccache); + + if (!response.called) { + fprintf(stderr, "error: responder callback wasn't called\n"); + err = 1; + } else if (err) { + errmsg = krb5_get_error_message(context, err); + fprintf(stderr, "error: krb5_get_init_creds_password failed: %s\n", + errmsg); + krb5_free_error_message(context, errmsg); + err = 2; + } + krb5_free_context(context); + return err; +} diff --git a/krb5-1.21.3/src/tests/s2p.c b/krb5-1.21.3/src/tests/s2p.c new file mode 100644 index 00000000..8fb2a94d --- /dev/null +++ b/krb5-1.21.3/src/tests/s2p.c @@ -0,0 +1,81 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/s2p.c - krb5_name_to_principal test harness */ +/* + * 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. + */ + +#include +#include +#include +#include + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +int +main(int argc, char **argv) +{ + krb5_principal princ; + krb5_int32 type; + const char *service, *hostname; + char *name; + + /* Parse arguments. */ + assert(argc == 4); + hostname = argv[1]; + service = argv[2]; + if (strcmp(argv[3], "unknown") == 0) + type = KRB5_NT_UNKNOWN; + else if (strcmp(argv[3], "srv-hst") == 0) + type = KRB5_NT_SRV_HST; + else + abort(); + + check(krb5_init_context(&ctx)); + check(krb5_sname_to_principal(ctx, hostname, service, type, &princ)); + check(krb5_unparse_name(ctx, princ, &name)); + printf("%s\n", name); + + krb5_free_unparsed_name(ctx, name); + krb5_free_principal(ctx, princ); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/s4u2proxy.c b/krb5-1.21.3/src/tests/s4u2proxy.c new file mode 100644 index 00000000..3786bad2 --- /dev/null +++ b/krb5-1.21.3/src/tests/s4u2proxy.c @@ -0,0 +1,147 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/s4u2proxy.c - S4U2Proxy test harness */ +/* + * Copyright (C) 2015 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. + */ + +/* + * Usage: s4u2proxy evccname targetname [ad-type ad-contents] + * + * evccname contains an evidence ticket. The default ccache contains a TGT for + * the intermediate service. The default keytab contains a key for the + * intermediate service. An S4U2Proxy request is made to get a ticket from + * evccname's default principal to the target service. The resulting cred is + * stored in the default ccache. + */ + +#include + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +static krb5_authdata ** +make_request_authdata(int type, const char *contents) +{ + krb5_authdata *ad; + krb5_authdata **req_authdata; + + ad = malloc(sizeof(*ad)); + assert(ad != NULL); + ad->magic = KV5M_AUTHDATA; + ad->ad_type = type; + ad->length = strlen(contents); + ad->contents = (unsigned char *)strdup(contents); + assert(ad->contents != NULL); + + req_authdata = malloc(2 * sizeof(*req_authdata)); + assert(req_authdata != NULL); + req_authdata[0] = ad; + req_authdata[1] = NULL; + + return req_authdata; +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_ccache defcc, evcc; + krb5_principal client_name, int_name, target_name; + krb5_keytab defkt; + krb5_creds mcred, ev_cred, *new_cred; + krb5_ticket *ev_ticket; + krb5_authdata **req_authdata = NULL; + + if (argc == 5) { + req_authdata = make_request_authdata(atoi(argv[3]), argv[4]); + argc -= 2; + } + + assert(argc == 3); + check(krb5_init_context(&context)); + + /* Open the default ccache, evidence ticket ccache, and default keytab. */ + check(krb5_cc_default(context, &defcc)); + check(krb5_cc_resolve(context, argv[1], &evcc)); + check(krb5_kt_default(context, &defkt)); + + /* Determine the client name, intermediate name, and target name. */ + check(krb5_cc_get_principal(context, evcc, &client_name)); + check(krb5_cc_get_principal(context, defcc, &int_name)); + check(krb5_parse_name(context, argv[2], &target_name)); + + /* Retrieve and decrypt the evidence ticket. */ + memset(&mcred, 0, sizeof(mcred)); + mcred.client = client_name; + mcred.server = int_name; + check(krb5_cc_retrieve_cred(context, evcc, 0, &mcred, &ev_cred)); + check(krb5_decode_ticket(&ev_cred.ticket, &ev_ticket)); + check(krb5_server_decrypt_ticket_keytab(context, defkt, ev_ticket)); + + /* Make an S4U2Proxy request for the target service. */ + mcred.client = client_name; + mcred.server = target_name; + mcred.authdata = req_authdata; + check(krb5_get_credentials_for_proxy(context, KRB5_GC_NO_STORE | + KRB5_GC_CANONICALIZE, defcc, + &mcred, ev_ticket, &new_cred)); + + assert(data_eq(new_cred->second_ticket, ev_cred.ticket)); + assert(new_cred->second_ticket.length != 0); + + /* Store the new cred in the default ccache. */ + check(krb5_cc_store_cred(context, defcc, new_cred)); + + assert(req_authdata == NULL || new_cred->authdata != NULL); + + krb5_cc_close(context, defcc); + krb5_cc_close(context, evcc); + krb5_kt_close(context, defkt); + krb5_free_principal(context, client_name); + krb5_free_principal(context, int_name); + krb5_free_principal(context, target_name); + krb5_free_cred_contents(context, &ev_cred); + krb5_free_ticket(context, ev_ticket); + krb5_free_creds(context, new_cred); + krb5_free_authdata(context, req_authdata); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/tests/s4u2self.c b/krb5-1.21.3/src/tests/s4u2self.c new file mode 100644 index 00000000..c8e48229 --- /dev/null +++ b/krb5-1.21.3/src/tests/s4u2self.c @@ -0,0 +1,128 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (C) 2019 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. + */ + +/* + * Usage: s4u2self user self out_cache [ad-type ad-contents] + * + * The default ccache contains a TGT for the intermediate service self. An + * S4U2Self request is made to self. The resulting cred is stored in + * out_cache. + */ + +#include + +static krb5_context ctx; + +static void +check(krb5_error_code code) +{ + const char *errmsg; + + if (code) { + errmsg = krb5_get_error_message(ctx, code); + fprintf(stderr, "%s\n", errmsg); + krb5_free_error_message(ctx, errmsg); + exit(1); + } +} + +static krb5_authdata ** +make_request_authdata(int type, const char *contents) +{ + krb5_authdata *ad; + krb5_authdata **req_authdata; + + ad = malloc(sizeof(*ad)); + assert(ad != NULL); + ad->magic = KV5M_AUTHDATA; + ad->ad_type = type; + ad->length = strlen(contents); + ad->contents = (unsigned char *)strdup(contents); + assert(ad->contents != NULL); + + req_authdata = malloc(2 * sizeof(*req_authdata)); + assert(req_authdata != NULL); + req_authdata[0] = ad; + req_authdata[1] = NULL; + + return req_authdata; +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_ccache defcc, ocache; + krb5_principal client, self; + krb5_creds mcred, *new_cred; + krb5_authdata **req_authdata = NULL; + + if (argc == 6) { + req_authdata = make_request_authdata(atoi(argv[4]), argv[5]); + argc -= 2; + } + + assert(argc == 4); + check(krb5_init_context(&context)); + + /* Open the default ccache. */ + check(krb5_cc_default(context, &defcc)); + + check(krb5_parse_name(context, argv[1], &client)); + check(krb5_parse_name(context, argv[2], &self)); + + memset(&mcred, 0, sizeof(mcred)); + mcred.client = client; + mcred.server = self; + mcred.authdata = req_authdata; + check(krb5_get_credentials_for_user(context, KRB5_GC_NO_STORE | + KRB5_GC_CANONICALIZE, defcc, + &mcred, NULL, &new_cred)); + + if (strcmp(argv[3], "-") == 0) { + check(krb5_cc_store_cred(context, defcc, new_cred)); + } else { + check(krb5_cc_resolve(context, argv[3], &ocache)); + check(krb5_cc_initialize(context, ocache, new_cred->client)); + check(krb5_cc_store_cred(context, ocache, new_cred)); + krb5_cc_close(context, ocache); + } + + assert(req_authdata == NULL || new_cred->authdata != NULL); + + krb5_cc_close(context, defcc); + krb5_free_principal(context, client); + krb5_free_principal(context, self); + krb5_free_creds(context, new_cred); + krb5_free_authdata(context, req_authdata); + krb5_free_context(context); + return 0; +} diff --git a/krb5-1.21.3/src/tests/shlib/Makefile.in b/krb5-1.21.3/src/tests/shlib/Makefile.in new file mode 100644 index 00000000..ce67be45 --- /dev/null +++ b/krb5-1.21.3/src/tests/shlib/Makefile.in @@ -0,0 +1,23 @@ +mydir=tests$(S)shlib +BUILDTOP=$(REL)..$(S).. + +#VALGRIND=valgrind +#VALGRINDFLAGS=--tool=memcheck --leak-check=yes --show-reachable=yes + +SRCS=$(srcdir)/t_loader.c + +all: + +run-t_loader: t_loader + $(RUN_TEST) ./t_loader + +t_loader: t_loader.o + $(CC_LINK) -o t_loader t_loader.o $(DL_LIB) + +check-unix: + +install: + +clean: + $(RM) t_loader.o t_loader + diff --git a/krb5-1.21.3/src/tests/shlib/deps b/krb5-1.21.3/src/tests/shlib/deps new file mode 100644 index 00000000..be6b824f --- /dev/null +++ b/krb5-1.21.3/src/tests/shlib/deps @@ -0,0 +1,8 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)t_loader.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/krb5/krb5.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ + t_loader.c diff --git a/krb5-1.21.3/src/tests/shlib/t_loader.c b/krb5-1.21.3/src/tests/shlib/t_loader.c new file mode 100644 index 00000000..29481a7b --- /dev/null +++ b/krb5-1.21.3/src/tests/shlib/t_loader.c @@ -0,0 +1,374 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/shlib/t_loader.c */ +/* + * Copyright (C) 2005 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-platform.h" +#include "krb5.h" +#include "gssapi/gssapi.h" +#define HAVE_DLOPEN 1 + +static int verbose = 1; + +#ifdef HAVE_DLFCN_H +# include +#endif +/* Solaris man page recommends link.h too */ + +/* lazy = 1 means resolve symbols later, 0 means now; any + other flags we should be testing? On Windows, maybe? + + Return value is the library handle. On error, print a message and + exit. */ +#define do_open(LIB,REV,FLAGS) do_open_1(LIB,REV,FLAGS,__LINE__) +static void *do_open_1(const char *libname, const char *rev, int lazy, int line); + +/* Look up a function symbol in the library and return a pointer. + + The return value may need casting to the correct type. On error, + print a message and exit. */ +static void *get_sym_1(void *libhandle, const char *sym, int line); +#define get_sym(LIB, NAME) get_sym_1(LIB, NAME, __LINE__) +#define GET_FSYM(TYPE, LIB, NAME) ((TYPE) get_sym(LIB, NAME)) +#define get_gfun(LIB, NAME) ((OM_uint32 KRB5_CALLCONV(*)()) get_sym(LIB, NAME)) + +/* Close dynamically-opened library. + + If the OS reports an error in doing so, print a message and + exit. */ +#define do_close(X) do_close_1(X, __LINE__) +static void do_close_1(void *libhandle, int line); + +#ifdef HAVE_DLOPEN + +#ifdef _AIX +# define SHLIB_SUFFIX ".a" +#else +# define SHLIB_SUFFIX ".so" +#endif + +#define HORIZ 25 + +static void *do_open_1(const char *libname, const char *rev, + int lazy, int line) +{ + void *p; + char *namebuf; + int r; + + if (verbose) + printf("from line %d: do_open(%s)...%*s", line, libname, + HORIZ-strlen(libname), ""); +#ifdef _AIX + r = asprintf(&namebuf, "lib%s%s", libname, SHLIB_SUFFIX); +#else + r = asprintf(&namebuf, "lib%s%s(shr.o.%s)", libname, SHLIB_SUFFIX, rev); +#endif + if (r < 0) { + perror("asprintf"); + exit(1); + } + +#ifndef RTLD_MEMBER +#define RTLD_MEMBER 0 +#endif + p = dlopen(namebuf, (lazy ? RTLD_LAZY : RTLD_NOW) | RTLD_MEMBER); + if (p == 0) { + fprintf(stderr, "dlopen of %s failed: %s\n", namebuf, dlerror()); + exit(1); + } + free(namebuf); + if (verbose) + printf("done: %p\n", p); + return p; +} + +#define SYM_PREFIX "" +static void *get_sym_1(void *libhandle, const char *symname, int line) +{ + void *s; + + /* Bah. Fix this later, if we care. */ + assert(strlen(SYM_PREFIX) == 0); + + if (verbose) + printf("from line %d: get_sym(%s)...%*s", line, symname, + HORIZ-strlen(symname), ""); + + s = dlsym(libhandle, symname); + if (s == 0) { + fprintf(stderr, "symbol %s not found\n", symname); + exit(1); + } + if (verbose) + printf("done: %p\n", s); + return s; +} + +static void do_close_1(void *libhandle, int line) +{ + if (verbose) { + char pbuf[3*sizeof(libhandle)+4]; + snprintf(pbuf, sizeof(pbuf), "%p", libhandle); + printf("from line %d: do_close(%s)...%*s", line, pbuf, + HORIZ-1-strlen(pbuf), ""); + } + if (dlclose(libhandle) != 0) { + fprintf(stderr, "dlclose failed: %s\n", dlerror()); + exit(1); + } + if (verbose) + printf("done\n"); +} + +#elif defined _WIN32 + +static void *do_open(const char *libname, int lazy) +{ + /* To be written? */ + abort(); +} + +static void *get_sym(void *libhandle, const char *symname) +{ + abort(); +} + +static void do_close(void *libhandle) +{ + abort(); +} + +#else + +static void *do_open(const char *libname, int lazy) +{ + printf("don't know how to do dynamic loading here, punting\n"); + exit(0); +} + +static void *get_sym(void *libhandle, const char *symname) +{ + abort(); +} + +static void do_close(void *libhandle) +{ + abort(); +} + +#endif + +int main() +{ + void *celib, *k5lib, *gsslib, *celib2; + + (void) setvbuf(stdout, 0, _IONBF, 0); + + celib = do_open("com_err", "3.0", 0); + k5lib = do_open("krb5", "3.2", 0); + gsslib = do_open("gssapi_krb5", "2.2", 0); + celib2 = do_open("com_err", "3.0", 0); + do_close(celib2); + { + typedef krb5_error_code KRB5_CALLCONV (*ict)(krb5_context *); + typedef void KRB5_CALLCONV (*fct)(krb5_context); + + ict init_context = (ict) get_sym(k5lib, "krb5_init_context"); + fct free_context = (fct) get_sym(k5lib, "krb5_free_context"); + krb5_context ctx; + krb5_error_code err; + +#define CALLING(S) (verbose ? printf("at line %d: calling %s...%*s", __LINE__, #S, (int)(HORIZ+1-strlen(#S)), "") : 0) +#define DONE() (verbose ? printf("done\n") : 0) + + CALLING(krb5_init_context); + err = init_context(&ctx); + DONE(); + if (err) { + fprintf(stderr, "error 0x%lx initializing context\n", + (unsigned long) err); + exit(1); + } + CALLING(krb5_free_context); + free_context(ctx); + DONE(); + } + celib2 = do_open("com_err", "3.0", 0); + do_close(celib); + do_close(k5lib); + do_close(celib2); + do_close(gsslib); + + /* Test gssapi_krb5 without having loaded anything else. */ + gsslib = do_open("gssapi_krb5", "2.2", 1); + { + OM_uint32 KRB5_CALLCONV (*init_sec_context)(OM_uint32 *, gss_cred_id_t, + gss_ctx_id_t *, gss_name_t, + gss_OID, + OM_uint32, OM_uint32, + gss_channel_bindings_t, + gss_buffer_t, gss_OID *, + gss_buffer_t, + OM_uint32 *, OM_uint32 *) + = get_gfun(gsslib, "gss_init_sec_context"); + OM_uint32 KRB5_CALLCONV (*import_name)(OM_uint32 *, gss_buffer_t, + gss_OID, gss_name_t *) + = get_gfun(gsslib, "gss_import_name"); + OM_uint32 KRB5_CALLCONV (*release_buffer)(OM_uint32 *, gss_buffer_t) + = get_gfun(gsslib, "gss_release_buffer"); + OM_uint32 KRB5_CALLCONV (*release_name)(OM_uint32 *, gss_name_t *) + = get_gfun(gsslib, "gss_release_name"); + OM_uint32 KRB5_CALLCONV (*delete_sec_context)(OM_uint32 *, + gss_ctx_id_t *, + gss_buffer_t) + = get_gfun(gsslib, "gss_delete_sec_context"); + + OM_uint32 gmaj, gmin; + OM_uint32 retflags; + gss_ctx_id_t gctx = GSS_C_NO_CONTEXT; + gss_buffer_desc token; + gss_name_t target; + static gss_buffer_desc target_name_buf = { + 9, "x@mit.edu" + }; + static gss_OID_desc service_name = { + 10, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04" + }; + + CALLING(gss_import_name); + gmaj = import_name(&gmin, &target_name_buf, &service_name, &target); + DONE(); + if (gmaj != GSS_S_COMPLETE) { + fprintf(stderr, + "import_name reports error major 0x%lx minor 0x%lx(%ld)\n", + (unsigned long) gmaj, (unsigned long) gmin, + (signed long) gmin); + exit(1); + } + /* This will probably get different errors, depending on + whether we have tickets at the time. Doesn't matter much, + we're ignoring the error and testing whether we're doing + cleanup properly. (Though the internal cleanup needed in + the two cases might be different.) */ + CALLING(gss_init_sec_context); + gmaj = init_sec_context(&gmin, GSS_C_NO_CREDENTIAL, &gctx, target, + GSS_C_NULL_OID, 0, 0, NULL, GSS_C_NO_BUFFER, + NULL, &token, &retflags, NULL); + DONE(); + /* Ignore success/failure indication. */ + if (token.length) { + CALLING(gss_release_buffer); + release_buffer(&gmin, &token); + DONE(); + } + CALLING(gss_release_name); + release_name(&gmin, &target); + DONE(); + if (gctx != GSS_C_NO_CONTEXT) { + CALLING(gss_delete_sec_context); + delete_sec_context(&gmin, gctx, GSS_C_NO_BUFFER); + DONE(); + } + } + do_close(gsslib); + + /* Test gssapi_krb5 with com_err already loaded, then unload + com_err first. */ + celib = do_open("com_err", "3.0", 1); + gsslib = do_open("gssapi_krb5", "2.2", 1); + { + OM_uint32 KRB5_CALLCONV (*init_sec_context)(OM_uint32 *, gss_cred_id_t, + gss_ctx_id_t *, gss_name_t, + gss_OID, + OM_uint32, OM_uint32, + gss_channel_bindings_t, + gss_buffer_t, gss_OID *, + gss_buffer_t, + OM_uint32 *, OM_uint32 *) + = get_gfun(gsslib, "gss_init_sec_context"); + OM_uint32 KRB5_CALLCONV (*import_name)(OM_uint32 *, gss_buffer_t, + gss_OID, gss_name_t *) + = get_gfun(gsslib, "gss_import_name"); + OM_uint32 KRB5_CALLCONV (*release_buffer)(OM_uint32 *, gss_buffer_t) + = get_gfun(gsslib, "gss_release_buffer"); + OM_uint32 KRB5_CALLCONV (*release_name)(OM_uint32 *, gss_name_t *) + = get_gfun(gsslib, "gss_release_name"); + OM_uint32 KRB5_CALLCONV (*delete_sec_context)(OM_uint32 *, + gss_ctx_id_t *, + gss_buffer_t) + = get_gfun(gsslib, "gss_delete_sec_context"); + + OM_uint32 gmaj, gmin; + OM_uint32 retflags; + gss_ctx_id_t gctx = GSS_C_NO_CONTEXT; + gss_buffer_desc token; + gss_name_t target; + static gss_buffer_desc target_name_buf = { + 9, "x@mit.edu" + }; + static gss_OID_desc service_name = { + 10, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04" + }; + + CALLING(gss_import_name); + gmaj = import_name(&gmin, &target_name_buf, &service_name, &target); + DONE(); + if (gmaj != GSS_S_COMPLETE) { + fprintf(stderr, + "import_name reports error major 0x%lx minor 0x%lx(%ld)\n", + (unsigned long) gmaj, (unsigned long) gmin, + (signed long) gmin); + exit(1); + } + /* This will probably get different errors, depending on + whether we have tickets at the time. Doesn't matter much, + we're ignoring the error and testing whether we're doing + cleanup properly. (Though the internal cleanup needed in + the two cases might be different.) */ + CALLING(gss_init_sec_context); + gmaj = init_sec_context(&gmin, GSS_C_NO_CREDENTIAL, &gctx, target, + GSS_C_NULL_OID, 0, 0, NULL, GSS_C_NO_BUFFER, + NULL, &token, &retflags, NULL); + DONE(); + /* Ignore success/failure indication. */ + if (token.length) { + CALLING(gss_release_buffer); + release_buffer(&gmin, &token); + DONE(); + } + CALLING(gss_release_name); + release_name(&gmin, &target); + DONE(); + if (gctx != GSS_C_NO_CONTEXT) { + CALLING(gss_delete_sec_context); + delete_sec_context(&gmin, gctx, GSS_C_NO_BUFFER); + DONE(); + } + } + do_close(celib); + do_close(gsslib); + + return 0; +} diff --git a/krb5-1.21.3/src/tests/softpkcs11/Makefile.in b/krb5-1.21.3/src/tests/softpkcs11/Makefile.in new file mode 100644 index 00000000..e8967815 --- /dev/null +++ b/krb5-1.21.3/src/tests/softpkcs11/Makefile.in @@ -0,0 +1,21 @@ +mydir=tests$(S)softpkcs11 +BUILDTOP=$(REL)..$(S).. + +LOCALINCLUDES = -I$(top_srcdir)/plugins/preauth/pkinit + +LIBBASE=softpkcs11 +LIBMAJOR=0 +LIBMINOR=0 + +SHLIB_EXPLIBS=$(SUPPORT_LIB) -lcrypto +SHLIB_EXPDEPS=$(SUPPORT_DEPLIB) + +STLIBOBJS=main.o + +SRCS=$(srcdir)/main.c + +all-unix: all-libs +clean-unix:: clean-libs clean-libobjs + +@libnover_frag@ +@libobj_frag@ diff --git a/krb5-1.21.3/src/tests/softpkcs11/deps b/krb5-1.21.3/src/tests/softpkcs11/deps new file mode 100644 index 00000000..1e82d957 --- /dev/null +++ b/krb5-1.21.3/src/tests/softpkcs11/deps @@ -0,0 +1,6 @@ +# +# Generated makefile dependencies follow. +# +main.so main.po $(OUTPRE)main.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/plugins/preauth/pkinit/pkcs11.h main.c diff --git a/krb5-1.21.3/src/tests/softpkcs11/main.c b/krb5-1.21.3/src/tests/softpkcs11/main.c new file mode 100644 index 00000000..82b05ff0 --- /dev/null +++ b/krb5-1.21.3/src/tests/softpkcs11/main.c @@ -0,0 +1,2107 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright (c) 2004-2006, Stockholms universitet + * (Stockholm University, Stockholm Sweden) + * 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 university 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 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. + */ + +#include "k5-platform.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define EVP_PKEY_get0_RSA(key) ((key)->pkey.rsa) +#define RSA_PKCS1_OpenSSL RSA_PKCS1_SSLeay +#define RSA_get0_key compat_rsa_get0_key +static void +compat_rsa_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e, + const BIGNUM **d) +{ + if (n != NULL) + *n = rsa->n; + if (e != NULL) + *e = rsa->e; + if (d != NULL) + *d = rsa->d; +} +#endif + +#define OPENSSL_ASN1_MALLOC_ENCODE(T, B, BL, S, R) \ + { \ + unsigned char *p; \ + (BL) = i2d_##T((S), NULL); \ + if ((BL) <= 0) { \ + (R) = EINVAL; \ + } else { \ + (B) = malloc((BL)); \ + if ((B) == NULL) { \ + (R) = ENOMEM; \ + } else { \ + p = (B); \ + (R) = 0; \ + (BL) = i2d_##T((S), &p); \ + if ((BL) <= 0) { \ + free((B)); \ + (B) = NULL; \ + (R) = EINVAL; \ + } \ + } \ + } \ + } + +/* RCSID("$Id: main.c,v 1.24 2006/01/11 12:42:53 lha Exp $"); */ + +#define OBJECT_ID_MASK 0xfff +#define HANDLE_OBJECT_ID(h) ((h) & OBJECT_ID_MASK) +#define OBJECT_ID(obj) HANDLE_OBJECT_ID((obj)->object_handle) + +struct st_attr { + CK_ATTRIBUTE attribute; + int secret; +}; + +struct st_object { + CK_OBJECT_HANDLE object_handle; + struct st_attr *attrs; + int num_attributes; + enum { + STO_T_CERTIFICATE, + STO_T_PRIVATE_KEY, + STO_T_PUBLIC_KEY + } type; + union { + X509 *cert; + EVP_PKEY *public_key; + struct { + char *file; + EVP_PKEY *key; + X509 *cert; + } private_key; + } u; +}; + +static struct soft_token { + CK_VOID_PTR application; + CK_NOTIFY notify; + struct { + struct st_object **objs; + int num_objs; + } object; + struct { + int hardware_slot; + int app_error_fatal; + int login_done; + } flags; + int open_sessions; + struct session_state { + CK_SESSION_HANDLE session_handle; + + struct { + CK_ATTRIBUTE *attributes; + CK_ULONG num_attributes; + int next_object; + } find; + + int encrypt_object; + CK_MECHANISM_PTR encrypt_mechanism; + int decrypt_object; + CK_MECHANISM_PTR decrypt_mechanism; + int sign_object; + CK_MECHANISM_PTR sign_mechanism; + int verify_object; + CK_MECHANISM_PTR verify_mechanism; + int digest_object; + } state[10]; +#define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0])) + FILE *logfile; + CK_SESSION_HANDLE next_session_handle; +} soft_token; + +static void +application_error(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + if (soft_token.flags.app_error_fatal) + abort(); +} + +static void +st_logf(const char *fmt, ...) +{ + va_list ap; + if (soft_token.logfile == NULL) + return; + va_start(ap, fmt); + vfprintf(soft_token.logfile, fmt, ap); + va_end(ap); + fflush(soft_token.logfile); +} + +static void +snprintf_fill(char *str, int size, char fillchar, const char *fmt, ...) +{ + int len; + va_list ap; + va_start(ap, fmt); + len = vsnprintf(str, size, fmt, ap); + va_end(ap); + if (len < 0 || len > size) + return; + while(len < size) + str[len++] = fillchar; +} + +#ifndef TEST_APP +#define printf error_use_st_logf +#endif + +#define VERIFY_SESSION_HANDLE(s, state) \ + { \ + CK_RV vshret; \ + vshret = verify_session_handle(s, state); \ + if (vshret != CKR_OK) { \ + /* return CKR_OK */; \ + } \ + } + +static CK_RV +verify_session_handle(CK_SESSION_HANDLE hSession, + struct session_state **state) +{ + size_t i; + + for (i = 0; i < MAX_NUM_SESSION; i++){ + if (soft_token.state[i].session_handle == hSession) + break; + } + if (i == MAX_NUM_SESSION) { + application_error("use of invalid handle: 0x%08lx\n", + (unsigned long)hSession); + return CKR_SESSION_HANDLE_INVALID; + } + if (state) + *state = &soft_token.state[i]; + return CKR_OK; +} + +static CK_RV +object_handle_to_object(CK_OBJECT_HANDLE handle, + struct st_object **object) +{ + int i = HANDLE_OBJECT_ID(handle); + + *object = NULL; + if (i >= soft_token.object.num_objs) + return CKR_ARGUMENTS_BAD; + if (soft_token.object.objs[i] == NULL) + return CKR_ARGUMENTS_BAD; + if (soft_token.object.objs[i]->object_handle != handle) + return CKR_ARGUMENTS_BAD; + *object = soft_token.object.objs[i]; + return CKR_OK; +} + +static int +attributes_match(const struct st_object *obj, + const CK_ATTRIBUTE *attributes, + CK_ULONG num_attributes) +{ + CK_ULONG i; + int j; + st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj)); + + for (i = 0; i < num_attributes; i++) { + int match = 0; + for (j = 0; j < obj->num_attributes; j++) { + if (attributes[i].type == obj->attrs[j].attribute.type && + attributes[i].ulValueLen == obj->attrs[j].attribute.ulValueLen && + memcmp(attributes[i].pValue, obj->attrs[j].attribute.pValue, + attributes[i].ulValueLen) == 0) { + match = 1; + break; + } + } + if (match == 0) { + st_logf("type %lu attribute have no match\n", attributes[i].type); + return 0; + } + } + st_logf("attribute matches\n"); + return 1; +} + +static void +print_attributes(const CK_ATTRIBUTE *attributes, + CK_ULONG num_attributes) +{ + CK_ULONG i; + + st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes); + + for (i = 0; i < num_attributes; i++) { + st_logf(" type: "); + switch (attributes[i].type) { + case CKA_TOKEN: { + CK_BBOOL *ck_true; + if (attributes[i].ulValueLen != sizeof(CK_BBOOL)) { + application_error("token attribute wrong length\n"); + break; + } + ck_true = attributes[i].pValue; + st_logf("token: %s", *ck_true ? "TRUE" : "FALSE"); + break; + } + case CKA_CLASS: { + CK_OBJECT_CLASS *class; + if (attributes[i].ulValueLen != sizeof(CK_ULONG)) { + application_error("class attribute wrong length\n"); + break; + } + class = attributes[i].pValue; + st_logf("class "); + switch (*class) { + case CKO_CERTIFICATE: + st_logf("certificate"); + break; + case CKO_PUBLIC_KEY: + st_logf("public key"); + break; + case CKO_PRIVATE_KEY: + st_logf("private key"); + break; + case CKO_SECRET_KEY: + st_logf("secret key"); + break; + case CKO_DOMAIN_PARAMETERS: + st_logf("domain parameters"); + break; + default: + st_logf("[class %lx]", (long unsigned)*class); + break; + } + break; + } + case CKA_PRIVATE: + st_logf("private"); + break; + case CKA_LABEL: + st_logf("label"); + break; + case CKA_APPLICATION: + st_logf("application"); + break; + case CKA_VALUE: + st_logf("value"); + break; + case CKA_ID: + st_logf("id"); + break; + default: + st_logf("[unknown 0x%08lx]", (unsigned long)attributes[i].type); + break; + } + st_logf("\n"); + } +} + +static void +free_st_object(struct st_object *o) +{ + int i; + + for (i = 0; i < o->num_attributes; i++) + free(o->attrs[i].attribute.pValue); + free(o->attrs); + if (o->type == STO_T_CERTIFICATE) { + X509_free(o->u.cert); + } else if (o->type == STO_T_PRIVATE_KEY) { + free(o->u.private_key.file); + EVP_PKEY_free(o->u.private_key.key); + X509_free(o->u.private_key.cert); + } else if (o->type == STO_T_PUBLIC_KEY) { + EVP_PKEY_free(o->u.public_key); + } + free(o); +} + +static struct st_object * +add_st_object(void) +{ + struct st_object *o, **objs; + + objs = realloc(soft_token.object.objs, + (soft_token.object.num_objs + 1) * + sizeof(soft_token.object.objs[0])); + if (objs == NULL) + return NULL; + soft_token.object.objs = objs; + + o = calloc(1, sizeof(*o)); + if (o == NULL) + return NULL; + o->attrs = NULL; + o->num_attributes = 0; + o->object_handle = soft_token.object.num_objs; + + soft_token.object.objs[soft_token.object.num_objs++] = o; + return o; +} + +static CK_RV +add_object_attribute(struct st_object *o, + int secret, + CK_ATTRIBUTE_TYPE type, + CK_VOID_PTR pValue, + CK_ULONG ulValueLen) +{ + struct st_attr *a; + int i; + + i = o->num_attributes; + a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0])); + if (a == NULL) + return CKR_DEVICE_MEMORY; + o->attrs = a; + o->attrs[i].secret = secret; + o->attrs[i].attribute.type = type; + o->attrs[i].attribute.pValue = malloc(ulValueLen); + if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0) + return CKR_DEVICE_MEMORY; + memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen); + o->attrs[i].attribute.ulValueLen = ulValueLen; + o->num_attributes++; + + return CKR_OK; +} + +#ifdef HAVE_EVP_PKEY_GET_BN_PARAM + +/* Declare owner pointers since EVP_PKEY_get_bn_param() gives us copies. */ +#define DECLARE_BIGNUM(name) BIGNUM *name = NULL +#define RELEASE_BIGNUM(bn) BN_clear_free(bn) +static CK_RV +get_bignums(EVP_PKEY *key, BIGNUM **n, BIGNUM **e) +{ + if (EVP_PKEY_get_bn_param(key, "n", n) == 0 || + EVP_PKEY_get_bn_param(key, "e", e) == 0) + return CKR_DEVICE_ERROR; + + return CKR_OK; +} + +#else + +/* Declare const pointers since the old API gives us aliases. */ +#define DECLARE_BIGNUM(name) const BIGNUM *name +#define RELEASE_BIGNUM(bn) +static CK_RV +get_bignums(EVP_PKEY *key, const BIGNUM **n, const BIGNUM **e) +{ + const RSA *rsa; + + rsa = EVP_PKEY_get0_RSA(key); + RSA_get0_key(rsa, n, e, NULL); + + return CKR_OK; +} + +#endif + +static CK_RV +add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key) +{ + CK_BYTE *modulus = NULL, *exponent = 0; + size_t modulus_len = 0, exponent_len = 0; + CK_ULONG modulus_bits = 0; + CK_RV ret; + DECLARE_BIGNUM(n); + DECLARE_BIGNUM(e); + + if (key_type != CKK_RSA) + abort(); + + ret = get_bignums(key, &n, &e); + if (ret != CKR_OK) + goto done; + + modulus_bits = BN_num_bits(n); + modulus_len = BN_num_bytes(n); + exponent_len = BN_num_bytes(e); + + modulus = malloc(modulus_len); + exponent = malloc(exponent_len); + if (modulus == NULL || exponent == NULL) { + ret = CKR_DEVICE_MEMORY; + goto done; + } + + BN_bn2bin(n, modulus); + BN_bn2bin(e, exponent); + + add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len); + add_object_attribute(o, 0, CKA_MODULUS_BITS, &modulus_bits, + sizeof(modulus_bits)); + add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT, exponent, exponent_len); + + ret = CKR_OK; +done: + free(modulus); + free(exponent); + RELEASE_BIGNUM(n); + RELEASE_BIGNUM(e); + return ret; +} + +static int +pem_callback(char *buf, int num, int w, void *key) +{ + return -1; +} + + +static CK_RV +add_certificate(char *label, + const char *cert_file, + const char *private_key_file, + char *id, + int anchor) +{ + struct st_object *o = NULL; + CK_BBOOL bool_true = CK_TRUE; + CK_BBOOL bool_false = CK_FALSE; + CK_OBJECT_CLASS c; + CK_CERTIFICATE_TYPE cert_type = CKC_X_509; + CK_KEY_TYPE key_type; + CK_MECHANISM_TYPE mech_type; + void *cert_data = NULL; + size_t cert_length; + void *subject_data = NULL; + size_t subject_length; + void *issuer_data = NULL; + size_t issuer_length; + void *serial_data = NULL; + size_t serial_length; + CK_RV ret = CKR_GENERAL_ERROR; + X509 *cert; + EVP_PKEY *public_key; + + size_t id_len = strlen(id); + + { + FILE *f; + + f = fopen(cert_file, "r"); + if (f == NULL) { + st_logf("failed to open file %s\n", cert_file); + return CKR_GENERAL_ERROR; + } + + cert = PEM_read_X509(f, NULL, NULL, NULL); + fclose(f); + if (cert == NULL) { + st_logf("failed reading PEM cert\n"); + return CKR_GENERAL_ERROR; + } + + OPENSSL_ASN1_MALLOC_ENCODE(X509, cert_data, cert_length, cert, ret); + if (ret) + goto out; + + OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, issuer_data, issuer_length, + X509_get_issuer_name(cert), ret); + if (ret) + goto out; + + OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, subject_data, subject_length, + X509_get_subject_name(cert), ret); + if (ret) + goto out; + + OPENSSL_ASN1_MALLOC_ENCODE(ASN1_INTEGER, serial_data, serial_length, + X509_get_serialNumber(cert), ret); + if (ret) + goto out; + + } + + st_logf("done parsing, adding to internal structure\n"); + + o = add_st_object(); + if (o == NULL) { + ret = CKR_DEVICE_MEMORY; + goto out; + } + o->type = STO_T_CERTIFICATE; + o->u.cert = X509_dup(cert); + if (o->u.cert == NULL) { + ret = CKR_DEVICE_MEMORY; + goto out; + } + public_key = X509_get_pubkey(o->u.cert); + + switch (EVP_PKEY_base_id(public_key)) { + case EVP_PKEY_RSA: + key_type = CKK_RSA; + break; + case EVP_PKEY_DSA: + key_type = CKK_DSA; + break; + default: + st_logf("invalid key_type\n"); + ret = CKR_GENERAL_ERROR; + goto out; + } + + c = CKO_CERTIFICATE; + add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c)); + add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_LABEL, label, strlen(label)); + + add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type)); + add_object_attribute(o, 0, CKA_ID, id, id_len); + + add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length); + add_object_attribute(o, 0, CKA_ISSUER, issuer_data, issuer_length); + add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data, serial_length); + add_object_attribute(o, 0, CKA_VALUE, cert_data, cert_length); + if (anchor) + add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true)); + else + add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false)); + + st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o)); + + o = add_st_object(); + if (o == NULL) { + ret = CKR_DEVICE_MEMORY; + goto out; + } + o->type = STO_T_PUBLIC_KEY; + o->u.public_key = public_key; + + c = CKO_PUBLIC_KEY; + add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c)); + add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_LABEL, label, strlen(label)); + + add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type)); + add_object_attribute(o, 0, CKA_ID, id, id_len); + add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */ + add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */ + add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false)); + mech_type = CKM_RSA_X_509; + add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type)); + + add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length); + add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true)); + + add_pubkey_info(o, key_type, public_key); + + st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o)); + + if (private_key_file) { + CK_FLAGS flags; + FILE *f; + + o = add_st_object(); + if (o == NULL) { + ret = CKR_DEVICE_MEMORY; + goto out; + } + o->type = STO_T_PRIVATE_KEY; + o->u.private_key.file = strdup(private_key_file); + o->u.private_key.key = NULL; + + o->u.private_key.cert = X509_dup(cert); + if (o->u.private_key.cert == NULL) { + ret = CKR_DEVICE_MEMORY; + goto out; + } + + c = CKO_PRIVATE_KEY; + add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c)); + add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_LABEL, label, strlen(label)); + + add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type)); + add_object_attribute(o, 0, CKA_ID, id, id_len); + add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */ + add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */ + add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false)); + mech_type = CKM_RSA_X_509; + add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type)); + + add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length); + add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true)); + flags = 0; + add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags)); + + add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false)); + add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true)); + add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false)); + + add_pubkey_info(o, key_type, public_key); + + f = fopen(private_key_file, "r"); + if (f == NULL) { + st_logf("failed to open private key\n"); + return CKR_GENERAL_ERROR; + } + + o->u.private_key.key = PEM_read_PrivateKey(f, NULL, pem_callback, NULL); + fclose(f); + if (o->u.private_key.key == NULL) { + st_logf("failed to read private key a startup\n"); + /* don't bother with this failure for now, + fix it at C_Login time */; + } else { + /* XXX verify keytype */ + + if (X509_check_private_key(cert, o->u.private_key.key) != 1) { + EVP_PKEY_free(o->u.private_key.key); + o->u.private_key.key = NULL; + st_logf("private key doesn't verify\n"); + } else { + st_logf("private key usable\n"); + soft_token.flags.login_done = 1; + } + } + } + + ret = CKR_OK; +out: + if (ret != CKR_OK) { + st_logf("something went wrong when adding cert!\n"); + + /* XXX wack o */; + } + free(cert_data); + free(serial_data); + free(issuer_data); + free(subject_data); + X509_free(cert); + + return ret; +} + +static void +find_object_final(struct session_state *state) +{ + if (state->find.attributes) { + CK_ULONG i; + + for (i = 0; i < state->find.num_attributes; i++) { + if (state->find.attributes[i].pValue) + free(state->find.attributes[i].pValue); + } + free(state->find.attributes); + state->find.attributes = NULL; + state->find.num_attributes = 0; + state->find.next_object = -1; + } +} + +static void +reset_crypto_state(struct session_state *state) +{ + state->encrypt_object = -1; + if (state->encrypt_mechanism) + free(state->encrypt_mechanism); + state->encrypt_mechanism = NULL_PTR; + state->decrypt_object = -1; + if (state->decrypt_mechanism) + free(state->decrypt_mechanism); + state->decrypt_mechanism = NULL_PTR; + state->sign_object = -1; + if (state->sign_mechanism) + free(state->sign_mechanism); + state->sign_mechanism = NULL_PTR; + state->verify_object = -1; + if (state->verify_mechanism) + free(state->verify_mechanism); + state->verify_mechanism = NULL_PTR; + state->digest_object = -1; +} + +static void +close_session(struct session_state *state) +{ + if (state->find.attributes) { + application_error("application didn't do C_FindObjectsFinal\n"); + find_object_final(state); + } + + state->session_handle = CK_INVALID_HANDLE; + soft_token.application = NULL_PTR; + soft_token.notify = NULL_PTR; + reset_crypto_state(state); +} + +static const char * +has_session(void) +{ + return soft_token.open_sessions > 0 ? "yes" : "no"; +} + +static void +read_conf_file(const char *fn) +{ + char buf[1024], *cert, *key, *id, *label, *s, *p; + int anchor; + FILE *f; + + f = fopen(fn, "r"); + if (f == NULL) { + st_logf("can't open configuration file %s\n", fn); + return; + } + + while(fgets(buf, sizeof(buf), f) != NULL) { + buf[strcspn(buf, "\n")] = '\0'; + + anchor = 0; + + st_logf("line: %s\n", buf); + + p = buf; + while (isspace(*p)) + p++; + if (*p == '#') + continue; + while (isspace(*p)) + p++; + + s = NULL; + id = strtok_r(p, "\t", &s); + if (id == NULL) + continue; + label = strtok_r(NULL, "\t", &s); + if (label == NULL) + continue; + cert = strtok_r(NULL, "\t", &s); + if (cert == NULL) + continue; + key = strtok_r(NULL, "\t", &s); + + /* XXX */ + if (strcmp(id, "anchor") == 0) { + id = "\x00\x00"; + anchor = 1; + } + + st_logf("adding: %s\n", label); + + add_certificate(label, cert, key, id, anchor); + } + + fclose(f); +} + +static CK_RV +func_not_supported(void) +{ + st_logf("function not supported\n"); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +static char * +get_rcfilename() +{ + struct passwd *pw; + const char *home = NULL; + char *fn; + + if (getuid() == geteuid()) { + fn = getenv("SOFTPKCS11RC"); + if (fn != NULL) + return strdup(fn); + + home = getenv("HOME"); + } + + if (home == NULL) { + pw = getpwuid(getuid()); + if (pw != NULL) + home = pw->pw_dir; + } + + if (home == NULL) + return strdup("/etc/soft-token.rc"); + + if (asprintf(&fn, "%s/.soft-token.rc", home) < 0) + return NULL; + return fn; +} + +CK_RV +C_Initialize(CK_VOID_PTR a) +{ + CK_C_INITIALIZE_ARGS_PTR args = a; + size_t i; + char *fn; + + st_logf("Initialize\n"); + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + for (i = 0; i < MAX_NUM_SESSION; i++) { + soft_token.state[i].session_handle = CK_INVALID_HANDLE; + soft_token.state[i].find.attributes = NULL; + soft_token.state[i].find.num_attributes = 0; + soft_token.state[i].find.next_object = -1; + reset_crypto_state(&soft_token.state[i]); + } + + soft_token.flags.hardware_slot = 1; + soft_token.flags.app_error_fatal = 0; + soft_token.flags.login_done = 0; + + soft_token.object.objs = NULL; + soft_token.object.num_objs = 0; + + soft_token.logfile = NULL; +#if 0 + soft_token.logfile = stdout; +#endif +#if 0 + soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a"); +#endif + + if (a != NULL_PTR) { + st_logf("\tCreateMutex:\t%p\n", args->CreateMutex); + st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex); + st_logf("\tLockMutext\t%p\n", args->LockMutex); + st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex); + st_logf("\tFlags\t%04x\n", (unsigned int)args->flags); + } + + soft_token.next_session_handle = 1; + + fn = get_rcfilename(); + if (fn == NULL) + return CKR_DEVICE_MEMORY; + read_conf_file(fn); + free(fn); + return CKR_OK; +} + +CK_RV +C_Finalize(CK_VOID_PTR args) +{ + size_t i; + int j; + + st_logf("Finalize\n"); + + for (i = 0; i < MAX_NUM_SESSION; i++) { + if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) { + application_error("application finalized without " + "closing session\n"); + close_session(&soft_token.state[i]); + } + } + + for (j = 0; j < soft_token.object.num_objs; j++) + free_st_object(soft_token.object.objs[j]); + free(soft_token.object.objs); + soft_token.object.objs = NULL; + soft_token.object.num_objs = 0; + + return CKR_OK; +} + +CK_RV +C_GetInfo(CK_INFO_PTR args) +{ + st_logf("GetInfo\n"); + + memset(args, 17, sizeof(*args)); + args->cryptokiVersion.major = 2; + args->cryptokiVersion.minor = 10; + snprintf_fill((char *)args->manufacturerID, + sizeof(args->manufacturerID), + ' ', + "SoftToken"); + snprintf_fill((char *)args->libraryDescription, + sizeof(args->libraryDescription), ' ', + "SoftToken"); + args->libraryVersion.major = 1; + args->libraryVersion.minor = 8; + + return CKR_OK; +} + +extern CK_FUNCTION_LIST funcs; + +CK_RV +C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) +{ + *ppFunctionList = &funcs; + return CKR_OK; +} + +CK_RV +C_GetSlotList(CK_BBOOL tokenPresent, + CK_SLOT_ID_PTR pSlotList, + CK_ULONG_PTR pulCount) +{ + st_logf("GetSlotList: %s\n", + tokenPresent ? "tokenPresent" : "token not Present"); + if (pSlotList) + pSlotList[0] = 1; + *pulCount = 1; + return CKR_OK; +} + +CK_RV +C_GetSlotInfo(CK_SLOT_ID slotID, + CK_SLOT_INFO_PTR pInfo) +{ + st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session()); + + memset(pInfo, 18, sizeof(*pInfo)); + + if (slotID != 1) + return CKR_ARGUMENTS_BAD; + + snprintf_fill((char *)pInfo->slotDescription, + sizeof(pInfo->slotDescription), + ' ', + "SoftToken (slot)"); + snprintf_fill((char *)pInfo->manufacturerID, + sizeof(pInfo->manufacturerID), + ' ', + "SoftToken (slot)"); + pInfo->flags = CKF_TOKEN_PRESENT; + if (soft_token.flags.hardware_slot) + pInfo->flags |= CKF_HW_SLOT; + pInfo->hardwareVersion.major = 1; + pInfo->hardwareVersion.minor = 0; + pInfo->firmwareVersion.major = 1; + pInfo->firmwareVersion.minor = 0; + + return CKR_OK; +} + +CK_RV +C_GetTokenInfo(CK_SLOT_ID slotID, + CK_TOKEN_INFO_PTR pInfo) +{ + st_logf("GetTokenInfo: %s\n", has_session()); + + memset(pInfo, 19, sizeof(*pInfo)); + + snprintf_fill((char *)pInfo->label, + sizeof(pInfo->label), + ' ', + "SoftToken (token)"); + snprintf_fill((char *)pInfo->manufacturerID, + sizeof(pInfo->manufacturerID), + ' ', + "SoftToken (token)"); + snprintf_fill((char *)pInfo->model, + sizeof(pInfo->model), + ' ', + "SoftToken (token)"); + snprintf_fill((char *)pInfo->serialNumber, + sizeof(pInfo->serialNumber), + ' ', + "4711"); + pInfo->flags = + CKF_TOKEN_INITIALIZED | + CKF_USER_PIN_INITIALIZED; + + if (soft_token.flags.login_done == 0) + pInfo->flags |= CKF_LOGIN_REQUIRED; + + /* CFK_RNG | + CKF_RESTORE_KEY_NOT_NEEDED | + */ + pInfo->ulMaxSessionCount = MAX_NUM_SESSION; + pInfo->ulSessionCount = soft_token.open_sessions; + pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION; + pInfo->ulRwSessionCount = soft_token.open_sessions; + pInfo->ulMaxPinLen = 1024; + pInfo->ulMinPinLen = 0; + pInfo->ulTotalPublicMemory = 4711; + pInfo->ulFreePublicMemory = 4712; + pInfo->ulTotalPrivateMemory = 4713; + pInfo->ulFreePrivateMemory = 4714; + pInfo->hardwareVersion.major = 2; + pInfo->hardwareVersion.minor = 0; + pInfo->firmwareVersion.major = 2; + pInfo->firmwareVersion.minor = 0; + + return CKR_OK; +} + +CK_RV +C_GetMechanismList(CK_SLOT_ID slotID, + CK_MECHANISM_TYPE_PTR pMechanismList, + CK_ULONG_PTR pulCount) +{ + st_logf("GetMechanismList\n"); + + *pulCount = 2; + if (pMechanismList == NULL_PTR) + return CKR_OK; + pMechanismList[0] = CKM_RSA_X_509; + pMechanismList[1] = CKM_RSA_PKCS; + + return CKR_OK; +} + +CK_RV +C_GetMechanismInfo(CK_SLOT_ID slotID, + CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR pInfo) +{ + st_logf("GetMechanismInfo: slot %d type: %d\n", + (int)slotID, (int)type); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_InitToken(CK_SLOT_ID slotID, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen, + CK_UTF8CHAR_PTR pLabel) +{ + st_logf("InitToken: slot %d\n", (int)slotID); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_OpenSession(CK_SLOT_ID slotID, + CK_FLAGS flags, + CK_VOID_PTR pApplication, + CK_NOTIFY Notify, + CK_SESSION_HANDLE_PTR phSession) +{ + size_t i; + + st_logf("OpenSession: slot: %d\n", (int)slotID); + + if (soft_token.open_sessions == MAX_NUM_SESSION) + return CKR_SESSION_COUNT; + + soft_token.application = pApplication; + soft_token.notify = Notify; + + for (i = 0; i < MAX_NUM_SESSION; i++) + if (soft_token.state[i].session_handle == CK_INVALID_HANDLE) + break; + if (i == MAX_NUM_SESSION) + abort(); + + soft_token.open_sessions++; + + soft_token.state[i].session_handle = soft_token.next_session_handle++; + *phSession = soft_token.state[i].session_handle; + + return CKR_OK; +} + +CK_RV +C_CloseSession(CK_SESSION_HANDLE hSession) +{ + struct session_state *state; + st_logf("CloseSession\n"); + + if (verify_session_handle(hSession, &state) != CKR_OK) + application_error("closed session not open"); + else + close_session(state); + + return CKR_OK; +} + +CK_RV +C_CloseAllSessions(CK_SLOT_ID slotID) +{ + size_t i; + + st_logf("CloseAllSessions\n"); + + for (i = 0; i < MAX_NUM_SESSION; i++) + if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) + close_session(&soft_token.state[i]); + + return CKR_OK; +} + +CK_RV +C_GetSessionInfo(CK_SESSION_HANDLE hSession, + CK_SESSION_INFO_PTR pInfo) +{ + st_logf("GetSessionInfo\n"); + + VERIFY_SESSION_HANDLE(hSession, NULL); + + memset(pInfo, 20, sizeof(*pInfo)); + + pInfo->slotID = 1; + if (soft_token.flags.login_done) + pInfo->state = CKS_RO_USER_FUNCTIONS; + else + pInfo->state = CKS_RO_PUBLIC_SESSION; + pInfo->flags = CKF_SERIAL_SESSION; + pInfo->ulDeviceError = 0; + + return CKR_OK; +} + +CK_RV +C_Login(CK_SESSION_HANDLE hSession, + CK_USER_TYPE userType, + CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen) +{ + char *pin = NULL; + int i; + + st_logf("Login\n"); + + VERIFY_SESSION_HANDLE(hSession, NULL); + + if (pPin != NULL_PTR) { + if (asprintf(&pin, "%.*s", (int)ulPinLen, pPin) < 0) + return CKR_DEVICE_MEMORY; + st_logf("type: %d password: %s\n", (int)userType, pin); + } + + for (i = 0; i < soft_token.object.num_objs; i++) { + struct st_object *o = soft_token.object.objs[i]; + FILE *f; + + if (o->type != STO_T_PRIVATE_KEY) + continue; + + if (o->u.private_key.key) + continue; + + f = fopen(o->u.private_key.file, "r"); + if (f == NULL) { + st_logf("can't open private file: %s\n", o->u.private_key.file); + continue; + } + + o->u.private_key.key = PEM_read_PrivateKey(f, NULL, NULL, pin); + fclose(f); + if (o->u.private_key.key == NULL) { + st_logf("failed to read key: %s error: %s\n", + o->u.private_key.file, + ERR_error_string(ERR_get_error(), NULL)); + /* just ignore failure */; + continue; + } + + /* XXX check keytype */ + + if (X509_check_private_key(o->u.private_key.cert, o->u.private_key.key) != 1) { + EVP_PKEY_free(o->u.private_key.key); + o->u.private_key.key = NULL; + st_logf("private key %s doesn't verify\n", o->u.private_key.file); + continue; + } + + soft_token.flags.login_done = 1; + } + free(pin); + + return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT; +} + +CK_RV +C_Logout(CK_SESSION_HANDLE hSession) +{ + st_logf("Logout\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_GetObjectSize(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ULONG_PTR pulSize) +{ + st_logf("GetObjectSize\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_GetAttributeValue(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount) +{ + struct session_state *state; + struct st_object *obj; + CK_ULONG i; + CK_RV ret; + int j; + + st_logf("GetAttributeValue: %lx\n", + (unsigned long)HANDLE_OBJECT_ID(hObject)); + VERIFY_SESSION_HANDLE(hSession, &state); + + if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) { + st_logf("object not found: %lx\n", + (unsigned long)HANDLE_OBJECT_ID(hObject)); + return ret; + } + + for (i = 0; i < ulCount; i++) { + st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate[i].type); + for (j = 0; j < obj->num_attributes; j++) { + if (obj->attrs[j].secret) { + pTemplate[i].ulValueLen = (CK_ULONG)-1; + break; + } + if (pTemplate[i].type == obj->attrs[j].attribute.type) { + if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) { + if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen) + memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue, + obj->attrs[j].attribute.ulValueLen); + } + pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen; + break; + } + } + if (j == obj->num_attributes) { + st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type); + pTemplate[i].ulValueLen = (CK_ULONG)-1; + } + + } + return CKR_OK; +} + +CK_RV +C_FindObjectsInit(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulCount) +{ + struct session_state *state; + + st_logf("FindObjectsInit\n"); + + VERIFY_SESSION_HANDLE(hSession, &state); + + if (state->find.next_object != -1) { + application_error("application didn't do C_FindObjectsFinal\n"); + find_object_final(state); + } + if (ulCount) { + CK_ULONG i; + + print_attributes(pTemplate, ulCount); + + state->find.attributes = + calloc(1, ulCount * sizeof(state->find.attributes[0])); + if (state->find.attributes == NULL) + return CKR_DEVICE_MEMORY; + for (i = 0; i < ulCount; i++) { + state->find.attributes[i].pValue = + malloc(pTemplate[i].ulValueLen); + if (state->find.attributes[i].pValue == NULL) { + find_object_final(state); + return CKR_DEVICE_MEMORY; + } + memcpy(state->find.attributes[i].pValue, + pTemplate[i].pValue, pTemplate[i].ulValueLen); + state->find.attributes[i].type = pTemplate[i].type; + state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen; + } + state->find.num_attributes = ulCount; + state->find.next_object = 0; + } else { + st_logf("find all objects\n"); + state->find.attributes = NULL; + state->find.num_attributes = 0; + state->find.next_object = 0; + } + + return CKR_OK; +} + +CK_RV +C_FindObjects(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE_PTR phObject, + CK_ULONG ulMaxObjectCount, + CK_ULONG_PTR pulObjectCount) +{ + struct session_state *state; + int i; + + st_logf("FindObjects\n"); + + VERIFY_SESSION_HANDLE(hSession, &state); + + if (state->find.next_object == -1) { + application_error("application didn't do C_FindObjectsInit\n"); + return CKR_ARGUMENTS_BAD; + } + if (ulMaxObjectCount == 0) { + application_error("application asked for 0 objects\n"); + return CKR_ARGUMENTS_BAD; + } + *pulObjectCount = 0; + for (i = state->find.next_object; i < soft_token.object.num_objs; i++) { + st_logf("FindObjects: %d\n", i); + state->find.next_object = i + 1; + if (attributes_match(soft_token.object.objs[i], + state->find.attributes, + state->find.num_attributes)) { + *phObject++ = soft_token.object.objs[i]->object_handle; + ulMaxObjectCount--; + (*pulObjectCount)++; + if (ulMaxObjectCount == 0) + break; + } + } + return CKR_OK; +} + +CK_RV +C_FindObjectsFinal(CK_SESSION_HANDLE hSession) +{ + struct session_state *state; + + st_logf("FindObjectsFinal\n"); + VERIFY_SESSION_HANDLE(hSession, &state); + find_object_final(state); + return CKR_OK; +} + +static CK_RV +commonInit(CK_ATTRIBUTE *attr_match, int attr_match_len, + const CK_MECHANISM_TYPE *mechs, int mechs_len, + const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, + struct st_object **o) +{ + CK_RV ret; + int i; + + *o = NULL; + if ((ret = object_handle_to_object(hKey, o)) != CKR_OK) + return ret; + + ret = attributes_match(*o, attr_match, attr_match_len); + if (!ret) { + application_error("called commonInit on key that doesn't " + "support required attr"); + return CKR_ARGUMENTS_BAD; + } + + for (i = 0; i < mechs_len; i++) + if (mechs[i] == pMechanism->mechanism) + break; + if (i == mechs_len) { + application_error("called mech (%08lx) not supported\n", + pMechanism->mechanism); + return CKR_ARGUMENTS_BAD; + } + return CKR_OK; +} + + +static CK_RV +dup_mechanism(CK_MECHANISM_PTR *dup, const CK_MECHANISM_PTR pMechanism) +{ + CK_MECHANISM_PTR p; + + p = malloc(sizeof(*p)); + if (p == NULL) + return CKR_DEVICE_MEMORY; + + if (*dup) + free(*dup); + *dup = p; + memcpy(p, pMechanism, sizeof(*p)); + + return CKR_OK; +} + + +CK_RV +C_EncryptInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + struct session_state *state; + CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 }; + CK_BBOOL bool_true = CK_TRUE; + CK_ATTRIBUTE attr[] = { + { CKA_ENCRYPT, &bool_true, sizeof(bool_true) } + }; + struct st_object *o; + CK_RV ret; + + st_logf("EncryptInit\n"); + VERIFY_SESSION_HANDLE(hSession, &state); + + ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), + mechs, sizeof(mechs)/sizeof(mechs[0]), + pMechanism, hKey, &o); + if (ret) + return ret; + + ret = dup_mechanism(&state->encrypt_mechanism, pMechanism); + if (ret == CKR_OK) + state->encrypt_object = OBJECT_ID(o); + + return ret; +} + +CK_RV +C_Encrypt(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pEncryptedData, + CK_ULONG_PTR pulEncryptedDataLen) +{ + struct session_state *state; + struct st_object *o; + void *buffer = NULL; + CK_RV ret; + size_t buffer_len = 0; + int padding; + EVP_PKEY_CTX *ctx = NULL; + + st_logf("Encrypt\n"); + + VERIFY_SESSION_HANDLE(hSession, &state); + + if (state->encrypt_object == -1) + return CKR_ARGUMENTS_BAD; + + o = soft_token.object.objs[state->encrypt_object]; + + if (o->u.public_key == NULL) { + st_logf("public key NULL\n"); + return CKR_ARGUMENTS_BAD; + } + + if (pulEncryptedDataLen == NULL) { + st_logf("pulEncryptedDataLen NULL\n"); + ret = CKR_ARGUMENTS_BAD; + goto out; + } + + if (pData == NULL) { + st_logf("data NULL\n"); + ret = CKR_ARGUMENTS_BAD; + goto out; + } + + switch(state->encrypt_mechanism->mechanism) { + case CKM_RSA_PKCS: + padding = RSA_PKCS1_PADDING; + break; + case CKM_RSA_X_509: + padding = RSA_NO_PADDING; + break; + default: + ret = CKR_FUNCTION_NOT_SUPPORTED; + goto out; + } + + ctx = EVP_PKEY_CTX_new(o->u.public_key, NULL); + if (ctx == NULL || EVP_PKEY_encrypt_init(ctx) <= 0 || + EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 || + EVP_PKEY_encrypt(ctx, NULL, &buffer_len, pData, ulDataLen) <= 0) { + ret = CKR_DEVICE_ERROR; + goto out; + } + + buffer = OPENSSL_malloc(buffer_len); + if (buffer == NULL) { + ret = CKR_DEVICE_MEMORY; + goto out; + } + + if (EVP_PKEY_encrypt(ctx, buffer, &buffer_len, pData, ulDataLen) <= 0) { + ret = CKR_DEVICE_ERROR; + goto out; + } + st_logf("Encrypt done\n"); + + if (pEncryptedData != NULL) + memcpy(pEncryptedData, buffer, buffer_len); + *pulEncryptedDataLen = buffer_len; + + ret = CKR_OK; +out: + OPENSSL_cleanse(buffer, buffer_len); + OPENSSL_free(buffer); + EVP_PKEY_CTX_free(ctx); + return ret; +} + +CK_RV +C_EncryptUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen) +{ + st_logf("EncryptUpdate\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + + +CK_RV +C_EncryptFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastEncryptedPart, + CK_ULONG_PTR pulLastEncryptedPartLen) +{ + st_logf("EncryptFinal\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + + +/* C_DecryptInit initializes a decryption operation. */ +CK_RV +C_DecryptInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + struct session_state *state; + CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 }; + CK_BBOOL bool_true = CK_TRUE; + CK_ATTRIBUTE attr[] = { + { CKA_DECRYPT, &bool_true, sizeof(bool_true) } + }; + struct st_object *o; + CK_RV ret; + + st_logf("DecryptInit\n"); + VERIFY_SESSION_HANDLE(hSession, &state); + + ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), + mechs, sizeof(mechs)/sizeof(mechs[0]), + pMechanism, hKey, &o); + if (ret) + return ret; + + ret = dup_mechanism(&state->decrypt_mechanism, pMechanism); + if (ret == CKR_OK) + state->decrypt_object = OBJECT_ID(o); + + return CKR_OK; +} + + +CK_RV +C_Decrypt(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, + CK_BYTE_PTR pData, + CK_ULONG_PTR pulDataLen) +{ + struct session_state *state; + struct st_object *o; + void *buffer = NULL; + CK_RV ret; + size_t buffer_len = 0; + int padding; + EVP_PKEY_CTX *ctx = NULL; + + st_logf("Decrypt\n"); + + VERIFY_SESSION_HANDLE(hSession, &state); + + if (state->decrypt_object == -1) + return CKR_ARGUMENTS_BAD; + + o = soft_token.object.objs[state->decrypt_object]; + + if (o->u.private_key.key == NULL) { + st_logf("private key NULL\n"); + return CKR_ARGUMENTS_BAD; + } + + if (pulDataLen == NULL) { + st_logf("pulDataLen NULL\n"); + ret = CKR_ARGUMENTS_BAD; + goto out; + } + + if (pEncryptedData == NULL_PTR) { + st_logf("data NULL\n"); + ret = CKR_ARGUMENTS_BAD; + goto out; + } + + switch(state->decrypt_mechanism->mechanism) { + case CKM_RSA_PKCS: + padding = RSA_PKCS1_PADDING; + break; + case CKM_RSA_X_509: + padding = RSA_NO_PADDING; + break; + default: + ret = CKR_FUNCTION_NOT_SUPPORTED; + goto out; + } + + ctx = EVP_PKEY_CTX_new(o->u.private_key.key, NULL); + if (ctx == NULL || EVP_PKEY_decrypt_init(ctx) <= 0 || + EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 || + EVP_PKEY_decrypt(ctx, NULL, &buffer_len, pEncryptedData, + ulEncryptedDataLen) <= 0) { + ret = CKR_DEVICE_ERROR; + goto out; + } + + buffer = OPENSSL_malloc(buffer_len); + if (buffer == NULL) { + ret = CKR_DEVICE_MEMORY; + goto out; + } + + if (EVP_PKEY_decrypt(ctx, buffer, &buffer_len, pEncryptedData, + ulEncryptedDataLen) <= 0) { + ret = CKR_DEVICE_ERROR; + goto out; + } + st_logf("Decrypt done\n"); + + if (pData != NULL_PTR) + memcpy(pData, buffer, buffer_len); + *pulDataLen = buffer_len; + + ret = CKR_OK; +out: + OPENSSL_cleanse(buffer, buffer_len); + OPENSSL_free(buffer); + EVP_PKEY_CTX_free(ctx); + return ret; +} + + +CK_RV +C_DecryptUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen) + +{ + st_logf("DecryptUpdate\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + + +CK_RV +C_DecryptFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastPart, + CK_ULONG_PTR pulLastPartLen) +{ + st_logf("DecryptFinal\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_DigestInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism) +{ + st_logf("DigestInit\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_SignInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + struct session_state *state; + CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 }; + CK_BBOOL bool_true = CK_TRUE; + CK_ATTRIBUTE attr[] = { + { CKA_SIGN, &bool_true, sizeof(bool_true) } + }; + struct st_object *o; + CK_RV ret; + + st_logf("SignInit\n"); + VERIFY_SESSION_HANDLE(hSession, &state); + + ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), + mechs, sizeof(mechs)/sizeof(mechs[0]), + pMechanism, hKey, &o); + if (ret) + return ret; + + ret = dup_mechanism(&state->sign_mechanism, pMechanism); + if (ret == CKR_OK) + state->sign_object = OBJECT_ID(o); + + return CKR_OK; +} + +CK_RV +C_Sign(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen) +{ + struct session_state *state; + struct st_object *o; + void *buffer = NULL; + CK_RV ret; + int padding; + size_t buffer_len = 0; + EVP_PKEY_CTX *ctx = NULL; + + st_logf("Sign\n"); + VERIFY_SESSION_HANDLE(hSession, &state); + + if (state->sign_object == -1) + return CKR_ARGUMENTS_BAD; + + o = soft_token.object.objs[state->sign_object]; + + if (o->u.private_key.key == NULL) { + st_logf("private key NULL\n"); + return CKR_ARGUMENTS_BAD; + } + + if (pulSignatureLen == NULL) { + st_logf("signature len NULL\n"); + ret = CKR_ARGUMENTS_BAD; + goto out; + } + + if (pData == NULL_PTR) { + st_logf("data NULL\n"); + ret = CKR_ARGUMENTS_BAD; + goto out; + } + + switch(state->sign_mechanism->mechanism) { + case CKM_RSA_PKCS: + padding = RSA_PKCS1_PADDING; + break; + case CKM_RSA_X_509: + padding = RSA_NO_PADDING; + break; + default: + ret = CKR_FUNCTION_NOT_SUPPORTED; + goto out; + } + + ctx = EVP_PKEY_CTX_new(o->u.private_key.key, NULL); + if (ctx == NULL || EVP_PKEY_sign_init(ctx) <= 0 || + EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 || + EVP_PKEY_sign(ctx, NULL, &buffer_len, pData, ulDataLen) <= 0) { + ret = CKR_DEVICE_ERROR; + goto out; + } + + buffer = OPENSSL_malloc(buffer_len); + if (buffer == NULL) { + ret = CKR_DEVICE_MEMORY; + goto out; + } + + if (EVP_PKEY_sign(ctx, buffer, &buffer_len, pData, ulDataLen) <= 0) { + ret = CKR_DEVICE_ERROR; + goto out; + } + st_logf("Sign done\n"); + + if (pSignature != NULL) + memcpy(pSignature, buffer, buffer_len); + *pulSignatureLen = buffer_len; + + ret = CKR_OK; +out: + OPENSSL_cleanse(buffer, buffer_len); + OPENSSL_free(buffer); + EVP_PKEY_CTX_free(ctx); + return ret; +} + +CK_RV +C_SignUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen) +{ + st_logf("SignUpdate\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + + +CK_RV +C_SignFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen) +{ + st_logf("SignUpdate\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_VerifyInit(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey) +{ + struct session_state *state; + CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 }; + CK_BBOOL bool_true = CK_TRUE; + CK_ATTRIBUTE attr[] = { + { CKA_VERIFY, &bool_true, sizeof(bool_true) } + }; + struct st_object *o; + CK_RV ret; + + st_logf("VerifyInit\n"); + VERIFY_SESSION_HANDLE(hSession, &state); + + ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), + mechs, sizeof(mechs)/sizeof(mechs[0]), + pMechanism, hKey, &o); + if (ret) + return ret; + + ret = dup_mechanism(&state->verify_mechanism, pMechanism); + if (ret == CKR_OK) + state->verify_object = OBJECT_ID(o); + + return ret; +} + +CK_RV +C_Verify(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pData, + CK_ULONG ulDataLen, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen) +{ + struct session_state *state; + struct st_object *o; + CK_RV ret; + int padding; + EVP_PKEY_CTX *ctx = NULL; + + st_logf("Verify\n"); + VERIFY_SESSION_HANDLE(hSession, &state); + + if (state->verify_object == -1) + return CKR_ARGUMENTS_BAD; + + o = soft_token.object.objs[state->verify_object]; + + if (o->u.public_key == NULL) { + st_logf("public key NULL\n"); + return CKR_ARGUMENTS_BAD; + } + + if (pSignature == NULL) { + st_logf("signature NULL\n"); + ret = CKR_ARGUMENTS_BAD; + goto out; + } + + if (pData == NULL_PTR) { + st_logf("data NULL\n"); + ret = CKR_ARGUMENTS_BAD; + goto out; + } + + switch(state->verify_mechanism->mechanism) { + case CKM_RSA_PKCS: + padding = RSA_PKCS1_PADDING; + break; + case CKM_RSA_X_509: + padding = RSA_NO_PADDING; + break; + default: + ret = CKR_FUNCTION_NOT_SUPPORTED; + goto out; + } + + ctx = EVP_PKEY_CTX_new(o->u.public_key, NULL); + if (ctx == NULL || EVP_PKEY_verify_init(ctx) <= 0 || + EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 || + EVP_PKEY_verify(ctx, pSignature, ulSignatureLen, pData, + ulDataLen) <= 0) { + ret = CKR_DEVICE_ERROR; + goto out; + } + st_logf("Verify done\n"); + + ret = CKR_OK; +out: + EVP_PKEY_CTX_free(ctx); + return ret; +} + +CK_RV +C_VerifyUpdate(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, + CK_ULONG ulPartLen) +{ + st_logf("VerifyUpdate\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_VerifyFinal(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen) +{ + st_logf("VerifyFinal\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +C_GenerateRandom(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR RandomData, + CK_ULONG ulRandomLen) +{ + st_logf("GenerateRandom\n"); + VERIFY_SESSION_HANDLE(hSession, NULL); + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_FUNCTION_LIST funcs = { + { 2, 11 }, + C_Initialize, + C_Finalize, + C_GetInfo, + C_GetFunctionList, + C_GetSlotList, + C_GetSlotInfo, + C_GetTokenInfo, + C_GetMechanismList, + C_GetMechanismInfo, + C_InitToken, + (void *)func_not_supported, /* C_InitPIN */ + (void *)func_not_supported, /* C_SetPIN */ + C_OpenSession, + C_CloseSession, + C_CloseAllSessions, + C_GetSessionInfo, + (void *)func_not_supported, /* C_GetOperationState */ + (void *)func_not_supported, /* C_SetOperationState */ + C_Login, + C_Logout, + (void *)func_not_supported, /* C_CreateObject */ + (void *)func_not_supported, /* C_CopyObject */ + (void *)func_not_supported, /* C_DestroyObject */ + (void *)func_not_supported, /* C_GetObjectSize */ + C_GetAttributeValue, + (void *)func_not_supported, /* C_SetAttributeValue */ + C_FindObjectsInit, + C_FindObjects, + C_FindObjectsFinal, + C_EncryptInit, + C_Encrypt, + C_EncryptUpdate, + C_EncryptFinal, + C_DecryptInit, + C_Decrypt, + C_DecryptUpdate, + C_DecryptFinal, + C_DigestInit, + (void *)func_not_supported, /* C_Digest */ + (void *)func_not_supported, /* C_DigestUpdate */ + (void *)func_not_supported, /* C_DigestKey */ + (void *)func_not_supported, /* C_DigestFinal */ + C_SignInit, + C_Sign, + C_SignUpdate, + C_SignFinal, + (void *)func_not_supported, /* C_SignRecoverInit */ + (void *)func_not_supported, /* C_SignRecover */ + C_VerifyInit, + C_Verify, + C_VerifyUpdate, + C_VerifyFinal, + (void *)func_not_supported, /* C_VerifyRecoverInit */ + (void *)func_not_supported, /* C_VerifyRecover */ + (void *)func_not_supported, /* C_DigestEncryptUpdate */ + (void *)func_not_supported, /* C_DecryptDigestUpdate */ + (void *)func_not_supported, /* C_SignEncryptUpdate */ + (void *)func_not_supported, /* C_DecryptVerifyUpdate */ + (void *)func_not_supported, /* C_GenerateKey */ + (void *)func_not_supported, /* C_GenerateKeyPair */ + (void *)func_not_supported, /* C_WrapKey */ + (void *)func_not_supported, /* C_UnwrapKey */ + (void *)func_not_supported, /* C_DeriveKey */ + (void *)func_not_supported, /* C_SeedRandom */ + C_GenerateRandom, + (void *)func_not_supported, /* C_GetFunctionStatus */ + (void *)func_not_supported, /* C_CancelFunction */ + (void *)func_not_supported /* C_WaitForSlotEvent */ +}; diff --git a/krb5-1.21.3/src/tests/softpkcs11/softpkcs11.exports b/krb5-1.21.3/src/tests/softpkcs11/softpkcs11.exports new file mode 100644 index 00000000..aa728451 --- /dev/null +++ b/krb5-1.21.3/src/tests/softpkcs11/softpkcs11.exports @@ -0,0 +1,39 @@ +C_CloseAllSessions +C_CloseSession +C_Decrypt +C_DecryptFinal +C_DecryptInit +C_DecryptUpdate +C_DigestInit +C_Encrypt +C_EncryptFinal +C_EncryptInit +C_EncryptUpdate +C_Finalize +C_FindObjects +C_FindObjectsFinal +C_FindObjectsInit +C_GenerateRandom +C_GetAttributeValue +C_GetFunctionList +C_GetInfo +C_GetMechanismInfo +C_GetMechanismList +C_GetObjectSize +C_GetSessionInfo +C_GetSlotInfo +C_GetSlotList +C_GetTokenInfo +C_Initialize +C_InitToken +C_Login +C_Logout +C_OpenSession +C_Sign +C_SignFinal +C_SignInit +C_SignUpdate +C_Verify +C_VerifyFinal +C_VerifyInit +C_VerifyUpdate diff --git a/krb5-1.21.3/src/tests/t_audit.py b/krb5-1.21.3/src/tests/t_audit.py new file mode 100755 index 00000000..e48f4ebc --- /dev/null +++ b/krb5-1.21.3/src/tests/t_audit.py @@ -0,0 +1,27 @@ +from k5test import * + +conf = {'plugins': {'audit': { + 'module': 'test:$plugins/audit/test/k5audit_test.so'}}} + +realm = K5Realm(krb5_conf=conf, get_creds=False) +realm.addprinc('target') +realm.run([kadminl, 'modprinc', '+ok_to_auth_as_delegate', realm.host_princ]) + +# Make normal AS and TGS requests so they will be audited. +realm.kinit(realm.host_princ, flags=['-k', '-f']) +realm.run([kvno, 'target']) + +# Make S4U2Self and S4U2Proxy requests so they will be audited. The +# S4U2Proxy request is expected to fail. +realm.run([kvno, '-k', realm.keytab, '-U', 'user', '-P', 'target'], + expected_code=1, expected_msg='KDC can\'t fulfill requested option') + +# Make a U2U request so it will be audited. +uuserver = os.path.join(buildtop, 'appl', 'user_user', 'uuserver') +uuclient = os.path.join(buildtop, 'appl', 'user_user', 'uuclient') +port_arg = str(realm.server_port()) +realm.start_server([uuserver, port_arg], 'Server started') +realm.run([uuclient, hostname, 'testing message', port_arg], + expected_msg='Hello') + +success('Audit tests') diff --git a/krb5-1.21.3/src/tests/t_authdata.py b/krb5-1.21.3/src/tests/t_authdata.py new file mode 100644 index 00000000..bde1c368 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_authdata.py @@ -0,0 +1,362 @@ +from k5test import * + +# Load the sample KDC authdata module. Allow renewable tickets. +greet_path = os.path.join(buildtop, 'plugins', 'authdata', 'greet_server', + 'greet_server.so') +conf = {'realms': {'$realm': {'max_life': '20h', 'max_renewable_life': '20h'}}, + 'plugins': {'kdcauthdata': {'module': 'greet:' + greet_path}}} +realm = K5Realm(krb5_conf=conf) + +# With no requested authdata, we expect to see PAC (128) in an +# if-relevant container and the greet authdata in a kdc-issued +# container. +mark('baseline authdata') +out = realm.run(['./adata', realm.host_princ]) +if '?128: [6, 7, 10, 16, 19]' not in out or '^-42: Hello' not in out: + fail('expected authdata not seen for basic request') + +# Requested authdata is copied into the ticket, with KDC-only types +# filtered out. (128 is win2k-pac, which should be filtered.) +mark('request authdata') +out = realm.run(['./adata', realm.host_princ, '-5', 'test1', '?-6', 'test2', + '128', 'fakepac', '?128', 'ifrelfakepac', + '^-8', 'fakekdcissued', '?^-8', 'ifrelfakekdcissued']) +if ' -5: test1' not in out or '?-6: test2' not in out: + fail('expected authdata not seen for request with authdata') +if 'fake' in out: + fail('KDC-only authdata not filtered for request with authdata') + +mark('AD-MANDATORY-FOR-KDC') +realm.run(['./adata', realm.host_princ, '!-1', 'mandatoryforkdc'], + expected_code=1, expected_msg='KDC policy rejects request') + +# The no_auth_data_required server flag should suppress the PAC, but +# not module or request authdata. +mark('no_auth_data_required server flag') +realm.run([kadminl, 'ank', '-randkey', '+no_auth_data_required', 'noauth']) +realm.extract_keytab('noauth', realm.keytab) +out = realm.run(['./adata', 'noauth', '-2', 'test']) +if '^-42: Hello' not in out or ' -2: test' not in out: + fail('expected authdata not seen for no_auth_data_required request') +if '128: ' in out: + fail('PAC authdata seen for no_auth_data_required request') + +# Cross-realm TGT requests should not suppress PAC or request +# authdata. +mark('cross-realm') +realm.addprinc('krbtgt/XREALM') +realm.extract_keytab('krbtgt/XREALM', realm.keytab) +out = realm.run(['./adata', 'krbtgt/XREALM', '-3', 'test']) +if '128:' not in out or '^-42: Hello' not in out or ' -3: test' not in out: + fail('expected authdata not seen for cross-realm TGT request') + +mark('pac_privsvr_enctype') +# Change the privsvr enctype and make sure we can still verify the PAC +# on a service ticket in a TGS request. +realm.run([kadminl, 'setstr', realm.host_princ, + 'pac_privsvr_enctype', 'aes128-sha1']) +realm.kinit(realm.user_princ, password('user'), + ['-S', realm.host_princ, '-r', '1h']) +realm.kinit(realm.user_princ, None, ['-S', realm.host_princ, '-R']) +# Remove the attribute and make sure the previously-issued service +# ticket PAC no longer verifies. +realm.run([kadminl, 'delstr', realm.host_princ, 'pac_privsvr_enctype']) +realm.kinit(realm.user_princ, None, ['-S', realm.host_princ, '-R'], + expected_code=1, expected_msg='Message stream modified') + +realm.stop() + +if not pkinit_enabled: + skipped('anonymous ticket authdata tests', 'PKINIT not built') +else: + # Set up a realm with PKINIT support and get anonymous tickets. + realm = K5Realm(krb5_conf=conf, get_creds=False, pkinit=True) + realm.addprinc('WELLKNOWN/ANONYMOUS') + realm.kinit('@%s' % realm.realm, flags=['-n']) + + # PAC and module authdata should be suppressed for anonymous + # tickets, but not request authdata. + mark('anonymous') + out = realm.run(['./adata', realm.host_princ, '-4', 'test']) + if ' -4: test' not in out: + fail('expected authdata not seen for anonymous request') + if '128: ' in out or '-42: ' in out: + fail('PAC or greet authdata seen for anonymous request') + +realm.stop() + +# Test authentication indicators. Load the test preauth module so we +# can control the indicators asserted. +testpreauth = os.path.join(buildtop, 'plugins', 'preauth', 'test', 'test.so') +krb5conf = {'plugins': {'kdcpreauth': {'module': 'test:' + testpreauth}, + 'clpreauth': {'module': 'test:' + testpreauth}}} +realm, realm2 = cross_realms(2, args=({'realm': 'LOCAL'}, + {'realm': 'FOREIGN'}), + krb5_conf=krb5conf, get_creds=False) +realm.run([kadminl, 'modprinc', '+requires_preauth', '-maxrenewlife', '2 days', + realm.user_princ]) +realm.run([kadminl, 'modprinc', '-maxrenewlife', '2 days', realm.host_princ]) +realm.run([kadminl, 'modprinc', '-maxrenewlife', '2 days', realm.krbtgt_princ]) +realm.extract_keytab(realm.krbtgt_princ, realm.keytab) +realm.extract_keytab(realm.host_princ, realm.keytab) +realm.extract_keytab('krbtgt/FOREIGN', realm.keytab) +realm2.extract_keytab(realm2.krbtgt_princ, realm.keytab) +realm2.extract_keytab(realm2.host_princ, realm.keytab) +realm2.extract_keytab('krbtgt/LOCAL', realm.keytab) + +# AS request to local-realm service +mark('AS-REQ to local service auth indicator') +realm.kinit(realm.user_princ, password('user'), + ['-X', 'indicators=indcl', '-r', '2d', '-S', realm.host_princ]) +realm.run(['./adata', realm.host_princ], expected_msg='+97: [indcl]') + +# Ticket modification request +mark('ticket modification auth indicator') +realm.kinit(realm.user_princ, None, ['-R', '-S', realm.host_princ]) +realm.run(['./adata', realm.host_princ], expected_msg='+97: [indcl]') + +# AS request to cross TGT +mark('AS-REQ to cross TGT auth indicator') +realm.kinit(realm.user_princ, password('user'), + ['-X', 'indicators=indcl', '-S', 'krbtgt/FOREIGN']) +realm.run(['./adata', 'krbtgt/FOREIGN'], expected_msg='+97: [indcl]') + +# Multiple indicators +mark('AS multiple indicators') +realm.kinit(realm.user_princ, password('user'), + ['-X', 'indicators=indcl indcl2 indcl3']) +realm.run(['./adata', realm.krbtgt_princ], + expected_msg='+97: [indcl, indcl2, indcl3]') + +# AS request to local TGT (resulting creds are used for TGS tests) +mark('AS-REQ to local TGT auth indicator') +realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=indcl']) +realm.run(['./adata', realm.krbtgt_princ], expected_msg='+97: [indcl]') + +# Local TGS request for local realm service +mark('TGS-REQ to local service auth indicator') +realm.run(['./adata', realm.host_princ], expected_msg='+97: [indcl]') + +# Local TGS request for cross TGT service +mark('TGS-REQ to cross TGT auth indicator') +realm.run(['./adata', 'krbtgt/FOREIGN'], expected_msg='+97: [indcl]') + +# We don't yet have support for passing auth indicators across realms, +# so just verify that indicators don't survive cross-realm requests. +mark('TGS-REQ to foreign service auth indicator') +out = realm.run(['./adata', realm2.krbtgt_princ]) +if '97:' in out: + fail('auth-indicator seen in cross TGT request to local TGT') +out = realm.run(['./adata', 'krbtgt/LOCAL@FOREIGN']) +if '97:' in out: + fail('auth-indicator seen in cross TGT request to cross TGT') +out = realm.run(['./adata', realm2.host_princ]) +if '97:' in out: + fail('auth-indicator seen in cross TGT request to service') + +# Test that the CAMMAC signature still works during a krbtgt rollover. +mark('CAMMAC signature across krbtgt rollover') +realm.run([kadminl, 'cpw', '-randkey', '-keepold', realm.krbtgt_princ]) +realm.run(['./adata', realm.host_princ], expected_msg='+97: [indcl]') + +# Test indicator enforcement. +mark('auth indicator enforcement') +realm.addprinc('restricted') +realm.run([kadminl, 'setstr', 'restricted', 'require_auth', 'superstrong']) +realm.kinit(realm.user_princ, password('user'), ['-S', 'restricted'], + expected_code=1, expected_msg='KDC policy rejects request') +realm.run([kvno, 'restricted'], expected_code=1, + expected_msg='KDC policy rejects request') +realm.run([kadminl, 'setstr', 'restricted', 'require_auth', 'indcl']) +realm.run([kvno, 'restricted']) +realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=ind1 ind2']) +realm.run([kvno, 'restricted'], expected_code=1) +realm.run([kadminl, 'setstr', 'restricted', 'require_auth', 'a b c ind2']) +realm.run([kvno, 'restricted']) + +# Regression test for one manifestation of #8139: ensure that +# forwarded TGTs obtained across a TGT re-key still work when the +# preferred krbtgt enctype changes. +mark('#8139 regression test') +realm.kinit(realm.user_princ, password('user'), ['-f']) +realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'des3-cbc-sha1', + realm.krbtgt_princ]) +realm.run(['./forward']) +realm.run([kvno, realm.host_princ]) + +# Repeat the above test using a renewed TGT. +mark('#8139 regression test (renewed TGT)') +realm.kinit(realm.user_princ, password('user'), ['-r', '2d']) +realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes128-cts', + realm.krbtgt_princ]) +realm.kinit(realm.user_princ, None, ['-R']) +realm.run([kvno, realm.host_princ]) + +realm.stop() +realm2.stop() + +# Load the test KDB module to allow successful S4U2Proxy +# auth-indicator requests and to detect whether replaced_reply_key is +# set. +testprincs = {'krbtgt/KRBTEST.COM': {'keys': 'aes128-cts'}, + 'krbtgt/FOREIGN': {'keys': 'aes128-cts'}, + 'user': {'keys': 'aes128-cts', 'flags': '+preauth'}, + 'user2': {'keys': 'aes128-cts', 'flags': '+preauth'}, + 'rservice': {'keys': 'aes128-cts', + 'strings': 'require_auth:strong'}, + 'service/1': {'keys': 'aes128-cts', + 'flags': '+ok_to_auth_as_delegate'}, + 'service/2': {'keys': 'aes128-cts'}, + 'noauthdata': {'keys': 'aes128-cts', + 'flags': '+no_auth_data_required'}} +kdcconf = {'realms': {'$realm': {'database_module': 'test'}}, + 'dbmodules': {'test': {'db_library': 'test', + 'princs': testprincs, + 'delegation': {'service/1': 'service/2'}}}} +realm = K5Realm(krb5_conf=krb5conf, kdc_conf=kdcconf, create_kdb=False, + pkinit=True) +usercache = 'FILE:' + os.path.join(realm.testdir, 'usercache') +realm.extract_keytab(realm.krbtgt_princ, realm.keytab) +realm.extract_keytab('krbtgt/FOREIGN', realm.keytab) +realm.extract_keytab(realm.user_princ, realm.keytab) +realm.extract_keytab('ruser', realm.keytab) +realm.extract_keytab('service/1', realm.keytab) +realm.extract_keytab('service/2', realm.keytab) +realm.extract_keytab('noauthdata', realm.keytab) +realm.start_kdc() + +if not pkinit_enabled: + skipped('replaced_reply_key test', 'PKINIT not built') +else: + # Check that replaced_reply_key is set in issue_pac() when PKINIT + # is used. The test KDB module will indicate this by including a + # fake PAC_CREDENTIAL_INFO(2) buffer in the PAC. + mark('PKINIT (replaced_reply_key set)') + realm.pkinit(realm.user_princ) + realm.run(['./adata', realm.krbtgt_princ], + expected_msg='?128: [1, 2, 6, 7, 10]') + +# S4U2Self (should have no indicators since client did not authenticate) +mark('S4U2Self (no auth indicators expected)') +realm.kinit('service/1', None, ['-k', '-f', '-X', 'indicators=inds1']) +realm.run([kvno, '-U', 'user', 'service/1']) +out = realm.run(['./adata', '-p', realm.user_princ, 'service/1']) +if '97:' in out: + fail('auth-indicator present in S4U2Self response') + +# Get another S4U2Self ticket with requested authdata. +realm.run(['./s4u2self', 'user', 'service/1', '-', '-2', 'self_ad']) +realm.run(['./adata', '-p', realm.user_princ, 'service/1', '-2', 'self_ad'], + expected_msg=' -2: self_ad') + +# S4U2Proxy (indicators should come from evidence ticket, not TGT) +mark('S4U2Proxy (auth indicators from evidence ticket expected)') +realm.kinit(realm.user_princ, None, ['-k', '-f', '-X', 'indicators=indcl', + '-S', 'service/1', '-c', usercache]) +realm.run(['./s4u2proxy', usercache, 'service/2']) +out = realm.run(['./adata', '-p', realm.user_princ, 'service/2']) +if '+97: [indcl]' not in out or '[inds1]' in out: + fail('correct auth-indicator not seen for S4U2Proxy req') +# Make sure a PAC with an S4U_DELEGATION_INFO(11) buffer is included. +if '?128: [1, 6, 7, 10, 11, 16, 19]' not in out: + fail('PAC with delegation info not seen for S4U2Proxy req') + +# Get another S4U2Proxy ticket including request-authdata. +realm.run(['./s4u2proxy', usercache, 'service/2', '-2', 'proxy_ad']) +realm.run(['./adata', '-p', realm.user_princ, 'service/2', '-2', 'proxy_ad'], + expected_msg=' -2: proxy_ad') + +# Get an S4U2Proxy ticket using an evidence ticket obtained by S4U2Self, +# with request authdata in both steps. +realm.run(['./s4u2self', 'user2', 'service/1', usercache, '-2', 'self_ad']) +realm.run(['./s4u2proxy', usercache, 'service/2', '-2', 'proxy_ad']) +out = realm.run(['./adata', '-p', 'user2', 'service/2', '-2', 'proxy_ad']) +if ' -2: self_ad' not in out or ' -2: proxy_ad' not in out: + fail('expected authdata not seen in S4U2Proxy ticket') + +# Test alteration of auth indicators by KDB module (AS and TGS). +realm.kinit(realm.user_princ, None, ['-k', '-X', 'indicators=dummy dbincr1']) +realm.run(['./adata', realm.krbtgt_princ], expected_msg='+97: [dbincr2]') +realm.run(['./adata', 'service/1'], expected_msg='+97: [dbincr3]') +realm.kinit(realm.user_princ, None, + ['-k', '-X', 'indicators=strong', '-S', 'rservice']) +# Test enforcement of altered indicators during AS request. +realm.kinit(realm.user_princ, None, + ['-k', '-X', 'indicators=strong dbincr1', '-S', 'rservice'], + expected_code=1) + +# Test that the PAC is suppressed in an AS request by a negative PAC +# request. +mark('AS-REQ PAC client supression') +realm.kinit(realm.user_princ, None, ['-k', '--no-request-pac']) +out = realm.run(['./adata', realm.krbtgt_princ]) +if '128:' in out: + fail('PAC not suppressed by --no-request-pac') + +mark('S4U2Proxy with a foreign client') + +a_princs = {'krbtgt/A': {'keys': 'aes128-cts'}, + 'krbtgt/B': {'keys': 'aes128-cts'}, + 'impersonator': {'keys': 'aes128-cts'}, + 'impersonator2': {'keys': 'aes128-cts'}, + 'resource': {'keys': 'aes128-cts'}} +a_kconf = {'realms': {'$realm': {'database_module': 'test'}}, + 'dbmodules': {'test': {'db_library': 'test', + 'delegation': {'impersonator' : 'resource'}, + 'princs': a_princs, + 'alias': {'service/rb.b': '@B'}}}} + +b_princs = {'krbtgt/B': {'keys': 'aes128-cts'}, + 'krbtgt/A': {'keys': 'aes128-cts'}, + 'user': {'keys': 'aes128-cts', 'flags': '+preauth'}, + 'rb': {'keys': 'aes128-cts'}} +b_kconf = {'realms': {'$realm': {'database_module': 'test'}}, + 'dbmodules': {'test': {'db_library': 'test', + 'princs': b_princs, + 'rbcd': {'rb@B': 'impersonator2@A'}, + 'alias': {'service/rb.b': 'rb', + 'impersonator2@A': '@A'}}}} + +ra, rb = cross_realms(2, xtgts=(), + args=({'realm': 'A', 'kdc_conf': a_kconf}, + {'realm': 'B', 'kdc_conf': b_kconf}), + create_kdb=False) + +ra.start_kdc() +rb.start_kdc() + +ra.extract_keytab('impersonator@A', ra.keytab) +ra.extract_keytab('impersonator2@A', ra.keytab) +rb.extract_keytab('user@B', rb.keytab) + +usercache = 'FILE:' + os.path.join(rb.testdir, 'usercache') +rb.kinit(rb.user_princ, None, ['-k', '-f', '-c', usercache]) +rb.run([kvno, '-C', 'impersonator@A', '-c', usercache]) + +ra.kinit('impersonator@A', None, ['-f', '-k', '-t', ra.keytab]) +ra.run(['./s4u2proxy', usercache, 'resource@A']) + +mark('Cross realm S4U authdata tests') + +ra.kinit('impersonator2@A', None, ['-f', '-k', '-t', ra.keytab]) +ra.run(['./s4u2self', rb.user_princ, 'impersonator2@A', usercache, '-2', + 'cross_s4u_self_ad']) +out = ra.run(['./adata', '-c', usercache, '-p', rb.user_princ, + 'impersonator2@A', '-2', 'cross_s4u_self_ad']) +if out.count(' -2: cross_s4u_self_ad') != 1: + fail('expected one cross_s4u_self_ad, got: %s' % count) + +ra.run(['./s4u2proxy', usercache, 'service/rb.b', '-2', + 'cross_s4u_proxy_ad']) +rb.extract_keytab('service/rb.b', ra.keytab) +out = ra.run(['./adata', '-p', rb.user_princ, 'service/rb.b', '-2', + 'cross_s4u_proxy_ad']) +if out.count(' -2: cross_s4u_self_ad') != 1: + fail('expected one cross_s4u_self_ad, got: %s' % count) +if out.count(' -2: cross_s4u_proxy_ad') != 1: + fail('expected one cross_s4u_proxy_ad, got: %s' % count) + +ra.stop() +rb.stop() + +success('Authorization data tests') diff --git a/krb5-1.21.3/src/tests/t_bogus_kdc_req.py b/krb5-1.21.3/src/tests/t_bogus_kdc_req.py new file mode 100755 index 00000000..a101c0e1 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_bogus_kdc_req.py @@ -0,0 +1,42 @@ +import base64 +import socket +from k5test import * + +realm = K5Realm() + +# Send encodings that are invalid KDC-REQs, but pass krb5_is_as_req() +# and krb5_is_tgs_req(), to make sure that the KDC recovers correctly +# from failures in decode_krb5_as_req() and decode_krb5_tgs_req(). + +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +a = (hostname, realm.portbase) + + +# Bogus AS-REQ + +x1 = base64.b16decode('6AFF') +s.sendto(x1, a) + +# Make sure kinit still works. + +realm.kinit(realm.user_princ, password('user')) + +# Bogus TGS-REQ + +x2 = base64.b16decode('6CFF') +s.sendto(x2, a) + +# Make sure kinit still works. + +realm.kinit(realm.user_princ, password('user')) + +# Not a KDC-REQ, even a little bit + +x3 = base64.b16decode('FFFF') +s.sendto(x3, a) + +# Make sure kinit still works. + +realm.kinit(realm.user_princ, password('user')) + +success('Bogus KDC-REQ test') diff --git a/krb5-1.21.3/src/tests/t_ccache.py b/krb5-1.21.3/src/tests/t_ccache.py new file mode 100755 index 00000000..11c94976 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_ccache.py @@ -0,0 +1,202 @@ +# Copyright (C) 2011 by the Massachusetts Institute of Technology. +# All rights reserved. + +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +from k5test import * +import tempfile + +socketdir = tempfile.TemporaryDirectory() +kcm_socket_path = os.path.join(socketdir.name, 'kcm') +conf = {'libdefaults': {'kcm_socket': kcm_socket_path, + 'kcm_mach_service': '-'}} +realm = K5Realm(krb5_conf=conf) + +realm.addprinc('contest') +realm.extract_keytab('contest', realm.keytab) +realm.run(['./conccache', realm.ccache + '.contest', 'contest', + realm.host_princ]) + +keyctl = which('keyctl') +out = realm.run([klist, '-c', 'KEYRING:process:abcd'], expected_code=1) +test_keyring = (keyctl is not None and + 'Unknown credential cache type' not in out) +if not test_keyring: + skipped('keyring ccache tests', 'keyring support not built') + +# Test kdestroy and klist of a non-existent ccache. +mark('no ccache') +realm.run([kdestroy]) +realm.run([klist], expected_code=1, expected_msg='No credentials cache found') + +# Test kinit with an inaccessible ccache. +mark('inaccessible ccache') +realm.kinit(realm.user_princ, password('user'), flags=['-c', 'testdir/xx/yy'], + expected_code=1, expected_msg='Failed to store credentials') + +# Test klist -s with a single ccache. +mark('klist -s single ccache') +realm.run([klist, '-s'], expected_code=1) +realm.kinit(realm.user_princ, password('user')) +realm.run([klist, '-s']) +realm.kinit(realm.user_princ, password('user'), ['-l', '-10s']) +realm.run([klist, '-s'], expected_code=1) +realm.kinit(realm.user_princ, password('user'), ['-S', 'kadmin/admin']) +realm.run([klist, '-s']) +realm.run([kdestroy]) +realm.run([klist, '-s'], expected_code=1) + +realm.addprinc('alice', password('alice')) +realm.addprinc('bob', password('bob')) +realm.addprinc('carol', password('carol')) +realm.addprinc('doug', password('doug')) + +def collection_test(realm, ccname): + cctype = ccname.partition(':')[0] + oldccname = realm.env['KRB5CCNAME'] + realm.env['KRB5CCNAME'] = ccname + + mark('%s collection, single cache' % cctype) + realm.run([klist, '-A', '-s'], expected_code=1) + realm.kinit('alice', password('alice')) + realm.run([klist], expected_msg='Default principal: alice@') + realm.run([klist, '-A', '-s']) + realm.run([kvno, realm.host_princ], expected_msg = 'kvno = 1') + realm.run([kvno, realm.host_princ], expected_msg = 'kvno = 1') + out = realm.run([klist]) + if out.count(realm.host_princ) != 1: + fail('Wrong number of service tickets in cache') + realm.run([kdestroy]) + output = realm.run([klist], expected_code=1) + if 'No credentials cache' not in output and 'not found' not in output: + fail('Initial kdestroy failed to destroy primary cache.') + output = realm.run([klist, '-l'], expected_code=1) + if not output.endswith('---\n') or output.count('\n') != 2: + fail('Initial kdestroy failed to empty cache collection.') + realm.run([klist, '-A', '-s'], expected_code=1) + + mark('%s collection, multiple caches' % cctype) + realm.kinit('alice', password('alice')) + realm.kinit('carol', password('carol')) + output = realm.run([klist, '-l']) + if '---\ncarol@' not in output or '\nalice@' not in output: + fail('klist -l did not show expected output after two kinits.') + realm.kinit('alice', password('alice')) + output = realm.run([klist, '-l']) + if '---\nalice@' not in output or output.count('\n') != 4: + fail('klist -l did not show expected output after re-kinit for alice.') + realm.kinit('doug', password('doug')) + realm.kinit('bob', password('bob')) + output = realm.run([klist, '-A', ccname]) + if 'bob@' not in output.splitlines()[1] or 'alice@' not in output or \ + 'carol@' not in output or 'doug@' not in output or \ + output.count('Default principal:') != 4: + fail('klist -A did not show expected output after kinit doug+bob.') + realm.run([kswitch, '-p', 'carol']) + output = realm.run([klist, '-l']) + if '---\ncarol@' not in output or output.count('\n') != 6: + fail('klist -l did not show expected output after kswitch to carol.') + + # Switch to specifying the collection name on the command line + # (only works with klist/kdestroy for now, not kinit/kswitch). + realm.env['KRB5CCNAME'] = oldccname + + mark('%s collection, command-line specifier' % cctype) + realm.run([kdestroy, '-c', ccname]) + output = realm.run([klist, '-l', ccname]) + if 'carol@' in output or 'bob@' not in output or output.count('\n') != 5: + fail('kdestroy failed to remove only primary ccache.') + realm.run([klist, '-s', ccname], expected_code=1) + realm.run([klist, '-A', '-s', ccname]) + realm.run([kdestroy, '-p', 'alice', '-c', ccname]) + output = realm.run([klist, '-l', ccname]) + if 'alice@' in output or 'bob@' not in output or output.count('\n') != 4: + fail('kdestroy -p failed to remove alice') + realm.run([kdestroy, '-A', '-c', ccname]) + output = realm.run([klist, '-l', ccname], expected_code=1) + if not output.endswith('---\n') or output.count('\n') != 2: + fail('kdestroy -a failed to empty cache collection.') + realm.run([klist, '-A', '-s', ccname], expected_code=1) + + +collection_test(realm, 'DIR:' + os.path.join(realm.testdir, 'cc')) + +# Test KCM with and without RETRIEVE and GET_CRED_LIST support. +kcmserver_path = os.path.join(srctop, 'tests', 'kcmserver.py') +kcmd = realm.start_server([sys.executable, kcmserver_path, kcm_socket_path], + 'starting...') +collection_test(realm, 'KCM:') +stop_daemon(kcmd) +os.remove(kcm_socket_path) +realm.start_server([sys.executable, kcmserver_path, '-f', kcm_socket_path], + 'starting...') +collection_test(realm, 'KCM:') + +if test_keyring: + def cleanup_keyring(anchor, name): + out = realm.run(['keyctl', 'list', anchor]) + if ('keyring: ' + name + '\n') in out: + keyid = realm.run(['keyctl', 'search', anchor, 'keyring', name]) + realm.run(['keyctl', 'unlink', keyid.strip(), anchor]) + + # Use realm.testdir as the collection name to avoid conflicts with + # other build trees. + cname = realm.testdir + col_ringname = '_krb_' + cname + + cleanup_keyring('@s', col_ringname) + collection_test(realm, 'KEYRING:session:' + cname) + cleanup_keyring('@s', col_ringname) + + # Test legacy keyring cache linkage. + mark('legacy keyring cache linkage') + realm.env['KRB5CCNAME'] = 'KEYRING:' + cname + realm.run([kdestroy, '-A']) + realm.kinit(realm.user_princ, password('user')) + msg = 'KEYRING:legacy:' + cname + ':' + cname + realm.run([klist, '-l'], expected_msg=msg) + # Make sure this cache is linked to the session keyring. + id = realm.run([keyctl, 'search', '@s', 'keyring', cname]) + realm.run([keyctl, 'list', id.strip()], + expected_msg='user: __krb5_princ__') + # Remove the collection keyring. When the collection is + # reinitialized, the legacy cache should reappear inside it + # automatically as the primary cache. + cleanup_keyring('@s', col_ringname) + realm.run([klist], expected_msg=realm.user_princ) + coll_id = realm.run([keyctl, 'search', '@s', 'keyring', '_krb_' + cname]) + msg = id.strip() + ':' + realm.run([keyctl, 'list', coll_id.strip()], expected_msg=msg) + # Destroy the cache and check that it is unlinked from the session keyring. + realm.run([kdestroy]) + realm.run([keyctl, 'search', '@s', 'keyring', cname], expected_code=1) + cleanup_keyring('@s', col_ringname) + +# Test parameter expansion in default_ccache_name +mark('default_ccache_name parameter expansion') +realm.stop() +conf = {'libdefaults': {'default_ccache_name': 'testdir/%{null}abc%{uid}'}} +realm = K5Realm(krb5_conf=conf, create_kdb=False) +del realm.env['KRB5CCNAME'] +uidstr = str(os.getuid()) +msg = 'testdir/abc%s' % uidstr +realm.run([klist], expected_code=1, expected_msg=msg) + +success('Credential cache tests') diff --git a/krb5-1.21.3/src/tests/t_certauth.py b/krb5-1.21.3/src/tests/t_certauth.py new file mode 100644 index 00000000..82a98a81 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_certauth.py @@ -0,0 +1,65 @@ +from k5test import * + +# Skip this test if pkinit wasn't built. +if not pkinit_enabled: + skip_rest('certauth tests', 'PKINIT module not built') + +modpath = os.path.join(buildtop, 'plugins', 'certauth', 'test', + 'certauth_test.so') +krb5_conf = {'plugins': {'certauth': { + 'module': ['test1:' + modpath, 'test2:' + modpath, 'test3:' + modpath], + 'enable_only': ['test1', 'test2', 'test3']}}} +kdc_conf = {'realms': {'$realm': { + 'default_principal_flags': '+preauth', + 'pkinit_indicator': ['indpkinit1', 'indpkinit2']}}} + +realm = K5Realm(krb5_conf=krb5_conf, kdc_conf=kdc_conf, get_creds=False, + pkinit=True) +realm.addprinc('nocert') + +def check_indicators(inds): + msg = '+97: [%s]' % inds + realm.run(['./adata', realm.host_princ], expected_msg=msg) + +# Test that authentication fails if no module accepts. +realm.pkinit('nocert', expected_code=1, expected_msg='Client name mismatch') + +# Let the test2 module match user to CN=user, with indicators. +realm.pkinit(realm.user_princ) +realm.klist(realm.user_princ) +check_indicators('test1, test2, user, indpkinit1, indpkinit2') + +# Let the test2 module mismatch with user2 to CN=user. +realm.addprinc('user2@KRBTEST.COM') +realm.pkinit('user2', expected_code=1, expected_msg='Certificate mismatch') + +# Test the KRB5_CERTAUTH_HWAUTH return code. +mark('hw-authent flag tests') +# First test +requires_hwauth without causing the hw-authent ticket +# flag to be set. This currently results in a preauth loop. +realm.run([kadminl, 'modprinc', '+requires_hwauth', realm.user_princ]) +realm.pkinit(realm.user_princ, expected_code=1, + expected_msg='Looping detected') +# Cause the test3 module to return KRB5_CERTAUTH_HWAUTH and try again. +# Authentication should succeed whether or not another module accepts, +# but not if another module rejects. +realm.run([kadminl, 'setstr', realm.user_princ, 'hwauth', 'ok']) +realm.run([kadminl, 'setstr', 'user2', 'hwauth', 'ok']) +realm.run([kadminl, 'setstr', 'nocert', 'hwauth', 'ok']) +realm.pkinit(realm.user_princ) +check_indicators('test1, test2, user, hwauth:ok, indpkinit1, indpkinit2') +realm.pkinit('user2', expected_code=1, expected_msg='Certificate mismatch') +realm.pkinit('nocert') +check_indicators('test1, hwauth:ok, indpkinit1, indpkinit2') + +# Cause the test3 module to return KRB5_CERTAUTH_HWAUTH_PASS and try +# again. Authentication should succeed only if another module accepts. +realm.run([kadminl, 'setstr', realm.user_princ, 'hwauth', 'pass']) +realm.run([kadminl, 'setstr', 'user2', 'hwauth', 'pass']) +realm.run([kadminl, 'setstr', 'nocert', 'hwauth', 'pass']) +realm.pkinit(realm.user_princ) +check_indicators('test1, test2, user, hwauth:pass, indpkinit1, indpkinit2') +realm.pkinit('user2', expected_code=1, expected_msg='Certificate mismatch') +realm.pkinit('nocert', expected_code=1, expected_msg='Client name mismatch') + +success("certauth tests") diff --git a/krb5-1.21.3/src/tests/t_changepw.py b/krb5-1.21.3/src/tests/t_changepw.py new file mode 100755 index 00000000..bf8e3a9e --- /dev/null +++ b/krb5-1.21.3/src/tests/t_changepw.py @@ -0,0 +1,50 @@ +from k5test import * + +realm = K5Realm(create_host=False, get_creds=False, start_kadmind=True) +realm.prep_kadmin() + +# Mark a principal as expired and change its password through kinit. +mark('password change via kinit') +realm.run([kadminl, 'modprinc', '-pwexpire', '1 day ago', 'user']) +pwinput = password('user') + '\nabcd\nabcd\n' +realm.run([kinit, realm.user_princ], input=pwinput) + +# Regression test for #7868 (preauth options ignored when +# krb5_get_init_creds_password() initiates a password change). This +# time use the REQUIRES_PWCHANGE bit instead of the password +# expiration time. +mark('password change via kinit with FAST') +realm.run([kadminl, 'modprinc', '+needchange', 'user']) +pwinput = 'abcd\nefgh\nefgh\n' +out, trace = realm.run([kinit, '-T', realm.ccache, realm.user_princ], + input=pwinput, return_trace=True) +# Check that FAST was used when getting the kadmin/changepw ticket. +getting_changepw = fast_used_for_changepw = False +for line in trace.splitlines(): + if 'Getting initial credentials for user@' in line: + getting_changepw_ticket = False + if 'Setting initial creds service to kadmin/changepw' in line: + getting_changepw_ticket = True + if getting_changepw_ticket and 'Using FAST' in line: + fast_used_for_changepw = True +if not fast_used_for_changepw: + fail('FAST was not used to get kadmin/changepw ticket') + +# Test that passwords specified via kadmin and kpasswd are usable with +# kinit. +mark('password change usability by kinit') +realm.run([kadminl, 'addprinc', '-pw', 'pw1', 'testprinc']) +# Run kpasswd with an active cache to exercise automatic FAST use. +realm.kinit('testprinc', 'pw1') +realm.run([kpasswd, 'testprinc'], input='pw1\npw2\npw2\n') +realm.kinit('testprinc', 'pw2') +realm.run([kdestroy]) +realm.run([kpasswd, 'testprinc'], input='pw2\npw3\npw3\n') +realm.kinit('testprinc', 'pw3') +realm.run([kdestroy]) +realm.run_kadmin(['cpw', '-pw', 'pw4', 'testprinc']) +realm.kinit('testprinc', 'pw4') +realm.run([kdestroy]) +realm.run([kadminl, 'delprinc', 'testprinc']) + +success('Password change tests') diff --git a/krb5-1.21.3/src/tests/t_crossrealm.py b/krb5-1.21.3/src/tests/t_crossrealm.py new file mode 100755 index 00000000..28b397cf --- /dev/null +++ b/krb5-1.21.3/src/tests/t_crossrealm.py @@ -0,0 +1,192 @@ +# Copyright (C) 2011 by the Massachusetts Institute of Technology. +# All rights reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +from k5test import * + +def test_kvno(r, princ, test, env=None): + r.run([kvno, princ], env=env, expected_msg=princ) + + +def stop(*realms): + for r in realms: + r.stop() + + +# Verify that the princs appear as the service principals in the klist +# output for the realm r, in order. +def check_klist(r, princs): + out = r.run([klist]) + count = 0 + seen_header = False + for l in out.split('\n'): + if l.startswith('Valid starting'): + seen_header = True + continue + if not seen_header or l == '': + continue + if count >= len(princs): + fail('too many entries in klist output') + svcprinc = l.split()[4] + if svcprinc != princs[count]: + fail('saw service princ %s in klist output, expected %s' % + (svcprinc, princs[count])) + count += 1 + if count != len(princs): + fail('not enough entries in klist output') + + +def tgt(r1, r2): + return 'krbtgt/%s@%s' % (r1.realm, r2.realm) + + +# Basic two-realm test with cross TGTs in both directions. +mark('two realms') +r1, r2 = cross_realms(2) +test_kvno(r1, r2.host_princ, 'basic r1->r2') +check_klist(r1, (tgt(r1, r1), tgt(r2, r1), r2.host_princ)) +test_kvno(r2, r1.host_princ, 'basic r2->r1') +check_klist(r2, (tgt(r2, r2), tgt(r1, r2), r1.host_princ)) +stop(r1, r2) + +# Test the KDC domain walk for hierarchically arranged realms. The +# client in A.X will ask for a cross TGT to B.X, but A.X's KDC only +# has a TGT for the intermediate realm X, so it will return that +# instead. The client will use that to get a TGT for B.X. +mark('hierarchical realms') +r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)), + args=({'realm': 'A.X'}, {'realm': 'X'}, + {'realm': 'B.X'})) +test_kvno(r1, r3.host_princ, 'KDC domain walk') +check_klist(r1, (tgt(r1, r1), r3.host_princ)) + +# Test start_realm in this setup. +r1.run([kvno, '--out-cache', r1.ccache, r2.krbtgt_princ]) +r1.run([klist, '-C'], expected_msg='config: start_realm = X') +msgs = ('Requesting TGT krbtgt/B.X@X using TGT krbtgt/X@X', + 'Received TGT for service realm: krbtgt/B.X@X') +r1.run([kvno, r3.host_princ], expected_trace=msgs) + +stop(r1, r2, r3) + +# Test client capaths. The client in A will ask for a cross TGT to D, +# but A's KDC won't have it and won't know an intermediate to return. +# The client will walk its A->D capaths to get TGTs for B, then C, +# then D. The KDCs for C and D need capaths settings to avoid failing +# transited checks, including a capaths for A->C. +mark('client capaths') +capaths = {'capaths': {'A': {'D': ['B', 'C'], 'C': 'B'}}} +r1, r2, r3, r4 = cross_realms(4, xtgts=((0,1), (1,2), (2,3)), + args=({'realm': 'A'}, + {'realm': 'B'}, + {'realm': 'C', 'krb5_conf': capaths}, + {'realm': 'D', 'krb5_conf': capaths})) +r1client = r1.special_env('client', False, krb5_conf=capaths) +test_kvno(r1, r4.host_princ, 'client capaths', r1client) +check_klist(r1, (tgt(r1, r1), tgt(r2, r1), tgt(r3, r2), tgt(r4, r3), + r4.host_princ)) +stop(r1, r2, r3, r4) + +# Test KDC capaths. The KDCs for A and B have appropriate capaths +# settings to determine intermediate TGTs to return, but the client +# has no idea. +mark('kdc capaths') +capaths = {'capaths': {'A': {'D': ['B', 'C'], 'C': 'B'}, 'B': {'D': 'C'}}} +r1, r2, r3, r4 = cross_realms(4, xtgts=((0,1), (1,2), (2,3)), + args=({'realm': 'A', 'krb5_conf': capaths}, + {'realm': 'B', 'krb5_conf': capaths}, + {'realm': 'C', 'krb5_conf': capaths}, + {'realm': 'D', 'krb5_conf': capaths})) +r1client = r1.special_env('client', False, krb5_conf={'capaths': None}) +test_kvno(r1, r4.host_princ, 'KDC capaths', r1client) +check_klist(r1, (tgt(r1, r1), r4.host_princ)) +stop(r1, r2, r3, r4) + +# A capaths value of '.' should enforce direct cross-realm, with no +# intermediate. +mark('direct cross-realm enforcement') +capaths = {'capaths': {'A.X': {'B.X': '.'}}} +r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)), + args=({'realm': 'A.X', 'krb5_conf': capaths}, + {'realm': 'X'}, {'realm': 'B.X'})) +r1.run([kvno, r3.host_princ], expected_code=1, + expected_msg='Server krbtgt/B.X@A.X not found in Kerberos database') +stop(r1, r2, r3) + +# Test transited error. The KDC for C does not recognize B as an +# intermediate realm for A->C, so it refuses to issue a service +# ticket. +mark('transited error (three realms)') +capaths = {'capaths': {'A': {'C': 'B'}}} +r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)), + args=({'realm': 'A', 'krb5_conf': capaths}, + {'realm': 'B'}, {'realm': 'C'})) +r1.run([kvno, r3.host_princ], expected_code=1, + expected_msg='KDC policy rejects request') +check_klist(r1, (tgt(r1, r1), tgt(r3, r2))) +stop(r1, r2, r3) + +# Test server transited checking. The KDC for C recognizes B as an +# intermediate realm for A->C, but the server environment does not. +# The server should honor the ticket if the transited-policy-checked +# flag is set, but not if it isn't. (It is only possible for our KDC +# to issue a ticket without the transited-policy-checked flag with +# reject_bad_transit=false.) +mark('server transited checking') +capaths = {'capaths': {'A': {'C': 'B'}}} +noreject = {'realms': {'$realm': {'reject_bad_transit': 'false'}}} +r1, r2, r3 = cross_realms(3, xtgts=((0,1), (1,2)), + args=({'realm': 'A', 'krb5_conf': capaths}, + {'realm': 'B'}, + {'realm': 'C', 'krb5_conf': capaths, + 'kdc_conf': noreject})) +r3server = r3.special_env('server', False, krb5_conf={'capaths': None}) +# Process a ticket with the transited-policy-checked flag set. +shutil.copy(r1.ccache, r1.ccache + '.copy') +r1.run(['./gcred', 'principal', r3.host_princ]) +os.rename(r1.ccache, r3.ccache) +r3.run(['./rdreq', r3.host_princ], env=r3server, expected_msg='0 success') +# Try again with the transited-policy-checked flag unset. +os.rename(r1.ccache + '.copy', r1.ccache) +r1.run(['./gcred', '-t', 'principal', r3.host_princ]) +os.rename(r1.ccache, r3.ccache) +r3.run(['./rdreq', r3.host_princ], env=r3server, + expected_msg='43 Illegal cross-realm ticket') +stop(r1, r2, r3) + +# Test a four-realm scenario. This test used to result in an "Illegal +# cross-realm ticket" error as the KDC for D would refuse to process +# the cross-realm ticket from C. Now that we honor the +# transited-policy-checked flag in krb5_rd_req(), it instead issues a +# policy error as in the three-realm scenario. +mark('transited error (four realms)') +capaths = {'capaths': {'A': {'D': ['B', 'C'], 'C': 'B'}, 'B': {'D': 'C'}}} +r1, r2, r3, r4 = cross_realms(4, xtgts=((0,1), (1,2), (2,3)), + args=({'realm': 'A', 'krb5_conf': capaths}, + {'realm': 'B', 'krb5_conf': capaths}, + {'realm': 'C', 'krb5_conf': capaths}, + {'realm': 'D'})) +r1.run([kvno, r4.host_princ], expected_code=1, + expected_msg='KDC policy rejects request') +check_klist(r1, (tgt(r1, r1), tgt(r4, r3))) +stop(r1, r2, r3, r4) + +success('Cross-realm tests') diff --git a/krb5-1.21.3/src/tests/t_cve-2012-1014.py b/krb5-1.21.3/src/tests/t_cve-2012-1014.py new file mode 100755 index 00000000..8447e0ee --- /dev/null +++ b/krb5-1.21.3/src/tests/t_cve-2012-1014.py @@ -0,0 +1,29 @@ +import base64 +import socket +from k5test import * + +realm = K5Realm() + +# CVE-2012-1014 KDC dereferences uninitialized pointer + +# Affects only krb5-1.10.x. + +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +a = (hostname, realm.portbase) + +x1 = base64.b16decode('6A5E305BA103020105A2030201') +x2 = base64.b16decode('A44F304DA007030500FEDCBA90A10E30' + + '0CA003020101A10530031B0141A2031B' + + '0141A30E300CA003020101A10530031B' + + '0141A511180F31393934303631303036' + + '303331375AA70302012AA80530030201' + + '01') + +for x in range(11, 128): + s.sendto(x1 + bytes([x]) + x2, a) + +# Make sure kinit still works. + +realm.kinit(realm.user_princ, password('user')) + +success('CVE-2012-1014 regression test') diff --git a/krb5-1.21.3/src/tests/t_cve-2012-1015.py b/krb5-1.21.3/src/tests/t_cve-2012-1015.py new file mode 100755 index 00000000..ae5678ca --- /dev/null +++ b/krb5-1.21.3/src/tests/t_cve-2012-1015.py @@ -0,0 +1,36 @@ +import base64 +import socket +from k5test import * + +realm = K5Realm() + +# CVE-2012-1015 KDC frees uninitialized pointer + +# Force a failure in krb5_c_make_checksum(), which causes the cleanup +# code in kdc_handle_protected_negotiation() to free an uninitialized +# pointer in an unpatched KDC. + +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +a = (hostname, realm.portbase) + +x1 = base64.b16decode('6A81A030819DA103020105A20302010A' + + 'A30E300C300AA10402020095A2020400' + + 'A48180307EA00703050000000000A120' + + '301EA003020101A11730151B066B7262' + + '7467741B0B4B5242544553542E434F4D' + + 'A20D1B0B4B5242544553542E434F4DA3' + + '20301EA003020101A11730151B066B72' + + '627467741B0B4B5242544553542E434F' + + '4DA511180F3139393430363130303630' + + '3331375AA7030201') + +x2 = base64.b16decode('A8083006020106020112') + +for x in range(0, 128): + s.sendto(x1 + bytes([x]) + x2, a) + +# Make sure kinit still works. + +realm.kinit(realm.user_princ, password('user')) + +success('CVE-2012-1015 regression test') diff --git a/krb5-1.21.3/src/tests/t_cve-2013-1416.py b/krb5-1.21.3/src/tests/t_cve-2013-1416.py new file mode 100755 index 00000000..8c4391a8 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_cve-2013-1416.py @@ -0,0 +1,13 @@ +from k5test import * + +realm = K5Realm() + +# CVE-2013-1416 KDC dereferences null pointer + +realm.kinit(realm.user_princ, password('user')) +realm.run([kvno, '/test'], expected_code=1) +realm.run([kvno, 'test/'], expected_code=1) +realm.run([kvno, '/'], expected_code=1) +# Make sure KDC is still running. +realm.kinit(realm.user_princ, password('user')) +success('CVE-2013-1416 regression test') diff --git a/krb5-1.21.3/src/tests/t_cve-2013-1417.py b/krb5-1.21.3/src/tests/t_cve-2013-1417.py new file mode 100755 index 00000000..ce47d21c --- /dev/null +++ b/krb5-1.21.3/src/tests/t_cve-2013-1417.py @@ -0,0 +1,11 @@ +from k5test import * + +realm = K5Realm(realm='TEST') + +# CVE-2013-1417 KDC dereferences null pointer + +realm.kinit(realm.user_princ, password('user')) +realm.run([kvno, '-S', 'host', 'example.com'], expected_code=1) +# Make sure KDC is still running. +realm.kinit(realm.user_princ, password('user')) +success('CVE-2013-1417 regression test') diff --git a/krb5-1.21.3/src/tests/t_cve-2021-36222.py b/krb5-1.21.3/src/tests/t_cve-2021-36222.py new file mode 100644 index 00000000..57e04993 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_cve-2021-36222.py @@ -0,0 +1,46 @@ +import socket +from k5test import * + +realm = K5Realm() + +# CVE-2021-36222 KDC null dereference on encrypted challenge preauth +# without FAST + +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +a = (hostname, realm.portbase) + +m = ('6A81A0' '30819D' # [APPLICATION 10] SEQUENCE + 'A103' '0201' '05' # [1] pvno = 5 + 'A203' '0201' '0A' # [2] msg-type = 10 + 'A30E' '300C' # [3] padata = SEQUENCE OF + '300A' # SEQUENCE + 'A104' '0202' '008A' # [1] padata-type = PA-ENCRYPTED-CHALLENGE + 'A202' '0400' # [2] padata-value = "" + 'A48180' '307E' # [4] req-body = SEQUENCE + 'A007' '0305' '0000000000' # [0] kdc-options = 0 + 'A120' '301E' # [1] cname = SEQUENCE + 'A003' '0201' '01' # [0] name-type = NT-PRINCIPAL + 'A117' '3015' # [1] name-string = SEQUENCE-OF + '1B06' '6B7262746774' # krbtgt + '1B0B' '4B5242544553542E434F4D' + # KRBTEST.COM + 'A20D' '1B0B' '4B5242544553542E434F4D' + # [2] realm = KRBTEST.COM + 'A320' '301E' # [3] sname = SEQUENCE + 'A003' '0201' '01' # [0] name-type = NT-PRINCIPAL + 'A117' '3015' # [1] name-string = SEQUENCE-OF + '1B06' '6B7262746774' # krbtgt + '1B0B' '4B5242544553542E434F4D' + # KRBTEST.COM + 'A511' '180F' '31393934303631303036303331375A' + # [5] till = 19940610060317Z + 'A703' '0201' '00' # [7] nonce = 0 + 'A808' '3006' # [8] etype = SEQUENCE OF + '020112' '020111') # aes256-cts aes128-cts + +s.sendto(bytes.fromhex(m), a) + +# Make sure kinit still works. +realm.kinit(realm.user_princ, password('user')) + +success('CVE-2021-36222 regression test') diff --git a/krb5-1.21.3/src/tests/t_dump.py b/krb5-1.21.3/src/tests/t_dump.py new file mode 100755 index 00000000..5d692df9 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_dump.py @@ -0,0 +1,94 @@ +from k5test import * +from filecmp import cmp + +def dump_compare(realm, opt, srcfile): + mark('dump comparison against %s' % os.path.basename(srcfile)) + realm.run([kdb5_util, 'dump'] + opt + [dumpfile]) + if not cmp(srcfile, dumpfile, False): + fail('Dump output does not match %s' % srcfile) + + +def load_dump_check_compare(realm, opt, srcfile): + mark('load check from %s' % os.path.basename(srcfile)) + realm.run([kdb5_util, 'destroy', '-f']) + realm.run([kdb5_util, 'load'] + opt + [srcfile]) + realm.run([kadminl, 'getprincs'], expected_msg='user@') + realm.run([kadminl, 'getprinc', 'nokeys'], + expected_msg='Number of keys: 0') + realm.run([kadminl, 'getpols'], expected_msg='testpol') + dump_compare(realm, opt, srcfile) + + +for realm in multidb_realms(start_kdc=False): + + # Make sure we can dump and load an ordinary database, and that + # principals and policies survive a dump/load cycle. + + realm.run([kadminl, 'addpol', 'fred']) + + # Create a dump file. + dumpfile = os.path.join(realm.testdir, 'dump') + realm.run([kdb5_util, 'dump', dumpfile]) + + # Write additional policy records to the dump. Use the 1.8 format for + # one of them, to test retroactive compatibility (for issue #8213). + f = open('testdir/dump', 'a') + f.write('policy\tcompat\t0\t0\t3\t4\t5\t0\t0\t0\t0\n') + f.write('policy\tbarney\t0\t0\t1\t1\t1\t0\t0\t0\t0\t0\t0\t0\t-\t1\t2\t28\t' + 'fd100f5064625f6372656174696f6e404b5242544553542e434f4d00\n') + f.close() + + # Destroy and load the database; check that the policies exist. + # Spot-check principal and policy fields. + mark('reload after dump') + realm.run([kdb5_util, 'destroy', '-f']) + realm.run([kdb5_util, 'load', dumpfile]) + out = realm.run([kadminl, 'getprincs']) + if realm.user_princ not in out or realm.host_princ not in out: + fail('Missing principal after load') + out = realm.run([kadminl, 'getprinc', realm.user_princ]) + if 'Expiration date: [never]' not in out or 'MKey: vno 1' not in out: + fail('Principal has wrong value after load') + out = realm.run([kadminl, 'getpols']) + if 'fred\n' not in out or 'barney\n' not in out: + fail('Missing policy after load') + realm.run([kadminl, 'getpol', 'compat'], + expected_msg='Number of old keys kept: 5') + realm.run([kadminl, 'getpol', 'barney'], + expected_msg='Number of old keys kept: 1') + + # Dump/load again, and make sure everything is still there. + mark('second reload') + realm.run([kdb5_util, 'dump', dumpfile]) + realm.run([kdb5_util, 'load', dumpfile]) + out = realm.run([kadminl, 'getprincs']) + if realm.user_princ not in out or realm.host_princ not in out: + fail('Missing principal after load') + out = realm.run([kadminl, 'getpols']) + if 'compat\n' not in out or 'fred\n' not in out or 'barney\n' not in out: + fail('Missing policy after second load') + + srcdumpdir = os.path.join(srctop, 'tests', 'dumpfiles') + srcdump = os.path.join(srcdumpdir, 'dump') + srcdump_r18 = os.path.join(srcdumpdir, 'dump.r18') + srcdump_r13 = os.path.join(srcdumpdir, 'dump.r13') + srcdump_b7 = os.path.join(srcdumpdir, 'dump.b7') + + # Load a dump file from the source directory. + realm.run([kdb5_util, 'destroy', '-f']) + realm.run([kdb5_util, 'load', srcdump]) + realm.run([kdb5_util, 'stash', '-P', 'master']) + + # Dump the resulting DB in each non-iprop format and compare with + # expected outputs. + dump_compare(realm, [], srcdump) + dump_compare(realm, ['-r18'], srcdump_r18) + dump_compare(realm, ['-r13'], srcdump_r13) + dump_compare(realm, ['-b7'], srcdump_b7) + + # Load each format of dump, check it, re-dump it, and compare. + load_dump_check_compare(realm, ['-r18'], srcdump_r18) + load_dump_check_compare(realm, ['-r13'], srcdump_r13) + load_dump_check_compare(realm, ['-b7'], srcdump_b7) + +success('Dump/load tests') diff --git a/krb5-1.21.3/src/tests/t_errmsg.py b/krb5-1.21.3/src/tests/t_errmsg.py new file mode 100755 index 00000000..4aacf4e0 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_errmsg.py @@ -0,0 +1,27 @@ +from k5test import * + +realm = K5Realm(create_kdb=False) + +# Test err_fmt, using klist -c to induce errors. +fmt1 = 'FOO Error: %M (see http://localhost:1234/%C for more information)' +conf1 = {'libdefaults': {'err_fmt': fmt1}} +e1 = realm.special_env('fmt1', False, krb5_conf=conf1) +out = realm.run([klist, '-c', 'testdir/xx/yy'], env=e1, expected_code=1) +if out != ('klist: FOO Error: No credentials cache found (filename: ' + 'testdir/xx/yy) (see http://localhost:1234/-1765328189 for more ' + 'information)\n'): + fail('err_fmt expansion failed') +conf2 = {'libdefaults': {'err_fmt': '%M - %C'}} +e2 = realm.special_env('fmt2', False, krb5_conf=conf2) +out = realm.run([klist, '-c', 'testdir/xx/yy'], env=e2, expected_code=1) +if out != ('klist: No credentials cache found (filename: testdir/xx/yy) - ' + '-1765328189\n'): + fail('err_fmt expansion failed') +conf3 = {'libdefaults': {'err_fmt': '%%%M %-% %C%'}} +e3 = realm.special_env('fmt3', False, krb5_conf=conf3) +out = realm.run([klist, '-c', 'testdir/xx/yy'], env=e3, expected_code=1) +if out != ('klist: %No credentials cache found (filename: testdir/xx/yy) %-% ' + '-1765328189%\n'): + fail('err_fmt expansion failed') + +success('error message tests') diff --git a/krb5-1.21.3/src/tests/t_etype_info.py b/krb5-1.21.3/src/tests/t_etype_info.py new file mode 100644 index 00000000..38cf96ca --- /dev/null +++ b/krb5-1.21.3/src/tests/t_etype_info.py @@ -0,0 +1,69 @@ +from k5test import * + +supported_enctypes = 'aes128-cts des3-cbc-sha1 rc4-hmac' +conf = {'libdefaults': {'allow_des3': 'true', 'allow_rc4': 'true'}, + 'realms': {'$realm': {'supported_enctypes': supported_enctypes}}} +realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf) + +realm.run([kadminl, 'addprinc', '-pw', 'pw', '+requires_preauth', + 'preauthuser']) +realm.run([kadminl, 'addprinc', '-pw', 'pw', '-e', 'rc4-hmac', + '+requires_preauth', 'rc4user']) +realm.run([kadminl, 'addprinc', '-nokey', '+requires_preauth', 'nokeyuser']) + + +# Run the test harness for the given principal and request enctype +# list. Compare the output to the expected lines, ignoring order. +def test_etinfo(princ, enctypes, expected_lines): + mark('etinfo test: %s %s' % (princ.partition('@')[0], enctypes)) + conf = {'libdefaults': {'default_tkt_enctypes': enctypes}} + etypes_env = realm.special_env('etypes', False, krb5_conf=conf) + lines = realm.run(['./etinfo', princ], env=etypes_env).splitlines() + if sorted(lines) != sorted(expected_lines): + fail('Unexpected output for princ %s, etypes %s' % (princ, enctypes)) + + +# With no newer enctypes in the request, PA-ETYPE-INFO2, +# PA-ETYPE-INFO, and PA-PW-SALT appear in the AS-REP, each listing one +# key for the most preferred matching enctype. +test_etinfo('user', 'rc4-hmac-exp des3 rc4', + ['asrep etype_info2 des3-cbc-sha1 KRBTEST.COMuser', + 'asrep etype_info des3-cbc-sha1 KRBTEST.COMuser', + 'asrep pw_salt KRBTEST.COMuser']) + +# With a newer enctype in the request (even if it is not the most +# preferred enctype and doesn't match any keys), only PA-ETYPE-INFO2 +# appears. +test_etinfo('user', 'rc4 aes256-cts', + ['asrep etype_info2 rc4-hmac KRBTEST.COMuser']) + +# In preauth-required errors, PA-PW-SALT does not appear, but the same +# etype-info2 values are expected. +test_etinfo('preauthuser', 'rc4-hmac-exp des3 rc4', + ['error etype_info2 des3-cbc-sha1 KRBTEST.COMpreauthuser', + 'error etype_info des3-cbc-sha1 KRBTEST.COMpreauthuser']) +test_etinfo('preauthuser', 'rc4 aes256-cts', + ['error etype_info2 rc4-hmac KRBTEST.COMpreauthuser']) + +# If no keys are found matching the request enctypes, a +# preauth-required error can be generated with no etype-info at all +# (to allow for preauth mechs which don't depend on long-term keys). +# An AS-REP cannot be generated without preauth as there is no reply +# key. +test_etinfo('rc4user', 'des3', []) +test_etinfo('nokeyuser', 'des3', []) + +# Verify that etype-info2 is included in a MORE_PREAUTH_DATA_REQUIRED +# error if the client does optimistic preauth. +mark('MORE_PREAUTH_DATA_REQUIRED test') +realm.stop() +testpreauth = os.path.join(buildtop, 'plugins', 'preauth', 'test', 'test.so') +conf = {'plugins': {'kdcpreauth': {'module': 'test:' + testpreauth}, + 'clpreauth': {'module': 'test:' + testpreauth}}} +realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf) +realm.run([kadminl, 'setstr', realm.user_princ, '2rt', '2rtval']) +out = realm.run(['./etinfo', realm.user_princ, '-123']) +if out != 'more etype_info2 aes256-cts KRBTEST.COMuser\n': + fail('Unexpected output for MORE_PREAUTH_DATA_REQUIRED test') + +success('KDC etype-info tests') diff --git a/krb5-1.21.3/src/tests/t_general.py b/krb5-1.21.3/src/tests/t_general.py new file mode 100755 index 00000000..8e81db1a --- /dev/null +++ b/krb5-1.21.3/src/tests/t_general.py @@ -0,0 +1,74 @@ +from k5test import * + +for realm in multipass_realms(create_host=False): + # Check that kinit fails appropriately with the wrong password. + mark('kinit wrong password failure') + msg = 'Password incorrect while getting initial credentials' + realm.run([kinit, realm.user_princ], input='wrong\n', expected_code=1, + expected_msg=msg) + + # Check that we can kinit as a different principal. + mark('kinit with specified principal') + realm.kinit(realm.admin_princ, password('admin')) + realm.klist(realm.admin_princ) + + # Test FAST kinit. + mark('FAST kinit') + fastpw = password('fast') + realm.run([kadminl, 'ank', '-pw', fastpw, '+requires_preauth', + 'user/fast']) + realm.kinit('user/fast', fastpw) + realm.kinit('user/fast', fastpw, flags=['-T', realm.ccache]) + realm.klist('user/fast@%s' % realm.realm) + + # Test kinit against kdb keytab + realm.run([kinit, "-k", "-t", "KDB:", realm.user_princ]) + +# Test that we can get initial creds with an empty password via the +# API. We have to disable the "empty" pwqual module to create a +# principal with an empty password. (Regression test for #7642.) +mark('initial creds with empty password') +conf={'plugins': {'pwqual': {'disable': 'empty'}}} +realm = K5Realm(create_user=False, create_host=False, krb5_conf=conf) +realm.run([kadminl, 'addprinc', '-pw', '', 'user']) +realm.run(['./icred', 'user', '']) +realm.run(['./icred', '-s', 'user', '']) +realm.stop() + +realm = K5Realm(create_host=False) + +# Regression test for #6428 (KDC should prefer account expiration +# error to password expiration error). +mark('#6428 regression test') +realm.run([kadminl, 'addprinc', '-randkey', '-pwexpire', 'yesterday', 'xpr']) +realm.run(['./icred', 'xpr'], expected_code=1, + expected_msg='Password has expired') +realm.run([kadminl, 'modprinc', '-expire', 'yesterday', 'xpr']) +realm.run(['./icred', 'xpr'], expected_code=1, + expected_msg="Client's entry in database has expired") + +# Regression test for #8454 (responder callback isn't used when +# preauth is not required). +mark('#8454 regression test') +realm.run(['./responder', '-r', 'password=%s' % password('user'), + realm.user_princ]) + +# Test that WRONG_REALM responses aren't treated as referrals unless +# they contain a crealm field pointing to a different realm. +# (Regression test for #8060.) +mark('#8060 regression test') +realm.run([kinit, '-C', 'notfoundprinc'], expected_code=1, + expected_msg='not found in Kerberos database') + +# Spot-check KRB5_TRACE output +mark('KRB5_TRACE spot check') +expected_trace = ('Sending initial UDP request', + 'Received answer', + 'Selected etype info', + 'AS key obtained', + 'Decrypted AS reply', + 'FAST negotiation: available', + 'Storing user@KRBTEST.COM') +realm.kinit(realm.user_princ, password('user'), expected_trace=expected_trace) + +success('FAST kinit, trace logging') diff --git a/krb5-1.21.3/src/tests/t_hooks.py b/krb5-1.21.3/src/tests/t_hooks.py new file mode 100755 index 00000000..4fd3822e --- /dev/null +++ b/krb5-1.21.3/src/tests/t_hooks.py @@ -0,0 +1,8 @@ +from k5test import * + +# Test that KDC send and recv hooks work correctly. +realm = K5Realm(create_host=False, get_creds=False) +realm.run(['./hooks', realm.user_princ, password('user')]) +realm.stop() + +success('send and recv hook tests') diff --git a/krb5-1.21.3/src/tests/t_hostrealm.py b/krb5-1.21.3/src/tests/t_hostrealm.py new file mode 100755 index 00000000..40b0e1e0 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_hostrealm.py @@ -0,0 +1,140 @@ +from k5test import * + +plugin = os.path.join(buildtop, "plugins", "hostrealm", "test", + "hostrealm_test.so") + +# Disable the "dns" module (we can't easily test TXT lookups) and +# arrange the remaining modules in an order which makes sense for most +# tests. +conf = {'plugins': {'hostrealm': {'module': ['test1:' + plugin, + 'test2:' + plugin], + 'enable_only': ['test2', 'profile', + 'domain', 'test1']}}, + 'domain_realm': {'.x': 'DOTMATCH', 'x': 'MATCH', '.1': 'NUMMATCH'}} +realm = K5Realm(krb5_conf=conf, create_kdb=False) + +def test(realm, args, expected_realms, msg, env=None): + out = realm.run(['./hrealm'] + args, env=env) + if out.split('\n') != expected_realms + ['']: + fail(msg) + +def test_error(realm, args, expected_error, msg, env=None): + realm.run(['./hrealm'] + args, env=env, expected_code=1, + expected_msg=expected_error) + +def testh(realm, host, expected_realms, msg, env=None): + test(realm, ['-h', host], expected_realms, msg, env=env) +def testf(realm, host, expected_realms, msg, env=None): + test(realm, ['-f', host], expected_realms, msg, env=env) +def testd(realm, expected_realm, msg, env=None): + test(realm, ['-d'], [expected_realm], msg, env=env) +def testh_error(realm, host, expected_error, msg, env=None): + test_error(realm, ['-h', host], expected_error, msg, env=env) +def testf_error(realm, host, expected_error, msg, env=None): + test_error(realm, ['-f', host], expected_error, msg, env=env) +def testd_error(realm, expected_error, msg, env=None): + test_error(realm, ['-d'], expected_error, msg, env=env) + +### +### krb5_get_host_realm tests +### + +# The test2 module returns a fatal error on hosts beginning with 'z', +# and an answer on hosts beginning with 'a'. +mark('test2 module') +testh_error(realm, 'zoo', 'service not available', 'host_realm test2 z') +testh(realm, 'abacus', ['a'], 'host_realm test2 a') + +# The profile module gives answers for hostnames equal to or ending in +# 'X', due to [domain_realms]. There is also an entry for hostnames +# ending in '1', but hostnames which appear to be IP or IPv6 addresses +# should instead fall through to test1. +mark('profile module') +testh(realm, 'x', ['MATCH'], 'host_realm profile x') +testh(realm, '.x', ['DOTMATCH'], 'host_realm profile .x') +testh(realm, 'b.x', ['DOTMATCH'], 'host_realm profile b.x') +testh(realm, '.b.c.x', ['DOTMATCH'], 'host_realm profile .b.c.x') +testh(realm, 'b.1', ['NUMMATCH'], 'host_realm profile b.1') +testh(realm, '4.3.2.1', ['4', '3', '2', '1'], 'host_realm profile 4.3.2.1') +testh(realm, 'b:c.x', ['b:c', 'x'], 'host_realm profile b:c.x') +# hostname cleaning should convert "X." to "x" before matching. +testh(realm, 'X.', ['MATCH'], 'host_realm profile X.') + +# The test1 module returns a list of the hostname components. +mark('test1 module') +testh(realm, 'b.c.d', ['b', 'c', 'd'], 'host_realm test1') + +# If no module returns a result, we should get the referral realm. +mark('no result') +testh(realm, '', [''], 'host_realm referral realm') + +### +### krb5_get_fallback_host_realm tests +### + +# Return a special environment with realm_try_domains set to n. +def try_env(realm, testname, n): + conf = {'libdefaults': {'realm_try_domains': str(n)}} + return realm.special_env(testname, False, krb5_conf=conf) + +# The domain module will answer with the uppercased parent domain, +# with no special configuration. +mark('fallback: domain module') +testf(realm, 'a.b.c', ['B.C'], 'fallback_realm domain a.b.c') + +# With realm_try_domains = 0, the hostname itself will be looked up as +# a realm and returned if found. +mark('fallback: realm_try_domains = 0') +try0 = try_env(realm, 'try0', 0) +testf(realm, 'krbtest.com', ['KRBTEST.COM'], 'fallback_realm try0', env=try0) +testf(realm, 'a.b.krbtest.com', ['B.KRBTEST.COM'], + 'fallback_realm try0 grandparent', env=try0) +testf(realm, 'a.b.c', ['B.C'], 'fallback_realm try0 nomatch', env=try0) + +# With realm_try_domains = 2, the parent and grandparent will be +# checked as well, but it stops there. +mark('fallback: realm_try_domains = 2') +try2 = try_env(realm, 'try2', 2) +testf(realm, 'krbtest.com', ['KRBTEST.COM'], 'fallback_realm try2', env=try2) +testf(realm, 'a.b.krbtest.com', ['KRBTEST.COM'], + 'fallback_realm try2 grandparent', env=try2) +testf(realm, 'a.b.c.krbtest.com', ['B.C.KRBTEST.COM'], + 'fallback_realm try2 great-grandparent', env=try2) + +# The test1 module answers with a list of components. Use an IPv4 +# address to bypass the domain module. +mark('fallback: test1 module') +testf(realm, '1.2.3.4', ['1', '2', '3', '4'], 'fallback_realm test1') + +# If no module answers, the default realm is returned. The test2 +# module returns an error when we try to look that up. +mark('fallback: default realm') +testf_error(realm, '', 'service not available', 'fallback_realm default') + +### +### krb5_get_default_realm tests +### + +# The test2 module returns an error. +mark('default_realm: test2 module') +testd_error(realm, 'service not available', 'default_realm test2') + +# The profile module returns the default realm from the profile. +# Disable test2 to expose this behavior. +mark('default_realm: profile module') +disable_conf = {'plugins': {'hostrealm': {'disable': 'test2'}}} +notest2 = realm.special_env('notest2', False, krb5_conf=disable_conf) +testd(realm, 'KRBTEST.COM', 'default_realm profile', env=notest2) + +# The test1 module returns a list of two realms, of which we can only +# see the first. Remove the profile default_realm setting to expose +# this behavior. +mark('default_realm: test1 module') +remove_default = {'libdefaults': {'default_realm': None}} +# Python 3.5+: nodefault_conf = {**disable_conf, **remove_default} +nodefault_conf = dict(list(disable_conf.items()) + + list(remove_default.items())) +nodefault = realm.special_env('nodefault', False, krb5_conf=nodefault_conf) +testd(realm, 'one', 'default_realm test1', env=nodefault) + +success('hostrealm interface tests') diff --git a/krb5-1.21.3/src/tests/t_inetd.c b/krb5-1.21.3/src/tests/t_inetd.c new file mode 100644 index 00000000..d22cf31f --- /dev/null +++ b/krb5-1.21.3/src/tests/t_inetd.c @@ -0,0 +1,129 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/t_inetd.c */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * A simple program to simulate starting a process from inetd. + * + * Unlike a proper inetd situation, environment variables are passed + * to the client. + * + * usage: t_inetd port program argv0 ... + */ + +#include "autoconf.h" + +#ifdef HAVE_STDLIB_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "com_err.h" + + +char *progname; + +static void usage() +{ + fprintf(stderr, "%s: port program argv0 argv1 ...\n", progname); + exit(1); +} + +int +main(argc, argv) + int argc; + char **argv; +{ + unsigned short port; + char *path; + int sock, acc; + int one = 1; + struct sockaddr_in l_inaddr, f_inaddr; /* local, foreign address */ + socklen_t namelen = sizeof(f_inaddr); + + progname = argv[0]; + + if(argc <= 3) usage(); + + if(atoi(argv[1]) == 0) usage(); + + port = htons(atoi(argv[1])); + path = argv[2]; + + if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { + com_err(progname, errno, "creating socket"); + exit(3); + } + + (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, + sizeof (one)); + + memset(&l_inaddr, 0, sizeof(l_inaddr)); + l_inaddr.sin_family = AF_INET; + l_inaddr.sin_addr.s_addr = 0; + l_inaddr.sin_port = port; + + if (bind(sock, (struct sockaddr *)&l_inaddr, sizeof(l_inaddr))) { + com_err(progname, errno, "binding socket"); + exit(3); + } + + if (listen(sock, 1) == -1) { + com_err(progname, errno, "listening"); + exit(3); + } + + printf("Ready!\n"); + fflush(stdout); + if ((acc = accept(sock, (struct sockaddr *)&f_inaddr, + &namelen)) == -1) { + com_err(progname, errno, "accepting"); + exit(3); + } + + dup2(acc, 0); + dup2(acc, 1); + dup2(acc, 2); + close(sock); + sock = 0; + + if(execv(path, &argv[3])) + fprintf(stderr, "t_inetd: Could not exec %s\n", path); + exit(1); +} diff --git a/krb5-1.21.3/src/tests/t_iprop.py b/krb5-1.21.3/src/tests/t_iprop.py new file mode 100755 index 00000000..b356971d --- /dev/null +++ b/krb5-1.21.3/src/tests/t_iprop.py @@ -0,0 +1,494 @@ +import os +import re + +from k5test import * + +# On macOS with System Integrity Protection enabled, this script hangs +# in the wait_for_prop() call after starting the first kpropd process, +# most likely due to signal restrictions preventing the listening +# child from informing the parent that a full resync was processed. +if which('csrutil'): + out = subprocess.check_output(['csrutil', 'status'], + universal_newlines=True) + if 'status: enabled' in out: + skip_rest('iprop tests', 'System Integrity Protection is enabled') + +# Read lines from kpropd output until we are synchronized. Error if +# full_expected is true and we didn't see a full propagation or vice +# versa. +def wait_for_prop(kpropd, full_expected, expected_old, expected_new): + output('*** Waiting for sync from kpropd\n') + full_seen = sleep_seen = False + old_sno = new_sno = -1 + while True: + line = kpropd.stdout.readline() + if line == '': + fail('kpropd process exited unexpectedly') + output('kpropd: ' + line) + + m = re.match(r'Calling iprop_get_updates_1 \(sno=(\d+) ', line) + if m: + if not full_seen: + old_sno = int(m.group(1)) + # Also record this as the new sno, in case we get back + # UPDATE_NIL. + new_sno = int(m.group(1)) + + m = re.match(r'Got incremental updates \(sno=(\d+) ', line) + if m: + new_sno = int(m.group(1)) + + if 'KDC is synchronized' in line or 'Incremental updates:' in line: + break + + # After a full resync request, these lines could appear in + # either order. + if 'Waiting for' in line: + sleep_seen = True + if 'load process for full propagation completed' in line: + full_seen = True + + # Detect some failure conditions. + if 'Still waiting for full resync' in line: + fail('kadmind gave consecutive full resyncs') + if 'Rejected connection' in line: + fail('kpropd rejected kprop connection') + if 'get updates failed' in line: + fail('iprop_get_updates failed') + if 'permission denied' in line: + fail('kadmind denied update') + if ('error from primary' in line or + 'error returned from primary' in line): + fail('kadmind reported error') + if 'invalid return' in line: + fail('kadmind returned invalid result') + + if full_expected and not full_seen: + fail('Expected full dump but saw only incremental') + if full_seen and not full_expected: + fail('Expected incremental prop but saw full dump') + if old_sno != expected_old: + fail('Expected old serial %d from kpropd sync' % expected_old) + if new_sno != expected_new: + fail('Expected new serial %d from kpropd sync' % expected_new) + + # Wait until kpropd is sleeping before continuing, to avoid races. + # (This is imperfect since there's there is a short window between + # the fprintf and the sleep; kpropd will need design changes to + # fix that.) + while True: + line = kpropd.stdout.readline() + output('kpropd: ' + line) + if 'Waiting for' in line: + break + output('*** Sync complete\n') + +# Verify the output of kproplog against the expected number of +# entries, first and last serial number, and a list of principal names +# for the update entrires. +def check_ulog(num, first, last, entries, env=None): + out = realm.run([kproplog], env=env) + if 'Number of entries : ' + str(num) + '\n' not in out: + fail('Expected %d entries' % num) + if last: + firststr = first and str(first) or 'None' + if 'First serial # : ' + firststr + '\n' not in out: + fail('Expected first serial number %d' % first) + laststr = last and str(last) or 'None' + if 'Last serial # : ' + laststr + '\n' not in out: + fail('Expected last serial number %d' % last) + assert(len(entries) == num) + ser = first - 1 + entindex = 0 + for line in out.splitlines(): + m = re.match(r'\tUpdate serial # : (\d+)$', line) + if m: + ser = ser + 1 + if m.group(1) != str(ser): + fail('Expected serial number %d in update entry' % ser) + m = re.match(r'\tUpdate principal : (.*)$', line) + if m: + eprinc = entries[ser - first] + if eprinc == None: + fail('Expected dummy update entry %d' % ser) + elif m.group(1) != eprinc: + fail('Expected princ %s in update entry %d' % (eprinc, ser)) + if line == '\tDummy entry': + eprinc = entries[ser - first] + if eprinc != None: + fail('Expected princ %s in update entry %d' % (eprinc, ser)) + +# replica1 will receive updates from primary, and replica2 will +# receive updates from replica1. Because of the awkward way iprop and +# kprop port configuration currently works, we need separate config +# files for the replica and primary sides of replica1, but they use +# the same DB and ulog file. +conf = {'realms': {'$realm': {'iprop_enable': 'true', + 'iprop_logfile': '$testdir/db.ulog'}}} +conf_rep1 = {'realms': {'$realm': {'iprop_replica_poll': '600', + 'iprop_logfile': '$testdir/ulog.replica1'}}, + 'dbmodules': {'db': {'database_name': '$testdir/db.replica1'}}} +conf_rep1m = {'realms': {'$realm': {'iprop_logfile': '$testdir/ulog.replica1', + 'iprop_port': '$port8'}}, + 'dbmodules': {'db': {'database_name': '$testdir/db.replica1'}}} +conf_rep2 = {'realms': {'$realm': {'iprop_replica_poll': '600', + 'iprop_logfile': '$testdir/ulog.replica2', + 'iprop_port': '$port8'}}, + 'dbmodules': {'db': {'database_name': '$testdir/db.replica2'}}} + +conf_foo = {'libdefaults': {'default_realm': 'FOO'}, + 'domain_realm': {hostname: 'FOO'}} +conf_rep3 = {'realms': {'$realm': {'iprop_replica_poll': '600', + 'iprop_logfile': '$testdir/ulog.replica3', + 'iprop_port': '$port8'}, + 'FOO': {'iprop_logfile': '$testdir/ulog.replica3'}}, + 'dbmodules': {'db': {'database_name': '$testdir/db.replica3'}}} + +krb5_conf_rep4 = {'domain_realm': {hostname: 'FOO'}} +conf_rep4 = {'realms': {'$realm': {'iprop_replica_poll': '600', + 'iprop_logfile': '$testdir/ulog.replica4', + 'iprop_port': '$port8'}}, + 'dbmodules': {'db': {'database_name': '$testdir/db.replica4'}}} + +for realm in multidb_realms(kdc_conf=conf, create_user=False, + start_kadmind=True): + replica1 = realm.special_env('replica1', True, kdc_conf=conf_rep1) + replica1m = realm.special_env('replica1m', True, krb5_conf=conf_foo, + kdc_conf=conf_rep1m) + replica2 = realm.special_env('replica2', True, kdc_conf=conf_rep2) + + # A default_realm and domain_realm that do not match the KDC's + # realm. The FOO realm iprop_logfile setting is needed to run + # kproplog during a replica3 test, since kproplog has no realm + # option. + replica3 = realm.special_env('replica3', True, krb5_conf=conf_foo, + kdc_conf=conf_rep3) + + # A default realm and a domain realm map that differ. + replica4 = realm.special_env('replica4', True, krb5_conf=krb5_conf_rep4, + kdc_conf=conf_rep4) + + # Define some principal names. pr3 is long enough to cause internal + # reallocs, but not long enough to grow the basic ulog entry size. + pr1 = 'wakawaka@' + realm.realm + pr2 = 'w@' + realm.realm + c = 'chocolate-flavored-school-bus' + cs = c + '/' + pr3 = (cs + cs + cs + cs + cs + cs + cs + cs + cs + cs + cs + cs + c + + '@' + realm.realm) + + # Create the kpropd ACL file. + acl_file = os.path.join(realm.testdir, 'kpropd-acl') + acl = open(acl_file, 'w') + acl.write(realm.host_princ + '\n') + acl.close() + + ulog = os.path.join(realm.testdir, 'db.ulog') + if not os.path.exists(ulog): + fail('update log not created: ' + ulog) + + # Create the principal used to authenticate kpropd to kadmind. + kiprop_princ = 'kiprop/' + hostname + realm.addprinc(kiprop_princ) + realm.extract_keytab(kiprop_princ, realm.keytab) + + # Create the initial replica databases. + dumpfile = os.path.join(realm.testdir, 'dump') + realm.run([kdb5_util, 'dump', dumpfile]) + realm.run([kdb5_util, 'load', dumpfile], replica1) + realm.run([kdb5_util, 'load', dumpfile], replica2) + realm.run([kdb5_util, '-r', realm.realm, 'load', dumpfile], replica3) + realm.run([kdb5_util, 'load', dumpfile], replica4) + + # Reinitialize the primary ulog so we know exactly what to expect + # in it. + realm.run([kproplog, '-R']) + check_ulog(1, 1, 1, [None]) + + # Make some changes to the primary DB. + realm.addprinc(pr1) + realm.addprinc(pr3) + realm.addprinc(pr2) + realm.run([kadminl, 'modprinc', '-allow_tix', pr2]) + realm.run([kadminl, 'modprinc', '+allow_tix', pr2]) + check_ulog(6, 1, 6, [None, pr1, pr3, pr2, pr2, pr2]) + + # Start kpropd for replica1 and get a full dump from primary. + mark('propagate M->1 full') + kpropd1 = realm.start_kpropd(replica1, ['-d']) + wait_for_prop(kpropd1, True, 1, 6) + out = realm.run([kadminl, 'listprincs'], env=replica1) + if pr1 not in out or pr2 not in out or pr3 not in out: + fail('replica1 does not have all principals from primary') + check_ulog(1, 6, 6, [None], replica1) + + # Make a change and check that it propagates incrementally. + mark('propagate M->1 incremental') + realm.run([kadminl, 'modprinc', '-allow_tix', pr2]) + check_ulog(7, 1, 7, [None, pr1, pr3, pr2, pr2, pr2, pr2]) + kpropd1.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd1, False, 6, 7) + check_ulog(2, 6, 7, [None, pr2], replica1) + realm.run([kadminl, 'getprinc', pr2], env=replica1, + expected_msg='Attributes: DISALLOW_ALL_TIX') + + # Start kadmind -proponly for replica1. (Use the replica1m + # environment which defines iprop_port to $port8.) + replica1_out_dump_path = os.path.join(realm.testdir, 'dump.replica1.out') + replica2_in_dump_path = os.path.join(realm.testdir, 'dump.replica2.in') + replica2_kprop_port = str(realm.portbase + 9) + kadmind_proponly = realm.start_server([kadmind, '-r', realm.realm, + '-nofork', '-proponly', + '-p', kdb5_util, + '-K', kprop, '-k', + replica2_kprop_port, + '-F', replica1_out_dump_path], + 'starting...', replica1m) + + # Test similar default_realm and domain_realm map settings with -r realm. + mark('propagate 1->3 full') + replica3_in_dump_path = os.path.join(realm.testdir, 'dump.replica3.in') + kpropd3 = realm.start_server([kpropd, '-d', '-D', '-r', realm.realm, '-P', + replica2_kprop_port, '-f', + replica3_in_dump_path, '-p', kdb5_util, '-a', + acl_file, '-A', hostname], 'ready', replica3) + wait_for_prop(kpropd3, True, 1, 7) + out = realm.run([kadminl, '-r', realm.realm, 'listprincs'], env=replica3) + if pr1 not in out or pr2 not in out or pr3 not in out: + fail('replica3 does not have all principals from replica1') + check_ulog(1, 7, 7, [None], env=replica3) + + # Test an incremental propagation for the kpropd -r case. + mark('propagate M->1->3 incremental') + realm.run([kadminl, 'modprinc', '-maxlife', '20 minutes', pr1]) + check_ulog(8, 1, 8, [None, pr1, pr3, pr2, pr2, pr2, pr2, pr1]) + kpropd1.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd1, False, 7, 8) + check_ulog(3, 6, 8, [None, pr2, pr1], replica1) + realm.run([kadminl, 'getprinc', pr1], env=replica1, + expected_msg='Maximum ticket life: 0 days 00:20:00') + kpropd3.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd3, False, 7, 8) + check_ulog(2, 7, 8, [None, pr1], replica3) + realm.run([kadminl, '-r', realm.realm, 'getprinc', pr1], env=replica3, + expected_msg='Maximum ticket life: 0 days 00:20:00') + stop_daemon(kpropd3) + + # Test dissimilar default_realm and domain_realm map settings (no + # -r realm). + mark('propagate 1->4 full') + replica4_in_dump_path = os.path.join(realm.testdir, 'dump.replica4.in') + kpropd4 = realm.start_server([kpropd, '-d', '-D', '-P', + replica2_kprop_port, '-f', + replica4_in_dump_path, '-p', kdb5_util, + '-a', acl_file, '-A', hostname], 'ready', + replica4) + wait_for_prop(kpropd4, True, 1, 8) + out = realm.run([kadminl, 'listprincs'], env=replica4) + if pr1 not in out or pr2 not in out or pr3 not in out: + fail('replica4 does not have all principals from replica1') + stop_daemon(kpropd4) + + # Start kpropd for replica2. The -A option isn't needed since + # we're talking to the same host as primary (we specify it anyway + # to exercise the code), but replica2 defines iprop_port to $port8 + # so it will talk to replica1. Get a full dump from replica1. + mark('propagate 1->2 full') + kpropd2 = realm.start_server([kpropd, '-d', '-D', '-P', + replica2_kprop_port, '-f', + replica2_in_dump_path, '-p', kdb5_util, + '-a', acl_file, '-A', hostname], 'ready', + replica2) + wait_for_prop(kpropd2, True, 1, 8) + check_ulog(2, 7, 8, [None, pr1], replica2) + out = realm.run([kadminl, 'listprincs'], env=replica1) + if pr1 not in out or pr2 not in out or pr3 not in out: + fail('replica2 does not have all principals from replica1') + + # Make another change and check that it propagates incrementally + # to both replicas. + mark('propagate M->1->2 incremental') + realm.run([kadminl, 'modprinc', '-maxrenewlife', '22 hours', pr1]) + check_ulog(9, 1, 9, [None, pr1, pr3, pr2, pr2, pr2, pr2, pr1, pr1]) + kpropd1.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd1, False, 8, 9) + check_ulog(4, 6, 9, [None, pr2, pr1, pr1], replica1) + realm.run([kadminl, 'getprinc', pr1], env=replica1, + expected_msg='Maximum renewable life: 0 days 22:00:00\n') + kpropd2.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd2, False, 8, 9) + check_ulog(3, 7, 9, [None, pr1, pr1], replica2) + realm.run([kadminl, 'getprinc', pr1], env=replica2, + expected_msg='Maximum renewable life: 0 days 22:00:00\n') + + # Reset the ulog on replica1 to force a full resync from primary. + # The resync will use the old dump file and then propagate + # changes. replica2 should still be in sync with replica1 after + # the resync, so make sure it doesn't take a full resync. + mark('propagate M->1->2 full') + realm.run([kproplog, '-R'], replica1) + check_ulog(1, 1, 1, [None], replica1) + kpropd1.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd1, True, 1, 9) + check_ulog(4, 6, 9, [None, pr2, pr1, pr1], replica1) + kpropd2.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd2, False, 9, 9) + check_ulog(3, 7, 9, [None, pr1, pr1], replica2) + + # Make another change and check that it propagates incrementally to + # both replicas. + mark('propagate M->1->2 incremental (after reset)') + realm.run([kadminl, 'modprinc', '+allow_tix', pr2]) + check_ulog(10, 1, 10, [None, pr1, pr3, pr2, pr2, pr2, pr2, pr1, pr1, pr2]) + kpropd1.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd1, False, 9, 10) + check_ulog(5, 6, 10, [None, pr2, pr1, pr1, pr2], replica1) + realm.run([kadminl, 'getprinc', pr2], env=replica1, + expected_msg='Attributes:\n') + kpropd2.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd2, False, 9, 10) + check_ulog(4, 7, 10, [None, pr1, pr1, pr2], replica2) + realm.run([kadminl, 'getprinc', pr2], env=replica2, + expected_msg='Attributes:\n') + + # Create a policy and check that it propagates via full resync. + mark('propagate M->1->2 full (new policy)') + realm.run([kadminl, 'addpol', '-minclasses', '2', 'testpol']) + check_ulog(1, 1, 1, [None]) + kpropd1.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd1, True, 10, 1) + check_ulog(1, 1, 1, [None], replica1) + realm.run([kadminl, 'getpol', 'testpol'], env=replica1, + expected_msg='Minimum number of password character classes: 2') + kpropd2.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd2, True, 10, 1) + check_ulog(1, 1, 1, [None], replica2) + realm.run([kadminl, 'getpol', 'testpol'], env=replica2, + expected_msg='Minimum number of password character classes: 2') + + # Modify the policy and test that it also propagates via full resync. + mark('propagate M->1->2 full (policy change)') + realm.run([kadminl, 'modpol', '-minlength', '17', 'testpol']) + check_ulog(1, 1, 1, [None]) + kpropd1.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd1, True, 1, 1) + check_ulog(1, 1, 1, [None], replica1) + realm.run([kadminl, 'getpol', 'testpol'], env=replica1, + expected_msg='Minimum password length: 17') + kpropd2.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd2, True, 1, 1) + check_ulog(1, 1, 1, [None], replica2) + realm.run([kadminl, 'getpol', 'testpol'], env=replica2, + expected_msg='Minimum password length: 17') + + # Delete the policy and test that it propagates via full resync. + mark('propgate M->1->2 full (policy delete)') + realm.run([kadminl, 'delpol', 'testpol']) + check_ulog(1, 1, 1, [None]) + kpropd1.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd1, True, 1, 1) + check_ulog(1, 1, 1, [None], replica1) + realm.run([kadminl, 'getpol', 'testpol'], env=replica1, expected_code=1, + expected_msg='Policy does not exist') + kpropd2.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd2, True, 1, 1) + check_ulog(1, 1, 1, [None], replica2) + realm.run([kadminl, 'getpol', 'testpol'], env=replica2, expected_code=1, + expected_msg='Policy does not exist') + + # Modify a principal on the primary and test that it propagates + # incrementally. + mark('propagate M->1->2 incremental (after policy changes)') + realm.run([kadminl, 'modprinc', '-maxlife', '10 minutes', pr1]) + check_ulog(2, 1, 2, [None, pr1]) + kpropd1.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd1, False, 1, 2) + check_ulog(2, 1, 2, [None, pr1], replica1) + realm.run([kadminl, 'getprinc', pr1], env=replica1, + expected_msg='Maximum ticket life: 0 days 00:10:00') + kpropd2.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd2, False, 1, 2) + check_ulog(2, 1, 2, [None, pr1], replica2) + realm.run([kadminl, 'getprinc', pr1], env=replica2, + expected_msg='Maximum ticket life: 0 days 00:10:00') + + # Delete a principal and test that it propagates incrementally. + mark('propagate M->1->2 incremental (princ delete)') + realm.run([kadminl, 'delprinc', pr3]) + check_ulog(3, 1, 3, [None, pr1, pr3]) + kpropd1.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd1, False, 2, 3) + check_ulog(3, 1, 3, [None, pr1, pr3], replica1) + realm.run([kadminl, 'getprinc', pr3], env=replica1, expected_code=1, + expected_msg='Principal does not exist') + kpropd2.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd2, False, 2, 3) + check_ulog(3, 1, 3, [None, pr1, pr3], replica2) + realm.run([kadminl, 'getprinc', pr3], env=replica2, expected_code=1, + expected_msg='Principal does not exist') + + # Rename a principal and test that it propagates incrementally. + mark('propagate M->1->2 incremental (princ rename)') + renpr = "quacked@" + realm.realm + realm.run([kadminl, 'renprinc', pr1, renpr]) + check_ulog(6, 1, 6, [None, pr1, pr3, renpr, pr1, renpr]) + kpropd1.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd1, False, 3, 6) + check_ulog(6, 1, 6, [None, pr1, pr3, renpr, pr1, renpr], replica1) + realm.run([kadminl, 'getprinc', pr1], env=replica1, expected_code=1, + expected_msg='Principal does not exist') + realm.run([kadminl, 'getprinc', renpr], env=replica1) + kpropd2.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd2, False, 3, 6) + check_ulog(6, 1, 6, [None, pr1, pr3, renpr, pr1, renpr], replica2) + realm.run([kadminl, 'getprinc', pr1], env=replica2, expected_code=1, + expected_msg='Principal does not exist') + realm.run([kadminl, 'getprinc', renpr], env=replica2) + + pr1 = renpr + + # Reset the ulog on the primary to force a full resync. + mark('propagate M->1->2 full (ulog reset)') + realm.run([kproplog, '-R']) + check_ulog(1, 1, 1, [None]) + kpropd1.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd1, True, 6, 1) + check_ulog(1, 1, 1, [None], replica1) + kpropd2.send_signal(signal.SIGUSR1) + wait_for_prop(kpropd2, True, 6, 1) + check_ulog(1, 1, 1, [None], replica2) + + # Stop the kprop daemons so we can test kpropd -t. + realm.stop_kpropd(kpropd1) + stop_daemon(kpropd2) + stop_daemon(kadmind_proponly) + mark('kpropd -t') + + # Test the case where no updates are needed. + out = realm.run_kpropd_once(replica1, ['-d']) + if 'KDC is synchronized' not in out: + fail('Expected synchronized from kpropd -t') + check_ulog(1, 1, 1, [None], replica1) + + # Make a change on the primary and fetch it incrementally. + realm.run([kadminl, 'modprinc', '-maxlife', '5 minutes', pr1]) + check_ulog(2, 1, 2, [None, pr1]) + out = realm.run_kpropd_once(replica1, ['-d']) + if 'Got incremental updates (sno=2 ' not in out: + fail('Expected full dump and synchronized from kpropd -t') + check_ulog(2, 1, 2, [None, pr1], replica1) + realm.run([kadminl, 'getprinc', pr1], env=replica1, + expected_msg='Maximum ticket life: 0 days 00:05:00') + + # Propagate a policy change via full resync. + realm.run([kadminl, 'addpol', '-minclasses', '3', 'testpol']) + check_ulog(1, 1, 1, [None]) + out = realm.run_kpropd_once(replica1, ['-d']) + if ('Full propagation transfer finished' not in out or + 'KDC is synchronized' not in out): + fail('Expected full dump and synchronized from kpropd -t') + check_ulog(1, 1, 1, [None], replica1) + realm.run([kadminl, 'getpol', 'testpol'], env=replica1, + expected_msg='Minimum number of password character classes: 3') + +success('iprop tests') diff --git a/krb5-1.21.3/src/tests/t_kadm5_auth.py b/krb5-1.21.3/src/tests/t_kadm5_auth.py new file mode 100644 index 00000000..6e0f42b0 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_kadm5_auth.py @@ -0,0 +1,80 @@ +from k5test import * + +# Create a realm with the welcomer and bouncer kadm5_auth test modules +# in place of the builtin modules. +modpath = os.path.join(buildtop, 'plugins', 'kadm5_auth', 'test', + 'kadm5_auth_test.so') +conf = {'plugins': {'kadm5_auth': {'module': ['welcomer:' + modpath, + 'bouncer:' + modpath], + 'enable_only': ['welcomer', 'bouncer']}}} +realm = K5Realm(krb5_conf=conf, create_host=False) +realm.start_kadmind() +realm.prep_kadmin() + +# addprinc: welcomer accepts with policy VIP, bouncer denies maxlife. +realm.run_kadmin(['addprinc', '-randkey', 'princ'], expected_code=1) +realm.run_kadmin(['addprinc', '-randkey', '-policy', 'VIP', 'princ']) +realm.run_kadmin(['addprinc', '-randkey', '-policy', 'VIP', '-maxlife', '3', + 'princ'], expected_code=1) + +# modprinc: welcomer accepts with only maxrenewlife, bouncer denies +# with even-component target principal. +realm.run_kadmin(['modprinc', '-maxlife', '3', 'princ'], expected_code=1) +realm.run_kadmin(['modprinc', '-maxrenewlife', '3', 'princ']) +realm.run_kadmin(['modprinc', '-maxrenewlife', '3', 'user/admin'], + expected_code=1) + +# setstr: welcomer accepts with key 'note', bouncer denies with value +# length > 10. +realm.run_kadmin(['setstr', 'princ', 'somekey', 'someval'], expected_code=1) +realm.run_kadmin(['setstr', 'princ', 'note', 'abc']) +realm.run_kadmin(['setstr', 'princ', 'note', 'abcdefghijkl'], expected_code=1) + +# delprinc: welcomer accepts with target principal beginning with 'd', +# bouncer denies with "nodelete" string attribute. +realm.run_kadmin(['delprinc', 'user'], expected_code=1) +realm.run([kadminl, 'addprinc', '-randkey', 'deltest']) +realm.run_kadmin(['delprinc', 'deltest']) +realm.run([kadminl, 'addprinc', '-randkey', 'deltest']) +realm.run([kadminl, 'setstr', 'deltest', 'nodelete', 'yes']) +realm.run_kadmin(['delprinc', 'deltest'], expected_code=1) + +# renprinc: welcomer accepts with same-length first components, bouncer +# refuses with source principal beginning with 'a'. +realm.run_kadmin(['renprinc', 'princ', 'xyz'], expected_code=1) +realm.run_kadmin(['renprinc', 'princ', 'abcde']) +realm.run_kadmin(['renprinc', 'abcde', 'fghij'], expected_code=1) + +# addpol: welcomer accepts with minlength 3, bouncer denies with name +# length <= 3. +realm.run_kadmin(['addpol', 'testpol'], expected_code=1) +realm.run_kadmin(['addpol', '-minlength', '3', 'testpol']) +realm.run_kadmin(['addpol', '-minlength', '3', 'abc'], expected_code=1) + +# modpol: welcomer accepts changes to minlife, bouncer denies with +# minlife > 10. +realm.run_kadmin(['modpol', '-minlength', '4', 'testpol'], expected_code=1) +realm.run_kadmin(['modpol', '-minlife', '8', 'testpol']) +realm.run_kadmin(['modpol', '-minlife', '11', 'testpol'], expected_code=1) + +# getpol: welcomer accepts if policy and client policy have same length, +# bouncer denies if policy name begins with 'x'. +realm.run([kadminl, 'addpol', 'aaaa']) +realm.run([kadminl, 'addpol', 'bbbb']) +realm.run([kadminl, 'addpol', 'xxxx']) +realm.run([kadminl, 'modprinc', '-policy', 'aaaa', 'user/admin']) +realm.run_kadmin(['getpol', 'testpol'], expected_code=1) +realm.run_kadmin(['getpol', 'bbbb']) +realm.run_kadmin(['getpol', 'xxxx'], expected_code=1) + +# end: welcomer counts operations using "ends" string attribute on +# "opcount" principal. kadmind is dumb and invokes the end method for +# every RPC operation including init, so we expect four calls to the +# end operation. +realm.run([kadminl, 'addprinc', '-nokey', 'opcount']) +realm.run([kadminl, 'setstr', 'opcount', 'ends', '0']) +realm.run_kadmin(['getprinc', 'user']) +realm.run_kadmin(['getpol', 'bbbb']) +realm.run([kadminl, 'getstrs', 'opcount'], expected_msg='ends: 4') + +success('kadm5_auth pluggable interface tests') diff --git a/krb5-1.21.3/src/tests/t_kadm5_hook.py b/krb5-1.21.3/src/tests/t_kadm5_hook.py new file mode 100755 index 00000000..32fab781 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_kadm5_hook.py @@ -0,0 +1,15 @@ +from k5test import * + +plugin = os.path.join(buildtop, "plugins", "kadm5_hook", "test", + "kadm5_hook_test.so") + +hook_krb5_conf = {'plugins': {'kadm5_hook': { 'module': 'test:' + plugin}}} + +realm = K5Realm(krb5_conf=hook_krb5_conf, create_user=False, create_host=False) +realm.run([kadminl, 'addprinc', '-randkey', 'test'], + expected_msg='create: stage precommit') + +realm.run([kadminl, 'renprinc', 'test', 'test2'], + expected_msg='rename: stage precommit') + +success('kadm5_hook') diff --git a/krb5-1.21.3/src/tests/t_kadmin.py b/krb5-1.21.3/src/tests/t_kadmin.py new file mode 100644 index 00000000..98453d92 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_kadmin.py @@ -0,0 +1,66 @@ +from k5test import * + +realm = K5Realm(start_kadmind=True) + +# Create a principal. Test -q option and keyboard entry of the admin +# password and principal password. Verify creation with kadmin.local. +realm.run([kadmin, '-q', 'addprinc princ/pw'], + input=password('admin') + '\npw1\npw1\n') +realm.run([kadminl, 'getprinc', 'princ/pw'], + expected_msg='Principal: princ/pw@KRBTEST.COM') + +# Run the remaining tests with a cache for efficiency. +realm.prep_kadmin() + +realm.run_kadmin(['addpol', 'standardpol']) +realm.run_kadmin(['listpols'], expected_msg='standardpol') +realm.run_kadmin(['modpol', '-minlength', '5', 'standardpol']) +realm.run_kadmin(['getpol', 'standardpol'], + expected_msg='Minimum password length: 5') + +realm.run_kadmin(['addprinc', '-randkey', 'princ/random']) +realm.run([kadminl, 'getprinc', 'princ/random'], + expected_msg='Principal: princ/random@KRBTEST.COM') + +realm.run_kadmin(['cpw', 'princ/pw'], input='newpw\nnewpw\n') +realm.run_kadmin(['cpw', '-randkey', 'princ/random']) + +realm.run_kadmin(['modprinc', '-allow_tix', 'princ/random']) +realm.run_kadmin(['modprinc', '+allow_tix', 'princ/random']) +realm.run_kadmin(['modprinc', '-policy', 'standardpol', 'princ/random']) + +realm.run_kadmin(['listprincs'], expected_msg='princ/random@KRBTEST.COM') + +realm.run_kadmin(['ktadd', 'princ/pw']) + +realm.run_kadmin(['delprinc', 'princ/random']) +realm.run([kadminl, 'getprinc', 'princ/random'], expected_code=1, + expected_msg='Principal does not exist') +realm.run_kadmin(['delprinc', 'princ/pw']) +realm.run([kadminl, 'getprinc', 'princ/pw'], expected_code=1, + expected_msg='Principal does not exist') + +realm.run_kadmin(['delpol', 'standardpol']) +realm.run([kadminl, 'getpol', 'standardpol'], expected_code=1, + expected_msg='Policy does not exist') + +# Regression test for #2877 (fixed-sized GSSRPC buffers can't +# accomodate large listprinc results). +mark('large listprincs result') +for i in range(200): + realm.run_kadmin(['addprinc', '-randkey', 'foo%d' % i]) +realm.run_kadmin(['listprincs'], expected_msg='foo199') + +# Test kadmin -k with the default principal, with and without +# fallback. This operation requires canonicalization against the +# keytab in krb5_get_init_creds_keytab() as the +# krb5_sname_to_principal() result won't have a realm. Try with and +# without without fallback processing since the code paths are +# different. +mark('kadmin -k') +realm.run([kadmin, '-k', 'getprinc', realm.host_princ]) +no_canon_conf = {'libdefaults': {'dns_canonicalize_hostname': 'false'}} +no_canon = realm.special_env('no_canon', False, krb5_conf=no_canon_conf) +realm.run([kadmin, '-k', 'getprinc', realm.host_princ], env=no_canon) + +success('kadmin and kpasswd tests') diff --git a/krb5-1.21.3/src/tests/t_kadmin_acl.py b/krb5-1.21.3/src/tests/t_kadmin_acl.py new file mode 100755 index 00000000..31a7fb87 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_kadmin_acl.py @@ -0,0 +1,352 @@ +from k5test import * +import os + +realm = K5Realm(create_host=False, create_user=False) + +def make_client(name): + global realm + realm.addprinc(name, password(name)) + ccache = os.path.join(realm.testdir, + 'kadmin_ccache_' + name.replace('/', '_')) + realm.kinit(name, password(name), + flags=['-S', 'kadmin/admin', '-c', ccache]) + return ccache + +def kadmin_as(client, query, **kwargs): + global realm + return realm.run([kadmin, '-c', client] + query, **kwargs) + +all_add = make_client('all_add') +all_changepw = make_client('all_changepw') +all_delete = make_client('all_delete') +all_inquire = make_client('all_inquire') +all_list = make_client('all_list') +all_modify = make_client('all_modify') +all_rename = make_client('all_rename') +all_wildcard = make_client('all_wildcard') +all_extract = make_client('all_extract') +some_add = make_client('some_add') +some_changepw = make_client('some_changepw') +some_delete = make_client('some_delete') +some_inquire = make_client('some_inquire') +some_modify = make_client('some_modify') +some_rename = make_client('some_rename') +restricted_add = make_client('restricted_add') +restricted_modify = make_client('restricted_modify') +restricted_rename = make_client('restricted_rename') +wctarget = make_client('wctarget') +admin = make_client('user/admin') +none = make_client('none') +restrictions = make_client('restrictions') +onetwothreefour = make_client('one/two/three/four') + +realm.run([kadminl, 'addpol', '-minlife', '1 day', 'minlife']) + +f = open(os.path.join(realm.testdir, 'acl'), 'w') +f.write(''' +all_add a +all_changepw c +all_delete d +all_inquire i +all_list l +all_modify im +all_rename ad +all_wildcard x +all_extract ie +some_add a selected +some_changepw c selected +some_delete d selected +some_inquire i selected +some_modify im selected +some_rename d from +some_rename a to +restricted_add a * +preauth +restricted_modify im * +preauth +restricted_rename ad * +preauth + +*/* d *2/*1 +# The next line is a regression test for #8154; it is not used directly. +one/*/*/five l +*/two/*/* d *3/*1/*2 +*/admin a +wctarget a wild/* +restrictions a type1 -policy minlife +restrictions a type2 -clearpolicy +restrictions a type3 -maxlife 1h -maxrenewlife 2h +''') +f.close() + +realm.start_kadmind() + +# cpw can generate four different RPC calls depending on options. +realm.addprinc('selected', 'oldpw') +realm.addprinc('unselected', 'oldpw') +for pw in (['-pw', 'newpw'], ['-randkey']): + for ks in ([], ['-e', 'aes256-cts']): + mark('cpw: %s %s' % (repr(pw), repr(ks))) + args = pw + ks + kadmin_as(all_changepw, ['cpw'] + args + ['unselected']) + kadmin_as(some_changepw, ['cpw'] + args + ['selected']) + msg = "Operation requires ``change-password'' privilege" + kadmin_as(none, ['cpw'] + args + ['selected'], expected_code=1, + expected_msg=msg) + kadmin_as(some_changepw, ['cpw'] + args + ['unselected'], + expected_code=1, expected_msg=msg) + kadmin_as(none, ['cpw'] + args + ['none']) + realm.run([kadminl, 'modprinc', '-policy', 'minlife', 'none']) + msg = "Current password's minimum life has not expired" + kadmin_as(none, ['cpw'] + args + ['none'], expected_code=1, + expected_msg=msg) + realm.run([kadminl, 'modprinc', '-clearpolicy', 'none']) +realm.run([kadminl, 'delprinc', 'selected']) +realm.run([kadminl, 'delprinc', 'unselected']) + +mark('addpol') +kadmin_as(all_add, ['addpol', 'policy']) +realm.run([kadminl, 'delpol', 'policy']) +kadmin_as(none, ['addpol', 'policy'], expected_code=1, + expected_msg="Operation requires ``add'' privilege") + +# addprinc can generate two different RPC calls depending on options. +for ks in ([], ['-e', 'aes256-cts']): + mark('addprinc: %s' % repr(ks)) + args = ['-pw', 'pw'] + ks + kadmin_as(all_add, ['addprinc'] + args + ['unselected']) + realm.run([kadminl, 'delprinc', 'unselected']) + kadmin_as(some_add, ['addprinc'] + args + ['selected']) + realm.run([kadminl, 'delprinc', 'selected']) + kadmin_as(restricted_add, ['addprinc'] + args + ['unselected']) + realm.run([kadminl, 'getprinc', 'unselected'], + expected_msg='REQUIRES_PRE_AUTH') + realm.run([kadminl, 'delprinc', 'unselected']) + kadmin_as(none, ['addprinc'] + args + ['selected'], expected_code=1, + expected_msg="Operation requires ``add'' privilege") + kadmin_as(some_add, ['addprinc'] + args + ['unselected'], expected_code=1, + expected_msg="Operation requires ``add'' privilege") + +mark('delprinc') +realm.addprinc('unselected', 'pw') +kadmin_as(all_delete, ['delprinc', 'unselected']) +realm.addprinc('selected', 'pw') +kadmin_as(some_delete, ['delprinc', 'selected']) +realm.addprinc('unselected', 'pw') +kadmin_as(none, ['delprinc', 'unselected'], expected_code=1, + expected_msg="Operation requires ``delete'' privilege") +kadmin_as(some_delete, ['delprinc', 'unselected'], expected_code=1, + expected_msg="Operation requires ``delete'' privilege") +realm.run([kadminl, 'delprinc', 'unselected']) + +mark('getpol') +kadmin_as(all_inquire, ['getpol', 'minlife'], expected_msg='Policy: minlife') +kadmin_as(none, ['getpol', 'minlife'], expected_code=1, + expected_msg="Operation requires ``get'' privilege") +realm.run([kadminl, 'modprinc', '-policy', 'minlife', 'none']) +kadmin_as(none, ['getpol', 'minlife'], expected_msg='Policy: minlife') +realm.run([kadminl, 'modprinc', '-clearpolicy', 'none']) + +mark('getprinc') +realm.addprinc('selected', 'pw') +realm.addprinc('unselected', 'pw') +kadmin_as(all_inquire, ['getprinc', 'unselected'], + expected_msg='Principal: unselected@KRBTEST.COM') +kadmin_as(some_inquire, ['getprinc', 'selected'], + expected_msg='Principal: selected@KRBTEST.COM') +kadmin_as(none, ['getprinc', 'selected'], expected_code=1, + expected_msg="Operation requires ``get'' privilege") +kadmin_as(some_inquire, ['getprinc', 'unselected'], expected_code=1, + expected_msg="Operation requires ``get'' privilege") +kadmin_as(none, ['getprinc', 'none'], + expected_msg='Principal: none@KRBTEST.COM') +realm.run([kadminl, 'delprinc', 'selected']) +realm.run([kadminl, 'delprinc', 'unselected']) + +mark('listprincs') +kadmin_as(all_list, ['listprincs'], expected_msg='K/M@KRBTEST.COM') +kadmin_as(none, ['listprincs'], expected_code=1, + expected_msg="Operation requires ``list'' privilege") + +mark('getstrs') +realm.addprinc('selected', 'pw') +realm.addprinc('unselected', 'pw') +realm.run([kadminl, 'setstr', 'selected', 'key', 'value']) +realm.run([kadminl, 'setstr', 'unselected', 'key', 'value']) +kadmin_as(all_inquire, ['getstrs', 'unselected'], expected_msg='key: value') +kadmin_as(some_inquire, ['getstrs', 'selected'], expected_msg='key: value') +kadmin_as(none, ['getstrs', 'selected'], expected_code=1, + expected_msg="Operation requires ``get'' privilege") +kadmin_as(some_inquire, ['getstrs', 'unselected'], expected_code=1, + expected_msg="Operation requires ``get'' privilege") +kadmin_as(none, ['getstrs', 'none'], expected_msg='(No string attributes.)') +realm.run([kadminl, 'delprinc', 'selected']) +realm.run([kadminl, 'delprinc', 'unselected']) + +mark('modpol') +out = kadmin_as(all_modify, ['modpol', '-maxlife', '1 hour', 'policy'], + expected_code=1) +if 'Operation requires' in out: + fail('modpol success (acl)') +kadmin_as(none, ['modpol', '-maxlife', '1 hour', 'policy'], expected_code=1, + expected_msg="Operation requires ``modify'' privilege") + +mark('modprinc') +realm.addprinc('selected', 'pw') +realm.addprinc('unselected', 'pw') +kadmin_as(all_modify, ['modprinc', '-maxlife', '1 hour', 'unselected']) +kadmin_as(some_modify, ['modprinc', '-maxlife', '1 hour', 'selected']) +kadmin_as(restricted_modify, ['modprinc', '-maxlife', '1 hour', 'unselected']) +realm.run([kadminl, 'getprinc', 'unselected'], + expected_msg='REQUIRES_PRE_AUTH') +kadmin_as(all_inquire, ['modprinc', '-maxlife', '1 hour', 'selected'], + expected_code=1, + expected_msg="Operation requires ``modify'' privilege") +kadmin_as(some_modify, ['modprinc', '-maxlife', '1 hour', 'unselected'], + expected_code=1, expected_msg='Operation requires') +realm.run([kadminl, 'delprinc', 'selected']) +realm.run([kadminl, 'delprinc', 'unselected']) + +mark('purgekeys') +realm.addprinc('selected', 'pw') +realm.addprinc('unselected', 'pw') +kadmin_as(all_modify, ['purgekeys', 'unselected']) +kadmin_as(some_modify, ['purgekeys', 'selected']) +kadmin_as(none, ['purgekeys', 'selected'], expected_code=1, + expected_msg="Operation requires ``modify'' privilege") +kadmin_as(some_modify, ['purgekeys', 'unselected'], expected_code=1, + expected_msg="Operation requires ``modify'' privilege") +kadmin_as(none, ['purgekeys', 'none']) +realm.run([kadminl, 'delprinc', 'selected']) +realm.run([kadminl, 'delprinc', 'unselected']) + +mark('renprinc') +realm.addprinc('from', 'pw') +kadmin_as(all_rename, ['renprinc', 'from', 'to']) +realm.run([kadminl, 'renprinc', 'to', 'from']) +kadmin_as(some_rename, ['renprinc', 'from', 'to']) +realm.run([kadminl, 'renprinc', 'to', 'from']) +kadmin_as(all_add, ['renprinc', 'from', 'to'], expected_code=1, + expected_msg="Insufficient authorization for operation") +kadmin_as(all_delete, ['renprinc', 'from', 'to'], expected_code=1, + expected_msg="Insufficient authorization for operation") +kadmin_as(some_rename, ['renprinc', 'from', 'notto'], expected_code=1, + expected_msg="Insufficient authorization for operation") +realm.run([kadminl, 'renprinc', 'from', 'notfrom']) +kadmin_as(some_rename, ['renprinc', 'notfrom', 'to'], expected_code=1, + expected_msg="Insufficient authorization for operation") +kadmin_as(restricted_rename, ['renprinc', 'notfrom', 'to'], expected_code=1, + expected_msg="Insufficient authorization for operation") +realm.run([kadminl, 'delprinc', 'notfrom']) + +mark('setstr') +realm.addprinc('selected', 'pw') +realm.addprinc('unselected', 'pw') +kadmin_as(all_modify, ['setstr', 'unselected', 'key', 'value']) +kadmin_as(some_modify, ['setstr', 'selected', 'key', 'value']) +kadmin_as(none, ['setstr', 'selected', 'key', 'value'], expected_code=1, + expected_msg="Operation requires ``modify'' privilege") +kadmin_as(some_modify, ['setstr', 'unselected', 'key', 'value'], + expected_code=1, expected_msg='Operation requires') +realm.run([kadminl, 'delprinc', 'selected']) +realm.run([kadminl, 'delprinc', 'unselected']) + +mark('addprinc/delprinc (wildcard)') +kadmin_as(admin, ['addprinc', '-pw', 'pw', 'anytarget']) +realm.run([kadminl, 'delprinc', 'anytarget']) +kadmin_as(wctarget, ['addprinc', '-pw', 'pw', 'wild/card']) +realm.run([kadminl, 'delprinc', 'wild/card']) +kadmin_as(wctarget, ['addprinc', '-pw', 'pw', 'wild/card/extra'], + expected_code=1, expected_msg='Operation requires') +realm.addprinc('admin/user', 'pw') +kadmin_as(admin, ['delprinc', 'admin/user']) +kadmin_as(admin, ['delprinc', 'none'], expected_code=1, + expected_msg='Operation requires') +realm.addprinc('four/one/three', 'pw') +kadmin_as(onetwothreefour, ['delprinc', 'four/one/three']) + +mark('addprinc (restrictions)') +kadmin_as(restrictions, ['addprinc', '-pw', 'pw', 'type1']) +realm.run([kadminl, 'getprinc', 'type1'], expected_msg='Policy: minlife') +realm.run([kadminl, 'delprinc', 'type1']) +kadmin_as(restrictions, ['addprinc', '-pw', 'pw', '-policy', 'minlife', + 'type2']) +realm.run([kadminl, 'getprinc', 'type2'], expected_msg='Policy: [none]') +realm.run([kadminl, 'delprinc', 'type2']) +kadmin_as(restrictions, ['addprinc', '-pw', 'pw', '-maxlife', '1 minute', + 'type3']) +out = realm.run([kadminl, 'getprinc', 'type3']) +if ('Maximum ticket life: 0 days 00:01:00' not in out or + 'Maximum renewable life: 0 days 02:00:00' not in out): + fail('restriction (maxlife low, maxrenewlife unspec)') +realm.run([kadminl, 'delprinc', 'type3']) +kadmin_as(restrictions, ['addprinc', '-pw', 'pw', '-maxrenewlife', '1 day', + 'type3']) +realm.run([kadminl, 'getprinc', 'type3'], + expected_msg='Maximum renewable life: 0 days 02:00:00') + +mark('extract') +realm.run([kadminl, 'addprinc', '-pw', 'pw', 'extractkeys']) +kadmin_as(all_wildcard, ['ktadd', '-norandkey', 'extractkeys'], + expected_code=1, + expected_msg="Operation requires ``extract-keys'' privilege") +kadmin_as(all_extract, ['ktadd', '-norandkey', 'extractkeys']) +realm.kinit('extractkeys', flags=['-k']) +os.remove(realm.keytab) + +mark('lockdown_keys') +kadmin_as(all_modify, ['modprinc', '+lockdown_keys', 'extractkeys']) +kadmin_as(all_changepw, ['cpw', '-pw', 'newpw', 'extractkeys'], + expected_code=1, + expected_msg="Operation requires ``change-password'' privilege") +kadmin_as(all_changepw, ['cpw', '-randkey', 'extractkeys']) +kadmin_as(all_extract, ['ktadd', '-norandkey', 'extractkeys'], expected_code=1, + expected_msg="Operation requires ``extract-keys'' privilege") +kadmin_as(all_delete, ['delprinc', 'extractkeys'], expected_code=1, + expected_msg="Operation requires ``delete'' privilege") +kadmin_as(all_rename, ['renprinc', 'extractkeys', 'renamedprinc'], + expected_code=1, + expected_msg="Operation requires ``delete'' privilege") +kadmin_as(all_modify, ['modprinc', '-lockdown_keys', 'extractkeys'], + expected_code=1, + expected_msg="Operation requires ``modify'' privilege") +realm.run([kadminl, 'modprinc', '-lockdown_keys', 'extractkeys']) +kadmin_as(all_extract, ['ktadd', '-norandkey', 'extractkeys']) +realm.kinit('extractkeys', flags=['-k']) +os.remove(realm.keytab) + +# Verify that self-service key changes require an initial ticket. +mark('self-service initial ticket') +realm.run([kadminl, 'cpw', '-pw', password('none'), 'none']) +realm.run([kadminl, 'modprinc', '+allow_tgs_req', 'kadmin/admin']) +realm.kinit('none', password('none')) +realm.run([kvno, 'kadmin/admin']) +msg = 'Operation requires initial ticket' +realm.run([kadmin, '-c', realm.ccache, 'cpw', '-pw', 'newpw', 'none'], + expected_code=1, expected_msg=msg) +realm.run([kadmin, '-c', realm.ccache, 'cpw', '-pw', 'newpw', + '-e', 'aes256-cts', 'none'], expected_code=1, expected_msg=msg) +realm.run([kadmin, '-c', realm.ccache, 'cpw', '-randkey', 'none'], + expected_code=1, expected_msg=msg) +realm.run([kadmin, '-c', realm.ccache, 'cpw', '-randkey', '-e', 'aes256-cts', + 'none'], expected_code=1, expected_msg=msg) + +# Test authentication to kadmin/hostname. +mark('authentication to kadmin/hostname') +kadmin_hostname = 'kadmin/' + hostname +realm.addprinc(kadmin_hostname) +realm.run([kadminl, 'delprinc', 'kadmin/admin']) +msgs = ('Getting initial credentials for user/admin@KRBTEST.COM', + 'Setting initial creds service to kadmin/admin', + '/Server not found in Kerberos database', + 'Getting initial credentials for user/admin@KRBTEST.COM', + 'Setting initial creds service to ' + kadmin_hostname, + 'Decrypted AS reply') +realm.run([kadmin, '-p', 'user/admin', 'listprincs'], expected_code=1, + expected_msg="Operation requires ``list'' privilege", + input=password('user/admin'), expected_trace=msgs) + +# Test operations disallowed at the libkadm5 layer. +realm.run([kadminl, 'delprinc', 'K/M'], + expected_code=1, expected_msg='Cannot change protected principal') +realm.run([kadminl, 'cpw', '-pw', 'pw', 'kadmin/history'], + expected_code=1, expected_msg='Cannot change protected principal') + +success('kadmin ACL enforcement') diff --git a/krb5-1.21.3/src/tests/t_kadmin_parsing.py b/krb5-1.21.3/src/tests/t_kadmin_parsing.py new file mode 100644 index 00000000..bebb0148 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_kadmin_parsing.py @@ -0,0 +1,82 @@ +from k5test import * + +# This file contains tests for kadmin command parsing. Principal +# flags (which can also be used in kadm5.acl or krb5.conf) are tested +# in t_princflags.py. + +# kadmin recognizes time intervals using either the +# krb5_string_to_deltat() formats or the relative getdate.y formats. +# (Absolute getdate.y formats also work with the current time +# subtracted; this isn't very useful and we won't test it here.) +intervals = ( + # krb5_string_to_deltat() formats. Whitespace ( \t\n) is allowed + # before or between most elements or at the end, but not after + # 's'. Negative or oversized numbers are allowed in most places, + # but not after the first number in an HH:MM:SS form. + ('28s', '0 days 00:00:28'), + ('7m ', '0 days 00:07:00'), + ('6m 9s', '0 days 00:06:09'), + ('2h', '0 days 02:00:00'), + ('2h-5s', '0 days 01:59:55'), + ('2h3m', '0 days 02:03:00'), + ('2h3m5s', '0 days 02:03:05'), + ('5d ', '5 days 00:00:00'), + ('5d-48s', '4 days 23:59:12'), + ('5d18m', '5 days 00:18:00'), + ('5d -6m56s', '4 days 23:54:56'), + ('5d4h', '5 days 04:00:00'), + ('5d4h 1s', '5 days 04:00:01'), + ('5d4h3m', '5 days 04:03:00'), + (' \t 15d \n 4h 3m 2s', '15 days 04:03:02'), + ('10-8:45:0', '10 days 08:45:00'), + ('1000:67:99', '41 days 17:08:39'), + ('999:11', '41 days 15:11:00'), + ('382512', '4 days 10:15:12'), + + # getdate.y relative formats (and "never", which is handled + # specially as a zero interval). Any number of relative forms can + # be specified in any order. Whitespace is ignored before or + # after any token. "month" and "year" are allowed as units but + # depend on the current time, so we won't test them. Plural unit + # names are treated identically to singular unit names. Numbers + # before unit names are optional and may be signed; there are also + # aliases for some numbers. "ago" inverts the interval up to the + # point where it appears. + ('never', '0 days 00:00:00'), + ('fortnight', '14 days 00:00:00'), + ('3 day ago 4 weeks 8 hours', '25 days 08:00:00'), + ('8 second -3 secs 5 minute ago 63 min', '0 days 00:57:55'), + ('min mins min mins min', '0 days 00:05:00'), + ('tomorrow tomorrow today yesterday now last minute', '0 days 23:59:00'), + ('this second next minute first hour third fortnight fourth day ' + 'fifth weeks sixth sec seventh secs eighth second ninth mins tenth ' + 'day eleventh min twelfth sec', '91 days 01:22:34')) + +realm = K5Realm(create_host=False, get_creds=False) +realm.run([kadminl, 'addpol', 'pol']) +for instr, outstr in intervals: + realm.run([kadminl, 'modprinc', '-maxlife', instr, realm.user_princ]) + msg = 'Maximum ticket life: ' + outstr + '\n' + realm.run([kadminl, 'getprinc', realm.user_princ], expected_msg=msg) + + realm.run([kadminl, 'modprinc', '-maxrenewlife', instr, realm.user_princ]) + msg = 'Maximum renewable life: ' + outstr + '\n' + realm.run([kadminl, 'getprinc', realm.user_princ], expected_msg=msg) + + realm.run([kadminl, 'modpol', '-maxlife', instr, 'pol']) + msg = 'Maximum password life: ' + outstr + '\n' + realm.run([kadminl, 'getpol', 'pol'], expected_msg=msg) + + realm.run([kadminl, 'modpol', '-minlife', instr, 'pol']) + msg = 'Minimum password life: ' + outstr + '\n' + realm.run([kadminl, 'getpol', 'pol'], expected_msg=msg) + + realm.run([kadminl, 'modpol', '-failurecountinterval', instr, 'pol']) + msg = 'Password failure count reset interval: ' + outstr + '\n' + realm.run([kadminl, 'getpol', 'pol'], expected_msg=msg) + + realm.run([kadminl, 'modpol', '-lockoutduration', instr, 'pol']) + msg = 'Password lockout duration: ' + outstr + '\n' + realm.run([kadminl, 'getpol', 'pol'], expected_msg=msg) + +success('kadmin command parsing tests') diff --git a/krb5-1.21.3/src/tests/t_kdb.py b/krb5-1.21.3/src/tests/t_kdb.py new file mode 100755 index 00000000..5211cbc7 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_kdb.py @@ -0,0 +1,622 @@ +from k5test import * +import time + +# Run kdbtest against the non-LDAP KDB modules. +for realm in multidb_realms(create_kdb=False): + realm.run(['./kdbtest']) + +# Set up an OpenLDAP test server if we can. + +if (not os.path.exists(os.path.join(plugins, 'kdb', 'kldap.so')) and + not os.path.exists(os.path.join(buildtop, 'lib', 'libkdb_ldap.a'))): + skip_rest('LDAP KDB tests', 'LDAP KDB module not built') + +if 'SLAPD' not in os.environ and not which('slapd'): + skip_rest('LDAP KDB tests', 'slapd not found') + +slapadd = which('slapadd') +if not slapadd: + skip_rest('LDAP KDB tests', 'slapadd not found') + +ldapdir = os.path.abspath('ldap') +dbdir = os.path.join(ldapdir, 'ldap') +slapd_conf = os.path.join(ldapdir, 'slapd.d') +slapd_out = os.path.join(ldapdir, 'slapd.out') +slapd_pidfile = os.path.join(ldapdir, 'pid') +ldap_pwfile = os.path.join(ldapdir, 'pw') +ldap_sock = os.path.join(ldapdir, 'sock') +ldap_uri = 'ldapi://%s/' % ldap_sock.replace(os.path.sep, '%2F') +schema = os.path.join(srctop, 'plugins', 'kdb', 'ldap', 'libkdb_ldap', + 'kerberos.openldap.ldif') +top_dn = 'cn=krb5' +admin_dn = 'cn=admin,cn=krb5' +admin_pw = 'admin' + +shutil.rmtree(ldapdir, True) +os.mkdir(ldapdir) +os.mkdir(slapd_conf) +os.mkdir(dbdir) + +if 'SLAPD' in os.environ: + slapd = os.environ['SLAPD'] +else: + # Some Linux installations have AppArmor or similar restrictions + # on the slapd binary, which would prevent it from accessing the + # build directory. Try to defeat this by copying the binary. + system_slapd = which('slapd') + slapd = os.path.join(ldapdir, 'slapd') + shutil.copy(system_slapd, slapd) + +def slap_add(ldif): + proc = subprocess.Popen([slapadd, '-b', 'cn=config', '-F', slapd_conf], + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, universal_newlines=True) + (out, dummy) = proc.communicate(ldif) + output(out) + return proc.wait() + + +# Configure the pid file and some authorization rules we will need for +# SASL testing. +if slap_add('dn: cn=config\n' + 'objectClass: olcGlobal\n' + 'olcPidFile: %s\n' + 'olcAuthzRegexp: ' + '".*uidNumber=%d,cn=peercred,cn=external,cn=auth" "%s"\n' + 'olcAuthzRegexp: "uid=digestuser,cn=digest-md5,cn=auth" "%s"\n' % + (slapd_pidfile, os.geteuid(), admin_dn, admin_dn)) != 0: + skip_rest('LDAP KDB tests', 'slapd basic configuration failed') + +# Find a working writable database type, trying mdb (added in OpenLDAP +# 2.4.27) and bdb (deprecated and sometimes not built due to licensing +# incompatibilities). +for dbtype in ('mdb', 'bdb'): + # Try to load the module. This could fail if OpenLDAP is built + # without module support, so ignore errors. + slap_add('dn: cn=module,cn=config\n' + 'objectClass: olcModuleList\n' + 'olcModuleLoad: back_%s\n' % dbtype) + + dbclass = 'olc%sConfig' % dbtype.capitalize() + if slap_add('dn: olcDatabase=%s,cn=config\n' + 'objectClass: olcDatabaseConfig\n' + 'objectClass: %s\n' + 'olcSuffix: %s\n' + 'olcRootDN: %s\n' + 'olcRootPW: %s\n' + 'olcDbDirectory: %s\n' % + (dbtype, dbclass, top_dn, admin_dn, admin_pw, dbdir)) == 0: + break +else: + skip_rest('LDAP KDB tests', 'could not find working slapd db type') + +if slap_add('include: file://%s\n' % schema) != 0: + skip_rest('LDAP KDB tests', 'failed to load Kerberos schema') + +# Load the core schema if we can. +ldap_homes = ['/etc/ldap', '/etc/openldap', '/usr/local/etc/openldap', + '/usr/local/etc/ldap'] +local_schema_path = '/schema/core.ldif' +core_schema = next((i for i in map(lambda x:x+local_schema_path, ldap_homes) + if os.path.isfile(i)), None) +if core_schema: + if slap_add('include: file://%s\n' % core_schema) != 0: + core_schema = None + +slapd_pid = -1 +def kill_slapd(): + global slapd_pid + if slapd_pid != -1: + os.kill(slapd_pid, signal.SIGTERM) + slapd_pid = -1 +atexit.register(kill_slapd) + +out = open(slapd_out, 'w') +subprocess.call([slapd, '-h', ldap_uri, '-F', slapd_conf], stdout=out, + stderr=out, universal_newlines=True) +out.close() +pidf = open(slapd_pidfile, 'r') +slapd_pid = int(pidf.read()) +pidf.close() +output('*** Started slapd (pid %d, output in %s)\n' % (slapd_pid, slapd_out)) + +# slapd detaches before it finishes setting up its listener sockets +# (they are bound but listen() has not been called). Give it a second +# to finish. +time.sleep(1) + +# Run kdbtest against the LDAP module. +conf = {'realms': {'$realm': {'database_module': 'ldap'}}, + 'dbmodules': {'ldap': {'db_library': 'kldap', + 'ldap_kerberos_container_dn': top_dn, + 'ldap_kdc_dn': admin_dn, + 'ldap_kadmind_dn': admin_dn, + 'ldap_service_password_file': ldap_pwfile, + 'ldap_servers': ldap_uri}}} +realm = K5Realm(create_kdb=False, kdc_conf=conf) +input = admin_pw + '\n' + admin_pw + '\n' +realm.run([kdb5_ldap_util, 'stashsrvpw', admin_dn], input=input) +realm.run(['./kdbtest']) + +# Run a kdb5_ldap_util command using the test server's admin DN and password. +def kldaputil(args, **kw): + return realm.run([kdb5_ldap_util, '-D', admin_dn, '-w', admin_pw] + args, + **kw) + +# kdbtest can't currently clean up after itself since the LDAP module +# doesn't support krb5_db_destroy. So clean up after it with +# kdb5_ldap_util before proceeding. +kldaputil(['destroy', '-f']) + +ldapmodify = which('ldapmodify') +ldapsearch = which('ldapsearch') +if not ldapmodify or not ldapsearch: + skip_rest('some LDAP KDB tests', 'ldapmodify or ldapsearch not found') + +def ldap_search(args): + proc = subprocess.Popen([ldapsearch, '-H', ldap_uri, '-b', top_dn, + '-D', admin_dn, '-w', admin_pw, args], + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, universal_newlines=True) + (out, dummy) = proc.communicate() + return out + +def ldap_modify(ldif, args=[]): + proc = subprocess.Popen([ldapmodify, '-H', ldap_uri, '-D', admin_dn, + '-x', '-w', admin_pw] + args, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, universal_newlines=True) + (out, dummy) = proc.communicate(ldif) + output(out) + +def ldap_add(dn, objectclass, attrs=[]): + in_data = 'dn: %s\nobjectclass: %s\n' % (dn, objectclass) + in_data += '\n'.join(attrs) + '\n' + ldap_modify(in_data, ['-a']) + +# Create krbContainer objects for use as subtrees. +ldap_add('cn=t1,cn=krb5', 'krbContainer') +ldap_add('cn=t2,cn=krb5', 'krbContainer') +ldap_add('cn=x,cn=t1,cn=krb5', 'krbContainer') +ldap_add('cn=y,cn=t2,cn=krb5', 'krbContainer') + +# Create a realm, exercising all of the realm options. +kldaputil(['create', '-s', '-P', 'master', '-subtrees', 'cn=t2,cn=krb5', + '-containerref', 'cn=t2,cn=krb5', '-sscope', 'one', + '-maxtktlife', '5min', '-maxrenewlife', '10min', '-allow_svr']) + +# Modify the realm, exercising overlapping subtree pruning. +kldaputil(['modify', '-subtrees', + 'cn=x,cn=t1,cn=krb5:cn=t1,cn=krb5:cn=t2,cn=krb5:cn=y,cn=t2,cn=krb5', + '-containerref', 'cn=t1,cn=krb5', '-sscope', 'sub', + '-maxtktlife', '5hour', '-maxrenewlife', '10hour', '+allow_svr']) + +out = kldaputil(['list']) +if out != 'KRBTEST.COM\n': + fail('Unexpected kdb5_ldap_util list output') + +# Create a principal at a specified DN. This is a little dodgy +# because we're sticking a krbPrincipalAux objectclass onto a subtree +# krbContainer, but it works and it avoids having to load core.schema +# in the test LDAP server. +mark('LDAP specified dn') +realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=krb5', 'princ1'], + expected_code=1, expected_msg='DN is out of the realm subtree') +# Check that the DN container check is a hierarchy test, not a simple +# suffix match (CVE-2018-5730). We expect this operation to fail +# either way (because "xcn" isn't a valid DN tag) but the container +# check should happen before the DN is parsed. +realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=xcn=t1,cn=krb5', 'princ1'], + expected_code=1, expected_msg='DN is out of the realm subtree') +realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=t2,cn=krb5', 'princ1']) +realm.run([kadminl, 'getprinc', 'princ1'], expected_msg='Principal: princ1') +realm.run([kadminl, 'ank', '-randkey', '-x', 'dn=cn=t2,cn=krb5', 'again'], + expected_code=1, expected_msg='ldap object is already kerberized') +# Check that we can't set linkdn on a non-standalone object. +realm.run([kadminl, 'modprinc', '-x', 'linkdn=cn=t1,cn=krb5', 'princ1'], + expected_code=1, expected_msg='link information can not be set') + +# Create a principal with a specified linkdn. +mark('LDAP specified linkdn') +realm.run([kadminl, 'ank', '-randkey', '-x', 'linkdn=cn=krb5', 'princ2'], + expected_code=1, expected_msg='DN is out of the realm subtree') +realm.run([kadminl, 'ank', '-randkey', '-x', 'linkdn=cn=t1,cn=krb5', 'princ2']) +# Check that we can't reset linkdn. +realm.run([kadminl, 'modprinc', '-x', 'linkdn=cn=t2,cn=krb5', 'princ2'], + expected_code=1, expected_msg='kerberos principal is already linked') + +# Create a principal with a specified containerdn. +mark('LDAP specified containerdn') +realm.run([kadminl, 'ank', '-randkey', '-x', 'containerdn=cn=krb5', 'princ3'], + expected_code=1, expected_msg='DN is out of the realm subtree') +realm.run([kadminl, 'ank', '-randkey', '-x', 'containerdn=cn=t1,cn=krb5', + 'princ3']) +realm.run([kadminl, 'modprinc', '-x', 'containerdn=cn=t2,cn=krb5', 'princ3'], + expected_code=1, expected_msg='containerdn option not supported') +# Verify that containerdn is checked when linkdn is also supplied +# (CVE-2018-5730). +realm.run([kadminl, 'ank', '-randkey', '-x', 'containerdn=cn=krb5', + '-x', 'linkdn=cn=t2,cn=krb5', 'princ4'], expected_code=1, + expected_msg='DN is out of the realm subtree') + +mark('LDAP ticket policy') + +# Create and modify a ticket policy. +kldaputil(['create_policy', '-maxtktlife', '3hour', '-maxrenewlife', '6hour', + '-allow_forwardable', 'tktpol']) +kldaputil(['modify_policy', '-maxtktlife', '4hour', '-maxrenewlife', '8hour', + '+requires_preauth', 'tktpol']) +out = kldaputil(['view_policy', 'tktpol']) +if ('Ticket policy: tktpol\n' not in out or + 'Maximum ticket life: 0 days 04:00:00\n' not in out or + 'Maximum renewable life: 0 days 08:00:00\n' not in out or + 'Ticket flags: DISALLOW_FORWARDABLE REQUIRES_PRE_AUTH' not in out): + fail('Unexpected kdb5_ldap_util view_policy output') + +out = kldaputil(['list_policy']) +if out != 'tktpol\n': + fail('Unexpected kdb5_ldap_util list_policy output') + +# Associate the ticket policy to a principal. +realm.run([kadminl, 'ank', '-randkey', '-x', 'tktpolicy=tktpol', 'princ4']) +out = realm.run([kadminl, 'getprinc', 'princ4']) +if ('Maximum ticket life: 0 days 04:00:00\n' not in out or + 'Maximum renewable life: 0 days 08:00:00\n' not in out or + 'Attributes: DISALLOW_FORWARDABLE REQUIRES_PRE_AUTH\n' not in out): + fail('Unexpected getprinc output with ticket policy') + +# Destroying the policy should fail while a principal references it. +kldaputil(['destroy_policy', '-force', 'tktpol'], expected_code=1) + +# Dissociate the ticket policy from the principal. +realm.run([kadminl, 'modprinc', '-x', 'tktpolicy=', 'princ4']) +out = realm.run([kadminl, 'getprinc', 'princ4']) +if ('Maximum ticket life: 0 days 05:00:00\n' not in out or + 'Maximum renewable life: 0 days 10:00:00\n' not in out or + 'Attributes:\n' not in out): + fail('Unexpected getprinc output without ticket policy') + +# Destroy the ticket policy. +kldaputil(['destroy_policy', '-force', 'tktpol']) +kldaputil(['view_policy', 'tktpol'], expected_code=1) +out = kldaputil(['list_policy']) +if out: + fail('Unexpected kdb5_ldap_util list_policy output after destroy') + +# Create another ticket policy to be destroyed with the realm. +kldaputil(['create_policy', 'tktpol2']) + +# Try to create a password policy conflicting with a ticket policy. +realm.run([kadminl, 'addpol', 'tktpol2'], expected_code=1, + expected_msg='Already exists while creating policy "tktpol2"') + +# Try to create a ticket policy conflicting with a password policy. +realm.run([kadminl, 'addpol', 'pwpol']) +out = kldaputil(['create_policy', 'pwpol'], expected_code=1) +if 'Already exists while creating policy object' not in out: + fail('Expected error not seen in kdb5_ldap_util output') + +# Try to use a password policy as a ticket policy. +realm.run([kadminl, 'modprinc', '-x', 'tktpolicy=pwpol', 'princ4'], + expected_code=1, expected_msg='Object class violation') + +# Use a ticket policy as a password policy (CVE-2014-5353). This +# works with a warning; use kadmin.local -q so the warning is shown. +realm.run([kadminl, '-q', 'modprinc -policy tktpol2 princ4'], + expected_msg='WARNING: policy "tktpol2" does not exist') + +# Do some basic tests with a KDC against the LDAP module, exercising the +# db_args processing code. +mark('LDAP KDC operation') +realm.start_kdc(['-x', 'nconns=3', '-x', 'host=' + ldap_uri, + '-x', 'binddn=' + admin_dn, '-x', 'bindpwd=' + admin_pw]) +realm.addprinc(realm.user_princ, password('user')) +realm.addprinc(realm.host_princ) +realm.extract_keytab(realm.host_princ, realm.keytab) +realm.kinit(realm.user_princ, password('user')) +realm.run([kvno, realm.host_princ]) +realm.klist(realm.user_princ, realm.host_princ) + +mark('LDAP auth indicator') + +# Test require_auth normalization. +realm.addprinc('authind', password('authind')) +realm.run([kadminl, 'setstr', 'authind', 'require_auth', 'otp radius']) + +# Check that krbPrincipalAuthInd attributes are set when the string +# attribute it set. +out = ldap_search('(krbPrincipalName=authind*)') +if 'krbPrincipalAuthInd: otp' not in out: + fail('Expected krbPrincipalAuthInd value not in output') +if 'krbPrincipalAuthInd: radius' not in out: + fail('Expected krbPrincipalAuthInd value not in output') + +# Check that the string attribute still appears when the principal is +# loaded. +realm.run([kadminl, 'getstrs', 'authind'], + expected_msg='require_auth: otp radius') + +# Modify the LDAP attributes and check that the change is reflected in +# the string attribute. +ldap_modify('dn: krbPrincipalName=authind@KRBTEST.COM,cn=t1,cn=krb5\n' + 'changetype: modify\n' + 'replace: krbPrincipalAuthInd\n' + 'krbPrincipalAuthInd: radius\n' + 'krbPrincipalAuthInd: pkinit\n') +realm.run([kadminl, 'getstrs', 'authind'], + expected_msg='require_auth: radius pkinit') + +# Regression test for #8877: remove the string attribute and check +# that it is reflected in the LDAP attributes and by getstrs. +realm.run([kadminl, 'delstr', 'authind', 'require_auth']) +out = ldap_search('(krbPrincipalName=authind*)') +if 'krbPrincipalAuthInd' in out: + fail('krbPrincipalAuthInd attribute still present after delstr') +out = realm.run([kadminl, 'getstrs', 'authind']) +if 'require_auth' in out: + fail('require_auth string attribute still visible after delstr') + +mark('LDAP service principal aliases') + +# Test service principal aliases. +realm.addprinc('canon', password('canon')) +ldap_modify('dn: krbPrincipalName=canon@KRBTEST.COM,cn=t1,cn=krb5\n' + 'changetype: modify\n' + 'add: krbPrincipalName\n' + 'krbPrincipalName: alias@KRBTEST.COM\n' + 'krbPrincipalName: ent@abc@KRBTEST.COM\n' + '-\n' + 'add: krbCanonicalName\n' + 'krbCanonicalName: canon@KRBTEST.COM\n') +realm.run([kadminl, 'getprinc', 'alias'], + expected_msg='Principal: canon@KRBTEST.COM\n') +realm.run([kadminl, 'getprinc', 'ent\\@abc'], + expected_msg='Principal: canon@KRBTEST.COM\n') +realm.run([kadminl, 'getprinc', 'canon'], + expected_msg='Principal: canon@KRBTEST.COM\n') +realm.run([kvno, 'alias', 'canon']) +out = realm.run([klist]) +if 'alias@KRBTEST.COM\n' not in out or 'canon@KRBTEST.COM' not in out: + fail('After fetching alias and canon, klist is missing one or both') +realm.kinit(realm.user_princ, password('user'), ['-S', 'alias']) +realm.klist(realm.user_princ, 'alias@KRBTEST.COM') + +# Make sure an alias to the local TGS is still treated like an alias. +ldap_modify('dn: krbPrincipalName=krbtgt/KRBTEST.COM@KRBTEST.COM,' + 'cn=KRBTEST.COM,cn=krb5\n' + 'changetype: modify\n' + 'add:krbPrincipalName\n' + 'krbPrincipalName: tgtalias@KRBTEST.COM\n' + '-\n' + 'add: krbCanonicalName\n' + 'krbCanonicalName: krbtgt/KRBTEST.COM@KRBTEST.COM\n') +realm.run([kadminl, 'getprinc', 'tgtalias'], + expected_msg='Principal: krbtgt/KRBTEST.COM@KRBTEST.COM') +realm.kinit(realm.user_princ, password('user')) +realm.run([kvno, 'tgtalias']) +realm.klist(realm.user_princ, 'tgtalias@KRBTEST.COM') + +# Make sure aliases work in header tickets. +realm.run([kadminl, 'modprinc', '-maxrenewlife', '3 hours', 'user']) +realm.run([kadminl, 'modprinc', '-maxrenewlife', '3 hours', + 'krbtgt/KRBTEST.COM']) +realm.kinit(realm.user_princ, password('user'), ['-l', '1h', '-r', '2h']) +realm.run([kvno, 'alias']) +realm.kinit(realm.user_princ, flags=['-R', '-S', 'alias']) +realm.klist(realm.user_princ, 'alias@KRBTEST.COM') + +# Test client principal aliases, with and without preauth. +realm.kinit('canon', password('canon')) +realm.kinit('alias', password('canon')) +realm.run([kvno, 'alias']) +realm.klist('alias@KRBTEST.COM', 'alias@KRBTEST.COM') +realm.kinit('alias', password('canon'), ['-C']) +realm.run([kvno, 'alias']) +realm.klist('canon@KRBTEST.COM', 'alias@KRBTEST.COM') +realm.run([kadminl, 'modprinc', '+requires_preauth', 'canon']) +realm.kinit('canon', password('canon')) +realm.kinit('alias', password('canon'), ['-C']) + +# Test enterprise alias with and without canonicalization. +realm.kinit('ent@abc', password('canon'), ['-E', '-C']) +realm.run([kvno, 'alias']) +realm.klist('canon@KRBTEST.COM', 'alias@KRBTEST.COM') + +realm.kinit('ent@abc', password('canon'), ['-E']) +realm.run([kvno, 'alias']) +realm.klist('ent\\@abc@KRBTEST.COM', 'alias@KRBTEST.COM') + +# Test client name canonicalization in non-krbtgt AS reply +realm.kinit('alias', password('canon'), ['-C', '-S', 'kadmin/changepw']) + +mark('LDAP password history') + +# Test password history. +def test_pwhist(nhist): + def cpw(n, **kwargs): + realm.run([kadminl, 'cpw', '-pw', str(n), princ], **kwargs) + def cpw_fail(n): + cpw(n, expected_code=1) + output('*** Testing password history of size %d\n' % nhist) + princ = 'pwhistprinc' + str(nhist) + pol = 'pwhistpol' + str(nhist) + realm.run([kadminl, 'addpol', '-history', str(nhist), pol]) + realm.run([kadminl, 'addprinc', '-policy', pol, '-nokey', princ]) + for i in range(nhist): + # Set a password, then check that all previous passwords fail. + cpw(i) + for j in range(i + 1): + cpw_fail(j) + # Set one more new password, and make sure the oldest key is + # rotated out. + cpw(nhist) + cpw_fail(1) + cpw(0) + +for n in (1, 2, 3, 4, 5): + test_pwhist(n) + +# Regression test for #8193: test password character class requirements. +princ = 'charclassprinc' +pol = 'charclasspol' +realm.run([kadminl, 'addpol', '-minclasses', '3', pol]) +realm.run([kadminl, 'addprinc', '-policy', pol, '-nokey', princ]) +realm.run([kadminl, 'cpw', '-pw', 'abcdef', princ], expected_code=1) +realm.run([kadminl, 'cpw', '-pw', 'Abcdef', princ], expected_code=1) +realm.run([kadminl, 'cpw', '-pw', 'Abcdef1', princ]) + +# Test principal renaming and make sure last modified is changed +def get_princ(princ): + out = realm.run([kadminl, 'getprinc', princ]) + return dict(map(str.strip, x.split(":", 1)) for x in out.splitlines()) + +mark('LDAP principal renaming') +realm.addprinc("rename", password('rename')) +renameprinc = get_princ("rename") +realm.run([kadminl, '-p', 'fake@KRBTEST.COM', 'renprinc', 'rename', 'renamed']) +renamedprinc = get_princ("renamed") +if renameprinc['Last modified'] == renamedprinc['Last modified']: + fail('Last modified data not updated when principal was renamed') + +# Regression test for #7980 (fencepost when dividing keys up by kvno). +mark('#7980 regression test') +realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts,aes128-cts', + 'kvnoprinc']) +realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', + 'aes256-cts,aes128-cts', 'kvnoprinc']) +realm.run([kadminl, 'getprinc', 'kvnoprinc'], expected_msg='Number of keys: 4') +realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', + 'aes256-cts,aes128-cts', 'kvnoprinc']) +realm.run([kadminl, 'getprinc', 'kvnoprinc'], expected_msg='Number of keys: 6') + +# Regression test for #8041 (NULL dereference on keyless principals). +mark('#8041 regression test') +realm.run([kadminl, 'addprinc', '-nokey', 'keylessprinc']) +realm.run([kadminl, 'getprinc', 'keylessprinc'], + expected_msg='Number of keys: 0') +realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts,aes128-cts', + 'keylessprinc']) +realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', + 'aes256-cts,aes128-cts', 'keylessprinc']) +realm.run([kadminl, 'getprinc', 'keylessprinc'], + expected_msg='Number of keys: 4') +realm.run([kadminl, 'purgekeys', '-all', 'keylessprinc']) +realm.run([kadminl, 'getprinc', 'keylessprinc'], + expected_msg='Number of keys: 0') + +# Test for 8354 (old password history entries when -keepold is used) +mark('#8354 regression test') +realm.run([kadminl, 'addpol', '-history', '2', 'keepoldpasspol']) +realm.run([kadminl, 'addprinc', '-policy', 'keepoldpasspol', '-pw', 'aaaa', + 'keepoldpassprinc']) +for p in ('bbbb', 'cccc', 'aaaa'): + realm.run([kadminl, 'cpw', '-keepold', '-pw', p, 'keepoldpassprinc']) + +if runenv.sizeof_time_t <= 4: + skipped('y2038 LDAP test', 'platform has 32-bit time_t') +else: + # Test storage of timestamps after y2038. + realm.run([kadminl, 'modprinc', '-pwexpire', '2040-02-03', 'user']) + realm.run([kadminl, 'getprinc', 'user'], expected_msg=' 2040\n') + +# Regression test for #8861 (pw_expiration policy enforcement). +mark('pw_expiration propogation') +# Create a policy with a max life and verify its application. +realm.run([kadminl, 'addpol', '-maxlife', '1s', 'pw_e']) +realm.run([kadminl, 'addprinc', '-policy', 'pw_e', '-pw', 'password', + 'pwuser']) +out = realm.run([kadminl, 'getprinc', 'pwuser'], + expected_msg='Password expiration date: ') +if 'Password expiration date: [never]' in out: + fail('pw_expiration not applied at principal creation') +# Unset the policy max life and verify its application during password +# change. +realm.run([kadminl, 'modpol', '-maxlife', '0', 'pw_e']) +realm.run([kadminl, 'cpw', '-pw', 'password_', 'pwuser']) +realm.run([kadminl, 'getprinc', 'pwuser'], + expected_msg='Password expiration date: [never]') + +realm.stop() + +# Test dump and load. Include a regression test for #8882 +# (pw_expiration not set during load operation). +mark('LDAP dump and load') +realm.run([kadminl, 'modprinc', '-pwexpire', 'now', 'pwuser']) +dumpfile = os.path.join(realm.testdir, 'dump') +realm.run([kdb5_util, 'dump', dumpfile]) +realm.run([kdb5_util, 'load', dumpfile], expected_code=1, + expected_msg='KDB module requires -update argument') +realm.run([kadminl, 'delprinc', 'pwuser']) +realm.run([kdb5_util, 'load', '-update', dumpfile]) +out = realm.run([kadminl, 'getprinc', 'pwuser']) +if 'Password expiration date: [never]' in out: + fail('pw_expiration not preserved across dump and load') + +# Destroy the realm. +kldaputil(['destroy', '-f']) +out = kldaputil(['list']) +if out: + fail('Unexpected kdb5_ldap_util list output after destroy') + +if not core_schema: + skip_rest('LDAP SASL tests', 'core schema not found') + +if runenv.have_sasl != 'yes': + skip_rest('LDAP SASL tests', 'SASL support not built') + +# Test SASL EXTERNAL auth. Remove the DNs and service password file +# from the DB module config. +mark('LDAP SASL EXTERNAL auth') +os.remove(ldap_pwfile) +dbmod = conf['dbmodules']['ldap'] +dbmod['ldap_kdc_sasl_mech'] = dbmod['ldap_kadmind_sasl_mech'] = 'EXTERNAL' +del dbmod['ldap_service_password_file'] +del dbmod['ldap_kdc_dn'], dbmod['ldap_kadmind_dn'] +realm = K5Realm(create_kdb=False, kdc_conf=conf) +realm.run([kdb5_ldap_util, 'create', '-s', '-P', 'master']) +realm.start_kdc() +realm.addprinc(realm.user_princ, password('user')) +realm.kinit(realm.user_princ, password('user')) +realm.stop() +realm.run([kdb5_ldap_util, 'destroy', '-f']) + +# Test SASL DIGEST-MD5 auth. We need to set a clear-text password for +# the admin DN, so create a person entry (requires the core schema). +# Restore the service password file in the config and set authcids. +mark('LDAP SASL DIGEST-MD5 auth') +ldap_add('cn=admin,cn=krb5', 'person', + ['sn: dummy', 'userPassword: admin']) +dbmod['ldap_kdc_sasl_mech'] = dbmod['ldap_kadmind_sasl_mech'] = 'DIGEST-MD5' +dbmod['ldap_kdc_sasl_authcid'] = 'digestuser' +dbmod['ldap_kadmind_sasl_authcid'] = 'digestuser' +dbmod['ldap_service_password_file'] = ldap_pwfile +realm = K5Realm(create_kdb=False, kdc_conf=conf) +input = admin_pw + '\n' + admin_pw + '\n' +realm.run([kdb5_ldap_util, 'stashsrvpw', 'digestuser'], input=input) +realm.run([kdb5_ldap_util, 'create', '-s', '-P', 'master']) +realm.start_kdc() +realm.addprinc(realm.user_princ, password('user')) +realm.kinit(realm.user_princ, password('user')) +realm.stop() +# Exercise DB options, which should cause binding to fail. +realm.run([kadminl, '-x', 'sasl_authcid=ab', 'getprinc', 'user'], + expected_code=1, expected_msg='Cannot bind to LDAP server') +realm.run([kadminl, '-x', 'bindpwd=wrong', 'getprinc', 'user'], + expected_code=1, expected_msg='Cannot bind to LDAP server') +realm.run([kdb5_ldap_util, 'destroy', '-f']) + +# We could still use tests to exercise: +# * DB arg handling in krb5_ldap_create +# * krbAllowedToDelegateTo attribute processing +# * A load operation overwriting a standalone principal entry which +# already exists but doesn't have a krbPrincipalName attribute +# matching the principal name. +# * A bunch of invalid-input error conditions +# +# There is no coverage for the following because it would be difficult: +# * Out-of-memory error conditions +# * Handling of failures from slapd (including krb5_retry_get_ldap_handle) +# * Handling of servers which don't support mod-increment +# * krb5_ldap_delete_krbcontainer (only happens if krb5_ldap_create fails) + +success('LDAP and DB2 KDB tests') diff --git a/krb5-1.21.3/src/tests/t_kdb_locking.py b/krb5-1.21.3/src/tests/t_kdb_locking.py new file mode 100755 index 00000000..9ae42a82 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_kdb_locking.py @@ -0,0 +1,32 @@ +# This is a regression test for +# https://bugzilla.redhat.com/show_bug.cgi?id=586032 . +# +# We start a KDC, remove the kadm5 lock file, use the KDC, re-create the +# kadm5 lock file, and use kadmin.local. The kinit should fail, and the +# kadmin.local should succeed. + + +import os + +from k5test import * + +p = 'foo' +realm = K5Realm(create_user=False, bdb_only=True) +realm.addprinc(p, p) + +kadm5_lock = os.path.join(realm.testdir, 'db.kadm5.lock') +if not os.path.exists(kadm5_lock): + fail('kadm5 lock file not created: ' + kadm5_lock) +os.unlink(kadm5_lock) + +realm.kinit(p, p, [], expected_code=1, + expected_msg='A service is not available') + +f = open(kadm5_lock, 'w') +f.close() + +output = realm.run([kadminl, 'modprinc', '-allow_tix', p]) +if 'Cannot lock database' in output: + fail('krb5kdc still holds a lock on the principal db') + +success('KDB locking tests') diff --git a/krb5-1.21.3/src/tests/t_kdc_log.py b/krb5-1.21.3/src/tests/t_kdc_log.py new file mode 100755 index 00000000..1b14828d --- /dev/null +++ b/krb5-1.21.3/src/tests/t_kdc_log.py @@ -0,0 +1,21 @@ +from k5test import * + +# Make a TGS request with an expired ticket. +realm = K5Realm() +realm.stop() +realm.start_kdc(['-T', '3600']) +realm.run([kvno, realm.host_princ], expected_code=1) + +kdc_logfile = os.path.join(realm.testdir, 'kdc.log') +f = open(kdc_logfile, 'r') +found_skew = False +for line in f: + if 'Clock skew too great' in line: + found_skew = True + if realm.user_princ not in line: + fail('Client principal not logged in expired-ticket TGS request') +f.close() +if not found_skew: + fail('Did not find KDC log line for expired-ticket TGS request') + +success('KDC logging tests') diff --git a/krb5-1.21.3/src/tests/t_kdcoptions.py b/krb5-1.21.3/src/tests/t_kdcoptions.py new file mode 100644 index 00000000..7ec57508 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_kdcoptions.py @@ -0,0 +1,100 @@ +from k5test import * +import re + +# KDC option test coverage notes: +# +# FORWARDABLE here +# FORWARDED no test +# PROXIABLE here +# PROXY no test +# ALLOW_POSTDATE no test +# POSTDATED no test +# RENEWABLE t_renew.py +# CNAME_IN_ADDL_TKT gssapi/t_s4u.py +# CANONICALIZE t_kdb.py and various other tests +# REQUEST_ANONYMOUS t_pkinit.py +# DISABLE_TRANSITED_CHECK no test +# RENEWABLE_OK t_renew.py +# ENC_TKT_IN_SKEY t_u2u.py +# RENEW t_renew.py +# VALIDATE no test + +# Run klist -f and return the flags on the ticket for svcprinc. +def get_flags(realm, svcprinc): + grab_flags = False + for line in realm.run([klist, '-f']).splitlines(): + if grab_flags: + return re.findall(r'Flags: ([a-zA-Z]*)', line)[0] + grab_flags = line.endswith(svcprinc) + + +# Get the flags on the ticket for svcprinc, and check for an expected +# element and an expected-absent element, either of which can be None. +def check_flags(realm, svcprinc, expected_flag, expected_noflag): + flags = get_flags(realm, svcprinc) + if expected_flag is not None and not expected_flag in flags: + fail('expected flag ' + expected_flag) + if expected_noflag is not None and expected_noflag in flags: + fail('did not expect flag ' + expected_noflag) + + +# Run kinit with the given flags, and check the flags on the resulting +# TGT. +def kinit_check_flags(realm, flags, expected_flag, expected_noflag): + realm.kinit(realm.user_princ, password('user'), flags) + check_flags(realm, realm.krbtgt_princ, expected_flag, expected_noflag) + + +# Run kinit with kflags. Then get credentials for the host principal +# with gflags, and check the flags on the resulting ticket. +def gcred_check_flags(realm, kflags, gflags, expected_flag, expected_noflag): + realm.kinit(realm.user_princ, password('user'), kflags) + realm.run(['./gcred'] + gflags + ['unknown', realm.host_princ]) + check_flags(realm, realm.host_princ, expected_flag, expected_noflag) + + +realm = K5Realm() + +mark('proxiable (AS)') +kinit_check_flags(realm, [], None, 'P') +kinit_check_flags(realm, ['-p'], 'P', None) +realm.run([kadminl, 'modprinc', '-allow_proxiable', realm.user_princ]) +kinit_check_flags(realm, ['-p'], None, 'P') +realm.run([kadminl, 'modprinc', '+allow_proxiable', realm.user_princ]) +realm.run([kadminl, 'modprinc', '-allow_proxiable', realm.krbtgt_princ]) +kinit_check_flags(realm, ['-p'], None, 'P') +realm.run([kadminl, 'modprinc', '+allow_proxiable', realm.krbtgt_princ]) + +mark('proxiable (TGS)') +gcred_check_flags(realm, [], [], None, 'P') +gcred_check_flags(realm, ['-p'], [], 'P', None) + +# Not tested: PROXIABLE option set with a non-proxiable TGT (because +# there is no krb5_get_credentials() flag to request this; would +# expect a non-proxiable ticket). + +# Not tested: proxiable TGT but PROXIABLE flag not set (because we +# internally set the PROXIABLE option when using a proxiable TGT; +# would expect a non-proxiable ticket). + +mark('forwardable (AS)') +kinit_check_flags(realm, [], None, 'F') +kinit_check_flags(realm, ['-f'], 'F', None) +realm.run([kadminl, 'modprinc', '-allow_forwardable', realm.user_princ]) +kinit_check_flags(realm, ['-f'], None, 'F') +realm.run([kadminl, 'modprinc', '+allow_forwardable', realm.user_princ]) +realm.run([kadminl, 'modprinc', '-allow_forwardable', realm.krbtgt_princ]) +kinit_check_flags(realm, ['-f'], None, 'F') +realm.run([kadminl, 'modprinc', '+allow_forwardable', realm.krbtgt_princ]) + +mark('forwardable (TGS)') +realm.kinit(realm.user_princ, password('user')) +gcred_check_flags(realm, [], [], None, 'F') +gcred_check_flags(realm, [], ['-f'], None, 'F') +gcred_check_flags(realm, ['-f'], [], 'F', None) + +# Not tested: forwardable TGT but FORWARDABLE flag not set (because we +# internally set the FORWARDABLE option when using a forwardable TGT; +# would expect a non-proxiable ticket). + +success('KDC option tests') diff --git a/krb5-1.21.3/src/tests/t_kdcpolicy.py b/krb5-1.21.3/src/tests/t_kdcpolicy.py new file mode 100644 index 00000000..92413338 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_kdcpolicy.py @@ -0,0 +1,65 @@ +from k5test import * +from datetime import datetime +import re + +testpreauth = os.path.join(buildtop, 'plugins', 'preauth', 'test', 'test.so') +testpolicy = os.path.join(buildtop, 'plugins', 'kdcpolicy', 'test', + 'kdcpolicy_test.so') +krb5_conf = {'plugins': {'kdcpreauth': {'module': 'test:' + testpreauth}, + 'clpreauth': {'module': 'test:' + testpreauth}, + 'kdcpolicy': {'module': 'test:' + testpolicy}}} +kdc_conf = {'realms': {'$realm': {'default_principal_flags': '+preauth', + 'max_renewable_life': '1d'}}} +realm = K5Realm(krb5_conf=krb5_conf, kdc_conf=kdc_conf) + +# We will be scraping timestamps from klist to compute lifetimes, so +# use a time zone with no daylight savings time. +realm.env['TZ'] = 'UTC' + +realm.run([kadminl, 'addprinc', '-pw', password('fail'), 'fail']) + +def verify_time(out, target_time): + times = re.findall(r'\d\d/\d\d/\d\d \d\d:\d\d:\d\d', out) + times = [datetime.strptime(t, '%m/%d/%y %H:%M:%S') for t in times] + divisor = 1 + while len(times) > 0: + starttime = times.pop(0) + endtime = times.pop(0) + renewtime = times.pop(0) + + if str((endtime - starttime) * divisor) != target_time: + fail('unexpected lifetime value') + if str((renewtime - endtime) * divisor) != target_time: + fail('unexpected renewable value') + + # Service tickets should have half the lifetime of initial + # tickets. + divisor = 2 + +rflags = ['-r', '1d', '-l', '12h'] + +# Test AS+TGS success path. +realm.kinit(realm.user_princ, password('user'), + rflags + ['-X', 'indicators=SEVEN_HOURS']) +realm.run([kvno, realm.host_princ]) +realm.run(['./adata', realm.host_princ], expected_msg='+97: [SEVEN_HOURS]') +out = realm.run([klist, '-e', realm.ccache]) +verify_time(out, '7:00:00') + +# Test AS+TGS success path with different values. +realm.kinit(realm.user_princ, password('user'), + rflags + ['-X', 'indicators=ONE_HOUR']) +realm.run([kvno, realm.host_princ]) +realm.run(['./adata', realm.host_princ], expected_msg='+97: [ONE_HOUR]') +out = realm.run([klist, '-e', realm.ccache]) +verify_time(out, '1:00:00') + +# Test TGS failure path (using previous creds). +realm.run([kvno, 'fail@%s' % realm.realm], expected_code=1, + expected_msg='KDC policy rejects request') + +# Test AS failure path. +realm.kinit('fail@%s' % realm.realm, password('fail'), + expected_code=1, expected_msg='KDC policy rejects request') + +success('kdcpolicy tests') diff --git a/krb5-1.21.3/src/tests/t_keydata.py b/krb5-1.21.3/src/tests/t_keydata.py new file mode 100755 index 00000000..baa40b62 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_keydata.py @@ -0,0 +1,49 @@ +from k5test import * + +realm = K5Realm(create_user=False, create_host=False) + +# Create a principal with no keys. +realm.run([kadminl, 'addprinc', '-nokey', 'user']) +realm.run([kadminl, 'getprinc', 'user'], expected_msg='Number of keys: 0') + +# Change its password and check the resulting kvno. +realm.run([kadminl, 'cpw', '-pw', 'password', 'user']) +realm.run([kadminl, 'getprinc', 'user'], expected_msg='vno 1') + +# Delete all of its keys. +realm.run([kadminl, 'purgekeys', '-all', 'user']) +realm.run([kadminl, 'getprinc', 'user'], expected_msg='Number of keys: 0') + +# Randomize its keys and check the resulting kvno. +realm.run([kadminl, 'cpw', '-randkey', 'user']) +realm.run([kadminl, 'getprinc', 'user'], expected_msg='vno 1') + +# Return true if patype appears to have been received in a hint list +# from a KDC error message, based on the trace file fname. +def preauth_type_received(trace, patype): + found = False + for line in trace.splitlines(): + if 'Processing preauth types:' in line: + ind = line.find('types:') + patypes = line[ind + 6:].split(', ') + if str(patype) in patypes: + found = True + return found + +# Make sure the KDC doesn't offer encrypted timestamp for a principal +# with no keys. +realm.run([kadminl, 'purgekeys', '-all', 'user']) +realm.run([kadminl, 'modprinc', '+requires_preauth', 'user']) +out, trace = realm.run([kinit, 'user'], expected_code=1, return_trace=True) +if preauth_type_received(trace, 2): + fail('encrypted timestamp') + +# Make sure it doesn't offer encrypted challenge either. +realm.run([kadminl, 'addprinc', '-pw', 'fast', 'armor']) +realm.kinit('armor', 'fast') +out, trace = realm.run([kinit, '-T', realm.ccache, 'user'], expected_code=1, + return_trace=True) +if preauth_type_received(trace, 138): + fail('encrypted challenge') + +success('Key data tests') diff --git a/krb5-1.21.3/src/tests/t_keyrollover.py b/krb5-1.21.3/src/tests/t_keyrollover.py new file mode 100755 index 00000000..e9840dfa --- /dev/null +++ b/krb5-1.21.3/src/tests/t_keyrollover.py @@ -0,0 +1,75 @@ +from k5test import * + +rollover_krb5_conf = {'libdefaults': {'allow_weak_crypto': 'true'}} + +realm = K5Realm(krbtgt_keysalt='aes128-cts-hmac-sha256-128:normal', + krb5_conf=rollover_krb5_conf) + +princ1 = 'host/test1@%s' % (realm.realm,) +princ2 = 'host/test2@%s' % (realm.realm,) +realm.addprinc(princ1) +realm.addprinc(princ2) + +realm.run([kvno, realm.host_princ]) + +# Change key for TGS, keeping old key. +realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts', '-keepold', + realm.krbtgt_princ]) + +# Ensure that kvno still works with an old TGT. +realm.run([kvno, princ1]) + +realm.run([kadminl, 'purgekeys', realm.krbtgt_princ]) +# Make sure an old TGT fails after purging old TGS key. +realm.run([kvno, princ2], expected_code=1) +msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): ' \ + 'aes256-cts-hmac-sha1-96, aes128-cts-hmac-sha256-128' % \ + (realm.realm, realm.realm) +realm.run([klist, '-e'], expected_msg=msg) + +# Check that new key actually works. +realm.kinit(realm.user_princ, password('user')) +realm.run([kvno, realm.host_princ]) +msg = 'krbtgt/%s@%s\n\tEtype (skey, tkt): ' \ + 'aes256-cts-hmac-sha1-96, aes256-cts-hmac-sha1-96' % \ + (realm.realm, realm.realm) +realm.run([klist, '-e'], expected_msg=msg) + +# Test that the KDC only accepts the first enctype for a kvno, for a +# local-realm TGS request. To set this up, we abuse an edge-case +# behavior of modprinc -kvno. First, set up a DES3 krbtgt entry at +# kvno 1 and cache a krbtgt ticket. +realm.run([kadminl, 'cpw', '-randkey', '-e', 'des3-cbc-sha1', + realm.krbtgt_princ]) +realm.run([kadminl, 'modprinc', '-kvno', '1', realm.krbtgt_princ]) +realm.kinit(realm.user_princ, password('user')) +# Add an AES krbtgt entry at kvno 2, and then reset it to kvno 1 +# (modprinc -kvno sets the kvno on all entries without deleting any). +realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes256-cts', + realm.krbtgt_princ]) +realm.run([kadminl, 'modprinc', '-kvno', '1', realm.krbtgt_princ]) +out = realm.run([kadminl, 'getprinc', realm.krbtgt_princ]) +if 'vno 1, aes256-cts' not in out or \ + 'vno 1, DEPRECATED:des3-cbc-sha1' not in out: + fail('keyrollover: setup for TGS enctype test failed') +# Now present the DES3 ticket to the KDC and make sure it's rejected. +realm.run([kvno, realm.host_princ], expected_code=1) + +realm.stop() + +# Test a cross-realm TGT key rollover scenario where realm 1 mimics +# the Active Directory behavior of always using kvno 0 when issuing +# cross-realm TGTs. The first kvno invocation caches a cross-realm +# TGT with the old key, and the second kvno invocation sends it to +# r2's KDC with no kvno to identify it, forcing the KDC to try +# multiple keys. +r1, r2 = cross_realms(2) +crosstgt_princ = 'krbtgt/%s@%s' % (r2.realm, r1.realm) +r1.run([kadminl, 'modprinc', '-kvno', '0', crosstgt_princ]) +r1.run([kvno, r2.host_princ]) +r2.run([kadminl, 'cpw', '-pw', 'newcross', '-keepold', crosstgt_princ]) +r1.run([kadminl, 'cpw', '-pw', 'newcross', crosstgt_princ]) +r1.run([kadminl, 'modprinc', '-kvno', '0', crosstgt_princ]) +r1.run([kvno, r2.user_princ]) + +success('keyrollover') diff --git a/krb5-1.21.3/src/tests/t_keytab.py b/krb5-1.21.3/src/tests/t_keytab.py new file mode 100755 index 00000000..a9adebb2 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_keytab.py @@ -0,0 +1,209 @@ +from k5test import * + +for realm in multipass_realms(create_user=False): + # Test kinit with a keytab. + realm.kinit(realm.host_princ, flags=['-k']) + +realm = K5Realm(get_creds=False, start_kadmind=True) + +# Test kinit with a partial keytab. +mark('partial keytab') +pkeytab = realm.keytab + '.partial' +realm.run([ktutil], input=('rkt %s\ndelent 1\nwkt %s\n' % + (realm.keytab, pkeytab))) +realm.kinit(realm.host_princ, flags=['-k', '-t', pkeytab]) + +# Test kinit with no keys for client in keytab. +mark('no keys for client') +realm.kinit(realm.user_princ, flags=['-k'], expected_code=1, + expected_msg='no suitable keys') + +# Test kinit and klist with client keytab defaults. +mark('client keytab') +realm.extract_keytab(realm.user_princ, realm.client_keytab); +realm.run([kinit, '-k', '-i']) +realm.klist(realm.user_princ) +realm.run([kdestroy]) +realm.kinit(realm.user_princ, flags=['-k', '-i']) +realm.klist(realm.user_princ) +out = realm.run([klist, '-k', '-i']) +if realm.client_keytab not in out or realm.user_princ not in out: + fail('Expected output not seen from klist -k -i') + +# Test implicit request for keytab (-i or -t without -k) +mark('implicit -k') +realm.run([kdestroy]) +realm.kinit(realm.host_princ, flags=['-t', realm.keytab], + expected_msg='keytab specified, forcing -k') +realm.klist(realm.host_princ) +realm.run([kdestroy]) +realm.kinit(realm.user_princ, flags=['-i'], + expected_msg='keytab specified, forcing -k') +realm.klist(realm.user_princ) + +# Test default principal for -k. This operation requires +# canonicalization against the keytab in krb5_get_init_creds_keytab() +# as the krb5_sname_to_principal() result won't have a realm. Try +# with and without without fallback processing since the code paths +# are different. +mark('default principal for -k') +realm.run([kinit, '-k']) +realm.klist(realm.host_princ) +no_canon_conf = {'libdefaults': {'dns_canonicalize_hostname': 'false'}} +no_canon = realm.special_env('no_canon', False, krb5_conf=no_canon_conf) +realm.run([kinit, '-k'], env=no_canon) +realm.klist(realm.host_princ) + +# Test extracting keys with multiple key versions present. +mark('multi-kvno extract') +os.remove(realm.keytab) +realm.run([kadminl, 'cpw', '-randkey', '-keepold', realm.host_princ]) +out = realm.run([kadminl, 'ktadd', '-norandkey', realm.host_princ]) +if 'with kvno 1,' not in out or 'with kvno 2,' not in out: + fail('Expected output not seen from kadmin.local ktadd -norandkey') +out = realm.run([klist, '-k', '-e']) +if ' 1 host/' not in out or ' 2 host/' not in out: + fail('Expected output not seen from klist -k -e') + +# Test again using kadmin over the network. +mark('multi-kvno extract (via kadmin)') +realm.prep_kadmin() +os.remove(realm.keytab) +out = realm.run_kadmin(['ktadd', '-norandkey', realm.host_princ]) +if 'with kvno 1,' not in out or 'with kvno 2,' not in out: + fail('Expected output not seen from kadmin.local ktadd -norandkey') +out = realm.run([klist, '-k', '-e']) +if ' 1 host/' not in out or ' 2 host/' not in out: + fail('Expected output not seen from klist -k -e') + +# Test handling of kvno values beyond 255. Use kadmin over the +# network since we used to have an 8-bit limit on kvno marshalling. + +# Test one key rotation, verifying that the expected new kvno appears +# in the keytab and in the principal entry. +def test_key_rotate(realm, princ, expected_kvno): + realm.run_kadmin(['ktadd', '-k', realm.keytab, princ]) + realm.run([kadminl, 'ktrem', princ, 'old']) + realm.kinit(princ, flags=['-k']) + msg = '%d %s' % (expected_kvno, princ) + out = realm.run([klist, '-k'], expected_msg=msg) + msg = 'Key: vno %d,' % expected_kvno + out = realm.run_kadmin(['getprinc', princ], expected_msg=msg) + +mark('key rotation across boundaries') +princ = 'foo/bar@%s' % realm.realm +realm.addprinc(princ) +os.remove(realm.keytab) +realm.run([kadminl, 'modprinc', '-kvno', '253', princ]) +test_key_rotate(realm, princ, 254) +test_key_rotate(realm, princ, 255) +test_key_rotate(realm, princ, 256) +test_key_rotate(realm, princ, 257) +realm.run([kadminl, 'modprinc', '-kvno', '32766', princ]) +test_key_rotate(realm, princ, 32767) +test_key_rotate(realm, princ, 32768) +test_key_rotate(realm, princ, 32769) +realm.run([kadminl, 'modprinc', '-kvno', '65534', princ]) +test_key_rotate(realm, princ, 65535) +test_key_rotate(realm, princ, 1) +test_key_rotate(realm, princ, 2) + +mark('32-bit kvno') + +# Test that klist -k can read a keytab entry without a 32-bit kvno and +# reports the 8-bit key version. +record = b'\x00\x01' # principal component count +record += b'\x00\x0bKRBTEST.COM' # realm +record += b'\x00\x04user' # principal component +record += b'\x00\x00\x00\x01' # name type (NT-PRINCIPAL) +record += b'\x54\xf7\x4d\x35' # timestamp +record += b'\x02' # key version +record += b'\x00\x12' # enctype +record += b'\x00\x20' # key length +record += b'\x00' * 32 # key bytes +f = open(realm.keytab, 'wb') +f.write(b'\x05\x02\x00\x00\x00' + bytes([len(record)])) +f.write(record) +f.close() +msg = ' 2 %s' % realm.user_princ +out = realm.run([klist, '-k'], expected_msg=msg) + +# Make sure zero-fill isn't treated as a 32-bit kvno. +f = open(realm.keytab, 'wb') +f.write(b'\x05\x02\x00\x00\x00' + bytes([len(record) + 4])) +f.write(record) +f.write(b'\x00\x00\x00\x00') +f.close() +msg = ' 2 %s' % realm.user_princ +out = realm.run([klist, '-k'], expected_msg=msg) + +# Make sure a hand-crafted 32-bit kvno is recognized. +f = open(realm.keytab, 'wb') +f.write(b'\x05\x02\x00\x00\x00' + bytes([len(record) + 4])) +f.write(record) +f.write(b'\x00\x00\x00\x03') +f.close() +msg = ' 3 %s' % realm.user_princ +out = realm.run([klist, '-k'], expected_msg=msg) + +# Test parameter expansion in profile variables +mark('parameter expansion') +realm.stop() +conf = {'libdefaults': { + 'default_keytab_name': 'testdir/%{null}abc%{uid}', + 'default_client_keytab_name': 'testdir/%{null}xyz%{uid}'}} +realm = K5Realm(krb5_conf=conf, create_kdb=False) +del realm.env['KRB5_KTNAME'] +del realm.env['KRB5_CLIENT_KTNAME'] +uidstr = str(os.getuid()) +msg = 'FILE:testdir/abc%s' % uidstr +out = realm.run([klist, '-k'], expected_code=1, expected_msg=msg) +msg = 'FILE:testdir/xyz%s' % uidstr +out = realm.run([klist, '-ki'], expected_code=1, expected_msg=msg) + +conf = {'libdefaults': {'allow_weak_crypto': 'true'}} +realm = K5Realm(create_user=False, create_host=False, krb5_conf=conf) + +realm.run([kadminl, 'ank', '-pw', 'pw', 'default']) +realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw', 'exp']) +realm.run([kadminl, 'ank', '-e', 'aes256-cts:special', '-pw', 'pw', '+preauth', + 'pexp']) + +# Extract one of the explicit salt values from the database. +out = realm.run([kdb5_util, 'tabdump', 'keyinfo']) +salt_dict = {f[0]: f[5] for f in [l.split('\t') for l in out.splitlines()]} +exp_salt = bytes.fromhex(salt_dict['exp@KRBTEST.COM']).decode('ascii') + +# Create a keytab using ktutil addent with the specified options and +# password "pw". Test that we can use it to get initial tickets. +# Remove the keytab afterwards. +def test_addent(realm, princ, opts): + realm.run([ktutil], input=('addent -password -p %s -k 1 %s\npw\nwkt %s\n' % + (princ, opts, realm.keytab))) + realm.kinit(princ, flags=['-k']) + os.remove(realm.keytab) + +mark('ktutil addent') + +# Test with default salt. +test_addent(realm, 'default', '-e aes128-cts') +test_addent(realm, 'default', '-e aes256-cts') + +# Test with a salt specified to ktutil addent. +test_addent(realm, 'exp', '-e aes256-cts -s %s' % exp_salt) + +# Test etype-info fetching. +test_addent(realm, 'default', '-f') +test_addent(realm, 'default', '-f -e aes128-cts') +test_addent(realm, 'exp', '-f') +test_addent(realm, 'pexp', '-f') + +# Regression test for #8914: INT32_MIN length can cause backwards seek +mark('invalid record length') +f = open(realm.keytab, 'wb') +f.write(b'\x05\x02\x80\x00\x00\x00') +f.close() +msg = 'Bad format in keytab while scanning keytab' +realm.run([klist, '-k'], expected_code=1, expected_msg=msg) + +success('Keytab-related tests') diff --git a/krb5-1.21.3/src/tests/t_kprop.py b/krb5-1.21.3/src/tests/t_kprop.py new file mode 100755 index 00000000..4421a7c3 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_kprop.py @@ -0,0 +1,125 @@ +from k5test import * + +conf_replica = {'dbmodules': {'db': {'database_name': '$testdir/db.replica'}}} + +def setup_acl(realm): + acl_file = os.path.join(realm.testdir, 'kpropd-acl') + acl = open(acl_file, 'w') + acl.write(realm.host_princ + '\n') + acl.close() + +def check_output(kpropd): + output('*** kpropd output follows\n') + while True: + line = kpropd.stdout.readline() + if 'Database load process for full propagation completed' in line: + break + output('kpropd: ' + line) + if 'Rejected connection' in line: + fail('kpropd rejected connection from kprop') + +# kprop/kpropd are the only users of krb5_auth_con_initivector, so run +# this test over all enctypes to exercise mkpriv cipher state. +for realm in multipass_realms(create_user=False): + replica = realm.special_env('replica', True, kdc_conf=conf_replica) + + # Set up the kpropd acl file. + setup_acl(realm) + + # Create the replica db. + dumpfile = os.path.join(realm.testdir, 'dump') + realm.run([kdb5_util, 'dump', dumpfile]) + realm.run([kdb5_util, 'load', dumpfile], replica) + realm.run([kdb5_util, 'stash', '-P', 'master'], replica) + + # Make some changes to the primary db. + realm.addprinc('wakawaka') + + # Start kpropd. + kpropd = realm.start_kpropd(replica, ['-d']) + + realm.run([kdb5_util, 'dump', dumpfile]) + realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname]) + check_output(kpropd) + + realm.run([kadminl, 'listprincs'], replica, expected_msg='wakawaka') + +# default_realm tests follow. +# default_realm and domain_realm different than realm.realm (test -r argument). +conf_rep2 = {'dbmodules': {'db': {'database_name': '$testdir/db.replica2'}}} +krb5_conf_rep2 = {'libdefaults': {'default_realm': 'FOO'}, + 'domain_realm': {hostname: 'FOO'}} +# default_realm and domain_realm map differ. +conf_rep3 = {'dbmodules': {'db': {'database_name': '$testdir/db.replica3'}}} +krb5_conf_rep3 = {'domain_realm': {hostname: 'BAR'}} + +realm = K5Realm(create_user=False) +replica2 = realm.special_env('replica2', True, kdc_conf=conf_rep2, + krb5_conf=krb5_conf_rep2) +replica3 = realm.special_env('replica3', True, kdc_conf=conf_rep3, + krb5_conf=krb5_conf_rep3) + +setup_acl(realm) + +# Create the replica db. +dumpfile = os.path.join(realm.testdir, 'dump') +realm.run([kdb5_util, 'dump', dumpfile]) +realm.run([kdb5_util, '-r', realm.realm, 'load', dumpfile], replica2) +realm.run([kdb5_util, 'load', dumpfile], replica3) + +# Make some changes to the primary db. +realm.addprinc('wakawaka') + +# Test override of default_realm with -r realm argument. +kpropd = realm.start_kpropd(replica2, ['-r', realm.realm, '-d']) +realm.run([kdb5_util, 'dump', dumpfile]) +realm.run([kprop, '-r', realm.realm, '-f', dumpfile, '-P', + str(realm.kprop_port()), hostname]) +check_output(kpropd) +realm.run([kadminl, '-r', realm.realm, 'listprincs'], replica2, + expected_msg='wakawaka') + +stop_daemon(kpropd) + +# Test default_realm and domain_realm mismatch. +kpropd = realm.start_kpropd(replica3, ['-d']) +realm.run([kdb5_util, 'dump', dumpfile]) +realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname]) +check_output(kpropd) +realm.run([kadminl, 'listprincs'], replica3, expected_msg='wakawaka') +stop_daemon(kpropd) + +# This test is too resource-intensive to be included in "make check" +# by default, but it can be enabled in the environment to test the +# propagation of databases large enough to require a 12-byte encoding +# of the database size. +if 'KPROP_LARGE_DB_TEST' in os.environ: + output('Generating >4GB dumpfile\n') + with open(dumpfile, 'w') as f: + f.write('kdb5_util load_dump version 6\n') + f.write('princ\t38\t15\t3\t1\t0\tK/M@KRBTEST.COM\t64\t86400\t0\t0\t0' + '\t0\t0\t0\t8\t2\t0100\t9\t8\t0100010000000000\t2\t28' + '\tb93e105164625f6372656174696f6e404b5242544553542e434f4d00' + '\t1\t1\t18\t62\t2000408c027c250e8cc3b81476414f2214d57c1ce' + '38891e29792e87258247c73547df4d5756266931dd6686b62270e6568' + '95a31ec66bfe913b4f15226227\t-1;\n') + for i in range(1, 20000000): + f.write('princ\t38\t21\t1\t1\t0\tp%08d@KRBTEST.COM' % i) + f.write('\t0\t86400\t0\t0\t0\t0\t0\t0\t2\t27' + '\td73e1051757365722f61646d696e404b5242544553542e434f4d00' + '\t1\t1\t17\t46' + '\t10009c8ab7b3f89ccf3ca3ad98352a461b7f4f1b0c49' + '5605117591d9ad52ba4da0adef7a902126973ed2bdc3ffbf\t-1;\n') + assert os.path.getsize(dumpfile) > 4 * 1024 * 1024 * 1024 + with open(dumpfile + '.dump_ok', 'w') as f: + f.write('\0') + conf_large = {'dbmodules': {'db': {'database_name': '$testdir/db.large'}}, + 'realms': {'$realm': {'iprop_resync_timeout': '3600'}}} + large = realm.special_env('large', True, kdc_conf=conf_large) + kpropd = realm.start_kpropd(large, ['-d']) + realm.run([kprop, '-f', dumpfile, '-P', str(realm.kprop_port()), hostname]) + check_output(kpropd) + realm.run([kadminl, 'getprinc', 'p19999999'], env=large, + expected_msg='Principal: p19999999') + +success('kprop tests') diff --git a/krb5-1.21.3/src/tests/t_localauth.py b/krb5-1.21.3/src/tests/t_localauth.py new file mode 100755 index 00000000..75b53a56 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_localauth.py @@ -0,0 +1,154 @@ +from k5test import * + +# Unfortunately, we can't reliably test the k5login module. We can control +# the directory where k5login files are read, but we can't suppress the UID +# validity check, which might fail in some filesystems for a .k5login file +# we create. +conf = {'plugins': {'localauth': { 'disable': 'k5login'}}} +realm = K5Realm(create_kdb=False, krb5_conf=conf) + +def test_an2ln(env, aname, result, msg): + out = realm.run(['./localauth', aname], env=env) + if out != result + '\n': + fail(msg) + +def test_an2ln_err(env, aname, err, msg): + realm.run(['./localauth', aname], env=env, expected_code=1, + expected_msg=err) + +def test_userok(env, aname, lname, ok, msg): + out = realm.run(['./localauth', aname, lname], env=env) + if ((ok and out != 'yes\n') or + (not ok and out != 'no\n')): + fail(msg) + +# The default an2ln method works only in the default realm, and works +# for a single-component principal or a two-component principal where +# the second component is the default realm. +mark('default') +test_an2ln(None, 'user@KRBTEST.COM', 'user', 'default rule 1') +test_an2ln(None, 'user/KRBTEST.COM@KRBTEST.COM', 'user', 'default rule 2') +test_an2ln_err(None, 'user/KRBTEST.COM/x@KRBTEST.COM', 'No translation', + 'default rule (3)') +test_an2ln_err(None, 'user/X@KRBTEST.COM', 'No translation', + 'default rule comp mismatch') +test_an2ln_err(None, 'user@X', 'No translation', 'default rule realm mismatch') + +# auth_to_local_names matches ignore the realm but are case-sensitive. +mark('auth_to_local_names') +conf_names1 = {'realms': {'$realm': {'auth_to_local_names': {'user': 'abcd'}}}} +names1 = realm.special_env('names1', False, conf_names1) +test_an2ln(names1, 'user@KRBTEST.COM', 'abcd', 'auth_to_local_names match') +test_an2ln(names1, 'user@X', 'abcd', 'auth_to_local_names out-of-realm match') +test_an2ln(names1, 'x@KRBTEST.COM', 'x', 'auth_to_local_names mismatch') +test_an2ln(names1, 'User@KRBTEST.COM', 'User', 'auth_to_local_names case') + +# auth_to_local_names values must be in the default realm's section. +conf_names2 = {'realms': {'X': {'auth_to_local_names': {'user': 'abcd'}}}} +names2 = realm.special_env('names2', False, conf_names2) +test_an2ln_err(names2, 'user@X', 'No translation', + 'auth_to_local_names section mismatch') + +# Return a realm environment containing an auth_to_local value (or list). +def a2l_realm(name, values): + conf = {'realms': {'$realm': {'auth_to_local': values}}} + return realm.special_env(name, False, conf) + +# Test explicit use of default method. +mark('explicit default') +auth1 = a2l_realm('auth1', 'DEFAULT') +test_an2ln(auth1, 'user@KRBTEST.COM', 'user', 'default rule') + +# Test some invalid auth_to_local values. +mark('auth_to_local invalid') +auth2 = a2l_realm('auth2', 'RULE') +test_an2ln_err(auth2, 'user@X', 'Improper format', 'null rule') +auth3 = a2l_realm('auth3', 'UNRECOGNIZED:stuff') +test_an2ln_err(auth3, 'user@X', 'Improper format', 'null rule') + +# An empty rule has the default selection string (unparsed principal +# without realm) and no match or substitutions. +mark('rule (empty)') +rule1 = a2l_realm('rule1', 'RULE:') +test_an2ln(rule1, 'user@KRBTEST.COM', 'user', 'empty rule') +test_an2ln(rule1, 'user@X', 'user', 'empty rule (foreign realm)') +test_an2ln(rule1, 'a/b/c@X', 'a/b/c', 'empty rule (multi-component)') + +# Test explicit selection string. Also test that the default method +# is suppressed when auth_to_local values are present. +mark('rule (selection string)') +rule2 = a2l_realm('rule2', 'RULE:[2:$$0.$$2.$$1]') +test_an2ln(rule2, 'aaron/burr@REALM', 'REALM.burr.aaron', 'selection string') +test_an2ln_err(rule2, 'user@KRBTEST.COM', 'No translation', 'suppress default') + +# Test match string. +mark('rule (match string)') +rule3 = a2l_realm('rule3', 'RULE:(.*tail)') +test_an2ln(rule3, 'withtail@X', 'withtail', 'rule match 1') +test_an2ln(rule3, 'x/withtail@X', 'x/withtail', 'rule match 2') +test_an2ln_err(rule3, 'tails@X', 'No translation', 'rule anchor mismatch') + +# Test substitutions. +mark('rule (substitutions)') +rule4 = a2l_realm('rule4', 'RULE:s/birds/bees/') +test_an2ln(rule4, 'thebirdsbirdsbirds@X', 'thebeesbirdsbirds', 'subst 1') +rule5 = a2l_realm('rule4', 'RULE:s/birds/bees/g s/bees/birds/') +test_an2ln(rule4, 'the/birdsbirdsbirds@x', 'the/birdsbeesbees', 'subst 2') + +# Test a bunch of auth_to_local values and rule features in combination. +mark('rule (combo)') +combo = a2l_realm('combo', ['RULE:[1:$$1-$$0](fred.*)s/-/ /g', + 'DEFAULT', + 'RULE:[3:$$1](z.*z)']) +test_an2ln(combo, 'fred@X', 'fred X', 'combo 1') +test_an2ln(combo, 'fred-too@X', 'fred too X', 'combo 2') +test_an2ln(combo, 'fred@KRBTEST.COM', 'fred KRBTEST.COM', 'combo 3') +test_an2ln(combo, 'user@KRBTEST.COM', 'user', 'combo 4') +test_an2ln(combo, 'zazz/b/c@X', 'zazz', 'combo 5') +test_an2ln_err(combo, 'a/b@KRBTEST.COM', 'No translation', 'combo 6') + +# Test the an2ln userok method with the combo environment. +mark('userok (an2ln)') +test_userok(combo, 'fred@X', 'fred X', True, 'combo userok 1') +test_userok(combo, 'user@KRBTEST.COM', 'user', True, 'combo userok 2') +test_userok(combo, 'user@KRBTEST.COM', 'X', False, 'combo userok 3') +test_userok(combo, 'a/b@KRBTEST.COM', 'a/b', False, 'combo userok 4') + +mark('test modules') + +# Register the two test modules and set up some auth_to_local and +# auth_to_local_names entries. +modpath = os.path.join(buildtop, 'plugins', 'localauth', 'test', + 'localauth_test.so') +conf = {'plugins': {'localauth': { 'module': [ + 'test1:' + modpath, + 'test2:' + modpath]}}, + 'realms': {'$realm': {'auth_to_local': [ + 'RULE:(test/rulefirst)s/.*/rule/', + 'TYPEA', + 'DEFAULT', + 'TYPEB:resid']}, + 'auth_to_local_names': {'test/a/b': 'name'}}} +mod = realm.special_env('mod', False, conf) + +# test1's untyped an2ln method should come before the names method, mapping +# test/a/b@X to its realm name (superseding auth_to_local_names). +test_an2ln(mod, 'test/a/b@X', 'X', 'mod untyped an2ln') + +# Match the auth_to_local values in order. test2's TYPEA should map +# test/notrule to its second component, and its TYPEB should map +# anything which gets there to the residual string. +test_an2ln(mod, 'test/rulefirst@X', 'rule', 'mod auth_to_local 1') +test_an2ln(mod, 'test/notrule', 'notrule', 'mod auth_to_local 2') +test_an2ln(mod, 'user@KRBTEST.COM', 'user', 'mod auth_to_local 3') +test_an2ln(mod, 'xyz@X', 'resid', 'mod auth_to_local 4') + +# test2's userok module should succeed when the number of components +# is equal to the length of the local name, should pass if the first +# component is 'pass', and should reject otherwise. +test_userok(mod, 'a/b/c/d@X', 'four', True, 'mod userok 1') +test_userok(mod, 'x/y/z@X', 'four', False, 'mod userok 2') +test_userok(mod, 'pass@KRBTEST.COM', 'pass', True, 'mod userok 3') +test_userok(mod, 'user@KRBTEST.COM', 'user', False, 'mod userok 4') + +success('krb5_kuserok and krb5_aname_to_localname tests') diff --git a/krb5-1.21.3/src/tests/t_mkey.py b/krb5-1.21.3/src/tests/t_mkey.py new file mode 100755 index 00000000..32f4070b --- /dev/null +++ b/krb5-1.21.3/src/tests/t_mkey.py @@ -0,0 +1,344 @@ +from k5test import * +import random +import re +import struct + +# Convenience constants for use as expected enctypes. defetype is the +# default enctype for master keys. +aes256 = 'aes256-cts-hmac-sha1-96' +aes128 = 'aes128-cts-hmac-sha1-96' +des3 = 'des3-cbc-sha1' +defetype = aes256 + +realm = K5Realm(create_host=False, start_kadmind=True) +realm.prep_kadmin() +stash_file = os.path.join(realm.testdir, 'stash') + +# Count the number of principals in the realm. +nprincs = len(realm.run([kadminl, 'listprincs']).splitlines()) + +# List the currently active mkeys and compare against expected +# results. Each argument must be a sequence of four elements: an +# expected kvno, an expected enctype, whether the key is expected to +# have an activation time, and whether the key is expected to be +# currently active. +list_mkeys_re = re.compile(r'^KVNO: (\d+), Enctype: (\S+), ' + r'(Active on: [^\*]+|No activate time set)( \*)?$') +def check_mkey_list(*expected): + # Split the output of kdb5_util list_mkeys into lines and ignore the first. + outlines = realm.run([kdb5_util, 'list_mkeys']).splitlines()[1:] + if len(outlines) != len(expected): + fail('Unexpected number of list_mkeys output lines') + for line, ex in zip(outlines, expected): + m = list_mkeys_re.match(line) + if not m: + fail('Unrecognized list_mkeys output line') + kvno, enctype, act_time, active = m.groups() + exp_kvno, exp_enctype, exp_act_time_present, exp_active = ex + if kvno != str(exp_kvno): + fail('Unexpected master key version') + if enctype != exp_enctype: + fail('Unexpected master key enctype') + if act_time.startswith('Active on: ') != exp_act_time_present: + fail('Unexpected presence or absence of mkey activation time') + if (active == ' *') != exp_active: + fail('Master key unexpectedly active or inactive') + + +# Get the K/M principal. Verify that it has the expected mkvno. Each +# remaining argument must be a sequence of two elements: an expected +# key version and an expected enctype. +keyline_re = re.compile(r'^Key: vno (\d+), (\S+)$') +def check_master_dbent(expected_mkvno, *expected_keys): + outlines = realm.run([kadminl, 'getprinc', 'K/M']).splitlines() + mkeyline = [l for l in outlines if l.startswith('MKey: vno ')] + if len(mkeyline) != 1 or mkeyline[0] != ('MKey: vno %d' % expected_mkvno): + fail('Unexpected mkvno in K/M DB entry') + keylines = [l for l in outlines if l.startswith('Key: vno ')] + if len(keylines) != len(expected_keys): + fail('Unexpected number of key lines in K/M DB entry') + for line, ex in zip(keylines, expected_keys): + m = keyline_re.match(line) + if not m: + fail('Unrecognized key line in K/M DB entry') + kvno, enctype = m.groups() + exp_kvno, exp_enctype = ex + if kvno != str(exp_kvno): + fail('Unexpected key version in K/M DB entry') + if enctype != exp_enctype: + fail('Unexpected enctype in K/M DB entry') + + +# Check the stash file. Each argument must be a sequence of two +# elements: an expected key version and an expected enctype. +klist_re = re.compile(r'^\s*(\d+) K/M@KRBTEST.COM \((\S+)\)') +def check_stash(*expected): + # Split the output of klist -e -k into lines and ignore the first three. + outlines = realm.run([klist, '-e', '-k', stash_file]).splitlines()[3:] + if len(outlines) != len(expected): + fail('Unexpected number of lines in stash file klist') + for line, ex in zip(outlines, expected): + m = klist_re.match(line) + if not m: + fail('Unrecognized stash file klist line') + kvno, enctype = m.groups() + exp_kvno, exp_enctype = ex + if kvno != str(exp_kvno): + fail('Unexpected stash file klist kvno') + if enctype != exp_enctype: + fail('Unexpected stash file klist enctype') + + +# Verify that the user principal has the expected mkvno. +def check_mkvno(princ, expected_mkvno): + msg = 'MKey: vno %d\n' % expected_mkvno + realm.run([kadminl, 'getprinc', princ], expected_msg=msg) + + +# Change the password using either kadmin.local or kadmin, then check +# the mkvno of the principal against expected_mkvno and verify that +# the running KDC can access the new key. +def change_password_check_mkvno(local, princ, password, expected_mkvno): + cmd = ['cpw', '-pw', password, princ] + if local: + realm.run([kadminl] + cmd) + else: + realm.run_kadmin(cmd) + check_mkvno(princ, expected_mkvno) + realm.kinit(princ, password) + + +# Add a master key with the specified options and a random password. +def add_mkey(options): + pw = ''.join(random.choice(string.ascii_uppercase) for x in range(5)) + realm.run([kdb5_util, 'add_mkey'] + options, input=(pw + '\n' + pw + '\n')) + + +# Run kdb5_util update_princ_encryption (with the dry-run option if +# specified) and verify the output against the expected mkvno, number +# of updated principals, and number of already-current principals. +mkvno_re = {False: re.compile(r'^Principals whose keys are being re-encrypted ' + r'to master key vno (\d+) if necessary:$'), + True: re.compile(r'^Principals whose keys WOULD BE re-encrypted ' + r'to master key vno (\d+):$')} +count_re = {False: re.compile(r'^(\d+) principals processed: (\d+) updated, ' + r'(\d+) already current$'), + True: re.compile(r'^(\d+) principals processed: (\d+) would be ' + r'updated, (\d+) already current$')} +def update_princ_encryption(dry_run, expected_mkvno, expected_updated, + expected_current): + opts = ['-f', '-v'] + if dry_run: + opts += ['-n'] + out = realm.run([kdb5_util, 'update_princ_encryption'] + opts) + lines = out.splitlines() + # Parse the first line to get the target mkvno. + m = mkvno_re[dry_run].match(lines[0]) + if not m: + fail('Unexpected first line of update_princ_encryption output') + if m.group(1) != str(expected_mkvno): + fail('Unexpected master key version in update_princ_encryption output') + # Parse the last line to get the principal counts. + m = count_re[dry_run].match(lines[-1]) + if not m: + fail('Unexpected last line of update_princ_encryption output') + total, updated, current = m.groups() + if (total != str(expected_updated + expected_current) or + updated != str(expected_updated) or current != str(expected_current)): + fail('Unexpected counts from update_princ_encryption') + + +# Check the initial state of the realm. +mark('initial state') +check_mkey_list((1, defetype, True, True)) +check_master_dbent(1, (1, defetype)) +check_stash((1, defetype)) +check_mkvno(realm.user_princ, 1) + +# Check that stash will fail if a temp stash file is already present. +mark('temp stash collision') +collisionfile = os.path.join(realm.testdir, 'stash_tmp') +f = open(collisionfile, 'w') +f.close() +realm.run([kdb5_util, 'stash'], expected_code=1, + expected_msg='Temporary stash file already exists') +os.unlink(collisionfile) + +# Add a new master key with no options. Verify that: +# 1. The new key appears in list_mkeys but has no activation time and +# is not active. +# 2. The new key appears in the K/M DB entry and is the current key to +# encrypt that entry. +# 3. The stash file is not modified (since we did not pass -s). +# 4. The old key is used for password changes. +mark('add_mkey (second master key)') +add_mkey([]) +check_mkey_list((2, defetype, False, False), (1, defetype, True, True)) +check_master_dbent(2, (2, defetype), (1, defetype)) +change_password_check_mkvno(True, realm.user_princ, 'abcd', 1) +change_password_check_mkvno(False, realm.user_princ, 'user', 1) + +# Verify that use_mkey won't make all master keys inactive. +mark('use_mkey (no active keys)') +realm.run([kdb5_util, 'use_mkey', '1', 'now+1day'], expected_code=1, + expected_msg='there must be one master key currently active') +check_mkey_list((2, defetype, False, False), (1, defetype, True, True)) + +# Make the new master key active. Verify that: +# 1. The new key has an activation time in list_mkeys and is active. +# 2. The new key is used for password changes. +# 3. The running KDC can access the new key. +mark('use_mkey') +realm.run([kdb5_util, 'use_mkey', '2', 'now-1day']) +check_mkey_list((2, defetype, True, True), (1, defetype, True, False)) +change_password_check_mkvno(True, realm.user_princ, 'abcd', 2) +change_password_check_mkvno(False, realm.user_princ, 'user', 2) + +# Check purge_mkeys behavior with both master keys still in use. +mark('purge_mkeys (nothing to purge)') +realm.run([kdb5_util, 'purge_mkeys', '-f', '-v'], + expected_msg='All keys in use, nothing purged.') + +# Do an update_princ_encryption dry run and for real. Verify that: +# 1. The target master key is 2 (the active mkvno). +# 2. nprincs - 2 principals were updated and one principal was +# skipped (K/M is not included in the output and user was updated +# above). +# 3. The dry run doesn't change user/admin's mkvno but the real update +# does. +# 4. The old stashed master key is sufficient to access the DB (via +# MKEY_AUX tl-data which keeps the current master key encrypted in +# each of the old master keys). +mark('update_princ_encryption') +update_princ_encryption(True, 2, nprincs - 2, 1) +check_mkvno(realm.admin_princ, 1) +update_princ_encryption(False, 2, nprincs - 2, 1) +check_mkvno(realm.admin_princ, 2) +realm.stop_kdc() +realm.start_kdc() +realm.kinit(realm.user_princ, 'user') + +# Update all principals back to mkvno 1 and to mkvno 2 again, to +# verify that update_princ_encryption targets the active master key. +mark('update_princ_encryption (back and forth)') +realm.run([kdb5_util, 'use_mkey', '2', 'now+1day']) +update_princ_encryption(False, 1, nprincs - 1, 0) +check_mkvno(realm.user_princ, 1) +realm.run([kdb5_util, 'use_mkey', '2', 'now-1day']) +update_princ_encryption(False, 2, nprincs - 1, 0) +check_mkvno(realm.user_princ, 2) + +# Test the safety check for purging with an outdated stash file. +mark('purge_mkeys (outdated stash file)') +realm.run([kdb5_util, 'purge_mkeys', '-f'], expected_code=1, + expected_msg='stash file needs updating') + +# Update the master stash file and check it. Save a copy of the old +# one for a later test. +mark('update stash file') +shutil.copy(stash_file, stash_file + '.old') +realm.run([kdb5_util, 'stash']) +check_stash((2, defetype), (1, defetype)) + +# Do a purge_mkeys dry run and for real. Verify that: +# 1. Master key 1 is purged. +# 2. The dry run doesn't remove mkvno 1 but the real one does. +# 3. The old stash file is no longer sufficient to access the DB. +# 4. If the stash file is updated, it no longer contains mkvno 1. +# 5. use_mkey now gives an error if we refer to mkvno 1. +# 6. A second purge_mkeys gives the right message. +mark('purge_mkeys') +out = realm.run([kdb5_util, 'purge_mkeys', '-v', '-n', '-f']) +if 'KVNO: 1' not in out or '1 key(s) would be purged' not in out: + fail('Unexpected output from purge_mkeys dry-run') +check_mkey_list((2, defetype, True, True), (1, defetype, True, False)) +check_master_dbent(2, (2, defetype), (1, defetype)) +out = realm.run([kdb5_util, 'purge_mkeys', '-v', '-f']) +check_mkey_list((2, defetype, True, True)) +check_master_dbent(2, (2, defetype)) +os.rename(stash_file, stash_file + '.save') +os.rename(stash_file + '.old', stash_file) +realm.run([kadminl, 'getprinc', 'user'], expected_code=1, + expected_msg='Unable to decrypt latest master key') +os.rename(stash_file + '.save', stash_file) +realm.run([kdb5_util, 'stash']) +check_stash((2, defetype)) +realm.run([kdb5_util, 'use_mkey', '1'], expected_code=1, + expected_msg='1 is an invalid KVNO value') +realm.run([kdb5_util, 'purge_mkeys', '-f', '-v'], + expected_msg='There is only one master key which can not be purged.') + +# Add a third master key with a specified enctype. Verify that: +# 1. The new master key receives the correct number. +# 2. The enctype argument is respected. +# 3. The new master key is stashed (by itself, at the moment). +# 4. We can roll over to the new master key and use it. +mark('add_mkey and update_princ_encryption (third master key)') +add_mkey(['-s', '-e', aes128]) +check_mkey_list((3, aes128, False, False), (2, defetype, True, True)) +check_master_dbent(3, (3, aes128), (2, defetype)) +check_stash((3, aes128)) +realm.run([kdb5_util, 'use_mkey', '3', 'now-1day']) +update_princ_encryption(False, 3, nprincs - 1, 0) +check_mkey_list((3, aes128, True, True), (2, defetype, True, False)) +check_mkvno(realm.user_princ, 3) + +# Regression test for #7994 (randkey does not update principal mkvno) +# and #7995 (-keepold does not re-encrypt old keys). +mark('#7994 and #7995 regression test') +add_mkey(['-s']) +realm.run([kdb5_util, 'use_mkey', '4', 'now-1day']) +realm.run([kadminl, 'cpw', '-randkey', '-keepold', realm.user_princ]) +# With #7994 unfixed, mkvno of user will still be 3. +check_mkvno(realm.user_princ, 4) +# With #7995 unfixed, old keys are still encrypted with mkvno 3. +update_princ_encryption(False, 4, nprincs - 2, 1) +realm.run([kdb5_util, 'purge_mkeys', '-f']) +out = realm.run([kadminl, 'xst', '-norandkey', realm.user_princ]) +if 'Decrypt integrity check failed' in out or 'added to keytab' not in out: + fail('Preserved old key data not updated to new master key') + +realm.stop() + +# Load a dump file created with krb5 1.6, before the master key +# rollover changes were introduced. Write out an old-format stash +# file consistent with the dump's master password ("footes"). The K/M +# entry in this database will not have actkvno tl-data because it was +# created prior to master key rollover support. Verify that: +# 1. We can access the database using the old-format stash file. +# 2. list_mkeys displays the same list as for a post-1.7 KDB. +mark('pre-1.7 stash file') +dumpfile = os.path.join(srctop, 'tests', 'dumpfiles', 'dump.16') +os.remove(stash_file) +f = open(stash_file, 'wb') +f.write(struct.pack('=HL24s', 16, 24, + b'\xF8\x3E\xFB\xBA\x6D\x80\xD9\x54\xE5\x5D\xF2\xE0' + b'\x94\xAD\x6D\x86\xB5\x16\x37\xEC\x7C\x8A\xBC\x86')) +f.close() +realm.run([kdb5_util, 'load', dumpfile]) +nprincs = len(realm.run([kadminl, 'listprincs']).splitlines()) +check_mkvno('K/M', 1) +check_mkey_list((1, des3, True, True)) + +# Create a new master key and verify that, without actkvkno tl-data: +# 1. list_mkeys displays the same as for a post-1.7 KDB. +# 2. update_princ_encryption still targets mkvno 1. +# 3. libkadm5 still uses mkvno 1 for key changes. +# 4. use_mkey creates the same list as for a post-1.7 KDB. +mark('rollover from pre-1.7 KDB') +add_mkey([]) +check_mkey_list((2, defetype, False, False), (1, des3, True, True)) +update_princ_encryption(False, 1, 0, nprincs - 1) +realm.run([kadminl, 'addprinc', '-randkey', realm.user_princ]) +check_mkvno(realm.user_princ, 1) +realm.run([kdb5_util, 'use_mkey', '2', 'now-1day']) +check_mkey_list((2, defetype, True, True), (1, des3, True, False)) + +# Regression test for #8395. Purge the master key and verify that a +# master key fetch does not segfault. +mark('#8395 regression test') +realm.run([kadminl, 'purgekeys', '-all', 'K/M']) +realm.run([kadminl, 'getprinc', realm.user_princ], expected_code=1, + expected_msg='Cannot find master key record in database') + +success('Master key rollover tests') diff --git a/krb5-1.21.3/src/tests/t_otp.py b/krb5-1.21.3/src/tests/t_otp.py new file mode 100755 index 00000000..c3b820a4 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_otp.py @@ -0,0 +1,272 @@ +# Author: Nathaniel McCallum +# +# Copyright (c) 2013 Red Hat, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +# +# This script tests OTP, both UDP and Unix Sockets, with a variety of +# configuration. It requires pyrad to run, but exits gracefully if not found. +# It also deliberately shuts down the test daemons between tests in order to +# test how OTP handles the case of short daemon restarts. +# + +from k5test import * +from queue import Empty +import io +import struct + +try: + from pyrad import packet, dictionary +except ImportError: + skip_rest('OTP tests', 'Python pyrad module not found') +try: + from multiprocessing import Process, Queue +except ImportError: + skip_rest('OTP tests', 'Python version 2.6 required') + +# We could use a dictionary file, but since we need so few attributes, +# we'll just include them here. +radius_attributes = ''' +ATTRIBUTE User-Name 1 string +ATTRIBUTE User-Password 2 octets +ATTRIBUTE Service-Type 6 integer +ATTRIBUTE NAS-Identifier 32 string +''' + +class RadiusDaemon(Process): + MAX_PACKET_SIZE = 4096 + DICTIONARY = dictionary.Dictionary(io.StringIO(radius_attributes)) + + def listen(self, addr): + raise NotImplementedError() + + def recvRequest(self, data): + raise NotImplementedError() + + def run(self): + addr = self._args[0] + secrfile = self._args[1] + pswd = self._args[2] + outq = self._args[3] + + if secrfile: + with open(secrfile, 'rb') as file: + secr = file.read().strip() + else: + secr = b'' + + data = self.listen(addr) + outq.put("started") + (buf, sock, addr) = self.recvRequest(data) + pkt = packet.AuthPacket(secret=secr, + dict=RadiusDaemon.DICTIONARY, + packet=buf) + + usernm = [] + passwd = [] + for key in pkt.keys(): + if key == 'User-Password': + passwd = list(map(pkt.PwDecrypt, pkt[key])) + elif key == 'User-Name': + usernm = pkt[key] + + reply = pkt.CreateReply() + replyq = {'user': usernm, 'pass': passwd} + if passwd == [pswd]: + reply.code = packet.AccessAccept + replyq['reply'] = True + else: + reply.code = packet.AccessReject + replyq['reply'] = False + + outq.put(replyq) + if addr is None: + sock.send(reply.ReplyPacket()) + else: + sock.sendto(reply.ReplyPacket(), addr) + sock.close() + +class UDPRadiusDaemon(RadiusDaemon): + def listen(self, addr): + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.bind((addr.split(':')[0], int(addr.split(':')[1]))) + return sock + + def recvRequest(self, sock): + (buf, addr) = sock.recvfrom(RadiusDaemon.MAX_PACKET_SIZE) + return (buf, sock, addr) + +class UnixRadiusDaemon(RadiusDaemon): + def listen(self, addr): + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + if os.path.exists(addr): + os.remove(addr) + sock.bind(addr) + sock.listen(1) + return (sock, addr) + + def recvRequest(self, sock_and_addr): + sock, addr = sock_and_addr + conn = sock.accept()[0] + sock.close() + os.remove(addr) + + buf = b'' + remain = RadiusDaemon.MAX_PACKET_SIZE + while True: + buf += conn.recv(remain) + remain = RadiusDaemon.MAX_PACKET_SIZE - len(buf) + if (len(buf) >= 4): + remain = struct.unpack("!BBH", buf[0:4])[2] - len(buf) + if (remain <= 0): + return (buf, conn, None) + +def verify(daemon, queue, reply, usernm, passwd): + try: + data = queue.get(timeout=1) + except Empty: + sys.stderr.write("ERROR: Packet not received by daemon!\n") + daemon.terminate() + sys.exit(1) + assert data['reply'] is reply + assert data['user'] == [usernm] + assert data['pass'] == [passwd] + daemon.join() + +# Compose a single token configuration. +def otpconfig_1(toktype, username=None, indicators=None): + val = '{"type": "%s"' % toktype + if username is not None: + val += ', "username": "%s"' % username + if indicators is not None: + qind = ['"%s"' % s for s in indicators] + jsonlist = '[' + ', '.join(qind) + ']' + val += ', "indicators":' + jsonlist + val += '}' + return val + +# Compose a token configuration list suitable for the "otp" string +# attribute. +def otpconfig(toktype, username=None, indicators=None): + return '[' + otpconfig_1(toktype, username, indicators) + ']' + +prefix = "/tmp/%d" % os.getpid() +secret_file = prefix + ".secret" +socket_file = prefix + ".socket" +with open(secret_file, "w") as file: + file.write("otptest") +atexit.register(lambda: os.remove(secret_file)) + +conf = {'plugins': {'kdcpreauth': {'enable_only': 'otp'}}, + 'otp': {'udp': {'server': '127.0.0.1:$port9', + 'secret': secret_file, + 'strip_realm': 'true', + 'indicator': ['indotp1', 'indotp2']}, + 'unix': {'server': socket_file, + 'strip_realm': 'false'}}} + +queue = Queue() + +realm = K5Realm(kdc_conf=conf) +realm.run([kadminl, 'modprinc', '+requires_preauth', realm.user_princ]) +flags = ['-T', realm.ccache] +server_addr = '127.0.0.1:' + str(realm.portbase + 9) + +## Test UDP fail / custom username +mark('UDP fail / custom username') +daemon = UDPRadiusDaemon(args=(server_addr, secret_file, 'accept', queue)) +daemon.start() +queue.get() +realm.run([kadminl, 'setstr', realm.user_princ, 'otp', + otpconfig('udp', 'custom')]) +realm.kinit(realm.user_princ, 'reject', flags=flags, expected_code=1) +verify(daemon, queue, False, 'custom', 'reject') + +## Test UDP success / standard username +mark('UDP success / standard username') +daemon = UDPRadiusDaemon(args=(server_addr, secret_file, 'accept', queue)) +daemon.start() +queue.get() +realm.run([kadminl, 'setstr', realm.user_princ, 'otp', otpconfig('udp')]) +realm.kinit(realm.user_princ, 'accept', flags=flags) +verify(daemon, queue, True, realm.user_princ.split('@')[0], 'accept') +realm.extract_keytab(realm.krbtgt_princ, realm.keytab) +realm.run(['./adata', realm.krbtgt_princ], + expected_msg='+97: [indotp1, indotp2]') + +# Repeat with an indicators override in the string attribute. +mark('auth indicator override') +daemon = UDPRadiusDaemon(args=(server_addr, secret_file, 'accept', queue)) +daemon.start() +queue.get() +oconf = otpconfig('udp', indicators=['indtok1', 'indtok2']) +realm.run([kadminl, 'setstr', realm.user_princ, 'otp', oconf]) +realm.kinit(realm.user_princ, 'accept', flags=flags) +verify(daemon, queue, True, realm.user_princ.split('@')[0], 'accept') +realm.extract_keytab(realm.krbtgt_princ, realm.keytab) +realm.run(['./adata', realm.krbtgt_princ], + expected_msg='+97: [indtok1, indtok2]') + +# Detect upstream pyrad bug +# https://github.com/wichert/pyrad/pull/18 +try: + auth = packet.Packet.CreateAuthenticator() + packet.Packet(authenticator=auth, secret=b'').ReplyPacket() +except AssertionError: + skip_rest('OTP UNIX domain socket tests', 'pyrad assertion bug detected') + +## Test Unix fail / custom username +mark('Unix socket fail / custom username') +daemon = UnixRadiusDaemon(args=(socket_file, None, 'accept', queue)) +daemon.start() +queue.get() +realm.run([kadminl, 'setstr', realm.user_princ, 'otp', + otpconfig('unix', 'custom')]) +realm.kinit(realm.user_princ, 'reject', flags=flags, expected_code=1) +verify(daemon, queue, False, 'custom', 'reject') + +## Test Unix success / standard username +mark('Unix socket success / standard username') +daemon = UnixRadiusDaemon(args=(socket_file, None, 'accept', queue)) +daemon.start() +queue.get() +realm.run([kadminl, 'setstr', realm.user_princ, 'otp', otpconfig('unix')]) +realm.kinit(realm.user_princ, 'accept', flags=flags) +verify(daemon, queue, True, realm.user_princ, 'accept') + +## Regression test for #8708: test with the standard username and two +## tokens configured, with the first rejecting and the second +## accepting. With the bug, the KDC incorrectly rejects the request +## and then performs invalid memory accesses, most likely crashing. +queue2 = Queue() +daemon1 = UDPRadiusDaemon(args=(server_addr, secret_file, 'accept1', queue)) +daemon2 = UnixRadiusDaemon(args=(socket_file, None, 'accept2', queue2)) +daemon1.start() +queue.get() +daemon2.start() +queue2.get() +oconf = '[' + otpconfig_1('udp') + ', ' + otpconfig_1('unix') + ']' +realm.run([kadminl, 'setstr', realm.user_princ, 'otp', oconf]) +realm.kinit(realm.user_princ, 'accept2', flags=flags) +verify(daemon1, queue, False, realm.user_princ.split('@')[0], 'accept2') +verify(daemon2, queue2, True, realm.user_princ, 'accept2') + +success('OTP tests') diff --git a/krb5-1.21.3/src/tests/t_pkinit.py b/krb5-1.21.3/src/tests/t_pkinit.py new file mode 100755 index 00000000..ec2356ea --- /dev/null +++ b/krb5-1.21.3/src/tests/t_pkinit.py @@ -0,0 +1,438 @@ +from k5test import * + +# Skip this test if pkinit wasn't built. +if not pkinit_enabled: + skip_rest('PKINIT tests', 'PKINIT module not built') + +soft_pkcs11 = os.path.join(buildtop, 'tests', 'softpkcs11', 'softpkcs11.so') + +# Construct a krb5.conf fragment configuring pkinit. +user_pem = os.path.join(pkinit_certs, 'user.pem') +privkey_pem = os.path.join(pkinit_certs, 'privkey.pem') +privkey_enc_pem = os.path.join(pkinit_certs, 'privkey-enc.pem') +user_p12 = os.path.join(pkinit_certs, 'user.p12') +user_enc_p12 = os.path.join(pkinit_certs, 'user-enc.p12') +user_upn_p12 = os.path.join(pkinit_certs, 'user-upn.p12') +user_upn2_p12 = os.path.join(pkinit_certs, 'user-upn2.p12') +user_upn3_p12 = os.path.join(pkinit_certs, 'user-upn3.p12') +generic_p12 = os.path.join(pkinit_certs, 'generic.p12') +path = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs') +path_enc = os.path.join(os.getcwd(), 'testdir', 'tmp-pkinit-certs-enc') + +pkinit_kdc_conf = {'realms': {'$realm': { + 'default_principal_flags': '+preauth', + 'pkinit_eku_checking': 'none', + 'pkinit_indicator': ['indpkinit1', 'indpkinit2']}}} +restrictive_kdc_conf = {'realms': {'$realm': { + 'restrict_anonymous_to_tgt': 'true' }}} +freshness_kdc_conf = {'realms': {'$realm': { + 'pkinit_require_freshness': 'true'}}} + +testprincs = {'krbtgt/KRBTEST.COM': {'keys': 'aes128-cts'}, + 'user': {'keys': 'aes128-cts', 'flags': '+preauth'}, + 'user2': {'keys': 'aes128-cts', 'flags': '+preauth'}} +alias_kdc_conf = {'realms': {'$realm': { + 'default_principal_flags': '+preauth', + 'pkinit_eku_checking': 'none', + 'pkinit_allow_upn': 'true', + 'database_module': 'test'}}, + 'dbmodules': {'test': { + 'db_library': 'test', + 'alias': {'user@krbtest.com': 'user'}, + 'princs': testprincs}}} + +file_identity = 'FILE:%s,%s' % (user_pem, privkey_pem) +file_enc_identity = 'FILE:%s,%s' % (user_pem, privkey_enc_pem) +dir_identity = 'DIR:%s' % path +dir_enc_identity = 'DIR:%s' % path_enc +dir_file_identity = 'FILE:%s,%s' % (os.path.join(path, 'user.crt'), + os.path.join(path, 'user.key')) +dir_file_enc_identity = 'FILE:%s,%s' % (os.path.join(path_enc, 'user.crt'), + os.path.join(path_enc, 'user.key')) +p12_identity = 'PKCS12:%s' % user_p12 +p12_upn_identity = 'PKCS12:%s' % user_upn_p12 +p12_upn2_identity = 'PKCS12:%s' % user_upn2_p12 +p12_upn3_identity = 'PKCS12:%s' % user_upn3_p12 +p12_generic_identity = 'PKCS12:%s' % generic_p12 +p12_enc_identity = 'PKCS12:%s' % user_enc_p12 +p11_identity = 'PKCS11:' + soft_pkcs11 +p11_token_identity = ('PKCS11:module_name=' + soft_pkcs11 + + ':slotid=1:token=SoftToken (token)') + +# Start a realm with the test kdb module for the following UPN SAN tests. +realm = K5Realm(kdc_conf=alias_kdc_conf, create_kdb=False, pkinit=True) +realm.start_kdc() + +mark('UPN SANs') + +# Compatibility check: cert contains UPN "user", which matches the +# request principal user@KRBTEST.COM if parsed as a normal principal. +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_upn2_identity]) + +# Compatibility check: cert contains UPN "user@KRBTEST.COM", which matches +# the request principal user@KRBTEST.COM if parsed as a normal principal. +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_upn3_identity]) + +# Cert contains UPN "user@krbtest.com" which is aliased to the request +# principal. +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_upn_identity]) + +# Test an id-pkinit-san match to a post-canonical principal. +realm.kinit('user@krbtest.com', + flags=['-E', '-X', 'X509_user_identity=%s' % p12_identity]) + +# Test a UPN match to a post-canonical principal. (This only works +# for the cert with the UPN containing just "user", as we don't allow +# UPN reparsing when comparing to the canonicalized client principal.) +realm.kinit('user@krbtest.com', + flags=['-E', '-X', 'X509_user_identity=%s' % p12_upn2_identity]) + +# Test a mismatch. +msg = 'kinit: Client name mismatch while getting initial credentials' +realm.run([kinit, '-X', 'X509_user_identity=%s' % p12_upn2_identity, 'user2'], + expected_code=1, expected_msg=msg) +realm.stop() + +realm = K5Realm(kdc_conf=pkinit_kdc_conf, get_creds=False, pkinit=True) + +# Sanity check - password-based preauth should still work. +mark('password preauth sanity check') +realm.run(['./responder', '-r', 'password=%s' % password('user'), + realm.user_princ]) +realm.kinit(realm.user_princ, password=password('user')) +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) + +# Having tested password preauth, remove the keys for better error +# reporting. +realm.run([kadminl, 'purgekeys', '-all', realm.user_princ]) + +# Test anonymous PKINIT. +mark('anonymous') +realm.kinit('@%s' % realm.realm, flags=['-n'], expected_code=1, + expected_msg='not found in Kerberos database') +realm.addprinc('WELLKNOWN/ANONYMOUS') +realm.kinit('@%s' % realm.realm, flags=['-n']) +realm.klist('WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS') +realm.run([kvno, realm.host_princ]) +out = realm.run(['./adata', realm.host_princ]) +if '97:' in out: + fail('auth indicators seen in anonymous PKINIT ticket') +# Verify start_realm setting and test referrals TGS request. +realm.run([klist, '-C'], expected_msg='start_realm = KRBTEST.COM') +realm.run([kvno, '-S', 'host', hostname]) + +# Test anonymous kadmin. +mark('anonymous kadmin') +f = open(os.path.join(realm.testdir, 'acl'), 'a') +f.write('WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS a *') +f.close() +realm.start_kadmind() +realm.run([kadmin, '-n', 'addprinc', '-pw', 'test', 'testadd']) +realm.run([kadmin, '-n', 'getprinc', 'testadd'], expected_code=1, + expected_msg="Operation requires ``get'' privilege") +realm.stop_kadmind() + +# Test with anonymous restricted; FAST should work but kvno should fail. +mark('anonymous restricted') +r_env = realm.special_env('restrict', True, kdc_conf=restrictive_kdc_conf) +realm.stop_kdc() +realm.start_kdc(env=r_env) +realm.kinit('@%s' % realm.realm, flags=['-n']) +realm.kinit('@%s' % realm.realm, flags=['-n', '-T', realm.ccache]) +realm.run([kvno, realm.host_princ], expected_code=1, + expected_msg='KDC policy rejects request') + +# Regression test for #8458: S4U2Self requests crash the KDC if +# anonymous is restricted. +mark('#8458 regression test') +realm.kinit(realm.host_princ, flags=['-k']) +realm.run([kvno, '-U', 'user', realm.host_princ]) + +# Go back to the normal KDC environment. +realm.stop_kdc() +realm.start_kdc() + +# Run the basic test - PKINIT with FILE: identity, with no password on the key. +mark('FILE identity, no password') +msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'PKINIT client received freshness token from KDC', + 'PKINIT loading CA certs and CRLs from FILE', + 'PKINIT client making DH request', + ' preauth for next request: PA-FX-COOKIE (133), PA-PK-AS-REQ (16)', + 'PKINIT client verified DH reply', + 'PKINIT client found id-pkinit-san in KDC cert', + 'PKINIT client matched KDC principal krbtgt/') +realm.pkinit(realm.user_princ, expected_trace=msgs) +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) + +# Try using multiple configured pkinit_identities, to make sure we +# fall back to the second one when the first one cannot be read. +id_conf = {'realms': {'$realm': {'pkinit_identities': [file_identity + 'X', + file_identity]}}} +id_env = realm.special_env('idconf', False, krb5_conf=id_conf) +realm.kinit(realm.user_princ, expected_trace=msgs, env=id_env) + +# Try again using RSA instead of DH. +mark('FILE identity, no password, RSA') +realm.pkinit(realm.user_princ, flags=['-X', 'flag_RSA_PROTOCOL=yes'], + expected_trace=('PKINIT client making RSA request', + 'PKINIT client verified RSA reply')) +realm.klist(realm.user_princ) + +# Test a DH parameter renegotiation by temporarily setting a 4096-bit +# minimum on the KDC. (Preauth type 16 is PKINIT PA_PK_AS_REQ; +# 109 is PKINIT TD_DH_PARAMETERS; 133 is FAST PA-FX-COOKIE.) +mark('DH parameter renegotiation') +minbits_kdc_conf = {'realms': {'$realm': {'pkinit_dh_min_bits': '4096'}}} +minbits_env = realm.special_env('restrict', True, kdc_conf=minbits_kdc_conf) +realm.stop_kdc() +realm.start_kdc(env=minbits_env) +msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Preauth module pkinit (16) (real) returned: 0/Success', + ' preauth for next request: PA-FX-COOKIE (133), PA-PK-AS-REQ (16)', + '/Key parameters not accepted', + 'Preauth tryagain input types (16): 109, PA-FX-COOKIE (133)', + 'trying again with KDC-provided parameters', + 'Preauth module pkinit (16) tryagain returned: 0/Success', + ' preauth for next request: PA-PK-AS-REQ (16), PA-FX-COOKIE (133)') +realm.pkinit(realm.user_princ, expected_trace=msgs) + +# Test enforcement of required freshness tokens. (We can leave +# freshness tokens required after this test.) +mark('freshness token enforcement') +realm.pkinit(realm.user_princ, flags=['-X', 'disable_freshness=yes']) +f_env = realm.special_env('freshness', True, kdc_conf=freshness_kdc_conf) +realm.stop_kdc() +realm.start_kdc(env=f_env) +realm.pkinit(realm.user_princ) +realm.pkinit(realm.user_princ, flags=['-X', 'disable_freshness=yes'], + expected_code=1, expected_msg='Preauthentication failed') +# Anonymous should never require a freshness token. +realm.kinit('@%s' % realm.realm, flags=['-n', '-X', 'disable_freshness=yes']) + +# Run the basic test - PKINIT with FILE: identity, with a password on the key, +# supplied by the prompter. +# Expect failure if the responder does nothing, and we have no prompter. +mark('FILE identity, password on key (prompter)') +realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % file_enc_identity, + '-X', 'X509_user_identity=%s' % file_enc_identity, realm.user_princ], + expected_code=2) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % file_enc_identity], + password='encrypted') +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) +realm.run(['./adata', realm.host_princ], + expected_msg='+97: [indpkinit1, indpkinit2]') + +# Run the basic test - PKINIT with FILE: identity, with a password on the key, +# supplied by the responder. +# Supply the response in raw form. +mark('FILE identity, password on key (responder)') +out = realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % file_enc_identity, + '-r', 'pkinit={"%s": "encrypted"}' % file_enc_identity, + '-X', 'X509_user_identity=%s' % file_enc_identity, + realm.user_princ]) +# Regression test for #8885 (password question asked twice). +if out.count('OK: ') != 1: + fail('Wrong number of responder calls') +# Supply the response through the convenience API. +realm.run(['./responder', '-X', 'X509_user_identity=%s' % file_enc_identity, + '-p', '%s=%s' % (file_enc_identity, 'encrypted'), realm.user_princ]) +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) + +# PKINIT with DIR: identity, with no password on the key. +mark('DIR identity, no password') +os.mkdir(path) +os.mkdir(path_enc) +shutil.copy(privkey_pem, os.path.join(path, 'user.key')) +shutil.copy(privkey_enc_pem, os.path.join(path_enc, 'user.key')) +shutil.copy(user_pem, os.path.join(path, 'user.crt')) +shutil.copy(user_pem, os.path.join(path_enc, 'user.crt')) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % dir_identity]) +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) + +# PKINIT with DIR: identity, with a password on the key, supplied by the +# prompter. +# Expect failure if the responder does nothing, and we have no prompter. +mark('DIR identity, password on key (prompter)') +realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % dir_file_enc_identity, + '-X', 'X509_user_identity=%s' % dir_enc_identity, realm.user_princ], + expected_code=2) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % dir_enc_identity], + password='encrypted') +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) + +# PKINIT with DIR: identity, with a password on the key, supplied by the +# responder. +# Supply the response in raw form. +mark('DIR identity, password on key (responder)') +realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % dir_file_enc_identity, + '-r', 'pkinit={"%s": "encrypted"}' % dir_file_enc_identity, + '-X', 'X509_user_identity=%s' % dir_enc_identity, realm.user_princ]) +# Supply the response through the convenience API. +realm.run(['./responder', '-X', 'X509_user_identity=%s' % dir_enc_identity, + '-p', '%s=%s' % (dir_file_enc_identity, 'encrypted'), + realm.user_princ]) +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) + +# PKINIT with PKCS12: identity, with no password on the bundle. +mark('PKCS12 identity, no password') +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_identity]) +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) + +# PKINIT with PKCS12: identity, with a password on the bundle, supplied by the +# prompter. +# Expect failure if the responder does nothing, and we have no prompter. +mark('PKCS12 identity, password on bundle (prompter)') +realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % p12_enc_identity, + '-X', 'X509_user_identity=%s' % p12_enc_identity, realm.user_princ], + expected_code=2) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_enc_identity], + password='encrypted') +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) + +# PKINIT with PKCS12: identity, with a password on the bundle, supplied by the +# responder. +# Supply the response in raw form. +mark('PKCS12 identity, password on bundle (responder)') +realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % p12_enc_identity, + '-r', 'pkinit={"%s": "encrypted"}' % p12_enc_identity, + '-X', 'X509_user_identity=%s' % p12_enc_identity, realm.user_princ]) +# Supply the response through the convenience API. +realm.run(['./responder', '-X', 'X509_user_identity=%s' % p12_enc_identity, + '-p', '%s=%s' % (p12_enc_identity, 'encrypted'), + realm.user_princ]) +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) + +mark('pkinit_cert_match rules') + +# Match a single rule. +rule = '^user@KRBTEST.COM$' +realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule]) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_identity]) +realm.klist(realm.user_princ) + +# Regression test for #8670: match a UPN SAN with a single rule. +rule = '^user@krbtest.com$' +realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule]) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_upn_identity]) +realm.klist(realm.user_princ) + +# Match a combined rule (default prefix is &&). +rule = 'CN=user$digitalSignature,keyEncipherment' +realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule]) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_identity]) +realm.klist(realm.user_princ) + +# Fail an && rule. +rule = '&&O=OTHER.COM^user@KRBTEST.COM$' +realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule]) +msg = 'kinit: Certificate mismatch while getting initial credentials' +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_identity], + expected_code=1, expected_msg=msg) + +# Pass an || rule. +rule = '||O=KRBTEST.COM^otheruser@KRBTEST.COM$' +realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule]) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_identity]) +realm.klist(realm.user_princ) + +# Fail an || rule. +rule = '||O=OTHER.COM^otheruser@KRBTEST.COM$' +realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule]) +msg = 'kinit: Certificate mismatch while getting initial credentials' +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_identity], + expected_code=1, expected_msg=msg) + +# Authorize a client cert with no PKINIT extensions using subject and +# issuer. (Relies on EKU checking being turned off.) +rule = '&&CN=user$O=MIT,' +realm.run([kadminl, 'setstr', realm.user_princ, 'pkinit_cert_match', rule]) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p12_generic_identity]) +realm.klist(realm.user_princ) + +# Regression test for #8726: null deref when parsing a FILE residual +# beginning with a comma. +realm.kinit(realm.user_princ, flags=['-X', 'X509_user_identity=,'], + expected_code=1, expected_msg='Preauthentication failed while') + +softpkcs11rc = os.path.join(os.getcwd(), 'testdir', 'soft-pkcs11.rc') +realm.env['SOFTPKCS11RC'] = softpkcs11rc + +# PKINIT with PKCS11: identity, with no need for a PIN. +mark('PKCS11 identity, no PIN') +conf = open(softpkcs11rc, 'w') +conf.write("%s\t%s\t%s\t%s\n" % ('user', 'user token', user_pem, privkey_pem)) +conf.close() +# Expect to succeed without having to supply any more information. +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p11_identity]) +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) + +# PKINIT with PKCS11: identity, with a PIN supplied by the prompter. +mark('PKCS11 identity, with PIN (prompter)') +os.remove(softpkcs11rc) +conf = open(softpkcs11rc, 'w') +conf.write("%s\t%s\t%s\t%s\n" % ('user', 'user token', user_pem, + privkey_enc_pem)) +conf.close() +# Expect failure if the responder does nothing, and there's no prompter +realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % p11_token_identity, + '-X', 'X509_user_identity=%s' % p11_identity, realm.user_princ], + expected_code=2) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p11_identity], + password='encrypted') +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) + +# Supply the wrong PIN. +mark('PKCS11 identity, wrong PIN') +expected_trace = ('PKINIT client has no configured identity; giving up',) +realm.kinit(realm.user_princ, + flags=['-X', 'X509_user_identity=%s' % p11_identity], + password='wrong', expected_code=1, expected_trace=expected_trace) + +# PKINIT with PKCS11: identity, with a PIN supplied by the responder. +# Supply the response in raw form. +mark('PKCS11 identity, with PIN (responder)') +realm.run(['./responder', '-x', 'pkinit={"%s": 0}' % p11_token_identity, + '-r', 'pkinit={"%s": "encrypted"}' % p11_token_identity, + '-X', 'X509_user_identity=%s' % p11_identity, realm.user_princ]) +# Supply the response through the convenience API. +realm.run(['./responder', '-X', 'X509_user_identity=%s' % p11_identity, + '-p', '%s=%s' % (p11_token_identity, 'encrypted'), + realm.user_princ]) +realm.klist(realm.user_princ) +realm.run([kvno, realm.host_princ]) + +success('PKINIT tests') diff --git a/krb5-1.21.3/src/tests/t_policy.py b/krb5-1.21.3/src/tests/t_policy.py new file mode 100755 index 00000000..2bb4f5f1 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_policy.py @@ -0,0 +1,217 @@ +from k5test import * +import re + +realm = K5Realm(create_host=False, start_kadmind=True) + +# Test password quality enforcement. +mark('password quality') +realm.run([kadminl, 'addpol', '-minlength', '6', '-minclasses', '2', 'pwpol']) +realm.run([kadminl, 'addprinc', '-randkey', '-policy', 'pwpol', 'pwuser']) +realm.run([kadminl, 'cpw', '-pw', 'sh0rt', 'pwuser'], expected_code=1, + expected_msg='Password is too short') +realm.run([kadminl, 'cpw', '-pw', 'longenough', 'pwuser'], expected_code=1, + expected_msg='Password does not contain enough character classes') +realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser']) + +# Test some password history enforcement. Even with no history value, +# the current password should be denied. +mark('password history') +realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser'], expected_code=1, + expected_msg='Cannot reuse password') +realm.run([kadminl, 'modpol', '-history', '2', 'pwpol']) +realm.run([kadminl, 'cpw', '-pw', 'an0therpw', 'pwuser']) +realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser'], expected_code=1, + expected_msg='Cannot reuse password') +realm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser']) +realm.run([kadminl, 'cpw', '-pw', 'l0ngenough', 'pwuser']) + +# Regression test for #929 (kadmind crash with more historical +# passwords in a principal entry than current policy history setting). +mark('password history (policy value reduced below current array size)') +realm.run([kadminl, 'addpol', '-history', '5', 'histpol']) +realm.addprinc('histprinc', 'first') +realm.run([kadminl, 'modprinc', '-policy', 'histpol', 'histprinc']) +realm.run([kadminl, 'cpw', '-pw', 'second', 'histprinc']) +realm.run([kadminl, 'cpw', '-pw', 'third', 'histprinc']) +realm.run([kadminl, 'cpw', '-pw', 'fourth', 'histprinc']) +realm.run([kadminl, 'modpol', '-history', '3', 'histpol']) +realm.run([kadminl, 'cpw', '-pw', 'fifth', 'histprinc']) +realm.run([kadminl, 'delprinc', 'histprinc']) + +# Regression test for #2841 (heap buffer overflow when policy history +# value is reduced to match the number of historical passwords for a +# principal). +mark('password history (policy value reduced to current array size)') +def histfail(*pwlist): + for pw in pwlist: + realm.run([kadminl, 'cpw', '-pw', pw, 'histprinc'], expected_code=1, + expected_msg='Cannot reuse password') +realm.run([kadminl, 'modpol', '-history', '3', 'histpol']) +realm.addprinc('histprinc', '1111') +realm.run([kadminl, 'modprinc', '-policy', 'histpol', 'histprinc']) +realm.run([kadminl, 'cpw', '-pw', '2222', 'histprinc']) +histfail('2222', '1111') +realm.run([kadminl, 'modpol', '-history', '2', 'histpol']) +realm.run([kadminl, 'cpw', '-pw', '3333', 'histprinc']) + +# Test that the history array is properly resized if the policy +# history value is increased after the array is filled. +mark('password history (policy value increase)') +realm.run([kadminl, 'delprinc', 'histprinc']) +realm.addprinc('histprinc', '1111') +realm.run([kadminl, 'modprinc', '-policy', 'histpol', 'histprinc']) +realm.run([kadminl, 'cpw', '-pw', '2222', 'histprinc']) +histfail('2222', '1111') +realm.run([kadminl, 'cpw', '-pw', '2222', 'histprinc'], expected_code=1, + expected_msg='Cannot reuse password') +realm.run([kadminl, 'cpw', '-pw', '1111', 'histprinc'], expected_code=1, + expected_msg='Cannot reuse password') +realm.run([kadminl, 'modpol', '-history', '3', 'histpol']) +realm.run([kadminl, 'cpw', '-pw', '3333', 'histprinc']) +histfail('3333', '2222', '1111') +realm.run([kadminl, 'modpol', '-history', '4', 'histpol']) +histfail('3333', '2222', '1111') +realm.run([kadminl, 'cpw', '-pw', '4444', 'histprinc']) +histfail('4444', '3333', '2222', '1111') + +# Test that when the policy history value is reduced, all currently +# known old passwords still fail until the next password change, after +# which the new number of old passwords fails (but no more). +mark('password history (policy value reduction)') +realm.run([kadminl, 'modpol', '-history', '3', 'histpol']) +histfail('4444', '3333', '2222', '1111') +realm.run([kadminl, 'cpw', '-pw', '5555', 'histprinc']) +histfail('5555', '3333', '3333') +realm.run([kadminl, 'cpw', '-pw', '2222', 'histprinc']) +realm.run([kadminl, 'modpol', '-history', '2', 'histpol']) +histfail('2222', '5555', '4444') +realm.run([kadminl, 'cpw', '-pw', '3333', 'histprinc']) + +# Test references to nonexistent policies. +mark('nonexistent policy references') +realm.run([kadminl, 'addprinc', '-randkey', '-policy', 'newpol', 'newuser']) +realm.run([kadminl, 'getprinc', 'newuser'], + expected_msg='Policy: newpol [does not exist]\n') +realm.run([kadminl, 'modprinc', '-policy', 'newpol', 'pwuser']) +# pwuser should allow reuse of the current password since newpol doesn't exist. +realm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser']) +# Regression test for #8427 (min_life check with nonexistent policy). +realm.run([kadmin, '-p', 'pwuser', '-w', '3rdpassword', 'cpw', '-pw', + '3rdpassword', 'pwuser']) + +# Create newpol and verify that it is enforced. +mark('create referenced policy') +realm.run([kadminl, 'addpol', '-minlength', '3', 'newpol']) +realm.run([kadminl, 'getprinc', 'pwuser'], expected_msg='Policy: newpol\n') +realm.run([kadminl, 'cpw', '-pw', 'aa', 'pwuser'], expected_code=1, + expected_msg='Password is too short') +realm.run([kadminl, 'cpw', '-pw', '3rdpassword', 'pwuser'], expected_code=1, + expected_msg='Cannot reuse password') + +realm.run([kadminl, 'getprinc', 'newuser'], expected_msg='Policy: newpol\n') +realm.run([kadminl, 'cpw', '-pw', 'aa', 'newuser'], expected_code=1, + expected_msg='Password is too short') + +# Delete the policy and verify that it is no longer enforced. +mark('delete referenced policy') +realm.run([kadminl, 'delpol', 'newpol']) +realm.run([kadminl, 'getpol', 'newpol'], expected_code=1, + expected_msg='Policy does not exist') +realm.run([kadminl, 'cpw', '-pw', 'aa', 'pwuser']) + +# Test basic password lockout support. +mark('password lockout') +realm.stop() +for realm in multidb_realms(create_host=False): + realm.run([kadminl, 'addpol', '-maxfailure', '2', '-failurecountinterval', + '5m', 'lockout']) + realm.run([kadminl, 'modprinc', '+requires_preauth', '-policy', 'lockout', + 'user']) + + # kinit twice with the wrong password. + msg = 'Password incorrect while getting initial credentials' + realm.run([kinit, realm.user_princ], input='wrong\n', expected_code=1, + expected_msg=msg) + realm.run([kinit, realm.user_princ], input='wrong\n', expected_code=1, + expected_msg=msg) + + # Now the account should be locked out. + msg = 'credentials have been revoked while getting initial credentials' + realm.run([kinit, realm.user_princ], expected_code=1, expected_msg=msg) + + # Check that modprinc -unlock allows a further attempt. + realm.run([kadminl, 'modprinc', '-unlock', 'user']) + realm.kinit(realm.user_princ, password('user')) + + # Make sure a nonexistent policy reference doesn't prevent authentication. + realm.run([kadminl, 'delpol', 'lockout']) + realm.kinit(realm.user_princ, password('user')) + +# Regression test for issue #7099: databases created prior to krb5 1.3 have +# multiple history keys, and kadmin prior to 1.7 didn't necessarily use the +# first one to create history entries. +mark('#7099 regression test') +realm = K5Realm(start_kdc=False) +# Create a history principal with two keys. +realm.run(['./hist', 'make']) +realm.run([kadminl, 'addpol', '-history', '2', 'pol']) +realm.run([kadminl, 'modprinc', '-policy', 'pol', 'user']) +realm.run([kadminl, 'cpw', '-pw', 'pw2', 'user']) +# Swap the keys, simulating older kadmin having chosen the second entry. +realm.run(['./hist', 'swap']) +# Make sure we can read the history entry. +realm.run([kadminl, 'cpw', '-pw', password('user'), 'user'], expected_code=1, + expected_msg='Cannot reuse password') + +# Test key/salt constraints. +mark('allowedkeysalts') + +realm.stop() +krb5_conf1 = {'libdefaults': {'supported_enctypes': 'aes256-cts'}} +realm = K5Realm(krb5_conf=krb5_conf1, create_host=False, get_creds=False) + +# Add policy. +realm.run([kadminl, 'addpol', '-allowedkeysalts', 'aes256-cts', 'ak']) +realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server']) + +# Test with one-enctype allowed_keysalts. +realm.run([kadminl, 'modprinc', '-policy', 'ak', 'server']) +out = realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes128-cts', 'server'], + expected_code=1) +if not 'Invalid key/salt tuples' in out: + fail('allowed_keysalts policy not applied properly') +realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts', 'server']) + +# Now test a multi-enctype allowed_keysalts. Test that subsets are allowed, +# the the complete set is allowed, that order doesn't matter, and that +# enctypes outside the set are not allowed. + +# Test modpol. +realm.run([kadminl, 'modpol', '-allowedkeysalts', 'aes256-cts,rc4-hmac', 'ak']) +realm.run([kadminl, 'getpol', 'ak'], + expected_msg='Allowed key/salt types: aes256-cts,rc4-hmac') + +# Test subsets and full set. +realm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac', 'server']) +realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts', 'server']) +realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes256-cts,rc4-hmac', 'server']) +realm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac,aes256-cts', 'server']) + +# Check that the order we got is the one from the policy. +realm.run([kadminl, 'getprinc', '-terse', 'server'], + expected_msg='2\t1\t6\t18\t0\t1\t6\t23\t0') + +# Test partially intersecting sets. +realm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac,aes128-cts', 'server'], + expected_code=1, expected_msg='Invalid key/salt tuples') +realm.run([kadminl, 'cpw', '-randkey', '-e', 'rc4-hmac,aes256-cts,aes128-cts', + 'server'], expected_code=1, expected_msg='Invalid key/salt tuples') + +# Test reset of allowedkeysalts. +realm.run([kadminl, 'modpol', '-allowedkeysalts', '-', 'ak']) +out = realm.run([kadminl, 'getpol', 'ak']) +if 'Allowed key/salt types' in out: + fail('failed to clear allowedkeysalts') +realm.run([kadminl, 'cpw', '-randkey', '-e', 'aes128-cts', 'server']) + +success('Policy tests') diff --git a/krb5-1.21.3/src/tests/t_preauth.py b/krb5-1.21.3/src/tests/t_preauth.py new file mode 100644 index 00000000..d95eed5d --- /dev/null +++ b/krb5-1.21.3/src/tests/t_preauth.py @@ -0,0 +1,265 @@ +from k5test import * + +# Test that the kdcpreauth client_keyblock() callback matches the key +# indicated by the etype info, and returns NULL if no key was selected. +testpreauth = os.path.join(buildtop, 'plugins', 'preauth', 'test', 'test.so') +conf = {'plugins': {'kdcpreauth': {'module': 'test:' + testpreauth}, + 'clpreauth': {'module': 'test:' + testpreauth}}} +realm = K5Realm(create_host=False, get_creds=False, krb5_conf=conf) +realm.run([kadminl, 'modprinc', '+requires_preauth', realm.user_princ]) +realm.run([kadminl, 'setstr', realm.user_princ, 'teststring', 'testval']) +realm.run([kadminl, 'addprinc', '-nokey', '+requires_preauth', 'nokeyuser']) +realm.kinit(realm.user_princ, password('user'), expected_msg='testval') +realm.kinit('nokeyuser', password('user'), expected_code=1, + expected_msg='no key') + +# Preauth type -123 is the test preauth module type; 133 is FAST +# PA-FX-COOKIE; 2 is encrypted timestamp. + +# Test normal preauth flow. +mark('normal') +msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: PA-FX-COOKIE (133), -123', + 'Decrypted AS reply') +realm.run(['./icred', realm.user_princ, password('user')], + expected_msg='testval', expected_trace=msgs) + +# Test successful optimistic preauth. +mark('optimistic') +expected_trace = ('Attempting optimistic preauth', + 'Processing preauth types: -123', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: -123', + 'Decrypted AS reply') +realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')], + expected_trace=expected_trace) + +# Test optimistic preauth failing on client, falling back to encrypted +# timestamp. +mark('optimistic (client failure)') +msgs = ('Attempting optimistic preauth', + 'Processing preauth types: -123', + '/induced optimistic fail', + 'Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Encrypted timestamp (for ', + 'module encrypted_timestamp (2) (real) returned: 0/Success', + 'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)', + 'Decrypted AS reply') +realm.run(['./icred', '-o', '-123', '-X', 'fail_optimistic', realm.user_princ, + password('user')], expected_trace=msgs) + +# Test optimistic preauth failing on KDC, falling back to encrypted +# timestamp. +mark('optimistic (KDC failure)') +realm.run([kadminl, 'setstr', realm.user_princ, 'failopt', 'yes']) +msgs = ('Attempting optimistic preauth', + 'Processing preauth types: -123', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: -123', + '/Preauthentication failed', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Encrypted timestamp (for ', + 'module encrypted_timestamp (2) (real) returned: 0/Success', + 'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)', + 'Decrypted AS reply') +realm.run(['./icred', '-o', '-123', realm.user_princ, password('user')], + expected_trace=msgs) +# Leave failopt set for the next test. + +# Test optimistic preauth failing on KDC, stopping because the test +# module disabled fallback. +mark('optimistic (KDC failure, no fallback)') +msgs = ('Attempting optimistic preauth', + 'Processing preauth types: -123', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: -123', + '/Preauthentication failed') +realm.run(['./icred', '-X', 'disable_fallback', '-o', '-123', realm.user_princ, + password('user')], expected_code=1, + expected_msg='Preauthentication failed', expected_trace=msgs) +realm.run([kadminl, 'delstr', realm.user_princ, 'failopt']) + +# Test KDC_ERR_MORE_PREAUTH_DATA_REQUIRED and secure cookies. +mark('second round-trip') +realm.run([kadminl, 'setstr', realm.user_princ, '2rt', 'secondtrip']) +msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: PA-FX-COOKIE (133), -123', + '/More preauthentication data is required', + 'Continuing preauth mech -123', + 'Processing preauth types: -123, PA-FX-COOKIE (133)', + 'Produced preauth for next request: PA-FX-COOKIE (133), -123', + 'Decrypted AS reply') +realm.run(['./icred', realm.user_princ, password('user')], + expected_msg='2rt: secondtrip', expected_trace=msgs) + +# Test client-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, +# falling back to encrypted timestamp. +mark('second round-trip (client failure)') +msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: PA-FX-COOKIE (133), -123', + '/More preauthentication data is required', + 'Continuing preauth mech -123', + 'Processing preauth types: -123, PA-FX-COOKIE (133)', + '/induced 2rt fail', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Encrypted timestamp (for ', + 'module encrypted_timestamp (2) (real) returned: 0/Success', + 'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)', + 'Decrypted AS reply') +realm.run(['./icred', '-X', 'fail_2rt', realm.user_princ, password('user')], + expected_msg='2rt: secondtrip', expected_trace=msgs) + +# Test client-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, +# stopping because the test module disabled fallback. +mark('second round-trip (client failure, no fallback)') +msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: PA-FX-COOKIE (133), -123', + '/More preauthentication data is required', + 'Continuing preauth mech -123', + 'Processing preauth types: -123, PA-FX-COOKIE (133)', + '/induced 2rt fail') +realm.run(['./icred', '-X', 'fail_2rt', '-X', 'disable_fallback', + realm.user_princ, password('user')], expected_code=1, + expected_msg='Pre-authentication failed: induced 2rt fail', + expected_trace=msgs) + +# Test KDC-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, +# falling back to encrypted timestamp. +mark('second round-trip (KDC failure)') +realm.run([kadminl, 'setstr', realm.user_princ, 'fail2rt', 'yes']) +msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: PA-FX-COOKIE (133), -123', + '/More preauthentication data is required', + 'Continuing preauth mech -123', + 'Processing preauth types: -123, PA-FX-COOKIE (133)', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: PA-FX-COOKIE (133), -123', + '/Preauthentication failed', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Encrypted timestamp (for ', + 'module encrypted_timestamp (2) (real) returned: 0/Success', + 'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)', + 'Decrypted AS reply') +realm.run(['./icred', realm.user_princ, password('user')], + expected_msg='2rt: secondtrip', expected_trace=msgs) +# Leave fail2rt set for the next test. + +# Test KDC-side failure after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED, +# stopping because the test module disabled fallback. +mark('second round-trip (KDC failure, no fallback)') +msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: PA-FX-COOKIE (133), -123', + '/More preauthentication data is required', + 'Continuing preauth mech -123', + 'Processing preauth types: -123, PA-FX-COOKIE (133)', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: PA-FX-COOKIE (133), -123', + '/Preauthentication failed') +realm.run(['./icred', '-X', 'disable_fallback', + realm.user_princ, password('user')], expected_code=1, + expected_msg='Preauthentication failed', expected_trace=msgs) +realm.run([kadminl, 'delstr', realm.user_princ, 'fail2rt']) + +# Test tryagain flow by inducing a KDC_ERR_ENCTYPE_NOSUPP error on the KDC. +mark('tryagain') +realm.run([kadminl, 'setstr', realm.user_princ, 'err', 'testagain']) +msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: PA-FX-COOKIE (133), -123', + '/KDC has no support for encryption type', + 'Recovering from KDC error 14 using preauth mech -123', + 'Preauth tryagain input types (-123): -123, PA-FX-COOKIE (133)', + 'Preauth module test (-123) tryagain returned: 0/Success', + 'Followup preauth for next request: -123, PA-FX-COOKIE (133)', + 'Decrypted AS reply') +realm.run(['./icred', realm.user_princ, password('user')], + expected_msg='tryagain: testagain', expected_trace=msgs) + +# Test a client-side tryagain failure, falling back to encrypted +# timestamp. +mark('tryagain (client failure)') +msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: PA-FX-COOKIE (133), -123', + '/KDC has no support for encryption type', + 'Recovering from KDC error 14 using preauth mech -123', + 'Preauth tryagain input types (-123): -123, PA-FX-COOKIE (133)', + '/induced tryagain fail', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Encrypted timestamp (for ', + 'module encrypted_timestamp (2) (real) returned: 0/Success', + 'preauth for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)', + 'Decrypted AS reply') +realm.run(['./icred', '-X', 'fail_tryagain', realm.user_princ, + password('user')], expected_trace=msgs) + +# Test a client-side tryagain failure, stopping because the test +# module disabled fallback. +mark('tryagain (client failure, no fallback)') +msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Preauthenticating using KDC method data', + 'Processing preauth types:', + 'Preauth module test (-123) (real) returned: 0/Success', + 'Produced preauth for next request: PA-FX-COOKIE (133), -123', + '/KDC has no support for encryption type', + 'Recovering from KDC error 14 using preauth mech -123', + 'Preauth tryagain input types (-123): -123, PA-FX-COOKIE (133)', + '/induced tryagain fail') +realm.run(['./icred', '-X', 'fail_tryagain', '-X', 'disable_fallback', + realm.user_princ, password('user')], expected_code=1, + expected_msg='KDC has no support for encryption type', + expected_trace=msgs) + +# Test that multiple stepwise initial creds operations can be +# performed with the same krb5_context, with proper tracking of +# clpreauth module request handles. +mark('interleaved') +realm.run([kadminl, 'addprinc', '-pw', 'pw', 'u1']) +realm.run([kadminl, 'addprinc', '+requires_preauth', '-pw', 'pw', 'u2']) +realm.run([kadminl, 'addprinc', '+requires_preauth', '-pw', 'pw', 'u3']) +realm.run([kadminl, 'setstr', 'u2', '2rt', 'extra']) +out = realm.run(['./icinterleave', 'pw', 'u1', 'u2', 'u3']) +if out != ('step 1\nstep 2\nstep 3\nstep 1\nfinish 1\nstep 2\nno attr\n' + 'step 3\nno attr\nstep 2\n2rt: extra\nstep 3\nfinish 3\nstep 2\n' + 'finish 2\n'): + fail('unexpected output from icinterleave') + +success('Pre-authentication framework tests') diff --git a/krb5-1.21.3/src/tests/t_princflags.py b/krb5-1.21.3/src/tests/t_princflags.py new file mode 100755 index 00000000..aa366021 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_princflags.py @@ -0,0 +1,138 @@ +from k5test import * +from princflags import * +import re + +realm = K5Realm(create_host=False, get_creds=False) + +# Regex pattern to match an empty attribute line from kadmin getprinc +emptyattr = re.compile('^Attributes:$', re.MULTILINE) + + +# Regex pattern to match a kadmin getprinc output for a flag tuple +def attr_pat(ftuple): + return re.compile('^Attributes: ' + ftuple.flagname() + '$', + re.MULTILINE) + + +# Test one flag tuple for kadmin ank. +def one_kadmin_flag(ftuple): + pat = attr_pat(ftuple) + realm.run([kadminl, 'ank', ftuple.setspec(), + '-pw', 'password', 'test']) + out = realm.run([kadminl, 'getprinc', 'test']) + if not pat.search(out): + fail('Failed to set flag ' + ftuple.flagname()) + + realm.run([kadminl, 'modprinc', ftuple.clearspec(), 'test']) + out = realm.run([kadminl, 'getprinc', 'test']) + if not emptyattr.search(out): + fail('Failed to clear flag ' + ftuple.flagname()) + realm.run([kadminl, 'delprinc', 'test']) + + +# Generate a custom kdc.conf with default_principal_flags set +# according to ftuple. +def genkdcconf(ftuple): + d = { 'realms': { '$realm': { + 'default_principal_flags': ftuple.setspec() + }}} + return realm.special_env('tmp', True, kdc_conf=d) + + +# Test one ftuple for kdc.conf default_principal_flags. +def one_kdcconf(ftuple): + e = genkdcconf(ftuple) + pat = attr_pat(ftuple) + realm.run([kadminl, 'ank', '-pw', 'password', 'test'], env=e) + out = realm.run([kadminl, 'getprinc', 'test']) + if not pat.search(out): + fail('Failed to set flag ' + ftuple.flagname() + ' via kdc.conf') + + realm.run([kadminl, 'delprinc', 'test']) + + +# Principal name for kadm5.acl line +def ftuple2pname(ftuple, doset): + pname = 'set_' if doset else 'clear_' + return pname + ftuple.flagname() + + +# Translate a strconv ftuple to a spec string for kadmin. +def ftuple2kadm_spec(ftuple, doset): + ktuple = kadmin_itable[ftuple.flag] + if ktuple.invert != ftuple.invert: + # Could do: + # doset = not doset + # but this shouldn't happen. + raise ValueError + return ktuple.spec(doset) + + +# Generate a line for kadm5.acl. +def acl_line(ftuple, doset): + pname = ftuple2pname(ftuple, doset) + spec = ftuple.spec(doset) + return "%s * %s %s\n" % (realm.admin_princ, pname, spec) + + +# Test one kadm5.acl line for a ftuple. +def one_aclcheck(ftuple, doset): + pname = ftuple2pname(ftuple, doset) + pat = attr_pat(ftuple) + outname = ftuple.flagname() + # Create the principal and check that the flag is correctly set or + # cleared. + realm.run_kadmin(['ank', '-pw', 'password', pname]) + out = realm.run([kadminl, 'getprinc', pname]) + if doset: + if not pat.search(out): + fail('Failed to set flag ' + outname + ' via kadm5.acl') + else: + if not emptyattr.search(out): + fail('Failed to clear flag ' + outname + ' via kadm5.acl') + # If acl forces flag to be set, try to clear it, and vice versa. + spec = ftuple2kadm_spec(ftuple, not doset) + realm.run_kadmin(['modprinc', spec, pname]) + out = realm.run([kadminl, 'getprinc', pname]) + if doset: + if not pat.search(out): + fail('Failed to keep flag ' + outname + ' set') + else: + if not emptyattr.search(out): + fail('Failed to keep flag ' + outname + ' clear') + + +# Set all flags simultaneously, even the ones that aren't defined yet. +def lamptest(): + pat = re.compile('^Attributes: ' + + ' '.join(flags2namelist(0xffffffff)) + + '$', re.MULTILINE) + realm.run([kadminl, 'ank', '-pw', 'password', '+0xffffffff', 'test']) + out = realm.run([kadminl, 'getprinc', 'test']) + if not pat.search(out): + fail('Failed to simultaenously set all flags') + realm.run([kadminl, 'delprinc', 'test']) + + +for ftuple in kadmin_ftuples: + one_kadmin_flag(ftuple) + +for ftuple in strconv_ftuples: + one_kdcconf(ftuple) + +f = open(os.path.join(realm.testdir, 'acl'), 'w') +for ftuple in strconv_ftuples: + f.write(acl_line(ftuple, True)) + f.write(acl_line(ftuple, False)) +f.close() + +realm.start_kadmind() +realm.prep_kadmin() + +for ftuple in strconv_ftuples: + one_aclcheck(ftuple, True) + one_aclcheck(ftuple, False) + +lamptest() + +success('KDB principal flags') diff --git a/krb5-1.21.3/src/tests/t_proxy.py b/krb5-1.21.3/src/tests/t_proxy.py new file mode 100755 index 00000000..cbd592a3 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_proxy.py @@ -0,0 +1,220 @@ +from k5test import * + +# Skip this test if we're missing proxy functionality or parts of the proxy. +if runenv.tls_impl == 'no': + skip_rest('HTTP proxy tests', 'TLS build support not enabled') +try: + import kdcproxy +except: + skip_rest('HTTP proxy tests', 'Python kdcproxy module not found') + +# Construct a krb5.conf fragment configuring the client to use a local proxy +# server. +proxycerts = os.path.join(srctop, 'tests', 'proxy-certs') +proxysubjectpem = os.path.join(proxycerts, 'proxy-subject.pem') +proxysanpem = os.path.join(proxycerts, 'proxy-san.pem') +proxyidealpem = os.path.join(proxycerts, 'proxy-ideal.pem') +proxywrongpem = os.path.join(proxycerts, 'proxy-no-match.pem') +proxybadpem = os.path.join(proxycerts, 'proxy-badsig.pem') +proxyca = os.path.join(proxycerts, 'ca.pem') +proxyurl = 'https://localhost:$port5/KdcProxy' +proxyurlupcase = 'https://LocalHost:$port5/KdcProxy' +proxyurl4 = 'https://127.0.0.1:$port5/KdcProxy' +proxyurl6 = 'https://[::1]:$port5/KdcProxy' + +unanchored_krb5_conf = {'realms': {'$realm': { + 'kdc': proxyurl, + 'kpasswd_server': proxyurl}}} +anchored_name_krb5_conf = {'realms': {'$realm': { + 'kdc': proxyurl, + 'kpasswd_server': proxyurl, + 'http_anchors': 'FILE:%s' % proxyca}}} +anchored_upcasename_krb5_conf = {'realms': {'$realm': { + 'kdc': proxyurlupcase, + 'kpasswd_server': proxyurlupcase, + 'http_anchors': 'FILE:%s' % proxyca}}} +anchored_kadmin_krb5_conf = {'realms': {'$realm': { + 'kdc': proxyurl, + 'admin_server': proxyurl, + 'http_anchors': 'FILE:%s' % proxyca}}} +anchored_ipv4_krb5_conf = {'realms': {'$realm': { + 'kdc': proxyurl4, + 'kpasswd_server': proxyurl4, + 'http_anchors': 'FILE:%s' % proxyca}}} +kpasswd_input = (password('user') + '\n' + password('user') + '\n' + + password('user') + '\n') + +def start_proxy(realm, keycertpem): + proxy_conf_path = os.path.join(realm.testdir, 'kdcproxy.conf') + proxy_exec_path = os.path.join(srctop, 'util', 'wsgiref-kdcproxy.py') + conf = open(proxy_conf_path, 'w') + conf.write('[%s]\n' % realm.realm) + conf.write('kerberos = kerberos://localhost:%d\n' % realm.portbase) + conf.write('kpasswd = kpasswd://localhost:%d\n' % (realm.portbase + 2)) + conf.close() + realm.env['KDCPROXY_CONFIG'] = proxy_conf_path + cmd = [sys.executable, proxy_exec_path, str(realm.server_port()), + keycertpem] + return realm.start_server(cmd, sentinel='proxy server ready') + +# Fail: untrusted issuer and hostname doesn't match. +mark('untrusted issuer, hostname mismatch') +output("running pass 1: issuer not trusted and hostname doesn't match\n") +realm = K5Realm(krb5_conf=unanchored_krb5_conf, get_creds=False, + create_host=False) +proxy = start_proxy(realm, proxywrongpem) +realm.kinit(realm.user_princ, password=password('user'), expected_code=1) +stop_daemon(proxy) +realm.stop() + +# Fail: untrusted issuer, host name matches subject. +mark('untrusted issuer, hostname subject match') +output("running pass 2: subject matches, issuer not trusted\n") +realm = K5Realm(krb5_conf=unanchored_krb5_conf, get_creds=False, + create_host=False) +proxy = start_proxy(realm, proxysubjectpem) +realm.kinit(realm.user_princ, password=password('user'), expected_code=1) +stop_daemon(proxy) +realm.stop() + +# Fail: untrusted issuer, host name matches subjectAltName. +mark('untrusted issuer, hostname SAN match') +output("running pass 3: subjectAltName matches, issuer not trusted\n") +realm = K5Realm(krb5_conf=unanchored_krb5_conf, get_creds=False, + create_host=False) +proxy = start_proxy(realm, proxysanpem) +realm.kinit(realm.user_princ, password=password('user'), expected_code=1) +stop_daemon(proxy) +realm.stop() + +# Fail: untrusted issuer, certificate signature is bad. +mark('untrusted issuer, bad signature') +output("running pass 4: subject matches, issuer not trusted\n") +realm = K5Realm(krb5_conf=unanchored_krb5_conf, get_creds=False, + create_host=False) +proxy = start_proxy(realm, proxybadpem) +realm.kinit(realm.user_princ, password=password('user'), expected_code=1) +stop_daemon(proxy) +realm.stop() + +# Fail: trusted issuer but hostname doesn't match. +mark('trusted issuer, hostname mismatch') +output("running pass 5: issuer trusted but hostname doesn't match\n") +realm = K5Realm(krb5_conf=anchored_name_krb5_conf, get_creds=False, + create_host=False) +proxy = start_proxy(realm, proxywrongpem) +realm.kinit(realm.user_princ, password=password('user'), expected_code=1) +stop_daemon(proxy) +realm.stop() + +# Succeed: trusted issuer and host name matches subject. +mark('trusted issuer, hostname subject match') +output("running pass 6: issuer trusted, subject matches\n") +realm = K5Realm(krb5_conf=anchored_name_krb5_conf, start_kadmind=True, + get_creds=False) +proxy = start_proxy(realm, proxysubjectpem) +realm.kinit(realm.user_princ, password=password('user')) +realm.run([kvno, realm.host_princ]) +realm.run([kpasswd, realm.user_princ], input=kpasswd_input) +stop_daemon(proxy) +realm.stop() + +# Succeed: trusted issuer and host name matches subjectAltName. +mark('trusted issuer, hostname SAN match') +output("running pass 7: issuer trusted, subjectAltName matches\n") +realm = K5Realm(krb5_conf=anchored_name_krb5_conf, start_kadmind=True, + get_creds=False) +proxy = start_proxy(realm, proxysanpem) +realm.kinit(realm.user_princ, password=password('user')) +realm.run([kvno, realm.host_princ]) +realm.run([kpasswd, realm.user_princ], input=kpasswd_input) +stop_daemon(proxy) +realm.stop() + +# Fail: certificate signature is bad. +mark('bad signature') +output("running pass 8: issuer trusted and subjectAltName matches, sig bad\n") +realm = K5Realm(krb5_conf=anchored_name_krb5_conf, + get_creds=False, + create_host=False) +proxy = start_proxy(realm, proxybadpem) +realm.kinit(realm.user_princ, password=password('user'), expected_code=1) +stop_daemon(proxy) +realm.stop() + +# Fail: trusted issuer but IP doesn't match. +mark('trusted issuer, IP mismatch') +output("running pass 9: issuer trusted but no name matches IP\n") +realm = K5Realm(krb5_conf=anchored_ipv4_krb5_conf, get_creds=False, + create_host=False) +proxy = start_proxy(realm, proxywrongpem) +realm.kinit(realm.user_princ, password=password('user'), expected_code=1) +stop_daemon(proxy) +realm.stop() + +# Fail: trusted issuer, but subject does not match. +mark('trusted issuer, IP mismatch (hostname in subject)') +output("running pass 10: issuer trusted, but subject does not match IP\n") +realm = K5Realm(krb5_conf=anchored_ipv4_krb5_conf, get_creds=False, + create_host=False) +proxy = start_proxy(realm, proxysubjectpem) +realm.kinit(realm.user_princ, password=password('user'), expected_code=1) +stop_daemon(proxy) +realm.stop() + +# Succeed: trusted issuer and host name matches subjectAltName. +mark('trusted issuer, IP SAN match') +output("running pass 11: issuer trusted, subjectAltName matches IP\n") +realm = K5Realm(krb5_conf=anchored_ipv4_krb5_conf, start_kadmind=True, + get_creds=False) +proxy = start_proxy(realm, proxysanpem) +realm.kinit(realm.user_princ, password=password('user')) +realm.run([kvno, realm.host_princ]) +realm.run([kpasswd, realm.user_princ], input=kpasswd_input) +stop_daemon(proxy) +realm.stop() + +# Fail: certificate signature is bad. +mark('bad signature (IP hostname)') +output("running pass 12: issuer trusted, names don't match, signature bad\n") +realm = K5Realm(krb5_conf=anchored_ipv4_krb5_conf, get_creds=False, + create_host=False) +proxy = start_proxy(realm, proxybadpem) +realm.kinit(realm.user_princ, password=password('user'), expected_code=1) +stop_daemon(proxy) +realm.stop() + +# Succeed: trusted issuer and host name matches subject, using kadmin +# configuration to find kpasswdd. +mark('trusted issuer, hostname subject match (kadmin)') +output("running pass 13: issuer trusted, subject matches\n") +realm = K5Realm(krb5_conf=anchored_kadmin_krb5_conf, start_kadmind=True, + get_creds=False, create_host=False) +proxy = start_proxy(realm, proxysubjectpem) +realm.run([kpasswd, realm.user_princ], input=kpasswd_input) +stop_daemon(proxy) +realm.stop() + +# Succeed: trusted issuer and host name matches subjectAltName, using +# kadmin configuration to find kpasswdd. +mark('trusted issuer, hostname SAN match (kadmin)') +output("running pass 14: issuer trusted, subjectAltName matches\n") +realm = K5Realm(krb5_conf=anchored_kadmin_krb5_conf, start_kadmind=True, + get_creds=False, create_host=False) +proxy = start_proxy(realm, proxysanpem) +realm.run([kpasswd, realm.user_princ], input=kpasswd_input) +stop_daemon(proxy) +realm.stop() + +# Succeed: trusted issuer and host name matches subjectAltName (give or take +# case). +mark('trusted issuer, hostname SAN case-insensitive match') +output("running pass 15: issuer trusted, subjectAltName case-insensitive\n") +realm = K5Realm(krb5_conf=anchored_upcasename_krb5_conf, start_kadmind=True, + get_creds=False, create_host=False) +proxy = start_proxy(realm, proxysanpem) +realm.run([kpasswd, realm.user_princ], input=kpasswd_input) +stop_daemon(proxy) +realm.stop() + +success('MS-KKDCP proxy') diff --git a/krb5-1.21.3/src/tests/t_pwqual.py b/krb5-1.21.3/src/tests/t_pwqual.py new file mode 100755 index 00000000..58d610d8 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_pwqual.py @@ -0,0 +1,78 @@ +from k5test import * + +plugin = os.path.join(buildtop, "plugins", "pwqual", "test", "pwqual_test.so") + +dictfile = os.path.join(os.getcwd(), 'testdir', 'dict') + +pconf = {'plugins': {'pwqual': {'module': 'combo:' + plugin}}} +dconf = {'realms': {'$realm': {'dict_file': dictfile}}} +realm = K5Realm(krb5_conf=pconf, kdc_conf=dconf, create_user=False, + create_host=False) + +# Write a short dictionary file. +f = open(dictfile, 'w') +f.write('birds\nbees\napples\noranges\n') +f.close() + +realm.run([kadminl, 'addpol', 'pol']) + +mark('pwqual modules') + +# The built-in "empty" module rejects empty passwords even without a policy. +realm.run([kadminl, 'addprinc', '-pw', '', 'p1'], expected_code=1, + expected_msg='Empty passwords are not allowed') + +# The built-in "dict" module rejects dictionary words, but only with a policy. +realm.run([kadminl, 'addprinc', '-pw', 'birds', 'p2']) +realm.run([kadminl, 'addprinc', '-pw', 'birds', '-policy', 'pol', 'p3'], + expected_code=1, + expected_msg='Password is in the password dictionary') + +# The built-in "princ" module rejects principal components, only with a policy. +realm.run([kadminl, 'addprinc', '-pw', 'p4', 'p4']) +realm.run([kadminl, 'addprinc', '-pw', 'p5', '-policy', 'pol', 'p5'], + expected_code=1, + expected_msg='Password may not match principal name') + +# The dynamic "combo" module rejects pairs of dictionary words. +realm.run([kadminl, 'addprinc', '-pw', 'birdsoranges', 'p6'], expected_code=1, + expected_msg='Password may not be a pair of dictionary words') + +# These plugin ordering tests aren't specifically related to the +# password quality interface, but are convenient to put here. + +mark('plugin module order') + +def test_order(realm, testname, conf, expected): + conf = {'plugins': {'pwqual': conf}} + env = realm.special_env(testname, False, krb5_conf=conf) + out = realm.run(['./plugorder'], env=env) + if out.split() != expected: + fail('order test: ' + testname) + +realm.stop() +realm = K5Realm(create_kdb=False) + +# Check the test harness with no special configuration. +test_order(realm, 'noconf', {}, ['blt1', 'blt2', 'blt3']) + +# Test the basic order: dynamic modules, then built-in modules, each +# in registration order. +conf = {'module': ['dyn3:' + plugin, 'dyn1:' + plugin, 'dyn2:' + plugin]} +test_order(realm, 'basic', conf, + ['dyn3', 'dyn1', 'dyn2', 'blt1', 'blt2', 'blt3']) + +# Disabling modules should not affect the order of other modules. +conf['disable'] = ['dyn1', 'blt3'] +test_order(realm, 'disable', conf, ['dyn3', 'dyn2', 'blt1', 'blt2']) + +# enable_only should reorder the modules, but can't resurrect disabled +# modules or create ones from thin air. +conf['enable_only'] = ['dyn2', 'blt3', 'blt2', 'dyn1', 'dyn3', 'xxx'] +test_order(realm, 'enable_only', conf, ['dyn2', 'blt2', 'dyn3']) + +# Duplicate modules should be pruned by preferring earlier entries. +conf = {'module': ['dyn3:' + plugin, 'dyn1:' + plugin, 'dyn3:' + plugin]} +test_order(realm, 'duplicate', conf, ['dyn3', 'dyn1', 'blt1', 'blt2', 'blt3']) + +success('Password quality interface tests') diff --git a/krb5-1.21.3/src/tests/t_rdreq.py b/krb5-1.21.3/src/tests/t_rdreq.py new file mode 100755 index 00000000..7b120b1d --- /dev/null +++ b/krb5-1.21.3/src/tests/t_rdreq.py @@ -0,0 +1,138 @@ +from k5test import * + +conf = {'realms': {'$realm': {'supported_enctypes': 'aes256-cts aes128-cts'}}} +realm = K5Realm(create_host=False, kdc_conf=conf) + +# Define some server principal names. +princ1 = 'host/1@%s' % realm.realm +princ2 = 'host/2@%s' % realm.realm +princ3 = 'HTTP/3@%s' % realm.realm +princ4 = 'HTTP/4@%s' % realm.realm +matchprinc = 'host/@' +nomatchprinc = 'x/@' +realm.addprinc(princ1) +realm.addprinc(princ2) +realm.addprinc(princ3) + +def test(tserver, server, expected): + args = ['./rdreq', tserver] + if server is not None: + args += [server] + out = realm.run(args) + if out.strip() != expected: + fail('unexpected rdreq output') + + +# No keytab present. +mark('no keytab') +nokeytab_err = "45 Key table file '%s' not found" % realm.keytab +test(princ1, None, nokeytab_err) +test(princ1, princ1, nokeytab_err) +test(princ1, matchprinc, nokeytab_err) + +# Keytab present, successful decryption. +mark('success') +realm.extract_keytab(princ1, realm.keytab) +test(princ1, None, '0 success') +test(princ1, princ1, '0 success') +test(princ1, matchprinc, '0 success') + +# Explicit server principal not found in keytab. +mark('explicit server not found') +test(princ2, princ2, '45 No key table entry found for host/2@KRBTEST.COM') + +# Matching server principal does not match any entries in keytab (with +# and without ticket server present in keytab). +mark('matching server') +nomatch_err = '45 Server principal x/@ does not match any keys in keytab' +test(princ1, nomatchprinc, nomatch_err) +test(princ2, nomatchprinc, nomatch_err) + +# Ticket server does not match explicit server principal (with and +# without ticket server present in keytab). +mark('ticket server mismatch') +test(princ1, princ2, '45 No key table entry found for host/2@KRBTEST.COM') +test(princ2, princ1, + '35 Cannot decrypt ticket for host/2@KRBTEST.COM using keytab key for ' + 'host/1@KRBTEST.COM') + +# Ticket server not found in keytab during iteration. +mark('ticket server not found') +test(princ2, None, + '35 Request ticket server host/2@KRBTEST.COM not found in keytab ' + '(ticket kvno 1)') + +# Ticket server found in keytab but is not matched by server principal +# (but other principals in keytab do match). +mark('ticket server mismatch (matching)') +realm.extract_keytab(princ3, realm.keytab) +test(princ3, matchprinc, + '35 Request ticket server HTTP/3@KRBTEST.COM found in keytab but does ' + 'not match server principal host/@') + +# Service ticket is out of date. +mark('outdated service ticket') +os.remove(realm.keytab) +realm.run([kadminl, 'ktadd', princ1]) +test(princ1, None, + '44 Request ticket server host/1@KRBTEST.COM kvno 1 not found in keytab; ' + 'ticket is likely out of date') +test(princ1, princ1, + '44 Cannot find key for host/1@KRBTEST.COM kvno 1 in keytab') + +# kvno mismatch due to ticket principal mismatch with explicit server. +mark('ticket server mismatch (kvno)') +test(princ2, princ1, + '35 Cannot find key for host/1@KRBTEST.COM kvno 1 in keytab (request ' + 'ticket server host/2@KRBTEST.COM)') + +# Keytab is out of date. +mark('outdated keytab') +realm.run([kadminl, 'cpw', '-randkey', princ1]) +realm.kinit(realm.user_princ, password('user')) +test(princ1, None, + '44 Request ticket server host/1@KRBTEST.COM kvno 3 not found in keytab; ' + 'keytab is likely out of date') +test(princ1, princ1, + '44 Cannot find key for host/1@KRBTEST.COM kvno 3 in keytab') + +# Ticket server and kvno found but not with ticket enctype. +mark('missing enctype') +os.remove(realm.keytab) +realm.extract_keytab(princ1, realm.keytab) +pkeytab = realm.keytab + '.partial' +realm.run([ktutil], input=('rkt %s\ndelent 1\nwkt %s\n' % + (realm.keytab, pkeytab))) +os.rename(pkeytab, realm.keytab) +realm.run([klist, '-ke']) +test(princ1, None, + '44 Request ticket server host/1@KRBTEST.COM kvno 3 found in keytab but ' + 'not with enctype aes256-cts') +# This is a bad code (KRB_AP_ERR_NOKEY) and message, because +# krb5_kt_get_entry returns the same result for this and not finding +# the principal at all. But it's an uncommon case; GSSAPI apps +# usually use a matching principal and missing key enctypes are rare. +test(princ1, princ1, '45 No key table entry found for host/1@KRBTEST.COM') + +# Ticket server, kvno, and enctype matched, but key does not work. +mark('wrong key') +realm.run([kadminl, 'cpw', '-randkey', princ1]) +realm.run([kadminl, 'modprinc', '-kvno', '3', princ1]) +os.remove(realm.keytab) +realm.extract_keytab(princ1, realm.keytab) +test(princ1, None, + '31 Request ticket server host/1@KRBTEST.COM kvno 3 enctype aes256-cts ' + 'found in keytab but cannot decrypt ticket') +test(princ1, princ1, + '31 Cannot decrypt ticket for host/1@KRBTEST.COM using keytab key for ' + 'host/1@KRBTEST.COM') + +# Test that aliases work. The ticket server (princ4) isn't present in +# keytab, but there is a usable princ1 entry with the same key. +mark('aliases') +realm.run([kadminl, 'renprinc', princ1, princ4]) +test(princ4, None, '0 success') +test(princ4, princ1, '0 success') +test(princ4, matchprinc, '0 success') + +success('krb5_rd_req tests') diff --git a/krb5-1.21.3/src/tests/t_referral.py b/krb5-1.21.3/src/tests/t_referral.py new file mode 100755 index 00000000..f427d5b6 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_referral.py @@ -0,0 +1,142 @@ +from k5test import * + +# Create a pair of realms, where KRBTEST1.COM can authenticate to +# REFREALM and has a domain-realm mapping for 'd' pointing to it. +drealm = {'domain_realm': {'d': 'REFREALM'}} +realm, refrealm = cross_realms(2, xtgts=((0,1),), + args=({'kdc_conf': drealm}, + {'realm': 'REFREALM', + 'create_user': False}), + create_host=False) +refrealm.addprinc('a/x.d') + +savefile = os.path.join(realm.testdir, 'ccache.copy') +os.rename(realm.ccache, savefile) + +# Get credentials and check that we got a referral to REFREALM. +def testref(realm, nametype): + shutil.copyfile(savefile, realm.ccache) + realm.run(['./gcred', nametype, 'a/x.d@']) + out = realm.run([klist]).split('\n') + if len(out) != 8: + fail('unexpected number of lines in klist output') + if out[5].split()[4] != 'a/x.d@' or out[6].split()[2] != 'a/x.d@REFREALM': + fail('unexpected service principals in klist output') + +# Get credentials and check that we get an error, not a referral. +def testfail(realm, nametype): + shutil.copyfile(savefile, realm.ccache) + realm.run(['./gcred', nametype, 'a/x.d@'], expected_code=1, + expected_msg='not found in Kerberos database') + +# Create a modified KDC environment and restart the KDC. +def restart_kdc(realm, kdc_conf): + env = realm.special_env('extravars', True, kdc_conf=kdc_conf) + realm.stop_kdc() + realm.start_kdc(env=env) + +# With no KDC configuration besides [domain_realm], we should get a +# referral for a NT-SRV-HST or NT-SRV-INST server name, but not an +# NT-UNKNOWN or NT-PRINCIPAL server name. +mark('[domain-realm] only') +testref(realm, 'srv-hst') +testref(realm, 'srv-inst') +testfail(realm, 'principal') +testfail(realm, 'unknown') + +# With host_based_services matching the first server name component +# ("a"), we should get a referral for an NT-UNKNOWN server name. +# host_based_services can appear in either [kdcdefaults] or the realm +# section, with the realm values supplementing the kdcdefaults values. +# NT-SRV-HST server names should be unaffected by host_based_services, +# and NT-PRINCIPAL server names shouldn't get a referral regardless. +mark('host_based_services') +restart_kdc(realm, {'kdcdefaults': {'host_based_services': '*'}}) +testref(realm, 'unknown') +testfail(realm, 'principal') +restart_kdc(realm, {'kdcdefaults': {'host_based_services': ['b', 'a,c']}}) +testref(realm, 'unknown') +restart_kdc(realm, {'realms': {'$realm': {'host_based_services': 'a b c'}}}) +testref(realm, 'unknown') +restart_kdc(realm, {'kdcdefaults': {'host_based_services': 'a'}, + 'realms': {'$realm': {'host_based_services': 'b c'}}}) +testref(realm, 'unknown') +restart_kdc(realm, {'kdcdefaults': {'host_based_services': 'b,c'}, + 'realms': {'$realm': {'host_based_services': 'a,b'}}}) +testref(realm, 'unknown') +restart_kdc(realm, {'kdcdefaults': {'host_based_services': 'b,c'}}) +testfail(realm, 'unknown') +testref(realm, 'srv-hst') + +# With no_host_referrals matching the first server name component, we +# should not get a referral even for NT-SRV-HOST server names +mark('no_host_referral') +restart_kdc(realm, {'kdcdefaults': {'no_host_referral': '*'}}) +testfail(realm, 'srv-hst') +restart_kdc(realm, {'kdcdefaults': {'no_host_referral': ['b', 'a,c']}}) +testfail(realm, 'srv-hst') +restart_kdc(realm, {'realms': {'$realm': {'no_host_referral': 'a b c'}}}) +testfail(realm, 'srv-hst') +restart_kdc(realm, {'kdcdefaults': {'no_host_referral': 'a'}, + 'realms': {'$realm': {'no_host_referral': 'b c'}}}) +testfail(realm, 'srv-hst') +restart_kdc(realm, {'kdcdefaults': {'no_host_referral': 'b,c'}, + 'realms': {'$realm': {'no_host_referral': 'a,b'}}}) +testfail(realm, 'srv-hst') +restart_kdc(realm, {'kdcdefaults': {'no_host_referral': 'b,c'}}) +testref(realm, 'srv-hst') + +# no_host_referrals should override host_based_services for NT-UNKNWON +# server names. +restart_kdc(realm, {'kdcdefaults': {'no_host_referral': '*', + 'host_based_services': '*'}}) +testfail(realm, 'unknown') + +realm.stop() +refrealm.stop() + +# Regression test for #7483: a KDC should not return a host referral +# to its own realm. +mark('#7483 regression test') +drealm = {'domain_realm': {'d': 'KRBTEST.COM'}} +realm = K5Realm(kdc_conf=drealm, create_host=False) +out, trace = realm.run(['./gcred', 'srv-hst', 'a/x.d@'], expected_code=1, + return_trace=True) +if 'back to same realm' in trace: + fail('KDC returned referral to service realm') +realm.stop() + +# Test client referrals. Use the test KDB module for KRBTEST1.COM to +# simulate referrals since our built-in modules do not support them. +# No cross-realm TGTs are necessary. +mark('client referrals') +kdcconf = {'realms': {'$realm': {'database_module': 'test'}}, + 'dbmodules': {'test': {'db_library': 'test', + 'alias': {'user': '@KRBTEST2.COM', + 'abc@XYZ': '@KRBTEST2.COM'}}}} +r1, r2 = cross_realms(2, xtgts=(), + args=({'kdc_conf': kdcconf, 'create_kdb': False}, None), + create_host=False) +r2.addprinc('abc\\@XYZ', 'pw') +r1.start_kdc() +r1.kinit('user', expected_code=1, + expected_msg='not found in Kerberos database') +r1.kinit('user', password('user'), ['-C']) +r1.klist('user@KRBTEST2.COM', 'krbtgt/KRBTEST2.COM') +r1.kinit('abc@XYZ', 'pw', ['-E']) +r1.klist('abc\\@XYZ@KRBTEST2.COM', 'krbtgt/KRBTEST2.COM') + +# Test that disable_encrypted_timestamp persists across client +# referrals. (This test relies on SPAKE not being enabled by default +# on the KDC.) +r2.run([kadminl, 'modprinc', '+preauth', 'user']) +msgs = ('Encrypted timestamp (for ') +r1.kinit('user', password('user'), ['-C'], expected_trace=msgs) +dconf = {'realms': {'$realm': {'disable_encrypted_timestamp': 'true'}}} +denv = r1.special_env('disable_encts', False, krb5_conf=dconf) +msgs = ('Ignoring encrypted timestamp because it is disabled', + '/Encrypted timestamp is disabled') +r1.kinit('user', None, ['-C'], env=denv, expected_code=1, expected_trace=msgs, + expected_msg='Encrypted timestamp is disabled') + +success('KDC host referral tests') diff --git a/krb5-1.21.3/src/tests/t_renew.py b/krb5-1.21.3/src/tests/t_renew.py new file mode 100755 index 00000000..9f22bab8 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_renew.py @@ -0,0 +1,122 @@ +from k5test import * +from datetime import datetime +import re + +conf = {'realms': {'$realm': {'max_life': '20h', 'max_renewable_life': '20h'}}} +realm = K5Realm(create_host=False, get_creds=False, kdc_conf=conf) + +# We will be scraping timestamps from klist to compute lifetimes, so +# use a time zone with no daylight savings time. +realm.env['TZ'] = 'UTC' + +def test(testname, life, rlife, exp_life, exp_rlife, env=None): + global realm + flags = ['-l', life] + if rlife is not None: + flags += ['-r', rlife] + realm.kinit(realm.user_princ, password('user'), flags=flags, env=env) + out = realm.run([klist, '-f']) + + if ('Default principal: %s\n' % realm.user_princ) not in out: + fail('%s: did not get tickets' % testname) + + # Extract flags and check the renewable flag against expectations. + flags = re.findall(r'Flags: ([a-zA-Z]*)', out)[0] + if exp_rlife is None and 'R' in flags: + fail('%s: ticket unexpectedly renewable' % testname) + if exp_rlife is not None and 'R' not in flags: + fail('%s: ticket unexpectedly non-renewable' % testname) + + # Extract the start time, end time, and renewable end time if present. + times = re.findall(r'\d\d/\d\d/\d\d \d\d:\d\d:\d\d', out) + times = [datetime.strptime(t, '%m/%d/%y %H:%M:%S') for t in times] + starttime = times[0] + endtime = times[1] + rtime = times[2] if len(times) >= 3 else None + + # Check the ticket lifetime against expectations. If the lifetime + # was determined by the request, there may be a small error + # because KDC requests contain an end time rather than a lifetime. + life = (endtime - starttime).seconds + if abs(life - exp_life) > 5: + fail('%s: expected life %d, got %d' % (testname, exp_life, life)) + + # Check the ticket renewable lifetime against expectations. + if exp_rlife is None and rtime is not None: + fail('%s: ticket has unexpected renew_till' % testname) + if exp_rlife is not None and rtime is None: + fail('%s: ticket is renewable but has no renew_till' % testname) + if rtime is not None: + rlife = (rtime - starttime).seconds + if abs(rlife - exp_rlife) > 5: + fail('%s: expected rlife %d, got %d' % + (testname, exp_rlife, rlife)) + +# Get renewable tickets. +test('simple', '1h', '2h', 3600, 7200) + +# Renew twice, to test that renewed tickets are renewable. +mark('renew twice') +realm.kinit(realm.user_princ, flags=['-R']) +realm.kinit(realm.user_princ, flags=['-R']) +realm.klist(realm.user_princ) + +# Make sure we can use a renewed ticket. +realm.run([kvno, realm.user_princ]) + +# Make sure we can't renew non-renewable tickets. +mark('non-renewable') +test('non-renewable', '1h', None, 3600, None) +realm.kinit(realm.user_princ, flags=['-R'], expected_code=1, + expected_msg="KDC can't fulfill requested option") + +# Test that -allow_renewable on the client principal works. +mark('allow_renewable (client)') +realm.run([kadminl, 'modprinc', '-allow_renewable', 'user']) +test('disallowed client', '1h', '2h', 3600, None) +realm.run([kadminl, 'modprinc', '+allow_renewable', 'user']) + +# Test that -allow_renewable on the server principal works. +mark('allow_renewable (server)') +realm.run([kadminl, 'modprinc', '-allow_renewable', realm.krbtgt_princ]) +test('disallowed server', '1h', '2h', 3600, None) +realm.run([kadminl, 'modprinc', '+allow_renewable', realm.krbtgt_princ]) + +# Test that trivially renewable tickets are issued if renew_till <= +# till. (Our client code bumps up the requested renewable life to the +# requested life.) +mark('trivially renewable') +test('short', '2h', '1h', 7200, 7200) + +# Test that renewable tickets are issued if till > max life by +# default, but not if we configure away the RENEWABLE-OK option. +mark('renewable-ok') +no_opts_conf = {'libdefaults': {'kdc_default_options': '0'}} +no_opts = realm.special_env('no_opts', False, krb5_conf=no_opts_conf) +realm.run([kadminl, 'modprinc', '-maxlife', '10 hours', 'user']) +test('long', '15h', None, 10 * 3600, 15 * 3600) +test('long noopts', '15h', None, 10 * 3600, None, env=no_opts) +realm.run([kadminl, 'modprinc', '-maxlife', '20 hours', 'user']) + +# Test maximum renewable life on the client principal. +mark('maxrenewlife (client)') +realm.run([kadminl, 'modprinc', '-maxrenewlife', '5 hours', 'user']) +test('maxrenewlife client 1', '4h', '5h', 4 * 3600, 5 * 3600) +test('maxrenewlife client 2', '6h', '10h', 6 * 3600, 5 * 3600) + +# Test maximum renewable life on the server principal. +mark('maxrenewlife (server)') +realm.run([kadminl, 'modprinc', '-maxrenewlife', '3 hours', + realm.krbtgt_princ]) +test('maxrenewlife server 1', '2h', '3h', 2 * 3600, 3 * 3600) +test('maxrenewlife server 2', '4h', '8h', 4 * 3600, 3 * 3600) + +# Test realm maximum life. +mark('realm maximum life') +realm.run([kadminl, 'modprinc', '-maxrenewlife', '40 hours', 'user']) +realm.run([kadminl, 'modprinc', '-maxrenewlife', '40 hours', + realm.krbtgt_princ]) +test('maxrenewlife realm 1', '10h', '20h', 10 * 3600, 20 * 3600) +test('maxrenewlife realm 2', '21h', '40h', 20 * 3600, 20 * 3600) + +success('Renewing credentials') diff --git a/krb5-1.21.3/src/tests/t_renprinc.py b/krb5-1.21.3/src/tests/t_renprinc.py new file mode 100755 index 00000000..3dbb3e77 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_renprinc.py @@ -0,0 +1,45 @@ +# Copyright (C) 2011 by the Massachusetts Institute of Technology. +# All rights reserved. + +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +from k5test import * + +enctype = "aes128-cts" + +realm = K5Realm(create_host=False, create_user=False) +salttypes = ('normal', 'norealm', 'onlyrealm') + +# For a variety of salt types, test that we can rename a principal and +# still get tickets with the same password. +for st in salttypes: + realm.run([kadminl, 'addprinc', '-e', enctype + ':' + st, + '-pw', password(st), st]) + realm.kinit(st, password(st)) + newprinc = 'new' + st + realm.run([kadminl, 'renprinc', st, newprinc]) + realm.kinit(newprinc, password(st)) + +# Rename the normal salt again to test renaming a principal with +# special salt type (which it will have after the first rename). +realm.run([kadminl, 'renprinc', 'newnormal', 'newnormal2']) +realm.kinit('newnormal2', password('normal')) + +success('Principal renaming tests') diff --git a/krb5-1.21.3/src/tests/t_replay.py b/krb5-1.21.3/src/tests/t_replay.py new file mode 100644 index 00000000..6ad58fe1 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_replay.py @@ -0,0 +1,6 @@ +from k5test import * + +realm = K5Realm() +realm.run(['./replay', realm.host_princ]) + +success('Replay tests') diff --git a/krb5-1.21.3/src/tests/t_salt.py b/krb5-1.21.3/src/tests/t_salt.py new file mode 100755 index 00000000..65084bbf --- /dev/null +++ b/krb5-1.21.3/src/tests/t_salt.py @@ -0,0 +1,55 @@ +from k5test import * +import re + +realm = K5Realm(create_user=False) + +# Check that a non-default salt type applies only to the key it is +# matched with and not to subsequent keys. e1 and e2 are enctypes, +# and salt is a non-default salt type. +def test_salt(realm, e1, salt, e2): + keysalts = e1 + ':' + salt + ',' + e2 + realm.run([kadminl, 'ank', '-e', keysalts, '-pw', 'password', 'user']) + out = realm.run([kadminl, 'getprinc', 'user']) + if len(re.findall(':' + salt, out)) != 1: + fail(salt + ' present in second enctype or not present') + realm.run([kadminl, 'delprinc', 'user']) + +# Enctype/salt pairs chosen with non-default salt types. +# The enctypes are mostly arbitrary. +salts = [('des3-cbc-sha1', 'norealm'), + ('arcfour-hmac', 'onlyrealm'), + ('aes128-cts-hmac-sha1-96', 'special')] +# These enctypes are chosen to cover the different string-to-key routines. +# Omit ":normal" from aes256 to check that salttype defaulting works. +second_kstypes = ['aes256-cts-hmac-sha1-96', 'arcfour-hmac:normal', + 'des3-cbc-sha1:normal'] + +# Test using different salt types in a principal's key list. +# Parameters from one key in the list must not leak over to later ones. +for e1, string in salts: + for e2 in second_kstypes: + test_salt(realm, e1, string, e2) + +def test_dup(realm, ks): + realm.run([kadminl, 'ank', '-e', ks, '-pw', 'password', 'ks_princ']) + out = realm.run([kadminl, 'getprinc', 'ks_princ']) + lines = out.split('\n') + keys = [l for l in lines if 'Key: ' in l] + uniq = set(keys) + # 'Key:' matches 'MKey:' as well so len(keys) has one extra + if (len(uniq) != len(keys)) or len(keys) > len(ks.split(',')): + fail('Duplicate keysalt detection failed for keysalt ' + ks) + realm.run([kadminl, 'delprinc', 'ks_princ']) + +# All in-tree callers request duplicate suppression from +# krb5_string_to_keysalts(); we should check that it works, respects +# aliases, and doesn't result in an infinite loop. +dup_kstypes = ['arcfour-hmac-md5:normal,rc4-hmac:normal', + 'aes256-cts-hmac-sha1-96:normal,aes128-cts,aes256-cts', + 'aes256-cts-hmac-sha1-96:normal,aes256-cts:special,' + + 'aes256-cts-hmac-sha1-96:normal'] + +for ks in dup_kstypes: + test_dup(realm, ks) + +success("Salt types") diff --git a/krb5-1.21.3/src/tests/t_sesskeynego.py b/krb5-1.21.3/src/tests/t_sesskeynego.py new file mode 100755 index 00000000..5a213617 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_sesskeynego.py @@ -0,0 +1,94 @@ +from k5test import * +import re + +# Run "kvno server" with a fresh set of client tickets, then check that the +# enctypes in the service ticket match the expected values. +etypes_re = re.compile(r'server@[^\n]+\n\tEtype \(skey, tkt\): ' + r'([^,]+), ([^\s]+)') +def test_kvno(realm, expected_skey, expected_tkt): + realm.kinit(realm.user_princ, password('user')) + realm.run([kvno, 'server']) + output = realm.run([klist, '-e']) + m = etypes_re.search(output) + if not m: + fail('could not parse etypes from klist -e output') + skey, tkt = m.groups() + if skey != expected_skey: + fail('got session key type %s, expected %s' % (skey, expected_skey)) + if tkt != expected_tkt: + fail('got ticket key type %s, expected %s' % (tkt, expected_tkt)) + +conf1 = {'libdefaults': {'default_tgs_enctypes': 'aes128-cts,aes256-cts'}} +conf2 = {'libdefaults': {'default_tgs_enctypes': 'aes256-cts,aes128-cts'}} +conf3 = {'libdefaults': { + 'allow_weak_crypto': 'true', + 'default_tkt_enctypes': 'aes128-cts', + 'default_tgs_enctypes': 'rc4-hmac,aes128-cts'}} +conf4 = {'libdefaults': {'permitted_enctypes': 'aes256-cts'}} +conf5 = {'libdefaults': {'allow_rc4': 'true'}} +conf6 = {'libdefaults': {'allow_des3': 'true'}} +# Test with client request and session_enctypes preferring aes128, but +# aes256 long-term key. +realm = K5Realm(krb5_conf=conf1, create_host=False, get_creds=False) +realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server']) +realm.run([kadminl, 'setstr', 'server', 'session_enctypes', + 'aes128-cts,aes256-cts']) +test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96') +realm.stop() + +# Second go, almost same as first, but resulting session key must be aes256 +# because of the difference in default_tgs_enctypes order. This tests that +# session_enctypes doesn't change the order in which we negotiate. +realm = K5Realm(krb5_conf=conf2, create_host=False, get_creds=False) +realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server']) +realm.run([kadminl, 'setstr', 'server', 'session_enctypes', + 'aes128-cts,aes256-cts']) +test_kvno(realm, 'aes256-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96') +realm.stop() + +# Next we use conf3 and try various things. +realm = K5Realm(krb5_conf=conf3, create_host=False, get_creds=False) +realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts:normal', + 'server']) + +# 3a: Negotiate aes128 session key when principal only has aes256 long-term. +realm.run([kadminl, 'setstr', 'server', 'session_enctypes', + 'aes128-cts,aes256-cts']) +test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96') + +# 3b: Skip RC4 (as the KDC does not allow it for session keys by +# default) and negotiate aes128-cts session key, with only an aes256 +# long-term service key. +realm.run([kadminl, 'setstr', 'server', 'session_enctypes', + 'rc4-hmac,aes128-cts,aes256-cts']) +test_kvno(realm, 'aes128-cts-hmac-sha1-96', 'aes256-cts-hmac-sha1-96') +realm.stop() + +# 4: Check that permitted_enctypes is a default for session key enctypes. +realm = K5Realm(krb5_conf=conf4, create_host=False, get_creds=False) +realm.kinit(realm.user_princ, password('user')) +realm.run([kvno, 'user'], + expected_trace=('etypes requested in TGS request: aes256-cts',)) +realm.stop() + +# 5: allow_rc4 permits negotiation of rc4-hmac session key. +realm = K5Realm(krb5_conf=conf5, create_host=False, get_creds=False) +realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server']) +realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'rc4-hmac']) +test_kvno(realm, 'DEPRECATED:arcfour-hmac', 'aes256-cts-hmac-sha1-96') +realm.stop() + +# 6: allow_des3 permits negotiation of des3-cbc-sha1 session key. +realm = K5Realm(krb5_conf=conf6, create_host=False, get_creds=False) +realm.run([kadminl, 'addprinc', '-randkey', '-e', 'aes256-cts', 'server']) +realm.run([kadminl, 'setstr', 'server', 'session_enctypes', 'des3-cbc-sha1']) +test_kvno(realm, 'DEPRECATED:des3-cbc-sha1', 'aes256-cts-hmac-sha1-96') +realm.stop() + +# 7: default config negotiates aes256-sha1 session key for RC4-only service. +realm = K5Realm(create_host=False, get_creds=False) +realm.run([kadminl, 'addprinc', '-randkey', '-e', 'rc4-hmac', 'server']) +test_kvno(realm, 'aes256-cts-hmac-sha1-96', 'DEPRECATED:arcfour-hmac') +realm.stop() + +success('sesskeynego') diff --git a/krb5-1.21.3/src/tests/t_skew.py b/krb5-1.21.3/src/tests/t_skew.py new file mode 100755 index 00000000..ed40edec --- /dev/null +++ b/krb5-1.21.3/src/tests/t_skew.py @@ -0,0 +1,55 @@ +from k5test import * + +# Create a realm with the KDC one hour in the past. +realm = K5Realm(start_kdc=False) +realm.start_kdc(['-T', '-3600']) + +# kinit (no preauth) should work, and should set a clock skew allowing +# kvno to work, with or without FAST. +mark('kdc_timesync enabled, no preauth') +realm.kinit(realm.user_princ, password('user')) +realm.run([kvno, realm.host_princ]) +realm.kinit(realm.user_princ, password('user'), flags=['-T', realm.ccache]) +realm.run([kvno, realm.host_princ]) +realm.run([kdestroy]) + +# kinit (with preauth) should work, with or without FAST. +mark('kdc_timesync enabled, with preauth') +realm.run([kadminl, 'modprinc', '+requires_preauth', 'user']) +realm.kinit(realm.user_princ, password('user')) +realm.run([kvno, realm.host_princ]) +realm.kinit(realm.user_princ, password('user'), flags=['-T', realm.ccache]) +realm.run([kvno, realm.host_princ]) +realm.run([kdestroy]) + +realm.stop() + +# Repeat the above tests with kdc_timesync disabled. +conf = {'libdefaults': {'kdc_timesync': '0'}} +realm = K5Realm(start_kdc=False, krb5_conf=conf) +realm.start_kdc(['-T', '-3600']) + +# Get tickets to use for FAST kinit tests. The start time offset is +# ignored by the KDC since we aren't getting postdatable tickets, but +# serves to suppress the client clock skew check on the KDC reply. +fast_cache = realm.ccache + '.fast' +realm.kinit(realm.user_princ, password('user'), + flags=['-s', '-3600s', '-c', fast_cache]) + +# kinit should detect too much skew in the KDC response. kinit with +# FAST should fail from the KDC since the armor AP-REQ won't be valid. +mark('KDC timesync disabled, no preauth') +realm.kinit(realm.user_princ, password('user'), expected_code=1, + expected_msg='Clock skew too great in KDC reply') +realm.kinit(realm.user_princ, None, flags=['-T', fast_cache], expected_code=1, + expected_msg='Clock skew too great while') + +# kinit (with preauth) should fail from the KDC, with or without FAST. +mark('KDC timesync disabled, with preauth') +realm.run([kadminl, 'modprinc', '+requires_preauth', 'user']) +realm.kinit(realm.user_princ, password('user'), expected_code=1, + expected_msg='Clock skew too great while') +realm.kinit(realm.user_princ, None, flags=['-T', fast_cache], expected_code=1, + expected_msg='Clock skew too great while') + +success('Clock skew tests') diff --git a/krb5-1.21.3/src/tests/t_sn2princ.py b/krb5-1.21.3/src/tests/t_sn2princ.py new file mode 100755 index 00000000..0b63dbec --- /dev/null +++ b/krb5-1.21.3/src/tests/t_sn2princ.py @@ -0,0 +1,167 @@ +from k5test import * + +offline = (len(args) > 0 and args[0] != "no") + +conf = {'libdefaults': {'dns_canonicalize_hostname': 'true'}, + 'domain_realm': {'kerberos.org': 'R1', + 'example.com': 'R2', + 'mit.edu': 'R3'}} +no_rdns_conf = {'libdefaults': {'rdns': 'false'}} +no_canon_conf = {'libdefaults': {'dns_canonicalize_hostname': 'false', + 'qualify_shortname': 'example.com'}} +fallback_canon_conf = {'libdefaults': + {'rdns': 'false', + 'dns_canonicalize_hostname': 'fallback'}} + +realm = K5Realm(realm='R1', create_host=False, krb5_conf=conf) +no_rdns = realm.special_env('no_rdns', False, krb5_conf=no_rdns_conf) +no_canon = realm.special_env('no_canon', False, krb5_conf=no_canon_conf) +fallback_canon = realm.special_env('fallback_canon', False, + krb5_conf=fallback_canon_conf) + +def testbase(host, nametype, princhost, princrealm, env=None): + # Run the sn2princ harness with a specified host and name type and + # the fixed service string 'svc', and compare the result to the + # expected hostname and realm part. + out = realm.run(['./s2p', host, 'SVC', nametype], env=env).rstrip() + expected = 'SVC/%s@%s' % (princhost, princrealm) + if out != expected: + fail('Expected %s, got %s' % (expected, out)) + +def test(host, princhost, princrealm): + # Test with the host-based name type with canonicalization enabled. + testbase(host, 'srv-hst', princhost, princrealm) + +def testnc(host, princhost, princrealm): + # Test with the host-based name type with canonicalization disabled. + testbase(host, 'srv-hst', princhost, princrealm, env=no_canon) + +def testnr(host, princhost, princrealm): + # Test with the host-based name type with reverse lookup disabled. + testbase(host, 'srv-hst', princhost, princrealm, env=no_rdns) + +def testu(host, princhost, princrealm): + # Test with the unknown name type. + testbase(host, 'unknown', princhost, princrealm) + +def testfc(host, princhost, princrealm): + # Test with the host-based name type with canonicalization fallback. + testbase(host, 'srv-hst', princhost, princrealm, env=fallback_canon) + +# With the unknown principal type, we do not canonicalize or downcase, +# but we do remove a trailing period and look up the realm. +mark('unknown type') +testu('ptr-mismatch.kerberos.org', 'ptr-mismatch.kerberos.org', 'R1') +testu('Example.COM', 'Example.COM', 'R2') +testu('abcde', 'abcde', '') + +# A ':port' or ':instance' trailer should be ignored for realm lookup. +# If there is more than one colon in the name, we assume it's an IPv6 +# address and don't treat it as having a trailer. +mark('port trailer') +testu('example.com.:123', 'example.com.:123', 'R2') +testu('Example.COM:xyZ', 'Example.COM:xyZ', 'R2') +testu('example.com.::123', 'example.com.::123', '') + +# With dns_canonicalize_hostname=false, we downcase and remove +# trailing dots but do not canonicalize the hostname. +# Single-component names are qualified with the configured suffix +# (defaulting to the first OS search domain, but Python cannot easily +# retrieve that value so we don't test it). Trailers do not get +# downcased. +mark('dns_canonicalize_host=false') +testnc('ptr-mismatch.kerberos.org', 'ptr-mismatch.kerberos.org', 'R1') +testnc('Example.COM', 'example.com', 'R2') +testnc('abcde', 'abcde.example.com', 'R2') +testnc('example.com.:123', 'example.com:123', 'R2') +testnc('Example.COM:xyZ', 'example.com:xyZ', 'R2') +testnc('example.com.::123', 'example.com.::123', '') + +if offline: + skip_rest('sn2princ tests', 'offline mode requested') + +# For the online tests, we rely on ptr-mismatch.kerberos.org forward +# and reverse resolving to these names. +oname = 'ptr-mismatch.kerberos.org' +fname = 'www.kerberos.org' + +# Test fallback canonicalization krb5_sname_to_principal() results. +mark('dns_canonicalize_host=fallback') +testfc(oname, oname, '') + +# Verify forward resolution before testing for it. +try: + ai = socket.getaddrinfo(oname, None, 0, 0, 0, socket.AI_CANONNAME) +except socket.gaierror: + skip_rest('sn2princ tests', 'cannot forward resolve %s' % oname) +(family, socktype, proto, canonname, sockaddr) = ai[0] +if canonname.lower() != fname: + skip_rest('sn2princ tests', + '%s forward resolves to %s, not %s' % (oname, canonname, fname)) + +# Test fallback canonicalization in krb5_get_credentials(). +oprinc = 'host/' + oname +fprinc = 'host/' + fname +shutil.copy(realm.ccache, realm.ccache + '.save') +# Test that we only try fprinc once if we enter it as input. +out, trace = realm.run(['./gcred', 'srv-hst', fprinc + '@'], + env=fallback_canon, expected_code=1, return_trace=True) +msg = 'Requesting tickets for %s@R1, referrals on' % fprinc +if trace.count(msg) != 1: + fail('Expected one try for %s' % fprinc) +# Create fprinc, and verify that we get it as the canonicalized +# fallback for oprinc. +realm.addprinc(fprinc) +msgs = ('Getting credentials user@R1 -> %s@ using' % oprinc, + 'Requesting tickets for %s@R1' % oprinc, + 'Requesting tickets for %s@R1' % fprinc, + 'Received creds for desired service %s@R1' % fprinc) +realm.run(['./gcred', 'srv-hst', oprinc + '@'], env=fallback_canon, + expected_msg=fprinc, expected_trace=msgs) +realm.addprinc(oprinc) +# oprinc now exists, but we still get the fprinc ticket from the cache. +realm.run(['./gcred', 'srv-hst', oprinc + '@'], env=fallback_canon, + expected_msg=fprinc) +# Without the cached result, we should get oprinc in preference to fprinc. +os.rename(realm.ccache + '.save', realm.ccache) +realm.run(['./gcred', 'srv-hst', oprinc], env=fallback_canon, + expected_msg=oprinc) + +# Test fallback canonicalization for krb5_rd_req(). +realm.run([kadminl, 'ktadd', fprinc]) +msgs = ('Decrypted AP-REQ with server principal %s@R1' % fprinc, + 'AP-REQ ticket: user@R1 -> %s@R1' % fprinc) +realm.run(['./rdreq', fprinc, oprinc + '@'], env=fallback_canon, + expected_trace=msgs) + +# Test fallback canonicalization for getting initial creds with a keytab. +msgs = ('Getting initial credentials for %s@' % oprinc, + 'Found entries for %s@R1 in keytab' % fprinc, + 'Retrieving %s@R1 from ' % fprinc) +realm.run(['./icred', '-k', realm.keytab, '-S', 'host', oname], + env=fallback_canon, expected_trace=msgs) + +# Test forward-only canonicalization (rdns=false). +mark('rdns=false') +testnr(oname, fname, 'R1') +testnr(oname + ':123', fname + ':123', 'R1') +testnr(oname + ':xyZ', fname + ':xyZ', 'R1') + +# Verify reverse resolution before testing for it. +try: + names = socket.getnameinfo(sockaddr, socket.NI_NAMEREQD) +except socket.gaierror: + skip_rest('reverse sn2princ tests', 'cannot reverse resolve %s' % oname) +rname = names[0].lower() +if rname == fname: + skip_rest('reverse sn2princ tests', + '%s reverse resolves to %s ' + 'which should be different from %s' % (oname, rname, fname)) + +# Test default canonicalization (forward and reverse lookup). +mark('default') +test(oname, rname, 'R3') +test(oname + ':123', rname + ':123', 'R3') +test(oname + ':xyZ', rname + ':xyZ', 'R3') + +success('krb5_sname_to_principal tests') diff --git a/krb5-1.21.3/src/tests/t_spake.py b/krb5-1.21.3/src/tests/t_spake.py new file mode 100644 index 00000000..f0afefb6 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_spake.py @@ -0,0 +1,149 @@ +from k5test import * + +# The name and number of each supported SPAKE group. +builtin_groups = ((1, 'edwards25519'),) +openssl_groups = ((2, 'P-256'), (3, 'P-384'), (4, 'P-521')) +if runenv.have_spake_openssl == 'yes': + groups = builtin_groups + openssl_groups +else: + groups = builtin_groups + +for gnum, gname in groups: + mark('group %s' % gname) + conf = {'libdefaults': {'spake_preauth_groups': gname}} + for realm in multipass_realms(create_user=False, create_host=False, + krb5_conf=conf): + realm.run([kadminl, 'addprinc', '+preauth', '-pw', 'pw', 'user']) + + # Test a basic SPAKE preauth scenario with no optimizations. + msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Selected etype info:', + 'Sending SPAKE support message', + 'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)', + '/More preauthentication data is required', + 'Continuing preauth mech PA-SPAKE (151)', + 'SPAKE challenge received with group ' + str(gnum), + 'Sending SPAKE response', + 'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)', + 'AS key determined by preauth:', + 'Decrypted AS reply') + realm.kinit('user', 'pw', expected_trace=msgs) + + # Test an unsuccessful authentication. + msgs = ('/Additional pre-authentication required', + 'Selected etype info:', + 'Sending SPAKE support message', + 'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)', + '/More preauthentication data is required', + 'Continuing preauth mech PA-SPAKE (151)', + 'SPAKE challenge received with group ' + str(gnum), + 'Sending SPAKE response', + '/Preauthentication failed') + realm.kinit('user', 'wrongpw', expected_code=1, expected_trace=msgs) + +conf = {'libdefaults': {'spake_preauth_groups': 'edwards25519'}} +kdcconf = {'realms': {'$realm': {'spake_preauth_indicator': 'indspake'}}} +realm = K5Realm(create_user=False, krb5_conf=conf, kdc_conf=kdcconf) +realm.run([kadminl, 'addprinc', '+preauth', '-pw', 'pw', 'user']) + +# Test with FAST. +mark('FAST') +msgs = ('Using FAST due to armor ccache negotiation', + 'FAST armor key:', + 'Sending unauthenticated request', + '/Additional pre-authentication required', + 'Decoding FAST response', + 'Selected etype info:', + 'Sending SPAKE support message', + 'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)', + '/More preauthentication data is required', + 'Continuing preauth mech PA-SPAKE (151)', + 'SPAKE challenge received with group 1', + 'Sending SPAKE response', + 'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)', + 'AS key determined by preauth:', + 'FAST reply key:') +realm.kinit(realm.host_princ, flags=['-k']) +realm.kinit('user', 'pw', flags=['-T', realm.ccache], expected_trace=msgs) + +# Test optimistic client preauth (151 is PA-SPAKE). +mark('client optimistic') +msgs = ('Attempting optimistic preauth', + 'Processing preauth types: PA-SPAKE (151)', + 'Sending SPAKE support message', + 'for next request: PA-SPAKE (151)', + '/More preauthentication data is required', + 'Selected etype info:', + 'SPAKE challenge received with group 1', + 'Sending SPAKE response', + 'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)', + 'AS key determined by preauth:', + 'Decrypted AS reply') +realm.run(['./icred', '-o', '151', 'user', 'pw'], expected_trace=msgs) + +# Test KDC optimistic challenge (accepted by client). +mark('KDC optimistic') +oconf = {'kdcdefaults': {'spake_preauth_kdc_challenge': 'edwards25519'}} +oenv = realm.special_env('ochal', True, krb5_conf=oconf) +realm.stop_kdc() +realm.start_kdc(env=oenv) +msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Selected etype info:', + 'SPAKE challenge received with group 1', + 'Sending SPAKE response', + 'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)', + 'AS key determined by preauth:', + 'Decrypted AS reply') +realm.kinit('user', 'pw', expected_trace=msgs) + +if runenv.have_spake_openssl != 'yes': + skip_rest('SPAKE fallback tests', 'SPAKE not built using OpenSSL') + +# Test optimistic client preauth falling back to encrypted timestamp +# because the KDC doesn't support any of the client groups. +mark('client optimistic (fallback)') +p256conf={'libdefaults': {'spake_preauth_groups': 'P-256'}} +p256env = realm.special_env('p256', False, krb5_conf=p256conf) +msgs = ('Attempting optimistic preauth', + 'Processing preauth types: PA-SPAKE (151)', + 'Sending SPAKE support message', + 'for next request: PA-SPAKE (151)', + '/Preauthentication failed', + 'Selected etype info:', + 'Encrypted timestamp ', + 'for next request: PA-FX-COOKIE (133), PA-ENC-TIMESTAMP (2)', + 'AS key determined by preauth:', + 'Decrypted AS reply') +realm.run(['./icred', '-o', '151', 'user', 'pw'], env=p256env, + expected_trace=msgs) + +# Test KDC optimistic challenge (rejected by client). +mark('KDC optimistic (rejected)') +rconf = {'libdefaults': {'spake_preauth_groups': 'P-384,edwards25519'}, + 'kdcdefaults': {'spake_preauth_kdc_challenge': 'P-384'}} +renv = realm.special_env('ochal', True, krb5_conf=rconf) +realm.stop_kdc() +realm.start_kdc(env=renv) +msgs = ('Sending unauthenticated request', + '/Additional pre-authentication required', + 'Selected etype info:', + 'SPAKE challenge with group 3 rejected', + 'Sending SPAKE support message', + 'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)', + '/More preauthentication data is required', + 'Continuing preauth mech PA-SPAKE (151)', + 'SPAKE challenge received with group 1', + 'Sending SPAKE response', + 'for next request: PA-FX-COOKIE (133), PA-SPAKE (151)', + 'AS key determined by preauth:', + 'Decrypted AS reply') +realm.kinit('user', 'pw', expected_trace=msgs) + +# Check that the auth indicator for SPAKE is properly included by the KDC. +mark('auth indicator') +realm.run([kvno, realm.host_princ]) +realm.run(['./adata', realm.host_princ], expected_msg='+97: [indspake]') + +success('SPAKE pre-authentication tests') diff --git a/krb5-1.21.3/src/tests/t_stringattr.py b/krb5-1.21.3/src/tests/t_stringattr.py new file mode 100755 index 00000000..c2dc348e --- /dev/null +++ b/krb5-1.21.3/src/tests/t_stringattr.py @@ -0,0 +1,41 @@ +# Copyright (C) 2011 by the Massachusetts Institute of Technology. +# All rights reserved. + +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +from k5test import * + +realm = K5Realm(start_kadmind=True, create_host=False, get_creds=False) + +realm.prep_kadmin() + +realm.run_kadmin(['getstrs', 'user'], expected_msg='(No string attributes.)') + +realm.run_kadmin(['setstr', 'user', 'attr1', 'value1']) +realm.run_kadmin(['setstr', 'user', 'attr2', 'value2']) +realm.run_kadmin(['delstr', 'user', 'attr1']) +realm.run_kadmin(['setstr', 'user', 'attr3', 'value3']) + +out = realm.run_kadmin(['getstrs', 'user']) +if ('attr2: value2' not in out or 'attr3: value3' not in out or + 'attr1:' in out): + fail('Final attribute query') + +success('KDB string attributes') diff --git a/krb5-1.21.3/src/tests/t_tabdump.py b/krb5-1.21.3/src/tests/t_tabdump.py new file mode 100755 index 00000000..49531bf4 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_tabdump.py @@ -0,0 +1,80 @@ +from k5test import * + +import csv +from io import StringIO + +def tab_csv(s): + io = StringIO(s) + return list(csv.DictReader(io, dialect=csv.excel_tab)) + + +def getrows(dumptype): + out = realm.run([kdb5_util, 'tabdump', dumptype]) + return tab_csv(out) + + +def checkkeys(rows, dumptype, names): + if sorted(rows[0].keys()) != sorted(names): + fail('tabdump %s field names' % dumptype) + + +realm = K5Realm(start_kdc=False, get_creds=False) + + +rows = getrows('keyinfo') +checkkeys(rows, 'keyinfo', + ["name", "keyindex", "kvno", "enctype", "salttype", "salt"]) + +userrows = [x for x in rows if x['name'].startswith('user@')] +userrows.sort(key=lambda x: x['keyindex']) + +if (userrows[0]['enctype'] != 'aes256-cts-hmac-sha1-96' or + userrows[1]['enctype'] != 'aes128-cts-hmac-sha1-96'): + fail('tabdump keyinfo enctypes') + +success('tabdump keyinfo') + + +rows = getrows('keydata') +checkkeys(rows, 'keydata', + ["name", "keyindex", "kvno", "enctype", "key", "salttype", "salt"]) + + +rows = getrows('princ_flags') +checkkeys(rows, 'princ_flags', ["name", "flag", "value"]) + + +rows = getrows('princ_lockout') +checkkeys(rows, 'princ_lockout', ["name", "last_success", "last_failed", + "fail_count"]) + + +realm.run([kadminl, 'addpol', '-history', '3', 'testpol']) +realm.run([kadminl, 'modprinc', '-policy', 'testpol', 'user']) + +rows = getrows('princ_meta') +checkkeys(rows, 'princ_meta', ["name", "modby", "modtime", "lastpwd", + "policy", "mkvno", "hist_kvno"]) + +userrows = [x for x in rows if x['name'].startswith('user@')] + +if userrows[0]['policy'] != 'testpol': + fail('tabdump princ_meta policy name') + + +realm.run([kadminl, 'set_string', 'user', 'foo', 'bar']) + +rows = getrows('princ_stringattrs') +checkkeys(rows, 'princ_stringattrs', ["name", "key", "value"]) + +userrows = [x for x in rows if x['name'].startswith('user@')] +if (len(userrows) != 1 or userrows[0]['key'] != 'foo' or + userrows[0]['value'] != 'bar'): + fail('tabdump princ_stringattrs key/value') + + +rows = getrows('princ_tktpolicy') +checkkeys(rows, 'princ_tktpolicy', ["name", "expiration", "pw_expiration", + "max_life", "max_renew_life"]) + +success('tabdump') diff --git a/krb5-1.21.3/src/tests/t_u2u.py b/krb5-1.21.3/src/tests/t_u2u.py new file mode 100644 index 00000000..4b8a82a2 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_u2u.py @@ -0,0 +1,60 @@ +from k5test import * + +realm = K5Realm(create_host=False) + +# Create a second user principal and get tickets for it. +u2u_ccache = 'FILE:' + os.path.join(realm.testdir, 'ccu2u') +realm.addprinc('alice', password('alice')) +realm.kinit('alice', password('alice'), ['-c', u2u_ccache]) + +# Verify that -allow_dup_skey denies u2u requests. +realm.run([kadminl, 'modprinc', '-allow_dup_skey', 'alice']) +realm.run([kvno, '--u2u', u2u_ccache, 'alice'], expected_code=1, + expected_msg='KDC policy rejects request') +realm.run([kadminl, 'modprinc', '+allow_dup_skey', 'alice']) + +# Verify that -allow_svr denies regular TGS requests, but allows +# user-to-user TGS requests. +realm.run([kadminl, 'modprinc', '-allow_svr', 'alice']) +realm.run([kvno, 'alice'], expected_code=1, + expected_msg='Server principal valid for user2user only') +realm.run([kvno, '--u2u', u2u_ccache, 'alice'], expected_msg='kvno = 0') +realm.run([kadminl, 'modprinc', '+allow_svr', 'alice']) + +# Verify that normal lookups ignore the user-to-user ticket. +realm.run([kvno, 'alice'], expected_msg='kvno = 1') +out = realm.run([klist]) +if out.count('alice@KRBTEST.COM') != 2: + fail('expected two alice tickets after regular kvno') + +# Try u2u against the client user. +realm.run([kvno, '--u2u', realm.ccache, realm.user_princ]) + +realm.run([klist]) + +realm.stop() + +# Load the test KDB module to test aliases +testprincs = {'krbtgt/KRBTEST.COM': {'keys': 'aes128-cts'}, + 'user': {'keys': 'aes128-cts', 'flags': '+preauth'}, + 'WIN10': {'keys': 'aes128-cts'}} +kdcconf = {'realms': {'$realm': {'database_module': 'test'}}, + 'dbmodules': {'test': {'db_library': 'test', + 'princs': testprincs, + 'alias': {'HOST/win10': 'WIN10'}}}} + +realm = K5Realm(kdc_conf=kdcconf, create_kdb=False) +realm.start_kdc() + +# Create a second user principal and get tickets for it. +u2u_ccache = 'FILE:' + os.path.join(realm.testdir, 'ccu2u') +realm.extract_keytab('WIN10', realm.keytab) +realm.kinit('WIN10', None, ['-k', '-c', u2u_ccache]) + +realm.extract_keytab(realm.user_princ, realm.keytab) +realm.kinit(realm.user_princ, None, ['-k']) + +realm.run([kvno, '--u2u', u2u_ccache, 'HOST/win10'], expected_msg='kvno = 0') +realm.run([kvno, '--u2u', u2u_ccache, 'WIN10'], expected_msg='kvno = 0') + +success('user-to-user tests') diff --git a/krb5-1.21.3/src/tests/t_unlockiter.py b/krb5-1.21.3/src/tests/t_unlockiter.py new file mode 100755 index 00000000..fb18abc6 --- /dev/null +++ b/krb5-1.21.3/src/tests/t_unlockiter.py @@ -0,0 +1,20 @@ +from k5test import * + +# Default KDB iteration is locked. Expect write lock failure unless +# unlocked iteration is explicitly requested. +realm = K5Realm(create_user=False, create_host=False, start_kdc=False, + bdb_only=True) +realm.run(['./unlockiter'], expected_code=1) +realm.run(['./unlockiter', '-u']) +realm.run(['./unlockiter', '-l'], expected_code=1) + +# Set default to unlocked iteration. Only explicitly requested locked +# iteration should block the write lock. +realm = K5Realm(create_user=False, create_host=False, start_kdc=False, + bdb_only=True, + krb5_conf={'dbmodules': {'db': {'unlockiter': 'true'}}}) +realm.run(['./unlockiter']) +realm.run(['./unlockiter', '-u']) +realm.run(['./unlockiter', '-l'], expected_code=1) + +success('Unlocked iteration unit tests') diff --git a/krb5-1.21.3/src/tests/t_y2038.py b/krb5-1.21.3/src/tests/t_y2038.py new file mode 100644 index 00000000..2eaa191e --- /dev/null +++ b/krb5-1.21.3/src/tests/t_y2038.py @@ -0,0 +1,79 @@ +from k5test import * + +# These tests will become much less important after the y2038 boundary +# has elapsed, and may start exhibiting problems around the year 2075. + +if runenv.sizeof_time_t <= 4: + skip_rest('y2038 timestamp tests', 'platform has 32-bit time_t') + +# Start a KDC running roughly 21 years in the future, after the y2038 +# boundary. Set long maximum lifetimes for later tests. +conf = {'realms': {'$realm': {'max_life': '9000d', + 'max_renewable_life': '9000d'}}} +realm = K5Realm(start_kdc=False, kdc_conf=conf) +realm.start_kdc(['-T', '662256000']) + +# kinit without preauth should succeed with clock skew correction, but +# will result in an expired ticket, because we sent an absolute end +# time and didn't get a chance to correct it.. +mark('kinit, no preauth') +realm.kinit(realm.user_princ, password('user')) +realm.run([kvno, realm.host_princ], expected_code=1, + expected_msg='Ticket expired') + +# kinit with preauth should succeed and result in a valid ticket, as +# we get a chance to correct the end time based on the KDC time. Try +# with encrypted timestamp and encrypted challenge. +mark('kinit, with preauth') +realm.run([kadminl, 'modprinc', '+requires_preauth', 'user']) +realm.kinit(realm.user_princ, password('user')) +realm.run([kvno, realm.host_princ]) +realm.kinit(realm.user_princ, password('user'), flags=['-T', realm.ccache]) +realm.run([kvno, realm.host_princ]) + +# Test that expiration warning works after y2038, by setting a +# password expiration time ten minutes after the KDC time. +mark('expiration warning') +realm.run([kadminl, 'modprinc', '-pwexpire', '662256600 seconds', 'user']) +out = realm.kinit(realm.user_princ, password('user')) +if 'will expire in less than one hour' not in out: + fail('password expiration message') +year = int(out.split()[-1]) +if year < 2038 or year > 9999: + fail('password expiration year') + +realm.stop_kdc() +realm.start_kdc() +realm.start_kadmind() +realm.prep_kadmin() + +# Test getdate parsing of absolute timestamps after 2038 and +# marshalling over the kadmin protocol. The local time zone will +# affect the display time by a little bit, so just look for the year. +mark('kadmin marshalling') +realm.run_kadmin(['modprinc', '-pwexpire', '2040-02-03', realm.host_princ]) +realm.run_kadmin(['getprinc', realm.host_princ], expected_msg=' 2040\n') + +# Get a ticket whose lifetime crosses the y2038 boundary and +# range-check the expiration year as reported by klist. +mark('ticket lifetime across y2038') +realm.kinit(realm.user_princ, password('user'), + flags=['-l', '8000d', '-r', '8500d']) +realm.run([kvno, realm.host_princ]) +out = realm.run([klist]) +if int(out.split('\n')[4].split()[2].split('/')[2]) < 39: + fail('unexpected tgt expiration year') +if int(out.split('\n')[5].split()[2].split('/')[2]) < 40: + fail('unexpected tgt rtill year') +if int(out.split('\n')[6].split()[2].split('/')[2]) < 39: + fail('unexpected service ticket expiration year') +if int(out.split('\n')[7].split()[2].split('/')[2]) < 40: + fail('unexpected service ticket rtill year') +realm.kinit(realm.user_princ, None, ['-R']) +out = realm.run([klist]) +if int(out.split('\n')[4].split()[2].split('/')[2]) < 39: + fail('unexpected renewed tgt expiration year') +if int(out.split('\n')[5].split()[2].split('/')[2]) < 40: + fail('unexpected renewed tgt rtill year') + +success('y2038 tests') diff --git a/krb5-1.21.3/src/tests/test1.c b/krb5-1.21.3/src/tests/test1.c new file mode 100644 index 00000000..aed656eb --- /dev/null +++ b/krb5-1.21.3/src/tests/test1.c @@ -0,0 +1,192 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/test1.c - Regression tests for krb5 library */ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "krb5.h" + +unsigned char key_one[8] = { 0x10, 0x23, 0x32, 0x45, 0x54, 0x67, 0x76, 0x89 }; +unsigned char key_two[8] = { 0xea, 0x89, 0x57, 0x76, 0x5b, 0xcd, 0x0d, 0x34 }; + +extern void dump_data(); + +tkt_test_1() +{ + krb5_data *data; + krb5_ticket tk_in, *tk_out; + krb5_keyblock sess_k, serv_k, *nsess; + krb5_enc_tkt_part tk_in_enc; + int code; + krb5_address *addr_list[2]; + krb5_address addr_1; + static krb5_octet ip_addr_1[4] = { 18, 72, 0, 122 }; + char *out; + + /* + * fill in some values on the "in" side of the ticket + */ + code = krb5_parse_name ("server/test/1@BOGUS.ORG", &tk_in.server); + if (code != 0) { + com_err("tkt_test_1", code, " parsing server principal"); + return; + } + + serv_k.enctype = 1; /* XXX symbolic constant */ + serv_k.length = 8; /* XXX symbolic constant */ + serv_k.contents = key_one; + + sess_k.enctype = 1; /* XXX symbolic constant */ + sess_k.length = 8; /* XXX symbolic constant */ + sess_k.contents = key_two; + + tk_in.etype = 1; /* XXX symbolic constant here */ + tk_in.skvno = 4; + + tk_in.enc_part2 = &tk_in_enc; + + tk_in_enc.flags = 0x11; + tk_in_enc.session = &sess_k; + + tk_in_enc.times.authtime = 42; + tk_in_enc.times.starttime = 43; + tk_in_enc.times.endtime = 44; + + code = krb5_parse_name ("client/test/1@BOGUS.ORG", &tk_in_enc.client); + if (code != 0) { + com_err("tkt_test_1", code, " parsing client principal"); + return; + } + tk_in_enc.transited.length = 0; + + addr_1.addrtype = ADDRTYPE_INET; /* XXX should be KRB5_ADDR... */ + addr_1.length = 4; + addr_1.contents = ip_addr_1; + + addr_list[0] = &addr_1; + addr_list[1] = 0; + + + tk_in_enc.caddrs = addr_list; + tk_in_enc.authorization_data = 0; + + code = krb5_encrypt_tkt_part(&serv_k, &tk_in); + if (code != 0) { + com_err ("tkt_test_1", code, " encrypting ticket"); + return; + } + + data = 0; + + code = krb5_encode_ticket (&tk_in, &data); + if (code != 0) { + com_err ("tkt_test_1", code, " encoding ticket"); + return; + } + + dump_data(data); + + tk_out = 0; + code = krb5_decode_ticket (data, &tk_out); + if (code != 0) { + com_err ("tkt_test_1", code, "decoding ticket"); + return; + } + /* check the plaintext values */ + if (tk_out->etype != 1) { + com_err ("tkt_test_1", 0, "wrong etype"); + return; + } + if (tk_out->skvno != 4) { + com_err ("tkt_test_1", 0, "wrong kvno"); + return; + } + + code = krb5_unparse_name(tk_out->server, &out); + if (code != 0) { + com_err ("tkt_test_1", code, "couldn't unparse server principal"); + return; + } + if (strcmp (out, "server/test/1@BOGUS.ORG") != 0) { + com_err("tkt_test_1", 0, "wrong server principal"); + return; + } + free(out); + out = 0; + + /* decode the ciphertext */ + code = krb5_decrypt_tkt_part (&serv_k, tk_out); + if (code != 0) { + com_err ("tkt_test_1", code, "while decrypting ticket"); + return; + } + + /* check the contents */ + if (tk_out->enc_part2->flags != 0x11) { + com_err("tkt_test_1", 0, "wrong flags"); + return; + } + + nsess = tk_out->enc_part2->session; + + if (nsess->enctype != 1) { + com_err("tkt_test_1", 0, "wrong session key type"); + return; + } + if (nsess->length != 8) { + com_err("tkt_test_1", 0, "wrong session key length"); + return; + } + if (memcmp(nsess->contents, key_two, 8) != 0) { + com_err("tkt_test_1", 0, "wrong session key contents"); + return; + } + + code = krb5_unparse_name(tk_out->enc_part2->client, &out); + if (code != 0) { + com_err ("tkt_test_1", code, "couldn't unparse client principal"); + return; + } + if (strcmp (out, "client/test/1@BOGUS.ORG") != 0) { + com_err("tkt_test_1", 0, "wrong client principal"); + return; + } + free(out); + out = 0; + if (tk_out->enc_part2->transited.length != 0) { + com_err("tkt_test_1", 0, "wrong transited length"); + return; + } + /* XXX should check address here, too */ + /* XXX should check times here */ + /* XXX should check auth. data here */ + printf("test 1 passed\n"); +} + + + +main() +{ + krb5_init_ets(); + tkt_test_1(); +} diff --git a/krb5-1.21.3/src/tests/threads/Makefile.in b/krb5-1.21.3/src/tests/threads/Makefile.in new file mode 100644 index 00000000..4e12b373 --- /dev/null +++ b/krb5-1.21.3/src/tests/threads/Makefile.in @@ -0,0 +1,40 @@ +# The test programs here are not built or run by default. You can +# build a specific test program with "make gss-perf" or similar. +# "make run-t_rcache" will run the replay cache test program in the +# proper environment. + +mydir=tests$(S)threads +BUILDTOP=$(REL)..$(S).. + +SRCS=$(srcdir)/t_rcache.c \ + $(srcdir)/gss-perf.c \ + $(srcdir)/init_ctx.c \ + $(srcdir)/profread.c \ + $(srcdir)/prof1.c + +all: + +run-t_rcache: t_rcache + $(RUN_TEST) ./t_rcache file2:test.rcache2 + +t_rcache: t_rcache.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_rcache t_rcache.o $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS) + +prof1: prof1.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o prof1 prof1.o $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS) + +prof1.o: prof1.c + +gss-perf: gss-perf.o $(KRB5_BASE_DEPLIBS) $(GSS_DEPLIBS) + $(CC_LINK) $(PTHREAD_CFLAGS) -o gss-perf gss-perf.o $(GSS_LIBS) $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS) + +init_ctx: init_ctx.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) $(PTHREAD_CFLAGS) -o init_ctx init_ctx.o $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS) + +profread: profread.o $(KRB5_BASE_DEPLIBS) + $(CC_LINK) $(PTHREAD_CFLAGS) -o profread profread.o $(KRB5_BASE_LIBS) $(THREAD_LINKOPTS) + +install: + +clean: + $(RM) *.o t_rcache syms prof1 gss-perf test.rcache2 diff --git a/krb5-1.21.3/src/tests/threads/deps b/krb5-1.21.3/src/tests/threads/deps new file mode 100644 index 00000000..f536935d --- /dev/null +++ b/krb5-1.21.3/src/tests/threads/deps @@ -0,0 +1,27 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)t_rcache.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \ + $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \ + $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h t_rcache.c +$(OUTPRE)gss-perf.$(OBJEXT): $(BUILDTOP)/include/gssapi/gssapi.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \ + gss-perf.c +$(OUTPRE)init_ctx.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ + init_ctx.c +$(OUTPRE)profread.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \ + profread.c +$(OUTPRE)prof1.$(OBJEXT): $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) prof1.c diff --git a/krb5-1.21.3/src/tests/threads/gss-perf.c b/krb5-1.21.3/src/tests/threads/gss-perf.c new file mode 100644 index 00000000..f3630c2f --- /dev/null +++ b/krb5-1.21.3/src/tests/threads/gss-perf.c @@ -0,0 +1,455 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/threads/gss-perf.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * GSSAPI performance testing + * initially contributed by Ken Raeburn + */ +/* + * Possible to-do items: + * - init-mutual testing (process msg back from accept) + * - wrap/unwrap testing (one init/accept per thread, loop on wrap/unwrap) + * - wrap/unwrap MT testing (one init/accept for process) ? + * - init+accept with replay cache + * - default to target "host@localhostname" + * - input ccache option? + * + * Also, perhaps try to simulate certain application patterns, like + * init/accept, exchange N messages with wrap/unwrap, destroy context, + * all in a loop in M parallel threads. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define N_THREADS 2 +#define ITER_COUNT 10000 +static int init_krb5_first = 0; + +struct resource_info { + struct timeval start_time, end_time; +}; +struct thread_info { + pthread_t tid; + struct resource_info r; +}; + +static gss_name_t target; +static char *prog, *target_name; +static unsigned int n_threads = N_THREADS; +static int iter_count = ITER_COUNT; +static int do_pause, do_mutual; +static int test_init, test_accept; + +static void usage (void) __attribute__((noreturn)); +static void set_target (char *); + +static void +usage () +{ + fprintf (stderr, "usage: %s [ options ] service-name\n", prog); + fprintf (stderr, " service-name\tGSSAPI host-based service name (e.g., 'host@FQDN')\n"); + fprintf (stderr, "options:\n"); + fprintf (stderr, "\t-I\ttest gss_init_sec_context\n"); + fprintf (stderr, "\t-A\ttest gss_accept_sec_context\n"); + fprintf (stderr, "\t-k K\tspecify keytab (remember FILE: or other prefix!)\n"); + fprintf (stderr, "\t-t N\tspecify number of threads (default %d)\n", + N_THREADS); + fprintf (stderr, "\t-i N\tset iteration count (default %d)\n", + ITER_COUNT); + fprintf (stderr, "\t-m\tenable mutual authentication flag (but don't do the additional calls)\n"); + fprintf (stderr, "\t-K\tinitialize a krb5_context for the duration\n"); + fprintf (stderr, "\t-P\tpause briefly after starting, to allow attaching dtrace/strace/etc\n"); + exit (1); +} + +static int +numarg (char *arg) +{ + char *end; + long val; + + val = strtol (arg, &end, 10); + if (*arg == 0 || *end != 0) { + fprintf (stderr, "invalid numeric argument '%s'\n", arg); + usage (); + } + if (val >= 1 && val <= INT_MAX) + return val; + fprintf (stderr, "out of range numeric value %ld (1..%d)\n", + val, INT_MAX); + usage (); +} + +static char optstring[] = "k:t:i:KPmIA"; + +static void +process_options (int argc, char *argv[]) +{ + int c; + + prog = strrchr (argv[0], '/'); + if (prog) + prog++; + else + prog = argv[0]; + while ((c = getopt (argc, argv, optstring)) != -1) { + switch (c) { + case '?': + case ':': + usage (); + break; + + case 'k': + setenv ("KRB5_KTNAME", optarg, 1); + break; + + case 't': + n_threads = numarg (optarg); + if (n_threads >= SIZE_MAX / sizeof (struct thread_info)) { + n_threads = SIZE_MAX / sizeof (struct thread_info); + fprintf (stderr, "limiting n_threads to %u\n", n_threads); + } + break; + + case 'i': + iter_count = numarg (optarg); + break; + + case 'K': + init_krb5_first = 1; + break; + + case 'P': + do_pause = 1; + break; + + case 'I': + test_init = 1; + break; + case 'A': + test_accept = 1; + break; + } + } + if (argc == optind + 1) + set_target (argv[optind]); + else + usage (); + + if (test_init && test_accept) { + fprintf (stderr, "-I and -A are mutually exclusive\n"); + usage (); + } + if (test_init == 0 && test_accept == 0) + test_init = 1; +} + +static void +display_a_status (const char *s_type, OM_uint32 type, OM_uint32 val) +{ + OM_uint32 mctx = 0; + OM_uint32 maj_stat, min_stat; + gss_buffer_desc msg = GSS_C_EMPTY_BUFFER; + + do { + maj_stat = gss_display_status (&min_stat, + val, + type, + GSS_C_NO_OID, + &mctx, + &msg); + if (maj_stat != GSS_S_COMPLETE) { + fprintf (stderr, + "error getting display form of %s status code %#lx\n", + s_type, (unsigned long) val); + exit (1); + } + fprintf (stderr, " %s: %.*s\n", s_type, + (int) msg.length, (char *) msg.value); + gss_release_buffer (&min_stat, &msg); + } while (mctx != 0); +} + +static void +gss_error(const char *where, OM_uint32 maj_stat, OM_uint32 min_stat) +{ + fprintf (stderr, "%s: %s:\n", prog, where); + display_a_status ("major", GSS_C_GSS_CODE, maj_stat); + display_a_status ("minor", GSS_C_MECH_CODE, min_stat); + exit (1); +} + +static void +do_accept (gss_buffer_desc *msg, int iter) +{ + OM_uint32 maj_stat, min_stat; + gss_name_t client = GSS_C_NO_NAME; + gss_buffer_desc reply = GSS_C_EMPTY_BUFFER; + gss_OID oid = GSS_C_NO_OID; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + OM_uint32 flags = do_mutual ? GSS_C_MUTUAL_FLAG : 0; + + reply.value = NULL; + reply.length = 0; + maj_stat = gss_accept_sec_context (&min_stat, + &ctx, + GSS_C_NO_CREDENTIAL, + msg, + GSS_C_NO_CHANNEL_BINDINGS, + &client, + &oid, + &reply, + &flags, + NULL, /* time_rec */ + NULL); /* del_cred_handle */ + if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) { + fprintf (stderr, "pid %lu thread %#lx failing in iteration %d\n", + (unsigned long) getpid (), (unsigned long) pthread_self (), + iter); + gss_error ("accepting context", maj_stat, min_stat); + } + gss_release_buffer (&min_stat, &reply); + if (ctx != GSS_C_NO_CONTEXT) + gss_delete_sec_context (&min_stat, &ctx, GSS_C_NO_BUFFER); + gss_release_name (&min_stat, &client); +} + +static gss_buffer_desc +do_init () +{ + OM_uint32 maj_stat, min_stat; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + OM_uint32 flags = 0, ret_flags = 0; + gss_buffer_desc msg = GSS_C_EMPTY_BUFFER; + + if (do_mutual) + flags |= GSS_C_MUTUAL_FLAG; + + msg.value = NULL; + msg.length = 0; + maj_stat = gss_init_sec_context (&min_stat, + GSS_C_NO_CREDENTIAL, + &ctx, + target, + GSS_C_NO_OID, + flags, + 0, + NULL, /* no channel bindings */ + NULL, /* no previous token */ + NULL, /* ignore mech type */ + &msg, + &ret_flags, + NULL); /* time_rec */ + if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) { + gss_error ("initiating", maj_stat, min_stat); + } + if (ctx != GSS_C_NO_CONTEXT) + gss_delete_sec_context (&min_stat, &ctx, GSS_C_NO_BUFFER); + return msg; +} + +static void +set_target (char *name) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc namebuf; + + target_name = name; + namebuf.value = name; + namebuf.length = strlen (name); + maj_stat = gss_import_name (&min_stat, + &namebuf, + GSS_C_NT_HOSTBASED_SERVICE, + &target); + if (maj_stat != GSS_S_COMPLETE) + gss_error ("importing target name", maj_stat, min_stat); +} + +static long double +tvsub (struct timeval t1, struct timeval t2) +{ + /* POSIX says .tv_usec is signed. */ + return (t1.tv_sec - t2.tv_sec + + (long double) 1.0e-6 * (t1.tv_usec - t2.tv_usec)); +} + +static struct timeval +now (void) +{ + struct timeval tv; + if (gettimeofday (&tv, NULL) < 0) { + perror ("gettimeofday"); + exit (1); + } + return tv; +} + +static gss_buffer_desc init_msg; + +static void run_iterations (struct resource_info *r) +{ + int i; + OM_uint32 min_stat; + + r->start_time = now (); + for (i = 0; i < iter_count; i++) { + if (test_init) { + gss_buffer_desc msg = do_init (); + gss_release_buffer (&min_stat, &msg); + } else if (test_accept) { + do_accept (&init_msg, i); + } else + assert (test_init || test_accept); + } + r->end_time = now (); +} + +static void * +thread_proc (void *p) +{ + run_iterations (p); + return 0; +} + +static struct thread_info *tinfo; + +static krb5_context kctx; +static struct rusage start, finish; +static struct timeval start_time, finish_time; + +int +main (int argc, char *argv[]) +{ + long double user, sys, wallclock, total; + unsigned int i; + + /* Probably should have a command-line option controlling this, + but if a replay cache is used, we can't do just one + init_sec_context and easily time just the accept_sec_context + side. */ + setenv ("KRB5RCACHETYPE", "none", 1); + + process_options (argc, argv); + + /* + * Some places in the krb5 library cache data globally. + * This option allows you to test the effect of that. + */ + if (init_krb5_first && krb5_init_context (&kctx) != 0) { + fprintf (stderr, "krb5_init_context error\n"); + exit (1); + } + tinfo = calloc (n_threads, sizeof (*tinfo)); + if (tinfo == NULL) { + perror ("calloc"); + exit (1); + } + printf ("Test: %s threads: %d iterations: %d target: %s\n", + test_init ? "init" : "accept", n_threads, iter_count, + target_name ? target_name : "(NONE)"); + if (do_pause) { + printf ("pid %lu napping...\n", (unsigned long) getpid ()); + sleep (10); + } + /* + * Some tests use one message and process it over and over. Even + * if not, this sort of "primes" things by fetching any needed + * tickets just once. + */ + init_msg = do_init (); + printf ("starting...\n"); + /* And *now* we start measuring the performance. */ + if (getrusage (RUSAGE_SELF, &start) < 0) { + perror ("getrusage"); + exit (1); + } + start_time = now (); +#define foreach_thread(IDXVAR) for (IDXVAR = 0; IDXVAR < n_threads; IDXVAR++) + foreach_thread (i) { + int err; + + err = pthread_create (&tinfo[i].tid, NULL, thread_proc, &tinfo[i].r); + if (err) { + fprintf (stderr, "pthread_create: %s\n", strerror (err)); + exit (1); + } + } + foreach_thread (i) { + int err; + void *val; + + err = pthread_join (tinfo[i].tid, &val); + if (err) { + fprintf (stderr, "pthread_join: %s\n", strerror (err)); + exit (1); + } + } + finish_time = now (); + if (getrusage (RUSAGE_SELF, &finish) < 0) { + perror ("getrusage"); + exit (1); + } + if (init_krb5_first) + krb5_free_context (kctx); + foreach_thread (i) { + printf ("Thread %2d: elapsed time %Lfs\n", i, + tvsub (tinfo[i].r.end_time, tinfo[i].r.start_time)); + } + wallclock = tvsub (finish_time, start_time); + /* + * Report on elapsed time and CPU usage. Depending what + * performance issue you're chasing down, different values may be + * of particular interest, so report all the info we've got. + */ + printf ("Overall run time with %d threads = %Lfs, %Lfms per iteration.\n", + n_threads, wallclock, 1000 * wallclock / iter_count); + user = tvsub (finish.ru_utime, start.ru_utime); + sys = tvsub (finish.ru_stime, start.ru_stime); + total = user + sys; + printf ("CPU usage: user=%Lfs sys=%Lfs total=%Lfs.\n", user, sys, total); + printf ("Utilization: user=%5.1Lf%% sys=%5.1Lf%% total=%5.1Lf%%\n", + 100 * user / wallclock, + 100 * sys / wallclock, + 100 * total / wallclock); + printf ("Util/thread: user=%5.1Lf%% sys=%5.1Lf%% total=%5.1Lf%%\n", + 100 * user / wallclock / n_threads, + 100 * sys / wallclock / n_threads, + 100 * total / wallclock / n_threads); + printf ("Total CPU use per iteration per thread: %Lfms\n", + 1000 * total / n_threads / iter_count); + return 0; +} diff --git a/krb5-1.21.3/src/tests/threads/init_ctx.c b/krb5-1.21.3/src/tests/threads/init_ctx.c new file mode 100644 index 00000000..42619a91 --- /dev/null +++ b/krb5-1.21.3/src/tests/threads/init_ctx.c @@ -0,0 +1,273 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/threads/init_ctx.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * krb5 context creation performance testing + * initially contributed by Ken Raeburn + */ + +#include "k5-platform.h" +#include +#include +#include + +#include +#include + +#define N_THREADS 4 +#define ITER_COUNT 40000 +static int init_krb5_first = 0; + +struct resource_info { + struct timeval start_time, end_time; +}; +struct thread_info { + pthread_t tid; + struct resource_info r; +}; + +static char *prog; +static unsigned int n_threads = N_THREADS; +static int iter_count = ITER_COUNT; +static int do_pause; + +static void usage (void) __attribute__((noreturn)); + +static void +usage () +{ + fprintf (stderr, "usage: %s [ options ]\n", prog); + fprintf (stderr, "options:\n"); + fprintf (stderr, "\t-t N\tspecify number of threads (default %d)\n", + N_THREADS); + fprintf (stderr, "\t-i N\tset iteration count (default %d)\n", + ITER_COUNT); + fprintf (stderr, "\t-K\tinitialize a krb5_context for the duration\n"); + fprintf (stderr, "\t-P\tpause briefly after starting, to allow attaching dtrace/strace/etc\n"); + exit (1); +} + +static int +numarg (char *arg) +{ + char *end; + long val; + + val = strtol (arg, &end, 10); + if (*arg == 0 || *end != 0) { + fprintf (stderr, "invalid numeric argument '%s'\n", arg); + usage (); + } + if (val >= 1 && val <= INT_MAX) + return val; + fprintf (stderr, "out of range numeric value %ld (1..%d)\n", + val, INT_MAX); + usage (); +} + +static char optstring[] = "t:i:KP"; + +static void +process_options (int argc, char *argv[]) +{ + int c; + + prog = strrchr (argv[0], '/'); + if (prog) + prog++; + else + prog = argv[0]; + while ((c = getopt (argc, argv, optstring)) != -1) { + switch (c) { + case '?': + case ':': + usage (); + break; + + case 't': + n_threads = numarg (optarg); + if (n_threads >= SIZE_MAX / sizeof (struct thread_info)) { + n_threads = SIZE_MAX / sizeof (struct thread_info); + fprintf (stderr, "limiting n_threads to %u\n", n_threads); + } + break; + + case 'i': + iter_count = numarg (optarg); + break; + + case 'K': + init_krb5_first = 1; + break; + + case 'P': + do_pause = 1; + break; + } + } + if (argc != optind) + usage (); +} + +static long double +tvsub (struct timeval t1, struct timeval t2) +{ + /* POSIX says .tv_usec is signed. */ + return (t1.tv_sec - t2.tv_sec + + (long double) 1.0e-6 * (t1.tv_usec - t2.tv_usec)); +} + +static struct timeval +now (void) +{ + struct timeval tv; + if (gettimeofday (&tv, NULL) < 0) { + perror ("gettimeofday"); + exit (1); + } + return tv; +} + +static void run_iterations (struct resource_info *r) +{ + int i; + krb5_error_code err; + krb5_context ctx; + + r->start_time = now (); + for (i = 0; i < iter_count; i++) { + err = krb5_init_context(&ctx); + if (err) { + com_err(prog, err, "initializing krb5 context"); + exit(1); + } + krb5_free_context(ctx); + } + r->end_time = now (); +} + +static void * +thread_proc (void *p) +{ + run_iterations (p); + return 0; +} + +static struct thread_info *tinfo; + +static krb5_context kctx; +static struct rusage start, finish; +static struct timeval start_time, finish_time; + +int +main (int argc, char *argv[]) +{ + long double user, sys, wallclock, total; + unsigned int i; + + process_options (argc, argv); + + /* + * Some places in the krb5 library cache data globally. + * This option allows you to test the effect of that. + */ + if (init_krb5_first && krb5_init_context (&kctx) != 0) { + fprintf (stderr, "krb5_init_context error\n"); + exit (1); + } + tinfo = calloc (n_threads, sizeof (*tinfo)); + if (tinfo == NULL) { + perror ("calloc"); + exit (1); + } + printf ("Threads: %d iterations: %d\n", n_threads, iter_count); + if (do_pause) { + printf ("pid %lu napping...\n", (unsigned long) getpid ()); + sleep (10); + } + printf ("starting...\n"); + /* And *now* we start measuring the performance. */ + if (getrusage (RUSAGE_SELF, &start) < 0) { + perror ("getrusage"); + exit (1); + } + start_time = now (); +#define foreach_thread(IDXVAR) for (IDXVAR = 0; IDXVAR < n_threads; IDXVAR++) + foreach_thread (i) { + int err; + + err = pthread_create (&tinfo[i].tid, NULL, thread_proc, &tinfo[i].r); + if (err) { + fprintf (stderr, "pthread_create: %s\n", strerror (err)); + exit (1); + } + } + foreach_thread (i) { + int err; + void *val; + + err = pthread_join (tinfo[i].tid, &val); + if (err) { + fprintf (stderr, "pthread_join: %s\n", strerror (err)); + exit (1); + } + } + finish_time = now (); + if (getrusage (RUSAGE_SELF, &finish) < 0) { + perror ("getrusage"); + exit (1); + } + if (init_krb5_first) + krb5_free_context (kctx); + foreach_thread (i) { + printf ("Thread %2d: elapsed time %Lfs\n", i, + tvsub (tinfo[i].r.end_time, tinfo[i].r.start_time)); + } + wallclock = tvsub (finish_time, start_time); + /* + * Report on elapsed time and CPU usage. Depending what + * performance issue you're chasing down, different values may be + * of particular interest, so report all the info we've got. + */ + printf ("Overall run time with %d threads = %Lfs, %Lfms per iteration.\n", + n_threads, wallclock, 1000 * wallclock / iter_count); + user = tvsub (finish.ru_utime, start.ru_utime); + sys = tvsub (finish.ru_stime, start.ru_stime); + total = user + sys; + printf ("CPU usage: user=%Lfs sys=%Lfs total=%Lfs.\n", user, sys, total); + printf ("Utilization: user=%5.1Lf%% sys=%5.1Lf%% total=%5.1Lf%%\n", + 100 * user / wallclock, + 100 * sys / wallclock, + 100 * total / wallclock); + printf ("Util/thread: user=%5.1Lf%% sys=%5.1Lf%% total=%5.1Lf%%\n", + 100 * user / wallclock / n_threads, + 100 * sys / wallclock / n_threads, + 100 * total / wallclock / n_threads); + printf ("Total CPU use per iteration per thread: %Lfms\n", + 1000 * total / n_threads / iter_count); + free(tinfo); + return 0; +} diff --git a/krb5-1.21.3/src/tests/threads/prof1.c b/krb5-1.21.3/src/tests/threads/prof1.c new file mode 100644 index 00000000..3d959784 --- /dev/null +++ b/krb5-1.21.3/src/tests/threads/prof1.c @@ -0,0 +1,105 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/threads/prof1.c */ +/* + * Copyright (C) 2004 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int nthreads = 10; +unsigned int delay = 3600; + +volatile int done = 0; /* XXX hack */ + +const char *path = "/tmp/foo1.conf:/tmp/foo.conf"; +const char *filename = "/tmp/foo.conf"; + +const char *prog; + +static void *worker(void *arg) +{ + profile_t p; + long err; + int i; + const char *const names[] = { + "one", "two", "three", 0 + }; + char **values; + const char *mypath = (random() & 1) ? path : filename; + + while (!done) { + err = profile_init_path(mypath, &p); + if (err) { + com_err(prog, err, "calling profile_init(\"%s\")", mypath); + exit(1); + } + for (i = 0; i < 10; i++) { + values = 0; + err = profile_get_values(p, names, &values); + if (err == 0 && values != 0) + profile_free_list(values); + } + profile_release(p); + } + return 0; +} + +static void *modifier(void *arg) +{ + struct timespec req; + while (!done) { + req.tv_sec = 0; + req.tv_nsec = random() & 499999999; + nanosleep(&req, 0); + utime(filename, 0); +/* printf("."), fflush(stdout); */ + } + return 0; +} + +int main(int argc, char *argv[]) +{ + int i; + pthread_t thr; + + prog = argv[0]; + for (i = 0; i < nthreads; i++) { + assert(0 == pthread_create(&thr, 0, worker, 0)); + } + sleep(1); + pthread_create(&thr, 0, modifier, 0); + sleep(delay); + done = 1; + sleep(2); + return 0; +} diff --git a/krb5-1.21.3/src/tests/threads/profread.c b/krb5-1.21.3/src/tests/threads/profread.c new file mode 100644 index 00000000..be28ba40 --- /dev/null +++ b/krb5-1.21.3/src/tests/threads/profread.c @@ -0,0 +1,287 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/threads/profread.c */ +/* + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* + * krb5 profile data retrieval performance testing + * initially contributed by Ken Raeburn + */ + +#include "k5-platform.h" +#include +#include +#include +#include + +#include +#include + +#define N_THREADS 4 +#define ITER_COUNT 40000 +static int init_krb5_first = 0; + +struct resource_info { + struct timeval start_time, end_time; +}; +struct thread_info { + pthread_t tid; + struct resource_info r; + krb5_context ctx; +}; + +static char *prog; +static unsigned int n_threads = N_THREADS; +static int iter_count = ITER_COUNT; +static int do_pause; + +static void usage (void) __attribute__((noreturn)); + +static void +usage () +{ + fprintf (stderr, "usage: %s [ options ]\n", prog); + fprintf (stderr, "options:\n"); + fprintf (stderr, "\t-t N\tspecify number of threads (default %d)\n", + N_THREADS); + fprintf (stderr, "\t-i N\tset iteration count (default %d)\n", + ITER_COUNT); + fprintf (stderr, "\t-K\tinitialize a krb5_context for the duration\n"); + fprintf (stderr, "\t-P\tpause briefly after starting, to allow attaching dtrace/strace/etc\n"); + exit (1); +} + +static int +numarg (char *arg) +{ + char *end; + long val; + + val = strtol (arg, &end, 10); + if (*arg == 0 || *end != 0) { + fprintf (stderr, "invalid numeric argument '%s'\n", arg); + usage (); + } + if (val >= 1 && val <= INT_MAX) + return val; + fprintf (stderr, "out of range numeric value %ld (1..%d)\n", + val, INT_MAX); + usage (); +} + +static char optstring[] = "t:i:KP"; + +static void +process_options (int argc, char *argv[]) +{ + int c; + + prog = strrchr (argv[0], '/'); + if (prog) + prog++; + else + prog = argv[0]; + while ((c = getopt (argc, argv, optstring)) != -1) { + switch (c) { + case '?': + case ':': + usage (); + break; + + case 't': + n_threads = numarg (optarg); + if (n_threads >= SIZE_MAX / sizeof (struct thread_info)) { + n_threads = SIZE_MAX / sizeof (struct thread_info); + fprintf (stderr, "limiting n_threads to %u\n", n_threads); + } + break; + + case 'i': + iter_count = numarg (optarg); + break; + + case 'K': + init_krb5_first = 1; + break; + + case 'P': + do_pause = 1; + break; + } + } + if (argc != optind) + usage (); +} + +static long double +tvsub (struct timeval t1, struct timeval t2) +{ + /* POSIX says .tv_usec is signed. */ + return (t1.tv_sec - t2.tv_sec + + (long double) 1.0e-6 * (t1.tv_usec - t2.tv_usec)); +} + +static struct timeval +now (void) +{ + struct timeval tv; + if (gettimeofday (&tv, NULL) < 0) { + perror ("gettimeofday"); + exit (1); + } + return tv; +} + +static void run_iterations (struct resource_info *r) +{ + int i; + krb5_error_code err; + krb5_context ctx; + profile_t prof = NULL; + + err = krb5_init_context(&ctx); + if (err) { + com_err(prog, err, "initializing krb5 context"); + exit(1); + } + err = krb5_get_profile(ctx, &prof); + if (err) { + com_err(prog, err, "fetching profile from context"); + exit(1); + } + r->start_time = now (); + for (i = 0; i < iter_count; i++) { + int ival; + err = profile_get_integer(prof, "one", "two", "three", 42, &ival); + if (err) { + com_err(prog, err, "fetching value from profile"); + exit(1); + } + } + r->end_time = now (); + profile_release (prof); + krb5_free_context(ctx); +} + +static void * +thread_proc (void *p) +{ + run_iterations (p); + return 0; +} + +static struct thread_info *tinfo; + +static krb5_context kctx; +static struct rusage start, finish; +static struct timeval start_time, finish_time; + +int +main (int argc, char *argv[]) +{ + long double user, sys, wallclock, total; + unsigned int i; + + process_options (argc, argv); + + /* + * Some places in the krb5 library cache data globally. + * This option allows you to test the effect of that. + */ + if (init_krb5_first && krb5_init_context (&kctx) != 0) { + fprintf (stderr, "krb5_init_context error\n"); + exit (1); + } + tinfo = calloc (n_threads, sizeof (*tinfo)); + if (tinfo == NULL) { + perror ("calloc"); + exit (1); + } + printf ("Threads: %d iterations: %d\n", n_threads, iter_count); + if (do_pause) { + printf ("pid %lu napping...\n", (unsigned long) getpid ()); + sleep (10); + } + printf ("starting...\n"); + /* And *now* we start measuring the performance. */ + if (getrusage (RUSAGE_SELF, &start) < 0) { + perror ("getrusage"); + exit (1); + } + start_time = now (); +#define foreach_thread(IDXVAR) for (IDXVAR = 0; IDXVAR < n_threads; IDXVAR++) + foreach_thread (i) { + int err; + + err = pthread_create (&tinfo[i].tid, NULL, thread_proc, &tinfo[i].r); + if (err) { + fprintf (stderr, "pthread_create: %s\n", strerror (err)); + exit (1); + } + } + foreach_thread (i) { + int err; + void *val; + + err = pthread_join (tinfo[i].tid, &val); + if (err) { + fprintf (stderr, "pthread_join: %s\n", strerror (err)); + exit (1); + } + } + finish_time = now (); + if (getrusage (RUSAGE_SELF, &finish) < 0) { + perror ("getrusage"); + exit (1); + } + if (init_krb5_first) + krb5_free_context (kctx); + foreach_thread (i) { + printf ("Thread %2d: elapsed time %Lfs\n", i, + tvsub (tinfo[i].r.end_time, tinfo[i].r.start_time)); + } + wallclock = tvsub (finish_time, start_time); + /* + * Report on elapsed time and CPU usage. Depending what + * performance issue you're chasing down, different values may be + * of particular interest, so report all the info we've got. + */ + printf ("Overall run time with %d threads = %Lfs, %.2Lfus per iteration.\n", + n_threads, wallclock, 1000000 * wallclock / iter_count); + user = tvsub (finish.ru_utime, start.ru_utime); + sys = tvsub (finish.ru_stime, start.ru_stime); + total = user + sys; + printf ("CPU usage: user=%Lfs sys=%Lfs total=%Lfs.\n", user, sys, total); + printf ("Utilization: user=%5.1Lf%% sys=%5.1Lf%% total=%5.1Lf%%\n", + 100 * user / wallclock, + 100 * sys / wallclock, + 100 * total / wallclock); + printf ("Util/thread: user=%5.1Lf%% sys=%5.1Lf%% total=%5.1Lf%%\n", + 100 * user / wallclock / n_threads, + 100 * sys / wallclock / n_threads, + 100 * total / wallclock / n_threads); + printf ("Total CPU use per iteration per thread: %.2Lfus\n", + 1000000 * total / n_threads / iter_count); + return 0; +} diff --git a/krb5-1.21.3/src/tests/threads/t_rcache.c b/krb5-1.21.3/src/tests/threads/t_rcache.c new file mode 100644 index 00000000..07c45cca --- /dev/null +++ b/krb5-1.21.3/src/tests/threads/t_rcache.c @@ -0,0 +1,260 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/threads/t_rcache.c */ +/* + * Copyright (C) 2006 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include +#include +#include + +krb5_context ctx; +krb5_rcache rcache; +const char *rcname; +time_t end_time; +const char *prog; + +struct tinfo { + time_t now; + unsigned long my_ctime; + unsigned int my_cusec; + unsigned int total; + int idx; +}; + +#define DEFAULT_N_THREADS 2 +#define DEFAULT_INTERVAL 20 /* 5 * 60 */ + +int init_once = 0; +int n_threads = DEFAULT_N_THREADS; +int interval = DEFAULT_INTERVAL; +int *ip; + +static void wait_for_tick () +{ + time_t now, next; + now = time(0); + do { + next = time(0); + } while (now == next); +} + +/* Encrypt data into out (preallocated by the caller) with a random key. */ +static krb5_error_code encrypt_data (krb5_data *data, krb5_enc_data *out) +{ + krb5_keyblock kb; + krb5_error_code err; + + err = krb5_c_make_random_key(ctx, ENCTYPE_AES256_CTS_HMAC_SHA1_96, + &kb); + if (err) + return err; + err = krb5_c_encrypt(ctx, &kb, KRB5_KEYUSAGE_TGS_REQ_AUTH, NULL, data, + out); + krb5_free_keyblock_contents(ctx, &kb); + return err; +} + +static void try_one (struct tinfo *t) +{ + krb5_error_code err; + char buf[256], buf2[512]; + krb5_rcache my_rcache; + krb5_data d; + krb5_enc_data enc; + + snprintf(buf, sizeof(buf), "host/all-in-one.mit.edu/%p@ATHENA.MIT.EDU", + buf); + + /* k5_rc_store() requires a ciphertext. Create one by encrypting a dummy + * value in a random key. */ + d = string2data(buf); + enc.ciphertext = make_data(buf2, sizeof(buf2)); + err = encrypt_data(&d, &enc); + if (err != 0) { + const char *msg = krb5_get_error_message(ctx, err); + fprintf(stderr, "%s: encrypting authenticator: %s\n", prog, msg); + krb5_free_error_message(ctx, msg); + exit(1); + } + + if (t->now != t->my_ctime) { + if (t->my_ctime != 0) { + snprintf(buf2, sizeof(buf2), "%3d: %ld %5d\n", t->idx, + t->my_ctime, t->my_cusec); + printf("%s", buf2); + } + t->my_ctime = t->now; + t->my_cusec = 1; + } else + t->my_cusec++; + if (!init_once) { + err = k5_rc_resolve(ctx, rcname, &my_rcache); + if (err) { + const char *msg = krb5_get_error_message(ctx, err); + fprintf(stderr, "%s: %s while initializing replay cache\n", prog, msg); + krb5_free_error_message(ctx, msg); + exit(1); + } + } else + my_rcache = rcache; + err = k5_rc_store(ctx, my_rcache, &enc); + if (err) { + com_err(prog, err, "storing in replay cache"); + exit(1); + } + if (!init_once) + k5_rc_close(ctx, my_rcache); +} + +static void *run_a_loop (void *x) +{ + struct tinfo t = { 0 }; + + t.now = time(0); + t.idx = *(int *)x; + while (t.now != time(0)) + ; + t.now = time(0); + while (t.now < end_time) { + t.now = time(0); + try_one(&t); + t.total++; + } + *(int*)x = t.total; + return 0; +} + +static void usage(void) +{ + fprintf (stderr, "usage: %s [ options ] rcname\n", prog); + fprintf (stderr, "options:\n"); + fprintf (stderr, "\t-1\tcreate one rcache handle for process\n"); + fprintf (stderr, "\t-t N\tnumber of threads to create (default: %d)\n", + DEFAULT_N_THREADS); + fprintf (stderr, + "\t-i N\tinterval to run test over, in seconds (default: %d)\n", + DEFAULT_INTERVAL); + exit(1); +} + +static const char optstring[] = "1t:i:"; + +static void process_options (int argc, char *argv[]) +{ + int c; + + prog = argv[0]; + while ((c = getopt(argc, argv, optstring)) != -1) { + switch (c) { + case '?': + case ':': + default: + usage (); + case '1': + init_once = 1; + break; + case 't': + n_threads = atoi (optarg); + if (n_threads < 1 || n_threads > 10000) + usage (); + break; + case 'i': + interval = atoi (optarg); + if (interval < 2 || n_threads > 100000) + usage (); + break; + } + } + + argc -= optind; + argv += optind; + if (argc != 1) + usage (); + rcname = argv[0]; +} + +int main (int argc, char *argv[]) +{ + krb5_error_code err; + int i; + unsigned long sum; + + process_options (argc, argv); + err = krb5_init_context(&ctx); + if (err) { + com_err(prog, err, "initializing context"); + return 1; + } + + if (init_once) { + err = k5_rc_resolve(ctx, rcname, &rcache); + if (err) { + const char *msg = krb5_get_error_message(ctx, err); + fprintf(stderr, "%s: %s while initializing new replay cache\n", + prog, msg); + krb5_free_error_message(ctx, msg); + return 1; + } + } + + ip = malloc(sizeof(int) * n_threads); + if (ip == 0 && n_threads > 0) { + perror("malloc"); + exit(1); + } + for (i = 0; i < n_threads; i++) + ip[i] = i; + + wait_for_tick (); + end_time = time(0) + interval; + + for (i = 0; i < n_threads; i++) { + pthread_t new_thread; + int perr; + perr = pthread_create(&new_thread, 0, run_a_loop, &ip[i]); + if (perr) { + errno = perr; + perror("pthread_create"); + exit(1); + } + } + while (time(0) < end_time + 1) + sleep(1); + sum = 0; + for (i = 0; i < n_threads; i++) { + sum += ip[i]; + printf("thread %d total %5d, about %.1f per second\n", i, ip[i], + ((double) ip[i])/interval); + } + printf("total %lu in %d seconds, avg ~%.1f/sec, ~%.1f/sec/thread\n", + sum, interval, + ((double)sum)/interval, ((double)sum)/interval/n_threads); + free(ip); + + if (init_once) + k5_rc_close(ctx, rcache); + krb5_free_context(ctx); + return 0; +} diff --git a/krb5-1.21.3/src/tests/unlockiter.c b/krb5-1.21.3/src/tests/unlockiter.c new file mode 100644 index 00000000..e854bc90 --- /dev/null +++ b/krb5-1.21.3/src/tests/unlockiter.c @@ -0,0 +1,276 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/unlockiter.c - test program for unlocked iteration */ +/* + * Copyright (C) 2014 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. + */ + +/* + * Test unlocked KDB iteration. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include /* Some platforms need memset() for FD_ZERO */ +#include + +struct cb_arg { + int inpipe; + int outpipe; + int timeout; + int done; +}; + +/* Helper function for cb(): read a sync byte (with possible timeout), then + * write a sync byte. */ +static int +syncpair_rw(const char *name, struct cb_arg *arg, char *cp, int timeout) +{ + struct timeval tv; + fd_set rset; + int nfds; + + FD_ZERO(&rset); + FD_SET(arg->inpipe, &rset); + tv.tv_sec = timeout; + tv.tv_usec = 0; + + printf("cb: waiting for %s sync pair\n", name); + nfds = select(arg->inpipe + 1, &rset, + NULL, NULL, (timeout == 0) ? NULL : &tv); + if (nfds < 0) + return -1; + if (nfds == 0) { + errno = ETIMEDOUT; + return -1; + } + if (read(arg->inpipe, cp, 1) < 0) + return -1; + printf("cb: writing %s sync pair\n", name); + if (write(arg->outpipe, cp, 1) < 0) + return -1; + return 0; +} + +/* On the first iteration only, receive and send sync bytes to the locking + * child to drive its locking activities. */ +static krb5_error_code +cb(void *argin, krb5_db_entry *ent) +{ + struct cb_arg *arg = argin; + char c = '\0'; + + if (arg->done) + return 0; + + if (syncpair_rw("first", arg, &c, 0) < 0) { + com_err("cb", errno, "first sync pair"); + return errno; + } + if (syncpair_rw("second", arg, &c, arg->timeout) < 0) { + com_err("cb", errno, "second sync pair"); + return errno; + } + printf("cb: waiting for final sync byte\n"); + if (read(arg->inpipe, &c, 1) < 0) { + com_err("cb", errno, "final sync byte"); + return errno; + } + arg->done = 1; + return 0; +} + +/* Parent process: iterate over the KDB, using a callback that synchronizes + * with the locking child. */ +static int +iterator(struct cb_arg *cb_arg, char **db_args, pid_t child) +{ + krb5_error_code retval; + krb5_context ctx; + + retval = krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_KDC, &ctx); + if (retval) + goto cleanup; + + retval = krb5_db_open(ctx, db_args, + KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN); + if (retval) + goto cleanup; + + retval = krb5_db_iterate(ctx, NULL, cb, cb_arg, 0); + if (retval) + goto cleanup; + + retval = krb5_db_fini(ctx); + +cleanup: + krb5_free_context(ctx); + if (retval) { + com_err("iterator", retval, ""); + kill(child, SIGTERM); + exit(1); + } + return retval; +} + +/* Helper function for locker(): write, then receive a sync byte. */ +static int +syncpair_wr(const char *name, int inpipe, int outpipe, unsigned char *cp) +{ + printf("locker: writing %s sync pair\n", name); + if (write(outpipe, cp, 1) < 0) + return -1; + printf("locker: waiting for %s sync pair\n", name); + if (read(inpipe, cp, 1) < 0) + return -1; + return 0; +} + +/* Child process: acquire and release a write lock on the KDB, synchronized + * with parent. */ +static int +locker(int inpipe, int outpipe, char **db_args) +{ + krb5_error_code retval; + unsigned char c = '\0'; + krb5_context ctx; + + retval = krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_KDC, &ctx); + if (retval) + goto cleanup; + + retval = krb5_db_open(ctx, db_args, + KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN); + if (retval) + goto cleanup; + + if (syncpair_wr("first", inpipe, outpipe, &c) < 0) { + retval = errno; + goto cleanup; + } + printf("locker: acquiring lock...\n"); + retval = krb5_db_lock(ctx, KRB5_DB_LOCKMODE_EXCLUSIVE); + if (retval) + goto cleanup; + printf("locker: acquired lock\n"); + if (syncpair_wr("second", inpipe, outpipe, &c) < 0) { + retval = errno; + goto cleanup; + } + krb5_db_unlock(ctx); + printf("locker: released lock\n"); + printf("locker: writing final sync byte\n"); + if (write(outpipe, &c, 1) < 0) { + retval = errno; + goto cleanup; + } + retval = krb5_db_fini(ctx); +cleanup: + if (retval) + com_err("locker", retval, ""); + + krb5_free_context(ctx); + exit(retval != 0); +} + +static void +usage(const char *prog) +{ + fprintf(stderr, "usage: %s [-lu] [-t timeout]\n", prog); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + struct cb_arg cb_arg; + pid_t child; + char *db_args[2] = { NULL, NULL }; + int c; + int cstatus; + int pipe_to_locker[2], pipe_to_iterator[2]; + + cb_arg.timeout = 1; + cb_arg.done = 0; + while ((c = getopt(argc, argv, "lt:u")) != -1) { + switch (c) { + case 'l': + db_args[0] = "lockiter"; + break; + case 't': + cb_arg.timeout = atoi(optarg); + break; + case 'u': + db_args[0] = "unlockiter"; + break; + default: + usage(argv[0]); + } + } + if (pipe(pipe_to_locker) < 0) { + com_err(argv[0], errno, "pipe(p_il)"); + exit(1); + } + if (pipe(pipe_to_iterator) < 0) { + com_err(argv[0], errno, "pipe(p_li)"); + exit(1); + } + cb_arg.inpipe = pipe_to_iterator[0]; + cb_arg.outpipe = pipe_to_locker[1]; + child = fork(); + switch (child) { + case -1: + com_err(argv[0], errno, "fork"); + exit(1); + break; + case 0: + locker(pipe_to_locker[0], pipe_to_iterator[1], db_args); + break; + default: + if (iterator(&cb_arg, db_args, child)) + exit(1); + if (wait(&cstatus) < 0) { + com_err(argv[0], errno, "wait"); + exit(1); + } + if (WIFSIGNALED(cstatus)) + exit(1); + if (WIFEXITED(cstatus) && WEXITSTATUS(cstatus) != 0) { + exit(1); + } + } + exit(0); +} diff --git a/krb5-1.21.3/src/tests/verify/Makefile.in b/krb5-1.21.3/src/tests/verify/Makefile.in new file mode 100644 index 00000000..bdff9d68 --- /dev/null +++ b/krb5-1.21.3/src/tests/verify/Makefile.in @@ -0,0 +1,16 @@ +mydir=tests$(S)verify +BUILDTOP=$(REL)..$(S).. +KDB5_DEP_LIB=$(THREAD_LINKOPTS) $(DL_LIB) + +SRCS=$(srcdir)/kdb5_verify.c + +all: kdb5_verify + +kdb5_verify: kdb5_verify.o $(KDB5_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o kdb5_verify kdb5_verify.o $(KDB5_LIBS) $(KDB5_DEP_LIB) $(KRB5_BASE_LIBS) + +install: + +clean: + $(RM) kdb5_verify.o kdb5_verify + diff --git a/krb5-1.21.3/src/tests/verify/deps b/krb5-1.21.3/src/tests/verify/deps new file mode 100644 index 00000000..066e907c --- /dev/null +++ b/krb5-1.21.3/src/tests/verify/deps @@ -0,0 +1,14 @@ +# +# Generated makefile dependencies follow. +# +$(OUTPRE)kdb5_verify.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SS_DEPS) \ + $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \ + $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \ + $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \ + $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \ + $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/kdb.h \ + $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \ + $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \ + $(top_srcdir)/include/socket-utils.h kdb5_verify.c diff --git a/krb5-1.21.3/src/tests/verify/kdb5_verify.c b/krb5-1.21.3/src/tests/verify/kdb5_verify.c new file mode 100644 index 00000000..3b152bae --- /dev/null +++ b/krb5-1.21.3/src/tests/verify/kdb5_verify.c @@ -0,0 +1,449 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/verify/kdb5_verify.c */ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "k5-int.h" +#include "kdb.h" +#include "com_err.h" +#include +#include + +#define REALM_SEP '@' +#define REALM_SEP_STR "@" + +struct mblock { + krb5_deltat max_life; + krb5_deltat max_rlife; + krb5_timestamp expiration; + krb5_flags flags; + krb5_kvno mkvno; +} mblock = { /* XXX */ + KRB5_KDB_MAX_LIFE, + KRB5_KDB_MAX_RLIFE, + KRB5_KDB_EXPIRATION, + KRB5_KDB_DEF_FLAGS, + 0 +}; + +int set_dbname_help (krb5_context, char *, char *); + +static void +usage(who, status) + char *who; + int status; +{ + fprintf(stderr, + "usage: %s -p prefix -n num_to_check [-d dbpathname] [-r realmname]\n", + who); + fprintf(stderr, "\t [-D depth] [-k enctype] [-M mkeyname]\n"); + + exit(status); +} + +krb5_keyblock master_keyblock; +krb5_principal master_princ; +krb5_encrypt_block master_encblock; +krb5_pointer master_random; +char *str_master_princ; + +static char *progname; +static char *cur_realm = 0; +static char *mkey_name = 0; +static char *mkey_password = 0; +static krb5_boolean manual_mkey = FALSE; + + +int check_princ (krb5_context, char *); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + int optchar, i, n; + char tmp[4096], tmp2[BUFSIZ], *str_princ; + + krb5_context context; + krb5_error_code retval; + char *dbname = 0; + int enctypedone = 0; + int num_to_check; + char principal_string[BUFSIZ]; + char *suffix = 0; + size_t suffix_size = 0; + int depth, errors; + + krb5_init_context(&context); + + if (strrchr(argv[0], '/')) + argv[0] = strrchr(argv[0], '/')+1; + + progname = argv[0]; + + memset(principal_string, 0, sizeof(principal_string)); + num_to_check = 0; + depth = 1; + + while ((optchar = getopt(argc, argv, "D:P:p:n:d:r:R:k:M:e:m")) != -1) { + switch(optchar) { + case 'D': + depth = atoi(optarg); /* how deep to go */ + break; + case 'P': /* Only used for testing!!! */ + mkey_password = optarg; + break; + case 'p': /* prefix name to check */ + strncpy(principal_string, optarg, sizeof(principal_string) - 1); + principal_string[sizeof(principal_string) - 1] = '\0'; + suffix = principal_string + strlen(principal_string); + suffix_size = sizeof(principal_string) - + (suffix - principal_string); + break; + case 'n': /* how many to check */ + num_to_check = atoi(optarg); + break; + case 'd': /* set db name */ + dbname = optarg; + break; + case 'r': + cur_realm = optarg; + break; + case 'k': + master_keyblock.enctype = atoi(optarg); + enctypedone++; + break; + case 'M': /* master key name in DB */ + mkey_name = optarg; + break; + case 'm': + manual_mkey = TRUE; + break; + case '?': + default: + usage(progname, 1); + /*NOTREACHED*/ + } + } + + if (!(num_to_check && suffix)) usage(progname, 1); + + if (!enctypedone) + master_keyblock.enctype = DEFAULT_KDC_ENCTYPE; + + if (!krb5_c_valid_enctype(master_keyblock.enctype)) { + com_err(progname, KRB5_PROG_ETYPE_NOSUPP, + "while setting up enctype %d", master_keyblock.enctype); + exit(1); + } + + krb5_use_enctype(context, &master_encblock, master_keyblock.enctype); + + if (!dbname) + dbname = DEFAULT_KDB_FILE; /* XXX? */ + + if (!cur_realm) { + if ((retval = krb5_get_default_realm(context, &cur_realm))) { + com_err(progname, retval, "while retrieving default realm name"); + exit(1); + } + } + if ((retval = set_dbname_help(context, progname, dbname))) + exit(retval); + + errors = 0; + + fprintf(stdout, "\nChecking "); + + for (n = 1; n <= num_to_check; n++) { + /* build the new principal name */ + /* we can't pick random names because we need to generate all the names + again given a prefix and count to test the db lib and kdb */ + (void) snprintf(suffix, suffix_size, "%d", n); + (void) snprintf(tmp, sizeof(tmp), "%s-DEPTH-1", principal_string); + str_princ = tmp; + if (check_princ(context, str_princ)) errors++; + + for (i = 2; i <= depth; i++) { + (void) snprintf(tmp2, sizeof(tmp2), "/%s-DEPTH-%d", + principal_string, i); + tmp2[sizeof(tmp2) - 1] = '\0'; + strncat(tmp, tmp2, sizeof(tmp) - 1 - strlen(tmp)); + str_princ = tmp; + if (check_princ(context, str_princ)) errors++; + } + } + + if (errors) + fprintf(stdout, "\n%d errors/principals failed.\n", errors); + else + fprintf(stdout, "\nNo errors.\n"); + + krb5_finish_random_key(context, &master_encblock, &master_random); + krb5_finish_key(context, &master_encblock); + + retval = krb5_db_fini(context); + memset(master_keyblock.contents, 0, (size_t) master_keyblock.length); + if (retval && retval != KRB5_KDB_DBNOTINITED) { + com_err(progname, retval, "while closing database"); + exit(1); + } + krb5_free_keyblock_contents(context, &master_keyblock); + + if (str_master_princ) { + krb5_free_unparsed_name(context, str_master_princ); + } + krb5_free_principal(context, master_princ); + krb5_free_context(context); + exit(0); +} + +int +check_princ(context, str_princ) + krb5_context context; + char * str_princ; +{ + krb5_error_code retval; + krb5_db_entry *kdbe = NULL; + krb5_keyblock pwd_key, db_key; + krb5_data pwd, salt; + krb5_principal princ; + /* char *str_mod_name; */ + char princ_name[4096]; + + snprintf(princ_name, sizeof(princ_name), "%s@%s", str_princ, cur_realm); + + if ((retval = krb5_parse_name(context, princ_name, &princ))) { + com_err(progname, retval, "while parsing '%s'", princ_name); + goto out; + } + + pwd.data = princ_name; /* must be able to regenerate */ + pwd.length = strlen(princ_name); + + if ((retval = krb5_principal2salt(context, princ, &salt))) { + com_err(progname, retval, "while converting principal to salt for '%s'", princ_name); + krb5_free_principal(context, princ); + goto out; + } + + if ((retval = krb5_string_to_key(context, &master_encblock, + &pwd_key, &pwd, &salt))) { + com_err(progname, retval, "while converting password to key for '%s'", + princ_name); + krb5_free_data_contents(context, &salt); + krb5_free_principal(context, princ); + goto out; + } + krb5_free_data_contents(context, &salt); + + if ((retval = krb5_db_get_principal(context, princ, 0, &kdbe))) { + com_err(progname, retval, "while attempting to verify principal's existence"); + krb5_free_principal(context, princ); + goto out; + } + krb5_free_principal(context, princ); + + if ((retval = krb5_dbe_decrypt_key_data(context, NULL, + kdbe->key_data, &db_key, NULL))) { + com_err(progname, retval, "while decrypting key for '%s'", princ_name); + goto errout; + } + + if ((pwd_key.enctype != db_key.enctype) || + (pwd_key.length != db_key.length)) { + fprintf (stderr, "\tKey types do not agree (%d expected, %d from db)\n", + pwd_key.enctype, db_key.enctype); + errout: + krb5_db_free_principal(context, kdbe); + return(-1); + } + else { + if (memcmp((char *)pwd_key.contents, (char *) db_key.contents, + (size_t) pwd_key.length)) { + fprintf(stderr, "\t key did not match stored value for %s\n", + princ_name); + goto errout; + } + } + + free(pwd_key.contents); + free(db_key.contents); + + if (kdbe->key_data[0].key_data_kvno != 1) { + fprintf(stderr,"\tkvno did not match stored value for %s.\n", princ_name); + goto errout; + } + + if (kdbe->max_life != mblock.max_life) { + fprintf(stderr, "\tmax life did not match stored value for %s.\n", + princ_name); + goto errout; + } + + if (kdbe->max_renewable_life != mblock.max_rlife) { + fprintf(stderr, + "\tmax renewable life did not match stored value for %s.\n", + princ_name); + goto errout; + } + + if (kdbe->expiration != mblock.expiration) { + fprintf(stderr, "\texpiration time did not match stored value for %s.\n", + princ_name); + goto errout; + } + +/* + if ((retval = krb5_unparse_name(context, kdbe.mod_name, &str_mod_name))) + com_err(progname, retval, "while unparsing mode name"); + else { + if (strcmp(str_mod_name, str_master_princ) != 0) { + fprintf(stderr, "\tmod name isn't the master princ (%s not %s).\n", + str_mod_name, str_master_princ); + free(str_mod_name); + goto errout; + } + else free(str_mod_name); + } +*/ + + if (kdbe->attributes != mblock.flags) { + fprintf(stderr, "\tAttributes did not match stored value for %s.\n", + princ_name); + goto errout; + } + +out: + krb5_db_free_principal(context, kdbe); + + return(0); +} + +int +set_dbname_help(context, pname, dbname) + krb5_context context; + char *pname; + char *dbname; +{ + krb5_error_code retval; + krb5_data pwd, scratch; + char *args[2]; + krb5_db_entry *master_entry; + + /* assemble & parse the master key name */ + + if ((retval = krb5_db_setup_mkey_name(context, mkey_name, cur_realm, 0, + &master_princ))) { + com_err(pname, retval, "while setting up master key name"); + return(1); + } + if (mkey_password) { + pwd.data = mkey_password; + pwd.length = strlen(mkey_password); + retval = krb5_principal2salt(context, master_princ, &scratch); + if (retval) { + com_err(pname, retval, "while calculated master key salt"); + return(1); + } + if ((retval = krb5_string_to_key(context, &master_encblock, + &master_keyblock, &pwd, &scratch))) { + com_err(pname, retval, + "while transforming master key from password"); + return(1); + } + free(scratch.data); + } else { + if ((retval = krb5_db_fetch_mkey(context, master_princ, + master_keyblock.enctype, + manual_mkey, FALSE, (char *) NULL, + NULL, NULL, + &master_keyblock))) { + com_err(pname, retval, "while reading master key"); + return(1); + } + } + + /* Ick! Current DAL interface requires that the default_realm + field be set in the krb5_context. */ + if ((retval = krb5_set_default_realm(context, cur_realm))) { + com_err(pname, retval, "setting default realm"); + return 1; + } + /* Pathname is passed to db2 via 'args' parameter. */ + args[1] = NULL; + if (asprintf(&args[0], "dbname=%s", dbname) < 0) { + com_err(pname, errno, "while setting up db parameters"); + return 1; + } + + if ((retval = krb5_db_open(context, args, KRB5_KDB_OPEN_RO))) { + com_err(pname, retval, "while initializing database"); + return(1); + } + if ((retval = krb5_db_fetch_mkey_list(context, master_princ, + &master_keyblock))) { + com_err(pname, retval, "while verifying master key"); + (void) krb5_db_fini(context); + return(1); + } + if ((retval = krb5_db_get_principal(context, master_princ, 0, + &master_entry))) { + com_err(pname, retval, "while retrieving master entry"); + (void) krb5_db_fini(context); + return(1); + } + + if ((retval = krb5_unparse_name(context, master_princ, + &str_master_princ))) { + com_err(pname, retval, "while unparsing master principal"); + krb5_db_fini(context); + return(1); + } + + if ((retval = krb5_process_key(context, + &master_encblock, &master_keyblock))) { + com_err(pname, retval, "while processing master key"); + (void) krb5_db_fini(context); + return(1); + } + if ((retval = krb5_init_random_key(context, + &master_encblock, &master_keyblock, + &master_random))) { + com_err(pname, retval, "while initializing random key generator"); + krb5_finish_key(context, &master_encblock); + (void) krb5_db_fini(context); + return(1); + } + mblock.max_life = master_entry->max_life; + mblock.max_rlife = master_entry->max_renewable_life; + mblock.expiration = master_entry->expiration; + /* don't set flags, master has some extra restrictions */ + mblock.mkvno = master_entry->key_data[0].key_data_kvno; + + krb5_db_free_principal(context, master_entry); + free(args[0]); + return 0; +} diff --git a/krb5-1.21.3/src/tests/verify/pkey.c b/krb5-1.21.3/src/tests/verify/pkey.c new file mode 100644 index 00000000..9ed575c4 --- /dev/null +++ b/krb5-1.21.3/src/tests/verify/pkey.c @@ -0,0 +1,24 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* tests/verify/pkey.c */ +/* + * Copyright 1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * For copying and distribution information, please see the file + * . + * + */ + +#include + +void pkey(k) + unsigned char *k; +{ + int i; + unsigned int foo; + + for (i = 0 ; i < 8 ; i++) { + foo = *k++; + fprintf(stderr, "%x ", foo); + } +} diff --git a/krb5-1.21.3/src/util/Makefile.in b/krb5-1.21.3/src/util/Makefile.in new file mode 100644 index 00000000..b80ffbed --- /dev/null +++ b/krb5-1.21.3/src/util/Makefile.in @@ -0,0 +1,29 @@ +mydir=util +# Windows NMAKE doesn't like @ in make variable names, and on +# Windows we don't do the @FOO@ substitutions we do with UNIX +# configure scripts, so hide this. +##WIN32##!if 0 +SUBDIRS=support $(MAYBE_ET_@COM_ERR_VERSION@) $(MAYBE_SS_@SS_VERSION@) \ + profile $(MAYBE_VERTO_@VERTO_VERSION@) +##WIN32##!endif +WINSUBDIRS=windows support et profile +BUILDTOP=$(REL).. + +MAYBE_ET_k5 = et +MAYBE_SS_k5 = ss +MAYBE_ET_sys = +MAYBE_ET_intlsys = +MAYBE_SS_sys = +MAYBE_VERTO_sys = +MAYBE_VERTO_k5 = verto + +all-recurse: + +NO_OUTDIR=1 + +install: + $(INSTALL_SCRIPT) $(srcdir)/krb5-send-pr.sh $(DESTDIR)$(ADMIN_BINDIR)/krb5-send-pr + +clean-unix:: + $(RM) *.pyc + $(RM) -r __pycache__ diff --git a/krb5-1.21.3/src/util/ac_check_krb5.m4 b/krb5-1.21.3/src/util/ac_check_krb5.m4 new file mode 100644 index 00000000..e18183b6 --- /dev/null +++ b/krb5-1.21.3/src/util/ac_check_krb5.m4 @@ -0,0 +1,58 @@ +dnl Copyright (C) 2005 by the Massachusetts Institute of Technology. +dnl All rights reserved. +dnl +dnl Export of this software from the United States of America may +dnl require a specific license from the United States Government. +dnl It is the responsibility of any person or organization contemplating +dnl export to obtain such a license before exporting. +dnl +dnl WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +dnl distribute this software and its documentation for any purpose and +dnl without fee is hereby granted, provided that the above copyright +dnl notice appear in all copies and that both that copyright notice and +dnl this permission notice appear in supporting documentation, and that +dnl the name of M.I.T. not be used in advertising or publicity pertaining +dnl to distribution of the software without specific, written prior +dnl permission. Furthermore if you modify this software you must label +dnl your software as modified software and not distribute it in such a +dnl fashion that it might be confused with the original M.I.T. software. +dnl M.I.T. makes no representations about the suitability of +dnl this software for any purpose. It is provided "as is" without express +dnl or implied warranty. + +dnl AC_CHECK_KRB5 +dnl +dnl Check for krb5-config; update CPPFLAGS and LDFLAGS accordingly. +dnl +AC_DEFUN([AC_CHECK_KRB5], +[AC_ARG_WITH([kerberos5], + [ --with-kerberos5=PATH Enable Kerberos 5 support], + [if test "x$withval" != "xno"; then + if test "x$withval" = "xyes"; then + KRB5ROOT=/usr/local + else + KRB5ROOT=${withval} + fi + AC_MSG_CHECKING([for krb5-config]) + if test -x "$KRB5ROOT/bin/krb5-config"; then + KRB5CONF=$KRB5ROOT/bin/krb5-config + AC_MSG_RESULT([$KRB5CONF]) + AC_MSG_CHECKING([for gssapi support in krb5-config]) + if "$KRB5CONF" | grep gssapi > /dev/null; then + AC_MSG_RESULT([yes]) + k5confopts=gssapi + else + AC_MSG_RESULT([no]) + k5confopts= + fi + K5CFLAGS=`"$KRB5CONF" --cflags $k5confopts` + CPPFLAGS="$CPPFLAGS $K5CFLAGS" + + K5LIBS=`"$KRB5CONF" --libs $k5confopts` + LIBS="$LIBS $K5LIBS" + else + AC_MSG_RESULT([no]) + AC_MSG_WARN([--with-kerberos5 specified but krb5-config not found]) + fi + fi]) +]) diff --git a/krb5-1.21.3/src/util/check-ac-syms b/krb5-1.21.3/src/util/check-ac-syms new file mode 100755 index 00000000..68131101 --- /dev/null +++ b/krb5-1.21.3/src/util/check-ac-syms @@ -0,0 +1,33 @@ +#!/bin/sh + +# args: srcdir srctop-from-srcdir header-path + +d=`pwd` +head -1 $1/configure.ac > config-in.tmp +echo "AC_CONFIG_HEADER(fooconfig.h:$d/fooconfig-h.tmp)" >> config-in.tmp +tail +2 $1/configure.ac | grep -v AC_CONFIG_HEADER >> config-in.tmp +mv -f config-in.tmp config-in.ac~ + +if (cd $1 && autoheader --include=$2 $d/config-in.ac~) > /dev/null; then + rm -rf $1/autom4te.cache config-in.ac~ +else + rm -rf $1/autom4te.cache +# config-in.ac~ fooconfig-h.tmp + echo autoheader failed, eek + exit 1 +fi + +awk '/^#undef/ { print $2; }' < fooconfig-h.tmp | sort > acsyms.here +rm -f fooconfig-h.tmp +awk '/^#undef/ { print $2; }' < $3 | sort > acsyms.there + +comm -23 acsyms.here acsyms.there > acsyms.extra +rm -f acsyms.here acsyms.there + +if test -s acsyms.extra; then + echo ERROR: Symbol or symbols defined here but not in `basename $3`: `cat acsyms.extra` + rm -f acsyms.extra + exit 1 +fi +rm -f acsyms.extra +exit 0 diff --git a/krb5-1.21.3/src/util/cstyle-file.py b/krb5-1.21.3/src/util/cstyle-file.py new file mode 100644 index 00000000..837fa05e --- /dev/null +++ b/krb5-1.21.3/src/util/cstyle-file.py @@ -0,0 +1,323 @@ +# Copyright (C) 2012 by the Massachusetts Institute of Technology. +# All rights reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +# This program checks for some kinds of MIT krb5 coding style +# violations in a single file. Checked violations include: +# +# Line is too long +# Tabs violations +# Trailing whitespace and final blank lines +# Comment formatting errors +# Preprocessor statements in function bodies +# Misplaced braces +# Space before paren in function call, or no space after if/for/while +# Parenthesized return expression +# Space after cast operator, or no space before * in cast operator +# Line broken before binary operator +# Lack of spaces around binary operator (sometimes) +# Assignment at the beginning of an if conditional +# Use of prohibited string functions +# Lack of braces around 2+ line flow control body +# Incorrect indentation as determined by emacs c-mode (if possible) +# +# This program does not check for the following: +# +# Anything outside of a function body except line length/whitespace +# Anything non-syntactic (proper cleanup flow control, naming, etc.) +# UTF-8 violations +# Implicit tests against NULL or '\0' +# Inner-scope variable declarations +# Over- or under-parenthesization +# Long or deeply nested function bodies +# Syntax of function calls through pointers + +import os +import re +import sys +from subprocess import call +from tempfile import NamedTemporaryFile + +def warn(ln, msg): + print('%5d %s' % (ln, msg)) + + +# If lines[0] indicates the krb5 C style, try to use emacs to reindent +# a copy of lines. Return None if the file does not use the krb5 C +# style or if the emacs batch reindent is unsuccessful. +def emacs_reindent(lines): + if 'c-basic-offset: 4; indent-tabs-mode: nil' not in lines[0]: + return None + + util_dir = os.path.dirname(sys.argv[0]) + cstyle_el = os.path.join(util_dir, 'krb5-c-style.el') + reindent_el = os.path.join(util_dir, 'krb5-batch-reindent.el') + with NamedTemporaryFile(suffix='.c', mode='w+') as f: + f.write(''.join(lines)) + f.flush() + args = ['emacs', '-q', '-batch', '-l', cstyle_el, '-l', reindent_el, + f.name] + with open(os.devnull, 'w') as devnull: + try: + st = call(args, stdin=devnull, stdout=devnull, stderr=devnull) + if st != 0: + return None + except OSError: + # Fail gracefully if emacs isn't installed. + return None + f.seek(0) + ilines = f.readlines() + f.close() + return ilines + + +def check_length(line, ln): + if len(line) > 79 and not line.startswith(' * Copyright'): + warn(ln, 'Length exceeds 79 characters') + + +def check_tabs(line, ln, allow_tabs, seen_tab): + if not allow_tabs: + if '\t' in line: + warn(ln, 'Tab character in file which does not allow tabs') + else: + if ' \t' in line: + warn(ln, 'Tab character immediately following space') + if ' ' in line and seen_tab: + warn(ln, '8+ spaces in file which uses tabs') + + +def check_trailing_whitespace(line, ln): + if line and line[-1] in ' \t': + warn(ln, 'Trailing whitespace') + + +def check_comment(lines, ln): + align = lines[0].index('/*') + 1 + if not lines[0].lstrip().startswith('/*'): + warn(ln, 'Multi-line comment begins after code') + for line in lines[1:]: + ln += 1 + if len(line) <= align or line[align] != '*': + warn(ln, 'Comment line does not have * aligned with top') + elif line[:align].lstrip() != '': + warn(ln, 'Garbage before * in comment line') + if not lines[-1].rstrip().endswith('*/'): + warn(ln, 'Code after end of multi-line comment') + if len(lines) > 2 and (lines[0].strip() not in ('/*', '/**') or + lines[-1].strip() != '*/'): + warn(ln, 'Comment is 3+ lines but is not formatted as block comment') + + +def check_preprocessor(line, ln): + if line.startswith('#'): + warn(ln, 'Preprocessor statement in function body') + + +def check_braces(line, ln): + # Strip out one-line initializer expressions. + line = re.sub(r'=\s*{.*}', '', line) + if line.lstrip().startswith('{') and not line.startswith('{'): + warn(ln, 'Un-cuddled open brace') + if re.search(r'{\s*\S', line): + warn(ln, 'Code on line after open brace') + if re.search(r'\S.*}', line): + warn(ln, 'Code on line before close brace') + + +# This test gives false positives on some function pointer type +# declarations or casts. Avoid this by using typedefs. +def check_space_before_paren(line, ln): + for m in re.finditer(r'([\w]+)(\s*)\(', line): + ident, ws = m.groups() + if ident in ('void', 'char', 'int', 'long', 'unsigned'): + pass + elif ident in ('if', 'for', 'while', 'switch'): + if not ws: + warn(ln, 'No space after flow control keyword') + elif ident != 'return': + if ws: + warn(ln, 'Space before parenthesis in function call') + + if re.search(r' \)', line): + warn(ln, 'Space before close parenthesis') + + +def check_parenthesized_return(line, ln): + if re.search(r'return\s*\(.*\);', line): + warn(ln, 'Parenthesized return expression') + + +def check_cast(line, ln): + # We can't reliably distinguish cast operators from parenthesized + # expressions or function call parameters without a real C parser, + # so we use some heuristics. A cast operator is followed by an + # expression, which usually begins with an identifier or an open + # paren. A function call or parenthesized expression is never + # followed by an identifier and only rarely by an open paren. We + # won't detect a cast operator when it's followed by an expression + # beginning with '*', since it's hard to distinguish that from a + # multiplication operator. We will get false positives from + # "(*fp) (args)" and "if (condition) statement", but both of those + # are erroneous anyway. + for m in re.finditer(r'\(([^(]+)\)(\s*)[a-zA-Z_(]', line): + if m.group(2): + warn(ln, 'Space after cast operator (or inline if/while body)') + # Check for casts like (char*) which should have a space. + if re.search(r'[^\s\*]\*+$', m.group(1)): + warn(ln, 'No space before * in cast operator') + + +def check_binary_operator(line, ln): + binop = r'(\+|-|\*|/|%|\^|==|=|!=|<=|<|>=|>|&&|&|\|\||\|)' + if re.match(r'\s*' + binop + r'\s', line): + warn(ln - 1, 'Line broken before binary operator') + for m in re.finditer(r'(\s|\w)' + binop + r'(\s|\w)', line): + before, op, after = m.groups() + if not before.isspace() and not after.isspace(): + warn(ln, 'No space before or after binary operator') + elif not before.isspace(): + warn(ln, 'No space before binary operator') + elif op not in ('-', '*', '&') and not after.isspace(): + warn(ln, 'No space after binary operator') + + +def check_assignment_in_conditional(line, ln): + # Check specifically for if statements; we allow assignments in + # loop expressions. + if re.search(r'if\s*\(+\w+\s*=[^=]', line): + warn(ln, 'Assignment in if conditional') + + +def indent(line): + return len(re.match('\s*', line).group(0).expandtabs()) + + +def check_unbraced_flow_body(line, ln, lines): + if re.match(r'\s*do$', line): + warn(ln, 'do statement without braces') + return + + m = re.match(r'\s*(})?\s*else(\s*if\s*\(.*\))?\s*({)?\s*$', line) + if m and (m.group(1) is None) != (m.group(3) is None): + warn(ln, 'One arm of if/else statement braced but not the other') + + if (re.match('\s*(if|else if|for|while)\s*\(.*\)$', line) or + re.match('\s*else$', line)): + base = indent(line) + # Look at the next two lines (ln is 1-based so lines[ln] is next). + if indent(lines[ln]) > base and indent(lines[ln + 1]) > base: + warn(ln, 'Body is 2+ lines but has no braces') + + +def check_bad_string_fn(line, ln): + # This is intentionally pretty fuzzy so that we catch the whole scanf + if re.search(r'\W(strcpy|strcat|sprintf|\w*scanf)\W', line): + warn(ln, 'Prohibited string function') + + +def check_indentation(line, indented_lines, ln): + if not indented_lines: + return + + if ln - 1 >= len(indented_lines): + # This should only happen when the emacs reindent removed + # blank lines from the input file, but check. + if line.strip() == '': + warn(ln, 'Trailing blank line') + return + + if line != indented_lines[ln - 1].rstrip('\r\n'): + warn(ln, 'Indentation may be incorrect') + + +def check_file(lines): + # Check if this file allows tabs. + if len(lines) == 0: + return + allow_tabs = 'indent-tabs-mode: nil' not in lines[0] + seen_tab = False + indented_lines = emacs_reindent(lines) + + in_function = False + comment = [] + ln = 0 + for line in lines: + ln += 1 + line = line.rstrip('\r\n') + seen_tab = seen_tab or ('\t' in line) + + # Check line structure issues before altering the line. + check_indentation(line, indented_lines, ln) + check_length(line, ln) + check_tabs(line, ln, allow_tabs, seen_tab) + check_trailing_whitespace(line, ln) + + # Strip out single-line comments the contents of string literals. + if not comment: + line = re.sub(r'/\*.*?\*/', '', line) + line = re.sub(r'"(\\.|[^"])*"', '""', line) + + # Parse out and check multi-line comments. (Ignore code on + # the first or last line; check_comment will warn about it.) + if comment or '/*' in line: + comment.append(line) + if '*/' in line: + check_comment(comment, ln - len(comment) + 1) + comment = [] + continue + + # Warn if we see a // comment and ignore anything following. + if '//' in line: + warn(ln, '// comment') + line = re.sub(r'//.*/', '', line) + + if line.startswith('{'): + in_function = True + elif line.startswith('}'): + in_function = False + + if in_function: + check_preprocessor(line, ln) + check_braces(line, ln) + check_space_before_paren(line, ln) + check_parenthesized_return(line, ln) + check_cast(line, ln) + check_binary_operator(line, ln) + check_assignment_in_conditional(line, ln) + check_unbraced_flow_body(line, ln, lines) + check_bad_string_fn(line, ln) + + if lines[-1] == '': + warn(ln, 'Blank line at end of file') + + +if len(sys.argv) == 1: + lines = sys.stdin.readlines() +elif len(sys.argv) == 2: + f = open(sys.argv[1]) + lines = f.readlines() + f.close() +else: + sys.stderr.write('Usage: cstyle-file [filename]\n') + sys.exit(1) + +check_file(lines) diff --git a/krb5-1.21.3/src/util/cstyle.py b/krb5-1.21.3/src/util/cstyle.py new file mode 100644 index 00000000..c485d3ff --- /dev/null +++ b/krb5-1.21.3/src/util/cstyle.py @@ -0,0 +1,188 @@ +# Copyright (C) 2012 by the Massachusetts Institute of Technology. +# All rights reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. + +# This program attempts to detect MIT krb5 coding style violations +# attributable to the changes a series of git commits. It can be run +# from anywhere within a git working tree. + +import getopt +import os +import re +import sys +from subprocess import Popen, PIPE, call + +def usage(): + u = ['Usage: cstyle [-w] [rev|rev1..rev2]', + '', + 'By default, checks working tree against HEAD, or checks changes in', + 'HEAD if the working tree is clean. With a revision option, checks', + 'changes in rev or the series rev1..rev2. With the -w option,', + 'checks working tree against rev (defaults to HEAD).'] + sys.stderr.write('\n'.join(u) + '\n') + sys.exit(1) + + +# Run a command and return a list of its output lines. +def run(args): + # subprocess.check_output would be ideal here, but requires Python 2.7. + p = Popen(args, stdout=PIPE, stderr=PIPE, universal_newlines=True) + out, err = p.communicate() + if p.returncode != 0: + sys.stderr.write('Failed command: ' + ' '.join(args) + '\n') + if err != '': + sys.stderr.write('stderr:\n' + err) + sys.stderr.write('Unexpected command failure, exiting\n') + sys.exit(1) + return out.splitlines() + + +# Find the top level of the git working tree, or None if we're not in +# one. +def find_toplevel(): + # git doesn't seem to have a way to do this, so we search by hand. + dir = os.getcwd() + while True: + if os.path.exists(os.path.join(dir, '.git')): + break + parent = os.path.dirname(dir) + if (parent == dir): + return None + dir = parent + return dir + + +# Check for style issues in a file within rev (or within the current +# checkout if rev is None). Report only problems on line numbers in +# new_lines. +line_re = re.compile(r'^\s*(\d+) (.*)$') +def check_file(filename, rev, new_lines): + # Process only C source files under src. + root, ext = os.path.splitext(filename) + if not filename.startswith('src/') or ext not in ('.c', '.h', '.hin'): + return + dispname = filename[4:] + + if rev is None: + p1 = Popen(['cat', filename], stdout=PIPE) + else: + p1 = Popen(['git', 'show', rev + ':' + filename], stdout=PIPE) + p2 = Popen([sys.executable, 'src/util/cstyle-file.py'], stdin=p1.stdout, + stdout=PIPE, universal_newlines=True) + p1.stdout.close() + out, err = p2.communicate() + if p2.returncode != 0: + sys.exit(1) + + first = True + for line in out.splitlines(): + m = line_re.match(line) + if int(m.group(1)) in new_lines: + if first: + print(' ' + dispname + ':') + first = False + print(' ' + line) + + +# Determine the lines of each file modified by diff (a sequence of +# strings) and check for style violations in those lines. rev +# indicates the version in which the new contents of each file can be +# found, or is None if the current contents are in the working copy. +chunk_header_re = re.compile(r'^@@ -\d+(,(\d+))? \+(\d+)(,(\d+))? @@') +def check_diff(diff, rev): + old_count, new_count, lineno = 0, 0, 0 + filename = None + for line in diff: + if not line or line.startswith('\\ No newline'): + continue + if old_count > 0 or new_count > 0: + # We're in a chunk. + if line[0] == '+': + new_lines.append(lineno) + if line[0] in ('+', ' '): + new_count = new_count - 1 + lineno = lineno + 1 + if line[0] in ('-', ' '): + old_count = old_count - 1 + elif line.startswith('+++ b/'): + # We're starting a new file. Check the last one. + if filename: + check_file(filename, rev, new_lines) + filename = line[6:] + new_lines = [] + else: + m = chunk_header_re.match(line) + if m: + old_count = int(m.group(2) or '1') + lineno = int(m.group(3)) + new_count = int(m.group(5) or '1') + + # Check the last file in the diff. + if filename: + check_file(filename, rev, new_lines) + + +# Check a sequence of revisions for style issues. +def check_series(revlist): + for rev in revlist: + sys.stdout.flush() + call(['git', 'show', '-s', '--oneline', rev]) + diff = run(['git', 'diff-tree', '--no-commit-id', '--root', '-M', + '--cc', rev]) + check_diff(diff, rev) + + +# Parse arguments. +try: + opts, args = getopt.getopt(sys.argv[1:], 'w') +except getopt.GetoptError as err: + print(str(err)) + usage() +if len(args) > 1: + usage() + +# Change to the top level of the working tree so we easily run the file +# checker and refer to working tree files. +toplevel = find_toplevel() +if toplevel is None: + sys.stderr.write('%s must be run within a git working tree') +os.chdir(toplevel) + +if ('-w', '') in opts: + # Check the working tree against a base revision. + arg = 'HEAD' + if args: + arg = args[0] + check_diff(run(['git', 'diff', arg]), None) +elif args: + # Check the differences in a rev or a series of revs. + if '..' in args[0]: + check_series(run(['git', 'rev-list', '--reverse', args[0]])) + else: + check_series([args[0]]) +else: + # No options or arguments. Check the differences against HEAD, or + # the differences in HEAD if the working tree is clean. + diff = run(['git', 'diff', 'HEAD']) + if diff: + check_diff(diff, None) + else: + check_series(['HEAD']) diff --git a/krb5-1.21.3/src/util/def-check.pl b/krb5-1.21.3/src/util/def-check.pl new file mode 100644 index 00000000..ccdf8ef1 --- /dev/null +++ b/krb5-1.21.3/src/util/def-check.pl @@ -0,0 +1,265 @@ +#!/usr/athena/bin/perl -w + +# Code initially generated by s2p +# Code modified to use strict and IO::File + +eval 'exec /usr/athena/bin/perl -S $0 ${1+"$@"}' + if 0; # line above evaluated when running under some shell (i.e., not perl) + +use strict; +use IO::File; + +my $verbose = 0; +my $error = 0; +if ( $ARGV[0] eq "-v" ) { $verbose = 1; shift @ARGV; } +my $h_filename = shift @ARGV || die "usage: $0 [-v] header-file [def-file]\n"; +my $d_filename = shift @ARGV; + +my $h = open_always($h_filename); +my $d = open_always($d_filename) if $d_filename; + +sub open_always +{ + my $file = shift || die; + my $handle = new IO::File "<$file"; + die "Could not open $file\n" if !$handle; + return $handle; +} + +my @convW = (); +my @convC = (); +my @convK = (); +my @convD = (); +my @vararg = (); + +my $len1; +my %conv; +my $printit; +my $vararg; + +LINE: +while (! $h->eof()) { + $_ = $h->getline(); + chop; + # get calling convention info for function decls + # what about function pointer typedefs? + # need to verify unhandled syntax actually triggers a report, not ignored + # blank lines + if (/^[ \t]*$/) { + next LINE; + } + Top: + # drop KRB5INT_BEGIN_DECLS and KRB5INT_END_DECLS + if (/^ *(KRB5INT|GSSAPI[A-Z]*)_(BEGIN|END)_DECLS/) { + next LINE; + } + # drop preprocessor directives + if (/^ *#/) { + while (/\\$/) { $_ .= $h->getline(); } + next LINE; + } + if (/^ *\?==/) { + next LINE; + } + s/#.*$//; + if (/^\} *$/) { + next LINE; + } + # strip comments + Cloop1: + if (/\/\*./) { + s;/\*[^*]*;/*;; + s;/\*\*([^/]);/*$1;; + s;/\*\*$;/*;; + s;/\*\*/; ;g; + goto Cloop1; + } + # multi-line comments? + if (/\/\*$/) { + $_ .= " "; + $len1 = length; + $_ .= $h->getline(); + chop if $len1 < length; + goto Cloop1 if /\/\*./; + } + # blank lines + if (/^[ \t]*$/) { + next LINE; + } + if (/^ *extern "C" \{/) { + next LINE; + } + s/KRB5_ATTR_DEPRECATED//; + # elide struct definitions + Struct1: + if (/\{[^}]*\}/) { + s/\{[^}]*\}/ /g; + goto Struct1; + } + # multi-line defs + if (/\{/) { + $_ .= "\n"; + $len1 = length; + $_ .= $h->getline(); + chop if $len1 < length; + goto Struct1; + } + Semi: + unless (/;/) { + $_ .= "\n"; + $len1 = length; + $_ .= $h->getline(); + chop if $len1 < length; + s/\n/ /g; + s/[ \t]+/ /g; + s/^[ \t]*//; + goto Top; + } + if (/^typedef[^;]*;/) { + s/^typedef[^;]*;//g; + goto Semi; + } + if (/^struct[^\(\)]*;/) { + s/^struct[^\(\)]*;//g; + goto Semi; + } + # should just have simple decls now; split lines at semicolons + s/ *;[ \t]*$//; + s/ *;/\n/g; + if (/^[ \t]*$/) { + next LINE; + } + s/[ \t]*$//; + goto Notfunct unless /\(.*\)/; + # Get rid of KRB5_PROTOTYPE + s/KRB5_PROTOTYPE//; + s/KRB5_STDARG_P//; + # here, is probably function decl + # strip simple arg list - parens, no parens inside; discard, iterate. + # the iteration should deal with function pointer args. + $vararg = /\.\.\./; + Striparg: + if (/ *\([^\(\)]*\)/) { + s/ *\([^\(\)]*\)//g; + goto Striparg; + } + # Also strip out attributes, or what's left over of them. + if (/__attribute__/) { + s/[ \t]*__attribute__[ \t]*//g; + goto Striparg; + } + # replace return type etc with one token indicating calling convention + if (/CALLCONV/) { + if (/\bKRB5_CALLCONV_WRONG\b/) { + s/^.*KRB5_CALLCONV_WRONG *//; + die "Invalid function name: '$_'" if (!/^[A-Za-z0-9_]+$/); + push @convW, $_; + push @vararg, $_ if $vararg; + } elsif (/\bKRB5_CALLCONV_C\b/) { + s/^.*KRB5_CALLCONV_C *//; + die "Invalid function name: '$_'" if (!/^[A-Za-z0-9_]+$/); + push @convC, $_; + push @vararg, $_ if $vararg; + } elsif (/\bKRB5_CALLCONV\b/) { + s/^.*KRB5_CALLCONV *//; + die "Invalid function name: '$_'" if (!/^[A-Za-z0-9_]+$/); + push @convK, $_; + push @vararg, $_ if $vararg; + } else { + die "Unrecognized calling convention while parsing: '$_'\n"; + } + goto Hadcallc; + } + # deal with no CALLCONV indicator + s/^.* \**(\w+) *$/$1/; + die "Invalid function name: '$_'" if (!/^[A-Za-z0-9_]+$/); + push @convD, $_; + push @vararg, $_ if $vararg; + Hadcallc: + goto Skipnotf; + Notfunct: + # probably a variable + s/^/VARIABLE_DECL /; + Skipnotf: + # toss blank lines + if (/^[ \t]*$/) { + next LINE; + } +} + +if ( $verbose ) { + print join("\n\t", "Using default calling convention:", sort(@convD)); + print join("\n\t", "\nUsing KRB5_CALLCONV:", sort(@convK)); + print join("\n\t", "\nUsing KRB5_CALLCONV_C:", sort(@convC)); + print join("\n\t", "\nUsing KRB5_CALLCONV_WRONG:", sort(@convW)); + print "\n","-"x70,"\n"; +} + +%conv = (); +map { $conv{$_} = "default"; } @convD; +map { $conv{$_} = "KRB5_CALLCONV"; } @convK; +map { $conv{$_} = "KRB5_CALLCONV_C"; } @convC; +map { $conv{$_} = "KRB5_CALLCONV_WRONG"; } @convW; + +my %vararg = (); +map { $vararg{$_} = 1; } @vararg; + +if (!$d) { + print "No .DEF file specified\n" if $verbose; + exit 0; +} + +LINE2: +while (! $d->eof()) { + $_ = $d->getline(); + chop; + # + if (/^;/) { + $printit = 0; + next LINE2; + } + if (/^[ \t]*$/) { + $printit = 0; + next LINE2; + } + if (/^EXPORTS/ || /^DESCRIPTION/ || /^HEAPSIZE/) { + $printit = 0; + next LINE2; + } + s/[ \t]*//g; + s/@[0-9]+//; + my($xconv); + if (/PRIVATE/ || /INTERNAL/) { + $xconv = "PRIVATE"; + } elsif (/DATA/) { + $xconv = "DATA"; + } elsif (/!CALLCONV/ || /KRB5_CALLCONV_WRONG/) { + $xconv = "KRB5_CALLCONV_WRONG"; + } elsif ($vararg{$_}) { + $xconv = "KRB5_CALLCONV_C"; + } else { + $xconv = "KRB5_CALLCONV"; + } + s/;.*$//; + + if ($xconv eq "PRIVATE") { + print "\t private $_\n" if $verbose; + next LINE2; + } + if ($xconv eq "DATA") { + print "\t data $_\n" if $verbose; + next LINE2; + } + if (!defined($conv{$_})) { + print "No calling convention specified for $_!\n"; + $error = 1; + } elsif (! ($conv{$_} eq $xconv)) { + print "Function $_ should have calling convention '$xconv', but has '$conv{$_}' instead.\n"; + $error = 1; + } else { +# print "Function $_ is okay.\n"; + } +} + +#print "Calling conventions defined for: ", keys(%conv); +exit $error; diff --git a/krb5-1.21.3/src/util/depfix.pl b/krb5-1.21.3/src/util/depfix.pl new file mode 100644 index 00000000..9982fa0d --- /dev/null +++ b/krb5-1.21.3/src/util/depfix.pl @@ -0,0 +1,216 @@ +#!env perl -w +# +# Copyright 1995,2001,2002,2003,2004,2005,2009 by the Massachusetts Institute of Technology. +# All Rights Reserved. +# +# Export of this software from the United States of America may +# require a specific license from the United States Government. +# It is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of M.I.T. not be used in advertising or publicity pertaining +# to distribution of the software without specific, written prior +# permission. Furthermore if you modify this software you must label +# your software as modified software and not distribute it in such a +# fashion that it might be confused with the original M.I.T. software. +# M.I.T. makes no representations about the suitability of +# this software for any purpose. It is provided "as is" without express +# or implied warranty. +# + +eval 'exec perl -S $0 ${1+"$@"}' + if 0; +$0 =~ s/^.*?(\w+)[\.\w+]*$/$1/; + +# Input: srctop thisdir srcdir buildtop stlibobjs + +# Notes: myrelativedir is something like "lib/krb5/asn.1" or ".". +# stlibobjs will usually be empty, or include spaces. + +# A typical set of inputs, produced with srcdir=.. at top level: +# +# top_srcdir = ../../../util/et/../.. +# thisdir = util/et +# srcdir = ../../../util/et +# BUILDTOP = ../.. +# STLIBOBJS = error_message.o et_name.o com_err.o + +my($top_srcdir,$thisdir,$srcdir,$BUILDTOP,$STLIBOBJS) = @ARGV; + +if (0) { + print STDERR "top_srcdir = $top_srcdir\n"; + print STDERR "BUILDTOP = $BUILDTOP\n"; + print STDERR "STLIBOBJS = $STLIBOBJS\n"; +} + +#$srcdirpat = quotemeta($srcdir); + +my($extrasuffixes) = ($STLIBOBJS ne ""); + +sub my_qm { + my($x) = @_; + $x = quotemeta($x); + $x =~ s,\\/,/,g; + return $x; +} + +sub strrep { + my($old,$new,$s) = @_; + my($l) = "strrep('$old','$new','$s')"; + my($out) = ""; + while ($s ne "") { + my($i) = index($s, $old); + if ($i == -1) { + $out .= $s; + $s = ""; + } else { + $out .= substr($s, 0, $i) . $new; + if (length($s) > $i + length($old)) { + $s = substr($s, $i + length($old)); + } else { + $s = ""; + } + } + } +# print STDERR "$l = '$out'\n"; + return $out; +} + +sub do_subs { + local($_) = @_; + s,\\$, \\,g; s, + \\$, \\,g; + s,//+,/,g; s, \./, ,g; + if ($extrasuffixes) { + # Only care about the additional prefixes if we're building + # shared libraries. + s,^([a-zA-Z0-9_\-]*)\.o:,$1.so $1.po \$(OUTPRE)$1.\$(OBJEXT):,; + } else { + s,^([a-zA-Z0-9_\-]*)\.o:,\$(OUTPRE)$1.\$(OBJEXT):,; + } + # Recognize $(top_srcdir) and variants. + my($srct) = $top_srcdir . "/"; + $_ = strrep(" $srct", " \$(top_srcdir)/", $_); +# s, $pat, \$(top_srcdir)/,go; + while ($srct =~ m,/[a-z][a-zA-Z0-9_.\-]*/\.\./,) { + $srct =~ s,/[a-z][a-zA-Z0-9_.\-]*/\.\./,/,; + $_ = strrep(" $srct", " \$(top_srcdir)/", $_); + } + # Now try to produce pathnames relative to $(srcdir). + if ($thisdir eq ".") { + # blah + } else { + my($pat) = " \$(top_srcdir)/$thisdir/"; + my($out) = " \$(srcdir)/"; + $_ = strrep($pat, $out, $_); + while ($pat =~ m,/[a-z][a-zA-Z0-9_.\-]*/$,) { + $pat =~ s,/[a-z][a-zA-Z0-9_.\-]*/$,/,; + $out .= "../"; + if ($pat ne " \$(top_srcdir)/") { + $_ = strrep($pat, $out, $_); + } + } + } + # Now substitute for BUILDTOP: + $_ = strrep(" $BUILDTOP/", " \$(BUILDTOP)/", $_); + return $_; +} + +sub do_subs_2 { + local($_) = @_; + # Add a trailing space. + s/$/ /; + # Remove excess spaces. + s/ */ /g; + # Delete headers external to the source and build tree. + s; /[^ ]*;;g; + # Remove foo/../ sequences. + while (m/\/[a-z][a-z0-9_.\-]*\/\.\.\//) { + s//\//g; + } + # Use VPATH. + s;\$\(srcdir\)/([^ /]* );$1;g; + + $_ = &uniquify($_); + + # Allow override of some util dependencies in case local tools are used. + s;\$\(BUILDTOP\)/include/com_err.h ;\$(COM_ERR_DEPS) ;g; + s;\$\(BUILDTOP\)/include/ss/ss.h \$\(BUILDTOP\)/include/ss/ss_err.h ;\$(SS_DEPS) ;g; + s;\$\(BUILDTOP\)/include/db-config.h \$\(BUILDTOP\)/include/db.h ;\$(DB_DEPS) ;g; + s;\$\(BUILDTOP\)/include/verto.h ;\$(VERTO_DEPS) ;g; + if ($thisdir eq "util/gss-kernel-lib") { + # Here com_err.h is used from the current directory. + s;com_err.h ;\$(COM_ERR_DEPS) ;g; + } + if ($thisdir eq "lib/krb5/ccache") { + # These files are only used (and kcmrpc.h only generated) on macOS. + # There are conditional dependencies in Makefile.in. + s;kcmrpc.h ;;g; + s;kcmrpc_types.h ;;g; + } + + $_ = &uniquify($_); + + # Delete trailing whitespace. + s; *$;;g; + + return $_; +} + +sub uniquify { + # Apparently some versions of gcc -- like + # "gcc version 3.4.4 20050721 (Red Hat 3.4.4-2)" + # -- will sometimes emit duplicate header file names. + local($_) = @_; + my(@sides) = split ": ", $_; + my($lhs) = ""; + if ($#sides == 1) { + $lhs = $sides[0] . ": "; + $_ = $sides[1]; + } + my(@words) = split " ", $_; + my($w); + my($result) = ""; + my(%seen); + undef %seen; + foreach $w (sort { $a cmp $b; } @words) { + next if defined($seen{$w}); + $seen{$w} = 1; + if ($result ne "") { $result .= " "; } + $result .= $w; + } + return $lhs . $result . " "; +} + +sub split_lines { + local($_) = @_; + s/(.{50}[^ ]*) /$1 \\\n /g; + return $_ . "\n"; +} + +print <) { + # Strip newline. + chop; + next if /^\s*#/; + # Do directory-specific path substitutions on each filename read. + $_ = &do_subs($_); + if (m/\\$/) { + chop; + $buf .= $_; + } else { + $buf = &do_subs_2($buf . $_); + print &split_lines($buf); + $buf = ''; + } +} +exit 0; diff --git a/krb5-1.21.3/src/util/deps b/krb5-1.21.3/src/util/deps new file mode 100644 index 00000000..2feac3c9 --- /dev/null +++ b/krb5-1.21.3/src/util/deps @@ -0,0 +1 @@ +# No dependencies here. diff --git a/krb5-1.21.3/src/util/et/ISSUES b/krb5-1.21.3/src/util/et/ISSUES new file mode 100644 index 00000000..48317eca --- /dev/null +++ b/krb5-1.21.3/src/util/et/ISSUES @@ -0,0 +1,64 @@ +Issues to be addressed for src/util/et: -*- text -*- + + +Non-thread-safe aspects: + +error_message uses a static buffer for "unknown error code" messages; +a per-thread buffer may be better, but that depends on dynamic +allocation working. A caller-provided buffer would be best, but +that's a API change. + +initialize_foo_error_table uses a global linked list hung off an +unprotected variable in the library. {add,remove}_error_table do +likewise, but can be changed without externally visible effect. + +Workaround: Use a global lock for all calls to error_message and +com_err, and when adding or removing error tables. + + +API divergence: + +Transarc and Heimdal both have APIs that are different from this +version. (Specifics?) + +Karl Ramm has offered to try to combine them. + +Workaround: + + +Reference counting: + +If libraries are dynamically loaded and unloaded, and the init/fini +functions add and remove error tables for *other* libraries they +depend on (e.g., if a dynamically loadable Zephyr library's fini +function removes the krb4 library error table and then dlcloses the +krb4 library, while another dlopen reference keeps the krb4 library +around), the error table is kept; a table must be removed the same +number of times it was added before the library itself can be +discarded. + +It's not implemented as a reference count, but the effect is the same. + +Fix needed: Update documentation. + + +64-bit support: + +Values are currently computed as 32-bit values, sign-extended to +"long", and output with "L" suffixes. Type errcode_t is "long". +Kerberos uses a separately chosen signed type of at least 32 bits for +error codes. The com_err library only look at the low 32 bits, so +this is mostly just an issue for application code -- if anything +truncates to 32 bits, and then widens without sign-extending, the +value may not compare equal to the macro defined in the .h file. This +isn't anything unusual for signed constants, of course, just something +to keep in mind.... + +Workaround: Always use signed types of at least 32 bits for error +codes. + + +man page: + +No documentation on add_error_table/remove_error_table interfaces, +even though they're the new, preferred interface. diff --git a/krb5-1.21.3/src/util/et/Makefile.in b/krb5-1.21.3/src/util/et/Makefile.in new file mode 100644 index 00000000..47fde03e --- /dev/null +++ b/krb5-1.21.3/src/util/et/Makefile.in @@ -0,0 +1,181 @@ +prefix=@prefix@ +bindir=@bindir@ +datadir=@datadir@ +mydatadir=$(datadir)/et +mydir=util$(S)et +BUILDTOP=$(REL)..$(S).. +RELDIR=../util/et +SED = sed + +##DOS##BUILDTOP = ..\.. +##DOS##LIBNAME=$(OUTPRE)comerr.lib +##DOS##XTRA= +##DOS##OBJFILE=$(OUTPRE)comerr.lst + +STLIBOBJS=error_message.o et_name.o com_err.o +LIBBASE=com_err +LIBMAJOR=3 +LIBMINOR=0 +LIBINITFUNC=com_err_initialize +LIBFINIFUNC=com_err_terminate + +all-unix: all-liblinks +clean-unix:: clean-liblinks clean-libs clean-libobjs +install-unix: install-libs + +LINTFLAGS=-uhvb +LINTFILES= error_message.c et_name.c com_err.c +LIBOBJS=$(OUTPRE)com_err.$(OBJEXT) \ + $(OUTPRE)error_message.$(OBJEXT) \ + $(OUTPRE)et_name.$(OBJEXT) +LOCALINCLUDES=-I. + +SRCS= $(srcdir)/error_message.c \ + $(srcdir)/et_name.c \ + $(srcdir)/com_err.c + +# +# Warning flags +# +# Uncomment WFLAGS if you want really anal GCC warning messages +# +# +WFLAGS= -ansi -D_POSIX_SOURCE -pedantic \ + -Wall -Wwrite-strings -Wpointer-arith \ + -Wcast-qual -Wcast-align -Wtraditional \ + -Wstrict-prototypes -Wmissing-prototypes \ + -Wnested-externs -Winline -DNO_INLINE_FUNCS -Wshadow + +DEPLIBS= +SHLIB_LIBS= +SHLIB_EXPDEPS = $(SUPPORT_DEPLIB) +SHLIB_EXPLIBS=-l$(SUPPORT_LIBNAME) $(LIBS) +SHLIB_LDFLAGS= $(LDFLAGS) @SHLIB_RPATH_DIRS@ + +COM_ERR_HDR=$(BUILDTOP)$(S)include$(S)com_err.h + +all-windows: $(COM_ERR_HDR) + +$(COM_ERR_HDR): com_err.h + $(CP) com_err.h "$@" + +generate-files-mac: compile_et + +com_err.o : com_err.c + +test1.o: test1.c +test2.o: test2.c +test_et.o: test1.h test2.h +et1.o: et1.c +et2.o: et2.c +test1.c test2.c et1.c et2.c test1.h test2.h et1.h et2.h: \ + compile_et et_c.awk et_h.awk +t_com_err.o: et1.h et2.h t_com_err.c + +#test_et: test_et.o test1.o test2.o $(LIBOBJS) +# $(CC) -o test_et test_et.o test1.o test2.o $(LIBOBJS) +#t_com_err: t_com_err.o et1.o et2.o $(LIBOBJS) +# $(CC) -o t_com_err t_com_err.o et1.o et2.o $(LIBOBJS) + +test_et: test_et.o test1.o test2.o $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB) + $(CC_LINK) -o test_et test_et.o test1.o test2.o $(COM_ERR_LIB) $(SUPPORT_LIB) +t_com_err: t_com_err.o et1.o et2.o $(COM_ERR_DEPLIB) $(SUPPORT_DEPLIB) + $(CC_LINK) -o t_com_err t_com_err.o et1.o et2.o $(COM_ERR_LIB) $(SUPPORT_LIB) + +$(OUTPRE)test_et.exe: $(OUTPRE)test_et.$(OBJEXT) $(OUTPRE)test1.$(OBJEXT) \ + $(OUTPRE)test2.$(OBJEXT) $(CLIB) + link $(EXE_LINKOPTS) -out:$(OUTPRE)test_et$(EXEEXT) $** + +all-unix: compile_et includes + +includes: com_err.h + if cmp $(srcdir)/com_err.h \ + $(BUILDTOP)/include/com_err.h >/dev/null 2>&1; then :; \ + else \ + (set -x; $(RM) $(BUILDTOP)/include/com_err.h; \ + $(CP) $(srcdir)/com_err.h \ + $(BUILDTOP)/include/com_err.h) ; \ + fi + +clean-unix:: + $(RM) $(BUILDTOP)/include/com_err.h + +# test_et doesn't have an interesting exit status, but it'll exercise +# some cases that t_com_err doesn't, so let's see if it crashes. +check-unix: t_com_err test_et + $(RUN_TEST) ./test_et + $(RUN_TEST) ./t_com_err + +check-windows: $(OUTPRE)test_et$(EXEEXT) + set path=$(BUILDTOP)\lib\$(OUTPRE);%path%; + path + $(OUTPRE)test_et$(EXEEXT) + +install-unix: compile_et compile_et.1 + $(INSTALL) compile_et $(DESTDIR)$(bindir)/compile_et + test -d $(DESTDIR)$(mydatadir) || mkdir $(DESTDIR)$(mydatadir) + $(INSTALL_DATA) $(srcdir)/et_c.awk $(DESTDIR)$(mydatadir) + $(INSTALL_DATA) $(srcdir)/et_h.awk $(DESTDIR)$(mydatadir) + $(INSTALL_DATA) $(srcdir)/compile_et.1 $(DESTDIR)$(CLIENT_MANDIR)/compile_et.1 + + +install-headers: compile_et + +compile_et: $(srcdir)/compile_et.sh $(srcdir)/config_script + $(SHELL) $(srcdir)/config_script $(srcdir)/compile_et.sh \ + "$(mydatadir)" $(AWK) $(SED) > compile_et + chmod 755 compile_et + +rebuild: rebuild-c rebuild-h +rebuild-c: + a2p < $(srcdir)/et_c.awk | awk 'NR != 1 || $$0 !~ /^\043!/{print;}' > $(srcdir)/et_c.tmp + mv -f $(srcdir)/et_c.tmp $(srcdir)/et_c.pl +rebuild-h: + a2p < $(srcdir)/et_h.awk | awk 'NR != 1 || $$0 !~ /^\043!/{print;}' > $(srcdir)/et_h.tmp + mv -f $(srcdir)/et_h.tmp $(srcdir)/et_h.pl + +clean-unix:: + $(RM) compile_et + +depend: + +install: com_err.h + $(INSTALL_DATA) $(srcdir)/com_err.h $(DESTDIR)$(KRB5_INCDIR)/com_err.h + + +## install_library_target(com_err,$(LIBOBJS),$(LINTFILES),) + +clean-unix:: clean-files + +clean-files: + rm -f *~ \#* *.bak \ + *.otl *.aux *.toc *.PS *.dvi *.x9700 *.ps \ + *.cp *.fn *.ky *.log *.pg *.tp *.vr \ + *.o profiled/?*.o libcom_err.a libcom_err_p.a \ + com_err.o compile_et \ + et.ar TAGS \ + test1.h test1.c test2.h test2.c test_et \ + et1.c et1.h et2.c et2.h t_com_err \ + eddep makedep *.ln + +clean-windows:: + $(RM) $(COM_ERR_HDR) + +com_err.ps : com_err.dvi +com_err.dvi: com_err.texinfo + +libcom_err.o: $(LIBOBJS) + ld -r -s -o libcom_err.o $(LIBOBJS) + chmod -x libcom_err.o + +archive: et.tar + +TAGS: et_name.c error_message.c + etags et_name.c error_message.c + +depend: includes compile_et + + +@lib_frag@ +@libobj_frag@ + diff --git a/krb5-1.21.3/src/util/et/com_err.3 b/krb5-1.21.3/src/util/et/com_err.3 new file mode 100644 index 00000000..d4704342 --- /dev/null +++ b/krb5-1.21.3/src/util/et/com_err.3 @@ -0,0 +1,96 @@ +.\" Copyright (c) 1988 Massachusetts Institute of Technology, +.\" Student Information Processing Board. All rights reserved. +.\" +.\" util/et/com_err.3 +.\" +.TH COM_ERR 3 "22 Nov 1988" SIPB +.SH NAME +com_err \- common error display routine +.SH SYNOPSIS +.nf + #include "com_err.h" +.PP +void com_err (whoami, code, format, ...); + const char *whoami; + long code; + const char *format; +.PP +proc = set_com_err_hook (proc); +.fi +void (* +.I proc +) (const char *, long, const char *, va_list); +.nf +.PP +proc = reset_com_err_hook (); +.PP +void initialize_XXXX_error_table (); +.fi +.SH DESCRIPTION +.I Com_err +displays an error message on the standard error stream +.I stderr +(see +.IR stdio (3S)) +composed of the +.I whoami +string, which should specify the program name or some subportion of +a program, followed by an error message generated from the +.I code +value (derived from +.IR compile_et (1)), +and a string produced using the +.I format +string and any following arguments, in the same style as +.IR fprintf (3). + +The behavior of +.I com_err +can be modified using +.I set_com_err_hook; +this defines a procedure which is called with the arguments passed to +.I com_err, +instead of the default internal procedure which sends the formatted +text to error output. Thus the error messages from a program can all +easily be diverted to another form of diagnostic logging, such as +.IR syslog (3). +.I Reset_com_err_hook +may be used to restore the behavior of +.I com_err +to its default form. Both procedures return the previous ``hook'' +value. These ``hook'' procedures must have the declaration given for +.I proc +above in the synopsis. + +The +.I initialize_XXXX_error_table +routine is generated mechanically by +.IR compile_et (1) +from a source file containing names and associated strings. Each +table has a name of up to four characters, which is used in place of +the +.B XXXX +in the name of the routine. These routines should be called before +any of the corresponding error codes are used, so that the +.I com_err +library will recognize error codes from these tables when they are +used. + +The +.B com_err.h +header file should be included in any source file that uses routines +from the +.I com_err +library; executable files must be linked using +.I ``-lcom_err'' +in order to cause the +.I com_err +library to be included. + +.\" .IR for manual entries +.\" .PP for paragraph breaks + +.SH "SEE ALSO" +compile_et (1), syslog (3). + +Ken Raeburn, "A Common Error Description Library for UNIX". diff --git a/krb5-1.21.3/src/util/et/com_err.c b/krb5-1.21.3/src/util/et/com_err.c new file mode 100644 index 00000000..c1e3be77 --- /dev/null +++ b/krb5-1.21.3/src/util/et/com_err.c @@ -0,0 +1,176 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + * Copyright 1997 by Massachusetts Institute of Technology + * + * Copyright 1987, 1988 by MIT Student Information Processing Board + * + * Permission to use, copy, modify, and distribute this software + * and its documentation for any purpose and without fee is + * hereby granted, provided that the above copyright notice + * appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, + * and that the names of M.I.T. and the M.I.T. S.I.P.B. not be + * used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. and the M.I.T. S.I.P.B. make no representations about + * the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. + */ + +#include +#include +#include + +#include "com_err.h" +#include "error_table.h" + +#if defined(_WIN32) +#include +#endif + +static /*@null@*/ et_old_error_hook_func com_err_hook = 0; +k5_mutex_t com_err_hook_lock = K5_MUTEX_PARTIAL_INITIALIZER; + +#if defined(_WIN32) +BOOL isGuiApp() { + DWORD mypid; + HANDLE myprocess; + mypid = GetCurrentProcessId(); + myprocess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, mypid); + return GetGuiResources(myprocess, 1) > 0; +} +#endif + +static void default_com_err_proc (const char *whoami, errcode_t code, + const char *fmt, va_list ap) +{ +#if defined(_WIN32) + + char errbuf[1024] = ""; + + if (whoami) { + errbuf[sizeof(errbuf) - 1] = '\0'; + strncat (errbuf, whoami, sizeof(errbuf) - 1 - strlen(errbuf)); + strncat (errbuf, ": ", sizeof(errbuf) - 1 - strlen(errbuf)); + } + if (code) { + errbuf[sizeof(errbuf) - 1] = '\0'; + strncat (errbuf, error_message(code), sizeof(errbuf) - 1 - strlen(errbuf)); + strncat (errbuf, " ", sizeof(errbuf) - 1 - strlen(errbuf)); + } + if (fmt) + /* ITS4: ignore vsprintf */ + vsprintf (errbuf + strlen (errbuf), fmt, ap); + errbuf[sizeof(errbuf) - 1] = '\0'; + + if (_isatty(_fileno(stderr)) || !isGuiApp()) { + fputs(errbuf, stderr); + fputc('\r', stderr); + fputc('\n', stderr); + fflush(stderr); + } else + MessageBox ((HWND)NULL, errbuf, "Kerberos", MB_ICONEXCLAMATION); + +#else /* !_WIN32 */ + + if (whoami) { + fputs(whoami, stderr); + fputs(": ", stderr); + } + if (code) { + fputs(error_message(code), stderr); + fputs(" ", stderr); + } + if (fmt) { + vfprintf(stderr, fmt, ap); + } + /* should do this only on a tty in raw mode */ + putc('\r', stderr); + putc('\n', stderr); + fflush(stderr); + +#endif +} + +void KRB5_CALLCONV com_err_va(const char *whoami, + errcode_t code, + const char *fmt, + va_list ap) +{ + int err; + et_old_error_hook_func p; + + err = com_err_finish_init(); + if (err) + goto best_try; + k5_mutex_lock(&com_err_hook_lock); + p = com_err_hook ? com_err_hook : default_com_err_proc; + (*p)(whoami, code, fmt, ap); + k5_mutex_unlock(&com_err_hook_lock); + return; + +best_try: + /* Yikes. Our library initialization failed or we couldn't lock + the lock we want. We could be in trouble. Gosh, we should + probably print an error message. Oh, wait. That's what we're + trying to do. In fact, if we're losing on initialization here, + there's a good chance it has to do with failed initialization + of the caller. */ + if (!com_err_hook) + default_com_err_proc(whoami, code, fmt, ap); + else + (com_err_hook)(whoami, code, fmt, ap); + assert(err == 0); + abort(); +} + + +void KRB5_CALLCONV_C com_err(const char *whoami, + errcode_t code, + const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + com_err_va(whoami, code, fmt, ap); + va_end(ap); +} + +/* Make a separate function because the assert invocations below + use the macro expansion on some platforms, which may be insanely + long and incomprehensible. */ +static void com_err_lock_hook_handle(void) +{ + k5_mutex_lock(&com_err_hook_lock); +} + +et_old_error_hook_func set_com_err_hook (et_old_error_hook_func new_proc) +{ + et_old_error_hook_func x; + + /* Broken initialization? What can we do? */ + if (com_err_finish_init() != 0) + abort(); + com_err_lock_hook_handle(); + x = com_err_hook; + com_err_hook = new_proc; + k5_mutex_unlock(&com_err_hook_lock); + return x; +} + +et_old_error_hook_func reset_com_err_hook () +{ + et_old_error_hook_func x; + + /* Broken initialization? What can we do? */ + if (com_err_finish_init() != 0) + abort(); + com_err_lock_hook_handle(); + x = com_err_hook; + com_err_hook = NULL; + k5_mutex_unlock(&com_err_hook_lock); + return x; +} diff --git a/krb5-1.21.3/src/util/et/com_err.h b/krb5-1.21.3/src/util/et/com_err.h new file mode 100644 index 00000000..0a631e98 --- /dev/null +++ b/krb5-1.21.3/src/util/et/com_err.h @@ -0,0 +1,80 @@ +/* + * Copyright 1988, Student Information Processing Board of the + * Massachusetts Institute of Technology. + * + * Copyright 1995 by Cygnus Support. + * + * For copyright and distribution info, see the documentation supplied + * with this package. + */ + +/* Header file for common error description library. */ + +#ifndef __COM_ERR_H + +#if defined(_WIN32) +#include +#endif + +#ifndef KRB5_CALLCONV +#define KRB5_CALLCONV +#define KRB5_CALLCONV_C +#endif + +#include + +typedef long errcode_t; +typedef void (*et_old_error_hook_func) (const char *, errcode_t, + const char *, va_list ap); + +struct error_table { + /*@shared@*/ char const * const * msgs; + long base; + unsigned int n_msgs; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/* Public interfaces */ +extern void KRB5_CALLCONV_C com_err + (const char *, errcode_t, const char *, ...) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 4))) +#endif + ; +extern void KRB5_CALLCONV com_err_va + (const char *whoami, errcode_t code, const char *fmt, + va_list ap) +#if !defined(__cplusplus) && (__GNUC__ > 2) + __attribute__((__format__(__printf__, 3, 0))) +#endif + ; +extern /*@observer@*//*@dependent@*/ const char * KRB5_CALLCONV error_message + (errcode_t) + /*@modifies internalState@*/; +extern errcode_t KRB5_CALLCONV add_error_table + (/*@dependent@*/ const struct error_table *) + /*@modifies internalState@*/; +extern errcode_t KRB5_CALLCONV remove_error_table + (const struct error_table *) + /*@modifies internalState@*/; + +#if !defined(_WIN32) +/* + * The display routine should be application specific. A global hook, + * may cause inappropriate display procedures to be called between + * applications under non-Unix environments. + */ + +extern et_old_error_hook_func set_com_err_hook (et_old_error_hook_func); +extern et_old_error_hook_func reset_com_err_hook (void); +#endif + +#ifdef __cplusplus +} +#endif + +#define __COM_ERR_H +#endif /* ! defined(__COM_ERR_H) */ diff --git a/krb5-1.21.3/src/util/et/com_err.texinfo b/krb5-1.21.3/src/util/et/com_err.texinfo new file mode 100644 index 00000000..145aadfc --- /dev/null +++ b/krb5-1.21.3/src/util/et/com_err.texinfo @@ -0,0 +1,555 @@ +\input texinfo @c -*-texinfo-*- + +@c util/et/com_err.texinfo + +@c Note that although this source file is in texinfo format (more +@c or less), it is not yet suitable for turning into an ``info'' +@c file. Sorry, maybe next time. +@c +@c In order to produce hardcopy documentation from a texinfo file, +@c run ``tex com_err.texinfo'' which will load in texinfo.tex, +@c provided in this distribution. (texinfo.tex is from the Free +@c Software Foundation, and is under different copyright restrictions +@c from the rest of this package.) + +@ifinfo +@barfo +@end ifinfo + +@iftex +@tolerance 10000 + +@c Mutate section headers... +@begingroup + @catcode#=6 + @gdef@secheading#1#2#3{@secheadingi {#3@enspace #1}} +@endgroup +@end iftex + +@setfilename com_err +@settitle A Common Error Description Library for UNIX + +@ifinfo +This file documents the use of the Common Error Description library. + +Copyright (C) 1987, 1988 Student Information Processing Board of the +Massachusetts Institute of Technology. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided +that the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be +used in advertising or publicity pertaining to distribution of the software +without specific, written prior permission. Furthermore if you modify this +software you must label your software as modified software and not +distribute it in such a fashion that it might be confused with the +original M.I.T. software. M.I.T. and the M.I.T. S.I.P.B. +make no representations about the suitability of this software for any +purpose. It is provided "as is" without express or implied warranty. + +Note that the file texinfo.tex, provided with this distribution, is from +the Free Software Foundation, and is under different copyright restrictions +from the remainder of this package. + +@end ifinfo + +@ignore +Permission is granted to process this file through Tex and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore + +@setchapternewpage odd + +@titlepage +@center @titlefont{A Common Error Description} +@center @titlefont{Library for UNIX} +@sp 2 +@center Ken Raeburn +@center Bill Sommerfeld +@sp 1 +@center MIT Student Information Processing Board +@sp 3 +@center last updated 1 January 1989 +@center for version 1.2 +@center ***DRAFT COPY ONLY*** + +@vskip 2in + +@center @b{Abstract} + +UNIX has always had a clean and simple system call interface, with a +standard set of error codes passed between the kernel and user +programs. Unfortunately, the same cannot be said of many of the +libraries layered on top of the primitives provided by the kernel. +Typically, each one has used a different style of indicating errors to +their callers, leading to a total hodgepodge of error handling, and +considerable amounts of work for the programmer. This paper describes +a library and associated utilities which allows a more uniform way for +libraries to return errors to their callers, and for programs to +describe errors and exceptional conditions to their users. + +@page +@vskip 0pt plus 1filll + +Copyright @copyright{} 1987, 1988 by the Student Information Processing +Board of the Massachusetts Institute of Technology. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided +that the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation, and that the names of M.I.T. and the M.I.T. S.I.P.B. not be +used in advertising or publicity pertaining to distribution of the software +without specific, written prior permission. M.I.T. and the M.I.T. S.I.P.B. +make no representations about the suitability of this software for any +purpose. It is provided "as is" without express or implied warranty. + +Note that the file texinfo.tex, provided with this distribution, is from +the Free Software Foundation, and is under different copyright restrictions +from the remainder of this package. + +@end titlepage + +@ifinfo +@c should put a menu here someday.... +@end ifinfo + +@page + +@section Why com_err? + +In building application software packages, a programmer often has to +deal with a number of libraries, each of which can use a different +error-reporting mechanism. Sometimes one of two values is returned, +indicating simply SUCCESS or FAILURE, with no description of errors +encountered. Sometimes it is an index into a table of text strings, +where the name of the table used is dependent on the library being +used when the error is generated; since each table starts numbering at +0 or 1, additional information as to the source of the error code is +needed to determine which table to look at. Sometimes no text messages are +supplied at all, and the programmer must supply them at any point at which +he may wish to report error conditions. +Often, a global variable is assigned some value describing the error, but +the programmer has to know in each case whether to look at @code{errno}, +@code{h_errno}, the return value from @code{hes_err()}, or whatever other +variables or routines are specified. +And what happens if something +in the procedure of +examining or reporting the error changes the same variable? + +The package we have developed is an attempt to present a common +error-handling mechanism to manipulate the most common form of error code +in a fashion that does not have the problems listed above. + +A list of up to 256 text messages is supplied to a translator we have +written, along with the three- to four-character ``name'' of the error +table. The library using this error table need only call a routine +generated from this error-table source to make the table ``known'' to the +com_err library, and any error code the library generates can be converted +to the corresponding error message. There is also a default format for +error codes accidentally returned before making the table known, which is +of the form @samp{unknown code foo 32}, where @samp{foo} would be the name +of the table. + +@section Error codes + +Error codes themselves are 32 bit (signed) integers, of which the high +order 24 bits are an identifier of which error table the error code is +from, and the low order 8 bits are a sequential error number within +the table. An error code may thus be easily decomposed into its component +parts. Only the lowest 32 bits of an error code are considered significant +on systems which support wider values. + +Error table 0 is defined to match the UNIX system call error table +(@code{sys_errlist}); this allows @code{errno} values to be used directly +in the library (assuming that @code{errno} is of a type with the same width +as @t{long}). Other error table numbers are formed by compacting together +the first four characters of the error table name. The mapping between +characters in the name and numeric values in the error code are defined in +a system-independent fashion, so that two systems that can pass integral +values between them can reliably pass error codes without loss of meaning; +this should work even if the character sets used are not the same. +(However, if this is to be done, error table 0 should be avoided, since the +local system call error tables may differ.) + +Any variable which is to contain an error code should be declared @t{long}. +The draft proposed American National Standard for C (as of May, 1988) +requires that @t{long} variables be at least 32 bits; any system which does +not support 32-bit @t{long} values cannot make use of this package (nor +much other software that assumes an ANSI-C environment base) without +significant effort. + +@section Error table source file + +The error table source file begins with the declaration of the table name, +as + +@example +error_table @var{tablename} +@end example + +Individual error codes are +specified with + +@example +error_code @var{ERROR_NAME}, @var{"text message"} +@end example + +where @samp{ec} can also be used as a short form of @samp{error_code}. To +indicate the end of the table, use @samp{end}. Thus, a (short) sample +error table might be: + +@example + + error_table dsc + + error_code DSC_DUP_MTG_NAME, + "Meeting already exists" + + ec DSC_BAD_PATH, + "A bad meeting pathname was given" + + ec DSC_BAD_MODES, + "Invalid mode for this access control list" + + end + +@end example + +@section The error-table compiler + +The error table compiler is named @code{compile_et}. It takes one +argument, the pathname of a file (ending in @samp{.et}, e.g., +@samp{dsc_err.et}) containing an error table source file. It parses the +error table, and generates two output files -- a C header file +(@samp{discuss_err.h}) which contains definitions of the numerical values +of the error codes defined in the error table, and a C source file which +should be compiled and linked with the executable. The header file must be +included in the source of a module which wishes to reference the error +codes defined; the object module generated from the C code may be linked in +to a program which wishes to use the printed forms of the error codes. + +This translator accepts a @kbd{-language @var{lang}} argument, which +determines for which language (or language variant) the output should be +written. At the moment, @var{lang} is currently limited to @kbd{ANSI-C} +and @kbd{K&R-C}, and some abbreviated forms of each. Eventually, this will +be extended to include some support for C++. The default is currently +@kbd{K&R-C}, though the generated sources will have ANSI-C code +conditionalized on the symbol @t{__STDC__}. + +@section Run-time support routines + +Any source file which uses the routines supplied with or produced by the +com_err package should include the header file @file{}. It +contains declarations and definitions which may be needed on some systems. +(Some functions cannot be referenced properly without the return type +declarations in this file. Some functions may work properly on most +architectures even without the header file, but relying on this is not +recommended.) + +The run-time support routines and variables provided via this package +include the following: + +@example +void initialize_@var{xxxx}_error_table (void); +@end example + +One of these routines is built by the error compiler for each error table. +It makes the @var{xxxx} error table ``known'' to the error reporting +system. By convention, this routine should be called in the initialization +routine of the @var{xxxx} library. If the library has no initialization +routine, some combination of routines which form the core of the library +should ensure that this routine is called. It is not advised to leave it +the caller to make this call. + +There is no harm in calling this routine more than once. + +@example +#define ERROR_TABLE_BASE_@var{xxxx} @var{nnnnn}L +@end example + +This symbol contains the value of the first error code entry in the +specified table. +This rarely needs be used by the +programmer. + +@example +const char *error_message (long code); +@end example + +This routine returns the character string error message associated +with @code{code}; if this is associated with an unknown error table, or +if the code is associated with a known error table but the code is not +in the table, a string of the form @samp{Unknown code @var{xxxx nn}} is +returned, where @var{xxxx} is the error table name produced by +reversing the compaction performed on the error table number implied +by that error code, and @var{nn} is the offset from that base value. + +Although this routine is available for use when needed, its use should be +left to circumstances which render @code{com_err} (below) unusable. + +@example +void com_err (const char *whoami, /* module reporting error */ + long code, /* error code */ + const char *format, /* format for additional detail */ + ...); /* (extra parameters) */ +@end example + +This routine provides an alternate way to print error messages to +standard error; it allows the error message to be passed in as a +parameter, rather than in an external variable. @emph{Provide grammatical +context for ``message.''} + +If @var{format} is @code{(char *)NULL}, the formatted message will not be +printed. @var{format} may not be omitted. + +@example +#include + +void com_err_va (const char *whoami, + long code, + const char *format, + va_list args); +@end example + +This routine provides an interface, equivalent to @code{com_err} above, +which may be used by higher-level variadic functions (functions which +accept variable numbers of arguments). + +@example +#include + +void (*set_com_err_hook (void (*proc) ())) (); + +void (*@var{proc}) (const char *whoami, long code, va_list args); + +void reset_com_err_hook (); +@end example + +These two routines allow a routine to be dynamically substituted for +@samp{com_err}. After @samp{set_com_err_hook} has been called, +calls to @samp{com_err} will turn into calls to the new hook routine. +@samp{reset_com_err_hook} turns off this hook. This may intended to +be used in daemons (to use a routine which calls @var{syslog(3)}), or +in a window system application (which could pop up a dialogue box). + +If a program is to be used in an environment in which simply printing +messages to the @code{stderr} stream would be inappropriate (such as in a +daemon program which runs without a terminal attached), +@code{set_com_err_hook} may be used to redirect output from @code{com_err}. +The following is an example of an error handler which uses @var{syslog(3)} +as supplied in BSD 4.3: + +@example +#include +#include +#include + +/* extern openlog (const char * name, int logopt, int facility); */ +/* extern syslog (int priority, char * message, ...); */ + +void hook (const char * whoami, long code, + const char * format, va_list args) +@{ + char buffer[BUFSIZ]; + static int initialized = 0; + if (!initialized) @{ + openlog (whoami, + LOG_NOWAIT|LOG_CONS|LOG_PID|LOG_NDELAY, + LOG_DAEMON); + initialized = 1; + @} + vsprintf (buffer, format, args); + syslog (LOG_ERR, "%s %s", error_message (code), buffer); +@} +@end example + +After making the call +@code{set_com_err_hook (hook);}, +any calls to @code{com_err} will result in messages being sent to the +@var{syslogd} daemon for logging. +The name of the program, @samp{whoami}, is supplied to the +@samp{openlog()} call, and the message is formatted into a buffer and +passed to @code{syslog}. + +Note that since the extra arguments to @code{com_err} are passed by +reference via the @code{va_list} value @code{args}, the hook routine may +place any form of interpretation on them, including ignoring them. For +consistency, @code{printf}-style interpretation is suggested, via +@code{vsprintf} (or @code{_doprnt} on BSD systems without full support for +the ANSI C library). + +@section Coding Conventions + +The following conventions are just some general stylistic conventions +to follow when writing robust libraries and programs. Conventions +similar to this are generally followed inside the UNIX kernel and most +routines in the Multics operating system. In general, a routine +either succeeds (returning a zero error code, and doing some side +effects in the process), or it fails, doing minimal side effects; in +any event, any invariant which the library assumes must be maintained. + +In general, it is not in the domain of non user-interface library +routines to write error messages to the user's terminal, or halt the +process. Such forms of ``error handling'' should be reserved for +failures of internal invariants and consistency checks only, as it +provides the user of the library no way to clean up for himself in the +event of total failure. + +Library routines which can fail should be set up to return an error +code. This should usually be done as the return value of the +function; if this is not acceptable, the routine should return a +``null'' value, and put the error code into a parameter passed by +reference. + +Routines which use the first style of interface can be used from +user-interface levels of a program as follows: + +@example +@{ + if ((code = initialize_world(getuid(), random())) != 0) @{ + com_err("demo", code, + "when trying to initialize world"); + exit(1); + @} + if ((database = open_database("my_secrets", &code))==NULL) @{ + com_err("demo", code, + "while opening my_secrets"); + exit(1); + @} +@} +@end example + +A caller which fails to check the return status is in error. It is +possible to look for code which ignores error returns by using lint; +look for error messages of the form ``foobar returns value which is +sometimes ignored'' or ``foobar returns value which is always +ignored.'' + +Since libraries may be built out of other libraries, it is often necessary +for the success of one routine to depend on another. When a lower level +routine returns an error code, the middle level routine has a few possible +options. It can simply return the error code to its caller after doing +some form of cleanup, it can substitute one of its own, or it can take +corrective action of its own and continue normally. For instance, a +library routine which makes a ``connect'' system call to make a network +connection may reflect the system error code @code{ECONNREFUSED} +(Connection refused) to its caller, or it may return a ``server not +available, try again later,'' or it may try a different server. + +Cleanup which is typically necessary may include, but not be limited +to, freeing allocated memory which will not be needed any more, +unlocking concurrancy locks, dropping reference counts, closing file +descriptors, or otherwise undoing anything which the procedure did up +to this point. When there are a lot of things which can go wrong, it +is generally good to write one block of error-handling code which is +branched to, using a goto, in the event of failure. A common source +of errors in UNIX programs is failing to close file descriptors on +error returns; this leaves a number of ``zombied'' file descriptors +open, which eventually causes the process to run out of file +descriptors and fall over. + +@example +@{ + FILE *f1=NULL, *f2=NULL, *f3=NULL; + int status = 0; + + if ( (f1 = fopen(FILE1, "r")) == NULL) @{ + status = errno; + goto error; + @} + + /* + * Crunch for a while + */ + + if ( (f2 = fopen(FILE2, "w")) == NULL) @{ + status = errno; + goto error; + @} + + if ( (f3 = fopen(FILE3, "a+")) == NULL) @{ + status = errno; + goto error; + @} + + /* + * Do more processing. + */ + fclose(f1); + fclose(f2); + fclose(f3); + return 0; + +error: + if (f1) fclose(f1); + if (f2) fclose(f2); + if (f3) fclose(f3); + return status; +@} +@end example + +@section Building and Installation + +The distribution of this package will probably be done as a compressed +``tar''-format file available via anonymous FTP from SIPB.MIT.EDU. +Retrieve @samp{pub/com_err.tar.Z} and extract the contents. A subdirectory +@t{profiled} should be created to hold objects compiled for profiling. +Running ``make all'' should then be sufficient to build the library and +error-table compiler. The files @samp{libcom_err.a}, +@samp{libcom_err_p.a}, @samp{com_err.h}, and @samp{compile_et} should be +installed for use; @samp{com_err.3} and @samp{compile_et.1} can also be +installed as manual pages. + +Potential problems: + +@itemize @bullet + +@item Use of @code{strcasecmp}, a routine provided in BSD for +case-insensitive string comparisons. If an equivalent routine is +available, you can modify @code{CFLAGS} in the makefile to define +@code{strcasecmp} to the name of that routine. + +@item Compilers that defined @code{__STDC__} without providing the header +file @code{}. One such example is Metaware's High ``C'' +compiler, as provided at Project Athena on the IBM RT/PC workstation; if +@code{__HIGHC__} is defined, it is assumed that @code{} is not +available, and therefore @code{} must be used. If the symbol +@code{VARARGS} is defined (e.g., in the makefile), @code{} will +be used. + +@item If your linker rejects symbols that are simultaneously defined in two +library files, edit @samp{Makefile} to remove @samp{perror.c} from the +library. This file contains a version of @var{perror(3)} which calls +@code{com_err} instead of calling @code{write} directly. + +@end itemize + +As I do not have access to non-BSD systems, there are probably +bugs present that may interfere with building or using this package on +other systems. If they are reported to me, they can probably be fixed for +the next version. + +@section Bug Reports + +Please send any comments or bug reports to the principal author: Ken +Raeburn, @t{Raeburn@@Athena.MIT.EDU}. + +@section Acknowledgements + +I would like to thank: Bill Sommerfeld, for his help with some of this +documentation, and catching some of the bugs the first time around; +Honeywell Information Systems, for not killing off the @emph{Multics} +operating system before I had an opportunity to use it; Honeywell's +customers, who persuaded them not to do so, for a while; Ted Anderson of +CMU, for catching some problems before version 1.2 left the nest; Stan +Zanarotti and several others of MIT's Student Information Processing Board, +for getting us started with ``discuss,'' for which this package was +originally written; and everyone I've talked into --- I mean, asked to read +this document and the ``man'' pages. + +@bye diff --git a/krb5-1.21.3/src/util/et/compile_et.1 b/krb5-1.21.3/src/util/et/compile_et.1 new file mode 100644 index 00000000..c9dff781 --- /dev/null +++ b/krb5-1.21.3/src/util/et/compile_et.1 @@ -0,0 +1,97 @@ +.\" Copyright (c) 1988 Massachusetts Institute of Technology, +.\" Student Information Processing Board. All rights reserved. +.\" +.\" util/et/compile_et.1 +.\" +.TH COMPILE_ET 1 "22 Nov 1988" SIPB +.SH NAME +compile_et \- error table compiler +.SH SYNOPSIS +.B compile_et +[ +.B \-\-textdomain +.I domain +[ +.B \-\-localedir +.I dir +] ] +file +.SH DESCRIPTION +.B Compile_et +converts a table listing error-code names and associated messages into +a C source file suitable for use with the +.IR com_err (3) +library. + +The source file name must end with a suffix of ``.et''; the file +consists of a declaration supplying the name (up to four characters +long) of the error-code table: + +.B error_table +.I name + +followed by up to 256 entries of the form: + +.B error_code +.I name, +" +.I string +" + +and a final + +.B end + +to indicate the end of the table. + +The name of the table is used to construct the name of a subroutine +.I initialize_XXXX_error_table +which must be called in order for the +.I com_err +library to recognize the error table. + +The various error codes defined are assigned sequentially increasing +numbers (starting with a large number computed as a hash function of +the name of the table); thus for compatibility it is suggested that +new codes be added only to the end of an existing table, and that no +codes be removed from tables. + +The names defined in the table are placed into a C header file with +preprocessor directives defining them as integer constants of up to +32 bits in magnitude. + +A C source file is also generated which should be compiled and linked +with the object files which reference these error codes; it contains +the text of the messages and the initialization subroutine. Both C +files have names derived from that of the original source file, with +the ``.et'' suffix replaced by ``.c'' and ``.h''. + +A ``#'' in the source file is treated as a comment character, and all +remaining text to the end of the source line will be ignored. + +If a text domain is provided with the +.B \-\-textdomain +option, error messages will be looked up in the specified domain with +.BR gettext . +If a locale directory is also provided with the +.B \-\-localedir +option, the text domain will be bound to the specified locale +directory with +.B bindtextdomain +when the error table is initialized. + +.SH BUGS + +Since +.B compile_et +uses a very simple parser based on +.IR yacc (1), +its error recovery leaves much to be desired. + +.\" .IR for manual entries +.\" .PP for paragraph breaks + +.SH "SEE ALSO" +com_err (3). + +Ken Raeburn, "A Common Error Description Library for UNIX". diff --git a/krb5-1.21.3/src/util/et/compile_et.sh b/krb5-1.21.3/src/util/et/compile_et.sh new file mode 100755 index 00000000..f17ddba7 --- /dev/null +++ b/krb5-1.21.3/src/util/et/compile_et.sh @@ -0,0 +1,36 @@ +#!/bin/sh +# +# +AWK=@AWK@ +DIR=@DIR@ + +usage="usage: $0 [ -d scriptDir ] [ --textdomain domain [ --localedir dir ] ]" +usage="$usage inputfile.et" + +TEXTDOMAIN= +LOCALEDIR= + +while [ $# -ge 2 ]; do + if [ "$1" = "-d" ]; then + DIR=$2; shift; shift + elif [ "$1" = "--textdomain" ]; then + TEXTDOMAIN=$2; shift; shift + elif [ "$1" = "--localedir" ]; then + LOCALEDIR=$2; shift; shift + else + echo $usage 1>&2 ; exit 1 + fi +done + +# --localedir requires --textdomain. +if [ $# -ne 1 -o \( -n "$LOCALEDIR" -a -z "$TEXTDOMAIN" \) ]; then + echo $usage 1>&2 ; exit 1 +fi + +ROOT=`echo $1 | sed -e s/.et$//` +BASE=`echo "$ROOT" | sed -e 's;.*/;;'` + +set -ex +$AWK -f ${DIR}/et_h.awk "outfile=${BASE}.h" "$ROOT.et" +$AWK -f ${DIR}/et_c.awk "outfile=${BASE}.c" "textdomain=$TEXTDOMAIN" \ + "localedir=$LOCALEDIR" "$ROOT.et" diff --git a/krb5-1.21.3/src/util/et/config_script b/krb5-1.21.3/src/util/et/config_script new file mode 100755 index 00000000..ee3bb270 --- /dev/null +++ b/krb5-1.21.3/src/util/et/config_script @@ -0,0 +1,22 @@ +#!/bin/sh +# +# This program takes a shell script and configures for the following +# variables: @DIR@ +# @AWK@ +# @SED@ +# +# Usage: config_script [

      5`AlyjEhc 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 Ekg^=lZStR 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 literal 0 HcmV?d00001 diff --git a/krb5-1.21.3/doc/pdf/appdev.tex b/krb5-1.21.3/doc/pdf/appdev.tex new file mode 100644 index 00000000..1f9ec20e --- /dev/null +++ b/krb5-1.21.3/doc/pdf/appdev.tex @@ -0,0 +1,31210 @@ +%% Generated by Sphinx. +\def\sphinxdocclass{report} +\documentclass[letterpaper,10pt,english]{sphinxmanual} +\ifdefined\pdfpxdimen + \let\sphinxpxdimen\pdfpxdimen\else\newdimen\sphinxpxdimen +\fi \sphinxpxdimen=.75bp\relax +\ifdefined\pdfimageresolution + \pdfimageresolution= \numexpr \dimexpr1in\relax/\sphinxpxdimen\relax +\fi +%% let collapsible pdf bookmarks panel have high depth per default +\PassOptionsToPackage{bookmarksdepth=5}{hyperref} + +\PassOptionsToPackage{warn}{textcomp} +\usepackage[utf8]{inputenc} +\ifdefined\DeclareUnicodeCharacter +% support both utf8 and utf8x syntaxes + \ifdefined\DeclareUnicodeCharacterAsOptional + \def\sphinxDUC#1{\DeclareUnicodeCharacter{"#1}} + \else + \let\sphinxDUC\DeclareUnicodeCharacter + \fi + \sphinxDUC{00A0}{\nobreakspace} + \sphinxDUC{2500}{\sphinxunichar{2500}} + \sphinxDUC{2502}{\sphinxunichar{2502}} + \sphinxDUC{2514}{\sphinxunichar{2514}} + \sphinxDUC{251C}{\sphinxunichar{251C}} + \sphinxDUC{2572}{\textbackslash} +\fi +\usepackage{cmap} +\usepackage[T1]{fontenc} +\usepackage{amsmath,amssymb,amstext} +\usepackage{babel} + + + +\usepackage{tgtermes} +\usepackage{tgheros} +\renewcommand{\ttdefault}{txtt} + + + +\usepackage[Bjarne]{fncychap} +\usepackage{sphinx} + +\fvset{fontsize=auto} +\usepackage{geometry} + + +% Include hyperref last. +\usepackage{hyperref} +% Fix anchor placement for figures with captions. +\usepackage{hypcap}% it must be loaded after hyperref. +% Set up styles of URL: it should be placed after hyperref. +\urlstyle{same} + + +\usepackage{sphinxmessages} +\setcounter{tocdepth}{0} + + + +\title{Kerberos Application Developer Guide} +\date{ } +\release{1.21.3} +\author{MIT} +\newcommand{\sphinxlogo}{\vbox{}} +\renewcommand{\releasename}{Release} +\makeindex +\begin{document} + +\pagestyle{empty} +\sphinxmaketitle +\pagestyle{plain} +\sphinxtableofcontents +\pagestyle{normal} +\phantomsection\label{\detokenize{appdev/index::doc}} + + + +\chapter{Developing with GSSAPI} +\label{\detokenize{appdev/gssapi:developing-with-gssapi}}\label{\detokenize{appdev/gssapi::doc}} +\sphinxAtStartPar +The GSSAPI (Generic Security Services API) allows applications to +communicate securely using Kerberos 5 or other security mechanisms. +We recommend using the GSSAPI (or a higher\sphinxhyphen{}level framework which +encompasses GSSAPI, such as SASL) for secure network communication +over using the libkrb5 API directly. + +\sphinxAtStartPar +GSSAPIv2 is specified in \index{RFC@\spxentry{RFC}!RFC 2743@\spxentry{RFC 2743}}\sphinxhref{https://tools.ietf.org/html/rfc2743.html}{\sphinxstylestrong{RFC 2743}} and \index{RFC@\spxentry{RFC}!RFC 2744@\spxentry{RFC 2744}}\sphinxhref{https://tools.ietf.org/html/rfc2744.html}{\sphinxstylestrong{RFC 2744}}. Also see +\index{RFC@\spxentry{RFC}!RFC 7546@\spxentry{RFC 7546}}\sphinxhref{https://tools.ietf.org/html/rfc7546.html}{\sphinxstylestrong{RFC 7546}} for a description of how to use the GSSAPI in a client or +server program. + +\sphinxAtStartPar +This documentation will describe how various ways of using the +GSSAPI will behave with the krb5 mechanism as implemented in MIT krb5, +as well as krb5\sphinxhyphen{}specific extensions to the GSSAPI. + + +\section{Name types} +\label{\detokenize{appdev/gssapi:name-types}} +\sphinxAtStartPar +A GSSAPI application can name a local or remote entity by calling +\sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.16}{gss\_import\_name}, specifying a name type and a value. The following +name types are supported by the krb5 mechanism: +\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_NT\_HOSTBASED\_SERVICE}: The value should be a string of the +form \sphinxcode{\sphinxupquote{service}} or \sphinxcode{\sphinxupquote{service@hostname}}. This is the most common +way to name target services when initiating a security context, and +is the most likely name type to work across multiple mechanisms. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_KRB5\_NT\_PRINCIPAL\_NAME}: The value should be a principal name +string. This name type only works with the krb5 mechanism, and is +defined in the \sphinxcode{\sphinxupquote{\textless{}gssapi/gssapi\_krb5.h\textgreater{}}} header. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_NT\_USER\_NAME} or \sphinxstylestrong{GSS\_C\_NULL\_OID}: The value is treated +as an unparsed principal name string, as above. These name types +may work with mechanisms other than krb5, but will have different +interpretations in those mechanisms. \sphinxstylestrong{GSS\_C\_NT\_USER\_NAME} is +intended to be used with a local username, which will parse into a +single\sphinxhyphen{}component principal in the default realm. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_NT\_ANONYMOUS}: The value is ignored. The anonymous +principal is used, allowing a client to authenticate to a server +without asserting a particular identity (which may or may not be +allowed by a particular server or Kerberos realm). + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_NT\_MACHINE\_UID\_NAME}: The value is uid\_t object. On +Unix\sphinxhyphen{}like systems, the username of the uid is looked up in the +system user database and the resulting username is parsed as a +principal name. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_NT\_STRING\_UID\_NAME}: As above, but the value is a decimal +string representation of the uid. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_NT\_EXPORT\_NAME}: The value must be the result of a +\sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.13}{gss\_export\_name} call. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_KRB5\_NT\_ENTERPRISE\_NAME}: The value should be a krb5 +enterprise name string (see \index{RFC@\spxentry{RFC}!RFC 6806@\spxentry{RFC 6806}}\sphinxhref{https://tools.ietf.org/html/rfc6806.html}{\sphinxstylestrong{RFC 6806}} section 5), in the form +\sphinxcode{\sphinxupquote{user@suffix}}. This name type is used to convey alias names, and +is defined in the \sphinxcode{\sphinxupquote{\textless{}gssapi/gssapi\_krb5.h\textgreater{}}} header. (New in +release 1.17.) + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_KRB5\_NT\_X509\_CERT}: The value should be an X.509 certificate +encoded according to \index{RFC@\spxentry{RFC}!RFC 5280@\spxentry{RFC 5280}}\sphinxhref{https://tools.ietf.org/html/rfc5280.html}{\sphinxstylestrong{RFC 5280}}. This name form can be used for +the desired\_name parameter of gss\_acquire\_cred\_impersonate\_name(), +to identify the S4U2Self user by certificate. (New in release +1.19.) + +\end{itemize} + + +\section{Initiator credentials} +\label{\detokenize{appdev/gssapi:initiator-credentials}} +\sphinxAtStartPar +A GSSAPI client application uses \sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.19}{gss\_init\_sec\_context} to establish a +security context. The \sphinxstyleemphasis{initiator\_cred\_handle} parameter determines +what tickets are used to establish the connection. An application can +either pass \sphinxstylestrong{GSS\_C\_NO\_CREDENTIAL} to use the default client +credential, or it can use \sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.2}{gss\_acquire\_cred} beforehand to acquire an +initiator credential. The call to \sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.2}{gss\_acquire\_cred} may include a +\sphinxstyleemphasis{desired\_name} parameter, or it may pass \sphinxstylestrong{GSS\_C\_NO\_NAME} if it does +not have a specific name preference. + +\sphinxAtStartPar +If the desired name for a krb5 initiator credential is a host\sphinxhyphen{}based +name, it is converted to a principal name of the form +\sphinxcode{\sphinxupquote{service/hostname}} in the local realm, where \sphinxstyleemphasis{hostname} is the local +hostname if not specified. The hostname will be canonicalized using +forward name resolution, and possibly also using reverse name +resolution depending on the value of the \sphinxstylestrong{rdns} variable in +\DUrole{xref,std,std-ref}{libdefaults}. + +\sphinxAtStartPar +If a desired name is specified in the call to \sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.2}{gss\_acquire\_cred}, the +krb5 mechanism will attempt to find existing tickets for that client +principal name in the default credential cache or collection. If the +default cache type does not support a collection, and the default +cache contains credentials for a different principal than the desired +name, a \sphinxstylestrong{GSS\_S\_CRED\_UNAVAIL} error will be returned with a minor +code indicating a mismatch. + +\sphinxAtStartPar +If no existing tickets are available for the desired name, but the +name has an entry in the default client \DUrole{xref,std,std-ref}{keytab\_definition}, the +krb5 mechanism will acquire initial tickets for the name using the +default client keytab. + +\sphinxAtStartPar +If no desired name is specified, credential acquisition will be +deferred until the credential is used in a call to +\sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.19}{gss\_init\_sec\_context} or \sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.21}{gss\_inquire\_cred}. If the call is to +\sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.19}{gss\_init\_sec\_context}, the target name will be used to choose a client +principal name using the credential cache selection facility. (This +facility might, for instance, try to choose existing tickets for a +client principal in the same realm as the target service). If there +are no existing tickets for the chosen principal, but it is present in +the default client keytab, the krb5 mechanism will acquire initial +tickets using the keytab. + +\sphinxAtStartPar +If the target name cannot be used to select a client principal +(because the credentials are used in a call to \sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.21}{gss\_inquire\_cred}), or +if the credential cache selection facility cannot choose a principal +for it, the default credential cache will be selected if it exists and +contains tickets. + +\sphinxAtStartPar +If the default credential cache does not exist, but the default client +keytab does, the krb5 mechanism will try to acquire initial tickets +for the first principal in the default client keytab. + +\sphinxAtStartPar +If the krb5 mechanism acquires initial tickets using the default +client keytab, the resulting tickets will be stored in the default +cache or collection, and will be refreshed by future calls to +\sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.2}{gss\_acquire\_cred} as they approach their expire time. + + +\section{Acceptor names} +\label{\detokenize{appdev/gssapi:acceptor-names}} +\sphinxAtStartPar +A GSSAPI server application uses \sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.1}{gss\_accept\_sec\_context} to establish +a security context based on tokens provided by the client. The +\sphinxstyleemphasis{acceptor\_cred\_handle} parameter determines what +\DUrole{xref,std,std-ref}{keytab\_definition} entries may be authenticated to by the +client, if the krb5 mechanism is used. + +\sphinxAtStartPar +The simplest choice is to pass \sphinxstylestrong{GSS\_C\_NO\_CREDENTIAL} as the acceptor +credential. In this case, clients may authenticate to any service +principal in the default keytab (typically \DUrole{xref,std,std-ref}{DEFKTNAME}, or the value of +the \sphinxstylestrong{KRB5\_KTNAME} environment variable). This is the recommended +approach if the server application has no specific requirements to the +contrary. + +\sphinxAtStartPar +A server may acquire an acceptor credential with \sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.2}{gss\_acquire\_cred} and +a \sphinxstyleemphasis{cred\_usage} of \sphinxstylestrong{GSS\_C\_ACCEPT} or \sphinxstylestrong{GSS\_C\_BOTH}. If the +\sphinxstyleemphasis{desired\_name} parameter is \sphinxstylestrong{GSS\_C\_NO\_NAME}, then clients will be +allowed to authenticate to any service principal in the default +keytab, just as if no acceptor credential was supplied. + +\sphinxAtStartPar +If a server wishes to specify a \sphinxstyleemphasis{desired\_name} to \sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.2}{gss\_acquire\_cred}, +the most common choice is a host\sphinxhyphen{}based name. If the host\sphinxhyphen{}based +\sphinxstyleemphasis{desired\_name} contains just a \sphinxstyleemphasis{service}, then clients will be allowed +to authenticate to any host\sphinxhyphen{}based service principal (that is, a +principal of the form \sphinxcode{\sphinxupquote{service/hostname@REALM}}) for the named +service, regardless of hostname or realm, as long as it is present in +the default keytab. If the input name contains both a \sphinxstyleemphasis{service} and a +\sphinxstyleemphasis{hostname}, clients will be allowed to authenticate to any host\sphinxhyphen{}based +principal for the named service and hostname, regardless of realm. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +If a \sphinxstyleemphasis{hostname} is specified, it will be canonicalized +using forward name resolution, and possibly also using +reverse name resolution depending on the value of the +\sphinxstylestrong{rdns} variable in \DUrole{xref,std,std-ref}{libdefaults}. +\end{sphinxadmonition} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +If the \sphinxstylestrong{ignore\_acceptor\_hostname} variable in +\DUrole{xref,std,std-ref}{libdefaults} is enabled, then \sphinxstyleemphasis{hostname} will be +ignored even if one is specified in the input name. +\end{sphinxadmonition} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +In MIT krb5 versions prior to 1.10, and in Heimdal’s +implementation of the krb5 mechanism, an input name with +just a \sphinxstyleemphasis{service} is treated like an input name of +\sphinxcode{\sphinxupquote{service@localhostname}}, where \sphinxstyleemphasis{localhostname} is the +string returned by gethostname(). +\end{sphinxadmonition} + +\sphinxAtStartPar +If the \sphinxstyleemphasis{desired\_name} is a krb5 principal name or a local system name +type which is mapped to a krb5 principal name, clients will only be +allowed to authenticate to that principal in the default keytab. + + +\section{Name Attributes} +\label{\detokenize{appdev/gssapi:name-attributes}} +\sphinxAtStartPar +In release 1.8 or later, the \sphinxhref{https://tools.ietf.org/html/rfc6680.txt\#section-7.4}{gss\_inquire\_name} and +\sphinxhref{https://tools.ietf.org/html/6680.html\#section-7.5}{gss\_get\_name\_attribute} functions, specified in \index{RFC@\spxentry{RFC}!RFC 6680@\spxentry{RFC 6680}}\sphinxhref{https://tools.ietf.org/html/rfc6680.html}{\sphinxstylestrong{RFC 6680}}, can be +used to retrieve name attributes from the \sphinxstyleemphasis{src\_name} returned by +\sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.1}{gss\_accept\_sec\_context}. The following attributes are defined when +the krb5 mechanism is used: + +\phantomsection\label{\detokenize{appdev/gssapi:gssapi-authind-attr}}\begin{itemize} +\item {} +\sphinxAtStartPar +“auth\sphinxhyphen{}indicators” attribute: + +\end{itemize} + +\sphinxAtStartPar +This attribute will be included in the \sphinxhref{https://tools.ietf.org/html/rfc6680.txt\#section-7.4}{gss\_inquire\_name} output if the +ticket contains \DUrole{xref,std,std-ref}{authentication indicators}. +One indicator is returned per invocation of \sphinxhref{https://tools.ietf.org/html/6680.html\#section-7.5}{gss\_get\_name\_attribute}, +so multiple invocations may be necessary to retrieve all of the +indicators from the ticket. (New in release 1.15.) + + +\section{Credential store extensions} +\label{\detokenize{appdev/gssapi:credential-store-extensions}} +\sphinxAtStartPar +Beginning with release 1.11, the following GSSAPI extensions declared +in \sphinxcode{\sphinxupquote{\textless{}gssapi/gssapi\_ext.h\textgreater{}}} can be used to specify how credentials +are acquired or stored: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{struct} \PYG{n}{gss\PYGZus{}key\PYGZus{}value\PYGZus{}element\PYGZus{}struct} \PYG{p}{\PYGZob{}} + \PYG{n}{const} \PYG{n}{char} \PYG{o}{*}\PYG{n}{key}\PYG{p}{;} + \PYG{n}{const} \PYG{n}{char} \PYG{o}{*}\PYG{n}{value}\PYG{p}{;} +\PYG{p}{\PYGZcb{}}\PYG{p}{;} +\PYG{n}{typedef} \PYG{n}{struct} \PYG{n}{gss\PYGZus{}key\PYGZus{}value\PYGZus{}element\PYGZus{}struct} \PYG{n}{gss\PYGZus{}key\PYGZus{}value\PYGZus{}element\PYGZus{}desc}\PYG{p}{;} + +\PYG{n}{struct} \PYG{n}{gss\PYGZus{}key\PYGZus{}value\PYGZus{}set\PYGZus{}struct} \PYG{p}{\PYGZob{}} + \PYG{n}{OM\PYGZus{}uint32} \PYG{n}{count}\PYG{p}{;} + \PYG{n}{gss\PYGZus{}key\PYGZus{}value\PYGZus{}element\PYGZus{}desc} \PYG{o}{*}\PYG{n}{elements}\PYG{p}{;} +\PYG{p}{\PYGZcb{}}\PYG{p}{;} +\PYG{n}{typedef} \PYG{n}{const} \PYG{n}{struct} \PYG{n}{gss\PYGZus{}key\PYGZus{}value\PYGZus{}set\PYGZus{}struct} \PYG{n}{gss\PYGZus{}key\PYGZus{}value\PYGZus{}set\PYGZus{}desc}\PYG{p}{;} +\PYG{n}{typedef} \PYG{n}{const} \PYG{n}{gss\PYGZus{}key\PYGZus{}value\PYGZus{}set\PYGZus{}desc} \PYG{o}{*}\PYG{n}{gss\PYGZus{}const\PYGZus{}key\PYGZus{}value\PYGZus{}set\PYGZus{}t}\PYG{p}{;} + +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}acquire\PYGZus{}cred\PYGZus{}from}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{const} \PYG{n}{gss\PYGZus{}name\PYGZus{}t} \PYG{n}{desired\PYGZus{}name}\PYG{p}{,} + \PYG{n}{OM\PYGZus{}uint32} \PYG{n}{time\PYGZus{}req}\PYG{p}{,} + \PYG{n}{const} \PYG{n}{gss\PYGZus{}OID\PYGZus{}set} \PYG{n}{desired\PYGZus{}mechs}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}cred\PYGZus{}usage\PYGZus{}t} \PYG{n}{cred\PYGZus{}usage}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}const\PYGZus{}key\PYGZus{}value\PYGZus{}set\PYGZus{}t} \PYG{n}{cred\PYGZus{}store}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}cred\PYGZus{}id\PYGZus{}t} \PYG{o}{*}\PYG{n}{output\PYGZus{}cred\PYGZus{}handle}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}OID\PYGZus{}set} \PYG{o}{*}\PYG{n}{actual\PYGZus{}mechs}\PYG{p}{,} + \PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{time\PYGZus{}rec}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}store\PYGZus{}cred\PYGZus{}into}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}cred\PYGZus{}id\PYGZus{}t} \PYG{n}{input\PYGZus{}cred\PYGZus{}handle}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}cred\PYGZus{}usage\PYGZus{}t} \PYG{n}{cred\PYGZus{}usage}\PYG{p}{,} + \PYG{n}{const} \PYG{n}{gss\PYGZus{}OID} \PYG{n}{desired\PYGZus{}mech}\PYG{p}{,} + \PYG{n}{OM\PYGZus{}uint32} \PYG{n}{overwrite\PYGZus{}cred}\PYG{p}{,} + \PYG{n}{OM\PYGZus{}uint32} \PYG{n}{default\PYGZus{}cred}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}const\PYGZus{}key\PYGZus{}value\PYGZus{}set\PYGZus{}t} \PYG{n}{cred\PYGZus{}store}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}OID\PYGZus{}set} \PYG{o}{*}\PYG{n}{elements\PYGZus{}stored}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}cred\PYGZus{}usage\PYGZus{}t} \PYG{o}{*}\PYG{n}{cred\PYGZus{}usage\PYGZus{}stored}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The additional \sphinxstyleemphasis{cred\_store} parameter allows the caller to specify +information about how the credentials should be obtained and stored. +The following options are supported by the krb5 mechanism: +\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstylestrong{ccache}: For acquiring initiator credentials, the name of the +\DUrole{xref,std,std-ref}{credential cache} to which the handle will +refer. For storing credentials, the name of the cache or collection +where the credentials will be stored (see below). + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{client\_keytab}: For acquiring initiator credentials, the name of +the \DUrole{xref,std,std-ref}{keytab} which will be used, if +necessary, to refresh the credentials in the cache. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{keytab}: For acquiring acceptor credentials, the name of the +\DUrole{xref,std,std-ref}{keytab} to which the handle will refer. +In release 1.19 and later, this option also determines the keytab to +be used for verification when initiator credentials are acquired +using a password and verified. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{password}: For acquiring initiator credentials, this option +instructs the mechanism to acquire fresh credentials into a unique +memory credential cache. This option may not be used with the +\sphinxstylestrong{ccache} or \sphinxstylestrong{client\_keytab} options, and a \sphinxstyleemphasis{desired\_name} must +be specified. (New in release 1.19.) + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{rcache}: For acquiring acceptor credentials, the name of the +\DUrole{xref,std,std-ref}{replay cache} to be used when processing +the initiator tokens. (New in release 1.13.) + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{verify}: For acquiring initiator credentials, this option +instructs the mechanism to verify the credentials by obtaining a +ticket to a service with a known key. The service key is obtained +from the keytab specified with the \sphinxstylestrong{keytab} option or the default +keytab. The value may be the name of a principal in the keytab, or +the empty string. If the empty string is given, any \sphinxcode{\sphinxupquote{host}} +service principal in the keytab may be used. (New in release 1.19.) + +\end{itemize} + +\sphinxAtStartPar +In release 1.20 or later, if a collection name is specified for +\sphinxstylestrong{cache} in a call to gss\_store\_cred\_into(), an existing cache for +the client principal within the collection will be selected, or a new +cache will be created within the collection. If \sphinxstyleemphasis{overwrite\_cred} is +false and the selected credential cache already exists, a +\sphinxstylestrong{GSS\_S\_DUPLICATE\_ELEMENT} error will be returned. If \sphinxstyleemphasis{default\_cred} +is true, the primary cache of the collection will be switched to the +selected cache. + + +\section{Importing and exporting credentials} +\label{\detokenize{appdev/gssapi:importing-and-exporting-credentials}} +\sphinxAtStartPar +The following GSSAPI extensions can be used to import and export +credentials (declared in \sphinxcode{\sphinxupquote{\textless{}gssapi/gssapi\_ext.h\textgreater{}}}): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}export\PYGZus{}cred}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}cred\PYGZus{}id\PYGZus{}t} \PYG{n}{cred\PYGZus{}handle}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}buffer\PYGZus{}t} \PYG{n}{token}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}import\PYGZus{}cred}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}buffer\PYGZus{}t} \PYG{n}{token}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}cred\PYGZus{}id\PYGZus{}t} \PYG{o}{*}\PYG{n}{cred\PYGZus{}handle}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The first function serializes a GSSAPI credential handle into a +buffer; the second unseralizes a buffer into a GSSAPI credential +handle. Serializing a credential does not destroy it. If any of the +mechanisms used in \sphinxstyleemphasis{cred\_handle} do not support serialization, +gss\_export\_cred will return \sphinxstylestrong{GSS\_S\_UNAVAILABLE}. As with other +GSSAPI serialization functions, these extensions are only intended to +work with a matching implementation on the other side; they do not +serialize credentials in a standardized format. + +\sphinxAtStartPar +A serialized credential may contain secret information such as ticket +session keys. The serialization format does not protect this +information from eavesdropping or tampering. The calling application +must take care to protect the serialized credential when communicating +it over an insecure channel or to an untrusted party. + +\sphinxAtStartPar +A krb5 GSSAPI credential may contain references to a credential cache, +a client keytab, an acceptor keytab, and a replay cache. These +resources are normally serialized as references to their external +locations (such as the filename of the credential cache). Because of +this, a serialized krb5 credential can only be imported by a process +with similar privileges to the exporter. A serialized credential +should not be trusted if it originates from a source with lower +privileges than the importer, as it may contain references to external +credential cache, keytab, or replay cache resources not accessible to +the originator. + +\sphinxAtStartPar +An exception to the above rule applies when a krb5 GSSAPI credential +refers to a memory credential cache, as is normally the case for +delegated credentials received by \sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.1}{gss\_accept\_sec\_context}. In this +case, the contents of the credential cache are serialized, so that the +resulting token may be imported even if the original memory credential +cache no longer exists. + + +\section{Constrained delegation (S4U)} +\label{\detokenize{appdev/gssapi:constrained-delegation-s4u}} +\sphinxAtStartPar +The Microsoft S4U2Self and S4U2Proxy Kerberos protocol extensions +allow an intermediate service to acquire credentials from a client to +a target service without requiring the client to delegate a +ticket\sphinxhyphen{}granting ticket, if the KDC is configured to allow it. + +\sphinxAtStartPar +To perform a constrained delegation operation, the intermediate +service must submit to the KDC an “evidence ticket” from the client to +the intermediate service. An evidence ticket can be acquired when the +client authenticates to the intermediate service with Kerberos, or +with an S4U2Self request if the KDC allows it. The MIT krb5 GSSAPI +library represents an evidence ticket using a “proxy credential”, +which is a special kind of gss\_cred\_id\_t object whose underlying +credential cache contains the evidence ticket and a krbtgt ticket for +the intermediate service. + +\sphinxAtStartPar +To acquire a proxy credential during client authentication, the +service should first create an acceptor credential using the +\sphinxstylestrong{GSS\_C\_BOTH} usage. The application should then pass this +credential as the \sphinxstyleemphasis{acceptor\_cred\_handle} to \sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.1}{gss\_accept\_sec\_context}, +and also pass a \sphinxstyleemphasis{delegated\_cred\_handle} output parameter to receive a +proxy credential containing the evidence ticket. The output value of +\sphinxstyleemphasis{delegated\_cred\_handle} may be a delegated ticket\sphinxhyphen{}granting ticket if +the client sent one, or a proxy credential if not. If the library can +determine that the client’s ticket is not a valid evidence ticket, it +will place \sphinxstylestrong{GSS\_C\_NO\_CREDENTIAL} in \sphinxstyleemphasis{delegated\_cred\_handle}. + +\sphinxAtStartPar +To acquire a proxy credential using an S4U2Self request, the service +can use the following GSSAPI extension: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}acquire\PYGZus{}cred\PYGZus{}impersonate\PYGZus{}name}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}cred\PYGZus{}id\PYGZus{}t} \PYG{n}{icred}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}name\PYGZus{}t} \PYG{n}{desired\PYGZus{}name}\PYG{p}{,} + \PYG{n}{OM\PYGZus{}uint32} \PYG{n}{time\PYGZus{}req}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}OID\PYGZus{}set} \PYG{n}{desired\PYGZus{}mechs}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}cred\PYGZus{}usage\PYGZus{}t} \PYG{n}{cred\PYGZus{}usage}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}cred\PYGZus{}id\PYGZus{}t} \PYG{o}{*}\PYG{n}{output\PYGZus{}cred}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}OID\PYGZus{}set} \PYG{o}{*}\PYG{n}{actual\PYGZus{}mechs}\PYG{p}{,} + \PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{time\PYGZus{}rec}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The parameters to this function are similar to those of +\sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.2}{gss\_acquire\_cred}, except that \sphinxstyleemphasis{icred} is used to make an S4U2Self +request to the KDC for a ticket from \sphinxstyleemphasis{desired\_name} to the +intermediate service. Both \sphinxstyleemphasis{icred} and \sphinxstyleemphasis{desired\_name} are required +for this function; passing \sphinxstylestrong{GSS\_C\_NO\_CREDENTIAL} or +\sphinxstylestrong{GSS\_C\_NO\_NAME} will cause the call to fail. \sphinxstyleemphasis{icred} must contain a +krbtgt ticket for the intermediate service. The result of this +operation is a proxy credential. (Prior to release 1.18, the result +of this operation may be a regular credential for \sphinxstyleemphasis{desired\_name}, if +the KDC issues a non\sphinxhyphen{}forwardable ticket.) + +\sphinxAtStartPar +Once the intermediate service has a proxy credential, it can simply +pass it to \sphinxhref{https://tools.ietf.org/html/rfc2744.html\#section-5.19}{gss\_init\_sec\_context} as the \sphinxstyleemphasis{initiator\_cred\_handle} +parameter, and the desired service as the \sphinxstyleemphasis{target\_name} parameter. +The GSSAPI library will present the krbtgt ticket and evidence ticket +in the proxy credential to the KDC in an S4U2Proxy request; if the +intermediate service has the appropriate permissions, the KDC will +issue a ticket from the client to the target service. The GSSAPI +library will then use this ticket to authenticate to the target +service. + +\sphinxAtStartPar +If an application needs to find out whether a credential it holds is a +proxy credential and the name of the intermediate service, it can +query the credential with the \sphinxstylestrong{GSS\_KRB5\_GET\_CRED\_IMPERSONATOR} OID +(new in release 1.16, declared in \sphinxcode{\sphinxupquote{\textless{}gssapi/gssapi\_krb5.h\textgreater{}}}) using +the gss\_inquire\_cred\_by\_oid extension (declared in +\sphinxcode{\sphinxupquote{\textless{}gssapi/gssapi\_ext.h\textgreater{}}}): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}inquire\PYGZus{}cred\PYGZus{}by\PYGZus{}oid}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{const} \PYG{n}{gss\PYGZus{}cred\PYGZus{}id\PYGZus{}t} \PYG{n}{cred\PYGZus{}handle}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}OID} \PYG{n}{desired\PYGZus{}object}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}buffer\PYGZus{}set\PYGZus{}t} \PYG{o}{*}\PYG{n}{data\PYGZus{}set}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If the call succeeds and \sphinxstyleemphasis{cred\_handle} is a proxy credential, +\sphinxstyleemphasis{data\_set} will be set to a single\sphinxhyphen{}element buffer set containing the +unparsed principal name of the intermediate service. If \sphinxstyleemphasis{cred\_handle} +is not a proxy credential, \sphinxstyleemphasis{data\_set} will be set to an empty buffer +set. If the library does not support the query, +gss\_inquire\_cred\_by\_oid will return \sphinxstylestrong{GSS\_S\_UNAVAILABLE}. + + +\section{AEAD message wrapping} +\label{\detokenize{appdev/gssapi:aead-message-wrapping}} +\sphinxAtStartPar +The following GSSAPI extensions (declared in +\sphinxcode{\sphinxupquote{\textless{}gssapi/gssapi\_ext.h\textgreater{}}}) can be used to wrap and unwrap messages +with additional “associated data” which is integrity\sphinxhyphen{}checked but is +not included in the output buffer: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}wrap\PYGZus{}aead}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}ctx\PYGZus{}id\PYGZus{}t} \PYG{n}{context\PYGZus{}handle}\PYG{p}{,} + \PYG{n+nb}{int} \PYG{n}{conf\PYGZus{}req\PYGZus{}flag}\PYG{p}{,} \PYG{n}{gss\PYGZus{}qop\PYGZus{}t} \PYG{n}{qop\PYGZus{}req}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}buffer\PYGZus{}t} \PYG{n}{input\PYGZus{}assoc\PYGZus{}buffer}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}buffer\PYGZus{}t} \PYG{n}{input\PYGZus{}payload\PYGZus{}buffer}\PYG{p}{,} + \PYG{n+nb}{int} \PYG{o}{*}\PYG{n}{conf\PYGZus{}state}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}buffer\PYGZus{}t} \PYG{n}{output\PYGZus{}message\PYGZus{}buffer}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}unwrap\PYGZus{}aead}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}ctx\PYGZus{}id\PYGZus{}t} \PYG{n}{context\PYGZus{}handle}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}buffer\PYGZus{}t} \PYG{n}{input\PYGZus{}message\PYGZus{}buffer}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}buffer\PYGZus{}t} \PYG{n}{input\PYGZus{}assoc\PYGZus{}buffer}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}buffer\PYGZus{}t} \PYG{n}{output\PYGZus{}payload\PYGZus{}buffer}\PYG{p}{,} + \PYG{n+nb}{int} \PYG{o}{*}\PYG{n}{conf\PYGZus{}state}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}qop\PYGZus{}t} \PYG{o}{*}\PYG{n}{qop\PYGZus{}state}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Wrap tokens created with gss\_wrap\_aead will successfully unwrap only +if the same \sphinxstyleemphasis{input\_assoc\_buffer} contents are presented to +gss\_unwrap\_aead. + + +\section{IOV message wrapping} +\label{\detokenize{appdev/gssapi:iov-message-wrapping}} +\sphinxAtStartPar +The following extensions (declared in \sphinxcode{\sphinxupquote{\textless{}gssapi/gssapi\_ext.h\textgreater{}}}) can +be used for in\sphinxhyphen{}place encryption, fine\sphinxhyphen{}grained control over wrap token +layout, and for constructing wrap tokens compatible with Microsoft DCE +RPC: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{typedef} \PYG{n}{struct} \PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc\PYGZus{}struct} \PYG{p}{\PYGZob{}} + \PYG{n}{OM\PYGZus{}uint32} \PYG{n+nb}{type}\PYG{p}{;} + \PYG{n}{gss\PYGZus{}buffer\PYGZus{}desc} \PYG{n}{buffer}\PYG{p}{;} +\PYG{p}{\PYGZcb{}} \PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc}\PYG{p}{,} \PYG{o}{*}\PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}t}\PYG{p}{;} + +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}wrap\PYGZus{}iov}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}ctx\PYGZus{}id\PYGZus{}t} \PYG{n}{context\PYGZus{}handle}\PYG{p}{,} + \PYG{n+nb}{int} \PYG{n}{conf\PYGZus{}req\PYGZus{}flag}\PYG{p}{,} \PYG{n}{gss\PYGZus{}qop\PYGZus{}t} \PYG{n}{qop\PYGZus{}req}\PYG{p}{,} + \PYG{n+nb}{int} \PYG{o}{*}\PYG{n}{conf\PYGZus{}state}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc} \PYG{o}{*}\PYG{n}{iov}\PYG{p}{,} \PYG{n+nb}{int} \PYG{n}{iov\PYGZus{}count}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}unwrap\PYGZus{}iov}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}ctx\PYGZus{}id\PYGZus{}t} \PYG{n}{context\PYGZus{}handle}\PYG{p}{,} + \PYG{n+nb}{int} \PYG{o}{*}\PYG{n}{conf\PYGZus{}state}\PYG{p}{,} \PYG{n}{gss\PYGZus{}qop\PYGZus{}t} \PYG{o}{*}\PYG{n}{qop\PYGZus{}state}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc} \PYG{o}{*}\PYG{n}{iov}\PYG{p}{,} \PYG{n+nb}{int} \PYG{n}{iov\PYGZus{}count}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}wrap\PYGZus{}iov\PYGZus{}length}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}ctx\PYGZus{}id\PYGZus{}t} \PYG{n}{context\PYGZus{}handle}\PYG{p}{,} + \PYG{n+nb}{int} \PYG{n}{conf\PYGZus{}req\PYGZus{}flag}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}qop\PYGZus{}t} \PYG{n}{qop\PYGZus{}req}\PYG{p}{,} \PYG{n+nb}{int} \PYG{o}{*}\PYG{n}{conf\PYGZus{}state}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc} \PYG{o}{*}\PYG{n}{iov}\PYG{p}{,} + \PYG{n+nb}{int} \PYG{n}{iov\PYGZus{}count}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}release\PYGZus{}iov\PYGZus{}buffer}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc} \PYG{o}{*}\PYG{n}{iov}\PYG{p}{,} + \PYG{n+nb}{int} \PYG{n}{iov\PYGZus{}count}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The caller of gss\_wrap\_iov provides an array of gss\_iov\_buffer\_desc +structures, each containing a type and a gss\_buffer\_desc structure. +Valid types include: +\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_BUFFER\_TYPE\_DATA}: A data buffer to be included in the +token, and to be encrypted or decrypted in\sphinxhyphen{}place if the token is +confidentiality\sphinxhyphen{}protected. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_BUFFER\_TYPE\_HEADER}: The GSSAPI wrap token header and +underlying cryptographic header. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_BUFFER\_TYPE\_TRAILER}: The cryptographic trailer, if one is +required. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_BUFFER\_TYPE\_PADDING}: Padding to be combined with the data +during encryption and decryption. (The implementation may choose to +place padding in the trailer buffer, in which case it will set the +padding buffer length to 0.) + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_BUFFER\_TYPE\_STREAM}: For unwrapping only, a buffer +containing a complete wrap token in standard format to be unwrapped. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_BUFFER\_TYPE\_SIGN\_ONLY}: A buffer to be included in the +token’s integrity protection checksum, but not to be encrypted or +included in the token itself. + +\end{itemize} + +\sphinxAtStartPar +For gss\_wrap\_iov, the IOV list should contain one HEADER buffer, +followed by zero or more SIGN\_ONLY buffers, followed by one or more +DATA buffers, followed by a TRAILER buffer. The memory pointed to by +the buffers is not required to be contiguous or in any particular +order. If \sphinxstyleemphasis{conf\_req\_flag} is true, DATA buffers will be encrypted +in\sphinxhyphen{}place, while SIGN\_ONLY buffers will not be modified. + +\sphinxAtStartPar +The type of an output buffer may be combined with +\sphinxstylestrong{GSS\_C\_BUFFER\_FLAG\_ALLOCATE} to request that gss\_wrap\_iov allocate +the buffer contents. If gss\_wrap\_iov allocates a buffer, it sets the +\sphinxstylestrong{GSS\_C\_BUFFER\_FLAG\_ALLOCATED} flag on the buffer type. +gss\_release\_iov\_buffer can be used to release all allocated buffers +within an iov list and unset their allocated flags. Here is an +example of how gss\_wrap\_iov can be used with allocation requested +(\sphinxstyleemphasis{ctx} is assumed to be a previously established gss\_ctx\_id\_t): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{major}\PYG{p}{,} \PYG{n}{minor}\PYG{p}{;} +\PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc} \PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{4}\PYG{p}{]}\PYG{p}{;} +\PYG{n}{char} \PYG{n+nb}{str}\PYG{p}{[}\PYG{p}{]} \PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{message}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{;} + +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}HEADER} \PYG{o}{|} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}FLAG\PYGZus{}ALLOCATE}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}DATA}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{value} \PYG{o}{=} \PYG{n+nb}{str}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{length} \PYG{o}{=} \PYG{n}{strlen}\PYG{p}{(}\PYG{n+nb}{str}\PYG{p}{)}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{2}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}PADDING} \PYG{o}{|} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}FLAG\PYGZus{}ALLOCATE}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{3}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}TRAILER} \PYG{o}{|} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}FLAG\PYGZus{}ALLOCATE}\PYG{p}{;} + +\PYG{n}{major} \PYG{o}{=} \PYG{n}{gss\PYGZus{}wrap\PYGZus{}iov}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{minor}\PYG{p}{,} \PYG{n}{ctx}\PYG{p}{,} \PYG{l+m+mi}{1}\PYG{p}{,} \PYG{n}{GSS\PYGZus{}C\PYGZus{}QOP\PYGZus{}DEFAULT}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} + \PYG{n}{iov}\PYG{p}{,} \PYG{l+m+mi}{4}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{GSS\PYGZus{}ERROR}\PYG{p}{(}\PYG{n}{major}\PYG{p}{)}\PYG{p}{)} + \PYG{n}{handle\PYGZus{}error}\PYG{p}{(}\PYG{n}{major}\PYG{p}{,} \PYG{n}{minor}\PYG{p}{)}\PYG{p}{;} + +\PYG{o}{/}\PYG{o}{*} \PYG{n}{Transmit} \PYG{o+ow}{or} \PYG{n}{otherwise} \PYG{n}{use} \PYG{n}{resulting} \PYG{n}{buffers}\PYG{o}{.} \PYG{o}{*}\PYG{o}{/} + +\PYG{p}{(}\PYG{n}{void}\PYG{p}{)}\PYG{n}{gss\PYGZus{}release\PYGZus{}iov\PYGZus{}buffer}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{minor}\PYG{p}{,} \PYG{n}{iov}\PYG{p}{,} \PYG{l+m+mi}{4}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If the caller does not choose to request buffer allocation by +gss\_wrap\_iov, it should first call gss\_wrap\_iov\_length to query the +lengths of the HEADER, PADDING, and TRAILER buffers. DATA buffers +must be provided in the iov list so that padding length can be +computed correctly, but the output buffers need not be initialized. +Here is an example of using gss\_wrap\_iov\_length and gss\_wrap\_iov: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{major}\PYG{p}{,} \PYG{n}{minor}\PYG{p}{;} +\PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc} \PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{4}\PYG{p}{]}\PYG{p}{;} +\PYG{n}{char} \PYG{n+nb}{str}\PYG{p}{[}\PYG{l+m+mi}{1024}\PYG{p}{]} \PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{message}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{,} \PYG{o}{*}\PYG{n}{ptr}\PYG{p}{;} + +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}HEADER}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}DATA}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{value} \PYG{o}{=} \PYG{n+nb}{str}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{length} \PYG{o}{=} \PYG{n}{strlen}\PYG{p}{(}\PYG{n+nb}{str}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{2}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}PADDING}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{3}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}TRAILER}\PYG{p}{;} + +\PYG{n}{major} \PYG{o}{=} \PYG{n}{gss\PYGZus{}wrap\PYGZus{}iov\PYGZus{}length}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{minor}\PYG{p}{,} \PYG{n}{ctx}\PYG{p}{,} \PYG{l+m+mi}{1}\PYG{p}{,} \PYG{n}{GSS\PYGZus{}C\PYGZus{}QOP\PYGZus{}DEFAULT}\PYG{p}{,} + \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{iov}\PYG{p}{,} \PYG{l+m+mi}{4}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{GSS\PYGZus{}ERROR}\PYG{p}{(}\PYG{n}{major}\PYG{p}{)}\PYG{p}{)} + \PYG{n}{handle\PYGZus{}error}\PYG{p}{(}\PYG{n}{major}\PYG{p}{,} \PYG{n}{minor}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{strlen}\PYG{p}{(}\PYG{n+nb}{str}\PYG{p}{)} \PYG{o}{+} \PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{length} \PYG{o}{+} \PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{2}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{length} \PYG{o}{+} + \PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{3}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{length} \PYG{o}{\PYGZgt{}} \PYG{n}{sizeof}\PYG{p}{(}\PYG{n+nb}{str}\PYG{p}{)}\PYG{p}{)} + \PYG{n}{handle\PYGZus{}out\PYGZus{}of\PYGZus{}space\PYGZus{}error}\PYG{p}{(}\PYG{p}{)}\PYG{p}{;} +\PYG{n}{ptr} \PYG{o}{=} \PYG{n+nb}{str} \PYG{o}{+} \PYG{n}{strlen}\PYG{p}{(}\PYG{n+nb}{str}\PYG{p}{)}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{value} \PYG{o}{=} \PYG{n}{ptr}\PYG{p}{;} +\PYG{n}{ptr} \PYG{o}{+}\PYG{o}{=} \PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{length}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{2}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{value} \PYG{o}{=} \PYG{n}{ptr}\PYG{p}{;} +\PYG{n}{ptr} \PYG{o}{+}\PYG{o}{=} \PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{2}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{length}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{3}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{value} \PYG{o}{=} \PYG{n}{ptr}\PYG{p}{;} + +\PYG{n}{major} \PYG{o}{=} \PYG{n}{gss\PYGZus{}wrap\PYGZus{}iov}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{minor}\PYG{p}{,} \PYG{n}{ctx}\PYG{p}{,} \PYG{l+m+mi}{1}\PYG{p}{,} \PYG{n}{GSS\PYGZus{}C\PYGZus{}QOP\PYGZus{}DEFAULT}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} + \PYG{n}{iov}\PYG{p}{,} \PYG{l+m+mi}{4}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{GSS\PYGZus{}ERROR}\PYG{p}{(}\PYG{n}{major}\PYG{p}{)}\PYG{p}{)} + \PYG{n}{handle\PYGZus{}error}\PYG{p}{(}\PYG{n}{major}\PYG{p}{,} \PYG{n}{minor}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If the context was established using the \sphinxstylestrong{GSS\_C\_DCE\_STYLE} flag +(described in \index{RFC@\spxentry{RFC}!RFC 4757@\spxentry{RFC 4757}}\sphinxhref{https://tools.ietf.org/html/rfc4757.html}{\sphinxstylestrong{RFC 4757}}), wrap tokens compatible with Microsoft DCE +RPC can be constructed. In this case, the IOV list must include a +SIGN\_ONLY buffer, a DATA buffer, a second SIGN\_ONLY buffer, and a +HEADER buffer in that order (the order of the buffer contents remains +arbitrary). The application must pad the DATA buffer to a multiple of +16 bytes as no padding or trailer buffer is used. + +\sphinxAtStartPar +gss\_unwrap\_iov may be called with an IOV list just like one which +would be provided to gss\_wrap\_iov. DATA buffers will be decrypted +in\sphinxhyphen{}place if they were encrypted, and SIGN\_ONLY buffers will not be +modified. + +\sphinxAtStartPar +Alternatively, gss\_unwrap\_iov may be called with a single STREAM +buffer, zero or more SIGN\_ONLY buffers, and a single DATA buffer. The +STREAM buffer is interpreted as a complete wrap token. The STREAM +buffer will be modified in\sphinxhyphen{}place to decrypt its contents. The DATA +buffer will be initialized to point to the decrypted data within the +STREAM buffer, unless it has the \sphinxstylestrong{GSS\_C\_BUFFER\_FLAG\_ALLOCATE} flag +set, in which case it will be initialized with a copy of the decrypted +data. Here is an example (\sphinxstyleemphasis{token} and \sphinxstyleemphasis{token\_len} are assumed to be a +pre\sphinxhyphen{}existing pointer and length for a modifiable region of data): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{major}\PYG{p}{,} \PYG{n}{minor}\PYG{p}{;} +\PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc} \PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{2}\PYG{p}{]}\PYG{p}{;} + +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}STREAM}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{value} \PYG{o}{=} \PYG{n}{token}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{length} \PYG{o}{=} \PYG{n}{token\PYGZus{}len}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}DATA}\PYG{p}{;} +\PYG{n}{major} \PYG{o}{=} \PYG{n}{gss\PYGZus{}unwrap\PYGZus{}iov}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{minor}\PYG{p}{,} \PYG{n}{ctx}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{iov}\PYG{p}{,} \PYG{l+m+mi}{2}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{GSS\PYGZus{}ERROR}\PYG{p}{(}\PYG{n}{major}\PYG{p}{)}\PYG{p}{)} + \PYG{n}{handle\PYGZus{}error}\PYG{p}{(}\PYG{n}{major}\PYG{p}{,} \PYG{n}{minor}\PYG{p}{)}\PYG{p}{;} + +\PYG{o}{/}\PYG{o}{*} \PYG{n}{Decrypted} \PYG{n}{data} \PYG{o+ow}{is} \PYG{o+ow}{in} \PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{p}{,} \PYG{n}{pointing} \PYG{n}{to} \PYG{n}{a} \PYG{n}{subregion} \PYG{n}{of} + \PYG{o}{*} \PYG{n}{token}\PYG{o}{.} \PYG{o}{*}\PYG{o}{/} +\end{sphinxVerbatim} + + +\section{IOV MIC tokens} +\label{\detokenize{appdev/gssapi:iov-mic-tokens}}\label{\detokenize{appdev/gssapi:gssapi-mic-token}} +\sphinxAtStartPar +The following extensions (declared in \sphinxcode{\sphinxupquote{\textless{}gssapi/gssapi\_ext.h\textgreater{}}}) can +be used in release 1.12 or later to construct and verify MIC tokens +using an IOV list: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}get\PYGZus{}mic\PYGZus{}iov}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}ctx\PYGZus{}id\PYGZus{}t} \PYG{n}{context\PYGZus{}handle}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}qop\PYGZus{}t} \PYG{n}{qop\PYGZus{}req}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc} \PYG{o}{*}\PYG{n}{iov}\PYG{p}{,} + \PYG{n+nb}{int} \PYG{n}{iov\PYGZus{}count}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}get\PYGZus{}mic\PYGZus{}iov\PYGZus{}length}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}ctx\PYGZus{}id\PYGZus{}t} \PYG{n}{context\PYGZus{}handle}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}qop\PYGZus{}t} \PYG{n}{qop\PYGZus{}req}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc} \PYG{o}{*}\PYG{n}{iov}\PYG{p}{,} + \PYG{n}{iov\PYGZus{}count}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{gss\PYGZus{}verify\PYGZus{}mic\PYGZus{}iov}\PYG{p}{(}\PYG{n}{OM\PYGZus{}uint32} \PYG{o}{*}\PYG{n}{minor\PYGZus{}status}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}ctx\PYGZus{}id\PYGZus{}t} \PYG{n}{context\PYGZus{}handle}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}qop\PYGZus{}t} \PYG{o}{*}\PYG{n}{qop\PYGZus{}state}\PYG{p}{,} + \PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc} \PYG{o}{*}\PYG{n}{iov}\PYG{p}{,} + \PYG{n+nb}{int} \PYG{n}{iov\PYGZus{}count}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The caller of gss\_get\_mic\_iov provides an array of gss\_iov\_buffer\_desc +structures, each containing a type and a gss\_buffer\_desc structure. +Valid types include: +\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_BUFFER\_TYPE\_DATA} and \sphinxstylestrong{GSS\_C\_BUFFER\_TYPE\_SIGN\_ONLY}: The +corresponding buffer for each of these types will be signed for the +MIC token, in the order provided. + +\item {} +\sphinxAtStartPar +\sphinxstylestrong{GSS\_C\_BUFFER\_TYPE\_MIC\_TOKEN}: The GSSAPI MIC token. + +\end{itemize} + +\sphinxAtStartPar +The type of the MIC\_TOKEN buffer may be combined with +\sphinxstylestrong{GSS\_C\_BUFFER\_FLAG\_ALLOCATE} to request that gss\_get\_mic\_iov +allocate the buffer contents. If gss\_get\_mic\_iov allocates the +buffer, it sets the \sphinxstylestrong{GSS\_C\_BUFFER\_FLAG\_ALLOCATED} flag on the buffer +type. gss\_release\_iov\_buffer can be used to release all allocated +buffers within an iov list and unset their allocated flags. Here is +an example of how gss\_get\_mic\_iov can be used with allocation +requested (\sphinxstyleemphasis{ctx} is assumed to be a previously established +gss\_ctx\_id\_t): + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{major}\PYG{p}{,} \PYG{n}{minor}\PYG{p}{;} +\PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc} \PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{3}\PYG{p}{]}\PYG{p}{;} + +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}DATA}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{value} \PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{sign1}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{length} \PYG{o}{=} \PYG{l+m+mi}{5}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}SIGN\PYGZus{}ONLY}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{value} \PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{sign2}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{length} \PYG{o}{=} \PYG{l+m+mi}{5}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{2}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}MIC\PYGZus{}TOKEN} \PYG{o}{|} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}FLAG\PYGZus{}ALLOCATE}\PYG{p}{;} + +\PYG{n}{major} \PYG{o}{=} \PYG{n}{gss\PYGZus{}get\PYGZus{}mic\PYGZus{}iov}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{minor}\PYG{p}{,} \PYG{n}{ctx}\PYG{p}{,} \PYG{n}{GSS\PYGZus{}C\PYGZus{}QOP\PYGZus{}DEFAULT}\PYG{p}{,} \PYG{n}{iov}\PYG{p}{,} \PYG{l+m+mi}{3}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{GSS\PYGZus{}ERROR}\PYG{p}{(}\PYG{n}{major}\PYG{p}{)}\PYG{p}{)} + \PYG{n}{handle\PYGZus{}error}\PYG{p}{(}\PYG{n}{major}\PYG{p}{,} \PYG{n}{minor}\PYG{p}{)}\PYG{p}{;} + +\PYG{o}{/}\PYG{o}{*} \PYG{n}{Transmit} \PYG{o+ow}{or} \PYG{n}{otherwise} \PYG{n}{use} \PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{2}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.} \PYG{o}{*}\PYG{o}{/} + +\PYG{p}{(}\PYG{n}{void}\PYG{p}{)}\PYG{n}{gss\PYGZus{}release\PYGZus{}iov\PYGZus{}buffer}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{minor}\PYG{p}{,} \PYG{n}{iov}\PYG{p}{,} \PYG{l+m+mi}{3}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +If the caller does not choose to request buffer allocation by +gss\_get\_mic\_iov, it should first call gss\_get\_mic\_iov\_length to query +the length of the MIC\_TOKEN buffer. Here is an example of using +gss\_get\_mic\_iov\_length and gss\_get\_mic\_iov: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{OM\PYGZus{}uint32} \PYG{n}{major}\PYG{p}{,} \PYG{n}{minor}\PYG{p}{;} +\PYG{n}{gss\PYGZus{}iov\PYGZus{}buffer\PYGZus{}desc} \PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{2}\PYG{p}{]}\PYG{p}{;} +\PYG{n}{char} \PYG{n}{data}\PYG{p}{[}\PYG{l+m+mi}{1024}\PYG{p}{]}\PYG{p}{;} + +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}MIC\PYGZus{}TOKEN}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{type} \PYG{o}{=} \PYG{n}{GSS\PYGZus{}IOV\PYGZus{}BUFFER\PYGZus{}TYPE\PYGZus{}DATA}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{value} \PYG{o}{=} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{message}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{1}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{length} \PYG{o}{=} \PYG{l+m+mi}{7}\PYG{p}{;} + +\PYG{n}{major} \PYG{o}{=} \PYG{n}{gss\PYGZus{}get\PYGZus{}mic\PYGZus{}iov\PYGZus{}length}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{minor}\PYG{p}{,} \PYG{n}{ctx}\PYG{p}{,} \PYG{n}{GSS\PYGZus{}C\PYGZus{}QOP\PYGZus{}DEFAULT}\PYG{p}{,} \PYG{n}{iov}\PYG{p}{,} \PYG{l+m+mi}{2}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{GSS\PYGZus{}ERROR}\PYG{p}{(}\PYG{n}{major}\PYG{p}{)}\PYG{p}{)} + \PYG{n}{handle\PYGZus{}error}\PYG{p}{(}\PYG{n}{major}\PYG{p}{,} \PYG{n}{minor}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{length} \PYG{o}{\PYGZgt{}} \PYG{n}{sizeof}\PYG{p}{(}\PYG{n}{data}\PYG{p}{)}\PYG{p}{)} + \PYG{n}{handle\PYGZus{}out\PYGZus{}of\PYGZus{}space\PYGZus{}error}\PYG{p}{(}\PYG{p}{)}\PYG{p}{;} +\PYG{n}{iov}\PYG{p}{[}\PYG{l+m+mi}{0}\PYG{p}{]}\PYG{o}{.}\PYG{n}{buffer}\PYG{o}{.}\PYG{n}{value} \PYG{o}{=} \PYG{n}{data}\PYG{p}{;} + +\PYG{n}{major} \PYG{o}{=} \PYG{n}{gss\PYGZus{}get\PYGZus{}mic\PYGZus{}iov}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{minor}\PYG{p}{,} \PYG{n}{ctx}\PYG{p}{,} \PYG{n}{GSS\PYGZus{}C\PYGZus{}QOP\PYGZus{}DEFAULT}\PYG{p}{,} \PYG{n}{iov}\PYG{p}{,} \PYG{l+m+mi}{2}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{GSS\PYGZus{}ERROR}\PYG{p}{(}\PYG{n}{major}\PYG{p}{)}\PYG{p}{)} + \PYG{n}{handle\PYGZus{}error}\PYG{p}{(}\PYG{n}{major}\PYG{p}{,} \PYG{n}{minor}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + + +\chapter{Year 2038 considerations for uses of krb5\_timestamp} +\label{\detokenize{appdev/y2038:year-2038-considerations-for-uses-of-krb5-timestamp}}\label{\detokenize{appdev/y2038::doc}} +\sphinxAtStartPar +POSIX time values, which measure the number of seconds since January 1 +1970, will exceed the maximum value representable in a signed 32\sphinxhyphen{}bit +integer in January 2038. This documentation describes considerations +for consumers of the MIT krb5 libraries. + +\sphinxAtStartPar +Applications or libraries which use libkrb5 and consume the timestamps +included in credentials or other structures make use of the +{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_timestamp}}}}} type. For historical reasons, krb5\_timestamp +is a signed 32\sphinxhyphen{}bit integer, even on platforms where a larger type is +natively used to represent time values. To behave properly for time +values after January 2038, calling code should cast krb5\_timestamp +values to uint32\_t, and then to time\_t: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{(}\PYG{n}{time\PYGZus{}t}\PYG{p}{)}\PYG{p}{(}\PYG{n}{uint32\PYGZus{}t}\PYG{p}{)}\PYG{n}{timestamp} +\end{sphinxVerbatim} + +\sphinxAtStartPar +Used in this way, krb5\_timestamp values can represent time values up +until February 2106, provided that the platform uses a 64\sphinxhyphen{}bit or +larger time\_t type. This usage will also remain safe if a later +version of MIT krb5 changes krb5\_timestamp to an unsigned 32\sphinxhyphen{}bit +integer. + +\sphinxAtStartPar +The GSSAPI only uses representations of time intervals, not absolute +times. Callers of the GSSAPI should require no changes to behave +correctly after January 2038, provided that they use MIT krb5 release +1.16 or later. + + +\chapter{Differences between Heimdal and MIT Kerberos API} +\label{\detokenize{appdev/h5l_mit_apidiff:differences-between-heimdal-and-mit-kerberos-api}}\label{\detokenize{appdev/h5l_mit_apidiff::doc}} + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|l|l|} +\hline + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_auth_con_getaddrs:c.krb5_auth_con_getaddrs}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_auth\_con\_getaddrs()}}}}} +& +\sphinxAtStartPar +H5l: If either of the pointers to local\_addr +and remote\_addr is not NULL, it is freed +first and then reallocated before being +populated with the content of corresponding +address from authentication context. +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_auth_con_setaddrs:c.krb5_auth_con_setaddrs}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_auth\_con\_setaddrs()}}}}} +& +\sphinxAtStartPar +H5l: If either address is NULL, the previous +address remains in place +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_auth_con_setports:c.krb5_auth_con_setports}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_auth\_con\_setports()}}}}} +& +\sphinxAtStartPar +H5l: Not implemented as of version 1.3.3 +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_auth_con_setrecvsubkey:c.krb5_auth_con_setrecvsubkey}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_auth\_con\_setrecvsubkey()}}}}} +& +\sphinxAtStartPar +H5l: If either port is NULL, the previous +port remains in place +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_auth_con_setsendsubkey:c.krb5_auth_con_setsendsubkey}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_auth\_con\_setsendsubkey()}}}}} +& +\sphinxAtStartPar +H5l: Not implemented as of version 1.3.3 +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_cc_set_config:c.krb5_cc_set_config}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_cc\_set\_config()}}}}} +& +\sphinxAtStartPar +MIT: Before version 1.10 it was assumed that +the last argument \sphinxstyleemphasis{data} is ALWAYS non\sphinxhyphen{}zero. +\\ +\hline +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_cccol\_last\_change\_time()}} +& +\sphinxAtStartPar +MIT: not implemented +\\ +\hline +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_set_default_realm:c.krb5_set_default_realm}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_set\_default\_realm()}}}}} +& +\sphinxAtStartPar +H5l: Caches the computed default realm context +field. If the second argument is NULL, +it tries to retrieve it from libdefaults or DNS. +MIT: Computes the default realm each time +if it wasn’t explicitly set in the context +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\chapter{Initial credentials} +\label{\detokenize{appdev/init_creds:initial-credentials}}\label{\detokenize{appdev/init_creds::doc}} +\sphinxAtStartPar +Software that performs tasks such as logging users into a computer +when they type their Kerberos password needs to get initial +credentials (usually ticket granting tickets) from Kerberos. Such +software shares some behavior with the \DUrole{xref,std,std-ref}{kinit(1)} program. + +\sphinxAtStartPar +Whenever a program grants access to a resource (such as a local login +session on a desktop computer) based on a user successfully getting +initial Kerberos credentials, it must verify those credentials against +a secure shared secret (e.g., a host keytab) to ensure that the user +credentials actually originate from a legitimate KDC. Failure to +perform this verification is a critical vulnerability, because a +malicious user can execute the “Zanarotti attack”: the user constructs +a fake response that appears to come from the legitimate KDC, but +whose contents come from an attacker\sphinxhyphen{}controlled KDC. + +\sphinxAtStartPar +Some applications read a Kerberos password over the network (ideally +over a secure channel), which they then verify against the KDC. While +this technique may be the only practical way to integrate Kerberos +into some existing legacy systems, its use is contrary to the original +design goals of Kerberos. + +\sphinxAtStartPar +The function {\hyperref[\detokenize{appdev/refs/api/krb5_get_init_creds_password:c.krb5_get_init_creds_password}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_get\_init\_creds\_password()}}}}} will get initial +credentials for a client using a password. An application that needs +to verify the credentials can call {\hyperref[\detokenize{appdev/refs/api/krb5_verify_init_creds:c.krb5_verify_init_creds}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_verify\_init\_creds()}}}}}. +Here is an example of code to obtain and verify TGT credentials, given +strings \sphinxstyleemphasis{princname} and \sphinxstyleemphasis{password} for the client principal name and +password: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{krb5\PYGZus{}error\PYGZus{}code} \PYG{n}{ret}\PYG{p}{;} +\PYG{n}{krb5\PYGZus{}creds} \PYG{n}{creds}\PYG{p}{;} +\PYG{n}{krb5\PYGZus{}principal} \PYG{n}{client\PYGZus{}princ} \PYG{o}{=} \PYG{n}{NULL}\PYG{p}{;} + +\PYG{n}{memset}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{creds}\PYG{p}{,} \PYG{l+m+mi}{0}\PYG{p}{,} \PYG{n}{sizeof}\PYG{p}{(}\PYG{n}{creds}\PYG{p}{)}\PYG{p}{)}\PYG{p}{;} +\PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}parse\PYGZus{}name}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{n}{princname}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{client\PYGZus{}princ}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{ret}\PYG{p}{)} + \PYG{n}{goto} \PYG{n}{cleanup}\PYG{p}{;} +\PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}password}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{creds}\PYG{p}{,} \PYG{n}{client\PYGZus{}princ}\PYG{p}{,} + \PYG{n}{password}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{l+m+mi}{0}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{ret}\PYG{p}{)} + \PYG{n}{goto} \PYG{n}{cleanup}\PYG{p}{;} +\PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}verify\PYGZus{}init\PYGZus{}creds}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{creds}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{cleanup}\PYG{p}{:} +\PYG{n}{krb5\PYGZus{}free\PYGZus{}principal}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{n}{client\PYGZus{}princ}\PYG{p}{)}\PYG{p}{;} +\PYG{n}{krb5\PYGZus{}free\PYGZus{}cred\PYGZus{}contents}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{creds}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{return} \PYG{n}{ret}\PYG{p}{;} +\end{sphinxVerbatim} + + +\section{Options for get\_init\_creds} +\label{\detokenize{appdev/init_creds:options-for-get-init-creds}} +\sphinxAtStartPar +The function {\hyperref[\detokenize{appdev/refs/api/krb5_get_init_creds_password:c.krb5_get_init_creds_password}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_get\_init\_creds\_password()}}}}} takes an options +parameter (which can be a null pointer). Use the function +{\hyperref[\detokenize{appdev/refs/api/krb5_get_init_creds_opt_alloc:c.krb5_get_init_creds_opt_alloc}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_get\_init\_creds\_opt\_alloc()}}}}} to allocate an options +structure, and {\hyperref[\detokenize{appdev/refs/api/krb5_get_init_creds_opt_free:c.krb5_get_init_creds_opt_free}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_get\_init\_creds\_opt\_free()}}}}} to free it. For +example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{krb5\PYGZus{}error\PYGZus{}code} \PYG{n}{ret}\PYG{p}{;} +\PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}opt} \PYG{o}{*}\PYG{n}{opt} \PYG{o}{=} \PYG{n}{NULL}\PYG{p}{;} +\PYG{n}{krb5\PYGZus{}creds} \PYG{n}{creds}\PYG{p}{;} + +\PYG{n}{memset}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{creds}\PYG{p}{,} \PYG{l+m+mi}{0}\PYG{p}{,} \PYG{n}{sizeof}\PYG{p}{(}\PYG{n}{creds}\PYG{p}{)}\PYG{p}{)}\PYG{p}{;} +\PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}opt\PYGZus{}alloc}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{opt}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{ret}\PYG{p}{)} + \PYG{n}{goto} \PYG{n}{cleanup}\PYG{p}{;} +\PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}opt\PYGZus{}set\PYGZus{}tkt\PYGZus{}life}\PYG{p}{(}\PYG{n}{opt}\PYG{p}{,} \PYG{l+m+mi}{24} \PYG{o}{*} \PYG{l+m+mi}{60} \PYG{o}{*} \PYG{l+m+mi}{60}\PYG{p}{)}\PYG{p}{;} +\PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}password}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{creds}\PYG{p}{,} \PYG{n}{client\PYGZus{}princ}\PYG{p}{,} + \PYG{n}{password}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{l+m+mi}{0}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{opt}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{ret}\PYG{p}{)} + \PYG{n}{goto} \PYG{n}{cleanup}\PYG{p}{;} + +\PYG{n}{cleanup}\PYG{p}{:} +\PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}opt\PYGZus{}free}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{n}{opt}\PYG{p}{)}\PYG{p}{;} +\PYG{n}{krb5\PYGZus{}free\PYGZus{}cred\PYGZus{}contents}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{creds}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{return} \PYG{n}{ret}\PYG{p}{;} +\end{sphinxVerbatim} + + +\section{Getting anonymous credentials} +\label{\detokenize{appdev/init_creds:getting-anonymous-credentials}} +\sphinxAtStartPar +As of release 1.8, it is possible to obtain fully anonymous or +partially anonymous (realm\sphinxhyphen{}exposed) credentials, if the KDC supports +it. The MIT KDC supports issuing fully anonymous credentials as of +release 1.8 if configured appropriately (see \DUrole{xref,std,std-ref}{anonymous\_pkinit}), +but does not support issuing realm\sphinxhyphen{}exposed anonymous credentials at +this time. + +\sphinxAtStartPar +To obtain fully anonymous credentials, call +{\hyperref[\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_anonymous:c.krb5_get_init_creds_opt_set_anonymous}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_get\_init\_creds\_opt\_set\_anonymous()}}}}} on the options +structure to set the anonymous flag, and specify a client principal +with the KDC’s realm and a single empty data component (the principal +obtained by parsing \sphinxcode{\sphinxupquote{@}}\sphinxstyleemphasis{realmname}). Authentication will take +place using anonymous PKINIT; if successful, the client principal of +the resulting tickets will be +\sphinxcode{\sphinxupquote{WELLKNOWN/ANONYMOUS@WELLKNOWN:ANONYMOUS}}. Here is an example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}opt\PYGZus{}set\PYGZus{}anonymous}\PYG{p}{(}\PYG{n}{opt}\PYG{p}{,} \PYG{l+m+mi}{1}\PYG{p}{)}\PYG{p}{;} +\PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}build\PYGZus{}principal}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{client\PYGZus{}princ}\PYG{p}{,} \PYG{n}{strlen}\PYG{p}{(}\PYG{n}{myrealm}\PYG{p}{)}\PYG{p}{,} + \PYG{n}{myrealm}\PYG{p}{,} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{,} \PYG{p}{(}\PYG{n}{char} \PYG{o}{*}\PYG{p}{)}\PYG{n}{NULL}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{ret}\PYG{p}{)} + \PYG{n}{goto} \PYG{n}{cleanup}\PYG{p}{;} +\PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}password}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{creds}\PYG{p}{,} \PYG{n}{client\PYGZus{}princ}\PYG{p}{,} + \PYG{n}{password}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{l+m+mi}{0}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{opt}\PYG{p}{)}\PYG{p}{;} +\PYG{k}{if} \PYG{p}{(}\PYG{n}{ret}\PYG{p}{)} + \PYG{n}{goto} \PYG{n}{cleanup}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +To obtain realm\sphinxhyphen{}exposed anonymous credentials, set the anonymous flag +on the options structure as above, but specify a normal client +principal in order to prove membership in the realm. Authentication +will take place as it normally does; if successful, the client +principal of the resulting tickets will be \sphinxcode{\sphinxupquote{WELLKNOWN/ANONYMOUS@}}\sphinxstyleemphasis{realmname}. + + +\section{User interaction} +\label{\detokenize{appdev/init_creds:user-interaction}} +\sphinxAtStartPar +Authenticating a user usually requires the entry of secret +information, such as a password. A password can be supplied directly +to {\hyperref[\detokenize{appdev/refs/api/krb5_get_init_creds_password:c.krb5_get_init_creds_password}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_get\_init\_creds\_password()}}}}} via the \sphinxstyleemphasis{password} +parameter, or the application can supply prompter and/or responder +callbacks instead. If callbacks are used, the user can also be +queried for other secret information such as a PIN, informed of +impending password expiration, or prompted to change a password which +has expired. + + +\subsection{Prompter callback} +\label{\detokenize{appdev/init_creds:prompter-callback}} +\sphinxAtStartPar +A prompter callback can be specified via the \sphinxstyleemphasis{prompter} and \sphinxstyleemphasis{data} +parameters to {\hyperref[\detokenize{appdev/refs/api/krb5_get_init_creds_password:c.krb5_get_init_creds_password}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_get\_init\_creds\_password()}}}}}. The prompter +will be invoked each time the krb5 library has a question to ask or +information to present. When the prompter callback is invoked, the +\sphinxstyleemphasis{banner} argument (if not null) is intended to be displayed to the +user, and the questions to be answered are specified in the \sphinxstyleemphasis{prompts} +array. Each prompt contains a text question in the \sphinxstyleemphasis{prompt} field, a +\sphinxstyleemphasis{hidden} bit to indicate whether the answer should be hidden from +display, and a storage area for the answer in the \sphinxstyleemphasis{reply} field. The +callback should fill in each question’s \sphinxcode{\sphinxupquote{reply\sphinxhyphen{}\textgreater{}data}} with the +answer, up to a maximum number of \sphinxcode{\sphinxupquote{reply\sphinxhyphen{}\textgreater{}length}} bytes, and then +reset \sphinxcode{\sphinxupquote{reply\sphinxhyphen{}\textgreater{}length}} to the length of the answer. + +\sphinxAtStartPar +A prompter callback can call {\hyperref[\detokenize{appdev/refs/api/krb5_get_prompt_types:c.krb5_get_prompt_types}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_get\_prompt\_types()}}}}} to get an +array of type constants corresponding to the prompts, to get +programmatic information about the semantic meaning of the questions. +{\hyperref[\detokenize{appdev/refs/api/krb5_get_prompt_types:c.krb5_get_prompt_types}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_get\_prompt\_types()}}}}} may return a null pointer if no prompt +type information is available. + +\sphinxAtStartPar +Text\sphinxhyphen{}based applications can use a built\sphinxhyphen{}in text prompter +implementation by supplying {\hyperref[\detokenize{appdev/refs/api/krb5_prompter_posix:c.krb5_prompter_posix}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_prompter\_posix()}}}}} as the +\sphinxstyleemphasis{prompter} parameter and a null pointer as the \sphinxstyleemphasis{data} parameter. For +example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}password}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{creds}\PYG{p}{,} \PYG{n}{client\PYGZus{}princ}\PYG{p}{,} + \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{krb5\PYGZus{}prompter\PYGZus{}posix}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{l+m+mi}{0}\PYG{p}{,} + \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + + +\subsection{Responder callback} +\label{\detokenize{appdev/init_creds:responder-callback}} +\sphinxAtStartPar +A responder callback can be specified through the init\_creds options +using the {\hyperref[\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_responder:c.krb5_get_init_creds_opt_set_responder}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_get\_init\_creds\_opt\_set\_responder()}}}}} function. +Responder callbacks can present a more sophisticated user interface +for authentication secrets. The responder callback is usually invoked +only once per authentication, with a list of questions produced by all +of the allowed preauthentication mechanisms. + +\sphinxAtStartPar +When the responder callback is invoked, the \sphinxstyleemphasis{rctx} argument can be +accessed to obtain the list of questions and to answer them. The +{\hyperref[\detokenize{appdev/refs/api/krb5_responder_list_questions:c.krb5_responder_list_questions}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_responder\_list\_questions()}}}}} function retrieves an array of +question types. For each question type, the +{\hyperref[\detokenize{appdev/refs/api/krb5_responder_get_challenge:c.krb5_responder_get_challenge}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_responder\_get\_challenge()}}}}} function retrieves additional +information about the question, if applicable, and the +{\hyperref[\detokenize{appdev/refs/api/krb5_responder_set_answer:c.krb5_responder_set_answer}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_responder\_set\_answer()}}}}} function sets the answer. + +\sphinxAtStartPar +Responder question types, challenges, and answers are UTF\sphinxhyphen{}8 strings. +The question type is a well\sphinxhyphen{}known string; the meaning of the challenge +and answer depend on the question type. If an application does not +understand a question type, it cannot interpret the challenge or +provide an answer. Failing to answer a question typically results in +the prompter callback being used as a fallback. + + +\subsubsection{Password question} +\label{\detokenize{appdev/init_creds:password-question}} +\sphinxAtStartPar +The \sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_QUESTION\_PASSWORD}} (or \sphinxcode{\sphinxupquote{"password"}}) +question type requests the user’s password. This question does not +have a challenge, and the response is simply the password string. + + +\subsubsection{One\sphinxhyphen{}time password question} +\label{\detokenize{appdev/init_creds:one-time-password-question}} +\sphinxAtStartPar +The \sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_QUESTION\_OTP}} (or \sphinxcode{\sphinxupquote{"otp"}}) question +type requests a choice among one\sphinxhyphen{}time password tokens and the PIN and +value for the chosen token. The challenge and answer are JSON\sphinxhyphen{}encoded +strings, but an application can use convenience functions to avoid +doing any JSON processing itself. + +\sphinxAtStartPar +The {\hyperref[\detokenize{appdev/refs/api/krb5_responder_otp_get_challenge:c.krb5_responder_otp_get_challenge}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_responder\_otp\_get\_challenge()}}}}} function decodes the +challenge into a krb5\_responder\_otp\_challenge structure. The +{\hyperref[\detokenize{appdev/refs/api/krb5_responder_otp_set_answer:c.krb5_responder_otp_set_answer}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_responder\_otp\_set\_answer()}}}}} function selects one of the +token information elements from the challenge and supplies the value +and pin for that token. + + +\subsubsection{PKINIT password or PIN question} +\label{\detokenize{appdev/init_creds:pkinit-password-or-pin-question}} +\sphinxAtStartPar +The \sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_QUESTION\_PKINIT}} (or \sphinxcode{\sphinxupquote{"pkinit"}}) question +type requests PINs for hardware devices and/or passwords for encrypted +credentials which are stored on disk, potentially also supplying +information about the state of the hardware devices. The challenge and +answer are JSON\sphinxhyphen{}encoded strings, but an application can use convenience +functions to avoid doing any JSON processing itself. + +\sphinxAtStartPar +The {\hyperref[\detokenize{appdev/refs/api/krb5_responder_pkinit_get_challenge:c.krb5_responder_pkinit_get_challenge}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_responder\_pkinit\_get\_challenge()}}}}} function decodes the +challenges into a krb5\_responder\_pkinit\_challenge structure. The +{\hyperref[\detokenize{appdev/refs/api/krb5_responder_pkinit_set_answer:c.krb5_responder_pkinit_set_answer}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_responder\_pkinit\_set\_answer()}}}}} function can be used to +supply the PIN or password for a particular client credential, and can +be called multiple times. + + +\subsubsection{Example} +\label{\detokenize{appdev/init_creds:example}} +\sphinxAtStartPar +Here is an example of using a responder callback: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{static} \PYG{n}{krb5\PYGZus{}error\PYGZus{}code} +\PYG{n}{my\PYGZus{}responder}\PYG{p}{(}\PYG{n}{krb5\PYGZus{}context} \PYG{n}{context}\PYG{p}{,} \PYG{n}{void} \PYG{o}{*}\PYG{n}{data}\PYG{p}{,} + \PYG{n}{krb5\PYGZus{}responder\PYGZus{}context} \PYG{n}{rctx}\PYG{p}{)} +\PYG{p}{\PYGZob{}} + \PYG{n}{krb5\PYGZus{}error\PYGZus{}code} \PYG{n}{ret}\PYG{p}{;} + \PYG{n}{krb5\PYGZus{}responder\PYGZus{}otp\PYGZus{}challenge} \PYG{o}{*}\PYG{n}{chl}\PYG{p}{;} + + \PYG{k}{if} \PYG{p}{(}\PYG{n}{krb5\PYGZus{}responder\PYGZus{}get\PYGZus{}challenge}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{n}{rctx}\PYG{p}{,} + \PYG{n}{KRB5\PYGZus{}RESPONDER\PYGZus{}QUESTION\PYGZus{}PASSWORD}\PYG{p}{)}\PYG{p}{)} \PYG{p}{\PYGZob{}} + \PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}responder\PYGZus{}set\PYGZus{}answer}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{n}{rctx}\PYG{p}{,} + \PYG{n}{KRB5\PYGZus{}RESPONDER\PYGZus{}QUESTION\PYGZus{}PASSWORD}\PYG{p}{,} + \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{open sesame}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{)}\PYG{p}{;} + \PYG{k}{if} \PYG{p}{(}\PYG{n}{ret}\PYG{p}{)} + \PYG{k}{return} \PYG{n}{ret}\PYG{p}{;} + \PYG{p}{\PYGZcb{}} + \PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}responder\PYGZus{}otp\PYGZus{}get\PYGZus{}challenge}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{n}{rctx}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{chl}\PYG{p}{)}\PYG{p}{;} + \PYG{k}{if} \PYG{p}{(}\PYG{n}{ret} \PYG{o}{==} \PYG{l+m+mi}{0} \PYG{o}{\PYGZam{}}\PYG{o}{\PYGZam{}} \PYG{n}{chl} \PYG{o}{!=} \PYG{n}{NULL}\PYG{p}{)} \PYG{p}{\PYGZob{}} + \PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}responder\PYGZus{}otp\PYGZus{}set\PYGZus{}answer}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{n}{rctx}\PYG{p}{,} \PYG{l+m+mi}{0}\PYG{p}{,} \PYG{l+s+s2}{\PYGZdq{}}\PYG{l+s+s2}{1234}\PYG{l+s+s2}{\PYGZdq{}}\PYG{p}{,} + \PYG{n}{NULL}\PYG{p}{)}\PYG{p}{;} + \PYG{n}{krb5\PYGZus{}responder\PYGZus{}otp\PYGZus{}challenge\PYGZus{}free}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{n}{rctx}\PYG{p}{,} \PYG{n}{chl}\PYG{p}{)}\PYG{p}{;} + \PYG{k}{if} \PYG{p}{(}\PYG{n}{ret}\PYG{p}{)} + \PYG{k}{return} \PYG{n}{ret}\PYG{p}{;} + \PYG{p}{\PYGZcb{}} + \PYG{k}{return} \PYG{l+m+mi}{0}\PYG{p}{;} +\PYG{p}{\PYGZcb{}} + +\PYG{n}{static} \PYG{n}{krb5\PYGZus{}error\PYGZus{}code} +\PYG{n}{get\PYGZus{}creds}\PYG{p}{(}\PYG{n}{krb5\PYGZus{}context} \PYG{n}{context}\PYG{p}{,} \PYG{n}{krb5\PYGZus{}principal} \PYG{n}{client\PYGZus{}princ}\PYG{p}{)} +\PYG{p}{\PYGZob{}} + \PYG{n}{krb5\PYGZus{}error\PYGZus{}code} \PYG{n}{ret}\PYG{p}{;} + \PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}opt} \PYG{o}{*}\PYG{n}{opt} \PYG{o}{=} \PYG{n}{NULL}\PYG{p}{;} + \PYG{n}{krb5\PYGZus{}creds} \PYG{n}{creds}\PYG{p}{;} + + \PYG{n}{memset}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{creds}\PYG{p}{,} \PYG{l+m+mi}{0}\PYG{p}{,} \PYG{n}{sizeof}\PYG{p}{(}\PYG{n}{creds}\PYG{p}{)}\PYG{p}{)}\PYG{p}{;} + \PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}opt\PYGZus{}alloc}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{opt}\PYG{p}{)}\PYG{p}{;} + \PYG{k}{if} \PYG{p}{(}\PYG{n}{ret}\PYG{p}{)} + \PYG{n}{goto} \PYG{n}{cleanup}\PYG{p}{;} + \PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}opt\PYGZus{}set\PYGZus{}responder}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{n}{opt}\PYG{p}{,} \PYG{n}{my\PYGZus{}responder}\PYG{p}{,} + \PYG{n}{NULL}\PYG{p}{)}\PYG{p}{;} + \PYG{k}{if} \PYG{p}{(}\PYG{n}{ret}\PYG{p}{)} + \PYG{n}{goto} \PYG{n}{cleanup}\PYG{p}{;} + \PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}password}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{creds}\PYG{p}{,} \PYG{n}{client\PYGZus{}princ}\PYG{p}{,} + \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{l+m+mi}{0}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{opt}\PYG{p}{)}\PYG{p}{;} + +\PYG{n}{cleanup}\PYG{p}{:} + \PYG{n}{krb5\PYGZus{}get\PYGZus{}init\PYGZus{}creds\PYGZus{}opt\PYGZus{}free}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{n}{opt}\PYG{p}{)}\PYG{p}{;} + \PYG{n}{krb5\PYGZus{}free\PYGZus{}cred\PYGZus{}contents}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{creds}\PYG{p}{)}\PYG{p}{;} + \PYG{k}{return} \PYG{n}{ret}\PYG{p}{;} +\PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + + +\section{Verifying initial credentials} +\label{\detokenize{appdev/init_creds:verifying-initial-credentials}} +\sphinxAtStartPar +Use the function {\hyperref[\detokenize{appdev/refs/api/krb5_verify_init_creds:c.krb5_verify_init_creds}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_verify\_init\_creds()}}}}} to verify initial +credentials. It takes an options structure (which can be a null +pointer). Use {\hyperref[\detokenize{appdev/refs/api/krb5_verify_init_creds_opt_init:c.krb5_verify_init_creds_opt_init}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_verify\_init\_creds\_opt\_init()}}}}} to initialize +the caller\sphinxhyphen{}allocated options structure, and +{\hyperref[\detokenize{appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail:c.krb5_verify_init_creds_opt_set_ap_req_nofail}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_verify\_init\_creds\_opt\_set\_ap\_req\_nofail()}}}}} to set the +“nofail” option. For example: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{n}{krb5\PYGZus{}verify\PYGZus{}init\PYGZus{}creds\PYGZus{}opt} \PYG{n}{vopt}\PYG{p}{;} + +\PYG{n}{krb5\PYGZus{}verify\PYGZus{}init\PYGZus{}creds\PYGZus{}opt\PYGZus{}init}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{vopt}\PYG{p}{)}\PYG{p}{;} +\PYG{n}{krb5\PYGZus{}verify\PYGZus{}init\PYGZus{}creds\PYGZus{}opt\PYGZus{}set\PYGZus{}ap\PYGZus{}req\PYGZus{}nofail}\PYG{p}{(}\PYG{o}{\PYGZam{}}\PYG{n}{vopt}\PYG{p}{,} \PYG{l+m+mi}{1}\PYG{p}{)}\PYG{p}{;} +\PYG{n}{ret} \PYG{o}{=} \PYG{n}{krb5\PYGZus{}verify\PYGZus{}init\PYGZus{}creds}\PYG{p}{(}\PYG{n}{context}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{creds}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{n}{NULL}\PYG{p}{,} \PYG{o}{\PYGZam{}}\PYG{n}{vopt}\PYG{p}{)}\PYG{p}{;} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The confusingly named “nofail” option, when set, means that the +verification must actually succeed in order for +{\hyperref[\detokenize{appdev/refs/api/krb5_verify_init_creds:c.krb5_verify_init_creds}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_verify\_init\_creds()}}}}} to indicate success. The default +state of this option (cleared) means that if there is no key material +available to verify the user credentials, the verification will +succeed anyway. (The default can be changed by a configuration file +setting.) + +\sphinxAtStartPar +This accommodates a use case where a large number of unkeyed shared +desktop workstations need to allow users to log in using Kerberos. +The security risks from this practice are mitigated by the absence of +valuable state on the shared workstations—any valuable resources +that the users would access reside on networked servers. + + +\chapter{Principal manipulation and parsing} +\label{\detokenize{appdev/princ_handle:principal-manipulation-and-parsing}}\label{\detokenize{appdev/princ_handle::doc}} +\sphinxAtStartPar +Kerberos principal structure + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/types/krb5_principal_data:c.krb5_principal_data}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_principal\_data}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_principal}}}}} + +\sphinxAtStartPar +Create and free principal + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_build_principal:c.krb5_build_principal}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_build\_principal()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_build_principal_alloc_va:c.krb5_build_principal_alloc_va}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_build\_principal\_alloc\_va()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_build_principal_ext:c.krb5_build_principal_ext}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_build\_principal\_ext()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_copy_principal:c.krb5_copy_principal}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_copy\_principal()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_free_principal:c.krb5_free_principal}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_free\_principal()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_cc_get_principal:c.krb5_cc_get_principal}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_cc\_get\_principal()}}}}} + +\sphinxAtStartPar +Comparing + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_principal_compare:c.krb5_principal_compare}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_principal\_compare()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_principal_compare_flags:c.krb5_principal_compare_flags}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_principal\_compare\_flags()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_principal_compare_any_realm:c.krb5_principal_compare_any_realm}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_principal\_compare\_any\_realm()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_sname_match:c.krb5_sname_match}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_sname\_match()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_sname_to_principal:c.krb5_sname_to_principal}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_sname\_to\_principal()}}}}} + +\sphinxAtStartPar +Parsing: + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_parse_name:c.krb5_parse_name}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_parse\_name()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_parse_name_flags:c.krb5_parse_name_flags}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_parse\_name\_flags()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_unparse_name:c.krb5_unparse_name}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_unparse\_name()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_unparse_name_flags:c.krb5_unparse_name_flags}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_unparse\_name\_flags()}}}}} + +\sphinxAtStartPar +Utilities: + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_is_config_principal:c.krb5_is_config_principal}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_is\_config\_principal()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_kuserok:c.krb5_kuserok}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_kuserok()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_set_password:c.krb5_set_password}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_set\_password()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_set_password_using_ccache:c.krb5_set_password_using_ccache}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_set\_password\_using\_ccache()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_set_principal_realm:c.krb5_set_principal_realm}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_set\_principal\_realm()}}}}} + +\sphinxAtStartPar +{\hyperref[\detokenize{appdev/refs/api/krb5_realm_compare:c.krb5_realm_compare}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_realm\_compare()}}}}} + + +\chapter{Complete reference \sphinxhyphen{} API and datatypes} +\label{\detokenize{appdev/refs/index:complete-reference-api-and-datatypes}}\label{\detokenize{appdev/refs/index::doc}} + +\section{krb5 API} +\label{\detokenize{appdev/refs/api/index:krb5-api}}\label{\detokenize{appdev/refs/api/index::doc}} + +\subsection{Frequently used public interfaces} +\label{\detokenize{appdev/refs/api/index:frequently-used-public-interfaces}} + +\subsubsection{krb5\_build\_principal \sphinxhyphen{} Build a principal name using null\sphinxhyphen{}terminated strings.} +\label{\detokenize{appdev/refs/api/krb5_build_principal:krb5-build-principal-build-a-principal-name-using-null-terminated-strings}}\label{\detokenize{appdev/refs/api/krb5_build_principal::doc}}\index{krb5\_build\_principal (C function)@\spxentry{krb5\_build\_principal}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_build_principal:c.krb5_build_principal}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_build\_principal}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{princ}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{rlen}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{realm}, \DUrole{p}{...}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{princ} \sphinxhyphen{} Principal name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rlen} \sphinxhyphen{} Realm name length + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{realm} \sphinxhyphen{} Realm name + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Call krb5\_free\_principal() to free \sphinxstyleemphasis{princ} when it is no longer needed. + +\sphinxAtStartPar +Beginning with release 1.20, the name type of the principal will be inferred as \sphinxstylestrong{KRB5\_NT\_SRV\_INST} or \sphinxstylestrong{KRB5\_NT\_WELLKNOWN} based on the principal name. The type will be \sphinxstylestrong{KRB5\_NT\_PRINCIPAL} if a type cannot be inferred. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +krb5\_build\_principal() and krb5\_build\_principal\_alloc\_va() perform the same task. krb5\_build\_principal() takes variadic arguments. krb5\_build\_principal\_alloc\_va() takes a pre\sphinxhyphen{}computed \sphinxstyleemphasis{varargs} pointer. +\end{sphinxadmonition} + + +\subsubsection{krb5\_build\_principal\_alloc\_va \sphinxhyphen{} Build a principal name, using a precomputed variable argument list.} +\label{\detokenize{appdev/refs/api/krb5_build_principal_alloc_va:krb5-build-principal-alloc-va-build-a-principal-name-using-a-precomputed-variable-argument-list}}\label{\detokenize{appdev/refs/api/krb5_build_principal_alloc_va::doc}}\index{krb5\_build\_principal\_alloc\_va (C function)@\spxentry{krb5\_build\_principal\_alloc\_va}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_build_principal_alloc_va:c.krb5_build_principal_alloc_va}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_build\_principal\_alloc\_va}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{princ}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{rlen}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{realm}, \DUrole{n}{va\_list}\DUrole{w}{ }\DUrole{n}{ap}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{princ} \sphinxhyphen{} Principal structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rlen} \sphinxhyphen{} Realm name length + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{realm} \sphinxhyphen{} Realm name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ap} \sphinxhyphen{} List of char * components, ending with NULL + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Similar to krb5\_build\_principal(), this function builds a principal name, but its name components are specified as a va\_list. + +\sphinxAtStartPar +Use krb5\_free\_principal() to deallocate \sphinxstyleemphasis{princ} when it is no longer needed. + + +\subsubsection{krb5\_build\_principal\_ext \sphinxhyphen{} Build a principal name using length\sphinxhyphen{}counted strings.} +\label{\detokenize{appdev/refs/api/krb5_build_principal_ext:krb5-build-principal-ext-build-a-principal-name-using-length-counted-strings}}\label{\detokenize{appdev/refs/api/krb5_build_principal_ext::doc}}\index{krb5\_build\_principal\_ext (C function)@\spxentry{krb5\_build\_principal\_ext}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_build_principal_ext:c.krb5_build_principal_ext}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_build\_principal\_ext}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{princ}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{rlen}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{realm}, \DUrole{p}{...}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{princ} \sphinxhyphen{} Principal name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rlen} \sphinxhyphen{} Realm name length + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{realm} \sphinxhyphen{} Realm name + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a principal from a length\sphinxhyphen{}counted string and a variable\sphinxhyphen{}length list of length\sphinxhyphen{}counted components. The list of components ends with the first 0 length argument (so it is not possible to specify an empty component with this function). Call krb5\_free\_principal() to free allocated memory for principal when it is no longer needed. + +\sphinxAtStartPar +Beginning with release 1.20, the name type of the principal will be inferred as \sphinxstylestrong{KRB5\_NT\_SRV\_INST} or \sphinxstylestrong{KRB5\_NT\_WELLKNOWN} based on the principal name. The type will be \sphinxstylestrong{KRB5\_NT\_PRINCIPAL} if a type cannot be inferred. + + +\subsubsection{krb5\_cc\_close \sphinxhyphen{} Close a credential cache handle.} +\label{\detokenize{appdev/refs/api/krb5_cc_close:krb5-cc-close-close-a-credential-cache-handle}}\label{\detokenize{appdev/refs/api/krb5_cc_close::doc}}\index{krb5\_cc\_close (C function)@\spxentry{krb5\_cc\_close}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_close:c.krb5_cc_close}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_close}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function closes a credential cache handle \sphinxstyleemphasis{cache} without affecting the contents of the cache. + + +\subsubsection{krb5\_cc\_default \sphinxhyphen{} Resolve the default credential cache name.} +\label{\detokenize{appdev/refs/api/krb5_cc_default:krb5-cc-default-resolve-the-default-credential-cache-name}}\label{\detokenize{appdev/refs/api/krb5_cc_default::doc}}\index{krb5\_cc\_default (C function)@\spxentry{krb5\_cc\_default}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_default:c.krb5_cc_default}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_default}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ccache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ccache} \sphinxhyphen{} Pointer to credential cache name + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +KV5M\_CONTEXT Bad magic number for \_krb5\_context structure + +\item {} +\sphinxAtStartPar +KRB5\_FCC\_INTERNAL The name of the default credential cache cannot be obtained + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Create a handle to the default credential cache as given by krb5\_cc\_default\_name(). + + +\subsubsection{krb5\_cc\_default\_name \sphinxhyphen{} Return the name of the default credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_default_name:krb5-cc-default-name-return-the-name-of-the-default-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_default_name::doc}}\index{krb5\_cc\_default\_name (C function)@\spxentry{krb5\_cc\_default\_name}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_default_name:c.krb5_cc_default_name}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_default\_name}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Name of default credential cache for the current user. + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Return a pointer to the default credential cache name for \sphinxstyleemphasis{context} , as determined by a prior call to krb5\_cc\_set\_default\_name(), by the KRB5CCNAME environment variable, by the default\_ccache\_name profile variable, or by the operating system or build\sphinxhyphen{}time default value. The returned value must not be modified or freed by the caller. The returned value becomes invalid when \sphinxstyleemphasis{context} is destroyed krb5\_free\_context() or if a subsequent call to krb5\_cc\_set\_default\_name() is made on \sphinxstyleemphasis{context} . + +\sphinxAtStartPar +The default credential cache name is cached in \sphinxstyleemphasis{context} between calls to this function, so if the value of KRB5CCNAME changes in the process environment after the first call to this function on, that change will not be reflected in later calls with the same context. The caller can invoke krb5\_cc\_set\_default\_name() with a NULL value of \sphinxstyleemphasis{name} to clear the cached value and force the default name to be recomputed. + + +\subsubsection{krb5\_cc\_destroy \sphinxhyphen{} Destroy a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_destroy:krb5-cc-destroy-destroy-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_destroy::doc}}\index{krb5\_cc\_destroy (C function)@\spxentry{krb5\_cc\_destroy}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_destroy:c.krb5_cc_destroy}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_destroy}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Permission errors + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function destroys any existing contents of \sphinxstyleemphasis{cache} and closes the handle to it. + + +\subsubsection{krb5\_cc\_dup \sphinxhyphen{} Duplicate ccache handle.} +\label{\detokenize{appdev/refs/api/krb5_cc_dup:krb5-cc-dup-duplicate-ccache-handle}}\label{\detokenize{appdev/refs/api/krb5_cc_dup::doc}}\index{krb5\_cc\_dup (C function)@\spxentry{krb5\_cc\_dup}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_dup:c.krb5_cc_dup}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_dup}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{in}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in} \sphinxhyphen{} Credential cache handle to be duplicated + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{out} \sphinxhyphen{} Credential cache handle + +\end{description}\end{quote} + +\sphinxAtStartPar +Create a new handle referring to the same cache as \sphinxstyleemphasis{in} . The new handle and \sphinxstyleemphasis{in} can be closed independently. + + +\subsubsection{krb5\_cc\_get\_name \sphinxhyphen{} Retrieve the name, but not type of a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_get_name:krb5-cc-get-name-retrieve-the-name-but-not-type-of-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_get_name::doc}}\index{krb5\_cc\_get\_name (C function)@\spxentry{krb5\_cc\_get\_name}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_get_name:c.krb5_cc_get_name}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_get\_name}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +On success \sphinxhyphen{} the name of the credential cache. + +\end{itemize} + +\end{description}\end{quote} + +\begin{sphinxadmonition}{warning}{Warning:} +\sphinxAtStartPar +Returns the name of the credential cache. The result is an alias into \sphinxstyleemphasis{cache} and should not be freed or modified by the caller. This name does not include the cache type, so should not be used as input to krb5\_cc\_resolve(). +\end{sphinxadmonition} + + +\subsubsection{krb5\_cc\_get\_principal \sphinxhyphen{} Get the default principal of a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_get_principal:krb5-cc-get-principal-get-the-default-principal-of-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_get_principal::doc}}\index{krb5\_cc\_get\_principal (C function)@\spxentry{krb5\_cc\_get\_principal}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_get_principal:c.krb5_cc_get_principal}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_get\_principal}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{principal}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Primary principal + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Returns the default client principal of a credential cache as set by krb5\_cc\_initialize(). + +\sphinxAtStartPar +Use krb5\_free\_principal() to free \sphinxstyleemphasis{principal} when it is no longer needed. + + +\subsubsection{krb5\_cc\_get\_type \sphinxhyphen{} Retrieve the type of a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_get_type:krb5-cc-get-type-retrieve-the-type-of-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_get_type::doc}}\index{krb5\_cc\_get\_type (C function)@\spxentry{krb5\_cc\_get\_type}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_get_type:c.krb5_cc_get_type}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_get\_type}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +The type of a credential cache as an alias that must not be modified or freed by the caller. + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_cc\_initialize \sphinxhyphen{} Initialize a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_initialize:krb5-cc-initialize-initialize-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_initialize::doc}}\index{krb5\_cc\_initialize (C function)@\spxentry{krb5\_cc\_initialize}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_initialize:c.krb5_cc_initialize}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_initialize}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Default principal name + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +System errors; Permission errors; Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Destroy any existing contents of \sphinxstyleemphasis{cache} and initialize it for the default principal \sphinxstyleemphasis{principal} . + + +\subsubsection{krb5\_cc\_new\_unique \sphinxhyphen{} Create a new credential cache of the specified type with a unique name.} +\label{\detokenize{appdev/refs/api/krb5_cc_new_unique:krb5-cc-new-unique-create-a-new-credential-cache-of-the-specified-type-with-a-unique-name}}\label{\detokenize{appdev/refs/api/krb5_cc_new_unique::doc}}\index{krb5\_cc\_new\_unique (C function)@\spxentry{krb5\_cc\_new\_unique}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_new_unique:c.krb5_cc_new_unique}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_new\_unique}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{type}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{hint}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{id}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{type} \sphinxhyphen{} Credential cache type name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{hint} \sphinxhyphen{} Unused + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{id} \sphinxhyphen{} Credential cache handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_cc\_resolve \sphinxhyphen{} Resolve a credential cache name.} +\label{\detokenize{appdev/refs/api/krb5_cc_resolve:krb5-cc-resolve-resolve-a-credential-cache-name}}\label{\detokenize{appdev/refs/api/krb5_cc_resolve::doc}}\index{krb5\_cc\_resolve (C function)@\spxentry{krb5\_cc\_resolve}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_resolve:c.krb5_cc_resolve}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_resolve}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{name}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{name} \sphinxhyphen{} Credential cache name to be resolved + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Fills in \sphinxstyleemphasis{cache} with a \sphinxstyleemphasis{cache} handle that corresponds to the name in \sphinxstyleemphasis{name} . \sphinxstyleemphasis{name} should be of the form \sphinxstylestrong{type:residual} , and \sphinxstyleemphasis{type} must be a type known to the library. If the \sphinxstyleemphasis{name} does not contain a colon, interpret it as a file name. + + +\subsubsection{krb5\_change\_password \sphinxhyphen{} Change a password for an existing Kerberos account.} +\label{\detokenize{appdev/refs/api/krb5_change_password:krb5-change-password-change-a-password-for-an-existing-kerberos-account}}\label{\detokenize{appdev/refs/api/krb5_change_password::doc}}\index{krb5\_change\_password (C function)@\spxentry{krb5\_change\_password}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_change_password:c.krb5_change_password}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_change\_password}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{newpw}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{result\_code}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{result\_code\_string}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{result\_string}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Credentials for kadmin/changepw service + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{newpw} \sphinxhyphen{} New password + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{result\_code} \sphinxhyphen{} Numeric error code from server + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{result\_code\_string} \sphinxhyphen{} String equivalent to \sphinxstyleemphasis{result\_code} + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{result\_string} \sphinxhyphen{} Change password response from the KDC + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Change the password for the existing principal identified by \sphinxstyleemphasis{creds} . + +\sphinxAtStartPar +The possible values of the output \sphinxstyleemphasis{result\_code} are: +\begin{itemize} +\item {} +\sphinxAtStartPar +\#KRB5\_KPASSWD\_SUCCESS (0) \sphinxhyphen{} success + +\item {} +\sphinxAtStartPar +\#KRB5\_KPASSWD\_MALFORMED (1) \sphinxhyphen{} Malformed request error + +\item {} +\sphinxAtStartPar +\#KRB5\_KPASSWD\_HARDERROR (2) \sphinxhyphen{} Server error + +\item {} +\sphinxAtStartPar +\#KRB5\_KPASSWD\_AUTHERROR (3) \sphinxhyphen{} Authentication error + +\item {} +\sphinxAtStartPar +\#KRB5\_KPASSWD\_SOFTERROR (4) \sphinxhyphen{} Password change rejected + +\end{itemize} + + +\subsubsection{krb5\_chpw\_message \sphinxhyphen{} Get a result message for changing or setting a password.} +\label{\detokenize{appdev/refs/api/krb5_chpw_message:krb5-chpw-message-get-a-result-message-for-changing-or-setting-a-password}}\label{\detokenize{appdev/refs/api/krb5_chpw_message::doc}}\index{krb5\_chpw\_message (C function)@\spxentry{krb5\_chpw\_message}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_chpw_message:c.krb5_chpw_message}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_chpw\_message}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{server\_string}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{message\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server\_string} \sphinxhyphen{} Data returned from the remote system + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{message\_out} \sphinxhyphen{} A message displayable to the user + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function processes the \sphinxstyleemphasis{server\_string} returned in the \sphinxstyleemphasis{result\_string} parameter of krb5\_change\_password(), krb5\_set\_password(), and related functions, and returns a displayable string. If \sphinxstyleemphasis{server\_string} contains Active Directory structured policy information, it will be converted into human\sphinxhyphen{}readable text. + +\sphinxAtStartPar +Use krb5\_free\_string() to free \sphinxstyleemphasis{message\_out} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.11 +\end{sphinxadmonition} + + +\subsubsection{krb5\_expand\_hostname \sphinxhyphen{} Canonicalize a hostname, possibly using name service.} +\label{\detokenize{appdev/refs/api/krb5_expand_hostname:krb5-expand-hostname-canonicalize-a-hostname-possibly-using-name-service}}\label{\detokenize{appdev/refs/api/krb5_expand_hostname::doc}}\index{krb5\_expand\_hostname (C function)@\spxentry{krb5\_expand\_hostname}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_expand_hostname:c.krb5_expand_hostname}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_expand\_hostname}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{host}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{canonhost\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{host} \sphinxhyphen{} Input hostname + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{canonhost\_out} \sphinxhyphen{} Canonicalized hostname + +\end{description}\end{quote} + +\sphinxAtStartPar +This function canonicalizes orig\_hostname, possibly using name service lookups if configuration permits. Use krb5\_free\_string() to free \sphinxstyleemphasis{canonhost\_out} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.15 +\end{sphinxadmonition} + + +\subsubsection{krb5\_free\_context \sphinxhyphen{} Free a krb5 library context.} +\label{\detokenize{appdev/refs/api/krb5_free_context:krb5-free-context-free-a-krb5-library-context}}\label{\detokenize{appdev/refs/api/krb5_free_context::doc}}\index{krb5\_free\_context (C function)@\spxentry{krb5\_free\_context}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_context:c.krb5_free_context}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_context}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees a \sphinxstyleemphasis{context} that was created by krb5\_init\_context() or krb5\_init\_secure\_context(). + + +\subsubsection{krb5\_free\_error\_message \sphinxhyphen{} Free an error message generated by krb5\_get\_error\_message().} +\label{\detokenize{appdev/refs/api/krb5_free_error_message:krb5-free-error-message-free-an-error-message-generated-by-krb5-get-error-message}}\label{\detokenize{appdev/refs/api/krb5_free_error_message::doc}}\index{krb5\_free\_error\_message (C function)@\spxentry{krb5\_free\_error\_message}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_error_message:c.krb5_free_error_message}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_error\_message}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{msg}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{msg} \sphinxhyphen{} Pointer to error message + +\end{description}\end{quote} + + +\subsubsection{krb5\_free\_principal \sphinxhyphen{} Free the storage assigned to a principal.} +\label{\detokenize{appdev/refs/api/krb5_free_principal:krb5-free-principal-free-the-storage-assigned-to-a-principal}}\label{\detokenize{appdev/refs/api/krb5_free_principal::doc}}\index{krb5\_free\_principal (C function)@\spxentry{krb5\_free\_principal}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_principal:c.krb5_free_principal}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_principal}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Principal to be freed + +\end{description}\end{quote} + + +\subsubsection{krb5\_fwd\_tgt\_creds \sphinxhyphen{} Get a forwarded TGT and format a KRB\sphinxhyphen{}CRED message.} +\label{\detokenize{appdev/refs/api/krb5_fwd_tgt_creds:krb5-fwd-tgt-creds-get-a-forwarded-tgt-and-format-a-krb-cred-message}}\label{\detokenize{appdev/refs/api/krb5_fwd_tgt_creds::doc}}\index{krb5\_fwd\_tgt\_creds (C function)@\spxentry{krb5\_fwd\_tgt\_creds}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_fwd_tgt_creds:c.krb5_fwd_tgt_creds}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_fwd\_tgt\_creds}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{rhost}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{client}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{server}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cc}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{forwardable}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{outbuf}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rhost} \sphinxhyphen{} Remote host + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{client} \sphinxhyphen{} Client principal of TGT + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server} \sphinxhyphen{} Principal of server to receive TGT + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cc} \sphinxhyphen{} Credential cache handle (NULL to use default) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{forwardable} \sphinxhyphen{} Whether TGT should be forwardable + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{outbuf} \sphinxhyphen{} KRB\sphinxhyphen{}CRED message + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +ENOMEM Insufficient memory + +\item {} +\sphinxAtStartPar +KRB5\_PRINC\_NOMATCH Requested principal and ticket do not match + +\item {} +\sphinxAtStartPar +KRB5\_NO\_TKT\_SUPPLIED Request did not supply a ticket + +\item {} +\sphinxAtStartPar +KRB5\_CC\_BADNAME Credential cache name or principal name malformed + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Get a TGT for use at the remote host \sphinxstyleemphasis{rhost} and format it into a KRB\sphinxhyphen{}CRED message. If \sphinxstyleemphasis{rhost} is NULL and \sphinxstyleemphasis{server} is of type \#KRB5\_NT\_SRV\_HST, the second component of \sphinxstyleemphasis{server} will be used. + + +\subsubsection{krb5\_get\_default\_realm \sphinxhyphen{} Retrieve the default realm.} +\label{\detokenize{appdev/refs/api/krb5_get_default_realm:krb5-get-default-realm-retrieve-the-default-realm}}\label{\detokenize{appdev/refs/api/krb5_get_default_realm::doc}}\index{krb5\_get\_default\_realm (C function)@\spxentry{krb5\_get\_default\_realm}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_default_realm:c.krb5_get_default_realm}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_default\_realm}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{lrealm}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{lrealm} \sphinxhyphen{} Default realm name + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Retrieves the default realm to be used if no user\sphinxhyphen{}specified realm is available. + +\sphinxAtStartPar +Use krb5\_free\_default\_realm() to free \sphinxstyleemphasis{lrealm} when it is no longer needed. + + +\subsubsection{krb5\_get\_error\_message \sphinxhyphen{} Get the (possibly extended) error message for a code.} +\label{\detokenize{appdev/refs/api/krb5_get_error_message:krb5-get-error-message-get-the-possibly-extended-error-message-for-a-code}}\label{\detokenize{appdev/refs/api/krb5_get_error_message::doc}}\index{krb5\_get\_error\_message (C function)@\spxentry{krb5\_get\_error\_message}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_error_message:c.krb5_get_error_message}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_error\_message}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\DUrole{n}{code}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{code} \sphinxhyphen{} Error code + +\end{description}\end{quote} + +\sphinxAtStartPar +The behavior of krb5\_get\_error\_message() is only defined the first time it is called after a failed call to a krb5 function using the same context, and only when the error code passed in is the same as that returned by the krb5 function. + +\sphinxAtStartPar +This function never returns NULL, so its result may be used unconditionally as a C string. + +\sphinxAtStartPar +The string returned by this function must be freed using krb5\_free\_error\_message() + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +Future versions may return the same string for the second and following calls. +\end{sphinxadmonition} + + +\subsubsection{krb5\_get\_host\_realm \sphinxhyphen{} Get the Kerberos realm names for a host.} +\label{\detokenize{appdev/refs/api/krb5_get_host_realm:krb5-get-host-realm-get-the-kerberos-realm-names-for-a-host}}\label{\detokenize{appdev/refs/api/krb5_get_host_realm::doc}}\index{krb5\_get\_host\_realm (C function)@\spxentry{krb5\_get\_host\_realm}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_host_realm:c.krb5_get_host_realm}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_host\_realm}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{host}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{realmsp}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{host} \sphinxhyphen{} Host name (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{realmsp} \sphinxhyphen{} Null\sphinxhyphen{}terminated list of realm names + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +ENOMEM Insufficient memory + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Fill in \sphinxstyleemphasis{realmsp} with a pointer to a null\sphinxhyphen{}terminated list of realm names. If there are no known realms for the host, a list containing the referral (empty) realm is returned. + +\sphinxAtStartPar +If \sphinxstyleemphasis{host} is NULL, the local host’s realms are determined. + +\sphinxAtStartPar +Use krb5\_free\_host\_realm() to release \sphinxstyleemphasis{realmsp} when it is no longer needed. + + +\subsubsection{krb5\_get\_credentials \sphinxhyphen{} Get an additional ticket.} +\label{\detokenize{appdev/refs/api/krb5_get_credentials:krb5-get-credentials-get-an-additional-ticket}}\label{\detokenize{appdev/refs/api/krb5_get_credentials::doc}}\index{krb5\_get\_credentials (C function)@\spxentry{krb5\_get\_credentials}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_credentials:c.krb5_get_credentials}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_credentials}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{options}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{out\_creds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{options} \sphinxhyphen{} Options + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ccache} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in\_creds} \sphinxhyphen{} Input credentials + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{out\_creds} \sphinxhyphen{} Output updated credentials + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Use \sphinxstyleemphasis{ccache} or a TGS exchange to get a service ticket matching \sphinxstyleemphasis{in\_creds} . + +\sphinxAtStartPar +Valid values for \sphinxstyleemphasis{options} are: +\begin{quote} +\begin{itemize} +\item {} +\sphinxAtStartPar +\#KRB5\_GC\_CACHED Search only credential cache for the ticket + +\item {} +\sphinxAtStartPar +\#KRB5\_GC\_USER\_USER Return a user to user authentication ticket + +\end{itemize} + +\sphinxAtStartPar +\sphinxstyleemphasis{in\_creds} must be non\sphinxhyphen{}null. \sphinxstyleemphasis{in\_creds\sphinxhyphen{}\textgreater{}client} and \sphinxstyleemphasis{in\_creds\sphinxhyphen{}\textgreater{}server} must be filled in to specify the client and the server respectively. If any authorization data needs to be requested for the service ticket (such as restrictions on how the ticket can be used), specify it in \sphinxstyleemphasis{in\_creds\sphinxhyphen{}\textgreater{}authdata} ; otherwise set \sphinxstyleemphasis{in\_creds\sphinxhyphen{}\textgreater{}authdata} to NULL. The session key type is specified in \sphinxstyleemphasis{in\_creds\sphinxhyphen{}\textgreater{}keyblock.enctype} , if it is nonzero. +\end{quote} + +\sphinxAtStartPar +The expiration date is specified in \sphinxstyleemphasis{in\_creds\sphinxhyphen{}\textgreater{}times.endtime} . The KDC may return tickets with an earlier expiration date. If \sphinxstyleemphasis{in\_creds\sphinxhyphen{}\textgreater{}times.endtime} is set to 0, the latest possible expiration date will be requested. + +\sphinxAtStartPar +Any returned ticket and intermediate ticket\sphinxhyphen{}granting tickets are stored in \sphinxstyleemphasis{ccache} . + +\sphinxAtStartPar +Use krb5\_free\_creds() to free \sphinxstyleemphasis{out\_creds} when it is no longer needed. + + +\subsubsection{krb5\_get\_fallback\_host\_realm} +\label{\detokenize{appdev/refs/api/krb5_get_fallback_host_realm:krb5-get-fallback-host-realm}}\label{\detokenize{appdev/refs/api/krb5_get_fallback_host_realm::doc}}\index{krb5\_get\_fallback\_host\_realm (C function)@\spxentry{krb5\_get\_fallback\_host\_realm}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_fallback_host_realm:c.krb5_get_fallback_host_realm}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_fallback\_host\_realm}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{hdata}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{realmsp}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{hdata} \sphinxhyphen{} Host name (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{realmsp} \sphinxhyphen{} Null\sphinxhyphen{}terminated list of realm names + +\end{description}\end{quote} + +\sphinxAtStartPar +Fill in \sphinxstyleemphasis{realmsp} with a pointer to a null\sphinxhyphen{}terminated list of realm names obtained through heuristics or insecure resolution methods which have lower priority than KDC referrals. + +\sphinxAtStartPar +If \sphinxstyleemphasis{host} is NULL, the local host’s realms are determined. + +\sphinxAtStartPar +Use krb5\_free\_host\_realm() to release \sphinxstyleemphasis{realmsp} when it is no longer needed. + + +\subsubsection{krb5\_get\_init\_creds\_keytab \sphinxhyphen{} Get initial credentials using a key table.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_keytab:krb5-get-init-creds-keytab-get-initial-credentials-using-a-key-table}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_keytab::doc}}\index{krb5\_get\_init\_creds\_keytab (C function)@\spxentry{krb5\_get\_init\_creds\_keytab}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_keytab:c.krb5_get_init_creds_keytab}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_keytab}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{client}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{arg\_keytab}, {\hyperref[\detokenize{appdev/refs/types/krb5_deltat:c.krb5_deltat}]{\sphinxcrossref{\DUrole{n}{krb5\_deltat}}}}\DUrole{w}{ }\DUrole{n}{start\_time}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_tkt\_service}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{k5\_gic\_options}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{creds} \sphinxhyphen{} New credentials + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{client} \sphinxhyphen{} Client principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{arg\_keytab} \sphinxhyphen{} Key table handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{start\_time} \sphinxhyphen{} Time when ticket becomes valid (0 for now) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in\_tkt\_service} \sphinxhyphen{} Service name of initial credentials (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{k5\_gic\_options} \sphinxhyphen{} Initial credential options + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function requests KDC for an initial credentials for \sphinxstyleemphasis{client} using a client key stored in \sphinxstyleemphasis{arg\_keytab} . If \sphinxstyleemphasis{in\_tkt\_service} is specified, it is parsed as a principal name (with the realm ignored) and used as the service principal for the request; otherwise the ticket\sphinxhyphen{}granting service is used. + + +\subsubsection{krb5\_get\_init\_creds\_opt\_alloc \sphinxhyphen{} Allocate a new initial credential options structure.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_alloc:krb5-get-init-creds-opt-alloc-allocate-a-new-initial-credential-options-structure}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_alloc::doc}}\index{krb5\_get\_init\_creds\_opt\_alloc (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_alloc}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_alloc:c.krb5_get_init_creds_opt_alloc}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_alloc}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{opt}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{opt} \sphinxhyphen{} New options structure + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 \sphinxhyphen{} Success; Kerberos errors otherwise. + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function is the preferred way to create an options structure for getting initial credentials, and is required to make use of certain options. Use krb5\_get\_init\_creds\_opt\_free() to free \sphinxstyleemphasis{opt} when it is no longer needed. + + +\subsubsection{krb5\_get\_init\_creds\_opt\_free \sphinxhyphen{} Free initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_free:krb5-get-init-creds-opt-free-free-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_free::doc}}\index{krb5\_get\_init\_creds\_opt\_free (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_free}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_free:c.krb5_get_init_creds_opt_free}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_free}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure to free + +\end{description}\end{quote} + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_get\_init\_creds\_opt\_alloc() + + + + +\subsubsection{krb5\_get\_init\_creds\_opt\_get\_fast\_flags \sphinxhyphen{} Retrieve FAST flags from initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_get_fast_flags:krb5-get-init-creds-opt-get-fast-flags-retrieve-fast-flags-from-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_get_fast_flags::doc}}\index{krb5\_get\_init\_creds\_opt\_get\_fast\_flags (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_get\_fast\_flags}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_get_fast_flags:c.krb5_get_init_creds_opt_get_fast_flags}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_get\_fast\_flags}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{out\_flags}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{out\_flags} \sphinxhyphen{} FAST flags + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 \sphinxhyphen{} Success; Kerberos errors otherwise. + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_address\_list \sphinxhyphen{} Set address restrictions in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_address_list:krb5-get-init-creds-opt-set-address-list-set-address-restrictions-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_address_list::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_address\_list (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_address\_list}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_address_list:c.krb5_get_init_creds_opt_set_address_list}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_address\_list}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{addresses}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{addresses} \sphinxhyphen{} Null\sphinxhyphen{}terminated array of addresses + +\end{description}\end{quote} + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_anonymous \sphinxhyphen{} Set or unset the anonymous flag in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_anonymous:krb5-get-init-creds-opt-set-anonymous-set-or-unset-the-anonymous-flag-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_anonymous::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_anonymous (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_anonymous}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_anonymous:c.krb5_get_init_creds_opt_set_anonymous}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_anonymous}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{anonymous}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{anonymous} \sphinxhyphen{} Whether to make an anonymous request + +\end{description}\end{quote} + +\sphinxAtStartPar +This function may be used to request anonymous credentials from the KDC by setting \sphinxstyleemphasis{anonymous} to non\sphinxhyphen{}zero. Note that anonymous credentials are only a request; clients must verify that credentials are anonymous if that is a requirement. + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_canonicalize \sphinxhyphen{} Set or unset the canonicalize flag in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_canonicalize:krb5-get-init-creds-opt-set-canonicalize-set-or-unset-the-canonicalize-flag-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_canonicalize::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_canonicalize (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_canonicalize}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_canonicalize:c.krb5_get_init_creds_opt_set_canonicalize}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_canonicalize}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{canonicalize}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{canonicalize} \sphinxhyphen{} Whether to canonicalize client principal + +\end{description}\end{quote} + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_change\_password\_prompt \sphinxhyphen{} Set or unset change\sphinxhyphen{}password\sphinxhyphen{}prompt flag in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_change_password_prompt:krb5-get-init-creds-opt-set-change-password-prompt-set-or-unset-change-password-prompt-flag-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_change_password_prompt::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_change\_password\_prompt (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_change\_password\_prompt}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_change_password_prompt:c.krb5_get_init_creds_opt_set_change_password_prompt}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_change\_password\_prompt}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{prompt}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{prompt} \sphinxhyphen{} Whether to prompt to change password + +\end{description}\end{quote} + +\sphinxAtStartPar +This flag is on by default. It controls whether krb5\_get\_init\_creds\_password() will react to an expired\sphinxhyphen{}password error by prompting for a new password and attempting to change the old one. + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_etype\_list \sphinxhyphen{} Set allowable encryption types in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_etype_list:krb5-get-init-creds-opt-set-etype-list-set-allowable-encryption-types-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_etype_list::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_etype\_list (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_etype\_list}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_etype_list:c.krb5_get_init_creds_opt_set_etype_list}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_etype\_list}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{etype\_list}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{etype\_list\_length}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{etype\_list} \sphinxhyphen{} Array of encryption types + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{etype\_list\_length} \sphinxhyphen{} Length of \sphinxstyleemphasis{etype\_list} + +\end{description}\end{quote} + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_expire\_callback \sphinxhyphen{} Set an expiration callback in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_expire_callback:krb5-get-init-creds-opt-set-expire-callback-set-an-expiration-callback-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_expire_callback::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_expire\_callback (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_expire\_callback}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_expire_callback:c.krb5_get_init_creds_opt_set_expire_callback}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_expire\_callback}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_expire_callback_func:c.krb5_expire_callback_func}]{\sphinxcrossref{\DUrole{n}{krb5\_expire\_callback\_func}}}}\DUrole{w}{ }\DUrole{n}{cb}, \DUrole{kt}{void}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cb} \sphinxhyphen{} Callback function + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} Callback argument + +\end{description}\end{quote} + +\sphinxAtStartPar +Set a callback to receive password and account expiration times. +\begin{quote} + +\sphinxAtStartPar +\sphinxstyleemphasis{cb} will be invoked if and only if credentials are successfully acquired. The callback will receive the \sphinxstyleemphasis{context} from the calling function and the \sphinxstyleemphasis{data} argument supplied with this API. The remaining arguments should be interpreted as follows: +\end{quote} + +\sphinxAtStartPar +If \sphinxstyleemphasis{is\_last\_req} is true, then the KDC reply contained last\sphinxhyphen{}req entries which unambiguously indicated the password expiration, account expiration, or both. (If either value was not present, the corresponding argument will be 0.) Furthermore, a non\sphinxhyphen{}zero \sphinxstyleemphasis{password\_expiration} should be taken as a suggestion from the KDC that a warning be displayed. + +\sphinxAtStartPar +If \sphinxstyleemphasis{is\_last\_req} is false, then \sphinxstyleemphasis{account\_expiration} will be 0 and \sphinxstyleemphasis{password\_expiration} will contain the expiration time of either the password or account, or 0 if no expiration time was indicated in the KDC reply. The callback should independently decide whether to display a password expiration warning. + +\sphinxAtStartPar +Note that \sphinxstyleemphasis{cb} may be invoked even if credentials are being acquired for the kadmin/changepw service in order to change the password. It is the caller’s responsibility to avoid displaying a password expiry warning in this case. + +\begin{sphinxadmonition}{warning}{Warning:} +\sphinxAtStartPar +Setting an expire callback with this API will cause krb5\_get\_init\_creds\_password() not to send password expiry warnings to the prompter, as it ordinarily may. +\end{sphinxadmonition} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.9 +\end{sphinxadmonition} + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_fast\_ccache \sphinxhyphen{} Set FAST armor cache in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache:krb5-get-init-creds-opt-set-fast-ccache-set-fast-armor-cache-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_fast\_ccache (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_fast\_ccache}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache:c.krb5_get_init_creds_opt_set_fast_ccache}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_fast\_ccache}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ccache} \sphinxhyphen{} Credential cache handle + +\end{description}\end{quote} + +\sphinxAtStartPar +This function is similar to krb5\_get\_init\_creds\_opt\_set\_fast\_ccache\_name(), but uses a credential cache handle instead of a name. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.9 +\end{sphinxadmonition} + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_fast\_ccache\_name \sphinxhyphen{} Set location of FAST armor ccache in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache_name:krb5-get-init-creds-opt-set-fast-ccache-name-set-location-of-fast-armor-ccache-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache_name::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_fast\_ccache\_name (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_fast\_ccache\_name}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_fast_ccache_name:c.krb5_get_init_creds_opt_set_fast_ccache_name}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_fast\_ccache\_name}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{fast\_ccache\_name}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{fast\_ccache\_name} \sphinxhyphen{} Credential cache name + +\end{description}\end{quote} + +\sphinxAtStartPar +Sets the location of a credential cache containing an armor ticket to protect an initial credential exchange using the FAST protocol extension. + +\sphinxAtStartPar +In version 1.7, setting an armor ccache requires that FAST be used for the exchange. In version 1.8 or later, setting the armor ccache causes FAST to be used if the KDC supports it; krb5\_get\_init\_creds\_opt\_set\_fast\_flags() must be used to require that FAST be used. + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_fast\_flags \sphinxhyphen{} Set FAST flags in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_fast_flags:krb5-get-init-creds-opt-set-fast-flags-set-fast-flags-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_fast_flags::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_fast\_flags (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_fast\_flags}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_fast_flags:c.krb5_get_init_creds_opt_set_fast_flags}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_fast\_flags}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{flags}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{flags} \sphinxhyphen{} FAST flags + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 \sphinxhyphen{} Success; Kerberos errors otherwise. + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +The following flag values are valid: +\begin{itemize} +\item {} +\sphinxAtStartPar +\#KRB5\_FAST\_REQUIRED \sphinxhyphen{} Require FAST to be used + +\end{itemize} + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_forwardable \sphinxhyphen{} Set or unset the forwardable flag in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_forwardable:krb5-get-init-creds-opt-set-forwardable-set-or-unset-the-forwardable-flag-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_forwardable::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_forwardable (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_forwardable}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_forwardable:c.krb5_get_init_creds_opt_set_forwardable}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_forwardable}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{forwardable}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{forwardable} \sphinxhyphen{} Whether credentials should be forwardable + +\end{description}\end{quote} + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_in\_ccache \sphinxhyphen{} Set an input credential cache in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_in_ccache:krb5-get-init-creds-opt-set-in-ccache-set-an-input-credential-cache-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_in_ccache::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_in\_ccache (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_in\_ccache}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_in_ccache:c.krb5_get_init_creds_opt_set_in_ccache}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_in\_ccache}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ccache} \sphinxhyphen{} Credential cache handle + +\end{description}\end{quote} + +\sphinxAtStartPar +If an input credential cache is set, then the krb5\_get\_init\_creds family of APIs will read settings from it. Setting an input ccache is desirable when the application wishes to perform authentication in the same way (using the same preauthentication mechanisms, and making the same non\sphinxhyphen{}security\sphinxhyphen{} sensitive choices) as the previous authentication attempt, which stored information in the passed\sphinxhyphen{}in ccache. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.11 +\end{sphinxadmonition} + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_out\_ccache \sphinxhyphen{} Set an output credential cache in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_out_ccache:krb5-get-init-creds-opt-set-out-ccache-set-an-output-credential-cache-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_out_ccache::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_out\_ccache (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_out\_ccache}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_out_ccache:c.krb5_get_init_creds_opt_set_out_ccache}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_out\_ccache}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ccache} \sphinxhyphen{} Credential cache handle + +\end{description}\end{quote} + +\sphinxAtStartPar +If an output credential cache is set, then the krb5\_get\_init\_creds family of APIs will write credentials to it. Setting an output ccache is desirable both because it simplifies calling code and because it permits the krb5\_get\_init\_creds APIs to write out configuration information about the realm to the ccache. + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_pa \sphinxhyphen{} Supply options for preauthentication in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_pa:krb5-get-init-creds-opt-set-pa-supply-options-for-preauthentication-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_pa::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_pa (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_pa}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_pa:c.krb5_get_init_creds_opt_set_pa}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_pa}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{attr}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{value}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{attr} \sphinxhyphen{} Preauthentication option name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{value} \sphinxhyphen{} Preauthentication option value + +\end{description}\end{quote} + +\sphinxAtStartPar +This function allows the caller to supply options for preauthentication. The values of \sphinxstyleemphasis{attr} and \sphinxstyleemphasis{value} are supplied to each preauthentication module available within \sphinxstyleemphasis{context} . + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_pac\_request \sphinxhyphen{} Ask the KDC to include or not include a PAC in the ticket.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_pac_request:krb5-get-init-creds-opt-set-pac-request-ask-the-kdc-to-include-or-not-include-a-pac-in-the-ticket}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_pac_request::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_pac\_request (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_pac\_request}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_pac_request:c.krb5_get_init_creds_opt_set_pac_request}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_pac\_request}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\DUrole{n}{req\_pac}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{req\_pac} \sphinxhyphen{} Whether to request a PAC or not + +\end{description}\end{quote} + +\sphinxAtStartPar +If this option is set, the AS request will include a PAC\sphinxhyphen{}REQUEST pa\sphinxhyphen{}data item explicitly asking the KDC to either include or not include a privilege attribute certificate in the ticket authorization data. By default, no request is made; typically the KDC will default to including a PAC if it supports them. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.15 +\end{sphinxadmonition} + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_preauth\_list \sphinxhyphen{} Set preauthentication types in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_preauth_list:krb5-get-init-creds-opt-set-preauth-list-set-preauthentication-types-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_preauth_list::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_preauth\_list (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_preauth\_list}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_preauth_list:c.krb5_get_init_creds_opt_set_preauth_list}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_preauth\_list}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_preauthtype:c.krb5_preauthtype}]{\sphinxcrossref{\DUrole{n}{krb5\_preauthtype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{preauth\_list}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{preauth\_list\_length}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{preauth\_list} \sphinxhyphen{} Array of preauthentication types + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{preauth\_list\_length} \sphinxhyphen{} Length of \sphinxstyleemphasis{preauth\_list} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function can be used to perform optimistic preauthentication when getting initial credentials, in combination with krb5\_get\_init\_creds\_opt\_set\_salt() and krb5\_get\_init\_creds\_opt\_set\_pa(). + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_proxiable \sphinxhyphen{} Set or unset the proxiable flag in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_proxiable:krb5-get-init-creds-opt-set-proxiable-set-or-unset-the-proxiable-flag-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_proxiable::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_proxiable (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_proxiable}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_proxiable:c.krb5_get_init_creds_opt_set_proxiable}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_proxiable}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{proxiable}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{proxiable} \sphinxhyphen{} Whether credentials should be proxiable + +\end{description}\end{quote} + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_renew\_life \sphinxhyphen{} Set the ticket renewal lifetime in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_renew_life:krb5-get-init-creds-opt-set-renew-life-set-the-ticket-renewal-lifetime-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_renew_life::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_renew\_life (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_renew\_life}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_renew_life:c.krb5_get_init_creds_opt_set_renew_life}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_renew\_life}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_deltat:c.krb5_deltat}]{\sphinxcrossref{\DUrole{n}{krb5\_deltat}}}}\DUrole{w}{ }\DUrole{n}{renew\_life}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Pointer to \sphinxstyleemphasis{options} field + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{renew\_life} \sphinxhyphen{} Ticket renewal lifetime + +\end{description}\end{quote} + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_responder \sphinxhyphen{} Set the responder function in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_responder:krb5-get-init-creds-opt-set-responder-set-the-responder-function-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_responder::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_responder (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_responder}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_responder:c.krb5_get_init_creds_opt_set_responder}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_responder}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_fn:c.krb5_responder_fn}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_fn}}}}\DUrole{w}{ }\DUrole{n}{responder}, \DUrole{kt}{void}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{responder} \sphinxhyphen{} Responder function + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} Responder data argument + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.11 +\end{sphinxadmonition} + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_salt \sphinxhyphen{} Set salt for optimistic preauthentication in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_salt:krb5-get-init-creds-opt-set-salt-set-salt-for-optimistic-preauthentication-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_salt::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_salt (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_salt}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_salt:c.krb5_get_init_creds_opt_set_salt}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_salt}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{salt}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{salt} \sphinxhyphen{} Salt data + +\end{description}\end{quote} + +\sphinxAtStartPar +When getting initial credentials with a password, a salt string it used to convert the password to a key. Normally this salt is obtained from the first KDC reply, but when performing optimistic preauthentication, the client may need to supply the salt string with this function. + + +\subsubsection{krb5\_get\_init\_creds\_opt\_set\_tkt\_life \sphinxhyphen{} Set the ticket lifetime in initial credential options.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_tkt_life:krb5-get-init-creds-opt-set-tkt-life-set-the-ticket-lifetime-in-initial-credential-options}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_tkt_life::doc}}\index{krb5\_get\_init\_creds\_opt\_set\_tkt\_life (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_set\_tkt\_life}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_set_tkt_life:c.krb5_get_init_creds_opt_set_tkt_life}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_set\_tkt\_life}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_deltat:c.krb5_deltat}]{\sphinxcrossref{\DUrole{n}{krb5\_deltat}}}}\DUrole{w}{ }\DUrole{n}{tkt\_life}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{tkt\_life} \sphinxhyphen{} Ticket lifetime + +\end{description}\end{quote} + + +\subsubsection{krb5\_get\_init\_creds\_password \sphinxhyphen{} Get initial credentials using a password.} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_password:krb5-get-init-creds-password-get-initial-credentials-using-a-password}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_password::doc}}\index{krb5\_get\_init\_creds\_password (C function)@\spxentry{krb5\_get\_init\_creds\_password}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_password:c.krb5_get_init_creds_password}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_password}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{client}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{password}, {\hyperref[\detokenize{appdev/refs/types/krb5_prompter_fct:c.krb5_prompter_fct}]{\sphinxcrossref{\DUrole{n}{krb5\_prompter\_fct}}}}\DUrole{w}{ }\DUrole{n}{prompter}, \DUrole{kt}{void}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, {\hyperref[\detokenize{appdev/refs/types/krb5_deltat:c.krb5_deltat}]{\sphinxcrossref{\DUrole{n}{krb5\_deltat}}}}\DUrole{w}{ }\DUrole{n}{start\_time}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_tkt\_service}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{k5\_gic\_options}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{creds} \sphinxhyphen{} New credentials + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{client} \sphinxhyphen{} Client principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{password} \sphinxhyphen{} Password (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{prompter} \sphinxhyphen{} Prompter function + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} Prompter callback data + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{start\_time} \sphinxhyphen{} Time when ticket becomes valid (0 for now) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in\_tkt\_service} \sphinxhyphen{} Service name of initial credentials (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{k5\_gic\_options} \sphinxhyphen{} Initial credential options + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +EINVAL Invalid argument + +\item {} +\sphinxAtStartPar +KRB5\_KDC\_UNREACH Cannot contact any KDC for requested realm + +\item {} +\sphinxAtStartPar +KRB5\_PREAUTH\_FAILED Generic Pre\sphinxhyphen{}athentication failure + +\item {} +\sphinxAtStartPar +KRB5\_LIBOS\_PWDINTR Password read interrupted + +\item {} +\sphinxAtStartPar +KRB5\_REALM\_CANT\_RESOLVE Cannot resolve network address for KDC in requested realm + +\item {} +\sphinxAtStartPar +KRB5KDC\_ERR\_KEY\_EXP Password has expired + +\item {} +\sphinxAtStartPar +KRB5\_LIBOS\_BADPWDMATCH Password mismatch + +\item {} +\sphinxAtStartPar +KRB5\_CHPW\_PWDNULL New password cannot be zero length + +\item {} +\sphinxAtStartPar +KRB5\_CHPW\_FAIL Password change failed + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function requests KDC for an initial credentials for \sphinxstyleemphasis{client} using \sphinxstyleemphasis{password} . If \sphinxstyleemphasis{password} is NULL, a password will be prompted for using \sphinxstyleemphasis{prompter} if necessary. If \sphinxstyleemphasis{in\_tkt\_service} is specified, it is parsed as a principal name (with the realm ignored) and used as the service principal for the request; otherwise the ticket\sphinxhyphen{}granting service is used. + + +\subsubsection{krb5\_get\_profile \sphinxhyphen{} Retrieve configuration profile from the context.} +\label{\detokenize{appdev/refs/api/krb5_get_profile:krb5-get-profile-retrieve-configuration-profile-from-the-context}}\label{\detokenize{appdev/refs/api/krb5_get_profile::doc}}\index{krb5\_get\_profile (C function)@\spxentry{krb5\_get\_profile}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_profile:c.krb5_get_profile}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_profile}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{struct}\DUrole{w}{ }\DUrole{n}{\_profile\_t}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{profile}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{profile} \sphinxhyphen{} Pointer to data read from a configuration file + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a new \sphinxstyleemphasis{profile} object that reflects profile in the supplied \sphinxstyleemphasis{context} . + +\sphinxAtStartPar +The \sphinxstyleemphasis{profile} object may be freed with profile\_release() function. See profile.h and profile API for more details. + + +\subsubsection{krb5\_get\_prompt\_types \sphinxhyphen{} Get prompt types array from a context.} +\label{\detokenize{appdev/refs/api/krb5_get_prompt_types:krb5-get-prompt-types-get-prompt-types-array-from-a-context}}\label{\detokenize{appdev/refs/api/krb5_get_prompt_types::doc}}\index{krb5\_get\_prompt\_types (C function)@\spxentry{krb5\_get\_prompt\_types}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_prompt_types:c.krb5_get_prompt_types}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_prompt_type:c.krb5_prompt_type}]{\sphinxcrossref{\DUrole{n}{krb5\_prompt\_type}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_prompt\_types}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Pointer to an array of prompt types corresponding to the prompter’s prompts arguments. Each type has one of the following values: \#KRB5\_PROMPT\_TYPE\_PASSWORD \#KRB5\_PROMPT\_TYPE\_NEW\_PASSWORD \#KRB5\_PROMPT\_TYPE\_NEW\_PASSWORD\_AGAIN \#KRB5\_PROMPT\_TYPE\_PREAUTH + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_get\_renewed\_creds \sphinxhyphen{} Get renewed credential from KDC using an existing credential.} +\label{\detokenize{appdev/refs/api/krb5_get_renewed_creds:krb5-get-renewed-creds-get-renewed-credential-from-kdc-using-an-existing-credential}}\label{\detokenize{appdev/refs/api/krb5_get_renewed_creds::doc}}\index{krb5\_get\_renewed\_creds (C function)@\spxentry{krb5\_get\_renewed\_creds}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_renewed_creds:c.krb5_get_renewed_creds}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_renewed\_creds}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{client}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_tkt\_service}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Renewed credentials + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{client} \sphinxhyphen{} Client principal name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ccache} \sphinxhyphen{} Credential cache + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in\_tkt\_service} \sphinxhyphen{} Server principal string (or NULL) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function gets a renewed credential using an existing one from \sphinxstyleemphasis{ccache} . If \sphinxstyleemphasis{in\_tkt\_service} is specified, it is parsed (with the realm part ignored) and used as the server principal of the credential; otherwise, the ticket\sphinxhyphen{}granting service is used. + +\sphinxAtStartPar +If successful, the renewed credential is placed in \sphinxstyleemphasis{creds} . + + +\subsubsection{krb5\_get\_validated\_creds \sphinxhyphen{} Get validated credentials from the KDC.} +\label{\detokenize{appdev/refs/api/krb5_get_validated_creds:krb5-get-validated-creds-get-validated-credentials-from-the-kdc}}\label{\detokenize{appdev/refs/api/krb5_get_validated_creds::doc}}\index{krb5\_get\_validated\_creds (C function)@\spxentry{krb5\_get\_validated\_creds}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_validated_creds:c.krb5_get_validated_creds}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_validated\_creds}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{client}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_tkt\_service}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Validated credentials + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{client} \sphinxhyphen{} Client principal name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ccache} \sphinxhyphen{} Credential cache + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in\_tkt\_service} \sphinxhyphen{} Server principal string (or NULL) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +KRB5\_NO\_2ND\_TKT Request missing second ticket + +\item {} +\sphinxAtStartPar +KRB5\_NO\_TKT\_SUPPLIED Request did not supply a ticket + +\item {} +\sphinxAtStartPar +KRB5\_PRINC\_NOMATCH Requested principal and ticket do not match + +\item {} +\sphinxAtStartPar +KRB5\_KDCREP\_MODIFIED KDC reply did not match expectations + +\item {} +\sphinxAtStartPar +KRB5\_KDCREP\_SKEW Clock skew too great in KDC reply + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function gets a validated credential using a postdated credential from \sphinxstyleemphasis{ccache} . If \sphinxstyleemphasis{in\_tkt\_service} is specified, it is parsed (with the realm part ignored) and used as the server principal of the credential; otherwise, the ticket\sphinxhyphen{}granting service is used. + +\sphinxAtStartPar +If successful, the validated credential is placed in \sphinxstyleemphasis{creds} . + + +\subsubsection{krb5\_init\_context \sphinxhyphen{} Create a krb5 library context.} +\label{\detokenize{appdev/refs/api/krb5_init_context:krb5-init-context-create-a-krb5-library-context}}\label{\detokenize{appdev/refs/api/krb5_init_context::doc}}\index{krb5\_init\_context (C function)@\spxentry{krb5\_init\_context}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_context:c.krb5_init_context}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_context}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{context}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +The \sphinxstyleemphasis{context} must be released by calling krb5\_free\_context() when it is no longer needed. + +\begin{sphinxadmonition}{warning}{Warning:} +\sphinxAtStartPar +Any program or module that needs the Kerberos code to not trust the environment must use krb5\_init\_secure\_context(), or clean out the environment. +\end{sphinxadmonition} + + +\subsubsection{krb5\_init\_secure\_context \sphinxhyphen{} Create a krb5 library context using only configuration files.} +\label{\detokenize{appdev/refs/api/krb5_init_secure_context:krb5-init-secure-context-create-a-krb5-library-context-using-only-configuration-files}}\label{\detokenize{appdev/refs/api/krb5_init_secure_context::doc}}\index{krb5\_init\_secure\_context (C function)@\spxentry{krb5\_init\_secure\_context}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_secure_context:c.krb5_init_secure_context}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_secure\_context}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{context}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Create a context structure, using only system configuration files. All information passed through the environment variables is ignored. + +\sphinxAtStartPar +The \sphinxstyleemphasis{context} must be released by calling krb5\_free\_context() when it is no longer needed. + + +\subsubsection{krb5\_is\_config\_principal \sphinxhyphen{} Test whether a principal is a configuration principal.} +\label{\detokenize{appdev/refs/api/krb5_is_config_principal:krb5-is-config-principal-test-whether-a-principal-is-a-configuration-principal}}\label{\detokenize{appdev/refs/api/krb5_is_config_principal::doc}}\index{krb5\_is\_config\_principal (C function)@\spxentry{krb5\_is\_config\_principal}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_is_config_principal:c.krb5_is_config_principal}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_is\_config\_principal}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Principal to check + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if the principal is a configuration principal (generated part of krb5\_cc\_set\_config()); FALSE otherwise. + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_is\_thread\_safe \sphinxhyphen{} Test whether the Kerberos library was built with multithread support.} +\label{\detokenize{appdev/refs/api/krb5_is_thread_safe:krb5-is-thread-safe-test-whether-the-kerberos-library-was-built-with-multithread-support}}\label{\detokenize{appdev/refs/api/krb5_is_thread_safe::doc}}\index{krb5\_is\_thread\_safe (C function)@\spxentry{krb5\_is\_thread\_safe}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_is_thread_safe:c.krb5_is_thread_safe}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_is\_thread\_safe}}}}{\DUrole{kt}{void}\DUrole{w}{ }\DUrole{n}{None}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{None} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if the library is threadsafe; FALSE otherwise + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_kt\_close \sphinxhyphen{} Close a key table handle.} +\label{\detokenize{appdev/refs/api/krb5_kt_close:krb5-kt-close-close-a-key-table-handle}}\label{\detokenize{appdev/refs/api/krb5_kt_close::doc}}\index{krb5\_kt\_close (C function)@\spxentry{krb5\_kt\_close}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_close:c.krb5_kt_close}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_close}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{keytab}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keytab} \sphinxhyphen{} Key table handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 None + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_kt\_client\_default \sphinxhyphen{} Resolve the default client key table.} +\label{\detokenize{appdev/refs/api/krb5_kt_client_default:krb5-kt-client-default-resolve-the-default-client-key-table}}\label{\detokenize{appdev/refs/api/krb5_kt_client_default::doc}}\index{krb5\_kt\_client\_default (C function)@\spxentry{krb5\_kt\_client\_default}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_client_default:c.krb5_kt_client_default}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_client\_default}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{keytab\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{keytab\_out} \sphinxhyphen{} Key table handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Fill \sphinxstyleemphasis{keytab\_out} with a handle to the default client key table. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.11 +\end{sphinxadmonition} + + +\subsubsection{krb5\_kt\_default \sphinxhyphen{} Resolve the default key table.} +\label{\detokenize{appdev/refs/api/krb5_kt_default:krb5-kt-default-resolve-the-default-key-table}}\label{\detokenize{appdev/refs/api/krb5_kt_default::doc}}\index{krb5\_kt\_default (C function)@\spxentry{krb5\_kt\_default}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_default:c.krb5_kt_default}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_default}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{id}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{id} \sphinxhyphen{} Key table handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Set \sphinxstyleemphasis{id} to a handle to the default key table. The key table is not opened. + + +\subsubsection{krb5\_kt\_default\_name \sphinxhyphen{} Get the default key table name.} +\label{\detokenize{appdev/refs/api/krb5_kt_default_name:krb5-kt-default-name-get-the-default-key-table-name}}\label{\detokenize{appdev/refs/api/krb5_kt_default_name::doc}}\index{krb5\_kt\_default\_name (C function)@\spxentry{krb5\_kt\_default\_name}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_default_name:c.krb5_kt_default_name}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_default\_name}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{name}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{name\_size}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{name} \sphinxhyphen{} Default key table name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{name\_size} \sphinxhyphen{} Space available in \sphinxstyleemphasis{name} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +KRB5\_CONFIG\_NOTENUFSPACE Buffer is too short + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Fill \sphinxstyleemphasis{name} with the name of the default key table for \sphinxstyleemphasis{context} . + + +\subsubsection{krb5\_kt\_dup \sphinxhyphen{} Duplicate keytab handle.} +\label{\detokenize{appdev/refs/api/krb5_kt_dup:krb5-kt-dup-duplicate-keytab-handle}}\label{\detokenize{appdev/refs/api/krb5_kt_dup::doc}}\index{krb5\_kt\_dup (C function)@\spxentry{krb5\_kt\_dup}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_dup:c.krb5_kt_dup}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_dup}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{in}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in} \sphinxhyphen{} Key table handle to be duplicated + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{out} \sphinxhyphen{} Key table handle + +\end{description}\end{quote} + +\sphinxAtStartPar +Create a new handle referring to the same key table as \sphinxstyleemphasis{in} . The new handle and \sphinxstyleemphasis{in} can be closed independently. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.12 +\end{sphinxadmonition} + + +\subsubsection{krb5\_kt\_get\_name \sphinxhyphen{} Get a key table name.} +\label{\detokenize{appdev/refs/api/krb5_kt_get_name:krb5-kt-get-name-get-a-key-table-name}}\label{\detokenize{appdev/refs/api/krb5_kt_get_name::doc}}\index{krb5\_kt\_get\_name (C function)@\spxentry{krb5\_kt\_get\_name}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_get_name:c.krb5_kt_get_name}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_get\_name}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{keytab}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{name}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{namelen}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keytab} \sphinxhyphen{} Key table handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{name} \sphinxhyphen{} Key table name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{namelen} \sphinxhyphen{} Maximum length to fill in name + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +KRB5\_KT\_NAME\_TOOLONG Key table name does not fit in namelen bytes + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Fill \sphinxstyleemphasis{name} with the name of \sphinxstyleemphasis{keytab} including the type and delimiter. + + +\subsubsection{krb5\_kt\_get\_type \sphinxhyphen{} Return the type of a key table.} +\label{\detokenize{appdev/refs/api/krb5_kt_get_type:krb5-kt-get-type-return-the-type-of-a-key-table}}\label{\detokenize{appdev/refs/api/krb5_kt_get_type::doc}}\index{krb5\_kt\_get\_type (C function)@\spxentry{krb5\_kt\_get\_type}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_get_type:c.krb5_kt_get_type}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_get\_type}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{keytab}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keytab} \sphinxhyphen{} Key table handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +The type of a key table as an alias that must not be modified or freed by the caller. + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_kt\_resolve \sphinxhyphen{} Get a handle for a key table.} +\label{\detokenize{appdev/refs/api/krb5_kt_resolve:krb5-kt-resolve-get-a-handle-for-a-key-table}}\label{\detokenize{appdev/refs/api/krb5_kt_resolve::doc}}\index{krb5\_kt\_resolve (C function)@\spxentry{krb5\_kt\_resolve}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_resolve:c.krb5_kt_resolve}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_resolve}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{name}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ktid}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{name} \sphinxhyphen{} Name of the key table + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ktid} \sphinxhyphen{} Key table handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Resolve the key table name \sphinxstyleemphasis{name} and set \sphinxstyleemphasis{ktid} to a handle identifying the key table. Use krb5\_kt\_close() to free \sphinxstyleemphasis{ktid} when it is no longer needed. +\begin{quote} + +\sphinxAtStartPar +\sphinxstyleemphasis{name} must be of the form \sphinxstylestrong{type:residual} , where \sphinxstyleemphasis{type} must be a type known to the library and \sphinxstyleemphasis{residual} portion should be specific to the particular keytab type. If no \sphinxstyleemphasis{type} is given, the default is \sphinxstylestrong{FILE} . +\end{quote} + +\sphinxAtStartPar +If \sphinxstyleemphasis{name} is of type \sphinxstylestrong{FILE} , the keytab file is not opened by this call. + + +\subsubsection{krb5\_kuserok \sphinxhyphen{} Determine if a principal is authorized to log in as a local user.} +\label{\detokenize{appdev/refs/api/krb5_kuserok:krb5-kuserok-determine-if-a-principal-is-authorized-to-log-in-as-a-local-user}}\label{\detokenize{appdev/refs/api/krb5_kuserok::doc}}\index{krb5\_kuserok (C function)@\spxentry{krb5\_kuserok}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kuserok:c.krb5_kuserok}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kuserok}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{luser}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Principal name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{luser} \sphinxhyphen{} Local username + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE Principal is authorized to log in as user; FALSE otherwise. + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Determine whether \sphinxstyleemphasis{principal} is authorized to log in as a local user \sphinxstyleemphasis{luser} . + + +\subsubsection{krb5\_parse\_name \sphinxhyphen{} Convert a string principal name to a krb5\_principal structure.} +\label{\detokenize{appdev/refs/api/krb5_parse_name:krb5-parse-name-convert-a-string-principal-name-to-a-krb5-principal-structure}}\label{\detokenize{appdev/refs/api/krb5_parse_name::doc}}\index{krb5\_parse\_name (C function)@\spxentry{krb5\_parse\_name}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_parse_name:c.krb5_parse_name}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_parse\_name}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{name}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{principal\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{name} \sphinxhyphen{} String representation of a principal name + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{principal\_out} \sphinxhyphen{} New principal + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Convert a string representation of a principal name to a krb5\_principal structure. + +\sphinxAtStartPar +A string representation of a Kerberos name consists of one or more principal name components, separated by slashes, optionally followed by the @ character and a realm name. If the realm name is not specified, the local realm is used. + +\sphinxAtStartPar +To use the slash and @ symbols as part of a component (quoted) instead of using them as a component separator or as a realm prefix), put a backslash () character in front of the symbol. Similarly, newline, tab, backspace, and NULL characters can be included in a component by using \sphinxstylestrong{n} , \sphinxstylestrong{t} , \sphinxstylestrong{b} or \sphinxstylestrong{0} , respectively. + +\sphinxAtStartPar +Beginning with release 1.20, the name type of the principal will be inferred as \sphinxstylestrong{KRB5\_NT\_SRV\_INST} or \sphinxstylestrong{KRB5\_NT\_WELLKNOWN} based on the principal name. The type will be \sphinxstylestrong{KRB5\_NT\_PRINCIPAL} if a type cannot be inferred. + +\sphinxAtStartPar +Use krb5\_free\_principal() to free \sphinxstyleemphasis{principal\_out} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The realm in a Kerberos \sphinxstyleemphasis{name} cannot contain slash, colon, or NULL characters. +\end{sphinxadmonition} + + +\subsubsection{krb5\_parse\_name\_flags \sphinxhyphen{} Convert a string principal name to a krb5\_principal with flags.} +\label{\detokenize{appdev/refs/api/krb5_parse_name_flags:krb5-parse-name-flags-convert-a-string-principal-name-to-a-krb5-principal-with-flags}}\label{\detokenize{appdev/refs/api/krb5_parse_name_flags::doc}}\index{krb5\_parse\_name\_flags (C function)@\spxentry{krb5\_parse\_name\_flags}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_parse_name_flags:c.krb5_parse_name_flags}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_parse\_name\_flags}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{name}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{flags}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{principal\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{name} \sphinxhyphen{} String representation of a principal name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Flag + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{principal\_out} \sphinxhyphen{} New principal + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Similar to krb5\_parse\_name(), this function converts a single\sphinxhyphen{}string representation of a principal name to a krb5\_principal structure. + +\sphinxAtStartPar +The following flags are valid: +\begin{quote} +\begin{itemize} +\item {} +\sphinxAtStartPar +\#KRB5\_PRINCIPAL\_PARSE\_NO\_REALM \sphinxhyphen{} no realm must be present in \sphinxstyleemphasis{name} + +\item {} +\sphinxAtStartPar +\#KRB5\_PRINCIPAL\_PARSE\_REQUIRE\_REALM \sphinxhyphen{} realm must be present in \sphinxstyleemphasis{name} + +\item {} +\sphinxAtStartPar +\#KRB5\_PRINCIPAL\_PARSE\_ENTERPRISE \sphinxhyphen{} create single\sphinxhyphen{}component enterprise principal + +\item {} +\sphinxAtStartPar +\#KRB5\_PRINCIPAL\_PARSE\_IGNORE\_REALM \sphinxhyphen{} ignore realm if present in \sphinxstyleemphasis{name} + +\end{itemize} + +\sphinxAtStartPar +If \sphinxstylestrong{KRB5\_PRINCIPAL\_PARSE\_NO\_REALM} or \sphinxstylestrong{KRB5\_PRINCIPAL\_PARSE\_IGNORE\_REALM} is specified in \sphinxstyleemphasis{flags} , the realm of the new principal will be empty. Otherwise, the default realm for \sphinxstyleemphasis{context} will be used if \sphinxstyleemphasis{name} does not specify a realm. +\end{quote} + +\sphinxAtStartPar +Use krb5\_free\_principal() to free \sphinxstyleemphasis{principal\_out} when it is no longer needed. + + +\subsubsection{krb5\_principal\_compare \sphinxhyphen{} Compare two principals.} +\label{\detokenize{appdev/refs/api/krb5_principal_compare:krb5-principal-compare-compare-two-principals}}\label{\detokenize{appdev/refs/api/krb5_principal_compare::doc}}\index{krb5\_principal\_compare (C function)@\spxentry{krb5\_principal\_compare}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_principal_compare:c.krb5_principal_compare}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_principal\_compare}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{princ1}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{princ2}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{princ1} \sphinxhyphen{} First principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{princ2} \sphinxhyphen{} Second principal + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if the principals are the same; FALSE otherwise + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_principal\_compare\_any\_realm \sphinxhyphen{} Compare two principals ignoring realm components.} +\label{\detokenize{appdev/refs/api/krb5_principal_compare_any_realm:krb5-principal-compare-any-realm-compare-two-principals-ignoring-realm-components}}\label{\detokenize{appdev/refs/api/krb5_principal_compare_any_realm::doc}}\index{krb5\_principal\_compare\_any\_realm (C function)@\spxentry{krb5\_principal\_compare\_any\_realm}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_principal_compare_any_realm:c.krb5_principal_compare_any_realm}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_principal\_compare\_any\_realm}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{princ1}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{princ2}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{princ1} \sphinxhyphen{} First principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{princ2} \sphinxhyphen{} Second principal + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if the principals are the same; FALSE otherwise + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Similar to krb5\_principal\_compare(), but do not compare the realm components of the principals. + + +\subsubsection{krb5\_principal\_compare\_flags \sphinxhyphen{} Compare two principals with additional flags.} +\label{\detokenize{appdev/refs/api/krb5_principal_compare_flags:krb5-principal-compare-flags-compare-two-principals-with-additional-flags}}\label{\detokenize{appdev/refs/api/krb5_principal_compare_flags::doc}}\index{krb5\_principal\_compare\_flags (C function)@\spxentry{krb5\_principal\_compare\_flags}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_principal_compare_flags:c.krb5_principal_compare_flags}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_principal\_compare\_flags}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{princ1}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{princ2}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{flags}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{princ1} \sphinxhyphen{} First principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{princ2} \sphinxhyphen{} Second principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Flags + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if the principal names are the same; FALSE otherwise + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Valid flags are: +\begin{itemize} +\item {} +\sphinxAtStartPar +\#KRB5\_PRINCIPAL\_COMPARE\_IGNORE\_REALM \sphinxhyphen{} ignore realm component + +\item {} +\sphinxAtStartPar +\#KRB5\_PRINCIPAL\_COMPARE\_ENTERPRISE \sphinxhyphen{} UPNs as real principals + +\item {} +\sphinxAtStartPar +\#KRB5\_PRINCIPAL\_COMPARE\_CASEFOLD case\sphinxhyphen{}insensitive + +\item {} +\sphinxAtStartPar +\#KRB5\_PRINCIPAL\_COMPARE\_UTF8 \sphinxhyphen{} treat principals as UTF\sphinxhyphen{}8 + +\end{itemize} + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_principal\_compare() + + + + +\subsubsection{krb5\_prompter\_posix \sphinxhyphen{} Prompt user for password.} +\label{\detokenize{appdev/refs/api/krb5_prompter_posix:krb5-prompter-posix-prompt-user-for-password}}\label{\detokenize{appdev/refs/api/krb5_prompter_posix::doc}}\index{krb5\_prompter\_posix (C function)@\spxentry{krb5\_prompter\_posix}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_prompter_posix:c.krb5_prompter_posix}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_prompter\_posix}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{kt}{void}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{name}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{banner}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{num\_prompts}, {\hyperref[\detokenize{appdev/refs/types/krb5_prompt:c.krb5_prompt}]{\sphinxcrossref{\DUrole{n}{krb5\_prompt}}}}\DUrole{w}{ }\DUrole{n}{prompts}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{data} \sphinxhyphen{} Unused (callback argument) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{name} \sphinxhyphen{} Name to output during prompt + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{banner} \sphinxhyphen{} Banner to output during prompt + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{num\_prompts} \sphinxhyphen{} Number of prompts in \sphinxstyleemphasis{prompts} + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{prompts} \sphinxhyphen{} Array of prompts and replies + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function is intended to be used as a prompter callback for krb5\_get\_init\_creds\_password() or krb5\_init\_creds\_init(). + +\sphinxAtStartPar +Writes \sphinxstyleemphasis{name} and \sphinxstyleemphasis{banner} to stdout, each followed by a newline, then writes each prompt field in the \sphinxstyleemphasis{prompts} array, followed by”:”, and sets the reply field of the entry to a line of input read from stdin. If the hidden flag is set for a prompt, then terminal echoing is turned off when input is read. + + +\subsubsection{krb5\_realm\_compare \sphinxhyphen{} Compare the realms of two principals.} +\label{\detokenize{appdev/refs/api/krb5_realm_compare:krb5-realm-compare-compare-the-realms-of-two-principals}}\label{\detokenize{appdev/refs/api/krb5_realm_compare::doc}}\index{krb5\_realm\_compare (C function)@\spxentry{krb5\_realm\_compare}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_realm_compare:c.krb5_realm_compare}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_realm\_compare}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{princ1}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{princ2}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{princ1} \sphinxhyphen{} First principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{princ2} \sphinxhyphen{} Second principal + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if the realm names are the same; FALSE otherwise + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_responder\_get\_challenge \sphinxhyphen{} Retrieve the challenge data for a given question in the responder context.} +\label{\detokenize{appdev/refs/api/krb5_responder_get_challenge:krb5-responder-get-challenge-retrieve-the-challenge-data-for-a-given-question-in-the-responder-context}}\label{\detokenize{appdev/refs/api/krb5_responder_get_challenge::doc}}\index{krb5\_responder\_get\_challenge (C function)@\spxentry{krb5\_responder\_get\_challenge}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_responder_get_challenge:c.krb5_responder_get_challenge}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_get\_challenge}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_context:c.krb5_responder_context}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_context}}}}\DUrole{w}{ }\DUrole{n}{rctx}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{question}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rctx} \sphinxhyphen{} Responder context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{question} \sphinxhyphen{} Question name + +\end{description}\end{quote} + +\sphinxAtStartPar +Return a pointer to a C string containing the challenge for \sphinxstyleemphasis{question} within \sphinxstyleemphasis{rctx} , or NULL if the question is not present in \sphinxstyleemphasis{rctx} . The structure of the question depends on the question name, but will always be printable UTF\sphinxhyphen{}8 text. The returned pointer is an alias, valid only as long as the lifetime of \sphinxstyleemphasis{rctx} , and should not be modified or freed by the caller. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.11 +\end{sphinxadmonition} + + +\subsubsection{krb5\_responder\_list\_questions \sphinxhyphen{} List the question names contained in the responder context.} +\label{\detokenize{appdev/refs/api/krb5_responder_list_questions:krb5-responder-list-questions-list-the-question-names-contained-in-the-responder-context}}\label{\detokenize{appdev/refs/api/krb5_responder_list_questions::doc}}\index{krb5\_responder\_list\_questions (C function)@\spxentry{krb5\_responder\_list\_questions}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_responder_list_questions:c.krb5_responder_list_questions}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_list\_questions}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_context:c.krb5_responder_context}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_context}}}}\DUrole{w}{ }\DUrole{n}{rctx}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rctx} \sphinxhyphen{} Responder context + +\end{description}\end{quote} + +\sphinxAtStartPar +Return a pointer to a null\sphinxhyphen{}terminated list of question names which are present in \sphinxstyleemphasis{rctx} . The pointer is an alias, valid only as long as the lifetime of \sphinxstyleemphasis{rctx} , and should not be modified or freed by the caller. A question’s challenge can be retrieved using krb5\_responder\_get\_challenge() and answered using krb5\_responder\_set\_answer(). + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.11 +\end{sphinxadmonition} + + +\subsubsection{krb5\_responder\_set\_answer \sphinxhyphen{} Answer a named question in the responder context.} +\label{\detokenize{appdev/refs/api/krb5_responder_set_answer:krb5-responder-set-answer-answer-a-named-question-in-the-responder-context}}\label{\detokenize{appdev/refs/api/krb5_responder_set_answer::doc}}\index{krb5\_responder\_set\_answer (C function)@\spxentry{krb5\_responder\_set\_answer}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_responder_set_answer:c.krb5_responder_set_answer}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_set\_answer}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_context:c.krb5_responder_context}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_context}}}}\DUrole{w}{ }\DUrole{n}{rctx}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{question}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{answer}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rctx} \sphinxhyphen{} Responder context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{question} \sphinxhyphen{} Question name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{answer} \sphinxhyphen{} The string to set (MUST be printable UTF\sphinxhyphen{}8) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +EINVAL question is not present within rctx + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function supplies an answer to \sphinxstyleemphasis{question} within \sphinxstyleemphasis{rctx} . The appropriate form of the answer depends on the question name. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.11 +\end{sphinxadmonition} + + +\subsubsection{krb5\_responder\_otp\_get\_challenge \sphinxhyphen{} Decode the KRB5\_RESPONDER\_QUESTION\_OTP to a C struct.} +\label{\detokenize{appdev/refs/api/krb5_responder_otp_get_challenge:krb5-responder-otp-get-challenge-decode-the-krb5-responder-question-otp-to-a-c-struct}}\label{\detokenize{appdev/refs/api/krb5_responder_otp_get_challenge::doc}}\index{krb5\_responder\_otp\_get\_challenge (C function)@\spxentry{krb5\_responder\_otp\_get\_challenge}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_responder_otp_get_challenge:c.krb5_responder_otp_get_challenge}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_otp\_get\_challenge}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_context:c.krb5_responder_context}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_context}}}}\DUrole{w}{ }\DUrole{n}{rctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_otp_challenge:c.krb5_responder_otp_challenge}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_otp\_challenge}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{chl}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rctx} \sphinxhyphen{} Responder context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{chl} \sphinxhyphen{} Challenge structure + +\end{description}\end{quote} + +\sphinxAtStartPar +A convenience function which parses the KRB5\_RESPONDER\_QUESTION\_OTP question challenge data, making it available in native C. The main feature of this function is the ability to interact with OTP tokens without parsing the JSON. + +\sphinxAtStartPar +The returned value must be passed to krb5\_responder\_otp\_challenge\_free() to be freed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.11 +\end{sphinxadmonition} + + +\subsubsection{krb5\_responder\_otp\_set\_answer \sphinxhyphen{} Answer the KRB5\_RESPONDER\_QUESTION\_OTP question.} +\label{\detokenize{appdev/refs/api/krb5_responder_otp_set_answer:krb5-responder-otp-set-answer-answer-the-krb5-responder-question-otp-question}}\label{\detokenize{appdev/refs/api/krb5_responder_otp_set_answer::doc}}\index{krb5\_responder\_otp\_set\_answer (C function)@\spxentry{krb5\_responder\_otp\_set\_answer}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_responder_otp_set_answer:c.krb5_responder_otp_set_answer}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_otp\_set\_answer}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_context:c.krb5_responder_context}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_context}}}}\DUrole{w}{ }\DUrole{n}{rctx}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{ti}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{value}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{pin}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rctx} \sphinxhyphen{} Responder context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ti} \sphinxhyphen{} The index of the tokeninfo selected + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{value} \sphinxhyphen{} The value to set, or NULL for none + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pin} \sphinxhyphen{} The pin to set, or NULL for none + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.11 +\end{sphinxadmonition} + + +\subsubsection{krb5\_responder\_otp\_challenge\_free \sphinxhyphen{} Free the value returned by krb5\_responder\_otp\_get\_challenge().} +\label{\detokenize{appdev/refs/api/krb5_responder_otp_challenge_free:krb5-responder-otp-challenge-free-free-the-value-returned-by-krb5-responder-otp-get-challenge}}\label{\detokenize{appdev/refs/api/krb5_responder_otp_challenge_free::doc}}\index{krb5\_responder\_otp\_challenge\_free (C function)@\spxentry{krb5\_responder\_otp\_challenge\_free}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_responder_otp_challenge_free:c.krb5_responder_otp_challenge_free}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_otp\_challenge\_free}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_context:c.krb5_responder_context}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_context}}}}\DUrole{w}{ }\DUrole{n}{rctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_otp_challenge:c.krb5_responder_otp_challenge}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_otp\_challenge}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{chl}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rctx} \sphinxhyphen{} Responder context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{chl} \sphinxhyphen{} The challenge to free + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.11 +\end{sphinxadmonition} + + +\subsubsection{krb5\_responder\_pkinit\_get\_challenge \sphinxhyphen{} Decode the KRB5\_RESPONDER\_QUESTION\_PKINIT to a C struct.} +\label{\detokenize{appdev/refs/api/krb5_responder_pkinit_get_challenge:krb5-responder-pkinit-get-challenge-decode-the-krb5-responder-question-pkinit-to-a-c-struct}}\label{\detokenize{appdev/refs/api/krb5_responder_pkinit_get_challenge::doc}}\index{krb5\_responder\_pkinit\_get\_challenge (C function)@\spxentry{krb5\_responder\_pkinit\_get\_challenge}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_responder_pkinit_get_challenge:c.krb5_responder_pkinit_get_challenge}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_pkinit\_get\_challenge}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_context:c.krb5_responder_context}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_context}}}}\DUrole{w}{ }\DUrole{n}{rctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_pkinit_challenge:c.krb5_responder_pkinit_challenge}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_pkinit\_challenge}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{chl\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rctx} \sphinxhyphen{} Responder context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{chl\_out} \sphinxhyphen{} Challenge structure + +\end{description}\end{quote} + +\sphinxAtStartPar +A convenience function which parses the KRB5\_RESPONDER\_QUESTION\_PKINIT question challenge data, making it available in native C. The main feature of this function is the ability to read the challenge without parsing the JSON. + +\sphinxAtStartPar +The returned value must be passed to krb5\_responder\_pkinit\_challenge\_free() to be freed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.12 +\end{sphinxadmonition} + + +\subsubsection{krb5\_responder\_pkinit\_set\_answer \sphinxhyphen{} Answer the KRB5\_RESPONDER\_QUESTION\_PKINIT question for one identity.} +\label{\detokenize{appdev/refs/api/krb5_responder_pkinit_set_answer:krb5-responder-pkinit-set-answer-answer-the-krb5-responder-question-pkinit-question-for-one-identity}}\label{\detokenize{appdev/refs/api/krb5_responder_pkinit_set_answer::doc}}\index{krb5\_responder\_pkinit\_set\_answer (C function)@\spxentry{krb5\_responder\_pkinit\_set\_answer}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_responder_pkinit_set_answer:c.krb5_responder_pkinit_set_answer}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_pkinit\_set\_answer}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_context:c.krb5_responder_context}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_context}}}}\DUrole{w}{ }\DUrole{n}{rctx}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{identity}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{pin}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rctx} \sphinxhyphen{} Responder context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{identity} \sphinxhyphen{} The identity for which a PIN is being supplied + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pin} \sphinxhyphen{} The provided PIN, or NULL for none + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.12 +\end{sphinxadmonition} + + +\subsubsection{krb5\_responder\_pkinit\_challenge\_free \sphinxhyphen{} Free the value returned by krb5\_responder\_pkinit\_get\_challenge().} +\label{\detokenize{appdev/refs/api/krb5_responder_pkinit_challenge_free:krb5-responder-pkinit-challenge-free-free-the-value-returned-by-krb5-responder-pkinit-get-challenge}}\label{\detokenize{appdev/refs/api/krb5_responder_pkinit_challenge_free::doc}}\index{krb5\_responder\_pkinit\_challenge\_free (C function)@\spxentry{krb5\_responder\_pkinit\_challenge\_free}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_responder_pkinit_challenge_free:c.krb5_responder_pkinit_challenge_free}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_pkinit\_challenge\_free}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_context:c.krb5_responder_context}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_context}}}}\DUrole{w}{ }\DUrole{n}{rctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_responder_pkinit_challenge:c.krb5_responder_pkinit_challenge}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_pkinit\_challenge}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{chl}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rctx} \sphinxhyphen{} Responder context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{chl} \sphinxhyphen{} The challenge to free + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.12 +\end{sphinxadmonition} + + +\subsubsection{krb5\_set\_default\_realm \sphinxhyphen{} Override the default realm for the specified context.} +\label{\detokenize{appdev/refs/api/krb5_set_default_realm:krb5-set-default-realm-override-the-default-realm-for-the-specified-context}}\label{\detokenize{appdev/refs/api/krb5_set_default_realm::doc}}\index{krb5\_set\_default\_realm (C function)@\spxentry{krb5\_set\_default\_realm}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_set_default_realm:c.krb5_set_default_realm}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_set\_default\_realm}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{lrealm}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{lrealm} \sphinxhyphen{} Realm name for the default realm + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +If \sphinxstyleemphasis{lrealm} is NULL, clear the default realm setting. + + +\subsubsection{krb5\_set\_password \sphinxhyphen{} Set a password for a principal using specified credentials.} +\label{\detokenize{appdev/refs/api/krb5_set_password:krb5-set-password-set-a-password-for-a-principal-using-specified-credentials}}\label{\detokenize{appdev/refs/api/krb5_set_password::doc}}\index{krb5\_set\_password (C function)@\spxentry{krb5\_set\_password}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_set_password:c.krb5_set_password}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_set\_password}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{newpw}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{change\_password\_for}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{result\_code}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{result\_code\_string}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{result\_string}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Credentials for kadmin/changepw service + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{newpw} \sphinxhyphen{} New password + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{change\_password\_for} \sphinxhyphen{} Change the password for this principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{result\_code} \sphinxhyphen{} Numeric error code from server + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{result\_code\_string} \sphinxhyphen{} String equivalent to \sphinxstyleemphasis{result\_code} + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{result\_string} \sphinxhyphen{} Data returned from the remote system + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success and result\_code is set to \#KRB5\_KPASSWD\_SUCCESS. + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes. + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function uses the credentials \sphinxstyleemphasis{creds} to set the password \sphinxstyleemphasis{newpw} for the principal \sphinxstyleemphasis{change\_password\_for} . It implements the set password operation of RFC 3244, for interoperability with Microsoft Windows implementations. + +\sphinxAtStartPar +The error code and strings are returned in \sphinxstyleemphasis{result\_code} , \sphinxstyleemphasis{result\_code\_string} and \sphinxstyleemphasis{result\_string} . + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +If \sphinxstyleemphasis{change\_password\_for} is NULL, the change is performed on the current principal. If \sphinxstyleemphasis{change\_password\_for} is non\sphinxhyphen{}null, the change is performed on the principal name passed in \sphinxstyleemphasis{change\_password\_for} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_set\_password\_using\_ccache \sphinxhyphen{} Set a password for a principal using cached credentials.} +\label{\detokenize{appdev/refs/api/krb5_set_password_using_ccache:krb5-set-password-using-ccache-set-a-password-for-a-principal-using-cached-credentials}}\label{\detokenize{appdev/refs/api/krb5_set_password_using_ccache::doc}}\index{krb5\_set\_password\_using\_ccache (C function)@\spxentry{krb5\_set\_password\_using\_ccache}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_set_password_using_ccache:c.krb5_set_password_using_ccache}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_set\_password\_using\_ccache}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{newpw}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{change\_password\_for}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{result\_code}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{result\_code\_string}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{result\_string}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ccache} \sphinxhyphen{} Credential cache + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{newpw} \sphinxhyphen{} New password + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{change\_password\_for} \sphinxhyphen{} Change the password for this principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{result\_code} \sphinxhyphen{} Numeric error code from server + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{result\_code\_string} \sphinxhyphen{} String equivalent to \sphinxstyleemphasis{result\_code} + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{result\_string} \sphinxhyphen{} Data returned from the remote system + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function uses the cached credentials from \sphinxstyleemphasis{ccache} to set the password \sphinxstyleemphasis{newpw} for the principal \sphinxstyleemphasis{change\_password\_for} . It implements RFC 3244 set password operation (interoperable with MS Windows implementations) using the credential cache. + +\sphinxAtStartPar +The error code and strings are returned in \sphinxstyleemphasis{result\_code} , \sphinxstyleemphasis{result\_code\_string} and \sphinxstyleemphasis{result\_string} . + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +If \sphinxstyleemphasis{change\_password\_for} is set to NULL, the change is performed on the default principal in \sphinxstyleemphasis{ccache} . If \sphinxstyleemphasis{change\_password\_for} is non null, the change is performed on the specified principal. +\end{sphinxadmonition} + + +\subsubsection{krb5\_set\_principal\_realm \sphinxhyphen{} Set the realm field of a principal.} +\label{\detokenize{appdev/refs/api/krb5_set_principal_realm:krb5-set-principal-realm-set-the-realm-field-of-a-principal}}\label{\detokenize{appdev/refs/api/krb5_set_principal_realm::doc}}\index{krb5\_set\_principal\_realm (C function)@\spxentry{krb5\_set\_principal\_realm}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_set_principal_realm:c.krb5_set_principal_realm}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_set\_principal\_realm}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{realm}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Principal name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{realm} \sphinxhyphen{} Realm name + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Set the realm name part of \sphinxstyleemphasis{principal} to \sphinxstyleemphasis{realm} , overwriting the previous realm. + + +\subsubsection{krb5\_set\_trace\_callback \sphinxhyphen{} Specify a callback function for trace events.} +\label{\detokenize{appdev/refs/api/krb5_set_trace_callback:krb5-set-trace-callback-specify-a-callback-function-for-trace-events}}\label{\detokenize{appdev/refs/api/krb5_set_trace_callback::doc}}\index{krb5\_set\_trace\_callback (C function)@\spxentry{krb5\_set\_trace\_callback}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_set_trace_callback:c.krb5_set_trace_callback}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_set\_trace\_callback}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_trace_callback:c.krb5_trace_callback}]{\sphinxcrossref{\DUrole{n}{krb5\_trace\_callback}}}}\DUrole{w}{ }\DUrole{n}{fn}, \DUrole{kt}{void}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cb\_data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{fn} \sphinxhyphen{} Callback function + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cb\_data} \sphinxhyphen{} Callback data + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Returns KRB5\_TRACE\_NOSUPP if tracing is not supported in the library (unless fn is NULL). + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Specify a callback for trace events occurring in krb5 operations performed within \sphinxstyleemphasis{context} . \sphinxstyleemphasis{fn} will be invoked with \sphinxstyleemphasis{context} as the first argument, \sphinxstyleemphasis{cb\_data} as the last argument, and a pointer to a krb5\_trace\_info as the second argument. If the trace callback is reset via this function or \sphinxstyleemphasis{context} is destroyed, \sphinxstyleemphasis{fn} will be invoked with a NULL second argument so it can clean up \sphinxstyleemphasis{cb\_data} . Supply a NULL value for \sphinxstyleemphasis{fn} to disable trace callbacks within \sphinxstyleemphasis{context} . + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +This function overrides the information passed through the \sphinxstyleemphasis{KRB5\_TRACE} environment variable. +\end{sphinxadmonition} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.9 +\end{sphinxadmonition} + + +\subsubsection{krb5\_set\_trace\_filename \sphinxhyphen{} Specify a file name for directing trace events.} +\label{\detokenize{appdev/refs/api/krb5_set_trace_filename:krb5-set-trace-filename-specify-a-file-name-for-directing-trace-events}}\label{\detokenize{appdev/refs/api/krb5_set_trace_filename::doc}}\index{krb5\_set\_trace\_filename (C function)@\spxentry{krb5\_set\_trace\_filename}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_set_trace_filename:c.krb5_set_trace_filename}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_set\_trace\_filename}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{filename}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{filename} \sphinxhyphen{} File name + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +KRB5\_TRACE\_NOSUPP Tracing is not supported in the library. + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Open \sphinxstyleemphasis{filename} for appending (creating it, if necessary) and set up a callback to write trace events to it. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +This function overrides the information passed through the \sphinxstyleemphasis{KRB5\_TRACE} environment variable. +\end{sphinxadmonition} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.9 +\end{sphinxadmonition} + + +\subsubsection{krb5\_sname\_match \sphinxhyphen{} Test whether a principal matches a matching principal.} +\label{\detokenize{appdev/refs/api/krb5_sname_match:krb5-sname-match-test-whether-a-principal-matches-a-matching-principal}}\label{\detokenize{appdev/refs/api/krb5_sname_match::doc}}\index{krb5\_sname\_match (C function)@\spxentry{krb5\_sname\_match}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_sname_match:c.krb5_sname_match}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_sname\_match}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{matching}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{princ}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{matching} \sphinxhyphen{} Matching principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{princ} \sphinxhyphen{} Principal to test + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if princ matches matching , FALSE otherwise. + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +If \sphinxstyleemphasis{matching} is NULL, return TRUE. If \sphinxstyleemphasis{matching} is not a matching principal, return the value of krb5\_principal\_compare(context, matching, princ). + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +A matching principal is a host\sphinxhyphen{}based principal with an empty realm and/or second data component (hostname). Profile configuration may cause the hostname to be ignored even if it is present. A principal matches a matching principal if the former has the same non\sphinxhyphen{}empty (and non\sphinxhyphen{}ignored) components of the latter. +\end{sphinxadmonition} + + +\subsubsection{krb5\_sname\_to\_principal \sphinxhyphen{} Generate a full principal name from a service name.} +\label{\detokenize{appdev/refs/api/krb5_sname_to_principal:krb5-sname-to-principal-generate-a-full-principal-name-from-a-service-name}}\label{\detokenize{appdev/refs/api/krb5_sname_to_principal::doc}}\index{krb5\_sname\_to\_principal (C function)@\spxentry{krb5\_sname\_to\_principal}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_sname_to_principal:c.krb5_sname_to_principal}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_sname\_to\_principal}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{hostname}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{sname}, {\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\DUrole{n}{type}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ret\_princ}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{hostname} \sphinxhyphen{} Host name, or NULL to use local host + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{sname} \sphinxhyphen{} Service name, or NULL to use \sphinxstylestrong{“host”} + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{type} \sphinxhyphen{} Principal type + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ret\_princ} \sphinxhyphen{} Generated principal + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function converts a \sphinxstyleemphasis{hostname} and \sphinxstyleemphasis{sname} into \sphinxstyleemphasis{krb5\_principal} structure \sphinxstyleemphasis{ret\_princ} . The returned principal will be of the form \sphinxstyleemphasis{sname/hostname@REALM} where REALM is determined by krb5\_get\_host\_realm(). In some cases this may be the referral (empty) realm. + +\sphinxAtStartPar +The \sphinxstyleemphasis{type} can be one of the following: +\begin{quote} +\begin{itemize} +\item {} +\sphinxAtStartPar +\#KRB5\_NT\_SRV\_HST canonicalizes the host name before looking up the realm and generating the principal. + +\item {} +\sphinxAtStartPar +\#KRB5\_NT\_UNKNOWN accepts the hostname as given, and does not canonicalize it. + +\end{itemize} + +\sphinxAtStartPar +Use krb5\_free\_principal to free \sphinxstyleemphasis{ret\_princ} when it is no longer needed. +\end{quote} + + +\subsubsection{krb5\_unparse\_name \sphinxhyphen{} Convert a krb5\_principal structure to a string representation.} +\label{\detokenize{appdev/refs/api/krb5_unparse_name:krb5-unparse-name-convert-a-krb5-principal-structure-to-a-string-representation}}\label{\detokenize{appdev/refs/api/krb5_unparse_name::doc}}\index{krb5\_unparse\_name (C function)@\spxentry{krb5\_unparse\_name}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_unparse_name:c.krb5_unparse_name}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_unparse\_name}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{name}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{name} \sphinxhyphen{} String representation of principal name + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +The resulting string representation uses the format and quoting conventions described for krb5\_parse\_name(). + +\sphinxAtStartPar +Use krb5\_free\_unparsed\_name() to free \sphinxstyleemphasis{name} when it is no longer needed. + + +\subsubsection{krb5\_unparse\_name\_ext \sphinxhyphen{} Convert krb5\_principal structure to string and length.} +\label{\detokenize{appdev/refs/api/krb5_unparse_name_ext:krb5-unparse-name-ext-convert-krb5-principal-structure-to-string-and-length}}\label{\detokenize{appdev/refs/api/krb5_unparse_name_ext::doc}}\index{krb5\_unparse\_name\_ext (C function)@\spxentry{krb5\_unparse\_name\_ext}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_unparse_name_ext:c.krb5_unparse_name_ext}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_unparse\_name\_ext}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{name}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{size}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{name} \sphinxhyphen{} String representation of principal name + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{size} \sphinxhyphen{} Size of unparsed name + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes. On failure name is set to NULL + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function is similar to krb5\_unparse\_name(), but allows the use of an existing buffer for the result. If size is not NULL, then \sphinxstyleemphasis{name} must point to either NULL or an existing buffer of at least the size pointed to by \sphinxstyleemphasis{size} . The buffer will be allocated or resized if necessary, with the new pointer stored into \sphinxstyleemphasis{name} . Whether or not the buffer is resized, the necessary space for the result, including null terminator, will be stored into \sphinxstyleemphasis{size} . + +\sphinxAtStartPar +If size is NULL, this function behaves exactly as krb5\_unparse\_name(). + + +\subsubsection{krb5\_unparse\_name\_flags \sphinxhyphen{} Convert krb5\_principal structure to a string with flags.} +\label{\detokenize{appdev/refs/api/krb5_unparse_name_flags:krb5-unparse-name-flags-convert-krb5-principal-structure-to-a-string-with-flags}}\label{\detokenize{appdev/refs/api/krb5_unparse_name_flags::doc}}\index{krb5\_unparse\_name\_flags (C function)@\spxentry{krb5\_unparse\_name\_flags}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_unparse_name_flags:c.krb5_unparse_name_flags}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_unparse\_name\_flags}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{flags}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{name}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Flags + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{name} \sphinxhyphen{} String representation of principal name + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes. On failure name is set to NULL + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Similar to krb5\_unparse\_name(), this function converts a krb5\_principal structure to a string representation. + +\sphinxAtStartPar +The following flags are valid: +\begin{quote} +\begin{itemize} +\item {} +\sphinxAtStartPar +\#KRB5\_PRINCIPAL\_UNPARSE\_SHORT \sphinxhyphen{} omit realm if it is the local realm + +\item {} +\sphinxAtStartPar +\#KRB5\_PRINCIPAL\_UNPARSE\_NO\_REALM \sphinxhyphen{} omit realm + +\item {} +\sphinxAtStartPar +\#KRB5\_PRINCIPAL\_UNPARSE\_DISPLAY \sphinxhyphen{} do not quote special characters + +\end{itemize} + +\sphinxAtStartPar +Use krb5\_free\_unparsed\_name() to free \sphinxstyleemphasis{name} when it is no longer needed. +\end{quote} + + +\subsubsection{krb5\_unparse\_name\_flags\_ext \sphinxhyphen{} Convert krb5\_principal structure to string format with flags.} +\label{\detokenize{appdev/refs/api/krb5_unparse_name_flags_ext:krb5-unparse-name-flags-ext-convert-krb5-principal-structure-to-string-format-with-flags}}\label{\detokenize{appdev/refs/api/krb5_unparse_name_flags_ext::doc}}\index{krb5\_unparse\_name\_flags\_ext (C function)@\spxentry{krb5\_unparse\_name\_flags\_ext}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_unparse_name_flags_ext:c.krb5_unparse_name_flags_ext}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_unparse\_name\_flags\_ext}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{flags}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{name}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{size}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Flags + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{name} \sphinxhyphen{} Single string format of principal name + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{size} \sphinxhyphen{} Size of unparsed name buffer + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes. On failure name is set to NULL + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_us\_timeofday \sphinxhyphen{} Retrieve the system time of day, in sec and ms, since the epoch.} +\label{\detokenize{appdev/refs/api/krb5_us_timeofday:krb5-us-timeofday-retrieve-the-system-time-of-day-in-sec-and-ms-since-the-epoch}}\label{\detokenize{appdev/refs/api/krb5_us_timeofday::doc}}\index{krb5\_us\_timeofday (C function)@\spxentry{krb5\_us\_timeofday}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_us_timeofday:c.krb5_us_timeofday}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_us\_timeofday}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{seconds}, {\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{microseconds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{seconds} \sphinxhyphen{} System timeofday, seconds portion + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{microseconds} \sphinxhyphen{} System timeofday, microseconds portion + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function retrieves the system time of day with the context specific time offset adjustment. + + +\subsubsection{krb5\_verify\_authdata\_kdc\_issued \sphinxhyphen{} Unwrap and verify AD\sphinxhyphen{}KDCIssued authorization data.} +\label{\detokenize{appdev/refs/api/krb5_verify_authdata_kdc_issued:krb5-verify-authdata-kdc-issued-unwrap-and-verify-ad-kdcissued-authorization-data}}\label{\detokenize{appdev/refs/api/krb5_verify_authdata_kdc_issued::doc}}\index{krb5\_verify\_authdata\_kdc\_issued (C function)@\spxentry{krb5\_verify\_authdata\_kdc\_issued}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_verify_authdata_kdc_issued:c.krb5_verify_authdata_kdc_issued}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_verify\_authdata\_kdc\_issued}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ad\_kdcissued}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{issuer}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{authdata}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Session key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ad\_kdcissued} \sphinxhyphen{} AD\sphinxhyphen{}KDCIssued authorization data to be unwrapped + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{issuer} \sphinxhyphen{} Name of issuing principal (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{authdata} \sphinxhyphen{} Unwrapped list of authorization data + +\end{description}\end{quote} + +\sphinxAtStartPar +This function unwraps an AD\sphinxhyphen{}KDCIssued authdatum (see RFC 4120 section 5.2.6.2) and verifies its signature against \sphinxstyleemphasis{key} . The issuer field of the authdatum element is returned in \sphinxstyleemphasis{issuer} , and the unwrapped list of authdata is returned in \sphinxstyleemphasis{authdata} . + + +\subsection{Rarely used public interfaces} +\label{\detokenize{appdev/refs/api/index:rarely-used-public-interfaces}} + +\subsubsection{krb5\_425\_conv\_principal \sphinxhyphen{} Convert a Kerberos V4 principal to a Kerberos V5 principal.} +\label{\detokenize{appdev/refs/api/krb5_425_conv_principal:krb5-425-conv-principal-convert-a-kerberos-v4-principal-to-a-kerberos-v5-principal}}\label{\detokenize{appdev/refs/api/krb5_425_conv_principal::doc}}\index{krb5\_425\_conv\_principal (C function)@\spxentry{krb5\_425\_conv\_principal}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_425_conv_principal:c.krb5_425_conv_principal}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_425\_conv\_principal}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{name}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{instance}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{realm}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{princ}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{name} \sphinxhyphen{} V4 name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{instance} \sphinxhyphen{} V4 instance + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{realm} \sphinxhyphen{} Realm + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{princ} \sphinxhyphen{} V5 principal + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function builds a \sphinxstyleemphasis{princ} from V4 specification based on given input \sphinxstyleemphasis{name.instance@realm} . + +\sphinxAtStartPar +Use krb5\_free\_principal() to free \sphinxstyleemphasis{princ} when it is no longer needed. + + +\subsubsection{krb5\_524\_conv\_principal \sphinxhyphen{} Convert a Kerberos V5 principal to a Kerberos V4 principal.} +\label{\detokenize{appdev/refs/api/krb5_524_conv_principal:krb5-524-conv-principal-convert-a-kerberos-v5-principal-to-a-kerberos-v4-principal}}\label{\detokenize{appdev/refs/api/krb5_524_conv_principal::doc}}\index{krb5\_524\_conv\_principal (C function)@\spxentry{krb5\_524\_conv\_principal}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_524_conv_principal:c.krb5_524_conv_principal}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_524\_conv\_principal}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{princ}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{name}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{inst}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{realm}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{princ} \sphinxhyphen{} V5 Principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{name} \sphinxhyphen{} V4 principal’s name to be filled in + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{inst} \sphinxhyphen{} V4 principal’s instance name to be filled in + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{realm} \sphinxhyphen{} Principal’s realm name to be filled in + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +KRB5\_INVALID\_PRINCIPAL Invalid principal name + +\item {} +\sphinxAtStartPar +KRB5\_CONFIG\_CANTOPEN Can’t open or find Kerberos configuration file + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function separates a V5 principal \sphinxstyleemphasis{princ} into \sphinxstyleemphasis{name} , \sphinxstyleemphasis{instance} , and \sphinxstyleemphasis{realm} . + + +\subsubsection{krb5\_address\_compare \sphinxhyphen{} Compare two Kerberos addresses.} +\label{\detokenize{appdev/refs/api/krb5_address_compare:krb5-address-compare-compare-two-kerberos-addresses}}\label{\detokenize{appdev/refs/api/krb5_address_compare::doc}}\index{krb5\_address\_compare (C function)@\spxentry{krb5\_address\_compare}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_address_compare:c.krb5_address_compare}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_address\_compare}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{addr1}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{addr2}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{addr1} \sphinxhyphen{} First address to be compared + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{addr2} \sphinxhyphen{} Second address to be compared + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if the addresses are the same, FALSE otherwise + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_address\_order \sphinxhyphen{} Return an ordering of the specified addresses.} +\label{\detokenize{appdev/refs/api/krb5_address_order:krb5-address-order-return-an-ordering-of-the-specified-addresses}}\label{\detokenize{appdev/refs/api/krb5_address_order::doc}}\index{krb5\_address\_order (C function)@\spxentry{krb5\_address\_order}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_address_order:c.krb5_address_order}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{int}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_address\_order}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{addr1}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{addr2}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{addr1} \sphinxhyphen{} First address + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{addr2} \sphinxhyphen{} Second address + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 if The two addresses are the same + +\item {} +\sphinxAtStartPar +\textless{} 0 First address is less than second + +\item {} +\sphinxAtStartPar +\textgreater{} 0 First address is greater than second + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_address\_search \sphinxhyphen{} Search a list of addresses for a specified address.} +\label{\detokenize{appdev/refs/api/krb5_address_search:krb5-address-search-search-a-list-of-addresses-for-a-specified-address}}\label{\detokenize{appdev/refs/api/krb5_address_search::doc}}\index{krb5\_address\_search (C function)@\spxentry{krb5\_address\_search}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_address_search:c.krb5_address_search}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_address\_search}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{addr}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{addrlist}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{addr} \sphinxhyphen{} Address to search for + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{addrlist} \sphinxhyphen{} Address list to be searched (or NULL) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if addr is listed in addrlist , or addrlist is NULL; FALSE otherwise + +\end{itemize} + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +If \sphinxstyleemphasis{addrlist} contains only a NetBIOS addresses, it will be treated as a null list. +\end{sphinxadmonition} + + +\subsubsection{krb5\_allow\_weak\_crypto \sphinxhyphen{} Allow the application to override the profile’s allow\_weak\_crypto setting.} +\label{\detokenize{appdev/refs/api/krb5_allow_weak_crypto:krb5-allow-weak-crypto-allow-the-application-to-override-the-profile-s-allow-weak-crypto-setting}}\label{\detokenize{appdev/refs/api/krb5_allow_weak_crypto::doc}}\index{krb5\_allow\_weak\_crypto (C function)@\spxentry{krb5\_allow\_weak\_crypto}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_allow_weak_crypto:c.krb5_allow_weak_crypto}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_allow\_weak\_crypto}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\DUrole{n}{enable}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enable} \sphinxhyphen{} Boolean flag + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 (always) + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function allows an application to override the allow\_weak\_crypto setting. It is primarily for use by aklog. + + +\subsubsection{krb5\_aname\_to\_localname \sphinxhyphen{} Convert a principal name to a local name.} +\label{\detokenize{appdev/refs/api/krb5_aname_to_localname:krb5-aname-to-localname-convert-a-principal-name-to-a-local-name}}\label{\detokenize{appdev/refs/api/krb5_aname_to_localname::doc}}\index{krb5\_aname\_to\_localname (C function)@\spxentry{krb5\_aname\_to\_localname}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_aname_to_localname:c.krb5_aname_to_localname}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_aname\_to\_localname}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{aname}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{lnsize\_in}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{lname}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{aname} \sphinxhyphen{} Principal name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{lnsize\_in} \sphinxhyphen{} Space available in \sphinxstyleemphasis{lname} + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{lname} \sphinxhyphen{} Local name buffer to be filled in + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +System errors + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +If \sphinxstyleemphasis{aname} does not correspond to any local account, KRB5\_LNAME\_NOTRANS is returned. If \sphinxstyleemphasis{lnsize\_in} is too small for the local name, KRB5\_CONFIG\_NOTENUFSPACE is returned. + +\sphinxAtStartPar +Local names, rather than principal names, can be used by programs that translate to an environment\sphinxhyphen{}specific name (for example, a user account name). + + +\subsubsection{krb5\_anonymous\_principal \sphinxhyphen{} Build an anonymous principal.} +\label{\detokenize{appdev/refs/api/krb5_anonymous_principal:krb5-anonymous-principal-build-an-anonymous-principal}}\label{\detokenize{appdev/refs/api/krb5_anonymous_principal::doc}}\index{krb5\_anonymous\_principal (C function)@\spxentry{krb5\_anonymous\_principal}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_anonymous_principal:c.krb5_anonymous_principal}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_anonymous\_principal}}}}{\DUrole{kt}{void}\DUrole{w}{ }\DUrole{n}{None}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{None} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function returns constant storage that must not be freed. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +\#KRB5\_ANONYMOUS\_PRINCSTR + + + + +\subsubsection{krb5\_anonymous\_realm \sphinxhyphen{} Return an anonymous realm data.} +\label{\detokenize{appdev/refs/api/krb5_anonymous_realm:krb5-anonymous-realm-return-an-anonymous-realm-data}}\label{\detokenize{appdev/refs/api/krb5_anonymous_realm::doc}}\index{krb5\_anonymous\_realm (C function)@\spxentry{krb5\_anonymous\_realm}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_anonymous_realm:c.krb5_anonymous_realm}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_anonymous\_realm}}}}{\DUrole{kt}{void}\DUrole{w}{ }\DUrole{n}{None}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{None} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function returns constant storage that must not be freed. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +\#KRB5\_ANONYMOUS\_REALMSTR + + + + +\subsubsection{krb5\_appdefault\_boolean \sphinxhyphen{} Retrieve a boolean value from the appdefaults section of krb5.conf.} +\label{\detokenize{appdev/refs/api/krb5_appdefault_boolean:krb5-appdefault-boolean-retrieve-a-boolean-value-from-the-appdefaults-section-of-krb5-conf}}\label{\detokenize{appdev/refs/api/krb5_appdefault_boolean::doc}}\index{krb5\_appdefault\_boolean (C function)@\spxentry{krb5\_appdefault\_boolean}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_appdefault_boolean:c.krb5_appdefault_boolean}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_appdefault\_boolean}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{appname}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{realm}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{option}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{default\_value}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ret\_value}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{appname} \sphinxhyphen{} Application name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{realm} \sphinxhyphen{} Realm name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{option} \sphinxhyphen{} Option to be checked + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{default\_value} \sphinxhyphen{} Default value to return if no match is found + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ret\_value} \sphinxhyphen{} Boolean value of \sphinxstyleemphasis{option} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function gets the application defaults for \sphinxstyleemphasis{option} based on the given \sphinxstyleemphasis{appname} and/or \sphinxstyleemphasis{realm} . + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_appdefault\_string() + + + + +\subsubsection{krb5\_appdefault\_string \sphinxhyphen{} Retrieve a string value from the appdefaults section of krb5.conf.} +\label{\detokenize{appdev/refs/api/krb5_appdefault_string:krb5-appdefault-string-retrieve-a-string-value-from-the-appdefaults-section-of-krb5-conf}}\label{\detokenize{appdev/refs/api/krb5_appdefault_string::doc}}\index{krb5\_appdefault\_string (C function)@\spxentry{krb5\_appdefault\_string}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_appdefault_string:c.krb5_appdefault_string}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_appdefault\_string}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{appname}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{realm}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{option}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{default\_value}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{ret\_value}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{appname} \sphinxhyphen{} Application name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{realm} \sphinxhyphen{} Realm name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{option} \sphinxhyphen{} Option to be checked + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{default\_value} \sphinxhyphen{} Default value to return if no match is found + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ret\_value} \sphinxhyphen{} String value of \sphinxstyleemphasis{option} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function gets the application defaults for \sphinxstyleemphasis{option} based on the given \sphinxstyleemphasis{appname} and/or \sphinxstyleemphasis{realm} . + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_appdefault\_boolean() + + + + +\subsubsection{krb5\_auth\_con\_free \sphinxhyphen{} Free a krb5\_auth\_context structure.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_free:krb5-auth-con-free-free-a-krb5-auth-context-structure}}\label{\detokenize{appdev/refs/api/krb5_auth_con_free::doc}}\index{krb5\_auth\_con\_free (C function)@\spxentry{krb5\_auth\_con\_free}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_free:c.krb5_auth_con_free}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_free}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context to be freed + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 (always) + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees an auth context allocated by krb5\_auth\_con\_init(). + + +\subsubsection{krb5\_auth\_con\_genaddrs \sphinxhyphen{} Generate auth context addresses from a connected socket.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_genaddrs:krb5-auth-con-genaddrs-generate-auth-context-addresses-from-a-connected-socket}}\label{\detokenize{appdev/refs/api/krb5_auth_con_genaddrs::doc}}\index{krb5\_auth\_con\_genaddrs (C function)@\spxentry{krb5\_auth\_con\_genaddrs}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_genaddrs:c.krb5_auth_con_genaddrs}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_genaddrs}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{infd}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{flags}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{infd} \sphinxhyphen{} Connected socket descriptor + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Flags + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function sets the local and/or remote addresses in \sphinxstyleemphasis{auth\_context} based on the local and remote endpoints of the socket \sphinxstyleemphasis{infd} . The following flags determine the operations performed: +\begin{itemize} +\item {} +\sphinxAtStartPar +\#KRB5\_AUTH\_CONTEXT\_GENERATE\_LOCAL\_ADDR Generate local address. + +\item {} +\sphinxAtStartPar +\#KRB5\_AUTH\_CONTEXT\_GENERATE\_REMOTE\_ADDR Generate remote address. + +\item {} +\sphinxAtStartPar +\#KRB5\_AUTH\_CONTEXT\_GENERATE\_LOCAL\_FULL\_ADDR Generate local address and port. + +\item {} +\sphinxAtStartPar +\#KRB5\_AUTH\_CONTEXT\_GENERATE\_REMOTE\_FULL\_ADDR Generate remote address and port. + +\end{itemize} + + +\subsubsection{krb5\_auth\_con\_get\_checksum\_func \sphinxhyphen{} Get the checksum callback from an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_get_checksum_func:krb5-auth-con-get-checksum-func-get-the-checksum-callback-from-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_get_checksum_func::doc}}\index{krb5\_auth\_con\_get\_checksum\_func (C function)@\spxentry{krb5\_auth\_con\_get\_checksum\_func}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_get_checksum_func:c.krb5_auth_con_get_checksum_func}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_get\_checksum\_func}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_mk_req_checksum_func:c.krb5_mk_req_checksum_func}]{\sphinxcrossref{\DUrole{n}{krb5\_mk\_req\_checksum\_func}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{func}, \DUrole{kt}{void}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{func} \sphinxhyphen{} Checksum callback + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{data} \sphinxhyphen{} Callback argument + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 (always) + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_auth\_con\_getaddrs \sphinxhyphen{} Retrieve address fields from an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getaddrs:krb5-auth-con-getaddrs-retrieve-address-fields-from-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getaddrs::doc}}\index{krb5\_auth\_con\_getaddrs (C function)@\spxentry{krb5\_auth\_con\_getaddrs}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getaddrs:c.krb5_auth_con_getaddrs}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getaddrs}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{local\_addr}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{remote\_addr}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{local\_addr} \sphinxhyphen{} Local address (NULL if not needed) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{remote\_addr} \sphinxhyphen{} Remote address (NULL if not needed) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_auth\_con\_getauthenticator \sphinxhyphen{} Retrieve the authenticator from an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getauthenticator:krb5-auth-con-getauthenticator-retrieve-the-authenticator-from-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getauthenticator::doc}}\index{krb5\_auth\_con\_getauthenticator (C function)@\spxentry{krb5\_auth\_con\_getauthenticator}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getauthenticator:c.krb5_auth_con_getauthenticator}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getauthenticator}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}]{\sphinxcrossref{\DUrole{n}{krb5\_authenticator}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{authenticator}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{authenticator} \sphinxhyphen{} Authenticator + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success. Otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Use krb5\_free\_authenticator() to free \sphinxstyleemphasis{authenticator} when it is no longer needed. + + +\subsubsection{krb5\_auth\_con\_getflags \sphinxhyphen{} Retrieve flags from a krb5\_auth\_context structure.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getflags:krb5-auth-con-getflags-retrieve-flags-from-a-krb5-auth-context-structure}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getflags::doc}}\index{krb5\_auth\_con\_getflags (C function)@\spxentry{krb5\_auth\_con\_getflags}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getflags:c.krb5_auth_con_getflags}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getflags}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{flags}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Flags bit mask + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 (always) + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Valid values for \sphinxstyleemphasis{flags} are: +\begin{itemize} +\item {} +\sphinxAtStartPar +\#KRB5\_AUTH\_CONTEXT\_DO\_TIME Use timestamps + +\item {} +\sphinxAtStartPar +\#KRB5\_AUTH\_CONTEXT\_RET\_TIME Save timestamps + +\item {} +\sphinxAtStartPar +\#KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE Use sequence numbers + +\item {} +\sphinxAtStartPar +\#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE Save sequence numbers + +\end{itemize} + + +\subsubsection{krb5\_auth\_con\_getkey \sphinxhyphen{} Retrieve the session key from an auth context as a keyblock.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getkey:krb5-auth-con-getkey-retrieve-the-session-key-from-an-auth-context-as-a-keyblock}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getkey::doc}}\index{krb5\_auth\_con\_getkey (C function)@\spxentry{krb5\_auth\_con\_getkey}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getkey:c.krb5_auth_con_getkey}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getkey}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{keyblock}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{keyblock} \sphinxhyphen{} Session key + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success. Otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a keyblock containing the session key from \sphinxstyleemphasis{auth\_context} . Use krb5\_free\_keyblock() to free \sphinxstyleemphasis{keyblock} when it is no longer needed + + +\subsubsection{krb5\_auth\_con\_getkey\_k \sphinxhyphen{} Retrieve the session key from an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getkey_k:krb5-auth-con-getkey-k-retrieve-the-session-key-from-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getkey_k::doc}}\index{krb5\_auth\_con\_getkey\_k (C function)@\spxentry{krb5\_auth\_con\_getkey\_k}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getkey_k:c.krb5_auth_con_getkey_k}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getkey\_k}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{key} \sphinxhyphen{} Session key + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 (always) + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function sets \sphinxstyleemphasis{key} to the session key from \sphinxstyleemphasis{auth\_context} . Use krb5\_k\_free\_key() to release \sphinxstyleemphasis{key} when it is no longer needed. + + +\subsubsection{krb5\_auth\_con\_getlocalseqnumber \sphinxhyphen{} Retrieve the local sequence number from an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getlocalseqnumber:krb5-auth-con-getlocalseqnumber-retrieve-the-local-sequence-number-from-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getlocalseqnumber::doc}}\index{krb5\_auth\_con\_getlocalseqnumber (C function)@\spxentry{krb5\_auth\_con\_getlocalseqnumber}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getlocalseqnumber:c.krb5_auth_con_getlocalseqnumber}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getlocalseqnumber}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{seqnumber}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{seqnumber} \sphinxhyphen{} Local sequence number + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Retrieve the local sequence number from \sphinxstyleemphasis{auth\_context} and return it in \sphinxstyleemphasis{seqnumber} . The \#KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE flag must be set in \sphinxstyleemphasis{auth\_context} for this function to be useful. + + +\subsubsection{krb5\_auth\_con\_getrcache \sphinxhyphen{} Retrieve the replay cache from an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getrcache:krb5-auth-con-getrcache-retrieve-the-replay-cache-from-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getrcache::doc}}\index{krb5\_auth\_con\_getrcache (C function)@\spxentry{krb5\_auth\_con\_getrcache}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getrcache:c.krb5_auth_con_getrcache}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getrcache}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_rcache:c.krb5_rcache}]{\sphinxcrossref{\DUrole{n}{krb5\_rcache}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{rcache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{rcache} \sphinxhyphen{} Replay cache handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 (always) + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function fetches the replay cache from \sphinxstyleemphasis{auth\_context} . The caller should not close \sphinxstyleemphasis{rcache} . + + +\subsubsection{krb5\_auth\_con\_getrecvsubkey \sphinxhyphen{} Retrieve the receiving subkey from an auth context as a keyblock.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getrecvsubkey:krb5-auth-con-getrecvsubkey-retrieve-the-receiving-subkey-from-an-auth-context-as-a-keyblock}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getrecvsubkey::doc}}\index{krb5\_auth\_con\_getrecvsubkey (C function)@\spxentry{krb5\_auth\_con\_getrecvsubkey}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getrecvsubkey:c.krb5_auth_con_getrecvsubkey}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getrecvsubkey}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{ac}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{keyblock}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ac} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{keyblock} \sphinxhyphen{} Receiving subkey + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a keyblock containing the receiving subkey from \sphinxstyleemphasis{auth\_context} . Use krb5\_free\_keyblock() to free \sphinxstyleemphasis{keyblock} when it is no longer needed. + + +\subsubsection{krb5\_auth\_con\_getrecvsubkey\_k \sphinxhyphen{} Retrieve the receiving subkey from an auth context as a keyblock.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getrecvsubkey_k:krb5-auth-con-getrecvsubkey-k-retrieve-the-receiving-subkey-from-an-auth-context-as-a-keyblock}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getrecvsubkey_k::doc}}\index{krb5\_auth\_con\_getrecvsubkey\_k (C function)@\spxentry{krb5\_auth\_con\_getrecvsubkey\_k}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getrecvsubkey_k:c.krb5_auth_con_getrecvsubkey_k}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getrecvsubkey\_k}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{ac}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ac} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{key} \sphinxhyphen{} Receiving subkey + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function sets \sphinxstyleemphasis{key} to the receiving subkey from \sphinxstyleemphasis{auth\_context} . Use krb5\_k\_free\_key() to release \sphinxstyleemphasis{key} when it is no longer needed. + + +\subsubsection{krb5\_auth\_con\_getremoteseqnumber \sphinxhyphen{} Retrieve the remote sequence number from an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getremoteseqnumber:krb5-auth-con-getremoteseqnumber-retrieve-the-remote-sequence-number-from-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getremoteseqnumber::doc}}\index{krb5\_auth\_con\_getremoteseqnumber (C function)@\spxentry{krb5\_auth\_con\_getremoteseqnumber}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getremoteseqnumber:c.krb5_auth_con_getremoteseqnumber}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getremoteseqnumber}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{seqnumber}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{seqnumber} \sphinxhyphen{} Remote sequence number + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Retrieve the remote sequence number from \sphinxstyleemphasis{auth\_context} and return it in \sphinxstyleemphasis{seqnumber} . The \#KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE flag must be set in \sphinxstyleemphasis{auth\_context} for this function to be useful. + + +\subsubsection{krb5\_auth\_con\_getsendsubkey \sphinxhyphen{} Retrieve the send subkey from an auth context as a keyblock.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getsendsubkey:krb5-auth-con-getsendsubkey-retrieve-the-send-subkey-from-an-auth-context-as-a-keyblock}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getsendsubkey::doc}}\index{krb5\_auth\_con\_getsendsubkey (C function)@\spxentry{krb5\_auth\_con\_getsendsubkey}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getsendsubkey:c.krb5_auth_con_getsendsubkey}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getsendsubkey}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{ac}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{keyblock}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ac} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{keyblock} \sphinxhyphen{} Send subkey + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a keyblock containing the send subkey from \sphinxstyleemphasis{auth\_context} . Use krb5\_free\_keyblock() to free \sphinxstyleemphasis{keyblock} when it is no longer needed. + + +\subsubsection{krb5\_auth\_con\_getsendsubkey\_k \sphinxhyphen{} Retrieve the send subkey from an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getsendsubkey_k:krb5-auth-con-getsendsubkey-k-retrieve-the-send-subkey-from-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getsendsubkey_k::doc}}\index{krb5\_auth\_con\_getsendsubkey\_k (C function)@\spxentry{krb5\_auth\_con\_getsendsubkey\_k}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getsendsubkey_k:c.krb5_auth_con_getsendsubkey_k}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getsendsubkey\_k}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{ac}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ac} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{key} \sphinxhyphen{} Send subkey + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function sets \sphinxstyleemphasis{key} to the send subkey from \sphinxstyleemphasis{auth\_context} . Use krb5\_k\_free\_key() to release \sphinxstyleemphasis{key} when it is no longer needed. + + +\subsubsection{krb5\_auth\_con\_init \sphinxhyphen{} Create and initialize an authentication context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_init:krb5-auth-con-init-create-and-initialize-an-authentication-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_init::doc}}\index{krb5\_auth\_con\_init (C function)@\spxentry{krb5\_auth\_con\_init}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_init:c.krb5_auth_con_init}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_init}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{auth\_context}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates an authentication context to hold configuration and state relevant to krb5 functions for authenticating principals and protecting messages once authentication has occurred. + +\sphinxAtStartPar +By default, flags for the context are set to enable the use of the replay cache (\#KRB5\_AUTH\_CONTEXT\_DO\_TIME), but not sequence numbers. Use krb5\_auth\_con\_setflags() to change the flags. + +\sphinxAtStartPar +The allocated \sphinxstyleemphasis{auth\_context} must be freed with krb5\_auth\_con\_free() when it is no longer needed. + + +\subsubsection{krb5\_auth\_con\_set\_checksum\_func \sphinxhyphen{} Set a checksum callback in an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_set_checksum_func:krb5-auth-con-set-checksum-func-set-a-checksum-callback-in-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_set_checksum_func::doc}}\index{krb5\_auth\_con\_set\_checksum\_func (C function)@\spxentry{krb5\_auth\_con\_set\_checksum\_func}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_set_checksum_func:c.krb5_auth_con_set_checksum_func}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_set\_checksum\_func}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_mk_req_checksum_func:c.krb5_mk_req_checksum_func}]{\sphinxcrossref{\DUrole{n}{krb5\_mk\_req\_checksum\_func}}}}\DUrole{w}{ }\DUrole{n}{func}, \DUrole{kt}{void}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{func} \sphinxhyphen{} Checksum callback + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} Callback argument + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 (always) + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Set a callback to obtain checksum data in krb5\_mk\_req(). The callback will be invoked after the subkey and local sequence number are stored in \sphinxstyleemphasis{auth\_context} . + + +\subsubsection{krb5\_auth\_con\_set\_req\_cksumtype \sphinxhyphen{} Set checksum type in an an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_set_req_cksumtype:krb5-auth-con-set-req-cksumtype-set-checksum-type-in-an-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_set_req_cksumtype::doc}}\index{krb5\_auth\_con\_set\_req\_cksumtype (C function)@\spxentry{krb5\_auth\_con\_set\_req\_cksumtype}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_set_req_cksumtype:c.krb5_auth_con_set_req_cksumtype}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_set\_req\_cksumtype}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{cksumtype}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cksumtype} \sphinxhyphen{} Checksum type + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success. Otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function sets the checksum type in \sphinxstyleemphasis{auth\_context} to be used by krb5\_mk\_req() for the authenticator checksum. + + +\subsubsection{krb5\_auth\_con\_setaddrs \sphinxhyphen{} Set the local and remote addresses in an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_setaddrs:krb5-auth-con-setaddrs-set-the-local-and-remote-addresses-in-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_setaddrs::doc}}\index{krb5\_auth\_con\_setaddrs (C function)@\spxentry{krb5\_auth\_con\_setaddrs}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_setaddrs:c.krb5_auth_con_setaddrs}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_setaddrs}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{local\_addr}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{remote\_addr}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{local\_addr} \sphinxhyphen{} Local address + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{remote\_addr} \sphinxhyphen{} Remote address + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function releases the storage assigned to the contents of the local and remote addresses of \sphinxstyleemphasis{auth\_context} and then sets them to \sphinxstyleemphasis{local\_addr} and \sphinxstyleemphasis{remote\_addr} respectively. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_auth\_con\_genaddrs() + + + + +\subsubsection{krb5\_auth\_con\_setflags \sphinxhyphen{} Set a flags field in a krb5\_auth\_context structure.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_setflags:krb5-auth-con-setflags-set-a-flags-field-in-a-krb5-auth-context-structure}}\label{\detokenize{appdev/refs/api/krb5_auth_con_setflags::doc}}\index{krb5\_auth\_con\_setflags (C function)@\spxentry{krb5\_auth\_con\_setflags}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_setflags:c.krb5_auth_con_setflags}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_setflags}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\DUrole{n}{flags}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Flags bit mask + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 (always) + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Valid values for \sphinxstyleemphasis{flags} are: +\begin{itemize} +\item {} +\sphinxAtStartPar +\#KRB5\_AUTH\_CONTEXT\_DO\_TIME Use timestamps + +\item {} +\sphinxAtStartPar +\#KRB5\_AUTH\_CONTEXT\_RET\_TIME Save timestamps + +\item {} +\sphinxAtStartPar +\#KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE Use sequence numbers + +\item {} +\sphinxAtStartPar +\#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE Save sequence numbers + +\end{itemize} + + +\subsubsection{krb5\_auth\_con\_setports \sphinxhyphen{} Set local and remote port fields in an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_setports:krb5-auth-con-setports-set-local-and-remote-port-fields-in-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_setports::doc}}\index{krb5\_auth\_con\_setports (C function)@\spxentry{krb5\_auth\_con\_setports}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_setports:c.krb5_auth_con_setports}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_setports}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{local\_port}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{remote\_port}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{local\_port} \sphinxhyphen{} Local port + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{remote\_port} \sphinxhyphen{} Remote port + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function releases the storage assigned to the contents of the local and remote ports of \sphinxstyleemphasis{auth\_context} and then sets them to \sphinxstyleemphasis{local\_port} and \sphinxstyleemphasis{remote\_port} respectively. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_auth\_con\_genaddrs() + + + + +\subsubsection{krb5\_auth\_con\_setrcache \sphinxhyphen{} Set the replay cache in an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_setrcache:krb5-auth-con-setrcache-set-the-replay-cache-in-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_setrcache::doc}}\index{krb5\_auth\_con\_setrcache (C function)@\spxentry{krb5\_auth\_con\_setrcache}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_setrcache:c.krb5_auth_con_setrcache}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_setrcache}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_rcache:c.krb5_rcache}]{\sphinxcrossref{\DUrole{n}{krb5\_rcache}}}}\DUrole{w}{ }\DUrole{n}{rcache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{rcache} \sphinxhyphen{} Replay cache haddle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function sets the replay cache in \sphinxstyleemphasis{auth\_context} to \sphinxstyleemphasis{rcache} . \sphinxstyleemphasis{rcache} will be closed when \sphinxstyleemphasis{auth\_context} is freed, so the caller should relinquish that responsibility. + + +\subsubsection{krb5\_auth\_con\_setrecvsubkey \sphinxhyphen{} Set the receiving subkey in an auth context with a keyblock.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_setrecvsubkey:krb5-auth-con-setrecvsubkey-set-the-receiving-subkey-in-an-auth-context-with-a-keyblock}}\label{\detokenize{appdev/refs/api/krb5_auth_con_setrecvsubkey::doc}}\index{krb5\_auth\_con\_setrecvsubkey (C function)@\spxentry{krb5\_auth\_con\_setrecvsubkey}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_setrecvsubkey:c.krb5_auth_con_setrecvsubkey}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_setrecvsubkey}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{ac}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{keyblock}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ac} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keyblock} \sphinxhyphen{} Receiving subkey + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function sets the receiving subkey in \sphinxstyleemphasis{ac} to a copy of \sphinxstyleemphasis{keyblock} . + + +\subsubsection{krb5\_auth\_con\_setrecvsubkey\_k \sphinxhyphen{} Set the receiving subkey in an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_setrecvsubkey_k:krb5-auth-con-setrecvsubkey-k-set-the-receiving-subkey-in-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_setrecvsubkey_k::doc}}\index{krb5\_auth\_con\_setrecvsubkey\_k (C function)@\spxentry{krb5\_auth\_con\_setrecvsubkey\_k}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_setrecvsubkey_k:c.krb5_auth_con_setrecvsubkey_k}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_setrecvsubkey\_k}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{ac}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ac} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Receiving subkey + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function sets the receiving subkey in \sphinxstyleemphasis{ac} to \sphinxstyleemphasis{key} , incrementing its reference count. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.9 +\end{sphinxadmonition} + + +\subsubsection{krb5\_auth\_con\_setsendsubkey \sphinxhyphen{} Set the send subkey in an auth context with a keyblock.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_setsendsubkey:krb5-auth-con-setsendsubkey-set-the-send-subkey-in-an-auth-context-with-a-keyblock}}\label{\detokenize{appdev/refs/api/krb5_auth_con_setsendsubkey::doc}}\index{krb5\_auth\_con\_setsendsubkey (C function)@\spxentry{krb5\_auth\_con\_setsendsubkey}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_setsendsubkey:c.krb5_auth_con_setsendsubkey}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_setsendsubkey}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{ac}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{keyblock}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ac} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keyblock} \sphinxhyphen{} Send subkey + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success. Otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function sets the send subkey in \sphinxstyleemphasis{ac} to a copy of \sphinxstyleemphasis{keyblock} . + + +\subsubsection{krb5\_auth\_con\_setsendsubkey\_k \sphinxhyphen{} Set the send subkey in an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_setsendsubkey_k:krb5-auth-con-setsendsubkey-k-set-the-send-subkey-in-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_setsendsubkey_k::doc}}\index{krb5\_auth\_con\_setsendsubkey\_k (C function)@\spxentry{krb5\_auth\_con\_setsendsubkey\_k}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_setsendsubkey_k:c.krb5_auth_con_setsendsubkey_k}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_setsendsubkey\_k}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{ac}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ac} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{key} \sphinxhyphen{} Send subkey + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function sets the send subkey in \sphinxstyleemphasis{ac} to \sphinxstyleemphasis{key} , incrementing its reference count. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.9 +\end{sphinxadmonition} + + +\subsubsection{krb5\_auth\_con\_setuseruserkey \sphinxhyphen{} Set the session key in an auth context.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_setuseruserkey:krb5-auth-con-setuseruserkey-set-the-session-key-in-an-auth-context}}\label{\detokenize{appdev/refs/api/krb5_auth_con_setuseruserkey::doc}}\index{krb5\_auth\_con\_setuseruserkey (C function)@\spxentry{krb5\_auth\_con\_setuseruserkey}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_setuseruserkey:c.krb5_auth_con_setuseruserkey}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_setuseruserkey}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{keyblock}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keyblock} \sphinxhyphen{} User key + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_cc\_cache\_match \sphinxhyphen{} Find a credential cache with a specified client principal.} +\label{\detokenize{appdev/refs/api/krb5_cc_cache_match:krb5-cc-cache-match-find-a-credential-cache-with-a-specified-client-principal}}\label{\detokenize{appdev/refs/api/krb5_cc_cache_match::doc}}\index{krb5\_cc\_cache\_match (C function)@\spxentry{krb5\_cc\_cache\_match}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_cache_match:c.krb5_cc_cache_match}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_cache\_match}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{client}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cache\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{client} \sphinxhyphen{} Client principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{cache\_out} \sphinxhyphen{} Credential cache handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +KRB5\_CC\_NOTFOUND None + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Find a cache within the collection whose default principal is \sphinxstyleemphasis{client} . Use \sphinxstyleemphasis{krb5\_cc\_close} to close \sphinxstyleemphasis{ccache} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.10 +\end{sphinxadmonition} + + +\subsubsection{krb5\_cc\_copy\_creds \sphinxhyphen{} Copy a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_copy_creds:krb5-cc-copy-creds-copy-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_copy_creds::doc}}\index{krb5\_cc\_copy\_creds (C function)@\spxentry{krb5\_cc\_copy\_creds}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_copy_creds:c.krb5_cc_copy_creds}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_copy\_creds}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{incc}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{outcc}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{incc} \sphinxhyphen{} Credential cache to be copied + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{outcc} \sphinxhyphen{} Copy of credential cache to be filled in + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_cc\_end\_seq\_get \sphinxhyphen{} Finish a series of sequential processing credential cache entries.} +\label{\detokenize{appdev/refs/api/krb5_cc_end_seq_get:krb5-cc-end-seq-get-finish-a-series-of-sequential-processing-credential-cache-entries}}\label{\detokenize{appdev/refs/api/krb5_cc_end_seq_get::doc}}\index{krb5\_cc\_end\_seq\_get (C function)@\spxentry{krb5\_cc\_end\_seq\_get}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_end_seq_get:c.krb5_cc_end_seq_get}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_end\_seq\_get}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}, {\hyperref[\detokenize{appdev/refs/types/krb5_cc_cursor:c.krb5_cc_cursor}]{\sphinxcrossref{\DUrole{n}{krb5\_cc\_cursor}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cursor}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cursor} \sphinxhyphen{} Cursor + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 (always) + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function finishes processing credential cache entries and invalidates \sphinxstyleemphasis{cursor} . + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_cc\_start\_seq\_get(), krb5\_cc\_next\_cred() + + + + +\subsubsection{krb5\_cc\_get\_config \sphinxhyphen{} Get a configuration value from a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_get_config:krb5-cc-get-config-get-a-configuration-value-from-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_get_config::doc}}\index{krb5\_cc\_get\_config (C function)@\spxentry{krb5\_cc\_get\_config}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_get_config:c.krb5_cc_get_config}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_get\_config}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{id}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{id} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Configuration for this principal; if NULL, global for the whole cache + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Name of config variable + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{data} \sphinxhyphen{} Data to be fetched + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Use krb5\_free\_data\_contents() to free \sphinxstyleemphasis{data} when it is no longer needed. + + +\subsubsection{krb5\_cc\_get\_flags \sphinxhyphen{} Retrieve flags from a credential cache structure.} +\label{\detokenize{appdev/refs/api/krb5_cc_get_flags:krb5-cc-get-flags-retrieve-flags-from-a-credential-cache-structure}}\label{\detokenize{appdev/refs/api/krb5_cc_get_flags::doc}}\index{krb5\_cc\_get\_flags (C function)@\spxentry{krb5\_cc\_get\_flags}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_get_flags:c.krb5_cc_get_flags}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_get\_flags}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{flags}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Flag bit mask + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\begin{sphinxadmonition}{warning}{Warning:} +\sphinxAtStartPar +For memory credential cache always returns a flag mask of 0. +\end{sphinxadmonition} + + +\subsubsection{krb5\_cc\_get\_full\_name \sphinxhyphen{} Retrieve the full name of a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_get_full_name:krb5-cc-get-full-name-retrieve-the-full-name-of-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_get_full_name::doc}}\index{krb5\_cc\_get\_full\_name (C function)@\spxentry{krb5\_cc\_get\_full\_name}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_get_full_name:c.krb5_cc_get_full_name}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_get\_full\_name}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{fullname\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{fullname\_out} \sphinxhyphen{} Full name of cache + +\end{description}\end{quote} + +\sphinxAtStartPar +Use krb5\_free\_string() to free \sphinxstyleemphasis{fullname\_out} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.10 +\end{sphinxadmonition} + + +\subsubsection{krb5\_cc\_move \sphinxhyphen{} Move a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_move:krb5-cc-move-move-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_move::doc}}\index{krb5\_cc\_move (C function)@\spxentry{krb5\_cc\_move}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_move:c.krb5_cc_move}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_move}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{src}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{dst}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{src} \sphinxhyphen{} The credential cache to move the content from + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{dst} \sphinxhyphen{} The credential cache to move the content to + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; src is closed. + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes; src is still allocated. + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function reinitializes \sphinxstyleemphasis{dst} and populates it with the credentials and default principal of \sphinxstyleemphasis{src} ; then, if successful, destroys \sphinxstyleemphasis{src} . + + +\subsubsection{krb5\_cc\_next\_cred \sphinxhyphen{} Retrieve the next entry from the credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_next_cred:krb5-cc-next-cred-retrieve-the-next-entry-from-the-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_next_cred::doc}}\index{krb5\_cc\_next\_cred (C function)@\spxentry{krb5\_cc\_next\_cred}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_next_cred:c.krb5_cc_next_cred}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_next\_cred}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}, {\hyperref[\detokenize{appdev/refs/types/krb5_cc_cursor:c.krb5_cc_cursor}]{\sphinxcrossref{\DUrole{n}{krb5\_cc\_cursor}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cursor}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cursor} \sphinxhyphen{} Cursor + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Next credential cache entry + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function fills in \sphinxstyleemphasis{creds} with the next entry in \sphinxstyleemphasis{cache} and advances \sphinxstyleemphasis{cursor} . + +\sphinxAtStartPar +Use krb5\_free\_cred\_contents() to free \sphinxstyleemphasis{creds} when it is no longer needed. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_cc\_start\_seq\_get(), krb5\_end\_seq\_get() + + + + +\subsubsection{krb5\_cc\_remove\_cred \sphinxhyphen{} Remove credentials from a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_remove_cred:krb5-cc-remove-cred-remove-credentials-from-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_remove_cred::doc}}\index{krb5\_cc\_remove\_cred (C function)@\spxentry{krb5\_cc\_remove\_cred}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_remove_cred:c.krb5_cc_remove_cred}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_remove\_cred}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{flags}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Bitwise\sphinxhyphen{}ORed search flags + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Credentials to be matched + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +KRB5\_CC\_NOSUPP Not implemented for this cache type + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +No matches found; Data cannot be deleted; Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function accepts the same flag values as krb5\_cc\_retrieve\_cred(). + +\begin{sphinxadmonition}{warning}{Warning:} +\sphinxAtStartPar +This function is not implemented for some cache types. +\end{sphinxadmonition} + + +\subsubsection{krb5\_cc\_retrieve\_cred \sphinxhyphen{} Retrieve a specified credentials from a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_retrieve_cred:krb5-cc-retrieve-cred-retrieve-a-specified-credentials-from-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_retrieve_cred::doc}}\index{krb5\_cc\_retrieve\_cred (C function)@\spxentry{krb5\_cc\_retrieve\_cred}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_retrieve_cred:c.krb5_cc_retrieve_cred}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_retrieve\_cred}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{flags}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{mcreds}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Flags bit mask + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{mcreds} \sphinxhyphen{} Credentials to match + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Credentials matching the requested value + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function searches a credential cache for credentials matching \sphinxstyleemphasis{mcreds} and returns it if found. + +\sphinxAtStartPar +Valid values for \sphinxstyleemphasis{flags} are: +\begin{quote} +\begin{itemize} +\item {} +\sphinxAtStartPar +\#KRB5\_TC\_MATCH\_TIMES The requested lifetime must be at least as great as in \sphinxstyleemphasis{mcreds} . + +\item {} +\sphinxAtStartPar +\#KRB5\_TC\_MATCH\_IS\_SKEY The \sphinxstyleemphasis{is\_skey} field much match exactly. + +\item {} +\sphinxAtStartPar +\#KRB5\_TC\_MATCH\_FLAGS Flags set in \sphinxstyleemphasis{mcreds} must be set. + +\item {} +\sphinxAtStartPar +\#KRB5\_TC\_MATCH\_TIMES\_EXACT The requested lifetime must match exactly. + +\item {} +\sphinxAtStartPar +\#KRB5\_TC\_MATCH\_FLAGS\_EXACT Flags must match exactly. + +\item {} +\sphinxAtStartPar +\#KRB5\_TC\_MATCH\_AUTHDATA The authorization data must match. + +\item {} +\sphinxAtStartPar +\#KRB5\_TC\_MATCH\_SRV\_NAMEONLY Only the name portion of the principal name must match, not the realm. + +\item {} +\sphinxAtStartPar +\#KRB5\_TC\_MATCH\_2ND\_TKT The second tickets must match. + +\item {} +\sphinxAtStartPar +\#KRB5\_TC\_MATCH\_KTYPE The encryption key types must match. + +\item {} +\sphinxAtStartPar +\#KRB5\_TC\_SUPPORTED\_KTYPES Check all matching entries that have any supported encryption type and return the one with the encryption type listed earliest. + +\end{itemize} + +\sphinxAtStartPar +Use krb5\_free\_cred\_contents() to free \sphinxstyleemphasis{creds} when it is no longer needed. +\end{quote} + + +\subsubsection{krb5\_cc\_select \sphinxhyphen{} Select a credential cache to use with a server principal.} +\label{\detokenize{appdev/refs/api/krb5_cc_select:krb5-cc-select-select-a-credential-cache-to-use-with-a-server-principal}}\label{\detokenize{appdev/refs/api/krb5_cc_select::doc}}\index{krb5\_cc\_select (C function)@\spxentry{krb5\_cc\_select}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_select:c.krb5_cc_select}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_select}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{server}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cache\_out}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{princ\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server} \sphinxhyphen{} Server principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{cache\_out} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{princ\_out} \sphinxhyphen{} Client principal + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +If an appropriate cache is found, 0 is returned, cache\_out is set to the selected cache, and princ\_out is set to the default principal of that cache. + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Select a cache within the collection containing credentials most appropriate for use with \sphinxstyleemphasis{server} , according to configured rules and heuristics. + +\sphinxAtStartPar +Use krb5\_cc\_close() to release \sphinxstyleemphasis{cache\_out} when it is no longer needed. Use krb5\_free\_principal() to release \sphinxstyleemphasis{princ\_out} when it is no longer needed. Note that \sphinxstyleemphasis{princ\_out} is set in some error conditions. + +\sphinxAtStartPar +If the appropriate client principal can be authoritatively determined but the cache collection contains no credentials for that principal, then KRB5\_CC\_NOTFOUND is returned, \sphinxstyleemphasis{cache\_out} is set to NULL, and \sphinxstyleemphasis{princ\_out} is set to the appropriate client principal. + +\sphinxAtStartPar +If no configured mechanism can determine the appropriate cache or principal, KRB5\_CC\_NOTFOUND is returned and \sphinxstyleemphasis{cache\_out} and \sphinxstyleemphasis{princ\_out} are set to NULL. + +\sphinxAtStartPar +Any other error code indicates a fatal error in the processing of a cache selection mechanism. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.10 +\end{sphinxadmonition} + + +\subsubsection{krb5\_cc\_set\_config \sphinxhyphen{} Store a configuration value in a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_set_config:krb5-cc-set-config-store-a-configuration-value-in-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_set_config::doc}}\index{krb5\_cc\_set\_config (C function)@\spxentry{krb5\_cc\_set\_config}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_set_config:c.krb5_cc_set_config}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_set\_config}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{id}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{id} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Configuration for a specific principal; if NULL, global for the whole cache + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Name of config variable + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} Data to store, or NULL to remove + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\begin{sphinxadmonition}{warning}{Warning:} +\sphinxAtStartPar +Before version 1.10 \sphinxstyleemphasis{data} was assumed to be always non\sphinxhyphen{}null. +\end{sphinxadmonition} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +Existing configuration under the same key is over\sphinxhyphen{}written. +\end{sphinxadmonition} + + +\subsubsection{krb5\_cc\_set\_default\_name \sphinxhyphen{} Set the default credential cache name.} +\label{\detokenize{appdev/refs/api/krb5_cc_set_default_name:krb5-cc-set-default-name-set-the-default-credential-cache-name}}\label{\detokenize{appdev/refs/api/krb5_cc_set_default_name::doc}}\index{krb5\_cc\_set\_default\_name (C function)@\spxentry{krb5\_cc\_set\_default\_name}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_set_default_name:c.krb5_cc_set_default_name}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_set\_default\_name}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{name}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{name} \sphinxhyphen{} Default credential cache name or NULL + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +KV5M\_CONTEXT Bad magic number for \_krb5\_context structure + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Set the default credential cache name to \sphinxstyleemphasis{name} for future operations using \sphinxstyleemphasis{context} . If \sphinxstyleemphasis{name} is NULL, clear any previous application\sphinxhyphen{}set default name and forget any cached value of the default name for \sphinxstyleemphasis{context} . + +\sphinxAtStartPar +Calls to this function invalidate the result of any previous calls to krb5\_cc\_default\_name() using \sphinxstyleemphasis{context} . + + +\subsubsection{krb5\_cc\_set\_flags \sphinxhyphen{} Set options flags on a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_set_flags:krb5-cc-set-flags-set-options-flags-on-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_set_flags::doc}}\index{krb5\_cc\_set\_flags (C function)@\spxentry{krb5\_cc\_set\_flags}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_set_flags:c.krb5_cc_set_flags}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_set\_flags}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{flags}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Flag bit mask + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function resets \sphinxstyleemphasis{cache} flags to \sphinxstyleemphasis{flags} . + + +\subsubsection{krb5\_cc\_start\_seq\_get \sphinxhyphen{} Prepare to sequentially read every credential in a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_start_seq_get:krb5-cc-start-seq-get-prepare-to-sequentially-read-every-credential-in-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_start_seq_get::doc}}\index{krb5\_cc\_start\_seq\_get (C function)@\spxentry{krb5\_cc\_start\_seq\_get}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_start_seq_get:c.krb5_cc_start_seq_get}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_start\_seq\_get}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}, {\hyperref[\detokenize{appdev/refs/types/krb5_cc_cursor:c.krb5_cc_cursor}]{\sphinxcrossref{\DUrole{n}{krb5\_cc\_cursor}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cursor}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{cursor} \sphinxhyphen{} Cursor + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +krb5\_cc\_end\_seq\_get() must be called to complete the retrieve operation. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +If the cache represented by \sphinxstyleemphasis{cache} is modified between the time of the call to this function and the time of the final krb5\_cc\_end\_seq\_get(), these changes may not be reflected in the results of krb5\_cc\_next\_cred() calls. +\end{sphinxadmonition} + + +\subsubsection{krb5\_cc\_store\_cred \sphinxhyphen{} Store credentials in a credential cache.} +\label{\detokenize{appdev/refs/api/krb5_cc_store_cred:krb5-cc-store-cred-store-credentials-in-a-credential-cache}}\label{\detokenize{appdev/refs/api/krb5_cc_store_cred::doc}}\index{krb5\_cc\_store\_cred (C function)@\spxentry{krb5\_cc\_store\_cred}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_store_cred:c.krb5_cc_store_cred}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_store\_cred}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Credentials to be stored in cache + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Permission errors; storage failure errors; Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function stores \sphinxstyleemphasis{creds} into \sphinxstyleemphasis{cache} . If \sphinxstyleemphasis{creds\sphinxhyphen{}\textgreater{}server} and the server in the decoded ticket \sphinxstyleemphasis{creds\sphinxhyphen{}\textgreater{}ticket} differ, the credentials will be stored under both server principal names. + + +\subsubsection{krb5\_cc\_support\_switch \sphinxhyphen{} Determine whether a credential cache type supports switching.} +\label{\detokenize{appdev/refs/api/krb5_cc_support_switch:krb5-cc-support-switch-determine-whether-a-credential-cache-type-supports-switching}}\label{\detokenize{appdev/refs/api/krb5_cc_support_switch::doc}}\index{krb5\_cc\_support\_switch (C function)@\spxentry{krb5\_cc\_support\_switch}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_support_switch:c.krb5_cc_support_switch}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_support\_switch}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{type}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{type} \sphinxhyphen{} Credential cache type + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if type supports switching + +\item {} +\sphinxAtStartPar +FALSE if it does not or is not a valid credential cache type. + +\end{itemize} + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.10 +\end{sphinxadmonition} + + +\subsubsection{krb5\_cc\_switch \sphinxhyphen{} Make a credential cache the primary cache for its collection.} +\label{\detokenize{appdev/refs/api/krb5_cc_switch:krb5-cc-switch-make-a-credential-cache-the-primary-cache-for-its-collection}}\label{\detokenize{appdev/refs/api/krb5_cc_switch::doc}}\index{krb5\_cc\_switch (C function)@\spxentry{krb5\_cc\_switch}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_switch:c.krb5_cc_switch}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_switch}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{cache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cache} \sphinxhyphen{} Credential cache handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success, or the type of cache doesn’t support switching + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +If the type of \sphinxstyleemphasis{cache} supports it, set \sphinxstyleemphasis{cache} to be the primary credential cache for the collection it belongs to. + + +\subsubsection{krb5\_cccol\_cursor\_free \sphinxhyphen{} Free a credential cache collection cursor.} +\label{\detokenize{appdev/refs/api/krb5_cccol_cursor_free:krb5-cccol-cursor-free-free-a-credential-cache-collection-cursor}}\label{\detokenize{appdev/refs/api/krb5_cccol_cursor_free::doc}}\index{krb5\_cccol\_cursor\_free (C function)@\spxentry{krb5\_cccol\_cursor\_free}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cccol_cursor_free:c.krb5_cccol_cursor_free}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cccol\_cursor\_free}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cccol_cursor:c.krb5_cccol_cursor}]{\sphinxcrossref{\DUrole{n}{krb5\_cccol\_cursor}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cursor}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cursor} \sphinxhyphen{} Cursor + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_cccol\_cursor\_new(), krb5\_cccol\_cursor\_next() + + + + +\subsubsection{krb5\_cccol\_cursor\_new \sphinxhyphen{} Prepare to iterate over the collection of known credential caches.} +\label{\detokenize{appdev/refs/api/krb5_cccol_cursor_new:krb5-cccol-cursor-new-prepare-to-iterate-over-the-collection-of-known-credential-caches}}\label{\detokenize{appdev/refs/api/krb5_cccol_cursor_new::doc}}\index{krb5\_cccol\_cursor\_new (C function)@\spxentry{krb5\_cccol\_cursor\_new}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cccol_cursor_new:c.krb5_cccol_cursor_new}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cccol\_cursor\_new}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cccol_cursor:c.krb5_cccol_cursor}]{\sphinxcrossref{\DUrole{n}{krb5\_cccol\_cursor}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cursor}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{cursor} \sphinxhyphen{} Cursor + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Get a new cache iteration \sphinxstyleemphasis{cursor} that will iterate over all known credential caches independent of type. + +\sphinxAtStartPar +Use krb5\_cccol\_cursor\_free() to release \sphinxstyleemphasis{cursor} when it is no longer needed. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_cccol\_cursor\_next() + + + + +\subsubsection{krb5\_cccol\_cursor\_next \sphinxhyphen{} Get the next credential cache in the collection.} +\label{\detokenize{appdev/refs/api/krb5_cccol_cursor_next:krb5-cccol-cursor-next-get-the-next-credential-cache-in-the-collection}}\label{\detokenize{appdev/refs/api/krb5_cccol_cursor_next::doc}}\index{krb5\_cccol\_cursor\_next (C function)@\spxentry{krb5\_cccol\_cursor\_next}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cccol_cursor_next:c.krb5_cccol_cursor_next}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cccol\_cursor\_next}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cccol_cursor:c.krb5_cccol_cursor}]{\sphinxcrossref{\DUrole{n}{krb5\_cccol\_cursor}}}}\DUrole{w}{ }\DUrole{n}{cursor}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ccache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cursor} \sphinxhyphen{} Cursor + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ccache} \sphinxhyphen{} Credential cache handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Use krb5\_cc\_close() to close \sphinxstyleemphasis{ccache} when it is no longer needed. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_cccol\_cursor\_new(), krb5\_cccol\_cursor\_free() + + + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +When all caches are iterated over and the end of the list is reached, \sphinxstyleemphasis{ccache} is set to NULL. +\end{sphinxadmonition} + + +\subsubsection{krb5\_cccol\_have\_content \sphinxhyphen{} Check if the credential cache collection contains any initialized caches.} +\label{\detokenize{appdev/refs/api/krb5_cccol_have_content:krb5-cccol-have-content-check-if-the-credential-cache-collection-contains-any-initialized-caches}}\label{\detokenize{appdev/refs/api/krb5_cccol_have_content::doc}}\index{krb5\_cccol\_have\_content (C function)@\spxentry{krb5\_cccol\_have\_content}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cccol_have_content:c.krb5_cccol_have_content}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cccol\_have\_content}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 At least one initialized cache is present in the collection + +\item {} +\sphinxAtStartPar +KRB5\_CC\_NOTFOUND The collection contains no caches + +\end{itemize} + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.11 +\end{sphinxadmonition} + + +\subsubsection{krb5\_clear\_error\_message \sphinxhyphen{} Clear the extended error message in a context.} +\label{\detokenize{appdev/refs/api/krb5_clear_error_message:krb5-clear-error-message-clear-the-extended-error-message-in-a-context}}\label{\detokenize{appdev/refs/api/krb5_clear_error_message::doc}}\index{krb5\_clear\_error\_message (C function)@\spxentry{krb5\_clear\_error\_message}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_clear_error_message:c.krb5_clear_error_message}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_clear\_error\_message}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\end{description}\end{quote} + +\sphinxAtStartPar +This function unsets the extended error message in a context, to ensure that it is not mistakenly applied to another occurrence of the same error code. + + +\subsubsection{krb5\_check\_clockskew \sphinxhyphen{} Check if a timestamp is within the allowed clock skew of the current time.} +\label{\detokenize{appdev/refs/api/krb5_check_clockskew:krb5-check-clockskew-check-if-a-timestamp-is-within-the-allowed-clock-skew-of-the-current-time}}\label{\detokenize{appdev/refs/api/krb5_check_clockskew::doc}}\index{krb5\_check\_clockskew (C function)@\spxentry{krb5\_check\_clockskew}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_check_clockskew:c.krb5_check_clockskew}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_check\_clockskew}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\DUrole{n}{date}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{date} \sphinxhyphen{} Timestamp to check + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +KRB5KRB\_AP\_ERR\_SKEW date is not within allowable clock skew + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function checks if \sphinxstyleemphasis{date} is close enough to the current time according to the configured allowable clock skew. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.10 +\end{sphinxadmonition} + + +\subsubsection{krb5\_copy\_addresses \sphinxhyphen{} Copy an array of addresses.} +\label{\detokenize{appdev/refs/api/krb5_copy_addresses:krb5-copy-addresses-copy-an-array-of-addresses}}\label{\detokenize{appdev/refs/api/krb5_copy_addresses::doc}}\index{krb5\_copy\_addresses (C function)@\spxentry{krb5\_copy\_addresses}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_copy_addresses:c.krb5_copy_addresses}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_copy\_addresses}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{inaddr}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{outaddr}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{inaddr} \sphinxhyphen{} Array of addresses to be copied + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{outaddr} \sphinxhyphen{} Copy of array of addresses + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a new address array containing a copy of \sphinxstyleemphasis{inaddr} . Use krb5\_free\_addresses() to free \sphinxstyleemphasis{outaddr} when it is no longer needed. + + +\subsubsection{krb5\_copy\_authdata \sphinxhyphen{} Copy an authorization data list.} +\label{\detokenize{appdev/refs/api/krb5_copy_authdata:krb5-copy-authdata-copy-an-authorization-data-list}}\label{\detokenize{appdev/refs/api/krb5_copy_authdata::doc}}\index{krb5\_copy\_authdata (C function)@\spxentry{krb5\_copy\_authdata}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_copy_authdata:c.krb5_copy_authdata}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_copy\_authdata}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_authdat}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in\_authdat} \sphinxhyphen{} List of \sphinxstyleemphasis{krb5\_authdata} structures + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{out} \sphinxhyphen{} New array of \sphinxstyleemphasis{krb5\_authdata} structures + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a new authorization data list containing a copy of \sphinxstyleemphasis{in\_authdat} , which must be null\sphinxhyphen{}terminated. Use krb5\_free\_authdata() to free \sphinxstyleemphasis{out} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The last array entry in \sphinxstyleemphasis{in\_authdat} must be a NULL pointer. +\end{sphinxadmonition} + + +\subsubsection{krb5\_copy\_authenticator \sphinxhyphen{} Copy a krb5\_authenticator structure.} +\label{\detokenize{appdev/refs/api/krb5_copy_authenticator:krb5-copy-authenticator-copy-a-krb5-authenticator-structure}}\label{\detokenize{appdev/refs/api/krb5_copy_authenticator::doc}}\index{krb5\_copy\_authenticator (C function)@\spxentry{krb5\_copy\_authenticator}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_copy_authenticator:c.krb5_copy_authenticator}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_copy\_authenticator}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}]{\sphinxcrossref{\DUrole{n}{krb5\_authenticator}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{authfrom}, {\hyperref[\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}]{\sphinxcrossref{\DUrole{n}{krb5\_authenticator}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{authto}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{authfrom} \sphinxhyphen{} krb5\_authenticator structure to be copied + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{authto} \sphinxhyphen{} Copy of krb5\_authenticator structure + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a new krb5\_authenticator structure with the content of \sphinxstyleemphasis{authfrom} . Use krb5\_free\_authenticator() to free \sphinxstyleemphasis{authto} when it is no longer needed. + + +\subsubsection{krb5\_copy\_checksum \sphinxhyphen{} Copy a krb5\_checksum structure.} +\label{\detokenize{appdev/refs/api/krb5_copy_checksum:krb5-copy-checksum-copy-a-krb5-checksum-structure}}\label{\detokenize{appdev/refs/api/krb5_copy_checksum::doc}}\index{krb5\_copy\_checksum (C function)@\spxentry{krb5\_copy\_checksum}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_copy_checksum:c.krb5_copy_checksum}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_copy\_checksum}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ckfrom}, {\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{ckto}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ckfrom} \sphinxhyphen{} Checksum to be copied + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ckto} \sphinxhyphen{} Copy of krb5\_checksum structure + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a new krb5\_checksum structure with the contents of \sphinxstyleemphasis{ckfrom} . Use krb5\_free\_checksum() to free \sphinxstyleemphasis{ckto} when it is no longer needed. + + +\subsubsection{krb5\_copy\_context \sphinxhyphen{} Copy a krb5\_context structure.} +\label{\detokenize{appdev/refs/api/krb5_copy_context:krb5-copy-context-copy-a-krb5-context-structure}}\label{\detokenize{appdev/refs/api/krb5_copy_context::doc}}\index{krb5\_copy\_context (C function)@\spxentry{krb5\_copy\_context}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_copy_context:c.krb5_copy_context}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_copy\_context}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{nctx\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{nctx\_out} \sphinxhyphen{} New context structure + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +The newly created context must be released by calling krb5\_free\_context() when it is no longer needed. + + +\subsubsection{krb5\_copy\_creds \sphinxhyphen{} Copy a krb5\_creds structure.} +\label{\detokenize{appdev/refs/api/krb5_copy_creds:krb5-copy-creds-copy-a-krb5-creds-structure}}\label{\detokenize{appdev/refs/api/krb5_copy_creds::doc}}\index{krb5\_copy\_creds (C function)@\spxentry{krb5\_copy\_creds}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_copy_creds:c.krb5_copy_creds}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_copy\_creds}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{incred}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{outcred}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{incred} \sphinxhyphen{} Credentials structure to be copied + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{outcred} \sphinxhyphen{} Copy of \sphinxstyleemphasis{incred} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a new credential with the contents of \sphinxstyleemphasis{incred} . Use krb5\_free\_creds() to free \sphinxstyleemphasis{outcred} when it is no longer needed. + + +\subsubsection{krb5\_copy\_data \sphinxhyphen{} Copy a krb5\_data object.} +\label{\detokenize{appdev/refs/api/krb5_copy_data:krb5-copy-data-copy-a-krb5-data-object}}\label{\detokenize{appdev/refs/api/krb5_copy_data::doc}}\index{krb5\_copy\_data (C function)@\spxentry{krb5\_copy\_data}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_copy_data:c.krb5_copy_data}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_copy\_data}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{indata}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{outdata}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{indata} \sphinxhyphen{} Data object to be copied + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{outdata} \sphinxhyphen{} Copy of \sphinxstyleemphasis{indata} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a new krb5\_data object with the contents of \sphinxstyleemphasis{indata} . Use krb5\_free\_data() to free \sphinxstyleemphasis{outdata} when it is no longer needed. + + +\subsubsection{krb5\_copy\_error\_message \sphinxhyphen{} Copy the most recent extended error message from one context to another.} +\label{\detokenize{appdev/refs/api/krb5_copy_error_message:krb5-copy-error-message-copy-the-most-recent-extended-error-message-from-one-context-to-another}}\label{\detokenize{appdev/refs/api/krb5_copy_error_message::doc}}\index{krb5\_copy\_error\_message (C function)@\spxentry{krb5\_copy\_error\_message}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_copy_error_message:c.krb5_copy_error_message}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_copy\_error\_message}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{dest\_ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{src\_ctx}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{dest\_ctx} \sphinxhyphen{} Library context to copy message to + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{src\_ctx} \sphinxhyphen{} Library context with current message + +\end{description}\end{quote} + + +\subsubsection{krb5\_copy\_keyblock \sphinxhyphen{} Copy a keyblock.} +\label{\detokenize{appdev/refs/api/krb5_copy_keyblock:krb5-copy-keyblock-copy-a-keyblock}}\label{\detokenize{appdev/refs/api/krb5_copy_keyblock::doc}}\index{krb5\_copy\_keyblock (C function)@\spxentry{krb5\_copy\_keyblock}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_copy_keyblock:c.krb5_copy_keyblock}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_copy\_keyblock}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{from}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{to}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{from} \sphinxhyphen{} Keyblock to be copied + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{to} \sphinxhyphen{} Copy of keyblock \sphinxstyleemphasis{from} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a new keyblock with the same contents as \sphinxstyleemphasis{from} . Use krb5\_free\_keyblock() to free \sphinxstyleemphasis{to} when it is no longer needed. + + +\subsubsection{krb5\_copy\_keyblock\_contents \sphinxhyphen{} Copy the contents of a keyblock.} +\label{\detokenize{appdev/refs/api/krb5_copy_keyblock_contents:krb5-copy-keyblock-contents-copy-the-contents-of-a-keyblock}}\label{\detokenize{appdev/refs/api/krb5_copy_keyblock_contents::doc}}\index{krb5\_copy\_keyblock\_contents (C function)@\spxentry{krb5\_copy\_keyblock\_contents}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_copy_keyblock_contents:c.krb5_copy_keyblock_contents}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_copy\_keyblock\_contents}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{from}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{to}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{from} \sphinxhyphen{} Key to be copied + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{to} \sphinxhyphen{} Output key + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function copies the contents of \sphinxstyleemphasis{from} to \sphinxstyleemphasis{to} . Use krb5\_free\_keyblock\_contents() to free \sphinxstyleemphasis{to} when it is no longer needed. + + +\subsubsection{krb5\_copy\_principal \sphinxhyphen{} Copy a principal.} +\label{\detokenize{appdev/refs/api/krb5_copy_principal:krb5-copy-principal-copy-a-principal}}\label{\detokenize{appdev/refs/api/krb5_copy_principal::doc}}\index{krb5\_copy\_principal (C function)@\spxentry{krb5\_copy\_principal}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_copy_principal:c.krb5_copy_principal}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_copy\_principal}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{inprinc}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{outprinc}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{inprinc} \sphinxhyphen{} Principal to be copied + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{outprinc} \sphinxhyphen{} Copy of \sphinxstyleemphasis{inprinc} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a new principal structure with the contents of \sphinxstyleemphasis{inprinc} . Use krb5\_free\_principal() to free \sphinxstyleemphasis{outprinc} when it is no longer needed. + + +\subsubsection{krb5\_copy\_ticket \sphinxhyphen{} Copy a krb5\_ticket structure.} +\label{\detokenize{appdev/refs/api/krb5_copy_ticket:krb5-copy-ticket-copy-a-krb5-ticket-structure}}\label{\detokenize{appdev/refs/api/krb5_copy_ticket::doc}}\index{krb5\_copy\_ticket (C function)@\spxentry{krb5\_copy\_ticket}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_copy_ticket:c.krb5_copy_ticket}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_copy\_ticket}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{from}, {\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{pto}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{from} \sphinxhyphen{} Ticket to be copied + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{pto} \sphinxhyphen{} Copy of ticket + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a new krb5\_ticket structure containing the contents of \sphinxstyleemphasis{from} . Use krb5\_free\_ticket() to free \sphinxstyleemphasis{pto} when it is no longer needed. + + +\subsubsection{krb5\_find\_authdata \sphinxhyphen{} Find authorization data elements.} +\label{\detokenize{appdev/refs/api/krb5_find_authdata:krb5-find-authdata-find-authorization-data-elements}}\label{\detokenize{appdev/refs/api/krb5_find_authdata::doc}}\index{krb5\_find\_authdata (C function)@\spxentry{krb5\_find\_authdata}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_find_authdata:c.krb5_find_authdata}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_find\_authdata}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ticket\_authdata}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ap\_req\_authdata}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdatatype:c.krb5_authdatatype}]{\sphinxcrossref{\DUrole{n}{krb5\_authdatatype}}}}\DUrole{w}{ }\DUrole{n}{ad\_type}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{results}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ticket\_authdata} \sphinxhyphen{} Authorization data list from ticket + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ap\_req\_authdata} \sphinxhyphen{} Authorization data list from AP request + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ad\_type} \sphinxhyphen{} Authorization data type to find + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{results} \sphinxhyphen{} List of matching entries + +\end{description}\end{quote} + +\sphinxAtStartPar +This function searches \sphinxstyleemphasis{ticket\_authdata} and \sphinxstyleemphasis{ap\_req\_authdata} for elements of type \sphinxstyleemphasis{ad\_type} . Either input list may be NULL, in which case it will not be searched; otherwise, the input lists must be terminated by NULL entries. This function will search inside AD\sphinxhyphen{}IF\sphinxhyphen{}RELEVANT containers if found in either list. Use krb5\_free\_authdata() to free \sphinxstyleemphasis{results} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.10 +\end{sphinxadmonition} + + +\subsubsection{krb5\_free\_addresses \sphinxhyphen{} Free the data stored in array of addresses.} +\label{\detokenize{appdev/refs/api/krb5_free_addresses:krb5-free-addresses-free-the-data-stored-in-array-of-addresses}}\label{\detokenize{appdev/refs/api/krb5_free_addresses::doc}}\index{krb5\_free\_addresses (C function)@\spxentry{krb5\_free\_addresses}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_addresses:c.krb5_free_addresses}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_addresses}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Array of addresses to be freed + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{val} and the array itself. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The last entry in the array must be a NULL pointer. +\end{sphinxadmonition} + + +\subsubsection{krb5\_free\_ap\_rep\_enc\_part \sphinxhyphen{} Free a krb5\_ap\_rep\_enc\_part structure.} +\label{\detokenize{appdev/refs/api/krb5_free_ap_rep_enc_part:krb5-free-ap-rep-enc-part-free-a-krb5-ap-rep-enc-part-structure}}\label{\detokenize{appdev/refs/api/krb5_free_ap_rep_enc_part::doc}}\index{krb5\_free\_ap\_rep\_enc\_part (C function)@\spxentry{krb5\_free\_ap\_rep\_enc\_part}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_ap_rep_enc_part:c.krb5_free_ap_rep_enc_part}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_ap\_rep\_enc\_part}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_rep\_enc\_part}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} AP\sphinxhyphen{}REP enc part to be freed + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{val} and the structure itself. + + +\subsubsection{krb5\_free\_authdata \sphinxhyphen{} Free the storage assigned to array of authentication data.} +\label{\detokenize{appdev/refs/api/krb5_free_authdata:krb5-free-authdata-free-the-storage-assigned-to-array-of-authentication-data}}\label{\detokenize{appdev/refs/api/krb5_free_authdata::doc}}\index{krb5\_free\_authdata (C function)@\spxentry{krb5\_free\_authdata}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_authdata:c.krb5_free_authdata}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_authdata}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Array of authentication data to be freed + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{val} and the array itself. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The last entry in the array must be a NULL pointer. +\end{sphinxadmonition} + + +\subsubsection{krb5\_free\_authenticator \sphinxhyphen{} Free a krb5\_authenticator structure.} +\label{\detokenize{appdev/refs/api/krb5_free_authenticator:krb5-free-authenticator-free-a-krb5-authenticator-structure}}\label{\detokenize{appdev/refs/api/krb5_free_authenticator::doc}}\index{krb5\_free\_authenticator (C function)@\spxentry{krb5\_free\_authenticator}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_authenticator:c.krb5_free_authenticator}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_authenticator}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}]{\sphinxcrossref{\DUrole{n}{krb5\_authenticator}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Authenticator structure to be freed + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{val} and the structure itself. + + +\subsubsection{krb5\_free\_cred\_contents \sphinxhyphen{} Free the contents of a krb5\_creds structure.} +\label{\detokenize{appdev/refs/api/krb5_free_cred_contents:krb5-free-cred-contents-free-the-contents-of-a-krb5-creds-structure}}\label{\detokenize{appdev/refs/api/krb5_free_cred_contents::doc}}\index{krb5\_free\_cred\_contents (C function)@\spxentry{krb5\_free\_cred\_contents}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_cred_contents:c.krb5_free_cred_contents}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_cred\_contents}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Credential structure to free contents of + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{val} , but not the structure itself. + + +\subsubsection{krb5\_free\_creds \sphinxhyphen{} Free a krb5\_creds structure.} +\label{\detokenize{appdev/refs/api/krb5_free_creds:krb5-free-creds-free-a-krb5-creds-structure}}\label{\detokenize{appdev/refs/api/krb5_free_creds::doc}}\index{krb5\_free\_creds (C function)@\spxentry{krb5\_free\_creds}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_creds:c.krb5_free_creds}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_creds}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Credential structure to be freed. + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{val} and the structure itself. + + +\subsubsection{krb5\_free\_data \sphinxhyphen{} Free a krb5\_data structure.} +\label{\detokenize{appdev/refs/api/krb5_free_data:krb5-free-data-free-a-krb5-data-structure}}\label{\detokenize{appdev/refs/api/krb5_free_data::doc}}\index{krb5\_free\_data (C function)@\spxentry{krb5\_free\_data}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_data:c.krb5_free_data}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_data}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Data structure to be freed + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{val} and the structure itself. + + +\subsubsection{krb5\_free\_data\_contents \sphinxhyphen{} Free the contents of a krb5\_data structure and zero the data field.} +\label{\detokenize{appdev/refs/api/krb5_free_data_contents:krb5-free-data-contents-free-the-contents-of-a-krb5-data-structure-and-zero-the-data-field}}\label{\detokenize{appdev/refs/api/krb5_free_data_contents::doc}}\index{krb5\_free\_data\_contents (C function)@\spxentry{krb5\_free\_data\_contents}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_data_contents:c.krb5_free_data_contents}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_data\_contents}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Data structure to free contents of + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{val} , but not the structure itself. It sets the structure’s data pointer to null and (beginning in release 1.19) sets its length to zero. + + +\subsubsection{krb5\_free\_default\_realm \sphinxhyphen{} Free a default realm string returned by krb5\_get\_default\_realm().} +\label{\detokenize{appdev/refs/api/krb5_free_default_realm:krb5-free-default-realm-free-a-default-realm-string-returned-by-krb5-get-default-realm}}\label{\detokenize{appdev/refs/api/krb5_free_default_realm::doc}}\index{krb5\_free\_default\_realm (C function)@\spxentry{krb5\_free\_default\_realm}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_default_realm:c.krb5_free_default_realm}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_default\_realm}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{lrealm}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{lrealm} \sphinxhyphen{} Realm to be freed + +\end{description}\end{quote} + + +\subsubsection{krb5\_free\_enctypes \sphinxhyphen{} Free an array of encryption types.} +\label{\detokenize{appdev/refs/api/krb5_free_enctypes:krb5-free-enctypes-free-an-array-of-encryption-types}}\label{\detokenize{appdev/refs/api/krb5_free_enctypes::doc}}\index{krb5\_free\_enctypes (C function)@\spxentry{krb5\_free\_enctypes}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_enctypes:c.krb5_free_enctypes}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_enctypes}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Array of enctypes to be freed + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.12 +\end{sphinxadmonition} + + +\subsubsection{krb5\_free\_error \sphinxhyphen{} Free an error allocated by krb5\_read\_error() or krb5\_sendauth().} +\label{\detokenize{appdev/refs/api/krb5_free_error:krb5-free-error-free-an-error-allocated-by-krb5-read-error-or-krb5-sendauth}}\label{\detokenize{appdev/refs/api/krb5_free_error::doc}}\index{krb5\_free\_error (C function)@\spxentry{krb5\_free\_error}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_error:c.krb5_free_error}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_error}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Error data structure to be freed + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{val} and the structure itself. + + +\subsubsection{krb5\_free\_host\_realm \sphinxhyphen{} Free the memory allocated by krb5\_get\_host\_realm().} +\label{\detokenize{appdev/refs/api/krb5_free_host_realm:krb5-free-host-realm-free-the-memory-allocated-by-krb5-get-host-realm}}\label{\detokenize{appdev/refs/api/krb5_free_host_realm::doc}}\index{krb5\_free\_host\_realm (C function)@\spxentry{krb5\_free\_host\_realm}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_host_realm:c.krb5_free_host_realm}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_host\_realm}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{realmlist}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{realmlist} \sphinxhyphen{} List of realm names to be released + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_free\_keyblock \sphinxhyphen{} Free a krb5\_keyblock structure.} +\label{\detokenize{appdev/refs/api/krb5_free_keyblock:krb5-free-keyblock-free-a-krb5-keyblock-structure}}\label{\detokenize{appdev/refs/api/krb5_free_keyblock::doc}}\index{krb5\_free\_keyblock (C function)@\spxentry{krb5\_free\_keyblock}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_keyblock:c.krb5_free_keyblock}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_keyblock}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Keyblock to be freed + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{val} and the structure itself. + + +\subsubsection{krb5\_free\_keyblock\_contents \sphinxhyphen{} Free the contents of a krb5\_keyblock structure.} +\label{\detokenize{appdev/refs/api/krb5_free_keyblock_contents:krb5-free-keyblock-contents-free-the-contents-of-a-krb5-keyblock-structure}}\label{\detokenize{appdev/refs/api/krb5_free_keyblock_contents::doc}}\index{krb5\_free\_keyblock\_contents (C function)@\spxentry{krb5\_free\_keyblock\_contents}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_keyblock_contents:c.krb5_free_keyblock_contents}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_keyblock\_contents}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Keyblock to be freed + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{key} , but not the structure itself. + + +\subsubsection{krb5\_free\_keytab\_entry\_contents \sphinxhyphen{} Free the contents of a key table entry.} +\label{\detokenize{appdev/refs/api/krb5_free_keytab_entry_contents:krb5-free-keytab-entry-contents-free-the-contents-of-a-key-table-entry}}\label{\detokenize{appdev/refs/api/krb5_free_keytab_entry_contents::doc}}\index{krb5\_free\_keytab\_entry\_contents (C function)@\spxentry{krb5\_free\_keytab\_entry\_contents}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_keytab_entry_contents:c.krb5_free_keytab_entry_contents}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_keytab\_entry\_contents}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab\_entry}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{entry}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{entry} \sphinxhyphen{} Key table entry whose contents are to be freed + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The pointer is not freed. +\end{sphinxadmonition} + + +\subsubsection{krb5\_free\_string \sphinxhyphen{} Free a string allocated by a krb5 function.} +\label{\detokenize{appdev/refs/api/krb5_free_string:krb5-free-string-free-a-string-allocated-by-a-krb5-function}}\label{\detokenize{appdev/refs/api/krb5_free_string::doc}}\index{krb5\_free\_string (C function)@\spxentry{krb5\_free\_string}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_string:c.krb5_free_string}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_string}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} String to be freed + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.10 +\end{sphinxadmonition} + + +\subsubsection{krb5\_free\_ticket \sphinxhyphen{} Free a ticket.} +\label{\detokenize{appdev/refs/api/krb5_free_ticket:krb5-free-ticket-free-a-ticket}}\label{\detokenize{appdev/refs/api/krb5_free_ticket::doc}}\index{krb5\_free\_ticket (C function)@\spxentry{krb5\_free\_ticket}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_ticket:c.krb5_free_ticket}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_ticket}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Ticket to be freed + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{val} and the structure itself. + + +\subsubsection{krb5\_free\_unparsed\_name \sphinxhyphen{} Free a string representation of a principal.} +\label{\detokenize{appdev/refs/api/krb5_free_unparsed_name:krb5-free-unparsed-name-free-a-string-representation-of-a-principal}}\label{\detokenize{appdev/refs/api/krb5_free_unparsed_name::doc}}\index{krb5\_free\_unparsed\_name (C function)@\spxentry{krb5\_free\_unparsed\_name}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_unparsed_name:c.krb5_free_unparsed_name}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_unparsed\_name}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Name string to be freed + +\end{description}\end{quote} + + +\subsubsection{krb5\_get\_etype\_info \sphinxhyphen{} Retrieve enctype, salt and s2kparams from KDC.} +\label{\detokenize{appdev/refs/api/krb5_get_etype_info:krb5-get-etype-info-retrieve-enctype-salt-and-s2kparams-from-kdc}}\label{\detokenize{appdev/refs/api/krb5_get_etype_info::doc}}\index{krb5\_get\_etype\_info (C function)@\spxentry{krb5\_get\_etype\_info}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_etype_info:c.krb5_get_etype_info}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_etype\_info}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{enctype\_out}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{salt\_out}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{s2kparams\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Principal whose information is requested + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{opt} \sphinxhyphen{} Initial credential options + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{enctype\_out} \sphinxhyphen{} The enctype chosen by KDC + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{salt\_out} \sphinxhyphen{} Salt returned from KDC + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{s2kparams\_out} \sphinxhyphen{} String\sphinxhyphen{}to\sphinxhyphen{}key parameters returned from KDC + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +A Kerberos error code + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Send an initial ticket request for \sphinxstyleemphasis{principal} and extract the encryption type, salt type, and string\sphinxhyphen{}to\sphinxhyphen{}key parameters from the KDC response. If the KDC provides no etype\sphinxhyphen{}info, set \sphinxstyleemphasis{enctype\_out} to \sphinxstylestrong{ENCTYPE\_NULL} and set \sphinxstyleemphasis{salt\_out} and \sphinxstyleemphasis{s2kparams\_out} to empty. If the KDC etype\sphinxhyphen{}info provides no salt, compute the default salt and place it in \sphinxstyleemphasis{salt\_out} . If the KDC etype\sphinxhyphen{}info provides no string\sphinxhyphen{}to\sphinxhyphen{}key parameters, set \sphinxstyleemphasis{s2kparams\_out} to empty. +\begin{quote} + +\sphinxAtStartPar +\sphinxstyleemphasis{opt} may be used to specify options which affect the initial request, such as request encryption types or a FAST armor cache (see krb5\_get\_init\_creds\_opt\_set\_etype\_list() and krb5\_get\_init\_creds\_opt\_set\_fast\_ccache\_name()). +\end{quote} + +\sphinxAtStartPar +Use krb5\_free\_data\_contents() to free \sphinxstyleemphasis{salt\_out} and \sphinxstyleemphasis{s2kparams\_out} when they are no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.17 +\end{sphinxadmonition} + + +\subsubsection{krb5\_get\_permitted\_enctypes \sphinxhyphen{} Return a list of encryption types permitted for session keys.} +\label{\detokenize{appdev/refs/api/krb5_get_permitted_enctypes:krb5-get-permitted-enctypes-return-a-list-of-encryption-types-permitted-for-session-keys}}\label{\detokenize{appdev/refs/api/krb5_get_permitted_enctypes::doc}}\index{krb5\_get\_permitted\_enctypes (C function)@\spxentry{krb5\_get\_permitted\_enctypes}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_permitted_enctypes:c.krb5_get_permitted_enctypes}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_permitted\_enctypes}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{ktypes}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ktypes} \sphinxhyphen{} Zero\sphinxhyphen{}terminated list of encryption types + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function returns the list of encryption types permitted for session keys within \sphinxstyleemphasis{context} , as determined by configuration or by a previous call to krb5\_set\_default\_tgs\_enctypes(). + +\sphinxAtStartPar +Use krb5\_free\_enctypes() to free \sphinxstyleemphasis{ktypes} when it is no longer needed. + + +\subsubsection{krb5\_get\_server\_rcache \sphinxhyphen{} Generate a replay cache object for server use and open it.} +\label{\detokenize{appdev/refs/api/krb5_get_server_rcache:krb5-get-server-rcache-generate-a-replay-cache-object-for-server-use-and-open-it}}\label{\detokenize{appdev/refs/api/krb5_get_server_rcache::doc}}\index{krb5\_get\_server\_rcache (C function)@\spxentry{krb5\_get\_server\_rcache}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_server_rcache:c.krb5_get_server_rcache}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_server\_rcache}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{piece}, {\hyperref[\detokenize{appdev/refs/types/krb5_rcache:c.krb5_rcache}]{\sphinxcrossref{\DUrole{n}{krb5\_rcache}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{rcptr}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{piece} \sphinxhyphen{} Unused (replay cache identifier) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{rcptr} \sphinxhyphen{} Handle to an open rcache + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a handle to the default replay cache. Use krb5\_rc\_close() to close \sphinxstyleemphasis{rcptr} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +Prior to release 1.18, this function creates a handle to a different replay cache for each unique value of \sphinxstyleemphasis{piece} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_get\_time\_offsets \sphinxhyphen{} Return the time offsets from the os context.} +\label{\detokenize{appdev/refs/api/krb5_get_time_offsets:krb5-get-time-offsets-return-the-time-offsets-from-the-os-context}}\label{\detokenize{appdev/refs/api/krb5_get_time_offsets::doc}}\index{krb5\_get\_time\_offsets (C function)@\spxentry{krb5\_get\_time\_offsets}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_time_offsets:c.krb5_get_time_offsets}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_time\_offsets}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{seconds}, {\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{microseconds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{seconds} \sphinxhyphen{} Time offset, seconds portion + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{microseconds} \sphinxhyphen{} Time offset, microseconds portion + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function returns the time offsets in \sphinxstyleemphasis{context} . + + +\subsubsection{krb5\_init\_context\_profile \sphinxhyphen{} Create a krb5 library context using a specified profile.} +\label{\detokenize{appdev/refs/api/krb5_init_context_profile:krb5-init-context-profile-create-a-krb5-library-context-using-a-specified-profile}}\label{\detokenize{appdev/refs/api/krb5_init_context_profile::doc}}\index{krb5\_init\_context\_profile (C function)@\spxentry{krb5\_init\_context\_profile}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_context_profile:c.krb5_init_context_profile}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_context\_profile}}}}{\DUrole{k}{struct}\DUrole{w}{ }\DUrole{n}{\_profile\_t}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{profile}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{flags}, {\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{context}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{profile} \sphinxhyphen{} Profile object (NULL to create default profile) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Context initialization flags + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\end{description}\end{quote} + +\sphinxAtStartPar +Create a context structure, optionally using a specified profile and initialization flags. If \sphinxstyleemphasis{profile} is NULL, the default profile will be created from config files. If \sphinxstyleemphasis{profile} is non\sphinxhyphen{}null, a copy of it will be made for the new context; the caller should still clean up its copy. Valid flag values are: +\begin{itemize} +\item {} +\sphinxAtStartPar +\#KRB5\_INIT\_CONTEXT\_SECURE Ignore environment variables + +\item {} +\sphinxAtStartPar +\#KRB5\_INIT\_CONTEXT\_KDC Use KDC configuration if creating profile + +\end{itemize} + + +\subsubsection{krb5\_init\_creds\_free \sphinxhyphen{} Free an initial credentials context.} +\label{\detokenize{appdev/refs/api/krb5_init_creds_free:krb5-init-creds-free-free-an-initial-credentials-context}}\label{\detokenize{appdev/refs/api/krb5_init_creds_free::doc}}\index{krb5\_init\_creds\_free (C function)@\spxentry{krb5\_init\_creds\_free}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_creds_free:c.krb5_init_creds_free}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_creds\_free}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_init_creds_context:c.krb5_init_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_init\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Initial credentials context + +\end{description}\end{quote} +\begin{quote} + +\sphinxAtStartPar +\sphinxstyleemphasis{context} must be the same as the one passed to krb5\_init\_creds\_init() for this initial credentials context. +\end{quote} + + +\subsubsection{krb5\_init\_creds\_get \sphinxhyphen{} Acquire credentials using an initial credentials context.} +\label{\detokenize{appdev/refs/api/krb5_init_creds_get:krb5-init-creds-get-acquire-credentials-using-an-initial-credentials-context}}\label{\detokenize{appdev/refs/api/krb5_init_creds_get::doc}}\index{krb5\_init\_creds\_get (C function)@\spxentry{krb5\_init\_creds\_get}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_creds_get:c.krb5_init_creds_get}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_creds\_get}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_init_creds_context:c.krb5_init_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_init\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Initial credentials context + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function synchronously obtains credentials using a context created by krb5\_init\_creds\_init(). On successful return, the credentials can be retrieved with krb5\_init\_creds\_get\_creds(). +\begin{quote} + +\sphinxAtStartPar +\sphinxstyleemphasis{context} must be the same as the one passed to krb5\_init\_creds\_init() for this initial credentials context. +\end{quote} + + +\subsubsection{krb5\_init\_creds\_get\_creds \sphinxhyphen{} Retrieve acquired credentials from an initial credentials context.} +\label{\detokenize{appdev/refs/api/krb5_init_creds_get_creds:krb5-init-creds-get-creds-retrieve-acquired-credentials-from-an-initial-credentials-context}}\label{\detokenize{appdev/refs/api/krb5_init_creds_get_creds::doc}}\index{krb5\_init\_creds\_get\_creds (C function)@\spxentry{krb5\_init\_creds\_get\_creds}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_creds_get_creds:c.krb5_init_creds_get_creds}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_creds\_get\_creds}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_init_creds_context:c.krb5_init_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_init\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Initial credentials context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Acquired credentials + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function copies the acquired initial credentials from \sphinxstyleemphasis{ctx} into \sphinxstyleemphasis{creds} , after the successful completion of krb5\_init\_creds\_get() or krb5\_init\_creds\_step(). Use krb5\_free\_cred\_contents() to free \sphinxstyleemphasis{creds} when it is no longer needed. + + +\subsubsection{krb5\_init\_creds\_get\_error \sphinxhyphen{} Get the last error from KDC from an initial credentials context.} +\label{\detokenize{appdev/refs/api/krb5_init_creds_get_error:krb5-init-creds-get-error-get-the-last-error-from-kdc-from-an-initial-credentials-context}}\label{\detokenize{appdev/refs/api/krb5_init_creds_get_error::doc}}\index{krb5\_init\_creds\_get\_error (C function)@\spxentry{krb5\_init\_creds\_get\_error}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_creds_get_error:c.krb5_init_creds_get_error}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_creds\_get\_error}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_init_creds_context:c.krb5_init_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_init\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{error}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Initial credentials context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{error} \sphinxhyphen{} Error from KDC, or NULL if none was received + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_init\_creds\_get\_times \sphinxhyphen{} Retrieve ticket times from an initial credentials context.} +\label{\detokenize{appdev/refs/api/krb5_init_creds_get_times:krb5-init-creds-get-times-retrieve-ticket-times-from-an-initial-credentials-context}}\label{\detokenize{appdev/refs/api/krb5_init_creds_get_times::doc}}\index{krb5\_init\_creds\_get\_times (C function)@\spxentry{krb5\_init\_creds\_get\_times}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_creds_get_times:c.krb5_init_creds_get_times}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_creds\_get\_times}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_init_creds_context:c.krb5_init_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_init\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket\_times}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{times}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Initial credentials context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{times} \sphinxhyphen{} Ticket times for acquired credentials + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +The initial credentials context must have completed obtaining credentials via either krb5\_init\_creds\_get() or krb5\_init\_creds\_step(). + + +\subsubsection{krb5\_init\_creds\_init \sphinxhyphen{} Create a context for acquiring initial credentials.} +\label{\detokenize{appdev/refs/api/krb5_init_creds_init:krb5-init-creds-init-create-a-context-for-acquiring-initial-credentials}}\label{\detokenize{appdev/refs/api/krb5_init_creds_init::doc}}\index{krb5\_init\_creds\_init (C function)@\spxentry{krb5\_init\_creds\_init}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_creds_init:c.krb5_init_creds_init}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_creds\_init}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{client}, {\hyperref[\detokenize{appdev/refs/types/krb5_prompter_fct:c.krb5_prompter_fct}]{\sphinxcrossref{\DUrole{n}{krb5\_prompter\_fct}}}}\DUrole{w}{ }\DUrole{n}{prompter}, \DUrole{kt}{void}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, {\hyperref[\detokenize{appdev/refs/types/krb5_deltat:c.krb5_deltat}]{\sphinxcrossref{\DUrole{n}{krb5\_deltat}}}}\DUrole{w}{ }\DUrole{n}{start\_time}, {\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{options}, {\hyperref[\detokenize{appdev/refs/types/krb5_init_creds_context:c.krb5_init_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_init\_creds\_context}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ctx}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{client} \sphinxhyphen{} Client principal to get initial creds for + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{prompter} \sphinxhyphen{} Prompter callback + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} Prompter callback argument + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{start\_time} \sphinxhyphen{} Time when credentials become valid (0 for now) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{options} \sphinxhyphen{} Options structure (NULL for default) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} New initial credentials context + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a new context for acquiring initial credentials. Use krb5\_init\_creds\_free() to free \sphinxstyleemphasis{ctx} when it is no longer needed. + +\sphinxAtStartPar +Any subsequent calls to krb5\_init\_creds\_step(), krb5\_init\_creds\_get(), or krb5\_init\_creds\_free() for this initial credentials context must use the same \sphinxstyleemphasis{context} argument as the one passed to this function. + + +\subsubsection{krb5\_init\_creds\_set\_keytab \sphinxhyphen{} Specify a keytab to use for acquiring initial credentials.} +\label{\detokenize{appdev/refs/api/krb5_init_creds_set_keytab:krb5-init-creds-set-keytab-specify-a-keytab-to-use-for-acquiring-initial-credentials}}\label{\detokenize{appdev/refs/api/krb5_init_creds_set_keytab::doc}}\index{krb5\_init\_creds\_set\_keytab (C function)@\spxentry{krb5\_init\_creds\_set\_keytab}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_creds_set_keytab:c.krb5_init_creds_set_keytab}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_creds\_set\_keytab}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_init_creds_context:c.krb5_init_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_init\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{keytab}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Initial credentials context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keytab} \sphinxhyphen{} Key table handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function supplies a keytab containing the client key for an initial credentials request. + + +\subsubsection{krb5\_init\_creds\_set\_password \sphinxhyphen{} Set a password for acquiring initial credentials.} +\label{\detokenize{appdev/refs/api/krb5_init_creds_set_password:krb5-init-creds-set-password-set-a-password-for-acquiring-initial-credentials}}\label{\detokenize{appdev/refs/api/krb5_init_creds_set_password::doc}}\index{krb5\_init\_creds\_set\_password (C function)@\spxentry{krb5\_init\_creds\_set\_password}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_creds_set_password:c.krb5_init_creds_set_password}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_creds\_set\_password}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_init_creds_context:c.krb5_init_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_init\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{password}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Initial credentials context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{password} \sphinxhyphen{} Password + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function supplies a password to be used to construct the client key for an initial credentials request. + + +\subsubsection{krb5\_init\_creds\_set\_service \sphinxhyphen{} Specify a service principal for acquiring initial credentials.} +\label{\detokenize{appdev/refs/api/krb5_init_creds_set_service:krb5-init-creds-set-service-specify-a-service-principal-for-acquiring-initial-credentials}}\label{\detokenize{appdev/refs/api/krb5_init_creds_set_service::doc}}\index{krb5\_init\_creds\_set\_service (C function)@\spxentry{krb5\_init\_creds\_set\_service}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_creds_set_service:c.krb5_init_creds_set_service}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_creds\_set\_service}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_init_creds_context:c.krb5_init_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_init\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{service}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Initial credentials context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{service} \sphinxhyphen{} Service principal string + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function supplies a service principal string to acquire initial credentials for instead of the default krbtgt service. \sphinxstyleemphasis{service} is parsed as a principal name; any realm part is ignored. + + +\subsubsection{krb5\_init\_creds\_step \sphinxhyphen{} Get the next KDC request for acquiring initial credentials.} +\label{\detokenize{appdev/refs/api/krb5_init_creds_step:krb5-init-creds-step-get-the-next-kdc-request-for-acquiring-initial-credentials}}\label{\detokenize{appdev/refs/api/krb5_init_creds_step::doc}}\index{krb5\_init\_creds\_step (C function)@\spxentry{krb5\_init\_creds\_step}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_creds_step:c.krb5_init_creds_step}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_creds\_step}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_init_creds_context:c.krb5_init_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_init\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{out}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{realm}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{flags}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Initial credentials context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in} \sphinxhyphen{} KDC response (empty on the first call) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{out} \sphinxhyphen{} Next KDC request + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{realm} \sphinxhyphen{} Realm for next KDC request + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Output flags + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function constructs the next KDC request in an initial credential exchange, allowing the caller to control the transport of KDC requests and replies. On the first call, \sphinxstyleemphasis{in} should be set to an empty buffer; on subsequent calls, it should be set to the KDC’s reply to the previous request. + +\sphinxAtStartPar +If more requests are needed, \sphinxstyleemphasis{flags} will be set to \#KRB5\_INIT\_CREDS\_STEP\_FLAG\_CONTINUE and the next request will be placed in \sphinxstyleemphasis{out} . If no more requests are needed, \sphinxstyleemphasis{flags} will not contain \#KRB5\_INIT\_CREDS\_STEP\_FLAG\_CONTINUE and \sphinxstyleemphasis{out} will be empty. + +\sphinxAtStartPar +If this function returns \sphinxstylestrong{KRB5KRB\_ERR\_RESPONSE\_TOO\_BIG} , the caller should transmit the next request using TCP rather than UDP. If this function returns any other error, the initial credential exchange has failed. +\begin{quote} + +\sphinxAtStartPar +\sphinxstyleemphasis{context} must be the same as the one passed to krb5\_init\_creds\_init() for this initial credentials context. +\end{quote} + + +\subsubsection{krb5\_init\_keyblock \sphinxhyphen{} Initialize an empty krb5\_keyblock .} +\label{\detokenize{appdev/refs/api/krb5_init_keyblock:krb5-init-keyblock-initialize-an-empty-krb5-keyblock}}\label{\detokenize{appdev/refs/api/krb5_init_keyblock::doc}}\index{krb5\_init\_keyblock (C function)@\spxentry{krb5\_init\_keyblock}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_keyblock:c.krb5_init_keyblock}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_keyblock}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{length}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{length} \sphinxhyphen{} Length of keyblock (or 0) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{out} \sphinxhyphen{} New keyblock structure + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Initialize a new keyblock and allocate storage for the contents of the key. It is legal to pass in a length of 0, in which case contents are left unallocated. Use krb5\_free\_keyblock() to free \sphinxstyleemphasis{out} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +If \sphinxstyleemphasis{length} is set to 0, contents are left unallocated. +\end{sphinxadmonition} + + +\subsubsection{krb5\_is\_referral\_realm \sphinxhyphen{} Check for a match with KRB5\_REFERRAL\_REALM.} +\label{\detokenize{appdev/refs/api/krb5_is_referral_realm:krb5-is-referral-realm-check-for-a-match-with-krb5-referral-realm}}\label{\detokenize{appdev/refs/api/krb5_is_referral_realm::doc}}\index{krb5\_is\_referral\_realm (C function)@\spxentry{krb5\_is\_referral\_realm}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_is_referral_realm:c.krb5_is_referral_realm}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_is\_referral\_realm}}}}{\DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{r}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{r} \sphinxhyphen{} Realm to check + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if r is zero\sphinxhyphen{}length, FALSE otherwise + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_kdc\_sign\_ticket \sphinxhyphen{} Sign a PAC, possibly including a ticket signature.} +\label{\detokenize{appdev/refs/api/krb5_kdc_sign_ticket:krb5-kdc-sign-ticket-sign-a-pac-possibly-including-a-ticket-signature}}\label{\detokenize{appdev/refs/api/krb5_kdc_sign_ticket::doc}}\index{krb5\_kdc\_sign\_ticket (C function)@\spxentry{krb5\_kdc\_sign\_ticket}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kdc_sign_ticket:c.krb5_kdc_sign_ticket}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kdc\_sign\_ticket}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_tkt\_part}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{enc\_tkt}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}]{\sphinxcrossref{\DUrole{n}{krb5\_pac}}}}\DUrole{w}{ }\DUrole{n}{pac}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{server\_princ}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{client\_princ}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{server}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{privsvr}, {\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\DUrole{n}{with\_realm}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enc\_tkt} \sphinxhyphen{} The ticket for the signature + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pac} \sphinxhyphen{} PAC handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server\_princ} \sphinxhyphen{} Canonical ticket server name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{client\_princ} \sphinxhyphen{} PAC\_CLIENT\_INFO principal (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server} \sphinxhyphen{} Key for server checksum + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{privsvr} \sphinxhyphen{} Key for KDC and ticket checksum + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{with\_realm} \sphinxhyphen{} If true, include the realm of \sphinxstyleemphasis{principal} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 on success, otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Sign \sphinxstyleemphasis{pac} using the keys \sphinxstyleemphasis{server} and \sphinxstyleemphasis{privsvr} . Include a ticket signature over \sphinxstyleemphasis{enc\_tkt} if \sphinxstyleemphasis{server\_princ} is not a TGS or kadmin/changepw principal name. Add the signed PAC’s encoding to the authorization data of \sphinxstyleemphasis{enc\_tkt} in the first slot, wrapped in an AD\sphinxhyphen{}IF\sphinxhyphen{}RELEVANT container. If \sphinxstyleemphasis{client\_princ} is non\sphinxhyphen{}null, add a PAC\_CLIENT\_INFO buffer, including the realm if \sphinxstyleemphasis{with\_realm} is true. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.20 +\end{sphinxadmonition} + + +\subsubsection{krb5\_kdc\_verify\_ticket \sphinxhyphen{} Verify a PAC, possibly including ticket signature.} +\label{\detokenize{appdev/refs/api/krb5_kdc_verify_ticket:krb5-kdc-verify-ticket-verify-a-pac-possibly-including-ticket-signature}}\label{\detokenize{appdev/refs/api/krb5_kdc_verify_ticket::doc}}\index{krb5\_kdc\_verify\_ticket (C function)@\spxentry{krb5\_kdc\_verify\_ticket}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kdc_verify_ticket:c.krb5_kdc_verify_ticket}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kdc\_verify\_ticket}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_tkt\_part}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{enc\_tkt}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{server\_princ}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{server}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{privsvr}, {\hyperref[\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}]{\sphinxcrossref{\DUrole{n}{krb5\_pac}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{pac\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enc\_tkt} \sphinxhyphen{} Ticket enc\sphinxhyphen{}part, possibly containing a PAC + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server\_princ} \sphinxhyphen{} Canonicalized name of ticket server + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server} \sphinxhyphen{} Key to validate server checksum (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{privsvr} \sphinxhyphen{} Key to validate KDC checksum (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{pac\_out} \sphinxhyphen{} Verified PAC (NULL if no PAC included) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +If a PAC is present in \sphinxstyleemphasis{enc\_tkt} , verify its signatures. If \sphinxstyleemphasis{privsvr} is not NULL and \sphinxstyleemphasis{server\_princ} is not a krbtgt or kadmin/changepw service, require a ticket signature over \sphinxstyleemphasis{enc\_tkt} in addition to the KDC signature. Place the verified PAC in \sphinxstyleemphasis{pac\_out} . If an invalid PAC signature is found, return an error matching the Windows KDC protocol code for that condition as closely as possible. + +\sphinxAtStartPar +If no PAC is present in \sphinxstyleemphasis{enc\_tkt} , set \sphinxstyleemphasis{pac\_out} to NULL and return successfully. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +This function does not validate the PAC\_CLIENT\_INFO buffer. If a specific value is expected, the caller can make a separate call to krb5\_pac\_verify\_ext() with a principal but no keys. +\end{sphinxadmonition} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.20 +\end{sphinxadmonition} + + +\subsubsection{krb5\_kt\_add\_entry \sphinxhyphen{} Add a new entry to a key table.} +\label{\detokenize{appdev/refs/api/krb5_kt_add_entry:krb5-kt-add-entry-add-a-new-entry-to-a-key-table}}\label{\detokenize{appdev/refs/api/krb5_kt_add_entry::doc}}\index{krb5\_kt\_add\_entry (C function)@\spxentry{krb5\_kt\_add\_entry}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_add_entry:c.krb5_kt_add_entry}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_add\_entry}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{id}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab\_entry}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{entry}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{id} \sphinxhyphen{} Key table handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{entry} \sphinxhyphen{} Entry to be added + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +ENOMEM Insufficient memory + +\item {} +\sphinxAtStartPar +KRB5\_KT\_NOWRITE Key table is not writeable + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_kt\_end\_seq\_get \sphinxhyphen{} Release a keytab cursor.} +\label{\detokenize{appdev/refs/api/krb5_kt_end_seq_get:krb5-kt-end-seq-get-release-a-keytab-cursor}}\label{\detokenize{appdev/refs/api/krb5_kt_end_seq_get::doc}}\index{krb5\_kt\_end\_seq\_get (C function)@\spxentry{krb5\_kt\_end\_seq\_get}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_end_seq_get:c.krb5_kt_end_seq_get}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_end\_seq\_get}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{keytab}, {\hyperref[\detokenize{appdev/refs/types/krb5_kt_cursor:c.krb5_kt_cursor}]{\sphinxcrossref{\DUrole{n}{krb5\_kt\_cursor}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cursor}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keytab} \sphinxhyphen{} Key table handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{cursor} \sphinxhyphen{} Cursor + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function should be called to release the cursor created by krb5\_kt\_start\_seq\_get(). + + +\subsubsection{krb5\_kt\_get\_entry \sphinxhyphen{} Get an entry from a key table.} +\label{\detokenize{appdev/refs/api/krb5_kt_get_entry:krb5-kt-get-entry-get-an-entry-from-a-key-table}}\label{\detokenize{appdev/refs/api/krb5_kt_get_entry::doc}}\index{krb5\_kt\_get\_entry (C function)@\spxentry{krb5\_kt\_get\_entry}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_get_entry:c.krb5_kt_get_entry}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_get\_entry}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{keytab}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, {\hyperref[\detokenize{appdev/refs/types/krb5_kvno:c.krb5_kvno}]{\sphinxcrossref{\DUrole{n}{krb5\_kvno}}}}\DUrole{w}{ }\DUrole{n}{vno}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab\_entry}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{entry}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keytab} \sphinxhyphen{} Key table handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Principal name + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{vno} \sphinxhyphen{} Key version number (0 for highest available) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type (0 zero for any enctype) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{entry} \sphinxhyphen{} Returned entry from key table + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +Kerberos error codes on failure + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Retrieve an entry from a key table which matches the \sphinxstyleemphasis{keytab} , \sphinxstyleemphasis{principal} , \sphinxstyleemphasis{vno} , and \sphinxstyleemphasis{enctype} . If \sphinxstyleemphasis{vno} is zero, retrieve the highest\sphinxhyphen{}numbered kvno matching the other fields. If \sphinxstyleemphasis{enctype} is 0, match any enctype. + +\sphinxAtStartPar +Use krb5\_free\_keytab\_entry\_contents() to free \sphinxstyleemphasis{entry} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +If \sphinxstyleemphasis{vno} is zero, the function retrieves the highest\sphinxhyphen{}numbered\sphinxhyphen{}kvno entry that matches the specified principal. +\end{sphinxadmonition} + + +\subsubsection{krb5\_kt\_have\_content \sphinxhyphen{} Check if a keytab exists and contains entries.} +\label{\detokenize{appdev/refs/api/krb5_kt_have_content:krb5-kt-have-content-check-if-a-keytab-exists-and-contains-entries}}\label{\detokenize{appdev/refs/api/krb5_kt_have_content::doc}}\index{krb5\_kt\_have\_content (C function)@\spxentry{krb5\_kt\_have\_content}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_have_content:c.krb5_kt_have_content}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_have\_content}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{keytab}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keytab} \sphinxhyphen{} Key table handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Keytab exists and contains entries + +\item {} +\sphinxAtStartPar +KRB5\_KT\_NOTFOUND Keytab does not contain entries + +\end{itemize} + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.11 +\end{sphinxadmonition} + + +\subsubsection{krb5\_kt\_next\_entry \sphinxhyphen{} Retrieve the next entry from the key table.} +\label{\detokenize{appdev/refs/api/krb5_kt_next_entry:krb5-kt-next-entry-retrieve-the-next-entry-from-the-key-table}}\label{\detokenize{appdev/refs/api/krb5_kt_next_entry::doc}}\index{krb5\_kt\_next\_entry (C function)@\spxentry{krb5\_kt\_next\_entry}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_next_entry:c.krb5_kt_next_entry}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_next\_entry}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{keytab}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab\_entry}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{entry}, {\hyperref[\detokenize{appdev/refs/types/krb5_kt_cursor:c.krb5_kt_cursor}]{\sphinxcrossref{\DUrole{n}{krb5\_kt\_cursor}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cursor}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keytab} \sphinxhyphen{} Key table handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{entry} \sphinxhyphen{} Returned key table entry + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cursor} \sphinxhyphen{} Key table cursor + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +KRB5\_KT\_END \sphinxhyphen{} if the last entry was reached + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Return the next sequential entry in \sphinxstyleemphasis{keytab} and advance \sphinxstyleemphasis{cursor} . Callers must release the returned entry with krb5\_kt\_free\_entry(). + + +\subsubsection{krb5\_kt\_read\_service\_key \sphinxhyphen{} Retrieve a service key from a key table.} +\label{\detokenize{appdev/refs/api/krb5_kt_read_service_key:krb5-kt-read-service-key-retrieve-a-service-key-from-a-key-table}}\label{\detokenize{appdev/refs/api/krb5_kt_read_service_key::doc}}\index{krb5\_kt\_read\_service\_key (C function)@\spxentry{krb5\_kt\_read\_service\_key}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_read_service_key:c.krb5_kt_read_service_key}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_read\_service\_key}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_pointer:c.krb5_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_pointer}}}}\DUrole{w}{ }\DUrole{n}{keyprocarg}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, {\hyperref[\detokenize{appdev/refs/types/krb5_kvno:c.krb5_kvno}]{\sphinxcrossref{\DUrole{n}{krb5\_kvno}}}}\DUrole{w}{ }\DUrole{n}{vno}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keyprocarg} \sphinxhyphen{} Name of a key table (NULL to use default name) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Service principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{vno} \sphinxhyphen{} Key version number (0 for highest available) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type (0 for any type) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{key} \sphinxhyphen{} Service key from key table + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error code if not found or keyprocarg is invalid. + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Open and search the specified key table for the entry identified by \sphinxstyleemphasis{principal} , \sphinxstyleemphasis{enctype} , and \sphinxstyleemphasis{vno} . If no key is found, return an error code. + +\sphinxAtStartPar +The default key table is used, unless \sphinxstyleemphasis{keyprocarg} is non\sphinxhyphen{}null. \sphinxstyleemphasis{keyprocarg} designates a specific key table. + +\sphinxAtStartPar +Use krb5\_free\_keyblock() to free \sphinxstyleemphasis{key} when it is no longer needed. + + +\subsubsection{krb5\_kt\_remove\_entry \sphinxhyphen{} Remove an entry from a key table.} +\label{\detokenize{appdev/refs/api/krb5_kt_remove_entry:krb5-kt-remove-entry-remove-an-entry-from-a-key-table}}\label{\detokenize{appdev/refs/api/krb5_kt_remove_entry::doc}}\index{krb5\_kt\_remove\_entry (C function)@\spxentry{krb5\_kt\_remove\_entry}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_remove_entry:c.krb5_kt_remove_entry}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_remove\_entry}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{id}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab\_entry}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{entry}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{id} \sphinxhyphen{} Key table handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{entry} \sphinxhyphen{} Entry to remove from key table + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +KRB5\_KT\_NOWRITE Key table is not writable + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_kt\_start\_seq\_get \sphinxhyphen{} Start a sequential retrieval of key table entries.} +\label{\detokenize{appdev/refs/api/krb5_kt_start_seq_get:krb5-kt-start-seq-get-start-a-sequential-retrieval-of-key-table-entries}}\label{\detokenize{appdev/refs/api/krb5_kt_start_seq_get::doc}}\index{krb5\_kt\_start\_seq\_get (C function)@\spxentry{krb5\_kt\_start\_seq\_get}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_start_seq_get:c.krb5_kt_start_seq_get}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_start\_seq\_get}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{keytab}, {\hyperref[\detokenize{appdev/refs/types/krb5_kt_cursor:c.krb5_kt_cursor}]{\sphinxcrossref{\DUrole{n}{krb5\_kt\_cursor}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cursor}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keytab} \sphinxhyphen{} Key table handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{cursor} \sphinxhyphen{} Cursor + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Prepare to read sequentially every key in the specified key table. Use krb5\_kt\_end\_seq\_get() to release the cursor when it is no longer needed. + + +\subsubsection{krb5\_make\_authdata\_kdc\_issued \sphinxhyphen{} Encode and sign AD\sphinxhyphen{}KDCIssued authorization data.} +\label{\detokenize{appdev/refs/api/krb5_make_authdata_kdc_issued:krb5-make-authdata-kdc-issued-encode-and-sign-ad-kdcissued-authorization-data}}\label{\detokenize{appdev/refs/api/krb5_make_authdata_kdc_issued::doc}}\index{krb5\_make\_authdata\_kdc\_issued (C function)@\spxentry{krb5\_make\_authdata\_kdc\_issued}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_make_authdata_kdc_issued:c.krb5_make_authdata_kdc_issued}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_make\_authdata\_kdc\_issued}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{issuer}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{authdata}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{ad\_kdcissued}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Session key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{issuer} \sphinxhyphen{} The name of the issuing principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{authdata} \sphinxhyphen{} List of authorization data to be signed + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ad\_kdcissued} \sphinxhyphen{} List containing AD\sphinxhyphen{}KDCIssued authdata + +\end{description}\end{quote} + +\sphinxAtStartPar +This function wraps a list of authorization data entries \sphinxstyleemphasis{authdata} in an AD\sphinxhyphen{}KDCIssued container (see RFC 4120 section 5.2.6.2) signed with \sphinxstyleemphasis{key} . The result is returned in \sphinxstyleemphasis{ad\_kdcissued} as a single\sphinxhyphen{}element list. + + +\subsubsection{krb5\_marshal\_credentials \sphinxhyphen{} Serialize a krb5\_creds object.} +\label{\detokenize{appdev/refs/api/krb5_marshal_credentials:krb5-marshal-credentials-serialize-a-krb5-creds-object}}\label{\detokenize{appdev/refs/api/krb5_marshal_credentials::doc}}\index{krb5\_marshal\_credentials (C function)@\spxentry{krb5\_marshal\_credentials}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_marshal_credentials:c.krb5_marshal_credentials}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_marshal\_credentials}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{data\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in\_creds} \sphinxhyphen{} The credentials object to serialize + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{data\_out} \sphinxhyphen{} The serialized credentials + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Serialize \sphinxstyleemphasis{creds} in the format used by the FILE ccache format (vesion 4) and KCM ccache protocol. + +\sphinxAtStartPar +Use krb5\_free\_data() to free \sphinxstyleemphasis{data\_out} when it is no longer needed. + + +\subsubsection{krb5\_merge\_authdata \sphinxhyphen{} Merge two authorization data lists into a new list.} +\label{\detokenize{appdev/refs/api/krb5_merge_authdata:krb5-merge-authdata-merge-two-authorization-data-lists-into-a-new-list}}\label{\detokenize{appdev/refs/api/krb5_merge_authdata::doc}}\index{krb5\_merge\_authdata (C function)@\spxentry{krb5\_merge\_authdata}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_merge_authdata:c.krb5_merge_authdata}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_merge\_authdata}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{inauthdat1}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{inauthdat2}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{outauthdat}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{inauthdat1} \sphinxhyphen{} First list of \sphinxstyleemphasis{krb5\_authdata} structures + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{inauthdat2} \sphinxhyphen{} Second list of \sphinxstyleemphasis{krb5\_authdata} structures + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{outauthdat} \sphinxhyphen{} Merged list of \sphinxstyleemphasis{krb5\_authdata} structures + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Merge two authdata arrays, such as the array from a ticket and authenticator. Use krb5\_free\_authdata() to free \sphinxstyleemphasis{outauthdat} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The last array entry in \sphinxstyleemphasis{inauthdat1} and \sphinxstyleemphasis{inauthdat2} must be a NULL pointer. +\end{sphinxadmonition} + + +\subsubsection{krb5\_mk\_1cred \sphinxhyphen{} Format a KRB\sphinxhyphen{}CRED message for a single set of credentials.} +\label{\detokenize{appdev/refs/api/krb5_mk_1cred:krb5-mk-1cred-format-a-krb-cred-message-for-a-single-set-of-credentials}}\label{\detokenize{appdev/refs/api/krb5_mk_1cred::doc}}\index{krb5\_mk\_1cred (C function)@\spxentry{krb5\_mk\_1cred}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_mk_1cred:c.krb5_mk_1cred}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_mk\_1cred}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{der\_out}, {\hyperref[\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data}]{\sphinxcrossref{\DUrole{n}{krb5\_replay\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{rdata\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Pointer to credentials + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{der\_out} \sphinxhyphen{} Encoded credentials + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{rdata\_out} \sphinxhyphen{} Replay cache data (NULL if not needed) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +ENOMEM Insufficient memory + +\item {} +\sphinxAtStartPar +KRB5\_RC\_REQUIRED Message replay detection requires rcache parameter + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This is a convenience function that calls krb5\_mk\_ncred() with a single set of credentials. + + +\subsubsection{krb5\_mk\_error \sphinxhyphen{} Format and encode a KRB\_ERROR message.} +\label{\detokenize{appdev/refs/api/krb5_mk_error:krb5-mk-error-format-and-encode-a-krb-error-message}}\label{\detokenize{appdev/refs/api/krb5_mk_error::doc}}\index{krb5\_mk\_error (C function)@\spxentry{krb5\_mk\_error}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_mk_error:c.krb5_mk_error}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_mk\_error}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{dec\_err}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{enc\_err}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{dec\_err} \sphinxhyphen{} Error structure to be encoded + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{enc\_err} \sphinxhyphen{} Encoded error structure + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates a \sphinxstylestrong{KRB\_ERROR} message in \sphinxstyleemphasis{enc\_err} . Use krb5\_free\_data\_contents() to free \sphinxstyleemphasis{enc\_err} when it is no longer needed. + + +\subsubsection{krb5\_mk\_ncred \sphinxhyphen{} Format a KRB\sphinxhyphen{}CRED message for an array of credentials.} +\label{\detokenize{appdev/refs/api/krb5_mk_ncred:krb5-mk-ncred-format-a-krb-cred-message-for-an-array-of-credentials}}\label{\detokenize{appdev/refs/api/krb5_mk_ncred::doc}}\index{krb5\_mk\_ncred (C function)@\spxentry{krb5\_mk\_ncred}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_mk_ncred:c.krb5_mk_ncred}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_mk\_ncred}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{der\_out}, {\hyperref[\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data}]{\sphinxcrossref{\DUrole{n}{krb5\_replay\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{rdata\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Null\sphinxhyphen{}terminated array of credentials + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{der\_out} \sphinxhyphen{} Encoded credentials + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{rdata\_out} \sphinxhyphen{} Replay cache information (NULL if not needed) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +ENOMEM Insufficient memory + +\item {} +\sphinxAtStartPar +KRB5\_RC\_REQUIRED Message replay detection requires rcache parameter + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function takes an array of credentials \sphinxstyleemphasis{creds} and formats a \sphinxstylestrong{KRB\sphinxhyphen{}CRED} message \sphinxstyleemphasis{der\_out} to pass to krb5\_rd\_cred(). + +\sphinxAtStartPar +The local and remote addresses in \sphinxstyleemphasis{auth\_context} are optional; if either is specified, they are used to form the sender and receiver addresses in the KRB\sphinxhyphen{}CRED message. + +\sphinxAtStartPar +If the \#KRB5\_AUTH\_CONTEXT\_DO\_TIME flag is set in \sphinxstyleemphasis{auth\_context} , an entry for the message is entered in an in\sphinxhyphen{}memory replay cache to detect if the message is reflected by an attacker. If \#KRB5\_AUTH\_CONTEXT\_DO\_TIME is not set, no replay cache is used. If \#KRB5\_AUTH\_CONTEXT\_RET\_TIME is set in \sphinxstyleemphasis{auth\_context} , the timestamp used for the KRB\sphinxhyphen{}CRED message is stored in \sphinxstyleemphasis{rdata\_out} . + +\sphinxAtStartPar +If either \#KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE or \#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE is set, the \sphinxstyleemphasis{auth\_context} local sequence number is included in the KRB\sphinxhyphen{}CRED message and then incremented. If \#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE is set, the sequence number used is stored in \sphinxstyleemphasis{rdata\_out} . + +\sphinxAtStartPar +Use krb5\_free\_data\_contents() to free \sphinxstyleemphasis{der\_out} when it is no longer needed. + +\sphinxAtStartPar +The message will be encrypted using the send subkey of \sphinxstyleemphasis{auth\_context} if it is present, or the session key otherwise. If neither key is present, the credentials will not be encrypted, and the message should only be sent over a secure channel. No replay cache entry is used in this case. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The \sphinxstyleemphasis{rdata\_out} argument is required if the \#KRB5\_AUTH\_CONTEXT\_RET\_TIME or \#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE flag is set in \sphinxstyleemphasis{auth\_context} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_mk\_priv \sphinxhyphen{} Format a KRB\sphinxhyphen{}PRIV message.} +\label{\detokenize{appdev/refs/api/krb5_mk_priv:krb5-mk-priv-format-a-krb-priv-message}}\label{\detokenize{appdev/refs/api/krb5_mk_priv::doc}}\index{krb5\_mk\_priv (C function)@\spxentry{krb5\_mk\_priv}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_mk_priv:c.krb5_mk_priv}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_mk\_priv}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{userdata}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{der\_out}, {\hyperref[\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data}]{\sphinxcrossref{\DUrole{n}{krb5\_replay\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{rdata\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{userdata} \sphinxhyphen{} User data for \sphinxstylestrong{KRB\sphinxhyphen{}PRIV} message + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{der\_out} \sphinxhyphen{} Formatted \sphinxstylestrong{KRB\sphinxhyphen{}PRIV} message + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{rdata\_out} \sphinxhyphen{} Replay data (NULL if not needed) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function is similar to krb5\_mk\_safe(), but the message is encrypted and integrity\sphinxhyphen{}protected, not just integrity\sphinxhyphen{}protected. + +\sphinxAtStartPar +The local address in \sphinxstyleemphasis{auth\_context} must be set, and is used to form the sender address used in the KRB\sphinxhyphen{}PRIV message. The remote address is optional; if specified, it will be used to form the receiver address used in the message. + +\sphinxAtStartPar +If the \#KRB5\_AUTH\_CONTEXT\_DO\_TIME flag is set in \sphinxstyleemphasis{auth\_context} , a timestamp is included in the KRB\sphinxhyphen{}PRIV message, and an entry for the message is entered in an in\sphinxhyphen{}memory replay cache to detect if the message is reflected by an attacker. If \#KRB5\_AUTH\_CONTEXT\_DO\_TIME is not set, no replay cache is used. If \#KRB5\_AUTH\_CONTEXT\_RET\_TIME is set in \sphinxstyleemphasis{auth\_context} , a timestamp is included in the KRB\sphinxhyphen{}PRIV message and is stored in \sphinxstyleemphasis{rdata\_out} . + +\sphinxAtStartPar +If either \#KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE or \#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE is set, the \sphinxstyleemphasis{auth\_context} local sequence number is included in the KRB\sphinxhyphen{}PRIV message and then incremented. If \#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE is set, the sequence number used is stored in \sphinxstyleemphasis{rdata\_out} . + +\sphinxAtStartPar +Use krb5\_free\_data\_contents() to free \sphinxstyleemphasis{der\_out} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The \sphinxstyleemphasis{rdata\_out} argument is required if the \#KRB5\_AUTH\_CONTEXT\_RET\_TIME or \#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE flag is set in \sphinxstyleemphasis{auth\_context} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_mk\_rep \sphinxhyphen{} Format and encrypt a KRB\_AP\_REP message.} +\label{\detokenize{appdev/refs/api/krb5_mk_rep:krb5-mk-rep-format-and-encrypt-a-krb-ap-rep-message}}\label{\detokenize{appdev/refs/api/krb5_mk_rep::doc}}\index{krb5\_mk\_rep (C function)@\spxentry{krb5\_mk\_rep}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_mk_rep:c.krb5_mk_rep}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_mk\_rep}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{outbuf}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{outbuf} \sphinxhyphen{} \sphinxstylestrong{AP\sphinxhyphen{}REP} message + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function fills in \sphinxstyleemphasis{outbuf} with an AP\sphinxhyphen{}REP message using information from \sphinxstyleemphasis{auth\_context} . + +\sphinxAtStartPar +If the flags in \sphinxstyleemphasis{auth\_context} indicate that a sequence number should be used (either \#KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE or \#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE) and the local sequence number in \sphinxstyleemphasis{auth\_context} is 0, a new number will be generated with krb5\_generate\_seq\_number(). + +\sphinxAtStartPar +Use krb5\_free\_data\_contents() to free \sphinxstyleemphasis{outbuf} when it is no longer needed. + + +\subsubsection{krb5\_mk\_rep\_dce \sphinxhyphen{} Format and encrypt a KRB\_AP\_REP message for DCE RPC.} +\label{\detokenize{appdev/refs/api/krb5_mk_rep_dce:krb5-mk-rep-dce-format-and-encrypt-a-krb-ap-rep-message-for-dce-rpc}}\label{\detokenize{appdev/refs/api/krb5_mk_rep_dce::doc}}\index{krb5\_mk\_rep\_dce (C function)@\spxentry{krb5\_mk\_rep\_dce}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_mk_rep_dce:c.krb5_mk_rep_dce}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_mk\_rep\_dce}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{outbuf}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{outbuf} \sphinxhyphen{} \sphinxstylestrong{AP\sphinxhyphen{}REP} message + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Use krb5\_free\_data\_contents() to free \sphinxstyleemphasis{outbuf} when it is no longer needed. + + +\subsubsection{krb5\_mk\_req \sphinxhyphen{} Create a KRB\_AP\_REQ message.} +\label{\detokenize{appdev/refs/api/krb5_mk_req:krb5-mk-req-create-a-krb-ap-req-message}}\label{\detokenize{appdev/refs/api/krb5_mk_req::doc}}\index{krb5\_mk\_req (C function)@\spxentry{krb5\_mk\_req}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_mk_req:c.krb5_mk_req}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_mk\_req}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{ap\_req\_options}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{service}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{hostname}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_data}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{outbuf}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Pre\sphinxhyphen{}existing or newly created auth context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ap\_req\_options} \sphinxhyphen{} Options (see AP\_OPTS macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{service} \sphinxhyphen{} Service name, or NULL to use \sphinxstylestrong{“host”} + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{hostname} \sphinxhyphen{} Host name, or NULL to use local hostname + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in\_data} \sphinxhyphen{} Application data to be checksummed in the authenticator, or NULL + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ccache} \sphinxhyphen{} Credential cache used to obtain credentials for the desired service. + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{outbuf} \sphinxhyphen{} \sphinxstylestrong{AP\sphinxhyphen{}REQ} message + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function is similar to krb5\_mk\_req\_extended() except that it uses a given \sphinxstyleemphasis{hostname} , \sphinxstyleemphasis{service} , and \sphinxstyleemphasis{ccache} to construct a service principal name and obtain credentials. + +\sphinxAtStartPar +Use krb5\_free\_data\_contents() to free \sphinxstyleemphasis{outbuf} when it is no longer needed. + + +\subsubsection{krb5\_mk\_req\_extended \sphinxhyphen{} Create a KRB\_AP\_REQ message using supplied credentials.} +\label{\detokenize{appdev/refs/api/krb5_mk_req_extended:krb5-mk-req-extended-create-a-krb-ap-req-message-using-supplied-credentials}}\label{\detokenize{appdev/refs/api/krb5_mk_req_extended::doc}}\index{krb5\_mk\_req\_extended (C function)@\spxentry{krb5\_mk\_req\_extended}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_mk_req_extended:c.krb5_mk_req_extended}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_mk\_req\_extended}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{ap\_req\_options}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_data}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{outbuf}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Pre\sphinxhyphen{}existing or newly created auth context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ap\_req\_options} \sphinxhyphen{} Options (see AP\_OPTS macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in\_data} \sphinxhyphen{} Application data to be checksummed in the authenticator, or NULL + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in\_creds} \sphinxhyphen{} Credentials for the service with valid ticket and key + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{outbuf} \sphinxhyphen{} \sphinxstylestrong{AP\sphinxhyphen{}REQ} message + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Valid \sphinxstyleemphasis{ap\_req\_options} are: +\begin{quote} +\begin{itemize} +\item {} +\sphinxAtStartPar +\#AP\_OPTS\_USE\_SESSION\_KEY \sphinxhyphen{} Use the session key when creating the request used for user to user authentication. + +\item {} +\sphinxAtStartPar +\#AP\_OPTS\_MUTUAL\_REQUIRED \sphinxhyphen{} Request a mutual authentication packet from the receiver. + +\item {} +\sphinxAtStartPar +\#AP\_OPTS\_USE\_SUBKEY \sphinxhyphen{} Generate a subsession key from the current session key obtained from the credentials. + +\end{itemize} + +\sphinxAtStartPar +This function creates a KRB\_AP\_REQ message using supplied credentials \sphinxstyleemphasis{in\_creds} . \sphinxstyleemphasis{auth\_context} may point to an existing auth context or to NULL, in which case a new one will be created. If \sphinxstyleemphasis{in\_data} is non\sphinxhyphen{}null, a checksum of it will be included in the authenticator contained in the KRB\_AP\_REQ message. Use krb5\_free\_data\_contents() to free \sphinxstyleemphasis{outbuf} when it is no longer needed. +\end{quote} + +\sphinxAtStartPar +On successful return, the authenticator is stored in \sphinxstyleemphasis{auth\_context} with the \sphinxstyleemphasis{client} and \sphinxstyleemphasis{checksum} fields nulled out. (This is to prevent pointer\sphinxhyphen{}sharing problems; the caller should not need these fields anyway, since the caller supplied them.) + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_mk\_req() + + + + +\subsubsection{krb5\_mk\_safe \sphinxhyphen{} Format a KRB\sphinxhyphen{}SAFE message.} +\label{\detokenize{appdev/refs/api/krb5_mk_safe:krb5-mk-safe-format-a-krb-safe-message}}\label{\detokenize{appdev/refs/api/krb5_mk_safe::doc}}\index{krb5\_mk\_safe (C function)@\spxentry{krb5\_mk\_safe}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_mk_safe:c.krb5_mk_safe}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_mk\_safe}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{userdata}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{der\_out}, {\hyperref[\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data}]{\sphinxcrossref{\DUrole{n}{krb5\_replay\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{rdata\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{userdata} \sphinxhyphen{} User data in the message + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{der\_out} \sphinxhyphen{} Formatted \sphinxstylestrong{KRB\sphinxhyphen{}SAFE} buffer + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{rdata\_out} \sphinxhyphen{} Replay data. Specify NULL if not needed + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function creates an integrity protected \sphinxstylestrong{KRB\sphinxhyphen{}SAFE} message using data supplied by the application. + +\sphinxAtStartPar +Fields in \sphinxstyleemphasis{auth\_context} specify the checksum type, the keyblock that can be used to seed the checksum, full addresses (host and port) for the sender and receiver, and KRB5\_AUTH\_CONTEXT flags. + +\sphinxAtStartPar +The local address in \sphinxstyleemphasis{auth\_context} must be set, and is used to form the sender address used in the KRB\sphinxhyphen{}SAFE message. The remote address is optional; if specified, it will be used to form the receiver address used in the message. + +\sphinxAtStartPar +If the \#KRB5\_AUTH\_CONTEXT\_DO\_TIME flag is set in \sphinxstyleemphasis{auth\_context} , a timestamp is included in the KRB\sphinxhyphen{}SAFE message, and an entry for the message is entered in an in\sphinxhyphen{}memory replay cache to detect if the message is reflected by an attacker. If \#KRB5\_AUTH\_CONTEXT\_DO\_TIME is not set, no replay cache is used. If \#KRB5\_AUTH\_CONTEXT\_RET\_TIME is set in \sphinxstyleemphasis{auth\_context} , a timestamp is included in the KRB\sphinxhyphen{}SAFE message and is stored in \sphinxstyleemphasis{rdata\_out} . + +\sphinxAtStartPar +If either \#KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE or \#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE is set, the \sphinxstyleemphasis{auth\_context} local sequence number is included in the KRB\sphinxhyphen{}SAFE message and then incremented. If \#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE is set, the sequence number used is stored in \sphinxstyleemphasis{rdata\_out} . + +\sphinxAtStartPar +Use krb5\_free\_data\_contents() to free \sphinxstyleemphasis{der\_out} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The \sphinxstyleemphasis{rdata\_out} argument is required if the \#KRB5\_AUTH\_CONTEXT\_RET\_TIME or \#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE flag is set in \sphinxstyleemphasis{auth\_context} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_os\_localaddr \sphinxhyphen{} Return all interface addresses for this host.} +\label{\detokenize{appdev/refs/api/krb5_os_localaddr:krb5-os-localaddr-return-all-interface-addresses-for-this-host}}\label{\detokenize{appdev/refs/api/krb5_os_localaddr::doc}}\index{krb5\_os\_localaddr (C function)@\spxentry{krb5\_os\_localaddr}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_os_localaddr:c.krb5_os_localaddr}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_os\_localaddr}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{addr}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{addr} \sphinxhyphen{} Array of krb5\_address pointers, ending with NULL + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Use krb5\_free\_addresses() to free \sphinxstyleemphasis{addr} when it is no longer needed. + + +\subsubsection{krb5\_pac\_add\_buffer \sphinxhyphen{} Add a buffer to a PAC handle.} +\label{\detokenize{appdev/refs/api/krb5_pac_add_buffer:krb5-pac-add-buffer-add-a-buffer-to-a-pac-handle}}\label{\detokenize{appdev/refs/api/krb5_pac_add_buffer::doc}}\index{krb5\_pac\_add\_buffer (C function)@\spxentry{krb5\_pac\_add\_buffer}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_pac_add_buffer:c.krb5_pac_add_buffer}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pac\_add\_buffer}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}]{\sphinxcrossref{\DUrole{n}{krb5\_pac}}}}\DUrole{w}{ }\DUrole{n}{pac}, {\hyperref[\detokenize{appdev/refs/types/krb5_ui_4:c.krb5_ui_4}]{\sphinxcrossref{\DUrole{n}{krb5\_ui\_4}}}}\DUrole{w}{ }\DUrole{n}{type}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pac} \sphinxhyphen{} PAC handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{type} \sphinxhyphen{} Buffer type + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} contents + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function adds a buffer of type \sphinxstyleemphasis{type} and contents \sphinxstyleemphasis{data} to \sphinxstyleemphasis{pac} if there isn’t already a buffer of this type present. + +\sphinxAtStartPar +The valid values of \sphinxstyleemphasis{type} is one of the following: +\begin{itemize} +\item {} +\sphinxAtStartPar +\#KRB5\_PAC\_LOGON\_INFO \sphinxhyphen{} Logon information + +\item {} +\sphinxAtStartPar +\#KRB5\_PAC\_CREDENTIALS\_INFO \sphinxhyphen{} Credentials information + +\item {} +\sphinxAtStartPar +\#KRB5\_PAC\_SERVER\_CHECKSUM \sphinxhyphen{} Server checksum + +\item {} +\sphinxAtStartPar +\#KRB5\_PAC\_PRIVSVR\_CHECKSUM \sphinxhyphen{} KDC checksum + +\item {} +\sphinxAtStartPar +\#KRB5\_PAC\_CLIENT\_INFO \sphinxhyphen{} Client name and ticket information + +\item {} +\sphinxAtStartPar +\#KRB5\_PAC\_DELEGATION\_INFO \sphinxhyphen{} Constrained delegation information + +\item {} +\sphinxAtStartPar +\#KRB5\_PAC\_UPN\_DNS\_INFO \sphinxhyphen{} User principal name and DNS information + +\end{itemize} + + +\subsubsection{krb5\_pac\_free \sphinxhyphen{} Free a PAC handle.} +\label{\detokenize{appdev/refs/api/krb5_pac_free:krb5-pac-free-free-a-pac-handle}}\label{\detokenize{appdev/refs/api/krb5_pac_free::doc}}\index{krb5\_pac\_free (C function)@\spxentry{krb5\_pac\_free}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_pac_free:c.krb5_pac_free}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pac\_free}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}]{\sphinxcrossref{\DUrole{n}{krb5\_pac}}}}\DUrole{w}{ }\DUrole{n}{pac}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pac} \sphinxhyphen{} PAC to be freed + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{pac} and the structure itself. + + +\subsubsection{krb5\_pac\_get\_buffer \sphinxhyphen{} Retrieve a buffer value from a PAC.} +\label{\detokenize{appdev/refs/api/krb5_pac_get_buffer:krb5-pac-get-buffer-retrieve-a-buffer-value-from-a-pac}}\label{\detokenize{appdev/refs/api/krb5_pac_get_buffer::doc}}\index{krb5\_pac\_get\_buffer (C function)@\spxentry{krb5\_pac\_get\_buffer}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_pac_get_buffer:c.krb5_pac_get_buffer}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pac\_get\_buffer}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}]{\sphinxcrossref{\DUrole{n}{krb5\_pac}}}}\DUrole{w}{ }\DUrole{n}{pac}, {\hyperref[\detokenize{appdev/refs/types/krb5_ui_4:c.krb5_ui_4}]{\sphinxcrossref{\DUrole{n}{krb5\_ui\_4}}}}\DUrole{w}{ }\DUrole{n}{type}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pac} \sphinxhyphen{} PAC handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{type} \sphinxhyphen{} Type of buffer to retrieve + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{data} \sphinxhyphen{} Buffer value + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Use krb5\_free\_data\_contents() to free \sphinxstyleemphasis{data} when it is no longer needed. + + +\subsubsection{krb5\_pac\_get\_types \sphinxhyphen{} Return an array of buffer types in a PAC handle.} +\label{\detokenize{appdev/refs/api/krb5_pac_get_types:krb5-pac-get-types-return-an-array-of-buffer-types-in-a-pac-handle}}\label{\detokenize{appdev/refs/api/krb5_pac_get_types::doc}}\index{krb5\_pac\_get\_types (C function)@\spxentry{krb5\_pac\_get\_types}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_pac_get_types:c.krb5_pac_get_types}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pac\_get\_types}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}]{\sphinxcrossref{\DUrole{n}{krb5\_pac}}}}\DUrole{w}{ }\DUrole{n}{pac}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{len}, {\hyperref[\detokenize{appdev/refs/types/krb5_ui_4:c.krb5_ui_4}]{\sphinxcrossref{\DUrole{n}{krb5\_ui\_4}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{types}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pac} \sphinxhyphen{} PAC handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{len} \sphinxhyphen{} Number of entries in \sphinxstyleemphasis{types} + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{types} \sphinxhyphen{} Array of buffer types + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_pac\_init \sphinxhyphen{} Create an empty Privilege Attribute Certificate (PAC) handle.} +\label{\detokenize{appdev/refs/api/krb5_pac_init:krb5-pac-init-create-an-empty-privilege-attribute-certificate-pac-handle}}\label{\detokenize{appdev/refs/api/krb5_pac_init::doc}}\index{krb5\_pac\_init (C function)@\spxentry{krb5\_pac\_init}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_pac_init:c.krb5_pac_init}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pac\_init}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}]{\sphinxcrossref{\DUrole{n}{krb5\_pac}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{pac}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{pac} \sphinxhyphen{} New PAC handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Use krb5\_pac\_free() to free \sphinxstyleemphasis{pac} when it is no longer needed. + + +\subsubsection{krb5\_pac\_parse \sphinxhyphen{} Unparse an encoded PAC into a new handle.} +\label{\detokenize{appdev/refs/api/krb5_pac_parse:krb5-pac-parse-unparse-an-encoded-pac-into-a-new-handle}}\label{\detokenize{appdev/refs/api/krb5_pac_parse::doc}}\index{krb5\_pac\_parse (C function)@\spxentry{krb5\_pac\_parse}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_pac_parse:c.krb5_pac_parse}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pac\_parse}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{void}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ptr}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{len}, {\hyperref[\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}]{\sphinxcrossref{\DUrole{n}{krb5\_pac}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{pac}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ptr} \sphinxhyphen{} PAC buffer + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{len} \sphinxhyphen{} Length of \sphinxstyleemphasis{ptr} + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{pac} \sphinxhyphen{} PAC handle + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Use krb5\_pac\_free() to free \sphinxstyleemphasis{pac} when it is no longer needed. + + +\subsubsection{krb5\_pac\_sign} +\label{\detokenize{appdev/refs/api/krb5_pac_sign:krb5-pac-sign}}\label{\detokenize{appdev/refs/api/krb5_pac_sign::doc}}\index{krb5\_pac\_sign (C function)@\spxentry{krb5\_pac\_sign}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_pac_sign:c.krb5_pac_sign}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pac\_sign}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}]{\sphinxcrossref{\DUrole{n}{krb5\_pac}}}}\DUrole{w}{ }\DUrole{n}{pac}, {\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\DUrole{n}{authtime}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{server\_key}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{privsvr\_key}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{pac} + +\sphinxAtStartPar +\sphinxstylestrong{authtime} + +\sphinxAtStartPar +\sphinxstylestrong{principal} + +\sphinxAtStartPar +\sphinxstylestrong{server\_key} + +\sphinxAtStartPar +\sphinxstylestrong{privsvr\_key} + +\sphinxAtStartPar +\sphinxstylestrong{data} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Use krb5\_kdc\_sign\_ticket() instead. + + +\subsubsection{krb5\_pac\_sign\_ext} +\label{\detokenize{appdev/refs/api/krb5_pac_sign_ext:krb5-pac-sign-ext}}\label{\detokenize{appdev/refs/api/krb5_pac_sign_ext::doc}}\index{krb5\_pac\_sign\_ext (C function)@\spxentry{krb5\_pac\_sign\_ext}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_pac_sign_ext:c.krb5_pac_sign_ext}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pac\_sign\_ext}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}]{\sphinxcrossref{\DUrole{n}{krb5\_pac}}}}\DUrole{w}{ }\DUrole{n}{pac}, {\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\DUrole{n}{authtime}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{server\_key}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{privsvr\_key}, {\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\DUrole{n}{with\_realm}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{pac} + +\sphinxAtStartPar +\sphinxstylestrong{authtime} + +\sphinxAtStartPar +\sphinxstylestrong{principal} + +\sphinxAtStartPar +\sphinxstylestrong{server\_key} + +\sphinxAtStartPar +\sphinxstylestrong{privsvr\_key} + +\sphinxAtStartPar +\sphinxstylestrong{with\_realm} + +\sphinxAtStartPar +\sphinxstylestrong{data} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Use krb5\_kdc\_sign\_ticket() instead. + + +\subsubsection{krb5\_pac\_verify \sphinxhyphen{} Verify a PAC.} +\label{\detokenize{appdev/refs/api/krb5_pac_verify:krb5-pac-verify-verify-a-pac}}\label{\detokenize{appdev/refs/api/krb5_pac_verify::doc}}\index{krb5\_pac\_verify (C function)@\spxentry{krb5\_pac\_verify}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_pac_verify:c.krb5_pac_verify}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pac\_verify}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}]{\sphinxcrossref{\DUrole{n}{krb5\_pac}}}}\DUrole{w}{ }\DUrole{n}{pac}, {\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\DUrole{n}{authtime}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{server}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{privsvr}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pac} \sphinxhyphen{} PAC handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{authtime} \sphinxhyphen{} Expected timestamp + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Expected principal name (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server} \sphinxhyphen{} Key to validate server checksum (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{privsvr} \sphinxhyphen{} Key to validate KDC checksum (or NULL) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function validates \sphinxstyleemphasis{pac} against the supplied \sphinxstyleemphasis{server} , \sphinxstyleemphasis{privsvr} , \sphinxstyleemphasis{principal} and \sphinxstyleemphasis{authtime} . If \sphinxstyleemphasis{principal} is NULL, the principal and authtime are not verified. If \sphinxstyleemphasis{server} or \sphinxstyleemphasis{privsvr} is NULL, the corresponding checksum is not verified. + +\sphinxAtStartPar +If successful, \sphinxstyleemphasis{pac} is marked as verified. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +A checksum mismatch can occur if the PAC was copied from a cross\sphinxhyphen{}realm TGT by an ignorant KDC; also macOS Server Open Directory (as of 10.6) generates PACs with no server checksum at all. One should consider not failing the whole authentication because of this reason, but, instead, treating the ticket as if it did not contain a PAC or marking the PAC information as non\sphinxhyphen{}verified. +\end{sphinxadmonition} + + +\subsubsection{krb5\_pac\_verify\_ext \sphinxhyphen{} Verify a PAC, possibly from a specified realm.} +\label{\detokenize{appdev/refs/api/krb5_pac_verify_ext:krb5-pac-verify-ext-verify-a-pac-possibly-from-a-specified-realm}}\label{\detokenize{appdev/refs/api/krb5_pac_verify_ext::doc}}\index{krb5\_pac\_verify\_ext (C function)@\spxentry{krb5\_pac\_verify\_ext}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_pac_verify_ext:c.krb5_pac_verify_ext}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pac\_verify\_ext}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}]{\sphinxcrossref{\DUrole{n}{krb5\_pac}}}}\DUrole{w}{ }\DUrole{n}{pac}, {\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\DUrole{n}{authtime}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{principal}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{server}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{privsvr}, {\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\DUrole{n}{with\_realm}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pac} \sphinxhyphen{} PAC handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{authtime} \sphinxhyphen{} Expected timestamp + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{principal} \sphinxhyphen{} Expected principal name (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server} \sphinxhyphen{} Key to validate server checksum (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{privsvr} \sphinxhyphen{} Key to validate KDC checksum (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{with\_realm} \sphinxhyphen{} If true, expect the realm of \sphinxstyleemphasis{principal} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function is similar to krb5\_pac\_verify(), but adds a parameter \sphinxstyleemphasis{with\_realm} . If \sphinxstyleemphasis{with\_realm} is true, the PAC\_CLIENT\_INFO field is expected to include the realm of \sphinxstyleemphasis{principal} as well as the name. This flag is necessary to verify PACs in cross\sphinxhyphen{}realm S4U2Self referral TGTs. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.17 +\end{sphinxadmonition} + + +\subsubsection{krb5\_pac\_get\_client\_info \sphinxhyphen{} Read client information from a PAC.} +\label{\detokenize{appdev/refs/api/krb5_pac_get_client_info:krb5-pac-get-client-info-read-client-information-from-a-pac}}\label{\detokenize{appdev/refs/api/krb5_pac_get_client_info::doc}}\index{krb5\_pac\_get\_client\_info (C function)@\spxentry{krb5\_pac\_get\_client\_info}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_pac_get_client_info:c.krb5_pac_get_client_info}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pac\_get\_client\_info}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}]{\sphinxcrossref{\DUrole{n}{krb5\_pac}}}}\DUrole{w}{ }\DUrole{n}{pac}, {\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{authtime\_out}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{princname\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pac} \sphinxhyphen{} PAC handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{authtime\_out} \sphinxhyphen{} Authentication timestamp (NULL if not needed) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{princname\_out} \sphinxhyphen{} Client account name + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 on success, ENOENT if no PAC\_CLIENT\_INFO buffer is present in pac , ERANGE if the buffer contains invalid lengths. + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Read the PAC\_CLIENT\_INFO buffer in \sphinxstyleemphasis{pac} . Place the client account name as a string in \sphinxstyleemphasis{princname\_out} . If \sphinxstyleemphasis{authtime\_out} is not NULL, place the initial authentication timestamp in \sphinxstyleemphasis{authtime\_out} . + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.18 +\end{sphinxadmonition} + + +\subsubsection{krb5\_prepend\_error\_message \sphinxhyphen{} Add a prefix to the message for an error code.} +\label{\detokenize{appdev/refs/api/krb5_prepend_error_message:krb5-prepend-error-message-add-a-prefix-to-the-message-for-an-error-code}}\label{\detokenize{appdev/refs/api/krb5_prepend_error_message::doc}}\index{krb5\_prepend\_error\_message (C function)@\spxentry{krb5\_prepend\_error\_message}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_prepend_error_message:c.krb5_prepend_error_message}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_prepend\_error\_message}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\DUrole{n}{code}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{fmt}, \DUrole{p}{...}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{code} \sphinxhyphen{} Error code + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{fmt} \sphinxhyphen{} Format string for error message prefix + +\end{description}\end{quote} + +\sphinxAtStartPar +Format a message and prepend it to the current message for \sphinxstyleemphasis{code} . The prefix will be separated from the old message with a colon and space. + + +\subsubsection{krb5\_principal2salt \sphinxhyphen{} Convert a principal name into the default salt for that principal.} +\label{\detokenize{appdev/refs/api/krb5_principal2salt:krb5-principal2salt-convert-a-principal-name-into-the-default-salt-for-that-principal}}\label{\detokenize{appdev/refs/api/krb5_principal2salt::doc}}\index{krb5\_principal2salt (C function)@\spxentry{krb5\_principal2salt}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_principal2salt:c.krb5_principal2salt}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_principal2salt}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{pr}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ret}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pr} \sphinxhyphen{} Principal name + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ret} \sphinxhyphen{} Default salt for \sphinxstyleemphasis{pr} to be filled in + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_rd\_cred \sphinxhyphen{} Read and validate a KRB\sphinxhyphen{}CRED message.} +\label{\detokenize{appdev/refs/api/krb5_rd_cred:krb5-rd-cred-read-and-validate-a-krb-cred-message}}\label{\detokenize{appdev/refs/api/krb5_rd_cred::doc}}\index{krb5\_rd\_cred (C function)@\spxentry{krb5\_rd\_cred}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_rd_cred:c.krb5_rd_cred}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_rd\_cred}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creddata}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{creds\_out}, {\hyperref[\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data}]{\sphinxcrossref{\DUrole{n}{krb5\_replay\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{rdata\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{creddata} \sphinxhyphen{} \sphinxstylestrong{KRB\sphinxhyphen{}CRED} message + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{creds\_out} \sphinxhyphen{} Null\sphinxhyphen{}terminated array of forwarded credentials + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{rdata\_out} \sphinxhyphen{} Replay data (NULL if not needed) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} +\begin{quote} + +\sphinxAtStartPar +\sphinxstyleemphasis{creddata} will be decrypted using the receiving subkey if it is present in \sphinxstyleemphasis{auth\_context} , or the session key if the receiving subkey is not present or fails to decrypt the message. +\end{quote} + +\sphinxAtStartPar +Use krb5\_free\_tgt\_creds() to free \sphinxstyleemphasis{creds\_out} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The \sphinxstyleemphasis{rdata\_out} argument is required if the \#KRB5\_AUTH\_CONTEXT\_RET\_TIME or \#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE flag is set in \sphinxstyleemphasis{auth\_context} .\textasciigrave{} +\end{sphinxadmonition} + + +\subsubsection{krb5\_rd\_error \sphinxhyphen{} Decode a KRB\sphinxhyphen{}ERROR message.} +\label{\detokenize{appdev/refs/api/krb5_rd_error:krb5-rd-error-decode-a-krb-error-message}}\label{\detokenize{appdev/refs/api/krb5_rd_error::doc}}\index{krb5\_rd\_error (C function)@\spxentry{krb5\_rd\_error}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_rd_error:c.krb5_rd_error}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_rd\_error}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{enc\_errbuf}, {\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{dec\_error}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enc\_errbuf} \sphinxhyphen{} Encoded error message + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{dec\_error} \sphinxhyphen{} Decoded error message + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function processes \sphinxstylestrong{KRB\sphinxhyphen{}ERROR} message \sphinxstyleemphasis{enc\_errbuf} and returns an allocated structure \sphinxstyleemphasis{dec\_error} containing the error message. Use krb5\_free\_error() to free \sphinxstyleemphasis{dec\_error} when it is no longer needed. + + +\subsubsection{krb5\_rd\_priv \sphinxhyphen{} Process a KRB\sphinxhyphen{}PRIV message.} +\label{\detokenize{appdev/refs/api/krb5_rd_priv:krb5-rd-priv-process-a-krb-priv-message}}\label{\detokenize{appdev/refs/api/krb5_rd_priv::doc}}\index{krb5\_rd\_priv (C function)@\spxentry{krb5\_rd\_priv}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_rd_priv:c.krb5_rd_priv}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_rd\_priv}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{inbuf}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{userdata\_out}, {\hyperref[\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data}]{\sphinxcrossref{\DUrole{n}{krb5\_replay\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{rdata\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{inbuf} \sphinxhyphen{} \sphinxstylestrong{KRB\sphinxhyphen{}PRIV} message to be parsed + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{userdata\_out} \sphinxhyphen{} Data parsed from \sphinxstylestrong{KRB\sphinxhyphen{}PRIV} message + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{rdata\_out} \sphinxhyphen{} Replay data. Specify NULL if not needed + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function parses a \sphinxstylestrong{KRB\sphinxhyphen{}PRIV} message, verifies its integrity, and stores its unencrypted data into \sphinxstyleemphasis{userdata\_out} . + +\sphinxAtStartPar +If \sphinxstyleemphasis{auth\_context} has a remote address set, the address will be used to verify the sender address in the KRB\sphinxhyphen{}PRIV message. If \sphinxstyleemphasis{auth\_context} has a local address set, it will be used to verify the receiver address in the KRB\sphinxhyphen{}PRIV message if the message contains one. + +\sphinxAtStartPar +If the \#KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE flag is set in \sphinxstyleemphasis{auth\_context} , the sequence number of the KRB\sphinxhyphen{}PRIV message is checked against the remote sequence number field of \sphinxstyleemphasis{auth\_context} . Otherwise, the sequence number is not used. + +\sphinxAtStartPar +If the \#KRB5\_AUTH\_CONTEXT\_DO\_TIME flag is set in \sphinxstyleemphasis{auth\_context} , then the timestamp in the message is verified to be within the permitted clock skew of the current time, and the message is checked against an in\sphinxhyphen{}memory replay cache to detect reflections or replays. + +\sphinxAtStartPar +Use krb5\_free\_data\_contents() to free \sphinxstyleemphasis{userdata\_out} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The \sphinxstyleemphasis{rdata\_out} argument is required if the \#KRB5\_AUTH\_CONTEXT\_RET\_TIME or \#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE flag is set in \sphinxstyleemphasis{auth\_context} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_rd\_rep \sphinxhyphen{} Parse and decrypt a KRB\_AP\_REP message.} +\label{\detokenize{appdev/refs/api/krb5_rd_rep:krb5-rd-rep-parse-and-decrypt-a-krb-ap-rep-message}}\label{\detokenize{appdev/refs/api/krb5_rd_rep::doc}}\index{krb5\_rd\_rep (C function)@\spxentry{krb5\_rd\_rep}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_rd_rep:c.krb5_rd_rep}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_rd\_rep}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{inbuf}, {\hyperref[\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_rep\_enc\_part}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{repl}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{inbuf} \sphinxhyphen{} AP\sphinxhyphen{}REP message + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{repl} \sphinxhyphen{} Decrypted reply message + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function parses, decrypts and verifies a message from \sphinxstyleemphasis{inbuf} and fills in \sphinxstyleemphasis{repl} with a pointer to allocated memory containing the fields from the encrypted response. + +\sphinxAtStartPar +Use krb5\_free\_ap\_rep\_enc\_part() to free \sphinxstyleemphasis{repl} when it is no longer needed. + + +\subsubsection{krb5\_rd\_rep\_dce \sphinxhyphen{} Parse and decrypt a KRB\_AP\_REP message for DCE RPC.} +\label{\detokenize{appdev/refs/api/krb5_rd_rep_dce:krb5-rd-rep-dce-parse-and-decrypt-a-krb-ap-rep-message-for-dce-rpc}}\label{\detokenize{appdev/refs/api/krb5_rd_rep_dce::doc}}\index{krb5\_rd\_rep\_dce (C function)@\spxentry{krb5\_rd\_rep\_dce}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_rd_rep_dce:c.krb5_rd_rep_dce}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_rd\_rep\_dce}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{inbuf}, {\hyperref[\detokenize{appdev/refs/types/krb5_ui_4:c.krb5_ui_4}]{\sphinxcrossref{\DUrole{n}{krb5\_ui\_4}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{nonce}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{inbuf} \sphinxhyphen{} AP\sphinxhyphen{}REP message + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{nonce} \sphinxhyphen{} Sequence number from the decrypted reply + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function parses, decrypts and verifies a message from \sphinxstyleemphasis{inbuf} and fills in \sphinxstyleemphasis{nonce} with a decrypted reply sequence number. + + +\subsubsection{krb5\_rd\_req \sphinxhyphen{} Parse and decrypt a KRB\_AP\_REQ message.} +\label{\detokenize{appdev/refs/api/krb5_rd_req:krb5-rd-req-parse-and-decrypt-a-krb-ap-req-message}}\label{\detokenize{appdev/refs/api/krb5_rd_req::doc}}\index{krb5\_rd\_req (C function)@\spxentry{krb5\_rd\_req}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_rd_req:c.krb5_rd_req}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_rd\_req}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{auth\_context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{inbuf}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{w}{ }\DUrole{n}{server}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{keytab}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ap\_req\_options}, {\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{ticket}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Pre\sphinxhyphen{}existing or newly created auth context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{inbuf} \sphinxhyphen{} AP\sphinxhyphen{}REQ message to be parsed + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server} \sphinxhyphen{} Matching principal for server, or NULL to allow any principal in keytab + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keytab} \sphinxhyphen{} Key table, or NULL to use the default + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ap\_req\_options} \sphinxhyphen{} If non\sphinxhyphen{}null, the AP\sphinxhyphen{}REQ flags on output + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ticket} \sphinxhyphen{} If non\sphinxhyphen{}null, ticket from the AP\sphinxhyphen{}REQ message + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function parses, decrypts and verifies a AP\sphinxhyphen{}REQ message from \sphinxstyleemphasis{inbuf} and stores the authenticator in \sphinxstyleemphasis{auth\_context} . + +\sphinxAtStartPar +If a keyblock was specified in \sphinxstyleemphasis{auth\_context} using krb5\_auth\_con\_setuseruserkey(), that key is used to decrypt the ticket in AP\sphinxhyphen{}REQ message and \sphinxstyleemphasis{keytab} is ignored. In this case, \sphinxstyleemphasis{server} should be specified as a complete principal name to allow for proper transited\sphinxhyphen{}path checking and replay cache selection. + +\sphinxAtStartPar +Otherwise, the decryption key is obtained from \sphinxstyleemphasis{keytab} , or from the default keytab if it is NULL. In this case, \sphinxstyleemphasis{server} may be a complete principal name, a matching principal (see krb5\_sname\_match()), or NULL to match any principal name. The keys tried against the encrypted part of the ticket are determined as follows: +\begin{itemize} +\item {} +\sphinxAtStartPar +If \sphinxstyleemphasis{server} is a complete principal name, then its entry in \sphinxstyleemphasis{keytab} is tried. + +\item {} +\sphinxAtStartPar +Otherwise, if \sphinxstyleemphasis{keytab} is iterable, then all entries in \sphinxstyleemphasis{keytab} which match \sphinxstyleemphasis{server} are tried. + +\item {} +\sphinxAtStartPar +Otherwise, the server principal in the ticket must match \sphinxstyleemphasis{server} , and its entry in \sphinxstyleemphasis{keytab} is tried. + +\end{itemize} + +\sphinxAtStartPar +The client specified in the decrypted authenticator must match the client specified in the decrypted ticket. + +\sphinxAtStartPar +If the \sphinxstyleemphasis{remote\_addr} field of \sphinxstyleemphasis{auth\_context} is set, the request must come from that address. + +\sphinxAtStartPar +If a replay cache handle is provided in the \sphinxstyleemphasis{auth\_context} , the authenticator and ticket are verified against it. If no conflict is found, the new authenticator is then stored in the replay cache of \sphinxstyleemphasis{auth\_context} . + +\sphinxAtStartPar +Various other checks are performed on the decoded data, including cross\sphinxhyphen{}realm policy, clockskew, and ticket validation times. + +\sphinxAtStartPar +On success the authenticator, subkey, and remote sequence number of the request are stored in \sphinxstyleemphasis{auth\_context} . If the \#AP\_OPTS\_MUTUAL\_REQUIRED bit is set, the local sequence number is XORed with the remote sequence number in the request. + +\sphinxAtStartPar +Use krb5\_free\_ticket() to free \sphinxstyleemphasis{ticket} when it is no longer needed. + + +\subsubsection{krb5\_rd\_safe \sphinxhyphen{} Process KRB\sphinxhyphen{}SAFE message.} +\label{\detokenize{appdev/refs/api/krb5_rd_safe:krb5-rd-safe-process-krb-safe-message}}\label{\detokenize{appdev/refs/api/krb5_rd_safe::doc}}\index{krb5\_rd\_safe (C function)@\spxentry{krb5\_rd\_safe}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_rd_safe:c.krb5_rd_safe}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_rd\_safe}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{inbuf}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{userdata\_out}, {\hyperref[\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data}]{\sphinxcrossref{\DUrole{n}{krb5\_replay\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{rdata\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{inbuf} \sphinxhyphen{} \sphinxstylestrong{KRB\sphinxhyphen{}SAFE} message to be parsed + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{userdata\_out} \sphinxhyphen{} Data parsed from \sphinxstylestrong{KRB\sphinxhyphen{}SAFE} message + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{rdata\_out} \sphinxhyphen{} Replay data. Specify NULL if not needed + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function parses a \sphinxstylestrong{KRB\sphinxhyphen{}SAFE} message, verifies its integrity, and stores its data into \sphinxstyleemphasis{userdata\_out} . + +\sphinxAtStartPar +If \sphinxstyleemphasis{auth\_context} has a remote address set, the address will be used to verify the sender address in the KRB\sphinxhyphen{}SAFE message. If \sphinxstyleemphasis{auth\_context} has a local address set, it will be used to verify the receiver address in the KRB\sphinxhyphen{}SAFE message if the message contains one. + +\sphinxAtStartPar +If the \#KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE flag is set in \sphinxstyleemphasis{auth\_context} , the sequence number of the KRB\sphinxhyphen{}SAFE message is checked against the remote sequence number field of \sphinxstyleemphasis{auth\_context} . Otherwise, the sequence number is not used. + +\sphinxAtStartPar +If the \#KRB5\_AUTH\_CONTEXT\_DO\_TIME flag is set in \sphinxstyleemphasis{auth\_context} , then the timestamp in the message is verified to be within the permitted clock skew of the current time, and the message is checked against an in\sphinxhyphen{}memory replay cache to detect reflections or replays. + +\sphinxAtStartPar +Use krb5\_free\_data\_contents() to free \sphinxstyleemphasis{userdata\_out} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The \sphinxstyleemphasis{rdata\_out} argument is required if the \#KRB5\_AUTH\_CONTEXT\_RET\_TIME or \#KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE flag is set in \sphinxstyleemphasis{auth\_context} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_read\_password \sphinxhyphen{} Read a password from keyboard input.} +\label{\detokenize{appdev/refs/api/krb5_read_password:krb5-read-password-read-a-password-from-keyboard-input}}\label{\detokenize{appdev/refs/api/krb5_read_password::doc}}\index{krb5\_read\_password (C function)@\spxentry{krb5\_read\_password}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_read_password:c.krb5_read_password}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_read\_password}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{prompt}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{prompt2}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{return\_pwd}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{size\_return}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{prompt} \sphinxhyphen{} First user prompt when reading password + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{prompt2} \sphinxhyphen{} Second user prompt (NULL to prompt only once) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{return\_pwd} \sphinxhyphen{} Returned password + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{size\_return} \sphinxhyphen{} On input, maximum size of password; on output, size of password read + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Error in reading or verifying the password + +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function reads a password from keyboard input and stores it in \sphinxstyleemphasis{return\_pwd} . \sphinxstyleemphasis{size\_return} should be set by the caller to the amount of storage space available in \sphinxstyleemphasis{return\_pwd} ; on successful return, it will be set to the length of the password read. +\begin{quote} + +\sphinxAtStartPar +\sphinxstyleemphasis{prompt} is printed to the terminal, followed by”:”, and then a password is read from the keyboard. +\end{quote} + +\sphinxAtStartPar +If \sphinxstyleemphasis{prompt2} is NULL, the password is read only once. Otherwise, \sphinxstyleemphasis{prompt2} is printed to the terminal and a second password is read. If the two passwords entered are not identical, KRB5\_LIBOS\_BADPWDMATCH is returned. + +\sphinxAtStartPar +Echoing is turned off when the password is read. + + +\subsubsection{krb5\_salttype\_to\_string \sphinxhyphen{} Convert a salt type to a string.} +\label{\detokenize{appdev/refs/api/krb5_salttype_to_string:krb5-salttype-to-string-convert-a-salt-type-to-a-string}}\label{\detokenize{appdev/refs/api/krb5_salttype_to_string::doc}}\index{krb5\_salttype\_to\_string (C function)@\spxentry{krb5\_salttype\_to\_string}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_salttype_to_string:c.krb5_salttype_to_string}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_salttype\_to\_string}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\DUrole{n}{salttype}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{buffer}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{buflen}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{salttype} \sphinxhyphen{} Salttype to convert + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{buffer} \sphinxhyphen{} Buffer to receive the converted string + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{buflen} \sphinxhyphen{} Storage available in \sphinxstyleemphasis{buffer} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_server\_decrypt\_ticket\_keytab \sphinxhyphen{} Decrypt a ticket using the specified key table.} +\label{\detokenize{appdev/refs/api/krb5_server_decrypt_ticket_keytab:krb5-server-decrypt-ticket-keytab-decrypt-a-ticket-using-the-specified-key-table}}\label{\detokenize{appdev/refs/api/krb5_server_decrypt_ticket_keytab::doc}}\index{krb5\_server\_decrypt\_ticket\_keytab (C function)@\spxentry{krb5\_server\_decrypt\_ticket\_keytab}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_server_decrypt_ticket_keytab:c.krb5_server_decrypt_ticket_keytab}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_server\_decrypt\_ticket\_keytab}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{kt}, {\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ticket}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{kt} \sphinxhyphen{} Key table + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ticket} \sphinxhyphen{} Ticket to be decrypted + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function takes a \sphinxstyleemphasis{ticket} as input and decrypts it using key data from \sphinxstyleemphasis{kt} . The result is placed into \sphinxstyleemphasis{ticket\sphinxhyphen{}\textgreater{}enc\_part2} . + + +\subsubsection{krb5\_set\_default\_tgs\_enctypes \sphinxhyphen{} Set default TGS encryption types in a krb5\_context structure.} +\label{\detokenize{appdev/refs/api/krb5_set_default_tgs_enctypes:krb5-set-default-tgs-enctypes-set-default-tgs-encryption-types-in-a-krb5-context-structure}}\label{\detokenize{appdev/refs/api/krb5_set_default_tgs_enctypes::doc}}\index{krb5\_set\_default\_tgs\_enctypes (C function)@\spxentry{krb5\_set\_default\_tgs\_enctypes}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_set_default_tgs_enctypes:c.krb5_set_default_tgs_enctypes}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_set\_default\_tgs\_enctypes}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{etypes}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{etypes} \sphinxhyphen{} Encryption type(s) to set + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\item {} +\sphinxAtStartPar +KRB5\_PROG\_ETYPE\_NOSUPP Program lacks support for encryption type + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function sets the default enctype list for TGS requests made using \sphinxstyleemphasis{context} to \sphinxstyleemphasis{etypes} . + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +This overrides the default list (from config file or built\sphinxhyphen{}in). +\end{sphinxadmonition} + + +\subsubsection{krb5\_set\_error\_message \sphinxhyphen{} Set an extended error message for an error code.} +\label{\detokenize{appdev/refs/api/krb5_set_error_message:krb5-set-error-message-set-an-extended-error-message-for-an-error-code}}\label{\detokenize{appdev/refs/api/krb5_set_error_message::doc}}\index{krb5\_set\_error\_message (C function)@\spxentry{krb5\_set\_error\_message}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_set_error_message:c.krb5_set_error_message}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_set\_error\_message}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\DUrole{n}{code}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{fmt}, \DUrole{p}{...}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{code} \sphinxhyphen{} Error code + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{fmt} \sphinxhyphen{} Error string for the error code + +\end{description}\end{quote} + + +\subsubsection{krb5\_set\_kdc\_recv\_hook \sphinxhyphen{} Set a KDC post\sphinxhyphen{}receive hook function.} +\label{\detokenize{appdev/refs/api/krb5_set_kdc_recv_hook:krb5-set-kdc-recv-hook-set-a-kdc-post-receive-hook-function}}\label{\detokenize{appdev/refs/api/krb5_set_kdc_recv_hook::doc}}\index{krb5\_set\_kdc\_recv\_hook (C function)@\spxentry{krb5\_set\_kdc\_recv\_hook}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_set_kdc_recv_hook:c.krb5_set_kdc_recv_hook}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_set\_kdc\_recv\_hook}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_post_recv_fn:c.krb5_post_recv_fn}]{\sphinxcrossref{\DUrole{n}{krb5\_post\_recv\_fn}}}}\DUrole{w}{ }\DUrole{n}{recv\_hook}, \DUrole{kt}{void}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} The library context. + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{recv\_hook} \sphinxhyphen{} Hook function (or NULL to disable the hook) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} Callback data to be passed to \sphinxstyleemphasis{recv\_hook} + +\end{description}\end{quote} +\begin{quote} + +\sphinxAtStartPar +\sphinxstyleemphasis{recv\_hook} will be called after a reply is received from a KDC during a call to a library function such as krb5\_get\_credentials(). The hook function may inspect or override the reply. This hook will not be executed if the pre\sphinxhyphen{}send hook returns a synthetic reply. +\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.15 +\end{sphinxadmonition} + + +\subsubsection{krb5\_set\_kdc\_send\_hook \sphinxhyphen{} Set a KDC pre\sphinxhyphen{}send hook function.} +\label{\detokenize{appdev/refs/api/krb5_set_kdc_send_hook:krb5-set-kdc-send-hook-set-a-kdc-pre-send-hook-function}}\label{\detokenize{appdev/refs/api/krb5_set_kdc_send_hook::doc}}\index{krb5\_set\_kdc\_send\_hook (C function)@\spxentry{krb5\_set\_kdc\_send\_hook}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_set_kdc_send_hook:c.krb5_set_kdc_send_hook}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_set\_kdc\_send\_hook}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_pre_send_fn:c.krb5_pre_send_fn}]{\sphinxcrossref{\DUrole{n}{krb5\_pre\_send\_fn}}}}\DUrole{w}{ }\DUrole{n}{send\_hook}, \DUrole{kt}{void}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{send\_hook} \sphinxhyphen{} Hook function (or NULL to disable the hook) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} Callback data to be passed to \sphinxstyleemphasis{send\_hook} + +\end{description}\end{quote} +\begin{quote} + +\sphinxAtStartPar +\sphinxstyleemphasis{send\_hook} will be called before messages are sent to KDCs by library functions such as krb5\_get\_credentials(). The hook function may inspect, override, or synthesize its own reply to the message. +\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.15 +\end{sphinxadmonition} + + +\subsubsection{krb5\_set\_real\_time \sphinxhyphen{} Set time offset field in a krb5\_context structure.} +\label{\detokenize{appdev/refs/api/krb5_set_real_time:krb5-set-real-time-set-time-offset-field-in-a-krb5-context-structure}}\label{\detokenize{appdev/refs/api/krb5_set_real_time::doc}}\index{krb5\_set\_real\_time (C function)@\spxentry{krb5\_set\_real\_time}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_set_real_time:c.krb5_set_real_time}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_set\_real\_time}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\DUrole{n}{seconds}, {\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\DUrole{n}{microseconds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{seconds} \sphinxhyphen{} Real time, seconds portion + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{microseconds} \sphinxhyphen{} Real time, microseconds portion + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function sets the time offset in \sphinxstyleemphasis{context} to the difference between the system time and the real time as determined by \sphinxstyleemphasis{seconds} and \sphinxstyleemphasis{microseconds} . + + +\subsubsection{krb5\_string\_to\_cksumtype \sphinxhyphen{} Convert a string to a checksum type.} +\label{\detokenize{appdev/refs/api/krb5_string_to_cksumtype:krb5-string-to-cksumtype-convert-a-string-to-a-checksum-type}}\label{\detokenize{appdev/refs/api/krb5_string_to_cksumtype::doc}}\index{krb5\_string\_to\_cksumtype (C function)@\spxentry{krb5\_string\_to\_cksumtype}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_string_to_cksumtype:c.krb5_string_to_cksumtype}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_string\_to\_cksumtype}}}}{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{string}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cksumtypep}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{string} \sphinxhyphen{} String to be converted + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{cksumtypep} \sphinxhyphen{} Checksum type to be filled in + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} EINVAL + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_string\_to\_deltat \sphinxhyphen{} Convert a string to a delta time value.} +\label{\detokenize{appdev/refs/api/krb5_string_to_deltat:krb5-string-to-deltat-convert-a-string-to-a-delta-time-value}}\label{\detokenize{appdev/refs/api/krb5_string_to_deltat::doc}}\index{krb5\_string\_to\_deltat (C function)@\spxentry{krb5\_string\_to\_deltat}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_string_to_deltat:c.krb5_string_to_deltat}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_string\_to\_deltat}}}}{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{string}, {\hyperref[\detokenize{appdev/refs/types/krb5_deltat:c.krb5_deltat}]{\sphinxcrossref{\DUrole{n}{krb5\_deltat}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{deltatp}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{string} \sphinxhyphen{} String to be converted + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{deltatp} \sphinxhyphen{} Delta time to be filled in + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} KRB5\_DELTAT\_BADFORMAT + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_string\_to\_enctype \sphinxhyphen{} Convert a string to an encryption type.} +\label{\detokenize{appdev/refs/api/krb5_string_to_enctype:krb5-string-to-enctype-convert-a-string-to-an-encryption-type}}\label{\detokenize{appdev/refs/api/krb5_string_to_enctype::doc}}\index{krb5\_string\_to\_enctype (C function)@\spxentry{krb5\_string\_to\_enctype}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_string_to_enctype:c.krb5_string_to_enctype}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_string\_to\_enctype}}}}{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{string}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{enctypep}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{string} \sphinxhyphen{} String to convert to an encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{enctypep} \sphinxhyphen{} Encryption type + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} EINVAL + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_string\_to\_salttype \sphinxhyphen{} Convert a string to a salt type.} +\label{\detokenize{appdev/refs/api/krb5_string_to_salttype:krb5-string-to-salttype-convert-a-string-to-a-salt-type}}\label{\detokenize{appdev/refs/api/krb5_string_to_salttype::doc}}\index{krb5\_string\_to\_salttype (C function)@\spxentry{krb5\_string\_to\_salttype}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_string_to_salttype:c.krb5_string_to_salttype}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_string\_to\_salttype}}}}{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{string}, {\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{salttypep}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{string} \sphinxhyphen{} String to convert to an encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{salttypep} \sphinxhyphen{} Salt type to be filled in + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} EINVAL + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_string\_to\_timestamp \sphinxhyphen{} Convert a string to a timestamp.} +\label{\detokenize{appdev/refs/api/krb5_string_to_timestamp:krb5-string-to-timestamp-convert-a-string-to-a-timestamp}}\label{\detokenize{appdev/refs/api/krb5_string_to_timestamp::doc}}\index{krb5\_string\_to\_timestamp (C function)@\spxentry{krb5\_string\_to\_timestamp}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_string_to_timestamp:c.krb5_string_to_timestamp}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_string\_to\_timestamp}}}}{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{string}, {\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{timestampp}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{string} \sphinxhyphen{} String to be converted + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{timestampp} \sphinxhyphen{} Pointer to timestamp + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} EINVAL + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_timeofday \sphinxhyphen{} Retrieve the current time with context specific time offset adjustment.} +\label{\detokenize{appdev/refs/api/krb5_timeofday:krb5-timeofday-retrieve-the-current-time-with-context-specific-time-offset-adjustment}}\label{\detokenize{appdev/refs/api/krb5_timeofday::doc}}\index{krb5\_timeofday (C function)@\spxentry{krb5\_timeofday}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_timeofday:c.krb5_timeofday}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_timeofday}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{timeret}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{timeret} \sphinxhyphen{} Timestamp to fill in + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success + +\end{itemize} + +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function retrieves the system time of day with the context specific time offset adjustment. + + +\subsubsection{krb5\_timestamp\_to\_sfstring \sphinxhyphen{} Convert a timestamp to a string, with optional output padding.} +\label{\detokenize{appdev/refs/api/krb5_timestamp_to_sfstring:krb5-timestamp-to-sfstring-convert-a-timestamp-to-a-string-with-optional-output-padding}}\label{\detokenize{appdev/refs/api/krb5_timestamp_to_sfstring::doc}}\index{krb5\_timestamp\_to\_sfstring (C function)@\spxentry{krb5\_timestamp\_to\_sfstring}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_timestamp_to_sfstring:c.krb5_timestamp_to_sfstring}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_timestamp\_to\_sfstring}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\DUrole{n}{timestamp}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{buffer}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{buflen}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{pad}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{timestamp} \sphinxhyphen{} Timestamp to convert + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{buffer} \sphinxhyphen{} Buffer to hold the converted timestamp + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{buflen} \sphinxhyphen{} Length of buffer + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pad} \sphinxhyphen{} Optional value to pad \sphinxstyleemphasis{buffer} if converted timestamp does not fill it + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +If \sphinxstyleemphasis{pad} is not NULL, \sphinxstyleemphasis{buffer} is padded out to \sphinxstyleemphasis{buflen} \sphinxhyphen{} 1 characters with the value of * \sphinxstyleemphasis{pad} . + + +\subsubsection{krb5\_timestamp\_to\_string \sphinxhyphen{} Convert a timestamp to a string.} +\label{\detokenize{appdev/refs/api/krb5_timestamp_to_string:krb5-timestamp-to-string-convert-a-timestamp-to-a-string}}\label{\detokenize{appdev/refs/api/krb5_timestamp_to_string::doc}}\index{krb5\_timestamp\_to\_string (C function)@\spxentry{krb5\_timestamp\_to\_string}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_timestamp_to_string:c.krb5_timestamp_to_string}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_timestamp\_to\_string}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\DUrole{n}{timestamp}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{buffer}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{buflen}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{timestamp} \sphinxhyphen{} Timestamp to convert + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{buffer} \sphinxhyphen{} Buffer to hold converted timestamp + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{buflen} \sphinxhyphen{} Storage available in \sphinxstyleemphasis{buffer} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +The string is returned in the locale’s appropriate date and time representation. + + +\subsubsection{krb5\_tkt\_creds\_free \sphinxhyphen{} Free a TGS request context.} +\label{\detokenize{appdev/refs/api/krb5_tkt_creds_free:krb5-tkt-creds-free-free-a-tgs-request-context}}\label{\detokenize{appdev/refs/api/krb5_tkt_creds_free::doc}}\index{krb5\_tkt\_creds\_free (C function)@\spxentry{krb5\_tkt\_creds\_free}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_tkt_creds_free:c.krb5_tkt_creds_free}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_tkt\_creds\_free}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_tkt_creds_context:c.krb5_tkt_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_tkt\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} TGS request context + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.9 +\end{sphinxadmonition} + + +\subsubsection{krb5\_tkt\_creds\_get \sphinxhyphen{} Synchronously obtain credentials using a TGS request context.} +\label{\detokenize{appdev/refs/api/krb5_tkt_creds_get:krb5-tkt-creds-get-synchronously-obtain-credentials-using-a-tgs-request-context}}\label{\detokenize{appdev/refs/api/krb5_tkt_creds_get::doc}}\index{krb5\_tkt\_creds\_get (C function)@\spxentry{krb5\_tkt\_creds\_get}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_tkt_creds_get:c.krb5_tkt_creds_get}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_tkt\_creds\_get}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_tkt_creds_context:c.krb5_tkt_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_tkt\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} TGS request context + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function synchronously obtains credentials using a context created by krb5\_tkt\_creds\_init(). On successful return, the credentials can be retrieved with krb5\_tkt\_creds\_get\_creds(). + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.9 +\end{sphinxadmonition} + + +\subsubsection{krb5\_tkt\_creds\_get\_creds \sphinxhyphen{} Retrieve acquired credentials from a TGS request context.} +\label{\detokenize{appdev/refs/api/krb5_tkt_creds_get_creds:krb5-tkt-creds-get-creds-retrieve-acquired-credentials-from-a-tgs-request-context}}\label{\detokenize{appdev/refs/api/krb5_tkt_creds_get_creds::doc}}\index{krb5\_tkt\_creds\_get\_creds (C function)@\spxentry{krb5\_tkt\_creds\_get\_creds}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_tkt_creds_get_creds:c.krb5_tkt_creds_get_creds}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_tkt\_creds\_get\_creds}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_tkt_creds_context:c.krb5_tkt_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_tkt\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} TGS request context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Acquired credentials + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function copies the acquired initial credentials from \sphinxstyleemphasis{ctx} into \sphinxstyleemphasis{creds} , after the successful completion of krb5\_tkt\_creds\_get() or krb5\_tkt\_creds\_step(). Use krb5\_free\_cred\_contents() to free \sphinxstyleemphasis{creds} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.9 +\end{sphinxadmonition} + + +\subsubsection{krb5\_tkt\_creds\_get\_times \sphinxhyphen{} Retrieve ticket times from a TGS request context.} +\label{\detokenize{appdev/refs/api/krb5_tkt_creds_get_times:krb5-tkt-creds-get-times-retrieve-ticket-times-from-a-tgs-request-context}}\label{\detokenize{appdev/refs/api/krb5_tkt_creds_get_times::doc}}\index{krb5\_tkt\_creds\_get\_times (C function)@\spxentry{krb5\_tkt\_creds\_get\_times}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_tkt_creds_get_times:c.krb5_tkt_creds_get_times}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_tkt\_creds\_get\_times}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_tkt_creds_context:c.krb5_tkt_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_tkt\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket\_times}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{times}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} TGS request context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{times} \sphinxhyphen{} Ticket times for acquired credentials + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +The TGS request context must have completed obtaining credentials via either krb5\_tkt\_creds\_get() or krb5\_tkt\_creds\_step(). + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.9 +\end{sphinxadmonition} + + +\subsubsection{krb5\_tkt\_creds\_init \sphinxhyphen{} Create a context to get credentials from a KDC’s Ticket Granting Service.} +\label{\detokenize{appdev/refs/api/krb5_tkt_creds_init:krb5-tkt-creds-init-create-a-context-to-get-credentials-from-a-kdc-s-ticket-granting-service}}\label{\detokenize{appdev/refs/api/krb5_tkt_creds_init::doc}}\index{krb5\_tkt\_creds\_init (C function)@\spxentry{krb5\_tkt\_creds\_init}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_tkt_creds_init:c.krb5_tkt_creds_init}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_tkt\_creds\_init}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{options}, {\hyperref[\detokenize{appdev/refs/types/krb5_tkt_creds_context:c.krb5_tkt_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_tkt\_creds\_context}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ctx}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ccache} \sphinxhyphen{} Credential cache handle + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Input credentials + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{options} \sphinxhyphen{} Options (see KRB5\_GC macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} New TGS request context + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function prepares to obtain credentials matching \sphinxstyleemphasis{creds} , either by retrieving them from \sphinxstyleemphasis{ccache} or by making requests to ticket\sphinxhyphen{}granting services beginning with a ticket\sphinxhyphen{}granting ticket for the client principal’s realm. + +\sphinxAtStartPar +The resulting TGS acquisition context can be used asynchronously with krb5\_tkt\_creds\_step() or synchronously with krb5\_tkt\_creds\_get(). See also krb5\_get\_credentials() for synchronous use. + +\sphinxAtStartPar +Use krb5\_tkt\_creds\_free() to free \sphinxstyleemphasis{ctx} when it is no longer needed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.9 +\end{sphinxadmonition} + + +\subsubsection{krb5\_tkt\_creds\_step \sphinxhyphen{} Get the next KDC request in a TGS exchange.} +\label{\detokenize{appdev/refs/api/krb5_tkt_creds_step:krb5-tkt-creds-step-get-the-next-kdc-request-in-a-tgs-exchange}}\label{\detokenize{appdev/refs/api/krb5_tkt_creds_step::doc}}\index{krb5\_tkt\_creds\_step (C function)@\spxentry{krb5\_tkt\_creds\_step}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_tkt_creds_step:c.krb5_tkt_creds_step}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_tkt\_creds\_step}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_tkt_creds_context:c.krb5_tkt_creds_context}]{\sphinxcrossref{\DUrole{n}{krb5\_tkt\_creds\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{out}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{realm}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{flags}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} TGS request context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in} \sphinxhyphen{} KDC response (empty on the first call) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{out} \sphinxhyphen{} Next KDC request + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{realm} \sphinxhyphen{} Realm for next KDC request + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Output flags + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function constructs the next KDC request for a TGS exchange, allowing the caller to control the transport of KDC requests and replies. On the first call, \sphinxstyleemphasis{in} should be set to an empty buffer; on subsequent calls, it should be set to the KDC’s reply to the previous request. + +\sphinxAtStartPar +If more requests are needed, \sphinxstyleemphasis{flags} will be set to \#KRB5\_TKT\_CREDS\_STEP\_FLAG\_CONTINUE and the next request will be placed in \sphinxstyleemphasis{out} . If no more requests are needed, \sphinxstyleemphasis{flags} will not contain \#KRB5\_TKT\_CREDS\_STEP\_FLAG\_CONTINUE and \sphinxstyleemphasis{out} will be empty. + +\sphinxAtStartPar +If this function returns \sphinxstylestrong{KRB5KRB\_ERR\_RESPONSE\_TOO\_BIG} , the caller should transmit the next request using TCP rather than UDP. If this function returns any other error, the TGS exchange has failed. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.9 +\end{sphinxadmonition} + + +\subsubsection{krb5\_unmarshal\_credentials \sphinxhyphen{} Deserialize a krb5\_creds object.} +\label{\detokenize{appdev/refs/api/krb5_unmarshal_credentials:krb5-unmarshal-credentials-deserialize-a-krb5-creds-object}}\label{\detokenize{appdev/refs/api/krb5_unmarshal_credentials::doc}}\index{krb5\_unmarshal\_credentials (C function)@\spxentry{krb5\_unmarshal\_credentials}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_unmarshal_credentials:c.krb5_unmarshal_credentials}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_unmarshal\_credentials}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{creds\_out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} The serialized credentials + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{creds\_out} \sphinxhyphen{} The resulting creds object + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Deserialize \sphinxstyleemphasis{data} to credentials in the format used by the FILE ccache format (vesion 4) and KCM ccache protocol. + +\sphinxAtStartPar +Use krb5\_free\_creds() to free \sphinxstyleemphasis{creds\_out} when it is no longer needed. + + +\subsubsection{krb5\_verify\_init\_creds \sphinxhyphen{} Verify initial credentials against a keytab.} +\label{\detokenize{appdev/refs/api/krb5_verify_init_creds:krb5-verify-init-creds-verify-initial-credentials-against-a-keytab}}\label{\detokenize{appdev/refs/api/krb5_verify_init_creds::doc}}\index{krb5\_verify\_init\_creds (C function)@\spxentry{krb5\_verify\_init\_creds}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_verify_init_creds:c.krb5_verify_init_creds}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_verify\_init\_creds}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{server}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{keytab}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ccache}, {\hyperref[\detokenize{appdev/refs/types/krb5_verify_init_creds_opt:c.krb5_verify_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_verify\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{options}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{creds} \sphinxhyphen{} Initial credentials to be verified + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server} \sphinxhyphen{} Server principal (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keytab} \sphinxhyphen{} Key table (NULL to use default keytab) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ccache} \sphinxhyphen{} Credential cache for fetched creds (or NULL) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{options} \sphinxhyphen{} Verification options (NULL for default options) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function attempts to verify that \sphinxstyleemphasis{creds} were obtained from a KDC with knowledge of a key in \sphinxstyleemphasis{keytab} , or the default keytab if \sphinxstyleemphasis{keytab} is NULL. If \sphinxstyleemphasis{server} is provided, the highest\sphinxhyphen{}kvno key entry for that principal name is used to verify the credentials; otherwise, all unique”host”service principals in the keytab are tried. + +\sphinxAtStartPar +If the specified keytab does not exist, or is empty, or cannot be read, or does not contain an entry for \sphinxstyleemphasis{server} , then credential verification may be skipped unless configuration demands that it succeed. The caller can control this behavior by providing a verification options structure; see krb5\_verify\_init\_creds\_opt\_init() and krb5\_verify\_init\_creds\_opt\_set\_ap\_req\_nofail(). + +\sphinxAtStartPar +If \sphinxstyleemphasis{ccache} is NULL, any additional credentials fetched during the verification process will be destroyed. If \sphinxstyleemphasis{ccache} points to NULL, a memory ccache will be created for the additional credentials and returned in \sphinxstyleemphasis{ccache} . If \sphinxstyleemphasis{ccache} points to a valid credential cache handle, the additional credentials will be stored in that cache. + + +\subsubsection{krb5\_verify\_init\_creds\_opt\_init \sphinxhyphen{} Initialize a credential verification options structure.} +\label{\detokenize{appdev/refs/api/krb5_verify_init_creds_opt_init:krb5-verify-init-creds-opt-init-initialize-a-credential-verification-options-structure}}\label{\detokenize{appdev/refs/api/krb5_verify_init_creds_opt_init::doc}}\index{krb5\_verify\_init\_creds\_opt\_init (C function)@\spxentry{krb5\_verify\_init\_creds\_opt\_init}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_verify_init_creds_opt_init:c.krb5_verify_init_creds_opt_init}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_verify\_init\_creds\_opt\_init}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_verify_init_creds_opt:c.krb5_verify_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_verify\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{k5\_vic\_options}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{k5\_vic\_options} \sphinxhyphen{} Verification options structure + +\end{description}\end{quote} + + +\subsubsection{krb5\_verify\_init\_creds\_opt\_set\_ap\_req\_nofail \sphinxhyphen{} Set whether credential verification is required.} +\label{\detokenize{appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail:krb5-verify-init-creds-opt-set-ap-req-nofail-set-whether-credential-verification-is-required}}\label{\detokenize{appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail::doc}}\index{krb5\_verify\_init\_creds\_opt\_set\_ap\_req\_nofail (C function)@\spxentry{krb5\_verify\_init\_creds\_opt\_set\_ap\_req\_nofail}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_verify_init_creds_opt_set_ap_req_nofail:c.krb5_verify_init_creds_opt_set_ap_req_nofail}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_verify\_init\_creds\_opt\_set\_ap\_req\_nofail}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_verify_init_creds_opt:c.krb5_verify_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_verify\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{k5\_vic\_options}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{ap\_req\_nofail}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{k5\_vic\_options} \sphinxhyphen{} Verification options structure + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ap\_req\_nofail} \sphinxhyphen{} Whether to require successful verification + +\end{description}\end{quote} + +\sphinxAtStartPar +This function determines how krb5\_verify\_init\_creds() behaves if no keytab information is available. If \sphinxstyleemphasis{ap\_req\_nofail} is \sphinxstylestrong{FALSE} , verification will be skipped in this case and krb5\_verify\_init\_creds() will return successfully. If \sphinxstyleemphasis{ap\_req\_nofail} is \sphinxstylestrong{TRUE} , krb5\_verify\_init\_creds() will not return successfully unless verification can be performed. + +\sphinxAtStartPar +If this function is not used, the behavior of krb5\_verify\_init\_creds() is determined through configuration. + + +\subsubsection{krb5\_vprepend\_error\_message \sphinxhyphen{} Add a prefix to the message for an error code using a va\_list.} +\label{\detokenize{appdev/refs/api/krb5_vprepend_error_message:krb5-vprepend-error-message-add-a-prefix-to-the-message-for-an-error-code-using-a-va-list}}\label{\detokenize{appdev/refs/api/krb5_vprepend_error_message::doc}}\index{krb5\_vprepend\_error\_message (C function)@\spxentry{krb5\_vprepend\_error\_message}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_vprepend_error_message:c.krb5_vprepend_error_message}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_vprepend\_error\_message}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\DUrole{n}{code}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{fmt}, \DUrole{n}{va\_list}\DUrole{w}{ }\DUrole{n}{args}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{code} \sphinxhyphen{} Error code + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{fmt} \sphinxhyphen{} Format string for error message prefix + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{args} \sphinxhyphen{} List of vprintf(3) style arguments + +\end{description}\end{quote} + +\sphinxAtStartPar +This function is similar to krb5\_prepend\_error\_message(), but uses a va\_list instead of variadic arguments. + + +\subsubsection{krb5\_vset\_error\_message \sphinxhyphen{} Set an extended error message for an error code using a va\_list.} +\label{\detokenize{appdev/refs/api/krb5_vset_error_message:krb5-vset-error-message-set-an-extended-error-message-for-an-error-code-using-a-va-list}}\label{\detokenize{appdev/refs/api/krb5_vset_error_message::doc}}\index{krb5\_vset\_error\_message (C function)@\spxentry{krb5\_vset\_error\_message}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_vset_error_message:c.krb5_vset_error_message}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_vset\_error\_message}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\DUrole{n}{code}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{fmt}, \DUrole{n}{va\_list}\DUrole{w}{ }\DUrole{n}{args}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{code} \sphinxhyphen{} Error code + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{fmt} \sphinxhyphen{} Error string for the error code + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{args} \sphinxhyphen{} List of vprintf(3) style arguments + +\end{description}\end{quote} + + +\subsubsection{krb5\_vwrap\_error\_message \sphinxhyphen{} Add a prefix to a different error code’s message using a va\_list.} +\label{\detokenize{appdev/refs/api/krb5_vwrap_error_message:krb5-vwrap-error-message-add-a-prefix-to-a-different-error-code-s-message-using-a-va-list}}\label{\detokenize{appdev/refs/api/krb5_vwrap_error_message::doc}}\index{krb5\_vwrap\_error\_message (C function)@\spxentry{krb5\_vwrap\_error\_message}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_vwrap_error_message:c.krb5_vwrap_error_message}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_vwrap\_error\_message}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\DUrole{n}{old\_code}, {\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\DUrole{n}{code}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{fmt}, \DUrole{n}{va\_list}\DUrole{w}{ }\DUrole{n}{args}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{old\_code} \sphinxhyphen{} Previous error code + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{code} \sphinxhyphen{} Error code + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{fmt} \sphinxhyphen{} Format string for error message prefix + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{args} \sphinxhyphen{} List of vprintf(3) style arguments + +\end{description}\end{quote} + +\sphinxAtStartPar +This function is similar to krb5\_wrap\_error\_message(), but uses a va\_list instead of variadic arguments. + + +\subsubsection{krb5\_wrap\_error\_message \sphinxhyphen{} Add a prefix to a different error code’s message.} +\label{\detokenize{appdev/refs/api/krb5_wrap_error_message:krb5-wrap-error-message-add-a-prefix-to-a-different-error-code-s-message}}\label{\detokenize{appdev/refs/api/krb5_wrap_error_message::doc}}\index{krb5\_wrap\_error\_message (C function)@\spxentry{krb5\_wrap\_error\_message}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_wrap_error_message:c.krb5_wrap_error_message}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_wrap\_error\_message}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{ctx}, {\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\DUrole{n}{old\_code}, {\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\DUrole{n}{code}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{fmt}, \DUrole{p}{...}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctx} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{old\_code} \sphinxhyphen{} Previous error code + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{code} \sphinxhyphen{} Error code + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{fmt} \sphinxhyphen{} Format string for error message prefix + +\end{description}\end{quote} + +\sphinxAtStartPar +Format a message and prepend it to the message for \sphinxstyleemphasis{old\_code} . The prefix will be separated from the old message with a colon and space. Set the resulting message as the extended error message for \sphinxstyleemphasis{code} . + + +\subsection{Public interfaces that should not be called directly} +\label{\detokenize{appdev/refs/api/index:public-interfaces-that-should-not-be-called-directly}} + +\subsubsection{krb5\_c\_block\_size \sphinxhyphen{} Return cipher block size.} +\label{\detokenize{appdev/refs/api/krb5_c_block_size:krb5-c-block-size-return-cipher-block-size}}\label{\detokenize{appdev/refs/api/krb5_c_block_size::doc}}\index{krb5\_c\_block\_size (C function)@\spxentry{krb5\_c\_block\_size}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_block_size:c.krb5_c_block_size}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_block\_size}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{blocksize}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{blocksize} \sphinxhyphen{} Block size for \sphinxstyleemphasis{enctype} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_c\_checksum\_length \sphinxhyphen{} Return the length of checksums for a checksum type.} +\label{\detokenize{appdev/refs/api/krb5_c_checksum_length:krb5-c-checksum-length-return-the-length-of-checksums-for-a-checksum-type}}\label{\detokenize{appdev/refs/api/krb5_c_checksum_length::doc}}\index{krb5\_c\_checksum\_length (C function)@\spxentry{krb5\_c\_checksum\_length}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_checksum_length:c.krb5_c_checksum_length}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_checksum\_length}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{cksumtype}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{length}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cksumtype} \sphinxhyphen{} Checksum type + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{length} \sphinxhyphen{} Checksum length + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_c\_crypto\_length \sphinxhyphen{} Return a length of a message field specific to the encryption type.} +\label{\detokenize{appdev/refs/api/krb5_c_crypto_length:krb5-c-crypto-length-return-a-length-of-a-message-field-specific-to-the-encryption-type}}\label{\detokenize{appdev/refs/api/krb5_c_crypto_length::doc}}\index{krb5\_c\_crypto\_length (C function)@\spxentry{krb5\_c\_crypto\_length}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_crypto_length:c.krb5_c_crypto_length}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_crypto\_length}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, {\hyperref[\detokenize{appdev/refs/types/krb5_cryptotype:c.krb5_cryptotype}]{\sphinxcrossref{\DUrole{n}{krb5\_cryptotype}}}}\DUrole{w}{ }\DUrole{n}{type}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{size}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{type} \sphinxhyphen{} Type field (See KRB5\_CRYPTO\_TYPE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{size} \sphinxhyphen{} Length of the \sphinxstyleemphasis{type} specific to \sphinxstyleemphasis{enctype} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_c\_crypto\_length\_iov \sphinxhyphen{} Fill in lengths for header, trailer and padding in a IOV array.} +\label{\detokenize{appdev/refs/api/krb5_c_crypto_length_iov:krb5-c-crypto-length-iov-fill-in-lengths-for-header-trailer-and-padding-in-a-iov-array}}\label{\detokenize{appdev/refs/api/krb5_c_crypto_length_iov::doc}}\index{krb5\_c\_crypto\_length\_iov (C function)@\spxentry{krb5\_c\_crypto\_length\_iov}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_crypto_length_iov:c.krb5_c_crypto_length_iov}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_crypto\_length\_iov}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, {\hyperref[\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov}]{\sphinxcrossref{\DUrole{n}{krb5\_crypto\_iov}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{num\_data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{data} \sphinxhyphen{} IOV array + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{num\_data} \sphinxhyphen{} Size of \sphinxstyleemphasis{data} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Padding is set to the actual padding required based on the provided \sphinxstyleemphasis{data} buffers. Typically this API is used after setting up the data buffers and \#KRB5\_CRYPTO\_TYPE\_SIGN\_ONLY buffers, but before actually allocating header, trailer and padding. + + +\subsubsection{krb5\_c\_decrypt \sphinxhyphen{} Decrypt data using a key (operates on keyblock).} +\label{\detokenize{appdev/refs/api/krb5_c_decrypt:krb5-c-decrypt-decrypt-data-using-a-key-operates-on-keyblock}}\label{\detokenize{appdev/refs/api/krb5_c_decrypt::doc}}\index{krb5\_c\_decrypt (C function)@\spxentry{krb5\_c\_decrypt}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_decrypt:c.krb5_c_decrypt}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_decrypt}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cipher\_state}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{input}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{output}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{cipher\_state} \sphinxhyphen{} Cipher state; specify NULL if not needed + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{input} \sphinxhyphen{} Encrypted data + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{output} \sphinxhyphen{} Decrypted data + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function decrypts the data block \sphinxstyleemphasis{input} and stores the output into \sphinxstyleemphasis{output} . The actual decryption key will be derived from \sphinxstyleemphasis{key} and \sphinxstyleemphasis{usage} if key derivation is specified for the encryption type. If non\sphinxhyphen{}null, \sphinxstyleemphasis{cipher\_state} specifies the beginning state for the decryption operation, and is updated with the state to be passed as input to the next operation. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The caller must initialize \sphinxstyleemphasis{output} and allocate at least enough space for the result. The usual practice is to allocate an output buffer as long as the ciphertext, and let krb5\_c\_decrypt() trim \sphinxstyleemphasis{output\sphinxhyphen{}\textgreater{}length} . For some enctypes, the resulting \sphinxstyleemphasis{output\sphinxhyphen{}\textgreater{}length} may include padding bytes. +\end{sphinxadmonition} + + +\subsubsection{krb5\_c\_decrypt\_iov \sphinxhyphen{} Decrypt data in place supporting AEAD (operates on keyblock).} +\label{\detokenize{appdev/refs/api/krb5_c_decrypt_iov:krb5-c-decrypt-iov-decrypt-data-in-place-supporting-aead-operates-on-keyblock}}\label{\detokenize{appdev/refs/api/krb5_c_decrypt_iov::doc}}\index{krb5\_c\_decrypt\_iov (C function)@\spxentry{krb5\_c\_decrypt\_iov}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_decrypt_iov:c.krb5_c_decrypt_iov}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_decrypt\_iov}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{keyblock}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cipher\_state}, {\hyperref[\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov}]{\sphinxcrossref{\DUrole{n}{krb5\_crypto\_iov}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{num\_data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keyblock} \sphinxhyphen{} Encryption key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cipher\_state} \sphinxhyphen{} Cipher state; specify NULL if not needed + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{data} \sphinxhyphen{} IOV array. Modified in\sphinxhyphen{}place. + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{num\_data} \sphinxhyphen{} Size of \sphinxstyleemphasis{data} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function decrypts the data block \sphinxstyleemphasis{data} and stores the output in\sphinxhyphen{}place. The actual decryption key will be derived from \sphinxstyleemphasis{keyblock} and \sphinxstyleemphasis{usage} if key derivation is specified for the encryption type. If non\sphinxhyphen{}null, \sphinxstyleemphasis{cipher\_state} specifies the beginning state for the decryption operation, and is updated with the state to be passed as input to the next operation. The caller must allocate the right number of krb5\_crypto\_iov structures before calling into this API. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_c\_decrypt\_iov() + + + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +On return from a krb5\_c\_decrypt\_iov() call, the \sphinxstyleemphasis{data\sphinxhyphen{}\textgreater{}length} in the iov structure are adjusted to reflect actual lengths of the ciphertext used. For example, if the padding length is too large, the length will be reduced. Lengths are never increased. +\end{sphinxadmonition} + + +\subsubsection{krb5\_c\_derive\_prfplus \sphinxhyphen{} Derive a key using some input data (via RFC 6113 PRF+).} +\label{\detokenize{appdev/refs/api/krb5_c_derive_prfplus:krb5-c-derive-prfplus-derive-a-key-using-some-input-data-via-rfc-6113-prf}}\label{\detokenize{appdev/refs/api/krb5_c_derive_prfplus::doc}}\index{krb5\_c\_derive\_prfplus (C function)@\spxentry{krb5\_c\_derive\_prfplus}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_derive_prfplus:c.krb5_c_derive_prfplus}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_derive\_prfplus}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{k}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{input}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{k} \sphinxhyphen{} KDC contribution key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{input} \sphinxhyphen{} Input string + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Output key enctype (or \sphinxstylestrong{ENCTYPE\_NULL} ) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{out} \sphinxhyphen{} Derived keyblock + +\end{description}\end{quote} + +\sphinxAtStartPar +This function uses PRF+ as defined in RFC 6113 to derive a key from another key and an input string. If \sphinxstyleemphasis{enctype} is \sphinxstylestrong{ENCTYPE\_NULL} , the output key will have the same enctype as the input key. + + +\subsubsection{krb5\_c\_encrypt \sphinxhyphen{} Encrypt data using a key (operates on keyblock).} +\label{\detokenize{appdev/refs/api/krb5_c_encrypt:krb5-c-encrypt-encrypt-data-using-a-key-operates-on-keyblock}}\label{\detokenize{appdev/refs/api/krb5_c_encrypt::doc}}\index{krb5\_c\_encrypt (C function)@\spxentry{krb5\_c\_encrypt}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_encrypt:c.krb5_c_encrypt}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_encrypt}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cipher\_state}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{input}, {\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{output}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{cipher\_state} \sphinxhyphen{} Cipher state; specify NULL if not needed + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{input} \sphinxhyphen{} Data to be encrypted + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{output} \sphinxhyphen{} Encrypted data + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function encrypts the data block \sphinxstyleemphasis{input} and stores the outputinto \sphinxstyleemphasis{output} . The actual encryption key will be derived from \sphinxstyleemphasis{key} and \sphinxstyleemphasis{usage} if key derivation is specified for the encryption type. If non\sphinxhyphen{}null, \sphinxstyleemphasis{cipher\_state} specifies the beginning state for the encryption operation, and is updated with the state to be passed as input to the next operation. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The caller must initialize \sphinxstyleemphasis{output} and allocate at least enough space for the result (using krb5\_c\_encrypt\_length() to determine the amount of space needed). \sphinxstyleemphasis{output\sphinxhyphen{}\textgreater{}length} will be set to the actual length of the ciphertext. +\end{sphinxadmonition} + + +\subsubsection{krb5\_c\_encrypt\_iov \sphinxhyphen{} Encrypt data in place supporting AEAD (operates on keyblock).} +\label{\detokenize{appdev/refs/api/krb5_c_encrypt_iov:krb5-c-encrypt-iov-encrypt-data-in-place-supporting-aead-operates-on-keyblock}}\label{\detokenize{appdev/refs/api/krb5_c_encrypt_iov::doc}}\index{krb5\_c\_encrypt\_iov (C function)@\spxentry{krb5\_c\_encrypt\_iov}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_encrypt_iov:c.krb5_c_encrypt_iov}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_encrypt\_iov}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{keyblock}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cipher\_state}, {\hyperref[\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov}]{\sphinxcrossref{\DUrole{n}{krb5\_crypto\_iov}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{num\_data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keyblock} \sphinxhyphen{} Encryption key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cipher\_state} \sphinxhyphen{} Cipher state; specify NULL if not needed + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{data} \sphinxhyphen{} IOV array. Modified in\sphinxhyphen{}place. + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{num\_data} \sphinxhyphen{} Size of \sphinxstyleemphasis{data} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function encrypts the data block \sphinxstyleemphasis{data} and stores the output in\sphinxhyphen{}place. The actual encryption key will be derived from \sphinxstyleemphasis{keyblock} and \sphinxstyleemphasis{usage} if key derivation is specified for the encryption type. If non\sphinxhyphen{}null, \sphinxstyleemphasis{cipher\_state} specifies the beginning state for the encryption operation, and is updated with the state to be passed as input to the next operation. The caller must allocate the right number of krb5\_crypto\_iov structures before calling into this API. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_c\_decrypt\_iov() + + + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +On return from a krb5\_c\_encrypt\_iov() call, the \sphinxstyleemphasis{data\sphinxhyphen{}\textgreater{}length} in the iov structure are adjusted to reflect actual lengths of the ciphertext used. For example, if the padding length is too large, the length will be reduced. Lengths are never increased. +\end{sphinxadmonition} + + +\subsubsection{krb5\_c\_encrypt\_length \sphinxhyphen{} Compute encrypted data length.} +\label{\detokenize{appdev/refs/api/krb5_c_encrypt_length:krb5-c-encrypt-length-compute-encrypted-data-length}}\label{\detokenize{appdev/refs/api/krb5_c_encrypt_length::doc}}\index{krb5\_c\_encrypt\_length (C function)@\spxentry{krb5\_c\_encrypt\_length}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_encrypt_length:c.krb5_c_encrypt_length}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_encrypt\_length}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{inputlen}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{length}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{inputlen} \sphinxhyphen{} Length of the data to be encrypted + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{length} \sphinxhyphen{} Length of the encrypted data + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function computes the length of the ciphertext produced by encrypting \sphinxstyleemphasis{inputlen} bytes including padding, confounder, and checksum. + + +\subsubsection{krb5\_c\_enctype\_compare \sphinxhyphen{} Compare two encryption types.} +\label{\detokenize{appdev/refs/api/krb5_c_enctype_compare:krb5-c-enctype-compare-compare-two-encryption-types}}\label{\detokenize{appdev/refs/api/krb5_c_enctype_compare::doc}}\index{krb5\_c\_enctype\_compare (C function)@\spxentry{krb5\_c\_enctype\_compare}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_enctype_compare:c.krb5_c_enctype_compare}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_enctype\_compare}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{e1}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{e2}, {\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{similar}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{e1} \sphinxhyphen{} First encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{e2} \sphinxhyphen{} Second encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{similar} \sphinxhyphen{} \sphinxstylestrong{TRUE} if types are similar, \sphinxstylestrong{FALSE} if not + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function determines whether two encryption types use the same kind of keys. + + +\subsubsection{krb5\_c\_free\_state \sphinxhyphen{} Free a cipher state previously allocated by krb5\_c\_init\_state().} +\label{\detokenize{appdev/refs/api/krb5_c_free_state:krb5-c-free-state-free-a-cipher-state-previously-allocated-by-krb5-c-init-state}}\label{\detokenize{appdev/refs/api/krb5_c_free_state::doc}}\index{krb5\_c\_free\_state (C function)@\spxentry{krb5\_c\_free\_state}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_free_state:c.krb5_c_free_state}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_free\_state}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{state}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{state} \sphinxhyphen{} Cipher state to be freed + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_c\_fx\_cf2\_simple \sphinxhyphen{} Compute the KRB\sphinxhyphen{}FX\sphinxhyphen{}CF2 combination of two keys and pepper strings.} +\label{\detokenize{appdev/refs/api/krb5_c_fx_cf2_simple:krb5-c-fx-cf2-simple-compute-the-krb-fx-cf2-combination-of-two-keys-and-pepper-strings}}\label{\detokenize{appdev/refs/api/krb5_c_fx_cf2_simple::doc}}\index{krb5\_c\_fx\_cf2\_simple (C function)@\spxentry{krb5\_c\_fx\_cf2\_simple}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_fx_cf2_simple:c.krb5_c_fx_cf2_simple}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_fx\_cf2\_simple}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{k1}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{pepper1}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{k2}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{pepper2}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{k1} \sphinxhyphen{} KDC contribution key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pepper1} \sphinxhyphen{} String”PKINIT” + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{k2} \sphinxhyphen{} Reply key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{pepper2} \sphinxhyphen{} String”KeyExchange” + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{out} \sphinxhyphen{} Output key + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function computes the KRB\sphinxhyphen{}FX\sphinxhyphen{}CF2 function over its inputs and places the results in a newly allocated keyblock. This function is simple in that it assumes that \sphinxstyleemphasis{pepper1} and \sphinxstyleemphasis{pepper2} are C strings with no internal nulls and that the enctype of the result will be the same as that of \sphinxstyleemphasis{k1} . \sphinxstyleemphasis{k1} and \sphinxstyleemphasis{k2} may be of different enctypes. + + +\subsubsection{krb5\_c\_init\_state \sphinxhyphen{} Initialize a new cipher state.} +\label{\detokenize{appdev/refs/api/krb5_c_init_state:krb5-c-init-state-initialize-a-new-cipher-state}}\label{\detokenize{appdev/refs/api/krb5_c_init_state::doc}}\index{krb5\_c\_init\_state (C function)@\spxentry{krb5\_c\_init\_state}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_init_state:c.krb5_c_init_state}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_init\_state}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{new\_state}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{new\_state} \sphinxhyphen{} New cipher state + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_c\_is\_coll\_proof\_cksum \sphinxhyphen{} Test whether a checksum type is collision\sphinxhyphen{}proof.} +\label{\detokenize{appdev/refs/api/krb5_c_is_coll_proof_cksum:krb5-c-is-coll-proof-cksum-test-whether-a-checksum-type-is-collision-proof}}\label{\detokenize{appdev/refs/api/krb5_c_is_coll_proof_cksum::doc}}\index{krb5\_c\_is\_coll\_proof\_cksum (C function)@\spxentry{krb5\_c\_is\_coll\_proof\_cksum}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_is_coll_proof_cksum:c.krb5_c_is_coll_proof_cksum}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_is\_coll\_proof\_cksum}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{ctype}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctype} \sphinxhyphen{} Checksum type + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if ctype is collision\sphinxhyphen{}proof, FALSE if it is not collision\sphinxhyphen{}proof or not a valid checksum type. + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_c\_is\_keyed\_cksum \sphinxhyphen{} Test whether a checksum type is keyed.} +\label{\detokenize{appdev/refs/api/krb5_c_is_keyed_cksum:krb5-c-is-keyed-cksum-test-whether-a-checksum-type-is-keyed}}\label{\detokenize{appdev/refs/api/krb5_c_is_keyed_cksum::doc}}\index{krb5\_c\_is\_keyed\_cksum (C function)@\spxentry{krb5\_c\_is\_keyed\_cksum}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_is_keyed_cksum:c.krb5_c_is_keyed_cksum}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_is\_keyed\_cksum}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{ctype}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctype} \sphinxhyphen{} Checksum type + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if ctype is a keyed checksum type, FALSE otherwise. + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_c\_keyed\_checksum\_types \sphinxhyphen{} Return a list of keyed checksum types usable with an encryption type.} +\label{\detokenize{appdev/refs/api/krb5_c_keyed_checksum_types:krb5-c-keyed-checksum-types-return-a-list-of-keyed-checksum-types-usable-with-an-encryption-type}}\label{\detokenize{appdev/refs/api/krb5_c_keyed_checksum_types::doc}}\index{krb5\_c\_keyed\_checksum\_types (C function)@\spxentry{krb5\_c\_keyed\_checksum\_types}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_keyed_checksum_types:c.krb5_c_keyed_checksum_types}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_keyed\_checksum\_types}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{count}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{cksumtypes}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{count} \sphinxhyphen{} Count of allowable checksum types + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{cksumtypes} \sphinxhyphen{} Array of allowable checksum types + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Use krb5\_free\_cksumtypes() to free \sphinxstyleemphasis{cksumtypes} when it is no longer needed. + + +\subsubsection{krb5\_c\_keylengths \sphinxhyphen{} Return length of the specified key in bytes.} +\label{\detokenize{appdev/refs/api/krb5_c_keylengths:krb5-c-keylengths-return-length-of-the-specified-key-in-bytes}}\label{\detokenize{appdev/refs/api/krb5_c_keylengths::doc}}\index{krb5\_c\_keylengths (C function)@\spxentry{krb5\_c\_keylengths}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_keylengths:c.krb5_c_keylengths}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_keylengths}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{keybytes}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{keylength}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{keybytes} \sphinxhyphen{} Number of bytes required to make a key + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{keylength} \sphinxhyphen{} Length of final key + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_c\_make\_checksum \sphinxhyphen{} Compute a checksum (operates on keyblock).} +\label{\detokenize{appdev/refs/api/krb5_c_make_checksum:krb5-c-make-checksum-compute-a-checksum-operates-on-keyblock}}\label{\detokenize{appdev/refs/api/krb5_c_make_checksum::doc}}\index{krb5\_c\_make\_checksum (C function)@\spxentry{krb5\_c\_make\_checksum}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_make_checksum:c.krb5_c_make_checksum}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_make\_checksum}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{cksumtype}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{input}, {\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cksum}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cksumtype} \sphinxhyphen{} Checksum type (0 for mandatory type) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key for a keyed checksum + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{input} \sphinxhyphen{} Input data + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{cksum} \sphinxhyphen{} Generated checksum + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function computes a checksum of type \sphinxstyleemphasis{cksumtype} over \sphinxstyleemphasis{input} , using \sphinxstyleemphasis{key} if the checksum type is a keyed checksum. If \sphinxstyleemphasis{cksumtype} is 0 and \sphinxstyleemphasis{key} is non\sphinxhyphen{}null, the checksum type will be the mandatory\sphinxhyphen{}to\sphinxhyphen{}implement checksum type for the key’s encryption type. The actual checksum key will be derived from \sphinxstyleemphasis{key} and \sphinxstyleemphasis{usage} if key derivation is specified for the checksum type. The newly created \sphinxstyleemphasis{cksum} must be released by calling krb5\_free\_checksum\_contents() when it is no longer needed. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_c\_verify\_checksum() + + + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +This function is similar to krb5\_k\_make\_checksum(), but operates on keyblock \sphinxstyleemphasis{key} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_c\_make\_checksum\_iov \sphinxhyphen{} Fill in a checksum element in IOV array (operates on keyblock)} +\label{\detokenize{appdev/refs/api/krb5_c_make_checksum_iov:krb5-c-make-checksum-iov-fill-in-a-checksum-element-in-iov-array-operates-on-keyblock}}\label{\detokenize{appdev/refs/api/krb5_c_make_checksum_iov::doc}}\index{krb5\_c\_make\_checksum\_iov (C function)@\spxentry{krb5\_c\_make\_checksum\_iov}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_make_checksum_iov:c.krb5_c_make_checksum_iov}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_make\_checksum\_iov}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{cksumtype}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, {\hyperref[\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov}]{\sphinxcrossref{\DUrole{n}{krb5\_crypto\_iov}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{num\_data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cksumtype} \sphinxhyphen{} Checksum type (0 for mandatory type) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key for a keyed checksum + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{data} \sphinxhyphen{} IOV array + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{num\_data} \sphinxhyphen{} Size of \sphinxstyleemphasis{data} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Create a checksum in the \#KRB5\_CRYPTO\_TYPE\_CHECKSUM element over \#KRB5\_CRYPTO\_TYPE\_DATA and \#KRB5\_CRYPTO\_TYPE\_SIGN\_ONLY chunks in \sphinxstyleemphasis{data} . Only the \#KRB5\_CRYPTO\_TYPE\_CHECKSUM region is modified. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_c\_verify\_checksum\_iov() + + + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +This function is similar to krb5\_k\_make\_checksum\_iov(), but operates on keyblock \sphinxstyleemphasis{key} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_c\_make\_random\_key \sphinxhyphen{} Generate an enctype\sphinxhyphen{}specific random encryption key.} +\label{\detokenize{appdev/refs/api/krb5_c_make_random_key:krb5-c-make-random-key-generate-an-enctype-specific-random-encryption-key}}\label{\detokenize{appdev/refs/api/krb5_c_make_random_key::doc}}\index{krb5\_c\_make\_random\_key (C function)@\spxentry{krb5\_c\_make\_random\_key}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_make_random_key:c.krb5_c_make_random_key}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_make\_random\_key}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{k5\_random\_key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type of the generated key + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{k5\_random\_key} \sphinxhyphen{} An allocated and initialized keyblock + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Use krb5\_free\_keyblock\_contents() to free \sphinxstyleemphasis{k5\_random\_key} when no longer needed. + + +\subsubsection{krb5\_c\_padding\_length \sphinxhyphen{} Return a number of padding octets.} +\label{\detokenize{appdev/refs/api/krb5_c_padding_length:krb5-c-padding-length-return-a-number-of-padding-octets}}\label{\detokenize{appdev/refs/api/krb5_c_padding_length::doc}}\index{krb5\_c\_padding\_length (C function)@\spxentry{krb5\_c\_padding\_length}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_padding_length:c.krb5_c_padding_length}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_padding\_length}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{data\_length}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{size}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data\_length} \sphinxhyphen{} Length of the plaintext to pad + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{size} \sphinxhyphen{} Number of padding octets + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} KRB5\_BAD\_ENCTYPE + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function returns the number of the padding octets required to pad \sphinxstyleemphasis{data\_length} octets of plaintext. + + +\subsubsection{krb5\_c\_prf \sphinxhyphen{} Generate enctype\sphinxhyphen{}specific pseudo\sphinxhyphen{}random bytes.} +\label{\detokenize{appdev/refs/api/krb5_c_prf:krb5-c-prf-generate-enctype-specific-pseudo-random-bytes}}\label{\detokenize{appdev/refs/api/krb5_c_prf::doc}}\index{krb5\_c\_prf (C function)@\spxentry{krb5\_c\_prf}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_prf:c.krb5_c_prf}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_prf}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{keyblock}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{input}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{output}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keyblock} \sphinxhyphen{} Key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{input} \sphinxhyphen{} Input data + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{output} \sphinxhyphen{} Output data + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function selects a pseudo\sphinxhyphen{}random function based on \sphinxstyleemphasis{keyblock} and computes its value over \sphinxstyleemphasis{input} , placing the result into \sphinxstyleemphasis{output} . The caller must preinitialize \sphinxstyleemphasis{output} and allocate space for the result, using krb5\_c\_prf\_length() to determine the required length. + + +\subsubsection{krb5\_c\_prfplus \sphinxhyphen{} Generate pseudo\sphinxhyphen{}random bytes using RFC 6113 PRF+.} +\label{\detokenize{appdev/refs/api/krb5_c_prfplus:krb5-c-prfplus-generate-pseudo-random-bytes-using-rfc-6113-prf}}\label{\detokenize{appdev/refs/api/krb5_c_prfplus::doc}}\index{krb5\_c\_prfplus (C function)@\spxentry{krb5\_c\_prfplus}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_prfplus:c.krb5_c_prfplus}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_prfplus}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{k}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{input}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{output}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{k} \sphinxhyphen{} KDC contribution key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{input} \sphinxhyphen{} Input data + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{output} \sphinxhyphen{} Pseudo\sphinxhyphen{}random output buffer + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 on success, E2BIG if output\sphinxhyphen{}\textgreater{}length is too large for PRF+ to generate, ENOMEM on allocation failure, or an error code from krb5\_c\_prf() + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function fills \sphinxstyleemphasis{output} with PRF+(k, input) as defined in RFC 6113 section 5.1. The caller must preinitialize \sphinxstyleemphasis{output} and allocate the desired amount of space. The length of the pseudo\sphinxhyphen{}random output will match the length of \sphinxstyleemphasis{output} . + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +RFC 4402 defines a different PRF+ operation. This function does not implement that operation. +\end{sphinxadmonition} + + +\subsubsection{krb5\_c\_prf\_length \sphinxhyphen{} Get the output length of pseudo\sphinxhyphen{}random functions for an encryption type.} +\label{\detokenize{appdev/refs/api/krb5_c_prf_length:krb5-c-prf-length-get-the-output-length-of-pseudo-random-functions-for-an-encryption-type}}\label{\detokenize{appdev/refs/api/krb5_c_prf_length::doc}}\index{krb5\_c\_prf\_length (C function)@\spxentry{krb5\_c\_prf\_length}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_prf_length:c.krb5_c_prf_length}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_prf\_length}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{len}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{len} \sphinxhyphen{} Length of PRF output + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_c\_random\_add\_entropy} +\label{\detokenize{appdev/refs/api/krb5_c_random_add_entropy:krb5-c-random-add-entropy}}\label{\detokenize{appdev/refs/api/krb5_c_random_add_entropy::doc}}\index{krb5\_c\_random\_add\_entropy (C function)@\spxentry{krb5\_c\_random\_add\_entropy}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_random_add_entropy:c.krb5_c_random_add_entropy}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_random\_add\_entropy}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{randsource}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{randsource} + +\sphinxAtStartPar +\sphinxstylestrong{data} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED This call is no longer necessary. + + +\subsubsection{krb5\_c\_random\_make\_octets \sphinxhyphen{} Generate pseudo\sphinxhyphen{}random bytes.} +\label{\detokenize{appdev/refs/api/krb5_c_random_make_octets:krb5-c-random-make-octets-generate-pseudo-random-bytes}}\label{\detokenize{appdev/refs/api/krb5_c_random_make_octets::doc}}\index{krb5\_c\_random\_make\_octets (C function)@\spxentry{krb5\_c\_random\_make\_octets}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_random_make_octets:c.krb5_c_random_make_octets}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_random\_make\_octets}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{data} \sphinxhyphen{} Random data + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Fills in \sphinxstyleemphasis{data} with bytes from the PRNG used by krb5 crypto operations. The caller must preinitialize \sphinxstyleemphasis{data} and allocate the desired amount of space. + + +\subsubsection{krb5\_c\_random\_os\_entropy} +\label{\detokenize{appdev/refs/api/krb5_c_random_os_entropy:krb5-c-random-os-entropy}}\label{\detokenize{appdev/refs/api/krb5_c_random_os_entropy::doc}}\index{krb5\_c\_random\_os\_entropy (C function)@\spxentry{krb5\_c\_random\_os\_entropy}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_random_os_entropy:c.krb5_c_random_os_entropy}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_random\_os\_entropy}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{strong}, \DUrole{kt}{int}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{success}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{strong} + +\sphinxAtStartPar +\sphinxstylestrong{success} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED This call is no longer necessary. + + +\subsubsection{krb5\_c\_random\_to\_key \sphinxhyphen{} Generate an enctype\sphinxhyphen{}specific key from random data.} +\label{\detokenize{appdev/refs/api/krb5_c_random_to_key:krb5-c-random-to-key-generate-an-enctype-specific-key-from-random-data}}\label{\detokenize{appdev/refs/api/krb5_c_random_to_key::doc}}\index{krb5\_c\_random\_to\_key (C function)@\spxentry{krb5\_c\_random\_to\_key}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_random_to_key:c.krb5_c_random_to_key}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_random\_to\_key}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{random\_data}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{k5\_random\_key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{random\_data} \sphinxhyphen{} Random input data + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{k5\_random\_key} \sphinxhyphen{} Resulting key + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function takes random input data \sphinxstyleemphasis{random\_data} and produces a valid key \sphinxstyleemphasis{k5\_random\_key} for a given \sphinxstyleemphasis{enctype} . + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_c\_keylengths() + + + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +It is assumed that \sphinxstyleemphasis{k5\_random\_key} has already been initialized and \sphinxstyleemphasis{k5\_random\_key\sphinxhyphen{}\textgreater{}contents} has been allocated with the correct length. +\end{sphinxadmonition} + + +\subsubsection{krb5\_c\_string\_to\_key \sphinxhyphen{} Convert a string (such a password) to a key.} +\label{\detokenize{appdev/refs/api/krb5_c_string_to_key:krb5-c-string-to-key-convert-a-string-such-a-password-to-a-key}}\label{\detokenize{appdev/refs/api/krb5_c_string_to_key::doc}}\index{krb5\_c\_string\_to\_key (C function)@\spxentry{krb5\_c\_string\_to\_key}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_string_to_key:c.krb5_c_string_to_key}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_string\_to\_key}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{string}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{salt}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{string} \sphinxhyphen{} String to be converted + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{salt} \sphinxhyphen{} Salt value + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{key} \sphinxhyphen{} Generated key + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function converts \sphinxstyleemphasis{string} to a \sphinxstyleemphasis{key} of encryption type \sphinxstyleemphasis{enctype} , using the specified \sphinxstyleemphasis{salt} . The newly created \sphinxstyleemphasis{key} must be released by calling krb5\_free\_keyblock\_contents() when it is no longer needed. + + +\subsubsection{krb5\_c\_string\_to\_key\_with\_params \sphinxhyphen{} Convert a string (such as a password) to a key with additional parameters.} +\label{\detokenize{appdev/refs/api/krb5_c_string_to_key_with_params:krb5-c-string-to-key-with-params-convert-a-string-such-as-a-password-to-a-key-with-additional-parameters}}\label{\detokenize{appdev/refs/api/krb5_c_string_to_key_with_params::doc}}\index{krb5\_c\_string\_to\_key\_with\_params (C function)@\spxentry{krb5\_c\_string\_to\_key\_with\_params}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_string_to_key_with_params:c.krb5_c_string_to_key_with_params}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_string\_to\_key\_with\_params}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{string}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{salt}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{params}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{string} \sphinxhyphen{} String to be converted + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{salt} \sphinxhyphen{} Salt value + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{params} \sphinxhyphen{} Parameters + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{key} \sphinxhyphen{} Generated key + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function is similar to krb5\_c\_string\_to\_key(), but also takes parameters which may affect the algorithm in an enctype\sphinxhyphen{}dependent way. The newly created \sphinxstyleemphasis{key} must be released by calling krb5\_free\_keyblock\_contents() when it is no longer needed. + + +\subsubsection{krb5\_c\_valid\_cksumtype \sphinxhyphen{} Verify that specified checksum type is a valid Kerberos checksum type.} +\label{\detokenize{appdev/refs/api/krb5_c_valid_cksumtype:krb5-c-valid-cksumtype-verify-that-specified-checksum-type-is-a-valid-kerberos-checksum-type}}\label{\detokenize{appdev/refs/api/krb5_c_valid_cksumtype::doc}}\index{krb5\_c\_valid\_cksumtype (C function)@\spxentry{krb5\_c\_valid\_cksumtype}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_valid_cksumtype:c.krb5_c_valid_cksumtype}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_valid\_cksumtype}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{ctype}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ctype} \sphinxhyphen{} Checksum type + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if ctype is valid, FALSE if not + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_c\_valid\_enctype \sphinxhyphen{} Verify that a specified encryption type is a valid Kerberos encryption type.} +\label{\detokenize{appdev/refs/api/krb5_c_valid_enctype:krb5-c-valid-enctype-verify-that-a-specified-encryption-type-is-a-valid-kerberos-encryption-type}}\label{\detokenize{appdev/refs/api/krb5_c_valid_enctype::doc}}\index{krb5\_c\_valid\_enctype (C function)@\spxentry{krb5\_c\_valid\_enctype}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_valid_enctype:c.krb5_c_valid_enctype}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_valid\_enctype}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{ktype}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ktype} \sphinxhyphen{} Encryption type + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{return}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +TRUE if ktype is valid, FALSE if not + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_c\_verify\_checksum \sphinxhyphen{} Verify a checksum (operates on keyblock).} +\label{\detokenize{appdev/refs/api/krb5_c_verify_checksum:krb5-c-verify-checksum-verify-a-checksum-operates-on-keyblock}}\label{\detokenize{appdev/refs/api/krb5_c_verify_checksum::doc}}\index{krb5\_c\_verify\_checksum (C function)@\spxentry{krb5\_c\_verify\_checksum}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_verify_checksum:c.krb5_c_verify_checksum}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_verify\_checksum}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cksum}, {\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{valid}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key for a keyed checksum + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} \sphinxstyleemphasis{key} usage + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} Data to be used to compute a new checksum using \sphinxstyleemphasis{key} to compare \sphinxstyleemphasis{cksum} against + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cksum} \sphinxhyphen{} Checksum to be verified + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{valid} \sphinxhyphen{} Non\sphinxhyphen{}zero for success, zero for failure + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function verifies that \sphinxstyleemphasis{cksum} is a valid checksum for \sphinxstyleemphasis{data} . If the checksum type of \sphinxstyleemphasis{cksum} is a keyed checksum, \sphinxstyleemphasis{key} is used to verify the checksum. If the checksum type in \sphinxstyleemphasis{cksum} is 0 and \sphinxstyleemphasis{key} is not NULL, the mandatory checksum type for \sphinxstyleemphasis{key} will be used. The actual checksum key will be derived from \sphinxstyleemphasis{key} and \sphinxstyleemphasis{usage} if key derivation is specified for the checksum type. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +This function is similar to krb5\_k\_verify\_checksum(), but operates on keyblock \sphinxstyleemphasis{key} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_c\_verify\_checksum\_iov \sphinxhyphen{} Validate a checksum element in IOV array (operates on keyblock).} +\label{\detokenize{appdev/refs/api/krb5_c_verify_checksum_iov:krb5-c-verify-checksum-iov-validate-a-checksum-element-in-iov-array-operates-on-keyblock}}\label{\detokenize{appdev/refs/api/krb5_c_verify_checksum_iov::doc}}\index{krb5\_c\_verify\_checksum\_iov (C function)@\spxentry{krb5\_c\_verify\_checksum\_iov}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_verify_checksum_iov:c.krb5_c_verify_checksum_iov}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_verify\_checksum\_iov}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{cksumtype}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov}]{\sphinxcrossref{\DUrole{n}{krb5\_crypto\_iov}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{num\_data}, {\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{valid}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cksumtype} \sphinxhyphen{} Checksum type (0 for mandatory type) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key for a keyed checksum + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} IOV array + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{num\_data} \sphinxhyphen{} Size of \sphinxstyleemphasis{data} + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{valid} \sphinxhyphen{} Non\sphinxhyphen{}zero for success, zero for failure + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Confirm that the checksum in the \#KRB5\_CRYPTO\_TYPE\_CHECKSUM element is a valid checksum of the \#KRB5\_CRYPTO\_TYPE\_DATA and \#KRB5\_CRYPTO\_TYPE\_SIGN\_ONLY regions in the iov. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_c\_make\_checksum\_iov() + + + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +This function is similar to krb5\_k\_verify\_checksum\_iov(), but operates on keyblock \sphinxstyleemphasis{key} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_cksumtype\_to\_string \sphinxhyphen{} Convert a checksum type to a string.} +\label{\detokenize{appdev/refs/api/krb5_cksumtype_to_string:krb5-cksumtype-to-string-convert-a-checksum-type-to-a-string}}\label{\detokenize{appdev/refs/api/krb5_cksumtype_to_string::doc}}\index{krb5\_cksumtype\_to\_string (C function)@\spxentry{krb5\_cksumtype\_to\_string}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cksumtype_to_string:c.krb5_cksumtype_to_string}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cksumtype\_to\_string}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{cksumtype}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{buffer}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{buflen}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cksumtype} \sphinxhyphen{} Checksum type + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{buffer} \sphinxhyphen{} Buffer to hold converted checksum type + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{buflen} \sphinxhyphen{} Storage available in \sphinxstyleemphasis{buffer} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_decode\_authdata\_container \sphinxhyphen{} Unwrap authorization data.} +\label{\detokenize{appdev/refs/api/krb5_decode_authdata_container:krb5-decode-authdata-container-unwrap-authorization-data}}\label{\detokenize{appdev/refs/api/krb5_decode_authdata_container::doc}}\index{krb5\_decode\_authdata\_container (C function)@\spxentry{krb5\_decode\_authdata\_container}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_decode_authdata_container:c.krb5_decode_authdata_container}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_decode\_authdata\_container}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdatatype:c.krb5_authdatatype}]{\sphinxcrossref{\DUrole{n}{krb5\_authdatatype}}}}\DUrole{w}{ }\DUrole{n}{type}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{container}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{authdata}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{type} \sphinxhyphen{} Container type (see KRB5\_AUTHDATA macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{container} \sphinxhyphen{} Authorization data to be decoded + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{authdata} \sphinxhyphen{} List of decoded authorization data + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_encode\_authdata\_container() + + + + +\subsubsection{krb5\_decode\_ticket \sphinxhyphen{} Decode an ASN.1\sphinxhyphen{}formatted ticket.} +\label{\detokenize{appdev/refs/api/krb5_decode_ticket:krb5-decode-ticket-decode-an-asn-1-formatted-ticket}}\label{\detokenize{appdev/refs/api/krb5_decode_ticket::doc}}\index{krb5\_decode\_ticket (C function)@\spxentry{krb5\_decode\_ticket}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_decode_ticket:c.krb5_decode_ticket}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_decode\_ticket}}}}{\DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{code}, {\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{rep}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{code} \sphinxhyphen{} ASN.1\sphinxhyphen{}formatted ticket + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{rep} \sphinxhyphen{} Decoded ticket information + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_deltat\_to\_string \sphinxhyphen{} Convert a relative time value to a string.} +\label{\detokenize{appdev/refs/api/krb5_deltat_to_string:krb5-deltat-to-string-convert-a-relative-time-value-to-a-string}}\label{\detokenize{appdev/refs/api/krb5_deltat_to_string::doc}}\index{krb5\_deltat\_to\_string (C function)@\spxentry{krb5\_deltat\_to\_string}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_deltat_to_string:c.krb5_deltat_to_string}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_deltat\_to\_string}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_deltat:c.krb5_deltat}]{\sphinxcrossref{\DUrole{n}{krb5\_deltat}}}}\DUrole{w}{ }\DUrole{n}{deltat}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{buffer}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{buflen}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{deltat} \sphinxhyphen{} Relative time value to convert + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{buffer} \sphinxhyphen{} Buffer to hold time string + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{buflen} \sphinxhyphen{} Storage available in \sphinxstyleemphasis{buffer} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_encode\_authdata\_container \sphinxhyphen{} Wrap authorization data in a container.} +\label{\detokenize{appdev/refs/api/krb5_encode_authdata_container:krb5-encode-authdata-container-wrap-authorization-data-in-a-container}}\label{\detokenize{appdev/refs/api/krb5_encode_authdata_container::doc}}\index{krb5\_encode\_authdata\_container (C function)@\spxentry{krb5\_encode\_authdata\_container}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_encode_authdata_container:c.krb5_encode_authdata_container}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_encode\_authdata\_container}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdatatype:c.krb5_authdatatype}]{\sphinxcrossref{\DUrole{n}{krb5\_authdatatype}}}}\DUrole{w}{ }\DUrole{n}{type}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{authdata}, {\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{container}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{type} \sphinxhyphen{} Container type (see KRB5\_AUTHDATA macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{authdata} \sphinxhyphen{} List of authorization data to be encoded + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{container} \sphinxhyphen{} List of encoded authorization data + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +The result is returned in \sphinxstyleemphasis{container} as a single\sphinxhyphen{}element list. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_decode\_authdata\_container() + + + + +\subsubsection{krb5\_enctype\_to\_name \sphinxhyphen{} Convert an encryption type to a name or alias.} +\label{\detokenize{appdev/refs/api/krb5_enctype_to_name:krb5-enctype-to-name-convert-an-encryption-type-to-a-name-or-alias}}\label{\detokenize{appdev/refs/api/krb5_enctype_to_name::doc}}\index{krb5\_enctype\_to\_name (C function)@\spxentry{krb5\_enctype\_to\_name}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_enctype_to_name:c.krb5_enctype_to_name}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_enctype\_to\_name}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, {\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\DUrole{n}{shortest}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{buffer}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{buflen}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{shortest} \sphinxhyphen{} Flag + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{buffer} \sphinxhyphen{} Buffer to hold encryption type string + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{buflen} \sphinxhyphen{} Storage available in \sphinxstyleemphasis{buffer} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +If \sphinxstyleemphasis{shortest} is FALSE, this function returns the enctype’s canonical name (like”aes128\sphinxhyphen{}cts\sphinxhyphen{}hmac\sphinxhyphen{}sha1\sphinxhyphen{}96”). If \sphinxstyleemphasis{shortest} is TRUE, it return the enctype’s shortest alias (like”aes128\sphinxhyphen{}cts”). + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +New in 1.9 +\end{sphinxadmonition} + + +\subsubsection{krb5\_enctype\_to\_string \sphinxhyphen{} Convert an encryption type to a string.} +\label{\detokenize{appdev/refs/api/krb5_enctype_to_string:krb5-enctype-to-string-convert-an-encryption-type-to-a-string}}\label{\detokenize{appdev/refs/api/krb5_enctype_to_string::doc}}\index{krb5\_enctype\_to\_string (C function)@\spxentry{krb5\_enctype\_to\_string}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_enctype_to_string:c.krb5_enctype_to_string}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_enctype\_to\_string}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{buffer}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{buflen}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{enctype} \sphinxhyphen{} Encryption type + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{buffer} \sphinxhyphen{} Buffer to hold encryption type string + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{buflen} \sphinxhyphen{} Storage available in \sphinxstyleemphasis{buffer} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + + +\subsubsection{krb5\_free\_checksum \sphinxhyphen{} Free a krb5\_checksum structure.} +\label{\detokenize{appdev/refs/api/krb5_free_checksum:krb5-free-checksum-free-a-krb5-checksum-structure}}\label{\detokenize{appdev/refs/api/krb5_free_checksum::doc}}\index{krb5\_free\_checksum (C function)@\spxentry{krb5\_free\_checksum}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_checksum:c.krb5_free_checksum}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_checksum}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Checksum structure to be freed + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{val} and the structure itself. + + +\subsubsection{krb5\_free\_checksum\_contents \sphinxhyphen{} Free the contents of a krb5\_checksum structure.} +\label{\detokenize{appdev/refs/api/krb5_free_checksum_contents:krb5-free-checksum-contents-free-the-contents-of-a-krb5-checksum-structure}}\label{\detokenize{appdev/refs/api/krb5_free_checksum_contents::doc}}\index{krb5\_free\_checksum\_contents (C function)@\spxentry{krb5\_free\_checksum\_contents}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_checksum_contents:c.krb5_free_checksum_contents}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_checksum\_contents}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Checksum structure to free contents of + +\end{description}\end{quote} + +\sphinxAtStartPar +This function frees the contents of \sphinxstyleemphasis{val} , but not the structure itself. It sets the checksum’s data pointer to null and (beginning in release 1.19) sets its length to zero. + + +\subsubsection{krb5\_free\_cksumtypes \sphinxhyphen{} Free an array of checksum types.} +\label{\detokenize{appdev/refs/api/krb5_free_cksumtypes:krb5-free-cksumtypes-free-an-array-of-checksum-types}}\label{\detokenize{appdev/refs/api/krb5_free_cksumtypes::doc}}\index{krb5\_free\_cksumtypes (C function)@\spxentry{krb5\_free\_cksumtypes}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_cksumtypes:c.krb5_free_cksumtypes}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_cksumtypes}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{val}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{val} \sphinxhyphen{} Array of checksum types to be freed + +\end{description}\end{quote} + + +\subsubsection{krb5\_free\_tgt\_creds \sphinxhyphen{} Free an array of credential structures.} +\label{\detokenize{appdev/refs/api/krb5_free_tgt_creds:krb5-free-tgt-creds-free-an-array-of-credential-structures}}\label{\detokenize{appdev/refs/api/krb5_free_tgt_creds::doc}}\index{krb5\_free\_tgt\_creds (C function)@\spxentry{krb5\_free\_tgt\_creds}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_free_tgt_creds:c.krb5_free_tgt_creds}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_free\_tgt\_creds}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{tgts}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{tgts} \sphinxhyphen{} Null\sphinxhyphen{}terminated array of credentials to free + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The last entry in the array \sphinxstyleemphasis{tgts} must be a NULL pointer. +\end{sphinxadmonition} + + +\subsubsection{krb5\_k\_create\_key \sphinxhyphen{} Create a krb5\_key from the enctype and key data in a keyblock.} +\label{\detokenize{appdev/refs/api/krb5_k_create_key:krb5-k-create-key-create-a-krb5-key-from-the-enctype-and-key-data-in-a-keyblock}}\label{\detokenize{appdev/refs/api/krb5_k_create_key::doc}}\index{krb5\_k\_create\_key (C function)@\spxentry{krb5\_k\_create\_key}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_create_key:c.krb5_k_create_key}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_create\_key}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key\_data}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{out}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key\_data} \sphinxhyphen{} Keyblock + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{out} \sphinxhyphen{} Opaque key + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} KRB5\_BAD\_ENCTYPE + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +The reference count on a key \sphinxstyleemphasis{out} is set to 1. Use krb5\_k\_free\_key() to free \sphinxstyleemphasis{out} when it is no longer needed. + + +\subsubsection{krb5\_k\_decrypt \sphinxhyphen{} Decrypt data using a key (operates on opaque key).} +\label{\detokenize{appdev/refs/api/krb5_k_decrypt:krb5-k-decrypt-decrypt-data-using-a-key-operates-on-opaque-key}}\label{\detokenize{appdev/refs/api/krb5_k_decrypt::doc}}\index{krb5\_k\_decrypt (C function)@\spxentry{krb5\_k\_decrypt}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_decrypt:c.krb5_k_decrypt}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_decrypt}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cipher\_state}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{input}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{output}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{cipher\_state} \sphinxhyphen{} Cipher state; specify NULL if not needed + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{input} \sphinxhyphen{} Encrypted data + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{output} \sphinxhyphen{} Decrypted data + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function decrypts the data block \sphinxstyleemphasis{input} and stores the output into \sphinxstyleemphasis{output} . The actual decryption key will be derived from \sphinxstyleemphasis{key} and \sphinxstyleemphasis{usage} if key derivation is specified for the encryption type. If non\sphinxhyphen{}null, \sphinxstyleemphasis{cipher\_state} specifies the beginning state for the decryption operation, and is updated with the state to be passed as input to the next operation. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The caller must initialize \sphinxstyleemphasis{output} and allocate at least enough space for the result. The usual practice is to allocate an output buffer as long as the ciphertext, and let krb5\_c\_decrypt() trim \sphinxstyleemphasis{output\sphinxhyphen{}\textgreater{}length} . For some enctypes, the resulting \sphinxstyleemphasis{output\sphinxhyphen{}\textgreater{}length} may include padding bytes. +\end{sphinxadmonition} + + +\subsubsection{krb5\_k\_decrypt\_iov \sphinxhyphen{} Decrypt data in place supporting AEAD (operates on opaque key).} +\label{\detokenize{appdev/refs/api/krb5_k_decrypt_iov:krb5-k-decrypt-iov-decrypt-data-in-place-supporting-aead-operates-on-opaque-key}}\label{\detokenize{appdev/refs/api/krb5_k_decrypt_iov::doc}}\index{krb5\_k\_decrypt\_iov (C function)@\spxentry{krb5\_k\_decrypt\_iov}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_decrypt_iov:c.krb5_k_decrypt_iov}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_decrypt\_iov}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cipher\_state}, {\hyperref[\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov}]{\sphinxcrossref{\DUrole{n}{krb5\_crypto\_iov}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{num\_data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cipher\_state} \sphinxhyphen{} Cipher state; specify NULL if not needed + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{data} \sphinxhyphen{} IOV array. Modified in\sphinxhyphen{}place. + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{num\_data} \sphinxhyphen{} Size of \sphinxstyleemphasis{data} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function decrypts the data block \sphinxstyleemphasis{data} and stores the output in\sphinxhyphen{}place. The actual decryption key will be derived from \sphinxstyleemphasis{key} and \sphinxstyleemphasis{usage} if key derivation is specified for the encryption type. If non\sphinxhyphen{}null, \sphinxstyleemphasis{cipher\_state} specifies the beginning state for the decryption operation, and is updated with the state to be passed as input to the next operation. The caller must allocate the right number of krb5\_crypto\_iov structures before calling into this API. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_k\_encrypt\_iov() + + + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +On return from a krb5\_c\_decrypt\_iov() call, the \sphinxstyleemphasis{data\sphinxhyphen{}\textgreater{}length} in the iov structure are adjusted to reflect actual lengths of the ciphertext used. For example, if the padding length is too large, the length will be reduced. Lengths are never increased. +\end{sphinxadmonition} + + +\subsubsection{krb5\_k\_encrypt \sphinxhyphen{} Encrypt data using a key (operates on opaque key).} +\label{\detokenize{appdev/refs/api/krb5_k_encrypt:krb5-k-encrypt-encrypt-data-using-a-key-operates-on-opaque-key}}\label{\detokenize{appdev/refs/api/krb5_k_encrypt::doc}}\index{krb5\_k\_encrypt (C function)@\spxentry{krb5\_k\_encrypt}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_encrypt:c.krb5_k_encrypt}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_encrypt}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cipher\_state}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{input}, {\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{output}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{cipher\_state} \sphinxhyphen{} Cipher state; specify NULL if not needed + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{input} \sphinxhyphen{} Data to be encrypted + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{output} \sphinxhyphen{} Encrypted data + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function encrypts the data block \sphinxstyleemphasis{input} and stores the output into \sphinxstyleemphasis{output} . The actual encryption key will be derived from \sphinxstyleemphasis{key} and \sphinxstyleemphasis{usage} if key derivation is specified for the encryption type. If non\sphinxhyphen{}null, \sphinxstyleemphasis{cipher\_state} specifies the beginning state for the encryption operation, and is updated with the state to be passed as input to the next operation. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +The caller must initialize \sphinxstyleemphasis{output} and allocate at least enough space for the result (using krb5\_c\_encrypt\_length() to determine the amount of space needed). \sphinxstyleemphasis{output\sphinxhyphen{}\textgreater{}length} will be set to the actual length of the ciphertext. +\end{sphinxadmonition} + + +\subsubsection{krb5\_k\_encrypt\_iov \sphinxhyphen{} Encrypt data in place supporting AEAD (operates on opaque key).} +\label{\detokenize{appdev/refs/api/krb5_k_encrypt_iov:krb5-k-encrypt-iov-encrypt-data-in-place-supporting-aead-operates-on-opaque-key}}\label{\detokenize{appdev/refs/api/krb5_k_encrypt_iov::doc}}\index{krb5\_k\_encrypt\_iov (C function)@\spxentry{krb5\_k\_encrypt\_iov}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_encrypt_iov:c.krb5_k_encrypt_iov}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_encrypt\_iov}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cipher\_state}, {\hyperref[\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov}]{\sphinxcrossref{\DUrole{n}{krb5\_crypto\_iov}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{num\_data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cipher\_state} \sphinxhyphen{} Cipher state; specify NULL if not needed + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{data} \sphinxhyphen{} IOV array. Modified in\sphinxhyphen{}place. + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{num\_data} \sphinxhyphen{} Size of \sphinxstyleemphasis{data} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function encrypts the data block \sphinxstyleemphasis{data} and stores the output in\sphinxhyphen{}place. The actual encryption key will be derived from \sphinxstyleemphasis{key} and \sphinxstyleemphasis{usage} if key derivation is specified for the encryption type. If non\sphinxhyphen{}null, \sphinxstyleemphasis{cipher\_state} specifies the beginning state for the encryption operation, and is updated with the state to be passed as input to the next operation. The caller must allocate the right number of krb5\_crypto\_iov structures before calling into this API. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_k\_decrypt\_iov() + + + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +On return from a krb5\_c\_encrypt\_iov() call, the \sphinxstyleemphasis{data\sphinxhyphen{}\textgreater{}length} in the iov structure are adjusted to reflect actual lengths of the ciphertext used. For example, if the padding length is too large, the length will be reduced. Lengths are never increased. +\end{sphinxadmonition} + + +\subsubsection{krb5\_k\_free\_key \sphinxhyphen{} Decrement the reference count on a key and free it if it hits zero.} +\label{\detokenize{appdev/refs/api/krb5_k_free_key:krb5-k-free-key-decrement-the-reference-count-on-a-key-and-free-it-if-it-hits-zero}}\label{\detokenize{appdev/refs/api/krb5_k_free_key::doc}}\index{krb5\_k\_free\_key (C function)@\spxentry{krb5\_k\_free\_key}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_free_key:c.krb5_k_free_key}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_free\_key}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{key} + +\end{description}\end{quote} + + +\subsubsection{krb5\_k\_key\_enctype \sphinxhyphen{} Retrieve the enctype of a krb5\_key structure.} +\label{\detokenize{appdev/refs/api/krb5_k_key_enctype:krb5-k-key-enctype-retrieve-the-enctype-of-a-krb5-key-structure}}\label{\detokenize{appdev/refs/api/krb5_k_key_enctype::doc}}\index{krb5\_k\_key\_enctype (C function)@\spxentry{krb5\_k\_key\_enctype}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_key_enctype:c.krb5_k_key_enctype}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_key\_enctype}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{key} + +\end{description}\end{quote} + + +\subsubsection{krb5\_k\_key\_keyblock \sphinxhyphen{} Retrieve a copy of the keyblock from a krb5\_key structure.} +\label{\detokenize{appdev/refs/api/krb5_k_key_keyblock:krb5-k-key-keyblock-retrieve-a-copy-of-the-keyblock-from-a-krb5-key-structure}}\label{\detokenize{appdev/refs/api/krb5_k_key_keyblock::doc}}\index{krb5\_k\_key\_keyblock (C function)@\spxentry{krb5\_k\_key\_keyblock}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_key_keyblock:c.krb5_k_key_keyblock}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_key\_keyblock}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{key\_data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{key} + +\sphinxAtStartPar +\sphinxstylestrong{key\_data} + +\end{description}\end{quote} + + +\subsubsection{krb5\_k\_make\_checksum \sphinxhyphen{} Compute a checksum (operates on opaque key).} +\label{\detokenize{appdev/refs/api/krb5_k_make_checksum:krb5-k-make-checksum-compute-a-checksum-operates-on-opaque-key}}\label{\detokenize{appdev/refs/api/krb5_k_make_checksum::doc}}\index{krb5\_k\_make\_checksum (C function)@\spxentry{krb5\_k\_make\_checksum}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_make_checksum:c.krb5_k_make_checksum}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_make\_checksum}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{cksumtype}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{input}, {\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cksum}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cksumtype} \sphinxhyphen{} Checksum type (0 for mandatory type) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key for a keyed checksum + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{input} \sphinxhyphen{} Input data + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{cksum} \sphinxhyphen{} Generated checksum + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function computes a checksum of type \sphinxstyleemphasis{cksumtype} over \sphinxstyleemphasis{input} , using \sphinxstyleemphasis{key} if the checksum type is a keyed checksum. If \sphinxstyleemphasis{cksumtype} is 0 and \sphinxstyleemphasis{key} is non\sphinxhyphen{}null, the checksum type will be the mandatory\sphinxhyphen{}to\sphinxhyphen{}implement checksum type for the key’s encryption type. The actual checksum key will be derived from \sphinxstyleemphasis{key} and \sphinxstyleemphasis{usage} if key derivation is specified for the checksum type. The newly created \sphinxstyleemphasis{cksum} must be released by calling krb5\_free\_checksum\_contents() when it is no longer needed. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_c\_verify\_checksum() + + + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +This function is similar to krb5\_c\_make\_checksum(), but operates on opaque \sphinxstyleemphasis{key} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_k\_make\_checksum\_iov \sphinxhyphen{} Fill in a checksum element in IOV array (operates on opaque key)} +\label{\detokenize{appdev/refs/api/krb5_k_make_checksum_iov:krb5-k-make-checksum-iov-fill-in-a-checksum-element-in-iov-array-operates-on-opaque-key}}\label{\detokenize{appdev/refs/api/krb5_k_make_checksum_iov::doc}}\index{krb5\_k\_make\_checksum\_iov (C function)@\spxentry{krb5\_k\_make\_checksum\_iov}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_make_checksum_iov:c.krb5_k_make_checksum_iov}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_make\_checksum\_iov}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{cksumtype}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, {\hyperref[\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov}]{\sphinxcrossref{\DUrole{n}{krb5\_crypto\_iov}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{num\_data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cksumtype} \sphinxhyphen{} Checksum type (0 for mandatory type) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key for a keyed checksum + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{data} \sphinxhyphen{} IOV array + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{num\_data} \sphinxhyphen{} Size of \sphinxstyleemphasis{data} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Create a checksum in the \#KRB5\_CRYPTO\_TYPE\_CHECKSUM element over \#KRB5\_CRYPTO\_TYPE\_DATA and \#KRB5\_CRYPTO\_TYPE\_SIGN\_ONLY chunks in \sphinxstyleemphasis{data} . Only the \#KRB5\_CRYPTO\_TYPE\_CHECKSUM region is modified. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_k\_verify\_checksum\_iov() + + + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +This function is similar to krb5\_c\_make\_checksum\_iov(), but operates on opaque \sphinxstyleemphasis{key} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_k\_prf \sphinxhyphen{} Generate enctype\sphinxhyphen{}specific pseudo\sphinxhyphen{}random bytes (operates on opaque key).} +\label{\detokenize{appdev/refs/api/krb5_k_prf:krb5-k-prf-generate-enctype-specific-pseudo-random-bytes-operates-on-opaque-key}}\label{\detokenize{appdev/refs/api/krb5_k_prf::doc}}\index{krb5\_k\_prf (C function)@\spxentry{krb5\_k\_prf}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_prf:c.krb5_k_prf}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_prf}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{input}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{output}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Key + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{input} \sphinxhyphen{} Input data + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{output} \sphinxhyphen{} Output data + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function selects a pseudo\sphinxhyphen{}random function based on \sphinxstyleemphasis{key} and computes its value over \sphinxstyleemphasis{input} , placing the result into \sphinxstyleemphasis{output} . The caller must preinitialize \sphinxstyleemphasis{output} and allocate space for the result. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +This function is similar to krb5\_c\_prf(), but operates on opaque \sphinxstyleemphasis{key} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_k\_reference\_key \sphinxhyphen{} Increment the reference count on a key.} +\label{\detokenize{appdev/refs/api/krb5_k_reference_key:krb5-k-reference-key-increment-the-reference-count-on-a-key}}\label{\detokenize{appdev/refs/api/krb5_k_reference_key::doc}}\index{krb5\_k\_reference\_key (C function)@\spxentry{krb5\_k\_reference\_key}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_reference_key:c.krb5_k_reference_key}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_reference\_key}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{key} + +\end{description}\end{quote} + + +\subsubsection{krb5\_k\_verify\_checksum \sphinxhyphen{} Verify a checksum (operates on opaque key).} +\label{\detokenize{appdev/refs/api/krb5_k_verify_checksum:krb5-k-verify-checksum-verify-a-checksum-operates-on-opaque-key}}\label{\detokenize{appdev/refs/api/krb5_k_verify_checksum::doc}}\index{krb5\_k\_verify\_checksum (C function)@\spxentry{krb5\_k\_verify\_checksum}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_verify_checksum:c.krb5_k_verify_checksum}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_verify\_checksum}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cksum}, {\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{valid}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key for a keyed checksum + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} \sphinxstyleemphasis{key} usage + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} Data to be used to compute a new checksum using \sphinxstyleemphasis{key} to compare \sphinxstyleemphasis{cksum} against + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cksum} \sphinxhyphen{} Checksum to be verified + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{valid} \sphinxhyphen{} Non\sphinxhyphen{}zero for success, zero for failure + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function verifies that \sphinxstyleemphasis{cksum} is a valid checksum for \sphinxstyleemphasis{data} . If the checksum type of \sphinxstyleemphasis{cksum} is a keyed checksum, \sphinxstyleemphasis{key} is used to verify the checksum. If the checksum type in \sphinxstyleemphasis{cksum} is 0 and \sphinxstyleemphasis{key} is not NULL, the mandatory checksum type for \sphinxstyleemphasis{key} will be used. The actual checksum key will be derived from \sphinxstyleemphasis{key} and \sphinxstyleemphasis{usage} if key derivation is specified for the checksum type. + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +This function is similar to krb5\_c\_verify\_checksum(), but operates on opaque \sphinxstyleemphasis{key} . +\end{sphinxadmonition} + + +\subsubsection{krb5\_k\_verify\_checksum\_iov \sphinxhyphen{} Validate a checksum element in IOV array (operates on opaque key).} +\label{\detokenize{appdev/refs/api/krb5_k_verify_checksum_iov:krb5-k-verify-checksum-iov-validate-a-checksum-element-in-iov-array-operates-on-opaque-key}}\label{\detokenize{appdev/refs/api/krb5_k_verify_checksum_iov::doc}}\index{krb5\_k\_verify\_checksum\_iov (C function)@\spxentry{krb5\_k\_verify\_checksum\_iov}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_k_verify_checksum_iov:c.krb5_k_verify_checksum_iov}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_k\_verify\_checksum\_iov}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{cksumtype}, {\hyperref[\detokenize{appdev/refs/types/krb5_key:c.krb5_key}]{\sphinxcrossref{\DUrole{n}{krb5\_key}}}}\DUrole{w}{ }\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}]{\sphinxcrossref{\DUrole{n}{krb5\_keyusage}}}}\DUrole{w}{ }\DUrole{n}{usage}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov}]{\sphinxcrossref{\DUrole{n}{krb5\_crypto\_iov}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{num\_data}, {\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{valid}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{cksumtype} \sphinxhyphen{} Checksum type (0 for mandatory type) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{key} \sphinxhyphen{} Encryption key for a keyed checksum + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{usage} \sphinxhyphen{} Key usage (see KRB5\_KEYUSAGE macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{data} \sphinxhyphen{} IOV array + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{num\_data} \sphinxhyphen{} Size of \sphinxstyleemphasis{data} + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{valid} \sphinxhyphen{} Non\sphinxhyphen{}zero for success, zero for failure + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Confirm that the checksum in the \#KRB5\_CRYPTO\_TYPE\_CHECKSUM element is a valid checksum of the \#KRB5\_CRYPTO\_TYPE\_DATA and \#KRB5\_CRYPTO\_TYPE\_SIGN\_ONLY regions in the iov. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_k\_make\_checksum\_iov() + + + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +This function is similar to krb5\_c\_verify\_checksum\_iov(), but operates on opaque \sphinxstyleemphasis{key} . +\end{sphinxadmonition} + + +\subsection{Legacy convenience interfaces} +\label{\detokenize{appdev/refs/api/index:legacy-convenience-interfaces}} + +\subsubsection{krb5\_recvauth \sphinxhyphen{} Server function for sendauth protocol.} +\label{\detokenize{appdev/refs/api/krb5_recvauth:krb5-recvauth-server-function-for-sendauth-protocol}}\label{\detokenize{appdev/refs/api/krb5_recvauth::doc}}\index{krb5\_recvauth (C function)@\spxentry{krb5\_recvauth}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_recvauth:c.krb5_recvauth}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_recvauth}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_pointer:c.krb5_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_pointer}}}}\DUrole{w}{ }\DUrole{n}{fd}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{appl\_version}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{server}, {\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\DUrole{n}{flags}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{keytab}, {\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{ticket}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Pre\sphinxhyphen{}existing or newly created auth context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{fd} \sphinxhyphen{} File descriptor + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{appl\_version} \sphinxhyphen{} Application protocol version to be matched against the client’s application version + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server} \sphinxhyphen{} Server principal (NULL for any in \sphinxstyleemphasis{keytab} ) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Additional specifications + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keytab} \sphinxhyphen{} Key table containing service keys + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ticket} \sphinxhyphen{} Ticket (NULL if not needed) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function performs the server side of a sendauth/recvauth exchange by sending and receiving messages over \sphinxstyleemphasis{fd} . + +\sphinxAtStartPar +Use krb5\_free\_ticket() to free \sphinxstyleemphasis{ticket} when it is no longer needed. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_sendauth() + + + + +\subsubsection{krb5\_recvauth\_version \sphinxhyphen{} Server function for sendauth protocol with version parameter.} +\label{\detokenize{appdev/refs/api/krb5_recvauth_version:krb5-recvauth-version-server-function-for-sendauth-protocol-with-version-parameter}}\label{\detokenize{appdev/refs/api/krb5_recvauth_version::doc}}\index{krb5\_recvauth\_version (C function)@\spxentry{krb5\_recvauth\_version}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_recvauth_version:c.krb5_recvauth_version}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_recvauth\_version}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_pointer:c.krb5_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_pointer}}}}\DUrole{w}{ }\DUrole{n}{fd}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{server}, {\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\DUrole{n}{flags}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{keytab}, {\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{ticket}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{version}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Pre\sphinxhyphen{}existing or newly created auth context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{fd} \sphinxhyphen{} File descriptor + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server} \sphinxhyphen{} Server principal (NULL for any in \sphinxstyleemphasis{keytab} ) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{flags} \sphinxhyphen{} Additional specifications + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{keytab} \sphinxhyphen{} Decryption key + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{ticket} \sphinxhyphen{} Ticket (NULL if not needed) + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{version} \sphinxhyphen{} sendauth protocol version (NULL if not needed) + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function is similar to krb5\_recvauth() with the additional output information place into \sphinxstyleemphasis{version} . + + +\subsubsection{krb5\_sendauth \sphinxhyphen{} Client function for sendauth protocol.} +\label{\detokenize{appdev/refs/api/krb5_sendauth:krb5-sendauth-client-function-for-sendauth-protocol}}\label{\detokenize{appdev/refs/api/krb5_sendauth::doc}}\index{krb5\_sendauth (C function)@\spxentry{krb5\_sendauth}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_sendauth:c.krb5_sendauth}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_sendauth}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_pointer:c.krb5_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_pointer}}}}\DUrole{w}{ }\DUrole{n}{fd}, \DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{appl\_version}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{client}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{server}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{ap\_req\_options}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_data}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}, {\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{error}, {\hyperref[\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_rep\_enc\_part}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{rep\_result}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{out\_creds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}inout{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Pre\sphinxhyphen{}existing or newly created auth context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{fd} \sphinxhyphen{} File descriptor that describes network socket + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{appl\_version} \sphinxhyphen{} Application protocol version to be matched with the receiver’s application version + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{client} \sphinxhyphen{} Client principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{server} \sphinxhyphen{} Server principal + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ap\_req\_options} \sphinxhyphen{} Options (see AP\_OPTS macros) + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in\_data} \sphinxhyphen{} Data to be sent to the server + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{in\_creds} \sphinxhyphen{} Input credentials, or NULL to use \sphinxstyleemphasis{ccache} + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{ccache} \sphinxhyphen{} Credential cache + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{error} \sphinxhyphen{} If non\sphinxhyphen{}null, contains KRB\_ERROR message returned from server + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{rep\_result} \sphinxhyphen{} If non\sphinxhyphen{}null and \sphinxstyleemphasis{ap\_req\_options} is \#AP\_OPTS\_MUTUAL\_REQUIRED, contains the result of mutual authentication exchange + +\sphinxAtStartPar +\sphinxstylestrong{{[}out{]}} \sphinxstylestrong{out\_creds} \sphinxhyphen{} If non\sphinxhyphen{}null, the retrieved credentials + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +This function performs the client side of a sendauth/recvauth exchange by sending and receiving messages over \sphinxstyleemphasis{fd} . + +\sphinxAtStartPar +Credentials may be specified in three ways: +\begin{quote} +\begin{itemize} +\item {} +\sphinxAtStartPar +If \sphinxstyleemphasis{in\_creds} is NULL, credentials are obtained with krb5\_get\_credentials() using the principals \sphinxstyleemphasis{client} and \sphinxstyleemphasis{server} . \sphinxstyleemphasis{server} must be non\sphinxhyphen{}null; \sphinxstyleemphasis{client} may NULL to use the default principal of \sphinxstyleemphasis{ccache} . + +\item {} +\sphinxAtStartPar +If \sphinxstyleemphasis{in\_creds} is non\sphinxhyphen{}null, but does not contain a ticket, credentials for the exchange are obtained with krb5\_get\_credentials() using \sphinxstyleemphasis{in\_creds} . In this case, the values of \sphinxstyleemphasis{client} and \sphinxstyleemphasis{server} are unused. + +\item {} +\sphinxAtStartPar +If \sphinxstyleemphasis{in\_creds} is a complete credentials structure, it used directly. In this case, the values of \sphinxstyleemphasis{client} , \sphinxstyleemphasis{server} , and \sphinxstyleemphasis{ccache} are unused. + +\end{itemize} + +\sphinxAtStartPar +If the server is using a different application protocol than that specified in \sphinxstyleemphasis{appl\_version} , an error will be returned. +\end{quote} + +\sphinxAtStartPar +Use krb5\_free\_creds() to free \sphinxstyleemphasis{out\_creds} , krb5\_free\_ap\_rep\_enc\_part() to free \sphinxstyleemphasis{rep\_result} , and krb5\_free\_error() to free \sphinxstyleemphasis{error} when they are no longer needed. + + +\sphinxstrong{See also:} +\nopagebreak + + +\sphinxAtStartPar +krb5\_recvauth() + + + + +\subsection{Deprecated public interfaces} +\label{\detokenize{appdev/refs/api/index:deprecated-public-interfaces}} + +\subsubsection{krb5\_524\_convert\_creds \sphinxhyphen{} Convert a Kerberos V5 credentials to a Kerberos V4 credentials.} +\label{\detokenize{appdev/refs/api/krb5_524_convert_creds:krb5-524-convert-creds-convert-a-kerberos-v5-credentials-to-a-kerberos-v4-credentials}}\label{\detokenize{appdev/refs/api/krb5_524_convert_creds::doc}}\index{krb5\_524\_convert\_creds (C function)@\spxentry{krb5\_524\_convert\_creds}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_524_convert_creds:c.krb5_524_convert_creds}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{int}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_524\_convert\_creds}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{v5creds}, \DUrole{k}{struct}\DUrole{w}{ }\DUrole{n}{credentials}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{v4creds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{v5creds} + +\sphinxAtStartPar +\sphinxstylestrong{v4creds} + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +KRB524\_KRB4\_DISABLED (always) + +\end{itemize} + +\end{description}\end{quote} + +\begin{sphinxadmonition}{note}{Note:} +\sphinxAtStartPar +Not implemented +\end{sphinxadmonition} + + +\subsubsection{krb5\_auth\_con\_getlocalsubkey} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getlocalsubkey:krb5-auth-con-getlocalsubkey}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getlocalsubkey::doc}}\index{krb5\_auth\_con\_getlocalsubkey (C function)@\spxentry{krb5\_auth\_con\_getlocalsubkey}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getlocalsubkey:c.krb5_auth_con_getlocalsubkey}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getlocalsubkey}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{keyblock}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{auth\_context} + +\sphinxAtStartPar +\sphinxstylestrong{keyblock} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_auth\_con\_getsendsubkey(). + + +\subsubsection{krb5\_auth\_con\_getremotesubkey} +\label{\detokenize{appdev/refs/api/krb5_auth_con_getremotesubkey:krb5-auth-con-getremotesubkey}}\label{\detokenize{appdev/refs/api/krb5_auth_con_getremotesubkey::doc}}\index{krb5\_auth\_con\_getremotesubkey (C function)@\spxentry{krb5\_auth\_con\_getremotesubkey}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_getremotesubkey:c.krb5_auth_con_getremotesubkey}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_getremotesubkey}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{keyblock}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{auth\_context} + +\sphinxAtStartPar +\sphinxstylestrong{keyblock} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_auth\_con\_getrecvsubkey(). + + +\subsubsection{krb5\_auth\_con\_initivector \sphinxhyphen{} Cause an auth context to use cipher state.} +\label{\detokenize{appdev/refs/api/krb5_auth_con_initivector:krb5-auth-con-initivector-cause-an-auth-context-to-use-cipher-state}}\label{\detokenize{appdev/refs/api/krb5_auth_con_initivector::doc}}\index{krb5\_auth\_con\_initivector (C function)@\spxentry{krb5\_auth\_con\_initivector}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_auth_con_initivector:c.krb5_auth_con_initivector}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_con\_initivector}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}]{\sphinxcrossref{\DUrole{n}{krb5\_auth\_context}}}}\DUrole{w}{ }\DUrole{n}{auth\_context}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{context} \sphinxhyphen{} Library context + +\sphinxAtStartPar +\sphinxstylestrong{{[}in{]}} \sphinxstylestrong{auth\_context} \sphinxhyphen{} Authentication context + +\end{description}\end{quote} +\begin{quote}\begin{description} +\item[{retval}] \leavevmode\begin{itemize} +\item {} +\sphinxAtStartPar +0 Success; otherwise \sphinxhyphen{} Kerberos error codes + +\end{itemize} + +\end{description}\end{quote} + +\sphinxAtStartPar +Prepare \sphinxstyleemphasis{auth\_context} to use cipher state when krb5\_mk\_priv() or krb5\_rd\_priv() encrypt or decrypt data. + + +\subsubsection{krb5\_build\_principal\_va} +\label{\detokenize{appdev/refs/api/krb5_build_principal_va:krb5-build-principal-va}}\label{\detokenize{appdev/refs/api/krb5_build_principal_va::doc}}\index{krb5\_build\_principal\_va (C function)@\spxentry{krb5\_build\_principal\_va}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_build_principal_va:c.krb5_build_principal_va}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_build\_principal\_va}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\DUrole{n}{princ}, \DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\DUrole{n}{rlen}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{realm}, \DUrole{n}{va\_list}\DUrole{w}{ }\DUrole{n}{ap}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{princ} + +\sphinxAtStartPar +\sphinxstylestrong{rlen} + +\sphinxAtStartPar +\sphinxstylestrong{realm} + +\sphinxAtStartPar +\sphinxstylestrong{ap} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_build\_principal\_alloc\_va(). + + +\subsubsection{krb5\_c\_random\_seed} +\label{\detokenize{appdev/refs/api/krb5_c_random_seed:krb5-c-random-seed}}\label{\detokenize{appdev/refs/api/krb5_c_random_seed::doc}}\index{krb5\_c\_random\_seed (C function)@\spxentry{krb5\_c\_random\_seed}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_c_random_seed:c.krb5_c_random_seed}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_c\_random\_seed}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{data} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED This call is no longer necessary. + + +\subsubsection{krb5\_calculate\_checksum} +\label{\detokenize{appdev/refs/api/krb5_calculate_checksum:krb5-calculate-checksum}}\label{\detokenize{appdev/refs/api/krb5_calculate_checksum::doc}}\index{krb5\_calculate\_checksum (C function)@\spxentry{krb5\_calculate\_checksum}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_calculate_checksum:c.krb5_calculate_checksum}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_calculate\_checksum}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{ctype}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_pointer:c.krb5_const_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_pointer}}}}\DUrole{w}{ }\DUrole{n}{in}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{in\_length}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_pointer:c.krb5_const_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_pointer}}}}\DUrole{w}{ }\DUrole{n}{seed}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{seed\_length}, {\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{outcksum}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{ctype} + +\sphinxAtStartPar +\sphinxstylestrong{in} + +\sphinxAtStartPar +\sphinxstylestrong{in\_length} + +\sphinxAtStartPar +\sphinxstylestrong{seed} + +\sphinxAtStartPar +\sphinxstylestrong{seed\_length} + +\sphinxAtStartPar +\sphinxstylestrong{outcksum} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED See krb5\_c\_make\_checksum() + + +\subsubsection{krb5\_checksum\_size} +\label{\detokenize{appdev/refs/api/krb5_checksum_size:krb5-checksum-size}}\label{\detokenize{appdev/refs/api/krb5_checksum_size::doc}}\index{krb5\_checksum\_size (C function)@\spxentry{krb5\_checksum\_size}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_checksum_size:c.krb5_checksum_size}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{n}{size\_t}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_checksum\_size}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{ctype}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{ctype} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED See krb5\_c\_checksum\_length() + + +\subsubsection{krb5\_encrypt} +\label{\detokenize{appdev/refs/api/krb5_encrypt:krb5-encrypt}}\label{\detokenize{appdev/refs/api/krb5_encrypt::doc}}\index{krb5\_encrypt (C function)@\spxentry{krb5\_encrypt}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_encrypt:c.krb5_encrypt}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_encrypt}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_pointer:c.krb5_const_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_pointer}}}}\DUrole{w}{ }\DUrole{n}{inptr}, {\hyperref[\detokenize{appdev/refs/types/krb5_pointer:c.krb5_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_pointer}}}}\DUrole{w}{ }\DUrole{n}{outptr}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{size}, {\hyperref[\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}]{\sphinxcrossref{\DUrole{n}{krb5\_encrypt\_block}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{eblock}, {\hyperref[\detokenize{appdev/refs/types/krb5_pointer:c.krb5_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_pointer}}}}\DUrole{w}{ }\DUrole{n}{ivec}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{inptr} + +\sphinxAtStartPar +\sphinxstylestrong{outptr} + +\sphinxAtStartPar +\sphinxstylestrong{size} + +\sphinxAtStartPar +\sphinxstylestrong{eblock} + +\sphinxAtStartPar +\sphinxstylestrong{ivec} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_c\_* API family. + + +\subsubsection{krb5\_decrypt} +\label{\detokenize{appdev/refs/api/krb5_decrypt:krb5-decrypt}}\label{\detokenize{appdev/refs/api/krb5_decrypt::doc}}\index{krb5\_decrypt (C function)@\spxentry{krb5\_decrypt}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_decrypt:c.krb5_decrypt}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_decrypt}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_pointer:c.krb5_const_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_pointer}}}}\DUrole{w}{ }\DUrole{n}{inptr}, {\hyperref[\detokenize{appdev/refs/types/krb5_pointer:c.krb5_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_pointer}}}}\DUrole{w}{ }\DUrole{n}{outptr}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{size}, {\hyperref[\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}]{\sphinxcrossref{\DUrole{n}{krb5\_encrypt\_block}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{eblock}, {\hyperref[\detokenize{appdev/refs/types/krb5_pointer:c.krb5_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_pointer}}}}\DUrole{w}{ }\DUrole{n}{ivec}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{inptr} + +\sphinxAtStartPar +\sphinxstylestrong{outptr} + +\sphinxAtStartPar +\sphinxstylestrong{size} + +\sphinxAtStartPar +\sphinxstylestrong{eblock} + +\sphinxAtStartPar +\sphinxstylestrong{ivec} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_c\_* API family. + + +\subsubsection{krb5\_eblock\_enctype} +\label{\detokenize{appdev/refs/api/krb5_eblock_enctype:krb5-eblock-enctype}}\label{\detokenize{appdev/refs/api/krb5_eblock_enctype::doc}}\index{krb5\_eblock\_enctype (C function)@\spxentry{krb5\_eblock\_enctype}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_eblock_enctype:c.krb5_eblock_enctype}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_eblock\_enctype}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}]{\sphinxcrossref{\DUrole{n}{krb5\_encrypt\_block}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{eblock}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{eblock} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_c\_* API family. + + +\subsubsection{krb5\_encrypt\_size} +\label{\detokenize{appdev/refs/api/krb5_encrypt_size:krb5-encrypt-size}}\label{\detokenize{appdev/refs/api/krb5_encrypt_size::doc}}\index{krb5\_encrypt\_size (C function)@\spxentry{krb5\_encrypt\_size}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_encrypt_size:c.krb5_encrypt_size}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{n}{size\_t}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_encrypt\_size}}}}{\DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{length}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{crypto}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{length} + +\sphinxAtStartPar +\sphinxstylestrong{crypto} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_c\_* API family. + + +\subsubsection{krb5\_finish\_key} +\label{\detokenize{appdev/refs/api/krb5_finish_key:krb5-finish-key}}\label{\detokenize{appdev/refs/api/krb5_finish_key::doc}}\index{krb5\_finish\_key (C function)@\spxentry{krb5\_finish\_key}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_finish_key:c.krb5_finish_key}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_finish\_key}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}]{\sphinxcrossref{\DUrole{n}{krb5\_encrypt\_block}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{eblock}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{eblock} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_c\_* API family. + + +\subsubsection{krb5\_finish\_random\_key} +\label{\detokenize{appdev/refs/api/krb5_finish_random_key:krb5-finish-random-key}}\label{\detokenize{appdev/refs/api/krb5_finish_random_key::doc}}\index{krb5\_finish\_random\_key (C function)@\spxentry{krb5\_finish\_random\_key}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_finish_random_key:c.krb5_finish_random_key}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_finish\_random\_key}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}]{\sphinxcrossref{\DUrole{n}{krb5\_encrypt\_block}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{eblock}, {\hyperref[\detokenize{appdev/refs/types/krb5_pointer:c.krb5_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_pointer}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ptr}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{eblock} + +\sphinxAtStartPar +\sphinxstylestrong{ptr} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_c\_* API family. + + +\subsubsection{krb5\_cc\_gen\_new} +\label{\detokenize{appdev/refs/api/krb5_cc_gen_new:krb5-cc-gen-new}}\label{\detokenize{appdev/refs/api/krb5_cc_gen_new::doc}}\index{krb5\_cc\_gen\_new (C function)@\spxentry{krb5\_cc\_gen\_new}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_cc_gen_new:c.krb5_cc_gen_new}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_gen\_new}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cache}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{cache} + +\end{description}\end{quote} + + +\subsubsection{krb5\_get\_credentials\_renew} +\label{\detokenize{appdev/refs/api/krb5_get_credentials_renew:krb5-get-credentials-renew}}\label{\detokenize{appdev/refs/api/krb5_get_credentials_renew::doc}}\index{krb5\_get\_credentials\_renew (C function)@\spxentry{krb5\_get\_credentials\_renew}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_credentials_renew:c.krb5_get_credentials_renew}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_credentials\_renew}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{options}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{out\_creds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{options} + +\sphinxAtStartPar +\sphinxstylestrong{ccache} + +\sphinxAtStartPar +\sphinxstylestrong{in\_creds} + +\sphinxAtStartPar +\sphinxstylestrong{out\_creds} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_get\_renewed\_creds. + + +\subsubsection{krb5\_get\_credentials\_validate} +\label{\detokenize{appdev/refs/api/krb5_get_credentials_validate:krb5-get-credentials-validate}}\label{\detokenize{appdev/refs/api/krb5_get_credentials_validate::doc}}\index{krb5\_get\_credentials\_validate (C function)@\spxentry{krb5\_get\_credentials\_validate}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_credentials_validate:c.krb5_get_credentials_validate}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_credentials\_validate}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{options}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{in\_creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{out\_creds}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{options} + +\sphinxAtStartPar +\sphinxstylestrong{ccache} + +\sphinxAtStartPar +\sphinxstylestrong{in\_creds} + +\sphinxAtStartPar +\sphinxstylestrong{out\_creds} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_get\_validated\_creds. + + +\subsubsection{krb5\_get\_in\_tkt\_with\_password} +\label{\detokenize{appdev/refs/api/krb5_get_in_tkt_with_password:krb5-get-in-tkt-with-password}}\label{\detokenize{appdev/refs/api/krb5_get_in_tkt_with_password::doc}}\index{krb5\_get\_in\_tkt\_with\_password (C function)@\spxentry{krb5\_get\_in\_tkt\_with\_password}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_in_tkt_with_password:c.krb5_get_in_tkt_with_password}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_in\_tkt\_with\_password}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{options}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{addrs}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ktypes}, {\hyperref[\detokenize{appdev/refs/types/krb5_preauthtype:c.krb5_preauthtype}]{\sphinxcrossref{\DUrole{n}{krb5\_preauthtype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{pre\_auth\_types}, \DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{password}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_rep}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{ret\_as\_reply}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{options} + +\sphinxAtStartPar +\sphinxstylestrong{addrs} + +\sphinxAtStartPar +\sphinxstylestrong{ktypes} + +\sphinxAtStartPar +\sphinxstylestrong{pre\_auth\_types} + +\sphinxAtStartPar +\sphinxstylestrong{password} + +\sphinxAtStartPar +\sphinxstylestrong{ccache} + +\sphinxAtStartPar +\sphinxstylestrong{creds} + +\sphinxAtStartPar +\sphinxstylestrong{ret\_as\_reply} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_get\_init\_creds\_password(). + + +\subsubsection{krb5\_get\_in\_tkt\_with\_skey} +\label{\detokenize{appdev/refs/api/krb5_get_in_tkt_with_skey:krb5-get-in-tkt-with-skey}}\label{\detokenize{appdev/refs/api/krb5_get_in_tkt_with_skey::doc}}\index{krb5\_get\_in\_tkt\_with\_skey (C function)@\spxentry{krb5\_get\_in\_tkt\_with\_skey}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_in_tkt_with_skey:c.krb5_get_in_tkt_with_skey}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_in\_tkt\_with\_skey}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{options}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{addrs}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ktypes}, {\hyperref[\detokenize{appdev/refs/types/krb5_preauthtype:c.krb5_preauthtype}]{\sphinxcrossref{\DUrole{n}{krb5\_preauthtype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{pre\_auth\_types}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_rep}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{ret\_as\_reply}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{options} + +\sphinxAtStartPar +\sphinxstylestrong{addrs} + +\sphinxAtStartPar +\sphinxstylestrong{ktypes} + +\sphinxAtStartPar +\sphinxstylestrong{pre\_auth\_types} + +\sphinxAtStartPar +\sphinxstylestrong{key} + +\sphinxAtStartPar +\sphinxstylestrong{ccache} + +\sphinxAtStartPar +\sphinxstylestrong{creds} + +\sphinxAtStartPar +\sphinxstylestrong{ret\_as\_reply} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_get\_init\_creds(). + + +\subsubsection{krb5\_get\_in\_tkt\_with\_keytab} +\label{\detokenize{appdev/refs/api/krb5_get_in_tkt_with_keytab:krb5-get-in-tkt-with-keytab}}\label{\detokenize{appdev/refs/api/krb5_get_in_tkt_with_keytab::doc}}\index{krb5\_get\_in\_tkt\_with\_keytab (C function)@\spxentry{krb5\_get\_in\_tkt\_with\_keytab}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_in_tkt_with_keytab:c.krb5_get_in_tkt_with_keytab}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_in\_tkt\_with\_keytab}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\DUrole{n}{options}, {\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{k}{const}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{addrs}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ktypes}, {\hyperref[\detokenize{appdev/refs/types/krb5_preauthtype:c.krb5_preauthtype}]{\sphinxcrossref{\DUrole{n}{krb5\_preauthtype}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{pre\_auth\_types}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab}}}}\DUrole{w}{ }\DUrole{n}{arg\_keytab}, {\hyperref[\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}]{\sphinxcrossref{\DUrole{n}{krb5\_ccache}}}}\DUrole{w}{ }\DUrole{n}{ccache}, {\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{creds}, {\hyperref[\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_rep}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{ret\_as\_reply}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{options} + +\sphinxAtStartPar +\sphinxstylestrong{addrs} + +\sphinxAtStartPar +\sphinxstylestrong{ktypes} + +\sphinxAtStartPar +\sphinxstylestrong{pre\_auth\_types} + +\sphinxAtStartPar +\sphinxstylestrong{arg\_keytab} + +\sphinxAtStartPar +\sphinxstylestrong{ccache} + +\sphinxAtStartPar +\sphinxstylestrong{creds} + +\sphinxAtStartPar +\sphinxstylestrong{ret\_as\_reply} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_get\_init\_creds\_keytab(). + + +\subsubsection{krb5\_get\_init\_creds\_opt\_init} +\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_init:krb5-get-init-creds-opt-init}}\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_init::doc}}\index{krb5\_get\_init\_creds\_opt\_init (C function)@\spxentry{krb5\_get\_init\_creds\_opt\_init}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_get_init_creds_opt_init:c.krb5_get_init_creds_opt_init}}% +\pysigstartmultiline +\pysiglinewithargsret{\DUrole{kt}{void}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt\_init}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{opt}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{opt} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Use krb5\_get\_init\_creds\_opt\_alloc() instead. + + +\subsubsection{krb5\_init\_random\_key} +\label{\detokenize{appdev/refs/api/krb5_init_random_key:krb5-init-random-key}}\label{\detokenize{appdev/refs/api/krb5_init_random_key::doc}}\index{krb5\_init\_random\_key (C function)@\spxentry{krb5\_init\_random\_key}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_init_random_key:c.krb5_init_random_key}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_random\_key}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}]{\sphinxcrossref{\DUrole{n}{krb5\_encrypt\_block}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{eblock}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{keyblock}, {\hyperref[\detokenize{appdev/refs/types/krb5_pointer:c.krb5_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_pointer}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{ptr}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{eblock} + +\sphinxAtStartPar +\sphinxstylestrong{keyblock} + +\sphinxAtStartPar +\sphinxstylestrong{ptr} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_c\_* API family. + + +\subsubsection{krb5\_kt\_free\_entry} +\label{\detokenize{appdev/refs/api/krb5_kt_free_entry:krb5-kt-free-entry}}\label{\detokenize{appdev/refs/api/krb5_kt_free_entry::doc}}\index{krb5\_kt\_free\_entry (C function)@\spxentry{krb5\_kt\_free\_entry}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_kt_free_entry:c.krb5_kt_free_entry}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_free\_entry}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab\_entry}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{entry}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{entry} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Use krb5\_free\_keytab\_entry\_contents instead. + + +\subsubsection{krb5\_random\_key} +\label{\detokenize{appdev/refs/api/krb5_random_key:krb5-random-key}}\label{\detokenize{appdev/refs/api/krb5_random_key::doc}}\index{krb5\_random\_key (C function)@\spxentry{krb5\_random\_key}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_random_key:c.krb5_random_key}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_random\_key}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}]{\sphinxcrossref{\DUrole{n}{krb5\_encrypt\_block}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{eblock}, {\hyperref[\detokenize{appdev/refs/types/krb5_pointer:c.krb5_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_pointer}}}}\DUrole{w}{ }\DUrole{n}{ptr}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\DUrole{n}{keyblock}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{eblock} + +\sphinxAtStartPar +\sphinxstylestrong{ptr} + +\sphinxAtStartPar +\sphinxstylestrong{keyblock} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_c\_* API family. + + +\subsubsection{krb5\_process\_key} +\label{\detokenize{appdev/refs/api/krb5_process_key:krb5-process-key}}\label{\detokenize{appdev/refs/api/krb5_process_key::doc}}\index{krb5\_process\_key (C function)@\spxentry{krb5\_process\_key}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_process_key:c.krb5_process_key}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_process\_key}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}]{\sphinxcrossref{\DUrole{n}{krb5\_encrypt\_block}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{eblock}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{key}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{eblock} + +\sphinxAtStartPar +\sphinxstylestrong{key} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_c\_* API family. + + +\subsubsection{krb5\_string\_to\_key} +\label{\detokenize{appdev/refs/api/krb5_string_to_key:krb5-string-to-key}}\label{\detokenize{appdev/refs/api/krb5_string_to_key::doc}}\index{krb5\_string\_to\_key (C function)@\spxentry{krb5\_string\_to\_key}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_string_to_key:c.krb5_string_to_key}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_string\_to\_key}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}]{\sphinxcrossref{\DUrole{n}{krb5\_encrypt\_block}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{eblock}, {\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{keyblock}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{data}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{salt}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{eblock} + +\sphinxAtStartPar +\sphinxstylestrong{keyblock} + +\sphinxAtStartPar +\sphinxstylestrong{data} + +\sphinxAtStartPar +\sphinxstylestrong{salt} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED See krb5\_c\_string\_to\_key() + + +\subsubsection{krb5\_use\_enctype} +\label{\detokenize{appdev/refs/api/krb5_use_enctype:krb5-use-enctype}}\label{\detokenize{appdev/refs/api/krb5_use_enctype::doc}}\index{krb5\_use\_enctype (C function)@\spxentry{krb5\_use\_enctype}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_use_enctype:c.krb5_use_enctype}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_use\_enctype}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}]{\sphinxcrossref{\DUrole{n}{krb5\_encrypt\_block}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{eblock}, {\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{n}{enctype}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{eblock} + +\sphinxAtStartPar +\sphinxstylestrong{enctype} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED Replaced by krb5\_c\_* API family. + + +\subsubsection{krb5\_verify\_checksum} +\label{\detokenize{appdev/refs/api/krb5_verify_checksum:krb5-verify-checksum}}\label{\detokenize{appdev/refs/api/krb5_verify_checksum::doc}}\index{krb5\_verify\_checksum (C function)@\spxentry{krb5\_verify\_checksum}\spxextra{C function}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/api/krb5_verify_checksum:c.krb5_verify_checksum}}% +\pysigstartmultiline +\pysiglinewithargsret{{\hyperref[\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}]{\sphinxcrossref{\DUrole{n}{krb5\_error\_code}}}}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_verify\_checksum}}}}{{\hyperref[\detokenize{appdev/refs/types/krb5_context:c.krb5_context}]{\sphinxcrossref{\DUrole{n}{krb5\_context}}}}\DUrole{w}{ }\DUrole{n}{context}, {\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\DUrole{n}{ctype}, \DUrole{k}{const}\DUrole{w}{ }{\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{n}{cksum}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_pointer:c.krb5_const_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_pointer}}}}\DUrole{w}{ }\DUrole{n}{in}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{in\_length}, {\hyperref[\detokenize{appdev/refs/types/krb5_const_pointer:c.krb5_const_pointer}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_pointer}}}}\DUrole{w}{ }\DUrole{n}{seed}, \DUrole{n}{size\_t}\DUrole{w}{ }\DUrole{n}{seed\_length}}{}% +\pysigstopmultiline +\end{fulllineitems} + +\begin{quote}\begin{description} +\item[{param}] \leavevmode +\sphinxAtStartPar +\sphinxstylestrong{context} + +\sphinxAtStartPar +\sphinxstylestrong{ctype} + +\sphinxAtStartPar +\sphinxstylestrong{cksum} + +\sphinxAtStartPar +\sphinxstylestrong{in} + +\sphinxAtStartPar +\sphinxstylestrong{in\_length} + +\sphinxAtStartPar +\sphinxstylestrong{seed} + +\sphinxAtStartPar +\sphinxstylestrong{seed\_length} + +\end{description}\end{quote} + +\sphinxAtStartPar +DEPRECATED See krb5\_c\_verify\_checksum() + + +\section{krb5 types and structures} +\label{\detokenize{appdev/refs/types/index:krb5-types-and-structures}}\label{\detokenize{appdev/refs/types/index::doc}} + +\subsection{Public} +\label{\detokenize{appdev/refs/types/index:public}} + +\subsubsection{krb5\_address} +\label{\detokenize{appdev/refs/types/krb5_address:krb5-address}}\label{\detokenize{appdev/refs/types/krb5_address:krb5-address-struct}}\label{\detokenize{appdev/refs/types/krb5_address::doc}}\index{krb5\_address (C type)@\spxentry{krb5\_address}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_address:c.krb5_address}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_address}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Structure for address. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_address:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_address krb5\_address + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_address:members}}\index{krb5\_address.magic (C member)@\spxentry{krb5\_address.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_address:c.krb5_address.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_address.addrtype (C member)@\spxentry{krb5\_address.addrtype}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_address:c.krb5_address.addrtype}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_addrtype:c.krb5_addrtype}]{\sphinxcrossref{\DUrole{n}{krb5\_addrtype}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{addrtype}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_address.length (C member)@\spxentry{krb5\_address.length}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_address:c.krb5_address.length}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{length}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_address.contents (C member)@\spxentry{krb5\_address.contents}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_address:c.krb5_address.contents}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_octet:c.krb5_octet}]{\sphinxcrossref{\DUrole{n}{krb5\_octet}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{contents}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_addrtype} +\label{\detokenize{appdev/refs/types/krb5_addrtype:krb5-addrtype}}\label{\detokenize{appdev/refs/types/krb5_addrtype:krb5-addrtype-struct}}\label{\detokenize{appdev/refs/types/krb5_addrtype::doc}}\index{krb5\_addrtype (C type)@\spxentry{krb5\_addrtype}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_addrtype:c.krb5_addrtype}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_addrtype}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_addrtype:declaration}} +\sphinxAtStartPar +typedef krb5\_int32 krb5\_addrtype + + +\subsubsection{krb5\_ap\_req} +\label{\detokenize{appdev/refs/types/krb5_ap_req:krb5-ap-req}}\label{\detokenize{appdev/refs/types/krb5_ap_req:krb5-ap-req-struct}}\label{\detokenize{appdev/refs/types/krb5_ap_req::doc}}\index{krb5\_ap\_req (C type)@\spxentry{krb5\_ap\_req}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_req:c.krb5_ap_req}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_ap\_req}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Authentication header. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_ap_req:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_ap\_req krb5\_ap\_req + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_ap_req:members}}\index{krb5\_ap\_req.magic (C member)@\spxentry{krb5\_ap\_req.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_req:c.krb5_ap_req.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ap_req:c.krb5_ap_req}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_ap\_req.ap\_options (C member)@\spxentry{krb5\_ap\_req.ap\_options}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_req:c.krb5_ap_req.ap_options}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ap_req:c.krb5_ap_req}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ap\_options}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Requested options. + +\end{fulllineitems} + +\index{krb5\_ap\_req.ticket (C member)@\spxentry{krb5\_ap\_req.ticket}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_req:c.krb5_ap_req.ticket}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ap_req:c.krb5_ap_req}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ticket}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Ticket. + +\end{fulllineitems} + +\index{krb5\_ap\_req.authenticator (C member)@\spxentry{krb5\_ap\_req.authenticator}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_req:c.krb5_ap_req.authenticator}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ap_req:c.krb5_ap_req}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{authenticator}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Encrypted authenticator. + +\end{fulllineitems} + + + +\subsubsection{krb5\_ap\_rep} +\label{\detokenize{appdev/refs/types/krb5_ap_rep:krb5-ap-rep}}\label{\detokenize{appdev/refs/types/krb5_ap_rep:krb5-ap-rep-struct}}\label{\detokenize{appdev/refs/types/krb5_ap_rep::doc}}\index{krb5\_ap\_rep (C type)@\spxentry{krb5\_ap\_rep}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_rep:c.krb5_ap_rep}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_ap\_rep}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +C representaton of AP\sphinxhyphen{}REP message. + +\sphinxAtStartPar +The server’s response to a client’s request for mutual authentication. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_ap_rep:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_ap\_rep krb5\_ap\_rep + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_ap_rep:members}}\index{krb5\_ap\_rep.magic (C member)@\spxentry{krb5\_ap\_rep.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_rep:c.krb5_ap_rep.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ap_rep:c.krb5_ap_rep}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_rep}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_ap\_rep.enc\_part (C member)@\spxentry{krb5\_ap\_rep.enc\_part}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_rep:c.krb5_ap_rep.enc_part}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ap_rep:c.krb5_ap_rep}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_rep}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{enc\_part}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Ciphertext of ApRepEncPart. + +\end{fulllineitems} + + + +\subsubsection{krb5\_ap\_rep\_enc\_part} +\label{\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:krb5-ap-rep-enc-part}}\label{\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:krb5-ap-rep-enc-part-struct}}\label{\detokenize{appdev/refs/types/krb5_ap_rep_enc_part::doc}}\index{krb5\_ap\_rep\_enc\_part (C type)@\spxentry{krb5\_ap\_rep\_enc\_part}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_ap\_rep\_enc\_part}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Cleartext that is encrypted and put into \sphinxcode{\sphinxupquote{\_krb5\_ap\_rep}} . + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_ap\_rep\_enc\_part krb5\_ap\_rep\_enc\_part + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:members}}\index{krb5\_ap\_rep\_enc\_part.magic (C member)@\spxentry{krb5\_ap\_rep\_enc\_part.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_rep\_enc\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_ap\_rep\_enc\_part.ctime (C member)@\spxentry{krb5\_ap\_rep\_enc\_part.ctime}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part.ctime}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_rep\_enc\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ctime}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Client time, seconds portion. + +\end{fulllineitems} + +\index{krb5\_ap\_rep\_enc\_part.cusec (C member)@\spxentry{krb5\_ap\_rep\_enc\_part.cusec}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part.cusec}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_rep\_enc\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{cusec}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Client time, microseconds portion. + +\end{fulllineitems} + +\index{krb5\_ap\_rep\_enc\_part.subkey (C member)@\spxentry{krb5\_ap\_rep\_enc\_part.subkey}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part.subkey}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_rep\_enc\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{subkey}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Subkey (optional) + +\end{fulllineitems} + +\index{krb5\_ap\_rep\_enc\_part.seq\_number (C member)@\spxentry{krb5\_ap\_rep\_enc\_part.seq\_number}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part.seq_number}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_ui_4:c.krb5_ui_4}]{\sphinxcrossref{\DUrole{n}{krb5\_ui\_4}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ap_rep_enc_part:c.krb5_ap_rep_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_ap\_rep\_enc\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{seq\_number}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Sequence number. + +\end{fulllineitems} + + + +\subsubsection{krb5\_authdata} +\label{\detokenize{appdev/refs/types/krb5_authdata:krb5-authdata}}\label{\detokenize{appdev/refs/types/krb5_authdata:krb5-authdata-struct}}\label{\detokenize{appdev/refs/types/krb5_authdata::doc}}\index{krb5\_authdata (C type)@\spxentry{krb5\_authdata}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_authdata}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Structure for auth data. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_authdata:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_authdata krb5\_authdata + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_authdata:members}}\index{krb5\_authdata.magic (C member)@\spxentry{krb5\_authdata.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_authdata.ad\_type (C member)@\spxentry{krb5\_authdata.ad\_type}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata.ad_type}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_authdatatype:c.krb5_authdatatype}]{\sphinxcrossref{\DUrole{n}{krb5\_authdatatype}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ad\_type}}}}% +\pysigstopmultiline +\sphinxAtStartPar +ADTYPE. + +\end{fulllineitems} + +\index{krb5\_authdata.length (C member)@\spxentry{krb5\_authdata.length}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata.length}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{length}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Length of data. + +\end{fulllineitems} + +\index{krb5\_authdata.contents (C member)@\spxentry{krb5\_authdata.contents}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata.contents}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_octet:c.krb5_octet}]{\sphinxcrossref{\DUrole{n}{krb5\_octet}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{contents}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Data. + +\end{fulllineitems} + + + +\subsubsection{krb5\_authdatatype} +\label{\detokenize{appdev/refs/types/krb5_authdatatype:krb5-authdatatype}}\label{\detokenize{appdev/refs/types/krb5_authdatatype:krb5-authdatatype-struct}}\label{\detokenize{appdev/refs/types/krb5_authdatatype::doc}}\index{krb5\_authdatatype (C type)@\spxentry{krb5\_authdatatype}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authdatatype:c.krb5_authdatatype}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_authdatatype}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_authdatatype:declaration}} +\sphinxAtStartPar +typedef krb5\_int32 krb5\_authdatatype + + +\subsubsection{krb5\_authenticator} +\label{\detokenize{appdev/refs/types/krb5_authenticator:krb5-authenticator}}\label{\detokenize{appdev/refs/types/krb5_authenticator:krb5-authenticator-struct}}\label{\detokenize{appdev/refs/types/krb5_authenticator::doc}}\index{krb5\_authenticator (C type)@\spxentry{krb5\_authenticator}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_authenticator}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Ticket authenticator. + +\sphinxAtStartPar +The C representation of an unencrypted authenticator. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_authenticator:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_authenticator krb5\_authenticator + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_authenticator:members}}\index{krb5\_authenticator.magic (C member)@\spxentry{krb5\_authenticator.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}]{\sphinxcrossref{\DUrole{n}{krb5\_authenticator}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_authenticator.client (C member)@\spxentry{krb5\_authenticator.client}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator.client}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}]{\sphinxcrossref{\DUrole{n}{krb5\_authenticator}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{client}}}}% +\pysigstopmultiline +\sphinxAtStartPar +client name/realm + +\end{fulllineitems} + +\index{krb5\_authenticator.checksum (C member)@\spxentry{krb5\_authenticator.checksum}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator.checksum}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}]{\sphinxcrossref{\DUrole{n}{krb5\_authenticator}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{checksum}}}}% +\pysigstopmultiline +\sphinxAtStartPar +checksum, includes type, optional + +\end{fulllineitems} + +\index{krb5\_authenticator.cusec (C member)@\spxentry{krb5\_authenticator.cusec}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator.cusec}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}]{\sphinxcrossref{\DUrole{n}{krb5\_authenticator}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{cusec}}}}% +\pysigstopmultiline +\sphinxAtStartPar +client usec portion + +\end{fulllineitems} + +\index{krb5\_authenticator.ctime (C member)@\spxentry{krb5\_authenticator.ctime}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator.ctime}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}]{\sphinxcrossref{\DUrole{n}{krb5\_authenticator}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ctime}}}}% +\pysigstopmultiline +\sphinxAtStartPar +client sec portion + +\end{fulllineitems} + +\index{krb5\_authenticator.subkey (C member)@\spxentry{krb5\_authenticator.subkey}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator.subkey}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}]{\sphinxcrossref{\DUrole{n}{krb5\_authenticator}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{subkey}}}}% +\pysigstopmultiline +\sphinxAtStartPar +true session key, optional + +\end{fulllineitems} + +\index{krb5\_authenticator.seq\_number (C member)@\spxentry{krb5\_authenticator.seq\_number}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator.seq_number}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_ui_4:c.krb5_ui_4}]{\sphinxcrossref{\DUrole{n}{krb5\_ui\_4}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}]{\sphinxcrossref{\DUrole{n}{krb5\_authenticator}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{seq\_number}}}}% +\pysigstopmultiline +\sphinxAtStartPar +sequence \#, optional + +\end{fulllineitems} + +\index{krb5\_authenticator.authorization\_data (C member)@\spxentry{krb5\_authenticator.authorization\_data}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator.authorization_data}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}]{\sphinxcrossref{\DUrole{n}{krb5\_authenticator}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{authorization\_data}}}}% +\pysigstopmultiline +\sphinxAtStartPar +authoriazation data + +\end{fulllineitems} + + + +\subsubsection{krb5\_boolean} +\label{\detokenize{appdev/refs/types/krb5_boolean:krb5-boolean}}\label{\detokenize{appdev/refs/types/krb5_boolean:krb5-boolean-struct}}\label{\detokenize{appdev/refs/types/krb5_boolean::doc}}\index{krb5\_boolean (C type)@\spxentry{krb5\_boolean}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_boolean}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_boolean:declaration}} +\sphinxAtStartPar +typedef unsigned int krb5\_boolean + + +\subsubsection{krb5\_checksum} +\label{\detokenize{appdev/refs/types/krb5_checksum:krb5-checksum}}\label{\detokenize{appdev/refs/types/krb5_checksum:krb5-checksum-struct}}\label{\detokenize{appdev/refs/types/krb5_checksum::doc}}\index{krb5\_checksum (C type)@\spxentry{krb5\_checksum}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_checksum}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_checksum:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_checksum krb5\_checksum + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_checksum:members}}\index{krb5\_checksum.magic (C member)@\spxentry{krb5\_checksum.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_checksum.checksum\_type (C member)@\spxentry{krb5\_checksum.checksum\_type}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum.checksum_type}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}]{\sphinxcrossref{\DUrole{n}{krb5\_cksumtype}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{checksum\_type}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_checksum.length (C member)@\spxentry{krb5\_checksum.length}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum.length}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{length}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_checksum.contents (C member)@\spxentry{krb5\_checksum.contents}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum.contents}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_octet:c.krb5_octet}]{\sphinxcrossref{\DUrole{n}{krb5\_octet}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{contents}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_const\_pointer} +\label{\detokenize{appdev/refs/types/krb5_const_pointer:krb5-const-pointer}}\label{\detokenize{appdev/refs/types/krb5_const_pointer:krb5-const-pointer-struct}}\label{\detokenize{appdev/refs/types/krb5_const_pointer::doc}}\index{krb5\_const\_pointer (C type)@\spxentry{krb5\_const\_pointer}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_const_pointer:c.krb5_const_pointer}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_const\_pointer}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_const_pointer:declaration}} +\sphinxAtStartPar +typedef void const* krb5\_const\_pointer + + +\subsubsection{krb5\_const\_principal} +\label{\detokenize{appdev/refs/types/krb5_const_principal:krb5-const-principal}}\label{\detokenize{appdev/refs/types/krb5_const_principal:krb5-const-principal-struct}}\label{\detokenize{appdev/refs/types/krb5_const_principal::doc}}\index{krb5\_const\_principal (C type)@\spxentry{krb5\_const\_principal}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_const\_principal}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Constant version of {\hyperref[\detokenize{appdev/refs/types/krb5_principal_data:c.krb5_principal_data}]{\sphinxcrossref{\sphinxcode{\sphinxupquote{krb5\_principal\_data}}}}} . + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_const_principal:declaration}} +\sphinxAtStartPar +typedef const krb5\_principal\_data* krb5\_const\_principal + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_const_principal:members}}\index{krb5\_const\_principal.magic (C member)@\spxentry{krb5\_const\_principal.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_const\_principal.realm (C member)@\spxentry{krb5\_const\_principal.realm}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal.realm}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{realm}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_const\_principal.data (C member)@\spxentry{krb5\_const\_principal.data}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal.data}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{data}}}}% +\pysigstopmultiline +\sphinxAtStartPar +An array of strings. + +\end{fulllineitems} + +\index{krb5\_const\_principal.length (C member)@\spxentry{krb5\_const\_principal.length}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal.length}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{length}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_const\_principal.type (C member)@\spxentry{krb5\_const\_principal.type}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal.type}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_const_principal:c.krb5_const_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_const\_principal}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{type}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_cred} +\label{\detokenize{appdev/refs/types/krb5_cred:krb5-cred}}\label{\detokenize{appdev/refs/types/krb5_cred:krb5-cred-struct}}\label{\detokenize{appdev/refs/types/krb5_cred::doc}}\index{krb5\_cred (C type)@\spxentry{krb5\_cred}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred:c.krb5_cred}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cred}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Credentials data structure. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_cred:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_cred krb5\_cred + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_cred:members}}\index{krb5\_cred.magic (C member)@\spxentry{krb5\_cred.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred:c.krb5_cred.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred:c.krb5_cred}]{\sphinxcrossref{\DUrole{n}{krb5\_cred}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_cred.tickets (C member)@\spxentry{krb5\_cred.tickets}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred:c.krb5_cred.tickets}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred:c.krb5_cred}]{\sphinxcrossref{\DUrole{n}{krb5\_cred}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{tickets}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Tickets. + +\end{fulllineitems} + +\index{krb5\_cred.enc\_part (C member)@\spxentry{krb5\_cred.enc\_part}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred:c.krb5_cred.enc_part}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred:c.krb5_cred}]{\sphinxcrossref{\DUrole{n}{krb5\_cred}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{enc\_part}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Encrypted part. + +\end{fulllineitems} + +\index{krb5\_cred.enc\_part2 (C member)@\spxentry{krb5\_cred.enc\_part2}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred:c.krb5_cred.enc_part2}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_enc\_part}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred:c.krb5_cred}]{\sphinxcrossref{\DUrole{n}{krb5\_cred}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{enc\_part2}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Unencrypted version, if available. + +\end{fulllineitems} + + + +\subsubsection{krb5\_cred\_enc\_part} +\label{\detokenize{appdev/refs/types/krb5_cred_enc_part:krb5-cred-enc-part}}\label{\detokenize{appdev/refs/types/krb5_cred_enc_part:krb5-cred-enc-part-struct}}\label{\detokenize{appdev/refs/types/krb5_cred_enc_part::doc}}\index{krb5\_cred\_enc\_part (C type)@\spxentry{krb5\_cred\_enc\_part}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cred\_enc\_part}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Cleartext credentials information. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_cred_enc_part:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_cred\_enc\_part krb5\_cred\_enc\_part + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_cred_enc_part:members}}\index{krb5\_cred\_enc\_part.magic (C member)@\spxentry{krb5\_cred\_enc\_part.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_enc\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_cred\_enc\_part.nonce (C member)@\spxentry{krb5\_cred\_enc\_part.nonce}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part.nonce}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_enc\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{nonce}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Nonce (optional) + +\end{fulllineitems} + +\index{krb5\_cred\_enc\_part.timestamp (C member)@\spxentry{krb5\_cred\_enc\_part.timestamp}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part.timestamp}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_enc\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{timestamp}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Generation time, seconds portion. + +\end{fulllineitems} + +\index{krb5\_cred\_enc\_part.usec (C member)@\spxentry{krb5\_cred\_enc\_part.usec}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part.usec}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_enc\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{usec}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Generation time, microseconds portion. + +\end{fulllineitems} + +\index{krb5\_cred\_enc\_part.s\_address (C member)@\spxentry{krb5\_cred\_enc\_part.s\_address}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part.s_address}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_enc\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{s\_address}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Sender address (optional) + +\end{fulllineitems} + +\index{krb5\_cred\_enc\_part.r\_address (C member)@\spxentry{krb5\_cred\_enc\_part.r\_address}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part.r_address}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_enc\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{r\_address}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Recipient address (optional) + +\end{fulllineitems} + +\index{krb5\_cred\_enc\_part.ticket\_info (C member)@\spxentry{krb5\_cred\_enc\_part.ticket\_info}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part.ticket_info}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_info}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_enc_part:c.krb5_cred_enc_part}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_enc\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ticket\_info}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_cred\_info} +\label{\detokenize{appdev/refs/types/krb5_cred_info:krb5-cred-info}}\label{\detokenize{appdev/refs/types/krb5_cred_info:krb5-cred-info-struct}}\label{\detokenize{appdev/refs/types/krb5_cred_info::doc}}\index{krb5\_cred\_info (C type)@\spxentry{krb5\_cred\_info}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cred\_info}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Credentials information inserted into \sphinxstyleemphasis{EncKrbCredPart} . + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_cred_info:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_cred\_info krb5\_cred\_info + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_cred_info:members}}\index{krb5\_cred\_info.magic (C member)@\spxentry{krb5\_cred\_info.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_info}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_cred\_info.session (C member)@\spxentry{krb5\_cred\_info.session}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info.session}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_info}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{session}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Session key used to encrypt ticket. + +\end{fulllineitems} + +\index{krb5\_cred\_info.client (C member)@\spxentry{krb5\_cred\_info.client}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info.client}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_info}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{client}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Client principal and realm. + +\end{fulllineitems} + +\index{krb5\_cred\_info.server (C member)@\spxentry{krb5\_cred\_info.server}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info.server}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_info}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{server}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Server principal and realm. + +\end{fulllineitems} + +\index{krb5\_cred\_info.flags (C member)@\spxentry{krb5\_cred\_info.flags}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info.flags}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_info}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{flags}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Ticket flags. + +\end{fulllineitems} + +\index{krb5\_cred\_info.times (C member)@\spxentry{krb5\_cred\_info.times}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info.times}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket\_times}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_info}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{times}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Auth, start, end, renew\_till. + +\end{fulllineitems} + +\index{krb5\_cred\_info.caddrs (C member)@\spxentry{krb5\_cred\_info.caddrs}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info.caddrs}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_cred_info:c.krb5_cred_info}]{\sphinxcrossref{\DUrole{n}{krb5\_cred\_info}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{caddrs}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Array of pointers to addrs (optional) + +\end{fulllineitems} + + + +\subsubsection{krb5\_creds} +\label{\detokenize{appdev/refs/types/krb5_creds:krb5-creds}}\label{\detokenize{appdev/refs/types/krb5_creds:krb5-creds-struct}}\label{\detokenize{appdev/refs/types/krb5_creds::doc}}\index{krb5\_creds (C type)@\spxentry{krb5\_creds}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_creds}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Credentials structure including ticket, session key, and lifetime info. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_creds:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_creds krb5\_creds + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_creds:members}}\index{krb5\_creds.magic (C member)@\spxentry{krb5\_creds.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_creds.client (C member)@\spxentry{krb5\_creds.client}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds.client}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{client}}}}% +\pysigstopmultiline +\sphinxAtStartPar +client’s principal identifier + +\end{fulllineitems} + +\index{krb5\_creds.server (C member)@\spxentry{krb5\_creds.server}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds.server}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{server}}}}% +\pysigstopmultiline +\sphinxAtStartPar +server’s principal identifier + +\end{fulllineitems} + +\index{krb5\_creds.keyblock (C member)@\spxentry{krb5\_creds.keyblock}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds.keyblock}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{keyblock}}}}% +\pysigstopmultiline +\sphinxAtStartPar +session encryption key info + +\end{fulllineitems} + +\index{krb5\_creds.times (C member)@\spxentry{krb5\_creds.times}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds.times}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket\_times}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{times}}}}% +\pysigstopmultiline +\sphinxAtStartPar +lifetime info + +\end{fulllineitems} + +\index{krb5\_creds.is\_skey (C member)@\spxentry{krb5\_creds.is\_skey}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds.is_skey}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{is\_skey}}}}% +\pysigstopmultiline +\sphinxAtStartPar +true if ticket is encrypted in another ticket’s skey + +\end{fulllineitems} + +\index{krb5\_creds.ticket\_flags (C member)@\spxentry{krb5\_creds.ticket\_flags}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds.ticket_flags}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ticket\_flags}}}}% +\pysigstopmultiline +\sphinxAtStartPar +flags in ticket + +\end{fulllineitems} + +\index{krb5\_creds.addresses (C member)@\spxentry{krb5\_creds.addresses}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds.addresses}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{addresses}}}}% +\pysigstopmultiline +\sphinxAtStartPar +addrs in ticket + +\end{fulllineitems} + +\index{krb5\_creds.ticket (C member)@\spxentry{krb5\_creds.ticket}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds.ticket}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ticket}}}}% +\pysigstopmultiline +\sphinxAtStartPar +ticket string itself + +\end{fulllineitems} + +\index{krb5\_creds.second\_ticket (C member)@\spxentry{krb5\_creds.second\_ticket}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds.second_ticket}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{second\_ticket}}}}% +\pysigstopmultiline +\sphinxAtStartPar +second ticket, if related to ticket (via DUPLICATE\sphinxhyphen{}SKEY or ENC\sphinxhyphen{}TKT\sphinxhyphen{}IN\sphinxhyphen{}SKEY) + +\end{fulllineitems} + +\index{krb5\_creds.authdata (C member)@\spxentry{krb5\_creds.authdata}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds.authdata}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_creds:c.krb5_creds}]{\sphinxcrossref{\DUrole{n}{krb5\_creds}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{authdata}}}}% +\pysigstopmultiline +\sphinxAtStartPar +authorization data + +\end{fulllineitems} + + + +\subsubsection{krb5\_crypto\_iov} +\label{\detokenize{appdev/refs/types/krb5_crypto_iov:krb5-crypto-iov}}\label{\detokenize{appdev/refs/types/krb5_crypto_iov:krb5-crypto-iov-struct}}\label{\detokenize{appdev/refs/types/krb5_crypto_iov::doc}}\index{krb5\_crypto\_iov (C type)@\spxentry{krb5\_crypto\_iov}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_crypto\_iov}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Structure to describe a region of text to be encrypted or decrypted. + +\sphinxAtStartPar +The \sphinxstyleemphasis{flags} member describes the type of the iov. The \sphinxstyleemphasis{data} member points to the memory that will be manipulated. All iov APIs take a pointer to the first element of an array of krb5\_crypto\_iov’s along with the size of that array. Buffer contents are manipulated in\sphinxhyphen{}place; data is overwritten. Callers must allocate the right number of krb5\_crypto\_iov structures before calling into an iov API. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_crypto_iov:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_crypto\_iov krb5\_crypto\_iov + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_crypto_iov:members}}\index{krb5\_crypto\_iov.flags (C member)@\spxentry{krb5\_crypto\_iov.flags}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov.flags}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_cryptotype:c.krb5_cryptotype}]{\sphinxcrossref{\DUrole{n}{krb5\_cryptotype}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov}]{\sphinxcrossref{\DUrole{n}{krb5\_crypto\_iov}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{flags}}}}% +\pysigstopmultiline +\sphinxAtStartPar +iov type (see KRB5\_CRYPTO\_TYPE macros) + +\end{fulllineitems} + +\index{krb5\_crypto\_iov.data (C member)@\spxentry{krb5\_crypto\_iov.data}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov.data}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_crypto_iov:c.krb5_crypto_iov}]{\sphinxcrossref{\DUrole{n}{krb5\_crypto\_iov}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{data}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_cryptotype} +\label{\detokenize{appdev/refs/types/krb5_cryptotype:krb5-cryptotype}}\label{\detokenize{appdev/refs/types/krb5_cryptotype:krb5-cryptotype-struct}}\label{\detokenize{appdev/refs/types/krb5_cryptotype::doc}}\index{krb5\_cryptotype (C type)@\spxentry{krb5\_cryptotype}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cryptotype:c.krb5_cryptotype}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cryptotype}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_cryptotype:declaration}} +\sphinxAtStartPar +typedef krb5\_int32 krb5\_cryptotype + + +\subsubsection{krb5\_data} +\label{\detokenize{appdev/refs/types/krb5_data:krb5-data}}\label{\detokenize{appdev/refs/types/krb5_data:krb5-data-struct}}\label{\detokenize{appdev/refs/types/krb5_data::doc}}\index{krb5\_data (C type)@\spxentry{krb5\_data}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_data:c.krb5_data}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_data}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_data:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_data krb5\_data + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_data:members}}\index{krb5\_data.magic (C member)@\spxentry{krb5\_data.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_data:c.krb5_data.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_data.length (C member)@\spxentry{krb5\_data.length}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_data:c.krb5_data.length}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{length}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_data.data (C member)@\spxentry{krb5\_data.data}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_data:c.krb5_data.data}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{data}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_deltat} +\label{\detokenize{appdev/refs/types/krb5_deltat:krb5-deltat}}\label{\detokenize{appdev/refs/types/krb5_deltat:krb5-deltat-struct}}\label{\detokenize{appdev/refs/types/krb5_deltat::doc}}\index{krb5\_deltat (C type)@\spxentry{krb5\_deltat}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_deltat:c.krb5_deltat}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_deltat}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_deltat:declaration}} +\sphinxAtStartPar +typedef krb5\_int32 krb5\_deltat + + +\subsubsection{krb5\_enc\_data} +\label{\detokenize{appdev/refs/types/krb5_enc_data:krb5-enc-data}}\label{\detokenize{appdev/refs/types/krb5_enc_data:krb5-enc-data-struct}}\label{\detokenize{appdev/refs/types/krb5_enc_data::doc}}\index{krb5\_enc\_data (C type)@\spxentry{krb5\_enc\_data}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_enc\_data}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_enc_data:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_enc\_data krb5\_enc\_data + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_enc_data:members}}\index{krb5\_enc\_data.magic (C member)@\spxentry{krb5\_enc\_data.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_enc\_data.enctype (C member)@\spxentry{krb5\_enc\_data.enctype}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data.enctype}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{enctype}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_enc\_data.kvno (C member)@\spxentry{krb5\_enc\_data.kvno}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data.kvno}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_kvno:c.krb5_kvno}]{\sphinxcrossref{\DUrole{n}{krb5\_kvno}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{kvno}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_enc\_data.ciphertext (C member)@\spxentry{krb5\_enc\_data.ciphertext}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data.ciphertext}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ciphertext}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_enc\_kdc\_rep\_part} +\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:krb5-enc-kdc-rep-part}}\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:krb5-enc-kdc-rep-part-struct}}\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part::doc}}\index{krb5\_enc\_kdc\_rep\_part (C type)@\spxentry{krb5\_enc\_kdc\_rep\_part}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_enc\_kdc\_rep\_part}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +C representation of \sphinxstyleemphasis{EncKDCRepPart} protocol message. + +\sphinxAtStartPar +This is the cleartext message that is encrypted and inserted in \sphinxstyleemphasis{KDC\sphinxhyphen{}REP} . + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_enc\_kdc\_rep\_part krb5\_enc\_kdc\_rep\_part + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:members}}\index{krb5\_enc\_kdc\_rep\_part.magic (C member)@\spxentry{krb5\_enc\_kdc\_rep\_part.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_kdc\_rep\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_enc\_kdc\_rep\_part.msg\_type (C member)@\spxentry{krb5\_enc\_kdc\_rep\_part.msg\_type}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part.msg_type}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_msgtype:c.krb5_msgtype}]{\sphinxcrossref{\DUrole{n}{krb5\_msgtype}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_kdc\_rep\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{msg\_type}}}}% +\pysigstopmultiline +\sphinxAtStartPar +krb5 message type + +\end{fulllineitems} + +\index{krb5\_enc\_kdc\_rep\_part.session (C member)@\spxentry{krb5\_enc\_kdc\_rep\_part.session}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part.session}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_kdc\_rep\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{session}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Session key. + +\end{fulllineitems} + +\index{krb5\_enc\_kdc\_rep\_part.last\_req (C member)@\spxentry{krb5\_enc\_kdc\_rep\_part.last\_req}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part.last_req}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_last_req_entry:c.krb5_last_req_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_last\_req\_entry}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_kdc\_rep\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{last\_req}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Array of pointers to entries. + +\end{fulllineitems} + +\index{krb5\_enc\_kdc\_rep\_part.nonce (C member)@\spxentry{krb5\_enc\_kdc\_rep\_part.nonce}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part.nonce}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_kdc\_rep\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{nonce}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Nonce from request. + +\end{fulllineitems} + +\index{krb5\_enc\_kdc\_rep\_part.key\_exp (C member)@\spxentry{krb5\_enc\_kdc\_rep\_part.key\_exp}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part.key_exp}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_kdc\_rep\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{key\_exp}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Expiration date. + +\end{fulllineitems} + +\index{krb5\_enc\_kdc\_rep\_part.flags (C member)@\spxentry{krb5\_enc\_kdc\_rep\_part.flags}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part.flags}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_kdc\_rep\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{flags}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Ticket flags. + +\end{fulllineitems} + +\index{krb5\_enc\_kdc\_rep\_part.times (C member)@\spxentry{krb5\_enc\_kdc\_rep\_part.times}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part.times}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket\_times}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_kdc\_rep\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{times}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Lifetime info. + +\end{fulllineitems} + +\index{krb5\_enc\_kdc\_rep\_part.server (C member)@\spxentry{krb5\_enc\_kdc\_rep\_part.server}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part.server}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_kdc\_rep\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{server}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Server’s principal identifier. + +\end{fulllineitems} + +\index{krb5\_enc\_kdc\_rep\_part.caddrs (C member)@\spxentry{krb5\_enc\_kdc\_rep\_part.caddrs}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part.caddrs}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_kdc\_rep\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{caddrs}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Array of ptrs to addrs, optional. + +\end{fulllineitems} + +\index{krb5\_enc\_kdc\_rep\_part.enc\_padata (C member)@\spxentry{krb5\_enc\_kdc\_rep\_part.enc\_padata}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part.enc_padata}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_data:c.krb5_pa_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_kdc\_rep\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{enc\_padata}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Encrypted preauthentication data. + +\end{fulllineitems} + + + +\subsubsection{krb5\_enc\_tkt\_part} +\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part:krb5-enc-tkt-part}}\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part:krb5-enc-tkt-part-struct}}\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part::doc}}\index{krb5\_enc\_tkt\_part (C type)@\spxentry{krb5\_enc\_tkt\_part}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_enc\_tkt\_part}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Encrypted part of ticket. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_enc\_tkt\_part krb5\_enc\_tkt\_part + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part:members}}\index{krb5\_enc\_tkt\_part.magic (C member)@\spxentry{krb5\_enc\_tkt\_part.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_tkt\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_enc\_tkt\_part.flags (C member)@\spxentry{krb5\_enc\_tkt\_part.flags}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part.flags}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_tkt\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{flags}}}}% +\pysigstopmultiline +\sphinxAtStartPar +flags + +\end{fulllineitems} + +\index{krb5\_enc\_tkt\_part.session (C member)@\spxentry{krb5\_enc\_tkt\_part.session}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part.session}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_tkt\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{session}}}}% +\pysigstopmultiline +\sphinxAtStartPar +session key: includes enctype + +\end{fulllineitems} + +\index{krb5\_enc\_tkt\_part.client (C member)@\spxentry{krb5\_enc\_tkt\_part.client}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part.client}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_tkt\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{client}}}}% +\pysigstopmultiline +\sphinxAtStartPar +client name/realm + +\end{fulllineitems} + +\index{krb5\_enc\_tkt\_part.transited (C member)@\spxentry{krb5\_enc\_tkt\_part.transited}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part.transited}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_transited:c.krb5_transited}]{\sphinxcrossref{\DUrole{n}{krb5\_transited}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_tkt\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{transited}}}}% +\pysigstopmultiline +\sphinxAtStartPar +list of transited realms + +\end{fulllineitems} + +\index{krb5\_enc\_tkt\_part.times (C member)@\spxentry{krb5\_enc\_tkt\_part.times}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part.times}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket\_times}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_tkt\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{times}}}}% +\pysigstopmultiline +\sphinxAtStartPar +auth, start, end, renew\_till + +\end{fulllineitems} + +\index{krb5\_enc\_tkt\_part.caddrs (C member)@\spxentry{krb5\_enc\_tkt\_part.caddrs}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part.caddrs}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_tkt\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{caddrs}}}}% +\pysigstopmultiline +\sphinxAtStartPar +array of ptrs to addresses + +\end{fulllineitems} + +\index{krb5\_enc\_tkt\_part.authorization\_data (C member)@\spxentry{krb5\_enc\_tkt\_part.authorization\_data}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part.authorization_data}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_tkt\_part}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{authorization\_data}}}}% +\pysigstopmultiline +\sphinxAtStartPar +auth data + +\end{fulllineitems} + + + +\subsubsection{krb5\_encrypt\_block} +\label{\detokenize{appdev/refs/types/krb5_encrypt_block:krb5-encrypt-block}}\label{\detokenize{appdev/refs/types/krb5_encrypt_block:krb5-encrypt-block-struct}}\label{\detokenize{appdev/refs/types/krb5_encrypt_block::doc}}\index{krb5\_encrypt\_block (C type)@\spxentry{krb5\_encrypt\_block}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_encrypt\_block}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_encrypt_block:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_encrypt\_block krb5\_encrypt\_block + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_encrypt_block:members}}\index{krb5\_encrypt\_block.magic (C member)@\spxentry{krb5\_encrypt\_block.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}]{\sphinxcrossref{\DUrole{n}{krb5\_encrypt\_block}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_encrypt\_block.crypto\_entry (C member)@\spxentry{krb5\_encrypt\_block.crypto\_entry}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block.crypto_entry}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}]{\sphinxcrossref{\DUrole{n}{krb5\_encrypt\_block}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{crypto\_entry}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_encrypt\_block.key (C member)@\spxentry{krb5\_encrypt\_block.key}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block.key}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_encrypt_block:c.krb5_encrypt_block}]{\sphinxcrossref{\DUrole{n}{krb5\_encrypt\_block}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{key}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_enctype} +\label{\detokenize{appdev/refs/types/krb5_enctype:krb5-enctype}}\label{\detokenize{appdev/refs/types/krb5_enctype:krb5-enctype-struct}}\label{\detokenize{appdev/refs/types/krb5_enctype::doc}}\index{krb5\_enctype (C type)@\spxentry{krb5\_enctype}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_enctype}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_enctype:declaration}} +\sphinxAtStartPar +typedef krb5\_int32 krb5\_enctype + + +\subsubsection{krb5\_error} +\label{\detokenize{appdev/refs/types/krb5_error:krb5-error}}\label{\detokenize{appdev/refs/types/krb5_error:krb5-error-struct}}\label{\detokenize{appdev/refs/types/krb5_error::doc}}\index{krb5\_error (C type)@\spxentry{krb5\_error}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_error:c.krb5_error}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_error}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Error message structure. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_error:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_error krb5\_error + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_error:members}}\index{krb5\_error.magic (C member)@\spxentry{krb5\_error.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_error:c.krb5_error.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_error.ctime (C member)@\spxentry{krb5\_error.ctime}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_error:c.krb5_error.ctime}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ctime}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Client sec portion; optional. + +\end{fulllineitems} + +\index{krb5\_error.cusec (C member)@\spxentry{krb5\_error.cusec}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_error:c.krb5_error.cusec}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{cusec}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Client usec portion; optional. + +\end{fulllineitems} + +\index{krb5\_error.susec (C member)@\spxentry{krb5\_error.susec}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_error:c.krb5_error.susec}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{susec}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Server usec portion. + +\end{fulllineitems} + +\index{krb5\_error.stime (C member)@\spxentry{krb5\_error.stime}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_error:c.krb5_error.stime}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{stime}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Server sec portion. + +\end{fulllineitems} + +\index{krb5\_error.error (C member)@\spxentry{krb5\_error.error}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_error:c.krb5_error.error}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_ui_4:c.krb5_ui_4}]{\sphinxcrossref{\DUrole{n}{krb5\_ui\_4}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{error}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Error code (protocol error \#’s) + +\end{fulllineitems} + +\index{krb5\_error.client (C member)@\spxentry{krb5\_error.client}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_error:c.krb5_error.client}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{client}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Client principal and realm. + +\end{fulllineitems} + +\index{krb5\_error.server (C member)@\spxentry{krb5\_error.server}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_error:c.krb5_error.server}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{server}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Server principal and realm. + +\end{fulllineitems} + +\index{krb5\_error.text (C member)@\spxentry{krb5\_error.text}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_error:c.krb5_error.text}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{text}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Descriptive text. + +\end{fulllineitems} + +\index{krb5\_error.e\_data (C member)@\spxentry{krb5\_error.e\_data}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_error:c.krb5_error.e_data}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_error:c.krb5_error}]{\sphinxcrossref{\DUrole{n}{krb5\_error}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{e\_data}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Additional error\sphinxhyphen{}describing data. + +\end{fulllineitems} + + + +\subsubsection{krb5\_error\_code} +\label{\detokenize{appdev/refs/types/krb5_error_code:krb5-error-code}}\label{\detokenize{appdev/refs/types/krb5_error_code:krb5-error-code-struct}}\label{\detokenize{appdev/refs/types/krb5_error_code::doc}}\index{krb5\_error\_code (C type)@\spxentry{krb5\_error\_code}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_error_code:c.krb5_error_code}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_error\_code}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Used to convey an operation status. + +\sphinxAtStartPar +The value 0 indicates success; any other values are com\_err codes. Use krb5\_get\_error\_message() to obtain a string describing the error. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_error_code:declaration}} +\sphinxAtStartPar +typedef krb5\_int32 krb5\_error\_code + + +\subsubsection{krb5\_expire\_callback\_func} +\label{\detokenize{appdev/refs/types/krb5_expire_callback_func:krb5-expire-callback-func}}\label{\detokenize{appdev/refs/types/krb5_expire_callback_func:krb5-expire-callback-func-struct}}\label{\detokenize{appdev/refs/types/krb5_expire_callback_func::doc}}\index{krb5\_expire\_callback\_func (C type)@\spxentry{krb5\_expire\_callback\_func}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_expire_callback_func:c.krb5_expire_callback_func}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_expire\_callback\_func}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_expire_callback_func:declaration}} +\sphinxAtStartPar +typedef void( * krb5\_expire\_callback\_func) (krb5\_context context, void *data, krb5\_timestamp password\_expiration, krb5\_timestamp account\_expiration, krb5\_boolean is\_last\_req) + + +\subsubsection{krb5\_flags} +\label{\detokenize{appdev/refs/types/krb5_flags:krb5-flags}}\label{\detokenize{appdev/refs/types/krb5_flags:krb5-flags-struct}}\label{\detokenize{appdev/refs/types/krb5_flags::doc}}\index{krb5\_flags (C type)@\spxentry{krb5\_flags}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_flags}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_flags:declaration}} +\sphinxAtStartPar +typedef krb5\_int32 krb5\_flags + + +\subsubsection{krb5\_get\_init\_creds\_opt} +\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:krb5-get-init-creds-opt}}\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:krb5-get-init-creds-opt-struct}}\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt::doc}}\index{krb5\_get\_init\_creds\_opt (C type)@\spxentry{krb5\_get\_init\_creds\_opt}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Store options for \sphinxstyleemphasis{\_krb5\_get\_init\_creds} . + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_get\_init\_creds\_opt krb5\_get\_init\_creds\_opt + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:members}}\index{krb5\_get\_init\_creds\_opt.flags (C member)@\spxentry{krb5\_get\_init\_creds\_opt.flags}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt.flags}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{flags}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_get\_init\_creds\_opt.tkt\_life (C member)@\spxentry{krb5\_get\_init\_creds\_opt.tkt\_life}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt.tkt_life}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_deltat:c.krb5_deltat}]{\sphinxcrossref{\DUrole{n}{krb5\_deltat}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{tkt\_life}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_get\_init\_creds\_opt.renew\_life (C member)@\spxentry{krb5\_get\_init\_creds\_opt.renew\_life}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt.renew_life}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_deltat:c.krb5_deltat}]{\sphinxcrossref{\DUrole{n}{krb5\_deltat}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{renew\_life}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_get\_init\_creds\_opt.forwardable (C member)@\spxentry{krb5\_get\_init\_creds\_opt.forwardable}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt.forwardable}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{forwardable}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_get\_init\_creds\_opt.proxiable (C member)@\spxentry{krb5\_get\_init\_creds\_opt.proxiable}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt.proxiable}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{proxiable}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_get\_init\_creds\_opt.etype\_list (C member)@\spxentry{krb5\_get\_init\_creds\_opt.etype\_list}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt.etype_list}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{etype\_list}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_get\_init\_creds\_opt.etype\_list\_length (C member)@\spxentry{krb5\_get\_init\_creds\_opt.etype\_list\_length}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt.etype_list_length}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{etype\_list\_length}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_get\_init\_creds\_opt.address\_list (C member)@\spxentry{krb5\_get\_init\_creds\_opt.address\_list}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt.address_list}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{address\_list}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_get\_init\_creds\_opt.preauth\_list (C member)@\spxentry{krb5\_get\_init\_creds\_opt.preauth\_list}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt.preauth_list}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_preauthtype:c.krb5_preauthtype}]{\sphinxcrossref{\DUrole{n}{krb5\_preauthtype}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{preauth\_list}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_get\_init\_creds\_opt.preauth\_list\_length (C member)@\spxentry{krb5\_get\_init\_creds\_opt.preauth\_list\_length}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt.preauth_list_length}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{preauth\_list\_length}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_get\_init\_creds\_opt.salt (C member)@\spxentry{krb5\_get\_init\_creds\_opt.salt}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt.salt}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_get_init_creds_opt:c.krb5_get_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_get\_init\_creds\_opt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{salt}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_gic\_opt\_pa\_data} +\label{\detokenize{appdev/refs/types/krb5_gic_opt_pa_data:krb5-gic-opt-pa-data}}\label{\detokenize{appdev/refs/types/krb5_gic_opt_pa_data:krb5-gic-opt-pa-data-struct}}\label{\detokenize{appdev/refs/types/krb5_gic_opt_pa_data::doc}}\index{krb5\_gic\_opt\_pa\_data (C type)@\spxentry{krb5\_gic\_opt\_pa\_data}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_gic_opt_pa_data:c.krb5_gic_opt_pa_data}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_gic\_opt\_pa\_data}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Generic preauth option attribute/value pairs. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_gic_opt_pa_data:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_gic\_opt\_pa\_data krb5\_gic\_opt\_pa\_data + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_gic_opt_pa_data:members}}\index{krb5\_gic\_opt\_pa\_data.attr (C member)@\spxentry{krb5\_gic\_opt\_pa\_data.attr}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_gic_opt_pa_data:c.krb5_gic_opt_pa_data.attr}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_gic_opt_pa_data:c.krb5_gic_opt_pa_data}]{\sphinxcrossref{\DUrole{n}{krb5\_gic\_opt\_pa\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{attr}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_gic\_opt\_pa\_data.value (C member)@\spxentry{krb5\_gic\_opt\_pa\_data.value}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_gic_opt_pa_data:c.krb5_gic_opt_pa_data.value}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_gic_opt_pa_data:c.krb5_gic_opt_pa_data}]{\sphinxcrossref{\DUrole{n}{krb5\_gic\_opt\_pa\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{value}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_int16} +\label{\detokenize{appdev/refs/types/krb5_int16:krb5-int16}}\label{\detokenize{appdev/refs/types/krb5_int16:krb5-int16-struct}}\label{\detokenize{appdev/refs/types/krb5_int16::doc}}\index{krb5\_int16 (C type)@\spxentry{krb5\_int16}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_int16:c.krb5_int16}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_int16}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_int16:declaration}} +\sphinxAtStartPar +typedef int16\_t krb5\_int16 + + +\subsubsection{krb5\_int32} +\label{\detokenize{appdev/refs/types/krb5_int32:krb5-int32}}\label{\detokenize{appdev/refs/types/krb5_int32:krb5-int32-struct}}\label{\detokenize{appdev/refs/types/krb5_int32::doc}}\index{krb5\_int32 (C type)@\spxentry{krb5\_int32}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_int32}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_int32:declaration}} +\sphinxAtStartPar +typedef int32\_t krb5\_int32 + + +\subsubsection{krb5\_kdc\_rep} +\label{\detokenize{appdev/refs/types/krb5_kdc_rep:krb5-kdc-rep}}\label{\detokenize{appdev/refs/types/krb5_kdc_rep:krb5-kdc-rep-struct}}\label{\detokenize{appdev/refs/types/krb5_kdc_rep::doc}}\index{krb5\_kdc\_rep (C type)@\spxentry{krb5\_kdc\_rep}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kdc\_rep}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Representation of the \sphinxstyleemphasis{KDC\sphinxhyphen{}REP} protocol message. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_kdc_rep:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_kdc\_rep krb5\_kdc\_rep + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_kdc_rep:members}}\index{krb5\_kdc\_rep.magic (C member)@\spxentry{krb5\_kdc\_rep.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_rep}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_kdc\_rep.msg\_type (C member)@\spxentry{krb5\_kdc\_rep.msg\_type}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep.msg_type}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_msgtype:c.krb5_msgtype}]{\sphinxcrossref{\DUrole{n}{krb5\_msgtype}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_rep}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{msg\_type}}}}% +\pysigstopmultiline +\sphinxAtStartPar +KRB5\_AS\_REP or KRB5\_KDC\_REP. + +\end{fulllineitems} + +\index{krb5\_kdc\_rep.padata (C member)@\spxentry{krb5\_kdc\_rep.padata}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep.padata}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_data:c.krb5_pa_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_rep}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{padata}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Preauthentication data from KDC. + +\end{fulllineitems} + +\index{krb5\_kdc\_rep.client (C member)@\spxentry{krb5\_kdc\_rep.client}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep.client}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_rep}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{client}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Client principal and realm. + +\end{fulllineitems} + +\index{krb5\_kdc\_rep.ticket (C member)@\spxentry{krb5\_kdc\_rep.ticket}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep.ticket}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_rep}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ticket}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Ticket. + +\end{fulllineitems} + +\index{krb5\_kdc\_rep.enc\_part (C member)@\spxentry{krb5\_kdc\_rep.enc\_part}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep.enc_part}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_rep}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{enc\_part}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Encrypted part of reply. + +\end{fulllineitems} + +\index{krb5\_kdc\_rep.enc\_part2 (C member)@\spxentry{krb5\_kdc\_rep.enc\_part2}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep.enc_part2}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_kdc_rep_part:c.krb5_enc_kdc_rep_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_kdc\_rep\_part}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_rep:c.krb5_kdc_rep}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_rep}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{enc\_part2}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Unencrypted version, if available. + +\end{fulllineitems} + + + +\subsubsection{krb5\_kdc\_req} +\label{\detokenize{appdev/refs/types/krb5_kdc_req:krb5-kdc-req}}\label{\detokenize{appdev/refs/types/krb5_kdc_req:krb5-kdc-req-struct}}\label{\detokenize{appdev/refs/types/krb5_kdc_req::doc}}\index{krb5\_kdc\_req (C type)@\spxentry{krb5\_kdc\_req}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kdc\_req}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +C representation of KDC\sphinxhyphen{}REQ protocol message, including KDC\sphinxhyphen{}REQ\sphinxhyphen{}BODY. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_kdc_req:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_kdc\_req krb5\_kdc\_req + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_kdc_req:members}}\index{krb5\_kdc\_req.magic (C member)@\spxentry{krb5\_kdc\_req.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_kdc\_req.msg\_type (C member)@\spxentry{krb5\_kdc\_req.msg\_type}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.msg_type}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_msgtype:c.krb5_msgtype}]{\sphinxcrossref{\DUrole{n}{krb5\_msgtype}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{msg\_type}}}}% +\pysigstopmultiline +\sphinxAtStartPar +KRB5\_AS\_REQ or KRB5\_TGS\_REQ. + +\end{fulllineitems} + +\index{krb5\_kdc\_req.padata (C member)@\spxentry{krb5\_kdc\_req.padata}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.padata}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_data:c.krb5_pa_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{padata}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Preauthentication data. + +\end{fulllineitems} + +\index{krb5\_kdc\_req.kdc\_options (C member)@\spxentry{krb5\_kdc\_req.kdc\_options}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.kdc_options}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{kdc\_options}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Requested options. + +\end{fulllineitems} + +\index{krb5\_kdc\_req.client (C member)@\spxentry{krb5\_kdc\_req.client}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.client}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{client}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Client principal and realm. + +\end{fulllineitems} + +\index{krb5\_kdc\_req.server (C member)@\spxentry{krb5\_kdc\_req.server}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.server}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{server}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Server principal and realm. + +\end{fulllineitems} + +\index{krb5\_kdc\_req.from (C member)@\spxentry{krb5\_kdc\_req.from}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.from}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{from}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Requested start time. + +\end{fulllineitems} + +\index{krb5\_kdc\_req.till (C member)@\spxentry{krb5\_kdc\_req.till}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.till}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{till}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Requested end time. + +\end{fulllineitems} + +\index{krb5\_kdc\_req.rtime (C member)@\spxentry{krb5\_kdc\_req.rtime}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.rtime}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{rtime}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Requested renewable end time. + +\end{fulllineitems} + +\index{krb5\_kdc\_req.nonce (C member)@\spxentry{krb5\_kdc\_req.nonce}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.nonce}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{nonce}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Nonce to match request and response. + +\end{fulllineitems} + +\index{krb5\_kdc\_req.nktypes (C member)@\spxentry{krb5\_kdc\_req.nktypes}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.nktypes}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{nktypes}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Number of enctypes. + +\end{fulllineitems} + +\index{krb5\_kdc\_req.ktype (C member)@\spxentry{krb5\_kdc\_req.ktype}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.ktype}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ktype}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Requested enctypes. + +\end{fulllineitems} + +\index{krb5\_kdc\_req.addresses (C member)@\spxentry{krb5\_kdc\_req.addresses}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.addresses}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_address:c.krb5_address}]{\sphinxcrossref{\DUrole{n}{krb5\_address}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{addresses}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Requested addresses (optional) + +\end{fulllineitems} + +\index{krb5\_kdc\_req.authorization\_data (C member)@\spxentry{krb5\_kdc\_req.authorization\_data}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.authorization_data}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{authorization\_data}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Encrypted authz data (optional) + +\end{fulllineitems} + +\index{krb5\_kdc\_req.unenc\_authdata (C member)@\spxentry{krb5\_kdc\_req.unenc\_authdata}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.unenc_authdata}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_authdata:c.krb5_authdata}]{\sphinxcrossref{\DUrole{n}{krb5\_authdata}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{unenc\_authdata}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Unencrypted authz data. + +\end{fulllineitems} + +\index{krb5\_kdc\_req.second\_ticket (C member)@\spxentry{krb5\_kdc\_req.second\_ticket}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req.second_ticket}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_kdc_req:c.krb5_kdc_req}]{\sphinxcrossref{\DUrole{n}{krb5\_kdc\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{second\_ticket}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Second ticket array (optional) + +\end{fulllineitems} + + + +\subsubsection{krb5\_keyblock} +\label{\detokenize{appdev/refs/types/krb5_keyblock:krb5-keyblock}}\label{\detokenize{appdev/refs/types/krb5_keyblock:krb5-keyblock-struct}}\label{\detokenize{appdev/refs/types/krb5_keyblock::doc}}\index{krb5\_keyblock (C type)@\spxentry{krb5\_keyblock}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_keyblock}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Exposed contents of a key. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_keyblock:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_keyblock krb5\_keyblock + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_keyblock:members}}\index{krb5\_keyblock.magic (C member)@\spxentry{krb5\_keyblock.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_keyblock.enctype (C member)@\spxentry{krb5\_keyblock.enctype}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock.enctype}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_enctype:c.krb5_enctype}]{\sphinxcrossref{\DUrole{n}{krb5\_enctype}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{enctype}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_keyblock.length (C member)@\spxentry{krb5\_keyblock.length}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock.length}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{length}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_keyblock.contents (C member)@\spxentry{krb5\_keyblock.contents}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock.contents}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_octet:c.krb5_octet}]{\sphinxcrossref{\DUrole{n}{krb5\_octet}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{contents}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_keytab\_entry} +\label{\detokenize{appdev/refs/types/krb5_keytab_entry:krb5-keytab-entry}}\label{\detokenize{appdev/refs/types/krb5_keytab_entry:krb5-keytab-entry-struct}}\label{\detokenize{appdev/refs/types/krb5_keytab_entry::doc}}\index{krb5\_keytab\_entry (C type)@\spxentry{krb5\_keytab\_entry}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_keytab\_entry}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +A key table entry. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_keytab_entry:declaration}} +\sphinxAtStartPar +typedef struct krb5\_keytab\_entry\_st krb5\_keytab\_entry + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_keytab_entry:members}}\index{krb5\_keytab\_entry.magic (C member)@\spxentry{krb5\_keytab\_entry.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab\_entry}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_keytab\_entry.principal (C member)@\spxentry{krb5\_keytab\_entry.principal}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry.principal}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab\_entry}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{principal}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Principal of this key. + +\end{fulllineitems} + +\index{krb5\_keytab\_entry.timestamp (C member)@\spxentry{krb5\_keytab\_entry.timestamp}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry.timestamp}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab\_entry}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{timestamp}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Time entry written to keytable. + +\end{fulllineitems} + +\index{krb5\_keytab\_entry.vno (C member)@\spxentry{krb5\_keytab\_entry.vno}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry.vno}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_kvno:c.krb5_kvno}]{\sphinxcrossref{\DUrole{n}{krb5\_kvno}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab\_entry}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{vno}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Key version number. + +\end{fulllineitems} + +\index{krb5\_keytab\_entry.key (C member)@\spxentry{krb5\_keytab\_entry.key}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry.key}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_keyblock:c.krb5_keyblock}]{\sphinxcrossref{\DUrole{n}{krb5\_keyblock}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_keytab_entry:c.krb5_keytab_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_keytab\_entry}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{key}}}}% +\pysigstopmultiline +\sphinxAtStartPar +The secret key. + +\end{fulllineitems} + + + +\subsubsection{krb5\_keyusage} +\label{\detokenize{appdev/refs/types/krb5_keyusage:krb5-keyusage}}\label{\detokenize{appdev/refs/types/krb5_keyusage:krb5-keyusage-struct}}\label{\detokenize{appdev/refs/types/krb5_keyusage::doc}}\index{krb5\_keyusage (C type)@\spxentry{krb5\_keyusage}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_keyusage:c.krb5_keyusage}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_keyusage}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_keyusage:declaration}} +\sphinxAtStartPar +typedef krb5\_int32 krb5\_keyusage + + +\subsubsection{krb5\_kt\_cursor} +\label{\detokenize{appdev/refs/types/krb5_kt_cursor:krb5-kt-cursor}}\label{\detokenize{appdev/refs/types/krb5_kt_cursor:krb5-kt-cursor-struct}}\label{\detokenize{appdev/refs/types/krb5_kt_cursor::doc}}\index{krb5\_kt\_cursor (C type)@\spxentry{krb5\_kt\_cursor}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kt_cursor:c.krb5_kt_cursor}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kt\_cursor}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_kt_cursor:declaration}} +\sphinxAtStartPar +typedef krb5\_pointer krb5\_kt\_cursor + + +\subsubsection{krb5\_kvno} +\label{\detokenize{appdev/refs/types/krb5_kvno:krb5-kvno}}\label{\detokenize{appdev/refs/types/krb5_kvno:krb5-kvno-struct}}\label{\detokenize{appdev/refs/types/krb5_kvno::doc}}\index{krb5\_kvno (C type)@\spxentry{krb5\_kvno}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_kvno:c.krb5_kvno}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_kvno}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_kvno:declaration}} +\sphinxAtStartPar +typedef unsigned int krb5\_kvno + + +\subsubsection{krb5\_last\_req\_entry} +\label{\detokenize{appdev/refs/types/krb5_last_req_entry:krb5-last-req-entry}}\label{\detokenize{appdev/refs/types/krb5_last_req_entry:krb5-last-req-entry-struct}}\label{\detokenize{appdev/refs/types/krb5_last_req_entry::doc}}\index{krb5\_last\_req\_entry (C type)@\spxentry{krb5\_last\_req\_entry}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_last_req_entry:c.krb5_last_req_entry}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_last\_req\_entry}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Last request entry. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_last_req_entry:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_last\_req\_entry krb5\_last\_req\_entry + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_last_req_entry:members}}\index{krb5\_last\_req\_entry.magic (C member)@\spxentry{krb5\_last\_req\_entry.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_last_req_entry:c.krb5_last_req_entry.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_last_req_entry:c.krb5_last_req_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_last\_req\_entry}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_last\_req\_entry.lr\_type (C member)@\spxentry{krb5\_last\_req\_entry.lr\_type}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_last_req_entry:c.krb5_last_req_entry.lr_type}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_last_req_entry:c.krb5_last_req_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_last\_req\_entry}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{lr\_type}}}}% +\pysigstopmultiline +\sphinxAtStartPar +LR type. + +\end{fulllineitems} + +\index{krb5\_last\_req\_entry.value (C member)@\spxentry{krb5\_last\_req\_entry.value}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_last_req_entry:c.krb5_last_req_entry.value}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_last_req_entry:c.krb5_last_req_entry}]{\sphinxcrossref{\DUrole{n}{krb5\_last\_req\_entry}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{value}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Timestamp. + +\end{fulllineitems} + + + +\subsubsection{krb5\_magic} +\label{\detokenize{appdev/refs/types/krb5_magic:krb5-magic}}\label{\detokenize{appdev/refs/types/krb5_magic:krb5-magic-struct}}\label{\detokenize{appdev/refs/types/krb5_magic::doc}}\index{krb5\_magic (C type)@\spxentry{krb5\_magic}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_magic:declaration}} +\sphinxAtStartPar +typedef krb5\_error\_code krb5\_magic + + +\subsubsection{krb5\_mk\_req\_checksum\_func} +\label{\detokenize{appdev/refs/types/krb5_mk_req_checksum_func:krb5-mk-req-checksum-func}}\label{\detokenize{appdev/refs/types/krb5_mk_req_checksum_func:krb5-mk-req-checksum-func-struct}}\label{\detokenize{appdev/refs/types/krb5_mk_req_checksum_func::doc}}\index{krb5\_mk\_req\_checksum\_func (C type)@\spxentry{krb5\_mk\_req\_checksum\_func}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_mk_req_checksum_func:c.krb5_mk_req_checksum_func}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_mk\_req\_checksum\_func}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Type of function used as a callback to generate checksum data for mk\_req. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_mk_req_checksum_func:declaration}} +\sphinxAtStartPar +typedef krb5\_error\_code( * krb5\_mk\_req\_checksum\_func) (krb5\_context, krb5\_auth\_context, void *, krb5\_data **) + + +\subsubsection{krb5\_msgtype} +\label{\detokenize{appdev/refs/types/krb5_msgtype:krb5-msgtype}}\label{\detokenize{appdev/refs/types/krb5_msgtype:krb5-msgtype-struct}}\label{\detokenize{appdev/refs/types/krb5_msgtype::doc}}\index{krb5\_msgtype (C type)@\spxentry{krb5\_msgtype}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_msgtype:c.krb5_msgtype}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_msgtype}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_msgtype:declaration}} +\sphinxAtStartPar +typedef unsigned int krb5\_msgtype + + +\subsubsection{krb5\_octet} +\label{\detokenize{appdev/refs/types/krb5_octet:krb5-octet}}\label{\detokenize{appdev/refs/types/krb5_octet:krb5-octet-struct}}\label{\detokenize{appdev/refs/types/krb5_octet::doc}}\index{krb5\_octet (C type)@\spxentry{krb5\_octet}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_octet:c.krb5_octet}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_octet}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_octet:declaration}} +\sphinxAtStartPar +typedef uint8\_t krb5\_octet + + +\subsubsection{krb5\_pa\_pac\_req} +\label{\detokenize{appdev/refs/types/krb5_pa_pac_req:krb5-pa-pac-req}}\label{\detokenize{appdev/refs/types/krb5_pa_pac_req:krb5-pa-pac-req-struct}}\label{\detokenize{appdev/refs/types/krb5_pa_pac_req::doc}}\index{krb5\_pa\_pac\_req (C type)@\spxentry{krb5\_pa\_pac\_req}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_pac_req:c.krb5_pa_pac_req}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pa\_pac\_req}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_pa_pac_req:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_pa\_pac\_req krb5\_pa\_pac\_req + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_pa_pac_req:members}}\index{krb5\_pa\_pac\_req.include\_pac (C member)@\spxentry{krb5\_pa\_pac\_req.include\_pac}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_pac_req:c.krb5_pa_pac_req.include_pac}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_boolean:c.krb5_boolean}]{\sphinxcrossref{\DUrole{n}{krb5\_boolean}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_pac_req:c.krb5_pa_pac_req}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_pac\_req}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{include\_pac}}}}% +\pysigstopmultiline +\sphinxAtStartPar +TRUE if a PAC should be included in TGS\sphinxhyphen{}REP. + +\end{fulllineitems} + + + +\subsubsection{krb5\_pa\_server\_referral\_data} +\label{\detokenize{appdev/refs/types/krb5_pa_server_referral_data:krb5-pa-server-referral-data}}\label{\detokenize{appdev/refs/types/krb5_pa_server_referral_data:krb5-pa-server-referral-data-struct}}\label{\detokenize{appdev/refs/types/krb5_pa_server_referral_data::doc}}\index{krb5\_pa\_server\_referral\_data (C type)@\spxentry{krb5\_pa\_server\_referral\_data}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_server_referral_data:c.krb5_pa_server_referral_data}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pa\_server\_referral\_data}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_pa_server_referral_data:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_pa\_server\_referral\_data krb5\_pa\_server\_referral\_data + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_pa_server_referral_data:members}}\index{krb5\_pa\_server\_referral\_data.referred\_realm (C member)@\spxentry{krb5\_pa\_server\_referral\_data.referred\_realm}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_server_referral_data:c.krb5_pa_server_referral_data.referred_realm}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_server_referral_data:c.krb5_pa_server_referral_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_server\_referral\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{referred\_realm}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_pa\_server\_referral\_data.true\_principal\_name (C member)@\spxentry{krb5\_pa\_server\_referral\_data.true\_principal\_name}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_server_referral_data:c.krb5_pa_server_referral_data.true_principal_name}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_server_referral_data:c.krb5_pa_server_referral_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_server\_referral\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{true\_principal\_name}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_pa\_server\_referral\_data.requested\_principal\_name (C member)@\spxentry{krb5\_pa\_server\_referral\_data.requested\_principal\_name}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_server_referral_data:c.krb5_pa_server_referral_data.requested_principal_name}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_server_referral_data:c.krb5_pa_server_referral_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_server\_referral\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{requested\_principal\_name}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_pa\_server\_referral\_data.referral\_valid\_until (C member)@\spxentry{krb5\_pa\_server\_referral\_data.referral\_valid\_until}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_server_referral_data:c.krb5_pa_server_referral_data.referral_valid_until}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_server_referral_data:c.krb5_pa_server_referral_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_server\_referral\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{referral\_valid\_until}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_pa\_server\_referral\_data.rep\_cksum (C member)@\spxentry{krb5\_pa\_server\_referral\_data.rep\_cksum}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_server_referral_data:c.krb5_pa_server_referral_data.rep_cksum}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_checksum:c.krb5_checksum}]{\sphinxcrossref{\DUrole{n}{krb5\_checksum}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_server_referral_data:c.krb5_pa_server_referral_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_server\_referral\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{rep\_cksum}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_pa\_svr\_referral\_data} +\label{\detokenize{appdev/refs/types/krb5_pa_svr_referral_data:krb5-pa-svr-referral-data}}\label{\detokenize{appdev/refs/types/krb5_pa_svr_referral_data:krb5-pa-svr-referral-data-struct}}\label{\detokenize{appdev/refs/types/krb5_pa_svr_referral_data::doc}}\index{krb5\_pa\_svr\_referral\_data (C type)@\spxentry{krb5\_pa\_svr\_referral\_data}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_svr_referral_data:c.krb5_pa_svr_referral_data}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pa\_svr\_referral\_data}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_pa_svr_referral_data:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_pa\_svr\_referral\_data krb5\_pa\_svr\_referral\_data + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_pa_svr_referral_data:members}}\index{krb5\_pa\_svr\_referral\_data.principal (C member)@\spxentry{krb5\_pa\_svr\_referral\_data.principal}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_svr_referral_data:c.krb5_pa_svr_referral_data.principal}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_svr_referral_data:c.krb5_pa_svr_referral_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_svr\_referral\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{principal}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Referred name, only realm is required. + +\end{fulllineitems} + + + +\subsubsection{krb5\_pa\_data} +\label{\detokenize{appdev/refs/types/krb5_pa_data:krb5-pa-data}}\label{\detokenize{appdev/refs/types/krb5_pa_data:krb5-pa-data-struct}}\label{\detokenize{appdev/refs/types/krb5_pa_data::doc}}\index{krb5\_pa\_data (C type)@\spxentry{krb5\_pa\_data}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_data:c.krb5_pa_data}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pa\_data}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Pre\sphinxhyphen{}authentication data. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_pa_data:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_pa\_data krb5\_pa\_data + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_pa_data:members}}\index{krb5\_pa\_data.magic (C member)@\spxentry{krb5\_pa\_data.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_data:c.krb5_pa_data.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_data:c.krb5_pa_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_pa\_data.pa\_type (C member)@\spxentry{krb5\_pa\_data.pa\_type}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_data:c.krb5_pa_data.pa_type}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_preauthtype:c.krb5_preauthtype}]{\sphinxcrossref{\DUrole{n}{krb5\_preauthtype}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_data:c.krb5_pa_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{pa\_type}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Preauthentication data type. + +\end{fulllineitems} + +\index{krb5\_pa\_data.length (C member)@\spxentry{krb5\_pa\_data.length}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_data:c.krb5_pa_data.length}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_data:c.krb5_pa_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{length}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Length of data. + +\end{fulllineitems} + +\index{krb5\_pa\_data.contents (C member)@\spxentry{krb5\_pa\_data.contents}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pa_data:c.krb5_pa_data.contents}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_octet:c.krb5_octet}]{\sphinxcrossref{\DUrole{n}{krb5\_octet}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pa_data:c.krb5_pa_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pa\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{contents}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Data. + +\end{fulllineitems} + + + +\subsubsection{krb5\_pointer} +\label{\detokenize{appdev/refs/types/krb5_pointer:krb5-pointer}}\label{\detokenize{appdev/refs/types/krb5_pointer:krb5-pointer-struct}}\label{\detokenize{appdev/refs/types/krb5_pointer::doc}}\index{krb5\_pointer (C type)@\spxentry{krb5\_pointer}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pointer:c.krb5_pointer}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pointer}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_pointer:declaration}} +\sphinxAtStartPar +typedef void* krb5\_pointer + + +\subsubsection{krb5\_post\_recv\_fn} +\label{\detokenize{appdev/refs/types/krb5_post_recv_fn:krb5-post-recv-fn}}\label{\detokenize{appdev/refs/types/krb5_post_recv_fn:krb5-post-recv-fn-struct}}\label{\detokenize{appdev/refs/types/krb5_post_recv_fn::doc}}\index{krb5\_post\_recv\_fn (C type)@\spxentry{krb5\_post\_recv\_fn}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_post_recv_fn:c.krb5_post_recv_fn}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_post\_recv\_fn}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Hook function for inspecting or overriding KDC replies. + +\sphinxAtStartPar +If \sphinxstyleemphasis{code} is non\sphinxhyphen{}zero, KDC communication failed and \sphinxstyleemphasis{reply} should be ignored. The hook function may return \sphinxstyleemphasis{code} or a different error code, or may synthesize a reply by setting \sphinxstyleemphasis{new\_reply\_out} and return successfully. +The hook function should use krb5\_copy\_data() to construct the value for \sphinxstyleemphasis{new\_reply\_out} , to ensure that it can be freed correctly by the library. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_post_recv_fn:declaration}} +\sphinxAtStartPar +typedef krb5\_error\_code( * krb5\_post\_recv\_fn) (krb5\_context context, void *data, krb5\_error\_code code, const krb5\_data *realm, const krb5\_data *message, const krb5\_data *reply, krb5\_data **new\_reply\_out) + + +\subsubsection{krb5\_pre\_send\_fn} +\label{\detokenize{appdev/refs/types/krb5_pre_send_fn:krb5-pre-send-fn}}\label{\detokenize{appdev/refs/types/krb5_pre_send_fn:krb5-pre-send-fn-struct}}\label{\detokenize{appdev/refs/types/krb5_pre_send_fn::doc}}\index{krb5\_pre\_send\_fn (C type)@\spxentry{krb5\_pre\_send\_fn}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pre_send_fn:c.krb5_pre_send_fn}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pre\_send\_fn}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Hook function for inspecting or modifying messages sent to KDCs. + +\sphinxAtStartPar +If the hook function sets \sphinxstyleemphasis{new\_reply\_out} , \sphinxstyleemphasis{message} will not be sent to the KDC, and the given reply will used instead. +If the hook function sets \sphinxstyleemphasis{new\_message\_out} , the given message will be sent to the KDC in place of \sphinxstyleemphasis{message} . +If the hook function returns successfully without setting either output, \sphinxstyleemphasis{message} will be sent to the KDC normally. +The hook function should use krb5\_copy\_data() to construct the value for \sphinxstyleemphasis{new\_message\_out} or \sphinxstyleemphasis{reply\_out} , to ensure that it can be freed correctly by the library. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_pre_send_fn:declaration}} +\sphinxAtStartPar +typedef krb5\_error\_code( * krb5\_pre\_send\_fn) (krb5\_context context, void *data, const krb5\_data *realm, const krb5\_data *message, krb5\_data **new\_message\_out, krb5\_data **new\_reply\_out) + + +\subsubsection{krb5\_preauthtype} +\label{\detokenize{appdev/refs/types/krb5_preauthtype:krb5-preauthtype}}\label{\detokenize{appdev/refs/types/krb5_preauthtype:krb5-preauthtype-struct}}\label{\detokenize{appdev/refs/types/krb5_preauthtype::doc}}\index{krb5\_preauthtype (C type)@\spxentry{krb5\_preauthtype}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_preauthtype:c.krb5_preauthtype}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_preauthtype}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_preauthtype:declaration}} +\sphinxAtStartPar +typedef krb5\_int32 krb5\_preauthtype + + +\subsubsection{krb5\_principal} +\label{\detokenize{appdev/refs/types/krb5_principal:krb5-principal}}\label{\detokenize{appdev/refs/types/krb5_principal:krb5-principal-struct}}\label{\detokenize{appdev/refs/types/krb5_principal::doc}}\index{krb5\_principal (C type)@\spxentry{krb5\_principal}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_principal}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_principal:declaration}} +\sphinxAtStartPar +typedef krb5\_principal\_data* krb5\_principal + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_principal:members}}\index{krb5\_principal.magic (C member)@\spxentry{krb5\_principal.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_principal.realm (C member)@\spxentry{krb5\_principal.realm}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal.realm}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{realm}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_principal.data (C member)@\spxentry{krb5\_principal.data}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal.data}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{data}}}}% +\pysigstopmultiline +\sphinxAtStartPar +An array of strings. + +\end{fulllineitems} + +\index{krb5\_principal.length (C member)@\spxentry{krb5\_principal.length}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal.length}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{length}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_principal.type (C member)@\spxentry{krb5\_principal.type}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal.type}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{type}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_principal\_data} +\label{\detokenize{appdev/refs/types/krb5_principal_data:krb5-principal-data}}\label{\detokenize{appdev/refs/types/krb5_principal_data:krb5-principal-data-struct}}\label{\detokenize{appdev/refs/types/krb5_principal_data::doc}}\index{krb5\_principal\_data (C type)@\spxentry{krb5\_principal\_data}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_principal_data:c.krb5_principal_data}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_principal\_data}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_principal_data:declaration}} +\sphinxAtStartPar +typedef struct krb5\_principal\_data krb5\_principal\_data + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_principal_data:members}}\index{krb5\_principal\_data.magic (C member)@\spxentry{krb5\_principal\_data.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_principal_data:c.krb5_principal_data.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_principal_data:c.krb5_principal_data}]{\sphinxcrossref{\DUrole{n}{krb5\_principal\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_principal\_data.realm (C member)@\spxentry{krb5\_principal\_data.realm}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_principal_data:c.krb5_principal_data.realm}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_principal_data:c.krb5_principal_data}]{\sphinxcrossref{\DUrole{n}{krb5\_principal\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{realm}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_principal\_data.data (C member)@\spxentry{krb5\_principal\_data.data}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_principal_data:c.krb5_principal_data.data}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_principal_data:c.krb5_principal_data}]{\sphinxcrossref{\DUrole{n}{krb5\_principal\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{data}}}}% +\pysigstopmultiline +\sphinxAtStartPar +An array of strings. + +\end{fulllineitems} + +\index{krb5\_principal\_data.length (C member)@\spxentry{krb5\_principal\_data.length}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_principal_data:c.krb5_principal_data.length}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_principal_data:c.krb5_principal_data}]{\sphinxcrossref{\DUrole{n}{krb5\_principal\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{length}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_principal\_data.type (C member)@\spxentry{krb5\_principal\_data.type}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_principal_data:c.krb5_principal_data.type}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_principal_data:c.krb5_principal_data}]{\sphinxcrossref{\DUrole{n}{krb5\_principal\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{type}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_prompt} +\label{\detokenize{appdev/refs/types/krb5_prompt:krb5-prompt}}\label{\detokenize{appdev/refs/types/krb5_prompt:krb5-prompt-struct}}\label{\detokenize{appdev/refs/types/krb5_prompt::doc}}\index{krb5\_prompt (C type)@\spxentry{krb5\_prompt}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_prompt:c.krb5_prompt}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_prompt}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Text for prompt used in prompter callback function. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_prompt:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_prompt krb5\_prompt + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_prompt:members}}\index{krb5\_prompt.prompt (C member)@\spxentry{krb5\_prompt.prompt}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_prompt:c.krb5_prompt.prompt}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_prompt:c.krb5_prompt}]{\sphinxcrossref{\DUrole{n}{krb5\_prompt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{prompt}}}}% +\pysigstopmultiline +\sphinxAtStartPar +The prompt to show to the user. + +\end{fulllineitems} + +\index{krb5\_prompt.hidden (C member)@\spxentry{krb5\_prompt.hidden}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_prompt:c.krb5_prompt.hidden}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_prompt:c.krb5_prompt}]{\sphinxcrossref{\DUrole{n}{krb5\_prompt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{hidden}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Boolean; informative prompt or hidden (e.g. +PIN) + +\end{fulllineitems} + +\index{krb5\_prompt.reply (C member)@\spxentry{krb5\_prompt.reply}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_prompt:c.krb5_prompt.reply}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_prompt:c.krb5_prompt}]{\sphinxcrossref{\DUrole{n}{krb5\_prompt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{reply}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Must be allocated before call to prompt routine. + +\end{fulllineitems} + + + +\subsubsection{krb5\_prompt\_type} +\label{\detokenize{appdev/refs/types/krb5_prompt_type:krb5-prompt-type}}\label{\detokenize{appdev/refs/types/krb5_prompt_type:krb5-prompt-type-struct}}\label{\detokenize{appdev/refs/types/krb5_prompt_type::doc}}\index{krb5\_prompt\_type (C type)@\spxentry{krb5\_prompt\_type}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_prompt_type:c.krb5_prompt_type}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_prompt\_type}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_prompt_type:declaration}} +\sphinxAtStartPar +typedef krb5\_int32 krb5\_prompt\_type + + +\subsubsection{krb5\_prompter\_fct} +\label{\detokenize{appdev/refs/types/krb5_prompter_fct:krb5-prompter-fct}}\label{\detokenize{appdev/refs/types/krb5_prompter_fct:krb5-prompter-fct-struct}}\label{\detokenize{appdev/refs/types/krb5_prompter_fct::doc}}\index{krb5\_prompter\_fct (C type)@\spxentry{krb5\_prompter\_fct}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_prompter_fct:c.krb5_prompter_fct}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_prompter\_fct}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Pointer to a prompter callback function. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_prompter_fct:declaration}} +\sphinxAtStartPar +typedef krb5\_error\_code( * krb5\_prompter\_fct) (krb5\_context context, void *data, const char *name, const char *banner, int num\_prompts, krb5\_prompt prompts{[}{]}) + + +\subsubsection{krb5\_pwd\_data} +\label{\detokenize{appdev/refs/types/krb5_pwd_data:krb5-pwd-data}}\label{\detokenize{appdev/refs/types/krb5_pwd_data:krb5-pwd-data-struct}}\label{\detokenize{appdev/refs/types/krb5_pwd_data::doc}}\index{krb5\_pwd\_data (C type)@\spxentry{krb5\_pwd\_data}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pwd_data:c.krb5_pwd_data}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pwd\_data}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_pwd_data:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_pwd\_data krb5\_pwd\_data + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_pwd_data:members}}\index{krb5\_pwd\_data.magic (C member)@\spxentry{krb5\_pwd\_data.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pwd_data:c.krb5_pwd_data.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pwd_data:c.krb5_pwd_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pwd\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_pwd\_data.sequence\_count (C member)@\spxentry{krb5\_pwd\_data.sequence\_count}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pwd_data:c.krb5_pwd_data.sequence_count}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pwd_data:c.krb5_pwd_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pwd\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{sequence\_count}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_pwd\_data.element (C member)@\spxentry{krb5\_pwd\_data.element}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pwd_data:c.krb5_pwd_data.element}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/passwd_phrase_element:c.passwd_phrase_element}]{\sphinxcrossref{\DUrole{n}{passwd\_phrase\_element}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_pwd_data:c.krb5_pwd_data}]{\sphinxcrossref{\DUrole{n}{krb5\_pwd\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{element}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_responder\_context} +\label{\detokenize{appdev/refs/types/krb5_responder_context:krb5-responder-context}}\label{\detokenize{appdev/refs/types/krb5_responder_context:krb5-responder-context-struct}}\label{\detokenize{appdev/refs/types/krb5_responder_context::doc}}\index{krb5\_responder\_context (C type)@\spxentry{krb5\_responder\_context}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_context:c.krb5_responder_context}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_context}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +A container for a set of preauthentication questions and answers. + +\sphinxAtStartPar +A responder context is supplied by the krb5 authentication system to a krb5\_responder\_fn callback. It contains a list of questions and can receive answers. Questions contained in a responder context can be listed using krb5\_responder\_list\_questions(), retrieved using krb5\_responder\_get\_challenge(), or answered using krb5\_responder\_set\_answer(). The form of a question’s challenge and answer depend on the question name. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_responder_context:declaration}} +\sphinxAtStartPar +typedef struct krb5\_responder\_context\_st* krb5\_responder\_context + + +\subsubsection{krb5\_responder\_fn} +\label{\detokenize{appdev/refs/types/krb5_responder_fn:krb5-responder-fn}}\label{\detokenize{appdev/refs/types/krb5_responder_fn:krb5-responder-fn-struct}}\label{\detokenize{appdev/refs/types/krb5_responder_fn::doc}}\index{krb5\_responder\_fn (C type)@\spxentry{krb5\_responder\_fn}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_fn:c.krb5_responder_fn}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_fn}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Responder function for an initial credential exchange. + +\sphinxAtStartPar +If a required question is unanswered, the prompter may be called. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_responder_fn:declaration}} +\sphinxAtStartPar +typedef krb5\_error\_code( * krb5\_responder\_fn) (krb5\_context ctx, void *data, krb5\_responder\_context rctx) + + +\subsubsection{krb5\_responder\_otp\_challenge} +\label{\detokenize{appdev/refs/types/krb5_responder_otp_challenge:krb5-responder-otp-challenge}}\label{\detokenize{appdev/refs/types/krb5_responder_otp_challenge:krb5-responder-otp-challenge-struct}}\label{\detokenize{appdev/refs/types/krb5_responder_otp_challenge::doc}}\index{krb5\_responder\_otp\_challenge (C type)@\spxentry{krb5\_responder\_otp\_challenge}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_otp_challenge:c.krb5_responder_otp_challenge}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_otp\_challenge}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_responder_otp_challenge:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_responder\_otp\_challenge krb5\_responder\_otp\_challenge + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_responder_otp_challenge:members}}\index{krb5\_responder\_otp\_challenge.service (C member)@\spxentry{krb5\_responder\_otp\_challenge.service}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_otp_challenge:c.krb5_responder_otp_challenge.service}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_otp_challenge:c.krb5_responder_otp_challenge}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_otp\_challenge}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{service}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_responder\_otp\_challenge.tokeninfo (C member)@\spxentry{krb5\_responder\_otp\_challenge.tokeninfo}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_otp_challenge:c.krb5_responder_otp_challenge.tokeninfo}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_otp\_tokeninfo}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_otp_challenge:c.krb5_responder_otp_challenge}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_otp\_challenge}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{tokeninfo}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_responder\_otp\_tokeninfo} +\label{\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:krb5-responder-otp-tokeninfo}}\label{\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:krb5-responder-otp-tokeninfo-struct}}\label{\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo::doc}}\index{krb5\_responder\_otp\_tokeninfo (C type)@\spxentry{krb5\_responder\_otp\_tokeninfo}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_otp\_tokeninfo}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_responder\_otp\_tokeninfo krb5\_responder\_otp\_tokeninfo + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:members}}\index{krb5\_responder\_otp\_tokeninfo.flags (C member)@\spxentry{krb5\_responder\_otp\_tokeninfo.flags}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo.flags}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_otp\_tokeninfo}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{flags}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_responder\_otp\_tokeninfo.format (C member)@\spxentry{krb5\_responder\_otp\_tokeninfo.format}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo.format}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_otp\_tokeninfo}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{format}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_responder\_otp\_tokeninfo.length (C member)@\spxentry{krb5\_responder\_otp\_tokeninfo.length}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo.length}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_otp\_tokeninfo}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{length}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_responder\_otp\_tokeninfo.vendor (C member)@\spxentry{krb5\_responder\_otp\_tokeninfo.vendor}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo.vendor}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_otp\_tokeninfo}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{vendor}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_responder\_otp\_tokeninfo.challenge (C member)@\spxentry{krb5\_responder\_otp\_tokeninfo.challenge}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo.challenge}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_otp\_tokeninfo}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{challenge}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_responder\_otp\_tokeninfo.token\_id (C member)@\spxentry{krb5\_responder\_otp\_tokeninfo.token\_id}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo.token_id}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_otp\_tokeninfo}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{token\_id}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_responder\_otp\_tokeninfo.alg\_id (C member)@\spxentry{krb5\_responder\_otp\_tokeninfo.alg\_id}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo.alg_id}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_otp_tokeninfo:c.krb5_responder_otp_tokeninfo}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_otp\_tokeninfo}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{alg\_id}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_responder\_pkinit\_challenge} +\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_challenge:krb5-responder-pkinit-challenge}}\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_challenge:krb5-responder-pkinit-challenge-struct}}\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_challenge::doc}}\index{krb5\_responder\_pkinit\_challenge (C type)@\spxentry{krb5\_responder\_pkinit\_challenge}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_challenge:c.krb5_responder_pkinit_challenge}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_pkinit\_challenge}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_challenge:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_responder\_pkinit\_challenge krb5\_responder\_pkinit\_challenge + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_challenge:members}}\index{krb5\_responder\_pkinit\_challenge.identities (C member)@\spxentry{krb5\_responder\_pkinit\_challenge.identities}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_challenge:c.krb5_responder_pkinit_challenge.identities}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_pkinit_identity:c.krb5_responder_pkinit_identity}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_pkinit\_identity}}}}\DUrole{w}{ }\DUrole{p}{*}\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_pkinit_challenge:c.krb5_responder_pkinit_challenge}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_pkinit\_challenge}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{identities}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_responder\_pkinit\_identity} +\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_identity:krb5-responder-pkinit-identity}}\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_identity:krb5-responder-pkinit-identity-struct}}\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_identity::doc}}\index{krb5\_responder\_pkinit\_identity (C type)@\spxentry{krb5\_responder\_pkinit\_identity}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_identity:c.krb5_responder_pkinit_identity}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_responder\_pkinit\_identity}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_identity:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_responder\_pkinit\_identity krb5\_responder\_pkinit\_identity + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_identity:members}}\index{krb5\_responder\_pkinit\_identity.identity (C member)@\spxentry{krb5\_responder\_pkinit\_identity.identity}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_identity:c.krb5_responder_pkinit_identity.identity}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_pkinit_identity:c.krb5_responder_pkinit_identity}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_pkinit\_identity}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{identity}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_responder\_pkinit\_identity.token\_flags (C member)@\spxentry{krb5\_responder\_pkinit\_identity.token\_flags}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_responder_pkinit_identity:c.krb5_responder_pkinit_identity.token_flags}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_responder_pkinit_identity:c.krb5_responder_pkinit_identity}]{\sphinxcrossref{\DUrole{n}{krb5\_responder\_pkinit\_identity}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{token\_flags}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_response} +\label{\detokenize{appdev/refs/types/krb5_response:krb5-response}}\label{\detokenize{appdev/refs/types/krb5_response:krb5-response-struct}}\label{\detokenize{appdev/refs/types/krb5_response::doc}}\index{krb5\_response (C type)@\spxentry{krb5\_response}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_response:c.krb5_response}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_response}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_response:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_response krb5\_response + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_response:members}}\index{krb5\_response.magic (C member)@\spxentry{krb5\_response.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_response:c.krb5_response.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_response:c.krb5_response}]{\sphinxcrossref{\DUrole{n}{krb5\_response}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_response.message\_type (C member)@\spxentry{krb5\_response.message\_type}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_response:c.krb5_response.message_type}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_octet:c.krb5_octet}]{\sphinxcrossref{\DUrole{n}{krb5\_octet}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_response:c.krb5_response}]{\sphinxcrossref{\DUrole{n}{krb5\_response}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{message\_type}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_response.response (C member)@\spxentry{krb5\_response.response}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_response:c.krb5_response.response}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_response:c.krb5_response}]{\sphinxcrossref{\DUrole{n}{krb5\_response}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{response}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_response.expected\_nonce (C member)@\spxentry{krb5\_response.expected\_nonce}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_response:c.krb5_response.expected_nonce}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_response:c.krb5_response}]{\sphinxcrossref{\DUrole{n}{krb5\_response}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{expected\_nonce}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_response.request\_time (C member)@\spxentry{krb5\_response.request\_time}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_response:c.krb5_response.request_time}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_response:c.krb5_response}]{\sphinxcrossref{\DUrole{n}{krb5\_response}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{request\_time}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_replay\_data} +\label{\detokenize{appdev/refs/types/krb5_replay_data:krb5-replay-data}}\label{\detokenize{appdev/refs/types/krb5_replay_data:krb5-replay-data-struct}}\label{\detokenize{appdev/refs/types/krb5_replay_data::doc}}\index{krb5\_replay\_data (C type)@\spxentry{krb5\_replay\_data}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_replay\_data}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Replay data. + +\sphinxAtStartPar +Sequence number and timestamp information output by krb5\_rd\_priv() and krb5\_rd\_safe(). + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_replay_data:declaration}} +\sphinxAtStartPar +typedef struct krb5\_replay\_data krb5\_replay\_data + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_replay_data:members}}\index{krb5\_replay\_data.timestamp (C member)@\spxentry{krb5\_replay\_data.timestamp}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data.timestamp}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data}]{\sphinxcrossref{\DUrole{n}{krb5\_replay\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{timestamp}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Timestamp, seconds portion. + +\end{fulllineitems} + +\index{krb5\_replay\_data.usec (C member)@\spxentry{krb5\_replay\_data.usec}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data.usec}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data}]{\sphinxcrossref{\DUrole{n}{krb5\_replay\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{usec}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Timestamp, microseconds portion. + +\end{fulllineitems} + +\index{krb5\_replay\_data.seq (C member)@\spxentry{krb5\_replay\_data.seq}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data.seq}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_ui_4:c.krb5_ui_4}]{\sphinxcrossref{\DUrole{n}{krb5\_ui\_4}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_replay_data:c.krb5_replay_data}]{\sphinxcrossref{\DUrole{n}{krb5\_replay\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{seq}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Sequence number. + +\end{fulllineitems} + + + +\subsubsection{krb5\_ticket} +\label{\detokenize{appdev/refs/types/krb5_ticket:krb5-ticket}}\label{\detokenize{appdev/refs/types/krb5_ticket:krb5-ticket-struct}}\label{\detokenize{appdev/refs/types/krb5_ticket::doc}}\index{krb5\_ticket (C type)@\spxentry{krb5\_ticket}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_ticket}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Ticket structure. + +\sphinxAtStartPar +The C representation of the ticket message, with a pointer to the C representation of the encrypted part. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_ticket:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_ticket krb5\_ticket + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_ticket:members}}\index{krb5\_ticket.magic (C member)@\spxentry{krb5\_ticket.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_ticket.server (C member)@\spxentry{krb5\_ticket.server}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket.server}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_principal:c.krb5_principal}]{\sphinxcrossref{\DUrole{n}{krb5\_principal}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{server}}}}% +\pysigstopmultiline +\sphinxAtStartPar +server name/realm + +\end{fulllineitems} + +\index{krb5\_ticket.enc\_part (C member)@\spxentry{krb5\_ticket.enc\_part}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket.enc_part}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_data:c.krb5_enc_data}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{enc\_part}}}}% +\pysigstopmultiline +\sphinxAtStartPar +encryption type, kvno, encrypted encoding + +\end{fulllineitems} + +\index{krb5\_ticket.enc\_part2 (C member)@\spxentry{krb5\_ticket.enc\_part2}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket.enc_part2}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_enc_tkt_part:c.krb5_enc_tkt_part}]{\sphinxcrossref{\DUrole{n}{krb5\_enc\_tkt\_part}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{enc\_part2}}}}% +\pysigstopmultiline +\sphinxAtStartPar +ptr to decrypted version, if available + +\end{fulllineitems} + + + +\subsubsection{krb5\_ticket\_times} +\label{\detokenize{appdev/refs/types/krb5_ticket_times:krb5-ticket-times}}\label{\detokenize{appdev/refs/types/krb5_ticket_times:krb5-ticket-times-struct}}\label{\detokenize{appdev/refs/types/krb5_ticket_times::doc}}\index{krb5\_ticket\_times (C type)@\spxentry{krb5\_ticket\_times}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_ticket\_times}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Ticket start time, end time, and renewal duration. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_ticket_times:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_ticket\_times krb5\_ticket\_times + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_ticket_times:members}}\index{krb5\_ticket\_times.authtime (C member)@\spxentry{krb5\_ticket\_times.authtime}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times.authtime}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket\_times}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{authtime}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Time at which KDC issued the initial ticket that corresponds to this ticket. + +\end{fulllineitems} + +\index{krb5\_ticket\_times.starttime (C member)@\spxentry{krb5\_ticket\_times.starttime}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times.starttime}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket\_times}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{starttime}}}}% +\pysigstopmultiline +\sphinxAtStartPar +optional in ticket, if not present, use \sphinxstyleemphasis{authtime} + +\end{fulllineitems} + +\index{krb5\_ticket\_times.endtime (C member)@\spxentry{krb5\_ticket\_times.endtime}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times.endtime}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket\_times}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{endtime}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Ticket expiration time. + +\end{fulllineitems} + +\index{krb5\_ticket\_times.renew\_till (C member)@\spxentry{krb5\_ticket\_times.renew\_till}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times.renew_till}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}]{\sphinxcrossref{\DUrole{n}{krb5\_timestamp}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket_times:c.krb5_ticket_times}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket\_times}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{renew\_till}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Latest time at which renewal of ticket can be valid. + +\end{fulllineitems} + + + +\subsubsection{krb5\_timestamp} +\label{\detokenize{appdev/refs/types/krb5_timestamp:krb5-timestamp}}\label{\detokenize{appdev/refs/types/krb5_timestamp:krb5-timestamp-struct}}\label{\detokenize{appdev/refs/types/krb5_timestamp::doc}}\index{krb5\_timestamp (C type)@\spxentry{krb5\_timestamp}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_timestamp:c.krb5_timestamp}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_timestamp}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Represents a timestamp in seconds since the POSIX epoch. + +\sphinxAtStartPar +This legacy type is used frequently in the ABI, but cannot represent timestamps after 2038 as a positive number. Code which uses this type should cast values of it to uint32\_t so that negative values are treated as timestamps between 2038 and 2106 on platforms with 64\sphinxhyphen{}bit time\_t. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_timestamp:declaration}} +\sphinxAtStartPar +typedef krb5\_int32 krb5\_timestamp + + +\subsubsection{krb5\_tkt\_authent} +\label{\detokenize{appdev/refs/types/krb5_tkt_authent:krb5-tkt-authent}}\label{\detokenize{appdev/refs/types/krb5_tkt_authent:krb5-tkt-authent-struct}}\label{\detokenize{appdev/refs/types/krb5_tkt_authent::doc}}\index{krb5\_tkt\_authent (C type)@\spxentry{krb5\_tkt\_authent}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_tkt_authent:c.krb5_tkt_authent}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_tkt\_authent}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Ticket authentication data. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_tkt_authent:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_tkt\_authent krb5\_tkt\_authent + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_tkt_authent:members}}\index{krb5\_tkt\_authent.magic (C member)@\spxentry{krb5\_tkt\_authent.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_tkt_authent:c.krb5_tkt_authent.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_tkt_authent:c.krb5_tkt_authent}]{\sphinxcrossref{\DUrole{n}{krb5\_tkt\_authent}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_tkt\_authent.ticket (C member)@\spxentry{krb5\_tkt\_authent.ticket}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_tkt_authent:c.krb5_tkt_authent.ticket}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_ticket:c.krb5_ticket}]{\sphinxcrossref{\DUrole{n}{krb5\_ticket}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_tkt_authent:c.krb5_tkt_authent}]{\sphinxcrossref{\DUrole{n}{krb5\_tkt\_authent}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ticket}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_tkt\_authent.authenticator (C member)@\spxentry{krb5\_tkt\_authent.authenticator}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_tkt_authent:c.krb5_tkt_authent.authenticator}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_authenticator:c.krb5_authenticator}]{\sphinxcrossref{\DUrole{n}{krb5\_authenticator}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_tkt_authent:c.krb5_tkt_authent}]{\sphinxcrossref{\DUrole{n}{krb5\_tkt\_authent}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{authenticator}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_tkt\_authent.ap\_options (C member)@\spxentry{krb5\_tkt\_authent.ap\_options}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_tkt_authent:c.krb5_tkt_authent.ap_options}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_tkt_authent:c.krb5_tkt_authent}]{\sphinxcrossref{\DUrole{n}{krb5\_tkt\_authent}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ap\_options}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_trace\_callback} +\label{\detokenize{appdev/refs/types/krb5_trace_callback:krb5-trace-callback}}\label{\detokenize{appdev/refs/types/krb5_trace_callback:krb5-trace-callback-struct}}\label{\detokenize{appdev/refs/types/krb5_trace_callback::doc}}\index{krb5\_trace\_callback (C type)@\spxentry{krb5\_trace\_callback}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_trace_callback:c.krb5_trace_callback}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_trace\_callback}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_trace_callback:declaration}} +\sphinxAtStartPar +typedef void( * krb5\_trace\_callback) (krb5\_context context, const krb5\_trace\_info *info, void *cb\_data) + + +\subsubsection{krb5\_trace\_info} +\label{\detokenize{appdev/refs/types/krb5_trace_info:krb5-trace-info}}\label{\detokenize{appdev/refs/types/krb5_trace_info:krb5-trace-info-struct}}\label{\detokenize{appdev/refs/types/krb5_trace_info::doc}}\index{krb5\_trace\_info (C type)@\spxentry{krb5\_trace\_info}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_trace_info:c.krb5_trace_info}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_trace\_info}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +A wrapper for passing information to a \sphinxstyleemphasis{krb5\_trace\_callback} . + +\sphinxAtStartPar +Currently, it only contains the formatted message as determined the the format string and arguments of the tracing macro, but it may be extended to contain more fields in the future. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_trace_info:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_trace\_info krb5\_trace\_info + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_trace_info:members}}\index{krb5\_trace\_info.message (C member)@\spxentry{krb5\_trace\_info.message}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_trace_info:c.krb5_trace_info.message}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{const}\DUrole{w}{ }\DUrole{kt}{char}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_trace_info:c.krb5_trace_info}]{\sphinxcrossref{\DUrole{n}{krb5\_trace\_info}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{message}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_transited} +\label{\detokenize{appdev/refs/types/krb5_transited:krb5-transited}}\label{\detokenize{appdev/refs/types/krb5_transited:krb5-transited-struct}}\label{\detokenize{appdev/refs/types/krb5_transited::doc}}\index{krb5\_transited (C type)@\spxentry{krb5\_transited}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_transited:c.krb5_transited}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_transited}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Structure for transited encoding. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_transited:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_transited krb5\_transited + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_transited:members}}\index{krb5\_transited.magic (C member)@\spxentry{krb5\_transited.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_transited:c.krb5_transited.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_transited:c.krb5_transited}]{\sphinxcrossref{\DUrole{n}{krb5\_transited}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_transited.tr\_type (C member)@\spxentry{krb5\_transited.tr\_type}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_transited:c.krb5_transited.tr_type}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_octet:c.krb5_octet}]{\sphinxcrossref{\DUrole{n}{krb5\_octet}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_transited:c.krb5_transited}]{\sphinxcrossref{\DUrole{n}{krb5\_transited}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{tr\_type}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Transited encoding type. + +\end{fulllineitems} + +\index{krb5\_transited.tr\_contents (C member)@\spxentry{krb5\_transited.tr\_contents}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_transited:c.krb5_transited.tr_contents}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_transited:c.krb5_transited}]{\sphinxcrossref{\DUrole{n}{krb5\_transited}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{tr\_contents}}}}% +\pysigstopmultiline +\sphinxAtStartPar +Contents. + +\end{fulllineitems} + + + +\subsubsection{krb5\_typed\_data} +\label{\detokenize{appdev/refs/types/krb5_typed_data:krb5-typed-data}}\label{\detokenize{appdev/refs/types/krb5_typed_data:krb5-typed-data-struct}}\label{\detokenize{appdev/refs/types/krb5_typed_data::doc}}\index{krb5\_typed\_data (C type)@\spxentry{krb5\_typed\_data}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_typed_data:c.krb5_typed_data}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_typed\_data}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_typed_data:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_typed\_data krb5\_typed\_data + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_typed_data:members}}\index{krb5\_typed\_data.magic (C member)@\spxentry{krb5\_typed\_data.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_typed_data:c.krb5_typed_data.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_typed_data:c.krb5_typed_data}]{\sphinxcrossref{\DUrole{n}{krb5\_typed\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_typed\_data.type (C member)@\spxentry{krb5\_typed\_data.type}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_typed_data:c.krb5_typed_data.type}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_int32:c.krb5_int32}]{\sphinxcrossref{\DUrole{n}{krb5\_int32}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_typed_data:c.krb5_typed_data}]{\sphinxcrossref{\DUrole{n}{krb5\_typed\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{type}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_typed\_data.length (C member)@\spxentry{krb5\_typed\_data.length}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_typed_data:c.krb5_typed_data.length}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{unsigned}\DUrole{w}{ }\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_typed_data:c.krb5_typed_data}]{\sphinxcrossref{\DUrole{n}{krb5\_typed\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{length}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_typed\_data.data (C member)@\spxentry{krb5\_typed\_data.data}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_typed_data:c.krb5_typed_data.data}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_octet:c.krb5_octet}]{\sphinxcrossref{\DUrole{n}{krb5\_octet}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_typed_data:c.krb5_typed_data}]{\sphinxcrossref{\DUrole{n}{krb5\_typed\_data}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{data}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsubsection{krb5\_ui\_2} +\label{\detokenize{appdev/refs/types/krb5_ui_2:krb5-ui-2}}\label{\detokenize{appdev/refs/types/krb5_ui_2:krb5-ui-2-struct}}\label{\detokenize{appdev/refs/types/krb5_ui_2::doc}}\index{krb5\_ui\_2 (C type)@\spxentry{krb5\_ui\_2}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ui_2:c.krb5_ui_2}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_ui\_2}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_ui_2:declaration}} +\sphinxAtStartPar +typedef uint16\_t krb5\_ui\_2 + + +\subsubsection{krb5\_ui\_4} +\label{\detokenize{appdev/refs/types/krb5_ui_4:krb5-ui-4}}\label{\detokenize{appdev/refs/types/krb5_ui_4:krb5-ui-4-struct}}\label{\detokenize{appdev/refs/types/krb5_ui_4::doc}}\index{krb5\_ui\_4 (C type)@\spxentry{krb5\_ui\_4}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ui_4:c.krb5_ui_4}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_ui\_4}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_ui_4:declaration}} +\sphinxAtStartPar +typedef uint32\_t krb5\_ui\_4 + + +\subsubsection{krb5\_verify\_init\_creds\_opt} +\label{\detokenize{appdev/refs/types/krb5_verify_init_creds_opt:krb5-verify-init-creds-opt}}\label{\detokenize{appdev/refs/types/krb5_verify_init_creds_opt:krb5-verify-init-creds-opt-struct}}\label{\detokenize{appdev/refs/types/krb5_verify_init_creds_opt::doc}}\index{krb5\_verify\_init\_creds\_opt (C type)@\spxentry{krb5\_verify\_init\_creds\_opt}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_verify_init_creds_opt:c.krb5_verify_init_creds_opt}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_verify\_init\_creds\_opt}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_verify_init_creds_opt:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_verify\_init\_creds\_opt krb5\_verify\_init\_creds\_opt + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/krb5_verify_init_creds_opt:members}}\index{krb5\_verify\_init\_creds\_opt.flags (C member)@\spxentry{krb5\_verify\_init\_creds\_opt.flags}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_verify_init_creds_opt:c.krb5_verify_init_creds_opt.flags}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_flags:c.krb5_flags}]{\sphinxcrossref{\DUrole{n}{krb5\_flags}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_verify_init_creds_opt:c.krb5_verify_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_verify\_init\_creds\_opt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{flags}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{krb5\_verify\_init\_creds\_opt.ap\_req\_nofail (C member)@\spxentry{krb5\_verify\_init\_creds\_opt.ap\_req\_nofail}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_verify_init_creds_opt:c.krb5_verify_init_creds_opt.ap_req_nofail}}% +\pysigstartmultiline +\pysigline{\DUrole{kt}{int}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/krb5_verify_init_creds_opt:c.krb5_verify_init_creds_opt}]{\sphinxcrossref{\DUrole{n}{krb5\_verify\_init\_creds\_opt}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{ap\_req\_nofail}}}}% +\pysigstopmultiline +\sphinxAtStartPar +boolean + +\end{fulllineitems} + + + +\subsubsection{passwd\_phrase\_element} +\label{\detokenize{appdev/refs/types/passwd_phrase_element:passwd-phrase-element}}\label{\detokenize{appdev/refs/types/passwd_phrase_element:passwd-phrase-element-struct}}\label{\detokenize{appdev/refs/types/passwd_phrase_element::doc}}\index{passwd\_phrase\_element (C type)@\spxentry{passwd\_phrase\_element}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/passwd_phrase_element:c.passwd_phrase_element}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{passwd\_phrase\_element}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/passwd_phrase_element:declaration}} +\sphinxAtStartPar +typedef struct \_passwd\_phrase\_element passwd\_phrase\_element + + +\paragraph{Members} +\label{\detokenize{appdev/refs/types/passwd_phrase_element:members}}\index{passwd\_phrase\_element.magic (C member)@\spxentry{passwd\_phrase\_element.magic}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/passwd_phrase_element:c.passwd_phrase_element.magic}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_magic:c.krb5_magic}]{\sphinxcrossref{\DUrole{n}{krb5\_magic}}}}\DUrole{w}{ }\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/passwd_phrase_element:c.passwd_phrase_element}]{\sphinxcrossref{\DUrole{n}{passwd\_phrase\_element}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{magic}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{passwd\_phrase\_element.passwd (C member)@\spxentry{passwd\_phrase\_element.passwd}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/passwd_phrase_element:c.passwd_phrase_element.passwd}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/passwd_phrase_element:c.passwd_phrase_element}]{\sphinxcrossref{\DUrole{n}{passwd\_phrase\_element}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{passwd}}}}% +\pysigstopmultiline +\end{fulllineitems} + +\index{passwd\_phrase\_element.phrase (C member)@\spxentry{passwd\_phrase\_element.phrase}\spxextra{C member}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/passwd_phrase_element:c.passwd_phrase_element.phrase}}% +\pysigstartmultiline +\pysigline{{\hyperref[\detokenize{appdev/refs/types/krb5_data:c.krb5_data}]{\sphinxcrossref{\DUrole{n}{krb5\_data}}}}\DUrole{w}{ }\DUrole{p}{*}\sphinxcode{\sphinxupquote{{\hyperref[\detokenize{appdev/refs/types/passwd_phrase_element:c.passwd_phrase_element}]{\sphinxcrossref{\DUrole{n}{passwd\_phrase\_element}}}}\DUrole{p}{.}}}\sphinxbfcode{\sphinxupquote{\DUrole{n}{phrase}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\subsection{Internal} +\label{\detokenize{appdev/refs/types/index:internal}} + +\subsubsection{krb5\_auth\_context} +\label{\detokenize{appdev/refs/types/krb5_auth_context:krb5-auth-context}}\label{\detokenize{appdev/refs/types/krb5_auth_context:krb5-auth-context-struct}}\label{\detokenize{appdev/refs/types/krb5_auth_context::doc}}\index{krb5\_auth\_context (C type)@\spxentry{krb5\_auth\_context}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_auth_context:c.krb5_auth_context}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_auth\_context}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_auth_context:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_auth\_context* krb5\_auth\_context + + +\subsubsection{krb5\_cksumtype} +\label{\detokenize{appdev/refs/types/krb5_cksumtype:krb5-cksumtype}}\label{\detokenize{appdev/refs/types/krb5_cksumtype:krb5-cksumtype-struct}}\label{\detokenize{appdev/refs/types/krb5_cksumtype::doc}}\index{krb5\_cksumtype (C type)@\spxentry{krb5\_cksumtype}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cksumtype:c.krb5_cksumtype}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cksumtype}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_cksumtype:declaration}} +\sphinxAtStartPar +typedef krb5\_int32 krb5\_cksumtype + + +\subsubsection{krb5\_context} +\label{\detokenize{appdev/refs/types/krb5_context:krb5-context}}\label{\detokenize{appdev/refs/types/krb5_context:krb5-context-struct}}\label{\detokenize{appdev/refs/types/krb5_context::doc}}\index{krb5\_context (C type)@\spxentry{krb5\_context}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_context:c.krb5_context}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_context}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_context:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_context* krb5\_context + + +\subsubsection{krb5\_cc\_cursor} +\label{\detokenize{appdev/refs/types/krb5_cc_cursor:krb5-cc-cursor}}\label{\detokenize{appdev/refs/types/krb5_cc_cursor:krb5-cc-cursor-struct}}\label{\detokenize{appdev/refs/types/krb5_cc_cursor::doc}}\index{krb5\_cc\_cursor (C type)@\spxentry{krb5\_cc\_cursor}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cc_cursor:c.krb5_cc_cursor}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cc\_cursor}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Cursor for sequential lookup. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_cc_cursor:declaration}} +\sphinxAtStartPar +typedef krb5\_pointer krb5\_cc\_cursor + + +\subsubsection{krb5\_ccache} +\label{\detokenize{appdev/refs/types/krb5_ccache:krb5-ccache}}\label{\detokenize{appdev/refs/types/krb5_ccache:krb5-ccache-struct}}\label{\detokenize{appdev/refs/types/krb5_ccache::doc}}\index{krb5\_ccache (C type)@\spxentry{krb5\_ccache}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_ccache:c.krb5_ccache}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_ccache}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_ccache:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_ccache* krb5\_ccache + + +\subsubsection{krb5\_cccol\_cursor} +\label{\detokenize{appdev/refs/types/krb5_cccol_cursor:krb5-cccol-cursor}}\label{\detokenize{appdev/refs/types/krb5_cccol_cursor:krb5-cccol-cursor-struct}}\label{\detokenize{appdev/refs/types/krb5_cccol_cursor::doc}}\index{krb5\_cccol\_cursor (C type)@\spxentry{krb5\_cccol\_cursor}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_cccol_cursor:c.krb5_cccol_cursor}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_cccol\_cursor}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Cursor for iterating over all ccaches. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_cccol_cursor:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_cccol\_cursor* krb5\_cccol\_cursor + + +\subsubsection{krb5\_init\_creds\_context} +\label{\detokenize{appdev/refs/types/krb5_init_creds_context:krb5-init-creds-context}}\label{\detokenize{appdev/refs/types/krb5_init_creds_context:krb5-init-creds-context-struct}}\label{\detokenize{appdev/refs/types/krb5_init_creds_context::doc}}\index{krb5\_init\_creds\_context (C type)@\spxentry{krb5\_init\_creds\_context}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_init_creds_context:c.krb5_init_creds_context}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_init\_creds\_context}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_init_creds_context:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_init\_creds\_context* krb5\_init\_creds\_context + + +\subsubsection{krb5\_key} +\label{\detokenize{appdev/refs/types/krb5_key:krb5-key}}\label{\detokenize{appdev/refs/types/krb5_key:krb5-key-struct}}\label{\detokenize{appdev/refs/types/krb5_key::doc}}\index{krb5\_key (C type)@\spxentry{krb5\_key}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_key:c.krb5_key}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_key}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +Opaque identifier for a key. + +\sphinxAtStartPar +Use with the krb5\_k APIs for better performance for repeated operations with the same key and usage. Key identifiers must not be used simultaneously within multiple threads, as they may contain mutable internal state and are not mutex\sphinxhyphen{}protected. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_key:declaration}} +\sphinxAtStartPar +typedef struct krb5\_key\_st* krb5\_key + + +\subsubsection{krb5\_keytab} +\label{\detokenize{appdev/refs/types/krb5_keytab:krb5-keytab}}\label{\detokenize{appdev/refs/types/krb5_keytab:krb5-keytab-struct}}\label{\detokenize{appdev/refs/types/krb5_keytab::doc}}\index{krb5\_keytab (C type)@\spxentry{krb5\_keytab}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_keytab:c.krb5_keytab}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_keytab}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_keytab:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_kt* krb5\_keytab + + +\subsubsection{krb5\_pac} +\label{\detokenize{appdev/refs/types/krb5_pac:krb5-pac}}\label{\detokenize{appdev/refs/types/krb5_pac:krb5-pac-struct}}\label{\detokenize{appdev/refs/types/krb5_pac::doc}}\index{krb5\_pac (C type)@\spxentry{krb5\_pac}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_pac:c.krb5_pac}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_pac}}}}% +\pysigstopmultiline +\end{fulllineitems} + + +\sphinxAtStartPar +PAC data structure to convey authorization information. + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_pac:declaration}} +\sphinxAtStartPar +typedef struct krb5\_pac\_data* krb5\_pac + + +\subsubsection{krb5\_rcache} +\label{\detokenize{appdev/refs/types/krb5_rcache:krb5-rcache}}\label{\detokenize{appdev/refs/types/krb5_rcache:krb5-rcache-struct}}\label{\detokenize{appdev/refs/types/krb5_rcache::doc}}\index{krb5\_rcache (C type)@\spxentry{krb5\_rcache}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_rcache:c.krb5_rcache}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_rcache}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_rcache:declaration}} +\sphinxAtStartPar +typedef struct krb5\_rc\_st* krb5\_rcache + + +\subsubsection{krb5\_tkt\_creds\_context} +\label{\detokenize{appdev/refs/types/krb5_tkt_creds_context:krb5-tkt-creds-context}}\label{\detokenize{appdev/refs/types/krb5_tkt_creds_context:krb5-tkt-creds-context-struct}}\label{\detokenize{appdev/refs/types/krb5_tkt_creds_context::doc}}\index{krb5\_tkt\_creds\_context (C type)@\spxentry{krb5\_tkt\_creds\_context}\spxextra{C type}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/types/krb5_tkt_creds_context:c.krb5_tkt_creds_context}}% +\pysigstartmultiline +\pysigline{\DUrole{k}{type}\DUrole{w}{ }\sphinxbfcode{\sphinxupquote{\DUrole{n}{krb5\_tkt\_creds\_context}}}}% +\pysigstopmultiline +\end{fulllineitems} + + + +\paragraph{Declaration} +\label{\detokenize{appdev/refs/types/krb5_tkt_creds_context:declaration}} +\sphinxAtStartPar +typedef struct \_krb5\_tkt\_creds\_context* krb5\_tkt\_creds\_context + + +\section{krb5 simple macros} +\label{\detokenize{appdev/refs/macros/index:krb5-simple-macros}}\label{\detokenize{appdev/refs/macros/index::doc}} + +\subsection{Public} +\label{\detokenize{appdev/refs/macros/index:public}} + +\subsubsection{ADDRTYPE\_ADDRPORT} +\label{\detokenize{appdev/refs/macros/ADDRTYPE_ADDRPORT:addrtype-addrport}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_ADDRPORT:addrtype-addrport-data}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_ADDRPORT::doc}}\index{ADDRTYPE\_ADDRPORT (built\sphinxhyphen{}in variable)@\spxentry{ADDRTYPE\_ADDRPORT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ADDRTYPE_ADDRPORT:ADDRTYPE_ADDRPORT}}\pysigline{\sphinxbfcode{\sphinxupquote{ADDRTYPE\_ADDRPORT}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ADDRTYPE\_ADDRPORT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0100}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ADDRTYPE\_CHAOS} +\label{\detokenize{appdev/refs/macros/ADDRTYPE_CHAOS:addrtype-chaos}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_CHAOS:addrtype-chaos-data}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_CHAOS::doc}}\index{ADDRTYPE\_CHAOS (built\sphinxhyphen{}in variable)@\spxentry{ADDRTYPE\_CHAOS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ADDRTYPE_CHAOS:ADDRTYPE_CHAOS}}\pysigline{\sphinxbfcode{\sphinxupquote{ADDRTYPE\_CHAOS}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ADDRTYPE\_CHAOS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0005}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ADDRTYPE\_DDP} +\label{\detokenize{appdev/refs/macros/ADDRTYPE_DDP:addrtype-ddp}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_DDP:addrtype-ddp-data}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_DDP::doc}}\index{ADDRTYPE\_DDP (built\sphinxhyphen{}in variable)@\spxentry{ADDRTYPE\_DDP}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ADDRTYPE_DDP:ADDRTYPE_DDP}}\pysigline{\sphinxbfcode{\sphinxupquote{ADDRTYPE\_DDP}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ADDRTYPE\_DDP}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0010}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ADDRTYPE\_INET} +\label{\detokenize{appdev/refs/macros/ADDRTYPE_INET:addrtype-inet}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_INET:addrtype-inet-data}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_INET::doc}}\index{ADDRTYPE\_INET (built\sphinxhyphen{}in variable)@\spxentry{ADDRTYPE\_INET}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ADDRTYPE_INET:ADDRTYPE_INET}}\pysigline{\sphinxbfcode{\sphinxupquote{ADDRTYPE\_INET}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ADDRTYPE\_INET}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0002}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ADDRTYPE\_INET6} +\label{\detokenize{appdev/refs/macros/ADDRTYPE_INET6:addrtype-inet6}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_INET6:addrtype-inet6-data}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_INET6::doc}}\index{ADDRTYPE\_INET6 (built\sphinxhyphen{}in variable)@\spxentry{ADDRTYPE\_INET6}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ADDRTYPE_INET6:ADDRTYPE_INET6}}\pysigline{\sphinxbfcode{\sphinxupquote{ADDRTYPE\_INET6}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ADDRTYPE\_INET6}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0018}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ADDRTYPE\_IPPORT} +\label{\detokenize{appdev/refs/macros/ADDRTYPE_IPPORT:addrtype-ipport}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_IPPORT:addrtype-ipport-data}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_IPPORT::doc}}\index{ADDRTYPE\_IPPORT (built\sphinxhyphen{}in variable)@\spxentry{ADDRTYPE\_IPPORT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ADDRTYPE_IPPORT:ADDRTYPE_IPPORT}}\pysigline{\sphinxbfcode{\sphinxupquote{ADDRTYPE\_IPPORT}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ADDRTYPE\_IPPORT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0101}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ADDRTYPE\_ISO} +\label{\detokenize{appdev/refs/macros/ADDRTYPE_ISO:addrtype-iso}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_ISO:addrtype-iso-data}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_ISO::doc}}\index{ADDRTYPE\_ISO (built\sphinxhyphen{}in variable)@\spxentry{ADDRTYPE\_ISO}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ADDRTYPE_ISO:ADDRTYPE_ISO}}\pysigline{\sphinxbfcode{\sphinxupquote{ADDRTYPE\_ISO}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ADDRTYPE\_ISO}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0007}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ADDRTYPE\_IS\_LOCAL} +\label{\detokenize{appdev/refs/macros/ADDRTYPE_IS_LOCAL:addrtype-is-local}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_IS_LOCAL:addrtype-is-local-data}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_IS_LOCAL::doc}}\index{ADDRTYPE\_IS\_LOCAL (built\sphinxhyphen{}in variable)@\spxentry{ADDRTYPE\_IS\_LOCAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ADDRTYPE_IS_LOCAL:ADDRTYPE_IS_LOCAL}}\pysigline{\sphinxbfcode{\sphinxupquote{ADDRTYPE\_IS\_LOCAL}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ADDRTYPE\_IS\_LOCAL (addrtype)}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(addrtype \& 0x8000)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ADDRTYPE\_NETBIOS} +\label{\detokenize{appdev/refs/macros/ADDRTYPE_NETBIOS:addrtype-netbios}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_NETBIOS:addrtype-netbios-data}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_NETBIOS::doc}}\index{ADDRTYPE\_NETBIOS (built\sphinxhyphen{}in variable)@\spxentry{ADDRTYPE\_NETBIOS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ADDRTYPE_NETBIOS:ADDRTYPE_NETBIOS}}\pysigline{\sphinxbfcode{\sphinxupquote{ADDRTYPE\_NETBIOS}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ADDRTYPE\_NETBIOS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0014}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ADDRTYPE\_XNS} +\label{\detokenize{appdev/refs/macros/ADDRTYPE_XNS:addrtype-xns}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_XNS:addrtype-xns-data}}\label{\detokenize{appdev/refs/macros/ADDRTYPE_XNS::doc}}\index{ADDRTYPE\_XNS (built\sphinxhyphen{}in variable)@\spxentry{ADDRTYPE\_XNS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ADDRTYPE_XNS:ADDRTYPE_XNS}}\pysigline{\sphinxbfcode{\sphinxupquote{ADDRTYPE\_XNS}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ADDRTYPE\_XNS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0006}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{AD\_TYPE\_EXTERNAL} +\label{\detokenize{appdev/refs/macros/AD_TYPE_EXTERNAL:ad-type-external}}\label{\detokenize{appdev/refs/macros/AD_TYPE_EXTERNAL:ad-type-external-data}}\label{\detokenize{appdev/refs/macros/AD_TYPE_EXTERNAL::doc}}\index{AD\_TYPE\_EXTERNAL (built\sphinxhyphen{}in variable)@\spxentry{AD\_TYPE\_EXTERNAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/AD_TYPE_EXTERNAL:AD_TYPE_EXTERNAL}}\pysigline{\sphinxbfcode{\sphinxupquote{AD\_TYPE\_EXTERNAL}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{AD\_TYPE\_EXTERNAL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x4000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{AD\_TYPE\_FIELD\_TYPE\_MASK} +\label{\detokenize{appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK:ad-type-field-type-mask}}\label{\detokenize{appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK:ad-type-field-type-mask-data}}\label{\detokenize{appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK::doc}}\index{AD\_TYPE\_FIELD\_TYPE\_MASK (built\sphinxhyphen{}in variable)@\spxentry{AD\_TYPE\_FIELD\_TYPE\_MASK}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/AD_TYPE_FIELD_TYPE_MASK:AD_TYPE_FIELD_TYPE_MASK}}\pysigline{\sphinxbfcode{\sphinxupquote{AD\_TYPE\_FIELD\_TYPE\_MASK}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{AD\_TYPE\_FIELD\_TYPE\_MASK}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x1fff}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{AD\_TYPE\_REGISTERED} +\label{\detokenize{appdev/refs/macros/AD_TYPE_REGISTERED:ad-type-registered}}\label{\detokenize{appdev/refs/macros/AD_TYPE_REGISTERED:ad-type-registered-data}}\label{\detokenize{appdev/refs/macros/AD_TYPE_REGISTERED::doc}}\index{AD\_TYPE\_REGISTERED (built\sphinxhyphen{}in variable)@\spxentry{AD\_TYPE\_REGISTERED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/AD_TYPE_REGISTERED:AD_TYPE_REGISTERED}}\pysigline{\sphinxbfcode{\sphinxupquote{AD\_TYPE\_REGISTERED}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{AD\_TYPE\_REGISTERED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x2000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{AD\_TYPE\_RESERVED} +\label{\detokenize{appdev/refs/macros/AD_TYPE_RESERVED:ad-type-reserved}}\label{\detokenize{appdev/refs/macros/AD_TYPE_RESERVED:ad-type-reserved-data}}\label{\detokenize{appdev/refs/macros/AD_TYPE_RESERVED::doc}}\index{AD\_TYPE\_RESERVED (built\sphinxhyphen{}in variable)@\spxentry{AD\_TYPE\_RESERVED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/AD_TYPE_RESERVED:AD_TYPE_RESERVED}}\pysigline{\sphinxbfcode{\sphinxupquote{AD\_TYPE\_RESERVED}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{AD\_TYPE\_RESERVED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x8000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{AP\_OPTS\_ETYPE\_NEGOTIATION} +\label{\detokenize{appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION:ap-opts-etype-negotiation}}\label{\detokenize{appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION:ap-opts-etype-negotiation-data}}\label{\detokenize{appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION::doc}}\index{AP\_OPTS\_ETYPE\_NEGOTIATION (built\sphinxhyphen{}in variable)@\spxentry{AP\_OPTS\_ETYPE\_NEGOTIATION}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/AP_OPTS_ETYPE_NEGOTIATION:AP_OPTS_ETYPE_NEGOTIATION}}\pysigline{\sphinxbfcode{\sphinxupquote{AP\_OPTS\_ETYPE\_NEGOTIATION}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{AP\_OPTS\_ETYPE\_NEGOTIATION}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000002}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{AP\_OPTS\_MUTUAL\_REQUIRED} +\label{\detokenize{appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED:ap-opts-mutual-required}}\label{\detokenize{appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED:ap-opts-mutual-required-data}}\label{\detokenize{appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED::doc}}\index{AP\_OPTS\_MUTUAL\_REQUIRED (built\sphinxhyphen{}in variable)@\spxentry{AP\_OPTS\_MUTUAL\_REQUIRED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/AP_OPTS_MUTUAL_REQUIRED:AP_OPTS_MUTUAL_REQUIRED}}\pysigline{\sphinxbfcode{\sphinxupquote{AP\_OPTS\_MUTUAL\_REQUIRED}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Perform a mutual authentication exchange. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{AP\_OPTS\_MUTUAL\_REQUIRED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x20000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{AP\_OPTS\_RESERVED} +\label{\detokenize{appdev/refs/macros/AP_OPTS_RESERVED:ap-opts-reserved}}\label{\detokenize{appdev/refs/macros/AP_OPTS_RESERVED:ap-opts-reserved-data}}\label{\detokenize{appdev/refs/macros/AP_OPTS_RESERVED::doc}}\index{AP\_OPTS\_RESERVED (built\sphinxhyphen{}in variable)@\spxentry{AP\_OPTS\_RESERVED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/AP_OPTS_RESERVED:AP_OPTS_RESERVED}}\pysigline{\sphinxbfcode{\sphinxupquote{AP\_OPTS\_RESERVED}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{AP\_OPTS\_RESERVED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x80000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{AP\_OPTS\_USE\_SESSION\_KEY} +\label{\detokenize{appdev/refs/macros/AP_OPTS_USE_SESSION_KEY:ap-opts-use-session-key}}\label{\detokenize{appdev/refs/macros/AP_OPTS_USE_SESSION_KEY:ap-opts-use-session-key-data}}\label{\detokenize{appdev/refs/macros/AP_OPTS_USE_SESSION_KEY::doc}}\index{AP\_OPTS\_USE\_SESSION\_KEY (built\sphinxhyphen{}in variable)@\spxentry{AP\_OPTS\_USE\_SESSION\_KEY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/AP_OPTS_USE_SESSION_KEY:AP_OPTS_USE_SESSION_KEY}}\pysigline{\sphinxbfcode{\sphinxupquote{AP\_OPTS\_USE\_SESSION\_KEY}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Use session key. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{AP\_OPTS\_USE\_SESSION\_KEY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x40000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{AP\_OPTS\_USE\_SUBKEY} +\label{\detokenize{appdev/refs/macros/AP_OPTS_USE_SUBKEY:ap-opts-use-subkey}}\label{\detokenize{appdev/refs/macros/AP_OPTS_USE_SUBKEY:ap-opts-use-subkey-data}}\label{\detokenize{appdev/refs/macros/AP_OPTS_USE_SUBKEY::doc}}\index{AP\_OPTS\_USE\_SUBKEY (built\sphinxhyphen{}in variable)@\spxentry{AP\_OPTS\_USE\_SUBKEY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/AP_OPTS_USE_SUBKEY:AP_OPTS_USE_SUBKEY}}\pysigline{\sphinxbfcode{\sphinxupquote{AP\_OPTS\_USE\_SUBKEY}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Generate a subsession key from the current session key obtained from the credentials. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{AP\_OPTS\_USE\_SUBKEY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000001}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{AP\_OPTS\_WIRE\_MASK} +\label{\detokenize{appdev/refs/macros/AP_OPTS_WIRE_MASK:ap-opts-wire-mask}}\label{\detokenize{appdev/refs/macros/AP_OPTS_WIRE_MASK:ap-opts-wire-mask-data}}\label{\detokenize{appdev/refs/macros/AP_OPTS_WIRE_MASK::doc}}\index{AP\_OPTS\_WIRE\_MASK (built\sphinxhyphen{}in variable)@\spxentry{AP\_OPTS\_WIRE\_MASK}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/AP_OPTS_WIRE_MASK:AP_OPTS_WIRE_MASK}}\pysigline{\sphinxbfcode{\sphinxupquote{AP\_OPTS\_WIRE\_MASK}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{AP\_OPTS\_WIRE\_MASK}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0xfffffff0}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_CMAC\_CAMELLIA128} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128:cksumtype-cmac-camellia128}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128:cksumtype-cmac-camellia128-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128::doc}}\index{CKSUMTYPE\_CMAC\_CAMELLIA128 (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_CMAC\_CAMELLIA128}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA128:CKSUMTYPE_CMAC_CAMELLIA128}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_CMAC\_CAMELLIA128}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 6803. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_CMAC\_CAMELLIA128}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0011}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_CMAC\_CAMELLIA256} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256:cksumtype-cmac-camellia256}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256:cksumtype-cmac-camellia256-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256::doc}}\index{CKSUMTYPE\_CMAC\_CAMELLIA256 (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_CMAC\_CAMELLIA256}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_CMAC_CAMELLIA256:CKSUMTYPE_CMAC_CAMELLIA256}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_CMAC\_CAMELLIA256}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 6803. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_CMAC\_CAMELLIA256}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0012}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_CRC32} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_CRC32:cksumtype-crc32}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_CRC32:cksumtype-crc32-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_CRC32::doc}}\index{CKSUMTYPE\_CRC32 (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_CRC32}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_CRC32:CKSUMTYPE_CRC32}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_CRC32}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_CRC32}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0001}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_DESCBC} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_DESCBC:cksumtype-descbc}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_DESCBC:cksumtype-descbc-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_DESCBC::doc}}\index{CKSUMTYPE\_DESCBC (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_DESCBC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_DESCBC:CKSUMTYPE_DESCBC}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_DESCBC}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_DESCBC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0004}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_HMAC\_MD5\_ARCFOUR} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR:cksumtype-hmac-md5-arcfour}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR:cksumtype-hmac-md5-arcfour-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR::doc}}\index{CKSUMTYPE\_HMAC\_MD5\_ARCFOUR (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_HMAC\_MD5\_ARCFOUR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_MD5_ARCFOUR:CKSUMTYPE_HMAC_MD5_ARCFOUR}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_HMAC\_MD5\_ARCFOUR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 4757. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_HMAC\_MD5\_ARCFOUR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{\sphinxhyphen{}138}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_HMAC\_SHA1\_96\_AES128} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128:cksumtype-hmac-sha1-96-aes128}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128:cksumtype-hmac-sha1-96-aes128-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128::doc}}\index{CKSUMTYPE\_HMAC\_SHA1\_96\_AES128 (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_HMAC\_SHA1\_96\_AES128}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES128:CKSUMTYPE_HMAC_SHA1_96_AES128}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_HMAC\_SHA1\_96\_AES128}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 3962. + +\sphinxAtStartPar +Used with ENCTYPE\_AES128\_CTS\_HMAC\_SHA1\_96 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_HMAC\_SHA1\_96\_AES128}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x000f}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_HMAC\_SHA1\_96\_AES256} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256:cksumtype-hmac-sha1-96-aes256}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256:cksumtype-hmac-sha1-96-aes256-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256::doc}}\index{CKSUMTYPE\_HMAC\_SHA1\_96\_AES256 (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_HMAC\_SHA1\_96\_AES256}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_96_AES256:CKSUMTYPE_HMAC_SHA1_96_AES256}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_HMAC\_SHA1\_96\_AES256}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 3962. + +\sphinxAtStartPar +Used with ENCTYPE\_AES256\_CTS\_HMAC\_SHA1\_96 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_HMAC\_SHA1\_96\_AES256}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0010}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_HMAC\_SHA256\_128\_AES128} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128:cksumtype-hmac-sha256-128-aes128}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128:cksumtype-hmac-sha256-128-aes128-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128::doc}}\index{CKSUMTYPE\_HMAC\_SHA256\_128\_AES128 (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_HMAC\_SHA256\_128\_AES128}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA256_128_AES128:CKSUMTYPE_HMAC_SHA256_128_AES128}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_HMAC\_SHA256\_128\_AES128}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 8009. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_HMAC\_SHA256\_128\_AES128}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0013}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_HMAC\_SHA384\_192\_AES256} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256:cksumtype-hmac-sha384-192-aes256}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256:cksumtype-hmac-sha384-192-aes256-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256::doc}}\index{CKSUMTYPE\_HMAC\_SHA384\_192\_AES256 (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_HMAC\_SHA384\_192\_AES256}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA384_192_AES256:CKSUMTYPE_HMAC_SHA384_192_AES256}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_HMAC\_SHA384\_192\_AES256}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 8009. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_HMAC\_SHA384\_192\_AES256}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0014}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_HMAC\_SHA1\_DES3} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3:cksumtype-hmac-sha1-des3}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3:cksumtype-hmac-sha1-des3-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3::doc}}\index{CKSUMTYPE\_HMAC\_SHA1\_DES3 (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_HMAC\_SHA1\_DES3}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_HMAC_SHA1_DES3:CKSUMTYPE_HMAC_SHA1_DES3}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_HMAC\_SHA1\_DES3}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_HMAC\_SHA1\_DES3}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x000c}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_MD5\_HMAC\_ARCFOUR} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR:cksumtype-md5-hmac-arcfour}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR:cksumtype-md5-hmac-arcfour-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR::doc}}\index{CKSUMTYPE\_MD5\_HMAC\_ARCFOUR (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_MD5\_HMAC\_ARCFOUR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_MD5_HMAC_ARCFOUR:CKSUMTYPE_MD5_HMAC_ARCFOUR}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_MD5\_HMAC\_ARCFOUR}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_MD5\_HMAC\_ARCFOUR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{\sphinxhyphen{}137 /* Microsoft netlogon */}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_NIST\_SHA} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_NIST_SHA:cksumtype-nist-sha}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_NIST_SHA:cksumtype-nist-sha-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_NIST_SHA::doc}}\index{CKSUMTYPE\_NIST\_SHA (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_NIST\_SHA}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_NIST_SHA:CKSUMTYPE_NIST_SHA}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_NIST\_SHA}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_NIST\_SHA}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0009}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_RSA\_MD4} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD4:cksumtype-rsa-md4}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD4:cksumtype-rsa-md4-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD4::doc}}\index{CKSUMTYPE\_RSA\_MD4 (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_RSA\_MD4}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD4:CKSUMTYPE_RSA_MD4}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_RSA\_MD4}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_RSA\_MD4}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0002}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_RSA\_MD4\_DES} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES:cksumtype-rsa-md4-des}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES:cksumtype-rsa-md4-des-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES::doc}}\index{CKSUMTYPE\_RSA\_MD4\_DES (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_RSA\_MD4\_DES}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD4_DES:CKSUMTYPE_RSA_MD4_DES}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_RSA\_MD4\_DES}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_RSA\_MD4\_DES}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0003}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_RSA\_MD5} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD5:cksumtype-rsa-md5}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD5:cksumtype-rsa-md5-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD5::doc}}\index{CKSUMTYPE\_RSA\_MD5 (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_RSA\_MD5}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD5:CKSUMTYPE_RSA_MD5}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_RSA\_MD5}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_RSA\_MD5}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0007}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_RSA\_MD5\_DES} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES:cksumtype-rsa-md5-des}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES:cksumtype-rsa-md5-des-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES::doc}}\index{CKSUMTYPE\_RSA\_MD5\_DES (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_RSA\_MD5\_DES}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_RSA_MD5_DES:CKSUMTYPE_RSA_MD5_DES}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_RSA\_MD5\_DES}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_RSA\_MD5\_DES}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0008}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{CKSUMTYPE\_SHA1} +\label{\detokenize{appdev/refs/macros/CKSUMTYPE_SHA1:cksumtype-sha1}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_SHA1:cksumtype-sha1-data}}\label{\detokenize{appdev/refs/macros/CKSUMTYPE_SHA1::doc}}\index{CKSUMTYPE\_SHA1 (built\sphinxhyphen{}in variable)@\spxentry{CKSUMTYPE\_SHA1}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/CKSUMTYPE_SHA1:CKSUMTYPE_SHA1}}\pysigline{\sphinxbfcode{\sphinxupquote{CKSUMTYPE\_SHA1}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 3961. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{CKSUMTYPE\_SHA1}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x000e}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_AES128\_CTS\_HMAC\_SHA1\_96} +\label{\detokenize{appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96:enctype-aes128-cts-hmac-sha1-96}}\label{\detokenize{appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96:enctype-aes128-cts-hmac-sha1-96-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96::doc}}\index{ENCTYPE\_AES128\_CTS\_HMAC\_SHA1\_96 (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_AES128\_CTS\_HMAC\_SHA1\_96}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA1_96:ENCTYPE_AES128_CTS_HMAC_SHA1_96}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_AES128\_CTS\_HMAC\_SHA1\_96}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 3962. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_AES128\_CTS\_HMAC\_SHA1\_96}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0011}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_AES128\_CTS\_HMAC\_SHA256\_128} +\label{\detokenize{appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128:enctype-aes128-cts-hmac-sha256-128}}\label{\detokenize{appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128:enctype-aes128-cts-hmac-sha256-128-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128::doc}}\index{ENCTYPE\_AES128\_CTS\_HMAC\_SHA256\_128 (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_AES128\_CTS\_HMAC\_SHA256\_128}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_AES128_CTS_HMAC_SHA256_128:ENCTYPE_AES128_CTS_HMAC_SHA256_128}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_AES128\_CTS\_HMAC\_SHA256\_128}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 8009. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_AES128\_CTS\_HMAC\_SHA256\_128}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0013}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_AES256\_CTS\_HMAC\_SHA1\_96} +\label{\detokenize{appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96:enctype-aes256-cts-hmac-sha1-96}}\label{\detokenize{appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96:enctype-aes256-cts-hmac-sha1-96-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96::doc}}\index{ENCTYPE\_AES256\_CTS\_HMAC\_SHA1\_96 (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_AES256\_CTS\_HMAC\_SHA1\_96}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA1_96:ENCTYPE_AES256_CTS_HMAC_SHA1_96}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_AES256\_CTS\_HMAC\_SHA1\_96}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 3962. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_AES256\_CTS\_HMAC\_SHA1\_96}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0012}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_AES256\_CTS\_HMAC\_SHA384\_192} +\label{\detokenize{appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192:enctype-aes256-cts-hmac-sha384-192}}\label{\detokenize{appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192:enctype-aes256-cts-hmac-sha384-192-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192::doc}}\index{ENCTYPE\_AES256\_CTS\_HMAC\_SHA384\_192 (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_AES256\_CTS\_HMAC\_SHA384\_192}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_AES256_CTS_HMAC_SHA384_192:ENCTYPE_AES256_CTS_HMAC_SHA384_192}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_AES256\_CTS\_HMAC\_SHA384\_192}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 8009. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_AES256\_CTS\_HMAC\_SHA384\_192}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0014}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_ARCFOUR\_HMAC} +\label{\detokenize{appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC:enctype-arcfour-hmac}}\label{\detokenize{appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC:enctype-arcfour-hmac-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC::doc}}\index{ENCTYPE\_ARCFOUR\_HMAC (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_ARCFOUR\_HMAC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC:ENCTYPE_ARCFOUR_HMAC}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_ARCFOUR\_HMAC}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 4757. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_ARCFOUR\_HMAC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0017}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_ARCFOUR\_HMAC\_EXP} +\label{\detokenize{appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP:enctype-arcfour-hmac-exp}}\label{\detokenize{appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP:enctype-arcfour-hmac-exp-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP::doc}}\index{ENCTYPE\_ARCFOUR\_HMAC\_EXP (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_ARCFOUR\_HMAC\_EXP}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_ARCFOUR_HMAC_EXP:ENCTYPE_ARCFOUR_HMAC_EXP}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_ARCFOUR\_HMAC\_EXP}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 4757. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_ARCFOUR\_HMAC\_EXP}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0018}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_CAMELLIA128\_CTS\_CMAC} +\label{\detokenize{appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC:enctype-camellia128-cts-cmac}}\label{\detokenize{appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC:enctype-camellia128-cts-cmac-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC::doc}}\index{ENCTYPE\_CAMELLIA128\_CTS\_CMAC (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_CAMELLIA128\_CTS\_CMAC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_CAMELLIA128_CTS_CMAC:ENCTYPE_CAMELLIA128_CTS_CMAC}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_CAMELLIA128\_CTS\_CMAC}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 6803. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_CAMELLIA128\_CTS\_CMAC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0019}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_CAMELLIA256\_CTS\_CMAC} +\label{\detokenize{appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC:enctype-camellia256-cts-cmac}}\label{\detokenize{appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC:enctype-camellia256-cts-cmac-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC::doc}}\index{ENCTYPE\_CAMELLIA256\_CTS\_CMAC (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_CAMELLIA256\_CTS\_CMAC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_CAMELLIA256_CTS_CMAC:ENCTYPE_CAMELLIA256_CTS_CMAC}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_CAMELLIA256\_CTS\_CMAC}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 6803. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_CAMELLIA256\_CTS\_CMAC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x001a}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_DES3\_CBC\_ENV} +\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_ENV:enctype-des3-cbc-env}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_ENV:enctype-des3-cbc-env-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_ENV::doc}}\index{ENCTYPE\_DES3\_CBC\_ENV (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_DES3\_CBC\_ENV}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_ENV:ENCTYPE_DES3_CBC_ENV}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_DES3\_CBC\_ENV}}} +\end{fulllineitems} + + +\sphinxAtStartPar +DES\sphinxhyphen{}3 cbc mode, CMS enveloped data. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_DES3\_CBC\_ENV}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x000f}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_DES3\_CBC\_RAW} +\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_RAW:enctype-des3-cbc-raw}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_RAW:enctype-des3-cbc-raw-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_RAW::doc}}\index{ENCTYPE\_DES3\_CBC\_RAW (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_DES3\_CBC\_RAW}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_RAW:ENCTYPE_DES3_CBC_RAW}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_DES3\_CBC\_RAW}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_DES3\_CBC\_RAW}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0006}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_DES3\_CBC\_SHA} +\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_SHA:enctype-des3-cbc-sha}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_SHA:enctype-des3-cbc-sha-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_SHA::doc}}\index{ENCTYPE\_DES3\_CBC\_SHA (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_DES3\_CBC\_SHA}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_SHA:ENCTYPE_DES3_CBC_SHA}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_DES3\_CBC\_SHA}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_DES3\_CBC\_SHA}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0005}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_DES3\_CBC\_SHA1} +\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1:enctype-des3-cbc-sha1}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1:enctype-des3-cbc-sha1-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1::doc}}\index{ENCTYPE\_DES3\_CBC\_SHA1 (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_DES3\_CBC\_SHA1}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_DES3_CBC_SHA1:ENCTYPE_DES3_CBC_SHA1}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_DES3\_CBC\_SHA1}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_DES3\_CBC\_SHA1}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0010}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_DES\_CBC\_CRC} +\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_CRC:enctype-des-cbc-crc}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_CRC:enctype-des-cbc-crc-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_CRC::doc}}\index{ENCTYPE\_DES\_CBC\_CRC (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_DES\_CBC\_CRC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_CRC:ENCTYPE_DES_CBC_CRC}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_DES\_CBC\_CRC}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_DES\_CBC\_CRC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0001}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_DES\_CBC\_MD4} +\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_MD4:enctype-des-cbc-md4}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_MD4:enctype-des-cbc-md4-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_MD4::doc}}\index{ENCTYPE\_DES\_CBC\_MD4 (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_DES\_CBC\_MD4}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_MD4:ENCTYPE_DES_CBC_MD4}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_DES\_CBC\_MD4}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_DES\_CBC\_MD4}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0002}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_DES\_CBC\_MD5} +\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_MD5:enctype-des-cbc-md5}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_MD5:enctype-des-cbc-md5-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_MD5::doc}}\index{ENCTYPE\_DES\_CBC\_MD5 (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_DES\_CBC\_MD5}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_MD5:ENCTYPE_DES_CBC_MD5}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_DES\_CBC\_MD5}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_DES\_CBC\_MD5}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0003}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_DES\_CBC\_RAW} +\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_RAW:enctype-des-cbc-raw}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_RAW:enctype-des-cbc-raw-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_RAW::doc}}\index{ENCTYPE\_DES\_CBC\_RAW (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_DES\_CBC\_RAW}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_CBC_RAW:ENCTYPE_DES_CBC_RAW}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_DES\_CBC\_RAW}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_DES\_CBC\_RAW}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0004}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_DES\_HMAC\_SHA1} +\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1:enctype-des-hmac-sha1}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1:enctype-des-hmac-sha1-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1::doc}}\index{ENCTYPE\_DES\_HMAC\_SHA1 (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_DES\_HMAC\_SHA1}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_DES_HMAC_SHA1:ENCTYPE_DES_HMAC_SHA1}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_DES\_HMAC\_SHA1}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_DES\_HMAC\_SHA1}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0008}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_DSA\_SHA1\_CMS} +\label{\detokenize{appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS:enctype-dsa-sha1-cms}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS:enctype-dsa-sha1-cms-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS::doc}}\index{ENCTYPE\_DSA\_SHA1\_CMS (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_DSA\_SHA1\_CMS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_DSA_SHA1_CMS:ENCTYPE_DSA_SHA1_CMS}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_DSA\_SHA1\_CMS}}} +\end{fulllineitems} + + +\sphinxAtStartPar +DSA with SHA1, CMS signature. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_DSA\_SHA1\_CMS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0009}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_MD5\_RSA\_CMS} +\label{\detokenize{appdev/refs/macros/ENCTYPE_MD5_RSA_CMS:enctype-md5-rsa-cms}}\label{\detokenize{appdev/refs/macros/ENCTYPE_MD5_RSA_CMS:enctype-md5-rsa-cms-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_MD5_RSA_CMS::doc}}\index{ENCTYPE\_MD5\_RSA\_CMS (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_MD5\_RSA\_CMS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_MD5_RSA_CMS:ENCTYPE_MD5_RSA_CMS}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_MD5\_RSA\_CMS}}} +\end{fulllineitems} + + +\sphinxAtStartPar +MD5 with RSA, CMS signature. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_MD5\_RSA\_CMS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x000a}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_NULL} +\label{\detokenize{appdev/refs/macros/ENCTYPE_NULL:enctype-null}}\label{\detokenize{appdev/refs/macros/ENCTYPE_NULL:enctype-null-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_NULL::doc}}\index{ENCTYPE\_NULL (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_NULL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_NULL:ENCTYPE_NULL}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_NULL}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_NULL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_RC2\_CBC\_ENV} +\label{\detokenize{appdev/refs/macros/ENCTYPE_RC2_CBC_ENV:enctype-rc2-cbc-env}}\label{\detokenize{appdev/refs/macros/ENCTYPE_RC2_CBC_ENV:enctype-rc2-cbc-env-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_RC2_CBC_ENV::doc}}\index{ENCTYPE\_RC2\_CBC\_ENV (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_RC2\_CBC\_ENV}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_RC2_CBC_ENV:ENCTYPE_RC2_CBC_ENV}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_RC2\_CBC\_ENV}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RC2 cbc mode, CMS enveloped data. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_RC2\_CBC\_ENV}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x000c}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_RSA\_ENV} +\label{\detokenize{appdev/refs/macros/ENCTYPE_RSA_ENV:enctype-rsa-env}}\label{\detokenize{appdev/refs/macros/ENCTYPE_RSA_ENV:enctype-rsa-env-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_RSA_ENV::doc}}\index{ENCTYPE\_RSA\_ENV (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_RSA\_ENV}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_RSA_ENV:ENCTYPE_RSA_ENV}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_RSA\_ENV}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RSA encryption, CMS enveloped data. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_RSA\_ENV}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x000d}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_RSA\_ES\_OAEP\_ENV} +\label{\detokenize{appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV:enctype-rsa-es-oaep-env}}\label{\detokenize{appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV:enctype-rsa-es-oaep-env-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV::doc}}\index{ENCTYPE\_RSA\_ES\_OAEP\_ENV (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_RSA\_ES\_OAEP\_ENV}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_RSA_ES_OAEP_ENV:ENCTYPE_RSA_ES_OAEP_ENV}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_RSA\_ES\_OAEP\_ENV}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RSA w/OEAP encryption, CMS enveloped data. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_RSA\_ES\_OAEP\_ENV}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x000e}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_SHA1\_RSA\_CMS} +\label{\detokenize{appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS:enctype-sha1-rsa-cms}}\label{\detokenize{appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS:enctype-sha1-rsa-cms-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS::doc}}\index{ENCTYPE\_SHA1\_RSA\_CMS (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_SHA1\_RSA\_CMS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_SHA1_RSA_CMS:ENCTYPE_SHA1_RSA_CMS}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_SHA1\_RSA\_CMS}}} +\end{fulllineitems} + + +\sphinxAtStartPar +SHA1 with RSA, CMS signature. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_SHA1\_RSA\_CMS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x000b}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{ENCTYPE\_UNKNOWN} +\label{\detokenize{appdev/refs/macros/ENCTYPE_UNKNOWN:enctype-unknown}}\label{\detokenize{appdev/refs/macros/ENCTYPE_UNKNOWN:enctype-unknown-data}}\label{\detokenize{appdev/refs/macros/ENCTYPE_UNKNOWN::doc}}\index{ENCTYPE\_UNKNOWN (built\sphinxhyphen{}in variable)@\spxentry{ENCTYPE\_UNKNOWN}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/ENCTYPE_UNKNOWN:ENCTYPE_UNKNOWN}}\pysigline{\sphinxbfcode{\sphinxupquote{ENCTYPE\_UNKNOWN}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{ENCTYPE\_UNKNOWN}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x01ff}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_ALLOW\_POSTDATE} +\label{\detokenize{appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE:kdc-opt-allow-postdate}}\label{\detokenize{appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE:kdc-opt-allow-postdate-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE::doc}}\index{KDC\_OPT\_ALLOW\_POSTDATE (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_ALLOW\_POSTDATE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_ALLOW_POSTDATE:KDC_OPT_ALLOW_POSTDATE}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_ALLOW\_POSTDATE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_ALLOW\_POSTDATE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x04000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_CANONICALIZE} +\label{\detokenize{appdev/refs/macros/KDC_OPT_CANONICALIZE:kdc-opt-canonicalize}}\label{\detokenize{appdev/refs/macros/KDC_OPT_CANONICALIZE:kdc-opt-canonicalize-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_CANONICALIZE::doc}}\index{KDC\_OPT\_CANONICALIZE (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_CANONICALIZE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_CANONICALIZE:KDC_OPT_CANONICALIZE}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_CANONICALIZE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_CANONICALIZE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00010000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_CNAME\_IN\_ADDL\_TKT} +\label{\detokenize{appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT:kdc-opt-cname-in-addl-tkt}}\label{\detokenize{appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT:kdc-opt-cname-in-addl-tkt-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT::doc}}\index{KDC\_OPT\_CNAME\_IN\_ADDL\_TKT (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_CNAME\_IN\_ADDL\_TKT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_CNAME_IN_ADDL_TKT:KDC_OPT_CNAME_IN_ADDL_TKT}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_CNAME\_IN\_ADDL\_TKT}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_CNAME\_IN\_ADDL\_TKT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00020000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_DISABLE\_TRANSITED\_CHECK} +\label{\detokenize{appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK:kdc-opt-disable-transited-check}}\label{\detokenize{appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK:kdc-opt-disable-transited-check-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK::doc}}\index{KDC\_OPT\_DISABLE\_TRANSITED\_CHECK (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_DISABLE\_TRANSITED\_CHECK}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_DISABLE_TRANSITED_CHECK:KDC_OPT_DISABLE_TRANSITED_CHECK}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_DISABLE\_TRANSITED\_CHECK}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_DISABLE\_TRANSITED\_CHECK}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000020}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_ENC\_TKT\_IN\_SKEY} +\label{\detokenize{appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY:kdc-opt-enc-tkt-in-skey}}\label{\detokenize{appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY:kdc-opt-enc-tkt-in-skey-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY::doc}}\index{KDC\_OPT\_ENC\_TKT\_IN\_SKEY (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_ENC\_TKT\_IN\_SKEY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_ENC_TKT_IN_SKEY:KDC_OPT_ENC_TKT_IN_SKEY}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_ENC\_TKT\_IN\_SKEY}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_ENC\_TKT\_IN\_SKEY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000008}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_FORWARDABLE} +\label{\detokenize{appdev/refs/macros/KDC_OPT_FORWARDABLE:kdc-opt-forwardable}}\label{\detokenize{appdev/refs/macros/KDC_OPT_FORWARDABLE:kdc-opt-forwardable-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_FORWARDABLE::doc}}\index{KDC\_OPT\_FORWARDABLE (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_FORWARDABLE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_FORWARDABLE:KDC_OPT_FORWARDABLE}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_FORWARDABLE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_FORWARDABLE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x40000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_FORWARDED} +\label{\detokenize{appdev/refs/macros/KDC_OPT_FORWARDED:kdc-opt-forwarded}}\label{\detokenize{appdev/refs/macros/KDC_OPT_FORWARDED:kdc-opt-forwarded-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_FORWARDED::doc}}\index{KDC\_OPT\_FORWARDED (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_FORWARDED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_FORWARDED:KDC_OPT_FORWARDED}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_FORWARDED}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_FORWARDED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x20000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_POSTDATED} +\label{\detokenize{appdev/refs/macros/KDC_OPT_POSTDATED:kdc-opt-postdated}}\label{\detokenize{appdev/refs/macros/KDC_OPT_POSTDATED:kdc-opt-postdated-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_POSTDATED::doc}}\index{KDC\_OPT\_POSTDATED (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_POSTDATED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_POSTDATED:KDC_OPT_POSTDATED}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_POSTDATED}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_POSTDATED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x02000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_PROXIABLE} +\label{\detokenize{appdev/refs/macros/KDC_OPT_PROXIABLE:kdc-opt-proxiable}}\label{\detokenize{appdev/refs/macros/KDC_OPT_PROXIABLE:kdc-opt-proxiable-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_PROXIABLE::doc}}\index{KDC\_OPT\_PROXIABLE (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_PROXIABLE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_PROXIABLE:KDC_OPT_PROXIABLE}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_PROXIABLE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_PROXIABLE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x10000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_PROXY} +\label{\detokenize{appdev/refs/macros/KDC_OPT_PROXY:kdc-opt-proxy}}\label{\detokenize{appdev/refs/macros/KDC_OPT_PROXY:kdc-opt-proxy-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_PROXY::doc}}\index{KDC\_OPT\_PROXY (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_PROXY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_PROXY:KDC_OPT_PROXY}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_PROXY}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_PROXY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x08000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_RENEW} +\label{\detokenize{appdev/refs/macros/KDC_OPT_RENEW:kdc-opt-renew}}\label{\detokenize{appdev/refs/macros/KDC_OPT_RENEW:kdc-opt-renew-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_RENEW::doc}}\index{KDC\_OPT\_RENEW (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_RENEW}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_RENEW:KDC_OPT_RENEW}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_RENEW}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_RENEW}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000002}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_RENEWABLE} +\label{\detokenize{appdev/refs/macros/KDC_OPT_RENEWABLE:kdc-opt-renewable}}\label{\detokenize{appdev/refs/macros/KDC_OPT_RENEWABLE:kdc-opt-renewable-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_RENEWABLE::doc}}\index{KDC\_OPT\_RENEWABLE (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_RENEWABLE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_RENEWABLE:KDC_OPT_RENEWABLE}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_RENEWABLE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_RENEWABLE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00800000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_RENEWABLE\_OK} +\label{\detokenize{appdev/refs/macros/KDC_OPT_RENEWABLE_OK:kdc-opt-renewable-ok}}\label{\detokenize{appdev/refs/macros/KDC_OPT_RENEWABLE_OK:kdc-opt-renewable-ok-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_RENEWABLE_OK::doc}}\index{KDC\_OPT\_RENEWABLE\_OK (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_RENEWABLE\_OK}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_RENEWABLE_OK:KDC_OPT_RENEWABLE_OK}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_RENEWABLE\_OK}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_RENEWABLE\_OK}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000010}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_REQUEST\_ANONYMOUS} +\label{\detokenize{appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS:kdc-opt-request-anonymous}}\label{\detokenize{appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS:kdc-opt-request-anonymous-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS::doc}}\index{KDC\_OPT\_REQUEST\_ANONYMOUS (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_REQUEST\_ANONYMOUS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_REQUEST_ANONYMOUS:KDC_OPT_REQUEST_ANONYMOUS}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_REQUEST\_ANONYMOUS}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_REQUEST\_ANONYMOUS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00008000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_OPT\_VALIDATE} +\label{\detokenize{appdev/refs/macros/KDC_OPT_VALIDATE:kdc-opt-validate}}\label{\detokenize{appdev/refs/macros/KDC_OPT_VALIDATE:kdc-opt-validate-data}}\label{\detokenize{appdev/refs/macros/KDC_OPT_VALIDATE::doc}}\index{KDC\_OPT\_VALIDATE (built\sphinxhyphen{}in variable)@\spxentry{KDC\_OPT\_VALIDATE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_OPT_VALIDATE:KDC_OPT_VALIDATE}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_OPT\_VALIDATE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_OPT\_VALIDATE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000001}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KDC\_TKT\_COMMON\_MASK} +\label{\detokenize{appdev/refs/macros/KDC_TKT_COMMON_MASK:kdc-tkt-common-mask}}\label{\detokenize{appdev/refs/macros/KDC_TKT_COMMON_MASK:kdc-tkt-common-mask-data}}\label{\detokenize{appdev/refs/macros/KDC_TKT_COMMON_MASK::doc}}\index{KDC\_TKT\_COMMON\_MASK (built\sphinxhyphen{}in variable)@\spxentry{KDC\_TKT\_COMMON\_MASK}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KDC_TKT_COMMON_MASK:KDC_TKT_COMMON_MASK}}\pysigline{\sphinxbfcode{\sphinxupquote{KDC\_TKT\_COMMON\_MASK}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KDC\_TKT\_COMMON\_MASK}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x54800000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_ALTAUTH\_ATT\_CHALLENGE\_RESPONSE} +\label{\detokenize{appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE:krb5-altauth-att-challenge-response}}\label{\detokenize{appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE:krb5-altauth-att-challenge-response-data}}\label{\detokenize{appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE::doc}}\index{KRB5\_ALTAUTH\_ATT\_CHALLENGE\_RESPONSE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_ALTAUTH\_ATT\_CHALLENGE\_RESPONSE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE:KRB5_ALTAUTH_ATT_CHALLENGE_RESPONSE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_ALTAUTH\_ATT\_CHALLENGE\_RESPONSE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +alternate authentication types + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_ALTAUTH\_ATT\_CHALLENGE\_RESPONSE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{64}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_ANONYMOUS\_PRINCSTR} +\label{\detokenize{appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR:krb5-anonymous-princstr}}\label{\detokenize{appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR:krb5-anonymous-princstr-data}}\label{\detokenize{appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR::doc}}\index{KRB5\_ANONYMOUS\_PRINCSTR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_ANONYMOUS\_PRINCSTR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_ANONYMOUS_PRINCSTR:KRB5_ANONYMOUS_PRINCSTR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_ANONYMOUS\_PRINCSTR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Anonymous principal name. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_ANONYMOUS\_PRINCSTR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{"ANONYMOUS"}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_ANONYMOUS\_REALMSTR} +\label{\detokenize{appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR:krb5-anonymous-realmstr}}\label{\detokenize{appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR:krb5-anonymous-realmstr-data}}\label{\detokenize{appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR::doc}}\index{KRB5\_ANONYMOUS\_REALMSTR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_ANONYMOUS\_REALMSTR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_ANONYMOUS_REALMSTR:KRB5_ANONYMOUS_REALMSTR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_ANONYMOUS\_REALMSTR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Anonymous realm. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_ANONYMOUS\_REALMSTR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{"WELLKNOWN:ANONYMOUS"}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AP\_REP} +\label{\detokenize{appdev/refs/macros/KRB5_AP_REP:krb5-ap-rep}}\label{\detokenize{appdev/refs/macros/KRB5_AP_REP:krb5-ap-rep-data}}\label{\detokenize{appdev/refs/macros/KRB5_AP_REP::doc}}\index{KRB5\_AP\_REP (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AP\_REP}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AP_REP:KRB5_AP_REP}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AP\_REP}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Response to mutual AP request. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AP\_REP}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((krb5\_msgtype)15)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AP\_REQ} +\label{\detokenize{appdev/refs/macros/KRB5_AP_REQ:krb5-ap-req}}\label{\detokenize{appdev/refs/macros/KRB5_AP_REQ:krb5-ap-req-data}}\label{\detokenize{appdev/refs/macros/KRB5_AP_REQ::doc}}\index{KRB5\_AP\_REQ (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AP\_REQ}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AP_REQ:KRB5_AP_REQ}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AP\_REQ}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Auth req to application server. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AP\_REQ}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((krb5\_msgtype)14)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AS\_REP} +\label{\detokenize{appdev/refs/macros/KRB5_AS_REP:krb5-as-rep}}\label{\detokenize{appdev/refs/macros/KRB5_AS_REP:krb5-as-rep-data}}\label{\detokenize{appdev/refs/macros/KRB5_AS_REP::doc}}\index{KRB5\_AS\_REP (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AS\_REP}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AS_REP:KRB5_AS_REP}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AS\_REP}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Response to AS request. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AS\_REP}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((krb5\_msgtype)11)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AS\_REQ} +\label{\detokenize{appdev/refs/macros/KRB5_AS_REQ:krb5-as-req}}\label{\detokenize{appdev/refs/macros/KRB5_AS_REQ:krb5-as-req-data}}\label{\detokenize{appdev/refs/macros/KRB5_AS_REQ::doc}}\index{KRB5\_AS\_REQ (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AS\_REQ}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AS_REQ:KRB5_AS_REQ}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AS\_REQ}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Initial authentication request. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AS\_REQ}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((krb5\_msgtype)10)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_AND\_OR} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_AND_OR:krb5-authdata-and-or}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_AND_OR:krb5-authdata-and-or-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_AND_OR::doc}}\index{KRB5\_AUTHDATA\_AND\_OR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_AND\_OR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_AND_OR:KRB5_AUTHDATA_AND_OR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_AND\_OR}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_AND\_OR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{5}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_AP\_OPTIONS} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS:krb5-authdata-ap-options}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS:krb5-authdata-ap-options-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS::doc}}\index{KRB5\_AUTHDATA\_AP\_OPTIONS (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_AP\_OPTIONS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_AP_OPTIONS:KRB5_AUTHDATA_AP_OPTIONS}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_AP\_OPTIONS}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_AP\_OPTIONS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{143}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_AUTH\_INDICATOR} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR:krb5-authdata-auth-indicator}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR:krb5-authdata-auth-indicator-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR::doc}}\index{KRB5\_AUTHDATA\_AUTH\_INDICATOR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_AUTH\_INDICATOR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_AUTH_INDICATOR:KRB5_AUTHDATA_AUTH_INDICATOR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_AUTH\_INDICATOR}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_AUTH\_INDICATOR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{97}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_CAMMAC} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_CAMMAC:krb5-authdata-cammac}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_CAMMAC:krb5-authdata-cammac-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_CAMMAC::doc}}\index{KRB5\_AUTHDATA\_CAMMAC (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_CAMMAC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_CAMMAC:KRB5_AUTHDATA_CAMMAC}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_CAMMAC}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_CAMMAC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{96}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_ETYPE\_NEGOTIATION} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION:krb5-authdata-etype-negotiation}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION:krb5-authdata-etype-negotiation-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION::doc}}\index{KRB5\_AUTHDATA\_ETYPE\_NEGOTIATION (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_ETYPE\_NEGOTIATION}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_ETYPE_NEGOTIATION:KRB5_AUTHDATA_ETYPE_NEGOTIATION}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_ETYPE\_NEGOTIATION}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 4537. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_ETYPE\_NEGOTIATION}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{129}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_FX\_ARMOR} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR:krb5-authdata-fx-armor}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR:krb5-authdata-fx-armor-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR::doc}}\index{KRB5\_AUTHDATA\_FX\_ARMOR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_FX\_ARMOR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_FX_ARMOR:KRB5_AUTHDATA_FX_ARMOR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_FX\_ARMOR}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_FX\_ARMOR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{71}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_IF\_RELEVANT} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT:krb5-authdata-if-relevant}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT:krb5-authdata-if-relevant-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT::doc}}\index{KRB5\_AUTHDATA\_IF\_RELEVANT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_IF\_RELEVANT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_IF_RELEVANT:KRB5_AUTHDATA_IF_RELEVANT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_IF\_RELEVANT}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_IF\_RELEVANT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_INITIAL\_VERIFIED\_CAS} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS:krb5-authdata-initial-verified-cas}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS:krb5-authdata-initial-verified-cas-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS::doc}}\index{KRB5\_AUTHDATA\_INITIAL\_VERIFIED\_CAS (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_INITIAL\_VERIFIED\_CAS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_INITIAL_VERIFIED_CAS:KRB5_AUTHDATA_INITIAL_VERIFIED_CAS}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_INITIAL\_VERIFIED\_CAS}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_INITIAL\_VERIFIED\_CAS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{9}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_KDC\_ISSUED} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED:krb5-authdata-kdc-issued}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED:krb5-authdata-kdc-issued-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED::doc}}\index{KRB5\_AUTHDATA\_KDC\_ISSUED (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_KDC\_ISSUED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_KDC_ISSUED:KRB5_AUTHDATA_KDC_ISSUED}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_KDC\_ISSUED}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_KDC\_ISSUED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{4}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_MANDATORY\_FOR\_KDC} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC:krb5-authdata-mandatory-for-kdc}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC:krb5-authdata-mandatory-for-kdc-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC::doc}}\index{KRB5\_AUTHDATA\_MANDATORY\_FOR\_KDC (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_MANDATORY\_FOR\_KDC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_MANDATORY_FOR_KDC:KRB5_AUTHDATA_MANDATORY_FOR_KDC}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_MANDATORY\_FOR\_KDC}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_MANDATORY\_FOR\_KDC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{8}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_OSF\_DCE} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE:krb5-authdata-osf-dce}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE:krb5-authdata-osf-dce-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE::doc}}\index{KRB5\_AUTHDATA\_OSF\_DCE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_OSF\_DCE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_OSF_DCE:KRB5_AUTHDATA_OSF_DCE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_OSF\_DCE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_OSF\_DCE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{64}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_SESAME} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_SESAME:krb5-authdata-sesame}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_SESAME:krb5-authdata-sesame-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_SESAME::doc}}\index{KRB5\_AUTHDATA\_SESAME (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_SESAME}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_SESAME:KRB5_AUTHDATA_SESAME}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_SESAME}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_SESAME}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{65}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_SIGNTICKET} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET:krb5-authdata-signticket}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET:krb5-authdata-signticket-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET::doc}}\index{KRB5\_AUTHDATA\_SIGNTICKET (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_SIGNTICKET}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_SIGNTICKET:KRB5_AUTHDATA_SIGNTICKET}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_SIGNTICKET}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_SIGNTICKET}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{512}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTHDATA\_WIN2K\_PAC} +\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC:krb5-authdata-win2k-pac}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC:krb5-authdata-win2k-pac-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC::doc}}\index{KRB5\_AUTHDATA\_WIN2K\_PAC (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTHDATA\_WIN2K\_PAC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTHDATA_WIN2K_PAC:KRB5_AUTHDATA_WIN2K_PAC}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTHDATA\_WIN2K\_PAC}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTHDATA\_WIN2K\_PAC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{128}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE} +\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE:krb5-auth-context-do-sequence}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE:krb5-auth-context-do-sequence-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE::doc}}\index{KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_SEQUENCE:KRB5_AUTH_CONTEXT_DO_SEQUENCE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Prevent replays with sequence numbers. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_DO\_SEQUENCE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000004}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTH\_CONTEXT\_DO\_TIME} +\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME:krb5-auth-context-do-time}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME:krb5-auth-context-do-time-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME::doc}}\index{KRB5\_AUTH\_CONTEXT\_DO\_TIME (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTH\_CONTEXT\_DO\_TIME}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_DO_TIME:KRB5_AUTH_CONTEXT_DO_TIME}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_DO\_TIME}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Prevent replays with timestamps and replay cache. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_DO\_TIME}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000001}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTH\_CONTEXT\_GENERATE\_LOCAL\_ADDR} +\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR:krb5-auth-context-generate-local-addr}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR:krb5-auth-context-generate-local-addr-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR::doc}}\index{KRB5\_AUTH\_CONTEXT\_GENERATE\_LOCAL\_ADDR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTH\_CONTEXT\_GENERATE\_LOCAL\_ADDR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR:KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_GENERATE\_LOCAL\_ADDR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Generate the local network address. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_GENERATE\_LOCAL\_ADDR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000001}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTH\_CONTEXT\_GENERATE\_LOCAL\_FULL\_ADDR} +\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR:krb5-auth-context-generate-local-full-addr}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR:krb5-auth-context-generate-local-full-addr-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR::doc}}\index{KRB5\_AUTH\_CONTEXT\_GENERATE\_LOCAL\_FULL\_ADDR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTH\_CONTEXT\_GENERATE\_LOCAL\_FULL\_ADDR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR:KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_GENERATE\_LOCAL\_FULL\_ADDR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Generate the local network address and the local port. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_GENERATE\_LOCAL\_FULL\_ADDR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000004}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTH\_CONTEXT\_GENERATE\_REMOTE\_ADDR} +\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR:krb5-auth-context-generate-remote-addr}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR:krb5-auth-context-generate-remote-addr-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR::doc}}\index{KRB5\_AUTH\_CONTEXT\_GENERATE\_REMOTE\_ADDR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTH\_CONTEXT\_GENERATE\_REMOTE\_ADDR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR:KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_GENERATE\_REMOTE\_ADDR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Generate the remote network address. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_GENERATE\_REMOTE\_ADDR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000002}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTH\_CONTEXT\_GENERATE\_REMOTE\_FULL\_ADDR} +\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR:krb5-auth-context-generate-remote-full-addr}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR:krb5-auth-context-generate-remote-full-addr-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR::doc}}\index{KRB5\_AUTH\_CONTEXT\_GENERATE\_REMOTE\_FULL\_ADDR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTH\_CONTEXT\_GENERATE\_REMOTE\_FULL\_ADDR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR:KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_GENERATE\_REMOTE\_FULL\_ADDR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Generate the remote network address and the remote port. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_GENERATE\_REMOTE\_FULL\_ADDR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000008}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTH\_CONTEXT\_PERMIT\_ALL} +\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL:krb5-auth-context-permit-all}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL:krb5-auth-context-permit-all-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL::doc}}\index{KRB5\_AUTH\_CONTEXT\_PERMIT\_ALL (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTH\_CONTEXT\_PERMIT\_ALL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_PERMIT_ALL:KRB5_AUTH_CONTEXT_PERMIT_ALL}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_PERMIT\_ALL}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_PERMIT\_ALL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000010}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE} +\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE:krb5-auth-context-ret-sequence}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE:krb5-auth-context-ret-sequence-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE::doc}}\index{KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_SEQUENCE:KRB5_AUTH_CONTEXT_RET_SEQUENCE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Save sequence numbers for application. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_RET\_SEQUENCE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000008}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTH\_CONTEXT\_RET\_TIME} +\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME:krb5-auth-context-ret-time}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME:krb5-auth-context-ret-time-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME::doc}}\index{KRB5\_AUTH\_CONTEXT\_RET\_TIME (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTH\_CONTEXT\_RET\_TIME}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_RET_TIME:KRB5_AUTH_CONTEXT_RET_TIME}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_RET\_TIME}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Save timestamps for application. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_RET\_TIME}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000002}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_AUTH\_CONTEXT\_USE\_SUBKEY} +\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY:krb5-auth-context-use-subkey}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY:krb5-auth-context-use-subkey-data}}\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY::doc}}\index{KRB5\_AUTH\_CONTEXT\_USE\_SUBKEY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_AUTH\_CONTEXT\_USE\_SUBKEY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_AUTH_CONTEXT_USE_SUBKEY:KRB5_AUTH_CONTEXT_USE_SUBKEY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_USE\_SUBKEY}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_AUTH\_CONTEXT\_USE\_SUBKEY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000020}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_CRED} +\label{\detokenize{appdev/refs/macros/KRB5_CRED:krb5-cred}}\label{\detokenize{appdev/refs/macros/KRB5_CRED:krb5-cred-data}}\label{\detokenize{appdev/refs/macros/KRB5_CRED::doc}}\index{KRB5\_CRED (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_CRED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_CRED:KRB5_CRED}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_CRED}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Cred forwarding message. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_CRED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((krb5\_msgtype)22)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_CRYPTO\_TYPE\_CHECKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM:krb5-crypto-type-checksum}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM:krb5-crypto-type-checksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM::doc}}\index{KRB5\_CRYPTO\_TYPE\_CHECKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_CRYPTO\_TYPE\_CHECKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_CHECKSUM:KRB5_CRYPTO_TYPE_CHECKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_CHECKSUM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +{[}out{]} checksum for MIC + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_CHECKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{6}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_CRYPTO\_TYPE\_DATA} +\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA:krb5-crypto-type-data}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA:krb5-crypto-type-data-data}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA::doc}}\index{KRB5\_CRYPTO\_TYPE\_DATA (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_CRYPTO\_TYPE\_DATA}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_DATA:KRB5_CRYPTO_TYPE_DATA}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_DATA}}} +\end{fulllineitems} + + +\sphinxAtStartPar +{[}in, out{]} plaintext + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_DATA}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_CRYPTO\_TYPE\_EMPTY} +\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY:krb5-crypto-type-empty}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY:krb5-crypto-type-empty-data}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY::doc}}\index{KRB5\_CRYPTO\_TYPE\_EMPTY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_CRYPTO\_TYPE\_EMPTY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_EMPTY:KRB5_CRYPTO_TYPE_EMPTY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_EMPTY}}} +\end{fulllineitems} + + +\sphinxAtStartPar +{[}in{]} ignored + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_EMPTY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_CRYPTO\_TYPE\_HEADER} +\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER:krb5-crypto-type-header}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER:krb5-crypto-type-header-data}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER::doc}}\index{KRB5\_CRYPTO\_TYPE\_HEADER (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_CRYPTO\_TYPE\_HEADER}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_HEADER:KRB5_CRYPTO_TYPE_HEADER}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_HEADER}}} +\end{fulllineitems} + + +\sphinxAtStartPar +{[}out{]} header + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_HEADER}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_CRYPTO\_TYPE\_PADDING} +\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING:krb5-crypto-type-padding}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING:krb5-crypto-type-padding-data}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING::doc}}\index{KRB5\_CRYPTO\_TYPE\_PADDING (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_CRYPTO\_TYPE\_PADDING}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_PADDING:KRB5_CRYPTO_TYPE_PADDING}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_PADDING}}} +\end{fulllineitems} + + +\sphinxAtStartPar +{[}out{]} padding + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_PADDING}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{4}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_CRYPTO\_TYPE\_SIGN\_ONLY} +\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY:krb5-crypto-type-sign-only}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY:krb5-crypto-type-sign-only-data}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY::doc}}\index{KRB5\_CRYPTO\_TYPE\_SIGN\_ONLY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_CRYPTO\_TYPE\_SIGN\_ONLY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_SIGN_ONLY:KRB5_CRYPTO_TYPE_SIGN_ONLY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_SIGN\_ONLY}}} +\end{fulllineitems} + + +\sphinxAtStartPar +{[}in{]} associated data + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_SIGN\_ONLY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{3}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_CRYPTO\_TYPE\_STREAM} +\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM:krb5-crypto-type-stream}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM:krb5-crypto-type-stream-data}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM::doc}}\index{KRB5\_CRYPTO\_TYPE\_STREAM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_CRYPTO\_TYPE\_STREAM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_STREAM:KRB5_CRYPTO_TYPE_STREAM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_STREAM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +{[}in{]} entire message without decomposing the structure into header, data and trailer buffers + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_STREAM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{7}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_CRYPTO\_TYPE\_TRAILER} +\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER:krb5-crypto-type-trailer}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER:krb5-crypto-type-trailer-data}}\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER::doc}}\index{KRB5\_CRYPTO\_TYPE\_TRAILER (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_CRYPTO\_TYPE\_TRAILER}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_CRYPTO_TYPE_TRAILER:KRB5_CRYPTO_TYPE_TRAILER}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_TRAILER}}} +\end{fulllineitems} + + +\sphinxAtStartPar +{[}out{]} checksum for encrypt + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_CRYPTO\_TYPE\_TRAILER}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{5}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_CYBERSAFE\_SECUREID} +\label{\detokenize{appdev/refs/macros/KRB5_CYBERSAFE_SECUREID:krb5-cybersafe-secureid}}\label{\detokenize{appdev/refs/macros/KRB5_CYBERSAFE_SECUREID:krb5-cybersafe-secureid-data}}\label{\detokenize{appdev/refs/macros/KRB5_CYBERSAFE_SECUREID::doc}}\index{KRB5\_CYBERSAFE\_SECUREID (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_CYBERSAFE\_SECUREID}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_CYBERSAFE_SECUREID:KRB5_CYBERSAFE_SECUREID}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_CYBERSAFE\_SECUREID}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Cybersafe. + +\sphinxAtStartPar +RFC 4120 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_CYBERSAFE\_SECUREID}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{9}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_DOMAIN\_X500\_COMPRESS} +\label{\detokenize{appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS:krb5-domain-x500-compress}}\label{\detokenize{appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS:krb5-domain-x500-compress-data}}\label{\detokenize{appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS::doc}}\index{KRB5\_DOMAIN\_X500\_COMPRESS (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_DOMAIN\_X500\_COMPRESS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_DOMAIN_X500_COMPRESS:KRB5_DOMAIN_X500_COMPRESS}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_DOMAIN\_X500\_COMPRESS}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Transited encoding types. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_DOMAIN\_X500\_COMPRESS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_ENCPADATA\_REQ\_ENC\_PA\_REP} +\label{\detokenize{appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP:krb5-encpadata-req-enc-pa-rep}}\label{\detokenize{appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP:krb5-encpadata-req-enc-pa-rep-data}}\label{\detokenize{appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP::doc}}\index{KRB5\_ENCPADATA\_REQ\_ENC\_PA\_REP (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_ENCPADATA\_REQ\_ENC\_PA\_REP}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_ENCPADATA_REQ_ENC_PA_REP:KRB5_ENCPADATA_REQ_ENC_PA_REP}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_ENCPADATA\_REQ\_ENC\_PA\_REP}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 6806. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_ENCPADATA\_REQ\_ENC\_PA\_REP}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{149}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_ERROR} +\label{\detokenize{appdev/refs/macros/KRB5_ERROR:krb5-error}}\label{\detokenize{appdev/refs/macros/KRB5_ERROR:krb5-error-data}}\label{\detokenize{appdev/refs/macros/KRB5_ERROR::doc}}\index{KRB5\_ERROR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_ERROR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_ERROR:KRB5_ERROR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_ERROR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Error response. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_ERROR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((krb5\_msgtype)30)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_FAST\_REQUIRED} +\label{\detokenize{appdev/refs/macros/KRB5_FAST_REQUIRED:krb5-fast-required}}\label{\detokenize{appdev/refs/macros/KRB5_FAST_REQUIRED:krb5-fast-required-data}}\label{\detokenize{appdev/refs/macros/KRB5_FAST_REQUIRED::doc}}\index{KRB5\_FAST\_REQUIRED (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_FAST\_REQUIRED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_FAST_REQUIRED:KRB5_FAST_REQUIRED}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_FAST\_REQUIRED}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Require KDC to support FAST. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_FAST\_REQUIRED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0001}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GC\_CACHED} +\label{\detokenize{appdev/refs/macros/KRB5_GC_CACHED:krb5-gc-cached}}\label{\detokenize{appdev/refs/macros/KRB5_GC_CACHED:krb5-gc-cached-data}}\label{\detokenize{appdev/refs/macros/KRB5_GC_CACHED::doc}}\index{KRB5\_GC\_CACHED (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GC\_CACHED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GC_CACHED:KRB5_GC_CACHED}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GC\_CACHED}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Want cached ticket only. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GC\_CACHED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GC\_CANONICALIZE} +\label{\detokenize{appdev/refs/macros/KRB5_GC_CANONICALIZE:krb5-gc-canonicalize}}\label{\detokenize{appdev/refs/macros/KRB5_GC_CANONICALIZE:krb5-gc-canonicalize-data}}\label{\detokenize{appdev/refs/macros/KRB5_GC_CANONICALIZE::doc}}\index{KRB5\_GC\_CANONICALIZE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GC\_CANONICALIZE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GC_CANONICALIZE:KRB5_GC_CANONICALIZE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GC\_CANONICALIZE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Set canonicalize KDC option. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GC\_CANONICALIZE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{4}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GC\_CONSTRAINED\_DELEGATION} +\label{\detokenize{appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION:krb5-gc-constrained-delegation}}\label{\detokenize{appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION:krb5-gc-constrained-delegation-data}}\label{\detokenize{appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION::doc}}\index{KRB5\_GC\_CONSTRAINED\_DELEGATION (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GC\_CONSTRAINED\_DELEGATION}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GC_CONSTRAINED_DELEGATION:KRB5_GC_CONSTRAINED_DELEGATION}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GC\_CONSTRAINED\_DELEGATION}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Constrained delegation. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GC\_CONSTRAINED\_DELEGATION}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{64}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GC\_FORWARDABLE} +\label{\detokenize{appdev/refs/macros/KRB5_GC_FORWARDABLE:krb5-gc-forwardable}}\label{\detokenize{appdev/refs/macros/KRB5_GC_FORWARDABLE:krb5-gc-forwardable-data}}\label{\detokenize{appdev/refs/macros/KRB5_GC_FORWARDABLE::doc}}\index{KRB5\_GC\_FORWARDABLE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GC\_FORWARDABLE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GC_FORWARDABLE:KRB5_GC_FORWARDABLE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GC\_FORWARDABLE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Acquire forwardable tickets. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GC\_FORWARDABLE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{16}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GC\_NO\_STORE} +\label{\detokenize{appdev/refs/macros/KRB5_GC_NO_STORE:krb5-gc-no-store}}\label{\detokenize{appdev/refs/macros/KRB5_GC_NO_STORE:krb5-gc-no-store-data}}\label{\detokenize{appdev/refs/macros/KRB5_GC_NO_STORE::doc}}\index{KRB5\_GC\_NO\_STORE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GC\_NO\_STORE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GC_NO_STORE:KRB5_GC_NO_STORE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GC\_NO\_STORE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Do not store in credential cache. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GC\_NO\_STORE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{8}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GC\_NO\_TRANSIT\_CHECK} +\label{\detokenize{appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK:krb5-gc-no-transit-check}}\label{\detokenize{appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK:krb5-gc-no-transit-check-data}}\label{\detokenize{appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK::doc}}\index{KRB5\_GC\_NO\_TRANSIT\_CHECK (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GC\_NO\_TRANSIT\_CHECK}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GC_NO_TRANSIT_CHECK:KRB5_GC_NO_TRANSIT_CHECK}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GC\_NO\_TRANSIT\_CHECK}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Disable transited check. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GC\_NO\_TRANSIT\_CHECK}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{32}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GC\_USER\_USER} +\label{\detokenize{appdev/refs/macros/KRB5_GC_USER_USER:krb5-gc-user-user}}\label{\detokenize{appdev/refs/macros/KRB5_GC_USER_USER:krb5-gc-user-user-data}}\label{\detokenize{appdev/refs/macros/KRB5_GC_USER_USER::doc}}\index{KRB5\_GC\_USER\_USER (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GC\_USER\_USER}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GC_USER_USER:KRB5_GC_USER_USER}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GC\_USER\_USER}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Want user\sphinxhyphen{}user ticket. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GC\_USER\_USER}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GET\_INIT\_CREDS\_OPT\_ADDRESS\_LIST} +\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST:krb5-get-init-creds-opt-address-list}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST:krb5-get-init-creds-opt-address-list-data}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST::doc}}\index{KRB5\_GET\_INIT\_CREDS\_OPT\_ADDRESS\_LIST (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GET\_INIT\_CREDS\_OPT\_ADDRESS\_LIST}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST:KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_ADDRESS\_LIST}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_ADDRESS\_LIST}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0020}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GET\_INIT\_CREDS\_OPT\_ANONYMOUS} +\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS:krb5-get-init-creds-opt-anonymous}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS:krb5-get-init-creds-opt-anonymous-data}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS::doc}}\index{KRB5\_GET\_INIT\_CREDS\_OPT\_ANONYMOUS (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GET\_INIT\_CREDS\_OPT\_ANONYMOUS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ANONYMOUS:KRB5_GET_INIT_CREDS_OPT_ANONYMOUS}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_ANONYMOUS}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_ANONYMOUS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0400}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GET\_INIT\_CREDS\_OPT\_CANONICALIZE} +\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE:krb5-get-init-creds-opt-canonicalize}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE:krb5-get-init-creds-opt-canonicalize-data}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE::doc}}\index{KRB5\_GET\_INIT\_CREDS\_OPT\_CANONICALIZE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GET\_INIT\_CREDS\_OPT\_CANONICALIZE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CANONICALIZE:KRB5_GET_INIT_CREDS_OPT_CANONICALIZE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_CANONICALIZE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_CANONICALIZE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0200}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GET\_INIT\_CREDS\_OPT\_CHG\_PWD\_PRMPT} +\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT:krb5-get-init-creds-opt-chg-pwd-prmpt}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT:krb5-get-init-creds-opt-chg-pwd-prmpt-data}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT::doc}}\index{KRB5\_GET\_INIT\_CREDS\_OPT\_CHG\_PWD\_PRMPT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GET\_INIT\_CREDS\_OPT\_CHG\_PWD\_PRMPT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT:KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_CHG\_PWD\_PRMPT}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_CHG\_PWD\_PRMPT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0100}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GET\_INIT\_CREDS\_OPT\_ETYPE\_LIST} +\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST:krb5-get-init-creds-opt-etype-list}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST:krb5-get-init-creds-opt-etype-list-data}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST::doc}}\index{KRB5\_GET\_INIT\_CREDS\_OPT\_ETYPE\_LIST (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GET\_INIT\_CREDS\_OPT\_ETYPE\_LIST}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST:KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_ETYPE\_LIST}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_ETYPE\_LIST}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0010}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GET\_INIT\_CREDS\_OPT\_FORWARDABLE} +\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE:krb5-get-init-creds-opt-forwardable}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE:krb5-get-init-creds-opt-forwardable-data}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE::doc}}\index{KRB5\_GET\_INIT\_CREDS\_OPT\_FORWARDABLE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GET\_INIT\_CREDS\_OPT\_FORWARDABLE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_FORWARDABLE:KRB5_GET_INIT_CREDS_OPT_FORWARDABLE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_FORWARDABLE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_FORWARDABLE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0004}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GET\_INIT\_CREDS\_OPT\_PREAUTH\_LIST} +\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST:krb5-get-init-creds-opt-preauth-list}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST:krb5-get-init-creds-opt-preauth-list-data}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST::doc}}\index{KRB5\_GET\_INIT\_CREDS\_OPT\_PREAUTH\_LIST (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GET\_INIT\_CREDS\_OPT\_PREAUTH\_LIST}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST:KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_PREAUTH\_LIST}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_PREAUTH\_LIST}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0040}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GET\_INIT\_CREDS\_OPT\_PROXIABLE} +\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE:krb5-get-init-creds-opt-proxiable}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE:krb5-get-init-creds-opt-proxiable-data}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE::doc}}\index{KRB5\_GET\_INIT\_CREDS\_OPT\_PROXIABLE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GET\_INIT\_CREDS\_OPT\_PROXIABLE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_PROXIABLE:KRB5_GET_INIT_CREDS_OPT_PROXIABLE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_PROXIABLE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_PROXIABLE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0008}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GET\_INIT\_CREDS\_OPT\_RENEW\_LIFE} +\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE:krb5-get-init-creds-opt-renew-life}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE:krb5-get-init-creds-opt-renew-life-data}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE::doc}}\index{KRB5\_GET\_INIT\_CREDS\_OPT\_RENEW\_LIFE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GET\_INIT\_CREDS\_OPT\_RENEW\_LIFE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE:KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_RENEW\_LIFE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_RENEW\_LIFE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0002}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GET\_INIT\_CREDS\_OPT\_SALT} +\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT:krb5-get-init-creds-opt-salt}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT:krb5-get-init-creds-opt-salt-data}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT::doc}}\index{KRB5\_GET\_INIT\_CREDS\_OPT\_SALT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GET\_INIT\_CREDS\_OPT\_SALT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_SALT:KRB5_GET_INIT_CREDS_OPT_SALT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_SALT}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_SALT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0080}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_GET\_INIT\_CREDS\_OPT\_TKT\_LIFE} +\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE:krb5-get-init-creds-opt-tkt-life}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE:krb5-get-init-creds-opt-tkt-life-data}}\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE::doc}}\index{KRB5\_GET\_INIT\_CREDS\_OPT\_TKT\_LIFE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_GET\_INIT\_CREDS\_OPT\_TKT\_LIFE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_GET_INIT_CREDS_OPT_TKT_LIFE:KRB5_GET_INIT_CREDS_OPT_TKT_LIFE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_TKT\_LIFE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_GET\_INIT\_CREDS\_OPT\_TKT\_LIFE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0001}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_INIT\_CONTEXT\_SECURE} +\label{\detokenize{appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE:krb5-init-context-secure}}\label{\detokenize{appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE:krb5-init-context-secure-data}}\label{\detokenize{appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE::doc}}\index{KRB5\_INIT\_CONTEXT\_SECURE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_INIT\_CONTEXT\_SECURE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_INIT_CONTEXT_SECURE:KRB5_INIT_CONTEXT_SECURE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_INIT\_CONTEXT\_SECURE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Use secure context configuration. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_INIT\_CONTEXT\_SECURE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_INIT\_CONTEXT\_KDC} +\label{\detokenize{appdev/refs/macros/KRB5_INIT_CONTEXT_KDC:krb5-init-context-kdc}}\label{\detokenize{appdev/refs/macros/KRB5_INIT_CONTEXT_KDC:krb5-init-context-kdc-data}}\label{\detokenize{appdev/refs/macros/KRB5_INIT_CONTEXT_KDC::doc}}\index{KRB5\_INIT\_CONTEXT\_KDC (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_INIT\_CONTEXT\_KDC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_INIT_CONTEXT_KDC:KRB5_INIT_CONTEXT_KDC}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_INIT\_CONTEXT\_KDC}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Use KDC configuration if available. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_INIT\_CONTEXT\_KDC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_INIT\_CREDS\_STEP\_FLAG\_CONTINUE} +\label{\detokenize{appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE:krb5-init-creds-step-flag-continue}}\label{\detokenize{appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE:krb5-init-creds-step-flag-continue-data}}\label{\detokenize{appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE::doc}}\index{KRB5\_INIT\_CREDS\_STEP\_FLAG\_CONTINUE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_INIT\_CREDS\_STEP\_FLAG\_CONTINUE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_INIT_CREDS_STEP_FLAG_CONTINUE:KRB5_INIT_CREDS_STEP_FLAG_CONTINUE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_INIT\_CREDS\_STEP\_FLAG\_CONTINUE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +More responses needed. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_INIT\_CREDS\_STEP\_FLAG\_CONTINUE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_INT16\_MAX} +\label{\detokenize{appdev/refs/macros/KRB5_INT16_MAX:krb5-int16-max}}\label{\detokenize{appdev/refs/macros/KRB5_INT16_MAX:krb5-int16-max-data}}\label{\detokenize{appdev/refs/macros/KRB5_INT16_MAX::doc}}\index{KRB5\_INT16\_MAX (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_INT16\_MAX}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_INT16_MAX:KRB5_INT16_MAX}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_INT16\_MAX}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_INT16\_MAX}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{65535}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_INT16\_MIN} +\label{\detokenize{appdev/refs/macros/KRB5_INT16_MIN:krb5-int16-min}}\label{\detokenize{appdev/refs/macros/KRB5_INT16_MIN:krb5-int16-min-data}}\label{\detokenize{appdev/refs/macros/KRB5_INT16_MIN::doc}}\index{KRB5\_INT16\_MIN (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_INT16\_MIN}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_INT16_MIN:KRB5_INT16_MIN}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_INT16\_MIN}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_INT16\_MIN}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(\sphinxhyphen{}KRB5\_INT16\_MAX\sphinxhyphen{}1)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_INT32\_MAX} +\label{\detokenize{appdev/refs/macros/KRB5_INT32_MAX:krb5-int32-max}}\label{\detokenize{appdev/refs/macros/KRB5_INT32_MAX:krb5-int32-max-data}}\label{\detokenize{appdev/refs/macros/KRB5_INT32_MAX::doc}}\index{KRB5\_INT32\_MAX (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_INT32\_MAX}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_INT32_MAX:KRB5_INT32_MAX}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_INT32\_MAX}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_INT32\_MAX}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{2147483647}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_INT32\_MIN} +\label{\detokenize{appdev/refs/macros/KRB5_INT32_MIN:krb5-int32-min}}\label{\detokenize{appdev/refs/macros/KRB5_INT32_MIN:krb5-int32-min-data}}\label{\detokenize{appdev/refs/macros/KRB5_INT32_MIN::doc}}\index{KRB5\_INT32\_MIN (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_INT32\_MIN}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_INT32_MIN:KRB5_INT32_MIN}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_INT32\_MIN}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_INT32\_MIN}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(\sphinxhyphen{}KRB5\_INT32\_MAX\sphinxhyphen{}1)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_AD\_ITE} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE:krb5-keyusage-ad-ite}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE:krb5-keyusage-ad-ite-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE::doc}}\index{KRB5\_KEYUSAGE\_AD\_ITE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_AD\_ITE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_ITE:KRB5_KEYUSAGE_AD_ITE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_AD\_ITE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_AD\_ITE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{21}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_AD\_KDCISSUED\_CKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM:krb5-keyusage-ad-kdcissued-cksum}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM:krb5-keyusage-ad-kdcissued-cksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM::doc}}\index{KRB5\_KEYUSAGE\_AD\_KDCISSUED\_CKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_AD\_KDCISSUED\_CKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM:KRB5_KEYUSAGE_AD_KDCISSUED_CKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_AD\_KDCISSUED\_CKSUM}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_AD\_KDCISSUED\_CKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{19}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_AD\_MTE} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE:krb5-keyusage-ad-mte}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE:krb5-keyusage-ad-mte-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE::doc}}\index{KRB5\_KEYUSAGE\_AD\_MTE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_AD\_MTE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_MTE:KRB5_KEYUSAGE_AD_MTE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_AD\_MTE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_AD\_MTE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{20}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_AD\_SIGNEDPATH} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH:krb5-keyusage-ad-signedpath}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH:krb5-keyusage-ad-signedpath-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH::doc}}\index{KRB5\_KEYUSAGE\_AD\_SIGNEDPATH (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_AD\_SIGNEDPATH}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AD_SIGNEDPATH:KRB5_KEYUSAGE_AD_SIGNEDPATH}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_AD\_SIGNEDPATH}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_AD\_SIGNEDPATH}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{\sphinxhyphen{}21}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_APP\_DATA\_CKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM:krb5-keyusage-app-data-cksum}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM:krb5-keyusage-app-data-cksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM::doc}}\index{KRB5\_KEYUSAGE\_APP\_DATA\_CKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_APP\_DATA\_CKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_CKSUM:KRB5_KEYUSAGE_APP_DATA_CKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_APP\_DATA\_CKSUM}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_APP\_DATA\_CKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{17}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_APP\_DATA\_ENCRYPT} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT:krb5-keyusage-app-data-encrypt}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT:krb5-keyusage-app-data-encrypt-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT::doc}}\index{KRB5\_KEYUSAGE\_APP\_DATA\_ENCRYPT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_APP\_DATA\_ENCRYPT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_APP_DATA_ENCRYPT:KRB5_KEYUSAGE_APP_DATA_ENCRYPT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_APP\_DATA\_ENCRYPT}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_APP\_DATA\_ENCRYPT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{16}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_AP\_REP\_ENCPART} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART:krb5-keyusage-ap-rep-encpart}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART:krb5-keyusage-ap-rep-encpart-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART::doc}}\index{KRB5\_KEYUSAGE\_AP\_REP\_ENCPART (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_AP\_REP\_ENCPART}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AP_REP_ENCPART:KRB5_KEYUSAGE_AP_REP_ENCPART}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_AP\_REP\_ENCPART}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_AP\_REP\_ENCPART}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{12}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_AP\_REQ\_AUTH} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH:krb5-keyusage-ap-req-auth}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH:krb5-keyusage-ap-req-auth-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH::doc}}\index{KRB5\_KEYUSAGE\_AP\_REQ\_AUTH (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_AP\_REQ\_AUTH}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH:KRB5_KEYUSAGE_AP_REQ_AUTH}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_AP\_REQ\_AUTH}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_AP\_REQ\_AUTH}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{11}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_AP\_REQ\_AUTH\_CKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM:krb5-keyusage-ap-req-auth-cksum}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM:krb5-keyusage-ap-req-auth-cksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM::doc}}\index{KRB5\_KEYUSAGE\_AP\_REQ\_AUTH\_CKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_AP\_REQ\_AUTH\_CKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM:KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_AP\_REQ\_AUTH\_CKSUM}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_AP\_REQ\_AUTH\_CKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{10}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_AS\_REP\_ENCPART} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART:krb5-keyusage-as-rep-encpart}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART:krb5-keyusage-as-rep-encpart-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART::doc}}\index{KRB5\_KEYUSAGE\_AS\_REP\_ENCPART (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_AS\_REP\_ENCPART}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AS_REP_ENCPART:KRB5_KEYUSAGE_AS_REP_ENCPART}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_AS\_REP\_ENCPART}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_AS\_REP\_ENCPART}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{3}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_AS\_REQ} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ:krb5-keyusage-as-req}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ:krb5-keyusage-as-req-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ::doc}}\index{KRB5\_KEYUSAGE\_AS\_REQ (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_AS\_REQ}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ:KRB5_KEYUSAGE_AS_REQ}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_AS\_REQ}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_AS\_REQ}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{56}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_AS\_REQ\_PA\_ENC\_TS} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS:krb5-keyusage-as-req-pa-enc-ts}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS:krb5-keyusage-as-req-pa-enc-ts-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS::doc}}\index{KRB5\_KEYUSAGE\_AS\_REQ\_PA\_ENC\_TS (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_AS\_REQ\_PA\_ENC\_TS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS:KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_AS\_REQ\_PA\_ENC\_TS}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_AS\_REQ\_PA\_ENC\_TS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_CAMMAC} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC:krb5-keyusage-cammac}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC:krb5-keyusage-cammac-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC::doc}}\index{KRB5\_KEYUSAGE\_CAMMAC (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_CAMMAC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_CAMMAC:KRB5_KEYUSAGE_CAMMAC}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_CAMMAC}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_CAMMAC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{64}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_ENC\_CHALLENGE\_CLIENT} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT:krb5-keyusage-enc-challenge-client}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT:krb5-keyusage-enc-challenge-client-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT::doc}}\index{KRB5\_KEYUSAGE\_ENC\_CHALLENGE\_CLIENT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_ENC\_CHALLENGE\_CLIENT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT:KRB5_KEYUSAGE_ENC_CHALLENGE_CLIENT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_ENC\_CHALLENGE\_CLIENT}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_ENC\_CHALLENGE\_CLIENT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{54}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_ENC\_CHALLENGE\_KDC} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC:krb5-keyusage-enc-challenge-kdc}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC:krb5-keyusage-enc-challenge-kdc-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC::doc}}\index{KRB5\_KEYUSAGE\_ENC\_CHALLENGE\_KDC (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_ENC\_CHALLENGE\_KDC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_ENC_CHALLENGE_KDC:KRB5_KEYUSAGE_ENC_CHALLENGE_KDC}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_ENC\_CHALLENGE\_KDC}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_ENC\_CHALLENGE\_KDC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{55}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_FAST\_ENC} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC:krb5-keyusage-fast-enc}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC:krb5-keyusage-fast-enc-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC::doc}}\index{KRB5\_KEYUSAGE\_FAST\_ENC (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_FAST\_ENC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_ENC:KRB5_KEYUSAGE_FAST_ENC}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_FAST\_ENC}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_FAST\_ENC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{51}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_FAST\_FINISHED} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED:krb5-keyusage-fast-finished}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED:krb5-keyusage-fast-finished-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED::doc}}\index{KRB5\_KEYUSAGE\_FAST\_FINISHED (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_FAST\_FINISHED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_FINISHED:KRB5_KEYUSAGE_FAST_FINISHED}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_FAST\_FINISHED}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_FAST\_FINISHED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{53}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_FAST\_REP} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP:krb5-keyusage-fast-rep}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP:krb5-keyusage-fast-rep-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP::doc}}\index{KRB5\_KEYUSAGE\_FAST\_REP (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_FAST\_REP}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_REP:KRB5_KEYUSAGE_FAST_REP}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_FAST\_REP}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_FAST\_REP}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{52}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_FAST\_REQ\_CHKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM:krb5-keyusage-fast-req-chksum}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM:krb5-keyusage-fast-req-chksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM::doc}}\index{KRB5\_KEYUSAGE\_FAST\_REQ\_CHKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_FAST\_REQ\_CHKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_FAST_REQ_CHKSUM:KRB5_KEYUSAGE_FAST_REQ_CHKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_FAST\_REQ\_CHKSUM}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_FAST\_REQ\_CHKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{50}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_GSS\_TOK\_MIC} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC:krb5-keyusage-gss-tok-mic}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC:krb5-keyusage-gss-tok-mic-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC::doc}}\index{KRB5\_KEYUSAGE\_GSS\_TOK\_MIC (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_GSS\_TOK\_MIC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_MIC:KRB5_KEYUSAGE_GSS_TOK_MIC}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_GSS\_TOK\_MIC}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_GSS\_TOK\_MIC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{22}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_GSS\_TOK\_WRAP\_INTEG} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG:krb5-keyusage-gss-tok-wrap-integ}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG:krb5-keyusage-gss-tok-wrap-integ-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG::doc}}\index{KRB5\_KEYUSAGE\_GSS\_TOK\_WRAP\_INTEG (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_GSS\_TOK\_WRAP\_INTEG}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG:KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_GSS\_TOK\_WRAP\_INTEG}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_GSS\_TOK\_WRAP\_INTEG}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{23}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_GSS\_TOK\_WRAP\_PRIV} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV:krb5-keyusage-gss-tok-wrap-priv}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV:krb5-keyusage-gss-tok-wrap-priv-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV::doc}}\index{KRB5\_KEYUSAGE\_GSS\_TOK\_WRAP\_PRIV (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_GSS\_TOK\_WRAP\_PRIV}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV:KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_GSS\_TOK\_WRAP\_PRIV}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_GSS\_TOK\_WRAP\_PRIV}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{24}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_IAKERB\_FINISHED} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED:krb5-keyusage-iakerb-finished}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED:krb5-keyusage-iakerb-finished-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED::doc}}\index{KRB5\_KEYUSAGE\_IAKERB\_FINISHED (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_IAKERB\_FINISHED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_IAKERB_FINISHED:KRB5_KEYUSAGE_IAKERB_FINISHED}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_IAKERB\_FINISHED}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_IAKERB\_FINISHED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{42}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_KDC\_REP\_TICKET} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET:krb5-keyusage-kdc-rep-ticket}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET:krb5-keyusage-kdc-rep-ticket-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET::doc}}\index{KRB5\_KEYUSAGE\_KDC\_REP\_TICKET (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_KDC\_REP\_TICKET}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KDC_REP_TICKET:KRB5_KEYUSAGE_KDC_REP_TICKET}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_KDC\_REP\_TICKET}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_KDC\_REP\_TICKET}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_KRB\_CRED\_ENCPART} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART:krb5-keyusage-krb-cred-encpart}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART:krb5-keyusage-krb-cred-encpart-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART::doc}}\index{KRB5\_KEYUSAGE\_KRB\_CRED\_ENCPART (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_KRB\_CRED\_ENCPART}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_CRED_ENCPART:KRB5_KEYUSAGE_KRB_CRED_ENCPART}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_KRB\_CRED\_ENCPART}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_KRB\_CRED\_ENCPART}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{14}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_KRB\_ERROR\_CKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM:krb5-keyusage-krb-error-cksum}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM:krb5-keyusage-krb-error-cksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM::doc}}\index{KRB5\_KEYUSAGE\_KRB\_ERROR\_CKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_KRB\_ERROR\_CKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_ERROR_CKSUM:KRB5_KEYUSAGE_KRB_ERROR_CKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_KRB\_ERROR\_CKSUM}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_KRB\_ERROR\_CKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{18}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_KRB\_PRIV\_ENCPART} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART:krb5-keyusage-krb-priv-encpart}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART:krb5-keyusage-krb-priv-encpart-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART::doc}}\index{KRB5\_KEYUSAGE\_KRB\_PRIV\_ENCPART (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_KRB\_PRIV\_ENCPART}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_PRIV_ENCPART:KRB5_KEYUSAGE_KRB_PRIV_ENCPART}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_KRB\_PRIV\_ENCPART}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_KRB\_PRIV\_ENCPART}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{13}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_KRB\_SAFE\_CKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM:krb5-keyusage-krb-safe-cksum}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM:krb5-keyusage-krb-safe-cksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM::doc}}\index{KRB5\_KEYUSAGE\_KRB\_SAFE\_CKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_KRB\_SAFE\_CKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_KRB_SAFE_CKSUM:KRB5_KEYUSAGE_KRB_SAFE_CKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_KRB\_SAFE\_CKSUM}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_KRB\_SAFE\_CKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{15}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_PA\_AS\_FRESHNESS} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS:krb5-keyusage-pa-as-freshness}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS:krb5-keyusage-pa-as-freshness-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS::doc}}\index{KRB5\_KEYUSAGE\_PA\_AS\_FRESHNESS (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_PA\_AS\_FRESHNESS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_AS_FRESHNESS:KRB5_KEYUSAGE_PA_AS_FRESHNESS}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_AS\_FRESHNESS}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Used for freshness tokens. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_AS\_FRESHNESS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{514}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_PA\_FX\_COOKIE} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE:krb5-keyusage-pa-fx-cookie}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE:krb5-keyusage-pa-fx-cookie-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE::doc}}\index{KRB5\_KEYUSAGE\_PA\_FX\_COOKIE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_PA\_FX\_COOKIE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_FX_COOKIE:KRB5_KEYUSAGE_PA_FX_COOKIE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_FX\_COOKIE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Used for encrypted FAST cookies. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_FX\_COOKIE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{513}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_PA\_OTP\_REQUEST} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST:krb5-keyusage-pa-otp-request}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST:krb5-keyusage-pa-otp-request-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST::doc}}\index{KRB5\_KEYUSAGE\_PA\_OTP\_REQUEST (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_PA\_OTP\_REQUEST}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_OTP_REQUEST:KRB5_KEYUSAGE_PA_OTP_REQUEST}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_OTP\_REQUEST}}} +\end{fulllineitems} + + +\sphinxAtStartPar +See RFC 6560 section 4.2. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_OTP\_REQUEST}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{45}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_PA\_PKINIT\_KX} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX:krb5-keyusage-pa-pkinit-kx}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX:krb5-keyusage-pa-pkinit-kx-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX::doc}}\index{KRB5\_KEYUSAGE\_PA\_PKINIT\_KX (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_PA\_PKINIT\_KX}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_PKINIT_KX:KRB5_KEYUSAGE_PA_PKINIT_KX}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_PKINIT\_KX}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_PKINIT\_KX}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{44}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_PA\_S4U\_X509\_USER\_REPLY} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY:krb5-keyusage-pa-s4u-x509-user-reply}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY:krb5-keyusage-pa-s4u-x509-user-reply-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY::doc}}\index{KRB5\_KEYUSAGE\_PA\_S4U\_X509\_USER\_REPLY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_PA\_S4U\_X509\_USER\_REPLY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY:KRB5_KEYUSAGE_PA_S4U_X509_USER_REPLY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_S4U\_X509\_USER\_REPLY}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_S4U\_X509\_USER\_REPLY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{27}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_PA\_S4U\_X509\_USER\_REQUEST} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST:krb5-keyusage-pa-s4u-x509-user-request}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST:krb5-keyusage-pa-s4u-x509-user-request-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST::doc}}\index{KRB5\_KEYUSAGE\_PA\_S4U\_X509\_USER\_REQUEST (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_PA\_S4U\_X509\_USER\_REQUEST}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST:KRB5_KEYUSAGE_PA_S4U_X509_USER_REQUEST}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_S4U\_X509\_USER\_REQUEST}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_S4U\_X509\_USER\_REQUEST}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{26}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_PA\_SAM\_CHALLENGE\_CKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM:krb5-keyusage-pa-sam-challenge-cksum}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM:krb5-keyusage-pa-sam-challenge-cksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM::doc}}\index{KRB5\_KEYUSAGE\_PA\_SAM\_CHALLENGE\_CKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_PA\_SAM\_CHALLENGE\_CKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM:KRB5_KEYUSAGE_PA_SAM_CHALLENGE_CKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_SAM\_CHALLENGE\_CKSUM}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_SAM\_CHALLENGE\_CKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{25}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_PA\_SAM\_CHALLENGE\_TRACKID} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID:krb5-keyusage-pa-sam-challenge-trackid}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID:krb5-keyusage-pa-sam-challenge-trackid-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID::doc}}\index{KRB5\_KEYUSAGE\_PA\_SAM\_CHALLENGE\_TRACKID (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_PA\_SAM\_CHALLENGE\_TRACKID}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID:KRB5_KEYUSAGE_PA_SAM_CHALLENGE_TRACKID}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_SAM\_CHALLENGE\_TRACKID}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_SAM\_CHALLENGE\_TRACKID}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{26}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_PA\_SAM\_RESPONSE} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE:krb5-keyusage-pa-sam-response}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE:krb5-keyusage-pa-sam-response-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE::doc}}\index{KRB5\_KEYUSAGE\_PA\_SAM\_RESPONSE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_PA\_SAM\_RESPONSE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_PA_SAM_RESPONSE:KRB5_KEYUSAGE_PA_SAM_RESPONSE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_SAM\_RESPONSE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_PA\_SAM\_RESPONSE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{27}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_SPAKE} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_SPAKE:krb5-keyusage-spake}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_SPAKE:krb5-keyusage-spake-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_SPAKE::doc}}\index{KRB5\_KEYUSAGE\_SPAKE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_SPAKE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_SPAKE:KRB5_KEYUSAGE_SPAKE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_SPAKE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_SPAKE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{65}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_TGS\_REP\_ENCPART\_SESSKEY} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY:krb5-keyusage-tgs-rep-encpart-sesskey}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY:krb5-keyusage-tgs-rep-encpart-sesskey-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY::doc}}\index{KRB5\_KEYUSAGE\_TGS\_REP\_ENCPART\_SESSKEY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_TGS\_REP\_ENCPART\_SESSKEY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY:KRB5_KEYUSAGE_TGS_REP_ENCPART_SESSKEY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_TGS\_REP\_ENCPART\_SESSKEY}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_TGS\_REP\_ENCPART\_SESSKEY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{8}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_TGS\_REP\_ENCPART\_SUBKEY} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY:krb5-keyusage-tgs-rep-encpart-subkey}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY:krb5-keyusage-tgs-rep-encpart-subkey-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY::doc}}\index{KRB5\_KEYUSAGE\_TGS\_REP\_ENCPART\_SUBKEY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_TGS\_REP\_ENCPART\_SUBKEY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY:KRB5_KEYUSAGE_TGS_REP_ENCPART_SUBKEY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_TGS\_REP\_ENCPART\_SUBKEY}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_TGS\_REP\_ENCPART\_SUBKEY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{9}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_TGS\_REQ\_AD\_SESSKEY} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY:krb5-keyusage-tgs-req-ad-sesskey}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY:krb5-keyusage-tgs-req-ad-sesskey-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY::doc}}\index{KRB5\_KEYUSAGE\_TGS\_REQ\_AD\_SESSKEY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_TGS\_REQ\_AD\_SESSKEY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY:KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_TGS\_REQ\_AD\_SESSKEY}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_TGS\_REQ\_AD\_SESSKEY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{4}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_TGS\_REQ\_AD\_SUBKEY} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY:krb5-keyusage-tgs-req-ad-subkey}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY:krb5-keyusage-tgs-req-ad-subkey-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY::doc}}\index{KRB5\_KEYUSAGE\_TGS\_REQ\_AD\_SUBKEY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_TGS\_REQ\_AD\_SUBKEY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY:KRB5_KEYUSAGE_TGS_REQ_AD_SUBKEY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_TGS\_REQ\_AD\_SUBKEY}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_TGS\_REQ\_AD\_SUBKEY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{5}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_TGS\_REQ\_AUTH} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH:krb5-keyusage-tgs-req-auth}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH:krb5-keyusage-tgs-req-auth-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH::doc}}\index{KRB5\_KEYUSAGE\_TGS\_REQ\_AUTH (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_TGS\_REQ\_AUTH}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH:KRB5_KEYUSAGE_TGS_REQ_AUTH}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_TGS\_REQ\_AUTH}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_TGS\_REQ\_AUTH}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{7}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KEYUSAGE\_TGS\_REQ\_AUTH\_CKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM:krb5-keyusage-tgs-req-auth-cksum}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM:krb5-keyusage-tgs-req-auth-cksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM::doc}}\index{KRB5\_KEYUSAGE\_TGS\_REQ\_AUTH\_CKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KEYUSAGE\_TGS\_REQ\_AUTH\_CKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM:KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KEYUSAGE\_TGS\_REQ\_AUTH\_CKSUM}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KEYUSAGE\_TGS\_REQ\_AUTH\_CKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{6}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KPASSWD\_ACCESSDENIED} +\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED:krb5-kpasswd-accessdenied}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED:krb5-kpasswd-accessdenied-data}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED::doc}}\index{KRB5\_KPASSWD\_ACCESSDENIED (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KPASSWD\_ACCESSDENIED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_ACCESSDENIED:KRB5_KPASSWD_ACCESSDENIED}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KPASSWD\_ACCESSDENIED}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Not authorized. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KPASSWD\_ACCESSDENIED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{5}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KPASSWD\_AUTHERROR} +\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_AUTHERROR:krb5-kpasswd-autherror}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_AUTHERROR:krb5-kpasswd-autherror-data}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_AUTHERROR::doc}}\index{KRB5\_KPASSWD\_AUTHERROR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KPASSWD\_AUTHERROR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_AUTHERROR:KRB5_KPASSWD_AUTHERROR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KPASSWD\_AUTHERROR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Authentication error. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KPASSWD\_AUTHERROR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{3}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KPASSWD\_BAD\_VERSION} +\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION:krb5-kpasswd-bad-version}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION:krb5-kpasswd-bad-version-data}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION::doc}}\index{KRB5\_KPASSWD\_BAD\_VERSION (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KPASSWD\_BAD\_VERSION}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_BAD_VERSION:KRB5_KPASSWD_BAD_VERSION}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KPASSWD\_BAD\_VERSION}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Unknown RPC version. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KPASSWD\_BAD\_VERSION}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{6}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KPASSWD\_HARDERROR} +\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_HARDERROR:krb5-kpasswd-harderror}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_HARDERROR:krb5-kpasswd-harderror-data}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_HARDERROR::doc}}\index{KRB5\_KPASSWD\_HARDERROR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KPASSWD\_HARDERROR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_HARDERROR:KRB5_KPASSWD_HARDERROR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KPASSWD\_HARDERROR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Server error. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KPASSWD\_HARDERROR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KPASSWD\_INITIAL\_FLAG\_NEEDED} +\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED:krb5-kpasswd-initial-flag-needed}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED:krb5-kpasswd-initial-flag-needed-data}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED::doc}}\index{KRB5\_KPASSWD\_INITIAL\_FLAG\_NEEDED (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KPASSWD\_INITIAL\_FLAG\_NEEDED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_INITIAL_FLAG_NEEDED:KRB5_KPASSWD_INITIAL_FLAG_NEEDED}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KPASSWD\_INITIAL\_FLAG\_NEEDED}}} +\end{fulllineitems} + + +\sphinxAtStartPar +The presented credentials were not obtained using a password directly. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KPASSWD\_INITIAL\_FLAG\_NEEDED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{7}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KPASSWD\_MALFORMED} +\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_MALFORMED:krb5-kpasswd-malformed}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_MALFORMED:krb5-kpasswd-malformed-data}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_MALFORMED::doc}}\index{KRB5\_KPASSWD\_MALFORMED (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KPASSWD\_MALFORMED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_MALFORMED:KRB5_KPASSWD_MALFORMED}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KPASSWD\_MALFORMED}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Malformed request. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KPASSWD\_MALFORMED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KPASSWD\_SOFTERROR} +\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_SOFTERROR:krb5-kpasswd-softerror}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_SOFTERROR:krb5-kpasswd-softerror-data}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_SOFTERROR::doc}}\index{KRB5\_KPASSWD\_SOFTERROR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KPASSWD\_SOFTERROR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_SOFTERROR:KRB5_KPASSWD_SOFTERROR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KPASSWD\_SOFTERROR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Password change rejected. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KPASSWD\_SOFTERROR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{4}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_KPASSWD\_SUCCESS} +\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_SUCCESS:krb5-kpasswd-success}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_SUCCESS:krb5-kpasswd-success-data}}\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_SUCCESS::doc}}\index{KRB5\_KPASSWD\_SUCCESS (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_KPASSWD\_SUCCESS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_KPASSWD_SUCCESS:KRB5_KPASSWD_SUCCESS}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_KPASSWD\_SUCCESS}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Success. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_KPASSWD\_SUCCESS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ALL\_ACCT\_EXPTIME} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME:krb5-lrq-all-acct-exptime}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME:krb5-lrq-all-acct-exptime-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME::doc}}\index{KRB5\_LRQ\_ALL\_ACCT\_EXPTIME (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ALL\_ACCT\_EXPTIME}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_ACCT_EXPTIME:KRB5_LRQ_ALL_ACCT_EXPTIME}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ALL\_ACCT\_EXPTIME}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ALL\_ACCT\_EXPTIME}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{7}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ALL\_LAST\_INITIAL} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL:krb5-lrq-all-last-initial}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL:krb5-lrq-all-last-initial-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL::doc}}\index{KRB5\_LRQ\_ALL\_LAST\_INITIAL (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ALL\_LAST\_INITIAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_INITIAL:KRB5_LRQ_ALL_LAST_INITIAL}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ALL\_LAST\_INITIAL}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ALL\_LAST\_INITIAL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ALL\_LAST\_RENEWAL} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL:krb5-lrq-all-last-renewal}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL:krb5-lrq-all-last-renewal-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL::doc}}\index{KRB5\_LRQ\_ALL\_LAST\_RENEWAL (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ALL\_LAST\_RENEWAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_RENEWAL:KRB5_LRQ_ALL_LAST_RENEWAL}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ALL\_LAST\_RENEWAL}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ALL\_LAST\_RENEWAL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{4}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ALL\_LAST\_REQ} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ:krb5-lrq-all-last-req}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ:krb5-lrq-all-last-req-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ::doc}}\index{KRB5\_LRQ\_ALL\_LAST\_REQ (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ALL\_LAST\_REQ}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_REQ:KRB5_LRQ_ALL_LAST_REQ}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ALL\_LAST\_REQ}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ALL\_LAST\_REQ}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{5}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ALL\_LAST\_TGT} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT:krb5-lrq-all-last-tgt}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT:krb5-lrq-all-last-tgt-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT::doc}}\index{KRB5\_LRQ\_ALL\_LAST\_TGT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ALL\_LAST\_TGT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT:KRB5_LRQ_ALL_LAST_TGT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ALL\_LAST\_TGT}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ALL\_LAST\_TGT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ALL\_LAST\_TGT\_ISSUED} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED:krb5-lrq-all-last-tgt-issued}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED:krb5-lrq-all-last-tgt-issued-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED::doc}}\index{KRB5\_LRQ\_ALL\_LAST\_TGT\_ISSUED (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ALL\_LAST\_TGT\_ISSUED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_LAST_TGT_ISSUED:KRB5_LRQ_ALL_LAST_TGT_ISSUED}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ALL\_LAST\_TGT\_ISSUED}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ALL\_LAST\_TGT\_ISSUED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{3}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ALL\_PW\_EXPTIME} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME:krb5-lrq-all-pw-exptime}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME:krb5-lrq-all-pw-exptime-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME::doc}}\index{KRB5\_LRQ\_ALL\_PW\_EXPTIME (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ALL\_PW\_EXPTIME}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ALL_PW_EXPTIME:KRB5_LRQ_ALL_PW_EXPTIME}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ALL\_PW\_EXPTIME}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ALL\_PW\_EXPTIME}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{6}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_NONE} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_NONE:krb5-lrq-none}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_NONE:krb5-lrq-none-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_NONE::doc}}\index{KRB5\_LRQ\_NONE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_NONE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_NONE:KRB5_LRQ_NONE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_NONE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_NONE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ONE\_ACCT\_EXPTIME} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME:krb5-lrq-one-acct-exptime}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME:krb5-lrq-one-acct-exptime-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME::doc}}\index{KRB5\_LRQ\_ONE\_ACCT\_EXPTIME (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ONE\_ACCT\_EXPTIME}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_ACCT_EXPTIME:KRB5_LRQ_ONE_ACCT_EXPTIME}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ONE\_ACCT\_EXPTIME}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ONE\_ACCT\_EXPTIME}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(\sphinxhyphen{}7)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ONE\_LAST\_INITIAL} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL:krb5-lrq-one-last-initial}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL:krb5-lrq-one-last-initial-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL::doc}}\index{KRB5\_LRQ\_ONE\_LAST\_INITIAL (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ONE\_LAST\_INITIAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_INITIAL:KRB5_LRQ_ONE_LAST_INITIAL}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ONE\_LAST\_INITIAL}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ONE\_LAST\_INITIAL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(\sphinxhyphen{}2)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ONE\_LAST\_RENEWAL} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL:krb5-lrq-one-last-renewal}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL:krb5-lrq-one-last-renewal-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL::doc}}\index{KRB5\_LRQ\_ONE\_LAST\_RENEWAL (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ONE\_LAST\_RENEWAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_RENEWAL:KRB5_LRQ_ONE_LAST_RENEWAL}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ONE\_LAST\_RENEWAL}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ONE\_LAST\_RENEWAL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(\sphinxhyphen{}4)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ONE\_LAST\_REQ} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ:krb5-lrq-one-last-req}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ:krb5-lrq-one-last-req-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ::doc}}\index{KRB5\_LRQ\_ONE\_LAST\_REQ (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ONE\_LAST\_REQ}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_REQ:KRB5_LRQ_ONE_LAST_REQ}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ONE\_LAST\_REQ}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ONE\_LAST\_REQ}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(\sphinxhyphen{}5)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ONE\_LAST\_TGT} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT:krb5-lrq-one-last-tgt}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT:krb5-lrq-one-last-tgt-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT::doc}}\index{KRB5\_LRQ\_ONE\_LAST\_TGT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ONE\_LAST\_TGT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT:KRB5_LRQ_ONE_LAST_TGT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ONE\_LAST\_TGT}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ONE\_LAST\_TGT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(\sphinxhyphen{}1)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ONE\_LAST\_TGT\_ISSUED} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED:krb5-lrq-one-last-tgt-issued}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED:krb5-lrq-one-last-tgt-issued-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED::doc}}\index{KRB5\_LRQ\_ONE\_LAST\_TGT\_ISSUED (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ONE\_LAST\_TGT\_ISSUED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_LAST_TGT_ISSUED:KRB5_LRQ_ONE_LAST_TGT_ISSUED}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ONE\_LAST\_TGT\_ISSUED}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ONE\_LAST\_TGT\_ISSUED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(\sphinxhyphen{}3)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_LRQ\_ONE\_PW\_EXPTIME} +\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME:krb5-lrq-one-pw-exptime}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME:krb5-lrq-one-pw-exptime-data}}\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME::doc}}\index{KRB5\_LRQ\_ONE\_PW\_EXPTIME (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_LRQ\_ONE\_PW\_EXPTIME}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_LRQ_ONE_PW_EXPTIME:KRB5_LRQ_ONE_PW_EXPTIME}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_LRQ\_ONE\_PW\_EXPTIME}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_LRQ\_ONE\_PW\_EXPTIME}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(\sphinxhyphen{}6)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_NT\_ENTERPRISE\_PRINCIPAL} +\label{\detokenize{appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL:krb5-nt-enterprise-principal}}\label{\detokenize{appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL:krb5-nt-enterprise-principal-data}}\label{\detokenize{appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL::doc}}\index{KRB5\_NT\_ENTERPRISE\_PRINCIPAL (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_NT\_ENTERPRISE\_PRINCIPAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_NT_ENTERPRISE_PRINCIPAL:KRB5_NT_ENTERPRISE_PRINCIPAL}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_NT\_ENTERPRISE\_PRINCIPAL}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Windows 2000 UPN. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_NT\_ENTERPRISE\_PRINCIPAL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{10}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_NT\_ENT\_PRINCIPAL\_AND\_ID} +\label{\detokenize{appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID:krb5-nt-ent-principal-and-id}}\label{\detokenize{appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID:krb5-nt-ent-principal-and-id-data}}\label{\detokenize{appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID::doc}}\index{KRB5\_NT\_ENT\_PRINCIPAL\_AND\_ID (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_NT\_ENT\_PRINCIPAL\_AND\_ID}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_NT_ENT_PRINCIPAL_AND_ID:KRB5_NT_ENT_PRINCIPAL_AND_ID}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_NT\_ENT\_PRINCIPAL\_AND\_ID}}} +\end{fulllineitems} + + +\sphinxAtStartPar +NT 4 style name and SID. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_NT\_ENT\_PRINCIPAL\_AND\_ID}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{\sphinxhyphen{}130}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_NT\_MS\_PRINCIPAL} +\label{\detokenize{appdev/refs/macros/KRB5_NT_MS_PRINCIPAL:krb5-nt-ms-principal}}\label{\detokenize{appdev/refs/macros/KRB5_NT_MS_PRINCIPAL:krb5-nt-ms-principal-data}}\label{\detokenize{appdev/refs/macros/KRB5_NT_MS_PRINCIPAL::doc}}\index{KRB5\_NT\_MS\_PRINCIPAL (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_NT\_MS\_PRINCIPAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_NT_MS_PRINCIPAL:KRB5_NT_MS_PRINCIPAL}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_NT\_MS\_PRINCIPAL}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Windows 2000 UPN and SID. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_NT\_MS\_PRINCIPAL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{\sphinxhyphen{}128}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_NT\_MS\_PRINCIPAL\_AND\_ID} +\label{\detokenize{appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID:krb5-nt-ms-principal-and-id}}\label{\detokenize{appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID:krb5-nt-ms-principal-and-id-data}}\label{\detokenize{appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID::doc}}\index{KRB5\_NT\_MS\_PRINCIPAL\_AND\_ID (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_NT\_MS\_PRINCIPAL\_AND\_ID}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_NT_MS_PRINCIPAL_AND_ID:KRB5_NT_MS_PRINCIPAL_AND_ID}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_NT\_MS\_PRINCIPAL\_AND\_ID}}} +\end{fulllineitems} + + +\sphinxAtStartPar +NT 4 style name. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_NT\_MS\_PRINCIPAL\_AND\_ID}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{\sphinxhyphen{}129}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_NT\_PRINCIPAL} +\label{\detokenize{appdev/refs/macros/KRB5_NT_PRINCIPAL:krb5-nt-principal}}\label{\detokenize{appdev/refs/macros/KRB5_NT_PRINCIPAL:krb5-nt-principal-data}}\label{\detokenize{appdev/refs/macros/KRB5_NT_PRINCIPAL::doc}}\index{KRB5\_NT\_PRINCIPAL (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_NT\_PRINCIPAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_NT_PRINCIPAL:KRB5_NT_PRINCIPAL}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_NT\_PRINCIPAL}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Just the name of the principal as in DCE, or for users. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_NT\_PRINCIPAL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_NT\_SMTP\_NAME} +\label{\detokenize{appdev/refs/macros/KRB5_NT_SMTP_NAME:krb5-nt-smtp-name}}\label{\detokenize{appdev/refs/macros/KRB5_NT_SMTP_NAME:krb5-nt-smtp-name-data}}\label{\detokenize{appdev/refs/macros/KRB5_NT_SMTP_NAME::doc}}\index{KRB5\_NT\_SMTP\_NAME (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_NT\_SMTP\_NAME}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_NT_SMTP_NAME:KRB5_NT_SMTP_NAME}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_NT\_SMTP\_NAME}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Name in form of SMTP email name. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_NT\_SMTP\_NAME}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{7}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_NT\_SRV\_HST} +\label{\detokenize{appdev/refs/macros/KRB5_NT_SRV_HST:krb5-nt-srv-hst}}\label{\detokenize{appdev/refs/macros/KRB5_NT_SRV_HST:krb5-nt-srv-hst-data}}\label{\detokenize{appdev/refs/macros/KRB5_NT_SRV_HST::doc}}\index{KRB5\_NT\_SRV\_HST (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_NT\_SRV\_HST}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_NT_SRV_HST:KRB5_NT_SRV_HST}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_NT\_SRV\_HST}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Service with host name as instance (telnet, rcommands) + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_NT\_SRV\_HST}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{3}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_NT\_SRV\_INST} +\label{\detokenize{appdev/refs/macros/KRB5_NT_SRV_INST:krb5-nt-srv-inst}}\label{\detokenize{appdev/refs/macros/KRB5_NT_SRV_INST:krb5-nt-srv-inst-data}}\label{\detokenize{appdev/refs/macros/KRB5_NT_SRV_INST::doc}}\index{KRB5\_NT\_SRV\_INST (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_NT\_SRV\_INST}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_NT_SRV_INST:KRB5_NT_SRV_INST}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_NT\_SRV\_INST}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Service and other unique instance (krbtgt) + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_NT\_SRV\_INST}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_NT\_SRV\_XHST} +\label{\detokenize{appdev/refs/macros/KRB5_NT_SRV_XHST:krb5-nt-srv-xhst}}\label{\detokenize{appdev/refs/macros/KRB5_NT_SRV_XHST:krb5-nt-srv-xhst-data}}\label{\detokenize{appdev/refs/macros/KRB5_NT_SRV_XHST::doc}}\index{KRB5\_NT\_SRV\_XHST (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_NT\_SRV\_XHST}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_NT_SRV_XHST:KRB5_NT_SRV_XHST}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_NT\_SRV\_XHST}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Service with host as remaining components. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_NT\_SRV\_XHST}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{4}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_NT\_UID} +\label{\detokenize{appdev/refs/macros/KRB5_NT_UID:krb5-nt-uid}}\label{\detokenize{appdev/refs/macros/KRB5_NT_UID:krb5-nt-uid-data}}\label{\detokenize{appdev/refs/macros/KRB5_NT_UID::doc}}\index{KRB5\_NT\_UID (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_NT\_UID}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_NT_UID:KRB5_NT_UID}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_NT\_UID}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Unique ID. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_NT\_UID}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{5}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_NT\_UNKNOWN} +\label{\detokenize{appdev/refs/macros/KRB5_NT_UNKNOWN:krb5-nt-unknown}}\label{\detokenize{appdev/refs/macros/KRB5_NT_UNKNOWN:krb5-nt-unknown-data}}\label{\detokenize{appdev/refs/macros/KRB5_NT_UNKNOWN::doc}}\index{KRB5\_NT\_UNKNOWN (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_NT\_UNKNOWN}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_NT_UNKNOWN:KRB5_NT_UNKNOWN}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_NT\_UNKNOWN}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Name type not known. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_NT\_UNKNOWN}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_NT\_WELLKNOWN} +\label{\detokenize{appdev/refs/macros/KRB5_NT_WELLKNOWN:krb5-nt-wellknown}}\label{\detokenize{appdev/refs/macros/KRB5_NT_WELLKNOWN:krb5-nt-wellknown-data}}\label{\detokenize{appdev/refs/macros/KRB5_NT_WELLKNOWN::doc}}\index{KRB5\_NT\_WELLKNOWN (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_NT\_WELLKNOWN}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_NT_WELLKNOWN:KRB5_NT_WELLKNOWN}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_NT\_WELLKNOWN}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Well\sphinxhyphen{}known (special) principal. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_NT\_WELLKNOWN}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{11}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_NT\_X500\_PRINCIPAL} +\label{\detokenize{appdev/refs/macros/KRB5_NT_X500_PRINCIPAL:krb5-nt-x500-principal}}\label{\detokenize{appdev/refs/macros/KRB5_NT_X500_PRINCIPAL:krb5-nt-x500-principal-data}}\label{\detokenize{appdev/refs/macros/KRB5_NT_X500_PRINCIPAL::doc}}\index{KRB5\_NT\_X500\_PRINCIPAL (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_NT\_X500\_PRINCIPAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_NT_X500_PRINCIPAL:KRB5_NT_X500_PRINCIPAL}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_NT\_X500\_PRINCIPAL}}} +\end{fulllineitems} + + +\sphinxAtStartPar +PKINIT. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_NT\_X500\_PRINCIPAL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{6}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_ATTRIBUTES\_INFO} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO:krb5-pac-attributes-info}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO:krb5-pac-attributes-info-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO::doc}}\index{KRB5\_PAC\_ATTRIBUTES\_INFO (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_ATTRIBUTES\_INFO}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_ATTRIBUTES_INFO:KRB5_PAC_ATTRIBUTES_INFO}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_ATTRIBUTES\_INFO}}} +\end{fulllineitems} + + +\sphinxAtStartPar +PAC attributes. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_ATTRIBUTES\_INFO}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{17}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_CLIENT\_INFO} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_CLIENT_INFO:krb5-pac-client-info}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_CLIENT_INFO:krb5-pac-client-info-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_CLIENT_INFO::doc}}\index{KRB5\_PAC\_CLIENT\_INFO (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_CLIENT\_INFO}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_CLIENT_INFO:KRB5_PAC_CLIENT_INFO}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_CLIENT\_INFO}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Client name and ticket info. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_CLIENT\_INFO}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{10}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_CLIENT\_CLAIMS} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS:krb5-pac-client-claims}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS:krb5-pac-client-claims-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS::doc}}\index{KRB5\_PAC\_CLIENT\_CLAIMS (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_CLIENT\_CLAIMS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_CLIENT_CLAIMS:KRB5_PAC_CLIENT_CLAIMS}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_CLIENT\_CLAIMS}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Client claims information. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_CLIENT\_CLAIMS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{13}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_CREDENTIALS\_INFO} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO:krb5-pac-credentials-info}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO:krb5-pac-credentials-info-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO::doc}}\index{KRB5\_PAC\_CREDENTIALS\_INFO (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_CREDENTIALS\_INFO}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_CREDENTIALS_INFO:KRB5_PAC_CREDENTIALS_INFO}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_CREDENTIALS\_INFO}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Credentials information. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_CREDENTIALS\_INFO}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_DELEGATION\_INFO} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_DELEGATION_INFO:krb5-pac-delegation-info}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_DELEGATION_INFO:krb5-pac-delegation-info-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_DELEGATION_INFO::doc}}\index{KRB5\_PAC\_DELEGATION\_INFO (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_DELEGATION\_INFO}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_DELEGATION_INFO:KRB5_PAC_DELEGATION_INFO}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_DELEGATION\_INFO}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Constrained delegation info. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_DELEGATION\_INFO}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{11}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_DEVICE\_CLAIMS} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS:krb5-pac-device-claims}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS:krb5-pac-device-claims-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS::doc}}\index{KRB5\_PAC\_DEVICE\_CLAIMS (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_DEVICE\_CLAIMS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_DEVICE_CLAIMS:KRB5_PAC_DEVICE_CLAIMS}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_DEVICE\_CLAIMS}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Device claims information. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_DEVICE\_CLAIMS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{15}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_DEVICE\_INFO} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_DEVICE_INFO:krb5-pac-device-info}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_DEVICE_INFO:krb5-pac-device-info-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_DEVICE_INFO::doc}}\index{KRB5\_PAC\_DEVICE\_INFO (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_DEVICE\_INFO}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_DEVICE_INFO:KRB5_PAC_DEVICE_INFO}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_DEVICE\_INFO}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Device information. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_DEVICE\_INFO}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{14}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_LOGON\_INFO} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_LOGON_INFO:krb5-pac-logon-info}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_LOGON_INFO:krb5-pac-logon-info-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_LOGON_INFO::doc}}\index{KRB5\_PAC\_LOGON\_INFO (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_LOGON\_INFO}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_LOGON_INFO:KRB5_PAC_LOGON_INFO}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_LOGON\_INFO}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Logon information. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_LOGON\_INFO}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_PRIVSVR\_CHECKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM:krb5-pac-privsvr-checksum}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM:krb5-pac-privsvr-checksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM::doc}}\index{KRB5\_PAC\_PRIVSVR\_CHECKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_PRIVSVR\_CHECKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_PRIVSVR_CHECKSUM:KRB5_PAC_PRIVSVR_CHECKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_PRIVSVR\_CHECKSUM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +KDC checksum. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_PRIVSVR\_CHECKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{7}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_REQUESTOR} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_REQUESTOR:krb5-pac-requestor}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_REQUESTOR:krb5-pac-requestor-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_REQUESTOR::doc}}\index{KRB5\_PAC\_REQUESTOR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_REQUESTOR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_REQUESTOR:KRB5_PAC_REQUESTOR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_REQUESTOR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +PAC requestor SID. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_REQUESTOR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{18}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_SERVER\_CHECKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM:krb5-pac-server-checksum}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM:krb5-pac-server-checksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM::doc}}\index{KRB5\_PAC\_SERVER\_CHECKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_SERVER\_CHECKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_SERVER_CHECKSUM:KRB5_PAC_SERVER_CHECKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_SERVER\_CHECKSUM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Server checksum. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_SERVER\_CHECKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{6}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_TICKET\_CHECKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM:krb5-pac-ticket-checksum}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM:krb5-pac-ticket-checksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM::doc}}\index{KRB5\_PAC\_TICKET\_CHECKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_TICKET\_CHECKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_TICKET_CHECKSUM:KRB5_PAC_TICKET_CHECKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_TICKET\_CHECKSUM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Ticket checksum. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_TICKET\_CHECKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{16}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_UPN\_DNS\_INFO} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO:krb5-pac-upn-dns-info}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO:krb5-pac-upn-dns-info-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO::doc}}\index{KRB5\_PAC\_UPN\_DNS\_INFO (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_UPN\_DNS\_INFO}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_UPN_DNS_INFO:KRB5_PAC_UPN_DNS_INFO}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_UPN\_DNS\_INFO}}} +\end{fulllineitems} + + +\sphinxAtStartPar +User principal name and DNS info. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_UPN\_DNS\_INFO}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{12}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PAC\_FULL\_CHECKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM:krb5-pac-full-checksum}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM:krb5-pac-full-checksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM::doc}}\index{KRB5\_PAC\_FULL\_CHECKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PAC\_FULL\_CHECKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PAC_FULL_CHECKSUM:KRB5_PAC_FULL_CHECKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PAC\_FULL\_CHECKSUM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +KDC full checksum. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PAC\_FULL\_CHECKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{19}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_AFS3\_SALT} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AFS3_SALT:krb5-padata-afs3-salt}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AFS3_SALT:krb5-padata-afs3-salt-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AFS3_SALT::doc}}\index{KRB5\_PADATA\_AFS3\_SALT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_AFS3\_SALT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AFS3_SALT:KRB5_PADATA_AFS3_SALT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_AFS3\_SALT}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Cygnus. + +\sphinxAtStartPar +RFC 4120, 3961 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_AFS3\_SALT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{10}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_AP\_REQ} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AP_REQ:krb5-padata-ap-req}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AP_REQ:krb5-padata-ap-req-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AP_REQ::doc}}\index{KRB5\_PADATA\_AP\_REQ (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_AP\_REQ}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AP_REQ:KRB5_PADATA_AP_REQ}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_AP\_REQ}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_AP\_REQ}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_AS\_CHECKSUM} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM:krb5-padata-as-checksum}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM:krb5-padata-as-checksum-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM::doc}}\index{KRB5\_PADATA\_AS\_CHECKSUM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_AS\_CHECKSUM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AS_CHECKSUM:KRB5_PADATA_AS_CHECKSUM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_AS\_CHECKSUM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +AS checksum. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_AS\_CHECKSUM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{132}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_AS\_FRESHNESS} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS:krb5-padata-as-freshness}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS:krb5-padata-as-freshness-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS::doc}}\index{KRB5\_PADATA\_AS\_FRESHNESS (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_AS\_FRESHNESS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_AS_FRESHNESS:KRB5_PADATA_AS_FRESHNESS}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_AS\_FRESHNESS}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 8070. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_AS\_FRESHNESS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{150}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_ENCRYPTED\_CHALLENGE} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE:krb5-padata-encrypted-challenge}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE:krb5-padata-encrypted-challenge-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE::doc}}\index{KRB5\_PADATA\_ENCRYPTED\_CHALLENGE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_ENCRYPTED\_CHALLENGE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENCRYPTED_CHALLENGE:KRB5_PADATA_ENCRYPTED_CHALLENGE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_ENCRYPTED\_CHALLENGE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 6113. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_ENCRYPTED\_CHALLENGE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{138}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_ENC\_SANDIA\_SECURID} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID:krb5-padata-enc-sandia-securid}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID:krb5-padata-enc-sandia-securid-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID::doc}}\index{KRB5\_PADATA\_ENC\_SANDIA\_SECURID (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_ENC\_SANDIA\_SECURID}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENC_SANDIA_SECURID:KRB5_PADATA_ENC_SANDIA_SECURID}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_ENC\_SANDIA\_SECURID}}} +\end{fulllineitems} + + +\sphinxAtStartPar +SecurId passcode. + +\sphinxAtStartPar +RFC 4120 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_ENC\_SANDIA\_SECURID}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{6}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_ENC\_TIMESTAMP} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP:krb5-padata-enc-timestamp}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP:krb5-padata-enc-timestamp-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP::doc}}\index{KRB5\_PADATA\_ENC\_TIMESTAMP (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_ENC\_TIMESTAMP}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENC_TIMESTAMP:KRB5_PADATA_ENC_TIMESTAMP}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_ENC\_TIMESTAMP}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 4120. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_ENC\_TIMESTAMP}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_ENC\_UNIX\_TIME} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME:krb5-padata-enc-unix-time}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME:krb5-padata-enc-unix-time-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME::doc}}\index{KRB5\_PADATA\_ENC\_UNIX\_TIME (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_ENC\_UNIX\_TIME}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ENC_UNIX_TIME:KRB5_PADATA_ENC_UNIX_TIME}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_ENC\_UNIX\_TIME}}} +\end{fulllineitems} + + +\sphinxAtStartPar +timestamp encrypted in key. + +\sphinxAtStartPar +RFC 4120 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_ENC\_UNIX\_TIME}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{5}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_ETYPE\_INFO} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ETYPE_INFO:krb5-padata-etype-info}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ETYPE_INFO:krb5-padata-etype-info-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ETYPE_INFO::doc}}\index{KRB5\_PADATA\_ETYPE\_INFO (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_ETYPE\_INFO}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ETYPE_INFO:KRB5_PADATA_ETYPE_INFO}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_ETYPE\_INFO}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Etype info for preauth. + +\sphinxAtStartPar +RFC 4120 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_ETYPE\_INFO}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{11}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_ETYPE\_INFO2} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2:krb5-padata-etype-info2}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2:krb5-padata-etype-info2-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2::doc}}\index{KRB5\_PADATA\_ETYPE\_INFO2 (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_ETYPE\_INFO2}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_ETYPE_INFO2:KRB5_PADATA_ETYPE_INFO2}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_ETYPE\_INFO2}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 4120. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_ETYPE\_INFO2}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{19}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_FOR\_USER} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FOR_USER:krb5-padata-for-user}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FOR_USER:krb5-padata-for-user-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FOR_USER::doc}}\index{KRB5\_PADATA\_FOR\_USER (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_FOR\_USER}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FOR_USER:KRB5_PADATA_FOR_USER}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_FOR\_USER}}} +\end{fulllineitems} + + +\sphinxAtStartPar +username protocol transition request + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_FOR\_USER}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{129}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_FX\_COOKIE} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FX_COOKIE:krb5-padata-fx-cookie}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FX_COOKIE:krb5-padata-fx-cookie-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FX_COOKIE::doc}}\index{KRB5\_PADATA\_FX\_COOKIE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_FX\_COOKIE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FX_COOKIE:KRB5_PADATA_FX_COOKIE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_FX\_COOKIE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 6113. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_FX\_COOKIE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{133}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_FX\_ERROR} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FX_ERROR:krb5-padata-fx-error}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FX_ERROR:krb5-padata-fx-error-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FX_ERROR::doc}}\index{KRB5\_PADATA\_FX\_ERROR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_FX\_ERROR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FX_ERROR:KRB5_PADATA_FX_ERROR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_FX\_ERROR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 6113. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_FX\_ERROR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{137}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_FX\_FAST} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FX_FAST:krb5-padata-fx-fast}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FX_FAST:krb5-padata-fx-fast-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FX_FAST::doc}}\index{KRB5\_PADATA\_FX\_FAST (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_FX\_FAST}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_FX_FAST:KRB5_PADATA_FX_FAST}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_FX\_FAST}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 6113. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_FX\_FAST}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{136}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_GET\_FROM\_TYPED\_DATA} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA:krb5-padata-get-from-typed-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA:krb5-padata-get-from-typed-data-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA::doc}}\index{KRB5\_PADATA\_GET\_FROM\_TYPED\_DATA (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_GET\_FROM\_TYPED\_DATA}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_GET_FROM_TYPED_DATA:KRB5_PADATA_GET_FROM_TYPED_DATA}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_GET\_FROM\_TYPED\_DATA}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Embedded in typed data. + +\sphinxAtStartPar +RFC 4120 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_GET\_FROM\_TYPED\_DATA}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{22}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_NONE} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_NONE:krb5-padata-none}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_NONE:krb5-padata-none-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_NONE::doc}}\index{KRB5\_PADATA\_NONE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_NONE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_NONE:KRB5_PADATA_NONE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_NONE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_NONE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_OSF\_DCE} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OSF_DCE:krb5-padata-osf-dce}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OSF_DCE:krb5-padata-osf-dce-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OSF_DCE::doc}}\index{KRB5\_PADATA\_OSF\_DCE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_OSF\_DCE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OSF_DCE:KRB5_PADATA_OSF_DCE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_OSF\_DCE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +OSF DCE. + +\sphinxAtStartPar +RFC 4120 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_OSF\_DCE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{8}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_OTP\_CHALLENGE} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE:krb5-padata-otp-challenge}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE:krb5-padata-otp-challenge-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE::doc}}\index{KRB5\_PADATA\_OTP\_CHALLENGE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_OTP\_CHALLENGE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OTP_CHALLENGE:KRB5_PADATA_OTP_CHALLENGE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_OTP\_CHALLENGE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 6560 section 4.1. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_OTP\_CHALLENGE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{141}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_OTP\_PIN\_CHANGE} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE:krb5-padata-otp-pin-change}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE:krb5-padata-otp-pin-change-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE::doc}}\index{KRB5\_PADATA\_OTP\_PIN\_CHANGE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_OTP\_PIN\_CHANGE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OTP_PIN_CHANGE:KRB5_PADATA_OTP_PIN_CHANGE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_OTP\_PIN\_CHANGE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 6560 section 4.3. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_OTP\_PIN\_CHANGE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{144}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_OTP\_REQUEST} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OTP_REQUEST:krb5-padata-otp-request}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OTP_REQUEST:krb5-padata-otp-request-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OTP_REQUEST::doc}}\index{KRB5\_PADATA\_OTP\_REQUEST (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_OTP\_REQUEST}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_OTP_REQUEST:KRB5_PADATA_OTP_REQUEST}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_OTP\_REQUEST}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 6560 section 4.2. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_OTP\_REQUEST}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{142}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_PAC\_OPTIONS} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS:krb5-padata-pac-options}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS:krb5-padata-pac-options-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS::doc}}\index{KRB5\_PADATA\_PAC\_OPTIONS (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_PAC\_OPTIONS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PAC_OPTIONS:KRB5_PADATA_PAC_OPTIONS}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_PAC\_OPTIONS}}} +\end{fulllineitems} + + +\sphinxAtStartPar +MS\sphinxhyphen{}KILE and MS\sphinxhyphen{}SFU. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_PAC\_OPTIONS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{167}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_PAC\_REQUEST} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PAC_REQUEST:krb5-padata-pac-request}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PAC_REQUEST:krb5-padata-pac-request-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PAC_REQUEST::doc}}\index{KRB5\_PADATA\_PAC\_REQUEST (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_PAC\_REQUEST}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PAC_REQUEST:KRB5_PADATA_PAC_REQUEST}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_PAC\_REQUEST}}} +\end{fulllineitems} + + +\sphinxAtStartPar +include Windows PAC + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_PAC\_REQUEST}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{128}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_PKINIT\_KX} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PKINIT_KX:krb5-padata-pkinit-kx}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PKINIT_KX:krb5-padata-pkinit-kx-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PKINIT_KX::doc}}\index{KRB5\_PADATA\_PKINIT\_KX (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_PKINIT\_KX}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PKINIT_KX:KRB5_PADATA_PKINIT_KX}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_PKINIT\_KX}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 6112. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_PKINIT\_KX}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{147}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_PK\_AS\_REP} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REP:krb5-padata-pk-as-rep}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REP:krb5-padata-pk-as-rep-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REP::doc}}\index{KRB5\_PADATA\_PK\_AS\_REP (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_PK\_AS\_REP}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REP:KRB5_PADATA_PK_AS_REP}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_PK\_AS\_REP}}} +\end{fulllineitems} + + +\sphinxAtStartPar +PKINIT. + +\sphinxAtStartPar +RFC 4556 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_PK\_AS\_REP}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{17}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_PK\_AS\_REP\_OLD} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD:krb5-padata-pk-as-rep-old}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD:krb5-padata-pk-as-rep-old-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD::doc}}\index{KRB5\_PADATA\_PK\_AS\_REP\_OLD (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_PK\_AS\_REP\_OLD}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REP_OLD:KRB5_PADATA_PK_AS_REP_OLD}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_PK\_AS\_REP\_OLD}}} +\end{fulllineitems} + + +\sphinxAtStartPar +PKINIT. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_PK\_AS\_REP\_OLD}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{15}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_PK\_AS\_REQ} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REQ:krb5-padata-pk-as-req}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REQ:krb5-padata-pk-as-req-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REQ::doc}}\index{KRB5\_PADATA\_PK\_AS\_REQ (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_PK\_AS\_REQ}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REQ:KRB5_PADATA_PK_AS_REQ}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_PK\_AS\_REQ}}} +\end{fulllineitems} + + +\sphinxAtStartPar +PKINIT. + +\sphinxAtStartPar +RFC 4556 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_PK\_AS\_REQ}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{16}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_PK\_AS\_REQ\_OLD} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD:krb5-padata-pk-as-req-old}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD:krb5-padata-pk-as-req-old-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD::doc}}\index{KRB5\_PADATA\_PK\_AS\_REQ\_OLD (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_PK\_AS\_REQ\_OLD}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PK_AS_REQ_OLD:KRB5_PADATA_PK_AS_REQ_OLD}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_PK\_AS\_REQ\_OLD}}} +\end{fulllineitems} + + +\sphinxAtStartPar +PKINIT. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_PK\_AS\_REQ\_OLD}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{14}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_PW\_SALT} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PW_SALT:krb5-padata-pw-salt}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PW_SALT:krb5-padata-pw-salt-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PW_SALT::doc}}\index{KRB5\_PADATA\_PW\_SALT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_PW\_SALT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_PW_SALT:KRB5_PADATA_PW_SALT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_PW\_SALT}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 4120. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_PW\_SALT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{3}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_REFERRAL} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_REFERRAL:krb5-padata-referral}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_REFERRAL:krb5-padata-referral-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_REFERRAL::doc}}\index{KRB5\_PADATA\_REFERRAL (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_REFERRAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_REFERRAL:KRB5_PADATA_REFERRAL}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_REFERRAL}}} +\end{fulllineitems} + + +\sphinxAtStartPar +draft referral system + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_REFERRAL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{25}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_S4U\_X509\_USER} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_S4U_X509_USER:krb5-padata-s4u-x509-user}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_S4U_X509_USER:krb5-padata-s4u-x509-user-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_S4U_X509_USER::doc}}\index{KRB5\_PADATA\_S4U\_X509\_USER (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_S4U\_X509\_USER}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_S4U_X509_USER:KRB5_PADATA_S4U_X509_USER}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_S4U\_X509\_USER}}} +\end{fulllineitems} + + +\sphinxAtStartPar +certificate protocol transition request + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_S4U\_X509\_USER}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{130}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_SAM\_CHALLENGE} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE:krb5-padata-sam-challenge}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE:krb5-padata-sam-challenge-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE::doc}}\index{KRB5\_PADATA\_SAM\_CHALLENGE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_SAM\_CHALLENGE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE:KRB5_PADATA_SAM_CHALLENGE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_SAM\_CHALLENGE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +SAM/OTP. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_SAM\_CHALLENGE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{12}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_SAM\_CHALLENGE\_2} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2:krb5-padata-sam-challenge-2}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2:krb5-padata-sam-challenge-2-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2::doc}}\index{KRB5\_PADATA\_SAM\_CHALLENGE\_2 (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_SAM\_CHALLENGE\_2}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_CHALLENGE_2:KRB5_PADATA_SAM_CHALLENGE_2}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_SAM\_CHALLENGE\_2}}} +\end{fulllineitems} + + +\sphinxAtStartPar +draft challenge system, updated + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_SAM\_CHALLENGE\_2}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{30}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_SAM\_REDIRECT} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT:krb5-padata-sam-redirect}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT:krb5-padata-sam-redirect-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT::doc}}\index{KRB5\_PADATA\_SAM\_REDIRECT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_SAM\_REDIRECT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_REDIRECT:KRB5_PADATA_SAM_REDIRECT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_SAM\_REDIRECT}}} +\end{fulllineitems} + + +\sphinxAtStartPar +SAM/OTP. + +\sphinxAtStartPar +RFC 4120 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_SAM\_REDIRECT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{21}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_SAM\_RESPONSE} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE:krb5-padata-sam-response}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE:krb5-padata-sam-response-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE::doc}}\index{KRB5\_PADATA\_SAM\_RESPONSE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_SAM\_RESPONSE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE:KRB5_PADATA_SAM_RESPONSE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_SAM\_RESPONSE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +SAM/OTP. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_SAM\_RESPONSE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{13}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_SAM\_RESPONSE\_2} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2:krb5-padata-sam-response-2}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2:krb5-padata-sam-response-2-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2::doc}}\index{KRB5\_PADATA\_SAM\_RESPONSE\_2 (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_SAM\_RESPONSE\_2}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SAM_RESPONSE_2:KRB5_PADATA_SAM_RESPONSE_2}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_SAM\_RESPONSE\_2}}} +\end{fulllineitems} + + +\sphinxAtStartPar +draft challenge system, updated + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_SAM\_RESPONSE\_2}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{31}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_SESAME} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SESAME:krb5-padata-sesame}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SESAME:krb5-padata-sesame-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SESAME::doc}}\index{KRB5\_PADATA\_SESAME (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_SESAME}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SESAME:KRB5_PADATA_SESAME}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_SESAME}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Sesame project. + +\sphinxAtStartPar +RFC 4120 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_SESAME}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{7}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_SPAKE} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SPAKE:krb5-padata-spake}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SPAKE:krb5-padata-spake-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SPAKE::doc}}\index{KRB5\_PADATA\_SPAKE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_SPAKE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SPAKE:KRB5_PADATA_SPAKE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_SPAKE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_SPAKE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{151}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_REDHAT\_IDP\_OAUTH2} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2:krb5-padata-redhat-idp-oauth2}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2:krb5-padata-redhat-idp-oauth2-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2::doc}}\index{KRB5\_PADATA\_REDHAT\_IDP\_OAUTH2 (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_REDHAT\_IDP\_OAUTH2}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_REDHAT_IDP_OAUTH2:KRB5_PADATA_REDHAT_IDP_OAUTH2}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_REDHAT\_IDP\_OAUTH2}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Red Hat IdP mechanism. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_REDHAT\_IDP\_OAUTH2}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{152}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_REDHAT\_PASSKEY} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY:krb5-padata-redhat-passkey}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY:krb5-padata-redhat-passkey-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY::doc}}\index{KRB5\_PADATA\_REDHAT\_PASSKEY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_REDHAT\_PASSKEY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_REDHAT_PASSKEY:KRB5_PADATA_REDHAT_PASSKEY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_REDHAT\_PASSKEY}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Red Hat Passkey mechanism. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_REDHAT\_PASSKEY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{153}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_SVR\_REFERRAL\_INFO} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO:krb5-padata-svr-referral-info}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO:krb5-padata-svr-referral-info-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO::doc}}\index{KRB5\_PADATA\_SVR\_REFERRAL\_INFO (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_SVR\_REFERRAL\_INFO}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_SVR_REFERRAL_INFO:KRB5_PADATA_SVR_REFERRAL_INFO}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_SVR\_REFERRAL\_INFO}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Windows 2000 referrals. + +\sphinxAtStartPar +RFC 6820 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_SVR\_REFERRAL\_INFO}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{20}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_TGS\_REQ} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_TGS_REQ:krb5-padata-tgs-req}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_TGS_REQ:krb5-padata-tgs-req-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_TGS_REQ::doc}}\index{KRB5\_PADATA\_TGS\_REQ (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_TGS\_REQ}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_TGS_REQ:KRB5_PADATA_TGS_REQ}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_TGS\_REQ}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_TGS\_REQ}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_AP\_REQ}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PADATA\_USE\_SPECIFIED\_KVNO} +\label{\detokenize{appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO:krb5-padata-use-specified-kvno}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO:krb5-padata-use-specified-kvno-data}}\label{\detokenize{appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO::doc}}\index{KRB5\_PADATA\_USE\_SPECIFIED\_KVNO (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PADATA\_USE\_SPECIFIED\_KVNO}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PADATA_USE_SPECIFIED_KVNO:KRB5_PADATA_USE_SPECIFIED_KVNO}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PADATA\_USE\_SPECIFIED\_KVNO}}} +\end{fulllineitems} + + +\sphinxAtStartPar +RFC 4120. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PADATA\_USE\_SPECIFIED\_KVNO}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{20}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PRINCIPAL\_COMPARE\_CASEFOLD} +\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD:krb5-principal-compare-casefold}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD:krb5-principal-compare-casefold-data}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD::doc}}\index{KRB5\_PRINCIPAL\_COMPARE\_CASEFOLD (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PRINCIPAL\_COMPARE\_CASEFOLD}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_CASEFOLD:KRB5_PRINCIPAL_COMPARE_CASEFOLD}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PRINCIPAL\_COMPARE\_CASEFOLD}}} +\end{fulllineitems} + + +\sphinxAtStartPar +case\sphinxhyphen{}insensitive + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PRINCIPAL\_COMPARE\_CASEFOLD}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{4}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PRINCIPAL\_COMPARE\_ENTERPRISE} +\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE:krb5-principal-compare-enterprise}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE:krb5-principal-compare-enterprise-data}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE::doc}}\index{KRB5\_PRINCIPAL\_COMPARE\_ENTERPRISE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PRINCIPAL\_COMPARE\_ENTERPRISE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_ENTERPRISE:KRB5_PRINCIPAL_COMPARE_ENTERPRISE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PRINCIPAL\_COMPARE\_ENTERPRISE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +UPNs as real principals. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PRINCIPAL\_COMPARE\_ENTERPRISE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PRINCIPAL\_COMPARE\_IGNORE\_REALM} +\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM:krb5-principal-compare-ignore-realm}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM:krb5-principal-compare-ignore-realm-data}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM::doc}}\index{KRB5\_PRINCIPAL\_COMPARE\_IGNORE\_REALM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PRINCIPAL\_COMPARE\_IGNORE\_REALM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_IGNORE_REALM:KRB5_PRINCIPAL_COMPARE_IGNORE_REALM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PRINCIPAL\_COMPARE\_IGNORE\_REALM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +ignore realm component + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PRINCIPAL\_COMPARE\_IGNORE\_REALM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PRINCIPAL\_COMPARE\_UTF8} +\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8:krb5-principal-compare-utf8}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8:krb5-principal-compare-utf8-data}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8::doc}}\index{KRB5\_PRINCIPAL\_COMPARE\_UTF8 (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PRINCIPAL\_COMPARE\_UTF8}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_COMPARE_UTF8:KRB5_PRINCIPAL_COMPARE_UTF8}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PRINCIPAL\_COMPARE\_UTF8}}} +\end{fulllineitems} + + +\sphinxAtStartPar +treat principals as UTF\sphinxhyphen{}8 + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PRINCIPAL\_COMPARE\_UTF8}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{8}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PRINCIPAL\_PARSE\_ENTERPRISE} +\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE:krb5-principal-parse-enterprise}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE:krb5-principal-parse-enterprise-data}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE::doc}}\index{KRB5\_PRINCIPAL\_PARSE\_ENTERPRISE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PRINCIPAL\_PARSE\_ENTERPRISE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_ENTERPRISE:KRB5_PRINCIPAL_PARSE_ENTERPRISE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PRINCIPAL\_PARSE\_ENTERPRISE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Create single\sphinxhyphen{}component enterprise principle. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PRINCIPAL\_PARSE\_ENTERPRISE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x4}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PRINCIPAL\_PARSE\_IGNORE\_REALM} +\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM:krb5-principal-parse-ignore-realm}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM:krb5-principal-parse-ignore-realm-data}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM::doc}}\index{KRB5\_PRINCIPAL\_PARSE\_IGNORE\_REALM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PRINCIPAL\_PARSE\_IGNORE\_REALM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_IGNORE_REALM:KRB5_PRINCIPAL_PARSE_IGNORE_REALM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PRINCIPAL\_PARSE\_IGNORE\_REALM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Ignore realm if present. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PRINCIPAL\_PARSE\_IGNORE\_REALM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x8}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PRINCIPAL\_PARSE\_NO\_DEF\_REALM} +\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM:krb5-principal-parse-no-def-realm}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM:krb5-principal-parse-no-def-realm-data}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM::doc}}\index{KRB5\_PRINCIPAL\_PARSE\_NO\_DEF\_REALM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PRINCIPAL\_PARSE\_NO\_DEF\_REALM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_DEF_REALM:KRB5_PRINCIPAL_PARSE_NO_DEF_REALM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PRINCIPAL\_PARSE\_NO\_DEF\_REALM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Don’t add default realm. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PRINCIPAL\_PARSE\_NO\_DEF\_REALM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x10}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PRINCIPAL\_PARSE\_NO\_REALM} +\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM:krb5-principal-parse-no-realm}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM:krb5-principal-parse-no-realm-data}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM::doc}}\index{KRB5\_PRINCIPAL\_PARSE\_NO\_REALM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PRINCIPAL\_PARSE\_NO\_REALM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_NO_REALM:KRB5_PRINCIPAL_PARSE_NO_REALM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PRINCIPAL\_PARSE\_NO\_REALM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Error if realm is present. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PRINCIPAL\_PARSE\_NO\_REALM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PRINCIPAL\_PARSE\_REQUIRE\_REALM} +\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM:krb5-principal-parse-require-realm}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM:krb5-principal-parse-require-realm-data}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM::doc}}\index{KRB5\_PRINCIPAL\_PARSE\_REQUIRE\_REALM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PRINCIPAL\_PARSE\_REQUIRE\_REALM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_PARSE_REQUIRE_REALM:KRB5_PRINCIPAL_PARSE_REQUIRE_REALM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PRINCIPAL\_PARSE\_REQUIRE\_REALM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Error if realm is not present. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PRINCIPAL\_PARSE\_REQUIRE\_REALM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PRINCIPAL\_UNPARSE\_DISPLAY} +\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY:krb5-principal-unparse-display}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY:krb5-principal-unparse-display-data}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY::doc}}\index{KRB5\_PRINCIPAL\_UNPARSE\_DISPLAY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PRINCIPAL\_UNPARSE\_DISPLAY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_DISPLAY:KRB5_PRINCIPAL_UNPARSE_DISPLAY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PRINCIPAL\_UNPARSE\_DISPLAY}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Don’t escape special characters. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PRINCIPAL\_UNPARSE\_DISPLAY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x4}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PRINCIPAL\_UNPARSE\_NO\_REALM} +\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM:krb5-principal-unparse-no-realm}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM:krb5-principal-unparse-no-realm-data}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM::doc}}\index{KRB5\_PRINCIPAL\_UNPARSE\_NO\_REALM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PRINCIPAL\_UNPARSE\_NO\_REALM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_NO_REALM:KRB5_PRINCIPAL_UNPARSE_NO_REALM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PRINCIPAL\_UNPARSE\_NO\_REALM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Omit realm always. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PRINCIPAL\_UNPARSE\_NO\_REALM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PRINCIPAL\_UNPARSE\_SHORT} +\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT:krb5-principal-unparse-short}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT:krb5-principal-unparse-short-data}}\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT::doc}}\index{KRB5\_PRINCIPAL\_UNPARSE\_SHORT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PRINCIPAL\_UNPARSE\_SHORT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PRINCIPAL_UNPARSE_SHORT:KRB5_PRINCIPAL_UNPARSE_SHORT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PRINCIPAL\_UNPARSE\_SHORT}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Omit realm if it is the local realm. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PRINCIPAL\_UNPARSE\_SHORT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PRIV} +\label{\detokenize{appdev/refs/macros/KRB5_PRIV:krb5-priv}}\label{\detokenize{appdev/refs/macros/KRB5_PRIV:krb5-priv-data}}\label{\detokenize{appdev/refs/macros/KRB5_PRIV::doc}}\index{KRB5\_PRIV (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PRIV}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PRIV:KRB5_PRIV}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PRIV}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Private application message. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PRIV}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((krb5\_msgtype)21)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PROMPT\_TYPE\_NEW\_PASSWORD} +\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD:krb5-prompt-type-new-password}}\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD:krb5-prompt-type-new-password-data}}\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD::doc}}\index{KRB5\_PROMPT\_TYPE\_NEW\_PASSWORD (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PROMPT\_TYPE\_NEW\_PASSWORD}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD:KRB5_PROMPT_TYPE_NEW_PASSWORD}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PROMPT\_TYPE\_NEW\_PASSWORD}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Prompt for new password (during password change) + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PROMPT\_TYPE\_NEW\_PASSWORD}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PROMPT\_TYPE\_NEW\_PASSWORD\_AGAIN} +\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN:krb5-prompt-type-new-password-again}}\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN:krb5-prompt-type-new-password-again-data}}\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN::doc}}\index{KRB5\_PROMPT\_TYPE\_NEW\_PASSWORD\_AGAIN (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PROMPT\_TYPE\_NEW\_PASSWORD\_AGAIN}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN:KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PROMPT\_TYPE\_NEW\_PASSWORD\_AGAIN}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Prompt for new password again. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PROMPT\_TYPE\_NEW\_PASSWORD\_AGAIN}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x3}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PROMPT\_TYPE\_PASSWORD} +\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD:krb5-prompt-type-password}}\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD:krb5-prompt-type-password-data}}\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD::doc}}\index{KRB5\_PROMPT\_TYPE\_PASSWORD (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PROMPT\_TYPE\_PASSWORD}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_PASSWORD:KRB5_PROMPT_TYPE_PASSWORD}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PROMPT\_TYPE\_PASSWORD}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Prompt for password. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PROMPT\_TYPE\_PASSWORD}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PROMPT\_TYPE\_PREAUTH} +\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH:krb5-prompt-type-preauth}}\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH:krb5-prompt-type-preauth-data}}\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH::doc}}\index{KRB5\_PROMPT\_TYPE\_PREAUTH (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PROMPT\_TYPE\_PREAUTH}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PROMPT_TYPE_PREAUTH:KRB5_PROMPT_TYPE_PREAUTH}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PROMPT\_TYPE\_PREAUTH}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Prompt for preauthentication data (such as an OTP value) + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PROMPT\_TYPE\_PREAUTH}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x4}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_PVNO} +\label{\detokenize{appdev/refs/macros/KRB5_PVNO:krb5-pvno}}\label{\detokenize{appdev/refs/macros/KRB5_PVNO:krb5-pvno-data}}\label{\detokenize{appdev/refs/macros/KRB5_PVNO::doc}}\index{KRB5\_PVNO (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_PVNO}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_PVNO:KRB5_PVNO}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_PVNO}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Protocol version number. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_PVNO}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{5}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_REALM\_BRANCH\_CHAR} +\label{\detokenize{appdev/refs/macros/KRB5_REALM_BRANCH_CHAR:krb5-realm-branch-char}}\label{\detokenize{appdev/refs/macros/KRB5_REALM_BRANCH_CHAR:krb5-realm-branch-char-data}}\label{\detokenize{appdev/refs/macros/KRB5_REALM_BRANCH_CHAR::doc}}\index{KRB5\_REALM\_BRANCH\_CHAR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_REALM\_BRANCH\_CHAR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_REALM_BRANCH_CHAR:KRB5_REALM_BRANCH_CHAR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_REALM\_BRANCH\_CHAR}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_REALM\_BRANCH\_CHAR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{\textquotesingle{}.\textquotesingle{}}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RECVAUTH\_BADAUTHVERS} +\label{\detokenize{appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS:krb5-recvauth-badauthvers}}\label{\detokenize{appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS:krb5-recvauth-badauthvers-data}}\label{\detokenize{appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS::doc}}\index{KRB5\_RECVAUTH\_BADAUTHVERS (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RECVAUTH\_BADAUTHVERS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RECVAUTH_BADAUTHVERS:KRB5_RECVAUTH_BADAUTHVERS}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RECVAUTH\_BADAUTHVERS}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RECVAUTH\_BADAUTHVERS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0002}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RECVAUTH\_SKIP\_VERSION} +\label{\detokenize{appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION:krb5-recvauth-skip-version}}\label{\detokenize{appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION:krb5-recvauth-skip-version-data}}\label{\detokenize{appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION::doc}}\index{KRB5\_RECVAUTH\_SKIP\_VERSION (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RECVAUTH\_SKIP\_VERSION}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RECVAUTH_SKIP_VERSION:KRB5_RECVAUTH_SKIP_VERSION}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RECVAUTH\_SKIP\_VERSION}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RECVAUTH\_SKIP\_VERSION}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0001}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_REFERRAL\_REALM} +\label{\detokenize{appdev/refs/macros/KRB5_REFERRAL_REALM:krb5-referral-realm}}\label{\detokenize{appdev/refs/macros/KRB5_REFERRAL_REALM:krb5-referral-realm-data}}\label{\detokenize{appdev/refs/macros/KRB5_REFERRAL_REALM::doc}}\index{KRB5\_REFERRAL\_REALM (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_REFERRAL\_REALM}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_REFERRAL_REALM:KRB5_REFERRAL_REALM}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_REFERRAL\_REALM}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Constant for realm referrals. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_REFERRAL\_REALM}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{""}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_COUNT\_LOW} +\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW:krb5-responder-pkinit-flags-token-user-pin-count-low}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW:krb5-responder-pkinit-flags-token-user-pin-count-low-data}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW::doc}}\index{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_COUNT\_LOW (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_COUNT\_LOW}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW:KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_COUNT_LOW}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_COUNT\_LOW}}} +\end{fulllineitems} + + +\sphinxAtStartPar +This flag indicates that an incorrect PIN was supplied at least once since the last time the correct PIN was supplied. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_COUNT\_LOW}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(1 \textless{}\textless{} 0)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_FINAL\_TRY} +\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY:krb5-responder-pkinit-flags-token-user-pin-final-try}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY:krb5-responder-pkinit-flags-token-user-pin-final-try-data}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY::doc}}\index{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_FINAL\_TRY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_FINAL\_TRY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY:KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_FINAL_TRY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_FINAL\_TRY}}} +\end{fulllineitems} + + +\sphinxAtStartPar +This flag indicates that supplying an incorrect PIN will cause the token to lock itself. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_FINAL\_TRY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(1 \textless{}\textless{} 1)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_LOCKED} +\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED:krb5-responder-pkinit-flags-token-user-pin-locked}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED:krb5-responder-pkinit-flags-token-user-pin-locked-data}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED::doc}}\index{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_LOCKED (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_LOCKED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED:KRB5_RESPONDER_PKINIT_FLAGS_TOKEN_USER_PIN_LOCKED}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_LOCKED}}} +\end{fulllineitems} + + +\sphinxAtStartPar +This flag indicates that the user PIN is locked, and you can’t log in to the token with it. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_USER\_PIN\_LOCKED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(1 \textless{}\textless{} 2)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RESPONDER\_QUESTION\_PKINIT} +\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT:krb5-responder-question-pkinit}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT:krb5-responder-question-pkinit-data}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT::doc}}\index{KRB5\_RESPONDER\_QUESTION\_PKINIT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RESPONDER\_QUESTION\_PKINIT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_QUESTION_PKINIT:KRB5_RESPONDER_QUESTION_PKINIT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RESPONDER\_QUESTION\_PKINIT}}} +\end{fulllineitems} + + +\sphinxAtStartPar +PKINIT responder question. + +\sphinxAtStartPar +The PKINIT responder question is asked when the client needs a password that’s being used to protect key information, and is formatted as a JSON object. A specific identity’s flags value, if not zero, is the bitwise\sphinxhyphen{}OR of one or more of the KRB5\_RESPONDER\_PKINIT\_FLAGS\_TOKEN\_* flags defined below, and possibly other flags to be added later. Any resemblance to similarly\sphinxhyphen{}named CKF\_* values in the PKCS\#11 API should not be depended on. + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{\PYGZob{}} +\PYG{+w}{ }\PYG{n}{identity}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{string}\PYG{o}{\PYGZgt{}}\PYG{+w}{ }\PYG{o}{:}\PYG{+w}{ }\PYG{n}{flags}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{number}\PYG{o}{\PYGZgt{}}\PYG{p}{,} +\PYG{+w}{ }\PYG{p}{.}\PYG{p}{.}\PYG{p}{.} +\PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The answer to the question MUST be JSON formatted: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{\PYGZob{}} +\PYG{+w}{ }\PYG{n}{identity}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{string}\PYG{o}{\PYGZgt{}}\PYG{+w}{ }\PYG{o}{:}\PYG{+w}{ }\PYG{n}{password}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{string}\PYG{o}{\PYGZgt{}}\PYG{p}{,} +\PYG{+w}{ }\PYG{p}{.}\PYG{p}{.}\PYG{p}{.} +\PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_QUESTION\_PKINIT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{"pkinit"}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RESPONDER\_OTP\_FLAGS\_COLLECT\_PIN} +\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN:krb5-responder-otp-flags-collect-pin}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN:krb5-responder-otp-flags-collect-pin-data}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN::doc}}\index{KRB5\_RESPONDER\_OTP\_FLAGS\_COLLECT\_PIN (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RESPONDER\_OTP\_FLAGS\_COLLECT\_PIN}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN:KRB5_RESPONDER_OTP_FLAGS_COLLECT_PIN}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FLAGS\_COLLECT\_PIN}}} +\end{fulllineitems} + + +\sphinxAtStartPar +This flag indicates that the PIN value MUST be collected. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FLAGS\_COLLECT\_PIN}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0002}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RESPONDER\_OTP\_FLAGS\_COLLECT\_TOKEN} +\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN:krb5-responder-otp-flags-collect-token}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN:krb5-responder-otp-flags-collect-token-data}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN::doc}}\index{KRB5\_RESPONDER\_OTP\_FLAGS\_COLLECT\_TOKEN (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RESPONDER\_OTP\_FLAGS\_COLLECT\_TOKEN}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN:KRB5_RESPONDER_OTP_FLAGS_COLLECT_TOKEN}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FLAGS\_COLLECT\_TOKEN}}} +\end{fulllineitems} + + +\sphinxAtStartPar +This flag indicates that the token value MUST be collected. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FLAGS\_COLLECT\_TOKEN}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0001}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RESPONDER\_OTP\_FLAGS\_NEXTOTP} +\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP:krb5-responder-otp-flags-nextotp}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP:krb5-responder-otp-flags-nextotp-data}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP::doc}}\index{KRB5\_RESPONDER\_OTP\_FLAGS\_NEXTOTP (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RESPONDER\_OTP\_FLAGS\_NEXTOTP}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_NEXTOTP:KRB5_RESPONDER_OTP_FLAGS_NEXTOTP}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FLAGS\_NEXTOTP}}} +\end{fulllineitems} + + +\sphinxAtStartPar +This flag indicates that the token is now in re\sphinxhyphen{}synchronization mode with the server. + +\sphinxAtStartPar +The user is expected to reply with the next code displayed on the token. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FLAGS\_NEXTOTP}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0004}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RESPONDER\_OTP\_FLAGS\_SEPARATE\_PIN} +\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN:krb5-responder-otp-flags-separate-pin}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN:krb5-responder-otp-flags-separate-pin-data}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN::doc}}\index{KRB5\_RESPONDER\_OTP\_FLAGS\_SEPARATE\_PIN (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RESPONDER\_OTP\_FLAGS\_SEPARATE\_PIN}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN:KRB5_RESPONDER_OTP_FLAGS_SEPARATE_PIN}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FLAGS\_SEPARATE\_PIN}}} +\end{fulllineitems} + + +\sphinxAtStartPar +This flag indicates that the PIN MUST be returned as a separate item. + +\sphinxAtStartPar +This flag only takes effect if KRB5\_RESPONDER\_OTP\_FLAGS\_COLLECT\_PIN is set. If this flag is not set, the responder may either concatenate PIN + token value and store it as “value” in the answer or it may return them separately. If they are returned separately, they will be concatenated internally. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FLAGS\_SEPARATE\_PIN}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0008}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RESPONDER\_OTP\_FORMAT\_ALPHANUMERIC} +\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC:krb5-responder-otp-format-alphanumeric}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC:krb5-responder-otp-format-alphanumeric-data}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC::doc}}\index{KRB5\_RESPONDER\_OTP\_FORMAT\_ALPHANUMERIC (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RESPONDER\_OTP\_FORMAT\_ALPHANUMERIC}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC:KRB5_RESPONDER_OTP_FORMAT_ALPHANUMERIC}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FORMAT\_ALPHANUMERIC}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FORMAT\_ALPHANUMERIC}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{2}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RESPONDER\_OTP\_FORMAT\_DECIMAL} +\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL:krb5-responder-otp-format-decimal}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL:krb5-responder-otp-format-decimal-data}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL::doc}}\index{KRB5\_RESPONDER\_OTP\_FORMAT\_DECIMAL (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RESPONDER\_OTP\_FORMAT\_DECIMAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_DECIMAL:KRB5_RESPONDER_OTP_FORMAT_DECIMAL}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FORMAT\_DECIMAL}}} +\end{fulllineitems} + + +\sphinxAtStartPar +These format constants identify the format of the token value. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FORMAT\_DECIMAL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RESPONDER\_OTP\_FORMAT\_HEXADECIMAL} +\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL:krb5-responder-otp-format-hexadecimal}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL:krb5-responder-otp-format-hexadecimal-data}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL::doc}}\index{KRB5\_RESPONDER\_OTP\_FORMAT\_HEXADECIMAL (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RESPONDER\_OTP\_FORMAT\_HEXADECIMAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL:KRB5_RESPONDER_OTP_FORMAT_HEXADECIMAL}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FORMAT\_HEXADECIMAL}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_OTP\_FORMAT\_HEXADECIMAL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RESPONDER\_QUESTION\_OTP} +\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP:krb5-responder-question-otp}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP:krb5-responder-question-otp-data}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP::doc}}\index{KRB5\_RESPONDER\_QUESTION\_OTP (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RESPONDER\_QUESTION\_OTP}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_QUESTION_OTP:KRB5_RESPONDER_QUESTION_OTP}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RESPONDER\_QUESTION\_OTP}}} +\end{fulllineitems} + + +\sphinxAtStartPar +OTP responder question. + +\sphinxAtStartPar +The OTP responder question is asked when the KDC indicates that an OTP value is required in order to complete the authentication. The JSON format of the challenge is: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{\PYGZob{}} +\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}}\PYG{l+s}{service}\PYG{l+s}{\PYGZdq{}}\PYG{o}{:}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{string}\PYG{+w}{ }\PYG{p}{(}\PYG{n}{optional}\PYG{p}{)}\PYG{o}{\PYGZgt{}}\PYG{p}{,} +\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}}\PYG{l+s}{tokenInfo}\PYG{l+s}{\PYGZdq{}}\PYG{o}{:}\PYG{+w}{ }\PYG{p}{[} +\PYG{+w}{ }\PYG{p}{\PYGZob{}} +\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}}\PYG{l+s}{flags}\PYG{l+s}{\PYGZdq{}}\PYG{o}{:}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{number}\PYG{o}{\PYGZgt{}}\PYG{p}{,} +\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}}\PYG{l+s}{vendor}\PYG{l+s}{\PYGZdq{}}\PYG{o}{:}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{string}\PYG{+w}{ }\PYG{p}{(}\PYG{n}{optional}\PYG{p}{)}\PYG{o}{\PYGZgt{}}\PYG{p}{,} +\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}}\PYG{l+s}{challenge}\PYG{l+s}{\PYGZdq{}}\PYG{o}{:}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{string}\PYG{+w}{ }\PYG{p}{(}\PYG{n}{optional}\PYG{p}{)}\PYG{o}{\PYGZgt{}}\PYG{p}{,} +\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}}\PYG{l+s}{length}\PYG{l+s}{\PYGZdq{}}\PYG{o}{:}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{number}\PYG{+w}{ }\PYG{p}{(}\PYG{n}{optional}\PYG{p}{)}\PYG{o}{\PYGZgt{}}\PYG{p}{,} +\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}}\PYG{l+s}{format}\PYG{l+s}{\PYGZdq{}}\PYG{o}{:}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{number}\PYG{+w}{ }\PYG{p}{(}\PYG{n}{optional}\PYG{p}{)}\PYG{o}{\PYGZgt{}}\PYG{p}{,} +\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}}\PYG{l+s}{tokenID}\PYG{l+s}{\PYGZdq{}}\PYG{o}{:}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{string}\PYG{+w}{ }\PYG{p}{(}\PYG{n}{optional}\PYG{p}{)}\PYG{o}{\PYGZgt{}}\PYG{p}{,} +\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}}\PYG{l+s}{algID}\PYG{l+s}{\PYGZdq{}}\PYG{o}{:}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{string}\PYG{+w}{ }\PYG{p}{(}\PYG{n}{optional}\PYG{p}{)}\PYG{o}{\PYGZgt{}}\PYG{p}{,} +\PYG{+w}{ }\PYG{p}{\PYGZcb{}}\PYG{p}{,} +\PYG{+w}{ }\PYG{p}{.}\PYG{p}{.}\PYG{p}{.} +\PYG{+w}{ }\PYG{p}{]} +\PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +The answer to the question MUST be JSON formatted: + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +\PYG{p}{\PYGZob{}} +\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}}\PYG{l+s}{tokeninfo}\PYG{l+s}{\PYGZdq{}}\PYG{o}{:}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{number}\PYG{o}{\PYGZgt{}}\PYG{p}{,} +\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}}\PYG{l+s}{value}\PYG{l+s}{\PYGZdq{}}\PYG{o}{:}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{string}\PYG{+w}{ }\PYG{p}{(}\PYG{n}{optional}\PYG{p}{)}\PYG{o}{\PYGZgt{}}\PYG{p}{,} +\PYG{+w}{ }\PYG{l+s}{\PYGZdq{}}\PYG{l+s}{pin}\PYG{l+s}{\PYGZdq{}}\PYG{o}{:}\PYG{+w}{ }\PYG{o}{\PYGZlt{}}\PYG{n}{string}\PYG{+w}{ }\PYG{p}{(}\PYG{n}{optional}\PYG{p}{)}\PYG{o}{\PYGZgt{}}\PYG{p}{,} +\PYG{p}{\PYGZcb{}} +\end{sphinxVerbatim} + +\sphinxAtStartPar +For more detail, please see RFC 6560. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_QUESTION\_OTP}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{"otp"}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_RESPONDER\_QUESTION\_PASSWORD} +\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD:krb5-responder-question-password}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD:krb5-responder-question-password-data}}\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD::doc}}\index{KRB5\_RESPONDER\_QUESTION\_PASSWORD (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_RESPONDER\_QUESTION\_PASSWORD}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_RESPONDER_QUESTION_PASSWORD:KRB5_RESPONDER_QUESTION_PASSWORD}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_RESPONDER\_QUESTION\_PASSWORD}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Long\sphinxhyphen{}term password responder question. + +\sphinxAtStartPar +This question is asked when the long\sphinxhyphen{}term password is needed. It has no challenge and the response is simply the password string. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_RESPONDER\_QUESTION\_PASSWORD}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{"password"}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_SAFE} +\label{\detokenize{appdev/refs/macros/KRB5_SAFE:krb5-safe}}\label{\detokenize{appdev/refs/macros/KRB5_SAFE:krb5-safe-data}}\label{\detokenize{appdev/refs/macros/KRB5_SAFE::doc}}\index{KRB5\_SAFE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_SAFE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_SAFE:KRB5_SAFE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_SAFE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Safe application message. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_SAFE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((krb5\_msgtype)20)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_SAM\_MUST\_PK\_ENCRYPT\_SAD} +\label{\detokenize{appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD:krb5-sam-must-pk-encrypt-sad}}\label{\detokenize{appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD:krb5-sam-must-pk-encrypt-sad-data}}\label{\detokenize{appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD::doc}}\index{KRB5\_SAM\_MUST\_PK\_ENCRYPT\_SAD (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_SAM\_MUST\_PK\_ENCRYPT\_SAD}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_SAM_MUST_PK_ENCRYPT_SAD:KRB5_SAM_MUST_PK_ENCRYPT_SAD}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_SAM\_MUST\_PK\_ENCRYPT\_SAD}}} +\end{fulllineitems} + + +\sphinxAtStartPar +currently must be zero + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_SAM\_MUST\_PK\_ENCRYPT\_SAD}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x20000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_SAM\_SEND\_ENCRYPTED\_SAD} +\label{\detokenize{appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD:krb5-sam-send-encrypted-sad}}\label{\detokenize{appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD:krb5-sam-send-encrypted-sad-data}}\label{\detokenize{appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD::doc}}\index{KRB5\_SAM\_SEND\_ENCRYPTED\_SAD (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_SAM\_SEND\_ENCRYPTED\_SAD}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_SAM_SEND_ENCRYPTED_SAD:KRB5_SAM_SEND_ENCRYPTED_SAD}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_SAM\_SEND\_ENCRYPTED\_SAD}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_SAM\_SEND\_ENCRYPTED\_SAD}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x40000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_SAM\_USE\_SAD\_AS\_KEY} +\label{\detokenize{appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY:krb5-sam-use-sad-as-key}}\label{\detokenize{appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY:krb5-sam-use-sad-as-key-data}}\label{\detokenize{appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY::doc}}\index{KRB5\_SAM\_USE\_SAD\_AS\_KEY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_SAM\_USE\_SAD\_AS\_KEY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_SAM_USE_SAD_AS_KEY:KRB5_SAM_USE_SAD_AS_KEY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_SAM\_USE\_SAD\_AS\_KEY}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_SAM\_USE\_SAD\_AS\_KEY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x80000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TC\_MATCH\_2ND\_TKT} +\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT:krb5-tc-match-2nd-tkt}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT:krb5-tc-match-2nd-tkt-data}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT::doc}}\index{KRB5\_TC\_MATCH\_2ND\_TKT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TC\_MATCH\_2ND\_TKT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_2ND_TKT:KRB5_TC_MATCH_2ND_TKT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TC\_MATCH\_2ND\_TKT}}} +\end{fulllineitems} + + +\sphinxAtStartPar +The second ticket must match. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TC\_MATCH\_2ND\_TKT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000080}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TC\_MATCH\_AUTHDATA} +\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA:krb5-tc-match-authdata}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA:krb5-tc-match-authdata-data}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA::doc}}\index{KRB5\_TC\_MATCH\_AUTHDATA (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TC\_MATCH\_AUTHDATA}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_AUTHDATA:KRB5_TC_MATCH_AUTHDATA}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TC\_MATCH\_AUTHDATA}}} +\end{fulllineitems} + + +\sphinxAtStartPar +The authorization data must match. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TC\_MATCH\_AUTHDATA}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000020}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TC\_MATCH\_FLAGS} +\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_FLAGS:krb5-tc-match-flags}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_FLAGS:krb5-tc-match-flags-data}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_FLAGS::doc}}\index{KRB5\_TC\_MATCH\_FLAGS (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TC\_MATCH\_FLAGS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_FLAGS:KRB5_TC_MATCH_FLAGS}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TC\_MATCH\_FLAGS}}} +\end{fulllineitems} + + +\sphinxAtStartPar +All the flags set in the match credentials must be set. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TC\_MATCH\_FLAGS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000004}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TC\_MATCH\_FLAGS\_EXACT} +\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT:krb5-tc-match-flags-exact}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT:krb5-tc-match-flags-exact-data}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT::doc}}\index{KRB5\_TC\_MATCH\_FLAGS\_EXACT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TC\_MATCH\_FLAGS\_EXACT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_FLAGS_EXACT:KRB5_TC_MATCH_FLAGS_EXACT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TC\_MATCH\_FLAGS\_EXACT}}} +\end{fulllineitems} + + +\sphinxAtStartPar +All the flags must match exactly. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TC\_MATCH\_FLAGS\_EXACT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000010}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TC\_MATCH\_IS\_SKEY} +\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY:krb5-tc-match-is-skey}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY:krb5-tc-match-is-skey-data}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY::doc}}\index{KRB5\_TC\_MATCH\_IS\_SKEY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TC\_MATCH\_IS\_SKEY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_IS_SKEY:KRB5_TC_MATCH_IS_SKEY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TC\_MATCH\_IS\_SKEY}}} +\end{fulllineitems} + + +\sphinxAtStartPar +The is\_skey field must match exactly. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TC\_MATCH\_IS\_SKEY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000002}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TC\_MATCH\_KTYPE} +\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_KTYPE:krb5-tc-match-ktype}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_KTYPE:krb5-tc-match-ktype-data}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_KTYPE::doc}}\index{KRB5\_TC\_MATCH\_KTYPE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TC\_MATCH\_KTYPE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_KTYPE:KRB5_TC_MATCH_KTYPE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TC\_MATCH\_KTYPE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +The encryption key type must match. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TC\_MATCH\_KTYPE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000100}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TC\_MATCH\_SRV\_NAMEONLY} +\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY:krb5-tc-match-srv-nameonly}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY:krb5-tc-match-srv-nameonly-data}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY::doc}}\index{KRB5\_TC\_MATCH\_SRV\_NAMEONLY (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TC\_MATCH\_SRV\_NAMEONLY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_SRV_NAMEONLY:KRB5_TC_MATCH_SRV_NAMEONLY}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TC\_MATCH\_SRV\_NAMEONLY}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Only the name portion of the principal name must match. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TC\_MATCH\_SRV\_NAMEONLY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000040}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TC\_MATCH\_TIMES} +\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_TIMES:krb5-tc-match-times}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_TIMES:krb5-tc-match-times-data}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_TIMES::doc}}\index{KRB5\_TC\_MATCH\_TIMES (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TC\_MATCH\_TIMES}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_TIMES:KRB5_TC_MATCH_TIMES}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TC\_MATCH\_TIMES}}} +\end{fulllineitems} + + +\sphinxAtStartPar +The requested lifetime must be at least as great as the time specified. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TC\_MATCH\_TIMES}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000001}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TC\_MATCH\_TIMES\_EXACT} +\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT:krb5-tc-match-times-exact}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT:krb5-tc-match-times-exact-data}}\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT::doc}}\index{KRB5\_TC\_MATCH\_TIMES\_EXACT (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TC\_MATCH\_TIMES\_EXACT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TC_MATCH_TIMES_EXACT:KRB5_TC_MATCH_TIMES_EXACT}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TC\_MATCH\_TIMES\_EXACT}}} +\end{fulllineitems} + + +\sphinxAtStartPar +All the time fields must match exactly. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TC\_MATCH\_TIMES\_EXACT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000008}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TC\_NOTICKET} +\label{\detokenize{appdev/refs/macros/KRB5_TC_NOTICKET:krb5-tc-noticket}}\label{\detokenize{appdev/refs/macros/KRB5_TC_NOTICKET:krb5-tc-noticket-data}}\label{\detokenize{appdev/refs/macros/KRB5_TC_NOTICKET::doc}}\index{KRB5\_TC\_NOTICKET (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TC\_NOTICKET}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TC_NOTICKET:KRB5_TC_NOTICKET}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TC\_NOTICKET}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TC\_NOTICKET}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000002}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TC\_OPENCLOSE} +\label{\detokenize{appdev/refs/macros/KRB5_TC_OPENCLOSE:krb5-tc-openclose}}\label{\detokenize{appdev/refs/macros/KRB5_TC_OPENCLOSE:krb5-tc-openclose-data}}\label{\detokenize{appdev/refs/macros/KRB5_TC_OPENCLOSE::doc}}\index{KRB5\_TC\_OPENCLOSE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TC\_OPENCLOSE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TC_OPENCLOSE:KRB5_TC_OPENCLOSE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TC\_OPENCLOSE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Open and close the file for each cache operation. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TC\_OPENCLOSE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000001}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TC\_SUPPORTED\_KTYPES} +\label{\detokenize{appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES:krb5-tc-supported-ktypes}}\label{\detokenize{appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES:krb5-tc-supported-ktypes-data}}\label{\detokenize{appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES::doc}}\index{KRB5\_TC\_SUPPORTED\_KTYPES (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TC\_SUPPORTED\_KTYPES}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TC_SUPPORTED_KTYPES:KRB5_TC_SUPPORTED_KTYPES}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TC\_SUPPORTED\_KTYPES}}} +\end{fulllineitems} + + +\sphinxAtStartPar +The supported key types must match. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TC\_SUPPORTED\_KTYPES}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00000200}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TGS\_NAME} +\label{\detokenize{appdev/refs/macros/KRB5_TGS_NAME:krb5-tgs-name}}\label{\detokenize{appdev/refs/macros/KRB5_TGS_NAME:krb5-tgs-name-data}}\label{\detokenize{appdev/refs/macros/KRB5_TGS_NAME::doc}}\index{KRB5\_TGS\_NAME (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TGS\_NAME}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TGS_NAME:KRB5_TGS_NAME}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TGS\_NAME}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TGS\_NAME}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{"krbtgt"}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TGS\_NAME\_SIZE} +\label{\detokenize{appdev/refs/macros/KRB5_TGS_NAME_SIZE:krb5-tgs-name-size}}\label{\detokenize{appdev/refs/macros/KRB5_TGS_NAME_SIZE:krb5-tgs-name-size-data}}\label{\detokenize{appdev/refs/macros/KRB5_TGS_NAME_SIZE::doc}}\index{KRB5\_TGS\_NAME\_SIZE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TGS\_NAME\_SIZE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TGS_NAME_SIZE:KRB5_TGS_NAME_SIZE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TGS\_NAME\_SIZE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TGS\_NAME\_SIZE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{6}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TGS\_REP} +\label{\detokenize{appdev/refs/macros/KRB5_TGS_REP:krb5-tgs-rep}}\label{\detokenize{appdev/refs/macros/KRB5_TGS_REP:krb5-tgs-rep-data}}\label{\detokenize{appdev/refs/macros/KRB5_TGS_REP::doc}}\index{KRB5\_TGS\_REP (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TGS\_REP}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TGS_REP:KRB5_TGS_REP}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TGS\_REP}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Response to TGS request. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TGS\_REP}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((krb5\_msgtype)13)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TGS\_REQ} +\label{\detokenize{appdev/refs/macros/KRB5_TGS_REQ:krb5-tgs-req}}\label{\detokenize{appdev/refs/macros/KRB5_TGS_REQ:krb5-tgs-req-data}}\label{\detokenize{appdev/refs/macros/KRB5_TGS_REQ::doc}}\index{KRB5\_TGS\_REQ (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TGS\_REQ}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TGS_REQ:KRB5_TGS_REQ}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TGS\_REQ}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Ticket granting server request. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TGS\_REQ}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((krb5\_msgtype)12)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_TKT\_CREDS\_STEP\_FLAG\_CONTINUE} +\label{\detokenize{appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE:krb5-tkt-creds-step-flag-continue}}\label{\detokenize{appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE:krb5-tkt-creds-step-flag-continue-data}}\label{\detokenize{appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE::doc}}\index{KRB5\_TKT\_CREDS\_STEP\_FLAG\_CONTINUE (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_TKT\_CREDS\_STEP\_FLAG\_CONTINUE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_TKT_CREDS_STEP_FLAG_CONTINUE:KRB5_TKT_CREDS_STEP_FLAG_CONTINUE}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_TKT\_CREDS\_STEP\_FLAG\_CONTINUE}}} +\end{fulllineitems} + + +\sphinxAtStartPar +More responses needed. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_TKT\_CREDS\_STEP\_FLAG\_CONTINUE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x1}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_VERIFY\_INIT\_CREDS\_OPT\_AP\_REQ\_NOFAIL} +\label{\detokenize{appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL:krb5-verify-init-creds-opt-ap-req-nofail}}\label{\detokenize{appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL:krb5-verify-init-creds-opt-ap-req-nofail-data}}\label{\detokenize{appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL::doc}}\index{KRB5\_VERIFY\_INIT\_CREDS\_OPT\_AP\_REQ\_NOFAIL (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_VERIFY\_INIT\_CREDS\_OPT\_AP\_REQ\_NOFAIL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL:KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_VERIFY\_INIT\_CREDS\_OPT\_AP\_REQ\_NOFAIL}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_VERIFY\_INIT\_CREDS\_OPT\_AP\_REQ\_NOFAIL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x0001}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{KRB5\_WELLKNOWN\_NAMESTR} +\label{\detokenize{appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR:krb5-wellknown-namestr}}\label{\detokenize{appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR:krb5-wellknown-namestr-data}}\label{\detokenize{appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR::doc}}\index{KRB5\_WELLKNOWN\_NAMESTR (built\sphinxhyphen{}in variable)@\spxentry{KRB5\_WELLKNOWN\_NAMESTR}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/KRB5_WELLKNOWN_NAMESTR:KRB5_WELLKNOWN_NAMESTR}}\pysigline{\sphinxbfcode{\sphinxupquote{KRB5\_WELLKNOWN\_NAMESTR}}} +\end{fulllineitems} + + +\sphinxAtStartPar +First component of NT\_WELLKNOWN principals. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{KRB5\_WELLKNOWN\_NAMESTR}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{"WELLKNOWN"}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{LR\_TYPE\_INTERPRETATION\_MASK} +\label{\detokenize{appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK:lr-type-interpretation-mask}}\label{\detokenize{appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK:lr-type-interpretation-mask-data}}\label{\detokenize{appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK::doc}}\index{LR\_TYPE\_INTERPRETATION\_MASK (built\sphinxhyphen{}in variable)@\spxentry{LR\_TYPE\_INTERPRETATION\_MASK}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/LR_TYPE_INTERPRETATION_MASK:LR_TYPE_INTERPRETATION_MASK}}\pysigline{\sphinxbfcode{\sphinxupquote{LR\_TYPE\_INTERPRETATION\_MASK}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{LR\_TYPE\_INTERPRETATION\_MASK}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x7fff}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{LR\_TYPE\_THIS\_SERVER\_ONLY} +\label{\detokenize{appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY:lr-type-this-server-only}}\label{\detokenize{appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY:lr-type-this-server-only-data}}\label{\detokenize{appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY::doc}}\index{LR\_TYPE\_THIS\_SERVER\_ONLY (built\sphinxhyphen{}in variable)@\spxentry{LR\_TYPE\_THIS\_SERVER\_ONLY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/LR_TYPE_THIS_SERVER_ONLY:LR_TYPE_THIS_SERVER_ONLY}}\pysigline{\sphinxbfcode{\sphinxupquote{LR\_TYPE\_THIS\_SERVER\_ONLY}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{LR\_TYPE\_THIS\_SERVER\_ONLY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x8000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{MAX\_KEYTAB\_NAME\_LEN} +\label{\detokenize{appdev/refs/macros/MAX_KEYTAB_NAME_LEN:max-keytab-name-len}}\label{\detokenize{appdev/refs/macros/MAX_KEYTAB_NAME_LEN:max-keytab-name-len-data}}\label{\detokenize{appdev/refs/macros/MAX_KEYTAB_NAME_LEN::doc}}\index{MAX\_KEYTAB\_NAME\_LEN (built\sphinxhyphen{}in variable)@\spxentry{MAX\_KEYTAB\_NAME\_LEN}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/MAX_KEYTAB_NAME_LEN:MAX_KEYTAB_NAME_LEN}}\pysigline{\sphinxbfcode{\sphinxupquote{MAX\_KEYTAB\_NAME\_LEN}}} +\end{fulllineitems} + + +\sphinxAtStartPar +Long enough for MAXPATHLEN + some extra. + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{MAX\_KEYTAB\_NAME\_LEN}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{1100}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{MSEC\_DIRBIT} +\label{\detokenize{appdev/refs/macros/MSEC_DIRBIT:msec-dirbit}}\label{\detokenize{appdev/refs/macros/MSEC_DIRBIT:msec-dirbit-data}}\label{\detokenize{appdev/refs/macros/MSEC_DIRBIT::doc}}\index{MSEC\_DIRBIT (built\sphinxhyphen{}in variable)@\spxentry{MSEC\_DIRBIT}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/MSEC_DIRBIT:MSEC_DIRBIT}}\pysigline{\sphinxbfcode{\sphinxupquote{MSEC\_DIRBIT}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{MSEC\_DIRBIT}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x8000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{MSEC\_VAL\_MASK} +\label{\detokenize{appdev/refs/macros/MSEC_VAL_MASK:msec-val-mask}}\label{\detokenize{appdev/refs/macros/MSEC_VAL_MASK:msec-val-mask-data}}\label{\detokenize{appdev/refs/macros/MSEC_VAL_MASK::doc}}\index{MSEC\_VAL\_MASK (built\sphinxhyphen{}in variable)@\spxentry{MSEC\_VAL\_MASK}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/MSEC_VAL_MASK:MSEC_VAL_MASK}}\pysigline{\sphinxbfcode{\sphinxupquote{MSEC\_VAL\_MASK}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{MSEC\_VAL\_MASK}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x7fff}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{SALT\_TYPE\_AFS\_LENGTH} +\label{\detokenize{appdev/refs/macros/SALT_TYPE_AFS_LENGTH:salt-type-afs-length}}\label{\detokenize{appdev/refs/macros/SALT_TYPE_AFS_LENGTH:salt-type-afs-length-data}}\label{\detokenize{appdev/refs/macros/SALT_TYPE_AFS_LENGTH::doc}}\index{SALT\_TYPE\_AFS\_LENGTH (built\sphinxhyphen{}in variable)@\spxentry{SALT\_TYPE\_AFS\_LENGTH}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/SALT_TYPE_AFS_LENGTH:SALT_TYPE_AFS_LENGTH}}\pysigline{\sphinxbfcode{\sphinxupquote{SALT\_TYPE\_AFS\_LENGTH}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{SALT\_TYPE\_AFS\_LENGTH}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{UINT\_MAX}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{SALT\_TYPE\_NO\_LENGTH} +\label{\detokenize{appdev/refs/macros/SALT_TYPE_NO_LENGTH:salt-type-no-length}}\label{\detokenize{appdev/refs/macros/SALT_TYPE_NO_LENGTH:salt-type-no-length-data}}\label{\detokenize{appdev/refs/macros/SALT_TYPE_NO_LENGTH::doc}}\index{SALT\_TYPE\_NO\_LENGTH (built\sphinxhyphen{}in variable)@\spxentry{SALT\_TYPE\_NO\_LENGTH}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/SALT_TYPE_NO_LENGTH:SALT_TYPE_NO_LENGTH}}\pysigline{\sphinxbfcode{\sphinxupquote{SALT\_TYPE\_NO\_LENGTH}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{SALT\_TYPE\_NO\_LENGTH}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{UINT\_MAX}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{THREEPARAMOPEN} +\label{\detokenize{appdev/refs/macros/THREEPARAMOPEN:threeparamopen}}\label{\detokenize{appdev/refs/macros/THREEPARAMOPEN:threeparamopen-data}}\label{\detokenize{appdev/refs/macros/THREEPARAMOPEN::doc}}\index{THREEPARAMOPEN (built\sphinxhyphen{}in variable)@\spxentry{THREEPARAMOPEN}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/THREEPARAMOPEN:THREEPARAMOPEN}}\pysigline{\sphinxbfcode{\sphinxupquote{THREEPARAMOPEN}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{THREEPARAMOPEN (x, y, z)}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{open(x,y,z)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_ANONYMOUS} +\label{\detokenize{appdev/refs/macros/TKT_FLG_ANONYMOUS:tkt-flg-anonymous}}\label{\detokenize{appdev/refs/macros/TKT_FLG_ANONYMOUS:tkt-flg-anonymous-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_ANONYMOUS::doc}}\index{TKT\_FLG\_ANONYMOUS (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_ANONYMOUS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_ANONYMOUS:TKT_FLG_ANONYMOUS}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_ANONYMOUS}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_ANONYMOUS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00008000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_ENC\_PA\_REP} +\label{\detokenize{appdev/refs/macros/TKT_FLG_ENC_PA_REP:tkt-flg-enc-pa-rep}}\label{\detokenize{appdev/refs/macros/TKT_FLG_ENC_PA_REP:tkt-flg-enc-pa-rep-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_ENC_PA_REP::doc}}\index{TKT\_FLG\_ENC\_PA\_REP (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_ENC\_PA\_REP}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_ENC_PA_REP:TKT_FLG_ENC_PA_REP}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_ENC\_PA\_REP}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_ENC\_PA\_REP}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00010000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_FORWARDABLE} +\label{\detokenize{appdev/refs/macros/TKT_FLG_FORWARDABLE:tkt-flg-forwardable}}\label{\detokenize{appdev/refs/macros/TKT_FLG_FORWARDABLE:tkt-flg-forwardable-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_FORWARDABLE::doc}}\index{TKT\_FLG\_FORWARDABLE (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_FORWARDABLE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_FORWARDABLE:TKT_FLG_FORWARDABLE}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_FORWARDABLE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_FORWARDABLE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x40000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_FORWARDED} +\label{\detokenize{appdev/refs/macros/TKT_FLG_FORWARDED:tkt-flg-forwarded}}\label{\detokenize{appdev/refs/macros/TKT_FLG_FORWARDED:tkt-flg-forwarded-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_FORWARDED::doc}}\index{TKT\_FLG\_FORWARDED (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_FORWARDED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_FORWARDED:TKT_FLG_FORWARDED}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_FORWARDED}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_FORWARDED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x20000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_HW\_AUTH} +\label{\detokenize{appdev/refs/macros/TKT_FLG_HW_AUTH:tkt-flg-hw-auth}}\label{\detokenize{appdev/refs/macros/TKT_FLG_HW_AUTH:tkt-flg-hw-auth-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_HW_AUTH::doc}}\index{TKT\_FLG\_HW\_AUTH (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_HW\_AUTH}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_HW_AUTH:TKT_FLG_HW_AUTH}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_HW\_AUTH}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_HW\_AUTH}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00100000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_INITIAL} +\label{\detokenize{appdev/refs/macros/TKT_FLG_INITIAL:tkt-flg-initial}}\label{\detokenize{appdev/refs/macros/TKT_FLG_INITIAL:tkt-flg-initial-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_INITIAL::doc}}\index{TKT\_FLG\_INITIAL (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_INITIAL}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_INITIAL:TKT_FLG_INITIAL}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_INITIAL}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_INITIAL}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00400000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_INVALID} +\label{\detokenize{appdev/refs/macros/TKT_FLG_INVALID:tkt-flg-invalid}}\label{\detokenize{appdev/refs/macros/TKT_FLG_INVALID:tkt-flg-invalid-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_INVALID::doc}}\index{TKT\_FLG\_INVALID (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_INVALID}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_INVALID:TKT_FLG_INVALID}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_INVALID}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_INVALID}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x01000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_MAY\_POSTDATE} +\label{\detokenize{appdev/refs/macros/TKT_FLG_MAY_POSTDATE:tkt-flg-may-postdate}}\label{\detokenize{appdev/refs/macros/TKT_FLG_MAY_POSTDATE:tkt-flg-may-postdate-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_MAY_POSTDATE::doc}}\index{TKT\_FLG\_MAY\_POSTDATE (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_MAY\_POSTDATE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_MAY_POSTDATE:TKT_FLG_MAY_POSTDATE}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_MAY\_POSTDATE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_MAY\_POSTDATE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x04000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_OK\_AS\_DELEGATE} +\label{\detokenize{appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE:tkt-flg-ok-as-delegate}}\label{\detokenize{appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE:tkt-flg-ok-as-delegate-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE::doc}}\index{TKT\_FLG\_OK\_AS\_DELEGATE (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_OK\_AS\_DELEGATE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_OK_AS_DELEGATE:TKT_FLG_OK_AS_DELEGATE}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_OK\_AS\_DELEGATE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_OK\_AS\_DELEGATE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00040000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_POSTDATED} +\label{\detokenize{appdev/refs/macros/TKT_FLG_POSTDATED:tkt-flg-postdated}}\label{\detokenize{appdev/refs/macros/TKT_FLG_POSTDATED:tkt-flg-postdated-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_POSTDATED::doc}}\index{TKT\_FLG\_POSTDATED (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_POSTDATED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_POSTDATED:TKT_FLG_POSTDATED}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_POSTDATED}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_POSTDATED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x02000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_PRE\_AUTH} +\label{\detokenize{appdev/refs/macros/TKT_FLG_PRE_AUTH:tkt-flg-pre-auth}}\label{\detokenize{appdev/refs/macros/TKT_FLG_PRE_AUTH:tkt-flg-pre-auth-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_PRE_AUTH::doc}}\index{TKT\_FLG\_PRE\_AUTH (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_PRE\_AUTH}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_PRE_AUTH:TKT_FLG_PRE_AUTH}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_PRE\_AUTH}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_PRE\_AUTH}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00200000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_PROXIABLE} +\label{\detokenize{appdev/refs/macros/TKT_FLG_PROXIABLE:tkt-flg-proxiable}}\label{\detokenize{appdev/refs/macros/TKT_FLG_PROXIABLE:tkt-flg-proxiable-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_PROXIABLE::doc}}\index{TKT\_FLG\_PROXIABLE (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_PROXIABLE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_PROXIABLE:TKT_FLG_PROXIABLE}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_PROXIABLE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_PROXIABLE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x10000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_PROXY} +\label{\detokenize{appdev/refs/macros/TKT_FLG_PROXY:tkt-flg-proxy}}\label{\detokenize{appdev/refs/macros/TKT_FLG_PROXY:tkt-flg-proxy-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_PROXY::doc}}\index{TKT\_FLG\_PROXY (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_PROXY}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_PROXY:TKT_FLG_PROXY}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_PROXY}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_PROXY}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x08000000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_RENEWABLE} +\label{\detokenize{appdev/refs/macros/TKT_FLG_RENEWABLE:tkt-flg-renewable}}\label{\detokenize{appdev/refs/macros/TKT_FLG_RENEWABLE:tkt-flg-renewable-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_RENEWABLE::doc}}\index{TKT\_FLG\_RENEWABLE (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_RENEWABLE}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_RENEWABLE:TKT_FLG_RENEWABLE}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_RENEWABLE}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_RENEWABLE}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00800000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{TKT\_FLG\_TRANSIT\_POLICY\_CHECKED} +\label{\detokenize{appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED:tkt-flg-transit-policy-checked}}\label{\detokenize{appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED:tkt-flg-transit-policy-checked-data}}\label{\detokenize{appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED::doc}}\index{TKT\_FLG\_TRANSIT\_POLICY\_CHECKED (built\sphinxhyphen{}in variable)@\spxentry{TKT\_FLG\_TRANSIT\_POLICY\_CHECKED}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/TKT_FLG_TRANSIT_POLICY_CHECKED:TKT_FLG_TRANSIT_POLICY_CHECKED}}\pysigline{\sphinxbfcode{\sphinxupquote{TKT\_FLG\_TRANSIT\_POLICY\_CHECKED}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{TKT\_FLG\_TRANSIT\_POLICY\_CHECKED}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{0x00080000}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{VALID\_INT\_BITS} +\label{\detokenize{appdev/refs/macros/VALID_INT_BITS:valid-int-bits}}\label{\detokenize{appdev/refs/macros/VALID_INT_BITS:valid-int-bits-data}}\label{\detokenize{appdev/refs/macros/VALID_INT_BITS::doc}}\index{VALID\_INT\_BITS (built\sphinxhyphen{}in variable)@\spxentry{VALID\_INT\_BITS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/VALID_INT_BITS:VALID_INT_BITS}}\pysigline{\sphinxbfcode{\sphinxupquote{VALID\_INT\_BITS}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{VALID\_INT\_BITS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{INT\_MAX}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{VALID\_UINT\_BITS} +\label{\detokenize{appdev/refs/macros/VALID_UINT_BITS:valid-uint-bits}}\label{\detokenize{appdev/refs/macros/VALID_UINT_BITS:valid-uint-bits-data}}\label{\detokenize{appdev/refs/macros/VALID_UINT_BITS::doc}}\index{VALID\_UINT\_BITS (built\sphinxhyphen{}in variable)@\spxentry{VALID\_UINT\_BITS}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/VALID_UINT_BITS:VALID_UINT_BITS}}\pysigline{\sphinxbfcode{\sphinxupquote{VALID\_UINT\_BITS}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{VALID\_UINT\_BITS}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{UINT\_MAX}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{krb5\_const} +\label{\detokenize{appdev/refs/macros/krb5_const:krb5-const}}\label{\detokenize{appdev/refs/macros/krb5_const:krb5-const-data}}\label{\detokenize{appdev/refs/macros/krb5_const::doc}}\index{krb5\_const (built\sphinxhyphen{}in variable)@\spxentry{krb5\_const}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb5_const:krb5_const}}\pysigline{\sphinxbfcode{\sphinxupquote{krb5\_const}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_const}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{const}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{krb5\_princ\_component} +\label{\detokenize{appdev/refs/macros/krb5_princ_component:krb5-princ-component}}\label{\detokenize{appdev/refs/macros/krb5_princ_component:krb5-princ-component-data}}\label{\detokenize{appdev/refs/macros/krb5_princ_component::doc}}\index{krb5\_princ\_component (built\sphinxhyphen{}in variable)@\spxentry{krb5\_princ\_component}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb5_princ_component:krb5_princ_component}}\pysigline{\sphinxbfcode{\sphinxupquote{krb5\_princ\_component}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_princ\_component (context, princ, i)}} +& +\sphinxAtStartPar +\textasciigrave{}\textasciigrave{} (((i) \textless{} krb5\_princ\_size(context, princ)) ? (princ)\sphinxhyphen{}\textgreater{}data + (i) : NULL)\textasciigrave{}\textasciigrave{} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{krb5\_princ\_name} +\label{\detokenize{appdev/refs/macros/krb5_princ_name:krb5-princ-name}}\label{\detokenize{appdev/refs/macros/krb5_princ_name:krb5-princ-name-data}}\label{\detokenize{appdev/refs/macros/krb5_princ_name::doc}}\index{krb5\_princ\_name (built\sphinxhyphen{}in variable)@\spxentry{krb5\_princ\_name}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb5_princ_name:krb5_princ_name}}\pysigline{\sphinxbfcode{\sphinxupquote{krb5\_princ\_name}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_princ\_name (context, princ)}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(princ)\sphinxhyphen{}\textgreater{}data}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{krb5\_princ\_realm} +\label{\detokenize{appdev/refs/macros/krb5_princ_realm:krb5-princ-realm}}\label{\detokenize{appdev/refs/macros/krb5_princ_realm:krb5-princ-realm-data}}\label{\detokenize{appdev/refs/macros/krb5_princ_realm::doc}}\index{krb5\_princ\_realm (built\sphinxhyphen{}in variable)@\spxentry{krb5\_princ\_realm}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb5_princ_realm:krb5_princ_realm}}\pysigline{\sphinxbfcode{\sphinxupquote{krb5\_princ\_realm}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_princ\_realm (context, princ)}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(\&(princ)\sphinxhyphen{}\textgreater{}realm)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{krb5\_princ\_set\_realm} +\label{\detokenize{appdev/refs/macros/krb5_princ_set_realm:krb5-princ-set-realm}}\label{\detokenize{appdev/refs/macros/krb5_princ_set_realm:krb5-princ-set-realm-data}}\label{\detokenize{appdev/refs/macros/krb5_princ_set_realm::doc}}\index{krb5\_princ\_set\_realm (built\sphinxhyphen{}in variable)@\spxentry{krb5\_princ\_set\_realm}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb5_princ_set_realm:krb5_princ_set_realm}}\pysigline{\sphinxbfcode{\sphinxupquote{krb5\_princ\_set\_realm}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_princ\_set\_realm (context, princ, value)}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((princ)\sphinxhyphen{}\textgreater{}realm = *(value))}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{krb5\_princ\_set\_realm\_data} +\label{\detokenize{appdev/refs/macros/krb5_princ_set_realm_data:krb5-princ-set-realm-data}}\label{\detokenize{appdev/refs/macros/krb5_princ_set_realm_data:krb5-princ-set-realm-data-data}}\label{\detokenize{appdev/refs/macros/krb5_princ_set_realm_data::doc}}\index{krb5\_princ\_set\_realm\_data (built\sphinxhyphen{}in variable)@\spxentry{krb5\_princ\_set\_realm\_data}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb5_princ_set_realm_data:krb5_princ_set_realm_data}}\pysigline{\sphinxbfcode{\sphinxupquote{krb5\_princ\_set\_realm\_data}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_princ\_set\_realm\_data (context, princ, value)}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(princ)\sphinxhyphen{}\textgreater{}realm.data = (value)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{krb5\_princ\_set\_realm\_length} +\label{\detokenize{appdev/refs/macros/krb5_princ_set_realm_length:krb5-princ-set-realm-length}}\label{\detokenize{appdev/refs/macros/krb5_princ_set_realm_length:krb5-princ-set-realm-length-data}}\label{\detokenize{appdev/refs/macros/krb5_princ_set_realm_length::doc}}\index{krb5\_princ\_set\_realm\_length (built\sphinxhyphen{}in variable)@\spxentry{krb5\_princ\_set\_realm\_length}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb5_princ_set_realm_length:krb5_princ_set_realm_length}}\pysigline{\sphinxbfcode{\sphinxupquote{krb5\_princ\_set\_realm\_length}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_princ\_set\_realm\_length (context, princ, value)}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(princ)\sphinxhyphen{}\textgreater{}realm.length = (value)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{krb5\_princ\_size} +\label{\detokenize{appdev/refs/macros/krb5_princ_size:krb5-princ-size}}\label{\detokenize{appdev/refs/macros/krb5_princ_size:krb5-princ-size-data}}\label{\detokenize{appdev/refs/macros/krb5_princ_size::doc}}\index{krb5\_princ\_size (built\sphinxhyphen{}in variable)@\spxentry{krb5\_princ\_size}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb5_princ_size:krb5_princ_size}}\pysigline{\sphinxbfcode{\sphinxupquote{krb5\_princ\_size}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_princ\_size (context, princ)}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(princ)\sphinxhyphen{}\textgreater{}length}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{krb5\_princ\_type} +\label{\detokenize{appdev/refs/macros/krb5_princ_type:krb5-princ-type}}\label{\detokenize{appdev/refs/macros/krb5_princ_type:krb5-princ-type-data}}\label{\detokenize{appdev/refs/macros/krb5_princ_type::doc}}\index{krb5\_princ\_type (built\sphinxhyphen{}in variable)@\spxentry{krb5\_princ\_type}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb5_princ_type:krb5_princ_type}}\pysigline{\sphinxbfcode{\sphinxupquote{krb5\_princ\_type}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_princ\_type (context, princ)}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(princ)\sphinxhyphen{}\textgreater{}type}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{krb5\_roundup} +\label{\detokenize{appdev/refs/macros/krb5_roundup:krb5-roundup}}\label{\detokenize{appdev/refs/macros/krb5_roundup:krb5-roundup-data}}\label{\detokenize{appdev/refs/macros/krb5_roundup::doc}}\index{krb5\_roundup (built\sphinxhyphen{}in variable)@\spxentry{krb5\_roundup}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb5_roundup:krb5_roundup}}\pysigline{\sphinxbfcode{\sphinxupquote{krb5\_roundup}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_roundup (x, y)}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((((x) + (y) \sphinxhyphen{} 1)/(y))*(y))}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{krb5\_x} +\label{\detokenize{appdev/refs/macros/krb5_x:krb5-x}}\label{\detokenize{appdev/refs/macros/krb5_x:krb5-x-data}}\label{\detokenize{appdev/refs/macros/krb5_x::doc}}\index{krb5\_x (built\sphinxhyphen{}in variable)@\spxentry{krb5\_x}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb5_x:krb5_x}}\pysigline{\sphinxbfcode{\sphinxupquote{krb5\_x}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_x (ptr, args)}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((ptr)?((*(ptr)) args):(abort(),1))}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{krb5\_xc} +\label{\detokenize{appdev/refs/macros/krb5_xc:krb5-xc}}\label{\detokenize{appdev/refs/macros/krb5_xc:krb5-xc-data}}\label{\detokenize{appdev/refs/macros/krb5_xc::doc}}\index{krb5\_xc (built\sphinxhyphen{}in variable)@\spxentry{krb5\_xc}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb5_xc:krb5_xc}}\pysigline{\sphinxbfcode{\sphinxupquote{krb5\_xc}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_xc (ptr, args)}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{((ptr)?((*(ptr)) args):(abort(),(char*)0))}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsection{Deprecated macros} +\label{\detokenize{appdev/refs/macros/index:deprecated-macros}} + +\subsubsection{krb524\_convert\_creds\_kdc} +\label{\detokenize{appdev/refs/macros/krb524_convert_creds_kdc:krb524-convert-creds-kdc}}\label{\detokenize{appdev/refs/macros/krb524_convert_creds_kdc:krb524-convert-creds-kdc-data}}\label{\detokenize{appdev/refs/macros/krb524_convert_creds_kdc::doc}}\index{krb524\_convert\_creds\_kdc (built\sphinxhyphen{}in variable)@\spxentry{krb524\_convert\_creds\_kdc}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb524_convert_creds_kdc:krb524_convert_creds_kdc}}\pysigline{\sphinxbfcode{\sphinxupquote{krb524\_convert\_creds\_kdc}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb524\_convert\_creds\_kdc}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb5\_524\_convert\_creds}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + +\subsubsection{krb524\_init\_ets} +\label{\detokenize{appdev/refs/macros/krb524_init_ets:krb524-init-ets}}\label{\detokenize{appdev/refs/macros/krb524_init_ets:krb524-init-ets-data}}\label{\detokenize{appdev/refs/macros/krb524_init_ets::doc}}\index{krb524\_init\_ets (built\sphinxhyphen{}in variable)@\spxentry{krb524\_init\_ets}\spxextra{built\sphinxhyphen{}in variable}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{appdev/refs/macros/krb524_init_ets:krb524_init_ets}}\pysigline{\sphinxbfcode{\sphinxupquote{krb524\_init\_ets}}} +\end{fulllineitems} + + + +\begin{savenotes}\sphinxattablestart +\centering +\begin{tabulary}{\linewidth}[t]{|T|T|} +\hline + +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{krb524\_init\_ets (x)}} +& +\sphinxAtStartPar +\sphinxcode{\sphinxupquote{(0)}} +\\ +\hline +\end{tabulary} +\par +\sphinxattableend\end{savenotes} + + + +\renewcommand{\indexname}{Index} +\printindex +\end{document} \ No newline at end of file diff --git a/krb5-1.21.3/doc/pdf/basic.pdf b/krb5-1.21.3/doc/pdf/basic.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9f9887df5c16c891f72505b03652fe8df785802e GIT binary patch literal 185464 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